* [PATCH 6.6 047/331] mtd: rawnand: Fix core interference with sequential reads
@ 2024-01-29 17:01 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2024-01-29 17:01 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alexander Shiyan,
Måns Rullgård, Martin Hundebøll, Miquel Raynal
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miquel Raynal <miquel.raynal@bootlin.com>
commit 7c9414c870c027737d0f2ed7b0ed10f26edb1c61 upstream.
A couple of reports pointed at some strange failures happening a bit
randomly since the introduction of sequential page reads support. After
investigation it turned out the most likely reason for these issues was
the fact that sometimes a (longer) read might happen, starting at the
same page that was read previously. This is optimized by the raw NAND
core, by not sending the READ_PAGE command to the NAND device and just
reading out the data in a local cache. When this page is also flagged as
being the starting point for a sequential read, it means the page right
next will be accessed without the right instructions. The NAND chip will
be confused and will not output correct data. In order to avoid such
situation from happening anymore, we can however handle this case with a
bit of additional logic, to postpone the initialization of the read
sequence by one page.
Reported-by: Alexander Shiyan <eagle.alexander923@gmail.com>
Closes: https://lore.kernel.org/linux-mtd/CAP1tNvS=NVAm-vfvYWbc3k9Cx9YxMc2uZZkmXk8h1NhGX877Zg@mail.gmail.com/
Reported-by: Måns Rullgård <mans@mansr.com>
Closes: https://lore.kernel.org/linux-mtd/yw1xfs6j4k6q.fsf@mansr.com/
Reported-by: Martin Hundebøll <martin@geanix.com>
Closes: https://lore.kernel.org/linux-mtd/9d0c42fcde79bfedfe5b05d6a4e9fdef71d3dd52.camel@geanix.com/
Fixes: 003fe4b9545b ("mtd: rawnand: Support for sequential cache reads")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Martin Hundebøll <martin@geanix.com>
Link: https://lore.kernel.org/linux-mtd/20231215123208.516590-3-miquel.raynal@bootlin.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mtd/nand/raw/nand_base.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3479,6 +3479,18 @@ static void rawnand_enable_cont_reads(st
rawnand_cap_cont_reads(chip);
}
+static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned int page)
+{
+ if (!chip->cont_read.ongoing || page != chip->cont_read.first_page)
+ return;
+
+ chip->cont_read.first_page++;
+ if (chip->cont_read.first_page == chip->cont_read.pause_page)
+ chip->cont_read.first_page++;
+ if (chip->cont_read.first_page >= chip->cont_read.last_page)
+ chip->cont_read.ongoing = false;
+}
+
/**
* nand_setup_read_retry - [INTERN] Set the READ RETRY mode
* @chip: NAND chip object
@@ -3653,6 +3665,8 @@ read_retry:
buf += bytes;
max_bitflips = max_t(unsigned int, max_bitflips,
chip->pagecache.bitflips);
+
+ rawnand_cont_read_skip_first_page(chip, page);
}
readlen -= bytes;
^ permalink raw reply [relevance 5%]
* [PATCH 6.7 024/346] mtd: rawnand: Fix core interference with sequential reads
@ 2024-01-29 17:00 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2024-01-29 17:00 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alexander Shiyan,
Måns Rullgård, Martin Hundebøll, Miquel Raynal
6.7-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miquel Raynal <miquel.raynal@bootlin.com>
commit 7c9414c870c027737d0f2ed7b0ed10f26edb1c61 upstream.
A couple of reports pointed at some strange failures happening a bit
randomly since the introduction of sequential page reads support. After
investigation it turned out the most likely reason for these issues was
the fact that sometimes a (longer) read might happen, starting at the
same page that was read previously. This is optimized by the raw NAND
core, by not sending the READ_PAGE command to the NAND device and just
reading out the data in a local cache. When this page is also flagged as
being the starting point for a sequential read, it means the page right
next will be accessed without the right instructions. The NAND chip will
be confused and will not output correct data. In order to avoid such
situation from happening anymore, we can however handle this case with a
bit of additional logic, to postpone the initialization of the read
sequence by one page.
Reported-by: Alexander Shiyan <eagle.alexander923@gmail.com>
Closes: https://lore.kernel.org/linux-mtd/CAP1tNvS=NVAm-vfvYWbc3k9Cx9YxMc2uZZkmXk8h1NhGX877Zg@mail.gmail.com/
Reported-by: Måns Rullgård <mans@mansr.com>
Closes: https://lore.kernel.org/linux-mtd/yw1xfs6j4k6q.fsf@mansr.com/
Reported-by: Martin Hundebøll <martin@geanix.com>
Closes: https://lore.kernel.org/linux-mtd/9d0c42fcde79bfedfe5b05d6a4e9fdef71d3dd52.camel@geanix.com/
Fixes: 003fe4b9545b ("mtd: rawnand: Support for sequential cache reads")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Martin Hundebøll <martin@geanix.com>
Link: https://lore.kernel.org/linux-mtd/20231215123208.516590-3-miquel.raynal@bootlin.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mtd/nand/raw/nand_base.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3478,6 +3478,18 @@ static void rawnand_enable_cont_reads(st
rawnand_cap_cont_reads(chip);
}
+static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned int page)
+{
+ if (!chip->cont_read.ongoing || page != chip->cont_read.first_page)
+ return;
+
+ chip->cont_read.first_page++;
+ if (chip->cont_read.first_page == chip->cont_read.pause_page)
+ chip->cont_read.first_page++;
+ if (chip->cont_read.first_page >= chip->cont_read.last_page)
+ chip->cont_read.ongoing = false;
+}
+
/**
* nand_setup_read_retry - [INTERN] Set the READ RETRY mode
* @chip: NAND chip object
@@ -3652,6 +3664,8 @@ read_retry:
buf += bytes;
max_bitflips = max_t(unsigned int, max_bitflips,
chip->pagecache.bitflips);
+
+ rawnand_cont_read_skip_first_page(chip, page);
}
readlen -= bytes;
^ permalink raw reply [relevance 5%]
* Re: [PATCH 2/4] mtd: rawnand: Fix core interference with sequential reads
2023-12-15 12:32 5% ` [PATCH 2/4] mtd: rawnand: Fix core interference with sequential reads Miquel Raynal
@ 2023-12-22 11:37 0% ` Miquel Raynal
0 siblings, 0 replies; 200+ results
From: Miquel Raynal @ 2023-12-22 11:37 UTC (permalink / raw)
To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
Tudor Ambarus, Pratyush Yadav, Michael Walle, linux-mtd
Cc: Thomas Petazzoni, Julien Su, Jaime Liao, Jaime Liao, Alvin Zhou,
eagle.alexander923, mans, martin, Sean Nyekjær, stable
On Fri, 2023-12-15 at 12:32:06 UTC, Miquel Raynal wrote:
> A couple of reports pointed at some strange failures happening a bit
> randomly since the introduction of sequential page reads support. After
> investigation it turned out the most likely reason for these issues was
> the fact that sometimes a (longer) read might happen, starting at the
> same page that was read previously. This is optimized by the raw NAND
> core, by not sending the READ_PAGE command to the NAND device and just
> reading out the data in a local cache. When this page is also flagged as
> being the starting point for a sequential read, it means the page right
> next will be accessed without the right instructions. The NAND chip will
> be confused and will not output correct data. In order to avoid such
> situation from happening anymore, we can however handle this case with a
> bit of additional logic, to postpone the initialization of the read
> sequence by one page.
>
> Reported-by: Alexander Shiyan <eagle.alexander923@gmail.com>
> Closes: https://lore.kernel.org/linux-mtd/CAP1tNvS=NVAm-vfvYWbc3k9Cx9YxMc2uZZkmXk8h1NhGX877Zg@mail.gmail.com/
> Reported-by: Måns Rullgård <mans@mansr.com>
> Closes: https://lore.kernel.org/linux-mtd/yw1xfs6j4k6q.fsf@mansr.com/
> Reported-by: Martin Hundebøll <martin@geanix.com>
> Closes: https://lore.kernel.org/linux-mtd/9d0c42fcde79bfedfe5b05d6a4e9fdef71d3dd52.camel@geanix.com/
> Fixes: 003fe4b9545b ("mtd: rawnand: Support for sequential cache reads")
> Cc: stable@vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next.
Miquel
^ permalink raw reply [relevance 0%]
* [PATCH 2/4] mtd: rawnand: Fix core interference with sequential reads
[not found] <20231215123208.516590-1-miquel.raynal@bootlin.com>
@ 2023-12-15 12:32 5% ` Miquel Raynal
2023-12-22 11:37 0% ` Miquel Raynal
0 siblings, 1 reply; 200+ results
From: Miquel Raynal @ 2023-12-15 12:32 UTC (permalink / raw)
To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus,
Pratyush Yadav, Michael Walle, linux-mtd
Cc: Thomas Petazzoni, Julien Su, Jaime Liao, Jaime Liao, Alvin Zhou,
eagle.alexander923, mans, martin, Sean Nyekjær,
Miquel Raynal, stable
A couple of reports pointed at some strange failures happening a bit
randomly since the introduction of sequential page reads support. After
investigation it turned out the most likely reason for these issues was
the fact that sometimes a (longer) read might happen, starting at the
same page that was read previously. This is optimized by the raw NAND
core, by not sending the READ_PAGE command to the NAND device and just
reading out the data in a local cache. When this page is also flagged as
being the starting point for a sequential read, it means the page right
next will be accessed without the right instructions. The NAND chip will
be confused and will not output correct data. In order to avoid such
situation from happening anymore, we can however handle this case with a
bit of additional logic, to postpone the initialization of the read
sequence by one page.
Reported-by: Alexander Shiyan <eagle.alexander923@gmail.com>
Closes: https://lore.kernel.org/linux-mtd/CAP1tNvS=NVAm-vfvYWbc3k9Cx9YxMc2uZZkmXk8h1NhGX877Zg@mail.gmail.com/
Reported-by: Måns Rullgård <mans@mansr.com>
Closes: https://lore.kernel.org/linux-mtd/yw1xfs6j4k6q.fsf@mansr.com/
Reported-by: Martin Hundebøll <martin@geanix.com>
Closes: https://lore.kernel.org/linux-mtd/9d0c42fcde79bfedfe5b05d6a4e9fdef71d3dd52.camel@geanix.com/
Fixes: 003fe4b9545b ("mtd: rawnand: Support for sequential cache reads")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
drivers/mtd/nand/raw/nand_base.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 04e80ace4182..1b0a984d181d 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3478,6 +3478,18 @@ static void rawnand_enable_cont_reads(struct nand_chip *chip, unsigned int page,
rawnand_cap_cont_reads(chip);
}
+static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned int page)
+{
+ if (!chip->cont_read.ongoing || page != chip->cont_read.first_page)
+ return;
+
+ chip->cont_read.first_page++;
+ if (chip->cont_read.first_page == chip->cont_read.pause_page)
+ chip->cont_read.first_page++;
+ if (chip->cont_read.first_page >= chip->cont_read.last_page)
+ chip->cont_read.ongoing = false;
+}
+
/**
* nand_setup_read_retry - [INTERN] Set the READ RETRY mode
* @chip: NAND chip object
@@ -3652,6 +3664,8 @@ static int nand_do_read_ops(struct nand_chip *chip, loff_t from,
buf += bytes;
max_bitflips = max_t(unsigned int, max_bitflips,
chip->pagecache.bitflips);
+
+ rawnand_cont_read_skip_first_page(chip, page);
}
readlen -= bytes;
--
2.34.1
^ permalink raw reply related [relevance 5%]
* Linux 4.19.299
@ 2023-11-20 10:04 3% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-11-20 10:04 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 4.19.299 kernel.
All users of the 4.19 kernel series must upgrade.
The updated 4.19.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-4.19.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Makefile | 2
arch/arm/boot/dts/qcom-mdm9615.dtsi | 14
arch/arm/lib/memset.S | 1
arch/sh/Kconfig.debug | 11
drivers/acpi/device_sysfs.c | 10
drivers/base/regmap/regmap-debugfs.c | 2
drivers/char/hw_random/geode-rng.c | 6
drivers/clk/clk-npcm7xx.c | 2
drivers/clk/clk-scmi.c | 1
drivers/clk/keystone/pll.c | 15
drivers/clk/mediatek/clk-mt2701.c | 8
drivers/clk/mediatek/clk-mt6797.c | 6
drivers/clk/qcom/clk-rcg2.c | 14
drivers/crypto/chelsio/chtls/chtls_cm.c | 2
drivers/dma/pxa_dma.c | 1
drivers/dma/ti/edma.c | 4
drivers/firmware/ti_sci.c | 46
drivers/gpu/drm/radeon/evergreen.c | 7
drivers/gpu/drm/rockchip/cdn-dp-core.c | 15
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3
drivers/hid/hid-cp2112.c | 23
drivers/hwmon/coretemp.c | 2
drivers/infiniband/hw/hfi1/efivar.c | 2
drivers/input/rmi4/rmi_bus.c | 2
drivers/leds/leds-pwm.c | 41
drivers/leds/trigger/ledtrig-cpu.c | 17
drivers/media/pci/bt8xx/bttv-driver.c | 1
drivers/media/platform/s3c-camif/camif-capture.c | 6
drivers/media/usb/dvb-usb-v2/af9035.c | 13
drivers/mfd/dln2.c | 1
drivers/misc/ti-st/st_core.c | 7
drivers/mmc/core/mmc.c | 2
drivers/net/can/Makefile | 7
drivers/net/can/dev.c | 1324 -------------
drivers/net/can/dev/Makefile | 7
drivers/net/can/dev/dev.c | 1326 ++++++++++++++
drivers/net/can/dev/rx-offload.c | 404 ++++
drivers/net/can/rx-offload.c | 404 ----
drivers/net/ethernet/broadcom/tg3.c | 3
drivers/net/ethernet/intel/i40e/i40e_main.c | 10
drivers/net/ethernet/realtek/r8169_main.c | 56
drivers/net/ipvlan/ipvlan_core.c | 8
drivers/net/ipvlan/ipvlan_main.c | 1
drivers/net/macsec.c | 70
drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c | 2
drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c | 2
drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c | 2
drivers/nvdimm/region_devs.c | 8
drivers/pcmcia/cs.c | 1
drivers/pcmcia/ds.c | 14
drivers/platform/x86/wmi.c | 50
drivers/pwm/pwm-brcmstb.c | 4
drivers/pwm/pwm-sti.c | 75
drivers/thermal/thermal_core.c | 6
drivers/tty/tty_jobctrl.c | 17
drivers/usb/dwc2/hcd.c | 2
drivers/usb/usbip/stub_dev.c | 9
drivers/video/fbdev/fsl-diu-fb.c | 2
drivers/video/fbdev/imsttfb.c | 33
fs/btrfs/ioctl.c | 10
fs/ext4/extents.c | 10
fs/f2fs/file.c | 1
include/linux/netdevice.h | 1
include/linux/preempt.h | 30
kernel/irq/matrix.c | 6
mm/readahead.c | 3
net/dccp/ipv4.c | 6
net/dccp/ipv6.c | 6
net/ipv4/tcp_metrics.c | 15
net/ipv6/ip6_output.c | 8
net/ipv6/syncookies.c | 7
net/llc/llc_input.c | 10
net/llc/llc_s_ac.c | 3
net/llc/llc_station.c | 3
net/netfilter/xt_recent.c | 2
net/smc/af_smc.c | 43
net/smc/smc.h | 5
net/smc/smc_cdc.c | 2
net/smc/smc_close.c | 26
net/smc/smc_close.h | 1
net/tipc/netlink.c | 4
sound/soc/intel/skylake/skl-sst-utils.c | 1
sound/soc/omap/ams-delta.c | 4
tools/iio/iio_generic_buffer.c | 59
84 files changed, 2271 insertions(+), 2129 deletions(-)
Alexandru Ardelean (1):
tools: iio: privatize globals and functions in iio_generic_buffer.c file
Andrii Staikov (1):
i40e: fix potential memory leaks in i40e_remove()
Armin Wolf (2):
platform/x86: wmi: Fix probe failure when failing to register WMI devices
platform/x86: wmi: Fix opening of char device
Arnd Bergmann (1):
fbdev: fsl-diu-fb: mark wr_reg_wa() static
Barnabás Pőcze (1):
platform/x86: wmi: remove unnecessary initializations
Cezary Rojewski (1):
ASoC: Intel: Skylake: Fix mem leak when parsing UUIDs fails
Chao Yu (1):
f2fs: fix to initialize map.m_pblk in f2fs_precache_extents()
Chen Yu (1):
genirq/matrix: Exclude managed interrupts in irq_matrix_allocated()
Chenyuan Mi (1):
tools: iio: iio_generic_buffer: Fix some integer type and calculation
Christophe JAILLET (5):
ACPI: sysfs: Fix create_pnp_modalias() and create_of_modalias()
regmap: debugfs: Fix a erroneous check after snprintf()
drm/rockchip: cdn-dp: Fix some error handling paths in cdn_dp_probe()
leds: trigger: ledtrig-cpu:: Fix 'output may be truncated' issue for 'cpu'
dmaengine: pxa_dma: Remove an erroneous BUG_ON() in pxad_free_desc()
Clayton Yager (1):
macsec: Fix traffic counters/statistics
D. Wythe (1):
net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT
Dan Carpenter (5):
thermal: core: prevent potential string overflow
clk: keystone: pll: fix a couple NULL vs IS_ERR() checks
dmaengine: ti: edma: handle irq_of_parse_and_map() errors
Input: synaptics-rmi4 - fix use after free in rmi_unregister_function()
fbdev: imsttfb: fix a resource leak in probe
Danny Kaehn (1):
hid: cp2112: Fix duplicate workqueue initialization
Devi Priya (1):
clk: qcom: clk-rcg2: Fix clock rate overflow for high parent frequencies
Dhruva Gole (1):
firmware: ti_sci: Mark driver as non removable
Dinghao Liu (1):
mfd: dln2: Fix double put in dln2_probe
Dmitry Antipov (1):
wifi: rtlwifi: fix EDCA limit set by BT coexistence
Dominique Martinet (1):
Revert "mmc: core: Capture correct oemid-bits for eMMC cards"
Eric Dumazet (7):
tcp_metrics: add missing barriers on delete
tcp_metrics: properly set tp->snd_ssthresh in tcp_init_metrics()
tcp_metrics: do not create an entry from tcp_init_metrics()
chtls: fix tp->rcv_tstamp initialization
macsec: use DEV_STATS_INC()
net: add DEV_STATS_READ() helper
ipvlan: properly track tx_errors
Filipe Manana (1):
btrfs: use u64 for buffer sizes in the tree search ioctls
Florian Fainelli (1):
pwm: brcmstb: Utilize appropriate clock APIs in suspend/resume
Geert Uytterhoeven (1):
sh: bios: Revive earlyprintk support
George Shuklin (1):
tg3: power down device only on SYSTEM_POWER_OFF
Gou Hao (1):
ext4: move 'ix' sanity check to corrent position
Greg Kroah-Hartman (1):
Linux 4.19.299
Hans Verkuil (1):
media: dvb-usb-v2: af9035: fix missing unlock
Heiner Kallweit (2):
r8169: improve rtl_set_rx_mode
r8169: respect userspace disabling IFF_MULTICAST
Helge Deller (1):
fbdev: imsttfb: Fix error path of imsttfb_probe()
Jia-Ju Bai (1):
usb: dwc2: fix possible NULL pointer dereference caused by driver concurrency
Jiasheng Jiang (2):
clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data
clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data
Jinjie Ruan (1):
misc: st_core: Do not call kfree_skb() under spin_lock_irqsave()
Jonas Blixt (1):
USB: usbip: fix stub_dev hub disconnect
Jonas Gorski (1):
hwrng: geode - fix accessing registers
Jonas Karlman (1):
drm/rockchip: vop: Fix reset of state in duplicate state crtc funcs
Jonathan Neuschäfer (1):
clk: npcm7xx: Fix incorrect kfree
Karsten Graul (1):
net/smc: wait for pending work before clcsock release_sock
Katya Orlova (1):
media: s3c-camif: Avoid inappropriate kfree()
Konstantin Meskhidze (1):
drm/radeon: possible buffer overflow
Krzysztof Kozlowski (1):
ARM: dts: qcom: mdm9615: populate vsdcc fixed regulator
Kuninori Morimoto (1):
ASoC: ams-delta.c: use component after check
Kuniyuki Iwashima (2):
dccp: Call security_inet_conn_request() after setting IPv4 addresses.
dccp/tcp: Call security_inet_conn_request() after setting IPv6 addresses.
Kursad Oney (1):
ARM: 9321/1: memset: cast the constant byte to unsigned char
Leon Romanovsky (1):
RDMA/hfi1: Workaround truncation compilation error
Linus Walleij (1):
HID: cp2112: Use irqchip template
Maciej Żenczykowski (1):
netfilter: xt_recent: fix (increase) ipv6 literal buffer length
Marc Kleine-Budde (3):
can: dev: move driver related infrastructure into separate subdir
can: dev: can_restart(): don't crash kernel if carrier is OK
can: dev: can_restart(): fix race condition between controller restart and netif_carrier_on()
Matti Vaittinen (1):
tools: iio: iio_generic_buffer ensure alignment
Patrick Thompson (1):
net: r8169: Disable multicast filter for RTL8168H and RTL8107E
Pavel Machek (1):
ledtrig-cpu: Limit to 8 CPUs
Reuben Hawkins (1):
vfs: fix readahead(2) on block devices
Shigeru Yoshida (1):
tipc: Change nla_policy for bearer-related names to NLA_NUL_STRING
Sudeep Holla (1):
clk: scmi: Free scmi_clk allocated when the clocks with invalid info are skipped
Thierry Reding (1):
pwm: sti: Avoid conditional gotos
Thomas Gleixner (1):
sched/rt: Provide migrate_disable/enable() inlines
Tomas Glozar (1):
nd_btt: Make BTT lanes preemptible
Ursula Braun (1):
net/smc: postpone release of clcsock
Uwe Kleine-König (4):
leds: pwm: simplify if condition
leds: pwm: convert to atomic PWM API
leds: pwm: Don't disable the PWM when the LED should be off
pwm: sti: Reduce number of allocations and drop usage of chip_data
Willem de Bruijn (1):
llc: verify mac len before reading mac header
Yan Zhai (1):
ipv6: avoid atomic fragment on GSO packets
Yang Yingliang (3):
pcmcia: cs: fix possible hung task and memory leak pccardd()
pcmcia: ds: fix refcount leak in pcmcia_device_add()
pcmcia: ds: fix possible name leak in error path in pcmcia_device_add()
Yi Yang (1):
tty: tty_jobctrl: fix pid memleak in disassociate_ctty()
Zhang Rui (1):
hwmon: (coretemp) Fix potentially truncated sysfs attribute name
Zheng Wang (1):
media: bttv: fix use after free error due to btv->timeout timer
^ permalink raw reply [relevance 3%]
* [PATCH 4.19 78/88] net/smc: postpone release of clcsock
2023-11-15 20:35 2% [PATCH 4.19 00/88] 4.19.299-rc1 review Greg Kroah-Hartman
@ 2023-11-15 20:36 6% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-11-15 20:36 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ursula Braun, David S. Miller, Sasha Levin
4.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ursula Braun <ubraun@linux.ibm.com>
[ Upstream commit b03faa1fafc8018295401dc558bdc76362d860a4 ]
According to RFC7609 (http://www.rfc-editor.org/info/rfc7609)
first the SMC-R connection is shut down and then the normal TCP
connection FIN processing drives cleanup of the internal TCP connection.
The unconditional release of the clcsock during active socket closing
has to be postponed if the peer has not yet signalled socket closing.
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 5211c9729484 ("net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/smc/af_smc.c | 33 +++++++++++++++++----------------
net/smc/smc_close.c | 7 ++++++-
2 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index dcd00b514c3f9..6f342f6cc4876 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -143,32 +143,33 @@ static int smc_release(struct socket *sock)
rc = smc_close_active(smc);
sock_set_flag(sk, SOCK_DEAD);
sk->sk_shutdown |= SHUTDOWN_MASK;
- }
-
- sk->sk_prot->unhash(sk);
-
- if (smc->clcsock) {
- if (smc->use_fallback && sk->sk_state == SMC_LISTEN) {
+ } else {
+ if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT)
+ sock_put(sk); /* passive closing */
+ if (sk->sk_state == SMC_LISTEN) {
/* wake up clcsock accept */
rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR);
}
- mutex_lock(&smc->clcsock_release_lock);
- sock_release(smc->clcsock);
- smc->clcsock = NULL;
- mutex_unlock(&smc->clcsock_release_lock);
- }
- if (smc->use_fallback) {
- if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT)
- sock_put(sk); /* passive closing */
sk->sk_state = SMC_CLOSED;
sk->sk_state_change(sk);
}
+ sk->sk_prot->unhash(sk);
+
+ if (sk->sk_state == SMC_CLOSED) {
+ if (smc->clcsock) {
+ mutex_lock(&smc->clcsock_release_lock);
+ sock_release(smc->clcsock);
+ smc->clcsock = NULL;
+ mutex_unlock(&smc->clcsock_release_lock);
+ }
+ if (!smc->use_fallback)
+ smc_conn_free(&smc->conn);
+ }
+
/* detach socket */
sock_orphan(sk);
sock->sk = NULL;
- if (!smc->use_fallback && sk->sk_state == SMC_CLOSED)
- smc_conn_free(&smc->conn);
release_sock(sk);
sock_put(sk); /* final sock_put */
diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c
index 092696d738c00..3e7858793d485 100644
--- a/net/smc/smc_close.c
+++ b/net/smc/smc_close.c
@@ -415,8 +415,13 @@ static void smc_close_passive_work(struct work_struct *work)
if (old_state != sk->sk_state) {
sk->sk_state_change(sk);
if ((sk->sk_state == SMC_CLOSED) &&
- (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket))
+ (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) {
smc_conn_free(conn);
+ if (smc->clcsock) {
+ sock_release(smc->clcsock);
+ smc->clcsock = NULL;
+ }
+ }
}
release_sock(sk);
sock_put(sk); /* sock_hold done by schedulers of close_work */
--
2.42.0
^ permalink raw reply related [relevance 6%]
* [PATCH 4.19 00/88] 4.19.299-rc1 review
@ 2023-11-15 20:35 2% Greg Kroah-Hartman
2023-11-15 20:36 6% ` [PATCH 4.19 78/88] net/smc: postpone release of clcsock Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2023-11-15 20:35 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, srw, rwarsow, conor
This is the start of the stable review cycle for the 4.19.299 release.
There are 88 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Fri, 17 Nov 2023 19:14:03 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.19.299-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.19.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 4.19.299-rc1
Filipe Manana <fdmanana@suse.com>
btrfs: use u64 for buffer sizes in the tree search ioctls
Dominique Martinet <dominique.martinet@atmark-techno.com>
Revert "mmc: core: Capture correct oemid-bits for eMMC cards"
Arnd Bergmann <arnd@arndb.de>
fbdev: fsl-diu-fb: mark wr_reg_wa() static
Dan Carpenter <dan.carpenter@linaro.org>
fbdev: imsttfb: fix a resource leak in probe
Helge Deller <deller@gmx.de>
fbdev: imsttfb: Fix error path of imsttfb_probe()
Maciej Żenczykowski <zenczykowski@gmail.com>
netfilter: xt_recent: fix (increase) ipv6 literal buffer length
Heiner Kallweit <hkallweit1@gmail.com>
r8169: respect userspace disabling IFF_MULTICAST
George Shuklin <george.shuklin@gmail.com>
tg3: power down device only on SYSTEM_POWER_OFF
D. Wythe <alibuda@linux.alibaba.com>
net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT
Karsten Graul <kgraul@linux.ibm.com>
net/smc: wait for pending work before clcsock release_sock
Ursula Braun <ubraun@linux.ibm.com>
net/smc: postpone release of clcsock
Patrick Thompson <ptf@google.com>
net: r8169: Disable multicast filter for RTL8168H and RTL8107E
Heiner Kallweit <hkallweit1@gmail.com>
r8169: improve rtl_set_rx_mode
Kuniyuki Iwashima <kuniyu@amazon.com>
dccp/tcp: Call security_inet_conn_request() after setting IPv6 addresses.
Kuniyuki Iwashima <kuniyu@amazon.com>
dccp: Call security_inet_conn_request() after setting IPv4 addresses.
Shigeru Yoshida <syoshida@redhat.com>
tipc: Change nla_policy for bearer-related names to NLA_NUL_STRING
Willem de Bruijn <willemb@google.com>
llc: verify mac len before reading mac header
Dan Carpenter <dan.carpenter@linaro.org>
Input: synaptics-rmi4 - fix use after free in rmi_unregister_function()
Florian Fainelli <florian.fainelli@broadcom.com>
pwm: brcmstb: Utilize appropriate clock APIs in suspend/resume
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
pwm: sti: Reduce number of allocations and drop usage of chip_data
Thierry Reding <thierry.reding@gmail.com>
pwm: sti: Avoid conditional gotos
Hans Verkuil <hverkuil-cisco@xs4all.nl>
media: dvb-usb-v2: af9035: fix missing unlock
Katya Orlova <e.orlova@ispras.ru>
media: s3c-camif: Avoid inappropriate kfree()
Zheng Wang <zyytlz.wz@163.com>
media: bttv: fix use after free error due to btv->timeout timer
Yang Yingliang <yangyingliang@huawei.com>
pcmcia: ds: fix possible name leak in error path in pcmcia_device_add()
Yang Yingliang <yangyingliang@huawei.com>
pcmcia: ds: fix refcount leak in pcmcia_device_add()
Yang Yingliang <yangyingliang@huawei.com>
pcmcia: cs: fix possible hung task and memory leak pccardd()
Chao Yu <chao@kernel.org>
f2fs: fix to initialize map.m_pblk in f2fs_precache_extents()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: pxa_dma: Remove an erroneous BUG_ON() in pxad_free_desc()
Jonas Blixt <jonas.blixt@actia.se>
USB: usbip: fix stub_dev hub disconnect
Matti Vaittinen <mazziesaccount@gmail.com>
tools: iio: iio_generic_buffer ensure alignment
Chenyuan Mi <michenyuan@huawei.com>
tools: iio: iio_generic_buffer: Fix some integer type and calculation
Alexandru Ardelean <alexandru.ardelean@analog.com>
tools: iio: privatize globals and functions in iio_generic_buffer.c file
Jinjie Ruan <ruanjinjie@huawei.com>
misc: st_core: Do not call kfree_skb() under spin_lock_irqsave()
Dan Carpenter <dan.carpenter@linaro.org>
dmaengine: ti: edma: handle irq_of_parse_and_map() errors
Jia-Ju Bai <baijiaju@buaa.edu.cn>
usb: dwc2: fix possible NULL pointer dereference caused by driver concurrency
Yi Yang <yiyang13@huawei.com>
tty: tty_jobctrl: fix pid memleak in disassociate_ctty()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
leds: trigger: ledtrig-cpu:: Fix 'output may be truncated' issue for 'cpu'
Pavel Machek <pavel@ucw.cz>
ledtrig-cpu: Limit to 8 CPUs
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
leds: pwm: Don't disable the PWM when the LED should be off
Uwe Kleine-König <uwe@kleine-koenig.org>
leds: pwm: convert to atomic PWM API
Uwe Kleine-König <uwe@kleine-koenig.org>
leds: pwm: simplify if condition
Dinghao Liu <dinghao.liu@zju.edu.cn>
mfd: dln2: Fix double put in dln2_probe
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: ams-delta.c: use component after check
Cezary Rojewski <cezary.rojewski@intel.com>
ASoC: Intel: Skylake: Fix mem leak when parsing UUIDs fails
Geert Uytterhoeven <geert+renesas@glider.be>
sh: bios: Revive earlyprintk support
Leon Romanovsky <leonro@nvidia.com>
RDMA/hfi1: Workaround truncation compilation error
Gou Hao <gouhao@uniontech.com>
ext4: move 'ix' sanity check to corrent position
Kursad Oney <kursad.oney@broadcom.com>
ARM: 9321/1: memset: cast the constant byte to unsigned char
Danny Kaehn <danny.kaehn@plexus.com>
hid: cp2112: Fix duplicate workqueue initialization
Linus Walleij <linus.walleij@linaro.org>
HID: cp2112: Use irqchip template
Tomas Glozar <tglozar@redhat.com>
nd_btt: Make BTT lanes preemptible
Thomas Gleixner <tglx@linutronix.de>
sched/rt: Provide migrate_disable/enable() inlines
Jonas Gorski <jonas.gorski@gmail.com>
hwrng: geode - fix accessing registers
Sudeep Holla <sudeep.holla@arm.com>
clk: scmi: Free scmi_clk allocated when the clocks with invalid info are skipped
Dhruva Gole <d-gole@ti.com>
firmware: ti_sci: Mark driver as non removable
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: qcom: mdm9615: populate vsdcc fixed regulator
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
drm/rockchip: cdn-dp: Fix some error handling paths in cdn_dp_probe()
Konstantin Meskhidze <konstantin.meskhidze@huawei.com>
drm/radeon: possible buffer overflow
Jonas Karlman <jonas@kwiboo.se>
drm/rockchip: vop: Fix reset of state in duplicate state crtc funcs
Zhang Rui <rui.zhang@intel.com>
hwmon: (coretemp) Fix potentially truncated sysfs attribute name
Armin Wolf <W_Armin@gmx.de>
platform/x86: wmi: Fix opening of char device
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: remove unnecessary initializations
Armin Wolf <W_Armin@gmx.de>
platform/x86: wmi: Fix probe failure when failing to register WMI devices
Jiasheng Jiang <jiasheng@iscas.ac.cn>
clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data
Jiasheng Jiang <jiasheng@iscas.ac.cn>
clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data
Jonathan Neuschäfer <j.neuschaefer@gmx.net>
clk: npcm7xx: Fix incorrect kfree
Dan Carpenter <dan.carpenter@linaro.org>
clk: keystone: pll: fix a couple NULL vs IS_ERR() checks
Devi Priya <quic_devipriy@quicinc.com>
clk: qcom: clk-rcg2: Fix clock rate overflow for high parent frequencies
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
regmap: debugfs: Fix a erroneous check after snprintf()
Eric Dumazet <edumazet@google.com>
ipvlan: properly track tx_errors
Eric Dumazet <edumazet@google.com>
net: add DEV_STATS_READ() helper
Eric Dumazet <edumazet@google.com>
macsec: use DEV_STATS_INC()
Clayton Yager <Clayton_Yager@selinc.com>
macsec: Fix traffic counters/statistics
Yan Zhai <yan@cloudflare.com>
ipv6: avoid atomic fragment on GSO packets
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
ACPI: sysfs: Fix create_pnp_modalias() and create_of_modalias()
Eric Dumazet <edumazet@google.com>
chtls: fix tp->rcv_tstamp initialization
Dan Carpenter <dan.carpenter@linaro.org>
thermal: core: prevent potential string overflow
Marc Kleine-Budde <mkl@pengutronix.de>
can: dev: can_restart(): fix race condition between controller restart and netif_carrier_on()
Marc Kleine-Budde <mkl@pengutronix.de>
can: dev: can_restart(): don't crash kernel if carrier is OK
Marc Kleine-Budde <mkl@pengutronix.de>
can: dev: move driver related infrastructure into separate subdir
Dmitry Antipov <dmantipov@yandex.ru>
wifi: rtlwifi: fix EDCA limit set by BT coexistence
Eric Dumazet <edumazet@google.com>
tcp_metrics: do not create an entry from tcp_init_metrics()
Eric Dumazet <edumazet@google.com>
tcp_metrics: properly set tp->snd_ssthresh in tcp_init_metrics()
Eric Dumazet <edumazet@google.com>
tcp_metrics: add missing barriers on delete
Andrii Staikov <andrii.staikov@intel.com>
i40e: fix potential memory leaks in i40e_remove()
Chen Yu <yu.c.chen@intel.com>
genirq/matrix: Exclude managed interrupts in irq_matrix_allocated()
Reuben Hawkins <reubenhwk@gmail.com>
vfs: fix readahead(2) on block devices
-------------
Diffstat:
Makefile | 4 +-
arch/arm/boot/dts/qcom-mdm9615.dtsi | 14 ++--
arch/arm/lib/memset.S | 1 +
arch/sh/Kconfig.debug | 11 ++++
drivers/acpi/device_sysfs.c | 10 +--
drivers/base/regmap/regmap-debugfs.c | 2 +-
drivers/char/hw_random/geode-rng.c | 6 +-
drivers/clk/clk-npcm7xx.c | 2 +-
drivers/clk/clk-scmi.c | 1 +
drivers/clk/keystone/pll.c | 15 +++--
drivers/clk/mediatek/clk-mt2701.c | 8 +++
drivers/clk/mediatek/clk-mt6797.c | 6 ++
drivers/clk/qcom/clk-rcg2.c | 14 ++--
drivers/crypto/chelsio/chtls/chtls_cm.c | 2 +-
drivers/dma/pxa_dma.c | 1 -
drivers/dma/ti/edma.c | 4 +-
drivers/firmware/ti_sci.c | 46 +------------
drivers/gpu/drm/radeon/evergreen.c | 7 +-
drivers/gpu/drm/rockchip/cdn-dp-core.c | 15 ++++-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 +-
drivers/hid/hid-cp2112.c | 23 +++----
drivers/hwmon/coretemp.c | 2 +-
drivers/infiniband/hw/hfi1/efivar.c | 2 +-
drivers/input/rmi4/rmi_bus.c | 2 +-
drivers/leds/leds-pwm.c | 41 +++---------
drivers/leds/trigger/ledtrig-cpu.c | 17 +++--
drivers/media/pci/bt8xx/bttv-driver.c | 1 +
drivers/media/platform/s3c-camif/camif-capture.c | 6 +-
drivers/media/usb/dvb-usb-v2/af9035.c | 13 ++--
drivers/mfd/dln2.c | 1 -
drivers/misc/ti-st/st_core.c | 7 +-
drivers/mmc/core/mmc.c | 2 +-
drivers/net/can/Makefile | 7 +-
drivers/net/can/dev/Makefile | 7 ++
drivers/net/can/{ => dev}/dev.c | 10 +--
drivers/net/can/{ => dev}/rx-offload.c | 0
drivers/net/ethernet/broadcom/tg3.c | 3 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 10 ++-
drivers/net/ethernet/realtek/r8169_main.c | 56 ++++++++--------
drivers/net/ipvlan/ipvlan_core.c | 8 +--
drivers/net/ipvlan/ipvlan_main.c | 1 +
drivers/net/macsec.c | 70 +++++++++++++++-----
.../net/wireless/realtek/rtlwifi/rtl8188ee/dm.c | 2 +-
.../wireless/realtek/rtlwifi/rtl8192c/dm_common.c | 2 +-
.../net/wireless/realtek/rtlwifi/rtl8723ae/dm.c | 2 +-
drivers/nvdimm/region_devs.c | 8 +--
drivers/pcmcia/cs.c | 1 +
drivers/pcmcia/ds.c | 14 ++--
drivers/platform/x86/wmi.c | 50 ++++++---------
drivers/pwm/pwm-brcmstb.c | 4 +-
drivers/pwm/pwm-sti.c | 75 ++++++++++------------
drivers/thermal/thermal_core.c | 6 +-
drivers/tty/tty_jobctrl.c | 17 +++--
drivers/usb/dwc2/hcd.c | 2 +-
drivers/usb/usbip/stub_dev.c | 9 ++-
drivers/video/fbdev/fsl-diu-fb.c | 2 +-
drivers/video/fbdev/imsttfb.c | 33 ++++++----
fs/btrfs/ioctl.c | 10 +--
fs/ext4/extents.c | 10 +--
fs/f2fs/file.c | 1 +
include/linux/netdevice.h | 1 +
include/linux/preempt.h | 30 +++++++++
kernel/irq/matrix.c | 6 +-
mm/readahead.c | 3 +-
net/dccp/ipv4.c | 6 +-
net/dccp/ipv6.c | 6 +-
net/ipv4/tcp_metrics.c | 15 ++---
net/ipv6/ip6_output.c | 8 ++-
net/ipv6/syncookies.c | 7 +-
net/llc/llc_input.c | 10 ++-
net/llc/llc_s_ac.c | 3 +
net/llc/llc_station.c | 3 +
net/netfilter/xt_recent.c | 2 +-
net/smc/af_smc.c | 43 +++++++------
net/smc/smc.h | 5 ++
net/smc/smc_cdc.c | 2 +-
net/smc/smc_close.c | 26 +++++++-
net/smc/smc_close.h | 1 +
net/tipc/netlink.c | 4 +-
sound/soc/intel/skylake/skl-sst-utils.c | 1 +
sound/soc/omap/ams-delta.c | 4 +-
tools/iio/iio_generic_buffer.c | 59 +++++++++++------
82 files changed, 548 insertions(+), 406 deletions(-)
^ permalink raw reply [relevance 2%]
* Re: [PATCH AUTOSEL 6.5 13/41] btrfs: do not block starts waiting on previous transaction commit
2023-09-25 13:01 5% ` David Sterba
@ 2023-09-25 17:47 0% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2023-09-25 17:47 UTC (permalink / raw)
To: David Sterba
Cc: linux-kernel, stable, Josef Bacik, Filipe Manana, David Sterba,
clm, linux-btrfs, bpf
On Mon, Sep 25, 2023 at 03:01:12PM +0200, David Sterba wrote:
>On Sun, Sep 24, 2023 at 09:15:01AM -0400, Sasha Levin wrote:
>> From: Josef Bacik <josef@toxicpanda.com>
>>
>> [ Upstream commit 77d20c685b6baeb942606a93ed861c191381b73e ]
>>
>> Internally I got a report of very long stalls on normal operations like
>> creating a new file when auto relocation was running. The reporter used
>> the 'bpf offcputime' tracer to show that we would get stuck in
>> start_transaction for 5 to 30 seconds, and were always being woken up by
>> the transaction commit.
>>
>> Using my timing-everything script, which times how long a function takes
>> and what percentage of that total time is taken up by its children, I
>> saw several traces like this
>>
>> 1083 took 32812902424 ns
>> 29929002926 ns 91.2110% wait_for_commit_duration
>> 25568 ns 7.7920e-05% commit_fs_roots_duration
>> 1007751 ns 0.00307% commit_cowonly_roots_duration
>> 446855602 ns 1.36182% btrfs_run_delayed_refs_duration
>> 271980 ns 0.00082% btrfs_run_delayed_items_duration
>> 2008 ns 6.1195e-06% btrfs_apply_pending_changes_duration
>> 9656 ns 2.9427e-05% switch_commit_roots_duration
>> 1598 ns 4.8700e-06% btrfs_commit_device_sizes_duration
>> 4314 ns 1.3147e-05% btrfs_free_log_root_tree_duration
>>
>> Here I was only tracing functions that happen where we are between
>> START_COMMIT and UNBLOCKED in order to see what would be keeping us
>> blocked for so long. The wait_for_commit() we do is where we wait for a
>> previous transaction that hasn't completed it's commit. This can
>> include all of the unpin work and other cleanups, which tends to be the
>> longest part of our transaction commit.
>>
>> There is no reason we should be blocking new things from entering the
>> transaction at this point, it just adds to random latency spikes for no
>> reason.
>>
>> Fix this by adding a PREP stage. This allows us to properly deal with
>> multiple committers coming in at the same time, we retain the behavior
>> that the winner waits on the previous transaction and the losers all
>> wait for this transaction commit to occur. Nothing else is blocked
>> during the PREP stage, and then once the wait is complete we switch to
>> COMMIT_START and all of the same behavior as before is maintained.
>>
>> Reviewed-by: Filipe Manana <fdmanana@suse.com>
>> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
>> Reviewed-by: David Sterba <dsterba@suse.com>
>> Signed-off-by: David Sterba <dsterba@suse.com>
>> Signed-off-by: Sasha Levin <sashal@kernel.org>
>
>Please postpone adding this patch to stable trees until 6.6 is
>released. Thanks.
Ack.
--
Thanks,
Sasha
^ permalink raw reply [relevance 0%]
* Re: [PATCH AUTOSEL 6.5 13/41] btrfs: do not block starts waiting on previous transaction commit
@ 2023-09-25 13:01 5% ` David Sterba
2023-09-25 17:47 0% ` Sasha Levin
0 siblings, 1 reply; 200+ results
From: David Sterba @ 2023-09-25 13:01 UTC (permalink / raw)
To: Sasha Levin
Cc: linux-kernel, stable, Josef Bacik, Filipe Manana, David Sterba,
clm, linux-btrfs, bpf
On Sun, Sep 24, 2023 at 09:15:01AM -0400, Sasha Levin wrote:
> From: Josef Bacik <josef@toxicpanda.com>
>
> [ Upstream commit 77d20c685b6baeb942606a93ed861c191381b73e ]
>
> Internally I got a report of very long stalls on normal operations like
> creating a new file when auto relocation was running. The reporter used
> the 'bpf offcputime' tracer to show that we would get stuck in
> start_transaction for 5 to 30 seconds, and were always being woken up by
> the transaction commit.
>
> Using my timing-everything script, which times how long a function takes
> and what percentage of that total time is taken up by its children, I
> saw several traces like this
>
> 1083 took 32812902424 ns
> 29929002926 ns 91.2110% wait_for_commit_duration
> 25568 ns 7.7920e-05% commit_fs_roots_duration
> 1007751 ns 0.00307% commit_cowonly_roots_duration
> 446855602 ns 1.36182% btrfs_run_delayed_refs_duration
> 271980 ns 0.00082% btrfs_run_delayed_items_duration
> 2008 ns 6.1195e-06% btrfs_apply_pending_changes_duration
> 9656 ns 2.9427e-05% switch_commit_roots_duration
> 1598 ns 4.8700e-06% btrfs_commit_device_sizes_duration
> 4314 ns 1.3147e-05% btrfs_free_log_root_tree_duration
>
> Here I was only tracing functions that happen where we are between
> START_COMMIT and UNBLOCKED in order to see what would be keeping us
> blocked for so long. The wait_for_commit() we do is where we wait for a
> previous transaction that hasn't completed it's commit. This can
> include all of the unpin work and other cleanups, which tends to be the
> longest part of our transaction commit.
>
> There is no reason we should be blocking new things from entering the
> transaction at this point, it just adds to random latency spikes for no
> reason.
>
> Fix this by adding a PREP stage. This allows us to properly deal with
> multiple committers coming in at the same time, we retain the behavior
> that the winner waits on the previous transaction and the losers all
> wait for this transaction commit to occur. Nothing else is blocked
> during the PREP stage, and then once the wait is complete we switch to
> COMMIT_START and all of the same behavior as before is maintained.
>
> Reviewed-by: Filipe Manana <fdmanana@suse.com>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> Reviewed-by: David Sterba <dsterba@suse.com>
> Signed-off-by: David Sterba <dsterba@suse.com>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
Please postpone adding this patch to stable trees until 6.6 is
released. Thanks.
^ permalink raw reply [relevance 5%]
* Re: [REGRESSION] Re: [PATCH 6.1 033/219] memcg: drop kmem.limit_in_bytes
2023-09-20 10:21 0% ` Jeremi Piotrowski
@ 2023-09-20 10:45 0% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-09-20 10:45 UTC (permalink / raw)
To: Jeremi Piotrowski
Cc: Michal Hocko, stable, patches, Shakeel Butt, Johannes Weiner,
Roman Gushchin, Muchun Song, Tejun Heo, Andrew Morton,
linux-kernel, regressions, mathieu.tortuyaux
On Wed, Sep 20, 2023 at 12:21:37PM +0200, Jeremi Piotrowski wrote:
> On 9/20/2023 11:25 AM, Greg Kroah-Hartman wrote:
> > On Wed, Sep 20, 2023 at 10:43:56AM +0200, Michal Hocko wrote:
> >> On Wed 20-09-23 01:11:01, Jeremi Piotrowski wrote:
> >>> On Sun, Sep 17, 2023 at 09:12:40PM +0200, Greg Kroah-Hartman wrote:
> >>>> 6.1-stable review patch. If anyone has any objections, please let me know.
> >>>>
> >>>> ------------------
> >>>
> >>> Hi Greg/Michal,
> >>>
> >>> This commit breaks userspace which makes it a bad commit for mainline and an
> >>> even worse commit for stable.
> >>>
> >>> We ingested 6.1.54 into our nightly testing and found that runc fails to gather
> >>> cgroup statistics (when reading kmem.limit_in_bytes). The same code is vendored
> >>> into kubelet and kubelet fails to start if this operation fails. 6.1.53 is
> >>> fine.
> >>
> >> Could you expand some more on why is the file read? It doesn't support
> >> writing to it for some time so how does reading it helps in any sense?
> >>
> >> Anyway, I do agree that the stable backport should be reverted.
> >
> > That will just postpone the breakage, we really shouldn't break
> > userspace.
> >
> > That being said, having userspace "break" because a file is no longer
> > present is not good coding style on the userspace side at all. That's
> > why we have sysfs and single-value-files now, if the file isn't present,
> > then userspace instantly notices and can handle it. Much easier than
> > the old-style multi-fields-in-one-file problem.
> >
>
> The memcg files in this case are single-value, but userspace expects to be able
> to read memcg limits when it can read the usage (indicating MEMCG is enabled).
> If it can't - then something is off, and the node is marked unhealthy.
>
> >>>> Address this by wiping out the file completely and effectively get back to
> >>>> pre 4.5 era and CONFIG_MEMCG_KMEM=n configuration.
> >
> > The fact that this is a valid option (i.e. no file) with that config
> > option disabled makes me want to keep this as well, as how does
> > userspace handle this option disabled at all? Or old kernels?
> >
>
> Userspace has had to handle the case of MEMCG_KMEM=n, but that had 2 cases so far:
>
> limits/usage/max_usage/failcnt files are all available or none of them are available.
>
> Now it needs to handle 3 of 4 files being available, but only for kmem (and not plain
> memory, memsw or kmem.tcp). That's an inconsistency.
>
> > I can drop this from stable kernels, but again, this feels like the runc
> > developers are just postponing the problem...
> >
>
> Since cgroups v1 is deprecated, I think the runc developers haven't touched this part
> of the code in years and expected it to keep working while they wait for the long tail
> of usage to die out.
Ok, then we should revert this, I'll go drop it in the stable trees, it
should also be reverted in Linus's tree too.
thanks,
greg k-h
^ permalink raw reply [relevance 0%]
* Re: [REGRESSION] Re: [PATCH 6.1 033/219] memcg: drop kmem.limit_in_bytes
2023-09-20 9:25 5% ` Greg Kroah-Hartman
@ 2023-09-20 10:21 0% ` Jeremi Piotrowski
2023-09-20 10:45 0% ` Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Jeremi Piotrowski @ 2023-09-20 10:21 UTC (permalink / raw)
To: Greg Kroah-Hartman, Michal Hocko
Cc: stable, patches, Shakeel Butt, Johannes Weiner, Roman Gushchin,
Muchun Song, Tejun Heo, Andrew Morton, linux-kernel, regressions,
mathieu.tortuyaux
On 9/20/2023 11:25 AM, Greg Kroah-Hartman wrote:
> On Wed, Sep 20, 2023 at 10:43:56AM +0200, Michal Hocko wrote:
>> On Wed 20-09-23 01:11:01, Jeremi Piotrowski wrote:
>>> On Sun, Sep 17, 2023 at 09:12:40PM +0200, Greg Kroah-Hartman wrote:
>>>> 6.1-stable review patch. If anyone has any objections, please let me know.
>>>>
>>>> ------------------
>>>
>>> Hi Greg/Michal,
>>>
>>> This commit breaks userspace which makes it a bad commit for mainline and an
>>> even worse commit for stable.
>>>
>>> We ingested 6.1.54 into our nightly testing and found that runc fails to gather
>>> cgroup statistics (when reading kmem.limit_in_bytes). The same code is vendored
>>> into kubelet and kubelet fails to start if this operation fails. 6.1.53 is
>>> fine.
>>
>> Could you expand some more on why is the file read? It doesn't support
>> writing to it for some time so how does reading it helps in any sense?
>>
>> Anyway, I do agree that the stable backport should be reverted.
>
> That will just postpone the breakage, we really shouldn't break
> userspace.
>
> That being said, having userspace "break" because a file is no longer
> present is not good coding style on the userspace side at all. That's
> why we have sysfs and single-value-files now, if the file isn't present,
> then userspace instantly notices and can handle it. Much easier than
> the old-style multi-fields-in-one-file problem.
>
The memcg files in this case are single-value, but userspace expects to be able
to read memcg limits when it can read the usage (indicating MEMCG is enabled).
If it can't - then something is off, and the node is marked unhealthy.
>>>> Address this by wiping out the file completely and effectively get back to
>>>> pre 4.5 era and CONFIG_MEMCG_KMEM=n configuration.
>
> The fact that this is a valid option (i.e. no file) with that config
> option disabled makes me want to keep this as well, as how does
> userspace handle this option disabled at all? Or old kernels?
>
Userspace has had to handle the case of MEMCG_KMEM=n, but that had 2 cases so far:
limits/usage/max_usage/failcnt files are all available or none of them are available.
Now it needs to handle 3 of 4 files being available, but only for kmem (and not plain
memory, memsw or kmem.tcp). That's an inconsistency.
> I can drop this from stable kernels, but again, this feels like the runc
> developers are just postponing the problem...
>
Since cgroups v1 is deprecated, I think the runc developers haven't touched this part
of the code in years and expected it to keep working while they wait for the long tail
of usage to die out.
> thanks,
>
> greg k-h
^ permalink raw reply [relevance 0%]
* Re: [REGRESSION] Re: [PATCH 6.1 033/219] memcg: drop kmem.limit_in_bytes
@ 2023-09-20 9:25 5% ` Greg Kroah-Hartman
2023-09-20 10:21 0% ` Jeremi Piotrowski
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2023-09-20 9:25 UTC (permalink / raw)
To: Michal Hocko, Jeremi Piotrowski
Cc: stable, patches, Shakeel Butt, Johannes Weiner, Roman Gushchin,
Muchun Song, Tejun Heo, Andrew Morton, linux-kernel, regressions,
mathieu.tortuyaux
On Wed, Sep 20, 2023 at 10:43:56AM +0200, Michal Hocko wrote:
> On Wed 20-09-23 01:11:01, Jeremi Piotrowski wrote:
> > On Sun, Sep 17, 2023 at 09:12:40PM +0200, Greg Kroah-Hartman wrote:
> > > 6.1-stable review patch. If anyone has any objections, please let me know.
> > >
> > > ------------------
> >
> > Hi Greg/Michal,
> >
> > This commit breaks userspace which makes it a bad commit for mainline and an
> > even worse commit for stable.
> >
> > We ingested 6.1.54 into our nightly testing and found that runc fails to gather
> > cgroup statistics (when reading kmem.limit_in_bytes). The same code is vendored
> > into kubelet and kubelet fails to start if this operation fails. 6.1.53 is
> > fine.
>
> Could you expand some more on why is the file read? It doesn't support
> writing to it for some time so how does reading it helps in any sense?
>
> Anyway, I do agree that the stable backport should be reverted.
That will just postpone the breakage, we really shouldn't break
userspace.
That being said, having userspace "break" because a file is no longer
present is not good coding style on the userspace side at all. That's
why we have sysfs and single-value-files now, if the file isn't present,
then userspace instantly notices and can handle it. Much easier than
the old-style multi-fields-in-one-file problem.
> > > Address this by wiping out the file completely and effectively get back to
> > > pre 4.5 era and CONFIG_MEMCG_KMEM=n configuration.
The fact that this is a valid option (i.e. no file) with that config
option disabled makes me want to keep this as well, as how does
userspace handle this option disabled at all? Or old kernels?
I can drop this from stable kernels, but again, this feels like the runc
developers are just postponing the problem...
thanks,
greg k-h
^ permalink raw reply [relevance 5%]
* [PATCH 5.10 71/84] cgroup/cpuset: Free DL BW in case can_attach() fails
@ 2023-08-28 10:14 4% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-08-28 10:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Waiman Long, Dietmar Eggemann,
Juri Lelli, Tejun Heo, Qais Yousef (Google)
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dietmar Eggemann <dietmar.eggemann@arm.com>
commit 2ef269ef1ac006acf974793d975539244d77b28f upstream.
cpuset_can_attach() can fail. Postpone DL BW allocation until all tasks
have been checked. DL BW is not allocated per-task but as a sum over
all DL tasks migrating.
If multiple controllers are attached to the cgroup next to the cpuset
controller a non-cpuset can_attach() can fail. In this case free DL BW
in cpuset_cancel_attach().
Finally, update cpuset DL task count (nr_deadline_tasks) only in
cpuset_attach().
Suggested-by: Waiman Long <longman@redhat.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
[ Fix conflicts in kernel/cgroup/cpuset.c due to new code being applied
that is not applicable on this branch. Reject new code. ]
Signed-off-by: Qais Yousef (Google) <qyousef@layalina.io>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/sched.h | 2 -
kernel/cgroup/cpuset.c | 51 +++++++++++++++++++++++++++++++++++++++++++++----
kernel/sched/core.c | 17 +---------------
3 files changed, 50 insertions(+), 20 deletions(-)
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1657,7 +1657,7 @@ current_restore_flags(unsigned long orig
}
extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
-extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus);
+extern int task_can_attach(struct task_struct *p);
extern int dl_bw_alloc(int cpu, u64 dl_bw);
extern void dl_bw_free(int cpu, u64 dl_bw);
#ifdef CONFIG_SMP
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -167,6 +167,8 @@ struct cpuset {
* know when to rebuild associated root domain bandwidth information.
*/
int nr_deadline_tasks;
+ int nr_migrate_dl_tasks;
+ u64 sum_migrate_dl_bw;
};
/*
@@ -2168,16 +2170,23 @@ static int fmeter_getrate(struct fmeter
static struct cpuset *cpuset_attach_old_cs;
+static void reset_migrate_dl_data(struct cpuset *cs)
+{
+ cs->nr_migrate_dl_tasks = 0;
+ cs->sum_migrate_dl_bw = 0;
+}
+
/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
static int cpuset_can_attach(struct cgroup_taskset *tset)
{
struct cgroup_subsys_state *css;
- struct cpuset *cs;
+ struct cpuset *cs, *oldcs;
struct task_struct *task;
int ret;
/* used later by cpuset_attach() */
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+ oldcs = cpuset_attach_old_cs;
cs = css_cs(css);
mutex_lock(&cpuset_mutex);
@@ -2189,7 +2198,7 @@ static int cpuset_can_attach(struct cgro
goto out_unlock;
cgroup_taskset_for_each(task, css, tset) {
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
ret = security_task_setscheduler(task);
@@ -2197,11 +2206,31 @@ static int cpuset_can_attach(struct cgro
goto out_unlock;
if (dl_task(task)) {
- cs->nr_deadline_tasks++;
- cpuset_attach_old_cs->nr_deadline_tasks--;
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
}
}
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+ if (!cpumask_intersects(oldcs->effective_cpus, cs->effective_cpus)) {
+ int cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
+
+ if (unlikely(cpu >= nr_cpu_ids)) {
+ reset_migrate_dl_data(cs);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
+ if (ret) {
+ reset_migrate_dl_data(cs);
+ goto out_unlock;
+ }
+ }
+
+out_success:
/*
* Mark attach is in progress. This makes validate_change() fail
* changes which zero cpus/mems_allowed.
@@ -2225,6 +2254,14 @@ static void cpuset_cancel_attach(struct
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
+
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
+
mutex_unlock(&cpuset_mutex);
}
@@ -2299,6 +2336,12 @@ static void cpuset_attach(struct cgroup_
cs->old_mems_allowed = cpuset_attach_nodemask_to;
+ if (cs->nr_migrate_dl_tasks) {
+ cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
+ oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
+ reset_migrate_dl_data(cs);
+ }
+
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6600,8 +6600,7 @@ int cpuset_cpumask_can_shrink(const stru
return ret;
}
-int task_can_attach(struct task_struct *p,
- const struct cpumask *cs_effective_cpus)
+int task_can_attach(struct task_struct *p)
{
int ret = 0;
@@ -6614,21 +6613,9 @@ int task_can_attach(struct task_struct *
* success of set_cpus_allowed_ptr() on all attached tasks
* before cpus_mask may be changed.
*/
- if (p->flags & PF_NO_SETAFFINITY) {
+ if (p->flags & PF_NO_SETAFFINITY)
ret = -EINVAL;
- goto out;
- }
- if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
- cs_effective_cpus)) {
- int cpu = cpumask_any_and(cpu_active_mask, cs_effective_cpus);
-
- if (unlikely(cpu >= nr_cpu_ids))
- return -EINVAL;
- ret = dl_bw_alloc(cpu, p->dl.dl_bw);
- }
-
-out:
return ret;
}
^ permalink raw reply [relevance 4%]
* [PATCH 5.15 79/89] cgroup/cpuset: Free DL BW in case can_attach() fails
@ 2023-08-28 10:14 4% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-08-28 10:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Waiman Long, Dietmar Eggemann,
Juri Lelli, Tejun Heo, Qais Yousef (Google)
5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dietmar Eggemann <dietmar.eggemann@arm.com>
commit 2ef269ef1ac006acf974793d975539244d77b28f upstream.
cpuset_can_attach() can fail. Postpone DL BW allocation until all tasks
have been checked. DL BW is not allocated per-task but as a sum over
all DL tasks migrating.
If multiple controllers are attached to the cgroup next to the cpuset
controller a non-cpuset can_attach() can fail. In this case free DL BW
in cpuset_cancel_attach().
Finally, update cpuset DL task count (nr_deadline_tasks) only in
cpuset_attach().
Suggested-by: Waiman Long <longman@redhat.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
[ Conflict in kernel/cgroup/cpuset.c due to pulling extra neighboring
functions that are not applicable on this branch. ]
Signed-off-by: Qais Yousef (Google) <qyousef@layalina.io>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/sched.h | 2 -
kernel/cgroup/cpuset.c | 51 +++++++++++++++++++++++++++++++++++++++++++++----
kernel/sched/core.c | 17 +---------------
3 files changed, 50 insertions(+), 20 deletions(-)
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1797,7 +1797,7 @@ current_restore_flags(unsigned long orig
}
extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
-extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus);
+extern int task_can_attach(struct task_struct *p);
extern int dl_bw_alloc(int cpu, u64 dl_bw);
extern void dl_bw_free(int cpu, u64 dl_bw);
#ifdef CONFIG_SMP
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -167,6 +167,8 @@ struct cpuset {
* know when to rebuild associated root domain bandwidth information.
*/
int nr_deadline_tasks;
+ int nr_migrate_dl_tasks;
+ u64 sum_migrate_dl_bw;
/* Handle for cpuset.cpus.partition */
struct cgroup_file partition_file;
@@ -2206,16 +2208,23 @@ static int fmeter_getrate(struct fmeter
static struct cpuset *cpuset_attach_old_cs;
+static void reset_migrate_dl_data(struct cpuset *cs)
+{
+ cs->nr_migrate_dl_tasks = 0;
+ cs->sum_migrate_dl_bw = 0;
+}
+
/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
static int cpuset_can_attach(struct cgroup_taskset *tset)
{
struct cgroup_subsys_state *css;
- struct cpuset *cs;
+ struct cpuset *cs, *oldcs;
struct task_struct *task;
int ret;
/* used later by cpuset_attach() */
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+ oldcs = cpuset_attach_old_cs;
cs = css_cs(css);
mutex_lock(&cpuset_mutex);
@@ -2227,7 +2236,7 @@ static int cpuset_can_attach(struct cgro
goto out_unlock;
cgroup_taskset_for_each(task, css, tset) {
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
ret = security_task_setscheduler(task);
@@ -2235,11 +2244,31 @@ static int cpuset_can_attach(struct cgro
goto out_unlock;
if (dl_task(task)) {
- cs->nr_deadline_tasks++;
- cpuset_attach_old_cs->nr_deadline_tasks--;
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
}
}
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+ if (!cpumask_intersects(oldcs->effective_cpus, cs->effective_cpus)) {
+ int cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
+
+ if (unlikely(cpu >= nr_cpu_ids)) {
+ reset_migrate_dl_data(cs);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
+ if (ret) {
+ reset_migrate_dl_data(cs);
+ goto out_unlock;
+ }
+ }
+
+out_success:
/*
* Mark attach is in progress. This makes validate_change() fail
* changes which zero cpus/mems_allowed.
@@ -2263,6 +2292,14 @@ static void cpuset_cancel_attach(struct
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
+
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
+
mutex_unlock(&cpuset_mutex);
}
@@ -2335,6 +2372,12 @@ static void cpuset_attach(struct cgroup_
cs->old_mems_allowed = cpuset_attach_nodemask_to;
+ if (cs->nr_migrate_dl_tasks) {
+ cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
+ oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
+ reset_migrate_dl_data(cs);
+ }
+
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8789,8 +8789,7 @@ int cpuset_cpumask_can_shrink(const stru
return ret;
}
-int task_can_attach(struct task_struct *p,
- const struct cpumask *cs_effective_cpus)
+int task_can_attach(struct task_struct *p)
{
int ret = 0;
@@ -8803,21 +8802,9 @@ int task_can_attach(struct task_struct *
* success of set_cpus_allowed_ptr() on all attached tasks
* before cpus_mask may be changed.
*/
- if (p->flags & PF_NO_SETAFFINITY) {
+ if (p->flags & PF_NO_SETAFFINITY)
ret = -EINVAL;
- goto out;
- }
- if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
- cs_effective_cpus)) {
- int cpu = cpumask_any_and(cpu_active_mask, cs_effective_cpus);
-
- if (unlikely(cpu >= nr_cpu_ids))
- return -EINVAL;
- ret = dl_bw_alloc(cpu, p->dl.dl_bw);
- }
-
-out:
return ret;
}
^ permalink raw reply [relevance 4%]
* [PATCH 6.1 106/122] cgroup/cpuset: Free DL BW in case can_attach() fails
@ 2023-08-28 10:13 4% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-08-28 10:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Waiman Long, Dietmar Eggemann,
Juri Lelli, Tejun Heo, Qais Yousef (Google)
6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dietmar Eggemann <dietmar.eggemann@arm.com>
commit 2ef269ef1ac006acf974793d975539244d77b28f upstream.
cpuset_can_attach() can fail. Postpone DL BW allocation until all tasks
have been checked. DL BW is not allocated per-task but as a sum over
all DL tasks migrating.
If multiple controllers are attached to the cgroup next to the cpuset
controller a non-cpuset can_attach() can fail. In this case free DL BW
in cpuset_cancel_attach().
Finally, update cpuset DL task count (nr_deadline_tasks) only in
cpuset_attach().
Suggested-by: Waiman Long <longman@redhat.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Qais Yousef (Google) <qyousef@layalina.io>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/sched.h | 2 -
kernel/cgroup/cpuset.c | 53 ++++++++++++++++++++++++++++++++++++++++++++-----
kernel/sched/core.c | 17 +--------------
3 files changed, 51 insertions(+), 21 deletions(-)
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1846,7 +1846,7 @@ current_restore_flags(unsigned long orig
}
extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
-extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus);
+extern int task_can_attach(struct task_struct *p);
extern int dl_bw_alloc(int cpu, u64 dl_bw);
extern void dl_bw_free(int cpu, u64 dl_bw);
#ifdef CONFIG_SMP
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -198,6 +198,8 @@ struct cpuset {
* know when to rebuild associated root domain bandwidth information.
*/
int nr_deadline_tasks;
+ int nr_migrate_dl_tasks;
+ u64 sum_migrate_dl_bw;
/* Invalid partition error code, not lock protected */
enum prs_errcode prs_err;
@@ -2491,16 +2493,23 @@ static int cpuset_can_attach_check(struc
return 0;
}
+static void reset_migrate_dl_data(struct cpuset *cs)
+{
+ cs->nr_migrate_dl_tasks = 0;
+ cs->sum_migrate_dl_bw = 0;
+}
+
/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
static int cpuset_can_attach(struct cgroup_taskset *tset)
{
struct cgroup_subsys_state *css;
- struct cpuset *cs;
+ struct cpuset *cs, *oldcs;
struct task_struct *task;
int ret;
/* used later by cpuset_attach() */
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+ oldcs = cpuset_attach_old_cs;
cs = css_cs(css);
mutex_lock(&cpuset_mutex);
@@ -2511,7 +2520,7 @@ static int cpuset_can_attach(struct cgro
goto out_unlock;
cgroup_taskset_for_each(task, css, tset) {
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
ret = security_task_setscheduler(task);
@@ -2519,11 +2528,31 @@ static int cpuset_can_attach(struct cgro
goto out_unlock;
if (dl_task(task)) {
- cs->nr_deadline_tasks++;
- cpuset_attach_old_cs->nr_deadline_tasks--;
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
}
}
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+ if (!cpumask_intersects(oldcs->effective_cpus, cs->effective_cpus)) {
+ int cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
+
+ if (unlikely(cpu >= nr_cpu_ids)) {
+ reset_migrate_dl_data(cs);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
+ if (ret) {
+ reset_migrate_dl_data(cs);
+ goto out_unlock;
+ }
+ }
+
+out_success:
/*
* Mark attach is in progress. This makes validate_change() fail
* changes which zero cpus/mems_allowed.
@@ -2546,6 +2575,14 @@ static void cpuset_cancel_attach(struct
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
+
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
+
mutex_unlock(&cpuset_mutex);
}
@@ -2623,6 +2660,12 @@ static void cpuset_attach(struct cgroup_
cs->old_mems_allowed = cpuset_attach_nodemask_to;
+ if (cs->nr_migrate_dl_tasks) {
+ cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
+ oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
+ reset_migrate_dl_data(cs);
+ }
+
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
@@ -3298,7 +3341,7 @@ static int cpuset_can_fork(struct task_s
if (ret)
goto out_unlock;
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -9083,8 +9083,7 @@ int cpuset_cpumask_can_shrink(const stru
return ret;
}
-int task_can_attach(struct task_struct *p,
- const struct cpumask *cs_effective_cpus)
+int task_can_attach(struct task_struct *p)
{
int ret = 0;
@@ -9097,21 +9096,9 @@ int task_can_attach(struct task_struct *
* success of set_cpus_allowed_ptr() on all attached tasks
* before cpus_mask may be changed.
*/
- if (p->flags & PF_NO_SETAFFINITY) {
+ if (p->flags & PF_NO_SETAFFINITY)
ret = -EINVAL;
- goto out;
- }
- if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
- cs_effective_cpus)) {
- int cpu = cpumask_any_and(cpu_active_mask, cs_effective_cpus);
-
- if (unlikely(cpu >= nr_cpu_ids))
- return -EINVAL;
- ret = dl_bw_alloc(cpu, p->dl.dl_bw);
- }
-
-out:
return ret;
}
^ permalink raw reply [relevance 4%]
* [PATCH 6.4 084/129] cgroup/cpuset: Free DL BW in case can_attach() fails
@ 2023-08-28 10:12 4% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-08-28 10:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Waiman Long, Dietmar Eggemann,
Juri Lelli, Tejun Heo, Qais Yousef (Google)
6.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dietmar Eggemann <dietmar.eggemann@arm.com>
commit 2ef269ef1ac006acf974793d975539244d77b28f upstream.
cpuset_can_attach() can fail. Postpone DL BW allocation until all tasks
have been checked. DL BW is not allocated per-task but as a sum over
all DL tasks migrating.
If multiple controllers are attached to the cgroup next to the cpuset
controller a non-cpuset can_attach() can fail. In this case free DL BW
in cpuset_cancel_attach().
Finally, update cpuset DL task count (nr_deadline_tasks) only in
cpuset_attach().
Suggested-by: Waiman Long <longman@redhat.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Qais Yousef (Google) <qyousef@layalina.io>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/sched.h | 2 -
kernel/cgroup/cpuset.c | 53 ++++++++++++++++++++++++++++++++++++++++++++-----
kernel/sched/core.c | 17 +--------------
3 files changed, 51 insertions(+), 21 deletions(-)
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1852,7 +1852,7 @@ current_restore_flags(unsigned long orig
}
extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
-extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus);
+extern int task_can_attach(struct task_struct *p);
extern int dl_bw_alloc(int cpu, u64 dl_bw);
extern void dl_bw_free(int cpu, u64 dl_bw);
#ifdef CONFIG_SMP
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -198,6 +198,8 @@ struct cpuset {
* know when to rebuild associated root domain bandwidth information.
*/
int nr_deadline_tasks;
+ int nr_migrate_dl_tasks;
+ u64 sum_migrate_dl_bw;
/* Invalid partition error code, not lock protected */
enum prs_errcode prs_err;
@@ -2496,16 +2498,23 @@ static int cpuset_can_attach_check(struc
return 0;
}
+static void reset_migrate_dl_data(struct cpuset *cs)
+{
+ cs->nr_migrate_dl_tasks = 0;
+ cs->sum_migrate_dl_bw = 0;
+}
+
/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
static int cpuset_can_attach(struct cgroup_taskset *tset)
{
struct cgroup_subsys_state *css;
- struct cpuset *cs;
+ struct cpuset *cs, *oldcs;
struct task_struct *task;
int ret;
/* used later by cpuset_attach() */
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+ oldcs = cpuset_attach_old_cs;
cs = css_cs(css);
mutex_lock(&cpuset_mutex);
@@ -2516,7 +2525,7 @@ static int cpuset_can_attach(struct cgro
goto out_unlock;
cgroup_taskset_for_each(task, css, tset) {
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
ret = security_task_setscheduler(task);
@@ -2524,11 +2533,31 @@ static int cpuset_can_attach(struct cgro
goto out_unlock;
if (dl_task(task)) {
- cs->nr_deadline_tasks++;
- cpuset_attach_old_cs->nr_deadline_tasks--;
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
}
}
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+ if (!cpumask_intersects(oldcs->effective_cpus, cs->effective_cpus)) {
+ int cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
+
+ if (unlikely(cpu >= nr_cpu_ids)) {
+ reset_migrate_dl_data(cs);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
+ if (ret) {
+ reset_migrate_dl_data(cs);
+ goto out_unlock;
+ }
+ }
+
+out_success:
/*
* Mark attach is in progress. This makes validate_change() fail
* changes which zero cpus/mems_allowed.
@@ -2551,6 +2580,14 @@ static void cpuset_cancel_attach(struct
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
+
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
+
mutex_unlock(&cpuset_mutex);
}
@@ -2651,6 +2688,12 @@ static void cpuset_attach(struct cgroup_
out:
cs->old_mems_allowed = cpuset_attach_nodemask_to;
+ if (cs->nr_migrate_dl_tasks) {
+ cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
+ oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
+ reset_migrate_dl_data(cs);
+ }
+
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
@@ -3330,7 +3373,7 @@ static int cpuset_can_fork(struct task_s
if (ret)
goto out_unlock;
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -9294,8 +9294,7 @@ int cpuset_cpumask_can_shrink(const stru
return ret;
}
-int task_can_attach(struct task_struct *p,
- const struct cpumask *cs_effective_cpus)
+int task_can_attach(struct task_struct *p)
{
int ret = 0;
@@ -9308,21 +9307,9 @@ int task_can_attach(struct task_struct *
* success of set_cpus_allowed_ptr() on all attached tasks
* before cpus_mask may be changed.
*/
- if (p->flags & PF_NO_SETAFFINITY) {
+ if (p->flags & PF_NO_SETAFFINITY)
ret = -EINVAL;
- goto out;
- }
- if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
- cs_effective_cpus)) {
- int cpu = cpumask_any_and(cpu_active_mask, cs_effective_cpus);
-
- if (unlikely(cpu >= nr_cpu_ids))
- return -EINVAL;
- ret = dl_bw_alloc(cpu, p->dl.dl_bw);
- }
-
-out:
return ret;
}
^ permalink raw reply [relevance 4%]
* [PATCH 6/6] cgroup/cpuset: Free DL BW in case can_attach() fails
@ 2023-08-21 22:19 4% ` Qais Yousef
0 siblings, 0 replies; 200+ results
From: Qais Yousef @ 2023-08-21 22:19 UTC (permalink / raw)
To: stable
Cc: Juri Lelli, Waiman Long, Tejun Heo, Dietmar Eggemann,
Peter Zijlstra, Vincent Guittot, Ingo Molnar, Hao Luo,
John Stultz, cgroups, linux-kernel, Qais Yousef
From: Dietmar Eggemann <dietmar.eggemann@arm.com>
commit 2ef269ef1ac006acf974793d975539244d77b28f upstream.
cpuset_can_attach() can fail. Postpone DL BW allocation until all tasks
have been checked. DL BW is not allocated per-task but as a sum over
all DL tasks migrating.
If multiple controllers are attached to the cgroup next to the cpuset
controller a non-cpuset can_attach() can fail. In this case free DL BW
in cpuset_cancel_attach().
Finally, update cpuset DL task count (nr_deadline_tasks) only in
cpuset_attach().
Suggested-by: Waiman Long <longman@redhat.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
(cherry picked from commit 2ef269ef1ac006acf974793d975539244d77b28f)
Signed-off-by: Qais Yousef (Google) <qyousef@layalina.io>
---
include/linux/sched.h | 2 +-
kernel/cgroup/cpuset.c | 53 ++++++++++++++++++++++++++++++++++++++----
kernel/sched/core.c | 17 ++------------
3 files changed, 51 insertions(+), 21 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 0bee06542450..2553918f0b61 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1852,7 +1852,7 @@ current_restore_flags(unsigned long orig_flags, unsigned long flags)
}
extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
-extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus);
+extern int task_can_attach(struct task_struct *p);
extern int dl_bw_alloc(int cpu, u64 dl_bw);
extern void dl_bw_free(int cpu, u64 dl_bw);
#ifdef CONFIG_SMP
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index b7168970fff2..2c76fcd9f0bc 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -198,6 +198,8 @@ struct cpuset {
* know when to rebuild associated root domain bandwidth information.
*/
int nr_deadline_tasks;
+ int nr_migrate_dl_tasks;
+ u64 sum_migrate_dl_bw;
/* Invalid partition error code, not lock protected */
enum prs_errcode prs_err;
@@ -2496,16 +2498,23 @@ static int cpuset_can_attach_check(struct cpuset *cs)
return 0;
}
+static void reset_migrate_dl_data(struct cpuset *cs)
+{
+ cs->nr_migrate_dl_tasks = 0;
+ cs->sum_migrate_dl_bw = 0;
+}
+
/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
static int cpuset_can_attach(struct cgroup_taskset *tset)
{
struct cgroup_subsys_state *css;
- struct cpuset *cs;
+ struct cpuset *cs, *oldcs;
struct task_struct *task;
int ret;
/* used later by cpuset_attach() */
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+ oldcs = cpuset_attach_old_cs;
cs = css_cs(css);
mutex_lock(&cpuset_mutex);
@@ -2516,7 +2525,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
goto out_unlock;
cgroup_taskset_for_each(task, css, tset) {
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
ret = security_task_setscheduler(task);
@@ -2524,11 +2533,31 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
goto out_unlock;
if (dl_task(task)) {
- cs->nr_deadline_tasks++;
- cpuset_attach_old_cs->nr_deadline_tasks--;
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
}
}
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+ if (!cpumask_intersects(oldcs->effective_cpus, cs->effective_cpus)) {
+ int cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
+
+ if (unlikely(cpu >= nr_cpu_ids)) {
+ reset_migrate_dl_data(cs);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
+ if (ret) {
+ reset_migrate_dl_data(cs);
+ goto out_unlock;
+ }
+ }
+
+out_success:
/*
* Mark attach is in progress. This makes validate_change() fail
* changes which zero cpus/mems_allowed.
@@ -2551,6 +2580,14 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
+
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
+
mutex_unlock(&cpuset_mutex);
}
@@ -2651,6 +2688,12 @@ static void cpuset_attach(struct cgroup_taskset *tset)
out:
cs->old_mems_allowed = cpuset_attach_nodemask_to;
+ if (cs->nr_migrate_dl_tasks) {
+ cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
+ oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
+ reset_migrate_dl_data(cs);
+ }
+
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
@@ -3330,7 +3373,7 @@ static int cpuset_can_fork(struct task_struct *task, struct css_set *cset)
if (ret)
goto out_unlock;
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 50fab8114260..90005760003f 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -9294,8 +9294,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur,
return ret;
}
-int task_can_attach(struct task_struct *p,
- const struct cpumask *cs_effective_cpus)
+int task_can_attach(struct task_struct *p)
{
int ret = 0;
@@ -9308,21 +9307,9 @@ int task_can_attach(struct task_struct *p,
* success of set_cpus_allowed_ptr() on all attached tasks
* before cpus_mask may be changed.
*/
- if (p->flags & PF_NO_SETAFFINITY) {
+ if (p->flags & PF_NO_SETAFFINITY)
ret = -EINVAL;
- goto out;
- }
-
- if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
- cs_effective_cpus)) {
- int cpu = cpumask_any_and(cpu_active_mask, cs_effective_cpus);
- if (unlikely(cpu >= nr_cpu_ids))
- return -EINVAL;
- ret = dl_bw_alloc(cpu, p->dl.dl_bw);
- }
-
-out:
return ret;
}
--
2.34.1
^ permalink raw reply related [relevance 4%]
* [PATCH 6/6] cgroup/cpuset: Free DL BW in case can_attach() fails
@ 2023-08-20 15:22 4% ` Qais Yousef
0 siblings, 0 replies; 200+ results
From: Qais Yousef @ 2023-08-20 15:22 UTC (permalink / raw)
To: stable
Cc: Juri Lelli, Waiman Long, Tejun Heo, Dietmar Eggemann,
Peter Zijlstra, Vincent Guittot, Ingo Molnar, Hao Luo,
John Stultz, cgroups, linux-kernel, Qais Yousef
From: Dietmar Eggemann <dietmar.eggemann@arm.com>
commit 2ef269ef1ac006acf974793d975539244d77b28f upstream.
cpuset_can_attach() can fail. Postpone DL BW allocation until all tasks
have been checked. DL BW is not allocated per-task but as a sum over
all DL tasks migrating.
If multiple controllers are attached to the cgroup next to the cpuset
controller a non-cpuset can_attach() can fail. In this case free DL BW
in cpuset_cancel_attach().
Finally, update cpuset DL task count (nr_deadline_tasks) only in
cpuset_attach().
Suggested-by: Waiman Long <longman@redhat.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
(cherry picked from commit 2ef269ef1ac006acf974793d975539244d77b28f)
[Conflict in kernel/cgroup/cpuset.c due to pulling extra neighboring
functions that are not applicable on this branch.]
Signed-off-by: Qais Yousef (Google) <qyousef@layalina.io>
---
include/linux/sched.h | 2 +-
kernel/cgroup/cpuset.c | 51 ++++++++++++++++++++++++++++++++++++++----
kernel/sched/core.c | 17 ++------------
3 files changed, 50 insertions(+), 20 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 91fe1d6418e7..7bfc2b45cd99 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1797,7 +1797,7 @@ current_restore_flags(unsigned long orig_flags, unsigned long flags)
}
extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
-extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus);
+extern int task_can_attach(struct task_struct *p);
extern int dl_bw_alloc(int cpu, u64 dl_bw);
extern void dl_bw_free(int cpu, u64 dl_bw);
#ifdef CONFIG_SMP
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 63c8939503cb..6905079c15c2 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -167,6 +167,8 @@ struct cpuset {
* know when to rebuild associated root domain bandwidth information.
*/
int nr_deadline_tasks;
+ int nr_migrate_dl_tasks;
+ u64 sum_migrate_dl_bw;
/* Handle for cpuset.cpus.partition */
struct cgroup_file partition_file;
@@ -2206,16 +2208,23 @@ static int fmeter_getrate(struct fmeter *fmp)
static struct cpuset *cpuset_attach_old_cs;
+static void reset_migrate_dl_data(struct cpuset *cs)
+{
+ cs->nr_migrate_dl_tasks = 0;
+ cs->sum_migrate_dl_bw = 0;
+}
+
/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
static int cpuset_can_attach(struct cgroup_taskset *tset)
{
struct cgroup_subsys_state *css;
- struct cpuset *cs;
+ struct cpuset *cs, *oldcs;
struct task_struct *task;
int ret;
/* used later by cpuset_attach() */
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+ oldcs = cpuset_attach_old_cs;
cs = css_cs(css);
mutex_lock(&cpuset_mutex);
@@ -2227,7 +2236,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
goto out_unlock;
cgroup_taskset_for_each(task, css, tset) {
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
ret = security_task_setscheduler(task);
@@ -2235,11 +2244,31 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
goto out_unlock;
if (dl_task(task)) {
- cs->nr_deadline_tasks++;
- cpuset_attach_old_cs->nr_deadline_tasks--;
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
}
}
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+ if (!cpumask_intersects(oldcs->effective_cpus, cs->effective_cpus)) {
+ int cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
+
+ if (unlikely(cpu >= nr_cpu_ids)) {
+ reset_migrate_dl_data(cs);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
+ if (ret) {
+ reset_migrate_dl_data(cs);
+ goto out_unlock;
+ }
+ }
+
+out_success:
/*
* Mark attach is in progress. This makes validate_change() fail
* changes which zero cpus/mems_allowed.
@@ -2263,6 +2292,14 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
+
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
+
mutex_unlock(&cpuset_mutex);
}
@@ -2335,6 +2372,12 @@ static void cpuset_attach(struct cgroup_taskset *tset)
cs->old_mems_allowed = cpuset_attach_nodemask_to;
+ if (cs->nr_migrate_dl_tasks) {
+ cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
+ oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
+ reset_migrate_dl_data(cs);
+ }
+
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index da2a2906a826..2324b7055260 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8789,8 +8789,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur,
return ret;
}
-int task_can_attach(struct task_struct *p,
- const struct cpumask *cs_effective_cpus)
+int task_can_attach(struct task_struct *p)
{
int ret = 0;
@@ -8803,21 +8802,9 @@ int task_can_attach(struct task_struct *p,
* success of set_cpus_allowed_ptr() on all attached tasks
* before cpus_mask may be changed.
*/
- if (p->flags & PF_NO_SETAFFINITY) {
+ if (p->flags & PF_NO_SETAFFINITY)
ret = -EINVAL;
- goto out;
- }
-
- if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
- cs_effective_cpus)) {
- int cpu = cpumask_any_and(cpu_active_mask, cs_effective_cpus);
- if (unlikely(cpu >= nr_cpu_ids))
- return -EINVAL;
- ret = dl_bw_alloc(cpu, p->dl.dl_bw);
- }
-
-out:
return ret;
}
--
2.34.1
^ permalink raw reply related [relevance 4%]
* [PATCH 6/6] cgroup/cpuset: Free DL BW in case can_attach() fails
@ 2023-08-20 15:21 4% ` Qais Yousef
0 siblings, 0 replies; 200+ results
From: Qais Yousef @ 2023-08-20 15:21 UTC (permalink / raw)
To: stable
Cc: Juri Lelli, Waiman Long, Tejun Heo, Dietmar Eggemann,
Peter Zijlstra, Vincent Guittot, Ingo Molnar, Hao Luo,
John Stultz, cgroups, linux-kernel, Qais Yousef
From: Dietmar Eggemann <dietmar.eggemann@arm.com>
commit 2ef269ef1ac006acf974793d975539244d77b28f upstream.
cpuset_can_attach() can fail. Postpone DL BW allocation until all tasks
have been checked. DL BW is not allocated per-task but as a sum over
all DL tasks migrating.
If multiple controllers are attached to the cgroup next to the cpuset
controller a non-cpuset can_attach() can fail. In this case free DL BW
in cpuset_cancel_attach().
Finally, update cpuset DL task count (nr_deadline_tasks) only in
cpuset_attach().
Suggested-by: Waiman Long <longman@redhat.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
(cherry picked from commit 2ef269ef1ac006acf974793d975539244d77b28f)
[Fix conflicts in kernel/cgroup/cpuset.c due to new code being applied
that is not applicable on this branch. Reject new code.]
Signed-off-by: Qais Yousef (Google) <qyousef@layalina.io>
---
include/linux/sched.h | 2 +-
kernel/cgroup/cpuset.c | 51 ++++++++++++++++++++++++++++++++++++++----
kernel/sched/core.c | 17 ++------------
3 files changed, 50 insertions(+), 20 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f4b3640dadb8..aa015416c569 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1657,7 +1657,7 @@ current_restore_flags(unsigned long orig_flags, unsigned long flags)
}
extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
-extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus);
+extern int task_can_attach(struct task_struct *p);
extern int dl_bw_alloc(int cpu, u64 dl_bw);
extern void dl_bw_free(int cpu, u64 dl_bw);
#ifdef CONFIG_SMP
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 6c69e715b05a..195f9cccab20 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -167,6 +167,8 @@ struct cpuset {
* know when to rebuild associated root domain bandwidth information.
*/
int nr_deadline_tasks;
+ int nr_migrate_dl_tasks;
+ u64 sum_migrate_dl_bw;
};
/*
@@ -2168,16 +2170,23 @@ static int fmeter_getrate(struct fmeter *fmp)
static struct cpuset *cpuset_attach_old_cs;
+static void reset_migrate_dl_data(struct cpuset *cs)
+{
+ cs->nr_migrate_dl_tasks = 0;
+ cs->sum_migrate_dl_bw = 0;
+}
+
/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
static int cpuset_can_attach(struct cgroup_taskset *tset)
{
struct cgroup_subsys_state *css;
- struct cpuset *cs;
+ struct cpuset *cs, *oldcs;
struct task_struct *task;
int ret;
/* used later by cpuset_attach() */
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+ oldcs = cpuset_attach_old_cs;
cs = css_cs(css);
mutex_lock(&cpuset_mutex);
@@ -2189,7 +2198,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
goto out_unlock;
cgroup_taskset_for_each(task, css, tset) {
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
ret = security_task_setscheduler(task);
@@ -2197,11 +2206,31 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
goto out_unlock;
if (dl_task(task)) {
- cs->nr_deadline_tasks++;
- cpuset_attach_old_cs->nr_deadline_tasks--;
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
}
}
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+ if (!cpumask_intersects(oldcs->effective_cpus, cs->effective_cpus)) {
+ int cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
+
+ if (unlikely(cpu >= nr_cpu_ids)) {
+ reset_migrate_dl_data(cs);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
+ if (ret) {
+ reset_migrate_dl_data(cs);
+ goto out_unlock;
+ }
+ }
+
+out_success:
/*
* Mark attach is in progress. This makes validate_change() fail
* changes which zero cpus/mems_allowed.
@@ -2225,6 +2254,14 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
+
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
+
mutex_unlock(&cpuset_mutex);
}
@@ -2299,6 +2336,12 @@ static void cpuset_attach(struct cgroup_taskset *tset)
cs->old_mems_allowed = cpuset_attach_nodemask_to;
+ if (cs->nr_migrate_dl_tasks) {
+ cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
+ oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
+ reset_migrate_dl_data(cs);
+ }
+
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 3cfcd2059a66..40f40f359c5d 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6600,8 +6600,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur,
return ret;
}
-int task_can_attach(struct task_struct *p,
- const struct cpumask *cs_effective_cpus)
+int task_can_attach(struct task_struct *p)
{
int ret = 0;
@@ -6614,21 +6613,9 @@ int task_can_attach(struct task_struct *p,
* success of set_cpus_allowed_ptr() on all attached tasks
* before cpus_mask may be changed.
*/
- if (p->flags & PF_NO_SETAFFINITY) {
+ if (p->flags & PF_NO_SETAFFINITY)
ret = -EINVAL;
- goto out;
- }
-
- if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
- cs_effective_cpus)) {
- int cpu = cpumask_any_and(cpu_active_mask, cs_effective_cpus);
- if (unlikely(cpu >= nr_cpu_ids))
- return -EINVAL;
- ret = dl_bw_alloc(cpu, p->dl.dl_bw);
- }
-
-out:
return ret;
}
--
2.34.1
^ permalink raw reply related [relevance 4%]
* [PATCH 6/6] cgroup/cpuset: Free DL BW in case can_attach() fails
@ 2023-08-20 15:24 4% ` Qais Yousef
0 siblings, 0 replies; 200+ results
From: Qais Yousef @ 2023-08-20 15:24 UTC (permalink / raw)
To: stable
Cc: Juri Lelli, Waiman Long, Tejun Heo, Dietmar Eggemann,
Peter Zijlstra, Vincent Guittot, Ingo Molnar, Hao Luo,
John Stultz, cgroups, linux-kernel, Qais Yousef
From: Dietmar Eggemann <dietmar.eggemann@arm.com>
commit 2ef269ef1ac006acf974793d975539244d77b28f upstream.
cpuset_can_attach() can fail. Postpone DL BW allocation until all tasks
have been checked. DL BW is not allocated per-task but as a sum over
all DL tasks migrating.
If multiple controllers are attached to the cgroup next to the cpuset
controller a non-cpuset can_attach() can fail. In this case free DL BW
in cpuset_cancel_attach().
Finally, update cpuset DL task count (nr_deadline_tasks) only in
cpuset_attach().
Suggested-by: Waiman Long <longman@redhat.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
(cherry picked from commit 2ef269ef1ac006acf974793d975539244d77b28f)
Signed-off-by: Qais Yousef (Google) <qyousef@layalina.io>
---
include/linux/sched.h | 2 +-
kernel/cgroup/cpuset.c | 53 ++++++++++++++++++++++++++++++++++++++----
kernel/sched/core.c | 17 ++------------
3 files changed, 51 insertions(+), 21 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b2e30fbbeef0..0cac69902ec5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1846,7 +1846,7 @@ current_restore_flags(unsigned long orig_flags, unsigned long flags)
}
extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
-extern int task_can_attach(struct task_struct *p, const struct cpumask *cs_effective_cpus);
+extern int task_can_attach(struct task_struct *p);
extern int dl_bw_alloc(int cpu, u64 dl_bw);
extern void dl_bw_free(int cpu, u64 dl_bw);
#ifdef CONFIG_SMP
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index eca07ff71656..db3e05b6b4dd 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -198,6 +198,8 @@ struct cpuset {
* know when to rebuild associated root domain bandwidth information.
*/
int nr_deadline_tasks;
+ int nr_migrate_dl_tasks;
+ u64 sum_migrate_dl_bw;
/* Invalid partition error code, not lock protected */
enum prs_errcode prs_err;
@@ -2491,16 +2493,23 @@ static int cpuset_can_attach_check(struct cpuset *cs)
return 0;
}
+static void reset_migrate_dl_data(struct cpuset *cs)
+{
+ cs->nr_migrate_dl_tasks = 0;
+ cs->sum_migrate_dl_bw = 0;
+}
+
/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
static int cpuset_can_attach(struct cgroup_taskset *tset)
{
struct cgroup_subsys_state *css;
- struct cpuset *cs;
+ struct cpuset *cs, *oldcs;
struct task_struct *task;
int ret;
/* used later by cpuset_attach() */
cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+ oldcs = cpuset_attach_old_cs;
cs = css_cs(css);
mutex_lock(&cpuset_mutex);
@@ -2511,7 +2520,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
goto out_unlock;
cgroup_taskset_for_each(task, css, tset) {
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
ret = security_task_setscheduler(task);
@@ -2519,11 +2528,31 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
goto out_unlock;
if (dl_task(task)) {
- cs->nr_deadline_tasks++;
- cpuset_attach_old_cs->nr_deadline_tasks--;
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
}
}
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+ if (!cpumask_intersects(oldcs->effective_cpus, cs->effective_cpus)) {
+ int cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
+
+ if (unlikely(cpu >= nr_cpu_ids)) {
+ reset_migrate_dl_data(cs);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
+ if (ret) {
+ reset_migrate_dl_data(cs);
+ goto out_unlock;
+ }
+ }
+
+out_success:
/*
* Mark attach is in progress. This makes validate_change() fail
* changes which zero cpus/mems_allowed.
@@ -2546,6 +2575,14 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
+
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
+
mutex_unlock(&cpuset_mutex);
}
@@ -2623,6 +2660,12 @@ static void cpuset_attach(struct cgroup_taskset *tset)
cs->old_mems_allowed = cpuset_attach_nodemask_to;
+ if (cs->nr_migrate_dl_tasks) {
+ cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
+ oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
+ reset_migrate_dl_data(cs);
+ }
+
cs->attach_in_progress--;
if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
@@ -3298,7 +3341,7 @@ static int cpuset_can_fork(struct task_struct *task, struct css_set *cset)
if (ret)
goto out_unlock;
- ret = task_can_attach(task, cs->effective_cpus);
+ ret = task_can_attach(task);
if (ret)
goto out_unlock;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 6963fc4ef897..0f6a92737c91 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -9083,8 +9083,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur,
return ret;
}
-int task_can_attach(struct task_struct *p,
- const struct cpumask *cs_effective_cpus)
+int task_can_attach(struct task_struct *p)
{
int ret = 0;
@@ -9097,21 +9096,9 @@ int task_can_attach(struct task_struct *p,
* success of set_cpus_allowed_ptr() on all attached tasks
* before cpus_mask may be changed.
*/
- if (p->flags & PF_NO_SETAFFINITY) {
+ if (p->flags & PF_NO_SETAFFINITY)
ret = -EINVAL;
- goto out;
- }
-
- if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
- cs_effective_cpus)) {
- int cpu = cpumask_any_and(cpu_active_mask, cs_effective_cpus);
- if (unlikely(cpu >= nr_cpu_ids))
- return -EINVAL;
- ret = dl_bw_alloc(cpu, p->dl.dl_bw);
- }
-
-out:
return ret;
}
--
2.34.1
^ permalink raw reply related [relevance 4%]
* [PATCH 4.19 045/323] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
@ 2023-08-09 10:38 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-08-09 10:38 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Remi Pommarel, Nicolas Escande,
Toke Høiland-Jørgensen, Kalle Valo, Sasha Levin
From: Remi Pommarel <repk@triplefau.lt>
[ Upstream commit 75086cc6dee046e3fbb3dba148b376d8802f83bc ]
On EDMA capable hardware, ath9k_txq_list_has_key() can enter infinite
loop if it is called while all txq_fifos have packets that use different
key that the one we are looking for. Fix it by exiting the loop if all
txq_fifos have been checked already.
Because this loop is called under spin_lock_bh() (see ath_txq_lock) it
causes the following rcu stall:
rcu: INFO: rcu_sched self-detected stall on CPU
ath10k_pci 0000:01:00.0: failed to read temperature -11
rcu: 1-....: (5254 ticks this GP) idle=189/1/0x4000000000000002 softirq=8442983/8442984 fqs=2579
(t=5257 jiffies g=17983297 q=334)
Task dump for CPU 1:
task:hostapd state:R running task stack: 0 pid: 297 ppid: 289 flags:0x0000000a
Call trace:
dump_backtrace+0x0/0x170
show_stack+0x1c/0x24
sched_show_task+0x140/0x170
dump_cpu_task+0x48/0x54
rcu_dump_cpu_stacks+0xf0/0x134
rcu_sched_clock_irq+0x8d8/0x9fc
update_process_times+0xa0/0xec
tick_sched_timer+0x5c/0xd0
__hrtimer_run_queues+0x154/0x320
hrtimer_interrupt+0x120/0x2f0
arch_timer_handler_virt+0x38/0x44
handle_percpu_devid_irq+0x9c/0x1e0
handle_domain_irq+0x64/0x90
gic_handle_irq+0x78/0xb0
call_on_irq_stack+0x28/0x38
do_interrupt_handler+0x54/0x5c
el1_interrupt+0x2c/0x4c
el1h_64_irq_handler+0x14/0x1c
el1h_64_irq+0x74/0x78
ath9k_txq_has_key+0x1bc/0x250 [ath9k]
ath9k_set_key+0x1cc/0x3dc [ath9k]
drv_set_key+0x78/0x170
ieee80211_key_replace+0x564/0x6cc
ieee80211_key_link+0x174/0x220
ieee80211_add_key+0x11c/0x300
nl80211_new_key+0x12c/0x330
genl_family_rcv_msg_doit+0xbc/0x11c
genl_rcv_msg+0xd8/0x1c4
netlink_rcv_skb+0x40/0x100
genl_rcv+0x3c/0x50
netlink_unicast+0x1ec/0x2c0
netlink_sendmsg+0x198/0x3c0
____sys_sendmsg+0x210/0x250
___sys_sendmsg+0x78/0xc4
__sys_sendmsg+0x4c/0x90
__arm64_sys_sendmsg+0x28/0x30
invoke_syscall.constprop.0+0x60/0x100
do_el0_svc+0x48/0xd0
el0_svc+0x14/0x50
el0t_64_sync_handler+0xa8/0xb0
el0t_64_sync+0x158/0x15c
This rcu stall is hard to reproduce as is, but changing ATH_TXFIFO_DEPTH
from 8 to 2 makes it reasonably easy to reproduce.
Fixes: ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
Tested-by: Nicolas Escande <nico.escande@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230609093744.1985-1-repk@triplefau.lt
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath9k/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index ee1b9c39bad7a..e8e297a04d360 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -847,7 +847,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -865,8 +865,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 4.14 026/204] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
@ 2023-08-09 10:39 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-08-09 10:39 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Remi Pommarel, Nicolas Escande,
Toke Høiland-Jørgensen, Kalle Valo, Sasha Levin
From: Remi Pommarel <repk@triplefau.lt>
[ Upstream commit 75086cc6dee046e3fbb3dba148b376d8802f83bc ]
On EDMA capable hardware, ath9k_txq_list_has_key() can enter infinite
loop if it is called while all txq_fifos have packets that use different
key that the one we are looking for. Fix it by exiting the loop if all
txq_fifos have been checked already.
Because this loop is called under spin_lock_bh() (see ath_txq_lock) it
causes the following rcu stall:
rcu: INFO: rcu_sched self-detected stall on CPU
ath10k_pci 0000:01:00.0: failed to read temperature -11
rcu: 1-....: (5254 ticks this GP) idle=189/1/0x4000000000000002 softirq=8442983/8442984 fqs=2579
(t=5257 jiffies g=17983297 q=334)
Task dump for CPU 1:
task:hostapd state:R running task stack: 0 pid: 297 ppid: 289 flags:0x0000000a
Call trace:
dump_backtrace+0x0/0x170
show_stack+0x1c/0x24
sched_show_task+0x140/0x170
dump_cpu_task+0x48/0x54
rcu_dump_cpu_stacks+0xf0/0x134
rcu_sched_clock_irq+0x8d8/0x9fc
update_process_times+0xa0/0xec
tick_sched_timer+0x5c/0xd0
__hrtimer_run_queues+0x154/0x320
hrtimer_interrupt+0x120/0x2f0
arch_timer_handler_virt+0x38/0x44
handle_percpu_devid_irq+0x9c/0x1e0
handle_domain_irq+0x64/0x90
gic_handle_irq+0x78/0xb0
call_on_irq_stack+0x28/0x38
do_interrupt_handler+0x54/0x5c
el1_interrupt+0x2c/0x4c
el1h_64_irq_handler+0x14/0x1c
el1h_64_irq+0x74/0x78
ath9k_txq_has_key+0x1bc/0x250 [ath9k]
ath9k_set_key+0x1cc/0x3dc [ath9k]
drv_set_key+0x78/0x170
ieee80211_key_replace+0x564/0x6cc
ieee80211_key_link+0x174/0x220
ieee80211_add_key+0x11c/0x300
nl80211_new_key+0x12c/0x330
genl_family_rcv_msg_doit+0xbc/0x11c
genl_rcv_msg+0xd8/0x1c4
netlink_rcv_skb+0x40/0x100
genl_rcv+0x3c/0x50
netlink_unicast+0x1ec/0x2c0
netlink_sendmsg+0x198/0x3c0
____sys_sendmsg+0x210/0x250
___sys_sendmsg+0x78/0xc4
__sys_sendmsg+0x4c/0x90
__arm64_sys_sendmsg+0x28/0x30
invoke_syscall.constprop.0+0x60/0x100
do_el0_svc+0x48/0xd0
el0_svc+0x14/0x50
el0t_64_sync_handler+0xa8/0xb0
el0t_64_sync+0x158/0x15c
This rcu stall is hard to reproduce as is, but changing ATH_TXFIFO_DEPTH
from 8 to 2 makes it reasonably easy to reproduce.
Fixes: ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
Tested-by: Nicolas Escande <nico.escande@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230609093744.1985-1-repk@triplefau.lt
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath9k/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 507d8c5149686..1afaa437619d3 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -846,7 +846,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -864,8 +864,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
--
2.39.2
^ permalink raw reply related [relevance 5%]
* Re: [PATCH 5.10 000/509] 5.10.188-rc1 review
2023-07-25 10:38 1% [PATCH 5.10 000/509] 5.10.188-rc1 review Greg Kroah-Hartman
2023-07-25 10:40 5% ` [PATCH 5.10 073/509] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-07-25 10:44 7% ` [PATCH 5.10 348/509] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
@ 2023-07-28 9:31 0% ` luomeng
2 siblings, 0 replies; 200+ results
From: luomeng @ 2023-07-28 9:31 UTC (permalink / raw)
To: Greg Kroah-Hartman, stable
Cc: patches, linux-kernel, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, sudipm.mukherjee, srw,
rwarsow, conor
Tested on arm64 and x86 for 5.10.188-rc1,
Kernel
repo:https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
Branch: linux-5.10.y
Version: 5.10.188-rc1
Commit: 4a64f03701033c39271bac1039ff76ef15ae50a3
Compiler: gcc version 7.3.0 (GCC)
arm64:
--------------------------------------------------------------------
Testcase Result Summary:
total: 8978
passed: 8978
failed: 0
timeout: 0
--------------------------------------------------------------------
x86:
--------------------------------------------------------------------
Testcase Result Summary:
total: 8978
passed: 8978
failed: 0
timeout: 0
--------------------------------------------------------------------
Tested-by: Hulk Robot <hulkrobot@huawei.com>
在 2023/7/25 18:38, Greg Kroah-Hartman 写道:
> This is the start of the stable review cycle for the 5.10.188 release.
> There are 509 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu, 27 Jul 2023 10:44:26 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.188-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
>
> -------------
> Pseudo-Shortlog of commits:
>
> Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Linux 5.10.188-rc1
>
> Zheng Yejian <zhengyejian1@huawei.com>
> ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
>
> Linus Torvalds <torvalds@linux-foundation.org>
> ftrace: Store the order of pages allocated in ftrace_page
>
> Zheng Yejian <zhengyejian1@huawei.com>
> tracing: Fix memory leak of iter->temp when reading trace_pipe
>
> Mohamed Khalfella <mkhalfella@purestorage.com>
> tracing/histograms: Return an error if we fail to add histogram to hist_vars list
>
> Vladimir Oltean <vladimir.oltean@nxp.com>
> net: phy: prevent stale pointer dereference in phy_init()
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around fastopenq.max_qlen
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around icsk->icsk_user_timeout
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around tp->notsent_lowat
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around rskq_defer_accept
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around tp->linger2
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around icsk->icsk_syn_retries
>
> Kuniyuki Iwashima <kuniyu@amazon.com>
> tcp: Fix data-races around sysctl_tcp_syn(ack)?_retries.
>
> Kuniyuki Iwashima <kuniyu@amazon.co.jp>
> net: Introduce net.ipv4.tcp_migrate_req.
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around tp->keepalive_probes
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around tp->keepalive_intvl
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around tp->keepalive_time
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around tp->tcp_tx_delay
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nf_tables: skip bound chain on rule flush
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nf_tables: skip bound chain in netns release path
>
> Florian Westphal <fw@strlen.de>
> netfilter: nft_set_pipapo: fix improper element removal
>
> Florian Westphal <fw@strlen.de>
> netfilter: nf_tables: can't schedule in nft_chain_validate
>
> Florian Westphal <fw@strlen.de>
> netfilter: nf_tables: fix spurious set element insertion failure
>
> Kuniyuki Iwashima <kuniyu@amazon.com>
> llc: Don't drop packet from non-root netns.
>
> Zhang Shurong <zhang_shurong@foxmail.com>
> fbdev: au1200fb: Fix missing IRQ check in au1200fb_drv_probe
>
> Kuniyuki Iwashima <kuniyu@amazon.com>
> Revert "tcp: avoid the lookup process failing to get sk in ehash table"
>
> Yuanjun Gong <ruc_gongyuanjun@163.com>
> net:ipv6: check return value of pskb_trim()
>
> Wang Ming <machel@vivo.com>
> net: ipv4: Use kfree_sensitive instead of kfree
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data-races around tcp_rsk(req)->ts_recent
>
> Geetha sowjanya <gakula@marvell.com>
> octeontx2-pf: Dont allocate BPIDs for LBK interfaces
>
> Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
> security: keys: Modify mismatched function name
>
> Ding Hui <dinghui@sangfor.com.cn>
> iavf: Fix out-of-bounds when setting channels on remove
>
> Ding Hui <dinghui@sangfor.com.cn>
> iavf: Fix use-after-free in free_netdev
>
> Kuniyuki Iwashima <kuniyu@amazon.com>
> bridge: Add extack warning when enabling STP in netns.
>
> Tanmay Patil <t-patil@ti.com>
> net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()
>
> Mario Limonciello <mario.limonciello@amd.com>
> pinctrl: amd: Use amd_pinconf_set() for all config options
>
> Martin Kaiser <martin@kaiser.cx>
> fbdev: imxfb: warn about invalid left/right margin
>
> Jonas Gorski <jonas.gorski@gmail.com>
> spi: bcm63xx: fix max prepend length
>
> Ying Hsu <yinghsu@chromium.org>
> igb: Fix igb_down hung on surprise removal
>
> Johannes Berg <johannes.berg@intel.com>
> wifi: iwlwifi: mvm: avoid baid size integer overflow
>
> Gustavo A. R. Silva <gustavoars@kernel.org>
> wifi: wext-core: Fix -Wstringop-overflow warning in ioctl_standard_iw_point()
>
> Petr Oros <poros@redhat.com>
> devlink: report devlink_port_type_warn source device
>
> Martin KaFai Lau <martin.lau@kernel.org>
> bpf: Address KCSAN report on bpf_lru_list
>
> Maxime Bizon <mbizon@freebox.fr>
> wifi: ath11k: fix registration of 6Ghz-only phy without the full channel range
>
> Yicong Yang <yangyicong@hisilicon.com>
> sched/fair: Don't balance task to its current running CPU
>
> Mark Rutland <mark.rutland@arm.com>
> arm64: mm: fix VA-range sanity check
>
> Youngmin Nam <youngmin.nam@samsung.com>
> arm64: set __exception_irq_entry with __irq_entry as a default
>
> Hans de Goede <hdegoede@redhat.com>
> ACPI: video: Add backlight=native DMI quirk for Lenovo ThinkPad X131e (3371 AMD version)
>
> Hans de Goede <hdegoede@redhat.com>
> ACPI: video: Add backlight=native DMI quirk for Apple iMac11,3
>
> Hans de Goede <hdegoede@redhat.com>
> ACPI: button: Add lid disable DMI quirk for Nextbook Ares 8A
>
> David Sterba <dsterba@suse.com>
> btrfs: add xxhash to fast checksum implementations
>
> Thomas Gleixner <tglx@linutronix.de>
> posix-timers: Ensure timer ID search-loop limit is valid
>
> Yu Kuai <yukuai3@huawei.com>
> md/raid10: prevent soft lockup while flush writes
>
> Yu Kuai <yukuai3@huawei.com>
> md: fix data corruption for raid456 when reshape restart while grow up
>
> Zhong Jinghua <zhongjinghua@huawei.com>
> nbd: Add the maximum limit of allocated index in nbd_dev_add
>
> Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> debugobjects: Recheck debug_objects_enabled before reporting
>
> Eric Whitney <enwlinux@gmail.com>
> ext4: correct inline offset when handling xattrs in inode body
>
> Matus Gajdos <matuszpd@gmail.com>
> ASoC: fsl_sai: Disable bit clock with transmitter
>
> Jocelyn Falempe <jfalempe@redhat.com>
> drm/client: Fix memory leak in drm_client_modeset_probe
>
> Jocelyn Falempe <jfalempe@redhat.com>
> drm/client: Fix memory leak in drm_client_target_cloned
>
> YueHaibing <yuehaibing@huawei.com>
> can: bcm: Fix UAF in bcm_proc_show()
>
> Mark Brown <broonie@kernel.org>
> regmap: Account for register length in SMBus I/O limits
>
> Mark Brown <broonie@kernel.org>
> regmap: Drop initial version of maximum transfer length fixes
>
> Matthieu Baerts <matthieu.baerts@tessares.net>
> selftests: tc: add 'ct' action kconfig dep
>
> Matthieu Baerts <matthieu.baerts@tessares.net>
> selftests: tc: set timeout to 15 minutes
>
> Miklos Szeredi <mszeredi@redhat.com>
> fuse: revalidate: don't invalidate if interrupted
>
> Filipe Manana <fdmanana@suse.com>
> btrfs: fix warning when putting transaction with qgroups enabled after abort
>
> Georg Müller <georgmueller@gmx.net>
> perf probe: Add test for regression introduced by switch to die_get_decl_file()
>
> Petr Pavlu <petr.pavlu@suse.com>
> keys: Fix linking a duplicate key to a keyring's assoc_array
>
> Luka Guzenko <l.guzenko@web.de>
> ALSA: hda/realtek: Enable Mute LED on HP Laptop 15s-eq2xxx
>
> Kailang Yang <kailang@realtek.com>
> ALSA: hda/realtek - remove 3k pull low procedure
>
> Daniel Vetter <daniel.vetter@ffwll.ch>
> drm/atomic: Fix potential use-after-free in nonblocking commits
>
> Jason Gunthorpe <jgg@ziepe.ca>
> RDMA/cma: Ensure rdma_addr_cancel() happens before issuing more requests
>
> Pedro Tammela <pctammela@mojatatu.com>
> net/sched: sch_qfq: reintroduce lmax bound check for MTU
>
> Manish Rangankar <mrangankar@marvell.com>
> scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
>
> Shreyas Deodhar <sdeodhar@marvell.com>
> scsi: qla2xxx: Pointer may be dereferenced
>
> Bikash Hazarika <bhazarika@marvell.com>
> scsi: qla2xxx: Correct the index of array
>
> Nilesh Javali <njavali@marvell.com>
> scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
>
> Bikash Hazarika <bhazarika@marvell.com>
> scsi: qla2xxx: Fix potential NULL pointer dereference
>
> Quinn Tran <qutran@marvell.com>
> scsi: qla2xxx: Fix buffer overrun
>
> Nilesh Javali <njavali@marvell.com>
> scsi: qla2xxx: Array index may go out of bound
>
> Quinn Tran <qutran@marvell.com>
> scsi: qla2xxx: Wait for io return on terminate rport
>
> Masami Hiramatsu (Google) <mhiramat@kernel.org>
> tracing/probes: Fix not to count error code to total length
>
> Mateusz Stachyra <m.stachyra@samsung.com>
> tracing: Fix null pointer dereference in tracing_err_log_open()
>
> Max Filippov <jcmvbkbc@gmail.com>
> xtensa: ISS: fix call to split_if_spec
>
> Zheng Yejian <zhengyejian1@huawei.com>
> ring-buffer: Fix deadloop issue on reading trace_pipe
>
> Krister Johansen <kjlx@templeofstupid.com>
> net: ena: fix shift-out-of-bounds in exponential backoff
>
> Florent Revest <revest@chromium.org>
> samples: ftrace: Save required argument registers in sample trampolines
>
> Mohamed Khalfella <mkhalfella@purestorage.com>
> tracing/histograms: Add histograms to hist_vars if they have referenced variables
>
> Heiko Carstens <hca@linux.ibm.com>
> s390/decompressor: fix misaligned symbol build error
>
> Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
> Revert "8250: add support for ASIX devices with a FIFO bug"
>
> George Stark <gnstark@sberdevices.ru>
> meson saradc: fix clock divider mask length
>
> Weitao Wang <WeitaoWang-oc@zhaoxin.com>
> xhci: Show ZHAOXIN xHCI root hub speed correctly
>
> Weitao Wang <WeitaoWang-oc@zhaoxin.com>
> xhci: Fix TRB prefetch issue of ZHAOXIN hosts
>
> Weitao Wang <WeitaoWang-oc@zhaoxin.com>
> xhci: Fix resume issue of some ZHAOXIN hosts
>
> Xiubo Li <xiubli@redhat.com>
> ceph: don't let check_caps skip sending responses for revoke msgs
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
>
> Dan Carpenter <dan.carpenter@linaro.org>
> serial: atmel: don't enable IRQs prematurely
>
> Mario Limonciello <mario.limonciello@amd.com>
> drm/amd/display: Correct `DMUB_FW_VERSION` macro
>
> Brian Norris <briannorris@chromium.org>
> drm/rockchip: vop: Leave vblank enabled in self-refresh
>
> Brian Norris <briannorris@chromium.org>
> drm/atomic: Allow vblank-enabled + self-refresh "disable"
>
> Alexander Aring <aahringo@redhat.com>
> fs: dlm: return positive pid value for F_GETLK
>
> Jason Baron <jbaron@akamai.com>
> md/raid0: add discard support for the 'original' layout
>
> Damien Le Moal <dlemoal@kernel.org>
> misc: pci_endpoint_test: Re-init completion for every test
>
> Damien Le Moal <dlemoal@kernel.org>
> misc: pci_endpoint_test: Free IRQs before removing the device
>
> Damien Le Moal <dlemoal@kernel.org>
> PCI: rockchip: Set address alignment for endpoint mode
>
> Rick Wertenbroek <rick.wertenbroek@gmail.com>
> PCI: rockchip: Use u32 variable to access 32-bit registers
>
> Rick Wertenbroek <rick.wertenbroek@gmail.com>
> PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
>
> Rick Wertenbroek <rick.wertenbroek@gmail.com>
> PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
>
> Rick Wertenbroek <rick.wertenbroek@gmail.com>
> PCI: rockchip: Write PCI Device ID to correct register
>
> Rick Wertenbroek <rick.wertenbroek@gmail.com>
> PCI: rockchip: Assert PCI Configuration Enable bit after probe
>
> Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> PCI: qcom: Disable write access to read only registers for IP v2.3.3
>
> Robin Murphy <robin.murphy@arm.com>
> PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
>
> Ondrej Zary <linux@zary.sk>
> PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
>
> Martin Kaiser <martin@kaiser.cx>
> hwrng: imx-rngc - fix the timeout for init and self check
>
> Siddh Raman Pant <code@siddh.me>
> jfs: jfs_dmap: Validate db_l2nbperpage while mounting
>
> Baokun Li <libaokun1@huawei.com>
> ext4: only update i_reserved_data_blocks on successful block allocation
>
> Chao Yu <chao@kernel.org>
> ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
>
> Kemeng Shi <shikemeng@huaweicloud.com>
> ext4: fix wrong unit use in ext4_mb_new_blocks
>
> Kemeng Shi <shikemeng@huaweicloud.com>
> ext4: get block from bh in ext4_free_blocks for fast commit replay
>
> Kemeng Shi <shikemeng@huaweicloud.com>
> ext4: fix wrong unit use in ext4_mb_clear_bb
>
> Zhihao Cheng <chengzhihao1@huawei.com>
> ext4: Fix reusing stale buffer heads from last failed mounting
>
> Huacai Chen <chenhuacai@loongson.cn>
> MIPS: Loongson: Fix cpu_probe_loongson() again
>
> Gao Xiang <hsiangkao@linux.alibaba.com>
> erofs: fix compact 4B support for 16k block size
>
> Ekansh Gupta <quic_ekangupt@quicinc.com>
> misc: fastrpc: Create fastrpc scalar with correct buffer count
>
> Naveen N Rao <naveen@kernel.org>
> powerpc: Fail build if using recordmcount with binutils v2.37
>
> Florian Fainelli <florian.fainelli@broadcom.com>
> net: bcmgenet: Ensure MDIO unregistration has clocks enabled
>
> Arseniy Krasnov <AVKrasnov@sberdevices.ru>
> mtd: rawnand: meson: fix unaligned DMA buffers handling
>
> Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
> tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
>
> Mario Limonciello <mario.limonciello@amd.com>
> pinctrl: amd: Only use special debounce behavior for GPIO 0
>
> Mario Limonciello <mario.limonciello@amd.com>
> pinctrl: amd: Detect internal GPIO0 debounce handling
>
> Mario Limonciello <mario.limonciello@amd.com>
> pinctrl: amd: Fix mistake in handling clearing pins at startup
>
> Chao Yu <chao@kernel.org>
> f2fs: fix to avoid NULL pointer dereference f2fs_write_end_io()
>
> Ming Lei <ming.lei@redhat.com>
> nvme-pci: fix DMA direction of unmapping integrity data
>
> Pedro Tammela <pctammela@mojatatu.com>
> net/sched: sch_qfq: account for stab overhead in qfq_enqueue
>
> Pedro Tammela <pctammela@mojatatu.com>
> net/sched: sch_qfq: refactor parsing of netlink parameters
>
> Pedro Tammela <pctammela@mojatatu.com>
> net/sched: make psched_mtu() RTNL-less safe
>
> Dan Carpenter <dan.carpenter@linaro.org>
> netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
>
> Ido Schimmel <idosch@nvidia.com>
> net/sched: flower: Ensure both minimum and maximum ports are specified
>
> Randy Dunlap <rdunlap@infradead.org>
> wifi: airo: avoid uninitialized warning in airo_get_rate()
>
> Chunhai Guo <guochunhai@vivo.com>
> erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
>
> Björn Töpel <bjorn@rivosinc.com>
> riscv, bpf: Fix inconsistent JIT image generation
>
> Pu Lehui <pulehui@huawei.com>
> bpf, riscv: Support riscv jit to provide bpf_line_info
>
> Jisheng Zhang <jszhang@kernel.org>
> riscv: bpf: Avoid breaking W^X
>
> Jisheng Zhang <jszhang@kernel.org>
> riscv: bpf: Move bpf_jit_alloc_exec() and bpf_jit_free_exec() to core
>
> Florian Kauer <florian.kauer@linutronix.de>
> igc: Fix inserting of empty frame for launchtime
>
> Florian Kauer <florian.kauer@linutronix.de>
> igc: Fix launchtime before start of cycle
>
> Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> platform/x86: wmi: Break possible infinite loop when parsing GUID
>
> Barnabás Pőcze <pobrn@protonmail.com>
> platform/x86: wmi: move variables
>
> Barnabás Pőcze <pobrn@protonmail.com>
> platform/x86: wmi: use guid_t and guid_equal()
>
> Barnabás Pőcze <pobrn@protonmail.com>
> platform/x86: wmi: remove unnecessary argument
>
> Ziyang Xuan <william.xuanziyang@huawei.com>
> ipv6/addrconf: fix a potential refcount underflow for idev
>
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
> NTB: ntb_tool: Add check for devm_kcalloc
>
> Yang Yingliang <yangyingliang@huawei.com>
> NTB: ntb_transport: fix possible memory leak while device_register() fails
>
> Yuan Can <yuancan@huawei.com>
> ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
>
> Yuan Can <yuancan@huawei.com>
> NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
>
> Yuan Can <yuancan@huawei.com>
> ntb: idt: Fix error handling in idt_pci_driver_init()
>
> Eric Dumazet <edumazet@google.com>
> udp6: fix udp6_ehashfn() typo
>
> Kuniyuki Iwashima <kuniyu@amazon.com>
> icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
>
> Paolo Abeni <pabeni@redhat.com>
> net: prevent skb corruption on frag list segmentation
>
> Rafał Miłecki <rafal@milecki.pl>
> net: bgmac: postpone turning IRQs off to avoid SoC hangs
>
> Nitya Sunkad <nitya.sunkad@amd.com>
> ionic: remove WARN_ON to prevent panic_on_warn
>
> Junfeng Guo <junfeng.guo@intel.com>
> gve: Set default duplex configuration to full
>
> M A Ramdhan <ramdhan@starlabs.sg>
> net/sched: cls_fw: Fix improper refcount update leads to use-after-free
>
> Klaus Kudielka <klaus.kudielka@gmail.com>
> net: mvneta: fix txq_map in case of txq_number==1
>
> Dan Carpenter <dan.carpenter@linaro.org>
> scsi: qla2xxx: Fix error code in qla2x00_start_sp()
>
> Prasad Koya <prasad@arista.com>
> igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
>
> Vlad Buslov <vladbu@nvidia.com>
> net/mlx5e: Check for NOT_READY flag state after locking
>
> Zhengchao Shao <shaozhengchao@huawei.com>
> net/mlx5e: fix double free in mlx5e_destroy_flow_table
>
> Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
> igc: Remove delay during TX ring configuration
>
> Marek Vasut <marex@denx.de>
> drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
>
> Fabio Estevam <festevam@denx.de>
> drm/panel: simple: Add connector_type for innolux_at043tn24
>
> Linus Torvalds <torvalds@linux-foundation.org>
> workqueue: clean up WORK_* constant types, clarify masking
>
> Moritz Fischer <moritzf@google.com>
> net: lan743x: Don't sleep in atomic context
>
> Jens Axboe <axboe@kernel.dk>
> io_uring: add reschedule point to handle_tw_list()
>
> Andres Freund <andres@anarazel.de>
> io_uring: Use io_schedule* in cqring wait
>
> Michael Schmitz <schmitzmic@gmail.com>
> block/partition: fix signedness issue for Amiga partitions
>
> Paul E. McKenney <paulmck@kernel.org>
> rcu-tasks: Simplify trc_read_check_handler() atomic operations
>
> Paul E. McKenney <paulmck@kernel.org>
> rcu-tasks: Mark ->trc_reader_special.b.need_qs data races
>
> Paul E. McKenney <paulmck@kernel.org>
> rcu-tasks: Mark ->trc_reader_nesting data races
>
> Sherry Sun <sherry.sun@nxp.com>
> tty: serial: fsl_lpuart: add earlycon for imx8ulp platform
>
> Jason A. Donenfeld <Jason@zx2c4.com>
> wireguard: netlink: send staged packets when setting initial private key
>
> Jason A. Donenfeld <Jason@zx2c4.com>
> wireguard: queueing: use saner cpu selection wrapping
>
> Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
> netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
>
> Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
> netfilter: nf_tables: do not ignore genmask when looking up chain by id
>
> Florent Revest <revest@chromium.org>
> netfilter: conntrack: Avoid nf_ct_helper_hash uses after free
>
> Florian Westphal <fw@strlen.de>
> netfilter: nf_tables: fix scheduling-while-atomic splat
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nf_tables: unbind non-anonymous set if rule construction fails
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nf_tables: drop map element references from preparation phase
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nftables: rename set element data activation/deactivation functions
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nf_tables: reject unbound chain set before commit phase
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nf_tables: reject unbound anonymous set before commit phase
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nf_tables: add NFT_TRANS_PREPARE_ERROR to deal with bound set/chain
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nf_tables: fix chain binding transaction logic
>
> Pablo Neira Ayuso <pablo@netfilter.org>
> netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE
>
> Florian Westphal <fw@strlen.de>
> netfilter: nf_tables: add rescheduling points during loop detection walks
>
> Florian Westphal <fw@strlen.de>
> netfilter: nf_tables: use net_generic infra for transaction data
>
> Geert Uytterhoeven <geert+renesas@glider.be>
> sh: pgtable-3level: Fix cast to pointer from integer of different size
>
> Michael Schmitz <schmitzmic@gmail.com>
> block: add overflow checks for Amiga partition support
>
> Gilad Reti <gilad.reti@gmail.com>
> selftests/bpf: Add verifier test for PTR_TO_MEM spill
>
> Lino Sanfilippo <l.sanfilippo@kunbus.com>
> tpm, tpm_tis: Claim locality in interrupt handler
>
> Amir Goldstein <amir73il@gmail.com>
> fanotify: disallow mount/sb marks on kernel internal pseudo fs
>
> Jan Kara <jack@suse.cz>
> fs: no need to check source
>
> Christian Marangi <ansuelsmth@gmail.com>
> leds: trigger: netdev: Recheck NETDEV_LED_MODE_LINKUP on dev rename
>
> Arnd Bergmann <arnd@arndb.de>
> ARM: orion5x: fix d2net gpio initialization
>
> Ricardo Ribalda Delgado <ribalda@chromium.org>
> ASoC: mediatek: mt8173: Fix snd_soc_component_initialize error path
>
> Ricardo Ribalda Delgado <ribalda@chromium.org>
> ASoC: mediatek: mt8173: Fix irq error path
>
> Filipe Manana <fdmanana@suse.com>
> btrfs: fix race when deleting quota root from the dirty cow roots list
>
> Matt Corallo <blnxfsl@bluematt.me>
> btrfs: add handling for RAID1C23/DUP to btrfs_reduce_alloc_profile
>
> Jan Kara <jack@suse.cz>
> fs: Lock moved directories
>
> Jan Kara <jack@suse.cz>
> fs: Establish locking order for unrelated directories
>
> Jan Kara <jack@suse.cz>
> Revert "f2fs: fix potential corruption when moving a directory"
>
> Jan Kara <jack@suse.cz>
> ext4: Remove ext4 locking of moved directory
>
> Thomas Weißschuh <linux@weissschuh.net>
> fs: avoid empty option when generating legacy mount string
>
> Fabian Frederick <fabf@skynet.be>
> jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
>
> Roberto Sassu <roberto.sassu@huawei.com>
> shmem: use ramfs_kill_sb() for kill_sb method of ramfs-based tmpfs
>
> Arnd Bergmann <arnd@arndb.de>
> autofs: use flexible array in ioctl structure
>
> Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
> integrity: Fix possible multiple allocation in integrity_inode_get()
>
> Kees Cook <keescook@chromium.org>
> um: Use HOST_DIR for mrproper
>
> Zheng Wang <zyytlz.wz@163.com>
> bcache: Fix __bch_btree_node_alloc to make the failure behavior consistent
>
> Zheng Wang <zyytlz.wz@163.com>
> bcache: Remove unnecessary NULL point check in node allocations
>
> Mingzhe Zou <mingzhe.zou@easystack.cn>
> bcache: fixup btree_cache_wait list damage
>
> Chevron Li <chevron.li@bayhubtech.com>
> mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is used.
>
> Ulf Hansson <ulf.hansson@linaro.org>
> mmc: mmci: Set PROBE_PREFER_ASYNCHRONOUS
>
> Robert Marko <robimarko@gmail.com>
> mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
>
> Robert Marko <robimarko@gmail.com>
> mmc: core: disable TRIM on Kingston EMMC04G-M627
>
> Jens Axboe <axboe@kernel.dk>
> io_uring: wait interruptibly for request completions on exit
>
> Dai Ngo <dai.ngo@oracle.com>
> NFSD: add encoding of op_recall flag for write delegation
>
> Shuai Jiang <d202180596@hust.edu.cn>
> i2c: qup: Add missing unwind goto in qup_i2c_probe()
>
> Takashi Iwai <tiwai@suse.de>
> ALSA: jack: Fix mutex call in snd_jack_report()
>
> Robert Hancock <robert.hancock@calian.com>
> i2c: xiic: Don't try to handle more interrupt events after error
>
> Marek Vasut <marex@denx.de>
> i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()
>
> Danila Chernetsov <listdansp@mail.ru>
> apparmor: fix missing error check for rhashtable_insert_fast
>
> Artur Rojek <contact@artur-rojek.eu>
> sh: dma: Fix DMA channel offset calculation
>
> Thorsten Winkler <twinkler@linux.ibm.com>
> s390/qeth: Fix vipa deletion
>
> Vladimir Oltean <vladimir.oltean@nxp.com>
> net: dsa: tag_sja1105: fix MAC DA patching from meta frames
>
> Guillaume Nault <gnault@redhat.com>
> pptp: Fix fib lookup calls.
>
> Lin Ma <linma@zju.edu.cn>
> net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
>
> Ilya Maximets <i.maximets@ovn.org>
> xsk: Honor SO_BINDTODEVICE on bind
>
> Eric Dumazet <edumazet@google.com>
> tcp: annotate data races in __tcp_oow_rate_limited()
>
> Vladimir Oltean <vladimir.oltean@nxp.com>
> net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode
>
> Randy Dunlap <rdunlap@infradead.org>
> powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y
>
> Hariprasad Kelam <hkelam@marvell.com>
> octeontx2-af: Fix mapping for NIX block from CGX connection
>
> Chao Yu <chao@kernel.org>
> f2fs: fix error path handling in truncate_dnode()
>
> Nishanth Menon <nm@ti.com>
> mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0
>
> Jonas Gorski <jonas.gorski@gmail.com>
> spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
>
> Pawel Dembicki <paweldembicki@gmail.com>
> net: dsa: vsc73xx: fix MTU configuration
>
> Tobias Heider <me@tobhe.de>
> Add MODULE_FIRMWARE() for FIRMWARE_TG357766.
>
> Chengfeng Ye <dg573847474@gmail.com>
> sctp: fix potential deadlock on &net->sctp.addr_wq_lock
>
> Randy Dunlap <rdunlap@infradead.org>
> media: cec: i2c: ch7322: also select REGMAP
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
>
> Marek Vasut <marex@denx.de>
> pwm: sysfs: Do not apply state to already disabled PWMs
>
> Fancy Fang <chen.fang@nxp.com>
> pwm: imx-tpm: force 'real_period' to be zero in suspend
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> phy: tegra: xusb: check return value of devm_kzalloc()
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> mfd: stmpe: Only disable the regulators if they are enabled
>
> Pierre Morel <pmorel@linux.ibm.com>
> KVM: s390: vsie: fix the length of APCB bitmap
>
> Amelie Delaunay <amelie.delaunay@foss.st.com>
> mfd: stmfx: Nullify stmfx->vdd in case of error
>
> Amelie Delaunay <amelie.delaunay@foss.st.com>
> mfd: stmfx: Fix error path in stmfx_chip_init
>
> Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
> test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation
>
> Tony Lindgren <tony@atomide.com>
> serial: 8250_omap: Use force_suspend and resume for system suspend
>
> Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Revert "usb: common: usb-conn-gpio: Set last role to unknown before initial detection"
>
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
> mfd: intel-lpss: Add missing check for platform_get_resource
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> usb: dwc3-meson-g12a: Fix an error handling path in dwc3_meson_g12a_probe()
>
> Prashanth K <quic_prashk@quicinc.com>
> usb: common: usb-conn-gpio: Set last role to unknown before initial detection
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> usb: dwc3: qcom: Fix an error handling path in dwc3_qcom_probe()
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> usb: dwc3: qcom: Release the correct resources in dwc3_qcom_remove()
>
> Nico Boehr <nrb@linux.ibm.com>
> KVM: s390: fix KVM_S390_GET_CMMA_BITS for GFNs in memslot holes
>
> Dan Carpenter <dan.carpenter@linaro.org>
> media: atomisp: gmin_platform: fix out_len in gmin_get_config_dsm_var()
>
> Rikard Falkeborn <rikard.falkeborn@gmail.com>
> media: venus: helpers: Fix ALIGN() of non power of two
>
> Stephan Gerhold <stephan@gerhold.net>
> mfd: rt5033: Drop rt5033-battery sub-device
>
> James Clark <james.clark@arm.com>
> coresight: Fix loss of connection info when a module is unloaded
>
> Muchun Song <songmuchun@bytedance.com>
> kernfs: fix missing kernfs_idr_lock to remove an ID from the IDR
>
> John Ogness <john.ogness@linutronix.de>
> serial: 8250: lock port for UART_IER access in omap8250_irq()
>
> John Ogness <john.ogness@linutronix.de>
> serial: 8250: lock port for stop_rx() in omap8250_irq()
>
> Arnd Bergmann <arnd@arndb.de>
> usb: hide unused usbfs_notify_suspend/resume functions
>
> Li Yang <lidaxian@hust.edu.cn>
> usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
>
> Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> extcon: Fix kernel doc of property capability fields to avoid warnings
>
> Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> extcon: Fix kernel doc of property fields to avoid warnings
>
> Prashanth K <quic_prashk@quicinc.com>
> usb: gadget: u_serial: Add null pointer check in gserial_suspend
>
> Vladislav Efanov <VEfanov@ispras.ru>
> usb: dwc3: qcom: Fix potential memory leak
>
> Robert Marko <robimarko@gmail.com>
> clk: qcom: ipq6018: fix networking resets
>
> Robert Marko <robimarko@gmail.com>
> clk: qcom: reset: support resetting multiple bits
>
> Stephan Gerhold <stephan.gerhold@kernkonzept.com>
> clk: qcom: reset: Allow specifying custom reset delay
>
> Duoming Zhou <duoming@zju.edu.cn>
> media: usb: siano: Fix warning due to null work_func_t function pointer
>
> Marek Vasut <marex@denx.de>
> media: videodev2.h: Fix struct v4l2_input tuner index comment
>
> Daniil Dulov <d.dulov@aladdin.ru>
> media: usb: Check az6007_read() return value
>
> Mantas Pucka <mantas@8devices.com>
> clk: qcom: gcc-ipq6018: Use floor ops for sdcc clocks
>
> Tony Lindgren <tony@atomide.com>
> serial: 8250: omap: Fix freeing of resources on failed register
>
> John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
> sh: j2: Use ioremap() to translate device tree address into kernel memory
>
> Dan Carpenter <dan.carpenter@oracle.com>
> w1: fix loop in w1_fini()
>
> Stefan Wahren <stefan.wahren@i2se.com>
> w1: w1_therm: fix locking behavior in convert_t
>
> Ding Hui <dinghui@sangfor.com.cn>
> SUNRPC: Fix UAF in svc_tcp_listen_data_ready()
>
> Michael Schmitz <schmitzmic@gmail.com>
> block: change all __u32 annotations to __be32 in affs_hardblocks.h
>
> Michael Schmitz <schmitzmic@gmail.com>
> block: fix signed int overflow in Amiga partition support
>
> EJ Hsu <ejh@nvidia.com>
> phy: tegra: xusb: Clear the driver reference in usb-phy dev
>
> Krishna Kurapati <quic_kriskura@quicinc.com>
> usb: dwc3: gadget: Propagate core init errors to UDC during pullup
>
> Davide Tronchin <davide.tronchin.94@gmail.com>
> USB: serial: option: add LARA-R6 01B PIDs
>
> Jens Axboe <axboe@kernel.dk>
> io_uring: ensure IOPOLL locks around deferred work
>
> Martin Kaiser <martin@kaiser.cx>
> hwrng: st - keep clock enabled while hwrng is registered
>
> Dan Williams <dan.j.williams@intel.com>
> dax: Introduce alloc_dev_dax_id()
>
> Dan Williams <dan.j.williams@intel.com>
> dax: Fix dax_mapping_release() use after free
>
> Olga Kornievskaia <kolga@netapp.com>
> NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
>
> Masahiro Yamada <masahiroy@kernel.org>
> ARC: define ASM_NL and __ALIGN(_STR) outside #ifdef __ASSEMBLY__ guard
>
> Dan Carpenter <dan.carpenter@linaro.org>
> modpost: fix off by one in is_executable_section()
>
> Arnd Bergmann <arnd@arndb.de>
> crypto: marvell/cesa - Fix type mismatch warning
>
> Masahiro Yamada <masahiroy@kernel.org>
> modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24}
>
> Masahiro Yamada <masahiroy@kernel.org>
> modpost: fix section mismatch message for R_ARM_ABS32
>
> Randy Dunlap <rdunlap@infradead.org>
> crypto: nx - fix build warnings when DEBUG_FS is not enabled
>
> Herbert Xu <herbert@gondor.apana.org.au>
> hwrng: virtio - Fix race on data_avail and actual data
>
> Laurent Vivier <lvivier@redhat.com>
> hwrng: virtio - always add a pending request
>
> Laurent Vivier <lvivier@redhat.com>
> hwrng: virtio - don't waste entropy
>
> Laurent Vivier <lvivier@redhat.com>
> hwrng: virtio - don't wait on cleanup
>
> Laurent Vivier <lvivier@redhat.com>
> hwrng: virtio - add an internal buffer
>
> Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> powerpc/mm/dax: Fix the condition when checking if altmap vmemap can cross-boundary
>
> Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> powerpc/book3s64/mm: Fix DirectMap stats in /proc/meminfo
>
> Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> mm: rename p4d_page_vaddr to p4d_pgtable and make it return pud_t *
>
> Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> mm: rename pud_page_vaddr to pud_pgtable and make it return pmd_t *
>
> Colin Ian King <colin.i.king@gmail.com>
> powerpc/powernv/sriov: perform null check on iov before dereferencing iov
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> pinctrl: at91-pio4: check return value of devm_kasprintf()
>
> Namhyung Kim <namhyung@kernel.org>
> perf dwarf-aux: Fix off-by-one in die_get_varname()
>
> Arnaldo Carvalho de Melo <acme@redhat.com>
> perf script: Fix allocation of evsel->priv related to per-event dump files
>
> Arnaldo Carvalho de Melo <acme@redhat.com>
> perf script: Fixup 'struct evsel_script' method prefix
>
> Christophe Leroy <christophe.leroy@csgroup.eu>
> kcsan: Don't expect 64 bits atomic builtins from 32 bits architectures
>
> Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> pinctrl: cherryview: Return correct value if pin in push-pull mode
>
> Arnaldo Carvalho de Melo <acme@redhat.com>
> perf bench: Add missing setlocale() call to allow usage of %'d style formatting
>
> Sohaib Mohamed <sohaib.amhmd@gmail.com>
> perf bench: Use unbuffered output when pipe/tee'ing to a file
>
> Sui Jingfeng <suijingfeng@loongson.cn>
> PCI: Add pci_clear_master() stub for non-CONFIG_PCI
>
> Junyan Ye <yejunyan@hust.edu.cn>
> PCI: ftpci100: Release the clock resources
>
> Rongguang Wei <weirongguang@kylinos.cn>
> PCI: pciehp: Cancel bringup sequence if card is not present
>
> Yuchen Yang <u202114568@hust.edu.cn>
> scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
>
> Ding Hui <dinghui@sangfor.com.cn>
> PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> pinctrl: bcm2835: Handle gpiochip_add_pin_range() errors
>
> Jinhong Zhu <jinhongzhu@hust.edu.cn>
> scsi: qedf: Fix NULL dereference in error handling
>
> Siddharth Vadapalli <s-vadapalli@ti.com>
> PCI: cadence: Fix Gen2 Link Retraining process
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> ASoC: imx-audmix: check return value of devm_kasprintf()
>
> Amir Goldstein <amir73il@gmail.com>
> ovl: update of dentry revalidate flags after copy up
>
> Alexey Romanov <avromanov@sberdevices.ru>
> drivers: meson: secure-pwrc: always enable DMA domain
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> clk: ti: clkctrl: check return value of kasprintf()
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> clk: keystone: sci-clk: check return value of kasprintf()
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> clk: si5341: free unused memory on probe failure
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> clk: si5341: check return value of {devm_}kasprintf()
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> clk: si5341: return error if one synth clock registration fails
>
> Robert Hancock <robert.hancock@calian.com>
> clk: si5341: Add sysfs properties to allow checking/resetting device faults
>
> Robert Hancock <robert.hancock@calian.com>
> clk: si5341: Allow different output VDD_SEL values
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> clk: cdce925: check return value of kasprintf()
>
> Claudiu Beznea <claudiu.beznea@microchip.com>
> clk: vc5: check memory returned by kasprintf()
>
> Bjorn Andersson <quic_bjorande@quicinc.com>
> drm/msm/dp: Free resources after unregistering them
>
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> drm/msm/dpu: do not enable color-management if DSPPs are not available
>
> Su Hui <suhui@nfschina.com>
> ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer
>
> Yuan Can <yuancan@huawei.com>
> clk: tegra: tegra124-emc: Fix potential memory leak
>
> Yuxing Liu <lyx2022@hust.edu.cn>
> clk: imx: clk-imx8mp: improve error handling in imx8mp_clocks_probe()
>
> Hao Luo <m202171776@hust.edu.cn>
> clk: imx: clk-imx8mn: fix memory leak in imx8mn_clocks_probe
>
> Kashyap Desai <kashyap.desai@broadcom.com>
> RDMA/bnxt_re: Avoid calling wake_up threads from spin_lock context
>
> Kashyap Desai <kashyap.desai@broadcom.com>
> RDMA/bnxt_re: wraparound mbox producer index
>
> Chia-I Wu <olvaffe@gmail.com>
> amdgpu: validate offset_in_bo of drm_amdgpu_gem_va
>
> Nikita Zhandarovich <n.zhandarovich@fintech.ru>
> drm/radeon: fix possible division-by-zero errors
>
> Daniil Dulov <d.dulov@aladdin.ru>
> drm/amdkfd: Fix potential deallocation of previously deallocated memory.
>
> Christian Lamparter <chunkeey@gmail.com>
> ARM: dts: BCM5301X: fix duplex-full => full-duplex
>
> Guenter Roeck <linux@roeck-us.net>
> hwmon: (pmbus/adm1275) Fix problems with temperature monitoring on ADM1272
>
> Potin Lai <potin.lai@quantatw.com>
> hwmon: (adm1275) Allow setting sample averaging
>
> Chu Lin <linchuyuan@google.com>
> hwmon: (adm1275) enable adm1272 temperature reporting
>
> Tim Harvey <tharvey@gateworks.com>
> hwmon: (gsc-hwmon) fix fan pwm temperature scaling
>
> Olivier Moysan <olivier.moysan@foss.st.com>
> ARM: dts: stm32: fix i2s endpoint format property for stm32mp15xx-dkx
>
> Marek Vasut <marex@denx.de>
> ARM: dts: stm32: Fix audio routing on STM32MP15xx DHCOM PDK2
>
> Keerthy <j-keerthy@ti.com>
> arm64: dts: ti: k3-j7200: Fix physical address of pin
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe()
>
> Wolfram Sang <wsa+renesas@sang-engineering.com>
> arm64: dts: renesas: ulcb-kf: Remove flow control for SCIF1
>
> Geert Uytterhoeven <geert+renesas@glider.be>
> ARM: dts: iwg20d-q7-common: Fix backlight pwm specifier
>
> Chengchang Tang <tangchengchang@huawei.com>
> RDMA/hns: Fix hns_roce_table_get return value
>
> Xi Wang <wangxi11@huawei.com>
> RDMA/hns: Clean the hardware related code for HEM
>
> Weihang Li <liweihang@huawei.com>
> RDMA/hns: Use refcount_t APIs for HEM
>
> Lang Cheng <chenglang@huawei.com>
> RDMA/hns: Fix coding style issues
>
> Jason Gunthorpe <jgg@ziepe.ca>
> RDMA: Remove uverbs_ex_cmd_mask values that are linked to functions
>
> Brendan Cunningham <bcunningham@cornelisnetworks.com>
> IB/hfi1: Fix wrong mmu_node used for user SDMA packet after invalidate
>
> Patrick Kelsey <pat.kelsey@cornelisnetworks.com>
> IB/hfi1: Fix sdma.h tx->num_descs off-by-one errors
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> IB/hfi1: Use bitmap_zalloc() when applicable
>
> Randy Dunlap <rdunlap@infradead.org>
> soc/fsl/qe: fix usb.c build errors
>
> Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> ARM: dts: meson8: correct uart_B and uart_C clock references
>
> Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
> ASoC: es8316: Do not set rate constraints for unsupported MCLKs
>
> Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
> ASoC: es8316: Increment max value for ALC Capture Target Volume control
>
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> memory: brcmstb_dpfe: fix testing array offset after use
>
> Marek Vasut <marex@denx.de>
> ARM: dts: stm32: Shorten the AV96 HDMI sound card name
>
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> arm64: dts: qcom: apq8096: fix fixed regulator name property
>
> Arnd Bergmann <arnd@arndb.de>
> ARM: omap2: fix missing tick_broadcast() prototype
>
> Arnd Bergmann <arnd@arndb.de>
> ARM: ep93xx: fix missing-prototype warnings
>
> Dario Binacchi <dario.binacchi@amarulasolutions.com>
> drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H
>
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> arm64: dts: qcom: msm8996: correct camss unit address
>
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> arm64: dts: qcom: msm8994: correct SPMI unit address
>
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> arm64: dts: qcom: msm8916: correct camss unit address
>
> Tony Lindgren <tony@atomide.com>
> ARM: dts: gta04: Move model property out of pinctrl node
>
> Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> RDMA/bnxt_re: Fix to remove an unnecessary log
>
> Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> RDMA/bnxt_re: Remove a redundant check inside bnxt_re_update_gid
>
> Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> RDMA/bnxt_re: Use unique names while registering interrupts
>
> Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> RDMA/bnxt_re: Fix to remove unnecessary return labels
>
> Selvin Xavier <selvin.xavier@broadcom.com>
> RDMA/bnxt_re: Disable/kill tasklet only if it is enabled
>
> Robert Marko <robert.marko@sartura.hr>
> arm64: dts: microchip: sparx5: do not use PSCI on reference boards
>
> Tony Lindgren <tony@atomide.com>
> bus: ti-sysc: Fix dispc quirk masking bool variables
>
> Marek Vasut <marex@denx.de>
> ARM: dts: stm32: Move ethernet MAC EEPROM from SoM to carrier boards
>
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> drm/panel: sharp-ls043t1le01: adjust mode settings
>
> XuDong Liu <m202071377@hust.edu.cn>
> drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
>
> Marek Vasut <marex@denx.de>
> Input: adxl34x - do not hardcode interrupt trigger type
>
> hfdevel@gmx.net <hfdevel@gmx.net>
> ARM: dts: meson8b: correct uart_B and uart_C clock references
>
> Rafał Miłecki <rafal@milecki.pl>
> ARM: dts: BCM5301X: Drop "clock-names" from the SPI node
>
> Luc Ma <luc@sietium.com>
> drm/vram-helper: fix function names in vram helper doc
>
> Francesco Dolcini <francesco.dolcini@toradex.com>
> drm/bridge: tc358768: fix THS_TRAILCNT computation
>
> Francesco Dolcini <francesco.dolcini@toradex.com>
> drm/bridge: tc358768: fix TXTAGOCNT computation
>
> Francesco Dolcini <francesco.dolcini@toradex.com>
> drm/bridge: tc358768: fix THS_ZEROCNT computation
>
> Francesco Dolcini <francesco.dolcini@toradex.com>
> drm/bridge: tc358768: fix TCLK_TRAILCNT computation
>
> Francesco Dolcini <francesco.dolcini@toradex.com>
> drm/bridge: tc358768: Add atomic_get_input_bus_fmts() implementation
>
> Francesco Dolcini <francesco.dolcini@toradex.com>
> drm/bridge: tc358768: fix TCLK_ZEROCNT computation
>
> Francesco Dolcini <francesco.dolcini@toradex.com>
> drm/bridge: tc358768: fix PLL target frequency
>
> Francesco Dolcini <francesco.dolcini@toradex.com>
> drm/bridge: tc358768: fix PLL parameters computation
>
> Francesco Dolcini <francesco.dolcini@toradex.com>
> drm/bridge: tc358768: always enable HS video mode
>
> Luca Weiss <luca@z3ntu.xyz>
> Input: drv260x - sleep between polling GO bit
>
> Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
> drm/amd/display: Explicitly specify update type per plane info change
>
> Nikita Zhandarovich <n.zhandarovich@fintech.ru>
> radeon: avoid double free in ci_dpm_init()
>
> Kuniyuki Iwashima <kuniyu@amazon.com>
> netlink: Add __sock_i_ino() for __netlink_diag_dump().
>
> Cambda Zhu <cambda@linux.alibaba.com>
> ipvlan: Fix return value of ipvlan_queue_xmit()
>
> Ilia.Gavrilov <Ilia.Gavrilov@infotecs.ru>
> netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return value.
>
> Florian Westphal <fw@strlen.de>
> netfilter: conntrack: dccp: copy entire header to stack buffer, not just basic one
>
> Jeremy Sowden <jeremy@azazel.net>
> lib/ts_bm: reset initial match offset for every block of text
>
> Lin Ma <linma@zju.edu.cn>
> net: nfc: Fix use-after-free caused by nfc_llcp_find_local
>
> Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
> nfc: llcp: simplify llcp_sock_connect() error paths
>
> Edward Cree <ecree.xilinx@gmail.com>
> sfc: fix crash when reading stats while NIC is resetting
>
> Maxim Kochetkov <fido_max@inbox.ru>
> net: axienet: Move reset before 64-bit DMA detection
>
> Kuniyuki Iwashima <kuniyu@amazon.com>
> gtp: Fix use-after-free in __gtp_encap_destroy().
>
> Sabrina Dubroca <sd@queasysnail.net>
> selftests: rtnetlink: remove netdevsim device after ipsec offload test
>
> Eric Dumazet <edumazet@google.com>
> netlink: do not hard code device address lenth in fdb dumps
>
> Eric Dumazet <edumazet@google.com>
> netlink: fix potential deadlock in netlink_set_err()
>
> Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> net: stmmac: fix double serdes powerdown
>
> Vinicius Costa Gomes <vinicius.gomes@intel.com>
> igc: Fix race condition in PTP tx code
>
> Dmitry Antipov <dmantipov@yandex.ru>
> wifi: ath9k: convert msecs to jiffies where needed
>
> Benjamin Berg <benjamin.berg@intel.com>
> wifi: cfg80211: rewrite merging of inherited elements
>
> Johannes Berg <johannes.berg@intel.com>
> wifi: iwlwifi: pull from TXQs with softirqs disabled
>
> Edwin Peer <edwin.peer@broadcom.com>
> rtnetlink: extend RTEXT_FILTER_SKIP_STATS to IFLA_VF_INFO
>
> Remi Pommarel <repk@triplefau.lt>
> wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
>
> Arnd Bergmann <arnd@arndb.de>
> memstick r592: make memstick_debug_get_tpc_name() static
>
> Zhen Lei <thunder.leizhen@huawei.com>
> kexec: fix a memory leak in crash_shrink_memory()
>
> Douglas Anderson <dianders@chromium.org>
> watchdog/perf: more properly prevent false positives with turbo modes
>
> Douglas Anderson <dianders@chromium.org>
> watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct config
>
> Marek Vasut <marex@denx.de>
> wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown
>
> Marek Vasut <marex@denx.de>
> wifi: rsi: Do not configure WoWlan in shutdown hook if not enabled
>
> Fedor Pchelkin <pchelkin@ispras.ru>
> wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> wifi: ray_cs: Fix an error handling path in ray_probe()
>
> Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> wifi: ray_cs: Drop useless status variable in parse_addr()
>
> Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> wifi: ray_cs: Utilize strnlen() in parse_addr()
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> wifi: wl3501_cs: Fix an error handling path in wl3501_probe()
>
> Jakub Kicinski <kuba@kernel.org>
> wl3501_cs: use eth_hw_addr_set()
>
> Jakub Kicinski <kuba@kernel.org>
> net: create netdev->dev_addr assignment helpers
>
> Lee Jones <lee.jones@linaro.org>
> wl3501_cs: Fix misspelling and provide missing documentation
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> wifi: atmel: Fix an error handling path in atmel_probe()
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> wifi: orinoco: Fix an error handling path in orinoco_cs_probe()
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> wifi: orinoco: Fix an error handling path in spectrum_cs_probe()
>
> Geert Uytterhoeven <geert+renesas@glider.be>
> regulator: core: Streamline debugfs operations
>
> Geert Uytterhoeven <geert+renesas@glider.be>
> regulator: core: Fix more error checking for debugfs_create_dir()
>
> Alan Maguire <alan.maguire@oracle.com>
> bpftool: JIT limited misreported as negative value on aarch64
>
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> nfc: llcp: fix possible use of uninitialized variable in nfc_llcp_send_connect()
>
> Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
> nfc: constify several pointers to u8, char and sk_buff
>
> Andrii Nakryiko <andrii@kernel.org>
> libbpf: fix offsetof() and container_of() to work with CO-RE
>
> Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
> sctp: add bpf_bypass_getsockopt proto callback
>
> Stanislav Fomichev <sdf@google.com>
> bpf: Remove extra lock_sock for TCP_ZEROCOPY_RECEIVE
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> wifi: mwifiex: Fix the size of a memory allocation in mwifiex_ret_802_11_scan()
>
> Amisha Patel <amisha.patel@microchip.com>
> wifi: wilc1000: fix for absent RSN capabilities WFA testcase
>
> Vijaya Krishna Nivarthi <quic_vnivarth@quicinc.com>
> spi: spi-geni-qcom: Correct CS_TOGGLE bit in SPI_TRANS_CFG
>
> Pengcheng Yang <yangpc@wangsu.com>
> samples/bpf: Fix buffer overflow in tcp_basertt
>
> Fedor Pchelkin <pchelkin@ispras.ru>
> wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx
>
> Peter Seiderer <ps.report@gmx.net>
> wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation
>
> Jesper Dangaard Brouer <brouer@redhat.com>
> igc: Enable and fix RX hash usage by netstack
>
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
> pstore/ram: Add check for kstrdup
>
> Roberto Sassu <roberto.sassu@huawei.com>
> ima: Fix build warnings
>
> Roberto Sassu <roberto.sassu@huawei.com>
> evm: Complete description of evm_inode_setattr()
>
> Juergen Gross <jgross@suse.com>
> x86/mm: Fix __swp_entry_to_pte() for Xen PV guests
>
> Ravi Bangoria <ravi.bangoria@amd.com>
> perf/ibs: Fix interface via core pmu events
>
> Qiuxu Zhuo <qiuxu.zhuo@intel.com>
> rcu/rcuscale: Stop kfree_scale_thread thread(s) after unloading rcuscale
>
> Qiuxu Zhuo <qiuxu.zhuo@intel.com>
> rcu/rcuscale: Move rcu_scale_*() after kfree_scale_cleanup()
>
> Paul E. McKenney <paulmck@kernel.org>
> rcuscale: Move shutdown from wait_event() to wait_event_idle()
>
> Li Zhijian <zhijianx.li@intel.com>
> rcuscale: Always log error message
>
> Jiangong.Han <jiangong.han@windriver.com>
> rcuscale: Console output claims too few grace periods
>
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
> thermal/drivers/sun8i: Fix some error handling paths in sun8i_ths_probe()
>
> Tero Kristo <tero.kristo@linux.intel.com>
> cpufreq: intel_pstate: Fix energy_performance_preference for passive
>
> Arnd Bergmann <arnd@arndb.de>
> ARM: 9303/1: kprobes: avoid missing-declaration warnings
>
> Zhang Rui <rui.zhang@intel.com>
> powercap: RAPL: Fix CONFIG_IOSF_MBI dependency
>
> Robin Murphy <robin.murphy@arm.com>
> perf/arm-cmn: Fix DTC reset
>
> Nikita Zhandarovich <n.zhandarovich@fintech.ru>
> PM: domains: fix integer overflow issues in genpd_parse_state()
>
> Feng Mingxi <m202271825@hust.edu.cn>
> clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
>
> Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> tracing/timer: Add missing hrtimer modes to decode_hrtimer_mode().
>
> Thomas Gleixner <tglx@linutronix.de>
> posix-timers: Prevent RT livelock in itimer_delete()
>
> John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
> irqchip/jcore-aic: Fix missing allocation of IRQ descriptors
>
> Marc Zyngier <maz@kernel.org>
> irqchip/jcore-aic: Kill use of irq_create_strict_mappings()
>
> Li Nan <linan122@huawei.com>
> md/raid10: fix io loss while replacement replace rdev
>
> Li Nan <linan122@huawei.com>
> md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request
>
> Li Nan <linan122@huawei.com>
> md/raid10: fix wrong setting of max_corr_read_errors
>
> Li Nan <linan122@huawei.com>
> md/raid10: fix overflow of md/safe_mode_delay
>
> Li Nan <linan122@huawei.com>
> md/raid10: check slab-out-of-bounds in md_bitmap_get_counter
>
> Li Nan <linan122@huawei.com>
> blk-iocost: use spin_lock_irqsave in adjust_inuse_and_calc_cost
>
> Shawn Wang <shawnwang@linux.alibaba.com>
> x86/resctrl: Only show tasks' pid in current pid namespace
>
> Arnd Bergmann <arnd@arndb.de>
> fs: pipe: reveal missing function protoypes
>
> Finn Thain <fthain@linux-m68k.org>
> nubus: Partially revert proc_create_single_data() conversion
>
> Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
> drm/amdgpu: Validate VM ioctl flags.
>
> Ahmed S. Darwish <darwi@linutronix.de>
> scripts/tags.sh: Resolve gtags empty index generation
>
> Ricardo Cañuelo <ricardo.canuelo@collabora.com>
> Revert "thermal/drivers/mediatek: Use devm_of_iomap to avoid resource leak in mtk_thermal_probe"
>
> Mike Hommey <mh@glandium.org>
> HID: logitech-hidpp: add HIDPP_QUIRK_DELAYED_INIT for the T651.
>
> Jason Gerecke <jason.gerecke@wacom.com>
> HID: wacom: Use ktime_t rather than int when dealing with timestamps
>
> Zheng Wang <zyytlz.wz@163.com>
> fbdev: imsttfb: Fix use after free bug in imsttfb_probe
>
> Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> video: imsttfb: check for ioremap() failures
>
> Oliver Hartkopp <socketcan@hartkopp.net>
> can: isotp: isotp_sendmsg(): fix return error fix on TX path
>
> Thomas Gleixner <tglx@linutronix.de>
> x86/smp: Use dedicated cache-line for mwait_play_dead()
>
> Tsuchiya Yuto <kitakar@gmail.com>
> media: atomisp: fix "variable dereferenced before check 'asd'"
>
>
> -------------
>
> Diffstat:
>
> Documentation/filesystems/autofs-mount-control.rst | 2 +-
> Documentation/filesystems/autofs.rst | 2 +-
> Documentation/filesystems/directory-locking.rst | 26 +-
> Documentation/networking/af_xdp.rst | 9 +
> Documentation/networking/ip-sysctl.rst | 25 +
> Makefile | 4 +-
> arch/alpha/include/asm/pgtable.h | 8 +-
> arch/arc/include/asm/linkage.h | 8 +-
> arch/arm/boot/dts/bcm53015-meraki-mr26.dts | 2 +-
> arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 2 +-
> arch/arm/boot/dts/bcm5301x.dtsi | 1 -
> arch/arm/boot/dts/iwg20d-q7-common.dtsi | 2 +-
> arch/arm/boot/dts/meson8.dtsi | 4 +-
> arch/arm/boot/dts/meson8b.dtsi | 4 +-
> arch/arm/boot/dts/omap3-gta04a5one.dts | 4 +-
> arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi | 11 +-
> arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 8 +-
> arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi | 6 -
> arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 2 +-
> arch/arm/include/asm/pgtable-3level.h | 2 +-
> arch/arm/mach-ep93xx/timer-ep93xx.c | 3 +-
> arch/arm/mach-omap2/board-generic.c | 1 +
> arch/arm/mach-orion5x/board-dt.c | 3 +
> arch/arm/mach-orion5x/common.h | 6 +
> arch/arm/probes/kprobes/checkers-common.c | 2 +-
> arch/arm/probes/kprobes/core.c | 2 +-
> arch/arm/probes/kprobes/opt-arm.c | 2 -
> arch/arm/probes/kprobes/test-core.c | 2 +-
> arch/arm/probes/kprobes/test-core.h | 4 +
> arch/arm64/boot/dts/microchip/sparx5.dtsi | 2 +-
> .../boot/dts/microchip/sparx5_pcb_common.dtsi | 12 +
> arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts | 4 +-
> arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +-
> arch/arm64/boot/dts/qcom/msm8994.dtsi | 2 +-
> arch/arm64/boot/dts/qcom/msm8996.dtsi | 2 +-
> arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 3 +-
> .../boot/dts/ti/k3-j7200-common-proc-board.dts | 28 +-
> arch/arm64/include/asm/exception.h | 5 -
> arch/arm64/include/asm/pgtable.h | 8 +-
> arch/arm64/mm/mmu.c | 4 +-
> arch/ia64/include/asm/pgtable.h | 4 +-
> arch/m68k/include/asm/motorola_pgtable.h | 2 +-
> arch/mips/include/asm/pgtable-64.h | 8 +-
> arch/mips/kernel/cpu-probe.c | 9 +-
> arch/parisc/include/asm/pgtable.h | 4 +-
> arch/powerpc/Kconfig.debug | 2 +-
> arch/powerpc/Makefile | 8 +
> arch/powerpc/include/asm/book3s/64/pgtable.h | 11 +-
> arch/powerpc/include/asm/nohash/64/pgtable-4k.h | 6 +-
> arch/powerpc/include/asm/nohash/64/pgtable.h | 6 +-
> arch/powerpc/mm/book3s64/radix_pgtable.c | 40 +-
> arch/powerpc/mm/init_64.c | 2 +-
> arch/powerpc/mm/pgtable_64.c | 4 +-
> arch/powerpc/platforms/powernv/pci-sriov.c | 6 +-
> arch/riscv/include/asm/pgtable-64.h | 4 +-
> arch/riscv/net/bpf_jit.h | 5 +-
> arch/riscv/net/bpf_jit_comp64.c | 13 -
> arch/riscv/net/bpf_jit_core.c | 29 +-
> arch/s390/Makefile | 1 +
> arch/s390/kvm/kvm-s390.c | 4 +
> arch/s390/kvm/vsie.c | 6 +-
> arch/sh/drivers/dma/dma-sh.c | 37 +-
> arch/sh/include/asm/pgtable-3level.h | 4 +-
> arch/sh/kernel/cpu/sh2/probe.c | 2 +-
> arch/sparc/include/asm/pgtable_32.h | 6 +-
> arch/sparc/include/asm/pgtable_64.h | 10 +-
> arch/um/Makefile | 2 +-
> arch/um/include/asm/pgtable-3level.h | 2 +-
> arch/x86/events/amd/core.c | 2 +-
> arch/x86/events/amd/ibs.c | 53 +-
> arch/x86/include/asm/perf_event.h | 2 +
> arch/x86/include/asm/pgtable.h | 8 +-
> arch/x86/include/asm/pgtable_64.h | 4 +-
> arch/x86/kernel/cpu/resctrl/rdtgroup.c | 8 +-
> arch/x86/kernel/smpboot.c | 24 +-
> arch/x86/mm/init_64.c | 4 +-
> arch/x86/mm/pat/set_memory.c | 4 +-
> arch/x86/mm/pgtable.c | 2 +-
> arch/xtensa/platforms/iss/network.c | 2 +-
> block/blk-iocost.c | 7 +-
> block/partitions/amiga.c | 104 +++-
> drivers/acpi/button.c | 9 +
> drivers/acpi/video_detect.c | 16 +
> drivers/base/power/domain.c | 6 +-
> drivers/base/regmap/regmap-i2c.c | 8 +-
> drivers/base/regmap/regmap-spi-avmm.c | 2 +-
> drivers/base/regmap/regmap.c | 6 +-
> drivers/block/nbd.c | 3 +-
> drivers/bus/ti-sysc.c | 4 +-
> drivers/char/hw_random/imx-rngc.c | 6 +-
> drivers/char/hw_random/st-rng.c | 21 +-
> drivers/char/hw_random/virtio-rng.c | 86 ++-
> drivers/char/tpm/tpm_tis_core.c | 2 +
> drivers/char/tpm/tpm_vtpm_proxy.c | 30 +-
> drivers/clk/clk-cdce925.c | 12 +
> drivers/clk/clk-si5341.c | 242 +++++++-
> drivers/clk/clk-versaclock5.c | 29 +
> drivers/clk/imx/clk-imx8mn.c | 8 +-
> drivers/clk/imx/clk-imx8mp.c | 24 +-
> drivers/clk/keystone/sci-clk.c | 2 +
> drivers/clk/qcom/gcc-ipq6018.c | 34 +-
> drivers/clk/qcom/reset.c | 8 +-
> drivers/clk/qcom/reset.h | 2 +
> drivers/clk/tegra/clk-tegra124-emc.c | 2 +
> drivers/clk/ti/clkctrl.c | 7 +
> drivers/clocksource/timer-cadence-ttc.c | 19 +-
> drivers/cpufreq/intel_pstate.c | 2 +
> drivers/crypto/marvell/cesa/cipher.c | 2 +-
> drivers/crypto/nx/Makefile | 2 +-
> drivers/crypto/nx/nx.h | 4 +-
> drivers/dax/bus.c | 61 +-
> drivers/dax/dax-private.h | 4 +-
> drivers/extcon/extcon.c | 8 +
> drivers/firmware/stratix10-svc.c | 2 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 20 +-
> drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 13 +-
> drivers/gpu/drm/amd/display/dc/core/dc.c | 3 -
> drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 +-
> drivers/gpu/drm/bridge/tc358768.c | 93 ++-
> drivers/gpu/drm/drm_atomic.c | 11 +-
> drivers/gpu/drm/drm_atomic_helper.c | 11 +-
> drivers/gpu/drm/drm_client_modeset.c | 6 +
> drivers/gpu/drm/drm_gem_vram_helper.c | 6 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 5 +-
> drivers/gpu/drm/msm/dp/dp_display.c | 2 +-
> drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 11 +-
> drivers/gpu/drm/panel/panel-simple.c | 6 +-
> drivers/gpu/drm/radeon/ci_dpm.c | 28 +-
> drivers/gpu/drm/radeon/cypress_dpm.c | 8 +-
> drivers/gpu/drm/radeon/ni_dpm.c | 8 +-
> drivers/gpu/drm/radeon/rv740_dpm.c | 8 +-
> drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 +-
> drivers/gpu/drm/sun4i/sun4i_tcon.c | 19 +-
> drivers/hid/hid-logitech-hidpp.c | 2 +-
> drivers/hid/wacom_wac.c | 6 +-
> drivers/hid/wacom_wac.h | 2 +-
> drivers/hwmon/gsc-hwmon.c | 6 +-
> drivers/hwmon/pmbus/adm1275.c | 94 ++-
> drivers/hwtracing/coresight/coresight-core.c | 9 +-
> drivers/i2c/busses/i2c-qup.c | 21 +-
> drivers/i2c/busses/i2c-xiic.c | 39 +-
> drivers/iio/adc/meson_saradc.c | 2 +-
> drivers/infiniband/core/cma.c | 23 +
> drivers/infiniband/core/cma_priv.h | 1 +
> drivers/infiniband/core/device.c | 11 +
> drivers/infiniband/core/uverbs_cmd.c | 2 +-
> drivers/infiniband/hw/bnxt_re/main.c | 20 +-
> drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40 +-
> drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2 +-
> drivers/infiniband/hw/bnxt_re/qplib_rcfw.c | 46 +-
> drivers/infiniband/hw/bnxt_re/qplib_rcfw.h | 1 +
> drivers/infiniband/hw/efa/efa_main.c | 3 -
> drivers/infiniband/hw/hfi1/ipoib_tx.c | 4 +-
> drivers/infiniband/hw/hfi1/mmu_rb.c | 101 +--
> drivers/infiniband/hw/hfi1/mmu_rb.h | 3 +
> drivers/infiniband/hw/hfi1/sdma.c | 27 +-
> drivers/infiniband/hw/hfi1/sdma.h | 62 +-
> drivers/infiniband/hw/hfi1/sdma_txreq.h | 2 +
> drivers/infiniband/hw/hfi1/user_sdma.c | 145 ++---
> drivers/infiniband/hw/hfi1/user_sdma.h | 1 -
> drivers/infiniband/hw/hfi1/vnic_sdma.c | 4 +-
> drivers/infiniband/hw/hns/hns_roce_cmd.c | 27 +-
> drivers/infiniband/hw/hns/hns_roce_cmd.h | 4 +-
> drivers/infiniband/hw/hns/hns_roce_cq.c | 2 +-
> drivers/infiniband/hw/hns/hns_roce_device.h | 2 -
> drivers/infiniband/hw/hns/hns_roce_hem.c | 131 +---
> drivers/infiniband/hw/hns/hns_roce_hem.h | 15 +-
> drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 93 ++-
> drivers/infiniband/hw/hns/hns_roce_hw_v1.h | 7 +-
> drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 9 +-
> drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 6 +-
> drivers/infiniband/hw/hns/hns_roce_main.c | 8 +-
> drivers/infiniband/hw/hns/hns_roce_mr.c | 4 +-
> drivers/infiniband/hw/hns/hns_roce_qp.c | 2 +-
> drivers/infiniband/hw/hns/hns_roce_srq.c | 1 -
> drivers/infiniband/hw/mlx4/main.c | 14 +-
> drivers/infiniband/hw/mlx5/main.c | 14 +-
> drivers/input/misc/adxl34x.c | 3 +-
> drivers/input/misc/drv260x.c | 1 +
> drivers/irqchip/irq-jcore-aic.c | 11 +-
> drivers/leds/trigger/ledtrig-netdev.c | 3 +
> drivers/mailbox/ti-msgmgr.c | 12 +-
> drivers/md/bcache/btree.c | 25 +-
> drivers/md/bcache/btree.h | 1 +
> drivers/md/bcache/super.c | 4 +-
> drivers/md/bcache/writeback.c | 10 +
> drivers/md/md-bitmap.c | 17 +-
> drivers/md/md.c | 23 +-
> drivers/md/raid0.c | 62 +-
> drivers/md/raid0.h | 1 +
> drivers/md/raid10.c | 38 +-
> drivers/media/cec/i2c/Kconfig | 1 +
> drivers/media/platform/qcom/venus/helpers.c | 4 +-
> drivers/media/usb/dvb-usb-v2/az6007.c | 3 +-
> drivers/media/usb/siano/smsusb.c | 3 +-
> drivers/memory/brcmstb_dpfe.c | 4 +-
> drivers/memstick/host/r592.c | 4 +-
> drivers/mfd/intel-lpss-acpi.c | 3 +
> drivers/mfd/rt5033.c | 3 -
> drivers/mfd/stmfx.c | 7 +-
> drivers/mfd/stmpe.c | 4 +-
> drivers/misc/fastrpc.c | 2 +-
> drivers/misc/pci_endpoint_test.c | 10 +-
> drivers/mmc/core/quirks.h | 14 +
> drivers/mmc/host/mmci.c | 1 +
> drivers/mmc/host/sdhci.c | 4 +-
> drivers/mtd/nand/raw/meson_nand.c | 4 +
> drivers/net/dsa/vitesse-vsc73xx-core.c | 6 +-
> drivers/net/ethernet/amazon/ena/ena_com.c | 3 +
> drivers/net/ethernet/broadcom/bgmac.c | 4 +-
> drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +
> drivers/net/ethernet/broadcom/tg3.c | 1 +
> drivers/net/ethernet/google/gve/gve_ethtool.c | 3 +
> drivers/net/ethernet/intel/iavf/iavf_ethtool.c | 2 +-
> drivers/net/ethernet/intel/iavf/iavf_main.c | 5 +-
> drivers/net/ethernet/intel/igb/igb_main.c | 5 +
> drivers/net/ethernet/intel/igc/igc.h | 33 +-
> drivers/net/ethernet/intel/igc/igc_ethtool.c | 2 +
> drivers/net/ethernet/intel/igc/igc_main.c | 45 +-
> drivers/net/ethernet/intel/igc/igc_ptp.c | 57 +-
> drivers/net/ethernet/marvell/mvneta.c | 4 +-
> drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 11 +
> .../net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 2 +-
> .../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5 +-
> .../ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1 +
> drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +-
> drivers/net/ethernet/microchip/lan743x_main.c | 21 +-
> drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5 -
> drivers/net/ethernet/sfc/ef10.c | 13 +-
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 -
> drivers/net/ethernet/ti/cpsw_ale.c | 24 +-
> drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 10 +-
> drivers/net/gtp.c | 2 +
> drivers/net/ipvlan/ipvlan_core.c | 9 +-
> drivers/net/netdevsim/dev.c | 9 +-
> drivers/net/phy/phy_device.c | 21 +-
> drivers/net/ppp/pptp.c | 31 +-
> drivers/net/wireguard/netlink.c | 14 +-
> drivers/net/wireguard/queueing.c | 1 +
> drivers/net/wireguard/queueing.h | 25 +-
> drivers/net/wireguard/receive.c | 2 +-
> drivers/net/wireguard/send.c | 2 +-
> drivers/net/wireless/ath/ath11k/mac.c | 2 +-
> drivers/net/wireless/ath/ath9k/ar9003_hw.c | 27 +-
> drivers/net/wireless/ath/ath9k/htc_hst.c | 8 +-
> drivers/net/wireless/ath/ath9k/main.c | 11 +-
> drivers/net/wireless/ath/ath9k/wmi.c | 4 +
> drivers/net/wireless/atmel/atmel_cs.c | 13 +-
> drivers/net/wireless/cisco/airo.c | 5 +-
> drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 +-
> drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 2 +-
> drivers/net/wireless/intersil/orinoco/orinoco_cs.c | 13 +-
> .../net/wireless/intersil/orinoco/spectrum_cs.c | 13 +-
> drivers/net/wireless/marvell/mwifiex/scan.c | 6 +-
> drivers/net/wireless/microchip/wilc1000/hif.c | 8 +-
> drivers/net/wireless/ray_cs.c | 36 +-
> drivers/net/wireless/rsi/rsi_91x_sdio.c | 9 +-
> drivers/net/wireless/wl3501_cs.c | 27 +-
> drivers/ntb/hw/amd/ntb_hw_amd.c | 7 +-
> drivers/ntb/hw/idt/ntb_hw_idt.c | 7 +-
> drivers/ntb/hw/intel/ntb_hw_gen1.c | 7 +-
> drivers/ntb/ntb_transport.c | 2 +-
> drivers/ntb/test/ntb_tool.c | 2 +
> drivers/nubus/proc.c | 22 +-
> drivers/nvme/host/pci.c | 3 +-
> drivers/pci/controller/cadence/pcie-cadence-host.c | 27 +
> drivers/pci/controller/dwc/pcie-qcom.c | 2 +
> drivers/pci/controller/pci-ftpci100.c | 14 +-
> drivers/pci/controller/pcie-rockchip-ep.c | 65 +-
> drivers/pci/controller/pcie-rockchip.c | 17 +
> drivers/pci/controller/pcie-rockchip.h | 11 +-
> drivers/pci/hotplug/pciehp_ctrl.c | 8 +
> drivers/pci/pci.c | 10 +-
> drivers/pci/pcie/aspm.c | 21 +-
> drivers/pci/quirks.c | 2 +
> drivers/perf/arm-cmn.c | 7 +-
> drivers/phy/tegra/xusb.c | 4 +
> drivers/pinctrl/bcm/pinctrl-bcm2835.c | 6 +-
> drivers/pinctrl/intel/pinctrl-cherryview.c | 15 +-
> drivers/pinctrl/pinctrl-amd.c | 41 +-
> drivers/pinctrl/pinctrl-amd.h | 1 +
> drivers/pinctrl/pinctrl-at91-pio4.c | 2 +
> drivers/platform/x86/wmi.c | 64 +-
> drivers/powercap/Kconfig | 4 +-
> drivers/powercap/intel_rapl_msr.c | 1 -
> drivers/pwm/pwm-imx-tpm.c | 7 +
> drivers/pwm/sysfs.c | 17 +
> drivers/regulator/core.c | 30 +-
> drivers/rtc/rtc-st-lpc.c | 2 +-
> drivers/s390/net/qeth_l3_sys.c | 2 +-
> drivers/scsi/3w-xxxx.c | 4 +-
> drivers/scsi/qedf/qedf_main.c | 3 +-
> drivers/scsi/qla2xxx/qla_attr.c | 13 +
> drivers/scsi/qla2xxx/qla_bsg.c | 6 +
> drivers/scsi/qla2xxx/qla_def.h | 1 -
> drivers/scsi/qla2xxx/qla_init.c | 2 +-
> drivers/scsi/qla2xxx/qla_inline.h | 5 +-
> drivers/scsi/qla2xxx/qla_iocb.c | 5 +-
> drivers/scsi/qla2xxx/qla_nvme.c | 3 -
> drivers/scsi/qla2xxx/qla_os.c | 3 +-
> drivers/soc/amlogic/meson-secure-pwrc.c | 2 +-
> drivers/soc/fsl/qe/Kconfig | 1 +
> drivers/spi/spi-bcm-qspi.c | 10 +-
> drivers/spi/spi-bcm63xx.c | 2 +-
> drivers/spi/spi-geni-qcom.c | 2 +-
> drivers/staging/media/atomisp/pci/atomisp_cmd.c | 3 +-
> .../media/atomisp/pci/atomisp_gmin_platform.c | 2 +-
> drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 3 +-
> drivers/thermal/mtk_thermal.c | 14 +-
> drivers/thermal/sun8i_thermal.c | 55 +-
> drivers/tty/serial/8250/8250.h | 1 -
> drivers/tty/serial/8250/8250_omap.c | 25 +-
> drivers/tty/serial/8250/8250_pci.c | 19 -
> drivers/tty/serial/8250/8250_port.c | 11 +-
> drivers/tty/serial/atmel_serial.c | 4 +-
> drivers/tty/serial/fsl_lpuart.c | 1 +
> drivers/tty/serial/samsung_tty.c | 14 +-
> drivers/usb/core/devio.c | 2 +
> drivers/usb/dwc3/dwc3-meson-g12a.c | 5 +-
> drivers/usb/dwc3/dwc3-qcom.c | 17 +-
> drivers/usb/dwc3/gadget.c | 4 +-
> drivers/usb/gadget/function/u_serial.c | 13 +-
> drivers/usb/host/xhci-mem.c | 39 +-
> drivers/usb/host/xhci-pci.c | 12 +
> drivers/usb/host/xhci.h | 2 +
> drivers/usb/phy/phy-tahvo.c | 2 +-
> drivers/usb/serial/option.c | 4 +
> drivers/video/fbdev/au1200fb.c | 3 +
> drivers/video/fbdev/imsttfb.c | 34 +-
> drivers/video/fbdev/imxfb.c | 4 +-
> drivers/video/fbdev/omap/lcd_mipid.c | 6 +-
> drivers/w1/slaves/w1_therm.c | 31 +-
> drivers/w1/w1.c | 4 +-
> fs/btrfs/block-group.c | 9 +-
> fs/btrfs/disk-io.c | 3 +
> fs/btrfs/qgroup.c | 3 +
> fs/ceph/caps.c | 9 +
> fs/dlm/plock.c | 4 +-
> fs/erofs/zdata.c | 2 +-
> fs/erofs/zmap.c | 6 +-
> fs/ext4/indirect.c | 8 +
> fs/ext4/inode.c | 10 -
> fs/ext4/ioctl.c | 5 +-
> fs/ext4/mballoc.c | 17 +-
> fs/ext4/namei.c | 17 +-
> fs/ext4/super.c | 13 +-
> fs/ext4/xattr.c | 14 +
> fs/f2fs/f2fs.h | 2 +-
> fs/f2fs/file.c | 2 +-
> fs/f2fs/gc.c | 22 +-
> fs/f2fs/namei.c | 16 +-
> fs/f2fs/node.c | 4 +-
> fs/fs_context.c | 3 +-
> fs/fuse/dir.c | 2 +-
> fs/inode.c | 42 ++
> fs/internal.h | 2 +
> fs/jffs2/build.c | 5 +-
> fs/jffs2/xattr.c | 13 +-
> fs/jffs2/xattr.h | 4 +-
> fs/jfs/jfs_dmap.c | 6 +
> fs/jfs/jfs_filsys.h | 2 +
> fs/kernfs/dir.c | 2 +
> fs/namei.c | 25 +-
> fs/nfs/nfs4proc.c | 1 +
> fs/nfsd/nfs4xdr.c | 2 +-
> fs/notify/fanotify/fanotify_user.c | 22 +-
> fs/overlayfs/copy_up.c | 2 +
> fs/overlayfs/dir.c | 3 +-
> fs/overlayfs/export.c | 3 +-
> fs/overlayfs/namei.c | 3 +-
> fs/overlayfs/overlayfs.h | 6 +-
> fs/overlayfs/super.c | 2 +-
> fs/overlayfs/util.c | 24 +-
> fs/pstore/ram_core.c | 2 +
> fs/ramfs/inode.c | 2 +-
> include/asm-generic/pgtable-nop4d.h | 2 +-
> include/asm-generic/pgtable-nopmd.h | 2 +-
> include/asm-generic/pgtable-nopud.h | 2 +-
> include/linux/bpf-cgroup.h | 27 +-
> include/linux/etherdevice.h | 12 +
> include/linux/indirect_call_wrapper.h | 6 +
> include/linux/netdevice.h | 18 +
> include/linux/nmi.h | 2 +-
> include/linux/pci.h | 1 +
> include/linux/pgtable.h | 4 +-
> include/linux/pipe_fs_i.h | 4 -
> include/linux/ramfs.h | 1 +
> include/linux/sched/signal.h | 2 +-
> include/linux/serial_8250.h | 1 -
> include/linux/tcp.h | 2 +-
> include/linux/workqueue.h | 15 +-
> include/net/netfilter/nf_tables.h | 41 +-
> include/net/netns/ipv4.h | 1 +
> include/net/netns/nftables.h | 7 -
> include/net/nfc/nfc.h | 4 +-
> include/net/pkt_sched.h | 2 +-
> include/net/sock.h | 3 +
> include/net/tcp.h | 32 +-
> include/trace/events/timer.h | 6 +-
> include/uapi/linux/affs_hardblocks.h | 68 +-
> include/uapi/linux/auto_dev-ioctl.h | 2 +-
> include/uapi/linux/videodev2.h | 2 +-
> io_uring/io_uring.c | 66 +-
> kernel/bpf/bpf_lru_list.c | 21 +-
> kernel/bpf/bpf_lru_list.h | 7 +-
> kernel/bpf/cgroup.c | 46 ++
> kernel/kcsan/core.c | 2 +
> kernel/kexec_core.c | 5 +-
> kernel/rcu/rcuscale.c | 214 +++----
> kernel/rcu/tasks.h | 37 +-
> kernel/sched/fair.c | 2 +-
> kernel/time/posix-timers.c | 74 ++-
> kernel/trace/ftrace.c | 72 ++-
> kernel/trace/ring_buffer.c | 24 +-
> kernel/trace/trace.c | 3 +-
> kernel/trace/trace_events_hist.c | 9 +-
> kernel/trace/trace_probe_tmpl.h | 2 +
> kernel/watchdog_hld.c | 6 +-
> kernel/workqueue.c | 13 +-
> lib/debugobjects.c | 9 +
> lib/test_firmware.c | 12 +-
> lib/ts_bm.c | 4 +-
> mm/shmem.c | 2 +-
> net/bridge/br_if.c | 5 +-
> net/bridge/br_stp_if.c | 3 +
> net/can/bcm.c | 12 +-
> net/can/isotp.c | 5 +-
> net/core/devlink.c | 5 +-
> net/core/rtnetlink.c | 104 ++--
> net/core/skbuff.c | 5 +
> net/core/sock.c | 17 +-
> net/dsa/tag_sja1105.c | 4 +-
> net/ipv4/esp4.c | 2 +-
> net/ipv4/inet_connection_sock.c | 3 +-
> net/ipv4/inet_hashtables.c | 17 +-
> net/ipv4/inet_timewait_sock.c | 8 +-
> net/ipv4/sysctl_net_ipv4.c | 9 +
> net/ipv4/tcp.c | 68 +-
> net/ipv4/tcp_fastopen.c | 6 +-
> net/ipv4/tcp_input.c | 12 +-
> net/ipv4/tcp_ipv4.c | 3 +-
> net/ipv4/tcp_minisocks.c | 9 +-
> net/ipv4/tcp_output.c | 2 +-
> net/ipv4/tcp_timer.c | 10 +-
> net/ipv6/addrconf.c | 3 +-
> net/ipv6/icmp.c | 5 +-
> net/ipv6/ip6_gre.c | 3 +-
> net/ipv6/tcp_ipv6.c | 3 +-
> net/ipv6/udp.c | 2 +-
> net/llc/llc_input.c | 3 -
> net/netfilter/nf_conntrack_helper.c | 4 +
> net/netfilter/nf_conntrack_proto_dccp.c | 52 +-
> net/netfilter/nf_conntrack_sip.c | 2 +-
> net/netfilter/nf_tables_api.c | 681 +++++++++++++++------
> net/netfilter/nf_tables_offload.c | 30 +-
> net/netfilter/nft_byteorder.c | 14 +-
> net/netfilter/nft_chain_filter.c | 11 +-
> net/netfilter/nft_dynset.c | 6 +-
> net/netfilter/nft_immediate.c | 90 ++-
> net/netfilter/nft_set_bitmap.c | 5 +-
> net/netfilter/nft_set_hash.c | 23 +-
> net/netfilter/nft_set_pipapo.c | 20 +-
> net/netfilter/nft_set_rbtree.c | 5 +-
> net/netlink/af_netlink.c | 5 +-
> net/netlink/diag.c | 7 +-
> net/nfc/core.c | 4 +-
> net/nfc/hci/llc_shdlc.c | 10 +-
> net/nfc/llcp.h | 9 +-
> net/nfc/llcp_commands.c | 59 +-
> net/nfc/llcp_core.c | 95 ++-
> net/nfc/llcp_sock.c | 21 +-
> net/nfc/netlink.c | 20 +-
> net/nfc/nfc.h | 3 +-
> net/sched/act_pedit.c | 1 +
> net/sched/cls_flower.c | 10 +
> net/sched/cls_fw.c | 10 +-
> net/sched/sch_qfq.c | 41 +-
> net/sctp/socket.c | 22 +-
> net/socket.c | 3 +
> net/sunrpc/svcsock.c | 23 +-
> net/wireless/scan.c | 217 ++++---
> net/wireless/wext-core.c | 6 +
> net/xdp/xsk.c | 5 +
> samples/bpf/tcp_basertt_kern.c | 2 +-
> samples/ftrace/ftrace-direct-too.c | 14 +-
> scripts/mod/modpost.c | 26 +-
> scripts/tags.sh | 9 +-
> security/apparmor/policy_unpack.c | 9 +-
> security/integrity/evm/evm_main.c | 2 +
> security/integrity/iint.c | 15 +-
> security/integrity/ima/ima_modsig.c | 3 +
> security/integrity/ima/ima_policy.c | 3 +-
> security/keys/request_key.c | 35 +-
> security/keys/trusted-keys/trusted_tpm2.c | 2 +-
> sound/core/jack.c | 15 +-
> sound/pci/ac97/ac97_codec.c | 4 +-
> sound/pci/hda/patch_realtek.c | 28 +-
> sound/soc/codecs/es8316.c | 23 +-
> sound/soc/fsl/fsl_sai.c | 2 +-
> sound/soc/fsl/fsl_sai.h | 1 +
> sound/soc/fsl/imx-audmix.c | 9 +
> sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 13 +-
> tools/bpf/bpftool/feature.c | 24 +-
> tools/include/uapi/linux/tcp.h | 357 +++++++++++
> tools/lib/bpf/bpf_helpers.h | 15 +-
> tools/perf/builtin-bench.c | 7 +-
> tools/perf/builtin-script.c | 34 +-
> tools/perf/tests/builtin-test.c | 3 +
> .../tests/shell/test_uprobe_from_different_cu.sh | 77 +++
> tools/perf/util/dwarf-aux.c | 2 +-
> .../testing/selftests/bpf/prog_tests/bpf_tcp_ca.c | 1 +
> .../selftests/bpf/prog_tests/cls_redirect.c | 1 +
> .../selftests/bpf/prog_tests/sockmap_basic.c | 1 +
> .../testing/selftests/bpf/prog_tests/sockopt_sk.c | 28 +
> tools/testing/selftests/bpf/progs/sockopt_sk.c | 23 +-
> tools/testing/selftests/bpf/test_progs.h | 1 -
> tools/testing/selftests/bpf/test_verifier.c | 12 +-
> tools/testing/selftests/bpf/verifier/spill_fill.c | 30 +
> tools/testing/selftests/net/rtnetlink.sh | 1 +
> tools/testing/selftests/tc-testing/config | 1 +
> tools/testing/selftests/tc-testing/settings | 1 +
> tools/testing/selftests/wireguard/netns.sh | 30 +-
> 522 files changed, 5604 insertions(+), 2683 deletions(-)
>
>
> .
>
^ permalink raw reply [relevance 0%]
* Linux 5.10.188
@ 2023-07-27 7:13 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-27 7:13 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.10.188 kernel.
All users of the 5.10 kernel series must upgrade.
The updated 5.10.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.10.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/filesystems/autofs-mount-control.rst | 2
Documentation/filesystems/autofs.rst | 2
Documentation/filesystems/directory-locking.rst | 26
Documentation/networking/af_xdp.rst | 9
Documentation/networking/ip-sysctl.rst | 25
Makefile | 2
arch/alpha/include/asm/pgtable.h | 8
arch/arc/include/asm/linkage.h | 8
arch/arm/boot/dts/bcm53015-meraki-mr26.dts | 2
arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 2
arch/arm/boot/dts/bcm5301x.dtsi | 1
arch/arm/boot/dts/iwg20d-q7-common.dtsi | 2
arch/arm/boot/dts/meson8.dtsi | 4
arch/arm/boot/dts/meson8b.dtsi | 4
arch/arm/boot/dts/omap3-gta04a5one.dts | 4
arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi | 11
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 8
arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi | 6
arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 2
arch/arm/include/asm/pgtable-3level.h | 2
arch/arm/mach-ep93xx/timer-ep93xx.c | 3
arch/arm/mach-omap2/board-generic.c | 1
arch/arm/mach-orion5x/board-dt.c | 3
arch/arm/mach-orion5x/common.h | 6
arch/arm/probes/kprobes/checkers-common.c | 2
arch/arm/probes/kprobes/core.c | 2
arch/arm/probes/kprobes/opt-arm.c | 2
arch/arm/probes/kprobes/test-core.c | 2
arch/arm/probes/kprobes/test-core.h | 4
arch/arm64/boot/dts/microchip/sparx5.dtsi | 2
arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi | 12
arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts | 4
arch/arm64/boot/dts/qcom/msm8916.dtsi | 2
arch/arm64/boot/dts/qcom/msm8994.dtsi | 2
arch/arm64/boot/dts/qcom/msm8996.dtsi | 2
arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 3
arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts | 28
arch/arm64/include/asm/exception.h | 5
arch/arm64/include/asm/pgtable.h | 8
arch/arm64/mm/mmu.c | 4
arch/ia64/include/asm/pgtable.h | 4
arch/m68k/include/asm/motorola_pgtable.h | 2
arch/mips/include/asm/pgtable-64.h | 8
arch/mips/kernel/cpu-probe.c | 9
arch/parisc/include/asm/pgtable.h | 4
arch/powerpc/Kconfig.debug | 2
arch/powerpc/Makefile | 8
arch/powerpc/include/asm/book3s/64/pgtable.h | 11
arch/powerpc/include/asm/nohash/64/pgtable-4k.h | 6
arch/powerpc/include/asm/nohash/64/pgtable.h | 6
arch/powerpc/mm/book3s64/radix_pgtable.c | 40
arch/powerpc/mm/init_64.c | 2
arch/powerpc/mm/pgtable_64.c | 4
arch/powerpc/platforms/powernv/pci-sriov.c | 6
arch/riscv/include/asm/pgtable-64.h | 4
arch/riscv/net/bpf_jit.h | 5
arch/riscv/net/bpf_jit_comp64.c | 13
arch/riscv/net/bpf_jit_core.c | 29
arch/s390/Makefile | 1
arch/s390/kvm/kvm-s390.c | 4
arch/s390/kvm/vsie.c | 6
arch/sh/drivers/dma/dma-sh.c | 37
arch/sh/include/asm/pgtable-3level.h | 4
arch/sh/kernel/cpu/sh2/probe.c | 2
arch/sparc/include/asm/pgtable_32.h | 6
arch/sparc/include/asm/pgtable_64.h | 10
arch/um/Makefile | 2
arch/um/include/asm/pgtable-3level.h | 2
arch/x86/events/amd/core.c | 2
arch/x86/events/amd/ibs.c | 53 -
arch/x86/include/asm/perf_event.h | 2
arch/x86/include/asm/pgtable.h | 8
arch/x86/include/asm/pgtable_64.h | 4
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 8
arch/x86/kernel/smpboot.c | 24
arch/x86/mm/init_64.c | 4
arch/x86/mm/pat/set_memory.c | 4
arch/x86/mm/pgtable.c | 2
arch/xtensa/platforms/iss/network.c | 2
block/blk-iocost.c | 7
block/partitions/amiga.c | 104 +-
drivers/acpi/button.c | 9
drivers/acpi/video_detect.c | 16
drivers/base/power/domain.c | 6
drivers/base/regmap/regmap-i2c.c | 8
drivers/base/regmap/regmap-spi-avmm.c | 2
drivers/base/regmap/regmap.c | 6
drivers/block/nbd.c | 3
drivers/bus/ti-sysc.c | 4
drivers/char/hw_random/imx-rngc.c | 6
drivers/char/hw_random/st-rng.c | 21
drivers/char/hw_random/virtio-rng.c | 88 +
drivers/char/tpm/tpm_tis_core.c | 2
drivers/char/tpm/tpm_vtpm_proxy.c | 30
drivers/clk/clk-cdce925.c | 12
drivers/clk/clk-si5341.c | 242 ++++
drivers/clk/clk-versaclock5.c | 29
drivers/clk/imx/clk-imx8mn.c | 8
drivers/clk/imx/clk-imx8mp.c | 24
drivers/clk/keystone/sci-clk.c | 2
drivers/clk/qcom/gcc-ipq6018.c | 34
drivers/clk/qcom/reset.c | 8
drivers/clk/qcom/reset.h | 2
drivers/clk/tegra/clk-tegra124-emc.c | 2
drivers/clk/ti/clkctrl.c | 7
drivers/clocksource/timer-cadence-ttc.c | 19
drivers/cpufreq/intel_pstate.c | 2
drivers/crypto/marvell/cesa/cipher.c | 2
drivers/crypto/nx/Makefile | 2
drivers/crypto/nx/nx.h | 4
drivers/dax/bus.c | 61 -
drivers/dax/dax-private.h | 4
drivers/extcon/extcon.c | 8
drivers/firmware/stratix10-svc.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 20
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 13
drivers/gpu/drm/amd/display/dc/core/dc.c | 3
drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2
drivers/gpu/drm/bridge/tc358768.c | 93 +
drivers/gpu/drm/drm_atomic.c | 11
drivers/gpu/drm/drm_atomic_helper.c | 11
drivers/gpu/drm/drm_client_modeset.c | 6
drivers/gpu/drm/drm_gem_vram_helper.c | 6
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 5
drivers/gpu/drm/msm/dp/dp_display.c | 2
drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 11
drivers/gpu/drm/panel/panel-simple.c | 6
drivers/gpu/drm/radeon/ci_dpm.c | 28
drivers/gpu/drm/radeon/cypress_dpm.c | 8
drivers/gpu/drm/radeon/ni_dpm.c | 8
drivers/gpu/drm/radeon/rv740_dpm.c | 8
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8
drivers/gpu/drm/sun4i/sun4i_tcon.c | 19
drivers/hid/hid-logitech-hidpp.c | 2
drivers/hid/wacom_wac.c | 6
drivers/hid/wacom_wac.h | 2
drivers/hwmon/gsc-hwmon.c | 6
drivers/hwmon/pmbus/adm1275.c | 96 +
drivers/hwtracing/coresight/coresight-core.c | 9
drivers/i2c/busses/i2c-qup.c | 21
drivers/i2c/busses/i2c-xiic.c | 39
drivers/iio/adc/meson_saradc.c | 2
drivers/infiniband/core/cma.c | 23
drivers/infiniband/core/cma_priv.h | 1
drivers/infiniband/core/device.c | 11
drivers/infiniband/core/uverbs_cmd.c | 2
drivers/infiniband/hw/bnxt_re/main.c | 20
drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40
drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c | 46
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h | 1
drivers/infiniband/hw/efa/efa_main.c | 3
drivers/infiniband/hw/hfi1/ipoib_tx.c | 4
drivers/infiniband/hw/hfi1/mmu_rb.c | 101 +-
drivers/infiniband/hw/hfi1/mmu_rb.h | 3
drivers/infiniband/hw/hfi1/sdma.c | 27
drivers/infiniband/hw/hfi1/sdma.h | 62 -
drivers/infiniband/hw/hfi1/sdma_txreq.h | 2
drivers/infiniband/hw/hfi1/user_sdma.c | 145 +-
drivers/infiniband/hw/hfi1/user_sdma.h | 1
drivers/infiniband/hw/hfi1/vnic_sdma.c | 4
drivers/infiniband/hw/hns/hns_roce_cmd.c | 27
drivers/infiniband/hw/hns/hns_roce_cmd.h | 4
drivers/infiniband/hw/hns/hns_roce_cq.c | 2
drivers/infiniband/hw/hns/hns_roce_device.h | 2
drivers/infiniband/hw/hns/hns_roce_hem.c | 131 --
drivers/infiniband/hw/hns/hns_roce_hem.h | 15
drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 93 +
drivers/infiniband/hw/hns/hns_roce_hw_v1.h | 7
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 9
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 6
drivers/infiniband/hw/hns/hns_roce_main.c | 8
drivers/infiniband/hw/hns/hns_roce_mr.c | 4
drivers/infiniband/hw/hns/hns_roce_qp.c | 2
drivers/infiniband/hw/hns/hns_roce_srq.c | 1
drivers/infiniband/hw/mlx4/main.c | 14
drivers/infiniband/hw/mlx5/main.c | 14
drivers/input/misc/adxl34x.c | 3
drivers/input/misc/drv260x.c | 1
drivers/irqchip/irq-jcore-aic.c | 11
drivers/leds/trigger/ledtrig-netdev.c | 3
drivers/mailbox/ti-msgmgr.c | 12
drivers/md/bcache/btree.c | 25
drivers/md/bcache/btree.h | 1
drivers/md/bcache/super.c | 4
drivers/md/bcache/writeback.c | 10
drivers/md/md-bitmap.c | 17
drivers/md/md.c | 23
drivers/md/raid0.c | 62 +
drivers/md/raid0.h | 1
drivers/md/raid10.c | 38
drivers/media/cec/i2c/Kconfig | 1
drivers/media/platform/qcom/venus/helpers.c | 4
drivers/media/usb/dvb-usb-v2/az6007.c | 3
drivers/media/usb/siano/smsusb.c | 3
drivers/memory/brcmstb_dpfe.c | 4
drivers/memstick/host/r592.c | 4
drivers/mfd/intel-lpss-acpi.c | 3
drivers/mfd/rt5033.c | 3
drivers/mfd/stmfx.c | 7
drivers/mfd/stmpe.c | 4
drivers/misc/fastrpc.c | 2
drivers/misc/pci_endpoint_test.c | 10
drivers/mmc/core/quirks.h | 14
drivers/mmc/host/mmci.c | 1
drivers/mmc/host/sdhci.c | 4
drivers/mtd/nand/raw/meson_nand.c | 4
drivers/net/dsa/vitesse-vsc73xx-core.c | 6
drivers/net/ethernet/amazon/ena/ena_com.c | 3
drivers/net/ethernet/broadcom/bgmac.c | 4
drivers/net/ethernet/broadcom/genet/bcmmii.c | 2
drivers/net/ethernet/broadcom/tg3.c | 1
drivers/net/ethernet/google/gve/gve_ethtool.c | 3
drivers/net/ethernet/intel/iavf/iavf_ethtool.c | 2
drivers/net/ethernet/intel/iavf/iavf_main.c | 5
drivers/net/ethernet/intel/igb/igb_main.c | 5
drivers/net/ethernet/intel/igc/igc.h | 33
drivers/net/ethernet/intel/igc/igc_ethtool.c | 2
drivers/net/ethernet/intel/igc/igc_main.c | 45
drivers/net/ethernet/intel/igc/igc_ptp.c | 57 -
drivers/net/ethernet/marvell/mvneta.c | 4
drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 11
drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 2
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6
drivers/net/ethernet/microchip/lan743x_main.c | 21
drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5
drivers/net/ethernet/sfc/ef10.c | 13
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6
drivers/net/ethernet/ti/cpsw_ale.c | 24
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 10
drivers/net/gtp.c | 2
drivers/net/ipvlan/ipvlan_core.c | 9
drivers/net/netdevsim/dev.c | 9
drivers/net/phy/phy_device.c | 21
drivers/net/ppp/pptp.c | 31
drivers/net/wireguard/netlink.c | 14
drivers/net/wireguard/queueing.c | 1
drivers/net/wireguard/queueing.h | 25
drivers/net/wireguard/receive.c | 2
drivers/net/wireguard/send.c | 2
drivers/net/wireless/ath/ath11k/mac.c | 2
drivers/net/wireless/ath/ath9k/ar9003_hw.c | 27
drivers/net/wireless/ath/ath9k/htc_hst.c | 8
drivers/net/wireless/ath/ath9k/main.c | 11
drivers/net/wireless/ath/ath9k/wmi.c | 4
drivers/net/wireless/atmel/atmel_cs.c | 13
drivers/net/wireless/cisco/airo.c | 5
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 2
drivers/net/wireless/intersil/orinoco/orinoco_cs.c | 13
drivers/net/wireless/intersil/orinoco/spectrum_cs.c | 13
drivers/net/wireless/marvell/mwifiex/scan.c | 6
drivers/net/wireless/microchip/wilc1000/hif.c | 8
drivers/net/wireless/ray_cs.c | 36
drivers/net/wireless/rsi/rsi_91x_sdio.c | 9
drivers/net/wireless/wl3501_cs.c | 27
drivers/ntb/hw/amd/ntb_hw_amd.c | 7
drivers/ntb/hw/idt/ntb_hw_idt.c | 7
drivers/ntb/hw/intel/ntb_hw_gen1.c | 7
drivers/ntb/ntb_transport.c | 2
drivers/ntb/test/ntb_tool.c | 2
drivers/nubus/proc.c | 22
drivers/nvme/host/pci.c | 3
drivers/pci/controller/cadence/pcie-cadence-host.c | 27
drivers/pci/controller/dwc/pcie-qcom.c | 2
drivers/pci/controller/pci-ftpci100.c | 14
drivers/pci/controller/pcie-rockchip-ep.c | 65 -
drivers/pci/controller/pcie-rockchip.c | 17
drivers/pci/controller/pcie-rockchip.h | 11
drivers/pci/hotplug/pciehp_ctrl.c | 8
drivers/pci/pci.c | 10
drivers/pci/pcie/aspm.c | 21
drivers/pci/quirks.c | 2
drivers/perf/arm-cmn.c | 7
drivers/phy/tegra/xusb.c | 4
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 6
drivers/pinctrl/intel/pinctrl-cherryview.c | 15
drivers/pinctrl/pinctrl-amd.c | 41
drivers/pinctrl/pinctrl-amd.h | 1
drivers/pinctrl/pinctrl-at91-pio4.c | 2
drivers/platform/x86/wmi.c | 64 -
drivers/powercap/Kconfig | 4
drivers/powercap/intel_rapl_msr.c | 1
drivers/pwm/pwm-imx-tpm.c | 7
drivers/pwm/sysfs.c | 17
drivers/regulator/core.c | 30
drivers/rtc/rtc-st-lpc.c | 2
drivers/s390/net/qeth_l3_sys.c | 2
drivers/scsi/3w-xxxx.c | 4
drivers/scsi/qedf/qedf_main.c | 3
drivers/scsi/qla2xxx/qla_attr.c | 13
drivers/scsi/qla2xxx/qla_bsg.c | 6
drivers/scsi/qla2xxx/qla_def.h | 1
drivers/scsi/qla2xxx/qla_init.c | 2
drivers/scsi/qla2xxx/qla_inline.h | 5
drivers/scsi/qla2xxx/qla_iocb.c | 5
drivers/scsi/qla2xxx/qla_nvme.c | 3
drivers/scsi/qla2xxx/qla_os.c | 3
drivers/soc/amlogic/meson-secure-pwrc.c | 2
drivers/soc/fsl/qe/Kconfig | 1
drivers/spi/spi-bcm-qspi.c | 10
drivers/spi/spi-bcm63xx.c | 2
drivers/spi/spi-geni-qcom.c | 2
drivers/staging/media/atomisp/pci/atomisp_cmd.c | 3
drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c | 2
drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 3
drivers/thermal/mtk_thermal.c | 14
drivers/thermal/sun8i_thermal.c | 55 -
drivers/tty/serial/8250/8250.h | 1
drivers/tty/serial/8250/8250_omap.c | 25
drivers/tty/serial/8250/8250_pci.c | 19
drivers/tty/serial/8250/8250_port.c | 11
drivers/tty/serial/atmel_serial.c | 4
drivers/tty/serial/fsl_lpuart.c | 1
drivers/tty/serial/samsung_tty.c | 14
drivers/usb/core/devio.c | 2
drivers/usb/dwc3/dwc3-meson-g12a.c | 5
drivers/usb/dwc3/dwc3-qcom.c | 17
drivers/usb/dwc3/gadget.c | 4
drivers/usb/gadget/function/u_serial.c | 13
drivers/usb/host/xhci-mem.c | 39
drivers/usb/host/xhci-pci.c | 12
drivers/usb/host/xhci.h | 2
drivers/usb/phy/phy-tahvo.c | 2
drivers/usb/serial/option.c | 4
drivers/video/fbdev/au1200fb.c | 3
drivers/video/fbdev/imsttfb.c | 36
drivers/video/fbdev/imxfb.c | 4
drivers/video/fbdev/omap/lcd_mipid.c | 6
drivers/w1/slaves/w1_therm.c | 31
drivers/w1/w1.c | 4
fs/btrfs/block-group.c | 9
fs/btrfs/disk-io.c | 3
fs/btrfs/qgroup.c | 3
fs/ceph/caps.c | 9
fs/dlm/plock.c | 4
fs/erofs/zdata.c | 2
fs/erofs/zmap.c | 6
fs/ext4/indirect.c | 8
fs/ext4/inode.c | 10
fs/ext4/mballoc.c | 17
fs/ext4/namei.c | 17
fs/ext4/super.c | 13
fs/ext4/xattr.c | 14
fs/f2fs/f2fs.h | 2
fs/f2fs/file.c | 2
fs/f2fs/gc.c | 22
fs/f2fs/namei.c | 16
fs/f2fs/node.c | 4
fs/fs_context.c | 3
fs/fuse/dir.c | 2
fs/inode.c | 42
fs/internal.h | 2
fs/jffs2/build.c | 5
fs/jffs2/xattr.c | 13
fs/jffs2/xattr.h | 4
fs/jfs/jfs_dmap.c | 6
fs/jfs/jfs_filsys.h | 2
fs/kernfs/dir.c | 2
fs/namei.c | 25
fs/nfs/nfs4proc.c | 1
fs/nfsd/nfs4xdr.c | 2
fs/notify/fanotify/fanotify_user.c | 22
fs/overlayfs/copy_up.c | 2
fs/overlayfs/dir.c | 3
fs/overlayfs/export.c | 3
fs/overlayfs/namei.c | 3
fs/overlayfs/overlayfs.h | 6
fs/overlayfs/super.c | 2
fs/overlayfs/util.c | 24
fs/pstore/ram_core.c | 2
fs/ramfs/inode.c | 2
include/asm-generic/pgtable-nop4d.h | 2
include/asm-generic/pgtable-nopmd.h | 2
include/asm-generic/pgtable-nopud.h | 2
include/linux/bpf-cgroup.h | 27
include/linux/etherdevice.h | 12
include/linux/indirect_call_wrapper.h | 6
include/linux/netdevice.h | 18
include/linux/nmi.h | 2
include/linux/pci.h | 1
include/linux/pgtable.h | 4
include/linux/pipe_fs_i.h | 4
include/linux/ramfs.h | 1
include/linux/sched/signal.h | 2
include/linux/serial_8250.h | 1
include/linux/tcp.h | 2
include/linux/workqueue.h | 15
include/net/netfilter/nf_tables.h | 41
include/net/netns/ipv4.h | 1
include/net/netns/nftables.h | 7
include/net/nfc/nfc.h | 4
include/net/pkt_sched.h | 2
include/net/sock.h | 3
include/net/tcp.h | 32
include/trace/events/timer.h | 6
include/uapi/linux/affs_hardblocks.h | 68 -
include/uapi/linux/auto_dev-ioctl.h | 2
include/uapi/linux/videodev2.h | 2
io_uring/io_uring.c | 66 +
kernel/bpf/bpf_lru_list.c | 21
kernel/bpf/bpf_lru_list.h | 7
kernel/bpf/cgroup.c | 46
kernel/kcsan/core.c | 2
kernel/kexec_core.c | 5
kernel/rcu/rcuscale.c | 214 ++--
kernel/rcu/tasks.h | 37
kernel/sched/fair.c | 2
kernel/time/posix-timers.c | 74 +
kernel/trace/ftrace.c | 72 -
kernel/trace/ring_buffer.c | 24
kernel/trace/trace.c | 3
kernel/trace/trace_events_hist.c | 9
kernel/trace/trace_probe_tmpl.h | 2
kernel/watchdog_hld.c | 6
kernel/workqueue.c | 13
lib/debugobjects.c | 9
lib/test_firmware.c | 12
lib/ts_bm.c | 4
mm/shmem.c | 2
net/bridge/br_if.c | 5
net/bridge/br_stp_if.c | 3
net/can/bcm.c | 12
net/can/isotp.c | 5
net/core/devlink.c | 5
net/core/rtnetlink.c | 104 +-
net/core/skbuff.c | 5
net/core/sock.c | 17
net/dsa/tag_sja1105.c | 4
net/ipv4/esp4.c | 2
net/ipv4/inet_connection_sock.c | 3
net/ipv4/inet_hashtables.c | 17
net/ipv4/inet_timewait_sock.c | 8
net/ipv4/sysctl_net_ipv4.c | 9
net/ipv4/tcp.c | 68 -
net/ipv4/tcp_fastopen.c | 6
net/ipv4/tcp_input.c | 12
net/ipv4/tcp_ipv4.c | 3
net/ipv4/tcp_minisocks.c | 9
net/ipv4/tcp_output.c | 2
net/ipv4/tcp_timer.c | 10
net/ipv6/addrconf.c | 3
net/ipv6/icmp.c | 5
net/ipv6/ip6_gre.c | 3
net/ipv6/tcp_ipv6.c | 3
net/ipv6/udp.c | 2
net/llc/llc_input.c | 3
net/netfilter/nf_conntrack_helper.c | 4
net/netfilter/nf_conntrack_proto_dccp.c | 52 +
net/netfilter/nf_conntrack_sip.c | 2
net/netfilter/nf_tables_api.c | 681 +++++++++-----
net/netfilter/nf_tables_offload.c | 30
net/netfilter/nft_byteorder.c | 14
net/netfilter/nft_chain_filter.c | 11
net/netfilter/nft_dynset.c | 6
net/netfilter/nft_immediate.c | 90 +
net/netfilter/nft_set_bitmap.c | 5
net/netfilter/nft_set_hash.c | 23
net/netfilter/nft_set_pipapo.c | 20
net/netfilter/nft_set_rbtree.c | 5
net/netlink/af_netlink.c | 5
net/netlink/diag.c | 7
net/nfc/core.c | 4
net/nfc/hci/llc_shdlc.c | 10
net/nfc/llcp.h | 9
net/nfc/llcp_commands.c | 59 -
net/nfc/llcp_core.c | 93 +
net/nfc/llcp_sock.c | 21
net/nfc/netlink.c | 20
net/nfc/nfc.h | 3
net/sched/act_pedit.c | 1
net/sched/cls_flower.c | 10
net/sched/cls_fw.c | 10
net/sched/sch_qfq.c | 41
net/sctp/socket.c | 22
net/socket.c | 3
net/sunrpc/svcsock.c | 23
net/wireless/scan.c | 213 ++--
net/wireless/wext-core.c | 6
net/xdp/xsk.c | 5
samples/bpf/tcp_basertt_kern.c | 2
samples/ftrace/ftrace-direct-too.c | 14
scripts/mod/modpost.c | 26
scripts/tags.sh | 9
security/apparmor/policy_unpack.c | 9
security/integrity/evm/evm_main.c | 2
security/integrity/iint.c | 15
security/integrity/ima/ima_modsig.c | 3
security/integrity/ima/ima_policy.c | 3
security/keys/request_key.c | 35
security/keys/trusted-keys/trusted_tpm2.c | 2
sound/core/jack.c | 15
sound/pci/ac97/ac97_codec.c | 4
sound/pci/hda/patch_realtek.c | 28
sound/soc/codecs/es8316.c | 23
sound/soc/fsl/fsl_sai.c | 2
sound/soc/fsl/fsl_sai.h | 1
sound/soc/fsl/imx-audmix.c | 9
sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 13
tools/bpf/bpftool/feature.c | 24
tools/include/uapi/linux/tcp.h | 357 +++++++
tools/lib/bpf/bpf_helpers.h | 15
tools/perf/builtin-bench.c | 7
tools/perf/builtin-script.c | 34
tools/perf/tests/builtin-test.c | 3
tools/perf/tests/shell/test_uprobe_from_different_cu.sh | 77 +
tools/perf/util/dwarf-aux.c | 2
tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c | 1
tools/testing/selftests/bpf/prog_tests/cls_redirect.c | 1
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c | 1
tools/testing/selftests/bpf/prog_tests/sockopt_sk.c | 28
tools/testing/selftests/bpf/progs/sockopt_sk.c | 23
tools/testing/selftests/bpf/test_progs.h | 1
tools/testing/selftests/bpf/test_verifier.c | 12
tools/testing/selftests/bpf/verifier/spill_fill.c | 30
tools/testing/selftests/net/rtnetlink.sh | 1
tools/testing/selftests/tc-testing/config | 1
tools/testing/selftests/tc-testing/settings | 1
tools/testing/selftests/wireguard/netns.sh | 30
521 files changed, 5599 insertions(+), 2681 deletions(-)
Ahmed S. Darwish (1):
scripts/tags.sh: Resolve gtags empty index generation
Alan Maguire (1):
bpftool: JIT limited misreported as negative value on aarch64
Alexander Aring (1):
fs: dlm: return positive pid value for F_GETLK
Alexander Mikhalitsyn (1):
sctp: add bpf_bypass_getsockopt proto callback
Alexey Romanov (1):
drivers: meson: secure-pwrc: always enable DMA domain
Amelie Delaunay (2):
mfd: stmfx: Fix error path in stmfx_chip_init
mfd: stmfx: Nullify stmfx->vdd in case of error
Amir Goldstein (2):
ovl: update of dentry revalidate flags after copy up
fanotify: disallow mount/sb marks on kernel internal pseudo fs
Amisha Patel (1):
wifi: wilc1000: fix for absent RSN capabilities WFA testcase
Andres Freund (1):
io_uring: Use io_schedule* in cqring wait
Andrii Nakryiko (1):
libbpf: fix offsetof() and container_of() to work with CO-RE
Andy Shevchenko (6):
wifi: ray_cs: Utilize strnlen() in parse_addr()
wifi: ray_cs: Drop useless status variable in parse_addr()
pinctrl: cherryview: Return correct value if pin in push-pull mode
extcon: Fix kernel doc of property fields to avoid warnings
extcon: Fix kernel doc of property capability fields to avoid warnings
platform/x86: wmi: Break possible infinite loop when parsing GUID
Aneesh Kumar K.V (4):
mm: rename pud_page_vaddr to pud_pgtable and make it return pmd_t *
mm: rename p4d_page_vaddr to p4d_pgtable and make it return pud_t *
powerpc/book3s64/mm: Fix DirectMap stats in /proc/meminfo
powerpc/mm/dax: Fix the condition when checking if altmap vmemap can cross-boundary
Arnaldo Carvalho de Melo (3):
perf bench: Add missing setlocale() call to allow usage of %'d style formatting
perf script: Fixup 'struct evsel_script' method prefix
perf script: Fix allocation of evsel->priv related to per-event dump files
Arnd Bergmann (9):
fs: pipe: reveal missing function protoypes
ARM: 9303/1: kprobes: avoid missing-declaration warnings
memstick r592: make memstick_debug_get_tpc_name() static
ARM: ep93xx: fix missing-prototype warnings
ARM: omap2: fix missing tick_broadcast() prototype
crypto: marvell/cesa - Fix type mismatch warning
usb: hide unused usbfs_notify_suspend/resume functions
autofs: use flexible array in ioctl structure
ARM: orion5x: fix d2net gpio initialization
Arseniy Krasnov (1):
mtd: rawnand: meson: fix unaligned DMA buffers handling
Artur Rojek (1):
sh: dma: Fix DMA channel offset calculation
Baokun Li (1):
ext4: only update i_reserved_data_blocks on successful block allocation
Barnabás Pőcze (3):
platform/x86: wmi: remove unnecessary argument
platform/x86: wmi: use guid_t and guid_equal()
platform/x86: wmi: move variables
Bartosz Golaszewski (1):
net: stmmac: fix double serdes powerdown
Bas Nieuwenhuizen (1):
drm/amdgpu: Validate VM ioctl flags.
Benjamin Berg (1):
wifi: cfg80211: rewrite merging of inherited elements
Bikash Hazarika (2):
scsi: qla2xxx: Fix potential NULL pointer dereference
scsi: qla2xxx: Correct the index of array
Bjorn Andersson (1):
drm/msm/dp: Free resources after unregistering them
Björn Töpel (1):
riscv, bpf: Fix inconsistent JIT image generation
Brendan Cunningham (1):
IB/hfi1: Fix wrong mmu_node used for user SDMA packet after invalidate
Brian Norris (2):
drm/atomic: Allow vblank-enabled + self-refresh "disable"
drm/rockchip: vop: Leave vblank enabled in self-refresh
Cambda Zhu (1):
ipvlan: Fix return value of ipvlan_queue_xmit()
Chao Yu (2):
f2fs: fix error path handling in truncate_dnode()
f2fs: fix to avoid NULL pointer dereference f2fs_write_end_io()
Chengchang Tang (1):
RDMA/hns: Fix hns_roce_table_get return value
Chengfeng Ye (1):
sctp: fix potential deadlock on &net->sctp.addr_wq_lock
Chevron Li (1):
mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is used.
Chia-I Wu (1):
amdgpu: validate offset_in_bo of drm_amdgpu_gem_va
Christian Lamparter (1):
ARM: dts: BCM5301X: fix duplex-full => full-duplex
Christian Marangi (1):
leds: trigger: netdev: Recheck NETDEV_LED_MODE_LINKUP on dev rename
Christophe JAILLET (18):
thermal/drivers/sun8i: Fix some error handling paths in sun8i_ths_probe()
wifi: mwifiex: Fix the size of a memory allocation in mwifiex_ret_802_11_scan()
wifi: orinoco: Fix an error handling path in spectrum_cs_probe()
wifi: orinoco: Fix an error handling path in orinoco_cs_probe()
wifi: atmel: Fix an error handling path in atmel_probe()
wifi: wl3501_cs: Fix an error handling path in wl3501_probe()
wifi: ray_cs: Fix an error handling path in ray_probe()
IB/hfi1: Use bitmap_zalloc() when applicable
fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe()
pinctrl: bcm2835: Handle gpiochip_add_pin_range() errors
usb: dwc3: qcom: Release the correct resources in dwc3_qcom_remove()
usb: dwc3: qcom: Fix an error handling path in dwc3_qcom_probe()
usb: dwc3-meson-g12a: Fix an error handling path in dwc3_meson_g12a_probe()
mfd: stmpe: Only disable the regulators if they are enabled
rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
Christophe Leroy (1):
kcsan: Don't expect 64 bits atomic builtins from 32 bits architectures
Chu Lin (1):
hwmon: (adm1275) enable adm1272 temperature reporting
Chunhai Guo (1):
erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
Claudiu Beznea (10):
clk: vc5: check memory returned by kasprintf()
clk: cdce925: check return value of kasprintf()
clk: si5341: return error if one synth clock registration fails
clk: si5341: check return value of {devm_}kasprintf()
clk: si5341: free unused memory on probe failure
clk: keystone: sci-clk: check return value of kasprintf()
clk: ti: clkctrl: check return value of kasprintf()
ASoC: imx-audmix: check return value of devm_kasprintf()
pinctrl: at91-pio4: check return value of devm_kasprintf()
phy: tegra: xusb: check return value of devm_kzalloc()
Colin Ian King (1):
powerpc/powernv/sriov: perform null check on iov before dereferencing iov
Cristian Ciocaltea (2):
ASoC: es8316: Increment max value for ALC Capture Target Volume control
ASoC: es8316: Do not set rate constraints for unsupported MCLKs
Dai Ngo (1):
NFSD: add encoding of op_recall flag for write delegation
Damien Le Moal (3):
PCI: rockchip: Set address alignment for endpoint mode
misc: pci_endpoint_test: Free IRQs before removing the device
misc: pci_endpoint_test: Re-init completion for every test
Dan Carpenter (6):
modpost: fix off by one in is_executable_section()
w1: fix loop in w1_fini()
media: atomisp: gmin_platform: fix out_len in gmin_get_config_dsm_var()
scsi: qla2xxx: Fix error code in qla2x00_start_sp()
netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
serial: atmel: don't enable IRQs prematurely
Dan Williams (2):
dax: Fix dax_mapping_release() use after free
dax: Introduce alloc_dev_dax_id()
Daniel Vetter (1):
drm/atomic: Fix potential use-after-free in nonblocking commits
Daniil Dulov (2):
drm/amdkfd: Fix potential deallocation of previously deallocated memory.
media: usb: Check az6007_read() return value
Danila Chernetsov (1):
apparmor: fix missing error check for rhashtable_insert_fast
Dario Binacchi (1):
drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H
David Sterba (1):
btrfs: add xxhash to fast checksum implementations
Davide Tronchin (1):
USB: serial: option: add LARA-R6 01B PIDs
Ding Hui (4):
PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free
SUNRPC: Fix UAF in svc_tcp_listen_data_ready()
iavf: Fix use-after-free in free_netdev
iavf: Fix out-of-bounds when setting channels on remove
Dmitry Antipov (1):
wifi: ath9k: convert msecs to jiffies where needed
Dmitry Baryshkov (2):
drm/panel: sharp-ls043t1le01: adjust mode settings
drm/msm/dpu: do not enable color-management if DSPPs are not available
Douglas Anderson (2):
watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct config
watchdog/perf: more properly prevent false positives with turbo modes
Duoming Zhou (1):
media: usb: siano: Fix warning due to null work_func_t function pointer
EJ Hsu (1):
phy: tegra: xusb: Clear the driver reference in usb-phy dev
Edward Cree (1):
sfc: fix crash when reading stats while NIC is resetting
Edwin Peer (1):
rtnetlink: extend RTEXT_FILTER_SKIP_STATS to IFLA_VF_INFO
Ekansh Gupta (1):
misc: fastrpc: Create fastrpc scalar with correct buffer count
Eric Dumazet (15):
netlink: fix potential deadlock in netlink_set_err()
netlink: do not hard code device address lenth in fdb dumps
tcp: annotate data races in __tcp_oow_rate_limited()
udp6: fix udp6_ehashfn() typo
tcp: annotate data-races around tcp_rsk(req)->ts_recent
tcp: annotate data-races around tp->tcp_tx_delay
tcp: annotate data-races around tp->keepalive_time
tcp: annotate data-races around tp->keepalive_intvl
tcp: annotate data-races around tp->keepalive_probes
tcp: annotate data-races around icsk->icsk_syn_retries
tcp: annotate data-races around tp->linger2
tcp: annotate data-races around rskq_defer_accept
tcp: annotate data-races around tp->notsent_lowat
tcp: annotate data-races around icsk->icsk_user_timeout
tcp: annotate data-races around fastopenq.max_qlen
Eric Whitney (1):
ext4: correct inline offset when handling xattrs in inode body
Fabian Frederick (1):
jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
Fabio Estevam (1):
drm/panel: simple: Add connector_type for innolux_at043tn24
Fancy Fang (1):
pwm: imx-tpm: force 'real_period' to be zero in suspend
Fedor Pchelkin (2):
wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx
wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes
Feng Mingxi (1):
clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
Filipe Manana (2):
btrfs: fix race when deleting quota root from the dirty cow roots list
btrfs: fix warning when putting transaction with qgroups enabled after abort
Finn Thain (1):
nubus: Partially revert proc_create_single_data() conversion
Florent Revest (2):
netfilter: conntrack: Avoid nf_ct_helper_hash uses after free
samples: ftrace: Save required argument registers in sample trampolines
Florian Fainelli (1):
net: bcmgenet: Ensure MDIO unregistration has clocks enabled
Florian Kauer (2):
igc: Fix launchtime before start of cycle
igc: Fix inserting of empty frame for launchtime
Florian Westphal (7):
netfilter: conntrack: dccp: copy entire header to stack buffer, not just basic one
netfilter: nf_tables: use net_generic infra for transaction data
netfilter: nf_tables: add rescheduling points during loop detection walks
netfilter: nf_tables: fix scheduling-while-atomic splat
netfilter: nf_tables: fix spurious set element insertion failure
netfilter: nf_tables: can't schedule in nft_chain_validate
netfilter: nft_set_pipapo: fix improper element removal
Francesco Dolcini (9):
drm/bridge: tc358768: always enable HS video mode
drm/bridge: tc358768: fix PLL parameters computation
drm/bridge: tc358768: fix PLL target frequency
drm/bridge: tc358768: fix TCLK_ZEROCNT computation
drm/bridge: tc358768: Add atomic_get_input_bus_fmts() implementation
drm/bridge: tc358768: fix TCLK_TRAILCNT computation
drm/bridge: tc358768: fix THS_ZEROCNT computation
drm/bridge: tc358768: fix TXTAGOCNT computation
drm/bridge: tc358768: fix THS_TRAILCNT computation
Gao Xiang (1):
erofs: fix compact 4B support for 16k block size
Geert Uytterhoeven (4):
regulator: core: Fix more error checking for debugfs_create_dir()
regulator: core: Streamline debugfs operations
ARM: dts: iwg20d-q7-common: Fix backlight pwm specifier
sh: pgtable-3level: Fix cast to pointer from integer of different size
Geetha sowjanya (1):
octeontx2-pf: Dont allocate BPIDs for LBK interfaces
Georg Müller (1):
perf probe: Add test for regression introduced by switch to die_get_decl_file()
George Stark (1):
meson saradc: fix clock divider mask length
Gilad Reti (1):
selftests/bpf: Add verifier test for PTR_TO_MEM spill
Greg Kroah-Hartman (3):
video: imsttfb: check for ioremap() failures
Revert "usb: common: usb-conn-gpio: Set last role to unknown before initial detection"
Linux 5.10.188
Guenter Roeck (1):
hwmon: (pmbus/adm1275) Fix problems with temperature monitoring on ADM1272
Guillaume Nault (1):
pptp: Fix fib lookup calls.
Gustavo A. R. Silva (1):
wifi: wext-core: Fix -Wstringop-overflow warning in ioctl_standard_iw_point()
Hans de Goede (3):
ACPI: button: Add lid disable DMI quirk for Nextbook Ares 8A
ACPI: video: Add backlight=native DMI quirk for Apple iMac11,3
ACPI: video: Add backlight=native DMI quirk for Lenovo ThinkPad X131e (3371 AMD version)
Hao Luo (1):
clk: imx: clk-imx8mn: fix memory leak in imx8mn_clocks_probe
Hariprasad Kelam (1):
octeontx2-af: Fix mapping for NIX block from CGX connection
Heiko Carstens (1):
s390/decompressor: fix misaligned symbol build error
Herbert Xu (1):
hwrng: virtio - Fix race on data_avail and actual data
Huacai Chen (1):
MIPS: Loongson: Fix cpu_probe_loongson() again
Ido Schimmel (1):
net/sched: flower: Ensure both minimum and maximum ports are specified
Ilia.Gavrilov (1):
netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return value.
Ilya Maximets (1):
xsk: Honor SO_BINDTODEVICE on bind
Jakub Kicinski (2):
net: create netdev->dev_addr assignment helpers
wl3501_cs: use eth_hw_addr_set()
James Clark (1):
coresight: Fix loss of connection info when a module is unloaded
Jan Kara (5):
ext4: Remove ext4 locking of moved directory
Revert "f2fs: fix potential corruption when moving a directory"
fs: Establish locking order for unrelated directories
fs: Lock moved directories
fs: no need to check source
Jarkko Sakkinen (1):
tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
Jason A. Donenfeld (2):
wireguard: queueing: use saner cpu selection wrapping
wireguard: netlink: send staged packets when setting initial private key
Jason Baron (1):
md/raid0: add discard support for the 'original' layout
Jason Gerecke (1):
HID: wacom: Use ktime_t rather than int when dealing with timestamps
Jason Gunthorpe (2):
RDMA: Remove uverbs_ex_cmd_mask values that are linked to functions
RDMA/cma: Ensure rdma_addr_cancel() happens before issuing more requests
Jens Axboe (3):
io_uring: ensure IOPOLL locks around deferred work
io_uring: wait interruptibly for request completions on exit
io_uring: add reschedule point to handle_tw_list()
Jeremy Sowden (1):
lib/ts_bm: reset initial match offset for every block of text
Jesper Dangaard Brouer (1):
igc: Enable and fix RX hash usage by netstack
Jiangong.Han (1):
rcuscale: Console output claims too few grace periods
Jiapeng Chong (1):
security: keys: Modify mismatched function name
Jiaqing Zhao (1):
Revert "8250: add support for ASIX devices with a FIFO bug"
Jiasheng Jiang (3):
pstore/ram: Add check for kstrdup
mfd: intel-lpss: Add missing check for platform_get_resource
NTB: ntb_tool: Add check for devm_kcalloc
Jinhong Zhu (1):
scsi: qedf: Fix NULL dereference in error handling
Jisheng Zhang (2):
riscv: bpf: Move bpf_jit_alloc_exec() and bpf_jit_free_exec() to core
riscv: bpf: Avoid breaking W^X
Jocelyn Falempe (2):
drm/client: Fix memory leak in drm_client_target_cloned
drm/client: Fix memory leak in drm_client_modeset_probe
Johannes Berg (2):
wifi: iwlwifi: pull from TXQs with softirqs disabled
wifi: iwlwifi: mvm: avoid baid size integer overflow
John Ogness (2):
serial: 8250: lock port for stop_rx() in omap8250_irq()
serial: 8250: lock port for UART_IER access in omap8250_irq()
John Paul Adrian Glaubitz (2):
irqchip/jcore-aic: Fix missing allocation of IRQ descriptors
sh: j2: Use ioremap() to translate device tree address into kernel memory
Jonas Gorski (2):
spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
spi: bcm63xx: fix max prepend length
Juergen Gross (1):
x86/mm: Fix __swp_entry_to_pte() for Xen PV guests
Junfeng Guo (1):
gve: Set default duplex configuration to full
Junyan Ye (1):
PCI: ftpci100: Release the clock resources
Kailang Yang (1):
ALSA: hda/realtek - remove 3k pull low procedure
Kalesh AP (4):
RDMA/bnxt_re: Fix to remove unnecessary return labels
RDMA/bnxt_re: Use unique names while registering interrupts
RDMA/bnxt_re: Remove a redundant check inside bnxt_re_update_gid
RDMA/bnxt_re: Fix to remove an unnecessary log
Kashyap Desai (2):
RDMA/bnxt_re: wraparound mbox producer index
RDMA/bnxt_re: Avoid calling wake_up threads from spin_lock context
Keerthy (1):
arm64: dts: ti: k3-j7200: Fix physical address of pin
Kees Cook (1):
um: Use HOST_DIR for mrproper
Kemeng Shi (3):
ext4: fix wrong unit use in ext4_mb_clear_bb
ext4: get block from bh in ext4_free_blocks for fast commit replay
ext4: fix wrong unit use in ext4_mb_new_blocks
Klaus Kudielka (1):
net: mvneta: fix txq_map in case of txq_number==1
Krishna Kurapati (1):
usb: dwc3: gadget: Propagate core init errors to UDC during pullup
Krister Johansen (1):
net: ena: fix shift-out-of-bounds in exponential backoff
Krzysztof Kozlowski (8):
nfc: constify several pointers to u8, char and sk_buff
nfc: llcp: fix possible use of uninitialized variable in nfc_llcp_send_connect()
nfc: llcp: simplify llcp_sock_connect() error paths
arm64: dts: qcom: msm8916: correct camss unit address
arm64: dts: qcom: msm8994: correct SPMI unit address
arm64: dts: qcom: msm8996: correct camss unit address
arm64: dts: qcom: apq8096: fix fixed regulator name property
memory: brcmstb_dpfe: fix testing array offset after use
Kuniyuki Iwashima (8):
gtp: Fix use-after-free in __gtp_encap_destroy().
netlink: Add __sock_i_ino() for __netlink_diag_dump().
icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
bridge: Add extack warning when enabling STP in netns.
Revert "tcp: avoid the lookup process failing to get sk in ehash table"
llc: Don't drop packet from non-root netns.
net: Introduce net.ipv4.tcp_migrate_req.
tcp: Fix data-races around sysctl_tcp_syn(ack)?_retries.
Lang Cheng (1):
RDMA/hns: Fix coding style issues
Laurent Vivier (4):
hwrng: virtio - add an internal buffer
hwrng: virtio - don't wait on cleanup
hwrng: virtio - don't waste entropy
hwrng: virtio - always add a pending request
Lee Jones (1):
wl3501_cs: Fix misspelling and provide missing documentation
Li Nan (6):
blk-iocost: use spin_lock_irqsave in adjust_inuse_and_calc_cost
md/raid10: check slab-out-of-bounds in md_bitmap_get_counter
md/raid10: fix overflow of md/safe_mode_delay
md/raid10: fix wrong setting of max_corr_read_errors
md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request
md/raid10: fix io loss while replacement replace rdev
Li Yang (1):
usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
Li Zhijian (1):
rcuscale: Always log error message
Lin Ma (2):
net: nfc: Fix use-after-free caused by nfc_llcp_find_local
net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
Lino Sanfilippo (1):
tpm, tpm_tis: Claim locality in interrupt handler
Linus Torvalds (2):
workqueue: clean up WORK_* constant types, clarify masking
ftrace: Store the order of pages allocated in ftrace_page
Luc Ma (1):
drm/vram-helper: fix function names in vram helper doc
Luca Weiss (1):
Input: drv260x - sleep between polling GO bit
Luka Guzenko (1):
ALSA: hda/realtek: Enable Mute LED on HP Laptop 15s-eq2xxx
M A Ramdhan (1):
net/sched: cls_fw: Fix improper refcount update leads to use-after-free
Manish Rangankar (1):
scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
Manivannan Sadhasivam (1):
PCI: qcom: Disable write access to read only registers for IP v2.3.3
Mantas Pucka (1):
clk: qcom: gcc-ipq6018: Use floor ops for sdcc clocks
Marc Zyngier (1):
irqchip/jcore-aic: Kill use of irq_create_strict_mappings()
Marek Vasut (10):
wifi: rsi: Do not configure WoWlan in shutdown hook if not enabled
wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown
Input: adxl34x - do not hardcode interrupt trigger type
ARM: dts: stm32: Move ethernet MAC EEPROM from SoM to carrier boards
ARM: dts: stm32: Shorten the AV96 HDMI sound card name
ARM: dts: stm32: Fix audio routing on STM32MP15xx DHCOM PDK2
media: videodev2.h: Fix struct v4l2_input tuner index comment
pwm: sysfs: Do not apply state to already disabled PWMs
i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()
drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
Mario Limonciello (5):
pinctrl: amd: Fix mistake in handling clearing pins at startup
pinctrl: amd: Detect internal GPIO0 debounce handling
pinctrl: amd: Only use special debounce behavior for GPIO 0
drm/amd/display: Correct `DMUB_FW_VERSION` macro
pinctrl: amd: Use amd_pinconf_set() for all config options
Mark Brown (2):
regmap: Drop initial version of maximum transfer length fixes
regmap: Account for register length in SMBus I/O limits
Mark Rutland (1):
arm64: mm: fix VA-range sanity check
Martin Blumenstingl (1):
ARM: dts: meson8: correct uart_B and uart_C clock references
Martin KaFai Lau (1):
bpf: Address KCSAN report on bpf_lru_list
Martin Kaiser (3):
hwrng: st - keep clock enabled while hwrng is registered
hwrng: imx-rngc - fix the timeout for init and self check
fbdev: imxfb: warn about invalid left/right margin
Masahiro Yamada (3):
modpost: fix section mismatch message for R_ARM_ABS32
modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24}
ARC: define ASM_NL and __ALIGN(_STR) outside #ifdef __ASSEMBLY__ guard
Masami Hiramatsu (Google) (1):
tracing/probes: Fix not to count error code to total length
Mateusz Stachyra (1):
tracing: Fix null pointer dereference in tracing_err_log_open()
Matt Corallo (1):
btrfs: add handling for RAID1C23/DUP to btrfs_reduce_alloc_profile
Matthieu Baerts (2):
selftests: tc: set timeout to 15 minutes
selftests: tc: add 'ct' action kconfig dep
Matus Gajdos (1):
ASoC: fsl_sai: Disable bit clock with transmitter
Max Filippov (1):
xtensa: ISS: fix call to split_if_spec
Maxim Kochetkov (1):
net: axienet: Move reset before 64-bit DMA detection
Maxime Bizon (1):
wifi: ath11k: fix registration of 6Ghz-only phy without the full channel range
Michael Schmitz (4):
block: fix signed int overflow in Amiga partition support
block: change all __u32 annotations to __be32 in affs_hardblocks.h
block: add overflow checks for Amiga partition support
block/partition: fix signedness issue for Amiga partitions
Mike Hommey (1):
HID: logitech-hidpp: add HIDPP_QUIRK_DELAYED_INIT for the T651.
Miklos Szeredi (1):
fuse: revalidate: don't invalidate if interrupted
Ming Lei (1):
nvme-pci: fix DMA direction of unmapping integrity data
Mingzhe Zou (1):
bcache: fixup btree_cache_wait list damage
Mirsad Goran Todorovac (1):
test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation
Mohamed Khalfella (2):
tracing/histograms: Add histograms to hist_vars if they have referenced variables
tracing/histograms: Return an error if we fail to add histogram to hist_vars list
Moritz Fischer (1):
net: lan743x: Don't sleep in atomic context
Muchun Song (1):
kernfs: fix missing kernfs_idr_lock to remove an ID from the IDR
Muhammad Husaini Zulkifli (1):
igc: Remove delay during TX ring configuration
Namhyung Kim (1):
perf dwarf-aux: Fix off-by-one in die_get_varname()
Naveen N Rao (1):
powerpc: Fail build if using recordmcount with binutils v2.37
Nicholas Kazlauskas (1):
drm/amd/display: Explicitly specify update type per plane info change
Nico Boehr (1):
KVM: s390: fix KVM_S390_GET_CMMA_BITS for GFNs in memslot holes
Nikita Zhandarovich (3):
PM: domains: fix integer overflow issues in genpd_parse_state()
radeon: avoid double free in ci_dpm_init()
drm/radeon: fix possible division-by-zero errors
Nilesh Javali (2):
scsi: qla2xxx: Array index may go out of bound
scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
Nishanth Menon (1):
mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0
Nitya Sunkad (1):
ionic: remove WARN_ON to prevent panic_on_warn
Olga Kornievskaia (1):
NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
Oliver Hartkopp (1):
can: isotp: isotp_sendmsg(): fix return error fix on TX path
Olivier Moysan (1):
ARM: dts: stm32: fix i2s endpoint format property for stm32mp15xx-dkx
Ondrej Zary (1):
PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
Pablo Neira Ayuso (10):
netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE
netfilter: nf_tables: fix chain binding transaction logic
netfilter: nf_tables: add NFT_TRANS_PREPARE_ERROR to deal with bound set/chain
netfilter: nf_tables: reject unbound anonymous set before commit phase
netfilter: nf_tables: reject unbound chain set before commit phase
netfilter: nftables: rename set element data activation/deactivation functions
netfilter: nf_tables: drop map element references from preparation phase
netfilter: nf_tables: unbind non-anonymous set if rule construction fails
netfilter: nf_tables: skip bound chain in netns release path
netfilter: nf_tables: skip bound chain on rule flush
Paolo Abeni (1):
net: prevent skb corruption on frag list segmentation
Patrick Kelsey (1):
IB/hfi1: Fix sdma.h tx->num_descs off-by-one errors
Paul E. McKenney (4):
rcuscale: Move shutdown from wait_event() to wait_event_idle()
rcu-tasks: Mark ->trc_reader_nesting data races
rcu-tasks: Mark ->trc_reader_special.b.need_qs data races
rcu-tasks: Simplify trc_read_check_handler() atomic operations
Pawel Dembicki (1):
net: dsa: vsc73xx: fix MTU configuration
Pedro Tammela (4):
net/sched: make psched_mtu() RTNL-less safe
net/sched: sch_qfq: refactor parsing of netlink parameters
net/sched: sch_qfq: account for stab overhead in qfq_enqueue
net/sched: sch_qfq: reintroduce lmax bound check for MTU
Pengcheng Yang (1):
samples/bpf: Fix buffer overflow in tcp_basertt
Peter Seiderer (1):
wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation
Petr Oros (1):
devlink: report devlink_port_type_warn source device
Petr Pavlu (1):
keys: Fix linking a duplicate key to a keyring's assoc_array
Pierre Morel (1):
KVM: s390: vsie: fix the length of APCB bitmap
Potin Lai (1):
hwmon: (adm1275) Allow setting sample averaging
Prasad Koya (1):
igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
Prashanth K (2):
usb: gadget: u_serial: Add null pointer check in gserial_suspend
usb: common: usb-conn-gpio: Set last role to unknown before initial detection
Pu Lehui (1):
bpf, riscv: Support riscv jit to provide bpf_line_info
Qiuxu Zhuo (2):
rcu/rcuscale: Move rcu_scale_*() after kfree_scale_cleanup()
rcu/rcuscale: Stop kfree_scale_thread thread(s) after unloading rcuscale
Quinn Tran (2):
scsi: qla2xxx: Wait for io return on terminate rport
scsi: qla2xxx: Fix buffer overrun
Rafał Miłecki (2):
ARM: dts: BCM5301X: Drop "clock-names" from the SPI node
net: bgmac: postpone turning IRQs off to avoid SoC hangs
Randy Dunlap (5):
soc/fsl/qe: fix usb.c build errors
crypto: nx - fix build warnings when DEBUG_FS is not enabled
media: cec: i2c: ch7322: also select REGMAP
powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y
wifi: airo: avoid uninitialized warning in airo_get_rate()
Ravi Bangoria (1):
perf/ibs: Fix interface via core pmu events
Remi Pommarel (1):
wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
Ricardo Cañuelo (1):
Revert "thermal/drivers/mediatek: Use devm_of_iomap to avoid resource leak in mtk_thermal_probe"
Ricardo Ribalda Delgado (2):
ASoC: mediatek: mt8173: Fix irq error path
ASoC: mediatek: mt8173: Fix snd_soc_component_initialize error path
Rick Wertenbroek (5):
PCI: rockchip: Assert PCI Configuration Enable bit after probe
PCI: rockchip: Write PCI Device ID to correct register
PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
PCI: rockchip: Use u32 variable to access 32-bit registers
Rikard Falkeborn (1):
media: venus: helpers: Fix ALIGN() of non power of two
Robert Hancock (3):
clk: si5341: Allow different output VDD_SEL values
clk: si5341: Add sysfs properties to allow checking/resetting device faults
i2c: xiic: Don't try to handle more interrupt events after error
Robert Marko (5):
arm64: dts: microchip: sparx5: do not use PSCI on reference boards
clk: qcom: reset: support resetting multiple bits
clk: qcom: ipq6018: fix networking resets
mmc: core: disable TRIM on Kingston EMMC04G-M627
mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
Roberto Sassu (3):
evm: Complete description of evm_inode_setattr()
ima: Fix build warnings
shmem: use ramfs_kill_sb() for kill_sb method of ramfs-based tmpfs
Robin Murphy (2):
perf/arm-cmn: Fix DTC reset
PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
Rongguang Wei (1):
PCI: pciehp: Cancel bringup sequence if card is not present
Sabrina Dubroca (1):
selftests: rtnetlink: remove netdevsim device after ipsec offload test
Sebastian Andrzej Siewior (1):
tracing/timer: Add missing hrtimer modes to decode_hrtimer_mode().
Selvin Xavier (1):
RDMA/bnxt_re: Disable/kill tasklet only if it is enabled
Shawn Wang (1):
x86/resctrl: Only show tasks' pid in current pid namespace
Sherry Sun (1):
tty: serial: fsl_lpuart: add earlycon for imx8ulp platform
Shreyas Deodhar (1):
scsi: qla2xxx: Pointer may be dereferenced
Shuai Jiang (1):
i2c: qup: Add missing unwind goto in qup_i2c_probe()
Siddh Raman Pant (1):
jfs: jfs_dmap: Validate db_l2nbperpage while mounting
Siddharth Vadapalli (1):
PCI: cadence: Fix Gen2 Link Retraining process
Sohaib Mohamed (1):
perf bench: Use unbuffered output when pipe/tee'ing to a file
Stanislav Fomichev (1):
bpf: Remove extra lock_sock for TCP_ZEROCOPY_RECEIVE
Stefan Wahren (1):
w1: w1_therm: fix locking behavior in convert_t
Stephan Gerhold (2):
clk: qcom: reset: Allow specifying custom reset delay
mfd: rt5033: Drop rt5033-battery sub-device
Su Hui (1):
ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer
Sui Jingfeng (1):
PCI: Add pci_clear_master() stub for non-CONFIG_PCI
Takashi Iwai (1):
ALSA: jack: Fix mutex call in snd_jack_report()
Tanmay Patil (1):
net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()
Tero Kristo (1):
cpufreq: intel_pstate: Fix energy_performance_preference for passive
Tetsuo Handa (1):
debugobjects: Recheck debug_objects_enabled before reporting
Thadeu Lima de Souza Cascardo (2):
netfilter: nf_tables: do not ignore genmask when looking up chain by id
netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
Thomas Gleixner (3):
x86/smp: Use dedicated cache-line for mwait_play_dead()
posix-timers: Prevent RT livelock in itimer_delete()
posix-timers: Ensure timer ID search-loop limit is valid
Thomas Weißschuh (1):
fs: avoid empty option when generating legacy mount string
Thorsten Winkler (1):
s390/qeth: Fix vipa deletion
Tianjia Zhang (1):
integrity: Fix possible multiple allocation in integrity_inode_get()
Tim Harvey (1):
hwmon: (gsc-hwmon) fix fan pwm temperature scaling
Tobias Heider (1):
Add MODULE_FIRMWARE() for FIRMWARE_TG357766.
Tony Lindgren (4):
bus: ti-sysc: Fix dispc quirk masking bool variables
ARM: dts: gta04: Move model property out of pinctrl node
serial: 8250: omap: Fix freeing of resources on failed register
serial: 8250_omap: Use force_suspend and resume for system suspend
Tsuchiya Yuto (1):
media: atomisp: fix "variable dereferenced before check 'asd'"
Ulf Hansson (1):
mmc: mmci: Set PROBE_PREFER_ASYNCHRONOUS
Vijaya Krishna Nivarthi (1):
spi: spi-geni-qcom: Correct CS_TOGGLE bit in SPI_TRANS_CFG
Vinicius Costa Gomes (1):
igc: Fix race condition in PTP tx code
Vlad Buslov (1):
net/mlx5e: Check for NOT_READY flag state after locking
Vladimir Oltean (3):
net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode
net: dsa: tag_sja1105: fix MAC DA patching from meta frames
net: phy: prevent stale pointer dereference in phy_init()
Vladislav Efanov (1):
usb: dwc3: qcom: Fix potential memory leak
Wang Ming (1):
net: ipv4: Use kfree_sensitive instead of kfree
Weihang Li (1):
RDMA/hns: Use refcount_t APIs for HEM
Weitao Wang (3):
xhci: Fix resume issue of some ZHAOXIN hosts
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
xhci: Show ZHAOXIN xHCI root hub speed correctly
Wolfram Sang (1):
arm64: dts: renesas: ulcb-kf: Remove flow control for SCIF1
Xi Wang (1):
RDMA/hns: Clean the hardware related code for HEM
Xiubo Li (1):
ceph: don't let check_caps skip sending responses for revoke msgs
XuDong Liu (1):
drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
Yang Yingliang (1):
NTB: ntb_transport: fix possible memory leak while device_register() fails
Yicong Yang (1):
sched/fair: Don't balance task to its current running CPU
Ying Hsu (1):
igb: Fix igb_down hung on surprise removal
Youngmin Nam (1):
arm64: set __exception_irq_entry with __irq_entry as a default
Yu Kuai (2):
md: fix data corruption for raid456 when reshape restart while grow up
md/raid10: prevent soft lockup while flush writes
Yuan Can (4):
clk: tegra: tegra124-emc: Fix potential memory leak
ntb: idt: Fix error handling in idt_pci_driver_init()
NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
Yuanjun Gong (1):
net:ipv6: check return value of pskb_trim()
Yuchen Yang (1):
scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
YueHaibing (1):
can: bcm: Fix UAF in bcm_proc_show()
Yuxing Liu (1):
clk: imx: clk-imx8mp: improve error handling in imx8mp_clocks_probe()
Zhang Rui (1):
powercap: RAPL: Fix CONFIG_IOSF_MBI dependency
Zhang Shurong (1):
fbdev: au1200fb: Fix missing IRQ check in au1200fb_drv_probe
Zhen Lei (1):
kexec: fix a memory leak in crash_shrink_memory()
Zheng Wang (3):
fbdev: imsttfb: Fix use after free bug in imsttfb_probe
bcache: Remove unnecessary NULL point check in node allocations
bcache: Fix __bch_btree_node_alloc to make the failure behavior consistent
Zheng Yejian (3):
ring-buffer: Fix deadloop issue on reading trace_pipe
tracing: Fix memory leak of iter->temp when reading trace_pipe
ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
Zhengchao Shao (1):
net/mlx5e: fix double free in mlx5e_destroy_flow_table
Zhihao Cheng (1):
ext4: Fix reusing stale buffer heads from last failed mounting
Zhong Jinghua (1):
nbd: Add the maximum limit of allocated index in nbd_dev_add
Ziyang Xuan (1):
ipv6/addrconf: fix a potential refcount underflow for idev
hfdevel@gmx.net (1):
ARM: dts: meson8b: correct uart_B and uart_C clock references
^ permalink raw reply [relevance 1%]
* [PATCH 5.10 000/508] 5.10.188-rc2 review
@ 2023-07-26 4:54 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-26 4:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, srw, rwarsow, conor
This is the start of the stable review cycle for the 5.10.188 release.
There are 508 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Fri, 28 Jul 2023 04:52:02 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.188-rc2.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.188-rc2
Zheng Yejian <zhengyejian1@huawei.com>
ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
Linus Torvalds <torvalds@linux-foundation.org>
ftrace: Store the order of pages allocated in ftrace_page
Zheng Yejian <zhengyejian1@huawei.com>
tracing: Fix memory leak of iter->temp when reading trace_pipe
Mohamed Khalfella <mkhalfella@purestorage.com>
tracing/histograms: Return an error if we fail to add histogram to hist_vars list
Vladimir Oltean <vladimir.oltean@nxp.com>
net: phy: prevent stale pointer dereference in phy_init()
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around fastopenq.max_qlen
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around icsk->icsk_user_timeout
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->notsent_lowat
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around rskq_defer_accept
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->linger2
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around icsk->icsk_syn_retries
Kuniyuki Iwashima <kuniyu@amazon.com>
tcp: Fix data-races around sysctl_tcp_syn(ack)?_retries.
Kuniyuki Iwashima <kuniyu@amazon.co.jp>
net: Introduce net.ipv4.tcp_migrate_req.
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->keepalive_probes
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->keepalive_intvl
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->keepalive_time
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->tcp_tx_delay
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: skip bound chain on rule flush
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: skip bound chain in netns release path
Florian Westphal <fw@strlen.de>
netfilter: nft_set_pipapo: fix improper element removal
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: can't schedule in nft_chain_validate
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: fix spurious set element insertion failure
Kuniyuki Iwashima <kuniyu@amazon.com>
llc: Don't drop packet from non-root netns.
Zhang Shurong <zhang_shurong@foxmail.com>
fbdev: au1200fb: Fix missing IRQ check in au1200fb_drv_probe
Kuniyuki Iwashima <kuniyu@amazon.com>
Revert "tcp: avoid the lookup process failing to get sk in ehash table"
Yuanjun Gong <ruc_gongyuanjun@163.com>
net:ipv6: check return value of pskb_trim()
Wang Ming <machel@vivo.com>
net: ipv4: Use kfree_sensitive instead of kfree
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tcp_rsk(req)->ts_recent
Geetha sowjanya <gakula@marvell.com>
octeontx2-pf: Dont allocate BPIDs for LBK interfaces
Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
security: keys: Modify mismatched function name
Ding Hui <dinghui@sangfor.com.cn>
iavf: Fix out-of-bounds when setting channels on remove
Ding Hui <dinghui@sangfor.com.cn>
iavf: Fix use-after-free in free_netdev
Kuniyuki Iwashima <kuniyu@amazon.com>
bridge: Add extack warning when enabling STP in netns.
Tanmay Patil <t-patil@ti.com>
net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Use amd_pinconf_set() for all config options
Martin Kaiser <martin@kaiser.cx>
fbdev: imxfb: warn about invalid left/right margin
Jonas Gorski <jonas.gorski@gmail.com>
spi: bcm63xx: fix max prepend length
Ying Hsu <yinghsu@chromium.org>
igb: Fix igb_down hung on surprise removal
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: mvm: avoid baid size integer overflow
Gustavo A. R. Silva <gustavoars@kernel.org>
wifi: wext-core: Fix -Wstringop-overflow warning in ioctl_standard_iw_point()
Petr Oros <poros@redhat.com>
devlink: report devlink_port_type_warn source device
Martin KaFai Lau <martin.lau@kernel.org>
bpf: Address KCSAN report on bpf_lru_list
Maxime Bizon <mbizon@freebox.fr>
wifi: ath11k: fix registration of 6Ghz-only phy without the full channel range
Yicong Yang <yangyicong@hisilicon.com>
sched/fair: Don't balance task to its current running CPU
Mark Rutland <mark.rutland@arm.com>
arm64: mm: fix VA-range sanity check
Youngmin Nam <youngmin.nam@samsung.com>
arm64: set __exception_irq_entry with __irq_entry as a default
Hans de Goede <hdegoede@redhat.com>
ACPI: video: Add backlight=native DMI quirk for Lenovo ThinkPad X131e (3371 AMD version)
Hans de Goede <hdegoede@redhat.com>
ACPI: video: Add backlight=native DMI quirk for Apple iMac11,3
Hans de Goede <hdegoede@redhat.com>
ACPI: button: Add lid disable DMI quirk for Nextbook Ares 8A
David Sterba <dsterba@suse.com>
btrfs: add xxhash to fast checksum implementations
Thomas Gleixner <tglx@linutronix.de>
posix-timers: Ensure timer ID search-loop limit is valid
Yu Kuai <yukuai3@huawei.com>
md/raid10: prevent soft lockup while flush writes
Yu Kuai <yukuai3@huawei.com>
md: fix data corruption for raid456 when reshape restart while grow up
Zhong Jinghua <zhongjinghua@huawei.com>
nbd: Add the maximum limit of allocated index in nbd_dev_add
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
debugobjects: Recheck debug_objects_enabled before reporting
Eric Whitney <enwlinux@gmail.com>
ext4: correct inline offset when handling xattrs in inode body
Matus Gajdos <matuszpd@gmail.com>
ASoC: fsl_sai: Disable bit clock with transmitter
Jocelyn Falempe <jfalempe@redhat.com>
drm/client: Fix memory leak in drm_client_modeset_probe
Jocelyn Falempe <jfalempe@redhat.com>
drm/client: Fix memory leak in drm_client_target_cloned
YueHaibing <yuehaibing@huawei.com>
can: bcm: Fix UAF in bcm_proc_show()
Mark Brown <broonie@kernel.org>
regmap: Account for register length in SMBus I/O limits
Mark Brown <broonie@kernel.org>
regmap: Drop initial version of maximum transfer length fixes
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: tc: add 'ct' action kconfig dep
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: tc: set timeout to 15 minutes
Miklos Szeredi <mszeredi@redhat.com>
fuse: revalidate: don't invalidate if interrupted
Filipe Manana <fdmanana@suse.com>
btrfs: fix warning when putting transaction with qgroups enabled after abort
Georg Müller <georgmueller@gmx.net>
perf probe: Add test for regression introduced by switch to die_get_decl_file()
Petr Pavlu <petr.pavlu@suse.com>
keys: Fix linking a duplicate key to a keyring's assoc_array
Luka Guzenko <l.guzenko@web.de>
ALSA: hda/realtek: Enable Mute LED on HP Laptop 15s-eq2xxx
Kailang Yang <kailang@realtek.com>
ALSA: hda/realtek - remove 3k pull low procedure
Daniel Vetter <daniel.vetter@ffwll.ch>
drm/atomic: Fix potential use-after-free in nonblocking commits
Jason Gunthorpe <jgg@ziepe.ca>
RDMA/cma: Ensure rdma_addr_cancel() happens before issuing more requests
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: reintroduce lmax bound check for MTU
Manish Rangankar <mrangankar@marvell.com>
scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
Shreyas Deodhar <sdeodhar@marvell.com>
scsi: qla2xxx: Pointer may be dereferenced
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Correct the index of array
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Fix potential NULL pointer dereference
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix buffer overrun
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Array index may go out of bound
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Wait for io return on terminate rport
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix not to count error code to total length
Mateusz Stachyra <m.stachyra@samsung.com>
tracing: Fix null pointer dereference in tracing_err_log_open()
Max Filippov <jcmvbkbc@gmail.com>
xtensa: ISS: fix call to split_if_spec
Zheng Yejian <zhengyejian1@huawei.com>
ring-buffer: Fix deadloop issue on reading trace_pipe
Krister Johansen <kjlx@templeofstupid.com>
net: ena: fix shift-out-of-bounds in exponential backoff
Florent Revest <revest@chromium.org>
samples: ftrace: Save required argument registers in sample trampolines
Mohamed Khalfella <mkhalfella@purestorage.com>
tracing/histograms: Add histograms to hist_vars if they have referenced variables
Heiko Carstens <hca@linux.ibm.com>
s390/decompressor: fix misaligned symbol build error
Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Revert "8250: add support for ASIX devices with a FIFO bug"
George Stark <gnstark@sberdevices.ru>
meson saradc: fix clock divider mask length
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Show ZHAOXIN xHCI root hub speed correctly
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix resume issue of some ZHAOXIN hosts
Xiubo Li <xiubli@redhat.com>
ceph: don't let check_caps skip sending responses for revoke msgs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
Dan Carpenter <dan.carpenter@linaro.org>
serial: atmel: don't enable IRQs prematurely
Mario Limonciello <mario.limonciello@amd.com>
drm/amd/display: Correct `DMUB_FW_VERSION` macro
Brian Norris <briannorris@chromium.org>
drm/rockchip: vop: Leave vblank enabled in self-refresh
Brian Norris <briannorris@chromium.org>
drm/atomic: Allow vblank-enabled + self-refresh "disable"
Alexander Aring <aahringo@redhat.com>
fs: dlm: return positive pid value for F_GETLK
Jason Baron <jbaron@akamai.com>
md/raid0: add discard support for the 'original' layout
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Re-init completion for every test
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Free IRQs before removing the device
Damien Le Moal <dlemoal@kernel.org>
PCI: rockchip: Set address alignment for endpoint mode
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Use u32 variable to access 32-bit registers
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Write PCI Device ID to correct register
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Assert PCI Configuration Enable bit after probe
Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
PCI: qcom: Disable write access to read only registers for IP v2.3.3
Robin Murphy <robin.murphy@arm.com>
PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
Ondrej Zary <linux@zary.sk>
PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
Martin Kaiser <martin@kaiser.cx>
hwrng: imx-rngc - fix the timeout for init and self check
Siddh Raman Pant <code@siddh.me>
jfs: jfs_dmap: Validate db_l2nbperpage while mounting
Baokun Li <libaokun1@huawei.com>
ext4: only update i_reserved_data_blocks on successful block allocation
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_new_blocks
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: get block from bh in ext4_free_blocks for fast commit replay
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_clear_bb
Zhihao Cheng <chengzhihao1@huawei.com>
ext4: Fix reusing stale buffer heads from last failed mounting
Huacai Chen <chenhuacai@loongson.cn>
MIPS: Loongson: Fix cpu_probe_loongson() again
Gao Xiang <hsiangkao@linux.alibaba.com>
erofs: fix compact 4B support for 16k block size
Ekansh Gupta <quic_ekangupt@quicinc.com>
misc: fastrpc: Create fastrpc scalar with correct buffer count
Naveen N Rao <naveen@kernel.org>
powerpc: Fail build if using recordmcount with binutils v2.37
Florian Fainelli <florian.fainelli@broadcom.com>
net: bcmgenet: Ensure MDIO unregistration has clocks enabled
Arseniy Krasnov <AVKrasnov@sberdevices.ru>
mtd: rawnand: meson: fix unaligned DMA buffers handling
Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Only use special debounce behavior for GPIO 0
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Detect internal GPIO0 debounce handling
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Fix mistake in handling clearing pins at startup
Chao Yu <chao@kernel.org>
f2fs: fix to avoid NULL pointer dereference f2fs_write_end_io()
Ming Lei <ming.lei@redhat.com>
nvme-pci: fix DMA direction of unmapping integrity data
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: account for stab overhead in qfq_enqueue
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: refactor parsing of netlink parameters
Pedro Tammela <pctammela@mojatatu.com>
net/sched: make psched_mtu() RTNL-less safe
Dan Carpenter <dan.carpenter@linaro.org>
netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
Ido Schimmel <idosch@nvidia.com>
net/sched: flower: Ensure both minimum and maximum ports are specified
Randy Dunlap <rdunlap@infradead.org>
wifi: airo: avoid uninitialized warning in airo_get_rate()
Chunhai Guo <guochunhai@vivo.com>
erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
Björn Töpel <bjorn@rivosinc.com>
riscv, bpf: Fix inconsistent JIT image generation
Pu Lehui <pulehui@huawei.com>
bpf, riscv: Support riscv jit to provide bpf_line_info
Jisheng Zhang <jszhang@kernel.org>
riscv: bpf: Avoid breaking W^X
Jisheng Zhang <jszhang@kernel.org>
riscv: bpf: Move bpf_jit_alloc_exec() and bpf_jit_free_exec() to core
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix inserting of empty frame for launchtime
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix launchtime before start of cycle
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
platform/x86: wmi: Break possible infinite loop when parsing GUID
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: move variables
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: use guid_t and guid_equal()
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: remove unnecessary argument
Ziyang Xuan <william.xuanziyang@huawei.com>
ipv6/addrconf: fix a potential refcount underflow for idev
Jiasheng Jiang <jiasheng@iscas.ac.cn>
NTB: ntb_tool: Add check for devm_kcalloc
Yang Yingliang <yangyingliang@huawei.com>
NTB: ntb_transport: fix possible memory leak while device_register() fails
Yuan Can <yuancan@huawei.com>
ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
ntb: idt: Fix error handling in idt_pci_driver_init()
Eric Dumazet <edumazet@google.com>
udp6: fix udp6_ehashfn() typo
Kuniyuki Iwashima <kuniyu@amazon.com>
icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
Paolo Abeni <pabeni@redhat.com>
net: prevent skb corruption on frag list segmentation
Rafał Miłecki <rafal@milecki.pl>
net: bgmac: postpone turning IRQs off to avoid SoC hangs
Nitya Sunkad <nitya.sunkad@amd.com>
ionic: remove WARN_ON to prevent panic_on_warn
Junfeng Guo <junfeng.guo@intel.com>
gve: Set default duplex configuration to full
M A Ramdhan <ramdhan@starlabs.sg>
net/sched: cls_fw: Fix improper refcount update leads to use-after-free
Klaus Kudielka <klaus.kudielka@gmail.com>
net: mvneta: fix txq_map in case of txq_number==1
Dan Carpenter <dan.carpenter@linaro.org>
scsi: qla2xxx: Fix error code in qla2x00_start_sp()
Prasad Koya <prasad@arista.com>
igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
Vlad Buslov <vladbu@nvidia.com>
net/mlx5e: Check for NOT_READY flag state after locking
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix double free in mlx5e_destroy_flow_table
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Remove delay during TX ring configuration
Marek Vasut <marex@denx.de>
drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
Fabio Estevam <festevam@denx.de>
drm/panel: simple: Add connector_type for innolux_at043tn24
Linus Torvalds <torvalds@linux-foundation.org>
workqueue: clean up WORK_* constant types, clarify masking
Moritz Fischer <moritzf@google.com>
net: lan743x: Don't sleep in atomic context
Jens Axboe <axboe@kernel.dk>
io_uring: add reschedule point to handle_tw_list()
Andres Freund <andres@anarazel.de>
io_uring: Use io_schedule* in cqring wait
Michael Schmitz <schmitzmic@gmail.com>
block/partition: fix signedness issue for Amiga partitions
Paul E. McKenney <paulmck@kernel.org>
rcu-tasks: Simplify trc_read_check_handler() atomic operations
Paul E. McKenney <paulmck@kernel.org>
rcu-tasks: Mark ->trc_reader_special.b.need_qs data races
Paul E. McKenney <paulmck@kernel.org>
rcu-tasks: Mark ->trc_reader_nesting data races
Sherry Sun <sherry.sun@nxp.com>
tty: serial: fsl_lpuart: add earlycon for imx8ulp platform
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: netlink: send staged packets when setting initial private key
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: use saner cpu selection wrapping
Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
netfilter: nf_tables: do not ignore genmask when looking up chain by id
Florent Revest <revest@chromium.org>
netfilter: conntrack: Avoid nf_ct_helper_hash uses after free
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: fix scheduling-while-atomic splat
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: unbind non-anonymous set if rule construction fails
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: drop map element references from preparation phase
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: rename set element data activation/deactivation functions
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: reject unbound chain set before commit phase
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: reject unbound anonymous set before commit phase
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: add NFT_TRANS_PREPARE_ERROR to deal with bound set/chain
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: fix chain binding transaction logic
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: add rescheduling points during loop detection walks
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: use net_generic infra for transaction data
Geert Uytterhoeven <geert+renesas@glider.be>
sh: pgtable-3level: Fix cast to pointer from integer of different size
Michael Schmitz <schmitzmic@gmail.com>
block: add overflow checks for Amiga partition support
Gilad Reti <gilad.reti@gmail.com>
selftests/bpf: Add verifier test for PTR_TO_MEM spill
Lino Sanfilippo <l.sanfilippo@kunbus.com>
tpm, tpm_tis: Claim locality in interrupt handler
Amir Goldstein <amir73il@gmail.com>
fanotify: disallow mount/sb marks on kernel internal pseudo fs
Jan Kara <jack@suse.cz>
fs: no need to check source
Christian Marangi <ansuelsmth@gmail.com>
leds: trigger: netdev: Recheck NETDEV_LED_MODE_LINKUP on dev rename
Arnd Bergmann <arnd@arndb.de>
ARM: orion5x: fix d2net gpio initialization
Ricardo Ribalda Delgado <ribalda@chromium.org>
ASoC: mediatek: mt8173: Fix snd_soc_component_initialize error path
Ricardo Ribalda Delgado <ribalda@chromium.org>
ASoC: mediatek: mt8173: Fix irq error path
Filipe Manana <fdmanana@suse.com>
btrfs: fix race when deleting quota root from the dirty cow roots list
Matt Corallo <blnxfsl@bluematt.me>
btrfs: add handling for RAID1C23/DUP to btrfs_reduce_alloc_profile
Jan Kara <jack@suse.cz>
fs: Lock moved directories
Jan Kara <jack@suse.cz>
fs: Establish locking order for unrelated directories
Jan Kara <jack@suse.cz>
Revert "f2fs: fix potential corruption when moving a directory"
Jan Kara <jack@suse.cz>
ext4: Remove ext4 locking of moved directory
Thomas Weißschuh <linux@weissschuh.net>
fs: avoid empty option when generating legacy mount string
Fabian Frederick <fabf@skynet.be>
jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
Roberto Sassu <roberto.sassu@huawei.com>
shmem: use ramfs_kill_sb() for kill_sb method of ramfs-based tmpfs
Arnd Bergmann <arnd@arndb.de>
autofs: use flexible array in ioctl structure
Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
integrity: Fix possible multiple allocation in integrity_inode_get()
Kees Cook <keescook@chromium.org>
um: Use HOST_DIR for mrproper
Zheng Wang <zyytlz.wz@163.com>
bcache: Fix __bch_btree_node_alloc to make the failure behavior consistent
Zheng Wang <zyytlz.wz@163.com>
bcache: Remove unnecessary NULL point check in node allocations
Mingzhe Zou <mingzhe.zou@easystack.cn>
bcache: fixup btree_cache_wait list damage
Chevron Li <chevron.li@bayhubtech.com>
mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is used.
Ulf Hansson <ulf.hansson@linaro.org>
mmc: mmci: Set PROBE_PREFER_ASYNCHRONOUS
Robert Marko <robimarko@gmail.com>
mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
Robert Marko <robimarko@gmail.com>
mmc: core: disable TRIM on Kingston EMMC04G-M627
Jens Axboe <axboe@kernel.dk>
io_uring: wait interruptibly for request completions on exit
Dai Ngo <dai.ngo@oracle.com>
NFSD: add encoding of op_recall flag for write delegation
Shuai Jiang <d202180596@hust.edu.cn>
i2c: qup: Add missing unwind goto in qup_i2c_probe()
Takashi Iwai <tiwai@suse.de>
ALSA: jack: Fix mutex call in snd_jack_report()
Robert Hancock <robert.hancock@calian.com>
i2c: xiic: Don't try to handle more interrupt events after error
Marek Vasut <marex@denx.de>
i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()
Danila Chernetsov <listdansp@mail.ru>
apparmor: fix missing error check for rhashtable_insert_fast
Artur Rojek <contact@artur-rojek.eu>
sh: dma: Fix DMA channel offset calculation
Thorsten Winkler <twinkler@linux.ibm.com>
s390/qeth: Fix vipa deletion
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: tag_sja1105: fix MAC DA patching from meta frames
Guillaume Nault <gnault@redhat.com>
pptp: Fix fib lookup calls.
Lin Ma <linma@zju.edu.cn>
net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
Ilya Maximets <i.maximets@ovn.org>
xsk: Honor SO_BINDTODEVICE on bind
Eric Dumazet <edumazet@google.com>
tcp: annotate data races in __tcp_oow_rate_limited()
Vladimir Oltean <vladimir.oltean@nxp.com>
net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode
Randy Dunlap <rdunlap@infradead.org>
powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-af: Fix mapping for NIX block from CGX connection
Chao Yu <chao@kernel.org>
f2fs: fix error path handling in truncate_dnode()
Nishanth Menon <nm@ti.com>
mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0
Jonas Gorski <jonas.gorski@gmail.com>
spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
Pawel Dembicki <paweldembicki@gmail.com>
net: dsa: vsc73xx: fix MTU configuration
Tobias Heider <me@tobhe.de>
Add MODULE_FIRMWARE() for FIRMWARE_TG357766.
Chengfeng Ye <dg573847474@gmail.com>
sctp: fix potential deadlock on &net->sctp.addr_wq_lock
Randy Dunlap <rdunlap@infradead.org>
media: cec: i2c: ch7322: also select REGMAP
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
Marek Vasut <marex@denx.de>
pwm: sysfs: Do not apply state to already disabled PWMs
Fancy Fang <chen.fang@nxp.com>
pwm: imx-tpm: force 'real_period' to be zero in suspend
Claudiu Beznea <claudiu.beznea@microchip.com>
phy: tegra: xusb: check return value of devm_kzalloc()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mfd: stmpe: Only disable the regulators if they are enabled
Pierre Morel <pmorel@linux.ibm.com>
KVM: s390: vsie: fix the length of APCB bitmap
Amelie Delaunay <amelie.delaunay@foss.st.com>
mfd: stmfx: Nullify stmfx->vdd in case of error
Amelie Delaunay <amelie.delaunay@foss.st.com>
mfd: stmfx: Fix error path in stmfx_chip_init
Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation
Tony Lindgren <tony@atomide.com>
serial: 8250_omap: Use force_suspend and resume for system suspend
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Revert "usb: common: usb-conn-gpio: Set last role to unknown before initial detection"
Jiasheng Jiang <jiasheng@iscas.ac.cn>
mfd: intel-lpss: Add missing check for platform_get_resource
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc3-meson-g12a: Fix an error handling path in dwc3_meson_g12a_probe()
Prashanth K <quic_prashk@quicinc.com>
usb: common: usb-conn-gpio: Set last role to unknown before initial detection
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc3: qcom: Fix an error handling path in dwc3_qcom_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc3: qcom: Release the correct resources in dwc3_qcom_remove()
Nico Boehr <nrb@linux.ibm.com>
KVM: s390: fix KVM_S390_GET_CMMA_BITS for GFNs in memslot holes
Dan Carpenter <dan.carpenter@linaro.org>
media: atomisp: gmin_platform: fix out_len in gmin_get_config_dsm_var()
Rikard Falkeborn <rikard.falkeborn@gmail.com>
media: venus: helpers: Fix ALIGN() of non power of two
Stephan Gerhold <stephan@gerhold.net>
mfd: rt5033: Drop rt5033-battery sub-device
James Clark <james.clark@arm.com>
coresight: Fix loss of connection info when a module is unloaded
Muchun Song <songmuchun@bytedance.com>
kernfs: fix missing kernfs_idr_lock to remove an ID from the IDR
John Ogness <john.ogness@linutronix.de>
serial: 8250: lock port for UART_IER access in omap8250_irq()
John Ogness <john.ogness@linutronix.de>
serial: 8250: lock port for stop_rx() in omap8250_irq()
Arnd Bergmann <arnd@arndb.de>
usb: hide unused usbfs_notify_suspend/resume functions
Li Yang <lidaxian@hust.edu.cn>
usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
extcon: Fix kernel doc of property capability fields to avoid warnings
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
extcon: Fix kernel doc of property fields to avoid warnings
Prashanth K <quic_prashk@quicinc.com>
usb: gadget: u_serial: Add null pointer check in gserial_suspend
Vladislav Efanov <VEfanov@ispras.ru>
usb: dwc3: qcom: Fix potential memory leak
Robert Marko <robimarko@gmail.com>
clk: qcom: ipq6018: fix networking resets
Robert Marko <robimarko@gmail.com>
clk: qcom: reset: support resetting multiple bits
Stephan Gerhold <stephan.gerhold@kernkonzept.com>
clk: qcom: reset: Allow specifying custom reset delay
Duoming Zhou <duoming@zju.edu.cn>
media: usb: siano: Fix warning due to null work_func_t function pointer
Marek Vasut <marex@denx.de>
media: videodev2.h: Fix struct v4l2_input tuner index comment
Daniil Dulov <d.dulov@aladdin.ru>
media: usb: Check az6007_read() return value
Mantas Pucka <mantas@8devices.com>
clk: qcom: gcc-ipq6018: Use floor ops for sdcc clocks
Tony Lindgren <tony@atomide.com>
serial: 8250: omap: Fix freeing of resources on failed register
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
sh: j2: Use ioremap() to translate device tree address into kernel memory
Dan Carpenter <dan.carpenter@oracle.com>
w1: fix loop in w1_fini()
Stefan Wahren <stefan.wahren@i2se.com>
w1: w1_therm: fix locking behavior in convert_t
Ding Hui <dinghui@sangfor.com.cn>
SUNRPC: Fix UAF in svc_tcp_listen_data_ready()
Michael Schmitz <schmitzmic@gmail.com>
block: change all __u32 annotations to __be32 in affs_hardblocks.h
Michael Schmitz <schmitzmic@gmail.com>
block: fix signed int overflow in Amiga partition support
EJ Hsu <ejh@nvidia.com>
phy: tegra: xusb: Clear the driver reference in usb-phy dev
Krishna Kurapati <quic_kriskura@quicinc.com>
usb: dwc3: gadget: Propagate core init errors to UDC during pullup
Davide Tronchin <davide.tronchin.94@gmail.com>
USB: serial: option: add LARA-R6 01B PIDs
Jens Axboe <axboe@kernel.dk>
io_uring: ensure IOPOLL locks around deferred work
Martin Kaiser <martin@kaiser.cx>
hwrng: st - keep clock enabled while hwrng is registered
Dan Williams <dan.j.williams@intel.com>
dax: Introduce alloc_dev_dax_id()
Dan Williams <dan.j.williams@intel.com>
dax: Fix dax_mapping_release() use after free
Olga Kornievskaia <kolga@netapp.com>
NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
Masahiro Yamada <masahiroy@kernel.org>
ARC: define ASM_NL and __ALIGN(_STR) outside #ifdef __ASSEMBLY__ guard
Dan Carpenter <dan.carpenter@linaro.org>
modpost: fix off by one in is_executable_section()
Arnd Bergmann <arnd@arndb.de>
crypto: marvell/cesa - Fix type mismatch warning
Masahiro Yamada <masahiroy@kernel.org>
modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24}
Masahiro Yamada <masahiroy@kernel.org>
modpost: fix section mismatch message for R_ARM_ABS32
Randy Dunlap <rdunlap@infradead.org>
crypto: nx - fix build warnings when DEBUG_FS is not enabled
Herbert Xu <herbert@gondor.apana.org.au>
hwrng: virtio - Fix race on data_avail and actual data
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - always add a pending request
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - don't waste entropy
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - don't wait on cleanup
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - add an internal buffer
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
powerpc/mm/dax: Fix the condition when checking if altmap vmemap can cross-boundary
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
powerpc/book3s64/mm: Fix DirectMap stats in /proc/meminfo
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
mm: rename p4d_page_vaddr to p4d_pgtable and make it return pud_t *
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
mm: rename pud_page_vaddr to pud_pgtable and make it return pmd_t *
Colin Ian King <colin.i.king@gmail.com>
powerpc/powernv/sriov: perform null check on iov before dereferencing iov
Claudiu Beznea <claudiu.beznea@microchip.com>
pinctrl: at91-pio4: check return value of devm_kasprintf()
Namhyung Kim <namhyung@kernel.org>
perf dwarf-aux: Fix off-by-one in die_get_varname()
Arnaldo Carvalho de Melo <acme@redhat.com>
perf script: Fix allocation of evsel->priv related to per-event dump files
Arnaldo Carvalho de Melo <acme@redhat.com>
perf script: Fixup 'struct evsel_script' method prefix
Christophe Leroy <christophe.leroy@csgroup.eu>
kcsan: Don't expect 64 bits atomic builtins from 32 bits architectures
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
pinctrl: cherryview: Return correct value if pin in push-pull mode
Arnaldo Carvalho de Melo <acme@redhat.com>
perf bench: Add missing setlocale() call to allow usage of %'d style formatting
Sohaib Mohamed <sohaib.amhmd@gmail.com>
perf bench: Use unbuffered output when pipe/tee'ing to a file
Sui Jingfeng <suijingfeng@loongson.cn>
PCI: Add pci_clear_master() stub for non-CONFIG_PCI
Junyan Ye <yejunyan@hust.edu.cn>
PCI: ftpci100: Release the clock resources
Rongguang Wei <weirongguang@kylinos.cn>
PCI: pciehp: Cancel bringup sequence if card is not present
Yuchen Yang <u202114568@hust.edu.cn>
scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
Ding Hui <dinghui@sangfor.com.cn>
PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
pinctrl: bcm2835: Handle gpiochip_add_pin_range() errors
Jinhong Zhu <jinhongzhu@hust.edu.cn>
scsi: qedf: Fix NULL dereference in error handling
Siddharth Vadapalli <s-vadapalli@ti.com>
PCI: cadence: Fix Gen2 Link Retraining process
Claudiu Beznea <claudiu.beznea@microchip.com>
ASoC: imx-audmix: check return value of devm_kasprintf()
Amir Goldstein <amir73il@gmail.com>
ovl: update of dentry revalidate flags after copy up
Alexey Romanov <avromanov@sberdevices.ru>
drivers: meson: secure-pwrc: always enable DMA domain
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: ti: clkctrl: check return value of kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: keystone: sci-clk: check return value of kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: si5341: free unused memory on probe failure
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: si5341: check return value of {devm_}kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: si5341: return error if one synth clock registration fails
Robert Hancock <robert.hancock@calian.com>
clk: si5341: Add sysfs properties to allow checking/resetting device faults
Robert Hancock <robert.hancock@calian.com>
clk: si5341: Allow different output VDD_SEL values
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: cdce925: check return value of kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: vc5: check memory returned by kasprintf()
Bjorn Andersson <quic_bjorande@quicinc.com>
drm/msm/dp: Free resources after unregistering them
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: do not enable color-management if DSPPs are not available
Su Hui <suhui@nfschina.com>
ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer
Yuan Can <yuancan@huawei.com>
clk: tegra: tegra124-emc: Fix potential memory leak
Yuxing Liu <lyx2022@hust.edu.cn>
clk: imx: clk-imx8mp: improve error handling in imx8mp_clocks_probe()
Hao Luo <m202171776@hust.edu.cn>
clk: imx: clk-imx8mn: fix memory leak in imx8mn_clocks_probe
Kashyap Desai <kashyap.desai@broadcom.com>
RDMA/bnxt_re: Avoid calling wake_up threads from spin_lock context
Kashyap Desai <kashyap.desai@broadcom.com>
RDMA/bnxt_re: wraparound mbox producer index
Chia-I Wu <olvaffe@gmail.com>
amdgpu: validate offset_in_bo of drm_amdgpu_gem_va
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
drm/radeon: fix possible division-by-zero errors
Daniil Dulov <d.dulov@aladdin.ru>
drm/amdkfd: Fix potential deallocation of previously deallocated memory.
Christian Lamparter <chunkeey@gmail.com>
ARM: dts: BCM5301X: fix duplex-full => full-duplex
Guenter Roeck <linux@roeck-us.net>
hwmon: (pmbus/adm1275) Fix problems with temperature monitoring on ADM1272
Potin Lai <potin.lai@quantatw.com>
hwmon: (adm1275) Allow setting sample averaging
Chu Lin <linchuyuan@google.com>
hwmon: (adm1275) enable adm1272 temperature reporting
Tim Harvey <tharvey@gateworks.com>
hwmon: (gsc-hwmon) fix fan pwm temperature scaling
Olivier Moysan <olivier.moysan@foss.st.com>
ARM: dts: stm32: fix i2s endpoint format property for stm32mp15xx-dkx
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Fix audio routing on STM32MP15xx DHCOM PDK2
Keerthy <j-keerthy@ti.com>
arm64: dts: ti: k3-j7200: Fix physical address of pin
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe()
Wolfram Sang <wsa+renesas@sang-engineering.com>
arm64: dts: renesas: ulcb-kf: Remove flow control for SCIF1
Geert Uytterhoeven <geert+renesas@glider.be>
ARM: dts: iwg20d-q7-common: Fix backlight pwm specifier
Chengchang Tang <tangchengchang@huawei.com>
RDMA/hns: Fix hns_roce_table_get return value
Xi Wang <wangxi11@huawei.com>
RDMA/hns: Clean the hardware related code for HEM
Weihang Li <liweihang@huawei.com>
RDMA/hns: Use refcount_t APIs for HEM
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Fix coding style issues
Jason Gunthorpe <jgg@ziepe.ca>
RDMA: Remove uverbs_ex_cmd_mask values that are linked to functions
Brendan Cunningham <bcunningham@cornelisnetworks.com>
IB/hfi1: Fix wrong mmu_node used for user SDMA packet after invalidate
Patrick Kelsey <pat.kelsey@cornelisnetworks.com>
IB/hfi1: Fix sdma.h tx->num_descs off-by-one errors
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
IB/hfi1: Use bitmap_zalloc() when applicable
Randy Dunlap <rdunlap@infradead.org>
soc/fsl/qe: fix usb.c build errors
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
ARM: dts: meson8: correct uart_B and uart_C clock references
Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
ASoC: es8316: Do not set rate constraints for unsupported MCLKs
Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
ASoC: es8316: Increment max value for ALC Capture Target Volume control
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
memory: brcmstb_dpfe: fix testing array offset after use
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Shorten the AV96 HDMI sound card name
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: apq8096: fix fixed regulator name property
Arnd Bergmann <arnd@arndb.de>
ARM: omap2: fix missing tick_broadcast() prototype
Arnd Bergmann <arnd@arndb.de>
ARM: ep93xx: fix missing-prototype warnings
Dario Binacchi <dario.binacchi@amarulasolutions.com>
drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: msm8996: correct camss unit address
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: msm8994: correct SPMI unit address
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: msm8916: correct camss unit address
Tony Lindgren <tony@atomide.com>
ARM: dts: gta04: Move model property out of pinctrl node
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Fix to remove an unnecessary log
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Remove a redundant check inside bnxt_re_update_gid
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Use unique names while registering interrupts
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Fix to remove unnecessary return labels
Selvin Xavier <selvin.xavier@broadcom.com>
RDMA/bnxt_re: Disable/kill tasklet only if it is enabled
Robert Marko <robert.marko@sartura.hr>
arm64: dts: microchip: sparx5: do not use PSCI on reference boards
Tony Lindgren <tony@atomide.com>
bus: ti-sysc: Fix dispc quirk masking bool variables
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Move ethernet MAC EEPROM from SoM to carrier boards
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/panel: sharp-ls043t1le01: adjust mode settings
XuDong Liu <m202071377@hust.edu.cn>
drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
Marek Vasut <marex@denx.de>
Input: adxl34x - do not hardcode interrupt trigger type
hfdevel@gmx.net <hfdevel@gmx.net>
ARM: dts: meson8b: correct uart_B and uart_C clock references
Rafał Miłecki <rafal@milecki.pl>
ARM: dts: BCM5301X: Drop "clock-names" from the SPI node
Luc Ma <luc@sietium.com>
drm/vram-helper: fix function names in vram helper doc
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix THS_TRAILCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix TXTAGOCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix THS_ZEROCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix TCLK_TRAILCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: Add atomic_get_input_bus_fmts() implementation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix TCLK_ZEROCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix PLL target frequency
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix PLL parameters computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: always enable HS video mode
Luca Weiss <luca@z3ntu.xyz>
Input: drv260x - sleep between polling GO bit
Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
drm/amd/display: Explicitly specify update type per plane info change
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
radeon: avoid double free in ci_dpm_init()
Kuniyuki Iwashima <kuniyu@amazon.com>
netlink: Add __sock_i_ino() for __netlink_diag_dump().
Cambda Zhu <cambda@linux.alibaba.com>
ipvlan: Fix return value of ipvlan_queue_xmit()
Ilia.Gavrilov <Ilia.Gavrilov@infotecs.ru>
netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return value.
Florian Westphal <fw@strlen.de>
netfilter: conntrack: dccp: copy entire header to stack buffer, not just basic one
Jeremy Sowden <jeremy@azazel.net>
lib/ts_bm: reset initial match offset for every block of text
Lin Ma <linma@zju.edu.cn>
net: nfc: Fix use-after-free caused by nfc_llcp_find_local
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
nfc: llcp: simplify llcp_sock_connect() error paths
Edward Cree <ecree.xilinx@gmail.com>
sfc: fix crash when reading stats while NIC is resetting
Maxim Kochetkov <fido_max@inbox.ru>
net: axienet: Move reset before 64-bit DMA detection
Kuniyuki Iwashima <kuniyu@amazon.com>
gtp: Fix use-after-free in __gtp_encap_destroy().
Sabrina Dubroca <sd@queasysnail.net>
selftests: rtnetlink: remove netdevsim device after ipsec offload test
Eric Dumazet <edumazet@google.com>
netlink: do not hard code device address lenth in fdb dumps
Eric Dumazet <edumazet@google.com>
netlink: fix potential deadlock in netlink_set_err()
Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
net: stmmac: fix double serdes powerdown
Vinicius Costa Gomes <vinicius.gomes@intel.com>
igc: Fix race condition in PTP tx code
Dmitry Antipov <dmantipov@yandex.ru>
wifi: ath9k: convert msecs to jiffies where needed
Benjamin Berg <benjamin.berg@intel.com>
wifi: cfg80211: rewrite merging of inherited elements
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: pull from TXQs with softirqs disabled
Edwin Peer <edwin.peer@broadcom.com>
rtnetlink: extend RTEXT_FILTER_SKIP_STATS to IFLA_VF_INFO
Remi Pommarel <repk@triplefau.lt>
wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
Arnd Bergmann <arnd@arndb.de>
memstick r592: make memstick_debug_get_tpc_name() static
Zhen Lei <thunder.leizhen@huawei.com>
kexec: fix a memory leak in crash_shrink_memory()
Douglas Anderson <dianders@chromium.org>
watchdog/perf: more properly prevent false positives with turbo modes
Douglas Anderson <dianders@chromium.org>
watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct config
Marek Vasut <marex@denx.de>
wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown
Marek Vasut <marex@denx.de>
wifi: rsi: Do not configure WoWlan in shutdown hook if not enabled
Fedor Pchelkin <pchelkin@ispras.ru>
wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: ray_cs: Fix an error handling path in ray_probe()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
wifi: ray_cs: Drop useless status variable in parse_addr()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
wifi: ray_cs: Utilize strnlen() in parse_addr()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: wl3501_cs: Fix an error handling path in wl3501_probe()
Jakub Kicinski <kuba@kernel.org>
wl3501_cs: use eth_hw_addr_set()
Jakub Kicinski <kuba@kernel.org>
net: create netdev->dev_addr assignment helpers
Lee Jones <lee.jones@linaro.org>
wl3501_cs: Fix misspelling and provide missing documentation
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: atmel: Fix an error handling path in atmel_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: orinoco: Fix an error handling path in orinoco_cs_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: orinoco: Fix an error handling path in spectrum_cs_probe()
Geert Uytterhoeven <geert+renesas@glider.be>
regulator: core: Streamline debugfs operations
Geert Uytterhoeven <geert+renesas@glider.be>
regulator: core: Fix more error checking for debugfs_create_dir()
Alan Maguire <alan.maguire@oracle.com>
bpftool: JIT limited misreported as negative value on aarch64
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
nfc: llcp: fix possible use of uninitialized variable in nfc_llcp_send_connect()
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
nfc: constify several pointers to u8, char and sk_buff
Andrii Nakryiko <andrii@kernel.org>
libbpf: fix offsetof() and container_of() to work with CO-RE
Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
sctp: add bpf_bypass_getsockopt proto callback
Stanislav Fomichev <sdf@google.com>
bpf: Remove extra lock_sock for TCP_ZEROCOPY_RECEIVE
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: mwifiex: Fix the size of a memory allocation in mwifiex_ret_802_11_scan()
Amisha Patel <amisha.patel@microchip.com>
wifi: wilc1000: fix for absent RSN capabilities WFA testcase
Vijaya Krishna Nivarthi <quic_vnivarth@quicinc.com>
spi: spi-geni-qcom: Correct CS_TOGGLE bit in SPI_TRANS_CFG
Pengcheng Yang <yangpc@wangsu.com>
samples/bpf: Fix buffer overflow in tcp_basertt
Fedor Pchelkin <pchelkin@ispras.ru>
wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx
Peter Seiderer <ps.report@gmx.net>
wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation
Jesper Dangaard Brouer <brouer@redhat.com>
igc: Enable and fix RX hash usage by netstack
Jiasheng Jiang <jiasheng@iscas.ac.cn>
pstore/ram: Add check for kstrdup
Roberto Sassu <roberto.sassu@huawei.com>
ima: Fix build warnings
Roberto Sassu <roberto.sassu@huawei.com>
evm: Complete description of evm_inode_setattr()
Juergen Gross <jgross@suse.com>
x86/mm: Fix __swp_entry_to_pte() for Xen PV guests
Ravi Bangoria <ravi.bangoria@amd.com>
perf/ibs: Fix interface via core pmu events
Qiuxu Zhuo <qiuxu.zhuo@intel.com>
rcu/rcuscale: Stop kfree_scale_thread thread(s) after unloading rcuscale
Qiuxu Zhuo <qiuxu.zhuo@intel.com>
rcu/rcuscale: Move rcu_scale_*() after kfree_scale_cleanup()
Paul E. McKenney <paulmck@kernel.org>
rcuscale: Move shutdown from wait_event() to wait_event_idle()
Li Zhijian <zhijianx.li@intel.com>
rcuscale: Always log error message
Jiangong.Han <jiangong.han@windriver.com>
rcuscale: Console output claims too few grace periods
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
thermal/drivers/sun8i: Fix some error handling paths in sun8i_ths_probe()
Tero Kristo <tero.kristo@linux.intel.com>
cpufreq: intel_pstate: Fix energy_performance_preference for passive
Arnd Bergmann <arnd@arndb.de>
ARM: 9303/1: kprobes: avoid missing-declaration warnings
Zhang Rui <rui.zhang@intel.com>
powercap: RAPL: Fix CONFIG_IOSF_MBI dependency
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix DTC reset
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
PM: domains: fix integer overflow issues in genpd_parse_state()
Feng Mingxi <m202271825@hust.edu.cn>
clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
tracing/timer: Add missing hrtimer modes to decode_hrtimer_mode().
Thomas Gleixner <tglx@linutronix.de>
posix-timers: Prevent RT livelock in itimer_delete()
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
irqchip/jcore-aic: Fix missing allocation of IRQ descriptors
Marc Zyngier <maz@kernel.org>
irqchip/jcore-aic: Kill use of irq_create_strict_mappings()
Li Nan <linan122@huawei.com>
md/raid10: fix io loss while replacement replace rdev
Li Nan <linan122@huawei.com>
md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request
Li Nan <linan122@huawei.com>
md/raid10: fix wrong setting of max_corr_read_errors
Li Nan <linan122@huawei.com>
md/raid10: fix overflow of md/safe_mode_delay
Li Nan <linan122@huawei.com>
md/raid10: check slab-out-of-bounds in md_bitmap_get_counter
Li Nan <linan122@huawei.com>
blk-iocost: use spin_lock_irqsave in adjust_inuse_and_calc_cost
Shawn Wang <shawnwang@linux.alibaba.com>
x86/resctrl: Only show tasks' pid in current pid namespace
Arnd Bergmann <arnd@arndb.de>
fs: pipe: reveal missing function protoypes
Finn Thain <fthain@linux-m68k.org>
nubus: Partially revert proc_create_single_data() conversion
Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
drm/amdgpu: Validate VM ioctl flags.
Ahmed S. Darwish <darwi@linutronix.de>
scripts/tags.sh: Resolve gtags empty index generation
Ricardo Cañuelo <ricardo.canuelo@collabora.com>
Revert "thermal/drivers/mediatek: Use devm_of_iomap to avoid resource leak in mtk_thermal_probe"
Mike Hommey <mh@glandium.org>
HID: logitech-hidpp: add HIDPP_QUIRK_DELAYED_INIT for the T651.
Jason Gerecke <jason.gerecke@wacom.com>
HID: wacom: Use ktime_t rather than int when dealing with timestamps
Zheng Wang <zyytlz.wz@163.com>
fbdev: imsttfb: Fix use after free bug in imsttfb_probe
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
video: imsttfb: check for ioremap() failures
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: isotp_sendmsg(): fix return error fix on TX path
Thomas Gleixner <tglx@linutronix.de>
x86/smp: Use dedicated cache-line for mwait_play_dead()
Tsuchiya Yuto <kitakar@gmail.com>
media: atomisp: fix "variable dereferenced before check 'asd'"
-------------
Diffstat:
Documentation/filesystems/autofs-mount-control.rst | 2 +-
Documentation/filesystems/autofs.rst | 2 +-
Documentation/filesystems/directory-locking.rst | 26 +-
Documentation/networking/af_xdp.rst | 9 +
Documentation/networking/ip-sysctl.rst | 25 +
Makefile | 4 +-
arch/alpha/include/asm/pgtable.h | 8 +-
arch/arc/include/asm/linkage.h | 8 +-
arch/arm/boot/dts/bcm53015-meraki-mr26.dts | 2 +-
arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 2 +-
arch/arm/boot/dts/bcm5301x.dtsi | 1 -
arch/arm/boot/dts/iwg20d-q7-common.dtsi | 2 +-
arch/arm/boot/dts/meson8.dtsi | 4 +-
arch/arm/boot/dts/meson8b.dtsi | 4 +-
arch/arm/boot/dts/omap3-gta04a5one.dts | 4 +-
arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi | 11 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 8 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi | 6 -
arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 2 +-
arch/arm/include/asm/pgtable-3level.h | 2 +-
arch/arm/mach-ep93xx/timer-ep93xx.c | 3 +-
arch/arm/mach-omap2/board-generic.c | 1 +
arch/arm/mach-orion5x/board-dt.c | 3 +
arch/arm/mach-orion5x/common.h | 6 +
arch/arm/probes/kprobes/checkers-common.c | 2 +-
arch/arm/probes/kprobes/core.c | 2 +-
arch/arm/probes/kprobes/opt-arm.c | 2 -
arch/arm/probes/kprobes/test-core.c | 2 +-
arch/arm/probes/kprobes/test-core.h | 4 +
arch/arm64/boot/dts/microchip/sparx5.dtsi | 2 +-
.../boot/dts/microchip/sparx5_pcb_common.dtsi | 12 +
arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts | 4 +-
arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8994.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8996.dtsi | 2 +-
arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 3 +-
.../boot/dts/ti/k3-j7200-common-proc-board.dts | 28 +-
arch/arm64/include/asm/exception.h | 5 -
arch/arm64/include/asm/pgtable.h | 8 +-
arch/arm64/mm/mmu.c | 4 +-
arch/ia64/include/asm/pgtable.h | 4 +-
arch/m68k/include/asm/motorola_pgtable.h | 2 +-
arch/mips/include/asm/pgtable-64.h | 8 +-
arch/mips/kernel/cpu-probe.c | 9 +-
arch/parisc/include/asm/pgtable.h | 4 +-
arch/powerpc/Kconfig.debug | 2 +-
arch/powerpc/Makefile | 8 +
arch/powerpc/include/asm/book3s/64/pgtable.h | 11 +-
arch/powerpc/include/asm/nohash/64/pgtable-4k.h | 6 +-
arch/powerpc/include/asm/nohash/64/pgtable.h | 6 +-
arch/powerpc/mm/book3s64/radix_pgtable.c | 40 +-
arch/powerpc/mm/init_64.c | 2 +-
arch/powerpc/mm/pgtable_64.c | 4 +-
arch/powerpc/platforms/powernv/pci-sriov.c | 6 +-
arch/riscv/include/asm/pgtable-64.h | 4 +-
arch/riscv/net/bpf_jit.h | 5 +-
arch/riscv/net/bpf_jit_comp64.c | 13 -
arch/riscv/net/bpf_jit_core.c | 29 +-
arch/s390/Makefile | 1 +
arch/s390/kvm/kvm-s390.c | 4 +
arch/s390/kvm/vsie.c | 6 +-
arch/sh/drivers/dma/dma-sh.c | 37 +-
arch/sh/include/asm/pgtable-3level.h | 4 +-
arch/sh/kernel/cpu/sh2/probe.c | 2 +-
arch/sparc/include/asm/pgtable_32.h | 6 +-
arch/sparc/include/asm/pgtable_64.h | 10 +-
arch/um/Makefile | 2 +-
arch/um/include/asm/pgtable-3level.h | 2 +-
arch/x86/events/amd/core.c | 2 +-
arch/x86/events/amd/ibs.c | 53 +-
arch/x86/include/asm/perf_event.h | 2 +
arch/x86/include/asm/pgtable.h | 8 +-
arch/x86/include/asm/pgtable_64.h | 4 +-
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 8 +-
arch/x86/kernel/smpboot.c | 24 +-
arch/x86/mm/init_64.c | 4 +-
arch/x86/mm/pat/set_memory.c | 4 +-
arch/x86/mm/pgtable.c | 2 +-
arch/xtensa/platforms/iss/network.c | 2 +-
block/blk-iocost.c | 7 +-
block/partitions/amiga.c | 104 +++-
drivers/acpi/button.c | 9 +
drivers/acpi/video_detect.c | 16 +
drivers/base/power/domain.c | 6 +-
drivers/base/regmap/regmap-i2c.c | 8 +-
drivers/base/regmap/regmap-spi-avmm.c | 2 +-
drivers/base/regmap/regmap.c | 6 +-
drivers/block/nbd.c | 3 +-
drivers/bus/ti-sysc.c | 4 +-
drivers/char/hw_random/imx-rngc.c | 6 +-
drivers/char/hw_random/st-rng.c | 21 +-
drivers/char/hw_random/virtio-rng.c | 86 ++-
drivers/char/tpm/tpm_tis_core.c | 2 +
drivers/char/tpm/tpm_vtpm_proxy.c | 30 +-
drivers/clk/clk-cdce925.c | 12 +
drivers/clk/clk-si5341.c | 242 +++++++-
drivers/clk/clk-versaclock5.c | 29 +
drivers/clk/imx/clk-imx8mn.c | 8 +-
drivers/clk/imx/clk-imx8mp.c | 24 +-
drivers/clk/keystone/sci-clk.c | 2 +
drivers/clk/qcom/gcc-ipq6018.c | 34 +-
drivers/clk/qcom/reset.c | 8 +-
drivers/clk/qcom/reset.h | 2 +
drivers/clk/tegra/clk-tegra124-emc.c | 2 +
drivers/clk/ti/clkctrl.c | 7 +
drivers/clocksource/timer-cadence-ttc.c | 19 +-
drivers/cpufreq/intel_pstate.c | 2 +
drivers/crypto/marvell/cesa/cipher.c | 2 +-
drivers/crypto/nx/Makefile | 2 +-
drivers/crypto/nx/nx.h | 4 +-
drivers/dax/bus.c | 61 +-
drivers/dax/dax-private.h | 4 +-
drivers/extcon/extcon.c | 8 +
drivers/firmware/stratix10-svc.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 20 +-
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 13 +-
drivers/gpu/drm/amd/display/dc/core/dc.c | 3 -
drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 +-
drivers/gpu/drm/bridge/tc358768.c | 93 ++-
drivers/gpu/drm/drm_atomic.c | 11 +-
drivers/gpu/drm/drm_atomic_helper.c | 11 +-
drivers/gpu/drm/drm_client_modeset.c | 6 +
drivers/gpu/drm/drm_gem_vram_helper.c | 6 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 5 +-
drivers/gpu/drm/msm/dp/dp_display.c | 2 +-
drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 11 +-
drivers/gpu/drm/panel/panel-simple.c | 6 +-
drivers/gpu/drm/radeon/ci_dpm.c | 28 +-
drivers/gpu/drm/radeon/cypress_dpm.c | 8 +-
drivers/gpu/drm/radeon/ni_dpm.c | 8 +-
drivers/gpu/drm/radeon/rv740_dpm.c | 8 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 +-
drivers/gpu/drm/sun4i/sun4i_tcon.c | 19 +-
drivers/hid/hid-logitech-hidpp.c | 2 +-
drivers/hid/wacom_wac.c | 6 +-
drivers/hid/wacom_wac.h | 2 +-
drivers/hwmon/gsc-hwmon.c | 6 +-
drivers/hwmon/pmbus/adm1275.c | 94 ++-
drivers/hwtracing/coresight/coresight-core.c | 9 +-
drivers/i2c/busses/i2c-qup.c | 21 +-
drivers/i2c/busses/i2c-xiic.c | 39 +-
drivers/iio/adc/meson_saradc.c | 2 +-
drivers/infiniband/core/cma.c | 23 +
drivers/infiniband/core/cma_priv.h | 1 +
drivers/infiniband/core/device.c | 11 +
drivers/infiniband/core/uverbs_cmd.c | 2 +-
drivers/infiniband/hw/bnxt_re/main.c | 20 +-
drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40 +-
drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2 +-
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c | 46 +-
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h | 1 +
drivers/infiniband/hw/efa/efa_main.c | 3 -
drivers/infiniband/hw/hfi1/ipoib_tx.c | 4 +-
drivers/infiniband/hw/hfi1/mmu_rb.c | 101 +--
drivers/infiniband/hw/hfi1/mmu_rb.h | 3 +
drivers/infiniband/hw/hfi1/sdma.c | 27 +-
drivers/infiniband/hw/hfi1/sdma.h | 62 +-
drivers/infiniband/hw/hfi1/sdma_txreq.h | 2 +
drivers/infiniband/hw/hfi1/user_sdma.c | 145 ++---
drivers/infiniband/hw/hfi1/user_sdma.h | 1 -
drivers/infiniband/hw/hfi1/vnic_sdma.c | 4 +-
drivers/infiniband/hw/hns/hns_roce_cmd.c | 27 +-
drivers/infiniband/hw/hns/hns_roce_cmd.h | 4 +-
drivers/infiniband/hw/hns/hns_roce_cq.c | 2 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 2 -
drivers/infiniband/hw/hns/hns_roce_hem.c | 131 +---
drivers/infiniband/hw/hns/hns_roce_hem.h | 15 +-
drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 93 ++-
drivers/infiniband/hw/hns/hns_roce_hw_v1.h | 7 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 9 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 6 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 8 +-
drivers/infiniband/hw/hns/hns_roce_mr.c | 4 +-
drivers/infiniband/hw/hns/hns_roce_qp.c | 2 +-
drivers/infiniband/hw/hns/hns_roce_srq.c | 1 -
drivers/infiniband/hw/mlx4/main.c | 14 +-
drivers/infiniband/hw/mlx5/main.c | 14 +-
drivers/input/misc/adxl34x.c | 3 +-
drivers/input/misc/drv260x.c | 1 +
drivers/irqchip/irq-jcore-aic.c | 11 +-
drivers/leds/trigger/ledtrig-netdev.c | 3 +
drivers/mailbox/ti-msgmgr.c | 12 +-
drivers/md/bcache/btree.c | 25 +-
drivers/md/bcache/btree.h | 1 +
drivers/md/bcache/super.c | 4 +-
drivers/md/bcache/writeback.c | 10 +
drivers/md/md-bitmap.c | 17 +-
drivers/md/md.c | 23 +-
drivers/md/raid0.c | 62 +-
drivers/md/raid0.h | 1 +
drivers/md/raid10.c | 38 +-
drivers/media/cec/i2c/Kconfig | 1 +
drivers/media/platform/qcom/venus/helpers.c | 4 +-
drivers/media/usb/dvb-usb-v2/az6007.c | 3 +-
drivers/media/usb/siano/smsusb.c | 3 +-
drivers/memory/brcmstb_dpfe.c | 4 +-
drivers/memstick/host/r592.c | 4 +-
drivers/mfd/intel-lpss-acpi.c | 3 +
drivers/mfd/rt5033.c | 3 -
drivers/mfd/stmfx.c | 7 +-
drivers/mfd/stmpe.c | 4 +-
drivers/misc/fastrpc.c | 2 +-
drivers/misc/pci_endpoint_test.c | 10 +-
drivers/mmc/core/quirks.h | 14 +
drivers/mmc/host/mmci.c | 1 +
drivers/mmc/host/sdhci.c | 4 +-
drivers/mtd/nand/raw/meson_nand.c | 4 +
drivers/net/dsa/vitesse-vsc73xx-core.c | 6 +-
drivers/net/ethernet/amazon/ena/ena_com.c | 3 +
drivers/net/ethernet/broadcom/bgmac.c | 4 +-
drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +
drivers/net/ethernet/broadcom/tg3.c | 1 +
drivers/net/ethernet/google/gve/gve_ethtool.c | 3 +
drivers/net/ethernet/intel/iavf/iavf_ethtool.c | 2 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 5 +-
drivers/net/ethernet/intel/igb/igb_main.c | 5 +
drivers/net/ethernet/intel/igc/igc.h | 33 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 2 +
drivers/net/ethernet/intel/igc/igc_main.c | 45 +-
drivers/net/ethernet/intel/igc/igc_ptp.c | 57 +-
drivers/net/ethernet/marvell/mvneta.c | 4 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 11 +
.../net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 2 +-
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5 +-
.../ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +-
drivers/net/ethernet/microchip/lan743x_main.c | 21 +-
drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5 -
drivers/net/ethernet/sfc/ef10.c | 13 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 -
drivers/net/ethernet/ti/cpsw_ale.c | 24 +-
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 10 +-
drivers/net/gtp.c | 2 +
drivers/net/ipvlan/ipvlan_core.c | 9 +-
drivers/net/netdevsim/dev.c | 9 +-
drivers/net/phy/phy_device.c | 21 +-
drivers/net/ppp/pptp.c | 31 +-
drivers/net/wireguard/netlink.c | 14 +-
drivers/net/wireguard/queueing.c | 1 +
drivers/net/wireguard/queueing.h | 25 +-
drivers/net/wireguard/receive.c | 2 +-
drivers/net/wireguard/send.c | 2 +-
drivers/net/wireless/ath/ath11k/mac.c | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_hw.c | 27 +-
drivers/net/wireless/ath/ath9k/htc_hst.c | 8 +-
drivers/net/wireless/ath/ath9k/main.c | 11 +-
drivers/net/wireless/ath/ath9k/wmi.c | 4 +
drivers/net/wireless/atmel/atmel_cs.c | 13 +-
drivers/net/wireless/cisco/airo.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 2 +-
drivers/net/wireless/intersil/orinoco/orinoco_cs.c | 13 +-
.../net/wireless/intersil/orinoco/spectrum_cs.c | 13 +-
drivers/net/wireless/marvell/mwifiex/scan.c | 6 +-
drivers/net/wireless/microchip/wilc1000/hif.c | 8 +-
drivers/net/wireless/ray_cs.c | 36 +-
drivers/net/wireless/rsi/rsi_91x_sdio.c | 9 +-
drivers/net/wireless/wl3501_cs.c | 27 +-
drivers/ntb/hw/amd/ntb_hw_amd.c | 7 +-
drivers/ntb/hw/idt/ntb_hw_idt.c | 7 +-
drivers/ntb/hw/intel/ntb_hw_gen1.c | 7 +-
drivers/ntb/ntb_transport.c | 2 +-
drivers/ntb/test/ntb_tool.c | 2 +
drivers/nubus/proc.c | 22 +-
drivers/nvme/host/pci.c | 3 +-
drivers/pci/controller/cadence/pcie-cadence-host.c | 27 +
drivers/pci/controller/dwc/pcie-qcom.c | 2 +
drivers/pci/controller/pci-ftpci100.c | 14 +-
drivers/pci/controller/pcie-rockchip-ep.c | 65 +-
drivers/pci/controller/pcie-rockchip.c | 17 +
drivers/pci/controller/pcie-rockchip.h | 11 +-
drivers/pci/hotplug/pciehp_ctrl.c | 8 +
drivers/pci/pci.c | 10 +-
drivers/pci/pcie/aspm.c | 21 +-
drivers/pci/quirks.c | 2 +
drivers/perf/arm-cmn.c | 7 +-
drivers/phy/tegra/xusb.c | 4 +
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 6 +-
drivers/pinctrl/intel/pinctrl-cherryview.c | 15 +-
drivers/pinctrl/pinctrl-amd.c | 41 +-
drivers/pinctrl/pinctrl-amd.h | 1 +
drivers/pinctrl/pinctrl-at91-pio4.c | 2 +
drivers/platform/x86/wmi.c | 64 +-
drivers/powercap/Kconfig | 4 +-
drivers/powercap/intel_rapl_msr.c | 1 -
drivers/pwm/pwm-imx-tpm.c | 7 +
drivers/pwm/sysfs.c | 17 +
drivers/regulator/core.c | 30 +-
drivers/rtc/rtc-st-lpc.c | 2 +-
drivers/s390/net/qeth_l3_sys.c | 2 +-
drivers/scsi/3w-xxxx.c | 4 +-
drivers/scsi/qedf/qedf_main.c | 3 +-
drivers/scsi/qla2xxx/qla_attr.c | 13 +
drivers/scsi/qla2xxx/qla_bsg.c | 6 +
drivers/scsi/qla2xxx/qla_def.h | 1 -
drivers/scsi/qla2xxx/qla_init.c | 2 +-
drivers/scsi/qla2xxx/qla_inline.h | 5 +-
drivers/scsi/qla2xxx/qla_iocb.c | 5 +-
drivers/scsi/qla2xxx/qla_nvme.c | 3 -
drivers/scsi/qla2xxx/qla_os.c | 3 +-
drivers/soc/amlogic/meson-secure-pwrc.c | 2 +-
drivers/soc/fsl/qe/Kconfig | 1 +
drivers/spi/spi-bcm-qspi.c | 10 +-
drivers/spi/spi-bcm63xx.c | 2 +-
drivers/spi/spi-geni-qcom.c | 2 +-
drivers/staging/media/atomisp/pci/atomisp_cmd.c | 3 +-
.../media/atomisp/pci/atomisp_gmin_platform.c | 2 +-
drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 3 +-
drivers/thermal/mtk_thermal.c | 14 +-
drivers/thermal/sun8i_thermal.c | 55 +-
drivers/tty/serial/8250/8250.h | 1 -
drivers/tty/serial/8250/8250_omap.c | 25 +-
drivers/tty/serial/8250/8250_pci.c | 19 -
drivers/tty/serial/8250/8250_port.c | 11 +-
drivers/tty/serial/atmel_serial.c | 4 +-
drivers/tty/serial/fsl_lpuart.c | 1 +
drivers/tty/serial/samsung_tty.c | 14 +-
drivers/usb/core/devio.c | 2 +
drivers/usb/dwc3/dwc3-meson-g12a.c | 5 +-
drivers/usb/dwc3/dwc3-qcom.c | 17 +-
drivers/usb/dwc3/gadget.c | 4 +-
drivers/usb/gadget/function/u_serial.c | 13 +-
drivers/usb/host/xhci-mem.c | 39 +-
drivers/usb/host/xhci-pci.c | 12 +
drivers/usb/host/xhci.h | 2 +
drivers/usb/phy/phy-tahvo.c | 2 +-
drivers/usb/serial/option.c | 4 +
drivers/video/fbdev/au1200fb.c | 3 +
drivers/video/fbdev/imsttfb.c | 34 +-
drivers/video/fbdev/imxfb.c | 4 +-
drivers/video/fbdev/omap/lcd_mipid.c | 6 +-
drivers/w1/slaves/w1_therm.c | 31 +-
drivers/w1/w1.c | 4 +-
fs/btrfs/block-group.c | 9 +-
fs/btrfs/disk-io.c | 3 +
fs/btrfs/qgroup.c | 3 +
fs/ceph/caps.c | 9 +
fs/dlm/plock.c | 4 +-
fs/erofs/zdata.c | 2 +-
fs/erofs/zmap.c | 6 +-
fs/ext4/indirect.c | 8 +
fs/ext4/inode.c | 10 -
fs/ext4/mballoc.c | 17 +-
fs/ext4/namei.c | 17 +-
fs/ext4/super.c | 13 +-
fs/ext4/xattr.c | 14 +
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 2 +-
fs/f2fs/gc.c | 22 +-
fs/f2fs/namei.c | 16 +-
fs/f2fs/node.c | 4 +-
fs/fs_context.c | 3 +-
fs/fuse/dir.c | 2 +-
fs/inode.c | 42 ++
fs/internal.h | 2 +
fs/jffs2/build.c | 5 +-
fs/jffs2/xattr.c | 13 +-
fs/jffs2/xattr.h | 4 +-
fs/jfs/jfs_dmap.c | 6 +
fs/jfs/jfs_filsys.h | 2 +
fs/kernfs/dir.c | 2 +
fs/namei.c | 25 +-
fs/nfs/nfs4proc.c | 1 +
fs/nfsd/nfs4xdr.c | 2 +-
fs/notify/fanotify/fanotify_user.c | 22 +-
fs/overlayfs/copy_up.c | 2 +
fs/overlayfs/dir.c | 3 +-
fs/overlayfs/export.c | 3 +-
fs/overlayfs/namei.c | 3 +-
fs/overlayfs/overlayfs.h | 6 +-
fs/overlayfs/super.c | 2 +-
fs/overlayfs/util.c | 24 +-
fs/pstore/ram_core.c | 2 +
fs/ramfs/inode.c | 2 +-
include/asm-generic/pgtable-nop4d.h | 2 +-
include/asm-generic/pgtable-nopmd.h | 2 +-
include/asm-generic/pgtable-nopud.h | 2 +-
include/linux/bpf-cgroup.h | 27 +-
include/linux/etherdevice.h | 12 +
include/linux/indirect_call_wrapper.h | 6 +
include/linux/netdevice.h | 18 +
include/linux/nmi.h | 2 +-
include/linux/pci.h | 1 +
include/linux/pgtable.h | 4 +-
include/linux/pipe_fs_i.h | 4 -
include/linux/ramfs.h | 1 +
include/linux/sched/signal.h | 2 +-
include/linux/serial_8250.h | 1 -
include/linux/tcp.h | 2 +-
include/linux/workqueue.h | 15 +-
include/net/netfilter/nf_tables.h | 41 +-
include/net/netns/ipv4.h | 1 +
include/net/netns/nftables.h | 7 -
include/net/nfc/nfc.h | 4 +-
include/net/pkt_sched.h | 2 +-
include/net/sock.h | 3 +
include/net/tcp.h | 32 +-
include/trace/events/timer.h | 6 +-
include/uapi/linux/affs_hardblocks.h | 68 +-
include/uapi/linux/auto_dev-ioctl.h | 2 +-
include/uapi/linux/videodev2.h | 2 +-
io_uring/io_uring.c | 66 +-
kernel/bpf/bpf_lru_list.c | 21 +-
kernel/bpf/bpf_lru_list.h | 7 +-
kernel/bpf/cgroup.c | 46 ++
kernel/kcsan/core.c | 2 +
kernel/kexec_core.c | 5 +-
kernel/rcu/rcuscale.c | 214 +++----
kernel/rcu/tasks.h | 37 +-
kernel/sched/fair.c | 2 +-
kernel/time/posix-timers.c | 74 ++-
kernel/trace/ftrace.c | 72 ++-
kernel/trace/ring_buffer.c | 24 +-
kernel/trace/trace.c | 3 +-
kernel/trace/trace_events_hist.c | 9 +-
kernel/trace/trace_probe_tmpl.h | 2 +
kernel/watchdog_hld.c | 6 +-
kernel/workqueue.c | 13 +-
lib/debugobjects.c | 9 +
lib/test_firmware.c | 12 +-
lib/ts_bm.c | 4 +-
mm/shmem.c | 2 +-
net/bridge/br_if.c | 5 +-
net/bridge/br_stp_if.c | 3 +
net/can/bcm.c | 12 +-
net/can/isotp.c | 5 +-
net/core/devlink.c | 5 +-
net/core/rtnetlink.c | 104 ++--
net/core/skbuff.c | 5 +
net/core/sock.c | 17 +-
net/dsa/tag_sja1105.c | 4 +-
net/ipv4/esp4.c | 2 +-
net/ipv4/inet_connection_sock.c | 3 +-
net/ipv4/inet_hashtables.c | 17 +-
net/ipv4/inet_timewait_sock.c | 8 +-
net/ipv4/sysctl_net_ipv4.c | 9 +
net/ipv4/tcp.c | 68 +-
net/ipv4/tcp_fastopen.c | 6 +-
net/ipv4/tcp_input.c | 12 +-
net/ipv4/tcp_ipv4.c | 3 +-
net/ipv4/tcp_minisocks.c | 9 +-
net/ipv4/tcp_output.c | 2 +-
net/ipv4/tcp_timer.c | 10 +-
net/ipv6/addrconf.c | 3 +-
net/ipv6/icmp.c | 5 +-
net/ipv6/ip6_gre.c | 3 +-
net/ipv6/tcp_ipv6.c | 3 +-
net/ipv6/udp.c | 2 +-
net/llc/llc_input.c | 3 -
net/netfilter/nf_conntrack_helper.c | 4 +
net/netfilter/nf_conntrack_proto_dccp.c | 52 +-
net/netfilter/nf_conntrack_sip.c | 2 +-
net/netfilter/nf_tables_api.c | 681 +++++++++++++++------
net/netfilter/nf_tables_offload.c | 30 +-
net/netfilter/nft_byteorder.c | 14 +-
net/netfilter/nft_chain_filter.c | 11 +-
net/netfilter/nft_dynset.c | 6 +-
net/netfilter/nft_immediate.c | 90 ++-
net/netfilter/nft_set_bitmap.c | 5 +-
net/netfilter/nft_set_hash.c | 23 +-
net/netfilter/nft_set_pipapo.c | 20 +-
net/netfilter/nft_set_rbtree.c | 5 +-
net/netlink/af_netlink.c | 5 +-
net/netlink/diag.c | 7 +-
net/nfc/core.c | 4 +-
net/nfc/hci/llc_shdlc.c | 10 +-
net/nfc/llcp.h | 9 +-
net/nfc/llcp_commands.c | 59 +-
net/nfc/llcp_core.c | 95 ++-
net/nfc/llcp_sock.c | 21 +-
net/nfc/netlink.c | 20 +-
net/nfc/nfc.h | 3 +-
net/sched/act_pedit.c | 1 +
net/sched/cls_flower.c | 10 +
net/sched/cls_fw.c | 10 +-
net/sched/sch_qfq.c | 41 +-
net/sctp/socket.c | 22 +-
net/socket.c | 3 +
net/sunrpc/svcsock.c | 23 +-
net/wireless/scan.c | 217 ++++---
net/wireless/wext-core.c | 6 +
net/xdp/xsk.c | 5 +
samples/bpf/tcp_basertt_kern.c | 2 +-
samples/ftrace/ftrace-direct-too.c | 14 +-
scripts/mod/modpost.c | 26 +-
scripts/tags.sh | 9 +-
security/apparmor/policy_unpack.c | 9 +-
security/integrity/evm/evm_main.c | 2 +
security/integrity/iint.c | 15 +-
security/integrity/ima/ima_modsig.c | 3 +
security/integrity/ima/ima_policy.c | 3 +-
security/keys/request_key.c | 35 +-
security/keys/trusted-keys/trusted_tpm2.c | 2 +-
sound/core/jack.c | 15 +-
sound/pci/ac97/ac97_codec.c | 4 +-
sound/pci/hda/patch_realtek.c | 28 +-
sound/soc/codecs/es8316.c | 23 +-
sound/soc/fsl/fsl_sai.c | 2 +-
sound/soc/fsl/fsl_sai.h | 1 +
sound/soc/fsl/imx-audmix.c | 9 +
sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 13 +-
tools/bpf/bpftool/feature.c | 24 +-
tools/include/uapi/linux/tcp.h | 357 +++++++++++
tools/lib/bpf/bpf_helpers.h | 15 +-
tools/perf/builtin-bench.c | 7 +-
tools/perf/builtin-script.c | 34 +-
tools/perf/tests/builtin-test.c | 3 +
.../tests/shell/test_uprobe_from_different_cu.sh | 77 +++
tools/perf/util/dwarf-aux.c | 2 +-
.../testing/selftests/bpf/prog_tests/bpf_tcp_ca.c | 1 +
.../selftests/bpf/prog_tests/cls_redirect.c | 1 +
.../selftests/bpf/prog_tests/sockmap_basic.c | 1 +
.../testing/selftests/bpf/prog_tests/sockopt_sk.c | 28 +
tools/testing/selftests/bpf/progs/sockopt_sk.c | 23 +-
tools/testing/selftests/bpf/test_progs.h | 1 -
tools/testing/selftests/bpf/test_verifier.c | 12 +-
tools/testing/selftests/bpf/verifier/spill_fill.c | 30 +
tools/testing/selftests/net/rtnetlink.sh | 1 +
tools/testing/selftests/tc-testing/config | 1 +
tools/testing/selftests/tc-testing/settings | 1 +
tools/testing/selftests/wireguard/netns.sh | 30 +-
521 files changed, 5600 insertions(+), 2682 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.4 055/313] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
@ 2023-07-25 10:43 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-25 10:43 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Remi Pommarel, Nicolas Escande,
Toke Høiland-Jørgensen, Kalle Valo, Sasha Levin
From: Remi Pommarel <repk@triplefau.lt>
[ Upstream commit 75086cc6dee046e3fbb3dba148b376d8802f83bc ]
On EDMA capable hardware, ath9k_txq_list_has_key() can enter infinite
loop if it is called while all txq_fifos have packets that use different
key that the one we are looking for. Fix it by exiting the loop if all
txq_fifos have been checked already.
Because this loop is called under spin_lock_bh() (see ath_txq_lock) it
causes the following rcu stall:
rcu: INFO: rcu_sched self-detected stall on CPU
ath10k_pci 0000:01:00.0: failed to read temperature -11
rcu: 1-....: (5254 ticks this GP) idle=189/1/0x4000000000000002 softirq=8442983/8442984 fqs=2579
(t=5257 jiffies g=17983297 q=334)
Task dump for CPU 1:
task:hostapd state:R running task stack: 0 pid: 297 ppid: 289 flags:0x0000000a
Call trace:
dump_backtrace+0x0/0x170
show_stack+0x1c/0x24
sched_show_task+0x140/0x170
dump_cpu_task+0x48/0x54
rcu_dump_cpu_stacks+0xf0/0x134
rcu_sched_clock_irq+0x8d8/0x9fc
update_process_times+0xa0/0xec
tick_sched_timer+0x5c/0xd0
__hrtimer_run_queues+0x154/0x320
hrtimer_interrupt+0x120/0x2f0
arch_timer_handler_virt+0x38/0x44
handle_percpu_devid_irq+0x9c/0x1e0
handle_domain_irq+0x64/0x90
gic_handle_irq+0x78/0xb0
call_on_irq_stack+0x28/0x38
do_interrupt_handler+0x54/0x5c
el1_interrupt+0x2c/0x4c
el1h_64_irq_handler+0x14/0x1c
el1h_64_irq+0x74/0x78
ath9k_txq_has_key+0x1bc/0x250 [ath9k]
ath9k_set_key+0x1cc/0x3dc [ath9k]
drv_set_key+0x78/0x170
ieee80211_key_replace+0x564/0x6cc
ieee80211_key_link+0x174/0x220
ieee80211_add_key+0x11c/0x300
nl80211_new_key+0x12c/0x330
genl_family_rcv_msg_doit+0xbc/0x11c
genl_rcv_msg+0xd8/0x1c4
netlink_rcv_skb+0x40/0x100
genl_rcv+0x3c/0x50
netlink_unicast+0x1ec/0x2c0
netlink_sendmsg+0x198/0x3c0
____sys_sendmsg+0x210/0x250
___sys_sendmsg+0x78/0xc4
__sys_sendmsg+0x4c/0x90
__arm64_sys_sendmsg+0x28/0x30
invoke_syscall.constprop.0+0x60/0x100
do_el0_svc+0x48/0xd0
el0_svc+0x14/0x50
el0t_64_sync_handler+0xa8/0xb0
el0t_64_sync+0x158/0x15c
This rcu stall is hard to reproduce as is, but changing ATH_TXFIFO_DEPTH
from 8 to 2 makes it reasonably easy to reproduce.
Fixes: ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
Tested-by: Nicolas Escande <nico.escande@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230609093744.1985-1-repk@triplefau.lt
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath9k/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index eb5751a45f266..4e606a4b19f2d 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -847,7 +847,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -865,8 +865,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 5.10 348/509] net: bgmac: postpone turning IRQs off to avoid SoC hangs
2023-07-25 10:38 1% [PATCH 5.10 000/509] 5.10.188-rc1 review Greg Kroah-Hartman
2023-07-25 10:40 5% ` [PATCH 5.10 073/509] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
@ 2023-07-25 10:44 7% ` Greg Kroah-Hartman
2023-07-28 9:31 0% ` [PATCH 5.10 000/509] 5.10.188-rc1 review luomeng
2 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-25 10:44 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rafał Miłecki,
Michal Kubiak, David S. Miller, Sasha Levin
From: Rafał Miłecki <rafal@milecki.pl>
[ Upstream commit e7731194fdf085f46d58b1adccfddbd0dfee4873 ]
Turning IRQs off is done by accessing Ethernet controller registers.
That can't be done until device's clock is enabled. It results in a SoC
hang otherwise.
This bug remained unnoticed for years as most bootloaders keep all
Ethernet interfaces turned on. It seems to only affect a niche SoC
family BCM47189. It has two Ethernet controllers but CFE bootloader uses
only the first one.
Fixes: 34322615cbaa ("net: bgmac: Mask interrupts during probe")
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Reviewed-by: Michal Kubiak <michal.kubiak@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/broadcom/bgmac.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index bb999e67d7736..ab8ee93316354 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1492,8 +1492,6 @@ int bgmac_enet_probe(struct bgmac *bgmac)
bgmac->in_init = true;
- bgmac_chip_intrs_off(bgmac);
-
net_dev->irq = bgmac->irq;
SET_NETDEV_DEV(net_dev, bgmac->dev);
dev_set_drvdata(bgmac->dev, bgmac);
@@ -1511,6 +1509,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)
*/
bgmac_clk_enable(bgmac, 0);
+ bgmac_chip_intrs_off(bgmac);
+
/* This seems to be fixing IRQ by assigning OOB #6 to the core */
if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) {
if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
--
2.39.2
^ permalink raw reply related [relevance 7%]
* [PATCH 5.10 073/509] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
2023-07-25 10:38 1% [PATCH 5.10 000/509] 5.10.188-rc1 review Greg Kroah-Hartman
@ 2023-07-25 10:40 5% ` Greg Kroah-Hartman
2023-07-25 10:44 7% ` [PATCH 5.10 348/509] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
2023-07-28 9:31 0% ` [PATCH 5.10 000/509] 5.10.188-rc1 review luomeng
2 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-25 10:40 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Remi Pommarel, Nicolas Escande,
Toke Høiland-Jørgensen, Kalle Valo, Sasha Levin
From: Remi Pommarel <repk@triplefau.lt>
[ Upstream commit 75086cc6dee046e3fbb3dba148b376d8802f83bc ]
On EDMA capable hardware, ath9k_txq_list_has_key() can enter infinite
loop if it is called while all txq_fifos have packets that use different
key that the one we are looking for. Fix it by exiting the loop if all
txq_fifos have been checked already.
Because this loop is called under spin_lock_bh() (see ath_txq_lock) it
causes the following rcu stall:
rcu: INFO: rcu_sched self-detected stall on CPU
ath10k_pci 0000:01:00.0: failed to read temperature -11
rcu: 1-....: (5254 ticks this GP) idle=189/1/0x4000000000000002 softirq=8442983/8442984 fqs=2579
(t=5257 jiffies g=17983297 q=334)
Task dump for CPU 1:
task:hostapd state:R running task stack: 0 pid: 297 ppid: 289 flags:0x0000000a
Call trace:
dump_backtrace+0x0/0x170
show_stack+0x1c/0x24
sched_show_task+0x140/0x170
dump_cpu_task+0x48/0x54
rcu_dump_cpu_stacks+0xf0/0x134
rcu_sched_clock_irq+0x8d8/0x9fc
update_process_times+0xa0/0xec
tick_sched_timer+0x5c/0xd0
__hrtimer_run_queues+0x154/0x320
hrtimer_interrupt+0x120/0x2f0
arch_timer_handler_virt+0x38/0x44
handle_percpu_devid_irq+0x9c/0x1e0
handle_domain_irq+0x64/0x90
gic_handle_irq+0x78/0xb0
call_on_irq_stack+0x28/0x38
do_interrupt_handler+0x54/0x5c
el1_interrupt+0x2c/0x4c
el1h_64_irq_handler+0x14/0x1c
el1h_64_irq+0x74/0x78
ath9k_txq_has_key+0x1bc/0x250 [ath9k]
ath9k_set_key+0x1cc/0x3dc [ath9k]
drv_set_key+0x78/0x170
ieee80211_key_replace+0x564/0x6cc
ieee80211_key_link+0x174/0x220
ieee80211_add_key+0x11c/0x300
nl80211_new_key+0x12c/0x330
genl_family_rcv_msg_doit+0xbc/0x11c
genl_rcv_msg+0xd8/0x1c4
netlink_rcv_skb+0x40/0x100
genl_rcv+0x3c/0x50
netlink_unicast+0x1ec/0x2c0
netlink_sendmsg+0x198/0x3c0
____sys_sendmsg+0x210/0x250
___sys_sendmsg+0x78/0xc4
__sys_sendmsg+0x4c/0x90
__arm64_sys_sendmsg+0x28/0x30
invoke_syscall.constprop.0+0x60/0x100
do_el0_svc+0x48/0xd0
el0_svc+0x14/0x50
el0t_64_sync_handler+0xa8/0xb0
el0t_64_sync+0x158/0x15c
This rcu stall is hard to reproduce as is, but changing ATH_TXFIFO_DEPTH
from 8 to 2 makes it reasonably easy to reproduce.
Fixes: ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
Tested-by: Nicolas Escande <nico.escande@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230609093744.1985-1-repk@triplefau.lt
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath9k/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index ac354dfc50559..2bd4d295c9bdf 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 5.10 000/509] 5.10.188-rc1 review
@ 2023-07-25 10:38 1% Greg Kroah-Hartman
2023-07-25 10:40 5% ` [PATCH 5.10 073/509] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
` (2 more replies)
0 siblings, 3 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-25 10:38 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, srw, rwarsow, conor
This is the start of the stable review cycle for the 5.10.188 release.
There are 509 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 27 Jul 2023 10:44:26 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.188-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.188-rc1
Zheng Yejian <zhengyejian1@huawei.com>
ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
Linus Torvalds <torvalds@linux-foundation.org>
ftrace: Store the order of pages allocated in ftrace_page
Zheng Yejian <zhengyejian1@huawei.com>
tracing: Fix memory leak of iter->temp when reading trace_pipe
Mohamed Khalfella <mkhalfella@purestorage.com>
tracing/histograms: Return an error if we fail to add histogram to hist_vars list
Vladimir Oltean <vladimir.oltean@nxp.com>
net: phy: prevent stale pointer dereference in phy_init()
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around fastopenq.max_qlen
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around icsk->icsk_user_timeout
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->notsent_lowat
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around rskq_defer_accept
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->linger2
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around icsk->icsk_syn_retries
Kuniyuki Iwashima <kuniyu@amazon.com>
tcp: Fix data-races around sysctl_tcp_syn(ack)?_retries.
Kuniyuki Iwashima <kuniyu@amazon.co.jp>
net: Introduce net.ipv4.tcp_migrate_req.
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->keepalive_probes
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->keepalive_intvl
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->keepalive_time
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tp->tcp_tx_delay
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: skip bound chain on rule flush
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: skip bound chain in netns release path
Florian Westphal <fw@strlen.de>
netfilter: nft_set_pipapo: fix improper element removal
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: can't schedule in nft_chain_validate
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: fix spurious set element insertion failure
Kuniyuki Iwashima <kuniyu@amazon.com>
llc: Don't drop packet from non-root netns.
Zhang Shurong <zhang_shurong@foxmail.com>
fbdev: au1200fb: Fix missing IRQ check in au1200fb_drv_probe
Kuniyuki Iwashima <kuniyu@amazon.com>
Revert "tcp: avoid the lookup process failing to get sk in ehash table"
Yuanjun Gong <ruc_gongyuanjun@163.com>
net:ipv6: check return value of pskb_trim()
Wang Ming <machel@vivo.com>
net: ipv4: Use kfree_sensitive instead of kfree
Eric Dumazet <edumazet@google.com>
tcp: annotate data-races around tcp_rsk(req)->ts_recent
Geetha sowjanya <gakula@marvell.com>
octeontx2-pf: Dont allocate BPIDs for LBK interfaces
Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
security: keys: Modify mismatched function name
Ding Hui <dinghui@sangfor.com.cn>
iavf: Fix out-of-bounds when setting channels on remove
Ding Hui <dinghui@sangfor.com.cn>
iavf: Fix use-after-free in free_netdev
Kuniyuki Iwashima <kuniyu@amazon.com>
bridge: Add extack warning when enabling STP in netns.
Tanmay Patil <t-patil@ti.com>
net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Use amd_pinconf_set() for all config options
Martin Kaiser <martin@kaiser.cx>
fbdev: imxfb: warn about invalid left/right margin
Jonas Gorski <jonas.gorski@gmail.com>
spi: bcm63xx: fix max prepend length
Ying Hsu <yinghsu@chromium.org>
igb: Fix igb_down hung on surprise removal
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: mvm: avoid baid size integer overflow
Gustavo A. R. Silva <gustavoars@kernel.org>
wifi: wext-core: Fix -Wstringop-overflow warning in ioctl_standard_iw_point()
Petr Oros <poros@redhat.com>
devlink: report devlink_port_type_warn source device
Martin KaFai Lau <martin.lau@kernel.org>
bpf: Address KCSAN report on bpf_lru_list
Maxime Bizon <mbizon@freebox.fr>
wifi: ath11k: fix registration of 6Ghz-only phy without the full channel range
Yicong Yang <yangyicong@hisilicon.com>
sched/fair: Don't balance task to its current running CPU
Mark Rutland <mark.rutland@arm.com>
arm64: mm: fix VA-range sanity check
Youngmin Nam <youngmin.nam@samsung.com>
arm64: set __exception_irq_entry with __irq_entry as a default
Hans de Goede <hdegoede@redhat.com>
ACPI: video: Add backlight=native DMI quirk for Lenovo ThinkPad X131e (3371 AMD version)
Hans de Goede <hdegoede@redhat.com>
ACPI: video: Add backlight=native DMI quirk for Apple iMac11,3
Hans de Goede <hdegoede@redhat.com>
ACPI: button: Add lid disable DMI quirk for Nextbook Ares 8A
David Sterba <dsterba@suse.com>
btrfs: add xxhash to fast checksum implementations
Thomas Gleixner <tglx@linutronix.de>
posix-timers: Ensure timer ID search-loop limit is valid
Yu Kuai <yukuai3@huawei.com>
md/raid10: prevent soft lockup while flush writes
Yu Kuai <yukuai3@huawei.com>
md: fix data corruption for raid456 when reshape restart while grow up
Zhong Jinghua <zhongjinghua@huawei.com>
nbd: Add the maximum limit of allocated index in nbd_dev_add
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
debugobjects: Recheck debug_objects_enabled before reporting
Eric Whitney <enwlinux@gmail.com>
ext4: correct inline offset when handling xattrs in inode body
Matus Gajdos <matuszpd@gmail.com>
ASoC: fsl_sai: Disable bit clock with transmitter
Jocelyn Falempe <jfalempe@redhat.com>
drm/client: Fix memory leak in drm_client_modeset_probe
Jocelyn Falempe <jfalempe@redhat.com>
drm/client: Fix memory leak in drm_client_target_cloned
YueHaibing <yuehaibing@huawei.com>
can: bcm: Fix UAF in bcm_proc_show()
Mark Brown <broonie@kernel.org>
regmap: Account for register length in SMBus I/O limits
Mark Brown <broonie@kernel.org>
regmap: Drop initial version of maximum transfer length fixes
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: tc: add 'ct' action kconfig dep
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: tc: set timeout to 15 minutes
Miklos Szeredi <mszeredi@redhat.com>
fuse: revalidate: don't invalidate if interrupted
Filipe Manana <fdmanana@suse.com>
btrfs: fix warning when putting transaction with qgroups enabled after abort
Georg Müller <georgmueller@gmx.net>
perf probe: Add test for regression introduced by switch to die_get_decl_file()
Petr Pavlu <petr.pavlu@suse.com>
keys: Fix linking a duplicate key to a keyring's assoc_array
Luka Guzenko <l.guzenko@web.de>
ALSA: hda/realtek: Enable Mute LED on HP Laptop 15s-eq2xxx
Kailang Yang <kailang@realtek.com>
ALSA: hda/realtek - remove 3k pull low procedure
Daniel Vetter <daniel.vetter@ffwll.ch>
drm/atomic: Fix potential use-after-free in nonblocking commits
Jason Gunthorpe <jgg@ziepe.ca>
RDMA/cma: Ensure rdma_addr_cancel() happens before issuing more requests
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: reintroduce lmax bound check for MTU
Manish Rangankar <mrangankar@marvell.com>
scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
Shreyas Deodhar <sdeodhar@marvell.com>
scsi: qla2xxx: Pointer may be dereferenced
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Correct the index of array
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Fix potential NULL pointer dereference
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix buffer overrun
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Array index may go out of bound
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Wait for io return on terminate rport
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix not to count error code to total length
Mateusz Stachyra <m.stachyra@samsung.com>
tracing: Fix null pointer dereference in tracing_err_log_open()
Max Filippov <jcmvbkbc@gmail.com>
xtensa: ISS: fix call to split_if_spec
Zheng Yejian <zhengyejian1@huawei.com>
ring-buffer: Fix deadloop issue on reading trace_pipe
Krister Johansen <kjlx@templeofstupid.com>
net: ena: fix shift-out-of-bounds in exponential backoff
Florent Revest <revest@chromium.org>
samples: ftrace: Save required argument registers in sample trampolines
Mohamed Khalfella <mkhalfella@purestorage.com>
tracing/histograms: Add histograms to hist_vars if they have referenced variables
Heiko Carstens <hca@linux.ibm.com>
s390/decompressor: fix misaligned symbol build error
Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Revert "8250: add support for ASIX devices with a FIFO bug"
George Stark <gnstark@sberdevices.ru>
meson saradc: fix clock divider mask length
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Show ZHAOXIN xHCI root hub speed correctly
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix resume issue of some ZHAOXIN hosts
Xiubo Li <xiubli@redhat.com>
ceph: don't let check_caps skip sending responses for revoke msgs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
Dan Carpenter <dan.carpenter@linaro.org>
serial: atmel: don't enable IRQs prematurely
Mario Limonciello <mario.limonciello@amd.com>
drm/amd/display: Correct `DMUB_FW_VERSION` macro
Brian Norris <briannorris@chromium.org>
drm/rockchip: vop: Leave vblank enabled in self-refresh
Brian Norris <briannorris@chromium.org>
drm/atomic: Allow vblank-enabled + self-refresh "disable"
Alexander Aring <aahringo@redhat.com>
fs: dlm: return positive pid value for F_GETLK
Jason Baron <jbaron@akamai.com>
md/raid0: add discard support for the 'original' layout
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Re-init completion for every test
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Free IRQs before removing the device
Damien Le Moal <dlemoal@kernel.org>
PCI: rockchip: Set address alignment for endpoint mode
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Use u32 variable to access 32-bit registers
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Write PCI Device ID to correct register
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Assert PCI Configuration Enable bit after probe
Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
PCI: qcom: Disable write access to read only registers for IP v2.3.3
Robin Murphy <robin.murphy@arm.com>
PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
Ondrej Zary <linux@zary.sk>
PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
Martin Kaiser <martin@kaiser.cx>
hwrng: imx-rngc - fix the timeout for init and self check
Siddh Raman Pant <code@siddh.me>
jfs: jfs_dmap: Validate db_l2nbperpage while mounting
Baokun Li <libaokun1@huawei.com>
ext4: only update i_reserved_data_blocks on successful block allocation
Chao Yu <chao@kernel.org>
ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_new_blocks
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: get block from bh in ext4_free_blocks for fast commit replay
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_clear_bb
Zhihao Cheng <chengzhihao1@huawei.com>
ext4: Fix reusing stale buffer heads from last failed mounting
Huacai Chen <chenhuacai@loongson.cn>
MIPS: Loongson: Fix cpu_probe_loongson() again
Gao Xiang <hsiangkao@linux.alibaba.com>
erofs: fix compact 4B support for 16k block size
Ekansh Gupta <quic_ekangupt@quicinc.com>
misc: fastrpc: Create fastrpc scalar with correct buffer count
Naveen N Rao <naveen@kernel.org>
powerpc: Fail build if using recordmcount with binutils v2.37
Florian Fainelli <florian.fainelli@broadcom.com>
net: bcmgenet: Ensure MDIO unregistration has clocks enabled
Arseniy Krasnov <AVKrasnov@sberdevices.ru>
mtd: rawnand: meson: fix unaligned DMA buffers handling
Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Only use special debounce behavior for GPIO 0
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Detect internal GPIO0 debounce handling
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Fix mistake in handling clearing pins at startup
Chao Yu <chao@kernel.org>
f2fs: fix to avoid NULL pointer dereference f2fs_write_end_io()
Ming Lei <ming.lei@redhat.com>
nvme-pci: fix DMA direction of unmapping integrity data
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: account for stab overhead in qfq_enqueue
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: refactor parsing of netlink parameters
Pedro Tammela <pctammela@mojatatu.com>
net/sched: make psched_mtu() RTNL-less safe
Dan Carpenter <dan.carpenter@linaro.org>
netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
Ido Schimmel <idosch@nvidia.com>
net/sched: flower: Ensure both minimum and maximum ports are specified
Randy Dunlap <rdunlap@infradead.org>
wifi: airo: avoid uninitialized warning in airo_get_rate()
Chunhai Guo <guochunhai@vivo.com>
erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
Björn Töpel <bjorn@rivosinc.com>
riscv, bpf: Fix inconsistent JIT image generation
Pu Lehui <pulehui@huawei.com>
bpf, riscv: Support riscv jit to provide bpf_line_info
Jisheng Zhang <jszhang@kernel.org>
riscv: bpf: Avoid breaking W^X
Jisheng Zhang <jszhang@kernel.org>
riscv: bpf: Move bpf_jit_alloc_exec() and bpf_jit_free_exec() to core
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix inserting of empty frame for launchtime
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix launchtime before start of cycle
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
platform/x86: wmi: Break possible infinite loop when parsing GUID
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: move variables
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: use guid_t and guid_equal()
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: remove unnecessary argument
Ziyang Xuan <william.xuanziyang@huawei.com>
ipv6/addrconf: fix a potential refcount underflow for idev
Jiasheng Jiang <jiasheng@iscas.ac.cn>
NTB: ntb_tool: Add check for devm_kcalloc
Yang Yingliang <yangyingliang@huawei.com>
NTB: ntb_transport: fix possible memory leak while device_register() fails
Yuan Can <yuancan@huawei.com>
ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
ntb: idt: Fix error handling in idt_pci_driver_init()
Eric Dumazet <edumazet@google.com>
udp6: fix udp6_ehashfn() typo
Kuniyuki Iwashima <kuniyu@amazon.com>
icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
Paolo Abeni <pabeni@redhat.com>
net: prevent skb corruption on frag list segmentation
Rafał Miłecki <rafal@milecki.pl>
net: bgmac: postpone turning IRQs off to avoid SoC hangs
Nitya Sunkad <nitya.sunkad@amd.com>
ionic: remove WARN_ON to prevent panic_on_warn
Junfeng Guo <junfeng.guo@intel.com>
gve: Set default duplex configuration to full
M A Ramdhan <ramdhan@starlabs.sg>
net/sched: cls_fw: Fix improper refcount update leads to use-after-free
Klaus Kudielka <klaus.kudielka@gmail.com>
net: mvneta: fix txq_map in case of txq_number==1
Dan Carpenter <dan.carpenter@linaro.org>
scsi: qla2xxx: Fix error code in qla2x00_start_sp()
Prasad Koya <prasad@arista.com>
igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
Vlad Buslov <vladbu@nvidia.com>
net/mlx5e: Check for NOT_READY flag state after locking
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix double free in mlx5e_destroy_flow_table
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Remove delay during TX ring configuration
Marek Vasut <marex@denx.de>
drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
Fabio Estevam <festevam@denx.de>
drm/panel: simple: Add connector_type for innolux_at043tn24
Linus Torvalds <torvalds@linux-foundation.org>
workqueue: clean up WORK_* constant types, clarify masking
Moritz Fischer <moritzf@google.com>
net: lan743x: Don't sleep in atomic context
Jens Axboe <axboe@kernel.dk>
io_uring: add reschedule point to handle_tw_list()
Andres Freund <andres@anarazel.de>
io_uring: Use io_schedule* in cqring wait
Michael Schmitz <schmitzmic@gmail.com>
block/partition: fix signedness issue for Amiga partitions
Paul E. McKenney <paulmck@kernel.org>
rcu-tasks: Simplify trc_read_check_handler() atomic operations
Paul E. McKenney <paulmck@kernel.org>
rcu-tasks: Mark ->trc_reader_special.b.need_qs data races
Paul E. McKenney <paulmck@kernel.org>
rcu-tasks: Mark ->trc_reader_nesting data races
Sherry Sun <sherry.sun@nxp.com>
tty: serial: fsl_lpuart: add earlycon for imx8ulp platform
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: netlink: send staged packets when setting initial private key
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: use saner cpu selection wrapping
Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
netfilter: nf_tables: do not ignore genmask when looking up chain by id
Florent Revest <revest@chromium.org>
netfilter: conntrack: Avoid nf_ct_helper_hash uses after free
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: fix scheduling-while-atomic splat
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: unbind non-anonymous set if rule construction fails
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: drop map element references from preparation phase
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: rename set element data activation/deactivation functions
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: reject unbound chain set before commit phase
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: reject unbound anonymous set before commit phase
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: add NFT_TRANS_PREPARE_ERROR to deal with bound set/chain
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: fix chain binding transaction logic
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: add rescheduling points during loop detection walks
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: use net_generic infra for transaction data
Geert Uytterhoeven <geert+renesas@glider.be>
sh: pgtable-3level: Fix cast to pointer from integer of different size
Michael Schmitz <schmitzmic@gmail.com>
block: add overflow checks for Amiga partition support
Gilad Reti <gilad.reti@gmail.com>
selftests/bpf: Add verifier test for PTR_TO_MEM spill
Lino Sanfilippo <l.sanfilippo@kunbus.com>
tpm, tpm_tis: Claim locality in interrupt handler
Amir Goldstein <amir73il@gmail.com>
fanotify: disallow mount/sb marks on kernel internal pseudo fs
Jan Kara <jack@suse.cz>
fs: no need to check source
Christian Marangi <ansuelsmth@gmail.com>
leds: trigger: netdev: Recheck NETDEV_LED_MODE_LINKUP on dev rename
Arnd Bergmann <arnd@arndb.de>
ARM: orion5x: fix d2net gpio initialization
Ricardo Ribalda Delgado <ribalda@chromium.org>
ASoC: mediatek: mt8173: Fix snd_soc_component_initialize error path
Ricardo Ribalda Delgado <ribalda@chromium.org>
ASoC: mediatek: mt8173: Fix irq error path
Filipe Manana <fdmanana@suse.com>
btrfs: fix race when deleting quota root from the dirty cow roots list
Matt Corallo <blnxfsl@bluematt.me>
btrfs: add handling for RAID1C23/DUP to btrfs_reduce_alloc_profile
Jan Kara <jack@suse.cz>
fs: Lock moved directories
Jan Kara <jack@suse.cz>
fs: Establish locking order for unrelated directories
Jan Kara <jack@suse.cz>
Revert "f2fs: fix potential corruption when moving a directory"
Jan Kara <jack@suse.cz>
ext4: Remove ext4 locking of moved directory
Thomas Weißschuh <linux@weissschuh.net>
fs: avoid empty option when generating legacy mount string
Fabian Frederick <fabf@skynet.be>
jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
Roberto Sassu <roberto.sassu@huawei.com>
shmem: use ramfs_kill_sb() for kill_sb method of ramfs-based tmpfs
Arnd Bergmann <arnd@arndb.de>
autofs: use flexible array in ioctl structure
Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
integrity: Fix possible multiple allocation in integrity_inode_get()
Kees Cook <keescook@chromium.org>
um: Use HOST_DIR for mrproper
Zheng Wang <zyytlz.wz@163.com>
bcache: Fix __bch_btree_node_alloc to make the failure behavior consistent
Zheng Wang <zyytlz.wz@163.com>
bcache: Remove unnecessary NULL point check in node allocations
Mingzhe Zou <mingzhe.zou@easystack.cn>
bcache: fixup btree_cache_wait list damage
Chevron Li <chevron.li@bayhubtech.com>
mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is used.
Ulf Hansson <ulf.hansson@linaro.org>
mmc: mmci: Set PROBE_PREFER_ASYNCHRONOUS
Robert Marko <robimarko@gmail.com>
mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
Robert Marko <robimarko@gmail.com>
mmc: core: disable TRIM on Kingston EMMC04G-M627
Jens Axboe <axboe@kernel.dk>
io_uring: wait interruptibly for request completions on exit
Dai Ngo <dai.ngo@oracle.com>
NFSD: add encoding of op_recall flag for write delegation
Shuai Jiang <d202180596@hust.edu.cn>
i2c: qup: Add missing unwind goto in qup_i2c_probe()
Takashi Iwai <tiwai@suse.de>
ALSA: jack: Fix mutex call in snd_jack_report()
Robert Hancock <robert.hancock@calian.com>
i2c: xiic: Don't try to handle more interrupt events after error
Marek Vasut <marex@denx.de>
i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()
Danila Chernetsov <listdansp@mail.ru>
apparmor: fix missing error check for rhashtable_insert_fast
Artur Rojek <contact@artur-rojek.eu>
sh: dma: Fix DMA channel offset calculation
Thorsten Winkler <twinkler@linux.ibm.com>
s390/qeth: Fix vipa deletion
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: tag_sja1105: fix MAC DA patching from meta frames
Guillaume Nault <gnault@redhat.com>
pptp: Fix fib lookup calls.
Lin Ma <linma@zju.edu.cn>
net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
Ilya Maximets <i.maximets@ovn.org>
xsk: Honor SO_BINDTODEVICE on bind
Eric Dumazet <edumazet@google.com>
tcp: annotate data races in __tcp_oow_rate_limited()
Vladimir Oltean <vladimir.oltean@nxp.com>
net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode
Randy Dunlap <rdunlap@infradead.org>
powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-af: Fix mapping for NIX block from CGX connection
Chao Yu <chao@kernel.org>
f2fs: fix error path handling in truncate_dnode()
Nishanth Menon <nm@ti.com>
mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0
Jonas Gorski <jonas.gorski@gmail.com>
spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
Pawel Dembicki <paweldembicki@gmail.com>
net: dsa: vsc73xx: fix MTU configuration
Tobias Heider <me@tobhe.de>
Add MODULE_FIRMWARE() for FIRMWARE_TG357766.
Chengfeng Ye <dg573847474@gmail.com>
sctp: fix potential deadlock on &net->sctp.addr_wq_lock
Randy Dunlap <rdunlap@infradead.org>
media: cec: i2c: ch7322: also select REGMAP
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
Marek Vasut <marex@denx.de>
pwm: sysfs: Do not apply state to already disabled PWMs
Fancy Fang <chen.fang@nxp.com>
pwm: imx-tpm: force 'real_period' to be zero in suspend
Claudiu Beznea <claudiu.beznea@microchip.com>
phy: tegra: xusb: check return value of devm_kzalloc()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mfd: stmpe: Only disable the regulators if they are enabled
Pierre Morel <pmorel@linux.ibm.com>
KVM: s390: vsie: fix the length of APCB bitmap
Amelie Delaunay <amelie.delaunay@foss.st.com>
mfd: stmfx: Nullify stmfx->vdd in case of error
Amelie Delaunay <amelie.delaunay@foss.st.com>
mfd: stmfx: Fix error path in stmfx_chip_init
Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation
Tony Lindgren <tony@atomide.com>
serial: 8250_omap: Use force_suspend and resume for system suspend
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Revert "usb: common: usb-conn-gpio: Set last role to unknown before initial detection"
Jiasheng Jiang <jiasheng@iscas.ac.cn>
mfd: intel-lpss: Add missing check for platform_get_resource
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc3-meson-g12a: Fix an error handling path in dwc3_meson_g12a_probe()
Prashanth K <quic_prashk@quicinc.com>
usb: common: usb-conn-gpio: Set last role to unknown before initial detection
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc3: qcom: Fix an error handling path in dwc3_qcom_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc3: qcom: Release the correct resources in dwc3_qcom_remove()
Nico Boehr <nrb@linux.ibm.com>
KVM: s390: fix KVM_S390_GET_CMMA_BITS for GFNs in memslot holes
Dan Carpenter <dan.carpenter@linaro.org>
media: atomisp: gmin_platform: fix out_len in gmin_get_config_dsm_var()
Rikard Falkeborn <rikard.falkeborn@gmail.com>
media: venus: helpers: Fix ALIGN() of non power of two
Stephan Gerhold <stephan@gerhold.net>
mfd: rt5033: Drop rt5033-battery sub-device
James Clark <james.clark@arm.com>
coresight: Fix loss of connection info when a module is unloaded
Muchun Song <songmuchun@bytedance.com>
kernfs: fix missing kernfs_idr_lock to remove an ID from the IDR
John Ogness <john.ogness@linutronix.de>
serial: 8250: lock port for UART_IER access in omap8250_irq()
John Ogness <john.ogness@linutronix.de>
serial: 8250: lock port for stop_rx() in omap8250_irq()
Arnd Bergmann <arnd@arndb.de>
usb: hide unused usbfs_notify_suspend/resume functions
Li Yang <lidaxian@hust.edu.cn>
usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
extcon: Fix kernel doc of property capability fields to avoid warnings
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
extcon: Fix kernel doc of property fields to avoid warnings
Prashanth K <quic_prashk@quicinc.com>
usb: gadget: u_serial: Add null pointer check in gserial_suspend
Vladislav Efanov <VEfanov@ispras.ru>
usb: dwc3: qcom: Fix potential memory leak
Robert Marko <robimarko@gmail.com>
clk: qcom: ipq6018: fix networking resets
Robert Marko <robimarko@gmail.com>
clk: qcom: reset: support resetting multiple bits
Stephan Gerhold <stephan.gerhold@kernkonzept.com>
clk: qcom: reset: Allow specifying custom reset delay
Duoming Zhou <duoming@zju.edu.cn>
media: usb: siano: Fix warning due to null work_func_t function pointer
Marek Vasut <marex@denx.de>
media: videodev2.h: Fix struct v4l2_input tuner index comment
Daniil Dulov <d.dulov@aladdin.ru>
media: usb: Check az6007_read() return value
Mantas Pucka <mantas@8devices.com>
clk: qcom: gcc-ipq6018: Use floor ops for sdcc clocks
Tony Lindgren <tony@atomide.com>
serial: 8250: omap: Fix freeing of resources on failed register
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
sh: j2: Use ioremap() to translate device tree address into kernel memory
Dan Carpenter <dan.carpenter@oracle.com>
w1: fix loop in w1_fini()
Stefan Wahren <stefan.wahren@i2se.com>
w1: w1_therm: fix locking behavior in convert_t
Ding Hui <dinghui@sangfor.com.cn>
SUNRPC: Fix UAF in svc_tcp_listen_data_ready()
Michael Schmitz <schmitzmic@gmail.com>
block: change all __u32 annotations to __be32 in affs_hardblocks.h
Michael Schmitz <schmitzmic@gmail.com>
block: fix signed int overflow in Amiga partition support
EJ Hsu <ejh@nvidia.com>
phy: tegra: xusb: Clear the driver reference in usb-phy dev
Krishna Kurapati <quic_kriskura@quicinc.com>
usb: dwc3: gadget: Propagate core init errors to UDC during pullup
Davide Tronchin <davide.tronchin.94@gmail.com>
USB: serial: option: add LARA-R6 01B PIDs
Jens Axboe <axboe@kernel.dk>
io_uring: ensure IOPOLL locks around deferred work
Martin Kaiser <martin@kaiser.cx>
hwrng: st - keep clock enabled while hwrng is registered
Dan Williams <dan.j.williams@intel.com>
dax: Introduce alloc_dev_dax_id()
Dan Williams <dan.j.williams@intel.com>
dax: Fix dax_mapping_release() use after free
Olga Kornievskaia <kolga@netapp.com>
NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
Masahiro Yamada <masahiroy@kernel.org>
ARC: define ASM_NL and __ALIGN(_STR) outside #ifdef __ASSEMBLY__ guard
Dan Carpenter <dan.carpenter@linaro.org>
modpost: fix off by one in is_executable_section()
Arnd Bergmann <arnd@arndb.de>
crypto: marvell/cesa - Fix type mismatch warning
Masahiro Yamada <masahiroy@kernel.org>
modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24}
Masahiro Yamada <masahiroy@kernel.org>
modpost: fix section mismatch message for R_ARM_ABS32
Randy Dunlap <rdunlap@infradead.org>
crypto: nx - fix build warnings when DEBUG_FS is not enabled
Herbert Xu <herbert@gondor.apana.org.au>
hwrng: virtio - Fix race on data_avail and actual data
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - always add a pending request
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - don't waste entropy
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - don't wait on cleanup
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - add an internal buffer
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
powerpc/mm/dax: Fix the condition when checking if altmap vmemap can cross-boundary
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
powerpc/book3s64/mm: Fix DirectMap stats in /proc/meminfo
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
mm: rename p4d_page_vaddr to p4d_pgtable and make it return pud_t *
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
mm: rename pud_page_vaddr to pud_pgtable and make it return pmd_t *
Colin Ian King <colin.i.king@gmail.com>
powerpc/powernv/sriov: perform null check on iov before dereferencing iov
Claudiu Beznea <claudiu.beznea@microchip.com>
pinctrl: at91-pio4: check return value of devm_kasprintf()
Namhyung Kim <namhyung@kernel.org>
perf dwarf-aux: Fix off-by-one in die_get_varname()
Arnaldo Carvalho de Melo <acme@redhat.com>
perf script: Fix allocation of evsel->priv related to per-event dump files
Arnaldo Carvalho de Melo <acme@redhat.com>
perf script: Fixup 'struct evsel_script' method prefix
Christophe Leroy <christophe.leroy@csgroup.eu>
kcsan: Don't expect 64 bits atomic builtins from 32 bits architectures
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
pinctrl: cherryview: Return correct value if pin in push-pull mode
Arnaldo Carvalho de Melo <acme@redhat.com>
perf bench: Add missing setlocale() call to allow usage of %'d style formatting
Sohaib Mohamed <sohaib.amhmd@gmail.com>
perf bench: Use unbuffered output when pipe/tee'ing to a file
Sui Jingfeng <suijingfeng@loongson.cn>
PCI: Add pci_clear_master() stub for non-CONFIG_PCI
Junyan Ye <yejunyan@hust.edu.cn>
PCI: ftpci100: Release the clock resources
Rongguang Wei <weirongguang@kylinos.cn>
PCI: pciehp: Cancel bringup sequence if card is not present
Yuchen Yang <u202114568@hust.edu.cn>
scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
Ding Hui <dinghui@sangfor.com.cn>
PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
pinctrl: bcm2835: Handle gpiochip_add_pin_range() errors
Jinhong Zhu <jinhongzhu@hust.edu.cn>
scsi: qedf: Fix NULL dereference in error handling
Siddharth Vadapalli <s-vadapalli@ti.com>
PCI: cadence: Fix Gen2 Link Retraining process
Claudiu Beznea <claudiu.beznea@microchip.com>
ASoC: imx-audmix: check return value of devm_kasprintf()
Amir Goldstein <amir73il@gmail.com>
ovl: update of dentry revalidate flags after copy up
Alexey Romanov <avromanov@sberdevices.ru>
drivers: meson: secure-pwrc: always enable DMA domain
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: ti: clkctrl: check return value of kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: keystone: sci-clk: check return value of kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: si5341: free unused memory on probe failure
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: si5341: check return value of {devm_}kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: si5341: return error if one synth clock registration fails
Robert Hancock <robert.hancock@calian.com>
clk: si5341: Add sysfs properties to allow checking/resetting device faults
Robert Hancock <robert.hancock@calian.com>
clk: si5341: Allow different output VDD_SEL values
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: cdce925: check return value of kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: vc5: check memory returned by kasprintf()
Bjorn Andersson <quic_bjorande@quicinc.com>
drm/msm/dp: Free resources after unregistering them
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: do not enable color-management if DSPPs are not available
Su Hui <suhui@nfschina.com>
ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer
Yuan Can <yuancan@huawei.com>
clk: tegra: tegra124-emc: Fix potential memory leak
Yuxing Liu <lyx2022@hust.edu.cn>
clk: imx: clk-imx8mp: improve error handling in imx8mp_clocks_probe()
Hao Luo <m202171776@hust.edu.cn>
clk: imx: clk-imx8mn: fix memory leak in imx8mn_clocks_probe
Kashyap Desai <kashyap.desai@broadcom.com>
RDMA/bnxt_re: Avoid calling wake_up threads from spin_lock context
Kashyap Desai <kashyap.desai@broadcom.com>
RDMA/bnxt_re: wraparound mbox producer index
Chia-I Wu <olvaffe@gmail.com>
amdgpu: validate offset_in_bo of drm_amdgpu_gem_va
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
drm/radeon: fix possible division-by-zero errors
Daniil Dulov <d.dulov@aladdin.ru>
drm/amdkfd: Fix potential deallocation of previously deallocated memory.
Christian Lamparter <chunkeey@gmail.com>
ARM: dts: BCM5301X: fix duplex-full => full-duplex
Guenter Roeck <linux@roeck-us.net>
hwmon: (pmbus/adm1275) Fix problems with temperature monitoring on ADM1272
Potin Lai <potin.lai@quantatw.com>
hwmon: (adm1275) Allow setting sample averaging
Chu Lin <linchuyuan@google.com>
hwmon: (adm1275) enable adm1272 temperature reporting
Tim Harvey <tharvey@gateworks.com>
hwmon: (gsc-hwmon) fix fan pwm temperature scaling
Olivier Moysan <olivier.moysan@foss.st.com>
ARM: dts: stm32: fix i2s endpoint format property for stm32mp15xx-dkx
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Fix audio routing on STM32MP15xx DHCOM PDK2
Keerthy <j-keerthy@ti.com>
arm64: dts: ti: k3-j7200: Fix physical address of pin
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe()
Wolfram Sang <wsa+renesas@sang-engineering.com>
arm64: dts: renesas: ulcb-kf: Remove flow control for SCIF1
Geert Uytterhoeven <geert+renesas@glider.be>
ARM: dts: iwg20d-q7-common: Fix backlight pwm specifier
Chengchang Tang <tangchengchang@huawei.com>
RDMA/hns: Fix hns_roce_table_get return value
Xi Wang <wangxi11@huawei.com>
RDMA/hns: Clean the hardware related code for HEM
Weihang Li <liweihang@huawei.com>
RDMA/hns: Use refcount_t APIs for HEM
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Fix coding style issues
Jason Gunthorpe <jgg@ziepe.ca>
RDMA: Remove uverbs_ex_cmd_mask values that are linked to functions
Brendan Cunningham <bcunningham@cornelisnetworks.com>
IB/hfi1: Fix wrong mmu_node used for user SDMA packet after invalidate
Patrick Kelsey <pat.kelsey@cornelisnetworks.com>
IB/hfi1: Fix sdma.h tx->num_descs off-by-one errors
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
IB/hfi1: Use bitmap_zalloc() when applicable
Randy Dunlap <rdunlap@infradead.org>
soc/fsl/qe: fix usb.c build errors
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
ARM: dts: meson8: correct uart_B and uart_C clock references
Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
ASoC: es8316: Do not set rate constraints for unsupported MCLKs
Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
ASoC: es8316: Increment max value for ALC Capture Target Volume control
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
memory: brcmstb_dpfe: fix testing array offset after use
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Shorten the AV96 HDMI sound card name
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: apq8096: fix fixed regulator name property
Arnd Bergmann <arnd@arndb.de>
ARM: omap2: fix missing tick_broadcast() prototype
Arnd Bergmann <arnd@arndb.de>
ARM: ep93xx: fix missing-prototype warnings
Dario Binacchi <dario.binacchi@amarulasolutions.com>
drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: msm8996: correct camss unit address
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: msm8994: correct SPMI unit address
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: msm8916: correct camss unit address
Tony Lindgren <tony@atomide.com>
ARM: dts: gta04: Move model property out of pinctrl node
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Fix to remove an unnecessary log
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Remove a redundant check inside bnxt_re_update_gid
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Use unique names while registering interrupts
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Fix to remove unnecessary return labels
Selvin Xavier <selvin.xavier@broadcom.com>
RDMA/bnxt_re: Disable/kill tasklet only if it is enabled
Robert Marko <robert.marko@sartura.hr>
arm64: dts: microchip: sparx5: do not use PSCI on reference boards
Tony Lindgren <tony@atomide.com>
bus: ti-sysc: Fix dispc quirk masking bool variables
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Move ethernet MAC EEPROM from SoM to carrier boards
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/panel: sharp-ls043t1le01: adjust mode settings
XuDong Liu <m202071377@hust.edu.cn>
drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
Marek Vasut <marex@denx.de>
Input: adxl34x - do not hardcode interrupt trigger type
hfdevel@gmx.net <hfdevel@gmx.net>
ARM: dts: meson8b: correct uart_B and uart_C clock references
Rafał Miłecki <rafal@milecki.pl>
ARM: dts: BCM5301X: Drop "clock-names" from the SPI node
Luc Ma <luc@sietium.com>
drm/vram-helper: fix function names in vram helper doc
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix THS_TRAILCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix TXTAGOCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix THS_ZEROCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix TCLK_TRAILCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: Add atomic_get_input_bus_fmts() implementation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix TCLK_ZEROCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix PLL target frequency
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix PLL parameters computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: always enable HS video mode
Luca Weiss <luca@z3ntu.xyz>
Input: drv260x - sleep between polling GO bit
Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
drm/amd/display: Explicitly specify update type per plane info change
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
radeon: avoid double free in ci_dpm_init()
Kuniyuki Iwashima <kuniyu@amazon.com>
netlink: Add __sock_i_ino() for __netlink_diag_dump().
Cambda Zhu <cambda@linux.alibaba.com>
ipvlan: Fix return value of ipvlan_queue_xmit()
Ilia.Gavrilov <Ilia.Gavrilov@infotecs.ru>
netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return value.
Florian Westphal <fw@strlen.de>
netfilter: conntrack: dccp: copy entire header to stack buffer, not just basic one
Jeremy Sowden <jeremy@azazel.net>
lib/ts_bm: reset initial match offset for every block of text
Lin Ma <linma@zju.edu.cn>
net: nfc: Fix use-after-free caused by nfc_llcp_find_local
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
nfc: llcp: simplify llcp_sock_connect() error paths
Edward Cree <ecree.xilinx@gmail.com>
sfc: fix crash when reading stats while NIC is resetting
Maxim Kochetkov <fido_max@inbox.ru>
net: axienet: Move reset before 64-bit DMA detection
Kuniyuki Iwashima <kuniyu@amazon.com>
gtp: Fix use-after-free in __gtp_encap_destroy().
Sabrina Dubroca <sd@queasysnail.net>
selftests: rtnetlink: remove netdevsim device after ipsec offload test
Eric Dumazet <edumazet@google.com>
netlink: do not hard code device address lenth in fdb dumps
Eric Dumazet <edumazet@google.com>
netlink: fix potential deadlock in netlink_set_err()
Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
net: stmmac: fix double serdes powerdown
Vinicius Costa Gomes <vinicius.gomes@intel.com>
igc: Fix race condition in PTP tx code
Dmitry Antipov <dmantipov@yandex.ru>
wifi: ath9k: convert msecs to jiffies where needed
Benjamin Berg <benjamin.berg@intel.com>
wifi: cfg80211: rewrite merging of inherited elements
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: pull from TXQs with softirqs disabled
Edwin Peer <edwin.peer@broadcom.com>
rtnetlink: extend RTEXT_FILTER_SKIP_STATS to IFLA_VF_INFO
Remi Pommarel <repk@triplefau.lt>
wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
Arnd Bergmann <arnd@arndb.de>
memstick r592: make memstick_debug_get_tpc_name() static
Zhen Lei <thunder.leizhen@huawei.com>
kexec: fix a memory leak in crash_shrink_memory()
Douglas Anderson <dianders@chromium.org>
watchdog/perf: more properly prevent false positives with turbo modes
Douglas Anderson <dianders@chromium.org>
watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct config
Marek Vasut <marex@denx.de>
wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown
Marek Vasut <marex@denx.de>
wifi: rsi: Do not configure WoWlan in shutdown hook if not enabled
Fedor Pchelkin <pchelkin@ispras.ru>
wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: ray_cs: Fix an error handling path in ray_probe()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
wifi: ray_cs: Drop useless status variable in parse_addr()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
wifi: ray_cs: Utilize strnlen() in parse_addr()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: wl3501_cs: Fix an error handling path in wl3501_probe()
Jakub Kicinski <kuba@kernel.org>
wl3501_cs: use eth_hw_addr_set()
Jakub Kicinski <kuba@kernel.org>
net: create netdev->dev_addr assignment helpers
Lee Jones <lee.jones@linaro.org>
wl3501_cs: Fix misspelling and provide missing documentation
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: atmel: Fix an error handling path in atmel_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: orinoco: Fix an error handling path in orinoco_cs_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: orinoco: Fix an error handling path in spectrum_cs_probe()
Geert Uytterhoeven <geert+renesas@glider.be>
regulator: core: Streamline debugfs operations
Geert Uytterhoeven <geert+renesas@glider.be>
regulator: core: Fix more error checking for debugfs_create_dir()
Alan Maguire <alan.maguire@oracle.com>
bpftool: JIT limited misreported as negative value on aarch64
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
nfc: llcp: fix possible use of uninitialized variable in nfc_llcp_send_connect()
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
nfc: constify several pointers to u8, char and sk_buff
Andrii Nakryiko <andrii@kernel.org>
libbpf: fix offsetof() and container_of() to work with CO-RE
Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
sctp: add bpf_bypass_getsockopt proto callback
Stanislav Fomichev <sdf@google.com>
bpf: Remove extra lock_sock for TCP_ZEROCOPY_RECEIVE
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: mwifiex: Fix the size of a memory allocation in mwifiex_ret_802_11_scan()
Amisha Patel <amisha.patel@microchip.com>
wifi: wilc1000: fix for absent RSN capabilities WFA testcase
Vijaya Krishna Nivarthi <quic_vnivarth@quicinc.com>
spi: spi-geni-qcom: Correct CS_TOGGLE bit in SPI_TRANS_CFG
Pengcheng Yang <yangpc@wangsu.com>
samples/bpf: Fix buffer overflow in tcp_basertt
Fedor Pchelkin <pchelkin@ispras.ru>
wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx
Peter Seiderer <ps.report@gmx.net>
wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation
Jesper Dangaard Brouer <brouer@redhat.com>
igc: Enable and fix RX hash usage by netstack
Jiasheng Jiang <jiasheng@iscas.ac.cn>
pstore/ram: Add check for kstrdup
Roberto Sassu <roberto.sassu@huawei.com>
ima: Fix build warnings
Roberto Sassu <roberto.sassu@huawei.com>
evm: Complete description of evm_inode_setattr()
Juergen Gross <jgross@suse.com>
x86/mm: Fix __swp_entry_to_pte() for Xen PV guests
Ravi Bangoria <ravi.bangoria@amd.com>
perf/ibs: Fix interface via core pmu events
Qiuxu Zhuo <qiuxu.zhuo@intel.com>
rcu/rcuscale: Stop kfree_scale_thread thread(s) after unloading rcuscale
Qiuxu Zhuo <qiuxu.zhuo@intel.com>
rcu/rcuscale: Move rcu_scale_*() after kfree_scale_cleanup()
Paul E. McKenney <paulmck@kernel.org>
rcuscale: Move shutdown from wait_event() to wait_event_idle()
Li Zhijian <zhijianx.li@intel.com>
rcuscale: Always log error message
Jiangong.Han <jiangong.han@windriver.com>
rcuscale: Console output claims too few grace periods
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
thermal/drivers/sun8i: Fix some error handling paths in sun8i_ths_probe()
Tero Kristo <tero.kristo@linux.intel.com>
cpufreq: intel_pstate: Fix energy_performance_preference for passive
Arnd Bergmann <arnd@arndb.de>
ARM: 9303/1: kprobes: avoid missing-declaration warnings
Zhang Rui <rui.zhang@intel.com>
powercap: RAPL: Fix CONFIG_IOSF_MBI dependency
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix DTC reset
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
PM: domains: fix integer overflow issues in genpd_parse_state()
Feng Mingxi <m202271825@hust.edu.cn>
clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
tracing/timer: Add missing hrtimer modes to decode_hrtimer_mode().
Thomas Gleixner <tglx@linutronix.de>
posix-timers: Prevent RT livelock in itimer_delete()
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
irqchip/jcore-aic: Fix missing allocation of IRQ descriptors
Marc Zyngier <maz@kernel.org>
irqchip/jcore-aic: Kill use of irq_create_strict_mappings()
Li Nan <linan122@huawei.com>
md/raid10: fix io loss while replacement replace rdev
Li Nan <linan122@huawei.com>
md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request
Li Nan <linan122@huawei.com>
md/raid10: fix wrong setting of max_corr_read_errors
Li Nan <linan122@huawei.com>
md/raid10: fix overflow of md/safe_mode_delay
Li Nan <linan122@huawei.com>
md/raid10: check slab-out-of-bounds in md_bitmap_get_counter
Li Nan <linan122@huawei.com>
blk-iocost: use spin_lock_irqsave in adjust_inuse_and_calc_cost
Shawn Wang <shawnwang@linux.alibaba.com>
x86/resctrl: Only show tasks' pid in current pid namespace
Arnd Bergmann <arnd@arndb.de>
fs: pipe: reveal missing function protoypes
Finn Thain <fthain@linux-m68k.org>
nubus: Partially revert proc_create_single_data() conversion
Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
drm/amdgpu: Validate VM ioctl flags.
Ahmed S. Darwish <darwi@linutronix.de>
scripts/tags.sh: Resolve gtags empty index generation
Ricardo Cañuelo <ricardo.canuelo@collabora.com>
Revert "thermal/drivers/mediatek: Use devm_of_iomap to avoid resource leak in mtk_thermal_probe"
Mike Hommey <mh@glandium.org>
HID: logitech-hidpp: add HIDPP_QUIRK_DELAYED_INIT for the T651.
Jason Gerecke <jason.gerecke@wacom.com>
HID: wacom: Use ktime_t rather than int when dealing with timestamps
Zheng Wang <zyytlz.wz@163.com>
fbdev: imsttfb: Fix use after free bug in imsttfb_probe
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
video: imsttfb: check for ioremap() failures
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: isotp_sendmsg(): fix return error fix on TX path
Thomas Gleixner <tglx@linutronix.de>
x86/smp: Use dedicated cache-line for mwait_play_dead()
Tsuchiya Yuto <kitakar@gmail.com>
media: atomisp: fix "variable dereferenced before check 'asd'"
-------------
Diffstat:
Documentation/filesystems/autofs-mount-control.rst | 2 +-
Documentation/filesystems/autofs.rst | 2 +-
Documentation/filesystems/directory-locking.rst | 26 +-
Documentation/networking/af_xdp.rst | 9 +
Documentation/networking/ip-sysctl.rst | 25 +
Makefile | 4 +-
arch/alpha/include/asm/pgtable.h | 8 +-
arch/arc/include/asm/linkage.h | 8 +-
arch/arm/boot/dts/bcm53015-meraki-mr26.dts | 2 +-
arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 2 +-
arch/arm/boot/dts/bcm5301x.dtsi | 1 -
arch/arm/boot/dts/iwg20d-q7-common.dtsi | 2 +-
arch/arm/boot/dts/meson8.dtsi | 4 +-
arch/arm/boot/dts/meson8b.dtsi | 4 +-
arch/arm/boot/dts/omap3-gta04a5one.dts | 4 +-
arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi | 11 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 8 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi | 6 -
arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 2 +-
arch/arm/include/asm/pgtable-3level.h | 2 +-
arch/arm/mach-ep93xx/timer-ep93xx.c | 3 +-
arch/arm/mach-omap2/board-generic.c | 1 +
arch/arm/mach-orion5x/board-dt.c | 3 +
arch/arm/mach-orion5x/common.h | 6 +
arch/arm/probes/kprobes/checkers-common.c | 2 +-
arch/arm/probes/kprobes/core.c | 2 +-
arch/arm/probes/kprobes/opt-arm.c | 2 -
arch/arm/probes/kprobes/test-core.c | 2 +-
arch/arm/probes/kprobes/test-core.h | 4 +
arch/arm64/boot/dts/microchip/sparx5.dtsi | 2 +-
.../boot/dts/microchip/sparx5_pcb_common.dtsi | 12 +
arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts | 4 +-
arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8994.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8996.dtsi | 2 +-
arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 3 +-
.../boot/dts/ti/k3-j7200-common-proc-board.dts | 28 +-
arch/arm64/include/asm/exception.h | 5 -
arch/arm64/include/asm/pgtable.h | 8 +-
arch/arm64/mm/mmu.c | 4 +-
arch/ia64/include/asm/pgtable.h | 4 +-
arch/m68k/include/asm/motorola_pgtable.h | 2 +-
arch/mips/include/asm/pgtable-64.h | 8 +-
arch/mips/kernel/cpu-probe.c | 9 +-
arch/parisc/include/asm/pgtable.h | 4 +-
arch/powerpc/Kconfig.debug | 2 +-
arch/powerpc/Makefile | 8 +
arch/powerpc/include/asm/book3s/64/pgtable.h | 11 +-
arch/powerpc/include/asm/nohash/64/pgtable-4k.h | 6 +-
arch/powerpc/include/asm/nohash/64/pgtable.h | 6 +-
arch/powerpc/mm/book3s64/radix_pgtable.c | 40 +-
arch/powerpc/mm/init_64.c | 2 +-
arch/powerpc/mm/pgtable_64.c | 4 +-
arch/powerpc/platforms/powernv/pci-sriov.c | 6 +-
arch/riscv/include/asm/pgtable-64.h | 4 +-
arch/riscv/net/bpf_jit.h | 5 +-
arch/riscv/net/bpf_jit_comp64.c | 13 -
arch/riscv/net/bpf_jit_core.c | 29 +-
arch/s390/Makefile | 1 +
arch/s390/kvm/kvm-s390.c | 4 +
arch/s390/kvm/vsie.c | 6 +-
arch/sh/drivers/dma/dma-sh.c | 37 +-
arch/sh/include/asm/pgtable-3level.h | 4 +-
arch/sh/kernel/cpu/sh2/probe.c | 2 +-
arch/sparc/include/asm/pgtable_32.h | 6 +-
arch/sparc/include/asm/pgtable_64.h | 10 +-
arch/um/Makefile | 2 +-
arch/um/include/asm/pgtable-3level.h | 2 +-
arch/x86/events/amd/core.c | 2 +-
arch/x86/events/amd/ibs.c | 53 +-
arch/x86/include/asm/perf_event.h | 2 +
arch/x86/include/asm/pgtable.h | 8 +-
arch/x86/include/asm/pgtable_64.h | 4 +-
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 8 +-
arch/x86/kernel/smpboot.c | 24 +-
arch/x86/mm/init_64.c | 4 +-
arch/x86/mm/pat/set_memory.c | 4 +-
arch/x86/mm/pgtable.c | 2 +-
arch/xtensa/platforms/iss/network.c | 2 +-
block/blk-iocost.c | 7 +-
block/partitions/amiga.c | 104 +++-
drivers/acpi/button.c | 9 +
drivers/acpi/video_detect.c | 16 +
drivers/base/power/domain.c | 6 +-
drivers/base/regmap/regmap-i2c.c | 8 +-
drivers/base/regmap/regmap-spi-avmm.c | 2 +-
drivers/base/regmap/regmap.c | 6 +-
drivers/block/nbd.c | 3 +-
drivers/bus/ti-sysc.c | 4 +-
drivers/char/hw_random/imx-rngc.c | 6 +-
drivers/char/hw_random/st-rng.c | 21 +-
drivers/char/hw_random/virtio-rng.c | 86 ++-
drivers/char/tpm/tpm_tis_core.c | 2 +
drivers/char/tpm/tpm_vtpm_proxy.c | 30 +-
drivers/clk/clk-cdce925.c | 12 +
drivers/clk/clk-si5341.c | 242 +++++++-
drivers/clk/clk-versaclock5.c | 29 +
drivers/clk/imx/clk-imx8mn.c | 8 +-
drivers/clk/imx/clk-imx8mp.c | 24 +-
drivers/clk/keystone/sci-clk.c | 2 +
drivers/clk/qcom/gcc-ipq6018.c | 34 +-
drivers/clk/qcom/reset.c | 8 +-
drivers/clk/qcom/reset.h | 2 +
drivers/clk/tegra/clk-tegra124-emc.c | 2 +
drivers/clk/ti/clkctrl.c | 7 +
drivers/clocksource/timer-cadence-ttc.c | 19 +-
drivers/cpufreq/intel_pstate.c | 2 +
drivers/crypto/marvell/cesa/cipher.c | 2 +-
drivers/crypto/nx/Makefile | 2 +-
drivers/crypto/nx/nx.h | 4 +-
drivers/dax/bus.c | 61 +-
drivers/dax/dax-private.h | 4 +-
drivers/extcon/extcon.c | 8 +
drivers/firmware/stratix10-svc.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 20 +-
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 13 +-
drivers/gpu/drm/amd/display/dc/core/dc.c | 3 -
drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 +-
drivers/gpu/drm/bridge/tc358768.c | 93 ++-
drivers/gpu/drm/drm_atomic.c | 11 +-
drivers/gpu/drm/drm_atomic_helper.c | 11 +-
drivers/gpu/drm/drm_client_modeset.c | 6 +
drivers/gpu/drm/drm_gem_vram_helper.c | 6 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 5 +-
drivers/gpu/drm/msm/dp/dp_display.c | 2 +-
drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 11 +-
drivers/gpu/drm/panel/panel-simple.c | 6 +-
drivers/gpu/drm/radeon/ci_dpm.c | 28 +-
drivers/gpu/drm/radeon/cypress_dpm.c | 8 +-
drivers/gpu/drm/radeon/ni_dpm.c | 8 +-
drivers/gpu/drm/radeon/rv740_dpm.c | 8 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 +-
drivers/gpu/drm/sun4i/sun4i_tcon.c | 19 +-
drivers/hid/hid-logitech-hidpp.c | 2 +-
drivers/hid/wacom_wac.c | 6 +-
drivers/hid/wacom_wac.h | 2 +-
drivers/hwmon/gsc-hwmon.c | 6 +-
drivers/hwmon/pmbus/adm1275.c | 94 ++-
drivers/hwtracing/coresight/coresight-core.c | 9 +-
drivers/i2c/busses/i2c-qup.c | 21 +-
drivers/i2c/busses/i2c-xiic.c | 39 +-
drivers/iio/adc/meson_saradc.c | 2 +-
drivers/infiniband/core/cma.c | 23 +
drivers/infiniband/core/cma_priv.h | 1 +
drivers/infiniband/core/device.c | 11 +
drivers/infiniband/core/uverbs_cmd.c | 2 +-
drivers/infiniband/hw/bnxt_re/main.c | 20 +-
drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40 +-
drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2 +-
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c | 46 +-
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h | 1 +
drivers/infiniband/hw/efa/efa_main.c | 3 -
drivers/infiniband/hw/hfi1/ipoib_tx.c | 4 +-
drivers/infiniband/hw/hfi1/mmu_rb.c | 101 +--
drivers/infiniband/hw/hfi1/mmu_rb.h | 3 +
drivers/infiniband/hw/hfi1/sdma.c | 27 +-
drivers/infiniband/hw/hfi1/sdma.h | 62 +-
drivers/infiniband/hw/hfi1/sdma_txreq.h | 2 +
drivers/infiniband/hw/hfi1/user_sdma.c | 145 ++---
drivers/infiniband/hw/hfi1/user_sdma.h | 1 -
drivers/infiniband/hw/hfi1/vnic_sdma.c | 4 +-
drivers/infiniband/hw/hns/hns_roce_cmd.c | 27 +-
drivers/infiniband/hw/hns/hns_roce_cmd.h | 4 +-
drivers/infiniband/hw/hns/hns_roce_cq.c | 2 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 2 -
drivers/infiniband/hw/hns/hns_roce_hem.c | 131 +---
drivers/infiniband/hw/hns/hns_roce_hem.h | 15 +-
drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 93 ++-
drivers/infiniband/hw/hns/hns_roce_hw_v1.h | 7 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 9 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 6 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 8 +-
drivers/infiniband/hw/hns/hns_roce_mr.c | 4 +-
drivers/infiniband/hw/hns/hns_roce_qp.c | 2 +-
drivers/infiniband/hw/hns/hns_roce_srq.c | 1 -
drivers/infiniband/hw/mlx4/main.c | 14 +-
drivers/infiniband/hw/mlx5/main.c | 14 +-
drivers/input/misc/adxl34x.c | 3 +-
drivers/input/misc/drv260x.c | 1 +
drivers/irqchip/irq-jcore-aic.c | 11 +-
drivers/leds/trigger/ledtrig-netdev.c | 3 +
drivers/mailbox/ti-msgmgr.c | 12 +-
drivers/md/bcache/btree.c | 25 +-
drivers/md/bcache/btree.h | 1 +
drivers/md/bcache/super.c | 4 +-
drivers/md/bcache/writeback.c | 10 +
drivers/md/md-bitmap.c | 17 +-
drivers/md/md.c | 23 +-
drivers/md/raid0.c | 62 +-
drivers/md/raid0.h | 1 +
drivers/md/raid10.c | 38 +-
drivers/media/cec/i2c/Kconfig | 1 +
drivers/media/platform/qcom/venus/helpers.c | 4 +-
drivers/media/usb/dvb-usb-v2/az6007.c | 3 +-
drivers/media/usb/siano/smsusb.c | 3 +-
drivers/memory/brcmstb_dpfe.c | 4 +-
drivers/memstick/host/r592.c | 4 +-
drivers/mfd/intel-lpss-acpi.c | 3 +
drivers/mfd/rt5033.c | 3 -
drivers/mfd/stmfx.c | 7 +-
drivers/mfd/stmpe.c | 4 +-
drivers/misc/fastrpc.c | 2 +-
drivers/misc/pci_endpoint_test.c | 10 +-
drivers/mmc/core/quirks.h | 14 +
drivers/mmc/host/mmci.c | 1 +
drivers/mmc/host/sdhci.c | 4 +-
drivers/mtd/nand/raw/meson_nand.c | 4 +
drivers/net/dsa/vitesse-vsc73xx-core.c | 6 +-
drivers/net/ethernet/amazon/ena/ena_com.c | 3 +
drivers/net/ethernet/broadcom/bgmac.c | 4 +-
drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +
drivers/net/ethernet/broadcom/tg3.c | 1 +
drivers/net/ethernet/google/gve/gve_ethtool.c | 3 +
drivers/net/ethernet/intel/iavf/iavf_ethtool.c | 2 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 5 +-
drivers/net/ethernet/intel/igb/igb_main.c | 5 +
drivers/net/ethernet/intel/igc/igc.h | 33 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 2 +
drivers/net/ethernet/intel/igc/igc_main.c | 45 +-
drivers/net/ethernet/intel/igc/igc_ptp.c | 57 +-
drivers/net/ethernet/marvell/mvneta.c | 4 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 11 +
.../net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 2 +-
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5 +-
.../ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +-
drivers/net/ethernet/microchip/lan743x_main.c | 21 +-
drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5 -
drivers/net/ethernet/sfc/ef10.c | 13 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 -
drivers/net/ethernet/ti/cpsw_ale.c | 24 +-
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 10 +-
drivers/net/gtp.c | 2 +
drivers/net/ipvlan/ipvlan_core.c | 9 +-
drivers/net/netdevsim/dev.c | 9 +-
drivers/net/phy/phy_device.c | 21 +-
drivers/net/ppp/pptp.c | 31 +-
drivers/net/wireguard/netlink.c | 14 +-
drivers/net/wireguard/queueing.c | 1 +
drivers/net/wireguard/queueing.h | 25 +-
drivers/net/wireguard/receive.c | 2 +-
drivers/net/wireguard/send.c | 2 +-
drivers/net/wireless/ath/ath11k/mac.c | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_hw.c | 27 +-
drivers/net/wireless/ath/ath9k/htc_hst.c | 8 +-
drivers/net/wireless/ath/ath9k/main.c | 11 +-
drivers/net/wireless/ath/ath9k/wmi.c | 4 +
drivers/net/wireless/atmel/atmel_cs.c | 13 +-
drivers/net/wireless/cisco/airo.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 2 +-
drivers/net/wireless/intersil/orinoco/orinoco_cs.c | 13 +-
.../net/wireless/intersil/orinoco/spectrum_cs.c | 13 +-
drivers/net/wireless/marvell/mwifiex/scan.c | 6 +-
drivers/net/wireless/microchip/wilc1000/hif.c | 8 +-
drivers/net/wireless/ray_cs.c | 36 +-
drivers/net/wireless/rsi/rsi_91x_sdio.c | 9 +-
drivers/net/wireless/wl3501_cs.c | 27 +-
drivers/ntb/hw/amd/ntb_hw_amd.c | 7 +-
drivers/ntb/hw/idt/ntb_hw_idt.c | 7 +-
drivers/ntb/hw/intel/ntb_hw_gen1.c | 7 +-
drivers/ntb/ntb_transport.c | 2 +-
drivers/ntb/test/ntb_tool.c | 2 +
drivers/nubus/proc.c | 22 +-
drivers/nvme/host/pci.c | 3 +-
drivers/pci/controller/cadence/pcie-cadence-host.c | 27 +
drivers/pci/controller/dwc/pcie-qcom.c | 2 +
drivers/pci/controller/pci-ftpci100.c | 14 +-
drivers/pci/controller/pcie-rockchip-ep.c | 65 +-
drivers/pci/controller/pcie-rockchip.c | 17 +
drivers/pci/controller/pcie-rockchip.h | 11 +-
drivers/pci/hotplug/pciehp_ctrl.c | 8 +
drivers/pci/pci.c | 10 +-
drivers/pci/pcie/aspm.c | 21 +-
drivers/pci/quirks.c | 2 +
drivers/perf/arm-cmn.c | 7 +-
drivers/phy/tegra/xusb.c | 4 +
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 6 +-
drivers/pinctrl/intel/pinctrl-cherryview.c | 15 +-
drivers/pinctrl/pinctrl-amd.c | 41 +-
drivers/pinctrl/pinctrl-amd.h | 1 +
drivers/pinctrl/pinctrl-at91-pio4.c | 2 +
drivers/platform/x86/wmi.c | 64 +-
drivers/powercap/Kconfig | 4 +-
drivers/powercap/intel_rapl_msr.c | 1 -
drivers/pwm/pwm-imx-tpm.c | 7 +
drivers/pwm/sysfs.c | 17 +
drivers/regulator/core.c | 30 +-
drivers/rtc/rtc-st-lpc.c | 2 +-
drivers/s390/net/qeth_l3_sys.c | 2 +-
drivers/scsi/3w-xxxx.c | 4 +-
drivers/scsi/qedf/qedf_main.c | 3 +-
drivers/scsi/qla2xxx/qla_attr.c | 13 +
drivers/scsi/qla2xxx/qla_bsg.c | 6 +
drivers/scsi/qla2xxx/qla_def.h | 1 -
drivers/scsi/qla2xxx/qla_init.c | 2 +-
drivers/scsi/qla2xxx/qla_inline.h | 5 +-
drivers/scsi/qla2xxx/qla_iocb.c | 5 +-
drivers/scsi/qla2xxx/qla_nvme.c | 3 -
drivers/scsi/qla2xxx/qla_os.c | 3 +-
drivers/soc/amlogic/meson-secure-pwrc.c | 2 +-
drivers/soc/fsl/qe/Kconfig | 1 +
drivers/spi/spi-bcm-qspi.c | 10 +-
drivers/spi/spi-bcm63xx.c | 2 +-
drivers/spi/spi-geni-qcom.c | 2 +-
drivers/staging/media/atomisp/pci/atomisp_cmd.c | 3 +-
.../media/atomisp/pci/atomisp_gmin_platform.c | 2 +-
drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 3 +-
drivers/thermal/mtk_thermal.c | 14 +-
drivers/thermal/sun8i_thermal.c | 55 +-
drivers/tty/serial/8250/8250.h | 1 -
drivers/tty/serial/8250/8250_omap.c | 25 +-
drivers/tty/serial/8250/8250_pci.c | 19 -
drivers/tty/serial/8250/8250_port.c | 11 +-
drivers/tty/serial/atmel_serial.c | 4 +-
drivers/tty/serial/fsl_lpuart.c | 1 +
drivers/tty/serial/samsung_tty.c | 14 +-
drivers/usb/core/devio.c | 2 +
drivers/usb/dwc3/dwc3-meson-g12a.c | 5 +-
drivers/usb/dwc3/dwc3-qcom.c | 17 +-
drivers/usb/dwc3/gadget.c | 4 +-
drivers/usb/gadget/function/u_serial.c | 13 +-
drivers/usb/host/xhci-mem.c | 39 +-
drivers/usb/host/xhci-pci.c | 12 +
drivers/usb/host/xhci.h | 2 +
drivers/usb/phy/phy-tahvo.c | 2 +-
drivers/usb/serial/option.c | 4 +
drivers/video/fbdev/au1200fb.c | 3 +
drivers/video/fbdev/imsttfb.c | 34 +-
drivers/video/fbdev/imxfb.c | 4 +-
drivers/video/fbdev/omap/lcd_mipid.c | 6 +-
drivers/w1/slaves/w1_therm.c | 31 +-
drivers/w1/w1.c | 4 +-
fs/btrfs/block-group.c | 9 +-
fs/btrfs/disk-io.c | 3 +
fs/btrfs/qgroup.c | 3 +
fs/ceph/caps.c | 9 +
fs/dlm/plock.c | 4 +-
fs/erofs/zdata.c | 2 +-
fs/erofs/zmap.c | 6 +-
fs/ext4/indirect.c | 8 +
fs/ext4/inode.c | 10 -
fs/ext4/ioctl.c | 5 +-
fs/ext4/mballoc.c | 17 +-
fs/ext4/namei.c | 17 +-
fs/ext4/super.c | 13 +-
fs/ext4/xattr.c | 14 +
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 2 +-
fs/f2fs/gc.c | 22 +-
fs/f2fs/namei.c | 16 +-
fs/f2fs/node.c | 4 +-
fs/fs_context.c | 3 +-
fs/fuse/dir.c | 2 +-
fs/inode.c | 42 ++
fs/internal.h | 2 +
fs/jffs2/build.c | 5 +-
fs/jffs2/xattr.c | 13 +-
fs/jffs2/xattr.h | 4 +-
fs/jfs/jfs_dmap.c | 6 +
fs/jfs/jfs_filsys.h | 2 +
fs/kernfs/dir.c | 2 +
fs/namei.c | 25 +-
fs/nfs/nfs4proc.c | 1 +
fs/nfsd/nfs4xdr.c | 2 +-
fs/notify/fanotify/fanotify_user.c | 22 +-
fs/overlayfs/copy_up.c | 2 +
fs/overlayfs/dir.c | 3 +-
fs/overlayfs/export.c | 3 +-
fs/overlayfs/namei.c | 3 +-
fs/overlayfs/overlayfs.h | 6 +-
fs/overlayfs/super.c | 2 +-
fs/overlayfs/util.c | 24 +-
fs/pstore/ram_core.c | 2 +
fs/ramfs/inode.c | 2 +-
include/asm-generic/pgtable-nop4d.h | 2 +-
include/asm-generic/pgtable-nopmd.h | 2 +-
include/asm-generic/pgtable-nopud.h | 2 +-
include/linux/bpf-cgroup.h | 27 +-
include/linux/etherdevice.h | 12 +
include/linux/indirect_call_wrapper.h | 6 +
include/linux/netdevice.h | 18 +
include/linux/nmi.h | 2 +-
include/linux/pci.h | 1 +
include/linux/pgtable.h | 4 +-
include/linux/pipe_fs_i.h | 4 -
include/linux/ramfs.h | 1 +
include/linux/sched/signal.h | 2 +-
include/linux/serial_8250.h | 1 -
include/linux/tcp.h | 2 +-
include/linux/workqueue.h | 15 +-
include/net/netfilter/nf_tables.h | 41 +-
include/net/netns/ipv4.h | 1 +
include/net/netns/nftables.h | 7 -
include/net/nfc/nfc.h | 4 +-
include/net/pkt_sched.h | 2 +-
include/net/sock.h | 3 +
include/net/tcp.h | 32 +-
include/trace/events/timer.h | 6 +-
include/uapi/linux/affs_hardblocks.h | 68 +-
include/uapi/linux/auto_dev-ioctl.h | 2 +-
include/uapi/linux/videodev2.h | 2 +-
io_uring/io_uring.c | 66 +-
kernel/bpf/bpf_lru_list.c | 21 +-
kernel/bpf/bpf_lru_list.h | 7 +-
kernel/bpf/cgroup.c | 46 ++
kernel/kcsan/core.c | 2 +
kernel/kexec_core.c | 5 +-
kernel/rcu/rcuscale.c | 214 +++----
kernel/rcu/tasks.h | 37 +-
kernel/sched/fair.c | 2 +-
kernel/time/posix-timers.c | 74 ++-
kernel/trace/ftrace.c | 72 ++-
kernel/trace/ring_buffer.c | 24 +-
kernel/trace/trace.c | 3 +-
kernel/trace/trace_events_hist.c | 9 +-
kernel/trace/trace_probe_tmpl.h | 2 +
kernel/watchdog_hld.c | 6 +-
kernel/workqueue.c | 13 +-
lib/debugobjects.c | 9 +
lib/test_firmware.c | 12 +-
lib/ts_bm.c | 4 +-
mm/shmem.c | 2 +-
net/bridge/br_if.c | 5 +-
net/bridge/br_stp_if.c | 3 +
net/can/bcm.c | 12 +-
net/can/isotp.c | 5 +-
net/core/devlink.c | 5 +-
net/core/rtnetlink.c | 104 ++--
net/core/skbuff.c | 5 +
net/core/sock.c | 17 +-
net/dsa/tag_sja1105.c | 4 +-
net/ipv4/esp4.c | 2 +-
net/ipv4/inet_connection_sock.c | 3 +-
net/ipv4/inet_hashtables.c | 17 +-
net/ipv4/inet_timewait_sock.c | 8 +-
net/ipv4/sysctl_net_ipv4.c | 9 +
net/ipv4/tcp.c | 68 +-
net/ipv4/tcp_fastopen.c | 6 +-
net/ipv4/tcp_input.c | 12 +-
net/ipv4/tcp_ipv4.c | 3 +-
net/ipv4/tcp_minisocks.c | 9 +-
net/ipv4/tcp_output.c | 2 +-
net/ipv4/tcp_timer.c | 10 +-
net/ipv6/addrconf.c | 3 +-
net/ipv6/icmp.c | 5 +-
net/ipv6/ip6_gre.c | 3 +-
net/ipv6/tcp_ipv6.c | 3 +-
net/ipv6/udp.c | 2 +-
net/llc/llc_input.c | 3 -
net/netfilter/nf_conntrack_helper.c | 4 +
net/netfilter/nf_conntrack_proto_dccp.c | 52 +-
net/netfilter/nf_conntrack_sip.c | 2 +-
net/netfilter/nf_tables_api.c | 681 +++++++++++++++------
net/netfilter/nf_tables_offload.c | 30 +-
net/netfilter/nft_byteorder.c | 14 +-
net/netfilter/nft_chain_filter.c | 11 +-
net/netfilter/nft_dynset.c | 6 +-
net/netfilter/nft_immediate.c | 90 ++-
net/netfilter/nft_set_bitmap.c | 5 +-
net/netfilter/nft_set_hash.c | 23 +-
net/netfilter/nft_set_pipapo.c | 20 +-
net/netfilter/nft_set_rbtree.c | 5 +-
net/netlink/af_netlink.c | 5 +-
net/netlink/diag.c | 7 +-
net/nfc/core.c | 4 +-
net/nfc/hci/llc_shdlc.c | 10 +-
net/nfc/llcp.h | 9 +-
net/nfc/llcp_commands.c | 59 +-
net/nfc/llcp_core.c | 95 ++-
net/nfc/llcp_sock.c | 21 +-
net/nfc/netlink.c | 20 +-
net/nfc/nfc.h | 3 +-
net/sched/act_pedit.c | 1 +
net/sched/cls_flower.c | 10 +
net/sched/cls_fw.c | 10 +-
net/sched/sch_qfq.c | 41 +-
net/sctp/socket.c | 22 +-
net/socket.c | 3 +
net/sunrpc/svcsock.c | 23 +-
net/wireless/scan.c | 217 ++++---
net/wireless/wext-core.c | 6 +
net/xdp/xsk.c | 5 +
samples/bpf/tcp_basertt_kern.c | 2 +-
samples/ftrace/ftrace-direct-too.c | 14 +-
scripts/mod/modpost.c | 26 +-
scripts/tags.sh | 9 +-
security/apparmor/policy_unpack.c | 9 +-
security/integrity/evm/evm_main.c | 2 +
security/integrity/iint.c | 15 +-
security/integrity/ima/ima_modsig.c | 3 +
security/integrity/ima/ima_policy.c | 3 +-
security/keys/request_key.c | 35 +-
security/keys/trusted-keys/trusted_tpm2.c | 2 +-
sound/core/jack.c | 15 +-
sound/pci/ac97/ac97_codec.c | 4 +-
sound/pci/hda/patch_realtek.c | 28 +-
sound/soc/codecs/es8316.c | 23 +-
sound/soc/fsl/fsl_sai.c | 2 +-
sound/soc/fsl/fsl_sai.h | 1 +
sound/soc/fsl/imx-audmix.c | 9 +
sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 13 +-
tools/bpf/bpftool/feature.c | 24 +-
tools/include/uapi/linux/tcp.h | 357 +++++++++++
tools/lib/bpf/bpf_helpers.h | 15 +-
tools/perf/builtin-bench.c | 7 +-
tools/perf/builtin-script.c | 34 +-
tools/perf/tests/builtin-test.c | 3 +
.../tests/shell/test_uprobe_from_different_cu.sh | 77 +++
tools/perf/util/dwarf-aux.c | 2 +-
.../testing/selftests/bpf/prog_tests/bpf_tcp_ca.c | 1 +
.../selftests/bpf/prog_tests/cls_redirect.c | 1 +
.../selftests/bpf/prog_tests/sockmap_basic.c | 1 +
.../testing/selftests/bpf/prog_tests/sockopt_sk.c | 28 +
tools/testing/selftests/bpf/progs/sockopt_sk.c | 23 +-
tools/testing/selftests/bpf/test_progs.h | 1 -
tools/testing/selftests/bpf/test_verifier.c | 12 +-
tools/testing/selftests/bpf/verifier/spill_fill.c | 30 +
tools/testing/selftests/net/rtnetlink.sh | 1 +
tools/testing/selftests/tc-testing/config | 1 +
tools/testing/selftests/tc-testing/settings | 1 +
tools/testing/selftests/wireguard/netns.sh | 30 +-
522 files changed, 5604 insertions(+), 2683 deletions(-)
^ permalink raw reply [relevance 1%]
* Linux 6.4.5
@ 2023-07-23 12:28 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-23 12:28 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 6.4.5 kernel.
All users of the 6.4 kernel series must upgrade.
The updated 6.4.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-6.4.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/arm64/silicon-errata.rst | 3
Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst | 2
Makefile | 28 -
arch/arm64/Kconfig | 19
arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 7
arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts | 42 -
arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts | 76 +-
arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi | 29 +
arch/arm64/kernel/cpu_errata.c | 7
arch/arm64/kernel/traps.c | 2
arch/arm64/kvm/hyp/pgtable.c | 14
arch/arm64/mm/fault.c | 2
arch/arm64/tools/cpucaps | 1
arch/mips/Makefile | 10
arch/mips/include/asm/cpu-features.h | 4
arch/mips/include/asm/kvm_host.h | 6
arch/mips/kernel/cpu-probe.c | 9
arch/mips/kvm/emulate.c | 22
arch/mips/kvm/mips.c | 16
arch/mips/kvm/stats.c | 4
arch/mips/kvm/trace.h | 8
arch/mips/kvm/vz.c | 20
arch/openrisc/include/uapi/asm/sigcontext.h | 6
arch/openrisc/kernel/signal.c | 4
arch/powerpc/Makefile | 8
arch/powerpc/kernel/security.c | 37 -
arch/powerpc/mm/book3s64/hash_native.c | 13
arch/riscv/mm/init.c | 2
arch/riscv/net/bpf_jit.h | 6
arch/riscv/net/bpf_jit_core.c | 19
arch/s390/Makefile | 1
arch/x86/events/intel/core.c | 7
arch/xtensa/platforms/iss/network.c | 2
block/blk-crypto-profile.c | 12
drivers/accel/ivpu/ivpu_drv.h | 1
drivers/accel/ivpu/ivpu_hw_mtl.c | 20
drivers/base/regmap/regmap-irq.c | 2
drivers/bus/intel-ixp4xx-eb.c | 2
drivers/char/hw_random/imx-rngc.c | 6
drivers/char/tpm/tpm-chip.c | 7
drivers/char/tpm/tpm_crb.c | 19
drivers/char/tpm/tpm_tis.c | 25
drivers/char/tpm/tpm_tis_core.c | 103 +++
drivers/char/tpm/tpm_tis_core.h | 4
drivers/char/tpm/tpm_tis_i2c.c | 59 +-
drivers/char/tpm/tpm_vtpm_proxy.c | 30 -
drivers/firmware/stratix10-svc.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 3
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 12
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 64 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 26 +
drivers/gpu/drm/amd/display/dc/core/dc.c | 3
drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 10
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 11
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 4
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 2
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h | 1
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 2
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 15
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h | 2
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c | 11
drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 4
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 2
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 2
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 67 ++
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 35 -
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 2
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 33 -
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 9
drivers/gpu/drm/bridge/ti-sn65dsi86.c | 35 -
drivers/gpu/drm/display/drm_dp_mst_topology.c | 54 +-
drivers/gpu/drm/drm_atomic.c | 11
drivers/gpu/drm/drm_atomic_helper.c | 11
drivers/gpu/drm/drm_client.c | 21
drivers/gpu/drm/drm_fbdev_dma.c | 6
drivers/gpu/drm/drm_fbdev_generic.c | 4
drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4
drivers/gpu/drm/gma500/fbdev.c | 4
drivers/gpu/drm/i915/display/intel_display.c | 1
drivers/gpu/drm/i915/display/intel_dp.c | 7
drivers/gpu/drm/i915/gt/intel_gtt.c | 2
drivers/gpu/drm/msm/msm_fbdev.c | 4
drivers/gpu/drm/nouveau/dispnv50/disp.c | 12
drivers/gpu/drm/nouveau/nouveau_chan.c | 1
drivers/gpu/drm/nouveau/nouveau_chan.h | 1
drivers/gpu/drm/nouveau/nouveau_drm.c | 20
drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c | 1
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c | 2
drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 2
drivers/gpu/drm/omapdrm/omap_fbdev.c | 4
drivers/gpu/drm/panel/panel-simple.c | 2
drivers/gpu/drm/radeon/radeon_fbdev.c | 4
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8
drivers/gpu/drm/tegra/fbdev.c | 4
drivers/gpu/drm/ttm/ttm_bo.c | 23
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c | 30 -
drivers/hid/hid-hyperv.c | 10
drivers/hid/hid-input.c | 7
drivers/iio/adc/meson_saradc.c | 2
drivers/md/dm-integrity.c | 4
drivers/md/dm-verity-loadpin.c | 3
drivers/md/raid0.c | 62 ++
drivers/md/raid0.h | 1
drivers/mfd/qcom-pm8008.c | 1
drivers/misc/fastrpc.c | 2
drivers/misc/pci_endpoint_test.c | 10
drivers/mtd/nand/raw/meson_nand.c | 4
drivers/net/dsa/hirschmann/hellcreek.c | 14
drivers/net/dsa/ocelot/felix.c | 6
drivers/net/dsa/ocelot/felix.h | 1
drivers/net/dsa/ocelot/felix_vsc9959.c | 28 -
drivers/net/dsa/qca/qca8k-8xxx.c | 3
drivers/net/dsa/sja1105/sja1105_tas.c | 7
drivers/net/ethernet/amazon/ena/ena_com.c | 3
drivers/net/ethernet/broadcom/bgmac.c | 4
drivers/net/ethernet/broadcom/genet/bcmmii.c | 2
drivers/net/ethernet/engleder/tsnep_selftests.c | 12
drivers/net/ethernet/engleder/tsnep_tc.c | 4
drivers/net/ethernet/freescale/enetc/enetc_qos.c | 6
drivers/net/ethernet/freescale/fec.h | 17
drivers/net/ethernet/freescale/fec_main.c | 178 ++++--
drivers/net/ethernet/google/gve/gve_ethtool.c | 3
drivers/net/ethernet/intel/ice/ice_main.c | 23
drivers/net/ethernet/intel/ice/ice_tc_lib.c | 22
drivers/net/ethernet/intel/ice/ice_tc_lib.h | 1
drivers/net/ethernet/intel/igc/igc.h | 15
drivers/net/ethernet/intel/igc/igc_ethtool.c | 2
drivers/net/ethernet/intel/igc/igc_main.c | 158 +++++-
drivers/net/ethernet/intel/igc/igc_ptp.c | 25
drivers/net/ethernet/intel/igc/igc_tsn.c | 68 +-
drivers/net/ethernet/marvell/mvneta.c | 4
drivers/net/ethernet/marvell/octeontx2/af/ptp.c | 19
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 2
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c | 11
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c | 23
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 8
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 15
drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c | 6
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c | 6
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 14
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h | 1
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c | 3
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 44 -
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 3
drivers/net/ethernet/mellanox/mlx5/core/thermal.c | 19
drivers/net/ethernet/microchip/Kconfig | 2
drivers/net/ethernet/microchip/lan743x_main.c | 21
drivers/net/ethernet/microchip/lan966x/lan966x_tc.c | 10
drivers/net/ethernet/mscc/ocelot_mm.c | 7
drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 5
drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 7
drivers/net/ethernet/ti/am65-cpsw-qos.c | 11
drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c | 3
drivers/net/netdevsim/dev.c | 9
drivers/net/phy/dp83td510.c | 23
drivers/net/wireless/cisco/airo.c | 5
drivers/net/wireless/realtek/rtw89/debug.c | 5
drivers/ntb/hw/amd/ntb_hw_amd.c | 7
drivers/ntb/hw/idt/ntb_hw_idt.c | 7
drivers/ntb/hw/intel/ntb_hw_gen1.c | 7
drivers/ntb/ntb_transport.c | 2
drivers/ntb/test/ntb_tool.c | 2
drivers/nvme/host/core.c | 36 +
drivers/nvme/host/pci.c | 2
drivers/opp/core.c | 3
drivers/pci/controller/dwc/pcie-qcom.c | 2
drivers/pci/controller/pcie-rockchip-ep.c | 65 --
drivers/pci/controller/pcie-rockchip.c | 17
drivers/pci/controller/pcie-rockchip.h | 11
drivers/pci/endpoint/functions/pci-epf-test.c | 40 +
drivers/pci/pci.c | 10
drivers/pci/probe.c | 4
drivers/pci/quirks.c | 2
drivers/perf/riscv_pmu.c | 3
drivers/pinctrl/pinctrl-amd.c | 103 +--
drivers/pinctrl/pinctrl-amd.h | 2
drivers/platform/x86/wmi.c | 22
drivers/pwm/pwm-meson.c | 28 -
drivers/s390/crypto/zcrypt_msgtype6.c | 6
drivers/s390/net/ism_drv.c | 139 ++---
drivers/scsi/lpfc/lpfc_crtn.h | 1
drivers/scsi/lpfc/lpfc_els.c | 30 -
drivers/scsi/lpfc/lpfc_hbadisc.c | 24
drivers/scsi/mpi3mr/mpi3mr_fw.c | 5
drivers/scsi/qla2xxx/qla_attr.c | 13
drivers/scsi/qla2xxx/qla_bsg.c | 6
drivers/scsi/qla2xxx/qla_def.h | 22
drivers/scsi/qla2xxx/qla_edif.c | 4
drivers/scsi/qla2xxx/qla_gbl.h | 2
drivers/scsi/qla2xxx/qla_init.c | 258 +++++++++-
drivers/scsi/qla2xxx/qla_inline.h | 5
drivers/scsi/qla2xxx/qla_iocb.c | 38 +
drivers/scsi/qla2xxx/qla_isr.c | 64 ++
drivers/scsi/qla2xxx/qla_nvme.c | 3
drivers/scsi/qla2xxx/qla_os.c | 133 ++---
drivers/soc/qcom/mdt_loader.c | 16
drivers/soundwire/qcom.c | 3
drivers/tty/n_tty.c | 25
drivers/tty/serial/8250/8250.h | 1
drivers/tty/serial/8250/8250_pci.c | 19
drivers/tty/serial/8250/8250_port.c | 11
drivers/tty/serial/atmel_serial.c | 4
drivers/tty/serial/imx.c | 18
drivers/tty/serial/samsung_tty.c | 14
drivers/ufs/host/Kconfig | 1
drivers/usb/host/xhci-mem.c | 39 +
drivers/usb/host/xhci-pci.c | 12
drivers/usb/host/xhci.h | 2
drivers/xen/grant-dma-ops.c | 2
fs/ceph/addr.c | 85 ++-
fs/ceph/caps.c | 9
fs/ceph/super.h | 13
fs/dlm/ast.c | 8
fs/dlm/lockspace.c | 12
fs/dlm/lockspace.h | 1
fs/dlm/lowcomms.c | 1
fs/dlm/midcomms.c | 3
fs/dlm/plock.c | 115 ++--
fs/erofs/inode.c | 3
fs/erofs/zdata.c | 4
fs/ext2/inode.c | 5
fs/ext4/indirect.c | 8
fs/ext4/inode.c | 10
fs/ext4/ioctl.c | 5
fs/ext4/mballoc.c | 17
fs/ext4/super.c | 31 -
fs/f2fs/dir.c | 9
fs/f2fs/super.c | 30 -
fs/f2fs/xattr.c | 6
fs/jfs/jfs_dmap.c | 6
fs/jfs/jfs_filsys.h | 2
fs/smb/client/cifs_dfs_ref.c | 20
fs/smb/client/cifsproto.h | 2
fs/smb/client/cifssmb.c | 2
fs/smb/client/dfs.c | 43 -
fs/smb/client/file.c | 4
fs/smb/client/fs_context.c | 59 +-
fs/smb/client/misc.c | 17
fs/smb/client/smb2transport.c | 7
fs/smb/server/smb2pdu.c | 109 ++--
include/drm/display/drm_dp_mst_helper.h | 7
include/linux/blk-crypto-profile.h | 1
include/linux/ism.h | 7
include/linux/kasan.h | 2
include/linux/nvme.h | 2
include/linux/rethook.h | 1
include/linux/serial_8250.h | 1
include/net/netfilter/nf_conntrack_tuple.h | 3
include/net/netfilter/nf_tables.h | 31 +
include/net/pkt_sched.h | 9
include/soc/mscc/ocelot.h | 1
kernel/bpf/cpumap.c | 40 -
kernel/bpf/verifier.c | 5
kernel/dma/swiotlb.c | 46 +
kernel/power/qos.c | 9
kernel/trace/fprobe.c | 15
kernel/trace/ftrace.c | 45 +
kernel/trace/rethook.c | 13
kernel/trace/ring_buffer.c | 24
kernel/trace/trace.c | 3
kernel/trace/trace.h | 2
kernel/trace/trace_eprobe.c | 18
kernel/trace/trace_events_hist.c | 8
kernel/trace/trace_events_user.c | 6
kernel/trace/trace_probe.c | 2
kernel/trace/trace_probe_kernel.h | 30 -
kernel/trace/trace_probe_tmpl.h | 10
kernel/trace/trace_uprobe.c | 3
mm/kasan/common.c | 2
mm/kasan/generic.c | 73 +-
mm/kasan/kasan.h | 171 +++---
mm/kasan/report.c | 17
mm/kasan/report_generic.c | 12
mm/kasan/report_hw_tags.c | 2
mm/kasan/report_sw_tags.c | 2
mm/kasan/shadow.c | 36 -
mm/kasan/sw_tags.c | 20
mm/mmap.c | 9
mm/slab.h | 16
net/ceph/messenger_v2.c | 41 +
net/core/net-traces.c | 2
net/core/skbuff.c | 5
net/core/xdp.c | 2
net/ipv6/addrconf.c | 3
net/ipv6/icmp.c | 5
net/ipv6/udp.c | 4
net/mptcp/protocol.c | 7
net/ncsi/ncsi-rsp.c | 93 ---
net/netfilter/nf_conntrack_core.c | 20
net/netfilter/nf_tables_api.c | 163 +++---
net/netfilter/nft_flow_offload.c | 6
net/netfilter/nft_immediate.c | 8
net/netfilter/nft_objref.c | 8
net/sched/cls_flower.c | 10
net/sched/cls_fw.c | 10
net/sched/sch_qfq.c | 18
net/sched/sch_taprio.c | 4
samples/ftrace/ftrace-direct-too.c | 14
security/integrity/platform_certs/load_powerpc.c | 40 +
tools/testing/selftests/net/mptcp/config | 1
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 3
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh | 29 -
tools/testing/selftests/net/mptcp/pm_nl_ctl.c | 10
tools/testing/selftests/net/mptcp/userspace_pm.sh | 4
311 files changed, 3509 insertions(+), 1986 deletions(-)
Adrián Larumbe (1):
drm: bridge: dw_hdmi: fix connector access for scdc
Alan Liu (1):
drm/amd/display: Fix in secure display context creation
Alexander Aring (8):
fs: dlm: revert check required context while close
fs: dlm: return positive pid value for F_GETLK
fs: dlm: fix cleanup pending ops when interrupted
fs: dlm: interrupt posix locks only when process is killed
fs: dlm: make F_SETLK use unkillable wait_event
fs: dlm: fix mismatch of plock results from userspace
fs: dlm: clear pending bit when queue was empty
fs: dlm: fix missing pending to false
Alexander Sverdlin (2):
tpm: tis_i2c: Limit read bursts to I2C_SMBUS_BLOCK_MAX (32) bytes
tpm: tis_i2c: Limit write bursts to I2C_SMBUS_BLOCK_MAX (32) bytes
Alvin Lee (1):
drm/amd/display: Limit DCN32 8 channel or less parts to DPM1 for FPO
Andrey Konovalov (2):
kasan, slub: fix HW_TAGS zeroing with slub_debug
kasan: fix type cast in memory_is_poisoned_n
Andy Shevchenko (1):
platform/x86: wmi: Break possible infinite loop when parsing GUID
Ankit Kumar (1):
nvme: fix the NVME_ID_NS_NVM_STS_MASK definition
Aravindhan Gunasekaran (1):
igc: Handle PPS start time programming for past time values
Arnd Bergmann (3):
HID: hyperv: avoid struct memcpy overrun warning
kasan: add kasan_tag_mismatch prototype
kasan: use internal prototypes matching gcc-13 builtins
Arseniy Krasnov (1):
mtd: rawnand: meson: fix unaligned DMA buffers handling
Aurabindo Pillai (1):
drm/amd/display: Add monitor specific edid quirk
Austin Zheng (1):
drm/amd/display: Remove Phantom Pipe Check When Calculating K1 and K2
Baokun Li (2):
ext4: turn quotas off if mount failed after enabling quotas
ext4: only update i_reserved_data_blocks on successful block allocation
Basavaraj Natikar (2):
HID: amd_sfh: Rename the float32 variable
HID: amd_sfh: Fix for shift-out-of-bounds
Beau Belgrave (1):
tracing/user_events: Fix struct arg size match check
Bharath SM (1):
cifs: if deferred close is disabled then close files immediately
Bikash Hazarika (2):
scsi: qla2xxx: Fix potential NULL pointer dereference
scsi: qla2xxx: Correct the index of array
Björn Töpel (1):
riscv, bpf: Fix inconsistent JIT image generation
Brian Norris (2):
drm/atomic: Allow vblank-enabled + self-refresh "disable"
drm/rockchip: vop: Leave vblank enabled in self-refresh
Chao Yu (2):
f2fs: don't reset unchangable mount option in f2fs_remount()
ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
Christian Hesse (2):
tpm/tpm_tis: Disable interrupts for Framework Laptop Intel 12th gen
tpm/tpm_tis: Disable interrupts for Framework Laptop Intel 13th gen
Christian Marangi (1):
soc: qcom: mdt_loader: Fix unconditional call to scm_pas_mem_setup
Christoph Hellwig (1):
nvme: don't reject probe due to duplicate IDs for single-ported PCIe devices
Christophe JAILLET (3):
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
Chungkai Yang (1):
PM: QoS: Restore support for default value on frequency QoS
Chunhai Guo (2):
erofs: avoid useless loops in z_erofs_pcluster_readmore() when reading beyond EOF
erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
Damien Le Moal (5):
PCI: epf-test: Fix DMA transfer completion initialization
PCI: epf-test: Fix DMA transfer completion detection
PCI: rockchip: Set address alignment for endpoint mode
misc: pci_endpoint_test: Free IRQs before removing the device
misc: pci_endpoint_test: Re-init completion for every test
Dan Carpenter (5):
scsi: qla2xxx: Fix error code in qla2x00_start_sp()
netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
serial: atmel: don't enable IRQs prematurely
scsi: qla2xxx: Fix end of loop test
net: dsa: ocelot: unlock on error in vsc9959_qos_port_tas_set()
Daniel Vetter (1):
drm/atomic: Fix potential use-after-free in nonblocking commits
David Woodhouse (1):
mm/mmap: Fix error return in do_vmi_align_munmap()
Dmitry Torokhov (1):
HID: input: fix mapping for camera access keys
Dmytro Laktyushkin (1):
drm/amd/display: fix seamless odm transitions
Douglas Anderson (1):
drm/bridge: ti-sn65dsi86: Fix auxiliary bus lifetime
Dragos Tatulea (2):
net/mlx5e: RX, Fix flush and close release flow of regular rq for legacy rq
net/mlx5e: RX, Fix page_pool page fragment tracking for XDP
Ekansh Gupta (1):
misc: fastrpc: Create fastrpc scalar with correct buffer count
Eric Biggers (1):
blk-crypto: use dynamic lock class for blk_crypto_profile::lock
Eric Dumazet (1):
udp6: fix udp6_ehashfn() typo
Eric Lin (1):
perf: RISC-V: Remove PERF_HES_STOPPED flag checking in riscv_pmu_start()
Evan Quan (1):
drm/amd/pm: share the code around SMU13 pcie parameters update
Fabio Estevam (1):
drm/panel: simple: Add connector_type for innolux_at043tn24
Florent Revest (1):
samples: ftrace: Save required argument registers in sample trampolines
Florian Bezdeka (1):
tpm/tpm_tis: Disable interrupts for Lenovo L590 devices
Florian Fainelli (1):
net: bcmgenet: Ensure MDIO unregistration has clocks enabled
Florian Kauer (6):
igc: Rename qbv_enable to taprio_offload_enable
igc: Do not enable taprio offload for invalid arguments
igc: Handle already enabled taprio offload for basetime 0
igc: No strict mode in pure launchtime/CBS offload
igc: Fix launchtime before start of cycle
igc: Fix inserting of empty frame for launchtime
Florian Westphal (1):
netfilter: conntrack: don't fold port numbers into addresses before hashing
Frank Wunderlich (1):
arm64: dts: mt7986: use size of reserved partition for bl2
Geert Uytterhoeven (1):
drm/fbdev-dma: Fix documented default preferred_bpp value
George Stark (1):
meson saradc: fix clock divider mask length
Greg Kroah-Hartman (1):
Linux 6.4.5
Gustavo A. R. Silva (1):
smb: client: Fix -Wstringop-overflow issues
Hamza Mahfooz (1):
drm/amd/display: perform a bounds check before filling dirty rectangles
Harald Freudenberger (1):
s390/zcrypt: do not retry administrative requests
Heiko Carstens (1):
s390/decompressor: fix misaligned symbol build error
Heiner Kallweit (2):
pwm: meson: modify and simplify calculation in meson_pwm_get_state
pwm: meson: fix handling of period/duty if greater than UINT_MAX
Hersen Wu (1):
drm/amd/display: edp do not add non-edid timings
Huacai Chen (3):
MIPS: Loongson: Fix cpu_probe_loongson() again
MIPS: Loongson: Fix build error when make modules_install
MIPS: KVM: Fix NULL pointer dereference
Hui Li (1):
tty: fix hang on tty device with no_room set
Ido Schimmel (1):
net/sched: flower: Ensure both minimum and maximum ports are specified
Ilya Bakoulin (1):
drm/amd/display: Fix 128b132b link loss handling
Ilya Dryomov (1):
libceph: harden msgr2.1 frame segment length checks
Isaac J. Manjarres (1):
regmap-irq: Fix out-of-bounds access when allocating config buffers
Ivan Babrou (1):
udp6: add a missing call into udp_fail_queue_rcv_skb tracepoint
Ivan Mikhaylov (2):
net/ncsi: make one oem_gma function for all mfr id
net/ncsi: change from ndo_set_mac_address to dev_set_mac_address
Jaegeuk Kim (1):
f2fs: fix deadlock in i_xattr_sem and inode page lock
Jarkko Sakkinen (1):
tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
Jason Baron (1):
md/raid0: add discard support for the 'original' layout
Jerry Snitselaar (1):
tpm: return false from tpm_amd_is_rng_defective on non-x86 platforms
Jesper Dangaard Brouer (2):
igc: Add igc_xdp_buff wrapper for xdp_buff in driver
igc: Add XDP hints kfuncs for RX hash
Jiaqing Zhao (1):
Revert "8250: add support for ASIX devices with a FIFO bug"
Jiasheng Jiang (2):
NTB: ntb_tool: Add check for devm_kcalloc
net: dsa: qca8k: Add check for skb_copy
Jiawen Wu (1):
net: txgbe: fix eeprom calculation error
Jiaxun Yang (1):
MIPS: cpu-features: Use boot_cpu_type for CPU type based features
Jiri Olsa (1):
fprobe: Release rethook after the ftrace_ops is unregistered
Jisheng Zhang (1):
riscv: mm: fix truncation warning on RV32
Johan Hovold (1):
mfd: pm8008: Fix module autoloading
Jonas Gorski (1):
bus: ixp4xx: fix IXP4XX_EXP_T1_MASK
Junfeng Guo (1):
gve: Set default duplex configuration to full
Justin Tee (1):
scsi: lpfc: Fix double free in lpfc_cmpl_els_logo_acc() caused by lpfc_nlp_not_used()
Karol Herbst (4):
drm/nouveau/disp: fix HDMI on gt215+
drm/nouveau/disp/g94: enable HDMI
drm/nouveau/acr: Abort loading ACR if no firmware was found
drm/nouveau: bring back blit subchannel for pre nv50 GPUs
Karol Wachowski (2):
accel/ivpu: Fix VPU register access in irq disable
accel/ivpu: Clear specific interrupt status bits on C0
Kemeng Shi (3):
ext4: fix wrong unit use in ext4_mb_clear_bb
ext4: get block from bh in ext4_free_blocks for fast commit replay
ext4: fix wrong unit use in ext4_mb_new_blocks
Klaus Kudielka (1):
net: mvneta: fix txq_map in case of txq_number==1
Kornel Dulęba (1):
pinctrl: amd: Detect and mask spurious interrupts
Krister Johansen (1):
net: ena: fix shift-out-of-bounds in exponential backoff
Krzysztof Kozlowski (1):
soundwire: qcom: fix storing port config out-of-bounds
Kumar Kartikeya Dwivedi (1):
bpf: Fix max stack depth check for async callbacks
Kuniyuki Iwashima (1):
icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
Larysa Zaremba (1):
xdp: use trusted arguments in XDP hints kfuncs
Leo Chen (1):
drm/amd/display: disable seamless boot if force_odm_combine is enabled
Lino Sanfilippo (1):
tpm,tpm_tis: Disable interrupts after 1000 unhandled IRQs
Lu Hongfei (1):
net: dsa: Removed unneeded of_node_put in felix_parse_ports_node
M A Ramdhan (1):
net/sched: cls_fw: Fix improper refcount update leads to use-after-free
Maher Sanalla (1):
net/mlx5: Query hca_cap_2 only when supported
Manish Rangankar (1):
scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
Manivannan Sadhasivam (1):
PCI: qcom: Disable write access to read only registers for IP v2.3.3
Marek Vasut (1):
drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
Mario Limonciello (11):
pinctrl: amd: Detect internal GPIO0 debounce handling
pinctrl: amd: Fix mistake in handling clearing pins at startup
pinctrl: amd: Revert "pinctrl: amd: disable and mask interrupts on probe"
pinctrl: amd: Only use special debounce behavior for GPIO 0
pinctrl: amd: Use amd_pinconf_set() for all config options
pinctrl: amd: Drop pull up select configuration
pinctrl: amd: Unify debounce handling into amd_pinconf_set()
drm/amd: Disable PSR-SU on Parade 0803 TCON
drm/amd/display: Correct `DMUB_FW_VERSION` macro
drm/amd/pm: conditionally disable pcie lane/speed switching for SMU13
Revert "drm/amd: Disable PSR-SU on Parade 0803 TCON"
Martin Fuzzey (1):
tty: serial: imx: fix rs485 rx after tx
Martin Kaiser (1):
hwrng: imx-rngc - fix the timeout for init and self check
Masahiro Yamada (1):
kbuild: make modules_install copy modules.builtin(.modinfo)
Masami Hiramatsu (Google) (6):
fprobe: Ensure running fprobe_exit_handler() finished before calling rethook_free()
tracing/probes: Fix to avoid double count of the string length on the array
tracing/probes: Fix not to count error code to total length
tracing/probes: Fix to update dynamic data counter if fetcharg uses it
Revert "tracing: Add "(fault)" name injection to kernel probes"
tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails
Mateusz Stachyra (1):
tracing: Fix null pointer dereference in tracing_err_log_open()
Matthias Kaehlcke (1):
dm: verity-loadpin: Add NULL pointer check for 'bdev' parameter
Matthieu Baerts (7):
selftests: mptcp: sockopt: use 'iptables-legacy' if available
selftests: mptcp: connect: fail if nft supposed to work
selftests: mptcp: sockopt: return error if wrong mark
selftests: mptcp: userspace_pm: use correct server port
selftests: mptcp: userspace_pm: report errors with 'remove' tests
selftests: mptcp: depend on SYN_COOKIES
selftests: mptcp: pm_nl_ctl: fix 32-bit support
Max Filippov (1):
xtensa: ISS: fix call to split_if_spec
Michael Ellerman (2):
powerpc/security: Fix Speculation_Store_Bypass reporting on Power10
powerpc/64s: Fix native_hpte_remove() to be irq-safe
Mikulas Patocka (1):
dm integrity: reduce vmalloc space footprint on 32-bit architectures
Ming Lei (1):
nvme-pci: fix DMA direction of unmapping integrity data
Mohamed Khalfella (1):
tracing/histograms: Add histograms to hist_vars if they have referenced variables
Moritz Fischer (1):
net: lan743x: Don't sleep in atomic context
Muhammad Husaini Zulkifli (3):
igc: Add condition for qbv_config_change_errors counter
igc: Remove delay during TX ring configuration
igc: Fix TX Hang issue when QBV Gate is closed
Namhyung Kim (1):
perf/x86: Fix lockdep warning in for_each_sibling_event() on SPR
Namjae Jeon (2):
ksmbd: add missing compound request handing in some commands
ksmbd: fix out of bounds read in smb2_sess_setup
Naveen N Rao (1):
powerpc: Fail build if using recordmcount with binutils v2.37
Nayna Jain (1):
security/integrity: fix pointer to ESL data and its size on pseries
Niklas Schnelle (3):
s390/ism: Fix locking for forwarding of IRQs and events to clients
s390/ism: Fix and simplify add()/remove() callback handling
s390/ism: Do not unregister clients with registered DMBs
Nilesh Javali (3):
scsi: qla2xxx: Array index may go out of bound
scsi: qla2xxx: Avoid fcport pointer dereference
scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
Nitya Sunkad (1):
ionic: remove WARN_ON to prevent panic_on_warn
Oleksij Rempel (1):
net: phy: dp83td510: fix kernel stall during netboot in DP83TD510E PHY driver
Oliver Upton (1):
arm64: errata: Mitigate Ampere1 erratum AC03_CPU_38 at stage-2
Ondrej Zary (1):
PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
Pablo Neira Ayuso (1):
netfilter: nf_tables: report use refcount overflow
Paolo Abeni (3):
net: prevent skb corruption on frag list segmentation
mptcp: do not rely on implicit state check in mptcp_listen()
mptcp: ensure subflow is unhashed before cleaning the backlog
Paulo Alcantara (2):
smb: client: improve DFS mount check
smb: client: fix parsing of source mount option
Pedro Tammela (3):
net/sched: make psched_mtu() RTNL-less safe
net/sched: sch_qfq: reintroduce lmax bound check for MTU
net/sched: sch_qfq: account for stab overhead in qfq_enqueue
Peter Ujfalusi (1):
tpm: tpm_tis: Disable interrupts *only* for AEON UPX-i11
Petr Pavlu (1):
xen/virtio: Fix NULL deref when a bridge of PCI root bus has no parent
Petr Tesarik (2):
swiotlb: always set the number of areas before allocating the pool
swiotlb: reduce the number of areas to match actual memory pool size
Prasad Koya (1):
igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
Pu Lehui (1):
bpf: cpumap: Fix memory leak in cpu_map_update_elem
Quinn Tran (7):
scsi: qla2xxx: Multi-que support for TMF
scsi: qla2xxx: Fix task management cmd failure
scsi: qla2xxx: Fix task management cmd fail due to unavailable resource
scsi: qla2xxx: Fix hang in task management
scsi: qla2xxx: Wait for io return on terminate rport
scsi: qla2xxx: Fix mem access after free
scsi: qla2xxx: Fix buffer overrun
Rafał Miłecki (1):
net: bgmac: postpone turning IRQs off to avoid SoC hangs
Randy Dunlap (2):
scsi: ufs: ufs-mediatek: Add dependency for RESET_CONTROLLER
wifi: airo: avoid uninitialized warning in airo_get_rate()
Ratheesh Kannoth (1):
octeontx2-af: Promisc enable/disable through mbox
Rick Wertenbroek (5):
PCI: rockchip: Assert PCI Configuration Enable bit after probe
PCI: rockchip: Write PCI Device ID to correct register
PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
PCI: rockchip: Use u32 variable to access 32-bit registers
Ritesh Harjani (IBM) (1):
ext2/dax: Fix ext2_setsize when len is page aligned
Robin Murphy (1):
PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
Ross Lagerwall (1):
PCI: Release resource invalidated by coalescing
Saeed Mahameed (1):
net/mlx5: Register a unique thermal zone per device
Sai Krishna (1):
octeontx2-af: Move validation of ptp pointer before its usage
Sakari Ailus (1):
media: uapi: Fix [GS]_ROUTING ACTIVE flag value
Samuel Pitoiset (1):
drm/amdgpu: fix clearing mappings for BOs that are always valid in VM
Sathya Prakash (1):
scsi: mpi3mr: Propagate sense data for admin queue SCSI I/O
Shreyas Deodhar (1):
scsi: qla2xxx: Pointer may be dereferenced
Siddh Raman Pant (1):
jfs: jfs_dmap: Validate db_l2nbperpage while mounting
Simon Horman (1):
net: lan743x: select FIXED_PHY
Sinthu Raja (1):
arm64: dts: ti: k3-j721s2: Fix wkup pinmux range
Sridhar Samudrala (2):
ice: Fix max_rate check while configuring TX rate limits
ice: Fix tx queue rate limit when TCs are configured
Stafford Horne (1):
openrisc: Union fpcsr and oldmask in sigcontext to unbreak userspace ABI
Stanislav Lisovskiy (1):
drm/i915: Don't preserve dpll_hw_state for slave crtc in Bigjoiner
Stephan Gerhold (1):
opp: Fix use-after-free in lazy_opp_tables after probe deferral
Suman Ghosh (1):
octeontx2-pf: Add additional check for MCAM rules
Sung-huai Wang (1):
drm/amd/display: add a NULL pointer check
Tan Tee Min (1):
igc: Include the length/type field and VLAN tag in queueMaxSDU
Theodore Ts'o (1):
ext4: avoid updating the superblock on a r/o mount if not needed
Thomas Bogendoerfer (1):
MIPS: kvm: Fix build error with KVM_MIPS_DEBUG_COP0_COUNTERS enabled
Thomas Hellström (2):
drm/ttm: Don't leak a resource on eviction error
drm/ttm: Don't leak a resource on swapout move error
Thomas Zimmermann (1):
drm/client: Send hotplug event after registering a client
Tvrtko Ursulin (1):
drm/i915: Fix one wrong caching mode enum usage
Tzvetomir Stoyanov (VMware) (1):
kernel/trace: Fix cleanup logic of enable_trace_eprobe
Valentin David (1):
tpm: Do not remap from ACPI resources again for Pluton TPM
Vlad Buslov (1):
net/mlx5e: Check for NOT_READY flag state after locking
Vladimir Oltean (3):
net: dsa: felix: make vsc9959_tas_guard_bands_update() visible to ocelot->ops
net: mscc: ocelot: fix oversize frame dropping for preemptible TCs
net/sched: taprio: replace tc_taprio_qopt_offload :: enable with a "cmd" enum
Wayne Lin (1):
drm/dp_mst: Clear MSG_RDY flag before sending new message
Wei Fang (4):
net: fec: remove useless fec_enet_reset_skb()
net: fec: remove last_bdp from fec_enet_txq_xmit_frame()
net: fec: recycle pages for transmitted XDP frames
net: fec: increase the size of tx ring and update tx_wake_threshold
Weitao Wang (3):
xhci: Fix resume issue of some ZHAOXIN hosts
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
xhci: Show ZHAOXIN xHCI root hub speed correctly
Winston Wen (1):
cifs: fix session state check in smb2_find_smb_ses
Xin Yin (1):
erofs: fix fsdax unavailability for chunk-based regular files
Xiubo Li (3):
ceph: add a dedicated private data for netfs rreq
ceph: fix blindly expanding the readahead windows
ceph: don't let check_caps skip sending responses for revoke msgs
Yang Wang (1):
drm/amd/pm: fix smu i2c data read risk
Yang Yingliang (1):
NTB: ntb_transport: fix possible memory leak while device_register() fails
Yevgeny Kliteynik (1):
net/mlx5e: TC, CT: Offload ct clear only once
Yinjun Zhang (1):
nfp: clean mc addresses in application firmware when closing port
Yuan Can (3):
ntb: idt: Fix error handling in idt_pci_driver_init()
NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
Ze Gao (1):
fprobe: add unlock to match a succeeded ftrace_test_recursion_trylock
Zhang Shurong (1):
wifi: rtw89: debug: fix error code in rtw89_debug_priv_send_h2c_set()
Zheng Yejian (3):
tracing: Fix memory leak of iter->temp when reading trace_pipe
ring-buffer: Fix deadloop issue on reading trace_pipe
ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
Zhengchao Shao (3):
net/mlx5e: fix double free in mlx5e_destroy_flow_table
net/mlx5e: fix memory leak in mlx5e_fs_tt_redirect_any_create
net/mlx5e: fix memory leak in mlx5e_ptp_open
Zhihao Cheng (1):
ext4: Fix reusing stale buffer heads from last failed mounting
Ziyang Xuan (1):
ipv6/addrconf: fix a potential refcount underflow for idev
gaba (1):
drm/amdgpu: avoid restore process run into dead loop.
sunliming (1):
tracing/user_events: Fix incorrect return value for writing operation when events are disabled
^ permalink raw reply [relevance 1%]
* Linux 6.1.40
@ 2023-07-23 12:28 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-23 12:28 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 6.1.40 kernel.
All users of the 6.1 kernel series must upgrade.
The updated 6.1.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-6.1.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/admin-guide/device-mapper/dm-init.rst | 8
Makefile | 2
arch/mips/include/asm/kvm_host.h | 6
arch/mips/kernel/cpu-probe.c | 9
arch/mips/kvm/emulate.c | 22 -
arch/mips/kvm/mips.c | 16
arch/mips/kvm/stats.c | 4
arch/mips/kvm/trace.h | 8
arch/mips/kvm/vz.c | 20
arch/powerpc/Makefile | 8
arch/powerpc/kernel/security.c | 37 -
arch/powerpc/mm/book3s64/hash_native.c | 13
arch/riscv/mm/init.c | 2
arch/riscv/net/bpf_jit.h | 6
arch/riscv/net/bpf_jit_core.c | 19
arch/s390/Makefile | 1
arch/x86/events/intel/core.c | 7
arch/xtensa/platforms/iss/network.c | 2
block/blk-crypto-profile.c | 12
drivers/base/regmap/regmap-irq.c | 2
drivers/bus/intel-ixp4xx-eb.c | 2
drivers/char/hw_random/imx-rngc.c | 6
drivers/char/tpm/tpm-chip.c | 7
drivers/char/tpm/tpm_crb.c | 19
drivers/char/tpm/tpm_tis_i2c.c | 59 +-
drivers/char/tpm/tpm_vtpm_proxy.c | 30 -
drivers/firmware/stratix10-svc.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 3
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 12
drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c | 11
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 26 +
drivers/gpu/drm/amd/display/dc/core/dc.c | 3
drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 10
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 11
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 4
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 2
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h | 1
drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2
drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 4
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 98 ++++
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 34 -
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 34 -
drivers/gpu/drm/bridge/ti-sn65dsi86.c | 35 +
drivers/gpu/drm/drm_atomic.c | 11
drivers/gpu/drm/drm_atomic_helper.c | 11
drivers/gpu/drm/drm_client.c | 21
drivers/gpu/drm/drm_fb_helper.c | 4
drivers/gpu/drm/i915/display/intel_display.c | 1
drivers/gpu/drm/i915/gt/intel_gtt.c | 2
drivers/gpu/drm/panel/panel-simple.c | 2
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8
drivers/gpu/drm/ttm/ttm_bo.c | 1
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c | 30 +
drivers/iio/adc/meson_saradc.c | 2
drivers/md/dm-init.c | 22 -
drivers/md/dm-integrity.c | 4
drivers/md/dm-verity-loadpin.c | 3
drivers/md/raid0.c | 62 ++
drivers/md/raid0.h | 1
drivers/mfd/qcom-pm8008.c | 1
drivers/misc/fastrpc.c | 2
drivers/misc/pci_endpoint_test.c | 10
drivers/mtd/nand/raw/meson_nand.c | 4
drivers/net/dsa/qca/qca8k-8xxx.c | 3
drivers/net/ethernet/amazon/ena/ena_com.c | 3
drivers/net/ethernet/broadcom/bgmac.c | 4
drivers/net/ethernet/broadcom/genet/bcmmii.c | 2
drivers/net/ethernet/google/gve/gve_ethtool.c | 3
drivers/net/ethernet/intel/ice/ice_main.c | 16
drivers/net/ethernet/intel/igc/igc_ethtool.c | 2
drivers/net/ethernet/intel/igc/igc_main.c | 5
drivers/net/ethernet/intel/igc/igc_ptp.c | 25 +
drivers/net/ethernet/marvell/mvneta.c | 4
drivers/net/ethernet/marvell/octeontx2/af/ptp.c | 19
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 2
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c | 11
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c | 23 -
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 8
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 15
drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c | 6
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c | 6
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6
drivers/net/ethernet/microchip/lan743x_main.c | 21
drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5
drivers/net/netdevsim/dev.c | 9
drivers/net/phy/dp83td510.c | 23 -
drivers/net/wireless/cisco/airo.c | 5
drivers/net/wireless/realtek/rtw89/debug.c | 5
drivers/ntb/hw/amd/ntb_hw_amd.c | 7
drivers/ntb/hw/idt/ntb_hw_idt.c | 7
drivers/ntb/hw/intel/ntb_hw_gen1.c | 7
drivers/ntb/ntb_transport.c | 2
drivers/ntb/test/ntb_tool.c | 2
drivers/nvme/host/core.c | 36 +
drivers/nvme/host/pci.c | 2
drivers/opp/core.c | 3
drivers/pci/controller/dwc/pcie-qcom.c | 2
drivers/pci/controller/pcie-rockchip-ep.c | 65 +--
drivers/pci/controller/pcie-rockchip.c | 17
drivers/pci/controller/pcie-rockchip.h | 11
drivers/pci/endpoint/functions/pci-epf-test.c | 40 +
drivers/pci/pci.c | 10
drivers/pci/probe.c | 4
drivers/pci/quirks.c | 2
drivers/perf/riscv_pmu.c | 3
drivers/pinctrl/pinctrl-amd.c | 190 +++-----
drivers/pinctrl/pinctrl-amd.h | 3
drivers/platform/x86/wmi.c | 22 -
drivers/pwm/pwm-meson.c | 28 -
drivers/s390/crypto/zcrypt_msgtype6.c | 6
drivers/scsi/lpfc/lpfc_crtn.h | 1
drivers/scsi/lpfc/lpfc_els.c | 30 -
drivers/scsi/lpfc/lpfc_hbadisc.c | 24 -
drivers/scsi/mpi3mr/mpi3mr_fw.c | 5
drivers/scsi/qla2xxx/qla_attr.c | 13
drivers/scsi/qla2xxx/qla_bsg.c | 6
drivers/scsi/qla2xxx/qla_def.h | 22 -
drivers/scsi/qla2xxx/qla_edif.c | 4
drivers/scsi/qla2xxx/qla_gbl.h | 2
drivers/scsi/qla2xxx/qla_init.c | 258 +++++++++++-
drivers/scsi/qla2xxx/qla_inline.h | 5
drivers/scsi/qla2xxx/qla_iocb.c | 38 +
drivers/scsi/qla2xxx/qla_isr.c | 64 ++
drivers/scsi/qla2xxx/qla_nvme.c | 3
drivers/scsi/qla2xxx/qla_os.c | 133 +++---
drivers/soc/qcom/mdt_loader.c | 16
drivers/soundwire/qcom.c | 3
drivers/tty/serial/8250/8250.h | 1
drivers/tty/serial/8250/8250_pci.c | 19
drivers/tty/serial/8250/8250_port.c | 11
drivers/tty/serial/atmel_serial.c | 4
drivers/tty/serial/imx.c | 18
drivers/tty/serial/samsung_tty.c | 14
drivers/ufs/host/Kconfig | 1
drivers/usb/host/xhci-mem.c | 39 +
drivers/usb/host/xhci-pci.c | 12
drivers/usb/host/xhci.h | 2
fs/ceph/addr.c | 85 +++
fs/ceph/caps.c | 9
fs/ceph/super.h | 13
fs/dlm/lockspace.c | 12
fs/dlm/lockspace.h | 1
fs/dlm/midcomms.c | 3
fs/dlm/plock.c | 115 +++--
fs/erofs/inode.c | 3
fs/erofs/zdata.c | 4
fs/ext2/inode.c | 5
fs/ext4/indirect.c | 8
fs/ext4/inode.c | 10
fs/ext4/ioctl.c | 5
fs/ext4/mballoc.c | 17
fs/ext4/super.c | 19
fs/f2fs/compress.c | 2
fs/f2fs/dir.c | 9
fs/f2fs/xattr.c | 6
fs/jfs/jfs_dmap.c | 6
fs/jfs/jfs_filsys.h | 2
fs/ntfs3/index.c | 84 +++
fs/ntfs3/inode.c | 18
fs/ntfs3/ntfs_fs.h | 4
fs/ntfs3/run.c | 7
fs/ntfs3/xattr.c | 109 +++--
fs/overlayfs/inode.c | 12
fs/overlayfs/overlayfs.h | 2
fs/overlayfs/util.c | 7
fs/smb/client/file.c | 4
fs/smb/client/smb2transport.c | 7
fs/smb/server/smb2pdu.c | 109 +++--
include/linux/blk-crypto-profile.h | 1
include/linux/nvme.h | 2
include/linux/rethook.h | 1
include/linux/serial_8250.h | 1
include/linux/workqueue.h | 15
include/net/pkt_sched.h | 2
kernel/bpf/cpumap.c | 40 +
kernel/bpf/verifier.c | 5
kernel/dma/swiotlb.c | 110 +++--
kernel/power/qos.c | 9
kernel/trace/fprobe.c | 11
kernel/trace/ftrace.c | 45 +-
kernel/trace/rethook.c | 13
kernel/trace/ring_buffer.c | 24 -
kernel/trace/trace.c | 3
kernel/trace/trace_eprobe.c | 18
kernel/trace/trace_events_hist.c | 8
kernel/trace/trace_events_user.c | 6
kernel/trace/trace_probe_tmpl.h | 14
kernel/workqueue.c | 13
mm/kasan/kasan.h | 3
net/ceph/messenger_v2.c | 41 +
net/core/skbuff.c | 5
net/ipv6/addrconf.c | 3
net/ipv6/icmp.c | 5
net/ipv6/udp.c | 2
net/ncsi/ncsi-rsp.c | 93 +---
net/sched/cls_flower.c | 10
net/sched/cls_fw.c | 10
net/sched/sch_qfq.c | 41 +
samples/ftrace/ftrace-direct-too.c | 14
tools/testing/selftests/net/mptcp/config | 1
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 3
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh | 9
tools/testing/selftests/net/mptcp/pm_nl_ctl.c | 10
tools/testing/selftests/net/mptcp/userspace_pm.sh | 4
208 files changed, 2335 insertions(+), 1240 deletions(-)
Alex Deucher (1):
drm/amdgpu/sdma4: set align mask to 255
Alexander Aring (6):
fs: dlm: revert check required context while close
fs: dlm: return positive pid value for F_GETLK
fs: dlm: fix cleanup pending ops when interrupted
fs: dlm: interrupt posix locks only when process is killed
fs: dlm: make F_SETLK use unkillable wait_event
fs: dlm: fix mismatch of plock results from userspace
Alexander Sverdlin (2):
tpm: tis_i2c: Limit read bursts to I2C_SMBUS_BLOCK_MAX (32) bytes
tpm: tis_i2c: Limit write bursts to I2C_SMBUS_BLOCK_MAX (32) bytes
Alexey Kardashevskiy (1):
swiotlb: reduce the swiotlb buffer size on allocation failure
Andy Shevchenko (1):
platform/x86: wmi: Break possible infinite loop when parsing GUID
Ankit Kumar (1):
nvme: fix the NVME_ID_NS_NVM_STS_MASK definition
Aravindhan Gunasekaran (1):
igc: Handle PPS start time programming for past time values
Arnd Bergmann (1):
kasan: add kasan_tag_mismatch prototype
Arseniy Krasnov (1):
mtd: rawnand: meson: fix unaligned DMA buffers handling
Aurabindo Pillai (1):
drm/amd/display: Add monitor specific edid quirk
Austin Zheng (1):
drm/amd/display: Remove Phantom Pipe Check When Calculating K1 and K2
Baokun Li (2):
ext4: turn quotas off if mount failed after enabling quotas
ext4: only update i_reserved_data_blocks on successful block allocation
Basavaraj Natikar (3):
HID: amd_sfh: Rename the float32 variable
HID: amd_sfh: Fix for shift-out-of-bounds
pinctrl: amd: Add Z-state wake control bits
Beau Belgrave (1):
tracing/user_events: Fix struct arg size match check
Bharath SM (1):
cifs: if deferred close is disabled then close files immediately
Bikash Hazarika (2):
scsi: qla2xxx: Fix potential NULL pointer dereference
scsi: qla2xxx: Correct the index of array
Björn Töpel (1):
riscv, bpf: Fix inconsistent JIT image generation
Brian Norris (2):
drm/atomic: Allow vblank-enabled + self-refresh "disable"
drm/rockchip: vop: Leave vblank enabled in self-refresh
Chao Yu (1):
ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
Christian Marangi (1):
soc: qcom: mdt_loader: Fix unconditional call to scm_pas_mem_setup
Christoph Hellwig (1):
nvme: don't reject probe due to duplicate IDs for single-ported PCIe devices
Christophe JAILLET (3):
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
Chungkai Yang (1):
PM: QoS: Restore support for default value on frequency QoS
Chunhai Guo (2):
erofs: avoid useless loops in z_erofs_pcluster_readmore() when reading beyond EOF
erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
Damien Le Moal (5):
PCI: epf-test: Fix DMA transfer completion initialization
PCI: epf-test: Fix DMA transfer completion detection
PCI: rockchip: Set address alignment for endpoint mode
misc: pci_endpoint_test: Free IRQs before removing the device
misc: pci_endpoint_test: Re-init completion for every test
Dan Carpenter (4):
scsi: qla2xxx: Fix error code in qla2x00_start_sp()
netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
serial: atmel: don't enable IRQs prematurely
scsi: qla2xxx: Fix end of loop test
Daniel Vetter (1):
drm/atomic: Fix potential use-after-free in nonblocking commits
Dmytro Laktyushkin (1):
drm/amd/display: fix seamless odm transitions
Douglas Anderson (1):
drm/bridge: ti-sn65dsi86: Fix auxiliary bus lifetime
Ekansh Gupta (1):
misc: fastrpc: Create fastrpc scalar with correct buffer count
Eric Biggers (1):
blk-crypto: use dynamic lock class for blk_crypto_profile::lock
Eric Dumazet (1):
udp6: fix udp6_ehashfn() typo
Eric Lin (1):
perf: RISC-V: Remove PERF_HES_STOPPED flag checking in riscv_pmu_start()
Evan Quan (2):
drm/amd/pm: revise the ASPM settings for thunderbolt attached scenario
drm/amd/pm: share the code around SMU13 pcie parameters update
Fabio Estevam (1):
drm/panel: simple: Add connector_type for innolux_at043tn24
Florent Revest (1):
samples: ftrace: Save required argument registers in sample trampolines
Florian Fainelli (1):
net: bcmgenet: Ensure MDIO unregistration has clocks enabled
Florian Kauer (2):
igc: Fix launchtime before start of cycle
igc: Fix inserting of empty frame for launchtime
George Stark (1):
meson saradc: fix clock divider mask length
Greg Kroah-Hartman (1):
Linux 6.1.40
Harald Freudenberger (1):
s390/zcrypt: do not retry administrative requests
Heiko Carstens (1):
s390/decompressor: fix misaligned symbol build error
Heiner Kallweit (2):
pwm: meson: modify and simplify calculation in meson_pwm_get_state
pwm: meson: fix handling of period/duty if greater than UINT_MAX
Hersen Wu (1):
drm/amd/display: edp do not add non-edid timings
Huacai Chen (2):
MIPS: Loongson: Fix cpu_probe_loongson() again
MIPS: KVM: Fix NULL pointer dereference
Ido Schimmel (1):
net/sched: flower: Ensure both minimum and maximum ports are specified
Ilya Dryomov (1):
libceph: harden msgr2.1 frame segment length checks
Isaac J. Manjarres (1):
regmap-irq: Fix out-of-bounds access when allocating config buffers
Ivan Mikhaylov (2):
net/ncsi: make one oem_gma function for all mfr id
net/ncsi: change from ndo_set_mac_address to dev_set_mac_address
Jaegeuk Kim (2):
f2fs: fix the wrong condition to determine atomic context
f2fs: fix deadlock in i_xattr_sem and inode page lock
Jarkko Sakkinen (1):
tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
Jason Baron (1):
md/raid0: add discard support for the 'original' layout
Jerry Snitselaar (1):
tpm: return false from tpm_amd_is_rng_defective on non-x86 platforms
Jiaqing Zhao (1):
Revert "8250: add support for ASIX devices with a FIFO bug"
Jiasheng Jiang (2):
NTB: ntb_tool: Add check for devm_kcalloc
net: dsa: qca8k: Add check for skb_copy
Jiri Olsa (1):
fprobe: Release rethook after the ftrace_ops is unregistered
Jisheng Zhang (1):
riscv: mm: fix truncation warning on RV32
Johan Hovold (1):
mfd: pm8008: Fix module autoloading
Jonas Gorski (1):
bus: ixp4xx: fix IXP4XX_EXP_T1_MASK
Junfeng Guo (1):
gve: Set default duplex configuration to full
Justin Tee (1):
scsi: lpfc: Fix double free in lpfc_cmpl_els_logo_acc() caused by lpfc_nlp_not_used()
Kemeng Shi (3):
ext4: fix wrong unit use in ext4_mb_clear_bb
ext4: get block from bh in ext4_free_blocks for fast commit replay
ext4: fix wrong unit use in ext4_mb_new_blocks
Kenneth Feng (1):
drm/amd/pm: add abnormal fan detection for smu 13.0.0
Klaus Kudielka (1):
net: mvneta: fix txq_map in case of txq_number==1
Konstantin Komarov (1):
fs/ntfs3: Check fields while reading
Kornel Dulęba (1):
pinctrl: amd: Detect and mask spurious interrupts
Krister Johansen (1):
net: ena: fix shift-out-of-bounds in exponential backoff
Krzysztof Kozlowski (1):
soundwire: qcom: fix storing port config out-of-bounds
Kumar Kartikeya Dwivedi (1):
bpf: Fix max stack depth check for async callbacks
Kuniyuki Iwashima (1):
icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
Leo Chen (1):
drm/amd/display: disable seamless boot if force_odm_combine is enabled
Linus Torvalds (1):
workqueue: clean up WORK_* constant types, clarify masking
Luben Tuikov (1):
drm/amdgpu: Fix minmax warning
M A Ramdhan (1):
net/sched: cls_fw: Fix improper refcount update leads to use-after-free
Manish Rangankar (1):
scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
Manivannan Sadhasivam (1):
PCI: qcom: Disable write access to read only registers for IP v2.3.3
Marek Vasut (1):
drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
Mario Limonciello (13):
pinctrl: amd: Adjust debugfs output
pinctrl: amd: Add fields for interrupt status and wake status
pinctrl: amd: Detect internal GPIO0 debounce handling
pinctrl: amd: Fix mistake in handling clearing pins at startup
pinctrl: amd: Revert "pinctrl: amd: disable and mask interrupts on probe"
pinctrl: amd: Only use special debounce behavior for GPIO 0
pinctrl: amd: Use amd_pinconf_set() for all config options
pinctrl: amd: Drop pull up select configuration
pinctrl: amd: Unify debounce handling into amd_pinconf_set()
drm/amd: Disable PSR-SU on Parade 0803 TCON
drm/amd/display: Correct `DMUB_FW_VERSION` macro
drm/amd/pm: conditionally disable pcie lane/speed switching for SMU13
Revert "drm/amd: Disable PSR-SU on Parade 0803 TCON"
Martin Fuzzey (1):
tty: serial: imx: fix rs485 rx after tx
Martin Kaiser (1):
hwrng: imx-rngc - fix the timeout for init and self check
Masami Hiramatsu (Google) (3):
fprobe: Ensure running fprobe_exit_handler() finished before calling rethook_free()
tracing/probes: Fix not to count error code to total length
tracing/probes: Fix to update dynamic data counter if fetcharg uses it
Mateusz Stachyra (1):
tracing: Fix null pointer dereference in tracing_err_log_open()
Matthias Kaehlcke (1):
dm: verity-loadpin: Add NULL pointer check for 'bdev' parameter
Matthieu Baerts (6):
selftests: mptcp: connect: fail if nft supposed to work
selftests: mptcp: sockopt: return error if wrong mark
selftests: mptcp: userspace_pm: use correct server port
selftests: mptcp: userspace_pm: report errors with 'remove' tests
selftests: mptcp: depend on SYN_COOKIES
selftests: mptcp: pm_nl_ctl: fix 32-bit support
Max Filippov (1):
xtensa: ISS: fix call to split_if_spec
Michael Ellerman (2):
powerpc/security: Fix Speculation_Store_Bypass reporting on Power10
powerpc/64s: Fix native_hpte_remove() to be irq-safe
Mikulas Patocka (1):
dm integrity: reduce vmalloc space footprint on 32-bit architectures
Ming Lei (1):
nvme-pci: fix DMA direction of unmapping integrity data
Mohamed Khalfella (1):
tracing/histograms: Add histograms to hist_vars if they have referenced variables
Moritz Fischer (1):
net: lan743x: Don't sleep in atomic context
Muhammad Husaini Zulkifli (1):
igc: Remove delay during TX ring configuration
Namhyung Kim (1):
perf/x86: Fix lockdep warning in for_each_sibling_event() on SPR
Namjae Jeon (2):
ksmbd: add missing compound request handing in some commands
ksmbd: fix out of bounds read in smb2_sess_setup
Naveen N Rao (1):
powerpc: Fail build if using recordmcount with binutils v2.37
Nilesh Javali (3):
scsi: qla2xxx: Array index may go out of bound
scsi: qla2xxx: Avoid fcport pointer dereference
scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
Nitya Sunkad (1):
ionic: remove WARN_ON to prevent panic_on_warn
Oleksij Rempel (1):
net: phy: dp83td510: fix kernel stall during netboot in DP83TD510E PHY driver
Ondrej Zary (1):
PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
Paolo Abeni (1):
net: prevent skb corruption on frag list segmentation
Pedro Tammela (4):
net/sched: make psched_mtu() RTNL-less safe
net/sched: sch_qfq: refactor parsing of netlink parameters
net/sched: sch_qfq: account for stab overhead in qfq_enqueue
net/sched: sch_qfq: reintroduce lmax bound check for MTU
Peter Korsgaard (1):
dm init: add dm-mod.waitfor to wait for asynchronously probed block devices
Petr Tesarik (2):
swiotlb: always set the number of areas before allocating the pool
swiotlb: reduce the number of areas to match actual memory pool size
Prasad Koya (1):
igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
Pu Lehui (1):
bpf: cpumap: Fix memory leak in cpu_map_update_elem
Quinn Tran (7):
scsi: qla2xxx: Multi-que support for TMF
scsi: qla2xxx: Fix task management cmd failure
scsi: qla2xxx: Fix task management cmd fail due to unavailable resource
scsi: qla2xxx: Fix hang in task management
scsi: qla2xxx: Wait for io return on terminate rport
scsi: qla2xxx: Fix mem access after free
scsi: qla2xxx: Fix buffer overrun
Rafał Miłecki (1):
net: bgmac: postpone turning IRQs off to avoid SoC hangs
Randy Dunlap (3):
scsi: ufs: ufs-mediatek: Add dependency for RESET_CONTROLLER
wifi: airo: avoid uninitialized warning in airo_get_rate()
swiotlb: mark swiotlb_memblock_alloc() as __init
Ratheesh Kannoth (1):
octeontx2-af: Promisc enable/disable through mbox
Rick Wertenbroek (5):
PCI: rockchip: Assert PCI Configuration Enable bit after probe
PCI: rockchip: Write PCI Device ID to correct register
PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
PCI: rockchip: Use u32 variable to access 32-bit registers
Ritesh Harjani (IBM) (1):
ext2/dax: Fix ext2_setsize when len is page aligned
Robin Murphy (1):
PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
Ross Lagerwall (1):
PCI: Release resource invalidated by coalescing
Sai Krishna (1):
octeontx2-af: Move validation of ptp pointer before its usage
Samuel Pitoiset (1):
drm/amdgpu: fix clearing mappings for BOs that are always valid in VM
Sathya Prakash (1):
scsi: mpi3mr: Propagate sense data for admin queue SCSI I/O
Shreyas Deodhar (1):
scsi: qla2xxx: Pointer may be dereferenced
Siddh Raman Pant (1):
jfs: jfs_dmap: Validate db_l2nbperpage while mounting
Sridhar Samudrala (1):
ice: Fix max_rate check while configuring TX rate limits
Stanislav Lisovskiy (1):
drm/i915: Don't preserve dpll_hw_state for slave crtc in Bigjoiner
Stephan Gerhold (1):
opp: Fix use-after-free in lazy_opp_tables after probe deferral
Suman Ghosh (1):
octeontx2-pf: Add additional check for MCAM rules
Sung-huai Wang (1):
drm/amd/display: add a NULL pointer check
Thomas Bogendoerfer (1):
MIPS: kvm: Fix build error with KVM_MIPS_DEBUG_COP0_COUNTERS enabled
Thomas Hellström (1):
drm/ttm: Don't leak a resource on swapout move error
Thomas Zimmermann (1):
drm/client: Send hotplug event after registering a client
Tvrtko Ursulin (1):
drm/i915: Fix one wrong caching mode enum usage
Tzvetomir Stoyanov (VMware) (1):
kernel/trace: Fix cleanup logic of enable_trace_eprobe
Valentin David (1):
tpm: Do not remap from ACPI resources again for Pluton TPM
Vlad Buslov (1):
net/mlx5e: Check for NOT_READY flag state after locking
Weitao Wang (3):
xhci: Fix resume issue of some ZHAOXIN hosts
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
xhci: Show ZHAOXIN xHCI root hub speed correctly
Winston Wen (1):
cifs: fix session state check in smb2_find_smb_ses
Xin Yin (1):
erofs: fix fsdax unavailability for chunk-based regular files
Xiubo Li (3):
ceph: add a dedicated private data for netfs rreq
ceph: fix blindly expanding the readahead windows
ceph: don't let check_caps skip sending responses for revoke msgs
Yang Yingliang (1):
NTB: ntb_transport: fix possible memory leak while device_register() fails
Yuan Can (3):
ntb: idt: Fix error handling in idt_pci_driver_init()
NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
Zhang Shurong (1):
wifi: rtw89: debug: fix error code in rtw89_debug_priv_send_h2c_set()
Zheng Yejian (3):
tracing: Fix memory leak of iter->temp when reading trace_pipe
ring-buffer: Fix deadloop issue on reading trace_pipe
ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
Zhengchao Shao (3):
net/mlx5e: fix double free in mlx5e_destroy_flow_table
net/mlx5e: fix memory leak in mlx5e_fs_tt_redirect_any_create
net/mlx5e: fix memory leak in mlx5e_ptp_open
Zhihao Cheng (3):
ovl: let helper ovl_i_path_real() return the realinode
ovl: fix null pointer dereference in ovl_get_acl_rcu()
ext4: Fix reusing stale buffer heads from last failed mounting
Ziyang Xuan (1):
ipv6/addrconf: fix a potential refcount underflow for idev
gaba (1):
drm/amdgpu: avoid restore process run into dead loop.
lyndonli (1):
drm/amdgpu: add the fan abnormal detection feature
sunliming (1):
tracing/user_events: Fix incorrect return value for writing operation when events are disabled
^ permalink raw reply [relevance 1%]
* Linux 5.15.121
@ 2023-07-23 12:26 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-23 12:26 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.15.121 kernel.
All users of the 5.15 kernel series must upgrade.
The updated 5.15.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.15.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/admin-guide/device-mapper/dm-init.rst | 8
Documentation/arm64/silicon-errata.rst | 4
Documentation/filesystems/autofs-mount-control.rst | 2
Documentation/filesystems/autofs.rst | 2
Documentation/filesystems/directory-locking.rst | 26
Documentation/networking/af_xdp.rst | 9
Makefile | 2
arch/arc/include/asm/linkage.h | 8
arch/arm/boot/dts/bcm53015-meraki-mr26.dts | 2
arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 2
arch/arm/boot/dts/bcm5301x.dtsi | 1
arch/arm/boot/dts/iwg20d-q7-common.dtsi | 2
arch/arm/boot/dts/meson8.dtsi | 4
arch/arm/boot/dts/meson8b.dtsi | 4
arch/arm/boot/dts/omap3-gta04a5one.dts | 4
arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts | 8
arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi | 10
arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi | 12
arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi | 11
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 8
arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi | 6
arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 2
arch/arm/include/asm/assembler.h | 17
arch/arm/include/asm/sync_bitops.h | 29
arch/arm/lib/bitops.h | 14
arch/arm/lib/testchangebit.S | 4
arch/arm/lib/testclearbit.S | 4
arch/arm/lib/testsetbit.S | 4
arch/arm/mach-ep93xx/timer-ep93xx.c | 3
arch/arm/mach-omap2/board-generic.c | 1
arch/arm/mach-orion5x/board-dt.c | 3
arch/arm/mach-orion5x/common.h | 6
arch/arm/probes/kprobes/checkers-common.c | 2
arch/arm/probes/kprobes/core.c | 2
arch/arm/probes/kprobes/opt-arm.c | 2
arch/arm/probes/kprobes/test-core.c | 2
arch/arm/probes/kprobes/test-core.h | 4
arch/arm64/Kconfig | 41
arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi | 4
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 22
arch/arm64/boot/dts/microchip/sparx5.dtsi | 2
arch/arm64/boot/dts/microchip/sparx5_pcb_common.dtsi | 12
arch/arm64/boot/dts/qcom/apq8016-sbc.dts | 840 +++++++
arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 826 -------
arch/arm64/boot/dts/qcom/apq8096-db820c.dts | 1070 +++++++++
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi | 1105 ----------
arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts | 4
arch/arm64/boot/dts/qcom/msm8916-mtp.dts | 15
arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi | 21
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4
arch/arm64/boot/dts/qcom/msm8994.dtsi | 2
arch/arm64/boot/dts/qcom/msm8996-mtp.dts | 24
arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi | 30
arch/arm64/boot/dts/qcom/msm8996.dtsi | 19
arch/arm64/boot/dts/qcom/sdm630.dtsi | 2
arch/arm64/boot/dts/qcom/sdm845.dtsi | 2
arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi | 7
arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 3
arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts | 28
arch/arm64/kernel/cpu_errata.c | 26
arch/arm64/tools/cpucaps | 1
arch/mips/include/asm/kvm_host.h | 6
arch/mips/kernel/cpu-probe.c | 9
arch/mips/kvm/emulate.c | 22
arch/mips/kvm/mips.c | 16
arch/mips/kvm/stats.c | 4
arch/mips/kvm/trace.h | 8
arch/mips/kvm/vz.c | 20
arch/powerpc/Kconfig.debug | 2
arch/powerpc/Makefile | 8
arch/powerpc/kernel/interrupt.c | 3
arch/powerpc/kernel/ppc_save_regs.S | 61
arch/powerpc/kernel/security.c | 37
arch/powerpc/kernel/signal_32.c | 15
arch/powerpc/mm/book3s64/radix_pgtable.c | 34
arch/powerpc/mm/init_64.c | 2
arch/powerpc/platforms/powernv/pci-sriov.c | 6
arch/powerpc/platforms/powernv/vas-window.c | 2
arch/powerpc/platforms/pseries/vas.c | 2
arch/riscv/kernel/probes/uprobes.c | 2
arch/riscv/mm/init.c | 6
arch/riscv/net/bpf_jit.h | 5
arch/riscv/net/bpf_jit_core.c | 15
arch/s390/Makefile | 1
arch/s390/kvm/diag.c | 8
arch/s390/kvm/kvm-s390.c | 4
arch/s390/kvm/vsie.c | 6
arch/sh/drivers/dma/dma-sh.c | 37
arch/sh/kernel/cpu/sh2/probe.c | 2
arch/um/Makefile | 2
arch/x86/events/amd/core.c | 2
arch/x86/events/amd/ibs.c | 53
arch/x86/include/asm/perf_event.h | 2
arch/x86/include/asm/pgtable_64.h | 4
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 8
arch/xtensa/platforms/iss/network.c | 2
block/blk-iocost.c | 7
block/disk-events.c | 1
block/partitions/amiga.c | 104
drivers/base/power/domain.c | 6
drivers/bus/intel-ixp4xx-eb.c | 2
drivers/bus/ti-sysc.c | 4
drivers/char/hw_random/imx-rngc.c | 6
drivers/char/hw_random/st-rng.c | 21
drivers/char/hw_random/virtio-rng.c | 88
drivers/char/tpm/tpm_vtpm_proxy.c | 30
drivers/clk/clk-cdce925.c | 12
drivers/clk/clk-si5341.c | 38
drivers/clk/clk-versaclock5.c | 29
drivers/clk/clk.c | 1
drivers/clk/imx/clk-imx8mn.c | 8
drivers/clk/imx/clk-imx8mp.c | 24
drivers/clk/imx/clk-scu.c | 4
drivers/clk/keystone/sci-clk.c | 2
drivers/clk/qcom/camcc-sc7180.c | 19
drivers/clk/qcom/gcc-ipq6018.c | 34
drivers/clk/qcom/reset.c | 8
drivers/clk/qcom/reset.h | 2
drivers/clk/tegra/clk-tegra124-emc.c | 2
drivers/clk/ti/clkctrl.c | 7
drivers/clocksource/timer-cadence-ttc.c | 19
drivers/cpufreq/intel_pstate.c | 2
drivers/crypto/marvell/cesa/cipher.c | 2
drivers/crypto/nx/Makefile | 2
drivers/crypto/nx/nx.h | 4
drivers/crypto/qat/qat_common/adf_common_drv.h | 5
drivers/crypto/qat/qat_common/qat_algs.c | 23
drivers/crypto/qat/qat_common/qat_asym_algs.c | 53
drivers/crypto/qat/qat_common/qat_crypto.h | 5
drivers/dax/bus.c | 61
drivers/dax/dax-private.h | 4
drivers/dax/kmem.c | 2
drivers/extcon/extcon-usbc-tusb320.c | 5
drivers/extcon/extcon.c | 8
drivers/firmware/efi/libstub/efi-stub-helper.c | 7
drivers/firmware/stratix10-svc.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 3
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 28
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 13
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c | 3
drivers/gpu/drm/amd/display/dc/core/dc.c | 3
drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2
drivers/gpu/drm/bridge/tc358768.c | 93
drivers/gpu/drm/bridge/ti-sn65dsi86.c | 33
drivers/gpu/drm/drm_atomic.c | 11
drivers/gpu/drm/drm_atomic_helper.c | 11
drivers/gpu/drm/drm_gem_vram_helper.c | 6
drivers/gpu/drm/i915/display/intel_psr.c | 4
drivers/gpu/drm/i915/gt/intel_gtt.c | 2
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 3
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 5
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 10
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 12
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 8
drivers/gpu/drm/msm/dp/dp_display.c | 2
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 3
drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 11
drivers/gpu/drm/panel/panel-simple.c | 6
drivers/gpu/drm/radeon/ci_dpm.c | 28
drivers/gpu/drm/radeon/cypress_dpm.c | 8
drivers/gpu/drm/radeon/ni_dpm.c | 8
drivers/gpu/drm/radeon/rv740_dpm.c | 8
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8
drivers/gpu/drm/sun4i/sun4i_tcon.c | 19
drivers/gpu/drm/ttm/ttm_bo.c | 1
drivers/hwmon/gsc-hwmon.c | 6
drivers/hwmon/pmbus/adm1275.c | 90
drivers/hwtracing/coresight/coresight-core.c | 9
drivers/i2c/busses/i2c-qup.c | 21
drivers/i2c/busses/i2c-xiic.c | 39
drivers/iio/accel/fxls8962af-core.c | 8
drivers/iio/adc/ad7192.c | 8
drivers/iio/adc/meson_saradc.c | 2
drivers/infiniband/hw/bnxt_re/main.c | 20
drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40
drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c | 46
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h | 1
drivers/infiniband/hw/hfi1/ipoib_tx.c | 4
drivers/infiniband/hw/hfi1/mmu_rb.c | 101
drivers/infiniband/hw/hfi1/mmu_rb.h | 3
drivers/infiniband/hw/hfi1/sdma.c | 23
drivers/infiniband/hw/hfi1/sdma.h | 47
drivers/infiniband/hw/hfi1/sdma_txreq.h | 2
drivers/infiniband/hw/hfi1/user_sdma.c | 145 -
drivers/infiniband/hw/hfi1/user_sdma.h | 1
drivers/infiniband/hw/hfi1/vnic_sdma.c | 4
drivers/infiniband/hw/hns/hns_roce_hem.c | 7
drivers/infiniband/hw/irdma/uk.c | 10
drivers/input/misc/adxl34x.c | 3
drivers/input/misc/drv260x.c | 1
drivers/irqchip/irq-jcore-aic.c | 7
drivers/leds/trigger/ledtrig-netdev.c | 3
drivers/mailbox/ti-msgmgr.c | 12
drivers/md/bcache/btree.c | 25
drivers/md/bcache/btree.h | 1
drivers/md/bcache/super.c | 4
drivers/md/bcache/writeback.c | 10
drivers/md/dm-init.c | 22
drivers/md/dm-integrity.c | 4
drivers/md/md-bitmap.c | 17
drivers/md/md.c | 9
drivers/md/raid0.c | 62
drivers/md/raid0.h | 1
drivers/md/raid10.c | 38
drivers/media/cec/i2c/Kconfig | 1
drivers/media/i2c/st-mipid02.c | 9
drivers/media/platform/qcom/venus/helpers.c | 4
drivers/media/usb/dvb-usb-v2/az6007.c | 3
drivers/media/usb/siano/smsusb.c | 3
drivers/memory/brcmstb_dpfe.c | 4
drivers/memstick/host/r592.c | 4
drivers/mfd/intel-lpss-acpi.c | 3
drivers/mfd/qcom-pm8008.c | 1
drivers/mfd/rt5033.c | 3
drivers/mfd/stmfx.c | 7
drivers/mfd/stmpe.c | 4
drivers/misc/fastrpc.c | 2
drivers/misc/pci_endpoint_test.c | 10
drivers/mmc/core/quirks.h | 14
drivers/mmc/host/mmci.c | 1
drivers/mmc/host/sdhci.c | 4
drivers/mtd/nand/raw/meson_nand.c | 4
drivers/net/bonding/bond_main.c | 2
drivers/net/dsa/vitesse-vsc73xx-core.c | 6
drivers/net/ethernet/amazon/ena/ena_com.c | 3
drivers/net/ethernet/broadcom/bgmac.c | 4
drivers/net/ethernet/broadcom/genet/bcmmii.c | 2
drivers/net/ethernet/broadcom/tg3.c | 1
drivers/net/ethernet/google/gve/gve_ethtool.c | 3
drivers/net/ethernet/ibm/ibmvnic.c | 9
drivers/net/ethernet/intel/igc/igc.h | 33
drivers/net/ethernet/intel/igc/igc_ethtool.c | 2
drivers/net/ethernet/intel/igc/igc_main.c | 45
drivers/net/ethernet/intel/igc/igc_ptp.c | 82
drivers/net/ethernet/marvell/mvneta.c | 4
drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 7
drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 11
drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 4
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 8
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 15
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c | 6
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6
drivers/net/ethernet/microchip/lan743x_main.c | 21
drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5
drivers/net/ethernet/sfc/ef10.c | 13
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 10
drivers/net/gtp.c | 2
drivers/net/ipvlan/ipvlan_core.c | 9
drivers/net/netdevsim/dev.c | 9
drivers/net/ppp/pptp.c | 31
drivers/net/wireguard/netlink.c | 14
drivers/net/wireguard/queueing.c | 1
drivers/net/wireguard/queueing.h | 25
drivers/net/wireguard/receive.c | 2
drivers/net/wireguard/send.c | 2
drivers/net/wireless/ath/ath9k/ar9003_hw.c | 27
drivers/net/wireless/ath/ath9k/htc_hst.c | 8
drivers/net/wireless/ath/ath9k/main.c | 11
drivers/net/wireless/ath/ath9k/wmi.c | 4
drivers/net/wireless/atmel/atmel_cs.c | 13
drivers/net/wireless/cisco/airo.c | 5
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 9
drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 12
drivers/net/wireless/intersil/orinoco/orinoco_cs.c | 13
drivers/net/wireless/intersil/orinoco/spectrum_cs.c | 13
drivers/net/wireless/marvell/mwifiex/scan.c | 6
drivers/net/wireless/microchip/wilc1000/hif.c | 8
drivers/net/wireless/ray_cs.c | 36
drivers/net/wireless/rsi/rsi_91x_sdio.c | 9
drivers/net/wireless/wl3501_cs.c | 19
drivers/ntb/hw/amd/ntb_hw_amd.c | 7
drivers/ntb/hw/idt/ntb_hw_idt.c | 7
drivers/ntb/hw/intel/ntb_hw_gen1.c | 7
drivers/ntb/ntb_transport.c | 2
drivers/ntb/test/ntb_tool.c | 2
drivers/nvme/host/pci.c | 30
drivers/nvmem/rmem.c | 1
drivers/opp/core.c | 3
drivers/pci/controller/cadence/pcie-cadence-host.c | 27
drivers/pci/controller/dwc/pcie-qcom.c | 2
drivers/pci/controller/pci-ftpci100.c | 14
drivers/pci/controller/pcie-rockchip-ep.c | 65
drivers/pci/controller/pcie-rockchip.c | 17
drivers/pci/controller/pcie-rockchip.h | 11
drivers/pci/controller/vmd.c | 8
drivers/pci/hotplug/pciehp_ctrl.c | 8
drivers/pci/pci.c | 10
drivers/pci/pcie/aspm.c | 21
drivers/pci/quirks.c | 2
drivers/perf/arm-cmn.c | 7
drivers/phy/tegra/xusb.c | 4
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 6
drivers/pinctrl/intel/pinctrl-cherryview.c | 15
drivers/pinctrl/pinctrl-amd.c | 25
drivers/pinctrl/pinctrl-amd.h | 1
drivers/pinctrl/pinctrl-at91-pio4.c | 2
drivers/pinctrl/pinctrl-microchip-sgpio.c | 3
drivers/platform/x86/wmi.c | 64
drivers/powercap/Kconfig | 4
drivers/powercap/intel_rapl_msr.c | 1
drivers/pwm/pwm-ab8500.c | 2
drivers/pwm/pwm-imx-tpm.c | 7
drivers/pwm/pwm-mtk-disp.c | 13
drivers/pwm/sysfs.c | 17
drivers/regulator/core.c | 30
drivers/rtc/rtc-st-lpc.c | 2
drivers/s390/net/qeth_l3_sys.c | 2
drivers/scsi/3w-xxxx.c | 4
drivers/scsi/qedf/qedf_main.c | 3
drivers/scsi/qla2xxx/qla_attr.c | 13
drivers/scsi/qla2xxx/qla_bsg.c | 6
drivers/scsi/qla2xxx/qla_def.h | 1
drivers/scsi/qla2xxx/qla_edif.c | 4
drivers/scsi/qla2xxx/qla_init.c | 2
drivers/scsi/qla2xxx/qla_inline.h | 5
drivers/scsi/qla2xxx/qla_iocb.c | 5
drivers/scsi/qla2xxx/qla_nvme.c | 3
drivers/scsi/qla2xxx/qla_os.c | 3
drivers/soc/amlogic/meson-secure-pwrc.c | 2
drivers/soc/fsl/qe/Kconfig | 1
drivers/soundwire/qcom.c | 3
drivers/spi/spi-bcm-qspi.c | 10
drivers/spi/spi-dw-core.c | 5
drivers/spi/spi-geni-qcom.c | 2
drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c | 2
drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c | 2
drivers/thermal/sun8i_thermal.c | 55
drivers/tty/serial/8250/8250.h | 1
drivers/tty/serial/8250/8250_omap.c | 25
drivers/tty/serial/8250/8250_pci.c | 19
drivers/tty/serial/8250/8250_port.c | 11
drivers/tty/serial/atmel_serial.c | 4
drivers/tty/serial/fsl_lpuart.c | 1
drivers/tty/serial/imx.c | 18
drivers/tty/serial/samsung_tty.c | 14
drivers/usb/core/devio.c | 2
drivers/usb/dwc2/platform.c | 18
drivers/usb/dwc3/dwc3-meson-g12a.c | 5
drivers/usb/dwc3/dwc3-qcom.c | 17
drivers/usb/dwc3/gadget.c | 4
drivers/usb/gadget/function/u_serial.c | 13
drivers/usb/host/xhci-mem.c | 39
drivers/usb/host/xhci-pci.c | 12
drivers/usb/host/xhci.h | 2
drivers/usb/phy/phy-tahvo.c | 2
drivers/usb/serial/option.c | 4
drivers/video/fbdev/omap/lcd_mipid.c | 6
drivers/w1/slaves/w1_therm.c | 31
drivers/w1/w1.c | 4
fs/btrfs/block-group.c | 36
fs/btrfs/ctree.c | 28
fs/btrfs/qgroup.c | 2
fs/ceph/caps.c | 9
fs/cifs/file.c | 25
fs/dlm/plock.c | 4
fs/erofs/inode.c | 5
fs/erofs/internal.h | 16
fs/erofs/super.c | 58
fs/erofs/xattr.c | 4
fs/erofs/zdata.c | 10
fs/erofs/zmap.c | 6
fs/ext4/indirect.c | 8
fs/ext4/inode.c | 10
fs/ext4/ioctl.c | 5
fs/ext4/mballoc.c | 17
fs/ext4/namei.c | 17
fs/ext4/super.c | 19
fs/f2fs/f2fs.h | 2
fs/f2fs/file.c | 2
fs/f2fs/gc.c | 21
fs/f2fs/namei.c | 16
fs/f2fs/node.c | 4
fs/fs_context.c | 3
fs/inode.c | 42
fs/internal.h | 2
fs/jffs2/build.c | 5
fs/jffs2/xattr.c | 13
fs/jffs2/xattr.h | 4
fs/jfs/jfs_dmap.c | 6
fs/jfs/jfs_filsys.h | 2
fs/kernfs/dir.c | 2
fs/ksmbd/server.c | 33
fs/ksmbd/smb2misc.c | 38
fs/ksmbd/smb2pdu.c | 44
fs/ksmbd/smb_common.c | 2
fs/namei.c | 25
fs/nfs/nfs4proc.c | 1
fs/nfsd/nfs4xdr.c | 2
fs/notify/fanotify/fanotify_user.c | 22
fs/ntfs3/index.c | 84
fs/ntfs3/inode.c | 18
fs/ntfs3/ntfs_fs.h | 4
fs/ntfs3/run.c | 7
fs/ntfs3/xattr.c | 112 -
fs/overlayfs/copy_up.c | 2
fs/overlayfs/dir.c | 3
fs/overlayfs/export.c | 3
fs/overlayfs/inode.c | 10
fs/overlayfs/namei.c | 3
fs/overlayfs/overlayfs.h | 6
fs/overlayfs/super.c | 2
fs/overlayfs/util.c | 24
fs/pstore/ram_core.c | 2
fs/ramfs/inode.c | 2
include/acpi/acpi_bus.h | 3
include/crypto/internal/kpp.h | 6
include/linux/bootmem_info.h | 2
include/linux/can/length.h | 14
include/linux/netdevice.h | 9
include/linux/nmi.h | 2
include/linux/pci.h | 1
include/linux/pipe_fs_i.h | 4
include/linux/ramfs.h | 1
include/linux/serial_8250.h | 1
include/linux/workqueue.h | 15
include/net/netfilter/nf_tables.h | 5
include/net/pkt_sched.h | 2
include/net/sock.h | 1
include/trace/events/timer.h | 6
include/uapi/linux/affs_hardblocks.h | 68
include/uapi/linux/auto_dev-ioctl.h | 2
include/uapi/linux/videodev2.h | 2
io_uring/io_uring.c | 66
kernel/bpf/cgroup.c | 15
kernel/bpf/cpumap.c | 40
kernel/bpf/verifier.c | 5
kernel/kcsan/core.c | 2
kernel/kexec_core.c | 5
kernel/rcu/rcuscale.c | 212 -
kernel/time/posix-timers.c | 43
kernel/trace/ftrace.c | 45
kernel/trace/ring_buffer.c | 24
kernel/trace/trace.c | 3
kernel/trace/trace_eprobe.c | 18
kernel/trace/trace_events_hist.c | 8
kernel/trace/trace_probe_tmpl.h | 14
kernel/watchdog_hld.c | 6
kernel/workqueue.c | 13
lib/test_firmware.c | 12
lib/ts_bm.c | 4
mm/damon/vaddr.c | 20
mm/shmem.c | 2
net/bridge/br_if.c | 5
net/ceph/messenger_v2.c | 41
net/core/filter.c | 131 -
net/core/rtnetlink.c | 104
net/core/skbuff.c | 5
net/core/sock.c | 17
net/dsa/tag_sja1105.c | 4
net/ipv4/tcp_input.c | 12
net/ipv6/addrconf.c | 3
net/ipv6/icmp.c | 5
net/ipv6/udp.c | 2
net/netfilter/ipvs/Kconfig | 27
net/netfilter/ipvs/ip_vs_conn.c | 4
net/netfilter/nf_conntrack_helper.c | 4
net/netfilter/nf_conntrack_proto_dccp.c | 52
net/netfilter/nf_conntrack_sip.c | 2
net/netfilter/nf_tables_api.c | 158 +
net/netfilter/nft_byteorder.c | 14
net/netfilter/nft_set_bitmap.c | 5
net/netfilter/nft_set_hash.c | 23
net/netfilter/nft_set_pipapo.c | 14
net/netfilter/nft_set_rbtree.c | 5
net/netlink/af_netlink.c | 5
net/netlink/diag.c | 7
net/nfc/llcp.h | 1
net/nfc/llcp_commands.c | 15
net/nfc/llcp_core.c | 49
net/nfc/llcp_sock.c | 21
net/nfc/netlink.c | 20
net/nfc/nfc.h | 1
net/sched/act_ipt.c | 27
net/sched/act_pedit.c | 1
net/sched/cls_flower.c | 10
net/sched/cls_fw.c | 10
net/sched/sch_qfq.c | 41
net/sctp/socket.c | 22
net/sunrpc/svcsock.c | 23
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 12
net/wireless/scan.c | 213 +
net/xdp/xsk.c | 5
samples/bpf/tcp_basertt_kern.c | 2
samples/ftrace/ftrace-direct-too.c | 14
scripts/Makefile.modfinal | 2
scripts/mod/modpost.c | 86
security/apparmor/policy_unpack.c | 9
security/integrity/evm/evm_crypto.c | 2
security/integrity/evm/evm_main.c | 4
security/integrity/iint.c | 15
security/integrity/ima/ima_modsig.c | 3
security/integrity/ima/ima_policy.c | 3
sound/core/jack.c | 15
sound/pci/ac97/ac97_codec.c | 4
sound/pci/hda/patch_realtek.c | 1
sound/soc/codecs/es8316.c | 23
sound/soc/fsl/imx-audmix.c | 9
sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 13
tools/bpf/bpftool/feature.c | 24
tools/lib/bpf/bpf_helpers.h | 15
tools/lib/bpf/btf_dump.c | 22
tools/perf/builtin-bench.c | 7
tools/perf/builtin-script.c | 16
tools/perf/tests/builtin-test.c | 3
tools/perf/util/dwarf-aux.c | 2
tools/testing/selftests/bpf/prog_tests/check_mtu.c | 2
tools/testing/selftests/net/mptcp/config | 1
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh | 9
tools/testing/selftests/net/rtnetlink.sh | 1
tools/testing/selftests/rcutorture/configs/rcu/BUSTED-BOOST.boot | 2
tools/testing/selftests/rcutorture/configs/rcu/TREE03.boot | 2
tools/testing/selftests/vDSO/vdso_test_clock_getres.c | 4
tools/testing/selftests/wireguard/netns.sh | 30
518 files changed, 6689 insertions(+), 4479 deletions(-)
Abhijeet Rastogi (1):
ipvs: increase ip_vs_conn_tab_bits range for 64BIT
Aditya Gupta (1):
powerpc: update ppc_save_regs to save current r1 in pt_regs
Alan Maguire (1):
bpftool: JIT limited misreported as negative value on aarch64
Alexander Aring (1):
fs: dlm: return positive pid value for F_GETLK
Alexander Mikhalitsyn (1):
sctp: add bpf_bypass_getsockopt proto callback
Alexey Romanov (1):
drivers: meson: secure-pwrc: always enable DMA domain
Allen-KH Cheng (1):
arm64: dts: mediatek: Add cpufreq nodes for MT8192
Amelie Delaunay (2):
mfd: stmfx: Fix error path in stmfx_chip_init
mfd: stmfx: Nullify stmfx->vdd in case of error
Amir Goldstein (2):
ovl: update of dentry revalidate flags after copy up
fanotify: disallow mount/sb marks on kernel internal pseudo fs
Amisha Patel (1):
wifi: wilc1000: fix for absent RSN capabilities WFA testcase
Andre Przywara (1):
crypto: qat - replace get_current_node() with numa_node_id()
Andres Freund (1):
io_uring: Use io_schedule* in cqring wait
Andrii Nakryiko (1):
libbpf: fix offsetof() and container_of() to work with CO-RE
Andy Shevchenko (6):
wifi: ray_cs: Utilize strnlen() in parse_addr()
wifi: ray_cs: Drop useless status variable in parse_addr()
pinctrl: cherryview: Return correct value if pin in push-pull mode
extcon: Fix kernel doc of property fields to avoid warnings
extcon: Fix kernel doc of property capability fields to avoid warnings
platform/x86: wmi: Break possible infinite loop when parsing GUID
Aneesh Kumar K.V (2):
powerpc/book3s64/mm: Fix DirectMap stats in /proc/meminfo
powerpc/mm/dax: Fix the condition when checking if altmap vmemap can cross-boundary
Anjaneyulu (1):
wifi: iwlwifi: pcie: fix NULL pointer dereference in iwl_pcie_irq_rx_msix_handler()
Aravindhan Gunasekaran (1):
igc: Handle PPS start time programming for past time values
Ard Biesheuvel (1):
efi/libstub: Disable PCI DMA before grabbing the EFI memory map
Arnaldo Carvalho de Melo (2):
perf bench: Add missing setlocale() call to allow usage of %'d style formatting
perf script: Fix allocation of evsel->priv related to per-event dump files
Arnd Bergmann (11):
fs: pipe: reveal missing function protoypes
ARM: 9303/1: kprobes: avoid missing-declaration warnings
memstick r592: make memstick_debug_get_tpc_name() static
ARM: ep93xx: fix missing-prototype warnings
ARM: omap2: fix missing tick_broadcast() prototype
RDMA/irdma: avoid fortify-string warning in irdma_clr_wqes
crypto: marvell/cesa - Fix type mismatch warning
ksmbd: avoid field overflow warning
usb: hide unused usbfs_notify_suspend/resume functions
autofs: use flexible array in ioctl structure
ARM: orion5x: fix d2net gpio initialization
Arseniy Krasnov (1):
mtd: rawnand: meson: fix unaligned DMA buffers handling
Artur Rojek (1):
sh: dma: Fix DMA channel offset calculation
Aurabindo Pillai (1):
drm/amd/display: Fix artifacting on eDP panels when engaging freesync video mode
Baokun Li (2):
ext4: turn quotas off if mount failed after enabling quotas
ext4: only update i_reserved_data_blocks on successful block allocation
Barnabás Pőcze (3):
platform/x86: wmi: remove unnecessary argument
platform/x86: wmi: use guid_t and guid_equal()
platform/x86: wmi: move variables
Bartosz Golaszewski (1):
net: stmmac: fix double serdes powerdown
Benjamin Berg (1):
wifi: cfg80211: rewrite merging of inherited elements
Bharath SM (1):
SMB3: Do not send lease break acknowledgment if all file handles have been closed
Bikash Hazarika (2):
scsi: qla2xxx: Fix potential NULL pointer dereference
scsi: qla2xxx: Correct the index of array
Bjorn Andersson (2):
arm64: dts: qcom: apq8016-sbc: Update modem and WiFi firmware path
drm/msm/dp: Free resources after unregistering them
Björn Töpel (1):
riscv, bpf: Fix inconsistent JIT image generation
Brendan Cunningham (1):
IB/hfi1: Fix wrong mmu_node used for user SDMA packet after invalidate
Brian Norris (2):
drm/atomic: Allow vblank-enabled + self-refresh "disable"
drm/rockchip: vop: Leave vblank enabled in self-refresh
Cambda Zhu (1):
ipvlan: Fix return value of ipvlan_queue_xmit()
Chao Yu (3):
f2fs: fix error path handling in truncate_dnode()
f2fs: fix to avoid NULL pointer dereference f2fs_write_end_io()
ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
Chengchang Tang (1):
RDMA/hns: Fix hns_roce_table_get return value
Chengfeng Ye (1):
sctp: fix potential deadlock on &net->sctp.addr_wq_lock
Chevron Li (1):
mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is used.
Chia-I Wu (1):
amdgpu: validate offset_in_bo of drm_amdgpu_gem_va
Christian Borntraeger (1):
KVM: s390/diag: fix racy access of physical cpu number in diag 9c handler
Christian Lamparter (1):
ARM: dts: BCM5301X: fix duplex-full => full-duplex
Christian Marangi (1):
leds: trigger: netdev: Recheck NETDEV_LED_MODE_LINKUP on dev rename
Christophe JAILLET (19):
thermal/drivers/sun8i: Fix some error handling paths in sun8i_ths_probe()
wifi: mwifiex: Fix the size of a memory allocation in mwifiex_ret_802_11_scan()
wifi: orinoco: Fix an error handling path in spectrum_cs_probe()
wifi: orinoco: Fix an error handling path in orinoco_cs_probe()
wifi: atmel: Fix an error handling path in atmel_probe()
wifi: wl3501_cs: Fix an error handling path in wl3501_probe()
wifi: ray_cs: Fix an error handling path in ray_probe()
IB/hfi1: Use bitmap_zalloc() when applicable
fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe()
pinctrl: bcm2835: Handle gpiochip_add_pin_range() errors
usb: dwc2: Fix some error handling paths
usb: dwc3: qcom: Release the correct resources in dwc3_qcom_remove()
usb: dwc3: qcom: Fix an error handling path in dwc3_qcom_probe()
usb: dwc3-meson-g12a: Fix an error handling path in dwc3_meson_g12a_probe()
mfd: stmpe: Only disable the regulators if they are enabled
rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
Christophe Leroy (3):
kcsan: Don't expect 64 bits atomic builtins from 32 bits architectures
powerpc/interrupt: Don't read MSR from interrupt_exit_kernel_prepare()
powerpc/signal32: Force inlining of __unsafe_save_user_regs() and save_tm_user_regs_unsafe()
Chuck Lever (1):
svcrdma: Prevent page release when nothing was received
Chunhai Guo (1):
erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
Claudiu Beznea (11):
clk: vc5: check memory returned by kasprintf()
clk: cdce925: check return value of kasprintf()
clk: si5341: return error if one synth clock registration fails
clk: si5341: check return value of {devm_}kasprintf()
clk: si5341: free unused memory on probe failure
clk: keystone: sci-clk: check return value of kasprintf()
clk: ti: clkctrl: check return value of kasprintf()
ASoC: imx-audmix: check return value of devm_kasprintf()
pinctrl: microchip-sgpio: check return value of devm_kasprintf()
pinctrl: at91-pio4: check return value of devm_kasprintf()
phy: tegra: xusb: check return value of devm_kzalloc()
Colin Ian King (2):
kselftest: vDSO: Fix accumulation of uninitialized ret when CLOCK_REALTIME is undefined
powerpc/powernv/sriov: perform null check on iov before dereferencing iov
Cristian Ciocaltea (2):
ASoC: es8316: Increment max value for ALC Capture Target Volume control
ASoC: es8316: Do not set rate constraints for unsupported MCLKs
Dai Ngo (1):
NFSD: add encoding of op_recall flag for write delegation
Damian Muszynski (1):
crypto: qat - use reference to structure in dma_map_single()
Damien Le Moal (3):
PCI: rockchip: Set address alignment for endpoint mode
misc: pci_endpoint_test: Free IRQs before removing the device
misc: pci_endpoint_test: Re-init completion for every test
Dan Carpenter (9):
clk: imx: scu: use _safe list iterator to avoid a use after free
clk: clocking-wizard: Fix Oops in clk_wzrd_register_divider()
modpost: fix off by one in is_executable_section()
w1: fix loop in w1_fini()
media: atomisp: gmin_platform: fix out_len in gmin_get_config_dsm_var()
pwm: ab8500: Fix error code in probe()
scsi: qla2xxx: Fix error code in qla2x00_start_sp()
netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
serial: atmel: don't enable IRQs prematurely
Dan Williams (2):
dax: Fix dax_mapping_release() use after free
dax: Introduce alloc_dev_dax_id()
Daniel Scally (1):
media: i2c: Correct format propagation for st-mipid02
Daniel Vetter (1):
drm/atomic: Fix potential use-after-free in nonblocking commits
Daniil Dulov (2):
drm/amdkfd: Fix potential deallocation of previously deallocated memory.
media: usb: Check az6007_read() return value
Danila Chernetsov (1):
apparmor: fix missing error check for rhashtable_insert_fast
Dario Binacchi (1):
drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H
Davide Tronchin (1):
USB: serial: option: add LARA-R6 01B PIDs
Demi Marie Obenour (1):
block: increment diskseq on all media change events
Ding Hui (2):
PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free
SUNRPC: Fix UAF in svc_tcp_listen_data_ready()
Dmitry Antipov (1):
wifi: ath9k: convert msecs to jiffies where needed
Dmitry Baryshkov (6):
drm/panel: sharp-ls043t1le01: adjust mode settings
drm/msm/dsi: don't allow enabling 14nm VCO with unprogrammed rate
arm64: dts: qcom: apq8016-sbc: fix mpps state names
drm/msm/a5xx: really check for A510 in a5xx_gpu_init
drm/msm/dpu: do not enable color-management if DSPPs are not available
drm/msm/dpu: correct MERGE_3D length
Douglas Anderson (4):
watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct config
watchdog/perf: more properly prevent false positives with turbo modes
arm64: dts: mediatek: mt8183: Add mediatek,broken-save-restore-fw to kukui
drm/bridge: ti-sn65dsi86: Fix auxiliary bus lifetime
Duoming Zhou (1):
media: usb: siano: Fix warning due to null work_func_t function pointer
EJ Hsu (1):
phy: tegra: xusb: Clear the driver reference in usb-phy dev
Edward Cree (1):
sfc: fix crash when reading stats while NIC is resetting
Edwin Peer (1):
rtnetlink: extend RTEXT_FILTER_SKIP_STATS to IFLA_VF_INFO
Ekansh Gupta (1):
misc: fastrpc: Create fastrpc scalar with correct buffer count
Emmanuel Grumbach (1):
iwlwifi: don't dump_stack() when we get an unexpected interrupt
Eric Dumazet (5):
netlink: fix potential deadlock in netlink_set_err()
netlink: do not hard code device address lenth in fdb dumps
bonding: do not assume skb mac_header is set
tcp: annotate data races in __tcp_oow_rate_limited()
udp6: fix udp6_ehashfn() typo
Fabian Frederick (1):
jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
Fabio Estevam (1):
drm/panel: simple: Add connector_type for innolux_at043tn24
Fabrizio Lamarque (2):
iio: adc: ad7192: Fix null ad7192_state pointer access
iio: adc: ad7192: Fix internal/external clock selection
Fancy Fang (1):
pwm: imx-tpm: force 'real_period' to be zero in suspend
Fedor Pchelkin (2):
wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx
wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes
Fei Shao (1):
clk: Fix memory leak in devm_clk_notifier_register()
Feng Mingxi (1):
clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
Filipe Manana (4):
btrfs: do not BUG_ON() on tree mod log failure at balance_level()
btrfs: fix race when deleting quota root from the dirty cow roots list
btrfs: fix extent buffer leak after tree mod log failure at split_node()
btrfs: do not BUG_ON() on tree mod log failure at __btrfs_cow_block()
Florent Revest (2):
netfilter: conntrack: Avoid nf_ct_helper_hash uses after free
samples: ftrace: Save required argument registers in sample trampolines
Florian Fainelli (1):
net: bcmgenet: Ensure MDIO unregistration has clocks enabled
Florian Kauer (2):
igc: Fix launchtime before start of cycle
igc: Fix inserting of empty frame for launchtime
Florian Westphal (2):
netfilter: conntrack: dccp: copy entire header to stack buffer, not just basic one
net/sched: act_ipt: add sanity checks on table name and hook locations
Francesco Dolcini (9):
drm/bridge: tc358768: always enable HS video mode
drm/bridge: tc358768: fix PLL parameters computation
drm/bridge: tc358768: fix PLL target frequency
drm/bridge: tc358768: fix TCLK_ZEROCNT computation
drm/bridge: tc358768: Add atomic_get_input_bus_fmts() implementation
drm/bridge: tc358768: fix TCLK_TRAILCNT computation
drm/bridge: tc358768: fix THS_ZEROCNT computation
drm/bridge: tc358768: fix TXTAGOCNT computation
drm/bridge: tc358768: fix THS_TRAILCNT computation
Gao Xiang (2):
erofs: decouple basic mount options from fs_context
erofs: fix compact 4B support for 16k block size
Geert Uytterhoeven (3):
regulator: core: Fix more error checking for debugfs_create_dir()
regulator: core: Streamline debugfs operations
ARM: dts: iwg20d-q7-common: Fix backlight pwm specifier
George Stark (1):
meson saradc: fix clock divider mask length
Gilad Sever (3):
bpf: Factor out socket lookup functions for the TC hookpoint.
bpf: Call __bpf_sk_lookup()/__bpf_skc_lookup() directly via TC hookpoint
bpf: Fix bpf socket lookup from tc/xdp to respect socket VRF bindings
Giovanni Cabiddu (1):
crypto: qat - honor CRYPTO_TFM_REQ_MAY_SLEEP flag
Greg Kroah-Hartman (2):
Revert "usb: common: usb-conn-gpio: Set last role to unknown before initial detection"
Linux 5.15.121
Guenter Roeck (1):
hwmon: (pmbus/adm1275) Fix problems with temperature monitoring on ADM1272
Guillaume Nault (1):
pptp: Fix fib lookup calls.
Hao Luo (1):
clk: imx: clk-imx8mn: fix memory leak in imx8mn_clocks_probe
Hareshx Sankar Raj (2):
crypto: qat - unmap buffer before free for DH
crypto: qat - unmap buffers before free for RSA
Hariprasad Kelam (3):
octeontx2-af: Fix mapping for NIX block from CGX connection
octeontx2-af: Add validation before accessing cgx and lmac
octeontx-af: fix hardware timestamp configuration
Heiko Carstens (1):
s390/decompressor: fix misaligned symbol build error
Herbert Xu (3):
hwrng: virtio - Fix race on data_avail and actual data
crypto: kpp - Add helper to set reqsize
crypto: qat - Use helper to set reqsize
Huacai Chen (2):
MIPS: Loongson: Fix cpu_probe_loongson() again
MIPS: KVM: Fix NULL pointer dereference
Ido Schimmel (1):
net/sched: flower: Ensure both minimum and maximum ports are specified
Ilia.Gavrilov (1):
netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return value.
Ilya Dryomov (1):
libceph: harden msgr2.1 frame segment length checks
Ilya Maximets (1):
xsk: Honor SO_BINDTODEVICE on bind
Jakub Kicinski (1):
wl3501_cs: use eth_hw_addr_set()
James Clark (1):
coresight: Fix loss of connection info when a module is unloaded
Jan Kara (5):
ext4: Remove ext4 locking of moved directory
Revert "f2fs: fix potential corruption when moving a directory"
fs: Establish locking order for unrelated directories
fs: Lock moved directories
fs: no need to check source
Jarkko Sakkinen (1):
tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
Jason A. Donenfeld (2):
wireguard: queueing: use saner cpu selection wrapping
wireguard: netlink: send staged packets when setting initial private key
Jason Baron (1):
md/raid0: add discard support for the 'original' layout
Jens Axboe (3):
io_uring: ensure IOPOLL locks around deferred work
io_uring: wait interruptibly for request completions on exit
io_uring: add reschedule point to handle_tw_list()
Jeremy Sowden (1):
lib/ts_bm: reset initial match offset for every block of text
Jesper Dangaard Brouer (2):
igc: Enable and fix RX hash usage by netstack
selftests/bpf: Fix check_mtu using wrong variable type
Jiaqing Zhao (1):
Revert "8250: add support for ASIX devices with a FIFO bug"
Jiasheng Jiang (3):
pstore/ram: Add check for kstrdup
mfd: intel-lpss: Add missing check for platform_get_resource
NTB: ntb_tool: Add check for devm_kcalloc
Jinhong Zhu (1):
scsi: qedf: Fix NULL dereference in error handling
Jisheng Zhang (1):
riscv: mm: fix truncation warning on RV32
Johan Hovold (1):
mfd: pm8008: Fix module autoloading
Johannes Berg (2):
wifi: iwlwifi: pull from TXQs with softirqs disabled
wifi: iwlwifi: mvm: indicate HW decrypt for beacon protection
John Ogness (2):
serial: 8250: lock port for stop_rx() in omap8250_irq()
serial: 8250: lock port for UART_IER access in omap8250_irq()
John Paul Adrian Glaubitz (2):
irqchip/jcore-aic: Fix missing allocation of IRQ descriptors
sh: j2: Use ioremap() to translate device tree address into kernel memory
Jonas Gorski (2):
spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
bus: ixp4xx: fix IXP4XX_EXP_T1_MASK
Jouni Högander (1):
drm/i915/psr: Use hw.adjusted mode when calculating io/fast wake times
Joy Chakraborty (1):
spi: dw: Round of n_bytes to power of 2
Juergen Gross (1):
x86/mm: Fix __swp_entry_to_pte() for Xen PV guests
Junfeng Guo (1):
gve: Set default duplex configuration to full
Junyan Ye (1):
PCI: ftpci100: Release the clock resources
Kalesh AP (4):
RDMA/bnxt_re: Fix to remove unnecessary return labels
RDMA/bnxt_re: Use unique names while registering interrupts
RDMA/bnxt_re: Remove a redundant check inside bnxt_re_update_gid
RDMA/bnxt_re: Fix to remove an unnecessary log
Kashyap Desai (2):
RDMA/bnxt_re: wraparound mbox producer index
RDMA/bnxt_re: Avoid calling wake_up threads from spin_lock context
Keerthy (1):
arm64: dts: ti: k3-j7200: Fix physical address of pin
Kees Cook (1):
um: Use HOST_DIR for mrproper
Keith Busch (1):
nvme-pci: remove nvme_queue from nvme_iod
Kemeng Shi (3):
ext4: fix wrong unit use in ext4_mb_clear_bb
ext4: get block from bh in ext4_free_blocks for fast commit replay
ext4: fix wrong unit use in ext4_mb_new_blocks
Kiran K (1):
ACPI: utils: Fix acpi_evaluate_dsm_typed() redefinition error
Klaus Kudielka (1):
net: mvneta: fix txq_map in case of txq_number==1
Konrad Dybcio (1):
drm/msm/dpu: Set DPU_DATA_HCTL_EN for in INTF_SC7180_MASK
Konstantin Komarov (1):
fs/ntfs3: Check fields while reading
Kornel Dulęba (1):
pinctrl: amd: Detect and mask spurious interrupts
Krishna Kurapati (1):
usb: dwc3: gadget: Propagate core init errors to UDC during pullup
Krister Johansen (1):
net: ena: fix shift-out-of-bounds in exponential backoff
Krzysztof Kozlowski (11):
nfc: llcp: fix possible use of uninitialized variable in nfc_llcp_send_connect()
nfc: llcp: simplify llcp_sock_connect() error paths
arm64: dts: qcom: msm8916: correct camss unit address
arm64: dts: qcom: msm8994: correct SPMI unit address
arm64: dts: qcom: msm8996: correct camss unit address
arm64: dts: qcom: sdm630: correct camss unit address
arm64: dts: qcom: sdm845: correct camss unit address
arm64: dts: qcom: apq8096: fix fixed regulator name property
memory: brcmstb_dpfe: fix testing array offset after use
ARM: dts: qcom: ipq4019: fix broken NAND controller properties override
soundwire: qcom: fix storing port config out-of-bounds
Kumar Kartikeya Dwivedi (1):
bpf: Fix max stack depth check for async callbacks
Kuniyuki Iwashima (3):
gtp: Fix use-after-free in __gtp_encap_destroy().
netlink: Add __sock_i_ino() for __netlink_diag_dump().
icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
Laurent Vivier (4):
hwrng: virtio - add an internal buffer
hwrng: virtio - don't wait on cleanup
hwrng: virtio - don't waste entropy
hwrng: virtio - always add a pending request
Li Nan (7):
blk-iocost: use spin_lock_irqsave in adjust_inuse_and_calc_cost
md/raid10: check slab-out-of-bounds in md_bitmap_get_counter
md/raid10: fix overflow of md/safe_mode_delay
md/raid10: fix wrong setting of max_corr_read_errors
md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request
md/raid10: fix io loss while replacement replace rdev
md/raid10: fix the condition to call bio_end_io_acct()
Li Yang (1):
usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
Li Zhijian (1):
rcuscale: Always log error message
Lin Ma (2):
net: nfc: Fix use-after-free caused by nfc_llcp_find_local
net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
Linus Torvalds (1):
workqueue: clean up WORK_* constant types, clarify masking
Liu Shixin (1):
bootmem: remove the vmemmap pages from kmemleak in free_bootmem_page
Luc Ma (1):
drm/vram-helper: fix function names in vram helper doc
Luca Weiss (1):
Input: drv260x - sleep between polling GO bit
M A Ramdhan (1):
net/sched: cls_fw: Fix improper refcount update leads to use-after-free
Manish Rangankar (1):
scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
Manivannan Sadhasivam (1):
PCI: qcom: Disable write access to read only registers for IP v2.3.3
Mantas Pucka (1):
clk: qcom: gcc-ipq6018: Use floor ops for sdcc clocks
Marek Vasut (10):
wifi: rsi: Do not configure WoWlan in shutdown hook if not enabled
wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown
Input: adxl34x - do not hardcode interrupt trigger type
ARM: dts: stm32: Move ethernet MAC EEPROM from SoM to carrier boards
ARM: dts: stm32: Shorten the AV96 HDMI sound card name
ARM: dts: stm32: Fix audio routing on STM32MP15xx DHCOM PDK2
media: videodev2.h: Fix struct v4l2_input tuner index comment
pwm: sysfs: Do not apply state to already disabled PWMs
i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()
drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
Marijn Suijten (1):
arm64: dts: qcom: sm8250-edo: Panel framebuffer is 2.5k instead of 4k
Mario Limonciello (4):
pinctrl: amd: Fix mistake in handling clearing pins at startup
pinctrl: amd: Detect internal GPIO0 debounce handling
pinctrl: amd: Only use special debounce behavior for GPIO 0
drm/amd/display: Correct `DMUB_FW_VERSION` macro
Mark Rutland (1):
locking/atomic: arm: fix sync ops
Martin Blumenstingl (1):
ARM: dts: meson8: correct uart_B and uart_C clock references
Martin Fuzzey (1):
tty: serial: imx: fix rs485 rx after tx
Martin KaFai Lau (1):
libbpf: btf_dump_type_data_check_overflow needs to consider BTF_MEMBER_BITFIELD_SIZE
Martin Kaiser (2):
hwrng: st - keep clock enabled while hwrng is registered
hwrng: imx-rngc - fix the timeout for init and self check
Masahiro Yamada (4):
modpost: remove broken calculation of exception_table_entry size
modpost: fix section mismatch message for R_ARM_ABS32
modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24}
ARC: define ASM_NL and __ALIGN(_STR) outside #ifdef __ASSEMBLY__ guard
Masami Hiramatsu (Google) (2):
tracing/probes: Fix not to count error code to total length
tracing/probes: Fix to update dynamic data counter if fetcharg uses it
Mateusz Stachyra (1):
tracing: Fix null pointer dereference in tracing_err_log_open()
Matt Corallo (1):
btrfs: add handling for RAID1C23/DUP to btrfs_reduce_alloc_profile
Matthieu Baerts (2):
selftests: mptcp: sockopt: return error if wrong mark
selftests: mptcp: depend on SYN_COOKIES
Max Filippov (1):
xtensa: ISS: fix call to split_if_spec
Maxim Kochetkov (1):
net: axienet: Move reset before 64-bit DMA detection
Michael Ellerman (1):
powerpc/security: Fix Speculation_Store_Bypass reporting on Power10
Michael Schmitz (4):
block: fix signed int overflow in Amiga partition support
block: add overflow checks for Amiga partition support
block: change all __u32 annotations to __be32 in affs_hardblocks.h
block/partition: fix signedness issue for Amiga partitions
Mikulas Patocka (1):
dm integrity: reduce vmalloc space footprint on 32-bit architectures
Ming Lei (1):
nvme-pci: fix DMA direction of unmapping integrity data
Mingzhe Zou (1):
bcache: fixup btree_cache_wait list damage
Mirsad Goran Todorovac (1):
test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation
Mohamed Khalfella (1):
tracing/histograms: Add histograms to hist_vars if they have referenced variables
Moritz Fischer (1):
net: lan743x: Don't sleep in atomic context
Muchun Song (1):
kernfs: fix missing kernfs_idr_lock to remove an ID from the IDR
Muhammad Husaini Zulkifli (1):
igc: Remove delay during TX ring configuration
Namhyung Kim (1):
perf dwarf-aux: Fix off-by-one in die_get_varname()
Namjae Jeon (3):
ksmbd: validate command payload size
ksmbd: fix out-of-bound read in smb2_write
ksmbd: validate session id and tree id in the compound request
Naohiro Aota (3):
btrfs: delete unused BGs while reclaiming BGs
btrfs: bail out reclaim process if filesystem is read-only
btrfs: reinsert BGs failed to reclaim
Naveen N Rao (1):
powerpc: Fail build if using recordmcount with binutils v2.37
Nicholas Kazlauskas (1):
drm/amd/display: Explicitly specify update type per plane info change
Nicholas Piggin (2):
powerpc/64s: Fix VAS mm use after free
powerpc: simplify ppc_save_regs
Nick Child (1):
ibmvnic: Do not reset dql stats on NON_FATAL err
Nico Boehr (1):
KVM: s390: fix KVM_S390_GET_CMMA_BITS for GFNs in memslot holes
Nikita Zhandarovich (3):
PM: domains: fix integer overflow issues in genpd_parse_state()
radeon: avoid double free in ci_dpm_init()
drm/radeon: fix possible division-by-zero errors
Nilesh Javali (3):
scsi: qla2xxx: Array index may go out of bound
scsi: qla2xxx: Avoid fcport pointer dereference
scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
Nirmal Patel (1):
PCI: vmd: Reset VMD config register between soft reboots
Nishanth Menon (1):
mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0
Nitya Sunkad (1):
ionic: remove WARN_ON to prevent panic_on_warn
Nícolas F. R. A. Prado (1):
arm64: dts: mediatek: mt8192: Fix CPUs capacity-dmips-mhz
Olga Kornievskaia (1):
NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
Olivier Moysan (1):
ARM: dts: stm32: fix i2s endpoint format property for stm32mp15xx-dkx
Ondrej Zary (1):
PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
Pablo Neira Ayuso (2):
netfilter: nf_tables: drop map element references from preparation phase
netfilter: nf_tables: unbind non-anonymous set if rule construction fails
Paolo Abeni (1):
net: prevent skb corruption on frag list segmentation
Paul E. McKenney (2):
rcutorture: Correct name of use_softirq module parameter
rcuscale: Move shutdown from wait_event() to wait_event_idle()
Pawel Dembicki (1):
net: dsa: vsc73xx: fix MTU configuration
Pedro Tammela (4):
net/sched: make psched_mtu() RTNL-less safe
net/sched: sch_qfq: refactor parsing of netlink parameters
net/sched: sch_qfq: account for stab overhead in qfq_enqueue
net/sched: sch_qfq: reintroduce lmax bound check for MTU
Pengcheng Yang (1):
samples/bpf: Fix buffer overflow in tcp_basertt
Peter Korsgaard (1):
dm init: add dm-mod.waitfor to wait for asynchronously probed block devices
Peter Seiderer (1):
wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation
Phil Elwell (1):
nvmem: rmem: Use NVMEM_DEVID_AUTO
Pierre Morel (1):
KVM: s390: vsie: fix the length of APCB bitmap
Potin Lai (1):
hwmon: (adm1275) Allow setting sample averaging
Prasad Koya (1):
igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
Prashanth K (2):
usb: gadget: u_serial: Add null pointer check in gserial_suspend
usb: common: usb-conn-gpio: Set last role to unknown before initial detection
Pu Lehui (2):
bpf, riscv: Support riscv jit to provide bpf_line_info
bpf: cpumap: Fix memory leak in cpu_map_update_elem
Qiuxu Zhuo (2):
rcu/rcuscale: Move rcu_scale_*() after kfree_scale_cleanup()
rcu/rcuscale: Stop kfree_scale_thread thread(s) after unloading rcuscale
Quinn Tran (2):
scsi: qla2xxx: Wait for io return on terminate rport
scsi: qla2xxx: Fix buffer overrun
Rafał Miłecki (2):
ARM: dts: BCM5301X: Drop "clock-names" from the SPI node
net: bgmac: postpone turning IRQs off to avoid SoC hangs
Ralph Boehme (1):
ksmbd: use ksmbd_req_buf_next() in ksmbd_smb2_check_message()
Randy Dunlap (5):
soc/fsl/qe: fix usb.c build errors
crypto: nx - fix build warnings when DEBUG_FS is not enabled
media: cec: i2c: ch7322: also select REGMAP
powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y
wifi: airo: avoid uninitialized warning in airo_get_rate()
Ravi Bangoria (1):
perf/ibs: Fix interface via core pmu events
Remi Pommarel (1):
wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
Ricardo Ribalda Delgado (2):
ASoC: mediatek: mt8173: Fix irq error path
ASoC: mediatek: mt8173: Fix snd_soc_component_initialize error path
Rick Wertenbroek (5):
PCI: rockchip: Assert PCI Configuration Enable bit after probe
PCI: rockchip: Write PCI Device ID to correct register
PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
PCI: rockchip: Use u32 variable to access 32-bit registers
Rikard Falkeborn (1):
media: venus: helpers: Fix ALIGN() of non power of two
Robert Hancock (1):
i2c: xiic: Don't try to handle more interrupt events after error
Robert Marko (5):
arm64: dts: microchip: sparx5: do not use PSCI on reference boards
clk: qcom: reset: support resetting multiple bits
clk: qcom: ipq6018: fix networking resets
mmc: core: disable TRIM on Kingston EMMC04G-M627
mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
Roberto Sassu (4):
evm: Complete description of evm_inode_setattr()
evm: Fix build warnings
ima: Fix build warnings
shmem: use ramfs_kill_sb() for kill_sb method of ramfs-based tmpfs
Robin Murphy (2):
perf/arm-cmn: Fix DTC reset
PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
Rongguang Wei (1):
PCI: pciehp: Cancel bringup sequence if card is not present
Ryan Roberts (1):
mm/damon/ops-common: atomically test and clear young on ptes and pmds
Sabrina Dubroca (1):
selftests: rtnetlink: remove netdevsim device after ipsec offload test
Sami Tolvanen (1):
kbuild: Disable GCOV for *.mod.o
Samuel Pitoiset (1):
drm/amdgpu: fix clearing mappings for BOs that are always valid in VM
Sean Nyekjaer (2):
iio: accel: fxls8962af: errata bug only applicable for FXLS8962AF
iio: accel: fxls8962af: fixup buffer scan element type
Sebastian Andrzej Siewior (1):
tracing/timer: Add missing hrtimer modes to decode_hrtimer_mode().
Selvin Xavier (1):
RDMA/bnxt_re: Disable/kill tasklet only if it is enabled
Shawn Wang (1):
x86/resctrl: Only show tasks' pid in current pid namespace
Sherry Sun (1):
tty: serial: fsl_lpuart: add earlycon for imx8ulp platform
Shreyas Deodhar (1):
scsi: qla2xxx: Pointer may be dereferenced
Shuai Jiang (1):
i2c: qup: Add missing unwind goto in qup_i2c_probe()
Shuijing Li (1):
pwm: mtk_disp: Fix the disable flow of disp_pwm
Siddh Raman Pant (1):
jfs: jfs_dmap: Validate db_l2nbperpage while mounting
Siddharth Vadapalli (1):
PCI: cadence: Fix Gen2 Link Retraining process
Sohaib Mohamed (1):
perf bench: Use unbuffered output when pipe/tee'ing to a file
Stanislav Fomichev (1):
bpf: Don't EFAULT for {g,s}setsockopt with wrong optlen
Stefan Wahren (1):
w1: w1_therm: fix locking behavior in convert_t
Stephan Gerhold (7):
arm64: dts: qcom: apq8016-sbc: Clarify firmware-names
arm64: dts: qcom: Drop unneeded extra device-specific includes
arm64: dts: qcom: apq8016-sbc: Fix regulator constraints
arm64: dts: qcom: apq8016-sbc: Fix 1.8V power rail on LS expansion
clk: qcom: reset: Allow specifying custom reset delay
mfd: rt5033: Drop rt5033-battery sub-device
opp: Fix use-after-free in lazy_opp_tables after probe deferral
Su Hui (1):
ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer
Sui Jingfeng (1):
PCI: Add pci_clear_master() stub for non-CONFIG_PCI
Suman Ghosh (1):
octeontx2-pf: Add additional check for MCAM rules
Suzuki K Poulose (1):
arm64: errata: Add detection for TRBE overwrite in FILL mode
Takashi Iwai (1):
ALSA: jack: Fix mutex call in snd_jack_report()
Taniya Das (1):
clk: qcom: camcc-sc7180: Add parent dependency to all camera GDSCs
Tarun Sahu (1):
dax/kmem: Pass valid argument to memory_group_register_static
Tero Kristo (1):
cpufreq: intel_pstate: Fix energy_performance_preference for passive
Thadeu Lima de Souza Cascardo (2):
netfilter: nf_tables: do not ignore genmask when looking up chain by id
netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
Thomas Bogendoerfer (1):
MIPS: kvm: Fix build error with KVM_MIPS_DEBUG_COP0_COUNTERS enabled
Thomas Gleixner (1):
posix-timers: Prevent RT livelock in itimer_delete()
Thomas Hellström (1):
drm/ttm: Don't leak a resource on swapout move error
Thomas Weißschuh (1):
fs: avoid empty option when generating legacy mount string
Thorsten Winkler (1):
s390/qeth: Fix vipa deletion
Tianjia Zhang (1):
integrity: Fix possible multiple allocation in integrity_inode_get()
Tiezhu Yang (1):
riscv: uprobes: Restore thread.bad_cause
Tim Harvey (1):
hwmon: (gsc-hwmon) fix fan pwm temperature scaling
Tobias Heider (1):
Add MODULE_FIRMWARE() for FIRMWARE_TG357766.
Tobias Klauser (1):
bpf: Omit superfluous address family check in __bpf_skc_lookup
Tony Lindgren (4):
bus: ti-sysc: Fix dispc quirk masking bool variables
ARM: dts: gta04: Move model property out of pinctrl node
serial: 8250: omap: Fix freeing of resources on failed register
serial: 8250_omap: Use force_suspend and resume for system suspend
Tvrtko Ursulin (1):
drm/i915: Fix one wrong caching mode enum usage
Tzvetomir Stoyanov (VMware) (1):
kernel/trace: Fix cleanup logic of enable_trace_eprobe
Ulf Hansson (1):
mmc: mmci: Set PROBE_PREFER_ASYNCHRONOUS
Uwe Kleine-König (2):
usb: dwc2: platform: Improve error reporting for problems during .remove()
extcon: usbc-tusb320: Convert to i2c's .probe_new()
Vijaya Krishna Nivarthi (1):
spi: spi-geni-qcom: Correct CS_TOGGLE bit in SPI_TRANS_CFG
Vincent Mailhol (1):
can: length: fix bitstuffing count
Vinicius Costa Gomes (1):
igc: Fix race condition in PTP tx code
Vinod Polimera (1):
drm/msm/disp/dpu: get timing engine status from intf status register
Vlad Buslov (1):
net/mlx5e: Check for NOT_READY flag state after locking
Vladimir Oltean (2):
net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode
net: dsa: tag_sja1105: fix MAC DA patching from meta frames
Vladislav Efanov (1):
usb: dwc3: qcom: Fix potential memory leak
Weitao Wang (3):
xhci: Fix resume issue of some ZHAOXIN hosts
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
xhci: Show ZHAOXIN xHCI root hub speed correctly
Werner Sembach (1):
ALSA: hda/realtek: Add quirk for Clevo NPx0SNx
Wesley Chalmers (1):
drm/amd/display: Add logging for display MALL refresh setting
Wolfram Sang (1):
arm64: dts: renesas: ulcb-kf: Remove flow control for SCIF1
Woody Zhang (1):
riscv: move memblock_allow_resize() after linear mapping is ready
Xin Yin (1):
erofs: fix fsdax unavailability for chunk-based regular files
Xiubo Li (1):
ceph: don't let check_caps skip sending responses for revoke msgs
XuDong Liu (1):
drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
Yang Yingliang (1):
NTB: ntb_transport: fix possible memory leak while device_register() fails
Yassine Oudjana (1):
arm64: dts: qcom: db820c: Move blsp1_uart2 pin states to msm8996.dtsi
Yuan Can (4):
clk: tegra: tegra124-emc: Fix potential memory leak
ntb: idt: Fix error handling in idt_pci_driver_init()
NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
Yuchen Yang (1):
scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
Yuxing Liu (1):
clk: imx: clk-imx8mp: improve error handling in imx8mp_clocks_probe()
Zeng Heng (1):
ntfs: Fix panic about slab-out-of-bounds caused by ntfs_listxattr()
Zhang Rui (1):
powercap: RAPL: Fix CONFIG_IOSF_MBI dependency
Zhen Lei (1):
kexec: fix a memory leak in crash_shrink_memory()
Zheng Wang (2):
bcache: Remove unnecessary NULL point check in node allocations
bcache: Fix __bch_btree_node_alloc to make the failure behavior consistent
Zheng Yejian (3):
tracing: Fix memory leak of iter->temp when reading trace_pipe
ring-buffer: Fix deadloop issue on reading trace_pipe
ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
Zhengchao Shao (2):
net/mlx5e: fix double free in mlx5e_destroy_flow_table
net/mlx5e: fix memory leak in mlx5e_ptp_open
Zhihao Cheng (2):
ovl: fix null pointer dereference in ovl_get_acl_rcu()
ext4: Fix reusing stale buffer heads from last failed mounting
Ziyang Xuan (1):
ipv6/addrconf: fix a potential refcount underflow for idev
gaba (1):
drm/amdgpu: avoid restore process run into dead loop.
hfdevel@gmx.net (1):
ARM: dts: meson8b: correct uart_B and uart_C clock references
^ permalink raw reply [relevance 1%]
* [PATCH 6.1 032/223] net: bgmac: postpone turning IRQs off to avoid SoC hangs
2023-07-21 16:04 1% [PATCH 6.1 000/223] 6.1.40-rc1 review Greg Kroah-Hartman
@ 2023-07-21 16:04 7% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-21 16:04 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rafał Miłecki,
Michal Kubiak, David S. Miller, Sasha Levin
From: Rafał Miłecki <rafal@milecki.pl>
[ Upstream commit e7731194fdf085f46d58b1adccfddbd0dfee4873 ]
Turning IRQs off is done by accessing Ethernet controller registers.
That can't be done until device's clock is enabled. It results in a SoC
hang otherwise.
This bug remained unnoticed for years as most bootloaders keep all
Ethernet interfaces turned on. It seems to only affect a niche SoC
family BCM47189. It has two Ethernet controllers but CFE bootloader uses
only the first one.
Fixes: 34322615cbaa ("net: bgmac: Mask interrupts during probe")
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Reviewed-by: Michal Kubiak <michal.kubiak@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/broadcom/bgmac.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 1761df8fb7f96..10c7c232cc4ec 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1492,8 +1492,6 @@ int bgmac_enet_probe(struct bgmac *bgmac)
bgmac->in_init = true;
- bgmac_chip_intrs_off(bgmac);
-
net_dev->irq = bgmac->irq;
SET_NETDEV_DEV(net_dev, bgmac->dev);
dev_set_drvdata(bgmac->dev, bgmac);
@@ -1511,6 +1509,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)
*/
bgmac_clk_enable(bgmac, 0);
+ bgmac_chip_intrs_off(bgmac);
+
/* This seems to be fixing IRQ by assigning OOB #6 to the core */
if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) {
if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
--
2.39.2
^ permalink raw reply related [relevance 7%]
* [PATCH 6.1 000/223] 6.1.40-rc1 review
@ 2023-07-21 16:04 1% Greg Kroah-Hartman
2023-07-21 16:04 7% ` [PATCH 6.1 032/223] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2023-07-21 16:04 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, srw, rwarsow, conor
This is the start of the stable review cycle for the 6.1.40 release.
There are 223 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Sun, 23 Jul 2023 16:04:33 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.1.40-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.1.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 6.1.40-rc1
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: reintroduce lmax bound check for MTU
Randy Dunlap <rdunlap@infradead.org>
swiotlb: mark swiotlb_memblock_alloc() as __init
Mario Limonciello <mario.limonciello@amd.com>
Revert "drm/amd: Disable PSR-SU on Parade 0803 TCON"
Thomas Bogendoerfer <tsbogend@alpha.franken.de>
MIPS: kvm: Fix build error with KVM_MIPS_DEBUG_COP0_COUNTERS enabled
Dan Carpenter <dan.carpenter@linaro.org>
scsi: qla2xxx: Fix end of loop test
Manish Rangankar <mrangankar@marvell.com>
scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
Shreyas Deodhar <sdeodhar@marvell.com>
scsi: qla2xxx: Pointer may be dereferenced
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Correct the index of array
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Fix potential NULL pointer dereference
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix buffer overrun
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Avoid fcport pointer dereference
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Array index may go out of bound
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix mem access after free
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Wait for io return on terminate rport
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix hang in task management
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix task management cmd fail due to unavailable resource
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix task management cmd failure
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Multi-que support for TMF
Beau Belgrave <beaub@linux.microsoft.com>
tracing/user_events: Fix struct arg size match check
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix to update dynamic data counter if fetcharg uses it
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix not to count error code to total length
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: pm_nl_ctl: fix 32-bit support
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: depend on SYN_COOKIES
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: userspace_pm: report errors with 'remove' tests
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: userspace_pm: use correct server port
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: sockopt: return error if wrong mark
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: connect: fail if nft supposed to work
Mateusz Stachyra <m.stachyra@samsung.com>
tracing: Fix null pointer dereference in tracing_err_log_open()
Masami Hiramatsu (Google) <mhiramat@kernel.org>
fprobe: Ensure running fprobe_exit_handler() finished before calling rethook_free()
Jiri Olsa <jolsa@kernel.org>
fprobe: Release rethook after the ftrace_ops is unregistered
Heiner Kallweit <hkallweit1@gmail.com>
pwm: meson: fix handling of period/duty if greater than UINT_MAX
Heiner Kallweit <hkallweit1@gmail.com>
pwm: meson: modify and simplify calculation in meson_pwm_get_state
Chungkai Yang <Chung-kai.Yang@mediatek.com>
PM: QoS: Restore support for default value on frequency QoS
Namhyung Kim <namhyung@kernel.org>
perf/x86: Fix lockdep warning in for_each_sibling_event() on SPR
Max Filippov <jcmvbkbc@gmail.com>
xtensa: ISS: fix call to split_if_spec
Bharath SM <bharathsm@microsoft.com>
cifs: if deferred close is disabled then close files immediately
Mario Limonciello <mario.limonciello@amd.com>
drm/amd/pm: conditionally disable pcie lane/speed switching for SMU13
Evan Quan <evan.quan@amd.com>
drm/amd/pm: share the code around SMU13 pcie parameters update
Zheng Yejian <zhengyejian1@huawei.com>
ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
Zheng Yejian <zhengyejian1@huawei.com>
ring-buffer: Fix deadloop issue on reading trace_pipe
Krister Johansen <kjlx@templeofstupid.com>
net: ena: fix shift-out-of-bounds in exponential backoff
Isaac J. Manjarres <isaacmanjarres@google.com>
regmap-irq: Fix out-of-bounds access when allocating config buffers
Eric Lin <eric.lin@sifive.com>
perf: RISC-V: Remove PERF_HES_STOPPED flag checking in riscv_pmu_start()
Florent Revest <revest@chromium.org>
samples: ftrace: Save required argument registers in sample trampolines
Christoph Hellwig <hch@lst.de>
nvme: don't reject probe due to duplicate IDs for single-ported PCIe devices
Zheng Yejian <zhengyejian1@huawei.com>
tracing: Fix memory leak of iter->temp when reading trace_pipe
Mohamed Khalfella <mkhalfella@purestorage.com>
tracing/histograms: Add histograms to hist_vars if they have referenced variables
Matthias Kaehlcke <mka@chromium.org>
dm: verity-loadpin: Add NULL pointer check for 'bdev' parameter
Heiko Carstens <hca@linux.ibm.com>
s390/decompressor: fix misaligned symbol build error
Jonas Gorski <jonas.gorski@gmail.com>
bus: ixp4xx: fix IXP4XX_EXP_T1_MASK
Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Revert "8250: add support for ASIX devices with a FIFO bug"
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
soundwire: qcom: fix storing port config out-of-bounds
Stephan Gerhold <stephan.gerhold@kernkonzept.com>
opp: Fix use-after-free in lazy_opp_tables after probe deferral
George Stark <gnstark@sberdevices.ru>
meson saradc: fix clock divider mask length
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Show ZHAOXIN xHCI root hub speed correctly
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix resume issue of some ZHAOXIN hosts
Xiubo Li <xiubli@redhat.com>
ceph: don't let check_caps skip sending responses for revoke msgs
Xiubo Li <xiubli@redhat.com>
ceph: fix blindly expanding the readahead windows
Xiubo Li <xiubli@redhat.com>
ceph: add a dedicated private data for netfs rreq
Ilya Dryomov <idryomov@gmail.com>
libceph: harden msgr2.1 frame segment length checks
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
Martin Fuzzey <martin.fuzzey@flowbird.group>
tty: serial: imx: fix rs485 rx after tx
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
Dan Carpenter <dan.carpenter@linaro.org>
serial: atmel: don't enable IRQs prematurely
Christian König <christian.koenig@amd.com>
drm/ttm: never consider pinned BOs for eviction&swap
Thomas Hellström <thomas.hellstrom@linux.intel.com>
drm/ttm: Don't leak a resource on swapout move error
gaba <gaba@amd.com>
drm/amdgpu: avoid restore process run into dead loop.
Aurabindo Pillai <aurabindo.pillai@amd.com>
drm/amd/display: Add monitor specific edid quirk
Mario Limonciello <mario.limonciello@amd.com>
drm/amd/display: Correct `DMUB_FW_VERSION` macro
Sung-huai Wang <danny.wang@amd.com>
drm/amd/display: add a NULL pointer check
Mario Limonciello <mario.limonciello@amd.com>
drm/amd: Disable PSR-SU on Parade 0803 TCON
Samuel Pitoiset <samuel.pitoiset@gmail.com>
drm/amdgpu: fix clearing mappings for BOs that are always valid in VM
Leo Chen <sancchen@amd.com>
drm/amd/display: disable seamless boot if force_odm_combine is enabled
Austin Zheng <austin.zheng@amd.com>
drm/amd/display: Remove Phantom Pipe Check When Calculating K1 and K2
Hersen Wu <hersenxs.wu@amd.com>
drm/amd/display: edp do not add non-edid timings
Dmytro Laktyushkin <dmytro.laktyushkin@amd.com>
drm/amd/display: fix seamless odm transitions
Brian Norris <briannorris@chromium.org>
drm/rockchip: vop: Leave vblank enabled in self-refresh
Brian Norris <briannorris@chromium.org>
drm/atomic: Allow vblank-enabled + self-refresh "disable"
Justin Tee <justin.tee@broadcom.com>
scsi: lpfc: Fix double free in lpfc_cmpl_els_logo_acc() caused by lpfc_nlp_not_used()
Alexander Aring <aahringo@redhat.com>
fs: dlm: fix mismatch of plock results from userspace
Alexander Aring <aahringo@redhat.com>
fs: dlm: make F_SETLK use unkillable wait_event
Alexander Aring <aahringo@redhat.com>
fs: dlm: interrupt posix locks only when process is killed
Alexander Aring <aahringo@redhat.com>
fs: dlm: fix cleanup pending ops when interrupted
Alexander Aring <aahringo@redhat.com>
fs: dlm: return positive pid value for F_GETLK
Peter Korsgaard <peter@korsgaard.com>
dm init: add dm-mod.waitfor to wait for asynchronously probed block devices
Jason Baron <jbaron@akamai.com>
md/raid0: add discard support for the 'original' layout
Johan Hovold <johan+linaro@kernel.org>
mfd: pm8008: Fix module autoloading
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Re-init completion for every test
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Free IRQs before removing the device
Damien Le Moal <dlemoal@kernel.org>
PCI: rockchip: Set address alignment for endpoint mode
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Use u32 variable to access 32-bit registers
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Write PCI Device ID to correct register
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Assert PCI Configuration Enable bit after probe
Damien Le Moal <dlemoal@kernel.org>
PCI: epf-test: Fix DMA transfer completion detection
Damien Le Moal <dlemoal@kernel.org>
PCI: epf-test: Fix DMA transfer completion initialization
Manivannan Sadhasivam <mani@kernel.org>
PCI: qcom: Disable write access to read only registers for IP v2.3.3
Igor Mammedov <imammedo@redhat.com>
PCI: acpiphp: Reassign resources on bridge if necessary
Robin Murphy <robin.murphy@arm.com>
PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
Ross Lagerwall <ross.lagerwall@citrix.com>
PCI: Release resource invalidated by coalescing
Ondrej Zary <linux@zary.sk>
PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: do not retry administrative requests
Sathya Prakash <sathya.prakash@broadcom.com>
scsi: mpi3mr: Propagate sense data for admin queue SCSI I/O
Mikulas Patocka <mpatocka@redhat.com>
dm integrity: reduce vmalloc space footprint on 32-bit architectures
Martin Kaiser <martin@kaiser.cx>
hwrng: imx-rngc - fix the timeout for init and self check
Siddh Raman Pant <code@siddh.me>
jfs: jfs_dmap: Validate db_l2nbperpage while mounting
Ritesh Harjani (IBM) <ritesh.list@gmail.com>
ext2/dax: Fix ext2_setsize when len is page aligned
Christian Marangi <ansuelsmth@gmail.com>
soc: qcom: mdt_loader: Fix unconditional call to scm_pas_mem_setup
Alexander Aring <aahringo@redhat.com>
fs: dlm: revert check required context while close
Baokun Li <libaokun1@huawei.com>
ext4: only update i_reserved_data_blocks on successful block allocation
Baokun Li <libaokun1@huawei.com>
ext4: turn quotas off if mount failed after enabling quotas
Chao Yu <chao@kernel.org>
ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_new_blocks
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: get block from bh in ext4_free_blocks for fast commit replay
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_clear_bb
Zhihao Cheng <chengzhihao1@huawei.com>
ext4: Fix reusing stale buffer heads from last failed mounting
Huacai Chen <chenhuacai@kernel.org>
MIPS: KVM: Fix NULL pointer dereference
Huacai Chen <chenhuacai@kernel.org>
MIPS: Loongson: Fix cpu_probe_loongson() again
Michael Ellerman <mpe@ellerman.id.au>
powerpc/64s: Fix native_hpte_remove() to be irq-safe
Michael Ellerman <mpe@ellerman.id.au>
powerpc/security: Fix Speculation_Store_Bypass reporting on Power10
Ekansh Gupta <quic_ekangupt@quicinc.com>
misc: fastrpc: Create fastrpc scalar with correct buffer count
Naveen N Rao <naveen@kernel.org>
powerpc: Fail build if using recordmcount with binutils v2.37
sunliming <sunliming@kylinos.cn>
tracing/user_events: Fix incorrect return value for writing operation when events are disabled
Arnd Bergmann <arnd@arndb.de>
kasan: add kasan_tag_mismatch prototype
Oleksij Rempel <linux@rempel-privat.de>
net: phy: dp83td510: fix kernel stall during netboot in DP83TD510E PHY driver
Florian Fainelli <florian.fainelli@broadcom.com>
net: bcmgenet: Ensure MDIO unregistration has clocks enabled
Arseniy Krasnov <AVKrasnov@sberdevices.ru>
mtd: rawnand: meson: fix unaligned DMA buffers handling
Jerry Snitselaar <jsnitsel@redhat.com>
tpm: return false from tpm_amd_is_rng_defective on non-x86 platforms
Alexander Sverdlin <alexander.sverdlin@siemens.com>
tpm: tis_i2c: Limit write bursts to I2C_SMBUS_BLOCK_MAX (32) bytes
Alexander Sverdlin <alexander.sverdlin@siemens.com>
tpm: tis_i2c: Limit read bursts to I2C_SMBUS_BLOCK_MAX (32) bytes
Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
Valentin David <valentin.david@gmail.com>
tpm: Do not remap from ACPI resources again for Pluton TPM
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Unify debounce handling into amd_pinconf_set()
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Drop pull up select configuration
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Use amd_pinconf_set() for all config options
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Only use special debounce behavior for GPIO 0
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Revert "pinctrl: amd: disable and mask interrupts on probe"
Kornel Dulęba <korneld@chromium.org>
pinctrl: amd: Detect and mask spurious interrupts
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Fix mistake in handling clearing pins at startup
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Detect internal GPIO0 debounce handling
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Add fields for interrupt status and wake status
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Adjust debugfs output
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
pinctrl: amd: Add Z-state wake control bits
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: fix deadlock in i_xattr_sem and inode page lock
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: fix the wrong condition to determine atomic context
Kenneth Feng <kenneth.feng@amd.com>
drm/amd/pm: add abnormal fan detection for smu 13.0.0
Luben Tuikov <luben.tuikov@amd.com>
drm/amdgpu: Fix minmax warning
lyndonli <Lyndon.Li@amd.com>
drm/amdgpu: add the fan abnormal detection feature
Evan Quan <evan.quan@amd.com>
drm/amd/pm: revise the ASPM settings for thunderbolt attached scenario
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/sdma4: set align mask to 255
Thomas Zimmermann <tzimmermann@suse.de>
drm/client: Send hotplug event after registering a client
Winston Wen <wentao@uniontech.com>
cifs: fix session state check in smb2_find_smb_ses
Zhihao Cheng <chengzhihao1@huawei.com>
ovl: fix null pointer dereference in ovl_get_acl_rcu()
Zhihao Cheng <chengzhihao1@huawei.com>
ovl: let helper ovl_i_path_real() return the realinode
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Check fields while reading
Ming Lei <ming.lei@redhat.com>
nvme-pci: fix DMA direction of unmapping integrity data
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: account for stab overhead in qfq_enqueue
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: refactor parsing of netlink parameters
Zhang Shurong <zhang_shurong@foxmail.com>
wifi: rtw89: debug: fix error code in rtw89_debug_priv_send_h2c_set()
Pedro Tammela <pctammela@mojatatu.com>
net/sched: make psched_mtu() RTNL-less safe
Dan Carpenter <dan.carpenter@linaro.org>
netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
Jisheng Zhang <jszhang@kernel.org>
riscv: mm: fix truncation warning on RV32
Ido Schimmel <idosch@nvidia.com>
net/sched: flower: Ensure both minimum and maximum ports are specified
Pu Lehui <pulehui@huawei.com>
bpf: cpumap: Fix memory leak in cpu_map_update_elem
Randy Dunlap <rdunlap@infradead.org>
wifi: airo: avoid uninitialized warning in airo_get_rate()
Xin Yin <yinxin.x@bytedance.com>
erofs: fix fsdax unavailability for chunk-based regular files
Chunhai Guo <guochunhai@vivo.com>
erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
Chunhai Guo <guochunhai@vivo.com>
erofs: avoid useless loops in z_erofs_pcluster_readmore() when reading beyond EOF
Suman Ghosh <sumang@marvell.com>
octeontx2-pf: Add additional check for MCAM rules
Tvrtko Ursulin <tvrtko.ursulin@intel.com>
drm/i915: Fix one wrong caching mode enum usage
Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
drm/i915: Don't preserve dpll_hw_state for slave crtc in Bigjoiner
Björn Töpel <bjorn@rivosinc.com>
riscv, bpf: Fix inconsistent JIT image generation
Ankit Kumar <ankit.kumar@samsung.com>
nvme: fix the NVME_ID_NS_NVM_STS_MASK definition
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix inserting of empty frame for launchtime
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix launchtime before start of cycle
Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
kernel/trace: Fix cleanup logic of enable_trace_eprobe
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
platform/x86: wmi: Break possible infinite loop when parsing GUID
Jiasheng Jiang <jiasheng@iscas.ac.cn>
net: dsa: qca8k: Add check for skb_copy
Ziyang Xuan <william.xuanziyang@huawei.com>
ipv6/addrconf: fix a potential refcount underflow for idev
Jiasheng Jiang <jiasheng@iscas.ac.cn>
NTB: ntb_tool: Add check for devm_kcalloc
Yang Yingliang <yangyingliang@huawei.com>
NTB: ntb_transport: fix possible memory leak while device_register() fails
Yuan Can <yuancan@huawei.com>
ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
ntb: idt: Fix error handling in idt_pci_driver_init()
Eric Dumazet <edumazet@google.com>
udp6: fix udp6_ehashfn() typo
Kuniyuki Iwashima <kuniyu@amazon.com>
icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
Paolo Abeni <pabeni@redhat.com>
net: prevent skb corruption on frag list segmentation
Rafał Miłecki <rafal@milecki.pl>
net: bgmac: postpone turning IRQs off to avoid SoC hangs
Nitya Sunkad <nitya.sunkad@amd.com>
ionic: remove WARN_ON to prevent panic_on_warn
Sai Krishna <saikrishnag@marvell.com>
octeontx2-af: Move validation of ptp pointer before its usage
Ratheesh Kannoth <rkannoth@marvell.com>
octeontx2-af: Promisc enable/disable through mbox
Junfeng Guo <junfeng.guo@intel.com>
gve: Set default duplex configuration to full
M A Ramdhan <ramdhan@starlabs.sg>
net/sched: cls_fw: Fix improper refcount update leads to use-after-free
Klaus Kudielka <klaus.kudielka@gmail.com>
net: mvneta: fix txq_map in case of txq_number==1
Kumar Kartikeya Dwivedi <memxor@gmail.com>
bpf: Fix max stack depth check for async callbacks
Randy Dunlap <rdunlap@infradead.org>
scsi: ufs: ufs-mediatek: Add dependency for RESET_CONTROLLER
Dan Carpenter <dan.carpenter@linaro.org>
scsi: qla2xxx: Fix error code in qla2x00_start_sp()
Eric Biggers <ebiggers@google.com>
blk-crypto: use dynamic lock class for blk_crypto_profile::lock
Aravindhan Gunasekaran <aravindhan.gunasekaran@intel.com>
igc: Handle PPS start time programming for past time values
Prasad Koya <prasad@arista.com>
igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
Vlad Buslov <vladbu@nvidia.com>
net/mlx5e: Check for NOT_READY flag state after locking
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix memory leak in mlx5e_ptp_open
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix memory leak in mlx5e_fs_tt_redirect_any_create
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix double free in mlx5e_destroy_flow_table
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Remove delay during TX ring configuration
Sridhar Samudrala <sridhar.samudrala@intel.com>
ice: Fix max_rate check while configuring TX rate limits
Marek Vasut <marex@denx.de>
drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
Petr Tesarik <petr.tesarik.ext@huawei.com>
swiotlb: reduce the number of areas to match actual memory pool size
Alexey Kardashevskiy <aik@amd.com>
swiotlb: reduce the swiotlb buffer size on allocation failure
Petr Tesarik <petr.tesarik.ext@huawei.com>
swiotlb: always set the number of areas before allocating the pool
Douglas Anderson <dianders@chromium.org>
drm/bridge: ti-sn65dsi86: Fix auxiliary bus lifetime
Fabio Estevam <festevam@denx.de>
drm/panel: simple: Add connector_type for innolux_at043tn24
Namjae Jeon <linkinjeon@kernel.org>
ksmbd: fix out of bounds read in smb2_sess_setup
Namjae Jeon <linkinjeon@kernel.org>
ksmbd: add missing compound request handing in some commands
Linus Torvalds <torvalds@linux-foundation.org>
workqueue: clean up WORK_* constant types, clarify masking
Moritz Fischer <moritzf@google.com>
net: lan743x: Don't sleep in atomic context
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Fix for shift-out-of-bounds
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Rename the float32 variable
Ivan Mikhaylov <fr0st61te@gmail.com>
net/ncsi: change from ndo_set_mac_address to dev_set_mac_address
-------------
Diffstat:
.../admin-guide/device-mapper/dm-init.rst | 8 +
Makefile | 4 +-
arch/mips/include/asm/kvm_host.h | 6 +-
arch/mips/kernel/cpu-probe.c | 9 +-
arch/mips/kvm/emulate.c | 22 +-
arch/mips/kvm/mips.c | 16 +-
arch/mips/kvm/stats.c | 4 +-
arch/mips/kvm/trace.h | 8 +-
arch/mips/kvm/vz.c | 20 +-
arch/powerpc/Makefile | 8 +
arch/powerpc/kernel/security.c | 37 +--
arch/powerpc/mm/book3s64/hash_native.c | 13 +-
arch/riscv/mm/init.c | 2 +-
arch/riscv/net/bpf_jit.h | 6 +-
arch/riscv/net/bpf_jit_core.c | 19 +-
arch/s390/Makefile | 1 +
arch/x86/events/intel/core.c | 7 +
arch/xtensa/platforms/iss/network.c | 2 +-
block/blk-crypto-profile.c | 12 +-
drivers/base/regmap/regmap-irq.c | 2 +-
drivers/bus/intel-ixp4xx-eb.c | 2 +-
drivers/char/hw_random/imx-rngc.c | 6 +-
drivers/char/tpm/tpm-chip.c | 7 +
drivers/char/tpm/tpm_crb.c | 19 +-
drivers/char/tpm/tpm_tis_i2c.c | 59 +++--
drivers/char/tpm/tpm_vtpm_proxy.c | 30 +--
drivers/firmware/stratix10-svc.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 12 +
drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c | 11 +-
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 26 +++
drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +
.../drm/amd/display/dc/dce112/dce112_resource.c | 10 +-
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 11 +
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 4 -
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 2 +-
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h | 1 +
drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 +-
drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 +
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 4 +
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 98 ++++++++
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 34 +--
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 34 +--
drivers/gpu/drm/bridge/ti-sn65dsi86.c | 35 +--
drivers/gpu/drm/drm_atomic_helper.c | 11 +-
drivers/gpu/drm/drm_client.c | 21 ++
drivers/gpu/drm/drm_fb_helper.c | 4 -
drivers/gpu/drm/i915/display/intel_display.c | 1 -
drivers/gpu/drm/i915/gt/intel_gtt.c | 2 +-
drivers/gpu/drm/panel/panel-simple.c | 2 +
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 +-
drivers/gpu/drm/ttm/ttm_bo.c | 7 +
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c | 30 ++-
drivers/iio/adc/meson_saradc.c | 2 +-
drivers/md/dm-init.c | 22 +-
drivers/md/dm-integrity.c | 4 +-
drivers/md/dm-verity-loadpin.c | 3 +
drivers/md/raid0.c | 62 ++++-
drivers/md/raid0.h | 1 +
drivers/mfd/qcom-pm8008.c | 1 +
drivers/misc/fastrpc.c | 2 +-
drivers/misc/pci_endpoint_test.c | 10 +-
drivers/mtd/nand/raw/meson_nand.c | 4 +
drivers/net/dsa/qca/qca8k-8xxx.c | 3 +
drivers/net/ethernet/amazon/ena/ena_com.c | 3 +
drivers/net/ethernet/broadcom/bgmac.c | 4 +-
drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +
drivers/net/ethernet/google/gve/gve_ethtool.c | 3 +
drivers/net/ethernet/intel/ice/ice_main.c | 16 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 2 +
drivers/net/ethernet/intel/igc/igc_main.c | 5 +-
drivers/net/ethernet/intel/igc/igc_ptp.c | 25 +-
drivers/net/ethernet/marvell/mvneta.c | 4 +-
drivers/net/ethernet/marvell/octeontx2/af/ptp.c | 19 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 2 +-
.../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 11 +-
.../ethernet/marvell/octeontx2/af/rvu_npc_hash.c | 23 +-
.../ethernet/marvell/octeontx2/nic/otx2_flows.c | 8 +
.../net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 15 ++
.../mellanox/mlx5/core/en/fs_tt_redirect.c | 6 +-
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c | 6 +-
.../ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +-
drivers/net/ethernet/microchip/lan743x_main.c | 21 +-
drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5 -
drivers/net/netdevsim/dev.c | 9 +-
drivers/net/phy/dp83td510.c | 23 +-
drivers/net/wireless/cisco/airo.c | 5 +-
drivers/net/wireless/realtek/rtw89/debug.c | 5 +-
drivers/ntb/hw/amd/ntb_hw_amd.c | 7 +-
drivers/ntb/hw/idt/ntb_hw_idt.c | 7 +-
drivers/ntb/hw/intel/ntb_hw_gen1.c | 7 +-
drivers/ntb/ntb_transport.c | 2 +-
drivers/ntb/test/ntb_tool.c | 2 +
drivers/nvme/host/core.c | 36 ++-
drivers/nvme/host/pci.c | 2 +-
drivers/opp/core.c | 3 +
drivers/pci/controller/dwc/pcie-qcom.c | 2 +
drivers/pci/controller/pcie-rockchip-ep.c | 65 ++----
drivers/pci/controller/pcie-rockchip.c | 17 ++
drivers/pci/controller/pcie-rockchip.h | 11 +-
drivers/pci/endpoint/functions/pci-epf-test.c | 40 +++-
drivers/pci/hotplug/acpiphp_glue.c | 5 +-
drivers/pci/pci.c | 10 +-
drivers/pci/probe.c | 4 +-
drivers/pci/quirks.c | 2 +
drivers/perf/riscv_pmu.c | 3 -
drivers/pinctrl/pinctrl-amd.c | 190 +++++++--------
drivers/pinctrl/pinctrl-amd.h | 3 +-
drivers/platform/x86/wmi.c | 22 +-
drivers/pwm/pwm-meson.c | 28 +--
drivers/s390/crypto/zcrypt_msgtype6.c | 6 +
drivers/scsi/lpfc/lpfc_crtn.h | 1 -
drivers/scsi/lpfc/lpfc_els.c | 30 +--
drivers/scsi/lpfc/lpfc_hbadisc.c | 24 +-
drivers/scsi/mpi3mr/mpi3mr_fw.c | 5 +
drivers/scsi/qla2xxx/qla_attr.c | 13 ++
drivers/scsi/qla2xxx/qla_bsg.c | 6 +
drivers/scsi/qla2xxx/qla_def.h | 22 +-
drivers/scsi/qla2xxx/qla_edif.c | 4 +-
drivers/scsi/qla2xxx/qla_gbl.h | 2 +-
drivers/scsi/qla2xxx/qla_init.c | 258 +++++++++++++++++++--
drivers/scsi/qla2xxx/qla_inline.h | 5 +-
drivers/scsi/qla2xxx/qla_iocb.c | 38 ++-
drivers/scsi/qla2xxx/qla_isr.c | 64 ++++-
drivers/scsi/qla2xxx/qla_nvme.c | 3 -
drivers/scsi/qla2xxx/qla_os.c | 133 ++++++-----
drivers/soc/qcom/mdt_loader.c | 16 +-
drivers/soundwire/qcom.c | 3 +-
drivers/tty/serial/8250/8250.h | 1 -
drivers/tty/serial/8250/8250_pci.c | 19 --
drivers/tty/serial/8250/8250_port.c | 11 +-
drivers/tty/serial/atmel_serial.c | 4 +-
drivers/tty/serial/imx.c | 18 +-
drivers/tty/serial/samsung_tty.c | 14 +-
drivers/ufs/host/Kconfig | 1 +
drivers/usb/host/xhci-mem.c | 39 +++-
drivers/usb/host/xhci-pci.c | 12 +
drivers/usb/host/xhci.h | 2 +
fs/ceph/addr.c | 85 +++++--
fs/ceph/caps.c | 9 +
fs/ceph/super.h | 13 ++
fs/dlm/lockspace.c | 12 -
fs/dlm/lockspace.h | 1 -
fs/dlm/midcomms.c | 3 -
fs/dlm/plock.c | 115 +++++----
fs/erofs/inode.c | 3 +-
fs/erofs/zdata.c | 4 +-
fs/ext2/inode.c | 5 +-
fs/ext4/indirect.c | 8 +
fs/ext4/inode.c | 10 -
fs/ext4/ioctl.c | 5 +-
fs/ext4/mballoc.c | 17 +-
fs/ext4/super.c | 19 +-
fs/f2fs/compress.c | 2 +-
fs/f2fs/dir.c | 9 +-
fs/f2fs/xattr.c | 6 +-
fs/jfs/jfs_dmap.c | 6 +
fs/jfs/jfs_filsys.h | 2 +
fs/ntfs3/index.c | 84 ++++++-
fs/ntfs3/inode.c | 18 +-
fs/ntfs3/ntfs_fs.h | 4 +-
fs/ntfs3/run.c | 7 +-
fs/ntfs3/xattr.c | 109 ++++++---
fs/overlayfs/inode.c | 12 +-
fs/overlayfs/overlayfs.h | 2 +-
fs/overlayfs/util.c | 7 +-
fs/smb/client/file.c | 4 +-
fs/smb/client/smb2transport.c | 7 +
fs/smb/server/smb2pdu.c | 109 +++++----
include/linux/blk-crypto-profile.h | 1 +
include/linux/nvme.h | 2 +-
include/linux/rethook.h | 1 +
include/linux/serial_8250.h | 1 -
include/linux/workqueue.h | 15 +-
include/net/pkt_sched.h | 2 +-
kernel/bpf/cpumap.c | 40 ++--
kernel/bpf/verifier.c | 5 +-
kernel/dma/swiotlb.c | 110 ++++++---
kernel/power/qos.c | 9 +-
kernel/trace/fprobe.c | 11 +-
kernel/trace/ftrace.c | 45 ++--
kernel/trace/rethook.c | 13 ++
kernel/trace/ring_buffer.c | 24 +-
kernel/trace/trace.c | 3 +-
kernel/trace/trace_eprobe.c | 18 +-
kernel/trace/trace_events_hist.c | 8 +-
kernel/trace/trace_events_user.c | 6 +-
kernel/trace/trace_probe_tmpl.h | 14 +-
kernel/workqueue.c | 13 +-
mm/kasan/kasan.h | 3 +
net/ceph/messenger_v2.c | 41 ++--
net/core/skbuff.c | 5 +
net/ipv6/addrconf.c | 3 +-
net/ipv6/icmp.c | 5 +-
net/ipv6/udp.c | 2 +-
net/ncsi/ncsi-rsp.c | 5 +-
net/sched/cls_flower.c | 10 +
net/sched/cls_fw.c | 10 +-
net/sched/sch_qfq.c | 41 ++--
samples/ftrace/ftrace-direct-too.c | 14 +-
tools/testing/selftests/net/mptcp/config | 1 +
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 3 +
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh | 9 +-
tools/testing/selftests/net/mptcp/pm_nl_ctl.c | 10 +-
tools/testing/selftests/net/mptcp/userspace_pm.sh | 4 +-
208 files changed, 2314 insertions(+), 1175 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.15 410/532] net: bgmac: postpone turning IRQs off to avoid SoC hangs
2023-07-21 15:58 1% [PATCH 5.15 000/532] 5.15.121-rc1 review Greg Kroah-Hartman
2023-07-21 15:59 5% ` [PATCH 5.15 066/532] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
@ 2023-07-21 16:05 7% ` Greg Kroah-Hartman
1 sibling, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-21 16:05 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rafał Miłecki,
Michal Kubiak, David S. Miller, Sasha Levin
From: Rafał Miłecki <rafal@milecki.pl>
[ Upstream commit e7731194fdf085f46d58b1adccfddbd0dfee4873 ]
Turning IRQs off is done by accessing Ethernet controller registers.
That can't be done until device's clock is enabled. It results in a SoC
hang otherwise.
This bug remained unnoticed for years as most bootloaders keep all
Ethernet interfaces turned on. It seems to only affect a niche SoC
family BCM47189. It has two Ethernet controllers but CFE bootloader uses
only the first one.
Fixes: 34322615cbaa ("net: bgmac: Mask interrupts during probe")
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Reviewed-by: Michal Kubiak <michal.kubiak@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/broadcom/bgmac.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index f8fd65ab663ee..54ff28c9b2148 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1492,8 +1492,6 @@ int bgmac_enet_probe(struct bgmac *bgmac)
bgmac->in_init = true;
- bgmac_chip_intrs_off(bgmac);
-
net_dev->irq = bgmac->irq;
SET_NETDEV_DEV(net_dev, bgmac->dev);
dev_set_drvdata(bgmac->dev, bgmac);
@@ -1511,6 +1509,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)
*/
bgmac_clk_enable(bgmac, 0);
+ bgmac_chip_intrs_off(bgmac);
+
/* This seems to be fixing IRQ by assigning OOB #6 to the core */
if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) {
if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
--
2.39.2
^ permalink raw reply related [relevance 7%]
* [PATCH 5.15 066/532] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
2023-07-21 15:58 1% [PATCH 5.15 000/532] 5.15.121-rc1 review Greg Kroah-Hartman
@ 2023-07-21 15:59 5% ` Greg Kroah-Hartman
2023-07-21 16:05 7% ` [PATCH 5.15 410/532] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
1 sibling, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-21 15:59 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Remi Pommarel, Nicolas Escande,
Toke Høiland-Jørgensen, Kalle Valo, Sasha Levin
From: Remi Pommarel <repk@triplefau.lt>
[ Upstream commit 75086cc6dee046e3fbb3dba148b376d8802f83bc ]
On EDMA capable hardware, ath9k_txq_list_has_key() can enter infinite
loop if it is called while all txq_fifos have packets that use different
key that the one we are looking for. Fix it by exiting the loop if all
txq_fifos have been checked already.
Because this loop is called under spin_lock_bh() (see ath_txq_lock) it
causes the following rcu stall:
rcu: INFO: rcu_sched self-detected stall on CPU
ath10k_pci 0000:01:00.0: failed to read temperature -11
rcu: 1-....: (5254 ticks this GP) idle=189/1/0x4000000000000002 softirq=8442983/8442984 fqs=2579
(t=5257 jiffies g=17983297 q=334)
Task dump for CPU 1:
task:hostapd state:R running task stack: 0 pid: 297 ppid: 289 flags:0x0000000a
Call trace:
dump_backtrace+0x0/0x170
show_stack+0x1c/0x24
sched_show_task+0x140/0x170
dump_cpu_task+0x48/0x54
rcu_dump_cpu_stacks+0xf0/0x134
rcu_sched_clock_irq+0x8d8/0x9fc
update_process_times+0xa0/0xec
tick_sched_timer+0x5c/0xd0
__hrtimer_run_queues+0x154/0x320
hrtimer_interrupt+0x120/0x2f0
arch_timer_handler_virt+0x38/0x44
handle_percpu_devid_irq+0x9c/0x1e0
handle_domain_irq+0x64/0x90
gic_handle_irq+0x78/0xb0
call_on_irq_stack+0x28/0x38
do_interrupt_handler+0x54/0x5c
el1_interrupt+0x2c/0x4c
el1h_64_irq_handler+0x14/0x1c
el1h_64_irq+0x74/0x78
ath9k_txq_has_key+0x1bc/0x250 [ath9k]
ath9k_set_key+0x1cc/0x3dc [ath9k]
drv_set_key+0x78/0x170
ieee80211_key_replace+0x564/0x6cc
ieee80211_key_link+0x174/0x220
ieee80211_add_key+0x11c/0x300
nl80211_new_key+0x12c/0x330
genl_family_rcv_msg_doit+0xbc/0x11c
genl_rcv_msg+0xd8/0x1c4
netlink_rcv_skb+0x40/0x100
genl_rcv+0x3c/0x50
netlink_unicast+0x1ec/0x2c0
netlink_sendmsg+0x198/0x3c0
____sys_sendmsg+0x210/0x250
___sys_sendmsg+0x78/0xc4
__sys_sendmsg+0x4c/0x90
__arm64_sys_sendmsg+0x28/0x30
invoke_syscall.constprop.0+0x60/0x100
do_el0_svc+0x48/0xd0
el0_svc+0x14/0x50
el0t_64_sync_handler+0xa8/0xb0
el0t_64_sync+0x158/0x15c
This rcu stall is hard to reproduce as is, but changing ATH_TXFIFO_DEPTH
from 8 to 2 makes it reasonably easy to reproduce.
Fixes: ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
Tested-by: Nicolas Escande <nico.escande@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230609093744.1985-1-repk@triplefau.lt
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath9k/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e2791d45f5f59..98868f60a8c2f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 5.15 000/532] 5.15.121-rc1 review
@ 2023-07-21 15:58 1% Greg Kroah-Hartman
2023-07-21 15:59 5% ` [PATCH 5.15 066/532] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-07-21 16:05 7% ` [PATCH 5.15 410/532] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
0 siblings, 2 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-21 15:58 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, srw, rwarsow, conor
This is the start of the stable review cycle for the 5.15.121 release.
There are 532 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Sun, 23 Jul 2023 16:04:40 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.121-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.15.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.15.121-rc1
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: reintroduce lmax bound check for MTU
Thomas Bogendoerfer <tsbogend@alpha.franken.de>
MIPS: kvm: Fix build error with KVM_MIPS_DEBUG_COP0_COUNTERS enabled
Manish Rangankar <mrangankar@marvell.com>
scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
Shreyas Deodhar <sdeodhar@marvell.com>
scsi: qla2xxx: Pointer may be dereferenced
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Correct the index of array
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Fix potential NULL pointer dereference
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix buffer overrun
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Avoid fcport pointer dereference
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Array index may go out of bound
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Wait for io return on terminate rport
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix to update dynamic data counter if fetcharg uses it
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix not to count error code to total length
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: depend on SYN_COOKIES
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: sockopt: return error if wrong mark
Mateusz Stachyra <m.stachyra@samsung.com>
tracing: Fix null pointer dereference in tracing_err_log_open()
Max Filippov <jcmvbkbc@gmail.com>
xtensa: ISS: fix call to split_if_spec
Zheng Yejian <zhengyejian1@huawei.com>
ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
Zheng Yejian <zhengyejian1@huawei.com>
ring-buffer: Fix deadloop issue on reading trace_pipe
Krister Johansen <kjlx@templeofstupid.com>
net: ena: fix shift-out-of-bounds in exponential backoff
Florent Revest <revest@chromium.org>
samples: ftrace: Save required argument registers in sample trampolines
Zheng Yejian <zhengyejian1@huawei.com>
tracing: Fix memory leak of iter->temp when reading trace_pipe
Mohamed Khalfella <mkhalfella@purestorage.com>
tracing/histograms: Add histograms to hist_vars if they have referenced variables
Heiko Carstens <hca@linux.ibm.com>
s390/decompressor: fix misaligned symbol build error
Jonas Gorski <jonas.gorski@gmail.com>
bus: ixp4xx: fix IXP4XX_EXP_T1_MASK
Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Revert "8250: add support for ASIX devices with a FIFO bug"
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
soundwire: qcom: fix storing port config out-of-bounds
Stephan Gerhold <stephan.gerhold@kernkonzept.com>
opp: Fix use-after-free in lazy_opp_tables after probe deferral
George Stark <gnstark@sberdevices.ru>
meson saradc: fix clock divider mask length
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Show ZHAOXIN xHCI root hub speed correctly
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix resume issue of some ZHAOXIN hosts
Xiubo Li <xiubli@redhat.com>
ceph: don't let check_caps skip sending responses for revoke msgs
Ilya Dryomov <idryomov@gmail.com>
libceph: harden msgr2.1 frame segment length checks
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
Martin Fuzzey <martin.fuzzey@flowbird.group>
tty: serial: imx: fix rs485 rx after tx
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
Dan Carpenter <dan.carpenter@linaro.org>
serial: atmel: don't enable IRQs prematurely
Christian König <christian.koenig@amd.com>
drm/ttm: never consider pinned BOs for eviction&swap
Thomas Hellström <thomas.hellstrom@linux.intel.com>
drm/ttm: Don't leak a resource on swapout move error
gaba <gaba@amd.com>
drm/amdgpu: avoid restore process run into dead loop.
Mario Limonciello <mario.limonciello@amd.com>
drm/amd/display: Correct `DMUB_FW_VERSION` macro
Samuel Pitoiset <samuel.pitoiset@gmail.com>
drm/amdgpu: fix clearing mappings for BOs that are always valid in VM
Brian Norris <briannorris@chromium.org>
drm/rockchip: vop: Leave vblank enabled in self-refresh
Brian Norris <briannorris@chromium.org>
drm/atomic: Allow vblank-enabled + self-refresh "disable"
Alexander Aring <aahringo@redhat.com>
fs: dlm: return positive pid value for F_GETLK
Peter Korsgaard <peter@korsgaard.com>
dm init: add dm-mod.waitfor to wait for asynchronously probed block devices
Jason Baron <jbaron@akamai.com>
md/raid0: add discard support for the 'original' layout
Johan Hovold <johan+linaro@kernel.org>
mfd: pm8008: Fix module autoloading
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Re-init completion for every test
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Free IRQs before removing the device
Damien Le Moal <dlemoal@kernel.org>
PCI: rockchip: Set address alignment for endpoint mode
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Use u32 variable to access 32-bit registers
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Write PCI Device ID to correct register
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Assert PCI Configuration Enable bit after probe
Manivannan Sadhasivam <mani@kernel.org>
PCI: qcom: Disable write access to read only registers for IP v2.3.3
Igor Mammedov <imammedo@redhat.com>
PCI: acpiphp: Reassign resources on bridge if necessary
Robin Murphy <robin.murphy@arm.com>
PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
Ondrej Zary <linux@zary.sk>
PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
Mikulas Patocka <mpatocka@redhat.com>
dm integrity: reduce vmalloc space footprint on 32-bit architectures
Martin Kaiser <martin@kaiser.cx>
hwrng: imx-rngc - fix the timeout for init and self check
Siddh Raman Pant <code@siddh.me>
jfs: jfs_dmap: Validate db_l2nbperpage while mounting
Baokun Li <libaokun1@huawei.com>
ext4: only update i_reserved_data_blocks on successful block allocation
Baokun Li <libaokun1@huawei.com>
ext4: turn quotas off if mount failed after enabling quotas
Chao Yu <chao@kernel.org>
ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_new_blocks
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: get block from bh in ext4_free_blocks for fast commit replay
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_clear_bb
Zhihao Cheng <chengzhihao1@huawei.com>
ext4: Fix reusing stale buffer heads from last failed mounting
Huacai Chen <chenhuacai@kernel.org>
MIPS: KVM: Fix NULL pointer dereference
Huacai Chen <chenhuacai@kernel.org>
MIPS: Loongson: Fix cpu_probe_loongson() again
Gao Xiang <hsiangkao@linux.alibaba.com>
erofs: fix compact 4B support for 16k block size
Suzuki K Poulose <suzuki.poulose@arm.com>
arm64: errata: Add detection for TRBE overwrite in FILL mode
Michael Ellerman <mpe@ellerman.id.au>
powerpc/security: Fix Speculation_Store_Bypass reporting on Power10
Ekansh Gupta <quic_ekangupt@quicinc.com>
misc: fastrpc: Create fastrpc scalar with correct buffer count
Naveen N Rao <naveen@kernel.org>
powerpc: Fail build if using recordmcount with binutils v2.37
Ryan Roberts <ryan.roberts@arm.com>
mm/damon/ops-common: atomically test and clear young on ptes and pmds
Florian Fainelli <florian.fainelli@broadcom.com>
net: bcmgenet: Ensure MDIO unregistration has clocks enabled
Arseniy Krasnov <AVKrasnov@sberdevices.ru>
mtd: rawnand: meson: fix unaligned DMA buffers handling
Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Only use special debounce behavior for GPIO 0
Kornel Dulęba <korneld@chromium.org>
pinctrl: amd: Detect and mask spurious interrupts
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Detect internal GPIO0 debounce handling
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Fix mistake in handling clearing pins at startup
Chao Yu <chao@kernel.org>
f2fs: fix to avoid NULL pointer dereference f2fs_write_end_io()
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Check fields while reading
Ming Lei <ming.lei@redhat.com>
nvme-pci: fix DMA direction of unmapping integrity data
Keith Busch <kbusch@kernel.org>
nvme-pci: remove nvme_queue from nvme_iod
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: account for stab overhead in qfq_enqueue
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: refactor parsing of netlink parameters
Pedro Tammela <pctammela@mojatatu.com>
net/sched: make psched_mtu() RTNL-less safe
Dan Carpenter <dan.carpenter@linaro.org>
netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
Jisheng Zhang <jszhang@kernel.org>
riscv: mm: fix truncation warning on RV32
Ido Schimmel <idosch@nvidia.com>
net/sched: flower: Ensure both minimum and maximum ports are specified
Pu Lehui <pulehui@huawei.com>
bpf: cpumap: Fix memory leak in cpu_map_update_elem
Randy Dunlap <rdunlap@infradead.org>
wifi: airo: avoid uninitialized warning in airo_get_rate()
Xin Yin <yinxin.x@bytedance.com>
erofs: fix fsdax unavailability for chunk-based regular files
Gao Xiang <hsiangkao@linux.alibaba.com>
erofs: decouple basic mount options from fs_context
Chunhai Guo <guochunhai@vivo.com>
erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
Suman Ghosh <sumang@marvell.com>
octeontx2-pf: Add additional check for MCAM rules
Tvrtko Ursulin <tvrtko.ursulin@intel.com>
drm/i915: Fix one wrong caching mode enum usage
Björn Töpel <bjorn@rivosinc.com>
riscv, bpf: Fix inconsistent JIT image generation
Pu Lehui <pulehui@huawei.com>
bpf, riscv: Support riscv jit to provide bpf_line_info
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix inserting of empty frame for launchtime
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix launchtime before start of cycle
Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
kernel/trace: Fix cleanup logic of enable_trace_eprobe
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
platform/x86: wmi: Break possible infinite loop when parsing GUID
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: move variables
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: use guid_t and guid_equal()
Barnabás Pőcze <pobrn@protonmail.com>
platform/x86: wmi: remove unnecessary argument
Ziyang Xuan <william.xuanziyang@huawei.com>
ipv6/addrconf: fix a potential refcount underflow for idev
Jiasheng Jiang <jiasheng@iscas.ac.cn>
NTB: ntb_tool: Add check for devm_kcalloc
Yang Yingliang <yangyingliang@huawei.com>
NTB: ntb_transport: fix possible memory leak while device_register() fails
Yuan Can <yuancan@huawei.com>
ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
ntb: idt: Fix error handling in idt_pci_driver_init()
Eric Dumazet <edumazet@google.com>
udp6: fix udp6_ehashfn() typo
Kuniyuki Iwashima <kuniyu@amazon.com>
icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
Paolo Abeni <pabeni@redhat.com>
net: prevent skb corruption on frag list segmentation
Rafał Miłecki <rafal@milecki.pl>
net: bgmac: postpone turning IRQs off to avoid SoC hangs
Nitya Sunkad <nitya.sunkad@amd.com>
ionic: remove WARN_ON to prevent panic_on_warn
Junfeng Guo <junfeng.guo@intel.com>
gve: Set default duplex configuration to full
M A Ramdhan <ramdhan@starlabs.sg>
net/sched: cls_fw: Fix improper refcount update leads to use-after-free
Klaus Kudielka <klaus.kudielka@gmail.com>
net: mvneta: fix txq_map in case of txq_number==1
Kumar Kartikeya Dwivedi <memxor@gmail.com>
bpf: Fix max stack depth check for async callbacks
Dan Carpenter <dan.carpenter@linaro.org>
scsi: qla2xxx: Fix error code in qla2x00_start_sp()
Aravindhan Gunasekaran <aravindhan.gunasekaran@intel.com>
igc: Handle PPS start time programming for past time values
Prasad Koya <prasad@arista.com>
igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
Vlad Buslov <vladbu@nvidia.com>
net/mlx5e: Check for NOT_READY flag state after locking
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix memory leak in mlx5e_ptp_open
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix double free in mlx5e_destroy_flow_table
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Remove delay during TX ring configuration
Marek Vasut <marex@denx.de>
drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
Douglas Anderson <dianders@chromium.org>
drm/bridge: ti-sn65dsi86: Fix auxiliary bus lifetime
Fabio Estevam <festevam@denx.de>
drm/panel: simple: Add connector_type for innolux_at043tn24
Namjae Jeon <linkinjeon@kernel.org>
ksmbd: validate session id and tree id in the compound request
Namjae Jeon <linkinjeon@kernel.org>
ksmbd: fix out-of-bound read in smb2_write
Namjae Jeon <linkinjeon@kernel.org>
ksmbd: validate command payload size
Ralph Boehme <slow@samba.org>
ksmbd: use ksmbd_req_buf_next() in ksmbd_smb2_check_message()
Linus Torvalds <torvalds@linux-foundation.org>
workqueue: clean up WORK_* constant types, clarify masking
Moritz Fischer <moritzf@google.com>
net: lan743x: Don't sleep in atomic context
Jens Axboe <axboe@kernel.dk>
io_uring: add reschedule point to handle_tw_list()
Andres Freund <andres@anarazel.de>
io_uring: Use io_schedule* in cqring wait
Michael Schmitz <schmitzmic@gmail.com>
block/partition: fix signedness issue for Amiga partitions
Sherry Sun <sherry.sun@nxp.com>
tty: serial: fsl_lpuart: add earlycon for imx8ulp platform
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: netlink: send staged packets when setting initial private key
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: use saner cpu selection wrapping
Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
netfilter: nf_tables: do not ignore genmask when looking up chain by id
Florent Revest <revest@chromium.org>
netfilter: conntrack: Avoid nf_ct_helper_hash uses after free
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: unbind non-anonymous set if rule construction fails
Amir Goldstein <amir73il@gmail.com>
fanotify: disallow mount/sb marks on kernel internal pseudo fs
Zhihao Cheng <chengzhihao1@huawei.com>
ovl: fix null pointer dereference in ovl_get_acl_rcu()
Jan Kara <jack@suse.cz>
fs: no need to check source
Christian Marangi <ansuelsmth@gmail.com>
leds: trigger: netdev: Recheck NETDEV_LED_MODE_LINKUP on dev rename
Arnd Bergmann <arnd@arndb.de>
ARM: orion5x: fix d2net gpio initialization
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: qcom: ipq4019: fix broken NAND controller properties override
Ricardo Ribalda Delgado <ribalda@chromium.org>
ASoC: mediatek: mt8173: Fix snd_soc_component_initialize error path
Ricardo Ribalda Delgado <ribalda@chromium.org>
ASoC: mediatek: mt8173: Fix irq error path
Filipe Manana <fdmanana@suse.com>
btrfs: do not BUG_ON() on tree mod log failure at __btrfs_cow_block()
Filipe Manana <fdmanana@suse.com>
btrfs: fix extent buffer leak after tree mod log failure at split_node()
Filipe Manana <fdmanana@suse.com>
btrfs: fix race when deleting quota root from the dirty cow roots list
Naohiro Aota <naota@elisp.net>
btrfs: reinsert BGs failed to reclaim
Naohiro Aota <naota@elisp.net>
btrfs: bail out reclaim process if filesystem is read-only
Naohiro Aota <naota@elisp.net>
btrfs: delete unused BGs while reclaiming BGs
Matt Corallo <blnxfsl@bluematt.me>
btrfs: add handling for RAID1C23/DUP to btrfs_reduce_alloc_profile
Thomas Weißschuh <linux@weissschuh.net>
fs: avoid empty option when generating legacy mount string
Fabian Frederick <fabf@skynet.be>
jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
Abhijeet Rastogi <abhijeet.1989@gmail.com>
ipvs: increase ip_vs_conn_tab_bits range for 64BIT
Jan Kara <jack@suse.cz>
fs: Lock moved directories
Jan Kara <jack@suse.cz>
fs: Establish locking order for unrelated directories
Jan Kara <jack@suse.cz>
Revert "f2fs: fix potential corruption when moving a directory"
Jan Kara <jack@suse.cz>
ext4: Remove ext4 locking of moved directory
Roberto Sassu <roberto.sassu@huawei.com>
shmem: use ramfs_kill_sb() for kill_sb method of ramfs-based tmpfs
Arnd Bergmann <arnd@arndb.de>
autofs: use flexible array in ioctl structure
Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
integrity: Fix possible multiple allocation in integrity_inode_get()
Kees Cook <keescook@chromium.org>
um: Use HOST_DIR for mrproper
Zheng Wang <zyytlz.wz@163.com>
bcache: Fix __bch_btree_node_alloc to make the failure behavior consistent
Zheng Wang <zyytlz.wz@163.com>
bcache: Remove unnecessary NULL point check in node allocations
Mingzhe Zou <mingzhe.zou@easystack.cn>
bcache: fixup btree_cache_wait list damage
Chevron Li <chevron.li@bayhubtech.com>
mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is used.
Ulf Hansson <ulf.hansson@linaro.org>
mmc: mmci: Set PROBE_PREFER_ASYNCHRONOUS
Robert Marko <robimarko@gmail.com>
mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
Robert Marko <robimarko@gmail.com>
mmc: core: disable TRIM on Kingston EMMC04G-M627
Jens Axboe <axboe@kernel.dk>
io_uring: wait interruptibly for request completions on exit
Dai Ngo <dai.ngo@oracle.com>
NFSD: add encoding of op_recall flag for write delegation
Shuai Jiang <d202180596@hust.edu.cn>
i2c: qup: Add missing unwind goto in qup_i2c_probe()
Filipe Manana <fdmanana@suse.com>
btrfs: do not BUG_ON() on tree mod log failure at balance_level()
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
extcon: usbc-tusb320: Convert to i2c's .probe_new()
Robert Hancock <robert.hancock@calian.com>
i2c: xiic: Don't try to handle more interrupt events after error
Marek Vasut <marex@denx.de>
i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()
Danila Chernetsov <listdansp@mail.ru>
apparmor: fix missing error check for rhashtable_insert_fast
Artur Rojek <contact@artur-rojek.eu>
sh: dma: Fix DMA channel offset calculation
Thorsten Winkler <twinkler@linux.ibm.com>
s390/qeth: Fix vipa deletion
Hariprasad Kelam <hkelam@marvell.com>
octeontx-af: fix hardware timestamp configuration
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: tag_sja1105: fix MAC DA patching from meta frames
Guillaume Nault <gnault@redhat.com>
pptp: Fix fib lookup calls.
Woody Zhang <woodylab@foxmail.com>
riscv: move memblock_allow_resize() after linear mapping is ready
Lin Ma <linma@zju.edu.cn>
net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
Ilya Maximets <i.maximets@ovn.org>
xsk: Honor SO_BINDTODEVICE on bind
Eric Dumazet <edumazet@google.com>
tcp: annotate data races in __tcp_oow_rate_limited()
Vladimir Oltean <vladimir.oltean@nxp.com>
net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode
Randy Dunlap <rdunlap@infradead.org>
powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y
Zeng Heng <zengheng4@huawei.com>
ntfs: Fix panic about slab-out-of-bounds caused by ntfs_listxattr()
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-af: Add validation before accessing cgx and lmac
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-af: Fix mapping for NIX block from CGX connection
Chao Yu <chao@kernel.org>
f2fs: fix error path handling in truncate_dnode()
Nishanth Menon <nm@ti.com>
mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0
Jonas Gorski <jonas.gorski@gmail.com>
spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
Pawel Dembicki <paweldembicki@gmail.com>
net: dsa: vsc73xx: fix MTU configuration
Nick Child <nnac123@linux.ibm.com>
ibmvnic: Do not reset dql stats on NON_FATAL err
Tobias Heider <me@tobhe.de>
Add MODULE_FIRMWARE() for FIRMWARE_TG357766.
Florian Westphal <fw@strlen.de>
net/sched: act_ipt: add sanity checks on table name and hook locations
Chengfeng Ye <dg573847474@gmail.com>
sctp: fix potential deadlock on &net->sctp.addr_wq_lock
Randy Dunlap <rdunlap@infradead.org>
media: cec: i2c: ch7322: also select REGMAP
Jouni Högander <jouni.hogander@intel.com>
drm/i915/psr: Use hw.adjusted mode when calculating io/fast wake times
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
Li Nan <linan122@huawei.com>
md/raid10: fix the condition to call bio_end_io_acct()
Shuijing Li <shuijing.li@mediatek.com>
pwm: mtk_disp: Fix the disable flow of disp_pwm
Dan Carpenter <dan.carpenter@linaro.org>
pwm: ab8500: Fix error code in probe()
Marek Vasut <marex@denx.de>
pwm: sysfs: Do not apply state to already disabled PWMs
Fancy Fang <chen.fang@nxp.com>
pwm: imx-tpm: force 'real_period' to be zero in suspend
Claudiu Beznea <claudiu.beznea@microchip.com>
phy: tegra: xusb: check return value of devm_kzalloc()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mfd: stmpe: Only disable the regulators if they are enabled
Christian Borntraeger <borntraeger@linux.ibm.com>
KVM: s390/diag: fix racy access of physical cpu number in diag 9c handler
Pierre Morel <pmorel@linux.ibm.com>
KVM: s390: vsie: fix the length of APCB bitmap
Amelie Delaunay <amelie.delaunay@foss.st.com>
mfd: stmfx: Nullify stmfx->vdd in case of error
Amelie Delaunay <amelie.delaunay@foss.st.com>
mfd: stmfx: Fix error path in stmfx_chip_init
Phil Elwell <phil@raspberrypi.com>
nvmem: rmem: Use NVMEM_DEVID_AUTO
Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation
Tony Lindgren <tony@atomide.com>
serial: 8250_omap: Use force_suspend and resume for system suspend
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Revert "usb: common: usb-conn-gpio: Set last role to unknown before initial detection"
Jiasheng Jiang <jiasheng@iscas.ac.cn>
mfd: intel-lpss: Add missing check for platform_get_resource
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc3-meson-g12a: Fix an error handling path in dwc3_meson_g12a_probe()
Prashanth K <quic_prashk@quicinc.com>
usb: common: usb-conn-gpio: Set last role to unknown before initial detection
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc3: qcom: Fix an error handling path in dwc3_qcom_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc3: qcom: Release the correct resources in dwc3_qcom_remove()
Nico Boehr <nrb@linux.ibm.com>
KVM: s390: fix KVM_S390_GET_CMMA_BITS for GFNs in memslot holes
Dan Carpenter <dan.carpenter@linaro.org>
media: atomisp: gmin_platform: fix out_len in gmin_get_config_dsm_var()
Rikard Falkeborn <rikard.falkeborn@gmail.com>
media: venus: helpers: Fix ALIGN() of non power of two
Stephan Gerhold <stephan@gerhold.net>
mfd: rt5033: Drop rt5033-battery sub-device
James Clark <james.clark@arm.com>
coresight: Fix loss of connection info when a module is unloaded
Muchun Song <songmuchun@bytedance.com>
kernfs: fix missing kernfs_idr_lock to remove an ID from the IDR
John Ogness <john.ogness@linutronix.de>
serial: 8250: lock port for UART_IER access in omap8250_irq()
John Ogness <john.ogness@linutronix.de>
serial: 8250: lock port for stop_rx() in omap8250_irq()
Arnd Bergmann <arnd@arndb.de>
usb: hide unused usbfs_notify_suspend/resume functions
Li Yang <lidaxian@hust.edu.cn>
usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
extcon: Fix kernel doc of property capability fields to avoid warnings
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
extcon: Fix kernel doc of property fields to avoid warnings
Prashanth K <quic_prashk@quicinc.com>
usb: gadget: u_serial: Add null pointer check in gserial_suspend
Vladislav Efanov <VEfanov@ispras.ru>
usb: dwc3: qcom: Fix potential memory leak
Robert Marko <robimarko@gmail.com>
clk: qcom: ipq6018: fix networking resets
Robert Marko <robimarko@gmail.com>
clk: qcom: reset: support resetting multiple bits
Stephan Gerhold <stephan.gerhold@kernkonzept.com>
clk: qcom: reset: Allow specifying custom reset delay
Daniel Scally <dan.scally@ideasonboard.com>
media: i2c: Correct format propagation for st-mipid02
Duoming Zhou <duoming@zju.edu.cn>
media: usb: siano: Fix warning due to null work_func_t function pointer
Marek Vasut <marex@denx.de>
media: videodev2.h: Fix struct v4l2_input tuner index comment
Daniil Dulov <d.dulov@aladdin.ru>
media: usb: Check az6007_read() return value
Mantas Pucka <mantas@8devices.com>
clk: qcom: gcc-ipq6018: Use floor ops for sdcc clocks
Taniya Das <quic_tdas@quicinc.com>
clk: qcom: camcc-sc7180: Add parent dependency to all camera GDSCs
Tony Lindgren <tony@atomide.com>
serial: 8250: omap: Fix freeing of resources on failed register
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
usb: dwc2: Fix some error handling paths
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
usb: dwc2: platform: Improve error reporting for problems during .remove()
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
sh: j2: Use ioremap() to translate device tree address into kernel memory
Dan Carpenter <dan.carpenter@oracle.com>
w1: fix loop in w1_fini()
Stefan Wahren <stefan.wahren@i2se.com>
w1: w1_therm: fix locking behavior in convert_t
Ding Hui <dinghui@sangfor.com.cn>
SUNRPC: Fix UAF in svc_tcp_listen_data_ready()
Demi Marie Obenour <demi@invisiblethingslab.com>
block: increment diskseq on all media change events
Michael Schmitz <schmitzmic@gmail.com>
block: change all __u32 annotations to __be32 in affs_hardblocks.h
Michael Schmitz <schmitzmic@gmail.com>
block: add overflow checks for Amiga partition support
Michael Schmitz <schmitzmic@gmail.com>
block: fix signed int overflow in Amiga partition support
Takashi Iwai <tiwai@suse.de>
ALSA: jack: Fix mutex call in snd_jack_report()
Werner Sembach <wse@tuxedocomputers.com>
ALSA: hda/realtek: Add quirk for Clevo NPx0SNx
Sean Nyekjaer <sean@geanix.com>
iio: accel: fxls8962af: fixup buffer scan element type
Sean Nyekjaer <sean@geanix.com>
iio: accel: fxls8962af: errata bug only applicable for FXLS8962AF
Fabrizio Lamarque <fl.scratchpad@gmail.com>
iio: adc: ad7192: Fix internal/external clock selection
Fabrizio Lamarque <fl.scratchpad@gmail.com>
iio: adc: ad7192: Fix null ad7192_state pointer access
EJ Hsu <ejh@nvidia.com>
phy: tegra: xusb: Clear the driver reference in usb-phy dev
Krishna Kurapati <quic_kriskura@quicinc.com>
usb: dwc3: gadget: Propagate core init errors to UDC during pullup
Davide Tronchin <davide.tronchin.94@gmail.com>
USB: serial: option: add LARA-R6 01B PIDs
Jens Axboe <axboe@kernel.dk>
io_uring: ensure IOPOLL locks around deferred work
Liu Shixin <liushixin2@huawei.com>
bootmem: remove the vmemmap pages from kmemleak in free_bootmem_page
Kiran K <kiran.k@intel.com>
ACPI: utils: Fix acpi_evaluate_dsm_typed() redefinition error
Arnd Bergmann <arnd@arndb.de>
ksmbd: avoid field overflow warning
Ard Biesheuvel <ardb@kernel.org>
efi/libstub: Disable PCI DMA before grabbing the EFI memory map
Sami Tolvanen <samitolvanen@google.com>
kbuild: Disable GCOV for *.mod.o
Martin Kaiser <martin@kaiser.cx>
hwrng: st - keep clock enabled while hwrng is registered
Tarun Sahu <tsahu@linux.ibm.com>
dax/kmem: Pass valid argument to memory_group_register_static
Dan Williams <dan.j.williams@intel.com>
dax: Introduce alloc_dev_dax_id()
Dan Williams <dan.j.williams@intel.com>
dax: Fix dax_mapping_release() use after free
Bharath SM <bharathsm@microsoft.com>
SMB3: Do not send lease break acknowledgment if all file handles have been closed
Olga Kornievskaia <kolga@netapp.com>
NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
Hareshx Sankar Raj <hareshx.sankar.raj@intel.com>
crypto: qat - unmap buffers before free for RSA
Hareshx Sankar Raj <hareshx.sankar.raj@intel.com>
crypto: qat - unmap buffer before free for DH
Herbert Xu <herbert@gondor.apana.org.au>
crypto: qat - Use helper to set reqsize
Herbert Xu <herbert@gondor.apana.org.au>
crypto: kpp - Add helper to set reqsize
Damian Muszynski <damian.muszynski@intel.com>
crypto: qat - use reference to structure in dma_map_single()
Andre Przywara <andre.przywara@arm.com>
crypto: qat - replace get_current_node() with numa_node_id()
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - honor CRYPTO_TFM_REQ_MAY_SLEEP flag
Masahiro Yamada <masahiroy@kernel.org>
ARC: define ASM_NL and __ALIGN(_STR) outside #ifdef __ASSEMBLY__ guard
Dan Carpenter <dan.carpenter@linaro.org>
modpost: fix off by one in is_executable_section()
Arnd Bergmann <arnd@arndb.de>
crypto: marvell/cesa - Fix type mismatch warning
Masahiro Yamada <masahiroy@kernel.org>
modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24}
Masahiro Yamada <masahiroy@kernel.org>
modpost: fix section mismatch message for R_ARM_ABS32
Randy Dunlap <rdunlap@infradead.org>
crypto: nx - fix build warnings when DEBUG_FS is not enabled
Masahiro Yamada <masahiroy@kernel.org>
modpost: remove broken calculation of exception_table_entry size
Herbert Xu <herbert@gondor.apana.org.au>
hwrng: virtio - Fix race on data_avail and actual data
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - always add a pending request
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - don't waste entropy
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - don't wait on cleanup
Laurent Vivier <lvivier@redhat.com>
hwrng: virtio - add an internal buffer
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
powerpc/mm/dax: Fix the condition when checking if altmap vmemap can cross-boundary
Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
powerpc/book3s64/mm: Fix DirectMap stats in /proc/meminfo
Tiezhu Yang <yangtiezhu@loongson.cn>
riscv: uprobes: Restore thread.bad_cause
Aditya Gupta <adityag@linux.ibm.com>
powerpc: update ppc_save_regs to save current r1 in pt_regs
Nicholas Piggin <npiggin@gmail.com>
powerpc: simplify ppc_save_regs
Colin Ian King <colin.i.king@gmail.com>
powerpc/powernv/sriov: perform null check on iov before dereferencing iov
Claudiu Beznea <claudiu.beznea@microchip.com>
pinctrl: at91-pio4: check return value of devm_kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
pinctrl: microchip-sgpio: check return value of devm_kasprintf()
Nicholas Piggin <npiggin@gmail.com>
powerpc/64s: Fix VAS mm use after free
Namhyung Kim <namhyung@kernel.org>
perf dwarf-aux: Fix off-by-one in die_get_varname()
Arnaldo Carvalho de Melo <acme@redhat.com>
perf script: Fix allocation of evsel->priv related to per-event dump files
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/signal32: Force inlining of __unsafe_save_user_regs() and save_tm_user_regs_unsafe()
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/interrupt: Don't read MSR from interrupt_exit_kernel_prepare()
Christophe Leroy <christophe.leroy@csgroup.eu>
kcsan: Don't expect 64 bits atomic builtins from 32 bits architectures
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
pinctrl: cherryview: Return correct value if pin in push-pull mode
Arnaldo Carvalho de Melo <acme@redhat.com>
perf bench: Add missing setlocale() call to allow usage of %'d style formatting
Sohaib Mohamed <sohaib.amhmd@gmail.com>
perf bench: Use unbuffered output when pipe/tee'ing to a file
Sui Jingfeng <suijingfeng@loongson.cn>
PCI: Add pci_clear_master() stub for non-CONFIG_PCI
Junyan Ye <yejunyan@hust.edu.cn>
PCI: ftpci100: Release the clock resources
Rongguang Wei <weirongguang@kylinos.cn>
PCI: pciehp: Cancel bringup sequence if card is not present
Yuchen Yang <u202114568@hust.edu.cn>
scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
Ding Hui <dinghui@sangfor.com.cn>
PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
pinctrl: bcm2835: Handle gpiochip_add_pin_range() errors
Jinhong Zhu <jinhongzhu@hust.edu.cn>
scsi: qedf: Fix NULL dereference in error handling
Nirmal Patel <nirmal.patel@linux.intel.com>
PCI: vmd: Reset VMD config register between soft reboots
Siddharth Vadapalli <s-vadapalli@ti.com>
PCI: cadence: Fix Gen2 Link Retraining process
Fei Shao <fshao@chromium.org>
clk: Fix memory leak in devm_clk_notifier_register()
Claudiu Beznea <claudiu.beznea@microchip.com>
ASoC: imx-audmix: check return value of devm_kasprintf()
Amir Goldstein <amir73il@gmail.com>
ovl: update of dentry revalidate flags after copy up
Alexey Romanov <avromanov@sberdevices.ru>
drivers: meson: secure-pwrc: always enable DMA domain
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: ti: clkctrl: check return value of kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: keystone: sci-clk: check return value of kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: si5341: free unused memory on probe failure
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: si5341: check return value of {devm_}kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: si5341: return error if one synth clock registration fails
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: cdce925: check return value of kasprintf()
Claudiu Beznea <claudiu.beznea@microchip.com>
clk: vc5: check memory returned by kasprintf()
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: correct MERGE_3D length
Nícolas F. R. A. Prado <nfraprado@collabora.com>
arm64: dts: mediatek: mt8192: Fix CPUs capacity-dmips-mhz
Allen-KH Cheng <allen-kh.cheng@mediatek.com>
arm64: dts: mediatek: Add cpufreq nodes for MT8192
Bjorn Andersson <quic_bjorande@quicinc.com>
drm/msm/dp: Free resources after unregistering them
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: do not enable color-management if DSPPs are not available
Su Hui <suhui@nfschina.com>
ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer
Yuan Can <yuancan@huawei.com>
clk: tegra: tegra124-emc: Fix potential memory leak
Dan Carpenter <dan.carpenter@linaro.org>
clk: clocking-wizard: Fix Oops in clk_wzrd_register_divider()
Marijn Suijten <marijn.suijten@somainline.org>
arm64: dts: qcom: sm8250-edo: Panel framebuffer is 2.5k instead of 4k
Yuxing Liu <lyx2022@hust.edu.cn>
clk: imx: clk-imx8mp: improve error handling in imx8mp_clocks_probe()
Hao Luo <m202171776@hust.edu.cn>
clk: imx: clk-imx8mn: fix memory leak in imx8mn_clocks_probe
Kashyap Desai <kashyap.desai@broadcom.com>
RDMA/bnxt_re: Avoid calling wake_up threads from spin_lock context
Kashyap Desai <kashyap.desai@broadcom.com>
RDMA/bnxt_re: wraparound mbox producer index
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/a5xx: really check for A510 in a5xx_gpu_init
Chia-I Wu <olvaffe@gmail.com>
amdgpu: validate offset_in_bo of drm_amdgpu_gem_va
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
drm/radeon: fix possible division-by-zero errors
Aurabindo Pillai <aurabindo.pillai@amd.com>
drm/amd/display: Fix artifacting on eDP panels when engaging freesync video mode
Daniil Dulov <d.dulov@aladdin.ru>
drm/amdkfd: Fix potential deallocation of previously deallocated memory.
Christian Lamparter <chunkeey@gmail.com>
ARM: dts: BCM5301X: fix duplex-full => full-duplex
Guenter Roeck <linux@roeck-us.net>
hwmon: (pmbus/adm1275) Fix problems with temperature monitoring on ADM1272
Potin Lai <potin.lai@quantatw.com>
hwmon: (adm1275) Allow setting sample averaging
Tim Harvey <tharvey@gateworks.com>
hwmon: (gsc-hwmon) fix fan pwm temperature scaling
Olivier Moysan <olivier.moysan@foss.st.com>
ARM: dts: stm32: fix i2s endpoint format property for stm32mp15xx-dkx
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Fix audio routing on STM32MP15xx DHCOM PDK2
Keerthy <j-keerthy@ti.com>
arm64: dts: ti: k3-j7200: Fix physical address of pin
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe()
Wolfram Sang <wsa+renesas@sang-engineering.com>
arm64: dts: renesas: ulcb-kf: Remove flow control for SCIF1
Geert Uytterhoeven <geert+renesas@glider.be>
ARM: dts: iwg20d-q7-common: Fix backlight pwm specifier
Chengchang Tang <tangchengchang@huawei.com>
RDMA/hns: Fix hns_roce_table_get return value
Brendan Cunningham <bcunningham@cornelisnetworks.com>
IB/hfi1: Fix wrong mmu_node used for user SDMA packet after invalidate
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
IB/hfi1: Use bitmap_zalloc() when applicable
Arnd Bergmann <arnd@arndb.de>
RDMA/irdma: avoid fortify-string warning in irdma_clr_wqes
Randy Dunlap <rdunlap@infradead.org>
soc/fsl/qe: fix usb.c build errors
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
ARM: dts: meson8: correct uart_B and uart_C clock references
Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
ASoC: es8316: Do not set rate constraints for unsupported MCLKs
Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
ASoC: es8316: Increment max value for ALC Capture Target Volume control
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
memory: brcmstb_dpfe: fix testing array offset after use
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Shorten the AV96 HDMI sound card name
Douglas Anderson <dianders@chromium.org>
arm64: dts: mediatek: mt8183: Add mediatek,broken-save-restore-fw to kukui
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: apq8096: fix fixed regulator name property
Arnd Bergmann <arnd@arndb.de>
ARM: omap2: fix missing tick_broadcast() prototype
Arnd Bergmann <arnd@arndb.de>
ARM: ep93xx: fix missing-prototype warnings
Dario Binacchi <dario.binacchi@amarulasolutions.com>
drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: apq8016-sbc: Fix 1.8V power rail on LS expansion
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: apq8016-sbc: Fix regulator constraints
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: Drop unneeded extra device-specific includes
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: apq8016-sbc: fix mpps state names
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: apq8016-sbc: Clarify firmware-names
Bjorn Andersson <bjorn.andersson@linaro.org>
arm64: dts: qcom: apq8016-sbc: Update modem and WiFi firmware path
Yassine Oudjana <y.oudjana@protonmail.com>
arm64: dts: qcom: db820c: Move blsp1_uart2 pin states to msm8996.dtsi
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: sdm845: correct camss unit address
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: sdm630: correct camss unit address
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: msm8996: correct camss unit address
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: msm8994: correct SPMI unit address
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
arm64: dts: qcom: msm8916: correct camss unit address
Tony Lindgren <tony@atomide.com>
ARM: dts: gta04: Move model property out of pinctrl node
Konrad Dybcio <konrad.dybcio@linaro.org>
drm/msm/dpu: Set DPU_DATA_HCTL_EN for in INTF_SC7180_MASK
Vinod Polimera <quic_vpolimer@quicinc.com>
drm/msm/disp/dpu: get timing engine status from intf status register
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: don't allow enabling 14nm VCO with unprogrammed rate
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Fix to remove an unnecessary log
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Remove a redundant check inside bnxt_re_update_gid
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Use unique names while registering interrupts
Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
RDMA/bnxt_re: Fix to remove unnecessary return labels
Selvin Xavier <selvin.xavier@broadcom.com>
RDMA/bnxt_re: Disable/kill tasklet only if it is enabled
Dan Carpenter <dan.carpenter@linaro.org>
clk: imx: scu: use _safe list iterator to avoid a use after free
Robert Marko <robert.marko@sartura.hr>
arm64: dts: microchip: sparx5: do not use PSCI on reference boards
Tony Lindgren <tony@atomide.com>
bus: ti-sysc: Fix dispc quirk masking bool variables
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Move ethernet MAC EEPROM from SoM to carrier boards
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/panel: sharp-ls043t1le01: adjust mode settings
XuDong Liu <m202071377@hust.edu.cn>
drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
Marek Vasut <marex@denx.de>
Input: adxl34x - do not hardcode interrupt trigger type
hfdevel@gmx.net <hfdevel@gmx.net>
ARM: dts: meson8b: correct uart_B and uart_C clock references
Rafał Miłecki <rafal@milecki.pl>
ARM: dts: BCM5301X: Drop "clock-names" from the SPI node
Luc Ma <luc@sietium.com>
drm/vram-helper: fix function names in vram helper doc
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix THS_TRAILCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix TXTAGOCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix THS_ZEROCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix TCLK_TRAILCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: Add atomic_get_input_bus_fmts() implementation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix TCLK_ZEROCNT computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix PLL target frequency
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: fix PLL parameters computation
Francesco Dolcini <francesco.dolcini@toradex.com>
drm/bridge: tc358768: always enable HS video mode
Luca Weiss <luca@z3ntu.xyz>
Input: drv260x - sleep between polling GO bit
Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
drm/amd/display: Explicitly specify update type per plane info change
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
radeon: avoid double free in ci_dpm_init()
Wesley Chalmers <Wesley.Chalmers@amd.com>
drm/amd/display: Add logging for display MALL refresh setting
Kuniyuki Iwashima <kuniyu@amazon.com>
netlink: Add __sock_i_ino() for __netlink_diag_dump().
Cambda Zhu <cambda@linux.alibaba.com>
ipvlan: Fix return value of ipvlan_queue_xmit()
Ilia.Gavrilov <Ilia.Gavrilov@infotecs.ru>
netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return value.
Florian Westphal <fw@strlen.de>
netfilter: conntrack: dccp: copy entire header to stack buffer, not just basic one
Jeremy Sowden <jeremy@azazel.net>
lib/ts_bm: reset initial match offset for every block of text
Lin Ma <linma@zju.edu.cn>
net: nfc: Fix use-after-free caused by nfc_llcp_find_local
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
nfc: llcp: simplify llcp_sock_connect() error paths
Edward Cree <ecree.xilinx@gmail.com>
sfc: fix crash when reading stats while NIC is resetting
Maxim Kochetkov <fido_max@inbox.ru>
net: axienet: Move reset before 64-bit DMA detection
Kuniyuki Iwashima <kuniyu@amazon.com>
gtp: Fix use-after-free in __gtp_encap_destroy().
Sabrina Dubroca <sd@queasysnail.net>
selftests: rtnetlink: remove netdevsim device after ipsec offload test
Eric Dumazet <edumazet@google.com>
bonding: do not assume skb mac_header is set
Eric Dumazet <edumazet@google.com>
netlink: do not hard code device address lenth in fdb dumps
Eric Dumazet <edumazet@google.com>
netlink: fix potential deadlock in netlink_set_err()
Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
net: stmmac: fix double serdes powerdown
Vinicius Costa Gomes <vinicius.gomes@intel.com>
igc: Fix race condition in PTP tx code
Vincent Mailhol <mailhol.vincent@wanadoo.fr>
can: length: fix bitstuffing count
Gilad Sever <gilad9366@gmail.com>
bpf: Fix bpf socket lookup from tc/xdp to respect socket VRF bindings
Gilad Sever <gilad9366@gmail.com>
bpf: Call __bpf_sk_lookup()/__bpf_skc_lookup() directly via TC hookpoint
Gilad Sever <gilad9366@gmail.com>
bpf: Factor out socket lookup functions for the TC hookpoint.
Tobias Klauser <tklauser@distanz.ch>
bpf: Omit superfluous address family check in __bpf_skc_lookup
Dmitry Antipov <dmantipov@yandex.ru>
wifi: ath9k: convert msecs to jiffies where needed
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: mvm: indicate HW decrypt for beacon protection
Benjamin Berg <benjamin.berg@intel.com>
wifi: cfg80211: rewrite merging of inherited elements
Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
wifi: iwlwifi: pcie: fix NULL pointer dereference in iwl_pcie_irq_rx_msix_handler()
Emmanuel Grumbach <emmanuel.grumbach@intel.com>
iwlwifi: don't dump_stack() when we get an unexpected interrupt
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: pull from TXQs with softirqs disabled
Edwin Peer <edwin.peer@broadcom.com>
rtnetlink: extend RTEXT_FILTER_SKIP_STATS to IFLA_VF_INFO
Remi Pommarel <repk@triplefau.lt>
wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
Arnd Bergmann <arnd@arndb.de>
memstick r592: make memstick_debug_get_tpc_name() static
Zhen Lei <thunder.leizhen@huawei.com>
kexec: fix a memory leak in crash_shrink_memory()
Douglas Anderson <dianders@chromium.org>
watchdog/perf: more properly prevent false positives with turbo modes
Douglas Anderson <dianders@chromium.org>
watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct config
Marek Vasut <marex@denx.de>
wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown
Marek Vasut <marex@denx.de>
wifi: rsi: Do not configure WoWlan in shutdown hook if not enabled
Jesper Dangaard Brouer <brouer@redhat.com>
selftests/bpf: Fix check_mtu using wrong variable type
Fedor Pchelkin <pchelkin@ispras.ru>
wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: ray_cs: Fix an error handling path in ray_probe()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
wifi: ray_cs: Drop useless status variable in parse_addr()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
wifi: ray_cs: Utilize strnlen() in parse_addr()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: wl3501_cs: Fix an error handling path in wl3501_probe()
Jakub Kicinski <kuba@kernel.org>
wl3501_cs: use eth_hw_addr_set()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: atmel: Fix an error handling path in atmel_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: orinoco: Fix an error handling path in orinoco_cs_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: orinoco: Fix an error handling path in spectrum_cs_probe()
Geert Uytterhoeven <geert+renesas@glider.be>
regulator: core: Streamline debugfs operations
Geert Uytterhoeven <geert+renesas@glider.be>
regulator: core: Fix more error checking for debugfs_create_dir()
Alan Maguire <alan.maguire@oracle.com>
bpftool: JIT limited misreported as negative value on aarch64
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
nfc: llcp: fix possible use of uninitialized variable in nfc_llcp_send_connect()
Joy Chakraborty <joychakr@google.com>
spi: dw: Round of n_bytes to power of 2
Stanislav Fomichev <sdf@google.com>
bpf: Don't EFAULT for {g,s}setsockopt with wrong optlen
Andrii Nakryiko <andrii@kernel.org>
libbpf: fix offsetof() and container_of() to work with CO-RE
Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
sctp: add bpf_bypass_getsockopt proto callback
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: mwifiex: Fix the size of a memory allocation in mwifiex_ret_802_11_scan()
Amisha Patel <amisha.patel@microchip.com>
wifi: wilc1000: fix for absent RSN capabilities WFA testcase
Vijaya Krishna Nivarthi <quic_vnivarth@quicinc.com>
spi: spi-geni-qcom: Correct CS_TOGGLE bit in SPI_TRANS_CFG
Pengcheng Yang <yangpc@wangsu.com>
samples/bpf: Fix buffer overflow in tcp_basertt
Martin KaFai Lau <martin.lau@kernel.org>
libbpf: btf_dump_type_data_check_overflow needs to consider BTF_MEMBER_BITFIELD_SIZE
Fedor Pchelkin <pchelkin@ispras.ru>
wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx
Peter Seiderer <ps.report@gmx.net>
wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation
Jesper Dangaard Brouer <brouer@redhat.com>
igc: Enable and fix RX hash usage by netstack
Jiasheng Jiang <jiasheng@iscas.ac.cn>
pstore/ram: Add check for kstrdup
Roberto Sassu <roberto.sassu@huawei.com>
ima: Fix build warnings
Roberto Sassu <roberto.sassu@huawei.com>
evm: Fix build warnings
Roberto Sassu <roberto.sassu@huawei.com>
evm: Complete description of evm_inode_setattr()
Mark Rutland <mark.rutland@arm.com>
locking/atomic: arm: fix sync ops
Juergen Gross <jgross@suse.com>
x86/mm: Fix __swp_entry_to_pte() for Xen PV guests
Ravi Bangoria <ravi.bangoria@amd.com>
perf/ibs: Fix interface via core pmu events
Colin Ian King <colin.i.king@gmail.com>
kselftest: vDSO: Fix accumulation of uninitialized ret when CLOCK_REALTIME is undefined
Qiuxu Zhuo <qiuxu.zhuo@intel.com>
rcu/rcuscale: Stop kfree_scale_thread thread(s) after unloading rcuscale
Qiuxu Zhuo <qiuxu.zhuo@intel.com>
rcu/rcuscale: Move rcu_scale_*() after kfree_scale_cleanup()
Paul E. McKenney <paulmck@kernel.org>
rcuscale: Move shutdown from wait_event() to wait_event_idle()
Li Zhijian <zhijianx.li@intel.com>
rcuscale: Always log error message
Paul E. McKenney <paulmck@kernel.org>
rcutorture: Correct name of use_softirq module parameter
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
thermal/drivers/sun8i: Fix some error handling paths in sun8i_ths_probe()
Tero Kristo <tero.kristo@linux.intel.com>
cpufreq: intel_pstate: Fix energy_performance_preference for passive
Arnd Bergmann <arnd@arndb.de>
ARM: 9303/1: kprobes: avoid missing-declaration warnings
Zhang Rui <rui.zhang@intel.com>
powercap: RAPL: Fix CONFIG_IOSF_MBI dependency
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix DTC reset
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
PM: domains: fix integer overflow issues in genpd_parse_state()
Feng Mingxi <m202271825@hust.edu.cn>
clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
tracing/timer: Add missing hrtimer modes to decode_hrtimer_mode().
Thomas Gleixner <tglx@linutronix.de>
posix-timers: Prevent RT livelock in itimer_delete()
Chuck Lever <chuck.lever@oracle.com>
svcrdma: Prevent page release when nothing was received
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
irqchip/jcore-aic: Fix missing allocation of IRQ descriptors
Li Nan <linan122@huawei.com>
md/raid10: fix io loss while replacement replace rdev
Li Nan <linan122@huawei.com>
md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request
Li Nan <linan122@huawei.com>
md/raid10: fix wrong setting of max_corr_read_errors
Li Nan <linan122@huawei.com>
md/raid10: fix overflow of md/safe_mode_delay
Li Nan <linan122@huawei.com>
md/raid10: check slab-out-of-bounds in md_bitmap_get_counter
Li Nan <linan122@huawei.com>
blk-iocost: use spin_lock_irqsave in adjust_inuse_and_calc_cost
Shawn Wang <shawnwang@linux.alibaba.com>
x86/resctrl: Only show tasks' pid in current pid namespace
Arnd Bergmann <arnd@arndb.de>
fs: pipe: reveal missing function protoypes
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: drop map element references from preparation phase
-------------
Diffstat:
.../admin-guide/device-mapper/dm-init.rst | 8 +
Documentation/arm64/silicon-errata.rst | 4 +
Documentation/filesystems/autofs-mount-control.rst | 2 +-
Documentation/filesystems/autofs.rst | 2 +-
Documentation/filesystems/directory-locking.rst | 26 +-
Documentation/networking/af_xdp.rst | 9 +
Makefile | 4 +-
arch/arc/include/asm/linkage.h | 8 +-
arch/arm/boot/dts/bcm53015-meraki-mr26.dts | 2 +-
arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 2 +-
arch/arm/boot/dts/bcm5301x.dtsi | 1 -
arch/arm/boot/dts/iwg20d-q7-common.dtsi | 2 +-
arch/arm/boot/dts/meson8.dtsi | 4 +-
arch/arm/boot/dts/meson8b.dtsi | 4 +-
arch/arm/boot/dts/omap3-gta04a5one.dts | 4 +-
arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts | 8 +-
arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi | 10 +-
arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi | 12 +-
arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi | 11 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 8 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi | 6 -
arch/arm/boot/dts/stm32mp15xx-dkx.dtsi | 2 +-
arch/arm/include/asm/assembler.h | 17 +
arch/arm/include/asm/sync_bitops.h | 29 +-
arch/arm/lib/bitops.h | 14 +-
arch/arm/lib/testchangebit.S | 4 +
arch/arm/lib/testclearbit.S | 4 +
arch/arm/lib/testsetbit.S | 4 +
arch/arm/mach-ep93xx/timer-ep93xx.c | 3 +-
arch/arm/mach-omap2/board-generic.c | 1 +
arch/arm/mach-orion5x/board-dt.c | 3 +
arch/arm/mach-orion5x/common.h | 6 +
arch/arm/probes/kprobes/checkers-common.c | 2 +-
arch/arm/probes/kprobes/core.c | 2 +-
arch/arm/probes/kprobes/opt-arm.c | 2 -
arch/arm/probes/kprobes/test-core.c | 2 +-
arch/arm/probes/kprobes/test-core.h | 4 +
arch/arm64/Kconfig | 41 +
arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi | 4 +
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 22 +-
arch/arm64/boot/dts/microchip/sparx5.dtsi | 2 +-
.../boot/dts/microchip/sparx5_pcb_common.dtsi | 12 +
arch/arm64/boot/dts/qcom/apq8016-sbc.dts | 840 ++++++++++++++-
arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi | 826 ---------------
arch/arm64/boot/dts/qcom/apq8096-db820c.dts | 1070 ++++++++++++++++++-
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi | 1105 --------------------
arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts | 4 +-
arch/arm64/boot/dts/qcom/msm8916-mtp.dts | 15 +-
arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi | 21 -
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +-
arch/arm64/boot/dts/qcom/msm8994.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8996-mtp.dts | 24 +-
arch/arm64/boot/dts/qcom/msm8996-mtp.dtsi | 30 -
arch/arm64/boot/dts/qcom/msm8996.dtsi | 19 +-
arch/arm64/boot/dts/qcom/sdm630.dtsi | 2 +-
arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 +-
.../boot/dts/qcom/sm8250-sony-xperia-edo.dtsi | 7 +-
arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 3 +-
.../boot/dts/ti/k3-j7200-common-proc-board.dts | 28 +-
arch/arm64/kernel/cpu_errata.c | 26 +
arch/arm64/tools/cpucaps | 1 +
arch/mips/include/asm/kvm_host.h | 6 +-
arch/mips/kernel/cpu-probe.c | 9 +-
arch/mips/kvm/emulate.c | 22 +-
arch/mips/kvm/mips.c | 16 +-
arch/mips/kvm/stats.c | 4 +-
arch/mips/kvm/trace.h | 8 +-
arch/mips/kvm/vz.c | 20 +-
arch/powerpc/Kconfig.debug | 2 +-
arch/powerpc/Makefile | 8 +
arch/powerpc/kernel/interrupt.c | 3 +-
arch/powerpc/kernel/ppc_save_regs.S | 61 +-
arch/powerpc/kernel/security.c | 37 +-
arch/powerpc/kernel/signal_32.c | 15 +-
arch/powerpc/mm/book3s64/radix_pgtable.c | 34 +-
arch/powerpc/mm/init_64.c | 2 +-
arch/powerpc/platforms/powernv/pci-sriov.c | 6 +-
arch/powerpc/platforms/powernv/vas-window.c | 2 +-
arch/powerpc/platforms/pseries/vas.c | 2 +-
arch/riscv/kernel/probes/uprobes.c | 2 +
arch/riscv/mm/init.c | 6 +-
arch/riscv/net/bpf_jit.h | 5 +-
arch/riscv/net/bpf_jit_core.c | 15 +-
arch/s390/Makefile | 1 +
arch/s390/kvm/diag.c | 8 +-
arch/s390/kvm/kvm-s390.c | 4 +
arch/s390/kvm/vsie.c | 6 +-
arch/sh/drivers/dma/dma-sh.c | 37 +-
arch/sh/kernel/cpu/sh2/probe.c | 2 +-
arch/um/Makefile | 2 +-
arch/x86/events/amd/core.c | 2 +-
arch/x86/events/amd/ibs.c | 53 +-
arch/x86/include/asm/perf_event.h | 2 +
arch/x86/include/asm/pgtable_64.h | 4 +-
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 8 +-
arch/xtensa/platforms/iss/network.c | 2 +-
block/blk-iocost.c | 7 +-
block/disk-events.c | 1 +
block/partitions/amiga.c | 104 +-
drivers/base/power/domain.c | 6 +-
drivers/bus/intel-ixp4xx-eb.c | 2 +-
drivers/bus/ti-sysc.c | 4 +-
drivers/char/hw_random/imx-rngc.c | 6 +-
drivers/char/hw_random/st-rng.c | 21 +-
drivers/char/hw_random/virtio-rng.c | 88 +-
drivers/char/tpm/tpm_vtpm_proxy.c | 30 +-
drivers/clk/clk-cdce925.c | 12 +
drivers/clk/clk-si5341.c | 38 +-
drivers/clk/clk-versaclock5.c | 29 +
drivers/clk/clk.c | 1 +
drivers/clk/imx/clk-imx8mn.c | 8 +-
drivers/clk/imx/clk-imx8mp.c | 24 +-
drivers/clk/imx/clk-scu.c | 4 +-
drivers/clk/keystone/sci-clk.c | 2 +
drivers/clk/qcom/camcc-sc7180.c | 19 +-
drivers/clk/qcom/gcc-ipq6018.c | 34 +-
drivers/clk/qcom/reset.c | 8 +-
drivers/clk/qcom/reset.h | 2 +
drivers/clk/tegra/clk-tegra124-emc.c | 2 +
drivers/clk/ti/clkctrl.c | 7 +
drivers/clocksource/timer-cadence-ttc.c | 19 +-
drivers/cpufreq/intel_pstate.c | 2 +
drivers/crypto/marvell/cesa/cipher.c | 2 +-
drivers/crypto/nx/Makefile | 2 +-
drivers/crypto/nx/nx.h | 4 +-
drivers/crypto/qat/qat_common/adf_common_drv.h | 5 -
drivers/crypto/qat/qat_common/qat_algs.c | 23 +-
drivers/crypto/qat/qat_common/qat_asym_algs.c | 53 +-
drivers/crypto/qat/qat_common/qat_crypto.h | 5 +
drivers/dax/bus.c | 61 +-
drivers/dax/dax-private.h | 4 +-
drivers/dax/kmem.c | 2 +-
drivers/extcon/extcon-usbc-tusb320.c | 5 +-
drivers/extcon/extcon.c | 8 +
drivers/firmware/efi/libstub/efi-stub-helper.c | 7 +-
drivers/firmware/stratix10-svc.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 28 +-
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 13 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +
.../dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c | 3 +
drivers/gpu/drm/amd/display/dc/core/dc.c | 3 -
drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 +-
drivers/gpu/drm/bridge/tc358768.c | 93 +-
drivers/gpu/drm/bridge/ti-sn65dsi86.c | 33 +-
drivers/gpu/drm/drm_atomic_helper.c | 11 +-
drivers/gpu/drm/drm_gem_vram_helper.c | 6 +-
drivers/gpu/drm/i915/display/intel_psr.c | 4 +-
drivers/gpu/drm/i915/gt/intel_gtt.c | 2 +-
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 3 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 5 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 10 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 12 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 8 +-
drivers/gpu/drm/msm/dp/dp_display.c | 2 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 3 +
drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 11 +-
drivers/gpu/drm/panel/panel-simple.c | 6 +-
drivers/gpu/drm/radeon/ci_dpm.c | 28 +-
drivers/gpu/drm/radeon/cypress_dpm.c | 8 +-
drivers/gpu/drm/radeon/ni_dpm.c | 8 +-
drivers/gpu/drm/radeon/rv740_dpm.c | 8 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 +-
drivers/gpu/drm/sun4i/sun4i_tcon.c | 19 +-
drivers/gpu/drm/ttm/ttm_bo.c | 7 +
drivers/hwmon/gsc-hwmon.c | 6 +-
drivers/hwmon/pmbus/adm1275.c | 90 +-
drivers/hwtracing/coresight/coresight-core.c | 9 +-
drivers/i2c/busses/i2c-qup.c | 21 +-
drivers/i2c/busses/i2c-xiic.c | 39 +-
drivers/iio/accel/fxls8962af-core.c | 8 +-
drivers/iio/adc/ad7192.c | 8 +-
drivers/iio/adc/meson_saradc.c | 2 +-
drivers/infiniband/hw/bnxt_re/main.c | 20 +-
drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40 +-
drivers/infiniband/hw/bnxt_re/qplib_fp.h | 2 +-
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c | 46 +-
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h | 1 +
drivers/infiniband/hw/hfi1/ipoib_tx.c | 4 +-
drivers/infiniband/hw/hfi1/mmu_rb.c | 101 +-
drivers/infiniband/hw/hfi1/mmu_rb.h | 3 +
drivers/infiniband/hw/hfi1/sdma.c | 23 +-
drivers/infiniband/hw/hfi1/sdma.h | 47 +-
drivers/infiniband/hw/hfi1/sdma_txreq.h | 2 +
drivers/infiniband/hw/hfi1/user_sdma.c | 145 +--
drivers/infiniband/hw/hfi1/user_sdma.h | 1 -
drivers/infiniband/hw/hfi1/vnic_sdma.c | 4 +-
drivers/infiniband/hw/hns/hns_roce_hem.c | 7 +-
drivers/infiniband/hw/irdma/uk.c | 10 +-
drivers/input/misc/adxl34x.c | 3 +-
drivers/input/misc/drv260x.c | 1 +
drivers/irqchip/irq-jcore-aic.c | 7 +
drivers/leds/trigger/ledtrig-netdev.c | 3 +
drivers/mailbox/ti-msgmgr.c | 12 +-
drivers/md/bcache/btree.c | 25 +-
drivers/md/bcache/btree.h | 1 +
drivers/md/bcache/super.c | 4 +-
drivers/md/bcache/writeback.c | 10 +
drivers/md/dm-init.c | 22 +-
drivers/md/dm-integrity.c | 4 +-
drivers/md/md-bitmap.c | 17 +-
drivers/md/md.c | 9 +-
drivers/md/raid0.c | 62 +-
drivers/md/raid0.h | 1 +
drivers/md/raid10.c | 38 +-
drivers/media/cec/i2c/Kconfig | 1 +
drivers/media/i2c/st-mipid02.c | 9 +-
drivers/media/platform/qcom/venus/helpers.c | 4 +-
drivers/media/usb/dvb-usb-v2/az6007.c | 3 +-
drivers/media/usb/siano/smsusb.c | 3 +-
drivers/memory/brcmstb_dpfe.c | 4 +-
drivers/memstick/host/r592.c | 4 +-
drivers/mfd/intel-lpss-acpi.c | 3 +
drivers/mfd/qcom-pm8008.c | 1 +
drivers/mfd/rt5033.c | 3 -
drivers/mfd/stmfx.c | 7 +-
drivers/mfd/stmpe.c | 4 +-
drivers/misc/fastrpc.c | 2 +-
drivers/misc/pci_endpoint_test.c | 10 +-
drivers/mmc/core/quirks.h | 14 +
drivers/mmc/host/mmci.c | 1 +
drivers/mmc/host/sdhci.c | 4 +-
drivers/mtd/nand/raw/meson_nand.c | 4 +
drivers/net/bonding/bond_main.c | 2 +-
drivers/net/dsa/vitesse-vsc73xx-core.c | 6 +-
drivers/net/ethernet/amazon/ena/ena_com.c | 3 +
drivers/net/ethernet/broadcom/bgmac.c | 4 +-
drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +
drivers/net/ethernet/broadcom/tg3.c | 1 +
drivers/net/ethernet/google/gve/gve_ethtool.c | 3 +
drivers/net/ethernet/ibm/ibmvnic.c | 9 +-
drivers/net/ethernet/intel/igc/igc.h | 33 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 2 +
drivers/net/ethernet/intel/igc/igc_main.c | 45 +-
drivers/net/ethernet/intel/igc/igc_ptp.c | 82 +-
drivers/net/ethernet/marvell/mvneta.c | 4 +-
drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 7 +
drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 11 +
.../net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 4 +-
.../ethernet/marvell/octeontx2/nic/otx2_flows.c | 8 +
.../net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 15 +
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c | 6 +-
.../ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +-
drivers/net/ethernet/microchip/lan743x_main.c | 21 +-
drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5 -
drivers/net/ethernet/sfc/ef10.c | 13 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 -
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 10 +-
drivers/net/gtp.c | 2 +
drivers/net/ipvlan/ipvlan_core.c | 9 +-
drivers/net/netdevsim/dev.c | 9 +-
drivers/net/ppp/pptp.c | 31 +-
drivers/net/wireguard/netlink.c | 14 +-
drivers/net/wireguard/queueing.c | 1 +
drivers/net/wireguard/queueing.h | 25 +-
drivers/net/wireguard/receive.c | 2 +-
drivers/net/wireguard/send.c | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_hw.c | 27 +-
drivers/net/wireless/ath/ath9k/htc_hst.c | 8 +-
drivers/net/wireless/ath/ath9k/main.c | 11 +-
drivers/net/wireless/ath/ath9k/wmi.c | 4 +
drivers/net/wireless/atmel/atmel_cs.c | 13 +-
drivers/net/wireless/cisco/airo.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 9 +-
drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 12 +-
drivers/net/wireless/intersil/orinoco/orinoco_cs.c | 13 +-
.../net/wireless/intersil/orinoco/spectrum_cs.c | 13 +-
drivers/net/wireless/marvell/mwifiex/scan.c | 6 +-
drivers/net/wireless/microchip/wilc1000/hif.c | 8 +-
drivers/net/wireless/ray_cs.c | 36 +-
drivers/net/wireless/rsi/rsi_91x_sdio.c | 9 +-
drivers/net/wireless/wl3501_cs.c | 19 +-
drivers/ntb/hw/amd/ntb_hw_amd.c | 7 +-
drivers/ntb/hw/idt/ntb_hw_idt.c | 7 +-
drivers/ntb/hw/intel/ntb_hw_gen1.c | 7 +-
drivers/ntb/ntb_transport.c | 2 +-
drivers/ntb/test/ntb_tool.c | 2 +
drivers/nvme/host/pci.c | 30 +-
drivers/nvmem/rmem.c | 1 +
drivers/opp/core.c | 3 +
drivers/pci/controller/cadence/pcie-cadence-host.c | 27 +
drivers/pci/controller/dwc/pcie-qcom.c | 2 +
drivers/pci/controller/pci-ftpci100.c | 14 +-
drivers/pci/controller/pcie-rockchip-ep.c | 65 +-
drivers/pci/controller/pcie-rockchip.c | 17 +
drivers/pci/controller/pcie-rockchip.h | 11 +-
drivers/pci/controller/vmd.c | 8 +
drivers/pci/hotplug/acpiphp_glue.c | 5 +-
drivers/pci/hotplug/pciehp_ctrl.c | 8 +
drivers/pci/pci.c | 10 +-
drivers/pci/pcie/aspm.c | 21 +-
drivers/pci/quirks.c | 2 +
drivers/perf/arm-cmn.c | 7 +-
drivers/phy/tegra/xusb.c | 4 +
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 6 +-
drivers/pinctrl/intel/pinctrl-cherryview.c | 15 +-
drivers/pinctrl/pinctrl-amd.c | 25 +-
drivers/pinctrl/pinctrl-amd.h | 1 +
drivers/pinctrl/pinctrl-at91-pio4.c | 2 +
drivers/pinctrl/pinctrl-microchip-sgpio.c | 3 +
drivers/platform/x86/wmi.c | 64 +-
drivers/powercap/Kconfig | 4 +-
drivers/powercap/intel_rapl_msr.c | 1 -
drivers/pwm/pwm-ab8500.c | 2 +-
drivers/pwm/pwm-imx-tpm.c | 7 +
drivers/pwm/pwm-mtk-disp.c | 13 +-
drivers/pwm/sysfs.c | 17 +
drivers/regulator/core.c | 30 +-
drivers/rtc/rtc-st-lpc.c | 2 +-
drivers/s390/net/qeth_l3_sys.c | 2 +-
drivers/scsi/3w-xxxx.c | 4 +-
drivers/scsi/qedf/qedf_main.c | 3 +-
drivers/scsi/qla2xxx/qla_attr.c | 13 +
drivers/scsi/qla2xxx/qla_bsg.c | 6 +
drivers/scsi/qla2xxx/qla_def.h | 1 -
drivers/scsi/qla2xxx/qla_edif.c | 4 +-
drivers/scsi/qla2xxx/qla_init.c | 2 +-
drivers/scsi/qla2xxx/qla_inline.h | 5 +-
drivers/scsi/qla2xxx/qla_iocb.c | 5 +-
drivers/scsi/qla2xxx/qla_nvme.c | 3 -
drivers/scsi/qla2xxx/qla_os.c | 3 +-
drivers/soc/amlogic/meson-secure-pwrc.c | 2 +-
drivers/soc/fsl/qe/Kconfig | 1 +
drivers/soundwire/qcom.c | 3 +-
drivers/spi/spi-bcm-qspi.c | 10 +-
drivers/spi/spi-dw-core.c | 5 +-
drivers/spi/spi-geni-qcom.c | 2 +-
.../clocking-wizard/clk-xlnx-clock-wizard.c | 2 +-
.../media/atomisp/pci/atomisp_gmin_platform.c | 2 +-
drivers/thermal/sun8i_thermal.c | 55 +-
drivers/tty/serial/8250/8250.h | 1 -
drivers/tty/serial/8250/8250_omap.c | 25 +-
drivers/tty/serial/8250/8250_pci.c | 19 -
drivers/tty/serial/8250/8250_port.c | 11 +-
drivers/tty/serial/atmel_serial.c | 4 +-
drivers/tty/serial/fsl_lpuart.c | 1 +
drivers/tty/serial/imx.c | 18 +-
drivers/tty/serial/samsung_tty.c | 14 +-
drivers/usb/core/devio.c | 2 +
drivers/usb/dwc2/platform.c | 18 +-
drivers/usb/dwc3/dwc3-meson-g12a.c | 5 +-
drivers/usb/dwc3/dwc3-qcom.c | 17 +-
drivers/usb/dwc3/gadget.c | 4 +-
drivers/usb/gadget/function/u_serial.c | 13 +-
drivers/usb/host/xhci-mem.c | 39 +-
drivers/usb/host/xhci-pci.c | 12 +
drivers/usb/host/xhci.h | 2 +
drivers/usb/phy/phy-tahvo.c | 2 +-
drivers/usb/serial/option.c | 4 +
drivers/video/fbdev/omap/lcd_mipid.c | 6 +-
drivers/w1/slaves/w1_therm.c | 31 +-
drivers/w1/w1.c | 4 +-
fs/btrfs/block-group.c | 36 +-
fs/btrfs/ctree.c | 28 +-
fs/btrfs/qgroup.c | 2 +
fs/ceph/caps.c | 9 +
fs/cifs/file.c | 25 +-
fs/dlm/plock.c | 4 +-
fs/erofs/inode.c | 5 +-
fs/erofs/internal.h | 16 +-
fs/erofs/super.c | 58 +-
fs/erofs/xattr.c | 4 +-
fs/erofs/zdata.c | 10 +-
fs/erofs/zmap.c | 6 +-
fs/ext4/indirect.c | 8 +
fs/ext4/inode.c | 10 -
fs/ext4/ioctl.c | 5 +-
fs/ext4/mballoc.c | 17 +-
fs/ext4/namei.c | 17 +-
fs/ext4/super.c | 19 +-
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 2 +-
fs/f2fs/gc.c | 21 +-
fs/f2fs/namei.c | 16 +-
fs/f2fs/node.c | 4 +-
fs/fs_context.c | 3 +-
fs/inode.c | 42 +
fs/internal.h | 2 +
fs/jffs2/build.c | 5 +-
fs/jffs2/xattr.c | 13 +-
fs/jffs2/xattr.h | 4 +-
fs/jfs/jfs_dmap.c | 6 +
fs/jfs/jfs_filsys.h | 2 +
fs/kernfs/dir.c | 2 +
fs/ksmbd/server.c | 33 +-
fs/ksmbd/smb2misc.c | 38 +-
fs/ksmbd/smb2pdu.c | 44 +-
fs/ksmbd/smb_common.c | 2 +-
fs/namei.c | 25 +-
fs/nfs/nfs4proc.c | 1 +
fs/nfsd/nfs4xdr.c | 2 +-
fs/notify/fanotify/fanotify_user.c | 22 +-
fs/ntfs3/index.c | 84 +-
fs/ntfs3/inode.c | 18 +-
fs/ntfs3/ntfs_fs.h | 4 +-
fs/ntfs3/run.c | 7 +-
fs/ntfs3/xattr.c | 112 +-
fs/overlayfs/copy_up.c | 2 +
fs/overlayfs/dir.c | 3 +-
fs/overlayfs/export.c | 3 +-
fs/overlayfs/inode.c | 10 +-
fs/overlayfs/namei.c | 3 +-
fs/overlayfs/overlayfs.h | 6 +-
fs/overlayfs/super.c | 2 +-
fs/overlayfs/util.c | 24 +-
fs/pstore/ram_core.c | 2 +
fs/ramfs/inode.c | 2 +-
include/acpi/acpi_bus.h | 3 +-
include/crypto/internal/kpp.h | 6 +
include/linux/bootmem_info.h | 2 +
include/linux/can/length.h | 14 +-
include/linux/netdevice.h | 9 +
include/linux/nmi.h | 2 +-
include/linux/pci.h | 1 +
include/linux/pipe_fs_i.h | 4 -
include/linux/ramfs.h | 1 +
include/linux/serial_8250.h | 1 -
include/linux/workqueue.h | 15 +-
include/net/netfilter/nf_tables.h | 5 +-
include/net/pkt_sched.h | 2 +-
include/net/sock.h | 1 +
include/trace/events/timer.h | 6 +-
include/uapi/linux/affs_hardblocks.h | 68 +-
include/uapi/linux/auto_dev-ioctl.h | 2 +-
include/uapi/linux/videodev2.h | 2 +-
io_uring/io_uring.c | 66 +-
kernel/bpf/cgroup.c | 15 +
kernel/bpf/cpumap.c | 40 +-
kernel/bpf/verifier.c | 5 +-
kernel/kcsan/core.c | 2 +
kernel/kexec_core.c | 5 +-
kernel/rcu/rcuscale.c | 212 ++--
kernel/time/posix-timers.c | 43 +-
kernel/trace/ftrace.c | 45 +-
kernel/trace/ring_buffer.c | 24 +-
kernel/trace/trace.c | 3 +-
kernel/trace/trace_eprobe.c | 18 +-
kernel/trace/trace_events_hist.c | 8 +-
kernel/trace/trace_probe_tmpl.h | 14 +-
kernel/watchdog_hld.c | 6 +-
kernel/workqueue.c | 13 +-
lib/test_firmware.c | 12 +-
lib/ts_bm.c | 4 +-
mm/damon/vaddr.c | 20 +-
mm/shmem.c | 2 +-
net/bridge/br_if.c | 5 +-
net/ceph/messenger_v2.c | 41 +-
net/core/filter.c | 131 ++-
net/core/rtnetlink.c | 104 +-
net/core/skbuff.c | 5 +
net/core/sock.c | 17 +-
net/dsa/tag_sja1105.c | 4 +-
net/ipv4/tcp_input.c | 12 +-
net/ipv6/addrconf.c | 3 +-
net/ipv6/icmp.c | 5 +-
net/ipv6/udp.c | 2 +-
net/netfilter/ipvs/Kconfig | 27 +-
net/netfilter/ipvs/ip_vs_conn.c | 4 +-
net/netfilter/nf_conntrack_helper.c | 4 +
net/netfilter/nf_conntrack_proto_dccp.c | 52 +-
net/netfilter/nf_conntrack_sip.c | 2 +-
net/netfilter/nf_tables_api.c | 158 ++-
net/netfilter/nft_byteorder.c | 14 +-
net/netfilter/nft_set_bitmap.c | 5 +-
net/netfilter/nft_set_hash.c | 23 +-
net/netfilter/nft_set_pipapo.c | 14 +-
net/netfilter/nft_set_rbtree.c | 5 +-
net/netlink/af_netlink.c | 5 +-
net/netlink/diag.c | 7 +-
net/nfc/llcp.h | 1 -
net/nfc/llcp_commands.c | 15 +-
net/nfc/llcp_core.c | 49 +-
net/nfc/llcp_sock.c | 21 +-
net/nfc/netlink.c | 20 +-
net/nfc/nfc.h | 1 +
net/sched/act_ipt.c | 27 +-
net/sched/act_pedit.c | 1 +
net/sched/cls_flower.c | 10 +
net/sched/cls_fw.c | 10 +-
net/sched/sch_qfq.c | 41 +-
net/sctp/socket.c | 22 +-
net/sunrpc/svcsock.c | 23 +-
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 12 +-
net/wireless/scan.c | 213 ++--
net/xdp/xsk.c | 5 +
samples/bpf/tcp_basertt_kern.c | 2 +-
samples/ftrace/ftrace-direct-too.c | 14 +-
scripts/Makefile.modfinal | 2 +-
scripts/mod/modpost.c | 86 +-
security/apparmor/policy_unpack.c | 9 +-
security/integrity/evm/evm_crypto.c | 2 +-
security/integrity/evm/evm_main.c | 4 +-
security/integrity/iint.c | 15 +-
security/integrity/ima/ima_modsig.c | 3 +
security/integrity/ima/ima_policy.c | 3 +-
sound/core/jack.c | 15 +-
sound/pci/ac97/ac97_codec.c | 4 +-
sound/pci/hda/patch_realtek.c | 1 +
sound/soc/codecs/es8316.c | 23 +-
sound/soc/fsl/imx-audmix.c | 9 +
sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 13 +-
tools/bpf/bpftool/feature.c | 24 +-
tools/lib/bpf/bpf_helpers.h | 15 +-
tools/lib/bpf/btf_dump.c | 22 +-
tools/perf/builtin-bench.c | 7 +-
tools/perf/builtin-script.c | 16 +-
tools/perf/tests/builtin-test.c | 3 +
tools/perf/util/dwarf-aux.c | 2 +-
tools/testing/selftests/bpf/prog_tests/check_mtu.c | 2 +-
tools/testing/selftests/net/mptcp/config | 1 +
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh | 9 +-
tools/testing/selftests/net/rtnetlink.sh | 1 +
.../rcutorture/configs/rcu/BUSTED-BOOST.boot | 2 +-
.../selftests/rcutorture/configs/rcu/TREE03.boot | 2 +-
.../selftests/vDSO/vdso_test_clock_getres.c | 4 +-
tools/testing/selftests/wireguard/netns.sh | 30 +-
518 files changed, 6687 insertions(+), 4483 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 6.4 198/292] drm/amd/display: Fix in secure display context creation
2023-07-21 16:01 1% [PATCH 6.4 000/292] 6.4.5-rc1 review Greg Kroah-Hartman
2023-07-21 16:02 7% ` [PATCH 6.4 052/292] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
@ 2023-07-21 16:05 5% ` Greg Kroah-Hartman
1 sibling, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-21 16:05 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Daniel Wheeler, Wayne Lin,
Rodrigo Siqueira, Alan Liu, Alex Deucher
From: Alan Liu <HaoPing.Liu@amd.com>
commit f477c7b5ec3e4ef87606671b340abf3bdb0cccff upstream.
[Why & How]
We need to store CRTC information in secure_display_ctx, so postpone
the call to amdgpu_dm_crtc_secure_display_create_contexts() until we
initialize all CRTCs.
Cc: stable@vger.kernel.org
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alan Liu <HaoPing.Liu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++++------
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 2 +-
2 files changed, 6 insertions(+), 7 deletions(-)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1776,12 +1776,6 @@ static int amdgpu_dm_init(struct amdgpu_
dc_init_callbacks(adev->dm.dc, &init_params);
}
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
- adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
- if (!adev->dm.secure_display_ctxs) {
- DRM_ERROR("amdgpu: failed to initialize secure_display_ctxs.\n");
- }
-#endif
if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
init_completion(&adev->dm.dmub_aux_transfer_done);
adev->dm.dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_KERNEL);
@@ -1840,6 +1834,11 @@ static int amdgpu_dm_init(struct amdgpu_
goto error;
}
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+ adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
+ if (!adev->dm.secure_display_ctxs)
+ DRM_ERROR("amdgpu: failed to initialize secure display contexts.\n");
+#endif
DRM_DEBUG_DRIVER("KMS initialized.\n");
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
@@ -100,7 +100,7 @@ struct secure_display_context *amdgpu_dm
#else
#define amdgpu_dm_crc_window_is_activated(x)
#define amdgpu_dm_crtc_handle_crc_window_irq(x)
-#define amdgpu_dm_crtc_secure_display_create_contexts()
+#define amdgpu_dm_crtc_secure_display_create_contexts(x)
#endif
#endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */
^ permalink raw reply [relevance 5%]
* [PATCH 6.4 052/292] net: bgmac: postpone turning IRQs off to avoid SoC hangs
2023-07-21 16:01 1% [PATCH 6.4 000/292] 6.4.5-rc1 review Greg Kroah-Hartman
@ 2023-07-21 16:02 7% ` Greg Kroah-Hartman
2023-07-21 16:05 5% ` [PATCH 6.4 198/292] drm/amd/display: Fix in secure display context creation Greg Kroah-Hartman
1 sibling, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-21 16:02 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rafał Miłecki,
Michal Kubiak, David S. Miller, Sasha Levin
From: Rafał Miłecki <rafal@milecki.pl>
[ Upstream commit e7731194fdf085f46d58b1adccfddbd0dfee4873 ]
Turning IRQs off is done by accessing Ethernet controller registers.
That can't be done until device's clock is enabled. It results in a SoC
hang otherwise.
This bug remained unnoticed for years as most bootloaders keep all
Ethernet interfaces turned on. It seems to only affect a niche SoC
family BCM47189. It has two Ethernet controllers but CFE bootloader uses
only the first one.
Fixes: 34322615cbaa ("net: bgmac: Mask interrupts during probe")
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Reviewed-by: Michal Kubiak <michal.kubiak@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/broadcom/bgmac.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 1761df8fb7f96..10c7c232cc4ec 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1492,8 +1492,6 @@ int bgmac_enet_probe(struct bgmac *bgmac)
bgmac->in_init = true;
- bgmac_chip_intrs_off(bgmac);
-
net_dev->irq = bgmac->irq;
SET_NETDEV_DEV(net_dev, bgmac->dev);
dev_set_drvdata(bgmac->dev, bgmac);
@@ -1511,6 +1509,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)
*/
bgmac_clk_enable(bgmac, 0);
+ bgmac_chip_intrs_off(bgmac);
+
/* This seems to be fixing IRQ by assigning OOB #6 to the core */
if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) {
if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
--
2.39.2
^ permalink raw reply related [relevance 7%]
* [PATCH 6.4 000/292] 6.4.5-rc1 review
@ 2023-07-21 16:01 1% Greg Kroah-Hartman
2023-07-21 16:02 7% ` [PATCH 6.4 052/292] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
2023-07-21 16:05 5% ` [PATCH 6.4 198/292] drm/amd/display: Fix in secure display context creation Greg Kroah-Hartman
0 siblings, 2 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-21 16:01 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, srw, rwarsow, conor
This is the start of the stable review cycle for the 6.4.5 release.
There are 292 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Sun, 23 Jul 2023 16:04:29 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.4.5-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.4.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 6.4.5-rc1
Mario Limonciello <mario.limonciello@amd.com>
Revert "drm/amd: Disable PSR-SU on Parade 0803 TCON"
Thomas Bogendoerfer <tsbogend@alpha.franken.de>
MIPS: kvm: Fix build error with KVM_MIPS_DEBUG_COP0_COUNTERS enabled
Dan Carpenter <dan.carpenter@linaro.org>
net: dsa: ocelot: unlock on error in vsc9959_qos_port_tas_set()
Dan Carpenter <dan.carpenter@linaro.org>
scsi: qla2xxx: Fix end of loop test
Manish Rangankar <mrangankar@marvell.com>
scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
Shreyas Deodhar <sdeodhar@marvell.com>
scsi: qla2xxx: Pointer may be dereferenced
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Correct the index of array
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
Bikash Hazarika <bhazarika@marvell.com>
scsi: qla2xxx: Fix potential NULL pointer dereference
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix buffer overrun
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Avoid fcport pointer dereference
Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Array index may go out of bound
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix mem access after free
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Wait for io return on terminate rport
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix hang in task management
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix task management cmd fail due to unavailable resource
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix task management cmd failure
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Multi-que support for TMF
Beau Belgrave <beaub@linux.microsoft.com>
tracing/user_events: Fix struct arg size match check
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails
Masami Hiramatsu (Google) <mhiramat@kernel.org>
Revert "tracing: Add "(fault)" name injection to kernel probes"
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix to update dynamic data counter if fetcharg uses it
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix not to count error code to total length
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix to avoid double count of the string length on the array
Gustavo A. R. Silva <gustavoars@kernel.org>
smb: client: Fix -Wstringop-overflow issues
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: pm_nl_ctl: fix 32-bit support
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: depend on SYN_COOKIES
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: userspace_pm: report errors with 'remove' tests
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: userspace_pm: use correct server port
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: sockopt: return error if wrong mark
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: connect: fail if nft supposed to work
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: sockopt: use 'iptables-legacy' if available
Paolo Abeni <pabeni@redhat.com>
mptcp: ensure subflow is unhashed before cleaning the backlog
Paolo Abeni <pabeni@redhat.com>
mptcp: do not rely on implicit state check in mptcp_listen()
Mateusz Stachyra <m.stachyra@samsung.com>
tracing: Fix null pointer dereference in tracing_err_log_open()
Masami Hiramatsu (Google) <mhiramat@kernel.org>
fprobe: Ensure running fprobe_exit_handler() finished before calling rethook_free()
Jiri Olsa <jolsa@kernel.org>
fprobe: Release rethook after the ftrace_ops is unregistered
Karol Wachowski <karol.wachowski@linux.intel.com>
accel/ivpu: Clear specific interrupt status bits on C0
Karol Wachowski <karol.wachowski@linux.intel.com>
accel/ivpu: Fix VPU register access in irq disable
Heiner Kallweit <hkallweit1@gmail.com>
pwm: meson: fix handling of period/duty if greater than UINT_MAX
Heiner Kallweit <hkallweit1@gmail.com>
pwm: meson: modify and simplify calculation in meson_pwm_get_state
Chungkai Yang <Chung-kai.Yang@mediatek.com>
PM: QoS: Restore support for default value on frequency QoS
Namhyung Kim <namhyung@kernel.org>
perf/x86: Fix lockdep warning in for_each_sibling_event() on SPR
Max Filippov <jcmvbkbc@gmail.com>
xtensa: ISS: fix call to split_if_spec
Bharath SM <bharathsm@microsoft.com>
cifs: if deferred close is disabled then close files immediately
Mario Limonciello <mario.limonciello@amd.com>
drm/amd/pm: conditionally disable pcie lane/speed switching for SMU13
Evan Quan <evan.quan@amd.com>
drm/amd/pm: share the code around SMU13 pcie parameters update
Zheng Yejian <zhengyejian1@huawei.com>
ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
Zheng Yejian <zhengyejian1@huawei.com>
ring-buffer: Fix deadloop issue on reading trace_pipe
Krister Johansen <kjlx@templeofstupid.com>
net: ena: fix shift-out-of-bounds in exponential backoff
Isaac J. Manjarres <isaacmanjarres@google.com>
regmap-irq: Fix out-of-bounds access when allocating config buffers
Eric Lin <eric.lin@sifive.com>
perf: RISC-V: Remove PERF_HES_STOPPED flag checking in riscv_pmu_start()
Florent Revest <revest@chromium.org>
samples: ftrace: Save required argument registers in sample trampolines
Christoph Hellwig <hch@lst.de>
nvme: don't reject probe due to duplicate IDs for single-ported PCIe devices
Zheng Yejian <zhengyejian1@huawei.com>
tracing: Fix memory leak of iter->temp when reading trace_pipe
Mohamed Khalfella <mkhalfella@purestorage.com>
tracing/histograms: Add histograms to hist_vars if they have referenced variables
Matthias Kaehlcke <mka@chromium.org>
dm: verity-loadpin: Add NULL pointer check for 'bdev' parameter
Heiko Carstens <hca@linux.ibm.com>
s390/decompressor: fix misaligned symbol build error
Jonas Gorski <jonas.gorski@gmail.com>
bus: ixp4xx: fix IXP4XX_EXP_T1_MASK
Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Revert "8250: add support for ASIX devices with a FIFO bug"
Sakari Ailus <sakari.ailus@linux.intel.com>
media: uapi: Fix [GS]_ROUTING ACTIVE flag value
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
soundwire: qcom: fix storing port config out-of-bounds
Stephan Gerhold <stephan.gerhold@kernkonzept.com>
opp: Fix use-after-free in lazy_opp_tables after probe deferral
George Stark <gnstark@sberdevices.ru>
meson saradc: fix clock divider mask length
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Show ZHAOXIN xHCI root hub speed correctly
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
xhci: Fix resume issue of some ZHAOXIN hosts
Oliver Upton <oliver.upton@linux.dev>
arm64: errata: Mitigate Ampere1 erratum AC03_CPU_38 at stage-2
Yinjun Zhang <yinjun.zhang@corigine.com>
nfp: clean mc addresses in application firmware when closing port
Xiubo Li <xiubli@redhat.com>
ceph: don't let check_caps skip sending responses for revoke msgs
Xiubo Li <xiubli@redhat.com>
ceph: fix blindly expanding the readahead windows
Xiubo Li <xiubli@redhat.com>
ceph: add a dedicated private data for netfs rreq
Ilya Dryomov <idryomov@gmail.com>
libceph: harden msgr2.1 frame segment length checks
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
Hui Li <caelli@tencent.com>
tty: fix hang on tty device with no_room set
Martin Fuzzey <martin.fuzzey@flowbird.group>
tty: serial: imx: fix rs485 rx after tx
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
Dan Carpenter <dan.carpenter@linaro.org>
serial: atmel: don't enable IRQs prematurely
Christian König <christian.koenig@amd.com>
drm/ttm: never consider pinned BOs for eviction&swap
Thomas Hellström <thomas.hellstrom@linux.intel.com>
drm/ttm: Don't leak a resource on swapout move error
Thomas Hellström <thomas.hellstrom@linux.intel.com>
drm/ttm: Don't leak a resource on eviction error
Yang Wang <kevinyang.wang@amd.com>
drm/amd/pm: fix smu i2c data read risk
gaba <gaba@amd.com>
drm/amdgpu: avoid restore process run into dead loop.
Aurabindo Pillai <aurabindo.pillai@amd.com>
drm/amd/display: Add monitor specific edid quirk
Mario Limonciello <mario.limonciello@amd.com>
drm/amd/display: Correct `DMUB_FW_VERSION` macro
Ilya Bakoulin <ilya.bakoulin@amd.com>
drm/amd/display: Fix 128b132b link loss handling
Sung-huai Wang <danny.wang@amd.com>
drm/amd/display: add a NULL pointer check
Mario Limonciello <mario.limonciello@amd.com>
drm/amd: Disable PSR-SU on Parade 0803 TCON
Samuel Pitoiset <samuel.pitoiset@gmail.com>
drm/amdgpu: fix clearing mappings for BOs that are always valid in VM
Leo Chen <sancchen@amd.com>
drm/amd/display: disable seamless boot if force_odm_combine is enabled
Austin Zheng <austin.zheng@amd.com>
drm/amd/display: Remove Phantom Pipe Check When Calculating K1 and K2
Hersen Wu <hersenxs.wu@amd.com>
drm/amd/display: edp do not add non-edid timings
Dmytro Laktyushkin <dmytro.laktyushkin@amd.com>
drm/amd/display: fix seamless odm transitions
Alan Liu <HaoPing.Liu@amd.com>
drm/amd/display: Fix in secure display context creation
Alvin Lee <Alvin.Lee2@amd.com>
drm/amd/display: Limit DCN32 8 channel or less parts to DPM1 for FPO
Wayne Lin <Wayne.Lin@amd.com>
drm/dp_mst: Clear MSG_RDY flag before sending new message
Brian Norris <briannorris@chromium.org>
drm/rockchip: vop: Leave vblank enabled in self-refresh
Brian Norris <briannorris@chromium.org>
drm/atomic: Allow vblank-enabled + self-refresh "disable"
Justin Tee <justin.tee@broadcom.com>
scsi: lpfc: Fix double free in lpfc_cmpl_els_logo_acc() caused by lpfc_nlp_not_used()
Alexander Aring <aahringo@redhat.com>
fs: dlm: fix missing pending to false
Alexander Aring <aahringo@redhat.com>
fs: dlm: clear pending bit when queue was empty
Alexander Aring <aahringo@redhat.com>
fs: dlm: fix mismatch of plock results from userspace
Alexander Aring <aahringo@redhat.com>
fs: dlm: make F_SETLK use unkillable wait_event
Alexander Aring <aahringo@redhat.com>
fs: dlm: interrupt posix locks only when process is killed
Alexander Aring <aahringo@redhat.com>
fs: dlm: fix cleanup pending ops when interrupted
Alexander Aring <aahringo@redhat.com>
fs: dlm: return positive pid value for F_GETLK
Jason Baron <jbaron@akamai.com>
md/raid0: add discard support for the 'original' layout
Johan Hovold <johan+linaro@kernel.org>
mfd: pm8008: Fix module autoloading
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Re-init completion for every test
Damien Le Moal <dlemoal@kernel.org>
misc: pci_endpoint_test: Free IRQs before removing the device
Damien Le Moal <dlemoal@kernel.org>
PCI: rockchip: Set address alignment for endpoint mode
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Use u32 variable to access 32-bit registers
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Write PCI Device ID to correct register
Rick Wertenbroek <rick.wertenbroek@gmail.com>
PCI: rockchip: Assert PCI Configuration Enable bit after probe
Damien Le Moal <dlemoal@kernel.org>
PCI: epf-test: Fix DMA transfer completion detection
Damien Le Moal <dlemoal@kernel.org>
PCI: epf-test: Fix DMA transfer completion initialization
Manivannan Sadhasivam <mani@kernel.org>
PCI: qcom: Disable write access to read only registers for IP v2.3.3
Igor Mammedov <imammedo@redhat.com>
PCI: acpiphp: Reassign resources on bridge if necessary
Robin Murphy <robin.murphy@arm.com>
PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
Ross Lagerwall <ross.lagerwall@citrix.com>
PCI: Release resource invalidated by coalescing
Ondrej Zary <linux@zary.sk>
PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: do not retry administrative requests
Sathya Prakash <sathya.prakash@broadcom.com>
scsi: mpi3mr: Propagate sense data for admin queue SCSI I/O
Mikulas Patocka <mpatocka@redhat.com>
dm integrity: reduce vmalloc space footprint on 32-bit architectures
Martin Kaiser <martin@kaiser.cx>
hwrng: imx-rngc - fix the timeout for init and self check
Sinthu Raja <sinthu.raja@ti.com>
arm64: dts: ti: k3-j721s2: Fix wkup pinmux range
Frank Wunderlich <frank-w@public-files.de>
arm64: dts: mt7986: use size of reserved partition for bl2
Siddh Raman Pant <code@siddh.me>
jfs: jfs_dmap: Validate db_l2nbperpage while mounting
Ritesh Harjani (IBM) <ritesh.list@gmail.com>
ext2/dax: Fix ext2_setsize when len is page aligned
Christian Marangi <ansuelsmth@gmail.com>
soc: qcom: mdt_loader: Fix unconditional call to scm_pas_mem_setup
David Woodhouse <dwmw@amazon.co.uk>
mm/mmap: Fix error return in do_vmi_align_munmap()
Alexander Aring <aahringo@redhat.com>
fs: dlm: revert check required context while close
Baokun Li <libaokun1@huawei.com>
ext4: only update i_reserved_data_blocks on successful block allocation
Baokun Li <libaokun1@huawei.com>
ext4: turn quotas off if mount failed after enabling quotas
Chao Yu <chao@kernel.org>
ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
Theodore Ts'o <tytso@mit.edu>
ext4: avoid updating the superblock on a r/o mount if not needed
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_new_blocks
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: get block from bh in ext4_free_blocks for fast commit replay
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: fix wrong unit use in ext4_mb_clear_bb
Zhihao Cheng <chengzhihao1@huawei.com>
ext4: Fix reusing stale buffer heads from last failed mounting
Huacai Chen <chenhuacai@kernel.org>
MIPS: KVM: Fix NULL pointer dereference
Huacai Chen <chenhuacai@kernel.org>
MIPS: Loongson: Fix build error when make modules_install
Huacai Chen <chenhuacai@kernel.org>
MIPS: Loongson: Fix cpu_probe_loongson() again
Jiaxun Yang <jiaxun.yang@flygoat.com>
MIPS: cpu-features: Use boot_cpu_type for CPU type based features
Hamza Mahfooz <hamza.mahfooz@amd.com>
drm/amd/display: perform a bounds check before filling dirty rectangles
Michael Ellerman <mpe@ellerman.id.au>
powerpc/64s: Fix native_hpte_remove() to be irq-safe
Michael Ellerman <mpe@ellerman.id.au>
powerpc/security: Fix Speculation_Store_Bypass reporting on Power10
Ekansh Gupta <quic_ekangupt@quicinc.com>
misc: fastrpc: Create fastrpc scalar with correct buffer count
Naveen N Rao <naveen@kernel.org>
powerpc: Fail build if using recordmcount with binutils v2.37
sunliming <sunliming@kylinos.cn>
tracing/user_events: Fix incorrect return value for writing operation when events are disabled
Andrey Konovalov <andreyknvl@gmail.com>
kasan: fix type cast in memory_is_poisoned_n
Andrey Konovalov <andreyknvl@gmail.com>
kasan, slub: fix HW_TAGS zeroing with slub_debug
Arnd Bergmann <arnd@arndb.de>
kasan: use internal prototypes matching gcc-13 builtins
Arnd Bergmann <arnd@arndb.de>
kasan: add kasan_tag_mismatch prototype
Oleksij Rempel <linux@rempel-privat.de>
net: phy: dp83td510: fix kernel stall during netboot in DP83TD510E PHY driver
Florian Fainelli <florian.fainelli@broadcom.com>
net: bcmgenet: Ensure MDIO unregistration has clocks enabled
Arseniy Krasnov <AVKrasnov@sberdevices.ru>
mtd: rawnand: meson: fix unaligned DMA buffers handling
Florian Bezdeka <florian@bezdeka.de>
tpm/tpm_tis: Disable interrupts for Lenovo L590 devices
Lino Sanfilippo <l.sanfilippo@kunbus.com>
tpm,tpm_tis: Disable interrupts after 1000 unhandled IRQs
Christian Hesse <mail@eworm.de>
tpm/tpm_tis: Disable interrupts for Framework Laptop Intel 13th gen
Jerry Snitselaar <jsnitsel@redhat.com>
tpm: return false from tpm_amd_is_rng_defective on non-x86 platforms
Alexander Sverdlin <alexander.sverdlin@siemens.com>
tpm: tis_i2c: Limit write bursts to I2C_SMBUS_BLOCK_MAX (32) bytes
Christian Hesse <mail@eworm.de>
tpm/tpm_tis: Disable interrupts for Framework Laptop Intel 12th gen
Alexander Sverdlin <alexander.sverdlin@siemens.com>
tpm: tis_i2c: Limit read bursts to I2C_SMBUS_BLOCK_MAX (32) bytes
Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
tpm: tpm_tis: Disable interrupts *only* for AEON UPX-i11
Jarkko Sakkinen <jarkko@kernel.org>
tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
Valentin David <valentin.david@gmail.com>
tpm: Do not remap from ACPI resources again for Pluton TPM
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Unify debounce handling into amd_pinconf_set()
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Drop pull up select configuration
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Use amd_pinconf_set() for all config options
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Only use special debounce behavior for GPIO 0
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Revert "pinctrl: amd: disable and mask interrupts on probe"
Kornel Dulęba <korneld@chromium.org>
pinctrl: amd: Detect and mask spurious interrupts
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Fix mistake in handling clearing pins at startup
Mario Limonciello <mario.limonciello@amd.com>
pinctrl: amd: Detect internal GPIO0 debounce handling
Masahiro Yamada <masahiroy@kernel.org>
kbuild: make modules_install copy modules.builtin(.modinfo)
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: fix deadlock in i_xattr_sem and inode page lock
Chao Yu <chao@kernel.org>
f2fs: don't reset unchangable mount option in f2fs_remount()
Thomas Zimmermann <tzimmermann@suse.de>
drm/client: Send hotplug event after registering a client
Paulo Alcantara <pc@manguebit.com>
smb: client: fix parsing of source mount option
Winston Wen <wentao@uniontech.com>
cifs: fix session state check in smb2_find_smb_ses
Paulo Alcantara <pc@manguebit.com>
smb: client: improve DFS mount check
Ming Lei <ming.lei@redhat.com>
nvme-pci: fix DMA direction of unmapping integrity data
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: account for stab overhead in qfq_enqueue
Pedro Tammela <pctammela@mojatatu.com>
net/sched: sch_qfq: reintroduce lmax bound check for MTU
Zhang Shurong <zhang_shurong@foxmail.com>
wifi: rtw89: debug: fix error code in rtw89_debug_priv_send_h2c_set()
Jiawen Wu <jiawenwu@trustnetic.com>
net: txgbe: fix eeprom calculation error
Pedro Tammela <pctammela@mojatatu.com>
net/sched: make psched_mtu() RTNL-less safe
Karol Herbst <kherbst@redhat.com>
drm/nouveau: bring back blit subchannel for pre nv50 GPUs
Karol Herbst <kherbst@redhat.com>
drm/nouveau/acr: Abort loading ACR if no firmware was found
Dan Carpenter <dan.carpenter@linaro.org>
netdevsim: fix uninitialized data in nsim_dev_trap_fa_cookie_write()
Karol Herbst <kherbst@redhat.com>
drm/nouveau/disp/g94: enable HDMI
Karol Herbst <kherbst@redhat.com>
drm/nouveau/disp: fix HDMI on gt215+
Jisheng Zhang <jszhang@kernel.org>
riscv: mm: fix truncation warning on RV32
Ido Schimmel <idosch@nvidia.com>
net/sched: flower: Ensure both minimum and maximum ports are specified
Larysa Zaremba <larysa.zaremba@intel.com>
xdp: use trusted arguments in XDP hints kfuncs
Pu Lehui <pulehui@huawei.com>
bpf: cpumap: Fix memory leak in cpu_map_update_elem
Randy Dunlap <rdunlap@infradead.org>
wifi: airo: avoid uninitialized warning in airo_get_rate()
Xin Yin <yinxin.x@bytedance.com>
erofs: fix fsdax unavailability for chunk-based regular files
Chunhai Guo <guochunhai@vivo.com>
erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
Chunhai Guo <guochunhai@vivo.com>
erofs: avoid useless loops in z_erofs_pcluster_readmore() when reading beyond EOF
Suman Ghosh <sumang@marvell.com>
octeontx2-pf: Add additional check for MCAM rules
Lu Hongfei <luhongfei@vivo.com>
net: dsa: Removed unneeded of_node_put in felix_parse_ports_node
Tvrtko Ursulin <tvrtko.ursulin@intel.com>
drm/i915: Fix one wrong caching mode enum usage
Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
drm/i915: Don't preserve dpll_hw_state for slave crtc in Bigjoiner
Wei Fang <wei.fang@nxp.com>
net: fec: increase the size of tx ring and update tx_wake_threshold
Wei Fang <wei.fang@nxp.com>
net: fec: recycle pages for transmitted XDP frames
Wei Fang <wei.fang@nxp.com>
net: fec: remove last_bdp from fec_enet_txq_xmit_frame()
Wei Fang <wei.fang@nxp.com>
net: fec: remove useless fec_enet_reset_skb()
Björn Töpel <bjorn@rivosinc.com>
riscv, bpf: Fix inconsistent JIT image generation
Stafford Horne <shorne@gmail.com>
openrisc: Union fpcsr and oldmask in sigcontext to unbreak userspace ABI
Ankit Kumar <ankit.kumar@samsung.com>
nvme: fix the NVME_ID_NS_NVM_STS_MASK definition
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix inserting of empty frame for launchtime
Florian Kauer <florian.kauer@linutronix.de>
igc: Fix launchtime before start of cycle
Florian Kauer <florian.kauer@linutronix.de>
igc: No strict mode in pure launchtime/CBS offload
Ze Gao <zegao2021@gmail.com>
fprobe: add unlock to match a succeeded ftrace_test_recursion_trylock
Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
kernel/trace: Fix cleanup logic of enable_trace_eprobe
Florian Kauer <florian.kauer@linutronix.de>
igc: Handle already enabled taprio offload for basetime 0
Florian Kauer <florian.kauer@linutronix.de>
igc: Do not enable taprio offload for invalid arguments
Florian Kauer <florian.kauer@linutronix.de>
igc: Rename qbv_enable to taprio_offload_enable
Vladimir Oltean <vladimir.oltean@nxp.com>
net/sched: taprio: replace tc_taprio_qopt_offload :: enable with a "cmd" enum
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
platform/x86: wmi: Break possible infinite loop when parsing GUID
Peter Zijlstra <peterz@infradead.org>
x86/fineibt: Poison ENDBR at +0
Jiasheng Jiang <jiasheng@iscas.ac.cn>
net: dsa: qca8k: Add check for skb_copy
Arnd Bergmann <arnd@arndb.de>
HID: hyperv: avoid struct memcpy overrun warning
Ziyang Xuan <william.xuanziyang@huawei.com>
ipv6/addrconf: fix a potential refcount underflow for idev
Jiasheng Jiang <jiasheng@iscas.ac.cn>
NTB: ntb_tool: Add check for devm_kcalloc
Yang Yingliang <yangyingliang@huawei.com>
NTB: ntb_transport: fix possible memory leak while device_register() fails
Yuan Can <yuancan@huawei.com>
ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
Yuan Can <yuancan@huawei.com>
ntb: idt: Fix error handling in idt_pci_driver_init()
Eric Dumazet <edumazet@google.com>
udp6: fix udp6_ehashfn() typo
Kuniyuki Iwashima <kuniyu@amazon.com>
icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
Niklas Schnelle <schnelle@linux.ibm.com>
s390/ism: Do not unregister clients with registered DMBs
Niklas Schnelle <schnelle@linux.ibm.com>
s390/ism: Fix and simplify add()/remove() callback handling
Niklas Schnelle <schnelle@linux.ibm.com>
s390/ism: Fix locking for forwarding of IRQs and events to clients
Paolo Abeni <pabeni@redhat.com>
net: prevent skb corruption on frag list segmentation
Rafał Miłecki <rafal@milecki.pl>
net: bgmac: postpone turning IRQs off to avoid SoC hangs
Ivan Babrou <ivan@cloudflare.com>
udp6: add a missing call into udp_fail_queue_rcv_skb tracepoint
Nitya Sunkad <nitya.sunkad@amd.com>
ionic: remove WARN_ON to prevent panic_on_warn
Sai Krishna <saikrishnag@marvell.com>
octeontx2-af: Move validation of ptp pointer before its usage
Ratheesh Kannoth <rkannoth@marvell.com>
octeontx2-af: Promisc enable/disable through mbox
Geert Uytterhoeven <geert+renesas@glider.be>
drm/fbdev-dma: Fix documented default preferred_bpp value
Junfeng Guo <junfeng.guo@intel.com>
gve: Set default duplex configuration to full
M A Ramdhan <ramdhan@starlabs.sg>
net/sched: cls_fw: Fix improper refcount update leads to use-after-free
Vladimir Oltean <vladimir.oltean@nxp.com>
net: mscc: ocelot: fix oversize frame dropping for preemptible TCs
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: make vsc9959_tas_guard_bands_update() visible to ocelot->ops
Klaus Kudielka <klaus.kudielka@gmail.com>
net: mvneta: fix txq_map in case of txq_number==1
Kumar Kartikeya Dwivedi <memxor@gmail.com>
bpf: Fix max stack depth check for async callbacks
Randy Dunlap <rdunlap@infradead.org>
scsi: ufs: ufs-mediatek: Add dependency for RESET_CONTROLLER
Dan Carpenter <dan.carpenter@linaro.org>
scsi: qla2xxx: Fix error code in qla2x00_start_sp()
Eric Biggers <ebiggers@google.com>
blk-crypto: use dynamic lock class for blk_crypto_profile::lock
Aravindhan Gunasekaran <aravindhan.gunasekaran@intel.com>
igc: Handle PPS start time programming for past time values
Tan Tee Min <tee.min.tan@linux.intel.com>
igc: Include the length/type field and VLAN tag in queueMaxSDU
Prasad Koya <prasad@arista.com>
igc: set TP bit in 'supported' and 'advertising' fields of ethtool_link_ksettings
Dragos Tatulea <dtatulea@nvidia.com>
net/mlx5e: RX, Fix page_pool page fragment tracking for XDP
Maher Sanalla <msanalla@nvidia.com>
net/mlx5: Query hca_cap_2 only when supported
Yevgeny Kliteynik <kliteyn@nvidia.com>
net/mlx5e: TC, CT: Offload ct clear only once
Vlad Buslov <vladbu@nvidia.com>
net/mlx5e: Check for NOT_READY flag state after locking
Saeed Mahameed <saeedm@nvidia.com>
net/mlx5: Register a unique thermal zone per device
Dragos Tatulea <dtatulea@nvidia.com>
net/mlx5e: RX, Fix flush and close release flow of regular rq for legacy rq
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix memory leak in mlx5e_ptp_open
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix memory leak in mlx5e_fs_tt_redirect_any_create
Zhengchao Shao <shaozhengchao@huawei.com>
net/mlx5e: fix double free in mlx5e_destroy_flow_table
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix TX Hang issue when QBV Gate is closed
Jesper Dangaard Brouer <brouer@redhat.com>
igc: Add XDP hints kfuncs for RX hash
Jesper Dangaard Brouer <brouer@redhat.com>
igc: Add igc_xdp_buff wrapper for xdp_buff in driver
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Remove delay during TX ring configuration
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Add condition for qbv_config_change_errors counter
Sridhar Samudrala <sridhar.samudrala@intel.com>
ice: Fix tx queue rate limit when TCs are configured
Sridhar Samudrala <sridhar.samudrala@intel.com>
ice: Fix max_rate check while configuring TX rate limits
Florian Westphal <fw@strlen.de>
netfilter: conntrack: don't fold port numbers into addresses before hashing
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: report use refcount overflow
Petr Pavlu <petr.pavlu@suse.com>
xen/virtio: Fix NULL deref when a bridge of PCI root bus has no parent
Marek Vasut <marex@denx.de>
drm/panel: simple: Add Powertip PH800480T013 drm_display_mode flags
Petr Tesarik <petr.tesarik.ext@huawei.com>
swiotlb: reduce the number of areas to match actual memory pool size
Petr Tesarik <petr.tesarik.ext@huawei.com>
swiotlb: always set the number of areas before allocating the pool
Douglas Anderson <dianders@chromium.org>
drm/bridge: ti-sn65dsi86: Fix auxiliary bus lifetime
Adrián Larumbe <adrian.larumbe@collabora.com>
drm: bridge: dw_hdmi: fix connector access for scdc
Fabio Estevam <festevam@denx.de>
drm/panel: simple: Add connector_type for innolux_at043tn24
Namjae Jeon <linkinjeon@kernel.org>
ksmbd: fix out of bounds read in smb2_sess_setup
Namjae Jeon <linkinjeon@kernel.org>
ksmbd: add missing compound request handing in some commands
Simon Horman <horms@kernel.org>
net: lan743x: select FIXED_PHY
Moritz Fischer <moritzf@google.com>
net: lan743x: Don't sleep in atomic context
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Fix for shift-out-of-bounds
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Rename the float32 variable
Dmitry Torokhov <dmitry.torokhov@gmail.com>
HID: input: fix mapping for camera access keys
Nayna Jain <nayna@linux.ibm.com>
security/integrity: fix pointer to ESL data and its size on pseries
Ivan Mikhaylov <fr0st61te@gmail.com>
net/ncsi: change from ndo_set_mac_address to dev_set_mac_address
-------------
Diffstat:
Documentation/arm64/silicon-errata.rst | 3 +
.../media/v4l/vidioc-subdev-g-routing.rst | 2 +-
Makefile | 30 ++-
arch/arm64/Kconfig | 19 ++
.../dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 7 +-
arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts | 42 ++--
.../boot/dts/ti/k3-j721s2-common-proc-board.dts | 76 +++---
arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi | 29 ++-
arch/arm64/kernel/cpu_errata.c | 7 +
arch/arm64/kernel/traps.c | 2 +-
arch/arm64/kvm/hyp/pgtable.c | 14 +-
arch/arm64/mm/fault.c | 2 +-
arch/arm64/tools/cpucaps | 1 +
arch/mips/Makefile | 10 +-
arch/mips/include/asm/cpu-features.h | 4 +-
arch/mips/include/asm/kvm_host.h | 6 +-
arch/mips/kernel/cpu-probe.c | 9 +-
arch/mips/kvm/emulate.c | 22 +-
arch/mips/kvm/mips.c | 16 +-
arch/mips/kvm/stats.c | 4 +-
arch/mips/kvm/trace.h | 8 +-
arch/mips/kvm/vz.c | 20 +-
arch/openrisc/include/uapi/asm/sigcontext.h | 6 +-
arch/openrisc/kernel/signal.c | 4 +-
arch/powerpc/Makefile | 8 +
arch/powerpc/kernel/security.c | 37 +--
arch/powerpc/mm/book3s64/hash_native.c | 13 +-
arch/riscv/mm/init.c | 2 +-
arch/riscv/net/bpf_jit.h | 6 +-
arch/riscv/net/bpf_jit_core.c | 19 +-
arch/s390/Makefile | 1 +
arch/x86/events/intel/core.c | 7 +
arch/x86/kernel/alternative.c | 16 ++
arch/xtensa/platforms/iss/network.c | 2 +-
block/blk-crypto-profile.c | 12 +-
drivers/accel/ivpu/ivpu_drv.h | 1 +
drivers/accel/ivpu/ivpu_hw_mtl.c | 20 +-
drivers/base/regmap/regmap-irq.c | 2 +-
drivers/bus/intel-ixp4xx-eb.c | 2 +-
drivers/char/hw_random/imx-rngc.c | 6 +-
drivers/char/tpm/tpm-chip.c | 7 +
drivers/char/tpm/tpm_crb.c | 19 +-
drivers/char/tpm/tpm_tis.c | 25 ++
drivers/char/tpm/tpm_tis_core.c | 103 ++++++--
drivers/char/tpm/tpm_tis_core.h | 4 +
drivers/char/tpm/tpm_tis_i2c.c | 59 +++--
drivers/char/tpm/tpm_vtpm_proxy.c | 30 +--
drivers/firmware/stratix10-svc.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 12 +
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 64 ++---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 2 +-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 26 +++
drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +
.../drm/amd/display/dc/dce112/dce112_resource.c | 10 +-
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 11 +
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 4 -
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 2 +-
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h | 1 +
.../gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 2 +
.../gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 15 ++
.../gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h | 2 +
.../dc/link/protocols/link_dp_irq_handler.c | 11 +-
drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 +-
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 4 +
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 2 +-
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2 +-
.../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 +-
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 2 +-
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 67 ++++++
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 35 +--
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 2 +-
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 33 +--
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 9 +-
drivers/gpu/drm/bridge/ti-sn65dsi86.c | 35 +--
drivers/gpu/drm/display/drm_dp_mst_topology.c | 54 ++++-
drivers/gpu/drm/drm_atomic_helper.c | 11 +-
drivers/gpu/drm/drm_client.c | 21 ++
drivers/gpu/drm/drm_fbdev_dma.c | 6 +-
drivers/gpu/drm/drm_fbdev_generic.c | 4 -
drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 -
drivers/gpu/drm/gma500/fbdev.c | 4 -
drivers/gpu/drm/i915/display/intel_display.c | 1 -
drivers/gpu/drm/i915/display/intel_dp.c | 7 +-
drivers/gpu/drm/i915/gt/intel_gtt.c | 2 +-
drivers/gpu/drm/msm/msm_fbdev.c | 4 -
drivers/gpu/drm/nouveau/dispnv50/disp.c | 12 +-
drivers/gpu/drm/nouveau/nouveau_chan.c | 1 +
drivers/gpu/drm/nouveau/nouveau_chan.h | 1 +
drivers/gpu/drm/nouveau/nouveau_drm.c | 20 +-
drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c | 1 +
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c | 2 +-
drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 2 +-
drivers/gpu/drm/omapdrm/omap_fbdev.c | 4 -
drivers/gpu/drm/panel/panel-simple.c | 2 +
drivers/gpu/drm/radeon/radeon_fbdev.c | 4 -
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 +-
drivers/gpu/drm/tegra/fbdev.c | 4 -
drivers/gpu/drm/ttm/ttm_bo.c | 29 ++-
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c | 30 ++-
drivers/hid/hid-hyperv.c | 10 +-
drivers/hid/hid-input.c | 7 +-
drivers/iio/adc/meson_saradc.c | 2 +-
drivers/md/dm-integrity.c | 4 +-
drivers/md/dm-verity-loadpin.c | 3 +
drivers/md/raid0.c | 62 ++++-
drivers/md/raid0.h | 1 +
drivers/mfd/qcom-pm8008.c | 1 +
drivers/misc/fastrpc.c | 2 +-
drivers/misc/pci_endpoint_test.c | 10 +-
drivers/mtd/nand/raw/meson_nand.c | 4 +
drivers/net/dsa/hirschmann/hellcreek.c | 14 +-
drivers/net/dsa/ocelot/felix.c | 6 +-
drivers/net/dsa/ocelot/felix.h | 1 -
drivers/net/dsa/ocelot/felix_vsc9959.c | 28 ++-
drivers/net/dsa/qca/qca8k-8xxx.c | 3 +
drivers/net/dsa/sja1105/sja1105_tas.c | 7 +-
drivers/net/ethernet/amazon/ena/ena_com.c | 3 +
drivers/net/ethernet/broadcom/bgmac.c | 4 +-
drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +
drivers/net/ethernet/engleder/tsnep_selftests.c | 12 +-
drivers/net/ethernet/engleder/tsnep_tc.c | 4 +-
drivers/net/ethernet/freescale/enetc/enetc_qos.c | 6 +-
drivers/net/ethernet/freescale/fec.h | 17 +-
drivers/net/ethernet/freescale/fec_main.c | 178 ++++++++------
drivers/net/ethernet/google/gve/gve_ethtool.c | 3 +
drivers/net/ethernet/intel/ice/ice_main.c | 23 +-
drivers/net/ethernet/intel/ice/ice_tc_lib.c | 22 +-
drivers/net/ethernet/intel/ice/ice_tc_lib.h | 1 +
drivers/net/ethernet/intel/igc/igc.h | 15 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 2 +
drivers/net/ethernet/intel/igc/igc_main.c | 158 ++++++++++---
drivers/net/ethernet/intel/igc/igc_ptp.c | 25 +-
drivers/net/ethernet/intel/igc/igc_tsn.c | 68 ++++--
drivers/net/ethernet/marvell/mvneta.c | 4 +-
drivers/net/ethernet/marvell/octeontx2/af/ptp.c | 19 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 2 +-
.../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 11 +-
.../ethernet/marvell/octeontx2/af/rvu_npc_hash.c | 23 +-
.../ethernet/marvell/octeontx2/nic/otx2_flows.c | 8 +
.../net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 15 ++
.../mellanox/mlx5/core/en/fs_tt_redirect.c | 6 +-
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c | 6 +-
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 14 +-
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h | 1 +
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c | 3 +-
.../ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 44 ++--
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +-
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 3 +
drivers/net/ethernet/mellanox/mlx5/core/thermal.c | 19 +-
drivers/net/ethernet/microchip/Kconfig | 2 +-
drivers/net/ethernet/microchip/lan743x_main.c | 21 +-
.../net/ethernet/microchip/lan966x/lan966x_tc.c | 10 +-
drivers/net/ethernet/mscc/ocelot_mm.c | 7 +-
.../net/ethernet/netronome/nfp/nfp_net_common.c | 5 +
drivers/net/ethernet/pensando/ionic/ionic_lif.c | 5 -
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 7 +-
drivers/net/ethernet/ti/am65-cpsw-qos.c | 11 +-
drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c | 3 -
drivers/net/netdevsim/dev.c | 9 +-
drivers/net/phy/dp83td510.c | 23 +-
drivers/net/wireless/cisco/airo.c | 5 +-
drivers/net/wireless/realtek/rtw89/debug.c | 5 +-
drivers/ntb/hw/amd/ntb_hw_amd.c | 7 +-
drivers/ntb/hw/idt/ntb_hw_idt.c | 7 +-
drivers/ntb/hw/intel/ntb_hw_gen1.c | 7 +-
drivers/ntb/ntb_transport.c | 2 +-
drivers/ntb/test/ntb_tool.c | 2 +
drivers/nvme/host/core.c | 36 ++-
drivers/nvme/host/pci.c | 2 +-
drivers/opp/core.c | 3 +
drivers/pci/controller/dwc/pcie-qcom.c | 2 +
drivers/pci/controller/pcie-rockchip-ep.c | 65 ++----
drivers/pci/controller/pcie-rockchip.c | 17 ++
drivers/pci/controller/pcie-rockchip.h | 11 +-
drivers/pci/endpoint/functions/pci-epf-test.c | 40 +++-
drivers/pci/hotplug/acpiphp_glue.c | 5 +-
drivers/pci/pci.c | 10 +-
drivers/pci/probe.c | 4 +-
drivers/pci/quirks.c | 2 +
drivers/perf/riscv_pmu.c | 3 -
drivers/pinctrl/pinctrl-amd.c | 103 +++-----
drivers/pinctrl/pinctrl-amd.h | 2 +-
drivers/platform/x86/wmi.c | 22 +-
drivers/pwm/pwm-meson.c | 28 +--
drivers/s390/crypto/zcrypt_msgtype6.c | 6 +
drivers/s390/net/ism_drv.c | 139 ++++++-----
drivers/scsi/lpfc/lpfc_crtn.h | 1 -
drivers/scsi/lpfc/lpfc_els.c | 30 +--
drivers/scsi/lpfc/lpfc_hbadisc.c | 24 +-
drivers/scsi/mpi3mr/mpi3mr_fw.c | 5 +
drivers/scsi/qla2xxx/qla_attr.c | 13 ++
drivers/scsi/qla2xxx/qla_bsg.c | 6 +
drivers/scsi/qla2xxx/qla_def.h | 22 +-
drivers/scsi/qla2xxx/qla_edif.c | 4 +-
drivers/scsi/qla2xxx/qla_gbl.h | 2 +-
drivers/scsi/qla2xxx/qla_init.c | 258 +++++++++++++++++++--
drivers/scsi/qla2xxx/qla_inline.h | 5 +-
drivers/scsi/qla2xxx/qla_iocb.c | 38 ++-
drivers/scsi/qla2xxx/qla_isr.c | 64 ++++-
drivers/scsi/qla2xxx/qla_nvme.c | 3 -
drivers/scsi/qla2xxx/qla_os.c | 133 ++++++-----
drivers/soc/qcom/mdt_loader.c | 16 +-
drivers/soundwire/qcom.c | 3 +-
drivers/tty/n_tty.c | 25 +-
drivers/tty/serial/8250/8250.h | 1 -
drivers/tty/serial/8250/8250_pci.c | 19 --
drivers/tty/serial/8250/8250_port.c | 11 +-
drivers/tty/serial/atmel_serial.c | 4 +-
drivers/tty/serial/imx.c | 18 +-
drivers/tty/serial/samsung_tty.c | 14 +-
drivers/ufs/host/Kconfig | 1 +
drivers/usb/host/xhci-mem.c | 39 +++-
drivers/usb/host/xhci-pci.c | 12 +
drivers/usb/host/xhci.h | 2 +
drivers/xen/grant-dma-ops.c | 2 +
fs/ceph/addr.c | 85 +++++--
fs/ceph/caps.c | 9 +
fs/ceph/super.h | 13 ++
fs/dlm/ast.c | 8 +-
fs/dlm/lockspace.c | 12 -
fs/dlm/lockspace.h | 1 -
fs/dlm/lowcomms.c | 1 +
fs/dlm/midcomms.c | 3 -
fs/dlm/plock.c | 115 +++++----
fs/erofs/inode.c | 3 +-
fs/erofs/zdata.c | 4 +-
fs/ext2/inode.c | 5 +-
fs/ext4/indirect.c | 8 +
fs/ext4/inode.c | 10 -
fs/ext4/ioctl.c | 5 +-
fs/ext4/mballoc.c | 17 +-
fs/ext4/super.c | 31 ++-
fs/f2fs/dir.c | 9 +-
fs/f2fs/super.c | 30 ++-
fs/f2fs/xattr.c | 6 +-
fs/jfs/jfs_dmap.c | 6 +
fs/jfs/jfs_filsys.h | 2 +
fs/smb/client/cifs_dfs_ref.c | 20 +-
fs/smb/client/cifsproto.h | 2 +
fs/smb/client/cifssmb.c | 2 +-
fs/smb/client/dfs.c | 43 +---
fs/smb/client/file.c | 4 +-
fs/smb/client/fs_context.c | 59 ++++-
fs/smb/client/misc.c | 17 +-
fs/smb/client/smb2transport.c | 7 +
fs/smb/server/smb2pdu.c | 109 +++++----
include/drm/display/drm_dp_mst_helper.h | 7 +-
include/linux/blk-crypto-profile.h | 1 +
include/linux/ism.h | 7 +-
include/linux/kasan.h | 2 +-
include/linux/nvme.h | 2 +-
include/linux/rethook.h | 1 +
include/linux/serial_8250.h | 1 -
include/net/netfilter/nf_conntrack_tuple.h | 3 +
include/net/netfilter/nf_tables.h | 31 ++-
include/net/pkt_sched.h | 9 +-
include/soc/mscc/ocelot.h | 1 +
kernel/bpf/cpumap.c | 40 ++--
kernel/bpf/verifier.c | 5 +-
kernel/dma/swiotlb.c | 46 +++-
kernel/power/qos.c | 9 +-
kernel/trace/fprobe.c | 15 +-
kernel/trace/ftrace.c | 45 ++--
kernel/trace/rethook.c | 13 ++
kernel/trace/ring_buffer.c | 24 +-
kernel/trace/trace.c | 3 +-
kernel/trace/trace.h | 2 +
kernel/trace/trace_eprobe.c | 18 +-
kernel/trace/trace_events_hist.c | 8 +-
kernel/trace/trace_events_user.c | 6 +-
kernel/trace/trace_probe.c | 2 +-
kernel/trace/trace_probe_kernel.h | 30 +--
kernel/trace/trace_probe_tmpl.h | 10 +-
kernel/trace/trace_uprobe.c | 3 +-
mm/kasan/common.c | 2 +-
mm/kasan/generic.c | 73 +++---
mm/kasan/kasan.h | 171 +++++++-------
mm/kasan/report.c | 17 +-
mm/kasan/report_generic.c | 12 +-
mm/kasan/report_hw_tags.c | 2 +-
mm/kasan/report_sw_tags.c | 2 +-
mm/kasan/shadow.c | 36 +--
mm/kasan/sw_tags.c | 20 +-
mm/mmap.c | 9 +-
mm/slab.h | 16 +-
net/ceph/messenger_v2.c | 41 ++--
net/core/net-traces.c | 2 +
net/core/skbuff.c | 5 +
net/core/xdp.c | 2 +-
net/ipv6/addrconf.c | 3 +-
net/ipv6/icmp.c | 5 +-
net/ipv6/udp.c | 4 +-
net/mptcp/protocol.c | 7 +-
net/ncsi/ncsi-rsp.c | 5 +-
net/netfilter/nf_conntrack_core.c | 20 +-
net/netfilter/nf_tables_api.c | 163 ++++++++-----
net/netfilter/nft_flow_offload.c | 6 +-
net/netfilter/nft_immediate.c | 8 +-
net/netfilter/nft_objref.c | 8 +-
net/sched/cls_flower.c | 10 +
net/sched/cls_fw.c | 10 +-
net/sched/sch_qfq.c | 18 +-
net/sched/sch_taprio.c | 4 +-
samples/ftrace/ftrace-direct-too.c | 14 +-
security/integrity/platform_certs/load_powerpc.c | 40 ++--
tools/testing/selftests/net/mptcp/config | 1 +
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 3 +
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh | 29 +--
tools/testing/selftests/net/mptcp/pm_nl_ctl.c | 10 +-
tools/testing/selftests/net/mptcp/userspace_pm.sh | 4 +-
312 files changed, 3504 insertions(+), 1921 deletions(-)
^ permalink raw reply [relevance 1%]
* FAILED: patch "[PATCH] drm/amd/display: Fix in secure display context creation" failed to apply to 6.1-stable tree
@ 2023-07-21 7:23 4% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2023-07-21 7:23 UTC (permalink / raw)
To: HaoPing.Liu, Rodrigo.Siqueira, Wayne.Lin, alexander.deucher,
daniel.wheeler
Cc: stable
The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x f477c7b5ec3e4ef87606671b340abf3bdb0cccff
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2023072112-refocus-garnet-df10@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
f477c7b5ec3e ("drm/amd/display: Fix in secure display context creation")
1e88eb1b2c25 ("drm/amd/display: Drop CONFIG_DRM_AMD_DC_HDCP")
7ae1dbe6547c ("drm/amd/display: merge dc_link.h into dc.h and dc_types.h")
455ad25997ba ("drm/amdgpu: Select DRM_DISPLAY_HDCP_HELPER in amdgpu")
8e5cfe547bf3 ("drm/amd/display: upstream link_dp_dpia_bw.c")
5ca38a18b5a4 ("drm/amd/display: move public dc link function implementation to dc_link_exports")
54618888d1ea ("drm/amd/display: break down dc_link.c")
71d7e8904d54 ("drm/amd/display: Add HDMI manufacturer OUI and device id read")
65a4cfb45e0e ("drm/amdgpu/display: remove duplicate include header in files")
e322843e5e33 ("drm/amd/display: fix linux dp link lost handled only one time")
0c2bfcc338eb ("drm/amd/display: Add Function declaration in dc_link")
6ca7415f11af ("drm/amd/display: merge dc_link_dp into dc_link")
de3fb390175b ("drm/amd/display: move dp cts functions from dc_link_dp to link_dp_cts")
c5a31f178e35 ("drm/amd/display: move dp irq handler functions from dc_link_dp to link_dp_irq_handler")
e95afc1cf7c6 ("drm/amd/display: Enable AdaptiveSync in DC interface")
0078c924e733 ("drm/amd/display: move eDP panel control logic to link_edp_panel_control")
bc33f5e5f05b ("drm/amd/display: create accessories, hwss and protocols sub folders in link")
2daeb74b7d66 ("drm/amdgpu/display/mst: update mst_mgr relevant variable when long HPD")
028c4ccfb812 ("drm/amd/display: force connector state when bpc changes during compliance")
603a521ec279 ("drm/amd/display: remove duplicate included header files")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From f477c7b5ec3e4ef87606671b340abf3bdb0cccff Mon Sep 17 00:00:00 2001
From: Alan Liu <HaoPing.Liu@amd.com>
Date: Mon, 10 Apr 2023 11:35:44 +0800
Subject: [PATCH] drm/amd/display: Fix in secure display context creation
[Why & How]
We need to store CRTC information in secure_display_ctx, so postpone
the call to amdgpu_dm_crtc_secure_display_create_contexts() until we
initialize all CRTCs.
Cc: stable@vger.kernel.org
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alan Liu <HaoPing.Liu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index b265434c77e1..7f0dcd7af4c7 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1776,12 +1776,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
dc_init_callbacks(adev->dm.dc, &init_params);
}
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
- adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
- if (!adev->dm.secure_display_ctxs) {
- DRM_ERROR("amdgpu: failed to initialize secure_display_ctxs.\n");
- }
-#endif
if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
init_completion(&adev->dm.dmub_aux_transfer_done);
adev->dm.dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_KERNEL);
@@ -1840,6 +1834,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
goto error;
}
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+ adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
+ if (!adev->dm.secure_display_ctxs)
+ DRM_ERROR("amdgpu: failed to initialize secure display contexts.\n");
+#endif
DRM_DEBUG_DRIVER("KMS initialized.\n");
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
index 935adca6f048..748e80ef40d0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
@@ -100,7 +100,7 @@ struct secure_display_context *amdgpu_dm_crtc_secure_display_create_contexts(
#else
#define amdgpu_dm_crc_window_is_activated(x)
#define amdgpu_dm_crtc_handle_crc_window_irq(x)
-#define amdgpu_dm_crtc_secure_display_create_contexts()
+#define amdgpu_dm_crtc_secure_display_create_contexts(x)
#endif
#endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */
^ permalink raw reply related [relevance 4%]
* [PATCH 6.1 105/591] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
@ 2023-07-16 19:44 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-16 19:44 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Remi Pommarel, Nicolas Escande,
Toke Høiland-Jørgensen, Kalle Valo, Sasha Levin
From: Remi Pommarel <repk@triplefau.lt>
[ Upstream commit 75086cc6dee046e3fbb3dba148b376d8802f83bc ]
On EDMA capable hardware, ath9k_txq_list_has_key() can enter infinite
loop if it is called while all txq_fifos have packets that use different
key that the one we are looking for. Fix it by exiting the loop if all
txq_fifos have been checked already.
Because this loop is called under spin_lock_bh() (see ath_txq_lock) it
causes the following rcu stall:
rcu: INFO: rcu_sched self-detected stall on CPU
ath10k_pci 0000:01:00.0: failed to read temperature -11
rcu: 1-....: (5254 ticks this GP) idle=189/1/0x4000000000000002 softirq=8442983/8442984 fqs=2579
(t=5257 jiffies g=17983297 q=334)
Task dump for CPU 1:
task:hostapd state:R running task stack: 0 pid: 297 ppid: 289 flags:0x0000000a
Call trace:
dump_backtrace+0x0/0x170
show_stack+0x1c/0x24
sched_show_task+0x140/0x170
dump_cpu_task+0x48/0x54
rcu_dump_cpu_stacks+0xf0/0x134
rcu_sched_clock_irq+0x8d8/0x9fc
update_process_times+0xa0/0xec
tick_sched_timer+0x5c/0xd0
__hrtimer_run_queues+0x154/0x320
hrtimer_interrupt+0x120/0x2f0
arch_timer_handler_virt+0x38/0x44
handle_percpu_devid_irq+0x9c/0x1e0
handle_domain_irq+0x64/0x90
gic_handle_irq+0x78/0xb0
call_on_irq_stack+0x28/0x38
do_interrupt_handler+0x54/0x5c
el1_interrupt+0x2c/0x4c
el1h_64_irq_handler+0x14/0x1c
el1h_64_irq+0x74/0x78
ath9k_txq_has_key+0x1bc/0x250 [ath9k]
ath9k_set_key+0x1cc/0x3dc [ath9k]
drv_set_key+0x78/0x170
ieee80211_key_replace+0x564/0x6cc
ieee80211_key_link+0x174/0x220
ieee80211_add_key+0x11c/0x300
nl80211_new_key+0x12c/0x330
genl_family_rcv_msg_doit+0xbc/0x11c
genl_rcv_msg+0xd8/0x1c4
netlink_rcv_skb+0x40/0x100
genl_rcv+0x3c/0x50
netlink_unicast+0x1ec/0x2c0
netlink_sendmsg+0x198/0x3c0
____sys_sendmsg+0x210/0x250
___sys_sendmsg+0x78/0xc4
__sys_sendmsg+0x4c/0x90
__arm64_sys_sendmsg+0x28/0x30
invoke_syscall.constprop.0+0x60/0x100
do_el0_svc+0x48/0xd0
el0_svc+0x14/0x50
el0t_64_sync_handler+0xa8/0xb0
el0t_64_sync+0x158/0x15c
This rcu stall is hard to reproduce as is, but changing ATH_TXFIFO_DEPTH
from 8 to 2 makes it reasonably easy to reproduce.
Fixes: ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
Tested-by: Nicolas Escande <nico.escande@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230609093744.1985-1-repk@triplefau.lt
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath9k/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a4197c14f0a92..7f9f06ea8a05f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 6.4 161/800] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
@ 2023-07-16 19:40 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-16 19:40 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Remi Pommarel, Nicolas Escande,
Toke Høiland-Jørgensen, Kalle Valo, Sasha Levin
From: Remi Pommarel <repk@triplefau.lt>
[ Upstream commit 75086cc6dee046e3fbb3dba148b376d8802f83bc ]
On EDMA capable hardware, ath9k_txq_list_has_key() can enter infinite
loop if it is called while all txq_fifos have packets that use different
key that the one we are looking for. Fix it by exiting the loop if all
txq_fifos have been checked already.
Because this loop is called under spin_lock_bh() (see ath_txq_lock) it
causes the following rcu stall:
rcu: INFO: rcu_sched self-detected stall on CPU
ath10k_pci 0000:01:00.0: failed to read temperature -11
rcu: 1-....: (5254 ticks this GP) idle=189/1/0x4000000000000002 softirq=8442983/8442984 fqs=2579
(t=5257 jiffies g=17983297 q=334)
Task dump for CPU 1:
task:hostapd state:R running task stack: 0 pid: 297 ppid: 289 flags:0x0000000a
Call trace:
dump_backtrace+0x0/0x170
show_stack+0x1c/0x24
sched_show_task+0x140/0x170
dump_cpu_task+0x48/0x54
rcu_dump_cpu_stacks+0xf0/0x134
rcu_sched_clock_irq+0x8d8/0x9fc
update_process_times+0xa0/0xec
tick_sched_timer+0x5c/0xd0
__hrtimer_run_queues+0x154/0x320
hrtimer_interrupt+0x120/0x2f0
arch_timer_handler_virt+0x38/0x44
handle_percpu_devid_irq+0x9c/0x1e0
handle_domain_irq+0x64/0x90
gic_handle_irq+0x78/0xb0
call_on_irq_stack+0x28/0x38
do_interrupt_handler+0x54/0x5c
el1_interrupt+0x2c/0x4c
el1h_64_irq_handler+0x14/0x1c
el1h_64_irq+0x74/0x78
ath9k_txq_has_key+0x1bc/0x250 [ath9k]
ath9k_set_key+0x1cc/0x3dc [ath9k]
drv_set_key+0x78/0x170
ieee80211_key_replace+0x564/0x6cc
ieee80211_key_link+0x174/0x220
ieee80211_add_key+0x11c/0x300
nl80211_new_key+0x12c/0x330
genl_family_rcv_msg_doit+0xbc/0x11c
genl_rcv_msg+0xd8/0x1c4
netlink_rcv_skb+0x40/0x100
genl_rcv+0x3c/0x50
netlink_unicast+0x1ec/0x2c0
netlink_sendmsg+0x198/0x3c0
____sys_sendmsg+0x210/0x250
___sys_sendmsg+0x78/0xc4
__sys_sendmsg+0x4c/0x90
__arm64_sys_sendmsg+0x28/0x30
invoke_syscall.constprop.0+0x60/0x100
do_el0_svc+0x48/0xd0
el0_svc+0x14/0x50
el0t_64_sync_handler+0xa8/0xb0
el0t_64_sync+0x158/0x15c
This rcu stall is hard to reproduce as is, but changing ATH_TXFIFO_DEPTH
from 8 to 2 makes it reasonably easy to reproduce.
Fixes: ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
Tested-by: Nicolas Escande <nico.escande@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230609093744.1985-1-repk@triplefau.lt
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath9k/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a4197c14f0a92..7f9f06ea8a05f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 6.3 118/431] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
@ 2023-07-09 11:11 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-07-09 11:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Remi Pommarel, Nicolas Escande,
Toke Høiland-Jørgensen, Kalle Valo, Sasha Levin
From: Remi Pommarel <repk@triplefau.lt>
[ Upstream commit 75086cc6dee046e3fbb3dba148b376d8802f83bc ]
On EDMA capable hardware, ath9k_txq_list_has_key() can enter infinite
loop if it is called while all txq_fifos have packets that use different
key that the one we are looking for. Fix it by exiting the loop if all
txq_fifos have been checked already.
Because this loop is called under spin_lock_bh() (see ath_txq_lock) it
causes the following rcu stall:
rcu: INFO: rcu_sched self-detected stall on CPU
ath10k_pci 0000:01:00.0: failed to read temperature -11
rcu: 1-....: (5254 ticks this GP) idle=189/1/0x4000000000000002 softirq=8442983/8442984 fqs=2579
(t=5257 jiffies g=17983297 q=334)
Task dump for CPU 1:
task:hostapd state:R running task stack: 0 pid: 297 ppid: 289 flags:0x0000000a
Call trace:
dump_backtrace+0x0/0x170
show_stack+0x1c/0x24
sched_show_task+0x140/0x170
dump_cpu_task+0x48/0x54
rcu_dump_cpu_stacks+0xf0/0x134
rcu_sched_clock_irq+0x8d8/0x9fc
update_process_times+0xa0/0xec
tick_sched_timer+0x5c/0xd0
__hrtimer_run_queues+0x154/0x320
hrtimer_interrupt+0x120/0x2f0
arch_timer_handler_virt+0x38/0x44
handle_percpu_devid_irq+0x9c/0x1e0
handle_domain_irq+0x64/0x90
gic_handle_irq+0x78/0xb0
call_on_irq_stack+0x28/0x38
do_interrupt_handler+0x54/0x5c
el1_interrupt+0x2c/0x4c
el1h_64_irq_handler+0x14/0x1c
el1h_64_irq+0x74/0x78
ath9k_txq_has_key+0x1bc/0x250 [ath9k]
ath9k_set_key+0x1cc/0x3dc [ath9k]
drv_set_key+0x78/0x170
ieee80211_key_replace+0x564/0x6cc
ieee80211_key_link+0x174/0x220
ieee80211_add_key+0x11c/0x300
nl80211_new_key+0x12c/0x330
genl_family_rcv_msg_doit+0xbc/0x11c
genl_rcv_msg+0xd8/0x1c4
netlink_rcv_skb+0x40/0x100
genl_rcv+0x3c/0x50
netlink_unicast+0x1ec/0x2c0
netlink_sendmsg+0x198/0x3c0
____sys_sendmsg+0x210/0x250
___sys_sendmsg+0x78/0xc4
__sys_sendmsg+0x4c/0x90
__arm64_sys_sendmsg+0x28/0x30
invoke_syscall.constprop.0+0x60/0x100
do_el0_svc+0x48/0xd0
el0_svc+0x14/0x50
el0t_64_sync_handler+0xa8/0xb0
el0t_64_sync+0x158/0x15c
This rcu stall is hard to reproduce as is, but changing ATH_TXFIFO_DEPTH
from 8 to 2 makes it reasonably easy to reproduce.
Fixes: ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
Tested-by: Nicolas Escande <nico.escande@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230609093744.1985-1-repk@triplefau.lt
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath9k/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a4197c14f0a92..7f9f06ea8a05f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
--
2.39.2
^ permalink raw reply related [relevance 5%]
* Re: Linux 5.15.119
@ 2023-06-28 9:25 1% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-06-28 9:25 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/Makefile b/Makefile
index c4ef4eed1a12..b863208e31b2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 15
-SUBLEVEL = 118
+SUBLEVEL = 119
EXTRAVERSION =
NAME = Trick or Treat
diff --git a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
index 2e94f32d9dfc..5de82729eb7e 100644
--- a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
+++ b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
@@ -527,7 +527,7 @@ touchscreen@1 {
interrupt-parent = <&gpio1>;
interrupts = <31 0>;
- pendown-gpio = <&gpio1 31 0>;
+ pendown-gpio = <&gpio1 31 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
diff --git a/arch/arm/boot/dts/at91sam9261ek.dts b/arch/arm/boot/dts/at91sam9261ek.dts
index beed819609e8..8f3b483bb64d 100644
--- a/arch/arm/boot/dts/at91sam9261ek.dts
+++ b/arch/arm/boot/dts/at91sam9261ek.dts
@@ -156,7 +156,7 @@ tsc2046@2 {
compatible = "ti,ads7843";
interrupts-extended = <&pioC 2 IRQ_TYPE_EDGE_BOTH>;
spi-max-frequency = <3000000>;
- pendown-gpio = <&pioC 2 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&pioC 2 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <150>;
ti,x-max = /bits/ 16 <3830>;
diff --git a/arch/arm/boot/dts/imx7d-pico-hobbit.dts b/arch/arm/boot/dts/imx7d-pico-hobbit.dts
index d917dc4f2f22..6ad39dca7009 100644
--- a/arch/arm/boot/dts/imx7d-pico-hobbit.dts
+++ b/arch/arm/boot/dts/imx7d-pico-hobbit.dts
@@ -64,7 +64,7 @@ ads7846@0 {
interrupt-parent = <&gpio2>;
interrupts = <7 0>;
spi-max-frequency = <1000000>;
- pendown-gpio = <&gpio2 7 0>;
+ pendown-gpio = <&gpio2 7 GPIO_ACTIVE_LOW>;
vcc-supply = <®_3p3v>;
ti,x-min = /bits/ 16 <0>;
ti,x-max = /bits/ 16 <4095>;
diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
index 4e1a6cde90fe..4e62ed2df11d 100644
--- a/arch/arm/boot/dts/imx7d-sdb.dts
+++ b/arch/arm/boot/dts/imx7d-sdb.dts
@@ -205,7 +205,7 @@ tsc2046@0 {
pinctrl-0 = <&pinctrl_tsc2046_pendown>;
interrupt-parent = <&gpio2>;
interrupts = <29 0>;
- pendown-gpio = <&gpio2 29 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio2 29 GPIO_ACTIVE_LOW>;
touchscreen-max-pressure = <255>;
wakeup-source;
};
diff --git a/arch/arm/boot/dts/omap3-cm-t3x.dtsi b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
index e61b8a2bfb7d..51baedf1603b 100644
--- a/arch/arm/boot/dts/omap3-cm-t3x.dtsi
+++ b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
@@ -227,7 +227,7 @@ ads7846@0 {
interrupt-parent = <&gpio2>;
interrupts = <25 0>; /* gpio_57 */
- pendown-gpio = <&gpio2 25 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio2 25 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
index 3decc2d78a6c..a7f99ae0c1fe 100644
--- a/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
+++ b/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
@@ -54,7 +54,7 @@ ads7846@0 {
interrupt-parent = <&gpio1>;
interrupts = <27 0>; /* gpio_27 */
- pendown-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio1 27 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
index 73d477898ec2..06e7cf96c663 100644
--- a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
+++ b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
@@ -311,7 +311,7 @@ tsc2046@0 {
interrupt-parent = <&gpio1>;
interrupts = <8 0>; /* boot6 / gpio_8 */
spi-max-frequency = <1000000>;
- pendown-gpio = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio1 8 GPIO_ACTIVE_LOW>;
vcc-supply = <®_vcc3>;
pinctrl-names = "default";
pinctrl-0 = <&tsc2048_pins>;
diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi b/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
index 1d6e88f99eb3..c3570acc35fa 100644
--- a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
@@ -149,7 +149,7 @@ ads7846@0 {
interrupt-parent = <&gpio4>;
interrupts = <18 0>; /* gpio_114 */
- pendown-gpio = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio4 18 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi b/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
index 7e30f9d45790..d95a0e130058 100644
--- a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
@@ -160,7 +160,7 @@ ads7846@0 {
interrupt-parent = <&gpio4>;
interrupts = <18 0>; /* gpio_114 */
- pendown-gpio = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio4 18 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-pandora-common.dtsi b/arch/arm/boot/dts/omap3-pandora-common.dtsi
index 37608af6c07f..ca6d777ebf84 100644
--- a/arch/arm/boot/dts/omap3-pandora-common.dtsi
+++ b/arch/arm/boot/dts/omap3-pandora-common.dtsi
@@ -651,7 +651,7 @@ tsc2046@0 {
pinctrl-0 = <&penirq_pins>;
interrupt-parent = <&gpio3>;
interrupts = <30 IRQ_TYPE_NONE>; /* GPIO_94 */
- pendown-gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio3 30 GPIO_ACTIVE_LOW>;
vcc-supply = <&vaux4>;
ti,x-min = /bits/ 16 <0>;
diff --git a/arch/arm/boot/dts/omap5-cm-t54.dts b/arch/arm/boot/dts/omap5-cm-t54.dts
index ca759b7b8a58..e62ea8b6d53f 100644
--- a/arch/arm/boot/dts/omap5-cm-t54.dts
+++ b/arch/arm/boot/dts/omap5-cm-t54.dts
@@ -354,7 +354,7 @@ ads7846@0 {
interrupt-parent = <&gpio1>;
interrupts = <15 0>; /* gpio1_wk15 */
- pendown-gpio = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio1 15 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index f79f3720e4cb..543eb08fa8e5 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -109,8 +109,14 @@
#define SB_BARRIER_INSN __SYS_BARRIER_INSN(0, 7, 31)
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
+#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
+#define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6)
#define SYS_DC_CSW sys_insn(1, 0, 7, 10, 2)
+#define SYS_DC_CGSW sys_insn(1, 0, 7, 10, 4)
+#define SYS_DC_CGDSW sys_insn(1, 0, 7, 10, 6)
#define SYS_DC_CISW sys_insn(1, 0, 7, 14, 2)
+#define SYS_DC_CIGSW sys_insn(1, 0, 7, 14, 4)
+#define SYS_DC_CIGDSW sys_insn(1, 0, 7, 14, 6)
/*
* System registers, organised loosely by encoding but grouped together
diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile
index 360ada80d20c..d22ec8acb13c 100644
--- a/arch/s390/purgatory/Makefile
+++ b/arch/s390/purgatory/Makefile
@@ -26,6 +26,7 @@ KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare
KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding
KBUILD_CFLAGS += -c -MD -Os -m64 -msoft-float -fno-common
KBUILD_CFLAGS += -fno-stack-protector
+KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
KBUILD_CFLAGS += $(CLANG_FLAGS)
KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS))
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 6bde05a86b4e..896bc41cb2ba 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -97,7 +97,10 @@ static void init_x2apic_ldr(void)
static int x2apic_phys_probe(void)
{
- if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys()))
+ if (!x2apic_mode)
+ return 0;
+
+ if (x2apic_phys || x2apic_fadt_phys())
return 1;
return apic == &apic_x2apic_phys;
diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c
index 557f0fe25dff..37db264866b6 100644
--- a/arch/x86/mm/kaslr.c
+++ b/arch/x86/mm/kaslr.c
@@ -172,10 +172,10 @@ void __meminit init_trampoline_kaslr(void)
set_p4d(p4d_tramp,
__p4d(_KERNPG_TABLE | __pa(pud_page_tramp)));
- set_pgd(&trampoline_pgd_entry,
- __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp)));
+ trampoline_pgd_entry =
+ __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp));
} else {
- set_pgd(&trampoline_pgd_entry,
- __pgd(_KERNPG_TABLE | __pa(pud_page_tramp)));
+ trampoline_pgd_entry =
+ __pgd(_KERNPG_TABLE | __pa(pud_page_tramp));
}
}
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 810de0b4c125..9c3ad33e926a 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -101,8 +101,6 @@ acpi_status
acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
acpi_event_status *event_status);
-acpi_status acpi_hw_disable_all_gpes(void);
-
acpi_status acpi_hw_enable_all_runtime_gpes(void);
acpi_status acpi_hw_enable_all_wakeup_gpes(void);
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index d7194047d256..b277e25b276c 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -635,11 +635,19 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
}
/*
- * Disable and clear GPE status before interrupt is enabled. Some GPEs
- * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
- * acpi_leave_sleep_state will reenable specific GPEs later
+ * Disable all GPE and clear their status bits before interrupts are
+ * enabled. Some GPEs (like wakeup GPEs) have no handlers and this can
+ * prevent them from producing spurious interrups.
+ *
+ * acpi_leave_sleep_state() will reenable specific GPEs later.
+ *
+ * Because this code runs on one CPU with disabled interrupts (all of
+ * the other CPUs are offline at this time), it need not acquire any
+ * sleeping locks which may trigger an implicit preemption point even
+ * if there is no contention, so avoid doing that by using a low-level
+ * library routine here.
*/
- acpi_disable_all_gpes();
+ acpi_hw_disable_all_gpes();
/* Allow EC transactions to happen. */
acpi_ec_unblock_transactions();
diff --git a/drivers/base/regmap/regmap-spi-avmm.c b/drivers/base/regmap/regmap-spi-avmm.c
index ad1da83e849f..67f89937219c 100644
--- a/drivers/base/regmap/regmap-spi-avmm.c
+++ b/drivers/base/regmap/regmap-spi-avmm.c
@@ -666,7 +666,7 @@ static const struct regmap_bus regmap_spi_avmm_bus = {
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
.max_raw_read = SPI_AVMM_VAL_SIZE * MAX_READ_CNT,
- .max_raw_write = SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
+ .max_raw_write = SPI_AVMM_REG_SIZE + SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
.free_context = spi_avmm_bridge_ctx_free,
};
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 512c867495ea..365761055df3 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -731,7 +731,9 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
wake_up_interruptible(&priv->int_queue);
/* Clear interrupts handled with TPM_EOI */
+ tpm_tis_request_locality(chip, 0);
rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt);
+ tpm_tis_relinquish_locality(chip, 0);
if (rc < 0)
return IRQ_NONE;
diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c
index f41123de69c5..5ffab0fc1b76 100644
--- a/drivers/gpio/gpio-sifive.c
+++ b/drivers/gpio/gpio-sifive.c
@@ -215,8 +215,12 @@ static int sifive_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
- for (i = 0; i < ngpio; i++)
- chip->irq_number[i] = platform_get_irq(pdev, i);
+ for (i = 0; i < ngpio; i++) {
+ ret = platform_get_irq(pdev, i);
+ if (ret < 0)
+ return ret;
+ chip->irq_number[i] = ret;
+ }
ret = bgpio_init(&chip->gc, dev, 4,
chip->base + SIFIVE_GPIO_INPUT_VAL,
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 8c041a8dd9d8..f9fdd117c654 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1578,9 +1578,14 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
}
if (gc->irq.parent_handler) {
- void *data = gc->irq.parent_handler_data ?: gc;
-
for (i = 0; i < gc->irq.num_parents; i++) {
+ void *data;
+
+ if (gc->irq.per_parent_data)
+ data = gc->irq.parent_handler_data_array[i];
+ else
+ data = gc->irq.parent_handler_data ?: gc;
+
/*
* The parent IRQ chip is already using the chip_data
* for this IRQ chip, so our callbacks simply use the
@@ -1678,6 +1683,14 @@ int gpiochip_irqchip_add_domain(struct gpio_chip *gc,
gc->to_irq = gpiochip_to_irq;
gc->irq.domain = domain;
+ /*
+ * Using barrier() here to prevent compiler from reordering
+ * gc->irq.initialized before adding irqdomain.
+ */
+ barrier();
+
+ gc->irq.initialized = true;
+
return 0;
}
EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_domain);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 938aa11acb2d..be863af956bb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -353,6 +353,35 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
return false;
}
+/**
+ * update_planes_and_stream_adapter() - Send planes to be updated in DC
+ *
+ * DC has a generic way to update planes and stream via
+ * dc_update_planes_and_stream function; however, DM might need some
+ * adjustments and preparation before calling it. This function is a wrapper
+ * for the dc_update_planes_and_stream that does any required configuration
+ * before passing control to DC.
+ */
+static inline bool update_planes_and_stream_adapter(struct dc *dc,
+ int update_type,
+ int planes_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update,
+ struct dc_surface_update *array_of_surface_update)
+{
+ /*
+ * Previous frame finished and HW is ready for optimization.
+ */
+ if (update_type == UPDATE_TYPE_FAST)
+ dc_post_update_surfaces_to_stream(dc);
+
+ return dc_update_planes_and_stream(dc,
+ array_of_surface_update,
+ planes_count,
+ stream,
+ stream_update);
+}
+
/**
* dm_pflip_high_irq() - Handle pageflip interrupt
* @interrupt_params: ignored
@@ -2550,10 +2579,13 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
bundle->surface_updates[m].surface->force_full_update =
true;
}
- dc_commit_updates_for_stream(
- dm->dc, bundle->surface_updates,
- dc_state->stream_status->plane_count,
- dc_state->streams[k], &bundle->stream_update, dc_state);
+
+ update_planes_and_stream_adapter(dm->dc,
+ UPDATE_TYPE_FULL,
+ dc_state->stream_status->plane_count,
+ dc_state->streams[k],
+ &bundle->stream_update,
+ bundle->surface_updates);
}
cleanup:
@@ -9218,6 +9250,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
if (acrtc_state->abm_level != dm_old_crtc_state->abm_level)
bundle->stream_update.abm_level = &acrtc_state->abm_level;
+ mutex_lock(&dm->dc_lock);
+ if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
+ acrtc_state->stream->link->psr_settings.psr_allow_active)
+ amdgpu_dm_psr_disable(acrtc_state->stream);
+ mutex_unlock(&dm->dc_lock);
+
/*
* If FreeSync state on the stream has changed then we need to
* re-adjust the min/max bounds now that DC doesn't handle this
@@ -9231,16 +9269,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
}
mutex_lock(&dm->dc_lock);
- if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
- acrtc_state->stream->link->psr_settings.psr_allow_active)
- amdgpu_dm_psr_disable(acrtc_state->stream);
- dc_commit_updates_for_stream(dm->dc,
- bundle->surface_updates,
- planes_count,
- acrtc_state->stream,
- &bundle->stream_update,
- dc_state);
+ update_planes_and_stream_adapter(dm->dc,
+ acrtc_state->update_type,
+ planes_count,
+ acrtc_state->stream,
+ &bundle->stream_update,
+ bundle->surface_updates);
/**
* Enable or disable the interrupts on the backend.
@@ -9666,12 +9701,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
mutex_lock(&dm->dc_lock);
- dc_commit_updates_for_stream(dm->dc,
- dummy_updates,
- status->plane_count,
- dm_new_crtc_state->stream,
- &stream_update,
- dc_state);
+ dc_update_planes_and_stream(dm->dc,
+ dummy_updates,
+ status->plane_count,
+ dm_new_crtc_state->stream,
+ &stream_update);
mutex_unlock(&dm->dc_lock);
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index eca882438f6e..220a26e45a28 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2534,6 +2534,137 @@ static void copy_stream_update_to_stream(struct dc *dc,
}
}
+void dc_reset_state(struct dc *dc, struct dc_state *context)
+{
+ dc_resource_state_destruct(context);
+
+ /* clear the structure, but don't reset the reference count */
+ memset(context, 0, offsetof(struct dc_state, refcount));
+
+ init_state(dc, context);
+}
+
+static bool update_planes_and_stream_state(struct dc *dc,
+ struct dc_surface_update *srf_updates, int surface_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update,
+ enum surface_update_type *new_update_type,
+ struct dc_state **new_context)
+{
+ struct dc_state *context;
+ int i, j;
+ enum surface_update_type update_type;
+ const struct dc_stream_status *stream_status;
+ struct dc_context *dc_ctx = dc->ctx;
+
+ stream_status = dc_stream_get_status(stream);
+
+ if (!stream_status) {
+ if (surface_count) /* Only an error condition if surf_count non-zero*/
+ ASSERT(false);
+
+ return false; /* Cannot commit surface to stream that is not committed */
+ }
+
+ context = dc->current_state;
+
+ update_type = dc_check_update_surfaces_for_stream(
+ dc, srf_updates, surface_count, stream_update, stream_status);
+
+ /* update current stream with the new updates */
+ copy_stream_update_to_stream(dc, context, stream, stream_update);
+
+ /* do not perform surface update if surface has invalid dimensions
+ * (all zero) and no scaling_info is provided
+ */
+ if (surface_count > 0) {
+ for (i = 0; i < surface_count; i++) {
+ if ((srf_updates[i].surface->src_rect.width == 0 ||
+ srf_updates[i].surface->src_rect.height == 0 ||
+ srf_updates[i].surface->dst_rect.width == 0 ||
+ srf_updates[i].surface->dst_rect.height == 0) &&
+ (!srf_updates[i].scaling_info ||
+ srf_updates[i].scaling_info->src_rect.width == 0 ||
+ srf_updates[i].scaling_info->src_rect.height == 0 ||
+ srf_updates[i].scaling_info->dst_rect.width == 0 ||
+ srf_updates[i].scaling_info->dst_rect.height == 0)) {
+ DC_ERROR("Invalid src/dst rects in surface update!\n");
+ return false;
+ }
+ }
+ }
+
+ if (update_type >= update_surface_trace_level)
+ update_surface_trace(dc, srf_updates, surface_count);
+
+ if (update_type >= UPDATE_TYPE_FULL) {
+ struct dc_plane_state *new_planes[MAX_SURFACES] = {0};
+
+ for (i = 0; i < surface_count; i++)
+ new_planes[i] = srf_updates[i].surface;
+
+ /* initialize scratch memory for building context */
+ context = dc_create_state(dc);
+ if (context == NULL) {
+ DC_ERROR("Failed to allocate new validate context!\n");
+ return false;
+ }
+
+ dc_resource_state_copy_construct(
+ dc->current_state, context);
+
+ /*remove old surfaces from context */
+ if (!dc_rem_all_planes_for_stream(dc, stream, context)) {
+
+ BREAK_TO_DEBUGGER();
+ goto fail;
+ }
+
+ /* add surface to context */
+ if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) {
+
+ BREAK_TO_DEBUGGER();
+ goto fail;
+ }
+ }
+
+ /* save update parameters into surface */
+ for (i = 0; i < surface_count; i++) {
+ struct dc_plane_state *surface = srf_updates[i].surface;
+
+ copy_surface_update_to_plane(surface, &srf_updates[i]);
+
+ if (update_type >= UPDATE_TYPE_MED) {
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+ if (pipe_ctx->plane_state != surface)
+ continue;
+
+ resource_build_scaling_params(pipe_ctx);
+ }
+ }
+ }
+
+ if (update_type == UPDATE_TYPE_FULL) {
+ if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
+ BREAK_TO_DEBUGGER();
+ goto fail;
+ }
+ }
+
+ *new_context = context;
+ *new_update_type = update_type;
+
+ return true;
+
+fail:
+ dc_release_state(context);
+
+ return false;
+
+}
+
static void commit_planes_do_stream_update(struct dc *dc,
struct dc_stream_state *stream,
struct dc_stream_update *stream_update,
@@ -2931,6 +3062,152 @@ static void commit_planes_for_stream(struct dc *dc,
}
}
+static bool commit_minimal_transition_state(struct dc *dc,
+ struct dc_state *transition_base_context)
+{
+ struct dc_state *transition_context = dc_create_state(dc);
+ enum pipe_split_policy tmp_policy;
+ enum dc_status ret = DC_ERROR_UNEXPECTED;
+ unsigned int i, j;
+
+ if (!transition_context)
+ return false;
+
+ tmp_policy = dc->debug.pipe_split_policy;
+ dc->debug.pipe_split_policy = MPC_SPLIT_AVOID;
+
+ dc_resource_state_copy_construct(transition_base_context, transition_context);
+
+ //commit minimal state
+ if (dc->res_pool->funcs->validate_bandwidth(dc, transition_context, false)) {
+ for (i = 0; i < transition_context->stream_count; i++) {
+ struct dc_stream_status *stream_status = &transition_context->stream_status[i];
+
+ for (j = 0; j < stream_status->plane_count; j++) {
+ struct dc_plane_state *plane_state = stream_status->plane_states[j];
+
+ /* force vsync flip when reconfiguring pipes to prevent underflow
+ * and corruption
+ */
+ plane_state->flip_immediate = false;
+ }
+ }
+
+ ret = dc_commit_state_no_check(dc, transition_context);
+ }
+
+ //always release as dc_commit_state_no_check retains in good case
+ dc_release_state(transition_context);
+
+ //restore previous pipe split policy
+ dc->debug.pipe_split_policy = tmp_policy;
+
+ if (ret != DC_OK) {
+ //this should never happen
+ BREAK_TO_DEBUGGER();
+ return false;
+ }
+
+ //force full surface update
+ for (i = 0; i < dc->current_state->stream_count; i++) {
+ for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) {
+ dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF;
+ }
+ }
+
+ return true;
+}
+
+bool dc_update_planes_and_stream(struct dc *dc,
+ struct dc_surface_update *srf_updates, int surface_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update)
+{
+ struct dc_state *context;
+ enum surface_update_type update_type;
+ int i;
+
+ /* In cases where MPO and split or ODM are used transitions can
+ * cause underflow. Apply stream configuration with minimal pipe
+ * split first to avoid unsupported transitions for active pipes.
+ */
+ bool force_minimal_pipe_splitting = false;
+ bool is_plane_addition = false;
+
+ struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
+
+ if (cur_stream_status &&
+ dc->current_state->stream_count > 0 &&
+ dc->debug.pipe_split_policy != MPC_SPLIT_AVOID) {
+ /* determine if minimal transition is required */
+ if (cur_stream_status->plane_count > surface_count) {
+ force_minimal_pipe_splitting = true;
+ } else if (cur_stream_status->plane_count < surface_count) {
+ force_minimal_pipe_splitting = true;
+ is_plane_addition = true;
+ }
+ }
+
+ /* on plane addition, minimal state is the current one */
+ if (force_minimal_pipe_splitting && is_plane_addition &&
+ !commit_minimal_transition_state(dc, dc->current_state))
+ return false;
+
+ if (!update_planes_and_stream_state(
+ dc,
+ srf_updates,
+ surface_count,
+ stream,
+ stream_update,
+ &update_type,
+ &context))
+ return false;
+
+ /* on plane addition, minimal state is the new one */
+ if (force_minimal_pipe_splitting && !is_plane_addition) {
+ if (!commit_minimal_transition_state(dc, context)) {
+ dc_release_state(context);
+ return false;
+ }
+
+ update_type = UPDATE_TYPE_FULL;
+ }
+
+ commit_planes_for_stream(
+ dc,
+ srf_updates,
+ surface_count,
+ stream,
+ stream_update,
+ update_type,
+ context);
+
+ if (dc->current_state != context) {
+
+ /* Since memory free requires elevated IRQL, an interrupt
+ * request is generated by mem free. If this happens
+ * between freeing and reassigning the context, our vsync
+ * interrupt will call into dc and cause a memory
+ * corruption BSOD. Hence, we first reassign the context,
+ * then free the old context.
+ */
+
+ struct dc_state *old = dc->current_state;
+
+ dc->current_state = context;
+ dc_release_state(old);
+
+ // clear any forced full updates
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe_ctx->plane_state && pipe_ctx->stream == stream)
+ pipe_ctx->plane_state->force_full_update = false;
+ }
+ }
+ return true;
+}
+
void dc_commit_updates_for_stream(struct dc *dc,
struct dc_surface_update *srf_updates,
int surface_count,
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 7644f0e747d3..3e606faff58f 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -288,6 +288,9 @@ bool dc_is_stream_scaling_unchanged(
struct dc_stream_state *old_stream, struct dc_stream_state *stream);
/*
+ * Setup stream attributes if no stream updates are provided
+ * there will be no impact on the stream parameters
+ *
* Set up surface attributes and associate to a stream
* The surfaces parameter is an absolute set of all surface active for the stream.
* If no surfaces are provided, the stream will be blanked; no memory read.
@@ -296,8 +299,23 @@ bool dc_is_stream_scaling_unchanged(
* After this call:
* Surfaces attributes are programmed and configured to be composed into stream.
* This does not trigger a flip. No surface address is programmed.
+ *
*/
+bool dc_update_planes_and_stream(struct dc *dc,
+ struct dc_surface_update *surface_updates, int surface_count,
+ struct dc_stream_state *dc_stream,
+ struct dc_stream_update *stream_update);
+/*
+ * Set up surface attributes and associate to a stream
+ * The surfaces parameter is an absolute set of all surface active for the stream.
+ * If no surfaces are provided, the stream will be blanked; no memory read.
+ * Any flip related attribute changes must be done through this interface.
+ *
+ * After this call:
+ * Surfaces attributes are programmed and configured to be composed into stream.
+ * This does not trigger a flip. No surface address is programmed.
+ */
void dc_commit_updates_for_stream(struct dc *dc,
struct dc_surface_update *srf_updates,
int surface_count,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 471fd6c8135f..27613abeed96 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -1335,7 +1335,7 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
/* Let the runqueue know that there is work to do. */
queue_work(g2d->g2d_workq, &g2d->runqueue_work);
- if (runqueue_node->async)
+ if (req->async)
goto out;
wait_for_completion(&runqueue_node->complete);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index e5662bdcbbde..e96436e11a36 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -468,8 +468,6 @@ static int vidi_remove(struct platform_device *pdev)
if (ctx->raw_edid != (struct edid *)fake_edid_info) {
kfree(ctx->raw_edid);
ctx->raw_edid = NULL;
-
- return -EINVAL;
}
component_del(&pdev->dev, &vidi_component_ops);
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index a36a4f2c76b0..57218263ef3b 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -456,7 +456,6 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct radeon_device *rdev = dev->dev_private;
struct drm_radeon_gem_set_domain *args = data;
struct drm_gem_object *gobj;
- struct radeon_bo *robj;
int r;
/* for now if someone requests domain CPU -
@@ -469,13 +468,12 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
up_read(&rdev->exclusive_lock);
return -ENOENT;
}
- robj = gem_to_radeon_bo(gobj);
r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
drm_gem_object_put(gobj);
up_read(&rdev->exclusive_lock);
- r = radeon_gem_handle_lockup(robj->rdev, r);
+ r = radeon_gem_handle_lockup(rdev, r);
return r;
}
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index d29773a799b4..33e763e746a0 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -2425,8 +2425,13 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
goto fail_quirks;
}
- if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
+ if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) {
error = hid_hw_open(hdev);
+ if (error) {
+ hid_err(hdev, "hw open failed\n");
+ goto fail_quirks;
+ }
+ }
wacom_set_shared_values(wacom_wac);
devres_close_group(&hdev->dev, wacom);
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index d8dc5cc5e3a8..62c864f8d991 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -827,11 +827,22 @@ static void vmbus_wait_for_unload(void)
if (completion_done(&vmbus_connection.unload_event))
goto completed;
- for_each_online_cpu(cpu) {
+ for_each_present_cpu(cpu) {
struct hv_per_cpu_context *hv_cpu
= per_cpu_ptr(hv_context.cpu_context, cpu);
+ /*
+ * In a CoCo VM the synic_message_page is not allocated
+ * in hv_synic_alloc(). Instead it is set/cleared in
+ * hv_synic_enable_regs() and hv_synic_disable_regs()
+ * such that it is set only when the CPU is online. If
+ * not all present CPUs are online, the message page
+ * might be NULL, so skip such CPUs.
+ */
page_addr = hv_cpu->synic_message_page;
+ if (!page_addr)
+ continue;
+
msg = (struct hv_message *)page_addr
+ VMBUS_MESSAGE_SINT;
@@ -865,11 +876,14 @@ static void vmbus_wait_for_unload(void)
* maybe-pending messages on all CPUs to be able to receive new
* messages after we reconnect.
*/
- for_each_online_cpu(cpu) {
+ for_each_present_cpu(cpu) {
struct hv_per_cpu_context *hv_cpu
= per_cpu_ptr(hv_context.cpu_context, cpu);
page_addr = hv_cpu->synic_message_page;
+ if (!page_addr)
+ continue;
+
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
msg->header.message_type = HVMSG_NONE;
}
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index b906a3a7941c..115835bd562c 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1538,7 +1538,7 @@ static int vmbus_bus_init(void)
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online",
hv_synic_init, hv_synic_cleanup);
if (ret < 0)
- goto err_cpuhp;
+ goto err_alloc;
hyperv_cpuhp_online = ret;
ret = vmbus_connect();
@@ -1589,9 +1589,8 @@ static int vmbus_bus_init(void)
err_connect:
cpuhp_remove_state(hyperv_cpuhp_online);
-err_cpuhp:
- hv_synic_free();
err_alloc:
+ hv_synic_free();
if (vmbus_irq == -1) {
hv_remove_vmbus_handler();
} else {
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index d45ec26d51cb..c688f11ae5c9 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -200,8 +200,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
/* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */
static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
{
- u8 prescale, filt, sethold, clkhi, clklo, datavd;
- unsigned int clk_rate, clk_cycle;
+ u8 prescale, filt, sethold, datavd;
+ unsigned int clk_rate, clk_cycle, clkhi, clklo;
enum lpi2c_imx_pincfg pincfg;
unsigned int temp;
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index 31c02c2019c1..67a134c8448d 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -108,6 +108,27 @@ static const struct dmi_system_id dmi_use_low_level_irq[] = {
{} /* Terminating entry */
};
+/*
+ * Some devices have a wrong entry which points to a GPIO which is
+ * required in another driver, so this driver must not claim it.
+ */
+static const struct dmi_system_id dmi_invalid_acpi_index[] = {
+ {
+ /*
+ * Lenovo Yoga Book X90F / X90L, the PNP0C40 home button entry
+ * points to a GPIO which is not a home button and which is
+ * required by the lenovo-yogabook driver.
+ */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+ },
+ .driver_data = (void *)1l,
+ },
+ {} /* Terminating entry */
+};
+
/*
* Get the Nth GPIO number from the ACPI object.
*/
@@ -137,6 +158,8 @@ soc_button_device_create(struct platform_device *pdev,
struct platform_device *pd;
struct gpio_keys_button *gpio_keys;
struct gpio_keys_platform_data *gpio_keys_pdata;
+ const struct dmi_system_id *dmi_id;
+ int invalid_acpi_index = -1;
int error, gpio, irq;
int n_buttons = 0;
@@ -154,10 +177,17 @@ soc_button_device_create(struct platform_device *pdev,
gpio_keys = (void *)(gpio_keys_pdata + 1);
n_buttons = 0;
+ dmi_id = dmi_first_match(dmi_invalid_acpi_index);
+ if (dmi_id)
+ invalid_acpi_index = (long)dmi_id->driver_data;
+
for (info = button_info; info->name; info++) {
if (info->autorepeat != autorepeat)
continue;
+ if (info->acpi_index == invalid_acpi_index)
+ continue;
+
error = soc_button_lookup_gpio(&pdev->dev, info->acpi_index, &gpio, &irq);
if (error || irq < 0) {
/*
diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
index 67776a0d31e8..99ede1417d72 100644
--- a/drivers/media/cec/core/cec-adap.c
+++ b/drivers/media/cec/core/cec-adap.c
@@ -1086,7 +1086,8 @@ void cec_received_msg_ts(struct cec_adapter *adap,
mutex_lock(&adap->lock);
dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg);
- adap->last_initiator = 0xff;
+ if (!adap->transmit_in_progress)
+ adap->last_initiator = 0xff;
/* Check if this message was for us (directed or broadcast). */
if (!cec_msg_is_broadcast(msg))
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 753f9ea254d4..287705729064 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -981,11 +981,8 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) {
if (data && !cmd->error)
data->bytes_xfered = data->blksz * data->blocks;
- if (meson_mmc_bounce_buf_read(data) ||
- meson_mmc_get_next_command(cmd))
- ret = IRQ_WAKE_THREAD;
- else
- ret = IRQ_HANDLED;
+
+ return IRQ_WAKE_THREAD;
}
out:
@@ -997,9 +994,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
writel(start, host->regs + SD_EMMC_START);
}
- if (ret == IRQ_HANDLED)
- meson_mmc_request_done(host->mmc, cmd->mrq);
-
return ret;
}
@@ -1185,8 +1179,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
}
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0) {
- ret = -EINVAL;
+ if (host->irq < 0) {
+ ret = host->irq;
goto free_host;
}
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 2c4eda83ca18..090246aa6f03 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1729,7 +1729,8 @@ static void mmci_set_max_busy_timeout(struct mmc_host *mmc)
return;
if (host->variant->busy_timeout && mmc->actual_clock)
- max_busy_timeout = ~0UL / (mmc->actual_clock / MSEC_PER_SEC);
+ max_busy_timeout = U32_MAX / DIV_ROUND_UP(mmc->actual_clock,
+ MSEC_PER_SEC);
mmc->max_busy_timeout = max_busy_timeout;
}
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 9871c19d2b4e..6d0fc247bddb 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -2525,7 +2525,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
- ret = -EINVAL;
+ ret = host->irq;
goto host_free;
}
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 629efbe639c4..b4f6a0a2fcb5 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -704,7 +704,7 @@ static int mvsd_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0)
- return -ENXIO;
+ return irq;
mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
if (!mmc) {
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 5e5af34090f1..ecf2a68d0e84 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1343,7 +1343,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0)
- return -ENXIO;
+ return irq;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
host->virt_base = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index eb0bd46b7e81..500c906413a7 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1832,9 +1832,11 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (res == NULL || irq < 0)
+ if (!res)
return -ENXIO;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c
index 3dc143b03939..679b8b0b310e 100644
--- a/drivers/mmc/host/owl-mmc.c
+++ b/drivers/mmc/host/owl-mmc.c
@@ -638,7 +638,7 @@ static int owl_mmc_probe(struct platform_device *pdev)
owl_host->irq = platform_get_irq(pdev, 0);
if (owl_host->irq < 0) {
- ret = -EINVAL;
+ ret = owl_host->irq;
goto err_release_channel;
}
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 8fe65f172a61..f4e15eef7045 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -910,7 +910,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
host->ops = &sdhci_acpi_ops_dflt;
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
- err = -EINVAL;
+ err = host->irq;
goto err_free;
}
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 83d38e44fc25..6537a845266d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2482,6 +2482,9 @@ static inline void sdhci_msm_get_of_property(struct platform_device *pdev,
msm_host->ddr_config = DDR_CONFIG_POR_VAL;
of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config);
+
+ if (of_device_is_compatible(node, "qcom,msm8916-sdhci"))
+ host->quirks2 |= SDHCI_QUIRK2_BROKEN_64_BIT_DMA;
}
static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index bcc595c70a9f..e12fe29b275c 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1398,7 +1398,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
irq[0] = platform_get_irq(pdev, 0);
irq[1] = platform_get_irq_optional(pdev, 1);
if (irq[0] < 0)
- return -ENXIO;
+ return irq[0];
reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg))
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c
index 99515be6e5e5..2032e4e1ee68 100644
--- a/drivers/mmc/host/usdhi6rol0.c
+++ b/drivers/mmc/host/usdhi6rol0.c
@@ -1757,8 +1757,10 @@ static int usdhi6_probe(struct platform_device *pdev)
irq_cd = platform_get_irq_byname(pdev, "card detect");
irq_sd = platform_get_irq_byname(pdev, "data");
irq_sdio = platform_get_irq_byname(pdev, "SDIO");
- if (irq_sd < 0 || irq_sdio < 0)
- return -ENODEV;
+ if (irq_sd < 0)
+ return irq_sd;
+ if (irq_sdio < 0)
+ return irq_sdio;
mmc = mmc_alloc_host(sizeof(struct usdhi6_host), dev);
if (!mmc)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 4ec598efc333..f74d9fbd0817 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -993,6 +993,14 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
mutex_unlock(&priv->reg_mutex);
}
+static void
+mt753x_trap_frames(struct mt7530_priv *priv)
+{
+ /* Trap BPDUs to the CPU port(s) */
+ mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
+ MT753X_BPDU_CPU_ONLY);
+}
+
static int
mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
{
@@ -1015,7 +1023,7 @@ mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
UNU_FFP(BIT(port)));
/* Set CPU port number */
- if (priv->id == ID_MT7621)
+ if (priv->id == ID_MT7530 || priv->id == ID_MT7621)
mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
/* CPU port gets connected to all user ports of
@@ -2194,6 +2202,8 @@ mt7530_setup(struct dsa_switch *ds)
priv->p6_interface = PHY_INTERFACE_MODE_NA;
+ mt753x_trap_frames(priv);
+
/* Enable and reset MIB counters */
mt7530_mib_reset(ds);
@@ -2300,8 +2310,8 @@ mt7531_setup_common(struct dsa_switch *ds)
BIT(cpu_dp->index));
break;
}
- mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
- MT753X_BPDU_CPU_ONLY);
+
+ mt753x_trap_frames(priv);
/* Enable and reset MIB counters */
mt7530_mib_reset(ds);
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 361c1c87c183..e874b907bfbd 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1136,8 +1136,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
VLAN_ETH_HLEN : ETH_HLEN;
if (skb->len <= 60 &&
- (lancer_chip(adapter) || skb_vlan_tag_present(skb)) &&
- is_ipv4_pkt(skb)) {
+ (lancer_chip(adapter) || BE3_chip(adapter) ||
+ skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
ip = (struct iphdr *)ip_hdr(skb);
pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
}
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index 8427fe1b8fd1..2205bb437e68 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -582,8 +582,7 @@ qcaspi_spi_thread(void *data)
while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE);
if ((qca->intr_req == qca->intr_svc) &&
- (qca->txr.skb[qca->txr.head] == NULL) &&
- (qca->sync == QCASPI_SYNC_READY))
+ !qca->txr.skb[qca->txr.head])
schedule();
set_current_state(TASK_RUNNING);
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 36f1c5aa98fc..1ab1ba41c430 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -522,7 +522,7 @@ static int hwsim_del_edge_nl(struct sk_buff *msg, struct genl_info *info)
static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
{
struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1];
- struct hwsim_edge_info *einfo;
+ struct hwsim_edge_info *einfo, *einfo_old;
struct hwsim_phy *phy_v0;
struct hwsim_edge *e;
u32 v0, v1;
@@ -560,8 +560,10 @@ static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
list_for_each_entry_rcu(e, &phy_v0->edges, list) {
if (e->endpoint->idx == v1) {
einfo->lqi = lqi;
- rcu_assign_pointer(e->info, einfo);
+ einfo_old = rcu_replace_pointer(e->info, einfo,
+ lockdep_is_held(&hwsim_phys_lock));
rcu_read_unlock();
+ kfree_rcu(einfo_old, rcu);
mutex_unlock(&hwsim_phys_lock);
return 0;
}
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 6230dd5e2990..76ca43108d99 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -836,7 +836,7 @@ static int dp83867_phy_reset(struct phy_device *phydev)
{
int err;
- err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART);
+ err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET);
if (err < 0)
return err;
diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c
index 85bf8d586c70..0f6befe8be1e 100644
--- a/drivers/nfc/nfcsim.c
+++ b/drivers/nfc/nfcsim.c
@@ -336,10 +336,6 @@ static struct dentry *nfcsim_debugfs_root;
static void nfcsim_debugfs_init(void)
{
nfcsim_debugfs_root = debugfs_create_dir("nfcsim", NULL);
-
- if (!nfcsim_debugfs_root)
- pr_err("Could not create debugfs entry\n");
-
}
static void nfcsim_debugfs_remove(void)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index e5318b38c662..98a7649a0f06 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1247,9 +1247,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU);
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+ unsigned long delay = ctrl->kato * HZ / 2;
+
+ /*
+ * When using Traffic Based Keep Alive, we need to run
+ * nvme_keep_alive_work at twice the normal frequency, as one
+ * command completion can postpone sending a keep alive command
+ * by up to twice the delay between runs.
+ */
+ if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+ delay /= 2;
+ return delay;
+}
+
static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
{
- queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work,
+ nvme_keep_alive_work_period(ctrl));
}
static void nvme_keep_alive_end_io(struct request *rq, blk_status_t status)
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 9b54715a4b63..9b15c0130bbb 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -483,7 +483,10 @@ struct hv_pcibus_device {
struct fwnode_handle *fwnode;
/* Protocol version negotiated with the host */
enum pci_protocol_version_t protocol_version;
+
+ struct mutex state_lock;
enum hv_pcibus_state state;
+
struct hv_device *hdev;
resource_size_t low_mmio_space;
resource_size_t high_mmio_space;
@@ -547,19 +550,10 @@ struct hv_dr_state {
struct hv_pcidev_description func[];
};
-enum hv_pcichild_state {
- hv_pcichild_init = 0,
- hv_pcichild_requirements,
- hv_pcichild_resourced,
- hv_pcichild_ejecting,
- hv_pcichild_maximum
-};
-
struct hv_pci_dev {
/* List protected by pci_rescan_remove_lock */
struct list_head list_entry;
refcount_t refs;
- enum hv_pcichild_state state;
struct pci_slot *pci_slot;
struct hv_pcidev_description desc;
bool reported_missing;
@@ -1261,6 +1255,11 @@ static void hv_irq_unmask(struct irq_data *data)
pbus = pdev->bus;
hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
int_desc = data->chip_data;
+ if (!int_desc) {
+ dev_warn(&hbus->hdev->device, "%s() can not unmask irq %u\n",
+ __func__, data->irq);
+ return;
+ }
spin_lock_irqsave(&hbus->retarget_msi_interrupt_lock, flags);
@@ -1610,12 +1609,6 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
hv_pci_onchannelcallback(hbus);
spin_unlock_irqrestore(&channel->sched_lock, flags);
- if (hpdev->state == hv_pcichild_ejecting) {
- dev_err_once(&hbus->hdev->device,
- "the device is being ejected\n");
- goto enable_tasklet;
- }
-
udelay(100);
}
@@ -2201,6 +2194,8 @@ static void pci_devices_present_work(struct work_struct *work)
if (!dr)
return;
+ mutex_lock(&hbus->state_lock);
+
/* First, mark all existing children as reported missing. */
spin_lock_irqsave(&hbus->device_list_lock, flags);
list_for_each_entry(hpdev, &hbus->children, list_entry) {
@@ -2282,6 +2277,8 @@ static void pci_devices_present_work(struct work_struct *work)
break;
}
+ mutex_unlock(&hbus->state_lock);
+
kfree(dr);
}
@@ -2430,7 +2427,7 @@ static void hv_eject_device_work(struct work_struct *work)
hpdev = container_of(work, struct hv_pci_dev, wrk);
hbus = hpdev->hbus;
- WARN_ON(hpdev->state != hv_pcichild_ejecting);
+ mutex_lock(&hbus->state_lock);
/*
* Ejection can come before or after the PCI bus has been set up, so
@@ -2468,6 +2465,8 @@ static void hv_eject_device_work(struct work_struct *work)
put_pcichild(hpdev);
put_pcichild(hpdev);
/* hpdev has been freed. Do not use it any more. */
+
+ mutex_unlock(&hbus->state_lock);
}
/**
@@ -2488,7 +2487,6 @@ static void hv_pci_eject_device(struct hv_pci_dev *hpdev)
return;
}
- hpdev->state = hv_pcichild_ejecting;
get_pcichild(hpdev);
INIT_WORK(&hpdev->wrk, hv_eject_device_work);
queue_work(hbus->wq, &hpdev->wrk);
@@ -2889,8 +2887,10 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
struct pci_bus_d0_entry *d0_entry;
struct hv_pci_compl comp_pkt;
struct pci_packet *pkt;
+ bool retry = true;
int ret;
+enter_d0_retry:
/*
* Tell the host that the bus is ready to use, and moved into the
* powered-on state. This includes telling the host which region
@@ -2917,6 +2917,38 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
if (ret)
goto exit;
+ /*
+ * In certain case (Kdump) the pci device of interest was
+ * not cleanly shut down and resource is still held on host
+ * side, the host could return invalid device status.
+ * We need to explicitly request host to release the resource
+ * and try to enter D0 again.
+ */
+ if (comp_pkt.completion_status < 0 && retry) {
+ retry = false;
+
+ dev_err(&hdev->device, "Retrying D0 Entry\n");
+
+ /*
+ * Hv_pci_bus_exit() calls hv_send_resource_released()
+ * to free up resources of its child devices.
+ * In the kdump kernel we need to set the
+ * wslot_res_allocated to 255 so it scans all child
+ * devices to release resources allocated in the
+ * normal kernel before panic happened.
+ */
+ hbus->wslot_res_allocated = 255;
+
+ ret = hv_pci_bus_exit(hdev, true);
+
+ if (ret == 0) {
+ kfree(pkt);
+ goto enter_d0_retry;
+ }
+ dev_err(&hdev->device,
+ "Retrying D0 failed with ret %d\n", ret);
+ }
+
if (comp_pkt.completion_status < 0) {
dev_err(&hdev->device,
"PCI Pass-through VSP failed D0 Entry with status %x\n",
@@ -2959,6 +2991,24 @@ static int hv_pci_query_relations(struct hv_device *hdev)
if (!ret)
ret = wait_for_response(hdev, &comp);
+ /*
+ * In the case of fast device addition/removal, it's possible that
+ * vmbus_sendpacket() or wait_for_response() returns -ENODEV but we
+ * already got a PCI_BUS_RELATIONS* message from the host and the
+ * channel callback already scheduled a work to hbus->wq, which can be
+ * running pci_devices_present_work() -> survey_child_resources() ->
+ * complete(&hbus->survey_event), even after hv_pci_query_relations()
+ * exits and the stack variable 'comp' is no longer valid; as a result,
+ * a hang or a page fault may happen when the complete() calls
+ * raw_spin_lock_irqsave(). Flush hbus->wq before we exit from
+ * hv_pci_query_relations() to avoid the issues. Note: if 'ret' is
+ * -ENODEV, there can't be any more work item scheduled to hbus->wq
+ * after the flush_workqueue(): see vmbus_onoffer_rescind() ->
+ * vmbus_reset_channel_cb(), vmbus_rescind_cleanup() ->
+ * channel->rescind = true.
+ */
+ flush_workqueue(hbus->wq);
+
return ret;
}
@@ -3144,7 +3194,6 @@ static int hv_pci_probe(struct hv_device *hdev,
struct hv_pcibus_device *hbus;
u16 dom_req, dom;
char *name;
- bool enter_d0_retry = true;
int ret;
/*
@@ -3180,6 +3229,7 @@ static int hv_pci_probe(struct hv_device *hdev,
return -ENOMEM;
hbus->bridge = bridge;
+ mutex_init(&hbus->state_lock);
hbus->state = hv_pcibus_init;
hbus->wslot_res_allocated = -1;
@@ -3280,49 +3330,15 @@ static int hv_pci_probe(struct hv_device *hdev,
if (ret)
goto free_fwnode;
-retry:
ret = hv_pci_query_relations(hdev);
if (ret)
goto free_irq_domain;
- ret = hv_pci_enter_d0(hdev);
- /*
- * In certain case (Kdump) the pci device of interest was
- * not cleanly shut down and resource is still held on host
- * side, the host could return invalid device status.
- * We need to explicitly request host to release the resource
- * and try to enter D0 again.
- * Since the hv_pci_bus_exit() call releases structures
- * of all its child devices, we need to start the retry from
- * hv_pci_query_relations() call, requesting host to send
- * the synchronous child device relations message before this
- * information is needed in hv_send_resources_allocated()
- * call later.
- */
- if (ret == -EPROTO && enter_d0_retry) {
- enter_d0_retry = false;
-
- dev_err(&hdev->device, "Retrying D0 Entry\n");
-
- /*
- * Hv_pci_bus_exit() calls hv_send_resources_released()
- * to free up resources of its child devices.
- * In the kdump kernel we need to set the
- * wslot_res_allocated to 255 so it scans all child
- * devices to release resources allocated in the
- * normal kernel before panic happened.
- */
- hbus->wslot_res_allocated = 255;
- ret = hv_pci_bus_exit(hdev, true);
-
- if (ret == 0)
- goto retry;
+ mutex_lock(&hbus->state_lock);
- dev_err(&hdev->device,
- "Retrying D0 failed with ret %d\n", ret);
- }
+ ret = hv_pci_enter_d0(hdev);
if (ret)
- goto free_irq_domain;
+ goto release_state_lock;
ret = hv_pci_allocate_bridge_windows(hbus);
if (ret)
@@ -3340,12 +3356,15 @@ static int hv_pci_probe(struct hv_device *hdev,
if (ret)
goto free_windows;
+ mutex_unlock(&hbus->state_lock);
return 0;
free_windows:
hv_pci_free_bridge_windows(hbus);
exit_d0:
(void) hv_pci_bus_exit(hdev, true);
+release_state_lock:
+ mutex_unlock(&hbus->state_lock);
free_irq_domain:
irq_domain_remove(hbus->irq_domain);
free_fwnode:
@@ -3578,20 +3597,26 @@ static int hv_pci_resume(struct hv_device *hdev)
if (ret)
goto out;
+ mutex_lock(&hbus->state_lock);
+
ret = hv_pci_enter_d0(hdev);
if (ret)
- goto out;
+ goto release_state_lock;
ret = hv_send_resources_allocated(hdev);
if (ret)
- goto out;
+ goto release_state_lock;
prepopulate_bars(hbus);
hv_pci_restore_msi_state(hbus);
hbus->state = hv_pcibus_installed;
+ mutex_unlock(&hbus->state_lock);
return 0;
+
+release_state_lock:
+ mutex_unlock(&hbus->state_lock);
out:
vmbus_close(hdev->channel);
return ret;
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index b21fa57d1a46..a111154a9046 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1379,6 +1379,7 @@ void ccw_device_set_notoper(struct ccw_device *cdev)
enum io_sch_action {
IO_SCH_UNREG,
IO_SCH_ORPH_UNREG,
+ IO_SCH_UNREG_CDEV,
IO_SCH_ATTACH,
IO_SCH_UNREG_ATTACH,
IO_SCH_ORPH_ATTACH,
@@ -1411,7 +1412,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
}
if ((sch->schib.pmcw.pam & sch->opm) == 0) {
if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK)
- return IO_SCH_UNREG;
+ return IO_SCH_UNREG_CDEV;
return IO_SCH_DISC;
}
if (device_is_disconnected(cdev))
@@ -1473,6 +1474,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
case IO_SCH_ORPH_ATTACH:
ccw_device_set_disconnected(cdev);
break;
+ case IO_SCH_UNREG_CDEV:
case IO_SCH_UNREG_ATTACH:
case IO_SCH_UNREG:
if (!cdev)
@@ -1506,6 +1508,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
if (rc)
goto out;
break;
+ case IO_SCH_UNREG_CDEV:
case IO_SCH_UNREG_ATTACH:
spin_lock_irqsave(sch->lock, flags);
sch_set_cdev(sch, NULL);
diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c
index 2bf534632f64..39f0cc2a5b33 100644
--- a/drivers/soundwire/dmi-quirks.c
+++ b/drivers/soundwire/dmi-quirks.c
@@ -63,6 +63,13 @@ static const struct dmi_system_id adr_remap_quirk_table[] = {
},
.driver_data = (void *)intel_tgl_bios,
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8709"),
+ },
+ .driver_data = (void *)intel_tgl_bios,
+ },
{
/* quirk used for NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
.matches = {
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 5d98611dd999..c5ff6e8c45be 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -906,9 +906,14 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller);
if (ret == -EPROBE_DEFER)
goto out_pm_get;
-
if (ret < 0)
dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret);
+ else
+ /*
+ * disable LPSPI module IRQ when enable DMA mode successfully,
+ * to prevent the unexpected LPSPI module IRQ events.
+ */
+ disable_irq(irq);
ret = devm_spi_register_controller(&pdev->dev, controller);
if (ret < 0) {
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index c0ed6f8e5c5b..32a2852352db 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -1071,6 +1071,7 @@ int iscsi_target_locate_portal(
iscsi_target_set_sock_callbacks(conn);
login->np = np;
+ conn->tpg = NULL;
login_req = (struct iscsi_login_req *) login->req;
payload_length = ntoh24(login_req->dlength);
@@ -1138,7 +1139,6 @@ int iscsi_target_locate_portal(
*/
sessiontype = strncmp(s_buf, DISCOVERY, 9);
if (!sessiontype) {
- conn->tpg = iscsit_global->discovery_tpg;
if (!login->leading_connection)
goto get_target;
@@ -1155,9 +1155,11 @@ int iscsi_target_locate_portal(
* Serialize access across the discovery struct iscsi_portal_group to
* process login attempt.
*/
+ conn->tpg = iscsit_global->discovery_tpg;
if (iscsit_access_np(np, conn->tpg) < 0) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
+ conn->tpg = NULL;
ret = -1;
goto out;
}
diff --git a/drivers/usb/gadget/udc/amd5536udc_pci.c b/drivers/usb/gadget/udc/amd5536udc_pci.c
index c80f9bd51b75..a36913ae31f9 100644
--- a/drivers/usb/gadget/udc/amd5536udc_pci.c
+++ b/drivers/usb/gadget/udc/amd5536udc_pci.c
@@ -170,6 +170,9 @@ static int udc_pci_probe(
retval = -ENODEV;
goto err_probe;
}
+
+ udc = dev;
+
return 0;
err_probe:
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 32148f011200..00f10d340259 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -933,13 +933,18 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock)
err = sock->ops->sendmsg(sock, &msg, len);
if (unlikely(err < 0)) {
+ bool retry = err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS;
+
if (zcopy_used) {
if (vq->heads[ubuf->desc].len == VHOST_DMA_IN_PROGRESS)
vhost_net_ubuf_put(ubufs);
- nvq->upend_idx = ((unsigned)nvq->upend_idx - 1)
- % UIO_MAXIOV;
+ if (retry)
+ nvq->upend_idx = ((unsigned)nvq->upend_idx - 1)
+ % UIO_MAXIOV;
+ else
+ vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
}
- if (err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS) {
+ if (retry) {
vhost_discard_vq_desc(vq, 1);
vhost_net_enable_vq(net, vq);
break;
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index d1a148f0cae3..81992b9a219b 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -369,7 +369,15 @@ void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
struct page *page = pvec.pages[i];
lock_page(page);
- nilfs_clear_dirty_page(page, silent);
+
+ /*
+ * This page may have been removed from the address
+ * space by truncation or invalidation when the lock
+ * was acquired. Skip processing in that case.
+ */
+ if (likely(page->mapping == mapping))
+ nilfs_clear_dirty_page(page, silent);
+
unlock_page(page);
}
pagevec_release(&pvec);
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c
index 56872e93823d..5e845eea1af0 100644
--- a/fs/nilfs2/segbuf.c
+++ b/fs/nilfs2/segbuf.c
@@ -101,6 +101,12 @@ int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *segbuf)
if (unlikely(!bh))
return -ENOMEM;
+ lock_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ memset(bh->b_data, 0, bh->b_size);
+ set_buffer_uptodate(bh);
+ }
+ unlock_buffer(bh);
nilfs_segbuf_add_segsum_buffer(segbuf, bh);
return 0;
}
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index c25f28094508..5c310eb7dd0c 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -979,10 +979,13 @@ static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci,
unsigned int isz, srsz;
bh_sr = NILFS_LAST_SEGBUF(&sci->sc_segbufs)->sb_super_root;
+
+ lock_buffer(bh_sr);
raw_sr = (struct nilfs_super_root *)bh_sr->b_data;
isz = nilfs->ns_inode_size;
srsz = NILFS_SR_BYTES(isz);
+ raw_sr->sr_sum = 0; /* Ensure initialization within this update */
raw_sr->sr_bytes = cpu_to_le16(srsz);
raw_sr->sr_nongc_ctime
= cpu_to_le64(nilfs_doing_gc() ?
@@ -996,6 +999,8 @@ static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci,
nilfs_write_inode_common(nilfs->ns_sufile, (void *)raw_sr +
NILFS_SR_SUFILE_OFFSET(isz), 1);
memset((void *)raw_sr + srsz, 0, nilfs->ns_blocksize - srsz);
+ set_buffer_uptodate(bh_sr);
+ unlock_buffer(bh_sr);
}
static void nilfs_redirty_inodes(struct list_head *head)
@@ -1778,6 +1783,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
list_for_each_entry(segbuf, logs, sb_list) {
list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
b_assoc_buffers) {
+ clear_buffer_uptodate(bh);
if (bh->b_page != bd_page) {
if (bd_page)
end_page_writeback(bd_page);
@@ -1789,6 +1795,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
b_assoc_buffers) {
clear_buffer_async_write(bh);
if (bh == segbuf->sb_super_root) {
+ clear_buffer_uptodate(bh);
if (bh->b_page != bd_page) {
end_page_writeback(bd_page);
bd_page = bh->b_page;
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 9d5e4ce7426b..130ffa8a9bed 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -372,10 +372,31 @@ static int nilfs_move_2nd_super(struct super_block *sb, loff_t sb2off)
goto out;
}
nsbp = (void *)nsbh->b_data + offset;
- memset(nsbp, 0, nilfs->ns_blocksize);
+ lock_buffer(nsbh);
if (sb2i >= 0) {
+ /*
+ * The position of the second superblock only changes by 4KiB,
+ * which is larger than the maximum superblock data size
+ * (= 1KiB), so there is no need to use memmove() to allow
+ * overlap between source and destination.
+ */
memcpy(nsbp, nilfs->ns_sbp[sb2i], nilfs->ns_sbsize);
+
+ /*
+ * Zero fill after copy to avoid overwriting in case of move
+ * within the same block.
+ */
+ memset(nsbh->b_data, 0, offset);
+ memset((void *)nsbp + nilfs->ns_sbsize, 0,
+ nsbh->b_size - offset - nilfs->ns_sbsize);
+ } else {
+ memset(nsbh->b_data, 0, nsbh->b_size);
+ }
+ set_buffer_uptodate(nsbh);
+ unlock_buffer(nsbh);
+
+ if (sb2i >= 0) {
brelse(nilfs->ns_sbh[sb2i]);
nilfs->ns_sbh[sb2i] = nsbh;
nilfs->ns_sbp[sb2i] = nsbp;
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index fa02e3ff0faf..9d45a6001bc0 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -749,6 +749,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_event_status
*event_status))
ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number))
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_hw_disable_all_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 11c26ae7b4fa..65df2ce96f0b 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -168,11 +168,18 @@ struct gpio_irq_chip {
/**
* @parent_handler_data:
+ * @parent_handler_data_array:
*
* Data associated, and passed to, the handler for the parent
- * interrupt.
+ * interrupt. Can either be a single pointer if @per_parent_data
+ * is false, or an array of @num_parents pointers otherwise. If
+ * @per_parent_data is true, @parent_handler_data_array cannot be
+ * NULL.
*/
- void *parent_handler_data;
+ union {
+ void *parent_handler_data;
+ void **parent_handler_data_array;
+ };
/**
* @num_parents:
@@ -203,6 +210,14 @@ struct gpio_irq_chip {
*/
bool threaded;
+ /**
+ * @per_parent_data:
+ *
+ * True if parent_handler_data_array describes a @num_parents
+ * sized array to be used as parent data.
+ */
+ bool per_parent_data;
+
/**
* @init_hw: optional routine to initialize hardware before
* an IRQ chip will be added. This is quite useful when
diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h
index 71902f41c919..0c3edff6bdff 100644
--- a/include/linux/regulator/pca9450.h
+++ b/include/linux/regulator/pca9450.h
@@ -196,11 +196,11 @@ enum {
/* PCA9450_REG_LDO3_VOLT bits */
#define LDO3_EN_MASK 0xC0
-#define LDO3OUT_MASK 0x0F
+#define LDO3OUT_MASK 0x1F
/* PCA9450_REG_LDO4_VOLT bits */
#define LDO4_EN_MASK 0xC0
-#define LDO4OUT_MASK 0x0F
+#define LDO4OUT_MASK 0x1F
/* PCA9450_REG_LDO5_VOLT bits */
#define LDO5L_EN_MASK 0xC0
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 37d5d4968e20..4eb0edc6640d 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -377,9 +377,11 @@ static inline int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph,
const struct sk_buff *skb)
{
- if (skb->protocol == htons(ETH_P_IP))
+ __be16 payload_protocol = skb_protocol(skb, true);
+
+ if (payload_protocol == htons(ETH_P_IP))
return iph->tos;
- else if (skb->protocol == htons(ETH_P_IPV6))
+ else if (payload_protocol == htons(ETH_P_IPV6))
return ipv6_get_dsfield((const struct ipv6hdr *)iph);
else
return 0;
@@ -388,9 +390,11 @@ static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph,
static inline u8 ip_tunnel_get_ttl(const struct iphdr *iph,
const struct sk_buff *skb)
{
- if (skb->protocol == htons(ETH_P_IP))
+ __be16 payload_protocol = skb_protocol(skb, true);
+
+ if (payload_protocol == htons(ETH_P_IP))
return iph->ttl;
- else if (skb->protocol == htons(ETH_P_IPV6))
+ else if (payload_protocol == htons(ETH_P_IPV6))
return ((const struct ipv6hdr *)iph)->hop_limit;
else
return 0;
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 8bac5a5ca0f1..7da74b9428b9 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -863,6 +863,7 @@ struct nft_expr_type {
enum nft_trans_phase {
NFT_TRANS_PREPARE,
+ NFT_TRANS_PREPARE_ERROR,
NFT_TRANS_ABORT,
NFT_TRANS_COMMIT,
NFT_TRANS_RELEASE
@@ -968,7 +969,10 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
return (void *)&rule->data[rule->dlen];
}
-void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule);
+void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule);
+void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule,
+ enum nft_trans_phase phase);
+void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule);
static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
struct nft_regs *regs,
@@ -1037,6 +1041,8 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
const struct nft_set_iter *iter,
struct nft_set_elem *elem);
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
+int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
+void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
enum nft_chain_types {
NFT_CHAIN_T_DEFAULT = 0,
@@ -1073,11 +1079,17 @@ int nft_chain_validate_dependency(const struct nft_chain *chain,
int nft_chain_validate_hooks(const struct nft_chain *chain,
unsigned int hook_flags);
+static inline bool nft_chain_binding(const struct nft_chain *chain)
+{
+ return chain->flags & NFT_CHAIN_BINDING;
+}
+
static inline bool nft_chain_is_bound(struct nft_chain *chain)
{
return (chain->flags & NFT_CHAIN_BINDING) && chain->bound;
}
+int nft_chain_add(struct nft_table *table, struct nft_chain *chain);
void nft_chain_del(struct nft_chain *chain);
void nf_tables_chain_destroy(struct nft_ctx *ctx);
@@ -1491,6 +1503,7 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
* struct nft_trans - nf_tables object update in transaction
*
* @list: used internally
+ * @binding_list: list of objects with possible bindings
* @msg_type: message type
* @put_net: ctx->net needs to be put
* @ctx: transaction context
@@ -1498,6 +1511,7 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
*/
struct nft_trans {
struct list_head list;
+ struct list_head binding_list;
int msg_type;
bool put_net;
struct nft_ctx ctx;
@@ -1508,6 +1522,7 @@ struct nft_trans_rule {
struct nft_rule *rule;
struct nft_flow_rule *flow;
u32 rule_id;
+ bool bound;
};
#define nft_trans_rule(trans) \
@@ -1516,6 +1531,8 @@ struct nft_trans_rule {
(((struct nft_trans_rule *)trans->data)->flow)
#define nft_trans_rule_id(trans) \
(((struct nft_trans_rule *)trans->data)->rule_id)
+#define nft_trans_rule_bound(trans) \
+ (((struct nft_trans_rule *)trans->data)->bound)
struct nft_trans_set {
struct nft_set *set;
@@ -1540,13 +1557,17 @@ struct nft_trans_set {
(((struct nft_trans_set *)trans->data)->gc_int)
struct nft_trans_chain {
+ struct nft_chain *chain;
bool update;
char *name;
struct nft_stats __percpu *stats;
u8 policy;
+ bool bound;
u32 chain_id;
};
+#define nft_trans_chain(trans) \
+ (((struct nft_trans_chain *)trans->data)->chain)
#define nft_trans_chain_update(trans) \
(((struct nft_trans_chain *)trans->data)->update)
#define nft_trans_chain_name(trans) \
@@ -1555,6 +1576,8 @@ struct nft_trans_chain {
(((struct nft_trans_chain *)trans->data)->stats)
#define nft_trans_chain_policy(trans) \
(((struct nft_trans_chain *)trans->data)->policy)
+#define nft_trans_chain_bound(trans) \
+ (((struct nft_trans_chain *)trans->data)->bound)
#define nft_trans_chain_id(trans) \
(((struct nft_trans_chain *)trans->data)->chain_id)
@@ -1627,6 +1650,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
struct nftables_pernet {
struct list_head tables;
struct list_head commit_list;
+ struct list_head binding_list;
struct list_head module_list;
struct list_head notify_list;
struct mutex commit_mutex;
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 73030094c6e6..6156ed2950f9 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1026,6 +1026,7 @@ struct xfrm_offload {
struct sec_path {
int len;
int olen;
+ int verified_cnt;
struct xfrm_state *xvec[XFRM_MAX_DEPTH];
struct xfrm_offload ovec[XFRM_MAX_OFFLOAD_DEPTH];
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 840d1ba84cf5..9d8303a93a36 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -68,7 +68,7 @@ DECLARE_EVENT_CLASS(writeback_page_template,
strscpy_pad(__entry->name,
bdi_dev_name(mapping ? inode_to_bdi(mapping->host) :
NULL), 32);
- __entry->ino = mapping ? mapping->host->i_ino : 0;
+ __entry->ino = (mapping && mapping->host) ? mapping->host->i_ino : 0;
__entry->index = page->index;
),
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 1d8adc57a44a..cbfc9bbe87b0 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -581,6 +581,7 @@ struct io_sr_msg {
size_t len;
size_t done_io;
struct io_buffer *kbuf;
+ void __user *msg_control;
};
struct io_open {
@@ -4864,10 +4865,16 @@ static int io_setup_async_msg(struct io_kiocb *req,
static int io_sendmsg_copy_hdr(struct io_kiocb *req,
struct io_async_msghdr *iomsg)
{
+ struct io_sr_msg *sr = &req->sr_msg;
+ int ret;
+
iomsg->msg.msg_name = &iomsg->addr;
iomsg->free_iov = iomsg->fast_iov;
- return sendmsg_copy_msghdr(&iomsg->msg, req->sr_msg.umsg,
+ ret = sendmsg_copy_msghdr(&iomsg->msg, req->sr_msg.umsg,
req->sr_msg.msg_flags, &iomsg->free_iov);
+ /* save msg_control as sys_sendmsg() overwrites it */
+ sr->msg_control = iomsg->msg.msg_control;
+ return ret;
}
static int io_sendmsg_prep_async(struct io_kiocb *req)
@@ -4924,6 +4931,8 @@ static int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
if (ret)
return ret;
kmsg = &iomsg;
+ } else {
+ kmsg->msg.msg_control = sr->msg_control;
}
flags = req->sr_msg.msg_flags;
@@ -4940,6 +4949,8 @@ static int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
if (ret == -ERESTARTSYS)
ret = -EINTR;
if (ret > 0 && io_net_retry(sock, flags)) {
+ kmsg->msg.msg_controllen = 0;
+ kmsg->msg.msg_control = NULL;
sr->done_io += ret;
req->flags |= REQ_F_PARTIAL_IO;
return io_setup_async_msg(req, kmsg);
@@ -5190,7 +5201,7 @@ static int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
flags = req->sr_msg.msg_flags;
if (force_nonblock)
flags |= MSG_DONTWAIT;
- if (flags & MSG_WAITALL)
+ if (flags & MSG_WAITALL && !kmsg->msg.msg_controllen)
min_ret = iov_iter_count(&kmsg->msg.msg_iter);
ret = __sys_recvmsg_sock(sock, &kmsg->msg, req->sr_msg.umsg,
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 6c7126de5c17..5d4bea53ac1f 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -633,13 +633,12 @@ static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
return offset < btf->hdr.str_len;
}
-static bool __btf_name_char_ok(char c, bool first, bool dot_ok)
+static bool __btf_name_char_ok(char c, bool first)
{
if ((first ? !isalpha(c) :
!isalnum(c)) &&
c != '_' &&
- ((c == '.' && !dot_ok) ||
- c != '.'))
+ c != '.')
return false;
return true;
}
@@ -656,20 +655,20 @@ static const char *btf_str_by_offset(const struct btf *btf, u32 offset)
return NULL;
}
-static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
+static bool __btf_name_valid(const struct btf *btf, u32 offset)
{
/* offset must be valid */
const char *src = btf_str_by_offset(btf, offset);
const char *src_limit;
- if (!__btf_name_char_ok(*src, true, dot_ok))
+ if (!__btf_name_char_ok(*src, true))
return false;
/* set a limit on identifier length */
src_limit = src + KSYM_NAME_LEN;
src++;
while (*src && src < src_limit) {
- if (!__btf_name_char_ok(*src, false, dot_ok))
+ if (!__btf_name_char_ok(*src, false))
return false;
src++;
}
@@ -677,17 +676,14 @@ static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
return !*src;
}
-/* Only C-style identifier is permitted. This can be relaxed if
- * necessary.
- */
static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
{
- return __btf_name_valid(btf, offset, false);
+ return __btf_name_valid(btf, offset);
}
static bool btf_name_valid_section(const struct btf *btf, u32 offset)
{
- return __btf_name_valid(btf, offset, true);
+ return __btf_name_valid(btf, offset);
}
static const char *__btf_name_by_offset(const struct btf *btf, u32 offset)
@@ -3536,7 +3532,7 @@ static s32 btf_var_check_meta(struct btf_verifier_env *env,
}
if (!t->name_off ||
- !__btf_name_valid(env->btf, t->name_off, true)) {
+ !__btf_name_valid(env->btf, t->name_off)) {
btf_verifier_log_type(env, t, "Invalid name");
return -EINVAL;
}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 27fd331aefe5..4f2271f27a1d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2659,6 +2659,11 @@ static void save_register_state(struct bpf_func_state *state,
scrub_spilled_slot(&state->stack[spi].slot_type[i - 1]);
}
+static bool is_bpf_st_mem(struct bpf_insn *insn)
+{
+ return BPF_CLASS(insn->code) == BPF_ST && BPF_MODE(insn->code) == BPF_MEM;
+}
+
/* check_stack_{read,write}_fixed_off functions track spill/fill of registers,
* stack boundary and alignment are checked in check_mem_access()
*/
@@ -2670,8 +2675,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
{
struct bpf_func_state *cur; /* state of the current function */
int i, slot = -off - 1, spi = slot / BPF_REG_SIZE, err;
- u32 dst_reg = env->prog->insnsi[insn_idx].dst_reg;
+ struct bpf_insn *insn = &env->prog->insnsi[insn_idx];
struct bpf_reg_state *reg = NULL;
+ u32 dst_reg = insn->dst_reg;
err = grow_stack_state(state, round_up(slot + 1, BPF_REG_SIZE));
if (err)
@@ -2719,6 +2725,16 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
return err;
}
save_register_state(state, spi, reg, size);
+ /* Break the relation on a narrowing spill. */
+ if (fls64(reg->umax_value) > BITS_PER_BYTE * size)
+ state->stack[spi].spilled_ptr.id = 0;
+ } else if (!reg && !(off % BPF_REG_SIZE) && is_bpf_st_mem(insn) &&
+ insn->imm != 0 && env->bpf_capable) {
+ struct bpf_reg_state fake_reg = {};
+
+ __mark_reg_known(&fake_reg, (u32)insn->imm);
+ fake_reg.type = SCALAR_VALUE;
+ save_register_state(state, spi, &fake_reg, size);
} else if (reg && is_spillable_regtype(reg->type)) {
/* register containing pointer is being spilled into stack */
if (size != BPF_REG_SIZE) {
@@ -2753,7 +2769,8 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
state->stack[spi].spilled_ptr.live |= REG_LIVE_WRITTEN;
/* when we zero initialize stack slots mark them as such */
- if (reg && register_is_null(reg)) {
+ if ((reg && register_is_null(reg)) ||
+ (!reg && is_bpf_st_mem(insn) && insn->imm == 0)) {
/* backtracking doesn't work for STACK_ZERO yet. */
err = mark_chain_precision(env, value_regno);
if (err)
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index edae2f49f73f..6ccdbce17399 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1741,7 +1741,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
{
struct cgroup *dcgrp = &dst_root->cgrp;
struct cgroup_subsys *ss;
- int ssid, i, ret;
+ int ssid, ret;
u16 dfl_disable_ss_mask = 0;
lockdep_assert_held(&cgroup_mutex);
@@ -1785,7 +1785,8 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
struct cgroup_root *src_root = ss->root;
struct cgroup *scgrp = &src_root->cgrp;
struct cgroup_subsys_state *css = cgroup_css(scgrp, ss);
- struct css_set *cset;
+ struct css_set *cset, *cset_pos;
+ struct css_task_iter *it;
WARN_ON(!css || cgroup_css(dcgrp, ss));
@@ -1803,9 +1804,22 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
css->cgroup = dcgrp;
spin_lock_irq(&css_set_lock);
- hash_for_each(css_set_table, i, cset, hlist)
+ WARN_ON(!list_empty(&dcgrp->e_csets[ss->id]));
+ list_for_each_entry_safe(cset, cset_pos, &scgrp->e_csets[ss->id],
+ e_cset_node[ss->id]) {
list_move_tail(&cset->e_cset_node[ss->id],
&dcgrp->e_csets[ss->id]);
+ /*
+ * all css_sets of scgrp together in same order to dcgrp,
+ * patch in-flight iterators to preserve correct iteration.
+ * since the iterator is always advanced right away and
+ * finished when it->cset_pos meets it->cset_head, so only
+ * update it->cset_head is enough here.
+ */
+ list_for_each_entry(it, &cset->task_iters, iters_node)
+ if (it->cset_head == &scgrp->e_csets[ss->id])
+ it->cset_head = &dcgrp->e_csets[ss->id];
+ }
spin_unlock_irq(&css_set_lock);
if (ss->css_rstat_flush) {
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 65b8658da829..e9138cd7a0f5 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -218,19 +218,8 @@ static void tick_setup_device(struct tick_device *td,
* this cpu:
*/
if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) {
- ktime_t next_p;
- u32 rem;
-
tick_do_timer_cpu = cpu;
-
- next_p = ktime_get();
- div_u64_rem(next_p, TICK_NSEC, &rem);
- if (rem) {
- next_p -= rem;
- next_p += TICK_NSEC;
- }
-
- tick_next_period = next_p;
+ tick_next_period = ktime_get();
#ifdef CONFIG_NO_HZ_FULL
/*
* The boot CPU may be nohz_full, in which case set
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index e014927c82e7..f42d0776bc84 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -161,8 +161,19 @@ static ktime_t tick_init_jiffy_update(void)
raw_spin_lock(&jiffies_lock);
write_seqcount_begin(&jiffies_seq);
/* Did we start the jiffies update yet ? */
- if (last_jiffies_update == 0)
+ if (last_jiffies_update == 0) {
+ u32 rem;
+
+ /*
+ * Ensure that the tick is aligned to a multiple of
+ * TICK_NSEC.
+ */
+ div_u64_rem(tick_next_period, TICK_NSEC, &rem);
+ if (rem)
+ tick_next_period += TICK_NSEC - rem;
+
last_jiffies_update = tick_next_period;
+ }
period = last_jiffies_update;
write_seqcount_end(&jiffies_seq);
raw_spin_unlock(&jiffies_lock);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index f8b5abd6e36c..0202f23ae960 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2175,10 +2175,12 @@ void tracing_reset_online_cpus(struct array_buffer *buf)
}
/* Must have trace_types_lock held */
-void tracing_reset_all_online_cpus(void)
+void tracing_reset_all_online_cpus_unlocked(void)
{
struct trace_array *tr;
+ lockdep_assert_held(&trace_types_lock);
+
list_for_each_entry(tr, &ftrace_trace_arrays, list) {
if (!tr->clear_trace)
continue;
@@ -2190,6 +2192,13 @@ void tracing_reset_all_online_cpus(void)
}
}
+void tracing_reset_all_online_cpus(void)
+{
+ mutex_lock(&trace_types_lock);
+ tracing_reset_all_online_cpus_unlocked();
+ mutex_unlock(&trace_types_lock);
+}
+
/*
* The tgid_map array maps from pid to tgid; i.e. the value stored at index i
* is the tgid last observed corresponding to pid=i.
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 66b6c8395fbc..2c3d9b6ce148 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -580,6 +580,7 @@ int tracing_is_enabled(void);
void tracing_reset_online_cpus(struct array_buffer *buf);
void tracing_reset_current(int cpu);
void tracing_reset_all_online_cpus(void);
+void tracing_reset_all_online_cpus_unlocked(void);
int tracing_open_generic(struct inode *inode, struct file *filp);
int tracing_open_generic_tr(struct inode *inode, struct file *filp);
bool tracing_is_disabled(void);
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 1aadc9a6487b..160298d285c0 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -2974,7 +2974,7 @@ static void trace_module_remove_events(struct module *mod)
* over from this module may be passed to the new module events and
* unexpected results may occur.
*/
- tracing_reset_all_online_cpus();
+ tracing_reset_all_online_cpus_unlocked();
}
static int trace_module_notify(struct notifier_block *self,
diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
index 2fdf3fd591e1..08c7df42ade7 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -1416,7 +1416,6 @@ int synth_event_delete(const char *event_name)
mutex_unlock(&event_mutex);
if (mod) {
- mutex_lock(&trace_types_lock);
/*
* It is safest to reset the ring buffer if the module
* being unloaded registered any events that were
@@ -1428,7 +1427,6 @@ int synth_event_delete(const char *event_name)
* occur.
*/
tracing_reset_all_online_cpus();
- mutex_unlock(&trace_types_lock);
}
return ret;
diff --git a/mm/memfd.c b/mm/memfd.c
index 475d095dd7f5..a73af8be9c28 100644
--- a/mm/memfd.c
+++ b/mm/memfd.c
@@ -330,7 +330,8 @@ SYSCALL_DEFINE2(memfd_create,
if (flags & MFD_ALLOW_SEALING) {
file_seals = memfd_file_seals_ptr(file);
- *file_seals &= ~F_SEAL_SEAL;
+ if (file_seals)
+ *file_seals &= ~F_SEAL_SEAL;
}
fd_install(fd, file);
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 2ddba1e2cf22..ab6fe94b8fd9 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -337,6 +337,9 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_
secpath_reset(skb);
+ if (skb_needs_linearize(skb, skb->dev->features) &&
+ __skb_linearize(skb))
+ return -ENOMEM;
return 0;
}
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index ad2afeef4f10..eac206a290d0 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -164,6 +164,7 @@ int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb);
return 0;
}
+EXPORT_SYMBOL(xfrm4_udp_encap_rcv);
int xfrm4_rcv(struct sk_buff *skb)
{
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 4cc19acfc369..6b30f34c7978 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -372,6 +372,9 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features
secpath_reset(skb);
+ if (skb_needs_linearize(skb, skb->dev->features) &&
+ __skb_linearize(skb))
+ return -ENOMEM;
return 0;
}
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 04cbeefd8982..4907ab241d6b 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -86,6 +86,9 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
__be32 *udpdata32;
__u16 encap_type = up->encap_type;
+ if (skb->protocol == htons(ETH_P_IP))
+ return xfrm4_udp_encap_rcv(sk, skb);
+
/* if this is not encapsulated socket, then just return now */
if (!encap_type)
return 1;
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index d2e5a8f644b8..cd2130e98836 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -1225,6 +1225,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->transport_header = skb->network_header;
skb_set_inner_ipproto(skb, next_protocol);
+ skb_set_inner_mac_header(skb, skb_inner_network_offset(skb));
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
bool check = false;
@@ -1373,6 +1374,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->transport_header = skb->network_header;
skb_set_inner_ipproto(skb, next_protocol);
+ skb_set_inner_mac_header(skb, skb_inner_network_offset(skb));
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
bool check = false;
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 35b9f74f0bc6..826bd961d90c 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -153,6 +153,7 @@ static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
return NULL;
INIT_LIST_HEAD(&trans->list);
+ INIT_LIST_HEAD(&trans->binding_list);
trans->msg_type = msg_type;
trans->ctx = *ctx;
@@ -165,13 +166,20 @@ static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
}
-static void nft_trans_destroy(struct nft_trans *trans)
+static void nft_trans_list_del(struct nft_trans *trans)
{
list_del(&trans->list);
+ list_del(&trans->binding_list);
+}
+
+static void nft_trans_destroy(struct nft_trans *trans)
+{
+ nft_trans_list_del(trans);
kfree(trans);
}
-static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
+static void __nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set,
+ bool bind)
{
struct nftables_pernet *nft_net;
struct net *net = ctx->net;
@@ -185,16 +193,80 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
switch (trans->msg_type) {
case NFT_MSG_NEWSET:
if (nft_trans_set(trans) == set)
- nft_trans_set_bound(trans) = true;
+ nft_trans_set_bound(trans) = bind;
break;
case NFT_MSG_NEWSETELEM:
if (nft_trans_elem_set(trans) == set)
- nft_trans_elem_set_bound(trans) = true;
+ nft_trans_elem_set_bound(trans) = bind;
+ break;
+ }
+ }
+}
+
+static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ return __nft_set_trans_bind(ctx, set, true);
+}
+
+static void nft_set_trans_unbind(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ return __nft_set_trans_bind(ctx, set, false);
+}
+
+static void __nft_chain_trans_bind(const struct nft_ctx *ctx,
+ struct nft_chain *chain, bool bind)
+{
+ struct nftables_pernet *nft_net;
+ struct net *net = ctx->net;
+ struct nft_trans *trans;
+
+ if (!nft_chain_binding(chain))
+ return;
+
+ nft_net = nft_pernet(net);
+ list_for_each_entry_reverse(trans, &nft_net->commit_list, list) {
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWCHAIN:
+ if (nft_trans_chain(trans) == chain)
+ nft_trans_chain_bound(trans) = bind;
+ break;
+ case NFT_MSG_NEWRULE:
+ if (trans->ctx.chain == chain)
+ nft_trans_rule_bound(trans) = bind;
break;
}
}
}
+static void nft_chain_trans_bind(const struct nft_ctx *ctx,
+ struct nft_chain *chain)
+{
+ __nft_chain_trans_bind(ctx, chain, true);
+}
+
+int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
+{
+ if (!nft_chain_binding(chain))
+ return 0;
+
+ if (nft_chain_binding(ctx->chain))
+ return -EOPNOTSUPP;
+
+ if (chain->bound)
+ return -EBUSY;
+
+ chain->bound = true;
+ chain->use++;
+ nft_chain_trans_bind(ctx, chain);
+
+ return 0;
+}
+
+void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
+{
+ __nft_chain_trans_bind(ctx, chain, false);
+}
+
static int nft_netdev_register_hooks(struct net *net,
struct list_head *hook_list)
{
@@ -294,6 +366,19 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
{
struct nftables_pernet *nft_net = nft_pernet(net);
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWSET:
+ if (!nft_trans_set_update(trans) &&
+ nft_set_is_anonymous(nft_trans_set(trans)))
+ list_add_tail(&trans->binding_list, &nft_net->binding_list);
+ break;
+ case NFT_MSG_NEWCHAIN:
+ if (!nft_trans_chain_update(trans) &&
+ nft_chain_binding(nft_trans_chain(trans)))
+ list_add_tail(&trans->binding_list, &nft_net->binding_list);
+ break;
+ }
+
list_add_tail(&trans->list, &nft_net->commit_list);
}
@@ -340,8 +425,9 @@ static struct nft_trans *nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
ntohl(nla_get_be32(ctx->nla[NFTA_CHAIN_ID]));
}
}
-
+ nft_trans_chain(trans) = ctx->chain;
nft_trans_commit_list_add_tail(ctx->net, trans);
+
return trans;
}
@@ -359,8 +445,7 @@ static int nft_delchain(struct nft_ctx *ctx)
return 0;
}
-static void nft_rule_expr_activate(const struct nft_ctx *ctx,
- struct nft_rule *rule)
+void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule)
{
struct nft_expr *expr;
@@ -373,9 +458,8 @@ static void nft_rule_expr_activate(const struct nft_ctx *ctx,
}
}
-static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
- struct nft_rule *rule,
- enum nft_trans_phase phase)
+void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule,
+ enum nft_trans_phase phase)
{
struct nft_expr *expr;
@@ -2094,7 +2178,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
return 0;
}
-static int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
+int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
{
int err;
@@ -3220,8 +3304,7 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
return err;
}
-static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
- struct nft_rule *rule)
+void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule)
{
struct nft_expr *expr, *next;
@@ -3238,7 +3321,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
kfree(rule);
}
-void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
+static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
{
nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
nf_tables_rule_destroy(ctx, rule);
@@ -3572,7 +3655,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
if (flow)
nft_flow_rule_destroy(flow);
err_release_rule:
- nft_rule_expr_deactivate(&ctx, rule, NFT_TRANS_PREPARE);
+ nft_rule_expr_deactivate(&ctx, rule, NFT_TRANS_PREPARE_ERROR);
nf_tables_rule_destroy(&ctx, rule);
err_release_expr:
for (i = 0; i < n; i++) {
@@ -4545,6 +4628,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
return -EOPNOTSUPP;
+ if (nft_set_is_anonymous(set))
+ return -EOPNOTSUPP;
+
err = nft_set_expr_alloc(&ctx, set, nla, exprs, &num_exprs, flags);
if (err < 0)
return err;
@@ -4853,6 +4939,13 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
enum nft_trans_phase phase)
{
switch (phase) {
+ case NFT_TRANS_PREPARE_ERROR:
+ nft_set_trans_unbind(ctx, set);
+ if (nft_set_is_anonymous(set))
+ nft_deactivate_next(ctx->net, set);
+
+ set->use--;
+ break;
case NFT_TRANS_PREPARE:
if (nft_set_is_anonymous(set))
nft_deactivate_next(ctx->net, set);
@@ -6262,7 +6355,8 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
if (IS_ERR(set))
return PTR_ERR(set);
- if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
+ if (!list_empty(&set->bindings) &&
+ (set->flags & (NFT_SET_CONSTANT | NFT_SET_ANONYMOUS)))
return -EBUSY;
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
@@ -6293,7 +6387,6 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
{
struct nft_chain *chain;
- struct nft_rule *rule;
if (type == NFT_DATA_VERDICT) {
switch (data->verdict.code) {
@@ -6301,15 +6394,6 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
case NFT_GOTO:
chain = data->verdict.chain;
chain->use++;
-
- if (!nft_chain_is_bound(chain))
- break;
-
- chain->table->use++;
- list_for_each_entry(rule, &chain->rules, list)
- chain->use++;
-
- nft_chain_add(chain->table, chain);
break;
}
}
@@ -6542,7 +6626,9 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
set = nft_set_lookup(table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
if (IS_ERR(set))
return PTR_ERR(set);
- if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
+
+ if (!list_empty(&set->bindings) &&
+ (set->flags & (NFT_SET_CONSTANT | NFT_SET_ANONYMOUS)))
return -EBUSY;
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
@@ -7307,6 +7393,7 @@ void nf_tables_deactivate_flowtable(const struct nft_ctx *ctx,
enum nft_trans_phase phase)
{
switch (phase) {
+ case NFT_TRANS_PREPARE_ERROR:
case NFT_TRANS_PREPARE:
case NFT_TRANS_ABORT:
case NFT_TRANS_RELEASE:
@@ -8501,7 +8588,7 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
synchronize_rcu();
list_for_each_entry_safe(trans, next, &head, list) {
- list_del(&trans->list);
+ nft_trans_list_del(trans);
nft_commit_release(trans);
}
}
@@ -8819,6 +8906,27 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
return 0;
}
+ list_for_each_entry(trans, &nft_net->binding_list, binding_list) {
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWSET:
+ if (!nft_trans_set_update(trans) &&
+ nft_set_is_anonymous(nft_trans_set(trans)) &&
+ !nft_trans_set_bound(trans)) {
+ pr_warn_once("nftables ruleset with unbound set\n");
+ return -EINVAL;
+ }
+ break;
+ case NFT_MSG_NEWCHAIN:
+ if (!nft_trans_chain_update(trans) &&
+ nft_chain_binding(nft_trans_chain(trans)) &&
+ !nft_trans_chain_bound(trans)) {
+ pr_warn_once("nftables ruleset with unbound chain\n");
+ return -EINVAL;
+ }
+ break;
+ }
+ }
+
/* 0. Validate ruleset, otherwise roll back for error reporting. */
if (nf_tables_validate(net) < 0)
return -EAGAIN;
@@ -9162,7 +9270,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
kfree(nft_trans_chain_name(trans));
nft_trans_destroy(trans);
} else {
- if (nft_chain_is_bound(trans->ctx.chain)) {
+ if (nft_trans_chain_bound(trans)) {
nft_trans_destroy(trans);
break;
}
@@ -9179,6 +9287,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
nft_trans_destroy(trans);
break;
case NFT_MSG_NEWRULE:
+ if (nft_trans_rule_bound(trans)) {
+ nft_trans_destroy(trans);
+ break;
+ }
trans->ctx.chain->use--;
list_del_rcu(&nft_trans_rule(trans)->list);
nft_rule_expr_deactivate(&trans->ctx,
@@ -9288,7 +9400,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
list_for_each_entry_safe_reverse(trans, next,
&nft_net->commit_list, list) {
- list_del(&trans->list);
+ nft_trans_list_del(trans);
nf_tables_abort_release(trans);
}
@@ -9737,22 +9849,12 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
static void nft_verdict_uninit(const struct nft_data *data)
{
struct nft_chain *chain;
- struct nft_rule *rule;
switch (data->verdict.code) {
case NFT_JUMP:
case NFT_GOTO:
chain = data->verdict.chain;
chain->use--;
-
- if (!nft_chain_is_bound(chain))
- break;
-
- chain->table->use--;
- list_for_each_entry(rule, &chain->rules, list)
- chain->use--;
-
- nft_chain_del(chain);
break;
}
}
@@ -10071,6 +10173,7 @@ static int __net_init nf_tables_init_net(struct net *net)
INIT_LIST_HEAD(&nft_net->tables);
INIT_LIST_HEAD(&nft_net->commit_list);
+ INIT_LIST_HEAD(&nft_net->binding_list);
INIT_LIST_HEAD(&nft_net->module_list);
INIT_LIST_HEAD(&nft_net->notify_list);
mutex_init(&nft_net->commit_mutex);
diff --git a/net/netfilter/nfnetlink_osf.c b/net/netfilter/nfnetlink_osf.c
index ee6840bd5933..8f1bfa6ccc2d 100644
--- a/net/netfilter/nfnetlink_osf.c
+++ b/net/netfilter/nfnetlink_osf.c
@@ -439,3 +439,4 @@ module_init(nfnl_osf_init);
module_exit(nfnl_osf_fini);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF);
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
index fcdbc5ed3f36..6b0efab4fad0 100644
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -76,11 +76,9 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
switch (priv->data.verdict.code) {
case NFT_JUMP:
case NFT_GOTO:
- if (nft_chain_is_bound(chain)) {
- err = -EBUSY;
- goto err1;
- }
- chain->bound = true;
+ err = nf_tables_bind_chain(ctx, chain);
+ if (err < 0)
+ return err;
break;
default:
break;
@@ -98,6 +96,31 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+ const struct nft_data *data = &priv->data;
+ struct nft_ctx chain_ctx;
+ struct nft_chain *chain;
+ struct nft_rule *rule;
+
+ if (priv->dreg == NFT_REG_VERDICT) {
+ switch (data->verdict.code) {
+ case NFT_JUMP:
+ case NFT_GOTO:
+ chain = data->verdict.chain;
+ if (!nft_chain_binding(chain))
+ break;
+
+ chain_ctx = *ctx;
+ chain_ctx.chain = chain;
+
+ list_for_each_entry(rule, &chain->rules, list)
+ nft_rule_expr_activate(&chain_ctx, rule);
+
+ nft_clear(ctx->net, chain);
+ break;
+ default:
+ break;
+ }
+ }
return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
}
@@ -107,6 +130,43 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
enum nft_trans_phase phase)
{
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+ const struct nft_data *data = &priv->data;
+ struct nft_ctx chain_ctx;
+ struct nft_chain *chain;
+ struct nft_rule *rule;
+
+ if (priv->dreg == NFT_REG_VERDICT) {
+ switch (data->verdict.code) {
+ case NFT_JUMP:
+ case NFT_GOTO:
+ chain = data->verdict.chain;
+ if (!nft_chain_binding(chain))
+ break;
+
+ chain_ctx = *ctx;
+ chain_ctx.chain = chain;
+
+ list_for_each_entry(rule, &chain->rules, list)
+ nft_rule_expr_deactivate(&chain_ctx, rule, phase);
+
+ switch (phase) {
+ case NFT_TRANS_PREPARE_ERROR:
+ nf_tables_unbind_chain(ctx, chain);
+ fallthrough;
+ case NFT_TRANS_PREPARE:
+ nft_deactivate_next(ctx->net, chain);
+ break;
+ default:
+ nft_chain_del(chain);
+ chain->bound = false;
+ chain->table->use--;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
if (phase == NFT_TRANS_COMMIT)
return;
@@ -131,15 +191,27 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
case NFT_GOTO:
chain = data->verdict.chain;
- if (!nft_chain_is_bound(chain))
+ if (!nft_chain_binding(chain))
+ break;
+
+ /* Rule construction failed, but chain is already bound:
+ * let the transaction records release this chain and its rules.
+ */
+ if (chain->bound) {
+ chain->use--;
break;
+ }
+ /* Rule has been deleted, release chain and its rules. */
chain_ctx = *ctx;
chain_ctx.chain = chain;
- list_for_each_entry_safe(rule, n, &chain->rules, list)
- nf_tables_rule_release(&chain_ctx, rule);
-
+ chain->use--;
+ list_for_each_entry_safe(rule, n, &chain->rules, list) {
+ chain->use--;
+ list_del(&rule->list);
+ nf_tables_rule_destroy(&chain_ctx, rule);
+ }
nf_tables_chain_destroy(&chain_ctx);
break;
default:
diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
index 15e451dc3fc4..78e1ec8badde 100644
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -1974,12 +1974,16 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_iter *iter)
{
struct nft_pipapo *priv = nft_set_priv(set);
+ struct net *net = read_pnet(&set->net);
struct nft_pipapo_match *m;
struct nft_pipapo_field *f;
int i, r;
rcu_read_lock();
- m = rcu_dereference(priv->match);
+ if (iter->genmask == nft_genmask_cur(net))
+ m = rcu_dereference(priv->match);
+ else
+ m = priv->clone;
if (unlikely(!m))
goto out;
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index e1990baf3a3b..dc9485854002 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -71,4 +71,3 @@ MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Passive OS fingerprint matching.");
MODULE_ALIAS("ipt_osf");
MODULE_ALIAS("ip6t_osf");
-MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index adc5407fd5d5..be42b1196786 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -969,6 +969,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
if (ret < 0)
return ret;
+ sch_tree_lock(sch);
/* backup q->clg and q->loss_model */
old_clg = q->clg;
old_loss_model = q->loss_model;
@@ -977,7 +978,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]);
if (ret) {
q->loss_model = old_loss_model;
- return ret;
+ goto unlock;
}
} else {
q->loss_model = CLG_RANDOM;
@@ -1044,6 +1045,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
/* capping jitter to the range acceptable by tabledist() */
q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
+unlock:
+ sch_tree_unlock(sch);
return ret;
get_table_failure:
@@ -1053,7 +1056,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
*/
q->clg = old_clg;
q->loss_model = old_loss_model;
- return ret;
+
+ goto unlock;
}
static int netem_init(struct Qdisc *sch, struct nlattr *opt,
diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile
index 494aa744bfb9..08a2870fdd36 100644
--- a/net/xfrm/Makefile
+++ b/net/xfrm/Makefile
@@ -3,6 +3,8 @@
# Makefile for the XFRM subsystem.
#
+xfrm_interface-$(CONFIG_XFRM_INTERFACE) += xfrm_interface_core.o
+
obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
xfrm_input.o xfrm_output.o \
xfrm_sysctl.o xfrm_replay.o xfrm_device.o
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 7c5958a2eed4..a6861832710d 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -130,6 +130,7 @@ struct sec_path *secpath_set(struct sk_buff *skb)
memset(sp->ovec, 0, sizeof(sp->ovec));
sp->olen = 0;
sp->len = 0;
+ sp->verified_cnt = 0;
return sp;
}
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
deleted file mode 100644
index 1e8b26eecb3f..000000000000
--- a/net/xfrm/xfrm_interface.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * XFRM virtual interface
- *
- * Copyright (C) 2018 secunet Security Networks AG
- *
- * Author:
- * Steffen Klassert <steffen.klassert@secunet.com>
- */
-
-#include <linux/module.h>
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/sockios.h>
-#include <linux/icmp.h>
-#include <linux/if.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/net.h>
-#include <linux/in6.h>
-#include <linux/netdevice.h>
-#include <linux/if_link.h>
-#include <linux/if_arp.h>
-#include <linux/icmpv6.h>
-#include <linux/init.h>
-#include <linux/route.h>
-#include <linux/rtnetlink.h>
-#include <linux/netfilter_ipv6.h>
-#include <linux/slab.h>
-#include <linux/hash.h>
-
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-
-#include <net/icmp.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/ip6_route.h>
-#include <net/ip_tunnels.h>
-#include <net/addrconf.h>
-#include <net/xfrm.h>
-#include <net/net_namespace.h>
-#include <net/netns/generic.h>
-#include <linux/etherdevice.h>
-
-static int xfrmi_dev_init(struct net_device *dev);
-static void xfrmi_dev_setup(struct net_device *dev);
-static struct rtnl_link_ops xfrmi_link_ops __read_mostly;
-static unsigned int xfrmi_net_id __read_mostly;
-static const struct net_device_ops xfrmi_netdev_ops;
-
-#define XFRMI_HASH_BITS 8
-#define XFRMI_HASH_SIZE BIT(XFRMI_HASH_BITS)
-
-struct xfrmi_net {
- /* lists for storing interfaces in use */
- struct xfrm_if __rcu *xfrmi[XFRMI_HASH_SIZE];
-};
-
-#define for_each_xfrmi_rcu(start, xi) \
- for (xi = rcu_dereference(start); xi; xi = rcu_dereference(xi->next))
-
-static u32 xfrmi_hash(u32 if_id)
-{
- return hash_32(if_id, XFRMI_HASH_BITS);
-}
-
-static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x)
-{
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
- struct xfrm_if *xi;
-
- for_each_xfrmi_rcu(xfrmn->xfrmi[xfrmi_hash(x->if_id)], xi) {
- if (x->if_id == xi->p.if_id &&
- (xi->dev->flags & IFF_UP))
- return xi;
- }
-
- return NULL;
-}
-
-static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb,
- unsigned short family)
-{
- struct net_device *dev;
- int ifindex = 0;
-
- if (!secpath_exists(skb) || !skb->dev)
- return NULL;
-
- switch (family) {
- case AF_INET6:
- ifindex = inet6_sdif(skb);
- break;
- case AF_INET:
- ifindex = inet_sdif(skb);
- break;
- }
-
- if (ifindex) {
- struct net *net = xs_net(xfrm_input_state(skb));
-
- dev = dev_get_by_index_rcu(net, ifindex);
- } else {
- dev = skb->dev;
- }
-
- if (!dev || !(dev->flags & IFF_UP))
- return NULL;
- if (dev->netdev_ops != &xfrmi_netdev_ops)
- return NULL;
-
- return netdev_priv(dev);
-}
-
-static void xfrmi_link(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
-{
- struct xfrm_if __rcu **xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
-
- rcu_assign_pointer(xi->next , rtnl_dereference(*xip));
- rcu_assign_pointer(*xip, xi);
-}
-
-static void xfrmi_unlink(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
-{
- struct xfrm_if __rcu **xip;
- struct xfrm_if *iter;
-
- for (xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
- (iter = rtnl_dereference(*xip)) != NULL;
- xip = &iter->next) {
- if (xi == iter) {
- rcu_assign_pointer(*xip, xi->next);
- break;
- }
- }
-}
-
-static void xfrmi_dev_free(struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
-
- gro_cells_destroy(&xi->gro_cells);
- free_percpu(dev->tstats);
-}
-
-static int xfrmi_create(struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net *net = dev_net(dev);
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
- int err;
-
- dev->rtnl_link_ops = &xfrmi_link_ops;
- err = register_netdevice(dev);
- if (err < 0)
- goto out;
-
- xfrmi_link(xfrmn, xi);
-
- return 0;
-
-out:
- return err;
-}
-
-static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p)
-{
- struct xfrm_if __rcu **xip;
- struct xfrm_if *xi;
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
-
- for (xip = &xfrmn->xfrmi[xfrmi_hash(p->if_id)];
- (xi = rtnl_dereference(*xip)) != NULL;
- xip = &xi->next)
- if (xi->p.if_id == p->if_id)
- return xi;
-
- return NULL;
-}
-
-static void xfrmi_dev_uninit(struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
-
- xfrmi_unlink(xfrmn, xi);
-}
-
-static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
-{
- skb->tstamp = 0;
- skb->pkt_type = PACKET_HOST;
- skb->skb_iif = 0;
- skb->ignore_df = 0;
- skb_dst_drop(skb);
- nf_reset_ct(skb);
- nf_reset_trace(skb);
-
- if (!xnet)
- return;
-
- ipvs_reset(skb);
- secpath_reset(skb);
- skb_orphan(skb);
- skb->mark = 0;
-}
-
-static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
-{
- const struct xfrm_mode *inner_mode;
- struct net_device *dev;
- struct xfrm_state *x;
- struct xfrm_if *xi;
- bool xnet;
-
- if (err && !secpath_exists(skb))
- return 0;
-
- x = xfrm_input_state(skb);
-
- xi = xfrmi_lookup(xs_net(x), x);
- if (!xi)
- return 1;
-
- dev = xi->dev;
- skb->dev = dev;
-
- if (err) {
- dev->stats.rx_errors++;
- dev->stats.rx_dropped++;
-
- return 0;
- }
-
- xnet = !net_eq(xi->net, dev_net(skb->dev));
-
- if (xnet) {
- inner_mode = &x->inner_mode;
-
- if (x->sel.family == AF_UNSPEC) {
- inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
- if (inner_mode == NULL) {
- XFRM_INC_STATS(dev_net(skb->dev),
- LINUX_MIB_XFRMINSTATEMODEERROR);
- return -EINVAL;
- }
- }
-
- if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb,
- inner_mode->family))
- return -EPERM;
- }
-
- xfrmi_scrub_packet(skb, xnet);
- dev_sw_netstats_rx_add(dev, skb->len);
-
- return 0;
-}
-
-static int
-xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net_device_stats *stats = &xi->dev->stats;
- struct dst_entry *dst = skb_dst(skb);
- unsigned int length = skb->len;
- struct net_device *tdev;
- struct xfrm_state *x;
- int err = -1;
- int mtu;
-
- dst_hold(dst);
- dst = xfrm_lookup_with_ifid(xi->net, dst, fl, NULL, 0, xi->p.if_id);
- if (IS_ERR(dst)) {
- err = PTR_ERR(dst);
- dst = NULL;
- goto tx_err_link_failure;
- }
-
- x = dst->xfrm;
- if (!x)
- goto tx_err_link_failure;
-
- if (x->if_id != xi->p.if_id)
- goto tx_err_link_failure;
-
- tdev = dst->dev;
-
- if (tdev == dev) {
- stats->collisions++;
- net_warn_ratelimited("%s: Local routing loop detected!\n",
- dev->name);
- goto tx_err_dst_release;
- }
-
- mtu = dst_mtu(dst);
- if ((!skb_is_gso(skb) && skb->len > mtu) ||
- (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu))) {
- skb_dst_update_pmtu_no_confirm(skb, mtu);
-
- if (skb->protocol == htons(ETH_P_IPV6)) {
- if (mtu < IPV6_MIN_MTU)
- mtu = IPV6_MIN_MTU;
-
- if (skb->len > 1280)
- icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
- else
- goto xmit;
- } else {
- if (!(ip_hdr(skb)->frag_off & htons(IP_DF)))
- goto xmit;
- icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
- htonl(mtu));
- }
-
- dst_release(dst);
- return -EMSGSIZE;
- }
-
-xmit:
- xfrmi_scrub_packet(skb, !net_eq(xi->net, dev_net(dev)));
- skb_dst_set(skb, dst);
- skb->dev = tdev;
-
- err = dst_output(xi->net, skb->sk, skb);
- if (net_xmit_eval(err) == 0) {
- dev_sw_netstats_tx_add(dev, 1, length);
- } else {
- stats->tx_errors++;
- stats->tx_aborted_errors++;
- }
-
- return 0;
-tx_err_link_failure:
- stats->tx_carrier_errors++;
- dst_link_failure(skb);
-tx_err_dst_release:
- dst_release(dst);
- return err;
-}
-
-static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net_device_stats *stats = &xi->dev->stats;
- struct dst_entry *dst = skb_dst(skb);
- struct flowi fl;
- int ret;
-
- memset(&fl, 0, sizeof(fl));
-
- switch (skb->protocol) {
- case htons(ETH_P_IPV6):
- xfrm_decode_session(skb, &fl, AF_INET6);
- memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
- if (!dst) {
- fl.u.ip6.flowi6_oif = dev->ifindex;
- fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
- dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6);
- if (dst->error) {
- dst_release(dst);
- stats->tx_carrier_errors++;
- goto tx_err;
- }
- skb_dst_set(skb, dst);
- }
- break;
- case htons(ETH_P_IP):
- xfrm_decode_session(skb, &fl, AF_INET);
- memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
- if (!dst) {
- struct rtable *rt;
-
- fl.u.ip4.flowi4_oif = dev->ifindex;
- fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
- rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4);
- if (IS_ERR(rt)) {
- stats->tx_carrier_errors++;
- goto tx_err;
- }
- skb_dst_set(skb, &rt->dst);
- }
- break;
- default:
- goto tx_err;
- }
-
- fl.flowi_oif = xi->p.link;
-
- ret = xfrmi_xmit2(skb, dev, &fl);
- if (ret < 0)
- goto tx_err;
-
- return NETDEV_TX_OK;
-
-tx_err:
- stats->tx_errors++;
- stats->tx_dropped++;
- kfree_skb(skb);
- return NETDEV_TX_OK;
-}
-
-static int xfrmi4_err(struct sk_buff *skb, u32 info)
-{
- const struct iphdr *iph = (const struct iphdr *)skb->data;
- struct net *net = dev_net(skb->dev);
- int protocol = iph->protocol;
- struct ip_comp_hdr *ipch;
- struct ip_esp_hdr *esph;
- struct ip_auth_hdr *ah ;
- struct xfrm_state *x;
- struct xfrm_if *xi;
- __be32 spi;
-
- switch (protocol) {
- case IPPROTO_ESP:
- esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
- spi = esph->spi;
- break;
- case IPPROTO_AH:
- ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
- spi = ah->spi;
- break;
- case IPPROTO_COMP:
- ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
- spi = htonl(ntohs(ipch->cpi));
- break;
- default:
- return 0;
- }
-
- switch (icmp_hdr(skb)->type) {
- case ICMP_DEST_UNREACH:
- if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
- return 0;
- break;
- case ICMP_REDIRECT:
- break;
- default:
- return 0;
- }
-
- x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
- spi, protocol, AF_INET);
- if (!x)
- return 0;
-
- xi = xfrmi_lookup(net, x);
- if (!xi) {
- xfrm_state_put(x);
- return -1;
- }
-
- if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
- ipv4_update_pmtu(skb, net, info, 0, protocol);
- else
- ipv4_redirect(skb, net, 0, protocol);
- xfrm_state_put(x);
-
- return 0;
-}
-
-static int xfrmi6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- u8 type, u8 code, int offset, __be32 info)
-{
- const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
- struct net *net = dev_net(skb->dev);
- int protocol = iph->nexthdr;
- struct ip_comp_hdr *ipch;
- struct ip_esp_hdr *esph;
- struct ip_auth_hdr *ah;
- struct xfrm_state *x;
- struct xfrm_if *xi;
- __be32 spi;
-
- switch (protocol) {
- case IPPROTO_ESP:
- esph = (struct ip_esp_hdr *)(skb->data + offset);
- spi = esph->spi;
- break;
- case IPPROTO_AH:
- ah = (struct ip_auth_hdr *)(skb->data + offset);
- spi = ah->spi;
- break;
- case IPPROTO_COMP:
- ipch = (struct ip_comp_hdr *)(skb->data + offset);
- spi = htonl(ntohs(ipch->cpi));
- break;
- default:
- return 0;
- }
-
- if (type != ICMPV6_PKT_TOOBIG &&
- type != NDISC_REDIRECT)
- return 0;
-
- x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
- spi, protocol, AF_INET6);
- if (!x)
- return 0;
-
- xi = xfrmi_lookup(net, x);
- if (!xi) {
- xfrm_state_put(x);
- return -1;
- }
-
- if (type == NDISC_REDIRECT)
- ip6_redirect(skb, net, skb->dev->ifindex, 0,
- sock_net_uid(net, NULL));
- else
- ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
- xfrm_state_put(x);
-
- return 0;
-}
-
-static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p)
-{
- if (xi->p.link != p->link)
- return -EINVAL;
-
- xi->p.if_id = p->if_id;
-
- return 0;
-}
-
-static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
-{
- struct net *net = xi->net;
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
- int err;
-
- xfrmi_unlink(xfrmn, xi);
- synchronize_net();
- err = xfrmi_change(xi, p);
- xfrmi_link(xfrmn, xi);
- netdev_state_change(xi->dev);
- return err;
-}
-
-static int xfrmi_get_iflink(const struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
-
- return xi->p.link;
-}
-
-static const struct net_device_ops xfrmi_netdev_ops = {
- .ndo_init = xfrmi_dev_init,
- .ndo_uninit = xfrmi_dev_uninit,
- .ndo_start_xmit = xfrmi_xmit,
- .ndo_get_stats64 = dev_get_tstats64,
- .ndo_get_iflink = xfrmi_get_iflink,
-};
-
-static void xfrmi_dev_setup(struct net_device *dev)
-{
- dev->netdev_ops = &xfrmi_netdev_ops;
- dev->header_ops = &ip_tunnel_header_ops;
- dev->type = ARPHRD_NONE;
- dev->mtu = ETH_DATA_LEN;
- dev->min_mtu = ETH_MIN_MTU;
- dev->max_mtu = IP_MAX_MTU;
- dev->flags = IFF_NOARP;
- dev->needs_free_netdev = true;
- dev->priv_destructor = xfrmi_dev_free;
- netif_keep_dst(dev);
-
- eth_broadcast_addr(dev->broadcast);
-}
-
-#define XFRMI_FEATURES (NETIF_F_SG | \
- NETIF_F_FRAGLIST | \
- NETIF_F_GSO_SOFTWARE | \
- NETIF_F_HW_CSUM)
-
-static int xfrmi_dev_init(struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
- int err;
-
- dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
- if (!dev->tstats)
- return -ENOMEM;
-
- err = gro_cells_init(&xi->gro_cells, dev);
- if (err) {
- free_percpu(dev->tstats);
- return err;
- }
-
- dev->features |= NETIF_F_LLTX;
- dev->features |= XFRMI_FEATURES;
- dev->hw_features |= XFRMI_FEATURES;
-
- if (phydev) {
- dev->needed_headroom = phydev->needed_headroom;
- dev->needed_tailroom = phydev->needed_tailroom;
-
- if (is_zero_ether_addr(dev->dev_addr))
- eth_hw_addr_inherit(dev, phydev);
- if (is_zero_ether_addr(dev->broadcast))
- memcpy(dev->broadcast, phydev->broadcast,
- dev->addr_len);
- } else {
- eth_hw_addr_random(dev);
- eth_broadcast_addr(dev->broadcast);
- }
-
- return 0;
-}
-
-static int xfrmi_validate(struct nlattr *tb[], struct nlattr *data[],
- struct netlink_ext_ack *extack)
-{
- return 0;
-}
-
-static void xfrmi_netlink_parms(struct nlattr *data[],
- struct xfrm_if_parms *parms)
-{
- memset(parms, 0, sizeof(*parms));
-
- if (!data)
- return;
-
- if (data[IFLA_XFRM_LINK])
- parms->link = nla_get_u32(data[IFLA_XFRM_LINK]);
-
- if (data[IFLA_XFRM_IF_ID])
- parms->if_id = nla_get_u32(data[IFLA_XFRM_IF_ID]);
-}
-
-static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
- struct nlattr *tb[], struct nlattr *data[],
- struct netlink_ext_ack *extack)
-{
- struct net *net = dev_net(dev);
- struct xfrm_if_parms p = {};
- struct xfrm_if *xi;
- int err;
-
- xfrmi_netlink_parms(data, &p);
- if (!p.if_id) {
- NL_SET_ERR_MSG(extack, "if_id must be non zero");
- return -EINVAL;
- }
-
- xi = xfrmi_locate(net, &p);
- if (xi)
- return -EEXIST;
-
- xi = netdev_priv(dev);
- xi->p = p;
- xi->net = net;
- xi->dev = dev;
-
- err = xfrmi_create(dev);
- return err;
-}
-
-static void xfrmi_dellink(struct net_device *dev, struct list_head *head)
-{
- unregister_netdevice_queue(dev, head);
-}
-
-static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
- struct nlattr *data[],
- struct netlink_ext_ack *extack)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net *net = xi->net;
- struct xfrm_if_parms p = {};
-
- xfrmi_netlink_parms(data, &p);
- if (!p.if_id) {
- NL_SET_ERR_MSG(extack, "if_id must be non zero");
- return -EINVAL;
- }
-
- xi = xfrmi_locate(net, &p);
- if (!xi) {
- xi = netdev_priv(dev);
- } else {
- if (xi->dev != dev)
- return -EEXIST;
- }
-
- return xfrmi_update(xi, &p);
-}
-
-static size_t xfrmi_get_size(const struct net_device *dev)
-{
- return
- /* IFLA_XFRM_LINK */
- nla_total_size(4) +
- /* IFLA_XFRM_IF_ID */
- nla_total_size(4) +
- 0;
-}
-
-static int xfrmi_fill_info(struct sk_buff *skb, const struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct xfrm_if_parms *parm = &xi->p;
-
- if (nla_put_u32(skb, IFLA_XFRM_LINK, parm->link) ||
- nla_put_u32(skb, IFLA_XFRM_IF_ID, parm->if_id))
- goto nla_put_failure;
- return 0;
-
-nla_put_failure:
- return -EMSGSIZE;
-}
-
-static struct net *xfrmi_get_link_net(const struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
-
- return xi->net;
-}
-
-static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
- [IFLA_XFRM_LINK] = { .type = NLA_U32 },
- [IFLA_XFRM_IF_ID] = { .type = NLA_U32 },
-};
-
-static struct rtnl_link_ops xfrmi_link_ops __read_mostly = {
- .kind = "xfrm",
- .maxtype = IFLA_XFRM_MAX,
- .policy = xfrmi_policy,
- .priv_size = sizeof(struct xfrm_if),
- .setup = xfrmi_dev_setup,
- .validate = xfrmi_validate,
- .newlink = xfrmi_newlink,
- .dellink = xfrmi_dellink,
- .changelink = xfrmi_changelink,
- .get_size = xfrmi_get_size,
- .fill_info = xfrmi_fill_info,
- .get_link_net = xfrmi_get_link_net,
-};
-
-static void __net_exit xfrmi_exit_batch_net(struct list_head *net_exit_list)
-{
- struct net *net;
- LIST_HEAD(list);
-
- rtnl_lock();
- list_for_each_entry(net, net_exit_list, exit_list) {
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
- struct xfrm_if __rcu **xip;
- struct xfrm_if *xi;
- int i;
-
- for (i = 0; i < XFRMI_HASH_SIZE; i++) {
- for (xip = &xfrmn->xfrmi[i];
- (xi = rtnl_dereference(*xip)) != NULL;
- xip = &xi->next)
- unregister_netdevice_queue(xi->dev, &list);
- }
- }
- unregister_netdevice_many(&list);
- rtnl_unlock();
-}
-
-static struct pernet_operations xfrmi_net_ops = {
- .exit_batch = xfrmi_exit_batch_net,
- .id = &xfrmi_net_id,
- .size = sizeof(struct xfrmi_net),
-};
-
-static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
- .handler = xfrm6_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 10,
-};
-
-static struct xfrm6_protocol xfrmi_ah6_protocol __read_mostly = {
- .handler = xfrm6_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 10,
-};
-
-static struct xfrm6_protocol xfrmi_ipcomp6_protocol __read_mostly = {
- .handler = xfrm6_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 10,
-};
-
-#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
-static int xfrmi6_rcv_tunnel(struct sk_buff *skb)
-{
- const xfrm_address_t *saddr;
- __be32 spi;
-
- saddr = (const xfrm_address_t *)&ipv6_hdr(skb)->saddr;
- spi = xfrm6_tunnel_spi_lookup(dev_net(skb->dev), saddr);
-
- return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi, NULL);
-}
-
-static struct xfrm6_tunnel xfrmi_ipv6_handler __read_mostly = {
- .handler = xfrmi6_rcv_tunnel,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 2,
-};
-
-static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
- .handler = xfrmi6_rcv_tunnel,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 2,
-};
-#endif
-
-static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
- .handler = xfrm4_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 10,
-};
-
-static struct xfrm4_protocol xfrmi_ah4_protocol __read_mostly = {
- .handler = xfrm4_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 10,
-};
-
-static struct xfrm4_protocol xfrmi_ipcomp4_protocol __read_mostly = {
- .handler = xfrm4_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 10,
-};
-
-#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
-static int xfrmi4_rcv_tunnel(struct sk_buff *skb)
-{
- return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr);
-}
-
-static struct xfrm_tunnel xfrmi_ipip_handler __read_mostly = {
- .handler = xfrmi4_rcv_tunnel,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 3,
-};
-
-static struct xfrm_tunnel xfrmi_ipip6_handler __read_mostly = {
- .handler = xfrmi4_rcv_tunnel,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 2,
-};
-#endif
-
-static int __init xfrmi4_init(void)
-{
- int err;
-
- err = xfrm4_protocol_register(&xfrmi_esp4_protocol, IPPROTO_ESP);
- if (err < 0)
- goto xfrm_proto_esp_failed;
- err = xfrm4_protocol_register(&xfrmi_ah4_protocol, IPPROTO_AH);
- if (err < 0)
- goto xfrm_proto_ah_failed;
- err = xfrm4_protocol_register(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
- if (err < 0)
- goto xfrm_proto_comp_failed;
-#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
- err = xfrm4_tunnel_register(&xfrmi_ipip_handler, AF_INET);
- if (err < 0)
- goto xfrm_tunnel_ipip_failed;
- err = xfrm4_tunnel_register(&xfrmi_ipip6_handler, AF_INET6);
- if (err < 0)
- goto xfrm_tunnel_ipip6_failed;
-#endif
-
- return 0;
-
-#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
-xfrm_tunnel_ipip6_failed:
- xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
-xfrm_tunnel_ipip_failed:
- xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
-#endif
-xfrm_proto_comp_failed:
- xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
-xfrm_proto_ah_failed:
- xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
-xfrm_proto_esp_failed:
- return err;
-}
-
-static void xfrmi4_fini(void)
-{
-#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
- xfrm4_tunnel_deregister(&xfrmi_ipip6_handler, AF_INET6);
- xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
-#endif
- xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
- xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
- xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
-}
-
-static int __init xfrmi6_init(void)
-{
- int err;
-
- err = xfrm6_protocol_register(&xfrmi_esp6_protocol, IPPROTO_ESP);
- if (err < 0)
- goto xfrm_proto_esp_failed;
- err = xfrm6_protocol_register(&xfrmi_ah6_protocol, IPPROTO_AH);
- if (err < 0)
- goto xfrm_proto_ah_failed;
- err = xfrm6_protocol_register(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
- if (err < 0)
- goto xfrm_proto_comp_failed;
-#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
- err = xfrm6_tunnel_register(&xfrmi_ipv6_handler, AF_INET6);
- if (err < 0)
- goto xfrm_tunnel_ipv6_failed;
- err = xfrm6_tunnel_register(&xfrmi_ip6ip_handler, AF_INET);
- if (err < 0)
- goto xfrm_tunnel_ip6ip_failed;
-#endif
-
- return 0;
-
-#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
-xfrm_tunnel_ip6ip_failed:
- xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
-xfrm_tunnel_ipv6_failed:
- xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
-#endif
-xfrm_proto_comp_failed:
- xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
-xfrm_proto_ah_failed:
- xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
-xfrm_proto_esp_failed:
- return err;
-}
-
-static void xfrmi6_fini(void)
-{
-#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
- xfrm6_tunnel_deregister(&xfrmi_ip6ip_handler, AF_INET);
- xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
-#endif
- xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
- xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
- xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
-}
-
-static const struct xfrm_if_cb xfrm_if_cb = {
- .decode_session = xfrmi_decode_session,
-};
-
-static int __init xfrmi_init(void)
-{
- const char *msg;
- int err;
-
- pr_info("IPsec XFRM device driver\n");
-
- msg = "tunnel device";
- err = register_pernet_device(&xfrmi_net_ops);
- if (err < 0)
- goto pernet_dev_failed;
-
- msg = "xfrm4 protocols";
- err = xfrmi4_init();
- if (err < 0)
- goto xfrmi4_failed;
-
- msg = "xfrm6 protocols";
- err = xfrmi6_init();
- if (err < 0)
- goto xfrmi6_failed;
-
-
- msg = "netlink interface";
- err = rtnl_link_register(&xfrmi_link_ops);
- if (err < 0)
- goto rtnl_link_failed;
-
- xfrm_if_register_cb(&xfrm_if_cb);
-
- return err;
-
-rtnl_link_failed:
- xfrmi6_fini();
-xfrmi6_failed:
- xfrmi4_fini();
-xfrmi4_failed:
- unregister_pernet_device(&xfrmi_net_ops);
-pernet_dev_failed:
- pr_err("xfrmi init: failed to register %s\n", msg);
- return err;
-}
-
-static void __exit xfrmi_fini(void)
-{
- xfrm_if_unregister_cb();
- rtnl_link_unregister(&xfrmi_link_ops);
- xfrmi4_fini();
- xfrmi6_fini();
- unregister_pernet_device(&xfrmi_net_ops);
-}
-
-module_init(xfrmi_init);
-module_exit(xfrmi_fini);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_RTNL_LINK("xfrm");
-MODULE_ALIAS_NETDEV("xfrm0");
-MODULE_AUTHOR("Steffen Klassert");
-MODULE_DESCRIPTION("XFRM virtual interface");
diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c
new file mode 100644
index 000000000000..694eec6ca147
--- /dev/null
+++ b/net/xfrm/xfrm_interface_core.c
@@ -0,0 +1,1078 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * XFRM virtual interface
+ *
+ * Copyright (C) 2018 secunet Security Networks AG
+ *
+ * Author:
+ * Steffen Klassert <steffen.klassert@secunet.com>
+ */
+
+#include <linux/module.h>
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/sockios.h>
+#include <linux/icmp.h>
+#include <linux/if.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/net.h>
+#include <linux/in6.h>
+#include <linux/netdevice.h>
+#include <linux/if_link.h>
+#include <linux/if_arp.h>
+#include <linux/icmpv6.h>
+#include <linux/init.h>
+#include <linux/route.h>
+#include <linux/rtnetlink.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/slab.h>
+#include <linux/hash.h>
+
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+
+#include <net/icmp.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/ip_tunnels.h>
+#include <net/addrconf.h>
+#include <net/xfrm.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+#include <linux/etherdevice.h>
+
+static int xfrmi_dev_init(struct net_device *dev);
+static void xfrmi_dev_setup(struct net_device *dev);
+static struct rtnl_link_ops xfrmi_link_ops __read_mostly;
+static unsigned int xfrmi_net_id __read_mostly;
+static const struct net_device_ops xfrmi_netdev_ops;
+
+#define XFRMI_HASH_BITS 8
+#define XFRMI_HASH_SIZE BIT(XFRMI_HASH_BITS)
+
+struct xfrmi_net {
+ /* lists for storing interfaces in use */
+ struct xfrm_if __rcu *xfrmi[XFRMI_HASH_SIZE];
+};
+
+#define for_each_xfrmi_rcu(start, xi) \
+ for (xi = rcu_dereference(start); xi; xi = rcu_dereference(xi->next))
+
+static u32 xfrmi_hash(u32 if_id)
+{
+ return hash_32(if_id, XFRMI_HASH_BITS);
+}
+
+static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x)
+{
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+ struct xfrm_if *xi;
+
+ for_each_xfrmi_rcu(xfrmn->xfrmi[xfrmi_hash(x->if_id)], xi) {
+ if (x->if_id == xi->p.if_id &&
+ (xi->dev->flags & IFF_UP))
+ return xi;
+ }
+
+ return NULL;
+}
+
+static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb,
+ unsigned short family)
+{
+ struct net_device *dev;
+ int ifindex = 0;
+
+ if (!secpath_exists(skb) || !skb->dev)
+ return NULL;
+
+ switch (family) {
+ case AF_INET6:
+ ifindex = inet6_sdif(skb);
+ break;
+ case AF_INET:
+ ifindex = inet_sdif(skb);
+ break;
+ }
+
+ if (ifindex) {
+ struct net *net = xs_net(xfrm_input_state(skb));
+
+ dev = dev_get_by_index_rcu(net, ifindex);
+ } else {
+ dev = skb->dev;
+ }
+
+ if (!dev || !(dev->flags & IFF_UP))
+ return NULL;
+ if (dev->netdev_ops != &xfrmi_netdev_ops)
+ return NULL;
+
+ return netdev_priv(dev);
+}
+
+static void xfrmi_link(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
+{
+ struct xfrm_if __rcu **xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
+
+ rcu_assign_pointer(xi->next , rtnl_dereference(*xip));
+ rcu_assign_pointer(*xip, xi);
+}
+
+static void xfrmi_unlink(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
+{
+ struct xfrm_if __rcu **xip;
+ struct xfrm_if *iter;
+
+ for (xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
+ (iter = rtnl_dereference(*xip)) != NULL;
+ xip = &iter->next) {
+ if (xi == iter) {
+ rcu_assign_pointer(*xip, xi->next);
+ break;
+ }
+ }
+}
+
+static void xfrmi_dev_free(struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+
+ gro_cells_destroy(&xi->gro_cells);
+ free_percpu(dev->tstats);
+}
+
+static int xfrmi_create(struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net *net = dev_net(dev);
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+ int err;
+
+ dev->rtnl_link_ops = &xfrmi_link_ops;
+ err = register_netdevice(dev);
+ if (err < 0)
+ goto out;
+
+ xfrmi_link(xfrmn, xi);
+
+ return 0;
+
+out:
+ return err;
+}
+
+static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p)
+{
+ struct xfrm_if __rcu **xip;
+ struct xfrm_if *xi;
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+
+ for (xip = &xfrmn->xfrmi[xfrmi_hash(p->if_id)];
+ (xi = rtnl_dereference(*xip)) != NULL;
+ xip = &xi->next)
+ if (xi->p.if_id == p->if_id)
+ return xi;
+
+ return NULL;
+}
+
+static void xfrmi_dev_uninit(struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
+
+ xfrmi_unlink(xfrmn, xi);
+}
+
+static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
+{
+ skb->tstamp = 0;
+ skb->pkt_type = PACKET_HOST;
+ skb->skb_iif = 0;
+ skb->ignore_df = 0;
+ skb_dst_drop(skb);
+ nf_reset_ct(skb);
+ nf_reset_trace(skb);
+
+ if (!xnet)
+ return;
+
+ ipvs_reset(skb);
+ secpath_reset(skb);
+ skb_orphan(skb);
+ skb->mark = 0;
+}
+
+static int xfrmi_input(struct sk_buff *skb, int nexthdr, __be32 spi,
+ int encap_type, unsigned short family)
+{
+ struct sec_path *sp;
+
+ sp = skb_sec_path(skb);
+ if (sp && (sp->len || sp->olen) &&
+ !xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
+ goto discard;
+
+ XFRM_SPI_SKB_CB(skb)->family = family;
+ if (family == AF_INET) {
+ XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
+ XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
+ } else {
+ XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
+ XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
+ }
+
+ return xfrm_input(skb, nexthdr, spi, encap_type);
+discard:
+ kfree_skb(skb);
+ return 0;
+}
+
+static int xfrmi4_rcv(struct sk_buff *skb)
+{
+ return xfrmi_input(skb, ip_hdr(skb)->protocol, 0, 0, AF_INET);
+}
+
+static int xfrmi6_rcv(struct sk_buff *skb)
+{
+ return xfrmi_input(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
+ 0, 0, AF_INET6);
+}
+
+static int xfrmi4_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
+{
+ return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET);
+}
+
+static int xfrmi6_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
+{
+ return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET6);
+}
+
+static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
+{
+ const struct xfrm_mode *inner_mode;
+ struct net_device *dev;
+ struct xfrm_state *x;
+ struct xfrm_if *xi;
+ bool xnet;
+
+ if (err && !secpath_exists(skb))
+ return 0;
+
+ x = xfrm_input_state(skb);
+
+ xi = xfrmi_lookup(xs_net(x), x);
+ if (!xi)
+ return 1;
+
+ dev = xi->dev;
+ skb->dev = dev;
+
+ if (err) {
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
+
+ return 0;
+ }
+
+ xnet = !net_eq(xi->net, dev_net(skb->dev));
+
+ if (xnet) {
+ inner_mode = &x->inner_mode;
+
+ if (x->sel.family == AF_UNSPEC) {
+ inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
+ if (inner_mode == NULL) {
+ XFRM_INC_STATS(dev_net(skb->dev),
+ LINUX_MIB_XFRMINSTATEMODEERROR);
+ return -EINVAL;
+ }
+ }
+
+ if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb,
+ inner_mode->family))
+ return -EPERM;
+ }
+
+ xfrmi_scrub_packet(skb, xnet);
+ dev_sw_netstats_rx_add(dev, skb->len);
+
+ return 0;
+}
+
+static int
+xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net_device_stats *stats = &xi->dev->stats;
+ struct dst_entry *dst = skb_dst(skb);
+ unsigned int length = skb->len;
+ struct net_device *tdev;
+ struct xfrm_state *x;
+ int err = -1;
+ int mtu;
+
+ dst_hold(dst);
+ dst = xfrm_lookup_with_ifid(xi->net, dst, fl, NULL, 0, xi->p.if_id);
+ if (IS_ERR(dst)) {
+ err = PTR_ERR(dst);
+ dst = NULL;
+ goto tx_err_link_failure;
+ }
+
+ x = dst->xfrm;
+ if (!x)
+ goto tx_err_link_failure;
+
+ if (x->if_id != xi->p.if_id)
+ goto tx_err_link_failure;
+
+ tdev = dst->dev;
+
+ if (tdev == dev) {
+ stats->collisions++;
+ net_warn_ratelimited("%s: Local routing loop detected!\n",
+ dev->name);
+ goto tx_err_dst_release;
+ }
+
+ mtu = dst_mtu(dst);
+ if ((!skb_is_gso(skb) && skb->len > mtu) ||
+ (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu))) {
+ skb_dst_update_pmtu_no_confirm(skb, mtu);
+
+ if (skb->protocol == htons(ETH_P_IPV6)) {
+ if (mtu < IPV6_MIN_MTU)
+ mtu = IPV6_MIN_MTU;
+
+ if (skb->len > 1280)
+ icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ else
+ goto xmit;
+ } else {
+ if (!(ip_hdr(skb)->frag_off & htons(IP_DF)))
+ goto xmit;
+ icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+ htonl(mtu));
+ }
+
+ dst_release(dst);
+ return -EMSGSIZE;
+ }
+
+xmit:
+ xfrmi_scrub_packet(skb, !net_eq(xi->net, dev_net(dev)));
+ skb_dst_set(skb, dst);
+ skb->dev = tdev;
+
+ err = dst_output(xi->net, skb->sk, skb);
+ if (net_xmit_eval(err) == 0) {
+ dev_sw_netstats_tx_add(dev, 1, length);
+ } else {
+ stats->tx_errors++;
+ stats->tx_aborted_errors++;
+ }
+
+ return 0;
+tx_err_link_failure:
+ stats->tx_carrier_errors++;
+ dst_link_failure(skb);
+tx_err_dst_release:
+ dst_release(dst);
+ return err;
+}
+
+static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net_device_stats *stats = &xi->dev->stats;
+ struct dst_entry *dst = skb_dst(skb);
+ struct flowi fl;
+ int ret;
+
+ memset(&fl, 0, sizeof(fl));
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IPV6):
+ xfrm_decode_session(skb, &fl, AF_INET6);
+ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+ if (!dst) {
+ fl.u.ip6.flowi6_oif = dev->ifindex;
+ fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
+ dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6);
+ if (dst->error) {
+ dst_release(dst);
+ stats->tx_carrier_errors++;
+ goto tx_err;
+ }
+ skb_dst_set(skb, dst);
+ }
+ break;
+ case htons(ETH_P_IP):
+ xfrm_decode_session(skb, &fl, AF_INET);
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+ if (!dst) {
+ struct rtable *rt;
+
+ fl.u.ip4.flowi4_oif = dev->ifindex;
+ fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+ rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4);
+ if (IS_ERR(rt)) {
+ stats->tx_carrier_errors++;
+ goto tx_err;
+ }
+ skb_dst_set(skb, &rt->dst);
+ }
+ break;
+ default:
+ goto tx_err;
+ }
+
+ fl.flowi_oif = xi->p.link;
+
+ ret = xfrmi_xmit2(skb, dev, &fl);
+ if (ret < 0)
+ goto tx_err;
+
+ return NETDEV_TX_OK;
+
+tx_err:
+ stats->tx_errors++;
+ stats->tx_dropped++;
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+static int xfrmi4_err(struct sk_buff *skb, u32 info)
+{
+ const struct iphdr *iph = (const struct iphdr *)skb->data;
+ struct net *net = dev_net(skb->dev);
+ int protocol = iph->protocol;
+ struct ip_comp_hdr *ipch;
+ struct ip_esp_hdr *esph;
+ struct ip_auth_hdr *ah ;
+ struct xfrm_state *x;
+ struct xfrm_if *xi;
+ __be32 spi;
+
+ switch (protocol) {
+ case IPPROTO_ESP:
+ esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
+ spi = esph->spi;
+ break;
+ case IPPROTO_AH:
+ ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
+ spi = ah->spi;
+ break;
+ case IPPROTO_COMP:
+ ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
+ spi = htonl(ntohs(ipch->cpi));
+ break;
+ default:
+ return 0;
+ }
+
+ switch (icmp_hdr(skb)->type) {
+ case ICMP_DEST_UNREACH:
+ if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
+ return 0;
+ break;
+ case ICMP_REDIRECT:
+ break;
+ default:
+ return 0;
+ }
+
+ x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
+ spi, protocol, AF_INET);
+ if (!x)
+ return 0;
+
+ xi = xfrmi_lookup(net, x);
+ if (!xi) {
+ xfrm_state_put(x);
+ return -1;
+ }
+
+ if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+ ipv4_update_pmtu(skb, net, info, 0, protocol);
+ else
+ ipv4_redirect(skb, net, 0, protocol);
+ xfrm_state_put(x);
+
+ return 0;
+}
+
+static int xfrmi6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ u8 type, u8 code, int offset, __be32 info)
+{
+ const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
+ struct net *net = dev_net(skb->dev);
+ int protocol = iph->nexthdr;
+ struct ip_comp_hdr *ipch;
+ struct ip_esp_hdr *esph;
+ struct ip_auth_hdr *ah;
+ struct xfrm_state *x;
+ struct xfrm_if *xi;
+ __be32 spi;
+
+ switch (protocol) {
+ case IPPROTO_ESP:
+ esph = (struct ip_esp_hdr *)(skb->data + offset);
+ spi = esph->spi;
+ break;
+ case IPPROTO_AH:
+ ah = (struct ip_auth_hdr *)(skb->data + offset);
+ spi = ah->spi;
+ break;
+ case IPPROTO_COMP:
+ ipch = (struct ip_comp_hdr *)(skb->data + offset);
+ spi = htonl(ntohs(ipch->cpi));
+ break;
+ default:
+ return 0;
+ }
+
+ if (type != ICMPV6_PKT_TOOBIG &&
+ type != NDISC_REDIRECT)
+ return 0;
+
+ x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
+ spi, protocol, AF_INET6);
+ if (!x)
+ return 0;
+
+ xi = xfrmi_lookup(net, x);
+ if (!xi) {
+ xfrm_state_put(x);
+ return -1;
+ }
+
+ if (type == NDISC_REDIRECT)
+ ip6_redirect(skb, net, skb->dev->ifindex, 0,
+ sock_net_uid(net, NULL));
+ else
+ ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
+ xfrm_state_put(x);
+
+ return 0;
+}
+
+static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p)
+{
+ if (xi->p.link != p->link)
+ return -EINVAL;
+
+ xi->p.if_id = p->if_id;
+
+ return 0;
+}
+
+static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
+{
+ struct net *net = xi->net;
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+ int err;
+
+ xfrmi_unlink(xfrmn, xi);
+ synchronize_net();
+ err = xfrmi_change(xi, p);
+ xfrmi_link(xfrmn, xi);
+ netdev_state_change(xi->dev);
+ return err;
+}
+
+static int xfrmi_get_iflink(const struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+
+ return xi->p.link;
+}
+
+static const struct net_device_ops xfrmi_netdev_ops = {
+ .ndo_init = xfrmi_dev_init,
+ .ndo_uninit = xfrmi_dev_uninit,
+ .ndo_start_xmit = xfrmi_xmit,
+ .ndo_get_stats64 = dev_get_tstats64,
+ .ndo_get_iflink = xfrmi_get_iflink,
+};
+
+static void xfrmi_dev_setup(struct net_device *dev)
+{
+ dev->netdev_ops = &xfrmi_netdev_ops;
+ dev->header_ops = &ip_tunnel_header_ops;
+ dev->type = ARPHRD_NONE;
+ dev->mtu = ETH_DATA_LEN;
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = IP_MAX_MTU;
+ dev->flags = IFF_NOARP;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = xfrmi_dev_free;
+ netif_keep_dst(dev);
+
+ eth_broadcast_addr(dev->broadcast);
+}
+
+#define XFRMI_FEATURES (NETIF_F_SG | \
+ NETIF_F_FRAGLIST | \
+ NETIF_F_GSO_SOFTWARE | \
+ NETIF_F_HW_CSUM)
+
+static int xfrmi_dev_init(struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
+ int err;
+
+ dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+ if (!dev->tstats)
+ return -ENOMEM;
+
+ err = gro_cells_init(&xi->gro_cells, dev);
+ if (err) {
+ free_percpu(dev->tstats);
+ return err;
+ }
+
+ dev->features |= NETIF_F_LLTX;
+ dev->features |= XFRMI_FEATURES;
+ dev->hw_features |= XFRMI_FEATURES;
+
+ if (phydev) {
+ dev->needed_headroom = phydev->needed_headroom;
+ dev->needed_tailroom = phydev->needed_tailroom;
+
+ if (is_zero_ether_addr(dev->dev_addr))
+ eth_hw_addr_inherit(dev, phydev);
+ if (is_zero_ether_addr(dev->broadcast))
+ memcpy(dev->broadcast, phydev->broadcast,
+ dev->addr_len);
+ } else {
+ eth_hw_addr_random(dev);
+ eth_broadcast_addr(dev->broadcast);
+ }
+
+ return 0;
+}
+
+static int xfrmi_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static void xfrmi_netlink_parms(struct nlattr *data[],
+ struct xfrm_if_parms *parms)
+{
+ memset(parms, 0, sizeof(*parms));
+
+ if (!data)
+ return;
+
+ if (data[IFLA_XFRM_LINK])
+ parms->link = nla_get_u32(data[IFLA_XFRM_LINK]);
+
+ if (data[IFLA_XFRM_IF_ID])
+ parms->if_id = nla_get_u32(data[IFLA_XFRM_IF_ID]);
+}
+
+static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ struct net *net = dev_net(dev);
+ struct xfrm_if_parms p = {};
+ struct xfrm_if *xi;
+ int err;
+
+ xfrmi_netlink_parms(data, &p);
+ if (!p.if_id) {
+ NL_SET_ERR_MSG(extack, "if_id must be non zero");
+ return -EINVAL;
+ }
+
+ xi = xfrmi_locate(net, &p);
+ if (xi)
+ return -EEXIST;
+
+ xi = netdev_priv(dev);
+ xi->p = p;
+ xi->net = net;
+ xi->dev = dev;
+
+ err = xfrmi_create(dev);
+ return err;
+}
+
+static void xfrmi_dellink(struct net_device *dev, struct list_head *head)
+{
+ unregister_netdevice_queue(dev, head);
+}
+
+static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
+ struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net *net = xi->net;
+ struct xfrm_if_parms p = {};
+
+ xfrmi_netlink_parms(data, &p);
+ if (!p.if_id) {
+ NL_SET_ERR_MSG(extack, "if_id must be non zero");
+ return -EINVAL;
+ }
+
+ xi = xfrmi_locate(net, &p);
+ if (!xi) {
+ xi = netdev_priv(dev);
+ } else {
+ if (xi->dev != dev)
+ return -EEXIST;
+ }
+
+ return xfrmi_update(xi, &p);
+}
+
+static size_t xfrmi_get_size(const struct net_device *dev)
+{
+ return
+ /* IFLA_XFRM_LINK */
+ nla_total_size(4) +
+ /* IFLA_XFRM_IF_ID */
+ nla_total_size(4) +
+ 0;
+}
+
+static int xfrmi_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct xfrm_if_parms *parm = &xi->p;
+
+ if (nla_put_u32(skb, IFLA_XFRM_LINK, parm->link) ||
+ nla_put_u32(skb, IFLA_XFRM_IF_ID, parm->if_id))
+ goto nla_put_failure;
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static struct net *xfrmi_get_link_net(const struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+
+ return xi->net;
+}
+
+static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
+ [IFLA_XFRM_LINK] = { .type = NLA_U32 },
+ [IFLA_XFRM_IF_ID] = { .type = NLA_U32 },
+};
+
+static struct rtnl_link_ops xfrmi_link_ops __read_mostly = {
+ .kind = "xfrm",
+ .maxtype = IFLA_XFRM_MAX,
+ .policy = xfrmi_policy,
+ .priv_size = sizeof(struct xfrm_if),
+ .setup = xfrmi_dev_setup,
+ .validate = xfrmi_validate,
+ .newlink = xfrmi_newlink,
+ .dellink = xfrmi_dellink,
+ .changelink = xfrmi_changelink,
+ .get_size = xfrmi_get_size,
+ .fill_info = xfrmi_fill_info,
+ .get_link_net = xfrmi_get_link_net,
+};
+
+static void __net_exit xfrmi_exit_batch_net(struct list_head *net_exit_list)
+{
+ struct net *net;
+ LIST_HEAD(list);
+
+ rtnl_lock();
+ list_for_each_entry(net, net_exit_list, exit_list) {
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+ struct xfrm_if __rcu **xip;
+ struct xfrm_if *xi;
+ int i;
+
+ for (i = 0; i < XFRMI_HASH_SIZE; i++) {
+ for (xip = &xfrmn->xfrmi[i];
+ (xi = rtnl_dereference(*xip)) != NULL;
+ xip = &xi->next)
+ unregister_netdevice_queue(xi->dev, &list);
+ }
+ }
+ unregister_netdevice_many(&list);
+ rtnl_unlock();
+}
+
+static struct pernet_operations xfrmi_net_ops = {
+ .exit_batch = xfrmi_exit_batch_net,
+ .id = &xfrmi_net_id,
+ .size = sizeof(struct xfrmi_net),
+};
+
+static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
+ .handler = xfrmi6_rcv,
+ .input_handler = xfrmi6_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 10,
+};
+
+static struct xfrm6_protocol xfrmi_ah6_protocol __read_mostly = {
+ .handler = xfrm6_rcv,
+ .input_handler = xfrm_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 10,
+};
+
+static struct xfrm6_protocol xfrmi_ipcomp6_protocol __read_mostly = {
+ .handler = xfrm6_rcv,
+ .input_handler = xfrm_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 10,
+};
+
+#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+static int xfrmi6_rcv_tunnel(struct sk_buff *skb)
+{
+ const xfrm_address_t *saddr;
+ __be32 spi;
+
+ saddr = (const xfrm_address_t *)&ipv6_hdr(skb)->saddr;
+ spi = xfrm6_tunnel_spi_lookup(dev_net(skb->dev), saddr);
+
+ return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi, NULL);
+}
+
+static struct xfrm6_tunnel xfrmi_ipv6_handler __read_mostly = {
+ .handler = xfrmi6_rcv_tunnel,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 2,
+};
+
+static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
+ .handler = xfrmi6_rcv_tunnel,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 2,
+};
+#endif
+
+static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
+ .handler = xfrmi4_rcv,
+ .input_handler = xfrmi4_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 10,
+};
+
+static struct xfrm4_protocol xfrmi_ah4_protocol __read_mostly = {
+ .handler = xfrm4_rcv,
+ .input_handler = xfrm_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 10,
+};
+
+static struct xfrm4_protocol xfrmi_ipcomp4_protocol __read_mostly = {
+ .handler = xfrm4_rcv,
+ .input_handler = xfrm_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 10,
+};
+
+#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+static int xfrmi4_rcv_tunnel(struct sk_buff *skb)
+{
+ return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr);
+}
+
+static struct xfrm_tunnel xfrmi_ipip_handler __read_mostly = {
+ .handler = xfrmi4_rcv_tunnel,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 3,
+};
+
+static struct xfrm_tunnel xfrmi_ipip6_handler __read_mostly = {
+ .handler = xfrmi4_rcv_tunnel,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 2,
+};
+#endif
+
+static int __init xfrmi4_init(void)
+{
+ int err;
+
+ err = xfrm4_protocol_register(&xfrmi_esp4_protocol, IPPROTO_ESP);
+ if (err < 0)
+ goto xfrm_proto_esp_failed;
+ err = xfrm4_protocol_register(&xfrmi_ah4_protocol, IPPROTO_AH);
+ if (err < 0)
+ goto xfrm_proto_ah_failed;
+ err = xfrm4_protocol_register(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
+ if (err < 0)
+ goto xfrm_proto_comp_failed;
+#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+ err = xfrm4_tunnel_register(&xfrmi_ipip_handler, AF_INET);
+ if (err < 0)
+ goto xfrm_tunnel_ipip_failed;
+ err = xfrm4_tunnel_register(&xfrmi_ipip6_handler, AF_INET6);
+ if (err < 0)
+ goto xfrm_tunnel_ipip6_failed;
+#endif
+
+ return 0;
+
+#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+xfrm_tunnel_ipip6_failed:
+ xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
+xfrm_tunnel_ipip_failed:
+ xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
+#endif
+xfrm_proto_comp_failed:
+ xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
+xfrm_proto_ah_failed:
+ xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
+xfrm_proto_esp_failed:
+ return err;
+}
+
+static void xfrmi4_fini(void)
+{
+#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+ xfrm4_tunnel_deregister(&xfrmi_ipip6_handler, AF_INET6);
+ xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
+#endif
+ xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
+ xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
+ xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
+}
+
+static int __init xfrmi6_init(void)
+{
+ int err;
+
+ err = xfrm6_protocol_register(&xfrmi_esp6_protocol, IPPROTO_ESP);
+ if (err < 0)
+ goto xfrm_proto_esp_failed;
+ err = xfrm6_protocol_register(&xfrmi_ah6_protocol, IPPROTO_AH);
+ if (err < 0)
+ goto xfrm_proto_ah_failed;
+ err = xfrm6_protocol_register(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
+ if (err < 0)
+ goto xfrm_proto_comp_failed;
+#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+ err = xfrm6_tunnel_register(&xfrmi_ipv6_handler, AF_INET6);
+ if (err < 0)
+ goto xfrm_tunnel_ipv6_failed;
+ err = xfrm6_tunnel_register(&xfrmi_ip6ip_handler, AF_INET);
+ if (err < 0)
+ goto xfrm_tunnel_ip6ip_failed;
+#endif
+
+ return 0;
+
+#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+xfrm_tunnel_ip6ip_failed:
+ xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
+xfrm_tunnel_ipv6_failed:
+ xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
+#endif
+xfrm_proto_comp_failed:
+ xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
+xfrm_proto_ah_failed:
+ xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
+xfrm_proto_esp_failed:
+ return err;
+}
+
+static void xfrmi6_fini(void)
+{
+#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+ xfrm6_tunnel_deregister(&xfrmi_ip6ip_handler, AF_INET);
+ xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
+#endif
+ xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
+ xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
+ xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
+}
+
+static const struct xfrm_if_cb xfrm_if_cb = {
+ .decode_session = xfrmi_decode_session,
+};
+
+static int __init xfrmi_init(void)
+{
+ const char *msg;
+ int err;
+
+ pr_info("IPsec XFRM device driver\n");
+
+ msg = "tunnel device";
+ err = register_pernet_device(&xfrmi_net_ops);
+ if (err < 0)
+ goto pernet_dev_failed;
+
+ msg = "xfrm4 protocols";
+ err = xfrmi4_init();
+ if (err < 0)
+ goto xfrmi4_failed;
+
+ msg = "xfrm6 protocols";
+ err = xfrmi6_init();
+ if (err < 0)
+ goto xfrmi6_failed;
+
+
+ msg = "netlink interface";
+ err = rtnl_link_register(&xfrmi_link_ops);
+ if (err < 0)
+ goto rtnl_link_failed;
+
+ xfrm_if_register_cb(&xfrm_if_cb);
+
+ return err;
+
+rtnl_link_failed:
+ xfrmi6_fini();
+xfrmi6_failed:
+ xfrmi4_fini();
+xfrmi4_failed:
+ unregister_pernet_device(&xfrmi_net_ops);
+pernet_dev_failed:
+ pr_err("xfrmi init: failed to register %s\n", msg);
+ return err;
+}
+
+static void __exit xfrmi_fini(void)
+{
+ xfrm_if_unregister_cb();
+ rtnl_link_unregister(&xfrmi_link_ops);
+ xfrmi4_fini();
+ xfrmi6_fini();
+ unregister_pernet_device(&xfrmi_net_ops);
+}
+
+module_init(xfrmi_init);
+module_exit(xfrmi_fini);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_RTNL_LINK("xfrm");
+MODULE_ALIAS_NETDEV("xfrm0");
+MODULE_AUTHOR("Steffen Klassert");
+MODULE_DESCRIPTION("XFRM virtual interface");
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 3e28a84ab922..b0a19cc92879 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3275,6 +3275,13 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
return ++idx;
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
+ if (idx < sp->verified_cnt) {
+ /* Secpath entry previously verified, consider optional and
+ * continue searching
+ */
+ continue;
+ }
+
if (start == -1)
start = -2-idx;
break;
@@ -3647,6 +3654,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
* Order is _important_. Later we will implement
* some barriers, but at the moment barriers
* are implied between each two transformations.
+ * Upon success, marks secpath entries as having been
+ * verified to allow them to be skipped in future policy
+ * checks (e.g. nested tunnels).
*/
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
@@ -3665,6 +3675,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
}
xfrm_pols_put(pols, npols);
+ sp->verified_cnt = k;
+
return 1;
}
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK);
diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c
index 27589900f4fb..f7ff130a9485 100644
--- a/sound/soc/codecs/nau8824.c
+++ b/sound/soc/codecs/nau8824.c
@@ -1866,6 +1866,30 @@ static const struct dmi_system_id nau8824_quirk_table[] = {
},
.driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
},
+ {
+ /* Positivo CW14Q01P */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+ DMI_MATCH(DMI_BOARD_NAME, "CW14Q01P"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
+ {
+ /* Positivo K1424G */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+ DMI_MATCH(DMI_BOARD_NAME, "K1424G"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
+ {
+ /* Positivo N14ZP74G */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+ DMI_MATCH(DMI_BOARD_NAME, "N14ZP74G"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
{}
};
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index bc3e24c6a28a..283aa21879aa 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -417,6 +417,7 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv,
if (ret < 0) {
of_node_put(codec);
+ of_node_put(plat);
of_node_put(np);
goto error;
}
diff --git a/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c b/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c
index c2aa6f26738b..bf82b923c5fe 100644
--- a/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c
+++ b/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c
@@ -1,13 +1,14 @@
{
"bounds checks mixing signed and unsigned, positive bounds",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 2),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 3),
@@ -17,20 +18,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 3),
@@ -40,20 +42,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 2",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 5),
@@ -65,20 +68,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 3",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 4),
@@ -89,20 +93,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 4",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 1),
BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
@@ -112,19 +117,20 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.result = ACCEPT,
},
{
"bounds checks mixing signed and unsigned, variant 5",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 5),
@@ -135,17 +141,20 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 6",
.insns = {
+ BPF_MOV64_REG(BPF_REG_9, BPF_REG_1),
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_9),
BPF_MOV64_IMM(BPF_REG_2, 0),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -512),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_6, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_6, 5),
@@ -163,13 +172,14 @@
{
"bounds checks mixing signed and unsigned, variant 7",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 1024 * 1024 * 1024),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 3),
@@ -179,19 +189,20 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.result = ACCEPT,
},
{
"bounds checks mixing signed and unsigned, variant 8",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 2),
@@ -203,20 +214,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 9",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_LD_IMM64(BPF_REG_2, -9223372036854775808ULL),
BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 2),
@@ -228,19 +240,20 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.result = ACCEPT,
},
{
"bounds checks mixing signed and unsigned, variant 10",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 0),
BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 2),
@@ -252,20 +265,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 11",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
@@ -278,20 +292,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 12",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -6),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
@@ -303,20 +318,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 13",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 2),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
@@ -331,7 +347,7 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
@@ -340,13 +356,14 @@
.insns = {
BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
offsetof(struct __sk_buff, mark)),
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_MOV64_IMM(BPF_REG_8, 2),
@@ -360,20 +377,21 @@
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, -3),
BPF_JMP_IMM(BPF_JA, 0, 0, -7),
},
- .fixup_map_hash_8b = { 4 },
+ .fixup_map_hash_8b = { 6 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 15",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -6),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
@@ -387,7 +405,7 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c
index 969647228817..c6a8c732b802 100644
--- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c
+++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c
@@ -104,13 +104,6 @@
#else
#define __NR_mount_setattr 442
#endif
-
-struct mount_attr {
- __u64 attr_set;
- __u64 attr_clr;
- __u64 propagation;
- __u64 userns_fd;
-};
#endif
#ifndef __NR_open_tree
diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index 364c82b797c1..6ecdbbe1b54f 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -84,6 +84,13 @@ NSC_CMD="ip netns exec ${NSC}"
which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
+# Check if FIPS mode is enabled
+if [ -f /proc/sys/crypto/fips_enabled ]; then
+ fips_enabled=`cat /proc/sys/crypto/fips_enabled`
+else
+ fips_enabled=0
+fi
+
################################################################################
# utilities
@@ -1202,7 +1209,7 @@ ipv4_tcp_novrf()
run_cmd nettest -d ${NSA_DEV} -r ${a}
log_test_addr ${a} $? 1 "No server, device client, local conn"
- ipv4_tcp_md5_novrf
+ [ "$fips_enabled" = "1" ] || ipv4_tcp_md5_novrf
}
ipv4_tcp_vrf()
@@ -1256,9 +1263,11 @@ ipv4_tcp_vrf()
log_test_addr ${a} $? 1 "Global server, local connection"
# run MD5 tests
- setup_vrf_dup
- ipv4_tcp_md5
- cleanup_vrf_dup
+ if [ "$fips_enabled" = "0" ]; then
+ setup_vrf_dup
+ ipv4_tcp_md5
+ cleanup_vrf_dup
+ fi
#
# enable VRF global server
@@ -2674,7 +2683,7 @@ ipv6_tcp_novrf()
log_test_addr ${a} $? 1 "No server, device client, local conn"
done
- ipv6_tcp_md5_novrf
+ [ "$fips_enabled" = "1" ] || ipv6_tcp_md5_novrf
}
ipv6_tcp_vrf()
@@ -2744,9 +2753,11 @@ ipv6_tcp_vrf()
log_test_addr ${a} $? 1 "Global server, local connection"
# run MD5 tests
- setup_vrf_dup
- ipv6_tcp_md5
- cleanup_vrf_dup
+ if [ "$fips_enabled" = "0" ]; then
+ setup_vrf_dup
+ ipv6_tcp_md5
+ cleanup_vrf_dup
+ fi
#
# enable VRF global server
diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh
index c5095da7f6bf..aec752a22e9e 100755
--- a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh
+++ b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh
@@ -93,12 +93,16 @@ cleanup()
test_gretap()
{
+ ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \
+ nud permanent dev br2
full_test_span_gre_dir gt4 ingress 8 0 "mirror to gretap"
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
}
test_ip6gretap()
{
+ ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \
+ nud permanent dev br2
full_test_span_gre_dir gt6 ingress 8 0 "mirror to ip6gretap"
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
}
diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
index 9ff22f28032d..0cf4c47a46f9 100755
--- a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
+++ b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
@@ -90,12 +90,16 @@ cleanup()
test_gretap()
{
+ ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \
+ nud permanent dev br1
full_test_span_gre_dir gt4 ingress 8 0 "mirror to gretap"
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
}
test_ip6gretap()
{
+ ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \
+ nud permanent dev br1
full_test_span_gre_dir gt6 ingress 8 0 "mirror to ip6gretap"
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
}
diff --git a/tools/testing/selftests/net/forwarding/tc_actions.sh b/tools/testing/selftests/net/forwarding/tc_actions.sh
index 22a1e4c9553a..1e27031288c8 100755
--- a/tools/testing/selftests/net/forwarding/tc_actions.sh
+++ b/tools/testing/selftests/net/forwarding/tc_actions.sh
@@ -199,7 +199,6 @@ mirred_egress_to_ingress_tcp_test()
log_test "mirred_egress_to_ingress_tcp ($tcflags)"
}
->>>>>>> e921d05033293 (act_mirred: use the backlog for nested calls to mirred ingress)
setup_prepare()
{
h1=${NETIFS[p1]}
diff --git a/tools/testing/selftests/net/mptcp/config b/tools/testing/selftests/net/mptcp/config
index 0faaccd21447..f7d33a16051c 100644
--- a/tools/testing/selftests/net/mptcp/config
+++ b/tools/testing/selftests/net/mptcp/config
@@ -1,3 +1,4 @@
+CONFIG_KALLSYMS=y
CONFIG_MPTCP=y
CONFIG_IPV6=y
CONFIG_MPTCP_IPV6=y
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 7330e32bb9ab..368fae525fea 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -12,6 +12,8 @@ cinfail=""
cinsent=""
cout=""
ksft_skip=4
+iptables="iptables"
+ip6tables="ip6tables"
timeout_poll=30
timeout_test=$((timeout_poll * 2 + 1))
mptcp_connect=""
@@ -126,9 +128,9 @@ reset_with_add_addr_timeout()
local ip="${1:-4}"
local tables
- tables="iptables"
+ tables="${iptables}"
if [ $ip -eq 6 ]; then
- tables="ip6tables"
+ tables="${ip6tables}"
fi
reset
@@ -171,8 +173,10 @@ if [ $? -ne 0 ];then
exit $ksft_skip
fi
-iptables -V > /dev/null 2>&1
-if [ $? -ne 0 ];then
+if iptables-legacy -V &> /dev/null; then
+ iptables="iptables-legacy"
+ ip6tables="ip6tables-legacy"
+elif ! iptables -V &> /dev/null; then
echo "SKIP: Could not run all tests without iptables tool"
exit $ksft_skip
fi
@@ -243,6 +247,22 @@ is_v6()
[ -z "${1##*:*}" ]
}
+# $1: ns ; $2: counter
+get_counter()
+{
+ local ns="${1}"
+ local counter="${2}"
+ local count
+
+ count=$(ip netns exec ${ns} nstat -asz "${counter}" | awk 'NR==1 {next} {print $2}')
+ if [ -z "${count}" ]; then
+ mptcp_lib_fail_if_expected_feature "${counter} counter"
+ return 1
+ fi
+
+ echo "${count}"
+}
+
do_transfer()
{
listener_ns="$1"
@@ -556,9 +576,10 @@ chk_csum_nr()
echo -n " "
fi
printf " %-36s %s" "$msg" "sum"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != 0 ]; then
+ count=$(get_counter ${ns1} "MPTcpExtDataCsumErr")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != 0 ]; then
echo "[fail] got $count data checksum error[s] expected 0"
ret=1
dump_stats=1
@@ -566,9 +587,10 @@ chk_csum_nr()
echo -n "[ ok ]"
fi
echo -n " - csum "
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != 0 ]; then
+ count=$(get_counter ${ns2} "MPTcpExtDataCsumErr")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != 0 ]; then
echo "[fail] got $count data checksum error[s] expected 0"
ret=1
dump_stats=1
@@ -591,9 +613,10 @@ chk_fail_nr()
local dump_stats
printf "%-39s %s" " " "ftx"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPFailTx | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$mp_fail_nr_tx" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPFailTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$mp_fail_nr_tx" ]; then
echo "[fail] got $count MP_FAIL[s] TX expected $mp_fail_nr_tx"
ret=1
dump_stats=1
@@ -602,9 +625,10 @@ chk_fail_nr()
fi
echo -n " - frx "
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPFailRx | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$mp_fail_nr_rx" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtMPFailRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$mp_fail_nr_rx" ]; then
echo "[fail] got $count MP_FAIL[s] RX expected $mp_fail_nr_rx"
ret=1
dump_stats=1
@@ -631,9 +655,10 @@ chk_join_nr()
local with_cookie
printf "%02u %-36s %s" "$TEST_COUNT" "$msg" "syn"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinSynRx | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinSynRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn expected $syn_nr"
ret=1
dump_stats=1
@@ -643,9 +668,10 @@ chk_join_nr()
echo -n " - synack"
with_cookie=`ip netns exec $ns2 sysctl -n net.ipv4.tcp_syncookies`
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinSynAckRx | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_ack_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtMPJoinSynAckRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_ack_nr" ]; then
# simult connections exceeding the limit with cookie enabled could go up to
# synack validation as the conn limit can be enforced reliably only after
# the subflow creation
@@ -661,9 +687,10 @@ chk_join_nr()
fi
echo -n " - ack"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinAckRx | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$ack_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinAckRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack expected $ack_nr"
ret=1
dump_stats=1
@@ -698,14 +725,13 @@ chk_stale_nr()
local recover_nr
printf "%-39s %-18s" " " "stale"
- stale_nr=`ip netns exec $ns nstat -as | grep MPTcpExtSubflowStale | awk '{print $2}'`
- [ -z "$stale_nr" ] && stale_nr=0
- recover_nr=`ip netns exec $ns nstat -as | grep MPTcpExtSubflowRecover | awk '{print $2}'`
- [ -z "$recover_nr" ] && recover_nr=0
-
- if [ $stale_nr -lt $stale_min ] ||
- [ $stale_max -gt 0 -a $stale_nr -gt $stale_max ] ||
- [ $((stale_nr - $recover_nr)) -ne $stale_delta ]; then
+ stale_nr=$(get_counter ${ns} "MPTcpExtSubflowStale")
+ recover_nr=$(get_counter ${ns} "MPTcpExtSubflowRecover")
+ if [ -z "$stale_nr" ] || [ -z "$recover_nr" ]; then
+ echo "[skip]"
+ elif [ $stale_nr -lt $stale_min ] ||
+ [ $stale_max -gt 0 -a $stale_nr -gt $stale_max ] ||
+ [ $((stale_nr - $recover_nr)) -ne $stale_delta ]; then
echo "[fail] got $stale_nr stale[s] $recover_nr recover[s], " \
" expected stale in range [$stale_min..$stale_max]," \
" stale-recover delta $stale_delta "
@@ -736,9 +762,10 @@ chk_add_nr()
local dump_stats
printf "%-39s %s" " " "add"
- count=`ip netns exec $ns2 nstat -as MPTcpExtAddAddr | grep MPTcpExtAddAddr | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$add_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtAddAddr")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$add_nr" ]; then
echo "[fail] got $count ADD_ADDR[s] expected $add_nr"
ret=1
dump_stats=1
@@ -747,9 +774,10 @@ chk_add_nr()
fi
echo -n " - echo "
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtEchoAdd | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$echo_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtEchoAdd")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$echo_nr" ]; then
echo "[fail] got $count ADD_ADDR echo[s] expected $echo_nr"
ret=1
dump_stats=1
@@ -759,9 +787,10 @@ chk_add_nr()
if [ $port_nr -gt 0 ]; then
echo -n " - pt "
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtPortAdd | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$port_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtPortAdd")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$port_nr" ]; then
echo "[fail] got $count ADD_ADDR[s] with a port-number expected $port_nr"
ret=1
dump_stats=1
@@ -770,10 +799,10 @@ chk_add_nr()
fi
printf "%-39s %s" " " "syn"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortSynRx |
- awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinPortSynRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn with a different \
port-number expected $syn_nr"
ret=1
@@ -783,10 +812,10 @@ chk_add_nr()
fi
echo -n " - synack"
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinPortSynAckRx |
- awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_ack_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_ack_nr" ]; then
echo "[fail] got $count JOIN[s] synack with a different \
port-number expected $syn_ack_nr"
ret=1
@@ -796,10 +825,10 @@ chk_add_nr()
fi
echo -n " - ack"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortAckRx |
- awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$ack_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinPortAckRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack with a different \
port-number expected $ack_nr"
ret=1
@@ -809,10 +838,10 @@ chk_add_nr()
fi
printf "%-39s %s" " " "syn"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortSynRx |
- awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$mis_syn_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMismatchPortSynRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$mis_syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn with a mismatched \
port-number expected $mis_syn_nr"
ret=1
@@ -822,10 +851,10 @@ chk_add_nr()
fi
echo -n " - ack "
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortAckRx |
- awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$mis_ack_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMismatchPortAckRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$mis_ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack with a mismatched \
port-number expected $mis_ack_nr"
ret=1
@@ -864,9 +893,10 @@ chk_rm_nr()
fi
printf "%-39s %s" " " "rm "
- count=`ip netns exec $addr_ns nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$rm_addr_nr" ]; then
+ count=$(get_counter ${addr_ns} "MPTcpExtRmAddr")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$rm_addr_nr" ]; then
echo "[fail] got $count RM_ADDR[s] expected $rm_addr_nr"
ret=1
dump_stats=1
@@ -875,9 +905,10 @@ chk_rm_nr()
fi
echo -n " - sf "
- count=`ip netns exec $subflow_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$rm_subflow_nr" ]; then
+ count=$(get_counter ${subflow_ns} "MPTcpExtRmSubflow")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$rm_subflow_nr" ]; then
echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr"
ret=1
dump_stats=1
@@ -901,9 +932,10 @@ chk_prio_nr()
local dump_stats
printf "%-39s %s" " " "ptx"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$mp_prio_nr_tx" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPPrioTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$mp_prio_nr_tx" ]; then
echo "[fail] got $count MP_PRIO[s] TX expected $mp_prio_nr_tx"
ret=1
dump_stats=1
@@ -912,9 +944,10 @@ chk_prio_nr()
fi
echo -n " - prx "
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}'`
- [ -z "$count" ] && count=0
- if [ "$count" != "$mp_prio_nr_rx" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPPrioRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$mp_prio_nr_rx" ]; then
echo "[fail] got $count MP_PRIO[s] RX expected $mp_prio_nr_rx"
ret=1
dump_stats=1
diff --git a/tools/testing/selftests/net/mptcp/mptcp_lib.sh b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
index 3286536b79d5..f32045b23b89 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_lib.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
@@ -38,3 +38,67 @@ mptcp_lib_check_mptcp() {
exit ${KSFT_SKIP}
fi
}
+
+mptcp_lib_check_kallsyms() {
+ if ! mptcp_lib_has_file "/proc/kallsyms"; then
+ echo "SKIP: CONFIG_KALLSYMS is missing"
+ exit ${KSFT_SKIP}
+ fi
+}
+
+# Internal: use mptcp_lib_kallsyms_has() instead
+__mptcp_lib_kallsyms_has() {
+ local sym="${1}"
+
+ mptcp_lib_check_kallsyms
+
+ grep -q " ${sym}" /proc/kallsyms
+}
+
+# $1: part of a symbol to look at, add '$' at the end for full name
+mptcp_lib_kallsyms_has() {
+ local sym="${1}"
+
+ if __mptcp_lib_kallsyms_has "${sym}"; then
+ return 0
+ fi
+
+ mptcp_lib_fail_if_expected_feature "${sym} symbol not found"
+}
+
+# $1: part of a symbol to look at, add '$' at the end for full name
+mptcp_lib_kallsyms_doesnt_have() {
+ local sym="${1}"
+
+ if ! __mptcp_lib_kallsyms_has "${sym}"; then
+ return 0
+ fi
+
+ mptcp_lib_fail_if_expected_feature "${sym} symbol has been found"
+}
+
+# !!!AVOID USING THIS!!!
+# Features might not land in the expected version and features can be backported
+#
+# $1: kernel version, e.g. 6.3
+mptcp_lib_kversion_ge() {
+ local exp_maj="${1%.*}"
+ local exp_min="${1#*.}"
+ local v maj min
+
+ # If the kernel has backported features, set this env var to 1:
+ if [ "${SELFTESTS_MPTCP_LIB_NO_KVERSION_CHECK:-}" = "1" ]; then
+ return 0
+ fi
+
+ v=$(uname -r | cut -d'.' -f1,2)
+ maj=${v%.*}
+ min=${v#*.}
+
+ if [ "${maj}" -gt "${exp_maj}" ] ||
+ { [ "${maj}" -eq "${exp_maj}" ] && [ "${min}" -ge "${exp_min}" ]; }; then
+ return 0
+ fi
+
+ mptcp_lib_fail_if_expected_feature "kernel version ${1} lower than ${v}"
+}
diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh
index 7fb06c854852..306372b1526a 100755
--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh
+++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh
@@ -73,8 +73,12 @@ check()
}
check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "defaults addr list"
-check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
+
+default_limits="$(ip netns exec $ns1 ./pm_nl_ctl limits)"
+if mptcp_lib_expect_all_features; then
+ check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
subflows 0" "defaults limits"
+fi
ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1
ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.2 flags subflow dev lo
@@ -121,12 +125,10 @@ ip netns exec $ns1 ./pm_nl_ctl flush
check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "flush addrs"
ip netns exec $ns1 ./pm_nl_ctl limits 9 1
-check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
-subflows 0" "rcv addrs above hard limit"
+check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "rcv addrs above hard limit"
ip netns exec $ns1 ./pm_nl_ctl limits 1 9
-check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
-subflows 0" "subflows above hard limit"
+check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "subflows above hard limit"
ip netns exec $ns1 ./pm_nl_ctl limits 8 8
check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 8
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 1cb2530831f4..3967184b7d62 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -636,6 +636,24 @@ static __always_inline int kvm_handle_hva_range_no_flush(struct mmu_notifier *mn
return __kvm_handle_hva_range(kvm, &range);
}
+
+static bool kvm_change_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ /*
+ * Skipping invalid memslots is correct if and only change_pte() is
+ * surrounded by invalidate_range_{start,end}(), which is currently
+ * guaranteed by the primary MMU. If that ever changes, KVM needs to
+ * unmap the memslot instead of skipping the memslot to ensure that KVM
+ * doesn't hold references to the old PFN.
+ */
+ WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count));
+
+ if (range->slot->flags & KVM_MEMSLOT_INVALID)
+ return false;
+
+ return kvm_set_spte_gfn(kvm, range);
+}
+
static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long address,
@@ -656,7 +674,7 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
if (!READ_ONCE(kvm->mmu_notifier_count))
return;
- kvm_handle_hva_range(mn, address, address + 1, pte, kvm_set_spte_gfn);
+ kvm_handle_hva_range(mn, address, address + 1, pte, kvm_change_spte_gfn);
}
void kvm_inc_notifier_count(struct kvm *kvm, unsigned long start,
^ permalink raw reply related [relevance 1%]
* Re: Linux 6.3.10
@ 2023-06-28 9:26 1% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-06-28 9:26 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/Makefile b/Makefile
index f8ee72375885..47253ac6c85c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 3
-SUBLEVEL = 9
+SUBLEVEL = 10
EXTRAVERSION =
NAME = Hurr durr I'ma ninja sloth
diff --git a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
index 2fc9a5d5e0c0..625b9b311b49 100644
--- a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
+++ b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
@@ -527,7 +527,7 @@ touchscreen@1 {
interrupt-parent = <&gpio1>;
interrupts = <31 0>;
- pendown-gpio = <&gpio1 31 0>;
+ pendown-gpio = <&gpio1 31 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
diff --git a/arch/arm/boot/dts/at91sam9261ek.dts b/arch/arm/boot/dts/at91sam9261ek.dts
index 88869ca874d1..045cb253f23a 100644
--- a/arch/arm/boot/dts/at91sam9261ek.dts
+++ b/arch/arm/boot/dts/at91sam9261ek.dts
@@ -156,7 +156,7 @@ tsc2046@2 {
compatible = "ti,ads7843";
interrupts-extended = <&pioC 2 IRQ_TYPE_EDGE_BOTH>;
spi-max-frequency = <3000000>;
- pendown-gpio = <&pioC 2 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&pioC 2 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <150>;
ti,x-max = /bits/ 16 <3830>;
diff --git a/arch/arm/boot/dts/imx7d-pico-hobbit.dts b/arch/arm/boot/dts/imx7d-pico-hobbit.dts
index d917dc4f2f22..6ad39dca7009 100644
--- a/arch/arm/boot/dts/imx7d-pico-hobbit.dts
+++ b/arch/arm/boot/dts/imx7d-pico-hobbit.dts
@@ -64,7 +64,7 @@ ads7846@0 {
interrupt-parent = <&gpio2>;
interrupts = <7 0>;
spi-max-frequency = <1000000>;
- pendown-gpio = <&gpio2 7 0>;
+ pendown-gpio = <&gpio2 7 GPIO_ACTIVE_LOW>;
vcc-supply = <®_3p3v>;
ti,x-min = /bits/ 16 <0>;
ti,x-max = /bits/ 16 <4095>;
diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
index f483bc0afe5e..234e5fc647b2 100644
--- a/arch/arm/boot/dts/imx7d-sdb.dts
+++ b/arch/arm/boot/dts/imx7d-sdb.dts
@@ -205,7 +205,7 @@ tsc2046@0 {
pinctrl-0 = <&pinctrl_tsc2046_pendown>;
interrupt-parent = <&gpio2>;
interrupts = <29 0>;
- pendown-gpio = <&gpio2 29 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio2 29 GPIO_ACTIVE_LOW>;
touchscreen-max-pressure = <255>;
wakeup-source;
};
diff --git a/arch/arm/boot/dts/omap3-cm-t3x.dtsi b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
index e61b8a2bfb7d..51baedf1603b 100644
--- a/arch/arm/boot/dts/omap3-cm-t3x.dtsi
+++ b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
@@ -227,7 +227,7 @@ ads7846@0 {
interrupt-parent = <&gpio2>;
interrupts = <25 0>; /* gpio_57 */
- pendown-gpio = <&gpio2 25 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio2 25 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
index 3decc2d78a6c..a7f99ae0c1fe 100644
--- a/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
+++ b/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
@@ -54,7 +54,7 @@ ads7846@0 {
interrupt-parent = <&gpio1>;
interrupts = <27 0>; /* gpio_27 */
- pendown-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio1 27 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
index c595afe4181d..d310b5c7bac3 100644
--- a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
+++ b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
@@ -311,7 +311,7 @@ tsc2046@0 {
interrupt-parent = <&gpio1>;
interrupts = <8 0>; /* boot6 / gpio_8 */
spi-max-frequency = <1000000>;
- pendown-gpio = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio1 8 GPIO_ACTIVE_LOW>;
vcc-supply = <®_vcc3>;
pinctrl-names = "default";
pinctrl-0 = <&tsc2048_pins>;
diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi b/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
index 1d6e88f99eb3..c3570acc35fa 100644
--- a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
@@ -149,7 +149,7 @@ ads7846@0 {
interrupt-parent = <&gpio4>;
interrupts = <18 0>; /* gpio_114 */
- pendown-gpio = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio4 18 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi b/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
index 7e30f9d45790..d95a0e130058 100644
--- a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
@@ -160,7 +160,7 @@ ads7846@0 {
interrupt-parent = <&gpio4>;
interrupts = <18 0>; /* gpio_114 */
- pendown-gpio = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio4 18 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-pandora-common.dtsi b/arch/arm/boot/dts/omap3-pandora-common.dtsi
index 559853764487..4c3b6bab179c 100644
--- a/arch/arm/boot/dts/omap3-pandora-common.dtsi
+++ b/arch/arm/boot/dts/omap3-pandora-common.dtsi
@@ -651,7 +651,7 @@ tsc2046@0 {
pinctrl-0 = <&penirq_pins>;
interrupt-parent = <&gpio3>;
interrupts = <30 IRQ_TYPE_NONE>; /* GPIO_94 */
- pendown-gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio3 30 GPIO_ACTIVE_LOW>;
vcc-supply = <&vaux4>;
ti,x-min = /bits/ 16 <0>;
diff --git a/arch/arm/boot/dts/omap5-cm-t54.dts b/arch/arm/boot/dts/omap5-cm-t54.dts
index 2d87b9fc230e..af288d63a26a 100644
--- a/arch/arm/boot/dts/omap5-cm-t54.dts
+++ b/arch/arm/boot/dts/omap5-cm-t54.dts
@@ -354,7 +354,7 @@ ads7846@0 {
interrupt-parent = <&gpio1>;
interrupts = <15 0>; /* gpio1_wk15 */
- pendown-gpio = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio1 15 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
index 8b5293e7fd2a..a0e767ff252c 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
@@ -480,7 +480,6 @@ &swr0 {
wcd_rx: codec@0,4 {
compatible = "sdw20217010d00";
reg = <0 4>;
- #sound-dai-cells = <1>;
qcom,rx-port-mapping = <1 2 3 4 5>;
};
};
@@ -491,7 +490,6 @@ &swr1 {
wcd_tx: codec@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
- #sound-dai-cells = <1>;
qcom,tx-port-mapping = <1 2 3 4>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
index 88204f794ccb..1080d701d45a 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
@@ -419,7 +419,6 @@ &swr0 {
wcd_rx: codec@0,4 {
compatible = "sdw20217010d00";
reg = <0 4>;
- #sound-dai-cells = <1>;
qcom,rx-port-mapping = <1 2 3 4 5>;
};
};
@@ -428,7 +427,6 @@ &swr1 {
wcd_tx: codec@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
- #sound-dai-cells = <1>;
qcom,tx-port-mapping = <1 2 3 4>;
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
index 263ce40770dd..cddf6cd2fecb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
@@ -28,6 +28,16 @@ vcc_5v: vcc-5v-regulator {
regulator-max-microvolt = <5000000>;
vin-supply = <&vcc12v_dcin>;
};
+
+ vcc_sd_pwr: vcc-sd-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sd_pwr";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
};
/* phy for pcie */
@@ -130,13 +140,7 @@ &saradc {
};
&sdmmc0 {
- vmmc-supply = <&sdmmc_pwr>;
- status = "okay";
-};
-
-&sdmmc_pwr {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
+ vmmc-supply = <&vcc_sd_pwr>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
index 102e448bc026..31aa2b8efe39 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
@@ -104,16 +104,6 @@ vcc3v3_sys: vcc3v3-sys-regulator {
regulator-max-microvolt = <3300000>;
vin-supply = <&vcc5v0_sys>;
};
-
- sdmmc_pwr: sdmmc-pwr-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&sdmmc_pwr_h>;
- regulator-name = "sdmmc_pwr";
- status = "disabled";
- };
};
&cpu0 {
@@ -155,6 +145,19 @@ &gmac1m0_clkinout
status = "disabled";
};
+&gpio0 {
+ nextrst-hog {
+ gpio-hog;
+ /*
+ * GPIO_ACTIVE_LOW + output-low here means that the pin is set
+ * to high, because output-low decides the value pre-inversion.
+ */
+ gpios = <RK_PA5 GPIO_ACTIVE_LOW>;
+ line-name = "nEXTRST";
+ output-low;
+ };
+};
+
&gpu {
mali-supply = <&vdd_gpu>;
status = "okay";
@@ -538,12 +541,6 @@ wifi_enable_h: wifi-enable-h {
rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
-
- sdmmc-pwr {
- sdmmc_pwr_h: sdmmc-pwr-h {
- rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
};
&pmu_io_domains {
diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
index ba67b58f05b7..f1be76a54ceb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
@@ -94,9 +94,10 @@ pcie3x1: pcie@fe270000 {
power-domains = <&power RK3568_PD_PIPE>;
reg = <0x3 0xc0400000 0x0 0x00400000>,
<0x0 0xfe270000 0x0 0x00010000>,
- <0x3 0x7f000000 0x0 0x01000000>;
- ranges = <0x01000000 0x0 0x3ef00000 0x3 0x7ef00000 0x0 0x00100000>,
- <0x02000000 0x0 0x00000000 0x3 0x40000000 0x0 0x3ef00000>;
+ <0x0 0xf2000000 0x0 0x00100000>;
+ ranges = <0x01000000 0x0 0xf2100000 0x0 0xf2100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf2200000 0x0 0xf2200000 0x0 0x01e00000>,
+ <0x03000000 0x0 0x40000000 0x3 0x40000000 0x0 0x40000000>;
reg-names = "dbi", "apb", "config";
resets = <&cru SRST_PCIE30X1_POWERUP>;
reset-names = "pipe";
@@ -146,9 +147,10 @@ pcie3x2: pcie@fe280000 {
power-domains = <&power RK3568_PD_PIPE>;
reg = <0x3 0xc0800000 0x0 0x00400000>,
<0x0 0xfe280000 0x0 0x00010000>,
- <0x3 0xbf000000 0x0 0x01000000>;
- ranges = <0x01000000 0x0 0x3ef00000 0x3 0xbef00000 0x0 0x00100000>,
- <0x02000000 0x0 0x00000000 0x3 0x80000000 0x0 0x3ef00000>;
+ <0x0 0xf0000000 0x0 0x00100000>;
+ ranges = <0x01000000 0x0 0xf0100000 0x0 0xf0100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf0200000 0x0 0xf0200000 0x0 0x01e00000>,
+ <0x03000000 0x0 0x40000000 0x3 0x80000000 0x0 0x40000000>;
reg-names = "dbi", "apb", "config";
resets = <&cru SRST_PCIE30X2_POWERUP>;
reset-names = "pipe";
diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index eed0059a68b8..3ee5d764ac63 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -952,7 +952,7 @@ pcie2x1: pcie@fe260000 {
compatible = "rockchip,rk3568-pcie";
reg = <0x3 0xc0000000 0x0 0x00400000>,
<0x0 0xfe260000 0x0 0x00010000>,
- <0x3 0x3f000000 0x0 0x01000000>;
+ <0x0 0xf4000000 0x0 0x00100000>;
reg-names = "dbi", "apb", "config";
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
@@ -982,8 +982,9 @@ pcie2x1: pcie@fe260000 {
phys = <&combphy2 PHY_TYPE_PCIE>;
phy-names = "pcie-phy";
power-domains = <&power RK3568_PD_PIPE>;
- ranges = <0x01000000 0x0 0x3ef00000 0x3 0x3ef00000 0x0 0x00100000
- 0x02000000 0x0 0x00000000 0x3 0x00000000 0x0 0x3ef00000>;
+ ranges = <0x01000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0x01e00000>,
+ <0x03000000 0x0 0x40000000 0x3 0x00000000 0x0 0x40000000>;
resets = <&cru SRST_PCIE20_POWERUP>;
reset-names = "pipe";
#address-cells = <3>;
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 9e3ecba3c4e6..d4a85c1db2e2 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -115,8 +115,14 @@
#define SB_BARRIER_INSN __SYS_BARRIER_INSN(0, 7, 31)
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
+#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
+#define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6)
#define SYS_DC_CSW sys_insn(1, 0, 7, 10, 2)
+#define SYS_DC_CGSW sys_insn(1, 0, 7, 10, 4)
+#define SYS_DC_CGDSW sys_insn(1, 0, 7, 10, 6)
#define SYS_DC_CISW sys_insn(1, 0, 7, 14, 2)
+#define SYS_DC_CIGSW sys_insn(1, 0, 7, 14, 4)
+#define SYS_DC_CIGDSW sys_insn(1, 0, 7, 14, 6)
/*
* Automatically generated definitions for system registers, the
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 33f4d4200329..168365167a13 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -81,7 +81,12 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
* EL1 instead of being trapped to EL2.
*/
if (kvm_arm_support_pmu_v3()) {
+ struct kvm_cpu_context *hctxt;
+
write_sysreg(0, pmselr_el0);
+
+ hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
+ ctxt_sys_reg(hctxt, PMUSERENR_EL0) = read_sysreg(pmuserenr_el0);
write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);
}
@@ -105,8 +110,12 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
write_sysreg(vcpu->arch.mdcr_el2_host, mdcr_el2);
write_sysreg(0, hstr_el2);
- if (kvm_arm_support_pmu_v3())
- write_sysreg(0, pmuserenr_el0);
+ if (kvm_arm_support_pmu_v3()) {
+ struct kvm_cpu_context *hctxt;
+
+ hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
+ write_sysreg(ctxt_sys_reg(hctxt, PMUSERENR_EL0), pmuserenr_el0);
+ }
if (cpus_have_final_cap(ARM64_SME)) {
sysreg_clear_set_s(SYS_HFGRTR_EL2, 0,
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index c199ba2f192e..06ca3b722f26 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -446,6 +446,7 @@ int vgic_lazy_init(struct kvm *kvm)
int kvm_vgic_map_resources(struct kvm *kvm)
{
struct vgic_dist *dist = &kvm->arch.vgic;
+ enum vgic_type type;
gpa_t dist_base;
int ret = 0;
@@ -460,10 +461,13 @@ int kvm_vgic_map_resources(struct kvm *kvm)
if (!irqchip_in_kernel(kvm))
goto out;
- if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+ if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
ret = vgic_v2_map_resources(kvm);
- else
+ type = VGIC_V2;
+ } else {
ret = vgic_v3_map_resources(kvm);
+ type = VGIC_V3;
+ }
if (ret) {
__kvm_vgic_destroy(kvm);
@@ -473,8 +477,7 @@ int kvm_vgic_map_resources(struct kvm *kvm)
dist_base = dist->vgic_dist_base;
mutex_unlock(&kvm->arch.config_lock);
- ret = vgic_register_dist_iodev(kvm, dist_base,
- kvm_vgic_global_state.type);
+ ret = vgic_register_dist_iodev(kvm, dist_base, type);
if (ret) {
kvm_err("Unable to register VGIC dist MMIO regions\n");
kvm_vgic_destroy(kvm);
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index b05e833a022d..d46b6722710f 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -7,7 +7,7 @@
#
OBJCOPYFLAGS := -O binary
-LDFLAGS_vmlinux :=
+LDFLAGS_vmlinux := -z norelro
ifeq ($(CONFIG_DYNAMIC_FTRACE),y)
LDFLAGS_vmlinux := --no-relax
KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile
index 32573b4f9bd2..cc8cf5abea15 100644
--- a/arch/s390/purgatory/Makefile
+++ b/arch/s390/purgatory/Makefile
@@ -26,6 +26,7 @@ KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare
KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding
KBUILD_CFLAGS += -Os -m64 -msoft-float -fno-common
KBUILD_CFLAGS += -fno-stack-protector
+KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
KBUILD_CFLAGS += $(CLANG_FLAGS)
KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS))
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index b39975977c03..fdc2e3abd615 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -305,6 +305,18 @@ ifeq ($(RETPOLINE_CFLAGS),)
endif
endif
+ifdef CONFIG_UNWINDER_ORC
+orc_hash_h := arch/$(SRCARCH)/include/generated/asm/orc_hash.h
+orc_hash_sh := $(srctree)/scripts/orc_hash.sh
+targets += $(orc_hash_h)
+quiet_cmd_orc_hash = GEN $@
+ cmd_orc_hash = mkdir -p $(dir $@); \
+ $(CONFIG_SHELL) $(orc_hash_sh) < $< > $@
+$(orc_hash_h): $(srctree)/arch/x86/include/asm/orc_types.h $(orc_hash_sh) FORCE
+ $(call if_changed,orc_hash)
+archprepare: $(orc_hash_h)
+endif
+
archclean:
$(Q)rm -rf $(objtree)/arch/i386
$(Q)rm -rf $(objtree)/arch/x86_64
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 1e51650b79d7..4f1ce5fc4e19 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
+generated-y += orc_hash.h
generated-y += syscalls_32.h
generated-y += syscalls_64.h
generated-y += syscalls_x32.h
diff --git a/arch/x86/include/asm/orc_header.h b/arch/x86/include/asm/orc_header.h
new file mode 100644
index 000000000000..07bacf3e160e
--- /dev/null
+++ b/arch/x86/include/asm/orc_header.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
+#ifndef _ORC_HEADER_H
+#define _ORC_HEADER_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <asm/orc_hash.h>
+
+/*
+ * The header is currently a 20-byte hash of the ORC entry definition; see
+ * scripts/orc_hash.sh.
+ */
+#define ORC_HEADER \
+ __used __section(".orc_header") __aligned(4) \
+ static const u8 orc_header[] = { ORC_HASH }
+
+#endif /* _ORC_HEADER_H */
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 6bde05a86b4e..896bc41cb2ba 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -97,7 +97,10 @@ static void init_x2apic_ldr(void)
static int x2apic_phys_probe(void)
{
- if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys()))
+ if (!x2apic_mode)
+ return 0;
+
+ if (x2apic_phys || x2apic_fadt_phys())
return 1;
return apic == &apic_x2apic_phys;
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index 37307b40f8da..c960f250624a 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -7,6 +7,9 @@
#include <asm/unwind.h>
#include <asm/orc_types.h>
#include <asm/orc_lookup.h>
+#include <asm/orc_header.h>
+
+ORC_HEADER;
#define orc_warn(fmt, ...) \
printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__)
diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c
index 557f0fe25dff..37db264866b6 100644
--- a/arch/x86/mm/kaslr.c
+++ b/arch/x86/mm/kaslr.c
@@ -172,10 +172,10 @@ void __meminit init_trampoline_kaslr(void)
set_p4d(p4d_tramp,
__p4d(_KERNPG_TABLE | __pa(pud_page_tramp)));
- set_pgd(&trampoline_pgd_entry,
- __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp)));
+ trampoline_pgd_entry =
+ __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp));
} else {
- set_pgd(&trampoline_pgd_entry,
- __pgd(_KERNPG_TABLE | __pa(pud_page_tramp)));
+ trampoline_pgd_entry =
+ __pgd(_KERNPG_TABLE | __pa(pud_page_tramp));
}
}
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 1056bbf55b17..438adb695daa 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -2570,7 +2570,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
}
if (bpf_jit_enable > 1)
- bpf_jit_dump(prog->len, proglen, pass + 1, image);
+ bpf_jit_dump(prog->len, proglen, pass + 1, rw_image);
if (image) {
if (!prog->is_func || extra_pass) {
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index dd6d1c0117b1..581aa08e34a8 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -907,6 +907,7 @@ static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu)
struct llist_head *lhead = per_cpu_ptr(blkcg->lhead, cpu);
struct llist_node *lnode;
struct blkg_iostat_set *bisc, *next_bisc;
+ unsigned long flags;
rcu_read_lock();
@@ -920,7 +921,7 @@ static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu)
* When flushing from cgroup, cgroup_rstat_lock is always held, so
* this lock won't cause contention most of time.
*/
- raw_spin_lock(&blkg_stat_lock);
+ raw_spin_lock_irqsave(&blkg_stat_lock, flags);
/*
* Iterate only the iostat_cpu's queued in the lockless list.
@@ -946,7 +947,7 @@ static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu)
blkcg_iostat_update(parent, &blkg->iostat.cur,
&blkg->iostat.last);
}
- raw_spin_unlock(&blkg_stat_lock);
+ raw_spin_unlock_irqrestore(&blkg_stat_lock, flags);
out:
rcu_read_unlock();
}
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 6f2787506b50..c1b6e7bf4fcb 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -101,8 +101,6 @@ acpi_status
acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
acpi_event_status *event_status);
-acpi_status acpi_hw_disable_all_gpes(void);
-
acpi_status acpi_hw_enable_all_runtime_gpes(void);
acpi_status acpi_hw_enable_all_wakeup_gpes(void);
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 4ca667251272..539c12fbd2f1 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -636,11 +636,19 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
}
/*
- * Disable and clear GPE status before interrupt is enabled. Some GPEs
- * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
- * acpi_leave_sleep_state will reenable specific GPEs later
+ * Disable all GPE and clear their status bits before interrupts are
+ * enabled. Some GPEs (like wakeup GPEs) have no handlers and this can
+ * prevent them from producing spurious interrups.
+ *
+ * acpi_leave_sleep_state() will reenable specific GPEs later.
+ *
+ * Because this code runs on one CPU with disabled interrupts (all of
+ * the other CPUs are offline at this time), it need not acquire any
+ * sleeping locks which may trigger an implicit preemption point even
+ * if there is no contention, so avoid doing that by using a low-level
+ * library routine here.
*/
- acpi_disable_all_gpes();
+ acpi_hw_disable_all_gpes();
/* Allow EC transactions to happen. */
acpi_ec_unblock_transactions();
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 14c17c3bda4e..d37df499c9fa 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5348,7 +5348,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
mutex_init(&ap->scsi_scan_mutex);
INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
- INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
+ INIT_DELAYED_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
INIT_LIST_HEAD(&ap->eh_done_q);
init_waitqueue_head(&ap->eh_wait_q);
init_completion(&ap->park_req_pending);
@@ -5954,6 +5954,7 @@ static void ata_port_detach(struct ata_port *ap)
WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED));
cancel_delayed_work_sync(&ap->hotplug_task);
+ cancel_delayed_work_sync(&ap->scsi_rescan_task);
skip_eh:
/* clean up zpodd on port removal */
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index a6c901811802..6f8d14191593 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2984,7 +2984,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
ehc->i.flags |= ATA_EHI_SETMODE;
/* schedule the scsi_rescan_device() here */
- schedule_work(&(ap->scsi_rescan_task));
+ schedule_delayed_work(&ap->scsi_rescan_task, 0);
} else if (dev->class == ATA_DEV_UNKNOWN &&
ehc->tries[dev->devno] &&
ata_class_enabled(ehc->classes[dev->devno])) {
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index a9e768fdae4e..51673d95e5b2 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -4597,10 +4597,11 @@ int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
void ata_scsi_dev_rescan(struct work_struct *work)
{
struct ata_port *ap =
- container_of(work, struct ata_port, scsi_rescan_task);
+ container_of(work, struct ata_port, scsi_rescan_task.work);
struct ata_link *link;
struct ata_device *dev;
unsigned long flags;
+ bool delay_rescan = false;
mutex_lock(&ap->scsi_scan_mutex);
spin_lock_irqsave(ap->lock, flags);
@@ -4614,6 +4615,21 @@ void ata_scsi_dev_rescan(struct work_struct *work)
if (scsi_device_get(sdev))
continue;
+ /*
+ * If the rescan work was scheduled because of a resume
+ * event, the port is already fully resumed, but the
+ * SCSI device may not yet be fully resumed. In such
+ * case, executing scsi_rescan_device() may cause a
+ * deadlock with the PM code on device_lock(). Prevent
+ * this by giving up and retrying rescan after a short
+ * delay.
+ */
+ delay_rescan = sdev->sdev_gendev.power.is_suspended;
+ if (delay_rescan) {
+ scsi_device_put(sdev);
+ break;
+ }
+
spin_unlock_irqrestore(ap->lock, flags);
scsi_rescan_device(&(sdev->sdev_gendev));
scsi_device_put(sdev);
@@ -4623,4 +4639,8 @@ void ata_scsi_dev_rescan(struct work_struct *work)
spin_unlock_irqrestore(ap->lock, flags);
mutex_unlock(&ap->scsi_scan_mutex);
+
+ if (delay_rescan)
+ schedule_delayed_work(&ap->scsi_rescan_task,
+ msecs_to_jiffies(5));
}
diff --git a/drivers/base/regmap/regmap-spi-avmm.c b/drivers/base/regmap/regmap-spi-avmm.c
index 4c2b94b3e30b..6af692844c19 100644
--- a/drivers/base/regmap/regmap-spi-avmm.c
+++ b/drivers/base/regmap/regmap-spi-avmm.c
@@ -660,7 +660,7 @@ static const struct regmap_bus regmap_spi_avmm_bus = {
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
.max_raw_read = SPI_AVMM_VAL_SIZE * MAX_READ_CNT,
- .max_raw_write = SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
+ .max_raw_write = SPI_AVMM_REG_SIZE + SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
.free_context = spi_avmm_bridge_ctx_free,
};
diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index 14491952047f..3b6b4cb400f4 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -2212,6 +2212,7 @@ static void null_destroy_dev(struct nullb *nullb)
struct nullb_device *dev = nullb->dev;
null_del_dev(nullb);
+ null_free_device_storage(dev, false);
null_free_dev(dev);
}
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 2b918e28acaa..b47358da92a2 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -348,63 +348,33 @@ static inline void virtblk_request_done(struct request *req)
blk_mq_end_request(req, status);
}
-static void virtblk_complete_batch(struct io_comp_batch *iob)
-{
- struct request *req;
-
- rq_list_for_each(&iob->req_list, req) {
- virtblk_unmap_data(req, blk_mq_rq_to_pdu(req));
- virtblk_cleanup_cmd(req);
- }
- blk_mq_end_request_batch(iob);
-}
-
-static int virtblk_handle_req(struct virtio_blk_vq *vq,
- struct io_comp_batch *iob)
-{
- struct virtblk_req *vbr;
- int req_done = 0;
- unsigned int len;
-
- while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) {
- struct request *req = blk_mq_rq_from_pdu(vbr);
-
- if (likely(!blk_should_fake_timeout(req->q)) &&
- !blk_mq_complete_request_remote(req) &&
- !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr),
- virtblk_complete_batch))
- virtblk_request_done(req);
- req_done++;
- }
-
- return req_done;
-}
-
static void virtblk_done(struct virtqueue *vq)
{
struct virtio_blk *vblk = vq->vdev->priv;
- struct virtio_blk_vq *vblk_vq = &vblk->vqs[vq->index];
- int req_done = 0;
+ bool req_done = false;
+ int qid = vq->index;
+ struct virtblk_req *vbr;
unsigned long flags;
- DEFINE_IO_COMP_BATCH(iob);
+ unsigned int len;
- spin_lock_irqsave(&vblk_vq->lock, flags);
+ spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
do {
virtqueue_disable_cb(vq);
- req_done += virtblk_handle_req(vblk_vq, &iob);
+ while ((vbr = virtqueue_get_buf(vblk->vqs[qid].vq, &len)) != NULL) {
+ struct request *req = blk_mq_rq_from_pdu(vbr);
+ if (likely(!blk_should_fake_timeout(req->q)))
+ blk_mq_complete_request(req);
+ req_done = true;
+ }
if (unlikely(virtqueue_is_broken(vq)))
break;
} while (!virtqueue_enable_cb(vq));
- if (req_done) {
- if (!rq_list_empty(iob.req_list))
- iob.complete(&iob);
-
- /* In case queue is stopped waiting for more buffers. */
+ /* In case queue is stopped waiting for more buffers. */
+ if (req_done)
blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);
- }
- spin_unlock_irqrestore(&vblk_vq->lock, flags);
+ spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
}
static void virtio_commit_rqs(struct blk_mq_hw_ctx *hctx)
@@ -1283,15 +1253,37 @@ static void virtblk_map_queues(struct blk_mq_tag_set *set)
}
}
+static void virtblk_complete_batch(struct io_comp_batch *iob)
+{
+ struct request *req;
+
+ rq_list_for_each(&iob->req_list, req) {
+ virtblk_unmap_data(req, blk_mq_rq_to_pdu(req));
+ virtblk_cleanup_cmd(req);
+ }
+ blk_mq_end_request_batch(iob);
+}
+
static int virtblk_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
{
struct virtio_blk *vblk = hctx->queue->queuedata;
struct virtio_blk_vq *vq = get_virtio_blk_vq(hctx);
+ struct virtblk_req *vbr;
unsigned long flags;
+ unsigned int len;
int found = 0;
spin_lock_irqsave(&vq->lock, flags);
- found = virtblk_handle_req(vq, iob);
+
+ while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) {
+ struct request *req = blk_mq_rq_from_pdu(vbr);
+
+ found++;
+ if (!blk_mq_complete_request_remote(req) &&
+ !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr),
+ virtblk_complete_batch))
+ virtblk_request_done(req);
+ }
if (found)
blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index e05d2b227de3..55f6ff1e05aa 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -772,7 +772,9 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
wake_up_interruptible(&priv->int_queue);
/* Clear interrupts handled with TPM_EOI */
+ tpm_tis_request_locality(chip, 0);
rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt);
+ tpm_tis_relinquish_locality(chip, 0);
if (rc < 0)
return IRQ_NONE;
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index 740d6e426ee9..1e946c3c1260 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -12,7 +12,6 @@
#include <linux/shmem_fs.h>
#include <linux/slab.h>
#include <linux/udmabuf.h>
-#include <linux/hugetlb.h>
#include <linux/vmalloc.h>
#include <linux/iosys-map.h>
@@ -207,9 +206,7 @@ static long udmabuf_create(struct miscdevice *device,
struct udmabuf *ubuf;
struct dma_buf *buf;
pgoff_t pgoff, pgcnt, pgidx, pgbuf = 0, pglimit;
- struct page *page, *hpage = NULL;
- pgoff_t subpgoff, maxsubpgs;
- struct hstate *hpstate;
+ struct page *page;
int seals, ret = -EINVAL;
u32 i, flags;
@@ -245,7 +242,7 @@ static long udmabuf_create(struct miscdevice *device,
if (!memfd)
goto err;
mapping = memfd->f_mapping;
- if (!shmem_mapping(mapping) && !is_file_hugepages(memfd))
+ if (!shmem_mapping(mapping))
goto err;
seals = memfd_fcntl(memfd, F_GET_SEALS, 0);
if (seals == -EINVAL)
@@ -256,48 +253,16 @@ static long udmabuf_create(struct miscdevice *device,
goto err;
pgoff = list[i].offset >> PAGE_SHIFT;
pgcnt = list[i].size >> PAGE_SHIFT;
- if (is_file_hugepages(memfd)) {
- hpstate = hstate_file(memfd);
- pgoff = list[i].offset >> huge_page_shift(hpstate);
- subpgoff = (list[i].offset &
- ~huge_page_mask(hpstate)) >> PAGE_SHIFT;
- maxsubpgs = huge_page_size(hpstate) >> PAGE_SHIFT;
- }
for (pgidx = 0; pgidx < pgcnt; pgidx++) {
- if (is_file_hugepages(memfd)) {
- if (!hpage) {
- hpage = find_get_page_flags(mapping, pgoff,
- FGP_ACCESSED);
- if (!hpage) {
- ret = -EINVAL;
- goto err;
- }
- }
- page = hpage + subpgoff;
- get_page(page);
- subpgoff++;
- if (subpgoff == maxsubpgs) {
- put_page(hpage);
- hpage = NULL;
- subpgoff = 0;
- pgoff++;
- }
- } else {
- page = shmem_read_mapping_page(mapping,
- pgoff + pgidx);
- if (IS_ERR(page)) {
- ret = PTR_ERR(page);
- goto err;
- }
+ page = shmem_read_mapping_page(mapping, pgoff + pgidx);
+ if (IS_ERR(page)) {
+ ret = PTR_ERR(page);
+ goto err;
}
ubuf->pages[pgbuf++] = page;
}
fput(memfd);
memfd = NULL;
- if (hpage) {
- put_page(hpage);
- hpage = NULL;
- }
}
exp_info.ops = &udmabuf_ops;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index abeff7dc0b58..34b9e7876538 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -361,24 +361,6 @@ static void __init efi_debugfs_init(void)
static inline void efi_debugfs_init(void) {}
#endif
-static void refresh_nv_rng_seed(struct work_struct *work)
-{
- u8 seed[EFI_RANDOM_SEED_SIZE];
-
- get_random_bytes(seed, sizeof(seed));
- efi.set_variable(L"RandomSeed", &LINUX_EFI_RANDOM_SEED_TABLE_GUID,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS, sizeof(seed), seed);
- memzero_explicit(seed, sizeof(seed));
-}
-static int refresh_nv_rng_seed_notification(struct notifier_block *nb, unsigned long action, void *data)
-{
- static DECLARE_WORK(work, refresh_nv_rng_seed);
- schedule_work(&work);
- return NOTIFY_DONE;
-}
-static struct notifier_block refresh_nv_rng_seed_nb = { .notifier_call = refresh_nv_rng_seed_notification };
-
/*
* We register the efi subsystem with the firmware subsystem and the
* efivars subsystem with the efi subsystem, if the system was booted with
@@ -451,9 +433,6 @@ static int __init efisubsys_init(void)
platform_device_register_simple("efi_secret", 0, NULL, 0);
#endif
- if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE))
- execute_with_initialized_rng(&refresh_nv_rng_seed_nb);
-
return 0;
err_remove_group:
diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c
index bc5660f61c57..0f1e1226ebbe 100644
--- a/drivers/gpio/gpio-sifive.c
+++ b/drivers/gpio/gpio-sifive.c
@@ -221,8 +221,12 @@ static int sifive_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
- for (i = 0; i < ngpio; i++)
- chip->irq_number[i] = platform_get_irq(pdev, i);
+ for (i = 0; i < ngpio; i++) {
+ ret = platform_get_irq(pdev, i);
+ if (ret < 0)
+ return ret;
+ chip->irq_number[i] = ret;
+ }
ret = bgpio_init(&chip->gc, dev, 4,
chip->base + SIFIVE_GPIO_INPUT_VAL,
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 4472214fcd43..ce8f71e06eb6 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1716,7 +1716,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gc)
}
/* Remove all IRQ mappings and delete the domain */
- if (gc->irq.domain) {
+ if (!gc->irq.domain_is_allocated_externally && gc->irq.domain) {
unsigned int irq;
for (offset = 0; offset < gc->ngpio; offset++) {
@@ -1762,6 +1762,15 @@ int gpiochip_irqchip_add_domain(struct gpio_chip *gc,
gc->to_irq = gpiochip_to_irq;
gc->irq.domain = domain;
+ gc->irq.domain_is_allocated_externally = true;
+
+ /*
+ * Using barrier() here to prevent compiler from reordering
+ * gc->irq.initialized before adding irqdomain.
+ */
+ barrier();
+
+ gc->irq.initialized = true;
return 0;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 289c261ffe87..2cbd6949804f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -350,6 +350,35 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
return false;
}
+/**
+ * update_planes_and_stream_adapter() - Send planes to be updated in DC
+ *
+ * DC has a generic way to update planes and stream via
+ * dc_update_planes_and_stream function; however, DM might need some
+ * adjustments and preparation before calling it. This function is a wrapper
+ * for the dc_update_planes_and_stream that does any required configuration
+ * before passing control to DC.
+ */
+static inline bool update_planes_and_stream_adapter(struct dc *dc,
+ int update_type,
+ int planes_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update,
+ struct dc_surface_update *array_of_surface_update)
+{
+ /*
+ * Previous frame finished and HW is ready for optimization.
+ */
+ if (update_type == UPDATE_TYPE_FAST)
+ dc_post_update_surfaces_to_stream(dc);
+
+ return dc_update_planes_and_stream(dc,
+ array_of_surface_update,
+ planes_count,
+ stream,
+ stream_update);
+}
+
/**
* dm_pflip_high_irq() - Handle pageflip interrupt
* @interrupt_params: ignored
@@ -2683,10 +2712,13 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
bundle->surface_updates[m].surface->force_full_update =
true;
}
- dc_commit_updates_for_stream(
- dm->dc, bundle->surface_updates,
- dc_state->stream_status->plane_count,
- dc_state->streams[k], &bundle->stream_update, dc_state);
+
+ update_planes_and_stream_adapter(dm->dc,
+ UPDATE_TYPE_FULL,
+ dc_state->stream_status->plane_count,
+ dc_state->streams[k],
+ &bundle->stream_update,
+ bundle->surface_updates);
}
cleanup:
@@ -8181,6 +8213,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
if (acrtc_state->abm_level != dm_old_crtc_state->abm_level)
bundle->stream_update.abm_level = &acrtc_state->abm_level;
+ mutex_lock(&dm->dc_lock);
+ if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
+ acrtc_state->stream->link->psr_settings.psr_allow_active)
+ amdgpu_dm_psr_disable(acrtc_state->stream);
+ mutex_unlock(&dm->dc_lock);
+
/*
* If FreeSync state on the stream has changed then we need to
* re-adjust the min/max bounds now that DC doesn't handle this
@@ -8194,16 +8232,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
}
mutex_lock(&dm->dc_lock);
- if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
- acrtc_state->stream->link->psr_settings.psr_allow_active)
- amdgpu_dm_psr_disable(acrtc_state->stream);
-
- dc_commit_updates_for_stream(dm->dc,
- bundle->surface_updates,
- planes_count,
- acrtc_state->stream,
- &bundle->stream_update,
- dc_state);
+ update_planes_and_stream_adapter(dm->dc,
+ acrtc_state->update_type,
+ planes_count,
+ acrtc_state->stream,
+ &bundle->stream_update,
+ bundle->surface_updates);
/**
* Enable or disable the interrupts on the backend.
@@ -8741,12 +8775,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
mutex_lock(&dm->dc_lock);
- dc_commit_updates_for_stream(dm->dc,
- dummy_updates,
- status->plane_count,
- dm_new_crtc_state->stream,
- &stream_update,
- dc_state);
+ dc_update_planes_and_stream(dm->dc,
+ dummy_updates,
+ status->plane_count,
+ dm_new_crtc_state->stream,
+ &stream_update);
mutex_unlock(&dm->dc_lock);
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index ec784e58da5c..414e585ec7dd 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -1335,7 +1335,7 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
/* Let the runqueue know that there is work to do. */
queue_work(g2d->g2d_workq, &g2d->runqueue_work);
- if (runqueue_node->async)
+ if (req->async)
goto out;
wait_for_completion(&runqueue_node->complete);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 4d56c8c799c5..f5e1adfcaa51 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -469,8 +469,6 @@ static int vidi_remove(struct platform_device *pdev)
if (ctx->raw_edid != (struct edid *)fake_edid_info) {
kfree(ctx->raw_edid);
ctx->raw_edid = NULL;
-
- return -EINVAL;
}
component_del(&pdev->dev, &vidi_component_ops);
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index 261fcbae88d7..75d79c311038 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -459,7 +459,6 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct radeon_device *rdev = dev->dev_private;
struct drm_radeon_gem_set_domain *args = data;
struct drm_gem_object *gobj;
- struct radeon_bo *robj;
int r;
/* for now if someone requests domain CPU -
@@ -472,13 +471,12 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
up_read(&rdev->exclusive_lock);
return -ENOENT;
}
- robj = gem_to_radeon_bo(gobj);
r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
drm_gem_object_put(gobj);
up_read(&rdev->exclusive_lock);
- r = radeon_gem_handle_lockup(robj->rdev, r);
+ r = radeon_gem_handle_lockup(rdev, r);
return r;
}
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index fb538a6c4add..aff4a21a46b6 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -2417,8 +2417,13 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
goto fail_quirks;
}
- if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
+ if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) {
error = hid_hw_open(hdev);
+ if (error) {
+ hid_err(hdev, "hw open failed\n");
+ goto fail_quirks;
+ }
+ }
wacom_set_shared_values(wacom_wac);
devres_close_group(&hdev->dev, wacom);
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index cc23b90cae02..d95e567a190d 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -829,11 +829,22 @@ static void vmbus_wait_for_unload(void)
if (completion_done(&vmbus_connection.unload_event))
goto completed;
- for_each_online_cpu(cpu) {
+ for_each_present_cpu(cpu) {
struct hv_per_cpu_context *hv_cpu
= per_cpu_ptr(hv_context.cpu_context, cpu);
+ /*
+ * In a CoCo VM the synic_message_page is not allocated
+ * in hv_synic_alloc(). Instead it is set/cleared in
+ * hv_synic_enable_regs() and hv_synic_disable_regs()
+ * such that it is set only when the CPU is online. If
+ * not all present CPUs are online, the message page
+ * might be NULL, so skip such CPUs.
+ */
page_addr = hv_cpu->synic_message_page;
+ if (!page_addr)
+ continue;
+
msg = (struct hv_message *)page_addr
+ VMBUS_MESSAGE_SINT;
@@ -867,11 +878,14 @@ static void vmbus_wait_for_unload(void)
* maybe-pending messages on all CPUs to be able to receive new
* messages after we reconnect.
*/
- for_each_online_cpu(cpu) {
+ for_each_present_cpu(cpu) {
struct hv_per_cpu_context *hv_cpu
= per_cpu_ptr(hv_context.cpu_context, cpu);
page_addr = hv_cpu->synic_message_page;
+ if (!page_addr)
+ continue;
+
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
msg->header.message_type = HVMSG_NONE;
}
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index d24dd65b33d4..b50cc83e8315 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1525,7 +1525,7 @@ static int vmbus_bus_init(void)
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online",
hv_synic_init, hv_synic_cleanup);
if (ret < 0)
- goto err_cpuhp;
+ goto err_alloc;
hyperv_cpuhp_online = ret;
ret = vmbus_connect();
@@ -1577,9 +1577,8 @@ static int vmbus_bus_init(void)
err_connect:
cpuhp_remove_state(hyperv_cpuhp_online);
-err_cpuhp:
- hv_synic_free();
err_alloc:
+ hv_synic_free();
if (vmbus_irq == -1) {
hv_remove_vmbus_handler();
} else {
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 050d8c63ad3c..0164d9216330 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -40,6 +40,7 @@
#define DW_IC_CON_BUS_CLEAR_CTRL BIT(11)
#define DW_IC_DATA_CMD_DAT GENMASK(7, 0)
+#define DW_IC_DATA_CMD_FIRST_DATA_BYTE BIT(11)
/*
* Registers offset
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index cec25054bb24..2e079cf20bb5 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -176,6 +176,10 @@ static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
do {
regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
+ if (tmp & DW_IC_DATA_CMD_FIRST_DATA_BYTE)
+ i2c_slave_event(dev->slave,
+ I2C_SLAVE_WRITE_REQUESTED,
+ &val);
val = tmp;
i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED,
&val);
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index a49b14d52a98..ff12018bc206 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -201,8 +201,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
/* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */
static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
{
- u8 prescale, filt, sethold, clkhi, clklo, datavd;
- unsigned int clk_rate, clk_cycle;
+ u8 prescale, filt, sethold, datavd;
+ unsigned int clk_rate, clk_cycle, clkhi, clklo;
enum lpi2c_imx_pincfg pincfg;
unsigned int temp;
diff --git a/drivers/i2c/busses/i2c-mchp-pci1xxxx.c b/drivers/i2c/busses/i2c-mchp-pci1xxxx.c
index b21ffd6df927..5ef136c3ecb1 100644
--- a/drivers/i2c/busses/i2c-mchp-pci1xxxx.c
+++ b/drivers/i2c/busses/i2c-mchp-pci1xxxx.c
@@ -1118,8 +1118,10 @@ static int pci1xxxx_i2c_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(pci1xxxx_i2c_pm_ops, pci1xxxx_i2c_suspend,
pci1xxxx_i2c_resume);
-static void pci1xxxx_i2c_shutdown(struct pci1xxxx_i2c *i2c)
+static void pci1xxxx_i2c_shutdown(void *data)
{
+ struct pci1xxxx_i2c *i2c = data;
+
pci1xxxx_i2c_config_padctrl(i2c, false);
pci1xxxx_i2c_configure_core_reg(i2c, false);
}
@@ -1156,7 +1158,7 @@ static int pci1xxxx_i2c_probe_pci(struct pci_dev *pdev,
init_completion(&i2c->i2c_xfer_done);
pci1xxxx_i2c_init(i2c);
- ret = devm_add_action(dev, (void (*)(void *))pci1xxxx_i2c_shutdown, i2c);
+ ret = devm_add_action(dev, pci1xxxx_i2c_shutdown, i2c);
if (ret)
return ret;
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index 09489380afda..e79f5497948b 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -108,6 +108,27 @@ static const struct dmi_system_id dmi_use_low_level_irq[] = {
{} /* Terminating entry */
};
+/*
+ * Some devices have a wrong entry which points to a GPIO which is
+ * required in another driver, so this driver must not claim it.
+ */
+static const struct dmi_system_id dmi_invalid_acpi_index[] = {
+ {
+ /*
+ * Lenovo Yoga Book X90F / X90L, the PNP0C40 home button entry
+ * points to a GPIO which is not a home button and which is
+ * required by the lenovo-yogabook driver.
+ */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+ },
+ .driver_data = (void *)1l,
+ },
+ {} /* Terminating entry */
+};
+
/*
* Get the Nth GPIO number from the ACPI object.
*/
@@ -137,6 +158,8 @@ soc_button_device_create(struct platform_device *pdev,
struct platform_device *pd;
struct gpio_keys_button *gpio_keys;
struct gpio_keys_platform_data *gpio_keys_pdata;
+ const struct dmi_system_id *dmi_id;
+ int invalid_acpi_index = -1;
int error, gpio, irq;
int n_buttons = 0;
@@ -154,10 +177,17 @@ soc_button_device_create(struct platform_device *pdev,
gpio_keys = (void *)(gpio_keys_pdata + 1);
n_buttons = 0;
+ dmi_id = dmi_first_match(dmi_invalid_acpi_index);
+ if (dmi_id)
+ invalid_acpi_index = (long)dmi_id->driver_data;
+
for (info = button_info; info->name; info++) {
if (info->autorepeat != autorepeat)
continue;
+ if (info->acpi_index == invalid_acpi_index)
+ continue;
+
error = soc_button_lookup_gpio(&pdev->dev, info->acpi_index, &gpio, &irq);
if (error || irq < 0) {
/*
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index cd0e3fb78c3f..e9eac86cddbd 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2069,10 +2069,6 @@ static struct protection_domain *protection_domain_alloc(unsigned int type)
int mode = DEFAULT_PGTABLE_LEVEL;
int ret;
- domain = kzalloc(sizeof(*domain), GFP_KERNEL);
- if (!domain)
- return NULL;
-
/*
* Force IOMMU v1 page table when iommu=pt and
* when allocating domain for pass-through devices.
@@ -2088,6 +2084,10 @@ static struct protection_domain *protection_domain_alloc(unsigned int type)
return NULL;
}
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ if (!domain)
+ return NULL;
+
switch (pgtable) {
case AMD_IOMMU_V1:
ret = protection_domain_init_v1(domain, mode);
diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
index 4f5ab3cae8a7..b1512f9c5895 100644
--- a/drivers/media/cec/core/cec-adap.c
+++ b/drivers/media/cec/core/cec-adap.c
@@ -1090,7 +1090,8 @@ void cec_received_msg_ts(struct cec_adapter *adap,
mutex_lock(&adap->lock);
dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg);
- adap->last_initiator = 0xff;
+ if (!adap->transmit_in_progress)
+ adap->last_initiator = 0xff;
/* Check if this message was for us (directed or broadcast). */
if (!cec_msg_is_broadcast(msg))
@@ -1582,7 +1583,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
*
* This function is called with adap->lock held.
*/
-static int cec_adap_enable(struct cec_adapter *adap)
+int cec_adap_enable(struct cec_adapter *adap)
{
bool enable;
int ret = 0;
@@ -1592,6 +1593,9 @@ static int cec_adap_enable(struct cec_adapter *adap)
if (adap->needs_hpd)
enable = enable && adap->phys_addr != CEC_PHYS_ADDR_INVALID;
+ if (adap->devnode.unregistered)
+ enable = false;
+
if (enable == adap->is_enabled)
return 0;
diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c
index af358e901b5f..7e153c5cad04 100644
--- a/drivers/media/cec/core/cec-core.c
+++ b/drivers/media/cec/core/cec-core.c
@@ -191,6 +191,8 @@ static void cec_devnode_unregister(struct cec_adapter *adap)
mutex_lock(&adap->lock);
__cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
__cec_s_log_addrs(adap, NULL, false);
+ // Disable the adapter (since adap->devnode.unregistered is true)
+ cec_adap_enable(adap);
mutex_unlock(&adap->lock);
cdev_device_del(&devnode->cdev, &devnode->dev);
diff --git a/drivers/media/cec/core/cec-priv.h b/drivers/media/cec/core/cec-priv.h
index b78df931aa74..ed1f8c67626b 100644
--- a/drivers/media/cec/core/cec-priv.h
+++ b/drivers/media/cec/core/cec-priv.h
@@ -47,6 +47,7 @@ int cec_monitor_pin_cnt_inc(struct cec_adapter *adap);
void cec_monitor_pin_cnt_dec(struct cec_adapter *adap);
int cec_adap_status(struct seq_file *file, void *priv);
int cec_thread_func(void *_adap);
+int cec_adap_enable(struct cec_adapter *adap);
void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
int __cec_s_log_addrs(struct cec_adapter *adap,
struct cec_log_addrs *log_addrs, bool block);
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 8648f7e63ca1..eea208856ce0 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -1403,8 +1403,8 @@ static int bcm2835_probe(struct platform_device *pdev)
host->max_clk = clk_get_rate(clk);
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0) {
- ret = -EINVAL;
+ if (host->irq < 0) {
+ ret = host->irq;
goto err;
}
diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
index 39c6707fdfdb..9af6b0902efe 100644
--- a/drivers/mmc/host/litex_mmc.c
+++ b/drivers/mmc/host/litex_mmc.c
@@ -649,6 +649,7 @@ static struct platform_driver litex_mmc_driver = {
.driver = {
.name = "litex-mmc",
.of_match_table = litex_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};
module_platform_driver(litex_mmc_driver);
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 2b963a81c2ad..2eda0e496225 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -1006,11 +1006,8 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
if (data && !cmd->error)
data->bytes_xfered = data->blksz * data->blocks;
- if (meson_mmc_bounce_buf_read(data) ||
- meson_mmc_get_next_command(cmd))
- ret = IRQ_WAKE_THREAD;
- else
- ret = IRQ_HANDLED;
+
+ return IRQ_WAKE_THREAD;
}
out:
@@ -1022,9 +1019,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
writel(start, host->regs + SD_EMMC_START);
}
- if (ret == IRQ_HANDLED)
- meson_mmc_request_done(host->mmc, cmd->mrq);
-
return ret;
}
@@ -1208,8 +1202,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
return PTR_ERR(host->regs);
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0)
- return -EINVAL;
+ if (host->irq < 0)
+ return host->irq;
cd_irq = platform_get_irq_optional(pdev, 1);
mmc_gpio_set_cd_irq(mmc, cd_irq);
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index b9e5dfe74e5c..1c326e4307f4 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1735,7 +1735,8 @@ static void mmci_set_max_busy_timeout(struct mmc_host *mmc)
return;
if (host->variant->busy_timeout && mmc->actual_clock)
- max_busy_timeout = ~0UL / (mmc->actual_clock / MSEC_PER_SEC);
+ max_busy_timeout = U32_MAX / DIV_ROUND_UP(mmc->actual_clock,
+ MSEC_PER_SEC);
mmc->max_busy_timeout = max_busy_timeout;
}
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index edade0e54a0c..9785ec91654f 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -2680,7 +2680,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
- ret = -EINVAL;
+ ret = host->irq;
goto host_free;
}
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 629efbe639c4..b4f6a0a2fcb5 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -704,7 +704,7 @@ static int mvsd_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0)
- return -ENXIO;
+ return irq;
mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
if (!mmc) {
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 57d39283924d..cc2213ea324f 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1343,7 +1343,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0)
- return -ENXIO;
+ return irq;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
host->virt_base = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4bd744755205..2db3a16e63c4 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1791,9 +1791,11 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (res == NULL || irq < 0)
+ if (!res)
return -ENXIO;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c
index 3dc143b03939..679b8b0b310e 100644
--- a/drivers/mmc/host/owl-mmc.c
+++ b/drivers/mmc/host/owl-mmc.c
@@ -638,7 +638,7 @@ static int owl_mmc_probe(struct platform_device *pdev)
owl_host->irq = platform_get_irq(pdev, 0);
if (owl_host->irq < 0) {
- ret = -EINVAL;
+ ret = owl_host->irq;
goto err_release_channel;
}
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 8f0e639236b1..edf2e6c14dc6 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -829,7 +829,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
host->ops = &sdhci_acpi_ops_dflt;
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
- err = -EINVAL;
+ err = host->irq;
goto err_free;
}
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 8ac81d57a3df..1877d583fe8c 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2479,6 +2479,9 @@ static inline void sdhci_msm_get_of_property(struct platform_device *pdev,
msm_host->ddr_config = DDR_CONFIG_POR_VAL;
of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config);
+
+ if (of_device_is_compatible(node, "qcom,msm8916-sdhci"))
+ host->quirks2 |= SDHCI_QUIRK2_BROKEN_64_BIT_DMA;
}
static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host)
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index d463e2fd5b1a..c79035727b20 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -65,8 +65,8 @@ static int sdhci_probe(struct platform_device *pdev)
host->hw_name = "sdhci";
host->ops = &sdhci_pltfm_ops;
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0) {
- ret = -EINVAL;
+ if (host->irq < 0) {
+ ret = host->irq;
goto err_host;
}
host->quirks = SDHCI_QUIRK_BROKEN_ADMA;
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 0fd4c9d644dd..5cf53348372a 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1400,7 +1400,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
irq[0] = platform_get_irq(pdev, 0);
irq[1] = platform_get_irq_optional(pdev, 1);
if (irq[0] < 0)
- return -ENXIO;
+ return irq[0];
reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg))
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 3db9f32d6a7b..69dcb8805e05 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -1350,8 +1350,8 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
return ret;
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0) {
- ret = -EINVAL;
+ if (host->irq < 0) {
+ ret = host->irq;
goto error_disable_mmc;
}
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c
index 99515be6e5e5..2032e4e1ee68 100644
--- a/drivers/mmc/host/usdhi6rol0.c
+++ b/drivers/mmc/host/usdhi6rol0.c
@@ -1757,8 +1757,10 @@ static int usdhi6_probe(struct platform_device *pdev)
irq_cd = platform_get_irq_byname(pdev, "card detect");
irq_sd = platform_get_irq_byname(pdev, "data");
irq_sdio = platform_get_irq_byname(pdev, "SDIO");
- if (irq_sd < 0 || irq_sdio < 0)
- return -ENODEV;
+ if (irq_sd < 0)
+ return irq_sd;
+ if (irq_sdio < 0)
+ return irq_sdio;
mmc = mmc_alloc_host(sizeof(struct usdhi6_host), dev);
if (!mmc)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 0c81f5830b90..566545b6554b 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -419,6 +419,20 @@ static void mt7530_pll_setup(struct mt7530_priv *priv)
core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
}
+/* If port 6 is available as a CPU port, always prefer that as the default,
+ * otherwise don't care.
+ */
+static struct dsa_port *
+mt753x_preferred_default_local_cpu_port(struct dsa_switch *ds)
+{
+ struct dsa_port *cpu_dp = dsa_to_port(ds, 6);
+
+ if (dsa_port_is_cpu(cpu_dp))
+ return cpu_dp;
+
+ return NULL;
+}
+
/* Setup port 6 interface mode and TRGMII TX circuit */
static int
mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
@@ -991,6 +1005,18 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
mutex_unlock(&priv->reg_mutex);
}
+static void
+mt753x_trap_frames(struct mt7530_priv *priv)
+{
+ /* Trap BPDUs to the CPU port(s) */
+ mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
+ MT753X_BPDU_CPU_ONLY);
+
+ /* Trap LLDP frames with :0E MAC DA to the CPU port(s) */
+ mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_PORT_FW_MASK,
+ MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY));
+}
+
static int
mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
{
@@ -1013,7 +1039,7 @@ mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
UNU_FFP(BIT(port)));
/* Set CPU port number */
- if (priv->id == ID_MT7621)
+ if (priv->id == ID_MT7530 || priv->id == ID_MT7621)
mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
/* CPU port gets connected to all user ports of
@@ -2214,6 +2240,8 @@ mt7530_setup(struct dsa_switch *ds)
priv->p6_interface = PHY_INTERFACE_MODE_NA;
+ mt753x_trap_frames(priv);
+
/* Enable and reset MIB counters */
mt7530_mib_reset(ds);
@@ -2320,8 +2348,8 @@ mt7531_setup_common(struct dsa_switch *ds)
BIT(cpu_dp->index));
break;
}
- mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
- MT753X_BPDU_CPU_ONLY);
+
+ mt753x_trap_frames(priv);
/* Enable and reset MIB counters */
mt7530_mib_reset(ds);
@@ -3177,6 +3205,7 @@ static int mt753x_set_mac_eee(struct dsa_switch *ds, int port,
static const struct dsa_switch_ops mt7530_switch_ops = {
.get_tag_protocol = mtk_get_tag_protocol,
.setup = mt753x_setup,
+ .preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port,
.get_strings = mt7530_get_strings,
.get_ethtool_stats = mt7530_get_ethtool_stats,
.get_sset_count = mt7530_get_sset_count,
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index 6b2fc6290ea8..31c0f7156b69 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -65,6 +65,11 @@ enum mt753x_id {
#define MT753X_BPC 0x24
#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0)
+/* Register for :03 and :0E MAC DA frame control */
+#define MT753X_RGAC2 0x2c
+#define MT753X_R0E_PORT_FW_MASK GENMASK(18, 16)
+#define MT753X_R0E_PORT_FW(x) FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x)
+
enum mt753x_bpdu_port_fw {
MT753X_BPDU_FOLLOW_MFC,
MT753X_BPDU_CPU_EXCLUDE = 4,
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 46fe3d74e2e9..7236c4f70cf5 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1136,8 +1136,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
VLAN_ETH_HLEN : ETH_HLEN;
if (skb->len <= 60 &&
- (lancer_chip(adapter) || skb_vlan_tag_present(skb)) &&
- is_ipv4_pkt(skb)) {
+ (lancer_chip(adapter) || BE3_chip(adapter) ||
+ skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
ip = (struct iphdr *)ip_hdr(skb);
pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
index ee104cf04392..438c3bfae762 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
@@ -1403,9 +1403,13 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
}
case DR_ACTION_TYP_TNL_L3_TO_L2:
{
- u8 hw_actions[ACTION_CACHE_LINE_SIZE] = {};
+ u8 *hw_actions;
int ret;
+ hw_actions = kzalloc(ACTION_CACHE_LINE_SIZE, GFP_KERNEL);
+ if (!hw_actions)
+ return -ENOMEM;
+
ret = mlx5dr_ste_set_action_decap_l3_list(dmn->ste_ctx,
data, data_sz,
hw_actions,
@@ -1413,6 +1417,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
&action->rewrite->num_of_actions);
if (ret) {
mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n");
+ kfree(hw_actions);
return ret;
}
@@ -1420,6 +1425,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
DR_CHUNK_SIZE_8);
if (!action->rewrite->chunk) {
mlx5dr_dbg(dmn, "Failed allocating modify header chunk\n");
+ kfree(hw_actions);
return -ENOMEM;
}
@@ -1433,6 +1439,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
if (ret) {
mlx5dr_dbg(dmn, "Writing decap l3 actions to ICM failed\n");
mlx5dr_icm_free_chunk(action->rewrite->chunk);
+ kfree(hw_actions);
return ret;
}
return 0;
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index c865a4be05ee..4a1b94e5a8ea 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -582,8 +582,7 @@ qcaspi_spi_thread(void *data)
while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE);
if ((qca->intr_req == qca->intr_svc) &&
- (qca->txr.skb[qca->txr.head] == NULL) &&
- (qca->sync == QCASPI_SYNC_READY))
+ !qca->txr.skb[qca->txr.head])
schedule();
set_current_state(TASK_RUNNING);
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index d30459dbfe8f..b63e47af6365 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -2950,7 +2950,7 @@ static u32 efx_ef10_extract_event_ts(efx_qword_t *event)
return tstamp;
}
-static void
+static int
efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
{
struct efx_nic *efx = channel->efx;
@@ -2958,13 +2958,14 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
unsigned int tx_ev_desc_ptr;
unsigned int tx_ev_q_label;
unsigned int tx_ev_type;
+ int work_done;
u64 ts_part;
if (unlikely(READ_ONCE(efx->reset_pending)))
- return;
+ return 0;
if (unlikely(EFX_QWORD_FIELD(*event, ESF_DZ_TX_DROP_EVENT)))
- return;
+ return 0;
/* Get the transmit queue */
tx_ev_q_label = EFX_QWORD_FIELD(*event, ESF_DZ_TX_QLABEL);
@@ -2973,8 +2974,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
if (!tx_queue->timestamping) {
/* Transmit completion */
tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, ESF_DZ_TX_DESCR_INDX);
- efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
- return;
+ return efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
}
/* Transmit timestamps are only available for 8XXX series. They result
@@ -3000,6 +3000,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
* fields in the event.
*/
tx_ev_type = EFX_QWORD_FIELD(*event, ESF_EZ_TX_SOFT1);
+ work_done = 0;
switch (tx_ev_type) {
case TX_TIMESTAMP_EVENT_TX_EV_COMPLETION:
@@ -3016,6 +3017,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
tx_queue->completed_timestamp_major = ts_part;
efx_xmit_done_single(tx_queue);
+ work_done = 1;
break;
default:
@@ -3026,6 +3028,8 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
EFX_QWORD_VAL(*event));
break;
}
+
+ return work_done;
}
static void
@@ -3081,13 +3085,16 @@ static void efx_ef10_handle_driver_generated_event(struct efx_channel *channel,
}
}
+#define EFX_NAPI_MAX_TX 512
+
static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
{
struct efx_nic *efx = channel->efx;
efx_qword_t event, *p_event;
unsigned int read_ptr;
- int ev_code;
+ int spent_tx = 0;
int spent = 0;
+ int ev_code;
if (quota <= 0)
return spent;
@@ -3126,7 +3133,11 @@ static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
}
break;
case ESE_DZ_EV_CODE_TX_EV:
- efx_ef10_handle_tx_event(channel, &event);
+ spent_tx += efx_ef10_handle_tx_event(channel, &event);
+ if (spent_tx >= EFX_NAPI_MAX_TX) {
+ spent = quota;
+ goto out;
+ }
break;
case ESE_DZ_EV_CODE_DRIVER_EV:
efx_ef10_handle_driver_event(channel, &event);
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 4dc643b0d2db..7adde9639c8a 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -253,6 +253,8 @@ static void ef100_ev_read_ack(struct efx_channel *channel)
efx_reg(channel->efx, ER_GZ_EVQ_INT_PRIME));
}
+#define EFX_NAPI_MAX_TX 512
+
static int ef100_ev_process(struct efx_channel *channel, int quota)
{
struct efx_nic *efx = channel->efx;
@@ -260,6 +262,7 @@ static int ef100_ev_process(struct efx_channel *channel, int quota)
bool evq_phase, old_evq_phase;
unsigned int read_ptr;
efx_qword_t *p_event;
+ int spent_tx = 0;
int spent = 0;
bool ev_phase;
int ev_type;
@@ -295,7 +298,9 @@ static int ef100_ev_process(struct efx_channel *channel, int quota)
efx_mcdi_process_event(channel, p_event);
break;
case ESE_GZ_EF100_EV_TX_COMPLETION:
- ef100_ev_tx(channel, p_event);
+ spent_tx += ef100_ev_tx(channel, p_event);
+ if (spent_tx >= EFX_NAPI_MAX_TX)
+ spent = quota;
break;
case ESE_GZ_EF100_EV_DRIVER:
netif_info(efx, drv, efx->net_dev,
diff --git a/drivers/net/ethernet/sfc/ef100_tx.c b/drivers/net/ethernet/sfc/ef100_tx.c
index 29ffaf35559d..849e5555bd12 100644
--- a/drivers/net/ethernet/sfc/ef100_tx.c
+++ b/drivers/net/ethernet/sfc/ef100_tx.c
@@ -346,7 +346,7 @@ void ef100_tx_write(struct efx_tx_queue *tx_queue)
ef100_tx_push_buffers(tx_queue);
}
-void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event)
+int ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event)
{
unsigned int tx_done =
EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_TXCMPL_NUM_DESC);
@@ -357,7 +357,7 @@ void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event)
unsigned int tx_index = (tx_queue->read_count + tx_done - 1) &
tx_queue->ptr_mask;
- efx_xmit_done(tx_queue, tx_index);
+ return efx_xmit_done(tx_queue, tx_index);
}
/* Add a socket buffer to a TX queue
diff --git a/drivers/net/ethernet/sfc/ef100_tx.h b/drivers/net/ethernet/sfc/ef100_tx.h
index e9e11540fcde..d9a0819c5a72 100644
--- a/drivers/net/ethernet/sfc/ef100_tx.h
+++ b/drivers/net/ethernet/sfc/ef100_tx.h
@@ -20,7 +20,7 @@ void ef100_tx_init(struct efx_tx_queue *tx_queue);
void ef100_tx_write(struct efx_tx_queue *tx_queue);
unsigned int ef100_tx_max_skb_descs(struct efx_nic *efx);
-void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event);
+int ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event);
netdev_tx_t ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
int __ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c
index 67e789b96c43..755aa92bf823 100644
--- a/drivers/net/ethernet/sfc/tx_common.c
+++ b/drivers/net/ethernet/sfc/tx_common.c
@@ -249,7 +249,7 @@ void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue)
}
}
-void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
+int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
{
unsigned int fill_level, pkts_compl = 0, bytes_compl = 0;
unsigned int efv_pkts_compl = 0;
@@ -279,6 +279,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
}
efx_xmit_done_check_empty(tx_queue);
+
+ return pkts_compl + efv_pkts_compl;
}
/* Remove buffers put into a tx_queue for the current packet.
diff --git a/drivers/net/ethernet/sfc/tx_common.h b/drivers/net/ethernet/sfc/tx_common.h
index d87aecbc7bf1..1e9f42938aac 100644
--- a/drivers/net/ethernet/sfc/tx_common.h
+++ b/drivers/net/ethernet/sfc/tx_common.h
@@ -28,7 +28,7 @@ static inline bool efx_tx_buffer_in_use(struct efx_tx_buffer *buffer)
}
void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue);
-void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
+int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
unsigned int insert_count);
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 8445c2189d11..31cba9aa7636 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -685,7 +685,7 @@ static int hwsim_del_edge_nl(struct sk_buff *msg, struct genl_info *info)
static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
{
struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1];
- struct hwsim_edge_info *einfo;
+ struct hwsim_edge_info *einfo, *einfo_old;
struct hwsim_phy *phy_v0;
struct hwsim_edge *e;
u32 v0, v1;
@@ -723,8 +723,10 @@ static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
list_for_each_entry_rcu(e, &phy_v0->edges, list) {
if (e->endpoint->idx == v1) {
einfo->lqi = lqi;
- rcu_assign_pointer(e->info, einfo);
+ einfo_old = rcu_replace_pointer(e->info, einfo,
+ lockdep_is_held(&hwsim_phys_lock));
rcu_read_unlock();
+ kfree_rcu(einfo_old, rcu);
mutex_unlock(&hwsim_phys_lock);
return 0;
}
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 9f7ff8820048..76fe7e7d9ac9 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -905,7 +905,7 @@ static int dp83867_phy_reset(struct phy_device *phydev)
{
int err;
- err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART);
+ err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET);
if (err < 0)
return err;
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 389f33a12534..8b3618d3da4a 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -1287,7 +1287,7 @@ EXPORT_SYMBOL_GPL(mdiobus_modify_changed);
* @mask: bit mask of bits to clear
* @set: bit mask of bits to set
*/
-int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr,
+int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad,
u32 regnum, u16 mask, u16 set)
{
int err;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 25b2d41de4c1..3a6a7d62e883 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -547,6 +547,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
+ IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
+ IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_name),
diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c
index 85bf8d586c70..0f6befe8be1e 100644
--- a/drivers/nfc/nfcsim.c
+++ b/drivers/nfc/nfcsim.c
@@ -336,10 +336,6 @@ static struct dentry *nfcsim_debugfs_root;
static void nfcsim_debugfs_init(void)
{
nfcsim_debugfs_root = debugfs_create_dir("nfcsim", NULL);
-
- if (!nfcsim_debugfs_root)
- pr_err("Could not create debugfs entry\n");
-
}
static void nfcsim_debugfs_remove(void)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index c015393beeee..8a632bf7f5a8 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -397,7 +397,16 @@ void nvme_complete_rq(struct request *req)
trace_nvme_complete_rq(req);
nvme_cleanup_cmd(req);
- if (ctrl->kas)
+ /*
+ * Completions of long-running commands should not be able to
+ * defer sending of periodic keep alives, since the controller
+ * may have completed processing such commands a long time ago
+ * (arbitrarily close to command submission time).
+ * req->deadline - req->timeout is the command submission time
+ * in jiffies.
+ */
+ if (ctrl->kas &&
+ req->deadline - req->timeout >= ctrl->ka_last_check_time)
ctrl->comp_seen = true;
switch (nvme_decide_disposition(req)) {
@@ -1115,7 +1124,7 @@ u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode)
}
EXPORT_SYMBOL_NS_GPL(nvme_passthru_start, NVME_TARGET_PASSTHRU);
-void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects,
+void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
struct nvme_command *cmd, int status)
{
if (effects & NVME_CMD_EFFECTS_CSE_MASK) {
@@ -1132,6 +1141,8 @@ void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects,
nvme_queue_scan(ctrl);
flush_work(&ctrl->scan_work);
}
+ if (ns)
+ return;
switch (cmd->common.opcode) {
case nvme_admin_set_features:
@@ -1161,9 +1172,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_passthru_end, NVME_TARGET_PASSTHRU);
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+ unsigned long delay = ctrl->kato * HZ / 2;
+
+ /*
+ * When using Traffic Based Keep Alive, we need to run
+ * nvme_keep_alive_work at twice the normal frequency, as one
+ * command completion can postpone sending a keep alive command
+ * by up to twice the delay between runs.
+ */
+ if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+ delay /= 2;
+ return delay;
+}
+
static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
{
- queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work,
+ nvme_keep_alive_work_period(ctrl));
}
static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
@@ -1172,6 +1199,20 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
struct nvme_ctrl *ctrl = rq->end_io_data;
unsigned long flags;
bool startka = false;
+ unsigned long rtt = jiffies - (rq->deadline - rq->timeout);
+ unsigned long delay = nvme_keep_alive_work_period(ctrl);
+
+ /*
+ * Subtract off the keepalive RTT so nvme_keep_alive_work runs
+ * at the desired frequency.
+ */
+ if (rtt <= delay) {
+ delay -= rtt;
+ } else {
+ dev_warn(ctrl->device, "long keepalive RTT (%u ms)\n",
+ jiffies_to_msecs(rtt));
+ delay = 0;
+ }
blk_mq_free_request(rq);
@@ -1182,6 +1223,7 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
return RQ_END_IO_NONE;
}
+ ctrl->ka_last_check_time = jiffies;
ctrl->comp_seen = false;
spin_lock_irqsave(&ctrl->lock, flags);
if (ctrl->state == NVME_CTRL_LIVE ||
@@ -1189,7 +1231,7 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
startka = true;
spin_unlock_irqrestore(&ctrl->lock, flags);
if (startka)
- nvme_queue_keep_alive_work(ctrl);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
return RQ_END_IO_NONE;
}
@@ -1200,6 +1242,8 @@ static void nvme_keep_alive_work(struct work_struct *work)
bool comp_seen = ctrl->comp_seen;
struct request *rq;
+ ctrl->ka_last_check_time = jiffies;
+
if ((ctrl->ctratt & NVME_CTRL_ATTR_TBKAS) && comp_seen) {
dev_dbg(ctrl->device,
"reschedule traffic based keep-alive timer\n");
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index d24ea2e05156..0264ec74a436 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -254,7 +254,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
blk_mq_free_request(req);
if (effects)
- nvme_passthru_end(ctrl, effects, cmd, ret);
+ nvme_passthru_end(ctrl, ns, effects, cmd, ret);
return ret;
}
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index a2d4f59e0535..8657811f8b88 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -328,6 +328,7 @@ struct nvme_ctrl {
struct delayed_work ka_work;
struct delayed_work failfast_work;
struct nvme_command ka_cmd;
+ unsigned long ka_last_check_time;
struct work_struct fw_act_work;
unsigned long events;
@@ -1077,7 +1078,7 @@ u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
u8 opcode);
u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode);
int nvme_execute_rq(struct request *rq, bool at_head);
-void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects,
+void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
struct nvme_command *cmd, int status);
struct nvme_ctrl *nvme_ctrl_from_file(struct file *file);
struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid);
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 511c980d538d..71a9c1cc57f5 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -243,7 +243,7 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
blk_mq_free_request(rq);
if (effects)
- nvme_passthru_end(ctrl, effects, req->cmd, status);
+ nvme_passthru_end(ctrl, ns, effects, req->cmd, status);
}
static enum rq_end_io_ret nvmet_passthru_req_done(struct request *rq,
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index f33370b75628..e961424ed7d9 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -489,7 +489,10 @@ struct hv_pcibus_device {
struct fwnode_handle *fwnode;
/* Protocol version negotiated with the host */
enum pci_protocol_version_t protocol_version;
+
+ struct mutex state_lock;
enum hv_pcibus_state state;
+
struct hv_device *hdev;
resource_size_t low_mmio_space;
resource_size_t high_mmio_space;
@@ -553,19 +556,10 @@ struct hv_dr_state {
struct hv_pcidev_description func[];
};
-enum hv_pcichild_state {
- hv_pcichild_init = 0,
- hv_pcichild_requirements,
- hv_pcichild_resourced,
- hv_pcichild_ejecting,
- hv_pcichild_maximum
-};
-
struct hv_pci_dev {
/* List protected by pci_rescan_remove_lock */
struct list_head list_entry;
refcount_t refs;
- enum hv_pcichild_state state;
struct pci_slot *pci_slot;
struct hv_pcidev_description desc;
bool reported_missing;
@@ -643,6 +637,11 @@ static void hv_arch_irq_unmask(struct irq_data *data)
pbus = pdev->bus;
hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
int_desc = data->chip_data;
+ if (!int_desc) {
+ dev_warn(&hbus->hdev->device, "%s() can not unmask irq %u\n",
+ __func__, data->irq);
+ return;
+ }
spin_lock_irqsave(&hbus->retarget_msi_interrupt_lock, flags);
@@ -1911,12 +1910,6 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
hv_pci_onchannelcallback(hbus);
spin_unlock_irqrestore(&channel->sched_lock, flags);
- if (hpdev->state == hv_pcichild_ejecting) {
- dev_err_once(&hbus->hdev->device,
- "the device is being ejected\n");
- goto enable_tasklet;
- }
-
udelay(100);
}
@@ -2522,6 +2515,8 @@ static void pci_devices_present_work(struct work_struct *work)
if (!dr)
return;
+ mutex_lock(&hbus->state_lock);
+
/* First, mark all existing children as reported missing. */
spin_lock_irqsave(&hbus->device_list_lock, flags);
list_for_each_entry(hpdev, &hbus->children, list_entry) {
@@ -2603,6 +2598,8 @@ static void pci_devices_present_work(struct work_struct *work)
break;
}
+ mutex_unlock(&hbus->state_lock);
+
kfree(dr);
}
@@ -2751,7 +2748,7 @@ static void hv_eject_device_work(struct work_struct *work)
hpdev = container_of(work, struct hv_pci_dev, wrk);
hbus = hpdev->hbus;
- WARN_ON(hpdev->state != hv_pcichild_ejecting);
+ mutex_lock(&hbus->state_lock);
/*
* Ejection can come before or after the PCI bus has been set up, so
@@ -2789,6 +2786,8 @@ static void hv_eject_device_work(struct work_struct *work)
put_pcichild(hpdev);
put_pcichild(hpdev);
/* hpdev has been freed. Do not use it any more. */
+
+ mutex_unlock(&hbus->state_lock);
}
/**
@@ -2809,7 +2808,6 @@ static void hv_pci_eject_device(struct hv_pci_dev *hpdev)
return;
}
- hpdev->state = hv_pcichild_ejecting;
get_pcichild(hpdev);
INIT_WORK(&hpdev->wrk, hv_eject_device_work);
queue_work(hbus->wq, &hpdev->wrk);
@@ -3238,8 +3236,10 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
struct pci_bus_d0_entry *d0_entry;
struct hv_pci_compl comp_pkt;
struct pci_packet *pkt;
+ bool retry = true;
int ret;
+enter_d0_retry:
/*
* Tell the host that the bus is ready to use, and moved into the
* powered-on state. This includes telling the host which region
@@ -3266,6 +3266,38 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
if (ret)
goto exit;
+ /*
+ * In certain case (Kdump) the pci device of interest was
+ * not cleanly shut down and resource is still held on host
+ * side, the host could return invalid device status.
+ * We need to explicitly request host to release the resource
+ * and try to enter D0 again.
+ */
+ if (comp_pkt.completion_status < 0 && retry) {
+ retry = false;
+
+ dev_err(&hdev->device, "Retrying D0 Entry\n");
+
+ /*
+ * Hv_pci_bus_exit() calls hv_send_resource_released()
+ * to free up resources of its child devices.
+ * In the kdump kernel we need to set the
+ * wslot_res_allocated to 255 so it scans all child
+ * devices to release resources allocated in the
+ * normal kernel before panic happened.
+ */
+ hbus->wslot_res_allocated = 255;
+
+ ret = hv_pci_bus_exit(hdev, true);
+
+ if (ret == 0) {
+ kfree(pkt);
+ goto enter_d0_retry;
+ }
+ dev_err(&hdev->device,
+ "Retrying D0 failed with ret %d\n", ret);
+ }
+
if (comp_pkt.completion_status < 0) {
dev_err(&hdev->device,
"PCI Pass-through VSP failed D0 Entry with status %x\n",
@@ -3308,6 +3340,24 @@ static int hv_pci_query_relations(struct hv_device *hdev)
if (!ret)
ret = wait_for_response(hdev, &comp);
+ /*
+ * In the case of fast device addition/removal, it's possible that
+ * vmbus_sendpacket() or wait_for_response() returns -ENODEV but we
+ * already got a PCI_BUS_RELATIONS* message from the host and the
+ * channel callback already scheduled a work to hbus->wq, which can be
+ * running pci_devices_present_work() -> survey_child_resources() ->
+ * complete(&hbus->survey_event), even after hv_pci_query_relations()
+ * exits and the stack variable 'comp' is no longer valid; as a result,
+ * a hang or a page fault may happen when the complete() calls
+ * raw_spin_lock_irqsave(). Flush hbus->wq before we exit from
+ * hv_pci_query_relations() to avoid the issues. Note: if 'ret' is
+ * -ENODEV, there can't be any more work item scheduled to hbus->wq
+ * after the flush_workqueue(): see vmbus_onoffer_rescind() ->
+ * vmbus_reset_channel_cb(), vmbus_rescind_cleanup() ->
+ * channel->rescind = true.
+ */
+ flush_workqueue(hbus->wq);
+
return ret;
}
@@ -3493,7 +3543,6 @@ static int hv_pci_probe(struct hv_device *hdev,
struct hv_pcibus_device *hbus;
u16 dom_req, dom;
char *name;
- bool enter_d0_retry = true;
int ret;
/*
@@ -3529,6 +3578,7 @@ static int hv_pci_probe(struct hv_device *hdev,
return -ENOMEM;
hbus->bridge = bridge;
+ mutex_init(&hbus->state_lock);
hbus->state = hv_pcibus_init;
hbus->wslot_res_allocated = -1;
@@ -3633,49 +3683,15 @@ static int hv_pci_probe(struct hv_device *hdev,
if (ret)
goto free_fwnode;
-retry:
ret = hv_pci_query_relations(hdev);
if (ret)
goto free_irq_domain;
- ret = hv_pci_enter_d0(hdev);
- /*
- * In certain case (Kdump) the pci device of interest was
- * not cleanly shut down and resource is still held on host
- * side, the host could return invalid device status.
- * We need to explicitly request host to release the resource
- * and try to enter D0 again.
- * Since the hv_pci_bus_exit() call releases structures
- * of all its child devices, we need to start the retry from
- * hv_pci_query_relations() call, requesting host to send
- * the synchronous child device relations message before this
- * information is needed in hv_send_resources_allocated()
- * call later.
- */
- if (ret == -EPROTO && enter_d0_retry) {
- enter_d0_retry = false;
-
- dev_err(&hdev->device, "Retrying D0 Entry\n");
-
- /*
- * Hv_pci_bus_exit() calls hv_send_resources_released()
- * to free up resources of its child devices.
- * In the kdump kernel we need to set the
- * wslot_res_allocated to 255 so it scans all child
- * devices to release resources allocated in the
- * normal kernel before panic happened.
- */
- hbus->wslot_res_allocated = 255;
- ret = hv_pci_bus_exit(hdev, true);
-
- if (ret == 0)
- goto retry;
+ mutex_lock(&hbus->state_lock);
- dev_err(&hdev->device,
- "Retrying D0 failed with ret %d\n", ret);
- }
+ ret = hv_pci_enter_d0(hdev);
if (ret)
- goto free_irq_domain;
+ goto release_state_lock;
ret = hv_pci_allocate_bridge_windows(hbus);
if (ret)
@@ -3693,12 +3709,15 @@ static int hv_pci_probe(struct hv_device *hdev,
if (ret)
goto free_windows;
+ mutex_unlock(&hbus->state_lock);
return 0;
free_windows:
hv_pci_free_bridge_windows(hbus);
exit_d0:
(void) hv_pci_bus_exit(hdev, true);
+release_state_lock:
+ mutex_unlock(&hbus->state_lock);
free_irq_domain:
irq_domain_remove(hbus->irq_domain);
free_fwnode:
@@ -3948,20 +3967,26 @@ static int hv_pci_resume(struct hv_device *hdev)
if (ret)
goto out;
+ mutex_lock(&hbus->state_lock);
+
ret = hv_pci_enter_d0(hdev);
if (ret)
- goto out;
+ goto release_state_lock;
ret = hv_send_resources_allocated(hdev);
if (ret)
- goto out;
+ goto release_state_lock;
prepopulate_bars(hbus);
hv_pci_restore_msi_state(hbus);
hbus->state = hv_pcibus_installed;
+ mutex_unlock(&hbus->state_lock);
return 0;
+
+release_state_lock:
+ mutex_unlock(&hbus->state_lock);
out:
vmbus_close(hdev->channel);
return ret;
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index dc9803e1a4b9..73d2357e32f8 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -297,6 +297,8 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
/* Enable Static Slider */
if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
amd_pmf_init_sps(dev);
+ dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
+ power_supply_reg_notifier(&dev->pwr_src_notifier);
dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
}
@@ -315,8 +317,10 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
{
- if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
+ if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+ power_supply_unreg_notifier(&dev->pwr_src_notifier);
amd_pmf_deinit_sps(dev);
+ }
if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
amd_pmf_deinit_auto_mode(dev);
@@ -399,9 +403,6 @@ static int amd_pmf_probe(struct platform_device *pdev)
apmf_install_handler(dev);
amd_pmf_dbgfs_register(dev);
- dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
- power_supply_reg_notifier(&dev->pwr_src_notifier);
-
dev_info(dev->dev, "registered PMF device successfully\n");
return 0;
@@ -411,7 +412,6 @@ static int amd_pmf_remove(struct platform_device *pdev)
{
struct amd_pmf_dev *dev = platform_get_drvdata(pdev);
- power_supply_unreg_notifier(&dev->pwr_src_notifier);
amd_pmf_deinit_features(dev);
apmf_acpi_deinit(dev);
amd_pmf_dbgfs_unregister(dev);
diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c
index 1086c3d83494..399f0623ca1b 100644
--- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c
+++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c
@@ -101,9 +101,11 @@ int skl_int3472_register_clock(struct int3472_discrete_device *int3472,
int3472->clock.ena_gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0],
"int3472,clk-enable");
- if (IS_ERR(int3472->clock.ena_gpio))
- return dev_err_probe(int3472->dev, PTR_ERR(int3472->clock.ena_gpio),
- "getting clk-enable GPIO\n");
+ if (IS_ERR(int3472->clock.ena_gpio)) {
+ ret = PTR_ERR(int3472->clock.ena_gpio);
+ int3472->clock.ena_gpio = NULL;
+ return dev_err_probe(int3472->dev, ret, "getting clk-enable GPIO\n");
+ }
if (polarity == GPIO_ACTIVE_LOW)
gpiod_toggle_active_low(int3472->clock.ena_gpio);
@@ -199,8 +201,9 @@ int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
int3472->regulator.gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0],
"int3472,regulator");
if (IS_ERR(int3472->regulator.gpio)) {
- dev_err(int3472->dev, "Failed to get regulator GPIO line\n");
- return PTR_ERR(int3472->regulator.gpio);
+ ret = PTR_ERR(int3472->regulator.gpio);
+ int3472->regulator.gpio = NULL;
+ return dev_err_probe(int3472->dev, ret, "getting regulator GPIO\n");
}
/* Ensure the pin is in output mode and non-active state */
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index d5c43e9b5128..c0d620ffea61 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1376,6 +1376,7 @@ void ccw_device_set_notoper(struct ccw_device *cdev)
enum io_sch_action {
IO_SCH_UNREG,
IO_SCH_ORPH_UNREG,
+ IO_SCH_UNREG_CDEV,
IO_SCH_ATTACH,
IO_SCH_UNREG_ATTACH,
IO_SCH_ORPH_ATTACH,
@@ -1408,7 +1409,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
}
if ((sch->schib.pmcw.pam & sch->opm) == 0) {
if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK)
- return IO_SCH_UNREG;
+ return IO_SCH_UNREG_CDEV;
return IO_SCH_DISC;
}
if (device_is_disconnected(cdev))
@@ -1470,6 +1471,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
case IO_SCH_ORPH_ATTACH:
ccw_device_set_disconnected(cdev);
break;
+ case IO_SCH_UNREG_CDEV:
case IO_SCH_UNREG_ATTACH:
case IO_SCH_UNREG:
if (!cdev)
@@ -1503,6 +1505,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
if (rc)
goto out;
break;
+ case IO_SCH_UNREG_CDEV:
case IO_SCH_UNREG_ATTACH:
spin_lock_irqsave(sch->lock, flags);
sch_set_cdev(sch, NULL);
diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c
index 58ea013fa918..2a1096dab63d 100644
--- a/drivers/soundwire/dmi-quirks.c
+++ b/drivers/soundwire/dmi-quirks.c
@@ -99,6 +99,13 @@ static const struct dmi_system_id adr_remap_quirk_table[] = {
},
.driver_data = (void *)intel_tgl_bios,
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8709"),
+ },
+ .driver_data = (void *)intel_tgl_bios,
+ },
{
/* quirk used for NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
.matches = {
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index 30575ed20947..0dcdbd4e1ec3 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -1098,8 +1098,10 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
}
sruntime = sdw_alloc_stream(dai->name);
- if (!sruntime)
- return -ENOMEM;
+ if (!sruntime) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
ctrl->sruntime[dai->id] = sruntime;
@@ -1109,12 +1111,19 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
if (ret < 0 && ret != -ENOTSUPP) {
dev_err(dai->dev, "Failed to set sdw stream on %s\n",
codec_dai->name);
- sdw_release_stream(sruntime);
- return ret;
+ goto err_set_stream;
}
}
return 0;
+
+err_set_stream:
+ sdw_release_stream(sruntime);
+err_alloc:
+ pm_runtime_mark_last_busy(ctrl->dev);
+ pm_runtime_put_autosuspend(ctrl->dev);
+
+ return ret;
}
static void qcom_swrm_shutdown(struct snd_pcm_substream *substream,
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 34488de55587..457fe6bc7e41 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -910,9 +910,14 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller);
if (ret == -EPROBE_DEFER)
goto out_pm_get;
-
if (ret < 0)
dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret);
+ else
+ /*
+ * disable LPSPI module IRQ when enable DMA mode successfully,
+ * to prevent the unexpected LPSPI module IRQ events.
+ */
+ disable_irq(irq);
ret = devm_spi_register_controller(&pdev->dev, controller);
if (ret < 0) {
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index b106faf21a72..baf477383682 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -646,6 +646,8 @@ static int spi_geni_init(struct spi_geni_master *mas)
geni_se_select_mode(se, GENI_GPI_DMA);
dev_dbg(mas->dev, "Using GPI DMA mode for SPI\n");
break;
+ } else if (ret == -EPROBE_DEFER) {
+ goto out_pm;
}
/*
* in case of failure to get gpi dma channel, we can still do the
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 07e196b44b91..c70ce1fa399f 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -363,8 +363,6 @@ struct iscsi_np *iscsit_add_np(
init_completion(&np->np_restart_comp);
INIT_LIST_HEAD(&np->np_list);
- timer_setup(&np->np_login_timer, iscsi_handle_login_thread_timeout, 0);
-
ret = iscsi_target_setup_login_socket(np, sockaddr);
if (ret != 0) {
kfree(np);
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 274bdd7845ca..90b870f234f0 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -811,59 +811,6 @@ void iscsi_post_login_handler(
iscsit_dec_conn_usage_count(conn);
}
-void iscsi_handle_login_thread_timeout(struct timer_list *t)
-{
- struct iscsi_np *np = from_timer(np, t, np_login_timer);
-
- spin_lock_bh(&np->np_thread_lock);
- pr_err("iSCSI Login timeout on Network Portal %pISpc\n",
- &np->np_sockaddr);
-
- if (np->np_login_timer_flags & ISCSI_TF_STOP) {
- spin_unlock_bh(&np->np_thread_lock);
- return;
- }
-
- if (np->np_thread)
- send_sig(SIGINT, np->np_thread, 1);
-
- np->np_login_timer_flags &= ~ISCSI_TF_RUNNING;
- spin_unlock_bh(&np->np_thread_lock);
-}
-
-static void iscsi_start_login_thread_timer(struct iscsi_np *np)
-{
- /*
- * This used the TA_LOGIN_TIMEOUT constant because at this
- * point we do not have access to ISCSI_TPG_ATTRIB(tpg)->login_timeout
- */
- spin_lock_bh(&np->np_thread_lock);
- np->np_login_timer_flags &= ~ISCSI_TF_STOP;
- np->np_login_timer_flags |= ISCSI_TF_RUNNING;
- mod_timer(&np->np_login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
-
- pr_debug("Added timeout timer to iSCSI login request for"
- " %u seconds.\n", TA_LOGIN_TIMEOUT);
- spin_unlock_bh(&np->np_thread_lock);
-}
-
-static void iscsi_stop_login_thread_timer(struct iscsi_np *np)
-{
- spin_lock_bh(&np->np_thread_lock);
- if (!(np->np_login_timer_flags & ISCSI_TF_RUNNING)) {
- spin_unlock_bh(&np->np_thread_lock);
- return;
- }
- np->np_login_timer_flags |= ISCSI_TF_STOP;
- spin_unlock_bh(&np->np_thread_lock);
-
- del_timer_sync(&np->np_login_timer);
-
- spin_lock_bh(&np->np_thread_lock);
- np->np_login_timer_flags &= ~ISCSI_TF_RUNNING;
- spin_unlock_bh(&np->np_thread_lock);
-}
-
int iscsit_setup_np(
struct iscsi_np *np,
struct sockaddr_storage *sockaddr)
@@ -1123,10 +1070,13 @@ static struct iscsit_conn *iscsit_alloc_conn(struct iscsi_np *np)
spin_lock_init(&conn->nopin_timer_lock);
spin_lock_init(&conn->response_queue_lock);
spin_lock_init(&conn->state_lock);
+ spin_lock_init(&conn->login_worker_lock);
+ spin_lock_init(&conn->login_timer_lock);
timer_setup(&conn->nopin_response_timer,
iscsit_handle_nopin_response_timeout, 0);
timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0);
+ timer_setup(&conn->login_timer, iscsit_login_timeout, 0);
if (iscsit_conn_set_transport(conn, np->np_transport) < 0)
goto free_conn;
@@ -1304,7 +1254,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
goto new_sess_out;
}
- iscsi_start_login_thread_timer(np);
+ iscsit_start_login_timer(conn, current);
pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n");
conn->conn_state = TARG_CONN_STATE_XPT_UP;
@@ -1417,8 +1367,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
if (ret < 0)
goto new_sess_out;
- iscsi_stop_login_thread_timer(np);
-
if (ret == 1) {
tpg_np = conn->tpg_np;
@@ -1434,7 +1382,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
new_sess_out:
new_sess = true;
old_sess_out:
- iscsi_stop_login_thread_timer(np);
+ iscsit_stop_login_timer(conn);
tpg_np = conn->tpg_np;
iscsi_target_login_sess_out(conn, zero_tsih, new_sess);
new_sess = false;
@@ -1448,7 +1396,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
return 1;
exit:
- iscsi_stop_login_thread_timer(np);
spin_lock_bh(&np->np_thread_lock);
np->np_thread_state = ISCSI_NP_THREAD_EXIT;
spin_unlock_bh(&np->np_thread_lock);
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 24040c118e49..fa3fb5f4e6bc 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -535,25 +535,6 @@ static void iscsi_target_login_drop(struct iscsit_conn *conn, struct iscsi_login
iscsi_target_login_sess_out(conn, zero_tsih, true);
}
-struct conn_timeout {
- struct timer_list timer;
- struct iscsit_conn *conn;
-};
-
-static void iscsi_target_login_timeout(struct timer_list *t)
-{
- struct conn_timeout *timeout = from_timer(timeout, t, timer);
- struct iscsit_conn *conn = timeout->conn;
-
- pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n");
-
- if (conn->login_kworker) {
- pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n",
- conn->login_kworker->comm, conn->login_kworker->pid);
- send_sig(SIGINT, conn->login_kworker, 1);
- }
-}
-
static void iscsi_target_do_login_rx(struct work_struct *work)
{
struct iscsit_conn *conn = container_of(work,
@@ -562,12 +543,15 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
struct iscsi_np *np = login->np;
struct iscsi_portal_group *tpg = conn->tpg;
struct iscsi_tpg_np *tpg_np = conn->tpg_np;
- struct conn_timeout timeout;
int rc, zero_tsih = login->zero_tsih;
bool state;
pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n",
conn, current->comm, current->pid);
+
+ spin_lock(&conn->login_worker_lock);
+ set_bit(LOGIN_FLAGS_WORKER_RUNNING, &conn->login_flags);
+ spin_unlock(&conn->login_worker_lock);
/*
* If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready()
* before initial PDU processing in iscsi_target_start_negotiation()
@@ -597,19 +581,16 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
goto err;
}
- conn->login_kworker = current;
allow_signal(SIGINT);
-
- timeout.conn = conn;
- timer_setup_on_stack(&timeout.timer, iscsi_target_login_timeout, 0);
- mod_timer(&timeout.timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
- pr_debug("Starting login timer for %s/%d\n", current->comm, current->pid);
+ rc = iscsit_set_login_timer_kworker(conn, current);
+ if (rc < 0) {
+ /* The login timer has already expired */
+ pr_debug("iscsi_target_do_login_rx, login failed\n");
+ goto err;
+ }
rc = conn->conn_transport->iscsit_get_login_rx(conn, login);
- del_timer_sync(&timeout.timer);
- destroy_timer_on_stack(&timeout.timer);
flush_signals(current);
- conn->login_kworker = NULL;
if (rc < 0)
goto err;
@@ -646,7 +627,17 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
if (iscsi_target_sk_check_and_clear(conn,
LOGIN_FLAGS_WRITE_ACTIVE))
goto err;
+
+ /*
+ * Set the login timer thread pointer to NULL to prevent the
+ * login process from getting stuck if the initiator
+ * stops sending data.
+ */
+ rc = iscsit_set_login_timer_kworker(conn, NULL);
+ if (rc < 0)
+ goto err;
} else if (rc == 1) {
+ iscsit_stop_login_timer(conn);
cancel_delayed_work(&conn->login_work);
iscsi_target_nego_release(conn);
iscsi_post_login_handler(np, conn, zero_tsih);
@@ -656,6 +647,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
err:
iscsi_target_restore_sock_callbacks(conn);
+ iscsit_stop_login_timer(conn);
cancel_delayed_work(&conn->login_work);
iscsi_target_login_drop(conn, login);
iscsit_deaccess_np(np, tpg, tpg_np);
@@ -1130,6 +1122,7 @@ int iscsi_target_locate_portal(
iscsi_target_set_sock_callbacks(conn);
login->np = np;
+ conn->tpg = NULL;
login_req = (struct iscsi_login_req *) login->req;
payload_length = ntoh24(login_req->dlength);
@@ -1197,7 +1190,6 @@ int iscsi_target_locate_portal(
*/
sessiontype = strncmp(s_buf, DISCOVERY, 9);
if (!sessiontype) {
- conn->tpg = iscsit_global->discovery_tpg;
if (!login->leading_connection)
goto get_target;
@@ -1214,9 +1206,11 @@ int iscsi_target_locate_portal(
* Serialize access across the discovery struct iscsi_portal_group to
* process login attempt.
*/
+ conn->tpg = iscsit_global->discovery_tpg;
if (iscsit_access_np(np, conn->tpg) < 0) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
+ conn->tpg = NULL;
ret = -1;
goto out;
}
@@ -1368,14 +1362,30 @@ int iscsi_target_start_negotiation(
* and perform connection cleanup now.
*/
ret = iscsi_target_do_login(conn, login);
- if (!ret && iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU))
- ret = -1;
+ if (!ret) {
+ spin_lock(&conn->login_worker_lock);
+
+ if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU))
+ ret = -1;
+ else if (!test_bit(LOGIN_FLAGS_WORKER_RUNNING, &conn->login_flags)) {
+ if (iscsit_set_login_timer_kworker(conn, NULL) < 0) {
+ /*
+ * The timeout has expired already.
+ * Schedule login_work to perform the cleanup.
+ */
+ schedule_delayed_work(&conn->login_work, 0);
+ }
+ }
+
+ spin_unlock(&conn->login_worker_lock);
+ }
if (ret < 0) {
iscsi_target_restore_sock_callbacks(conn);
iscsi_remove_failed_auth_entry(conn);
}
if (ret != 0) {
+ iscsit_stop_login_timer(conn);
cancel_delayed_work_sync(&conn->login_work);
iscsi_target_nego_release(conn);
}
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 26dc8ed3045b..b14835fcb033 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -1040,6 +1040,57 @@ void iscsit_stop_nopin_timer(struct iscsit_conn *conn)
spin_unlock_bh(&conn->nopin_timer_lock);
}
+void iscsit_login_timeout(struct timer_list *t)
+{
+ struct iscsit_conn *conn = from_timer(conn, t, login_timer);
+ struct iscsi_login *login = conn->login;
+
+ pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n");
+
+ spin_lock_bh(&conn->login_timer_lock);
+ login->login_failed = 1;
+
+ if (conn->login_kworker) {
+ pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n",
+ conn->login_kworker->comm, conn->login_kworker->pid);
+ send_sig(SIGINT, conn->login_kworker, 1);
+ } else {
+ schedule_delayed_work(&conn->login_work, 0);
+ }
+ spin_unlock_bh(&conn->login_timer_lock);
+}
+
+void iscsit_start_login_timer(struct iscsit_conn *conn, struct task_struct *kthr)
+{
+ pr_debug("Login timer started\n");
+
+ conn->login_kworker = kthr;
+ mod_timer(&conn->login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ);
+}
+
+int iscsit_set_login_timer_kworker(struct iscsit_conn *conn, struct task_struct *kthr)
+{
+ struct iscsi_login *login = conn->login;
+ int ret = 0;
+
+ spin_lock_bh(&conn->login_timer_lock);
+ if (login->login_failed) {
+ /* The timer has already expired */
+ ret = -1;
+ } else {
+ conn->login_kworker = kthr;
+ }
+ spin_unlock_bh(&conn->login_timer_lock);
+
+ return ret;
+}
+
+void iscsit_stop_login_timer(struct iscsit_conn *conn)
+{
+ pr_debug("Login timer stopped\n");
+ timer_delete_sync(&conn->login_timer);
+}
+
int iscsit_send_tx_data(
struct iscsit_cmd *cmd,
struct iscsit_conn *conn,
diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h
index 33ea799a0850..24b8e577575a 100644
--- a/drivers/target/iscsi/iscsi_target_util.h
+++ b/drivers/target/iscsi/iscsi_target_util.h
@@ -56,6 +56,10 @@ extern void iscsit_handle_nopin_timeout(struct timer_list *t);
extern void __iscsit_start_nopin_timer(struct iscsit_conn *);
extern void iscsit_start_nopin_timer(struct iscsit_conn *);
extern void iscsit_stop_nopin_timer(struct iscsit_conn *);
+extern void iscsit_login_timeout(struct timer_list *t);
+extern void iscsit_start_login_timer(struct iscsit_conn *, struct task_struct *kthr);
+extern void iscsit_stop_login_timer(struct iscsit_conn *);
+extern int iscsit_set_login_timer_kworker(struct iscsit_conn *, struct task_struct *kthr);
extern int iscsit_send_tx_data(struct iscsit_cmd *, struct iscsit_conn *, int);
extern int iscsit_fe_sendpage_sg(struct iscsit_cmd *, struct iscsit_conn *);
extern int iscsit_tx_login_rsp(struct iscsit_conn *, u8, u8);
diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c
index 8c26f7b2316b..99b3c2ce4643 100644
--- a/drivers/thermal/intel/intel_soc_dts_iosf.c
+++ b/drivers/thermal/intel/intel_soc_dts_iosf.c
@@ -401,7 +401,7 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
spin_lock_init(&sensors->intr_notify_lock);
mutex_init(&sensors->dts_update_lock);
sensors->intr_type = intr_type;
- sensors->tj_max = tj_max;
+ sensors->tj_max = tj_max * 1000;
if (intr_type == INTEL_SOC_DTS_INTERRUPT_NONE)
notification = false;
else
diff --git a/drivers/usb/gadget/udc/amd5536udc_pci.c b/drivers/usb/gadget/udc/amd5536udc_pci.c
index c80f9bd51b75..a36913ae31f9 100644
--- a/drivers/usb/gadget/udc/amd5536udc_pci.c
+++ b/drivers/usb/gadget/udc/amd5536udc_pci.c
@@ -170,6 +170,9 @@ static int udc_pci_probe(
retval = -ENODEV;
goto err_probe;
}
+
+ udc = dev;
+
return 0;
err_probe:
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 07181cd8d52e..ae2273196b0c 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -935,13 +935,18 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock)
err = sock->ops->sendmsg(sock, &msg, len);
if (unlikely(err < 0)) {
+ bool retry = err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS;
+
if (zcopy_used) {
if (vq->heads[ubuf->desc].len == VHOST_DMA_IN_PROGRESS)
vhost_net_ubuf_put(ubufs);
- nvq->upend_idx = ((unsigned)nvq->upend_idx - 1)
- % UIO_MAXIOV;
+ if (retry)
+ nvq->upend_idx = ((unsigned)nvq->upend_idx - 1)
+ % UIO_MAXIOV;
+ else
+ vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
}
- if (err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS) {
+ if (retry) {
vhost_discard_vq_desc(vq, 1);
vhost_net_enable_vq(net, vq);
break;
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index 779fc4467716..22e6b23ac96f 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -385,7 +385,10 @@ static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep)
{
struct vdpa_device *vdpa = v->vdpa;
const struct vdpa_config_ops *ops = vdpa->config;
+ struct vhost_dev *d = &v->vdev;
+ u64 actual_features;
u64 features;
+ int i;
/*
* It's not allowed to change the features after they have
@@ -400,6 +403,16 @@ static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep)
if (vdpa_set_features(vdpa, features))
return -EINVAL;
+ /* let the vqs know what has been configured */
+ actual_features = ops->get_driver_features(vdpa);
+ for (i = 0; i < d->nvqs; ++i) {
+ struct vhost_virtqueue *vq = d->vqs[i];
+
+ mutex_lock(&vq->mutex);
+ vq->acked_features = actual_features;
+ mutex_unlock(&vq->mutex);
+ }
+
return 0;
}
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 571f3b9a417e..ad46f4b3c0c8 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -731,6 +731,7 @@ static int afs_writepages_region(struct address_space *mapping,
* (changing page->mapping to NULL), or even swizzled
* back from swapper_space to tmpfs file mapping
*/
+try_again:
if (wbc->sync_mode != WB_SYNC_NONE) {
ret = folio_lock_killable(folio);
if (ret < 0) {
@@ -757,12 +758,14 @@ static int afs_writepages_region(struct address_space *mapping,
#ifdef CONFIG_AFS_FSCACHE
folio_wait_fscache(folio);
#endif
- } else {
- start += folio_size(folio);
+ goto try_again;
}
+
+ start += folio_size(folio);
if (wbc->sync_mode == WB_SYNC_NONE) {
if (skips >= 5 || need_resched()) {
*_next = start;
+ folio_batch_release(&fbatch);
_leave(" = 0 [%llx]", *_next);
return 0;
}
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 200cea6e49e5..b91fa398b814 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -6163,7 +6163,7 @@ static int log_delayed_deletions_incremental(struct btrfs_trans_handle *trans,
{
struct btrfs_root *log = inode->root->log_root;
const struct btrfs_delayed_item *curr;
- u64 last_range_start;
+ u64 last_range_start = 0;
u64 last_range_end = 0;
struct btrfs_key key;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 8e9a672320ab..1250d156619b 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -4086,16 +4086,17 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
/* only send once per connect */
spin_lock(&tcon->tc_lock);
+ if (tcon->status == TID_GOOD) {
+ spin_unlock(&tcon->tc_lock);
+ return 0;
+ }
+
if (tcon->status != TID_NEW &&
tcon->status != TID_NEED_TCON) {
spin_unlock(&tcon->tc_lock);
return -EHOSTDOWN;
}
- if (tcon->status == TID_GOOD) {
- spin_unlock(&tcon->tc_lock);
- return 0;
- }
tcon->status = TID_IN_TCON;
spin_unlock(&tcon->tc_lock);
diff --git a/fs/cifs/dfs.c b/fs/cifs/dfs.c
index 2f93bf8c3325..2390b2fedd6a 100644
--- a/fs/cifs/dfs.c
+++ b/fs/cifs/dfs.c
@@ -575,16 +575,17 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
/* only send once per connect */
spin_lock(&tcon->tc_lock);
+ if (tcon->status == TID_GOOD) {
+ spin_unlock(&tcon->tc_lock);
+ return 0;
+ }
+
if (tcon->status != TID_NEW &&
tcon->status != TID_NEED_TCON) {
spin_unlock(&tcon->tc_lock);
return -EHOSTDOWN;
}
- if (tcon->status == TID_GOOD) {
- spin_unlock(&tcon->tc_lock);
- return 0;
- }
tcon->status = TID_IN_TCON;
spin_unlock(&tcon->tc_lock);
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 02228a590cd5..a2a95cd113df 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -3777,7 +3777,7 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
if (*out_data == NULL) {
rc = -ENOMEM;
goto cnotify_exit;
- } else
+ } else if (plen)
*plen = le32_to_cpu(smb_rsp->OutputBufferLength);
}
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 300844f50dcd..cb62c8f07d1e 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -784,9 +784,13 @@ static inline bool should_fault_in_pages(struct iov_iter *i,
if (!user_backed_iter(i))
return false;
+ /*
+ * Try to fault in multiple pages initially. When that doesn't result
+ * in any progress, fall back to a single page.
+ */
size = PAGE_SIZE;
offs = offset_in_page(iocb->ki_pos);
- if (*prev_count != count || !*window_size) {
+ if (*prev_count != count) {
size_t nr_dirtied;
nr_dirtied = max(current->nr_dirtied_pause -
@@ -870,6 +874,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
struct gfs2_inode *ip = GFS2_I(inode);
size_t prev_count = 0, window_size = 0;
size_t written = 0;
+ bool enough_retries;
ssize_t ret;
/*
@@ -913,11 +918,17 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
if (ret > 0)
written = ret;
+ enough_retries = prev_count == iov_iter_count(from) &&
+ window_size <= PAGE_SIZE;
if (should_fault_in_pages(from, iocb, &prev_count, &window_size)) {
gfs2_glock_dq(gh);
window_size -= fault_in_iov_iter_readable(from, window_size);
- if (window_size)
- goto retry;
+ if (window_size) {
+ if (!enough_retries)
+ goto retry;
+ /* fall back to buffered I/O */
+ ret = 0;
+ }
}
out_unlock:
if (gfs2_holder_queued(gh))
diff --git a/fs/internal.h b/fs/internal.h
index dc4eb91a577a..071a7517f1a7 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -59,8 +59,6 @@ extern int finish_clean_context(struct fs_context *fc);
*/
extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
struct path *path, struct path *root);
-extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
- const char *, unsigned int, struct path *);
int do_rmdir(int dfd, struct filename *name);
int do_unlinkat(int dfd, struct filename *name);
int may_linkat(struct mnt_idmap *idmap, const struct path *link);
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index dc76d7cf241f..14df83c20557 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -185,24 +185,31 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
goto send;
}
- if (conn->ops->check_user_session) {
- rc = conn->ops->check_user_session(work);
- if (rc < 0) {
- command = conn->ops->get_cmd_val(work);
- conn->ops->set_rsp_status(work,
- STATUS_USER_SESSION_DELETED);
- goto send;
- } else if (rc > 0) {
- rc = conn->ops->get_ksmbd_tcon(work);
+ do {
+ if (conn->ops->check_user_session) {
+ rc = conn->ops->check_user_session(work);
if (rc < 0) {
- conn->ops->set_rsp_status(work,
- STATUS_NETWORK_NAME_DELETED);
+ if (rc == -EINVAL)
+ conn->ops->set_rsp_status(work,
+ STATUS_INVALID_PARAMETER);
+ else
+ conn->ops->set_rsp_status(work,
+ STATUS_USER_SESSION_DELETED);
goto send;
+ } else if (rc > 0) {
+ rc = conn->ops->get_ksmbd_tcon(work);
+ if (rc < 0) {
+ if (rc == -EINVAL)
+ conn->ops->set_rsp_status(work,
+ STATUS_INVALID_PARAMETER);
+ else
+ conn->ops->set_rsp_status(work,
+ STATUS_NETWORK_NAME_DELETED);
+ goto send;
+ }
}
}
- }
- do {
rc = __process_request(work, conn, &command);
if (rc == SERVER_HANDLER_ABORT)
break;
diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c
index 0ffe663b7590..33b7e6c4ceff 100644
--- a/fs/ksmbd/smb2misc.c
+++ b/fs/ksmbd/smb2misc.c
@@ -351,9 +351,16 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
int command;
__u32 clc_len; /* calculated length */
__u32 len = get_rfc1002_len(work->request_buf);
+ __u32 req_struct_size, next_cmd = le32_to_cpu(hdr->NextCommand);
- if (le32_to_cpu(hdr->NextCommand) > 0)
- len = le32_to_cpu(hdr->NextCommand);
+ if ((u64)work->next_smb2_rcv_hdr_off + next_cmd > len) {
+ pr_err("next command(%u) offset exceeds smb msg size\n",
+ next_cmd);
+ return 1;
+ }
+
+ if (next_cmd > 0)
+ len = next_cmd;
else if (work->next_smb2_rcv_hdr_off)
len -= work->next_smb2_rcv_hdr_off;
@@ -373,17 +380,9 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
}
if (smb2_req_struct_sizes[command] != pdu->StructureSize2) {
- if (command != SMB2_OPLOCK_BREAK_HE &&
- (hdr->Status == 0 || pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2_LE)) {
- /* error packets have 9 byte structure size */
- ksmbd_debug(SMB,
- "Illegal request size %u for command %d\n",
- le16_to_cpu(pdu->StructureSize2), command);
- return 1;
- } else if (command == SMB2_OPLOCK_BREAK_HE &&
- hdr->Status == 0 &&
- le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 &&
- le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) {
+ if (command == SMB2_OPLOCK_BREAK_HE &&
+ le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 &&
+ le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) {
/* special case for SMB2.1 lease break message */
ksmbd_debug(SMB,
"Illegal request size %d for oplock break\n",
@@ -392,6 +391,14 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
}
}
+ req_struct_size = le16_to_cpu(pdu->StructureSize2) +
+ __SMB2_HEADER_STRUCTURE_SIZE;
+ if (command == SMB2_LOCK_HE)
+ req_struct_size -= sizeof(struct smb2_lock_element);
+
+ if (req_struct_size > len + 1)
+ return 1;
+
if (smb2_calc_size(hdr, &clc_len))
return 1;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 85783112e56a..9610b8a884d0 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -91,7 +91,6 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
unsigned int cmd = le16_to_cpu(req_hdr->Command);
int tree_id;
- work->tcon = NULL;
if (cmd == SMB2_TREE_CONNECT_HE ||
cmd == SMB2_CANCEL_HE ||
cmd == SMB2_LOGOFF_HE) {
@@ -105,10 +104,28 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
}
tree_id = le32_to_cpu(req_hdr->Id.SyncId.TreeId);
+
+ /*
+ * If request is not the first in Compound request,
+ * Just validate tree id in header with work->tcon->id.
+ */
+ if (work->next_smb2_rcv_hdr_off) {
+ if (!work->tcon) {
+ pr_err("The first operation in the compound does not have tcon\n");
+ return -EINVAL;
+ }
+ if (work->tcon->id != tree_id) {
+ pr_err("tree id(%u) is different with id(%u) in first operation\n",
+ tree_id, work->tcon->id);
+ return -EINVAL;
+ }
+ return 1;
+ }
+
work->tcon = ksmbd_tree_conn_lookup(work->sess, tree_id);
if (!work->tcon) {
pr_err("Invalid tid %d\n", tree_id);
- return -EINVAL;
+ return -ENOENT;
}
return 1;
@@ -547,7 +564,6 @@ int smb2_check_user_session(struct ksmbd_work *work)
unsigned int cmd = conn->ops->get_cmd_val(work);
unsigned long long sess_id;
- work->sess = NULL;
/*
* SMB2_ECHO, SMB2_NEGOTIATE, SMB2_SESSION_SETUP command do not
* require a session id, so no need to validate user session's for
@@ -558,15 +574,33 @@ int smb2_check_user_session(struct ksmbd_work *work)
return 0;
if (!ksmbd_conn_good(conn))
- return -EINVAL;
+ return -EIO;
sess_id = le64_to_cpu(req_hdr->SessionId);
+
+ /*
+ * If request is not the first in Compound request,
+ * Just validate session id in header with work->sess->id.
+ */
+ if (work->next_smb2_rcv_hdr_off) {
+ if (!work->sess) {
+ pr_err("The first operation in the compound does not have sess\n");
+ return -EINVAL;
+ }
+ if (work->sess->id != sess_id) {
+ pr_err("session id(%llu) is different with the first operation(%lld)\n",
+ sess_id, work->sess->id);
+ return -EINVAL;
+ }
+ return 1;
+ }
+
/* Check for validity of user session */
work->sess = ksmbd_session_lookup_all(conn, sess_id);
if (work->sess)
return 1;
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
- return -EINVAL;
+ return -ENOENT;
}
static void destroy_previous_session(struct ksmbd_conn *conn,
@@ -2277,7 +2311,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
/* delete the EA only when it exits */
if (rc > 0) {
rc = ksmbd_vfs_remove_xattr(idmap,
- path->dentry,
+ path,
attr_name);
if (rc < 0) {
@@ -2291,8 +2325,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
/* if the EA doesn't exist, just do nothing. */
rc = 0;
} else {
- rc = ksmbd_vfs_setxattr(idmap,
- path->dentry, attr_name, value,
+ rc = ksmbd_vfs_setxattr(idmap, path, attr_name, value,
le16_to_cpu(eabuf->EaValueLength), 0);
if (rc < 0) {
ksmbd_debug(SMB,
@@ -2349,8 +2382,7 @@ static noinline int smb2_set_stream_name_xattr(const struct path *path,
return -EBADF;
}
- rc = ksmbd_vfs_setxattr(idmap, path->dentry,
- xattr_stream_name, NULL, 0, 0);
+ rc = ksmbd_vfs_setxattr(idmap, path, xattr_stream_name, NULL, 0, 0);
if (rc < 0)
pr_err("Failed to store XATTR stream name :%d\n", rc);
return 0;
@@ -2378,7 +2410,7 @@ static int smb2_remove_smb_xattrs(const struct path *path)
if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
!strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
STREAM_PREFIX_LEN)) {
- err = ksmbd_vfs_remove_xattr(idmap, path->dentry,
+ err = ksmbd_vfs_remove_xattr(idmap, path,
name);
if (err)
ksmbd_debug(SMB, "remove xattr failed : %s\n",
@@ -2425,8 +2457,7 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
XATTR_DOSINFO_ITIME;
- rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt),
- path->dentry, &da);
+ rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da);
if (rc)
ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
}
@@ -2481,7 +2512,7 @@ static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
return rc;
}
- rc = ksmbd_vfs_kern_path(work, name, 0, path, 0);
+ rc = ksmbd_vfs_kern_path_locked(work, name, 0, path, 0);
if (rc) {
pr_err("cannot get linux path (%s), err = %d\n",
name, rc);
@@ -2772,8 +2803,10 @@ int smb2_open(struct ksmbd_work *work)
goto err_out1;
}
- rc = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS, &path, 1);
+ rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS, &path, 1);
if (!rc) {
+ file_present = true;
+
if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) {
/*
* If file exists with under flags, return access
@@ -2782,7 +2815,6 @@ int smb2_open(struct ksmbd_work *work)
if (req->CreateDisposition == FILE_OVERWRITE_IF_LE ||
req->CreateDisposition == FILE_OPEN_IF_LE) {
rc = -EACCES;
- path_put(&path);
goto err_out;
}
@@ -2790,26 +2822,23 @@ int smb2_open(struct ksmbd_work *work)
ksmbd_debug(SMB,
"User does not have write permission\n");
rc = -EACCES;
- path_put(&path);
goto err_out;
}
} else if (d_is_symlink(path.dentry)) {
rc = -EACCES;
- path_put(&path);
goto err_out;
}
- }
- if (rc) {
+ file_present = true;
+ idmap = mnt_idmap(path.mnt);
+ } else {
if (rc != -ENOENT)
goto err_out;
ksmbd_debug(SMB, "can not get linux path for %s, rc = %d\n",
name, rc);
rc = 0;
- } else {
- file_present = true;
- idmap = mnt_idmap(path.mnt);
}
+
if (stream_name) {
if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
if (s_type == DATA_STREAM) {
@@ -2937,8 +2966,9 @@ int smb2_open(struct ksmbd_work *work)
if ((daccess & FILE_DELETE_LE) ||
(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
- rc = ksmbd_vfs_may_delete(idmap,
- path.dentry);
+ rc = inode_permission(idmap,
+ d_inode(path.dentry->d_parent),
+ MAY_EXEC | MAY_WRITE);
if (rc)
goto err_out;
}
@@ -3001,7 +3031,7 @@ int smb2_open(struct ksmbd_work *work)
struct inode *inode = d_inode(path.dentry);
posix_acl_rc = ksmbd_vfs_inherit_posix_acl(idmap,
- path.dentry,
+ &path,
d_inode(path.dentry->d_parent));
if (posix_acl_rc)
ksmbd_debug(SMB, "inherit posix acl failed : %d\n", posix_acl_rc);
@@ -3017,7 +3047,7 @@ int smb2_open(struct ksmbd_work *work)
if (rc) {
if (posix_acl_rc)
ksmbd_vfs_set_init_posix_acl(idmap,
- path.dentry);
+ &path);
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_ACL_XATTR)) {
@@ -3057,7 +3087,7 @@ int smb2_open(struct ksmbd_work *work)
rc = ksmbd_vfs_set_sd_xattr(conn,
idmap,
- path.dentry,
+ &path,
pntsd,
pntsd_size);
kfree(pntsd);
@@ -3309,10 +3339,13 @@ int smb2_open(struct ksmbd_work *work)
}
err_out:
- if (file_present || created)
- path_put(&path);
+ if (file_present || created) {
+ inode_unlock(d_inode(path.dentry->d_parent));
+ dput(path.dentry);
+ }
ksmbd_revert_fsids(work);
err_out1:
+
if (rc) {
if (rc == -EINVAL)
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
@@ -5451,44 +5484,19 @@ int smb2_echo(struct ksmbd_work *work)
static int smb2_rename(struct ksmbd_work *work,
struct ksmbd_file *fp,
- struct mnt_idmap *idmap,
struct smb2_file_rename_info *file_info,
struct nls_table *local_nls)
{
struct ksmbd_share_config *share = fp->tcon->share_conf;
- char *new_name = NULL, *abs_oldname = NULL, *old_name = NULL;
- char *pathname = NULL;
- struct path path;
- bool file_present = true;
- int rc;
+ char *new_name = NULL;
+ int rc, flags = 0;
ksmbd_debug(SMB, "setting FILE_RENAME_INFO\n");
- pathname = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!pathname)
- return -ENOMEM;
-
- abs_oldname = file_path(fp->filp, pathname, PATH_MAX);
- if (IS_ERR(abs_oldname)) {
- rc = -EINVAL;
- goto out;
- }
- old_name = strrchr(abs_oldname, '/');
- if (old_name && old_name[1] != '\0') {
- old_name++;
- } else {
- ksmbd_debug(SMB, "can't get last component in path %s\n",
- abs_oldname);
- rc = -ENOENT;
- goto out;
- }
-
new_name = smb2_get_name(file_info->FileName,
le32_to_cpu(file_info->FileNameLength),
local_nls);
- if (IS_ERR(new_name)) {
- rc = PTR_ERR(new_name);
- goto out;
- }
+ if (IS_ERR(new_name))
+ return PTR_ERR(new_name);
if (strchr(new_name, ':')) {
int s_type;
@@ -5514,8 +5522,8 @@ static int smb2_rename(struct ksmbd_work *work,
if (rc)
goto out;
- rc = ksmbd_vfs_setxattr(idmap,
- fp->filp->f_path.dentry,
+ rc = ksmbd_vfs_setxattr(file_mnt_idmap(fp->filp),
+ &fp->filp->f_path,
xattr_stream_name,
NULL, 0, 0);
if (rc < 0) {
@@ -5529,47 +5537,18 @@ static int smb2_rename(struct ksmbd_work *work,
}
ksmbd_debug(SMB, "new name %s\n", new_name);
- rc = ksmbd_vfs_kern_path(work, new_name, LOOKUP_NO_SYMLINKS, &path, 1);
- if (rc) {
- if (rc != -ENOENT)
- goto out;
- file_present = false;
- } else {
- path_put(&path);
- }
-
if (ksmbd_share_veto_filename(share, new_name)) {
rc = -ENOENT;
ksmbd_debug(SMB, "Can't rename vetoed file: %s\n", new_name);
goto out;
}
- if (file_info->ReplaceIfExists) {
- if (file_present) {
- rc = ksmbd_vfs_remove_file(work, new_name);
- if (rc) {
- if (rc != -ENOTEMPTY)
- rc = -EINVAL;
- ksmbd_debug(SMB, "cannot delete %s, rc %d\n",
- new_name, rc);
- goto out;
- }
- }
- } else {
- if (file_present &&
- strncmp(old_name, path.dentry->d_name.name, strlen(old_name))) {
- rc = -EEXIST;
- ksmbd_debug(SMB,
- "cannot rename already existing file\n");
- goto out;
- }
- }
+ if (!file_info->ReplaceIfExists)
+ flags = RENAME_NOREPLACE;
- rc = ksmbd_vfs_fp_rename(work, fp, new_name);
+ rc = ksmbd_vfs_rename(work, &fp->filp->f_path, new_name, flags);
out:
- kfree(pathname);
- if (!IS_ERR(new_name))
- kfree(new_name);
+ kfree(new_name);
return rc;
}
@@ -5581,7 +5560,7 @@ static int smb2_create_link(struct ksmbd_work *work,
{
char *link_name = NULL, *target_name = NULL, *pathname = NULL;
struct path path;
- bool file_present = true;
+ bool file_present = false;
int rc;
if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
@@ -5609,18 +5588,17 @@ static int smb2_create_link(struct ksmbd_work *work,
}
ksmbd_debug(SMB, "target name is %s\n", target_name);
- rc = ksmbd_vfs_kern_path(work, link_name, LOOKUP_NO_SYMLINKS, &path, 0);
+ rc = ksmbd_vfs_kern_path_locked(work, link_name, LOOKUP_NO_SYMLINKS,
+ &path, 0);
if (rc) {
if (rc != -ENOENT)
goto out;
- file_present = false;
- } else {
- path_put(&path);
- }
+ } else
+ file_present = true;
if (file_info->ReplaceIfExists) {
if (file_present) {
- rc = ksmbd_vfs_remove_file(work, link_name);
+ rc = ksmbd_vfs_remove_file(work, &path);
if (rc) {
rc = -EINVAL;
ksmbd_debug(SMB, "cannot delete %s\n",
@@ -5640,6 +5618,10 @@ static int smb2_create_link(struct ksmbd_work *work,
if (rc)
rc = -EINVAL;
out:
+ if (file_present) {
+ inode_unlock(d_inode(path.dentry->d_parent));
+ path_put(&path);
+ }
if (!IS_ERR(link_name))
kfree(link_name);
kfree(pathname);
@@ -5706,8 +5688,7 @@ static int set_file_basic_info(struct ksmbd_file *fp,
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
XATTR_DOSINFO_ITIME;
- rc = ksmbd_vfs_set_dos_attrib_xattr(idmap,
- filp->f_path.dentry, &da);
+ rc = ksmbd_vfs_set_dos_attrib_xattr(idmap, &filp->f_path, &da);
if (rc)
ksmbd_debug(SMB,
"failed to restore file attribute in EA\n");
@@ -5817,12 +5798,6 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
struct smb2_file_rename_info *rename_info,
unsigned int buf_len)
{
- struct mnt_idmap *idmap;
- struct ksmbd_file *parent_fp;
- struct dentry *parent;
- struct dentry *dentry = fp->filp->f_path.dentry;
- int ret;
-
if (!(fp->daccess & FILE_DELETE_LE)) {
pr_err("no right to delete : 0x%x\n", fp->daccess);
return -EACCES;
@@ -5832,32 +5807,10 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
le32_to_cpu(rename_info->FileNameLength))
return -EINVAL;
- idmap = file_mnt_idmap(fp->filp);
- if (ksmbd_stream_fd(fp))
- goto next;
-
- parent = dget_parent(dentry);
- ret = ksmbd_vfs_lock_parent(idmap, parent, dentry);
- if (ret) {
- dput(parent);
- return ret;
- }
-
- parent_fp = ksmbd_lookup_fd_inode(d_inode(parent));
- inode_unlock(d_inode(parent));
- dput(parent);
+ if (!le32_to_cpu(rename_info->FileNameLength))
+ return -EINVAL;
- if (parent_fp) {
- if (parent_fp->daccess & FILE_DELETE_LE) {
- pr_err("parent dir is opened with delete access\n");
- ksmbd_fd_put(work, parent_fp);
- return -ESHARE;
- }
- ksmbd_fd_put(work, parent_fp);
- }
-next:
- return smb2_rename(work, fp, idmap, rename_info,
- work->conn->local_nls);
+ return smb2_rename(work, fp, rename_info, work->conn->local_nls);
}
static int set_file_disposition_info(struct ksmbd_file *fp,
@@ -7590,7 +7543,7 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
da.attr = le32_to_cpu(fp->f_ci->m_fattr);
ret = ksmbd_vfs_set_dos_attrib_xattr(idmap,
- fp->filp->f_path.dentry, &da);
+ &fp->filp->f_path, &da);
if (ret)
fp->f_ci->m_fattr = old_fattr;
}
diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c
index 0a5862a61c77..ad919a4239d0 100644
--- a/fs/ksmbd/smbacl.c
+++ b/fs/ksmbd/smbacl.c
@@ -1162,8 +1162,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
pntsd_size += sizeof(struct smb_acl) + nt_size;
}
- ksmbd_vfs_set_sd_xattr(conn, idmap,
- path->dentry, pntsd, pntsd_size);
+ ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, pntsd_size);
kfree(pntsd);
}
@@ -1383,7 +1382,7 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
newattrs.ia_valid |= ATTR_MODE;
newattrs.ia_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777);
- ksmbd_vfs_remove_acl_xattrs(idmap, path->dentry);
+ ksmbd_vfs_remove_acl_xattrs(idmap, path);
/* Update posix acls */
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && fattr.cf_dacls) {
rc = set_posix_acl(idmap, path->dentry,
@@ -1414,9 +1413,8 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) {
/* Update WinACL in xattr */
- ksmbd_vfs_remove_sd_xattrs(idmap, path->dentry);
- ksmbd_vfs_set_sd_xattr(conn, idmap,
- path->dentry, pntsd, ntsd_len);
+ ksmbd_vfs_remove_sd_xattrs(idmap, path);
+ ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, ntsd_len);
}
out:
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index f6a8b2659309..81489fdedd8e 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -18,8 +18,7 @@
#include <linux/vmalloc.h>
#include <linux/sched/xacct.h>
#include <linux/crc32c.h>
-
-#include "../internal.h" /* for vfs_path_lookup */
+#include <linux/namei.h>
#include "glob.h"
#include "oplock.h"
@@ -37,19 +36,6 @@
#include "mgmt/user_session.h"
#include "mgmt/user_config.h"
-static char *extract_last_component(char *path)
-{
- char *p = strrchr(path, '/');
-
- if (p && p[1] != '\0') {
- *p = '\0';
- p++;
- } else {
- p = NULL;
- }
- return p;
-}
-
static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
struct inode *parent_inode,
struct inode *inode)
@@ -63,65 +49,81 @@ static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
/**
* ksmbd_vfs_lock_parent() - lock parent dentry if it is stable
- *
- * the parent dentry got by dget_parent or @parent could be
- * unstable, we try to lock a parent inode and lookup the
- * child dentry again.
- *
- * the reference count of @parent isn't incremented.
*/
-int ksmbd_vfs_lock_parent(struct mnt_idmap *idmap, struct dentry *parent,
- struct dentry *child)
+int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
{
- struct dentry *dentry;
- int ret = 0;
-
inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
- dentry = lookup_one(idmap, child->d_name.name, parent,
- child->d_name.len);
- if (IS_ERR(dentry)) {
- ret = PTR_ERR(dentry);
- goto out_err;
- }
-
- if (dentry != child) {
- ret = -ESTALE;
- dput(dentry);
- goto out_err;
+ if (child->d_parent != parent) {
+ inode_unlock(d_inode(parent));
+ return -ENOENT;
}
- dput(dentry);
return 0;
-out_err:
- inode_unlock(d_inode(parent));
- return ret;
}
-int ksmbd_vfs_may_delete(struct mnt_idmap *idmap,
- struct dentry *dentry)
+static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
+ char *pathname, unsigned int flags,
+ struct path *path)
{
- struct dentry *parent;
- int ret;
+ struct qstr last;
+ struct filename *filename;
+ struct path *root_share_path = &share_conf->vfs_path;
+ int err, type;
+ struct path parent_path;
+ struct dentry *d;
+
+ if (pathname[0] == '\0') {
+ pathname = share_conf->path;
+ root_share_path = NULL;
+ } else {
+ flags |= LOOKUP_BENEATH;
+ }
+
+ filename = getname_kernel(pathname);
+ if (IS_ERR(filename))
+ return PTR_ERR(filename);
+
+ err = vfs_path_parent_lookup(filename, flags,
+ &parent_path, &last, &type,
+ root_share_path);
+ if (err) {
+ putname(filename);
+ return err;
+ }
- parent = dget_parent(dentry);
- ret = ksmbd_vfs_lock_parent(idmap, parent, dentry);
- if (ret) {
- dput(parent);
- return ret;
+ if (unlikely(type != LAST_NORM)) {
+ path_put(&parent_path);
+ putname(filename);
+ return -ENOENT;
}
- ret = inode_permission(idmap, d_inode(parent),
- MAY_EXEC | MAY_WRITE);
+ inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
+ d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
+ if (IS_ERR(d))
+ goto err_out;
- inode_unlock(d_inode(parent));
- dput(parent);
- return ret;
+ if (d_is_negative(d)) {
+ dput(d);
+ goto err_out;
+ }
+
+ path->dentry = d;
+ path->mnt = share_conf->vfs_path.mnt;
+ path_put(&parent_path);
+ putname(filename);
+
+ return 0;
+
+err_out:
+ inode_unlock(parent_path.dentry->d_inode);
+ path_put(&parent_path);
+ putname(filename);
+ return -ENOENT;
}
int ksmbd_vfs_query_maximal_access(struct mnt_idmap *idmap,
struct dentry *dentry, __le32 *daccess)
{
- struct dentry *parent;
int ret = 0;
*daccess = cpu_to_le32(FILE_READ_ATTRIBUTES | READ_CONTROL);
@@ -138,18 +140,9 @@ int ksmbd_vfs_query_maximal_access(struct mnt_idmap *idmap,
if (!inode_permission(idmap, d_inode(dentry), MAY_OPEN | MAY_EXEC))
*daccess |= FILE_EXECUTE_LE;
- parent = dget_parent(dentry);
- ret = ksmbd_vfs_lock_parent(idmap, parent, dentry);
- if (ret) {
- dput(parent);
- return ret;
- }
-
- if (!inode_permission(idmap, d_inode(parent), MAY_EXEC | MAY_WRITE))
+ if (!inode_permission(idmap, d_inode(dentry->d_parent), MAY_EXEC | MAY_WRITE))
*daccess |= FILE_DELETE_LE;
- inode_unlock(d_inode(parent));
- dput(parent);
return ret;
}
@@ -177,6 +170,10 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
return err;
}
+ err = mnt_want_write(path.mnt);
+ if (err)
+ goto out_err;
+
mode |= S_IFREG;
err = vfs_create(mnt_idmap(path.mnt), d_inode(path.dentry),
dentry, mode, true);
@@ -186,6 +183,9 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
} else {
pr_err("File(%s): creation failed (err:%d)\n", name, err);
}
+ mnt_drop_write(path.mnt);
+
+out_err:
done_path_create(&path, dentry);
return err;
}
@@ -216,30 +216,35 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
return err;
}
+ err = mnt_want_write(path.mnt);
+ if (err)
+ goto out_err2;
+
idmap = mnt_idmap(path.mnt);
mode |= S_IFDIR;
err = vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode);
- if (err) {
- goto out;
- } else if (d_unhashed(dentry)) {
+ if (!err && d_unhashed(dentry)) {
struct dentry *d;
d = lookup_one(idmap, dentry->d_name.name, dentry->d_parent,
dentry->d_name.len);
if (IS_ERR(d)) {
err = PTR_ERR(d);
- goto out;
+ goto out_err1;
}
if (unlikely(d_is_negative(d))) {
dput(d);
err = -ENOENT;
- goto out;
+ goto out_err1;
}
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(d));
dput(d);
}
-out:
+
+out_err1:
+ mnt_drop_write(path.mnt);
+out_err2:
done_path_create(&path, dentry);
if (err)
pr_err("mkdir(%s): creation failed (err:%d)\n", name, err);
@@ -450,7 +455,7 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
memcpy(&stream_buf[*pos], buf, count);
err = ksmbd_vfs_setxattr(idmap,
- fp->filp->f_path.dentry,
+ &fp->filp->f_path,
fp->stream.name,
(void *)stream_buf,
size,
@@ -582,54 +587,37 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
*
* Return: 0 on success, otherwise error
*/
-int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
+int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
{
struct mnt_idmap *idmap;
- struct path path;
- struct dentry *parent;
+ struct dentry *parent = path->dentry->d_parent;
int err;
if (ksmbd_override_fsids(work))
return -ENOMEM;
- err = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS, &path, false);
- if (err) {
- ksmbd_debug(VFS, "can't get %s, err %d\n", name, err);
- ksmbd_revert_fsids(work);
- return err;
- }
-
- idmap = mnt_idmap(path.mnt);
- parent = dget_parent(path.dentry);
- err = ksmbd_vfs_lock_parent(idmap, parent, path.dentry);
- if (err) {
- dput(parent);
- path_put(&path);
- ksmbd_revert_fsids(work);
- return err;
- }
-
- if (!d_inode(path.dentry)->i_nlink) {
+ if (!d_inode(path->dentry)->i_nlink) {
err = -ENOENT;
goto out_err;
}
- if (S_ISDIR(d_inode(path.dentry)->i_mode)) {
- err = vfs_rmdir(idmap, d_inode(parent), path.dentry);
+ err = mnt_want_write(path->mnt);
+ if (err)
+ goto out_err;
+
+ idmap = mnt_idmap(path->mnt);
+ if (S_ISDIR(d_inode(path->dentry)->i_mode)) {
+ err = vfs_rmdir(idmap, d_inode(parent), path->dentry);
if (err && err != -ENOTEMPTY)
- ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
- err);
+ ksmbd_debug(VFS, "rmdir failed, err %d\n", err);
} else {
- err = vfs_unlink(idmap, d_inode(parent), path.dentry, NULL);
+ err = vfs_unlink(idmap, d_inode(parent), path->dentry, NULL);
if (err)
- ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
- err);
+ ksmbd_debug(VFS, "unlink failed, err %d\n", err);
}
+ mnt_drop_write(path->mnt);
out_err:
- inode_unlock(d_inode(parent));
- dput(parent);
- path_put(&path);
ksmbd_revert_fsids(work);
return err;
}
@@ -673,11 +661,16 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
goto out3;
}
+ err = mnt_want_write(newpath.mnt);
+ if (err)
+ goto out3;
+
err = vfs_link(oldpath.dentry, mnt_idmap(newpath.mnt),
d_inode(newpath.dentry),
dentry, NULL);
if (err)
ksmbd_debug(VFS, "vfs_link failed err %d\n", err);
+ mnt_drop_write(newpath.mnt);
out3:
done_path_create(&newpath, dentry);
@@ -688,149 +681,120 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
return err;
}
-static int ksmbd_validate_entry_in_use(struct dentry *src_dent)
+int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
+ char *newname, int flags)
{
- struct dentry *dst_dent;
+ struct dentry *old_parent, *new_dentry, *trap;
+ struct dentry *old_child = old_path->dentry;
+ struct path new_path;
+ struct qstr new_last;
+ struct renamedata rd;
+ struct filename *to;
+ struct ksmbd_share_config *share_conf = work->tcon->share_conf;
+ struct ksmbd_file *parent_fp;
+ int new_type;
+ int err, lookup_flags = LOOKUP_NO_SYMLINKS;
+
+ if (ksmbd_override_fsids(work))
+ return -ENOMEM;
- spin_lock(&src_dent->d_lock);
- list_for_each_entry(dst_dent, &src_dent->d_subdirs, d_child) {
- struct ksmbd_file *child_fp;
+ to = getname_kernel(newname);
+ if (IS_ERR(to)) {
+ err = PTR_ERR(to);
+ goto revert_fsids;
+ }
- if (d_really_is_negative(dst_dent))
- continue;
+retry:
+ err = vfs_path_parent_lookup(to, lookup_flags | LOOKUP_BENEATH,
+ &new_path, &new_last, &new_type,
+ &share_conf->vfs_path);
+ if (err)
+ goto out1;
- child_fp = ksmbd_lookup_fd_inode(d_inode(dst_dent));
- if (child_fp) {
- spin_unlock(&src_dent->d_lock);
- ksmbd_debug(VFS, "Forbid rename, sub file/dir is in use\n");
- return -EACCES;
- }
+ if (old_path->mnt != new_path.mnt) {
+ err = -EXDEV;
+ goto out2;
}
- spin_unlock(&src_dent->d_lock);
- return 0;
-}
+ err = mnt_want_write(old_path->mnt);
+ if (err)
+ goto out2;
-static int __ksmbd_vfs_rename(struct ksmbd_work *work,
- struct mnt_idmap *src_idmap,
- struct dentry *src_dent_parent,
- struct dentry *src_dent,
- struct mnt_idmap *dst_idmap,
- struct dentry *dst_dent_parent,
- struct dentry *trap_dent,
- char *dst_name)
-{
- struct dentry *dst_dent;
- int err;
+ trap = lock_rename_child(old_child, new_path.dentry);
- if (!work->tcon->posix_extensions) {
- err = ksmbd_validate_entry_in_use(src_dent);
- if (err)
- return err;
+ old_parent = dget(old_child->d_parent);
+ if (d_unhashed(old_child)) {
+ err = -EINVAL;
+ goto out3;
}
- if (d_really_is_negative(src_dent_parent))
- return -ENOENT;
- if (d_really_is_negative(dst_dent_parent))
- return -ENOENT;
- if (d_really_is_negative(src_dent))
- return -ENOENT;
- if (src_dent == trap_dent)
- return -EINVAL;
-
- if (ksmbd_override_fsids(work))
- return -ENOMEM;
+ parent_fp = ksmbd_lookup_fd_inode(d_inode(old_child->d_parent));
+ if (parent_fp) {
+ if (parent_fp->daccess & FILE_DELETE_LE) {
+ pr_err("parent dir is opened with delete access\n");
+ err = -ESHARE;
+ ksmbd_fd_put(work, parent_fp);
+ goto out3;
+ }
+ ksmbd_fd_put(work, parent_fp);
+ }
- dst_dent = lookup_one(dst_idmap, dst_name,
- dst_dent_parent, strlen(dst_name));
- err = PTR_ERR(dst_dent);
- if (IS_ERR(dst_dent)) {
- pr_err("lookup failed %s [%d]\n", dst_name, err);
- goto out;
+ new_dentry = lookup_one_qstr_excl(&new_last, new_path.dentry,
+ lookup_flags | LOOKUP_RENAME_TARGET);
+ if (IS_ERR(new_dentry)) {
+ err = PTR_ERR(new_dentry);
+ goto out3;
}
- err = -ENOTEMPTY;
- if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
- struct renamedata rd = {
- .old_mnt_idmap = src_idmap,
- .old_dir = d_inode(src_dent_parent),
- .old_dentry = src_dent,
- .new_mnt_idmap = dst_idmap,
- .new_dir = d_inode(dst_dent_parent),
- .new_dentry = dst_dent,
- };
- err = vfs_rename(&rd);
+ if (d_is_symlink(new_dentry)) {
+ err = -EACCES;
+ goto out4;
}
- if (err)
- pr_err("vfs_rename failed err %d\n", err);
- if (dst_dent)
- dput(dst_dent);
-out:
- ksmbd_revert_fsids(work);
- return err;
-}
-int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
- char *newname)
-{
- struct mnt_idmap *idmap;
- struct path dst_path;
- struct dentry *src_dent_parent, *dst_dent_parent;
- struct dentry *src_dent, *trap_dent, *src_child;
- char *dst_name;
- int err;
+ if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) {
+ err = -EEXIST;
+ goto out4;
+ }
- dst_name = extract_last_component(newname);
- if (!dst_name) {
- dst_name = newname;
- newname = "";
+ if (old_child == trap) {
+ err = -EINVAL;
+ goto out4;
}
- src_dent_parent = dget_parent(fp->filp->f_path.dentry);
- src_dent = fp->filp->f_path.dentry;
+ if (new_dentry == trap) {
+ err = -ENOTEMPTY;
+ goto out4;
+ }
+
+ rd.old_mnt_idmap = mnt_idmap(old_path->mnt),
+ rd.old_dir = d_inode(old_parent),
+ rd.old_dentry = old_child,
+ rd.new_mnt_idmap = mnt_idmap(new_path.mnt),
+ rd.new_dir = new_path.dentry->d_inode,
+ rd.new_dentry = new_dentry,
+ rd.flags = flags,
+ rd.delegated_inode = NULL,
+ err = vfs_rename(&rd);
+ if (err)
+ ksmbd_debug(VFS, "vfs_rename failed err %d\n", err);
- err = ksmbd_vfs_kern_path(work, newname,
- LOOKUP_NO_SYMLINKS | LOOKUP_DIRECTORY,
- &dst_path, false);
- if (err) {
- ksmbd_debug(VFS, "Cannot get path for %s [%d]\n", newname, err);
- goto out;
+out4:
+ dput(new_dentry);
+out3:
+ dput(old_parent);
+ unlock_rename(old_parent, new_path.dentry);
+ mnt_drop_write(old_path->mnt);
+out2:
+ path_put(&new_path);
+
+ if (retry_estale(err, lookup_flags)) {
+ lookup_flags |= LOOKUP_REVAL;
+ goto retry;
}
- dst_dent_parent = dst_path.dentry;
-
- trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
- dget(src_dent);
- dget(dst_dent_parent);
- idmap = file_mnt_idmap(fp->filp);
- src_child = lookup_one(idmap, src_dent->d_name.name, src_dent_parent,
- src_dent->d_name.len);
- if (IS_ERR(src_child)) {
- err = PTR_ERR(src_child);
- goto out_lock;
- }
-
- if (src_child != src_dent) {
- err = -ESTALE;
- dput(src_child);
- goto out_lock;
- }
- dput(src_child);
-
- err = __ksmbd_vfs_rename(work,
- idmap,
- src_dent_parent,
- src_dent,
- mnt_idmap(dst_path.mnt),
- dst_dent_parent,
- trap_dent,
- dst_name);
-out_lock:
- dput(src_dent);
- dput(dst_dent_parent);
- unlock_rename(src_dent_parent, dst_dent_parent);
- path_put(&dst_path);
-out:
- dput(src_dent_parent);
+out1:
+ putname(to);
+revert_fsids:
+ ksmbd_revert_fsids(work);
return err;
}
@@ -960,19 +924,24 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap,
* Return: 0 on success, otherwise error
*/
int ksmbd_vfs_setxattr(struct mnt_idmap *idmap,
- struct dentry *dentry, const char *attr_name,
+ const struct path *path, const char *attr_name,
void *attr_value, size_t attr_size, int flags)
{
int err;
+ err = mnt_want_write(path->mnt);
+ if (err)
+ return err;
+
err = vfs_setxattr(idmap,
- dentry,
+ path->dentry,
attr_name,
attr_value,
attr_size,
flags);
if (err)
ksmbd_debug(VFS, "setxattr failed, err %d\n", err);
+ mnt_drop_write(path->mnt);
return err;
}
@@ -1076,19 +1045,34 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
}
int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
- struct dentry *dentry, char *attr_name)
+ const struct path *path, char *attr_name)
{
- return vfs_removexattr(idmap, dentry, attr_name);
+ int err;
+
+ err = mnt_want_write(path->mnt);
+ if (err)
+ return err;
+
+ err = vfs_removexattr(idmap, path->dentry, attr_name);
+ mnt_drop_write(path->mnt);
+
+ return err;
}
-int ksmbd_vfs_unlink(struct mnt_idmap *idmap,
- struct dentry *dir, struct dentry *dentry)
+int ksmbd_vfs_unlink(struct file *filp)
{
int err = 0;
+ struct dentry *dir, *dentry = filp->f_path.dentry;
+ struct mnt_idmap *idmap = file_mnt_idmap(filp);
- err = ksmbd_vfs_lock_parent(idmap, dir, dentry);
+ err = mnt_want_write(filp->f_path.mnt);
if (err)
return err;
+
+ dir = dget_parent(dentry);
+ err = ksmbd_vfs_lock_parent(dir, dentry);
+ if (err)
+ goto out;
dget(dentry);
if (S_ISDIR(d_inode(dentry)->i_mode))
@@ -1100,6 +1084,9 @@ int ksmbd_vfs_unlink(struct mnt_idmap *idmap,
inode_unlock(d_inode(dir));
if (err)
ksmbd_debug(VFS, "failed to delete, err %d\n", err);
+out:
+ dput(dir);
+ mnt_drop_write(filp->f_path.mnt);
return err;
}
@@ -1202,7 +1189,7 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
}
/**
- * ksmbd_vfs_kern_path() - lookup a file and get path info
+ * ksmbd_vfs_kern_path_locked() - lookup a file and get path info
* @name: file path that is relative to share
* @flags: lookup flags
* @path: if lookup succeed, return path info
@@ -1210,24 +1197,20 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
*
* Return: 0 on success, otherwise error
*/
-int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
- unsigned int flags, struct path *path, bool caseless)
+int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
+ unsigned int flags, struct path *path,
+ bool caseless)
{
struct ksmbd_share_config *share_conf = work->tcon->share_conf;
int err;
+ struct path parent_path;
- flags |= LOOKUP_BENEATH;
- err = vfs_path_lookup(share_conf->vfs_path.dentry,
- share_conf->vfs_path.mnt,
- name,
- flags,
- path);
+ err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, path);
if (!err)
- return 0;
+ return err;
if (caseless) {
char *filepath;
- struct path parent;
size_t path_len, remain_len;
filepath = kstrdup(name, GFP_KERNEL);
@@ -1237,10 +1220,10 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
path_len = strlen(filepath);
remain_len = path_len;
- parent = share_conf->vfs_path;
- path_get(&parent);
+ parent_path = share_conf->vfs_path;
+ path_get(&parent_path);
- while (d_can_lookup(parent.dentry)) {
+ while (d_can_lookup(parent_path.dentry)) {
char *filename = filepath + path_len - remain_len;
char *next = strchrnul(filename, '/');
size_t filename_len = next - filename;
@@ -1249,12 +1232,11 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
if (filename_len == 0)
break;
- err = ksmbd_vfs_lookup_in_dir(&parent, filename,
+ err = ksmbd_vfs_lookup_in_dir(&parent_path, filename,
filename_len,
work->conn->um);
- path_put(&parent);
if (err)
- goto out;
+ goto out2;
next[0] = '\0';
@@ -1262,23 +1244,31 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
share_conf->vfs_path.mnt,
filepath,
flags,
- &parent);
+ path);
if (err)
- goto out;
- else if (is_last) {
- *path = parent;
- goto out;
- }
+ goto out2;
+ else if (is_last)
+ goto out1;
+ path_put(&parent_path);
+ parent_path = *path;
next[0] = '/';
remain_len -= filename_len + 1;
}
- path_put(&parent);
err = -EINVAL;
-out:
+out2:
+ path_put(&parent_path);
+out1:
kfree(filepath);
}
+
+ if (!err) {
+ err = ksmbd_vfs_lock_parent(parent_path.dentry, path->dentry);
+ if (err)
+ dput(path->dentry);
+ path_put(&parent_path);
+ }
return err;
}
@@ -1300,13 +1290,13 @@ struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
}
int ksmbd_vfs_remove_acl_xattrs(struct mnt_idmap *idmap,
- struct dentry *dentry)
+ const struct path *path)
{
char *name, *xattr_list = NULL;
ssize_t xattr_list_len;
int err = 0;
- xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
+ xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
if (xattr_list_len < 0) {
goto out;
} else if (!xattr_list_len) {
@@ -1314,6 +1304,10 @@ int ksmbd_vfs_remove_acl_xattrs(struct mnt_idmap *idmap,
goto out;
}
+ err = mnt_want_write(path->mnt);
+ if (err)
+ goto out;
+
for (name = xattr_list; name - xattr_list < xattr_list_len;
name += strlen(name) + 1) {
ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
@@ -1322,25 +1316,26 @@ int ksmbd_vfs_remove_acl_xattrs(struct mnt_idmap *idmap,
sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) ||
!strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) {
- err = vfs_remove_acl(idmap, dentry, name);
+ err = vfs_remove_acl(idmap, path->dentry, name);
if (err)
ksmbd_debug(SMB,
"remove acl xattr failed : %s\n", name);
}
}
+ mnt_drop_write(path->mnt);
+
out:
kvfree(xattr_list);
return err;
}
-int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idmap,
- struct dentry *dentry)
+int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idmap, const struct path *path)
{
char *name, *xattr_list = NULL;
ssize_t xattr_list_len;
int err = 0;
- xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
+ xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
if (xattr_list_len < 0) {
goto out;
} else if (!xattr_list_len) {
@@ -1353,7 +1348,7 @@ int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idmap,
ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) {
- err = ksmbd_vfs_remove_xattr(idmap, dentry, name);
+ err = ksmbd_vfs_remove_xattr(idmap, path, name);
if (err)
ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
}
@@ -1430,13 +1425,14 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct mnt_idmap *id
int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
struct mnt_idmap *idmap,
- struct dentry *dentry,
+ const struct path *path,
struct smb_ntsd *pntsd, int len)
{
int rc;
struct ndr sd_ndr = {0}, acl_ndr = {0};
struct xattr_ntacl acl = {0};
struct xattr_smb_acl *smb_acl, *def_smb_acl = NULL;
+ struct dentry *dentry = path->dentry;
struct inode *inode = d_inode(dentry);
acl.version = 4;
@@ -1488,7 +1484,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
goto out;
}
- rc = ksmbd_vfs_setxattr(idmap, dentry,
+ rc = ksmbd_vfs_setxattr(idmap, path,
XATTR_NAME_SD, sd_ndr.data,
sd_ndr.offset, 0);
if (rc < 0)
@@ -1578,7 +1574,7 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
}
int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap,
- struct dentry *dentry,
+ const struct path *path,
struct xattr_dos_attrib *da)
{
struct ndr n;
@@ -1588,7 +1584,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap,
if (err)
return err;
- err = ksmbd_vfs_setxattr(idmap, dentry, XATTR_NAME_DOS_ATTRIBUTE,
+ err = ksmbd_vfs_setxattr(idmap, path, XATTR_NAME_DOS_ATTRIBUTE,
(void *)n.data, n.offset, 0);
if (err)
ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
@@ -1825,10 +1821,11 @@ void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock)
}
int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap,
- struct dentry *dentry)
+ struct path *path)
{
struct posix_acl_state acl_state;
struct posix_acl *acls;
+ struct dentry *dentry = path->dentry;
struct inode *inode = d_inode(dentry);
int rc;
@@ -1858,6 +1855,11 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap,
return -ENOMEM;
}
posix_state_to_acl(&acl_state, acls->a_entries);
+
+ rc = mnt_want_write(path->mnt);
+ if (rc)
+ goto out_err;
+
rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
@@ -1869,16 +1871,20 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap,
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
rc);
}
+ mnt_drop_write(path->mnt);
+
+out_err:
free_acl_state(&acl_state);
posix_acl_release(acls);
return rc;
}
int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap,
- struct dentry *dentry, struct inode *parent_inode)
+ struct path *path, struct inode *parent_inode)
{
struct posix_acl *acls;
struct posix_acl_entry *pace;
+ struct dentry *dentry = path->dentry;
struct inode *inode = d_inode(dentry);
int rc, i;
@@ -1897,6 +1903,10 @@ int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap,
}
}
+ rc = mnt_want_write(path->mnt);
+ if (rc)
+ goto out_err;
+
rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls);
if (rc < 0)
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
@@ -1908,6 +1918,9 @@ int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap,
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
rc);
}
+ mnt_drop_write(path->mnt);
+
+out_err:
posix_acl_release(acls);
return rc;
}
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
index 9d676ab0cd25..8c0931d4d531 100644
--- a/fs/ksmbd/vfs.h
+++ b/fs/ksmbd/vfs.h
@@ -71,9 +71,7 @@ struct ksmbd_kstat {
__le32 file_attributes;
};
-int ksmbd_vfs_lock_parent(struct mnt_idmap *idmap, struct dentry *parent,
- struct dentry *child);
-int ksmbd_vfs_may_delete(struct mnt_idmap *idmap, struct dentry *dentry);
+int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child);
int ksmbd_vfs_query_maximal_access(struct mnt_idmap *idmap,
struct dentry *dentry, __le32 *daccess);
int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
@@ -84,12 +82,12 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
char *buf, size_t count, loff_t *pos, bool sync,
ssize_t *written);
int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id);
-int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name);
+int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path);
int ksmbd_vfs_link(struct ksmbd_work *work,
const char *oldname, const char *newname);
int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat);
-int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
- char *newname);
+int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
+ char *newname, int flags);
int ksmbd_vfs_truncate(struct ksmbd_work *work,
struct ksmbd_file *fp, loff_t size);
struct srv_copychunk;
@@ -110,15 +108,15 @@ ssize_t ksmbd_vfs_casexattr_len(struct mnt_idmap *idmap,
struct dentry *dentry, char *attr_name,
int attr_name_len);
int ksmbd_vfs_setxattr(struct mnt_idmap *idmap,
- struct dentry *dentry, const char *attr_name,
+ const struct path *path, const char *attr_name,
void *attr_value, size_t attr_size, int flags);
int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
size_t *xattr_stream_name_size, int s_type);
int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
- struct dentry *dentry, char *attr_name);
-int ksmbd_vfs_kern_path(struct ksmbd_work *work,
- char *name, unsigned int flags, struct path *path,
- bool caseless);
+ const struct path *path, char *attr_name);
+int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
+ unsigned int flags, struct path *path,
+ bool caseless);
struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
const char *name,
unsigned int flags,
@@ -131,8 +129,7 @@ struct file_allocated_range_buffer;
int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
struct file_allocated_range_buffer *ranges,
unsigned int in_count, unsigned int *out_count);
-int ksmbd_vfs_unlink(struct mnt_idmap *idmap, struct dentry *dir,
- struct dentry *dentry);
+int ksmbd_vfs_unlink(struct file *filp);
void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat);
int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
struct mnt_idmap *idmap,
@@ -142,26 +139,25 @@ void ksmbd_vfs_posix_lock_wait(struct file_lock *flock);
int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout);
void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock);
int ksmbd_vfs_remove_acl_xattrs(struct mnt_idmap *idmap,
- struct dentry *dentry);
-int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idmap,
- struct dentry *dentry);
+ const struct path *path);
+int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idmap, const struct path *path);
int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
struct mnt_idmap *idmap,
- struct dentry *dentry,
+ const struct path *path,
struct smb_ntsd *pntsd, int len);
int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
struct mnt_idmap *idmap,
struct dentry *dentry,
struct smb_ntsd **pntsd);
int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap,
- struct dentry *dentry,
+ const struct path *path,
struct xattr_dos_attrib *da);
int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap,
struct dentry *dentry,
struct xattr_dos_attrib *da);
int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap,
- struct dentry *dentry);
+ struct path *path);
int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap,
- struct dentry *dentry,
+ struct path *path,
struct inode *parent_inode);
#endif /* __KSMBD_VFS_H__ */
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
index 054a7d2e0f48..f41f8d6108ce 100644
--- a/fs/ksmbd/vfs_cache.c
+++ b/fs/ksmbd/vfs_cache.c
@@ -244,7 +244,6 @@ void ksmbd_release_inode_hash(void)
static void __ksmbd_inode_close(struct ksmbd_file *fp)
{
- struct dentry *dir, *dentry;
struct ksmbd_inode *ci = fp->f_ci;
int err;
struct file *filp;
@@ -253,7 +252,7 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) {
ci->m_flags &= ~S_DEL_ON_CLS_STREAM;
err = ksmbd_vfs_remove_xattr(file_mnt_idmap(filp),
- filp->f_path.dentry,
+ &filp->f_path,
fp->stream.name);
if (err)
pr_err("remove xattr failed : %s\n",
@@ -263,11 +262,9 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
if (atomic_dec_and_test(&ci->m_count)) {
write_lock(&ci->m_lock);
if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
- dentry = filp->f_path.dentry;
- dir = dentry->d_parent;
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
write_unlock(&ci->m_lock);
- ksmbd_vfs_unlink(file_mnt_idmap(filp), dir, dentry);
+ ksmbd_vfs_unlink(filp);
write_lock(&ci->m_lock);
}
write_unlock(&ci->m_lock);
diff --git a/fs/namei.c b/fs/namei.c
index edfedfbccaef..c1d59ae5af83 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -254,6 +254,7 @@ getname_kernel(const char * filename)
return result;
}
+EXPORT_SYMBOL(getname_kernel);
void putname(struct filename *name)
{
@@ -271,6 +272,7 @@ void putname(struct filename *name)
} else
__putname(name);
}
+EXPORT_SYMBOL(putname);
/**
* check_acl - perform ACL permission checking
@@ -1581,8 +1583,9 @@ static struct dentry *lookup_dcache(const struct qstr *name,
* when directory is guaranteed to have no in-lookup children
* at all.
*/
-static struct dentry *__lookup_hash(const struct qstr *name,
- struct dentry *base, unsigned int flags)
+struct dentry *lookup_one_qstr_excl(const struct qstr *name,
+ struct dentry *base,
+ unsigned int flags)
{
struct dentry *dentry = lookup_dcache(name, base, flags);
struct dentry *old;
@@ -1606,6 +1609,7 @@ static struct dentry *__lookup_hash(const struct qstr *name,
}
return dentry;
}
+EXPORT_SYMBOL(lookup_one_qstr_excl);
static struct dentry *lookup_fast(struct nameidata *nd)
{
@@ -2532,16 +2536,17 @@ static int path_parentat(struct nameidata *nd, unsigned flags,
}
/* Note: this does not consume "name" */
-static int filename_parentat(int dfd, struct filename *name,
- unsigned int flags, struct path *parent,
- struct qstr *last, int *type)
+static int __filename_parentat(int dfd, struct filename *name,
+ unsigned int flags, struct path *parent,
+ struct qstr *last, int *type,
+ const struct path *root)
{
int retval;
struct nameidata nd;
if (IS_ERR(name))
return PTR_ERR(name);
- set_nameidata(&nd, dfd, name, NULL);
+ set_nameidata(&nd, dfd, name, root);
retval = path_parentat(&nd, flags | LOOKUP_RCU, parent);
if (unlikely(retval == -ECHILD))
retval = path_parentat(&nd, flags, parent);
@@ -2556,6 +2561,13 @@ static int filename_parentat(int dfd, struct filename *name,
return retval;
}
+static int filename_parentat(int dfd, struct filename *name,
+ unsigned int flags, struct path *parent,
+ struct qstr *last, int *type)
+{
+ return __filename_parentat(dfd, name, flags, parent, last, type, NULL);
+}
+
/* does lookup, returns the object with parent locked */
static struct dentry *__kern_path_locked(struct filename *name, struct path *path)
{
@@ -2571,7 +2583,7 @@ static struct dentry *__kern_path_locked(struct filename *name, struct path *pat
return ERR_PTR(-EINVAL);
}
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
- d = __lookup_hash(&last, path->dentry, 0);
+ d = lookup_one_qstr_excl(&last, path->dentry, 0);
if (IS_ERR(d)) {
inode_unlock(path->dentry->d_inode);
path_put(path);
@@ -2599,6 +2611,24 @@ int kern_path(const char *name, unsigned int flags, struct path *path)
}
EXPORT_SYMBOL(kern_path);
+/**
+ * vfs_path_parent_lookup - lookup a parent path relative to a dentry-vfsmount pair
+ * @filename: filename structure
+ * @flags: lookup flags
+ * @parent: pointer to struct path to fill
+ * @last: last component
+ * @type: type of the last component
+ * @root: pointer to struct path of the base directory
+ */
+int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
+ struct path *parent, struct qstr *last, int *type,
+ const struct path *root)
+{
+ return __filename_parentat(AT_FDCWD, filename, flags, parent, last,
+ type, root);
+}
+EXPORT_SYMBOL(vfs_path_parent_lookup);
+
/**
* vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair
* @dentry: pointer to dentry of the base directory
@@ -2980,20 +3010,10 @@ static inline int may_create(struct mnt_idmap *idmap,
return inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
}
-/*
- * p1 and p2 should be directories on the same fs.
- */
-struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
+static struct dentry *lock_two_directories(struct dentry *p1, struct dentry *p2)
{
struct dentry *p;
- if (p1 == p2) {
- inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
- return NULL;
- }
-
- mutex_lock(&p1->d_sb->s_vfs_rename_mutex);
-
p = d_ancestor(p2, p1);
if (p) {
inode_lock_nested(p2->d_inode, I_MUTEX_PARENT);
@@ -3012,8 +3032,64 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
inode_lock_nested(p2->d_inode, I_MUTEX_PARENT2);
return NULL;
}
+
+/*
+ * p1 and p2 should be directories on the same fs.
+ */
+struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
+{
+ if (p1 == p2) {
+ inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
+ return NULL;
+ }
+
+ mutex_lock(&p1->d_sb->s_vfs_rename_mutex);
+ return lock_two_directories(p1, p2);
+}
EXPORT_SYMBOL(lock_rename);
+/*
+ * c1 and p2 should be on the same fs.
+ */
+struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2)
+{
+ if (READ_ONCE(c1->d_parent) == p2) {
+ /*
+ * hopefully won't need to touch ->s_vfs_rename_mutex at all.
+ */
+ inode_lock_nested(p2->d_inode, I_MUTEX_PARENT);
+ /*
+ * now that p2 is locked, nobody can move in or out of it,
+ * so the test below is safe.
+ */
+ if (likely(c1->d_parent == p2))
+ return NULL;
+
+ /*
+ * c1 got moved out of p2 while we'd been taking locks;
+ * unlock and fall back to slow case.
+ */
+ inode_unlock(p2->d_inode);
+ }
+
+ mutex_lock(&c1->d_sb->s_vfs_rename_mutex);
+ /*
+ * nobody can move out of any directories on this fs.
+ */
+ if (likely(c1->d_parent != p2))
+ return lock_two_directories(c1->d_parent, p2);
+
+ /*
+ * c1 got moved into p2 while we were taking locks;
+ * we need p2 locked and ->s_vfs_rename_mutex unlocked,
+ * for consistency with lock_rename().
+ */
+ inode_lock_nested(p2->d_inode, I_MUTEX_PARENT);
+ mutex_unlock(&c1->d_sb->s_vfs_rename_mutex);
+ return NULL;
+}
+EXPORT_SYMBOL(lock_rename_child);
+
void unlock_rename(struct dentry *p1, struct dentry *p2)
{
inode_unlock(p1->d_inode);
@@ -3806,7 +3882,8 @@ static struct dentry *filename_create(int dfd, struct filename *name,
if (last.name[last.len] && !want_dir)
create_flags = 0;
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
- dentry = __lookup_hash(&last, path->dentry, reval_flag | create_flags);
+ dentry = lookup_one_qstr_excl(&last, path->dentry,
+ reval_flag | create_flags);
if (IS_ERR(dentry))
goto unlock;
@@ -4166,7 +4243,7 @@ int do_rmdir(int dfd, struct filename *name)
goto exit2;
inode_lock_nested(path.dentry->d_inode, I_MUTEX_PARENT);
- dentry = __lookup_hash(&last, path.dentry, lookup_flags);
+ dentry = lookup_one_qstr_excl(&last, path.dentry, lookup_flags);
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto exit3;
@@ -4299,7 +4376,7 @@ int do_unlinkat(int dfd, struct filename *name)
goto exit2;
retry_deleg:
inode_lock_nested(path.dentry->d_inode, I_MUTEX_PARENT);
- dentry = __lookup_hash(&last, path.dentry, lookup_flags);
+ dentry = lookup_one_qstr_excl(&last, path.dentry, lookup_flags);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
@@ -4863,7 +4940,8 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
retry_deleg:
trap = lock_rename(new_path.dentry, old_path.dentry);
- old_dentry = __lookup_hash(&old_last, old_path.dentry, lookup_flags);
+ old_dentry = lookup_one_qstr_excl(&old_last, old_path.dentry,
+ lookup_flags);
error = PTR_ERR(old_dentry);
if (IS_ERR(old_dentry))
goto exit3;
@@ -4871,7 +4949,8 @@ int do_renameat2(int olddfd, struct filename *from, int newdfd,
error = -ENOENT;
if (d_is_negative(old_dentry))
goto exit4;
- new_dentry = __lookup_hash(&new_last, new_path.dentry, lookup_flags | target_flags);
+ new_dentry = lookup_one_qstr_excl(&new_last, new_path.dentry,
+ lookup_flags | target_flags);
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
goto exit4;
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 41ccd43cd979..afbf4bcefaf2 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -370,7 +370,15 @@ void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
struct folio *folio = fbatch.folios[i];
folio_lock(folio);
- nilfs_clear_dirty_page(&folio->page, silent);
+
+ /*
+ * This folio may have been removed from the address
+ * space by truncation or invalidation when the lock
+ * was acquired. Skip processing in that case.
+ */
+ if (likely(folio->mapping == mapping))
+ nilfs_clear_dirty_page(&folio->page, silent);
+
folio_unlock(folio);
}
folio_batch_release(&fbatch);
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c
index 1362ccb64ec7..6e59dc19a732 100644
--- a/fs/nilfs2/segbuf.c
+++ b/fs/nilfs2/segbuf.c
@@ -101,6 +101,12 @@ int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *segbuf)
if (unlikely(!bh))
return -ENOMEM;
+ lock_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ memset(bh->b_data, 0, bh->b_size);
+ set_buffer_uptodate(bh);
+ }
+ unlock_buffer(bh);
nilfs_segbuf_add_segsum_buffer(segbuf, bh);
return 0;
}
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index ac949fd7603f..c2553024bd25 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -981,10 +981,13 @@ static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci,
unsigned int isz, srsz;
bh_sr = NILFS_LAST_SEGBUF(&sci->sc_segbufs)->sb_super_root;
+
+ lock_buffer(bh_sr);
raw_sr = (struct nilfs_super_root *)bh_sr->b_data;
isz = nilfs->ns_inode_size;
srsz = NILFS_SR_BYTES(isz);
+ raw_sr->sr_sum = 0; /* Ensure initialization within this update */
raw_sr->sr_bytes = cpu_to_le16(srsz);
raw_sr->sr_nongc_ctime
= cpu_to_le64(nilfs_doing_gc() ?
@@ -998,6 +1001,8 @@ static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci,
nilfs_write_inode_common(nilfs->ns_sufile, (void *)raw_sr +
NILFS_SR_SUFILE_OFFSET(isz), 1);
memset((void *)raw_sr + srsz, 0, nilfs->ns_blocksize - srsz);
+ set_buffer_uptodate(bh_sr);
+ unlock_buffer(bh_sr);
}
static void nilfs_redirty_inodes(struct list_head *head)
@@ -1780,6 +1785,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
list_for_each_entry(segbuf, logs, sb_list) {
list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
b_assoc_buffers) {
+ clear_buffer_uptodate(bh);
if (bh->b_page != bd_page) {
if (bd_page)
end_page_writeback(bd_page);
@@ -1791,6 +1797,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
b_assoc_buffers) {
clear_buffer_async_write(bh);
if (bh == segbuf->sb_super_root) {
+ clear_buffer_uptodate(bh);
if (bh->b_page != bd_page) {
end_page_writeback(bd_page);
bd_page = bh->b_page;
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 77f1e5778d1c..9ba4933087af 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -372,10 +372,31 @@ static int nilfs_move_2nd_super(struct super_block *sb, loff_t sb2off)
goto out;
}
nsbp = (void *)nsbh->b_data + offset;
- memset(nsbp, 0, nilfs->ns_blocksize);
+ lock_buffer(nsbh);
if (sb2i >= 0) {
+ /*
+ * The position of the second superblock only changes by 4KiB,
+ * which is larger than the maximum superblock data size
+ * (= 1KiB), so there is no need to use memmove() to allow
+ * overlap between source and destination.
+ */
memcpy(nsbp, nilfs->ns_sbp[sb2i], nilfs->ns_sbsize);
+
+ /*
+ * Zero fill after copy to avoid overwriting in case of move
+ * within the same block.
+ */
+ memset(nsbh->b_data, 0, offset);
+ memset((void *)nsbp + nilfs->ns_sbsize, 0,
+ nsbh->b_size - offset - nilfs->ns_sbsize);
+ } else {
+ memset(nsbh->b_data, 0, nsbh->b_size);
+ }
+ set_buffer_uptodate(nsbh);
+ unlock_buffer(nsbh);
+
+ if (sb2i >= 0) {
brelse(nilfs->ns_sbh[sb2i]);
nilfs->ns_sbh[sb2i] = nsbh;
nilfs->ns_sbp[sb2i] = nsbp;
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 8e364cbdd14a..651c0fe56757 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -761,6 +761,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_event_status
*event_status))
ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number))
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_hw_disable_all_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index d1f57e4868ed..7058b01e9f14 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -839,6 +839,9 @@
#ifdef CONFIG_UNWINDER_ORC
#define ORC_UNWIND_TABLE \
+ .orc_header : AT(ADDR(.orc_header) - LOAD_OFFSET) { \
+ BOUNDED_SECTION_BY(.orc_header, _orc_header) \
+ } \
. = ALIGN(4); \
.orc_unwind_ip : AT(ADDR(.orc_unwind_ip) - LOAD_OFFSET) { \
BOUNDED_SECTION_BY(.orc_unwind_ip, _orc_unwind_ip) \
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index ccd8a512d854..b769ff6b00fd 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -244,6 +244,14 @@ struct gpio_irq_chip {
*/
bool initialized;
+ /**
+ * @domain_is_allocated_externally:
+ *
+ * True it the irq_domain was allocated outside of gpiolib, in which
+ * case gpiolib won't free the irq_domain itself.
+ */
+ bool domain_is_allocated_externally;
+
/**
* @init_hw: optional routine to initialize hardware before
* an IRQ chip will be added. This is quite useful when
diff --git a/include/linux/libata.h b/include/linux/libata.h
index a759dfbdcc91..bb5dda3ec2db 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -836,7 +836,7 @@ struct ata_port {
struct mutex scsi_scan_mutex;
struct delayed_work hotplug_task;
- struct work_struct scsi_rescan_task;
+ struct delayed_work scsi_rescan_task;
unsigned int hsm_task_state;
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 0d797f3367ca..1463cbda4888 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -57,12 +57,20 @@ static inline int user_path_at(int dfd, const char __user *name, unsigned flags,
return user_path_at_empty(dfd, name, flags, path, NULL);
}
+struct dentry *lookup_one_qstr_excl(const struct qstr *name,
+ struct dentry *base,
+ unsigned int flags);
extern int kern_path(const char *, unsigned, struct path *);
extern struct dentry *kern_path_create(int, const char *, struct path *, unsigned int);
extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
extern void done_path_create(struct path *, struct dentry *);
extern struct dentry *kern_path_locked(const char *, struct path *);
+int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
+ struct path *parent, struct qstr *last, int *type,
+ const struct path *root);
+int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *,
+ unsigned int, struct path *);
extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int);
extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
@@ -81,6 +89,7 @@ extern int follow_down(struct path *path, unsigned int flags);
extern int follow_up(struct path *);
extern struct dentry *lock_rename(struct dentry *, struct dentry *);
+extern struct dentry *lock_rename_child(struct dentry *, struct dentry *);
extern void unlock_rename(struct dentry *, struct dentry *);
extern int __must_check nd_jump_link(const struct path *path);
diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h
index 3c01c2bf84f5..505c908dbb81 100644
--- a/include/linux/regulator/pca9450.h
+++ b/include/linux/regulator/pca9450.h
@@ -196,11 +196,11 @@ enum {
/* PCA9450_REG_LDO3_VOLT bits */
#define LDO3_EN_MASK 0xC0
-#define LDO3OUT_MASK 0x0F
+#define LDO3OUT_MASK 0x1F
/* PCA9450_REG_LDO4_VOLT bits */
#define LDO4_EN_MASK 0xC0
-#define LDO4OUT_MASK 0x0F
+#define LDO4OUT_MASK 0x1F
/* PCA9450_REG_LDO5_VOLT bits */
#define LDO5L_EN_MASK 0xC0
diff --git a/include/net/dsa.h b/include/net/dsa.h
index a15f17a38eca..def06ef676dd 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -973,6 +973,14 @@ struct dsa_switch_ops {
struct phy_device *phy);
void (*port_disable)(struct dsa_switch *ds, int port);
+ /*
+ * Compatibility between device trees defining multiple CPU ports and
+ * drivers which are not OK to use by default the numerically smallest
+ * CPU port of a switch for its local ports. This can return NULL,
+ * meaning "don't know/don't care".
+ */
+ struct dsa_port *(*preferred_default_local_cpu_port)(struct dsa_switch *ds);
+
/*
* Port's MAC EEE settings
*/
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 300bce4d67ce..730c63ceee56 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -472,7 +472,8 @@ struct nft_set_ops {
int (*init)(const struct nft_set *set,
const struct nft_set_desc *desc,
const struct nlattr * const nla[]);
- void (*destroy)(const struct nft_set *set);
+ void (*destroy)(const struct nft_ctx *ctx,
+ const struct nft_set *set);
void (*gc_init)(const struct nft_set *set);
unsigned int elemsize;
@@ -809,6 +810,8 @@ int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_expr *expr_array[]);
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
bool destroy_expr);
+void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set, void *elem);
/**
* struct nft_set_gc_batch_head - nf_tables set garbage collection batch
@@ -901,6 +904,7 @@ struct nft_expr_type {
enum nft_trans_phase {
NFT_TRANS_PREPARE,
+ NFT_TRANS_PREPARE_ERROR,
NFT_TRANS_ABORT,
NFT_TRANS_COMMIT,
NFT_TRANS_RELEASE
@@ -1009,7 +1013,10 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
return (void *)&rule->data[rule->dlen];
}
-void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule);
+void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule);
+void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule,
+ enum nft_trans_phase phase);
+void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule);
static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
struct nft_regs *regs,
@@ -1092,6 +1099,8 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
const struct nft_set_iter *iter,
struct nft_set_elem *elem);
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
+int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
+void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
enum nft_chain_types {
NFT_CHAIN_T_DEFAULT = 0,
@@ -1128,11 +1137,17 @@ int nft_chain_validate_dependency(const struct nft_chain *chain,
int nft_chain_validate_hooks(const struct nft_chain *chain,
unsigned int hook_flags);
+static inline bool nft_chain_binding(const struct nft_chain *chain)
+{
+ return chain->flags & NFT_CHAIN_BINDING;
+}
+
static inline bool nft_chain_is_bound(struct nft_chain *chain)
{
return (chain->flags & NFT_CHAIN_BINDING) && chain->bound;
}
+int nft_chain_add(struct nft_table *table, struct nft_chain *chain);
void nft_chain_del(struct nft_chain *chain);
void nf_tables_chain_destroy(struct nft_ctx *ctx);
@@ -1550,6 +1565,7 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
* struct nft_trans - nf_tables object update in transaction
*
* @list: used internally
+ * @binding_list: list of objects with possible bindings
* @msg_type: message type
* @put_net: ctx->net needs to be put
* @ctx: transaction context
@@ -1557,6 +1573,7 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
*/
struct nft_trans {
struct list_head list;
+ struct list_head binding_list;
int msg_type;
bool put_net;
struct nft_ctx ctx;
@@ -1567,6 +1584,7 @@ struct nft_trans_rule {
struct nft_rule *rule;
struct nft_flow_rule *flow;
u32 rule_id;
+ bool bound;
};
#define nft_trans_rule(trans) \
@@ -1575,6 +1593,8 @@ struct nft_trans_rule {
(((struct nft_trans_rule *)trans->data)->flow)
#define nft_trans_rule_id(trans) \
(((struct nft_trans_rule *)trans->data)->rule_id)
+#define nft_trans_rule_bound(trans) \
+ (((struct nft_trans_rule *)trans->data)->bound)
struct nft_trans_set {
struct nft_set *set;
@@ -1599,15 +1619,19 @@ struct nft_trans_set {
(((struct nft_trans_set *)trans->data)->gc_int)
struct nft_trans_chain {
+ struct nft_chain *chain;
bool update;
char *name;
struct nft_stats __percpu *stats;
u8 policy;
+ bool bound;
u32 chain_id;
struct nft_base_chain *basechain;
struct list_head hook_list;
};
+#define nft_trans_chain(trans) \
+ (((struct nft_trans_chain *)trans->data)->chain)
#define nft_trans_chain_update(trans) \
(((struct nft_trans_chain *)trans->data)->update)
#define nft_trans_chain_name(trans) \
@@ -1616,6 +1640,8 @@ struct nft_trans_chain {
(((struct nft_trans_chain *)trans->data)->stats)
#define nft_trans_chain_policy(trans) \
(((struct nft_trans_chain *)trans->data)->policy)
+#define nft_trans_chain_bound(trans) \
+ (((struct nft_trans_chain *)trans->data)->bound)
#define nft_trans_chain_id(trans) \
(((struct nft_trans_chain *)trans->data)->chain_id)
#define nft_trans_basechain(trans) \
@@ -1692,6 +1718,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
struct nftables_pernet {
struct list_head tables;
struct list_head commit_list;
+ struct list_head binding_list;
struct list_head module_list;
struct list_head notify_list;
struct mutex commit_mutex;
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 3e1f70e8e424..47ecf1d4719b 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1049,6 +1049,7 @@ struct xfrm_offload {
struct sec_path {
int len;
int olen;
+ int verified_cnt;
struct xfrm_state *xvec[XFRM_MAX_DEPTH];
struct xfrm_offload ovec[XFRM_MAX_OFFLOAD_DEPTH];
diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h
index 229118156a1f..4c15420e8965 100644
--- a/include/target/iscsi/iscsi_target_core.h
+++ b/include/target/iscsi/iscsi_target_core.h
@@ -562,12 +562,13 @@ struct iscsit_conn {
#define LOGIN_FLAGS_READ_ACTIVE 2
#define LOGIN_FLAGS_WRITE_ACTIVE 3
#define LOGIN_FLAGS_CLOSED 4
+#define LOGIN_FLAGS_WORKER_RUNNING 5
unsigned long login_flags;
struct delayed_work login_work;
struct iscsi_login *login;
struct timer_list nopin_timer;
struct timer_list nopin_response_timer;
- struct timer_list transport_timer;
+ struct timer_list login_timer;
struct task_struct *login_kworker;
/* Spinlock used for add/deleting cmd's from conn_cmd_list */
spinlock_t cmd_lock;
@@ -576,6 +577,8 @@ struct iscsit_conn {
spinlock_t nopin_timer_lock;
spinlock_t response_queue_lock;
spinlock_t state_lock;
+ spinlock_t login_timer_lock;
+ spinlock_t login_worker_lock;
/* libcrypto RX and TX contexts for crc32c */
struct ahash_request *conn_rx_hash;
struct ahash_request *conn_tx_hash;
@@ -792,7 +795,6 @@ struct iscsi_np {
enum np_thread_state_table np_thread_state;
bool enabled;
atomic_t np_reset_count;
- enum iscsi_timer_flags_table np_login_timer_flags;
u32 np_exports;
enum np_flags_table np_flags;
spinlock_t np_thread_lock;
@@ -800,7 +802,6 @@ struct iscsi_np {
struct socket *np_socket;
struct sockaddr_storage np_sockaddr;
struct task_struct *np_thread;
- struct timer_list np_login_timer;
void *np_context;
struct iscsit_transport *np_transport;
struct list_head np_list;
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 86b2a82da546..54e353c9f919 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -68,7 +68,7 @@ DECLARE_EVENT_CLASS(writeback_folio_template,
strscpy_pad(__entry->name,
bdi_dev_name(mapping ? inode_to_bdi(mapping->host) :
NULL), 32);
- __entry->ino = mapping ? mapping->host->i_ino : 0;
+ __entry->ino = (mapping && mapping->host) ? mapping->host->i_ino : 0;
__entry->index = folio->index;
),
diff --git a/io_uring/net.c b/io_uring/net.c
index 05fd285ac75a..2cf671cef0b6 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -203,7 +203,7 @@ static int io_sendmsg_copy_hdr(struct io_kiocb *req,
ret = sendmsg_copy_msghdr(&iomsg->msg, sr->umsg, sr->msg_flags,
&iomsg->free_iov);
/* save msg_control as sys_sendmsg() overwrites it */
- sr->msg_control = iomsg->msg.msg_control;
+ sr->msg_control = iomsg->msg.msg_control_user;
return ret;
}
@@ -302,7 +302,7 @@ int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
if (req_has_async_data(req)) {
kmsg = req->async_data;
- kmsg->msg.msg_control = sr->msg_control;
+ kmsg->msg.msg_control_user = sr->msg_control;
} else {
ret = io_sendmsg_copy_hdr(req, &iomsg);
if (ret)
@@ -326,6 +326,8 @@ int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK))
return io_setup_async_msg(req, kmsg, issue_flags);
if (ret > 0 && io_net_retry(sock, flags)) {
+ kmsg->msg.msg_controllen = 0;
+ kmsg->msg.msg_control = NULL;
sr->done_io += ret;
req->flags |= REQ_F_PARTIAL_IO;
return io_setup_async_msg(req, kmsg, issue_flags);
@@ -787,16 +789,19 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
flags = sr->msg_flags;
if (force_nonblock)
flags |= MSG_DONTWAIT;
- if (flags & MSG_WAITALL)
- min_ret = iov_iter_count(&kmsg->msg.msg_iter);
kmsg->msg.msg_get_inq = 1;
- if (req->flags & REQ_F_APOLL_MULTISHOT)
+ if (req->flags & REQ_F_APOLL_MULTISHOT) {
ret = io_recvmsg_multishot(sock, sr, kmsg, flags,
&mshot_finished);
- else
+ } else {
+ /* disable partial retry for recvmsg with cmsg attached */
+ if (flags & MSG_WAITALL && !kmsg->msg.msg_controllen)
+ min_ret = iov_iter_count(&kmsg->msg.msg_iter);
+
ret = __sys_recvmsg_sock(sock, &kmsg->msg, sr->umsg,
kmsg->uaddr, flags);
+ }
if (ret < min_ret) {
if (ret == -EAGAIN && force_nonblock) {
diff --git a/io_uring/poll.c b/io_uring/poll.c
index 55306e801081..e346a518dfcf 100644
--- a/io_uring/poll.c
+++ b/io_uring/poll.c
@@ -977,8 +977,9 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
struct io_hash_bucket *bucket;
struct io_kiocb *preq;
int ret2, ret = 0;
- bool locked;
+ bool locked = true;
+ io_ring_submit_lock(ctx, issue_flags);
preq = io_poll_find(ctx, true, &cd, &ctx->cancel_table, &bucket);
ret2 = io_poll_disarm(preq);
if (bucket)
@@ -990,12 +991,10 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
goto out;
}
- io_ring_submit_lock(ctx, issue_flags);
preq = io_poll_find(ctx, true, &cd, &ctx->cancel_table_locked, &bucket);
ret2 = io_poll_disarm(preq);
if (bucket)
spin_unlock(&bucket->lock);
- io_ring_submit_unlock(ctx, issue_flags);
if (ret2) {
ret = ret2;
goto out;
@@ -1019,7 +1018,7 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
if (poll_update->update_user_data)
preq->cqe.user_data = poll_update->new_user_data;
- ret2 = io_poll_add(preq, issue_flags);
+ ret2 = io_poll_add(preq, issue_flags & ~IO_URING_F_UNLOCKED);
/* successfully updated, don't complete poll request */
if (!ret2 || ret2 == -EIOCBQUEUED)
goto out;
@@ -1027,9 +1026,9 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
req_set_fail(preq);
io_req_set_res(preq, -ECANCELED, 0);
- locked = !(issue_flags & IO_URING_F_UNLOCKED);
io_req_task_complete(preq, &locked);
out:
+ io_ring_submit_unlock(ctx, issue_flags);
if (ret < 0) {
req_set_fail(req);
return ret;
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 46bce5577fb4..3cc3232f8c33 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -735,13 +735,12 @@ static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
return offset < btf->hdr.str_len;
}
-static bool __btf_name_char_ok(char c, bool first, bool dot_ok)
+static bool __btf_name_char_ok(char c, bool first)
{
if ((first ? !isalpha(c) :
!isalnum(c)) &&
c != '_' &&
- ((c == '.' && !dot_ok) ||
- c != '.'))
+ c != '.')
return false;
return true;
}
@@ -758,20 +757,20 @@ static const char *btf_str_by_offset(const struct btf *btf, u32 offset)
return NULL;
}
-static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
+static bool __btf_name_valid(const struct btf *btf, u32 offset)
{
/* offset must be valid */
const char *src = btf_str_by_offset(btf, offset);
const char *src_limit;
- if (!__btf_name_char_ok(*src, true, dot_ok))
+ if (!__btf_name_char_ok(*src, true))
return false;
/* set a limit on identifier length */
src_limit = src + KSYM_NAME_LEN;
src++;
while (*src && src < src_limit) {
- if (!__btf_name_char_ok(*src, false, dot_ok))
+ if (!__btf_name_char_ok(*src, false))
return false;
src++;
}
@@ -779,17 +778,14 @@ static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
return !*src;
}
-/* Only C-style identifier is permitted. This can be relaxed if
- * necessary.
- */
static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
{
- return __btf_name_valid(btf, offset, false);
+ return __btf_name_valid(btf, offset);
}
static bool btf_name_valid_section(const struct btf *btf, u32 offset)
{
- return __btf_name_valid(btf, offset, true);
+ return __btf_name_valid(btf, offset);
}
static const char *__btf_name_by_offset(const struct btf *btf, u32 offset)
@@ -4450,7 +4446,7 @@ static s32 btf_var_check_meta(struct btf_verifier_env *env,
}
if (!t->name_off ||
- !__btf_name_valid(env->btf, t->name_off, true)) {
+ !__btf_name_valid(env->btf, t->name_off)) {
btf_verifier_log_type(env, t, "Invalid name");
return -EINVAL;
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index adc83cb82f37..8bd5e3741d41 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -3412,6 +3412,11 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
return prog->enforce_expected_attach_type &&
prog->expected_attach_type != attach_type ?
-EINVAL : 0;
+ case BPF_PROG_TYPE_KPROBE:
+ if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI &&
+ attach_type != BPF_TRACE_KPROBE_MULTI)
+ return -EINVAL;
+ return 0;
default:
return 0;
}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 8ed149cc9f64..b03999013744 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3559,6 +3559,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
return err;
}
save_register_state(state, spi, reg, size);
+ /* Break the relation on a narrowing spill. */
+ if (fls64(reg->umax_value) > BITS_PER_BYTE * size)
+ state->stack[spi].spilled_ptr.id = 0;
} else if (!reg && !(off % BPF_REG_SIZE) && is_bpf_st_mem(insn) &&
insn->imm != 0 && env->bpf_capable) {
struct bpf_reg_state fake_reg = {};
@@ -16198,9 +16201,10 @@ static int jit_subprogs(struct bpf_verifier_env *env)
}
/* finally lock prog and jit images for all functions and
- * populate kallsysm
+ * populate kallsysm. Begin at the first subprogram, since
+ * bpf_prog_load will add the kallsyms for the main program.
*/
- for (i = 0; i < env->subprog_cnt; i++) {
+ for (i = 1; i < env->subprog_cnt; i++) {
bpf_prog_lock_ro(func[i]);
bpf_prog_kallsyms_add(func[i]);
}
@@ -16226,6 +16230,8 @@ static int jit_subprogs(struct bpf_verifier_env *env)
prog->jited = 1;
prog->bpf_func = func[0]->bpf_func;
prog->jited_len = func[0]->jited_len;
+ prog->aux->extable = func[0]->aux->extable;
+ prog->aux->num_exentries = func[0]->aux->num_exentries;
prog->aux->func = func;
prog->aux->func_cnt = env->subprog_cnt;
bpf_prog_jit_attempt_done(prog);
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index fd57c1dca1cc..dad3eacf5126 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1788,7 +1788,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
{
struct cgroup *dcgrp = &dst_root->cgrp;
struct cgroup_subsys *ss;
- int ssid, i, ret;
+ int ssid, ret;
u16 dfl_disable_ss_mask = 0;
lockdep_assert_held(&cgroup_mutex);
@@ -1832,7 +1832,8 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
struct cgroup_root *src_root = ss->root;
struct cgroup *scgrp = &src_root->cgrp;
struct cgroup_subsys_state *css = cgroup_css(scgrp, ss);
- struct css_set *cset;
+ struct css_set *cset, *cset_pos;
+ struct css_task_iter *it;
WARN_ON(!css || cgroup_css(dcgrp, ss));
@@ -1850,9 +1851,22 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
css->cgroup = dcgrp;
spin_lock_irq(&css_set_lock);
- hash_for_each(css_set_table, i, cset, hlist)
+ WARN_ON(!list_empty(&dcgrp->e_csets[ss->id]));
+ list_for_each_entry_safe(cset, cset_pos, &scgrp->e_csets[ss->id],
+ e_cset_node[ss->id]) {
list_move_tail(&cset->e_cset_node[ss->id],
&dcgrp->e_csets[ss->id]);
+ /*
+ * all css_sets of scgrp together in same order to dcgrp,
+ * patch in-flight iterators to preserve correct iteration.
+ * since the iterator is always advanced right away and
+ * finished when it->cset_pos meets it->cset_head, so only
+ * update it->cset_head is enough here.
+ */
+ list_for_each_entry(it, &cset->task_iters, iters_node)
+ if (it->cset_head == &scgrp->e_csets[ss->id])
+ it->cset_head = &dcgrp->e_csets[ss->id];
+ }
spin_unlock_irq(&css_set_lock);
if (ss->css_rstat_flush) {
diff --git a/kernel/cgroup/legacy_freezer.c b/kernel/cgroup/legacy_freezer.c
index 936473203a6b..122dacb3a443 100644
--- a/kernel/cgroup/legacy_freezer.c
+++ b/kernel/cgroup/legacy_freezer.c
@@ -108,16 +108,18 @@ static int freezer_css_online(struct cgroup_subsys_state *css)
struct freezer *freezer = css_freezer(css);
struct freezer *parent = parent_freezer(freezer);
+ cpus_read_lock();
mutex_lock(&freezer_mutex);
freezer->state |= CGROUP_FREEZER_ONLINE;
if (parent && (parent->state & CGROUP_FREEZING)) {
freezer->state |= CGROUP_FREEZING_PARENT | CGROUP_FROZEN;
- static_branch_inc(&freezer_active);
+ static_branch_inc_cpuslocked(&freezer_active);
}
mutex_unlock(&freezer_mutex);
+ cpus_read_unlock();
return 0;
}
@@ -132,14 +134,16 @@ static void freezer_css_offline(struct cgroup_subsys_state *css)
{
struct freezer *freezer = css_freezer(css);
+ cpus_read_lock();
mutex_lock(&freezer_mutex);
if (freezer->state & CGROUP_FREEZING)
- static_branch_dec(&freezer_active);
+ static_branch_dec_cpuslocked(&freezer_active);
freezer->state = 0;
mutex_unlock(&freezer_mutex);
+ cpus_read_unlock();
}
static void freezer_css_free(struct cgroup_subsys_state *css)
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 65b8658da829..e9138cd7a0f5 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -218,19 +218,8 @@ static void tick_setup_device(struct tick_device *td,
* this cpu:
*/
if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) {
- ktime_t next_p;
- u32 rem;
-
tick_do_timer_cpu = cpu;
-
- next_p = ktime_get();
- div_u64_rem(next_p, TICK_NSEC, &rem);
- if (rem) {
- next_p -= rem;
- next_p += TICK_NSEC;
- }
-
- tick_next_period = next_p;
+ tick_next_period = ktime_get();
#ifdef CONFIG_NO_HZ_FULL
/*
* The boot CPU may be nohz_full, in which case set
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index a46506f7ec6d..d6fb6a676bbb 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -161,8 +161,19 @@ static ktime_t tick_init_jiffy_update(void)
raw_spin_lock(&jiffies_lock);
write_seqcount_begin(&jiffies_seq);
/* Did we start the jiffies update yet ? */
- if (last_jiffies_update == 0)
+ if (last_jiffies_update == 0) {
+ u32 rem;
+
+ /*
+ * Ensure that the tick is aligned to a multiple of
+ * TICK_NSEC.
+ */
+ div_u64_rem(tick_next_period, TICK_NSEC, &rem);
+ if (rem)
+ tick_next_period += TICK_NSEC - rem;
+
last_jiffies_update = tick_next_period;
+ }
period = last_jiffies_update;
write_seqcount_end(&jiffies_seq);
raw_spin_unlock(&jiffies_lock);
diff --git a/mm/maccess.c b/mm/maccess.c
index 074f6b086671..518a25667323 100644
--- a/mm/maccess.c
+++ b/mm/maccess.c
@@ -5,6 +5,7 @@
#include <linux/export.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
+#include <asm/tlb.h>
bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src,
size_t size)
@@ -113,11 +114,16 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
{
long ret = -EFAULT;
- if (access_ok(src, size)) {
- pagefault_disable();
- ret = __copy_from_user_inatomic(dst, src, size);
- pagefault_enable();
- }
+
+ if (!__access_ok(src, size))
+ return ret;
+
+ if (!nmi_uaccess_okay())
+ return ret;
+
+ pagefault_disable();
+ ret = __copy_from_user_inatomic(dst, src, size);
+ pagefault_enable();
if (ret)
return -EFAULT;
diff --git a/mm/memfd.c b/mm/memfd.c
index a0a7a37e8177..0382f001e2a0 100644
--- a/mm/memfd.c
+++ b/mm/memfd.c
@@ -375,12 +375,15 @@ SYSCALL_DEFINE2(memfd_create,
inode->i_mode &= ~0111;
file_seals = memfd_file_seals_ptr(file);
- *file_seals &= ~F_SEAL_SEAL;
- *file_seals |= F_SEAL_EXEC;
+ if (file_seals) {
+ *file_seals &= ~F_SEAL_SEAL;
+ *file_seals |= F_SEAL_EXEC;
+ }
} else if (flags & MFD_ALLOW_SEALING) {
/* MFD_EXEC and MFD_ALLOW_SEALING are set */
file_seals = memfd_file_seals_ptr(file);
- *file_seals &= ~F_SEAL_SEAL;
+ if (file_seals)
+ *file_seals &= ~F_SEAL_SEAL;
}
fd_install(fd, file);
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 36351a00c0e8..498de2c2f2c4 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -838,7 +838,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
}
tlb_finish_mmu(&tlb);
- if (!error && vma_iter_end(&vmi) < end)
+ if (!error && tmp < end)
error = -ENOMEM;
out:
diff --git a/mm/usercopy.c b/mm/usercopy.c
index 4c3164beacec..83c164aba6e0 100644
--- a/mm/usercopy.c
+++ b/mm/usercopy.c
@@ -173,7 +173,7 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
return;
}
- if (is_vmalloc_addr(ptr)) {
+ if (is_vmalloc_addr(ptr) && !pagefault_disabled()) {
struct vmap_area *area = find_vmap_area(addr);
if (!area)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 31ff782d368b..f908abba4d4a 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -3046,11 +3046,20 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
* allocation request, free them via vfree() if any.
*/
if (area->nr_pages != nr_small_pages) {
- /* vm_area_alloc_pages() can also fail due to a fatal signal */
- if (!fatal_signal_pending(current))
+ /*
+ * vm_area_alloc_pages() can fail due to insufficient memory but
+ * also:-
+ *
+ * - a pending fatal signal
+ * - insufficient huge page-order pages
+ *
+ * Since we always retry allocations at order-0 in the huge page
+ * case a warning for either is spurious.
+ */
+ if (!fatal_signal_pending(current) && page_order == 0)
warn_alloc(gfp_mask, NULL,
- "vmalloc error: size %lu, page order %u, failed to allocate pages",
- area->nr_pages * PAGE_SIZE, page_order);
+ "vmalloc error: size %lu, failed to allocate pages",
+ area->nr_pages * PAGE_SIZE);
goto fail;
}
diff --git a/net/core/sock.c b/net/core/sock.c
index 3fd71f343c9f..b34c48f802e9 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1362,12 +1362,6 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
__sock_set_mark(sk, val);
break;
case SO_RCVMARK:
- if (!sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
- !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
- ret = -EPERM;
- break;
- }
-
sock_valbool_flag(sk, SOCK_RCVMARK, valbool);
break;
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index e5f156940c67..6cd8607a3928 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -402,6 +402,24 @@ static int dsa_tree_setup_default_cpu(struct dsa_switch_tree *dst)
return 0;
}
+static struct dsa_port *
+dsa_switch_preferred_default_local_cpu_port(struct dsa_switch *ds)
+{
+ struct dsa_port *cpu_dp;
+
+ if (!ds->ops->preferred_default_local_cpu_port)
+ return NULL;
+
+ cpu_dp = ds->ops->preferred_default_local_cpu_port(ds);
+ if (!cpu_dp)
+ return NULL;
+
+ if (WARN_ON(!dsa_port_is_cpu(cpu_dp) || cpu_dp->ds != ds))
+ return NULL;
+
+ return cpu_dp;
+}
+
/* Perform initial assignment of CPU ports to user ports and DSA links in the
* fabric, giving preference to CPU ports local to each switch. Default to
* using the first CPU port in the switch tree if the port does not have a CPU
@@ -409,12 +427,16 @@ static int dsa_tree_setup_default_cpu(struct dsa_switch_tree *dst)
*/
static int dsa_tree_setup_cpu_ports(struct dsa_switch_tree *dst)
{
- struct dsa_port *cpu_dp, *dp;
+ struct dsa_port *preferred_cpu_dp, *cpu_dp, *dp;
list_for_each_entry(cpu_dp, &dst->ports, list) {
if (!dsa_port_is_cpu(cpu_dp))
continue;
+ preferred_cpu_dp = dsa_switch_preferred_default_local_cpu_port(cpu_dp->ds);
+ if (preferred_cpu_dp && preferred_cpu_dp != cpu_dp)
+ continue;
+
/* Prefer a local CPU port */
dsa_switch_for_each_port(dp, cpu_dp->ds) {
/* Prefer the first local CPU port found */
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 3969fa805679..ee848be59e65 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -340,6 +340,9 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_
secpath_reset(skb);
+ if (skb_needs_linearize(skb, skb->dev->features) &&
+ __skb_linearize(skb))
+ return -ENOMEM;
return 0;
}
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index ad2afeef4f10..eac206a290d0 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -164,6 +164,7 @@ int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb);
return 0;
}
+EXPORT_SYMBOL(xfrm4_udp_encap_rcv);
int xfrm4_rcv(struct sk_buff *skb)
{
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 75c02992c520..772340268997 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -374,6 +374,9 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features
secpath_reset(skb);
+ if (skb_needs_linearize(skb, skb->dev->features) &&
+ __skb_linearize(skb))
+ return -ENOMEM;
return 0;
}
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 04cbeefd8982..4907ab241d6b 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -86,6 +86,9 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
__be32 *udpdata32;
__u16 encap_type = up->encap_type;
+ if (skb->protocol == htons(ETH_P_IP))
+ return xfrm4_udp_encap_rcv(sk, skb);
+
/* if this is not encapsulated socket, then just return now */
if (!encap_type)
return 1;
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 5396907cc596..7b185a064acc 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -1047,6 +1047,7 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
if (err)
return err;
+ inet_sk_state_store(newsk, TCP_LISTEN);
err = kernel_listen(ssock, backlog);
if (err)
return err;
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 0e7c194948cf..a08b7419062c 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -44,7 +44,7 @@ enum {
static struct percpu_counter mptcp_sockets_allocated ____cacheline_aligned_in_smp;
static void __mptcp_destroy_sock(struct sock *sk);
-static void __mptcp_check_send_data_fin(struct sock *sk);
+static void mptcp_check_send_data_fin(struct sock *sk);
DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions);
static struct net_device mptcp_napi_dev;
@@ -411,8 +411,7 @@ static bool mptcp_pending_data_fin_ack(struct sock *sk)
{
struct mptcp_sock *msk = mptcp_sk(sk);
- return !__mptcp_check_fallback(msk) &&
- ((1 << sk->sk_state) &
+ return ((1 << sk->sk_state) &
(TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK)) &&
msk->write_seq == READ_ONCE(msk->snd_una);
}
@@ -570,9 +569,6 @@ static bool mptcp_check_data_fin(struct sock *sk)
u64 rcv_data_fin_seq;
bool ret = false;
- if (__mptcp_check_fallback(msk))
- return ret;
-
/* Need to ack a DATA_FIN received from a peer while this side
* of the connection is in ESTABLISHED, FIN_WAIT1, or FIN_WAIT2.
* msk->rcv_data_fin was set when parsing the incoming options
@@ -610,7 +606,8 @@ static bool mptcp_check_data_fin(struct sock *sk)
}
ret = true;
- mptcp_send_ack(msk);
+ if (!__mptcp_check_fallback(msk))
+ mptcp_send_ack(msk);
mptcp_close_wake_up(sk);
}
return ret;
@@ -837,12 +834,12 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
return true;
}
-static void __mptcp_flush_join_list(struct sock *sk)
+static void __mptcp_flush_join_list(struct sock *sk, struct list_head *join_list)
{
struct mptcp_subflow_context *tmp, *subflow;
struct mptcp_sock *msk = mptcp_sk(sk);
- list_for_each_entry_safe(subflow, tmp, &msk->join_list, node) {
+ list_for_each_entry_safe(subflow, tmp, join_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
bool slow = lock_sock_fast(ssk);
@@ -1596,7 +1593,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
if (!mptcp_timer_pending(sk))
mptcp_reset_timer(sk);
if (do_check_data_fin)
- __mptcp_check_send_data_fin(sk);
+ mptcp_check_send_data_fin(sk);
}
static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool first)
@@ -1696,7 +1693,13 @@ static int mptcp_sendmsg_fastopen(struct sock *sk, struct sock *ssk, struct msgh
if (ret && ret != -EINPROGRESS && ret != -ERESTARTSYS && ret != -EINTR)
*copied_syn = 0;
} else if (ret && ret != -EINPROGRESS) {
- mptcp_disconnect(sk, 0);
+ /* The disconnect() op called by tcp_sendmsg_fastopen()/
+ * __inet_stream_connect() can fail, due to looking check,
+ * see mptcp_disconnect().
+ * Attempt it again outside the problematic scope.
+ */
+ if (!mptcp_disconnect(sk, 0))
+ sk->sk_socket->state = SS_UNCONNECTED;
}
return ret;
@@ -2360,7 +2363,10 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk);
if (!dispose_it) {
- tcp_disconnect(ssk, 0);
+ /* The MPTCP code never wait on the subflow sockets, TCP-level
+ * disconnect should never fail
+ */
+ WARN_ON_ONCE(tcp_disconnect(ssk, 0));
msk->subflow->state = SS_UNCONNECTED;
mptcp_subflow_ctx_reset(subflow);
release_sock(ssk);
@@ -2379,13 +2385,6 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
kfree_rcu(subflow, rcu);
} else {
/* otherwise tcp will dispose of the ssk and subflow ctx */
- if (ssk->sk_state == TCP_LISTEN) {
- tcp_set_state(ssk, TCP_CLOSE);
- mptcp_subflow_queue_clean(sk, ssk);
- inet_csk_listen_stop(ssk);
- mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
- }
-
__tcp_close(ssk, 0);
/* close acquired an extra ref */
@@ -2642,8 +2641,6 @@ static void mptcp_worker(struct work_struct *work)
if (unlikely((1 << state) & (TCPF_CLOSE | TCPF_LISTEN)))
goto unlock;
- mptcp_check_data_fin_ack(sk);
-
mptcp_check_fastclose(msk);
mptcp_pm_nl_work(msk);
@@ -2651,7 +2648,8 @@ static void mptcp_worker(struct work_struct *work)
if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
mptcp_check_for_eof(msk);
- __mptcp_check_send_data_fin(sk);
+ mptcp_check_send_data_fin(sk);
+ mptcp_check_data_fin_ack(sk);
mptcp_check_data_fin(sk);
if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
@@ -2787,13 +2785,19 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
break;
fallthrough;
case TCP_SYN_SENT:
- tcp_disconnect(ssk, O_NONBLOCK);
+ WARN_ON_ONCE(tcp_disconnect(ssk, O_NONBLOCK));
break;
default:
if (__mptcp_check_fallback(mptcp_sk(sk))) {
pr_debug("Fallback");
ssk->sk_shutdown |= how;
tcp_shutdown(ssk, how);
+
+ /* simulate the data_fin ack reception to let the state
+ * machine move forward
+ */
+ WRITE_ONCE(mptcp_sk(sk)->snd_una, mptcp_sk(sk)->snd_nxt);
+ mptcp_schedule_work(sk);
} else {
pr_debug("Sending DATA_FIN on subflow %p", ssk);
tcp_send_ack(ssk);
@@ -2833,7 +2837,7 @@ static int mptcp_close_state(struct sock *sk)
return next & TCP_ACTION_FIN;
}
-static void __mptcp_check_send_data_fin(struct sock *sk)
+static void mptcp_check_send_data_fin(struct sock *sk)
{
struct mptcp_subflow_context *subflow;
struct mptcp_sock *msk = mptcp_sk(sk);
@@ -2851,19 +2855,6 @@ static void __mptcp_check_send_data_fin(struct sock *sk)
WRITE_ONCE(msk->snd_nxt, msk->write_seq);
- /* fallback socket will not get data_fin/ack, can move to the next
- * state now
- */
- if (__mptcp_check_fallback(msk)) {
- WRITE_ONCE(msk->snd_una, msk->write_seq);
- if ((1 << sk->sk_state) & (TCPF_CLOSING | TCPF_LAST_ACK)) {
- inet_sk_state_store(sk, TCP_CLOSE);
- mptcp_close_wake_up(sk);
- } else if (sk->sk_state == TCP_FIN_WAIT1) {
- inet_sk_state_store(sk, TCP_FIN_WAIT2);
- }
- }
-
mptcp_for_each_subflow(msk, subflow) {
struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
@@ -2883,7 +2874,7 @@ static void __mptcp_wr_shutdown(struct sock *sk)
WRITE_ONCE(msk->write_seq, msk->write_seq + 1);
WRITE_ONCE(msk->snd_data_fin_enable, 1);
- __mptcp_check_send_data_fin(sk);
+ mptcp_check_send_data_fin(sk);
}
static void __mptcp_destroy_sock(struct sock *sk)
@@ -2928,10 +2919,24 @@ static __poll_t mptcp_check_readable(struct mptcp_sock *msk)
return EPOLLIN | EPOLLRDNORM;
}
-static void mptcp_listen_inuse_dec(struct sock *sk)
+static void mptcp_check_listen_stop(struct sock *sk)
{
- if (inet_sk_state_load(sk) == TCP_LISTEN)
- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ struct sock *ssk;
+
+ if (inet_sk_state_load(sk) != TCP_LISTEN)
+ return;
+
+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ ssk = mptcp_sk(sk)->first;
+ if (WARN_ON_ONCE(!ssk || inet_sk_state_load(ssk) != TCP_LISTEN))
+ return;
+
+ lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
+ mptcp_subflow_queue_clean(sk, ssk);
+ inet_csk_listen_stop(ssk);
+ mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
+ tcp_set_state(ssk, TCP_CLOSE);
+ release_sock(ssk);
}
bool __mptcp_close(struct sock *sk, long timeout)
@@ -2944,7 +2949,7 @@ bool __mptcp_close(struct sock *sk, long timeout)
WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) {
- mptcp_listen_inuse_dec(sk);
+ mptcp_check_listen_stop(sk);
inet_sk_state_store(sk, TCP_CLOSE);
goto cleanup;
}
@@ -3045,15 +3050,20 @@ static int mptcp_disconnect(struct sock *sk, int flags)
{
struct mptcp_sock *msk = mptcp_sk(sk);
+ /* Deny disconnect if other threads are blocked in sk_wait_event()
+ * or inet_wait_for_connect().
+ */
+ if (sk->sk_wait_pending)
+ return -EBUSY;
+
/* We are on the fastopen error path. We can't call straight into the
* subflows cleanup code due to lock nesting (we are already under
- * msk->firstsocket lock). Do nothing and leave the cleanup to the
- * caller.
+ * msk->firstsocket lock).
*/
if (msk->fastopening)
- return 0;
+ return -EBUSY;
- mptcp_listen_inuse_dec(sk);
+ mptcp_check_listen_stop(sk);
inet_sk_state_store(sk, TCP_CLOSE);
mptcp_stop_timer(sk);
@@ -3112,6 +3122,7 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk,
inet_sk(nsk)->pinet6 = mptcp_inet6_sk(nsk);
#endif
+ nsk->sk_wait_pending = 0;
__mptcp_init_sock(nsk);
msk = mptcp_sk(nsk);
@@ -3299,9 +3310,14 @@ static void mptcp_release_cb(struct sock *sk)
for (;;) {
unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED) |
msk->push_pending;
+ struct list_head join_list;
+
if (!flags)
break;
+ INIT_LIST_HEAD(&join_list);
+ list_splice_init(&msk->join_list, &join_list);
+
/* the following actions acquire the subflow socket lock
*
* 1) can't be invoked in atomic scope
@@ -3312,8 +3328,9 @@ static void mptcp_release_cb(struct sock *sk)
msk->push_pending = 0;
msk->cb_flags &= ~flags;
spin_unlock_bh(&sk->sk_lock.slock);
+
if (flags & BIT(MPTCP_FLUSH_JOIN_LIST))
- __mptcp_flush_join_list(sk);
+ __mptcp_flush_join_list(sk, &join_list);
if (flags & BIT(MPTCP_PUSH_PENDING))
__mptcp_push_pending(sk, 0);
if (flags & BIT(MPTCP_RETRANSMIT))
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index bb0301398d3b..8e0c35c59828 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1749,14 +1749,16 @@ static void subflow_state_change(struct sock *sk)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
struct sock *parent = subflow->conn;
+ struct mptcp_sock *msk;
__subflow_state_change(sk);
+ msk = mptcp_sk(parent);
if (subflow_simultaneous_connect(sk)) {
mptcp_propagate_sndbuf(parent, sk);
mptcp_do_fallback(sk);
- mptcp_rcv_space_init(mptcp_sk(parent), sk);
- pr_fallback(mptcp_sk(parent));
+ mptcp_rcv_space_init(msk, sk);
+ pr_fallback(msk);
subflow->conn_finished = 1;
mptcp_set_connected(parent);
}
@@ -1772,11 +1774,12 @@ static void subflow_state_change(struct sock *sk)
subflow_sched_work_if_closed(mptcp_sk(parent), sk);
- if (__mptcp_check_fallback(mptcp_sk(parent)) &&
- !subflow->rx_eof && subflow_is_done(sk)) {
- subflow->rx_eof = 1;
- mptcp_subflow_eof(parent);
- }
+ /* when the fallback subflow closes the rx side, trigger a 'dummy'
+ * ingress data fin, so that the msk state will follow along
+ */
+ if (__mptcp_check_fallback(msk) && subflow_is_done(sk) && msk->first == sk &&
+ mptcp_update_rcv_data_fin(msk, READ_ONCE(msk->ack_seq), true))
+ mptcp_schedule_work(parent);
}
void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk)
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 80448885c3d7..b452eb3ddcec 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -1225,6 +1225,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->transport_header = skb->network_header;
skb_set_inner_ipproto(skb, next_protocol);
+ skb_set_inner_mac_header(skb, skb_inner_network_offset(skb));
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
bool check = false;
@@ -1373,6 +1374,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->transport_header = skb->network_header;
skb_set_inner_ipproto(skb, next_protocol);
+ skb_set_inner_mac_header(skb, skb_inner_network_offset(skb));
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
bool check = false;
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 8f63514656a1..398bb8fb30a5 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -153,6 +153,7 @@ static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
return NULL;
INIT_LIST_HEAD(&trans->list);
+ INIT_LIST_HEAD(&trans->binding_list);
trans->msg_type = msg_type;
trans->ctx = *ctx;
@@ -165,13 +166,20 @@ static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
}
-static void nft_trans_destroy(struct nft_trans *trans)
+static void nft_trans_list_del(struct nft_trans *trans)
{
list_del(&trans->list);
+ list_del(&trans->binding_list);
+}
+
+static void nft_trans_destroy(struct nft_trans *trans)
+{
+ nft_trans_list_del(trans);
kfree(trans);
}
-static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
+static void __nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set,
+ bool bind)
{
struct nftables_pernet *nft_net;
struct net *net = ctx->net;
@@ -185,16 +193,80 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
switch (trans->msg_type) {
case NFT_MSG_NEWSET:
if (nft_trans_set(trans) == set)
- nft_trans_set_bound(trans) = true;
+ nft_trans_set_bound(trans) = bind;
break;
case NFT_MSG_NEWSETELEM:
if (nft_trans_elem_set(trans) == set)
- nft_trans_elem_set_bound(trans) = true;
+ nft_trans_elem_set_bound(trans) = bind;
break;
}
}
}
+static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ return __nft_set_trans_bind(ctx, set, true);
+}
+
+static void nft_set_trans_unbind(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ return __nft_set_trans_bind(ctx, set, false);
+}
+
+static void __nft_chain_trans_bind(const struct nft_ctx *ctx,
+ struct nft_chain *chain, bool bind)
+{
+ struct nftables_pernet *nft_net;
+ struct net *net = ctx->net;
+ struct nft_trans *trans;
+
+ if (!nft_chain_binding(chain))
+ return;
+
+ nft_net = nft_pernet(net);
+ list_for_each_entry_reverse(trans, &nft_net->commit_list, list) {
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWCHAIN:
+ if (nft_trans_chain(trans) == chain)
+ nft_trans_chain_bound(trans) = bind;
+ break;
+ case NFT_MSG_NEWRULE:
+ if (trans->ctx.chain == chain)
+ nft_trans_rule_bound(trans) = bind;
+ break;
+ }
+ }
+}
+
+static void nft_chain_trans_bind(const struct nft_ctx *ctx,
+ struct nft_chain *chain)
+{
+ __nft_chain_trans_bind(ctx, chain, true);
+}
+
+int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
+{
+ if (!nft_chain_binding(chain))
+ return 0;
+
+ if (nft_chain_binding(ctx->chain))
+ return -EOPNOTSUPP;
+
+ if (chain->bound)
+ return -EBUSY;
+
+ chain->bound = true;
+ chain->use++;
+ nft_chain_trans_bind(ctx, chain);
+
+ return 0;
+}
+
+void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
+{
+ __nft_chain_trans_bind(ctx, chain, false);
+}
+
static int nft_netdev_register_hooks(struct net *net,
struct list_head *hook_list)
{
@@ -294,6 +366,19 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
{
struct nftables_pernet *nft_net = nft_pernet(net);
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWSET:
+ if (!nft_trans_set_update(trans) &&
+ nft_set_is_anonymous(nft_trans_set(trans)))
+ list_add_tail(&trans->binding_list, &nft_net->binding_list);
+ break;
+ case NFT_MSG_NEWCHAIN:
+ if (!nft_trans_chain_update(trans) &&
+ nft_chain_binding(nft_trans_chain(trans)))
+ list_add_tail(&trans->binding_list, &nft_net->binding_list);
+ break;
+ }
+
list_add_tail(&trans->list, &nft_net->commit_list);
}
@@ -340,8 +425,9 @@ static struct nft_trans *nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
ntohl(nla_get_be32(ctx->nla[NFTA_CHAIN_ID]));
}
}
-
+ nft_trans_chain(trans) = ctx->chain;
nft_trans_commit_list_add_tail(ctx->net, trans);
+
return trans;
}
@@ -359,8 +445,7 @@ static int nft_delchain(struct nft_ctx *ctx)
return 0;
}
-static void nft_rule_expr_activate(const struct nft_ctx *ctx,
- struct nft_rule *rule)
+void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule)
{
struct nft_expr *expr;
@@ -373,9 +458,8 @@ static void nft_rule_expr_activate(const struct nft_ctx *ctx,
}
}
-static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
- struct nft_rule *rule,
- enum nft_trans_phase phase)
+void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule,
+ enum nft_trans_phase phase)
{
struct nft_expr *expr;
@@ -497,6 +581,58 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
return __nft_trans_set_add(ctx, msg_type, set, NULL);
}
+static void nft_setelem_data_deactivate(const struct net *net,
+ const struct nft_set *set,
+ struct nft_set_elem *elem);
+
+static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
+ struct nft_set *set,
+ const struct nft_set_iter *iter,
+ struct nft_set_elem *elem)
+{
+ nft_setelem_data_deactivate(ctx->net, set, elem);
+
+ return 0;
+}
+
+struct nft_set_elem_catchall {
+ struct list_head list;
+ struct rcu_head rcu;
+ void *elem;
+};
+
+static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
+ struct nft_set *set)
+{
+ u8 genmask = nft_genmask_next(ctx->net);
+ struct nft_set_elem_catchall *catchall;
+ struct nft_set_elem elem;
+ struct nft_set_ext *ext;
+
+ list_for_each_entry(catchall, &set->catchall_list, list) {
+ ext = nft_set_elem_ext(set, catchall->elem);
+ if (!nft_set_elem_active(ext, genmask))
+ continue;
+
+ elem.priv = catchall->elem;
+ nft_setelem_data_deactivate(ctx->net, set, &elem);
+ break;
+ }
+}
+
+static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ struct nft_set_iter iter = {
+ .genmask = nft_genmask_next(ctx->net),
+ .fn = nft_mapelem_deactivate,
+ };
+
+ set->ops->walk(ctx, set, &iter);
+ WARN_ON_ONCE(iter.err);
+
+ nft_map_catchall_deactivate(ctx, set);
+}
+
static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
{
int err;
@@ -505,6 +641,9 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
if (err < 0)
return err;
+ if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_deactivate(ctx, set);
+
nft_deactivate_next(ctx->net, set);
ctx->table->use--;
@@ -2221,7 +2360,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
return 0;
}
-static int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
+int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
{
int err;
@@ -2525,6 +2664,8 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
nft_trans_basechain(trans) = basechain;
INIT_LIST_HEAD(&nft_trans_chain_hooks(trans));
list_splice(&hook.list, &nft_trans_chain_hooks(trans));
+ if (nla[NFTA_CHAIN_HOOK])
+ module_put(hook.type->owner);
nft_trans_commit_list_add_tail(ctx->net, trans);
@@ -3427,8 +3568,7 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
return err;
}
-static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
- struct nft_rule *rule)
+void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule)
{
struct nft_expr *expr, *next;
@@ -3445,7 +3585,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
kfree(rule);
}
-void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
+static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
{
nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
nf_tables_rule_destroy(ctx, rule);
@@ -3533,12 +3673,6 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
return 0;
}
-struct nft_set_elem_catchall {
- struct list_head list;
- struct rcu_head rcu;
- void *elem;
-};
-
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
{
u8 genmask = nft_genmask_next(ctx->net);
@@ -3781,7 +3915,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
if (flow)
nft_flow_rule_destroy(flow);
err_release_rule:
- nft_rule_expr_deactivate(&ctx, rule, NFT_TRANS_PREPARE);
+ nft_rule_expr_deactivate(&ctx, rule, NFT_TRANS_PREPARE_ERROR);
nf_tables_rule_destroy(&ctx, rule);
err_release_expr:
for (i = 0; i < n; i++) {
@@ -4762,6 +4896,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
return -EOPNOTSUPP;
+ if (nft_set_is_anonymous(set))
+ return -EOPNOTSUPP;
+
err = nft_set_expr_alloc(&ctx, set, nla, exprs, &num_exprs, flags);
if (err < 0)
return err;
@@ -4865,7 +5002,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
for (i = 0; i < set->num_exprs; i++)
nft_expr_destroy(&ctx, set->exprs[i]);
err_set_destroy:
- ops->destroy(set);
+ ops->destroy(&ctx, set);
err_set_init:
kfree(set->name);
err_set_name:
@@ -4880,7 +5017,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
list_del_rcu(&catchall->list);
- nft_set_elem_destroy(set, catchall->elem, true);
+ nf_tables_set_elem_destroy(ctx, set, catchall->elem);
kfree_rcu(catchall, rcu);
}
}
@@ -4895,7 +5032,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
for (i = 0; i < set->num_exprs; i++)
nft_expr_destroy(ctx, set->exprs[i]);
- set->ops->destroy(set);
+ set->ops->destroy(ctx, set);
nft_set_catchall_destroy(ctx, set);
kfree(set->name);
kvfree(set);
@@ -5060,10 +5197,60 @@ static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
}
}
+static void nft_setelem_data_activate(const struct net *net,
+ const struct nft_set *set,
+ struct nft_set_elem *elem);
+
+static int nft_mapelem_activate(const struct nft_ctx *ctx,
+ struct nft_set *set,
+ const struct nft_set_iter *iter,
+ struct nft_set_elem *elem)
+{
+ nft_setelem_data_activate(ctx->net, set, elem);
+
+ return 0;
+}
+
+static void nft_map_catchall_activate(const struct nft_ctx *ctx,
+ struct nft_set *set)
+{
+ u8 genmask = nft_genmask_next(ctx->net);
+ struct nft_set_elem_catchall *catchall;
+ struct nft_set_elem elem;
+ struct nft_set_ext *ext;
+
+ list_for_each_entry(catchall, &set->catchall_list, list) {
+ ext = nft_set_elem_ext(set, catchall->elem);
+ if (!nft_set_elem_active(ext, genmask))
+ continue;
+
+ elem.priv = catchall->elem;
+ nft_setelem_data_activate(ctx->net, set, &elem);
+ break;
+ }
+}
+
+static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ struct nft_set_iter iter = {
+ .genmask = nft_genmask_next(ctx->net),
+ .fn = nft_mapelem_activate,
+ };
+
+ set->ops->walk(ctx, set, &iter);
+ WARN_ON_ONCE(iter.err);
+
+ nft_map_catchall_activate(ctx, set);
+}
+
void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set)
{
- if (nft_set_is_anonymous(set))
+ if (nft_set_is_anonymous(set)) {
+ if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_activate(ctx, set);
+
nft_clear(ctx->net, set);
+ }
set->use++;
}
@@ -5074,14 +5261,28 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
enum nft_trans_phase phase)
{
switch (phase) {
- case NFT_TRANS_PREPARE:
+ case NFT_TRANS_PREPARE_ERROR:
+ nft_set_trans_unbind(ctx, set);
if (nft_set_is_anonymous(set))
nft_deactivate_next(ctx->net, set);
+ set->use--;
+ break;
+ case NFT_TRANS_PREPARE:
+ if (nft_set_is_anonymous(set)) {
+ if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_deactivate(ctx, set);
+
+ nft_deactivate_next(ctx->net, set);
+ }
set->use--;
return;
case NFT_TRANS_ABORT:
case NFT_TRANS_RELEASE:
+ if (nft_set_is_anonymous(set) &&
+ set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_deactivate(ctx, set);
+
set->use--;
fallthrough;
default:
@@ -5834,6 +6035,7 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
__nft_set_elem_expr_destroy(ctx, expr);
}
+/* Drop references and destroy. Called from gc, dynset and abort path. */
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
bool destroy_expr)
{
@@ -5855,11 +6057,11 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
}
EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
-/* Only called from commit path, nft_setelem_data_deactivate() already deals
- * with the refcounting from the preparation phase.
+/* Destroy element. References have been already dropped in the preparation
+ * path via nft_setelem_data_deactivate().
*/
-static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
- const struct nft_set *set, void *elem)
+void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set, void *elem)
{
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
@@ -6492,7 +6694,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
if (obj)
obj->use--;
err_elem_userdata:
- nf_tables_set_elem_destroy(ctx, set, elem.priv);
+ nft_set_elem_destroy(set, elem.priv, true);
err_parse_data:
if (nla[NFTA_SET_ELEM_DATA] != NULL)
nft_data_release(&elem.data.val, desc.type);
@@ -6537,7 +6739,8 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
if (IS_ERR(set))
return PTR_ERR(set);
- if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
+ if (!list_empty(&set->bindings) &&
+ (set->flags & (NFT_SET_CONSTANT | NFT_SET_ANONYMOUS)))
return -EBUSY;
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
@@ -6570,7 +6773,6 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
{
struct nft_chain *chain;
- struct nft_rule *rule;
if (type == NFT_DATA_VERDICT) {
switch (data->verdict.code) {
@@ -6578,15 +6780,6 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
case NFT_GOTO:
chain = data->verdict.chain;
chain->use++;
-
- if (!nft_chain_is_bound(chain))
- break;
-
- chain->table->use++;
- list_for_each_entry(rule, &chain->rules, list)
- chain->use++;
-
- nft_chain_add(chain->table, chain);
break;
}
}
@@ -6821,7 +7014,9 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
set = nft_set_lookup(table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
if (IS_ERR(set))
return PTR_ERR(set);
- if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
+
+ if (!list_empty(&set->bindings) &&
+ (set->flags & (NFT_SET_CONSTANT | NFT_SET_ANONYMOUS)))
return -EBUSY;
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
@@ -7596,6 +7791,7 @@ void nf_tables_deactivate_flowtable(const struct nft_ctx *ctx,
enum nft_trans_phase phase)
{
switch (phase) {
+ case NFT_TRANS_PREPARE_ERROR:
case NFT_TRANS_PREPARE:
case NFT_TRANS_ABORT:
case NFT_TRANS_RELEASE:
@@ -8856,7 +9052,7 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
synchronize_rcu();
list_for_each_entry_safe(trans, next, &head, list) {
- list_del(&trans->list);
+ nft_trans_list_del(trans);
nft_commit_release(trans);
}
}
@@ -9223,6 +9419,27 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
return 0;
}
+ list_for_each_entry(trans, &nft_net->binding_list, binding_list) {
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWSET:
+ if (!nft_trans_set_update(trans) &&
+ nft_set_is_anonymous(nft_trans_set(trans)) &&
+ !nft_trans_set_bound(trans)) {
+ pr_warn_once("nftables ruleset with unbound set\n");
+ return -EINVAL;
+ }
+ break;
+ case NFT_MSG_NEWCHAIN:
+ if (!nft_trans_chain_update(trans) &&
+ nft_chain_binding(nft_trans_chain(trans)) &&
+ !nft_trans_chain_bound(trans)) {
+ pr_warn_once("nftables ruleset with unbound chain\n");
+ return -EINVAL;
+ }
+ break;
+ }
+ }
+
/* 0. Validate ruleset, otherwise roll back for error reporting. */
if (nf_tables_validate(net) < 0)
return -EAGAIN;
@@ -9583,7 +9800,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
kfree(nft_trans_chain_name(trans));
nft_trans_destroy(trans);
} else {
- if (nft_chain_is_bound(trans->ctx.chain)) {
+ if (nft_trans_chain_bound(trans)) {
nft_trans_destroy(trans);
break;
}
@@ -9601,6 +9818,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
nft_trans_destroy(trans);
break;
case NFT_MSG_NEWRULE:
+ if (nft_trans_rule_bound(trans)) {
+ nft_trans_destroy(trans);
+ break;
+ }
trans->ctx.chain->use--;
list_del_rcu(&nft_trans_rule(trans)->list);
nft_rule_expr_deactivate(&trans->ctx,
@@ -9635,6 +9856,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
case NFT_MSG_DESTROYSET:
trans->ctx.table->use++;
nft_clear(trans->ctx.net, nft_trans_set(trans));
+ if (nft_trans_set(trans)->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_activate(&trans->ctx, nft_trans_set(trans));
+
nft_trans_destroy(trans);
break;
case NFT_MSG_NEWSETELEM:
@@ -9715,7 +9939,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
list_for_each_entry_safe_reverse(trans, next,
&nft_net->commit_list, list) {
- list_del(&trans->list);
+ nft_trans_list_del(trans);
nf_tables_abort_release(trans);
}
@@ -10164,22 +10388,12 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
static void nft_verdict_uninit(const struct nft_data *data)
{
struct nft_chain *chain;
- struct nft_rule *rule;
switch (data->verdict.code) {
case NFT_JUMP:
case NFT_GOTO:
chain = data->verdict.chain;
chain->use--;
-
- if (!nft_chain_is_bound(chain))
- break;
-
- chain->table->use--;
- list_for_each_entry(rule, &chain->rules, list)
- chain->use--;
-
- nft_chain_del(chain);
break;
}
}
@@ -10414,6 +10628,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
list_for_each_entry_safe(set, ns, &table->sets, list) {
list_del(&set->list);
table->use--;
+ if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_deactivate(&ctx, set);
+
nft_set_destroy(&ctx, set);
}
list_for_each_entry_safe(obj, ne, &table->objects, list) {
@@ -10498,6 +10715,7 @@ static int __net_init nf_tables_init_net(struct net *net)
INIT_LIST_HEAD(&nft_net->tables);
INIT_LIST_HEAD(&nft_net->commit_list);
+ INIT_LIST_HEAD(&nft_net->binding_list);
INIT_LIST_HEAD(&nft_net->module_list);
INIT_LIST_HEAD(&nft_net->notify_list);
mutex_init(&nft_net->commit_mutex);
diff --git a/net/netfilter/nfnetlink_osf.c b/net/netfilter/nfnetlink_osf.c
index ee6840bd5933..8f1bfa6ccc2d 100644
--- a/net/netfilter/nfnetlink_osf.c
+++ b/net/netfilter/nfnetlink_osf.c
@@ -439,3 +439,4 @@ module_init(nfnl_osf_init);
module_exit(nfnl_osf_fini);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF);
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
index c9d2f7c29f53..3d76ebfe8939 100644
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -76,11 +76,9 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
switch (priv->data.verdict.code) {
case NFT_JUMP:
case NFT_GOTO:
- if (nft_chain_is_bound(chain)) {
- err = -EBUSY;
- goto err1;
- }
- chain->bound = true;
+ err = nf_tables_bind_chain(ctx, chain);
+ if (err < 0)
+ return err;
break;
default:
break;
@@ -98,6 +96,31 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+ const struct nft_data *data = &priv->data;
+ struct nft_ctx chain_ctx;
+ struct nft_chain *chain;
+ struct nft_rule *rule;
+
+ if (priv->dreg == NFT_REG_VERDICT) {
+ switch (data->verdict.code) {
+ case NFT_JUMP:
+ case NFT_GOTO:
+ chain = data->verdict.chain;
+ if (!nft_chain_binding(chain))
+ break;
+
+ chain_ctx = *ctx;
+ chain_ctx.chain = chain;
+
+ list_for_each_entry(rule, &chain->rules, list)
+ nft_rule_expr_activate(&chain_ctx, rule);
+
+ nft_clear(ctx->net, chain);
+ break;
+ default:
+ break;
+ }
+ }
return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
}
@@ -107,6 +130,43 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
enum nft_trans_phase phase)
{
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+ const struct nft_data *data = &priv->data;
+ struct nft_ctx chain_ctx;
+ struct nft_chain *chain;
+ struct nft_rule *rule;
+
+ if (priv->dreg == NFT_REG_VERDICT) {
+ switch (data->verdict.code) {
+ case NFT_JUMP:
+ case NFT_GOTO:
+ chain = data->verdict.chain;
+ if (!nft_chain_binding(chain))
+ break;
+
+ chain_ctx = *ctx;
+ chain_ctx.chain = chain;
+
+ list_for_each_entry(rule, &chain->rules, list)
+ nft_rule_expr_deactivate(&chain_ctx, rule, phase);
+
+ switch (phase) {
+ case NFT_TRANS_PREPARE_ERROR:
+ nf_tables_unbind_chain(ctx, chain);
+ fallthrough;
+ case NFT_TRANS_PREPARE:
+ nft_deactivate_next(ctx->net, chain);
+ break;
+ default:
+ nft_chain_del(chain);
+ chain->bound = false;
+ chain->table->use--;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
if (phase == NFT_TRANS_COMMIT)
return;
@@ -131,15 +191,27 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
case NFT_GOTO:
chain = data->verdict.chain;
- if (!nft_chain_is_bound(chain))
+ if (!nft_chain_binding(chain))
+ break;
+
+ /* Rule construction failed, but chain is already bound:
+ * let the transaction records release this chain and its rules.
+ */
+ if (chain->bound) {
+ chain->use--;
break;
+ }
+ /* Rule has been deleted, release chain and its rules. */
chain_ctx = *ctx;
chain_ctx.chain = chain;
- list_for_each_entry_safe(rule, n, &chain->rules, list)
- nf_tables_rule_release(&chain_ctx, rule);
-
+ chain->use--;
+ list_for_each_entry_safe(rule, n, &chain->rules, list) {
+ chain->use--;
+ list_del(&rule->list);
+ nf_tables_rule_destroy(&chain_ctx, rule);
+ }
nf_tables_chain_destroy(&chain_ctx);
break;
default:
diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c
index 96081ac8d2b4..1e5e7a181e0b 100644
--- a/net/netfilter/nft_set_bitmap.c
+++ b/net/netfilter/nft_set_bitmap.c
@@ -271,13 +271,14 @@ static int nft_bitmap_init(const struct nft_set *set,
return 0;
}
-static void nft_bitmap_destroy(const struct nft_set *set)
+static void nft_bitmap_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_bitmap *priv = nft_set_priv(set);
struct nft_bitmap_elem *be, *n;
list_for_each_entry_safe(be, n, &priv->list, head)
- nft_set_elem_destroy(set, be, true);
+ nf_tables_set_elem_destroy(ctx, set, be);
}
static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features,
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
index 76de6c8d9865..0b73cb0e752f 100644
--- a/net/netfilter/nft_set_hash.c
+++ b/net/netfilter/nft_set_hash.c
@@ -400,19 +400,31 @@ static int nft_rhash_init(const struct nft_set *set,
return 0;
}
+struct nft_rhash_ctx {
+ const struct nft_ctx ctx;
+ const struct nft_set *set;
+};
+
static void nft_rhash_elem_destroy(void *ptr, void *arg)
{
- nft_set_elem_destroy(arg, ptr, true);
+ struct nft_rhash_ctx *rhash_ctx = arg;
+
+ nf_tables_set_elem_destroy(&rhash_ctx->ctx, rhash_ctx->set, ptr);
}
-static void nft_rhash_destroy(const struct nft_set *set)
+static void nft_rhash_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_rhash *priv = nft_set_priv(set);
+ struct nft_rhash_ctx rhash_ctx = {
+ .ctx = *ctx,
+ .set = set,
+ };
cancel_delayed_work_sync(&priv->gc_work);
rcu_barrier();
rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
- (void *)set);
+ (void *)&rhash_ctx);
}
/* Number of buckets is stored in u32, so cap our result to 1U<<31 */
@@ -643,7 +655,8 @@ static int nft_hash_init(const struct nft_set *set,
return 0;
}
-static void nft_hash_destroy(const struct nft_set *set)
+static void nft_hash_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_hash *priv = nft_set_priv(set);
struct nft_hash_elem *he;
@@ -653,7 +666,7 @@ static void nft_hash_destroy(const struct nft_set *set)
for (i = 0; i < priv->buckets; i++) {
hlist_for_each_entry_safe(he, next, &priv->table[i], node) {
hlist_del_rcu(&he->node);
- nft_set_elem_destroy(set, he, true);
+ nf_tables_set_elem_destroy(ctx, set, he);
}
}
}
diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
index 15e451dc3fc4..0452ee586c1c 100644
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -1974,12 +1974,16 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_iter *iter)
{
struct nft_pipapo *priv = nft_set_priv(set);
+ struct net *net = read_pnet(&set->net);
struct nft_pipapo_match *m;
struct nft_pipapo_field *f;
int i, r;
rcu_read_lock();
- m = rcu_dereference(priv->match);
+ if (iter->genmask == nft_genmask_cur(net))
+ m = rcu_dereference(priv->match);
+ else
+ m = priv->clone;
if (unlikely(!m))
goto out;
@@ -2148,10 +2152,12 @@ static int nft_pipapo_init(const struct nft_set *set,
/**
* nft_set_pipapo_match_destroy() - Destroy elements from key mapping array
+ * @ctx: context
* @set: nftables API set representation
* @m: matching data pointing to key mapping array
*/
-static void nft_set_pipapo_match_destroy(const struct nft_set *set,
+static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set,
struct nft_pipapo_match *m)
{
struct nft_pipapo_field *f;
@@ -2168,15 +2174,17 @@ static void nft_set_pipapo_match_destroy(const struct nft_set *set,
e = f->mt[r].e;
- nft_set_elem_destroy(set, e, true);
+ nf_tables_set_elem_destroy(ctx, set, e);
}
}
/**
* nft_pipapo_destroy() - Free private data for set and all committed elements
+ * @ctx: context
* @set: nftables API set representation
*/
-static void nft_pipapo_destroy(const struct nft_set *set)
+static void nft_pipapo_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_pipapo *priv = nft_set_priv(set);
struct nft_pipapo_match *m;
@@ -2186,7 +2194,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
if (m) {
rcu_barrier();
- nft_set_pipapo_match_destroy(set, m);
+ nft_set_pipapo_match_destroy(ctx, set, m);
#ifdef NFT_PIPAPO_ALIGN
free_percpu(m->scratch_aligned);
@@ -2203,7 +2211,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
m = priv->clone;
if (priv->dirty)
- nft_set_pipapo_match_destroy(set, m);
+ nft_set_pipapo_match_destroy(ctx, set, m);
#ifdef NFT_PIPAPO_ALIGN
free_percpu(priv->clone->scratch_aligned);
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
index 2f114aa10f1a..5c05c9b990fb 100644
--- a/net/netfilter/nft_set_rbtree.c
+++ b/net/netfilter/nft_set_rbtree.c
@@ -664,7 +664,8 @@ static int nft_rbtree_init(const struct nft_set *set,
return 0;
}
-static void nft_rbtree_destroy(const struct nft_set *set)
+static void nft_rbtree_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_rbtree *priv = nft_set_priv(set);
struct nft_rbtree_elem *rbe;
@@ -675,7 +676,7 @@ static void nft_rbtree_destroy(const struct nft_set *set)
while ((node = priv->root.rb_node) != NULL) {
rb_erase(node, &priv->root);
rbe = rb_entry(node, struct nft_rbtree_elem, node);
- nft_set_elem_destroy(set, rbe, true);
+ nf_tables_set_elem_destroy(ctx, set, rbe);
}
}
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index e1990baf3a3b..dc9485854002 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -71,4 +71,3 @@ MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Passive OS fingerprint matching.");
MODULE_ALIAS("ipt_osf");
MODULE_ALIAS("ip6t_osf");
-MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 3f7311529cc0..34c90c9c2fca 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -2324,7 +2324,9 @@ static struct pernet_operations psched_net_ops = {
.exit = psched_net_exit,
};
+#if IS_ENABLED(CONFIG_RETPOLINE)
DEFINE_STATIC_KEY_FALSE(tc_skip_wrapper);
+#endif
static int __init pktsched_init(void)
{
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 6ef3021e1169..e79be1b3e74d 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -966,6 +966,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
if (ret < 0)
return ret;
+ sch_tree_lock(sch);
/* backup q->clg and q->loss_model */
old_clg = q->clg;
old_loss_model = q->loss_model;
@@ -974,7 +975,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]);
if (ret) {
q->loss_model = old_loss_model;
- return ret;
+ goto unlock;
}
} else {
q->loss_model = CLG_RANDOM;
@@ -1041,6 +1042,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
/* capping jitter to the range acceptable by tabledist() */
q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
+unlock:
+ sch_tree_unlock(sch);
return ret;
get_table_failure:
@@ -1050,7 +1053,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
*/
q->clg = old_clg;
q->loss_model = old_loss_model;
- return ret;
+
+ goto unlock;
}
static int netem_init(struct Qdisc *sch, struct nlattr *opt,
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 436d29640ac2..9f294a20dcec 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -131,6 +131,7 @@ struct sec_path *secpath_set(struct sk_buff *skb)
memset(sp->ovec, 0, sizeof(sp->ovec));
sp->olen = 0;
sp->len = 0;
+ sp->verified_cnt = 0;
return sp;
}
diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c
index 1f99dc469027..35279c220bd7 100644
--- a/net/xfrm/xfrm_interface_core.c
+++ b/net/xfrm/xfrm_interface_core.c
@@ -310,6 +310,52 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
skb->mark = 0;
}
+static int xfrmi_input(struct sk_buff *skb, int nexthdr, __be32 spi,
+ int encap_type, unsigned short family)
+{
+ struct sec_path *sp;
+
+ sp = skb_sec_path(skb);
+ if (sp && (sp->len || sp->olen) &&
+ !xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
+ goto discard;
+
+ XFRM_SPI_SKB_CB(skb)->family = family;
+ if (family == AF_INET) {
+ XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
+ XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
+ } else {
+ XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
+ XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
+ }
+
+ return xfrm_input(skb, nexthdr, spi, encap_type);
+discard:
+ kfree_skb(skb);
+ return 0;
+}
+
+static int xfrmi4_rcv(struct sk_buff *skb)
+{
+ return xfrmi_input(skb, ip_hdr(skb)->protocol, 0, 0, AF_INET);
+}
+
+static int xfrmi6_rcv(struct sk_buff *skb)
+{
+ return xfrmi_input(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
+ 0, 0, AF_INET6);
+}
+
+static int xfrmi4_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
+{
+ return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET);
+}
+
+static int xfrmi6_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
+{
+ return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET6);
+}
+
static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
{
const struct xfrm_mode *inner_mode;
@@ -945,8 +991,8 @@ static struct pernet_operations xfrmi_net_ops = {
};
static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
- .handler = xfrm6_rcv,
- .input_handler = xfrm_input,
+ .handler = xfrmi6_rcv,
+ .input_handler = xfrmi6_input,
.cb_handler = xfrmi_rcv_cb,
.err_handler = xfrmi6_err,
.priority = 10,
@@ -996,8 +1042,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
#endif
static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
- .handler = xfrm4_rcv,
- .input_handler = xfrm_input,
+ .handler = xfrmi4_rcv,
+ .input_handler = xfrmi4_input,
.cb_handler = xfrmi_rcv_cb,
.err_handler = xfrmi4_err,
.priority = 10,
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 6d15788b5123..e7617c9959c3 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1831,6 +1831,7 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
__xfrm_policy_unlink(pol, dir);
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
+ xfrm_dev_policy_delete(pol);
cnt++;
xfrm_audit_policy_delete(pol, 1, task_valid);
xfrm_policy_kill(pol);
@@ -1869,6 +1870,7 @@ int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
__xfrm_policy_unlink(pol, dir);
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
+ xfrm_dev_policy_delete(pol);
cnt++;
xfrm_audit_policy_delete(pol, 1, task_valid);
xfrm_policy_kill(pol);
@@ -3349,6 +3351,13 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
return ++idx;
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
+ if (idx < sp->verified_cnt) {
+ /* Secpath entry previously verified, consider optional and
+ * continue searching
+ */
+ continue;
+ }
+
if (start == -1)
start = -2-idx;
break;
@@ -3723,6 +3732,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
* Order is _important_. Later we will implement
* some barriers, but at the moment barriers
* are implied between each two transformations.
+ * Upon success, marks secpath entries as having been
+ * verified to allow them to be skipped in future policy
+ * checks (e.g. nested tunnels).
*/
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
@@ -3741,6 +3753,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
}
xfrm_pols_put(pols, npols);
+ sp->verified_cnt = k;
+
return 1;
}
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK);
diff --git a/scripts/gfp-translate b/scripts/gfp-translate
index b2ce416d944b..6c9aed17cf56 100755
--- a/scripts/gfp-translate
+++ b/scripts/gfp-translate
@@ -63,11 +63,11 @@ fi
# Extract GFP flags from the kernel source
TMPFILE=`mktemp -t gfptranslate-XXXXXX` || exit 1
-grep -q ___GFP $SOURCE/include/linux/gfp.h
+grep -q ___GFP $SOURCE/include/linux/gfp_types.h
if [ $? -eq 0 ]; then
- grep "^#define ___GFP" $SOURCE/include/linux/gfp.h | sed -e 's/u$//' | grep -v GFP_BITS > $TMPFILE
+ grep "^#define ___GFP" $SOURCE/include/linux/gfp_types.h | sed -e 's/u$//' | grep -v GFP_BITS > $TMPFILE
else
- grep "^#define __GFP" $SOURCE/include/linux/gfp.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE
+ grep "^#define __GFP" $SOURCE/include/linux/gfp_types.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE
fi
# Parse the flags
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 9466b6a2abae..5b3964b39709 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1985,6 +1985,11 @@ static void add_header(struct buffer *b, struct module *mod)
buf_printf(b, "#include <linux/vermagic.h>\n");
buf_printf(b, "#include <linux/compiler.h>\n");
buf_printf(b, "\n");
+ buf_printf(b, "#ifdef CONFIG_UNWINDER_ORC\n");
+ buf_printf(b, "#include <asm/orc_header.h>\n");
+ buf_printf(b, "ORC_HEADER;\n");
+ buf_printf(b, "#endif\n");
+ buf_printf(b, "\n");
buf_printf(b, "BUILD_SALT;\n");
buf_printf(b, "BUILD_LTO_INFO;\n");
buf_printf(b, "\n");
diff --git a/scripts/orc_hash.sh b/scripts/orc_hash.sh
new file mode 100644
index 000000000000..466611aa0053
--- /dev/null
+++ b/scripts/orc_hash.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) Meta Platforms, Inc. and affiliates.
+
+set -e
+
+printf '%s' '#define ORC_HASH '
+
+awk '
+/^#define ORC_(REG|TYPE)_/ { print }
+/^struct orc_entry {$/ { p=1 }
+p { print }
+/^}/ { p=0 }' |
+ sha1sum |
+ cut -d " " -f 1 |
+ sed 's/\([0-9a-f]\{2\}\)/0x\1,/g'
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 920e44ba998a..eb049014f87a 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -9594,6 +9594,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
+ SND_PCI_QUIRK(0x10ec, 0x12cc, "Intel Reference board", ALC225_FIXUP_HEADSET_JACK),
SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
@@ -9814,6 +9815,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED),
SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10),
+ SND_PCI_QUIRK(0x8086, 0x3038, "Intel NUC 13", ALC225_FIXUP_HEADSET_JACK),
SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
#if 0
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 84b401b685f7..c1ca3ceac5f2 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -171,6 +171,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "21CL"),
}
},
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21EF"),
+ }
+ },
{
.driver_data = &acp6x_card,
.matches = {
diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c
index 4f19fd9b65d1..5a4db8944d06 100644
--- a/sound/soc/codecs/nau8824.c
+++ b/sound/soc/codecs/nau8824.c
@@ -1903,6 +1903,30 @@ static const struct dmi_system_id nau8824_quirk_table[] = {
},
.driver_data = (void *)(NAU8824_MONO_SPEAKER),
},
+ {
+ /* Positivo CW14Q01P */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+ DMI_MATCH(DMI_BOARD_NAME, "CW14Q01P"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
+ {
+ /* Positivo K1424G */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+ DMI_MATCH(DMI_BOARD_NAME, "K1424G"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
+ {
+ /* Positivo N14ZP74G */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+ DMI_MATCH(DMI_BOARD_NAME, "N14ZP74G"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
{}
};
diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c
index 402286dfaea4..9c10200ff34b 100644
--- a/sound/soc/codecs/wcd938x-sdw.c
+++ b/sound/soc/codecs/wcd938x-sdw.c
@@ -1190,7 +1190,6 @@ static const struct regmap_config wcd938x_regmap_config = {
.readable_reg = wcd938x_readable_register,
.writeable_reg = wcd938x_writeable_register,
.volatile_reg = wcd938x_volatile_register,
- .can_multi_write = true,
};
static const struct sdw_slave_ops wcd9380_slave_ops = {
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 990bba0be1fb..8a64f3c1d155 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -491,14 +491,21 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
regmap_update_bits(sai->regmap, reg, FSL_SAI_CR2_MSEL_MASK,
FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
- if (savediv == 1)
+ if (savediv == 1) {
regmap_update_bits(sai->regmap, reg,
FSL_SAI_CR2_DIV_MASK | FSL_SAI_CR2_BYP,
FSL_SAI_CR2_BYP);
- else
+ if (fsl_sai_dir_is_synced(sai, adir))
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
+ FSL_SAI_CR2_BCI, FSL_SAI_CR2_BCI);
+ else
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
+ FSL_SAI_CR2_BCI, 0);
+ } else {
regmap_update_bits(sai->regmap, reg,
FSL_SAI_CR2_DIV_MASK | FSL_SAI_CR2_BYP,
savediv / 2 - 1);
+ }
if (sai->soc_data->max_register >= FSL_SAI_MCTL) {
/* SAI is in master mode at this point, so enable MCLK */
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index 197748a888d5..a53c4f0e25fa 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -116,6 +116,7 @@
/* SAI Transmit and Receive Configuration 2 Register */
#define FSL_SAI_CR2_SYNC BIT(30)
+#define FSL_SAI_CR2_BCI BIT(28)
#define FSL_SAI_CR2_MSEL_MASK (0x3 << 26)
#define FSL_SAI_CR2_MSEL_BUS 0
#define FSL_SAI_CR2_MSEL_MCLK1 BIT(26)
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index e98932c16754..5f8468ff3656 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -416,6 +416,7 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv,
if (ret < 0) {
of_node_put(codec);
+ of_node_put(plat);
of_node_put(np);
goto error;
}
diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index 21ca91473c09..ee6880ac3e5e 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -92,6 +92,13 @@ NSC_CMD="ip netns exec ${NSC}"
which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
+# Check if FIPS mode is enabled
+if [ -f /proc/sys/crypto/fips_enabled ]; then
+ fips_enabled=`cat /proc/sys/crypto/fips_enabled`
+else
+ fips_enabled=0
+fi
+
################################################################################
# utilities
@@ -1216,7 +1223,7 @@ ipv4_tcp_novrf()
run_cmd nettest -d ${NSA_DEV} -r ${a}
log_test_addr ${a} $? 1 "No server, device client, local conn"
- ipv4_tcp_md5_novrf
+ [ "$fips_enabled" = "1" ] || ipv4_tcp_md5_novrf
}
ipv4_tcp_vrf()
@@ -1270,9 +1277,11 @@ ipv4_tcp_vrf()
log_test_addr ${a} $? 1 "Global server, local connection"
# run MD5 tests
- setup_vrf_dup
- ipv4_tcp_md5
- cleanup_vrf_dup
+ if [ "$fips_enabled" = "0" ]; then
+ setup_vrf_dup
+ ipv4_tcp_md5
+ cleanup_vrf_dup
+ fi
#
# enable VRF global server
@@ -2772,7 +2781,7 @@ ipv6_tcp_novrf()
log_test_addr ${a} $? 1 "No server, device client, local conn"
done
- ipv6_tcp_md5_novrf
+ [ "$fips_enabled" = "1" ] || ipv6_tcp_md5_novrf
}
ipv6_tcp_vrf()
@@ -2842,9 +2851,11 @@ ipv6_tcp_vrf()
log_test_addr ${a} $? 1 "Global server, local connection"
# run MD5 tests
- setup_vrf_dup
- ipv6_tcp_md5
- cleanup_vrf_dup
+ if [ "$fips_enabled" = "0" ]; then
+ setup_vrf_dup
+ ipv6_tcp_md5
+ cleanup_vrf_dup
+ fi
#
# enable VRF global server
diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh
index c5095da7f6bf..aec752a22e9e 100755
--- a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh
+++ b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh
@@ -93,12 +93,16 @@ cleanup()
test_gretap()
{
+ ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \
+ nud permanent dev br2
full_test_span_gre_dir gt4 ingress 8 0 "mirror to gretap"
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
}
test_ip6gretap()
{
+ ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \
+ nud permanent dev br2
full_test_span_gre_dir gt6 ingress 8 0 "mirror to ip6gretap"
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
}
diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
index 9ff22f28032d..0cf4c47a46f9 100755
--- a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
+++ b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
@@ -90,12 +90,16 @@ cleanup()
test_gretap()
{
+ ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \
+ nud permanent dev br1
full_test_span_gre_dir gt4 ingress 8 0 "mirror to gretap"
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
}
test_ip6gretap()
{
+ ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \
+ nud permanent dev br1
full_test_span_gre_dir gt6 ingress 8 0 "mirror to ip6gretap"
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
}
diff --git a/tools/testing/selftests/net/mptcp/config b/tools/testing/selftests/net/mptcp/config
index 38021a0dd527..6032f9b23c4c 100644
--- a/tools/testing/selftests/net/mptcp/config
+++ b/tools/testing/selftests/net/mptcp/config
@@ -1,3 +1,4 @@
+CONFIG_KALLSYMS=y
CONFIG_MPTCP=y
CONFIG_IPV6=y
CONFIG_MPTCP_IPV6=y
diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh
index 4eacdb1ab962..fa9e09ad97d9 100755
--- a/tools/testing/selftests/net/mptcp/diag.sh
+++ b/tools/testing/selftests/net/mptcp/diag.sh
@@ -55,16 +55,20 @@ __chk_nr()
{
local command="$1"
local expected=$2
- local msg nr
+ local msg="$3"
+ local skip="${4:-SKIP}"
+ local nr
- shift 2
- msg=$*
nr=$(eval $command)
printf "%-50s" "$msg"
if [ $nr != $expected ]; then
- echo "[ fail ] expected $expected found $nr"
- ret=$test_cnt
+ if [ $nr = "$skip" ] && ! mptcp_lib_expect_all_features; then
+ echo "[ skip ] Feature probably not supported"
+ else
+ echo "[ fail ] expected $expected found $nr"
+ ret=$test_cnt
+ fi
else
echo "[ ok ]"
fi
@@ -76,12 +80,12 @@ __chk_msk_nr()
local condition=$1
shift 1
- __chk_nr "ss -inmHMN $ns | $condition" $*
+ __chk_nr "ss -inmHMN $ns | $condition" "$@"
}
chk_msk_nr()
{
- __chk_msk_nr "grep -c token:" $*
+ __chk_msk_nr "grep -c token:" "$@"
}
wait_msk_nr()
@@ -119,37 +123,26 @@ wait_msk_nr()
chk_msk_fallback_nr()
{
- __chk_msk_nr "grep -c fallback" $*
+ __chk_msk_nr "grep -c fallback" "$@"
}
chk_msk_remote_key_nr()
{
- __chk_msk_nr "grep -c remote_key" $*
+ __chk_msk_nr "grep -c remote_key" "$@"
}
__chk_listen()
{
local filter="$1"
local expected=$2
+ local msg="$3"
- shift 2
- msg=$*
-
- nr=$(ss -N $ns -Ml "$filter" | grep -c LISTEN)
- printf "%-50s" "$msg"
-
- if [ $nr != $expected ]; then
- echo "[ fail ] expected $expected found $nr"
- ret=$test_cnt
- else
- echo "[ ok ]"
- fi
+ __chk_nr "ss -N $ns -Ml '$filter' | grep -c LISTEN" "$expected" "$msg" 0
}
chk_msk_listen()
{
lport=$1
- local msg="check for listen socket"
# destination port search should always return empty list
__chk_listen "dport $lport" 0 "listen match for dport $lport"
@@ -167,10 +160,9 @@ chk_msk_listen()
chk_msk_inuse()
{
local expected=$1
+ local msg="$2"
local listen_nr
- shift 1
-
listen_nr=$(ss -N "${ns}" -Ml | grep -c LISTEN)
expected=$((expected + listen_nr))
@@ -181,7 +173,7 @@ chk_msk_inuse()
sleep 0.1
done
- __chk_nr get_msk_inuse $expected $*
+ __chk_nr get_msk_inuse $expected "$msg" 0
}
# $1: ns, $2: port
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index b25a31445ded..c7f9ebeebc2c 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -106,8 +106,8 @@ static struct cfg_sockopt_types cfg_sockopt_types;
static void die_usage(void)
{
fprintf(stderr, "Usage: mptcp_connect [-6] [-c cmsg] [-f offset] [-i file] [-I num] [-j] [-l] "
- "[-m mode] [-M mark] [-o option] [-p port] [-P mode] [-j] [-l] [-r num] "
- "[-s MPTCP|TCP] [-S num] [-r num] [-t num] [-T num] [-u] [-w sec] connect_address\n");
+ "[-m mode] [-M mark] [-o option] [-p port] [-P mode] [-r num] [-R num] "
+ "[-s MPTCP|TCP] [-S num] [-t num] [-T num] [-w sec] connect_address\n");
fprintf(stderr, "\t-6 use ipv6\n");
fprintf(stderr, "\t-c cmsg -- test cmsg type <cmsg>\n");
fprintf(stderr, "\t-f offset -- stop the I/O after receiving and sending the specified amount "
@@ -126,13 +126,13 @@ static void die_usage(void)
fprintf(stderr, "\t-p num -- use port num\n");
fprintf(stderr,
"\t-P [saveWithPeek|saveAfterPeek] -- save data with/after MSG_PEEK form tcp socket\n");
- fprintf(stderr, "\t-t num -- set poll timeout to num\n");
- fprintf(stderr, "\t-T num -- set expected runtime to num ms\n");
fprintf(stderr, "\t-r num -- enable slow mode, limiting each write to num bytes "
"-- for remove addr tests\n");
fprintf(stderr, "\t-R num -- set SO_RCVBUF to num\n");
fprintf(stderr, "\t-s [MPTCP|TCP] -- use mptcp(default) or tcp sockets\n");
fprintf(stderr, "\t-S num -- set SO_SNDBUF to num\n");
+ fprintf(stderr, "\t-t num -- set poll timeout to num\n");
+ fprintf(stderr, "\t-T num -- set expected runtime to num ms\n");
fprintf(stderr, "\t-w num -- wait num sec before closing the socket\n");
exit(1);
}
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
index c1f7bac19942..773dd770a567 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
@@ -144,6 +144,7 @@ cleanup()
}
mptcp_lib_check_mptcp
+mptcp_lib_check_kallsyms
ip -Version > /dev/null 2>&1
if [ $? -ne 0 ];then
@@ -695,6 +696,15 @@ run_test_transparent()
return 0
fi
+ # IP(V6)_TRANSPARENT has been added after TOS support which came with
+ # the required infrastructure in MPTCP sockopt code. To support TOS, the
+ # following function has been exported (T). Not great but better than
+ # checking for a specific kernel version.
+ if ! mptcp_lib_kallsyms_has "T __ip_sock_set_tos$"; then
+ echo "INFO: ${msg} not supported by the kernel: SKIP"
+ return
+ fi
+
ip netns exec "$listener_ns" nft -f /dev/stdin <<"EOF"
flush ruleset
table inet mangle {
@@ -767,6 +777,11 @@ run_tests_peekmode()
run_tests_mptfo()
{
+ if ! mptcp_lib_kallsyms_has "mptcp_fastopen_"; then
+ echo "INFO: TFO not supported by the kernel: SKIP"
+ return
+ fi
+
echo "INFO: with MPTFO start"
ip netns exec "$ns1" sysctl -q net.ipv4.tcp_fastopen=2
ip netns exec "$ns2" sysctl -q net.ipv4.tcp_fastopen=1
@@ -787,6 +802,11 @@ run_tests_disconnect()
local old_cin=$cin
local old_sin=$sin
+ if ! mptcp_lib_kallsyms_has "mptcp_pm_data_reset$"; then
+ echo "INFO: Full disconnect not supported: SKIP"
+ return
+ fi
+
cat $cin $cin $cin > "$cin".disconnect
# force do_transfer to cope with the multiple tranmissions
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 4152370298bf..11ea1406d79f 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -8,6 +8,10 @@
. "$(dirname "${0}")/mptcp_lib.sh"
+# ShellCheck incorrectly believes that most of the code here is unreachable
+# because it's invoked by variable name, see how the "tests" array is used
+#shellcheck disable=SC2317
+
ret=0
sin=""
sinfail=""
@@ -21,6 +25,8 @@ capout=""
ns1=""
ns2=""
ksft_skip=4
+iptables="iptables"
+ip6tables="ip6tables"
timeout_poll=30
timeout_test=$((timeout_poll * 2 + 1))
capture=0
@@ -78,7 +84,7 @@ init_partial()
ip netns add $netns || exit $ksft_skip
ip -net $netns link set lo up
ip netns exec $netns sysctl -q net.mptcp.enabled=1
- ip netns exec $netns sysctl -q net.mptcp.pm_type=0
+ ip netns exec $netns sysctl -q net.mptcp.pm_type=0 2>/dev/null || true
ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0
ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0
if [ $checksum -eq 1 ]; then
@@ -136,13 +142,18 @@ cleanup_partial()
check_tools()
{
mptcp_lib_check_mptcp
+ mptcp_lib_check_kallsyms
if ! ip -Version &> /dev/null; then
echo "SKIP: Could not run test without ip tool"
exit $ksft_skip
fi
- if ! iptables -V &> /dev/null; then
+ # Use the legacy version if available to support old kernel versions
+ if iptables-legacy -V &> /dev/null; then
+ iptables="iptables-legacy"
+ ip6tables="ip6tables-legacy"
+ elif ! iptables -V &> /dev/null; then
echo "SKIP: Could not run all tests without iptables tool"
exit $ksft_skip
fi
@@ -181,6 +192,32 @@ cleanup()
cleanup_partial
}
+# $1: msg
+print_title()
+{
+ printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${1}"
+}
+
+# [ $1: fail msg ]
+mark_as_skipped()
+{
+ local msg="${1:-"Feature not supported"}"
+
+ mptcp_lib_fail_if_expected_feature "${msg}"
+
+ print_title "[ skip ] ${msg}"
+ printf "\n"
+}
+
+# $@: condition
+continue_if()
+{
+ if ! "${@}"; then
+ mark_as_skipped
+ return 1
+ fi
+}
+
skip_test()
{
if [ "${#only_tests_ids[@]}" -eq 0 ] && [ "${#only_tests_names[@]}" -eq 0 ]; then
@@ -224,6 +261,19 @@ reset()
return 0
}
+# $1: test name ; $2: counter to check
+reset_check_counter()
+{
+ reset "${1}" || return 1
+
+ local counter="${2}"
+
+ if ! nstat -asz "${counter}" | grep -wq "${counter}"; then
+ mark_as_skipped "counter '${counter}' is not available"
+ return 1
+ fi
+}
+
# $1: test name
reset_with_cookies()
{
@@ -243,17 +293,21 @@ reset_with_add_addr_timeout()
reset "${1}" || return 1
- tables="iptables"
+ tables="${iptables}"
if [ $ip -eq 6 ]; then
- tables="ip6tables"
+ tables="${ip6tables}"
fi
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
- ip netns exec $ns2 $tables -A OUTPUT -p tcp \
- -m tcp --tcp-option 30 \
- -m bpf --bytecode \
- "$CBPF_MPTCP_SUBOPTION_ADD_ADDR" \
- -j DROP
+
+ if ! ip netns exec $ns2 $tables -A OUTPUT -p tcp \
+ -m tcp --tcp-option 30 \
+ -m bpf --bytecode \
+ "$CBPF_MPTCP_SUBOPTION_ADD_ADDR" \
+ -j DROP; then
+ mark_as_skipped "unable to set the 'add addr' rule"
+ return 1
+ fi
}
# $1: test name
@@ -297,22 +351,17 @@ reset_with_allow_join_id0()
# tc action pedit offset 162 out of bounds
#
# Netfilter is used to mark packets with enough data.
-reset_with_fail()
+setup_fail_rules()
{
- reset "${1}" || return 1
-
- ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=1
- ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=1
-
check_invert=1
validate_checksum=1
- local i="$2"
- local ip="${3:-4}"
+ local i="$1"
+ local ip="${2:-4}"
local tables
- tables="iptables"
+ tables="${iptables}"
if [ $ip -eq 6 ]; then
- tables="ip6tables"
+ tables="${ip6tables}"
fi
ip netns exec $ns2 $tables \
@@ -322,15 +371,32 @@ reset_with_fail()
-p tcp \
-m length --length 150:9999 \
-m statistic --mode nth --packet 1 --every 99999 \
- -j MARK --set-mark 42 || exit 1
+ -j MARK --set-mark 42 || return ${ksft_skip}
- tc -n $ns2 qdisc add dev ns2eth$i clsact || exit 1
+ tc -n $ns2 qdisc add dev ns2eth$i clsact || return ${ksft_skip}
tc -n $ns2 filter add dev ns2eth$i egress \
protocol ip prio 1000 \
handle 42 fw \
action pedit munge offset 148 u8 invert \
pipe csum tcp \
- index 100 || exit 1
+ index 100 || return ${ksft_skip}
+}
+
+reset_with_fail()
+{
+ reset_check_counter "${1}" "MPTcpExtInfiniteMapTx" || return 1
+ shift
+
+ ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=1
+ ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=1
+
+ local rc=0
+ setup_fail_rules "${@}" || rc=$?
+
+ if [ ${rc} -eq ${ksft_skip} ]; then
+ mark_as_skipped "unable to set the 'fail' rules"
+ return 1
+ fi
}
reset_with_events()
@@ -345,6 +411,25 @@ reset_with_events()
evts_ns2_pid=$!
}
+reset_with_tcp_filter()
+{
+ reset "${1}" || return 1
+ shift
+
+ local ns="${!1}"
+ local src="${2}"
+ local target="${3}"
+
+ if ! ip netns exec "${ns}" ${iptables} \
+ -A INPUT \
+ -s "${src}" \
+ -p tcp \
+ -j "${target}"; then
+ mark_as_skipped "unable to set the filter rules"
+ return 1
+ fi
+}
+
fail_test()
{
ret=1
@@ -377,8 +462,9 @@ check_transfer()
local line
if [ -n "$bytes" ]; then
+ local out_size
# when truncating we must check the size explicitly
- local out_size=$(wc -c $out | awk '{print $1}')
+ out_size=$(wc -c $out | awk '{print $1}')
if [ $out_size -ne $bytes ]; then
echo "[ FAIL ] $what output file has wrong size ($out_size, $bytes)"
fail_test
@@ -462,11 +548,25 @@ wait_local_port_listen()
done
}
-rm_addr_count()
+# $1: ns ; $2: counter
+get_counter()
{
- local ns=${1}
+ local ns="${1}"
+ local counter="${2}"
+ local count
+
+ count=$(ip netns exec ${ns} nstat -asz "${counter}" | awk 'NR==1 {next} {print $2}')
+ if [ -z "${count}" ]; then
+ mptcp_lib_fail_if_expected_feature "${counter} counter"
+ return 1
+ fi
- ip netns exec ${ns} nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'
+ echo "${count}"
+}
+
+rm_addr_count()
+{
+ get_counter "${1}" "MPTcpExtRmAddr"
}
# $1: ns, $2: old rm_addr counter in $ns
@@ -489,11 +589,11 @@ wait_mpj()
local ns="${1}"
local cnt old_cnt
- old_cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
+ old_cnt=$(get_counter ${ns} "MPTcpExtMPJoinAckRx")
local i
for i in $(seq 10); do
- cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
+ cnt=$(get_counter ${ns} "MPTcpExtMPJoinAckRx")
[ "$cnt" = "${old_cnt}" ] || break
sleep 0.1
done
@@ -513,6 +613,7 @@ kill_events_pids()
kill_tests_wait()
{
+ #shellcheck disable=SC2046
kill -SIGUSR1 $(ip netns pids $ns2) $(ip netns pids $ns1)
wait
}
@@ -692,15 +793,6 @@ pm_nl_check_endpoint()
fi
}
-filter_tcp_from()
-{
- local ns="${1}"
- local src="${2}"
- local target="${3}"
-
- ip netns exec "${ns}" iptables -A INPUT -s "${src}" -p tcp -j "${target}"
-}
-
do_transfer()
{
local listener_ns="$1"
@@ -1151,12 +1243,13 @@ chk_csum_nr()
fi
printf "%-${nr_blank}s %s" " " "sum"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}')
- [ -z "$count" ] && count=0
+ count=$(get_counter ${ns1} "MPTcpExtDataCsumErr")
if [ "$count" != "$csum_ns1" ]; then
extra_msg="$extra_msg ns1=$count"
fi
- if { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } ||
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } ||
{ [ "$count" -lt $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 1 ]; }; then
echo "[fail] got $count data checksum error[s] expected $csum_ns1"
fail_test
@@ -1165,12 +1258,13 @@ chk_csum_nr()
echo -n "[ ok ]"
fi
echo -n " - csum "
- count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}')
- [ -z "$count" ] && count=0
+ count=$(get_counter ${ns2} "MPTcpExtDataCsumErr")
if [ "$count" != "$csum_ns2" ]; then
extra_msg="$extra_msg ns2=$count"
fi
- if { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } ||
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } ||
{ [ "$count" -lt $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 1 ]; }; then
echo "[fail] got $count data checksum error[s] expected $csum_ns2"
fail_test
@@ -1212,12 +1306,13 @@ chk_fail_nr()
fi
printf "%-${nr_blank}s %s" " " "ftx"
- count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPFailTx | awk '{print $2}')
- [ -z "$count" ] && count=0
+ count=$(get_counter ${ns_tx} "MPTcpExtMPFailTx")
if [ "$count" != "$fail_tx" ]; then
extra_msg="$extra_msg,tx=$count"
fi
- if { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } ||
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } ||
{ [ "$count" -gt "$fail_tx" ] && [ $allow_tx_lost -eq 1 ]; }; then
echo "[fail] got $count MP_FAIL[s] TX expected $fail_tx"
fail_test
@@ -1227,12 +1322,13 @@ chk_fail_nr()
fi
echo -n " - failrx"
- count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPFailRx | awk '{print $2}')
- [ -z "$count" ] && count=0
+ count=$(get_counter ${ns_rx} "MPTcpExtMPFailRx")
if [ "$count" != "$fail_rx" ]; then
extra_msg="$extra_msg,rx=$count"
fi
- if { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } ||
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } ||
{ [ "$count" -gt "$fail_rx" ] && [ $allow_rx_lost -eq 1 ]; }; then
echo "[fail] got $count MP_FAIL[s] RX expected $fail_rx"
fail_test
@@ -1264,10 +1360,11 @@ chk_fclose_nr()
fi
printf "%-${nr_blank}s %s" " " "ctx"
- count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPFastcloseTx | awk '{print $2}')
- [ -z "$count" ] && count=0
- [ "$count" != "$fclose_tx" ] && extra_msg="$extra_msg,tx=$count"
- if [ "$count" != "$fclose_tx" ]; then
+ count=$(get_counter ${ns_tx} "MPTcpExtMPFastcloseTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$fclose_tx" ]; then
+ extra_msg="$extra_msg,tx=$count"
echo "[fail] got $count MP_FASTCLOSE[s] TX expected $fclose_tx"
fail_test
dump_stats=1
@@ -1276,10 +1373,11 @@ chk_fclose_nr()
fi
echo -n " - fclzrx"
- count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPFastcloseRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- [ "$count" != "$fclose_rx" ] && extra_msg="$extra_msg,rx=$count"
- if [ "$count" != "$fclose_rx" ]; then
+ count=$(get_counter ${ns_rx} "MPTcpExtMPFastcloseRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$fclose_rx" ]; then
+ extra_msg="$extra_msg,rx=$count"
echo "[fail] got $count MP_FASTCLOSE[s] RX expected $fclose_rx"
fail_test
dump_stats=1
@@ -1310,9 +1408,10 @@ chk_rst_nr()
fi
printf "%-${nr_blank}s %s" " " "rtx"
- count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPRstTx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ $count -lt $rst_tx ]; then
+ count=$(get_counter ${ns_tx} "MPTcpExtMPRstTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ $count -lt $rst_tx ]; then
echo "[fail] got $count MP_RST[s] TX expected $rst_tx"
fail_test
dump_stats=1
@@ -1321,9 +1420,10 @@ chk_rst_nr()
fi
echo -n " - rstrx "
- count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPRstRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" -lt "$rst_rx" ]; then
+ count=$(get_counter ${ns_rx} "MPTcpExtMPRstRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" -lt "$rst_rx" ]; then
echo "[fail] got $count MP_RST[s] RX expected $rst_rx"
fail_test
dump_stats=1
@@ -1344,9 +1444,10 @@ chk_infi_nr()
local dump_stats
printf "%-${nr_blank}s %s" " " "itx"
- count=$(ip netns exec $ns2 nstat -as | grep InfiniteMapTx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$infi_tx" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtInfiniteMapTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$infi_tx" ]; then
echo "[fail] got $count infinite map[s] TX expected $infi_tx"
fail_test
dump_stats=1
@@ -1355,9 +1456,10 @@ chk_infi_nr()
fi
echo -n " - infirx"
- count=$(ip netns exec $ns1 nstat -as | grep InfiniteMapRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$infi_rx" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtInfiniteMapRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$infi_rx" ]; then
echo "[fail] got $count infinite map[s] RX expected $infi_rx"
fail_test
dump_stats=1
@@ -1389,9 +1491,10 @@ chk_join_nr()
fi
printf "%03u %-36s %s" "${TEST_COUNT}" "${title}" "syn"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinSynRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinSynRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn expected $syn_nr"
fail_test
dump_stats=1
@@ -1401,9 +1504,10 @@ chk_join_nr()
echo -n " - synack"
with_cookie=$(ip netns exec $ns2 sysctl -n net.ipv4.tcp_syncookies)
- count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinSynAckRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_ack_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtMPJoinSynAckRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_ack_nr" ]; then
# simult connections exceeding the limit with cookie enabled could go up to
# synack validation as the conn limit can be enforced reliably only after
# the subflow creation
@@ -1419,9 +1523,10 @@ chk_join_nr()
fi
echo -n " - ack"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinAckRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$ack_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinAckRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack expected $ack_nr"
fail_test
dump_stats=1
@@ -1453,12 +1558,12 @@ chk_stale_nr()
local recover_nr
printf "%-${nr_blank}s %-18s" " " "stale"
- stale_nr=$(ip netns exec $ns nstat -as | grep MPTcpExtSubflowStale | awk '{print $2}')
- [ -z "$stale_nr" ] && stale_nr=0
- recover_nr=$(ip netns exec $ns nstat -as | grep MPTcpExtSubflowRecover | awk '{print $2}')
- [ -z "$recover_nr" ] && recover_nr=0
- if [ $stale_nr -lt $stale_min ] ||
+ stale_nr=$(get_counter ${ns} "MPTcpExtSubflowStale")
+ recover_nr=$(get_counter ${ns} "MPTcpExtSubflowRecover")
+ if [ -z "$stale_nr" ] || [ -z "$recover_nr" ]; then
+ echo "[skip]"
+ elif [ $stale_nr -lt $stale_min ] ||
{ [ $stale_max -gt 0 ] && [ $stale_nr -gt $stale_max ]; } ||
[ $((stale_nr - recover_nr)) -ne $stale_delta ]; then
echo "[fail] got $stale_nr stale[s] $recover_nr recover[s], " \
@@ -1494,12 +1599,12 @@ chk_add_nr()
timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout)
printf "%-${nr_blank}s %s" " " "add"
- count=$(ip netns exec $ns2 nstat -as MPTcpExtAddAddr | grep MPTcpExtAddAddr | awk '{print $2}')
- [ -z "$count" ] && count=0
-
+ count=$(get_counter ${ns2} "MPTcpExtAddAddr")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
# if the test configured a short timeout tolerate greater then expected
# add addrs options, due to retransmissions
- if [ "$count" != "$add_nr" ] && { [ "$timeout" -gt 1 ] || [ "$count" -lt "$add_nr" ]; }; then
+ elif [ "$count" != "$add_nr" ] && { [ "$timeout" -gt 1 ] || [ "$count" -lt "$add_nr" ]; }; then
echo "[fail] got $count ADD_ADDR[s] expected $add_nr"
fail_test
dump_stats=1
@@ -1508,9 +1613,10 @@ chk_add_nr()
fi
echo -n " - echo "
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtEchoAdd | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$echo_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtEchoAdd")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$echo_nr" ]; then
echo "[fail] got $count ADD_ADDR echo[s] expected $echo_nr"
fail_test
dump_stats=1
@@ -1520,9 +1626,10 @@ chk_add_nr()
if [ $port_nr -gt 0 ]; then
echo -n " - pt "
- count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtPortAdd | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$port_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtPortAdd")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$port_nr" ]; then
echo "[fail] got $count ADD_ADDR[s] with a port-number expected $port_nr"
fail_test
dump_stats=1
@@ -1531,10 +1638,10 @@ chk_add_nr()
fi
printf "%-${nr_blank}s %s" " " "syn"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortSynRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinPortSynRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn with a different \
port-number expected $syn_nr"
fail_test
@@ -1544,10 +1651,10 @@ chk_add_nr()
fi
echo -n " - synack"
- count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinPortSynAckRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_ack_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_ack_nr" ]; then
echo "[fail] got $count JOIN[s] synack with a different \
port-number expected $syn_ack_nr"
fail_test
@@ -1557,10 +1664,10 @@ chk_add_nr()
fi
echo -n " - ack"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortAckRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$ack_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinPortAckRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack with a different \
port-number expected $ack_nr"
fail_test
@@ -1570,10 +1677,10 @@ chk_add_nr()
fi
printf "%-${nr_blank}s %s" " " "syn"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortSynRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$mis_syn_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMismatchPortSynRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$mis_syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn with a mismatched \
port-number expected $mis_syn_nr"
fail_test
@@ -1583,10 +1690,10 @@ chk_add_nr()
fi
echo -n " - ack "
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortAckRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$mis_ack_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMismatchPortAckRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$mis_ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack with a mismatched \
port-number expected $mis_ack_nr"
fail_test
@@ -1630,9 +1737,10 @@ chk_rm_nr()
fi
printf "%-${nr_blank}s %s" " " "rm "
- count=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmAddr | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$rm_addr_nr" ]; then
+ count=$(get_counter ${addr_ns} "MPTcpExtRmAddr")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$rm_addr_nr" ]; then
echo "[fail] got $count RM_ADDR[s] expected $rm_addr_nr"
fail_test
dump_stats=1
@@ -1641,29 +1749,27 @@ chk_rm_nr()
fi
echo -n " - rmsf "
- count=$(ip netns exec $subflow_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ -n "$simult" ]; then
+ count=$(get_counter ${subflow_ns} "MPTcpExtRmSubflow")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ -n "$simult" ]; then
local cnt suffix
- cnt=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}')
+ cnt=$(get_counter ${addr_ns} "MPTcpExtRmSubflow")
# in case of simult flush, the subflow removal count on each side is
# unreliable
- [ -z "$cnt" ] && cnt=0
count=$((count + cnt))
[ "$count" != "$rm_subflow_nr" ] && suffix="$count in [$rm_subflow_nr:$((rm_subflow_nr*2))]"
if [ $count -ge "$rm_subflow_nr" ] && \
[ "$count" -le "$((rm_subflow_nr *2 ))" ]; then
- echo "[ ok ] $suffix"
+ echo -n "[ ok ] $suffix"
else
echo "[fail] got $count RM_SUBFLOW[s] expected in range [$rm_subflow_nr:$((rm_subflow_nr*2))]"
fail_test
dump_stats=1
fi
- return
- fi
- if [ "$count" != "$rm_subflow_nr" ]; then
+ elif [ "$count" != "$rm_subflow_nr" ]; then
echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr"
fail_test
dump_stats=1
@@ -1684,9 +1790,10 @@ chk_prio_nr()
local dump_stats
printf "%-${nr_blank}s %s" " " "ptx"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$mp_prio_nr_tx" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPPrioTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$mp_prio_nr_tx" ]; then
echo "[fail] got $count MP_PRIO[s] TX expected $mp_prio_nr_tx"
fail_test
dump_stats=1
@@ -1695,9 +1802,10 @@ chk_prio_nr()
fi
echo -n " - prx "
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$mp_prio_nr_rx" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPPrioRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$mp_prio_nr_rx" ]; then
echo "[fail] got $count MP_PRIO[s] RX expected $mp_prio_nr_rx"
fail_test
dump_stats=1
@@ -1725,7 +1833,7 @@ chk_subflow_nr()
cnt1=$(ss -N $ns1 -tOni | grep -c token)
cnt2=$(ss -N $ns2 -tOni | grep -c token)
- if [ "$cnt1" != "$subflow_nr" -o "$cnt2" != "$subflow_nr" ]; then
+ if [ "$cnt1" != "$subflow_nr" ] || [ "$cnt2" != "$subflow_nr" ]; then
echo "[fail] got $cnt1:$cnt2 subflows expected $subflow_nr"
fail_test
dump_stats=1
@@ -1773,7 +1881,7 @@ wait_attempt_fail()
while [ $time -lt $timeout_ms ]; do
local cnt
- cnt=$(ip netns exec $ns nstat -as TcpAttemptFails | grep TcpAttemptFails | awk '{print $2}')
+ cnt=$(get_counter ${ns} "TcpAttemptFails")
[ "$cnt" = 1 ] && return 1
time=$((time + 100))
@@ -1866,23 +1974,23 @@ subflows_error_tests()
fi
# multiple subflows, with subflow creation error
- if reset "multi subflows, with failing subflow"; then
+ if reset_with_tcp_filter "multi subflows, with failing subflow" ns1 10.0.3.2 REJECT &&
+ continue_if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
- filter_tcp_from $ns1 10.0.3.2 REJECT
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
chk_join_nr 1 1 1
fi
# multiple subflows, with subflow timeout on MPJ
- if reset "multi subflows, with subflow timeout"; then
+ if reset_with_tcp_filter "multi subflows, with subflow timeout" ns1 10.0.3.2 DROP &&
+ continue_if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
- filter_tcp_from $ns1 10.0.3.2 DROP
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
chk_join_nr 1 1 1
fi
@@ -1890,11 +1998,11 @@ subflows_error_tests()
# multiple subflows, check that the endpoint corresponding to
# closed subflow (due to reset) is not reused if additional
# subflows are added later
- if reset "multi subflows, fair usage on close"; then
+ if reset_with_tcp_filter "multi subflows, fair usage on close" ns1 10.0.3.2 REJECT &&
+ continue_if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
- filter_tcp_from $ns1 10.0.3.2 REJECT
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow &
# mpj subflow will be in TW after the reset
@@ -1994,11 +2102,18 @@ signal_address_tests()
# the peer could possibly miss some addr notification, allow retransmission
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
- chk_join_nr 3 3 3
- # the server will not signal the address terminating
- # the MPC subflow
- chk_add_nr 3 3
+ # It is not directly linked to the commit introducing this
+ # symbol but for the parent one which is linked anyway.
+ if ! mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
+ chk_join_nr 3 3 2
+ chk_add_nr 4 4
+ else
+ chk_join_nr 3 3 3
+ # the server will not signal the address terminating
+ # the MPC subflow
+ chk_add_nr 3 3
+ fi
fi
}
@@ -2239,7 +2354,12 @@ remove_tests()
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
chk_join_nr 3 3 3
- chk_rm_nr 0 3 simult
+
+ if mptcp_lib_kversion_ge 5.18; then
+ chk_rm_nr 0 3 simult
+ else
+ chk_rm_nr 3 3
+ fi
fi
# addresses flush
@@ -2477,7 +2597,8 @@ v4mapped_tests()
mixed_tests()
{
- if reset "IPv4 sockets do not use IPv6 addresses"; then
+ if reset "IPv4 sockets do not use IPv6 addresses" &&
+ continue_if mptcp_lib_kversion_ge 6.3; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
@@ -2486,7 +2607,8 @@ mixed_tests()
fi
# Need an IPv6 mptcp socket to allow subflows of both families
- if reset "simult IPv4 and IPv6 subflows"; then
+ if reset "simult IPv4 and IPv6 subflows" &&
+ continue_if mptcp_lib_kversion_ge 6.3; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 10.0.1.1 flags signal
@@ -2495,7 +2617,8 @@ mixed_tests()
fi
# cross families subflows will not be created even in fullmesh mode
- if reset "simult IPv4 and IPv6 subflows, fullmesh 1x1"; then
+ if reset "simult IPv4 and IPv6 subflows, fullmesh 1x1" &&
+ continue_if mptcp_lib_kversion_ge 6.3; then
pm_nl_set_limits $ns1 0 4
pm_nl_set_limits $ns2 1 4
pm_nl_add_endpoint $ns2 dead:beef:2::2 flags subflow,fullmesh
@@ -2506,7 +2629,8 @@ mixed_tests()
# fullmesh still tries to create all the possibly subflows with
# matching family
- if reset "simult IPv4 and IPv6 subflows, fullmesh 2x2"; then
+ if reset "simult IPv4 and IPv6 subflows, fullmesh 2x2" &&
+ continue_if mptcp_lib_kversion_ge 6.3; then
pm_nl_set_limits $ns1 0 4
pm_nl_set_limits $ns2 2 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
@@ -2519,7 +2643,8 @@ mixed_tests()
backup_tests()
{
# single subflow, backup
- if reset "single subflow, backup"; then
+ if reset "single subflow, backup" &&
+ continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
@@ -2529,7 +2654,8 @@ backup_tests()
fi
# single address, backup
- if reset "single address, backup"; then
+ if reset "single address, backup" &&
+ continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 0 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_set_limits $ns2 1 1
@@ -2540,7 +2666,8 @@ backup_tests()
fi
# single address with port, backup
- if reset "single address with port, backup"; then
+ if reset "single address with port, backup" &&
+ continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 0 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
pm_nl_set_limits $ns2 1 1
@@ -2550,14 +2677,16 @@ backup_tests()
chk_prio_nr 1 1
fi
- if reset "mpc backup"; then
+ if reset "mpc backup" &&
+ continue_if mptcp_lib_kallsyms_doesnt_have "mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,backup
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
chk_join_nr 0 0 0
chk_prio_nr 0 1
fi
- if reset "mpc backup both sides"; then
+ if reset "mpc backup both sides" &&
+ continue_if mptcp_lib_kallsyms_doesnt_have "mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns1 10.0.1.1 flags subflow,backup
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,backup
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
@@ -2565,14 +2694,16 @@ backup_tests()
chk_prio_nr 1 1
fi
- if reset "mpc switch to backup"; then
+ if reset "mpc switch to backup" &&
+ continue_if mptcp_lib_kallsyms_doesnt_have "mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
chk_join_nr 0 0 0
chk_prio_nr 0 1
fi
- if reset "mpc switch to backup both sides"; then
+ if reset "mpc switch to backup both sides" &&
+ continue_if mptcp_lib_kallsyms_doesnt_have "mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns1 10.0.1.1 flags subflow
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
@@ -2598,38 +2729,41 @@ verify_listener_events()
local family
local saddr
local sport
+ local name
if [ $e_type = $LISTENER_CREATED ]; then
- stdbuf -o0 -e0 printf "\t\t\t\t\t CREATE_LISTENER %s:%s"\
- $e_saddr $e_sport
+ name="LISTENER_CREATED"
elif [ $e_type = $LISTENER_CLOSED ]; then
- stdbuf -o0 -e0 printf "\t\t\t\t\t CLOSE_LISTENER %s:%s "\
- $e_saddr $e_sport
+ name="LISTENER_CLOSED"
+ else
+ name="$e_type"
fi
- type=$(grep "type:$e_type," $evt |
- sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q')
- family=$(grep "type:$e_type," $evt |
- sed --unbuffered -n 's/.*\(family:\)\([[:digit:]]*\).*$/\2/p;q')
- sport=$(grep "type:$e_type," $evt |
- sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q')
+ printf "%-${nr_blank}s %s %s:%s " " " "$name" "$e_saddr" "$e_sport"
+
+ if ! mptcp_lib_kallsyms_has "mptcp_event_pm_listener$"; then
+ printf "[skip]: event not supported\n"
+ return
+ fi
+
+ type=$(grep "type:$e_type," $evt | sed -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q')
+ family=$(grep "type:$e_type," $evt | sed -n 's/.*\(family:\)\([[:digit:]]*\).*$/\2/p;q')
+ sport=$(grep "type:$e_type," $evt | sed -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q')
if [ $family ] && [ $family = $AF_INET6 ]; then
- saddr=$(grep "type:$e_type," $evt |
- sed --unbuffered -n 's/.*\(saddr6:\)\([0-9a-f:.]*\).*$/\2/p;q')
+ saddr=$(grep "type:$e_type," $evt | sed -n 's/.*\(saddr6:\)\([0-9a-f:.]*\).*$/\2/p;q')
else
- saddr=$(grep "type:$e_type," $evt |
- sed --unbuffered -n 's/.*\(saddr4:\)\([0-9.]*\).*$/\2/p;q')
+ saddr=$(grep "type:$e_type," $evt | sed -n 's/.*\(saddr4:\)\([0-9.]*\).*$/\2/p;q')
fi
if [ $type ] && [ $type = $e_type ] &&
[ $family ] && [ $family = $e_family ] &&
[ $saddr ] && [ $saddr = $e_saddr ] &&
[ $sport ] && [ $sport = $e_sport ]; then
- stdbuf -o0 -e0 printf "[ ok ]\n"
+ echo "[ ok ]"
return 0
fi
fail_test
- stdbuf -o0 -e0 printf "[fail]\n"
+ echo "[fail]"
}
add_addr_ports_tests()
@@ -2935,7 +3069,8 @@ fullmesh_tests()
fi
# set fullmesh flag
- if reset "set fullmesh flag test"; then
+ if reset "set fullmesh flag test" &&
+ continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow
pm_nl_set_limits $ns2 4 4
@@ -2945,7 +3080,8 @@ fullmesh_tests()
fi
# set nofullmesh flag
- if reset "set nofullmesh flag test"; then
+ if reset "set nofullmesh flag test" &&
+ continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow,fullmesh
pm_nl_set_limits $ns2 4 4
@@ -2955,7 +3091,8 @@ fullmesh_tests()
fi
# set backup,fullmesh flags
- if reset "set backup,fullmesh flags test"; then
+ if reset "set backup,fullmesh flags test" &&
+ continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow
pm_nl_set_limits $ns2 4 4
@@ -2966,7 +3103,8 @@ fullmesh_tests()
fi
# set nobackup,nofullmesh flags
- if reset "set nobackup,nofullmesh flags test"; then
+ if reset "set nobackup,nofullmesh flags test" &&
+ continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_set_limits $ns2 4 4
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow,backup,fullmesh
@@ -2979,14 +3117,14 @@ fullmesh_tests()
fastclose_tests()
{
- if reset "fastclose test"; then
+ if reset_check_counter "fastclose test" "MPTcpExtMPFastcloseTx"; then
run_tests $ns1 $ns2 10.0.1.1 1024 0 fastclose_client
chk_join_nr 0 0 0
chk_fclose_nr 1 1
chk_rst_nr 1 1 invert
fi
- if reset "fastclose server test"; then
+ if reset_check_counter "fastclose server test" "MPTcpExtMPFastcloseRx"; then
run_tests $ns1 $ns2 10.0.1.1 1024 0 fastclose_server
chk_join_nr 0 0 0
chk_fclose_nr 1 1 invert
@@ -3024,7 +3162,8 @@ fail_tests()
userspace_tests()
{
# userspace pm type prevents add_addr
- if reset "userspace pm type prevents add_addr"; then
+ if reset "userspace pm type prevents add_addr" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
@@ -3035,7 +3174,8 @@ userspace_tests()
fi
# userspace pm type does not echo add_addr without daemon
- if reset "userspace pm no echo w/o daemon"; then
+ if reset "userspace pm no echo w/o daemon" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns2
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
@@ -3046,7 +3186,8 @@ userspace_tests()
fi
# userspace pm type rejects join
- if reset "userspace pm type rejects join"; then
+ if reset "userspace pm type rejects join" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
@@ -3056,7 +3197,8 @@ userspace_tests()
fi
# userspace pm type does not send join
- if reset "userspace pm type does not send join"; then
+ if reset "userspace pm type does not send join" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns2
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
@@ -3066,7 +3208,8 @@ userspace_tests()
fi
# userspace pm type prevents mp_prio
- if reset "userspace pm type prevents mp_prio"; then
+ if reset "userspace pm type prevents mp_prio" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
@@ -3077,7 +3220,8 @@ userspace_tests()
fi
# userspace pm type prevents rm_addr
- if reset "userspace pm type prevents rm_addr"; then
+ if reset "userspace pm type prevents rm_addr" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
set_userspace_pm $ns2
pm_nl_set_limits $ns1 0 1
@@ -3089,7 +3233,8 @@ userspace_tests()
fi
# userspace pm add & remove address
- if reset_with_events "userspace pm add & remove address"; then
+ if reset_with_events "userspace pm add & remove address" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
pm_nl_set_limits $ns2 1 1
run_tests $ns1 $ns2 10.0.1.1 0 userspace_1 0 slow
@@ -3100,7 +3245,8 @@ userspace_tests()
fi
# userspace pm create destroy subflow
- if reset_with_events "userspace pm create destroy subflow"; then
+ if reset_with_events "userspace pm create destroy subflow" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns2
pm_nl_set_limits $ns1 0 1
run_tests $ns1 $ns2 10.0.1.1 0 0 userspace_1 slow
@@ -3112,8 +3258,10 @@ userspace_tests()
endpoint_tests()
{
+ # subflow_rebuild_header is needed to support the implicit flag
# userspace pm type prevents add_addr
- if reset "implicit EP"; then
+ if reset "implicit EP" &&
+ mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 2 2
pm_nl_set_limits $ns2 2 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
@@ -3133,7 +3281,8 @@ endpoint_tests()
kill_tests_wait
fi
- if reset "delete and re-add"; then
+ if reset "delete and re-add" &&
+ mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
diff --git a/tools/testing/selftests/net/mptcp/mptcp_lib.sh b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
index 3286536b79d5..f32045b23b89 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_lib.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
@@ -38,3 +38,67 @@ mptcp_lib_check_mptcp() {
exit ${KSFT_SKIP}
fi
}
+
+mptcp_lib_check_kallsyms() {
+ if ! mptcp_lib_has_file "/proc/kallsyms"; then
+ echo "SKIP: CONFIG_KALLSYMS is missing"
+ exit ${KSFT_SKIP}
+ fi
+}
+
+# Internal: use mptcp_lib_kallsyms_has() instead
+__mptcp_lib_kallsyms_has() {
+ local sym="${1}"
+
+ mptcp_lib_check_kallsyms
+
+ grep -q " ${sym}" /proc/kallsyms
+}
+
+# $1: part of a symbol to look at, add '$' at the end for full name
+mptcp_lib_kallsyms_has() {
+ local sym="${1}"
+
+ if __mptcp_lib_kallsyms_has "${sym}"; then
+ return 0
+ fi
+
+ mptcp_lib_fail_if_expected_feature "${sym} symbol not found"
+}
+
+# $1: part of a symbol to look at, add '$' at the end for full name
+mptcp_lib_kallsyms_doesnt_have() {
+ local sym="${1}"
+
+ if ! __mptcp_lib_kallsyms_has "${sym}"; then
+ return 0
+ fi
+
+ mptcp_lib_fail_if_expected_feature "${sym} symbol has been found"
+}
+
+# !!!AVOID USING THIS!!!
+# Features might not land in the expected version and features can be backported
+#
+# $1: kernel version, e.g. 6.3
+mptcp_lib_kversion_ge() {
+ local exp_maj="${1%.*}"
+ local exp_min="${1#*.}"
+ local v maj min
+
+ # If the kernel has backported features, set this env var to 1:
+ if [ "${SELFTESTS_MPTCP_LIB_NO_KVERSION_CHECK:-}" = "1" ]; then
+ return 0
+ fi
+
+ v=$(uname -r | cut -d'.' -f1,2)
+ maj=${v%.*}
+ min=${v#*.}
+
+ if [ "${maj}" -gt "${exp_maj}" ] ||
+ { [ "${maj}" -eq "${exp_maj}" ] && [ "${min}" -ge "${exp_min}" ]; }; then
+ return 0
+ fi
+
+ mptcp_lib_fail_if_expected_feature "kernel version ${1} lower than ${v}"
+}
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index ae61f39556ca..b35148edbf02 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -87,6 +87,10 @@ struct so_state {
uint64_t tcpi_rcv_delta;
};
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
static void die_perror(const char *msg)
{
perror(msg);
@@ -349,13 +353,14 @@ static void do_getsockopt_tcp_info(struct so_state *s, int fd, size_t r, size_t
xerror("getsockopt MPTCP_TCPINFO (tries %d, %m)");
assert(olen <= sizeof(ti));
- assert(ti.d.size_user == ti.d.size_kernel);
- assert(ti.d.size_user == sizeof(struct tcp_info));
+ assert(ti.d.size_kernel > 0);
+ assert(ti.d.size_user ==
+ MIN(ti.d.size_kernel, sizeof(struct tcp_info)));
assert(ti.d.num_subflows == 1);
assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data));
olen -= sizeof(struct mptcp_subflow_data);
- assert(olen == sizeof(struct tcp_info));
+ assert(olen == ti.d.size_user);
if (ti.ti[0].tcpi_bytes_sent == w &&
ti.ti[0].tcpi_bytes_received == r)
@@ -401,13 +406,14 @@ static void do_getsockopt_subflow_addrs(int fd)
die_perror("getsockopt MPTCP_SUBFLOW_ADDRS");
assert(olen <= sizeof(addrs));
- assert(addrs.d.size_user == addrs.d.size_kernel);
- assert(addrs.d.size_user == sizeof(struct mptcp_subflow_addrs));
+ assert(addrs.d.size_kernel > 0);
+ assert(addrs.d.size_user ==
+ MIN(addrs.d.size_kernel, sizeof(struct mptcp_subflow_addrs)));
assert(addrs.d.num_subflows == 1);
assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data));
olen -= sizeof(struct mptcp_subflow_data);
- assert(olen == sizeof(struct mptcp_subflow_addrs));
+ assert(olen == addrs.d.size_user);
llen = sizeof(local);
ret = getsockname(fd, (struct sockaddr *)&local, &llen);
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index ff5adbb9c7f2..f295a371ff14 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -87,6 +87,7 @@ cleanup()
}
mptcp_lib_check_mptcp
+mptcp_lib_check_kallsyms
ip -Version > /dev/null 2>&1
if [ $? -ne 0 ];then
@@ -186,9 +187,14 @@ do_transfer()
local_addr="0.0.0.0"
fi
+ cmsg="TIMESTAMPNS"
+ if mptcp_lib_kallsyms_has "mptcp_ioctl$"; then
+ cmsg+=",TCPINQ"
+ fi
+
timeout ${timeout_test} \
ip netns exec ${listener_ns} \
- $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c TIMESTAMPNS,TCPINQ \
+ $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c "${cmsg}" \
${local_addr} < "$sin" > "$sout" &
local spid=$!
@@ -196,7 +202,7 @@ do_transfer()
timeout ${timeout_test} \
ip netns exec ${connector_ns} \
- $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c TIMESTAMPNS,TCPINQ \
+ $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c "${cmsg}" \
$connect_addr < "$cin" > "$cout" &
local cpid=$!
@@ -253,6 +259,11 @@ do_mptcp_sockopt_tests()
{
local lret=0
+ if ! mptcp_lib_kallsyms_has "mptcp_diag_fill_info$"; then
+ echo "INFO: MPTCP sockopt not supported: SKIP"
+ return
+ fi
+
ip netns exec "$ns_sbox" ./mptcp_sockopt
lret=$?
@@ -307,6 +318,11 @@ do_tcpinq_tests()
{
local lret=0
+ if ! mptcp_lib_kallsyms_has "mptcp_ioctl$"; then
+ echo "INFO: TCP_INQ not supported: SKIP"
+ return
+ fi
+
local args
for args in "-t tcp" "-r tcp"; do
do_tcpinq_test $args
diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh
index 32f7533e0919..d02e0d63a8f9 100755
--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh
+++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh
@@ -73,8 +73,12 @@ check()
}
check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "defaults addr list"
-check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
+
+default_limits="$(ip netns exec $ns1 ./pm_nl_ctl limits)"
+if mptcp_lib_expect_all_features; then
+ check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
subflows 2" "defaults limits"
+fi
ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1
ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.2 flags subflow dev lo
@@ -121,12 +125,10 @@ ip netns exec $ns1 ./pm_nl_ctl flush
check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "flush addrs"
ip netns exec $ns1 ./pm_nl_ctl limits 9 1
-check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
-subflows 2" "rcv addrs above hard limit"
+check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "rcv addrs above hard limit"
ip netns exec $ns1 ./pm_nl_ctl limits 1 9
-check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
-subflows 2" "subflows above hard limit"
+check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "subflows above hard limit"
ip netns exec $ns1 ./pm_nl_ctl limits 8 8
check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 8
@@ -176,14 +178,19 @@ subflow,backup 10.0.1.1" "set flags (backup)"
ip netns exec $ns1 ./pm_nl_ctl set 10.0.1.1 flags nobackup
check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
subflow 10.0.1.1" " (nobackup)"
+
+# fullmesh support has been added later
ip netns exec $ns1 ./pm_nl_ctl set id 1 flags fullmesh
-check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+if ip netns exec $ns1 ./pm_nl_ctl dump | grep -q "fullmesh" ||
+ mptcp_lib_expect_all_features; then
+ check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
subflow,fullmesh 10.0.1.1" " (fullmesh)"
-ip netns exec $ns1 ./pm_nl_ctl set id 1 flags nofullmesh
-check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+ ip netns exec $ns1 ./pm_nl_ctl set id 1 flags nofullmesh
+ check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
subflow 10.0.1.1" " (nofullmesh)"
-ip netns exec $ns1 ./pm_nl_ctl set id 1 flags backup,fullmesh
-check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+ ip netns exec $ns1 ./pm_nl_ctl set id 1 flags backup,fullmesh
+ check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
subflow,backup,fullmesh 10.0.1.1" " (backup,fullmesh)"
+fi
exit $ret
diff --git a/tools/testing/selftests/net/mptcp/userspace_pm.sh b/tools/testing/selftests/net/mptcp/userspace_pm.sh
index 8092399d911f..98d9e4d2d3fc 100755
--- a/tools/testing/selftests/net/mptcp/userspace_pm.sh
+++ b/tools/testing/selftests/net/mptcp/userspace_pm.sh
@@ -4,11 +4,17 @@
. "$(dirname "${0}")/mptcp_lib.sh"
mptcp_lib_check_mptcp
+mptcp_lib_check_kallsyms
+
+if ! mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
+ echo "userspace pm tests are not supported by the kernel: SKIP"
+ exit ${KSFT_SKIP}
+fi
ip -Version > /dev/null 2>&1
if [ $? -ne 0 ];then
echo "SKIP: Cannot not run test without ip tool"
- exit 1
+ exit ${KSFT_SKIP}
fi
ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED
@@ -909,6 +915,11 @@ test_listener()
{
print_title "Listener tests"
+ if ! mptcp_lib_kallsyms_has "mptcp_event_pm_listener$"; then
+ stdbuf -o0 -e0 printf "LISTENER events \t[SKIP] Not supported\n"
+ return
+ fi
+
# Capture events on the network namespace running the client
:>$client_evts
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index 2cbb12736596..c0ad8385441f 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -25,6 +25,8 @@
#define TLS_PAYLOAD_MAX_LEN 16384
#define SOL_TLS 282
+static int fips_enabled;
+
struct tls_crypto_info_keys {
union {
struct tls12_crypto_info_aes_gcm_128 aes128;
@@ -235,7 +237,7 @@ FIXTURE_VARIANT(tls)
{
uint16_t tls_version;
uint16_t cipher_type;
- bool nopad;
+ bool nopad, fips_non_compliant;
};
FIXTURE_VARIANT_ADD(tls, 12_aes_gcm)
@@ -254,24 +256,28 @@ FIXTURE_VARIANT_ADD(tls, 12_chacha)
{
.tls_version = TLS_1_2_VERSION,
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
+ .fips_non_compliant = true,
};
FIXTURE_VARIANT_ADD(tls, 13_chacha)
{
.tls_version = TLS_1_3_VERSION,
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
+ .fips_non_compliant = true,
};
FIXTURE_VARIANT_ADD(tls, 13_sm4_gcm)
{
.tls_version = TLS_1_3_VERSION,
.cipher_type = TLS_CIPHER_SM4_GCM,
+ .fips_non_compliant = true,
};
FIXTURE_VARIANT_ADD(tls, 13_sm4_ccm)
{
.tls_version = TLS_1_3_VERSION,
.cipher_type = TLS_CIPHER_SM4_CCM,
+ .fips_non_compliant = true,
};
FIXTURE_VARIANT_ADD(tls, 12_aes_ccm)
@@ -311,6 +317,9 @@ FIXTURE_SETUP(tls)
int one = 1;
int ret;
+ if (fips_enabled && variant->fips_non_compliant)
+ SKIP(return, "Unsupported cipher in FIPS mode");
+
tls_crypto_info_init(variant->tls_version, variant->cipher_type,
&tls12);
@@ -1820,4 +1829,17 @@ TEST(tls_v6ops) {
close(sfd);
}
+static void __attribute__((constructor)) fips_check(void) {
+ int res;
+ FILE *f;
+
+ f = fopen("/proc/sys/crypto/fips_enabled", "r");
+ if (f) {
+ res = fscanf(f, "%d", &fips_enabled);
+ if (res != 1)
+ ksft_print_msg("ERROR: Couldn't read /proc/sys/crypto/fips_enabled\n");
+ fclose(f);
+ }
+}
+
TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/net/vrf-xfrm-tests.sh b/tools/testing/selftests/net/vrf-xfrm-tests.sh
index 184da81f554f..452638ae8aed 100755
--- a/tools/testing/selftests/net/vrf-xfrm-tests.sh
+++ b/tools/testing/selftests/net/vrf-xfrm-tests.sh
@@ -264,60 +264,60 @@ setup_xfrm()
ip -netns host1 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
proto esp spi ${SPI_1} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
- enc 'cbc(des3_ede)' ${ENC_1} \
+ auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
+ enc 'cbc(aes)' ${ENC_1} \
sel src ${h1_4} dst ${h2_4} ${devarg}
ip -netns host2 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
proto esp spi ${SPI_1} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
- enc 'cbc(des3_ede)' ${ENC_1} \
+ auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
+ enc 'cbc(aes)' ${ENC_1} \
sel src ${h1_4} dst ${h2_4}
ip -netns host1 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
proto esp spi ${SPI_2} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
- enc 'cbc(des3_ede)' ${ENC_2} \
+ auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
+ enc 'cbc(aes)' ${ENC_2} \
sel src ${h2_4} dst ${h1_4} ${devarg}
ip -netns host2 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
proto esp spi ${SPI_2} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
- enc 'cbc(des3_ede)' ${ENC_2} \
+ auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
+ enc 'cbc(aes)' ${ENC_2} \
sel src ${h2_4} dst ${h1_4}
ip -6 -netns host1 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
proto esp spi ${SPI_1} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
- enc 'cbc(des3_ede)' ${ENC_1} \
+ auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
+ enc 'cbc(aes)' ${ENC_1} \
sel src ${h1_6} dst ${h2_6} ${devarg}
ip -6 -netns host2 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
proto esp spi ${SPI_1} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
- enc 'cbc(des3_ede)' ${ENC_1} \
+ auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
+ enc 'cbc(aes)' ${ENC_1} \
sel src ${h1_6} dst ${h2_6}
ip -6 -netns host1 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
proto esp spi ${SPI_2} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
- enc 'cbc(des3_ede)' ${ENC_2} \
+ auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
+ enc 'cbc(aes)' ${ENC_2} \
sel src ${h2_6} dst ${h1_6} ${devarg}
ip -6 -netns host2 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
proto esp spi ${SPI_2} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
- enc 'cbc(des3_ede)' ${ENC_2} \
+ auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
+ enc 'cbc(aes)' ${ENC_2} \
sel src ${h2_6} dst ${h1_6}
}
diff --git a/tools/virtio/ringtest/main.h b/tools/virtio/ringtest/main.h
index b68920d52750..d18dd317e27f 100644
--- a/tools/virtio/ringtest/main.h
+++ b/tools/virtio/ringtest/main.h
@@ -8,6 +8,7 @@
#ifndef MAIN_H
#define MAIN_H
+#include <assert.h>
#include <stdbool.h>
extern int param;
@@ -95,6 +96,8 @@ extern unsigned ring_size;
#define cpu_relax() asm ("rep; nop" ::: "memory")
#elif defined(__s390x__)
#define cpu_relax() barrier()
+#elif defined(__aarch64__)
+#define cpu_relax() asm ("yield" ::: "memory")
#else
#define cpu_relax() assert(0)
#endif
@@ -112,6 +115,8 @@ static inline void busy_wait(void)
#if defined(__x86_64__) || defined(__i386__)
#define smp_mb() asm volatile("lock; addl $0,-132(%%rsp)" ::: "memory", "cc")
+#elif defined(__aarch64__)
+#define smp_mb() asm volatile("dmb ish" ::: "memory")
#else
/*
* Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized
@@ -136,10 +141,16 @@ static inline void busy_wait(void)
#if defined(__i386__) || defined(__x86_64__) || defined(__s390x__)
#define smp_wmb() barrier()
+#elif defined(__aarch64__)
+#define smp_wmb() asm volatile("dmb ishst" ::: "memory")
#else
#define smp_wmb() smp_release()
#endif
+#ifndef __always_inline
+#define __always_inline inline __attribute__((always_inline))
+#endif
+
static __always_inline
void __read_once_size(const volatile void *p, void *res, int size)
{
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 4ec97f72f8ce..9386e415e6b1 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -683,6 +683,24 @@ static __always_inline int kvm_handle_hva_range_no_flush(struct mmu_notifier *mn
return __kvm_handle_hva_range(kvm, &range);
}
+
+static bool kvm_change_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ /*
+ * Skipping invalid memslots is correct if and only change_pte() is
+ * surrounded by invalidate_range_{start,end}(), which is currently
+ * guaranteed by the primary MMU. If that ever changes, KVM needs to
+ * unmap the memslot instead of skipping the memslot to ensure that KVM
+ * doesn't hold references to the old PFN.
+ */
+ WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count));
+
+ if (range->slot->flags & KVM_MEMSLOT_INVALID)
+ return false;
+
+ return kvm_set_spte_gfn(kvm, range);
+}
+
static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long address,
@@ -704,7 +722,7 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
if (!READ_ONCE(kvm->mmu_invalidate_in_progress))
return;
- kvm_handle_hva_range(mn, address, address + 1, pte, kvm_set_spte_gfn);
+ kvm_handle_hva_range(mn, address, address + 1, pte, kvm_change_spte_gfn);
}
void kvm_mmu_invalidate_begin(struct kvm *kvm, unsigned long start,
^ permalink raw reply related [relevance 1%]
* Re: Linux 6.1.36
@ 2023-06-28 9:25 1% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-06-28 9:25 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/MAINTAINERS b/MAINTAINERS
index 301b9ba6af79..379387e20a96 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5183,8 +5183,8 @@ S: Supported
W: https://wiki.samba.org/index.php/LinuxCIFS
T: git git://git.samba.org/sfrench/cifs-2.6.git
F: Documentation/admin-guide/cifs/
-F: fs/cifs/
-F: fs/smbfs_common/
+F: fs/smb/client/
+F: fs/smb/common/
F: include/uapi/linux/cifs
COMPACTPCI HOTPLUG CORE
@@ -11168,8 +11168,8 @@ L: linux-cifs@vger.kernel.org
S: Maintained
T: git git://git.samba.org/ksmbd.git
F: Documentation/filesystems/cifs/ksmbd.rst
-F: fs/ksmbd/
-F: fs/smbfs_common/
+F: fs/smb/common/
+F: fs/smb/server/
KERNEL UNIT TESTING FRAMEWORK (KUnit)
M: Brendan Higgins <brendanhiggins@google.com>
diff --git a/Makefile b/Makefile
index 46c06af912d9..cffb83d7a0fb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
-SUBLEVEL = 35
+SUBLEVEL = 36
EXTRAVERSION =
NAME = Curry Ramen
diff --git a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
index 2fc9a5d5e0c0..625b9b311b49 100644
--- a/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
+++ b/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
@@ -527,7 +527,7 @@ touchscreen@1 {
interrupt-parent = <&gpio1>;
interrupts = <31 0>;
- pendown-gpio = <&gpio1 31 0>;
+ pendown-gpio = <&gpio1 31 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
diff --git a/arch/arm/boot/dts/at91sam9261ek.dts b/arch/arm/boot/dts/at91sam9261ek.dts
index 88869ca874d1..045cb253f23a 100644
--- a/arch/arm/boot/dts/at91sam9261ek.dts
+++ b/arch/arm/boot/dts/at91sam9261ek.dts
@@ -156,7 +156,7 @@ tsc2046@2 {
compatible = "ti,ads7843";
interrupts-extended = <&pioC 2 IRQ_TYPE_EDGE_BOTH>;
spi-max-frequency = <3000000>;
- pendown-gpio = <&pioC 2 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&pioC 2 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <150>;
ti,x-max = /bits/ 16 <3830>;
diff --git a/arch/arm/boot/dts/imx7d-pico-hobbit.dts b/arch/arm/boot/dts/imx7d-pico-hobbit.dts
index d917dc4f2f22..6ad39dca7009 100644
--- a/arch/arm/boot/dts/imx7d-pico-hobbit.dts
+++ b/arch/arm/boot/dts/imx7d-pico-hobbit.dts
@@ -64,7 +64,7 @@ ads7846@0 {
interrupt-parent = <&gpio2>;
interrupts = <7 0>;
spi-max-frequency = <1000000>;
- pendown-gpio = <&gpio2 7 0>;
+ pendown-gpio = <&gpio2 7 GPIO_ACTIVE_LOW>;
vcc-supply = <®_3p3v>;
ti,x-min = /bits/ 16 <0>;
ti,x-max = /bits/ 16 <4095>;
diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
index f483bc0afe5e..234e5fc647b2 100644
--- a/arch/arm/boot/dts/imx7d-sdb.dts
+++ b/arch/arm/boot/dts/imx7d-sdb.dts
@@ -205,7 +205,7 @@ tsc2046@0 {
pinctrl-0 = <&pinctrl_tsc2046_pendown>;
interrupt-parent = <&gpio2>;
interrupts = <29 0>;
- pendown-gpio = <&gpio2 29 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio2 29 GPIO_ACTIVE_LOW>;
touchscreen-max-pressure = <255>;
wakeup-source;
};
diff --git a/arch/arm/boot/dts/omap3-cm-t3x.dtsi b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
index e61b8a2bfb7d..51baedf1603b 100644
--- a/arch/arm/boot/dts/omap3-cm-t3x.dtsi
+++ b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
@@ -227,7 +227,7 @@ ads7846@0 {
interrupt-parent = <&gpio2>;
interrupts = <25 0>; /* gpio_57 */
- pendown-gpio = <&gpio2 25 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio2 25 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
index 3decc2d78a6c..a7f99ae0c1fe 100644
--- a/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
+++ b/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
@@ -54,7 +54,7 @@ ads7846@0 {
interrupt-parent = <&gpio1>;
interrupts = <27 0>; /* gpio_27 */
- pendown-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio1 27 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
index c595afe4181d..d310b5c7bac3 100644
--- a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
+++ b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
@@ -311,7 +311,7 @@ tsc2046@0 {
interrupt-parent = <&gpio1>;
interrupts = <8 0>; /* boot6 / gpio_8 */
spi-max-frequency = <1000000>;
- pendown-gpio = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio1 8 GPIO_ACTIVE_LOW>;
vcc-supply = <®_vcc3>;
pinctrl-names = "default";
pinctrl-0 = <&tsc2048_pins>;
diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi b/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
index 1d6e88f99eb3..c3570acc35fa 100644
--- a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
@@ -149,7 +149,7 @@ ads7846@0 {
interrupt-parent = <&gpio4>;
interrupts = <18 0>; /* gpio_114 */
- pendown-gpio = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio4 18 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi b/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
index 7e30f9d45790..d95a0e130058 100644
--- a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
@@ -160,7 +160,7 @@ ads7846@0 {
interrupt-parent = <&gpio4>;
interrupts = <18 0>; /* gpio_114 */
- pendown-gpio = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio4 18 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
ti,x-max = /bits/ 16 <0x0fff>;
diff --git a/arch/arm/boot/dts/omap3-pandora-common.dtsi b/arch/arm/boot/dts/omap3-pandora-common.dtsi
index 559853764487..4c3b6bab179c 100644
--- a/arch/arm/boot/dts/omap3-pandora-common.dtsi
+++ b/arch/arm/boot/dts/omap3-pandora-common.dtsi
@@ -651,7 +651,7 @@ tsc2046@0 {
pinctrl-0 = <&penirq_pins>;
interrupt-parent = <&gpio3>;
interrupts = <30 IRQ_TYPE_NONE>; /* GPIO_94 */
- pendown-gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio3 30 GPIO_ACTIVE_LOW>;
vcc-supply = <&vaux4>;
ti,x-min = /bits/ 16 <0>;
diff --git a/arch/arm/boot/dts/omap5-cm-t54.dts b/arch/arm/boot/dts/omap5-cm-t54.dts
index ca759b7b8a58..e62ea8b6d53f 100644
--- a/arch/arm/boot/dts/omap5-cm-t54.dts
+++ b/arch/arm/boot/dts/omap5-cm-t54.dts
@@ -354,7 +354,7 @@ ads7846@0 {
interrupt-parent = <&gpio1>;
interrupts = <15 0>; /* gpio1_wk15 */
- pendown-gpio = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+ pendown-gpio = <&gpio1 15 GPIO_ACTIVE_LOW>;
ti,x-min = /bits/ 16 <0x0>;
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
index ca50f0ba9b81..1c370dcfe60b 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
@@ -488,7 +488,6 @@ &swr0 {
wcd_rx: codec@0,4 {
compatible = "sdw20217010d00";
reg = <0 4>;
- #sound-dai-cells = <1>;
qcom,rx-port-mapping = <1 2 3 4 5>;
};
};
@@ -499,7 +498,6 @@ &swr1 {
wcd_tx: codec@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
- #sound-dai-cells = <1>;
qcom,tx-port-mapping = <1 2 3 4>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
index f7665b379923..c358abc052eb 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
@@ -418,7 +418,6 @@ &swr0 {
wcd_rx: codec@0,4 {
compatible = "sdw20217010d00";
reg = <0 4>;
- #sound-dai-cells = <1>;
qcom,rx-port-mapping = <1 2 3 4 5>;
};
};
@@ -427,7 +426,6 @@ &swr1 {
wcd_tx: codec@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
- #sound-dai-cells = <1>;
qcom,tx-port-mapping = <1 2 3 4>;
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
index e00568a6be5c..6ba562b922e6 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
@@ -28,6 +28,16 @@ vcc_5v: vcc-5v-regulator {
regulator-max-microvolt = <5000000>;
vin-supply = <&vcc12v_dcin>;
};
+
+ vcc_sd_pwr: vcc-sd-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sd_pwr";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
};
&gmac1 {
@@ -119,13 +129,7 @@ &saradc {
};
&sdmmc0 {
- vmmc-supply = <&sdmmc_pwr>;
- status = "okay";
-};
-
-&sdmmc_pwr {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
+ vmmc-supply = <&vcc_sd_pwr>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
index 4d494b53a71a..ba56ca2e66c8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
@@ -92,16 +92,6 @@ vcc3v3_sys: vcc3v3-sys-regulator {
regulator-max-microvolt = <3300000>;
vin-supply = <&vcc5v0_sys>;
};
-
- sdmmc_pwr: sdmmc-pwr-regulator {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&sdmmc_pwr_h>;
- regulator-name = "sdmmc_pwr";
- status = "disabled";
- };
};
&cpu0 {
@@ -143,6 +133,24 @@ &gmac1m0_clkinout
status = "disabled";
};
+&gpio0 {
+ nextrst-hog {
+ gpio-hog;
+ /*
+ * GPIO_ACTIVE_LOW + output-low here means that the pin is set
+ * to high, because output-low decides the value pre-inversion.
+ */
+ gpios = <RK_PA5 GPIO_ACTIVE_LOW>;
+ line-name = "nEXTRST";
+ output-low;
+ };
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu>;
+ status = "okay";
+};
+
&i2c0 {
status = "okay";
@@ -480,12 +488,6 @@ wifi_enable_h: wifi-enable-h {
rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
-
- sdmmc-pwr {
- sdmmc_pwr_h: sdmmc-pwr-h {
- rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
};
&pmu_io_domains {
diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
index ba67b58f05b7..f1be76a54ceb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi
@@ -94,9 +94,10 @@ pcie3x1: pcie@fe270000 {
power-domains = <&power RK3568_PD_PIPE>;
reg = <0x3 0xc0400000 0x0 0x00400000>,
<0x0 0xfe270000 0x0 0x00010000>,
- <0x3 0x7f000000 0x0 0x01000000>;
- ranges = <0x01000000 0x0 0x3ef00000 0x3 0x7ef00000 0x0 0x00100000>,
- <0x02000000 0x0 0x00000000 0x3 0x40000000 0x0 0x3ef00000>;
+ <0x0 0xf2000000 0x0 0x00100000>;
+ ranges = <0x01000000 0x0 0xf2100000 0x0 0xf2100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf2200000 0x0 0xf2200000 0x0 0x01e00000>,
+ <0x03000000 0x0 0x40000000 0x3 0x40000000 0x0 0x40000000>;
reg-names = "dbi", "apb", "config";
resets = <&cru SRST_PCIE30X1_POWERUP>;
reset-names = "pipe";
@@ -146,9 +147,10 @@ pcie3x2: pcie@fe280000 {
power-domains = <&power RK3568_PD_PIPE>;
reg = <0x3 0xc0800000 0x0 0x00400000>,
<0x0 0xfe280000 0x0 0x00010000>,
- <0x3 0xbf000000 0x0 0x01000000>;
- ranges = <0x01000000 0x0 0x3ef00000 0x3 0xbef00000 0x0 0x00100000>,
- <0x02000000 0x0 0x00000000 0x3 0x80000000 0x0 0x3ef00000>;
+ <0x0 0xf0000000 0x0 0x00100000>;
+ ranges = <0x01000000 0x0 0xf0100000 0x0 0xf0100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf0200000 0x0 0xf0200000 0x0 0x01e00000>,
+ <0x03000000 0x0 0x40000000 0x3 0x80000000 0x0 0x40000000>;
reg-names = "dbi", "apb", "config";
resets = <&cru SRST_PCIE30X2_POWERUP>;
reset-names = "pipe";
diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 1d423daae971..234b5bbda120 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -951,7 +951,7 @@ pcie2x1: pcie@fe260000 {
compatible = "rockchip,rk3568-pcie";
reg = <0x3 0xc0000000 0x0 0x00400000>,
<0x0 0xfe260000 0x0 0x00010000>,
- <0x3 0x3f000000 0x0 0x01000000>;
+ <0x0 0xf4000000 0x0 0x00100000>;
reg-names = "dbi", "apb", "config";
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
@@ -981,8 +981,9 @@ pcie2x1: pcie@fe260000 {
phys = <&combphy2 PHY_TYPE_PCIE>;
phy-names = "pcie-phy";
power-domains = <&power RK3568_PD_PIPE>;
- ranges = <0x01000000 0x0 0x3ef00000 0x3 0x3ef00000 0x0 0x00100000
- 0x02000000 0x0 0x00000000 0x3 0x00000000 0x0 0x3ef00000>;
+ ranges = <0x01000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x00100000>,
+ <0x02000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0x01e00000>,
+ <0x03000000 0x0 0x40000000 0x3 0x00000000 0x0 0x40000000>;
resets = <&cru SRST_PCIE20_POWERUP>;
reset-names = "pipe";
#address-cells = <3>;
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 7d301700d1a9..3a448ab0924b 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -111,8 +111,14 @@
#define SB_BARRIER_INSN __SYS_BARRIER_INSN(0, 7, 31)
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
+#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
+#define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6)
#define SYS_DC_CSW sys_insn(1, 0, 7, 10, 2)
+#define SYS_DC_CGSW sys_insn(1, 0, 7, 10, 4)
+#define SYS_DC_CGDSW sys_insn(1, 0, 7, 10, 6)
#define SYS_DC_CISW sys_insn(1, 0, 7, 14, 2)
+#define SYS_DC_CIGSW sys_insn(1, 0, 7, 14, 4)
+#define SYS_DC_CIGDSW sys_insn(1, 0, 7, 14, 6)
/*
* Automatically generated definitions for system registers, the
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 2208d79b18de..081aca8f432e 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -81,7 +81,12 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
* EL1 instead of being trapped to EL2.
*/
if (kvm_arm_support_pmu_v3()) {
+ struct kvm_cpu_context *hctxt;
+
write_sysreg(0, pmselr_el0);
+
+ hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
+ ctxt_sys_reg(hctxt, PMUSERENR_EL0) = read_sysreg(pmuserenr_el0);
write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);
}
@@ -105,8 +110,12 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
write_sysreg(vcpu->arch.mdcr_el2_host, mdcr_el2);
write_sysreg(0, hstr_el2);
- if (kvm_arm_support_pmu_v3())
- write_sysreg(0, pmuserenr_el0);
+ if (kvm_arm_support_pmu_v3()) {
+ struct kvm_cpu_context *hctxt;
+
+ hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
+ write_sysreg(ctxt_sys_reg(hctxt, PMUSERENR_EL0), pmuserenr_el0);
+ }
if (cpus_have_final_cap(ARM64_SME)) {
sysreg_clear_set_s(SYS_HFGRTR_EL2, 0,
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index 37e74ca4dad8..f2f3bf4a04b0 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -446,6 +446,7 @@ int vgic_lazy_init(struct kvm *kvm)
int kvm_vgic_map_resources(struct kvm *kvm)
{
struct vgic_dist *dist = &kvm->arch.vgic;
+ enum vgic_type type;
gpa_t dist_base;
int ret = 0;
@@ -460,10 +461,13 @@ int kvm_vgic_map_resources(struct kvm *kvm)
if (!irqchip_in_kernel(kvm))
goto out;
- if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+ if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
ret = vgic_v2_map_resources(kvm);
- else
+ type = VGIC_V2;
+ } else {
ret = vgic_v3_map_resources(kvm);
+ type = VGIC_V3;
+ }
if (ret) {
__kvm_vgic_destroy(kvm);
@@ -473,8 +477,7 @@ int kvm_vgic_map_resources(struct kvm *kvm)
dist_base = dist->vgic_dist_base;
mutex_unlock(&kvm->arch.config_lock);
- ret = vgic_register_dist_iodev(kvm, dist_base,
- kvm_vgic_global_state.type);
+ ret = vgic_register_dist_iodev(kvm, dist_base, type);
if (ret) {
kvm_err("Unable to register VGIC dist MMIO regions\n");
kvm_vgic_destroy(kvm);
diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile
index d237bc6841cb..4cbf306b8181 100644
--- a/arch/s390/purgatory/Makefile
+++ b/arch/s390/purgatory/Makefile
@@ -26,6 +26,7 @@ KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare
KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding
KBUILD_CFLAGS += -c -MD -Os -m64 -msoft-float -fno-common
KBUILD_CFLAGS += -fno-stack-protector
+KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
KBUILD_CFLAGS += $(CLANG_FLAGS)
KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS))
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 6bde05a86b4e..896bc41cb2ba 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -97,7 +97,10 @@ static void init_x2apic_ldr(void)
static int x2apic_phys_probe(void)
{
- if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys()))
+ if (!x2apic_mode)
+ return 0;
+
+ if (x2apic_phys || x2apic_fadt_phys())
return 1;
return apic == &apic_x2apic_phys;
diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c
index 557f0fe25dff..37db264866b6 100644
--- a/arch/x86/mm/kaslr.c
+++ b/arch/x86/mm/kaslr.c
@@ -172,10 +172,10 @@ void __meminit init_trampoline_kaslr(void)
set_p4d(p4d_tramp,
__p4d(_KERNPG_TABLE | __pa(pud_page_tramp)));
- set_pgd(&trampoline_pgd_entry,
- __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp)));
+ trampoline_pgd_entry =
+ __pgd(_KERNPG_TABLE | __pa(p4d_page_tramp));
} else {
- set_pgd(&trampoline_pgd_entry,
- __pgd(_KERNPG_TABLE | __pa(pud_page_tramp)));
+ trampoline_pgd_entry =
+ __pgd(_KERNPG_TABLE | __pa(pud_page_tramp));
}
}
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 99620428ad78..db6053a22e86 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -2478,7 +2478,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
}
if (bpf_jit_enable > 1)
- bpf_jit_dump(prog->len, proglen, pass + 1, image);
+ bpf_jit_dump(prog->len, proglen, pass + 1, rw_image);
if (image) {
if (!prog->is_func || extra_pass) {
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 6f2787506b50..c1b6e7bf4fcb 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -101,8 +101,6 @@ acpi_status
acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
acpi_event_status *event_status);
-acpi_status acpi_hw_disable_all_gpes(void);
-
acpi_status acpi_hw_enable_all_runtime_gpes(void);
acpi_status acpi_hw_enable_all_wakeup_gpes(void);
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 4ca667251272..539c12fbd2f1 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -636,11 +636,19 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
}
/*
- * Disable and clear GPE status before interrupt is enabled. Some GPEs
- * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
- * acpi_leave_sleep_state will reenable specific GPEs later
+ * Disable all GPE and clear their status bits before interrupts are
+ * enabled. Some GPEs (like wakeup GPEs) have no handlers and this can
+ * prevent them from producing spurious interrups.
+ *
+ * acpi_leave_sleep_state() will reenable specific GPEs later.
+ *
+ * Because this code runs on one CPU with disabled interrupts (all of
+ * the other CPUs are offline at this time), it need not acquire any
+ * sleeping locks which may trigger an implicit preemption point even
+ * if there is no contention, so avoid doing that by using a low-level
+ * library routine here.
*/
- acpi_disable_all_gpes();
+ acpi_hw_disable_all_gpes();
/* Allow EC transactions to happen. */
acpi_ec_unblock_transactions();
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index a5ea144722fa..0ba0c3d1613f 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5313,7 +5313,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
mutex_init(&ap->scsi_scan_mutex);
INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
- INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
+ INIT_DELAYED_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
INIT_LIST_HEAD(&ap->eh_done_q);
init_waitqueue_head(&ap->eh_wait_q);
init_completion(&ap->park_req_pending);
@@ -5919,6 +5919,7 @@ static void ata_port_detach(struct ata_port *ap)
WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED));
cancel_delayed_work_sync(&ap->hotplug_task);
+ cancel_delayed_work_sync(&ap->scsi_rescan_task);
skip_eh:
/* clean up zpodd on port removal */
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 08e11bc312c2..a3ae5fc2a42f 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2973,7 +2973,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
ehc->i.flags |= ATA_EHI_SETMODE;
/* schedule the scsi_rescan_device() here */
- schedule_work(&(ap->scsi_rescan_task));
+ schedule_delayed_work(&ap->scsi_rescan_task, 0);
} else if (dev->class == ATA_DEV_UNKNOWN &&
ehc->tries[dev->devno] &&
ata_class_enabled(ehc->classes[dev->devno])) {
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 39e1ff9b686b..9c0052d28078 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -4601,10 +4601,11 @@ int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
void ata_scsi_dev_rescan(struct work_struct *work)
{
struct ata_port *ap =
- container_of(work, struct ata_port, scsi_rescan_task);
+ container_of(work, struct ata_port, scsi_rescan_task.work);
struct ata_link *link;
struct ata_device *dev;
unsigned long flags;
+ bool delay_rescan = false;
mutex_lock(&ap->scsi_scan_mutex);
spin_lock_irqsave(ap->lock, flags);
@@ -4618,6 +4619,21 @@ void ata_scsi_dev_rescan(struct work_struct *work)
if (scsi_device_get(sdev))
continue;
+ /*
+ * If the rescan work was scheduled because of a resume
+ * event, the port is already fully resumed, but the
+ * SCSI device may not yet be fully resumed. In such
+ * case, executing scsi_rescan_device() may cause a
+ * deadlock with the PM code on device_lock(). Prevent
+ * this by giving up and retrying rescan after a short
+ * delay.
+ */
+ delay_rescan = sdev->sdev_gendev.power.is_suspended;
+ if (delay_rescan) {
+ scsi_device_put(sdev);
+ break;
+ }
+
spin_unlock_irqrestore(ap->lock, flags);
scsi_rescan_device(&(sdev->sdev_gendev));
scsi_device_put(sdev);
@@ -4627,4 +4643,8 @@ void ata_scsi_dev_rescan(struct work_struct *work)
spin_unlock_irqrestore(ap->lock, flags);
mutex_unlock(&ap->scsi_scan_mutex);
+
+ if (delay_rescan)
+ schedule_delayed_work(&ap->scsi_rescan_task,
+ msecs_to_jiffies(5));
}
diff --git a/drivers/base/regmap/regmap-spi-avmm.c b/drivers/base/regmap/regmap-spi-avmm.c
index 4c2b94b3e30b..6af692844c19 100644
--- a/drivers/base/regmap/regmap-spi-avmm.c
+++ b/drivers/base/regmap/regmap-spi-avmm.c
@@ -660,7 +660,7 @@ static const struct regmap_bus regmap_spi_avmm_bus = {
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
.max_raw_read = SPI_AVMM_VAL_SIZE * MAX_READ_CNT,
- .max_raw_write = SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
+ .max_raw_write = SPI_AVMM_REG_SIZE + SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
.free_context = spi_avmm_bridge_ctx_free,
};
diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index c45d09a9a942..e8cb914223cd 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -2194,6 +2194,7 @@ static void null_destroy_dev(struct nullb *nullb)
struct nullb_device *dev = nullb->dev;
null_del_dev(nullb);
+ null_free_device_storage(dev, false);
null_free_dev(dev);
}
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 16fc481d6095..916f4ff246c1 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -98,6 +98,8 @@ struct crb_priv {
u8 __iomem *rsp;
u32 cmd_size;
u32 smc_func_id;
+ u32 __iomem *pluton_start_addr;
+ u32 __iomem *pluton_reply_addr;
};
struct tpm2_crb_smc {
@@ -108,6 +110,11 @@ struct tpm2_crb_smc {
u32 smc_func_id;
};
+struct tpm2_crb_pluton {
+ u64 start_addr;
+ u64 reply_addr;
+};
+
static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
unsigned long timeout)
{
@@ -127,6 +134,25 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
return ((ioread32(reg) & mask) == value);
}
+static int crb_try_pluton_doorbell(struct crb_priv *priv, bool wait_for_complete)
+{
+ if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON)
+ return 0;
+
+ if (!crb_wait_for_reg_32(priv->pluton_reply_addr, ~0, 1, TPM2_TIMEOUT_C))
+ return -ETIME;
+
+ iowrite32(1, priv->pluton_start_addr);
+ if (wait_for_complete == false)
+ return 0;
+
+ if (!crb_wait_for_reg_32(priv->pluton_start_addr,
+ 0xffffffff, 0, 200))
+ return -ETIME;
+
+ return 0;
+}
+
/**
* __crb_go_idle - request tpm crb device to go the idle state
*
@@ -145,6 +171,8 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
*/
static int __crb_go_idle(struct device *dev, struct crb_priv *priv)
{
+ int rc;
+
if ((priv->sm == ACPI_TPM2_START_METHOD) ||
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC))
@@ -152,6 +180,10 @@ static int __crb_go_idle(struct device *dev, struct crb_priv *priv)
iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
+ rc = crb_try_pluton_doorbell(priv, true);
+ if (rc)
+ return rc;
+
if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
CRB_CTRL_REQ_GO_IDLE/* mask */,
0, /* value */
@@ -188,12 +220,19 @@ static int crb_go_idle(struct tpm_chip *chip)
*/
static int __crb_cmd_ready(struct device *dev, struct crb_priv *priv)
{
+ int rc;
+
if ((priv->sm == ACPI_TPM2_START_METHOD) ||
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC))
return 0;
iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
+
+ rc = crb_try_pluton_doorbell(priv, true);
+ if (rc)
+ return rc;
+
if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
CRB_CTRL_REQ_CMD_READY /* mask */,
0, /* value */
@@ -371,6 +410,10 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
return -E2BIG;
}
+ /* Seems to be necessary for every command */
+ if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON)
+ __crb_cmd_ready(&chip->dev, priv);
+
memcpy_toio(priv->cmd, buf, len);
/* Make sure that cmd is populated before issuing start. */
@@ -394,7 +437,10 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id);
}
- return rc;
+ if (rc)
+ return rc;
+
+ return crb_try_pluton_doorbell(priv, false);
}
static void crb_cancel(struct tpm_chip *chip)
@@ -524,15 +570,18 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
return ret;
acpi_dev_free_resource_list(&acpi_resource_list);
- if (resource_type(iores_array) != IORESOURCE_MEM) {
- dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n");
- return -EINVAL;
- } else if (resource_type(iores_array + TPM_CRB_MAX_RESOURCES) ==
- IORESOURCE_MEM) {
- dev_warn(dev, "TPM2 ACPI table defines too many memory resources\n");
- memset(iores_array + TPM_CRB_MAX_RESOURCES,
- 0, sizeof(*iores_array));
- iores_array[TPM_CRB_MAX_RESOURCES].flags = 0;
+ /* Pluton doesn't appear to define ACPI memory regions */
+ if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) {
+ if (resource_type(iores_array) != IORESOURCE_MEM) {
+ dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n");
+ return -EINVAL;
+ } else if (resource_type(iores_array + TPM_CRB_MAX_RESOURCES) ==
+ IORESOURCE_MEM) {
+ dev_warn(dev, "TPM2 ACPI table defines too many memory resources\n");
+ memset(iores_array + TPM_CRB_MAX_RESOURCES,
+ 0, sizeof(*iores_array));
+ iores_array[TPM_CRB_MAX_RESOURCES].flags = 0;
+ }
}
iores = NULL;
@@ -656,6 +705,22 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
return ret;
}
+static int crb_map_pluton(struct device *dev, struct crb_priv *priv,
+ struct acpi_table_tpm2 *buf, struct tpm2_crb_pluton *crb_pluton)
+{
+ priv->pluton_start_addr = crb_map_res(dev, NULL, NULL,
+ crb_pluton->start_addr, 4);
+ if (IS_ERR(priv->pluton_start_addr))
+ return PTR_ERR(priv->pluton_start_addr);
+
+ priv->pluton_reply_addr = crb_map_res(dev, NULL, NULL,
+ crb_pluton->reply_addr, 4);
+ if (IS_ERR(priv->pluton_reply_addr))
+ return PTR_ERR(priv->pluton_reply_addr);
+
+ return 0;
+}
+
static int crb_acpi_add(struct acpi_device *device)
{
struct acpi_table_tpm2 *buf;
@@ -663,6 +728,7 @@ static int crb_acpi_add(struct acpi_device *device)
struct tpm_chip *chip;
struct device *dev = &device->dev;
struct tpm2_crb_smc *crb_smc;
+ struct tpm2_crb_pluton *crb_pluton;
acpi_status status;
u32 sm;
int rc;
@@ -700,6 +766,20 @@ static int crb_acpi_add(struct acpi_device *device)
priv->smc_func_id = crb_smc->smc_func_id;
}
+ if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) {
+ if (buf->header.length < (sizeof(*buf) + sizeof(*crb_pluton))) {
+ dev_err(dev,
+ FW_BUG "TPM2 ACPI table has wrong size %u for start method type %d\n",
+ buf->header.length,
+ ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON);
+ return -EINVAL;
+ }
+ crb_pluton = ACPI_ADD_PTR(struct tpm2_crb_pluton, buf, sizeof(*buf));
+ rc = crb_map_pluton(dev, priv, buf, crb_pluton);
+ if (rc)
+ return rc;
+ }
+
priv->sm = sm;
priv->hid = acpi_device_hid(device);
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index e05d2b227de3..55f6ff1e05aa 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -772,7 +772,9 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
wake_up_interruptible(&priv->int_queue);
/* Clear interrupts handled with TPM_EOI */
+ tpm_tis_request_locality(chip, 0);
rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt);
+ tpm_tis_relinquish_locality(chip, 0);
if (rc < 0)
return IRQ_NONE;
diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c
index bc5660f61c57..0f1e1226ebbe 100644
--- a/drivers/gpio/gpio-sifive.c
+++ b/drivers/gpio/gpio-sifive.c
@@ -221,8 +221,12 @@ static int sifive_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
- for (i = 0; i < ngpio; i++)
- chip->irq_number[i] = platform_get_irq(pdev, i);
+ for (i = 0; i < ngpio; i++) {
+ ret = platform_get_irq(pdev, i);
+ if (ret < 0)
+ return ret;
+ chip->irq_number[i] = ret;
+ }
ret = bgpio_init(&chip->gc, dev, 4,
chip->base + SIFIVE_GPIO_INPUT_VAL,
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 5974cfc61b41..6d3e3454a6ed 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1650,7 +1650,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gc)
}
/* Remove all IRQ mappings and delete the domain */
- if (gc->irq.domain) {
+ if (!gc->irq.domain_is_allocated_externally && gc->irq.domain) {
unsigned int irq;
for (offset = 0; offset < gc->ngpio; offset++) {
@@ -1696,6 +1696,15 @@ int gpiochip_irqchip_add_domain(struct gpio_chip *gc,
gc->to_irq = gpiochip_to_irq;
gc->irq.domain = domain;
+ gc->irq.domain_is_allocated_externally = true;
+
+ /*
+ * Using barrier() here to prevent compiler from reordering
+ * gc->irq.initialized before adding irqdomain.
+ */
+ barrier();
+
+ gc->irq.initialized = true;
return 0;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 53687de6c053..91c308cf27eb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -348,6 +348,35 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
return false;
}
+/**
+ * update_planes_and_stream_adapter() - Send planes to be updated in DC
+ *
+ * DC has a generic way to update planes and stream via
+ * dc_update_planes_and_stream function; however, DM might need some
+ * adjustments and preparation before calling it. This function is a wrapper
+ * for the dc_update_planes_and_stream that does any required configuration
+ * before passing control to DC.
+ */
+static inline bool update_planes_and_stream_adapter(struct dc *dc,
+ int update_type,
+ int planes_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update,
+ struct dc_surface_update *array_of_surface_update)
+{
+ /*
+ * Previous frame finished and HW is ready for optimization.
+ */
+ if (update_type == UPDATE_TYPE_FAST)
+ dc_post_update_surfaces_to_stream(dc);
+
+ return dc_update_planes_and_stream(dc,
+ array_of_surface_update,
+ planes_count,
+ stream,
+ stream_update);
+}
+
/**
* dm_pflip_high_irq() - Handle pageflip interrupt
* @interrupt_params: ignored
@@ -2632,10 +2661,13 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
bundle->surface_updates[m].surface->force_full_update =
true;
}
- dc_commit_updates_for_stream(
- dm->dc, bundle->surface_updates,
- dc_state->stream_status->plane_count,
- dc_state->streams[k], &bundle->stream_update, dc_state);
+
+ update_planes_and_stream_adapter(dm->dc,
+ UPDATE_TYPE_FULL,
+ dc_state->stream_status->plane_count,
+ dc_state->streams[k],
+ &bundle->stream_update,
+ bundle->surface_updates);
}
cleanup:
@@ -7870,6 +7902,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
if (acrtc_state->abm_level != dm_old_crtc_state->abm_level)
bundle->stream_update.abm_level = &acrtc_state->abm_level;
+ mutex_lock(&dm->dc_lock);
+ if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
+ acrtc_state->stream->link->psr_settings.psr_allow_active)
+ amdgpu_dm_psr_disable(acrtc_state->stream);
+ mutex_unlock(&dm->dc_lock);
+
/*
* If FreeSync state on the stream has changed then we need to
* re-adjust the min/max bounds now that DC doesn't handle this
@@ -7883,16 +7921,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
}
mutex_lock(&dm->dc_lock);
- if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
- acrtc_state->stream->link->psr_settings.psr_allow_active)
- amdgpu_dm_psr_disable(acrtc_state->stream);
-
- dc_commit_updates_for_stream(dm->dc,
- bundle->surface_updates,
- planes_count,
- acrtc_state->stream,
- &bundle->stream_update,
- dc_state);
+ update_planes_and_stream_adapter(dm->dc,
+ acrtc_state->update_type,
+ planes_count,
+ acrtc_state->stream,
+ &bundle->stream_update,
+ bundle->surface_updates);
/**
* Enable or disable the interrupts on the backend.
@@ -8334,12 +8368,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
mutex_lock(&dm->dc_lock);
- dc_commit_updates_for_stream(dm->dc,
- dummy_updates,
- status->plane_count,
- dm_new_crtc_state->stream,
- &stream_update,
- dc_state);
+ dc_update_planes_and_stream(dm->dc,
+ dummy_updates,
+ status->plane_count,
+ dm_new_crtc_state->stream,
+ &stream_update);
mutex_unlock(&dm->dc_lock);
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 471fd6c8135f..27613abeed96 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -1335,7 +1335,7 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
/* Let the runqueue know that there is work to do. */
queue_work(g2d->g2d_workq, &g2d->runqueue_work);
- if (runqueue_node->async)
+ if (req->async)
goto out;
wait_for_completion(&runqueue_node->complete);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 4d56c8c799c5..f5e1adfcaa51 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -469,8 +469,6 @@ static int vidi_remove(struct platform_device *pdev)
if (ctx->raw_edid != (struct edid *)fake_edid_info) {
kfree(ctx->raw_edid);
ctx->raw_edid = NULL;
-
- return -EINVAL;
}
component_del(&pdev->dev, &vidi_component_ops);
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index 261fcbae88d7..75d79c311038 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -459,7 +459,6 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct radeon_device *rdev = dev->dev_private;
struct drm_radeon_gem_set_domain *args = data;
struct drm_gem_object *gobj;
- struct radeon_bo *robj;
int r;
/* for now if someone requests domain CPU -
@@ -472,13 +471,12 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
up_read(&rdev->exclusive_lock);
return -ENOENT;
}
- robj = gem_to_radeon_bo(gobj);
r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
drm_gem_object_put(gobj);
up_read(&rdev->exclusive_lock);
- r = radeon_gem_handle_lockup(robj->rdev, r);
+ r = radeon_gem_handle_lockup(rdev, r);
return r;
}
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index fb538a6c4add..aff4a21a46b6 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -2417,8 +2417,13 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
goto fail_quirks;
}
- if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
+ if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) {
error = hid_hw_open(hdev);
+ if (error) {
+ hid_err(hdev, "hw open failed\n");
+ goto fail_quirks;
+ }
+ }
wacom_set_shared_values(wacom_wac);
devres_close_group(&hdev->dev, wacom);
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index cc23b90cae02..d95e567a190d 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -829,11 +829,22 @@ static void vmbus_wait_for_unload(void)
if (completion_done(&vmbus_connection.unload_event))
goto completed;
- for_each_online_cpu(cpu) {
+ for_each_present_cpu(cpu) {
struct hv_per_cpu_context *hv_cpu
= per_cpu_ptr(hv_context.cpu_context, cpu);
+ /*
+ * In a CoCo VM the synic_message_page is not allocated
+ * in hv_synic_alloc(). Instead it is set/cleared in
+ * hv_synic_enable_regs() and hv_synic_disable_regs()
+ * such that it is set only when the CPU is online. If
+ * not all present CPUs are online, the message page
+ * might be NULL, so skip such CPUs.
+ */
page_addr = hv_cpu->synic_message_page;
+ if (!page_addr)
+ continue;
+
msg = (struct hv_message *)page_addr
+ VMBUS_MESSAGE_SINT;
@@ -867,11 +878,14 @@ static void vmbus_wait_for_unload(void)
* maybe-pending messages on all CPUs to be able to receive new
* messages after we reconnect.
*/
- for_each_online_cpu(cpu) {
+ for_each_present_cpu(cpu) {
struct hv_per_cpu_context *hv_cpu
= per_cpu_ptr(hv_context.cpu_context, cpu);
page_addr = hv_cpu->synic_message_page;
+ if (!page_addr)
+ continue;
+
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
msg->header.message_type = HVMSG_NONE;
}
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index e592c481f7ae..b03cb7ae7fd3 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1504,7 +1504,7 @@ static int vmbus_bus_init(void)
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online",
hv_synic_init, hv_synic_cleanup);
if (ret < 0)
- goto err_cpuhp;
+ goto err_alloc;
hyperv_cpuhp_online = ret;
ret = vmbus_connect();
@@ -1555,9 +1555,8 @@ static int vmbus_bus_init(void)
err_connect:
cpuhp_remove_state(hyperv_cpuhp_online);
-err_cpuhp:
- hv_synic_free();
err_alloc:
+ hv_synic_free();
if (vmbus_irq == -1) {
hv_remove_vmbus_handler();
} else {
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index a49b14d52a98..ff12018bc206 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -201,8 +201,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
/* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */
static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
{
- u8 prescale, filt, sethold, clkhi, clklo, datavd;
- unsigned int clk_rate, clk_cycle;
+ u8 prescale, filt, sethold, datavd;
+ unsigned int clk_rate, clk_cycle, clkhi, clklo;
enum lpi2c_imx_pincfg pincfg;
unsigned int temp;
diff --git a/drivers/i2c/busses/i2c-mchp-pci1xxxx.c b/drivers/i2c/busses/i2c-mchp-pci1xxxx.c
index b21ffd6df927..5ef136c3ecb1 100644
--- a/drivers/i2c/busses/i2c-mchp-pci1xxxx.c
+++ b/drivers/i2c/busses/i2c-mchp-pci1xxxx.c
@@ -1118,8 +1118,10 @@ static int pci1xxxx_i2c_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(pci1xxxx_i2c_pm_ops, pci1xxxx_i2c_suspend,
pci1xxxx_i2c_resume);
-static void pci1xxxx_i2c_shutdown(struct pci1xxxx_i2c *i2c)
+static void pci1xxxx_i2c_shutdown(void *data)
{
+ struct pci1xxxx_i2c *i2c = data;
+
pci1xxxx_i2c_config_padctrl(i2c, false);
pci1xxxx_i2c_configure_core_reg(i2c, false);
}
@@ -1156,7 +1158,7 @@ static int pci1xxxx_i2c_probe_pci(struct pci_dev *pdev,
init_completion(&i2c->i2c_xfer_done);
pci1xxxx_i2c_init(i2c);
- ret = devm_add_action(dev, (void (*)(void *))pci1xxxx_i2c_shutdown, i2c);
+ ret = devm_add_action(dev, pci1xxxx_i2c_shutdown, i2c);
if (ret)
return ret;
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index 09489380afda..e79f5497948b 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -108,6 +108,27 @@ static const struct dmi_system_id dmi_use_low_level_irq[] = {
{} /* Terminating entry */
};
+/*
+ * Some devices have a wrong entry which points to a GPIO which is
+ * required in another driver, so this driver must not claim it.
+ */
+static const struct dmi_system_id dmi_invalid_acpi_index[] = {
+ {
+ /*
+ * Lenovo Yoga Book X90F / X90L, the PNP0C40 home button entry
+ * points to a GPIO which is not a home button and which is
+ * required by the lenovo-yogabook driver.
+ */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+ },
+ .driver_data = (void *)1l,
+ },
+ {} /* Terminating entry */
+};
+
/*
* Get the Nth GPIO number from the ACPI object.
*/
@@ -137,6 +158,8 @@ soc_button_device_create(struct platform_device *pdev,
struct platform_device *pd;
struct gpio_keys_button *gpio_keys;
struct gpio_keys_platform_data *gpio_keys_pdata;
+ const struct dmi_system_id *dmi_id;
+ int invalid_acpi_index = -1;
int error, gpio, irq;
int n_buttons = 0;
@@ -154,10 +177,17 @@ soc_button_device_create(struct platform_device *pdev,
gpio_keys = (void *)(gpio_keys_pdata + 1);
n_buttons = 0;
+ dmi_id = dmi_first_match(dmi_invalid_acpi_index);
+ if (dmi_id)
+ invalid_acpi_index = (long)dmi_id->driver_data;
+
for (info = button_info; info->name; info++) {
if (info->autorepeat != autorepeat)
continue;
+ if (info->acpi_index == invalid_acpi_index)
+ continue;
+
error = soc_button_lookup_gpio(&pdev->dev, info->acpi_index, &gpio, &irq);
if (error || irq < 0) {
/*
diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
index 4f5ab3cae8a7..b1512f9c5895 100644
--- a/drivers/media/cec/core/cec-adap.c
+++ b/drivers/media/cec/core/cec-adap.c
@@ -1090,7 +1090,8 @@ void cec_received_msg_ts(struct cec_adapter *adap,
mutex_lock(&adap->lock);
dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg);
- adap->last_initiator = 0xff;
+ if (!adap->transmit_in_progress)
+ adap->last_initiator = 0xff;
/* Check if this message was for us (directed or broadcast). */
if (!cec_msg_is_broadcast(msg))
@@ -1582,7 +1583,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
*
* This function is called with adap->lock held.
*/
-static int cec_adap_enable(struct cec_adapter *adap)
+int cec_adap_enable(struct cec_adapter *adap)
{
bool enable;
int ret = 0;
@@ -1592,6 +1593,9 @@ static int cec_adap_enable(struct cec_adapter *adap)
if (adap->needs_hpd)
enable = enable && adap->phys_addr != CEC_PHYS_ADDR_INVALID;
+ if (adap->devnode.unregistered)
+ enable = false;
+
if (enable == adap->is_enabled)
return 0;
diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c
index af358e901b5f..7e153c5cad04 100644
--- a/drivers/media/cec/core/cec-core.c
+++ b/drivers/media/cec/core/cec-core.c
@@ -191,6 +191,8 @@ static void cec_devnode_unregister(struct cec_adapter *adap)
mutex_lock(&adap->lock);
__cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
__cec_s_log_addrs(adap, NULL, false);
+ // Disable the adapter (since adap->devnode.unregistered is true)
+ cec_adap_enable(adap);
mutex_unlock(&adap->lock);
cdev_device_del(&devnode->cdev, &devnode->dev);
diff --git a/drivers/media/cec/core/cec-priv.h b/drivers/media/cec/core/cec-priv.h
index b78df931aa74..ed1f8c67626b 100644
--- a/drivers/media/cec/core/cec-priv.h
+++ b/drivers/media/cec/core/cec-priv.h
@@ -47,6 +47,7 @@ int cec_monitor_pin_cnt_inc(struct cec_adapter *adap);
void cec_monitor_pin_cnt_dec(struct cec_adapter *adap);
int cec_adap_status(struct seq_file *file, void *priv);
int cec_thread_func(void *_adap);
+int cec_adap_enable(struct cec_adapter *adap);
void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
int __cec_s_log_addrs(struct cec_adapter *adap,
struct cec_log_addrs *log_addrs, bool block);
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 641ab4f42125..c15226be4d2a 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -1411,8 +1411,8 @@ static int bcm2835_probe(struct platform_device *pdev)
host->max_clk = clk_get_rate(clk);
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0) {
- ret = -EINVAL;
+ if (host->irq < 0) {
+ ret = host->irq;
goto err;
}
diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
index 39c6707fdfdb..9af6b0902efe 100644
--- a/drivers/mmc/host/litex_mmc.c
+++ b/drivers/mmc/host/litex_mmc.c
@@ -649,6 +649,7 @@ static struct platform_driver litex_mmc_driver = {
.driver = {
.name = "litex-mmc",
.of_match_table = litex_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};
module_platform_driver(litex_mmc_driver);
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 5c94ad4661ce..0f39f86bd0c2 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -1007,11 +1007,8 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
if (data && !cmd->error)
data->bytes_xfered = data->blksz * data->blocks;
- if (meson_mmc_bounce_buf_read(data) ||
- meson_mmc_get_next_command(cmd))
- ret = IRQ_WAKE_THREAD;
- else
- ret = IRQ_HANDLED;
+
+ return IRQ_WAKE_THREAD;
}
out:
@@ -1023,9 +1020,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
writel(start, host->regs + SD_EMMC_START);
}
- if (ret == IRQ_HANDLED)
- meson_mmc_request_done(host->mmc, cmd->mrq);
-
return ret;
}
@@ -1233,8 +1227,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
}
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0) {
- ret = -EINVAL;
+ if (host->irq < 0) {
+ ret = host->irq;
goto free_host;
}
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index b9e5dfe74e5c..1c326e4307f4 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1735,7 +1735,8 @@ static void mmci_set_max_busy_timeout(struct mmc_host *mmc)
return;
if (host->variant->busy_timeout && mmc->actual_clock)
- max_busy_timeout = ~0UL / (mmc->actual_clock / MSEC_PER_SEC);
+ max_busy_timeout = U32_MAX / DIV_ROUND_UP(mmc->actual_clock,
+ MSEC_PER_SEC);
mmc->max_busy_timeout = max_busy_timeout;
}
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 26bc59b5a7cc..425efb3fba04 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -2658,7 +2658,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
- ret = -EINVAL;
+ ret = host->irq;
goto host_free;
}
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 629efbe639c4..b4f6a0a2fcb5 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -704,7 +704,7 @@ static int mvsd_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0)
- return -ENXIO;
+ return irq;
mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
if (!mmc) {
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 57d39283924d..cc2213ea324f 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1343,7 +1343,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0)
- return -ENXIO;
+ return irq;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
host->virt_base = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4bd744755205..2db3a16e63c4 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1791,9 +1791,11 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (res == NULL || irq < 0)
+ if (!res)
return -ENXIO;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c
index 3dc143b03939..679b8b0b310e 100644
--- a/drivers/mmc/host/owl-mmc.c
+++ b/drivers/mmc/host/owl-mmc.c
@@ -638,7 +638,7 @@ static int owl_mmc_probe(struct platform_device *pdev)
owl_host->irq = platform_get_irq(pdev, 0);
if (owl_host->irq < 0) {
- ret = -EINVAL;
+ ret = owl_host->irq;
goto err_release_channel;
}
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 4cca4c90769b..b917060a258a 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -829,7 +829,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
host->ops = &sdhci_acpi_ops_dflt;
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
- err = -EINVAL;
+ err = host->irq;
goto err_free;
}
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 3a091a387ecb..a5ab2af3e520 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2486,6 +2486,9 @@ static inline void sdhci_msm_get_of_property(struct platform_device *pdev,
msm_host->ddr_config = DDR_CONFIG_POR_VAL;
of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config);
+
+ if (of_device_is_compatible(node, "qcom,msm8916-sdhci"))
+ host->quirks2 |= SDHCI_QUIRK2_BROKEN_64_BIT_DMA;
}
static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host)
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index d463e2fd5b1a..c79035727b20 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -65,8 +65,8 @@ static int sdhci_probe(struct platform_device *pdev)
host->hw_name = "sdhci";
host->ops = &sdhci_pltfm_ops;
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0) {
- ret = -EINVAL;
+ if (host->irq < 0) {
+ ret = host->irq;
goto err_host;
}
host->quirks = SDHCI_QUIRK_BROKEN_ADMA;
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 0fd4c9d644dd..5cf53348372a 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1400,7 +1400,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
irq[0] = platform_get_irq(pdev, 0);
irq[1] = platform_get_irq_optional(pdev, 1);
if (irq[0] < 0)
- return -ENXIO;
+ return irq[0];
reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg))
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 3db9f32d6a7b..69dcb8805e05 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -1350,8 +1350,8 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
return ret;
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0) {
- ret = -EINVAL;
+ if (host->irq < 0) {
+ ret = host->irq;
goto error_disable_mmc;
}
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c
index 99515be6e5e5..2032e4e1ee68 100644
--- a/drivers/mmc/host/usdhi6rol0.c
+++ b/drivers/mmc/host/usdhi6rol0.c
@@ -1757,8 +1757,10 @@ static int usdhi6_probe(struct platform_device *pdev)
irq_cd = platform_get_irq_byname(pdev, "card detect");
irq_sd = platform_get_irq_byname(pdev, "data");
irq_sdio = platform_get_irq_byname(pdev, "SDIO");
- if (irq_sd < 0 || irq_sdio < 0)
- return -ENODEV;
+ if (irq_sd < 0)
+ return irq_sd;
+ if (irq_sdio < 0)
+ return irq_sdio;
mmc = mmc_alloc_host(sizeof(struct usdhi6_host), dev);
if (!mmc)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 855220c5ce33..51d2ef0dc835 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -998,6 +998,18 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
mutex_unlock(&priv->reg_mutex);
}
+static void
+mt753x_trap_frames(struct mt7530_priv *priv)
+{
+ /* Trap BPDUs to the CPU port(s) */
+ mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
+ MT753X_BPDU_CPU_ONLY);
+
+ /* Trap LLDP frames with :0E MAC DA to the CPU port(s) */
+ mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_PORT_FW_MASK,
+ MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY));
+}
+
static int
mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
{
@@ -1020,7 +1032,7 @@ mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
UNU_FFP(BIT(port)));
/* Set CPU port number */
- if (priv->id == ID_MT7621)
+ if (priv->id == ID_MT7530 || priv->id == ID_MT7621)
mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
/* CPU port gets connected to all user ports of
@@ -2219,6 +2231,8 @@ mt7530_setup(struct dsa_switch *ds)
priv->p6_interface = PHY_INTERFACE_MODE_NA;
+ mt753x_trap_frames(priv);
+
/* Enable and reset MIB counters */
mt7530_mib_reset(ds);
@@ -2325,8 +2339,8 @@ mt7531_setup_common(struct dsa_switch *ds)
BIT(cpu_dp->index));
break;
}
- mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
- MT753X_BPDU_CPU_ONLY);
+
+ mt753x_trap_frames(priv);
/* Enable and reset MIB counters */
mt7530_mib_reset(ds);
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index e8d966435350..9a45663d8b4e 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -65,6 +65,11 @@ enum mt753x_id {
#define MT753X_BPC 0x24
#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0)
+/* Register for :03 and :0E MAC DA frame control */
+#define MT753X_RGAC2 0x2c
+#define MT753X_R0E_PORT_FW_MASK GENMASK(18, 16)
+#define MT753X_R0E_PORT_FW(x) FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x)
+
enum mt753x_bpdu_port_fw {
MT753X_BPDU_FOLLOW_MFC,
MT753X_BPDU_CPU_EXCLUDE = 4,
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index a92a74761546..5d39df845265 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1136,8 +1136,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
VLAN_ETH_HLEN : ETH_HLEN;
if (skb->len <= 60 &&
- (lancer_chip(adapter) || skb_vlan_tag_present(skb)) &&
- is_ipv4_pkt(skb)) {
+ (lancer_chip(adapter) || BE3_chip(adapter) ||
+ skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
ip = (struct iphdr *)ip_hdr(skb);
pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
index b1dfad274a39..a3e7602b044e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
@@ -1200,9 +1200,13 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
}
case DR_ACTION_TYP_TNL_L3_TO_L2:
{
- u8 hw_actions[ACTION_CACHE_LINE_SIZE] = {};
+ u8 *hw_actions;
int ret;
+ hw_actions = kzalloc(ACTION_CACHE_LINE_SIZE, GFP_KERNEL);
+ if (!hw_actions)
+ return -ENOMEM;
+
ret = mlx5dr_ste_set_action_decap_l3_list(dmn->ste_ctx,
data, data_sz,
hw_actions,
@@ -1210,6 +1214,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
&action->rewrite->num_of_actions);
if (ret) {
mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n");
+ kfree(hw_actions);
return ret;
}
@@ -1217,6 +1222,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
DR_CHUNK_SIZE_8);
if (!action->rewrite->chunk) {
mlx5dr_dbg(dmn, "Failed allocating modify header chunk\n");
+ kfree(hw_actions);
return -ENOMEM;
}
@@ -1230,6 +1236,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
if (ret) {
mlx5dr_dbg(dmn, "Writing decap l3 actions to ICM failed\n");
mlx5dr_icm_free_chunk(action->rewrite->chunk);
+ kfree(hw_actions);
return ret;
}
return 0;
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index c865a4be05ee..4a1b94e5a8ea 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -582,8 +582,7 @@ qcaspi_spi_thread(void *data)
while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE);
if ((qca->intr_req == qca->intr_svc) &&
- (qca->txr.skb[qca->txr.head] == NULL) &&
- (qca->sync == QCASPI_SYNC_READY))
+ !qca->txr.skb[qca->txr.head])
schedule();
set_current_state(TASK_RUNNING);
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index d30459dbfe8f..b63e47af6365 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -2950,7 +2950,7 @@ static u32 efx_ef10_extract_event_ts(efx_qword_t *event)
return tstamp;
}
-static void
+static int
efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
{
struct efx_nic *efx = channel->efx;
@@ -2958,13 +2958,14 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
unsigned int tx_ev_desc_ptr;
unsigned int tx_ev_q_label;
unsigned int tx_ev_type;
+ int work_done;
u64 ts_part;
if (unlikely(READ_ONCE(efx->reset_pending)))
- return;
+ return 0;
if (unlikely(EFX_QWORD_FIELD(*event, ESF_DZ_TX_DROP_EVENT)))
- return;
+ return 0;
/* Get the transmit queue */
tx_ev_q_label = EFX_QWORD_FIELD(*event, ESF_DZ_TX_QLABEL);
@@ -2973,8 +2974,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
if (!tx_queue->timestamping) {
/* Transmit completion */
tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, ESF_DZ_TX_DESCR_INDX);
- efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
- return;
+ return efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
}
/* Transmit timestamps are only available for 8XXX series. They result
@@ -3000,6 +3000,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
* fields in the event.
*/
tx_ev_type = EFX_QWORD_FIELD(*event, ESF_EZ_TX_SOFT1);
+ work_done = 0;
switch (tx_ev_type) {
case TX_TIMESTAMP_EVENT_TX_EV_COMPLETION:
@@ -3016,6 +3017,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
tx_queue->completed_timestamp_major = ts_part;
efx_xmit_done_single(tx_queue);
+ work_done = 1;
break;
default:
@@ -3026,6 +3028,8 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
EFX_QWORD_VAL(*event));
break;
}
+
+ return work_done;
}
static void
@@ -3081,13 +3085,16 @@ static void efx_ef10_handle_driver_generated_event(struct efx_channel *channel,
}
}
+#define EFX_NAPI_MAX_TX 512
+
static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
{
struct efx_nic *efx = channel->efx;
efx_qword_t event, *p_event;
unsigned int read_ptr;
- int ev_code;
+ int spent_tx = 0;
int spent = 0;
+ int ev_code;
if (quota <= 0)
return spent;
@@ -3126,7 +3133,11 @@ static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
}
break;
case ESE_DZ_EV_CODE_TX_EV:
- efx_ef10_handle_tx_event(channel, &event);
+ spent_tx += efx_ef10_handle_tx_event(channel, &event);
+ if (spent_tx >= EFX_NAPI_MAX_TX) {
+ spent = quota;
+ goto out;
+ }
break;
case ESE_DZ_EV_CODE_DRIVER_EV:
efx_ef10_handle_driver_event(channel, &event);
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index ad686c671ab8..fa1f7039a8e2 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -242,6 +242,8 @@ static void ef100_ev_read_ack(struct efx_channel *channel)
efx_reg(channel->efx, ER_GZ_EVQ_INT_PRIME));
}
+#define EFX_NAPI_MAX_TX 512
+
static int ef100_ev_process(struct efx_channel *channel, int quota)
{
struct efx_nic *efx = channel->efx;
@@ -249,6 +251,7 @@ static int ef100_ev_process(struct efx_channel *channel, int quota)
bool evq_phase, old_evq_phase;
unsigned int read_ptr;
efx_qword_t *p_event;
+ int spent_tx = 0;
int spent = 0;
bool ev_phase;
int ev_type;
@@ -284,7 +287,9 @@ static int ef100_ev_process(struct efx_channel *channel, int quota)
efx_mcdi_process_event(channel, p_event);
break;
case ESE_GZ_EF100_EV_TX_COMPLETION:
- ef100_ev_tx(channel, p_event);
+ spent_tx += ef100_ev_tx(channel, p_event);
+ if (spent_tx >= EFX_NAPI_MAX_TX)
+ spent = quota;
break;
case ESE_GZ_EF100_EV_DRIVER:
netif_info(efx, drv, efx->net_dev,
diff --git a/drivers/net/ethernet/sfc/ef100_tx.c b/drivers/net/ethernet/sfc/ef100_tx.c
index 29ffaf35559d..849e5555bd12 100644
--- a/drivers/net/ethernet/sfc/ef100_tx.c
+++ b/drivers/net/ethernet/sfc/ef100_tx.c
@@ -346,7 +346,7 @@ void ef100_tx_write(struct efx_tx_queue *tx_queue)
ef100_tx_push_buffers(tx_queue);
}
-void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event)
+int ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event)
{
unsigned int tx_done =
EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_TXCMPL_NUM_DESC);
@@ -357,7 +357,7 @@ void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event)
unsigned int tx_index = (tx_queue->read_count + tx_done - 1) &
tx_queue->ptr_mask;
- efx_xmit_done(tx_queue, tx_index);
+ return efx_xmit_done(tx_queue, tx_index);
}
/* Add a socket buffer to a TX queue
diff --git a/drivers/net/ethernet/sfc/ef100_tx.h b/drivers/net/ethernet/sfc/ef100_tx.h
index e9e11540fcde..d9a0819c5a72 100644
--- a/drivers/net/ethernet/sfc/ef100_tx.h
+++ b/drivers/net/ethernet/sfc/ef100_tx.h
@@ -20,7 +20,7 @@ void ef100_tx_init(struct efx_tx_queue *tx_queue);
void ef100_tx_write(struct efx_tx_queue *tx_queue);
unsigned int ef100_tx_max_skb_descs(struct efx_nic *efx);
-void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event);
+int ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event);
netdev_tx_t ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
int __ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c
index 67e789b96c43..755aa92bf823 100644
--- a/drivers/net/ethernet/sfc/tx_common.c
+++ b/drivers/net/ethernet/sfc/tx_common.c
@@ -249,7 +249,7 @@ void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue)
}
}
-void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
+int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
{
unsigned int fill_level, pkts_compl = 0, bytes_compl = 0;
unsigned int efv_pkts_compl = 0;
@@ -279,6 +279,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
}
efx_xmit_done_check_empty(tx_queue);
+
+ return pkts_compl + efv_pkts_compl;
}
/* Remove buffers put into a tx_queue for the current packet.
diff --git a/drivers/net/ethernet/sfc/tx_common.h b/drivers/net/ethernet/sfc/tx_common.h
index d87aecbc7bf1..1e9f42938aac 100644
--- a/drivers/net/ethernet/sfc/tx_common.h
+++ b/drivers/net/ethernet/sfc/tx_common.h
@@ -28,7 +28,7 @@ static inline bool efx_tx_buffer_in_use(struct efx_tx_buffer *buffer)
}
void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue);
-void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
+int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
unsigned int insert_count);
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 2f0544dd7c2a..9b3da61840a8 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -522,7 +522,7 @@ static int hwsim_del_edge_nl(struct sk_buff *msg, struct genl_info *info)
static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
{
struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1];
- struct hwsim_edge_info *einfo;
+ struct hwsim_edge_info *einfo, *einfo_old;
struct hwsim_phy *phy_v0;
struct hwsim_edge *e;
u32 v0, v1;
@@ -560,8 +560,10 @@ static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
list_for_each_entry_rcu(e, &phy_v0->edges, list) {
if (e->endpoint->idx == v1) {
einfo->lqi = lqi;
- rcu_assign_pointer(e->info, einfo);
+ einfo_old = rcu_replace_pointer(e->info, einfo,
+ lockdep_is_held(&hwsim_phys_lock));
rcu_read_unlock();
+ kfree_rcu(einfo_old, rcu);
mutex_unlock(&hwsim_phys_lock);
return 0;
}
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 14990f8462ae..f7436191fa80 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -905,7 +905,7 @@ static int dp83867_phy_reset(struct phy_device *phydev)
{
int err;
- err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART);
+ err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET);
if (err < 0)
return err;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 03e8234d0352..f6872b2a0d9d 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -547,6 +547,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
+ IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
+ IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_name),
diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c
index 85bf8d586c70..0f6befe8be1e 100644
--- a/drivers/nfc/nfcsim.c
+++ b/drivers/nfc/nfcsim.c
@@ -336,10 +336,6 @@ static struct dentry *nfcsim_debugfs_root;
static void nfcsim_debugfs_init(void)
{
nfcsim_debugfs_root = debugfs_create_dir("nfcsim", NULL);
-
- if (!nfcsim_debugfs_root)
- pr_err("Could not create debugfs entry\n");
-
}
static void nfcsim_debugfs_remove(void)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 2e22c78991cc..a7d9b5b42b38 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -395,7 +395,16 @@ void nvme_complete_rq(struct request *req)
trace_nvme_complete_rq(req);
nvme_cleanup_cmd(req);
- if (ctrl->kas)
+ /*
+ * Completions of long-running commands should not be able to
+ * defer sending of periodic keep alives, since the controller
+ * may have completed processing such commands a long time ago
+ * (arbitrarily close to command submission time).
+ * req->deadline - req->timeout is the command submission time
+ * in jiffies.
+ */
+ if (ctrl->kas &&
+ req->deadline - req->timeout >= ctrl->ka_last_check_time)
ctrl->comp_seen = true;
switch (nvme_decide_disposition(req)) {
@@ -1198,9 +1207,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU);
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+ unsigned long delay = ctrl->kato * HZ / 2;
+
+ /*
+ * When using Traffic Based Keep Alive, we need to run
+ * nvme_keep_alive_work at twice the normal frequency, as one
+ * command completion can postpone sending a keep alive command
+ * by up to twice the delay between runs.
+ */
+ if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+ delay /= 2;
+ return delay;
+}
+
static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
{
- queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work,
+ nvme_keep_alive_work_period(ctrl));
}
static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
@@ -1209,6 +1234,20 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
struct nvme_ctrl *ctrl = rq->end_io_data;
unsigned long flags;
bool startka = false;
+ unsigned long rtt = jiffies - (rq->deadline - rq->timeout);
+ unsigned long delay = nvme_keep_alive_work_period(ctrl);
+
+ /*
+ * Subtract off the keepalive RTT so nvme_keep_alive_work runs
+ * at the desired frequency.
+ */
+ if (rtt <= delay) {
+ delay -= rtt;
+ } else {
+ dev_warn(ctrl->device, "long keepalive RTT (%u ms)\n",
+ jiffies_to_msecs(rtt));
+ delay = 0;
+ }
blk_mq_free_request(rq);
@@ -1219,6 +1258,7 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
return RQ_END_IO_NONE;
}
+ ctrl->ka_last_check_time = jiffies;
ctrl->comp_seen = false;
spin_lock_irqsave(&ctrl->lock, flags);
if (ctrl->state == NVME_CTRL_LIVE ||
@@ -1226,7 +1266,7 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
startka = true;
spin_unlock_irqrestore(&ctrl->lock, flags);
if (startka)
- nvme_queue_keep_alive_work(ctrl);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
return RQ_END_IO_NONE;
}
@@ -1237,6 +1277,8 @@ static void nvme_keep_alive_work(struct work_struct *work)
bool comp_seen = ctrl->comp_seen;
struct request *rq;
+ ctrl->ka_last_check_time = jiffies;
+
if ((ctrl->ctratt & NVME_CTRL_ATTR_TBKAS) && comp_seen) {
dev_dbg(ctrl->device,
"reschedule traffic based keep-alive timer\n");
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 3f82de6060ef..2aa514c3dfa1 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -323,6 +323,7 @@ struct nvme_ctrl {
struct delayed_work ka_work;
struct delayed_work failfast_work;
struct nvme_command ka_cmd;
+ unsigned long ka_last_check_time;
struct work_struct fw_act_work;
unsigned long events;
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index f1ec8931dfbc..3351863352d3 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -489,7 +489,10 @@ struct hv_pcibus_device {
struct fwnode_handle *fwnode;
/* Protocol version negotiated with the host */
enum pci_protocol_version_t protocol_version;
+
+ struct mutex state_lock;
enum hv_pcibus_state state;
+
struct hv_device *hdev;
resource_size_t low_mmio_space;
resource_size_t high_mmio_space;
@@ -553,19 +556,10 @@ struct hv_dr_state {
struct hv_pcidev_description func[];
};
-enum hv_pcichild_state {
- hv_pcichild_init = 0,
- hv_pcichild_requirements,
- hv_pcichild_resourced,
- hv_pcichild_ejecting,
- hv_pcichild_maximum
-};
-
struct hv_pci_dev {
/* List protected by pci_rescan_remove_lock */
struct list_head list_entry;
refcount_t refs;
- enum hv_pcichild_state state;
struct pci_slot *pci_slot;
struct hv_pcidev_description desc;
bool reported_missing;
@@ -656,6 +650,11 @@ static void hv_arch_irq_unmask(struct irq_data *data)
pbus = pdev->bus;
hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
int_desc = data->chip_data;
+ if (!int_desc) {
+ dev_warn(&hbus->hdev->device, "%s() can not unmask irq %u\n",
+ __func__, data->irq);
+ return;
+ }
spin_lock_irqsave(&hbus->retarget_msi_interrupt_lock, flags);
@@ -1924,12 +1923,6 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
hv_pci_onchannelcallback(hbus);
spin_unlock_irqrestore(&channel->sched_lock, flags);
- if (hpdev->state == hv_pcichild_ejecting) {
- dev_err_once(&hbus->hdev->device,
- "the device is being ejected\n");
- goto enable_tasklet;
- }
-
udelay(100);
}
@@ -2535,6 +2528,8 @@ static void pci_devices_present_work(struct work_struct *work)
if (!dr)
return;
+ mutex_lock(&hbus->state_lock);
+
/* First, mark all existing children as reported missing. */
spin_lock_irqsave(&hbus->device_list_lock, flags);
list_for_each_entry(hpdev, &hbus->children, list_entry) {
@@ -2616,6 +2611,8 @@ static void pci_devices_present_work(struct work_struct *work)
break;
}
+ mutex_unlock(&hbus->state_lock);
+
kfree(dr);
}
@@ -2764,7 +2761,7 @@ static void hv_eject_device_work(struct work_struct *work)
hpdev = container_of(work, struct hv_pci_dev, wrk);
hbus = hpdev->hbus;
- WARN_ON(hpdev->state != hv_pcichild_ejecting);
+ mutex_lock(&hbus->state_lock);
/*
* Ejection can come before or after the PCI bus has been set up, so
@@ -2802,6 +2799,8 @@ static void hv_eject_device_work(struct work_struct *work)
put_pcichild(hpdev);
put_pcichild(hpdev);
/* hpdev has been freed. Do not use it any more. */
+
+ mutex_unlock(&hbus->state_lock);
}
/**
@@ -2822,7 +2821,6 @@ static void hv_pci_eject_device(struct hv_pci_dev *hpdev)
return;
}
- hpdev->state = hv_pcichild_ejecting;
get_pcichild(hpdev);
INIT_WORK(&hpdev->wrk, hv_eject_device_work);
queue_work(hbus->wq, &hpdev->wrk);
@@ -3251,8 +3249,10 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
struct pci_bus_d0_entry *d0_entry;
struct hv_pci_compl comp_pkt;
struct pci_packet *pkt;
+ bool retry = true;
int ret;
+enter_d0_retry:
/*
* Tell the host that the bus is ready to use, and moved into the
* powered-on state. This includes telling the host which region
@@ -3279,6 +3279,38 @@ static int hv_pci_enter_d0(struct hv_device *hdev)
if (ret)
goto exit;
+ /*
+ * In certain case (Kdump) the pci device of interest was
+ * not cleanly shut down and resource is still held on host
+ * side, the host could return invalid device status.
+ * We need to explicitly request host to release the resource
+ * and try to enter D0 again.
+ */
+ if (comp_pkt.completion_status < 0 && retry) {
+ retry = false;
+
+ dev_err(&hdev->device, "Retrying D0 Entry\n");
+
+ /*
+ * Hv_pci_bus_exit() calls hv_send_resource_released()
+ * to free up resources of its child devices.
+ * In the kdump kernel we need to set the
+ * wslot_res_allocated to 255 so it scans all child
+ * devices to release resources allocated in the
+ * normal kernel before panic happened.
+ */
+ hbus->wslot_res_allocated = 255;
+
+ ret = hv_pci_bus_exit(hdev, true);
+
+ if (ret == 0) {
+ kfree(pkt);
+ goto enter_d0_retry;
+ }
+ dev_err(&hdev->device,
+ "Retrying D0 failed with ret %d\n", ret);
+ }
+
if (comp_pkt.completion_status < 0) {
dev_err(&hdev->device,
"PCI Pass-through VSP failed D0 Entry with status %x\n",
@@ -3321,6 +3353,24 @@ static int hv_pci_query_relations(struct hv_device *hdev)
if (!ret)
ret = wait_for_response(hdev, &comp);
+ /*
+ * In the case of fast device addition/removal, it's possible that
+ * vmbus_sendpacket() or wait_for_response() returns -ENODEV but we
+ * already got a PCI_BUS_RELATIONS* message from the host and the
+ * channel callback already scheduled a work to hbus->wq, which can be
+ * running pci_devices_present_work() -> survey_child_resources() ->
+ * complete(&hbus->survey_event), even after hv_pci_query_relations()
+ * exits and the stack variable 'comp' is no longer valid; as a result,
+ * a hang or a page fault may happen when the complete() calls
+ * raw_spin_lock_irqsave(). Flush hbus->wq before we exit from
+ * hv_pci_query_relations() to avoid the issues. Note: if 'ret' is
+ * -ENODEV, there can't be any more work item scheduled to hbus->wq
+ * after the flush_workqueue(): see vmbus_onoffer_rescind() ->
+ * vmbus_reset_channel_cb(), vmbus_rescind_cleanup() ->
+ * channel->rescind = true.
+ */
+ flush_workqueue(hbus->wq);
+
return ret;
}
@@ -3506,7 +3556,6 @@ static int hv_pci_probe(struct hv_device *hdev,
struct hv_pcibus_device *hbus;
u16 dom_req, dom;
char *name;
- bool enter_d0_retry = true;
int ret;
/*
@@ -3542,6 +3591,7 @@ static int hv_pci_probe(struct hv_device *hdev,
return -ENOMEM;
hbus->bridge = bridge;
+ mutex_init(&hbus->state_lock);
hbus->state = hv_pcibus_init;
hbus->wslot_res_allocated = -1;
@@ -3646,49 +3696,15 @@ static int hv_pci_probe(struct hv_device *hdev,
if (ret)
goto free_fwnode;
-retry:
ret = hv_pci_query_relations(hdev);
if (ret)
goto free_irq_domain;
- ret = hv_pci_enter_d0(hdev);
- /*
- * In certain case (Kdump) the pci device of interest was
- * not cleanly shut down and resource is still held on host
- * side, the host could return invalid device status.
- * We need to explicitly request host to release the resource
- * and try to enter D0 again.
- * Since the hv_pci_bus_exit() call releases structures
- * of all its child devices, we need to start the retry from
- * hv_pci_query_relations() call, requesting host to send
- * the synchronous child device relations message before this
- * information is needed in hv_send_resources_allocated()
- * call later.
- */
- if (ret == -EPROTO && enter_d0_retry) {
- enter_d0_retry = false;
-
- dev_err(&hdev->device, "Retrying D0 Entry\n");
-
- /*
- * Hv_pci_bus_exit() calls hv_send_resources_released()
- * to free up resources of its child devices.
- * In the kdump kernel we need to set the
- * wslot_res_allocated to 255 so it scans all child
- * devices to release resources allocated in the
- * normal kernel before panic happened.
- */
- hbus->wslot_res_allocated = 255;
- ret = hv_pci_bus_exit(hdev, true);
-
- if (ret == 0)
- goto retry;
+ mutex_lock(&hbus->state_lock);
- dev_err(&hdev->device,
- "Retrying D0 failed with ret %d\n", ret);
- }
+ ret = hv_pci_enter_d0(hdev);
if (ret)
- goto free_irq_domain;
+ goto release_state_lock;
ret = hv_pci_allocate_bridge_windows(hbus);
if (ret)
@@ -3706,12 +3722,15 @@ static int hv_pci_probe(struct hv_device *hdev,
if (ret)
goto free_windows;
+ mutex_unlock(&hbus->state_lock);
return 0;
free_windows:
hv_pci_free_bridge_windows(hbus);
exit_d0:
(void) hv_pci_bus_exit(hdev, true);
+release_state_lock:
+ mutex_unlock(&hbus->state_lock);
free_irq_domain:
irq_domain_remove(hbus->irq_domain);
free_fwnode:
@@ -3965,20 +3984,26 @@ static int hv_pci_resume(struct hv_device *hdev)
if (ret)
goto out;
+ mutex_lock(&hbus->state_lock);
+
ret = hv_pci_enter_d0(hdev);
if (ret)
- goto out;
+ goto release_state_lock;
ret = hv_send_resources_allocated(hdev);
if (ret)
- goto out;
+ goto release_state_lock;
prepopulate_bars(hbus);
hv_pci_restore_msi_state(hbus);
hbus->state = hv_pcibus_installed;
+ mutex_unlock(&hbus->state_lock);
return 0;
+
+release_state_lock:
+ mutex_unlock(&hbus->state_lock);
out:
vmbus_close(hdev->channel);
return ret;
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index dc9803e1a4b9..73d2357e32f8 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -297,6 +297,8 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
/* Enable Static Slider */
if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
amd_pmf_init_sps(dev);
+ dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
+ power_supply_reg_notifier(&dev->pwr_src_notifier);
dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
}
@@ -315,8 +317,10 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
{
- if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
+ if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+ power_supply_unreg_notifier(&dev->pwr_src_notifier);
amd_pmf_deinit_sps(dev);
+ }
if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
amd_pmf_deinit_auto_mode(dev);
@@ -399,9 +403,6 @@ static int amd_pmf_probe(struct platform_device *pdev)
apmf_install_handler(dev);
amd_pmf_dbgfs_register(dev);
- dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
- power_supply_reg_notifier(&dev->pwr_src_notifier);
-
dev_info(dev->dev, "registered PMF device successfully\n");
return 0;
@@ -411,7 +412,6 @@ static int amd_pmf_remove(struct platform_device *pdev)
{
struct amd_pmf_dev *dev = platform_get_drvdata(pdev);
- power_supply_unreg_notifier(&dev->pwr_src_notifier);
amd_pmf_deinit_features(dev);
apmf_acpi_deinit(dev);
amd_pmf_dbgfs_unregister(dev);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index ba4c69226c33..02813b63f90f 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1367,6 +1367,7 @@ void ccw_device_set_notoper(struct ccw_device *cdev)
enum io_sch_action {
IO_SCH_UNREG,
IO_SCH_ORPH_UNREG,
+ IO_SCH_UNREG_CDEV,
IO_SCH_ATTACH,
IO_SCH_UNREG_ATTACH,
IO_SCH_ORPH_ATTACH,
@@ -1399,7 +1400,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
}
if ((sch->schib.pmcw.pam & sch->opm) == 0) {
if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK)
- return IO_SCH_UNREG;
+ return IO_SCH_UNREG_CDEV;
return IO_SCH_DISC;
}
if (device_is_disconnected(cdev))
@@ -1461,6 +1462,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
case IO_SCH_ORPH_ATTACH:
ccw_device_set_disconnected(cdev);
break;
+ case IO_SCH_UNREG_CDEV:
case IO_SCH_UNREG_ATTACH:
case IO_SCH_UNREG:
if (!cdev)
@@ -1494,6 +1496,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
if (rc)
goto out;
break;
+ case IO_SCH_UNREG_CDEV:
case IO_SCH_UNREG_ATTACH:
spin_lock_irqsave(sch->lock, flags);
sch_set_cdev(sch, NULL);
diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c
index 58ea013fa918..2a1096dab63d 100644
--- a/drivers/soundwire/dmi-quirks.c
+++ b/drivers/soundwire/dmi-quirks.c
@@ -99,6 +99,13 @@ static const struct dmi_system_id adr_remap_quirk_table[] = {
},
.driver_data = (void *)intel_tgl_bios,
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8709"),
+ },
+ .driver_data = (void *)intel_tgl_bios,
+ },
{
/* quirk used for NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
.matches = {
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index 21c50972047f..b2eb3090f4b4 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -1090,8 +1090,10 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
}
sruntime = sdw_alloc_stream(dai->name);
- if (!sruntime)
- return -ENOMEM;
+ if (!sruntime) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
ctrl->sruntime[dai->id] = sruntime;
@@ -1101,12 +1103,19 @@ static int qcom_swrm_startup(struct snd_pcm_substream *substream,
if (ret < 0 && ret != -ENOTSUPP) {
dev_err(dai->dev, "Failed to set sdw stream on %s\n",
codec_dai->name);
- sdw_release_stream(sruntime);
- return ret;
+ goto err_set_stream;
}
}
return 0;
+
+err_set_stream:
+ sdw_release_stream(sruntime);
+err_alloc:
+ pm_runtime_mark_last_busy(ctrl->dev);
+ pm_runtime_put_autosuspend(ctrl->dev);
+
+ return ret;
}
static void qcom_swrm_shutdown(struct snd_pcm_substream *substream,
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index e8c1c8a4c6c8..9e324d72596a 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -905,9 +905,14 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller);
if (ret == -EPROBE_DEFER)
goto out_pm_get;
-
if (ret < 0)
dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret);
+ else
+ /*
+ * disable LPSPI module IRQ when enable DMA mode successfully,
+ * to prevent the unexpected LPSPI module IRQ events.
+ */
+ disable_irq(irq);
ret = devm_spi_register_controller(&pdev->dev, controller);
if (ret < 0) {
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 4e83cc5b445d..dd1581893fe7 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -595,6 +595,8 @@ static int spi_geni_init(struct spi_geni_master *mas)
geni_se_select_mode(se, GENI_GPI_DMA);
dev_dbg(mas->dev, "Using GPI DMA mode for SPI\n");
break;
+ } else if (ret == -EPROBE_DEFER) {
+ goto out_pm;
}
/*
* in case of failure to get dma channel, we can still do the
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index ff49c8f3fe24..62b2d0dcfda8 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -1128,6 +1128,7 @@ int iscsi_target_locate_portal(
iscsi_target_set_sock_callbacks(conn);
login->np = np;
+ conn->tpg = NULL;
login_req = (struct iscsi_login_req *) login->req;
payload_length = ntoh24(login_req->dlength);
@@ -1195,7 +1196,6 @@ int iscsi_target_locate_portal(
*/
sessiontype = strncmp(s_buf, DISCOVERY, 9);
if (!sessiontype) {
- conn->tpg = iscsit_global->discovery_tpg;
if (!login->leading_connection)
goto get_target;
@@ -1212,9 +1212,11 @@ int iscsi_target_locate_portal(
* Serialize access across the discovery struct iscsi_portal_group to
* process login attempt.
*/
+ conn->tpg = iscsit_global->discovery_tpg;
if (iscsit_access_np(np, conn->tpg) < 0) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
+ conn->tpg = NULL;
ret = -1;
goto out;
}
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index dc7ac1ddbca5..1093c74b5284 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -257,6 +257,7 @@ struct lpuart_port {
unsigned int txfifo_size;
unsigned int rxfifo_size;
+ u8 rx_watermark;
bool lpuart_dma_tx_use;
bool lpuart_dma_rx_use;
struct dma_chan *dma_tx_chan;
@@ -283,38 +284,45 @@ struct lpuart_soc_data {
enum lpuart_type devtype;
char iotype;
u8 reg_off;
+ u8 rx_watermark;
};
static const struct lpuart_soc_data vf_data = {
.devtype = VF610_LPUART,
.iotype = UPIO_MEM,
+ .rx_watermark = 1,
};
static const struct lpuart_soc_data ls1021a_data = {
.devtype = LS1021A_LPUART,
.iotype = UPIO_MEM32BE,
+ .rx_watermark = 1,
};
static const struct lpuart_soc_data ls1028a_data = {
.devtype = LS1028A_LPUART,
.iotype = UPIO_MEM32,
+ .rx_watermark = 0,
};
static struct lpuart_soc_data imx7ulp_data = {
.devtype = IMX7ULP_LPUART,
.iotype = UPIO_MEM32,
.reg_off = IMX_REG_OFF,
+ .rx_watermark = 1,
};
static struct lpuart_soc_data imx8qxp_data = {
.devtype = IMX8QXP_LPUART,
.iotype = UPIO_MEM32,
.reg_off = IMX_REG_OFF,
+ .rx_watermark = 1,
};
static struct lpuart_soc_data imxrt1050_data = {
.devtype = IMXRT1050_LPUART,
.iotype = UPIO_MEM32,
.reg_off = IMX_REG_OFF,
+ .rx_watermark = 1,
};
static const struct of_device_id lpuart_dt_ids[] = {
@@ -1533,7 +1541,7 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
}
writeb(0, sport->port.membase + UARTTWFIFO);
- writeb(1, sport->port.membase + UARTRWFIFO);
+ writeb(sport->rx_watermark, sport->port.membase + UARTRWFIFO);
/* Restore cr2 */
writeb(cr2_saved, sport->port.membase + UARTCR2);
@@ -1568,7 +1576,8 @@ static void lpuart32_setup_watermark(struct lpuart_port *sport)
lpuart32_write(&sport->port, val, UARTFIFO);
/* set the watermark */
- val = (0x1 << UARTWATER_RXWATER_OFF) | (0x0 << UARTWATER_TXWATER_OFF);
+ val = (sport->rx_watermark << UARTWATER_RXWATER_OFF) |
+ (0x0 << UARTWATER_TXWATER_OFF);
lpuart32_write(&sport->port, val, UARTWATER);
/* Restore cr2 */
@@ -2714,6 +2723,7 @@ static int lpuart_probe(struct platform_device *pdev)
sport->port.dev = &pdev->dev;
sport->port.type = PORT_LPUART;
sport->devtype = sdata->devtype;
+ sport->rx_watermark = sdata->rx_watermark;
ret = platform_get_irq(pdev, 0);
if (ret < 0)
return ret;
diff --git a/drivers/usb/gadget/udc/amd5536udc_pci.c b/drivers/usb/gadget/udc/amd5536udc_pci.c
index c80f9bd51b75..a36913ae31f9 100644
--- a/drivers/usb/gadget/udc/amd5536udc_pci.c
+++ b/drivers/usb/gadget/udc/amd5536udc_pci.c
@@ -170,6 +170,9 @@ static int udc_pci_probe(
retval = -ENODEV;
goto err_probe;
}
+
+ udc = dev;
+
return 0;
err_probe:
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 4c538b30fd76..4418192ab8aa 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -934,13 +934,18 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock)
err = sock->ops->sendmsg(sock, &msg, len);
if (unlikely(err < 0)) {
+ bool retry = err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS;
+
if (zcopy_used) {
if (vq->heads[ubuf->desc].len == VHOST_DMA_IN_PROGRESS)
vhost_net_ubuf_put(ubufs);
- nvq->upend_idx = ((unsigned)nvq->upend_idx - 1)
- % UIO_MAXIOV;
+ if (retry)
+ nvq->upend_idx = ((unsigned)nvq->upend_idx - 1)
+ % UIO_MAXIOV;
+ else
+ vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
}
- if (err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS) {
+ if (retry) {
vhost_discard_vq_desc(vq, 1);
vhost_net_enable_vq(net, vq);
break;
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index d591f77961aa..31a156669a53 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -377,7 +377,10 @@ static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep)
{
struct vdpa_device *vdpa = v->vdpa;
const struct vdpa_config_ops *ops = vdpa->config;
+ struct vhost_dev *d = &v->vdev;
+ u64 actual_features;
u64 features;
+ int i;
/*
* It's not allowed to change the features after they have
@@ -392,6 +395,16 @@ static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep)
if (vdpa_set_features(vdpa, features))
return -EINVAL;
+ /* let the vqs know what has been configured */
+ actual_features = ops->get_driver_features(vdpa);
+ for (i = 0; i < d->nvqs; ++i) {
+ struct vhost_virtqueue *vq = d->vqs[i];
+
+ mutex_lock(&vq->mutex);
+ vq->acked_features = actual_features;
+ mutex_unlock(&vq->mutex);
+ }
+
return 0;
}
diff --git a/fs/Kconfig b/fs/Kconfig
index 2685a4d0d353..703a1cea0fc0 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -371,14 +371,7 @@ config NFS_V4_2_SSC_HELPER
source "net/sunrpc/Kconfig"
source "fs/ceph/Kconfig"
-source "fs/cifs/Kconfig"
-source "fs/ksmbd/Kconfig"
-
-config SMBFS_COMMON
- tristate
- default y if CIFS=y || SMB_SERVER=y
- default m if CIFS=m || SMB_SERVER=m
-
+source "fs/smb/Kconfig"
source "fs/coda/Kconfig"
source "fs/afs/Kconfig"
source "fs/9p/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index 80ab0154419e..9b7bcf6e54cd 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -94,9 +94,7 @@ obj-$(CONFIG_LOCKD) += lockd/
obj-$(CONFIG_NLS) += nls/
obj-y += unicode/
obj-$(CONFIG_SYSV_FS) += sysv/
-obj-$(CONFIG_SMBFS_COMMON) += smbfs_common/
-obj-$(CONFIG_CIFS) += cifs/
-obj-$(CONFIG_SMB_SERVER) += ksmbd/
+obj-$(CONFIG_SMBFS) += smb/
obj-$(CONFIG_HPFS_FS) += hpfs/
obj-$(CONFIG_NTFS_FS) += ntfs/
obj-$(CONFIG_NTFS3_FS) += ntfs3/
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index e71464c0e466..00be69ce7b90 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -6205,7 +6205,7 @@ static int log_delayed_deletions_incremental(struct btrfs_trans_handle *trans,
{
struct btrfs_root *log = inode->root->log_root;
const struct btrfs_delayed_item *curr;
- u64 last_range_start;
+ u64 last_range_start = 0;
u64 last_range_end = 0;
struct btrfs_key key;
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
deleted file mode 100644
index 3b7e3b9e4fd2..000000000000
--- a/fs/cifs/Kconfig
+++ /dev/null
@@ -1,203 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config CIFS
- tristate "SMB3 and CIFS support (advanced network filesystem)"
- depends on INET
- select NLS
- select CRYPTO
- select CRYPTO_MD5
- select CRYPTO_SHA256
- select CRYPTO_SHA512
- select CRYPTO_CMAC
- select CRYPTO_HMAC
- select CRYPTO_AEAD2
- select CRYPTO_CCM
- select CRYPTO_GCM
- select CRYPTO_ECB
- select CRYPTO_AES
- select KEYS
- select DNS_RESOLVER
- select ASN1
- select OID_REGISTRY
- help
- This is the client VFS module for the SMB3 family of NAS protocols,
- (including support for the most recent, most secure dialect SMB3.1.1)
- as well as for earlier dialects such as SMB2.1, SMB2 and the older
- Common Internet File System (CIFS) protocol. CIFS was the successor
- to the original dialect, the Server Message Block (SMB) protocol, the
- native file sharing mechanism for most early PC operating systems.
-
- The SMB3 protocol is supported by most modern operating systems
- and NAS appliances (e.g. Samba, Windows 10, Windows Server 2016,
- MacOS) and even in the cloud (e.g. Microsoft Azure).
- The older CIFS protocol was included in Windows NT4, 2000 and XP (and
- later) as well by Samba (which provides excellent CIFS and SMB3
- server support for Linux and many other operating systems). Use of
- dialects older than SMB2.1 is often discouraged on public networks.
- This module also provides limited support for OS/2 and Windows ME
- and similar very old servers.
-
- This module provides an advanced network file system client
- for mounting to SMB3 (and CIFS) compliant servers. It includes
- support for DFS (hierarchical name space), secure per-user
- session establishment via Kerberos or NTLM or NTLMv2, RDMA
- (smbdirect), advanced security features, per-share encryption,
- directory leases, safe distributed caching (oplock), optional packet
- signing, Unicode and other internationalization improvements.
-
- In general, the default dialects, SMB3 and later, enable better
- performance, security and features, than would be possible with CIFS.
- Note that when mounting to Samba, due to the CIFS POSIX extensions,
- CIFS mounts can provide slightly better POSIX compatibility
- than SMB3 mounts. SMB2/SMB3 mount options are also
- slightly simpler (compared to CIFS) due to protocol improvements.
-
- If you need to mount to Samba, Azure, Macs or Windows from this machine, say Y.
-
-config CIFS_STATS2
- bool "Extended statistics"
- depends on CIFS
- default y
- help
- Enabling this option will allow more detailed statistics on SMB
- request timing to be displayed in /proc/fs/cifs/DebugData and also
- allow optional logging of slow responses to dmesg (depending on the
- value of /proc/fs/cifs/cifsFYI). See Documentation/admin-guide/cifs/usage.rst
- for more details. These additional statistics may have a minor effect
- on performance and memory utilization.
-
- If unsure, say Y.
-
-config CIFS_ALLOW_INSECURE_LEGACY
- bool "Support legacy servers which use less secure dialects"
- depends on CIFS
- default y
- help
- Modern dialects, SMB2.1 and later (including SMB3 and 3.1.1), have
- additional security features, including protection against
- man-in-the-middle attacks and stronger crypto hashes, so the use
- of legacy dialects (SMB1/CIFS and SMB2.0) is discouraged.
-
- Disabling this option prevents users from using vers=1.0 or vers=2.0
- on mounts with cifs.ko
-
- If unsure, say Y.
-
-config CIFS_UPCALL
- bool "Kerberos/SPNEGO advanced session setup"
- depends on CIFS
- help
- Enables an upcall mechanism for CIFS which accesses userspace helper
- utilities to provide SPNEGO packaged (RFC 4178) Kerberos tickets
- which are needed to mount to certain secure servers (for which more
- secure Kerberos authentication is required). If unsure, say Y.
-
-config CIFS_XATTR
- bool "CIFS extended attributes"
- depends on CIFS
- help
- Extended attributes are name:value pairs associated with inodes by
- the kernel or by users (see the attr(5) manual page for details).
- CIFS maps the name of extended attributes beginning with the user
- namespace prefix to SMB/CIFS EAs. EAs are stored on Windows
- servers without the user namespace prefix, but their names are
- seen by Linux cifs clients prefaced by the user namespace prefix.
- The system namespace (used by some filesystems to store ACLs) is
- not supported at this time.
-
- If unsure, say Y.
-
-config CIFS_POSIX
- bool "CIFS POSIX Extensions"
- depends on CIFS && CIFS_ALLOW_INSECURE_LEGACY && CIFS_XATTR
- help
- Enabling this option will cause the cifs client to attempt to
- negotiate a newer dialect with servers, such as Samba 3.0.5
- or later, that optionally can handle more POSIX like (rather
- than Windows like) file behavior. It also enables
- support for POSIX ACLs (getfacl and setfacl) to servers
- (such as Samba 3.10 and later) which can negotiate
- CIFS POSIX ACL support. If unsure, say N.
-
-config CIFS_DEBUG
- bool "Enable CIFS debugging routines"
- default y
- depends on CIFS
- help
- Enabling this option adds helpful debugging messages to
- the cifs code which increases the size of the cifs module.
- If unsure, say Y.
-
-config CIFS_DEBUG2
- bool "Enable additional CIFS debugging routines"
- depends on CIFS_DEBUG
- help
- Enabling this option adds a few more debugging routines
- to the cifs code which slightly increases the size of
- the cifs module and can cause additional logging of debug
- messages in some error paths, slowing performance. This
- option can be turned off unless you are debugging
- cifs problems. If unsure, say N.
-
-config CIFS_DEBUG_DUMP_KEYS
- bool "Dump encryption keys for offline decryption (Unsafe)"
- depends on CIFS_DEBUG
- help
- Enabling this will dump the encryption and decryption keys
- used to communicate on an encrypted share connection on the
- console. This allows Wireshark to decrypt and dissect
- encrypted network captures. Enable this carefully.
- If unsure, say N.
-
-config CIFS_DFS_UPCALL
- bool "DFS feature support"
- depends on CIFS
- help
- Distributed File System (DFS) support is used to access shares
- transparently in an enterprise name space, even if the share
- moves to a different server. This feature also enables
- an upcall mechanism for CIFS which contacts userspace helper
- utilities to provide server name resolution (host names to
- IP addresses) which is needed in order to reconnect to
- servers if their addresses change or for implicit mounts of
- DFS junction points. If unsure, say Y.
-
-config CIFS_SWN_UPCALL
- bool "SWN feature support"
- depends on CIFS
- help
- The Service Witness Protocol (SWN) is used to get notifications
- from a highly available server of resource state changes. This
- feature enables an upcall mechanism for CIFS which contacts a
- userspace daemon to establish the DCE/RPC connection to retrieve
- the cluster available interfaces and resource change notifications.
- If unsure, say Y.
-
-config CIFS_NFSD_EXPORT
- bool "Allow nfsd to export CIFS file system"
- depends on CIFS && BROKEN
- help
- Allows NFS server to export a CIFS mounted share (nfsd over cifs)
-
-config CIFS_SMB_DIRECT
- bool "SMB Direct support"
- depends on CIFS=m && INFINIBAND && INFINIBAND_ADDR_TRANS || CIFS=y && INFINIBAND=y && INFINIBAND_ADDR_TRANS=y
- help
- Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1.
- SMB Direct allows transferring SMB packets over RDMA. If unsure,
- say Y.
-
-config CIFS_FSCACHE
- bool "Provide CIFS client caching support"
- depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
- help
- Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
- to be cached locally on disk through the general filesystem cache
- manager. If unsure, say N.
-
-config CIFS_ROOT
- bool "SMB root file system (Experimental)"
- depends on CIFS=y && IP_PNP
- help
- Enables root file system support over SMB protocol.
-
- Most people say N here.
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
deleted file mode 100644
index 7c9785973f49..000000000000
--- a/fs/cifs/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for Linux CIFS/SMB2/SMB3 VFS client
-#
-ccflags-y += -I$(src) # needed for trace events
-obj-$(CONFIG_CIFS) += cifs.o
-
-cifs-y := trace.o cifsfs.o cifs_debug.o connect.o dir.o file.o \
- inode.o link.o misc.o netmisc.o smbencrypt.o transport.o \
- cached_dir.o cifs_unicode.o nterr.o cifsencrypt.o \
- readdir.o ioctl.o sess.o export.o unc.o winucase.o \
- smb2ops.o smb2maperror.o smb2transport.o \
- smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o \
- dns_resolve.o cifs_spnego_negtokeninit.asn1.o asn1.o
-
-$(obj)/asn1.o: $(obj)/cifs_spnego_negtokeninit.asn1.h
-
-$(obj)/cifs_spnego_negtokeninit.asn1.o: $(obj)/cifs_spnego_negtokeninit.asn1.c $(obj)/cifs_spnego_negtokeninit.asn1.h
-
-cifs-$(CONFIG_CIFS_XATTR) += xattr.o
-
-cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
-
-cifs-$(CONFIG_CIFS_DFS_UPCALL) += cifs_dfs_ref.o dfs_cache.o
-
-cifs-$(CONFIG_CIFS_SWN_UPCALL) += netlink.o cifs_swn.o
-
-cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o
-
-cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o
-
-cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o
-
-cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
deleted file mode 100644
index b5724ef9f182..000000000000
--- a/fs/cifs/asn1.c
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/oid_registry.h>
-#include "cifsglob.h"
-#include "cifs_debug.h"
-#include "cifsproto.h"
-#include "cifs_spnego_negtokeninit.asn1.h"
-
-int
-decode_negTokenInit(unsigned char *security_blob, int length,
- struct TCP_Server_Info *server)
-{
- if (asn1_ber_decoder(&cifs_spnego_negtokeninit_decoder, server,
- security_blob, length) == 0)
- return 1;
- else
- return 0;
-}
-
-int cifs_gssapi_this_mech(void *context, size_t hdrlen,
- unsigned char tag, const void *value, size_t vlen)
-{
- enum OID oid;
-
- oid = look_up_OID(value, vlen);
- if (oid != OID_spnego) {
- char buf[50];
-
- sprint_oid(value, vlen, buf, sizeof(buf));
- cifs_dbg(FYI, "Error decoding negTokenInit header: unexpected OID %s\n",
- buf);
- return -EBADMSG;
- }
- return 0;
-}
-
-int cifs_neg_token_init_mech_type(void *context, size_t hdrlen,
- unsigned char tag,
- const void *value, size_t vlen)
-{
- struct TCP_Server_Info *server = context;
- enum OID oid;
-
- oid = look_up_OID(value, vlen);
- if (oid == OID_mskrb5)
- server->sec_mskerberos = true;
- else if (oid == OID_krb5u2u)
- server->sec_kerberosu2u = true;
- else if (oid == OID_krb5)
- server->sec_kerberos = true;
- else if (oid == OID_ntlmssp)
- server->sec_ntlmssp = true;
- else {
- char buf[50];
-
- sprint_oid(value, vlen, buf, sizeof(buf));
- cifs_dbg(FYI, "Decoding negTokenInit: unsupported OID %s\n",
- buf);
- }
- return 0;
-}
diff --git a/fs/cifs/cached_dir.c b/fs/cifs/cached_dir.c
deleted file mode 100644
index bfc964b36c72..000000000000
--- a/fs/cifs/cached_dir.c
+++ /dev/null
@@ -1,606 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Functions to handle the cached directory entries
- *
- * Copyright (c) 2022, Ronnie Sahlberg <lsahlber@redhat.com>
- */
-
-#include <linux/namei.h>
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "smb2proto.h"
-#include "cached_dir.h"
-
-static struct cached_fid *init_cached_dir(const char *path);
-static void free_cached_dir(struct cached_fid *cfid);
-static void smb2_close_cached_fid(struct kref *ref);
-
-static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
- const char *path,
- bool lookup_only)
-{
- struct cached_fid *cfid;
-
- spin_lock(&cfids->cfid_list_lock);
- list_for_each_entry(cfid, &cfids->entries, entry) {
- if (!strcmp(cfid->path, path)) {
- /*
- * If it doesn't have a lease it is either not yet
- * fully cached or it may be in the process of
- * being deleted due to a lease break.
- */
- if (!cfid->has_lease) {
- spin_unlock(&cfids->cfid_list_lock);
- return NULL;
- }
- kref_get(&cfid->refcount);
- spin_unlock(&cfids->cfid_list_lock);
- return cfid;
- }
- }
- if (lookup_only) {
- spin_unlock(&cfids->cfid_list_lock);
- return NULL;
- }
- if (cfids->num_entries >= MAX_CACHED_FIDS) {
- spin_unlock(&cfids->cfid_list_lock);
- return NULL;
- }
- cfid = init_cached_dir(path);
- if (cfid == NULL) {
- spin_unlock(&cfids->cfid_list_lock);
- return NULL;
- }
- cfid->cfids = cfids;
- cfids->num_entries++;
- list_add(&cfid->entry, &cfids->entries);
- cfid->on_list = true;
- kref_get(&cfid->refcount);
- spin_unlock(&cfids->cfid_list_lock);
- return cfid;
-}
-
-static struct dentry *
-path_to_dentry(struct cifs_sb_info *cifs_sb, const char *path)
-{
- struct dentry *dentry;
- const char *s, *p;
- char sep;
-
- sep = CIFS_DIR_SEP(cifs_sb);
- dentry = dget(cifs_sb->root);
- s = path;
-
- do {
- struct inode *dir = d_inode(dentry);
- struct dentry *child;
-
- if (!S_ISDIR(dir->i_mode)) {
- dput(dentry);
- dentry = ERR_PTR(-ENOTDIR);
- break;
- }
-
- /* skip separators */
- while (*s == sep)
- s++;
- if (!*s)
- break;
- p = s++;
- /* next separator */
- while (*s && *s != sep)
- s++;
-
- child = lookup_positive_unlocked(p, dentry, s - p);
- dput(dentry);
- dentry = child;
- } while (!IS_ERR(dentry));
- return dentry;
-}
-
-static const char *path_no_prefix(struct cifs_sb_info *cifs_sb,
- const char *path)
-{
- size_t len = 0;
-
- if (!*path)
- return path;
-
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
- cifs_sb->prepath) {
- len = strlen(cifs_sb->prepath) + 1;
- if (unlikely(len > strlen(path)))
- return ERR_PTR(-EINVAL);
- }
- return path + len;
-}
-
-/*
- * Open the and cache a directory handle.
- * If error then *cfid is not initialized.
- */
-int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
- const char *path,
- struct cifs_sb_info *cifs_sb,
- bool lookup_only, struct cached_fid **ret_cfid)
-{
- struct cifs_ses *ses;
- struct TCP_Server_Info *server;
- struct cifs_open_parms oparms;
- struct smb2_create_rsp *o_rsp = NULL;
- struct smb2_query_info_rsp *qi_rsp = NULL;
- int resp_buftype[2];
- struct smb_rqst rqst[2];
- struct kvec rsp_iov[2];
- struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
- struct kvec qi_iov[1];
- int rc, flags = 0;
- __le16 *utf16_path = NULL;
- u8 oplock = SMB2_OPLOCK_LEVEL_II;
- struct cifs_fid *pfid;
- struct dentry *dentry = NULL;
- struct cached_fid *cfid;
- struct cached_fids *cfids;
- const char *npath;
-
- if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache ||
- is_smb1_server(tcon->ses->server))
- return -EOPNOTSUPP;
-
- ses = tcon->ses;
- server = ses->server;
- cfids = tcon->cfids;
-
- if (!server->ops->new_lease_key)
- return -EIO;
-
- if (cifs_sb->root == NULL)
- return -ENOENT;
-
- utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
-
- cfid = find_or_create_cached_dir(cfids, path, lookup_only);
- if (cfid == NULL) {
- kfree(utf16_path);
- return -ENOENT;
- }
- /*
- * At this point we either have a lease already and we can just
- * return it. If not we are guaranteed to be the only thread accessing
- * this cfid.
- */
- if (cfid->has_lease) {
- *ret_cfid = cfid;
- kfree(utf16_path);
- return 0;
- }
-
- /*
- * Skip any prefix paths in @path as lookup_positive_unlocked() ends up
- * calling ->lookup() which already adds those through
- * build_path_from_dentry(). Also, do it earlier as we might reconnect
- * below when trying to send compounded request and then potentially
- * having a different prefix path (e.g. after DFS failover).
- */
- npath = path_no_prefix(cifs_sb, path);
- if (IS_ERR(npath)) {
- rc = PTR_ERR(npath);
- kfree(utf16_path);
- return rc;
- }
-
- /*
- * We do not hold the lock for the open because in case
- * SMB2_open needs to reconnect.
- * This is safe because no other thread will be able to get a ref
- * to the cfid until we have finished opening the file and (possibly)
- * acquired a lease.
- */
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- pfid = &cfid->fid;
- server->ops->new_lease_key(pfid);
-
- memset(rqst, 0, sizeof(rqst));
- resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER;
- memset(rsp_iov, 0, sizeof(rsp_iov));
-
- /* Open */
- memset(&open_iov, 0, sizeof(open_iov));
- rqst[0].rq_iov = open_iov;
- rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = path,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE),
- .desired_access = FILE_READ_ATTRIBUTES,
- .disposition = FILE_OPEN,
- .fid = pfid,
- };
-
- rc = SMB2_open_init(tcon, server,
- &rqst[0], &oplock, &oparms, utf16_path);
- if (rc)
- goto oshr_free;
- smb2_set_next_command(tcon, &rqst[0]);
-
- memset(&qi_iov, 0, sizeof(qi_iov));
- rqst[1].rq_iov = qi_iov;
- rqst[1].rq_nvec = 1;
-
- rc = SMB2_query_info_init(tcon, server,
- &rqst[1], COMPOUND_FID,
- COMPOUND_FID, FILE_ALL_INFORMATION,
- SMB2_O_INFO_FILE, 0,
- sizeof(struct smb2_file_all_info) +
- PATH_MAX * 2, 0, NULL);
- if (rc)
- goto oshr_free;
-
- smb2_set_related(&rqst[1]);
-
- rc = compound_send_recv(xid, ses, server,
- flags, 2, rqst,
- resp_buftype, rsp_iov);
- if (rc) {
- if (rc == -EREMCHG) {
- tcon->need_reconnect = true;
- pr_warn_once("server share %s deleted\n",
- tcon->tree_name);
- }
- goto oshr_free;
- }
- cfid->tcon = tcon;
- cfid->is_open = true;
-
- o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
- oparms.fid->persistent_fid = o_rsp->PersistentFileId;
- oparms.fid->volatile_fid = o_rsp->VolatileFileId;
-#ifdef CONFIG_CIFS_DEBUG2
- oparms.fid->mid = le64_to_cpu(o_rsp->hdr.MessageId);
-#endif /* CIFS_DEBUG2 */
-
- if (o_rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
- goto oshr_free;
-
- smb2_parse_contexts(server, o_rsp,
- &oparms.fid->epoch,
- oparms.fid->lease_key, &oplock,
- NULL, NULL);
- if (!(oplock & SMB2_LEASE_READ_CACHING_HE))
- goto oshr_free;
- qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
- if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info))
- goto oshr_free;
- if (!smb2_validate_and_copy_iov(
- le16_to_cpu(qi_rsp->OutputBufferOffset),
- sizeof(struct smb2_file_all_info),
- &rsp_iov[1], sizeof(struct smb2_file_all_info),
- (char *)&cfid->file_all_info))
- cfid->file_all_info_is_valid = true;
-
- if (!npath[0])
- dentry = dget(cifs_sb->root);
- else {
- dentry = path_to_dentry(cifs_sb, npath);
- if (IS_ERR(dentry)) {
- rc = -ENOENT;
- goto oshr_free;
- }
- }
- cfid->dentry = dentry;
- cfid->time = jiffies;
- cfid->has_lease = true;
-
-oshr_free:
- kfree(utf16_path);
- SMB2_open_free(&rqst[0]);
- SMB2_query_info_free(&rqst[1]);
- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- spin_lock(&cfids->cfid_list_lock);
- if (rc && !cfid->has_lease) {
- if (cfid->on_list) {
- list_del(&cfid->entry);
- cfid->on_list = false;
- cfids->num_entries--;
- }
- rc = -ENOENT;
- }
- spin_unlock(&cfids->cfid_list_lock);
- if (!rc && !cfid->has_lease) {
- /*
- * We are guaranteed to have two references at this point.
- * One for the caller and one for a potential lease.
- * Release the Lease-ref so that the directory will be closed
- * when the caller closes the cached handle.
- */
- kref_put(&cfid->refcount, smb2_close_cached_fid);
- }
- if (rc) {
- if (cfid->is_open)
- SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
- cfid->fid.volatile_fid);
- free_cached_dir(cfid);
- cfid = NULL;
- }
-
- if (rc == 0) {
- *ret_cfid = cfid;
- atomic_inc(&tcon->num_remote_opens);
- }
-
- return rc;
-}
-
-int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
- struct dentry *dentry,
- struct cached_fid **ret_cfid)
-{
- struct cached_fid *cfid;
- struct cached_fids *cfids = tcon->cfids;
-
- if (cfids == NULL)
- return -ENOENT;
-
- spin_lock(&cfids->cfid_list_lock);
- list_for_each_entry(cfid, &cfids->entries, entry) {
- if (dentry && cfid->dentry == dentry) {
- cifs_dbg(FYI, "found a cached root file handle by dentry\n");
- kref_get(&cfid->refcount);
- *ret_cfid = cfid;
- spin_unlock(&cfids->cfid_list_lock);
- return 0;
- }
- }
- spin_unlock(&cfids->cfid_list_lock);
- return -ENOENT;
-}
-
-static void
-smb2_close_cached_fid(struct kref *ref)
-{
- struct cached_fid *cfid = container_of(ref, struct cached_fid,
- refcount);
-
- spin_lock(&cfid->cfids->cfid_list_lock);
- if (cfid->on_list) {
- list_del(&cfid->entry);
- cfid->on_list = false;
- cfid->cfids->num_entries--;
- }
- spin_unlock(&cfid->cfids->cfid_list_lock);
-
- dput(cfid->dentry);
- cfid->dentry = NULL;
-
- if (cfid->is_open) {
- SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
- cfid->fid.volatile_fid);
- atomic_dec(&cfid->tcon->num_remote_opens);
- }
-
- free_cached_dir(cfid);
-}
-
-void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon,
- const char *name, struct cifs_sb_info *cifs_sb)
-{
- struct cached_fid *cfid = NULL;
- int rc;
-
- rc = open_cached_dir(xid, tcon, name, cifs_sb, true, &cfid);
- if (rc) {
- cifs_dbg(FYI, "no cached dir found for rmdir(%s)\n", name);
- return;
- }
- spin_lock(&cfid->cfids->cfid_list_lock);
- if (cfid->has_lease) {
- cfid->has_lease = false;
- kref_put(&cfid->refcount, smb2_close_cached_fid);
- }
- spin_unlock(&cfid->cfids->cfid_list_lock);
- close_cached_dir(cfid);
-}
-
-
-void close_cached_dir(struct cached_fid *cfid)
-{
- kref_put(&cfid->refcount, smb2_close_cached_fid);
-}
-
-/*
- * Called from cifs_kill_sb when we unmount a share
- */
-void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
-{
- struct rb_root *root = &cifs_sb->tlink_tree;
- struct rb_node *node;
- struct cached_fid *cfid;
- struct cifs_tcon *tcon;
- struct tcon_link *tlink;
- struct cached_fids *cfids;
-
- for (node = rb_first(root); node; node = rb_next(node)) {
- tlink = rb_entry(node, struct tcon_link, tl_rbnode);
- tcon = tlink_tcon(tlink);
- if (IS_ERR(tcon))
- continue;
- cfids = tcon->cfids;
- if (cfids == NULL)
- continue;
- list_for_each_entry(cfid, &cfids->entries, entry) {
- dput(cfid->dentry);
- cfid->dentry = NULL;
- }
- }
-}
-
-/*
- * Invalidate all cached dirs when a TCON has been reset
- * due to a session loss.
- */
-void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
-{
- struct cached_fids *cfids = tcon->cfids;
- struct cached_fid *cfid, *q;
- LIST_HEAD(entry);
-
- spin_lock(&cfids->cfid_list_lock);
- list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
- list_move(&cfid->entry, &entry);
- cfids->num_entries--;
- cfid->is_open = false;
- cfid->on_list = false;
- /* To prevent race with smb2_cached_lease_break() */
- kref_get(&cfid->refcount);
- }
- spin_unlock(&cfids->cfid_list_lock);
-
- list_for_each_entry_safe(cfid, q, &entry, entry) {
- list_del(&cfid->entry);
- cancel_work_sync(&cfid->lease_break);
- if (cfid->has_lease) {
- /*
- * We lease was never cancelled from the server so we
- * need to drop the reference.
- */
- spin_lock(&cfids->cfid_list_lock);
- cfid->has_lease = false;
- spin_unlock(&cfids->cfid_list_lock);
- kref_put(&cfid->refcount, smb2_close_cached_fid);
- }
- /* Drop the extra reference opened above*/
- kref_put(&cfid->refcount, smb2_close_cached_fid);
- }
-}
-
-static void
-smb2_cached_lease_break(struct work_struct *work)
-{
- struct cached_fid *cfid = container_of(work,
- struct cached_fid, lease_break);
-
- spin_lock(&cfid->cfids->cfid_list_lock);
- cfid->has_lease = false;
- spin_unlock(&cfid->cfids->cfid_list_lock);
- kref_put(&cfid->refcount, smb2_close_cached_fid);
-}
-
-int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
-{
- struct cached_fids *cfids = tcon->cfids;
- struct cached_fid *cfid;
-
- if (cfids == NULL)
- return false;
-
- spin_lock(&cfids->cfid_list_lock);
- list_for_each_entry(cfid, &cfids->entries, entry) {
- if (cfid->has_lease &&
- !memcmp(lease_key,
- cfid->fid.lease_key,
- SMB2_LEASE_KEY_SIZE)) {
- cfid->time = 0;
- /*
- * We found a lease remove it from the list
- * so no threads can access it.
- */
- list_del(&cfid->entry);
- cfid->on_list = false;
- cfids->num_entries--;
-
- queue_work(cifsiod_wq,
- &cfid->lease_break);
- spin_unlock(&cfids->cfid_list_lock);
- return true;
- }
- }
- spin_unlock(&cfids->cfid_list_lock);
- return false;
-}
-
-static struct cached_fid *init_cached_dir(const char *path)
-{
- struct cached_fid *cfid;
-
- cfid = kzalloc(sizeof(*cfid), GFP_ATOMIC);
- if (!cfid)
- return NULL;
- cfid->path = kstrdup(path, GFP_ATOMIC);
- if (!cfid->path) {
- kfree(cfid);
- return NULL;
- }
-
- INIT_WORK(&cfid->lease_break, smb2_cached_lease_break);
- INIT_LIST_HEAD(&cfid->entry);
- INIT_LIST_HEAD(&cfid->dirents.entries);
- mutex_init(&cfid->dirents.de_mutex);
- spin_lock_init(&cfid->fid_lock);
- kref_init(&cfid->refcount);
- return cfid;
-}
-
-static void free_cached_dir(struct cached_fid *cfid)
-{
- struct cached_dirent *dirent, *q;
-
- dput(cfid->dentry);
- cfid->dentry = NULL;
-
- /*
- * Delete all cached dirent names
- */
- list_for_each_entry_safe(dirent, q, &cfid->dirents.entries, entry) {
- list_del(&dirent->entry);
- kfree(dirent->name);
- kfree(dirent);
- }
-
- kfree(cfid->path);
- cfid->path = NULL;
- kfree(cfid);
-}
-
-struct cached_fids *init_cached_dirs(void)
-{
- struct cached_fids *cfids;
-
- cfids = kzalloc(sizeof(*cfids), GFP_KERNEL);
- if (!cfids)
- return NULL;
- spin_lock_init(&cfids->cfid_list_lock);
- INIT_LIST_HEAD(&cfids->entries);
- return cfids;
-}
-
-/*
- * Called from tconInfoFree when we are tearing down the tcon.
- * There are no active users or open files/directories at this point.
- */
-void free_cached_dirs(struct cached_fids *cfids)
-{
- struct cached_fid *cfid, *q;
- LIST_HEAD(entry);
-
- spin_lock(&cfids->cfid_list_lock);
- list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
- cfid->on_list = false;
- cfid->is_open = false;
- list_move(&cfid->entry, &entry);
- }
- spin_unlock(&cfids->cfid_list_lock);
-
- list_for_each_entry_safe(cfid, q, &entry, entry) {
- list_del(&cfid->entry);
- free_cached_dir(cfid);
- }
-
- kfree(cfids);
-}
diff --git a/fs/cifs/cached_dir.h b/fs/cifs/cached_dir.h
deleted file mode 100644
index 2f4e764c9ca9..000000000000
--- a/fs/cifs/cached_dir.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Functions to handle the cached directory entries
- *
- * Copyright (c) 2022, Ronnie Sahlberg <lsahlber@redhat.com>
- */
-
-#ifndef _CACHED_DIR_H
-#define _CACHED_DIR_H
-
-
-struct cached_dirent {
- struct list_head entry;
- char *name;
- int namelen;
- loff_t pos;
-
- struct cifs_fattr fattr;
-};
-
-struct cached_dirents {
- bool is_valid:1;
- bool is_failed:1;
- struct dir_context *ctx; /*
- * Only used to make sure we only take entries
- * from a single context. Never dereferenced.
- */
- struct mutex de_mutex;
- int pos; /* Expected ctx->pos */
- struct list_head entries;
-};
-
-struct cached_fid {
- struct list_head entry;
- struct cached_fids *cfids;
- const char *path;
- bool has_lease:1;
- bool is_open:1;
- bool on_list:1;
- bool file_all_info_is_valid:1;
- unsigned long time; /* jiffies of when lease was taken */
- struct kref refcount;
- struct cifs_fid fid;
- spinlock_t fid_lock;
- struct cifs_tcon *tcon;
- struct dentry *dentry;
- struct work_struct lease_break;
- struct smb2_file_all_info file_all_info;
- struct cached_dirents dirents;
-};
-
-#define MAX_CACHED_FIDS 16
-struct cached_fids {
- /* Must be held when:
- * - accessing the cfids->entries list
- */
- spinlock_t cfid_list_lock;
- int num_entries;
- struct list_head entries;
-};
-
-extern struct cached_fids *init_cached_dirs(void);
-extern void free_cached_dirs(struct cached_fids *cfids);
-extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
- const char *path,
- struct cifs_sb_info *cifs_sb,
- bool lookup_only, struct cached_fid **cfid);
-extern int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
- struct dentry *dentry,
- struct cached_fid **cfid);
-extern void close_cached_dir(struct cached_fid *cfid);
-extern void drop_cached_dir_by_name(const unsigned int xid,
- struct cifs_tcon *tcon,
- const char *name,
- struct cifs_sb_info *cifs_sb);
-extern void close_all_cached_dirs(struct cifs_sb_info *cifs_sb);
-extern void invalidate_all_cached_dirs(struct cifs_tcon *tcon);
-extern int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]);
-
-#endif /* _CACHED_DIR_H */
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
deleted file mode 100644
index e41154ad96af..000000000000
--- a/fs/cifs/cifs_debug.c
+++ /dev/null
@@ -1,1067 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * Copyright (C) International Business Machines Corp., 2000,2005
- *
- * Modified by Steve French (sfrench@us.ibm.com)
- */
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/uaccess.h>
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifsfs.h"
-#include "fs_context.h"
-#ifdef CONFIG_CIFS_DFS_UPCALL
-#include "dfs_cache.h"
-#endif
-#ifdef CONFIG_CIFS_SMB_DIRECT
-#include "smbdirect.h"
-#endif
-#include "cifs_swn.h"
-
-void
-cifs_dump_mem(char *label, void *data, int length)
-{
- pr_debug("%s: dump of %d bytes of data at 0x%p\n", label, length, data);
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
- data, length, true);
-}
-
-void cifs_dump_detail(void *buf, struct TCP_Server_Info *server)
-{
-#ifdef CONFIG_CIFS_DEBUG2
- struct smb_hdr *smb = buf;
-
- cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n",
- smb->Command, smb->Status.CifsError,
- smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
- cifs_dbg(VFS, "smb buf %p len %u\n", smb,
- server->ops->calc_smb_size(smb));
-#endif /* CONFIG_CIFS_DEBUG2 */
-}
-
-void cifs_dump_mids(struct TCP_Server_Info *server)
-{
-#ifdef CONFIG_CIFS_DEBUG2
- struct mid_q_entry *mid_entry;
-
- if (server == NULL)
- return;
-
- cifs_dbg(VFS, "Dump pending requests:\n");
- spin_lock(&server->mid_lock);
- list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
- cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n",
- mid_entry->mid_state,
- le16_to_cpu(mid_entry->command),
- mid_entry->pid,
- mid_entry->callback_data,
- mid_entry->mid);
-#ifdef CONFIG_CIFS_STATS2
- cifs_dbg(VFS, "IsLarge: %d buf: %p time rcv: %ld now: %ld\n",
- mid_entry->large_buf,
- mid_entry->resp_buf,
- mid_entry->when_received,
- jiffies);
-#endif /* STATS2 */
- cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
- mid_entry->multiRsp, mid_entry->multiEnd);
- if (mid_entry->resp_buf) {
- cifs_dump_detail(mid_entry->resp_buf, server);
- cifs_dump_mem("existing buf: ",
- mid_entry->resp_buf, 62);
- }
- }
- spin_unlock(&server->mid_lock);
-#endif /* CONFIG_CIFS_DEBUG2 */
-}
-
-#ifdef CONFIG_PROC_FS
-static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
-{
- __u32 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
-
- seq_printf(m, "%s Mounts: %d ", tcon->tree_name, tcon->tc_count);
- if (tcon->nativeFileSystem)
- seq_printf(m, "Type: %s ", tcon->nativeFileSystem);
- seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d Status: %d",
- le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
- le32_to_cpu(tcon->fsAttrInfo.Attributes),
- le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
- tcon->status);
- if (dev_type == FILE_DEVICE_DISK)
- seq_puts(m, " type: DISK ");
- else if (dev_type == FILE_DEVICE_CD_ROM)
- seq_puts(m, " type: CDROM ");
- else
- seq_printf(m, " type: %d ", dev_type);
-
- seq_printf(m, "Serial Number: 0x%x", tcon->vol_serial_number);
-
- if ((tcon->seal) ||
- (tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
- (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
- seq_printf(m, " Encrypted");
- if (tcon->nocase)
- seq_printf(m, " nocase");
- if (tcon->unix_ext)
- seq_printf(m, " POSIX Extensions");
- if (tcon->ses->server->ops->dump_share_caps)
- tcon->ses->server->ops->dump_share_caps(m, tcon);
- if (tcon->use_witness)
- seq_puts(m, " Witness");
- if (tcon->broken_sparse_sup)
- seq_puts(m, " nosparse");
- if (tcon->need_reconnect)
- seq_puts(m, "\tDISCONNECTED ");
- seq_putc(m, '\n');
-}
-
-static void
-cifs_dump_channel(struct seq_file *m, int i, struct cifs_chan *chan)
-{
- struct TCP_Server_Info *server = chan->server;
-
- seq_printf(m, "\n\n\t\tChannel: %d ConnectionId: 0x%llx"
- "\n\t\tNumber of credits: %d Dialect 0x%x"
- "\n\t\tTCP status: %d Instance: %d"
- "\n\t\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d"
- "\n\t\tIn Send: %d In MaxReq Wait: %d",
- i+1, server->conn_id,
- server->credits,
- server->dialect,
- server->tcpStatus,
- server->reconnect_instance,
- server->srv_count,
- server->sec_mode,
- in_flight(server),
- atomic_read(&server->in_send),
- atomic_read(&server->num_waiters));
-}
-
-static void
-cifs_dump_iface(struct seq_file *m, struct cifs_server_iface *iface)
-{
- struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
- struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
-
- seq_printf(m, "\tSpeed: %zu bps\n", iface->speed);
- seq_puts(m, "\t\tCapabilities: ");
- if (iface->rdma_capable)
- seq_puts(m, "rdma ");
- if (iface->rss_capable)
- seq_puts(m, "rss ");
- seq_putc(m, '\n');
- if (iface->sockaddr.ss_family == AF_INET)
- seq_printf(m, "\t\tIPv4: %pI4\n", &ipv4->sin_addr);
- else if (iface->sockaddr.ss_family == AF_INET6)
- seq_printf(m, "\t\tIPv6: %pI6\n", &ipv6->sin6_addr);
- if (!iface->is_active)
- seq_puts(m, "\t\t[for-cleanup]\n");
-}
-
-static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
-{
- struct TCP_Server_Info *server;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
- struct cifsFileInfo *cfile;
-
- seq_puts(m, "# Version:1\n");
- seq_puts(m, "# Format:\n");
- seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>");
-#ifdef CONFIG_CIFS_DEBUG2
- seq_printf(m, " <filename> <mid>\n");
-#else
- seq_printf(m, " <filename>\n");
-#endif /* CIFS_DEBUG2 */
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
- list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- spin_lock(&tcon->open_file_lock);
- list_for_each_entry(cfile, &tcon->openFileList, tlist) {
- seq_printf(m,
- "0x%x 0x%llx 0x%llx 0x%x %d %d %d %pd",
- tcon->tid,
- ses->Suid,
- cfile->fid.persistent_fid,
- cfile->f_flags,
- cfile->count,
- cfile->pid,
- from_kuid(&init_user_ns, cfile->uid),
- cfile->dentry);
-#ifdef CONFIG_CIFS_DEBUG2
- seq_printf(m, " %llu\n", cfile->fid.mid);
-#else
- seq_printf(m, "\n");
-#endif /* CIFS_DEBUG2 */
- }
- spin_unlock(&tcon->open_file_lock);
- }
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
- seq_putc(m, '\n');
- return 0;
-}
-
-static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
-{
- struct mid_q_entry *mid_entry;
- struct TCP_Server_Info *server;
- struct TCP_Server_Info *chan_server;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
- struct cifs_server_iface *iface;
- int c, i, j;
-
- seq_puts(m,
- "Display Internal CIFS Data Structures for Debugging\n"
- "---------------------------------------------------\n");
- seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
- seq_printf(m, "Features:");
-#ifdef CONFIG_CIFS_DFS_UPCALL
- seq_printf(m, " DFS");
-#endif
-#ifdef CONFIG_CIFS_FSCACHE
- seq_printf(m, ",FSCACHE");
-#endif
-#ifdef CONFIG_CIFS_SMB_DIRECT
- seq_printf(m, ",SMB_DIRECT");
-#endif
-#ifdef CONFIG_CIFS_STATS2
- seq_printf(m, ",STATS2");
-#else
- seq_printf(m, ",STATS");
-#endif
-#ifdef CONFIG_CIFS_DEBUG2
- seq_printf(m, ",DEBUG2");
-#elif defined(CONFIG_CIFS_DEBUG)
- seq_printf(m, ",DEBUG");
-#endif
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- seq_printf(m, ",ALLOW_INSECURE_LEGACY");
-#endif
-#ifdef CONFIG_CIFS_POSIX
- seq_printf(m, ",CIFS_POSIX");
-#endif
-#ifdef CONFIG_CIFS_UPCALL
- seq_printf(m, ",UPCALL(SPNEGO)");
-#endif
-#ifdef CONFIG_CIFS_XATTR
- seq_printf(m, ",XATTR");
-#endif
- seq_printf(m, ",ACL");
-#ifdef CONFIG_CIFS_SWN_UPCALL
- seq_puts(m, ",WITNESS");
-#endif
- seq_putc(m, '\n');
- seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
- seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
-
- seq_printf(m, "\nServers: ");
-
- c = 0;
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
- /* channel info will be printed as a part of sessions below */
- if (CIFS_SERVER_IS_CHAN(server))
- continue;
-
- c++;
- seq_printf(m, "\n%d) ConnectionId: 0x%llx ",
- c, server->conn_id);
-
- spin_lock(&server->srv_lock);
- if (server->hostname)
- seq_printf(m, "Hostname: %s ", server->hostname);
- spin_unlock(&server->srv_lock);
-#ifdef CONFIG_CIFS_SMB_DIRECT
- if (!server->rdma)
- goto skip_rdma;
-
- if (!server->smbd_conn) {
- seq_printf(m, "\nSMBDirect transport not available");
- goto skip_rdma;
- }
-
- seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
- "transport status: %x",
- server->smbd_conn->protocol,
- server->smbd_conn->transport_status);
- seq_printf(m, "\nConn receive_credit_max: %x "
- "send_credit_target: %x max_send_size: %x",
- server->smbd_conn->receive_credit_max,
- server->smbd_conn->send_credit_target,
- server->smbd_conn->max_send_size);
- seq_printf(m, "\nConn max_fragmented_recv_size: %x "
- "max_fragmented_send_size: %x max_receive_size:%x",
- server->smbd_conn->max_fragmented_recv_size,
- server->smbd_conn->max_fragmented_send_size,
- server->smbd_conn->max_receive_size);
- seq_printf(m, "\nConn keep_alive_interval: %x "
- "max_readwrite_size: %x rdma_readwrite_threshold: %x",
- server->smbd_conn->keep_alive_interval,
- server->smbd_conn->max_readwrite_size,
- server->smbd_conn->rdma_readwrite_threshold);
- seq_printf(m, "\nDebug count_get_receive_buffer: %x "
- "count_put_receive_buffer: %x count_send_empty: %x",
- server->smbd_conn->count_get_receive_buffer,
- server->smbd_conn->count_put_receive_buffer,
- server->smbd_conn->count_send_empty);
- seq_printf(m, "\nRead Queue count_reassembly_queue: %x "
- "count_enqueue_reassembly_queue: %x "
- "count_dequeue_reassembly_queue: %x "
- "fragment_reassembly_remaining: %x "
- "reassembly_data_length: %x "
- "reassembly_queue_length: %x",
- server->smbd_conn->count_reassembly_queue,
- server->smbd_conn->count_enqueue_reassembly_queue,
- server->smbd_conn->count_dequeue_reassembly_queue,
- server->smbd_conn->fragment_reassembly_remaining,
- server->smbd_conn->reassembly_data_length,
- server->smbd_conn->reassembly_queue_length);
- seq_printf(m, "\nCurrent Credits send_credits: %x "
- "receive_credits: %x receive_credit_target: %x",
- atomic_read(&server->smbd_conn->send_credits),
- atomic_read(&server->smbd_conn->receive_credits),
- server->smbd_conn->receive_credit_target);
- seq_printf(m, "\nPending send_pending: %x ",
- atomic_read(&server->smbd_conn->send_pending));
- seq_printf(m, "\nReceive buffers count_receive_queue: %x "
- "count_empty_packet_queue: %x",
- server->smbd_conn->count_receive_queue,
- server->smbd_conn->count_empty_packet_queue);
- seq_printf(m, "\nMR responder_resources: %x "
- "max_frmr_depth: %x mr_type: %x",
- server->smbd_conn->responder_resources,
- server->smbd_conn->max_frmr_depth,
- server->smbd_conn->mr_type);
- seq_printf(m, "\nMR mr_ready_count: %x mr_used_count: %x",
- atomic_read(&server->smbd_conn->mr_ready_count),
- atomic_read(&server->smbd_conn->mr_used_count));
-skip_rdma:
-#endif
- seq_printf(m, "\nNumber of credits: %d Dialect 0x%x",
- server->credits, server->dialect);
- if (server->compress_algorithm == SMB3_COMPRESS_LZNT1)
- seq_printf(m, " COMPRESS_LZNT1");
- else if (server->compress_algorithm == SMB3_COMPRESS_LZ77)
- seq_printf(m, " COMPRESS_LZ77");
- else if (server->compress_algorithm == SMB3_COMPRESS_LZ77_HUFF)
- seq_printf(m, " COMPRESS_LZ77_HUFF");
- if (server->sign)
- seq_printf(m, " signed");
- if (server->posix_ext_supported)
- seq_printf(m, " posix");
- if (server->nosharesock)
- seq_printf(m, " nosharesock");
-
- if (server->rdma)
- seq_printf(m, "\nRDMA ");
- seq_printf(m, "\nTCP status: %d Instance: %d"
- "\nLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
- server->tcpStatus,
- server->reconnect_instance,
- server->srv_count,
- server->sec_mode, in_flight(server));
-
- seq_printf(m, "\nIn Send: %d In MaxReq Wait: %d",
- atomic_read(&server->in_send),
- atomic_read(&server->num_waiters));
-
- seq_printf(m, "\n\n\tSessions: ");
- i = 0;
- list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
- i++;
- if ((ses->serverDomain == NULL) ||
- (ses->serverOS == NULL) ||
- (ses->serverNOS == NULL)) {
- seq_printf(m, "\n\t%d) Address: %s Uses: %d Capability: 0x%x\tSession Status: %d ",
- i, ses->ip_addr, ses->ses_count,
- ses->capabilities, ses->ses_status);
- if (ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
- seq_printf(m, "Guest ");
- else if (ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
- seq_printf(m, "Anonymous ");
- } else {
- seq_printf(m,
- "\n\t%d) Name: %s Domain: %s Uses: %d OS: %s "
- "\n\tNOS: %s\tCapability: 0x%x"
- "\n\tSMB session status: %d ",
- i, ses->ip_addr, ses->serverDomain,
- ses->ses_count, ses->serverOS, ses->serverNOS,
- ses->capabilities, ses->ses_status);
- }
-
- seq_printf(m, "\n\tSecurity type: %s ",
- get_security_type_str(server->ops->select_sectype(server, ses->sectype)));
-
- /* dump session id helpful for use with network trace */
- seq_printf(m, " SessionId: 0x%llx", ses->Suid);
- if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
- seq_puts(m, " encrypted");
- if (ses->sign)
- seq_puts(m, " signed");
-
- seq_printf(m, "\n\tUser: %d Cred User: %d",
- from_kuid(&init_user_ns, ses->linux_uid),
- from_kuid(&init_user_ns, ses->cred_uid));
-
- spin_lock(&ses->chan_lock);
- if (CIFS_CHAN_NEEDS_RECONNECT(ses, 0))
- seq_puts(m, "\tPrimary channel: DISCONNECTED ");
- if (CIFS_CHAN_IN_RECONNECT(ses, 0))
- seq_puts(m, "\t[RECONNECTING] ");
-
- if (ses->chan_count > 1) {
- seq_printf(m, "\n\n\tExtra Channels: %zu ",
- ses->chan_count-1);
- for (j = 1; j < ses->chan_count; j++) {
- cifs_dump_channel(m, j, &ses->chans[j]);
- if (CIFS_CHAN_NEEDS_RECONNECT(ses, j))
- seq_puts(m, "\tDISCONNECTED ");
- if (CIFS_CHAN_IN_RECONNECT(ses, j))
- seq_puts(m, "\t[RECONNECTING] ");
- }
- }
- spin_unlock(&ses->chan_lock);
-
- seq_puts(m, "\n\n\tShares: ");
- j = 0;
-
- seq_printf(m, "\n\t%d) IPC: ", j);
- if (ses->tcon_ipc)
- cifs_debug_tcon(m, ses->tcon_ipc);
- else
- seq_puts(m, "none\n");
-
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- ++j;
- seq_printf(m, "\n\t%d) ", j);
- cifs_debug_tcon(m, tcon);
- }
-
- spin_lock(&ses->iface_lock);
- if (ses->iface_count)
- seq_printf(m, "\n\n\tServer interfaces: %zu",
- ses->iface_count);
- j = 0;
- list_for_each_entry(iface, &ses->iface_list,
- iface_head) {
- seq_printf(m, "\n\t%d)", ++j);
- cifs_dump_iface(m, iface);
- if (is_ses_using_iface(ses, iface))
- seq_puts(m, "\t\t[CONNECTED]\n");
- }
- spin_unlock(&ses->iface_lock);
-
- seq_puts(m, "\n\n\tMIDs: ");
- spin_lock(&ses->chan_lock);
- for (j = 0; j < ses->chan_count; j++) {
- chan_server = ses->chans[j].server;
- if (!chan_server)
- continue;
-
- if (list_empty(&chan_server->pending_mid_q))
- continue;
-
- seq_printf(m, "\n\tServer ConnectionId: 0x%llx",
- chan_server->conn_id);
- spin_lock(&chan_server->mid_lock);
- list_for_each_entry(mid_entry, &chan_server->pending_mid_q, qhead) {
- seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu",
- mid_entry->mid_state,
- le16_to_cpu(mid_entry->command),
- mid_entry->pid,
- mid_entry->callback_data,
- mid_entry->mid);
- }
- spin_unlock(&chan_server->mid_lock);
- }
- spin_unlock(&ses->chan_lock);
- seq_puts(m, "\n--\n");
- }
- if (i == 0)
- seq_printf(m, "\n\t\t[NONE]");
- }
- if (c == 0)
- seq_printf(m, "\n\t[NONE]");
-
- spin_unlock(&cifs_tcp_ses_lock);
- seq_putc(m, '\n');
- cifs_swn_dump(m);
-
- /* BB add code to dump additional info such as TCP session info now */
- return 0;
-}
-
-static ssize_t cifs_stats_proc_write(struct file *file,
- const char __user *buffer, size_t count, loff_t *ppos)
-{
- bool bv;
- int rc;
- struct TCP_Server_Info *server;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
-
- rc = kstrtobool_from_user(buffer, count, &bv);
- if (rc == 0) {
-#ifdef CONFIG_CIFS_STATS2
- int i;
-
- atomic_set(&total_buf_alloc_count, 0);
- atomic_set(&total_small_buf_alloc_count, 0);
-#endif /* CONFIG_CIFS_STATS2 */
- atomic_set(&tcpSesReconnectCount, 0);
- atomic_set(&tconInfoReconnectCount, 0);
-
- spin_lock(&GlobalMid_Lock);
- GlobalMaxActiveXid = 0;
- GlobalCurrentXid = 0;
- spin_unlock(&GlobalMid_Lock);
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
- server->max_in_flight = 0;
-#ifdef CONFIG_CIFS_STATS2
- for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
- atomic_set(&server->num_cmds[i], 0);
- atomic_set(&server->smb2slowcmd[i], 0);
- server->time_per_cmd[i] = 0;
- server->slowest_cmd[i] = 0;
- server->fastest_cmd[0] = 0;
- }
-#endif /* CONFIG_CIFS_STATS2 */
- list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- atomic_set(&tcon->num_smbs_sent, 0);
- spin_lock(&tcon->stat_lock);
- tcon->bytes_read = 0;
- tcon->bytes_written = 0;
- spin_unlock(&tcon->stat_lock);
- if (server->ops->clear_stats)
- server->ops->clear_stats(tcon);
- }
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
- } else {
- return rc;
- }
-
- return count;
-}
-
-static int cifs_stats_proc_show(struct seq_file *m, void *v)
-{
- int i;
-#ifdef CONFIG_CIFS_STATS2
- int j;
-#endif /* STATS2 */
- struct TCP_Server_Info *server;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
-
- seq_printf(m, "Resources in use\nCIFS Session: %d\n",
- sesInfoAllocCount.counter);
- seq_printf(m, "Share (unique mount targets): %d\n",
- tconInfoAllocCount.counter);
- seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n",
- buf_alloc_count.counter,
- cifs_min_rcv + tcpSesAllocCount.counter);
- seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
- small_buf_alloc_count.counter, cifs_min_small);
-#ifdef CONFIG_CIFS_STATS2
- seq_printf(m, "Total Large %d Small %d Allocations\n",
- atomic_read(&total_buf_alloc_count),
- atomic_read(&total_small_buf_alloc_count));
-#endif /* CONFIG_CIFS_STATS2 */
-
- seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&mid_count));
- seq_printf(m,
- "\n%d session %d share reconnects\n",
- tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
-
- seq_printf(m,
- "Total vfs operations: %d maximum at one time: %d\n",
- GlobalCurrentXid, GlobalMaxActiveXid);
-
- i = 0;
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
- seq_printf(m, "\nMax requests in flight: %d", server->max_in_flight);
-#ifdef CONFIG_CIFS_STATS2
- seq_puts(m, "\nTotal time spent processing by command. Time ");
- seq_printf(m, "units are jiffies (%d per second)\n", HZ);
- seq_puts(m, " SMB3 CMD\tNumber\tTotal Time\tFastest\tSlowest\n");
- seq_puts(m, " --------\t------\t----------\t-------\t-------\n");
- for (j = 0; j < NUMBER_OF_SMB2_COMMANDS; j++)
- seq_printf(m, " %d\t\t%d\t%llu\t\t%u\t%u\n", j,
- atomic_read(&server->num_cmds[j]),
- server->time_per_cmd[j],
- server->fastest_cmd[j],
- server->slowest_cmd[j]);
- for (j = 0; j < NUMBER_OF_SMB2_COMMANDS; j++)
- if (atomic_read(&server->smb2slowcmd[j])) {
- spin_lock(&server->srv_lock);
- seq_printf(m, " %d slow responses from %s for command %d\n",
- atomic_read(&server->smb2slowcmd[j]),
- server->hostname, j);
- spin_unlock(&server->srv_lock);
- }
-#endif /* STATS2 */
- list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- i++;
- seq_printf(m, "\n%d) %s", i, tcon->tree_name);
- if (tcon->need_reconnect)
- seq_puts(m, "\tDISCONNECTED ");
- seq_printf(m, "\nSMBs: %d",
- atomic_read(&tcon->num_smbs_sent));
- if (server->ops->print_stats)
- server->ops->print_stats(m, tcon);
- }
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
-
- seq_putc(m, '\n');
- return 0;
-}
-
-static int cifs_stats_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, cifs_stats_proc_show, NULL);
-}
-
-static const struct proc_ops cifs_stats_proc_ops = {
- .proc_open = cifs_stats_proc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = single_release,
- .proc_write = cifs_stats_proc_write,
-};
-
-#ifdef CONFIG_CIFS_SMB_DIRECT
-#define PROC_FILE_DEFINE(name) \
-static ssize_t name##_write(struct file *file, const char __user *buffer, \
- size_t count, loff_t *ppos) \
-{ \
- int rc; \
- rc = kstrtoint_from_user(buffer, count, 10, & name); \
- if (rc) \
- return rc; \
- return count; \
-} \
-static int name##_proc_show(struct seq_file *m, void *v) \
-{ \
- seq_printf(m, "%d\n", name ); \
- return 0; \
-} \
-static int name##_open(struct inode *inode, struct file *file) \
-{ \
- return single_open(file, name##_proc_show, NULL); \
-} \
-\
-static const struct proc_ops cifs_##name##_proc_fops = { \
- .proc_open = name##_open, \
- .proc_read = seq_read, \
- .proc_lseek = seq_lseek, \
- .proc_release = single_release, \
- .proc_write = name##_write, \
-}
-
-PROC_FILE_DEFINE(rdma_readwrite_threshold);
-PROC_FILE_DEFINE(smbd_max_frmr_depth);
-PROC_FILE_DEFINE(smbd_keep_alive_interval);
-PROC_FILE_DEFINE(smbd_max_receive_size);
-PROC_FILE_DEFINE(smbd_max_fragmented_recv_size);
-PROC_FILE_DEFINE(smbd_max_send_size);
-PROC_FILE_DEFINE(smbd_send_credit_target);
-PROC_FILE_DEFINE(smbd_receive_credit_max);
-#endif
-
-static struct proc_dir_entry *proc_fs_cifs;
-static const struct proc_ops cifsFYI_proc_ops;
-static const struct proc_ops cifs_lookup_cache_proc_ops;
-static const struct proc_ops traceSMB_proc_ops;
-static const struct proc_ops cifs_security_flags_proc_ops;
-static const struct proc_ops cifs_linux_ext_proc_ops;
-static const struct proc_ops cifs_mount_params_proc_ops;
-
-void
-cifs_proc_init(void)
-{
- proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
- if (proc_fs_cifs == NULL)
- return;
-
- proc_create_single("DebugData", 0, proc_fs_cifs,
- cifs_debug_data_proc_show);
-
- proc_create_single("open_files", 0400, proc_fs_cifs,
- cifs_debug_files_proc_show);
-
- proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_ops);
- proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_ops);
- proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_ops);
- proc_create("LinuxExtensionsEnabled", 0644, proc_fs_cifs,
- &cifs_linux_ext_proc_ops);
- proc_create("SecurityFlags", 0644, proc_fs_cifs,
- &cifs_security_flags_proc_ops);
- proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
- &cifs_lookup_cache_proc_ops);
-
- proc_create("mount_params", 0444, proc_fs_cifs, &cifs_mount_params_proc_ops);
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
- proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops);
-#endif
-
-#ifdef CONFIG_CIFS_SMB_DIRECT
- proc_create("rdma_readwrite_threshold", 0644, proc_fs_cifs,
- &cifs_rdma_readwrite_threshold_proc_fops);
- proc_create("smbd_max_frmr_depth", 0644, proc_fs_cifs,
- &cifs_smbd_max_frmr_depth_proc_fops);
- proc_create("smbd_keep_alive_interval", 0644, proc_fs_cifs,
- &cifs_smbd_keep_alive_interval_proc_fops);
- proc_create("smbd_max_receive_size", 0644, proc_fs_cifs,
- &cifs_smbd_max_receive_size_proc_fops);
- proc_create("smbd_max_fragmented_recv_size", 0644, proc_fs_cifs,
- &cifs_smbd_max_fragmented_recv_size_proc_fops);
- proc_create("smbd_max_send_size", 0644, proc_fs_cifs,
- &cifs_smbd_max_send_size_proc_fops);
- proc_create("smbd_send_credit_target", 0644, proc_fs_cifs,
- &cifs_smbd_send_credit_target_proc_fops);
- proc_create("smbd_receive_credit_max", 0644, proc_fs_cifs,
- &cifs_smbd_receive_credit_max_proc_fops);
-#endif
-}
-
-void
-cifs_proc_clean(void)
-{
- if (proc_fs_cifs == NULL)
- return;
-
- remove_proc_entry("DebugData", proc_fs_cifs);
- remove_proc_entry("open_files", proc_fs_cifs);
- remove_proc_entry("cifsFYI", proc_fs_cifs);
- remove_proc_entry("traceSMB", proc_fs_cifs);
- remove_proc_entry("Stats", proc_fs_cifs);
- remove_proc_entry("SecurityFlags", proc_fs_cifs);
- remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
- remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
- remove_proc_entry("mount_params", proc_fs_cifs);
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
- remove_proc_entry("dfscache", proc_fs_cifs);
-#endif
-#ifdef CONFIG_CIFS_SMB_DIRECT
- remove_proc_entry("rdma_readwrite_threshold", proc_fs_cifs);
- remove_proc_entry("smbd_max_frmr_depth", proc_fs_cifs);
- remove_proc_entry("smbd_keep_alive_interval", proc_fs_cifs);
- remove_proc_entry("smbd_max_receive_size", proc_fs_cifs);
- remove_proc_entry("smbd_max_fragmented_recv_size", proc_fs_cifs);
- remove_proc_entry("smbd_max_send_size", proc_fs_cifs);
- remove_proc_entry("smbd_send_credit_target", proc_fs_cifs);
- remove_proc_entry("smbd_receive_credit_max", proc_fs_cifs);
-#endif
- remove_proc_entry("fs/cifs", NULL);
-}
-
-static int cifsFYI_proc_show(struct seq_file *m, void *v)
-{
- seq_printf(m, "%d\n", cifsFYI);
- return 0;
-}
-
-static int cifsFYI_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, cifsFYI_proc_show, NULL);
-}
-
-static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *ppos)
-{
- char c[2] = { '\0' };
- bool bv;
- int rc;
-
- rc = get_user(c[0], buffer);
- if (rc)
- return rc;
- if (strtobool(c, &bv) == 0)
- cifsFYI = bv;
- else if ((c[0] > '1') && (c[0] <= '9'))
- cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */
- else
- return -EINVAL;
-
- return count;
-}
-
-static const struct proc_ops cifsFYI_proc_ops = {
- .proc_open = cifsFYI_proc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = single_release,
- .proc_write = cifsFYI_proc_write,
-};
-
-static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
-{
- seq_printf(m, "%d\n", linuxExtEnabled);
- return 0;
-}
-
-static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, cifs_linux_ext_proc_show, NULL);
-}
-
-static ssize_t cifs_linux_ext_proc_write(struct file *file,
- const char __user *buffer, size_t count, loff_t *ppos)
-{
- int rc;
-
- rc = kstrtobool_from_user(buffer, count, &linuxExtEnabled);
- if (rc)
- return rc;
-
- return count;
-}
-
-static const struct proc_ops cifs_linux_ext_proc_ops = {
- .proc_open = cifs_linux_ext_proc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = single_release,
- .proc_write = cifs_linux_ext_proc_write,
-};
-
-static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v)
-{
- seq_printf(m, "%d\n", lookupCacheEnabled);
- return 0;
-}
-
-static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, cifs_lookup_cache_proc_show, NULL);
-}
-
-static ssize_t cifs_lookup_cache_proc_write(struct file *file,
- const char __user *buffer, size_t count, loff_t *ppos)
-{
- int rc;
-
- rc = kstrtobool_from_user(buffer, count, &lookupCacheEnabled);
- if (rc)
- return rc;
-
- return count;
-}
-
-static const struct proc_ops cifs_lookup_cache_proc_ops = {
- .proc_open = cifs_lookup_cache_proc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = single_release,
- .proc_write = cifs_lookup_cache_proc_write,
-};
-
-static int traceSMB_proc_show(struct seq_file *m, void *v)
-{
- seq_printf(m, "%d\n", traceSMB);
- return 0;
-}
-
-static int traceSMB_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, traceSMB_proc_show, NULL);
-}
-
-static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *ppos)
-{
- int rc;
-
- rc = kstrtobool_from_user(buffer, count, &traceSMB);
- if (rc)
- return rc;
-
- return count;
-}
-
-static const struct proc_ops traceSMB_proc_ops = {
- .proc_open = traceSMB_proc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = single_release,
- .proc_write = traceSMB_proc_write,
-};
-
-static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
-{
- seq_printf(m, "0x%x\n", global_secflags);
- return 0;
-}
-
-static int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, cifs_security_flags_proc_show, NULL);
-}
-
-/*
- * Ensure that if someone sets a MUST flag, that we disable all other MAY
- * flags except for the ones corresponding to the given MUST flag. If there are
- * multiple MUST flags, then try to prefer more secure ones.
- */
-static void
-cifs_security_flags_handle_must_flags(unsigned int *flags)
-{
- unsigned int signflags = *flags & CIFSSEC_MUST_SIGN;
-
- if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
- *flags = CIFSSEC_MUST_KRB5;
- else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
- *flags = CIFSSEC_MUST_NTLMSSP;
- else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
- *flags = CIFSSEC_MUST_NTLMV2;
-
- *flags |= signflags;
-}
-
-static ssize_t cifs_security_flags_proc_write(struct file *file,
- const char __user *buffer, size_t count, loff_t *ppos)
-{
- int rc;
- unsigned int flags;
- char flags_string[12];
- bool bv;
-
- if ((count < 1) || (count > 11))
- return -EINVAL;
-
- memset(flags_string, 0, 12);
-
- if (copy_from_user(flags_string, buffer, count))
- return -EFAULT;
-
- if (count < 3) {
- /* single char or single char followed by null */
- if (strtobool(flags_string, &bv) == 0) {
- global_secflags = bv ? CIFSSEC_MAX : CIFSSEC_DEF;
- return count;
- } else if (!isdigit(flags_string[0])) {
- cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
- flags_string);
- return -EINVAL;
- }
- }
-
- /* else we have a number */
- rc = kstrtouint(flags_string, 0, &flags);
- if (rc) {
- cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
- flags_string);
- return rc;
- }
-
- cifs_dbg(FYI, "sec flags 0x%x\n", flags);
-
- if (flags == 0) {
- cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", flags_string);
- return -EINVAL;
- }
-
- if (flags & ~CIFSSEC_MASK) {
- cifs_dbg(VFS, "Unsupported security flags: 0x%x\n",
- flags & ~CIFSSEC_MASK);
- return -EINVAL;
- }
-
- cifs_security_flags_handle_must_flags(&flags);
-
- /* flags look ok - update the global security flags for cifs module */
- global_secflags = flags;
- if (global_secflags & CIFSSEC_MUST_SIGN) {
- /* requiring signing implies signing is allowed */
- global_secflags |= CIFSSEC_MAY_SIGN;
- cifs_dbg(FYI, "packet signing now required\n");
- } else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) {
- cifs_dbg(FYI, "packet signing disabled\n");
- }
- /* BB should we turn on MAY flags for other MUST options? */
- return count;
-}
-
-static const struct proc_ops cifs_security_flags_proc_ops = {
- .proc_open = cifs_security_flags_proc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = single_release,
- .proc_write = cifs_security_flags_proc_write,
-};
-
-/* To make it easier to debug, can help to show mount params */
-static int cifs_mount_params_proc_show(struct seq_file *m, void *v)
-{
- const struct fs_parameter_spec *p;
- const char *type;
-
- for (p = smb3_fs_parameters; p->name; p++) {
- /* cannot use switch with pointers... */
- if (!p->type) {
- if (p->flags == fs_param_neg_with_no)
- type = "noflag";
- else
- type = "flag";
- } else if (p->type == fs_param_is_bool)
- type = "bool";
- else if (p->type == fs_param_is_u32)
- type = "u32";
- else if (p->type == fs_param_is_u64)
- type = "u64";
- else if (p->type == fs_param_is_string)
- type = "string";
- else
- type = "unknown";
-
- seq_printf(m, "%s:%s\n", p->name, type);
- }
-
- return 0;
-}
-
-static int cifs_mount_params_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, cifs_mount_params_proc_show, NULL);
-}
-
-static const struct proc_ops cifs_mount_params_proc_ops = {
- .proc_open = cifs_mount_params_proc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = single_release,
- /* No need for write for now */
- /* .proc_write = cifs_mount_params_proc_write, */
-};
-
-#else
-inline void cifs_proc_init(void)
-{
-}
-
-inline void cifs_proc_clean(void)
-{
-}
-#endif /* PROC_FS */
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
deleted file mode 100644
index ce5cfd236fdb..000000000000
--- a/fs/cifs/cifs_debug.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2000,2002
- * Modified by Steve French (sfrench@us.ibm.com)
- */
-
-#ifndef _H_CIFS_DEBUG
-#define _H_CIFS_DEBUG
-
-#ifdef pr_fmt
-#undef pr_fmt
-#endif
-
-#define pr_fmt(fmt) "CIFS: " fmt
-
-void cifs_dump_mem(char *label, void *data, int length);
-void cifs_dump_detail(void *buf, struct TCP_Server_Info *ptcp_info);
-void cifs_dump_mids(struct TCP_Server_Info *);
-extern bool traceSMB; /* flag which enables the function below */
-void dump_smb(void *, int);
-#define CIFS_INFO 0x01
-#define CIFS_RC 0x02
-#define CIFS_TIMER 0x04
-
-#define VFS 1
-#define FYI 2
-extern int cifsFYI;
-#ifdef CONFIG_CIFS_DEBUG2
-#define NOISY 4
-#else
-#define NOISY 0
-#endif
-#define ONCE 8
-
-/*
- * debug ON
- * --------
- */
-#ifdef CONFIG_CIFS_DEBUG
-
-
-/*
- * When adding tracepoints and debug messages we have various choices.
- * Some considerations:
- *
- * Use cifs_dbg(VFS, ...) for things we always want logged, and the user to see
- * cifs_info(...) slightly less important, admin can filter via loglevel > 6
- * cifs_dbg(FYI, ...) minor debugging messages, off by default
- * trace_smb3_* ftrace functions are preferred for complex debug messages
- * intended for developers or experienced admins, off by default
- */
-
-/* Information level messages, minor events */
-#define cifs_info_func(ratefunc, fmt, ...) \
- pr_info_ ## ratefunc(fmt, ##__VA_ARGS__)
-
-#define cifs_info(fmt, ...) \
- cifs_info_func(ratelimited, fmt, ##__VA_ARGS__)
-
-/* information message: e.g., configuration, major event */
-#define cifs_dbg_func(ratefunc, type, fmt, ...) \
-do { \
- if ((type) & FYI && cifsFYI & CIFS_INFO) { \
- pr_debug_ ## ratefunc("%s: " fmt, \
- __FILE__, ##__VA_ARGS__); \
- } else if ((type) & VFS) { \
- pr_err_ ## ratefunc("VFS: " fmt, ##__VA_ARGS__); \
- } else if ((type) & NOISY && (NOISY != 0)) { \
- pr_debug_ ## ratefunc(fmt, ##__VA_ARGS__); \
- } \
-} while (0)
-
-#define cifs_dbg(type, fmt, ...) \
-do { \
- if ((type) & ONCE) \
- cifs_dbg_func(once, type, fmt, ##__VA_ARGS__); \
- else \
- cifs_dbg_func(ratelimited, type, fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define cifs_server_dbg_func(ratefunc, type, fmt, ...) \
-do { \
- spin_lock(&server->srv_lock); \
- if ((type) & FYI && cifsFYI & CIFS_INFO) { \
- pr_debug_ ## ratefunc("%s: \\\\%s " fmt, \
- __FILE__, server->hostname, \
- ##__VA_ARGS__); \
- } else if ((type) & VFS) { \
- pr_err_ ## ratefunc("VFS: \\\\%s " fmt, \
- server->hostname, ##__VA_ARGS__); \
- } else if ((type) & NOISY && (NOISY != 0)) { \
- pr_debug_ ## ratefunc("\\\\%s " fmt, \
- server->hostname, ##__VA_ARGS__); \
- } \
- spin_unlock(&server->srv_lock); \
-} while (0)
-
-#define cifs_server_dbg(type, fmt, ...) \
-do { \
- if ((type) & ONCE) \
- cifs_server_dbg_func(once, type, fmt, ##__VA_ARGS__); \
- else \
- cifs_server_dbg_func(ratelimited, type, fmt, \
- ##__VA_ARGS__); \
-} while (0)
-
-#define cifs_tcon_dbg_func(ratefunc, type, fmt, ...) \
-do { \
- const char *tn = ""; \
- if (tcon && tcon->tree_name) \
- tn = tcon->tree_name; \
- if ((type) & FYI && cifsFYI & CIFS_INFO) { \
- pr_debug_ ## ratefunc("%s: %s " fmt, \
- __FILE__, tn, ##__VA_ARGS__); \
- } else if ((type) & VFS) { \
- pr_err_ ## ratefunc("VFS: %s " fmt, tn, ##__VA_ARGS__); \
- } else if ((type) & NOISY && (NOISY != 0)) { \
- pr_debug_ ## ratefunc("%s " fmt, tn, ##__VA_ARGS__); \
- } \
-} while (0)
-
-#define cifs_tcon_dbg(type, fmt, ...) \
-do { \
- if ((type) & ONCE) \
- cifs_tcon_dbg_func(once, type, fmt, ##__VA_ARGS__); \
- else \
- cifs_tcon_dbg_func(ratelimited, type, fmt, \
- ##__VA_ARGS__); \
-} while (0)
-
-/*
- * debug OFF
- * ---------
- */
-#else /* _CIFS_DEBUG */
-#define cifs_dbg(type, fmt, ...) \
-do { \
- if (0) \
- pr_debug(fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define cifs_server_dbg(type, fmt, ...) \
-do { \
- if (0) \
- pr_debug("\\\\%s " fmt, \
- server->hostname, ##__VA_ARGS__); \
-} while (0)
-
-#define cifs_tcon_dbg(type, fmt, ...) \
-do { \
- if (0) \
- pr_debug("%s " fmt, tcon->tree_name, ##__VA_ARGS__); \
-} while (0)
-
-#define cifs_info(fmt, ...) \
- pr_info(fmt, ##__VA_ARGS__)
-#endif
-
-#endif /* _H_CIFS_DEBUG */
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
deleted file mode 100644
index b0864da9ef43..000000000000
--- a/fs/cifs/cifs_dfs_ref.c
+++ /dev/null
@@ -1,374 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Contains the CIFS DFS referral mounting routines used for handling
- * traversal via DFS junction point
- *
- * Copyright (c) 2007 Igor Mammedov
- * Copyright (C) International Business Machines Corp., 2008
- * Author(s): Igor Mammedov (niallain@gmail.com)
- * Steve French (sfrench@us.ibm.com)
- */
-
-#include <linux/dcache.h>
-#include <linux/mount.h>
-#include <linux/namei.h>
-#include <linux/slab.h>
-#include <linux/vfs.h>
-#include <linux/fs.h>
-#include <linux/inet.h>
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifsfs.h"
-#include "dns_resolve.h"
-#include "cifs_debug.h"
-#include "cifs_unicode.h"
-#include "dfs_cache.h"
-#include "fs_context.h"
-
-static LIST_HEAD(cifs_dfs_automount_list);
-
-static void cifs_dfs_expire_automounts(struct work_struct *work);
-static DECLARE_DELAYED_WORK(cifs_dfs_automount_task,
- cifs_dfs_expire_automounts);
-static int cifs_dfs_mountpoint_expiry_timeout = 500 * HZ;
-
-static void cifs_dfs_expire_automounts(struct work_struct *work)
-{
- struct list_head *list = &cifs_dfs_automount_list;
-
- mark_mounts_for_expiry(list);
- if (!list_empty(list))
- schedule_delayed_work(&cifs_dfs_automount_task,
- cifs_dfs_mountpoint_expiry_timeout);
-}
-
-void cifs_dfs_release_automount_timer(void)
-{
- BUG_ON(!list_empty(&cifs_dfs_automount_list));
- cancel_delayed_work_sync(&cifs_dfs_automount_task);
-}
-
-/**
- * cifs_build_devname - build a devicename from a UNC and optional prepath
- * @nodename: pointer to UNC string
- * @prepath: pointer to prefixpath (or NULL if there isn't one)
- *
- * Build a new cifs devicename after chasing a DFS referral. Allocate a buffer
- * big enough to hold the final thing. Copy the UNC from the nodename, and
- * concatenate the prepath onto the end of it if there is one.
- *
- * Returns pointer to the built string, or a ERR_PTR. Caller is responsible
- * for freeing the returned string.
- */
-static char *
-cifs_build_devname(char *nodename, const char *prepath)
-{
- size_t pplen;
- size_t unclen;
- char *dev;
- char *pos;
-
- /* skip over any preceding delimiters */
- nodename += strspn(nodename, "\\");
- if (!*nodename)
- return ERR_PTR(-EINVAL);
-
- /* get length of UNC and set pos to last char */
- unclen = strlen(nodename);
- pos = nodename + unclen - 1;
-
- /* trim off any trailing delimiters */
- while (*pos == '\\') {
- --pos;
- --unclen;
- }
-
- /* allocate a buffer:
- * +2 for preceding "//"
- * +1 for delimiter between UNC and prepath
- * +1 for trailing NULL
- */
- pplen = prepath ? strlen(prepath) : 0;
- dev = kmalloc(2 + unclen + 1 + pplen + 1, GFP_KERNEL);
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- pos = dev;
- /* add the initial "//" */
- *pos = '/';
- ++pos;
- *pos = '/';
- ++pos;
-
- /* copy in the UNC portion from referral */
- memcpy(pos, nodename, unclen);
- pos += unclen;
-
- /* copy the prefixpath remainder (if there is one) */
- if (pplen) {
- *pos = '/';
- ++pos;
- memcpy(pos, prepath, pplen);
- pos += pplen;
- }
-
- /* NULL terminator */
- *pos = '\0';
-
- convert_delimiter(dev, '/');
- return dev;
-}
-
-
-/**
- * cifs_compose_mount_options - creates mount options for referral
- * @sb_mountdata: parent/root DFS mount options (template)
- * @fullpath: full path in UNC format
- * @ref: optional server's referral
- * @devname: return the built cifs device name if passed pointer not NULL
- * creates mount options for submount based on template options sb_mountdata
- * and replacing unc,ip,prefixpath options with ones we've got form ref_unc.
- *
- * Returns: pointer to new mount options or ERR_PTR.
- * Caller is responsible for freeing returned value if it is not error.
- */
-char *cifs_compose_mount_options(const char *sb_mountdata,
- const char *fullpath,
- const struct dfs_info3_param *ref,
- char **devname)
-{
- int rc;
- char *name;
- char *mountdata = NULL;
- const char *prepath = NULL;
- int md_len;
- char *tkn_e;
- char *srvIP = NULL;
- char sep = ',';
- int off, noff;
-
- if (sb_mountdata == NULL)
- return ERR_PTR(-EINVAL);
-
- if (ref) {
- if (WARN_ON_ONCE(!ref->node_name || ref->path_consumed < 0))
- return ERR_PTR(-EINVAL);
-
- if (strlen(fullpath) - ref->path_consumed) {
- prepath = fullpath + ref->path_consumed;
- /* skip initial delimiter */
- if (*prepath == '/' || *prepath == '\\')
- prepath++;
- }
-
- name = cifs_build_devname(ref->node_name, prepath);
- if (IS_ERR(name)) {
- rc = PTR_ERR(name);
- name = NULL;
- goto compose_mount_options_err;
- }
- } else {
- name = cifs_build_devname((char *)fullpath, NULL);
- if (IS_ERR(name)) {
- rc = PTR_ERR(name);
- name = NULL;
- goto compose_mount_options_err;
- }
- }
-
- rc = dns_resolve_server_name_to_ip(name, &srvIP, NULL);
- if (rc < 0) {
- cifs_dbg(FYI, "%s: Failed to resolve server part of %s to IP: %d\n",
- __func__, name, rc);
- goto compose_mount_options_err;
- }
-
- /*
- * In most cases, we'll be building a shorter string than the original,
- * but we do have to assume that the address in the ip= option may be
- * much longer than the original. Add the max length of an address
- * string to the length of the original string to allow for worst case.
- */
- md_len = strlen(sb_mountdata) + INET6_ADDRSTRLEN;
- mountdata = kzalloc(md_len + sizeof("ip=") + 1, GFP_KERNEL);
- if (mountdata == NULL) {
- rc = -ENOMEM;
- goto compose_mount_options_err;
- }
-
- /* copy all options except of unc,ip,prefixpath */
- off = 0;
- if (strncmp(sb_mountdata, "sep=", 4) == 0) {
- sep = sb_mountdata[4];
- strncpy(mountdata, sb_mountdata, 5);
- off += 5;
- }
-
- do {
- tkn_e = strchr(sb_mountdata + off, sep);
- if (tkn_e == NULL)
- noff = strlen(sb_mountdata + off);
- else
- noff = tkn_e - (sb_mountdata + off) + 1;
-
- if (strncasecmp(sb_mountdata + off, "cruid=", 6) == 0) {
- off += noff;
- continue;
- }
- if (strncasecmp(sb_mountdata + off, "unc=", 4) == 0) {
- off += noff;
- continue;
- }
- if (strncasecmp(sb_mountdata + off, "ip=", 3) == 0) {
- off += noff;
- continue;
- }
- if (strncasecmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
- off += noff;
- continue;
- }
- strncat(mountdata, sb_mountdata + off, noff);
- off += noff;
- } while (tkn_e);
- strcat(mountdata, sb_mountdata + off);
- mountdata[md_len] = '\0';
-
- /* copy new IP and ref share name */
- if (mountdata[strlen(mountdata) - 1] != sep)
- strncat(mountdata, &sep, 1);
- strcat(mountdata, "ip=");
- strcat(mountdata, srvIP);
-
- if (devname)
- *devname = name;
- else
- kfree(name);
-
- /*cifs_dbg(FYI, "%s: parent mountdata: %s\n", __func__, sb_mountdata);*/
- /*cifs_dbg(FYI, "%s: submount mountdata: %s\n", __func__, mountdata );*/
-
-compose_mount_options_out:
- kfree(srvIP);
- return mountdata;
-
-compose_mount_options_err:
- kfree(mountdata);
- mountdata = ERR_PTR(rc);
- kfree(name);
- goto compose_mount_options_out;
-}
-
-/**
- * cifs_dfs_do_mount - mounts specified path using DFS full path
- *
- * Always pass down @fullpath to smb3_do_mount() so we can use the root server
- * to perform failover in case we failed to connect to the first target in the
- * referral.
- *
- * @mntpt: directory entry for the path we are trying to automount
- * @cifs_sb: parent/root superblock
- * @fullpath: full path in UNC format
- */
-static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
- struct cifs_sb_info *cifs_sb,
- const char *fullpath)
-{
- struct vfsmount *mnt;
- char *mountdata;
- char *devname;
-
- devname = kstrdup(fullpath, GFP_KERNEL);
- if (!devname)
- return ERR_PTR(-ENOMEM);
-
- convert_delimiter(devname, '/');
-
- /* TODO: change to call fs_context_for_mount(), fill in context directly, call fc_mount */
-
- /* See afs_mntpt_do_automount in fs/afs/mntpt.c for an example */
-
- /* strip first '\' from fullpath */
- mountdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
- fullpath + 1, NULL, NULL);
- if (IS_ERR(mountdata)) {
- kfree(devname);
- return (struct vfsmount *)mountdata;
- }
-
- mnt = vfs_submount(mntpt, &cifs_fs_type, devname, mountdata);
- kfree(mountdata);
- kfree(devname);
- return mnt;
-}
-
-/*
- * Create a vfsmount that we can automount
- */
-static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
-{
- struct cifs_sb_info *cifs_sb;
- void *page;
- char *full_path;
- struct vfsmount *mnt;
-
- cifs_dbg(FYI, "in %s\n", __func__);
- BUG_ON(IS_ROOT(mntpt));
-
- /*
- * The MSDFS spec states that paths in DFS referral requests and
- * responses must be prefixed by a single '\' character instead of
- * the double backslashes usually used in the UNC. This function
- * gives us the latter, so we must adjust the result.
- */
- cifs_sb = CIFS_SB(mntpt->d_sb);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) {
- mnt = ERR_PTR(-EREMOTE);
- goto cdda_exit;
- }
-
- page = alloc_dentry_path();
- /* always use tree name prefix */
- full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
- if (IS_ERR(full_path)) {
- mnt = ERR_CAST(full_path);
- goto free_full_path;
- }
-
- convert_delimiter(full_path, '\\');
- cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
-
- mnt = cifs_dfs_do_mount(mntpt, cifs_sb, full_path);
- cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__, full_path + 1, mnt);
-
-free_full_path:
- free_dentry_path(page);
-cdda_exit:
- cifs_dbg(FYI, "leaving %s\n" , __func__);
- return mnt;
-}
-
-/*
- * Attempt to automount the referral
- */
-struct vfsmount *cifs_dfs_d_automount(struct path *path)
-{
- struct vfsmount *newmnt;
-
- cifs_dbg(FYI, "in %s\n", __func__);
-
- newmnt = cifs_dfs_do_automount(path->dentry);
- if (IS_ERR(newmnt)) {
- cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__);
- return newmnt;
- }
-
- mntget(newmnt); /* prevent immediate expiration */
- mnt_set_expiry(newmnt, &cifs_dfs_automount_list);
- schedule_delayed_work(&cifs_dfs_automount_task,
- cifs_dfs_mountpoint_expiry_timeout);
- cifs_dbg(FYI, "leaving %s [ok]\n" , __func__);
- return newmnt;
-}
-
-const struct inode_operations cifs_dfs_referral_inode_operations = {
-};
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
deleted file mode 100644
index 013a4bd65280..000000000000
--- a/fs/cifs/cifs_fs_sb.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2002,2004
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-#include <linux/rbtree.h>
-
-#ifndef _CIFS_FS_SB_H
-#define _CIFS_FS_SB_H
-
-#include <linux/backing-dev.h>
-
-#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
-#define CIFS_MOUNT_SET_UID 2 /* set current's euid in create etc. */
-#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
-#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
-#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
-#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
-#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible*/
-#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
-#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */
-#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */
-#define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */
-#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */
-#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */
-#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */
-#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/
-#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */
-#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */
-#define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */
-#define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */
-#define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */
-#define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of SB_POSIXACL in mnt_cifs_flags */
-#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */
-#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */
-#define CIFS_MOUNT_MAP_SFM_CHR 0x800000 /* SFM/MAC mapping for illegal chars */
-#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000 /* make subpath with unaccessible
- * root mountable
- */
-#define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */
-#define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */
-#define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */
-#define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */
-#define CIFS_MOUNT_RO_CACHE 0x20000000 /* assumes share will not change */
-#define CIFS_MOUNT_RW_CACHE 0x40000000 /* assumes only client accessing */
-#define CIFS_MOUNT_SHUTDOWN 0x80000000
-
-struct cifs_sb_info {
- struct rb_root tlink_tree;
- spinlock_t tlink_tree_lock;
- struct tcon_link *master_tlink;
- struct nls_table *local_nls;
- struct smb3_fs_context *ctx;
- atomic_t active;
- unsigned int mnt_cifs_flags;
- struct delayed_work prune_tlinks;
- struct rcu_head rcu;
-
- /* only used when CIFS_MOUNT_USE_PREFIX_PATH is set */
- char *prepath;
-
- /* randomly generated 128-bit number for indexing dfs mount groups in referral cache */
- uuid_t dfs_mount_id;
- /*
- * Indicate whether serverino option was turned off later
- * (cifs_autodisable_serverino) in order to match new mounts.
- */
- bool mnt_cifs_serverino_autodisabled;
- /*
- * Available once the mount has completed.
- */
- struct dentry *root;
-};
-#endif /* _CIFS_FS_SB_H */
diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
deleted file mode 100644
index d86d78d5bfdc..000000000000
--- a/fs/cifs/cifs_ioctl.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Structure definitions for io control for cifs/smb3
- *
- * Copyright (c) 2015 Steve French <steve.french@primarydata.com>
- *
- */
-
-struct smb_mnt_fs_info {
- __u32 version; /* 0001 */
- __u16 protocol_id;
- __u16 tcon_flags;
- __u32 vol_serial_number;
- __u32 vol_create_time;
- __u32 share_caps;
- __u32 share_flags;
- __u32 sector_flags;
- __u32 optimal_sector_size;
- __u32 max_bytes_chunk;
- __u32 fs_attributes;
- __u32 max_path_component;
- __u32 device_type;
- __u32 device_characteristics;
- __u32 maximal_access;
- __u64 cifs_posix_caps;
-} __packed;
-
-struct smb_snapshot_array {
- __u32 number_of_snapshots;
- __u32 number_of_snapshots_returned;
- __u32 snapshot_array_size;
- /* snapshots[]; */
-} __packed;
-
-/* query_info flags */
-#define PASSTHRU_QUERY_INFO 0x00000000
-#define PASSTHRU_FSCTL 0x00000001
-#define PASSTHRU_SET_INFO 0x00000002
-struct smb_query_info {
- __u32 info_type;
- __u32 file_info_class;
- __u32 additional_information;
- __u32 flags;
- __u32 input_buffer_length;
- __u32 output_buffer_length;
- /* char buffer[]; */
-} __packed;
-
-/*
- * Dumping the commonly used 16 byte (e.g. CCM and GCM128) keys still supported
- * for backlevel compatibility, but is not sufficient for dumping the less
- * frequently used GCM256 (32 byte) keys (see the newer "CIFS_DUMP_FULL_KEY"
- * ioctl for dumping decryption info for GCM256 mounts)
- */
-struct smb3_key_debug_info {
- __u64 Suid;
- __u16 cipher_type;
- __u8 auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */
- __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
- __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
-} __packed;
-
-/*
- * Dump variable-sized keys
- */
-struct smb3_full_key_debug_info {
- /* INPUT: size of userspace buffer */
- __u32 in_size;
-
- /*
- * INPUT: 0 for current user, otherwise session to dump
- * OUTPUT: session id that was dumped
- */
- __u64 session_id;
- __u16 cipher_type;
- __u8 session_key_length;
- __u8 server_in_key_length;
- __u8 server_out_key_length;
- __u8 data[];
- /*
- * return this struct with the keys appended at the end:
- * __u8 session_key[session_key_length];
- * __u8 server_in_key[server_in_key_length];
- * __u8 server_out_key[server_out_key_length];
- */
-} __packed;
-
-struct smb3_notify {
- __u32 completion_filter;
- bool watch_tree;
-} __packed;
-
-struct smb3_notify_info {
- __u32 completion_filter;
- bool watch_tree;
- __u32 data_len; /* size of notify data below */
- __u8 notify_data[];
-} __packed;
-
-#define CIFS_IOCTL_MAGIC 0xCF
-#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)
-#define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4)
-#define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
-#define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
-#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
-#define CIFS_DUMP_KEY _IOWR(CIFS_IOCTL_MAGIC, 8, struct smb3_key_debug_info)
-#define CIFS_IOC_NOTIFY _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify)
-#define CIFS_DUMP_FULL_KEY _IOWR(CIFS_IOCTL_MAGIC, 10, struct smb3_full_key_debug_info)
-#define CIFS_IOC_NOTIFY_INFO _IOWR(CIFS_IOCTL_MAGIC, 11, struct smb3_notify_info)
-#define CIFS_IOC_SHUTDOWN _IOR ('X', 125, __u32)
-
-/*
- * Flags for going down operation
- */
-#define CIFS_GOING_FLAGS_DEFAULT 0x0 /* going down */
-#define CIFS_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
-#define CIFS_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
-
-static inline bool cifs_forced_shutdown(struct cifs_sb_info *sbi)
-{
- if (CIFS_MOUNT_SHUTDOWN & sbi->mnt_cifs_flags)
- return true;
- else
- return false;
-}
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
deleted file mode 100644
index 342717bf1dc2..000000000000
--- a/fs/cifs/cifs_spnego.c
+++ /dev/null
@@ -1,236 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- * SPNEGO upcall management for CIFS
- *
- * Copyright (c) 2007 Red Hat, Inc.
- * Author(s): Jeff Layton (jlayton@redhat.com)
- *
- */
-
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <keys/user-type.h>
-#include <linux/key-type.h>
-#include <linux/keyctl.h>
-#include <linux/inet.h>
-#include "cifsglob.h"
-#include "cifs_spnego.h"
-#include "cifs_debug.h"
-#include "cifsproto.h"
-static const struct cred *spnego_cred;
-
-/* create a new cifs key */
-static int
-cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
-{
- char *payload;
- int ret;
-
- ret = -ENOMEM;
- payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
- if (!payload)
- goto error;
-
- /* attach the data */
- key->payload.data[0] = payload;
- ret = 0;
-
-error:
- return ret;
-}
-
-static void
-cifs_spnego_key_destroy(struct key *key)
-{
- kfree(key->payload.data[0]);
-}
-
-
-/*
- * keytype for CIFS spnego keys
- */
-struct key_type cifs_spnego_key_type = {
- .name = "cifs.spnego",
- .instantiate = cifs_spnego_key_instantiate,
- .destroy = cifs_spnego_key_destroy,
- .describe = user_describe,
-};
-
-/* length of longest version string e.g. strlen("ver=0xFF") */
-#define MAX_VER_STR_LEN 8
-
-/* length of longest security mechanism name, eg in future could have
- * strlen(";sec=ntlmsspi") */
-#define MAX_MECH_STR_LEN 13
-
-/* strlen of "host=" */
-#define HOST_KEY_LEN 5
-
-/* strlen of ";ip4=" or ";ip6=" */
-#define IP_KEY_LEN 5
-
-/* strlen of ";uid=0x" */
-#define UID_KEY_LEN 7
-
-/* strlen of ";creduid=0x" */
-#define CREDUID_KEY_LEN 11
-
-/* strlen of ";user=" */
-#define USER_KEY_LEN 6
-
-/* strlen of ";pid=0x" */
-#define PID_KEY_LEN 7
-
-/* get a key struct with a SPNEGO security blob, suitable for session setup */
-struct key *
-cifs_get_spnego_key(struct cifs_ses *sesInfo,
- struct TCP_Server_Info *server)
-{
- struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
- struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
- char *description, *dp;
- size_t desc_len;
- struct key *spnego_key;
- const char *hostname = server->hostname;
- const struct cred *saved_cred;
-
- /* length of fields (with semicolons): ver=0xyz ip4=ipaddress
- host=hostname sec=mechanism uid=0xFF user=username */
- desc_len = MAX_VER_STR_LEN +
- HOST_KEY_LEN + strlen(hostname) +
- IP_KEY_LEN + INET6_ADDRSTRLEN +
- MAX_MECH_STR_LEN +
- UID_KEY_LEN + (sizeof(uid_t) * 2) +
- CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
- PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
-
- if (sesInfo->user_name)
- desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
-
- spnego_key = ERR_PTR(-ENOMEM);
- description = kzalloc(desc_len, GFP_KERNEL);
- if (description == NULL)
- goto out;
-
- dp = description;
- /* start with version and hostname portion of UNC string */
- spnego_key = ERR_PTR(-EINVAL);
- sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
- hostname);
- dp = description + strlen(description);
-
- /* add the server address */
- if (server->dstaddr.ss_family == AF_INET)
- sprintf(dp, "ip4=%pI4", &sa->sin_addr);
- else if (server->dstaddr.ss_family == AF_INET6)
- sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
- else
- goto out;
-
- dp = description + strlen(description);
-
- /* for now, only sec=krb5 and sec=mskrb5 are valid */
- if (server->sec_kerberos)
- sprintf(dp, ";sec=krb5");
- else if (server->sec_mskerberos)
- sprintf(dp, ";sec=mskrb5");
- else {
- cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n");
- sprintf(dp, ";sec=krb5");
- }
-
- dp = description + strlen(description);
- sprintf(dp, ";uid=0x%x",
- from_kuid_munged(&init_user_ns, sesInfo->linux_uid));
-
- dp = description + strlen(description);
- sprintf(dp, ";creduid=0x%x",
- from_kuid_munged(&init_user_ns, sesInfo->cred_uid));
-
- if (sesInfo->user_name) {
- dp = description + strlen(description);
- sprintf(dp, ";user=%s", sesInfo->user_name);
- }
-
- dp = description + strlen(description);
- sprintf(dp, ";pid=0x%x", current->pid);
-
- cifs_dbg(FYI, "key description = %s\n", description);
- saved_cred = override_creds(spnego_cred);
- spnego_key = request_key(&cifs_spnego_key_type, description, "");
- revert_creds(saved_cred);
-
-#ifdef CONFIG_CIFS_DEBUG2
- if (cifsFYI && !IS_ERR(spnego_key)) {
- struct cifs_spnego_msg *msg = spnego_key->payload.data[0];
- cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U,
- msg->secblob_len + msg->sesskey_len));
- }
-#endif /* CONFIG_CIFS_DEBUG2 */
-
-out:
- kfree(description);
- return spnego_key;
-}
-
-int
-init_cifs_spnego(void)
-{
- struct cred *cred;
- struct key *keyring;
- int ret;
-
- cifs_dbg(FYI, "Registering the %s key type\n",
- cifs_spnego_key_type.name);
-
- /*
- * Create an override credential set with special thread keyring for
- * spnego upcalls.
- */
-
- cred = prepare_kernel_cred(NULL);
- if (!cred)
- return -ENOMEM;
-
- keyring = keyring_alloc(".cifs_spnego",
- GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
- (KEY_POS_ALL & ~KEY_POS_SETATTR) |
- KEY_USR_VIEW | KEY_USR_READ,
- KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
- goto failed_put_cred;
- }
-
- ret = register_key_type(&cifs_spnego_key_type);
- if (ret < 0)
- goto failed_put_key;
-
- /*
- * instruct request_key() to use this special keyring as a cache for
- * the results it looks up
- */
- set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
- cred->thread_keyring = keyring;
- cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
- spnego_cred = cred;
-
- cifs_dbg(FYI, "cifs spnego keyring: %d\n", key_serial(keyring));
- return 0;
-
-failed_put_key:
- key_put(keyring);
-failed_put_cred:
- put_cred(cred);
- return ret;
-}
-
-void
-exit_cifs_spnego(void)
-{
- key_revoke(spnego_cred->thread_keyring);
- unregister_key_type(&cifs_spnego_key_type);
- put_cred(spnego_cred);
- cifs_dbg(FYI, "Unregistered %s key type\n", cifs_spnego_key_type.name);
-}
diff --git a/fs/cifs/cifs_spnego.h b/fs/cifs/cifs_spnego.h
deleted file mode 100644
index 7f102ffeb675..000000000000
--- a/fs/cifs/cifs_spnego.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- * SPNEGO upcall management for CIFS
- *
- * Copyright (c) 2007 Red Hat, Inc.
- * Author(s): Jeff Layton (jlayton@redhat.com)
- * Steve French (sfrench@us.ibm.com)
- *
- */
-
-#ifndef _CIFS_SPNEGO_H
-#define _CIFS_SPNEGO_H
-
-#define CIFS_SPNEGO_UPCALL_VERSION 2
-
-/*
- * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION.
- * The flags field is for future use. The request-key callout should set
- * sesskey_len and secblob_len, and then concatenate the SessKey+SecBlob
- * and stuff it in the data field.
- */
-struct cifs_spnego_msg {
- uint32_t version;
- uint32_t flags;
- uint32_t sesskey_len;
- uint32_t secblob_len;
- uint8_t data[1];
-};
-
-#ifdef __KERNEL__
-extern struct key_type cifs_spnego_key_type;
-extern struct key *cifs_get_spnego_key(struct cifs_ses *sesInfo,
- struct TCP_Server_Info *server);
-#endif /* KERNEL */
-
-#endif /* _CIFS_SPNEGO_H */
diff --git a/fs/cifs/cifs_spnego_negtokeninit.asn1 b/fs/cifs/cifs_spnego_negtokeninit.asn1
deleted file mode 100644
index 181c083887d5..000000000000
--- a/fs/cifs/cifs_spnego_negtokeninit.asn1
+++ /dev/null
@@ -1,40 +0,0 @@
-GSSAPI ::=
- [APPLICATION 0] IMPLICIT SEQUENCE {
- thisMech
- OBJECT IDENTIFIER ({cifs_gssapi_this_mech}),
- negotiationToken
- NegotiationToken
- }
-
-MechType ::= OBJECT IDENTIFIER ({cifs_neg_token_init_mech_type})
-
-MechTypeList ::= SEQUENCE OF MechType
-
-NegHints ::= SEQUENCE {
- hintName
- [0] GeneralString OPTIONAL,
- hintAddress
- [1] OCTET STRING OPTIONAL
- }
-
-NegTokenInit2 ::=
- SEQUENCE {
- mechTypes
- [0] MechTypeList OPTIONAL,
- reqFlags
- [1] BIT STRING OPTIONAL,
- mechToken
- [2] OCTET STRING OPTIONAL,
- negHints
- [3] NegHints OPTIONAL,
- mechListMIC
- [3] OCTET STRING OPTIONAL
- }
-
-NegotiationToken ::=
- CHOICE {
- negTokenInit
- [0] NegTokenInit2,
- negTokenTarg
- [1] ANY
- }
diff --git a/fs/cifs/cifs_swn.c b/fs/cifs/cifs_swn.c
deleted file mode 100644
index 7233c6a7e6d7..000000000000
--- a/fs/cifs/cifs_swn.c
+++ /dev/null
@@ -1,674 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Witness Service client for CIFS
- *
- * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
- */
-
-#include <linux/kref.h>
-#include <net/genetlink.h>
-#include <uapi/linux/cifs/cifs_netlink.h>
-
-#include "cifs_swn.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "fscache.h"
-#include "cifs_debug.h"
-#include "netlink.h"
-
-static DEFINE_IDR(cifs_swnreg_idr);
-static DEFINE_MUTEX(cifs_swnreg_idr_mutex);
-
-struct cifs_swn_reg {
- int id;
- struct kref ref_count;
-
- const char *net_name;
- const char *share_name;
- bool net_name_notify;
- bool share_name_notify;
- bool ip_notify;
-
- struct cifs_tcon *tcon;
-};
-
-static int cifs_swn_auth_info_krb(struct cifs_tcon *tcon, struct sk_buff *skb)
-{
- int ret;
-
- ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_KRB_AUTH);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int cifs_swn_auth_info_ntlm(struct cifs_tcon *tcon, struct sk_buff *skb)
-{
- int ret;
-
- if (tcon->ses->user_name != NULL) {
- ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_USER_NAME, tcon->ses->user_name);
- if (ret < 0)
- return ret;
- }
-
- if (tcon->ses->password != NULL) {
- ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_PASSWORD, tcon->ses->password);
- if (ret < 0)
- return ret;
- }
-
- if (tcon->ses->domainName != NULL) {
- ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_DOMAIN_NAME, tcon->ses->domainName);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-/*
- * Sends a register message to the userspace daemon based on the registration.
- * The authentication information to connect to the witness service is bundled
- * into the message.
- */
-static int cifs_swn_send_register_message(struct cifs_swn_reg *swnreg)
-{
- struct sk_buff *skb;
- struct genlmsghdr *hdr;
- enum securityEnum authtype;
- struct sockaddr_storage *addr;
- int ret;
-
- skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (skb == NULL) {
- ret = -ENOMEM;
- goto fail;
- }
-
- hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_REGISTER);
- if (hdr == NULL) {
- ret = -ENOMEM;
- goto nlmsg_fail;
- }
-
- ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id);
- if (ret < 0)
- goto nlmsg_fail;
-
- ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name);
- if (ret < 0)
- goto nlmsg_fail;
-
- ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name);
- if (ret < 0)
- goto nlmsg_fail;
-
- /*
- * If there is an address stored use it instead of the server address, because we are
- * in the process of reconnecting to it after a share has been moved or we have been
- * told to switch to it (client move message). In these cases we unregister from the
- * server address and register to the new address when we receive the notification.
- */
- if (swnreg->tcon->ses->server->use_swn_dstaddr)
- addr = &swnreg->tcon->ses->server->swn_dstaddr;
- else
- addr = &swnreg->tcon->ses->server->dstaddr;
-
- ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage), addr);
- if (ret < 0)
- goto nlmsg_fail;
-
- if (swnreg->net_name_notify) {
- ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY);
- if (ret < 0)
- goto nlmsg_fail;
- }
-
- if (swnreg->share_name_notify) {
- ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY);
- if (ret < 0)
- goto nlmsg_fail;
- }
-
- if (swnreg->ip_notify) {
- ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY);
- if (ret < 0)
- goto nlmsg_fail;
- }
-
- authtype = cifs_select_sectype(swnreg->tcon->ses->server, swnreg->tcon->ses->sectype);
- switch (authtype) {
- case Kerberos:
- ret = cifs_swn_auth_info_krb(swnreg->tcon, skb);
- if (ret < 0) {
- cifs_dbg(VFS, "%s: Failed to get kerberos auth info: %d\n", __func__, ret);
- goto nlmsg_fail;
- }
- break;
- case NTLMv2:
- case RawNTLMSSP:
- ret = cifs_swn_auth_info_ntlm(swnreg->tcon, skb);
- if (ret < 0) {
- cifs_dbg(VFS, "%s: Failed to get NTLM auth info: %d\n", __func__, ret);
- goto nlmsg_fail;
- }
- break;
- default:
- cifs_dbg(VFS, "%s: secType %d not supported!\n", __func__, authtype);
- ret = -EINVAL;
- goto nlmsg_fail;
- }
-
- genlmsg_end(skb, hdr);
- genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC);
-
- cifs_dbg(FYI, "%s: Message to register for network name %s with id %d sent\n", __func__,
- swnreg->net_name, swnreg->id);
-
- return 0;
-
-nlmsg_fail:
- genlmsg_cancel(skb, hdr);
- nlmsg_free(skb);
-fail:
- return ret;
-}
-
-/*
- * Sends an uregister message to the userspace daemon based on the registration
- */
-static int cifs_swn_send_unregister_message(struct cifs_swn_reg *swnreg)
-{
- struct sk_buff *skb;
- struct genlmsghdr *hdr;
- int ret;
-
- skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (skb == NULL)
- return -ENOMEM;
-
- hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_UNREGISTER);
- if (hdr == NULL) {
- ret = -ENOMEM;
- goto nlmsg_fail;
- }
-
- ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id);
- if (ret < 0)
- goto nlmsg_fail;
-
- ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name);
- if (ret < 0)
- goto nlmsg_fail;
-
- ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name);
- if (ret < 0)
- goto nlmsg_fail;
-
- ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage),
- &swnreg->tcon->ses->server->dstaddr);
- if (ret < 0)
- goto nlmsg_fail;
-
- if (swnreg->net_name_notify) {
- ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY);
- if (ret < 0)
- goto nlmsg_fail;
- }
-
- if (swnreg->share_name_notify) {
- ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY);
- if (ret < 0)
- goto nlmsg_fail;
- }
-
- if (swnreg->ip_notify) {
- ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY);
- if (ret < 0)
- goto nlmsg_fail;
- }
-
- genlmsg_end(skb, hdr);
- genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC);
-
- cifs_dbg(FYI, "%s: Message to unregister for network name %s with id %d sent\n", __func__,
- swnreg->net_name, swnreg->id);
-
- return 0;
-
-nlmsg_fail:
- genlmsg_cancel(skb, hdr);
- nlmsg_free(skb);
- return ret;
-}
-
-/*
- * Try to find a matching registration for the tcon's server name and share name.
- * Calls to this function must be protected by cifs_swnreg_idr_mutex.
- * TODO Try to avoid memory allocations
- */
-static struct cifs_swn_reg *cifs_find_swn_reg(struct cifs_tcon *tcon)
-{
- struct cifs_swn_reg *swnreg;
- int id;
- const char *share_name;
- const char *net_name;
-
- net_name = extract_hostname(tcon->tree_name);
- if (IS_ERR(net_name)) {
- int ret;
-
- ret = PTR_ERR(net_name);
- cifs_dbg(VFS, "%s: failed to extract host name from target '%s': %d\n",
- __func__, tcon->tree_name, ret);
- return ERR_PTR(-EINVAL);
- }
-
- share_name = extract_sharename(tcon->tree_name);
- if (IS_ERR(share_name)) {
- int ret;
-
- ret = PTR_ERR(share_name);
- cifs_dbg(VFS, "%s: failed to extract share name from target '%s': %d\n",
- __func__, tcon->tree_name, ret);
- kfree(net_name);
- return ERR_PTR(-EINVAL);
- }
-
- idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
- if (strcasecmp(swnreg->net_name, net_name) != 0
- || strcasecmp(swnreg->share_name, share_name) != 0) {
- continue;
- }
-
- cifs_dbg(FYI, "Existing swn registration for %s:%s found\n", swnreg->net_name,
- swnreg->share_name);
-
- kfree(net_name);
- kfree(share_name);
-
- return swnreg;
- }
-
- kfree(net_name);
- kfree(share_name);
-
- return ERR_PTR(-EEXIST);
-}
-
-/*
- * Get a registration for the tcon's server and share name, allocating a new one if it does not
- * exists
- */
-static struct cifs_swn_reg *cifs_get_swn_reg(struct cifs_tcon *tcon)
-{
- struct cifs_swn_reg *reg = NULL;
- int ret;
-
- mutex_lock(&cifs_swnreg_idr_mutex);
-
- /* Check if we are already registered for this network and share names */
- reg = cifs_find_swn_reg(tcon);
- if (!IS_ERR(reg)) {
- kref_get(®->ref_count);
- mutex_unlock(&cifs_swnreg_idr_mutex);
- return reg;
- } else if (PTR_ERR(reg) != -EEXIST) {
- mutex_unlock(&cifs_swnreg_idr_mutex);
- return reg;
- }
-
- reg = kmalloc(sizeof(struct cifs_swn_reg), GFP_ATOMIC);
- if (reg == NULL) {
- mutex_unlock(&cifs_swnreg_idr_mutex);
- return ERR_PTR(-ENOMEM);
- }
-
- kref_init(®->ref_count);
-
- reg->id = idr_alloc(&cifs_swnreg_idr, reg, 1, 0, GFP_ATOMIC);
- if (reg->id < 0) {
- cifs_dbg(FYI, "%s: failed to allocate registration id\n", __func__);
- ret = reg->id;
- goto fail;
- }
-
- reg->net_name = extract_hostname(tcon->tree_name);
- if (IS_ERR(reg->net_name)) {
- ret = PTR_ERR(reg->net_name);
- cifs_dbg(VFS, "%s: failed to extract host name from target: %d\n", __func__, ret);
- goto fail_idr;
- }
-
- reg->share_name = extract_sharename(tcon->tree_name);
- if (IS_ERR(reg->share_name)) {
- ret = PTR_ERR(reg->share_name);
- cifs_dbg(VFS, "%s: failed to extract share name from target: %d\n", __func__, ret);
- goto fail_net_name;
- }
-
- reg->net_name_notify = true;
- reg->share_name_notify = true;
- reg->ip_notify = (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT);
-
- reg->tcon = tcon;
-
- mutex_unlock(&cifs_swnreg_idr_mutex);
-
- return reg;
-
-fail_net_name:
- kfree(reg->net_name);
-fail_idr:
- idr_remove(&cifs_swnreg_idr, reg->id);
-fail:
- kfree(reg);
- mutex_unlock(&cifs_swnreg_idr_mutex);
- return ERR_PTR(ret);
-}
-
-static void cifs_swn_reg_release(struct kref *ref)
-{
- struct cifs_swn_reg *swnreg = container_of(ref, struct cifs_swn_reg, ref_count);
- int ret;
-
- ret = cifs_swn_send_unregister_message(swnreg);
- if (ret < 0)
- cifs_dbg(VFS, "%s: Failed to send unregister message: %d\n", __func__, ret);
-
- idr_remove(&cifs_swnreg_idr, swnreg->id);
- kfree(swnreg->net_name);
- kfree(swnreg->share_name);
- kfree(swnreg);
-}
-
-static void cifs_put_swn_reg(struct cifs_swn_reg *swnreg)
-{
- mutex_lock(&cifs_swnreg_idr_mutex);
- kref_put(&swnreg->ref_count, cifs_swn_reg_release);
- mutex_unlock(&cifs_swnreg_idr_mutex);
-}
-
-static int cifs_swn_resource_state_changed(struct cifs_swn_reg *swnreg, const char *name, int state)
-{
- switch (state) {
- case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE:
- cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name);
- cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
- break;
- case CIFS_SWN_RESOURCE_STATE_AVAILABLE:
- cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name);
- cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
- break;
- case CIFS_SWN_RESOURCE_STATE_UNKNOWN:
- cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name);
- break;
- }
- return 0;
-}
-
-static bool cifs_sockaddr_equal(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2)
-{
- if (addr1->ss_family != addr2->ss_family)
- return false;
-
- if (addr1->ss_family == AF_INET) {
- return (memcmp(&((const struct sockaddr_in *)addr1)->sin_addr,
- &((const struct sockaddr_in *)addr2)->sin_addr,
- sizeof(struct in_addr)) == 0);
- }
-
- if (addr1->ss_family == AF_INET6) {
- return (memcmp(&((const struct sockaddr_in6 *)addr1)->sin6_addr,
- &((const struct sockaddr_in6 *)addr2)->sin6_addr,
- sizeof(struct in6_addr)) == 0);
- }
-
- return false;
-}
-
-static int cifs_swn_store_swn_addr(const struct sockaddr_storage *new,
- const struct sockaddr_storage *old,
- struct sockaddr_storage *dst)
-{
- __be16 port = cpu_to_be16(CIFS_PORT);
-
- if (old->ss_family == AF_INET) {
- struct sockaddr_in *ipv4 = (struct sockaddr_in *)old;
-
- port = ipv4->sin_port;
- } else if (old->ss_family == AF_INET6) {
- struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)old;
-
- port = ipv6->sin6_port;
- }
-
- if (new->ss_family == AF_INET) {
- struct sockaddr_in *ipv4 = (struct sockaddr_in *)new;
-
- ipv4->sin_port = port;
- } else if (new->ss_family == AF_INET6) {
- struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)new;
-
- ipv6->sin6_port = port;
- }
-
- *dst = *new;
-
- return 0;
-}
-
-static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *addr)
-{
- int ret = 0;
-
- /* Store the reconnect address */
- cifs_server_lock(tcon->ses->server);
- if (cifs_sockaddr_equal(&tcon->ses->server->dstaddr, addr))
- goto unlock;
-
- ret = cifs_swn_store_swn_addr(addr, &tcon->ses->server->dstaddr,
- &tcon->ses->server->swn_dstaddr);
- if (ret < 0) {
- cifs_dbg(VFS, "%s: failed to store address: %d\n", __func__, ret);
- goto unlock;
- }
- tcon->ses->server->use_swn_dstaddr = true;
-
- /*
- * Unregister to stop receiving notifications for the old IP address.
- */
- ret = cifs_swn_unregister(tcon);
- if (ret < 0) {
- cifs_dbg(VFS, "%s: Failed to unregister for witness notifications: %d\n",
- __func__, ret);
- goto unlock;
- }
-
- /*
- * And register to receive notifications for the new IP address now that we have
- * stored the new address.
- */
- ret = cifs_swn_register(tcon);
- if (ret < 0) {
- cifs_dbg(VFS, "%s: Failed to register for witness notifications: %d\n",
- __func__, ret);
- goto unlock;
- }
-
- cifs_signal_cifsd_for_reconnect(tcon->ses->server, false);
-
-unlock:
- cifs_server_unlock(tcon->ses->server);
-
- return ret;
-}
-
-static int cifs_swn_client_move(struct cifs_swn_reg *swnreg, struct sockaddr_storage *addr)
-{
- struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr;
- struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)addr;
-
- if (addr->ss_family == AF_INET)
- cifs_dbg(FYI, "%s: move to %pI4\n", __func__, &ipv4->sin_addr);
- else if (addr->ss_family == AF_INET6)
- cifs_dbg(FYI, "%s: move to %pI6\n", __func__, &ipv6->sin6_addr);
-
- return cifs_swn_reconnect(swnreg->tcon, addr);
-}
-
-int cifs_swn_notify(struct sk_buff *skb, struct genl_info *info)
-{
- struct cifs_swn_reg *swnreg;
- char name[256];
- int type;
-
- if (info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]) {
- int swnreg_id;
-
- swnreg_id = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]);
- mutex_lock(&cifs_swnreg_idr_mutex);
- swnreg = idr_find(&cifs_swnreg_idr, swnreg_id);
- mutex_unlock(&cifs_swnreg_idr_mutex);
- if (swnreg == NULL) {
- cifs_dbg(FYI, "%s: registration id %d not found\n", __func__, swnreg_id);
- return -EINVAL;
- }
- } else {
- cifs_dbg(FYI, "%s: missing registration id attribute\n", __func__);
- return -EINVAL;
- }
-
- if (info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]) {
- type = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]);
- } else {
- cifs_dbg(FYI, "%s: missing notification type attribute\n", __func__);
- return -EINVAL;
- }
-
- switch (type) {
- case CIFS_SWN_NOTIFICATION_RESOURCE_CHANGE: {
- int state;
-
- if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME]) {
- nla_strscpy(name, info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME],
- sizeof(name));
- } else {
- cifs_dbg(FYI, "%s: missing resource name attribute\n", __func__);
- return -EINVAL;
- }
- if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]) {
- state = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]);
- } else {
- cifs_dbg(FYI, "%s: missing resource state attribute\n", __func__);
- return -EINVAL;
- }
- return cifs_swn_resource_state_changed(swnreg, name, state);
- }
- case CIFS_SWN_NOTIFICATION_CLIENT_MOVE: {
- struct sockaddr_storage addr;
-
- if (info->attrs[CIFS_GENL_ATTR_SWN_IP]) {
- nla_memcpy(&addr, info->attrs[CIFS_GENL_ATTR_SWN_IP], sizeof(addr));
- } else {
- cifs_dbg(FYI, "%s: missing IP address attribute\n", __func__);
- return -EINVAL;
- }
- return cifs_swn_client_move(swnreg, &addr);
- }
- default:
- cifs_dbg(FYI, "%s: unknown notification type %d\n", __func__, type);
- break;
- }
-
- return 0;
-}
-
-int cifs_swn_register(struct cifs_tcon *tcon)
-{
- struct cifs_swn_reg *swnreg;
- int ret;
-
- swnreg = cifs_get_swn_reg(tcon);
- if (IS_ERR(swnreg))
- return PTR_ERR(swnreg);
-
- ret = cifs_swn_send_register_message(swnreg);
- if (ret < 0) {
- cifs_dbg(VFS, "%s: Failed to send swn register message: %d\n", __func__, ret);
- /* Do not put the swnreg or return error, the echo task will retry */
- }
-
- return 0;
-}
-
-int cifs_swn_unregister(struct cifs_tcon *tcon)
-{
- struct cifs_swn_reg *swnreg;
-
- mutex_lock(&cifs_swnreg_idr_mutex);
-
- swnreg = cifs_find_swn_reg(tcon);
- if (IS_ERR(swnreg)) {
- mutex_unlock(&cifs_swnreg_idr_mutex);
- return PTR_ERR(swnreg);
- }
-
- mutex_unlock(&cifs_swnreg_idr_mutex);
-
- cifs_put_swn_reg(swnreg);
-
- return 0;
-}
-
-void cifs_swn_dump(struct seq_file *m)
-{
- struct cifs_swn_reg *swnreg;
- struct sockaddr_in *sa;
- struct sockaddr_in6 *sa6;
- int id;
-
- seq_puts(m, "Witness registrations:");
-
- mutex_lock(&cifs_swnreg_idr_mutex);
- idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
- seq_printf(m, "\nId: %u Refs: %u Network name: '%s'%s Share name: '%s'%s Ip address: ",
- id, kref_read(&swnreg->ref_count),
- swnreg->net_name, swnreg->net_name_notify ? "(y)" : "(n)",
- swnreg->share_name, swnreg->share_name_notify ? "(y)" : "(n)");
- switch (swnreg->tcon->ses->server->dstaddr.ss_family) {
- case AF_INET:
- sa = (struct sockaddr_in *) &swnreg->tcon->ses->server->dstaddr;
- seq_printf(m, "%pI4", &sa->sin_addr.s_addr);
- break;
- case AF_INET6:
- sa6 = (struct sockaddr_in6 *) &swnreg->tcon->ses->server->dstaddr;
- seq_printf(m, "%pI6", &sa6->sin6_addr.s6_addr);
- if (sa6->sin6_scope_id)
- seq_printf(m, "%%%u", sa6->sin6_scope_id);
- break;
- default:
- seq_puts(m, "(unknown)");
- }
- seq_printf(m, "%s", swnreg->ip_notify ? "(y)" : "(n)");
- }
- mutex_unlock(&cifs_swnreg_idr_mutex);
- seq_puts(m, "\n");
-}
-
-void cifs_swn_check(void)
-{
- struct cifs_swn_reg *swnreg;
- int id;
- int ret;
-
- mutex_lock(&cifs_swnreg_idr_mutex);
- idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
- ret = cifs_swn_send_register_message(swnreg);
- if (ret < 0)
- cifs_dbg(FYI, "%s: Failed to send register message: %d\n", __func__, ret);
- }
- mutex_unlock(&cifs_swnreg_idr_mutex);
-}
diff --git a/fs/cifs/cifs_swn.h b/fs/cifs/cifs_swn.h
deleted file mode 100644
index 8a9d2a5c9077..000000000000
--- a/fs/cifs/cifs_swn.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Witness Service client for CIFS
- *
- * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
- */
-
-#ifndef _CIFS_SWN_H
-#define _CIFS_SWN_H
-#include "cifsglob.h"
-
-struct cifs_tcon;
-struct sk_buff;
-struct genl_info;
-
-#ifdef CONFIG_CIFS_SWN_UPCALL
-extern int cifs_swn_register(struct cifs_tcon *tcon);
-
-extern int cifs_swn_unregister(struct cifs_tcon *tcon);
-
-extern int cifs_swn_notify(struct sk_buff *skb, struct genl_info *info);
-
-extern void cifs_swn_dump(struct seq_file *m);
-
-extern void cifs_swn_check(void);
-
-static inline bool cifs_swn_set_server_dstaddr(struct TCP_Server_Info *server)
-{
- if (server->use_swn_dstaddr) {
- server->dstaddr = server->swn_dstaddr;
- return true;
- }
- return false;
-}
-
-static inline void cifs_swn_reset_server_dstaddr(struct TCP_Server_Info *server)
-{
- server->use_swn_dstaddr = false;
-}
-
-#else
-
-static inline int cifs_swn_register(struct cifs_tcon *tcon) { return 0; }
-static inline int cifs_swn_unregister(struct cifs_tcon *tcon) { return 0; }
-static inline int cifs_swn_notify(struct sk_buff *s, struct genl_info *i) { return 0; }
-static inline void cifs_swn_dump(struct seq_file *m) {}
-static inline void cifs_swn_check(void) {}
-static inline bool cifs_swn_set_server_dstaddr(struct TCP_Server_Info *server) { return false; }
-static inline void cifs_swn_reset_server_dstaddr(struct TCP_Server_Info *server) {}
-
-#endif /* CONFIG_CIFS_SWN_UPCALL */
-#endif /* _CIFS_SWN_H */
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
deleted file mode 100644
index e7582dd79179..000000000000
--- a/fs/cifs/cifs_unicode.c
+++ /dev/null
@@ -1,632 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * Copyright (c) International Business Machines Corp., 2000,2009
- * Modified by Steve French (sfrench@us.ibm.com)
- */
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "cifs_fs_sb.h"
-#include "cifs_unicode.h"
-#include "cifs_uniupr.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifs_debug.h"
-
-int cifs_remap(struct cifs_sb_info *cifs_sb)
-{
- int map_type;
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
- map_type = SFM_MAP_UNI_RSVD;
- else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
- map_type = SFU_MAP_UNI_RSVD;
- else
- map_type = NO_MAP_UNI_RSVD;
-
- return map_type;
-}
-
-/* Convert character using the SFU - "Services for Unix" remapping range */
-static bool
-convert_sfu_char(const __u16 src_char, char *target)
-{
- /*
- * BB: Cannot handle remapping UNI_SLASH until all the calls to
- * build_path_from_dentry are modified, as they use slash as
- * separator.
- */
- switch (src_char) {
- case UNI_COLON:
- *target = ':';
- break;
- case UNI_ASTERISK:
- *target = '*';
- break;
- case UNI_QUESTION:
- *target = '?';
- break;
- case UNI_PIPE:
- *target = '|';
- break;
- case UNI_GRTRTHAN:
- *target = '>';
- break;
- case UNI_LESSTHAN:
- *target = '<';
- break;
- default:
- return false;
- }
- return true;
-}
-
-/* Convert character using the SFM - "Services for Mac" remapping range */
-static bool
-convert_sfm_char(const __u16 src_char, char *target)
-{
- if (src_char >= 0xF001 && src_char <= 0xF01F) {
- *target = src_char - 0xF000;
- return true;
- }
- switch (src_char) {
- case SFM_COLON:
- *target = ':';
- break;
- case SFM_DOUBLEQUOTE:
- *target = '"';
- break;
- case SFM_ASTERISK:
- *target = '*';
- break;
- case SFM_QUESTION:
- *target = '?';
- break;
- case SFM_PIPE:
- *target = '|';
- break;
- case SFM_GRTRTHAN:
- *target = '>';
- break;
- case SFM_LESSTHAN:
- *target = '<';
- break;
- case SFM_SPACE:
- *target = ' ';
- break;
- case SFM_PERIOD:
- *target = '.';
- break;
- default:
- return false;
- }
- return true;
-}
-
-
-/*
- * cifs_mapchar - convert a host-endian char to proper char in codepage
- * @target - where converted character should be copied
- * @src_char - 2 byte host-endian source character
- * @cp - codepage to which character should be converted
- * @map_type - How should the 7 NTFS/SMB reserved characters be mapped to UCS2?
- *
- * This function handles the conversion of a single character. It is the
- * responsibility of the caller to ensure that the target buffer is large
- * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
- */
-static int
-cifs_mapchar(char *target, const __u16 *from, const struct nls_table *cp,
- int maptype)
-{
- int len = 1;
- __u16 src_char;
-
- src_char = *from;
-
- if ((maptype == SFM_MAP_UNI_RSVD) && convert_sfm_char(src_char, target))
- return len;
- else if ((maptype == SFU_MAP_UNI_RSVD) &&
- convert_sfu_char(src_char, target))
- return len;
-
- /* if character not one of seven in special remap set */
- len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE);
- if (len <= 0)
- goto surrogate_pair;
-
- return len;
-
-surrogate_pair:
- /* convert SURROGATE_PAIR and IVS */
- if (strcmp(cp->charset, "utf8"))
- goto unknown;
- len = utf16s_to_utf8s(from, 3, UTF16_LITTLE_ENDIAN, target, 6);
- if (len <= 0)
- goto unknown;
- return len;
-
-unknown:
- *target = '?';
- len = 1;
- return len;
-}
-
-/*
- * cifs_from_utf16 - convert utf16le string to local charset
- * @to - destination buffer
- * @from - source buffer
- * @tolen - destination buffer size (in bytes)
- * @fromlen - source buffer size (in bytes)
- * @codepage - codepage to which characters should be converted
- * @mapchar - should characters be remapped according to the mapchars option?
- *
- * Convert a little-endian utf16le string (as sent by the server) to a string
- * in the provided codepage. The tolen and fromlen parameters are to ensure
- * that the code doesn't walk off of the end of the buffer (which is always
- * a danger if the alignment of the source buffer is off). The destination
- * string is always properly null terminated and fits in the destination
- * buffer. Returns the length of the destination string in bytes (including
- * null terminator).
- *
- * Note that some windows versions actually send multiword UTF-16 characters
- * instead of straight UTF16-2. The linux nls routines however aren't able to
- * deal with those characters properly. In the event that we get some of
- * those characters, they won't be translated properly.
- */
-int
-cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
- const struct nls_table *codepage, int map_type)
-{
- int i, charlen, safelen;
- int outlen = 0;
- int nullsize = nls_nullsize(codepage);
- int fromwords = fromlen / 2;
- char tmp[NLS_MAX_CHARSET_SIZE];
- __u16 ftmp[3]; /* ftmp[3] = 3array x 2bytes = 6bytes UTF-16 */
-
- /*
- * because the chars can be of varying widths, we need to take care
- * not to overflow the destination buffer when we get close to the
- * end of it. Until we get to this offset, we don't need to check
- * for overflow however.
- */
- safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
-
- for (i = 0; i < fromwords; i++) {
- ftmp[0] = get_unaligned_le16(&from[i]);
- if (ftmp[0] == 0)
- break;
- if (i + 1 < fromwords)
- ftmp[1] = get_unaligned_le16(&from[i + 1]);
- else
- ftmp[1] = 0;
- if (i + 2 < fromwords)
- ftmp[2] = get_unaligned_le16(&from[i + 2]);
- else
- ftmp[2] = 0;
-
- /*
- * check to see if converting this character might make the
- * conversion bleed into the null terminator
- */
- if (outlen >= safelen) {
- charlen = cifs_mapchar(tmp, ftmp, codepage, map_type);
- if ((outlen + charlen) > (tolen - nullsize))
- break;
- }
-
- /* put converted char into 'to' buffer */
- charlen = cifs_mapchar(&to[outlen], ftmp, codepage, map_type);
- outlen += charlen;
-
- /* charlen (=bytes of UTF-8 for 1 character)
- * 4bytes UTF-8(surrogate pair) is charlen=4
- * (4bytes UTF-16 code)
- * 7-8bytes UTF-8(IVS) is charlen=3+4 or 4+4
- * (2 UTF-8 pairs divided to 2 UTF-16 pairs) */
- if (charlen == 4)
- i++;
- else if (charlen >= 5)
- /* 5-6bytes UTF-8 */
- i += 2;
- }
-
- /* properly null-terminate string */
- for (i = 0; i < nullsize; i++)
- to[outlen++] = 0;
-
- return outlen;
-}
-
-/*
- * NAME: cifs_strtoUTF16()
- *
- * FUNCTION: Convert character string to unicode string
- *
- */
-int
-cifs_strtoUTF16(__le16 *to, const char *from, int len,
- const struct nls_table *codepage)
-{
- int charlen;
- int i;
- wchar_t wchar_to; /* needed to quiet sparse */
-
- /* special case for utf8 to handle no plane0 chars */
- if (!strcmp(codepage->charset, "utf8")) {
- /*
- * convert utf8 -> utf16, we assume we have enough space
- * as caller should have assumed conversion does not overflow
- * in destination len is length in wchar_t units (16bits)
- */
- i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN,
- (wchar_t *) to, len);
-
- /* if success terminate and exit */
- if (i >= 0)
- goto success;
- /*
- * if fails fall back to UCS encoding as this
- * function should not return negative values
- * currently can fail only if source contains
- * invalid encoded characters
- */
- }
-
- for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
- charlen = codepage->char2uni(from, len, &wchar_to);
- if (charlen < 1) {
- cifs_dbg(VFS, "strtoUTF16: char2uni of 0x%x returned %d\n",
- *from, charlen);
- /* A question mark */
- wchar_to = 0x003f;
- charlen = 1;
- }
- put_unaligned_le16(wchar_to, &to[i]);
- }
-
-success:
- put_unaligned_le16(0, &to[i]);
- return i;
-}
-
-/*
- * cifs_utf16_bytes - how long will a string be after conversion?
- * @utf16 - pointer to input string
- * @maxbytes - don't go past this many bytes of input string
- * @codepage - destination codepage
- *
- * Walk a utf16le string and return the number of bytes that the string will
- * be after being converted to the given charset, not including any null
- * termination required. Don't walk past maxbytes in the source buffer.
- */
-int
-cifs_utf16_bytes(const __le16 *from, int maxbytes,
- const struct nls_table *codepage)
-{
- int i;
- int charlen, outlen = 0;
- int maxwords = maxbytes / 2;
- char tmp[NLS_MAX_CHARSET_SIZE];
- __u16 ftmp[3];
-
- for (i = 0; i < maxwords; i++) {
- ftmp[0] = get_unaligned_le16(&from[i]);
- if (ftmp[0] == 0)
- break;
- if (i + 1 < maxwords)
- ftmp[1] = get_unaligned_le16(&from[i + 1]);
- else
- ftmp[1] = 0;
- if (i + 2 < maxwords)
- ftmp[2] = get_unaligned_le16(&from[i + 2]);
- else
- ftmp[2] = 0;
-
- charlen = cifs_mapchar(tmp, ftmp, codepage, NO_MAP_UNI_RSVD);
- outlen += charlen;
- }
-
- return outlen;
-}
-
-/*
- * cifs_strndup_from_utf16 - copy a string from wire format to the local
- * codepage
- * @src - source string
- * @maxlen - don't walk past this many bytes in the source string
- * @is_unicode - is this a unicode string?
- * @codepage - destination codepage
- *
- * Take a string given by the server, convert it to the local codepage and
- * put it in a new buffer. Returns a pointer to the new string or NULL on
- * error.
- */
-char *
-cifs_strndup_from_utf16(const char *src, const int maxlen,
- const bool is_unicode, const struct nls_table *codepage)
-{
- int len;
- char *dst;
-
- if (is_unicode) {
- len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage);
- len += nls_nullsize(codepage);
- dst = kmalloc(len, GFP_KERNEL);
- if (!dst)
- return NULL;
- cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
- NO_MAP_UNI_RSVD);
- } else {
- dst = kstrndup(src, maxlen, GFP_KERNEL);
- }
-
- return dst;
-}
-
-static __le16 convert_to_sfu_char(char src_char)
-{
- __le16 dest_char;
-
- switch (src_char) {
- case ':':
- dest_char = cpu_to_le16(UNI_COLON);
- break;
- case '*':
- dest_char = cpu_to_le16(UNI_ASTERISK);
- break;
- case '?':
- dest_char = cpu_to_le16(UNI_QUESTION);
- break;
- case '<':
- dest_char = cpu_to_le16(UNI_LESSTHAN);
- break;
- case '>':
- dest_char = cpu_to_le16(UNI_GRTRTHAN);
- break;
- case '|':
- dest_char = cpu_to_le16(UNI_PIPE);
- break;
- default:
- dest_char = 0;
- }
-
- return dest_char;
-}
-
-static __le16 convert_to_sfm_char(char src_char, bool end_of_string)
-{
- __le16 dest_char;
-
- if (src_char >= 0x01 && src_char <= 0x1F) {
- dest_char = cpu_to_le16(src_char + 0xF000);
- return dest_char;
- }
- switch (src_char) {
- case ':':
- dest_char = cpu_to_le16(SFM_COLON);
- break;
- case '"':
- dest_char = cpu_to_le16(SFM_DOUBLEQUOTE);
- break;
- case '*':
- dest_char = cpu_to_le16(SFM_ASTERISK);
- break;
- case '?':
- dest_char = cpu_to_le16(SFM_QUESTION);
- break;
- case '<':
- dest_char = cpu_to_le16(SFM_LESSTHAN);
- break;
- case '>':
- dest_char = cpu_to_le16(SFM_GRTRTHAN);
- break;
- case '|':
- dest_char = cpu_to_le16(SFM_PIPE);
- break;
- case '.':
- if (end_of_string)
- dest_char = cpu_to_le16(SFM_PERIOD);
- else
- dest_char = 0;
- break;
- case ' ':
- if (end_of_string)
- dest_char = cpu_to_le16(SFM_SPACE);
- else
- dest_char = 0;
- break;
- default:
- dest_char = 0;
- }
-
- return dest_char;
-}
-
-/*
- * Convert 16 bit Unicode pathname to wire format from string in current code
- * page. Conversion may involve remapping up the six characters that are
- * only legal in POSIX-like OS (if they are present in the string). Path
- * names are little endian 16 bit Unicode on the wire
- */
-int
-cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
- const struct nls_table *cp, int map_chars)
-{
- int i, charlen;
- int j = 0;
- char src_char;
- __le16 dst_char;
- wchar_t tmp;
- wchar_t *wchar_to; /* UTF-16 */
- int ret;
- unicode_t u;
-
- if (map_chars == NO_MAP_UNI_RSVD)
- return cifs_strtoUTF16(target, source, PATH_MAX, cp);
-
- wchar_to = kzalloc(6, GFP_KERNEL);
-
- for (i = 0; i < srclen; j++) {
- src_char = source[i];
- charlen = 1;
-
- /* check if end of string */
- if (src_char == 0)
- goto ctoUTF16_out;
-
- /* see if we must remap this char */
- if (map_chars == SFU_MAP_UNI_RSVD)
- dst_char = convert_to_sfu_char(src_char);
- else if (map_chars == SFM_MAP_UNI_RSVD) {
- bool end_of_string;
-
- /**
- * Remap spaces and periods found at the end of every
- * component of the path. The special cases of '.' and
- * '..' do not need to be dealt with explicitly because
- * they are addressed in namei.c:link_path_walk().
- **/
- if ((i == srclen - 1) || (source[i+1] == '\\'))
- end_of_string = true;
- else
- end_of_string = false;
-
- dst_char = convert_to_sfm_char(src_char, end_of_string);
- } else
- dst_char = 0;
- /*
- * FIXME: We can not handle remapping backslash (UNI_SLASH)
- * until all the calls to build_path_from_dentry are modified,
- * as they use backslash as separator.
- */
- if (dst_char == 0) {
- charlen = cp->char2uni(source + i, srclen - i, &tmp);
- dst_char = cpu_to_le16(tmp);
-
- /*
- * if no match, use question mark, which at least in
- * some cases serves as wild card
- */
- if (charlen > 0)
- goto ctoUTF16;
-
- /* convert SURROGATE_PAIR */
- if (strcmp(cp->charset, "utf8") || !wchar_to)
- goto unknown;
- if (*(source + i) & 0x80) {
- charlen = utf8_to_utf32(source + i, 6, &u);
- if (charlen < 0)
- goto unknown;
- } else
- goto unknown;
- ret = utf8s_to_utf16s(source + i, charlen,
- UTF16_LITTLE_ENDIAN,
- wchar_to, 6);
- if (ret < 0)
- goto unknown;
-
- i += charlen;
- dst_char = cpu_to_le16(*wchar_to);
- if (charlen <= 3)
- /* 1-3bytes UTF-8 to 2bytes UTF-16 */
- put_unaligned(dst_char, &target[j]);
- else if (charlen == 4) {
- /* 4bytes UTF-8(surrogate pair) to 4bytes UTF-16
- * 7-8bytes UTF-8(IVS) divided to 2 UTF-16
- * (charlen=3+4 or 4+4) */
- put_unaligned(dst_char, &target[j]);
- dst_char = cpu_to_le16(*(wchar_to + 1));
- j++;
- put_unaligned(dst_char, &target[j]);
- } else if (charlen >= 5) {
- /* 5-6bytes UTF-8 to 6bytes UTF-16 */
- put_unaligned(dst_char, &target[j]);
- dst_char = cpu_to_le16(*(wchar_to + 1));
- j++;
- put_unaligned(dst_char, &target[j]);
- dst_char = cpu_to_le16(*(wchar_to + 2));
- j++;
- put_unaligned(dst_char, &target[j]);
- }
- continue;
-
-unknown:
- dst_char = cpu_to_le16(0x003f);
- charlen = 1;
- }
-
-ctoUTF16:
- /*
- * character may take more than one byte in the source string,
- * but will take exactly two bytes in the target string
- */
- i += charlen;
- put_unaligned(dst_char, &target[j]);
- }
-
-ctoUTF16_out:
- put_unaligned(0, &target[j]); /* Null terminate target unicode string */
- kfree(wchar_to);
- return j;
-}
-
-/*
- * cifs_local_to_utf16_bytes - how long will a string be after conversion?
- * @from - pointer to input string
- * @maxbytes - don't go past this many bytes of input string
- * @codepage - source codepage
- *
- * Walk a string and return the number of bytes that the string will
- * be after being converted to the given charset, not including any null
- * termination required. Don't walk past maxbytes in the source buffer.
- */
-
-static int
-cifs_local_to_utf16_bytes(const char *from, int len,
- const struct nls_table *codepage)
-{
- int charlen;
- int i;
- wchar_t wchar_to;
-
- for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
- charlen = codepage->char2uni(from, len, &wchar_to);
- /* Failed conversion defaults to a question mark */
- if (charlen < 1)
- charlen = 1;
- }
- return 2 * i; /* UTF16 characters are two bytes */
-}
-
-/*
- * cifs_strndup_to_utf16 - copy a string to wire format from the local codepage
- * @src - source string
- * @maxlen - don't walk past this many bytes in the source string
- * @utf16_len - the length of the allocated string in bytes (including null)
- * @cp - source codepage
- * @remap - map special chars
- *
- * Take a string convert it from the local codepage to UTF16 and
- * put it in a new buffer. Returns a pointer to the new string or NULL on
- * error.
- */
-__le16 *
-cifs_strndup_to_utf16(const char *src, const int maxlen, int *utf16_len,
- const struct nls_table *cp, int remap)
-{
- int len;
- __le16 *dst;
-
- len = cifs_local_to_utf16_bytes(src, maxlen, cp);
- len += 2; /* NULL */
- dst = kmalloc(len, GFP_KERNEL);
- if (!dst) {
- *utf16_len = 0;
- return NULL;
- }
- cifsConvertToUTF16(dst, src, strlen(src), cp, remap);
- *utf16_len = len;
- return dst;
-}
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
deleted file mode 100644
index 80b3d845419f..000000000000
--- a/fs/cifs/cifs_unicode.h
+++ /dev/null
@@ -1,404 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * cifs_unicode: Unicode kernel case support
- *
- * Function:
- * Convert a unicode character to upper or lower case using
- * compressed tables.
- *
- * Copyright (c) International Business Machines Corp., 2000,2009
- *
- * Notes:
- * These APIs are based on the C library functions. The semantics
- * should match the C functions but with expanded size operands.
- *
- * The upper/lower functions are based on a table created by mkupr.
- * This is a compressed table of upper and lower case conversion.
- */
-#ifndef _CIFS_UNICODE_H
-#define _CIFS_UNICODE_H
-
-#include <asm/byteorder.h>
-#include <linux/types.h>
-#include <linux/nls.h>
-
-#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
-
-/*
- * Windows maps these to the user defined 16 bit Unicode range since they are
- * reserved symbols (along with \ and /), otherwise illegal to store
- * in filenames in NTFS
- */
-#define UNI_ASTERISK (__u16) ('*' + 0xF000)
-#define UNI_QUESTION (__u16) ('?' + 0xF000)
-#define UNI_COLON (__u16) (':' + 0xF000)
-#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
-#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
-#define UNI_PIPE (__u16) ('|' + 0xF000)
-#define UNI_SLASH (__u16) ('\\' + 0xF000)
-
-/*
- * Macs use an older "SFM" mapping of the symbols above. Fortunately it does
- * not conflict (although almost does) with the mapping above.
- */
-
-#define SFM_DOUBLEQUOTE ((__u16) 0xF020)
-#define SFM_ASTERISK ((__u16) 0xF021)
-#define SFM_QUESTION ((__u16) 0xF025)
-#define SFM_COLON ((__u16) 0xF022)
-#define SFM_GRTRTHAN ((__u16) 0xF024)
-#define SFM_LESSTHAN ((__u16) 0xF023)
-#define SFM_PIPE ((__u16) 0xF027)
-#define SFM_SLASH ((__u16) 0xF026)
-#define SFM_SPACE ((__u16) 0xF028)
-#define SFM_PERIOD ((__u16) 0xF029)
-
-/*
- * Mapping mechanism to use when one of the seven reserved characters is
- * encountered. We can only map using one of the mechanisms at a time
- * since otherwise readdir could return directory entries which we would
- * not be able to open
- *
- * NO_MAP_UNI_RSVD = do not perform any remapping of the character
- * SFM_MAP_UNI_RSVD = map reserved characters using SFM scheme (MAC compatible)
- * SFU_MAP_UNI_RSVD = map reserved characters ala SFU ("mapchars" option)
- *
- */
-#define NO_MAP_UNI_RSVD 0
-#define SFM_MAP_UNI_RSVD 1
-#define SFU_MAP_UNI_RSVD 2
-
-/* Just define what we want from uniupr.h. We don't want to define the tables
- * in each source file.
- */
-#ifndef UNICASERANGE_DEFINED
-struct UniCaseRange {
- wchar_t start;
- wchar_t end;
- signed char *table;
-};
-#endif /* UNICASERANGE_DEFINED */
-
-#ifndef UNIUPR_NOUPPER
-extern signed char CifsUniUpperTable[512];
-extern const struct UniCaseRange CifsUniUpperRange[];
-#endif /* UNIUPR_NOUPPER */
-
-#ifndef UNIUPR_NOLOWER
-extern signed char CifsUniLowerTable[512];
-extern const struct UniCaseRange CifsUniLowerRange[];
-#endif /* UNIUPR_NOLOWER */
-
-#ifdef __KERNEL__
-int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
- const struct nls_table *cp, int map_type);
-int cifs_utf16_bytes(const __le16 *from, int maxbytes,
- const struct nls_table *codepage);
-int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *);
-char *cifs_strndup_from_utf16(const char *src, const int maxlen,
- const bool is_unicode,
- const struct nls_table *codepage);
-extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
- const struct nls_table *cp, int mapChars);
-extern int cifs_remap(struct cifs_sb_info *cifs_sb);
-extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen,
- int *utf16_len, const struct nls_table *cp,
- int remap);
-#endif
-
-wchar_t cifs_toupper(wchar_t in);
-
-/*
- * UniStrcat: Concatenate the second string to the first
- *
- * Returns:
- * Address of the first string
- */
-static inline __le16 *
-UniStrcat(__le16 *ucs1, const __le16 *ucs2)
-{
- __le16 *anchor = ucs1; /* save a pointer to start of ucs1 */
-
- while (*ucs1++) ; /* To end of first string */
- ucs1--; /* Return to the null */
- while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
- return anchor;
-}
-
-/*
- * UniStrchr: Find a character in a string
- *
- * Returns:
- * Address of first occurrence of character in string
- * or NULL if the character is not in the string
- */
-static inline wchar_t *
-UniStrchr(const wchar_t *ucs, wchar_t uc)
-{
- while ((*ucs != uc) && *ucs)
- ucs++;
-
- if (*ucs == uc)
- return (wchar_t *) ucs;
- return NULL;
-}
-
-/*
- * UniStrcmp: Compare two strings
- *
- * Returns:
- * < 0: First string is less than second
- * = 0: Strings are equal
- * > 0: First string is greater than second
- */
-static inline int
-UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
-{
- while ((*ucs1 == *ucs2) && *ucs1) {
- ucs1++;
- ucs2++;
- }
- return (int) *ucs1 - (int) *ucs2;
-}
-
-/*
- * UniStrcpy: Copy a string
- */
-static inline wchar_t *
-UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
-{
- wchar_t *anchor = ucs1; /* save the start of result string */
-
- while ((*ucs1++ = *ucs2++)) ;
- return anchor;
-}
-
-/*
- * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
- */
-static inline size_t
-UniStrlen(const wchar_t *ucs1)
-{
- int i = 0;
-
- while (*ucs1++)
- i++;
- return i;
-}
-
-/*
- * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
- * string (length limited)
- */
-static inline size_t
-UniStrnlen(const wchar_t *ucs1, int maxlen)
-{
- int i = 0;
-
- while (*ucs1++) {
- i++;
- if (i >= maxlen)
- break;
- }
- return i;
-}
-
-/*
- * UniStrncat: Concatenate length limited string
- */
-static inline wchar_t *
-UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- wchar_t *anchor = ucs1; /* save pointer to string 1 */
-
- while (*ucs1++) ;
- ucs1--; /* point to null terminator of s1 */
- while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
- ucs1++;
- ucs2++;
- }
- *ucs1 = 0; /* Null terminate the result */
- return (anchor);
-}
-
-/*
- * UniStrncmp: Compare length limited string
- */
-static inline int
-UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- if (!n)
- return 0; /* Null strings are equal */
- while ((*ucs1 == *ucs2) && *ucs1 && --n) {
- ucs1++;
- ucs2++;
- }
- return (int) *ucs1 - (int) *ucs2;
-}
-
-/*
- * UniStrncmp_le: Compare length limited string - native to little-endian
- */
-static inline int
-UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- if (!n)
- return 0; /* Null strings are equal */
- while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
- ucs1++;
- ucs2++;
- }
- return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
-}
-
-/*
- * UniStrncpy: Copy length limited string with pad
- */
-static inline wchar_t *
-UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- wchar_t *anchor = ucs1;
-
- while (n-- && *ucs2) /* Copy the strings */
- *ucs1++ = *ucs2++;
-
- n++;
- while (n--) /* Pad with nulls */
- *ucs1++ = 0;
- return anchor;
-}
-
-/*
- * UniStrncpy_le: Copy length limited string with pad to little-endian
- */
-static inline wchar_t *
-UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- wchar_t *anchor = ucs1;
-
- while (n-- && *ucs2) /* Copy the strings */
- *ucs1++ = __le16_to_cpu(*ucs2++);
-
- n++;
- while (n--) /* Pad with nulls */
- *ucs1++ = 0;
- return anchor;
-}
-
-/*
- * UniStrstr: Find a string in a string
- *
- * Returns:
- * Address of first match found
- * NULL if no matching string is found
- */
-static inline wchar_t *
-UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
-{
- const wchar_t *anchor1 = ucs1;
- const wchar_t *anchor2 = ucs2;
-
- while (*ucs1) {
- if (*ucs1 == *ucs2) {
- /* Partial match found */
- ucs1++;
- ucs2++;
- } else {
- if (!*ucs2) /* Match found */
- return (wchar_t *) anchor1;
- ucs1 = ++anchor1; /* No match */
- ucs2 = anchor2;
- }
- }
-
- if (!*ucs2) /* Both end together */
- return (wchar_t *) anchor1; /* Match found */
- return NULL; /* No match */
-}
-
-#ifndef UNIUPR_NOUPPER
-/*
- * UniToupper: Convert a unicode character to upper case
- */
-static inline wchar_t
-UniToupper(register wchar_t uc)
-{
- register const struct UniCaseRange *rp;
-
- if (uc < sizeof(CifsUniUpperTable)) {
- /* Latin characters */
- return uc + CifsUniUpperTable[uc]; /* Use base tables */
- } else {
- rp = CifsUniUpperRange; /* Use range tables */
- while (rp->start) {
- if (uc < rp->start) /* Before start of range */
- return uc; /* Uppercase = input */
- if (uc <= rp->end) /* In range */
- return uc + rp->table[uc - rp->start];
- rp++; /* Try next range */
- }
- }
- return uc; /* Past last range */
-}
-
-/*
- * UniStrupr: Upper case a unicode string
- */
-static inline __le16 *
-UniStrupr(register __le16 *upin)
-{
- register __le16 *up;
-
- up = upin;
- while (*up) { /* For all characters */
- *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
- up++;
- }
- return upin; /* Return input pointer */
-}
-#endif /* UNIUPR_NOUPPER */
-
-#ifndef UNIUPR_NOLOWER
-/*
- * UniTolower: Convert a unicode character to lower case
- */
-static inline wchar_t
-UniTolower(register wchar_t uc)
-{
- register const struct UniCaseRange *rp;
-
- if (uc < sizeof(CifsUniLowerTable)) {
- /* Latin characters */
- return uc + CifsUniLowerTable[uc]; /* Use base tables */
- } else {
- rp = CifsUniLowerRange; /* Use range tables */
- while (rp->start) {
- if (uc < rp->start) /* Before start of range */
- return uc; /* Uppercase = input */
- if (uc <= rp->end) /* In range */
- return uc + rp->table[uc - rp->start];
- rp++; /* Try next range */
- }
- }
- return uc; /* Past last range */
-}
-
-/*
- * UniStrlwr: Lower case a unicode string
- */
-static inline wchar_t *
-UniStrlwr(register wchar_t *upin)
-{
- register wchar_t *up;
-
- up = upin;
- while (*up) { /* For all characters */
- *up = UniTolower(*up);
- up++;
- }
- return upin; /* Return input pointer */
-}
-
-#endif
-
-#endif /* _CIFS_UNICODE_H */
diff --git a/fs/cifs/cifs_uniupr.h b/fs/cifs/cifs_uniupr.h
deleted file mode 100644
index 7b272fcdf0d3..000000000000
--- a/fs/cifs/cifs_uniupr.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (c) International Business Machines Corp., 2000,2002
- *
- * uniupr.h - Unicode compressed case ranges
-*/
-
-#ifndef UNIUPR_NOUPPER
-/*
- * Latin upper case
- */
-signed char CifsUniUpperTable[512] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
- 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
- -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
- 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
- -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
- 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
- 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
- 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
- -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
- 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
- -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
- 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
-};
-
-/* Upper case range - Greek */
-static signed char UniCaseRangeU03a0[47] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
- 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
- -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
- -63, -63,
-};
-
-/* Upper case range - Cyrillic */
-static signed char UniCaseRangeU0430[48] = {
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
- 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
-};
-
-/* Upper case range - Extended cyrillic */
-static signed char UniCaseRangeU0490[61] = {
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
- 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
-};
-
-/* Upper case range - Extended latin and greek */
-static signed char UniCaseRangeU1e00[509] = {
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
- 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
- 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
- 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
- 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
- 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
- 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
- 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
- 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
- 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
- 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-/* Upper case range - Wide latin */
-static signed char UniCaseRangeUff40[27] = {
- 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
-};
-
-/*
- * Upper Case Range
- */
-const struct UniCaseRange CifsUniUpperRange[] = {
- {0x03a0, 0x03ce, UniCaseRangeU03a0},
- {0x0430, 0x045f, UniCaseRangeU0430},
- {0x0490, 0x04cc, UniCaseRangeU0490},
- {0x1e00, 0x1ffc, UniCaseRangeU1e00},
- {0xff40, 0xff5a, UniCaseRangeUff40},
- {0}
-};
-#endif
-
-#ifndef UNIUPR_NOLOWER
-/*
- * Latin lower case
- */
-signed char CifsUniLowerTable[512] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
- 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
- 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
- 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
- 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
- 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
- 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
- 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
- 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
- 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
- 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
- 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
- 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
-};
-
-/* Lower case range - Greek */
-static signed char UniCaseRangeL0380[44] = {
- 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
- 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
- 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-};
-
-/* Lower case range - Cyrillic */
-static signed char UniCaseRangeL0400[48] = {
- 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
-};
-
-/* Lower case range - Extended cyrillic */
-static signed char UniCaseRangeL0490[60] = {
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
- 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
-};
-
-/* Lower case range - Extended latin and greek */
-static signed char UniCaseRangeL1e00[504] = {
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
- 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
- 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-/* Lower case range - Wide latin */
-static signed char UniCaseRangeLff20[27] = {
- 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-};
-
-/*
- * Lower Case Range
- */
-const struct UniCaseRange CifsUniLowerRange[] = {
- {0x0380, 0x03ab, UniCaseRangeL0380},
- {0x0400, 0x042f, UniCaseRangeL0400},
- {0x0490, 0x04cb, UniCaseRangeL0490},
- {0x1e00, 0x1ff7, UniCaseRangeL1e00},
- {0xff20, 0xff3a, UniCaseRangeLff20},
- {0}
-};
-#endif
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
deleted file mode 100644
index a6c7566a0182..000000000000
--- a/fs/cifs/cifsacl.c
+++ /dev/null
@@ -1,1672 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2007,2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- * Contains the routines for mapping CIFS/NTFS ACLs
- *
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/keyctl.h>
-#include <linux/key-type.h>
-#include <keys/user-type.h>
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsacl.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "fs_context.h"
-
-/* security id for everyone/world system group */
-static const struct cifs_sid sid_everyone = {
- 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
-/* security id for Authenticated Users system group */
-static const struct cifs_sid sid_authusers = {
- 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
-
-/* S-1-22-1 Unmapped Unix users */
-static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
- {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/* S-1-22-2 Unmapped Unix groups */
-static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
- {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/*
- * See https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
- */
-
-/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
-
-/* S-1-5-88-1 Unix uid */
-static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
- {cpu_to_le32(88),
- cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/* S-1-5-88-2 Unix gid */
-static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
- {cpu_to_le32(88),
- cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/* S-1-5-88-3 Unix mode */
-static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
- {cpu_to_le32(88),
- cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-static const struct cred *root_cred;
-
-static int
-cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
-{
- char *payload;
-
- /*
- * If the payload is less than or equal to the size of a pointer, then
- * an allocation here is wasteful. Just copy the data directly to the
- * payload.value union member instead.
- *
- * With this however, you must check the datalen before trying to
- * dereference payload.data!
- */
- if (prep->datalen <= sizeof(key->payload)) {
- key->payload.data[0] = NULL;
- memcpy(&key->payload, prep->data, prep->datalen);
- } else {
- payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
- if (!payload)
- return -ENOMEM;
- key->payload.data[0] = payload;
- }
-
- key->datalen = prep->datalen;
- return 0;
-}
-
-static inline void
-cifs_idmap_key_destroy(struct key *key)
-{
- if (key->datalen > sizeof(key->payload))
- kfree(key->payload.data[0]);
-}
-
-static struct key_type cifs_idmap_key_type = {
- .name = "cifs.idmap",
- .instantiate = cifs_idmap_key_instantiate,
- .destroy = cifs_idmap_key_destroy,
- .describe = user_describe,
-};
-
-static char *
-sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
-{
- int i, len;
- unsigned int saval;
- char *sidstr, *strptr;
- unsigned long long id_auth_val;
-
- /* 3 bytes for prefix */
- sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
- (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
- GFP_KERNEL);
- if (!sidstr)
- return sidstr;
-
- strptr = sidstr;
- len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
- sidptr->revision);
- strptr += len;
-
- /* The authority field is a single 48-bit number */
- id_auth_val = (unsigned long long)sidptr->authority[5];
- id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
- id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
- id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
- id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
- id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
-
- /*
- * MS-DTYP states that if the authority is >= 2^32, then it should be
- * expressed as a hex value.
- */
- if (id_auth_val <= UINT_MAX)
- len = sprintf(strptr, "-%llu", id_auth_val);
- else
- len = sprintf(strptr, "-0x%llx", id_auth_val);
-
- strptr += len;
-
- for (i = 0; i < sidptr->num_subauth; ++i) {
- saval = le32_to_cpu(sidptr->sub_auth[i]);
- len = sprintf(strptr, "-%u", saval);
- strptr += len;
- }
-
- return sidstr;
-}
-
-/*
- * if the two SIDs (roughly equivalent to a UUID for a user or group) are
- * the same returns zero, if they do not match returns non-zero.
- */
-static int
-compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
-{
- int i;
- int num_subauth, num_sat, num_saw;
-
- if ((!ctsid) || (!cwsid))
- return 1;
-
- /* compare the revision */
- if (ctsid->revision != cwsid->revision) {
- if (ctsid->revision > cwsid->revision)
- return 1;
- else
- return -1;
- }
-
- /* compare all of the six auth values */
- for (i = 0; i < NUM_AUTHS; ++i) {
- if (ctsid->authority[i] != cwsid->authority[i]) {
- if (ctsid->authority[i] > cwsid->authority[i])
- return 1;
- else
- return -1;
- }
- }
-
- /* compare all of the subauth values if any */
- num_sat = ctsid->num_subauth;
- num_saw = cwsid->num_subauth;
- num_subauth = num_sat < num_saw ? num_sat : num_saw;
- if (num_subauth) {
- for (i = 0; i < num_subauth; ++i) {
- if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
- if (le32_to_cpu(ctsid->sub_auth[i]) >
- le32_to_cpu(cwsid->sub_auth[i]))
- return 1;
- else
- return -1;
- }
- }
- }
-
- return 0; /* sids compare/match */
-}
-
-static bool
-is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
-{
- int i;
- int num_subauth;
- const struct cifs_sid *pwell_known_sid;
-
- if (!psid || (puid == NULL))
- return false;
-
- num_subauth = psid->num_subauth;
-
- /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
- if (num_subauth == 2) {
- if (is_group)
- pwell_known_sid = &sid_unix_groups;
- else
- pwell_known_sid = &sid_unix_users;
- } else if (num_subauth == 3) {
- if (is_group)
- pwell_known_sid = &sid_unix_NFS_groups;
- else
- pwell_known_sid = &sid_unix_NFS_users;
- } else
- return false;
-
- /* compare the revision */
- if (psid->revision != pwell_known_sid->revision)
- return false;
-
- /* compare all of the six auth values */
- for (i = 0; i < NUM_AUTHS; ++i) {
- if (psid->authority[i] != pwell_known_sid->authority[i]) {
- cifs_dbg(FYI, "auth %d did not match\n", i);
- return false;
- }
- }
-
- if (num_subauth == 2) {
- if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
- return false;
-
- *puid = le32_to_cpu(psid->sub_auth[1]);
- } else /* 3 subauths, ie Windows/Mac style */ {
- *puid = le32_to_cpu(psid->sub_auth[0]);
- if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
- (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
- return false;
-
- *puid = le32_to_cpu(psid->sub_auth[2]);
- }
-
- cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
- return true; /* well known sid found, uid returned */
-}
-
-static __u16
-cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
-{
- int i;
- __u16 size = 1 + 1 + 6;
-
- dst->revision = src->revision;
- dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
- for (i = 0; i < NUM_AUTHS; ++i)
- dst->authority[i] = src->authority[i];
- for (i = 0; i < dst->num_subauth; ++i)
- dst->sub_auth[i] = src->sub_auth[i];
- size += (dst->num_subauth * 4);
-
- return size;
-}
-
-static int
-id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
-{
- int rc;
- struct key *sidkey;
- struct cifs_sid *ksid;
- unsigned int ksid_size;
- char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
- const struct cred *saved_cred;
-
- rc = snprintf(desc, sizeof(desc), "%ci:%u",
- sidtype == SIDOWNER ? 'o' : 'g', cid);
- if (rc >= sizeof(desc))
- return -EINVAL;
-
- rc = 0;
- saved_cred = override_creds(root_cred);
- sidkey = request_key(&cifs_idmap_key_type, desc, "");
- if (IS_ERR(sidkey)) {
- rc = -EINVAL;
- cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
- __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
- goto out_revert_creds;
- } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
- rc = -EIO;
- cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
- __func__, sidkey->datalen);
- goto invalidate_key;
- }
-
- /*
- * A sid is usually too large to be embedded in payload.value, but if
- * there are no subauthorities and the host has 8-byte pointers, then
- * it could be.
- */
- ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
- (struct cifs_sid *)&sidkey->payload :
- (struct cifs_sid *)sidkey->payload.data[0];
-
- ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
- if (ksid_size > sidkey->datalen) {
- rc = -EIO;
- cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
- __func__, sidkey->datalen, ksid_size);
- goto invalidate_key;
- }
-
- cifs_copy_sid(ssid, ksid);
-out_key_put:
- key_put(sidkey);
-out_revert_creds:
- revert_creds(saved_cred);
- return rc;
-
-invalidate_key:
- key_invalidate(sidkey);
- goto out_key_put;
-}
-
-int
-sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
- struct cifs_fattr *fattr, uint sidtype)
-{
- int rc = 0;
- struct key *sidkey;
- char *sidstr;
- const struct cred *saved_cred;
- kuid_t fuid = cifs_sb->ctx->linux_uid;
- kgid_t fgid = cifs_sb->ctx->linux_gid;
-
- /*
- * If we have too many subauthorities, then something is really wrong.
- * Just return an error.
- */
- if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
- cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
- __func__, psid->num_subauth);
- return -EIO;
- }
-
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) ||
- (cifs_sb_master_tcon(cifs_sb)->posix_extensions)) {
- uint32_t unix_id;
- bool is_group;
-
- if (sidtype != SIDOWNER)
- is_group = true;
- else
- is_group = false;
-
- if (is_well_known_sid(psid, &unix_id, is_group) == false)
- goto try_upcall_to_get_id;
-
- if (is_group) {
- kgid_t gid;
- gid_t id;
-
- id = (gid_t)unix_id;
- gid = make_kgid(&init_user_ns, id);
- if (gid_valid(gid)) {
- fgid = gid;
- goto got_valid_id;
- }
- } else {
- kuid_t uid;
- uid_t id;
-
- id = (uid_t)unix_id;
- uid = make_kuid(&init_user_ns, id);
- if (uid_valid(uid)) {
- fuid = uid;
- goto got_valid_id;
- }
- }
- /* If unable to find uid/gid easily from SID try via upcall */
- }
-
-try_upcall_to_get_id:
- sidstr = sid_to_key_str(psid, sidtype);
- if (!sidstr)
- return -ENOMEM;
-
- saved_cred = override_creds(root_cred);
- sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
- if (IS_ERR(sidkey)) {
- cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
- __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
- goto out_revert_creds;
- }
-
- /*
- * FIXME: Here we assume that uid_t and gid_t are same size. It's
- * probably a safe assumption but might be better to check based on
- * sidtype.
- */
- BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
- if (sidkey->datalen != sizeof(uid_t)) {
- cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
- __func__, sidkey->datalen);
- key_invalidate(sidkey);
- goto out_key_put;
- }
-
- if (sidtype == SIDOWNER) {
- kuid_t uid;
- uid_t id;
- memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
- uid = make_kuid(&init_user_ns, id);
- if (uid_valid(uid))
- fuid = uid;
- } else {
- kgid_t gid;
- gid_t id;
- memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
- gid = make_kgid(&init_user_ns, id);
- if (gid_valid(gid))
- fgid = gid;
- }
-
-out_key_put:
- key_put(sidkey);
-out_revert_creds:
- revert_creds(saved_cred);
- kfree(sidstr);
-
- /*
- * Note that we return 0 here unconditionally. If the mapping
- * fails then we just fall back to using the ctx->linux_uid/linux_gid.
- */
-got_valid_id:
- rc = 0;
- if (sidtype == SIDOWNER)
- fattr->cf_uid = fuid;
- else
- fattr->cf_gid = fgid;
- return rc;
-}
-
-int
-init_cifs_idmap(void)
-{
- struct cred *cred;
- struct key *keyring;
- int ret;
-
- cifs_dbg(FYI, "Registering the %s key type\n",
- cifs_idmap_key_type.name);
-
- /* create an override credential set with a special thread keyring in
- * which requests are cached
- *
- * this is used to prevent malicious redirections from being installed
- * with add_key().
- */
- cred = prepare_kernel_cred(NULL);
- if (!cred)
- return -ENOMEM;
-
- keyring = keyring_alloc(".cifs_idmap",
- GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
- (KEY_POS_ALL & ~KEY_POS_SETATTR) |
- KEY_USR_VIEW | KEY_USR_READ,
- KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
- goto failed_put_cred;
- }
-
- ret = register_key_type(&cifs_idmap_key_type);
- if (ret < 0)
- goto failed_put_key;
-
- /* instruct request_key() to use this special keyring as a cache for
- * the results it looks up */
- set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
- cred->thread_keyring = keyring;
- cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
- root_cred = cred;
-
- cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
- return 0;
-
-failed_put_key:
- key_put(keyring);
-failed_put_cred:
- put_cred(cred);
- return ret;
-}
-
-void
-exit_cifs_idmap(void)
-{
- key_revoke(root_cred->thread_keyring);
- unregister_key_type(&cifs_idmap_key_type);
- put_cred(root_cred);
- cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
-}
-
-/* copy ntsd, owner sid, and group sid from a security descriptor to another */
-static __u32 copy_sec_desc(const struct cifs_ntsd *pntsd,
- struct cifs_ntsd *pnntsd,
- __u32 sidsoffset,
- struct cifs_sid *pownersid,
- struct cifs_sid *pgrpsid)
-{
- struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
- struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
-
- /* copy security descriptor control portion */
- pnntsd->revision = pntsd->revision;
- pnntsd->type = pntsd->type;
- pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
- pnntsd->sacloffset = 0;
- pnntsd->osidoffset = cpu_to_le32(sidsoffset);
- pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
-
- /* copy owner sid */
- if (pownersid)
- owner_sid_ptr = pownersid;
- else
- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->osidoffset));
- nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
- cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
-
- /* copy group sid */
- if (pgrpsid)
- group_sid_ptr = pgrpsid;
- else
- group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->gsidoffset));
- ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
- sizeof(struct cifs_sid));
- cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
-
- return sidsoffset + (2 * sizeof(struct cifs_sid));
-}
-
-
-/*
- change posix mode to reflect permissions
- pmode is the existing mode (we only want to overwrite part of this
- bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
-*/
-static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
- umode_t *pdenied, umode_t mask)
-{
- __u32 flags = le32_to_cpu(ace_flags);
- /*
- * Do not assume "preferred" or "canonical" order.
- * The first DENY or ALLOW ACE which matches perfectly is
- * the permission to be used. Once allowed or denied, same
- * permission in later ACEs do not matter.
- */
-
- /* If not already allowed, deny these bits */
- if (type == ACCESS_DENIED) {
- if (flags & GENERIC_ALL &&
- !(*pmode & mask & 0777))
- *pdenied |= mask & 0777;
-
- if (((flags & GENERIC_WRITE) ||
- ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) &&
- !(*pmode & mask & 0222))
- *pdenied |= mask & 0222;
-
- if (((flags & GENERIC_READ) ||
- ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) &&
- !(*pmode & mask & 0444))
- *pdenied |= mask & 0444;
-
- if (((flags & GENERIC_EXECUTE) ||
- ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) &&
- !(*pmode & mask & 0111))
- *pdenied |= mask & 0111;
-
- return;
- } else if (type != ACCESS_ALLOWED) {
- cifs_dbg(VFS, "unknown access control type %d\n", type);
- return;
- }
- /* else ACCESS_ALLOWED type */
-
- if ((flags & GENERIC_ALL) &&
- !(*pdenied & mask & 0777)) {
- *pmode |= mask & 0777;
- cifs_dbg(NOISY, "all perms\n");
- return;
- }
-
- if (((flags & GENERIC_WRITE) ||
- ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) &&
- !(*pdenied & mask & 0222))
- *pmode |= mask & 0222;
-
- if (((flags & GENERIC_READ) ||
- ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) &&
- !(*pdenied & mask & 0444))
- *pmode |= mask & 0444;
-
- if (((flags & GENERIC_EXECUTE) ||
- ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) &&
- !(*pdenied & mask & 0111))
- *pmode |= mask & 0111;
-
- /* If DELETE_CHILD is set only on an owner ACE, set sticky bit */
- if (flags & FILE_DELETE_CHILD) {
- if (mask == ACL_OWNER_MASK) {
- if (!(*pdenied & 01000))
- *pmode |= 01000;
- } else if (!(*pdenied & 01000)) {
- *pmode &= ~01000;
- *pdenied |= 01000;
- }
- }
-
- cifs_dbg(NOISY, "access flags 0x%x mode now %04o\n", flags, *pmode);
- return;
-}
-
-/*
- Generate access flags to reflect permissions mode is the existing mode.
- This function is called for every ACE in the DACL whose SID matches
- with either owner or group or everyone.
-*/
-
-static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
- __u32 *pace_flags)
-{
- /* reset access mask */
- *pace_flags = 0x0;
-
- /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
- mode &= bits_to_use;
-
- /* check for R/W/X UGO since we do not know whose flags
- is this but we have cleared all the bits sans RWX for
- either user or group or other as per bits_to_use */
- if (mode & S_IRUGO)
- *pace_flags |= SET_FILE_READ_RIGHTS;
- if (mode & S_IWUGO)
- *pace_flags |= SET_FILE_WRITE_RIGHTS;
- if (mode & S_IXUGO)
- *pace_flags |= SET_FILE_EXEC_RIGHTS;
-
- cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x\n",
- mode, *pace_flags);
- return;
-}
-
-static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct cifs_sid *psid)
-{
- __u16 size = 1 + 1 + 2 + 4;
-
- dst->type = src->type;
- dst->flags = src->flags;
- dst->access_req = src->access_req;
-
- /* Check if there's a replacement sid specified */
- if (psid)
- size += cifs_copy_sid(&dst->sid, psid);
- else
- size += cifs_copy_sid(&dst->sid, &src->sid);
-
- dst->size = cpu_to_le16(size);
-
- return size;
-}
-
-static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
- const struct cifs_sid *psid, __u64 nmode,
- umode_t bits, __u8 access_type,
- bool allow_delete_child)
-{
- int i;
- __u16 size = 0;
- __u32 access_req = 0;
-
- pntace->type = access_type;
- pntace->flags = 0x0;
- mode_to_access_flags(nmode, bits, &access_req);
-
- if (access_type == ACCESS_ALLOWED && allow_delete_child)
- access_req |= FILE_DELETE_CHILD;
-
- if (access_type == ACCESS_ALLOWED && !access_req)
- access_req = SET_MINIMUM_RIGHTS;
- else if (access_type == ACCESS_DENIED)
- access_req &= ~SET_MINIMUM_RIGHTS;
-
- pntace->access_req = cpu_to_le32(access_req);
-
- pntace->sid.revision = psid->revision;
- pntace->sid.num_subauth = psid->num_subauth;
- for (i = 0; i < NUM_AUTHS; i++)
- pntace->sid.authority[i] = psid->authority[i];
- for (i = 0; i < psid->num_subauth; i++)
- pntace->sid.sub_auth[i] = psid->sub_auth[i];
-
- size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
- pntace->size = cpu_to_le16(size);
-
- return size;
-}
-
-
-#ifdef CONFIG_CIFS_DEBUG2
-static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
-{
- int num_subauth;
-
- /* validate that we do not go past end of acl */
-
- if (le16_to_cpu(pace->size) < 16) {
- cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
- return;
- }
-
- if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
- cifs_dbg(VFS, "ACL too small to parse ACE\n");
- return;
- }
-
- num_subauth = pace->sid.num_subauth;
- if (num_subauth) {
- int i;
- cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
- pace->sid.revision, pace->sid.num_subauth, pace->type,
- pace->flags, le16_to_cpu(pace->size));
- for (i = 0; i < num_subauth; ++i) {
- cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
- i, le32_to_cpu(pace->sid.sub_auth[i]));
- }
-
- /* BB add length check to make sure that we do not have huge
- num auths and therefore go off the end */
- }
-
- return;
-}
-#endif
-
-static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
- struct cifs_fattr *fattr, bool mode_from_special_sid)
-{
- int i;
- int num_aces = 0;
- int acl_size;
- char *acl_base;
- struct cifs_ace **ppace;
-
- /* BB need to add parm so we can store the SID BB */
-
- if (!pdacl) {
- /* no DACL in the security descriptor, set
- all the permissions for user/group/other */
- fattr->cf_mode |= 0777;
- return;
- }
-
- /* validate that we do not go past end of acl */
- if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
- cifs_dbg(VFS, "ACL too small to parse DACL\n");
- return;
- }
-
- cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
- le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
- le32_to_cpu(pdacl->num_aces));
-
- /* reset rwx permissions for user/group/other.
- Also, if num_aces is 0 i.e. DACL has no ACEs,
- user/group/other have no permissions */
- fattr->cf_mode &= ~(0777);
-
- acl_base = (char *)pdacl;
- acl_size = sizeof(struct cifs_acl);
-
- num_aces = le32_to_cpu(pdacl->num_aces);
- if (num_aces > 0) {
- umode_t denied_mode = 0;
-
- if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
- return;
- ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
- GFP_KERNEL);
- if (!ppace)
- return;
-
- for (i = 0; i < num_aces; ++i) {
- ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
-#ifdef CONFIG_CIFS_DEBUG2
- dump_ace(ppace[i], end_of_acl);
-#endif
- if (mode_from_special_sid &&
- (compare_sids(&(ppace[i]->sid),
- &sid_unix_NFS_mode) == 0)) {
- /*
- * Full permissions are:
- * 07777 = S_ISUID | S_ISGID | S_ISVTX |
- * S_IRWXU | S_IRWXG | S_IRWXO
- */
- fattr->cf_mode &= ~07777;
- fattr->cf_mode |=
- le32_to_cpu(ppace[i]->sid.sub_auth[2]);
- break;
- } else {
- if (compare_sids(&(ppace[i]->sid), pownersid) == 0) {
- access_flags_to_mode(ppace[i]->access_req,
- ppace[i]->type,
- &fattr->cf_mode,
- &denied_mode,
- ACL_OWNER_MASK);
- } else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) {
- access_flags_to_mode(ppace[i]->access_req,
- ppace[i]->type,
- &fattr->cf_mode,
- &denied_mode,
- ACL_GROUP_MASK);
- } else if ((compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) ||
- (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)) {
- access_flags_to_mode(ppace[i]->access_req,
- ppace[i]->type,
- &fattr->cf_mode,
- &denied_mode,
- ACL_EVERYONE_MASK);
- }
- }
-
-
-/* memcpy((void *)(&(cifscred->aces[i])),
- (void *)ppace[i],
- sizeof(struct cifs_ace)); */
-
- acl_base = (char *)ppace[i];
- acl_size = le16_to_cpu(ppace[i]->size);
- }
-
- kfree(ppace);
- }
-
- return;
-}
-
-unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
-{
- int i;
- unsigned int ace_size = 20;
-
- pntace->type = ACCESS_ALLOWED_ACE_TYPE;
- pntace->flags = 0x0;
- pntace->access_req = cpu_to_le32(GENERIC_ALL);
- pntace->sid.num_subauth = 1;
- pntace->sid.revision = 1;
- for (i = 0; i < NUM_AUTHS; i++)
- pntace->sid.authority[i] = sid_authusers.authority[i];
-
- pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0];
-
- /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
- pntace->size = cpu_to_le16(ace_size);
- return ace_size;
-}
-
-/*
- * Fill in the special SID based on the mode. See
- * https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
- */
-unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
-{
- int i;
- unsigned int ace_size = 28;
-
- pntace->type = ACCESS_DENIED_ACE_TYPE;
- pntace->flags = 0x0;
- pntace->access_req = 0;
- pntace->sid.num_subauth = 3;
- pntace->sid.revision = 1;
- for (i = 0; i < NUM_AUTHS; i++)
- pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i];
-
- pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
- pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
- pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
-
- /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
- pntace->size = cpu_to_le16(ace_size);
- return ace_size;
-}
-
-unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
-{
- int i;
- unsigned int ace_size = 28;
-
- pntace->type = ACCESS_ALLOWED_ACE_TYPE;
- pntace->flags = 0x0;
- pntace->access_req = cpu_to_le32(GENERIC_ALL);
- pntace->sid.num_subauth = 3;
- pntace->sid.revision = 1;
- for (i = 0; i < NUM_AUTHS; i++)
- pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];
-
- pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
- pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
- pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);
-
- /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
- pntace->size = cpu_to_le16(ace_size);
- return ace_size;
-}
-
-static void populate_new_aces(char *nacl_base,
- struct cifs_sid *pownersid,
- struct cifs_sid *pgrpsid,
- __u64 *pnmode, u32 *pnum_aces, u16 *pnsize,
- bool modefromsid)
-{
- __u64 nmode;
- u32 num_aces = 0;
- u16 nsize = 0;
- __u64 user_mode;
- __u64 group_mode;
- __u64 other_mode;
- __u64 deny_user_mode = 0;
- __u64 deny_group_mode = 0;
- bool sticky_set = false;
- struct cifs_ace *pnntace = NULL;
-
- nmode = *pnmode;
- num_aces = *pnum_aces;
- nsize = *pnsize;
-
- if (modefromsid) {
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
- nsize += setup_special_mode_ACE(pnntace, nmode);
- num_aces++;
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
- nsize += setup_authusers_ACE(pnntace);
- num_aces++;
- goto set_size;
- }
-
- /*
- * We'll try to keep the mode as requested by the user.
- * But in cases where we cannot meaningfully convert that
- * into ACL, return back the updated mode, so that it is
- * updated in the inode.
- */
-
- if (!memcmp(pownersid, pgrpsid, sizeof(struct cifs_sid))) {
- /*
- * Case when owner and group SIDs are the same.
- * Set the more restrictive of the two modes.
- */
- user_mode = nmode & (nmode << 3) & 0700;
- group_mode = nmode & (nmode >> 3) & 0070;
- } else {
- user_mode = nmode & 0700;
- group_mode = nmode & 0070;
- }
-
- other_mode = nmode & 0007;
-
- /* We need DENY ACE when the perm is more restrictive than the next sets. */
- deny_user_mode = ~(user_mode) & ((group_mode << 3) | (other_mode << 6)) & 0700;
- deny_group_mode = ~(group_mode) & (other_mode << 3) & 0070;
-
- *pnmode = user_mode | group_mode | other_mode | (nmode & ~0777);
-
- /* This tells if we should allow delete child for group and everyone. */
- if (nmode & 01000)
- sticky_set = true;
-
- if (deny_user_mode) {
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
- nsize += fill_ace_for_sid(pnntace, pownersid, deny_user_mode,
- 0700, ACCESS_DENIED, false);
- num_aces++;
- }
-
- /* Group DENY ACE does not conflict with owner ALLOW ACE. Keep in preferred order*/
- if (deny_group_mode && !(deny_group_mode & (user_mode >> 3))) {
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
- nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
- 0070, ACCESS_DENIED, false);
- num_aces++;
- }
-
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
- nsize += fill_ace_for_sid(pnntace, pownersid, user_mode,
- 0700, ACCESS_ALLOWED, true);
- num_aces++;
-
- /* Group DENY ACE conflicts with owner ALLOW ACE. So keep it after. */
- if (deny_group_mode && (deny_group_mode & (user_mode >> 3))) {
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
- nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
- 0070, ACCESS_DENIED, false);
- num_aces++;
- }
-
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
- nsize += fill_ace_for_sid(pnntace, pgrpsid, group_mode,
- 0070, ACCESS_ALLOWED, !sticky_set);
- num_aces++;
-
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
- nsize += fill_ace_for_sid(pnntace, &sid_everyone, other_mode,
- 0007, ACCESS_ALLOWED, !sticky_set);
- num_aces++;
-
-set_size:
- *pnum_aces = num_aces;
- *pnsize = nsize;
-}
-
-static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
- struct cifs_sid *pnownersid, struct cifs_sid *pngrpsid)
-{
- int i;
- u16 size = 0;
- struct cifs_ace *pntace = NULL;
- char *acl_base = NULL;
- u32 src_num_aces = 0;
- u16 nsize = 0;
- struct cifs_ace *pnntace = NULL;
- char *nacl_base = NULL;
- u16 ace_size = 0;
-
- acl_base = (char *)pdacl;
- size = sizeof(struct cifs_acl);
- src_num_aces = le32_to_cpu(pdacl->num_aces);
-
- nacl_base = (char *)pndacl;
- nsize = sizeof(struct cifs_acl);
-
- /* Go through all the ACEs */
- for (i = 0; i < src_num_aces; ++i) {
- pntace = (struct cifs_ace *) (acl_base + size);
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
-
- if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0)
- ace_size = cifs_copy_ace(pnntace, pntace, pnownersid);
- else if (pngrpsid && compare_sids(&pntace->sid, pgrpsid) == 0)
- ace_size = cifs_copy_ace(pnntace, pntace, pngrpsid);
- else
- ace_size = cifs_copy_ace(pnntace, pntace, NULL);
-
- size += le16_to_cpu(pntace->size);
- nsize += ace_size;
- }
-
- return nsize;
-}
-
-static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
- __u64 *pnmode, bool mode_from_sid)
-{
- int i;
- u16 size = 0;
- struct cifs_ace *pntace = NULL;
- char *acl_base = NULL;
- u32 src_num_aces = 0;
- u16 nsize = 0;
- struct cifs_ace *pnntace = NULL;
- char *nacl_base = NULL;
- u32 num_aces = 0;
- bool new_aces_set = false;
-
- /* Assuming that pndacl and pnmode are never NULL */
- nacl_base = (char *)pndacl;
- nsize = sizeof(struct cifs_acl);
-
- /* If pdacl is NULL, we don't have a src. Simply populate new ACL. */
- if (!pdacl) {
- populate_new_aces(nacl_base,
- pownersid, pgrpsid,
- pnmode, &num_aces, &nsize,
- mode_from_sid);
- goto finalize_dacl;
- }
-
- acl_base = (char *)pdacl;
- size = sizeof(struct cifs_acl);
- src_num_aces = le32_to_cpu(pdacl->num_aces);
-
- /* Retain old ACEs which we can retain */
- for (i = 0; i < src_num_aces; ++i) {
- pntace = (struct cifs_ace *) (acl_base + size);
-
- if (!new_aces_set && (pntace->flags & INHERITED_ACE)) {
- /* Place the new ACEs in between existing explicit and inherited */
- populate_new_aces(nacl_base,
- pownersid, pgrpsid,
- pnmode, &num_aces, &nsize,
- mode_from_sid);
-
- new_aces_set = true;
- }
-
- /* If it's any one of the ACE we're replacing, skip! */
- if (((compare_sids(&pntace->sid, &sid_unix_NFS_mode) == 0) ||
- (compare_sids(&pntace->sid, pownersid) == 0) ||
- (compare_sids(&pntace->sid, pgrpsid) == 0) ||
- (compare_sids(&pntace->sid, &sid_everyone) == 0) ||
- (compare_sids(&pntace->sid, &sid_authusers) == 0))) {
- goto next_ace;
- }
-
- /* update the pointer to the next ACE to populate*/
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
-
- nsize += cifs_copy_ace(pnntace, pntace, NULL);
- num_aces++;
-
-next_ace:
- size += le16_to_cpu(pntace->size);
- }
-
- /* If inherited ACEs are not present, place the new ones at the tail */
- if (!new_aces_set) {
- populate_new_aces(nacl_base,
- pownersid, pgrpsid,
- pnmode, &num_aces, &nsize,
- mode_from_sid);
-
- new_aces_set = true;
- }
-
-finalize_dacl:
- pndacl->num_aces = cpu_to_le32(num_aces);
- pndacl->size = cpu_to_le16(nsize);
-
- return 0;
-}
-
-static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
-{
- /* BB need to add parm so we can store the SID BB */
-
- /* validate that we do not go past end of ACL - sid must be at least 8
- bytes long (assuming no sub-auths - e.g. the null SID */
- if (end_of_acl < (char *)psid + 8) {
- cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
- return -EINVAL;
- }
-
-#ifdef CONFIG_CIFS_DEBUG2
- if (psid->num_subauth) {
- int i;
- cifs_dbg(FYI, "SID revision %d num_auth %d\n",
- psid->revision, psid->num_subauth);
-
- for (i = 0; i < psid->num_subauth; i++) {
- cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
- i, le32_to_cpu(psid->sub_auth[i]));
- }
-
- /* BB add length check to make sure that we do not have huge
- num auths and therefore go off the end */
- cifs_dbg(FYI, "RID 0x%x\n",
- le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
- }
-#endif
-
- return 0;
-}
-
-
-/* Convert CIFS ACL to POSIX form */
-static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
- struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
- bool get_mode_from_special_sid)
-{
- int rc = 0;
- struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
- struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
- char *end_of_acl = ((char *)pntsd) + acl_len;
- __u32 dacloffset;
-
- if (pntsd == NULL)
- return -EIO;
-
- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->osidoffset));
- group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->gsidoffset));
- dacloffset = le32_to_cpu(pntsd->dacloffset);
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
- cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
- pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
- le32_to_cpu(pntsd->gsidoffset),
- le32_to_cpu(pntsd->sacloffset), dacloffset);
-/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
- rc = parse_sid(owner_sid_ptr, end_of_acl);
- if (rc) {
- cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
- return rc;
- }
- rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
- if (rc) {
- cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
- __func__, rc);
- return rc;
- }
-
- rc = parse_sid(group_sid_ptr, end_of_acl);
- if (rc) {
- cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
- __func__, rc);
- return rc;
- }
- rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
- if (rc) {
- cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
- __func__, rc);
- return rc;
- }
-
- if (dacloffset)
- parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
- group_sid_ptr, fattr, get_mode_from_special_sid);
- else
- cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
-
- return rc;
-}
-
-/* Convert permission bits from mode to equivalent CIFS ACL */
-static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
- __u32 secdesclen, __u32 *pnsecdesclen, __u64 *pnmode, kuid_t uid, kgid_t gid,
- bool mode_from_sid, bool id_from_sid, int *aclflag)
-{
- int rc = 0;
- __u32 dacloffset;
- __u32 ndacloffset;
- __u32 sidsoffset;
- struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
- struct cifs_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
- struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
- struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
- char *end_of_acl = ((char *)pntsd) + secdesclen;
- u16 size = 0;
-
- dacloffset = le32_to_cpu(pntsd->dacloffset);
- if (dacloffset) {
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
- if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) {
- cifs_dbg(VFS, "Server returned illegal ACL size\n");
- return -EINVAL;
- }
- }
-
- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->osidoffset));
- group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->gsidoffset));
-
- if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
- ndacloffset = sizeof(struct cifs_ntsd);
- ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
- ndacl_ptr->revision =
- dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
-
- ndacl_ptr->size = cpu_to_le16(0);
- ndacl_ptr->num_aces = cpu_to_le32(0);
-
- rc = set_chmod_dacl(dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr,
- pnmode, mode_from_sid);
-
- sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
- /* copy the non-dacl portion of secdesc */
- *pnsecdesclen = copy_sec_desc(pntsd, pnntsd, sidsoffset,
- NULL, NULL);
-
- *aclflag |= CIFS_ACL_DACL;
- } else {
- ndacloffset = sizeof(struct cifs_ntsd);
- ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
- ndacl_ptr->revision =
- dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
- ndacl_ptr->num_aces = dacl_ptr ? dacl_ptr->num_aces : 0;
-
- if (uid_valid(uid)) { /* chown */
- uid_t id;
- nowner_sid_ptr = kzalloc(sizeof(struct cifs_sid),
- GFP_KERNEL);
- if (!nowner_sid_ptr) {
- rc = -ENOMEM;
- goto chown_chgrp_exit;
- }
- id = from_kuid(&init_user_ns, uid);
- if (id_from_sid) {
- struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
- /* Populate the user ownership fields S-1-5-88-1 */
- osid->Revision = 1;
- osid->NumAuth = 3;
- osid->Authority[5] = 5;
- osid->SubAuthorities[0] = cpu_to_le32(88);
- osid->SubAuthorities[1] = cpu_to_le32(1);
- osid->SubAuthorities[2] = cpu_to_le32(id);
-
- } else { /* lookup sid with upcall */
- rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
- if (rc) {
- cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
- __func__, rc, id);
- goto chown_chgrp_exit;
- }
- }
- *aclflag |= CIFS_ACL_OWNER;
- }
- if (gid_valid(gid)) { /* chgrp */
- gid_t id;
- ngroup_sid_ptr = kzalloc(sizeof(struct cifs_sid),
- GFP_KERNEL);
- if (!ngroup_sid_ptr) {
- rc = -ENOMEM;
- goto chown_chgrp_exit;
- }
- id = from_kgid(&init_user_ns, gid);
- if (id_from_sid) {
- struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
- /* Populate the group ownership fields S-1-5-88-2 */
- gsid->Revision = 1;
- gsid->NumAuth = 3;
- gsid->Authority[5] = 5;
- gsid->SubAuthorities[0] = cpu_to_le32(88);
- gsid->SubAuthorities[1] = cpu_to_le32(2);
- gsid->SubAuthorities[2] = cpu_to_le32(id);
-
- } else { /* lookup sid with upcall */
- rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
- if (rc) {
- cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
- __func__, rc, id);
- goto chown_chgrp_exit;
- }
- }
- *aclflag |= CIFS_ACL_GROUP;
- }
-
- if (dacloffset) {
- /* Replace ACEs for old owner with new one */
- size = replace_sids_and_copy_aces(dacl_ptr, ndacl_ptr,
- owner_sid_ptr, group_sid_ptr,
- nowner_sid_ptr, ngroup_sid_ptr);
- ndacl_ptr->size = cpu_to_le16(size);
- }
-
- sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
- /* copy the non-dacl portion of secdesc */
- *pnsecdesclen = copy_sec_desc(pntsd, pnntsd, sidsoffset,
- nowner_sid_ptr, ngroup_sid_ptr);
-
-chown_chgrp_exit:
- /* errors could jump here. So make sure we return soon after this */
- kfree(nowner_sid_ptr);
- kfree(ngroup_sid_ptr);
- }
-
- return rc;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
- const struct cifs_fid *cifsfid, u32 *pacllen,
- u32 __maybe_unused unused)
-{
- struct cifs_ntsd *pntsd = NULL;
- unsigned int xid;
- int rc;
- struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
-
- if (IS_ERR(tlink))
- return ERR_CAST(tlink);
-
- xid = get_xid();
- rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
- pacllen);
- free_xid(xid);
-
- cifs_put_tlink(tlink);
-
- cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
- if (rc)
- return ERR_PTR(rc);
- return pntsd;
-}
-
-static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
- const char *path, u32 *pacllen)
-{
- struct cifs_ntsd *pntsd = NULL;
- int oplock = 0;
- unsigned int xid;
- int rc;
- struct cifs_tcon *tcon;
- struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
-
- if (IS_ERR(tlink))
- return ERR_CAST(tlink);
-
- tcon = tlink_tcon(tlink);
- xid = get_xid();
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = READ_CONTROL,
- .create_options = cifs_create_options(cifs_sb, 0),
- .disposition = FILE_OPEN,
- .path = path,
- .fid = &fid,
- };
-
- rc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (!rc) {
- rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
- CIFSSMBClose(xid, tcon, fid.netfid);
- }
-
- cifs_put_tlink(tlink);
- free_xid(xid);
-
- cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
- if (rc)
- return ERR_PTR(rc);
- return pntsd;
-}
-
-/* Retrieve an ACL from the server */
-struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
- struct inode *inode, const char *path,
- u32 *pacllen, u32 info)
-{
- struct cifs_ntsd *pntsd = NULL;
- struct cifsFileInfo *open_file = NULL;
-
- if (inode)
- open_file = find_readable_file(CIFS_I(inode), true);
- if (!open_file)
- return get_cifs_acl_by_path(cifs_sb, path, pacllen);
-
- pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
- cifsFileInfo_put(open_file);
- return pntsd;
-}
-
- /* Set an ACL on the server */
-int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
- struct inode *inode, const char *path, int aclflag)
-{
- int oplock = 0;
- unsigned int xid;
- int rc, access_flags;
- struct cifs_tcon *tcon;
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
-
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
-
- tcon = tlink_tcon(tlink);
- xid = get_xid();
-
- if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
- access_flags = WRITE_OWNER;
- else
- access_flags = WRITE_DAC;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = access_flags,
- .create_options = cifs_create_options(cifs_sb, 0),
- .disposition = FILE_OPEN,
- .path = path,
- .fid = &fid,
- };
-
- rc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (rc) {
- cifs_dbg(VFS, "Unable to open file to set ACL\n");
- goto out;
- }
-
- rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
- cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
-
- CIFSSMBClose(xid, tcon, fid.netfid);
-out:
- free_xid(xid);
- cifs_put_tlink(tlink);
- return rc;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-/* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
-int
-cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
- struct inode *inode, bool mode_from_special_sid,
- const char *path, const struct cifs_fid *pfid)
-{
- struct cifs_ntsd *pntsd = NULL;
- u32 acllen = 0;
- int rc = 0;
- struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
- struct smb_version_operations *ops;
- const u32 info = 0;
-
- cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
-
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
-
- ops = tlink_tcon(tlink)->ses->server->ops;
-
- if (pfid && (ops->get_acl_by_fid))
- pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen, info);
- else if (ops->get_acl)
- pntsd = ops->get_acl(cifs_sb, inode, path, &acllen, info);
- else {
- cifs_put_tlink(tlink);
- return -EOPNOTSUPP;
- }
- /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
- if (IS_ERR(pntsd)) {
- rc = PTR_ERR(pntsd);
- cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
- } else if (mode_from_special_sid) {
- rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
- kfree(pntsd);
- } else {
- /* get approximated mode from ACL */
- rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
- kfree(pntsd);
- if (rc)
- cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
- }
-
- cifs_put_tlink(tlink);
-
- return rc;
-}
-
-/* Convert mode bits to an ACL so we can update the ACL on the server */
-int
-id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
- kuid_t uid, kgid_t gid)
-{
- int rc = 0;
- int aclflag = CIFS_ACL_DACL; /* default flag to set */
- __u32 secdesclen = 0;
- __u32 nsecdesclen = 0;
- __u32 dacloffset = 0;
- struct cifs_acl *dacl_ptr = NULL;
- struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
- struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
- struct smb_version_operations *ops;
- bool mode_from_sid, id_from_sid;
- const u32 info = 0;
-
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
-
- ops = tlink_tcon(tlink)->ses->server->ops;
-
- cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
-
- /* Get the security descriptor */
-
- if (ops->get_acl == NULL) {
- cifs_put_tlink(tlink);
- return -EOPNOTSUPP;
- }
-
- pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen, info);
- if (IS_ERR(pntsd)) {
- rc = PTR_ERR(pntsd);
- cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
- cifs_put_tlink(tlink);
- return rc;
- }
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
- mode_from_sid = true;
- else
- mode_from_sid = false;
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
- id_from_sid = true;
- else
- id_from_sid = false;
-
- /* Potentially, five new ACEs can be added to the ACL for U,G,O mapping */
- nsecdesclen = secdesclen;
- if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
- if (mode_from_sid)
- nsecdesclen += 2 * sizeof(struct cifs_ace);
- else /* cifsacl */
- nsecdesclen += 5 * sizeof(struct cifs_ace);
- } else { /* chown */
- /* When ownership changes, changes new owner sid length could be different */
- nsecdesclen = sizeof(struct cifs_ntsd) + (sizeof(struct cifs_sid) * 2);
- dacloffset = le32_to_cpu(pntsd->dacloffset);
- if (dacloffset) {
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
- if (mode_from_sid)
- nsecdesclen +=
- le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct cifs_ace);
- else /* cifsacl */
- nsecdesclen += le16_to_cpu(dacl_ptr->size);
- }
- }
-
- /*
- * Add three ACEs for owner, group, everyone getting rid of other ACEs
- * as chmod disables ACEs and set the security descriptor. Allocate
- * memory for the smb header, set security descriptor request security
- * descriptor parameters, and security descriptor itself
- */
- nsecdesclen = max_t(u32, nsecdesclen, DEFAULT_SEC_DESC_LEN);
- pnntsd = kmalloc(nsecdesclen, GFP_KERNEL);
- if (!pnntsd) {
- kfree(pntsd);
- cifs_put_tlink(tlink);
- return -ENOMEM;
- }
-
- rc = build_sec_desc(pntsd, pnntsd, secdesclen, &nsecdesclen, pnmode, uid, gid,
- mode_from_sid, id_from_sid, &aclflag);
-
- cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
-
- if (ops->set_acl == NULL)
- rc = -EOPNOTSUPP;
-
- if (!rc) {
- /* Set the security descriptor */
- rc = ops->set_acl(pnntsd, nsecdesclen, inode, path, aclflag);
- cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
- }
- cifs_put_tlink(tlink);
-
- kfree(pnntsd);
- kfree(pntsd);
- return rc;
-}
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
deleted file mode 100644
index ccbfc754bd3c..000000000000
--- a/fs/cifs/cifsacl.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2007
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#ifndef _CIFSACL_H
-#define _CIFSACL_H
-
-#define NUM_AUTHS (6) /* number of authority fields */
-#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
-
-#define READ_BIT 0x4
-#define WRITE_BIT 0x2
-#define EXEC_BIT 0x1
-
-#define ACL_OWNER_MASK 0700
-#define ACL_GROUP_MASK 0070
-#define ACL_EVERYONE_MASK 0007
-
-#define UBITSHIFT 6
-#define GBITSHIFT 3
-
-#define ACCESS_ALLOWED 0
-#define ACCESS_DENIED 1
-
-#define SIDOWNER 1
-#define SIDGROUP 2
-
-/*
- * Security Descriptor length containing DACL with 3 ACEs (one each for
- * owner, group and world).
- */
-#define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \
- sizeof(struct cifs_acl) + \
- (sizeof(struct cifs_ace) * 4))
-
-/*
- * Maximum size of a string representation of a SID:
- *
- * The fields are unsigned values in decimal. So:
- *
- * u8: max 3 bytes in decimal
- * u32: max 10 bytes in decimal
- *
- * "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
- *
- * For authority field, max is when all 6 values are non-zero and it must be
- * represented in hex. So "-0x" + 12 hex digits.
- *
- * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
- */
-#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
-#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
-
-struct cifs_ntsd {
- __le16 revision; /* revision level */
- __le16 type;
- __le32 osidoffset;
- __le32 gsidoffset;
- __le32 sacloffset;
- __le32 dacloffset;
-} __attribute__((packed));
-
-struct cifs_sid {
- __u8 revision; /* revision level */
- __u8 num_subauth;
- __u8 authority[NUM_AUTHS];
- __le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
-} __attribute__((packed));
-
-/* size of a struct cifs_sid, sans sub_auth array */
-#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
-
-struct cifs_acl {
- __le16 revision; /* revision level */
- __le16 size;
- __le32 num_aces;
-} __attribute__((packed));
-
-/* ACE types - see MS-DTYP 2.4.4.1 */
-#define ACCESS_ALLOWED_ACE_TYPE 0x00
-#define ACCESS_DENIED_ACE_TYPE 0x01
-#define SYSTEM_AUDIT_ACE_TYPE 0x02
-#define SYSTEM_ALARM_ACE_TYPE 0x03
-#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
-#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
-#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
-#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
-#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
-#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
-#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
-#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
-#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C
-#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D
-#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */
-#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
-#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
-#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
-#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
-#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13
-
-/* ACE flags */
-#define OBJECT_INHERIT_ACE 0x01
-#define CONTAINER_INHERIT_ACE 0x02
-#define NO_PROPAGATE_INHERIT_ACE 0x04
-#define INHERIT_ONLY_ACE 0x08
-#define INHERITED_ACE 0x10
-#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
-#define FAILED_ACCESS_ACE_FLAG 0x80
-
-struct cifs_ace {
- __u8 type; /* see above and MS-DTYP 2.4.4.1 */
- __u8 flags;
- __le16 size;
- __le32 access_req;
- struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
-} __attribute__((packed));
-
-/*
- * The current SMB3 form of security descriptor is similar to what was used for
- * cifs (see above) but some fields are split, and fields in the struct below
- * matches names of fields to the spec, MS-DTYP (see sections 2.4.5 and
- * 2.4.6). Note that "CamelCase" fields are used in this struct in order to
- * match the MS-DTYP and MS-SMB2 specs which define the wire format.
- */
-struct smb3_sd {
- __u8 Revision; /* revision level, MUST be one */
- __u8 Sbz1; /* only meaningful if 'RM' flag set below */
- __le16 Control;
- __le32 OffsetOwner;
- __le32 OffsetGroup;
- __le32 OffsetSacl;
- __le32 OffsetDacl;
-} __packed;
-
-/* Meaning of 'Control' field flags */
-#define ACL_CONTROL_SR 0x8000 /* Self relative */
-#define ACL_CONTROL_RM 0x4000 /* Resource manager control bits */
-#define ACL_CONTROL_PS 0x2000 /* SACL protected from inherits */
-#define ACL_CONTROL_PD 0x1000 /* DACL protected from inherits */
-#define ACL_CONTROL_SI 0x0800 /* SACL Auto-Inherited */
-#define ACL_CONTROL_DI 0x0400 /* DACL Auto-Inherited */
-#define ACL_CONTROL_SC 0x0200 /* SACL computed through inheritance */
-#define ACL_CONTROL_DC 0x0100 /* DACL computed through inheritence */
-#define ACL_CONTROL_SS 0x0080 /* Create server ACL */
-#define ACL_CONTROL_DT 0x0040 /* DACL provided by trusted source */
-#define ACL_CONTROL_SD 0x0020 /* SACL defaulted */
-#define ACL_CONTROL_SP 0x0010 /* SACL is present on object */
-#define ACL_CONTROL_DD 0x0008 /* DACL defaulted */
-#define ACL_CONTROL_DP 0x0004 /* DACL is present on object */
-#define ACL_CONTROL_GD 0x0002 /* Group was defaulted */
-#define ACL_CONTROL_OD 0x0001 /* User was defaulted */
-
-/* Meaning of AclRevision flags */
-#define ACL_REVISION 0x02 /* See section 2.4.4.1 of MS-DTYP */
-#define ACL_REVISION_DS 0x04 /* Additional AceTypes allowed */
-
-struct smb3_acl {
- u8 AclRevision; /* revision level */
- u8 Sbz1; /* MBZ */
- __le16 AclSize;
- __le16 AceCount;
- __le16 Sbz2; /* MBZ */
-} __packed;
-
-/*
- * Used to store the special 'NFS SIDs' used to persist the POSIX uid and gid
- * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
- */
-struct owner_sid {
- u8 Revision;
- u8 NumAuth;
- u8 Authority[6];
- __le32 SubAuthorities[3];
-} __packed;
-
-struct owner_group_sids {
- struct owner_sid owner;
- struct owner_sid group;
-} __packed;
-
-/*
- * Minimum security identifier can be one for system defined Users
- * and Groups such as NULL SID and World or Built-in accounts such
- * as Administrator and Guest and consists of
- * Revision + Num (Sub)Auths + Authority + Domain (one Subauthority)
- */
-#define MIN_SID_LEN (1 + 1 + 6 + 4) /* in bytes */
-
-/*
- * Minimum security descriptor can be one without any SACL and DACL and can
- * consist of revision, type, and two sids of minimum size for owner and group
- */
-#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN))
-
-#endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
deleted file mode 100644
index cbc18b4a9cb2..000000000000
--- a/fs/cifs/cifsencrypt.c
+++ /dev/null
@@ -1,733 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Encryption and hashing operations relating to NTLM, NTLMv2. See MS-NLMP
- * for more detailed information
- *
- * Copyright (C) International Business Machines Corp., 2005,2013
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifs_debug.h"
-#include "cifs_unicode.h"
-#include "cifsproto.h"
-#include "ntlmssp.h"
-#include <linux/ctype.h>
-#include <linux/random.h>
-#include <linux/highmem.h>
-#include <linux/fips.h>
-#include "../smbfs_common/arc4.h"
-#include <crypto/aead.h>
-
-int __cifs_calc_signature(struct smb_rqst *rqst,
- struct TCP_Server_Info *server, char *signature,
- struct shash_desc *shash)
-{
- int i;
- int rc;
- struct kvec *iov = rqst->rq_iov;
- int n_vec = rqst->rq_nvec;
-
- /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
- if (!is_smb1(server)) {
- if (iov[0].iov_len <= 4)
- return -EIO;
- i = 0;
- } else {
- if (n_vec < 2 || iov[0].iov_len != 4)
- return -EIO;
- i = 1; /* skip rfc1002 length */
- }
-
- for (; i < n_vec; i++) {
- if (iov[i].iov_len == 0)
- continue;
- if (iov[i].iov_base == NULL) {
- cifs_dbg(VFS, "null iovec entry\n");
- return -EIO;
- }
-
- rc = crypto_shash_update(shash,
- iov[i].iov_base, iov[i].iov_len);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update with payload\n",
- __func__);
- return rc;
- }
- }
-
- /* now hash over the rq_pages array */
- for (i = 0; i < rqst->rq_npages; i++) {
- void *kaddr;
- unsigned int len, offset;
-
- rqst_page_get_length(rqst, i, &len, &offset);
-
- kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
-
- rc = crypto_shash_update(shash, kaddr, len);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update with payload\n",
- __func__);
- kunmap(rqst->rq_pages[i]);
- return rc;
- }
-
- kunmap(rqst->rq_pages[i]);
- }
-
- rc = crypto_shash_final(shash, signature);
- if (rc)
- cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
-
- return rc;
-}
-
-/*
- * Calculate and return the CIFS signature based on the mac key and SMB PDU.
- * The 16 byte signature must be allocated by the caller. Note we only use the
- * 1st eight bytes and that the smb header signature field on input contains
- * the sequence number before this function is called. Also, this function
- * should be called with the server->srv_mutex held.
- */
-static int cifs_calc_signature(struct smb_rqst *rqst,
- struct TCP_Server_Info *server, char *signature)
-{
- int rc;
-
- if (!rqst->rq_iov || !signature || !server)
- return -EINVAL;
-
- rc = cifs_alloc_hash("md5", &server->secmech.md5);
- if (rc)
- return -1;
-
- rc = crypto_shash_init(server->secmech.md5);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
- return rc;
- }
-
- rc = crypto_shash_update(server->secmech.md5,
- server->session_key.response, server->session_key.len);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
- return rc;
- }
-
- return __cifs_calc_signature(rqst, server, signature, server->secmech.md5);
-}
-
-/* must be called with server->srv_mutex held */
-int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
- __u32 *pexpected_response_sequence_number)
-{
- int rc = 0;
- char smb_signature[20];
- struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
-
- if (rqst->rq_iov[0].iov_len != 4 ||
- rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
- return -EIO;
-
- if ((cifs_pdu == NULL) || (server == NULL))
- return -EINVAL;
-
- spin_lock(&server->srv_lock);
- if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
- server->tcpStatus == CifsNeedNegotiate) {
- spin_unlock(&server->srv_lock);
- return rc;
- }
- spin_unlock(&server->srv_lock);
-
- if (!server->session_estab) {
- memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
- return rc;
- }
-
- cifs_pdu->Signature.Sequence.SequenceNumber =
- cpu_to_le32(server->sequence_number);
- cifs_pdu->Signature.Sequence.Reserved = 0;
-
- *pexpected_response_sequence_number = ++server->sequence_number;
- ++server->sequence_number;
-
- rc = cifs_calc_signature(rqst, server, smb_signature);
- if (rc)
- memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
- else
- memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
-
- return rc;
-}
-
-int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
- __u32 *pexpected_response_sequence)
-{
- struct smb_rqst rqst = { .rq_iov = iov,
- .rq_nvec = n_vec };
-
- return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
-}
-
-/* must be called with server->srv_mutex held */
-int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
- __u32 *pexpected_response_sequence_number)
-{
- struct kvec iov[2];
-
- iov[0].iov_base = cifs_pdu;
- iov[0].iov_len = 4;
- iov[1].iov_base = (char *)cifs_pdu + 4;
- iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
-
- return cifs_sign_smbv(iov, 2, server,
- pexpected_response_sequence_number);
-}
-
-int cifs_verify_signature(struct smb_rqst *rqst,
- struct TCP_Server_Info *server,
- __u32 expected_sequence_number)
-{
- unsigned int rc;
- char server_response_sig[8];
- char what_we_think_sig_should_be[20];
- struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
-
- if (rqst->rq_iov[0].iov_len != 4 ||
- rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
- return -EIO;
-
- if (cifs_pdu == NULL || server == NULL)
- return -EINVAL;
-
- if (!server->session_estab)
- return 0;
-
- if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
- struct smb_com_lock_req *pSMB =
- (struct smb_com_lock_req *)cifs_pdu;
- if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
- return 0;
- }
-
- /* BB what if signatures are supposed to be on for session but
- server does not send one? BB */
-
- /* Do not need to verify session setups with signature "BSRSPYL " */
- if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
- cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
- cifs_pdu->Command);
-
- /* save off the origiginal signature so we can modify the smb and check
- its signature against what the server sent */
- memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
-
- cifs_pdu->Signature.Sequence.SequenceNumber =
- cpu_to_le32(expected_sequence_number);
- cifs_pdu->Signature.Sequence.Reserved = 0;
-
- cifs_server_lock(server);
- rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
- cifs_server_unlock(server);
-
- if (rc)
- return rc;
-
-/* cifs_dump_mem("what we think it should be: ",
- what_we_think_sig_should_be, 16); */
-
- if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
- return -EACCES;
- else
- return 0;
-
-}
-
-/* Build a proper attribute value/target info pairs blob.
- * Fill in netbios and dns domain name and workstation name
- * and client time (total five av pairs and + one end of fields indicator.
- * Allocate domain name which gets freed when session struct is deallocated.
- */
-static int
-build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
-{
- unsigned int dlen;
- unsigned int size = 2 * sizeof(struct ntlmssp2_name);
- char *defdmname = "WORKGROUP";
- unsigned char *blobptr;
- struct ntlmssp2_name *attrptr;
-
- if (!ses->domainName) {
- ses->domainName = kstrdup(defdmname, GFP_KERNEL);
- if (!ses->domainName)
- return -ENOMEM;
- }
-
- dlen = strlen(ses->domainName);
-
- /*
- * The length of this blob is two times the size of a
- * structure (av pair) which holds name/size
- * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) +
- * unicode length of a netbios domain name
- */
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.len = size + 2 * dlen;
- ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
- if (!ses->auth_key.response) {
- ses->auth_key.len = 0;
- return -ENOMEM;
- }
-
- blobptr = ses->auth_key.response;
- attrptr = (struct ntlmssp2_name *) blobptr;
-
- /*
- * As defined in MS-NTLM 3.3.2, just this av pair field
- * is sufficient as part of the temp
- */
- attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
- attrptr->length = cpu_to_le16(2 * dlen);
- blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
- cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
-
- return 0;
-}
-
-/* Server has provided av pairs/target info in the type 2 challenge
- * packet and we have plucked it and stored within smb session.
- * We parse that blob here to find netbios domain name to be used
- * as part of ntlmv2 authentication (in Target String), if not already
- * specified on the command line.
- * If this function returns without any error but without fetching
- * domain name, authentication may fail against some server but
- * may not fail against other (those who are not very particular
- * about target string i.e. for some, just user name might suffice.
- */
-static int
-find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
-{
- unsigned int attrsize;
- unsigned int type;
- unsigned int onesize = sizeof(struct ntlmssp2_name);
- unsigned char *blobptr;
- unsigned char *blobend;
- struct ntlmssp2_name *attrptr;
-
- if (!ses->auth_key.len || !ses->auth_key.response)
- return 0;
-
- blobptr = ses->auth_key.response;
- blobend = blobptr + ses->auth_key.len;
-
- while (blobptr + onesize < blobend) {
- attrptr = (struct ntlmssp2_name *) blobptr;
- type = le16_to_cpu(attrptr->type);
- if (type == NTLMSSP_AV_EOL)
- break;
- blobptr += 2; /* advance attr type */
- attrsize = le16_to_cpu(attrptr->length);
- blobptr += 2; /* advance attr size */
- if (blobptr + attrsize > blobend)
- break;
- if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
- if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
- break;
- if (!ses->domainName) {
- ses->domainName =
- kmalloc(attrsize + 1, GFP_KERNEL);
- if (!ses->domainName)
- return -ENOMEM;
- cifs_from_utf16(ses->domainName,
- (__le16 *)blobptr, attrsize, attrsize,
- nls_cp, NO_MAP_UNI_RSVD);
- break;
- }
- }
- blobptr += attrsize; /* advance attr value */
- }
-
- return 0;
-}
-
-/* Server has provided av pairs/target info in the type 2 challenge
- * packet and we have plucked it and stored within smb session.
- * We parse that blob here to find the server given timestamp
- * as part of ntlmv2 authentication (or local current time as
- * default in case of failure)
- */
-static __le64
-find_timestamp(struct cifs_ses *ses)
-{
- unsigned int attrsize;
- unsigned int type;
- unsigned int onesize = sizeof(struct ntlmssp2_name);
- unsigned char *blobptr;
- unsigned char *blobend;
- struct ntlmssp2_name *attrptr;
- struct timespec64 ts;
-
- if (!ses->auth_key.len || !ses->auth_key.response)
- return 0;
-
- blobptr = ses->auth_key.response;
- blobend = blobptr + ses->auth_key.len;
-
- while (blobptr + onesize < blobend) {
- attrptr = (struct ntlmssp2_name *) blobptr;
- type = le16_to_cpu(attrptr->type);
- if (type == NTLMSSP_AV_EOL)
- break;
- blobptr += 2; /* advance attr type */
- attrsize = le16_to_cpu(attrptr->length);
- blobptr += 2; /* advance attr size */
- if (blobptr + attrsize > blobend)
- break;
- if (type == NTLMSSP_AV_TIMESTAMP) {
- if (attrsize == sizeof(u64))
- return *((__le64 *)blobptr);
- }
- blobptr += attrsize; /* advance attr value */
- }
-
- ktime_get_real_ts64(&ts);
- return cpu_to_le64(cifs_UnixTimeToNT(ts));
-}
-
-static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
- const struct nls_table *nls_cp)
-{
- int rc = 0;
- int len;
- char nt_hash[CIFS_NTHASH_SIZE];
- __le16 *user;
- wchar_t *domain;
- wchar_t *server;
-
- if (!ses->server->secmech.hmacmd5) {
- cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
- return -1;
- }
-
- /* calculate md4 hash of password */
- E_md4hash(ses->password, nt_hash, nls_cp);
-
- rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm, nt_hash,
- CIFS_NTHASH_SIZE);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
- return rc;
- }
-
- rc = crypto_shash_init(ses->server->secmech.hmacmd5);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
- return rc;
- }
-
- /* convert ses->user_name to unicode */
- len = ses->user_name ? strlen(ses->user_name) : 0;
- user = kmalloc(2 + (len * 2), GFP_KERNEL);
- if (user == NULL) {
- rc = -ENOMEM;
- return rc;
- }
-
- if (len) {
- len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
- UniStrupr(user);
- } else {
- memset(user, '\0', 2);
- }
-
- rc = crypto_shash_update(ses->server->secmech.hmacmd5,
- (char *)user, 2 * len);
- kfree(user);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
- return rc;
- }
-
- /* convert ses->domainName to unicode and uppercase */
- if (ses->domainName) {
- len = strlen(ses->domainName);
-
- domain = kmalloc(2 + (len * 2), GFP_KERNEL);
- if (domain == NULL) {
- rc = -ENOMEM;
- return rc;
- }
- len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
- nls_cp);
- rc =
- crypto_shash_update(ses->server->secmech.hmacmd5,
- (char *)domain, 2 * len);
- kfree(domain);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update with domain\n",
- __func__);
- return rc;
- }
- } else {
- /* We use ses->ip_addr if no domain name available */
- len = strlen(ses->ip_addr);
-
- server = kmalloc(2 + (len * 2), GFP_KERNEL);
- if (server == NULL) {
- rc = -ENOMEM;
- return rc;
- }
- len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len,
- nls_cp);
- rc =
- crypto_shash_update(ses->server->secmech.hmacmd5,
- (char *)server, 2 * len);
- kfree(server);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update with server\n",
- __func__);
- return rc;
- }
- }
-
- rc = crypto_shash_final(ses->server->secmech.hmacmd5,
- ntlmv2_hash);
- if (rc)
- cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
-
- return rc;
-}
-
-static int
-CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
-{
- int rc;
- struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
- (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
- unsigned int hash_len;
-
- /* The MD5 hash starts at challenge_key.key */
- hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
- offsetof(struct ntlmv2_resp, challenge.key[0]));
-
- if (!ses->server->secmech.hmacmd5) {
- cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
- return -1;
- }
-
- rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm,
- ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
- __func__);
- return rc;
- }
-
- rc = crypto_shash_init(ses->server->secmech.hmacmd5);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
- return rc;
- }
-
- if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
- memcpy(ntlmv2->challenge.key,
- ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
- else
- memcpy(ntlmv2->challenge.key,
- ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
- rc = crypto_shash_update(ses->server->secmech.hmacmd5,
- ntlmv2->challenge.key, hash_len);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
- return rc;
- }
-
- /* Note that the MD5 digest over writes anon.challenge_key.key */
- rc = crypto_shash_final(ses->server->secmech.hmacmd5,
- ntlmv2->ntlmv2_hash);
- if (rc)
- cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
-
- return rc;
-}
-
-int
-setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
-{
- int rc;
- int baselen;
- unsigned int tilen;
- struct ntlmv2_resp *ntlmv2;
- char ntlmv2_hash[16];
- unsigned char *tiblob = NULL; /* target info blob */
- __le64 rsp_timestamp;
-
- if (nls_cp == NULL) {
- cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__);
- return -EINVAL;
- }
-
- if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
- if (!ses->domainName) {
- if (ses->domainAuto) {
- rc = find_domain_name(ses, nls_cp);
- if (rc) {
- cifs_dbg(VFS, "error %d finding domain name\n",
- rc);
- goto setup_ntlmv2_rsp_ret;
- }
- } else {
- ses->domainName = kstrdup("", GFP_KERNEL);
- }
- }
- } else {
- rc = build_avpair_blob(ses, nls_cp);
- if (rc) {
- cifs_dbg(VFS, "error %d building av pair blob\n", rc);
- goto setup_ntlmv2_rsp_ret;
- }
- }
-
- /* Must be within 5 minutes of the server (or in range +/-2h
- * in case of Mac OS X), so simply carry over server timestamp
- * (as Windows 7 does)
- */
- rsp_timestamp = find_timestamp(ses);
-
- baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
- tilen = ses->auth_key.len;
- tiblob = ses->auth_key.response;
-
- ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
- if (!ses->auth_key.response) {
- rc = -ENOMEM;
- ses->auth_key.len = 0;
- goto setup_ntlmv2_rsp_ret;
- }
- ses->auth_key.len += baselen;
-
- ntlmv2 = (struct ntlmv2_resp *)
- (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
- ntlmv2->blob_signature = cpu_to_le32(0x00000101);
- ntlmv2->reserved = 0;
- ntlmv2->time = rsp_timestamp;
-
- get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
- ntlmv2->reserved2 = 0;
-
- memcpy(ses->auth_key.response + baselen, tiblob, tilen);
-
- cifs_server_lock(ses->server);
-
- rc = cifs_alloc_hash("hmac(md5)", &ses->server->secmech.hmacmd5);
- if (rc) {
- goto unlock;
- }
-
- /* calculate ntlmv2_hash */
- rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
- if (rc) {
- cifs_dbg(VFS, "Could not get v2 hash rc %d\n", rc);
- goto unlock;
- }
-
- /* calculate first part of the client response (CR1) */
- rc = CalcNTLMv2_response(ses, ntlmv2_hash);
- if (rc) {
- cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
- goto unlock;
- }
-
- /* now calculate the session key for NTLMv2 */
- rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm,
- ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
- __func__);
- goto unlock;
- }
-
- rc = crypto_shash_init(ses->server->secmech.hmacmd5);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
- goto unlock;
- }
-
- rc = crypto_shash_update(ses->server->secmech.hmacmd5,
- ntlmv2->ntlmv2_hash,
- CIFS_HMAC_MD5_HASH_SIZE);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
- goto unlock;
- }
-
- rc = crypto_shash_final(ses->server->secmech.hmacmd5,
- ses->auth_key.response);
- if (rc)
- cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
-
-unlock:
- cifs_server_unlock(ses->server);
-setup_ntlmv2_rsp_ret:
- kfree_sensitive(tiblob);
-
- return rc;
-}
-
-int
-calc_seckey(struct cifs_ses *ses)
-{
- unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */
- struct arc4_ctx *ctx_arc4;
-
- if (fips_enabled)
- return -ENODEV;
-
- get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
-
- ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
- if (!ctx_arc4) {
- cifs_dbg(VFS, "Could not allocate arc4 context\n");
- return -ENOMEM;
- }
-
- cifs_arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
- cifs_arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
- CIFS_CPHTXT_SIZE);
-
- /* make secondary_key/nonce as session key */
- memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
- /* and make len as that of session key only */
- ses->auth_key.len = CIFS_SESS_KEY_SIZE;
-
- memzero_explicit(sec_key, CIFS_SESS_KEY_SIZE);
- kfree_sensitive(ctx_arc4);
- return 0;
-}
-
-void
-cifs_crypto_secmech_release(struct TCP_Server_Info *server)
-{
- cifs_free_hash(&server->secmech.aes_cmac);
- cifs_free_hash(&server->secmech.hmacsha256);
- cifs_free_hash(&server->secmech.md5);
- cifs_free_hash(&server->secmech.sha512);
- cifs_free_hash(&server->secmech.hmacmd5);
-
- if (server->secmech.enc) {
- crypto_free_aead(server->secmech.enc);
- server->secmech.enc = NULL;
- }
-
- if (server->secmech.dec) {
- crypto_free_aead(server->secmech.dec);
- server->secmech.dec = NULL;
- }
-}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
deleted file mode 100644
index 078df1e2dd18..000000000000
--- a/fs/cifs/cifsfs.c
+++ /dev/null
@@ -1,1857 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002,2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- * Common Internet FileSystem (CIFS) client
- *
- */
-
-/* Note that BB means BUGBUG (ie something to fix eventually) */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/mount.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/seq_file.h>
-#include <linux/vfs.h>
-#include <linux/mempool.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/namei.h>
-#include <linux/random.h>
-#include <linux/uuid.h>
-#include <linux/xattr.h>
-#include <uapi/linux/magic.h>
-#include <net/ipv6.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#define DECLARE_GLOBALS_HERE
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include <linux/mm.h>
-#include <linux/key-type.h>
-#include "cifs_spnego.h"
-#include "fscache.h"
-#ifdef CONFIG_CIFS_DFS_UPCALL
-#include "dfs_cache.h"
-#endif
-#ifdef CONFIG_CIFS_SWN_UPCALL
-#include "netlink.h"
-#endif
-#include "fs_context.h"
-#include "cached_dir.h"
-
-/*
- * DOS dates from 1980/1/1 through 2107/12/31
- * Protocol specifications indicate the range should be to 119, which
- * limits maximum year to 2099. But this range has not been checked.
- */
-#define SMB_DATE_MAX (127<<9 | 12<<5 | 31)
-#define SMB_DATE_MIN (0<<9 | 1<<5 | 1)
-#define SMB_TIME_MAX (23<<11 | 59<<5 | 29)
-
-int cifsFYI = 0;
-bool traceSMB;
-bool enable_oplocks = true;
-bool linuxExtEnabled = true;
-bool lookupCacheEnabled = true;
-bool disable_legacy_dialects; /* false by default */
-bool enable_gcm_256 = true;
-bool require_gcm_256; /* false by default */
-bool enable_negotiate_signing; /* false by default */
-unsigned int global_secflags = CIFSSEC_DEF;
-/* unsigned int ntlmv2_support = 0; */
-unsigned int sign_CIFS_PDUs = 1;
-
-/*
- * Global transaction id (XID) information
- */
-unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
-unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
-unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
-spinlock_t GlobalMid_Lock; /* protects above & list operations on midQ entries */
-
-/*
- * Global counters, updated atomically
- */
-atomic_t sesInfoAllocCount;
-atomic_t tconInfoAllocCount;
-atomic_t tcpSesNextId;
-atomic_t tcpSesAllocCount;
-atomic_t tcpSesReconnectCount;
-atomic_t tconInfoReconnectCount;
-
-atomic_t mid_count;
-atomic_t buf_alloc_count;
-atomic_t small_buf_alloc_count;
-#ifdef CONFIG_CIFS_STATS2
-atomic_t total_buf_alloc_count;
-atomic_t total_small_buf_alloc_count;
-#endif/* STATS2 */
-struct list_head cifs_tcp_ses_list;
-spinlock_t cifs_tcp_ses_lock;
-static const struct super_operations cifs_super_ops;
-unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
-module_param(CIFSMaxBufSize, uint, 0444);
-MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header) "
- "for CIFS requests. "
- "Default: 16384 Range: 8192 to 130048");
-unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
-module_param(cifs_min_rcv, uint, 0444);
-MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
- "1 to 64");
-unsigned int cifs_min_small = 30;
-module_param(cifs_min_small, uint, 0444);
-MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
- "Range: 2 to 256");
-unsigned int cifs_max_pending = CIFS_MAX_REQ;
-module_param(cifs_max_pending, uint, 0444);
-MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server for "
- "CIFS/SMB1 dialect (N/A for SMB3) "
- "Default: 32767 Range: 2 to 32767.");
-#ifdef CONFIG_CIFS_STATS2
-unsigned int slow_rsp_threshold = 1;
-module_param(slow_rsp_threshold, uint, 0644);
-MODULE_PARM_DESC(slow_rsp_threshold, "Amount of time (in seconds) to wait "
- "before logging that a response is delayed. "
- "Default: 1 (if set to 0 disables msg).");
-#endif /* STATS2 */
-
-module_param(enable_oplocks, bool, 0644);
-MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1");
-
-module_param(enable_gcm_256, bool, 0644);
-MODULE_PARM_DESC(enable_gcm_256, "Enable requesting strongest (256 bit) GCM encryption. Default: n/N/0");
-
-module_param(require_gcm_256, bool, 0644);
-MODULE_PARM_DESC(require_gcm_256, "Require strongest (256 bit) GCM encryption. Default: n/N/0");
-
-module_param(enable_negotiate_signing, bool, 0644);
-MODULE_PARM_DESC(enable_negotiate_signing, "Enable negotiating packet signing algorithm with server. Default: n/N/0");
-
-module_param(disable_legacy_dialects, bool, 0644);
-MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be "
- "helpful to restrict the ability to "
- "override the default dialects (SMB2.1, "
- "SMB3 and SMB3.02) on mount with old "
- "dialects (CIFS/SMB1 and SMB2) since "
- "vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker"
- " and less secure. Default: n/N/0");
-
-extern mempool_t *cifs_sm_req_poolp;
-extern mempool_t *cifs_req_poolp;
-extern mempool_t *cifs_mid_poolp;
-
-struct workqueue_struct *cifsiod_wq;
-struct workqueue_struct *decrypt_wq;
-struct workqueue_struct *fileinfo_put_wq;
-struct workqueue_struct *cifsoplockd_wq;
-struct workqueue_struct *deferredclose_wq;
-__u32 cifs_lock_secret;
-
-/*
- * Bumps refcount for cifs super block.
- * Note that it should be only called if a referece to VFS super block is
- * already held, e.g. in open-type syscalls context. Otherwise it can race with
- * atomic_dec_and_test in deactivate_locked_super.
- */
-void
-cifs_sb_active(struct super_block *sb)
-{
- struct cifs_sb_info *server = CIFS_SB(sb);
-
- if (atomic_inc_return(&server->active) == 1)
- atomic_inc(&sb->s_active);
-}
-
-void
-cifs_sb_deactive(struct super_block *sb)
-{
- struct cifs_sb_info *server = CIFS_SB(sb);
-
- if (atomic_dec_and_test(&server->active))
- deactivate_super(sb);
-}
-
-static int
-cifs_read_super(struct super_block *sb)
-{
- struct inode *inode;
- struct cifs_sb_info *cifs_sb;
- struct cifs_tcon *tcon;
- struct timespec64 ts;
- int rc = 0;
-
- cifs_sb = CIFS_SB(sb);
- tcon = cifs_sb_master_tcon(cifs_sb);
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
- sb->s_flags |= SB_POSIXACL;
-
- if (tcon->snapshot_time)
- sb->s_flags |= SB_RDONLY;
-
- if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files)
- sb->s_maxbytes = MAX_LFS_FILESIZE;
- else
- sb->s_maxbytes = MAX_NON_LFS;
-
- /*
- * Some very old servers like DOS and OS/2 used 2 second granularity
- * (while all current servers use 100ns granularity - see MS-DTYP)
- * but 1 second is the maximum allowed granularity for the VFS
- * so for old servers set time granularity to 1 second while for
- * everything else (current servers) set it to 100ns.
- */
- if ((tcon->ses->server->vals->protocol_id == SMB10_PROT_ID) &&
- ((tcon->ses->capabilities &
- tcon->ses->server->vals->cap_nt_find) == 0) &&
- !tcon->unix_ext) {
- sb->s_time_gran = 1000000000; /* 1 second is max allowed gran */
- ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0);
- sb->s_time_min = ts.tv_sec;
- ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX),
- cpu_to_le16(SMB_TIME_MAX), 0);
- sb->s_time_max = ts.tv_sec;
- } else {
- /*
- * Almost every server, including all SMB2+, uses DCE TIME
- * ie 100 nanosecond units, since 1601. See MS-DTYP and MS-FSCC
- */
- sb->s_time_gran = 100;
- ts = cifs_NTtimeToUnix(0);
- sb->s_time_min = ts.tv_sec;
- ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX));
- sb->s_time_max = ts.tv_sec;
- }
-
- sb->s_magic = CIFS_SUPER_MAGIC;
- sb->s_op = &cifs_super_ops;
- sb->s_xattr = cifs_xattr_handlers;
- rc = super_setup_bdi(sb);
- if (rc)
- goto out_no_root;
- /* tune readahead according to rsize if readahead size not set on mount */
- if (cifs_sb->ctx->rsize == 0)
- cifs_sb->ctx->rsize =
- tcon->ses->server->ops->negotiate_rsize(tcon, cifs_sb->ctx);
- if (cifs_sb->ctx->rasize)
- sb->s_bdi->ra_pages = cifs_sb->ctx->rasize / PAGE_SIZE;
- else
- sb->s_bdi->ra_pages = cifs_sb->ctx->rsize / PAGE_SIZE;
-
- sb->s_blocksize = CIFS_MAX_MSGSIZE;
- sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
- inode = cifs_root_iget(sb);
-
- if (IS_ERR(inode)) {
- rc = PTR_ERR(inode);
- goto out_no_root;
- }
-
- if (tcon->nocase)
- sb->s_d_op = &cifs_ci_dentry_ops;
- else
- sb->s_d_op = &cifs_dentry_ops;
-
- sb->s_root = d_make_root(inode);
- if (!sb->s_root) {
- rc = -ENOMEM;
- goto out_no_root;
- }
-
-#ifdef CONFIG_CIFS_NFSD_EXPORT
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- cifs_dbg(FYI, "export ops supported\n");
- sb->s_export_op = &cifs_export_ops;
- }
-#endif /* CONFIG_CIFS_NFSD_EXPORT */
-
- return 0;
-
-out_no_root:
- cifs_dbg(VFS, "%s: get root inode failed\n", __func__);
- return rc;
-}
-
-static void cifs_kill_sb(struct super_block *sb)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-
- /*
- * We ned to release all dentries for the cached directories
- * before we kill the sb.
- */
- if (cifs_sb->root) {
- close_all_cached_dirs(cifs_sb);
-
- /* finally release root dentry */
- dput(cifs_sb->root);
- cifs_sb->root = NULL;
- }
-
- kill_anon_super(sb);
- cifs_umount(cifs_sb);
-}
-
-static int
-cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
- struct super_block *sb = dentry->d_sb;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- struct TCP_Server_Info *server = tcon->ses->server;
- unsigned int xid;
- int rc = 0;
-
- xid = get_xid();
-
- if (le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength) > 0)
- buf->f_namelen =
- le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength);
- else
- buf->f_namelen = PATH_MAX;
-
- buf->f_fsid.val[0] = tcon->vol_serial_number;
- /* are using part of create time for more randomness, see man statfs */
- buf->f_fsid.val[1] = (int)le64_to_cpu(tcon->vol_create_time);
-
- buf->f_files = 0; /* undefined */
- buf->f_ffree = 0; /* unlimited */
-
- if (server->ops->queryfs)
- rc = server->ops->queryfs(xid, tcon, cifs_sb, buf);
-
- free_xid(xid);
- return rc;
-}
-
-static long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len)
-{
- struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- struct TCP_Server_Info *server = tcon->ses->server;
-
- if (server->ops->fallocate)
- return server->ops->fallocate(file, tcon, mode, off, len);
-
- return -EOPNOTSUPP;
-}
-
-static int cifs_permission(struct user_namespace *mnt_userns,
- struct inode *inode, int mask)
-{
- struct cifs_sb_info *cifs_sb;
-
- cifs_sb = CIFS_SB(inode->i_sb);
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
- if ((mask & MAY_EXEC) && !execute_ok(inode))
- return -EACCES;
- else
- return 0;
- } else /* file mode might have been restricted at mount time
- on the client (above and beyond ACL on servers) for
- servers which do not support setting and viewing mode bits,
- so allowing client to check permissions is useful */
- return generic_permission(&init_user_ns, inode, mask);
-}
-
-static struct kmem_cache *cifs_inode_cachep;
-static struct kmem_cache *cifs_req_cachep;
-static struct kmem_cache *cifs_mid_cachep;
-static struct kmem_cache *cifs_sm_req_cachep;
-mempool_t *cifs_sm_req_poolp;
-mempool_t *cifs_req_poolp;
-mempool_t *cifs_mid_poolp;
-
-static struct inode *
-cifs_alloc_inode(struct super_block *sb)
-{
- struct cifsInodeInfo *cifs_inode;
- cifs_inode = alloc_inode_sb(sb, cifs_inode_cachep, GFP_KERNEL);
- if (!cifs_inode)
- return NULL;
- cifs_inode->cifsAttrs = 0x20; /* default */
- cifs_inode->time = 0;
- /*
- * Until the file is open and we have gotten oplock info back from the
- * server, can not assume caching of file data or metadata.
- */
- cifs_set_oplock_level(cifs_inode, 0);
- cifs_inode->flags = 0;
- spin_lock_init(&cifs_inode->writers_lock);
- cifs_inode->writers = 0;
- cifs_inode->netfs.inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
- cifs_inode->server_eof = 0;
- cifs_inode->uniqueid = 0;
- cifs_inode->createtime = 0;
- cifs_inode->epoch = 0;
- spin_lock_init(&cifs_inode->open_file_lock);
- generate_random_uuid(cifs_inode->lease_key);
- cifs_inode->symlink_target = NULL;
-
- /*
- * Can not set i_flags here - they get immediately overwritten to zero
- * by the VFS.
- */
- /* cifs_inode->netfs.inode.i_flags = S_NOATIME | S_NOCMTIME; */
- INIT_LIST_HEAD(&cifs_inode->openFileList);
- INIT_LIST_HEAD(&cifs_inode->llist);
- INIT_LIST_HEAD(&cifs_inode->deferred_closes);
- spin_lock_init(&cifs_inode->deferred_lock);
- return &cifs_inode->netfs.inode;
-}
-
-static void
-cifs_free_inode(struct inode *inode)
-{
- struct cifsInodeInfo *cinode = CIFS_I(inode);
-
- if (S_ISLNK(inode->i_mode))
- kfree(cinode->symlink_target);
- kmem_cache_free(cifs_inode_cachep, cinode);
-}
-
-static void
-cifs_evict_inode(struct inode *inode)
-{
- truncate_inode_pages_final(&inode->i_data);
- if (inode->i_state & I_PINNING_FSCACHE_WB)
- cifs_fscache_unuse_inode_cookie(inode, true);
- cifs_fscache_release_inode_cookie(inode);
- clear_inode(inode);
-}
-
-static void
-cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
-{
- struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
- struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
-
- seq_puts(s, ",addr=");
-
- switch (server->dstaddr.ss_family) {
- case AF_INET:
- seq_printf(s, "%pI4", &sa->sin_addr.s_addr);
- break;
- case AF_INET6:
- seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr);
- if (sa6->sin6_scope_id)
- seq_printf(s, "%%%u", sa6->sin6_scope_id);
- break;
- default:
- seq_puts(s, "(unknown)");
- }
- if (server->rdma)
- seq_puts(s, ",rdma");
-}
-
-static void
-cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
-{
- if (ses->sectype == Unspecified) {
- if (ses->user_name == NULL)
- seq_puts(s, ",sec=none");
- return;
- }
-
- seq_puts(s, ",sec=");
-
- switch (ses->sectype) {
- case NTLMv2:
- seq_puts(s, "ntlmv2");
- break;
- case Kerberos:
- seq_puts(s, "krb5");
- break;
- case RawNTLMSSP:
- seq_puts(s, "ntlmssp");
- break;
- default:
- /* shouldn't ever happen */
- seq_puts(s, "unknown");
- break;
- }
-
- if (ses->sign)
- seq_puts(s, "i");
-
- if (ses->sectype == Kerberos)
- seq_printf(s, ",cruid=%u",
- from_kuid_munged(&init_user_ns, ses->cred_uid));
-}
-
-static void
-cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
-{
- seq_puts(s, ",cache=");
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
- seq_puts(s, "strict");
- else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
- seq_puts(s, "none");
- else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
- seq_puts(s, "singleclient"); /* assume only one client access */
- else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)
- seq_puts(s, "ro"); /* read only caching assumed */
- else
- seq_puts(s, "loose");
-}
-
-/*
- * cifs_show_devname() is used so we show the mount device name with correct
- * format (e.g. forward slashes vs. back slashes) in /proc/mounts
- */
-static int cifs_show_devname(struct seq_file *m, struct dentry *root)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
- char *devname = kstrdup(cifs_sb->ctx->source, GFP_KERNEL);
-
- if (devname == NULL)
- seq_puts(m, "none");
- else {
- convert_delimiter(devname, '/');
- /* escape all spaces in share names */
- seq_escape(m, devname, " \t");
- kfree(devname);
- }
- return 0;
-}
-
-/*
- * cifs_show_options() is for displaying mount options in /proc/mounts.
- * Not all settable options are displayed but most of the important
- * ones are.
- */
-static int
-cifs_show_options(struct seq_file *s, struct dentry *root)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- struct sockaddr *srcaddr;
- srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
-
- seq_show_option(s, "vers", tcon->ses->server->vals->version_string);
- cifs_show_security(s, tcon->ses);
- cifs_show_cache_flavor(s, cifs_sb);
-
- if (tcon->no_lease)
- seq_puts(s, ",nolease");
- if (cifs_sb->ctx->multiuser)
- seq_puts(s, ",multiuser");
- else if (tcon->ses->user_name)
- seq_show_option(s, "username", tcon->ses->user_name);
-
- if (tcon->ses->domainName && tcon->ses->domainName[0] != 0)
- seq_show_option(s, "domain", tcon->ses->domainName);
-
- if (srcaddr->sa_family != AF_UNSPEC) {
- struct sockaddr_in *saddr4;
- struct sockaddr_in6 *saddr6;
- saddr4 = (struct sockaddr_in *)srcaddr;
- saddr6 = (struct sockaddr_in6 *)srcaddr;
- if (srcaddr->sa_family == AF_INET6)
- seq_printf(s, ",srcaddr=%pI6c",
- &saddr6->sin6_addr);
- else if (srcaddr->sa_family == AF_INET)
- seq_printf(s, ",srcaddr=%pI4",
- &saddr4->sin_addr.s_addr);
- else
- seq_printf(s, ",srcaddr=BAD-AF:%i",
- (int)(srcaddr->sa_family));
- }
-
- seq_printf(s, ",uid=%u",
- from_kuid_munged(&init_user_ns, cifs_sb->ctx->linux_uid));
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
- seq_puts(s, ",forceuid");
- else
- seq_puts(s, ",noforceuid");
-
- seq_printf(s, ",gid=%u",
- from_kgid_munged(&init_user_ns, cifs_sb->ctx->linux_gid));
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
- seq_puts(s, ",forcegid");
- else
- seq_puts(s, ",noforcegid");
-
- cifs_show_address(s, tcon->ses->server);
-
- if (!tcon->unix_ext)
- seq_printf(s, ",file_mode=0%ho,dir_mode=0%ho",
- cifs_sb->ctx->file_mode,
- cifs_sb->ctx->dir_mode);
- if (cifs_sb->ctx->iocharset)
- seq_printf(s, ",iocharset=%s", cifs_sb->ctx->iocharset);
- if (tcon->seal)
- seq_puts(s, ",seal");
- else if (tcon->ses->server->ignore_signature)
- seq_puts(s, ",signloosely");
- if (tcon->nocase)
- seq_puts(s, ",nocase");
- if (tcon->nodelete)
- seq_puts(s, ",nodelete");
- if (cifs_sb->ctx->no_sparse)
- seq_puts(s, ",nosparse");
- if (tcon->local_lease)
- seq_puts(s, ",locallease");
- if (tcon->retry)
- seq_puts(s, ",hard");
- else
- seq_puts(s, ",soft");
- if (tcon->use_persistent)
- seq_puts(s, ",persistenthandles");
- else if (tcon->use_resilient)
- seq_puts(s, ",resilienthandles");
- if (tcon->posix_extensions)
- seq_puts(s, ",posix");
- else if (tcon->unix_ext)
- seq_puts(s, ",unix");
- else
- seq_puts(s, ",nounix");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
- seq_puts(s, ",nodfs");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
- seq_puts(s, ",posixpaths");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
- seq_puts(s, ",setuids");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
- seq_puts(s, ",idsfromsid");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
- seq_puts(s, ",serverino");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
- seq_puts(s, ",rwpidforward");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL)
- seq_puts(s, ",forcemand");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
- seq_puts(s, ",nouser_xattr");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
- seq_puts(s, ",mapchars");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
- seq_puts(s, ",mapposix");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
- seq_puts(s, ",sfu");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
- seq_puts(s, ",nobrl");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_HANDLE_CACHE)
- seq_puts(s, ",nohandlecache");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
- seq_puts(s, ",modefromsid");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
- seq_puts(s, ",cifsacl");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
- seq_puts(s, ",dynperm");
- if (root->d_sb->s_flags & SB_POSIXACL)
- seq_puts(s, ",acl");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
- seq_puts(s, ",mfsymlinks");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
- seq_puts(s, ",fsc");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)
- seq_puts(s, ",nostrictsync");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
- seq_puts(s, ",noperm");
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
- seq_printf(s, ",backupuid=%u",
- from_kuid_munged(&init_user_ns,
- cifs_sb->ctx->backupuid));
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID)
- seq_printf(s, ",backupgid=%u",
- from_kgid_munged(&init_user_ns,
- cifs_sb->ctx->backupgid));
-
- seq_printf(s, ",rsize=%u", cifs_sb->ctx->rsize);
- seq_printf(s, ",wsize=%u", cifs_sb->ctx->wsize);
- seq_printf(s, ",bsize=%u", cifs_sb->ctx->bsize);
- if (cifs_sb->ctx->rasize)
- seq_printf(s, ",rasize=%u", cifs_sb->ctx->rasize);
- if (tcon->ses->server->min_offload)
- seq_printf(s, ",esize=%u", tcon->ses->server->min_offload);
- seq_printf(s, ",echo_interval=%lu",
- tcon->ses->server->echo_interval / HZ);
-
- /* Only display the following if overridden on mount */
- if (tcon->ses->server->max_credits != SMB2_MAX_CREDITS_AVAILABLE)
- seq_printf(s, ",max_credits=%u", tcon->ses->server->max_credits);
- if (tcon->ses->server->tcp_nodelay)
- seq_puts(s, ",tcpnodelay");
- if (tcon->ses->server->noautotune)
- seq_puts(s, ",noautotune");
- if (tcon->ses->server->noblocksnd)
- seq_puts(s, ",noblocksend");
-
- if (tcon->snapshot_time)
- seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
- if (tcon->handle_timeout)
- seq_printf(s, ",handletimeout=%u", tcon->handle_timeout);
-
- /*
- * Display file and directory attribute timeout in seconds.
- * If file and directory attribute timeout the same then actimeo
- * was likely specified on mount
- */
- if (cifs_sb->ctx->acdirmax == cifs_sb->ctx->acregmax)
- seq_printf(s, ",actimeo=%lu", cifs_sb->ctx->acregmax / HZ);
- else {
- seq_printf(s, ",acdirmax=%lu", cifs_sb->ctx->acdirmax / HZ);
- seq_printf(s, ",acregmax=%lu", cifs_sb->ctx->acregmax / HZ);
- }
- seq_printf(s, ",closetimeo=%lu", cifs_sb->ctx->closetimeo / HZ);
-
- if (tcon->ses->chan_max > 1)
- seq_printf(s, ",multichannel,max_channels=%zu",
- tcon->ses->chan_max);
-
- if (tcon->use_witness)
- seq_puts(s, ",witness");
-
- return 0;
-}
-
-static void cifs_umount_begin(struct super_block *sb)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifs_tcon *tcon;
-
- if (cifs_sb == NULL)
- return;
-
- tcon = cifs_sb_master_tcon(cifs_sb);
-
- spin_lock(&cifs_tcp_ses_lock);
- spin_lock(&tcon->tc_lock);
- if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
- /* we have other mounts to same share or we have
- already tried to umount this and woken up
- all waiting network requests, nothing to do */
- spin_unlock(&tcon->tc_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- return;
- }
- /*
- * can not set tcon->status to TID_EXITING yet since we don't know if umount -f will
- * fail later (e.g. due to open files). TID_EXITING will be set just before tdis req sent
- */
- spin_unlock(&tcon->tc_lock);
- spin_unlock(&cifs_tcp_ses_lock);
-
- cifs_close_all_deferred_files(tcon);
- /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
- /* cancel_notify_requests(tcon); */
- if (tcon->ses && tcon->ses->server) {
- cifs_dbg(FYI, "wake up tasks now - umount begin not complete\n");
- wake_up_all(&tcon->ses->server->request_q);
- wake_up_all(&tcon->ses->server->response_q);
- msleep(1); /* yield */
- /* we have to kick the requests once more */
- wake_up_all(&tcon->ses->server->response_q);
- msleep(1);
- }
-
- return;
-}
-
-static int cifs_freeze(struct super_block *sb)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifs_tcon *tcon;
-
- if (cifs_sb == NULL)
- return 0;
-
- tcon = cifs_sb_master_tcon(cifs_sb);
-
- cifs_close_all_deferred_files(tcon);
- return 0;
-}
-
-#ifdef CONFIG_CIFS_STATS2
-static int cifs_show_stats(struct seq_file *s, struct dentry *root)
-{
- /* BB FIXME */
- return 0;
-}
-#endif
-
-static int cifs_write_inode(struct inode *inode, struct writeback_control *wbc)
-{
- fscache_unpin_writeback(wbc, cifs_inode_cookie(inode));
- return 0;
-}
-
-static int cifs_drop_inode(struct inode *inode)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-
- /* no serverino => unconditional eviction */
- return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ||
- generic_drop_inode(inode);
-}
-
-static const struct super_operations cifs_super_ops = {
- .statfs = cifs_statfs,
- .alloc_inode = cifs_alloc_inode,
- .write_inode = cifs_write_inode,
- .free_inode = cifs_free_inode,
- .drop_inode = cifs_drop_inode,
- .evict_inode = cifs_evict_inode,
-/* .show_path = cifs_show_path, */ /* Would we ever need show path? */
- .show_devname = cifs_show_devname,
-/* .delete_inode = cifs_delete_inode, */ /* Do not need above
- function unless later we add lazy close of inodes or unless the
- kernel forgets to call us with the same number of releases (closes)
- as opens */
- .show_options = cifs_show_options,
- .umount_begin = cifs_umount_begin,
- .freeze_fs = cifs_freeze,
-#ifdef CONFIG_CIFS_STATS2
- .show_stats = cifs_show_stats,
-#endif
-};
-
-/*
- * Get root dentry from superblock according to prefix path mount option.
- * Return dentry with refcount + 1 on success and NULL otherwise.
- */
-static struct dentry *
-cifs_get_root(struct smb3_fs_context *ctx, struct super_block *sb)
-{
- struct dentry *dentry;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- char *full_path = NULL;
- char *s, *p;
- char sep;
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
- return dget(sb->s_root);
-
- full_path = cifs_build_path_to_root(ctx, cifs_sb,
- cifs_sb_master_tcon(cifs_sb), 0);
- if (full_path == NULL)
- return ERR_PTR(-ENOMEM);
-
- cifs_dbg(FYI, "Get root dentry for %s\n", full_path);
-
- sep = CIFS_DIR_SEP(cifs_sb);
- dentry = dget(sb->s_root);
- s = full_path;
-
- do {
- struct inode *dir = d_inode(dentry);
- struct dentry *child;
-
- if (!S_ISDIR(dir->i_mode)) {
- dput(dentry);
- dentry = ERR_PTR(-ENOTDIR);
- break;
- }
-
- /* skip separators */
- while (*s == sep)
- s++;
- if (!*s)
- break;
- p = s++;
- /* next separator */
- while (*s && *s != sep)
- s++;
-
- child = lookup_positive_unlocked(p, dentry, s - p);
- dput(dentry);
- dentry = child;
- } while (!IS_ERR(dentry));
- kfree(full_path);
- return dentry;
-}
-
-static int cifs_set_super(struct super_block *sb, void *data)
-{
- struct cifs_mnt_data *mnt_data = data;
- sb->s_fs_info = mnt_data->cifs_sb;
- return set_anon_super(sb, NULL);
-}
-
-struct dentry *
-cifs_smb3_do_mount(struct file_system_type *fs_type,
- int flags, struct smb3_fs_context *old_ctx)
-{
- int rc;
- struct super_block *sb = NULL;
- struct cifs_sb_info *cifs_sb = NULL;
- struct cifs_mnt_data mnt_data;
- struct dentry *root;
-
- /*
- * Prints in Kernel / CIFS log the attempted mount operation
- * If CIFS_DEBUG && cifs_FYI
- */
- if (cifsFYI)
- cifs_dbg(FYI, "Devname: %s flags: %d\n", old_ctx->UNC, flags);
- else
- cifs_info("Attempting to mount %s\n", old_ctx->UNC);
-
- cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
- if (cifs_sb == NULL) {
- root = ERR_PTR(-ENOMEM);
- goto out;
- }
-
- cifs_sb->ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
- if (!cifs_sb->ctx) {
- root = ERR_PTR(-ENOMEM);
- goto out;
- }
- rc = smb3_fs_context_dup(cifs_sb->ctx, old_ctx);
- if (rc) {
- root = ERR_PTR(rc);
- goto out;
- }
-
- rc = cifs_setup_volume_info(cifs_sb->ctx, NULL, NULL);
- if (rc) {
- root = ERR_PTR(rc);
- goto out;
- }
-
- rc = cifs_setup_cifs_sb(cifs_sb);
- if (rc) {
- root = ERR_PTR(rc);
- goto out;
- }
-
- rc = cifs_mount(cifs_sb, cifs_sb->ctx);
- if (rc) {
- if (!(flags & SB_SILENT))
- cifs_dbg(VFS, "cifs_mount failed w/return code = %d\n",
- rc);
- root = ERR_PTR(rc);
- goto out;
- }
-
- mnt_data.ctx = cifs_sb->ctx;
- mnt_data.cifs_sb = cifs_sb;
- mnt_data.flags = flags;
-
- /* BB should we make this contingent on mount parm? */
- flags |= SB_NODIRATIME | SB_NOATIME;
-
- sb = sget(fs_type, cifs_match_super, cifs_set_super, flags, &mnt_data);
- if (IS_ERR(sb)) {
- root = ERR_CAST(sb);
- cifs_umount(cifs_sb);
- cifs_sb = NULL;
- goto out;
- }
-
- if (sb->s_root) {
- cifs_dbg(FYI, "Use existing superblock\n");
- cifs_umount(cifs_sb);
- cifs_sb = NULL;
- } else {
- rc = cifs_read_super(sb);
- if (rc) {
- root = ERR_PTR(rc);
- goto out_super;
- }
-
- sb->s_flags |= SB_ACTIVE;
- }
-
- root = cifs_get_root(cifs_sb ? cifs_sb->ctx : old_ctx, sb);
- if (IS_ERR(root))
- goto out_super;
-
- if (cifs_sb)
- cifs_sb->root = dget(root);
-
- cifs_dbg(FYI, "dentry root is: %p\n", root);
- return root;
-
-out_super:
- deactivate_locked_super(sb);
- return root;
-out:
- if (cifs_sb) {
- if (!sb || IS_ERR(sb)) { /* otherwise kill_sb will handle */
- kfree(cifs_sb->prepath);
- smb3_cleanup_fs_context(cifs_sb->ctx);
- kfree(cifs_sb);
- }
- }
- return root;
-}
-
-
-static ssize_t
-cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
-{
- ssize_t rc;
- struct inode *inode = file_inode(iocb->ki_filp);
-
- if (iocb->ki_flags & IOCB_DIRECT)
- return cifs_user_readv(iocb, iter);
-
- rc = cifs_revalidate_mapping(inode);
- if (rc)
- return rc;
-
- return generic_file_read_iter(iocb, iter);
-}
-
-static ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
-{
- struct inode *inode = file_inode(iocb->ki_filp);
- struct cifsInodeInfo *cinode = CIFS_I(inode);
- ssize_t written;
- int rc;
-
- if (iocb->ki_filp->f_flags & O_DIRECT) {
- written = cifs_user_writev(iocb, from);
- if (written > 0 && CIFS_CACHE_READ(cinode)) {
- cifs_zap_mapping(inode);
- cifs_dbg(FYI,
- "Set no oplock for inode=%p after a write operation\n",
- inode);
- cinode->oplock = 0;
- }
- return written;
- }
-
- written = cifs_get_writer(cinode);
- if (written)
- return written;
-
- written = generic_file_write_iter(iocb, from);
-
- if (CIFS_CACHE_WRITE(CIFS_I(inode)))
- goto out;
-
- rc = filemap_fdatawrite(inode->i_mapping);
- if (rc)
- cifs_dbg(FYI, "cifs_file_write_iter: %d rc on %p inode\n",
- rc, inode);
-
-out:
- cifs_put_writer(cinode);
- return written;
-}
-
-static loff_t cifs_llseek(struct file *file, loff_t offset, int whence)
-{
- struct cifsFileInfo *cfile = file->private_data;
- struct cifs_tcon *tcon;
-
- /*
- * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate
- * the cached file length
- */
- if (whence != SEEK_SET && whence != SEEK_CUR) {
- int rc;
- struct inode *inode = file_inode(file);
-
- /*
- * We need to be sure that all dirty pages are written and the
- * server has the newest file length.
- */
- if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
- inode->i_mapping->nrpages != 0) {
- rc = filemap_fdatawait(inode->i_mapping);
- if (rc) {
- mapping_set_error(inode->i_mapping, rc);
- return rc;
- }
- }
- /*
- * Some applications poll for the file length in this strange
- * way so we must seek to end on non-oplocked files by
- * setting the revalidate time to zero.
- */
- CIFS_I(inode)->time = 0;
-
- rc = cifs_revalidate_file_attr(file);
- if (rc < 0)
- return (loff_t)rc;
- }
- if (cfile && cfile->tlink) {
- tcon = tlink_tcon(cfile->tlink);
- if (tcon->ses->server->ops->llseek)
- return tcon->ses->server->ops->llseek(file, tcon,
- offset, whence);
- }
- return generic_file_llseek(file, offset, whence);
-}
-
-static int
-cifs_setlease(struct file *file, long arg, struct file_lock **lease, void **priv)
-{
- /*
- * Note that this is called by vfs setlease with i_lock held to
- * protect *lease from going away.
- */
- struct inode *inode = file_inode(file);
- struct cifsFileInfo *cfile = file->private_data;
-
- if (!(S_ISREG(inode->i_mode)))
- return -EINVAL;
-
- /* Check if file is oplocked if this is request for new lease */
- if (arg == F_UNLCK ||
- ((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
- ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode))))
- return generic_setlease(file, arg, lease, priv);
- else if (tlink_tcon(cfile->tlink)->local_lease &&
- !CIFS_CACHE_READ(CIFS_I(inode)))
- /*
- * If the server claims to support oplock on this file, then we
- * still need to check oplock even if the local_lease mount
- * option is set, but there are servers which do not support
- * oplock for which this mount option may be useful if the user
- * knows that the file won't be changed on the server by anyone
- * else.
- */
- return generic_setlease(file, arg, lease, priv);
- else
- return -EAGAIN;
-}
-
-struct file_system_type cifs_fs_type = {
- .owner = THIS_MODULE,
- .name = "cifs",
- .init_fs_context = smb3_init_fs_context,
- .parameters = smb3_fs_parameters,
- .kill_sb = cifs_kill_sb,
- .fs_flags = FS_RENAME_DOES_D_MOVE,
-};
-MODULE_ALIAS_FS("cifs");
-
-struct file_system_type smb3_fs_type = {
- .owner = THIS_MODULE,
- .name = "smb3",
- .init_fs_context = smb3_init_fs_context,
- .parameters = smb3_fs_parameters,
- .kill_sb = cifs_kill_sb,
- .fs_flags = FS_RENAME_DOES_D_MOVE,
-};
-MODULE_ALIAS_FS("smb3");
-MODULE_ALIAS("smb3");
-
-const struct inode_operations cifs_dir_inode_ops = {
- .create = cifs_create,
- .atomic_open = cifs_atomic_open,
- .lookup = cifs_lookup,
- .getattr = cifs_getattr,
- .unlink = cifs_unlink,
- .link = cifs_hardlink,
- .mkdir = cifs_mkdir,
- .rmdir = cifs_rmdir,
- .rename = cifs_rename2,
- .permission = cifs_permission,
- .setattr = cifs_setattr,
- .symlink = cifs_symlink,
- .mknod = cifs_mknod,
- .listxattr = cifs_listxattr,
-};
-
-const struct inode_operations cifs_file_inode_ops = {
- .setattr = cifs_setattr,
- .getattr = cifs_getattr,
- .permission = cifs_permission,
- .listxattr = cifs_listxattr,
- .fiemap = cifs_fiemap,
-};
-
-const char *cifs_get_link(struct dentry *dentry, struct inode *inode,
- struct delayed_call *done)
-{
- char *target_path;
-
- target_path = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!target_path)
- return ERR_PTR(-ENOMEM);
-
- spin_lock(&inode->i_lock);
- if (likely(CIFS_I(inode)->symlink_target)) {
- strscpy(target_path, CIFS_I(inode)->symlink_target, PATH_MAX);
- } else {
- kfree(target_path);
- target_path = ERR_PTR(-EOPNOTSUPP);
- }
- spin_unlock(&inode->i_lock);
-
- if (!IS_ERR(target_path))
- set_delayed_call(done, kfree_link, target_path);
-
- return target_path;
-}
-
-const struct inode_operations cifs_symlink_inode_ops = {
- .get_link = cifs_get_link,
- .permission = cifs_permission,
- .listxattr = cifs_listxattr,
-};
-
-static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
- struct file *dst_file, loff_t destoff, loff_t len,
- unsigned int remap_flags)
-{
- struct inode *src_inode = file_inode(src_file);
- struct inode *target_inode = file_inode(dst_file);
- struct cifsFileInfo *smb_file_src = src_file->private_data;
- struct cifsFileInfo *smb_file_target;
- struct cifs_tcon *target_tcon;
- unsigned int xid;
- int rc;
-
- if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
- return -EINVAL;
-
- cifs_dbg(FYI, "clone range\n");
-
- xid = get_xid();
-
- if (!src_file->private_data || !dst_file->private_data) {
- rc = -EBADF;
- cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
- goto out;
- }
-
- smb_file_target = dst_file->private_data;
- target_tcon = tlink_tcon(smb_file_target->tlink);
-
- /*
- * Note: cifs case is easier than btrfs since server responsible for
- * checks for proper open modes and file type and if it wants
- * server could even support copy of range where source = target
- */
- lock_two_nondirectories(target_inode, src_inode);
-
- if (len == 0)
- len = src_inode->i_size - off;
-
- cifs_dbg(FYI, "about to flush pages\n");
- /* should we flush first and last page first */
- truncate_inode_pages_range(&target_inode->i_data, destoff,
- PAGE_ALIGN(destoff + len)-1);
-
- if (target_tcon->ses->server->ops->duplicate_extents)
- rc = target_tcon->ses->server->ops->duplicate_extents(xid,
- smb_file_src, smb_file_target, off, len, destoff);
- else
- rc = -EOPNOTSUPP;
-
- /* force revalidate of size and timestamps of target file now
- that target is updated on the server */
- CIFS_I(target_inode)->time = 0;
- /* although unlocking in the reverse order from locking is not
- strictly necessary here it is a little cleaner to be consistent */
- unlock_two_nondirectories(src_inode, target_inode);
-out:
- free_xid(xid);
- return rc < 0 ? rc : len;
-}
-
-ssize_t cifs_file_copychunk_range(unsigned int xid,
- struct file *src_file, loff_t off,
- struct file *dst_file, loff_t destoff,
- size_t len, unsigned int flags)
-{
- struct inode *src_inode = file_inode(src_file);
- struct inode *target_inode = file_inode(dst_file);
- struct cifsFileInfo *smb_file_src;
- struct cifsFileInfo *smb_file_target;
- struct cifs_tcon *src_tcon;
- struct cifs_tcon *target_tcon;
- ssize_t rc;
-
- cifs_dbg(FYI, "copychunk range\n");
-
- if (!src_file->private_data || !dst_file->private_data) {
- rc = -EBADF;
- cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
- goto out;
- }
-
- rc = -EXDEV;
- smb_file_target = dst_file->private_data;
- smb_file_src = src_file->private_data;
- src_tcon = tlink_tcon(smb_file_src->tlink);
- target_tcon = tlink_tcon(smb_file_target->tlink);
-
- if (src_tcon->ses != target_tcon->ses) {
- cifs_dbg(VFS, "source and target of copy not on same server\n");
- goto out;
- }
-
- rc = -EOPNOTSUPP;
- if (!target_tcon->ses->server->ops->copychunk_range)
- goto out;
-
- /*
- * Note: cifs case is easier than btrfs since server responsible for
- * checks for proper open modes and file type and if it wants
- * server could even support copy of range where source = target
- */
- lock_two_nondirectories(target_inode, src_inode);
-
- cifs_dbg(FYI, "about to flush pages\n");
-
- rc = filemap_write_and_wait_range(src_inode->i_mapping, off,
- off + len - 1);
- if (rc)
- goto unlock;
-
- /* should we flush first and last page first */
- truncate_inode_pages(&target_inode->i_data, 0);
-
- rc = file_modified(dst_file);
- if (!rc)
- rc = target_tcon->ses->server->ops->copychunk_range(xid,
- smb_file_src, smb_file_target, off, len, destoff);
-
- file_accessed(src_file);
-
- /* force revalidate of size and timestamps of target file now
- * that target is updated on the server
- */
- CIFS_I(target_inode)->time = 0;
-
-unlock:
- /* although unlocking in the reverse order from locking is not
- * strictly necessary here it is a little cleaner to be consistent
- */
- unlock_two_nondirectories(src_inode, target_inode);
-
-out:
- return rc;
-}
-
-/*
- * Directory operations under CIFS/SMB2/SMB3 are synchronous, so fsync()
- * is a dummy operation.
- */
-static int cifs_dir_fsync(struct file *file, loff_t start, loff_t end, int datasync)
-{
- cifs_dbg(FYI, "Sync directory - name: %pD datasync: 0x%x\n",
- file, datasync);
-
- return 0;
-}
-
-static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
- struct file *dst_file, loff_t destoff,
- size_t len, unsigned int flags)
-{
- unsigned int xid = get_xid();
- ssize_t rc;
- struct cifsFileInfo *cfile = dst_file->private_data;
-
- if (cfile->swapfile) {
- rc = -EOPNOTSUPP;
- free_xid(xid);
- return rc;
- }
-
- rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff,
- len, flags);
- free_xid(xid);
-
- if (rc == -EOPNOTSUPP || rc == -EXDEV)
- rc = generic_copy_file_range(src_file, off, dst_file,
- destoff, len, flags);
- return rc;
-}
-
-const struct file_operations cifs_file_ops = {
- .read_iter = cifs_loose_read_iter,
- .write_iter = cifs_file_write_iter,
- .open = cifs_open,
- .release = cifs_close,
- .lock = cifs_lock,
- .flock = cifs_flock,
- .fsync = cifs_fsync,
- .flush = cifs_flush,
- .mmap = cifs_file_mmap,
- .splice_read = generic_file_splice_read,
- .splice_write = iter_file_splice_write,
- .llseek = cifs_llseek,
- .unlocked_ioctl = cifs_ioctl,
- .copy_file_range = cifs_copy_file_range,
- .remap_file_range = cifs_remap_file_range,
- .setlease = cifs_setlease,
- .fallocate = cifs_fallocate,
-};
-
-const struct file_operations cifs_file_strict_ops = {
- .read_iter = cifs_strict_readv,
- .write_iter = cifs_strict_writev,
- .open = cifs_open,
- .release = cifs_close,
- .lock = cifs_lock,
- .flock = cifs_flock,
- .fsync = cifs_strict_fsync,
- .flush = cifs_flush,
- .mmap = cifs_file_strict_mmap,
- .splice_read = generic_file_splice_read,
- .splice_write = iter_file_splice_write,
- .llseek = cifs_llseek,
- .unlocked_ioctl = cifs_ioctl,
- .copy_file_range = cifs_copy_file_range,
- .remap_file_range = cifs_remap_file_range,
- .setlease = cifs_setlease,
- .fallocate = cifs_fallocate,
-};
-
-const struct file_operations cifs_file_direct_ops = {
- .read_iter = cifs_direct_readv,
- .write_iter = cifs_direct_writev,
- .open = cifs_open,
- .release = cifs_close,
- .lock = cifs_lock,
- .flock = cifs_flock,
- .fsync = cifs_fsync,
- .flush = cifs_flush,
- .mmap = cifs_file_mmap,
- .splice_read = generic_file_splice_read,
- .splice_write = iter_file_splice_write,
- .unlocked_ioctl = cifs_ioctl,
- .copy_file_range = cifs_copy_file_range,
- .remap_file_range = cifs_remap_file_range,
- .llseek = cifs_llseek,
- .setlease = cifs_setlease,
- .fallocate = cifs_fallocate,
-};
-
-const struct file_operations cifs_file_nobrl_ops = {
- .read_iter = cifs_loose_read_iter,
- .write_iter = cifs_file_write_iter,
- .open = cifs_open,
- .release = cifs_close,
- .fsync = cifs_fsync,
- .flush = cifs_flush,
- .mmap = cifs_file_mmap,
- .splice_read = generic_file_splice_read,
- .splice_write = iter_file_splice_write,
- .llseek = cifs_llseek,
- .unlocked_ioctl = cifs_ioctl,
- .copy_file_range = cifs_copy_file_range,
- .remap_file_range = cifs_remap_file_range,
- .setlease = cifs_setlease,
- .fallocate = cifs_fallocate,
-};
-
-const struct file_operations cifs_file_strict_nobrl_ops = {
- .read_iter = cifs_strict_readv,
- .write_iter = cifs_strict_writev,
- .open = cifs_open,
- .release = cifs_close,
- .fsync = cifs_strict_fsync,
- .flush = cifs_flush,
- .mmap = cifs_file_strict_mmap,
- .splice_read = generic_file_splice_read,
- .splice_write = iter_file_splice_write,
- .llseek = cifs_llseek,
- .unlocked_ioctl = cifs_ioctl,
- .copy_file_range = cifs_copy_file_range,
- .remap_file_range = cifs_remap_file_range,
- .setlease = cifs_setlease,
- .fallocate = cifs_fallocate,
-};
-
-const struct file_operations cifs_file_direct_nobrl_ops = {
- .read_iter = cifs_direct_readv,
- .write_iter = cifs_direct_writev,
- .open = cifs_open,
- .release = cifs_close,
- .fsync = cifs_fsync,
- .flush = cifs_flush,
- .mmap = cifs_file_mmap,
- .splice_read = generic_file_splice_read,
- .splice_write = iter_file_splice_write,
- .unlocked_ioctl = cifs_ioctl,
- .copy_file_range = cifs_copy_file_range,
- .remap_file_range = cifs_remap_file_range,
- .llseek = cifs_llseek,
- .setlease = cifs_setlease,
- .fallocate = cifs_fallocate,
-};
-
-const struct file_operations cifs_dir_ops = {
- .iterate_shared = cifs_readdir,
- .release = cifs_closedir,
- .read = generic_read_dir,
- .unlocked_ioctl = cifs_ioctl,
- .copy_file_range = cifs_copy_file_range,
- .remap_file_range = cifs_remap_file_range,
- .llseek = generic_file_llseek,
- .fsync = cifs_dir_fsync,
-};
-
-static void
-cifs_init_once(void *inode)
-{
- struct cifsInodeInfo *cifsi = inode;
-
- inode_init_once(&cifsi->netfs.inode);
- init_rwsem(&cifsi->lock_sem);
-}
-
-static int __init
-cifs_init_inodecache(void)
-{
- cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
- sizeof(struct cifsInodeInfo),
- 0, (SLAB_RECLAIM_ACCOUNT|
- SLAB_MEM_SPREAD|SLAB_ACCOUNT),
- cifs_init_once);
- if (cifs_inode_cachep == NULL)
- return -ENOMEM;
-
- return 0;
-}
-
-static void
-cifs_destroy_inodecache(void)
-{
- /*
- * Make sure all delayed rcu free inodes are flushed before we
- * destroy cache.
- */
- rcu_barrier();
- kmem_cache_destroy(cifs_inode_cachep);
-}
-
-static int
-cifs_init_request_bufs(void)
-{
- /*
- * SMB2 maximum header size is bigger than CIFS one - no problems to
- * allocate some more bytes for CIFS.
- */
- size_t max_hdr_size = MAX_SMB2_HDR_SIZE;
-
- if (CIFSMaxBufSize < 8192) {
- /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
- Unicode path name has to fit in any SMB/CIFS path based frames */
- CIFSMaxBufSize = 8192;
- } else if (CIFSMaxBufSize > 1024*127) {
- CIFSMaxBufSize = 1024 * 127;
- } else {
- CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
- }
-/*
- cifs_dbg(VFS, "CIFSMaxBufSize %d 0x%x\n",
- CIFSMaxBufSize, CIFSMaxBufSize);
-*/
- cifs_req_cachep = kmem_cache_create_usercopy("cifs_request",
- CIFSMaxBufSize + max_hdr_size, 0,
- SLAB_HWCACHE_ALIGN, 0,
- CIFSMaxBufSize + max_hdr_size,
- NULL);
- if (cifs_req_cachep == NULL)
- return -ENOMEM;
-
- if (cifs_min_rcv < 1)
- cifs_min_rcv = 1;
- else if (cifs_min_rcv > 64) {
- cifs_min_rcv = 64;
- cifs_dbg(VFS, "cifs_min_rcv set to maximum (64)\n");
- }
-
- cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
- cifs_req_cachep);
-
- if (cifs_req_poolp == NULL) {
- kmem_cache_destroy(cifs_req_cachep);
- return -ENOMEM;
- }
- /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
- almost all handle based requests (but not write response, nor is it
- sufficient for path based requests). A smaller size would have
- been more efficient (compacting multiple slab items on one 4k page)
- for the case in which debug was on, but this larger size allows
- more SMBs to use small buffer alloc and is still much more
- efficient to alloc 1 per page off the slab compared to 17K (5page)
- alloc of large cifs buffers even when page debugging is on */
- cifs_sm_req_cachep = kmem_cache_create_usercopy("cifs_small_rq",
- MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
- 0, MAX_CIFS_SMALL_BUFFER_SIZE, NULL);
- if (cifs_sm_req_cachep == NULL) {
- mempool_destroy(cifs_req_poolp);
- kmem_cache_destroy(cifs_req_cachep);
- return -ENOMEM;
- }
-
- if (cifs_min_small < 2)
- cifs_min_small = 2;
- else if (cifs_min_small > 256) {
- cifs_min_small = 256;
- cifs_dbg(FYI, "cifs_min_small set to maximum (256)\n");
- }
-
- cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
- cifs_sm_req_cachep);
-
- if (cifs_sm_req_poolp == NULL) {
- mempool_destroy(cifs_req_poolp);
- kmem_cache_destroy(cifs_req_cachep);
- kmem_cache_destroy(cifs_sm_req_cachep);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void
-cifs_destroy_request_bufs(void)
-{
- mempool_destroy(cifs_req_poolp);
- kmem_cache_destroy(cifs_req_cachep);
- mempool_destroy(cifs_sm_req_poolp);
- kmem_cache_destroy(cifs_sm_req_cachep);
-}
-
-static int init_mids(void)
-{
- cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
- sizeof(struct mid_q_entry), 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (cifs_mid_cachep == NULL)
- return -ENOMEM;
-
- /* 3 is a reasonable minimum number of simultaneous operations */
- cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
- if (cifs_mid_poolp == NULL) {
- kmem_cache_destroy(cifs_mid_cachep);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void destroy_mids(void)
-{
- mempool_destroy(cifs_mid_poolp);
- kmem_cache_destroy(cifs_mid_cachep);
-}
-
-static int __init
-init_cifs(void)
-{
- int rc = 0;
- cifs_proc_init();
- INIT_LIST_HEAD(&cifs_tcp_ses_list);
-/*
- * Initialize Global counters
- */
- atomic_set(&sesInfoAllocCount, 0);
- atomic_set(&tconInfoAllocCount, 0);
- atomic_set(&tcpSesNextId, 0);
- atomic_set(&tcpSesAllocCount, 0);
- atomic_set(&tcpSesReconnectCount, 0);
- atomic_set(&tconInfoReconnectCount, 0);
-
- atomic_set(&buf_alloc_count, 0);
- atomic_set(&small_buf_alloc_count, 0);
-#ifdef CONFIG_CIFS_STATS2
- atomic_set(&total_buf_alloc_count, 0);
- atomic_set(&total_small_buf_alloc_count, 0);
- if (slow_rsp_threshold < 1)
- cifs_dbg(FYI, "slow_response_threshold msgs disabled\n");
- else if (slow_rsp_threshold > 32767)
- cifs_dbg(VFS,
- "slow response threshold set higher than recommended (0 to 32767)\n");
-#endif /* CONFIG_CIFS_STATS2 */
-
- atomic_set(&mid_count, 0);
- GlobalCurrentXid = 0;
- GlobalTotalActiveXid = 0;
- GlobalMaxActiveXid = 0;
- spin_lock_init(&cifs_tcp_ses_lock);
- spin_lock_init(&GlobalMid_Lock);
-
- cifs_lock_secret = get_random_u32();
-
- if (cifs_max_pending < 2) {
- cifs_max_pending = 2;
- cifs_dbg(FYI, "cifs_max_pending set to min of 2\n");
- } else if (cifs_max_pending > CIFS_MAX_REQ) {
- cifs_max_pending = CIFS_MAX_REQ;
- cifs_dbg(FYI, "cifs_max_pending set to max of %u\n",
- CIFS_MAX_REQ);
- }
-
- cifsiod_wq = alloc_workqueue("cifsiod", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
- if (!cifsiod_wq) {
- rc = -ENOMEM;
- goto out_clean_proc;
- }
-
- /*
- * Consider in future setting limit!=0 maybe to min(num_of_cores - 1, 3)
- * so that we don't launch too many worker threads but
- * Documentation/core-api/workqueue.rst recommends setting it to 0
- */
-
- /* WQ_UNBOUND allows decrypt tasks to run on any CPU */
- decrypt_wq = alloc_workqueue("smb3decryptd",
- WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
- if (!decrypt_wq) {
- rc = -ENOMEM;
- goto out_destroy_cifsiod_wq;
- }
-
- fileinfo_put_wq = alloc_workqueue("cifsfileinfoput",
- WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
- if (!fileinfo_put_wq) {
- rc = -ENOMEM;
- goto out_destroy_decrypt_wq;
- }
-
- cifsoplockd_wq = alloc_workqueue("cifsoplockd",
- WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
- if (!cifsoplockd_wq) {
- rc = -ENOMEM;
- goto out_destroy_fileinfo_put_wq;
- }
-
- deferredclose_wq = alloc_workqueue("deferredclose",
- WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
- if (!deferredclose_wq) {
- rc = -ENOMEM;
- goto out_destroy_cifsoplockd_wq;
- }
-
- rc = cifs_init_inodecache();
- if (rc)
- goto out_destroy_deferredclose_wq;
-
- rc = init_mids();
- if (rc)
- goto out_destroy_inodecache;
-
- rc = cifs_init_request_bufs();
- if (rc)
- goto out_destroy_mids;
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
- rc = dfs_cache_init();
- if (rc)
- goto out_destroy_request_bufs;
-#endif /* CONFIG_CIFS_DFS_UPCALL */
-#ifdef CONFIG_CIFS_UPCALL
- rc = init_cifs_spnego();
- if (rc)
- goto out_destroy_dfs_cache;
-#endif /* CONFIG_CIFS_UPCALL */
-#ifdef CONFIG_CIFS_SWN_UPCALL
- rc = cifs_genl_init();
- if (rc)
- goto out_register_key_type;
-#endif /* CONFIG_CIFS_SWN_UPCALL */
-
- rc = init_cifs_idmap();
- if (rc)
- goto out_cifs_swn_init;
-
- rc = register_filesystem(&cifs_fs_type);
- if (rc)
- goto out_init_cifs_idmap;
-
- rc = register_filesystem(&smb3_fs_type);
- if (rc) {
- unregister_filesystem(&cifs_fs_type);
- goto out_init_cifs_idmap;
- }
-
- return 0;
-
-out_init_cifs_idmap:
- exit_cifs_idmap();
-out_cifs_swn_init:
-#ifdef CONFIG_CIFS_SWN_UPCALL
- cifs_genl_exit();
-out_register_key_type:
-#endif
-#ifdef CONFIG_CIFS_UPCALL
- exit_cifs_spnego();
-out_destroy_dfs_cache:
-#endif
-#ifdef CONFIG_CIFS_DFS_UPCALL
- dfs_cache_destroy();
-out_destroy_request_bufs:
-#endif
- cifs_destroy_request_bufs();
-out_destroy_mids:
- destroy_mids();
-out_destroy_inodecache:
- cifs_destroy_inodecache();
-out_destroy_deferredclose_wq:
- destroy_workqueue(deferredclose_wq);
-out_destroy_cifsoplockd_wq:
- destroy_workqueue(cifsoplockd_wq);
-out_destroy_fileinfo_put_wq:
- destroy_workqueue(fileinfo_put_wq);
-out_destroy_decrypt_wq:
- destroy_workqueue(decrypt_wq);
-out_destroy_cifsiod_wq:
- destroy_workqueue(cifsiod_wq);
-out_clean_proc:
- cifs_proc_clean();
- return rc;
-}
-
-static void __exit
-exit_cifs(void)
-{
- cifs_dbg(NOISY, "exit_smb3\n");
- unregister_filesystem(&cifs_fs_type);
- unregister_filesystem(&smb3_fs_type);
- cifs_dfs_release_automount_timer();
- exit_cifs_idmap();
-#ifdef CONFIG_CIFS_SWN_UPCALL
- cifs_genl_exit();
-#endif
-#ifdef CONFIG_CIFS_UPCALL
- exit_cifs_spnego();
-#endif
-#ifdef CONFIG_CIFS_DFS_UPCALL
- dfs_cache_destroy();
-#endif
- cifs_destroy_request_bufs();
- destroy_mids();
- cifs_destroy_inodecache();
- destroy_workqueue(deferredclose_wq);
- destroy_workqueue(cifsoplockd_wq);
- destroy_workqueue(decrypt_wq);
- destroy_workqueue(fileinfo_put_wq);
- destroy_workqueue(cifsiod_wq);
- cifs_proc_clean();
-}
-
-MODULE_AUTHOR("Steve French");
-MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
-MODULE_DESCRIPTION
- ("VFS to access SMB3 servers e.g. Samba, Macs, Azure and Windows (and "
- "also older servers complying with the SNIA CIFS Specification)");
-MODULE_VERSION(CIFS_VERSION);
-MODULE_SOFTDEP("ecb");
-MODULE_SOFTDEP("hmac");
-MODULE_SOFTDEP("md5");
-MODULE_SOFTDEP("nls");
-MODULE_SOFTDEP("aes");
-MODULE_SOFTDEP("cmac");
-MODULE_SOFTDEP("sha256");
-MODULE_SOFTDEP("sha512");
-MODULE_SOFTDEP("aead2");
-MODULE_SOFTDEP("ccm");
-MODULE_SOFTDEP("gcm");
-module_init(init_cifs)
-module_exit(exit_cifs)
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
deleted file mode 100644
index b6c38896fb2d..000000000000
--- a/fs/cifs/cifsfs.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2002, 2007
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#ifndef _CIFSFS_H
-#define _CIFSFS_H
-
-#include <linux/hash.h>
-
-#define ROOT_I 2
-
-/*
- * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
- * so that it will fit. We use hash_64 to convert the value to 31 bits, and
- * then add 1, to ensure that we don't end up with a 0 as the value.
- */
-static inline ino_t
-cifs_uniqueid_to_ino_t(u64 fileid)
-{
- if ((sizeof(ino_t)) < (sizeof(u64)))
- return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
-
- return (ino_t)fileid;
-
-}
-
-static inline void cifs_set_time(struct dentry *dentry, unsigned long time)
-{
- dentry->d_fsdata = (void *) time;
-}
-
-static inline unsigned long cifs_get_time(struct dentry *dentry)
-{
- return (unsigned long) dentry->d_fsdata;
-}
-
-extern struct file_system_type cifs_fs_type, smb3_fs_type;
-extern const struct address_space_operations cifs_addr_ops;
-extern const struct address_space_operations cifs_addr_ops_smallbuf;
-
-/* Functions related to super block operations */
-extern void cifs_sb_active(struct super_block *sb);
-extern void cifs_sb_deactive(struct super_block *sb);
-
-/* Functions related to inodes */
-extern const struct inode_operations cifs_dir_inode_ops;
-extern struct inode *cifs_root_iget(struct super_block *);
-extern int cifs_create(struct user_namespace *, struct inode *,
- struct dentry *, umode_t, bool excl);
-extern int cifs_atomic_open(struct inode *, struct dentry *,
- struct file *, unsigned, umode_t);
-extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
- unsigned int);
-extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
-extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
-extern int cifs_mknod(struct user_namespace *, struct inode *, struct dentry *,
- umode_t, dev_t);
-extern int cifs_mkdir(struct user_namespace *, struct inode *, struct dentry *,
- umode_t);
-extern int cifs_rmdir(struct inode *, struct dentry *);
-extern int cifs_rename2(struct user_namespace *, struct inode *,
- struct dentry *, struct inode *, struct dentry *,
- unsigned int);
-extern int cifs_revalidate_file_attr(struct file *filp);
-extern int cifs_revalidate_dentry_attr(struct dentry *);
-extern int cifs_revalidate_file(struct file *filp);
-extern int cifs_revalidate_dentry(struct dentry *);
-extern int cifs_invalidate_mapping(struct inode *inode);
-extern int cifs_revalidate_mapping(struct inode *inode);
-extern int cifs_zap_mapping(struct inode *inode);
-extern int cifs_getattr(struct user_namespace *, const struct path *,
- struct kstat *, u32, unsigned int);
-extern int cifs_setattr(struct user_namespace *, struct dentry *,
- struct iattr *);
-extern int cifs_fiemap(struct inode *, struct fiemap_extent_info *, u64 start,
- u64 len);
-
-extern const struct inode_operations cifs_file_inode_ops;
-extern const struct inode_operations cifs_symlink_inode_ops;
-extern const struct inode_operations cifs_dfs_referral_inode_operations;
-
-
-/* Functions related to files and directories */
-extern const struct file_operations cifs_file_ops;
-extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
-extern const struct file_operations cifs_file_strict_ops; /* if strictio mnt */
-extern const struct file_operations cifs_file_nobrl_ops; /* no brlocks */
-extern const struct file_operations cifs_file_direct_nobrl_ops;
-extern const struct file_operations cifs_file_strict_nobrl_ops;
-extern int cifs_open(struct inode *inode, struct file *file);
-extern int cifs_close(struct inode *inode, struct file *file);
-extern int cifs_closedir(struct inode *inode, struct file *file);
-extern ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to);
-extern ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to);
-extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to);
-extern ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from);
-extern ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from);
-extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from);
-extern int cifs_flock(struct file *pfile, int cmd, struct file_lock *plock);
-extern int cifs_lock(struct file *, int, struct file_lock *);
-extern int cifs_fsync(struct file *, loff_t, loff_t, int);
-extern int cifs_strict_fsync(struct file *, loff_t, loff_t, int);
-extern int cifs_flush(struct file *, fl_owner_t id);
-extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
-extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
-extern const struct file_operations cifs_dir_ops;
-extern int cifs_dir_open(struct inode *inode, struct file *file);
-extern int cifs_readdir(struct file *file, struct dir_context *ctx);
-
-/* Functions related to dir entries */
-extern const struct dentry_operations cifs_dentry_ops;
-extern const struct dentry_operations cifs_ci_dentry_ops;
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
-extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
-#else
-static inline struct vfsmount *cifs_dfs_d_automount(struct path *path)
-{
- return ERR_PTR(-EREMOTE);
-}
-#endif
-
-/* Functions related to symlinks */
-extern const char *cifs_get_link(struct dentry *, struct inode *,
- struct delayed_call *);
-extern int cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
- struct dentry *direntry, const char *symname);
-
-#ifdef CONFIG_CIFS_XATTR
-extern const struct xattr_handler *cifs_xattr_handlers[];
-extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
-#else
-# define cifs_xattr_handlers NULL
-# define cifs_listxattr NULL
-#endif
-
-extern ssize_t cifs_file_copychunk_range(unsigned int xid,
- struct file *src_file, loff_t off,
- struct file *dst_file, loff_t destoff,
- size_t len, unsigned int flags);
-
-extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
-extern void cifs_setsize(struct inode *inode, loff_t offset);
-extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
-
-struct smb3_fs_context;
-extern struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type,
- int flags, struct smb3_fs_context *ctx);
-
-#ifdef CONFIG_CIFS_NFSD_EXPORT
-extern const struct export_operations cifs_export_ops;
-#endif /* CONFIG_CIFS_NFSD_EXPORT */
-
-/* when changing internal version - update following two lines at same time */
-#define SMB3_PRODUCT_BUILD 40
-#define CIFS_VERSION "2.40"
-#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
deleted file mode 100644
index 6ec1a34738e2..000000000000
--- a/fs/cifs/cifsglob.h
+++ /dev/null
@@ -1,2208 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002,2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Jeremy Allison (jra@samba.org)
- *
- */
-#ifndef _CIFS_GLOB_H
-#define _CIFS_GLOB_H
-
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/inet.h>
-#include <linux/slab.h>
-#include <linux/scatterlist.h>
-#include <linux/mm.h>
-#include <linux/mempool.h>
-#include <linux/workqueue.h>
-#include <linux/utsname.h>
-#include <linux/sched/mm.h>
-#include <linux/netfs.h>
-#include "cifs_fs_sb.h"
-#include "cifsacl.h"
-#include <crypto/internal/hash.h>
-#include <linux/scatterlist.h>
-#include <uapi/linux/cifs/cifs_mount.h>
-#include "../smbfs_common/smb2pdu.h"
-#include "smb2pdu.h"
-
-#define SMB_PATH_MAX 260
-#define CIFS_PORT 445
-#define RFC1001_PORT 139
-
-/*
- * The sizes of various internal tables and strings
- */
-#define MAX_UID_INFO 16
-#define MAX_SES_INFO 2
-#define MAX_TCON_INFO 4
-
-#define MAX_TREE_SIZE (2 + CIFS_NI_MAXHOST + 1 + CIFS_MAX_SHARE_LEN + 1)
-
-#define CIFS_MIN_RCV_POOL 4
-
-#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */
-/*
- * default attribute cache timeout (jiffies)
- */
-#define CIFS_DEF_ACTIMEO (1 * HZ)
-
-/*
- * max attribute cache timeout (jiffies) - 2^30
- */
-#define CIFS_MAX_ACTIMEO (1 << 30)
-
-/*
- * Max persistent and resilient handle timeout (milliseconds).
- * Windows durable max was 960000 (16 minutes)
- */
-#define SMB3_MAX_HANDLE_TIMEOUT 960000
-
-/*
- * MAX_REQ is the maximum number of requests that WE will send
- * on one socket concurrently.
- */
-#define CIFS_MAX_REQ 32767
-
-#define RFC1001_NAME_LEN 15
-#define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1)
-
-/* maximum length of ip addr as a string (including ipv6 and sctp) */
-#define SERVER_NAME_LENGTH 80
-#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
-
-/* echo interval in seconds */
-#define SMB_ECHO_INTERVAL_MIN 1
-#define SMB_ECHO_INTERVAL_MAX 600
-#define SMB_ECHO_INTERVAL_DEFAULT 60
-
-/* dns resolution intervals in seconds */
-#define SMB_DNS_RESOLVE_INTERVAL_MIN 120
-#define SMB_DNS_RESOLVE_INTERVAL_DEFAULT 600
-
-/* smb multichannel query server interfaces interval in seconds */
-#define SMB_INTERFACE_POLL_INTERVAL 600
-
-/* maximum number of PDUs in one compound */
-#define MAX_COMPOUND 5
-
-/*
- * Default number of credits to keep available for SMB3.
- * This value is chosen somewhat arbitrarily. The Windows client
- * defaults to 128 credits, the Windows server allows clients up to
- * 512 credits (or 8K for later versions), and the NetApp server
- * does not limit clients at all. Choose a high enough default value
- * such that the client shouldn't limit performance, but allow mount
- * to override (until you approach 64K, where we limit credits to 65000
- * to reduce possibility of seeing more server credit overflow bugs.
- */
-#define SMB2_MAX_CREDITS_AVAILABLE 32000
-
-#include "cifspdu.h"
-
-#ifndef XATTR_DOS_ATTRIB
-#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
-#endif
-
-#define CIFS_MAX_WORKSTATION_LEN (__NEW_UTS_LEN + 1) /* reasonable max for client */
-
-/*
- * CIFS vfs client Status information (based on what we know.)
- */
-
-/* associated with each connection */
-enum statusEnum {
- CifsNew = 0,
- CifsGood,
- CifsExiting,
- CifsNeedReconnect,
- CifsNeedNegotiate,
- CifsInNegotiate,
-};
-
-/* associated with each smb session */
-enum ses_status_enum {
- SES_NEW = 0,
- SES_GOOD,
- SES_EXITING,
- SES_NEED_RECON,
- SES_IN_SETUP
-};
-
-/* associated with each tree connection to the server */
-enum tid_status_enum {
- TID_NEW = 0,
- TID_GOOD,
- TID_EXITING,
- TID_NEED_RECON,
- TID_NEED_TCON,
- TID_IN_TCON,
- TID_NEED_FILES_INVALIDATE, /* currently unused */
- TID_IN_FILES_INVALIDATE
-};
-
-enum securityEnum {
- Unspecified = 0, /* not specified */
- NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
- RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
- Kerberos, /* Kerberos via SPNEGO */
-};
-
-struct session_key {
- unsigned int len;
- char *response;
-};
-
-/* crypto hashing related structure/fields, not specific to a sec mech */
-struct cifs_secmech {
- struct shash_desc *hmacmd5; /* hmacmd5 hash function, for NTLMv2/CR1 hashes */
- struct shash_desc *md5; /* md5 hash function, for CIFS/SMB1 signatures */
- struct shash_desc *hmacsha256; /* hmac-sha256 hash function, for SMB2 signatures */
- struct shash_desc *sha512; /* sha512 hash function, for SMB3.1.1 preauth hash */
- struct shash_desc *aes_cmac; /* block-cipher based MAC function, for SMB3 signatures */
-
- struct crypto_aead *enc; /* smb3 encryption AEAD TFM (AES-CCM and AES-GCM) */
- struct crypto_aead *dec; /* smb3 decryption AEAD TFM (AES-CCM and AES-GCM) */
-};
-
-/* per smb session structure/fields */
-struct ntlmssp_auth {
- bool sesskey_per_smbsess; /* whether session key is per smb session */
- __u32 client_flags; /* sent by client in type 1 ntlmsssp exchange */
- __u32 server_flags; /* sent by server in type 2 ntlmssp exchange */
- unsigned char ciphertext[CIFS_CPHTXT_SIZE]; /* sent to server */
- char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlmssp */
-};
-
-struct cifs_cred {
- int uid;
- int gid;
- int mode;
- int cecount;
- struct cifs_sid osid;
- struct cifs_sid gsid;
- struct cifs_ntace *ntaces;
- struct cifs_ace *aces;
-};
-
-struct cifs_open_info_data {
- char *symlink_target;
- union {
- struct smb2_file_all_info fi;
- struct smb311_posix_qinfo posix_fi;
- };
-};
-
-static inline void cifs_free_open_info(struct cifs_open_info_data *data)
-{
- kfree(data->symlink_target);
-}
-
-/*
- *****************************************************************
- * Except the CIFS PDUs themselves all the
- * globally interesting structs should go here
- *****************************************************************
- */
-
-/*
- * A smb_rqst represents a complete request to be issued to a server. It's
- * formed by a kvec array, followed by an array of pages. Page data is assumed
- * to start at the beginning of the first page.
- */
-struct smb_rqst {
- struct kvec *rq_iov; /* array of kvecs */
- unsigned int rq_nvec; /* number of kvecs in array */
- struct page **rq_pages; /* pointer to array of page ptrs */
- unsigned int rq_offset; /* the offset to the 1st page */
- unsigned int rq_npages; /* number pages in array */
- unsigned int rq_pagesz; /* page size to use */
- unsigned int rq_tailsz; /* length of last page */
-};
-
-struct mid_q_entry;
-struct TCP_Server_Info;
-struct cifsFileInfo;
-struct cifs_ses;
-struct cifs_tcon;
-struct dfs_info3_param;
-struct cifs_fattr;
-struct smb3_fs_context;
-struct cifs_fid;
-struct cifs_readdata;
-struct cifs_writedata;
-struct cifs_io_parms;
-struct cifs_search_info;
-struct cifsInodeInfo;
-struct cifs_open_parms;
-struct cifs_credits;
-
-struct smb_version_operations {
- int (*send_cancel)(struct TCP_Server_Info *, struct smb_rqst *,
- struct mid_q_entry *);
- bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *);
- /* setup request: allocate mid, sign message */
- struct mid_q_entry *(*setup_request)(struct cifs_ses *,
- struct TCP_Server_Info *,
- struct smb_rqst *);
- /* setup async request: allocate mid, sign message */
- struct mid_q_entry *(*setup_async_request)(struct TCP_Server_Info *,
- struct smb_rqst *);
- /* check response: verify signature, map error */
- int (*check_receive)(struct mid_q_entry *, struct TCP_Server_Info *,
- bool);
- void (*add_credits)(struct TCP_Server_Info *server,
- const struct cifs_credits *credits,
- const int optype);
- void (*set_credits)(struct TCP_Server_Info *, const int);
- int * (*get_credits_field)(struct TCP_Server_Info *, const int);
- unsigned int (*get_credits)(struct mid_q_entry *);
- __u64 (*get_next_mid)(struct TCP_Server_Info *);
- void (*revert_current_mid)(struct TCP_Server_Info *server,
- const unsigned int val);
- /* data offset from read response message */
- unsigned int (*read_data_offset)(char *);
- /*
- * Data length from read response message
- * When in_remaining is true, the returned data length is in
- * message field DataRemaining for out-of-band data read (e.g through
- * Memory Registration RDMA write in SMBD).
- * Otherwise, the returned data length is in message field DataLength.
- */
- unsigned int (*read_data_length)(char *, bool in_remaining);
- /* map smb to linux error */
- int (*map_error)(char *, bool);
- /* find mid corresponding to the response message */
- struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *);
- void (*dump_detail)(void *buf, struct TCP_Server_Info *ptcp_info);
- void (*clear_stats)(struct cifs_tcon *);
- void (*print_stats)(struct seq_file *m, struct cifs_tcon *);
- void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *);
- /* verify the message */
- int (*check_message)(char *, unsigned int, struct TCP_Server_Info *);
- bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
- int (*handle_cancelled_mid)(struct mid_q_entry *, struct TCP_Server_Info *);
- void (*downgrade_oplock)(struct TCP_Server_Info *server,
- struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache);
- /* process transaction2 response */
- bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *,
- char *, int);
- /* check if we need to negotiate */
- bool (*need_neg)(struct TCP_Server_Info *);
- /* negotiate to the server */
- int (*negotiate)(const unsigned int xid,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server);
- /* set negotiated write size */
- unsigned int (*negotiate_wsize)(struct cifs_tcon *tcon, struct smb3_fs_context *ctx);
- /* set negotiated read size */
- unsigned int (*negotiate_rsize)(struct cifs_tcon *tcon, struct smb3_fs_context *ctx);
- /* setup smb sessionn */
- int (*sess_setup)(const unsigned int, struct cifs_ses *,
- struct TCP_Server_Info *server,
- const struct nls_table *);
- /* close smb session */
- int (*logoff)(const unsigned int, struct cifs_ses *);
- /* connect to a server share */
- int (*tree_connect)(const unsigned int, struct cifs_ses *, const char *,
- struct cifs_tcon *, const struct nls_table *);
- /* close tree connecion */
- int (*tree_disconnect)(const unsigned int, struct cifs_tcon *);
- /* get DFS referrals */
- int (*get_dfs_refer)(const unsigned int, struct cifs_ses *,
- const char *, struct dfs_info3_param **,
- unsigned int *, const struct nls_table *, int);
- /* informational QFS call */
- void (*qfs_tcon)(const unsigned int, struct cifs_tcon *,
- struct cifs_sb_info *);
- /* check if a path is accessible or not */
- int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
- struct cifs_sb_info *, const char *);
- /* query path data from the server */
- int (*query_path_info)(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
- /* query file data from the server */
- int (*query_file_info)(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile, struct cifs_open_info_data *data);
- /* query reparse tag from srv to determine which type of special file */
- int (*query_reparse_tag)(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *path,
- __u32 *reparse_tag);
- /* get server index number */
- int (*get_srv_inum)(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path, u64 *uniqueid,
- struct cifs_open_info_data *data);
- /* set size by path */
- int (*set_path_size)(const unsigned int, struct cifs_tcon *,
- const char *, __u64, struct cifs_sb_info *, bool);
- /* set size by file handle */
- int (*set_file_size)(const unsigned int, struct cifs_tcon *,
- struct cifsFileInfo *, __u64, bool);
- /* set attributes */
- int (*set_file_info)(struct inode *, const char *, FILE_BASIC_INFO *,
- const unsigned int);
- int (*set_compression)(const unsigned int, struct cifs_tcon *,
- struct cifsFileInfo *);
- /* check if we can send an echo or nor */
- bool (*can_echo)(struct TCP_Server_Info *);
- /* send echo request */
- int (*echo)(struct TCP_Server_Info *);
- /* create directory */
- int (*posix_mkdir)(const unsigned int xid, struct inode *inode,
- umode_t mode, struct cifs_tcon *tcon,
- const char *full_path,
- struct cifs_sb_info *cifs_sb);
- int (*mkdir)(const unsigned int xid, struct inode *inode, umode_t mode,
- struct cifs_tcon *tcon, const char *name,
- struct cifs_sb_info *sb);
- /* set info on created directory */
- void (*mkdir_setinfo)(struct inode *, const char *,
- struct cifs_sb_info *, struct cifs_tcon *,
- const unsigned int);
- /* remove directory */
- int (*rmdir)(const unsigned int, struct cifs_tcon *, const char *,
- struct cifs_sb_info *);
- /* unlink file */
- int (*unlink)(const unsigned int, struct cifs_tcon *, const char *,
- struct cifs_sb_info *);
- /* open, rename and delete file */
- int (*rename_pending_delete)(const char *, struct dentry *,
- const unsigned int);
- /* send rename request */
- int (*rename)(const unsigned int, struct cifs_tcon *, const char *,
- const char *, struct cifs_sb_info *);
- /* send create hardlink request */
- int (*create_hardlink)(const unsigned int, struct cifs_tcon *,
- const char *, const char *,
- struct cifs_sb_info *);
- /* query symlink target */
- int (*query_symlink)(const unsigned int, struct cifs_tcon *,
- struct cifs_sb_info *, const char *,
- char **, bool);
- /* open a file for non-posix mounts */
- int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
- void *buf);
- /* set fid protocol-specific info */
- void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32);
- /* close a file */
- void (*close)(const unsigned int, struct cifs_tcon *,
- struct cifs_fid *);
- /* close a file, returning file attributes and timestamps */
- void (*close_getattr)(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *pfile_info);
- /* send a flush request to the server */
- int (*flush)(const unsigned int, struct cifs_tcon *, struct cifs_fid *);
- /* async read from the server */
- int (*async_readv)(struct cifs_readdata *);
- /* async write to the server */
- int (*async_writev)(struct cifs_writedata *,
- void (*release)(struct kref *));
- /* sync read from the server */
- int (*sync_read)(const unsigned int, struct cifs_fid *,
- struct cifs_io_parms *, unsigned int *, char **,
- int *);
- /* sync write to the server */
- int (*sync_write)(const unsigned int, struct cifs_fid *,
- struct cifs_io_parms *, unsigned int *, struct kvec *,
- unsigned long);
- /* open dir, start readdir */
- int (*query_dir_first)(const unsigned int, struct cifs_tcon *,
- const char *, struct cifs_sb_info *,
- struct cifs_fid *, __u16,
- struct cifs_search_info *);
- /* continue readdir */
- int (*query_dir_next)(const unsigned int, struct cifs_tcon *,
- struct cifs_fid *,
- __u16, struct cifs_search_info *srch_inf);
- /* close dir */
- int (*close_dir)(const unsigned int, struct cifs_tcon *,
- struct cifs_fid *);
- /* calculate a size of SMB message */
- unsigned int (*calc_smb_size)(void *buf);
- /* check for STATUS_PENDING and process the response if yes */
- bool (*is_status_pending)(char *buf, struct TCP_Server_Info *server);
- /* check for STATUS_NETWORK_SESSION_EXPIRED */
- bool (*is_session_expired)(char *);
- /* send oplock break response */
- int (*oplock_response)(struct cifs_tcon *tcon, __u64 persistent_fid, __u64 volatile_fid,
- __u16 net_fid, struct cifsInodeInfo *cifs_inode);
- /* query remote filesystem */
- int (*queryfs)(const unsigned int, struct cifs_tcon *,
- struct cifs_sb_info *, struct kstatfs *);
- /* send mandatory brlock to the server */
- int (*mand_lock)(const unsigned int, struct cifsFileInfo *, __u64,
- __u64, __u32, int, int, bool);
- /* unlock range of mandatory locks */
- int (*mand_unlock_range)(struct cifsFileInfo *, struct file_lock *,
- const unsigned int);
- /* push brlocks from the cache to the server */
- int (*push_mand_locks)(struct cifsFileInfo *);
- /* get lease key of the inode */
- void (*get_lease_key)(struct inode *, struct cifs_fid *);
- /* set lease key of the inode */
- void (*set_lease_key)(struct inode *, struct cifs_fid *);
- /* generate new lease key */
- void (*new_lease_key)(struct cifs_fid *);
- int (*generate_signingkey)(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
- int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *,
- bool allocate_crypto);
- int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon,
- struct cifsFileInfo *src_file);
- int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *src_file, void __user *);
- int (*notify)(const unsigned int xid, struct file *pfile,
- void __user *pbuf, bool return_changes);
- int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
- struct cifs_sb_info *, const unsigned char *,
- char *, unsigned int *);
- int (*create_mf_symlink)(unsigned int, struct cifs_tcon *,
- struct cifs_sb_info *, const unsigned char *,
- char *, unsigned int *);
- /* if we can do cache read operations */
- bool (*is_read_op)(__u32);
- /* set oplock level for the inode */
- void (*set_oplock_level)(struct cifsInodeInfo *, __u32, unsigned int,
- bool *);
- /* create lease context buffer for CREATE request */
- char * (*create_lease_buf)(u8 *lease_key, u8 oplock);
- /* parse lease context buffer and return oplock/epoch info */
- __u8 (*parse_lease_buf)(void *buf, unsigned int *epoch, char *lkey);
- ssize_t (*copychunk_range)(const unsigned int,
- struct cifsFileInfo *src_file,
- struct cifsFileInfo *target_file,
- u64 src_off, u64 len, u64 dest_off);
- int (*duplicate_extents)(const unsigned int, struct cifsFileInfo *src,
- struct cifsFileInfo *target_file, u64 src_off, u64 len,
- u64 dest_off);
- int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
- ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *,
- const unsigned char *, const unsigned char *, char *,
- size_t, struct cifs_sb_info *);
- int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
- const char *, const void *, const __u16,
- const struct nls_table *, struct cifs_sb_info *);
- struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
- const char *, u32 *, u32);
- struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
- const struct cifs_fid *, u32 *, u32);
- int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
- int);
- /* writepages retry size */
- unsigned int (*wp_retry_size)(struct inode *);
- /* get mtu credits */
- int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int,
- unsigned int *, struct cifs_credits *);
- /* adjust previously taken mtu credits to request size */
- int (*adjust_credits)(struct TCP_Server_Info *server,
- struct cifs_credits *credits,
- const unsigned int payload_size);
- /* check if we need to issue closedir */
- bool (*dir_needs_close)(struct cifsFileInfo *);
- long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
- loff_t);
- /* init transform request - used for encryption for now */
- int (*init_transform_rq)(struct TCP_Server_Info *, int num_rqst,
- struct smb_rqst *, struct smb_rqst *);
- int (*is_transform_hdr)(void *buf);
- int (*receive_transform)(struct TCP_Server_Info *,
- struct mid_q_entry **, char **, int *);
- enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
- enum securityEnum);
- int (*next_header)(char *);
- /* ioctl passthrough for query_info */
- int (*ioctl_query_info)(const unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- __le16 *path, int is_dir,
- unsigned long p);
- /* make unix special files (block, char, fifo, socket) */
- int (*make_node)(unsigned int xid,
- struct inode *inode,
- struct dentry *dentry,
- struct cifs_tcon *tcon,
- const char *full_path,
- umode_t mode,
- dev_t device_number);
- /* version specific fiemap implementation */
- int (*fiemap)(struct cifs_tcon *tcon, struct cifsFileInfo *,
- struct fiemap_extent_info *, u64, u64);
- /* version specific llseek implementation */
- loff_t (*llseek)(struct file *, struct cifs_tcon *, loff_t, int);
- /* Check for STATUS_IO_TIMEOUT */
- bool (*is_status_io_timeout)(char *buf);
- /* Check for STATUS_NETWORK_NAME_DELETED */
- void (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
-};
-
-struct smb_version_values {
- char *version_string;
- __u16 protocol_id;
- __u32 req_capabilities;
- __u32 large_lock_type;
- __u32 exclusive_lock_type;
- __u32 shared_lock_type;
- __u32 unlock_lock_type;
- size_t header_preamble_size;
- size_t header_size;
- size_t max_header_size;
- size_t read_rsp_size;
- __le16 lock_cmd;
- unsigned int cap_unix;
- unsigned int cap_nt_find;
- unsigned int cap_large_files;
- __u16 signing_enabled;
- __u16 signing_required;
- size_t create_lease_size;
-};
-
-#define HEADER_SIZE(server) (server->vals->header_size)
-#define MAX_HEADER_SIZE(server) (server->vals->max_header_size)
-#define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size)
-#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1 - HEADER_PREAMBLE_SIZE(server))
-
-/**
- * CIFS superblock mount flags (mnt_cifs_flags) to consider when
- * trying to reuse existing superblock for a new mount
- */
-#define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \
- CIFS_MOUNT_SERVER_INUM | CIFS_MOUNT_DIRECT_IO | \
- CIFS_MOUNT_NO_XATTR | CIFS_MOUNT_MAP_SPECIAL_CHR | \
- CIFS_MOUNT_MAP_SFM_CHR | \
- CIFS_MOUNT_UNX_EMUL | CIFS_MOUNT_NO_BRL | \
- CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_OVERR_UID | \
- CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \
- CIFS_MOUNT_NOPOSIXBRL | CIFS_MOUNT_NOSSYNC | \
- CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \
- CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \
- CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \
- CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \
- CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID | \
- CIFS_MOUNT_RO_CACHE | CIFS_MOUNT_RW_CACHE)
-
-/**
- * Generic VFS superblock mount flags (s_flags) to consider when
- * trying to reuse existing superblock for a new mount
- */
-#define CIFS_MS_MASK (SB_RDONLY | SB_MANDLOCK | SB_NOEXEC | SB_NOSUID | \
- SB_NODEV | SB_SYNCHRONOUS)
-
-struct cifs_mnt_data {
- struct cifs_sb_info *cifs_sb;
- struct smb3_fs_context *ctx;
- int flags;
-};
-
-static inline unsigned int
-get_rfc1002_length(void *buf)
-{
- return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
-}
-
-static inline void
-inc_rfc1001_len(void *buf, int count)
-{
- be32_add_cpu((__be32 *)buf, count);
-}
-
-struct TCP_Server_Info {
- struct list_head tcp_ses_list;
- struct list_head smb_ses_list;
- spinlock_t srv_lock; /* protect anything here that is not protected */
- __u64 conn_id; /* connection identifier (useful for debugging) */
- int srv_count; /* reference counter */
- /* 15 character server name + 0x20 16th byte indicating type = srv */
- char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
- struct smb_version_operations *ops;
- struct smb_version_values *vals;
- /* updates to tcpStatus protected by cifs_tcp_ses_lock */
- enum statusEnum tcpStatus; /* what we think the status is */
- char *hostname; /* hostname portion of UNC string */
- struct socket *ssocket;
- struct sockaddr_storage dstaddr;
- struct sockaddr_storage srcaddr; /* locally bind to this IP */
-#ifdef CONFIG_NET_NS
- struct net *net;
-#endif
- wait_queue_head_t response_q;
- wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
- spinlock_t mid_lock; /* protect mid queue and it's entries */
- struct list_head pending_mid_q;
- bool noblocksnd; /* use blocking sendmsg */
- bool noautotune; /* do not autotune send buf sizes */
- bool nosharesock;
- bool tcp_nodelay;
- unsigned int credits; /* send no more requests at once */
- unsigned int max_credits; /* can override large 32000 default at mnt */
- unsigned int in_flight; /* number of requests on the wire to server */
- unsigned int max_in_flight; /* max number of requests that were on wire */
- spinlock_t req_lock; /* protect the two values above */
- struct mutex _srv_mutex;
- unsigned int nofs_flag;
- struct task_struct *tsk;
- char server_GUID[16];
- __u16 sec_mode;
- bool sign; /* is signing enabled on this connection? */
- bool ignore_signature:1; /* skip validation of signatures in SMB2/3 rsp */
- bool session_estab; /* mark when very first sess is established */
- int echo_credits; /* echo reserved slots */
- int oplock_credits; /* oplock break reserved slots */
- bool echoes:1; /* enable echoes */
- __u8 client_guid[SMB2_CLIENT_GUID_SIZE]; /* Client GUID */
- u16 dialect; /* dialect index that server chose */
- bool oplocks:1; /* enable oplocks */
- unsigned int maxReq; /* Clients should submit no more */
- /* than maxReq distinct unanswered SMBs to the server when using */
- /* multiplexed reads or writes (for SMB1/CIFS only, not SMB2/SMB3) */
- unsigned int maxBuf; /* maxBuf specifies the maximum */
- /* message size the server can send or receive for non-raw SMBs */
- /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */
- /* when socket is setup (and during reconnect) before NegProt sent */
- unsigned int max_rw; /* maxRw specifies the maximum */
- /* message size the server can send or receive for */
- /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
- unsigned int capabilities; /* selective disabling of caps by smb sess */
- int timeAdj; /* Adjust for difference in server time zone in sec */
- __u64 CurrentMid; /* multiplex id - rotating counter, protected by GlobalMid_Lock */
- char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
- /* 16th byte of RFC1001 workstation name is always null */
- char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
- __u32 sequence_number; /* for signing, protected by srv_mutex */
- __u32 reconnect_instance; /* incremented on each reconnect */
- struct session_key session_key;
- unsigned long lstrp; /* when we got last response from this server */
- struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */
-#define CIFS_NEGFLAVOR_UNENCAP 1 /* wct == 17, but no ext_sec */
-#define CIFS_NEGFLAVOR_EXTENDED 2 /* wct == 17, ext_sec bit set */
- char negflavor; /* NEGOTIATE response flavor */
- /* extended security flavors that server supports */
- bool sec_ntlmssp; /* supports NTLMSSP */
- bool sec_kerberosu2u; /* supports U2U Kerberos */
- bool sec_kerberos; /* supports plain Kerberos */
- bool sec_mskerberos; /* supports legacy MS Kerberos */
- bool large_buf; /* is current buffer large? */
- /* use SMBD connection instead of socket */
- bool rdma;
- /* point to the SMBD connection if RDMA is used instead of socket */
- struct smbd_connection *smbd_conn;
- struct delayed_work echo; /* echo ping workqueue job */
- struct delayed_work resolve; /* dns resolution workqueue job */
- char *smallbuf; /* pointer to current "small" buffer */
- char *bigbuf; /* pointer to current "big" buffer */
- /* Total size of this PDU. Only valid from cifs_demultiplex_thread */
- unsigned int pdu_size;
- unsigned int total_read; /* total amount of data read in this pass */
- atomic_t in_send; /* requests trying to send */
- atomic_t num_waiters; /* blocked waiting to get in sendrecv */
-#ifdef CONFIG_CIFS_STATS2
- atomic_t num_cmds[NUMBER_OF_SMB2_COMMANDS]; /* total requests by cmd */
- atomic_t smb2slowcmd[NUMBER_OF_SMB2_COMMANDS]; /* count resps > 1 sec */
- __u64 time_per_cmd[NUMBER_OF_SMB2_COMMANDS]; /* total time per cmd */
- __u32 slowest_cmd[NUMBER_OF_SMB2_COMMANDS];
- __u32 fastest_cmd[NUMBER_OF_SMB2_COMMANDS];
-#endif /* STATS2 */
- unsigned int max_read;
- unsigned int max_write;
- unsigned int min_offload;
- __le16 compress_algorithm;
- __u16 signing_algorithm;
- __le16 cipher_type;
- /* save initital negprot hash */
- __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
- bool signing_negotiated; /* true if valid signing context rcvd from server */
- bool posix_ext_supported;
- struct delayed_work reconnect; /* reconnect workqueue job */
- struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
- unsigned long echo_interval;
-
- /*
- * Number of targets available for reconnect. The more targets
- * the more tasks have to wait to let the demultiplex thread
- * reconnect.
- */
- int nr_targets;
- bool noblockcnt; /* use non-blocking connect() */
-
- /*
- * If this is a session channel,
- * primary_server holds the ref-counted
- * pointer to primary channel connection for the session.
- */
-#define CIFS_SERVER_IS_CHAN(server) (!!(server)->primary_server)
- struct TCP_Server_Info *primary_server;
-
-#ifdef CONFIG_CIFS_SWN_UPCALL
- bool use_swn_dstaddr;
- struct sockaddr_storage swn_dstaddr;
-#endif
-#ifdef CONFIG_CIFS_DFS_UPCALL
- bool is_dfs_conn; /* if a dfs connection */
- struct mutex refpath_lock; /* protects leaf_fullpath */
- /*
- * Canonical DFS full paths that were used to chase referrals in mount and reconnect.
- *
- * origin_fullpath: first or original referral path
- * leaf_fullpath: last referral path (might be changed due to nested links in reconnect)
- *
- * current_fullpath: pointer to either origin_fullpath or leaf_fullpath
- * NOTE: cannot be accessed outside cifs_reconnect() and smb2_reconnect()
- *
- * format: \\HOST\SHARE\[OPTIONAL PATH]
- */
- char *origin_fullpath, *leaf_fullpath, *current_fullpath;
-#endif
-};
-
-static inline bool is_smb1(struct TCP_Server_Info *server)
-{
- return HEADER_PREAMBLE_SIZE(server) != 0;
-}
-
-static inline void cifs_server_lock(struct TCP_Server_Info *server)
-{
- unsigned int nofs_flag = memalloc_nofs_save();
-
- mutex_lock(&server->_srv_mutex);
- server->nofs_flag = nofs_flag;
-}
-
-static inline void cifs_server_unlock(struct TCP_Server_Info *server)
-{
- unsigned int nofs_flag = server->nofs_flag;
-
- mutex_unlock(&server->_srv_mutex);
- memalloc_nofs_restore(nofs_flag);
-}
-
-struct cifs_credits {
- unsigned int value;
- unsigned int instance;
-};
-
-static inline unsigned int
-in_flight(struct TCP_Server_Info *server)
-{
- unsigned int num;
- spin_lock(&server->req_lock);
- num = server->in_flight;
- spin_unlock(&server->req_lock);
- return num;
-}
-
-static inline bool
-has_credits(struct TCP_Server_Info *server, int *credits, int num_credits)
-{
- int num;
- spin_lock(&server->req_lock);
- num = *credits;
- spin_unlock(&server->req_lock);
- return num >= num_credits;
-}
-
-static inline void
-add_credits(struct TCP_Server_Info *server, const struct cifs_credits *credits,
- const int optype)
-{
- server->ops->add_credits(server, credits, optype);
-}
-
-static inline void
-add_credits_and_wake_if(struct TCP_Server_Info *server,
- const struct cifs_credits *credits, const int optype)
-{
- if (credits->value) {
- server->ops->add_credits(server, credits, optype);
- wake_up(&server->request_q);
- }
-}
-
-static inline void
-set_credits(struct TCP_Server_Info *server, const int val)
-{
- server->ops->set_credits(server, val);
-}
-
-static inline int
-adjust_credits(struct TCP_Server_Info *server, struct cifs_credits *credits,
- const unsigned int payload_size)
-{
- return server->ops->adjust_credits ?
- server->ops->adjust_credits(server, credits, payload_size) : 0;
-}
-
-static inline __le64
-get_next_mid64(struct TCP_Server_Info *server)
-{
- return cpu_to_le64(server->ops->get_next_mid(server));
-}
-
-static inline __le16
-get_next_mid(struct TCP_Server_Info *server)
-{
- __u16 mid = server->ops->get_next_mid(server);
- /*
- * The value in the SMB header should be little endian for easy
- * on-the-wire decoding.
- */
- return cpu_to_le16(mid);
-}
-
-static inline void
-revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
-{
- if (server->ops->revert_current_mid)
- server->ops->revert_current_mid(server, val);
-}
-
-static inline void
-revert_current_mid_from_hdr(struct TCP_Server_Info *server,
- const struct smb2_hdr *shdr)
-{
- unsigned int num = le16_to_cpu(shdr->CreditCharge);
-
- return revert_current_mid(server, num > 0 ? num : 1);
-}
-
-static inline __u16
-get_mid(const struct smb_hdr *smb)
-{
- return le16_to_cpu(smb->Mid);
-}
-
-static inline bool
-compare_mid(__u16 mid, const struct smb_hdr *smb)
-{
- return mid == le16_to_cpu(smb->Mid);
-}
-
-/*
- * When the server supports very large reads and writes via POSIX extensions,
- * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
- * including the RFC1001 length.
- *
- * Note that this might make for "interesting" allocation problems during
- * writeback however as we have to allocate an array of pointers for the
- * pages. A 16M write means ~32kb page array with PAGE_SIZE == 4096.
- *
- * For reads, there is a similar problem as we need to allocate an array
- * of kvecs to handle the receive, though that should only need to be done
- * once.
- */
-#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
-#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
-
-/*
- * When the server doesn't allow large posix writes, only allow a rsize/wsize
- * of 2^17-1 minus the size of the call header. That allows for a read or
- * write up to the maximum size described by RFC1002.
- */
-#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
-#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
-
-#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
-
-/*
- * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
- * those values when posix extensions aren't in force. In actuality here, we
- * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
- * to be ok with the extra byte even though Windows doesn't send writes that
- * are that large.
- *
- * Citation:
- *
- * https://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
- */
-#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
-#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
-
-/*
- * Macros to allow the TCP_Server_Info->net field and related code to drop out
- * when CONFIG_NET_NS isn't set.
- */
-
-#ifdef CONFIG_NET_NS
-
-static inline struct net *cifs_net_ns(struct TCP_Server_Info *srv)
-{
- return srv->net;
-}
-
-static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net)
-{
- srv->net = net;
-}
-
-#else
-
-static inline struct net *cifs_net_ns(struct TCP_Server_Info *srv)
-{
- return &init_net;
-}
-
-static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net)
-{
-}
-
-#endif
-
-struct cifs_server_iface {
- struct list_head iface_head;
- struct kref refcount;
- size_t speed;
- unsigned int rdma_capable : 1;
- unsigned int rss_capable : 1;
- unsigned int is_active : 1; /* unset if non existent */
- struct sockaddr_storage sockaddr;
-};
-
-/* release iface when last ref is dropped */
-static inline void
-release_iface(struct kref *ref)
-{
- struct cifs_server_iface *iface = container_of(ref,
- struct cifs_server_iface,
- refcount);
- list_del_init(&iface->iface_head);
- kfree(iface);
-}
-
-/*
- * compare two interfaces a and b
- * return 0 if everything matches.
- * return 1 if a has higher link speed, or rdma capable, or rss capable
- * return -1 otherwise.
- */
-static inline int
-iface_cmp(struct cifs_server_iface *a, struct cifs_server_iface *b)
-{
- int cmp_ret = 0;
-
- WARN_ON(!a || !b);
- if (a->speed == b->speed) {
- if (a->rdma_capable == b->rdma_capable) {
- if (a->rss_capable == b->rss_capable) {
- cmp_ret = memcmp(&a->sockaddr, &b->sockaddr,
- sizeof(a->sockaddr));
- if (!cmp_ret)
- return 0;
- else if (cmp_ret > 0)
- return 1;
- else
- return -1;
- } else if (a->rss_capable > b->rss_capable)
- return 1;
- else
- return -1;
- } else if (a->rdma_capable > b->rdma_capable)
- return 1;
- else
- return -1;
- } else if (a->speed > b->speed)
- return 1;
- else
- return -1;
-}
-
-struct cifs_chan {
- unsigned int in_reconnect : 1; /* if session setup in progress for this channel */
- struct TCP_Server_Info *server;
- struct cifs_server_iface *iface; /* interface in use */
- __u8 signkey[SMB3_SIGN_KEY_SIZE];
-};
-
-/*
- * Session structure. One of these for each uid session with a particular host
- */
-struct cifs_ses {
- struct list_head smb_ses_list;
- struct list_head rlist; /* reconnect list */
- struct list_head tcon_list;
- struct cifs_tcon *tcon_ipc;
- spinlock_t ses_lock; /* protect anything here that is not protected */
- struct mutex session_mutex;
- struct TCP_Server_Info *server; /* pointer to server info */
- int ses_count; /* reference counter */
- enum ses_status_enum ses_status; /* updates protected by cifs_tcp_ses_lock */
- unsigned overrideSecFlg; /* if non-zero override global sec flags */
- char *serverOS; /* name of operating system underlying server */
- char *serverNOS; /* name of network operating system of server */
- char *serverDomain; /* security realm of server */
- __u64 Suid; /* remote smb uid */
- kuid_t linux_uid; /* overriding owner of files on the mount */
- kuid_t cred_uid; /* owner of credentials */
- unsigned int capabilities;
- char ip_addr[INET6_ADDRSTRLEN + 1]; /* Max ipv6 (or v4) addr string len */
- char *user_name; /* must not be null except during init of sess
- and after mount option parsing we fill it */
- char *domainName;
- char *password;
- char workstation_name[CIFS_MAX_WORKSTATION_LEN];
- struct session_key auth_key;
- struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
- enum securityEnum sectype; /* what security flavor was specified? */
- bool sign; /* is signing required? */
- bool domainAuto:1;
- __u16 session_flags;
- __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
- __u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
- __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
- __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
-
- /*
- * Network interfaces available on the server this session is
- * connected to.
- *
- * Other channels can be opened by connecting and binding this
- * session to interfaces from this list.
- *
- * iface_lock should be taken when accessing any of these fields
- */
- spinlock_t iface_lock;
- /* ========= begin: protected by iface_lock ======== */
- struct list_head iface_list;
- size_t iface_count;
- unsigned long iface_last_update; /* jiffies */
- /* ========= end: protected by iface_lock ======== */
-
- spinlock_t chan_lock;
- /* ========= begin: protected by chan_lock ======== */
-#define CIFS_MAX_CHANNELS 16
-#define CIFS_ALL_CHANNELS_SET(ses) \
- ((1UL << (ses)->chan_count) - 1)
-#define CIFS_ALL_CHANS_GOOD(ses) \
- (!(ses)->chans_need_reconnect)
-#define CIFS_ALL_CHANS_NEED_RECONNECT(ses) \
- ((ses)->chans_need_reconnect == CIFS_ALL_CHANNELS_SET(ses))
-#define CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses) \
- ((ses)->chans_need_reconnect = CIFS_ALL_CHANNELS_SET(ses))
-#define CIFS_CHAN_NEEDS_RECONNECT(ses, index) \
- test_bit((index), &(ses)->chans_need_reconnect)
-#define CIFS_CHAN_IN_RECONNECT(ses, index) \
- ((ses)->chans[(index)].in_reconnect)
-
- struct cifs_chan chans[CIFS_MAX_CHANNELS];
- size_t chan_count;
- size_t chan_max;
- atomic_t chan_seq; /* round robin state */
-
- /*
- * chans_need_reconnect is a bitmap indicating which of the channels
- * under this smb session needs to be reconnected.
- * If not multichannel session, only one bit will be used.
- *
- * We will ask for sess and tcon reconnection only if all the
- * channels are marked for needing reconnection. This will
- * enable the sessions on top to continue to live till any
- * of the channels below are active.
- */
- unsigned long chans_need_reconnect;
- /* ========= end: protected by chan_lock ======== */
-};
-
-static inline bool
-cap_unix(struct cifs_ses *ses)
-{
- return ses->server->vals->cap_unix & ses->capabilities;
-}
-
-/*
- * common struct for holding inode info when searching for or updating an
- * inode with new info
- */
-
-#define CIFS_FATTR_DFS_REFERRAL 0x1
-#define CIFS_FATTR_DELETE_PENDING 0x2
-#define CIFS_FATTR_NEED_REVAL 0x4
-#define CIFS_FATTR_INO_COLLISION 0x8
-#define CIFS_FATTR_UNKNOWN_NLINK 0x10
-#define CIFS_FATTR_FAKE_ROOT_INO 0x20
-
-struct cifs_fattr {
- u32 cf_flags;
- u32 cf_cifsattrs;
- u64 cf_uniqueid;
- u64 cf_eof;
- u64 cf_bytes;
- u64 cf_createtime;
- kuid_t cf_uid;
- kgid_t cf_gid;
- umode_t cf_mode;
- dev_t cf_rdev;
- unsigned int cf_nlink;
- unsigned int cf_dtype;
- struct timespec64 cf_atime;
- struct timespec64 cf_mtime;
- struct timespec64 cf_ctime;
- u32 cf_cifstag;
- char *cf_symlink_target;
-};
-
-/*
- * there is one of these for each connection to a resource on a particular
- * session
- */
-struct cifs_tcon {
- struct list_head tcon_list;
- int tc_count;
- struct list_head rlist; /* reconnect list */
- spinlock_t tc_lock; /* protect anything here that is not protected */
- atomic_t num_local_opens; /* num of all opens including disconnected */
- atomic_t num_remote_opens; /* num of all network opens on server */
- struct list_head openFileList;
- spinlock_t open_file_lock; /* protects list above */
- struct cifs_ses *ses; /* pointer to session associated with */
- char tree_name[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
- char *nativeFileSystem;
- char *password; /* for share-level security */
- __u32 tid; /* The 4 byte tree id */
- __u16 Flags; /* optional support bits */
- enum tid_status_enum status;
- atomic_t num_smbs_sent;
- union {
- struct {
- atomic_t num_writes;
- atomic_t num_reads;
- atomic_t num_flushes;
- atomic_t num_oplock_brks;
- atomic_t num_opens;
- atomic_t num_closes;
- atomic_t num_deletes;
- atomic_t num_mkdirs;
- atomic_t num_posixopens;
- atomic_t num_posixmkdirs;
- atomic_t num_rmdirs;
- atomic_t num_renames;
- atomic_t num_t2renames;
- atomic_t num_ffirst;
- atomic_t num_fnext;
- atomic_t num_fclose;
- atomic_t num_hardlinks;
- atomic_t num_symlinks;
- atomic_t num_locks;
- atomic_t num_acl_get;
- atomic_t num_acl_set;
- } cifs_stats;
- struct {
- atomic_t smb2_com_sent[NUMBER_OF_SMB2_COMMANDS];
- atomic_t smb2_com_failed[NUMBER_OF_SMB2_COMMANDS];
- } smb2_stats;
- } stats;
- __u64 bytes_read;
- __u64 bytes_written;
- spinlock_t stat_lock; /* protects the two fields above */
- FILE_SYSTEM_DEVICE_INFO fsDevInfo;
- FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
- FILE_SYSTEM_UNIX_INFO fsUnixInfo;
- bool ipc:1; /* set if connection to IPC$ share (always also pipe) */
- bool pipe:1; /* set if connection to pipe share */
- bool print:1; /* set if connection to printer share */
- bool retry:1;
- bool nocase:1;
- bool nohandlecache:1; /* if strange server resource prob can turn off */
- bool nodelete:1;
- bool seal:1; /* transport encryption for this mounted share */
- bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
- for this mount even if server would support */
- bool posix_extensions; /* if true SMB3.11 posix extensions enabled */
- bool local_lease:1; /* check leases (only) on local system not remote */
- bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
- bool broken_sparse_sup; /* if server or share does not support sparse */
- bool need_reconnect:1; /* connection reset, tid now invalid */
- bool need_reopen_files:1; /* need to reopen tcon file handles */
- bool use_resilient:1; /* use resilient instead of durable handles */
- bool use_persistent:1; /* use persistent instead of durable handles */
- bool no_lease:1; /* Do not request leases on files or directories */
- bool use_witness:1; /* use witness protocol */
- __le32 capabilities;
- __u32 share_flags;
- __u32 maximal_access;
- __u32 vol_serial_number;
- __le64 vol_create_time;
- __u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */
- __u32 handle_timeout; /* persistent and durable handle timeout in ms */
- __u32 ss_flags; /* sector size flags */
- __u32 perf_sector_size; /* best sector size for perf */
- __u32 max_chunks;
- __u32 max_bytes_chunk;
- __u32 max_bytes_copy;
-#ifdef CONFIG_CIFS_FSCACHE
- u64 resource_id; /* server resource id */
- struct fscache_volume *fscache; /* cookie for share */
-#endif
- struct list_head pending_opens; /* list of incomplete opens */
- struct cached_fids *cfids;
- /* BB add field for back pointer to sb struct(s)? */
-#ifdef CONFIG_CIFS_DFS_UPCALL
- struct list_head ulist; /* cache update list */
-#endif
- struct delayed_work query_interfaces; /* query interfaces workqueue job */
-};
-
-/*
- * This is a refcounted and timestamped container for a tcon pointer. The
- * container holds a tcon reference. It is considered safe to free one of
- * these when the tl_count goes to 0. The tl_time is the time of the last
- * "get" on the container.
- */
-struct tcon_link {
- struct rb_node tl_rbnode;
- kuid_t tl_uid;
- unsigned long tl_flags;
-#define TCON_LINK_MASTER 0
-#define TCON_LINK_PENDING 1
-#define TCON_LINK_IN_TREE 2
- unsigned long tl_time;
- atomic_t tl_count;
- struct cifs_tcon *tl_tcon;
-};
-
-extern struct tcon_link *cifs_sb_tlink(struct cifs_sb_info *cifs_sb);
-extern void smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst);
-
-static inline struct cifs_tcon *
-tlink_tcon(struct tcon_link *tlink)
-{
- return tlink->tl_tcon;
-}
-
-static inline struct tcon_link *
-cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
-{
- return cifs_sb->master_tlink;
-}
-
-extern void cifs_put_tlink(struct tcon_link *tlink);
-
-static inline struct tcon_link *
-cifs_get_tlink(struct tcon_link *tlink)
-{
- if (tlink && !IS_ERR(tlink))
- atomic_inc(&tlink->tl_count);
- return tlink;
-}
-
-/* This function is always expected to succeed */
-extern struct cifs_tcon *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb);
-
-#define CIFS_OPLOCK_NO_CHANGE 0xfe
-
-struct cifs_pending_open {
- struct list_head olist;
- struct tcon_link *tlink;
- __u8 lease_key[16];
- __u32 oplock;
-};
-
-struct cifs_deferred_close {
- struct list_head dlist;
- struct tcon_link *tlink;
- __u16 netfid;
- __u64 persistent_fid;
- __u64 volatile_fid;
-};
-
-/*
- * This info hangs off the cifsFileInfo structure, pointed to by llist.
- * This is used to track byte stream locks on the file
- */
-struct cifsLockInfo {
- struct list_head llist; /* pointer to next cifsLockInfo */
- struct list_head blist; /* pointer to locks blocked on this */
- wait_queue_head_t block_q;
- __u64 offset;
- __u64 length;
- __u32 pid;
- __u16 type;
- __u16 flags;
-};
-
-/*
- * One of these for each open instance of a file
- */
-struct cifs_search_info {
- loff_t index_of_last_entry;
- __u16 entries_in_buffer;
- __u16 info_level;
- __u32 resume_key;
- char *ntwrk_buf_start;
- char *srch_entries_start;
- char *last_entry;
- const char *presume_name;
- unsigned int resume_name_len;
- bool endOfSearch:1;
- bool emptyDir:1;
- bool unicode:1;
- bool smallBuf:1; /* so we know which buf_release function to call */
-};
-
-#define ACL_NO_MODE ((umode_t)(-1))
-struct cifs_open_parms {
- struct cifs_tcon *tcon;
- struct cifs_sb_info *cifs_sb;
- int disposition;
- int desired_access;
- int create_options;
- const char *path;
- struct cifs_fid *fid;
- umode_t mode;
- bool reconnect:1;
-};
-
-struct cifs_fid {
- __u16 netfid;
- __u64 persistent_fid; /* persist file id for smb2 */
- __u64 volatile_fid; /* volatile file id for smb2 */
- __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */
- __u8 create_guid[16];
- __u32 access;
- struct cifs_pending_open *pending_open;
- unsigned int epoch;
-#ifdef CONFIG_CIFS_DEBUG2
- __u64 mid;
-#endif /* CIFS_DEBUG2 */
- bool purge_cache;
-};
-
-struct cifs_fid_locks {
- struct list_head llist;
- struct cifsFileInfo *cfile; /* fid that owns locks */
- struct list_head locks; /* locks held by fid above */
-};
-
-struct cifsFileInfo {
- /* following two lists are protected by tcon->open_file_lock */
- struct list_head tlist; /* pointer to next fid owned by tcon */
- struct list_head flist; /* next fid (file instance) for this inode */
- /* lock list below protected by cifsi->lock_sem */
- struct cifs_fid_locks *llist; /* brlocks held by this fid */
- kuid_t uid; /* allows finding which FileInfo structure */
- __u32 pid; /* process id who opened file */
- struct cifs_fid fid; /* file id from remote */
- struct list_head rlist; /* reconnect list */
- /* BB add lock scope info here if needed */ ;
- /* lock scope id (0 if none) */
- struct dentry *dentry;
- struct tcon_link *tlink;
- unsigned int f_flags;
- bool invalidHandle:1; /* file closed via session abend */
- bool swapfile:1;
- bool oplock_break_cancelled:1;
- unsigned int oplock_epoch; /* epoch from the lease break */
- __u32 oplock_level; /* oplock/lease level from the lease break */
- int count;
- spinlock_t file_info_lock; /* protects four flag/count fields above */
- struct mutex fh_mutex; /* prevents reopen race after dead ses*/
- struct cifs_search_info srch_inf;
- struct work_struct oplock_break; /* work for oplock breaks */
- struct work_struct put; /* work for the final part of _put */
- struct delayed_work deferred;
- bool deferred_close_scheduled; /* Flag to indicate close is scheduled */
- char *symlink_target;
-};
-
-struct cifs_io_parms {
- __u16 netfid;
- __u64 persistent_fid; /* persist file id for smb2 */
- __u64 volatile_fid; /* volatile file id for smb2 */
- __u32 pid;
- __u64 offset;
- unsigned int length;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
-};
-
-struct cifs_aio_ctx {
- struct kref refcount;
- struct list_head list;
- struct mutex aio_mutex;
- struct completion done;
- struct iov_iter iter;
- struct kiocb *iocb;
- struct cifsFileInfo *cfile;
- struct bio_vec *bv;
- loff_t pos;
- unsigned int npages;
- ssize_t rc;
- unsigned int len;
- unsigned int total_len;
- bool should_dirty;
- /*
- * Indicates if this aio_ctx is for direct_io,
- * If yes, iter is a copy of the user passed iov_iter
- */
- bool direct_io;
-};
-
-/* asynchronous read support */
-struct cifs_readdata {
- struct kref refcount;
- struct list_head list;
- struct completion done;
- struct cifsFileInfo *cfile;
- struct address_space *mapping;
- struct cifs_aio_ctx *ctx;
- __u64 offset;
- unsigned int bytes;
- unsigned int got_bytes;
- pid_t pid;
- int result;
- struct work_struct work;
- int (*read_into_pages)(struct TCP_Server_Info *server,
- struct cifs_readdata *rdata,
- unsigned int len);
- int (*copy_into_pages)(struct TCP_Server_Info *server,
- struct cifs_readdata *rdata,
- struct iov_iter *iter);
- struct kvec iov[2];
- struct TCP_Server_Info *server;
-#ifdef CONFIG_CIFS_SMB_DIRECT
- struct smbd_mr *mr;
-#endif
- unsigned int pagesz;
- unsigned int page_offset;
- unsigned int tailsz;
- struct cifs_credits credits;
- unsigned int nr_pages;
- struct page **pages;
-};
-
-/* asynchronous write support */
-struct cifs_writedata {
- struct kref refcount;
- struct list_head list;
- struct completion done;
- enum writeback_sync_modes sync_mode;
- struct work_struct work;
- struct cifsFileInfo *cfile;
- struct cifs_aio_ctx *ctx;
- __u64 offset;
- pid_t pid;
- unsigned int bytes;
- int result;
- struct TCP_Server_Info *server;
-#ifdef CONFIG_CIFS_SMB_DIRECT
- struct smbd_mr *mr;
-#endif
- unsigned int pagesz;
- unsigned int page_offset;
- unsigned int tailsz;
- struct cifs_credits credits;
- unsigned int nr_pages;
- struct page **pages;
-};
-
-/*
- * Take a reference on the file private data. Must be called with
- * cfile->file_info_lock held.
- */
-static inline void
-cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
-{
- ++cifs_file->count;
-}
-
-struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file);
-void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_hdlr,
- bool offload);
-void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
-
-#define CIFS_CACHE_READ_FLG 1
-#define CIFS_CACHE_HANDLE_FLG 2
-#define CIFS_CACHE_RH_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_HANDLE_FLG)
-#define CIFS_CACHE_WRITE_FLG 4
-#define CIFS_CACHE_RW_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG)
-#define CIFS_CACHE_RHW_FLG (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG)
-
-#define CIFS_CACHE_READ(cinode) ((cinode->oplock & CIFS_CACHE_READ_FLG) || (CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE))
-#define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG)
-#define CIFS_CACHE_WRITE(cinode) ((cinode->oplock & CIFS_CACHE_WRITE_FLG) || (CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE))
-
-/*
- * One of these for each file inode
- */
-
-struct cifsInodeInfo {
- struct netfs_inode netfs; /* Netfslib context and vfs inode */
- bool can_cache_brlcks;
- struct list_head llist; /* locks helb by this inode */
- /*
- * NOTE: Some code paths call down_read(lock_sem) twice, so
- * we must always use cifs_down_write() instead of down_write()
- * for this semaphore to avoid deadlocks.
- */
- struct rw_semaphore lock_sem; /* protect the fields above */
- /* BB add in lists for dirty pages i.e. write caching info for oplock */
- struct list_head openFileList;
- spinlock_t open_file_lock; /* protects openFileList */
- __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
- unsigned int oplock; /* oplock/lease level we have */
- unsigned int epoch; /* used to track lease state changes */
-#define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */
-#define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */
-#define CIFS_INODE_FLAG_UNUSED (2) /* Unused flag */
-#define CIFS_INO_DELETE_PENDING (3) /* delete pending on server */
-#define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */
-#define CIFS_INO_LOCK (5) /* lock bit for synchronization */
-#define CIFS_INO_MODIFIED_ATTR (6) /* Indicate change in mtime/ctime */
-#define CIFS_INO_CLOSE_ON_LOCK (7) /* Not to defer the close when lock is set */
- unsigned long flags;
- spinlock_t writers_lock;
- unsigned int writers; /* Number of writers on this inode */
- unsigned long time; /* jiffies of last update of inode */
- u64 server_eof; /* current file size on server -- protected by i_lock */
- u64 uniqueid; /* server inode number */
- u64 createtime; /* creation time on server */
- __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for this inode */
- struct list_head deferred_closes; /* list of deferred closes */
- spinlock_t deferred_lock; /* protection on deferred list */
- bool lease_granted; /* Flag to indicate whether lease or oplock is granted. */
- char *symlink_target;
-};
-
-static inline struct cifsInodeInfo *
-CIFS_I(struct inode *inode)
-{
- return container_of(inode, struct cifsInodeInfo, netfs.inode);
-}
-
-static inline struct cifs_sb_info *
-CIFS_SB(struct super_block *sb)
-{
- return sb->s_fs_info;
-}
-
-static inline struct cifs_sb_info *
-CIFS_FILE_SB(struct file *file)
-{
- return CIFS_SB(file_inode(file)->i_sb);
-}
-
-static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
-{
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
- return '/';
- else
- return '\\';
-}
-
-static inline void
-convert_delimiter(char *path, char delim)
-{
- char old_delim, *pos;
-
- if (delim == '/')
- old_delim = '\\';
- else
- old_delim = '/';
-
- pos = path;
- while ((pos = strchr(pos, old_delim)))
- *pos = delim;
-}
-
-#define cifs_stats_inc atomic_inc
-
-static inline void cifs_stats_bytes_written(struct cifs_tcon *tcon,
- unsigned int bytes)
-{
- if (bytes) {
- spin_lock(&tcon->stat_lock);
- tcon->bytes_written += bytes;
- spin_unlock(&tcon->stat_lock);
- }
-}
-
-static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon,
- unsigned int bytes)
-{
- spin_lock(&tcon->stat_lock);
- tcon->bytes_read += bytes;
- spin_unlock(&tcon->stat_lock);
-}
-
-
-/*
- * This is the prototype for the mid receive function. This function is for
- * receiving the rest of the SMB frame, starting with the WordCount (which is
- * just after the MID in struct smb_hdr). Note:
- *
- * - This will be called by cifsd, with no locks held.
- * - The mid will still be on the pending_mid_q.
- * - mid->resp_buf will point to the current buffer.
- *
- * Returns zero on a successful receive, or an error. The receive state in
- * the TCP_Server_Info will also be updated.
- */
-typedef int (mid_receive_t)(struct TCP_Server_Info *server,
- struct mid_q_entry *mid);
-
-/*
- * This is the prototype for the mid callback function. This is called once the
- * mid has been received off of the socket. When creating one, take special
- * care to avoid deadlocks. Things to bear in mind:
- *
- * - it will be called by cifsd, with no locks held
- * - the mid will be removed from any lists
- */
-typedef void (mid_callback_t)(struct mid_q_entry *mid);
-
-/*
- * This is the protopyte for mid handle function. This is called once the mid
- * has been recognized after decryption of the message.
- */
-typedef int (mid_handle_t)(struct TCP_Server_Info *server,
- struct mid_q_entry *mid);
-
-/* one of these for every pending CIFS request to the server */
-struct mid_q_entry {
- struct list_head qhead; /* mids waiting on reply from this server */
- struct kref refcount;
- struct TCP_Server_Info *server; /* server corresponding to this mid */
- __u64 mid; /* multiplex id */
- __u16 credits; /* number of credits consumed by this mid */
- __u16 credits_received; /* number of credits from the response */
- __u32 pid; /* process id */
- __u32 sequence_number; /* for CIFS signing */
- unsigned long when_alloc; /* when mid was created */
-#ifdef CONFIG_CIFS_STATS2
- unsigned long when_sent; /* time when smb send finished */
- unsigned long when_received; /* when demux complete (taken off wire) */
-#endif
- mid_receive_t *receive; /* call receive callback */
- mid_callback_t *callback; /* call completion callback */
- mid_handle_t *handle; /* call handle mid callback */
- void *callback_data; /* general purpose pointer for callback */
- struct task_struct *creator;
- void *resp_buf; /* pointer to received SMB header */
- unsigned int resp_buf_size;
- int mid_state; /* wish this were enum but can not pass to wait_event */
- unsigned int mid_flags;
- __le16 command; /* smb command code */
- unsigned int optype; /* operation type */
- bool large_buf:1; /* if valid response, is pointer to large buf */
- bool multiRsp:1; /* multiple trans2 responses for one request */
- bool multiEnd:1; /* both received */
- bool decrypted:1; /* decrypted entry */
-};
-
-struct close_cancelled_open {
- struct cifs_fid fid;
- struct cifs_tcon *tcon;
- struct work_struct work;
- __u64 mid;
- __u16 cmd;
-};
-
-/* Make code in transport.c a little cleaner by moving
- update of optional stats into function below */
-static inline void cifs_in_send_inc(struct TCP_Server_Info *server)
-{
- atomic_inc(&server->in_send);
-}
-
-static inline void cifs_in_send_dec(struct TCP_Server_Info *server)
-{
- atomic_dec(&server->in_send);
-}
-
-static inline void cifs_num_waiters_inc(struct TCP_Server_Info *server)
-{
- atomic_inc(&server->num_waiters);
-}
-
-static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server)
-{
- atomic_dec(&server->num_waiters);
-}
-
-#ifdef CONFIG_CIFS_STATS2
-static inline void cifs_save_when_sent(struct mid_q_entry *mid)
-{
- mid->when_sent = jiffies;
-}
-#else
-static inline void cifs_save_when_sent(struct mid_q_entry *mid)
-{
-}
-#endif
-
-/* for pending dnotify requests */
-struct dir_notify_req {
- struct list_head lhead;
- __le16 Pid;
- __le16 PidHigh;
- __u16 Mid;
- __u16 Tid;
- __u16 Uid;
- __u16 netfid;
- __u32 filter; /* CompletionFilter (for multishot) */
- int multishot;
- struct file *pfile;
-};
-
-struct dfs_info3_param {
- int flags; /* DFSREF_REFERRAL_SERVER, DFSREF_STORAGE_SERVER*/
- int path_consumed;
- int server_type;
- int ref_flag;
- char *path_name;
- char *node_name;
- int ttl;
-};
-
-struct file_list {
- struct list_head list;
- struct cifsFileInfo *cfile;
-};
-
-static inline void free_dfs_info_param(struct dfs_info3_param *param)
-{
- if (param) {
- kfree(param->path_name);
- kfree(param->node_name);
- }
-}
-
-static inline void free_dfs_info_array(struct dfs_info3_param *param,
- int number_of_items)
-{
- int i;
- if ((number_of_items == 0) || (param == NULL))
- return;
- for (i = 0; i < number_of_items; i++) {
- kfree(param[i].path_name);
- kfree(param[i].node_name);
- }
- kfree(param);
-}
-
-static inline bool is_interrupt_error(int error)
-{
- switch (error) {
- case -EINTR:
- case -ERESTARTSYS:
- case -ERESTARTNOHAND:
- case -ERESTARTNOINTR:
- return true;
- }
- return false;
-}
-
-static inline bool is_retryable_error(int error)
-{
- if (is_interrupt_error(error) || error == -EAGAIN)
- return true;
- return false;
-}
-
-
-/* cifs_get_writable_file() flags */
-#define FIND_WR_ANY 0
-#define FIND_WR_FSUID_ONLY 1
-#define FIND_WR_WITH_DELETE 2
-
-#define MID_FREE 0
-#define MID_REQUEST_ALLOCATED 1
-#define MID_REQUEST_SUBMITTED 2
-#define MID_RESPONSE_RECEIVED 4
-#define MID_RETRY_NEEDED 8 /* session closed while this request out */
-#define MID_RESPONSE_MALFORMED 0x10
-#define MID_SHUTDOWN 0x20
-
-/* Flags */
-#define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */
-#define MID_DELETED 2 /* Mid has been dequeued/deleted */
-
-/* Types of response buffer returned from SendReceive2 */
-#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
-#define CIFS_SMALL_BUFFER 1
-#define CIFS_LARGE_BUFFER 2
-#define CIFS_IOVEC 4 /* array of response buffers */
-
-/* Type of Request to SendReceive2 */
-#define CIFS_BLOCKING_OP 1 /* operation can block */
-#define CIFS_NON_BLOCKING 2 /* do not block waiting for credits */
-#define CIFS_TIMEOUT_MASK 0x003 /* only one of above set in req */
-#define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */
-#define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */
-#define CIFS_NO_RSP_BUF 0x040 /* no response buffer required */
-
-/* Type of request operation */
-#define CIFS_ECHO_OP 0x080 /* echo request */
-#define CIFS_OBREAK_OP 0x0100 /* oplock break request */
-#define CIFS_NEG_OP 0x0200 /* negotiate request */
-#define CIFS_CP_CREATE_CLOSE_OP 0x0400 /* compound create+close request */
-/* Lower bitmask values are reserved by others below. */
-#define CIFS_SESS_OP 0x2000 /* session setup request */
-#define CIFS_OP_MASK 0x2780 /* mask request type */
-
-#define CIFS_HAS_CREDITS 0x0400 /* already has credits */
-#define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sending */
-#define CIFS_NO_SRV_RSP 0x1000 /* there is no server response */
-
-/* Security Flags: indicate type of session setup needed */
-#define CIFSSEC_MAY_SIGN 0x00001
-#define CIFSSEC_MAY_NTLMV2 0x00004
-#define CIFSSEC_MAY_KRB5 0x00008
-#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
-#define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */
-
-#define CIFSSEC_MUST_SIGN 0x01001
-/* note that only one of the following can be set so the
-result of setting MUST flags more than once will be to
-require use of the stronger protocol */
-#define CIFSSEC_MUST_NTLMV2 0x04004
-#define CIFSSEC_MUST_KRB5 0x08008
-#ifdef CONFIG_CIFS_UPCALL
-#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
-#else
-#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */
-#endif /* UPCALL */
-#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
-#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */
-
-#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP)
-#define CIFSSEC_MAX (CIFSSEC_MUST_NTLMV2)
-#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)
-/*
- *****************************************************************
- * All constants go here
- *****************************************************************
- */
-
-#define UID_HASH (16)
-
-/*
- * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
- * following to be declared.
- */
-
-/****************************************************************************
- * Here are all the locks (spinlock, mutex, semaphore) in cifs.ko, arranged according
- * to the locking order. i.e. if two locks are to be held together, the lock that
- * appears higher in this list needs to be taken before the other.
- *
- * If you hold a lock that is lower in this list, and you need to take a higher lock
- * (or if you think that one of the functions that you're calling may need to), first
- * drop the lock you hold, pick up the higher lock, then the lower one. This will
- * ensure that locks are picked up only in one direction in the below table
- * (top to bottom).
- *
- * Also, if you expect a function to be called with a lock held, explicitly document
- * this in the comments on top of your function definition.
- *
- * And also, try to keep the critical sections (lock hold time) to be as minimal as
- * possible. Blocking / calling other functions with a lock held always increase
- * the risk of a possible deadlock.
- *
- * Following this rule will avoid unnecessary deadlocks, which can get really hard to
- * debug. Also, any new lock that you introduce, please add to this list in the correct
- * order.
- *
- * Please populate this list whenever you introduce new locks in your changes. Or in
- * case I've missed some existing locks. Please ensure that it's added in the list
- * based on the locking order expected.
- *
- * =====================================================================================
- * Lock Protects Initialization fn
- * =====================================================================================
- * vol_list_lock
- * vol_info->ctx_lock vol_info->ctx
- * cifs_sb_info->tlink_tree_lock cifs_sb_info->tlink_tree cifs_setup_cifs_sb
- * TCP_Server_Info-> TCP_Server_Info cifs_get_tcp_session
- * reconnect_mutex
- * TCP_Server_Info->srv_mutex TCP_Server_Info cifs_get_tcp_session
- * cifs_ses->session_mutex cifs_ses sesInfoAlloc
- * cifs_tcon
- * cifs_tcon->open_file_lock cifs_tcon->openFileList tconInfoAlloc
- * cifs_tcon->pending_opens
- * cifs_tcon->stat_lock cifs_tcon->bytes_read tconInfoAlloc
- * cifs_tcon->bytes_written
- * cifs_tcp_ses_lock cifs_tcp_ses_list sesInfoAlloc
- * GlobalMid_Lock GlobalMaxActiveXid init_cifs
- * GlobalCurrentXid
- * GlobalTotalActiveXid
- * TCP_Server_Info->srv_lock (anything in struct not protected by another lock and can change)
- * TCP_Server_Info->mid_lock TCP_Server_Info->pending_mid_q cifs_get_tcp_session
- * ->CurrentMid
- * (any changes in mid_q_entry fields)
- * TCP_Server_Info->req_lock TCP_Server_Info->in_flight cifs_get_tcp_session
- * ->credits
- * ->echo_credits
- * ->oplock_credits
- * ->reconnect_instance
- * cifs_ses->ses_lock (anything that is not protected by another lock and can change)
- * cifs_ses->iface_lock cifs_ses->iface_list sesInfoAlloc
- * ->iface_count
- * ->iface_last_update
- * cifs_ses->chan_lock cifs_ses->chans
- * ->chans_need_reconnect
- * ->chans_in_reconnect
- * cifs_tcon->tc_lock (anything that is not protected by another lock and can change)
- * cifsInodeInfo->open_file_lock cifsInodeInfo->openFileList cifs_alloc_inode
- * cifsInodeInfo->writers_lock cifsInodeInfo->writers cifsInodeInfo_alloc
- * cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once
- * ->can_cache_brlcks
- * cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc
- * cached_fid->fid_mutex cifs_tcon->crfid tconInfoAlloc
- * cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo
- * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
- * ->invalidHandle initiate_cifs_search
- * ->oplock_break_cancelled
- * cifs_aio_ctx->aio_mutex cifs_aio_ctx cifs_aio_ctx_alloc
- ****************************************************************************/
-
-#ifdef DECLARE_GLOBALS_HERE
-#define GLOBAL_EXTERN
-#else
-#define GLOBAL_EXTERN extern
-#endif
-
-/*
- * the list of TCP_Server_Info structures, ie each of the sockets
- * connecting our client to a distinct server (ip address), is
- * chained together by cifs_tcp_ses_list. The list of all our SMB
- * sessions (and from that the tree connections) can be found
- * by iterating over cifs_tcp_ses_list
- */
-extern struct list_head cifs_tcp_ses_list;
-
-/*
- * This lock protects the cifs_tcp_ses_list, the list of smb sessions per
- * tcp session, and the list of tcon's per smb session. It also protects
- * the reference counters for the server, smb session, and tcon.
- * generally the locks should be taken in order tcp_ses_lock before
- * tcon->open_file_lock and that before file->file_info_lock since the
- * structure order is cifs_socket-->cifs_ses-->cifs_tcon-->cifs_file
- */
-extern spinlock_t cifs_tcp_ses_lock;
-
-/*
- * Global transaction id (XID) information
- */
-extern unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
-extern unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
-extern unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
-extern spinlock_t GlobalMid_Lock; /* protects above & list operations on midQ entries */
-
-/*
- * Global counters, updated atomically
- */
-extern atomic_t sesInfoAllocCount;
-extern atomic_t tconInfoAllocCount;
-extern atomic_t tcpSesNextId;
-extern atomic_t tcpSesAllocCount;
-extern atomic_t tcpSesReconnectCount;
-extern atomic_t tconInfoReconnectCount;
-
-/* Various Debug counters */
-extern atomic_t buf_alloc_count; /* current number allocated */
-extern atomic_t small_buf_alloc_count;
-#ifdef CONFIG_CIFS_STATS2
-extern atomic_t total_buf_alloc_count; /* total allocated over all time */
-extern atomic_t total_small_buf_alloc_count;
-extern unsigned int slow_rsp_threshold; /* number of secs before logging */
-#endif
-
-/* Misc globals */
-extern bool enable_oplocks; /* enable or disable oplocks */
-extern bool lookupCacheEnabled;
-extern unsigned int global_secflags; /* if on, session setup sent
- with more secure ntlmssp2 challenge/resp */
-extern unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
-extern bool enable_gcm_256; /* allow optional negotiate of strongest signing (aes-gcm-256) */
-extern bool require_gcm_256; /* require use of strongest signing (aes-gcm-256) */
-extern bool enable_negotiate_signing; /* request use of faster (GMAC) signing if available */
-extern bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
-extern unsigned int CIFSMaxBufSize; /* max size not including hdr */
-extern unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
-extern unsigned int cifs_min_small; /* min size of small buf pool */
-extern unsigned int cifs_max_pending; /* MAX requests at once to server*/
-extern bool disable_legacy_dialects; /* forbid vers=1.0 and vers=2.0 mounts */
-extern atomic_t mid_count;
-
-void cifs_oplock_break(struct work_struct *work);
-void cifs_queue_oplock_break(struct cifsFileInfo *cfile);
-void smb2_deferred_work_close(struct work_struct *work);
-
-extern const struct slow_work_ops cifs_oplock_break_ops;
-extern struct workqueue_struct *cifsiod_wq;
-extern struct workqueue_struct *decrypt_wq;
-extern struct workqueue_struct *fileinfo_put_wq;
-extern struct workqueue_struct *cifsoplockd_wq;
-extern struct workqueue_struct *deferredclose_wq;
-extern __u32 cifs_lock_secret;
-
-extern mempool_t *cifs_mid_poolp;
-
-/* Operations for different SMB versions */
-#define SMB1_VERSION_STRING "1.0"
-#define SMB20_VERSION_STRING "2.0"
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-extern struct smb_version_operations smb1_operations;
-extern struct smb_version_values smb1_values;
-extern struct smb_version_operations smb20_operations;
-extern struct smb_version_values smb20_values;
-#endif /* CIFS_ALLOW_INSECURE_LEGACY */
-#define SMB21_VERSION_STRING "2.1"
-extern struct smb_version_operations smb21_operations;
-extern struct smb_version_values smb21_values;
-#define SMBDEFAULT_VERSION_STRING "default"
-extern struct smb_version_values smbdefault_values;
-#define SMB3ANY_VERSION_STRING "3"
-extern struct smb_version_values smb3any_values;
-#define SMB30_VERSION_STRING "3.0"
-extern struct smb_version_operations smb30_operations;
-extern struct smb_version_values smb30_values;
-#define SMB302_VERSION_STRING "3.02"
-#define ALT_SMB302_VERSION_STRING "3.0.2"
-/*extern struct smb_version_operations smb302_operations;*/ /* not needed yet */
-extern struct smb_version_values smb302_values;
-#define SMB311_VERSION_STRING "3.1.1"
-#define ALT_SMB311_VERSION_STRING "3.11"
-extern struct smb_version_operations smb311_operations;
-extern struct smb_version_values smb311_values;
-
-static inline char *get_security_type_str(enum securityEnum sectype)
-{
- switch (sectype) {
- case RawNTLMSSP:
- return "RawNTLMSSP";
- case Kerberos:
- return "Kerberos";
- case NTLMv2:
- return "NTLMv2";
- default:
- return "Unknown";
- }
-}
-
-static inline bool is_smb1_server(struct TCP_Server_Info *server)
-{
- return strcmp(server->vals->version_string, SMB1_VERSION_STRING) == 0;
-}
-
-static inline bool is_tcon_dfs(struct cifs_tcon *tcon)
-{
- /*
- * For SMB1, see MS-CIFS 2.4.55 SMB_COM_TREE_CONNECT_ANDX (0x75) and MS-CIFS 3.3.4.4 DFS
- * Subsystem Notifies That a Share Is a DFS Share.
- *
- * For SMB2+, see MS-SMB2 2.2.10 SMB2 TREE_CONNECT Response and MS-SMB2 3.3.4.14 Server
- * Application Updates a Share.
- */
- if (!tcon || !tcon->ses || !tcon->ses->server)
- return false;
- return is_smb1_server(tcon->ses->server) ? tcon->Flags & SMB_SHARE_IS_IN_DFS :
- tcon->share_flags & (SHI1005_FLAGS_DFS | SHI1005_FLAGS_DFS_ROOT);
-}
-
-static inline bool cifs_is_referral_server(struct cifs_tcon *tcon,
- const struct dfs_info3_param *ref)
-{
- /*
- * Check if all targets are capable of handling DFS referrals as per
- * MS-DFSC 2.2.4 RESP_GET_DFS_REFERRAL.
- */
- return is_tcon_dfs(tcon) || (ref && (ref->flags & DFSREF_REFERRAL_SERVER));
-}
-
-static inline u64 cifs_flock_len(const struct file_lock *fl)
-{
- return (u64)fl->fl_end - fl->fl_start + 1;
-}
-
-static inline size_t ntlmssp_workstation_name_size(const struct cifs_ses *ses)
-{
- if (WARN_ON_ONCE(!ses || !ses->server))
- return 0;
- /*
- * Make workstation name no more than 15 chars when using insecure dialects as some legacy
- * servers do require it during NTLMSSP.
- */
- if (ses->server->dialect <= SMB20_PROT_ID)
- return min_t(size_t, sizeof(ses->workstation_name), RFC1001_NAME_LEN_WITH_NULL);
- return sizeof(ses->workstation_name);
-}
-
-static inline void move_cifs_info_to_smb2(struct smb2_file_all_info *dst, const FILE_ALL_INFO *src)
-{
- memcpy(dst, src, (size_t)((u8 *)&src->AccessFlags - (u8 *)src));
- dst->AccessFlags = src->AccessFlags;
- dst->CurrentByteOffset = src->CurrentByteOffset;
- dst->Mode = src->Mode;
- dst->AlignmentRequirement = src->AlignmentRequirement;
- dst->FileNameLength = src->FileNameLength;
-}
-
-static inline unsigned int cifs_get_num_sgs(const struct smb_rqst *rqst,
- int num_rqst,
- const u8 *sig)
-{
- unsigned int len, skip;
- unsigned int nents = 0;
- unsigned long addr;
- int i, j;
-
- /* Assumes the first rqst has a transform header as the first iov.
- * I.e.
- * rqst[0].rq_iov[0] is transform header
- * rqst[0].rq_iov[1+] data to be encrypted/decrypted
- * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
- */
- for (i = 0; i < num_rqst; i++) {
- /*
- * The first rqst has a transform header where the
- * first 20 bytes are not part of the encrypted blob.
- */
- for (j = 0; j < rqst[i].rq_nvec; j++) {
- struct kvec *iov = &rqst[i].rq_iov[j];
-
- skip = (i == 0) && (j == 0) ? 20 : 0;
- addr = (unsigned long)iov->iov_base + skip;
- if (unlikely(is_vmalloc_addr((void *)addr))) {
- len = iov->iov_len - skip;
- nents += DIV_ROUND_UP(offset_in_page(addr) + len,
- PAGE_SIZE);
- } else {
- nents++;
- }
- }
- nents += rqst[i].rq_npages;
- }
- nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE);
- return nents;
-}
-
-/* We can not use the normal sg_set_buf() as we will sometimes pass a
- * stack object as buf.
- */
-static inline struct scatterlist *cifs_sg_set_buf(struct scatterlist *sg,
- const void *buf,
- unsigned int buflen)
-{
- unsigned long addr = (unsigned long)buf;
- unsigned int off = offset_in_page(addr);
-
- addr &= PAGE_MASK;
- if (unlikely(is_vmalloc_addr((void *)addr))) {
- do {
- unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off);
-
- sg_set_page(sg++, vmalloc_to_page((void *)addr), len, off);
-
- off = 0;
- addr += PAGE_SIZE;
- buflen -= len;
- } while (buflen);
- } else {
- sg_set_page(sg++, virt_to_page(addr), buflen, off);
- }
- return sg;
-}
-
-#endif /* _CIFS_GLOB_H */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
deleted file mode 100644
index d1abaeea974a..000000000000
--- a/fs/cifs/cifspdu.h
+++ /dev/null
@@ -1,2730 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2002,2009
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#ifndef _CIFSPDU_H
-#define _CIFSPDU_H
-
-#include <net/sock.h>
-#include <asm/unaligned.h>
-#include "../smbfs_common/smbfsctl.h"
-
-#define CIFS_PROT 0
-#define POSIX_PROT (CIFS_PROT+1)
-#define BAD_PROT 0xFFFF
-
-/* SMB command codes:
- * Note some commands have minimal (wct=0,bcc=0), or uninteresting, responses
- * (ie which include no useful data other than the SMB error code itself).
- * This can allow us to avoid response buffer allocations and copy in some cases
- */
-#define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */
-#define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */
-#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
-#define SMB_COM_FLUSH 0x05 /* triv req/rsp */
-#define SMB_COM_DELETE 0x06 /* trivial response */
-#define SMB_COM_RENAME 0x07 /* trivial response */
-#define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */
-#define SMB_COM_SETATTR 0x09 /* trivial response */
-#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
-#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/
-#define SMB_COM_ECHO 0x2B /* echo request */
-#define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */
-#define SMB_COM_READ_ANDX 0x2E
-#define SMB_COM_WRITE_ANDX 0x2F
-#define SMB_COM_TRANSACTION2 0x32
-#define SMB_COM_TRANSACTION2_SECONDARY 0x33
-#define SMB_COM_FIND_CLOSE2 0x34 /* trivial response */
-#define SMB_COM_TREE_DISCONNECT 0x71 /* trivial response */
-#define SMB_COM_NEGOTIATE 0x72
-#define SMB_COM_SESSION_SETUP_ANDX 0x73
-#define SMB_COM_LOGOFF_ANDX 0x74 /* trivial response */
-#define SMB_COM_TREE_CONNECT_ANDX 0x75
-#define SMB_COM_NT_TRANSACT 0xA0
-#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
-#define SMB_COM_NT_CREATE_ANDX 0xA2
-#define SMB_COM_NT_CANCEL 0xA4 /* no response */
-#define SMB_COM_NT_RENAME 0xA5 /* trivial response */
-
-/* Transact2 subcommand codes */
-#define TRANS2_OPEN 0x00
-#define TRANS2_FIND_FIRST 0x01
-#define TRANS2_FIND_NEXT 0x02
-#define TRANS2_QUERY_FS_INFORMATION 0x03
-#define TRANS2_SET_FS_INFORMATION 0x04
-#define TRANS2_QUERY_PATH_INFORMATION 0x05
-#define TRANS2_SET_PATH_INFORMATION 0x06
-#define TRANS2_QUERY_FILE_INFORMATION 0x07
-#define TRANS2_SET_FILE_INFORMATION 0x08
-#define TRANS2_GET_DFS_REFERRAL 0x10
-#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
-
-/* SMB Transact (Named Pipe) subcommand codes */
-#define TRANS_SET_NMPIPE_STATE 0x0001
-#define TRANS_RAW_READ_NMPIPE 0x0011
-#define TRANS_QUERY_NMPIPE_STATE 0x0021
-#define TRANS_QUERY_NMPIPE_INFO 0x0022
-#define TRANS_PEEK_NMPIPE 0x0023
-#define TRANS_TRANSACT_NMPIPE 0x0026
-#define TRANS_RAW_WRITE_NMPIPE 0x0031
-#define TRANS_READ_NMPIPE 0x0036
-#define TRANS_WRITE_NMPIPE 0x0037
-#define TRANS_WAIT_NMPIPE 0x0053
-#define TRANS_CALL_NMPIPE 0x0054
-
-/* NT Transact subcommand codes */
-#define NT_TRANSACT_CREATE 0x01
-#define NT_TRANSACT_IOCTL 0x02
-#define NT_TRANSACT_SET_SECURITY_DESC 0x03
-#define NT_TRANSACT_NOTIFY_CHANGE 0x04
-#define NT_TRANSACT_RENAME 0x05
-#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
-#define NT_TRANSACT_GET_USER_QUOTA 0x07
-#define NT_TRANSACT_SET_USER_QUOTA 0x08
-
-#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
-/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
-/* among the requests (NTCreateX response is bigger with wct of 34) */
-#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
-#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */
-
-/* internal cifs vfs structures */
-/*****************************************************************
- * All constants go here
- *****************************************************************
- */
-
-/*
- * Starting value for maximum SMB size negotiation
- */
-#define CIFS_MAX_MSGSIZE (4*4096)
-
-/*
- * Size of encrypted user password in bytes
- */
-#define CIFS_ENCPWD_SIZE (16)
-
-/*
- * Size of the crypto key returned on the negotiate SMB in bytes
- */
-#define CIFS_CRYPTO_KEY_SIZE (8)
-
-/*
- * Size of the ntlm client response
- */
-#define CIFS_AUTH_RESP_SIZE (24)
-
-/*
- * Size of the session key (crypto key encrypted with the password
- */
-#define CIFS_SESS_KEY_SIZE (16)
-
-#define CIFS_SERVER_CHALLENGE_SIZE (8)
-#define CIFS_HMAC_MD5_HASH_SIZE (16)
-#define CIFS_CPHTXT_SIZE (16)
-#define CIFS_NTHASH_SIZE (16)
-
-/*
- * Maximum user name length
- */
-#define CIFS_UNLEN (20)
-
-/*
- * Flags on SMB open
- */
-#define SMBOPEN_WRITE_THROUGH 0x4000
-#define SMBOPEN_DENY_ALL 0x0010
-#define SMBOPEN_DENY_WRITE 0x0020
-#define SMBOPEN_DENY_READ 0x0030
-#define SMBOPEN_DENY_NONE 0x0040
-#define SMBOPEN_READ 0x0000
-#define SMBOPEN_WRITE 0x0001
-#define SMBOPEN_READWRITE 0x0002
-#define SMBOPEN_EXECUTE 0x0003
-
-#define SMBOPEN_OCREATE 0x0010
-#define SMBOPEN_OTRUNC 0x0002
-#define SMBOPEN_OAPPEND 0x0001
-
-/*
- * SMB flag definitions
- */
-#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock smb */
-#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
-#define SMBFLG_RSVD 0x04
-#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off
- implies case sensitive file handling request) */
-#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
-#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
-#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
-#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
-
-/*
- * SMB flag2 definitions
- */
-#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3)
- path names in response */
-#define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
-#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
-#define SMBFLG2_COMPRESSED (8)
-#define SMBFLG2_SECURITY_SIGNATURE_REQUIRED (0x10)
-#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
-#define SMBFLG2_REPARSE_PATH (0x400)
-#define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
-#define SMBFLG2_DFS cpu_to_le16(0x1000)
-#define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
-#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
-#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
-
-/*
- * These are the file access permission bits defined in CIFS for the
- * NTCreateAndX as well as the level 0x107
- * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
- * responds with the AccessFlags.
- * The AccessFlags specifies the access permissions a caller has to the
- * file and can have any suitable combination of the following values:
- */
-
-#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
-#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
-#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
-#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
- /* with the file can be read */
-#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
- /* with the file can be written */
-#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
- /* the file using system paging I/O */
-#define FILE_DELETE_CHILD 0x00000040
-#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
- /* file can be read */
-#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
- /* file can be written */
-#define DELETE 0x00010000 /* The file can be deleted */
-#define READ_CONTROL 0x00020000 /* The access control list and */
- /* ownership associated with the */
- /* file can be read */
-#define WRITE_DAC 0x00040000 /* The access control list and */
- /* ownership associated with the */
- /* file can be written. */
-#define WRITE_OWNER 0x00080000 /* Ownership information associated */
- /* with the file can be written */
-#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
- /* synchronize with the completion */
- /* of an input/output request */
-#define SYSTEM_SECURITY 0x01000000 /* The system access control list */
- /* can be read and changed */
-#define GENERIC_ALL 0x10000000
-#define GENERIC_EXECUTE 0x20000000
-#define GENERIC_WRITE 0x40000000
-#define GENERIC_READ 0x80000000
- /* In summary - Relevant file */
- /* access flags from CIFS are */
- /* file_read_data, file_write_data */
- /* file_execute, file_read_attributes*/
- /* write_dac, and delete. */
-
-#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
-#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
- | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
-#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
-
-#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA \
- | FILE_READ_ATTRIBUTES \
- | FILE_WRITE_ATTRIBUTES \
- | DELETE | READ_CONTROL | WRITE_DAC \
- | WRITE_OWNER | SYNCHRONIZE)
-#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
- | FILE_READ_EA | FILE_WRITE_EA \
- | FILE_READ_ATTRIBUTES \
- | FILE_WRITE_ATTRIBUTES \
- | DELETE | READ_CONTROL | WRITE_DAC \
- | WRITE_OWNER | SYNCHRONIZE)
-#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
- | FILE_READ_ATTRIBUTES \
- | FILE_WRITE_ATTRIBUTES \
- | DELETE | READ_CONTROL | WRITE_DAC \
- | WRITE_OWNER | SYNCHRONIZE)
-
-#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \
- | READ_CONTROL | SYNCHRONIZE)
-
-
-/*
- * Invalid readdir handle
- */
-#define CIFS_NO_HANDLE 0xFFFF
-
-#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL
-
-/* IPC$ in ASCII */
-#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
-
-/* IPC$ in Unicode */
-#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
-
-/* Unicode Null terminate 2 bytes of 0 */
-#define UNICODE_NULL "\x00\x00"
-#define ASCII_NULL 0x00
-
-/*
- * Server type values (returned on EnumServer API
- */
-#define CIFS_SV_TYPE_DC 0x00000008
-#define CIFS_SV_TYPE_BACKDC 0x00000010
-
-/*
- * Alias type flags (From EnumAlias API call
- */
-#define CIFS_ALIAS_TYPE_FILE 0x0001
-#define CIFS_SHARE_TYPE_FILE 0x0000
-
-/*
- * File Attribute flags
- */
-#define ATTR_READONLY 0x0001
-#define ATTR_HIDDEN 0x0002
-#define ATTR_SYSTEM 0x0004
-#define ATTR_VOLUME 0x0008
-#define ATTR_DIRECTORY 0x0010
-#define ATTR_ARCHIVE 0x0020
-#define ATTR_DEVICE 0x0040
-#define ATTR_NORMAL 0x0080
-#define ATTR_TEMPORARY 0x0100
-#define ATTR_SPARSE 0x0200
-#define ATTR_REPARSE 0x0400
-#define ATTR_COMPRESSED 0x0800
-#define ATTR_OFFLINE 0x1000 /* ie file not immediately available -
- on offline storage */
-#define ATTR_NOT_CONTENT_INDEXED 0x2000
-#define ATTR_ENCRYPTED 0x4000
-#define ATTR_POSIX_SEMANTICS 0x01000000
-#define ATTR_BACKUP_SEMANTICS 0x02000000
-#define ATTR_DELETE_ON_CLOSE 0x04000000
-#define ATTR_SEQUENTIAL_SCAN 0x08000000
-#define ATTR_RANDOM_ACCESS 0x10000000
-#define ATTR_NO_BUFFERING 0x20000000
-#define ATTR_WRITE_THROUGH 0x80000000
-
-/* ShareAccess flags */
-#define FILE_NO_SHARE 0x00000000
-#define FILE_SHARE_READ 0x00000001
-#define FILE_SHARE_WRITE 0x00000002
-#define FILE_SHARE_DELETE 0x00000004
-#define FILE_SHARE_ALL 0x00000007
-
-/* CreateDisposition flags, similar to CreateAction as well */
-#define FILE_SUPERSEDE 0x00000000
-#define FILE_OPEN 0x00000001
-#define FILE_CREATE 0x00000002
-#define FILE_OPEN_IF 0x00000003
-#define FILE_OVERWRITE 0x00000004
-#define FILE_OVERWRITE_IF 0x00000005
-
-/* CreateOptions */
-#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
-#define CREATE_WRITE_THROUGH 0x00000002
-#define CREATE_SEQUENTIAL 0x00000004
-#define CREATE_NO_BUFFER 0x00000008 /* should not buffer on srv */
-#define CREATE_SYNC_ALERT 0x00000010 /* MBZ */
-#define CREATE_ASYNC_ALERT 0x00000020 /* MBZ */
-#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
-#define CREATE_TREE_CONNECTION 0x00000080 /* should be zero */
-#define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */
-#define CREATE_NO_EA_KNOWLEDGE 0x00000200
-#define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete
- "open for recovery" flag should
- be zero in any case */
-#define CREATE_OPEN_FOR_RECOVERY 0x00000400
-#define CREATE_RANDOM_ACCESS 0x00000800
-#define CREATE_DELETE_ON_CLOSE 0x00001000
-#define CREATE_OPEN_BY_ID 0x00002000
-#define CREATE_OPEN_BACKUP_INTENT 0x00004000
-#define CREATE_NO_COMPRESSION 0x00008000
-#define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */
-#define OPEN_REPARSE_POINT 0x00200000
-#define OPEN_NO_RECALL 0x00400000
-#define OPEN_FREE_SPACE_QUERY 0x00800000 /* should be zero */
-#define CREATE_OPTIONS_MASK 0x007FFFFF
-#define CREATE_OPTION_READONLY 0x10000000
-#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
-
-/* ImpersonationLevel flags */
-#define SECURITY_ANONYMOUS 0
-#define SECURITY_IDENTIFICATION 1
-#define SECURITY_IMPERSONATION 2
-#define SECURITY_DELEGATION 3
-
-/* SecurityFlags */
-#define SECURITY_CONTEXT_TRACKING 0x01
-#define SECURITY_EFFECTIVE_ONLY 0x02
-
-/*
- * Default PID value, used in all SMBs where the PID is not important
- */
-#define CIFS_DFT_PID 0x1234
-
-/*
- * We use the same routine for Copy and Move SMBs. This flag is used to
- * distinguish
- */
-#define CIFS_COPY_OP 1
-#define CIFS_RENAME_OP 2
-
-#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
-#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
-
-struct smb_hdr {
- __be32 smb_buf_length; /* BB length is only two (rarely three) bytes,
- with one or two byte "type" preceding it that will be
- zero - we could mask the type byte off */
- __u8 Protocol[4];
- __u8 Command;
- union {
- struct {
- __u8 ErrorClass;
- __u8 Reserved;
- __le16 Error;
- } __attribute__((packed)) DosError;
- __le32 CifsError;
- } __attribute__((packed)) Status;
- __u8 Flags;
- __le16 Flags2; /* note: le */
- __le16 PidHigh;
- union {
- struct {
- __le32 SequenceNumber; /* le */
- __u32 Reserved; /* zero */
- } __attribute__((packed)) Sequence;
- __u8 SecuritySignature[8]; /* le */
- } __attribute__((packed)) Signature;
- __u8 pad[2];
- __u16 Tid;
- __le16 Pid;
- __u16 Uid;
- __le16 Mid;
- __u8 WordCount;
-} __attribute__((packed));
-
-/* given a pointer to an smb_hdr, retrieve a void pointer to the ByteCount */
-static inline void *
-BCC(struct smb_hdr *smb)
-{
- return (void *)smb + sizeof(*smb) + 2 * smb->WordCount;
-}
-
-/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
-#define pByteArea(smb_var) (BCC(smb_var) + 2)
-
-/* get the unconverted ByteCount for a SMB packet and return it */
-static inline __u16
-get_bcc(struct smb_hdr *hdr)
-{
- __le16 *bc_ptr = (__le16 *)BCC(hdr);
-
- return get_unaligned_le16(bc_ptr);
-}
-
-/* set the ByteCount for a SMB packet in little-endian */
-static inline void
-put_bcc(__u16 count, struct smb_hdr *hdr)
-{
- __le16 *bc_ptr = (__le16 *)BCC(hdr);
-
- put_unaligned_le16(count, bc_ptr);
-}
-
-/*
- * Computer Name Length (since Netbios name was length 16 with last byte 0x20)
- * No longer as important, now that TCP names are more commonly used to
- * resolve hosts.
- */
-#define CNLEN 15
-
-/*
- * Share Name Length (SNLEN)
- * Note: This length was limited by the SMB used to get
- * the Share info. NetShareEnum only returned 13
- * chars, including the null termination.
- * This was removed because it no longer is limiting.
- */
-
-/*
- * Comment Length
- */
-#define MAXCOMMENTLEN 40
-
-/*
- * The OS/2 maximum path name
- */
-#define MAX_PATHCONF 256
-
-/*
- * SMB frame definitions (following must be packed structs)
- * See the SNIA CIFS Specification for details.
- *
- * The Naming convention is the lower case version of the
- * smb command code name for the struct and this is typedef to the
- * uppercase version of the same name with the prefix SMB_ removed
- * for brevity. Although typedefs are not commonly used for
- * structure definitions in the Linux kernel, their use in the
- * CIFS standards document, which this code is based on, may
- * make this one of the cases where typedefs for structures make
- * sense to improve readability for readers of the standards doc.
- * Typedefs can always be removed later if they are too distracting
- * and they are only used for the CIFSs PDUs themselves, not
- * internal cifs vfs structures
- *
- */
-
-typedef struct negotiate_req {
- struct smb_hdr hdr; /* wct = 0 */
- __le16 ByteCount;
- unsigned char DialectsArray[];
-} __attribute__((packed)) NEGOTIATE_REQ;
-
-#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */
-
-#define READ_RAW_ENABLE 1
-#define WRITE_RAW_ENABLE 2
-#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
-#define SMB1_CLIENT_GUID_SIZE (16)
-typedef struct negotiate_rsp {
- struct smb_hdr hdr; /* wct = 17 */
- __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
- __u8 SecurityMode;
- __le16 MaxMpxCount;
- __le16 MaxNumberVcs;
- __le32 MaxBufferSize;
- __le32 MaxRawSize;
- __le32 SessionKey;
- __le32 Capabilities; /* see below */
- __le32 SystemTimeLow;
- __le32 SystemTimeHigh;
- __le16 ServerTimeZone;
- __u8 EncryptionKeyLength;
- __u16 ByteCount;
- union {
- /* cap extended security off */
- DECLARE_FLEX_ARRAY(unsigned char, EncryptionKey);
- /* followed by Domain name - if extended security is off */
- /* followed by 16 bytes of server GUID */
- /* then security blob if cap_extended_security negotiated */
- struct {
- unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
- unsigned char SecurityBlob[];
- } __attribute__((packed)) extended_response;
- } __attribute__((packed)) u;
-} __attribute__((packed)) NEGOTIATE_RSP;
-
-/* SecurityMode bits */
-#define SECMODE_USER 0x01 /* off indicates share level security */
-#define SECMODE_PW_ENCRYPT 0x02
-#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */
-#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */
-
-/* Negotiate response Capabilities */
-#define CAP_RAW_MODE 0x00000001
-#define CAP_MPX_MODE 0x00000002
-#define CAP_UNICODE 0x00000004
-#define CAP_LARGE_FILES 0x00000008
-#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */
-#define CAP_RPC_REMOTE_APIS 0x00000020
-#define CAP_STATUS32 0x00000040
-#define CAP_LEVEL_II_OPLOCKS 0x00000080
-#define CAP_LOCK_AND_READ 0x00000100
-#define CAP_NT_FIND 0x00000200
-#define CAP_DFS 0x00001000
-#define CAP_INFOLEVEL_PASSTHRU 0x00002000
-#define CAP_LARGE_READ_X 0x00004000
-#define CAP_LARGE_WRITE_X 0x00008000
-#define CAP_LWIO 0x00010000 /* support fctl_srv_req_resume_key */
-#define CAP_UNIX 0x00800000
-#define CAP_COMPRESSED_DATA 0x02000000
-#define CAP_DYNAMIC_REAUTH 0x20000000
-#define CAP_PERSISTENT_HANDLES 0x40000000
-#define CAP_EXTENDED_SECURITY 0x80000000
-
-typedef union smb_com_session_setup_andx {
- struct { /* request format */
- struct smb_hdr hdr; /* wct = 12 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 MaxBufferSize;
- __le16 MaxMpxCount;
- __le16 VcNumber;
- __u32 SessionKey;
- __le16 SecurityBlobLength;
- __u32 Reserved;
- __le32 Capabilities; /* see below */
- __le16 ByteCount;
- unsigned char SecurityBlob[1]; /* followed by */
- /* STRING NativeOS */
- /* STRING NativeLanMan */
- } __attribute__((packed)) req; /* NTLM request format (with
- extended security */
-
- struct { /* request format */
- struct smb_hdr hdr; /* wct = 13 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 MaxBufferSize;
- __le16 MaxMpxCount;
- __le16 VcNumber;
- __u32 SessionKey;
- __le16 CaseInsensitivePasswordLength; /* ASCII password len */
- __le16 CaseSensitivePasswordLength; /* Unicode password length*/
- __u32 Reserved; /* see below */
- __le32 Capabilities;
- __le16 ByteCount;
- unsigned char CaseInsensitivePassword[1]; /* followed by: */
- /* unsigned char * CaseSensitivePassword; */
- /* STRING AccountName */
- /* STRING PrimaryDomain */
- /* STRING NativeOS */
- /* STRING NativeLanMan */
- } __attribute__((packed)) req_no_secext; /* NTLM request format (without
- extended security */
-
- struct { /* default (NTLM) response format */
- struct smb_hdr hdr; /* wct = 4 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 Action; /* see below */
- __le16 SecurityBlobLength;
- __u16 ByteCount;
- unsigned char SecurityBlob[1]; /* followed by */
-/* unsigned char * NativeOS; */
-/* unsigned char * NativeLanMan; */
-/* unsigned char * PrimaryDomain; */
- } __attribute__((packed)) resp; /* NTLM response
- (with or without extended sec) */
-
- struct { /* request format */
- struct smb_hdr hdr; /* wct = 10 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 MaxBufferSize;
- __le16 MaxMpxCount;
- __le16 VcNumber;
- __u32 SessionKey;
- __le16 PasswordLength;
- __u32 Reserved; /* encrypt key len and offset */
- __le16 ByteCount;
- unsigned char AccountPassword[1]; /* followed by */
- /* STRING AccountName */
- /* STRING PrimaryDomain */
- /* STRING NativeOS */
- /* STRING NativeLanMan */
- } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) req format */
-
- struct { /* default (NTLM) response format */
- struct smb_hdr hdr; /* wct = 3 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 Action; /* see below */
- __u16 ByteCount;
- unsigned char NativeOS[1]; /* followed by */
-/* unsigned char * NativeLanMan; */
-/* unsigned char * PrimaryDomain; */
- } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */
-} __attribute__((packed)) SESSION_SETUP_ANDX;
-
-/* format of NLTMv2 Response ie "case sensitive password" hash when NTLMv2 */
-
-#define NTLMSSP_SERVER_TYPE 1
-#define NTLMSSP_DOMAIN_TYPE 2
-#define NTLMSSP_FQ_DOMAIN_TYPE 3
-#define NTLMSSP_DNS_DOMAIN_TYPE 4
-#define NTLMSSP_DNS_PARENT_TYPE 5
-
-struct ntlmssp2_name {
- __le16 type;
- __le16 length;
-/* char name[length]; */
-} __attribute__((packed));
-
-struct ntlmv2_resp {
- union {
- char ntlmv2_hash[CIFS_ENCPWD_SIZE];
- struct {
- __u8 reserved[8];
- __u8 key[CIFS_SERVER_CHALLENGE_SIZE];
- } __attribute__((packed)) challenge;
- } __attribute__((packed));
- __le32 blob_signature;
- __u32 reserved;
- __le64 time;
- __u64 client_chal; /* random */
- __u32 reserved2;
- /* array of name entries could follow ending in minimum 4 byte struct */
-} __attribute__((packed));
-
-
-#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
-
-/* Capabilities bits (for NTLM SessSetup request) */
-#define CAP_UNICODE 0x00000004
-#define CAP_LARGE_FILES 0x00000008
-#define CAP_NT_SMBS 0x00000010
-#define CAP_STATUS32 0x00000040
-#define CAP_LEVEL_II_OPLOCKS 0x00000080
-#define CAP_NT_FIND 0x00000200 /* reserved should be zero
- (because NT_SMBs implies the same thing?) */
-#define CAP_BULK_TRANSFER 0x20000000
-#define CAP_EXTENDED_SECURITY 0x80000000
-
-/* Action bits */
-#define GUEST_LOGIN 1
-
-typedef struct smb_com_tconx_req {
- struct smb_hdr hdr; /* wct = 4 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 Flags; /* see below */
- __le16 PasswordLength;
- __le16 ByteCount;
- unsigned char Password[1]; /* followed by */
-/* STRING Path *//* \\server\share name */
- /* STRING Service */
-} __attribute__((packed)) TCONX_REQ;
-
-typedef struct smb_com_tconx_rsp {
- struct smb_hdr hdr; /* wct = 3 , not extended response */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 OptionalSupport; /* see below */
- __u16 ByteCount;
- unsigned char Service[1]; /* always ASCII, not Unicode */
- /* STRING NativeFileSystem */
-} __attribute__((packed)) TCONX_RSP;
-
-typedef struct smb_com_tconx_rsp_ext {
- struct smb_hdr hdr; /* wct = 7, extended response */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 OptionalSupport; /* see below */
- __le32 MaximalShareAccessRights;
- __le32 GuestMaximalShareAccessRights;
- __u16 ByteCount;
- unsigned char Service[1]; /* always ASCII, not Unicode */
- /* STRING NativeFileSystem */
-} __attribute__((packed)) TCONX_RSP_EXT;
-
-
-/* tree connect Flags */
-#define DISCONNECT_TID 0x0001
-#define TCON_EXTENDED_SIGNATURES 0x0004
-#define TCON_EXTENDED_SECINFO 0x0008
-
-/* OptionalSupport bits */
-#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* "must have" directory search bits
- (exclusive searches supported) */
-#define SMB_SHARE_IS_IN_DFS 0x0002
-#define SMB_CSC_MASK 0x000C
-/* CSC flags defined as follows */
-#define SMB_CSC_CACHE_MANUAL_REINT 0x0000
-#define SMB_CSC_CACHE_AUTO_REINT 0x0004
-#define SMB_CSC_CACHE_VDO 0x0008
-#define SMB_CSC_NO_CACHING 0x000C
-#define SMB_UNIQUE_FILE_NAME 0x0010
-#define SMB_EXTENDED_SIGNATURES 0x0020
-
-/* services
- *
- * A: ie disk
- * LPT1: ie printer
- * IPC ie named pipe
- * COMM
- * ????? ie any type
- *
- */
-
-typedef struct smb_com_echo_req {
- struct smb_hdr hdr;
- __le16 EchoCount;
- __le16 ByteCount;
- char Data[1];
-} __attribute__((packed)) ECHO_REQ;
-
-typedef struct smb_com_echo_rsp {
- struct smb_hdr hdr;
- __le16 SequenceNumber;
- __le16 ByteCount;
- char Data[1];
-} __attribute__((packed)) ECHO_RSP;
-
-typedef struct smb_com_logoff_andx_req {
- struct smb_hdr hdr; /* wct = 2 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __u16 AndXOffset;
- __u16 ByteCount;
-} __attribute__((packed)) LOGOFF_ANDX_REQ;
-
-typedef struct smb_com_logoff_andx_rsp {
- struct smb_hdr hdr; /* wct = 2 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __u16 AndXOffset;
- __u16 ByteCount;
-} __attribute__((packed)) LOGOFF_ANDX_RSP;
-
-typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on
- tree_connect PDU to effect disconnect */
- /* tdis is probably simplest SMB PDU */
- struct {
- struct smb_hdr hdr; /* wct = 0 */
- __u16 ByteCount; /* bcc = 0 */
- } __attribute__((packed)) req;
- struct {
- struct smb_hdr hdr; /* wct = 0 */
- __u16 ByteCount; /* bcc = 0 */
- } __attribute__((packed)) resp;
-} __attribute__((packed)) TREE_DISCONNECT;
-
-typedef struct smb_com_close_req {
- struct smb_hdr hdr; /* wct = 3 */
- __u16 FileID;
- __u32 LastWriteTime; /* should be zero or -1 */
- __u16 ByteCount; /* 0 */
-} __attribute__((packed)) CLOSE_REQ;
-
-typedef struct smb_com_close_rsp {
- struct smb_hdr hdr; /* wct = 0 */
- __u16 ByteCount; /* bct = 0 */
-} __attribute__((packed)) CLOSE_RSP;
-
-typedef struct smb_com_flush_req {
- struct smb_hdr hdr; /* wct = 1 */
- __u16 FileID;
- __u16 ByteCount; /* 0 */
-} __attribute__((packed)) FLUSH_REQ;
-
-typedef struct smb_com_findclose_req {
- struct smb_hdr hdr; /* wct = 1 */
- __u16 FileID;
- __u16 ByteCount; /* 0 */
-} __attribute__((packed)) FINDCLOSE_REQ;
-
-/* OpenFlags */
-#define REQ_MORE_INFO 0x00000001 /* legacy (OPEN_AND_X) only */
-#define REQ_OPLOCK 0x00000002
-#define REQ_BATCHOPLOCK 0x00000004
-#define REQ_OPENDIRONLY 0x00000008
-#define REQ_EXTENDED_INFO 0x00000010
-
-/* File type */
-#define DISK_TYPE 0x0000
-#define BYTE_PIPE_TYPE 0x0001
-#define MESSAGE_PIPE_TYPE 0x0002
-#define PRINTER_TYPE 0x0003
-#define COMM_DEV_TYPE 0x0004
-#define UNKNOWN_TYPE 0xFFFF
-
-/* Device Type or File Status Flags */
-#define NO_EAS 0x0001
-#define NO_SUBSTREAMS 0x0002
-#define NO_REPARSETAG 0x0004
-/* following flags can apply if pipe */
-#define ICOUNT_MASK 0x00FF
-#define PIPE_READ_MODE 0x0100
-#define NAMED_PIPE_TYPE 0x0400
-#define PIPE_END_POINT 0x4000
-#define BLOCKING_NAMED_PIPE 0x8000
-
-typedef struct smb_com_open_req { /* also handles create */
- struct smb_hdr hdr; /* wct = 24 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u8 Reserved; /* Must Be Zero */
- __le16 NameLength;
- __le32 OpenFlags;
- __u32 RootDirectoryFid;
- __le32 DesiredAccess;
- __le64 AllocationSize;
- __le32 FileAttributes;
- __le32 ShareAccess;
- __le32 CreateDisposition;
- __le32 CreateOptions;
- __le32 ImpersonationLevel;
- __u8 SecurityFlags;
- __le16 ByteCount;
- char fileName[1];
-} __attribute__((packed)) OPEN_REQ;
-
-/* open response: oplock levels */
-#define OPLOCK_NONE 0
-#define OPLOCK_EXCLUSIVE 1
-#define OPLOCK_BATCH 2
-#define OPLOCK_READ 3 /* level 2 oplock */
-
-/* open response for CreateAction shifted left */
-#define CIFS_CREATE_ACTION 0x20000 /* file created */
-
-typedef struct smb_com_open_rsp {
- struct smb_hdr hdr; /* wct = 34 BB */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u8 OplockLevel;
- __u16 Fid;
- __le32 CreateAction;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le32 FileAttributes;
- __le64 AllocationSize;
- __le64 EndOfFile;
- __le16 FileType;
- __le16 DeviceState;
- __u8 DirectoryFlag;
- __u16 ByteCount; /* bct = 0 */
-} __attribute__((packed)) OPEN_RSP;
-
-typedef struct smb_com_open_rsp_ext {
- struct smb_hdr hdr; /* wct = 42 but meaningless due to MS bug? */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u8 OplockLevel;
- __u16 Fid;
- __le32 CreateAction;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le32 FileAttributes;
- __le64 AllocationSize;
- __le64 EndOfFile;
- __le16 FileType;
- __le16 DeviceState;
- __u8 DirectoryFlag;
- __u8 VolumeGUID[16];
- __u64 FileId; /* note no endian conversion - is opaque UniqueID */
- __le32 MaximalAccessRights;
- __le32 GuestMaximalAccessRights;
- __u16 ByteCount; /* bct = 0 */
-} __attribute__((packed)) OPEN_RSP_EXT;
-
-
-/* format of legacy open request */
-typedef struct smb_com_openx_req {
- struct smb_hdr hdr; /* wct = 15 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 OpenFlags;
- __le16 Mode;
- __le16 Sattr; /* search attributes */
- __le16 FileAttributes; /* dos attrs */
- __le32 CreateTime; /* os2 format */
- __le16 OpenFunction;
- __le32 EndOfFile;
- __le32 Timeout;
- __le32 Reserved;
- __le16 ByteCount; /* file name follows */
- char fileName[1];
-} __attribute__((packed)) OPENX_REQ;
-
-typedef struct smb_com_openx_rsp {
- struct smb_hdr hdr; /* wct = 15 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u16 Fid;
- __le16 FileAttributes;
- __le32 LastWriteTime; /* os2 format */
- __le32 EndOfFile;
- __le16 Access;
- __le16 FileType;
- __le16 IPCState;
- __le16 Action;
- __u32 FileId;
- __u16 Reserved;
- __u16 ByteCount;
-} __attribute__((packed)) OPENX_RSP;
-
-/* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */
-
-/* Legacy write request for older servers */
-typedef struct smb_com_writex_req {
- struct smb_hdr hdr; /* wct = 12 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u16 Fid;
- __le32 OffsetLow;
- __u32 Reserved; /* Timeout */
- __le16 WriteMode; /* 1 = write through */
- __le16 Remaining;
- __le16 Reserved2;
- __le16 DataLengthLow;
- __le16 DataOffset;
- __le16 ByteCount;
- __u8 Pad; /* BB check for whether padded to DWORD
- boundary and optimum performance here */
- char Data[];
-} __attribute__((packed)) WRITEX_REQ;
-
-typedef struct smb_com_write_req {
- struct smb_hdr hdr; /* wct = 14 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u16 Fid;
- __le32 OffsetLow;
- __u32 Reserved;
- __le16 WriteMode;
- __le16 Remaining;
- __le16 DataLengthHigh;
- __le16 DataLengthLow;
- __le16 DataOffset;
- __le32 OffsetHigh;
- __le16 ByteCount;
- __u8 Pad; /* BB check for whether padded to DWORD
- boundary and optimum performance here */
- char Data[];
-} __attribute__((packed)) WRITE_REQ;
-
-typedef struct smb_com_write_rsp {
- struct smb_hdr hdr; /* wct = 6 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 Count;
- __le16 Remaining;
- __le16 CountHigh;
- __u16 Reserved;
- __u16 ByteCount;
-} __attribute__((packed)) WRITE_RSP;
-
-/* legacy read request for older servers */
-typedef struct smb_com_readx_req {
- struct smb_hdr hdr; /* wct = 10 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u16 Fid;
- __le32 OffsetLow;
- __le16 MaxCount;
- __le16 MinCount; /* obsolete */
- __le32 Reserved;
- __le16 Remaining;
- __le16 ByteCount;
-} __attribute__((packed)) READX_REQ;
-
-typedef struct smb_com_read_req {
- struct smb_hdr hdr; /* wct = 12 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u16 Fid;
- __le32 OffsetLow;
- __le16 MaxCount;
- __le16 MinCount; /* obsolete */
- __le32 MaxCountHigh;
- __le16 Remaining;
- __le32 OffsetHigh;
- __le16 ByteCount;
-} __attribute__((packed)) READ_REQ;
-
-typedef struct smb_com_read_rsp {
- struct smb_hdr hdr; /* wct = 12 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __le16 Remaining;
- __le16 DataCompactionMode;
- __le16 Reserved;
- __le16 DataLength;
- __le16 DataOffset;
- __le16 DataLengthHigh;
- __u64 Reserved2;
- __u16 ByteCount;
- /* read response data immediately follows */
-} __attribute__((packed)) READ_RSP;
-
-typedef struct locking_andx_range {
- __le16 Pid;
- __le16 Pad;
- __le32 OffsetHigh;
- __le32 OffsetLow;
- __le32 LengthHigh;
- __le32 LengthLow;
-} __attribute__((packed)) LOCKING_ANDX_RANGE;
-
-#define LOCKING_ANDX_SHARED_LOCK 0x01
-#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
-#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
-#define LOCKING_ANDX_CANCEL_LOCK 0x08
-#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */
-
-typedef struct smb_com_lock_req {
- struct smb_hdr hdr; /* wct = 8 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u16 Fid;
- __u8 LockType;
- __u8 OplockLevel;
- __le32 Timeout;
- __le16 NumberOfUnlocks;
- __le16 NumberOfLocks;
- __le16 ByteCount;
- LOCKING_ANDX_RANGE Locks[1];
-} __attribute__((packed)) LOCK_REQ;
-
-/* lock type */
-#define CIFS_RDLCK 0
-#define CIFS_WRLCK 1
-#define CIFS_UNLCK 2
-typedef struct cifs_posix_lock {
- __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
- __le16 lock_flags; /* 1 = Wait (only valid for setlock) */
- __le32 pid;
- __le64 start;
- __le64 length;
- /* BB what about additional owner info to identify network client */
-} __attribute__((packed)) CIFS_POSIX_LOCK;
-
-typedef struct smb_com_lock_rsp {
- struct smb_hdr hdr; /* wct = 2 */
- __u8 AndXCommand;
- __u8 AndXReserved;
- __le16 AndXOffset;
- __u16 ByteCount;
-} __attribute__((packed)) LOCK_RSP;
-
-typedef struct smb_com_rename_req {
- struct smb_hdr hdr; /* wct = 1 */
- __le16 SearchAttributes; /* target file attributes */
- __le16 ByteCount;
- __u8 BufferFormat; /* 4 = ASCII or Unicode */
- unsigned char OldFileName[1];
- /* followed by __u8 BufferFormat2 */
- /* followed by NewFileName */
-} __attribute__((packed)) RENAME_REQ;
-
- /* copy request flags */
-#define COPY_MUST_BE_FILE 0x0001
-#define COPY_MUST_BE_DIR 0x0002
-#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
-#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
-#define COPY_VERIFY_WRITES 0x0010
-#define COPY_TREE 0x0020
-
-typedef struct smb_com_copy_req {
- struct smb_hdr hdr; /* wct = 3 */
- __u16 Tid2;
- __le16 OpenFunction;
- __le16 Flags;
- __le16 ByteCount;
- __u8 BufferFormat; /* 4 = ASCII or Unicode */
- unsigned char OldFileName[1];
- /* followed by __u8 BufferFormat2 */
- /* followed by NewFileName string */
-} __attribute__((packed)) COPY_REQ;
-
-typedef struct smb_com_copy_rsp {
- struct smb_hdr hdr; /* wct = 1 */
- __le16 CopyCount; /* number of files copied */
- __u16 ByteCount; /* may be zero */
- __u8 BufferFormat; /* 0x04 - only present if errored file follows */
- unsigned char ErrorFileName[1]; /* only present if error in copy */
-} __attribute__((packed)) COPY_RSP;
-
-#define CREATE_HARD_LINK 0x103
-#define MOVEFILE_COPY_ALLOWED 0x0002
-#define MOVEFILE_REPLACE_EXISTING 0x0001
-
-typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
- struct smb_hdr hdr; /* wct = 4 */
- __le16 SearchAttributes; /* target file attributes */
- __le16 Flags; /* spec says Information Level */
- __le32 ClusterCount;
- __le16 ByteCount;
- __u8 BufferFormat; /* 4 = ASCII or Unicode */
- unsigned char OldFileName[1];
- /* followed by __u8 BufferFormat2 */
- /* followed by NewFileName */
-} __attribute__((packed)) NT_RENAME_REQ;
-
-typedef struct smb_com_rename_rsp {
- struct smb_hdr hdr; /* wct = 0 */
- __u16 ByteCount; /* bct = 0 */
-} __attribute__((packed)) RENAME_RSP;
-
-typedef struct smb_com_delete_file_req {
- struct smb_hdr hdr; /* wct = 1 */
- __le16 SearchAttributes;
- __le16 ByteCount;
- __u8 BufferFormat; /* 4 = ASCII */
- unsigned char fileName[1];
-} __attribute__((packed)) DELETE_FILE_REQ;
-
-typedef struct smb_com_delete_file_rsp {
- struct smb_hdr hdr; /* wct = 0 */
- __u16 ByteCount; /* bct = 0 */
-} __attribute__((packed)) DELETE_FILE_RSP;
-
-typedef struct smb_com_delete_directory_req {
- struct smb_hdr hdr; /* wct = 0 */
- __le16 ByteCount;
- __u8 BufferFormat; /* 4 = ASCII */
- unsigned char DirName[1];
-} __attribute__((packed)) DELETE_DIRECTORY_REQ;
-
-typedef struct smb_com_delete_directory_rsp {
- struct smb_hdr hdr; /* wct = 0 */
- __u16 ByteCount; /* bct = 0 */
-} __attribute__((packed)) DELETE_DIRECTORY_RSP;
-
-typedef struct smb_com_create_directory_req {
- struct smb_hdr hdr; /* wct = 0 */
- __le16 ByteCount;
- __u8 BufferFormat; /* 4 = ASCII */
- unsigned char DirName[1];
-} __attribute__((packed)) CREATE_DIRECTORY_REQ;
-
-typedef struct smb_com_create_directory_rsp {
- struct smb_hdr hdr; /* wct = 0 */
- __u16 ByteCount; /* bct = 0 */
-} __attribute__((packed)) CREATE_DIRECTORY_RSP;
-
-typedef struct smb_com_query_information_req {
- struct smb_hdr hdr; /* wct = 0 */
- __le16 ByteCount; /* 1 + namelen + 1 */
- __u8 BufferFormat; /* 4 = ASCII */
- unsigned char FileName[1];
-} __attribute__((packed)) QUERY_INFORMATION_REQ;
-
-typedef struct smb_com_query_information_rsp {
- struct smb_hdr hdr; /* wct = 10 */
- __le16 attr;
- __le32 last_write_time;
- __le32 size;
- __u16 reserved[5];
- __le16 ByteCount; /* bcc = 0 */
-} __attribute__((packed)) QUERY_INFORMATION_RSP;
-
-typedef struct smb_com_setattr_req {
- struct smb_hdr hdr; /* wct = 8 */
- __le16 attr;
- __le16 time_low;
- __le16 time_high;
- __le16 reserved[5]; /* must be zero */
- __u16 ByteCount;
- __u8 BufferFormat; /* 4 = ASCII */
- unsigned char fileName[1];
-} __attribute__((packed)) SETATTR_REQ;
-
-typedef struct smb_com_setattr_rsp {
- struct smb_hdr hdr; /* wct = 0 */
- __u16 ByteCount; /* bct = 0 */
-} __attribute__((packed)) SETATTR_RSP;
-
-/* empty wct response to setattr */
-
-/*******************************************************/
-/* NT Transact structure definitions follow */
-/* Currently only ioctl, acl (get security descriptor) */
-/* and notify are implemented */
-/*******************************************************/
-typedef struct smb_com_ntransact_req {
- struct smb_hdr hdr; /* wct >= 19 */
- __u8 MaxSetupCount;
- __u16 Reserved;
- __le32 TotalParameterCount;
- __le32 TotalDataCount;
- __le32 MaxParameterCount;
- __le32 MaxDataCount;
- __le32 ParameterCount;
- __le32 ParameterOffset;
- __le32 DataCount;
- __le32 DataOffset;
- __u8 SetupCount; /* four setup words follow subcommand */
- /* SNIA spec incorrectly included spurious pad here */
- __le16 SubCommand; /* 2 = IOCTL/FSCTL */
- /* SetupCount words follow then */
- __le16 ByteCount;
- __u8 Pad[3];
- __u8 Parms[];
-} __attribute__((packed)) NTRANSACT_REQ;
-
-typedef struct smb_com_ntransact_rsp {
- struct smb_hdr hdr; /* wct = 18 */
- __u8 Reserved[3];
- __le32 TotalParameterCount;
- __le32 TotalDataCount;
- __le32 ParameterCount;
- __le32 ParameterOffset;
- __le32 ParameterDisplacement;
- __le32 DataCount;
- __le32 DataOffset;
- __le32 DataDisplacement;
- __u8 SetupCount; /* 0 */
- __u16 ByteCount;
- /* __u8 Pad[3]; */
- /* parms and data follow */
-} __attribute__((packed)) NTRANSACT_RSP;
-
-/* See MS-SMB 2.2.7.2.1.1 */
-struct srv_copychunk {
- __le64 SourceOffset;
- __le64 DestinationOffset;
- __le32 CopyLength;
- __u32 Reserved;
-} __packed;
-
-typedef struct smb_com_transaction_ioctl_req {
- struct smb_hdr hdr; /* wct = 23 */
- __u8 MaxSetupCount;
- __u16 Reserved;
- __le32 TotalParameterCount;
- __le32 TotalDataCount;
- __le32 MaxParameterCount;
- __le32 MaxDataCount;
- __le32 ParameterCount;
- __le32 ParameterOffset;
- __le32 DataCount;
- __le32 DataOffset;
- __u8 SetupCount; /* four setup words follow subcommand */
- /* SNIA spec incorrectly included spurious pad here */
- __le16 SubCommand; /* 2 = IOCTL/FSCTL */
- __le32 FunctionCode;
- __u16 Fid;
- __u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */
- __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
- __le16 ByteCount;
- __u8 Pad[3];
- __u8 Data[1];
-} __attribute__((packed)) TRANSACT_IOCTL_REQ;
-
-typedef struct smb_com_transaction_compr_ioctl_req {
- struct smb_hdr hdr; /* wct = 23 */
- __u8 MaxSetupCount;
- __u16 Reserved;
- __le32 TotalParameterCount;
- __le32 TotalDataCount;
- __le32 MaxParameterCount;
- __le32 MaxDataCount;
- __le32 ParameterCount;
- __le32 ParameterOffset;
- __le32 DataCount;
- __le32 DataOffset;
- __u8 SetupCount; /* four setup words follow subcommand */
- /* SNIA spec incorrectly included spurious pad here */
- __le16 SubCommand; /* 2 = IOCTL/FSCTL */
- __le32 FunctionCode;
- __u16 Fid;
- __u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */
- __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
- __le16 ByteCount;
- __u8 Pad[3];
- __le16 compression_state; /* See below for valid flags */
-} __attribute__((packed)) TRANSACT_COMPR_IOCTL_REQ;
-
-/* compression state flags */
-#define COMPRESSION_FORMAT_NONE 0x0000
-#define COMPRESSION_FORMAT_DEFAULT 0x0001
-#define COMPRESSION_FORMAT_LZNT1 0x0002
-
-typedef struct smb_com_transaction_ioctl_rsp {
- struct smb_hdr hdr; /* wct = 19 */
- __u8 Reserved[3];
- __le32 TotalParameterCount;
- __le32 TotalDataCount;
- __le32 ParameterCount;
- __le32 ParameterOffset;
- __le32 ParameterDisplacement;
- __le32 DataCount;
- __le32 DataOffset;
- __le32 DataDisplacement;
- __u8 SetupCount; /* 1 */
- __le16 ReturnedDataLen;
- __u16 ByteCount;
-} __attribute__((packed)) TRANSACT_IOCTL_RSP;
-
-#define CIFS_ACL_OWNER 1
-#define CIFS_ACL_GROUP 2
-#define CIFS_ACL_DACL 4
-#define CIFS_ACL_SACL 8
-
-typedef struct smb_com_transaction_qsec_req {
- struct smb_hdr hdr; /* wct = 19 */
- __u8 MaxSetupCount;
- __u16 Reserved;
- __le32 TotalParameterCount;
- __le32 TotalDataCount;
- __le32 MaxParameterCount;
- __le32 MaxDataCount;
- __le32 ParameterCount;
- __le32 ParameterOffset;
- __le32 DataCount;
- __le32 DataOffset;
- __u8 SetupCount; /* no setup words follow subcommand */
- /* SNIA spec incorrectly included spurious pad here */
- __le16 SubCommand; /* 6 = QUERY_SECURITY_DESC */
- __le16 ByteCount; /* bcc = 3 + 8 */
- __u8 Pad[3];
- __u16 Fid;
- __u16 Reserved2;
- __le32 AclFlags;
-} __attribute__((packed)) QUERY_SEC_DESC_REQ;
-
-
-typedef struct smb_com_transaction_ssec_req {
- struct smb_hdr hdr; /* wct = 19 */
- __u8 MaxSetupCount;
- __u16 Reserved;
- __le32 TotalParameterCount;
- __le32 TotalDataCount;
- __le32 MaxParameterCount;
- __le32 MaxDataCount;
- __le32 ParameterCount;
- __le32 ParameterOffset;
- __le32 DataCount;
- __le32 DataOffset;
- __u8 SetupCount; /* no setup words follow subcommand */
- /* SNIA spec incorrectly included spurious pad here */
- __le16 SubCommand; /* 3 = SET_SECURITY_DESC */
- __le16 ByteCount; /* bcc = 3 + 8 */
- __u8 Pad[3];
- __u16 Fid;
- __u16 Reserved2;
- __le32 AclFlags;
-} __attribute__((packed)) SET_SEC_DESC_REQ;
-
-typedef struct smb_com_transaction_change_notify_req {
- struct smb_hdr hdr; /* wct = 23 */
- __u8 MaxSetupCount;
- __u16 Reserved;
- __le32 TotalParameterCount;
- __le32 TotalDataCount;
- __le32 MaxParameterCount;
- __le32 MaxDataCount;
- __le32 ParameterCount;
- __le32 ParameterOffset;
- __le32 DataCount;
- __le32 DataOffset;
- __u8 SetupCount; /* four setup words follow subcommand */
- /* SNIA spec incorrectly included spurious pad here */
- __le16 SubCommand;/* 4 = Change Notify */
- __le32 CompletionFilter; /* operation to monitor */
- __u16 Fid;
- __u8 WatchTree; /* 1 = Monitor subdirectories */
- __u8 Reserved2;
- __le16 ByteCount;
-/* __u8 Pad[3];*/
-/* __u8 Data[1];*/
-} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
-
-/* BB eventually change to use generic ntransact rsp struct
- and validation routine */
-typedef struct smb_com_transaction_change_notify_rsp {
- struct smb_hdr hdr; /* wct = 18 */
- __u8 Reserved[3];
- __le32 TotalParameterCount;
- __le32 TotalDataCount;
- __le32 ParameterCount;
- __le32 ParameterOffset;
- __le32 ParameterDisplacement;
- __le32 DataCount;
- __le32 DataOffset;
- __le32 DataDisplacement;
- __u8 SetupCount; /* 0 */
- __u16 ByteCount;
- /* __u8 Pad[3]; */
-} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_RSP;
-/* Completion Filter flags for Notify */
-#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
-#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
-#define FILE_NOTIFY_CHANGE_NAME 0x00000003
-#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
-#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
-#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
-#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
-#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
-#define FILE_NOTIFY_CHANGE_EA 0x00000080
-#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
-#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
-#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
-#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
-
-#define FILE_ACTION_ADDED 0x00000001
-#define FILE_ACTION_REMOVED 0x00000002
-#define FILE_ACTION_MODIFIED 0x00000003
-#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
-#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
-#define FILE_ACTION_ADDED_STREAM 0x00000006
-#define FILE_ACTION_REMOVED_STREAM 0x00000007
-#define FILE_ACTION_MODIFIED_STREAM 0x00000008
-
-/* response contains array of the following structures */
-struct file_notify_information {
- __le32 NextEntryOffset;
- __le32 Action;
- __le32 FileNameLength;
- __u8 FileName[];
-} __attribute__((packed));
-
-/* For IO_REPARSE_TAG_SYMLINK */
-struct reparse_symlink_data {
- __le32 ReparseTag;
- __le16 ReparseDataLength;
- __u16 Reserved;
- __le16 SubstituteNameOffset;
- __le16 SubstituteNameLength;
- __le16 PrintNameOffset;
- __le16 PrintNameLength;
- __le32 Flags;
- char PathBuffer[];
-} __attribute__((packed));
-
-/* Flag above */
-#define SYMLINK_FLAG_RELATIVE 0x00000001
-
-/* For IO_REPARSE_TAG_NFS */
-#define NFS_SPECFILE_LNK 0x00000000014B4E4C
-#define NFS_SPECFILE_CHR 0x0000000000524843
-#define NFS_SPECFILE_BLK 0x00000000004B4C42
-#define NFS_SPECFILE_FIFO 0x000000004F464946
-#define NFS_SPECFILE_SOCK 0x000000004B434F53
-struct reparse_posix_data {
- __le32 ReparseTag;
- __le16 ReparseDataLength;
- __u16 Reserved;
- __le64 InodeType; /* LNK, FIFO, CHR etc. */
- char PathBuffer[];
-} __attribute__((packed));
-
-struct cifs_quota_data {
- __u32 rsrvd1; /* 0 */
- __u32 sid_size;
- __u64 rsrvd2; /* 0 */
- __u64 space_used;
- __u64 soft_limit;
- __u64 hard_limit;
- char sid[1]; /* variable size? */
-} __attribute__((packed));
-
-/* quota sub commands */
-#define QUOTA_LIST_CONTINUE 0
-#define QUOTA_LIST_START 0x100
-#define QUOTA_FOR_SID 0x101
-
-struct trans2_req {
- /* struct smb_hdr hdr precedes. Set wct = 14+ */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount;
- __le16 ParameterOffset;
- __le16 DataCount;
- __le16 DataOffset;
- __u8 SetupCount;
- __u8 Reserved3;
- __le16 SubCommand; /* 1st setup word - SetupCount words follow */
- __le16 ByteCount;
-} __attribute__((packed));
-
-struct smb_t2_req {
- struct smb_hdr hdr;
- struct trans2_req t2_req;
-} __attribute__((packed));
-
-struct trans2_resp {
- /* struct smb_hdr hdr precedes. Note wct = 10 + setup count */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __u16 Reserved;
- __le16 ParameterCount;
- __le16 ParameterOffset;
- __le16 ParameterDisplacement;
- __le16 DataCount;
- __le16 DataOffset;
- __le16 DataDisplacement;
- __u8 SetupCount;
- __u8 Reserved1;
- /* SetupWords[SetupCount];
- __u16 ByteCount;
- __u16 Reserved2;*/
- /* data area follows */
-} __attribute__((packed));
-
-struct smb_t2_rsp {
- struct smb_hdr hdr;
- struct trans2_resp t2_rsp;
-} __attribute__((packed));
-
-/* PathInfo/FileInfo infolevels */
-#define SMB_INFO_STANDARD 1
-#define SMB_SET_FILE_EA 2
-#define SMB_QUERY_FILE_EA_SIZE 2
-#define SMB_INFO_QUERY_EAS_FROM_LIST 3
-#define SMB_INFO_QUERY_ALL_EAS 4
-#define SMB_INFO_IS_NAME_VALID 6
-#define SMB_QUERY_FILE_BASIC_INFO 0x101
-#define SMB_QUERY_FILE_STANDARD_INFO 0x102
-#define SMB_QUERY_FILE_EA_INFO 0x103
-#define SMB_QUERY_FILE_NAME_INFO 0x104
-#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
-#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
-#define SMB_QUERY_FILE_ALL_INFO 0x107
-#define SMB_QUERY_ALT_NAME_INFO 0x108
-#define SMB_QUERY_FILE_STREAM_INFO 0x109
-#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
-#define SMB_QUERY_FILE_UNIX_BASIC 0x200
-#define SMB_QUERY_FILE_UNIX_LINK 0x201
-#define SMB_QUERY_POSIX_ACL 0x204
-#define SMB_QUERY_XATTR 0x205 /* e.g. system EA name space */
-#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
-#define SMB_QUERY_POSIX_PERMISSION 0x207
-#define SMB_QUERY_POSIX_LOCK 0x208
-/* #define SMB_POSIX_OPEN 0x209 */
-/* #define SMB_POSIX_UNLINK 0x20a */
-#define SMB_QUERY_FILE__UNIX_INFO2 0x20b
-#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
-#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
-#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
-#define SMB_QUERY_FILE_POSITION_INFO 0x3f6
-#define SMB_QUERY_FILE_MODE_INFO 0x3f8
-#define SMB_QUERY_FILE_ALGN_INFO 0x3f9
-
-
-#define SMB_SET_FILE_BASIC_INFO 0x101
-#define SMB_SET_FILE_DISPOSITION_INFO 0x102
-#define SMB_SET_FILE_ALLOCATION_INFO 0x103
-#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
-#define SMB_SET_FILE_UNIX_BASIC 0x200
-#define SMB_SET_FILE_UNIX_LINK 0x201
-#define SMB_SET_FILE_UNIX_HLINK 0x203
-#define SMB_SET_POSIX_ACL 0x204
-#define SMB_SET_XATTR 0x205
-#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
-#define SMB_SET_POSIX_LOCK 0x208
-#define SMB_POSIX_OPEN 0x209
-#define SMB_POSIX_UNLINK 0x20a
-#define SMB_SET_FILE_UNIX_INFO2 0x20b
-#define SMB_SET_FILE_BASIC_INFO2 0x3ec
-#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */
-#define SMB_FILE_ALL_INFO2 0x3fa
-#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
-#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
-#define SMB_FILE_MOVE_CLUSTER_INFO 0x407
-#define SMB_FILE_QUOTA_INFO 0x408
-#define SMB_FILE_REPARSEPOINT_INFO 0x409
-#define SMB_FILE_MAXIMUM_INFO 0x40d
-
-/* Find File infolevels */
-#define SMB_FIND_FILE_INFO_STANDARD 0x001
-#define SMB_FIND_FILE_QUERY_EA_SIZE 0x002
-#define SMB_FIND_FILE_QUERY_EAS_FROM_LIST 0x003
-#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
-#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
-#define SMB_FIND_FILE_NAMES_INFO 0x103
-#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
-#define SMB_FIND_FILE_ID_FULL_DIR_INFO 0x105
-#define SMB_FIND_FILE_ID_BOTH_DIR_INFO 0x106
-#define SMB_FIND_FILE_UNIX 0x202
-/* #define SMB_FIND_FILE_POSIX_INFO 0x064 */
-
-typedef struct smb_com_transaction2_qpi_req {
- struct smb_hdr hdr; /* wct = 14+ */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount;
- __le16 ParameterOffset;
- __le16 DataCount;
- __le16 DataOffset;
- __u8 SetupCount;
- __u8 Reserved3;
- __le16 SubCommand; /* one setup word */
- __le16 ByteCount;
- __u8 Pad;
- __le16 InformationLevel;
- __u32 Reserved4;
- char FileName[1];
-} __attribute__((packed)) TRANSACTION2_QPI_REQ;
-
-typedef struct smb_com_transaction2_qpi_rsp {
- struct smb_hdr hdr; /* wct = 10 + SetupCount */
- struct trans2_resp t2;
- __u16 ByteCount;
- __u16 Reserved2; /* parameter word is present for infolevels > 100 */
-} __attribute__((packed)) TRANSACTION2_QPI_RSP;
-
-typedef struct smb_com_transaction2_spi_req {
- struct smb_hdr hdr; /* wct = 15 */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount;
- __le16 ParameterOffset;
- __le16 DataCount;
- __le16 DataOffset;
- __u8 SetupCount;
- __u8 Reserved3;
- __le16 SubCommand; /* one setup word */
- __le16 ByteCount;
- __u8 Pad;
- __u16 Pad1;
- __le16 InformationLevel;
- __u32 Reserved4;
- char FileName[1];
-} __attribute__((packed)) TRANSACTION2_SPI_REQ;
-
-typedef struct smb_com_transaction2_spi_rsp {
- struct smb_hdr hdr; /* wct = 10 + SetupCount */
- struct trans2_resp t2;
- __u16 ByteCount;
- __u16 Reserved2; /* parameter word is present for infolevels > 100 */
-} __attribute__((packed)) TRANSACTION2_SPI_RSP;
-
-struct set_file_rename {
- __le32 overwrite; /* 1 = overwrite dest */
- __u32 root_fid; /* zero */
- __le32 target_name_len;
- char target_name[]; /* Must be unicode */
-} __attribute__((packed));
-
-struct smb_com_transaction2_sfi_req {
- struct smb_hdr hdr; /* wct = 15 */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount;
- __le16 ParameterOffset;
- __le16 DataCount;
- __le16 DataOffset;
- __u8 SetupCount;
- __u8 Reserved3;
- __le16 SubCommand; /* one setup word */
- __le16 ByteCount;
- __u8 Pad;
- __u16 Pad1;
- __u16 Fid;
- __le16 InformationLevel;
- __u16 Reserved4;
- __u8 payload[];
-} __attribute__((packed));
-
-struct smb_com_transaction2_sfi_rsp {
- struct smb_hdr hdr; /* wct = 10 + SetupCount */
- struct trans2_resp t2;
- __u16 ByteCount;
- __u16 Reserved2; /* parameter word reserved -
- present for infolevels > 100 */
-} __attribute__((packed));
-
-struct smb_t2_qfi_req {
- struct smb_hdr hdr;
- struct trans2_req t2;
- __u8 Pad;
- __u16 Fid;
- __le16 InformationLevel;
-} __attribute__((packed));
-
-struct smb_t2_qfi_rsp {
- struct smb_hdr hdr; /* wct = 10 + SetupCount */
- struct trans2_resp t2;
- __u16 ByteCount;
- __u16 Reserved2; /* parameter word reserved -
- present for infolevels > 100 */
-} __attribute__((packed));
-
-/*
- * Flags on T2 FINDFIRST and FINDNEXT
- */
-#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
-#define CIFS_SEARCH_CLOSE_AT_END 0x0002
-#define CIFS_SEARCH_RETURN_RESUME 0x0004
-#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
-#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
-
-/*
- * Size of the resume key on FINDFIRST and FINDNEXT calls
- */
-#define CIFS_SMB_RESUME_KEY_SIZE 4
-
-typedef struct smb_com_transaction2_ffirst_req {
- struct smb_hdr hdr; /* wct = 15 */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount;
- __le16 ParameterOffset;
- __le16 DataCount;
- __le16 DataOffset;
- __u8 SetupCount; /* one */
- __u8 Reserved3;
- __le16 SubCommand; /* TRANS2_FIND_FIRST */
- __le16 ByteCount;
- __u8 Pad;
- __le16 SearchAttributes;
- __le16 SearchCount;
- __le16 SearchFlags;
- __le16 InformationLevel;
- __le32 SearchStorageType;
- char FileName[1];
-} __attribute__((packed)) TRANSACTION2_FFIRST_REQ;
-
-typedef struct smb_com_transaction2_ffirst_rsp {
- struct smb_hdr hdr; /* wct = 10 */
- struct trans2_resp t2;
- __u16 ByteCount;
-} __attribute__((packed)) TRANSACTION2_FFIRST_RSP;
-
-typedef struct smb_com_transaction2_ffirst_rsp_parms {
- __u16 SearchHandle;
- __le16 SearchCount;
- __le16 EndofSearch;
- __le16 EAErrorOffset;
- __le16 LastNameOffset;
-} __attribute__((packed)) T2_FFIRST_RSP_PARMS;
-
-typedef struct smb_com_transaction2_fnext_req {
- struct smb_hdr hdr; /* wct = 15 */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount;
- __le16 ParameterOffset;
- __le16 DataCount;
- __le16 DataOffset;
- __u8 SetupCount; /* one */
- __u8 Reserved3;
- __le16 SubCommand; /* TRANS2_FIND_NEXT */
- __le16 ByteCount;
- __u8 Pad;
- __u16 SearchHandle;
- __le16 SearchCount;
- __le16 InformationLevel;
- __u32 ResumeKey;
- __le16 SearchFlags;
- char ResumeFileName[];
-} __attribute__((packed)) TRANSACTION2_FNEXT_REQ;
-
-typedef struct smb_com_transaction2_fnext_rsp {
- struct smb_hdr hdr; /* wct = 10 */
- struct trans2_resp t2;
- __u16 ByteCount;
-} __attribute__((packed)) TRANSACTION2_FNEXT_RSP;
-
-typedef struct smb_com_transaction2_fnext_rsp_parms {
- __le16 SearchCount;
- __le16 EndofSearch;
- __le16 EAErrorOffset;
- __le16 LastNameOffset;
-} __attribute__((packed)) T2_FNEXT_RSP_PARMS;
-
-/* QFSInfo Levels */
-#define SMB_INFO_ALLOCATION 1
-#define SMB_INFO_VOLUME 2
-#define SMB_QUERY_FS_VOLUME_INFO 0x102
-#define SMB_QUERY_FS_SIZE_INFO 0x103
-#define SMB_QUERY_FS_DEVICE_INFO 0x104
-#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
-#define SMB_QUERY_CIFS_UNIX_INFO 0x200
-#define SMB_QUERY_POSIX_FS_INFO 0x201
-#define SMB_QUERY_POSIX_WHO_AM_I 0x202
-#define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203
-#define SMB_QUERY_FS_PROXY 0x204 /* WAFS enabled. Returns structure
- FILE_SYSTEM__UNIX_INFO to tell
- whether new NTIOCTL available
- (0xACE) for WAN friendly SMB
- operations to be carried */
-#define SMB_QUERY_LABEL_INFO 0x3ea
-#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
-#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
-#define SMB_QUERY_OBJECTID_INFO 0x3f0
-
-typedef struct smb_com_transaction2_qfsi_req {
- struct smb_hdr hdr; /* wct = 14+ */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount;
- __le16 ParameterOffset;
- __le16 DataCount;
- __le16 DataOffset;
- __u8 SetupCount;
- __u8 Reserved3;
- __le16 SubCommand; /* one setup word */
- __le16 ByteCount;
- __u8 Pad;
- __le16 InformationLevel;
-} __attribute__((packed)) TRANSACTION2_QFSI_REQ;
-
-typedef struct smb_com_transaction_qfsi_rsp {
- struct smb_hdr hdr; /* wct = 10 + SetupCount */
- struct trans2_resp t2;
- __u16 ByteCount;
- __u8 Pad; /* may be three bytes? *//* followed by data area */
-} __attribute__((packed)) TRANSACTION2_QFSI_RSP;
-
-typedef struct whoami_rsp_data { /* Query level 0x202 */
- __u32 flags; /* 0 = Authenticated user 1 = GUEST */
- __u32 mask; /* which flags bits server understands ie 0x0001 */
- __u64 unix_user_id;
- __u64 unix_user_gid;
- __u32 number_of_supplementary_gids; /* may be zero */
- __u32 number_of_sids; /* may be zero */
- __u32 length_of_sid_array; /* in bytes - may be zero */
- __u32 pad; /* reserved - MBZ */
- /* __u64 gid_array[0]; */ /* may be empty */
- /* __u8 * psid_list */ /* may be empty */
-} __attribute__((packed)) WHOAMI_RSP_DATA;
-
-/* SETFSInfo Levels */
-#define SMB_SET_CIFS_UNIX_INFO 0x200
-/* level 0x203 is defined above in list of QFS info levels */
-/* #define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203 */
-
-/* Level 0x200 request structure follows */
-typedef struct smb_com_transaction2_setfsi_req {
- struct smb_hdr hdr; /* wct = 15 */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount; /* 4 */
- __le16 ParameterOffset;
- __le16 DataCount; /* 12 */
- __le16 DataOffset;
- __u8 SetupCount; /* one */
- __u8 Reserved3;
- __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
- __le16 ByteCount;
- __u8 Pad;
- __u16 FileNum; /* Parameters start. */
- __le16 InformationLevel;/* Parameters end. */
- __le16 ClientUnixMajor; /* Data start. */
- __le16 ClientUnixMinor;
- __le64 ClientUnixCap; /* Data end */
-} __attribute__((packed)) TRANSACTION2_SETFSI_REQ;
-
-/* level 0x203 request structure follows */
-typedef struct smb_com_transaction2_setfs_enc_req {
- struct smb_hdr hdr; /* wct = 15 */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount; /* 4 */
- __le16 ParameterOffset;
- __le16 DataCount; /* 12 */
- __le16 DataOffset;
- __u8 SetupCount; /* one */
- __u8 Reserved3;
- __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
- __le16 ByteCount;
- __u8 Pad;
- __u16 Reserved4; /* Parameters start. */
- __le16 InformationLevel;/* Parameters end. */
- /* NTLMSSP Blob, Data start. */
-} __attribute__((packed)) TRANSACTION2_SETFSI_ENC_REQ;
-
-/* response for setfsinfo levels 0x200 and 0x203 */
-typedef struct smb_com_transaction2_setfsi_rsp {
- struct smb_hdr hdr; /* wct = 10 */
- struct trans2_resp t2;
- __u16 ByteCount;
-} __attribute__((packed)) TRANSACTION2_SETFSI_RSP;
-
-typedef struct smb_com_transaction2_get_dfs_refer_req {
- struct smb_hdr hdr; /* wct = 15 */
- __le16 TotalParameterCount;
- __le16 TotalDataCount;
- __le16 MaxParameterCount;
- __le16 MaxDataCount;
- __u8 MaxSetupCount;
- __u8 Reserved;
- __le16 Flags;
- __le32 Timeout;
- __u16 Reserved2;
- __le16 ParameterCount;
- __le16 ParameterOffset;
- __le16 DataCount;
- __le16 DataOffset;
- __u8 SetupCount;
- __u8 Reserved3;
- __le16 SubCommand; /* one setup word */
- __le16 ByteCount;
- __u8 Pad[3]; /* Win2K has sent 0x0F01 (max response length
- perhaps?) followed by one byte pad - doesn't
- seem to matter though */
- __le16 MaxReferralLevel;
- char RequestFileName[1];
-} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
-
-#define DFS_VERSION cpu_to_le16(0x0003)
-
-/* DFS server target type */
-#define DFS_TYPE_LINK 0x0000 /* also for sysvol targets */
-#define DFS_TYPE_ROOT 0x0001
-
-/* Referral Entry Flags */
-#define DFS_NAME_LIST_REF 0x0200 /* set for domain or DC referral responses */
-#define DFS_TARGET_SET_BOUNDARY 0x0400 /* only valid with version 4 dfs req */
-
-typedef struct dfs_referral_level_3 { /* version 4 is same, + one flag bit */
- __le16 VersionNumber; /* must be 3 or 4 */
- __le16 Size;
- __le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */
- __le16 ReferralEntryFlags;
- __le32 TimeToLive;
- __le16 DfsPathOffset;
- __le16 DfsAlternatePathOffset;
- __le16 NetworkAddressOffset; /* offset of the link target */
- __u8 ServiceSiteGuid[16]; /* MBZ, ignored */
-} __attribute__((packed)) REFERRAL3;
-
-struct get_dfs_referral_rsp {
- __le16 PathConsumed;
- __le16 NumberOfReferrals;
- __le32 DFSFlags;
- REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
- /* followed by the strings pointed to by the referral structures */
-} __packed;
-
-typedef struct smb_com_transaction_get_dfs_refer_rsp {
- struct smb_hdr hdr; /* wct = 10 */
- struct trans2_resp t2;
- __u16 ByteCount;
- __u8 Pad;
- struct get_dfs_referral_rsp dfs_data;
-} __packed TRANSACTION2_GET_DFS_REFER_RSP;
-
-/* DFS Flags */
-#define DFSREF_REFERRAL_SERVER 0x00000001 /* all targets are DFS roots */
-#define DFSREF_STORAGE_SERVER 0x00000002 /* no further ref requests needed */
-#define DFSREF_TARGET_FAILBACK 0x00000004 /* only for DFS referral version 4 */
-
-/*
- ************************************************************************
- * All structs for everything above the SMB PDUs themselves
- * (such as the T2 level specific data) go here
- ************************************************************************
- */
-
-/*
- * Information on a server
- */
-
-struct serverInfo {
- char name[16];
- unsigned char versionMajor;
- unsigned char versionMinor;
- unsigned long type;
- unsigned int commentOffset;
-} __attribute__((packed));
-
-/*
- * The following structure is the format of the data returned on a NetShareEnum
- * with level "90" (x5A)
- */
-
-struct shareInfo {
- char shareName[13];
- char pad;
- unsigned short type;
- unsigned int commentOffset;
-} __attribute__((packed));
-
-struct aliasInfo {
- char aliasName[9];
- char pad;
- unsigned int commentOffset;
- unsigned char type[2];
-} __attribute__((packed));
-
-struct aliasInfo92 {
- int aliasNameOffset;
- int serverNameOffset;
- int shareNameOffset;
-} __attribute__((packed));
-
-typedef struct {
- __le64 TotalAllocationUnits;
- __le64 FreeAllocationUnits;
- __le32 SectorsPerAllocationUnit;
- __le32 BytesPerSector;
-} __attribute__((packed)) FILE_SYSTEM_INFO; /* size info, level 0x103 */
-
-typedef struct {
- __le32 fsid;
- __le32 SectorsPerAllocationUnit;
- __le32 TotalAllocationUnits;
- __le32 FreeAllocationUnits;
- __le16 BytesPerSector;
-} __attribute__((packed)) FILE_SYSTEM_ALLOC_INFO;
-
-typedef struct {
- __le16 MajorVersionNumber;
- __le16 MinorVersionNumber;
- __le64 Capability;
-} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extension level 0x200*/
-
-/* Version numbers for CIFS UNIX major and minor. */
-#define CIFS_UNIX_MAJOR_VERSION 1
-#define CIFS_UNIX_MINOR_VERSION 0
-
-/* Linux/Unix extensions capability flags */
-#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
-#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
-#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
-#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
-#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */
-#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
- calls including posix open
- and posix unlink */
-#define CIFS_UNIX_LARGE_READ_CAP 0x00000040 /* support reads >128K (up
- to 0xFFFF00 */
-#define CIFS_UNIX_LARGE_WRITE_CAP 0x00000080
-#define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x00000100 /* can do SPNEGO crypt */
-#define CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP 0x00000200 /* must do */
-#define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and
- QFS PROXY call */
-#ifdef CONFIG_CIFS_POSIX
-/* presumably don't need the 0x20 POSIX_PATH_OPS_CAP since we never send
- LockingX instead of posix locking call on unix sess (and we do not expect
- LockingX to use different (ie Windows) semantics than posix locking on
- the same session (if WINE needs to do this later, we can add this cap
- back in later */
-/* #define CIFS_UNIX_CAP_MASK 0x000000fb */
-#define CIFS_UNIX_CAP_MASK 0x000003db
-#else
-#define CIFS_UNIX_CAP_MASK 0x00000013
-#endif /* CONFIG_CIFS_POSIX */
-
-
-#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
-
-typedef struct {
- /* For undefined recommended transfer size return -1 in that field */
- __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
- __le32 BlockSize;
- /* The next three fields are in terms of the block size.
- (above). If block size is unknown, 4096 would be a
- reasonable block size for a server to report.
- Note that returning the blocks/blocksavail removes need
- to make a second call (to QFSInfo level 0x103 to get this info.
- UserBlockAvail is typically less than or equal to BlocksAvail,
- if no distinction is made return the same value in each */
- __le64 TotalBlocks;
- __le64 BlocksAvail; /* bfree */
- __le64 UserBlocksAvail; /* bavail */
- /* For undefined Node fields or FSID return -1 */
- __le64 TotalFileNodes;
- __le64 FreeFileNodes;
- __le64 FileSysIdentifier; /* fsid */
- /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
- /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
-} __attribute__((packed)) FILE_SYSTEM_POSIX_INFO;
-
-/* DeviceType Flags */
-#define FILE_DEVICE_CD_ROM 0x00000002
-#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
-#define FILE_DEVICE_DFS 0x00000006
-#define FILE_DEVICE_DISK 0x00000007
-#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
-#define FILE_DEVICE_FILE_SYSTEM 0x00000009
-#define FILE_DEVICE_NAMED_PIPE 0x00000011
-#define FILE_DEVICE_NETWORK 0x00000012
-#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
-#define FILE_DEVICE_NULL 0x00000015
-#define FILE_DEVICE_PARALLEL_PORT 0x00000016
-#define FILE_DEVICE_PRINTER 0x00000018
-#define FILE_DEVICE_SERIAL_PORT 0x0000001b
-#define FILE_DEVICE_STREAMS 0x0000001e
-#define FILE_DEVICE_TAPE 0x0000001f
-#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
-#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
-#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
-
-/* Device Characteristics */
-#define FILE_REMOVABLE_MEDIA 0x00000001
-#define FILE_READ_ONLY_DEVICE 0x00000002
-#define FILE_FLOPPY_DISKETTE 0x00000004
-#define FILE_WRITE_ONCE_MEDIA 0x00000008
-#define FILE_REMOTE_DEVICE 0x00000010
-#define FILE_DEVICE_IS_MOUNTED 0x00000020
-#define FILE_VIRTUAL_VOLUME 0x00000040
-#define FILE_DEVICE_SECURE_OPEN 0x00000100
-#define FILE_CHARACTERISTIC_TS_DEVICE 0x00001000
-#define FILE_CHARACTERISTIC_WEBDAV_DEVICE 0x00002000
-#define FILE_PORTABLE_DEVICE 0x00004000
-#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000
-
-typedef struct {
- __le32 DeviceType;
- __le32 DeviceCharacteristics;
-} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */
-
-/* minimum includes first three fields, and empty FS Name */
-#define MIN_FS_ATTR_INFO_SIZE 12
-
-
-/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */
-#define FILE_SUPPORTS_SPARSE_VDL 0x10000000 /* faster nonsparse extend */
-#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000 /* allow ioctl dup extents */
-#define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000
-#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
-#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
-#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
-#define FILE_SUPPORTS_HARD_LINKS 0x00400000
-#define FILE_SUPPORTS_TRANSACTIONS 0x00200000
-#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
-#define FILE_READ_ONLY_VOLUME 0x00080000
-#define FILE_NAMED_STREAMS 0x00040000
-#define FILE_SUPPORTS_ENCRYPTION 0x00020000
-#define FILE_SUPPORTS_OBJECT_IDS 0x00010000
-#define FILE_VOLUME_IS_COMPRESSED 0x00008000
-#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100
-#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080
-#define FILE_SUPPORTS_SPARSE_FILES 0x00000040
-#define FILE_VOLUME_QUOTAS 0x00000020
-#define FILE_FILE_COMPRESSION 0x00000010
-#define FILE_PERSISTENT_ACLS 0x00000008
-#define FILE_UNICODE_ON_DISK 0x00000004
-#define FILE_CASE_PRESERVED_NAMES 0x00000002
-#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
-typedef struct {
- __le32 Attributes;
- __le32 MaxPathNameComponentLength;
- __le32 FileSystemNameLen;
- char FileSystemName[52]; /* do not have to save this - get subset? */
-} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO;
-
-/******************************************************************************/
-/* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */
-/******************************************************************************/
-typedef struct { /* data block encoding of response to level 263 QPathInfo */
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le32 Attributes;
- __u32 Pad1;
- __le64 AllocationSize;
- __le64 EndOfFile; /* size ie offset to first free byte in file */
- __le32 NumberOfLinks; /* hard links */
- __u8 DeletePending;
- __u8 Directory;
- __u16 Pad2;
- __le64 IndexNumber;
- __le32 EASize;
- __le32 AccessFlags;
- __u64 IndexNumber1;
- __le64 CurrentByteOffset;
- __le32 Mode;
- __le32 AlignmentRequirement;
- __le32 FileNameLength;
- char FileName[1];
-} __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */
-
-typedef struct {
- __le64 AllocationSize;
- __le64 EndOfFile; /* size ie offset to first free byte in file */
- __le32 NumberOfLinks; /* hard links */
- __u8 DeletePending;
- __u8 Directory;
- __u16 Pad;
-} __attribute__((packed)) FILE_STANDARD_INFO; /* level 0x102 QPathInfo */
-
-
-/* defines for enumerating possible values of the Unix type field below */
-#define UNIX_FILE 0
-#define UNIX_DIR 1
-#define UNIX_SYMLINK 2
-#define UNIX_CHARDEV 3
-#define UNIX_BLOCKDEV 4
-#define UNIX_FIFO 5
-#define UNIX_SOCKET 6
-typedef struct {
- __le64 EndOfFile;
- __le64 NumOfBytes;
- __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */
- __le64 LastAccessTime;
- __le64 LastModificationTime;
- __le64 Uid;
- __le64 Gid;
- __le32 Type;
- __le64 DevMajor;
- __le64 DevMinor;
- __le64 UniqueId;
- __le64 Permissions;
- __le64 Nlinks;
-} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
-
-typedef struct {
- char LinkDest[1];
-} __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
-
-/* The following three structures are needed only for
- setting time to NT4 and some older servers via
- the primitive DOS time format */
-typedef struct {
- __u16 Day:5;
- __u16 Month:4;
- __u16 Year:7;
-} __attribute__((packed)) SMB_DATE;
-
-typedef struct {
- __u16 TwoSeconds:5;
- __u16 Minutes:6;
- __u16 Hours:5;
-} __attribute__((packed)) SMB_TIME;
-
-typedef struct {
- __le16 CreationDate; /* SMB Date see above */
- __le16 CreationTime; /* SMB Time */
- __le16 LastAccessDate;
- __le16 LastAccessTime;
- __le16 LastWriteDate;
- __le16 LastWriteTime;
- __le32 DataSize; /* File Size (EOF) */
- __le32 AllocationSize;
- __le16 Attributes; /* verify not u32 */
- __le32 EASize;
-} __attribute__((packed)) FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */
-
-typedef struct {
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le32 Attributes;
- __u32 Pad;
-} __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */
-
-struct file_allocation_info {
- __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
-} __attribute__((packed)); /* size used on disk, for level 0x103 for set,
- 0x105 for query */
-
-struct file_end_of_file_info {
- __le64 FileSize; /* offset to end of file */
-} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */
-
-struct file_alt_name_info {
- __u8 alt_name[1];
-} __attribute__((packed)); /* level 0x0108 */
-
-struct file_stream_info {
- __le32 number_of_streams; /* BB check sizes and verify location */
- /* followed by info on streams themselves
- u64 size;
- u64 allocation_size
- stream info */
-}; /* level 0x109 */
-
-struct file_compression_info {
- __le64 compressed_size;
- __le16 format;
- __u8 unit_shift;
- __u8 ch_shift;
- __u8 cl_shift;
- __u8 pad[3];
-} __attribute__((packed)); /* level 0x10b */
-
-/* POSIX ACL set/query path info structures */
-#define CIFS_ACL_VERSION 1
-struct cifs_posix_ace { /* access control entry (ACE) */
- __u8 cifs_e_tag;
- __u8 cifs_e_perm;
- __le64 cifs_uid; /* or gid */
-} __attribute__((packed));
-
-struct cifs_posix_acl { /* access conrol list (ACL) */
- __le16 version;
- __le16 access_entry_count; /* access ACL - count of entries */
- __le16 default_entry_count; /* default ACL - count of entries */
- struct cifs_posix_ace ace_array[];
- /* followed by
- struct cifs_posix_ace default_ace_arraay[] */
-} __attribute__((packed)); /* level 0x204 */
-
-/* types of access control entries already defined in posix_acl.h */
-/* #define CIFS_POSIX_ACL_USER_OBJ 0x01
-#define CIFS_POSIX_ACL_USER 0x02
-#define CIFS_POSIX_ACL_GROUP_OBJ 0x04
-#define CIFS_POSIX_ACL_GROUP 0x08
-#define CIFS_POSIX_ACL_MASK 0x10
-#define CIFS_POSIX_ACL_OTHER 0x20 */
-
-/* types of perms */
-/* #define CIFS_POSIX_ACL_EXECUTE 0x01
-#define CIFS_POSIX_ACL_WRITE 0x02
-#define CIFS_POSIX_ACL_READ 0x04 */
-
-/* end of POSIX ACL definitions */
-
-/* POSIX Open Flags */
-#define SMB_O_RDONLY 0x1
-#define SMB_O_WRONLY 0x2
-#define SMB_O_RDWR 0x4
-#define SMB_O_CREAT 0x10
-#define SMB_O_EXCL 0x20
-#define SMB_O_TRUNC 0x40
-#define SMB_O_APPEND 0x80
-#define SMB_O_SYNC 0x100
-#define SMB_O_DIRECTORY 0x200
-#define SMB_O_NOFOLLOW 0x400
-#define SMB_O_DIRECT 0x800
-
-typedef struct {
- __le32 OpenFlags; /* same as NT CreateX */
- __le32 PosixOpenFlags;
- __le64 Permissions;
- __le16 Level; /* reply level requested (see QPathInfo levels) */
-} __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */
-
-typedef struct {
- __le16 OplockFlags;
- __u16 Fid;
- __le32 CreateAction;
- __le16 ReturnedLevel;
- __le16 Pad;
- /* struct following varies based on requested level */
-} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
-
-#define SMB_POSIX_UNLINK_FILE_TARGET 0
-#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1
-
-struct unlink_psx_rq { /* level 0x20a SetPathInfo */
- __le16 type;
-} __attribute__((packed));
-
-struct file_internal_info {
- __le64 UniqueId; /* inode number */
-} __attribute__((packed)); /* level 0x3ee */
-
-struct file_mode_info {
- __le32 Mode;
-} __attribute__((packed)); /* level 0x3f8 */
-
-struct file_attrib_tag {
- __le32 Attribute;
- __le32 ReparseTag;
-} __attribute__((packed)); /* level 0x40b */
-
-
-/********************************************************/
-/* FindFirst/FindNext transact2 data buffer formats */
-/********************************************************/
-
-typedef struct {
- __le32 NextEntryOffset;
- __u32 ResumeKey; /* as with FileIndex - no need to convert */
- FILE_UNIX_BASIC_INFO basic;
- char FileName[1];
-} __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */
-
-typedef struct {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 ExtFileAttributes;
- __le32 FileNameLength;
- char FileName[1];
-} __attribute__((packed)) FILE_DIRECTORY_INFO; /* level 0x101 FF resp data */
-
-typedef struct {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 ExtFileAttributes;
- __le32 FileNameLength;
- __le32 EaSize; /* length of the xattrs */
- char FileName[1];
-} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 rsp data */
-
-typedef struct {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 ExtFileAttributes;
- __le32 FileNameLength;
- __le32 EaSize; /* EA size */
- __le32 Reserved;
- __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
- char FileName[1];
-} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */
-
-typedef struct {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 ExtFileAttributes;
- __le32 FileNameLength;
- __le32 EaSize; /* length of the xattrs */
- __u8 ShortNameLength;
- __u8 Reserved;
- __u8 ShortName[24];
- char FileName[1];
-} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FFrsp data */
-
-typedef struct {
- __u32 ResumeKey;
- __le16 CreationDate; /* SMB Date */
- __le16 CreationTime; /* SMB Time */
- __le16 LastAccessDate;
- __le16 LastAccessTime;
- __le16 LastWriteDate;
- __le16 LastWriteTime;
- __le32 DataSize; /* File Size (EOF) */
- __le32 AllocationSize;
- __le16 Attributes; /* verify not u32 */
- __u8 FileNameLength;
- char FileName[1];
-} __attribute__((packed)) FIND_FILE_STANDARD_INFO; /* level 0x1 FF resp data */
-
-
-struct win_dev {
- unsigned char type[8]; /* IntxCHR or IntxBLK */
- __le64 major;
- __le64 minor;
-} __attribute__((packed));
-
-struct gea {
- unsigned char name_len;
- char name[1];
-} __attribute__((packed));
-
-struct gealist {
- unsigned long list_len;
- struct gea list[1];
-} __attribute__((packed));
-
-struct fea {
- unsigned char EA_flags;
- __u8 name_len;
- __le16 value_len;
- char name[1];
- /* optionally followed by value */
-} __attribute__((packed));
-/* flags for _FEA.fEA */
-#define FEA_NEEDEA 0x80 /* need EA bit */
-
-struct fealist {
- __le32 list_len;
- struct fea list[1];
-} __attribute__((packed));
-
-/* used to hold an arbitrary blob of data */
-struct data_blob {
- __u8 *data;
- size_t length;
- void (*free) (struct data_blob *data_blob);
-} __attribute__((packed));
-
-
-#ifdef CONFIG_CIFS_POSIX
-/*
- For better POSIX semantics from Linux client, (even better
- than the existing CIFS Unix Extensions) we need updated PDUs for:
-
- 1) PosixCreateX - to set and return the mode, inode#, device info and
- perhaps add a CreateDevice - to create Pipes and other special .inodes
- Also note POSIX open flags
- 2) Close - to return the last write time to do cache across close
- more safely
- 3) FindFirst return unique inode number - what about resume key, two
- forms short (matches readdir) and full (enough info to cache inodes)
- 4) Mkdir - set mode
-
- And under consideration:
- 5) FindClose2 (return nanosecond timestamp ??)
- 6) Use nanosecond timestamps throughout all time fields if
- corresponding attribute flag is set
- 7) sendfile - handle based copy
-
- what about fixing 64 bit alignment
-
- There are also various legacy SMB/CIFS requests used as is
-
- From existing Lanman and NTLM dialects:
- --------------------------------------
- NEGOTIATE
- SESSION_SETUP_ANDX (BB which?)
- TREE_CONNECT_ANDX (BB which wct?)
- TREE_DISCONNECT (BB add volume timestamp on response)
- LOGOFF_ANDX
- DELETE (note delete open file behavior)
- DELETE_DIRECTORY
- READ_AND_X
- WRITE_AND_X
- LOCKING_AND_X (note posix lock semantics)
- RENAME (note rename across dirs and open file rename posix behaviors)
- NT_RENAME (for hardlinks) Is this good enough for all features?
- FIND_CLOSE2
- TRANSACTION2 (18 cases)
- SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
- (BB verify that never need to set allocation size)
- SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via
- Unix ext?)
-
- COPY (note support for copy across directories) - FUTURE, OPTIONAL
- setting/getting OS/2 EAs - FUTURE (BB can this handle
- setting Linux xattrs perfectly) - OPTIONAL
- dnotify - FUTURE, OPTIONAL
- quota - FUTURE, OPTIONAL
-
- Note that various requests implemented for NT interop such as
- NT_TRANSACT (IOCTL) QueryReparseInfo
- are unneeded to servers compliant with the CIFS POSIX extensions
-
- From CIFS Unix Extensions:
- -------------------------
- T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
- T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
- T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
- T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) BB check for missing
- inode fields
- Actually a need QUERY_FILE_UNIX_INFO
- since has inode num
- BB what about a) blksize/blkbits/blocks
- b) i_version
- c) i_rdev
- d) notify mask?
- e) generation
- f) size_seqcount
- T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
- TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
- T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
- */
-
-/* xsymlink is a symlink format (used by MacOS) that can be used
- to save symlink info in a regular file when
- mounted to operating systems that do not
- support the cifs Unix extensions or EAs (for xattr
- based symlinks). For such a file to be recognized
- as containing symlink data:
-
- 1) file size must be 1067,
- 2) signature must begin file data,
- 3) length field must be set to ASCII representation
- of a number which is less than or equal to 1024,
- 4) md5 must match that of the path data */
-
-struct xsymlink {
- /* 1067 bytes */
- char signature[4]; /* XSym */ /* not null terminated */
- char cr0; /* \n */
-/* ASCII representation of length (4 bytes decimal) terminated by \n not null */
- char length[4];
- char cr1; /* \n */
-/* md5 of valid subset of path ie path[0] through path[length-1] */
- __u8 md5[32];
- char cr2; /* \n */
-/* if room left, then end with \n then 0x20s by convention but not required */
- char path[1024];
-} __attribute__((packed));
-
-typedef struct file_xattr_info {
- /* BB do we need another field for flags? BB */
- __u32 xattr_name_len;
- __u32 xattr_value_len;
- char xattr_name[];
- /* followed by xattr_value[xattr_value_len], no pad */
-} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info
- level 0x205 */
-
-/* flags for lsattr and chflags commands removed arein uapi/linux/fs.h */
-
-typedef struct file_chattr_info {
- __le64 mask; /* list of all possible attribute bits */
- __le64 mode; /* list of actual attribute bits on this inode */
-} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes
- (chattr, chflags) level 0x206 */
-#endif /* POSIX */
-#endif /* _CIFSPDU_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
deleted file mode 100644
index 98513f5af3f9..000000000000
--- a/fs/cifs/cifsproto.h
+++ /dev/null
@@ -1,696 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2002,2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-#ifndef _CIFSPROTO_H
-#define _CIFSPROTO_H
-#include <linux/nls.h>
-#include "trace.h"
-#ifdef CONFIG_CIFS_DFS_UPCALL
-#include "dfs_cache.h"
-#endif
-
-struct statfs;
-struct smb_rqst;
-struct smb3_fs_context;
-
-/*
- *****************************************************************
- * All Prototypes
- *****************************************************************
- */
-
-extern struct smb_hdr *cifs_buf_get(void);
-extern void cifs_buf_release(void *);
-extern struct smb_hdr *cifs_small_buf_get(void);
-extern void cifs_small_buf_release(void *);
-extern void free_rsp_buf(int, void *);
-extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
- unsigned int /* length */);
-extern unsigned int _get_xid(void);
-extern void _free_xid(unsigned int);
-#define get_xid() \
-({ \
- unsigned int __xid = _get_xid(); \
- cifs_dbg(FYI, "VFS: in %s as Xid: %u with uid: %d\n", \
- __func__, __xid, \
- from_kuid(&init_user_ns, current_fsuid())); \
- trace_smb3_enter(__xid, __func__); \
- __xid; \
-})
-
-#define free_xid(curr_xid) \
-do { \
- _free_xid(curr_xid); \
- cifs_dbg(FYI, "VFS: leaving %s (xid = %u) rc = %d\n", \
- __func__, curr_xid, (int)rc); \
- if (rc) \
- trace_smb3_exit_err(curr_xid, __func__, (int)rc); \
- else \
- trace_smb3_exit_done(curr_xid, __func__); \
-} while (0)
-extern int init_cifs_idmap(void);
-extern void exit_cifs_idmap(void);
-extern int init_cifs_spnego(void);
-extern void exit_cifs_spnego(void);
-extern const char *build_path_from_dentry(struct dentry *, void *);
-extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
- void *page, bool prefix);
-static inline void *alloc_dentry_path(void)
-{
- return __getname();
-}
-
-static inline void free_dentry_path(void *page)
-{
- if (page)
- __putname(page);
-}
-
-extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
- struct cifs_sb_info *cifs_sb,
- struct cifs_tcon *tcon,
- int add_treename);
-extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
-extern char *cifs_compose_mount_options(const char *sb_mountdata,
- const char *fullpath, const struct dfs_info3_param *ref,
- char **devname);
-extern void delete_mid(struct mid_q_entry *mid);
-extern void release_mid(struct mid_q_entry *mid);
-extern void cifs_wake_up_task(struct mid_q_entry *mid);
-extern int cifs_handle_standard(struct TCP_Server_Info *server,
- struct mid_q_entry *mid);
-extern int smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx);
-extern int smb3_parse_opt(const char *options, const char *key, char **val);
-extern bool cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs);
-extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
-extern int cifs_call_async(struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- mid_receive_t *receive, mid_callback_t *callback,
- mid_handle_t *handle, void *cbdata, const int flags,
- const struct cifs_credits *exist_credits);
-extern struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses);
-extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- struct smb_rqst *rqst, int *resp_buf_type,
- const int flags, struct kvec *resp_iov);
-extern int compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const int flags, const int num_rqst,
- struct smb_rqst *rqst, int *resp_buf_type,
- struct kvec *resp_iov);
-extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
- struct smb_hdr * /* input */ ,
- struct smb_hdr * /* out */ ,
- int * /* bytes returned */ , const int);
-extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
- char *in_buf, int flags);
-extern struct mid_q_entry *cifs_setup_request(struct cifs_ses *,
- struct TCP_Server_Info *,
- struct smb_rqst *);
-extern struct mid_q_entry *cifs_setup_async_request(struct TCP_Server_Info *,
- struct smb_rqst *);
-extern int cifs_check_receive(struct mid_q_entry *mid,
- struct TCP_Server_Info *server, bool log_error);
-extern int cifs_wait_mtu_credits(struct TCP_Server_Info *server,
- unsigned int size, unsigned int *num,
- struct cifs_credits *credits);
-extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
- struct kvec *, int /* nvec to send */,
- int * /* type of buf returned */, const int flags,
- struct kvec * /* resp vec */);
-extern int SendReceiveBlockingLock(const unsigned int xid,
- struct cifs_tcon *ptcon,
- struct smb_hdr *in_buf ,
- struct smb_hdr *out_buf,
- int *bytes_returned);
-void
-cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
- bool all_channels);
-void
-cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
- bool mark_smb_session);
-extern int cifs_reconnect(struct TCP_Server_Info *server,
- bool mark_smb_session);
-extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr);
-extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
-extern bool backup_cred(struct cifs_sb_info *);
-extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
-extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
- unsigned int bytes_written);
-extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int);
-extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
- int flags,
- struct cifsFileInfo **ret_file);
-extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
- int flags,
- struct cifsFileInfo **ret_file);
-extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
-extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
- struct cifsFileInfo **ret_file);
-extern unsigned int smbCalcSize(void *buf);
-extern int decode_negTokenInit(unsigned char *security_blob, int length,
- struct TCP_Server_Info *server);
-extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
-extern void cifs_set_port(struct sockaddr *addr, const unsigned short int port);
-extern int map_smb_to_linux_error(char *buf, bool logErr);
-extern int map_and_check_smb_error(struct mid_q_entry *mid, bool logErr);
-extern void header_assemble(struct smb_hdr *, char /* command */ ,
- const struct cifs_tcon *, int /* length of
- fixed section (word count) in two byte units */);
-extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
- struct cifs_ses *ses,
- void **request_buf);
-extern enum securityEnum select_sectype(struct TCP_Server_Info *server,
- enum securityEnum requested);
-extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp);
-extern struct timespec64 cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
-extern u64 cifs_UnixTimeToNT(struct timespec64);
-extern struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
- int offset);
-extern void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
-extern int cifs_get_writer(struct cifsInodeInfo *cinode);
-extern void cifs_put_writer(struct cifsInodeInfo *cinode);
-extern void cifs_done_oplock_break(struct cifsInodeInfo *cinode);
-extern int cifs_unlock_range(struct cifsFileInfo *cfile,
- struct file_lock *flock, const unsigned int xid);
-extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile);
-
-extern void cifs_down_write(struct rw_semaphore *sem);
-struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
- struct tcon_link *tlink, __u32 oplock,
- const char *symlink_target);
-extern int cifs_posix_open(const char *full_path, struct inode **inode,
- struct super_block *sb, int mode,
- unsigned int f_flags, __u32 *oplock, __u16 *netfid,
- unsigned int xid);
-void cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr);
-extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
- FILE_UNIX_BASIC_INFO *info,
- struct cifs_sb_info *cifs_sb);
-extern void cifs_dir_info_to_fattr(struct cifs_fattr *, FILE_DIRECTORY_INFO *,
- struct cifs_sb_info *);
-extern int cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
-extern struct inode *cifs_iget(struct super_block *sb,
- struct cifs_fattr *fattr);
-
-int cifs_get_inode_info(struct inode **inode, const char *full_path,
- struct cifs_open_info_data *data, struct super_block *sb, int xid,
- const struct cifs_fid *fid);
-extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
- struct super_block *sb, unsigned int xid);
-extern int cifs_get_inode_info_unix(struct inode **pinode,
- const unsigned char *search_path,
- struct super_block *sb, unsigned int xid);
-extern int cifs_set_file_info(struct inode *inode, struct iattr *attrs,
- unsigned int xid, const char *full_path, __u32 dosattr);
-extern int cifs_rename_pending_delete(const char *full_path,
- struct dentry *dentry,
- const unsigned int xid);
-extern int sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
- struct cifs_fattr *fattr, uint sidtype);
-extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
- struct cifs_fattr *fattr, struct inode *inode,
- bool get_mode_from_special_sid,
- const char *path, const struct cifs_fid *pfid);
-extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
- kuid_t uid, kgid_t gid);
-extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
- const char *, u32 *, u32);
-extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
- const struct cifs_fid *, u32 *, u32);
-extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
- const char *, int);
-extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
-extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
-extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace);
-
-extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
-extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
- unsigned int to_read);
-extern ssize_t cifs_discard_from_socket(struct TCP_Server_Info *server,
- size_t to_read);
-extern int cifs_read_page_from_socket(struct TCP_Server_Info *server,
- struct page *page,
- unsigned int page_offset,
- unsigned int to_read);
-extern int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb);
-extern int cifs_match_super(struct super_block *, void *);
-extern int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx);
-extern void cifs_umount(struct cifs_sb_info *);
-extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
-extern void cifs_reopen_persistent_handles(struct cifs_tcon *tcon);
-
-extern bool cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset,
- __u64 length, __u8 type, __u16 flags,
- struct cifsLockInfo **conf_lock,
- int rw_check);
-extern void cifs_add_pending_open(struct cifs_fid *fid,
- struct tcon_link *tlink,
- struct cifs_pending_open *open);
-extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
- struct tcon_link *tlink,
- struct cifs_pending_open *open);
-extern void cifs_del_pending_open(struct cifs_pending_open *open);
-
-extern bool cifs_is_deferred_close(struct cifsFileInfo *cfile,
- struct cifs_deferred_close **dclose);
-
-extern void cifs_add_deferred_close(struct cifsFileInfo *cfile,
- struct cifs_deferred_close *dclose);
-
-extern void cifs_del_deferred_close(struct cifsFileInfo *cfile);
-
-extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
-
-extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
-
-extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
- const char *path);
-extern struct TCP_Server_Info *
-cifs_get_tcp_session(struct smb3_fs_context *ctx,
- struct TCP_Server_Info *primary_server);
-extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
- int from_reconnect);
-extern void cifs_put_tcon(struct cifs_tcon *tcon);
-
-#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
-extern void cifs_dfs_release_automount_timer(void);
-#else /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
-#define cifs_dfs_release_automount_timer() do { } while (0)
-#endif /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
-
-void cifs_proc_init(void);
-void cifs_proc_clean(void);
-
-extern void cifs_move_llist(struct list_head *source, struct list_head *dest);
-extern void cifs_free_llist(struct list_head *llist);
-extern void cifs_del_lock_waiters(struct cifsLockInfo *lock);
-
-extern int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon,
- const struct nls_table *nlsc);
-
-extern int cifs_negotiate_protocol(const unsigned int xid,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-extern int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- struct nls_table *nls_info);
-extern int cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required);
-extern int CIFSSMBNegotiate(const unsigned int xid,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-
-extern int CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
- const char *tree, struct cifs_tcon *tcon,
- const struct nls_table *);
-
-extern int CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
- const char *searchName, struct cifs_sb_info *cifs_sb,
- __u16 *searchHandle, __u16 search_flags,
- struct cifs_search_info *psrch_inf,
- bool msearch);
-
-extern int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
- __u16 searchHandle, __u16 search_flags,
- struct cifs_search_info *psrch_inf);
-
-extern int CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
- const __u16 search_handle);
-
-extern int CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
- u16 netfid, FILE_ALL_INFO *pFindData);
-extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const char *search_Name, FILE_ALL_INFO *data,
- int legacy /* whether to use old info level */,
- const struct nls_table *nls_codepage, int remap);
-extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
- const char *search_name, FILE_ALL_INFO *data,
- const struct nls_table *nls_codepage, int remap);
-
-extern int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
- u16 netfid, FILE_UNIX_BASIC_INFO *pFindData);
-extern int CIFSSMBUnixQPathInfo(const unsigned int xid,
- struct cifs_tcon *tcon,
- const unsigned char *searchName,
- FILE_UNIX_BASIC_INFO *pFindData,
- const struct nls_table *nls_codepage, int remap);
-
-extern int CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
- const char *search_name,
- struct dfs_info3_param **target_nodes,
- unsigned int *num_of_nodes,
- const struct nls_table *nls_codepage, int remap);
-
-extern int parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
- unsigned int *num_of_nodes,
- struct dfs_info3_param **target_nodes,
- const struct nls_table *nls_codepage, int remap,
- const char *searchName, bool is_unicode);
-extern void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- struct smb3_fs_context *ctx);
-extern int CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
- struct kstatfs *FSData);
-extern int SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
- struct kstatfs *FSData);
-extern int CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon,
- __u64 cap);
-
-extern int CIFSSMBQFSAttributeInfo(const unsigned int xid,
- struct cifs_tcon *tcon);
-extern int CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon);
-extern int CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon);
-extern int CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
- struct kstatfs *FSData);
-
-extern int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fileName, const FILE_BASIC_INFO *data,
- const struct nls_table *nls_codepage,
- struct cifs_sb_info *cifs_sb);
-extern int CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const FILE_BASIC_INFO *data, __u16 fid,
- __u32 pid_of_opener);
-extern int CIFSSMBSetFileDisposition(const unsigned int xid,
- struct cifs_tcon *tcon,
- bool delete_file, __u16 fid,
- __u32 pid_of_opener);
-extern int CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
- const char *file_name, __u64 size,
- struct cifs_sb_info *cifs_sb, bool set_allocation);
-extern int CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile, __u64 size,
- bool set_allocation);
-
-struct cifs_unix_set_info_args {
- __u64 ctime;
- __u64 atime;
- __u64 mtime;
- __u64 mode;
- kuid_t uid;
- kgid_t gid;
- dev_t device;
-};
-
-extern int CIFSSMBUnixSetFileInfo(const unsigned int xid,
- struct cifs_tcon *tcon,
- const struct cifs_unix_set_info_args *args,
- u16 fid, u32 pid_of_opener);
-
-extern int CIFSSMBUnixSetPathInfo(const unsigned int xid,
- struct cifs_tcon *tcon, const char *file_name,
- const struct cifs_unix_set_info_args *args,
- const struct nls_table *nls_codepage,
- int remap);
-
-extern int CIFSSMBMkDir(const unsigned int xid, struct inode *inode,
- umode_t mode, struct cifs_tcon *tcon,
- const char *name, struct cifs_sb_info *cifs_sb);
-extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
- const char *name, struct cifs_sb_info *cifs_sb);
-extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
- const char *name, __u16 type,
- const struct nls_table *nls_codepage,
- int remap_special_chars);
-extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
- const char *name, struct cifs_sb_info *cifs_sb);
-extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb);
-extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
- int netfid, const char *target_name,
- const struct nls_table *nls_codepage,
- int remap_special_chars);
-extern int CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb);
-extern int CIFSUnixCreateHardLink(const unsigned int xid,
- struct cifs_tcon *tcon,
- const char *fromName, const char *toName,
- const struct nls_table *nls_codepage,
- int remap_special_chars);
-extern int CIFSUnixCreateSymLink(const unsigned int xid,
- struct cifs_tcon *tcon,
- const char *fromName, const char *toName,
- const struct nls_table *nls_codepage, int remap);
-extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
- struct cifs_tcon *tcon,
- const unsigned char *searchName, char **syminfo,
- const struct nls_table *nls_codepage, int remap);
-extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
- __u16 fid, char **symlinkinfo,
- const struct nls_table *nls_codepage);
-extern int CIFSSMB_set_compression(const unsigned int xid,
- struct cifs_tcon *tcon, __u16 fid);
-extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
- int *oplock, FILE_ALL_INFO *buf);
-extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fileName, const int disposition,
- const int access_flags, const int omode,
- __u16 *netfid, int *pOplock, FILE_ALL_INFO *,
- const struct nls_table *nls_codepage, int remap);
-extern int CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
- u32 posix_flags, __u64 mode, __u16 *netfid,
- FILE_UNIX_BASIC_INFO *pRetData,
- __u32 *pOplock, const char *name,
- const struct nls_table *nls_codepage, int remap);
-extern int CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon,
- const int smb_file_id);
-
-extern int CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon,
- const int smb_file_id);
-
-extern int CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, char **buf,
- int *return_buf_type);
-extern int CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, const char *buf);
-extern int CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, struct kvec *iov, const int nvec);
-extern int CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
- const char *search_name, __u64 *inode_number,
- const struct nls_table *nls_codepage,
- int remap);
-
-extern int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
- const __u16 netfid, const __u8 lock_type,
- const __u32 num_unlock, const __u32 num_lock,
- LOCKING_ANDX_RANGE *buf);
-extern int CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
- const __u16 netfid, const __u32 netpid, const __u64 len,
- const __u64 offset, const __u32 numUnlock,
- const __u32 numLock, const __u8 lockType,
- const bool waitFlag, const __u8 oplock_level);
-extern int CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
- const __u16 smb_file_id, const __u32 netpid,
- const loff_t start_offset, const __u64 len,
- struct file_lock *, const __u16 lock_type,
- const bool waitFlag);
-extern int CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon);
-extern int CIFSSMBEcho(struct TCP_Server_Info *server);
-extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses);
-
-extern struct cifs_ses *sesInfoAlloc(void);
-extern void sesInfoFree(struct cifs_ses *);
-extern struct cifs_tcon *tconInfoAlloc(void);
-extern void tconInfoFree(struct cifs_tcon *);
-
-extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
- __u32 *pexpected_response_sequence_number);
-extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
- __u32 *);
-extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
-extern int cifs_verify_signature(struct smb_rqst *rqst,
- struct TCP_Server_Info *server,
- __u32 expected_sequence_number);
-extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
-extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
-extern int calc_seckey(struct cifs_ses *);
-extern int generate_smb30signingkey(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-extern int generate_smb311signingkey(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-extern int CIFSSMBCopy(unsigned int xid,
- struct cifs_tcon *source_tcon,
- const char *fromName,
- const __u16 target_tid,
- const char *toName, const int flags,
- const struct nls_table *nls_codepage,
- int remap_special_chars);
-extern ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *searchName,
- const unsigned char *ea_name, char *EAData,
- size_t bufsize, struct cifs_sb_info *cifs_sb);
-extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fileName, const char *ea_name,
- const void *ea_value, const __u16 ea_value_len,
- const struct nls_table *nls_codepage,
- struct cifs_sb_info *cifs_sb);
-extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
- __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
-extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,
- struct cifs_ntsd *, __u32, int);
-extern int CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *searchName,
- char *acl_inf, const int buflen, const int acl_type,
- const struct nls_table *nls_codepage, int remap_special_chars);
-extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *fileName,
- const char *local_acl, const int buflen, const int acl_type,
- const struct nls_table *nls_codepage, int remap_special_chars);
-extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
- const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
-#endif /* CIFS_ALLOW_INSECURE_LEGACY */
-extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
-extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr);
-extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- struct cifs_fattr *fattr,
- const unsigned char *path);
-extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
- const struct nls_table *codepage);
-
-extern int
-cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname);
-
-extern struct TCP_Server_Info *
-cifs_find_tcp_session(struct smb3_fs_context *ctx);
-
-extern void cifs_put_smb_ses(struct cifs_ses *ses);
-
-extern struct cifs_ses *
-cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx);
-
-void cifs_readdata_release(struct kref *refcount);
-int cifs_async_readv(struct cifs_readdata *rdata);
-int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid);
-
-int cifs_async_writev(struct cifs_writedata *wdata,
- void (*release)(struct kref *kref));
-void cifs_writev_complete(struct work_struct *work);
-struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
- work_func_t complete);
-struct cifs_writedata *cifs_writedata_direct_alloc(struct page **pages,
- work_func_t complete);
-void cifs_writedata_release(struct kref *refcount);
-int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- const unsigned char *path, char *pbuf,
- unsigned int *pbytes_read);
-int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- const unsigned char *path, char *pbuf,
- unsigned int *pbytes_written);
-int __cifs_calc_signature(struct smb_rqst *rqst,
- struct TCP_Server_Info *server, char *signature,
- struct shash_desc *shash);
-enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
- enum securityEnum);
-struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
-void cifs_aio_ctx_release(struct kref *refcount);
-int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
-
-int cifs_alloc_hash(const char *name, struct shash_desc **sdesc);
-void cifs_free_hash(struct shash_desc **sdesc);
-
-void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
- unsigned int *len, unsigned int *offset);
-struct cifs_chan *
-cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server);
-int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses);
-bool is_server_using_iface(struct TCP_Server_Info *server,
- struct cifs_server_iface *iface);
-bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface);
-void cifs_ses_mark_for_reconnect(struct cifs_ses *ses);
-
-unsigned int
-cifs_ses_get_chan_index(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-void
-cifs_chan_set_in_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-void
-cifs_chan_clear_in_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-bool
-cifs_chan_in_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-void
-cifs_chan_set_need_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-void
-cifs_chan_clear_need_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-bool
-cifs_chan_needs_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-bool
-cifs_chan_is_iface_active(struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-int
-cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server);
-int
-SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount);
-
-void extract_unc_hostname(const char *unc, const char **h, size_t *len);
-int copy_path_name(char *dst, const char *src);
-int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov,
- int resp_buftype,
- struct cifs_search_info *srch_inf);
-
-struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server);
-void cifs_put_tcp_super(struct super_block *sb);
-int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix);
-char *extract_hostname(const char *unc);
-char *extract_sharename(const char *unc);
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
-static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
- const char *old_path,
- const struct nls_table *nls_codepage,
- struct dfs_info3_param *referral, int remap)
-{
- return dfs_cache_find(xid, ses, nls_codepage, remap, old_path,
- referral, NULL);
-}
-
-int match_target_ip(struct TCP_Server_Info *server,
- const char *share, size_t share_len,
- bool *result);
-int cifs_inval_name_dfs_link_error(const unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- const char *full_path,
- bool *islink);
-#else
-static inline int cifs_inval_name_dfs_link_error(const unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- const char *full_path,
- bool *islink)
-{
- *islink = false;
- return 0;
-}
-#endif
-
-static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
-{
- if (cifs_sb && (backup_cred(cifs_sb)))
- return options | CREATE_OPEN_BACKUP_INTENT;
- else
- return options;
-}
-
-struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
-void cifs_put_tcon_super(struct super_block *sb);
-int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
-
-#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifsroot.c b/fs/cifs/cifsroot.c
deleted file mode 100644
index 56ec1b233f52..000000000000
--- a/fs/cifs/cifsroot.c
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * SMB root file system support
- *
- * Copyright (c) 2019 Paulo Alcantara <palcantara@suse.de>
- */
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/root_dev.h>
-#include <linux/kernel.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <net/ipconfig.h>
-
-#define DEFAULT_MNT_OPTS \
- "vers=1.0,cifsacl,mfsymlinks,rsize=1048576,wsize=65536,uid=0,gid=0," \
- "hard,rootfs"
-
-static char root_dev[2048] __initdata = "";
-static char root_opts[1024] __initdata = DEFAULT_MNT_OPTS;
-
-static __be32 __init parse_srvaddr(char *start, char *end)
-{
- /* TODO: ipv6 support */
- char addr[sizeof("aaa.bbb.ccc.ddd")];
- int i = 0;
-
- while (start < end && i < sizeof(addr) - 1) {
- if (isdigit(*start) || *start == '.')
- addr[i++] = *start;
- start++;
- }
- addr[i] = '\0';
- return in_aton(addr);
-}
-
-/* cifsroot=//<server-ip>/<share>[,options] */
-static int __init cifs_root_setup(char *line)
-{
- char *s;
- int len;
- __be32 srvaddr = htonl(INADDR_NONE);
-
- ROOT_DEV = Root_CIFS;
-
- if (strlen(line) > 3 && line[0] == '/' && line[1] == '/') {
- s = strchr(&line[2], '/');
- if (!s || s[1] == '\0')
- return 1;
-
- /* make s point to ',' or '\0' at end of line */
- s = strchrnul(s, ',');
- /* len is strlen(unc) + '\0' */
- len = s - line + 1;
- if (len > sizeof(root_dev)) {
- pr_err("Root-CIFS: UNC path too long\n");
- return 1;
- }
- strscpy(root_dev, line, len);
- srvaddr = parse_srvaddr(&line[2], s);
- if (*s) {
- int n = snprintf(root_opts,
- sizeof(root_opts), "%s,%s",
- DEFAULT_MNT_OPTS, s + 1);
- if (n >= sizeof(root_opts)) {
- pr_err("Root-CIFS: mount options string too long\n");
- root_opts[sizeof(root_opts)-1] = '\0';
- return 1;
- }
- }
- }
-
- root_server_addr = srvaddr;
-
- return 1;
-}
-
-__setup("cifsroot=", cifs_root_setup);
-
-int __init cifs_root_data(char **dev, char **opts)
-{
- if (!root_dev[0] || root_server_addr == htonl(INADDR_NONE)) {
- pr_err("Root-CIFS: no SMB server address\n");
- return -1;
- }
-
- *dev = root_dev;
- *opts = root_opts;
-
- return 0;
-}
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
deleted file mode 100644
index c90d4ec9292c..000000000000
--- a/fs/cifs/cifssmb.c
+++ /dev/null
@@ -1,5873 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002,2010
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- * Contains the routines for constructing the SMB PDUs themselves
- *
- */
-
- /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
- /* These are mostly routines that operate on a pathname, or on a tree id */
- /* (mounted volume), but there are eight handle based routines which must be */
- /* treated slightly differently for reconnection purposes since we never */
- /* want to reuse a stale file handle and only the caller knows the file info */
-
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/vfs.h>
-#include <linux/slab.h>
-#include <linux/posix_acl_xattr.h>
-#include <linux/pagemap.h>
-#include <linux/swap.h>
-#include <linux/task_io_accounting_ops.h>
-#include <linux/uaccess.h>
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsacl.h"
-#include "cifsproto.h"
-#include "cifs_unicode.h"
-#include "cifs_debug.h"
-#include "fscache.h"
-#include "smbdirect.h"
-#ifdef CONFIG_CIFS_DFS_UPCALL
-#include "dfs_cache.h"
-#endif
-
-#ifdef CONFIG_CIFS_POSIX
-static struct {
- int index;
- char *name;
-} protocols[] = {
- {CIFS_PROT, "\2NT LM 0.12"},
- {POSIX_PROT, "\2POSIX 2"},
- {BAD_PROT, "\2"}
-};
-#else
-static struct {
- int index;
- char *name;
-} protocols[] = {
- {CIFS_PROT, "\2NT LM 0.12"},
- {BAD_PROT, "\2"}
-};
-#endif
-
-/* define the number of elements in the cifs dialect array */
-#ifdef CONFIG_CIFS_POSIX
-#define CIFS_NUM_PROT 2
-#else /* not posix */
-#define CIFS_NUM_PROT 1
-#endif /* CIFS_POSIX */
-
-
-/* reconnect the socket, tcon, and smb session if needed */
-static int
-cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
-{
- int rc;
- struct cifs_ses *ses;
- struct TCP_Server_Info *server;
- struct nls_table *nls_codepage;
-
- /*
- * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
- * tcp and smb session status done differently for those three - in the
- * calling routine
- */
- if (!tcon)
- return 0;
-
- ses = tcon->ses;
- server = ses->server;
-
- /*
- * only tree disconnect, open, and write, (and ulogoff which does not
- * have tcon) are allowed as we start umount
- */
- spin_lock(&tcon->tc_lock);
- if (tcon->status == TID_EXITING) {
- if (smb_command != SMB_COM_TREE_DISCONNECT) {
- spin_unlock(&tcon->tc_lock);
- cifs_dbg(FYI, "can not send cmd %d while umounting\n",
- smb_command);
- return -ENODEV;
- }
- }
- spin_unlock(&tcon->tc_lock);
-
- rc = cifs_wait_for_server_reconnect(server, tcon->retry);
- if (rc)
- return rc;
-
- spin_lock(&ses->chan_lock);
- if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
- spin_unlock(&ses->chan_lock);
- return 0;
- }
- spin_unlock(&ses->chan_lock);
-
- nls_codepage = load_nls_default();
-
- /*
- * Recheck after acquire mutex. If another thread is negotiating
- * and the server never sends an answer the socket will be closed
- * and tcpStatus set to reconnect.
- */
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsNeedReconnect) {
- spin_unlock(&server->srv_lock);
- rc = -EHOSTDOWN;
- goto out;
- }
- spin_unlock(&server->srv_lock);
-
- /*
- * need to prevent multiple threads trying to simultaneously
- * reconnect the same SMB session
- */
- spin_lock(&ses->chan_lock);
- if (!cifs_chan_needs_reconnect(ses, server)) {
- spin_unlock(&ses->chan_lock);
-
- /* this means that we only need to tree connect */
- if (tcon->need_reconnect)
- goto skip_sess_setup;
-
- rc = -EHOSTDOWN;
- goto out;
- }
- spin_unlock(&ses->chan_lock);
-
- mutex_lock(&ses->session_mutex);
- rc = cifs_negotiate_protocol(0, ses, server);
- if (!rc)
- rc = cifs_setup_session(0, ses, server, nls_codepage);
-
- /* do we need to reconnect tcon? */
- if (rc || !tcon->need_reconnect) {
- mutex_unlock(&ses->session_mutex);
- goto out;
- }
-
-skip_sess_setup:
- cifs_mark_open_files_invalid(tcon);
- rc = cifs_tree_connect(0, tcon, nls_codepage);
- mutex_unlock(&ses->session_mutex);
- cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
-
- if (rc) {
- pr_warn_once("reconnect tcon failed rc = %d\n", rc);
- goto out;
- }
-
- atomic_inc(&tconInfoReconnectCount);
-
- /* tell server Unix caps we support */
- if (cap_unix(ses))
- reset_cifs_unix_caps(0, tcon, NULL, NULL);
-
- /*
- * Removed call to reopen open files here. It is safer (and faster) to
- * reopen files one at a time as needed in read and write.
- *
- * FIXME: what about file locks? don't we need to reclaim them ASAP?
- */
-
-out:
- /*
- * Check if handle based operation so we know whether we can continue
- * or not without returning to caller to reset file handle
- */
- switch (smb_command) {
- case SMB_COM_READ_ANDX:
- case SMB_COM_WRITE_ANDX:
- case SMB_COM_CLOSE:
- case SMB_COM_FIND_CLOSE2:
- case SMB_COM_LOCKING_ANDX:
- rc = -EAGAIN;
- }
-
- unload_nls(nls_codepage);
- return rc;
-}
-
-/* Allocate and return pointer to an SMB request buffer, and set basic
- SMB information in the SMB header. If the return code is zero, this
- function must have filled in request_buf pointer */
-static int
-small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
- void **request_buf)
-{
- int rc;
-
- rc = cifs_reconnect_tcon(tcon, smb_command);
- if (rc)
- return rc;
-
- *request_buf = cifs_small_buf_get();
- if (*request_buf == NULL) {
- /* BB should we add a retry in here if not a writepage? */
- return -ENOMEM;
- }
-
- header_assemble((struct smb_hdr *) *request_buf, smb_command,
- tcon, wct);
-
- if (tcon != NULL)
- cifs_stats_inc(&tcon->num_smbs_sent);
-
- return 0;
-}
-
-int
-small_smb_init_no_tc(const int smb_command, const int wct,
- struct cifs_ses *ses, void **request_buf)
-{
- int rc;
- struct smb_hdr *buffer;
-
- rc = small_smb_init(smb_command, wct, NULL, request_buf);
- if (rc)
- return rc;
-
- buffer = (struct smb_hdr *)*request_buf;
- buffer->Mid = get_next_mid(ses->server);
- if (ses->capabilities & CAP_UNICODE)
- buffer->Flags2 |= SMBFLG2_UNICODE;
- if (ses->capabilities & CAP_STATUS32)
- buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-
- /* uid, tid can stay at zero as set in header assemble */
-
- /* BB add support for turning on the signing when
- this function is used after 1st of session setup requests */
-
- return rc;
-}
-
-/* If the return code is zero, this function must fill in request_buf pointer */
-static int
-__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
- void **request_buf, void **response_buf)
-{
- *request_buf = cifs_buf_get();
- if (*request_buf == NULL) {
- /* BB should we add a retry in here if not a writepage? */
- return -ENOMEM;
- }
- /* Although the original thought was we needed the response buf for */
- /* potential retries of smb operations it turns out we can determine */
- /* from the mid flags when the request buffer can be resent without */
- /* having to use a second distinct buffer for the response */
- if (response_buf)
- *response_buf = *request_buf;
-
- header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
- wct);
-
- if (tcon != NULL)
- cifs_stats_inc(&tcon->num_smbs_sent);
-
- return 0;
-}
-
-/* If the return code is zero, this function must fill in request_buf pointer */
-static int
-smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
- void **request_buf, void **response_buf)
-{
- int rc;
-
- rc = cifs_reconnect_tcon(tcon, smb_command);
- if (rc)
- return rc;
-
- return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
-}
-
-static int
-smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
- void **request_buf, void **response_buf)
-{
- spin_lock(&tcon->ses->chan_lock);
- if (cifs_chan_needs_reconnect(tcon->ses, tcon->ses->server) ||
- tcon->need_reconnect) {
- spin_unlock(&tcon->ses->chan_lock);
- return -EHOSTDOWN;
- }
- spin_unlock(&tcon->ses->chan_lock);
-
- return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
-}
-
-static int validate_t2(struct smb_t2_rsp *pSMB)
-{
- unsigned int total_size;
-
- /* check for plausible wct */
- if (pSMB->hdr.WordCount < 10)
- goto vt2_err;
-
- /* check for parm and data offset going beyond end of smb */
- if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
- get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
- goto vt2_err;
-
- total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
- if (total_size >= 512)
- goto vt2_err;
-
- /* check that bcc is at least as big as parms + data, and that it is
- * less than negotiated smb buffer
- */
- total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
- if (total_size > get_bcc(&pSMB->hdr) ||
- total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
- goto vt2_err;
-
- return 0;
-vt2_err:
- cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
- sizeof(struct smb_t2_rsp) + 16);
- return -EINVAL;
-}
-
-static int
-decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
-{
- int rc = 0;
- u16 count;
- char *guid = pSMBr->u.extended_response.GUID;
- struct TCP_Server_Info *server = ses->server;
-
- count = get_bcc(&pSMBr->hdr);
- if (count < SMB1_CLIENT_GUID_SIZE)
- return -EIO;
-
- spin_lock(&cifs_tcp_ses_lock);
- if (server->srv_count > 1) {
- spin_unlock(&cifs_tcp_ses_lock);
- if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
- cifs_dbg(FYI, "server UID changed\n");
- memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
- }
- } else {
- spin_unlock(&cifs_tcp_ses_lock);
- memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
- }
-
- if (count == SMB1_CLIENT_GUID_SIZE) {
- server->sec_ntlmssp = true;
- } else {
- count -= SMB1_CLIENT_GUID_SIZE;
- rc = decode_negTokenInit(
- pSMBr->u.extended_response.SecurityBlob, count, server);
- if (rc != 1)
- return -EINVAL;
- }
-
- return 0;
-}
-
-static bool
-should_set_ext_sec_flag(enum securityEnum sectype)
-{
- switch (sectype) {
- case RawNTLMSSP:
- case Kerberos:
- return true;
- case Unspecified:
- if (global_secflags &
- (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
- return true;
- fallthrough;
- default:
- return false;
- }
-}
-
-int
-CIFSSMBNegotiate(const unsigned int xid,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- NEGOTIATE_REQ *pSMB;
- NEGOTIATE_RSP *pSMBr;
- int rc = 0;
- int bytes_returned;
- int i;
- u16 count;
-
- if (!server) {
- WARN(1, "%s: server is NULL!\n", __func__);
- return -EIO;
- }
-
- rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
- (void **) &pSMB, (void **) &pSMBr);
- if (rc)
- return rc;
-
- pSMB->hdr.Mid = get_next_mid(server);
- pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
-
- if (should_set_ext_sec_flag(ses->sectype)) {
- cifs_dbg(FYI, "Requesting extended security\n");
- pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
- }
-
- count = 0;
- /*
- * We know that all the name entries in the protocols array
- * are short (< 16 bytes anyway) and are NUL terminated.
- */
- for (i = 0; i < CIFS_NUM_PROT; i++) {
- size_t len = strlen(protocols[i].name) + 1;
-
- memcpy(&pSMB->DialectsArray[count], protocols[i].name, len);
- count += len;
- }
- inc_rfc1001_len(pSMB, count);
- pSMB->ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc != 0)
- goto neg_err_exit;
-
- server->dialect = le16_to_cpu(pSMBr->DialectIndex);
- cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
- /* Check wct = 1 error case */
- if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
- /* core returns wct = 1, but we do not ask for core - otherwise
- small wct just comes when dialect index is -1 indicating we
- could not negotiate a common dialect */
- rc = -EOPNOTSUPP;
- goto neg_err_exit;
- } else if (pSMBr->hdr.WordCount != 17) {
- /* unknown wct */
- rc = -EOPNOTSUPP;
- goto neg_err_exit;
- }
- /* else wct == 17, NTLM or better */
-
- server->sec_mode = pSMBr->SecurityMode;
- if ((server->sec_mode & SECMODE_USER) == 0)
- cifs_dbg(FYI, "share mode security\n");
-
- /* one byte, so no need to convert this or EncryptionKeyLen from
- little endian */
- server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
- cifs_max_pending);
- set_credits(server, server->maxReq);
- /* probably no need to store and check maxvcs */
- server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
- /* set up max_read for readahead check */
- server->max_read = server->maxBuf;
- server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
- cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
- server->capabilities = le32_to_cpu(pSMBr->Capabilities);
- server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
- server->timeAdj *= 60;
-
- if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
- server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
- memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
- CIFS_CRYPTO_KEY_SIZE);
- } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
- server->capabilities & CAP_EXTENDED_SECURITY) {
- server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
- rc = decode_ext_sec_blob(ses, pSMBr);
- } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
- rc = -EIO; /* no crypt key only if plain text pwd */
- } else {
- server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
- server->capabilities &= ~CAP_EXTENDED_SECURITY;
- }
-
- if (!rc)
- rc = cifs_enable_signing(server, ses->sign);
-neg_err_exit:
- cifs_buf_release(pSMB);
-
- cifs_dbg(FYI, "negprot rc %d\n", rc);
- return rc;
-}
-
-int
-CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
-{
- struct smb_hdr *smb_buffer;
- int rc = 0;
-
- cifs_dbg(FYI, "In tree disconnect\n");
-
- /* BB: do we need to check this? These should never be NULL. */
- if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
- return -EIO;
-
- /*
- * No need to return error on this operation if tid invalidated and
- * closed on server already e.g. due to tcp session crashing. Also,
- * the tcon is no longer on the list, so no need to take lock before
- * checking this.
- */
- spin_lock(&tcon->ses->chan_lock);
- if ((tcon->need_reconnect) || CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {
- spin_unlock(&tcon->ses->chan_lock);
- return -EIO;
- }
- spin_unlock(&tcon->ses->chan_lock);
-
- rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
- (void **)&smb_buffer);
- if (rc)
- return rc;
-
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
- cifs_small_buf_release(smb_buffer);
- if (rc)
- cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
-
- /* No need to return error on this operation if tid invalidated and
- closed on server already e.g. due to tcp session crashing */
- if (rc == -EAGAIN)
- rc = 0;
-
- return rc;
-}
-
-/*
- * This is a no-op for now. We're not really interested in the reply, but
- * rather in the fact that the server sent one and that server->lstrp
- * gets updated.
- *
- * FIXME: maybe we should consider checking that the reply matches request?
- */
-static void
-cifs_echo_callback(struct mid_q_entry *mid)
-{
- struct TCP_Server_Info *server = mid->callback_data;
- struct cifs_credits credits = { .value = 1, .instance = 0 };
-
- release_mid(mid);
- add_credits(server, &credits, CIFS_ECHO_OP);
-}
-
-int
-CIFSSMBEcho(struct TCP_Server_Info *server)
-{
- ECHO_REQ *smb;
- int rc = 0;
- struct kvec iov[2];
- struct smb_rqst rqst = { .rq_iov = iov,
- .rq_nvec = 2 };
-
- cifs_dbg(FYI, "In echo request\n");
-
- rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
- if (rc)
- return rc;
-
- if (server->capabilities & CAP_UNICODE)
- smb->hdr.Flags2 |= SMBFLG2_UNICODE;
-
- /* set up echo request */
- smb->hdr.Tid = 0xffff;
- smb->hdr.WordCount = 1;
- put_unaligned_le16(1, &smb->EchoCount);
- put_bcc(1, &smb->hdr);
- smb->Data[0] = 'a';
- inc_rfc1001_len(smb, 3);
-
- iov[0].iov_len = 4;
- iov[0].iov_base = smb;
- iov[1].iov_len = get_rfc1002_length(smb);
- iov[1].iov_base = (char *)smb + 4;
-
- rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
- server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
- if (rc)
- cifs_dbg(FYI, "Echo request failed: %d\n", rc);
-
- cifs_small_buf_release(smb);
-
- return rc;
-}
-
-int
-CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
-{
- LOGOFF_ANDX_REQ *pSMB;
- int rc = 0;
-
- cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
-
- /*
- * BB: do we need to check validity of ses and server? They should
- * always be valid since we have an active reference. If not, that
- * should probably be a BUG()
- */
- if (!ses || !ses->server)
- return -EIO;
-
- mutex_lock(&ses->session_mutex);
- spin_lock(&ses->chan_lock);
- if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
- spin_unlock(&ses->chan_lock);
- goto session_already_dead; /* no need to send SMBlogoff if uid
- already closed due to reconnect */
- }
- spin_unlock(&ses->chan_lock);
-
- rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
- if (rc) {
- mutex_unlock(&ses->session_mutex);
- return rc;
- }
-
- pSMB->hdr.Mid = get_next_mid(ses->server);
-
- if (ses->server->sign)
- pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- pSMB->hdr.Uid = ses->Suid;
-
- pSMB->AndXCommand = 0xFF;
- rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
- cifs_small_buf_release(pSMB);
-session_already_dead:
- mutex_unlock(&ses->session_mutex);
-
- /* if session dead then we do not need to do ulogoff,
- since server closed smb session, no sense reporting
- error */
- if (rc == -EAGAIN)
- rc = 0;
- return rc;
-}
-
-int
-CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fileName, __u16 type,
- const struct nls_table *nls_codepage, int remap)
-{
- TRANSACTION2_SPI_REQ *pSMB = NULL;
- TRANSACTION2_SPI_RSP *pSMBr = NULL;
- struct unlink_psx_rq *pRqD;
- int name_len;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, param_offset, offset, byte_count;
-
- cifs_dbg(FYI, "In POSIX delete\n");
-PsxDelete:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, fileName);
- }
-
- params = 6 + name_len;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = 0; /* BB double check this with jra */
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
-
- /* Setup pointer to Request Data (inode type).
- * Note that SMB offsets are from the beginning of SMB which is 4 bytes
- * in, after RFC1001 field
- */
- pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4);
- pRqD->type = cpu_to_le16(type);
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
-
- pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
- pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc)
- cifs_dbg(FYI, "Posix delete returned %d\n", rc);
- cifs_buf_release(pSMB);
-
- cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
-
- if (rc == -EAGAIN)
- goto PsxDelete;
-
- return rc;
-}
-
-int
-CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
- struct cifs_sb_info *cifs_sb)
-{
- DELETE_FILE_REQ *pSMB = NULL;
- DELETE_FILE_RSP *pSMBr = NULL;
- int rc = 0;
- int bytes_returned;
- int name_len;
- int remap = cifs_remap(cifs_sb);
-
-DelFileRetry:
- rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
- PATH_MAX, cifs_sb->local_nls,
- remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->fileName, name);
- }
- pSMB->SearchAttributes =
- cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
- pSMB->BufferFormat = 0x04;
- inc_rfc1001_len(pSMB, name_len + 1);
- pSMB->ByteCount = cpu_to_le16(name_len + 1);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
- if (rc)
- cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
-
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto DelFileRetry;
-
- return rc;
-}
-
-int
-CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
- struct cifs_sb_info *cifs_sb)
-{
- DELETE_DIRECTORY_REQ *pSMB = NULL;
- DELETE_DIRECTORY_RSP *pSMBr = NULL;
- int rc = 0;
- int bytes_returned;
- int name_len;
- int remap = cifs_remap(cifs_sb);
-
- cifs_dbg(FYI, "In CIFSSMBRmDir\n");
-RmDirRetry:
- rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
- PATH_MAX, cifs_sb->local_nls,
- remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->DirName, name);
- }
-
- pSMB->BufferFormat = 0x04;
- inc_rfc1001_len(pSMB, name_len + 1);
- pSMB->ByteCount = cpu_to_le16(name_len + 1);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
- if (rc)
- cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
-
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto RmDirRetry;
- return rc;
-}
-
-int
-CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
- struct cifs_tcon *tcon, const char *name,
- struct cifs_sb_info *cifs_sb)
-{
- int rc = 0;
- CREATE_DIRECTORY_REQ *pSMB = NULL;
- CREATE_DIRECTORY_RSP *pSMBr = NULL;
- int bytes_returned;
- int name_len;
- int remap = cifs_remap(cifs_sb);
-
- cifs_dbg(FYI, "In CIFSSMBMkDir\n");
-MkDirRetry:
- rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
- PATH_MAX, cifs_sb->local_nls,
- remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->DirName, name);
- }
-
- pSMB->BufferFormat = 0x04;
- inc_rfc1001_len(pSMB, name_len + 1);
- pSMB->ByteCount = cpu_to_le16(name_len + 1);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
- if (rc)
- cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
-
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto MkDirRetry;
- return rc;
-}
-
-int
-CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
- __u32 posix_flags, __u64 mode, __u16 *netfid,
- FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
- const char *name, const struct nls_table *nls_codepage,
- int remap)
-{
- TRANSACTION2_SPI_REQ *pSMB = NULL;
- TRANSACTION2_SPI_RSP *pSMBr = NULL;
- int name_len;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, param_offset, offset, byte_count, count;
- OPEN_PSX_REQ *pdata;
- OPEN_PSX_RSP *psx_rsp;
-
- cifs_dbg(FYI, "In POSIX Create\n");
-PsxCreat:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, name);
- }
-
- params = 6 + name_len;
- count = sizeof(OPEN_PSX_REQ);
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
- /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
- pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4);
- pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
- pdata->Permissions = cpu_to_le64(mode);
- pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
- pdata->OpenFlags = cpu_to_le32(*pOplock);
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- byte_count = 3 /* pad */ + params + count;
-
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Posix create returned %d\n", rc);
- goto psx_create_err;
- }
-
- cifs_dbg(FYI, "copying inode info\n");
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
- rc = -EIO; /* bad smb */
- goto psx_create_err;
- }
-
- /* copy return information to pRetData */
- psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
- + le16_to_cpu(pSMBr->t2.DataOffset));
-
- *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
- if (netfid)
- *netfid = psx_rsp->Fid; /* cifs fid stays in le */
- /* Let caller know file was created so we can set the mode. */
- /* Do we care about the CreateAction in any other cases? */
- if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
- *pOplock |= CIFS_CREATE_ACTION;
- /* check to make sure response data is there */
- if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
- pRetData->Type = cpu_to_le32(-1); /* unknown */
- cifs_dbg(NOISY, "unknown type\n");
- } else {
- if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
- + sizeof(FILE_UNIX_BASIC_INFO)) {
- cifs_dbg(VFS, "Open response data too small\n");
- pRetData->Type = cpu_to_le32(-1);
- goto psx_create_err;
- }
- memcpy((char *) pRetData,
- (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
- sizeof(FILE_UNIX_BASIC_INFO));
- }
-
-psx_create_err:
- cifs_buf_release(pSMB);
-
- if (posix_flags & SMB_O_DIRECTORY)
- cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
- else
- cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
-
- if (rc == -EAGAIN)
- goto PsxCreat;
-
- return rc;
-}
-
-static __u16 convert_disposition(int disposition)
-{
- __u16 ofun = 0;
-
- switch (disposition) {
- case FILE_SUPERSEDE:
- ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
- break;
- case FILE_OPEN:
- ofun = SMBOPEN_OAPPEND;
- break;
- case FILE_CREATE:
- ofun = SMBOPEN_OCREATE;
- break;
- case FILE_OPEN_IF:
- ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
- break;
- case FILE_OVERWRITE:
- ofun = SMBOPEN_OTRUNC;
- break;
- case FILE_OVERWRITE_IF:
- ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
- break;
- default:
- cifs_dbg(FYI, "unknown disposition %d\n", disposition);
- ofun = SMBOPEN_OAPPEND; /* regular open */
- }
- return ofun;
-}
-
-static int
-access_flags_to_smbopen_mode(const int access_flags)
-{
- int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
-
- if (masked_flags == GENERIC_READ)
- return SMBOPEN_READ;
- else if (masked_flags == GENERIC_WRITE)
- return SMBOPEN_WRITE;
-
- /* just go for read/write */
- return SMBOPEN_READWRITE;
-}
-
-int
-SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fileName, const int openDisposition,
- const int access_flags, const int create_options, __u16 *netfid,
- int *pOplock, FILE_ALL_INFO *pfile_info,
- const struct nls_table *nls_codepage, int remap)
-{
- int rc;
- OPENX_REQ *pSMB = NULL;
- OPENX_RSP *pSMBr = NULL;
- int bytes_returned;
- int name_len;
- __u16 count;
-
-OldOpenRetry:
- rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- pSMB->AndXCommand = 0xFF; /* none */
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- count = 1; /* account for one byte pad to word boundary */
- name_len =
- cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
- fileName, PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- count = 0; /* no pad */
- name_len = copy_path_name(pSMB->fileName, fileName);
- }
- if (*pOplock & REQ_OPLOCK)
- pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
- else if (*pOplock & REQ_BATCHOPLOCK)
- pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
-
- pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
- pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
- pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
- /* set file as system file if special file such
- as fifo and server expecting SFU style and
- no Unix extensions */
-
- if (create_options & CREATE_OPTION_SPECIAL)
- pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
- else /* BB FIXME BB */
- pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
-
- if (create_options & CREATE_OPTION_READONLY)
- pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
-
- /* BB FIXME BB */
-/* pSMB->CreateOptions = cpu_to_le32(create_options &
- CREATE_OPTIONS_MASK); */
- /* BB FIXME END BB */
-
- pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
- pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
- count += name_len;
- inc_rfc1001_len(pSMB, count);
-
- pSMB->ByteCount = cpu_to_le16(count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *)pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
- if (rc) {
- cifs_dbg(FYI, "Error in Open = %d\n", rc);
- } else {
- /* BB verify if wct == 15 */
-
-/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
-
- *netfid = pSMBr->Fid; /* cifs fid stays in le */
- /* Let caller know file was created so we can set the mode. */
- /* Do we care about the CreateAction in any other cases? */
- /* BB FIXME BB */
-/* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
- *pOplock |= CIFS_CREATE_ACTION; */
- /* BB FIXME END */
-
- if (pfile_info) {
- pfile_info->CreationTime = 0; /* BB convert CreateTime*/
- pfile_info->LastAccessTime = 0; /* BB fixme */
- pfile_info->LastWriteTime = 0; /* BB fixme */
- pfile_info->ChangeTime = 0; /* BB fixme */
- pfile_info->Attributes =
- cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
- /* the file_info buf is endian converted by caller */
- pfile_info->AllocationSize =
- cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
- pfile_info->EndOfFile = pfile_info->AllocationSize;
- pfile_info->NumberOfLinks = cpu_to_le32(1);
- pfile_info->DeletePending = 0;
- }
- }
-
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto OldOpenRetry;
- return rc;
-}
-
-int
-CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
- FILE_ALL_INFO *buf)
-{
- int rc;
- OPEN_REQ *req = NULL;
- OPEN_RSP *rsp = NULL;
- int bytes_returned;
- int name_len;
- __u16 count;
- struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
- struct cifs_tcon *tcon = oparms->tcon;
- int remap = cifs_remap(cifs_sb);
- const struct nls_table *nls = cifs_sb->local_nls;
- int create_options = oparms->create_options;
- int desired_access = oparms->desired_access;
- int disposition = oparms->disposition;
- const char *path = oparms->path;
-
-openRetry:
- rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
- (void **)&rsp);
- if (rc)
- return rc;
-
- /* no commands go after this */
- req->AndXCommand = 0xFF;
-
- if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
- /* account for one byte pad to word boundary */
- count = 1;
- name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
- path, PATH_MAX, nls, remap);
- /* trailing null */
- name_len++;
- name_len *= 2;
- req->NameLength = cpu_to_le16(name_len);
- } else {
- /* BB improve check for buffer overruns BB */
- /* no pad */
- count = 0;
- name_len = copy_path_name(req->fileName, path);
- req->NameLength = cpu_to_le16(name_len);
- }
-
- if (*oplock & REQ_OPLOCK)
- req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
- else if (*oplock & REQ_BATCHOPLOCK)
- req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
-
- req->DesiredAccess = cpu_to_le32(desired_access);
- req->AllocationSize = 0;
-
- /*
- * Set file as system file if special file such as fifo and server
- * expecting SFU style and no Unix extensions.
- */
- if (create_options & CREATE_OPTION_SPECIAL)
- req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
- else
- req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
-
- /*
- * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
- * sensitive checks for other servers such as Samba.
- */
- if (tcon->ses->capabilities & CAP_UNIX)
- req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
-
- if (create_options & CREATE_OPTION_READONLY)
- req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
-
- req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
- req->CreateDisposition = cpu_to_le32(disposition);
- req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
-
- /* BB Expirement with various impersonation levels and verify */
- req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
- req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
-
- count += name_len;
- inc_rfc1001_len(req, count);
-
- req->ByteCount = cpu_to_le16(count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
- (struct smb_hdr *)rsp, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
- if (rc) {
- cifs_dbg(FYI, "Error in Open = %d\n", rc);
- cifs_buf_release(req);
- if (rc == -EAGAIN)
- goto openRetry;
- return rc;
- }
-
- /* 1 byte no need to le_to_cpu */
- *oplock = rsp->OplockLevel;
- /* cifs fid stays in le */
- oparms->fid->netfid = rsp->Fid;
- oparms->fid->access = desired_access;
-
- /* Let caller know file was created so we can set the mode. */
- /* Do we care about the CreateAction in any other cases? */
- if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
- *oplock |= CIFS_CREATE_ACTION;
-
- if (buf) {
- /* copy from CreationTime to Attributes */
- memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
- /* the file_info buf is endian converted by caller */
- buf->AllocationSize = rsp->AllocationSize;
- buf->EndOfFile = rsp->EndOfFile;
- buf->NumberOfLinks = cpu_to_le32(1);
- buf->DeletePending = 0;
- }
-
- cifs_buf_release(req);
- return rc;
-}
-
-static void
-cifs_readv_callback(struct mid_q_entry *mid)
-{
- struct cifs_readdata *rdata = mid->callback_data;
- struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
- struct TCP_Server_Info *server = tcon->ses->server;
- struct smb_rqst rqst = { .rq_iov = rdata->iov,
- .rq_nvec = 2,
- .rq_pages = rdata->pages,
- .rq_offset = rdata->page_offset,
- .rq_npages = rdata->nr_pages,
- .rq_pagesz = rdata->pagesz,
- .rq_tailsz = rdata->tailsz };
- struct cifs_credits credits = { .value = 1, .instance = 0 };
-
- cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
- __func__, mid->mid, mid->mid_state, rdata->result,
- rdata->bytes);
-
- switch (mid->mid_state) {
- case MID_RESPONSE_RECEIVED:
- /* result already set, check signature */
- if (server->sign) {
- int rc = 0;
-
- rc = cifs_verify_signature(&rqst, server,
- mid->sequence_number);
- if (rc)
- cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
- rc);
- }
- /* FIXME: should this be counted toward the initiating task? */
- task_io_account_read(rdata->got_bytes);
- cifs_stats_bytes_read(tcon, rdata->got_bytes);
- break;
- case MID_REQUEST_SUBMITTED:
- case MID_RETRY_NEEDED:
- rdata->result = -EAGAIN;
- if (server->sign && rdata->got_bytes)
- /* reset bytes number since we can not check a sign */
- rdata->got_bytes = 0;
- /* FIXME: should this be counted toward the initiating task? */
- task_io_account_read(rdata->got_bytes);
- cifs_stats_bytes_read(tcon, rdata->got_bytes);
- break;
- default:
- rdata->result = -EIO;
- }
-
- queue_work(cifsiod_wq, &rdata->work);
- release_mid(mid);
- add_credits(server, &credits, 0);
-}
-
-/* cifs_async_readv - send an async write, and set up mid to handle result */
-int
-cifs_async_readv(struct cifs_readdata *rdata)
-{
- int rc;
- READ_REQ *smb = NULL;
- int wct;
- struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
- struct smb_rqst rqst = { .rq_iov = rdata->iov,
- .rq_nvec = 2 };
-
- cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
- __func__, rdata->offset, rdata->bytes);
-
- if (tcon->ses->capabilities & CAP_LARGE_FILES)
- wct = 12;
- else {
- wct = 10; /* old style read */
- if ((rdata->offset >> 32) > 0) {
- /* can not handle this big offset for old */
- return -EIO;
- }
- }
-
- rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
- if (rc)
- return rc;
-
- smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
- smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
-
- smb->AndXCommand = 0xFF; /* none */
- smb->Fid = rdata->cfile->fid.netfid;
- smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
- if (wct == 12)
- smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
- smb->Remaining = 0;
- smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
- smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
- if (wct == 12)
- smb->ByteCount = 0;
- else {
- /* old style read */
- struct smb_com_readx_req *smbr =
- (struct smb_com_readx_req *)smb;
- smbr->ByteCount = 0;
- }
-
- /* 4 for RFC1001 length + 1 for BCC */
- rdata->iov[0].iov_base = smb;
- rdata->iov[0].iov_len = 4;
- rdata->iov[1].iov_base = (char *)smb + 4;
- rdata->iov[1].iov_len = get_rfc1002_length(smb);
-
- kref_get(&rdata->refcount);
- rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
- cifs_readv_callback, NULL, rdata, 0, NULL);
-
- if (rc == 0)
- cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
- else
- kref_put(&rdata->refcount, cifs_readdata_release);
-
- cifs_small_buf_release(smb);
- return rc;
-}
-
-int
-CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, char **buf, int *pbuf_type)
-{
- int rc = -EACCES;
- READ_REQ *pSMB = NULL;
- READ_RSP *pSMBr = NULL;
- char *pReadData = NULL;
- int wct;
- int resp_buf_type = 0;
- struct kvec iov[1];
- struct kvec rsp_iov;
- __u32 pid = io_parms->pid;
- __u16 netfid = io_parms->netfid;
- __u64 offset = io_parms->offset;
- struct cifs_tcon *tcon = io_parms->tcon;
- unsigned int count = io_parms->length;
-
- cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
- if (tcon->ses->capabilities & CAP_LARGE_FILES)
- wct = 12;
- else {
- wct = 10; /* old style read */
- if ((offset >> 32) > 0) {
- /* can not handle this big offset for old */
- return -EIO;
- }
- }
-
- *nbytes = 0;
- rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
- if (rc)
- return rc;
-
- pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
- pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
-
- /* tcon and ses pointer are checked in smb_init */
- if (tcon->ses->server == NULL)
- return -ECONNABORTED;
-
- pSMB->AndXCommand = 0xFF; /* none */
- pSMB->Fid = netfid;
- pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
- if (wct == 12)
- pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
-
- pSMB->Remaining = 0;
- pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
- pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
- if (wct == 12)
- pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
- else {
- /* old style read */
- struct smb_com_readx_req *pSMBW =
- (struct smb_com_readx_req *)pSMB;
- pSMBW->ByteCount = 0;
- }
-
- iov[0].iov_base = (char *)pSMB;
- iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
- rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
- CIFS_LOG_ERROR, &rsp_iov);
- cifs_small_buf_release(pSMB);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
- pSMBr = (READ_RSP *)rsp_iov.iov_base;
- if (rc) {
- cifs_dbg(VFS, "Send error in read = %d\n", rc);
- } else {
- int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
- data_length = data_length << 16;
- data_length += le16_to_cpu(pSMBr->DataLength);
- *nbytes = data_length;
-
- /*check that DataLength would not go beyond end of SMB */
- if ((data_length > CIFSMaxBufSize)
- || (data_length > count)) {
- cifs_dbg(FYI, "bad length %d for count %d\n",
- data_length, count);
- rc = -EIO;
- *nbytes = 0;
- } else {
- pReadData = (char *) (&pSMBr->hdr.Protocol) +
- le16_to_cpu(pSMBr->DataOffset);
-/* if (rc = copy_to_user(buf, pReadData, data_length)) {
- cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
- rc = -EFAULT;
- }*/ /* can not use copy_to_user when using page cache*/
- if (*buf)
- memcpy(*buf, pReadData, data_length);
- }
- }
-
- if (*buf) {
- free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
- } else if (resp_buf_type != CIFS_NO_BUFFER) {
- /* return buffer to caller to free */
- *buf = rsp_iov.iov_base;
- if (resp_buf_type == CIFS_SMALL_BUFFER)
- *pbuf_type = CIFS_SMALL_BUFFER;
- else if (resp_buf_type == CIFS_LARGE_BUFFER)
- *pbuf_type = CIFS_LARGE_BUFFER;
- } /* else no valid buffer on return - leave as null */
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
- return rc;
-}
-
-
-int
-CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, const char *buf)
-{
- int rc = -EACCES;
- WRITE_REQ *pSMB = NULL;
- WRITE_RSP *pSMBr = NULL;
- int bytes_returned, wct;
- __u32 bytes_sent;
- __u16 byte_count;
- __u32 pid = io_parms->pid;
- __u16 netfid = io_parms->netfid;
- __u64 offset = io_parms->offset;
- struct cifs_tcon *tcon = io_parms->tcon;
- unsigned int count = io_parms->length;
-
- *nbytes = 0;
-
- /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
- if (tcon->ses == NULL)
- return -ECONNABORTED;
-
- if (tcon->ses->capabilities & CAP_LARGE_FILES)
- wct = 14;
- else {
- wct = 12;
- if ((offset >> 32) > 0) {
- /* can not handle big offset for old srv */
- return -EIO;
- }
- }
-
- rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
- pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
-
- /* tcon and ses pointer are checked in smb_init */
- if (tcon->ses->server == NULL)
- return -ECONNABORTED;
-
- pSMB->AndXCommand = 0xFF; /* none */
- pSMB->Fid = netfid;
- pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
- if (wct == 14)
- pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
-
- pSMB->Reserved = 0xFFFFFFFF;
- pSMB->WriteMode = 0;
- pSMB->Remaining = 0;
-
- /* Can increase buffer size if buffer is big enough in some cases ie we
- can send more if LARGE_WRITE_X capability returned by the server and if
- our buffer is big enough or if we convert to iovecs on socket writes
- and eliminate the copy to the CIFS buffer */
- if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
- bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
- } else {
- bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
- & ~0xFF;
- }
-
- if (bytes_sent > count)
- bytes_sent = count;
- pSMB->DataOffset =
- cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
- if (buf)
- memcpy(pSMB->Data, buf, bytes_sent);
- else if (count != 0) {
- /* No buffer */
- cifs_buf_release(pSMB);
- return -EINVAL;
- } /* else setting file size with write of zero bytes */
- if (wct == 14)
- byte_count = bytes_sent + 1; /* pad */
- else /* wct == 12 */
- byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
-
- pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
- pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
- inc_rfc1001_len(pSMB, byte_count);
-
- if (wct == 14)
- pSMB->ByteCount = cpu_to_le16(byte_count);
- else { /* old style write has byte count 4 bytes earlier
- so 4 bytes pad */
- struct smb_com_writex_req *pSMBW =
- (struct smb_com_writex_req *)pSMB;
- pSMBW->ByteCount = cpu_to_le16(byte_count);
- }
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
- if (rc) {
- cifs_dbg(FYI, "Send error in write = %d\n", rc);
- } else {
- *nbytes = le16_to_cpu(pSMBr->CountHigh);
- *nbytes = (*nbytes) << 16;
- *nbytes += le16_to_cpu(pSMBr->Count);
-
- /*
- * Mask off high 16 bits when bytes written as returned by the
- * server is greater than bytes requested by the client. Some
- * OS/2 servers are known to set incorrect CountHigh values.
- */
- if (*nbytes > count)
- *nbytes &= 0xFFFF;
- }
-
- cifs_buf_release(pSMB);
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
-
- return rc;
-}
-
-/*
- * Check the mid_state and signature on received buffer (if any), and queue the
- * workqueue completion task.
- */
-static void
-cifs_writev_callback(struct mid_q_entry *mid)
-{
- struct cifs_writedata *wdata = mid->callback_data;
- struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
- unsigned int written;
- WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
- struct cifs_credits credits = { .value = 1, .instance = 0 };
-
- switch (mid->mid_state) {
- case MID_RESPONSE_RECEIVED:
- wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
- if (wdata->result != 0)
- break;
-
- written = le16_to_cpu(smb->CountHigh);
- written <<= 16;
- written += le16_to_cpu(smb->Count);
- /*
- * Mask off high 16 bits when bytes written as returned
- * by the server is greater than bytes requested by the
- * client. OS/2 servers are known to set incorrect
- * CountHigh values.
- */
- if (written > wdata->bytes)
- written &= 0xFFFF;
-
- if (written < wdata->bytes)
- wdata->result = -ENOSPC;
- else
- wdata->bytes = written;
- break;
- case MID_REQUEST_SUBMITTED:
- case MID_RETRY_NEEDED:
- wdata->result = -EAGAIN;
- break;
- default:
- wdata->result = -EIO;
- break;
- }
-
- queue_work(cifsiod_wq, &wdata->work);
- release_mid(mid);
- add_credits(tcon->ses->server, &credits, 0);
-}
-
-/* cifs_async_writev - send an async write, and set up mid to handle result */
-int
-cifs_async_writev(struct cifs_writedata *wdata,
- void (*release)(struct kref *kref))
-{
- int rc = -EACCES;
- WRITE_REQ *smb = NULL;
- int wct;
- struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
- struct kvec iov[2];
- struct smb_rqst rqst = { };
-
- if (tcon->ses->capabilities & CAP_LARGE_FILES) {
- wct = 14;
- } else {
- wct = 12;
- if (wdata->offset >> 32 > 0) {
- /* can not handle big offset for old srv */
- return -EIO;
- }
- }
-
- rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
- if (rc)
- goto async_writev_out;
-
- smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
- smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
-
- smb->AndXCommand = 0xFF; /* none */
- smb->Fid = wdata->cfile->fid.netfid;
- smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
- if (wct == 14)
- smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
- smb->Reserved = 0xFFFFFFFF;
- smb->WriteMode = 0;
- smb->Remaining = 0;
-
- smb->DataOffset =
- cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
-
- /* 4 for RFC1001 length + 1 for BCC */
- iov[0].iov_len = 4;
- iov[0].iov_base = smb;
- iov[1].iov_len = get_rfc1002_length(smb) + 1;
- iov[1].iov_base = (char *)smb + 4;
-
- rqst.rq_iov = iov;
- rqst.rq_nvec = 2;
- rqst.rq_pages = wdata->pages;
- rqst.rq_offset = wdata->page_offset;
- rqst.rq_npages = wdata->nr_pages;
- rqst.rq_pagesz = wdata->pagesz;
- rqst.rq_tailsz = wdata->tailsz;
-
- cifs_dbg(FYI, "async write at %llu %u bytes\n",
- wdata->offset, wdata->bytes);
-
- smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
- smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
-
- if (wct == 14) {
- inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
- put_bcc(wdata->bytes + 1, &smb->hdr);
- } else {
- /* wct == 12 */
- struct smb_com_writex_req *smbw =
- (struct smb_com_writex_req *)smb;
- inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
- put_bcc(wdata->bytes + 5, &smbw->hdr);
- iov[1].iov_len += 4; /* pad bigger by four bytes */
- }
-
- kref_get(&wdata->refcount);
- rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
- cifs_writev_callback, NULL, wdata, 0, NULL);
-
- if (rc == 0)
- cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
- else
- kref_put(&wdata->refcount, release);
-
-async_writev_out:
- cifs_small_buf_release(smb);
- return rc;
-}
-
-int
-CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, struct kvec *iov, int n_vec)
-{
- int rc;
- WRITE_REQ *pSMB = NULL;
- int wct;
- int smb_hdr_len;
- int resp_buf_type = 0;
- __u32 pid = io_parms->pid;
- __u16 netfid = io_parms->netfid;
- __u64 offset = io_parms->offset;
- struct cifs_tcon *tcon = io_parms->tcon;
- unsigned int count = io_parms->length;
- struct kvec rsp_iov;
-
- *nbytes = 0;
-
- cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
-
- if (tcon->ses->capabilities & CAP_LARGE_FILES) {
- wct = 14;
- } else {
- wct = 12;
- if ((offset >> 32) > 0) {
- /* can not handle big offset for old srv */
- return -EIO;
- }
- }
- rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
- if (rc)
- return rc;
-
- pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
- pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
-
- /* tcon and ses pointer are checked in smb_init */
- if (tcon->ses->server == NULL)
- return -ECONNABORTED;
-
- pSMB->AndXCommand = 0xFF; /* none */
- pSMB->Fid = netfid;
- pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
- if (wct == 14)
- pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
- pSMB->Reserved = 0xFFFFFFFF;
- pSMB->WriteMode = 0;
- pSMB->Remaining = 0;
-
- pSMB->DataOffset =
- cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
-
- pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
- pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
- /* header + 1 byte pad */
- smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
- if (wct == 14)
- inc_rfc1001_len(pSMB, count + 1);
- else /* wct == 12 */
- inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
- if (wct == 14)
- pSMB->ByteCount = cpu_to_le16(count + 1);
- else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
- struct smb_com_writex_req *pSMBW =
- (struct smb_com_writex_req *)pSMB;
- pSMBW->ByteCount = cpu_to_le16(count + 5);
- }
- iov[0].iov_base = pSMB;
- if (wct == 14)
- iov[0].iov_len = smb_hdr_len + 4;
- else /* wct == 12 pad bigger by four bytes */
- iov[0].iov_len = smb_hdr_len + 8;
-
- rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
- &rsp_iov);
- cifs_small_buf_release(pSMB);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
- if (rc) {
- cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
- } else if (resp_buf_type == 0) {
- /* presumably this can not happen, but best to be safe */
- rc = -EIO;
- } else {
- WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
- *nbytes = le16_to_cpu(pSMBr->CountHigh);
- *nbytes = (*nbytes) << 16;
- *nbytes += le16_to_cpu(pSMBr->Count);
-
- /*
- * Mask off high 16 bits when bytes written as returned by the
- * server is greater than bytes requested by the client. OS/2
- * servers are known to set incorrect CountHigh values.
- */
- if (*nbytes > count)
- *nbytes &= 0xFFFF;
- }
-
- free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
-
- return rc;
-}
-
-int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
- const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
- const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
-{
- int rc = 0;
- LOCK_REQ *pSMB = NULL;
- struct kvec iov[2];
- struct kvec rsp_iov;
- int resp_buf_type;
- __u16 count;
-
- cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
- num_lock, num_unlock);
-
- rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
- if (rc)
- return rc;
-
- pSMB->Timeout = 0;
- pSMB->NumberOfLocks = cpu_to_le16(num_lock);
- pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
- pSMB->LockType = lock_type;
- pSMB->AndXCommand = 0xFF; /* none */
- pSMB->Fid = netfid; /* netfid stays le */
-
- count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
- inc_rfc1001_len(pSMB, count);
- pSMB->ByteCount = cpu_to_le16(count);
-
- iov[0].iov_base = (char *)pSMB;
- iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
- (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
- iov[1].iov_base = (char *)buf;
- iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
-
- cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
- rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
- CIFS_NO_RSP_BUF, &rsp_iov);
- cifs_small_buf_release(pSMB);
- if (rc)
- cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
-
- return rc;
-}
-
-int
-CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
- const __u16 smb_file_id, const __u32 netpid, const __u64 len,
- const __u64 offset, const __u32 numUnlock,
- const __u32 numLock, const __u8 lockType,
- const bool waitFlag, const __u8 oplock_level)
-{
- int rc = 0;
- LOCK_REQ *pSMB = NULL;
-/* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
- int bytes_returned;
- int flags = 0;
- __u16 count;
-
- cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
- (int)waitFlag, numLock);
- rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
-
- if (rc)
- return rc;
-
- if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
- /* no response expected */
- flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
- pSMB->Timeout = 0;
- } else if (waitFlag) {
- flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
- pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
- } else {
- pSMB->Timeout = 0;
- }
-
- pSMB->NumberOfLocks = cpu_to_le16(numLock);
- pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
- pSMB->LockType = lockType;
- pSMB->OplockLevel = oplock_level;
- pSMB->AndXCommand = 0xFF; /* none */
- pSMB->Fid = smb_file_id; /* netfid stays le */
-
- if ((numLock != 0) || (numUnlock != 0)) {
- pSMB->Locks[0].Pid = cpu_to_le16(netpid);
- /* BB where to store pid high? */
- pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
- pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
- pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
- pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
- count = sizeof(LOCKING_ANDX_RANGE);
- } else {
- /* oplock break */
- count = 0;
- }
- inc_rfc1001_len(pSMB, count);
- pSMB->ByteCount = cpu_to_le16(count);
-
- if (waitFlag)
- rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMB, &bytes_returned);
- else
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
- cifs_small_buf_release(pSMB);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
- if (rc)
- cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
- return rc;
-}
-
-int
-CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
- const __u16 smb_file_id, const __u32 netpid,
- const loff_t start_offset, const __u64 len,
- struct file_lock *pLockData, const __u16 lock_type,
- const bool waitFlag)
-{
- struct smb_com_transaction2_sfi_req *pSMB = NULL;
- struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
- struct cifs_posix_lock *parm_data;
- int rc = 0;
- int timeout = 0;
- int bytes_returned = 0;
- int resp_buf_type = 0;
- __u16 params, param_offset, offset, byte_count, count;
- struct kvec iov[1];
- struct kvec rsp_iov;
-
- cifs_dbg(FYI, "Posix Lock\n");
-
- rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
-
- if (rc)
- return rc;
-
- pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
-
- params = 6;
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
- offset = param_offset + params;
-
- count = sizeof(struct cifs_posix_lock);
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- if (pLockData)
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
- else
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
- byte_count = 3 /* pad */ + params + count;
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
- parm_data = (struct cifs_posix_lock *)
- (((char *)pSMB) + offset + 4);
-
- parm_data->lock_type = cpu_to_le16(lock_type);
- if (waitFlag) {
- timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
- parm_data->lock_flags = cpu_to_le16(1);
- pSMB->Timeout = cpu_to_le32(-1);
- } else
- pSMB->Timeout = 0;
-
- parm_data->pid = cpu_to_le32(netpid);
- parm_data->start = cpu_to_le64(start_offset);
- parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
-
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->Fid = smb_file_id;
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- if (waitFlag) {
- rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned);
- } else {
- iov[0].iov_base = (char *)pSMB;
- iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
- rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
- &resp_buf_type, timeout, &rsp_iov);
- pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
- }
- cifs_small_buf_release(pSMB);
-
- if (rc) {
- cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
- } else if (pLockData) {
- /* lock structure can be returned on get */
- __u16 data_offset;
- __u16 data_count;
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
- rc = -EIO; /* bad smb */
- goto plk_err_exit;
- }
- data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- data_count = le16_to_cpu(pSMBr->t2.DataCount);
- if (data_count < sizeof(struct cifs_posix_lock)) {
- rc = -EIO;
- goto plk_err_exit;
- }
- parm_data = (struct cifs_posix_lock *)
- ((char *)&pSMBr->hdr.Protocol + data_offset);
- if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
- pLockData->fl_type = F_UNLCK;
- else {
- if (parm_data->lock_type ==
- cpu_to_le16(CIFS_RDLCK))
- pLockData->fl_type = F_RDLCK;
- else if (parm_data->lock_type ==
- cpu_to_le16(CIFS_WRLCK))
- pLockData->fl_type = F_WRLCK;
-
- pLockData->fl_start = le64_to_cpu(parm_data->start);
- pLockData->fl_end = pLockData->fl_start +
- (le64_to_cpu(parm_data->length) ?
- le64_to_cpu(parm_data->length) - 1 : 0);
- pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
- }
- }
-
-plk_err_exit:
- free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
-
- return rc;
-}
-
-
-int
-CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
-{
- int rc = 0;
- CLOSE_REQ *pSMB = NULL;
- cifs_dbg(FYI, "In CIFSSMBClose\n");
-
-/* do not retry on dead session on close */
- rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
- if (rc == -EAGAIN)
- return 0;
- if (rc)
- return rc;
-
- pSMB->FileID = (__u16) smb_file_id;
- pSMB->LastWriteTime = 0xFFFFFFFF;
- pSMB->ByteCount = 0;
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
- cifs_small_buf_release(pSMB);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
- if (rc) {
- if (rc != -EINTR) {
- /* EINTR is expected when user ctl-c to kill app */
- cifs_dbg(VFS, "Send error in Close = %d\n", rc);
- }
- }
-
- /* Since session is dead, file will be closed on server already */
- if (rc == -EAGAIN)
- rc = 0;
-
- return rc;
-}
-
-int
-CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
-{
- int rc = 0;
- FLUSH_REQ *pSMB = NULL;
- cifs_dbg(FYI, "In CIFSSMBFlush\n");
-
- rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
- if (rc)
- return rc;
-
- pSMB->FileID = (__u16) smb_file_id;
- pSMB->ByteCount = 0;
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
- cifs_small_buf_release(pSMB);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
- if (rc)
- cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
-
- return rc;
-}
-
-int
-CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb)
-{
- int rc = 0;
- RENAME_REQ *pSMB = NULL;
- RENAME_RSP *pSMBr = NULL;
- int bytes_returned;
- int name_len, name_len2;
- __u16 count;
- int remap = cifs_remap(cifs_sb);
-
- cifs_dbg(FYI, "In CIFSSMBRename\n");
-renameRetry:
- rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- pSMB->BufferFormat = 0x04;
- pSMB->SearchAttributes =
- cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
- ATTR_DIRECTORY);
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
- from_name, PATH_MAX,
- cifs_sb->local_nls, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- pSMB->OldFileName[name_len] = 0x04; /* pad */
- /* protocol requires ASCII signature byte on Unicode string */
- pSMB->OldFileName[name_len + 1] = 0x00;
- name_len2 =
- cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
- to_name, PATH_MAX, cifs_sb->local_nls,
- remap);
- name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
- name_len2 *= 2; /* convert to bytes */
- } else {
- name_len = copy_path_name(pSMB->OldFileName, from_name);
- name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
- pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
- name_len2++; /* signature byte */
- }
-
- count = 1 /* 1st signature byte */ + name_len + name_len2;
- inc_rfc1001_len(pSMB, count);
- pSMB->ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
- if (rc)
- cifs_dbg(FYI, "Send error in rename = %d\n", rc);
-
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto renameRetry;
-
- return rc;
-}
-
-int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
- int netfid, const char *target_name,
- const struct nls_table *nls_codepage, int remap)
-{
- struct smb_com_transaction2_sfi_req *pSMB = NULL;
- struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
- struct set_file_rename *rename_info;
- char *data_offset;
- char dummy_string[30];
- int rc = 0;
- int bytes_returned = 0;
- int len_of_str;
- __u16 params, param_offset, offset, count, byte_count;
-
- cifs_dbg(FYI, "Rename to File by handle\n");
- rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 6;
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
- offset = param_offset + params;
-
- /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
- data_offset = (char *)(pSMB) + offset + 4;
- rename_info = (struct set_file_rename *) data_offset;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
- byte_count = 3 /* pad */ + params;
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- /* construct random name ".cifs_tmp<inodenum><mid>" */
- rename_info->overwrite = cpu_to_le32(1);
- rename_info->root_fid = 0;
- /* unicode only call */
- if (target_name == NULL) {
- sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
- len_of_str =
- cifsConvertToUTF16((__le16 *)rename_info->target_name,
- dummy_string, 24, nls_codepage, remap);
- } else {
- len_of_str =
- cifsConvertToUTF16((__le16 *)rename_info->target_name,
- target_name, PATH_MAX, nls_codepage,
- remap);
- }
- rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
- count = sizeof(struct set_file_rename) + (2 * len_of_str);
- byte_count += count;
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->Fid = netfid;
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
- if (rc)
- cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
- rc);
-
- cifs_buf_release(pSMB);
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
-
- return rc;
-}
-
-int
-CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fromName, const __u16 target_tid, const char *toName,
- const int flags, const struct nls_table *nls_codepage, int remap)
-{
- int rc = 0;
- COPY_REQ *pSMB = NULL;
- COPY_RSP *pSMBr = NULL;
- int bytes_returned;
- int name_len, name_len2;
- __u16 count;
-
- cifs_dbg(FYI, "In CIFSSMBCopy\n");
-copyRetry:
- rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- pSMB->BufferFormat = 0x04;
- pSMB->Tid2 = target_tid;
-
- pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
- fromName, PATH_MAX, nls_codepage,
- remap);
- name_len++; /* trailing null */
- name_len *= 2;
- pSMB->OldFileName[name_len] = 0x04; /* pad */
- /* protocol requires ASCII signature byte on Unicode string */
- pSMB->OldFileName[name_len + 1] = 0x00;
- name_len2 =
- cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
- toName, PATH_MAX, nls_codepage, remap);
- name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
- name_len2 *= 2; /* convert to bytes */
- } else {
- name_len = copy_path_name(pSMB->OldFileName, fromName);
- pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
- name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
- name_len2++; /* signature byte */
- }
-
- count = 1 /* 1st signature byte */ + name_len + name_len2;
- inc_rfc1001_len(pSMB, count);
- pSMB->ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
- rc, le16_to_cpu(pSMBr->CopyCount));
- }
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto copyRetry;
-
- return rc;
-}
-
-int
-CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fromName, const char *toName,
- const struct nls_table *nls_codepage, int remap)
-{
- TRANSACTION2_SPI_REQ *pSMB = NULL;
- TRANSACTION2_SPI_RSP *pSMBr = NULL;
- char *data_offset;
- int name_len;
- int name_len_target;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, param_offset, offset, byte_count;
-
- cifs_dbg(FYI, "In Symlink Unix style\n");
-createSymLinkRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
- /* find define for this maxpathcomponent */
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
-
- } else {
- name_len = copy_path_name(pSMB->FileName, fromName);
- }
- params = 6 + name_len;
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
-
- /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
- data_offset = (char *)pSMB + offset + 4;
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len_target =
- cifsConvertToUTF16((__le16 *) data_offset, toName,
- /* find define for this maxpathcomponent */
- PATH_MAX, nls_codepage, remap);
- name_len_target++; /* trailing null */
- name_len_target *= 2;
- } else {
- name_len_target = copy_path_name(data_offset, toName);
- }
-
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max on data count below from sess */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- byte_count = 3 /* pad */ + params + name_len_target;
- pSMB->DataCount = cpu_to_le16(name_len_target);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
- if (rc)
- cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
- rc);
-
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto createSymLinkRetry;
-
- return rc;
-}
-
-int
-CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fromName, const char *toName,
- const struct nls_table *nls_codepage, int remap)
-{
- TRANSACTION2_SPI_REQ *pSMB = NULL;
- TRANSACTION2_SPI_RSP *pSMBr = NULL;
- char *data_offset;
- int name_len;
- int name_len_target;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, param_offset, offset, byte_count;
-
- cifs_dbg(FYI, "In Create Hard link Unix style\n");
-createHardLinkRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
-
- } else {
- name_len = copy_path_name(pSMB->FileName, toName);
- }
- params = 6 + name_len;
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
-
- /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
- data_offset = (char *)pSMB + offset + 4;
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len_target =
- cifsConvertToUTF16((__le16 *) data_offset, fromName,
- PATH_MAX, nls_codepage, remap);
- name_len_target++; /* trailing null */
- name_len_target *= 2;
- } else {
- name_len_target = copy_path_name(data_offset, fromName);
- }
-
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max on data count below from sess*/
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- byte_count = 3 /* pad */ + params + name_len_target;
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->DataCount = cpu_to_le16(name_len_target);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
- if (rc)
- cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
- rc);
-
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto createHardLinkRetry;
-
- return rc;
-}
-
-int
-CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb)
-{
- int rc = 0;
- NT_RENAME_REQ *pSMB = NULL;
- RENAME_RSP *pSMBr = NULL;
- int bytes_returned;
- int name_len, name_len2;
- __u16 count;
- int remap = cifs_remap(cifs_sb);
-
- cifs_dbg(FYI, "In CIFSCreateHardLink\n");
-winCreateHardLinkRetry:
-
- rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- pSMB->SearchAttributes =
- cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
- ATTR_DIRECTORY);
- pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
- pSMB->ClusterCount = 0;
-
- pSMB->BufferFormat = 0x04;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
- PATH_MAX, cifs_sb->local_nls, remap);
- name_len++; /* trailing null */
- name_len *= 2;
-
- /* protocol specifies ASCII buffer format (0x04) for unicode */
- pSMB->OldFileName[name_len] = 0x04;
- pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
- name_len2 =
- cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
- to_name, PATH_MAX, cifs_sb->local_nls,
- remap);
- name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
- name_len2 *= 2; /* convert to bytes */
- } else {
- name_len = copy_path_name(pSMB->OldFileName, from_name);
- pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
- name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
- name_len2++; /* signature byte */
- }
-
- count = 1 /* string type byte */ + name_len + name_len2;
- inc_rfc1001_len(pSMB, count);
- pSMB->ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
- if (rc)
- cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
-
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto winCreateHardLinkRetry;
-
- return rc;
-}
-
-int
-CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *searchName, char **symlinkinfo,
- const struct nls_table *nls_codepage, int remap)
-{
-/* SMB_QUERY_FILE_UNIX_LINK */
- TRANSACTION2_QPI_REQ *pSMB = NULL;
- TRANSACTION2_QPI_RSP *pSMBr = NULL;
- int rc = 0;
- int bytes_returned;
- int name_len;
- __u16 params, byte_count;
- char *data_start;
-
- cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
-
-querySymLinkRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName,
- searchName, PATH_MAX, nls_codepage,
- remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, searchName);
- }
-
- params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
- } else {
- /* decode response */
-
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- /* BB also check enough total bytes returned */
- if (rc || get_bcc(&pSMBr->hdr) < 2)
- rc = -EIO;
- else {
- bool is_unicode;
- u16 count = le16_to_cpu(pSMBr->t2.DataCount);
-
- data_start = ((char *) &pSMBr->hdr.Protocol) +
- le16_to_cpu(pSMBr->t2.DataOffset);
-
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- is_unicode = true;
- else
- is_unicode = false;
-
- /* BB FIXME investigate remapping reserved chars here */
- *symlinkinfo = cifs_strndup_from_utf16(data_start,
- count, is_unicode, nls_codepage);
- if (!*symlinkinfo)
- rc = -ENOMEM;
- }
- }
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto querySymLinkRetry;
- return rc;
-}
-
-/*
- * Recent Windows versions now create symlinks more frequently
- * and they use the "reparse point" mechanism below. We can of course
- * do symlinks nicely to Samba and other servers which support the
- * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
- * "MF" symlinks optionally, but for recent Windows we really need to
- * reenable the code below and fix the cifs_symlink callers to handle this.
- * In the interim this code has been moved to its own config option so
- * it is not compiled in by default until callers fixed up and more tested.
- */
-int
-CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
- __u16 fid, char **symlinkinfo,
- const struct nls_table *nls_codepage)
-{
- int rc = 0;
- int bytes_returned;
- struct smb_com_transaction_ioctl_req *pSMB;
- struct smb_com_transaction_ioctl_rsp *pSMBr;
- bool is_unicode;
- unsigned int sub_len;
- char *sub_start;
- struct reparse_symlink_data *reparse_buf;
- struct reparse_posix_data *posix_buf;
- __u32 data_offset, data_count;
- char *end_of_smb;
-
- cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
- rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- pSMB->TotalParameterCount = 0 ;
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le32(2);
- /* BB find exact data count max from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
- pSMB->MaxSetupCount = 4;
- pSMB->Reserved = 0;
- pSMB->ParameterOffset = 0;
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 4;
- pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
- pSMB->IsFsctl = 1; /* FSCTL */
- pSMB->IsRootFlag = 0;
- pSMB->Fid = fid; /* file handle always le */
- pSMB->ByteCount = 0;
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
- goto qreparse_out;
- }
-
- data_offset = le32_to_cpu(pSMBr->DataOffset);
- data_count = le32_to_cpu(pSMBr->DataCount);
- if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
- /* BB also check enough total bytes returned */
- rc = -EIO; /* bad smb */
- goto qreparse_out;
- }
- if (!data_count || (data_count > 2048)) {
- rc = -EIO;
- cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
- goto qreparse_out;
- }
- end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
- reparse_buf = (struct reparse_symlink_data *)
- ((char *)&pSMBr->hdr.Protocol + data_offset);
- if ((char *)reparse_buf >= end_of_smb) {
- rc = -EIO;
- goto qreparse_out;
- }
- if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
- cifs_dbg(FYI, "NFS style reparse tag\n");
- posix_buf = (struct reparse_posix_data *)reparse_buf;
-
- if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
- cifs_dbg(FYI, "unsupported file type 0x%llx\n",
- le64_to_cpu(posix_buf->InodeType));
- rc = -EOPNOTSUPP;
- goto qreparse_out;
- }
- is_unicode = true;
- sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
- if (posix_buf->PathBuffer + sub_len > end_of_smb) {
- cifs_dbg(FYI, "reparse buf beyond SMB\n");
- rc = -EIO;
- goto qreparse_out;
- }
- *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
- sub_len, is_unicode, nls_codepage);
- goto qreparse_out;
- } else if (reparse_buf->ReparseTag !=
- cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
- rc = -EOPNOTSUPP;
- goto qreparse_out;
- }
-
- /* Reparse tag is NTFS symlink */
- sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
- reparse_buf->PathBuffer;
- sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
- if (sub_start + sub_len > end_of_smb) {
- cifs_dbg(FYI, "reparse buf beyond SMB\n");
- rc = -EIO;
- goto qreparse_out;
- }
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- is_unicode = true;
- else
- is_unicode = false;
-
- /* BB FIXME investigate remapping reserved chars here */
- *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
- nls_codepage);
- if (!*symlinkinfo)
- rc = -ENOMEM;
-qreparse_out:
- cifs_buf_release(pSMB);
-
- /*
- * Note: On -EAGAIN error only caller can retry on handle based calls
- * since file handle passed in no longer valid.
- */
- return rc;
-}
-
-int
-CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
- __u16 fid)
-{
- int rc = 0;
- int bytes_returned;
- struct smb_com_transaction_compr_ioctl_req *pSMB;
- struct smb_com_transaction_ioctl_rsp *pSMBr;
-
- cifs_dbg(FYI, "Set compression for %u\n", fid);
- rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
-
- pSMB->TotalParameterCount = 0;
- pSMB->TotalDataCount = cpu_to_le32(2);
- pSMB->MaxParameterCount = 0;
- pSMB->MaxDataCount = 0;
- pSMB->MaxSetupCount = 4;
- pSMB->Reserved = 0;
- pSMB->ParameterOffset = 0;
- pSMB->DataCount = cpu_to_le32(2);
- pSMB->DataOffset =
- cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
- compression_state) - 4); /* 84 */
- pSMB->SetupCount = 4;
- pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
- pSMB->ParameterCount = 0;
- pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
- pSMB->IsFsctl = 1; /* FSCTL */
- pSMB->IsRootFlag = 0;
- pSMB->Fid = fid; /* file handle always le */
- /* 3 byte pad, followed by 2 byte compress state */
- pSMB->ByteCount = cpu_to_le16(5);
- inc_rfc1001_len(pSMB, 5);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc)
- cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
-
- cifs_buf_release(pSMB);
-
- /*
- * Note: On -EAGAIN error only caller can retry on handle based calls
- * since file handle passed in no longer valid.
- */
- return rc;
-}
-
-
-#ifdef CONFIG_CIFS_POSIX
-
-/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
-static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
- struct cifs_posix_ace *cifs_ace)
-{
- /* u8 cifs fields do not need le conversion */
- ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
- ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
- ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
-/*
- cifs_dbg(FYI, "perm %d tag %d id %d\n",
- ace->e_perm, ace->e_tag, ace->e_id);
-*/
-
- return;
-}
-
-/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
-static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
- const int acl_type, const int size_of_data_area)
-{
- int size = 0;
- int i;
- __u16 count;
- struct cifs_posix_ace *pACE;
- struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
- struct posix_acl_xattr_header *local_acl = (void *)trgt;
-
- if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
- return -EOPNOTSUPP;
-
- if (acl_type == ACL_TYPE_ACCESS) {
- count = le16_to_cpu(cifs_acl->access_entry_count);
- pACE = &cifs_acl->ace_array[0];
- size = sizeof(struct cifs_posix_acl);
- size += sizeof(struct cifs_posix_ace) * count;
- /* check if we would go beyond end of SMB */
- if (size_of_data_area < size) {
- cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
- size_of_data_area, size);
- return -EINVAL;
- }
- } else if (acl_type == ACL_TYPE_DEFAULT) {
- count = le16_to_cpu(cifs_acl->access_entry_count);
- size = sizeof(struct cifs_posix_acl);
- size += sizeof(struct cifs_posix_ace) * count;
-/* skip past access ACEs to get to default ACEs */
- pACE = &cifs_acl->ace_array[count];
- count = le16_to_cpu(cifs_acl->default_entry_count);
- size += sizeof(struct cifs_posix_ace) * count;
- /* check if we would go beyond end of SMB */
- if (size_of_data_area < size)
- return -EINVAL;
- } else {
- /* illegal type */
- return -EINVAL;
- }
-
- size = posix_acl_xattr_size(count);
- if ((buflen == 0) || (local_acl == NULL)) {
- /* used to query ACL EA size */
- } else if (size > buflen) {
- return -ERANGE;
- } else /* buffer big enough */ {
- struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
-
- local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
- for (i = 0; i < count ; i++) {
- cifs_convert_ace(&ace[i], pACE);
- pACE++;
- }
- }
- return size;
-}
-
-static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
- const struct posix_acl_xattr_entry *local_ace)
-{
- cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
- cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
- /* BB is there a better way to handle the large uid? */
- if (local_ace->e_id == cpu_to_le32(-1)) {
- /* Probably no need to le convert -1 on any arch but can not hurt */
- cifs_ace->cifs_uid = cpu_to_le64(-1);
- } else
- cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
-/*
- cifs_dbg(FYI, "perm %d tag %d id %d\n",
- ace->e_perm, ace->e_tag, ace->e_id);
-*/
-}
-
-/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
-static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
- const int buflen, const int acl_type)
-{
- __u16 rc = 0;
- struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
- struct posix_acl_xattr_header *local_acl = (void *)pACL;
- struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
- int count;
- int i;
-
- if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
- return 0;
-
- count = posix_acl_xattr_count((size_t)buflen);
- cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
- count, buflen, le32_to_cpu(local_acl->a_version));
- if (le32_to_cpu(local_acl->a_version) != 2) {
- cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
- le32_to_cpu(local_acl->a_version));
- return 0;
- }
- cifs_acl->version = cpu_to_le16(1);
- if (acl_type == ACL_TYPE_ACCESS) {
- cifs_acl->access_entry_count = cpu_to_le16(count);
- cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
- } else if (acl_type == ACL_TYPE_DEFAULT) {
- cifs_acl->default_entry_count = cpu_to_le16(count);
- cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
- } else {
- cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
- return 0;
- }
- for (i = 0; i < count; i++)
- convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
- if (rc == 0) {
- rc = (__u16)(count * sizeof(struct cifs_posix_ace));
- rc += sizeof(struct cifs_posix_acl);
- /* BB add check to make sure ACL does not overflow SMB */
- }
- return rc;
-}
-
-int
-CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *searchName,
- char *acl_inf, const int buflen, const int acl_type,
- const struct nls_table *nls_codepage, int remap)
-{
-/* SMB_QUERY_POSIX_ACL */
- TRANSACTION2_QPI_REQ *pSMB = NULL;
- TRANSACTION2_QPI_RSP *pSMBr = NULL;
- int rc = 0;
- int bytes_returned;
- int name_len;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
-
-queryAclRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName,
- searchName, PATH_MAX, nls_codepage,
- remap);
- name_len++; /* trailing null */
- name_len *= 2;
- pSMB->FileName[name_len] = 0;
- pSMB->FileName[name_len+1] = 0;
- } else {
- name_len = copy_path_name(pSMB->FileName, searchName);
- }
-
- params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max data count below from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(4000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(
- offsetof(struct smb_com_transaction2_qpi_req,
- InformationLevel) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
- if (rc) {
- cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
- } else {
- /* decode response */
-
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- /* BB also check enough total bytes returned */
- if (rc || get_bcc(&pSMBr->hdr) < 2)
- rc = -EIO; /* bad smb */
- else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
- rc = cifs_copy_posix_acl(acl_inf,
- (char *)&pSMBr->hdr.Protocol+data_offset,
- buflen, acl_type, count);
- }
- }
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto queryAclRetry;
- return rc;
-}
-
-int
-CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *fileName,
- const char *local_acl, const int buflen,
- const int acl_type,
- const struct nls_table *nls_codepage, int remap)
-{
- struct smb_com_transaction2_spi_req *pSMB = NULL;
- struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
- char *parm_data;
- int name_len;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, byte_count, data_count, param_offset, offset;
-
- cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
-setAclRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, fileName);
- }
- params = 6 + name_len;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find max SMB size from sess */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
- parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
-
- /* convert to on the wire format for POSIX ACL */
- data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
-
- if (data_count == 0) {
- rc = -EOPNOTSUPP;
- goto setACLerrorExit;
- }
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
- byte_count = 3 /* pad */ + params + data_count;
- pSMB->DataCount = cpu_to_le16(data_count);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc)
- cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
-
-setACLerrorExit:
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto setAclRetry;
- return rc;
-}
-
-int
-CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
- const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
-{
- int rc = 0;
- struct smb_t2_qfi_req *pSMB = NULL;
- struct smb_t2_qfi_rsp *pSMBr = NULL;
- int bytes_returned;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In GetExtAttr\n");
- if (tcon == NULL)
- return -ENODEV;
-
-GetExtAttrRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 2 /* level */ + 2 /* fid */;
- pSMB->t2.TotalDataCount = 0;
- pSMB->t2.MaxParameterCount = cpu_to_le16(4);
- /* BB find exact max data count below from sess structure BB */
- pSMB->t2.MaxDataCount = cpu_to_le16(4000);
- pSMB->t2.MaxSetupCount = 0;
- pSMB->t2.Reserved = 0;
- pSMB->t2.Flags = 0;
- pSMB->t2.Timeout = 0;
- pSMB->t2.Reserved2 = 0;
- pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
- Fid) - 4);
- pSMB->t2.DataCount = 0;
- pSMB->t2.DataOffset = 0;
- pSMB->t2.SetupCount = 1;
- pSMB->t2.Reserved3 = 0;
- pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
- byte_count = params + 1 /* pad */ ;
- pSMB->t2.TotalParameterCount = cpu_to_le16(params);
- pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
- pSMB->Pad = 0;
- pSMB->Fid = netfid;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->t2.ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
- } else {
- /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- /* BB also check enough total bytes returned */
- if (rc || get_bcc(&pSMBr->hdr) < 2)
- /* If rc should we check for EOPNOSUPP and
- disable the srvino flag? or in caller? */
- rc = -EIO; /* bad smb */
- else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
- struct file_chattr_info *pfinfo;
-
- if (count != 16) {
- cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
- rc = -EIO;
- goto GetExtAttrOut;
- }
- pfinfo = (struct file_chattr_info *)
- (data_offset + (char *) &pSMBr->hdr.Protocol);
- *pExtAttrBits = le64_to_cpu(pfinfo->mode);
- *pMask = le64_to_cpu(pfinfo->mask);
- }
- }
-GetExtAttrOut:
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto GetExtAttrRetry;
- return rc;
-}
-
-#endif /* CONFIG_POSIX */
-
-/*
- * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
- * all NT TRANSACTS that we init here have total parm and data under about 400
- * bytes (to fit in small cifs buffer size), which is the case so far, it
- * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
- * returned setup area) and MaxParameterCount (returned parms size) must be set
- * by caller
- */
-static int
-smb_init_nttransact(const __u16 sub_command, const int setup_count,
- const int parm_len, struct cifs_tcon *tcon,
- void **ret_buf)
-{
- int rc;
- __u32 temp_offset;
- struct smb_com_ntransact_req *pSMB;
-
- rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
- (void **)&pSMB);
- if (rc)
- return rc;
- *ret_buf = (void *)pSMB;
- pSMB->Reserved = 0;
- pSMB->TotalParameterCount = cpu_to_le32(parm_len);
- pSMB->TotalDataCount = 0;
- pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->DataCount = pSMB->TotalDataCount;
- temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
- (setup_count * 2) - 4 /* for rfc1001 length itself */;
- pSMB->ParameterOffset = cpu_to_le32(temp_offset);
- pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
- pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
- pSMB->SubCommand = cpu_to_le16(sub_command);
- return 0;
-}
-
-static int
-validate_ntransact(char *buf, char **ppparm, char **ppdata,
- __u32 *pparmlen, __u32 *pdatalen)
-{
- char *end_of_smb;
- __u32 data_count, data_offset, parm_count, parm_offset;
- struct smb_com_ntransact_rsp *pSMBr;
- u16 bcc;
-
- *pdatalen = 0;
- *pparmlen = 0;
-
- if (buf == NULL)
- return -EINVAL;
-
- pSMBr = (struct smb_com_ntransact_rsp *)buf;
-
- bcc = get_bcc(&pSMBr->hdr);
- end_of_smb = 2 /* sizeof byte count */ + bcc +
- (char *)&pSMBr->ByteCount;
-
- data_offset = le32_to_cpu(pSMBr->DataOffset);
- data_count = le32_to_cpu(pSMBr->DataCount);
- parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
- parm_count = le32_to_cpu(pSMBr->ParameterCount);
-
- *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
- *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
-
- /* should we also check that parm and data areas do not overlap? */
- if (*ppparm > end_of_smb) {
- cifs_dbg(FYI, "parms start after end of smb\n");
- return -EINVAL;
- } else if (parm_count + *ppparm > end_of_smb) {
- cifs_dbg(FYI, "parm end after end of smb\n");
- return -EINVAL;
- } else if (*ppdata > end_of_smb) {
- cifs_dbg(FYI, "data starts after end of smb\n");
- return -EINVAL;
- } else if (data_count + *ppdata > end_of_smb) {
- cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
- *ppdata, data_count, (data_count + *ppdata),
- end_of_smb, pSMBr);
- return -EINVAL;
- } else if (parm_count + data_count > bcc) {
- cifs_dbg(FYI, "parm count and data count larger than SMB\n");
- return -EINVAL;
- }
- *pdatalen = data_count;
- *pparmlen = parm_count;
- return 0;
-}
-
-/* Get Security Descriptor (by handle) from remote server for a file or dir */
-int
-CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
- struct cifs_ntsd **acl_inf, __u32 *pbuflen)
-{
- int rc = 0;
- int buf_type = 0;
- QUERY_SEC_DESC_REQ *pSMB;
- struct kvec iov[1];
- struct kvec rsp_iov;
-
- cifs_dbg(FYI, "GetCifsACL\n");
-
- *pbuflen = 0;
- *acl_inf = NULL;
-
- rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
- 8 /* parm len */, tcon, (void **) &pSMB);
- if (rc)
- return rc;
-
- pSMB->MaxParameterCount = cpu_to_le32(4);
- /* BB TEST with big acls that might need to be e.g. larger than 16K */
- pSMB->MaxSetupCount = 0;
- pSMB->Fid = fid; /* file handle always le */
- pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
- CIFS_ACL_DACL);
- pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
- inc_rfc1001_len(pSMB, 11);
- iov[0].iov_base = (char *)pSMB;
- iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
-
- rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
- 0, &rsp_iov);
- cifs_small_buf_release(pSMB);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
- if (rc) {
- cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
- } else { /* decode response */
- __le32 *parm;
- __u32 parm_len;
- __u32 acl_len;
- struct smb_com_ntransact_rsp *pSMBr;
- char *pdata;
-
-/* validate_nttransact */
- rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
- &pdata, &parm_len, pbuflen);
- if (rc)
- goto qsec_out;
- pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
-
- cifs_dbg(FYI, "smb %p parm %p data %p\n",
- pSMBr, parm, *acl_inf);
-
- if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
- rc = -EIO; /* bad smb */
- *pbuflen = 0;
- goto qsec_out;
- }
-
-/* BB check that data area is minimum length and as big as acl_len */
-
- acl_len = le32_to_cpu(*parm);
- if (acl_len != *pbuflen) {
- cifs_dbg(VFS, "acl length %d does not match %d\n",
- acl_len, *pbuflen);
- if (*pbuflen > acl_len)
- *pbuflen = acl_len;
- }
-
- /* check if buffer is big enough for the acl
- header followed by the smallest SID */
- if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
- (*pbuflen >= 64 * 1024)) {
- cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
- rc = -EINVAL;
- *pbuflen = 0;
- } else {
- *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
- if (*acl_inf == NULL) {
- *pbuflen = 0;
- rc = -ENOMEM;
- }
- }
- }
-qsec_out:
- free_rsp_buf(buf_type, rsp_iov.iov_base);
- return rc;
-}
-
-int
-CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
- struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
-{
- __u16 byte_count, param_count, data_count, param_offset, data_offset;
- int rc = 0;
- int bytes_returned = 0;
- SET_SEC_DESC_REQ *pSMB = NULL;
- void *pSMBr;
-
-setCifsAclRetry:
- rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
- if (rc)
- return rc;
-
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
-
- param_count = 8;
- param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
- data_count = acllen;
- data_offset = param_offset + param_count;
- byte_count = 3 /* pad */ + param_count;
-
- pSMB->DataCount = cpu_to_le32(data_count);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->MaxParameterCount = cpu_to_le32(4);
- pSMB->MaxDataCount = cpu_to_le32(16384);
- pSMB->ParameterCount = cpu_to_le32(param_count);
- pSMB->ParameterOffset = cpu_to_le32(param_offset);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->DataOffset = cpu_to_le32(data_offset);
- pSMB->SetupCount = 0;
- pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
- pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
-
- pSMB->Fid = fid; /* file handle always le */
- pSMB->Reserved2 = 0;
- pSMB->AclFlags = cpu_to_le32(aclflag);
-
- if (pntsd && acllen) {
- memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
- data_offset, pntsd, acllen);
- inc_rfc1001_len(pSMB, byte_count + data_count);
- } else
- inc_rfc1001_len(pSMB, byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-
- cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
- bytes_returned, rc);
- if (rc)
- cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto setCifsAclRetry;
-
- return (rc);
-}
-
-
-/* Legacy Query Path Information call for lookup to old servers such
- as Win9x/WinME */
-int
-SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
- const char *search_name, FILE_ALL_INFO *data,
- const struct nls_table *nls_codepage, int remap)
-{
- QUERY_INFORMATION_REQ *pSMB;
- QUERY_INFORMATION_RSP *pSMBr;
- int rc = 0;
- int bytes_returned;
- int name_len;
-
- cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
-QInfRetry:
- rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName,
- search_name, PATH_MAX, nls_codepage,
- remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, search_name);
- }
- pSMB->BufferFormat = 0x04;
- name_len++; /* account for buffer type byte */
- inc_rfc1001_len(pSMB, (__u16)name_len);
- pSMB->ByteCount = cpu_to_le16(name_len);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
- } else if (data) {
- struct timespec64 ts;
- __u32 time = le32_to_cpu(pSMBr->last_write_time);
-
- /* decode response */
- /* BB FIXME - add time zone adjustment BB */
- memset(data, 0, sizeof(FILE_ALL_INFO));
- ts.tv_nsec = 0;
- ts.tv_sec = time;
- /* decode time fields */
- data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
- data->LastWriteTime = data->ChangeTime;
- data->LastAccessTime = 0;
- data->AllocationSize =
- cpu_to_le64(le32_to_cpu(pSMBr->size));
- data->EndOfFile = data->AllocationSize;
- data->Attributes =
- cpu_to_le32(le16_to_cpu(pSMBr->attr));
- } else
- rc = -EIO; /* bad buffer passed in */
-
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto QInfRetry;
-
- return rc;
-}
-
-int
-CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
- u16 netfid, FILE_ALL_INFO *pFindData)
-{
- struct smb_t2_qfi_req *pSMB = NULL;
- struct smb_t2_qfi_rsp *pSMBr = NULL;
- int rc = 0;
- int bytes_returned;
- __u16 params, byte_count;
-
-QFileInfoRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 2 /* level */ + 2 /* fid */;
- pSMB->t2.TotalDataCount = 0;
- pSMB->t2.MaxParameterCount = cpu_to_le16(4);
- /* BB find exact max data count below from sess structure BB */
- pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
- pSMB->t2.MaxSetupCount = 0;
- pSMB->t2.Reserved = 0;
- pSMB->t2.Flags = 0;
- pSMB->t2.Timeout = 0;
- pSMB->t2.Reserved2 = 0;
- pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
- Fid) - 4);
- pSMB->t2.DataCount = 0;
- pSMB->t2.DataOffset = 0;
- pSMB->t2.SetupCount = 1;
- pSMB->t2.Reserved3 = 0;
- pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
- byte_count = params + 1 /* pad */ ;
- pSMB->t2.TotalParameterCount = cpu_to_le16(params);
- pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
- pSMB->Pad = 0;
- pSMB->Fid = netfid;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->t2.ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc) /* BB add auto retry on EOPNOTSUPP? */
- rc = -EIO;
- else if (get_bcc(&pSMBr->hdr) < 40)
- rc = -EIO; /* bad smb */
- else if (pFindData) {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- memcpy((char *) pFindData,
- (char *) &pSMBr->hdr.Protocol +
- data_offset, sizeof(FILE_ALL_INFO));
- } else
- rc = -ENOMEM;
- }
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto QFileInfoRetry;
-
- return rc;
-}
-
-int
-CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const char *search_name, FILE_ALL_INFO *data,
- int legacy /* old style infolevel */,
- const struct nls_table *nls_codepage, int remap)
-{
- /* level 263 SMB_QUERY_FILE_ALL_INFO */
- TRANSACTION2_QPI_REQ *pSMB = NULL;
- TRANSACTION2_QPI_RSP *pSMBr = NULL;
- int rc = 0;
- int bytes_returned;
- int name_len;
- __u16 params, byte_count;
-
- /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
-QPathInfoRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, search_name);
- }
-
- params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(4000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- if (legacy)
- pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
- else
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc) /* BB add auto retry on EOPNOTSUPP? */
- rc = -EIO;
- else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
- rc = -EIO; /* bad smb */
- else if (legacy && get_bcc(&pSMBr->hdr) < 24)
- rc = -EIO; /* 24 or 26 expected but we do not read
- last field */
- else if (data) {
- int size;
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
-
- /*
- * On legacy responses we do not read the last field,
- * EAsize, fortunately since it varies by subdialect and
- * also note it differs on Set vs Get, ie two bytes or 4
- * bytes depending but we don't care here.
- */
- if (legacy)
- size = sizeof(FILE_INFO_STANDARD);
- else
- size = sizeof(FILE_ALL_INFO);
- memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
- data_offset, size);
- } else
- rc = -ENOMEM;
- }
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto QPathInfoRetry;
-
- return rc;
-}
-
-int
-CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
- u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
-{
- struct smb_t2_qfi_req *pSMB = NULL;
- struct smb_t2_qfi_rsp *pSMBr = NULL;
- int rc = 0;
- int bytes_returned;
- __u16 params, byte_count;
-
-UnixQFileInfoRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 2 /* level */ + 2 /* fid */;
- pSMB->t2.TotalDataCount = 0;
- pSMB->t2.MaxParameterCount = cpu_to_le16(4);
- /* BB find exact max data count below from sess structure BB */
- pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
- pSMB->t2.MaxSetupCount = 0;
- pSMB->t2.Reserved = 0;
- pSMB->t2.Flags = 0;
- pSMB->t2.Timeout = 0;
- pSMB->t2.Reserved2 = 0;
- pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
- Fid) - 4);
- pSMB->t2.DataCount = 0;
- pSMB->t2.DataOffset = 0;
- pSMB->t2.SetupCount = 1;
- pSMB->t2.Reserved3 = 0;
- pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
- byte_count = params + 1 /* pad */ ;
- pSMB->t2.TotalParameterCount = cpu_to_le16(params);
- pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
- pSMB->Pad = 0;
- pSMB->Fid = netfid;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->t2.ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
- cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
- rc = -EIO; /* bad smb */
- } else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- memcpy((char *) pFindData,
- (char *) &pSMBr->hdr.Protocol +
- data_offset,
- sizeof(FILE_UNIX_BASIC_INFO));
- }
- }
-
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto UnixQFileInfoRetry;
-
- return rc;
-}
-
-int
-CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *searchName,
- FILE_UNIX_BASIC_INFO *pFindData,
- const struct nls_table *nls_codepage, int remap)
-{
-/* SMB_QUERY_FILE_UNIX_BASIC */
- TRANSACTION2_QPI_REQ *pSMB = NULL;
- TRANSACTION2_QPI_RSP *pSMBr = NULL;
- int rc = 0;
- int bytes_returned = 0;
- int name_len;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
-UnixQPathInfoRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, searchName);
- }
-
- params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(4000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
- cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
- rc = -EIO; /* bad smb */
- } else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- memcpy((char *) pFindData,
- (char *) &pSMBr->hdr.Protocol +
- data_offset,
- sizeof(FILE_UNIX_BASIC_INFO));
- }
- }
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto UnixQPathInfoRetry;
-
- return rc;
-}
-
-/* xid, tcon, searchName and codepage are input parms, rest are returned */
-int
-CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
- const char *searchName, struct cifs_sb_info *cifs_sb,
- __u16 *pnetfid, __u16 search_flags,
- struct cifs_search_info *psrch_inf, bool msearch)
-{
-/* level 257 SMB_ */
- TRANSACTION2_FFIRST_REQ *pSMB = NULL;
- TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
- T2_FFIRST_RSP_PARMS *parms;
- int rc = 0;
- int bytes_returned = 0;
- int name_len, remap;
- __u16 params, byte_count;
- struct nls_table *nls_codepage;
-
- cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
-
-findFirstRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- nls_codepage = cifs_sb->local_nls;
- remap = cifs_remap(cifs_sb);
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
- /* We can not add the asterik earlier in case
- it got remapped to 0xF03A as if it were part of the
- directory name instead of a wildcard */
- name_len *= 2;
- if (msearch) {
- pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
- pSMB->FileName[name_len+1] = 0;
- pSMB->FileName[name_len+2] = '*';
- pSMB->FileName[name_len+3] = 0;
- name_len += 4; /* now the trailing null */
- /* null terminate just in case */
- pSMB->FileName[name_len] = 0;
- pSMB->FileName[name_len+1] = 0;
- name_len += 2;
- }
- } else {
- name_len = copy_path_name(pSMB->FileName, searchName);
- if (msearch) {
- if (WARN_ON_ONCE(name_len > PATH_MAX-2))
- name_len = PATH_MAX-2;
- /* overwrite nul byte */
- pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
- pSMB->FileName[name_len] = '*';
- pSMB->FileName[name_len+1] = 0;
- name_len += 2;
- }
- }
-
- params = 12 + name_len /* includes null */ ;
- pSMB->TotalDataCount = 0; /* no EAs */
- pSMB->MaxParameterCount = cpu_to_le16(10);
- pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(
- offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
- - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
- pSMB->SearchAttributes =
- cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
- ATTR_DIRECTORY);
- pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
- pSMB->SearchFlags = cpu_to_le16(search_flags);
- pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
-
- /* BB what should we set StorageType to? Does it matter? BB */
- pSMB->SearchStorageType = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
-
- if (rc) {/* BB add logic to retry regular search if Unix search
- rejected unexpectedly by server */
- /* BB Add code to handle unsupported level rc */
- cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
-
- cifs_buf_release(pSMB);
-
- /* BB eventually could optimize out free and realloc of buf */
- /* for this case */
- if (rc == -EAGAIN)
- goto findFirstRetry;
- } else { /* decode response */
- /* BB remember to free buffer if error BB */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if (rc == 0) {
- unsigned int lnoff;
-
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- psrch_inf->unicode = true;
- else
- psrch_inf->unicode = false;
-
- psrch_inf->ntwrk_buf_start = (char *)pSMBr;
- psrch_inf->smallBuf = false;
- psrch_inf->srch_entries_start =
- (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->t2.DataOffset);
- parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->t2.ParameterOffset));
-
- if (parms->EndofSearch)
- psrch_inf->endOfSearch = true;
- else
- psrch_inf->endOfSearch = false;
-
- psrch_inf->entries_in_buffer =
- le16_to_cpu(parms->SearchCount);
- psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
- psrch_inf->entries_in_buffer;
- lnoff = le16_to_cpu(parms->LastNameOffset);
- if (CIFSMaxBufSize < lnoff) {
- cifs_dbg(VFS, "ignoring corrupt resume name\n");
- psrch_inf->last_entry = NULL;
- return rc;
- }
-
- psrch_inf->last_entry = psrch_inf->srch_entries_start +
- lnoff;
-
- if (pnetfid)
- *pnetfid = parms->SearchHandle;
- } else {
- cifs_buf_release(pSMB);
- }
- }
-
- return rc;
-}
-
-int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
- __u16 searchHandle, __u16 search_flags,
- struct cifs_search_info *psrch_inf)
-{
- TRANSACTION2_FNEXT_REQ *pSMB = NULL;
- TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
- T2_FNEXT_RSP_PARMS *parms;
- char *response_data;
- int rc = 0;
- int bytes_returned;
- unsigned int name_len;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In FindNext\n");
-
- if (psrch_inf->endOfSearch)
- return -ENOENT;
-
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 14; /* includes 2 bytes of null string, converted to LE below*/
- byte_count = 0;
- pSMB->TotalDataCount = 0; /* no EAs */
- pSMB->MaxParameterCount = cpu_to_le16(8);
- pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(
- offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
- pSMB->SearchHandle = searchHandle; /* always kept as le */
- pSMB->SearchCount =
- cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
- pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
- pSMB->ResumeKey = psrch_inf->resume_key;
- pSMB->SearchFlags = cpu_to_le16(search_flags);
-
- name_len = psrch_inf->resume_name_len;
- params += name_len;
- if (name_len < PATH_MAX) {
- memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
- byte_count += name_len;
- /* 14 byte parm len above enough for 2 byte null terminator */
- pSMB->ResumeFileName[name_len] = 0;
- pSMB->ResumeFileName[name_len+1] = 0;
- } else {
- rc = -EINVAL;
- goto FNext2_err_exit;
- }
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
- if (rc) {
- if (rc == -EBADF) {
- psrch_inf->endOfSearch = true;
- cifs_buf_release(pSMB);
- rc = 0; /* search probably was closed at end of search*/
- } else
- cifs_dbg(FYI, "FindNext returned = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc == 0) {
- unsigned int lnoff;
-
- /* BB fixme add lock for file (srch_info) struct here */
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- psrch_inf->unicode = true;
- else
- psrch_inf->unicode = false;
- response_data = (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->t2.ParameterOffset);
- parms = (T2_FNEXT_RSP_PARMS *)response_data;
- response_data = (char *)&pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->t2.DataOffset);
- if (psrch_inf->smallBuf)
- cifs_small_buf_release(
- psrch_inf->ntwrk_buf_start);
- else
- cifs_buf_release(psrch_inf->ntwrk_buf_start);
- psrch_inf->srch_entries_start = response_data;
- psrch_inf->ntwrk_buf_start = (char *)pSMB;
- psrch_inf->smallBuf = false;
- if (parms->EndofSearch)
- psrch_inf->endOfSearch = true;
- else
- psrch_inf->endOfSearch = false;
- psrch_inf->entries_in_buffer =
- le16_to_cpu(parms->SearchCount);
- psrch_inf->index_of_last_entry +=
- psrch_inf->entries_in_buffer;
- lnoff = le16_to_cpu(parms->LastNameOffset);
- if (CIFSMaxBufSize < lnoff) {
- cifs_dbg(VFS, "ignoring corrupt resume name\n");
- psrch_inf->last_entry = NULL;
- return rc;
- } else
- psrch_inf->last_entry =
- psrch_inf->srch_entries_start + lnoff;
-
-/* cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
- psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
-
- /* BB fixme add unlock here */
- }
-
- }
-
- /* BB On error, should we leave previous search buf (and count and
- last entry fields) intact or free the previous one? */
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
-FNext2_err_exit:
- if (rc != 0)
- cifs_buf_release(pSMB);
- return rc;
-}
-
-int
-CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
- const __u16 searchHandle)
-{
- int rc = 0;
- FINDCLOSE_REQ *pSMB = NULL;
-
- cifs_dbg(FYI, "In CIFSSMBFindClose\n");
- rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
-
- /* no sense returning error if session restarted
- as file handle has been closed */
- if (rc == -EAGAIN)
- return 0;
- if (rc)
- return rc;
-
- pSMB->FileID = searchHandle;
- pSMB->ByteCount = 0;
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
- cifs_small_buf_release(pSMB);
- if (rc)
- cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
-
- cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
-
- /* Since session is dead, search handle closed on server already */
- if (rc == -EAGAIN)
- rc = 0;
-
- return rc;
-}
-
-int
-CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
- const char *search_name, __u64 *inode_number,
- const struct nls_table *nls_codepage, int remap)
-{
- int rc = 0;
- TRANSACTION2_QPI_REQ *pSMB = NULL;
- TRANSACTION2_QPI_RSP *pSMBr = NULL;
- int name_len, bytes_returned;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
- if (tcon == NULL)
- return -ENODEV;
-
-GetInodeNumberRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName,
- search_name, PATH_MAX, nls_codepage,
- remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, search_name);
- }
-
- params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max data count below from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(4000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
- } else {
- /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- /* BB also check enough total bytes returned */
- if (rc || get_bcc(&pSMBr->hdr) < 2)
- /* If rc should we check for EOPNOSUPP and
- disable the srvino flag? or in caller? */
- rc = -EIO; /* bad smb */
- else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
- struct file_internal_info *pfinfo;
- /* BB Do we need a cast or hash here ? */
- if (count < 8) {
- cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
- rc = -EIO;
- goto GetInodeNumOut;
- }
- pfinfo = (struct file_internal_info *)
- (data_offset + (char *) &pSMBr->hdr.Protocol);
- *inode_number = le64_to_cpu(pfinfo->UniqueId);
- }
- }
-GetInodeNumOut:
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto GetInodeNumberRetry;
- return rc;
-}
-
-int
-CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
- const char *search_name, struct dfs_info3_param **target_nodes,
- unsigned int *num_of_nodes,
- const struct nls_table *nls_codepage, int remap)
-{
-/* TRANS2_GET_DFS_REFERRAL */
- TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
- TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
- int rc = 0;
- int bytes_returned;
- int name_len;
- __u16 params, byte_count;
- *num_of_nodes = 0;
- *target_nodes = NULL;
-
- cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
- if (ses == NULL || ses->tcon_ipc == NULL)
- return -ENODEV;
-
-getDFSRetry:
- /*
- * Use smb_init_no_reconnect() instead of smb_init() as
- * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
- * causing an infinite recursion.
- */
- rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
- (void **)&pSMB, (void **)&pSMBr);
- if (rc)
- return rc;
-
- /* server pointer checked in called function,
- but should never be null here anyway */
- pSMB->hdr.Mid = get_next_mid(ses->server);
- pSMB->hdr.Tid = ses->tcon_ipc->tid;
- pSMB->hdr.Uid = ses->Suid;
- if (ses->capabilities & CAP_STATUS32)
- pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
- if (ses->capabilities & CAP_DFS)
- pSMB->hdr.Flags2 |= SMBFLG2_DFS;
-
- if (ses->capabilities & CAP_UNICODE) {
- pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
- search_name, PATH_MAX, nls_codepage,
- remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = copy_path_name(pSMB->RequestFileName, search_name);
- }
-
- if (ses->server->sign)
- pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- pSMB->hdr.Uid = ses->Suid;
-
- params = 2 /* level */ + name_len /*includes null */ ;
- pSMB->TotalDataCount = 0;
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->MaxParameterCount = 0;
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(4000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
- byte_count = params + 3 /* pad */ ;
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->MaxReferralLevel = cpu_to_le16(3);
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
- goto GetDFSRefExit;
- }
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- /* BB Also check if enough total bytes returned? */
- if (rc || get_bcc(&pSMBr->hdr) < 17) {
- rc = -EIO; /* bad smb */
- goto GetDFSRefExit;
- }
-
- cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
- get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
-
- /* parse returned result into more usable form */
- rc = parse_dfs_referrals(&pSMBr->dfs_data,
- le16_to_cpu(pSMBr->t2.DataCount),
- num_of_nodes, target_nodes, nls_codepage,
- remap, search_name,
- (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
-
-GetDFSRefExit:
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto getDFSRetry;
-
- return rc;
-}
-
-/* Query File System Info such as free space to old servers such as Win 9x */
-int
-SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
- struct kstatfs *FSData)
-{
-/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
- TRANSACTION2_QFSI_REQ *pSMB = NULL;
- TRANSACTION2_QFSI_RSP *pSMBr = NULL;
- FILE_SYSTEM_ALLOC_INFO *response_data;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "OldQFSInfo\n");
-oldQFSInfoRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 2; /* level */
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
- pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) < 18)
- rc = -EIO; /* bad smb */
- else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
- get_bcc(&pSMBr->hdr), data_offset);
-
- response_data = (FILE_SYSTEM_ALLOC_INFO *)
- (((char *) &pSMBr->hdr.Protocol) + data_offset);
- FSData->f_bsize =
- le16_to_cpu(response_data->BytesPerSector) *
- le32_to_cpu(response_data->
- SectorsPerAllocationUnit);
- /*
- * much prefer larger but if server doesn't report
- * a valid size than 4K is a reasonable minimum
- */
- if (FSData->f_bsize < 512)
- FSData->f_bsize = 4096;
-
- FSData->f_blocks =
- le32_to_cpu(response_data->TotalAllocationUnits);
- FSData->f_bfree = FSData->f_bavail =
- le32_to_cpu(response_data->FreeAllocationUnits);
- cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
- (unsigned long long)FSData->f_blocks,
- (unsigned long long)FSData->f_bfree,
- FSData->f_bsize);
- }
- }
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto oldQFSInfoRetry;
-
- return rc;
-}
-
-int
-CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
- struct kstatfs *FSData)
-{
-/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
- TRANSACTION2_QFSI_REQ *pSMB = NULL;
- TRANSACTION2_QFSI_RSP *pSMBr = NULL;
- FILE_SYSTEM_INFO *response_data;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In QFSInfo\n");
-QFSInfoRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 2; /* level */
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) < 24)
- rc = -EIO; /* bad smb */
- else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
-
- response_data =
- (FILE_SYSTEM_INFO
- *) (((char *) &pSMBr->hdr.Protocol) +
- data_offset);
- FSData->f_bsize =
- le32_to_cpu(response_data->BytesPerSector) *
- le32_to_cpu(response_data->
- SectorsPerAllocationUnit);
- /*
- * much prefer larger but if server doesn't report
- * a valid size than 4K is a reasonable minimum
- */
- if (FSData->f_bsize < 512)
- FSData->f_bsize = 4096;
-
- FSData->f_blocks =
- le64_to_cpu(response_data->TotalAllocationUnits);
- FSData->f_bfree = FSData->f_bavail =
- le64_to_cpu(response_data->FreeAllocationUnits);
- cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
- (unsigned long long)FSData->f_blocks,
- (unsigned long long)FSData->f_bfree,
- FSData->f_bsize);
- }
- }
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto QFSInfoRetry;
-
- return rc;
-}
-
-int
-CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
-{
-/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
- TRANSACTION2_QFSI_REQ *pSMB = NULL;
- TRANSACTION2_QFSI_RSP *pSMBr = NULL;
- FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In QFSAttributeInfo\n");
-QFSAttributeRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 2; /* level */
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) < 13) {
- /* BB also check if enough bytes returned */
- rc = -EIO; /* bad smb */
- } else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- response_data =
- (FILE_SYSTEM_ATTRIBUTE_INFO
- *) (((char *) &pSMBr->hdr.Protocol) +
- data_offset);
- memcpy(&tcon->fsAttrInfo, response_data,
- sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
- }
- }
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto QFSAttributeRetry;
-
- return rc;
-}
-
-int
-CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
-{
-/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
- TRANSACTION2_QFSI_REQ *pSMB = NULL;
- TRANSACTION2_QFSI_RSP *pSMBr = NULL;
- FILE_SYSTEM_DEVICE_INFO *response_data;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In QFSDeviceInfo\n");
-QFSDeviceRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 2; /* level */
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
-
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) <
- sizeof(FILE_SYSTEM_DEVICE_INFO))
- rc = -EIO; /* bad smb */
- else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- response_data =
- (FILE_SYSTEM_DEVICE_INFO *)
- (((char *) &pSMBr->hdr.Protocol) +
- data_offset);
- memcpy(&tcon->fsDevInfo, response_data,
- sizeof(FILE_SYSTEM_DEVICE_INFO));
- }
- }
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto QFSDeviceRetry;
-
- return rc;
-}
-
-int
-CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
-{
-/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
- TRANSACTION2_QFSI_REQ *pSMB = NULL;
- TRANSACTION2_QFSI_RSP *pSMBr = NULL;
- FILE_SYSTEM_UNIX_INFO *response_data;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In QFSUnixInfo\n");
-QFSUnixRetry:
- rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
- (void **) &pSMB, (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 2; /* level */
- pSMB->TotalDataCount = 0;
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(100);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- byte_count = params + 1 /* pad */ ;
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
- smb_com_transaction2_qfsi_req, InformationLevel) - 4);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) < 13) {
- rc = -EIO; /* bad smb */
- } else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- response_data =
- (FILE_SYSTEM_UNIX_INFO
- *) (((char *) &pSMBr->hdr.Protocol) +
- data_offset);
- memcpy(&tcon->fsUnixInfo, response_data,
- sizeof(FILE_SYSTEM_UNIX_INFO));
- }
- }
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto QFSUnixRetry;
-
-
- return rc;
-}
-
-int
-CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
-{
-/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
- TRANSACTION2_SETFSI_REQ *pSMB = NULL;
- TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, param_offset, offset, byte_count;
-
- cifs_dbg(FYI, "In SETFSUnixInfo\n");
-SETFSUnixRetry:
- /* BB switch to small buf init to save memory */
- rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
- (void **) &pSMB, (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 4; /* 2 bytes zero followed by info level. */
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
- - 4;
- offset = param_offset + params;
-
- pSMB->MaxParameterCount = cpu_to_le16(4);
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(100);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
- byte_count = 1 /* pad */ + params + 12;
-
- pSMB->DataCount = cpu_to_le16(12);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
-
- /* Params. */
- pSMB->FileNum = 0;
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
-
- /* Data. */
- pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
- pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
- pSMB->ClientUnixCap = cpu_to_le64(cap);
-
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if (rc)
- rc = -EIO; /* bad smb */
- }
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto SETFSUnixRetry;
-
- return rc;
-}
-
-
-
-int
-CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
- struct kstatfs *FSData)
-{
-/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
- TRANSACTION2_QFSI_REQ *pSMB = NULL;
- TRANSACTION2_QFSI_RSP *pSMBr = NULL;
- FILE_SYSTEM_POSIX_INFO *response_data;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, byte_count;
-
- cifs_dbg(FYI, "In QFSPosixInfo\n");
-QFSPosixRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 2; /* level */
- pSMB->TotalDataCount = 0;
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(100);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- byte_count = params + 1 /* pad */ ;
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
- smb_com_transaction2_qfsi_req, InformationLevel) - 4);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- if (rc || get_bcc(&pSMBr->hdr) < 13) {
- rc = -EIO; /* bad smb */
- } else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- response_data =
- (FILE_SYSTEM_POSIX_INFO
- *) (((char *) &pSMBr->hdr.Protocol) +
- data_offset);
- FSData->f_bsize =
- le32_to_cpu(response_data->BlockSize);
- /*
- * much prefer larger but if server doesn't report
- * a valid size than 4K is a reasonable minimum
- */
- if (FSData->f_bsize < 512)
- FSData->f_bsize = 4096;
-
- FSData->f_blocks =
- le64_to_cpu(response_data->TotalBlocks);
- FSData->f_bfree =
- le64_to_cpu(response_data->BlocksAvail);
- if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
- FSData->f_bavail = FSData->f_bfree;
- } else {
- FSData->f_bavail =
- le64_to_cpu(response_data->UserBlocksAvail);
- }
- if (response_data->TotalFileNodes != cpu_to_le64(-1))
- FSData->f_files =
- le64_to_cpu(response_data->TotalFileNodes);
- if (response_data->FreeFileNodes != cpu_to_le64(-1))
- FSData->f_ffree =
- le64_to_cpu(response_data->FreeFileNodes);
- }
- }
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto QFSPosixRetry;
-
- return rc;
-}
-
-
-/*
- * We can not use write of zero bytes trick to set file size due to need for
- * large file support. Also note that this SetPathInfo is preferred to
- * SetFileInfo based method in next routine which is only needed to work around
- * a sharing violation bugin Samba which this routine can run into.
- */
-int
-CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
- const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
- bool set_allocation)
-{
- struct smb_com_transaction2_spi_req *pSMB = NULL;
- struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
- struct file_end_of_file_info *parm_data;
- int name_len;
- int rc = 0;
- int bytes_returned = 0;
- int remap = cifs_remap(cifs_sb);
-
- __u16 params, byte_count, data_count, param_offset, offset;
-
- cifs_dbg(FYI, "In SetEOF\n");
-SetEOFRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
- PATH_MAX, cifs_sb->local_nls, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, file_name);
- }
- params = 6 + name_len;
- data_count = sizeof(struct file_end_of_file_info);
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(4100);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
- if (set_allocation) {
- if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
- else
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
- } else /* Set File Size */ {
- if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
- else
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
- }
-
- parm_data =
- (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
- offset);
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- byte_count = 3 /* pad */ + params + data_count;
- pSMB->DataCount = cpu_to_le16(data_count);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- parm_data->FileSize = cpu_to_le64(size);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc)
- cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
-
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto SetEOFRetry;
-
- return rc;
-}
-
-int
-CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
-{
- struct smb_com_transaction2_sfi_req *pSMB = NULL;
- struct file_end_of_file_info *parm_data;
- int rc = 0;
- __u16 params, param_offset, offset, byte_count, count;
-
- cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
- (long long)size);
- rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
-
- if (rc)
- return rc;
-
- pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
- pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
-
- params = 6;
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
- offset = param_offset + params;
-
- count = sizeof(struct file_end_of_file_info);
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
- byte_count = 3 /* pad */ + params + count;
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
- parm_data =
- (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);
- pSMB->DataOffset = cpu_to_le16(offset);
- parm_data->FileSize = cpu_to_le64(size);
- pSMB->Fid = cfile->fid.netfid;
- if (set_allocation) {
- if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
- else
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
- } else /* Set File Size */ {
- if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
- else
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
- }
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
- cifs_small_buf_release(pSMB);
- if (rc) {
- cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
- rc);
- }
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
-
- return rc;
-}
-
-/* Some legacy servers such as NT4 require that the file times be set on
- an open handle, rather than by pathname - this is awkward due to
- potential access conflicts on the open, but it is unavoidable for these
- old servers since the only other choice is to go from 100 nanosecond DCE
- time and resort to the original setpathinfo level which takes the ancient
- DOS time format with 2 second granularity */
-int
-CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
-{
- struct smb_com_transaction2_sfi_req *pSMB = NULL;
- char *data_offset;
- int rc = 0;
- __u16 params, param_offset, offset, byte_count, count;
-
- cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
- rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
-
- if (rc)
- return rc;
-
- pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
- pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
-
- params = 6;
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
- offset = param_offset + params;
-
- data_offset = (char *)pSMB +
- offsetof(struct smb_hdr, Protocol) + offset;
-
- count = sizeof(FILE_BASIC_INFO);
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find max SMB PDU from sess */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
- byte_count = 3 /* pad */ + params + count;
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->Fid = fid;
- if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
- else
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
- cifs_small_buf_release(pSMB);
- if (rc)
- cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
- rc);
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
-
- return rc;
-}
-
-int
-CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
- bool delete_file, __u16 fid, __u32 pid_of_opener)
-{
- struct smb_com_transaction2_sfi_req *pSMB = NULL;
- char *data_offset;
- int rc = 0;
- __u16 params, param_offset, offset, byte_count, count;
-
- cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
- rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
-
- if (rc)
- return rc;
-
- pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
- pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
-
- params = 6;
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
- offset = param_offset + params;
-
- /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
- data_offset = (char *)(pSMB) + offset + 4;
-
- count = 1;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find max SMB PDU from sess */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
- byte_count = 3 /* pad */ + params + count;
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->Fid = fid;
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- *data_offset = delete_file ? 1 : 0;
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
- cifs_small_buf_release(pSMB);
- if (rc)
- cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
-
- return rc;
-}
-
-static int
-CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fileName, const FILE_BASIC_INFO *data,
- const struct nls_table *nls_codepage,
- struct cifs_sb_info *cifs_sb)
-{
- int oplock = 0;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
- int rc;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = GENERIC_WRITE,
- .create_options = cifs_create_options(cifs_sb, 0),
- .disposition = FILE_OPEN,
- .path = fileName,
- .fid = &fid,
- };
-
- rc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (rc)
- goto out;
-
- rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
- CIFSSMBClose(xid, tcon, fid.netfid);
-out:
-
- return rc;
-}
-
-int
-CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fileName, const FILE_BASIC_INFO *data,
- const struct nls_table *nls_codepage,
- struct cifs_sb_info *cifs_sb)
-{
- TRANSACTION2_SPI_REQ *pSMB = NULL;
- TRANSACTION2_SPI_RSP *pSMBr = NULL;
- int name_len;
- int rc = 0;
- int bytes_returned = 0;
- char *data_offset;
- __u16 params, param_offset, offset, byte_count, count;
- int remap = cifs_remap(cifs_sb);
-
- cifs_dbg(FYI, "In SetTimes\n");
-
-SetTimesRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, fileName);
- }
-
- params = 6 + name_len;
- count = sizeof(FILE_BASIC_INFO);
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
- data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- byte_count = 3 /* pad */ + params + count;
-
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
- else
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc)
- cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
-
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto SetTimesRetry;
-
- if (rc == -EOPNOTSUPP)
- return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
- nls_codepage, cifs_sb);
-
- return rc;
-}
-
-static void
-cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
- const struct cifs_unix_set_info_args *args)
-{
- u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
- u64 mode = args->mode;
-
- if (uid_valid(args->uid))
- uid = from_kuid(&init_user_ns, args->uid);
- if (gid_valid(args->gid))
- gid = from_kgid(&init_user_ns, args->gid);
-
- /*
- * Samba server ignores set of file size to zero due to bugs in some
- * older clients, but we should be precise - we use SetFileSize to
- * set file size and do not want to truncate file size to zero
- * accidentally as happened on one Samba server beta by putting
- * zero instead of -1 here
- */
- data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
- data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
- data_offset->LastStatusChange = cpu_to_le64(args->ctime);
- data_offset->LastAccessTime = cpu_to_le64(args->atime);
- data_offset->LastModificationTime = cpu_to_le64(args->mtime);
- data_offset->Uid = cpu_to_le64(uid);
- data_offset->Gid = cpu_to_le64(gid);
- /* better to leave device as zero when it is */
- data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
- data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
- data_offset->Permissions = cpu_to_le64(mode);
-
- if (S_ISREG(mode))
- data_offset->Type = cpu_to_le32(UNIX_FILE);
- else if (S_ISDIR(mode))
- data_offset->Type = cpu_to_le32(UNIX_DIR);
- else if (S_ISLNK(mode))
- data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
- else if (S_ISCHR(mode))
- data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
- else if (S_ISBLK(mode))
- data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
- else if (S_ISFIFO(mode))
- data_offset->Type = cpu_to_le32(UNIX_FIFO);
- else if (S_ISSOCK(mode))
- data_offset->Type = cpu_to_le32(UNIX_SOCKET);
-}
-
-int
-CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const struct cifs_unix_set_info_args *args,
- u16 fid, u32 pid_of_opener)
-{
- struct smb_com_transaction2_sfi_req *pSMB = NULL;
- char *data_offset;
- int rc = 0;
- u16 params, param_offset, offset, byte_count, count;
-
- cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
- rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
-
- if (rc)
- return rc;
-
- pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
- pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
-
- params = 6;
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
- offset = param_offset + params;
-
- data_offset = (char *)pSMB +
- offsetof(struct smb_hdr, Protocol) + offset;
-
- count = sizeof(FILE_UNIX_BASIC_INFO);
-
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find max SMB PDU from sess */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
- byte_count = 3 /* pad */ + params + count;
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->Fid = fid;
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
-
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
- cifs_small_buf_release(pSMB);
- if (rc)
- cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
- rc);
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
-
- return rc;
-}
-
-int
-CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const char *file_name,
- const struct cifs_unix_set_info_args *args,
- const struct nls_table *nls_codepage, int remap)
-{
- TRANSACTION2_SPI_REQ *pSMB = NULL;
- TRANSACTION2_SPI_RSP *pSMBr = NULL;
- int name_len;
- int rc = 0;
- int bytes_returned = 0;
- FILE_UNIX_BASIC_INFO *data_offset;
- __u16 params, param_offset, offset, count, byte_count;
-
- cifs_dbg(FYI, "In SetUID/GID/Mode\n");
-setPermsRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, file_name);
- }
-
- params = 6 + name_len;
- count = sizeof(FILE_UNIX_BASIC_INFO);
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
- /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
- data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);
- memset(data_offset, 0, count);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- byte_count = 3 /* pad */ + params + count;
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->DataCount = cpu_to_le16(count);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
-
- cifs_fill_unix_set_info(data_offset, args);
-
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc)
- cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
-
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto setPermsRetry;
- return rc;
-}
-
-#ifdef CONFIG_CIFS_XATTR
-/*
- * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
- * function used by listxattr and getxattr type calls. When ea_name is set,
- * it looks for that attribute name and stuffs that value into the EAData
- * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
- * buffer. In both cases, the return value is either the length of the
- * resulting data or a negative error code. If EAData is a NULL pointer then
- * the data isn't copied to it, but the length is returned.
- */
-ssize_t
-CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *searchName, const unsigned char *ea_name,
- char *EAData, size_t buf_size,
- struct cifs_sb_info *cifs_sb)
-{
- /* BB assumes one setup word */
- TRANSACTION2_QPI_REQ *pSMB = NULL;
- TRANSACTION2_QPI_RSP *pSMBr = NULL;
- int remap = cifs_remap(cifs_sb);
- struct nls_table *nls_codepage = cifs_sb->local_nls;
- int rc = 0;
- int bytes_returned;
- int list_len;
- struct fealist *ea_response_data;
- struct fea *temp_fea;
- char *temp_ptr;
- char *end_of_smb;
- __u16 params, byte_count, data_offset;
- unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
-
- cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
-QAllEAsRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- list_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
- PATH_MAX, nls_codepage, remap);
- list_len++; /* trailing null */
- list_len *= 2;
- } else {
- list_len = copy_path_name(pSMB->FileName, searchName);
- }
-
- params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find exact max SMB PDU from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(offsetof(
- struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
- goto QAllEAsOut;
- }
-
-
- /* BB also check enough total bytes returned */
- /* BB we need to improve the validity checking
- of these trans2 responses */
-
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if (rc || get_bcc(&pSMBr->hdr) < 4) {
- rc = -EIO; /* bad smb */
- goto QAllEAsOut;
- }
-
- /* check that length of list is not more than bcc */
- /* check that each entry does not go beyond length
- of list */
- /* check that each element of each entry does not
- go beyond end of list */
- /* validate_trans2_offsets() */
- /* BB check if start of smb + data_offset > &bcc+ bcc */
-
- data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- ea_response_data = (struct fealist *)
- (((char *) &pSMBr->hdr.Protocol) + data_offset);
-
- list_len = le32_to_cpu(ea_response_data->list_len);
- cifs_dbg(FYI, "ea length %d\n", list_len);
- if (list_len <= 8) {
- cifs_dbg(FYI, "empty EA list returned from server\n");
- /* didn't find the named attribute */
- if (ea_name)
- rc = -ENODATA;
- goto QAllEAsOut;
- }
-
- /* make sure list_len doesn't go past end of SMB */
- end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
- if ((char *)ea_response_data + list_len > end_of_smb) {
- cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
- rc = -EIO;
- goto QAllEAsOut;
- }
-
- /* account for ea list len */
- list_len -= 4;
- temp_fea = ea_response_data->list;
- temp_ptr = (char *)temp_fea;
- while (list_len > 0) {
- unsigned int name_len;
- __u16 value_len;
-
- list_len -= 4;
- temp_ptr += 4;
- /* make sure we can read name_len and value_len */
- if (list_len < 0) {
- cifs_dbg(FYI, "EA entry goes beyond length of list\n");
- rc = -EIO;
- goto QAllEAsOut;
- }
-
- name_len = temp_fea->name_len;
- value_len = le16_to_cpu(temp_fea->value_len);
- list_len -= name_len + 1 + value_len;
- if (list_len < 0) {
- cifs_dbg(FYI, "EA entry goes beyond length of list\n");
- rc = -EIO;
- goto QAllEAsOut;
- }
-
- if (ea_name) {
- if (ea_name_len == name_len &&
- memcmp(ea_name, temp_ptr, name_len) == 0) {
- temp_ptr += name_len + 1;
- rc = value_len;
- if (buf_size == 0)
- goto QAllEAsOut;
- if ((size_t)value_len > buf_size) {
- rc = -ERANGE;
- goto QAllEAsOut;
- }
- memcpy(EAData, temp_ptr, value_len);
- goto QAllEAsOut;
- }
- } else {
- /* account for prefix user. and trailing null */
- rc += (5 + 1 + name_len);
- if (rc < (int) buf_size) {
- memcpy(EAData, "user.", 5);
- EAData += 5;
- memcpy(EAData, temp_ptr, name_len);
- EAData += name_len;
- /* null terminate name */
- *EAData = 0;
- ++EAData;
- } else if (buf_size == 0) {
- /* skip copy - calc size only */
- } else {
- /* stop before overrun buffer */
- rc = -ERANGE;
- break;
- }
- }
- temp_ptr += name_len + 1 + value_len;
- temp_fea = (struct fea *)temp_ptr;
- }
-
- /* didn't find the named attribute */
- if (ea_name)
- rc = -ENODATA;
-
-QAllEAsOut:
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto QAllEAsRetry;
-
- return (ssize_t)rc;
-}
-
-int
-CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fileName, const char *ea_name, const void *ea_value,
- const __u16 ea_value_len, const struct nls_table *nls_codepage,
- struct cifs_sb_info *cifs_sb)
-{
- struct smb_com_transaction2_spi_req *pSMB = NULL;
- struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
- struct fealist *parm_data;
- int name_len;
- int rc = 0;
- int bytes_returned = 0;
- __u16 params, param_offset, byte_count, offset, count;
- int remap = cifs_remap(cifs_sb);
-
- cifs_dbg(FYI, "In SetEA\n");
-SetEARetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
- PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
- name_len *= 2;
- } else {
- name_len = copy_path_name(pSMB->FileName, fileName);
- }
-
- params = 6 + name_len;
-
- /* done calculating parms using name_len of file name,
- now use name_len to calculate length of ea name
- we are going to create in the inode xattrs */
- if (ea_name == NULL)
- name_len = 0;
- else
- name_len = strnlen(ea_name, 255);
-
- count = sizeof(*parm_data) + ea_value_len + name_len;
- pSMB->MaxParameterCount = cpu_to_le16(2);
- /* BB find max SMB PDU from sess */
- pSMB->MaxDataCount = cpu_to_le16(1000);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
- offset = param_offset + params;
- pSMB->InformationLevel =
- cpu_to_le16(SMB_SET_FILE_EA);
-
- parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
- byte_count = 3 /* pad */ + params + count;
- pSMB->DataCount = cpu_to_le16(count);
- parm_data->list_len = cpu_to_le32(count);
- parm_data->list[0].EA_flags = 0;
- /* we checked above that name len is less than 255 */
- parm_data->list[0].name_len = (__u8)name_len;
- /* EA names are always ASCII */
- if (ea_name)
- strncpy(parm_data->list[0].name, ea_name, name_len);
- parm_data->list[0].name[name_len] = 0;
- parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
- /* caller ensures that ea_value_len is less than 64K but
- we need to ensure that it fits within the smb */
-
- /*BB add length check to see if it would fit in
- negotiated SMB buffer size BB */
- /* if (ea_value_len > buffer_size - 512 (enough for header)) */
- if (ea_value_len)
- memcpy(parm_data->list[0].name+name_len+1,
- ea_value, ea_value_len);
-
- pSMB->TotalDataCount = pSMB->DataCount;
- pSMB->ParameterCount = cpu_to_le16(params);
- pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->Reserved4 = 0;
- inc_rfc1001_len(pSMB, byte_count);
- pSMB->ByteCount = cpu_to_le16(byte_count);
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc)
- cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
-
- cifs_buf_release(pSMB);
-
- if (rc == -EAGAIN)
- goto SetEARetry;
-
- return rc;
-}
-#endif
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
deleted file mode 100644
index 935fe198a4ba..000000000000
--- a/fs/cifs/connect.c
+++ /dev/null
@@ -1,4754 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002,2011
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-#include <linux/fs.h>
-#include <linux/net.h>
-#include <linux/string.h>
-#include <linux/sched/mm.h>
-#include <linux/sched/signal.h>
-#include <linux/list.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/ctype.h>
-#include <linux/utsname.h>
-#include <linux/mempool.h>
-#include <linux/delay.h>
-#include <linux/completion.h>
-#include <linux/kthread.h>
-#include <linux/pagevec.h>
-#include <linux/freezer.h>
-#include <linux/namei.h>
-#include <linux/uuid.h>
-#include <linux/uaccess.h>
-#include <asm/processor.h>
-#include <linux/inet.h>
-#include <linux/module.h>
-#include <keys/user-type.h>
-#include <net/ipv6.h>
-#include <linux/parser.h>
-#include <linux/bvec.h>
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_unicode.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "ntlmssp.h"
-#include "nterr.h"
-#include "rfc1002pdu.h"
-#include "fscache.h"
-#include "smb2proto.h"
-#include "smbdirect.h"
-#include "dns_resolve.h"
-#ifdef CONFIG_CIFS_DFS_UPCALL
-#include "dfs_cache.h"
-#endif
-#include "fs_context.h"
-#include "cifs_swn.h"
-
-extern mempool_t *cifs_req_poolp;
-extern bool disable_legacy_dialects;
-
-/* FIXME: should these be tunable? */
-#define TLINK_ERROR_EXPIRE (1 * HZ)
-#define TLINK_IDLE_EXPIRE (600 * HZ)
-
-/* Drop the connection to not overload the server */
-#define NUM_STATUS_IO_TIMEOUT 5
-
-struct mount_ctx {
- struct cifs_sb_info *cifs_sb;
- struct smb3_fs_context *fs_ctx;
- unsigned int xid;
- struct TCP_Server_Info *server;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
-#ifdef CONFIG_CIFS_DFS_UPCALL
- struct cifs_ses *root_ses;
- uuid_t mount_id;
- char *origin_fullpath, *leaf_fullpath;
-#endif
-};
-
-static int ip_connect(struct TCP_Server_Info *server);
-static int generic_ip_connect(struct TCP_Server_Info *server);
-static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
-static void cifs_prune_tlinks(struct work_struct *work);
-
-/*
- * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
- * get their ip addresses changed at some point.
- *
- * This should be called with server->srv_mutex held.
- */
-static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
-{
- int rc;
- int len;
- char *unc, *ipaddr = NULL;
- time64_t expiry, now;
- unsigned long ttl = SMB_DNS_RESOLVE_INTERVAL_DEFAULT;
-
- if (!server->hostname)
- return -EINVAL;
-
- /* if server hostname isn't populated, there's nothing to do here */
- if (server->hostname[0] == '\0')
- return 0;
-
- len = strlen(server->hostname) + 3;
-
- unc = kmalloc(len, GFP_KERNEL);
- if (!unc) {
- cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
- return -ENOMEM;
- }
- scnprintf(unc, len, "\\\\%s", server->hostname);
-
- rc = dns_resolve_server_name_to_ip(unc, &ipaddr, &expiry);
- kfree(unc);
-
- if (rc < 0) {
- cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
- __func__, server->hostname, rc);
- goto requeue_resolve;
- }
-
- spin_lock(&server->srv_lock);
- rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
- strlen(ipaddr));
- spin_unlock(&server->srv_lock);
- kfree(ipaddr);
-
- /* rc == 1 means success here */
- if (rc) {
- now = ktime_get_real_seconds();
- if (expiry && expiry > now)
- /*
- * To make sure we don't use the cached entry, retry 1s
- * after expiry.
- */
- ttl = max_t(unsigned long, expiry - now, SMB_DNS_RESOLVE_INTERVAL_MIN) + 1;
- }
- rc = !rc ? -1 : 0;
-
-requeue_resolve:
- cifs_dbg(FYI, "%s: next dns resolution scheduled for %lu seconds in the future\n",
- __func__, ttl);
- mod_delayed_work(cifsiod_wq, &server->resolve, (ttl * HZ));
-
- return rc;
-}
-
-static void smb2_query_server_interfaces(struct work_struct *work)
-{
- int rc;
- struct cifs_tcon *tcon = container_of(work,
- struct cifs_tcon,
- query_interfaces.work);
-
- /*
- * query server network interfaces, in case they change
- */
- rc = SMB3_request_interfaces(0, tcon, false);
- if (rc) {
- cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
- __func__, rc);
- }
-
- queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
- (SMB_INTERFACE_POLL_INTERVAL * HZ));
-}
-
-static void cifs_resolve_server(struct work_struct *work)
-{
- int rc;
- struct TCP_Server_Info *server = container_of(work,
- struct TCP_Server_Info, resolve.work);
-
- cifs_server_lock(server);
-
- /*
- * Resolve the hostname again to make sure that IP address is up-to-date.
- */
- rc = reconn_set_ipaddr_from_hostname(server);
- if (rc) {
- cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
- __func__, rc);
- }
-
- cifs_server_unlock(server);
-}
-
-/*
- * Update the tcpStatus for the server.
- * This is used to signal the cifsd thread to call cifs_reconnect
- * ONLY cifsd thread should call cifs_reconnect. For any other
- * thread, use this function
- *
- * @server: the tcp ses for which reconnect is needed
- * @all_channels: if this needs to be done for all channels
- */
-void
-cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
- bool all_channels)
-{
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses;
- int i;
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
- spin_lock(&pserver->srv_lock);
- if (!all_channels) {
- pserver->tcpStatus = CifsNeedReconnect;
- spin_unlock(&pserver->srv_lock);
- return;
- }
- spin_unlock(&pserver->srv_lock);
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
- spin_lock(&ses->chan_lock);
- for (i = 0; i < ses->chan_count; i++) {
- spin_lock(&ses->chans[i].server->srv_lock);
- ses->chans[i].server->tcpStatus = CifsNeedReconnect;
- spin_unlock(&ses->chans[i].server->srv_lock);
- }
- spin_unlock(&ses->chan_lock);
- }
- spin_unlock(&cifs_tcp_ses_lock);
-}
-
-/*
- * Mark all sessions and tcons for reconnect.
- * IMPORTANT: make sure that this gets called only from
- * cifsd thread. For any other thread, use
- * cifs_signal_cifsd_for_reconnect
- *
- * @server: the tcp ses for which reconnect is needed
- * @server needs to be previously set to CifsNeedReconnect.
- * @mark_smb_session: whether even sessions need to be marked
- */
-void
-cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
- bool mark_smb_session)
-{
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses, *nses;
- struct cifs_tcon *tcon;
-
- /*
- * before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they
- * are not used until reconnected.
- */
- cifs_dbg(FYI, "%s: marking necessary sessions and tcons for reconnect\n", __func__);
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) {
- /* check if iface is still active */
- if (!cifs_chan_is_iface_active(ses, server))
- cifs_chan_update_iface(ses, server);
-
- spin_lock(&ses->chan_lock);
- if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) {
- spin_unlock(&ses->chan_lock);
- continue;
- }
-
- if (mark_smb_session)
- CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses);
- else
- cifs_chan_set_need_reconnect(ses, server);
-
- cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
- __func__, ses->chans_need_reconnect);
-
- /* If all channels need reconnect, then tcon needs reconnect */
- if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
- spin_unlock(&ses->chan_lock);
- continue;
- }
- spin_unlock(&ses->chan_lock);
-
- spin_lock(&ses->ses_lock);
- ses->ses_status = SES_NEED_RECON;
- spin_unlock(&ses->ses_lock);
-
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- tcon->need_reconnect = true;
- spin_lock(&tcon->tc_lock);
- tcon->status = TID_NEED_RECON;
- spin_unlock(&tcon->tc_lock);
- }
- if (ses->tcon_ipc) {
- ses->tcon_ipc->need_reconnect = true;
- spin_lock(&ses->tcon_ipc->tc_lock);
- ses->tcon_ipc->status = TID_NEED_RECON;
- spin_unlock(&ses->tcon_ipc->tc_lock);
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
-}
-
-static void
-cifs_abort_connection(struct TCP_Server_Info *server)
-{
- struct mid_q_entry *mid, *nmid;
- struct list_head retry_list;
-
- server->maxBuf = 0;
- server->max_read = 0;
-
- /* do not want to be sending data on a socket we are freeing */
- cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
- cifs_server_lock(server);
- if (server->ssocket) {
- cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", server->ssocket->state,
- server->ssocket->flags);
- kernel_sock_shutdown(server->ssocket, SHUT_WR);
- cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", server->ssocket->state,
- server->ssocket->flags);
- sock_release(server->ssocket);
- server->ssocket = NULL;
- }
- server->sequence_number = 0;
- server->session_estab = false;
- kfree_sensitive(server->session_key.response);
- server->session_key.response = NULL;
- server->session_key.len = 0;
- server->lstrp = jiffies;
-
- /* mark submitted MIDs for retry and issue callback */
- INIT_LIST_HEAD(&retry_list);
- cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
- spin_lock(&server->mid_lock);
- list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) {
- kref_get(&mid->refcount);
- if (mid->mid_state == MID_REQUEST_SUBMITTED)
- mid->mid_state = MID_RETRY_NEEDED;
- list_move(&mid->qhead, &retry_list);
- mid->mid_flags |= MID_DELETED;
- }
- spin_unlock(&server->mid_lock);
- cifs_server_unlock(server);
-
- cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
- list_for_each_entry_safe(mid, nmid, &retry_list, qhead) {
- list_del_init(&mid->qhead);
- mid->callback(mid);
- release_mid(mid);
- }
-
- if (cifs_rdma_enabled(server)) {
- cifs_server_lock(server);
- smbd_destroy(server);
- cifs_server_unlock(server);
- }
-}
-
-static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num_targets)
-{
- spin_lock(&server->srv_lock);
- server->nr_targets = num_targets;
- if (server->tcpStatus == CifsExiting) {
- /* the demux thread will exit normally next time through the loop */
- spin_unlock(&server->srv_lock);
- wake_up(&server->response_q);
- return false;
- }
-
- cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
- trace_smb3_reconnect(server->CurrentMid, server->conn_id,
- server->hostname);
- server->tcpStatus = CifsNeedReconnect;
-
- spin_unlock(&server->srv_lock);
- return true;
-}
-
-/*
- * cifs tcp session reconnection
- *
- * mark tcp session as reconnecting so temporarily locked
- * mark all smb sessions as reconnecting for tcp session
- * reconnect tcp session
- * wake up waiters on reconnection? - (not needed currently)
- *
- * if mark_smb_session is passed as true, unconditionally mark
- * the smb session (and tcon) for reconnect as well. This value
- * doesn't really matter for non-multichannel scenario.
- *
- */
-static int __cifs_reconnect(struct TCP_Server_Info *server,
- bool mark_smb_session)
-{
- int rc = 0;
-
- if (!cifs_tcp_ses_needs_reconnect(server, 1))
- return 0;
-
- cifs_mark_tcp_ses_conns_for_reconnect(server, mark_smb_session);
-
- cifs_abort_connection(server);
-
- do {
- try_to_freeze();
- cifs_server_lock(server);
-
- if (!cifs_swn_set_server_dstaddr(server)) {
- /* resolve the hostname again to make sure that IP address is up-to-date */
- rc = reconn_set_ipaddr_from_hostname(server);
- cifs_dbg(FYI, "%s: reconn_set_ipaddr_from_hostname: rc=%d\n", __func__, rc);
- }
-
- if (cifs_rdma_enabled(server))
- rc = smbd_reconnect(server);
- else
- rc = generic_ip_connect(server);
- if (rc) {
- cifs_server_unlock(server);
- cifs_dbg(FYI, "%s: reconnect error %d\n", __func__, rc);
- msleep(3000);
- } else {
- atomic_inc(&tcpSesReconnectCount);
- set_credits(server, 1);
- spin_lock(&server->srv_lock);
- if (server->tcpStatus != CifsExiting)
- server->tcpStatus = CifsNeedNegotiate;
- spin_unlock(&server->srv_lock);
- cifs_swn_reset_server_dstaddr(server);
- cifs_server_unlock(server);
- mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
- }
- } while (server->tcpStatus == CifsNeedReconnect);
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsNeedNegotiate)
- mod_delayed_work(cifsiod_wq, &server->echo, 0);
- spin_unlock(&server->srv_lock);
-
- wake_up(&server->response_q);
- return rc;
-}
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
-static int __reconnect_target_unlocked(struct TCP_Server_Info *server, const char *target)
-{
- int rc;
- char *hostname;
-
- if (!cifs_swn_set_server_dstaddr(server)) {
- if (server->hostname != target) {
- hostname = extract_hostname(target);
- if (!IS_ERR(hostname)) {
- spin_lock(&server->srv_lock);
- kfree(server->hostname);
- server->hostname = hostname;
- spin_unlock(&server->srv_lock);
- } else {
- cifs_dbg(FYI, "%s: couldn't extract hostname or address from dfs target: %ld\n",
- __func__, PTR_ERR(hostname));
- cifs_dbg(FYI, "%s: default to last target server: %s\n", __func__,
- server->hostname);
- }
- }
- /* resolve the hostname again to make sure that IP address is up-to-date. */
- rc = reconn_set_ipaddr_from_hostname(server);
- cifs_dbg(FYI, "%s: reconn_set_ipaddr_from_hostname: rc=%d\n", __func__, rc);
- }
- /* Reconnect the socket */
- if (cifs_rdma_enabled(server))
- rc = smbd_reconnect(server);
- else
- rc = generic_ip_connect(server);
-
- return rc;
-}
-
-static int reconnect_target_unlocked(struct TCP_Server_Info *server, struct dfs_cache_tgt_list *tl,
- struct dfs_cache_tgt_iterator **target_hint)
-{
- int rc;
- struct dfs_cache_tgt_iterator *tit;
-
- *target_hint = NULL;
-
- /* If dfs target list is empty, then reconnect to last server */
- tit = dfs_cache_get_tgt_iterator(tl);
- if (!tit)
- return __reconnect_target_unlocked(server, server->hostname);
-
- /* Otherwise, try every dfs target in @tl */
- for (; tit; tit = dfs_cache_get_next_tgt(tl, tit)) {
- rc = __reconnect_target_unlocked(server, dfs_cache_get_tgt_name(tit));
- if (!rc) {
- *target_hint = tit;
- break;
- }
- }
- return rc;
-}
-
-static int reconnect_dfs_server(struct TCP_Server_Info *server)
-{
- int rc = 0;
- const char *refpath = server->current_fullpath + 1;
- struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
- struct dfs_cache_tgt_iterator *target_hint = NULL;
- int num_targets = 0;
-
- /*
- * Determine the number of dfs targets the referral path in @cifs_sb resolves to.
- *
- * smb2_reconnect() needs to know how long it should wait based upon the number of dfs
- * targets (server->nr_targets). It's also possible that the cached referral was cleared
- * through /proc/fs/cifs/dfscache or the target list is empty due to server settings after
- * refreshing the referral, so, in this case, default it to 1.
- */
- if (!dfs_cache_noreq_find(refpath, NULL, &tl))
- num_targets = dfs_cache_get_nr_tgts(&tl);
- if (!num_targets)
- num_targets = 1;
-
- if (!cifs_tcp_ses_needs_reconnect(server, num_targets))
- return 0;
-
- /*
- * Unconditionally mark all sessions & tcons for reconnect as we might be connecting to a
- * different server or share during failover. It could be improved by adding some logic to
- * only do that in case it connects to a different server or share, though.
- */
- cifs_mark_tcp_ses_conns_for_reconnect(server, true);
-
- cifs_abort_connection(server);
-
- do {
- try_to_freeze();
- cifs_server_lock(server);
-
- rc = reconnect_target_unlocked(server, &tl, &target_hint);
- if (rc) {
- /* Failed to reconnect socket */
- cifs_server_unlock(server);
- cifs_dbg(FYI, "%s: reconnect error %d\n", __func__, rc);
- msleep(3000);
- continue;
- }
- /*
- * Socket was created. Update tcp session status to CifsNeedNegotiate so that a
- * process waiting for reconnect will know it needs to re-establish session and tcon
- * through the reconnected target server.
- */
- atomic_inc(&tcpSesReconnectCount);
- set_credits(server, 1);
- spin_lock(&server->srv_lock);
- if (server->tcpStatus != CifsExiting)
- server->tcpStatus = CifsNeedNegotiate;
- spin_unlock(&server->srv_lock);
- cifs_swn_reset_server_dstaddr(server);
- cifs_server_unlock(server);
- mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
- } while (server->tcpStatus == CifsNeedReconnect);
-
- if (target_hint)
- dfs_cache_noreq_update_tgthint(refpath, target_hint);
-
- dfs_cache_free_tgts(&tl);
-
- /* Need to set up echo worker again once connection has been established */
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsNeedNegotiate)
- mod_delayed_work(cifsiod_wq, &server->echo, 0);
- spin_unlock(&server->srv_lock);
-
- wake_up(&server->response_q);
- return rc;
-}
-
-int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
-{
- /* If tcp session is not an dfs connection, then reconnect to last target server */
- spin_lock(&server->srv_lock);
- if (!server->is_dfs_conn) {
- spin_unlock(&server->srv_lock);
- return __cifs_reconnect(server, mark_smb_session);
- }
- spin_unlock(&server->srv_lock);
-
- mutex_lock(&server->refpath_lock);
- if (!server->origin_fullpath || !server->leaf_fullpath) {
- mutex_unlock(&server->refpath_lock);
- return __cifs_reconnect(server, mark_smb_session);
- }
- mutex_unlock(&server->refpath_lock);
-
- return reconnect_dfs_server(server);
-}
-#else
-int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
-{
- return __cifs_reconnect(server, mark_smb_session);
-}
-#endif
-
-static void
-cifs_echo_request(struct work_struct *work)
-{
- int rc;
- struct TCP_Server_Info *server = container_of(work,
- struct TCP_Server_Info, echo.work);
-
- /*
- * We cannot send an echo if it is disabled.
- * Also, no need to ping if we got a response recently.
- */
-
- if (server->tcpStatus == CifsNeedReconnect ||
- server->tcpStatus == CifsExiting ||
- server->tcpStatus == CifsNew ||
- (server->ops->can_echo && !server->ops->can_echo(server)) ||
- time_before(jiffies, server->lstrp + server->echo_interval - HZ))
- goto requeue_echo;
-
- rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
- cifs_server_dbg(FYI, "send echo request: rc = %d\n", rc);
-
- /* Check witness registrations */
- cifs_swn_check();
-
-requeue_echo:
- queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
-}
-
-static bool
-allocate_buffers(struct TCP_Server_Info *server)
-{
- if (!server->bigbuf) {
- server->bigbuf = (char *)cifs_buf_get();
- if (!server->bigbuf) {
- cifs_server_dbg(VFS, "No memory for large SMB response\n");
- msleep(3000);
- /* retry will check if exiting */
- return false;
- }
- } else if (server->large_buf) {
- /* we are reusing a dirty large buf, clear its start */
- memset(server->bigbuf, 0, HEADER_SIZE(server));
- }
-
- if (!server->smallbuf) {
- server->smallbuf = (char *)cifs_small_buf_get();
- if (!server->smallbuf) {
- cifs_server_dbg(VFS, "No memory for SMB response\n");
- msleep(1000);
- /* retry will check if exiting */
- return false;
- }
- /* beginning of smb buffer is cleared in our buf_get */
- } else {
- /* if existing small buf clear beginning */
- memset(server->smallbuf, 0, HEADER_SIZE(server));
- }
-
- return true;
-}
-
-static bool
-server_unresponsive(struct TCP_Server_Info *server)
-{
- /*
- * We need to wait 3 echo intervals to make sure we handle such
- * situations right:
- * 1s client sends a normal SMB request
- * 2s client gets a response
- * 30s echo workqueue job pops, and decides we got a response recently
- * and don't need to send another
- * ...
- * 65s kernel_recvmsg times out, and we see that we haven't gotten
- * a response in >60s.
- */
- spin_lock(&server->srv_lock);
- if ((server->tcpStatus == CifsGood ||
- server->tcpStatus == CifsNeedNegotiate) &&
- (!server->ops->can_echo || server->ops->can_echo(server)) &&
- time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
- spin_unlock(&server->srv_lock);
- cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
- (3 * server->echo_interval) / HZ);
- cifs_reconnect(server, false);
- return true;
- }
- spin_unlock(&server->srv_lock);
-
- return false;
-}
-
-static inline bool
-zero_credits(struct TCP_Server_Info *server)
-{
- int val;
-
- spin_lock(&server->req_lock);
- val = server->credits + server->echo_credits + server->oplock_credits;
- if (server->in_flight == 0 && val == 0) {
- spin_unlock(&server->req_lock);
- return true;
- }
- spin_unlock(&server->req_lock);
- return false;
-}
-
-static int
-cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
-{
- int length = 0;
- int total_read;
-
- for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
- try_to_freeze();
-
- /* reconnect if no credits and no requests in flight */
- if (zero_credits(server)) {
- cifs_reconnect(server, false);
- return -ECONNABORTED;
- }
-
- if (server_unresponsive(server))
- return -ECONNABORTED;
- if (cifs_rdma_enabled(server) && server->smbd_conn)
- length = smbd_recv(server->smbd_conn, smb_msg);
- else
- length = sock_recvmsg(server->ssocket, smb_msg, 0);
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsExiting) {
- spin_unlock(&server->srv_lock);
- return -ESHUTDOWN;
- }
-
- if (server->tcpStatus == CifsNeedReconnect) {
- spin_unlock(&server->srv_lock);
- cifs_reconnect(server, false);
- return -ECONNABORTED;
- }
- spin_unlock(&server->srv_lock);
-
- if (length == -ERESTARTSYS ||
- length == -EAGAIN ||
- length == -EINTR) {
- /*
- * Minimum sleep to prevent looping, allowing socket
- * to clear and app threads to set tcpStatus
- * CifsNeedReconnect if server hung.
- */
- usleep_range(1000, 2000);
- length = 0;
- continue;
- }
-
- if (length <= 0) {
- cifs_dbg(FYI, "Received no data or error: %d\n", length);
- cifs_reconnect(server, false);
- return -ECONNABORTED;
- }
- }
- return total_read;
-}
-
-int
-cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
- unsigned int to_read)
-{
- struct msghdr smb_msg = {};
- struct kvec iov = {.iov_base = buf, .iov_len = to_read};
- iov_iter_kvec(&smb_msg.msg_iter, ITER_DEST, &iov, 1, to_read);
-
- return cifs_readv_from_socket(server, &smb_msg);
-}
-
-ssize_t
-cifs_discard_from_socket(struct TCP_Server_Info *server, size_t to_read)
-{
- struct msghdr smb_msg = {};
-
- /*
- * iov_iter_discard already sets smb_msg.type and count and iov_offset
- * and cifs_readv_from_socket sets msg_control and msg_controllen
- * so little to initialize in struct msghdr
- */
- iov_iter_discard(&smb_msg.msg_iter, ITER_DEST, to_read);
-
- return cifs_readv_from_socket(server, &smb_msg);
-}
-
-int
-cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
- unsigned int page_offset, unsigned int to_read)
-{
- struct msghdr smb_msg = {};
- struct bio_vec bv = {
- .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
- iov_iter_bvec(&smb_msg.msg_iter, ITER_DEST, &bv, 1, to_read);
- return cifs_readv_from_socket(server, &smb_msg);
-}
-
-static bool
-is_smb_response(struct TCP_Server_Info *server, unsigned char type)
-{
- /*
- * The first byte big endian of the length field,
- * is actually not part of the length but the type
- * with the most common, zero, as regular data.
- */
- switch (type) {
- case RFC1002_SESSION_MESSAGE:
- /* Regular SMB response */
- return true;
- case RFC1002_SESSION_KEEP_ALIVE:
- cifs_dbg(FYI, "RFC 1002 session keep alive\n");
- break;
- case RFC1002_POSITIVE_SESSION_RESPONSE:
- cifs_dbg(FYI, "RFC 1002 positive session response\n");
- break;
- case RFC1002_NEGATIVE_SESSION_RESPONSE:
- /*
- * We get this from Windows 98 instead of an error on
- * SMB negprot response.
- */
- cifs_dbg(FYI, "RFC 1002 negative session response\n");
- /* give server a second to clean up */
- msleep(1000);
- /*
- * Always try 445 first on reconnect since we get NACK
- * on some if we ever connected to port 139 (the NACK
- * is since we do not begin with RFC1001 session
- * initialize frame).
- */
- cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
- cifs_reconnect(server, true);
- break;
- default:
- cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
- cifs_reconnect(server, true);
- }
-
- return false;
-}
-
-void
-dequeue_mid(struct mid_q_entry *mid, bool malformed)
-{
-#ifdef CONFIG_CIFS_STATS2
- mid->when_received = jiffies;
-#endif
- spin_lock(&mid->server->mid_lock);
- if (!malformed)
- mid->mid_state = MID_RESPONSE_RECEIVED;
- else
- mid->mid_state = MID_RESPONSE_MALFORMED;
- /*
- * Trying to handle/dequeue a mid after the send_recv()
- * function has finished processing it is a bug.
- */
- if (mid->mid_flags & MID_DELETED) {
- spin_unlock(&mid->server->mid_lock);
- pr_warn_once("trying to dequeue a deleted mid\n");
- } else {
- list_del_init(&mid->qhead);
- mid->mid_flags |= MID_DELETED;
- spin_unlock(&mid->server->mid_lock);
- }
-}
-
-static unsigned int
-smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
-{
- struct smb2_hdr *shdr = (struct smb2_hdr *)buffer;
-
- /*
- * SMB1 does not use credits.
- */
- if (is_smb1(server))
- return 0;
-
- return le16_to_cpu(shdr->CreditRequest);
-}
-
-static void
-handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
- char *buf, int malformed)
-{
- if (server->ops->check_trans2 &&
- server->ops->check_trans2(mid, server, buf, malformed))
- return;
- mid->credits_received = smb2_get_credits_from_hdr(buf, server);
- mid->resp_buf = buf;
- mid->large_buf = server->large_buf;
- /* Was previous buf put in mpx struct for multi-rsp? */
- if (!mid->multiRsp) {
- /* smb buffer will be freed by user thread */
- if (server->large_buf)
- server->bigbuf = NULL;
- else
- server->smallbuf = NULL;
- }
- dequeue_mid(mid, malformed);
-}
-
-int
-cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
-{
- bool srv_sign_required = server->sec_mode & server->vals->signing_required;
- bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
- bool mnt_sign_enabled;
-
- /*
- * Is signing required by mnt options? If not then check
- * global_secflags to see if it is there.
- */
- if (!mnt_sign_required)
- mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
- CIFSSEC_MUST_SIGN);
-
- /*
- * If signing is required then it's automatically enabled too,
- * otherwise, check to see if the secflags allow it.
- */
- mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
- (global_secflags & CIFSSEC_MAY_SIGN);
-
- /* If server requires signing, does client allow it? */
- if (srv_sign_required) {
- if (!mnt_sign_enabled) {
- cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!\n");
- return -EOPNOTSUPP;
- }
- server->sign = true;
- }
-
- /* If client requires signing, does server allow it? */
- if (mnt_sign_required) {
- if (!srv_sign_enabled) {
- cifs_dbg(VFS, "Server does not support signing!\n");
- return -EOPNOTSUPP;
- }
- server->sign = true;
- }
-
- if (cifs_rdma_enabled(server) && server->sign)
- cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled\n");
-
- return 0;
-}
-
-
-static void clean_demultiplex_info(struct TCP_Server_Info *server)
-{
- int length;
-
- /* take it off the list, if it's not already */
- spin_lock(&server->srv_lock);
- list_del_init(&server->tcp_ses_list);
- spin_unlock(&server->srv_lock);
-
- cancel_delayed_work_sync(&server->echo);
- cancel_delayed_work_sync(&server->resolve);
-
- spin_lock(&server->srv_lock);
- server->tcpStatus = CifsExiting;
- spin_unlock(&server->srv_lock);
- wake_up_all(&server->response_q);
-
- /* check if we have blocked requests that need to free */
- spin_lock(&server->req_lock);
- if (server->credits <= 0)
- server->credits = 1;
- spin_unlock(&server->req_lock);
- /*
- * Although there should not be any requests blocked on this queue it
- * can not hurt to be paranoid and try to wake up requests that may
- * haven been blocked when more than 50 at time were on the wire to the
- * same server - they now will see the session is in exit state and get
- * out of SendReceive.
- */
- wake_up_all(&server->request_q);
- /* give those requests time to exit */
- msleep(125);
- if (cifs_rdma_enabled(server))
- smbd_destroy(server);
- if (server->ssocket) {
- sock_release(server->ssocket);
- server->ssocket = NULL;
- }
-
- if (!list_empty(&server->pending_mid_q)) {
- struct list_head dispose_list;
- struct mid_q_entry *mid_entry;
- struct list_head *tmp, *tmp2;
-
- INIT_LIST_HEAD(&dispose_list);
- spin_lock(&server->mid_lock);
- list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
- mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
- cifs_dbg(FYI, "Clearing mid %llu\n", mid_entry->mid);
- kref_get(&mid_entry->refcount);
- mid_entry->mid_state = MID_SHUTDOWN;
- list_move(&mid_entry->qhead, &dispose_list);
- mid_entry->mid_flags |= MID_DELETED;
- }
- spin_unlock(&server->mid_lock);
-
- /* now walk dispose list and issue callbacks */
- list_for_each_safe(tmp, tmp2, &dispose_list) {
- mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
- cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid);
- list_del_init(&mid_entry->qhead);
- mid_entry->callback(mid_entry);
- release_mid(mid_entry);
- }
- /* 1/8th of sec is more than enough time for them to exit */
- msleep(125);
- }
-
- if (!list_empty(&server->pending_mid_q)) {
- /*
- * mpx threads have not exited yet give them at least the smb
- * send timeout time for long ops.
- *
- * Due to delays on oplock break requests, we need to wait at
- * least 45 seconds before giving up on a request getting a
- * response and going ahead and killing cifsd.
- */
- cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
- msleep(46000);
- /*
- * If threads still have not exited they are probably never
- * coming home not much else we can do but free the memory.
- */
- }
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
- kfree(server->origin_fullpath);
- kfree(server->leaf_fullpath);
-#endif
- kfree(server);
-
- length = atomic_dec_return(&tcpSesAllocCount);
- if (length > 0)
- mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
-}
-
-static int
-standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
-{
- int length;
- char *buf = server->smallbuf;
- unsigned int pdu_length = server->pdu_size;
-
- /* make sure this will fit in a large buffer */
- if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
- HEADER_PREAMBLE_SIZE(server)) {
- cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
- cifs_reconnect(server, true);
- return -ECONNABORTED;
- }
-
- /* switch to large buffer if too big for a small one */
- if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
- server->large_buf = true;
- memcpy(server->bigbuf, buf, server->total_read);
- buf = server->bigbuf;
- }
-
- /* now read the rest */
- length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
- pdu_length - MID_HEADER_SIZE(server));
-
- if (length < 0)
- return length;
- server->total_read += length;
-
- dump_smb(buf, server->total_read);
-
- return cifs_handle_standard(server, mid);
-}
-
-int
-cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
-{
- char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
- int rc;
-
- /*
- * We know that we received enough to get to the MID as we
- * checked the pdu_length earlier. Now check to see
- * if the rest of the header is OK.
- *
- * 48 bytes is enough to display the header and a little bit
- * into the payload for debugging purposes.
- */
- rc = server->ops->check_message(buf, server->total_read, server);
- if (rc)
- cifs_dump_mem("Bad SMB: ", buf,
- min_t(unsigned int, server->total_read, 48));
-
- if (server->ops->is_session_expired &&
- server->ops->is_session_expired(buf)) {
- cifs_reconnect(server, true);
- return -1;
- }
-
- if (server->ops->is_status_pending &&
- server->ops->is_status_pending(buf, server))
- return -1;
-
- if (!mid)
- return rc;
-
- handle_mid(mid, server, buf, rc);
- return 0;
-}
-
-static void
-smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
-{
- struct smb2_hdr *shdr = (struct smb2_hdr *)buffer;
- int scredits, in_flight;
-
- /*
- * SMB1 does not use credits.
- */
- if (is_smb1(server))
- return;
-
- if (shdr->CreditRequest) {
- spin_lock(&server->req_lock);
- server->credits += le16_to_cpu(shdr->CreditRequest);
- scredits = server->credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
- wake_up(&server->request_q);
-
- trace_smb3_hdr_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits,
- le16_to_cpu(shdr->CreditRequest), in_flight);
- cifs_server_dbg(FYI, "%s: added %u credits total=%d\n",
- __func__, le16_to_cpu(shdr->CreditRequest),
- scredits);
- }
-}
-
-
-static int
-cifs_demultiplex_thread(void *p)
-{
- int i, num_mids, length;
- struct TCP_Server_Info *server = p;
- unsigned int pdu_length;
- unsigned int next_offset;
- char *buf = NULL;
- struct task_struct *task_to_wake = NULL;
- struct mid_q_entry *mids[MAX_COMPOUND];
- char *bufs[MAX_COMPOUND];
- unsigned int noreclaim_flag, num_io_timeout = 0;
-
- noreclaim_flag = memalloc_noreclaim_save();
- cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
-
- length = atomic_inc_return(&tcpSesAllocCount);
- if (length > 1)
- mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
-
- set_freezable();
- allow_kernel_signal(SIGKILL);
- while (server->tcpStatus != CifsExiting) {
- if (try_to_freeze())
- continue;
-
- if (!allocate_buffers(server))
- continue;
-
- server->large_buf = false;
- buf = server->smallbuf;
- pdu_length = 4; /* enough to get RFC1001 header */
-
- length = cifs_read_from_socket(server, buf, pdu_length);
- if (length < 0)
- continue;
-
- if (is_smb1(server))
- server->total_read = length;
- else
- server->total_read = 0;
-
- /*
- * The right amount was read from socket - 4 bytes,
- * so we can now interpret the length field.
- */
- pdu_length = get_rfc1002_length(buf);
-
- cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
- if (!is_smb_response(server, buf[0]))
- continue;
-next_pdu:
- server->pdu_size = pdu_length;
-
- /* make sure we have enough to get to the MID */
- if (server->pdu_size < MID_HEADER_SIZE(server)) {
- cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
- server->pdu_size);
- cifs_reconnect(server, true);
- continue;
- }
-
- /* read down to the MID */
- length = cifs_read_from_socket(server,
- buf + HEADER_PREAMBLE_SIZE(server),
- MID_HEADER_SIZE(server));
- if (length < 0)
- continue;
- server->total_read += length;
-
- if (server->ops->next_header) {
- next_offset = server->ops->next_header(buf);
- if (next_offset)
- server->pdu_size = next_offset;
- }
-
- memset(mids, 0, sizeof(mids));
- memset(bufs, 0, sizeof(bufs));
- num_mids = 0;
-
- if (server->ops->is_transform_hdr &&
- server->ops->receive_transform &&
- server->ops->is_transform_hdr(buf)) {
- length = server->ops->receive_transform(server,
- mids,
- bufs,
- &num_mids);
- } else {
- mids[0] = server->ops->find_mid(server, buf);
- bufs[0] = buf;
- num_mids = 1;
-
- if (!mids[0] || !mids[0]->receive)
- length = standard_receive3(server, mids[0]);
- else
- length = mids[0]->receive(server, mids[0]);
- }
-
- if (length < 0) {
- for (i = 0; i < num_mids; i++)
- if (mids[i])
- release_mid(mids[i]);
- continue;
- }
-
- if (server->ops->is_status_io_timeout &&
- server->ops->is_status_io_timeout(buf)) {
- num_io_timeout++;
- if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
- cifs_reconnect(server, false);
- num_io_timeout = 0;
- continue;
- }
- }
-
- server->lstrp = jiffies;
-
- for (i = 0; i < num_mids; i++) {
- if (mids[i] != NULL) {
- mids[i]->resp_buf_size = server->pdu_size;
-
- if (bufs[i] && server->ops->is_network_name_deleted)
- server->ops->is_network_name_deleted(bufs[i],
- server);
-
- if (!mids[i]->multiRsp || mids[i]->multiEnd)
- mids[i]->callback(mids[i]);
-
- release_mid(mids[i]);
- } else if (server->ops->is_oplock_break &&
- server->ops->is_oplock_break(bufs[i],
- server)) {
- smb2_add_credits_from_hdr(bufs[i], server);
- cifs_dbg(FYI, "Received oplock break\n");
- } else {
- cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
- atomic_read(&mid_count));
- cifs_dump_mem("Received Data is: ", bufs[i],
- HEADER_SIZE(server));
- smb2_add_credits_from_hdr(bufs[i], server);
-#ifdef CONFIG_CIFS_DEBUG2
- if (server->ops->dump_detail)
- server->ops->dump_detail(bufs[i],
- server);
- cifs_dump_mids(server);
-#endif /* CIFS_DEBUG2 */
- }
- }
-
- if (pdu_length > server->pdu_size) {
- if (!allocate_buffers(server))
- continue;
- pdu_length -= server->pdu_size;
- server->total_read = 0;
- server->large_buf = false;
- buf = server->smallbuf;
- goto next_pdu;
- }
- } /* end while !EXITING */
-
- /* buffer usually freed in free_mid - need to free it here on exit */
- cifs_buf_release(server->bigbuf);
- if (server->smallbuf) /* no sense logging a debug message if NULL */
- cifs_small_buf_release(server->smallbuf);
-
- task_to_wake = xchg(&server->tsk, NULL);
- clean_demultiplex_info(server);
-
- /* if server->tsk was NULL then wait for a signal before exiting */
- if (!task_to_wake) {
- set_current_state(TASK_INTERRUPTIBLE);
- while (!signal_pending(current)) {
- schedule();
- set_current_state(TASK_INTERRUPTIBLE);
- }
- set_current_state(TASK_RUNNING);
- }
-
- memalloc_noreclaim_restore(noreclaim_flag);
- module_put_and_kthread_exit(0);
-}
-
-/*
- * Returns true if srcaddr isn't specified and rhs isn't specified, or
- * if srcaddr is specified and matches the IP address of the rhs argument
- */
-bool
-cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
-{
- switch (srcaddr->sa_family) {
- case AF_UNSPEC:
- return (rhs->sa_family == AF_UNSPEC);
- case AF_INET: {
- struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
- struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
- return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
- }
- case AF_INET6: {
- struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
- struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
- return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
- }
- default:
- WARN_ON(1);
- return false; /* don't expect to be here */
- }
-}
-
-/*
- * If no port is specified in addr structure, we try to match with 445 port
- * and if it fails - with 139 ports. It should be called only if address
- * families of server and addr are equal.
- */
-static bool
-match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
-{
- __be16 port, *sport;
-
- /* SMBDirect manages its own ports, don't match it here */
- if (server->rdma)
- return true;
-
- switch (addr->sa_family) {
- case AF_INET:
- sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
- port = ((struct sockaddr_in *) addr)->sin_port;
- break;
- case AF_INET6:
- sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
- port = ((struct sockaddr_in6 *) addr)->sin6_port;
- break;
- default:
- WARN_ON(1);
- return false;
- }
-
- if (!port) {
- port = htons(CIFS_PORT);
- if (port == *sport)
- return true;
-
- port = htons(RFC1001_PORT);
- }
-
- return port == *sport;
-}
-
-static bool
-match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
- struct sockaddr *srcaddr)
-{
- switch (addr->sa_family) {
- case AF_INET: {
- struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
- struct sockaddr_in *srv_addr4 =
- (struct sockaddr_in *)&server->dstaddr;
-
- if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
- return false;
- break;
- }
- case AF_INET6: {
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
- struct sockaddr_in6 *srv_addr6 =
- (struct sockaddr_in6 *)&server->dstaddr;
-
- if (!ipv6_addr_equal(&addr6->sin6_addr,
- &srv_addr6->sin6_addr))
- return false;
- if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
- return false;
- break;
- }
- default:
- WARN_ON(1);
- return false; /* don't expect to be here */
- }
-
- if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr))
- return false;
-
- return true;
-}
-
-static bool
-match_security(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
-{
- /*
- * The select_sectype function should either return the ctx->sectype
- * that was specified, or "Unspecified" if that sectype was not
- * compatible with the given NEGOTIATE request.
- */
- if (server->ops->select_sectype(server, ctx->sectype)
- == Unspecified)
- return false;
-
- /*
- * Now check if signing mode is acceptable. No need to check
- * global_secflags at this point since if MUST_SIGN is set then
- * the server->sign had better be too.
- */
- if (ctx->sign && !server->sign)
- return false;
-
- return true;
-}
-
-/* this function must be called with srv_lock held */
-static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
-{
- struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
-
- lockdep_assert_held(&server->srv_lock);
-
- if (ctx->nosharesock)
- return 0;
-
- /* this server does not share socket */
- if (server->nosharesock)
- return 0;
-
- /* If multidialect negotiation see if existing sessions match one */
- if (strcmp(ctx->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
- if (server->vals->protocol_id < SMB30_PROT_ID)
- return 0;
- } else if (strcmp(ctx->vals->version_string,
- SMBDEFAULT_VERSION_STRING) == 0) {
- if (server->vals->protocol_id < SMB21_PROT_ID)
- return 0;
- } else if ((server->vals != ctx->vals) || (server->ops != ctx->ops))
- return 0;
-
- if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
- return 0;
-
- if (strcasecmp(server->hostname, ctx->server_hostname))
- return 0;
-
- if (!match_address(server, addr,
- (struct sockaddr *)&ctx->srcaddr))
- return 0;
-
- if (!match_port(server, addr))
- return 0;
-
- if (!match_security(server, ctx))
- return 0;
-
- if (server->echo_interval != ctx->echo_interval * HZ)
- return 0;
-
- if (server->rdma != ctx->rdma)
- return 0;
-
- if (server->ignore_signature != ctx->ignore_signature)
- return 0;
-
- if (server->min_offload != ctx->min_offload)
- return 0;
-
- return 1;
-}
-
-struct TCP_Server_Info *
-cifs_find_tcp_session(struct smb3_fs_context *ctx)
-{
- struct TCP_Server_Info *server;
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
- spin_lock(&server->srv_lock);
-#ifdef CONFIG_CIFS_DFS_UPCALL
- /*
- * DFS failover implementation in cifs_reconnect() requires unique tcp sessions for
- * DFS connections to do failover properly, so avoid sharing them with regular
- * shares or even links that may connect to same server but having completely
- * different failover targets.
- */
- if (server->is_dfs_conn) {
- spin_unlock(&server->srv_lock);
- continue;
- }
-#endif
- /*
- * Skip ses channels since they're only handled in lower layers
- * (e.g. cifs_send_recv).
- */
- if (CIFS_SERVER_IS_CHAN(server) || !match_server(server, ctx)) {
- spin_unlock(&server->srv_lock);
- continue;
- }
- spin_unlock(&server->srv_lock);
-
- ++server->srv_count;
- spin_unlock(&cifs_tcp_ses_lock);
- cifs_dbg(FYI, "Existing tcp session with server found\n");
- return server;
- }
- spin_unlock(&cifs_tcp_ses_lock);
- return NULL;
-}
-
-void
-cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
-{
- struct task_struct *task;
-
- spin_lock(&cifs_tcp_ses_lock);
- if (--server->srv_count > 0) {
- spin_unlock(&cifs_tcp_ses_lock);
- return;
- }
-
- /* srv_count can never go negative */
- WARN_ON(server->srv_count < 0);
-
- put_net(cifs_net_ns(server));
-
- list_del_init(&server->tcp_ses_list);
- spin_unlock(&cifs_tcp_ses_lock);
-
- /* For secondary channels, we pick up ref-count on the primary server */
- if (CIFS_SERVER_IS_CHAN(server))
- cifs_put_tcp_session(server->primary_server, from_reconnect);
-
- cancel_delayed_work_sync(&server->echo);
- cancel_delayed_work_sync(&server->resolve);
-
- if (from_reconnect)
- /*
- * Avoid deadlock here: reconnect work calls
- * cifs_put_tcp_session() at its end. Need to be sure
- * that reconnect work does nothing with server pointer after
- * that step.
- */
- cancel_delayed_work(&server->reconnect);
- else
- cancel_delayed_work_sync(&server->reconnect);
-
- spin_lock(&server->srv_lock);
- server->tcpStatus = CifsExiting;
- spin_unlock(&server->srv_lock);
-
- cifs_crypto_secmech_release(server);
-
- kfree_sensitive(server->session_key.response);
- server->session_key.response = NULL;
- server->session_key.len = 0;
- kfree(server->hostname);
- server->hostname = NULL;
-
- task = xchg(&server->tsk, NULL);
- if (task)
- send_sig(SIGKILL, task, 1);
-}
-
-struct TCP_Server_Info *
-cifs_get_tcp_session(struct smb3_fs_context *ctx,
- struct TCP_Server_Info *primary_server)
-{
- struct TCP_Server_Info *tcp_ses = NULL;
- int rc;
-
- cifs_dbg(FYI, "UNC: %s\n", ctx->UNC);
-
- /* see if we already have a matching tcp_ses */
- tcp_ses = cifs_find_tcp_session(ctx);
- if (tcp_ses)
- return tcp_ses;
-
- tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
- if (!tcp_ses) {
- rc = -ENOMEM;
- goto out_err;
- }
-
- tcp_ses->hostname = kstrdup(ctx->server_hostname, GFP_KERNEL);
- if (!tcp_ses->hostname) {
- rc = -ENOMEM;
- goto out_err;
- }
-
- if (ctx->nosharesock)
- tcp_ses->nosharesock = true;
-
- tcp_ses->ops = ctx->ops;
- tcp_ses->vals = ctx->vals;
- cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
-
- tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId);
- tcp_ses->noblockcnt = ctx->rootfs;
- tcp_ses->noblocksnd = ctx->noblocksnd || ctx->rootfs;
- tcp_ses->noautotune = ctx->noautotune;
- tcp_ses->tcp_nodelay = ctx->sockopt_tcp_nodelay;
- tcp_ses->rdma = ctx->rdma;
- tcp_ses->in_flight = 0;
- tcp_ses->max_in_flight = 0;
- tcp_ses->credits = 1;
- if (primary_server) {
- spin_lock(&cifs_tcp_ses_lock);
- ++primary_server->srv_count;
- spin_unlock(&cifs_tcp_ses_lock);
- tcp_ses->primary_server = primary_server;
- }
- init_waitqueue_head(&tcp_ses->response_q);
- init_waitqueue_head(&tcp_ses->request_q);
- INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
- mutex_init(&tcp_ses->_srv_mutex);
- memcpy(tcp_ses->workstation_RFC1001_name,
- ctx->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
- memcpy(tcp_ses->server_RFC1001_name,
- ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
- tcp_ses->session_estab = false;
- tcp_ses->sequence_number = 0;
- tcp_ses->reconnect_instance = 1;
- tcp_ses->lstrp = jiffies;
- tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression);
- spin_lock_init(&tcp_ses->req_lock);
- spin_lock_init(&tcp_ses->srv_lock);
- spin_lock_init(&tcp_ses->mid_lock);
- INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
- INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
- INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
- INIT_DELAYED_WORK(&tcp_ses->resolve, cifs_resolve_server);
- INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
- mutex_init(&tcp_ses->reconnect_mutex);
-#ifdef CONFIG_CIFS_DFS_UPCALL
- mutex_init(&tcp_ses->refpath_lock);
-#endif
- memcpy(&tcp_ses->srcaddr, &ctx->srcaddr,
- sizeof(tcp_ses->srcaddr));
- memcpy(&tcp_ses->dstaddr, &ctx->dstaddr,
- sizeof(tcp_ses->dstaddr));
- if (ctx->use_client_guid)
- memcpy(tcp_ses->client_guid, ctx->client_guid,
- SMB2_CLIENT_GUID_SIZE);
- else
- generate_random_uuid(tcp_ses->client_guid);
- /*
- * at this point we are the only ones with the pointer
- * to the struct since the kernel thread not created yet
- * no need to spinlock this init of tcpStatus or srv_count
- */
- tcp_ses->tcpStatus = CifsNew;
- ++tcp_ses->srv_count;
-
- if (ctx->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
- ctx->echo_interval <= SMB_ECHO_INTERVAL_MAX)
- tcp_ses->echo_interval = ctx->echo_interval * HZ;
- else
- tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
- if (tcp_ses->rdma) {
-#ifndef CONFIG_CIFS_SMB_DIRECT
- cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
- rc = -ENOENT;
- goto out_err_crypto_release;
-#endif
- tcp_ses->smbd_conn = smbd_get_connection(
- tcp_ses, (struct sockaddr *)&ctx->dstaddr);
- if (tcp_ses->smbd_conn) {
- cifs_dbg(VFS, "RDMA transport established\n");
- rc = 0;
- goto smbd_connected;
- } else {
- rc = -ENOENT;
- goto out_err_crypto_release;
- }
- }
- rc = ip_connect(tcp_ses);
- if (rc < 0) {
- cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
- goto out_err_crypto_release;
- }
-smbd_connected:
- /*
- * since we're in a cifs function already, we know that
- * this will succeed. No need for try_module_get().
- */
- __module_get(THIS_MODULE);
- tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
- tcp_ses, "cifsd");
- if (IS_ERR(tcp_ses->tsk)) {
- rc = PTR_ERR(tcp_ses->tsk);
- cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
- module_put(THIS_MODULE);
- goto out_err_crypto_release;
- }
- tcp_ses->min_offload = ctx->min_offload;
- /*
- * at this point we are the only ones with the pointer
- * to the struct since the kernel thread not created yet
- * no need to spinlock this update of tcpStatus
- */
- spin_lock(&tcp_ses->srv_lock);
- tcp_ses->tcpStatus = CifsNeedNegotiate;
- spin_unlock(&tcp_ses->srv_lock);
-
- if ((ctx->max_credits < 20) || (ctx->max_credits > 60000))
- tcp_ses->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
- else
- tcp_ses->max_credits = ctx->max_credits;
-
- tcp_ses->nr_targets = 1;
- tcp_ses->ignore_signature = ctx->ignore_signature;
- /* thread spawned, put it on the list */
- spin_lock(&cifs_tcp_ses_lock);
- list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
- spin_unlock(&cifs_tcp_ses_lock);
-
- /* queue echo request delayed work */
- queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
-
- /* queue dns resolution delayed work */
- cifs_dbg(FYI, "%s: next dns resolution scheduled for %d seconds in the future\n",
- __func__, SMB_DNS_RESOLVE_INTERVAL_DEFAULT);
-
- queue_delayed_work(cifsiod_wq, &tcp_ses->resolve, (SMB_DNS_RESOLVE_INTERVAL_DEFAULT * HZ));
-
- return tcp_ses;
-
-out_err_crypto_release:
- cifs_crypto_secmech_release(tcp_ses);
-
- put_net(cifs_net_ns(tcp_ses));
-
-out_err:
- if (tcp_ses) {
- if (CIFS_SERVER_IS_CHAN(tcp_ses))
- cifs_put_tcp_session(tcp_ses->primary_server, false);
- kfree(tcp_ses->hostname);
- if (tcp_ses->ssocket)
- sock_release(tcp_ses->ssocket);
- kfree(tcp_ses);
- }
- return ERR_PTR(rc);
-}
-
-/* this function must be called with ses_lock and chan_lock held */
-static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
-{
- if (ctx->sectype != Unspecified &&
- ctx->sectype != ses->sectype)
- return 0;
-
- /*
- * If an existing session is limited to less channels than
- * requested, it should not be reused
- */
- if (ses->chan_max < ctx->max_channels)
- return 0;
-
- switch (ses->sectype) {
- case Kerberos:
- if (!uid_eq(ctx->cred_uid, ses->cred_uid))
- return 0;
- break;
- default:
- /* NULL username means anonymous session */
- if (ses->user_name == NULL) {
- if (!ctx->nullauth)
- return 0;
- break;
- }
-
- /* anything else takes username/password */
- if (strncmp(ses->user_name,
- ctx->username ? ctx->username : "",
- CIFS_MAX_USERNAME_LEN))
- return 0;
- if ((ctx->username && strlen(ctx->username) != 0) &&
- ses->password != NULL &&
- strncmp(ses->password,
- ctx->password ? ctx->password : "",
- CIFS_MAX_PASSWORD_LEN))
- return 0;
- }
- return 1;
-}
-
-/**
- * cifs_setup_ipc - helper to setup the IPC tcon for the session
- * @ses: smb session to issue the request on
- * @ctx: the superblock configuration context to use for building the
- * new tree connection for the IPC (interprocess communication RPC)
- *
- * A new IPC connection is made and stored in the session
- * tcon_ipc. The IPC tcon has the same lifetime as the session.
- */
-static int
-cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
-{
- int rc = 0, xid;
- struct cifs_tcon *tcon;
- char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
- bool seal = false;
- struct TCP_Server_Info *server = ses->server;
-
- /*
- * If the mount request that resulted in the creation of the
- * session requires encryption, force IPC to be encrypted too.
- */
- if (ctx->seal) {
- if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
- seal = true;
- else {
- cifs_server_dbg(VFS,
- "IPC: server doesn't support encryption\n");
- return -EOPNOTSUPP;
- }
- }
-
- tcon = tconInfoAlloc();
- if (tcon == NULL)
- return -ENOMEM;
-
- spin_lock(&server->srv_lock);
- scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
- spin_unlock(&server->srv_lock);
-
- xid = get_xid();
- tcon->ses = ses;
- tcon->ipc = true;
- tcon->seal = seal;
- rc = server->ops->tree_connect(xid, ses, unc, tcon, ctx->local_nls);
- free_xid(xid);
-
- if (rc) {
- cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
- tconInfoFree(tcon);
- goto out;
- }
-
- cifs_dbg(FYI, "IPC tcon rc=%d ipc tid=0x%x\n", rc, tcon->tid);
-
- spin_lock(&tcon->tc_lock);
- tcon->status = TID_GOOD;
- spin_unlock(&tcon->tc_lock);
- ses->tcon_ipc = tcon;
-out:
- return rc;
-}
-
-/**
- * cifs_free_ipc - helper to release the session IPC tcon
- * @ses: smb session to unmount the IPC from
- *
- * Needs to be called everytime a session is destroyed.
- *
- * On session close, the IPC is closed and the server must release all tcons of the session.
- * No need to send a tree disconnect here.
- *
- * Besides, it will make the server to not close durable and resilient files on session close, as
- * specified in MS-SMB2 3.3.5.6 Receiving an SMB2 LOGOFF Request.
- */
-static int
-cifs_free_ipc(struct cifs_ses *ses)
-{
- struct cifs_tcon *tcon = ses->tcon_ipc;
-
- if (tcon == NULL)
- return 0;
-
- tconInfoFree(tcon);
- ses->tcon_ipc = NULL;
- return 0;
-}
-
-static struct cifs_ses *
-cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
-{
- struct cifs_ses *ses;
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
- spin_lock(&ses->ses_lock);
- if (ses->ses_status == SES_EXITING) {
- spin_unlock(&ses->ses_lock);
- continue;
- }
- spin_lock(&ses->chan_lock);
- if (!match_session(ses, ctx)) {
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
- continue;
- }
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
-
- ++ses->ses_count;
- spin_unlock(&cifs_tcp_ses_lock);
- return ses;
- }
- spin_unlock(&cifs_tcp_ses_lock);
- return NULL;
-}
-
-void cifs_put_smb_ses(struct cifs_ses *ses)
-{
- unsigned int rc, xid;
- unsigned int chan_count;
- struct TCP_Server_Info *server = ses->server;
-
- spin_lock(&ses->ses_lock);
- if (ses->ses_status == SES_EXITING) {
- spin_unlock(&ses->ses_lock);
- return;
- }
- spin_unlock(&ses->ses_lock);
-
- cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
- cifs_dbg(FYI,
- "%s: ses ipc: %s\n", __func__, ses->tcon_ipc ? ses->tcon_ipc->tree_name : "NONE");
-
- spin_lock(&cifs_tcp_ses_lock);
- if (--ses->ses_count > 0) {
- spin_unlock(&cifs_tcp_ses_lock);
- return;
- }
- spin_unlock(&cifs_tcp_ses_lock);
-
- /* ses_count can never go negative */
- WARN_ON(ses->ses_count < 0);
-
- if (ses->ses_status == SES_GOOD)
- ses->ses_status = SES_EXITING;
-
- cifs_free_ipc(ses);
-
- if (ses->ses_status == SES_EXITING && server->ops->logoff) {
- xid = get_xid();
- rc = server->ops->logoff(xid, ses);
- if (rc)
- cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
- __func__, rc);
- _free_xid(xid);
- }
-
- spin_lock(&cifs_tcp_ses_lock);
- list_del_init(&ses->smb_ses_list);
- spin_unlock(&cifs_tcp_ses_lock);
-
- chan_count = ses->chan_count;
-
- /* close any extra channels */
- if (chan_count > 1) {
- int i;
-
- for (i = 1; i < chan_count; i++) {
- if (ses->chans[i].iface) {
- kref_put(&ses->chans[i].iface->refcount, release_iface);
- ses->chans[i].iface = NULL;
- }
- cifs_put_tcp_session(ses->chans[i].server, 0);
- ses->chans[i].server = NULL;
- }
- }
-
- sesInfoFree(ses);
- cifs_put_tcp_session(server, 0);
-}
-
-#ifdef CONFIG_KEYS
-
-/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
-#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
-
-/* Populate username and pw fields from keyring if possible */
-static int
-cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
-{
- int rc = 0;
- int is_domain = 0;
- const char *delim, *payload;
- char *desc;
- ssize_t len;
- struct key *key;
- struct TCP_Server_Info *server = ses->server;
- struct sockaddr_in *sa;
- struct sockaddr_in6 *sa6;
- const struct user_key_payload *upayload;
-
- desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
-
- /* try to find an address key first */
- switch (server->dstaddr.ss_family) {
- case AF_INET:
- sa = (struct sockaddr_in *)&server->dstaddr;
- sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
- break;
- case AF_INET6:
- sa6 = (struct sockaddr_in6 *)&server->dstaddr;
- sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
- break;
- default:
- cifs_dbg(FYI, "Bad ss_family (%hu)\n",
- server->dstaddr.ss_family);
- rc = -EINVAL;
- goto out_err;
- }
-
- cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
- key = request_key(&key_type_logon, desc, "");
- if (IS_ERR(key)) {
- if (!ses->domainName) {
- cifs_dbg(FYI, "domainName is NULL\n");
- rc = PTR_ERR(key);
- goto out_err;
- }
-
- /* didn't work, try to find a domain key */
- sprintf(desc, "cifs:d:%s", ses->domainName);
- cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
- key = request_key(&key_type_logon, desc, "");
- if (IS_ERR(key)) {
- rc = PTR_ERR(key);
- goto out_err;
- }
- is_domain = 1;
- }
-
- down_read(&key->sem);
- upayload = user_key_payload_locked(key);
- if (IS_ERR_OR_NULL(upayload)) {
- rc = upayload ? PTR_ERR(upayload) : -EINVAL;
- goto out_key_put;
- }
-
- /* find first : in payload */
- payload = upayload->data;
- delim = strnchr(payload, upayload->datalen, ':');
- cifs_dbg(FYI, "payload=%s\n", payload);
- if (!delim) {
- cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
- upayload->datalen);
- rc = -EINVAL;
- goto out_key_put;
- }
-
- len = delim - payload;
- if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
- cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
- len);
- rc = -EINVAL;
- goto out_key_put;
- }
-
- ctx->username = kstrndup(payload, len, GFP_KERNEL);
- if (!ctx->username) {
- cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
- len);
- rc = -ENOMEM;
- goto out_key_put;
- }
- cifs_dbg(FYI, "%s: username=%s\n", __func__, ctx->username);
-
- len = key->datalen - (len + 1);
- if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
- cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
- rc = -EINVAL;
- kfree(ctx->username);
- ctx->username = NULL;
- goto out_key_put;
- }
-
- ++delim;
- ctx->password = kstrndup(delim, len, GFP_KERNEL);
- if (!ctx->password) {
- cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
- len);
- rc = -ENOMEM;
- kfree(ctx->username);
- ctx->username = NULL;
- goto out_key_put;
- }
-
- /*
- * If we have a domain key then we must set the domainName in the
- * for the request.
- */
- if (is_domain && ses->domainName) {
- ctx->domainname = kstrdup(ses->domainName, GFP_KERNEL);
- if (!ctx->domainname) {
- cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
- len);
- rc = -ENOMEM;
- kfree(ctx->username);
- ctx->username = NULL;
- kfree_sensitive(ctx->password);
- ctx->password = NULL;
- goto out_key_put;
- }
- }
-
- strscpy(ctx->workstation_name, ses->workstation_name, sizeof(ctx->workstation_name));
-
-out_key_put:
- up_read(&key->sem);
- key_put(key);
-out_err:
- kfree(desc);
- cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
- return rc;
-}
-#else /* ! CONFIG_KEYS */
-static inline int
-cifs_set_cifscreds(struct smb3_fs_context *ctx __attribute__((unused)),
- struct cifs_ses *ses __attribute__((unused)))
-{
- return -ENOSYS;
-}
-#endif /* CONFIG_KEYS */
-
-/**
- * cifs_get_smb_ses - get a session matching @ctx data from @server
- * @server: server to setup the session to
- * @ctx: superblock configuration context to use to setup the session
- *
- * This function assumes it is being called from cifs_mount() where we
- * already got a server reference (server refcount +1). See
- * cifs_get_tcon() for refcount explanations.
- */
-struct cifs_ses *
-cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
-{
- int rc = 0;
- unsigned int xid;
- struct cifs_ses *ses;
- struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
-
- xid = get_xid();
-
- ses = cifs_find_smb_ses(server, ctx);
- if (ses) {
- cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
- ses->ses_status);
-
- spin_lock(&ses->chan_lock);
- if (cifs_chan_needs_reconnect(ses, server)) {
- spin_unlock(&ses->chan_lock);
- cifs_dbg(FYI, "Session needs reconnect\n");
-
- mutex_lock(&ses->session_mutex);
- rc = cifs_negotiate_protocol(xid, ses, server);
- if (rc) {
- mutex_unlock(&ses->session_mutex);
- /* problem -- put our ses reference */
- cifs_put_smb_ses(ses);
- free_xid(xid);
- return ERR_PTR(rc);
- }
-
- rc = cifs_setup_session(xid, ses, server,
- ctx->local_nls);
- if (rc) {
- mutex_unlock(&ses->session_mutex);
- /* problem -- put our reference */
- cifs_put_smb_ses(ses);
- free_xid(xid);
- return ERR_PTR(rc);
- }
- mutex_unlock(&ses->session_mutex);
-
- spin_lock(&ses->chan_lock);
- }
- spin_unlock(&ses->chan_lock);
-
- /* existing SMB ses has a server reference already */
- cifs_put_tcp_session(server, 0);
- free_xid(xid);
- return ses;
- }
-
- rc = -ENOMEM;
-
- cifs_dbg(FYI, "Existing smb sess not found\n");
- ses = sesInfoAlloc();
- if (ses == NULL)
- goto get_ses_fail;
-
- /* new SMB session uses our server ref */
- ses->server = server;
- if (server->dstaddr.ss_family == AF_INET6)
- sprintf(ses->ip_addr, "%pI6", &addr6->sin6_addr);
- else
- sprintf(ses->ip_addr, "%pI4", &addr->sin_addr);
-
- if (ctx->username) {
- ses->user_name = kstrdup(ctx->username, GFP_KERNEL);
- if (!ses->user_name)
- goto get_ses_fail;
- }
-
- /* ctx->password freed at unmount */
- if (ctx->password) {
- ses->password = kstrdup(ctx->password, GFP_KERNEL);
- if (!ses->password)
- goto get_ses_fail;
- }
- if (ctx->domainname) {
- ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL);
- if (!ses->domainName)
- goto get_ses_fail;
- }
-
- strscpy(ses->workstation_name, ctx->workstation_name, sizeof(ses->workstation_name));
-
- if (ctx->domainauto)
- ses->domainAuto = ctx->domainauto;
- ses->cred_uid = ctx->cred_uid;
- ses->linux_uid = ctx->linux_uid;
-
- ses->sectype = ctx->sectype;
- ses->sign = ctx->sign;
-
- /* add server as first channel */
- spin_lock(&ses->chan_lock);
- ses->chans[0].server = server;
- ses->chan_count = 1;
- ses->chan_max = ctx->multichannel ? ctx->max_channels:1;
- ses->chans_need_reconnect = 1;
- spin_unlock(&ses->chan_lock);
-
- mutex_lock(&ses->session_mutex);
- rc = cifs_negotiate_protocol(xid, ses, server);
- if (!rc)
- rc = cifs_setup_session(xid, ses, server, ctx->local_nls);
- mutex_unlock(&ses->session_mutex);
-
- /* each channel uses a different signing key */
- spin_lock(&ses->chan_lock);
- memcpy(ses->chans[0].signkey, ses->smb3signingkey,
- sizeof(ses->smb3signingkey));
- spin_unlock(&ses->chan_lock);
-
- if (rc)
- goto get_ses_fail;
-
- /*
- * success, put it on the list and add it as first channel
- * note: the session becomes active soon after this. So you'll
- * need to lock before changing something in the session.
- */
- spin_lock(&cifs_tcp_ses_lock);
- list_add(&ses->smb_ses_list, &server->smb_ses_list);
- spin_unlock(&cifs_tcp_ses_lock);
-
- cifs_setup_ipc(ses, ctx);
-
- free_xid(xid);
-
- return ses;
-
-get_ses_fail:
- sesInfoFree(ses);
- free_xid(xid);
- return ERR_PTR(rc);
-}
-
-/* this function must be called with tc_lock held */
-static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
-{
- if (tcon->status == TID_EXITING)
- return 0;
- if (strncmp(tcon->tree_name, ctx->UNC, MAX_TREE_SIZE))
- return 0;
- if (tcon->seal != ctx->seal)
- return 0;
- if (tcon->snapshot_time != ctx->snapshot_time)
- return 0;
- if (tcon->handle_timeout != ctx->handle_timeout)
- return 0;
- if (tcon->no_lease != ctx->no_lease)
- return 0;
- if (tcon->nodelete != ctx->nodelete)
- return 0;
- return 1;
-}
-
-static struct cifs_tcon *
-cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
-{
- struct cifs_tcon *tcon;
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- spin_lock(&tcon->tc_lock);
- if (!match_tcon(tcon, ctx)) {
- spin_unlock(&tcon->tc_lock);
- continue;
- }
- ++tcon->tc_count;
- spin_unlock(&tcon->tc_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- return tcon;
- }
- spin_unlock(&cifs_tcp_ses_lock);
- return NULL;
-}
-
-void
-cifs_put_tcon(struct cifs_tcon *tcon)
-{
- unsigned int xid;
- struct cifs_ses *ses;
-
- /*
- * IPC tcon share the lifetime of their session and are
- * destroyed in the session put function
- */
- if (tcon == NULL || tcon->ipc)
- return;
-
- ses = tcon->ses;
- cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
- spin_lock(&cifs_tcp_ses_lock);
- spin_lock(&tcon->tc_lock);
- if (--tcon->tc_count > 0) {
- spin_unlock(&tcon->tc_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- return;
- }
-
- /* tc_count can never go negative */
- WARN_ON(tcon->tc_count < 0);
-
- list_del_init(&tcon->tcon_list);
- tcon->status = TID_EXITING;
- spin_unlock(&tcon->tc_lock);
- spin_unlock(&cifs_tcp_ses_lock);
-
- /* cancel polling of interfaces */
- cancel_delayed_work_sync(&tcon->query_interfaces);
-
- if (tcon->use_witness) {
- int rc;
-
- rc = cifs_swn_unregister(tcon);
- if (rc < 0) {
- cifs_dbg(VFS, "%s: Failed to unregister for witness notifications: %d\n",
- __func__, rc);
- }
- }
-
- xid = get_xid();
- if (ses->server->ops->tree_disconnect)
- ses->server->ops->tree_disconnect(xid, tcon);
- _free_xid(xid);
-
- cifs_fscache_release_super_cookie(tcon);
- tconInfoFree(tcon);
- cifs_put_smb_ses(ses);
-}
-
-/**
- * cifs_get_tcon - get a tcon matching @ctx data from @ses
- * @ses: smb session to issue the request on
- * @ctx: the superblock configuration context to use for building the
- *
- * - tcon refcount is the number of mount points using the tcon.
- * - ses refcount is the number of tcon using the session.
- *
- * 1. This function assumes it is being called from cifs_mount() where
- * we already got a session reference (ses refcount +1).
- *
- * 2. Since we're in the context of adding a mount point, the end
- * result should be either:
- *
- * a) a new tcon already allocated with refcount=1 (1 mount point) and
- * its session refcount incremented (1 new tcon). This +1 was
- * already done in (1).
- *
- * b) an existing tcon with refcount+1 (add a mount point to it) and
- * identical ses refcount (no new tcon). Because of (1) we need to
- * decrement the ses refcount.
- */
-static struct cifs_tcon *
-cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
-{
- int rc, xid;
- struct cifs_tcon *tcon;
-
- tcon = cifs_find_tcon(ses, ctx);
- if (tcon) {
- /*
- * tcon has refcount already incremented but we need to
- * decrement extra ses reference gotten by caller (case b)
- */
- cifs_dbg(FYI, "Found match on UNC path\n");
- cifs_put_smb_ses(ses);
- return tcon;
- }
-
- if (!ses->server->ops->tree_connect) {
- rc = -ENOSYS;
- goto out_fail;
- }
-
- tcon = tconInfoAlloc();
- if (tcon == NULL) {
- rc = -ENOMEM;
- goto out_fail;
- }
-
- if (ctx->snapshot_time) {
- if (ses->server->vals->protocol_id == 0) {
- cifs_dbg(VFS,
- "Use SMB2 or later for snapshot mount option\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- } else
- tcon->snapshot_time = ctx->snapshot_time;
- }
-
- if (ctx->handle_timeout) {
- if (ses->server->vals->protocol_id == 0) {
- cifs_dbg(VFS,
- "Use SMB2.1 or later for handle timeout option\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- } else
- tcon->handle_timeout = ctx->handle_timeout;
- }
-
- tcon->ses = ses;
- if (ctx->password) {
- tcon->password = kstrdup(ctx->password, GFP_KERNEL);
- if (!tcon->password) {
- rc = -ENOMEM;
- goto out_fail;
- }
- }
-
- if (ctx->seal) {
- if (ses->server->vals->protocol_id == 0) {
- cifs_dbg(VFS,
- "SMB3 or later required for encryption\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- } else if (tcon->ses->server->capabilities &
- SMB2_GLOBAL_CAP_ENCRYPTION)
- tcon->seal = true;
- else {
- cifs_dbg(VFS, "Encryption is not supported on share\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- }
- }
-
- if (ctx->linux_ext) {
- if (ses->server->posix_ext_supported) {
- tcon->posix_extensions = true;
- pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
- } else if ((ses->server->vals->protocol_id == SMB311_PROT_ID) ||
- (strcmp(ses->server->vals->version_string,
- SMB3ANY_VERSION_STRING) == 0) ||
- (strcmp(ses->server->vals->version_string,
- SMBDEFAULT_VERSION_STRING) == 0)) {
- cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- } else {
- cifs_dbg(VFS, "Check vers= mount option. SMB3.11 "
- "disabled but required for POSIX extensions\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- }
- }
-
- xid = get_xid();
- rc = ses->server->ops->tree_connect(xid, ses, ctx->UNC, tcon,
- ctx->local_nls);
- free_xid(xid);
- cifs_dbg(FYI, "Tcon rc = %d\n", rc);
- if (rc)
- goto out_fail;
-
- tcon->use_persistent = false;
- /* check if SMB2 or later, CIFS does not support persistent handles */
- if (ctx->persistent) {
- if (ses->server->vals->protocol_id == 0) {
- cifs_dbg(VFS,
- "SMB3 or later required for persistent handles\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- } else if (ses->server->capabilities &
- SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
- tcon->use_persistent = true;
- else /* persistent handles requested but not supported */ {
- cifs_dbg(VFS,
- "Persistent handles not supported on share\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- }
- } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
- && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
- && (ctx->nopersistent == false)) {
- cifs_dbg(FYI, "enabling persistent handles\n");
- tcon->use_persistent = true;
- } else if (ctx->resilient) {
- if (ses->server->vals->protocol_id == 0) {
- cifs_dbg(VFS,
- "SMB2.1 or later required for resilient handles\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- }
- tcon->use_resilient = true;
- }
-
- tcon->use_witness = false;
- if (IS_ENABLED(CONFIG_CIFS_SWN_UPCALL) && ctx->witness) {
- if (ses->server->vals->protocol_id >= SMB30_PROT_ID) {
- if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER) {
- /*
- * Set witness in use flag in first place
- * to retry registration in the echo task
- */
- tcon->use_witness = true;
- /* And try to register immediately */
- rc = cifs_swn_register(tcon);
- if (rc < 0) {
- cifs_dbg(VFS, "Failed to register for witness notifications: %d\n", rc);
- goto out_fail;
- }
- } else {
- /* TODO: try to extend for non-cluster uses (eg multichannel) */
- cifs_dbg(VFS, "witness requested on mount but no CLUSTER capability on share\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- }
- } else {
- cifs_dbg(VFS, "SMB3 or later required for witness option\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- }
- }
-
- /* If the user really knows what they are doing they can override */
- if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
- if (ctx->cache_ro)
- cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
- else if (ctx->cache_rw)
- cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
- }
-
- if (ctx->no_lease) {
- if (ses->server->vals->protocol_id == 0) {
- cifs_dbg(VFS,
- "SMB2 or later required for nolease option\n");
- rc = -EOPNOTSUPP;
- goto out_fail;
- } else
- tcon->no_lease = ctx->no_lease;
- }
-
- /*
- * We can have only one retry value for a connection to a share so for
- * resources mounted more than once to the same server share the last
- * value passed in for the retry flag is used.
- */
- tcon->retry = ctx->retry;
- tcon->nocase = ctx->nocase;
- tcon->broken_sparse_sup = ctx->no_sparse;
- if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
- tcon->nohandlecache = ctx->nohandlecache;
- else
- tcon->nohandlecache = true;
- tcon->nodelete = ctx->nodelete;
- tcon->local_lease = ctx->local_lease;
- INIT_LIST_HEAD(&tcon->pending_opens);
- tcon->status = TID_GOOD;
-
- INIT_DELAYED_WORK(&tcon->query_interfaces,
- smb2_query_server_interfaces);
- if (ses->server->dialect >= SMB30_PROT_ID &&
- (ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
- /* schedule query interfaces poll */
- queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
- (SMB_INTERFACE_POLL_INTERVAL * HZ));
- }
-
- spin_lock(&cifs_tcp_ses_lock);
- list_add(&tcon->tcon_list, &ses->tcon_list);
- spin_unlock(&cifs_tcp_ses_lock);
-
- return tcon;
-
-out_fail:
- tconInfoFree(tcon);
- return ERR_PTR(rc);
-}
-
-void
-cifs_put_tlink(struct tcon_link *tlink)
-{
- if (!tlink || IS_ERR(tlink))
- return;
-
- if (!atomic_dec_and_test(&tlink->tl_count) ||
- test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
- tlink->tl_time = jiffies;
- return;
- }
-
- if (!IS_ERR(tlink_tcon(tlink)))
- cifs_put_tcon(tlink_tcon(tlink));
- kfree(tlink);
- return;
-}
-
-static int
-compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
-{
- struct cifs_sb_info *old = CIFS_SB(sb);
- struct cifs_sb_info *new = mnt_data->cifs_sb;
- unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
- unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
-
- if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
- return 0;
-
- if (old->mnt_cifs_serverino_autodisabled)
- newflags &= ~CIFS_MOUNT_SERVER_INUM;
-
- if (oldflags != newflags)
- return 0;
-
- /*
- * We want to share sb only if we don't specify an r/wsize or
- * specified r/wsize is greater than or equal to existing one.
- */
- if (new->ctx->wsize && new->ctx->wsize < old->ctx->wsize)
- return 0;
-
- if (new->ctx->rsize && new->ctx->rsize < old->ctx->rsize)
- return 0;
-
- if (!uid_eq(old->ctx->linux_uid, new->ctx->linux_uid) ||
- !gid_eq(old->ctx->linux_gid, new->ctx->linux_gid))
- return 0;
-
- if (old->ctx->file_mode != new->ctx->file_mode ||
- old->ctx->dir_mode != new->ctx->dir_mode)
- return 0;
-
- if (strcmp(old->local_nls->charset, new->local_nls->charset))
- return 0;
-
- if (old->ctx->acregmax != new->ctx->acregmax)
- return 0;
- if (old->ctx->acdirmax != new->ctx->acdirmax)
- return 0;
- if (old->ctx->closetimeo != new->ctx->closetimeo)
- return 0;
-
- return 1;
-}
-
-static int
-match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
-{
- struct cifs_sb_info *old = CIFS_SB(sb);
- struct cifs_sb_info *new = mnt_data->cifs_sb;
- bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
- old->prepath;
- bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
- new->prepath;
-
- if (old_set && new_set && !strcmp(new->prepath, old->prepath))
- return 1;
- else if (!old_set && !new_set)
- return 1;
-
- return 0;
-}
-
-int
-cifs_match_super(struct super_block *sb, void *data)
-{
- struct cifs_mnt_data *mnt_data = data;
- struct smb3_fs_context *ctx;
- struct cifs_sb_info *cifs_sb;
- struct TCP_Server_Info *tcp_srv;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
- struct tcon_link *tlink;
- int rc = 0;
-
- spin_lock(&cifs_tcp_ses_lock);
- cifs_sb = CIFS_SB(sb);
-
- /* We do not want to use a superblock that has been shutdown */
- if (CIFS_MOUNT_SHUTDOWN & cifs_sb->mnt_cifs_flags) {
- spin_unlock(&cifs_tcp_ses_lock);
- return 0;
- }
-
- tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
- if (tlink == NULL) {
- /* can not match superblock if tlink were ever null */
- spin_unlock(&cifs_tcp_ses_lock);
- return 0;
- }
- tcon = tlink_tcon(tlink);
- ses = tcon->ses;
- tcp_srv = ses->server;
-
- ctx = mnt_data->ctx;
-
- spin_lock(&tcp_srv->srv_lock);
- spin_lock(&ses->ses_lock);
- spin_lock(&ses->chan_lock);
- spin_lock(&tcon->tc_lock);
- if (!match_server(tcp_srv, ctx) ||
- !match_session(ses, ctx) ||
- !match_tcon(tcon, ctx) ||
- !match_prepath(sb, mnt_data)) {
- rc = 0;
- goto out;
- }
-
- rc = compare_mount_options(sb, mnt_data);
-out:
- spin_unlock(&tcon->tc_lock);
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
- spin_unlock(&tcp_srv->srv_lock);
-
- spin_unlock(&cifs_tcp_ses_lock);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-static struct lock_class_key cifs_key[2];
-static struct lock_class_key cifs_slock_key[2];
-
-static inline void
-cifs_reclassify_socket4(struct socket *sock)
-{
- struct sock *sk = sock->sk;
- BUG_ON(!sock_allow_reclassification(sk));
- sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
- &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
-}
-
-static inline void
-cifs_reclassify_socket6(struct socket *sock)
-{
- struct sock *sk = sock->sk;
- BUG_ON(!sock_allow_reclassification(sk));
- sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
- &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
-}
-#else
-static inline void
-cifs_reclassify_socket4(struct socket *sock)
-{
-}
-
-static inline void
-cifs_reclassify_socket6(struct socket *sock)
-{
-}
-#endif
-
-/* See RFC1001 section 14 on representation of Netbios names */
-static void rfc1002mangle(char *target, char *source, unsigned int length)
-{
- unsigned int i, j;
-
- for (i = 0, j = 0; i < (length); i++) {
- /* mask a nibble at a time and encode */
- target[j] = 'A' + (0x0F & (source[i] >> 4));
- target[j+1] = 'A' + (0x0F & source[i]);
- j += 2;
- }
-
-}
-
-static int
-bind_socket(struct TCP_Server_Info *server)
-{
- int rc = 0;
- if (server->srcaddr.ss_family != AF_UNSPEC) {
- /* Bind to the specified local IP address */
- struct socket *socket = server->ssocket;
- rc = socket->ops->bind(socket,
- (struct sockaddr *) &server->srcaddr,
- sizeof(server->srcaddr));
- if (rc < 0) {
- struct sockaddr_in *saddr4;
- struct sockaddr_in6 *saddr6;
- saddr4 = (struct sockaddr_in *)&server->srcaddr;
- saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
- if (saddr6->sin6_family == AF_INET6)
- cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
- &saddr6->sin6_addr, rc);
- else
- cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
- &saddr4->sin_addr.s_addr, rc);
- }
- }
- return rc;
-}
-
-static int
-ip_rfc1001_connect(struct TCP_Server_Info *server)
-{
- int rc = 0;
- /*
- * some servers require RFC1001 sessinit before sending
- * negprot - BB check reconnection in case where second
- * sessinit is sent but no second negprot
- */
- struct rfc1002_session_packet req = {};
- struct smb_hdr *smb_buf = (struct smb_hdr *)&req;
- unsigned int len;
-
- req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name);
-
- if (server->server_RFC1001_name[0] != 0)
- rfc1002mangle(req.trailer.session_req.called_name,
- server->server_RFC1001_name,
- RFC1001_NAME_LEN_WITH_NULL);
- else
- rfc1002mangle(req.trailer.session_req.called_name,
- DEFAULT_CIFS_CALLED_NAME,
- RFC1001_NAME_LEN_WITH_NULL);
-
- req.trailer.session_req.calling_len = sizeof(req.trailer.session_req.calling_name);
-
- /* calling name ends in null (byte 16) from old smb convention */
- if (server->workstation_RFC1001_name[0] != 0)
- rfc1002mangle(req.trailer.session_req.calling_name,
- server->workstation_RFC1001_name,
- RFC1001_NAME_LEN_WITH_NULL);
- else
- rfc1002mangle(req.trailer.session_req.calling_name,
- "LINUX_CIFS_CLNT",
- RFC1001_NAME_LEN_WITH_NULL);
-
- /*
- * As per rfc1002, @len must be the number of bytes that follows the
- * length field of a rfc1002 session request payload.
- */
- len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req);
-
- smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len);
- rc = smb_send(server, smb_buf, len);
- /*
- * RFC1001 layer in at least one server requires very short break before
- * negprot presumably because not expecting negprot to follow so fast.
- * This is a simple solution that works without complicating the code
- * and causes no significant slowing down on mount for everyone else
- */
- usleep_range(1000, 2000);
-
- return rc;
-}
-
-static int
-generic_ip_connect(struct TCP_Server_Info *server)
-{
- int rc = 0;
- __be16 sport;
- int slen, sfamily;
- struct socket *socket = server->ssocket;
- struct sockaddr *saddr;
-
- saddr = (struct sockaddr *) &server->dstaddr;
-
- if (server->dstaddr.ss_family == AF_INET6) {
- struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr;
-
- sport = ipv6->sin6_port;
- slen = sizeof(struct sockaddr_in6);
- sfamily = AF_INET6;
- cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr,
- ntohs(sport));
- } else {
- struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr;
-
- sport = ipv4->sin_port;
- slen = sizeof(struct sockaddr_in);
- sfamily = AF_INET;
- cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr,
- ntohs(sport));
- }
-
- if (socket == NULL) {
- rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
- IPPROTO_TCP, &socket, 1);
- if (rc < 0) {
- cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
- server->ssocket = NULL;
- return rc;
- }
-
- /* BB other socket options to set KEEPALIVE, NODELAY? */
- cifs_dbg(FYI, "Socket created\n");
- server->ssocket = socket;
- socket->sk->sk_allocation = GFP_NOFS;
- if (sfamily == AF_INET6)
- cifs_reclassify_socket6(socket);
- else
- cifs_reclassify_socket4(socket);
- }
-
- rc = bind_socket(server);
- if (rc < 0)
- return rc;
-
- /*
- * Eventually check for other socket options to change from
- * the default. sock_setsockopt not used because it expects
- * user space buffer
- */
- socket->sk->sk_rcvtimeo = 7 * HZ;
- socket->sk->sk_sndtimeo = 5 * HZ;
-
- /* make the bufsizes depend on wsize/rsize and max requests */
- if (server->noautotune) {
- if (socket->sk->sk_sndbuf < (200 * 1024))
- socket->sk->sk_sndbuf = 200 * 1024;
- if (socket->sk->sk_rcvbuf < (140 * 1024))
- socket->sk->sk_rcvbuf = 140 * 1024;
- }
-
- if (server->tcp_nodelay)
- tcp_sock_set_nodelay(socket->sk);
-
- cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
- socket->sk->sk_sndbuf,
- socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
-
- rc = socket->ops->connect(socket, saddr, slen,
- server->noblockcnt ? O_NONBLOCK : 0);
- /*
- * When mounting SMB root file systems, we do not want to block in
- * connect. Otherwise bail out and then let cifs_reconnect() perform
- * reconnect failover - if possible.
- */
- if (server->noblockcnt && rc == -EINPROGRESS)
- rc = 0;
- if (rc < 0) {
- cifs_dbg(FYI, "Error %d connecting to server\n", rc);
- trace_smb3_connect_err(server->hostname, server->conn_id, &server->dstaddr, rc);
- sock_release(socket);
- server->ssocket = NULL;
- return rc;
- }
- trace_smb3_connect_done(server->hostname, server->conn_id, &server->dstaddr);
- if (sport == htons(RFC1001_PORT))
- rc = ip_rfc1001_connect(server);
-
- return rc;
-}
-
-static int
-ip_connect(struct TCP_Server_Info *server)
-{
- __be16 *sport;
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
- struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
-
- if (server->dstaddr.ss_family == AF_INET6)
- sport = &addr6->sin6_port;
- else
- sport = &addr->sin_port;
-
- if (*sport == 0) {
- int rc;
-
- /* try with 445 port at first */
- *sport = htons(CIFS_PORT);
-
- rc = generic_ip_connect(server);
- if (rc >= 0)
- return rc;
-
- /* if it failed, try with 139 port */
- *sport = htons(RFC1001_PORT);
- }
-
- return generic_ip_connect(server);
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
-{
- /*
- * If we are reconnecting then should we check to see if
- * any requested capabilities changed locally e.g. via
- * remount but we can not do much about it here
- * if they have (even if we could detect it by the following)
- * Perhaps we could add a backpointer to array of sb from tcon
- * or if we change to make all sb to same share the same
- * sb as NFS - then we only have one backpointer to sb.
- * What if we wanted to mount the server share twice once with
- * and once without posixacls or posix paths?
- */
- __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
-
- if (ctx && ctx->no_linux_ext) {
- tcon->fsUnixInfo.Capability = 0;
- tcon->unix_ext = 0; /* Unix Extensions disabled */
- cifs_dbg(FYI, "Linux protocol extensions disabled\n");
- return;
- } else if (ctx)
- tcon->unix_ext = 1; /* Unix Extensions supported */
-
- if (!tcon->unix_ext) {
- cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
- return;
- }
-
- if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
- __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
- cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
- /*
- * check for reconnect case in which we do not
- * want to change the mount behavior if we can avoid it
- */
- if (ctx == NULL) {
- /*
- * turn off POSIX ACL and PATHNAMES if not set
- * originally at mount time
- */
- if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
- cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
- if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
- if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
- cifs_dbg(VFS, "POSIXPATH support change\n");
- cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
- } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
- cifs_dbg(VFS, "possible reconnect error\n");
- cifs_dbg(VFS, "server disabled POSIX path support\n");
- }
- }
-
- if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
- cifs_dbg(VFS, "per-share encryption not supported yet\n");
-
- cap &= CIFS_UNIX_CAP_MASK;
- if (ctx && ctx->no_psx_acl)
- cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
- else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
- cifs_dbg(FYI, "negotiated posix acl support\n");
- if (cifs_sb)
- cifs_sb->mnt_cifs_flags |=
- CIFS_MOUNT_POSIXACL;
- }
-
- if (ctx && ctx->posix_paths == 0)
- cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
- else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
- cifs_dbg(FYI, "negotiate posix pathnames\n");
- if (cifs_sb)
- cifs_sb->mnt_cifs_flags |=
- CIFS_MOUNT_POSIX_PATHS;
- }
-
- cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
-#ifdef CONFIG_CIFS_DEBUG2
- if (cap & CIFS_UNIX_FCNTL_CAP)
- cifs_dbg(FYI, "FCNTL cap\n");
- if (cap & CIFS_UNIX_EXTATTR_CAP)
- cifs_dbg(FYI, "EXTATTR cap\n");
- if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
- cifs_dbg(FYI, "POSIX path cap\n");
- if (cap & CIFS_UNIX_XATTR_CAP)
- cifs_dbg(FYI, "XATTR cap\n");
- if (cap & CIFS_UNIX_POSIX_ACL_CAP)
- cifs_dbg(FYI, "POSIX ACL cap\n");
- if (cap & CIFS_UNIX_LARGE_READ_CAP)
- cifs_dbg(FYI, "very large read cap\n");
- if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
- cifs_dbg(FYI, "very large write cap\n");
- if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
- cifs_dbg(FYI, "transport encryption cap\n");
- if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
- cifs_dbg(FYI, "mandatory transport encryption cap\n");
-#endif /* CIFS_DEBUG2 */
- if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
- if (ctx == NULL)
- cifs_dbg(FYI, "resetting capabilities failed\n");
- else
- cifs_dbg(VFS, "Negotiating Unix capabilities with the server failed. Consider mounting with the Unix Extensions disabled if problems are found by specifying the nounix mount option.\n");
-
- }
- }
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
-{
- struct smb3_fs_context *ctx = cifs_sb->ctx;
-
- INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
-
- spin_lock_init(&cifs_sb->tlink_tree_lock);
- cifs_sb->tlink_tree = RB_ROOT;
-
- cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n",
- ctx->file_mode, ctx->dir_mode);
-
- /* this is needed for ASCII cp to Unicode converts */
- if (ctx->iocharset == NULL) {
- /* load_nls_default cannot return null */
- cifs_sb->local_nls = load_nls_default();
- } else {
- cifs_sb->local_nls = load_nls(ctx->iocharset);
- if (cifs_sb->local_nls == NULL) {
- cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
- ctx->iocharset);
- return -ELIBACC;
- }
- }
- ctx->local_nls = cifs_sb->local_nls;
-
- smb3_update_mnt_flags(cifs_sb);
-
- if (ctx->direct_io)
- cifs_dbg(FYI, "mounting share using direct i/o\n");
- if (ctx->cache_ro) {
- cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
- } else if (ctx->cache_rw) {
- cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
- cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
- CIFS_MOUNT_RW_CACHE);
- }
-
- if ((ctx->cifs_acl) && (ctx->dynperm))
- cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
-
- if (ctx->prepath) {
- cifs_sb->prepath = kstrdup(ctx->prepath, GFP_KERNEL);
- if (cifs_sb->prepath == NULL)
- return -ENOMEM;
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
- }
-
- return 0;
-}
-
-/* Release all succeed connections */
-static inline void mount_put_conns(struct mount_ctx *mnt_ctx)
-{
- int rc = 0;
-
- if (mnt_ctx->tcon)
- cifs_put_tcon(mnt_ctx->tcon);
- else if (mnt_ctx->ses)
- cifs_put_smb_ses(mnt_ctx->ses);
- else if (mnt_ctx->server)
- cifs_put_tcp_session(mnt_ctx->server, 0);
- mnt_ctx->cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
- free_xid(mnt_ctx->xid);
-}
-
-/* Get connections for tcp, ses and tcon */
-static int mount_get_conns(struct mount_ctx *mnt_ctx)
-{
- int rc = 0;
- struct TCP_Server_Info *server = NULL;
- struct cifs_ses *ses = NULL;
- struct cifs_tcon *tcon = NULL;
- struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
- struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
- unsigned int xid;
-
- xid = get_xid();
-
- /* get a reference to a tcp session */
- server = cifs_get_tcp_session(ctx, NULL);
- if (IS_ERR(server)) {
- rc = PTR_ERR(server);
- server = NULL;
- goto out;
- }
-
- /* get a reference to a SMB session */
- ses = cifs_get_smb_ses(server, ctx);
- if (IS_ERR(ses)) {
- rc = PTR_ERR(ses);
- ses = NULL;
- goto out;
- }
-
- if ((ctx->persistent == true) && (!(ses->server->capabilities &
- SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
- cifs_server_dbg(VFS, "persistent handles not supported by server\n");
- rc = -EOPNOTSUPP;
- goto out;
- }
-
- /* search for existing tcon to this server share */
- tcon = cifs_get_tcon(ses, ctx);
- if (IS_ERR(tcon)) {
- rc = PTR_ERR(tcon);
- tcon = NULL;
- goto out;
- }
-
- /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
- if (tcon->posix_extensions)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- /* tell server which Unix caps we support */
- if (cap_unix(tcon->ses)) {
- /*
- * reset of caps checks mount to see if unix extensions disabled
- * for just this mount.
- */
- reset_cifs_unix_caps(xid, tcon, cifs_sb, ctx);
- spin_lock(&tcon->ses->server->srv_lock);
- if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
- (le64_to_cpu(tcon->fsUnixInfo.Capability) &
- CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
- spin_unlock(&tcon->ses->server->srv_lock);
- rc = -EACCES;
- goto out;
- }
- spin_unlock(&tcon->ses->server->srv_lock);
- } else
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- tcon->unix_ext = 0; /* server does not support them */
-
- /* do not care if a following call succeed - informational */
- if (!tcon->pipe && server->ops->qfs_tcon) {
- server->ops->qfs_tcon(xid, tcon, cifs_sb);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
- if (tcon->fsDevInfo.DeviceCharacteristics &
- cpu_to_le32(FILE_READ_ONLY_DEVICE))
- cifs_dbg(VFS, "mounted to read only share\n");
- else if ((cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_RW_CACHE) == 0)
- cifs_dbg(VFS, "read only mount of RW share\n");
- /* no need to log a RW mount of a typical RW share */
- }
- }
-
- /*
- * Clamp the rsize/wsize mount arguments if they are too big for the server
- * and set the rsize/wsize to the negotiated values if not passed in by
- * the user on mount
- */
- if ((cifs_sb->ctx->wsize == 0) ||
- (cifs_sb->ctx->wsize > server->ops->negotiate_wsize(tcon, ctx)))
- cifs_sb->ctx->wsize = server->ops->negotiate_wsize(tcon, ctx);
- if ((cifs_sb->ctx->rsize == 0) ||
- (cifs_sb->ctx->rsize > server->ops->negotiate_rsize(tcon, ctx)))
- cifs_sb->ctx->rsize = server->ops->negotiate_rsize(tcon, ctx);
-
- /*
- * The cookie is initialized from volume info returned above.
- * Inside cifs_fscache_get_super_cookie it checks
- * that we do not get super cookie twice.
- */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
- cifs_fscache_get_super_cookie(tcon);
-
-out:
- mnt_ctx->server = server;
- mnt_ctx->ses = ses;
- mnt_ctx->tcon = tcon;
- mnt_ctx->xid = xid;
-
- return rc;
-}
-
-static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
- struct cifs_tcon *tcon)
-{
- struct tcon_link *tlink;
-
- /* hang the tcon off of the superblock */
- tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
- if (tlink == NULL)
- return -ENOMEM;
-
- tlink->tl_uid = ses->linux_uid;
- tlink->tl_tcon = tcon;
- tlink->tl_time = jiffies;
- set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
- set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
-
- cifs_sb->master_tlink = tlink;
- spin_lock(&cifs_sb->tlink_tree_lock);
- tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
- spin_unlock(&cifs_sb->tlink_tree_lock);
-
- queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
- TLINK_IDLE_EXPIRE);
- return 0;
-}
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
-/* Get unique dfs connections */
-static int mount_get_dfs_conns(struct mount_ctx *mnt_ctx)
-{
- int rc;
-
- mnt_ctx->fs_ctx->nosharesock = true;
- rc = mount_get_conns(mnt_ctx);
- if (mnt_ctx->server) {
- cifs_dbg(FYI, "%s: marking tcp session as a dfs connection\n", __func__);
- spin_lock(&mnt_ctx->server->srv_lock);
- mnt_ctx->server->is_dfs_conn = true;
- spin_unlock(&mnt_ctx->server->srv_lock);
- }
- return rc;
-}
-
-/*
- * cifs_build_path_to_root returns full path to root when we do not have an
- * existing connection (tcon)
- */
-static char *
-build_unc_path_to_root(const struct smb3_fs_context *ctx,
- const struct cifs_sb_info *cifs_sb, bool useppath)
-{
- char *full_path, *pos;
- unsigned int pplen = useppath && ctx->prepath ?
- strlen(ctx->prepath) + 1 : 0;
- unsigned int unc_len = strnlen(ctx->UNC, MAX_TREE_SIZE + 1);
-
- if (unc_len > MAX_TREE_SIZE)
- return ERR_PTR(-EINVAL);
-
- full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
- if (full_path == NULL)
- return ERR_PTR(-ENOMEM);
-
- memcpy(full_path, ctx->UNC, unc_len);
- pos = full_path + unc_len;
-
- if (pplen) {
- *pos = CIFS_DIR_SEP(cifs_sb);
- memcpy(pos + 1, ctx->prepath, pplen);
- pos += pplen;
- }
-
- *pos = '\0'; /* add trailing null */
- convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
- cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
- return full_path;
-}
-
-/*
- * expand_dfs_referral - Update cifs_sb from dfs referral path
- *
- * cifs_sb->ctx->mount_options will be (re-)allocated to a string containing updated options for the
- * submount. Otherwise it will be left untouched.
- */
-static int expand_dfs_referral(struct mount_ctx *mnt_ctx, const char *full_path,
- struct dfs_info3_param *referral)
-{
- int rc;
- struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
- struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
- char *fake_devname = NULL, *mdata = NULL;
-
- mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, full_path + 1, referral,
- &fake_devname);
- if (IS_ERR(mdata)) {
- rc = PTR_ERR(mdata);
- mdata = NULL;
- } else {
- /*
- * We can not clear out the whole structure since we no longer have an explicit
- * function to parse a mount-string. Instead we need to clear out the individual
- * fields that are no longer valid.
- */
- kfree(ctx->prepath);
- ctx->prepath = NULL;
- rc = cifs_setup_volume_info(ctx, mdata, fake_devname);
- }
- kfree(fake_devname);
- kfree(cifs_sb->ctx->mount_options);
- cifs_sb->ctx->mount_options = mdata;
-
- return rc;
-}
-#endif
-
-/* TODO: all callers to this are broken. We are not parsing mount_options here
- * we should pass a clone of the original context?
- */
-int
-cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname)
-{
- int rc;
-
- if (devname) {
- cifs_dbg(FYI, "%s: devname=%s\n", __func__, devname);
- rc = smb3_parse_devname(devname, ctx);
- if (rc) {
- cifs_dbg(VFS, "%s: failed to parse %s: %d\n", __func__, devname, rc);
- return rc;
- }
- }
-
- if (mntopts) {
- char *ip;
-
- rc = smb3_parse_opt(mntopts, "ip", &ip);
- if (rc) {
- cifs_dbg(VFS, "%s: failed to parse ip options: %d\n", __func__, rc);
- return rc;
- }
-
- rc = cifs_convert_address((struct sockaddr *)&ctx->dstaddr, ip, strlen(ip));
- kfree(ip);
- if (!rc) {
- cifs_dbg(VFS, "%s: failed to convert ip address\n", __func__);
- return -EINVAL;
- }
- }
-
- if (ctx->nullauth) {
- cifs_dbg(FYI, "Anonymous login\n");
- kfree(ctx->username);
- ctx->username = NULL;
- } else if (ctx->username) {
- /* BB fixme parse for domain name here */
- cifs_dbg(FYI, "Username: %s\n", ctx->username);
- } else {
- cifs_dbg(VFS, "No username specified\n");
- /* In userspace mount helper we can get user name from alternate
- locations such as env variables and files on disk */
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int
-cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
- unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- char *full_path,
- int added_treename)
-{
- int rc;
- char *s;
- char sep, tmp;
- int skip = added_treename ? 1 : 0;
-
- sep = CIFS_DIR_SEP(cifs_sb);
- s = full_path;
-
- rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
- while (rc == 0) {
- /* skip separators */
- while (*s == sep)
- s++;
- if (!*s)
- break;
- /* next separator */
- while (*s && *s != sep)
- s++;
- /*
- * if the treename is added, we then have to skip the first
- * part within the separators
- */
- if (skip) {
- skip = 0;
- continue;
- }
- /*
- * temporarily null-terminate the path at the end of
- * the current component
- */
- tmp = *s;
- *s = 0;
- rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
- full_path);
- *s = tmp;
- }
- return rc;
-}
-
-/*
- * Check if path is remote (i.e. a DFS share).
- *
- * Return -EREMOTE if it is, otherwise 0 or -errno.
- */
-static int is_path_remote(struct mount_ctx *mnt_ctx)
-{
- int rc;
- struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
- struct TCP_Server_Info *server = mnt_ctx->server;
- unsigned int xid = mnt_ctx->xid;
- struct cifs_tcon *tcon = mnt_ctx->tcon;
- struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
- char *full_path;
-
- if (!server->ops->is_path_accessible)
- return -EOPNOTSUPP;
-
- /*
- * cifs_build_path_to_root works only when we have a valid tcon
- */
- full_path = cifs_build_path_to_root(ctx, cifs_sb, tcon,
- tcon->Flags & SMB_SHARE_IS_IN_DFS);
- if (full_path == NULL)
- return -ENOMEM;
-
- cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
-
- rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
- full_path);
- if (rc != 0 && rc != -EREMOTE)
- goto out;
-
- if (rc != -EREMOTE) {
- rc = cifs_are_all_path_components_accessible(server, xid, tcon,
- cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
- if (rc != 0) {
- cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
- rc = 0;
- }
- }
-
-out:
- kfree(full_path);
- return rc;
-}
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
-static void set_root_ses(struct mount_ctx *mnt_ctx)
-{
- if (mnt_ctx->ses) {
- spin_lock(&cifs_tcp_ses_lock);
- mnt_ctx->ses->ses_count++;
- spin_unlock(&cifs_tcp_ses_lock);
- dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, mnt_ctx->ses);
- }
- mnt_ctx->root_ses = mnt_ctx->ses;
-}
-
-static int is_dfs_mount(struct mount_ctx *mnt_ctx, bool *isdfs, struct dfs_cache_tgt_list *root_tl)
-{
- int rc;
- struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
- struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
-
- *isdfs = true;
-
- rc = mount_get_conns(mnt_ctx);
- /*
- * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally
- * try to get an DFS referral (even cached) to determine whether it is an DFS mount.
- *
- * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem
- * to respond with PATH_NOT_COVERED to requests that include the prefix.
- */
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) ||
- dfs_cache_find(mnt_ctx->xid, mnt_ctx->ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
- ctx->UNC + 1, NULL, root_tl)) {
- if (rc)
- return rc;
- /* Check if it is fully accessible and then mount it */
- rc = is_path_remote(mnt_ctx);
- if (!rc)
- *isdfs = false;
- else if (rc != -EREMOTE)
- return rc;
- }
- return 0;
-}
-
-static int connect_dfs_target(struct mount_ctx *mnt_ctx, const char *full_path,
- const char *ref_path, struct dfs_cache_tgt_iterator *tit)
-{
- int rc;
- struct dfs_info3_param ref = {};
- struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
- char *oldmnt = cifs_sb->ctx->mount_options;
-
- cifs_dbg(FYI, "%s: full_path=%s ref_path=%s target=%s\n", __func__, full_path, ref_path,
- dfs_cache_get_tgt_name(tit));
-
- rc = dfs_cache_get_tgt_referral(ref_path, tit, &ref);
- if (rc)
- goto out;
-
- rc = expand_dfs_referral(mnt_ctx, full_path, &ref);
- if (rc)
- goto out;
-
- /* Connect to new target only if we were redirected (e.g. mount options changed) */
- if (oldmnt != cifs_sb->ctx->mount_options) {
- mount_put_conns(mnt_ctx);
- rc = mount_get_dfs_conns(mnt_ctx);
- }
- if (!rc) {
- if (cifs_is_referral_server(mnt_ctx->tcon, &ref))
- set_root_ses(mnt_ctx);
- rc = dfs_cache_update_tgthint(mnt_ctx->xid, mnt_ctx->root_ses, cifs_sb->local_nls,
- cifs_remap(cifs_sb), ref_path, tit);
- }
-
-out:
- free_dfs_info_param(&ref);
- return rc;
-}
-
-static int connect_dfs_root(struct mount_ctx *mnt_ctx, struct dfs_cache_tgt_list *root_tl)
-{
- int rc;
- char *full_path;
- struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
- struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
- struct dfs_cache_tgt_iterator *tit;
-
- /* Put initial connections as they might be shared with other mounts. We need unique dfs
- * connections per mount to properly failover, so mount_get_dfs_conns() must be used from
- * now on.
- */
- mount_put_conns(mnt_ctx);
- mount_get_dfs_conns(mnt_ctx);
- set_root_ses(mnt_ctx);
-
- full_path = build_unc_path_to_root(ctx, cifs_sb, true);
- if (IS_ERR(full_path))
- return PTR_ERR(full_path);
-
- mnt_ctx->origin_fullpath = dfs_cache_canonical_path(ctx->UNC, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- if (IS_ERR(mnt_ctx->origin_fullpath)) {
- rc = PTR_ERR(mnt_ctx->origin_fullpath);
- mnt_ctx->origin_fullpath = NULL;
- goto out;
- }
-
- /* Try all dfs root targets */
- for (rc = -ENOENT, tit = dfs_cache_get_tgt_iterator(root_tl);
- tit; tit = dfs_cache_get_next_tgt(root_tl, tit)) {
- rc = connect_dfs_target(mnt_ctx, full_path, mnt_ctx->origin_fullpath + 1, tit);
- if (!rc) {
- mnt_ctx->leaf_fullpath = kstrdup(mnt_ctx->origin_fullpath, GFP_KERNEL);
- if (!mnt_ctx->leaf_fullpath)
- rc = -ENOMEM;
- break;
- }
- }
-
-out:
- kfree(full_path);
- return rc;
-}
-
-static int __follow_dfs_link(struct mount_ctx *mnt_ctx)
-{
- int rc;
- struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
- struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
- char *full_path;
- struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
- struct dfs_cache_tgt_iterator *tit;
-
- full_path = build_unc_path_to_root(ctx, cifs_sb, true);
- if (IS_ERR(full_path))
- return PTR_ERR(full_path);
-
- kfree(mnt_ctx->leaf_fullpath);
- mnt_ctx->leaf_fullpath = dfs_cache_canonical_path(full_path, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- if (IS_ERR(mnt_ctx->leaf_fullpath)) {
- rc = PTR_ERR(mnt_ctx->leaf_fullpath);
- mnt_ctx->leaf_fullpath = NULL;
- goto out;
- }
-
- /* Get referral from dfs link */
- rc = dfs_cache_find(mnt_ctx->xid, mnt_ctx->root_ses, cifs_sb->local_nls,
- cifs_remap(cifs_sb), mnt_ctx->leaf_fullpath + 1, NULL, &tl);
- if (rc)
- goto out;
-
- /* Try all dfs link targets. If an I/O fails from currently connected DFS target with an
- * error other than STATUS_PATH_NOT_COVERED (-EREMOTE), then retry it from other targets as
- * specified in MS-DFSC "3.1.5.2 I/O Operation to Target Fails with an Error Other Than
- * STATUS_PATH_NOT_COVERED."
- */
- for (rc = -ENOENT, tit = dfs_cache_get_tgt_iterator(&tl);
- tit; tit = dfs_cache_get_next_tgt(&tl, tit)) {
- rc = connect_dfs_target(mnt_ctx, full_path, mnt_ctx->leaf_fullpath + 1, tit);
- if (!rc) {
- rc = is_path_remote(mnt_ctx);
- if (!rc || rc == -EREMOTE)
- break;
- }
- }
-
-out:
- kfree(full_path);
- dfs_cache_free_tgts(&tl);
- return rc;
-}
-
-static int follow_dfs_link(struct mount_ctx *mnt_ctx)
-{
- int rc;
- struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
- struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
- char *full_path;
- int num_links = 0;
-
- full_path = build_unc_path_to_root(ctx, cifs_sb, true);
- if (IS_ERR(full_path))
- return PTR_ERR(full_path);
-
- kfree(mnt_ctx->origin_fullpath);
- mnt_ctx->origin_fullpath = dfs_cache_canonical_path(full_path, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- kfree(full_path);
-
- if (IS_ERR(mnt_ctx->origin_fullpath)) {
- rc = PTR_ERR(mnt_ctx->origin_fullpath);
- mnt_ctx->origin_fullpath = NULL;
- return rc;
- }
-
- do {
- rc = __follow_dfs_link(mnt_ctx);
- if (!rc || rc != -EREMOTE)
- break;
- } while (rc = -ELOOP, ++num_links < MAX_NESTED_LINKS);
-
- return rc;
-}
-
-/* Set up DFS referral paths for failover */
-static void setup_server_referral_paths(struct mount_ctx *mnt_ctx)
-{
- struct TCP_Server_Info *server = mnt_ctx->server;
-
- mutex_lock(&server->refpath_lock);
- server->origin_fullpath = mnt_ctx->origin_fullpath;
- server->leaf_fullpath = mnt_ctx->leaf_fullpath;
- server->current_fullpath = mnt_ctx->leaf_fullpath;
- mutex_unlock(&server->refpath_lock);
- mnt_ctx->origin_fullpath = mnt_ctx->leaf_fullpath = NULL;
-}
-
-int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
-{
- int rc;
- struct mount_ctx mnt_ctx = { .cifs_sb = cifs_sb, .fs_ctx = ctx, };
- struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
- bool isdfs;
-
- rc = is_dfs_mount(&mnt_ctx, &isdfs, &tl);
- if (rc)
- goto error;
- if (!isdfs)
- goto out;
-
- /* proceed as DFS mount */
- uuid_gen(&mnt_ctx.mount_id);
- rc = connect_dfs_root(&mnt_ctx, &tl);
- dfs_cache_free_tgts(&tl);
-
- if (rc)
- goto error;
-
- rc = is_path_remote(&mnt_ctx);
- if (rc)
- rc = follow_dfs_link(&mnt_ctx);
- if (rc)
- goto error;
-
- setup_server_referral_paths(&mnt_ctx);
- /*
- * After reconnecting to a different server, unique ids won't match anymore, so we disable
- * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE).
- */
- cifs_autodisable_serverino(cifs_sb);
- /*
- * Force the use of prefix path to support failover on DFS paths that resolve to targets
- * that have different prefix paths.
- */
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
- kfree(cifs_sb->prepath);
- cifs_sb->prepath = ctx->prepath;
- ctx->prepath = NULL;
- uuid_copy(&cifs_sb->dfs_mount_id, &mnt_ctx.mount_id);
-
-out:
- cifs_try_adding_channels(cifs_sb, mnt_ctx.ses);
- rc = mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon);
- if (rc)
- goto error;
-
- free_xid(mnt_ctx.xid);
- return rc;
-
-error:
- dfs_cache_put_refsrv_sessions(&mnt_ctx.mount_id);
- kfree(mnt_ctx.origin_fullpath);
- kfree(mnt_ctx.leaf_fullpath);
- mount_put_conns(&mnt_ctx);
- return rc;
-}
-#else
-int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
-{
- int rc = 0;
- struct mount_ctx mnt_ctx = { .cifs_sb = cifs_sb, .fs_ctx = ctx, };
-
- rc = mount_get_conns(&mnt_ctx);
- if (rc)
- goto error;
-
- if (mnt_ctx.tcon) {
- rc = is_path_remote(&mnt_ctx);
- if (rc == -EREMOTE)
- rc = -EOPNOTSUPP;
- if (rc)
- goto error;
- }
-
- rc = mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon);
- if (rc)
- goto error;
-
- free_xid(mnt_ctx.xid);
- return rc;
-
-error:
- mount_put_conns(&mnt_ctx);
- return rc;
-}
-#endif
-
-/*
- * Issue a TREE_CONNECT request.
- */
-int
-CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
- const char *tree, struct cifs_tcon *tcon,
- const struct nls_table *nls_codepage)
-{
- struct smb_hdr *smb_buffer;
- struct smb_hdr *smb_buffer_response;
- TCONX_REQ *pSMB;
- TCONX_RSP *pSMBr;
- unsigned char *bcc_ptr;
- int rc = 0;
- int length;
- __u16 bytes_left, count;
-
- if (ses == NULL)
- return -EIO;
-
- smb_buffer = cifs_buf_get();
- if (smb_buffer == NULL)
- return -ENOMEM;
-
- smb_buffer_response = smb_buffer;
-
- header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
- NULL /*no tid */ , 4 /*wct */ );
-
- smb_buffer->Mid = get_next_mid(ses->server);
- smb_buffer->Uid = ses->Suid;
- pSMB = (TCONX_REQ *) smb_buffer;
- pSMBr = (TCONX_RSP *) smb_buffer_response;
-
- pSMB->AndXCommand = 0xFF;
- pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
- bcc_ptr = &pSMB->Password[0];
-
- pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
- *bcc_ptr = 0; /* password is null byte */
- bcc_ptr++; /* skip password */
- /* already aligned so no need to do it below */
-
- if (ses->server->sign)
- smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- if (ses->capabilities & CAP_STATUS32) {
- smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
- }
- if (ses->capabilities & CAP_DFS) {
- smb_buffer->Flags2 |= SMBFLG2_DFS;
- }
- if (ses->capabilities & CAP_UNICODE) {
- smb_buffer->Flags2 |= SMBFLG2_UNICODE;
- length =
- cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
- 6 /* max utf8 char length in bytes */ *
- (/* server len*/ + 256 /* share len */), nls_codepage);
- bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
- bcc_ptr += 2; /* skip trailing null */
- } else { /* ASCII */
- strcpy(bcc_ptr, tree);
- bcc_ptr += strlen(tree) + 1;
- }
- strcpy(bcc_ptr, "?????");
- bcc_ptr += strlen("?????");
- bcc_ptr += 1;
- count = bcc_ptr - &pSMB->Password[0];
- be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
- pSMB->ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
- 0);
-
- /* above now done in SendReceive */
- if (rc == 0) {
- bool is_unicode;
-
- tcon->tid = smb_buffer_response->Tid;
- bcc_ptr = pByteArea(smb_buffer_response);
- bytes_left = get_bcc(smb_buffer_response);
- length = strnlen(bcc_ptr, bytes_left - 2);
- if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
- is_unicode = true;
- else
- is_unicode = false;
-
-
- /* skip service field (NB: this field is always ASCII) */
- if (length == 3) {
- if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
- (bcc_ptr[2] == 'C')) {
- cifs_dbg(FYI, "IPC connection\n");
- tcon->ipc = true;
- tcon->pipe = true;
- }
- } else if (length == 2) {
- if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
- /* the most common case */
- cifs_dbg(FYI, "disk share connection\n");
- }
- }
- bcc_ptr += length + 1;
- bytes_left -= (length + 1);
- strscpy(tcon->tree_name, tree, sizeof(tcon->tree_name));
-
- /* mostly informational -- no need to fail on error here */
- kfree(tcon->nativeFileSystem);
- tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
- bytes_left, is_unicode,
- nls_codepage);
-
- cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
-
- if ((smb_buffer_response->WordCount == 3) ||
- (smb_buffer_response->WordCount == 7))
- /* field is in same location */
- tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
- else
- tcon->Flags = 0;
- cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
- }
-
- cifs_buf_release(smb_buffer);
- return rc;
-}
-
-static void delayed_free(struct rcu_head *p)
-{
- struct cifs_sb_info *cifs_sb = container_of(p, struct cifs_sb_info, rcu);
-
- unload_nls(cifs_sb->local_nls);
- smb3_cleanup_fs_context(cifs_sb->ctx);
- kfree(cifs_sb);
-}
-
-void
-cifs_umount(struct cifs_sb_info *cifs_sb)
-{
- struct rb_root *root = &cifs_sb->tlink_tree;
- struct rb_node *node;
- struct tcon_link *tlink;
-
- cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
-
- spin_lock(&cifs_sb->tlink_tree_lock);
- while ((node = rb_first(root))) {
- tlink = rb_entry(node, struct tcon_link, tl_rbnode);
- cifs_get_tlink(tlink);
- clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
- rb_erase(node, root);
-
- spin_unlock(&cifs_sb->tlink_tree_lock);
- cifs_put_tlink(tlink);
- spin_lock(&cifs_sb->tlink_tree_lock);
- }
- spin_unlock(&cifs_sb->tlink_tree_lock);
-
- kfree(cifs_sb->prepath);
-#ifdef CONFIG_CIFS_DFS_UPCALL
- dfs_cache_put_refsrv_sessions(&cifs_sb->dfs_mount_id);
-#endif
- call_rcu(&cifs_sb->rcu, delayed_free);
-}
-
-int
-cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- int rc = 0;
-
- if (!server->ops->need_neg || !server->ops->negotiate)
- return -ENOSYS;
-
- /* only send once per connect */
- spin_lock(&server->srv_lock);
- if (server->tcpStatus != CifsGood &&
- server->tcpStatus != CifsNew &&
- server->tcpStatus != CifsNeedNegotiate) {
- spin_unlock(&server->srv_lock);
- return -EHOSTDOWN;
- }
-
- if (!server->ops->need_neg(server) &&
- server->tcpStatus == CifsGood) {
- spin_unlock(&server->srv_lock);
- return 0;
- }
-
- server->tcpStatus = CifsInNegotiate;
- spin_unlock(&server->srv_lock);
-
- rc = server->ops->negotiate(xid, ses, server);
- if (rc == 0) {
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsInNegotiate)
- server->tcpStatus = CifsGood;
- else
- rc = -EHOSTDOWN;
- spin_unlock(&server->srv_lock);
- } else {
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsInNegotiate)
- server->tcpStatus = CifsNeedNegotiate;
- spin_unlock(&server->srv_lock);
- }
-
- return rc;
-}
-
-int
-cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- struct nls_table *nls_info)
-{
- int rc = -ENOSYS;
- struct TCP_Server_Info *pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr;
- struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr;
- bool is_binding = false;
-
- spin_lock(&ses->ses_lock);
- cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
- __func__, ses->chans_need_reconnect);
-
- if (ses->ses_status != SES_GOOD &&
- ses->ses_status != SES_NEW &&
- ses->ses_status != SES_NEED_RECON) {
- spin_unlock(&ses->ses_lock);
- return -EHOSTDOWN;
- }
-
- /* only send once per connect */
- spin_lock(&ses->chan_lock);
- if (CIFS_ALL_CHANS_GOOD(ses)) {
- if (ses->ses_status == SES_NEED_RECON)
- ses->ses_status = SES_GOOD;
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
- return 0;
- }
-
- cifs_chan_set_in_reconnect(ses, server);
- is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
- spin_unlock(&ses->chan_lock);
-
- if (!is_binding)
- ses->ses_status = SES_IN_SETUP;
- spin_unlock(&ses->ses_lock);
-
- /* update ses ip_addr only for primary chan */
- if (server == pserver) {
- if (server->dstaddr.ss_family == AF_INET6)
- scnprintf(ses->ip_addr, sizeof(ses->ip_addr), "%pI6", &addr6->sin6_addr);
- else
- scnprintf(ses->ip_addr, sizeof(ses->ip_addr), "%pI4", &addr->sin_addr);
- }
-
- if (!is_binding) {
- ses->capabilities = server->capabilities;
- if (!linuxExtEnabled)
- ses->capabilities &= (~server->vals->cap_unix);
-
- if (ses->auth_key.response) {
- cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
- ses->auth_key.response);
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.response = NULL;
- ses->auth_key.len = 0;
- }
- }
-
- cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
- server->sec_mode, server->capabilities, server->timeAdj);
-
- if (server->ops->sess_setup)
- rc = server->ops->sess_setup(xid, ses, server, nls_info);
-
- if (rc) {
- cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
- spin_lock(&ses->ses_lock);
- if (ses->ses_status == SES_IN_SETUP)
- ses->ses_status = SES_NEED_RECON;
- spin_lock(&ses->chan_lock);
- cifs_chan_clear_in_reconnect(ses, server);
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
- } else {
- spin_lock(&ses->ses_lock);
- if (ses->ses_status == SES_IN_SETUP)
- ses->ses_status = SES_GOOD;
- spin_lock(&ses->chan_lock);
- cifs_chan_clear_in_reconnect(ses, server);
- cifs_chan_clear_need_reconnect(ses, server);
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
- }
-
- return rc;
-}
-
-static int
-cifs_set_vol_auth(struct smb3_fs_context *ctx, struct cifs_ses *ses)
-{
- ctx->sectype = ses->sectype;
-
- /* krb5 is special, since we don't need username or pw */
- if (ctx->sectype == Kerberos)
- return 0;
-
- return cifs_set_cifscreds(ctx, ses);
-}
-
-static struct cifs_tcon *
-cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
-{
- int rc;
- struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
- struct cifs_ses *ses;
- struct cifs_tcon *tcon = NULL;
- struct smb3_fs_context *ctx;
-
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
- if (ctx == NULL)
- return ERR_PTR(-ENOMEM);
-
- ctx->local_nls = cifs_sb->local_nls;
- ctx->linux_uid = fsuid;
- ctx->cred_uid = fsuid;
- ctx->UNC = master_tcon->tree_name;
- ctx->retry = master_tcon->retry;
- ctx->nocase = master_tcon->nocase;
- ctx->nohandlecache = master_tcon->nohandlecache;
- ctx->local_lease = master_tcon->local_lease;
- ctx->no_lease = master_tcon->no_lease;
- ctx->resilient = master_tcon->use_resilient;
- ctx->persistent = master_tcon->use_persistent;
- ctx->handle_timeout = master_tcon->handle_timeout;
- ctx->no_linux_ext = !master_tcon->unix_ext;
- ctx->linux_ext = master_tcon->posix_extensions;
- ctx->sectype = master_tcon->ses->sectype;
- ctx->sign = master_tcon->ses->sign;
- ctx->seal = master_tcon->seal;
- ctx->witness = master_tcon->use_witness;
-
- rc = cifs_set_vol_auth(ctx, master_tcon->ses);
- if (rc) {
- tcon = ERR_PTR(rc);
- goto out;
- }
-
- /* get a reference for the same TCP session */
- spin_lock(&cifs_tcp_ses_lock);
- ++master_tcon->ses->server->srv_count;
- spin_unlock(&cifs_tcp_ses_lock);
-
- ses = cifs_get_smb_ses(master_tcon->ses->server, ctx);
- if (IS_ERR(ses)) {
- tcon = (struct cifs_tcon *)ses;
- cifs_put_tcp_session(master_tcon->ses->server, 0);
- goto out;
- }
-
- tcon = cifs_get_tcon(ses, ctx);
- if (IS_ERR(tcon)) {
- cifs_put_smb_ses(ses);
- goto out;
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (cap_unix(ses))
- reset_cifs_unix_caps(0, tcon, NULL, ctx);
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-out:
- kfree(ctx->username);
- kfree_sensitive(ctx->password);
- kfree(ctx);
-
- return tcon;
-}
-
-struct cifs_tcon *
-cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
-{
- return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
-}
-
-/* find and return a tlink with given uid */
-static struct tcon_link *
-tlink_rb_search(struct rb_root *root, kuid_t uid)
-{
- struct rb_node *node = root->rb_node;
- struct tcon_link *tlink;
-
- while (node) {
- tlink = rb_entry(node, struct tcon_link, tl_rbnode);
-
- if (uid_gt(tlink->tl_uid, uid))
- node = node->rb_left;
- else if (uid_lt(tlink->tl_uid, uid))
- node = node->rb_right;
- else
- return tlink;
- }
- return NULL;
-}
-
-/* insert a tcon_link into the tree */
-static void
-tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
-{
- struct rb_node **new = &(root->rb_node), *parent = NULL;
- struct tcon_link *tlink;
-
- while (*new) {
- tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
- parent = *new;
-
- if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
- new = &((*new)->rb_left);
- else
- new = &((*new)->rb_right);
- }
-
- rb_link_node(&new_tlink->tl_rbnode, parent, new);
- rb_insert_color(&new_tlink->tl_rbnode, root);
-}
-
-/*
- * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
- * current task.
- *
- * If the superblock doesn't refer to a multiuser mount, then just return
- * the master tcon for the mount.
- *
- * First, search the rbtree for an existing tcon for this fsuid. If one
- * exists, then check to see if it's pending construction. If it is then wait
- * for construction to complete. Once it's no longer pending, check to see if
- * it failed and either return an error or retry construction, depending on
- * the timeout.
- *
- * If one doesn't exist then insert a new tcon_link struct into the tree and
- * try to construct a new one.
- */
-struct tcon_link *
-cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
-{
- int ret;
- kuid_t fsuid = current_fsuid();
- struct tcon_link *tlink, *newtlink;
-
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
- return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
-
- spin_lock(&cifs_sb->tlink_tree_lock);
- tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
- if (tlink)
- cifs_get_tlink(tlink);
- spin_unlock(&cifs_sb->tlink_tree_lock);
-
- if (tlink == NULL) {
- newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
- if (newtlink == NULL)
- return ERR_PTR(-ENOMEM);
- newtlink->tl_uid = fsuid;
- newtlink->tl_tcon = ERR_PTR(-EACCES);
- set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
- set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
- cifs_get_tlink(newtlink);
-
- spin_lock(&cifs_sb->tlink_tree_lock);
- /* was one inserted after previous search? */
- tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
- if (tlink) {
- cifs_get_tlink(tlink);
- spin_unlock(&cifs_sb->tlink_tree_lock);
- kfree(newtlink);
- goto wait_for_construction;
- }
- tlink = newtlink;
- tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
- spin_unlock(&cifs_sb->tlink_tree_lock);
- } else {
-wait_for_construction:
- ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
- TASK_INTERRUPTIBLE);
- if (ret) {
- cifs_put_tlink(tlink);
- return ERR_PTR(-ERESTARTSYS);
- }
-
- /* if it's good, return it */
- if (!IS_ERR(tlink->tl_tcon))
- return tlink;
-
- /* return error if we tried this already recently */
- if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
- cifs_put_tlink(tlink);
- return ERR_PTR(-EACCES);
- }
-
- if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
- goto wait_for_construction;
- }
-
- tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
- clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
- wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
-
- if (IS_ERR(tlink->tl_tcon)) {
- cifs_put_tlink(tlink);
- return ERR_PTR(-EACCES);
- }
-
- return tlink;
-}
-
-/*
- * periodic workqueue job that scans tcon_tree for a superblock and closes
- * out tcons.
- */
-static void
-cifs_prune_tlinks(struct work_struct *work)
-{
- struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
- prune_tlinks.work);
- struct rb_root *root = &cifs_sb->tlink_tree;
- struct rb_node *node;
- struct rb_node *tmp;
- struct tcon_link *tlink;
-
- /*
- * Because we drop the spinlock in the loop in order to put the tlink
- * it's not guarded against removal of links from the tree. The only
- * places that remove entries from the tree are this function and
- * umounts. Because this function is non-reentrant and is canceled
- * before umount can proceed, this is safe.
- */
- spin_lock(&cifs_sb->tlink_tree_lock);
- node = rb_first(root);
- while (node != NULL) {
- tmp = node;
- node = rb_next(tmp);
- tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
-
- if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
- atomic_read(&tlink->tl_count) != 0 ||
- time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
- continue;
-
- cifs_get_tlink(tlink);
- clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
- rb_erase(tmp, root);
-
- spin_unlock(&cifs_sb->tlink_tree_lock);
- cifs_put_tlink(tlink);
- spin_lock(&cifs_sb->tlink_tree_lock);
- }
- spin_unlock(&cifs_sb->tlink_tree_lock);
-
- queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
- TLINK_IDLE_EXPIRE);
-}
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
-/* Update dfs referral path of superblock */
-static int update_server_fullpath(struct TCP_Server_Info *server, struct cifs_sb_info *cifs_sb,
- const char *target)
-{
- int rc = 0;
- size_t len = strlen(target);
- char *refpath, *npath;
-
- if (unlikely(len < 2 || *target != '\\'))
- return -EINVAL;
-
- if (target[1] == '\\') {
- len += 1;
- refpath = kmalloc(len, GFP_KERNEL);
- if (!refpath)
- return -ENOMEM;
-
- scnprintf(refpath, len, "%s", target);
- } else {
- len += sizeof("\\");
- refpath = kmalloc(len, GFP_KERNEL);
- if (!refpath)
- return -ENOMEM;
-
- scnprintf(refpath, len, "\\%s", target);
- }
-
- npath = dfs_cache_canonical_path(refpath, cifs_sb->local_nls, cifs_remap(cifs_sb));
- kfree(refpath);
-
- if (IS_ERR(npath)) {
- rc = PTR_ERR(npath);
- } else {
- mutex_lock(&server->refpath_lock);
- kfree(server->leaf_fullpath);
- server->leaf_fullpath = npath;
- mutex_unlock(&server->refpath_lock);
- server->current_fullpath = server->leaf_fullpath;
- }
- return rc;
-}
-
-static int target_share_matches_server(struct TCP_Server_Info *server, const char *tcp_host,
- size_t tcp_host_len, char *share, bool *target_match)
-{
- int rc = 0;
- const char *dfs_host;
- size_t dfs_host_len;
-
- *target_match = true;
- extract_unc_hostname(share, &dfs_host, &dfs_host_len);
-
- /* Check if hostnames or addresses match */
- if (dfs_host_len != tcp_host_len || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
- cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
- dfs_host, (int)tcp_host_len, tcp_host);
- rc = match_target_ip(server, dfs_host, dfs_host_len, target_match);
- if (rc)
- cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
- }
- return rc;
-}
-
-static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, char *tree, bool islink,
- struct dfs_cache_tgt_list *tl)
-{
- int rc;
- struct TCP_Server_Info *server = tcon->ses->server;
- const struct smb_version_operations *ops = server->ops;
- struct cifs_tcon *ipc = tcon->ses->tcon_ipc;
- char *share = NULL, *prefix = NULL;
- const char *tcp_host;
- size_t tcp_host_len;
- struct dfs_cache_tgt_iterator *tit;
- bool target_match;
-
- extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
-
- tit = dfs_cache_get_tgt_iterator(tl);
- if (!tit) {
- rc = -ENOENT;
- goto out;
- }
-
- /* Try to tree connect to all dfs targets */
- for (; tit; tit = dfs_cache_get_next_tgt(tl, tit)) {
- const char *target = dfs_cache_get_tgt_name(tit);
- struct dfs_cache_tgt_list ntl = DFS_CACHE_TGT_LIST_INIT(ntl);
-
- kfree(share);
- kfree(prefix);
- share = prefix = NULL;
-
- /* Check if share matches with tcp ses */
- rc = dfs_cache_get_tgt_share(server->current_fullpath + 1, tit, &share, &prefix);
- if (rc) {
- cifs_dbg(VFS, "%s: failed to parse target share: %d\n", __func__, rc);
- break;
- }
-
- rc = target_share_matches_server(server, tcp_host, tcp_host_len, share,
- &target_match);
- if (rc)
- break;
- if (!target_match) {
- rc = -EHOSTUNREACH;
- continue;
- }
-
- if (ipc->need_reconnect) {
- scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
- rc = ops->tree_connect(xid, ipc->ses, tree, ipc, cifs_sb->local_nls);
- if (rc)
- break;
- }
-
- scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
- if (!islink) {
- rc = ops->tree_connect(xid, tcon->ses, tree, tcon, cifs_sb->local_nls);
- break;
- }
- /*
- * If no dfs referrals were returned from link target, then just do a TREE_CONNECT
- * to it. Otherwise, cache the dfs referral and then mark current tcp ses for
- * reconnect so either the demultiplex thread or the echo worker will reconnect to
- * newly resolved target.
- */
- if (dfs_cache_find(xid, tcon->ses, cifs_sb->local_nls, cifs_remap(cifs_sb), target,
- NULL, &ntl)) {
- rc = ops->tree_connect(xid, tcon->ses, tree, tcon, cifs_sb->local_nls);
- if (rc)
- continue;
- rc = dfs_cache_noreq_update_tgthint(server->current_fullpath + 1, tit);
- if (!rc)
- rc = cifs_update_super_prepath(cifs_sb, prefix);
- } else {
- /* Target is another dfs share */
- rc = update_server_fullpath(server, cifs_sb, target);
- dfs_cache_free_tgts(tl);
-
- if (!rc) {
- rc = -EREMOTE;
- list_replace_init(&ntl.tl_list, &tl->tl_list);
- } else
- dfs_cache_free_tgts(&ntl);
- }
- break;
- }
-
-out:
- kfree(share);
- kfree(prefix);
-
- return rc;
-}
-
-static int tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, char *tree, bool islink,
- struct dfs_cache_tgt_list *tl)
-{
- int rc;
- int num_links = 0;
- struct TCP_Server_Info *server = tcon->ses->server;
-
- do {
- rc = __tree_connect_dfs_target(xid, tcon, cifs_sb, tree, islink, tl);
- if (!rc || rc != -EREMOTE)
- break;
- } while (rc = -ELOOP, ++num_links < MAX_NESTED_LINKS);
- /*
- * If we couldn't tree connect to any targets from last referral path, then retry from
- * original referral path.
- */
- if (rc && server->current_fullpath != server->origin_fullpath) {
- server->current_fullpath = server->origin_fullpath;
- cifs_signal_cifsd_for_reconnect(server, true);
- }
-
- dfs_cache_free_tgts(tl);
- return rc;
-}
-
-int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
-{
- int rc;
- struct TCP_Server_Info *server = tcon->ses->server;
- const struct smb_version_operations *ops = server->ops;
- struct super_block *sb = NULL;
- struct cifs_sb_info *cifs_sb;
- struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
- char *tree;
- struct dfs_info3_param ref = {0};
-
- /* only send once per connect */
- spin_lock(&tcon->tc_lock);
- if (tcon->ses->ses_status != SES_GOOD ||
- (tcon->status != TID_NEW &&
- tcon->status != TID_NEED_TCON)) {
- spin_unlock(&tcon->tc_lock);
- return 0;
- }
- tcon->status = TID_IN_TCON;
- spin_unlock(&tcon->tc_lock);
-
- tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
- if (!tree) {
- rc = -ENOMEM;
- goto out;
- }
-
- if (tcon->ipc) {
- scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
- rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
- goto out;
- }
-
- sb = cifs_get_tcp_super(server);
- if (IS_ERR(sb)) {
- rc = PTR_ERR(sb);
- cifs_dbg(VFS, "%s: could not find superblock: %d\n", __func__, rc);
- goto out;
- }
-
- cifs_sb = CIFS_SB(sb);
-
- /* If it is not dfs or there was no cached dfs referral, then reconnect to same share */
- if (!server->current_fullpath ||
- dfs_cache_noreq_find(server->current_fullpath + 1, &ref, &tl)) {
- rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon, cifs_sb->local_nls);
- goto out;
- }
-
- rc = tree_connect_dfs_target(xid, tcon, cifs_sb, tree, ref.server_type == DFS_TYPE_LINK,
- &tl);
- free_dfs_info_param(&ref);
-
-out:
- kfree(tree);
- cifs_put_tcp_super(sb);
-
- if (rc) {
- spin_lock(&tcon->tc_lock);
- if (tcon->status == TID_IN_TCON)
- tcon->status = TID_NEED_TCON;
- spin_unlock(&tcon->tc_lock);
- } else {
- spin_lock(&tcon->tc_lock);
- if (tcon->status == TID_IN_TCON)
- tcon->status = TID_GOOD;
- spin_unlock(&tcon->tc_lock);
- tcon->need_reconnect = false;
- }
-
- return rc;
-}
-#else
-int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
-{
- int rc;
- const struct smb_version_operations *ops = tcon->ses->server->ops;
-
- /* only send once per connect */
- spin_lock(&tcon->tc_lock);
- if (tcon->ses->ses_status != SES_GOOD ||
- (tcon->status != TID_NEW &&
- tcon->status != TID_NEED_TCON)) {
- spin_unlock(&tcon->tc_lock);
- return 0;
- }
- tcon->status = TID_IN_TCON;
- spin_unlock(&tcon->tc_lock);
-
- rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon, nlsc);
- if (rc) {
- spin_lock(&tcon->tc_lock);
- if (tcon->status == TID_IN_TCON)
- tcon->status = TID_NEED_TCON;
- spin_unlock(&tcon->tc_lock);
- } else {
- spin_lock(&tcon->tc_lock);
- if (tcon->status == TID_IN_TCON)
- tcon->status = TID_GOOD;
- tcon->need_reconnect = false;
- spin_unlock(&tcon->tc_lock);
- }
-
- return rc;
-}
-#endif
diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c
deleted file mode 100644
index 3bc1d3494be3..000000000000
--- a/fs/cifs/dfs_cache.c
+++ /dev/null
@@ -1,1690 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * DFS referral cache routines
- *
- * Copyright (c) 2018-2019 Paulo Alcantara <palcantara@suse.de>
- */
-
-#include <linux/jhash.h>
-#include <linux/ktime.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/nls.h>
-#include <linux/workqueue.h>
-#include <linux/uuid.h>
-#include "cifsglob.h"
-#include "smb2pdu.h"
-#include "smb2proto.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifs_unicode.h"
-#include "smb2glob.h"
-#include "dns_resolve.h"
-
-#include "dfs_cache.h"
-
-#define CACHE_HTABLE_SIZE 32
-#define CACHE_MAX_ENTRIES 64
-#define CACHE_MIN_TTL 120 /* 2 minutes */
-
-#define IS_DFS_INTERLINK(v) (((v) & DFSREF_REFERRAL_SERVER) && !((v) & DFSREF_STORAGE_SERVER))
-
-struct cache_dfs_tgt {
- char *name;
- int path_consumed;
- struct list_head list;
-};
-
-struct cache_entry {
- struct hlist_node hlist;
- const char *path;
- int hdr_flags; /* RESP_GET_DFS_REFERRAL.ReferralHeaderFlags */
- int ttl; /* DFS_REREFERRAL_V3.TimeToLive */
- int srvtype; /* DFS_REREFERRAL_V3.ServerType */
- int ref_flags; /* DFS_REREFERRAL_V3.ReferralEntryFlags */
- struct timespec64 etime;
- int path_consumed; /* RESP_GET_DFS_REFERRAL.PathConsumed */
- int numtgts;
- struct list_head tlist;
- struct cache_dfs_tgt *tgthint;
-};
-
-/* List of referral server sessions per dfs mount */
-struct mount_group {
- struct list_head list;
- uuid_t id;
- struct cifs_ses *sessions[CACHE_MAX_ENTRIES];
- int num_sessions;
- spinlock_t lock;
- struct list_head refresh_list;
- struct kref refcount;
-};
-
-static struct kmem_cache *cache_slab __read_mostly;
-static struct workqueue_struct *dfscache_wq __read_mostly;
-
-static int cache_ttl;
-static DEFINE_SPINLOCK(cache_ttl_lock);
-
-static struct nls_table *cache_cp;
-
-/*
- * Number of entries in the cache
- */
-static atomic_t cache_count;
-
-static struct hlist_head cache_htable[CACHE_HTABLE_SIZE];
-static DECLARE_RWSEM(htable_rw_lock);
-
-static LIST_HEAD(mount_group_list);
-static DEFINE_MUTEX(mount_group_list_lock);
-
-static void refresh_cache_worker(struct work_struct *work);
-
-static DECLARE_DELAYED_WORK(refresh_task, refresh_cache_worker);
-
-static void get_ipc_unc(const char *ref_path, char *ipc, size_t ipclen)
-{
- const char *host;
- size_t len;
-
- extract_unc_hostname(ref_path, &host, &len);
- scnprintf(ipc, ipclen, "\\\\%.*s\\IPC$", (int)len, host);
-}
-
-static struct cifs_ses *find_ipc_from_server_path(struct cifs_ses **ses, const char *path)
-{
- char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
-
- get_ipc_unc(path, unc, sizeof(unc));
- for (; *ses; ses++) {
- if (!strcasecmp(unc, (*ses)->tcon_ipc->tree_name))
- return *ses;
- }
- return ERR_PTR(-ENOENT);
-}
-
-static void __mount_group_release(struct mount_group *mg)
-{
- int i;
-
- for (i = 0; i < mg->num_sessions; i++)
- cifs_put_smb_ses(mg->sessions[i]);
- kfree(mg);
-}
-
-static void mount_group_release(struct kref *kref)
-{
- struct mount_group *mg = container_of(kref, struct mount_group, refcount);
-
- mutex_lock(&mount_group_list_lock);
- list_del(&mg->list);
- mutex_unlock(&mount_group_list_lock);
- __mount_group_release(mg);
-}
-
-static struct mount_group *find_mount_group_locked(const uuid_t *id)
-{
- struct mount_group *mg;
-
- list_for_each_entry(mg, &mount_group_list, list) {
- if (uuid_equal(&mg->id, id))
- return mg;
- }
- return ERR_PTR(-ENOENT);
-}
-
-static struct mount_group *__get_mount_group_locked(const uuid_t *id)
-{
- struct mount_group *mg;
-
- mg = find_mount_group_locked(id);
- if (!IS_ERR(mg))
- return mg;
-
- mg = kmalloc(sizeof(*mg), GFP_KERNEL);
- if (!mg)
- return ERR_PTR(-ENOMEM);
- kref_init(&mg->refcount);
- uuid_copy(&mg->id, id);
- mg->num_sessions = 0;
- spin_lock_init(&mg->lock);
- list_add(&mg->list, &mount_group_list);
- return mg;
-}
-
-static struct mount_group *get_mount_group(const uuid_t *id)
-{
- struct mount_group *mg;
-
- mutex_lock(&mount_group_list_lock);
- mg = __get_mount_group_locked(id);
- if (!IS_ERR(mg))
- kref_get(&mg->refcount);
- mutex_unlock(&mount_group_list_lock);
-
- return mg;
-}
-
-static void free_mount_group_list(void)
-{
- struct mount_group *mg, *tmp_mg;
-
- list_for_each_entry_safe(mg, tmp_mg, &mount_group_list, list) {
- list_del_init(&mg->list);
- __mount_group_release(mg);
- }
-}
-
-/**
- * dfs_cache_canonical_path - get a canonical DFS path
- *
- * @path: DFS path
- * @cp: codepage
- * @remap: mapping type
- *
- * Return canonical path if success, otherwise error.
- */
-char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap)
-{
- char *tmp;
- int plen = 0;
- char *npath;
-
- if (!path || strlen(path) < 3 || (*path != '\\' && *path != '/'))
- return ERR_PTR(-EINVAL);
-
- if (unlikely(strcmp(cp->charset, cache_cp->charset))) {
- tmp = (char *)cifs_strndup_to_utf16(path, strlen(path), &plen, cp, remap);
- if (!tmp) {
- cifs_dbg(VFS, "%s: failed to convert path to utf16\n", __func__);
- return ERR_PTR(-EINVAL);
- }
-
- npath = cifs_strndup_from_utf16(tmp, plen, true, cache_cp);
- kfree(tmp);
-
- if (!npath) {
- cifs_dbg(VFS, "%s: failed to convert path from utf16\n", __func__);
- return ERR_PTR(-EINVAL);
- }
- } else {
- npath = kstrdup(path, GFP_KERNEL);
- if (!npath)
- return ERR_PTR(-ENOMEM);
- }
- convert_delimiter(npath, '\\');
- return npath;
-}
-
-static inline bool cache_entry_expired(const struct cache_entry *ce)
-{
- struct timespec64 ts;
-
- ktime_get_coarse_real_ts64(&ts);
- return timespec64_compare(&ts, &ce->etime) >= 0;
-}
-
-static inline void free_tgts(struct cache_entry *ce)
-{
- struct cache_dfs_tgt *t, *n;
-
- list_for_each_entry_safe(t, n, &ce->tlist, list) {
- list_del(&t->list);
- kfree(t->name);
- kfree(t);
- }
-}
-
-static inline void flush_cache_ent(struct cache_entry *ce)
-{
- hlist_del_init(&ce->hlist);
- kfree(ce->path);
- free_tgts(ce);
- atomic_dec(&cache_count);
- kmem_cache_free(cache_slab, ce);
-}
-
-static void flush_cache_ents(void)
-{
- int i;
-
- for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
- struct hlist_head *l = &cache_htable[i];
- struct hlist_node *n;
- struct cache_entry *ce;
-
- hlist_for_each_entry_safe(ce, n, l, hlist) {
- if (!hlist_unhashed(&ce->hlist))
- flush_cache_ent(ce);
- }
- }
-}
-
-/*
- * dfs cache /proc file
- */
-static int dfscache_proc_show(struct seq_file *m, void *v)
-{
- int i;
- struct cache_entry *ce;
- struct cache_dfs_tgt *t;
-
- seq_puts(m, "DFS cache\n---------\n");
-
- down_read(&htable_rw_lock);
- for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
- struct hlist_head *l = &cache_htable[i];
-
- hlist_for_each_entry(ce, l, hlist) {
- if (hlist_unhashed(&ce->hlist))
- continue;
-
- seq_printf(m,
- "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n",
- ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link",
- ce->ttl, ce->etime.tv_nsec, ce->hdr_flags, ce->ref_flags,
- IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no",
- ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no");
-
- list_for_each_entry(t, &ce->tlist, list) {
- seq_printf(m, " %s%s\n",
- t->name,
- ce->tgthint == t ? " (target hint)" : "");
- }
- }
- }
- up_read(&htable_rw_lock);
-
- return 0;
-}
-
-static ssize_t dfscache_proc_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *ppos)
-{
- char c;
- int rc;
-
- rc = get_user(c, buffer);
- if (rc)
- return rc;
-
- if (c != '0')
- return -EINVAL;
-
- cifs_dbg(FYI, "clearing dfs cache\n");
-
- down_write(&htable_rw_lock);
- flush_cache_ents();
- up_write(&htable_rw_lock);
-
- return count;
-}
-
-static int dfscache_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, dfscache_proc_show, NULL);
-}
-
-const struct proc_ops dfscache_proc_ops = {
- .proc_open = dfscache_proc_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = single_release,
- .proc_write = dfscache_proc_write,
-};
-
-#ifdef CONFIG_CIFS_DEBUG2
-static inline void dump_tgts(const struct cache_entry *ce)
-{
- struct cache_dfs_tgt *t;
-
- cifs_dbg(FYI, "target list:\n");
- list_for_each_entry(t, &ce->tlist, list) {
- cifs_dbg(FYI, " %s%s\n", t->name,
- ce->tgthint == t ? " (target hint)" : "");
- }
-}
-
-static inline void dump_ce(const struct cache_entry *ce)
-{
- cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n",
- ce->path,
- ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl,
- ce->etime.tv_nsec,
- ce->hdr_flags, ce->ref_flags,
- IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no",
- ce->path_consumed,
- cache_entry_expired(ce) ? "yes" : "no");
- dump_tgts(ce);
-}
-
-static inline void dump_refs(const struct dfs_info3_param *refs, int numrefs)
-{
- int i;
-
- cifs_dbg(FYI, "DFS referrals returned by the server:\n");
- for (i = 0; i < numrefs; i++) {
- const struct dfs_info3_param *ref = &refs[i];
-
- cifs_dbg(FYI,
- "\n"
- "flags: 0x%x\n"
- "path_consumed: %d\n"
- "server_type: 0x%x\n"
- "ref_flag: 0x%x\n"
- "path_name: %s\n"
- "node_name: %s\n"
- "ttl: %d (%dm)\n",
- ref->flags, ref->path_consumed, ref->server_type,
- ref->ref_flag, ref->path_name, ref->node_name,
- ref->ttl, ref->ttl / 60);
- }
-}
-#else
-#define dump_tgts(e)
-#define dump_ce(e)
-#define dump_refs(r, n)
-#endif
-
-/**
- * dfs_cache_init - Initialize DFS referral cache.
- *
- * Return zero if initialized successfully, otherwise non-zero.
- */
-int dfs_cache_init(void)
-{
- int rc;
- int i;
-
- dfscache_wq = alloc_workqueue("cifs-dfscache", WQ_FREEZABLE | WQ_UNBOUND, 1);
- if (!dfscache_wq)
- return -ENOMEM;
-
- cache_slab = kmem_cache_create("cifs_dfs_cache",
- sizeof(struct cache_entry), 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (!cache_slab) {
- rc = -ENOMEM;
- goto out_destroy_wq;
- }
-
- for (i = 0; i < CACHE_HTABLE_SIZE; i++)
- INIT_HLIST_HEAD(&cache_htable[i]);
-
- atomic_set(&cache_count, 0);
- cache_cp = load_nls("utf8");
- if (!cache_cp)
- cache_cp = load_nls_default();
-
- cifs_dbg(FYI, "%s: initialized DFS referral cache\n", __func__);
- return 0;
-
-out_destroy_wq:
- destroy_workqueue(dfscache_wq);
- return rc;
-}
-
-static int cache_entry_hash(const void *data, int size, unsigned int *hash)
-{
- int i, clen;
- const unsigned char *s = data;
- wchar_t c;
- unsigned int h = 0;
-
- for (i = 0; i < size; i += clen) {
- clen = cache_cp->char2uni(&s[i], size - i, &c);
- if (unlikely(clen < 0)) {
- cifs_dbg(VFS, "%s: can't convert char\n", __func__);
- return clen;
- }
- c = cifs_toupper(c);
- h = jhash(&c, sizeof(c), h);
- }
- *hash = h % CACHE_HTABLE_SIZE;
- return 0;
-}
-
-/* Return target hint of a DFS cache entry */
-static inline char *get_tgt_name(const struct cache_entry *ce)
-{
- struct cache_dfs_tgt *t = ce->tgthint;
-
- return t ? t->name : ERR_PTR(-ENOENT);
-}
-
-/* Return expire time out of a new entry's TTL */
-static inline struct timespec64 get_expire_time(int ttl)
-{
- struct timespec64 ts = {
- .tv_sec = ttl,
- .tv_nsec = 0,
- };
- struct timespec64 now;
-
- ktime_get_coarse_real_ts64(&now);
- return timespec64_add(now, ts);
-}
-
-/* Allocate a new DFS target */
-static struct cache_dfs_tgt *alloc_target(const char *name, int path_consumed)
-{
- struct cache_dfs_tgt *t;
-
- t = kmalloc(sizeof(*t), GFP_ATOMIC);
- if (!t)
- return ERR_PTR(-ENOMEM);
- t->name = kstrdup(name, GFP_ATOMIC);
- if (!t->name) {
- kfree(t);
- return ERR_PTR(-ENOMEM);
- }
- t->path_consumed = path_consumed;
- INIT_LIST_HEAD(&t->list);
- return t;
-}
-
-/*
- * Copy DFS referral information to a cache entry and conditionally update
- * target hint.
- */
-static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
- struct cache_entry *ce, const char *tgthint)
-{
- int i;
-
- ce->ttl = max_t(int, refs[0].ttl, CACHE_MIN_TTL);
- ce->etime = get_expire_time(ce->ttl);
- ce->srvtype = refs[0].server_type;
- ce->hdr_flags = refs[0].flags;
- ce->ref_flags = refs[0].ref_flag;
- ce->path_consumed = refs[0].path_consumed;
-
- for (i = 0; i < numrefs; i++) {
- struct cache_dfs_tgt *t;
-
- t = alloc_target(refs[i].node_name, refs[i].path_consumed);
- if (IS_ERR(t)) {
- free_tgts(ce);
- return PTR_ERR(t);
- }
- if (tgthint && !strcasecmp(t->name, tgthint)) {
- list_add(&t->list, &ce->tlist);
- tgthint = NULL;
- } else {
- list_add_tail(&t->list, &ce->tlist);
- }
- ce->numtgts++;
- }
-
- ce->tgthint = list_first_entry_or_null(&ce->tlist,
- struct cache_dfs_tgt, list);
-
- return 0;
-}
-
-/* Allocate a new cache entry */
-static struct cache_entry *alloc_cache_entry(struct dfs_info3_param *refs, int numrefs)
-{
- struct cache_entry *ce;
- int rc;
-
- ce = kmem_cache_zalloc(cache_slab, GFP_KERNEL);
- if (!ce)
- return ERR_PTR(-ENOMEM);
-
- ce->path = refs[0].path_name;
- refs[0].path_name = NULL;
-
- INIT_HLIST_NODE(&ce->hlist);
- INIT_LIST_HEAD(&ce->tlist);
-
- rc = copy_ref_data(refs, numrefs, ce, NULL);
- if (rc) {
- kfree(ce->path);
- kmem_cache_free(cache_slab, ce);
- ce = ERR_PTR(rc);
- }
- return ce;
-}
-
-static void remove_oldest_entry_locked(void)
-{
- int i;
- struct cache_entry *ce;
- struct cache_entry *to_del = NULL;
-
- WARN_ON(!rwsem_is_locked(&htable_rw_lock));
-
- for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
- struct hlist_head *l = &cache_htable[i];
-
- hlist_for_each_entry(ce, l, hlist) {
- if (hlist_unhashed(&ce->hlist))
- continue;
- if (!to_del || timespec64_compare(&ce->etime,
- &to_del->etime) < 0)
- to_del = ce;
- }
- }
-
- if (!to_del) {
- cifs_dbg(FYI, "%s: no entry to remove\n", __func__);
- return;
- }
-
- cifs_dbg(FYI, "%s: removing entry\n", __func__);
- dump_ce(to_del);
- flush_cache_ent(to_del);
-}
-
-/* Add a new DFS cache entry */
-static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
-{
- int rc;
- struct cache_entry *ce;
- unsigned int hash;
-
- WARN_ON(!rwsem_is_locked(&htable_rw_lock));
-
- if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES) {
- cifs_dbg(FYI, "%s: reached max cache size (%d)\n", __func__, CACHE_MAX_ENTRIES);
- remove_oldest_entry_locked();
- }
-
- rc = cache_entry_hash(refs[0].path_name, strlen(refs[0].path_name), &hash);
- if (rc)
- return rc;
-
- ce = alloc_cache_entry(refs, numrefs);
- if (IS_ERR(ce))
- return PTR_ERR(ce);
-
- spin_lock(&cache_ttl_lock);
- if (!cache_ttl) {
- cache_ttl = ce->ttl;
- queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ);
- } else {
- cache_ttl = min_t(int, cache_ttl, ce->ttl);
- mod_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ);
- }
- spin_unlock(&cache_ttl_lock);
-
- hlist_add_head(&ce->hlist, &cache_htable[hash]);
- dump_ce(ce);
-
- atomic_inc(&cache_count);
-
- return 0;
-}
-
-/* Check if two DFS paths are equal. @s1 and @s2 are expected to be in @cache_cp's charset */
-static bool dfs_path_equal(const char *s1, int len1, const char *s2, int len2)
-{
- int i, l1, l2;
- wchar_t c1, c2;
-
- if (len1 != len2)
- return false;
-
- for (i = 0; i < len1; i += l1) {
- l1 = cache_cp->char2uni(&s1[i], len1 - i, &c1);
- l2 = cache_cp->char2uni(&s2[i], len2 - i, &c2);
- if (unlikely(l1 < 0 && l2 < 0)) {
- if (s1[i] != s2[i])
- return false;
- l1 = 1;
- continue;
- }
- if (l1 != l2)
- return false;
- if (cifs_toupper(c1) != cifs_toupper(c2))
- return false;
- }
- return true;
-}
-
-static struct cache_entry *__lookup_cache_entry(const char *path, unsigned int hash, int len)
-{
- struct cache_entry *ce;
-
- hlist_for_each_entry(ce, &cache_htable[hash], hlist) {
- if (dfs_path_equal(ce->path, strlen(ce->path), path, len)) {
- dump_ce(ce);
- return ce;
- }
- }
- return ERR_PTR(-ENOENT);
-}
-
-/*
- * Find a DFS cache entry in hash table and optionally check prefix path against normalized @path.
- *
- * Use whole path components in the match. Must be called with htable_rw_lock held.
- *
- * Return ERR_PTR(-ENOENT) if the entry is not found.
- */
-static struct cache_entry *lookup_cache_entry(const char *path)
-{
- struct cache_entry *ce;
- int cnt = 0;
- const char *s = path, *e;
- char sep = *s;
- unsigned int hash;
- int rc;
-
- while ((s = strchr(s, sep)) && ++cnt < 3)
- s++;
-
- if (cnt < 3) {
- rc = cache_entry_hash(path, strlen(path), &hash);
- if (rc)
- return ERR_PTR(rc);
- return __lookup_cache_entry(path, hash, strlen(path));
- }
- /*
- * Handle paths that have more than two path components and are a complete prefix of the DFS
- * referral request path (@path).
- *
- * See MS-DFSC 3.2.5.5 "Receiving a Root Referral Request or Link Referral Request".
- */
- e = path + strlen(path) - 1;
- while (e > s) {
- int len;
-
- /* skip separators */
- while (e > s && *e == sep)
- e--;
- if (e == s)
- break;
-
- len = e + 1 - path;
- rc = cache_entry_hash(path, len, &hash);
- if (rc)
- return ERR_PTR(rc);
- ce = __lookup_cache_entry(path, hash, len);
- if (!IS_ERR(ce))
- return ce;
-
- /* backward until separator */
- while (e > s && *e != sep)
- e--;
- }
- return ERR_PTR(-ENOENT);
-}
-
-/**
- * dfs_cache_destroy - destroy DFS referral cache
- */
-void dfs_cache_destroy(void)
-{
- cancel_delayed_work_sync(&refresh_task);
- unload_nls(cache_cp);
- free_mount_group_list();
- flush_cache_ents();
- kmem_cache_destroy(cache_slab);
- destroy_workqueue(dfscache_wq);
-
- cifs_dbg(FYI, "%s: destroyed DFS referral cache\n", __func__);
-}
-
-/* Update a cache entry with the new referral in @refs */
-static int update_cache_entry_locked(struct cache_entry *ce, const struct dfs_info3_param *refs,
- int numrefs)
-{
- int rc;
- char *s, *th = NULL;
-
- WARN_ON(!rwsem_is_locked(&htable_rw_lock));
-
- if (ce->tgthint) {
- s = ce->tgthint->name;
- th = kstrdup(s, GFP_ATOMIC);
- if (!th)
- return -ENOMEM;
- }
-
- free_tgts(ce);
- ce->numtgts = 0;
-
- rc = copy_ref_data(refs, numrefs, ce, th);
-
- kfree(th);
-
- return rc;
-}
-
-static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, const char *path,
- struct dfs_info3_param **refs, int *numrefs)
-{
- int rc;
- int i;
-
- cifs_dbg(FYI, "%s: get an DFS referral for %s\n", __func__, path);
-
- *refs = NULL;
- *numrefs = 0;
-
- if (!ses || !ses->server || !ses->server->ops->get_dfs_refer)
- return -EOPNOTSUPP;
- if (unlikely(!cache_cp))
- return -EINVAL;
-
- rc = ses->server->ops->get_dfs_refer(xid, ses, path, refs, numrefs, cache_cp,
- NO_MAP_UNI_RSVD);
- if (!rc) {
- struct dfs_info3_param *ref = *refs;
-
- for (i = 0; i < *numrefs; i++)
- convert_delimiter(ref[i].path_name, '\\');
- }
- return rc;
-}
-
-/*
- * Find, create or update a DFS cache entry.
- *
- * If the entry wasn't found, it will create a new one. Or if it was found but
- * expired, then it will update the entry accordingly.
- *
- * For interlinks, cifs_mount() and expand_dfs_referral() are supposed to
- * handle them properly.
- */
-static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses, const char *path)
-{
- struct dfs_info3_param *refs = NULL;
- struct cache_entry *ce;
- int numrefs = 0;
- int rc;
-
- cifs_dbg(FYI, "%s: search path: %s\n", __func__, path);
-
- down_read(&htable_rw_lock);
-
- ce = lookup_cache_entry(path);
- if (!IS_ERR(ce) && !cache_entry_expired(ce)) {
- up_read(&htable_rw_lock);
- return 0;
- }
- /*
- * Unlock shared access as we don't want to hold any locks while getting
- * a new referral. The @ses used for performing the I/O could be
- * reconnecting and it acquires @htable_rw_lock to look up the dfs cache
- * in order to failover -- if necessary.
- */
- up_read(&htable_rw_lock);
-
- /*
- * Either the entry was not found, or it is expired.
- * Request a new DFS referral in order to create or update a cache entry.
- */
- rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
- if (rc)
- goto out;
-
- dump_refs(refs, numrefs);
-
- down_write(&htable_rw_lock);
- /* Re-check as another task might have it added or refreshed already */
- ce = lookup_cache_entry(path);
- if (!IS_ERR(ce)) {
- if (cache_entry_expired(ce))
- rc = update_cache_entry_locked(ce, refs, numrefs);
- } else {
- rc = add_cache_entry_locked(refs, numrefs);
- }
-
- up_write(&htable_rw_lock);
-out:
- free_dfs_info_array(refs, numrefs);
- return rc;
-}
-
-/*
- * Set up a DFS referral from a given cache entry.
- *
- * Must be called with htable_rw_lock held.
- */
-static int setup_referral(const char *path, struct cache_entry *ce,
- struct dfs_info3_param *ref, const char *target)
-{
- int rc;
-
- cifs_dbg(FYI, "%s: set up new ref\n", __func__);
-
- memset(ref, 0, sizeof(*ref));
-
- ref->path_name = kstrdup(path, GFP_ATOMIC);
- if (!ref->path_name)
- return -ENOMEM;
-
- ref->node_name = kstrdup(target, GFP_ATOMIC);
- if (!ref->node_name) {
- rc = -ENOMEM;
- goto err_free_path;
- }
-
- ref->path_consumed = ce->path_consumed;
- ref->ttl = ce->ttl;
- ref->server_type = ce->srvtype;
- ref->ref_flag = ce->ref_flags;
- ref->flags = ce->hdr_flags;
-
- return 0;
-
-err_free_path:
- kfree(ref->path_name);
- ref->path_name = NULL;
- return rc;
-}
-
-/* Return target list of a DFS cache entry */
-static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
-{
- int rc;
- struct list_head *head = &tl->tl_list;
- struct cache_dfs_tgt *t;
- struct dfs_cache_tgt_iterator *it, *nit;
-
- memset(tl, 0, sizeof(*tl));
- INIT_LIST_HEAD(head);
-
- list_for_each_entry(t, &ce->tlist, list) {
- it = kzalloc(sizeof(*it), GFP_ATOMIC);
- if (!it) {
- rc = -ENOMEM;
- goto err_free_it;
- }
-
- it->it_name = kstrdup(t->name, GFP_ATOMIC);
- if (!it->it_name) {
- kfree(it);
- rc = -ENOMEM;
- goto err_free_it;
- }
- it->it_path_consumed = t->path_consumed;
-
- if (ce->tgthint == t)
- list_add(&it->it_list, head);
- else
- list_add_tail(&it->it_list, head);
- }
-
- tl->tl_numtgts = ce->numtgts;
-
- return 0;
-
-err_free_it:
- list_for_each_entry_safe(it, nit, head, it_list) {
- list_del(&it->it_list);
- kfree(it->it_name);
- kfree(it);
- }
- return rc;
-}
-
-/**
- * dfs_cache_find - find a DFS cache entry
- *
- * If it doesn't find the cache entry, then it will get a DFS referral
- * for @path and create a new entry.
- *
- * In case the cache entry exists but expired, it will get a DFS referral
- * for @path and then update the respective cache entry.
- *
- * These parameters are passed down to the get_dfs_refer() call if it
- * needs to be issued:
- * @xid: syscall xid
- * @ses: smb session to issue the request on
- * @cp: codepage
- * @remap: path character remapping type
- * @path: path to lookup in DFS referral cache.
- *
- * @ref: when non-NULL, store single DFS referral result in it.
- * @tgt_list: when non-NULL, store complete DFS target list in it.
- *
- * Return zero if the target was found, otherwise non-zero.
- */
-int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *cp,
- int remap, const char *path, struct dfs_info3_param *ref,
- struct dfs_cache_tgt_list *tgt_list)
-{
- int rc;
- const char *npath;
- struct cache_entry *ce;
-
- npath = dfs_cache_canonical_path(path, cp, remap);
- if (IS_ERR(npath))
- return PTR_ERR(npath);
-
- rc = cache_refresh_path(xid, ses, npath);
- if (rc)
- goto out_free_path;
-
- down_read(&htable_rw_lock);
-
- ce = lookup_cache_entry(npath);
- if (IS_ERR(ce)) {
- up_read(&htable_rw_lock);
- rc = PTR_ERR(ce);
- goto out_free_path;
- }
-
- if (ref)
- rc = setup_referral(path, ce, ref, get_tgt_name(ce));
- else
- rc = 0;
- if (!rc && tgt_list)
- rc = get_targets(ce, tgt_list);
-
- up_read(&htable_rw_lock);
-
-out_free_path:
- kfree(npath);
- return rc;
-}
-
-/**
- * dfs_cache_noreq_find - find a DFS cache entry without sending any requests to
- * the currently connected server.
- *
- * NOTE: This function will neither update a cache entry in case it was
- * expired, nor create a new cache entry if @path hasn't been found. It heavily
- * relies on an existing cache entry.
- *
- * @path: canonical DFS path to lookup in the DFS referral cache.
- * @ref: when non-NULL, store single DFS referral result in it.
- * @tgt_list: when non-NULL, store complete DFS target list in it.
- *
- * Return 0 if successful.
- * Return -ENOENT if the entry was not found.
- * Return non-zero for other errors.
- */
-int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
- struct dfs_cache_tgt_list *tgt_list)
-{
- int rc;
- struct cache_entry *ce;
-
- cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
-
- down_read(&htable_rw_lock);
-
- ce = lookup_cache_entry(path);
- if (IS_ERR(ce)) {
- rc = PTR_ERR(ce);
- goto out_unlock;
- }
-
- if (ref)
- rc = setup_referral(path, ce, ref, get_tgt_name(ce));
- else
- rc = 0;
- if (!rc && tgt_list)
- rc = get_targets(ce, tgt_list);
-
-out_unlock:
- up_read(&htable_rw_lock);
- return rc;
-}
-
-/**
- * dfs_cache_update_tgthint - update target hint of a DFS cache entry
- *
- * If it doesn't find the cache entry, then it will get a DFS referral for @path
- * and create a new entry.
- *
- * In case the cache entry exists but expired, it will get a DFS referral
- * for @path and then update the respective cache entry.
- *
- * @xid: syscall id
- * @ses: smb session
- * @cp: codepage
- * @remap: type of character remapping for paths
- * @path: path to lookup in DFS referral cache
- * @it: DFS target iterator
- *
- * Return zero if the target hint was updated successfully, otherwise non-zero.
- */
-int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
- const struct nls_table *cp, int remap, const char *path,
- const struct dfs_cache_tgt_iterator *it)
-{
- struct cache_dfs_tgt *t;
- struct cache_entry *ce;
- const char *npath;
- int rc = 0;
-
- npath = dfs_cache_canonical_path(path, cp, remap);
- if (IS_ERR(npath))
- return PTR_ERR(npath);
-
- cifs_dbg(FYI, "%s: update target hint - path: %s\n", __func__, npath);
-
- rc = cache_refresh_path(xid, ses, npath);
- if (rc)
- goto out_free_path;
-
- down_write(&htable_rw_lock);
-
- ce = lookup_cache_entry(npath);
- if (IS_ERR(ce)) {
- rc = PTR_ERR(ce);
- goto out_unlock;
- }
-
- t = ce->tgthint;
-
- if (likely(!strcasecmp(it->it_name, t->name)))
- goto out_unlock;
-
- list_for_each_entry(t, &ce->tlist, list) {
- if (!strcasecmp(t->name, it->it_name)) {
- ce->tgthint = t;
- cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
- it->it_name);
- break;
- }
- }
-
-out_unlock:
- up_write(&htable_rw_lock);
-out_free_path:
- kfree(npath);
- return rc;
-}
-
-/**
- * dfs_cache_noreq_update_tgthint - update target hint of a DFS cache entry
- * without sending any requests to the currently connected server.
- *
- * NOTE: This function will neither update a cache entry in case it was
- * expired, nor create a new cache entry if @path hasn't been found. It heavily
- * relies on an existing cache entry.
- *
- * @path: canonical DFS path to lookup in DFS referral cache.
- * @it: target iterator which contains the target hint to update the cache
- * entry with.
- *
- * Return zero if the target hint was updated successfully, otherwise non-zero.
- */
-int dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt_iterator *it)
-{
- int rc;
- struct cache_entry *ce;
- struct cache_dfs_tgt *t;
-
- if (!it)
- return -EINVAL;
-
- cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
-
- down_write(&htable_rw_lock);
-
- ce = lookup_cache_entry(path);
- if (IS_ERR(ce)) {
- rc = PTR_ERR(ce);
- goto out_unlock;
- }
-
- rc = 0;
- t = ce->tgthint;
-
- if (unlikely(!strcasecmp(it->it_name, t->name)))
- goto out_unlock;
-
- list_for_each_entry(t, &ce->tlist, list) {
- if (!strcasecmp(t->name, it->it_name)) {
- ce->tgthint = t;
- cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
- it->it_name);
- break;
- }
- }
-
-out_unlock:
- up_write(&htable_rw_lock);
- return rc;
-}
-
-/**
- * dfs_cache_get_tgt_referral - returns a DFS referral (@ref) from a given
- * target iterator (@it).
- *
- * @path: canonical DFS path to lookup in DFS referral cache.
- * @it: DFS target iterator.
- * @ref: DFS referral pointer to set up the gathered information.
- *
- * Return zero if the DFS referral was set up correctly, otherwise non-zero.
- */
-int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iterator *it,
- struct dfs_info3_param *ref)
-{
- int rc;
- struct cache_entry *ce;
-
- if (!it || !ref)
- return -EINVAL;
-
- cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
-
- down_read(&htable_rw_lock);
-
- ce = lookup_cache_entry(path);
- if (IS_ERR(ce)) {
- rc = PTR_ERR(ce);
- goto out_unlock;
- }
-
- cifs_dbg(FYI, "%s: target name: %s\n", __func__, it->it_name);
-
- rc = setup_referral(path, ce, ref, it->it_name);
-
-out_unlock:
- up_read(&htable_rw_lock);
- return rc;
-}
-
-/**
- * dfs_cache_add_refsrv_session - add SMB session of referral server
- *
- * @mount_id: mount group uuid to lookup.
- * @ses: reference counted SMB session of referral server.
- */
-void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses)
-{
- struct mount_group *mg;
-
- if (WARN_ON_ONCE(!mount_id || uuid_is_null(mount_id) || !ses))
- return;
-
- mg = get_mount_group(mount_id);
- if (WARN_ON_ONCE(IS_ERR(mg)))
- return;
-
- spin_lock(&mg->lock);
- if (mg->num_sessions < ARRAY_SIZE(mg->sessions))
- mg->sessions[mg->num_sessions++] = ses;
- spin_unlock(&mg->lock);
- kref_put(&mg->refcount, mount_group_release);
-}
-
-/**
- * dfs_cache_put_refsrv_sessions - put all referral server sessions
- *
- * Put all SMB sessions from the given mount group id.
- *
- * @mount_id: mount group uuid to lookup.
- */
-void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id)
-{
- struct mount_group *mg;
-
- if (!mount_id || uuid_is_null(mount_id))
- return;
-
- mutex_lock(&mount_group_list_lock);
- mg = find_mount_group_locked(mount_id);
- if (IS_ERR(mg)) {
- mutex_unlock(&mount_group_list_lock);
- return;
- }
- mutex_unlock(&mount_group_list_lock);
- kref_put(&mg->refcount, mount_group_release);
-}
-
-/* Extract share from DFS target and return a pointer to prefix path or NULL */
-static const char *parse_target_share(const char *target, char **share)
-{
- const char *s, *seps = "/\\";
- size_t len;
-
- s = strpbrk(target + 1, seps);
- if (!s)
- return ERR_PTR(-EINVAL);
-
- len = strcspn(s + 1, seps);
- if (!len)
- return ERR_PTR(-EINVAL);
- s += len;
-
- len = s - target + 1;
- *share = kstrndup(target, len, GFP_KERNEL);
- if (!*share)
- return ERR_PTR(-ENOMEM);
-
- s = target + len;
- return s + strspn(s, seps);
-}
-
-/**
- * dfs_cache_get_tgt_share - parse a DFS target
- *
- * @path: DFS full path
- * @it: DFS target iterator.
- * @share: tree name.
- * @prefix: prefix path.
- *
- * Return zero if target was parsed correctly, otherwise non-zero.
- */
-int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, char **share,
- char **prefix)
-{
- char sep;
- char *target_share;
- char *ppath = NULL;
- const char *target_ppath, *dfsref_ppath;
- size_t target_pplen, dfsref_pplen;
- size_t len, c;
-
- if (!it || !path || !share || !prefix || strlen(path) < it->it_path_consumed)
- return -EINVAL;
-
- sep = it->it_name[0];
- if (sep != '\\' && sep != '/')
- return -EINVAL;
-
- target_ppath = parse_target_share(it->it_name, &target_share);
- if (IS_ERR(target_ppath))
- return PTR_ERR(target_ppath);
-
- /* point to prefix in DFS referral path */
- dfsref_ppath = path + it->it_path_consumed;
- dfsref_ppath += strspn(dfsref_ppath, "/\\");
-
- target_pplen = strlen(target_ppath);
- dfsref_pplen = strlen(dfsref_ppath);
-
- /* merge prefix paths from DFS referral path and target node */
- if (target_pplen || dfsref_pplen) {
- len = target_pplen + dfsref_pplen + 2;
- ppath = kzalloc(len, GFP_KERNEL);
- if (!ppath) {
- kfree(target_share);
- return -ENOMEM;
- }
- c = strscpy(ppath, target_ppath, len);
- if (c && dfsref_pplen)
- ppath[c] = sep;
- strlcat(ppath, dfsref_ppath, len);
- }
- *share = target_share;
- *prefix = ppath;
- return 0;
-}
-
-static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, const char *s2)
-{
- char unc[sizeof("\\\\") + SERVER_NAME_LENGTH] = {0};
- const char *host;
- size_t hostlen;
- char *ip = NULL;
- struct sockaddr sa;
- bool match;
- int rc;
-
- if (strcasecmp(s1, s2))
- return false;
-
- /*
- * Resolve share's hostname and check if server address matches. Otherwise just ignore it
- * as we could not have upcall to resolve hostname or failed to convert ip address.
- */
- match = true;
- extract_unc_hostname(s1, &host, &hostlen);
- scnprintf(unc, sizeof(unc), "\\\\%.*s", (int)hostlen, host);
-
- rc = dns_resolve_server_name_to_ip(unc, &ip, NULL);
- if (rc < 0) {
- cifs_dbg(FYI, "%s: could not resolve %.*s. assuming server address matches.\n",
- __func__, (int)hostlen, host);
- return true;
- }
-
- if (!cifs_convert_address(&sa, ip, strlen(ip))) {
- cifs_dbg(VFS, "%s: failed to convert address \'%s\'. skip address matching.\n",
- __func__, ip);
- } else {
- cifs_server_lock(server);
- match = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, &sa);
- cifs_server_unlock(server);
- }
-
- kfree(ip);
- return match;
-}
-
-/*
- * Mark dfs tcon for reconnecting when the currently connected tcon does not match any of the new
- * target shares in @refs.
- */
-static void mark_for_reconnect_if_needed(struct cifs_tcon *tcon, struct dfs_cache_tgt_list *tl,
- const struct dfs_info3_param *refs, int numrefs)
-{
- struct dfs_cache_tgt_iterator *it;
- int i;
-
- for (it = dfs_cache_get_tgt_iterator(tl); it; it = dfs_cache_get_next_tgt(tl, it)) {
- for (i = 0; i < numrefs; i++) {
- if (target_share_equal(tcon->ses->server, dfs_cache_get_tgt_name(it),
- refs[i].node_name))
- return;
- }
- }
-
- cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__);
- cifs_signal_cifsd_for_reconnect(tcon->ses->server, true);
-}
-
-/* Refresh dfs referral of tcon and mark it for reconnect if needed */
-static int __refresh_tcon(const char *path, struct cifs_ses **sessions, struct cifs_tcon *tcon,
- bool force_refresh)
-{
- struct cifs_ses *ses;
- struct cache_entry *ce;
- struct dfs_info3_param *refs = NULL;
- int numrefs = 0;
- bool needs_refresh = false;
- struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
- int rc = 0;
- unsigned int xid;
-
- ses = find_ipc_from_server_path(sessions, path);
- if (IS_ERR(ses)) {
- cifs_dbg(FYI, "%s: could not find ipc session\n", __func__);
- return PTR_ERR(ses);
- }
-
- down_read(&htable_rw_lock);
- ce = lookup_cache_entry(path);
- needs_refresh = force_refresh || IS_ERR(ce) || cache_entry_expired(ce);
- if (!IS_ERR(ce)) {
- rc = get_targets(ce, &tl);
- if (rc)
- cifs_dbg(FYI, "%s: could not get dfs targets: %d\n", __func__, rc);
- }
- up_read(&htable_rw_lock);
-
- if (!needs_refresh) {
- rc = 0;
- goto out;
- }
-
- xid = get_xid();
- rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
- free_xid(xid);
-
- /* Create or update a cache entry with the new referral */
- if (!rc) {
- dump_refs(refs, numrefs);
-
- down_write(&htable_rw_lock);
- ce = lookup_cache_entry(path);
- if (IS_ERR(ce))
- add_cache_entry_locked(refs, numrefs);
- else if (force_refresh || cache_entry_expired(ce))
- update_cache_entry_locked(ce, refs, numrefs);
- up_write(&htable_rw_lock);
-
- mark_for_reconnect_if_needed(tcon, &tl, refs, numrefs);
- }
-
-out:
- dfs_cache_free_tgts(&tl);
- free_dfs_info_array(refs, numrefs);
- return rc;
-}
-
-static int refresh_tcon(struct cifs_ses **sessions, struct cifs_tcon *tcon, bool force_refresh)
-{
- struct TCP_Server_Info *server = tcon->ses->server;
-
- mutex_lock(&server->refpath_lock);
- if (server->origin_fullpath) {
- if (server->leaf_fullpath && strcasecmp(server->leaf_fullpath,
- server->origin_fullpath))
- __refresh_tcon(server->leaf_fullpath + 1, sessions, tcon, force_refresh);
- __refresh_tcon(server->origin_fullpath + 1, sessions, tcon, force_refresh);
- }
- mutex_unlock(&server->refpath_lock);
-
- return 0;
-}
-
-/**
- * dfs_cache_remount_fs - remount a DFS share
- *
- * Reconfigure dfs mount by forcing a new DFS referral and if the currently cached targets do not
- * match any of the new targets, mark it for reconnect.
- *
- * @cifs_sb: cifs superblock.
- *
- * Return zero if remounted, otherwise non-zero.
- */
-int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb)
-{
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct mount_group *mg;
- struct cifs_ses *sessions[CACHE_MAX_ENTRIES + 1] = {NULL};
- int rc;
-
- if (!cifs_sb || !cifs_sb->master_tlink)
- return -EINVAL;
-
- tcon = cifs_sb_master_tcon(cifs_sb);
- server = tcon->ses->server;
-
- if (!server->origin_fullpath) {
- cifs_dbg(FYI, "%s: not a dfs mount\n", __func__);
- return 0;
- }
-
- if (uuid_is_null(&cifs_sb->dfs_mount_id)) {
- cifs_dbg(FYI, "%s: no dfs mount group id\n", __func__);
- return -EINVAL;
- }
-
- mutex_lock(&mount_group_list_lock);
- mg = find_mount_group_locked(&cifs_sb->dfs_mount_id);
- if (IS_ERR(mg)) {
- mutex_unlock(&mount_group_list_lock);
- cifs_dbg(FYI, "%s: no ipc session for refreshing referral\n", __func__);
- return PTR_ERR(mg);
- }
- kref_get(&mg->refcount);
- mutex_unlock(&mount_group_list_lock);
-
- spin_lock(&mg->lock);
- memcpy(&sessions, mg->sessions, mg->num_sessions * sizeof(mg->sessions[0]));
- spin_unlock(&mg->lock);
-
- /*
- * After reconnecting to a different server, unique ids won't match anymore, so we disable
- * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE).
- */
- cifs_autodisable_serverino(cifs_sb);
- /*
- * Force the use of prefix path to support failover on DFS paths that resolve to targets
- * that have different prefix paths.
- */
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
- rc = refresh_tcon(sessions, tcon, true);
-
- kref_put(&mg->refcount, mount_group_release);
- return rc;
-}
-
-/*
- * Refresh all active dfs mounts regardless of whether they are in cache or not.
- * (cache can be cleared)
- */
-static void refresh_mounts(struct cifs_ses **sessions)
-{
- struct TCP_Server_Info *server;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon, *ntcon;
- struct list_head tcons;
-
- INIT_LIST_HEAD(&tcons);
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
- spin_lock(&server->srv_lock);
- if (!server->is_dfs_conn) {
- spin_unlock(&server->srv_lock);
- continue;
- }
- spin_unlock(&server->srv_lock);
-
- list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- spin_lock(&tcon->tc_lock);
- if (!tcon->ipc && !tcon->need_reconnect) {
- tcon->tc_count++;
- list_add_tail(&tcon->ulist, &tcons);
- }
- spin_unlock(&tcon->tc_lock);
- }
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
-
- list_for_each_entry_safe(tcon, ntcon, &tcons, ulist) {
- struct TCP_Server_Info *server = tcon->ses->server;
-
- list_del_init(&tcon->ulist);
-
- mutex_lock(&server->refpath_lock);
- if (server->origin_fullpath) {
- if (server->leaf_fullpath && strcasecmp(server->leaf_fullpath,
- server->origin_fullpath))
- __refresh_tcon(server->leaf_fullpath + 1, sessions, tcon, false);
- __refresh_tcon(server->origin_fullpath + 1, sessions, tcon, false);
- }
- mutex_unlock(&server->refpath_lock);
-
- cifs_put_tcon(tcon);
- }
-}
-
-static void refresh_cache(struct cifs_ses **sessions)
-{
- int i;
- struct cifs_ses *ses;
- unsigned int xid;
- char *ref_paths[CACHE_MAX_ENTRIES];
- int count = 0;
- struct cache_entry *ce;
-
- /*
- * Refresh all cached entries. Get all new referrals outside critical section to avoid
- * starvation while performing SMB2 IOCTL on broken or slow connections.
-
- * The cache entries may cover more paths than the active mounts
- * (e.g. domain-based DFS referrals or multi tier DFS setups).
- */
- down_read(&htable_rw_lock);
- for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
- struct hlist_head *l = &cache_htable[i];
-
- hlist_for_each_entry(ce, l, hlist) {
- if (count == ARRAY_SIZE(ref_paths))
- goto out_unlock;
- if (hlist_unhashed(&ce->hlist) || !cache_entry_expired(ce) ||
- IS_ERR(find_ipc_from_server_path(sessions, ce->path)))
- continue;
- ref_paths[count++] = kstrdup(ce->path, GFP_ATOMIC);
- }
- }
-
-out_unlock:
- up_read(&htable_rw_lock);
-
- for (i = 0; i < count; i++) {
- char *path = ref_paths[i];
- struct dfs_info3_param *refs = NULL;
- int numrefs = 0;
- int rc = 0;
-
- if (!path)
- continue;
-
- ses = find_ipc_from_server_path(sessions, path);
- if (IS_ERR(ses))
- goto next_referral;
-
- xid = get_xid();
- rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
- free_xid(xid);
-
- if (!rc) {
- down_write(&htable_rw_lock);
- ce = lookup_cache_entry(path);
- /*
- * We need to re-check it because other tasks might have it deleted or
- * updated.
- */
- if (!IS_ERR(ce) && cache_entry_expired(ce))
- update_cache_entry_locked(ce, refs, numrefs);
- up_write(&htable_rw_lock);
- }
-
-next_referral:
- kfree(path);
- free_dfs_info_array(refs, numrefs);
- }
-}
-
-/*
- * Worker that will refresh DFS cache and active mounts based on lowest TTL value from a DFS
- * referral.
- */
-static void refresh_cache_worker(struct work_struct *work)
-{
- struct list_head mglist;
- struct mount_group *mg, *tmp_mg;
- struct cifs_ses *sessions[CACHE_MAX_ENTRIES + 1] = {NULL};
- int max_sessions = ARRAY_SIZE(sessions) - 1;
- int i = 0, count;
-
- INIT_LIST_HEAD(&mglist);
-
- /* Get refereces of mount groups */
- mutex_lock(&mount_group_list_lock);
- list_for_each_entry(mg, &mount_group_list, list) {
- kref_get(&mg->refcount);
- list_add(&mg->refresh_list, &mglist);
- }
- mutex_unlock(&mount_group_list_lock);
-
- /* Fill in local array with an NULL-terminated list of all referral server sessions */
- list_for_each_entry(mg, &mglist, refresh_list) {
- if (i >= max_sessions)
- break;
-
- spin_lock(&mg->lock);
- if (i + mg->num_sessions > max_sessions)
- count = max_sessions - i;
- else
- count = mg->num_sessions;
- memcpy(&sessions[i], mg->sessions, count * sizeof(mg->sessions[0]));
- spin_unlock(&mg->lock);
- i += count;
- }
-
- if (sessions[0]) {
- /* Refresh all active mounts and cached entries */
- refresh_mounts(sessions);
- refresh_cache(sessions);
- }
-
- list_for_each_entry_safe(mg, tmp_mg, &mglist, refresh_list) {
- list_del_init(&mg->refresh_list);
- kref_put(&mg->refcount, mount_group_release);
- }
-
- spin_lock(&cache_ttl_lock);
- queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ);
- spin_unlock(&cache_ttl_lock);
-}
diff --git a/fs/cifs/dfs_cache.h b/fs/cifs/dfs_cache.h
deleted file mode 100644
index 52070d1df189..000000000000
--- a/fs/cifs/dfs_cache.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * DFS referral cache routines
- *
- * Copyright (c) 2018-2019 Paulo Alcantara <palcantara@suse.de>
- */
-
-#ifndef _CIFS_DFS_CACHE_H
-#define _CIFS_DFS_CACHE_H
-
-#include <linux/nls.h>
-#include <linux/list.h>
-#include <linux/uuid.h>
-#include "cifsglob.h"
-
-#define DFS_CACHE_TGT_LIST_INIT(var) { .tl_numtgts = 0, .tl_list = LIST_HEAD_INIT((var).tl_list), }
-
-struct dfs_cache_tgt_list {
- int tl_numtgts;
- struct list_head tl_list;
-};
-
-struct dfs_cache_tgt_iterator {
- char *it_name;
- int it_path_consumed;
- struct list_head it_list;
-};
-
-int dfs_cache_init(void);
-void dfs_cache_destroy(void);
-extern const struct proc_ops dfscache_proc_ops;
-
-int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *cp,
- int remap, const char *path, struct dfs_info3_param *ref,
- struct dfs_cache_tgt_list *tgt_list);
-int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
- struct dfs_cache_tgt_list *tgt_list);
-int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
- const struct nls_table *cp, int remap, const char *path,
- const struct dfs_cache_tgt_iterator *it);
-int dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt_iterator *it);
-int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iterator *it,
- struct dfs_info3_param *ref);
-int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, char **share,
- char **prefix);
-void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id);
-void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses);
-char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap);
-int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb);
-
-static inline struct dfs_cache_tgt_iterator *
-dfs_cache_get_next_tgt(struct dfs_cache_tgt_list *tl,
- struct dfs_cache_tgt_iterator *it)
-{
- if (!tl || list_empty(&tl->tl_list) || !it ||
- list_is_last(&it->it_list, &tl->tl_list))
- return NULL;
- return list_next_entry(it, it_list);
-}
-
-static inline struct dfs_cache_tgt_iterator *
-dfs_cache_get_tgt_iterator(struct dfs_cache_tgt_list *tl)
-{
- if (!tl)
- return NULL;
- return list_first_entry_or_null(&tl->tl_list,
- struct dfs_cache_tgt_iterator,
- it_list);
-}
-
-static inline void dfs_cache_free_tgts(struct dfs_cache_tgt_list *tl)
-{
- struct dfs_cache_tgt_iterator *it, *nit;
-
- if (!tl || list_empty(&tl->tl_list))
- return;
- list_for_each_entry_safe(it, nit, &tl->tl_list, it_list) {
- list_del(&it->it_list);
- kfree(it->it_name);
- kfree(it);
- }
- tl->tl_numtgts = 0;
-}
-
-static inline const char *
-dfs_cache_get_tgt_name(const struct dfs_cache_tgt_iterator *it)
-{
- return it ? it->it_name : NULL;
-}
-
-static inline int
-dfs_cache_get_nr_tgts(const struct dfs_cache_tgt_list *tl)
-{
- return tl ? tl->tl_numtgts : 0;
-}
-
-#endif /* _CIFS_DFS_CACHE_H */
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
deleted file mode 100644
index e382b794acbe..000000000000
--- a/fs/cifs/dir.c
+++ /dev/null
@@ -1,867 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * vfs operations that deal with dentries
- *
- * Copyright (C) International Business Machines Corp., 2002,2009
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/slab.h>
-#include <linux/namei.h>
-#include <linux/mount.h>
-#include <linux/file.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "cifs_unicode.h"
-#include "fs_context.h"
-#include "cifs_ioctl.h"
-#include "fscache.h"
-
-static void
-renew_parental_timestamps(struct dentry *direntry)
-{
- /* BB check if there is a way to get the kernel to do this or if we
- really need this */
- do {
- cifs_set_time(direntry, jiffies);
- direntry = direntry->d_parent;
- } while (!IS_ROOT(direntry));
-}
-
-char *
-cifs_build_path_to_root(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb,
- struct cifs_tcon *tcon, int add_treename)
-{
- int pplen = ctx->prepath ? strlen(ctx->prepath) + 1 : 0;
- int dfsplen;
- char *full_path = NULL;
-
- /* if no prefix path, simply set path to the root of share to "" */
- if (pplen == 0) {
- full_path = kzalloc(1, GFP_KERNEL);
- return full_path;
- }
-
- if (add_treename)
- dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
- else
- dfsplen = 0;
-
- full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
- if (full_path == NULL)
- return full_path;
-
- if (dfsplen)
- memcpy(full_path, tcon->tree_name, dfsplen);
- full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb);
- memcpy(full_path + dfsplen + 1, ctx->prepath, pplen);
- convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
- return full_path;
-}
-
-/* Note: caller must free return buffer */
-const char *
-build_path_from_dentry(struct dentry *direntry, void *page)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- bool prefix = tcon->Flags & SMB_SHARE_IS_IN_DFS;
-
- return build_path_from_dentry_optional_prefix(direntry, page,
- prefix);
-}
-
-char *
-build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
- bool prefix)
-{
- int dfsplen;
- int pplen = 0;
- struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- char dirsep = CIFS_DIR_SEP(cifs_sb);
- char *s;
-
- if (unlikely(!page))
- return ERR_PTR(-ENOMEM);
-
- if (prefix)
- dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
- else
- dfsplen = 0;
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
- pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
-
- s = dentry_path_raw(direntry, page, PATH_MAX);
- if (IS_ERR(s))
- return s;
- if (!s[1]) // for root we want "", not "/"
- s++;
- if (s < (char *)page + pplen + dfsplen)
- return ERR_PTR(-ENAMETOOLONG);
- if (pplen) {
- cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath);
- s -= pplen;
- memcpy(s + 1, cifs_sb->prepath, pplen - 1);
- *s = '/';
- }
- if (dirsep != '/') {
- /* BB test paths to Windows with '/' in the midst of prepath */
- char *p;
-
- for (p = s; *p; p++)
- if (*p == '/')
- *p = dirsep;
- }
- if (dfsplen) {
- s -= dfsplen;
- memcpy(s, tcon->tree_name, dfsplen);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
- int i;
- for (i = 0; i < dfsplen; i++) {
- if (s[i] == '\\')
- s[i] = '/';
- }
- }
- }
- return s;
-}
-
-/*
- * Don't allow path components longer than the server max.
- * Don't allow the separator character in a path component.
- * The VFS will not allow "/", but "\" is allowed by posix.
- */
-static int
-check_name(struct dentry *direntry, struct cifs_tcon *tcon)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
- int i;
-
- if (unlikely(tcon->fsAttrInfo.MaxPathNameComponentLength &&
- direntry->d_name.len >
- le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength)))
- return -ENAMETOOLONG;
-
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
- for (i = 0; i < direntry->d_name.len; i++) {
- if (direntry->d_name.name[i] == '\\') {
- cifs_dbg(FYI, "Invalid file name\n");
- return -EINVAL;
- }
- }
- }
- return 0;
-}
-
-
-/* Inode operations in similar order to how they appear in Linux file fs.h */
-
-static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
- struct tcon_link *tlink, unsigned int oflags, umode_t mode, __u32 *oplock,
- struct cifs_fid *fid, struct cifs_open_info_data *buf)
-{
- int rc = -ENOENT;
- int create_options = CREATE_NOT_DIR;
- int desired_access;
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifs_tcon *tcon = tlink_tcon(tlink);
- const char *full_path;
- void *page = alloc_dentry_path();
- struct inode *newinode = NULL;
- int disposition;
- struct TCP_Server_Info *server = tcon->ses->server;
- struct cifs_open_parms oparms;
-
- *oplock = 0;
- if (tcon->ses->server->oplocks)
- *oplock = REQ_OPLOCK;
-
- full_path = build_path_from_dentry(direntry, page);
- if (IS_ERR(full_path)) {
- free_dentry_path(page);
- return PTR_ERR(full_path);
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
- (CIFS_UNIX_POSIX_PATH_OPS_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))) {
- rc = cifs_posix_open(full_path, &newinode, inode->i_sb, mode,
- oflags, oplock, &fid->netfid, xid);
- switch (rc) {
- case 0:
- if (newinode == NULL) {
- /* query inode info */
- goto cifs_create_get_file_info;
- }
-
- if (S_ISDIR(newinode->i_mode)) {
- CIFSSMBClose(xid, tcon, fid->netfid);
- iput(newinode);
- rc = -EISDIR;
- goto out;
- }
-
- if (!S_ISREG(newinode->i_mode)) {
- /*
- * The server may allow us to open things like
- * FIFOs, but the client isn't set up to deal
- * with that. If it's not a regular file, just
- * close it and proceed as if it were a normal
- * lookup.
- */
- CIFSSMBClose(xid, tcon, fid->netfid);
- goto cifs_create_get_file_info;
- }
- /* success, no need to query */
- goto cifs_create_set_dentry;
-
- case -ENOENT:
- goto cifs_create_get_file_info;
-
- case -EIO:
- case -EINVAL:
- /*
- * EIO could indicate that (posix open) operation is not
- * supported, despite what server claimed in capability
- * negotiation.
- *
- * POSIX open in samba versions 3.3.1 and earlier could
- * incorrectly fail with invalid parameter.
- */
- tcon->broken_posix_open = true;
- break;
-
- case -EREMOTE:
- case -EOPNOTSUPP:
- /*
- * EREMOTE indicates DFS junction, which is not handled
- * in posix open. If either that or op not supported
- * returned, follow the normal lookup.
- */
- break;
-
- default:
- goto out;
- }
- /*
- * fallthrough to retry, using older open call, this is case
- * where server does not support this SMB level, and falsely
- * claims capability (also get here for DFS case which should be
- * rare for path not covered on files)
- */
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- desired_access = 0;
- if (OPEN_FMODE(oflags) & FMODE_READ)
- desired_access |= GENERIC_READ; /* is this too little? */
- if (OPEN_FMODE(oflags) & FMODE_WRITE)
- desired_access |= GENERIC_WRITE;
-
- disposition = FILE_OVERWRITE_IF;
- if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
- disposition = FILE_CREATE;
- else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
- disposition = FILE_OVERWRITE_IF;
- else if ((oflags & O_CREAT) == O_CREAT)
- disposition = FILE_OPEN_IF;
- else
- cifs_dbg(FYI, "Create flag not set in create function\n");
-
- /*
- * BB add processing to set equivalent of mode - e.g. via CreateX with
- * ACLs
- */
-
- if (!server->ops->open) {
- rc = -ENOSYS;
- goto out;
- }
-
- /*
- * if we're not using unix extensions, see if we need to set
- * ATTR_READONLY on the create call
- */
- if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
- create_options |= CREATE_OPTION_READONLY;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = desired_access,
- .create_options = cifs_create_options(cifs_sb, create_options),
- .disposition = disposition,
- .path = full_path,
- .fid = fid,
- .mode = mode,
- };
- rc = server->ops->open(xid, &oparms, oplock, buf);
- if (rc) {
- cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
- goto out;
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- /*
- * If Open reported that we actually created a file then we now have to
- * set the mode if possible.
- */
- if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
- struct cifs_unix_set_info_args args = {
- .mode = mode,
- .ctime = NO_CHANGE_64,
- .atime = NO_CHANGE_64,
- .mtime = NO_CHANGE_64,
- .device = 0,
- };
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = current_fsuid();
- if (inode->i_mode & S_ISGID)
- args.gid = inode->i_gid;
- else
- args.gid = current_fsgid();
- } else {
- args.uid = INVALID_UID; /* no change */
- args.gid = INVALID_GID; /* no change */
- }
- CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,
- current->tgid);
- } else {
- /*
- * BB implement mode setting via Windows security
- * descriptors e.g.
- */
- /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
-
- /* Could set r/o dos attribute if mode & 0222 == 0 */
- }
-
-cifs_create_get_file_info:
- /* server might mask mode so we have to query for it */
- if (tcon->unix_ext)
- rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
- xid);
- else {
-#else
- {
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- /* TODO: Add support for calling POSIX query info here, but passing in fid */
- rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, xid, fid);
- if (newinode) {
- if (server->ops->set_lease_key)
- server->ops->set_lease_key(newinode, fid);
- if ((*oplock & CIFS_CREATE_ACTION) && S_ISREG(newinode->i_mode)) {
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
- newinode->i_mode = mode;
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- newinode->i_uid = current_fsuid();
- if (inode->i_mode & S_ISGID)
- newinode->i_gid = inode->i_gid;
- else
- newinode->i_gid = current_fsgid();
- }
- }
- }
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-cifs_create_set_dentry:
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- if (rc != 0) {
- cifs_dbg(FYI, "Create worked, get_inode_info failed rc = %d\n",
- rc);
- goto out_err;
- }
-
- if (newinode)
- if (S_ISDIR(newinode->i_mode)) {
- rc = -EISDIR;
- goto out_err;
- }
-
- d_drop(direntry);
- d_add(direntry, newinode);
-
-out:
- free_dentry_path(page);
- return rc;
-
-out_err:
- if (server->ops->close)
- server->ops->close(xid, tcon, fid);
- if (newinode)
- iput(newinode);
- goto out;
-}
-
-int
-cifs_atomic_open(struct inode *inode, struct dentry *direntry,
- struct file *file, unsigned oflags, umode_t mode)
-{
- int rc;
- unsigned int xid;
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct cifs_fid fid = {};
- struct cifs_pending_open open;
- __u32 oplock;
- struct cifsFileInfo *file_info;
- struct cifs_open_info_data buf = {};
-
- if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
- return -EIO;
-
- /*
- * Posix open is only called (at lookup time) for file create now. For
- * opens (rather than creates), because we do not know if it is a file
- * or directory yet, and current Samba no longer allows us to do posix
- * open on dirs, we could end up wasting an open call on what turns out
- * to be a dir. For file opens, we wait to call posix open till
- * cifs_open. It could be added to atomic_open in the future but the
- * performance tradeoff of the extra network request when EISDIR or
- * EACCES is returned would have to be weighed against the 50% reduction
- * in network traffic in the other paths.
- */
- if (!(oflags & O_CREAT)) {
- struct dentry *res;
-
- /*
- * Check for hashed negative dentry. We have already revalidated
- * the dentry and it is fine. No need to perform another lookup.
- */
- if (!d_in_lookup(direntry))
- return -ENOENT;
-
- res = cifs_lookup(inode, direntry, 0);
- if (IS_ERR(res))
- return PTR_ERR(res);
-
- return finish_no_open(file, res);
- }
-
- xid = get_xid();
-
- cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
- inode, direntry, direntry);
-
- tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
- if (IS_ERR(tlink)) {
- rc = PTR_ERR(tlink);
- goto out_free_xid;
- }
-
- tcon = tlink_tcon(tlink);
-
- rc = check_name(direntry, tcon);
- if (rc)
- goto out;
-
- server = tcon->ses->server;
-
- if (server->ops->new_lease_key)
- server->ops->new_lease_key(&fid);
-
- cifs_add_pending_open(&fid, tlink, &open);
-
- rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
- &oplock, &fid, &buf);
- if (rc) {
- cifs_del_pending_open(&open);
- goto out;
- }
-
- if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
- file->f_mode |= FMODE_CREATED;
-
- rc = finish_open(file, direntry, generic_file_open);
- if (rc) {
- if (server->ops->close)
- server->ops->close(xid, tcon, &fid);
- cifs_del_pending_open(&open);
- goto out;
- }
-
- if (file->f_flags & O_DIRECT &&
- CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
- if (CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
- file->f_op = &cifs_file_direct_nobrl_ops;
- else
- file->f_op = &cifs_file_direct_ops;
- }
-
- file_info = cifs_new_fileinfo(&fid, file, tlink, oplock, buf.symlink_target);
- if (file_info == NULL) {
- if (server->ops->close)
- server->ops->close(xid, tcon, &fid);
- cifs_del_pending_open(&open);
- rc = -ENOMEM;
- goto out;
- }
-
- fscache_use_cookie(cifs_inode_cookie(file_inode(file)),
- file->f_mode & FMODE_WRITE);
-
-out:
- cifs_put_tlink(tlink);
-out_free_xid:
- free_xid(xid);
- cifs_free_open_info(&buf);
- return rc;
-}
-
-int cifs_create(struct user_namespace *mnt_userns, struct inode *inode,
- struct dentry *direntry, umode_t mode, bool excl)
-{
- int rc;
- unsigned int xid = get_xid();
- /*
- * BB below access is probably too much for mknod to request
- * but we have to do query and setpathinfo so requesting
- * less could fail (unless we want to request getatr and setatr
- * permissions (only). At least for POSIX we do not have to
- * request so much.
- */
- unsigned oflags = O_EXCL | O_CREAT | O_RDWR;
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct cifs_fid fid;
- __u32 oplock;
- struct cifs_open_info_data buf = {};
-
- cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
- inode, direntry, direntry);
-
- if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb)))) {
- rc = -EIO;
- goto out_free_xid;
- }
-
- tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
- rc = PTR_ERR(tlink);
- if (IS_ERR(tlink))
- goto out_free_xid;
-
- tcon = tlink_tcon(tlink);
- server = tcon->ses->server;
-
- if (server->ops->new_lease_key)
- server->ops->new_lease_key(&fid);
-
- rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, &oplock, &fid, &buf);
- if (!rc && server->ops->close)
- server->ops->close(xid, tcon, &fid);
-
- cifs_free_open_info(&buf);
- cifs_put_tlink(tlink);
-out_free_xid:
- free_xid(xid);
- return rc;
-}
-
-int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode,
- struct dentry *direntry, umode_t mode, dev_t device_number)
-{
- int rc = -EPERM;
- unsigned int xid;
- struct cifs_sb_info *cifs_sb;
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- const char *full_path;
- void *page;
-
- if (!old_valid_dev(device_number))
- return -EINVAL;
-
- cifs_sb = CIFS_SB(inode->i_sb);
- if (unlikely(cifs_forced_shutdown(cifs_sb)))
- return -EIO;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
-
- page = alloc_dentry_path();
- tcon = tlink_tcon(tlink);
- xid = get_xid();
-
- full_path = build_path_from_dentry(direntry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto mknod_out;
- }
-
- rc = tcon->ses->server->ops->make_node(xid, inode, direntry, tcon,
- full_path, mode,
- device_number);
-
-mknod_out:
- free_dentry_path(page);
- free_xid(xid);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-struct dentry *
-cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
- unsigned int flags)
-{
- unsigned int xid;
- int rc = 0; /* to get around spurious gcc warning, set to zero here */
- struct cifs_sb_info *cifs_sb;
- struct tcon_link *tlink;
- struct cifs_tcon *pTcon;
- struct inode *newInode = NULL;
- const char *full_path;
- void *page;
- int retry_count = 0;
-
- xid = get_xid();
-
- cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
- parent_dir_inode, direntry, direntry);
-
- /* check whether path exists */
-
- cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink)) {
- free_xid(xid);
- return ERR_CAST(tlink);
- }
- pTcon = tlink_tcon(tlink);
-
- rc = check_name(direntry, pTcon);
- if (unlikely(rc)) {
- cifs_put_tlink(tlink);
- free_xid(xid);
- return ERR_PTR(rc);
- }
-
- /* can not grab the rename sem here since it would
- deadlock in the cases (beginning of sys_rename itself)
- in which we already have the sb rename sem */
- page = alloc_dentry_path();
- full_path = build_path_from_dentry(direntry, page);
- if (IS_ERR(full_path)) {
- cifs_put_tlink(tlink);
- free_xid(xid);
- free_dentry_path(page);
- return ERR_CAST(full_path);
- }
-
- if (d_really_is_positive(direntry)) {
- cifs_dbg(FYI, "non-NULL inode in lookup\n");
- } else {
- cifs_dbg(FYI, "NULL inode in lookup\n");
- }
- cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
- full_path, d_inode(direntry));
-
-again:
- if (pTcon->posix_extensions)
- rc = smb311_posix_get_inode_info(&newInode, full_path, parent_dir_inode->i_sb, xid);
- else if (pTcon->unix_ext) {
- rc = cifs_get_inode_info_unix(&newInode, full_path,
- parent_dir_inode->i_sb, xid);
- } else {
- rc = cifs_get_inode_info(&newInode, full_path, NULL,
- parent_dir_inode->i_sb, xid, NULL);
- }
-
- if (rc == 0) {
- /* since paths are not looked up by component - the parent
- directories are presumed to be good here */
- renew_parental_timestamps(direntry);
- } else if (rc == -EAGAIN && retry_count++ < 10) {
- goto again;
- } else if (rc == -ENOENT) {
- cifs_set_time(direntry, jiffies);
- newInode = NULL;
- } else {
- if (rc != -EACCES) {
- cifs_dbg(FYI, "Unexpected lookup error %d\n", rc);
- /* We special case check for Access Denied - since that
- is a common return code */
- }
- newInode = ERR_PTR(rc);
- }
- free_dentry_path(page);
- cifs_put_tlink(tlink);
- free_xid(xid);
- return d_splice_alias(newInode, direntry);
-}
-
-static int
-cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
-{
- struct inode *inode;
- int rc;
-
- if (flags & LOOKUP_RCU)
- return -ECHILD;
-
- if (d_really_is_positive(direntry)) {
- inode = d_inode(direntry);
- if ((flags & LOOKUP_REVAL) && !CIFS_CACHE_READ(CIFS_I(inode)))
- CIFS_I(inode)->time = 0; /* force reval */
-
- rc = cifs_revalidate_dentry(direntry);
- if (rc) {
- cifs_dbg(FYI, "cifs_revalidate_dentry failed with rc=%d", rc);
- switch (rc) {
- case -ENOENT:
- case -ESTALE:
- /*
- * Those errors mean the dentry is invalid
- * (file was deleted or recreated)
- */
- return 0;
- default:
- /*
- * Otherwise some unexpected error happened
- * report it as-is to VFS layer
- */
- return rc;
- }
- }
- else {
- /*
- * If the inode wasn't known to be a dfs entry when
- * the dentry was instantiated, such as when created
- * via ->readdir(), it needs to be set now since the
- * attributes will have been updated by
- * cifs_revalidate_dentry().
- */
- if (IS_AUTOMOUNT(inode) &&
- !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) {
- spin_lock(&direntry->d_lock);
- direntry->d_flags |= DCACHE_NEED_AUTOMOUNT;
- spin_unlock(&direntry->d_lock);
- }
-
- return 1;
- }
- }
-
- /*
- * This may be nfsd (or something), anyway, we can't see the
- * intent of this. So, since this can be for creation, drop it.
- */
- if (!flags)
- return 0;
-
- /*
- * Drop the negative dentry, in order to make sure to use the
- * case sensitive name which is specified by user if this is
- * for creation.
- */
- if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
- return 0;
-
- if (time_after(jiffies, cifs_get_time(direntry) + HZ) || !lookupCacheEnabled)
- return 0;
-
- return 1;
-}
-
-/* static int cifs_d_delete(struct dentry *direntry)
-{
- int rc = 0;
-
- cifs_dbg(FYI, "In cifs d_delete, name = %pd\n", direntry);
-
- return rc;
-} */
-
-const struct dentry_operations cifs_dentry_ops = {
- .d_revalidate = cifs_d_revalidate,
- .d_automount = cifs_dfs_d_automount,
-/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
-};
-
-static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q)
-{
- struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
- unsigned long hash;
- wchar_t c;
- int i, charlen;
-
- hash = init_name_hash(dentry);
- for (i = 0; i < q->len; i += charlen) {
- charlen = codepage->char2uni(&q->name[i], q->len - i, &c);
- /* error out if we can't convert the character */
- if (unlikely(charlen < 0))
- return charlen;
- hash = partial_name_hash(cifs_toupper(c), hash);
- }
- q->hash = end_name_hash(hash);
-
- return 0;
-}
-
-static int cifs_ci_compare(const struct dentry *dentry,
- unsigned int len, const char *str, const struct qstr *name)
-{
- struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
- wchar_t c1, c2;
- int i, l1, l2;
-
- /*
- * We make the assumption here that uppercase characters in the local
- * codepage are always the same length as their lowercase counterparts.
- *
- * If that's ever not the case, then this will fail to match it.
- */
- if (name->len != len)
- return 1;
-
- for (i = 0; i < len; i += l1) {
- /* Convert characters in both strings to UTF-16. */
- l1 = codepage->char2uni(&str[i], len - i, &c1);
- l2 = codepage->char2uni(&name->name[i], name->len - i, &c2);
-
- /*
- * If we can't convert either character, just declare it to
- * be 1 byte long and compare the original byte.
- */
- if (unlikely(l1 < 0 && l2 < 0)) {
- if (str[i] != name->name[i])
- return 1;
- l1 = 1;
- continue;
- }
-
- /*
- * Here, we again ass|u|me that upper/lowercase versions of
- * a character are the same length in the local NLS.
- */
- if (l1 != l2)
- return 1;
-
- /* Now compare uppercase versions of these characters */
- if (cifs_toupper(c1) != cifs_toupper(c2))
- return 1;
- }
-
- return 0;
-}
-
-const struct dentry_operations cifs_ci_dentry_ops = {
- .d_revalidate = cifs_d_revalidate,
- .d_hash = cifs_ci_hash,
- .d_compare = cifs_ci_compare,
- .d_automount = cifs_dfs_d_automount,
-};
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
deleted file mode 100644
index 0458d28d71aa..000000000000
--- a/fs/cifs/dns_resolve.c
+++ /dev/null
@@ -1,89 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (c) 2007 Igor Mammedov
- * Author(s): Igor Mammedov (niallain@gmail.com)
- * Steve French (sfrench@us.ibm.com)
- * Wang Lei (wang840925@gmail.com)
- * David Howells (dhowells@redhat.com)
- *
- * Contains the CIFS DFS upcall routines used for hostname to
- * IP address translation.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/dns_resolver.h>
-#include "dns_resolve.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-
-/**
- * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address.
- * @unc: UNC path specifying the server (with '/' as delimiter)
- * @ip_addr: Where to return the IP address.
- * @expiry: Where to return the expiry time for the dns record.
- *
- * The IP address will be returned in string form, and the caller is
- * responsible for freeing it.
- *
- * Returns length of result on success, -ve on error.
- */
-int
-dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry)
-{
- struct sockaddr_storage ss;
- const char *hostname, *sep;
- char *name;
- int len, rc;
-
- if (!ip_addr || !unc)
- return -EINVAL;
-
- len = strlen(unc);
- if (len < 3) {
- cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc);
- return -EINVAL;
- }
-
- /* Discount leading slashes for cifs */
- len -= 2;
- hostname = unc + 2;
-
- /* Search for server name delimiter */
- sep = memchr(hostname, '/', len);
- if (sep)
- len = sep - hostname;
- else
- cifs_dbg(FYI, "%s: probably server name is whole unc: %s\n",
- __func__, unc);
-
- /* Try to interpret hostname as an IPv4 or IPv6 address */
- rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len);
- if (rc > 0)
- goto name_is_IP_address;
-
- /* Perform the upcall */
- rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len,
- NULL, ip_addr, expiry, false);
- if (rc < 0)
- cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n",
- __func__, len, len, hostname);
- else
- cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n",
- __func__, len, len, hostname, *ip_addr,
- expiry ? (*expiry) : 0);
- return rc;
-
-name_is_IP_address:
- name = kmalloc(len + 1, GFP_KERNEL);
- if (!name)
- return -ENOMEM;
- memcpy(name, hostname, len);
- name[len] = 0;
- cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %s\n",
- __func__, name);
- *ip_addr = name;
- return 0;
-}
diff --git a/fs/cifs/dns_resolve.h b/fs/cifs/dns_resolve.h
deleted file mode 100644
index afc0df381246..000000000000
--- a/fs/cifs/dns_resolve.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- * DNS Resolver upcall management for CIFS DFS
- * Handles host name to IP address resolution
- *
- * Copyright (c) International Business Machines Corp., 2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#ifndef _DNS_RESOLVE_H
-#define _DNS_RESOLVE_H
-
-#ifdef __KERNEL__
-extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry);
-#endif /* KERNEL */
-
-#endif /* _DNS_RESOLVE_H */
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
deleted file mode 100644
index 37c28415df1e..000000000000
--- a/fs/cifs/export.c
+++ /dev/null
@@ -1,54 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2007
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- * Common Internet FileSystem (CIFS) client
- *
- * Operations related to support for exporting files via NFSD
- *
- */
-
- /*
- * See Documentation/filesystems/nfs/exporting.rst
- * and examples in fs/exportfs
- *
- * Since cifs is a network file system, an "fsid" must be included for
- * any nfs exports file entries which refer to cifs paths. In addition
- * the cifs mount must be mounted with the "serverino" option (ie use stable
- * server inode numbers instead of locally generated temporary ones).
- * Although cifs inodes do not use generation numbers (have generation number
- * of zero) - the inode number alone should be good enough for simple cases
- * in which users want to export cifs shares with NFS. The decode and encode
- * could be improved by using a new routine which expects 64 bit inode numbers
- * instead of the default 32 bit routines in fs/exportfs
- *
- */
-
-#include <linux/fs.h>
-#include <linux/exportfs.h>
-#include "cifsglob.h"
-#include "cifs_debug.h"
-#include "cifsfs.h"
-
-#ifdef CONFIG_CIFS_NFSD_EXPORT
-static struct dentry *cifs_get_parent(struct dentry *dentry)
-{
- /* BB need to add code here eventually to enable export via NFSD */
- cifs_dbg(FYI, "get parent for %p\n", dentry);
- return ERR_PTR(-EACCES);
-}
-
-const struct export_operations cifs_export_ops = {
- .get_parent = cifs_get_parent,
-/* Following five export operations are unneeded so far and can default:
- .get_dentry =
- .get_name =
- .find_exported_dentry =
- .decode_fh =
- .encode_fs = */
-};
-
-#endif /* CONFIG_CIFS_NFSD_EXPORT */
-
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
deleted file mode 100644
index 87dcffece762..000000000000
--- a/fs/cifs/file.c
+++ /dev/null
@@ -1,5290 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * vfs operations that deal with files
- *
- * Copyright (C) International Business Machines Corp., 2002,2010
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Jeremy Allison (jra@samba.org)
- *
- */
-#include <linux/fs.h>
-#include <linux/backing-dev.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/pagemap.h>
-#include <linux/pagevec.h>
-#include <linux/writeback.h>
-#include <linux/task_io_accounting_ops.h>
-#include <linux/delay.h>
-#include <linux/mount.h>
-#include <linux/slab.h>
-#include <linux/swap.h>
-#include <linux/mm.h>
-#include <asm/div64.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "smb2proto.h"
-#include "cifs_unicode.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "fscache.h"
-#include "smbdirect.h"
-#include "fs_context.h"
-#include "cifs_ioctl.h"
-#include "cached_dir.h"
-
-/*
- * Mark as invalid, all open files on tree connections since they
- * were closed when session to server was lost.
- */
-void
-cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
-{
- struct cifsFileInfo *open_file = NULL;
- struct list_head *tmp;
- struct list_head *tmp1;
-
- /* only send once per connect */
- spin_lock(&tcon->ses->ses_lock);
- if ((tcon->ses->ses_status != SES_GOOD) || (tcon->status != TID_NEED_RECON)) {
- spin_unlock(&tcon->ses->ses_lock);
- return;
- }
- tcon->status = TID_IN_FILES_INVALIDATE;
- spin_unlock(&tcon->ses->ses_lock);
-
- /* list all files open on tree connection and mark them invalid */
- spin_lock(&tcon->open_file_lock);
- list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
- open_file = list_entry(tmp, struct cifsFileInfo, tlist);
- open_file->invalidHandle = true;
- open_file->oplock_break_cancelled = true;
- }
- spin_unlock(&tcon->open_file_lock);
-
- invalidate_all_cached_dirs(tcon);
- spin_lock(&tcon->tc_lock);
- if (tcon->status == TID_IN_FILES_INVALIDATE)
- tcon->status = TID_NEED_TCON;
- spin_unlock(&tcon->tc_lock);
-
- /*
- * BB Add call to invalidate_inodes(sb) for all superblocks mounted
- * to this tcon.
- */
-}
-
-static inline int cifs_convert_flags(unsigned int flags)
-{
- if ((flags & O_ACCMODE) == O_RDONLY)
- return GENERIC_READ;
- else if ((flags & O_ACCMODE) == O_WRONLY)
- return GENERIC_WRITE;
- else if ((flags & O_ACCMODE) == O_RDWR) {
- /* GENERIC_ALL is too much permission to request
- can cause unnecessary access denied on create */
- /* return GENERIC_ALL; */
- return (GENERIC_READ | GENERIC_WRITE);
- }
-
- return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
- FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
- FILE_READ_DATA);
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-static u32 cifs_posix_convert_flags(unsigned int flags)
-{
- u32 posix_flags = 0;
-
- if ((flags & O_ACCMODE) == O_RDONLY)
- posix_flags = SMB_O_RDONLY;
- else if ((flags & O_ACCMODE) == O_WRONLY)
- posix_flags = SMB_O_WRONLY;
- else if ((flags & O_ACCMODE) == O_RDWR)
- posix_flags = SMB_O_RDWR;
-
- if (flags & O_CREAT) {
- posix_flags |= SMB_O_CREAT;
- if (flags & O_EXCL)
- posix_flags |= SMB_O_EXCL;
- } else if (flags & O_EXCL)
- cifs_dbg(FYI, "Application %s pid %d has incorrectly set O_EXCL flag but not O_CREAT on file open. Ignoring O_EXCL\n",
- current->comm, current->tgid);
-
- if (flags & O_TRUNC)
- posix_flags |= SMB_O_TRUNC;
- /* be safe and imply O_SYNC for O_DSYNC */
- if (flags & O_DSYNC)
- posix_flags |= SMB_O_SYNC;
- if (flags & O_DIRECTORY)
- posix_flags |= SMB_O_DIRECTORY;
- if (flags & O_NOFOLLOW)
- posix_flags |= SMB_O_NOFOLLOW;
- if (flags & O_DIRECT)
- posix_flags |= SMB_O_DIRECT;
-
- return posix_flags;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-static inline int cifs_get_disposition(unsigned int flags)
-{
- if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
- return FILE_CREATE;
- else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
- return FILE_OVERWRITE_IF;
- else if ((flags & O_CREAT) == O_CREAT)
- return FILE_OPEN_IF;
- else if ((flags & O_TRUNC) == O_TRUNC)
- return FILE_OVERWRITE;
- else
- return FILE_OPEN;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-int cifs_posix_open(const char *full_path, struct inode **pinode,
- struct super_block *sb, int mode, unsigned int f_flags,
- __u32 *poplock, __u16 *pnetfid, unsigned int xid)
-{
- int rc;
- FILE_UNIX_BASIC_INFO *presp_data;
- __u32 posix_flags = 0;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifs_fattr fattr;
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
-
- cifs_dbg(FYI, "posix open %s\n", full_path);
-
- presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
- if (presp_data == NULL)
- return -ENOMEM;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink)) {
- rc = PTR_ERR(tlink);
- goto posix_open_ret;
- }
-
- tcon = tlink_tcon(tlink);
- mode &= ~current_umask();
-
- posix_flags = cifs_posix_convert_flags(f_flags);
- rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
- poplock, full_path, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- cifs_put_tlink(tlink);
-
- if (rc)
- goto posix_open_ret;
-
- if (presp_data->Type == cpu_to_le32(-1))
- goto posix_open_ret; /* open ok, caller does qpathinfo */
-
- if (!pinode)
- goto posix_open_ret; /* caller does not need info */
-
- cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
-
- /* get new inode and set it up */
- if (*pinode == NULL) {
- cifs_fill_uniqueid(sb, &fattr);
- *pinode = cifs_iget(sb, &fattr);
- if (!*pinode) {
- rc = -ENOMEM;
- goto posix_open_ret;
- }
- } else {
- cifs_revalidate_mapping(*pinode);
- rc = cifs_fattr_to_inode(*pinode, &fattr);
- }
-
-posix_open_ret:
- kfree(presp_data);
- return rc;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
- struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock,
- struct cifs_fid *fid, unsigned int xid, struct cifs_open_info_data *buf)
-{
- int rc;
- int desired_access;
- int disposition;
- int create_options = CREATE_NOT_DIR;
- struct TCP_Server_Info *server = tcon->ses->server;
- struct cifs_open_parms oparms;
-
- if (!server->ops->open)
- return -ENOSYS;
-
- desired_access = cifs_convert_flags(f_flags);
-
-/*********************************************************************
- * open flag mapping table:
- *
- * POSIX Flag CIFS Disposition
- * ---------- ----------------
- * O_CREAT FILE_OPEN_IF
- * O_CREAT | O_EXCL FILE_CREATE
- * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
- * O_TRUNC FILE_OVERWRITE
- * none of the above FILE_OPEN
- *
- * Note that there is not a direct match between disposition
- * FILE_SUPERSEDE (ie create whether or not file exists although
- * O_CREAT | O_TRUNC is similar but truncates the existing
- * file rather than creating a new file as FILE_SUPERSEDE does
- * (which uses the attributes / metadata passed in on open call)
- *?
- *? O_SYNC is a reasonable match to CIFS writethrough flag
- *? and the read write flags match reasonably. O_LARGEFILE
- *? is irrelevant because largefile support is always used
- *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
- * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
- *********************************************************************/
-
- disposition = cifs_get_disposition(f_flags);
-
- /* BB pass O_SYNC flag through on file attributes .. BB */
-
- /* O_SYNC also has bit for O_DSYNC so following check picks up either */
- if (f_flags & O_SYNC)
- create_options |= CREATE_WRITE_THROUGH;
-
- if (f_flags & O_DIRECT)
- create_options |= CREATE_NO_BUFFER;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = desired_access,
- .create_options = cifs_create_options(cifs_sb, create_options),
- .disposition = disposition,
- .path = full_path,
- .fid = fid,
- };
-
- rc = server->ops->open(xid, &oparms, oplock, buf);
- if (rc)
- return rc;
-
- /* TODO: Add support for calling posix query info but with passing in fid */
- if (tcon->unix_ext)
- rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
- xid);
- else
- rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
- xid, fid);
-
- if (rc) {
- server->ops->close(xid, tcon, fid);
- if (rc == -ESTALE)
- rc = -EOPENSTALE;
- }
-
- return rc;
-}
-
-static bool
-cifs_has_mand_locks(struct cifsInodeInfo *cinode)
-{
- struct cifs_fid_locks *cur;
- bool has_locks = false;
-
- down_read(&cinode->lock_sem);
- list_for_each_entry(cur, &cinode->llist, llist) {
- if (!list_empty(&cur->locks)) {
- has_locks = true;
- break;
- }
- }
- up_read(&cinode->lock_sem);
- return has_locks;
-}
-
-void
-cifs_down_write(struct rw_semaphore *sem)
-{
- while (!down_write_trylock(sem))
- msleep(10);
-}
-
-static void cifsFileInfo_put_work(struct work_struct *work);
-
-struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
- struct tcon_link *tlink, __u32 oplock,
- const char *symlink_target)
-{
- struct dentry *dentry = file_dentry(file);
- struct inode *inode = d_inode(dentry);
- struct cifsInodeInfo *cinode = CIFS_I(inode);
- struct cifsFileInfo *cfile;
- struct cifs_fid_locks *fdlocks;
- struct cifs_tcon *tcon = tlink_tcon(tlink);
- struct TCP_Server_Info *server = tcon->ses->server;
-
- cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
- if (cfile == NULL)
- return cfile;
-
- fdlocks = kzalloc(sizeof(struct cifs_fid_locks), GFP_KERNEL);
- if (!fdlocks) {
- kfree(cfile);
- return NULL;
- }
-
- if (symlink_target) {
- cfile->symlink_target = kstrdup(symlink_target, GFP_KERNEL);
- if (!cfile->symlink_target) {
- kfree(fdlocks);
- kfree(cfile);
- return NULL;
- }
- }
-
- INIT_LIST_HEAD(&fdlocks->locks);
- fdlocks->cfile = cfile;
- cfile->llist = fdlocks;
-
- cfile->count = 1;
- cfile->pid = current->tgid;
- cfile->uid = current_fsuid();
- cfile->dentry = dget(dentry);
- cfile->f_flags = file->f_flags;
- cfile->invalidHandle = false;
- cfile->deferred_close_scheduled = false;
- cfile->tlink = cifs_get_tlink(tlink);
- INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
- INIT_WORK(&cfile->put, cifsFileInfo_put_work);
- INIT_DELAYED_WORK(&cfile->deferred, smb2_deferred_work_close);
- mutex_init(&cfile->fh_mutex);
- spin_lock_init(&cfile->file_info_lock);
-
- cifs_sb_active(inode->i_sb);
-
- /*
- * If the server returned a read oplock and we have mandatory brlocks,
- * set oplock level to None.
- */
- if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) {
- cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n");
- oplock = 0;
- }
-
- cifs_down_write(&cinode->lock_sem);
- list_add(&fdlocks->llist, &cinode->llist);
- up_write(&cinode->lock_sem);
-
- spin_lock(&tcon->open_file_lock);
- if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock)
- oplock = fid->pending_open->oplock;
- list_del(&fid->pending_open->olist);
-
- fid->purge_cache = false;
- server->ops->set_fid(cfile, fid, oplock);
-
- list_add(&cfile->tlist, &tcon->openFileList);
- atomic_inc(&tcon->num_local_opens);
-
- /* if readable file instance put first in list*/
- spin_lock(&cinode->open_file_lock);
- if (file->f_mode & FMODE_READ)
- list_add(&cfile->flist, &cinode->openFileList);
- else
- list_add_tail(&cfile->flist, &cinode->openFileList);
- spin_unlock(&cinode->open_file_lock);
- spin_unlock(&tcon->open_file_lock);
-
- if (fid->purge_cache)
- cifs_zap_mapping(inode);
-
- file->private_data = cfile;
- return cfile;
-}
-
-struct cifsFileInfo *
-cifsFileInfo_get(struct cifsFileInfo *cifs_file)
-{
- spin_lock(&cifs_file->file_info_lock);
- cifsFileInfo_get_locked(cifs_file);
- spin_unlock(&cifs_file->file_info_lock);
- return cifs_file;
-}
-
-static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
-{
- struct inode *inode = d_inode(cifs_file->dentry);
- struct cifsInodeInfo *cifsi = CIFS_I(inode);
- struct cifsLockInfo *li, *tmp;
- struct super_block *sb = inode->i_sb;
-
- /*
- * Delete any outstanding lock records. We'll lose them when the file
- * is closed anyway.
- */
- cifs_down_write(&cifsi->lock_sem);
- list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) {
- list_del(&li->llist);
- cifs_del_lock_waiters(li);
- kfree(li);
- }
- list_del(&cifs_file->llist->llist);
- kfree(cifs_file->llist);
- up_write(&cifsi->lock_sem);
-
- cifs_put_tlink(cifs_file->tlink);
- dput(cifs_file->dentry);
- cifs_sb_deactive(sb);
- kfree(cifs_file->symlink_target);
- kfree(cifs_file);
-}
-
-static void cifsFileInfo_put_work(struct work_struct *work)
-{
- struct cifsFileInfo *cifs_file = container_of(work,
- struct cifsFileInfo, put);
-
- cifsFileInfo_put_final(cifs_file);
-}
-
-/**
- * cifsFileInfo_put - release a reference of file priv data
- *
- * Always potentially wait for oplock handler. See _cifsFileInfo_put().
- *
- * @cifs_file: cifs/smb3 specific info (eg refcounts) for an open file
- */
-void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
-{
- _cifsFileInfo_put(cifs_file, true, true);
-}
-
-/**
- * _cifsFileInfo_put - release a reference of file priv data
- *
- * This may involve closing the filehandle @cifs_file out on the
- * server. Must be called without holding tcon->open_file_lock,
- * cinode->open_file_lock and cifs_file->file_info_lock.
- *
- * If @wait_for_oplock_handler is true and we are releasing the last
- * reference, wait for any running oplock break handler of the file
- * and cancel any pending one.
- *
- * @cifs_file: cifs/smb3 specific info (eg refcounts) for an open file
- * @wait_oplock_handler: must be false if called from oplock_break_handler
- * @offload: not offloaded on close and oplock breaks
- *
- */
-void _cifsFileInfo_put(struct cifsFileInfo *cifs_file,
- bool wait_oplock_handler, bool offload)
-{
- struct inode *inode = d_inode(cifs_file->dentry);
- struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
- struct TCP_Server_Info *server = tcon->ses->server;
- struct cifsInodeInfo *cifsi = CIFS_I(inode);
- struct super_block *sb = inode->i_sb;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifs_fid fid = {};
- struct cifs_pending_open open;
- bool oplock_break_cancelled;
-
- spin_lock(&tcon->open_file_lock);
- spin_lock(&cifsi->open_file_lock);
- spin_lock(&cifs_file->file_info_lock);
- if (--cifs_file->count > 0) {
- spin_unlock(&cifs_file->file_info_lock);
- spin_unlock(&cifsi->open_file_lock);
- spin_unlock(&tcon->open_file_lock);
- return;
- }
- spin_unlock(&cifs_file->file_info_lock);
-
- if (server->ops->get_lease_key)
- server->ops->get_lease_key(inode, &fid);
-
- /* store open in pending opens to make sure we don't miss lease break */
- cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open);
-
- /* remove it from the lists */
- list_del(&cifs_file->flist);
- list_del(&cifs_file->tlist);
- atomic_dec(&tcon->num_local_opens);
-
- if (list_empty(&cifsi->openFileList)) {
- cifs_dbg(FYI, "closing last open instance for inode %p\n",
- d_inode(cifs_file->dentry));
- /*
- * In strict cache mode we need invalidate mapping on the last
- * close because it may cause a error when we open this file
- * again and get at least level II oplock.
- */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
- set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags);
- cifs_set_oplock_level(cifsi, 0);
- }
-
- spin_unlock(&cifsi->open_file_lock);
- spin_unlock(&tcon->open_file_lock);
-
- oplock_break_cancelled = wait_oplock_handler ?
- cancel_work_sync(&cifs_file->oplock_break) : false;
-
- if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
- struct TCP_Server_Info *server = tcon->ses->server;
- unsigned int xid;
-
- xid = get_xid();
- if (server->ops->close_getattr)
- server->ops->close_getattr(xid, tcon, cifs_file);
- else if (server->ops->close)
- server->ops->close(xid, tcon, &cifs_file->fid);
- _free_xid(xid);
- }
-
- if (oplock_break_cancelled)
- cifs_done_oplock_break(cifsi);
-
- cifs_del_pending_open(&open);
-
- if (offload)
- queue_work(fileinfo_put_wq, &cifs_file->put);
- else
- cifsFileInfo_put_final(cifs_file);
-}
-
-int cifs_open(struct inode *inode, struct file *file)
-
-{
- int rc = -EACCES;
- unsigned int xid;
- __u32 oplock;
- struct cifs_sb_info *cifs_sb;
- struct TCP_Server_Info *server;
- struct cifs_tcon *tcon;
- struct tcon_link *tlink;
- struct cifsFileInfo *cfile = NULL;
- void *page;
- const char *full_path;
- bool posix_open_ok = false;
- struct cifs_fid fid = {};
- struct cifs_pending_open open;
- struct cifs_open_info_data data = {};
-
- xid = get_xid();
-
- cifs_sb = CIFS_SB(inode->i_sb);
- if (unlikely(cifs_forced_shutdown(cifs_sb))) {
- free_xid(xid);
- return -EIO;
- }
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink)) {
- free_xid(xid);
- return PTR_ERR(tlink);
- }
- tcon = tlink_tcon(tlink);
- server = tcon->ses->server;
-
- page = alloc_dentry_path();
- full_path = build_path_from_dentry(file_dentry(file), page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto out;
- }
-
- cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
- inode, file->f_flags, full_path);
-
- if (file->f_flags & O_DIRECT &&
- cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
- file->f_op = &cifs_file_direct_nobrl_ops;
- else
- file->f_op = &cifs_file_direct_ops;
- }
-
- /* Get the cached handle as SMB2 close is deferred */
- rc = cifs_get_readable_path(tcon, full_path, &cfile);
- if (rc == 0) {
- if (file->f_flags == cfile->f_flags) {
- file->private_data = cfile;
- spin_lock(&CIFS_I(inode)->deferred_lock);
- cifs_del_deferred_close(cfile);
- spin_unlock(&CIFS_I(inode)->deferred_lock);
- goto use_cache;
- } else {
- _cifsFileInfo_put(cfile, true, false);
- }
- }
-
- if (server->oplocks)
- oplock = REQ_OPLOCK;
- else
- oplock = 0;
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (!tcon->broken_posix_open && tcon->unix_ext &&
- cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))) {
- /* can not refresh inode info since size could be stale */
- rc = cifs_posix_open(full_path, &inode, inode->i_sb,
- cifs_sb->ctx->file_mode /* ignored */,
- file->f_flags, &oplock, &fid.netfid, xid);
- if (rc == 0) {
- cifs_dbg(FYI, "posix open succeeded\n");
- posix_open_ok = true;
- } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
- if (tcon->ses->serverNOS)
- cifs_dbg(VFS, "server %s of type %s returned unexpected error on SMB posix open, disabling posix open support. Check if server update available.\n",
- tcon->ses->ip_addr,
- tcon->ses->serverNOS);
- tcon->broken_posix_open = true;
- } else if ((rc != -EIO) && (rc != -EREMOTE) &&
- (rc != -EOPNOTSUPP)) /* path not found or net err */
- goto out;
- /*
- * Else fallthrough to retry open the old way on network i/o
- * or DFS errors.
- */
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- if (server->ops->get_lease_key)
- server->ops->get_lease_key(inode, &fid);
-
- cifs_add_pending_open(&fid, tlink, &open);
-
- if (!posix_open_ok) {
- if (server->ops->get_lease_key)
- server->ops->get_lease_key(inode, &fid);
-
- rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, file->f_flags, &oplock, &fid,
- xid, &data);
- if (rc) {
- cifs_del_pending_open(&open);
- goto out;
- }
- }
-
- cfile = cifs_new_fileinfo(&fid, file, tlink, oplock, data.symlink_target);
- if (cfile == NULL) {
- if (server->ops->close)
- server->ops->close(xid, tcon, &fid);
- cifs_del_pending_open(&open);
- rc = -ENOMEM;
- goto out;
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
- /*
- * Time to set mode which we can not set earlier due to
- * problems creating new read-only files.
- */
- struct cifs_unix_set_info_args args = {
- .mode = inode->i_mode,
- .uid = INVALID_UID, /* no change */
- .gid = INVALID_GID, /* no change */
- .ctime = NO_CHANGE_64,
- .atime = NO_CHANGE_64,
- .mtime = NO_CHANGE_64,
- .device = 0,
- };
- CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid,
- cfile->pid);
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-use_cache:
- fscache_use_cookie(cifs_inode_cookie(file_inode(file)),
- file->f_mode & FMODE_WRITE);
- if (file->f_flags & O_DIRECT &&
- (!((file->f_flags & O_ACCMODE) != O_RDONLY) ||
- file->f_flags & O_APPEND))
- cifs_invalidate_cache(file_inode(file),
- FSCACHE_INVAL_DIO_WRITE);
-
-out:
- free_dentry_path(page);
- free_xid(xid);
- cifs_put_tlink(tlink);
- cifs_free_open_info(&data);
- return rc;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-static int cifs_push_posix_locks(struct cifsFileInfo *cfile);
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-/*
- * Try to reacquire byte range locks that were released when session
- * to server was lost.
- */
-static int
-cifs_relock_file(struct cifsFileInfo *cfile)
-{
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- int rc = 0;
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- down_read_nested(&cinode->lock_sem, SINGLE_DEPTH_NESTING);
- if (cinode->can_cache_brlcks) {
- /* can cache locks - no need to relock */
- up_read(&cinode->lock_sem);
- return rc;
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (cap_unix(tcon->ses) &&
- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
- ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
- rc = cifs_push_posix_locks(cfile);
- else
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- rc = tcon->ses->server->ops->push_mand_locks(cfile);
-
- up_read(&cinode->lock_sem);
- return rc;
-}
-
-static int
-cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
-{
- int rc = -EACCES;
- unsigned int xid;
- __u32 oplock;
- struct cifs_sb_info *cifs_sb;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct cifsInodeInfo *cinode;
- struct inode *inode;
- void *page;
- const char *full_path;
- int desired_access;
- int disposition = FILE_OPEN;
- int create_options = CREATE_NOT_DIR;
- struct cifs_open_parms oparms;
-
- xid = get_xid();
- mutex_lock(&cfile->fh_mutex);
- if (!cfile->invalidHandle) {
- mutex_unlock(&cfile->fh_mutex);
- free_xid(xid);
- return 0;
- }
-
- inode = d_inode(cfile->dentry);
- cifs_sb = CIFS_SB(inode->i_sb);
- tcon = tlink_tcon(cfile->tlink);
- server = tcon->ses->server;
-
- /*
- * Can not grab rename sem here because various ops, including those
- * that already have the rename sem can end up causing writepage to get
- * called and if the server was down that means we end up here, and we
- * can never tell if the caller already has the rename_sem.
- */
- page = alloc_dentry_path();
- full_path = build_path_from_dentry(cfile->dentry, page);
- if (IS_ERR(full_path)) {
- mutex_unlock(&cfile->fh_mutex);
- free_dentry_path(page);
- free_xid(xid);
- return PTR_ERR(full_path);
- }
-
- cifs_dbg(FYI, "inode = 0x%p file flags 0x%x for %s\n",
- inode, cfile->f_flags, full_path);
-
- if (tcon->ses->server->oplocks)
- oplock = REQ_OPLOCK;
- else
- oplock = 0;
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (tcon->unix_ext && cap_unix(tcon->ses) &&
- (CIFS_UNIX_POSIX_PATH_OPS_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))) {
- /*
- * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
- * original open. Must mask them off for a reopen.
- */
- unsigned int oflags = cfile->f_flags &
- ~(O_CREAT | O_EXCL | O_TRUNC);
-
- rc = cifs_posix_open(full_path, NULL, inode->i_sb,
- cifs_sb->ctx->file_mode /* ignored */,
- oflags, &oplock, &cfile->fid.netfid, xid);
- if (rc == 0) {
- cifs_dbg(FYI, "posix reopen succeeded\n");
- oparms.reconnect = true;
- goto reopen_success;
- }
- /*
- * fallthrough to retry open the old way on errors, especially
- * in the reconnect path it is important to retry hard
- */
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- desired_access = cifs_convert_flags(cfile->f_flags);
-
- /* O_SYNC also has bit for O_DSYNC so following check picks up either */
- if (cfile->f_flags & O_SYNC)
- create_options |= CREATE_WRITE_THROUGH;
-
- if (cfile->f_flags & O_DIRECT)
- create_options |= CREATE_NO_BUFFER;
-
- if (server->ops->get_lease_key)
- server->ops->get_lease_key(inode, &cfile->fid);
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = desired_access,
- .create_options = cifs_create_options(cifs_sb, create_options),
- .disposition = disposition,
- .path = full_path,
- .fid = &cfile->fid,
- .reconnect = true,
- };
-
- /*
- * Can not refresh inode by passing in file_info buf to be returned by
- * ops->open and then calling get_inode_info with returned buf since
- * file might have write behind data that needs to be flushed and server
- * version of file size can be stale. If we knew for sure that inode was
- * not dirty locally we could do this.
- */
- rc = server->ops->open(xid, &oparms, &oplock, NULL);
- if (rc == -ENOENT && oparms.reconnect == false) {
- /* durable handle timeout is expired - open the file again */
- rc = server->ops->open(xid, &oparms, &oplock, NULL);
- /* indicate that we need to relock the file */
- oparms.reconnect = true;
- }
-
- if (rc) {
- mutex_unlock(&cfile->fh_mutex);
- cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc);
- cifs_dbg(FYI, "oplock: %d\n", oplock);
- goto reopen_error_exit;
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-reopen_success:
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- cfile->invalidHandle = false;
- mutex_unlock(&cfile->fh_mutex);
- cinode = CIFS_I(inode);
-
- if (can_flush) {
- rc = filemap_write_and_wait(inode->i_mapping);
- if (!is_interrupt_error(rc))
- mapping_set_error(inode->i_mapping, rc);
-
- if (tcon->posix_extensions)
- rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid);
- else if (tcon->unix_ext)
- rc = cifs_get_inode_info_unix(&inode, full_path,
- inode->i_sb, xid);
- else
- rc = cifs_get_inode_info(&inode, full_path, NULL,
- inode->i_sb, xid, NULL);
- }
- /*
- * Else we are writing out data to server already and could deadlock if
- * we tried to flush data, and since we do not know if we have data that
- * would invalidate the current end of file on the server we can not go
- * to the server to get the new inode info.
- */
-
- /*
- * If the server returned a read oplock and we have mandatory brlocks,
- * set oplock level to None.
- */
- if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) {
- cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n");
- oplock = 0;
- }
-
- server->ops->set_fid(cfile, &cfile->fid, oplock);
- if (oparms.reconnect)
- cifs_relock_file(cfile);
-
-reopen_error_exit:
- free_dentry_path(page);
- free_xid(xid);
- return rc;
-}
-
-void smb2_deferred_work_close(struct work_struct *work)
-{
- struct cifsFileInfo *cfile = container_of(work,
- struct cifsFileInfo, deferred.work);
-
- spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
- cifs_del_deferred_close(cfile);
- cfile->deferred_close_scheduled = false;
- spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
- _cifsFileInfo_put(cfile, true, false);
-}
-
-int cifs_close(struct inode *inode, struct file *file)
-{
- struct cifsFileInfo *cfile;
- struct cifsInodeInfo *cinode = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifs_deferred_close *dclose;
-
- cifs_fscache_unuse_inode_cookie(inode, file->f_mode & FMODE_WRITE);
-
- if (file->private_data != NULL) {
- cfile = file->private_data;
- file->private_data = NULL;
- dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
- if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
- cinode->lease_granted &&
- !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) &&
- dclose) {
- if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
- inode->i_ctime = inode->i_mtime = current_time(inode);
- }
- spin_lock(&cinode->deferred_lock);
- cifs_add_deferred_close(cfile, dclose);
- if (cfile->deferred_close_scheduled &&
- delayed_work_pending(&cfile->deferred)) {
- /*
- * If there is no pending work, mod_delayed_work queues new work.
- * So, Increase the ref count to avoid use-after-free.
- */
- if (!mod_delayed_work(deferredclose_wq,
- &cfile->deferred, cifs_sb->ctx->closetimeo))
- cifsFileInfo_get(cfile);
- } else {
- /* Deferred close for files */
- queue_delayed_work(deferredclose_wq,
- &cfile->deferred, cifs_sb->ctx->closetimeo);
- cfile->deferred_close_scheduled = true;
- spin_unlock(&cinode->deferred_lock);
- return 0;
- }
- spin_unlock(&cinode->deferred_lock);
- _cifsFileInfo_put(cfile, true, false);
- } else {
- _cifsFileInfo_put(cfile, true, false);
- kfree(dclose);
- }
- }
-
- /* return code from the ->release op is always ignored */
- return 0;
-}
-
-void
-cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
-{
- struct cifsFileInfo *open_file, *tmp;
- struct list_head tmp_list;
-
- if (!tcon->use_persistent || !tcon->need_reopen_files)
- return;
-
- tcon->need_reopen_files = false;
-
- cifs_dbg(FYI, "Reopen persistent handles\n");
- INIT_LIST_HEAD(&tmp_list);
-
- /* list all files open on tree connection, reopen resilient handles */
- spin_lock(&tcon->open_file_lock);
- list_for_each_entry(open_file, &tcon->openFileList, tlist) {
- if (!open_file->invalidHandle)
- continue;
- cifsFileInfo_get(open_file);
- list_add_tail(&open_file->rlist, &tmp_list);
- }
- spin_unlock(&tcon->open_file_lock);
-
- list_for_each_entry_safe(open_file, tmp, &tmp_list, rlist) {
- if (cifs_reopen_file(open_file, false /* do not flush */))
- tcon->need_reopen_files = true;
- list_del_init(&open_file->rlist);
- cifsFileInfo_put(open_file);
- }
-}
-
-int cifs_closedir(struct inode *inode, struct file *file)
-{
- int rc = 0;
- unsigned int xid;
- struct cifsFileInfo *cfile = file->private_data;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- char *buf;
-
- cifs_dbg(FYI, "Closedir inode = 0x%p\n", inode);
-
- if (cfile == NULL)
- return rc;
-
- xid = get_xid();
- tcon = tlink_tcon(cfile->tlink);
- server = tcon->ses->server;
-
- cifs_dbg(FYI, "Freeing private data in close dir\n");
- spin_lock(&cfile->file_info_lock);
- if (server->ops->dir_needs_close(cfile)) {
- cfile->invalidHandle = true;
- spin_unlock(&cfile->file_info_lock);
- if (server->ops->close_dir)
- rc = server->ops->close_dir(xid, tcon, &cfile->fid);
- else
- rc = -ENOSYS;
- cifs_dbg(FYI, "Closing uncompleted readdir with rc %d\n", rc);
- /* not much we can do if it fails anyway, ignore rc */
- rc = 0;
- } else
- spin_unlock(&cfile->file_info_lock);
-
- buf = cfile->srch_inf.ntwrk_buf_start;
- if (buf) {
- cifs_dbg(FYI, "closedir free smb buf in srch struct\n");
- cfile->srch_inf.ntwrk_buf_start = NULL;
- if (cfile->srch_inf.smallBuf)
- cifs_small_buf_release(buf);
- else
- cifs_buf_release(buf);
- }
-
- cifs_put_tlink(cfile->tlink);
- kfree(file->private_data);
- file->private_data = NULL;
- /* BB can we lock the filestruct while this is going on? */
- free_xid(xid);
- return rc;
-}
-
-static struct cifsLockInfo *
-cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 flags)
-{
- struct cifsLockInfo *lock =
- kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
- if (!lock)
- return lock;
- lock->offset = offset;
- lock->length = length;
- lock->type = type;
- lock->pid = current->tgid;
- lock->flags = flags;
- INIT_LIST_HEAD(&lock->blist);
- init_waitqueue_head(&lock->block_q);
- return lock;
-}
-
-void
-cifs_del_lock_waiters(struct cifsLockInfo *lock)
-{
- struct cifsLockInfo *li, *tmp;
- list_for_each_entry_safe(li, tmp, &lock->blist, blist) {
- list_del_init(&li->blist);
- wake_up(&li->block_q);
- }
-}
-
-#define CIFS_LOCK_OP 0
-#define CIFS_READ_OP 1
-#define CIFS_WRITE_OP 2
-
-/* @rw_check : 0 - no op, 1 - read, 2 - write */
-static bool
-cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset,
- __u64 length, __u8 type, __u16 flags,
- struct cifsFileInfo *cfile,
- struct cifsLockInfo **conf_lock, int rw_check)
-{
- struct cifsLockInfo *li;
- struct cifsFileInfo *cur_cfile = fdlocks->cfile;
- struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
-
- list_for_each_entry(li, &fdlocks->locks, llist) {
- if (offset + length <= li->offset ||
- offset >= li->offset + li->length)
- continue;
- if (rw_check != CIFS_LOCK_OP && current->tgid == li->pid &&
- server->ops->compare_fids(cfile, cur_cfile)) {
- /* shared lock prevents write op through the same fid */
- if (!(li->type & server->vals->shared_lock_type) ||
- rw_check != CIFS_WRITE_OP)
- continue;
- }
- if ((type & server->vals->shared_lock_type) &&
- ((server->ops->compare_fids(cfile, cur_cfile) &&
- current->tgid == li->pid) || type == li->type))
- continue;
- if (rw_check == CIFS_LOCK_OP &&
- (flags & FL_OFDLCK) && (li->flags & FL_OFDLCK) &&
- server->ops->compare_fids(cfile, cur_cfile))
- continue;
- if (conf_lock)
- *conf_lock = li;
- return true;
- }
- return false;
-}
-
-bool
-cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
- __u8 type, __u16 flags,
- struct cifsLockInfo **conf_lock, int rw_check)
-{
- bool rc = false;
- struct cifs_fid_locks *cur;
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
-
- list_for_each_entry(cur, &cinode->llist, llist) {
- rc = cifs_find_fid_lock_conflict(cur, offset, length, type,
- flags, cfile, conf_lock,
- rw_check);
- if (rc)
- break;
- }
-
- return rc;
-}
-
-/*
- * Check if there is another lock that prevents us to set the lock (mandatory
- * style). If such a lock exists, update the flock structure with its
- * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
- * or leave it the same if we can't. Returns 0 if we don't need to request to
- * the server or 1 otherwise.
- */
-static int
-cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
- __u8 type, struct file_lock *flock)
-{
- int rc = 0;
- struct cifsLockInfo *conf_lock;
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
- bool exist;
-
- down_read(&cinode->lock_sem);
-
- exist = cifs_find_lock_conflict(cfile, offset, length, type,
- flock->fl_flags, &conf_lock,
- CIFS_LOCK_OP);
- if (exist) {
- flock->fl_start = conf_lock->offset;
- flock->fl_end = conf_lock->offset + conf_lock->length - 1;
- flock->fl_pid = conf_lock->pid;
- if (conf_lock->type & server->vals->shared_lock_type)
- flock->fl_type = F_RDLCK;
- else
- flock->fl_type = F_WRLCK;
- } else if (!cinode->can_cache_brlcks)
- rc = 1;
- else
- flock->fl_type = F_UNLCK;
-
- up_read(&cinode->lock_sem);
- return rc;
-}
-
-static void
-cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
-{
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- cifs_down_write(&cinode->lock_sem);
- list_add_tail(&lock->llist, &cfile->llist->locks);
- up_write(&cinode->lock_sem);
-}
-
-/*
- * Set the byte-range lock (mandatory style). Returns:
- * 1) 0, if we set the lock and don't need to request to the server;
- * 2) 1, if no locks prevent us but we need to request to the server;
- * 3) -EACCES, if there is a lock that prevents us and wait is false.
- */
-static int
-cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
- bool wait)
-{
- struct cifsLockInfo *conf_lock;
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- bool exist;
- int rc = 0;
-
-try_again:
- exist = false;
- cifs_down_write(&cinode->lock_sem);
-
- exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
- lock->type, lock->flags, &conf_lock,
- CIFS_LOCK_OP);
- if (!exist && cinode->can_cache_brlcks) {
- list_add_tail(&lock->llist, &cfile->llist->locks);
- up_write(&cinode->lock_sem);
- return rc;
- }
-
- if (!exist)
- rc = 1;
- else if (!wait)
- rc = -EACCES;
- else {
- list_add_tail(&lock->blist, &conf_lock->blist);
- up_write(&cinode->lock_sem);
- rc = wait_event_interruptible(lock->block_q,
- (lock->blist.prev == &lock->blist) &&
- (lock->blist.next == &lock->blist));
- if (!rc)
- goto try_again;
- cifs_down_write(&cinode->lock_sem);
- list_del_init(&lock->blist);
- }
-
- up_write(&cinode->lock_sem);
- return rc;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-/*
- * Check if there is another lock that prevents us to set the lock (posix
- * style). If such a lock exists, update the flock structure with its
- * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
- * or leave it the same if we can't. Returns 0 if we don't need to request to
- * the server or 1 otherwise.
- */
-static int
-cifs_posix_lock_test(struct file *file, struct file_lock *flock)
-{
- int rc = 0;
- struct cifsInodeInfo *cinode = CIFS_I(file_inode(file));
- unsigned char saved_type = flock->fl_type;
-
- if ((flock->fl_flags & FL_POSIX) == 0)
- return 1;
-
- down_read(&cinode->lock_sem);
- posix_test_lock(file, flock);
-
- if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) {
- flock->fl_type = saved_type;
- rc = 1;
- }
-
- up_read(&cinode->lock_sem);
- return rc;
-}
-
-/*
- * Set the byte-range lock (posix style). Returns:
- * 1) <0, if the error occurs while setting the lock;
- * 2) 0, if we set the lock and don't need to request to the server;
- * 3) FILE_LOCK_DEFERRED, if we will wait for some other file_lock;
- * 4) FILE_LOCK_DEFERRED + 1, if we need to request to the server.
- */
-static int
-cifs_posix_lock_set(struct file *file, struct file_lock *flock)
-{
- struct cifsInodeInfo *cinode = CIFS_I(file_inode(file));
- int rc = FILE_LOCK_DEFERRED + 1;
-
- if ((flock->fl_flags & FL_POSIX) == 0)
- return rc;
-
- cifs_down_write(&cinode->lock_sem);
- if (!cinode->can_cache_brlcks) {
- up_write(&cinode->lock_sem);
- return rc;
- }
-
- rc = posix_lock_file(file, flock, NULL);
- up_write(&cinode->lock_sem);
- return rc;
-}
-
-int
-cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
-{
- unsigned int xid;
- int rc = 0, stored_rc;
- struct cifsLockInfo *li, *tmp;
- struct cifs_tcon *tcon;
- unsigned int num, max_num, max_buf;
- LOCKING_ANDX_RANGE *buf, *cur;
- static const int types[] = {
- LOCKING_ANDX_LARGE_FILES,
- LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES
- };
- int i;
-
- xid = get_xid();
- tcon = tlink_tcon(cfile->tlink);
-
- /*
- * Accessing maxBuf is racy with cifs_reconnect - need to store value
- * and check it before using.
- */
- max_buf = tcon->ses->server->maxBuf;
- if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) {
- free_xid(xid);
- return -EINVAL;
- }
-
- BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
- PAGE_SIZE);
- max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
- PAGE_SIZE);
- max_num = (max_buf - sizeof(struct smb_hdr)) /
- sizeof(LOCKING_ANDX_RANGE);
- buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
- if (!buf) {
- free_xid(xid);
- return -ENOMEM;
- }
-
- for (i = 0; i < 2; i++) {
- cur = buf;
- num = 0;
- list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
- if (li->type != types[i])
- continue;
- cur->Pid = cpu_to_le16(li->pid);
- cur->LengthLow = cpu_to_le32((u32)li->length);
- cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
- cur->OffsetLow = cpu_to_le32((u32)li->offset);
- cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
- if (++num == max_num) {
- stored_rc = cifs_lockv(xid, tcon,
- cfile->fid.netfid,
- (__u8)li->type, 0, num,
- buf);
- if (stored_rc)
- rc = stored_rc;
- cur = buf;
- num = 0;
- } else
- cur++;
- }
-
- if (num) {
- stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
- (__u8)types[i], 0, num, buf);
- if (stored_rc)
- rc = stored_rc;
- }
- }
-
- kfree(buf);
- free_xid(xid);
- return rc;
-}
-
-static __u32
-hash_lockowner(fl_owner_t owner)
-{
- return cifs_lock_secret ^ hash32_ptr((const void *)owner);
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-struct lock_to_push {
- struct list_head llist;
- __u64 offset;
- __u64 length;
- __u32 pid;
- __u16 netfid;
- __u8 type;
-};
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-static int
-cifs_push_posix_locks(struct cifsFileInfo *cfile)
-{
- struct inode *inode = d_inode(cfile->dentry);
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- struct file_lock *flock;
- struct file_lock_context *flctx = inode->i_flctx;
- unsigned int count = 0, i;
- int rc = 0, xid, type;
- struct list_head locks_to_send, *el;
- struct lock_to_push *lck, *tmp;
- __u64 length;
-
- xid = get_xid();
-
- if (!flctx)
- goto out;
-
- spin_lock(&flctx->flc_lock);
- list_for_each(el, &flctx->flc_posix) {
- count++;
- }
- spin_unlock(&flctx->flc_lock);
-
- INIT_LIST_HEAD(&locks_to_send);
-
- /*
- * Allocating count locks is enough because no FL_POSIX locks can be
- * added to the list while we are holding cinode->lock_sem that
- * protects locking operations of this inode.
- */
- for (i = 0; i < count; i++) {
- lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
- if (!lck) {
- rc = -ENOMEM;
- goto err_out;
- }
- list_add_tail(&lck->llist, &locks_to_send);
- }
-
- el = locks_to_send.next;
- spin_lock(&flctx->flc_lock);
- list_for_each_entry(flock, &flctx->flc_posix, fl_list) {
- if (el == &locks_to_send) {
- /*
- * The list ended. We don't have enough allocated
- * structures - something is really wrong.
- */
- cifs_dbg(VFS, "Can't push all brlocks!\n");
- break;
- }
- length = cifs_flock_len(flock);
- if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
- type = CIFS_RDLCK;
- else
- type = CIFS_WRLCK;
- lck = list_entry(el, struct lock_to_push, llist);
- lck->pid = hash_lockowner(flock->fl_owner);
- lck->netfid = cfile->fid.netfid;
- lck->length = length;
- lck->type = type;
- lck->offset = flock->fl_start;
- }
- spin_unlock(&flctx->flc_lock);
-
- list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
- int stored_rc;
-
- stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid,
- lck->offset, lck->length, NULL,
- lck->type, 0);
- if (stored_rc)
- rc = stored_rc;
- list_del(&lck->llist);
- kfree(lck);
- }
-
-out:
- free_xid(xid);
- return rc;
-err_out:
- list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
- list_del(&lck->llist);
- kfree(lck);
- }
- goto out;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-static int
-cifs_push_locks(struct cifsFileInfo *cfile)
-{
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- int rc = 0;
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- /* we are going to update can_cache_brlcks here - need a write access */
- cifs_down_write(&cinode->lock_sem);
- if (!cinode->can_cache_brlcks) {
- up_write(&cinode->lock_sem);
- return rc;
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (cap_unix(tcon->ses) &&
- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
- ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
- rc = cifs_push_posix_locks(cfile);
- else
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- rc = tcon->ses->server->ops->push_mand_locks(cfile);
-
- cinode->can_cache_brlcks = false;
- up_write(&cinode->lock_sem);
- return rc;
-}
-
-static void
-cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
- bool *wait_flag, struct TCP_Server_Info *server)
-{
- if (flock->fl_flags & FL_POSIX)
- cifs_dbg(FYI, "Posix\n");
- if (flock->fl_flags & FL_FLOCK)
- cifs_dbg(FYI, "Flock\n");
- if (flock->fl_flags & FL_SLEEP) {
- cifs_dbg(FYI, "Blocking lock\n");
- *wait_flag = true;
- }
- if (flock->fl_flags & FL_ACCESS)
- cifs_dbg(FYI, "Process suspended by mandatory locking - not implemented yet\n");
- if (flock->fl_flags & FL_LEASE)
- cifs_dbg(FYI, "Lease on file - not implemented yet\n");
- if (flock->fl_flags &
- (~(FL_POSIX | FL_FLOCK | FL_SLEEP |
- FL_ACCESS | FL_LEASE | FL_CLOSE | FL_OFDLCK)))
- cifs_dbg(FYI, "Unknown lock flags 0x%x\n", flock->fl_flags);
-
- *type = server->vals->large_lock_type;
- if (flock->fl_type == F_WRLCK) {
- cifs_dbg(FYI, "F_WRLCK\n");
- *type |= server->vals->exclusive_lock_type;
- *lock = 1;
- } else if (flock->fl_type == F_UNLCK) {
- cifs_dbg(FYI, "F_UNLCK\n");
- *type |= server->vals->unlock_lock_type;
- *unlock = 1;
- /* Check if unlock includes more than one lock range */
- } else if (flock->fl_type == F_RDLCK) {
- cifs_dbg(FYI, "F_RDLCK\n");
- *type |= server->vals->shared_lock_type;
- *lock = 1;
- } else if (flock->fl_type == F_EXLCK) {
- cifs_dbg(FYI, "F_EXLCK\n");
- *type |= server->vals->exclusive_lock_type;
- *lock = 1;
- } else if (flock->fl_type == F_SHLCK) {
- cifs_dbg(FYI, "F_SHLCK\n");
- *type |= server->vals->shared_lock_type;
- *lock = 1;
- } else
- cifs_dbg(FYI, "Unknown type of lock\n");
-}
-
-static int
-cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
- bool wait_flag, bool posix_lck, unsigned int xid)
-{
- int rc = 0;
- __u64 length = cifs_flock_len(flock);
- struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- struct TCP_Server_Info *server = tcon->ses->server;
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- __u16 netfid = cfile->fid.netfid;
-
- if (posix_lck) {
- int posix_lock_type;
-
- rc = cifs_posix_lock_test(file, flock);
- if (!rc)
- return rc;
-
- if (type & server->vals->shared_lock_type)
- posix_lock_type = CIFS_RDLCK;
- else
- posix_lock_type = CIFS_WRLCK;
- rc = CIFSSMBPosixLock(xid, tcon, netfid,
- hash_lockowner(flock->fl_owner),
- flock->fl_start, length, flock,
- posix_lock_type, wait_flag);
- return rc;
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock);
- if (!rc)
- return rc;
-
- /* BB we could chain these into one lock request BB */
- rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, type,
- 1, 0, false);
- if (rc == 0) {
- rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
- type, 0, 1, false);
- flock->fl_type = F_UNLCK;
- if (rc != 0)
- cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n",
- rc);
- return 0;
- }
-
- if (type & server->vals->shared_lock_type) {
- flock->fl_type = F_WRLCK;
- return 0;
- }
-
- type &= ~server->vals->exclusive_lock_type;
-
- rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
- type | server->vals->shared_lock_type,
- 1, 0, false);
- if (rc == 0) {
- rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
- type | server->vals->shared_lock_type, 0, 1, false);
- flock->fl_type = F_RDLCK;
- if (rc != 0)
- cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n",
- rc);
- } else
- flock->fl_type = F_WRLCK;
-
- return 0;
-}
-
-void
-cifs_move_llist(struct list_head *source, struct list_head *dest)
-{
- struct list_head *li, *tmp;
- list_for_each_safe(li, tmp, source)
- list_move(li, dest);
-}
-
-void
-cifs_free_llist(struct list_head *llist)
-{
- struct cifsLockInfo *li, *tmp;
- list_for_each_entry_safe(li, tmp, llist, llist) {
- cifs_del_lock_waiters(li);
- list_del(&li->llist);
- kfree(li);
- }
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-int
-cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
- unsigned int xid)
-{
- int rc = 0, stored_rc;
- static const int types[] = {
- LOCKING_ANDX_LARGE_FILES,
- LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES
- };
- unsigned int i;
- unsigned int max_num, num, max_buf;
- LOCKING_ANDX_RANGE *buf, *cur;
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- struct cifsLockInfo *li, *tmp;
- __u64 length = cifs_flock_len(flock);
- struct list_head tmp_llist;
-
- INIT_LIST_HEAD(&tmp_llist);
-
- /*
- * Accessing maxBuf is racy with cifs_reconnect - need to store value
- * and check it before using.
- */
- max_buf = tcon->ses->server->maxBuf;
- if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE)))
- return -EINVAL;
-
- BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
- PAGE_SIZE);
- max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
- PAGE_SIZE);
- max_num = (max_buf - sizeof(struct smb_hdr)) /
- sizeof(LOCKING_ANDX_RANGE);
- buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- cifs_down_write(&cinode->lock_sem);
- for (i = 0; i < 2; i++) {
- cur = buf;
- num = 0;
- list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
- if (flock->fl_start > li->offset ||
- (flock->fl_start + length) <
- (li->offset + li->length))
- continue;
- if (current->tgid != li->pid)
- continue;
- if (types[i] != li->type)
- continue;
- if (cinode->can_cache_brlcks) {
- /*
- * We can cache brlock requests - simply remove
- * a lock from the file's list.
- */
- list_del(&li->llist);
- cifs_del_lock_waiters(li);
- kfree(li);
- continue;
- }
- cur->Pid = cpu_to_le16(li->pid);
- cur->LengthLow = cpu_to_le32((u32)li->length);
- cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
- cur->OffsetLow = cpu_to_le32((u32)li->offset);
- cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
- /*
- * We need to save a lock here to let us add it again to
- * the file's list if the unlock range request fails on
- * the server.
- */
- list_move(&li->llist, &tmp_llist);
- if (++num == max_num) {
- stored_rc = cifs_lockv(xid, tcon,
- cfile->fid.netfid,
- li->type, num, 0, buf);
- if (stored_rc) {
- /*
- * We failed on the unlock range
- * request - add all locks from the tmp
- * list to the head of the file's list.
- */
- cifs_move_llist(&tmp_llist,
- &cfile->llist->locks);
- rc = stored_rc;
- } else
- /*
- * The unlock range request succeed -
- * free the tmp list.
- */
- cifs_free_llist(&tmp_llist);
- cur = buf;
- num = 0;
- } else
- cur++;
- }
- if (num) {
- stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
- types[i], num, 0, buf);
- if (stored_rc) {
- cifs_move_llist(&tmp_llist,
- &cfile->llist->locks);
- rc = stored_rc;
- } else
- cifs_free_llist(&tmp_llist);
- }
- }
-
- up_write(&cinode->lock_sem);
- kfree(buf);
- return rc;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-static int
-cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
- bool wait_flag, bool posix_lck, int lock, int unlock,
- unsigned int xid)
-{
- int rc = 0;
- __u64 length = cifs_flock_len(flock);
- struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- struct TCP_Server_Info *server = tcon->ses->server;
- struct inode *inode = d_inode(cfile->dentry);
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (posix_lck) {
- int posix_lock_type;
-
- rc = cifs_posix_lock_set(file, flock);
- if (rc <= FILE_LOCK_DEFERRED)
- return rc;
-
- if (type & server->vals->shared_lock_type)
- posix_lock_type = CIFS_RDLCK;
- else
- posix_lock_type = CIFS_WRLCK;
-
- if (unlock == 1)
- posix_lock_type = CIFS_UNLCK;
-
- rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid,
- hash_lockowner(flock->fl_owner),
- flock->fl_start, length,
- NULL, posix_lock_type, wait_flag);
- goto out;
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- if (lock) {
- struct cifsLockInfo *lock;
-
- lock = cifs_lock_init(flock->fl_start, length, type,
- flock->fl_flags);
- if (!lock)
- return -ENOMEM;
-
- rc = cifs_lock_add_if(cfile, lock, wait_flag);
- if (rc < 0) {
- kfree(lock);
- return rc;
- }
- if (!rc)
- goto out;
-
- /*
- * Windows 7 server can delay breaking lease from read to None
- * if we set a byte-range lock on a file - break it explicitly
- * before sending the lock to the server to be sure the next
- * read won't conflict with non-overlapted locks due to
- * pagereading.
- */
- if (!CIFS_CACHE_WRITE(CIFS_I(inode)) &&
- CIFS_CACHE_READ(CIFS_I(inode))) {
- cifs_zap_mapping(inode);
- cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n",
- inode);
- CIFS_I(inode)->oplock = 0;
- }
-
- rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
- type, 1, 0, wait_flag);
- if (rc) {
- kfree(lock);
- return rc;
- }
-
- cifs_lock_add(cfile, lock);
- } else if (unlock)
- rc = server->ops->mand_unlock_range(cfile, flock, xid);
-
-out:
- if ((flock->fl_flags & FL_POSIX) || (flock->fl_flags & FL_FLOCK)) {
- /*
- * If this is a request to remove all locks because we
- * are closing the file, it doesn't matter if the
- * unlocking failed as both cifs.ko and the SMB server
- * remove the lock on file close
- */
- if (rc) {
- cifs_dbg(VFS, "%s failed rc=%d\n", __func__, rc);
- if (!(flock->fl_flags & FL_CLOSE))
- return rc;
- }
- rc = locks_lock_file_wait(file, flock);
- }
- return rc;
-}
-
-int cifs_flock(struct file *file, int cmd, struct file_lock *fl)
-{
- int rc, xid;
- int lock = 0, unlock = 0;
- bool wait_flag = false;
- bool posix_lck = false;
- struct cifs_sb_info *cifs_sb;
- struct cifs_tcon *tcon;
- struct cifsFileInfo *cfile;
- __u32 type;
-
- xid = get_xid();
-
- if (!(fl->fl_flags & FL_FLOCK)) {
- rc = -ENOLCK;
- free_xid(xid);
- return rc;
- }
-
- cfile = (struct cifsFileInfo *)file->private_data;
- tcon = tlink_tcon(cfile->tlink);
-
- cifs_read_flock(fl, &type, &lock, &unlock, &wait_flag,
- tcon->ses->server);
- cifs_sb = CIFS_FILE_SB(file);
-
- if (cap_unix(tcon->ses) &&
- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
- ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
- posix_lck = true;
-
- if (!lock && !unlock) {
- /*
- * if no lock or unlock then nothing to do since we do not
- * know what it is
- */
- rc = -EOPNOTSUPP;
- free_xid(xid);
- return rc;
- }
-
- rc = cifs_setlk(file, fl, type, wait_flag, posix_lck, lock, unlock,
- xid);
- free_xid(xid);
- return rc;
-
-
-}
-
-int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
-{
- int rc, xid;
- int lock = 0, unlock = 0;
- bool wait_flag = false;
- bool posix_lck = false;
- struct cifs_sb_info *cifs_sb;
- struct cifs_tcon *tcon;
- struct cifsFileInfo *cfile;
- __u32 type;
-
- rc = -EACCES;
- xid = get_xid();
-
- cifs_dbg(FYI, "%s: %pD2 cmd=0x%x type=0x%x flags=0x%x r=%lld:%lld\n", __func__, file, cmd,
- flock->fl_flags, flock->fl_type, (long long)flock->fl_start,
- (long long)flock->fl_end);
-
- cfile = (struct cifsFileInfo *)file->private_data;
- tcon = tlink_tcon(cfile->tlink);
-
- cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
- tcon->ses->server);
- cifs_sb = CIFS_FILE_SB(file);
- set_bit(CIFS_INO_CLOSE_ON_LOCK, &CIFS_I(d_inode(cfile->dentry))->flags);
-
- if (cap_unix(tcon->ses) &&
- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
- ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
- posix_lck = true;
- /*
- * BB add code here to normalize offset and length to account for
- * negative length which we can not accept over the wire.
- */
- if (IS_GETLK(cmd)) {
- rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid);
- free_xid(xid);
- return rc;
- }
-
- if (!lock && !unlock) {
- /*
- * if no lock or unlock then nothing to do since we do not
- * know what it is
- */
- free_xid(xid);
- return -EOPNOTSUPP;
- }
-
- rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
- xid);
- free_xid(xid);
- return rc;
-}
-
-/*
- * update the file size (if needed) after a write. Should be called with
- * the inode->i_lock held
- */
-void
-cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
- unsigned int bytes_written)
-{
- loff_t end_of_write = offset + bytes_written;
-
- if (end_of_write > cifsi->server_eof)
- cifsi->server_eof = end_of_write;
-}
-
-static ssize_t
-cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
- size_t write_size, loff_t *offset)
-{
- int rc = 0;
- unsigned int bytes_written = 0;
- unsigned int total_written;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- unsigned int xid;
- struct dentry *dentry = open_file->dentry;
- struct cifsInodeInfo *cifsi = CIFS_I(d_inode(dentry));
- struct cifs_io_parms io_parms = {0};
-
- cifs_dbg(FYI, "write %zd bytes to offset %lld of %pd\n",
- write_size, *offset, dentry);
-
- tcon = tlink_tcon(open_file->tlink);
- server = tcon->ses->server;
-
- if (!server->ops->sync_write)
- return -ENOSYS;
-
- xid = get_xid();
-
- for (total_written = 0; write_size > total_written;
- total_written += bytes_written) {
- rc = -EAGAIN;
- while (rc == -EAGAIN) {
- struct kvec iov[2];
- unsigned int len;
-
- if (open_file->invalidHandle) {
- /* we could deadlock if we called
- filemap_fdatawait from here so tell
- reopen_file not to flush data to
- server now */
- rc = cifs_reopen_file(open_file, false);
- if (rc != 0)
- break;
- }
-
- len = min(server->ops->wp_retry_size(d_inode(dentry)),
- (unsigned int)write_size - total_written);
- /* iov[0] is reserved for smb header */
- iov[1].iov_base = (char *)write_data + total_written;
- iov[1].iov_len = len;
- io_parms.pid = pid;
- io_parms.tcon = tcon;
- io_parms.offset = *offset;
- io_parms.length = len;
- rc = server->ops->sync_write(xid, &open_file->fid,
- &io_parms, &bytes_written, iov, 1);
- }
- if (rc || (bytes_written == 0)) {
- if (total_written)
- break;
- else {
- free_xid(xid);
- return rc;
- }
- } else {
- spin_lock(&d_inode(dentry)->i_lock);
- cifs_update_eof(cifsi, *offset, bytes_written);
- spin_unlock(&d_inode(dentry)->i_lock);
- *offset += bytes_written;
- }
- }
-
- cifs_stats_bytes_written(tcon, total_written);
-
- if (total_written > 0) {
- spin_lock(&d_inode(dentry)->i_lock);
- if (*offset > d_inode(dentry)->i_size) {
- i_size_write(d_inode(dentry), *offset);
- d_inode(dentry)->i_blocks = (512 - 1 + *offset) >> 9;
- }
- spin_unlock(&d_inode(dentry)->i_lock);
- }
- mark_inode_dirty_sync(d_inode(dentry));
- free_xid(xid);
- return total_written;
-}
-
-struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
- bool fsuid_only)
-{
- struct cifsFileInfo *open_file = NULL;
- struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb);
-
- /* only filter by fsuid on multiuser mounts */
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
- fsuid_only = false;
-
- spin_lock(&cifs_inode->open_file_lock);
- /* we could simply get the first_list_entry since write-only entries
- are always at the end of the list but since the first entry might
- have a close pending, we go through the whole list */
- list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
- if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
- continue;
- if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
- if ((!open_file->invalidHandle)) {
- /* found a good file */
- /* lock it so it will not be closed on us */
- cifsFileInfo_get(open_file);
- spin_unlock(&cifs_inode->open_file_lock);
- return open_file;
- } /* else might as well continue, and look for
- another, or simply have the caller reopen it
- again rather than trying to fix this handle */
- } else /* write only file */
- break; /* write only files are last so must be done */
- }
- spin_unlock(&cifs_inode->open_file_lock);
- return NULL;
-}
-
-/* Return -EBADF if no handle is found and general rc otherwise */
-int
-cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
- struct cifsFileInfo **ret_file)
-{
- struct cifsFileInfo *open_file, *inv_file = NULL;
- struct cifs_sb_info *cifs_sb;
- bool any_available = false;
- int rc = -EBADF;
- unsigned int refind = 0;
- bool fsuid_only = flags & FIND_WR_FSUID_ONLY;
- bool with_delete = flags & FIND_WR_WITH_DELETE;
- *ret_file = NULL;
-
- /*
- * Having a null inode here (because mapping->host was set to zero by
- * the VFS or MM) should not happen but we had reports of on oops (due
- * to it being zero) during stress testcases so we need to check for it
- */
-
- if (cifs_inode == NULL) {
- cifs_dbg(VFS, "Null inode passed to cifs_writeable_file\n");
- dump_stack();
- return rc;
- }
-
- cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb);
-
- /* only filter by fsuid on multiuser mounts */
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
- fsuid_only = false;
-
- spin_lock(&cifs_inode->open_file_lock);
-refind_writable:
- if (refind > MAX_REOPEN_ATT) {
- spin_unlock(&cifs_inode->open_file_lock);
- return rc;
- }
- list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
- if (!any_available && open_file->pid != current->tgid)
- continue;
- if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
- continue;
- if (with_delete && !(open_file->fid.access & DELETE))
- continue;
- if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
- if (!open_file->invalidHandle) {
- /* found a good writable file */
- cifsFileInfo_get(open_file);
- spin_unlock(&cifs_inode->open_file_lock);
- *ret_file = open_file;
- return 0;
- } else {
- if (!inv_file)
- inv_file = open_file;
- }
- }
- }
- /* couldn't find useable FH with same pid, try any available */
- if (!any_available) {
- any_available = true;
- goto refind_writable;
- }
-
- if (inv_file) {
- any_available = false;
- cifsFileInfo_get(inv_file);
- }
-
- spin_unlock(&cifs_inode->open_file_lock);
-
- if (inv_file) {
- rc = cifs_reopen_file(inv_file, false);
- if (!rc) {
- *ret_file = inv_file;
- return 0;
- }
-
- spin_lock(&cifs_inode->open_file_lock);
- list_move_tail(&inv_file->flist, &cifs_inode->openFileList);
- spin_unlock(&cifs_inode->open_file_lock);
- cifsFileInfo_put(inv_file);
- ++refind;
- inv_file = NULL;
- spin_lock(&cifs_inode->open_file_lock);
- goto refind_writable;
- }
-
- return rc;
-}
-
-struct cifsFileInfo *
-find_writable_file(struct cifsInodeInfo *cifs_inode, int flags)
-{
- struct cifsFileInfo *cfile;
- int rc;
-
- rc = cifs_get_writable_file(cifs_inode, flags, &cfile);
- if (rc)
- cifs_dbg(FYI, "Couldn't find writable handle rc=%d\n", rc);
-
- return cfile;
-}
-
-int
-cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
- int flags,
- struct cifsFileInfo **ret_file)
-{
- struct cifsFileInfo *cfile;
- void *page = alloc_dentry_path();
-
- *ret_file = NULL;
-
- spin_lock(&tcon->open_file_lock);
- list_for_each_entry(cfile, &tcon->openFileList, tlist) {
- struct cifsInodeInfo *cinode;
- const char *full_path = build_path_from_dentry(cfile->dentry, page);
- if (IS_ERR(full_path)) {
- spin_unlock(&tcon->open_file_lock);
- free_dentry_path(page);
- return PTR_ERR(full_path);
- }
- if (strcmp(full_path, name))
- continue;
-
- cinode = CIFS_I(d_inode(cfile->dentry));
- spin_unlock(&tcon->open_file_lock);
- free_dentry_path(page);
- return cifs_get_writable_file(cinode, flags, ret_file);
- }
-
- spin_unlock(&tcon->open_file_lock);
- free_dentry_path(page);
- return -ENOENT;
-}
-
-int
-cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
- struct cifsFileInfo **ret_file)
-{
- struct cifsFileInfo *cfile;
- void *page = alloc_dentry_path();
-
- *ret_file = NULL;
-
- spin_lock(&tcon->open_file_lock);
- list_for_each_entry(cfile, &tcon->openFileList, tlist) {
- struct cifsInodeInfo *cinode;
- const char *full_path = build_path_from_dentry(cfile->dentry, page);
- if (IS_ERR(full_path)) {
- spin_unlock(&tcon->open_file_lock);
- free_dentry_path(page);
- return PTR_ERR(full_path);
- }
- if (strcmp(full_path, name))
- continue;
-
- cinode = CIFS_I(d_inode(cfile->dentry));
- spin_unlock(&tcon->open_file_lock);
- free_dentry_path(page);
- *ret_file = find_readable_file(cinode, 0);
- return *ret_file ? 0 : -ENOENT;
- }
-
- spin_unlock(&tcon->open_file_lock);
- free_dentry_path(page);
- return -ENOENT;
-}
-
-void
-cifs_writedata_release(struct kref *refcount)
-{
- struct cifs_writedata *wdata = container_of(refcount,
- struct cifs_writedata, refcount);
-#ifdef CONFIG_CIFS_SMB_DIRECT
- if (wdata->mr) {
- smbd_deregister_mr(wdata->mr);
- wdata->mr = NULL;
- }
-#endif
-
- if (wdata->cfile)
- cifsFileInfo_put(wdata->cfile);
-
- kvfree(wdata->pages);
- kfree(wdata);
-}
-
-/*
- * Write failed with a retryable error. Resend the write request. It's also
- * possible that the page was redirtied so re-clean the page.
- */
-static void
-cifs_writev_requeue(struct cifs_writedata *wdata)
-{
- int i, rc = 0;
- struct inode *inode = d_inode(wdata->cfile->dentry);
- struct TCP_Server_Info *server;
- unsigned int rest_len;
-
- server = tlink_tcon(wdata->cfile->tlink)->ses->server;
- i = 0;
- rest_len = wdata->bytes;
- do {
- struct cifs_writedata *wdata2;
- unsigned int j, nr_pages, wsize, tailsz, cur_len;
-
- wsize = server->ops->wp_retry_size(inode);
- if (wsize < rest_len) {
- nr_pages = wsize / PAGE_SIZE;
- if (!nr_pages) {
- rc = -EOPNOTSUPP;
- break;
- }
- cur_len = nr_pages * PAGE_SIZE;
- tailsz = PAGE_SIZE;
- } else {
- nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
- cur_len = rest_len;
- tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
- }
-
- wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
- if (!wdata2) {
- rc = -ENOMEM;
- break;
- }
-
- for (j = 0; j < nr_pages; j++) {
- wdata2->pages[j] = wdata->pages[i + j];
- lock_page(wdata2->pages[j]);
- clear_page_dirty_for_io(wdata2->pages[j]);
- }
-
- wdata2->sync_mode = wdata->sync_mode;
- wdata2->nr_pages = nr_pages;
- wdata2->offset = page_offset(wdata2->pages[0]);
- wdata2->pagesz = PAGE_SIZE;
- wdata2->tailsz = tailsz;
- wdata2->bytes = cur_len;
-
- rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY,
- &wdata2->cfile);
- if (!wdata2->cfile) {
- cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n",
- rc);
- if (!is_retryable_error(rc))
- rc = -EBADF;
- } else {
- wdata2->pid = wdata2->cfile->pid;
- rc = server->ops->async_writev(wdata2,
- cifs_writedata_release);
- }
-
- for (j = 0; j < nr_pages; j++) {
- unlock_page(wdata2->pages[j]);
- if (rc != 0 && !is_retryable_error(rc)) {
- SetPageError(wdata2->pages[j]);
- end_page_writeback(wdata2->pages[j]);
- put_page(wdata2->pages[j]);
- }
- }
-
- kref_put(&wdata2->refcount, cifs_writedata_release);
- if (rc) {
- if (is_retryable_error(rc))
- continue;
- i += nr_pages;
- break;
- }
-
- rest_len -= cur_len;
- i += nr_pages;
- } while (i < wdata->nr_pages);
-
- /* cleanup remaining pages from the original wdata */
- for (; i < wdata->nr_pages; i++) {
- SetPageError(wdata->pages[i]);
- end_page_writeback(wdata->pages[i]);
- put_page(wdata->pages[i]);
- }
-
- if (rc != 0 && !is_retryable_error(rc))
- mapping_set_error(inode->i_mapping, rc);
- kref_put(&wdata->refcount, cifs_writedata_release);
-}
-
-void
-cifs_writev_complete(struct work_struct *work)
-{
- struct cifs_writedata *wdata = container_of(work,
- struct cifs_writedata, work);
- struct inode *inode = d_inode(wdata->cfile->dentry);
- int i = 0;
-
- if (wdata->result == 0) {
- spin_lock(&inode->i_lock);
- cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
- spin_unlock(&inode->i_lock);
- cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
- wdata->bytes);
- } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
- return cifs_writev_requeue(wdata);
-
- for (i = 0; i < wdata->nr_pages; i++) {
- struct page *page = wdata->pages[i];
-
- if (wdata->result == -EAGAIN)
- __set_page_dirty_nobuffers(page);
- else if (wdata->result < 0)
- SetPageError(page);
- end_page_writeback(page);
- cifs_readpage_to_fscache(inode, page);
- put_page(page);
- }
- if (wdata->result != -EAGAIN)
- mapping_set_error(inode->i_mapping, wdata->result);
- kref_put(&wdata->refcount, cifs_writedata_release);
-}
-
-struct cifs_writedata *
-cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
-{
- struct cifs_writedata *writedata = NULL;
- struct page **pages =
- kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
- if (pages) {
- writedata = cifs_writedata_direct_alloc(pages, complete);
- if (!writedata)
- kvfree(pages);
- }
-
- return writedata;
-}
-
-struct cifs_writedata *
-cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
-{
- struct cifs_writedata *wdata;
-
- wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
- if (wdata != NULL) {
- wdata->pages = pages;
- kref_init(&wdata->refcount);
- INIT_LIST_HEAD(&wdata->list);
- init_completion(&wdata->done);
- INIT_WORK(&wdata->work, complete);
- }
- return wdata;
-}
-
-
-static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
-{
- struct address_space *mapping = page->mapping;
- loff_t offset = (loff_t)page->index << PAGE_SHIFT;
- char *write_data;
- int rc = -EFAULT;
- int bytes_written = 0;
- struct inode *inode;
- struct cifsFileInfo *open_file;
-
- if (!mapping || !mapping->host)
- return -EFAULT;
-
- inode = page->mapping->host;
-
- offset += (loff_t)from;
- write_data = kmap(page);
- write_data += from;
-
- if ((to > PAGE_SIZE) || (from > to)) {
- kunmap(page);
- return -EIO;
- }
-
- /* racing with truncate? */
- if (offset > mapping->host->i_size) {
- kunmap(page);
- return 0; /* don't care */
- }
-
- /* check to make sure that we are not extending the file */
- if (mapping->host->i_size - offset < (loff_t)to)
- to = (unsigned)(mapping->host->i_size - offset);
-
- rc = cifs_get_writable_file(CIFS_I(mapping->host), FIND_WR_ANY,
- &open_file);
- if (!rc) {
- bytes_written = cifs_write(open_file, open_file->pid,
- write_data, to - from, &offset);
- cifsFileInfo_put(open_file);
- /* Does mm or vfs already set times? */
- inode->i_atime = inode->i_mtime = current_time(inode);
- if ((bytes_written > 0) && (offset))
- rc = 0;
- else if (bytes_written < 0)
- rc = bytes_written;
- else
- rc = -EFAULT;
- } else {
- cifs_dbg(FYI, "No writable handle for write page rc=%d\n", rc);
- if (!is_retryable_error(rc))
- rc = -EIO;
- }
-
- kunmap(page);
- return rc;
-}
-
-static struct cifs_writedata *
-wdata_alloc_and_fillpages(pgoff_t tofind, struct address_space *mapping,
- pgoff_t end, pgoff_t *index,
- unsigned int *found_pages)
-{
- struct cifs_writedata *wdata;
-
- wdata = cifs_writedata_alloc((unsigned int)tofind,
- cifs_writev_complete);
- if (!wdata)
- return NULL;
-
- *found_pages = find_get_pages_range_tag(mapping, index, end,
- PAGECACHE_TAG_DIRTY, tofind, wdata->pages);
- return wdata;
-}
-
-static unsigned int
-wdata_prepare_pages(struct cifs_writedata *wdata, unsigned int found_pages,
- struct address_space *mapping,
- struct writeback_control *wbc,
- pgoff_t end, pgoff_t *index, pgoff_t *next, bool *done)
-{
- unsigned int nr_pages = 0, i;
- struct page *page;
-
- for (i = 0; i < found_pages; i++) {
- page = wdata->pages[i];
- /*
- * At this point we hold neither the i_pages lock nor the
- * page lock: the page may be truncated or invalidated
- * (changing page->mapping to NULL), or even swizzled
- * back from swapper_space to tmpfs file mapping
- */
-
- if (nr_pages == 0)
- lock_page(page);
- else if (!trylock_page(page))
- break;
-
- if (unlikely(page->mapping != mapping)) {
- unlock_page(page);
- break;
- }
-
- if (!wbc->range_cyclic && page->index > end) {
- *done = true;
- unlock_page(page);
- break;
- }
-
- if (*next && (page->index != *next)) {
- /* Not next consecutive page */
- unlock_page(page);
- break;
- }
-
- if (wbc->sync_mode != WB_SYNC_NONE)
- wait_on_page_writeback(page);
-
- if (PageWriteback(page) ||
- !clear_page_dirty_for_io(page)) {
- unlock_page(page);
- break;
- }
-
- /*
- * This actually clears the dirty bit in the radix tree.
- * See cifs_writepage() for more commentary.
- */
- set_page_writeback(page);
- if (page_offset(page) >= i_size_read(mapping->host)) {
- *done = true;
- unlock_page(page);
- end_page_writeback(page);
- break;
- }
-
- wdata->pages[i] = page;
- *next = page->index + 1;
- ++nr_pages;
- }
-
- /* reset index to refind any pages skipped */
- if (nr_pages == 0)
- *index = wdata->pages[0]->index + 1;
-
- /* put any pages we aren't going to use */
- for (i = nr_pages; i < found_pages; i++) {
- put_page(wdata->pages[i]);
- wdata->pages[i] = NULL;
- }
-
- return nr_pages;
-}
-
-static int
-wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages,
- struct address_space *mapping, struct writeback_control *wbc)
-{
- int rc;
-
- wdata->sync_mode = wbc->sync_mode;
- wdata->nr_pages = nr_pages;
- wdata->offset = page_offset(wdata->pages[0]);
- wdata->pagesz = PAGE_SIZE;
- wdata->tailsz = min(i_size_read(mapping->host) -
- page_offset(wdata->pages[nr_pages - 1]),
- (loff_t)PAGE_SIZE);
- wdata->bytes = ((nr_pages - 1) * PAGE_SIZE) + wdata->tailsz;
- wdata->pid = wdata->cfile->pid;
-
- rc = adjust_credits(wdata->server, &wdata->credits, wdata->bytes);
- if (rc)
- return rc;
-
- if (wdata->cfile->invalidHandle)
- rc = -EAGAIN;
- else
- rc = wdata->server->ops->async_writev(wdata,
- cifs_writedata_release);
-
- return rc;
-}
-
-static int cifs_writepages(struct address_space *mapping,
- struct writeback_control *wbc)
-{
- struct inode *inode = mapping->host;
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct TCP_Server_Info *server;
- bool done = false, scanned = false, range_whole = false;
- pgoff_t end, index;
- struct cifs_writedata *wdata;
- struct cifsFileInfo *cfile = NULL;
- int rc = 0;
- int saved_rc = 0;
- unsigned int xid;
-
- /*
- * If wsize is smaller than the page cache size, default to writing
- * one page at a time via cifs_writepage
- */
- if (cifs_sb->ctx->wsize < PAGE_SIZE)
- return generic_writepages(mapping, wbc);
-
- xid = get_xid();
- if (wbc->range_cyclic) {
- index = mapping->writeback_index; /* Start from prev offset */
- end = -1;
- } else {
- index = wbc->range_start >> PAGE_SHIFT;
- end = wbc->range_end >> PAGE_SHIFT;
- if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
- range_whole = true;
- scanned = true;
- }
- server = cifs_pick_channel(cifs_sb_master_tcon(cifs_sb)->ses);
-
-retry:
- while (!done && index <= end) {
- unsigned int i, nr_pages, found_pages, wsize;
- pgoff_t next = 0, tofind, saved_index = index;
- struct cifs_credits credits_on_stack;
- struct cifs_credits *credits = &credits_on_stack;
- int get_file_rc = 0;
-
- if (cfile)
- cifsFileInfo_put(cfile);
-
- rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile);
-
- /* in case of an error store it to return later */
- if (rc)
- get_file_rc = rc;
-
- rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->wsize,
- &wsize, credits);
- if (rc != 0) {
- done = true;
- break;
- }
-
- tofind = min((wsize / PAGE_SIZE) - 1, end - index) + 1;
-
- wdata = wdata_alloc_and_fillpages(tofind, mapping, end, &index,
- &found_pages);
- if (!wdata) {
- rc = -ENOMEM;
- done = true;
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
-
- if (found_pages == 0) {
- kref_put(&wdata->refcount, cifs_writedata_release);
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
-
- nr_pages = wdata_prepare_pages(wdata, found_pages, mapping, wbc,
- end, &index, &next, &done);
-
- /* nothing to write? */
- if (nr_pages == 0) {
- kref_put(&wdata->refcount, cifs_writedata_release);
- add_credits_and_wake_if(server, credits, 0);
- continue;
- }
-
- wdata->credits = credits_on_stack;
- wdata->cfile = cfile;
- wdata->server = server;
- cfile = NULL;
-
- if (!wdata->cfile) {
- cifs_dbg(VFS, "No writable handle in writepages rc=%d\n",
- get_file_rc);
- if (is_retryable_error(get_file_rc))
- rc = get_file_rc;
- else
- rc = -EBADF;
- } else
- rc = wdata_send_pages(wdata, nr_pages, mapping, wbc);
-
- for (i = 0; i < nr_pages; ++i)
- unlock_page(wdata->pages[i]);
-
- /* send failure -- clean up the mess */
- if (rc != 0) {
- add_credits_and_wake_if(server, &wdata->credits, 0);
- for (i = 0; i < nr_pages; ++i) {
- if (is_retryable_error(rc))
- redirty_page_for_writepage(wbc,
- wdata->pages[i]);
- else
- SetPageError(wdata->pages[i]);
- end_page_writeback(wdata->pages[i]);
- put_page(wdata->pages[i]);
- }
- if (!is_retryable_error(rc))
- mapping_set_error(mapping, rc);
- }
- kref_put(&wdata->refcount, cifs_writedata_release);
-
- if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) {
- index = saved_index;
- continue;
- }
-
- /* Return immediately if we received a signal during writing */
- if (is_interrupt_error(rc)) {
- done = true;
- break;
- }
-
- if (rc != 0 && saved_rc == 0)
- saved_rc = rc;
-
- wbc->nr_to_write -= nr_pages;
- if (wbc->nr_to_write <= 0)
- done = true;
-
- index = next;
- }
-
- if (!scanned && !done) {
- /*
- * We hit the last page and there is more work to be done: wrap
- * back to the start of the file
- */
- scanned = true;
- index = 0;
- goto retry;
- }
-
- if (saved_rc != 0)
- rc = saved_rc;
-
- if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
- mapping->writeback_index = index;
-
- if (cfile)
- cifsFileInfo_put(cfile);
- free_xid(xid);
- /* Indication to update ctime and mtime as close is deferred */
- set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags);
- return rc;
-}
-
-static int
-cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
-{
- int rc;
- unsigned int xid;
-
- xid = get_xid();
-/* BB add check for wbc flags */
- get_page(page);
- if (!PageUptodate(page))
- cifs_dbg(FYI, "ppw - page not up to date\n");
-
- /*
- * Set the "writeback" flag, and clear "dirty" in the radix tree.
- *
- * A writepage() implementation always needs to do either this,
- * or re-dirty the page with "redirty_page_for_writepage()" in
- * the case of a failure.
- *
- * Just unlocking the page will cause the radix tree tag-bits
- * to fail to update with the state of the page correctly.
- */
- set_page_writeback(page);
-retry_write:
- rc = cifs_partialpagewrite(page, 0, PAGE_SIZE);
- if (is_retryable_error(rc)) {
- if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN)
- goto retry_write;
- redirty_page_for_writepage(wbc, page);
- } else if (rc != 0) {
- SetPageError(page);
- mapping_set_error(page->mapping, rc);
- } else {
- SetPageUptodate(page);
- }
- end_page_writeback(page);
- put_page(page);
- free_xid(xid);
- return rc;
-}
-
-static int cifs_writepage(struct page *page, struct writeback_control *wbc)
-{
- int rc = cifs_writepage_locked(page, wbc);
- unlock_page(page);
- return rc;
-}
-
-static int cifs_write_end(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata)
-{
- int rc;
- struct inode *inode = mapping->host;
- struct cifsFileInfo *cfile = file->private_data;
- struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
- __u32 pid;
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
- pid = cfile->pid;
- else
- pid = current->tgid;
-
- cifs_dbg(FYI, "write_end for page %p from pos %lld with %d bytes\n",
- page, pos, copied);
-
- if (PageChecked(page)) {
- if (copied == len)
- SetPageUptodate(page);
- ClearPageChecked(page);
- } else if (!PageUptodate(page) && copied == PAGE_SIZE)
- SetPageUptodate(page);
-
- if (!PageUptodate(page)) {
- char *page_data;
- unsigned offset = pos & (PAGE_SIZE - 1);
- unsigned int xid;
-
- xid = get_xid();
- /* this is probably better than directly calling
- partialpage_write since in this function the file handle is
- known which we might as well leverage */
- /* BB check if anything else missing out of ppw
- such as updating last write time */
- page_data = kmap(page);
- rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
- /* if (rc < 0) should we set writebehind rc? */
- kunmap(page);
-
- free_xid(xid);
- } else {
- rc = copied;
- pos += copied;
- set_page_dirty(page);
- }
-
- if (rc > 0) {
- spin_lock(&inode->i_lock);
- if (pos > inode->i_size) {
- i_size_write(inode, pos);
- inode->i_blocks = (512 - 1 + pos) >> 9;
- }
- spin_unlock(&inode->i_lock);
- }
-
- unlock_page(page);
- put_page(page);
- /* Indication to update ctime and mtime as close is deferred */
- set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags);
-
- return rc;
-}
-
-int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
- int datasync)
-{
- unsigned int xid;
- int rc = 0;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct cifsFileInfo *smbfile = file->private_data;
- struct inode *inode = file_inode(file);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-
- rc = file_write_and_wait_range(file, start, end);
- if (rc) {
- trace_cifs_fsync_err(inode->i_ino, rc);
- return rc;
- }
-
- xid = get_xid();
-
- cifs_dbg(FYI, "Sync file - name: %pD datasync: 0x%x\n",
- file, datasync);
-
- if (!CIFS_CACHE_READ(CIFS_I(inode))) {
- rc = cifs_zap_mapping(inode);
- if (rc) {
- cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc);
- rc = 0; /* don't care about it in fsync */
- }
- }
-
- tcon = tlink_tcon(smbfile->tlink);
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
- server = tcon->ses->server;
- if (server->ops->flush == NULL) {
- rc = -ENOSYS;
- goto strict_fsync_exit;
- }
-
- if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) {
- smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY);
- if (smbfile) {
- rc = server->ops->flush(xid, tcon, &smbfile->fid);
- cifsFileInfo_put(smbfile);
- } else
- cifs_dbg(FYI, "ignore fsync for file not open for write\n");
- } else
- rc = server->ops->flush(xid, tcon, &smbfile->fid);
- }
-
-strict_fsync_exit:
- free_xid(xid);
- return rc;
-}
-
-int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
-{
- unsigned int xid;
- int rc = 0;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct cifsFileInfo *smbfile = file->private_data;
- struct inode *inode = file_inode(file);
- struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
-
- rc = file_write_and_wait_range(file, start, end);
- if (rc) {
- trace_cifs_fsync_err(file_inode(file)->i_ino, rc);
- return rc;
- }
-
- xid = get_xid();
-
- cifs_dbg(FYI, "Sync file - name: %pD datasync: 0x%x\n",
- file, datasync);
-
- tcon = tlink_tcon(smbfile->tlink);
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
- server = tcon->ses->server;
- if (server->ops->flush == NULL) {
- rc = -ENOSYS;
- goto fsync_exit;
- }
-
- if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) {
- smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY);
- if (smbfile) {
- rc = server->ops->flush(xid, tcon, &smbfile->fid);
- cifsFileInfo_put(smbfile);
- } else
- cifs_dbg(FYI, "ignore fsync for file not open for write\n");
- } else
- rc = server->ops->flush(xid, tcon, &smbfile->fid);
- }
-
-fsync_exit:
- free_xid(xid);
- return rc;
-}
-
-/*
- * As file closes, flush all cached write data for this inode checking
- * for write behind errors.
- */
-int cifs_flush(struct file *file, fl_owner_t id)
-{
- struct inode *inode = file_inode(file);
- int rc = 0;
-
- if (file->f_mode & FMODE_WRITE)
- rc = filemap_write_and_wait(inode->i_mapping);
-
- cifs_dbg(FYI, "Flush inode %p file %p rc %d\n", inode, file, rc);
- if (rc) {
- /* get more nuanced writeback errors */
- rc = filemap_check_wb_err(file->f_mapping, 0);
- trace_cifs_flush_err(inode->i_ino, rc);
- }
- return rc;
-}
-
-static int
-cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
-{
- int rc = 0;
- unsigned long i;
-
- for (i = 0; i < num_pages; i++) {
- pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
- if (!pages[i]) {
- /*
- * save number of pages we have already allocated and
- * return with ENOMEM error
- */
- num_pages = i;
- rc = -ENOMEM;
- break;
- }
- }
-
- if (rc) {
- for (i = 0; i < num_pages; i++)
- put_page(pages[i]);
- }
- return rc;
-}
-
-static inline
-size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
-{
- size_t num_pages;
- size_t clen;
-
- clen = min_t(const size_t, len, wsize);
- num_pages = DIV_ROUND_UP(clen, PAGE_SIZE);
-
- if (cur_len)
- *cur_len = clen;
-
- return num_pages;
-}
-
-static void
-cifs_uncached_writedata_release(struct kref *refcount)
-{
- int i;
- struct cifs_writedata *wdata = container_of(refcount,
- struct cifs_writedata, refcount);
-
- kref_put(&wdata->ctx->refcount, cifs_aio_ctx_release);
- for (i = 0; i < wdata->nr_pages; i++)
- put_page(wdata->pages[i]);
- cifs_writedata_release(refcount);
-}
-
-static void collect_uncached_write_data(struct cifs_aio_ctx *ctx);
-
-static void
-cifs_uncached_writev_complete(struct work_struct *work)
-{
- struct cifs_writedata *wdata = container_of(work,
- struct cifs_writedata, work);
- struct inode *inode = d_inode(wdata->cfile->dentry);
- struct cifsInodeInfo *cifsi = CIFS_I(inode);
-
- spin_lock(&inode->i_lock);
- cifs_update_eof(cifsi, wdata->offset, wdata->bytes);
- if (cifsi->server_eof > inode->i_size)
- i_size_write(inode, cifsi->server_eof);
- spin_unlock(&inode->i_lock);
-
- complete(&wdata->done);
- collect_uncached_write_data(wdata->ctx);
- /* the below call can possibly free the last ref to aio ctx */
- kref_put(&wdata->refcount, cifs_uncached_writedata_release);
-}
-
-static int
-wdata_fill_from_iovec(struct cifs_writedata *wdata, struct iov_iter *from,
- size_t *len, unsigned long *num_pages)
-{
- size_t save_len, copied, bytes, cur_len = *len;
- unsigned long i, nr_pages = *num_pages;
-
- save_len = cur_len;
- for (i = 0; i < nr_pages; i++) {
- bytes = min_t(const size_t, cur_len, PAGE_SIZE);
- copied = copy_page_from_iter(wdata->pages[i], 0, bytes, from);
- cur_len -= copied;
- /*
- * If we didn't copy as much as we expected, then that
- * may mean we trod into an unmapped area. Stop copying
- * at that point. On the next pass through the big
- * loop, we'll likely end up getting a zero-length
- * write and bailing out of it.
- */
- if (copied < bytes)
- break;
- }
- cur_len = save_len - cur_len;
- *len = cur_len;
-
- /*
- * If we have no data to send, then that probably means that
- * the copy above failed altogether. That's most likely because
- * the address in the iovec was bogus. Return -EFAULT and let
- * the caller free anything we allocated and bail out.
- */
- if (!cur_len)
- return -EFAULT;
-
- /*
- * i + 1 now represents the number of pages we actually used in
- * the copy phase above.
- */
- *num_pages = i + 1;
- return 0;
-}
-
-static int
-cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list,
- struct cifs_aio_ctx *ctx)
-{
- unsigned int wsize;
- struct cifs_credits credits;
- int rc;
- struct TCP_Server_Info *server = wdata->server;
-
- do {
- if (wdata->cfile->invalidHandle) {
- rc = cifs_reopen_file(wdata->cfile, false);
- if (rc == -EAGAIN)
- continue;
- else if (rc)
- break;
- }
-
-
- /*
- * Wait for credits to resend this wdata.
- * Note: we are attempting to resend the whole wdata not in
- * segments
- */
- do {
- rc = server->ops->wait_mtu_credits(server, wdata->bytes,
- &wsize, &credits);
- if (rc)
- goto fail;
-
- if (wsize < wdata->bytes) {
- add_credits_and_wake_if(server, &credits, 0);
- msleep(1000);
- }
- } while (wsize < wdata->bytes);
- wdata->credits = credits;
-
- rc = adjust_credits(server, &wdata->credits, wdata->bytes);
-
- if (!rc) {
- if (wdata->cfile->invalidHandle)
- rc = -EAGAIN;
- else {
-#ifdef CONFIG_CIFS_SMB_DIRECT
- if (wdata->mr) {
- wdata->mr->need_invalidate = true;
- smbd_deregister_mr(wdata->mr);
- wdata->mr = NULL;
- }
-#endif
- rc = server->ops->async_writev(wdata,
- cifs_uncached_writedata_release);
- }
- }
-
- /* If the write was successfully sent, we are done */
- if (!rc) {
- list_add_tail(&wdata->list, wdata_list);
- return 0;
- }
-
- /* Roll back credits and retry if needed */
- add_credits_and_wake_if(server, &wdata->credits, 0);
- } while (rc == -EAGAIN);
-
-fail:
- kref_put(&wdata->refcount, cifs_uncached_writedata_release);
- return rc;
-}
-
-static int
-cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
- struct cifsFileInfo *open_file,
- struct cifs_sb_info *cifs_sb, struct list_head *wdata_list,
- struct cifs_aio_ctx *ctx)
-{
- int rc = 0;
- size_t cur_len;
- unsigned long nr_pages, num_pages, i;
- struct cifs_writedata *wdata;
- struct iov_iter saved_from = *from;
- loff_t saved_offset = offset;
- pid_t pid;
- struct TCP_Server_Info *server;
- struct page **pagevec;
- size_t start;
- unsigned int xid;
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
- pid = open_file->pid;
- else
- pid = current->tgid;
-
- server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses);
- xid = get_xid();
-
- do {
- unsigned int wsize;
- struct cifs_credits credits_on_stack;
- struct cifs_credits *credits = &credits_on_stack;
-
- if (open_file->invalidHandle) {
- rc = cifs_reopen_file(open_file, false);
- if (rc == -EAGAIN)
- continue;
- else if (rc)
- break;
- }
-
- rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->wsize,
- &wsize, credits);
- if (rc)
- break;
-
- cur_len = min_t(const size_t, len, wsize);
-
- if (ctx->direct_io) {
- ssize_t result;
-
- result = iov_iter_get_pages_alloc2(
- from, &pagevec, cur_len, &start);
- if (result < 0) {
- cifs_dbg(VFS,
- "direct_writev couldn't get user pages (rc=%zd) iter type %d iov_offset %zd count %zd\n",
- result, iov_iter_type(from),
- from->iov_offset, from->count);
- dump_stack();
-
- rc = result;
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
- cur_len = (size_t)result;
-
- nr_pages =
- (cur_len + start + PAGE_SIZE - 1) / PAGE_SIZE;
-
- wdata = cifs_writedata_direct_alloc(pagevec,
- cifs_uncached_writev_complete);
- if (!wdata) {
- rc = -ENOMEM;
- for (i = 0; i < nr_pages; i++)
- put_page(pagevec[i]);
- kvfree(pagevec);
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
-
-
- wdata->page_offset = start;
- wdata->tailsz =
- nr_pages > 1 ?
- cur_len - (PAGE_SIZE - start) -
- (nr_pages - 2) * PAGE_SIZE :
- cur_len;
- } else {
- nr_pages = get_numpages(wsize, len, &cur_len);
- wdata = cifs_writedata_alloc(nr_pages,
- cifs_uncached_writev_complete);
- if (!wdata) {
- rc = -ENOMEM;
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
-
- rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
- if (rc) {
- kvfree(wdata->pages);
- kfree(wdata);
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
-
- num_pages = nr_pages;
- rc = wdata_fill_from_iovec(
- wdata, from, &cur_len, &num_pages);
- if (rc) {
- for (i = 0; i < nr_pages; i++)
- put_page(wdata->pages[i]);
- kvfree(wdata->pages);
- kfree(wdata);
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
-
- /*
- * Bring nr_pages down to the number of pages we
- * actually used, and free any pages that we didn't use.
- */
- for ( ; nr_pages > num_pages; nr_pages--)
- put_page(wdata->pages[nr_pages - 1]);
-
- wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
- }
-
- wdata->sync_mode = WB_SYNC_ALL;
- wdata->nr_pages = nr_pages;
- wdata->offset = (__u64)offset;
- wdata->cfile = cifsFileInfo_get(open_file);
- wdata->server = server;
- wdata->pid = pid;
- wdata->bytes = cur_len;
- wdata->pagesz = PAGE_SIZE;
- wdata->credits = credits_on_stack;
- wdata->ctx = ctx;
- kref_get(&ctx->refcount);
-
- rc = adjust_credits(server, &wdata->credits, wdata->bytes);
-
- if (!rc) {
- if (wdata->cfile->invalidHandle)
- rc = -EAGAIN;
- else
- rc = server->ops->async_writev(wdata,
- cifs_uncached_writedata_release);
- }
-
- if (rc) {
- add_credits_and_wake_if(server, &wdata->credits, 0);
- kref_put(&wdata->refcount,
- cifs_uncached_writedata_release);
- if (rc == -EAGAIN) {
- *from = saved_from;
- iov_iter_advance(from, offset - saved_offset);
- continue;
- }
- break;
- }
-
- list_add_tail(&wdata->list, wdata_list);
- offset += cur_len;
- len -= cur_len;
- } while (len > 0);
-
- free_xid(xid);
- return rc;
-}
-
-static void collect_uncached_write_data(struct cifs_aio_ctx *ctx)
-{
- struct cifs_writedata *wdata, *tmp;
- struct cifs_tcon *tcon;
- struct cifs_sb_info *cifs_sb;
- struct dentry *dentry = ctx->cfile->dentry;
- ssize_t rc;
-
- tcon = tlink_tcon(ctx->cfile->tlink);
- cifs_sb = CIFS_SB(dentry->d_sb);
-
- mutex_lock(&ctx->aio_mutex);
-
- if (list_empty(&ctx->list)) {
- mutex_unlock(&ctx->aio_mutex);
- return;
- }
-
- rc = ctx->rc;
- /*
- * Wait for and collect replies for any successful sends in order of
- * increasing offset. Once an error is hit, then return without waiting
- * for any more replies.
- */
-restart_loop:
- list_for_each_entry_safe(wdata, tmp, &ctx->list, list) {
- if (!rc) {
- if (!try_wait_for_completion(&wdata->done)) {
- mutex_unlock(&ctx->aio_mutex);
- return;
- }
-
- if (wdata->result)
- rc = wdata->result;
- else
- ctx->total_len += wdata->bytes;
-
- /* resend call if it's a retryable error */
- if (rc == -EAGAIN) {
- struct list_head tmp_list;
- struct iov_iter tmp_from = ctx->iter;
-
- INIT_LIST_HEAD(&tmp_list);
- list_del_init(&wdata->list);
-
- if (ctx->direct_io)
- rc = cifs_resend_wdata(
- wdata, &tmp_list, ctx);
- else {
- iov_iter_advance(&tmp_from,
- wdata->offset - ctx->pos);
-
- rc = cifs_write_from_iter(wdata->offset,
- wdata->bytes, &tmp_from,
- ctx->cfile, cifs_sb, &tmp_list,
- ctx);
-
- kref_put(&wdata->refcount,
- cifs_uncached_writedata_release);
- }
-
- list_splice(&tmp_list, &ctx->list);
- goto restart_loop;
- }
- }
- list_del_init(&wdata->list);
- kref_put(&wdata->refcount, cifs_uncached_writedata_release);
- }
-
- cifs_stats_bytes_written(tcon, ctx->total_len);
- set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(dentry->d_inode)->flags);
-
- ctx->rc = (rc == 0) ? ctx->total_len : rc;
-
- mutex_unlock(&ctx->aio_mutex);
-
- if (ctx->iocb && ctx->iocb->ki_complete)
- ctx->iocb->ki_complete(ctx->iocb, ctx->rc);
- else
- complete(&ctx->done);
-}
-
-static ssize_t __cifs_writev(
- struct kiocb *iocb, struct iov_iter *from, bool direct)
-{
- struct file *file = iocb->ki_filp;
- ssize_t total_written = 0;
- struct cifsFileInfo *cfile;
- struct cifs_tcon *tcon;
- struct cifs_sb_info *cifs_sb;
- struct cifs_aio_ctx *ctx;
- struct iov_iter saved_from = *from;
- size_t len = iov_iter_count(from);
- int rc;
-
- /*
- * iov_iter_get_pages_alloc doesn't work with ITER_KVEC.
- * In this case, fall back to non-direct write function.
- * this could be improved by getting pages directly in ITER_KVEC
- */
- if (direct && iov_iter_is_kvec(from)) {
- cifs_dbg(FYI, "use non-direct cifs_writev for kvec I/O\n");
- direct = false;
- }
-
- rc = generic_write_checks(iocb, from);
- if (rc <= 0)
- return rc;
-
- cifs_sb = CIFS_FILE_SB(file);
- cfile = file->private_data;
- tcon = tlink_tcon(cfile->tlink);
-
- if (!tcon->ses->server->ops->async_writev)
- return -ENOSYS;
-
- ctx = cifs_aio_ctx_alloc();
- if (!ctx)
- return -ENOMEM;
-
- ctx->cfile = cifsFileInfo_get(cfile);
-
- if (!is_sync_kiocb(iocb))
- ctx->iocb = iocb;
-
- ctx->pos = iocb->ki_pos;
-
- if (direct) {
- ctx->direct_io = true;
- ctx->iter = *from;
- ctx->len = len;
- } else {
- rc = setup_aio_ctx_iter(ctx, from, ITER_SOURCE);
- if (rc) {
- kref_put(&ctx->refcount, cifs_aio_ctx_release);
- return rc;
- }
- }
-
- /* grab a lock here due to read response handlers can access ctx */
- mutex_lock(&ctx->aio_mutex);
-
- rc = cifs_write_from_iter(iocb->ki_pos, ctx->len, &saved_from,
- cfile, cifs_sb, &ctx->list, ctx);
-
- /*
- * If at least one write was successfully sent, then discard any rc
- * value from the later writes. If the other write succeeds, then
- * we'll end up returning whatever was written. If it fails, then
- * we'll get a new rc value from that.
- */
- if (!list_empty(&ctx->list))
- rc = 0;
-
- mutex_unlock(&ctx->aio_mutex);
-
- if (rc) {
- kref_put(&ctx->refcount, cifs_aio_ctx_release);
- return rc;
- }
-
- if (!is_sync_kiocb(iocb)) {
- kref_put(&ctx->refcount, cifs_aio_ctx_release);
- return -EIOCBQUEUED;
- }
-
- rc = wait_for_completion_killable(&ctx->done);
- if (rc) {
- mutex_lock(&ctx->aio_mutex);
- ctx->rc = rc = -EINTR;
- total_written = ctx->total_len;
- mutex_unlock(&ctx->aio_mutex);
- } else {
- rc = ctx->rc;
- total_written = ctx->total_len;
- }
-
- kref_put(&ctx->refcount, cifs_aio_ctx_release);
-
- if (unlikely(!total_written))
- return rc;
-
- iocb->ki_pos += total_written;
- return total_written;
-}
-
-ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from)
-{
- struct file *file = iocb->ki_filp;
-
- cifs_revalidate_mapping(file->f_inode);
- return __cifs_writev(iocb, from, true);
-}
-
-ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
-{
- return __cifs_writev(iocb, from, false);
-}
-
-static ssize_t
-cifs_writev(struct kiocb *iocb, struct iov_iter *from)
-{
- struct file *file = iocb->ki_filp;
- struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
- struct inode *inode = file->f_mapping->host;
- struct cifsInodeInfo *cinode = CIFS_I(inode);
- struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
- ssize_t rc;
-
- inode_lock(inode);
- /*
- * We need to hold the sem to be sure nobody modifies lock list
- * with a brlock that prevents writing.
- */
- down_read(&cinode->lock_sem);
-
- rc = generic_write_checks(iocb, from);
- if (rc <= 0)
- goto out;
-
- if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from),
- server->vals->exclusive_lock_type, 0,
- NULL, CIFS_WRITE_OP))
- rc = __generic_file_write_iter(iocb, from);
- else
- rc = -EACCES;
-out:
- up_read(&cinode->lock_sem);
- inode_unlock(inode);
-
- if (rc > 0)
- rc = generic_write_sync(iocb, rc);
- return rc;
-}
-
-ssize_t
-cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
-{
- struct inode *inode = file_inode(iocb->ki_filp);
- struct cifsInodeInfo *cinode = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsFileInfo *cfile = (struct cifsFileInfo *)
- iocb->ki_filp->private_data;
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- ssize_t written;
-
- written = cifs_get_writer(cinode);
- if (written)
- return written;
-
- if (CIFS_CACHE_WRITE(cinode)) {
- if (cap_unix(tcon->ses) &&
- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))
- && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
- written = generic_file_write_iter(iocb, from);
- goto out;
- }
- written = cifs_writev(iocb, from);
- goto out;
- }
- /*
- * For non-oplocked files in strict cache mode we need to write the data
- * to the server exactly from the pos to pos+len-1 rather than flush all
- * affected pages because it may cause a error with mandatory locks on
- * these pages but not on the region from pos to ppos+len-1.
- */
- written = cifs_user_writev(iocb, from);
- if (CIFS_CACHE_READ(cinode)) {
- /*
- * We have read level caching and we have just sent a write
- * request to the server thus making data in the cache stale.
- * Zap the cache and set oplock/lease level to NONE to avoid
- * reading stale data from the cache. All subsequent read
- * operations will read new data from the server.
- */
- cifs_zap_mapping(inode);
- cifs_dbg(FYI, "Set Oplock/Lease to NONE for inode=%p after write\n",
- inode);
- cinode->oplock = 0;
- }
-out:
- cifs_put_writer(cinode);
- return written;
-}
-
-static struct cifs_readdata *
-cifs_readdata_direct_alloc(struct page **pages, work_func_t complete)
-{
- struct cifs_readdata *rdata;
-
- rdata = kzalloc(sizeof(*rdata), GFP_KERNEL);
- if (rdata != NULL) {
- rdata->pages = pages;
- kref_init(&rdata->refcount);
- INIT_LIST_HEAD(&rdata->list);
- init_completion(&rdata->done);
- INIT_WORK(&rdata->work, complete);
- }
-
- return rdata;
-}
-
-static struct cifs_readdata *
-cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
-{
- struct page **pages =
- kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
- struct cifs_readdata *ret = NULL;
-
- if (pages) {
- ret = cifs_readdata_direct_alloc(pages, complete);
- if (!ret)
- kfree(pages);
- }
-
- return ret;
-}
-
-void
-cifs_readdata_release(struct kref *refcount)
-{
- struct cifs_readdata *rdata = container_of(refcount,
- struct cifs_readdata, refcount);
-#ifdef CONFIG_CIFS_SMB_DIRECT
- if (rdata->mr) {
- smbd_deregister_mr(rdata->mr);
- rdata->mr = NULL;
- }
-#endif
- if (rdata->cfile)
- cifsFileInfo_put(rdata->cfile);
-
- kvfree(rdata->pages);
- kfree(rdata);
-}
-
-static int
-cifs_read_allocate_pages(struct cifs_readdata *rdata, unsigned int nr_pages)
-{
- int rc = 0;
- struct page *page;
- unsigned int i;
-
- for (i = 0; i < nr_pages; i++) {
- page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
- if (!page) {
- rc = -ENOMEM;
- break;
- }
- rdata->pages[i] = page;
- }
-
- if (rc) {
- unsigned int nr_page_failed = i;
-
- for (i = 0; i < nr_page_failed; i++) {
- put_page(rdata->pages[i]);
- rdata->pages[i] = NULL;
- }
- }
- return rc;
-}
-
-static void
-cifs_uncached_readdata_release(struct kref *refcount)
-{
- struct cifs_readdata *rdata = container_of(refcount,
- struct cifs_readdata, refcount);
- unsigned int i;
-
- kref_put(&rdata->ctx->refcount, cifs_aio_ctx_release);
- for (i = 0; i < rdata->nr_pages; i++) {
- put_page(rdata->pages[i]);
- }
- cifs_readdata_release(refcount);
-}
-
-/**
- * cifs_readdata_to_iov - copy data from pages in response to an iovec
- * @rdata: the readdata response with list of pages holding data
- * @iter: destination for our data
- *
- * This function copies data from a list of pages in a readdata response into
- * an array of iovecs. It will first calculate where the data should go
- * based on the info in the readdata and then copy the data into that spot.
- */
-static int
-cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter)
-{
- size_t remaining = rdata->got_bytes;
- unsigned int i;
-
- for (i = 0; i < rdata->nr_pages; i++) {
- struct page *page = rdata->pages[i];
- size_t copy = min_t(size_t, remaining, PAGE_SIZE);
- size_t written;
-
- if (unlikely(iov_iter_is_pipe(iter))) {
- void *addr = kmap_atomic(page);
-
- written = copy_to_iter(addr, copy, iter);
- kunmap_atomic(addr);
- } else
- written = copy_page_to_iter(page, 0, copy, iter);
- remaining -= written;
- if (written < copy && iov_iter_count(iter) > 0)
- break;
- }
- return remaining ? -EFAULT : 0;
-}
-
-static void collect_uncached_read_data(struct cifs_aio_ctx *ctx);
-
-static void
-cifs_uncached_readv_complete(struct work_struct *work)
-{
- struct cifs_readdata *rdata = container_of(work,
- struct cifs_readdata, work);
-
- complete(&rdata->done);
- collect_uncached_read_data(rdata->ctx);
- /* the below call can possibly free the last ref to aio ctx */
- kref_put(&rdata->refcount, cifs_uncached_readdata_release);
-}
-
-static int
-uncached_fill_pages(struct TCP_Server_Info *server,
- struct cifs_readdata *rdata, struct iov_iter *iter,
- unsigned int len)
-{
- int result = 0;
- unsigned int i;
- unsigned int nr_pages = rdata->nr_pages;
- unsigned int page_offset = rdata->page_offset;
-
- rdata->got_bytes = 0;
- rdata->tailsz = PAGE_SIZE;
- for (i = 0; i < nr_pages; i++) {
- struct page *page = rdata->pages[i];
- size_t n;
- unsigned int segment_size = rdata->pagesz;
-
- if (i == 0)
- segment_size -= page_offset;
- else
- page_offset = 0;
-
-
- if (len <= 0) {
- /* no need to hold page hostage */
- rdata->pages[i] = NULL;
- rdata->nr_pages--;
- put_page(page);
- continue;
- }
-
- n = len;
- if (len >= segment_size)
- /* enough data to fill the page */
- n = segment_size;
- else
- rdata->tailsz = len;
- len -= n;
-
- if (iter)
- result = copy_page_from_iter(
- page, page_offset, n, iter);
-#ifdef CONFIG_CIFS_SMB_DIRECT
- else if (rdata->mr)
- result = n;
-#endif
- else
- result = cifs_read_page_from_socket(
- server, page, page_offset, n);
- if (result < 0)
- break;
-
- rdata->got_bytes += result;
- }
-
- return result != -ECONNABORTED && rdata->got_bytes > 0 ?
- rdata->got_bytes : result;
-}
-
-static int
-cifs_uncached_read_into_pages(struct TCP_Server_Info *server,
- struct cifs_readdata *rdata, unsigned int len)
-{
- return uncached_fill_pages(server, rdata, NULL, len);
-}
-
-static int
-cifs_uncached_copy_into_pages(struct TCP_Server_Info *server,
- struct cifs_readdata *rdata,
- struct iov_iter *iter)
-{
- return uncached_fill_pages(server, rdata, iter, iter->count);
-}
-
-static int cifs_resend_rdata(struct cifs_readdata *rdata,
- struct list_head *rdata_list,
- struct cifs_aio_ctx *ctx)
-{
- unsigned int rsize;
- struct cifs_credits credits;
- int rc;
- struct TCP_Server_Info *server;
-
- /* XXX: should we pick a new channel here? */
- server = rdata->server;
-
- do {
- if (rdata->cfile->invalidHandle) {
- rc = cifs_reopen_file(rdata->cfile, true);
- if (rc == -EAGAIN)
- continue;
- else if (rc)
- break;
- }
-
- /*
- * Wait for credits to resend this rdata.
- * Note: we are attempting to resend the whole rdata not in
- * segments
- */
- do {
- rc = server->ops->wait_mtu_credits(server, rdata->bytes,
- &rsize, &credits);
-
- if (rc)
- goto fail;
-
- if (rsize < rdata->bytes) {
- add_credits_and_wake_if(server, &credits, 0);
- msleep(1000);
- }
- } while (rsize < rdata->bytes);
- rdata->credits = credits;
-
- rc = adjust_credits(server, &rdata->credits, rdata->bytes);
- if (!rc) {
- if (rdata->cfile->invalidHandle)
- rc = -EAGAIN;
- else {
-#ifdef CONFIG_CIFS_SMB_DIRECT
- if (rdata->mr) {
- rdata->mr->need_invalidate = true;
- smbd_deregister_mr(rdata->mr);
- rdata->mr = NULL;
- }
-#endif
- rc = server->ops->async_readv(rdata);
- }
- }
-
- /* If the read was successfully sent, we are done */
- if (!rc) {
- /* Add to aio pending list */
- list_add_tail(&rdata->list, rdata_list);
- return 0;
- }
-
- /* Roll back credits and retry if needed */
- add_credits_and_wake_if(server, &rdata->credits, 0);
- } while (rc == -EAGAIN);
-
-fail:
- kref_put(&rdata->refcount, cifs_uncached_readdata_release);
- return rc;
-}
-
-static int
-cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
- struct cifs_sb_info *cifs_sb, struct list_head *rdata_list,
- struct cifs_aio_ctx *ctx)
-{
- struct cifs_readdata *rdata;
- unsigned int npages, rsize;
- struct cifs_credits credits_on_stack;
- struct cifs_credits *credits = &credits_on_stack;
- size_t cur_len;
- int rc;
- pid_t pid;
- struct TCP_Server_Info *server;
- struct page **pagevec;
- size_t start;
- struct iov_iter direct_iov = ctx->iter;
-
- server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses);
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
- pid = open_file->pid;
- else
- pid = current->tgid;
-
- if (ctx->direct_io)
- iov_iter_advance(&direct_iov, offset - ctx->pos);
-
- do {
- if (open_file->invalidHandle) {
- rc = cifs_reopen_file(open_file, true);
- if (rc == -EAGAIN)
- continue;
- else if (rc)
- break;
- }
-
- if (cifs_sb->ctx->rsize == 0)
- cifs_sb->ctx->rsize =
- server->ops->negotiate_rsize(tlink_tcon(open_file->tlink),
- cifs_sb->ctx);
-
- rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
- &rsize, credits);
- if (rc)
- break;
-
- cur_len = min_t(const size_t, len, rsize);
-
- if (ctx->direct_io) {
- ssize_t result;
-
- result = iov_iter_get_pages_alloc2(
- &direct_iov, &pagevec,
- cur_len, &start);
- if (result < 0) {
- cifs_dbg(VFS,
- "Couldn't get user pages (rc=%zd) iter type %d iov_offset %zd count %zd\n",
- result, iov_iter_type(&direct_iov),
- direct_iov.iov_offset,
- direct_iov.count);
- dump_stack();
-
- rc = result;
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
- cur_len = (size_t)result;
-
- rdata = cifs_readdata_direct_alloc(
- pagevec, cifs_uncached_readv_complete);
- if (!rdata) {
- add_credits_and_wake_if(server, credits, 0);
- rc = -ENOMEM;
- break;
- }
-
- npages = (cur_len + start + PAGE_SIZE-1) / PAGE_SIZE;
- rdata->page_offset = start;
- rdata->tailsz = npages > 1 ?
- cur_len-(PAGE_SIZE-start)-(npages-2)*PAGE_SIZE :
- cur_len;
-
- } else {
-
- npages = DIV_ROUND_UP(cur_len, PAGE_SIZE);
- /* allocate a readdata struct */
- rdata = cifs_readdata_alloc(npages,
- cifs_uncached_readv_complete);
- if (!rdata) {
- add_credits_and_wake_if(server, credits, 0);
- rc = -ENOMEM;
- break;
- }
-
- rc = cifs_read_allocate_pages(rdata, npages);
- if (rc) {
- kvfree(rdata->pages);
- kfree(rdata);
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
-
- rdata->tailsz = PAGE_SIZE;
- }
-
- rdata->server = server;
- rdata->cfile = cifsFileInfo_get(open_file);
- rdata->nr_pages = npages;
- rdata->offset = offset;
- rdata->bytes = cur_len;
- rdata->pid = pid;
- rdata->pagesz = PAGE_SIZE;
- rdata->read_into_pages = cifs_uncached_read_into_pages;
- rdata->copy_into_pages = cifs_uncached_copy_into_pages;
- rdata->credits = credits_on_stack;
- rdata->ctx = ctx;
- kref_get(&ctx->refcount);
-
- rc = adjust_credits(server, &rdata->credits, rdata->bytes);
-
- if (!rc) {
- if (rdata->cfile->invalidHandle)
- rc = -EAGAIN;
- else
- rc = server->ops->async_readv(rdata);
- }
-
- if (rc) {
- add_credits_and_wake_if(server, &rdata->credits, 0);
- kref_put(&rdata->refcount,
- cifs_uncached_readdata_release);
- if (rc == -EAGAIN) {
- iov_iter_revert(&direct_iov, cur_len);
- continue;
- }
- break;
- }
-
- list_add_tail(&rdata->list, rdata_list);
- offset += cur_len;
- len -= cur_len;
- } while (len > 0);
-
- return rc;
-}
-
-static void
-collect_uncached_read_data(struct cifs_aio_ctx *ctx)
-{
- struct cifs_readdata *rdata, *tmp;
- struct iov_iter *to = &ctx->iter;
- struct cifs_sb_info *cifs_sb;
- int rc;
-
- cifs_sb = CIFS_SB(ctx->cfile->dentry->d_sb);
-
- mutex_lock(&ctx->aio_mutex);
-
- if (list_empty(&ctx->list)) {
- mutex_unlock(&ctx->aio_mutex);
- return;
- }
-
- rc = ctx->rc;
- /* the loop below should proceed in the order of increasing offsets */
-again:
- list_for_each_entry_safe(rdata, tmp, &ctx->list, list) {
- if (!rc) {
- if (!try_wait_for_completion(&rdata->done)) {
- mutex_unlock(&ctx->aio_mutex);
- return;
- }
-
- if (rdata->result == -EAGAIN) {
- /* resend call if it's a retryable error */
- struct list_head tmp_list;
- unsigned int got_bytes = rdata->got_bytes;
-
- list_del_init(&rdata->list);
- INIT_LIST_HEAD(&tmp_list);
-
- /*
- * Got a part of data and then reconnect has
- * happened -- fill the buffer and continue
- * reading.
- */
- if (got_bytes && got_bytes < rdata->bytes) {
- rc = 0;
- if (!ctx->direct_io)
- rc = cifs_readdata_to_iov(rdata, to);
- if (rc) {
- kref_put(&rdata->refcount,
- cifs_uncached_readdata_release);
- continue;
- }
- }
-
- if (ctx->direct_io) {
- /*
- * Re-use rdata as this is a
- * direct I/O
- */
- rc = cifs_resend_rdata(
- rdata,
- &tmp_list, ctx);
- } else {
- rc = cifs_send_async_read(
- rdata->offset + got_bytes,
- rdata->bytes - got_bytes,
- rdata->cfile, cifs_sb,
- &tmp_list, ctx);
-
- kref_put(&rdata->refcount,
- cifs_uncached_readdata_release);
- }
-
- list_splice(&tmp_list, &ctx->list);
-
- goto again;
- } else if (rdata->result)
- rc = rdata->result;
- else if (!ctx->direct_io)
- rc = cifs_readdata_to_iov(rdata, to);
-
- /* if there was a short read -- discard anything left */
- if (rdata->got_bytes && rdata->got_bytes < rdata->bytes)
- rc = -ENODATA;
-
- ctx->total_len += rdata->got_bytes;
- }
- list_del_init(&rdata->list);
- kref_put(&rdata->refcount, cifs_uncached_readdata_release);
- }
-
- if (!ctx->direct_io)
- ctx->total_len = ctx->len - iov_iter_count(to);
-
- /* mask nodata case */
- if (rc == -ENODATA)
- rc = 0;
-
- ctx->rc = (rc == 0) ? (ssize_t)ctx->total_len : rc;
-
- mutex_unlock(&ctx->aio_mutex);
-
- if (ctx->iocb && ctx->iocb->ki_complete)
- ctx->iocb->ki_complete(ctx->iocb, ctx->rc);
- else
- complete(&ctx->done);
-}
-
-static ssize_t __cifs_readv(
- struct kiocb *iocb, struct iov_iter *to, bool direct)
-{
- size_t len;
- struct file *file = iocb->ki_filp;
- struct cifs_sb_info *cifs_sb;
- struct cifsFileInfo *cfile;
- struct cifs_tcon *tcon;
- ssize_t rc, total_read = 0;
- loff_t offset = iocb->ki_pos;
- struct cifs_aio_ctx *ctx;
-
- /*
- * iov_iter_get_pages_alloc() doesn't work with ITER_KVEC,
- * fall back to data copy read path
- * this could be improved by getting pages directly in ITER_KVEC
- */
- if (direct && iov_iter_is_kvec(to)) {
- cifs_dbg(FYI, "use non-direct cifs_user_readv for kvec I/O\n");
- direct = false;
- }
-
- len = iov_iter_count(to);
- if (!len)
- return 0;
-
- cifs_sb = CIFS_FILE_SB(file);
- cfile = file->private_data;
- tcon = tlink_tcon(cfile->tlink);
-
- if (!tcon->ses->server->ops->async_readv)
- return -ENOSYS;
-
- if ((file->f_flags & O_ACCMODE) == O_WRONLY)
- cifs_dbg(FYI, "attempting read on write only file instance\n");
-
- ctx = cifs_aio_ctx_alloc();
- if (!ctx)
- return -ENOMEM;
-
- ctx->cfile = cifsFileInfo_get(cfile);
-
- if (!is_sync_kiocb(iocb))
- ctx->iocb = iocb;
-
- if (user_backed_iter(to))
- ctx->should_dirty = true;
-
- if (direct) {
- ctx->pos = offset;
- ctx->direct_io = true;
- ctx->iter = *to;
- ctx->len = len;
- } else {
- rc = setup_aio_ctx_iter(ctx, to, ITER_DEST);
- if (rc) {
- kref_put(&ctx->refcount, cifs_aio_ctx_release);
- return rc;
- }
- len = ctx->len;
- }
-
- if (direct) {
- rc = filemap_write_and_wait_range(file->f_inode->i_mapping,
- offset, offset + len - 1);
- if (rc) {
- kref_put(&ctx->refcount, cifs_aio_ctx_release);
- return -EAGAIN;
- }
- }
-
- /* grab a lock here due to read response handlers can access ctx */
- mutex_lock(&ctx->aio_mutex);
-
- rc = cifs_send_async_read(offset, len, cfile, cifs_sb, &ctx->list, ctx);
-
- /* if at least one read request send succeeded, then reset rc */
- if (!list_empty(&ctx->list))
- rc = 0;
-
- mutex_unlock(&ctx->aio_mutex);
-
- if (rc) {
- kref_put(&ctx->refcount, cifs_aio_ctx_release);
- return rc;
- }
-
- if (!is_sync_kiocb(iocb)) {
- kref_put(&ctx->refcount, cifs_aio_ctx_release);
- return -EIOCBQUEUED;
- }
-
- rc = wait_for_completion_killable(&ctx->done);
- if (rc) {
- mutex_lock(&ctx->aio_mutex);
- ctx->rc = rc = -EINTR;
- total_read = ctx->total_len;
- mutex_unlock(&ctx->aio_mutex);
- } else {
- rc = ctx->rc;
- total_read = ctx->total_len;
- }
-
- kref_put(&ctx->refcount, cifs_aio_ctx_release);
-
- if (total_read) {
- iocb->ki_pos += total_read;
- return total_read;
- }
- return rc;
-}
-
-ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to)
-{
- return __cifs_readv(iocb, to, true);
-}
-
-ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to)
-{
- return __cifs_readv(iocb, to, false);
-}
-
-ssize_t
-cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
-{
- struct inode *inode = file_inode(iocb->ki_filp);
- struct cifsInodeInfo *cinode = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsFileInfo *cfile = (struct cifsFileInfo *)
- iocb->ki_filp->private_data;
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- int rc = -EACCES;
-
- /*
- * In strict cache mode we need to read from the server all the time
- * if we don't have level II oplock because the server can delay mtime
- * change - so we can't make a decision about inode invalidating.
- * And we can also fail with pagereading if there are mandatory locks
- * on pages affected by this read but not on the region from pos to
- * pos+len-1.
- */
- if (!CIFS_CACHE_READ(cinode))
- return cifs_user_readv(iocb, to);
-
- if (cap_unix(tcon->ses) &&
- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
- ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
- return generic_file_read_iter(iocb, to);
-
- /*
- * We need to hold the sem to be sure nobody modifies lock list
- * with a brlock that prevents reading.
- */
- down_read(&cinode->lock_sem);
- if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(to),
- tcon->ses->server->vals->shared_lock_type,
- 0, NULL, CIFS_READ_OP))
- rc = generic_file_read_iter(iocb, to);
- up_read(&cinode->lock_sem);
- return rc;
-}
-
-static ssize_t
-cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
-{
- int rc = -EACCES;
- unsigned int bytes_read = 0;
- unsigned int total_read;
- unsigned int current_read_size;
- unsigned int rsize;
- struct cifs_sb_info *cifs_sb;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- unsigned int xid;
- char *cur_offset;
- struct cifsFileInfo *open_file;
- struct cifs_io_parms io_parms = {0};
- int buf_type = CIFS_NO_BUFFER;
- __u32 pid;
-
- xid = get_xid();
- cifs_sb = CIFS_FILE_SB(file);
-
- /* FIXME: set up handlers for larger reads and/or convert to async */
- rsize = min_t(unsigned int, cifs_sb->ctx->rsize, CIFSMaxBufSize);
-
- if (file->private_data == NULL) {
- rc = -EBADF;
- free_xid(xid);
- return rc;
- }
- open_file = file->private_data;
- tcon = tlink_tcon(open_file->tlink);
- server = cifs_pick_channel(tcon->ses);
-
- if (!server->ops->sync_read) {
- free_xid(xid);
- return -ENOSYS;
- }
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
- pid = open_file->pid;
- else
- pid = current->tgid;
-
- if ((file->f_flags & O_ACCMODE) == O_WRONLY)
- cifs_dbg(FYI, "attempting read on write only file instance\n");
-
- for (total_read = 0, cur_offset = read_data; read_size > total_read;
- total_read += bytes_read, cur_offset += bytes_read) {
- do {
- current_read_size = min_t(uint, read_size - total_read,
- rsize);
- /*
- * For windows me and 9x we do not want to request more
- * than it negotiated since it will refuse the read
- * then.
- */
- if (!(tcon->ses->capabilities &
- tcon->ses->server->vals->cap_large_files)) {
- current_read_size = min_t(uint,
- current_read_size, CIFSMaxBufSize);
- }
- if (open_file->invalidHandle) {
- rc = cifs_reopen_file(open_file, true);
- if (rc != 0)
- break;
- }
- io_parms.pid = pid;
- io_parms.tcon = tcon;
- io_parms.offset = *offset;
- io_parms.length = current_read_size;
- io_parms.server = server;
- rc = server->ops->sync_read(xid, &open_file->fid, &io_parms,
- &bytes_read, &cur_offset,
- &buf_type);
- } while (rc == -EAGAIN);
-
- if (rc || (bytes_read == 0)) {
- if (total_read) {
- break;
- } else {
- free_xid(xid);
- return rc;
- }
- } else {
- cifs_stats_bytes_read(tcon, total_read);
- *offset += bytes_read;
- }
- }
- free_xid(xid);
- return total_read;
-}
-
-/*
- * If the page is mmap'ed into a process' page tables, then we need to make
- * sure that it doesn't change while being written back.
- */
-static vm_fault_t
-cifs_page_mkwrite(struct vm_fault *vmf)
-{
- struct page *page = vmf->page;
-
- /* Wait for the page to be written to the cache before we allow it to
- * be modified. We then assume the entire page will need writing back.
- */
-#ifdef CONFIG_CIFS_FSCACHE
- if (PageFsCache(page) &&
- wait_on_page_fscache_killable(page) < 0)
- return VM_FAULT_RETRY;
-#endif
-
- wait_on_page_writeback(page);
-
- if (lock_page_killable(page) < 0)
- return VM_FAULT_RETRY;
- return VM_FAULT_LOCKED;
-}
-
-static const struct vm_operations_struct cifs_file_vm_ops = {
- .fault = filemap_fault,
- .map_pages = filemap_map_pages,
- .page_mkwrite = cifs_page_mkwrite,
-};
-
-int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
-{
- int xid, rc = 0;
- struct inode *inode = file_inode(file);
-
- xid = get_xid();
-
- if (!CIFS_CACHE_READ(CIFS_I(inode)))
- rc = cifs_zap_mapping(inode);
- if (!rc)
- rc = generic_file_mmap(file, vma);
- if (!rc)
- vma->vm_ops = &cifs_file_vm_ops;
-
- free_xid(xid);
- return rc;
-}
-
-int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
-{
- int rc, xid;
-
- xid = get_xid();
-
- rc = cifs_revalidate_file(file);
- if (rc)
- cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n",
- rc);
- if (!rc)
- rc = generic_file_mmap(file, vma);
- if (!rc)
- vma->vm_ops = &cifs_file_vm_ops;
-
- free_xid(xid);
- return rc;
-}
-
-static void
-cifs_readv_complete(struct work_struct *work)
-{
- unsigned int i, got_bytes;
- struct cifs_readdata *rdata = container_of(work,
- struct cifs_readdata, work);
-
- got_bytes = rdata->got_bytes;
- for (i = 0; i < rdata->nr_pages; i++) {
- struct page *page = rdata->pages[i];
-
- if (rdata->result == 0 ||
- (rdata->result == -EAGAIN && got_bytes)) {
- flush_dcache_page(page);
- SetPageUptodate(page);
- } else
- SetPageError(page);
-
- if (rdata->result == 0 ||
- (rdata->result == -EAGAIN && got_bytes))
- cifs_readpage_to_fscache(rdata->mapping->host, page);
-
- unlock_page(page);
-
- got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes);
-
- put_page(page);
- rdata->pages[i] = NULL;
- }
- kref_put(&rdata->refcount, cifs_readdata_release);
-}
-
-static int
-readpages_fill_pages(struct TCP_Server_Info *server,
- struct cifs_readdata *rdata, struct iov_iter *iter,
- unsigned int len)
-{
- int result = 0;
- unsigned int i;
- u64 eof;
- pgoff_t eof_index;
- unsigned int nr_pages = rdata->nr_pages;
- unsigned int page_offset = rdata->page_offset;
-
- /* determine the eof that the server (probably) has */
- eof = CIFS_I(rdata->mapping->host)->server_eof;
- eof_index = eof ? (eof - 1) >> PAGE_SHIFT : 0;
- cifs_dbg(FYI, "eof=%llu eof_index=%lu\n", eof, eof_index);
-
- rdata->got_bytes = 0;
- rdata->tailsz = PAGE_SIZE;
- for (i = 0; i < nr_pages; i++) {
- struct page *page = rdata->pages[i];
- unsigned int to_read = rdata->pagesz;
- size_t n;
-
- if (i == 0)
- to_read -= page_offset;
- else
- page_offset = 0;
-
- n = to_read;
-
- if (len >= to_read) {
- len -= to_read;
- } else if (len > 0) {
- /* enough for partial page, fill and zero the rest */
- zero_user(page, len + page_offset, to_read - len);
- n = rdata->tailsz = len;
- len = 0;
- } else if (page->index > eof_index) {
- /*
- * The VFS will not try to do readahead past the
- * i_size, but it's possible that we have outstanding
- * writes with gaps in the middle and the i_size hasn't
- * caught up yet. Populate those with zeroed out pages
- * to prevent the VFS from repeatedly attempting to
- * fill them until the writes are flushed.
- */
- zero_user(page, 0, PAGE_SIZE);
- flush_dcache_page(page);
- SetPageUptodate(page);
- unlock_page(page);
- put_page(page);
- rdata->pages[i] = NULL;
- rdata->nr_pages--;
- continue;
- } else {
- /* no need to hold page hostage */
- unlock_page(page);
- put_page(page);
- rdata->pages[i] = NULL;
- rdata->nr_pages--;
- continue;
- }
-
- if (iter)
- result = copy_page_from_iter(
- page, page_offset, n, iter);
-#ifdef CONFIG_CIFS_SMB_DIRECT
- else if (rdata->mr)
- result = n;
-#endif
- else
- result = cifs_read_page_from_socket(
- server, page, page_offset, n);
- if (result < 0)
- break;
-
- rdata->got_bytes += result;
- }
-
- return result != -ECONNABORTED && rdata->got_bytes > 0 ?
- rdata->got_bytes : result;
-}
-
-static int
-cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
- struct cifs_readdata *rdata, unsigned int len)
-{
- return readpages_fill_pages(server, rdata, NULL, len);
-}
-
-static int
-cifs_readpages_copy_into_pages(struct TCP_Server_Info *server,
- struct cifs_readdata *rdata,
- struct iov_iter *iter)
-{
- return readpages_fill_pages(server, rdata, iter, iter->count);
-}
-
-static void cifs_readahead(struct readahead_control *ractl)
-{
- int rc;
- struct cifsFileInfo *open_file = ractl->file->private_data;
- struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(ractl->file);
- struct TCP_Server_Info *server;
- pid_t pid;
- unsigned int xid, nr_pages, last_batch_size = 0, cache_nr_pages = 0;
- pgoff_t next_cached = ULONG_MAX;
- bool caching = fscache_cookie_enabled(cifs_inode_cookie(ractl->mapping->host)) &&
- cifs_inode_cookie(ractl->mapping->host)->cache_priv;
- bool check_cache = caching;
-
- xid = get_xid();
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
- pid = open_file->pid;
- else
- pid = current->tgid;
-
- rc = 0;
- server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses);
-
- cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n",
- __func__, ractl->file, ractl->mapping, readahead_count(ractl));
-
- /*
- * Chop the readahead request up into rsize-sized read requests.
- */
- while ((nr_pages = readahead_count(ractl) - last_batch_size)) {
- unsigned int i, got, rsize;
- struct page *page;
- struct cifs_readdata *rdata;
- struct cifs_credits credits_on_stack;
- struct cifs_credits *credits = &credits_on_stack;
- pgoff_t index = readahead_index(ractl) + last_batch_size;
-
- /*
- * Find out if we have anything cached in the range of
- * interest, and if so, where the next chunk of cached data is.
- */
- if (caching) {
- if (check_cache) {
- rc = cifs_fscache_query_occupancy(
- ractl->mapping->host, index, nr_pages,
- &next_cached, &cache_nr_pages);
- if (rc < 0)
- caching = false;
- check_cache = false;
- }
-
- if (index == next_cached) {
- /*
- * TODO: Send a whole batch of pages to be read
- * by the cache.
- */
- struct folio *folio = readahead_folio(ractl);
-
- last_batch_size = folio_nr_pages(folio);
- if (cifs_readpage_from_fscache(ractl->mapping->host,
- &folio->page) < 0) {
- /*
- * TODO: Deal with cache read failure
- * here, but for the moment, delegate
- * that to readpage.
- */
- caching = false;
- }
- folio_unlock(folio);
- next_cached++;
- cache_nr_pages--;
- if (cache_nr_pages == 0)
- check_cache = true;
- continue;
- }
- }
-
- if (open_file->invalidHandle) {
- rc = cifs_reopen_file(open_file, true);
- if (rc) {
- if (rc == -EAGAIN)
- continue;
- break;
- }
- }
-
- if (cifs_sb->ctx->rsize == 0)
- cifs_sb->ctx->rsize =
- server->ops->negotiate_rsize(tlink_tcon(open_file->tlink),
- cifs_sb->ctx);
-
- rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
- &rsize, credits);
- if (rc)
- break;
- nr_pages = min_t(size_t, rsize / PAGE_SIZE, readahead_count(ractl));
- nr_pages = min_t(size_t, nr_pages, next_cached - index);
-
- /*
- * Give up immediately if rsize is too small to read an entire
- * page. The VFS will fall back to readpage. We should never
- * reach this point however since we set ra_pages to 0 when the
- * rsize is smaller than a cache page.
- */
- if (unlikely(!nr_pages)) {
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
-
- rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete);
- if (!rdata) {
- /* best to give up if we're out of mem */
- add_credits_and_wake_if(server, credits, 0);
- break;
- }
-
- got = __readahead_batch(ractl, rdata->pages, nr_pages);
- if (got != nr_pages) {
- pr_warn("__readahead_batch() returned %u/%u\n",
- got, nr_pages);
- nr_pages = got;
- }
-
- rdata->nr_pages = nr_pages;
- rdata->bytes = readahead_batch_length(ractl);
- rdata->cfile = cifsFileInfo_get(open_file);
- rdata->server = server;
- rdata->mapping = ractl->mapping;
- rdata->offset = readahead_pos(ractl);
- rdata->pid = pid;
- rdata->pagesz = PAGE_SIZE;
- rdata->tailsz = PAGE_SIZE;
- rdata->read_into_pages = cifs_readpages_read_into_pages;
- rdata->copy_into_pages = cifs_readpages_copy_into_pages;
- rdata->credits = credits_on_stack;
-
- rc = adjust_credits(server, &rdata->credits, rdata->bytes);
- if (!rc) {
- if (rdata->cfile->invalidHandle)
- rc = -EAGAIN;
- else
- rc = server->ops->async_readv(rdata);
- }
-
- if (rc) {
- add_credits_and_wake_if(server, &rdata->credits, 0);
- for (i = 0; i < rdata->nr_pages; i++) {
- page = rdata->pages[i];
- unlock_page(page);
- put_page(page);
- }
- /* Fallback to the readpage in error/reconnect cases */
- kref_put(&rdata->refcount, cifs_readdata_release);
- break;
- }
-
- kref_put(&rdata->refcount, cifs_readdata_release);
- last_batch_size = nr_pages;
- }
-
- free_xid(xid);
-}
-
-/*
- * cifs_readpage_worker must be called with the page pinned
- */
-static int cifs_readpage_worker(struct file *file, struct page *page,
- loff_t *poffset)
-{
- char *read_data;
- int rc;
-
- /* Is the page cached? */
- rc = cifs_readpage_from_fscache(file_inode(file), page);
- if (rc == 0)
- goto read_complete;
-
- read_data = kmap(page);
- /* for reads over a certain size could initiate async read ahead */
-
- rc = cifs_read(file, read_data, PAGE_SIZE, poffset);
-
- if (rc < 0)
- goto io_error;
- else
- cifs_dbg(FYI, "Bytes read %d\n", rc);
-
- /* we do not want atime to be less than mtime, it broke some apps */
- file_inode(file)->i_atime = current_time(file_inode(file));
- if (timespec64_compare(&(file_inode(file)->i_atime), &(file_inode(file)->i_mtime)))
- file_inode(file)->i_atime = file_inode(file)->i_mtime;
- else
- file_inode(file)->i_atime = current_time(file_inode(file));
-
- if (PAGE_SIZE > rc)
- memset(read_data + rc, 0, PAGE_SIZE - rc);
-
- flush_dcache_page(page);
- SetPageUptodate(page);
-
- /* send this page to the cache */
- cifs_readpage_to_fscache(file_inode(file), page);
-
- rc = 0;
-
-io_error:
- kunmap(page);
- unlock_page(page);
-
-read_complete:
- return rc;
-}
-
-static int cifs_read_folio(struct file *file, struct folio *folio)
-{
- struct page *page = &folio->page;
- loff_t offset = page_file_offset(page);
- int rc = -EACCES;
- unsigned int xid;
-
- xid = get_xid();
-
- if (file->private_data == NULL) {
- rc = -EBADF;
- free_xid(xid);
- return rc;
- }
-
- cifs_dbg(FYI, "read_folio %p at offset %d 0x%x\n",
- page, (int)offset, (int)offset);
-
- rc = cifs_readpage_worker(file, page, &offset);
-
- free_xid(xid);
- return rc;
-}
-
-static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
-{
- struct cifsFileInfo *open_file;
-
- spin_lock(&cifs_inode->open_file_lock);
- list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
- if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
- spin_unlock(&cifs_inode->open_file_lock);
- return 1;
- }
- }
- spin_unlock(&cifs_inode->open_file_lock);
- return 0;
-}
-
-/* We do not want to update the file size from server for inodes
- open for write - to avoid races with writepage extending
- the file - in the future we could consider allowing
- refreshing the inode only on increases in the file size
- but this is tricky to do without racing with writebehind
- page caching in the current Linux kernel design */
-bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
-{
- if (!cifsInode)
- return true;
-
- if (is_inode_writable(cifsInode)) {
- /* This inode is open for write at least once */
- struct cifs_sb_info *cifs_sb;
-
- cifs_sb = CIFS_SB(cifsInode->netfs.inode.i_sb);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
- /* since no page cache to corrupt on directio
- we can change size safely */
- return true;
- }
-
- if (i_size_read(&cifsInode->netfs.inode) < end_of_file)
- return true;
-
- return false;
- } else
- return true;
-}
-
-static int cifs_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len,
- struct page **pagep, void **fsdata)
-{
- int oncethru = 0;
- pgoff_t index = pos >> PAGE_SHIFT;
- loff_t offset = pos & (PAGE_SIZE - 1);
- loff_t page_start = pos & PAGE_MASK;
- loff_t i_size;
- struct page *page;
- int rc = 0;
-
- cifs_dbg(FYI, "write_begin from %lld len %d\n", (long long)pos, len);
-
-start:
- page = grab_cache_page_write_begin(mapping, index);
- if (!page) {
- rc = -ENOMEM;
- goto out;
- }
-
- if (PageUptodate(page))
- goto out;
-
- /*
- * If we write a full page it will be up to date, no need to read from
- * the server. If the write is short, we'll end up doing a sync write
- * instead.
- */
- if (len == PAGE_SIZE)
- goto out;
-
- /*
- * optimize away the read when we have an oplock, and we're not
- * expecting to use any of the data we'd be reading in. That
- * is, when the page lies beyond the EOF, or straddles the EOF
- * and the write will cover all of the existing data.
- */
- if (CIFS_CACHE_READ(CIFS_I(mapping->host))) {
- i_size = i_size_read(mapping->host);
- if (page_start >= i_size ||
- (offset == 0 && (pos + len) >= i_size)) {
- zero_user_segments(page, 0, offset,
- offset + len,
- PAGE_SIZE);
- /*
- * PageChecked means that the parts of the page
- * to which we're not writing are considered up
- * to date. Once the data is copied to the
- * page, it can be set uptodate.
- */
- SetPageChecked(page);
- goto out;
- }
- }
-
- if ((file->f_flags & O_ACCMODE) != O_WRONLY && !oncethru) {
- /*
- * might as well read a page, it is fast enough. If we get
- * an error, we don't need to return it. cifs_write_end will
- * do a sync write instead since PG_uptodate isn't set.
- */
- cifs_readpage_worker(file, page, &page_start);
- put_page(page);
- oncethru = 1;
- goto start;
- } else {
- /* we could try using another file handle if there is one -
- but how would we lock it to prevent close of that handle
- racing with this read? In any case
- this will be written out by write_end so is fine */
- }
-out:
- *pagep = page;
- return rc;
-}
-
-static bool cifs_release_folio(struct folio *folio, gfp_t gfp)
-{
- if (folio_test_private(folio))
- return 0;
- if (folio_test_fscache(folio)) {
- if (current_is_kswapd() || !(gfp & __GFP_FS))
- return false;
- folio_wait_fscache(folio);
- }
- fscache_note_page_release(cifs_inode_cookie(folio->mapping->host));
- return true;
-}
-
-static void cifs_invalidate_folio(struct folio *folio, size_t offset,
- size_t length)
-{
- folio_wait_fscache(folio);
-}
-
-static int cifs_launder_folio(struct folio *folio)
-{
- int rc = 0;
- loff_t range_start = folio_pos(folio);
- loff_t range_end = range_start + folio_size(folio);
- struct writeback_control wbc = {
- .sync_mode = WB_SYNC_ALL,
- .nr_to_write = 0,
- .range_start = range_start,
- .range_end = range_end,
- };
-
- cifs_dbg(FYI, "Launder page: %lu\n", folio->index);
-
- if (folio_clear_dirty_for_io(folio))
- rc = cifs_writepage_locked(&folio->page, &wbc);
-
- folio_wait_fscache(folio);
- return rc;
-}
-
-void cifs_oplock_break(struct work_struct *work)
-{
- struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
- oplock_break);
- struct inode *inode = d_inode(cfile->dentry);
- struct cifsInodeInfo *cinode = CIFS_I(inode);
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- struct TCP_Server_Info *server = tcon->ses->server;
- int rc = 0;
- bool purge_cache = false, oplock_break_cancelled;
- __u64 persistent_fid, volatile_fid;
- __u16 net_fid;
-
- wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
- TASK_UNINTERRUPTIBLE);
-
- server->ops->downgrade_oplock(server, cinode, cfile->oplock_level,
- cfile->oplock_epoch, &purge_cache);
-
- if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) &&
- cifs_has_mand_locks(cinode)) {
- cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n",
- inode);
- cinode->oplock = 0;
- }
-
- if (inode && S_ISREG(inode->i_mode)) {
- if (CIFS_CACHE_READ(cinode))
- break_lease(inode, O_RDONLY);
- else
- break_lease(inode, O_WRONLY);
- rc = filemap_fdatawrite(inode->i_mapping);
- if (!CIFS_CACHE_READ(cinode) || purge_cache) {
- rc = filemap_fdatawait(inode->i_mapping);
- mapping_set_error(inode->i_mapping, rc);
- cifs_zap_mapping(inode);
- }
- cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
- if (CIFS_CACHE_WRITE(cinode))
- goto oplock_break_ack;
- }
-
- rc = cifs_push_locks(cfile);
- if (rc)
- cifs_dbg(VFS, "Push locks rc = %d\n", rc);
-
-oplock_break_ack:
- /*
- * When oplock break is received and there are no active
- * file handles but cached, then schedule deferred close immediately.
- * So, new open will not use cached handle.
- */
-
- if (!CIFS_CACHE_HANDLE(cinode) && !list_empty(&cinode->deferred_closes))
- cifs_close_deferred_file(cinode);
-
- persistent_fid = cfile->fid.persistent_fid;
- volatile_fid = cfile->fid.volatile_fid;
- net_fid = cfile->fid.netfid;
- oplock_break_cancelled = cfile->oplock_break_cancelled;
-
- _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
- /*
- * releasing stale oplock after recent reconnect of smb session using
- * a now incorrect file handle is not a data integrity issue but do
- * not bother sending an oplock release if session to server still is
- * disconnected since oplock already released by the server
- */
- if (!oplock_break_cancelled) {
- /* check for server null since can race with kill_sb calling tree disconnect */
- if (tcon->ses && tcon->ses->server) {
- rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid,
- volatile_fid, net_fid, cinode);
- cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
- } else
- pr_warn_once("lease break not sent for unmounted share\n");
- }
-
- cifs_done_oplock_break(cinode);
-}
-
-/*
- * The presence of cifs_direct_io() in the address space ops vector
- * allowes open() O_DIRECT flags which would have failed otherwise.
- *
- * In the non-cached mode (mount with cache=none), we shunt off direct read and write requests
- * so this method should never be called.
- *
- * Direct IO is not yet supported in the cached mode.
- */
-static ssize_t
-cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter)
-{
- /*
- * FIXME
- * Eventually need to support direct IO for non forcedirectio mounts
- */
- return -EINVAL;
-}
-
-static int cifs_swap_activate(struct swap_info_struct *sis,
- struct file *swap_file, sector_t *span)
-{
- struct cifsFileInfo *cfile = swap_file->private_data;
- struct inode *inode = swap_file->f_mapping->host;
- unsigned long blocks;
- long long isize;
-
- cifs_dbg(FYI, "swap activate\n");
-
- if (!swap_file->f_mapping->a_ops->swap_rw)
- /* Cannot support swap */
- return -EINVAL;
-
- spin_lock(&inode->i_lock);
- blocks = inode->i_blocks;
- isize = inode->i_size;
- spin_unlock(&inode->i_lock);
- if (blocks*512 < isize) {
- pr_warn("swap activate: swapfile has holes\n");
- return -EINVAL;
- }
- *span = sis->pages;
-
- pr_warn_once("Swap support over SMB3 is experimental\n");
-
- /*
- * TODO: consider adding ACL (or documenting how) to prevent other
- * users (on this or other systems) from reading it
- */
-
-
- /* TODO: add sk_set_memalloc(inet) or similar */
-
- if (cfile)
- cfile->swapfile = true;
- /*
- * TODO: Since file already open, we can't open with DENY_ALL here
- * but we could add call to grab a byte range lock to prevent others
- * from reading or writing the file
- */
-
- sis->flags |= SWP_FS_OPS;
- return add_swap_extent(sis, 0, sis->max, 0);
-}
-
-static void cifs_swap_deactivate(struct file *file)
-{
- struct cifsFileInfo *cfile = file->private_data;
-
- cifs_dbg(FYI, "swap deactivate\n");
-
- /* TODO: undo sk_set_memalloc(inet) will eventually be needed */
-
- if (cfile)
- cfile->swapfile = false;
-
- /* do we need to unpin (or unlock) the file */
-}
-
-/*
- * Mark a page as having been made dirty and thus needing writeback. We also
- * need to pin the cache object to write back to.
- */
-#ifdef CONFIG_CIFS_FSCACHE
-static bool cifs_dirty_folio(struct address_space *mapping, struct folio *folio)
-{
- return fscache_dirty_folio(mapping, folio,
- cifs_inode_cookie(mapping->host));
-}
-#else
-#define cifs_dirty_folio filemap_dirty_folio
-#endif
-
-const struct address_space_operations cifs_addr_ops = {
- .read_folio = cifs_read_folio,
- .readahead = cifs_readahead,
- .writepage = cifs_writepage,
- .writepages = cifs_writepages,
- .write_begin = cifs_write_begin,
- .write_end = cifs_write_end,
- .dirty_folio = cifs_dirty_folio,
- .release_folio = cifs_release_folio,
- .direct_IO = cifs_direct_io,
- .invalidate_folio = cifs_invalidate_folio,
- .launder_folio = cifs_launder_folio,
- /*
- * TODO: investigate and if useful we could add an cifs_migratePage
- * helper (under an CONFIG_MIGRATION) in the future, and also
- * investigate and add an is_dirty_writeback helper if needed
- */
- .swap_activate = cifs_swap_activate,
- .swap_deactivate = cifs_swap_deactivate,
-};
-
-/*
- * cifs_readahead requires the server to support a buffer large enough to
- * contain the header plus one complete page of data. Otherwise, we need
- * to leave cifs_readahead out of the address space operations.
- */
-const struct address_space_operations cifs_addr_ops_smallbuf = {
- .read_folio = cifs_read_folio,
- .writepage = cifs_writepage,
- .writepages = cifs_writepages,
- .write_begin = cifs_write_begin,
- .write_end = cifs_write_end,
- .dirty_folio = cifs_dirty_folio,
- .release_folio = cifs_release_folio,
- .invalidate_folio = cifs_invalidate_folio,
- .launder_folio = cifs_launder_folio,
-};
diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c
deleted file mode 100644
index e2e2ef0fa9a0..000000000000
--- a/fs/cifs/fs_context.c
+++ /dev/null
@@ -1,1773 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2020, Microsoft Corporation.
- *
- * Author(s): Steve French <stfrench@microsoft.com>
- * David Howells <dhowells@redhat.com>
- */
-
-/*
-#include <linux/module.h>
-#include <linux/nsproxy.h>
-#include <linux/slab.h>
-#include <linux/magic.h>
-#include <linux/security.h>
-#include <net/net_namespace.h>
-#ifdef CONFIG_CIFS_DFS_UPCALL
-#include "dfs_cache.h"
-#endif
-*/
-
-#include <linux/ctype.h>
-#include <linux/fs_context.h>
-#include <linux/fs_parser.h>
-#include <linux/fs.h>
-#include <linux/mount.h>
-#include <linux/parser.h>
-#include <linux/utsname.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_unicode.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "ntlmssp.h"
-#include "nterr.h"
-#include "rfc1002pdu.h"
-#include "fs_context.h"
-
-static DEFINE_MUTEX(cifs_mount_mutex);
-
-static const match_table_t cifs_smb_version_tokens = {
- { Smb_1, SMB1_VERSION_STRING },
- { Smb_20, SMB20_VERSION_STRING},
- { Smb_21, SMB21_VERSION_STRING },
- { Smb_30, SMB30_VERSION_STRING },
- { Smb_302, SMB302_VERSION_STRING },
- { Smb_302, ALT_SMB302_VERSION_STRING },
- { Smb_311, SMB311_VERSION_STRING },
- { Smb_311, ALT_SMB311_VERSION_STRING },
- { Smb_3any, SMB3ANY_VERSION_STRING },
- { Smb_default, SMBDEFAULT_VERSION_STRING },
- { Smb_version_err, NULL }
-};
-
-static const match_table_t cifs_secflavor_tokens = {
- { Opt_sec_krb5, "krb5" },
- { Opt_sec_krb5i, "krb5i" },
- { Opt_sec_krb5p, "krb5p" },
- { Opt_sec_ntlmsspi, "ntlmsspi" },
- { Opt_sec_ntlmssp, "ntlmssp" },
- { Opt_sec_ntlmv2, "nontlm" },
- { Opt_sec_ntlmv2, "ntlmv2" },
- { Opt_sec_ntlmv2i, "ntlmv2i" },
- { Opt_sec_none, "none" },
-
- { Opt_sec_err, NULL }
-};
-
-const struct fs_parameter_spec smb3_fs_parameters[] = {
- /* Mount options that take no arguments */
- fsparam_flag_no("user_xattr", Opt_user_xattr),
- fsparam_flag_no("forceuid", Opt_forceuid),
- fsparam_flag_no("multichannel", Opt_multichannel),
- fsparam_flag_no("forcegid", Opt_forcegid),
- fsparam_flag("noblocksend", Opt_noblocksend),
- fsparam_flag("noautotune", Opt_noautotune),
- fsparam_flag("nolease", Opt_nolease),
- fsparam_flag_no("hard", Opt_hard),
- fsparam_flag_no("soft", Opt_soft),
- fsparam_flag_no("perm", Opt_perm),
- fsparam_flag("nodelete", Opt_nodelete),
- fsparam_flag_no("mapposix", Opt_mapposix),
- fsparam_flag("mapchars", Opt_mapchars),
- fsparam_flag("nomapchars", Opt_nomapchars),
- fsparam_flag_no("sfu", Opt_sfu),
- fsparam_flag("nodfs", Opt_nodfs),
- fsparam_flag_no("posixpaths", Opt_posixpaths),
- fsparam_flag_no("unix", Opt_unix),
- fsparam_flag_no("linux", Opt_unix),
- fsparam_flag_no("posix", Opt_unix),
- fsparam_flag("nocase", Opt_nocase),
- fsparam_flag("ignorecase", Opt_nocase),
- fsparam_flag_no("brl", Opt_brl),
- fsparam_flag_no("handlecache", Opt_handlecache),
- fsparam_flag("forcemandatorylock", Opt_forcemandatorylock),
- fsparam_flag("forcemand", Opt_forcemandatorylock),
- fsparam_flag("setuidfromacl", Opt_setuidfromacl),
- fsparam_flag("idsfromsid", Opt_setuidfromacl),
- fsparam_flag_no("setuids", Opt_setuids),
- fsparam_flag_no("dynperm", Opt_dynperm),
- fsparam_flag_no("intr", Opt_intr),
- fsparam_flag_no("strictsync", Opt_strictsync),
- fsparam_flag_no("serverino", Opt_serverino),
- fsparam_flag("rwpidforward", Opt_rwpidforward),
- fsparam_flag("cifsacl", Opt_cifsacl),
- fsparam_flag_no("acl", Opt_acl),
- fsparam_flag("locallease", Opt_locallease),
- fsparam_flag("sign", Opt_sign),
- fsparam_flag("ignore_signature", Opt_ignore_signature),
- fsparam_flag("signloosely", Opt_ignore_signature),
- fsparam_flag("seal", Opt_seal),
- fsparam_flag("noac", Opt_noac),
- fsparam_flag("fsc", Opt_fsc),
- fsparam_flag("mfsymlinks", Opt_mfsymlinks),
- fsparam_flag("multiuser", Opt_multiuser),
- fsparam_flag("sloppy", Opt_sloppy),
- fsparam_flag("nosharesock", Opt_nosharesock),
- fsparam_flag_no("persistenthandles", Opt_persistent),
- fsparam_flag_no("resilienthandles", Opt_resilient),
- fsparam_flag_no("tcpnodelay", Opt_tcp_nodelay),
- fsparam_flag("nosparse", Opt_nosparse),
- fsparam_flag("domainauto", Opt_domainauto),
- fsparam_flag("rdma", Opt_rdma),
- fsparam_flag("modesid", Opt_modesid),
- fsparam_flag("modefromsid", Opt_modesid),
- fsparam_flag("rootfs", Opt_rootfs),
- fsparam_flag("compress", Opt_compress),
- fsparam_flag("witness", Opt_witness),
-
- /* Mount options which take numeric value */
- fsparam_u32("backupuid", Opt_backupuid),
- fsparam_u32("backupgid", Opt_backupgid),
- fsparam_u32("uid", Opt_uid),
- fsparam_u32("cruid", Opt_cruid),
- fsparam_u32("gid", Opt_gid),
- fsparam_u32("file_mode", Opt_file_mode),
- fsparam_u32("dirmode", Opt_dirmode),
- fsparam_u32("dir_mode", Opt_dirmode),
- fsparam_u32("port", Opt_port),
- fsparam_u32("min_enc_offload", Opt_min_enc_offload),
- fsparam_u32("esize", Opt_min_enc_offload),
- fsparam_u32("bsize", Opt_blocksize),
- fsparam_u32("rasize", Opt_rasize),
- fsparam_u32("rsize", Opt_rsize),
- fsparam_u32("wsize", Opt_wsize),
- fsparam_u32("actimeo", Opt_actimeo),
- fsparam_u32("acdirmax", Opt_acdirmax),
- fsparam_u32("acregmax", Opt_acregmax),
- fsparam_u32("closetimeo", Opt_closetimeo),
- fsparam_u32("echo_interval", Opt_echo_interval),
- fsparam_u32("max_credits", Opt_max_credits),
- fsparam_u32("handletimeout", Opt_handletimeout),
- fsparam_u64("snapshot", Opt_snapshot),
- fsparam_u32("max_channels", Opt_max_channels),
-
- /* Mount options which take string value */
- fsparam_string("source", Opt_source),
- fsparam_string("user", Opt_user),
- fsparam_string("username", Opt_user),
- fsparam_string("pass", Opt_pass),
- fsparam_string("password", Opt_pass),
- fsparam_string("ip", Opt_ip),
- fsparam_string("addr", Opt_ip),
- fsparam_string("domain", Opt_domain),
- fsparam_string("dom", Opt_domain),
- fsparam_string("srcaddr", Opt_srcaddr),
- fsparam_string("iocharset", Opt_iocharset),
- fsparam_string("netbiosname", Opt_netbiosname),
- fsparam_string("servern", Opt_servern),
- fsparam_string("ver", Opt_ver),
- fsparam_string("vers", Opt_vers),
- fsparam_string("sec", Opt_sec),
- fsparam_string("cache", Opt_cache),
-
- /* Arguments that should be ignored */
- fsparam_flag("guest", Opt_ignore),
- fsparam_flag("noatime", Opt_ignore),
- fsparam_flag("relatime", Opt_ignore),
- fsparam_flag("_netdev", Opt_ignore),
- fsparam_flag_no("suid", Opt_ignore),
- fsparam_flag_no("exec", Opt_ignore),
- fsparam_flag_no("dev", Opt_ignore),
- fsparam_flag_no("mand", Opt_ignore),
- fsparam_flag_no("auto", Opt_ignore),
- fsparam_string("cred", Opt_ignore),
- fsparam_string("credentials", Opt_ignore),
- /*
- * UNC and prefixpath is now extracted from Opt_source
- * in the new mount API so we can just ignore them going forward.
- */
- fsparam_string("unc", Opt_ignore),
- fsparam_string("prefixpath", Opt_ignore),
- {}
-};
-
-static int
-cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
-{
-
- substring_t args[MAX_OPT_ARGS];
-
- /*
- * With mount options, the last one should win. Reset any existing
- * settings back to default.
- */
- ctx->sectype = Unspecified;
- ctx->sign = false;
-
- switch (match_token(value, cifs_secflavor_tokens, args)) {
- case Opt_sec_krb5p:
- cifs_errorf(fc, "sec=krb5p is not supported!\n");
- return 1;
- case Opt_sec_krb5i:
- ctx->sign = true;
- fallthrough;
- case Opt_sec_krb5:
- ctx->sectype = Kerberos;
- break;
- case Opt_sec_ntlmsspi:
- ctx->sign = true;
- fallthrough;
- case Opt_sec_ntlmssp:
- ctx->sectype = RawNTLMSSP;
- break;
- case Opt_sec_ntlmv2i:
- ctx->sign = true;
- fallthrough;
- case Opt_sec_ntlmv2:
- ctx->sectype = NTLMv2;
- break;
- case Opt_sec_none:
- ctx->nullauth = 1;
- break;
- default:
- cifs_errorf(fc, "bad security option: %s\n", value);
- return 1;
- }
-
- return 0;
-}
-
-static const match_table_t cifs_cacheflavor_tokens = {
- { Opt_cache_loose, "loose" },
- { Opt_cache_strict, "strict" },
- { Opt_cache_none, "none" },
- { Opt_cache_ro, "ro" },
- { Opt_cache_rw, "singleclient" },
- { Opt_cache_err, NULL }
-};
-
-static int
-cifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
-{
- substring_t args[MAX_OPT_ARGS];
-
- switch (match_token(value, cifs_cacheflavor_tokens, args)) {
- case Opt_cache_loose:
- ctx->direct_io = false;
- ctx->strict_io = false;
- ctx->cache_ro = false;
- ctx->cache_rw = false;
- break;
- case Opt_cache_strict:
- ctx->direct_io = false;
- ctx->strict_io = true;
- ctx->cache_ro = false;
- ctx->cache_rw = false;
- break;
- case Opt_cache_none:
- ctx->direct_io = true;
- ctx->strict_io = false;
- ctx->cache_ro = false;
- ctx->cache_rw = false;
- break;
- case Opt_cache_ro:
- ctx->direct_io = false;
- ctx->strict_io = false;
- ctx->cache_ro = true;
- ctx->cache_rw = false;
- break;
- case Opt_cache_rw:
- ctx->direct_io = false;
- ctx->strict_io = false;
- ctx->cache_ro = false;
- ctx->cache_rw = true;
- break;
- default:
- cifs_errorf(fc, "bad cache= option: %s\n", value);
- return 1;
- }
- return 0;
-}
-
-#define DUP_CTX_STR(field) \
-do { \
- if (ctx->field) { \
- new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC); \
- if (new_ctx->field == NULL) { \
- smb3_cleanup_fs_context_contents(new_ctx); \
- return -ENOMEM; \
- } \
- } \
-} while (0)
-
-int
-smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)
-{
- memcpy(new_ctx, ctx, sizeof(*ctx));
- new_ctx->prepath = NULL;
- new_ctx->mount_options = NULL;
- new_ctx->nodename = NULL;
- new_ctx->username = NULL;
- new_ctx->password = NULL;
- new_ctx->server_hostname = NULL;
- new_ctx->domainname = NULL;
- new_ctx->UNC = NULL;
- new_ctx->source = NULL;
- new_ctx->iocharset = NULL;
- /*
- * Make sure to stay in sync with smb3_cleanup_fs_context_contents()
- */
- DUP_CTX_STR(prepath);
- DUP_CTX_STR(mount_options);
- DUP_CTX_STR(username);
- DUP_CTX_STR(password);
- DUP_CTX_STR(server_hostname);
- DUP_CTX_STR(UNC);
- DUP_CTX_STR(source);
- DUP_CTX_STR(domainname);
- DUP_CTX_STR(nodename);
- DUP_CTX_STR(iocharset);
-
- return 0;
-}
-
-static int
-cifs_parse_smb_version(struct fs_context *fc, char *value, struct smb3_fs_context *ctx, bool is_smb3)
-{
- substring_t args[MAX_OPT_ARGS];
-
- switch (match_token(value, cifs_smb_version_tokens, args)) {
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- case Smb_1:
- if (disable_legacy_dialects) {
- cifs_errorf(fc, "mount with legacy dialect disabled\n");
- return 1;
- }
- if (is_smb3) {
- cifs_errorf(fc, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
- return 1;
- }
- cifs_errorf(fc, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
- ctx->ops = &smb1_operations;
- ctx->vals = &smb1_values;
- break;
- case Smb_20:
- if (disable_legacy_dialects) {
- cifs_errorf(fc, "mount with legacy dialect disabled\n");
- return 1;
- }
- if (is_smb3) {
- cifs_errorf(fc, "vers=2.0 not permitted when mounting with smb3\n");
- return 1;
- }
- ctx->ops = &smb20_operations;
- ctx->vals = &smb20_values;
- break;
-#else
- case Smb_1:
- cifs_errorf(fc, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
- return 1;
- case Smb_20:
- cifs_errorf(fc, "vers=2.0 mount not permitted when legacy dialects disabled\n");
- return 1;
-#endif /* CIFS_ALLOW_INSECURE_LEGACY */
- case Smb_21:
- ctx->ops = &smb21_operations;
- ctx->vals = &smb21_values;
- break;
- case Smb_30:
- ctx->ops = &smb30_operations;
- ctx->vals = &smb30_values;
- break;
- case Smb_302:
- ctx->ops = &smb30_operations; /* currently identical with 3.0 */
- ctx->vals = &smb302_values;
- break;
- case Smb_311:
- ctx->ops = &smb311_operations;
- ctx->vals = &smb311_values;
- break;
- case Smb_3any:
- ctx->ops = &smb30_operations; /* currently identical with 3.0 */
- ctx->vals = &smb3any_values;
- break;
- case Smb_default:
- ctx->ops = &smb30_operations;
- ctx->vals = &smbdefault_values;
- break;
- default:
- cifs_errorf(fc, "Unknown vers= option specified: %s\n", value);
- return 1;
- }
- return 0;
-}
-
-int smb3_parse_opt(const char *options, const char *key, char **val)
-{
- int rc = -ENOENT;
- char *opts, *orig, *p;
-
- orig = opts = kstrdup(options, GFP_KERNEL);
- if (!opts)
- return -ENOMEM;
-
- while ((p = strsep(&opts, ","))) {
- char *nval;
-
- if (!*p)
- continue;
- if (strncasecmp(p, key, strlen(key)))
- continue;
- nval = strchr(p, '=');
- if (nval) {
- if (nval == p)
- continue;
- *nval++ = 0;
- *val = kstrdup(nval, GFP_KERNEL);
- rc = !*val ? -ENOMEM : 0;
- goto out;
- }
- }
-out:
- kfree(orig);
- return rc;
-}
-
-/*
- * Remove duplicate path delimiters. Windows is supposed to do that
- * but there are some bugs that prevent rename from working if there are
- * multiple delimiters.
- *
- * Returns a sanitized duplicate of @path. @gfp indicates the GFP_* flags
- * for kstrdup.
- * The caller is responsible for freeing the original.
- */
-#define IS_DELIM(c) ((c) == '/' || (c) == '\\')
-char *cifs_sanitize_prepath(char *prepath, gfp_t gfp)
-{
- char *cursor1 = prepath, *cursor2 = prepath;
-
- /* skip all prepended delimiters */
- while (IS_DELIM(*cursor1))
- cursor1++;
-
- /* copy the first letter */
- *cursor2 = *cursor1;
-
- /* copy the remainder... */
- while (*(cursor1++)) {
- /* ... skipping all duplicated delimiters */
- if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2))
- continue;
- *(++cursor2) = *cursor1;
- }
-
- /* if the last character is a delimiter, skip it */
- if (IS_DELIM(*(cursor2 - 1)))
- cursor2--;
-
- *(cursor2) = '\0';
- return kstrdup(prepath, gfp);
-}
-
-/*
- * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath
- * fields with the result. Returns 0 on success and an error otherwise
- * (e.g. ENOMEM or EINVAL)
- */
-int
-smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
-{
- char *pos;
- const char *delims = "/\\";
- size_t len;
-
- if (unlikely(!devname || !*devname)) {
- cifs_dbg(VFS, "Device name not specified\n");
- return -EINVAL;
- }
-
- /* make sure we have a valid UNC double delimiter prefix */
- len = strspn(devname, delims);
- if (len != 2)
- return -EINVAL;
-
- /* find delimiter between host and sharename */
- pos = strpbrk(devname + 2, delims);
- if (!pos)
- return -EINVAL;
-
- /* record the server hostname */
- kfree(ctx->server_hostname);
- ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL);
- if (!ctx->server_hostname)
- return -ENOMEM;
-
- /* skip past delimiter */
- ++pos;
-
- /* now go until next delimiter or end of string */
- len = strcspn(pos, delims);
-
- /* move "pos" up to delimiter or NULL */
- pos += len;
- kfree(ctx->UNC);
- ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
- if (!ctx->UNC)
- return -ENOMEM;
-
- convert_delimiter(ctx->UNC, '\\');
-
- /* skip any delimiter */
- if (*pos == '/' || *pos == '\\')
- pos++;
-
- kfree(ctx->prepath);
- ctx->prepath = NULL;
-
- /* If pos is NULL then no prepath */
- if (!*pos)
- return 0;
-
- ctx->prepath = cifs_sanitize_prepath(pos, GFP_KERNEL);
- if (!ctx->prepath)
- return -ENOMEM;
-
- return 0;
-}
-
-static void smb3_fs_context_free(struct fs_context *fc);
-static int smb3_fs_context_parse_param(struct fs_context *fc,
- struct fs_parameter *param);
-static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
- void *data);
-static int smb3_get_tree(struct fs_context *fc);
-static int smb3_reconfigure(struct fs_context *fc);
-
-static const struct fs_context_operations smb3_fs_context_ops = {
- .free = smb3_fs_context_free,
- .parse_param = smb3_fs_context_parse_param,
- .parse_monolithic = smb3_fs_context_parse_monolithic,
- .get_tree = smb3_get_tree,
- .reconfigure = smb3_reconfigure,
-};
-
-/*
- * Parse a monolithic block of data from sys_mount().
- * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data
- * @ctx: The superblock configuration to fill in.
- * @data: The data to parse
- *
- * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be
- * called from the ->monolithic_mount_data() fs_context operation.
- *
- * Returns 0 on success or the error returned by the ->parse_option() fs_context
- * operation on failure.
- */
-static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
- void *data)
-{
- struct smb3_fs_context *ctx = smb3_fc2context(fc);
- char *options = data, *key;
- int ret = 0;
-
- if (!options)
- return 0;
-
- ctx->mount_options = kstrdup(data, GFP_KERNEL);
- if (ctx->mount_options == NULL)
- return -ENOMEM;
-
- ret = security_sb_eat_lsm_opts(options, &fc->security);
- if (ret)
- return ret;
-
- /* BB Need to add support for sep= here TBD */
- while ((key = strsep(&options, ",")) != NULL) {
- size_t len;
- char *value;
-
- if (*key == 0)
- break;
-
- /* Check if following character is the deliminator If yes,
- * we have encountered a double deliminator reset the NULL
- * character to the deliminator
- */
- while (options && options[0] == ',') {
- len = strlen(key);
- strcpy(key + len, options);
- options = strchr(options, ',');
- if (options)
- *options++ = 0;
- }
-
-
- len = 0;
- value = strchr(key, '=');
- if (value) {
- if (value == key)
- continue;
- *value++ = 0;
- len = strlen(value);
- }
-
- ret = vfs_parse_fs_string(fc, key, value, len);
- if (ret < 0)
- break;
- }
-
- return ret;
-}
-
-/*
- * Validate the preparsed information in the config.
- */
-static int smb3_fs_context_validate(struct fs_context *fc)
-{
- struct smb3_fs_context *ctx = smb3_fc2context(fc);
-
- if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
- cifs_errorf(fc, "SMB Direct requires Version >=3.0\n");
- return -EOPNOTSUPP;
- }
-
-#ifndef CONFIG_KEYS
- /* Muliuser mounts require CONFIG_KEYS support */
- if (ctx->multiuser) {
- cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
- return -1;
- }
-#endif
-
- if (ctx->got_version == false)
- pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n");
-
-
- if (!ctx->UNC) {
- cifs_errorf(fc, "CIFS mount error: No usable UNC path provided in device string!\n");
- return -1;
- }
-
- /* make sure UNC has a share name */
- if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
- cifs_errorf(fc, "Malformed UNC. Unable to find share name.\n");
- return -ENOENT;
- }
-
- if (!ctx->got_ip) {
- int len;
- const char *slash;
-
- /* No ip= option specified? Try to get it from UNC */
- /* Use the address part of the UNC. */
- slash = strchr(&ctx->UNC[2], '\\');
- len = slash - &ctx->UNC[2];
- if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
- &ctx->UNC[2], len)) {
- pr_err("Unable to determine destination address\n");
- return -EHOSTUNREACH;
- }
- }
-
- /* set the port that we got earlier */
- cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
-
- if (ctx->override_uid && !ctx->uid_specified) {
- ctx->override_uid = 0;
- pr_notice("ignoring forceuid mount option specified with no uid= option\n");
- }
-
- if (ctx->override_gid && !ctx->gid_specified) {
- ctx->override_gid = 0;
- pr_notice("ignoring forcegid mount option specified with no gid= option\n");
- }
-
- return 0;
-}
-
-static int smb3_get_tree_common(struct fs_context *fc)
-{
- struct smb3_fs_context *ctx = smb3_fc2context(fc);
- struct dentry *root;
- int rc = 0;
-
- root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);
- if (IS_ERR(root))
- return PTR_ERR(root);
-
- fc->root = root;
-
- return rc;
-}
-
-/*
- * Create an SMB3 superblock from the parameters passed.
- */
-static int smb3_get_tree(struct fs_context *fc)
-{
- int err = smb3_fs_context_validate(fc);
- int ret;
-
- if (err)
- return err;
- mutex_lock(&cifs_mount_mutex);
- ret = smb3_get_tree_common(fc);
- mutex_unlock(&cifs_mount_mutex);
- return ret;
-}
-
-static void smb3_fs_context_free(struct fs_context *fc)
-{
- struct smb3_fs_context *ctx = smb3_fc2context(fc);
-
- smb3_cleanup_fs_context(ctx);
-}
-
-/*
- * Compare the old and new proposed context during reconfigure
- * and check if the changes are compatible.
- */
-static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
- struct smb3_fs_context *new_ctx,
- struct smb3_fs_context *old_ctx)
-{
- if (new_ctx->posix_paths != old_ctx->posix_paths) {
- cifs_errorf(fc, "can not change posixpaths during remount\n");
- return -EINVAL;
- }
- if (new_ctx->sectype != old_ctx->sectype) {
- cifs_errorf(fc, "can not change sec during remount\n");
- return -EINVAL;
- }
- if (new_ctx->multiuser != old_ctx->multiuser) {
- cifs_errorf(fc, "can not change multiuser during remount\n");
- return -EINVAL;
- }
- if (new_ctx->UNC &&
- (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {
- cifs_errorf(fc, "can not change UNC during remount\n");
- return -EINVAL;
- }
- if (new_ctx->username &&
- (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {
- cifs_errorf(fc, "can not change username during remount\n");
- return -EINVAL;
- }
- if (new_ctx->password &&
- (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
- cifs_errorf(fc, "can not change password during remount\n");
- return -EINVAL;
- }
- if (new_ctx->domainname &&
- (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
- cifs_errorf(fc, "can not change domainname during remount\n");
- return -EINVAL;
- }
- if (strcmp(new_ctx->workstation_name, old_ctx->workstation_name)) {
- cifs_errorf(fc, "can not change workstation_name during remount\n");
- return -EINVAL;
- }
- if (new_ctx->nodename &&
- (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
- cifs_errorf(fc, "can not change nodename during remount\n");
- return -EINVAL;
- }
- if (new_ctx->iocharset &&
- (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {
- cifs_errorf(fc, "can not change iocharset during remount\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-#define STEAL_STRING(cifs_sb, ctx, field) \
-do { \
- kfree(ctx->field); \
- ctx->field = cifs_sb->ctx->field; \
- cifs_sb->ctx->field = NULL; \
-} while (0)
-
-#define STEAL_STRING_SENSITIVE(cifs_sb, ctx, field) \
-do { \
- kfree_sensitive(ctx->field); \
- ctx->field = cifs_sb->ctx->field; \
- cifs_sb->ctx->field = NULL; \
-} while (0)
-
-static int smb3_reconfigure(struct fs_context *fc)
-{
- struct smb3_fs_context *ctx = smb3_fc2context(fc);
- struct dentry *root = fc->root;
- struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
- int rc;
-
- rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx);
- if (rc)
- return rc;
-
- /*
- * We can not change UNC/username/password/domainname/
- * workstation_name/nodename/iocharset
- * during reconnect so ignore what we have in the new context and
- * just use what we already have in cifs_sb->ctx.
- */
- STEAL_STRING(cifs_sb, ctx, UNC);
- STEAL_STRING(cifs_sb, ctx, source);
- STEAL_STRING(cifs_sb, ctx, username);
- STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
- STEAL_STRING(cifs_sb, ctx, domainname);
- STEAL_STRING(cifs_sb, ctx, nodename);
- STEAL_STRING(cifs_sb, ctx, iocharset);
-
- /* if rsize or wsize not passed in on remount, use previous values */
- if (ctx->rsize == 0)
- ctx->rsize = cifs_sb->ctx->rsize;
- if (ctx->wsize == 0)
- ctx->wsize = cifs_sb->ctx->wsize;
-
-
- smb3_cleanup_fs_context_contents(cifs_sb->ctx);
- rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
- smb3_update_mnt_flags(cifs_sb);
-#ifdef CONFIG_CIFS_DFS_UPCALL
- if (!rc)
- rc = dfs_cache_remount_fs(cifs_sb);
-#endif
-
- return rc;
-}
-
-static int smb3_fs_context_parse_param(struct fs_context *fc,
- struct fs_parameter *param)
-{
- struct fs_parse_result result;
- struct smb3_fs_context *ctx = smb3_fc2context(fc);
- int i, opt;
- bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
- bool skip_parsing = false;
- kuid_t uid;
- kgid_t gid;
-
- cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
-
- /*
- * fs_parse can not handle string options with an empty value so
- * we will need special handling of them.
- */
- if (param->type == fs_value_is_string && param->string[0] == 0) {
- if (!strcmp("pass", param->key) || !strcmp("password", param->key)) {
- skip_parsing = true;
- opt = Opt_pass;
- } else if (!strcmp("user", param->key) || !strcmp("username", param->key)) {
- skip_parsing = true;
- opt = Opt_user;
- }
- }
-
- if (!skip_parsing) {
- opt = fs_parse(fc, smb3_fs_parameters, param, &result);
- if (opt < 0)
- return ctx->sloppy ? 1 : opt;
- }
-
- switch (opt) {
- case Opt_compress:
- ctx->compression = UNKNOWN_TYPE;
- cifs_dbg(VFS,
- "SMB3 compression support is experimental\n");
- break;
- case Opt_nodfs:
- ctx->nodfs = 1;
- break;
- case Opt_hard:
- if (result.negated)
- ctx->retry = 0;
- else
- ctx->retry = 1;
- break;
- case Opt_soft:
- if (result.negated)
- ctx->retry = 1;
- else
- ctx->retry = 0;
- break;
- case Opt_mapposix:
- if (result.negated)
- ctx->remap = false;
- else {
- ctx->remap = true;
- ctx->sfu_remap = false; /* disable SFU mapping */
- }
- break;
- case Opt_mapchars:
- if (result.negated)
- ctx->sfu_remap = false;
- else {
- ctx->sfu_remap = true;
- ctx->remap = false; /* disable SFM (mapposix) mapping */
- }
- break;
- case Opt_user_xattr:
- if (result.negated)
- ctx->no_xattr = 1;
- else
- ctx->no_xattr = 0;
- break;
- case Opt_forceuid:
- if (result.negated)
- ctx->override_uid = 0;
- else
- ctx->override_uid = 1;
- break;
- case Opt_forcegid:
- if (result.negated)
- ctx->override_gid = 0;
- else
- ctx->override_gid = 1;
- break;
- case Opt_perm:
- if (result.negated)
- ctx->noperm = 1;
- else
- ctx->noperm = 0;
- break;
- case Opt_dynperm:
- if (result.negated)
- ctx->dynperm = 0;
- else
- ctx->dynperm = 1;
- break;
- case Opt_sfu:
- if (result.negated)
- ctx->sfu_emul = 0;
- else
- ctx->sfu_emul = 1;
- break;
- case Opt_noblocksend:
- ctx->noblocksnd = 1;
- break;
- case Opt_noautotune:
- ctx->noautotune = 1;
- break;
- case Opt_nolease:
- ctx->no_lease = 1;
- break;
- case Opt_nosparse:
- ctx->no_sparse = 1;
- break;
- case Opt_nodelete:
- ctx->nodelete = 1;
- break;
- case Opt_multichannel:
- if (result.negated) {
- ctx->multichannel = false;
- ctx->max_channels = 1;
- } else {
- ctx->multichannel = true;
- /* if number of channels not specified, default to 2 */
- if (ctx->max_channels < 2)
- ctx->max_channels = 2;
- }
- break;
- case Opt_uid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- goto cifs_parse_mount_err;
- ctx->linux_uid = uid;
- ctx->uid_specified = true;
- break;
- case Opt_cruid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- goto cifs_parse_mount_err;
- ctx->cred_uid = uid;
- ctx->cruid_specified = true;
- break;
- case Opt_backupuid:
- uid = make_kuid(current_user_ns(), result.uint_32);
- if (!uid_valid(uid))
- goto cifs_parse_mount_err;
- ctx->backupuid = uid;
- ctx->backupuid_specified = true;
- break;
- case Opt_backupgid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid))
- goto cifs_parse_mount_err;
- ctx->backupgid = gid;
- ctx->backupgid_specified = true;
- break;
- case Opt_gid:
- gid = make_kgid(current_user_ns(), result.uint_32);
- if (!gid_valid(gid))
- goto cifs_parse_mount_err;
- ctx->linux_gid = gid;
- ctx->gid_specified = true;
- break;
- case Opt_port:
- ctx->port = result.uint_32;
- break;
- case Opt_file_mode:
- ctx->file_mode = result.uint_32;
- break;
- case Opt_dirmode:
- ctx->dir_mode = result.uint_32;
- break;
- case Opt_min_enc_offload:
- ctx->min_offload = result.uint_32;
- break;
- case Opt_blocksize:
- /*
- * inode blocksize realistically should never need to be
- * less than 16K or greater than 16M and default is 1MB.
- * Note that small inode block sizes (e.g. 64K) can lead
- * to very poor performance of common tools like cp and scp
- */
- if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||
- (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {
- cifs_errorf(fc, "%s: Invalid blocksize\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->bsize = result.uint_32;
- ctx->got_bsize = true;
- break;
- case Opt_rasize:
- /*
- * readahead size realistically should never need to be
- * less than 1M (CIFS_DEFAULT_IOSIZE) or greater than 32M
- * (perhaps an exception should be considered in the
- * for the case of a large number of channels
- * when multichannel is negotiated) since that would lead
- * to plenty of parallel I/O in flight to the server.
- * Note that smaller read ahead sizes would
- * hurt performance of common tools like cp and scp
- * which often trigger sequential i/o with read ahead
- */
- if ((result.uint_32 > (8 * SMB3_DEFAULT_IOSIZE)) ||
- (result.uint_32 < CIFS_DEFAULT_IOSIZE)) {
- cifs_errorf(fc, "%s: Invalid rasize %d vs. %d\n",
- __func__, result.uint_32, SMB3_DEFAULT_IOSIZE);
- goto cifs_parse_mount_err;
- }
- ctx->rasize = result.uint_32;
- break;
- case Opt_rsize:
- ctx->rsize = result.uint_32;
- ctx->got_rsize = true;
- break;
- case Opt_wsize:
- ctx->wsize = result.uint_32;
- ctx->got_wsize = true;
- break;
- case Opt_acregmax:
- ctx->acregmax = HZ * result.uint_32;
- if (ctx->acregmax > CIFS_MAX_ACTIMEO) {
- cifs_errorf(fc, "acregmax too large\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_acdirmax:
- ctx->acdirmax = HZ * result.uint_32;
- if (ctx->acdirmax > CIFS_MAX_ACTIMEO) {
- cifs_errorf(fc, "acdirmax too large\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_actimeo:
- if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) {
- cifs_errorf(fc, "timeout too large\n");
- goto cifs_parse_mount_err;
- }
- if ((ctx->acdirmax != CIFS_DEF_ACTIMEO) ||
- (ctx->acregmax != CIFS_DEF_ACTIMEO)) {
- cifs_errorf(fc, "actimeo ignored since acregmax or acdirmax specified\n");
- break;
- }
- ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
- break;
- case Opt_closetimeo:
- ctx->closetimeo = HZ * result.uint_32;
- if (ctx->closetimeo > SMB3_MAX_DCLOSETIMEO) {
- cifs_errorf(fc, "closetimeo too large\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_echo_interval:
- ctx->echo_interval = result.uint_32;
- break;
- case Opt_snapshot:
- ctx->snapshot_time = result.uint_64;
- break;
- case Opt_max_credits:
- if (result.uint_32 < 20 || result.uint_32 > 60000) {
- cifs_errorf(fc, "%s: Invalid max_credits value\n",
- __func__);
- goto cifs_parse_mount_err;
- }
- ctx->max_credits = result.uint_32;
- break;
- case Opt_max_channels:
- if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {
- cifs_errorf(fc, "%s: Invalid max_channels value, needs to be 1-%d\n",
- __func__, CIFS_MAX_CHANNELS);
- goto cifs_parse_mount_err;
- }
- ctx->max_channels = result.uint_32;
- /* If more than one channel requested ... they want multichan */
- if (result.uint_32 > 1)
- ctx->multichannel = true;
- break;
- case Opt_handletimeout:
- ctx->handle_timeout = result.uint_32;
- if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
- cifs_errorf(fc, "Invalid handle cache timeout, longer than 16 minutes\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_source:
- kfree(ctx->UNC);
- ctx->UNC = NULL;
- switch (smb3_parse_devname(param->string, ctx)) {
- case 0:
- break;
- case -ENOMEM:
- cifs_errorf(fc, "Unable to allocate memory for devname\n");
- goto cifs_parse_mount_err;
- case -EINVAL:
- cifs_errorf(fc, "Malformed UNC in devname\n");
- goto cifs_parse_mount_err;
- default:
- cifs_errorf(fc, "Unknown error parsing devname\n");
- goto cifs_parse_mount_err;
- }
- ctx->source = kstrdup(param->string, GFP_KERNEL);
- if (ctx->source == NULL) {
- cifs_errorf(fc, "OOM when copying UNC string\n");
- goto cifs_parse_mount_err;
- }
- fc->source = kstrdup(param->string, GFP_KERNEL);
- if (fc->source == NULL) {
- cifs_errorf(fc, "OOM when copying UNC string\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_user:
- kfree(ctx->username);
- ctx->username = NULL;
- if (strlen(param->string) == 0) {
- /* null user, ie. anonymous authentication */
- ctx->nullauth = 1;
- break;
- }
-
- if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) >
- CIFS_MAX_USERNAME_LEN) {
- pr_warn("username too long\n");
- goto cifs_parse_mount_err;
- }
- ctx->username = kstrdup(param->string, GFP_KERNEL);
- if (ctx->username == NULL) {
- cifs_errorf(fc, "OOM when copying username string\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_pass:
- kfree_sensitive(ctx->password);
- ctx->password = NULL;
- if (strlen(param->string) == 0)
- break;
-
- ctx->password = kstrdup(param->string, GFP_KERNEL);
- if (ctx->password == NULL) {
- cifs_errorf(fc, "OOM when copying password string\n");
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_ip:
- if (strlen(param->string) == 0) {
- ctx->got_ip = false;
- break;
- }
- if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
- param->string,
- strlen(param->string))) {
- pr_err("bad ip= option (%s)\n", param->string);
- goto cifs_parse_mount_err;
- }
- ctx->got_ip = true;
- break;
- case Opt_domain:
- if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN)
- == CIFS_MAX_DOMAINNAME_LEN) {
- pr_warn("domain name too long\n");
- goto cifs_parse_mount_err;
- }
-
- kfree(ctx->domainname);
- ctx->domainname = kstrdup(param->string, GFP_KERNEL);
- if (ctx->domainname == NULL) {
- cifs_errorf(fc, "OOM when copying domainname string\n");
- goto cifs_parse_mount_err;
- }
- cifs_dbg(FYI, "Domain name set\n");
- break;
- case Opt_srcaddr:
- if (!cifs_convert_address(
- (struct sockaddr *)&ctx->srcaddr,
- param->string, strlen(param->string))) {
- pr_warn("Could not parse srcaddr: %s\n",
- param->string);
- goto cifs_parse_mount_err;
- }
- break;
- case Opt_iocharset:
- if (strnlen(param->string, 1024) >= 65) {
- pr_warn("iocharset name too long\n");
- goto cifs_parse_mount_err;
- }
-
- if (strncasecmp(param->string, "default", 7) != 0) {
- kfree(ctx->iocharset);
- ctx->iocharset = kstrdup(param->string, GFP_KERNEL);
- if (ctx->iocharset == NULL) {
- cifs_errorf(fc, "OOM when copying iocharset string\n");
- goto cifs_parse_mount_err;
- }
- }
- /* if iocharset not set then load_nls_default
- * is used by caller
- */
- cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
- break;
- case Opt_netbiosname:
- memset(ctx->source_rfc1001_name, 0x20,
- RFC1001_NAME_LEN);
- /*
- * FIXME: are there cases in which a comma can
- * be valid in workstation netbios name (and
- * need special handling)?
- */
- for (i = 0; i < RFC1001_NAME_LEN; i++) {
- /* don't ucase netbiosname for user */
- if (param->string[i] == 0)
- break;
- ctx->source_rfc1001_name[i] = param->string[i];
- }
- /* The string has 16th byte zero still from
- * set at top of the function
- */
- if (i == RFC1001_NAME_LEN && param->string[i] != 0)
- pr_warn("netbiosname longer than 15 truncated\n");
- break;
- case Opt_servern:
- /* last byte, type, is 0x20 for servr type */
- memset(ctx->target_rfc1001_name, 0x20,
- RFC1001_NAME_LEN_WITH_NULL);
- /*
- * BB are there cases in which a comma can be valid in this
- * workstation netbios name (and need special handling)?
- */
-
- /* user or mount helper must uppercase the netbios name */
- for (i = 0; i < 15; i++) {
- if (param->string[i] == 0)
- break;
- ctx->target_rfc1001_name[i] = param->string[i];
- }
-
- /* The string has 16th byte zero still from set at top of function */
- if (i == RFC1001_NAME_LEN && param->string[i] != 0)
- pr_warn("server netbiosname longer than 15 truncated\n");
- break;
- case Opt_ver:
- /* version of mount userspace tools, not dialect */
- /* If interface changes in mount.cifs bump to new ver */
- if (strncasecmp(param->string, "1", 1) == 0) {
- if (strlen(param->string) > 1) {
- pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
- param->string);
- goto cifs_parse_mount_err;
- }
- /* This is the default */
- break;
- }
- /* For all other value, error */
- pr_warn("Invalid mount helper version specified\n");
- goto cifs_parse_mount_err;
- case Opt_vers:
- /* protocol version (dialect) */
- if (cifs_parse_smb_version(fc, param->string, ctx, is_smb3) != 0)
- goto cifs_parse_mount_err;
- ctx->got_version = true;
- break;
- case Opt_sec:
- if (cifs_parse_security_flavors(fc, param->string, ctx) != 0)
- goto cifs_parse_mount_err;
- break;
- case Opt_cache:
- if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0)
- goto cifs_parse_mount_err;
- break;
- case Opt_witness:
-#ifndef CONFIG_CIFS_SWN_UPCALL
- cifs_errorf(fc, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
- goto cifs_parse_mount_err;
-#endif
- ctx->witness = true;
- pr_warn_once("Witness protocol support is experimental\n");
- break;
- case Opt_rootfs:
-#ifndef CONFIG_CIFS_ROOT
- cifs_dbg(VFS, "rootfs support requires CONFIG_CIFS_ROOT config option\n");
- goto cifs_parse_mount_err;
-#endif
- ctx->rootfs = true;
- break;
- case Opt_posixpaths:
- if (result.negated)
- ctx->posix_paths = 0;
- else
- ctx->posix_paths = 1;
- break;
- case Opt_unix:
- if (result.negated) {
- if (ctx->linux_ext == 1)
- pr_warn_once("conflicting posix mount options specified\n");
- ctx->linux_ext = 0;
- ctx->no_linux_ext = 1;
- } else {
- if (ctx->no_linux_ext == 1)
- pr_warn_once("conflicting posix mount options specified\n");
- ctx->linux_ext = 1;
- ctx->no_linux_ext = 0;
- }
- break;
- case Opt_nocase:
- ctx->nocase = 1;
- break;
- case Opt_brl:
- if (result.negated) {
- /*
- * turn off mandatory locking in mode
- * if remote locking is turned off since the
- * local vfs will do advisory
- */
- if (ctx->file_mode ==
- (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
- ctx->file_mode = S_IALLUGO;
- ctx->nobrl = 1;
- } else
- ctx->nobrl = 0;
- break;
- case Opt_handlecache:
- if (result.negated)
- ctx->nohandlecache = 1;
- else
- ctx->nohandlecache = 0;
- break;
- case Opt_forcemandatorylock:
- ctx->mand_lock = 1;
- break;
- case Opt_setuids:
- ctx->setuids = result.negated;
- break;
- case Opt_intr:
- ctx->intr = !result.negated;
- break;
- case Opt_setuidfromacl:
- ctx->setuidfromacl = 1;
- break;
- case Opt_strictsync:
- ctx->nostrictsync = result.negated;
- break;
- case Opt_serverino:
- ctx->server_ino = !result.negated;
- break;
- case Opt_rwpidforward:
- ctx->rwpidforward = 1;
- break;
- case Opt_modesid:
- ctx->mode_ace = 1;
- break;
- case Opt_cifsacl:
- ctx->cifs_acl = !result.negated;
- break;
- case Opt_acl:
- ctx->no_psx_acl = result.negated;
- break;
- case Opt_locallease:
- ctx->local_lease = 1;
- break;
- case Opt_sign:
- ctx->sign = true;
- break;
- case Opt_ignore_signature:
- ctx->sign = true;
- ctx->ignore_signature = true;
- break;
- case Opt_seal:
- /* we do not do the following in secFlags because seal
- * is a per tree connection (mount) not a per socket
- * or per-smb connection option in the protocol
- * vol->secFlg |= CIFSSEC_MUST_SEAL;
- */
- ctx->seal = 1;
- break;
- case Opt_noac:
- pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
- break;
- case Opt_fsc:
-#ifndef CONFIG_CIFS_FSCACHE
- cifs_errorf(fc, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
- goto cifs_parse_mount_err;
-#endif
- ctx->fsc = true;
- break;
- case Opt_mfsymlinks:
- ctx->mfsymlinks = true;
- break;
- case Opt_multiuser:
- ctx->multiuser = true;
- break;
- case Opt_sloppy:
- ctx->sloppy = true;
- break;
- case Opt_nosharesock:
- ctx->nosharesock = true;
- break;
- case Opt_persistent:
- if (result.negated) {
- ctx->nopersistent = true;
- if (ctx->persistent) {
- cifs_errorf(fc, "persistenthandles mount options conflict\n");
- goto cifs_parse_mount_err;
- }
- } else {
- ctx->persistent = true;
- if ((ctx->nopersistent) || (ctx->resilient)) {
- cifs_errorf(fc, "persistenthandles mount options conflict\n");
- goto cifs_parse_mount_err;
- }
- }
- break;
- case Opt_resilient:
- if (result.negated) {
- ctx->resilient = false; /* already the default */
- } else {
- ctx->resilient = true;
- if (ctx->persistent) {
- cifs_errorf(fc, "persistenthandles mount options conflict\n");
- goto cifs_parse_mount_err;
- }
- }
- break;
- case Opt_tcp_nodelay:
- /* tcp nodelay should not usually be needed since we CORK/UNCORK the socket */
- if (result.negated)
- ctx->sockopt_tcp_nodelay = false;
- else
- ctx->sockopt_tcp_nodelay = true;
- break;
- case Opt_domainauto:
- ctx->domainauto = true;
- break;
- case Opt_rdma:
- ctx->rdma = true;
- break;
- }
- /* case Opt_ignore: - is ignored as expected ... */
-
- return 0;
-
- cifs_parse_mount_err:
- kfree_sensitive(ctx->password);
- return -EINVAL;
-}
-
-int smb3_init_fs_context(struct fs_context *fc)
-{
- struct smb3_fs_context *ctx;
- char *nodename = utsname()->nodename;
- int i;
-
- ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
- if (unlikely(!ctx))
- return -ENOMEM;
-
- strscpy(ctx->workstation_name, nodename, sizeof(ctx->workstation_name));
-
- /*
- * does not have to be perfect mapping since field is
- * informational, only used for servers that do not support
- * port 445 and it can be overridden at mount time
- */
- memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
- for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
- ctx->source_rfc1001_name[i] = toupper(nodename[i]);
-
- ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
- /*
- * null target name indicates to use *SMBSERVR default called name
- * if we end up sending RFC1001 session initialize
- */
- ctx->target_rfc1001_name[0] = 0;
- ctx->cred_uid = current_uid();
- ctx->linux_uid = current_uid();
- ctx->linux_gid = current_gid();
- /* By default 4MB read ahead size, 1MB block size */
- ctx->bsize = CIFS_DEFAULT_IOSIZE; /* can improve cp performance significantly */
- ctx->rasize = 0; /* 0 = use default (ie negotiated rsize) for read ahead pages */
-
- /*
- * default to SFM style remapping of seven reserved characters
- * unless user overrides it or we negotiate CIFS POSIX where
- * it is unnecessary. Can not simultaneously use more than one mapping
- * since then readdir could list files that open could not open
- */
- ctx->remap = true;
-
- /* default to only allowing write access to owner of the mount */
- ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
-
- /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
- /* default is always to request posix paths. */
- ctx->posix_paths = 1;
- /* default to using server inode numbers where available */
- ctx->server_ino = 1;
-
- /* default is to use strict cifs caching semantics */
- ctx->strict_io = true;
-
- ctx->acregmax = CIFS_DEF_ACTIMEO;
- ctx->acdirmax = CIFS_DEF_ACTIMEO;
- ctx->closetimeo = SMB3_DEF_DCLOSETIMEO;
-
- /* Most clients set timeout to 0, allows server to use its default */
- ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
-
- /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
- ctx->ops = &smb30_operations;
- ctx->vals = &smbdefault_values;
-
- ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
-
- /* default to no multichannel (single server connection) */
- ctx->multichannel = false;
- ctx->max_channels = 1;
-
- ctx->backupuid_specified = false; /* no backup intent for a user */
- ctx->backupgid_specified = false; /* no backup intent for a group */
-
-/*
- * short int override_uid = -1;
- * short int override_gid = -1;
- * char *nodename = strdup(utsname()->nodename);
- * struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
- */
-
- fc->fs_private = ctx;
- fc->ops = &smb3_fs_context_ops;
- return 0;
-}
-
-void
-smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
-{
- if (ctx == NULL)
- return;
-
- /*
- * Make sure this stays in sync with smb3_fs_context_dup()
- */
- kfree(ctx->mount_options);
- ctx->mount_options = NULL;
- kfree(ctx->username);
- ctx->username = NULL;
- kfree_sensitive(ctx->password);
- ctx->password = NULL;
- kfree(ctx->server_hostname);
- ctx->server_hostname = NULL;
- kfree(ctx->UNC);
- ctx->UNC = NULL;
- kfree(ctx->source);
- ctx->source = NULL;
- kfree(ctx->domainname);
- ctx->domainname = NULL;
- kfree(ctx->nodename);
- ctx->nodename = NULL;
- kfree(ctx->iocharset);
- ctx->iocharset = NULL;
- kfree(ctx->prepath);
- ctx->prepath = NULL;
-}
-
-void
-smb3_cleanup_fs_context(struct smb3_fs_context *ctx)
-{
- if (!ctx)
- return;
- smb3_cleanup_fs_context_contents(ctx);
- kfree(ctx);
-}
-
-void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
-{
- struct smb3_fs_context *ctx = cifs_sb->ctx;
-
- if (ctx->nodfs)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS;
-
- if (ctx->noperm)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM;
-
- if (ctx->setuids)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID;
-
- if (ctx->setuidfromacl)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL;
-
- if (ctx->server_ino)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
-
- if (ctx->remap)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR;
-
- if (ctx->sfu_remap)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
-
- if (ctx->no_xattr)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR;
-
- if (ctx->sfu_emul)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL;
-
- if (ctx->nobrl)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL;
-
- if (ctx->nohandlecache)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
-
- if (ctx->nostrictsync)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC;
-
- if (ctx->mand_lock)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL;
-
- if (ctx->rwpidforward)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD;
-
- if (ctx->mode_ace)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID;
-
- if (ctx->cifs_acl)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL;
-
- if (ctx->backupuid_specified)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
-
- if (ctx->backupgid_specified)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
-
- if (ctx->override_uid)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID;
-
- if (ctx->override_gid)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID;
-
- if (ctx->dynperm)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM;
-
- if (ctx->fsc)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE;
-
- if (ctx->multiuser)
- cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
- CIFS_MOUNT_NO_PERM);
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MULTIUSER;
-
-
- if (ctx->strict_io)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO;
-
- if (ctx->direct_io)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO;
-
- if (ctx->mfsymlinks)
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
- else
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS;
- if (ctx->mfsymlinks) {
- if (ctx->sfu_emul) {
- /*
- * Our SFU ("Services for Unix" emulation does not allow
- * creating symlinks but does allow reading existing SFU
- * symlinks (it does allow both creating and reading SFU
- * style mknod and FIFOs though). When "mfsymlinks" and
- * "sfu" are both enabled at the same time, it allows
- * reading both types of symlinks, but will only create
- * them with mfsymlinks format. This allows better
- * Apple compatibility (probably better for Samba too)
- * while still recognizing old Windows style symlinks.
- */
- cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
- }
- }
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SHUTDOWN;
-
- return;
-}
diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h
deleted file mode 100644
index 26093f54d3e6..000000000000
--- a/fs/cifs/fs_context.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2020, Microsoft Corporation.
- *
- * Author(s): Steve French <stfrench@microsoft.com>
- * David Howells <dhowells@redhat.com>
- */
-
-#ifndef _FS_CONTEXT_H
-#define _FS_CONTEXT_H
-
-#include "cifsglob.h"
-#include <linux/parser.h>
-#include <linux/fs_parser.h>
-
-/* Log errors in fs_context (new mount api) but also in dmesg (old style) */
-#define cifs_errorf(fc, fmt, ...) \
- do { \
- errorf(fc, fmt, ## __VA_ARGS__); \
- cifs_dbg(VFS, fmt, ## __VA_ARGS__); \
- } while (0)
-
-enum smb_version {
- Smb_1 = 1,
- Smb_20,
- Smb_21,
- Smb_30,
- Smb_302,
- Smb_311,
- Smb_3any,
- Smb_default,
- Smb_version_err
-};
-
-enum {
- Opt_cache_loose,
- Opt_cache_strict,
- Opt_cache_none,
- Opt_cache_ro,
- Opt_cache_rw,
- Opt_cache_err
-};
-
-enum cifs_sec_param {
- Opt_sec_krb5,
- Opt_sec_krb5i,
- Opt_sec_krb5p,
- Opt_sec_ntlmsspi,
- Opt_sec_ntlmssp,
- Opt_sec_ntlmv2,
- Opt_sec_ntlmv2i,
- Opt_sec_none,
-
- Opt_sec_err
-};
-
-enum cifs_param {
- /* Mount options that take no arguments */
- Opt_user_xattr,
- Opt_forceuid,
- Opt_forcegid,
- Opt_noblocksend,
- Opt_noautotune,
- Opt_nolease,
- Opt_nosparse,
- Opt_hard,
- Opt_soft,
- Opt_perm,
- Opt_nodelete,
- Opt_mapposix,
- Opt_mapchars,
- Opt_nomapchars,
- Opt_sfu,
- Opt_nodfs,
- Opt_posixpaths,
- Opt_unix,
- Opt_nocase,
- Opt_brl,
- Opt_handlecache,
- Opt_forcemandatorylock,
- Opt_setuidfromacl,
- Opt_setuids,
- Opt_dynperm,
- Opt_intr,
- Opt_strictsync,
- Opt_serverino,
- Opt_rwpidforward,
- Opt_cifsacl,
- Opt_acl,
- Opt_locallease,
- Opt_sign,
- Opt_ignore_signature,
- Opt_seal,
- Opt_noac,
- Opt_fsc,
- Opt_mfsymlinks,
- Opt_multiuser,
- Opt_sloppy,
- Opt_nosharesock,
- Opt_persistent,
- Opt_resilient,
- Opt_tcp_nodelay,
- Opt_domainauto,
- Opt_rdma,
- Opt_modesid,
- Opt_rootfs,
- Opt_multichannel,
- Opt_compress,
- Opt_witness,
-
- /* Mount options which take numeric value */
- Opt_backupuid,
- Opt_backupgid,
- Opt_uid,
- Opt_cruid,
- Opt_gid,
- Opt_port,
- Opt_file_mode,
- Opt_dirmode,
- Opt_min_enc_offload,
- Opt_blocksize,
- Opt_rasize,
- Opt_rsize,
- Opt_wsize,
- Opt_actimeo,
- Opt_acdirmax,
- Opt_acregmax,
- Opt_closetimeo,
- Opt_echo_interval,
- Opt_max_credits,
- Opt_snapshot,
- Opt_max_channels,
- Opt_handletimeout,
-
- /* Mount options which take string value */
- Opt_source,
- Opt_user,
- Opt_pass,
- Opt_ip,
- Opt_domain,
- Opt_srcaddr,
- Opt_iocharset,
- Opt_netbiosname,
- Opt_servern,
- Opt_ver,
- Opt_vers,
- Opt_sec,
- Opt_cache,
-
- /* Mount options to be ignored */
- Opt_ignore,
-
- Opt_err
-};
-
-struct smb3_fs_context {
- bool uid_specified;
- bool cruid_specified;
- bool gid_specified;
- bool sloppy;
- bool got_ip;
- bool got_version;
- bool got_rsize;
- bool got_wsize;
- bool got_bsize;
- unsigned short port;
-
- char *username;
- char *password;
- char *domainname;
- char *source;
- char *server_hostname;
- char *UNC;
- char *nodename;
- char workstation_name[CIFS_MAX_WORKSTATION_LEN];
- char *iocharset; /* local code page for mapping to and from Unicode */
- char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
- char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
- kuid_t cred_uid;
- kuid_t linux_uid;
- kgid_t linux_gid;
- kuid_t backupuid;
- kgid_t backupgid;
- umode_t file_mode;
- umode_t dir_mode;
- enum securityEnum sectype; /* sectype requested via mnt opts */
- bool sign; /* was signing requested via mnt opts? */
- bool ignore_signature:1;
- bool retry:1;
- bool intr:1;
- bool setuids:1;
- bool setuidfromacl:1;
- bool override_uid:1;
- bool override_gid:1;
- bool dynperm:1;
- bool noperm:1;
- bool nodelete:1;
- bool mode_ace:1;
- bool no_psx_acl:1; /* set if posix acl support should be disabled */
- bool cifs_acl:1;
- bool backupuid_specified; /* mount option backupuid is specified */
- bool backupgid_specified; /* mount option backupgid is specified */
- bool no_xattr:1; /* set if xattr (EA) support should be disabled*/
- bool server_ino:1; /* use inode numbers from server ie UniqueId */
- bool direct_io:1;
- bool strict_io:1; /* strict cache behavior */
- bool cache_ro:1;
- bool cache_rw:1;
- bool remap:1; /* set to remap seven reserved chars in filenames */
- bool sfu_remap:1; /* remap seven reserved chars ala SFU */
- bool posix_paths:1; /* unset to not ask for posix pathnames. */
- bool no_linux_ext:1;
- bool linux_ext:1;
- bool sfu_emul:1;
- bool nullauth:1; /* attempt to authenticate with null user */
- bool nocase:1; /* request case insensitive filenames */
- bool nobrl:1; /* disable sending byte range locks to srv */
- bool nohandlecache:1; /* disable caching dir handles if srvr probs */
- bool mand_lock:1; /* send mandatory not posix byte range lock reqs */
- bool seal:1; /* request transport encryption on share */
- bool nodfs:1; /* Do not request DFS, even if available */
- bool local_lease:1; /* check leases only on local system, not remote */
- bool noblocksnd:1;
- bool noautotune:1;
- bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
- bool no_lease:1; /* disable requesting leases */
- bool no_sparse:1; /* do not attempt to set files sparse */
- bool fsc:1; /* enable fscache */
- bool mfsymlinks:1; /* use Minshall+French Symlinks */
- bool multiuser:1;
- bool rwpidforward:1; /* pid forward for read/write operations */
- bool nosharesock:1;
- bool persistent:1;
- bool nopersistent:1;
- bool resilient:1; /* noresilient not required since not fored for CA */
- bool domainauto:1;
- bool rdma:1;
- bool multichannel:1;
- bool use_client_guid:1;
- /* reuse existing guid for multichannel */
- u8 client_guid[SMB2_CLIENT_GUID_SIZE];
- unsigned int bsize;
- unsigned int rasize;
- unsigned int rsize;
- unsigned int wsize;
- unsigned int min_offload;
- bool sockopt_tcp_nodelay:1;
- /* attribute cache timemout for files and directories in jiffies */
- unsigned long acregmax;
- unsigned long acdirmax;
- /* timeout for deferred close of files in jiffies */
- unsigned long closetimeo;
- struct smb_version_operations *ops;
- struct smb_version_values *vals;
- char *prepath;
- struct sockaddr_storage dstaddr; /* destination address */
- struct sockaddr_storage srcaddr; /* allow binding to a local IP */
- struct nls_table *local_nls; /* This is a copy of the pointer in cifs_sb */
- unsigned int echo_interval; /* echo interval in secs */
- __u64 snapshot_time; /* needed for timewarp tokens */
- __u32 handle_timeout; /* persistent and durable handle timeout in ms */
- unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
- unsigned int max_channels;
- __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
- bool rootfs:1; /* if it's a SMB root file system */
- bool witness:1; /* use witness protocol */
-
- char *mount_options;
-};
-
-extern const struct fs_parameter_spec smb3_fs_parameters[];
-
-extern int smb3_init_fs_context(struct fs_context *fc);
-extern void smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx);
-extern void smb3_cleanup_fs_context(struct smb3_fs_context *ctx);
-
-static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *fc)
-{
- return fc->fs_private;
-}
-
-extern int smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx);
-extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
-
-/*
- * max deferred close timeout (jiffies) - 2^30
- */
-#define SMB3_MAX_DCLOSETIMEO (1 << 30)
-#define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */
-
-extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp);
-
-#endif
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
deleted file mode 100644
index f6f3a6b75601..000000000000
--- a/fs/cifs/fscache.c
+++ /dev/null
@@ -1,253 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- * CIFS filesystem cache interface
- *
- * Copyright (c) 2010 Novell, Inc.
- * Author(s): Suresh Jayaraman <sjayaraman@suse.de>
- *
- */
-#include "fscache.h"
-#include "cifsglob.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "cifsproto.h"
-
-static void cifs_fscache_fill_volume_coherency(
- struct cifs_tcon *tcon,
- struct cifs_fscache_volume_coherency_data *cd)
-{
- memset(cd, 0, sizeof(*cd));
- cd->resource_id = cpu_to_le64(tcon->resource_id);
- cd->vol_create_time = tcon->vol_create_time;
- cd->vol_serial_number = cpu_to_le32(tcon->vol_serial_number);
-}
-
-int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
-{
- struct cifs_fscache_volume_coherency_data cd;
- struct TCP_Server_Info *server = tcon->ses->server;
- struct fscache_volume *vcookie;
- const struct sockaddr *sa = (struct sockaddr *)&server->dstaddr;
- size_t slen, i;
- char *sharename;
- char *key;
- int ret = -ENOMEM;
-
- tcon->fscache = NULL;
- switch (sa->sa_family) {
- case AF_INET:
- case AF_INET6:
- break;
- default:
- cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
- return -EINVAL;
- }
-
- memset(&key, 0, sizeof(key));
-
- sharename = extract_sharename(tcon->tree_name);
- if (IS_ERR(sharename)) {
- cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
- return -EINVAL;
- }
-
- slen = strlen(sharename);
- for (i = 0; i < slen; i++)
- if (sharename[i] == '/')
- sharename[i] = ';';
-
- key = kasprintf(GFP_KERNEL, "cifs,%pISpc,%s", sa, sharename);
- if (!key)
- goto out;
-
- cifs_fscache_fill_volume_coherency(tcon, &cd);
- vcookie = fscache_acquire_volume(key,
- NULL, /* preferred_cache */
- &cd, sizeof(cd));
- cifs_dbg(FYI, "%s: (%s/0x%p)\n", __func__, key, vcookie);
- if (IS_ERR(vcookie)) {
- if (vcookie != ERR_PTR(-EBUSY)) {
- ret = PTR_ERR(vcookie);
- goto out_2;
- }
- pr_err("Cache volume key already in use (%s)\n", key);
- vcookie = NULL;
- }
-
- tcon->fscache = vcookie;
- ret = 0;
-out_2:
- kfree(key);
-out:
- kfree(sharename);
- return ret;
-}
-
-void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
-{
- struct cifs_fscache_volume_coherency_data cd;
-
- cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
-
- cifs_fscache_fill_volume_coherency(tcon, &cd);
- fscache_relinquish_volume(tcon->fscache, &cd, false);
- tcon->fscache = NULL;
-}
-
-void cifs_fscache_get_inode_cookie(struct inode *inode)
-{
- struct cifs_fscache_inode_coherency_data cd;
- struct cifsInodeInfo *cifsi = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
-
- cifs_fscache_fill_coherency(&cifsi->netfs.inode, &cd);
-
- cifsi->netfs.cache =
- fscache_acquire_cookie(tcon->fscache, 0,
- &cifsi->uniqueid, sizeof(cifsi->uniqueid),
- &cd, sizeof(cd),
- i_size_read(&cifsi->netfs.inode));
-}
-
-void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update)
-{
- if (update) {
- struct cifs_fscache_inode_coherency_data cd;
- loff_t i_size = i_size_read(inode);
-
- cifs_fscache_fill_coherency(inode, &cd);
- fscache_unuse_cookie(cifs_inode_cookie(inode), &cd, &i_size);
- } else {
- fscache_unuse_cookie(cifs_inode_cookie(inode), NULL, NULL);
- }
-}
-
-void cifs_fscache_release_inode_cookie(struct inode *inode)
-{
- struct cifsInodeInfo *cifsi = CIFS_I(inode);
- struct fscache_cookie *cookie = cifs_inode_cookie(inode);
-
- if (cookie) {
- cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cookie);
- fscache_relinquish_cookie(cookie, false);
- cifsi->netfs.cache = NULL;
- }
-}
-
-/*
- * Fallback page reading interface.
- */
-static int fscache_fallback_read_page(struct inode *inode, struct page *page)
-{
- struct netfs_cache_resources cres;
- struct fscache_cookie *cookie = cifs_inode_cookie(inode);
- struct iov_iter iter;
- struct bio_vec bvec[1];
- int ret;
-
- memset(&cres, 0, sizeof(cres));
- bvec[0].bv_page = page;
- bvec[0].bv_offset = 0;
- bvec[0].bv_len = PAGE_SIZE;
- iov_iter_bvec(&iter, ITER_DEST, bvec, ARRAY_SIZE(bvec), PAGE_SIZE);
-
- ret = fscache_begin_read_operation(&cres, cookie);
- if (ret < 0)
- return ret;
-
- ret = fscache_read(&cres, page_offset(page), &iter, NETFS_READ_HOLE_FAIL,
- NULL, NULL);
- fscache_end_operation(&cres);
- return ret;
-}
-
-/*
- * Fallback page writing interface.
- */
-static int fscache_fallback_write_page(struct inode *inode, struct page *page,
- bool no_space_allocated_yet)
-{
- struct netfs_cache_resources cres;
- struct fscache_cookie *cookie = cifs_inode_cookie(inode);
- struct iov_iter iter;
- struct bio_vec bvec[1];
- loff_t start = page_offset(page);
- size_t len = PAGE_SIZE;
- int ret;
-
- memset(&cres, 0, sizeof(cres));
- bvec[0].bv_page = page;
- bvec[0].bv_offset = 0;
- bvec[0].bv_len = PAGE_SIZE;
- iov_iter_bvec(&iter, ITER_SOURCE, bvec, ARRAY_SIZE(bvec), PAGE_SIZE);
-
- ret = fscache_begin_write_operation(&cres, cookie);
- if (ret < 0)
- return ret;
-
- ret = cres.ops->prepare_write(&cres, &start, &len, i_size_read(inode),
- no_space_allocated_yet);
- if (ret == 0)
- ret = fscache_write(&cres, page_offset(page), &iter, NULL, NULL);
- fscache_end_operation(&cres);
- return ret;
-}
-
-/*
- * Retrieve a page from FS-Cache
- */
-int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
-{
- int ret;
-
- cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n",
- __func__, cifs_inode_cookie(inode), page, inode);
-
- ret = fscache_fallback_read_page(inode, page);
- if (ret < 0)
- return ret;
-
- /* Read completed synchronously */
- SetPageUptodate(page);
- return 0;
-}
-
-void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
-{
- cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
- __func__, cifs_inode_cookie(inode), page, inode);
-
- fscache_fallback_write_page(inode, page, true);
-}
-
-/*
- * Query the cache occupancy.
- */
-int __cifs_fscache_query_occupancy(struct inode *inode,
- pgoff_t first, unsigned int nr_pages,
- pgoff_t *_data_first,
- unsigned int *_data_nr_pages)
-{
- struct netfs_cache_resources cres;
- struct fscache_cookie *cookie = cifs_inode_cookie(inode);
- loff_t start, data_start;
- size_t len, data_len;
- int ret;
-
- ret = fscache_begin_read_operation(&cres, cookie);
- if (ret < 0)
- return ret;
-
- start = first * PAGE_SIZE;
- len = nr_pages * PAGE_SIZE;
- ret = cres.ops->query_occupancy(&cres, start, len, PAGE_SIZE,
- &data_start, &data_len);
- if (ret == 0) {
- *_data_first = data_start / PAGE_SIZE;
- *_data_nr_pages = len / PAGE_SIZE;
- }
-
- fscache_end_operation(&cres);
- return ret;
-}
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
deleted file mode 100644
index 67b601041f0a..000000000000
--- a/fs/cifs/fscache.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- * CIFS filesystem cache interface definitions
- *
- * Copyright (c) 2010 Novell, Inc.
- * Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
- *
- */
-#ifndef _CIFS_FSCACHE_H
-#define _CIFS_FSCACHE_H
-
-#include <linux/swap.h>
-#include <linux/fscache.h>
-
-#include "cifsglob.h"
-
-/*
- * Coherency data attached to CIFS volume within the cache
- */
-struct cifs_fscache_volume_coherency_data {
- __le64 resource_id; /* unique server resource id */
- __le64 vol_create_time;
- __le32 vol_serial_number;
-} __packed;
-
-/*
- * Coherency data attached to CIFS inode within the cache.
- */
-struct cifs_fscache_inode_coherency_data {
- __le64 last_write_time_sec;
- __le64 last_change_time_sec;
- __le32 last_write_time_nsec;
- __le32 last_change_time_nsec;
-};
-
-#ifdef CONFIG_CIFS_FSCACHE
-
-/*
- * fscache.c
- */
-extern int cifs_fscache_get_super_cookie(struct cifs_tcon *);
-extern void cifs_fscache_release_super_cookie(struct cifs_tcon *);
-
-extern void cifs_fscache_get_inode_cookie(struct inode *inode);
-extern void cifs_fscache_release_inode_cookie(struct inode *);
-extern void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update);
-
-static inline
-void cifs_fscache_fill_coherency(struct inode *inode,
- struct cifs_fscache_inode_coherency_data *cd)
-{
- struct cifsInodeInfo *cifsi = CIFS_I(inode);
-
- memset(cd, 0, sizeof(*cd));
- cd->last_write_time_sec = cpu_to_le64(cifsi->netfs.inode.i_mtime.tv_sec);
- cd->last_write_time_nsec = cpu_to_le32(cifsi->netfs.inode.i_mtime.tv_nsec);
- cd->last_change_time_sec = cpu_to_le64(cifsi->netfs.inode.i_ctime.tv_sec);
- cd->last_change_time_nsec = cpu_to_le32(cifsi->netfs.inode.i_ctime.tv_nsec);
-}
-
-
-static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode)
-{
- return netfs_i_cookie(&CIFS_I(inode)->netfs);
-}
-
-static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags)
-{
- struct cifs_fscache_inode_coherency_data cd;
-
- cifs_fscache_fill_coherency(inode, &cd);
- fscache_invalidate(cifs_inode_cookie(inode), &cd,
- i_size_read(inode), flags);
-}
-
-extern int __cifs_fscache_query_occupancy(struct inode *inode,
- pgoff_t first, unsigned int nr_pages,
- pgoff_t *_data_first,
- unsigned int *_data_nr_pages);
-
-static inline int cifs_fscache_query_occupancy(struct inode *inode,
- pgoff_t first, unsigned int nr_pages,
- pgoff_t *_data_first,
- unsigned int *_data_nr_pages)
-{
- if (!cifs_inode_cookie(inode))
- return -ENOBUFS;
- return __cifs_fscache_query_occupancy(inode, first, nr_pages,
- _data_first, _data_nr_pages);
-}
-
-extern int __cifs_readpage_from_fscache(struct inode *pinode, struct page *ppage);
-extern void __cifs_readpage_to_fscache(struct inode *pinode, struct page *ppage);
-
-
-static inline int cifs_readpage_from_fscache(struct inode *inode,
- struct page *page)
-{
- if (cifs_inode_cookie(inode))
- return __cifs_readpage_from_fscache(inode, page);
- return -ENOBUFS;
-}
-
-static inline void cifs_readpage_to_fscache(struct inode *inode,
- struct page *page)
-{
- if (cifs_inode_cookie(inode))
- __cifs_readpage_to_fscache(inode, page);
-}
-
-#else /* CONFIG_CIFS_FSCACHE */
-static inline
-void cifs_fscache_fill_coherency(struct inode *inode,
- struct cifs_fscache_inode_coherency_data *cd)
-{
-}
-
-static inline int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) { return 0; }
-static inline void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {}
-
-static inline void cifs_fscache_get_inode_cookie(struct inode *inode) {}
-static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
-static inline void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update) {}
-static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { return NULL; }
-static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {}
-
-static inline int cifs_fscache_query_occupancy(struct inode *inode,
- pgoff_t first, unsigned int nr_pages,
- pgoff_t *_data_first,
- unsigned int *_data_nr_pages)
-{
- *_data_first = ULONG_MAX;
- *_data_nr_pages = 0;
- return -ENOBUFS;
-}
-
-static inline int
-cifs_readpage_from_fscache(struct inode *inode, struct page *page)
-{
- return -ENOBUFS;
-}
-
-static inline
-void cifs_readpage_to_fscache(struct inode *inode, struct page *page) {}
-
-#endif /* CONFIG_CIFS_FSCACHE */
-
-#endif /* _CIFS_FSCACHE_H */
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
deleted file mode 100644
index 8901d884f5b9..000000000000
--- a/fs/cifs/inode.c
+++ /dev/null
@@ -1,3093 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002,2010
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/freezer.h>
-#include <linux/sched/signal.h>
-#include <linux/wait_bit.h>
-#include <linux/fiemap.h>
-#include <asm/div64.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "smb2proto.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "cifs_unicode.h"
-#include "fscache.h"
-#include "fs_context.h"
-#include "cifs_ioctl.h"
-#include "cached_dir.h"
-
-static void cifs_set_ops(struct inode *inode)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-
- switch (inode->i_mode & S_IFMT) {
- case S_IFREG:
- inode->i_op = &cifs_file_inode_ops;
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
- inode->i_fop = &cifs_file_direct_nobrl_ops;
- else
- inode->i_fop = &cifs_file_direct_ops;
- } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
- inode->i_fop = &cifs_file_strict_nobrl_ops;
- else
- inode->i_fop = &cifs_file_strict_ops;
- } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
- inode->i_fop = &cifs_file_nobrl_ops;
- else { /* not direct, send byte range locks */
- inode->i_fop = &cifs_file_ops;
- }
-
- /* check if server can support readahead */
- if (cifs_sb_master_tcon(cifs_sb)->ses->server->max_read <
- PAGE_SIZE + MAX_CIFS_HDR_SIZE)
- inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
- else
- inode->i_data.a_ops = &cifs_addr_ops;
- break;
- case S_IFDIR:
-#ifdef CONFIG_CIFS_DFS_UPCALL
- if (IS_AUTOMOUNT(inode)) {
- inode->i_op = &cifs_dfs_referral_inode_operations;
- } else {
-#else /* NO DFS support, treat as a directory */
- {
-#endif
- inode->i_op = &cifs_dir_inode_ops;
- inode->i_fop = &cifs_dir_ops;
- }
- break;
- case S_IFLNK:
- inode->i_op = &cifs_symlink_inode_ops;
- break;
- default:
- init_special_inode(inode, inode->i_mode, inode->i_rdev);
- break;
- }
-}
-
-/* check inode attributes against fattr. If they don't match, tag the
- * inode for cache invalidation
- */
-static void
-cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
-{
- struct cifs_fscache_inode_coherency_data cd;
- struct cifsInodeInfo *cifs_i = CIFS_I(inode);
-
- cifs_dbg(FYI, "%s: revalidating inode %llu\n",
- __func__, cifs_i->uniqueid);
-
- if (inode->i_state & I_NEW) {
- cifs_dbg(FYI, "%s: inode %llu is new\n",
- __func__, cifs_i->uniqueid);
- return;
- }
-
- /* don't bother with revalidation if we have an oplock */
- if (CIFS_CACHE_READ(cifs_i)) {
- cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
- __func__, cifs_i->uniqueid);
- return;
- }
-
- /* revalidate if mtime or size have changed */
- fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
- if (timespec64_equal(&inode->i_mtime, &fattr->cf_mtime) &&
- cifs_i->server_eof == fattr->cf_eof) {
- cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
- __func__, cifs_i->uniqueid);
- return;
- }
-
- cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
- __func__, cifs_i->uniqueid);
- set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
- /* Invalidate fscache cookie */
- cifs_fscache_fill_coherency(&cifs_i->netfs.inode, &cd);
- fscache_invalidate(cifs_inode_cookie(inode), &cd, i_size_read(inode), 0);
-}
-
-/*
- * copy nlink to the inode, unless it wasn't provided. Provide
- * sane values if we don't have an existing one and none was provided
- */
-static void
-cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
-{
- /*
- * if we're in a situation where we can't trust what we
- * got from the server (readdir, some non-unix cases)
- * fake reasonable values
- */
- if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
- /* only provide fake values on a new inode */
- if (inode->i_state & I_NEW) {
- if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
- set_nlink(inode, 2);
- else
- set_nlink(inode, 1);
- }
- return;
- }
-
- /* we trust the server, so update it */
- set_nlink(inode, fattr->cf_nlink);
-}
-
-/* populate an inode with info from a cifs_fattr struct */
-int
-cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
-{
- struct cifsInodeInfo *cifs_i = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-
- if (!(inode->i_state & I_NEW) &&
- unlikely(inode_wrong_type(inode, fattr->cf_mode))) {
- CIFS_I(inode)->time = 0; /* force reval */
- return -ESTALE;
- }
-
- cifs_revalidate_cache(inode, fattr);
-
- spin_lock(&inode->i_lock);
- fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
- fattr->cf_atime = timestamp_truncate(fattr->cf_atime, inode);
- fattr->cf_ctime = timestamp_truncate(fattr->cf_ctime, inode);
- /* we do not want atime to be less than mtime, it broke some apps */
- if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime) < 0)
- inode->i_atime = fattr->cf_mtime;
- else
- inode->i_atime = fattr->cf_atime;
- inode->i_mtime = fattr->cf_mtime;
- inode->i_ctime = fattr->cf_ctime;
- inode->i_rdev = fattr->cf_rdev;
- cifs_nlink_fattr_to_inode(inode, fattr);
- inode->i_uid = fattr->cf_uid;
- inode->i_gid = fattr->cf_gid;
-
- /* if dynperm is set, don't clobber existing mode */
- if (inode->i_state & I_NEW ||
- !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
- inode->i_mode = fattr->cf_mode;
-
- cifs_i->cifsAttrs = fattr->cf_cifsattrs;
-
- if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
- cifs_i->time = 0;
- else
- cifs_i->time = jiffies;
-
- if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
- set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
- else
- clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
-
- cifs_i->server_eof = fattr->cf_eof;
- /*
- * Can't safely change the file size here if the client is writing to
- * it due to potential races.
- */
- if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
- i_size_write(inode, fattr->cf_eof);
-
- /*
- * i_blocks is not related to (i_size / i_blksize),
- * but instead 512 byte (2**9) size is required for
- * calculating num blocks.
- */
- inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
- }
-
- if (S_ISLNK(fattr->cf_mode)) {
- kfree(cifs_i->symlink_target);
- cifs_i->symlink_target = fattr->cf_symlink_target;
- fattr->cf_symlink_target = NULL;
- }
- spin_unlock(&inode->i_lock);
-
- if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
- inode->i_flags |= S_AUTOMOUNT;
- if (inode->i_state & I_NEW)
- cifs_set_ops(inode);
- return 0;
-}
-
-void
-cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
- return;
-
- fattr->cf_uniqueid = iunique(sb, ROOT_I);
-}
-
-/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
-void
-cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
- struct cifs_sb_info *cifs_sb)
-{
- memset(fattr, 0, sizeof(*fattr));
- fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
- fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
- fattr->cf_eof = le64_to_cpu(info->EndOfFile);
-
- fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
- fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
- fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
- /* old POSIX extensions don't get create time */
-
- fattr->cf_mode = le64_to_cpu(info->Permissions);
-
- /*
- * Since we set the inode type below we need to mask off
- * to avoid strange results if bits set above.
- */
- fattr->cf_mode &= ~S_IFMT;
- switch (le32_to_cpu(info->Type)) {
- case UNIX_FILE:
- fattr->cf_mode |= S_IFREG;
- fattr->cf_dtype = DT_REG;
- break;
- case UNIX_SYMLINK:
- fattr->cf_mode |= S_IFLNK;
- fattr->cf_dtype = DT_LNK;
- break;
- case UNIX_DIR:
- fattr->cf_mode |= S_IFDIR;
- fattr->cf_dtype = DT_DIR;
- break;
- case UNIX_CHARDEV:
- fattr->cf_mode |= S_IFCHR;
- fattr->cf_dtype = DT_CHR;
- fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
- le64_to_cpu(info->DevMinor) & MINORMASK);
- break;
- case UNIX_BLOCKDEV:
- fattr->cf_mode |= S_IFBLK;
- fattr->cf_dtype = DT_BLK;
- fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
- le64_to_cpu(info->DevMinor) & MINORMASK);
- break;
- case UNIX_FIFO:
- fattr->cf_mode |= S_IFIFO;
- fattr->cf_dtype = DT_FIFO;
- break;
- case UNIX_SOCKET:
- fattr->cf_mode |= S_IFSOCK;
- fattr->cf_dtype = DT_SOCK;
- break;
- default:
- /* safest to call it a file if we do not know */
- fattr->cf_mode |= S_IFREG;
- fattr->cf_dtype = DT_REG;
- cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
- break;
- }
-
- fattr->cf_uid = cifs_sb->ctx->linux_uid;
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
- u64 id = le64_to_cpu(info->Uid);
- if (id < ((uid_t)-1)) {
- kuid_t uid = make_kuid(&init_user_ns, id);
- if (uid_valid(uid))
- fattr->cf_uid = uid;
- }
- }
-
- fattr->cf_gid = cifs_sb->ctx->linux_gid;
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
- u64 id = le64_to_cpu(info->Gid);
- if (id < ((gid_t)-1)) {
- kgid_t gid = make_kgid(&init_user_ns, id);
- if (gid_valid(gid))
- fattr->cf_gid = gid;
- }
- }
-
- fattr->cf_nlink = le64_to_cpu(info->Nlinks);
-}
-
-/*
- * Fill a cifs_fattr struct with fake inode info.
- *
- * Needed to setup cifs_fattr data for the directory which is the
- * junction to the new submount (ie to setup the fake directory
- * which represents a DFS referral).
- */
-static void
-cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-
- cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
-
- memset(fattr, 0, sizeof(*fattr));
- fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
- fattr->cf_uid = cifs_sb->ctx->linux_uid;
- fattr->cf_gid = cifs_sb->ctx->linux_gid;
- ktime_get_coarse_real_ts64(&fattr->cf_mtime);
- fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
- fattr->cf_nlink = 2;
- fattr->cf_flags = CIFS_FATTR_DFS_REFERRAL;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-static int
-cifs_get_file_info_unix(struct file *filp)
-{
- int rc;
- unsigned int xid;
- FILE_UNIX_BASIC_INFO find_data;
- struct cifs_fattr fattr = {};
- struct inode *inode = file_inode(filp);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsFileInfo *cfile = filp->private_data;
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
-
- xid = get_xid();
-
- if (cfile->symlink_target) {
- fattr.cf_symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
- if (!fattr.cf_symlink_target) {
- rc = -ENOMEM;
- goto cifs_gfiunix_out;
- }
- }
-
- rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
- if (!rc) {
- cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
- } else if (rc == -EREMOTE) {
- cifs_create_dfs_fattr(&fattr, inode->i_sb);
- rc = 0;
- } else
- goto cifs_gfiunix_out;
-
- rc = cifs_fattr_to_inode(inode, &fattr);
-
-cifs_gfiunix_out:
- free_xid(xid);
- return rc;
-}
-
-int cifs_get_inode_info_unix(struct inode **pinode,
- const unsigned char *full_path,
- struct super_block *sb, unsigned int xid)
-{
- int rc;
- FILE_UNIX_BASIC_INFO find_data;
- struct cifs_fattr fattr;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct tcon_link *tlink;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-
- cifs_dbg(FYI, "Getting info on %s\n", full_path);
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
- server = tcon->ses->server;
-
- /* could have done a find first instead but this returns more info */
- rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
- cifs_sb->local_nls, cifs_remap(cifs_sb));
- cifs_dbg(FYI, "%s: query path info: rc = %d\n", __func__, rc);
- cifs_put_tlink(tlink);
-
- if (!rc) {
- cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
- } else if (rc == -EREMOTE) {
- cifs_create_dfs_fattr(&fattr, sb);
- rc = 0;
- } else {
- return rc;
- }
-
- /* check for Minshall+French symlinks */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
- int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
- full_path);
- if (tmprc)
- cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
- }
-
- if (S_ISLNK(fattr.cf_mode) && !fattr.cf_symlink_target) {
- if (!server->ops->query_symlink)
- return -EOPNOTSUPP;
- rc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path,
- &fattr.cf_symlink_target, false);
- if (rc) {
- cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc);
- goto cgiiu_exit;
- }
- }
-
- if (*pinode == NULL) {
- /* get new inode */
- cifs_fill_uniqueid(sb, &fattr);
- *pinode = cifs_iget(sb, &fattr);
- if (!*pinode)
- rc = -ENOMEM;
- } else {
- /* we already have inode, update it */
-
- /* if uniqueid is different, return error */
- if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
- CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
- CIFS_I(*pinode)->time = 0; /* force reval */
- rc = -ESTALE;
- goto cgiiu_exit;
- }
-
- /* if filetype is different, return error */
- rc = cifs_fattr_to_inode(*pinode, &fattr);
- }
-
-cgiiu_exit:
- kfree(fattr.cf_symlink_target);
- return rc;
-}
-#else
-int cifs_get_inode_info_unix(struct inode **pinode,
- const unsigned char *full_path,
- struct super_block *sb, unsigned int xid)
-{
- return -EOPNOTSUPP;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-static int
-cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
- struct cifs_sb_info *cifs_sb, unsigned int xid)
-{
- int rc;
- __u32 oplock;
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- struct cifs_io_parms io_parms = {0};
- char buf[24];
- unsigned int bytes_read;
- char *pbuf;
- int buf_type = CIFS_NO_BUFFER;
-
- pbuf = buf;
-
- fattr->cf_mode &= ~S_IFMT;
-
- if (fattr->cf_eof == 0) {
- fattr->cf_mode |= S_IFIFO;
- fattr->cf_dtype = DT_FIFO;
- return 0;
- } else if (fattr->cf_eof < 8) {
- fattr->cf_mode |= S_IFREG;
- fattr->cf_dtype = DT_REG;
- return -EINVAL; /* EOPNOTSUPP? */
- }
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = GENERIC_READ,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
- .disposition = FILE_OPEN,
- .path = path,
- .fid = &fid,
- };
-
- if (tcon->ses->server->oplocks)
- oplock = REQ_OPLOCK;
- else
- oplock = 0;
- rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
- if (rc) {
- cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
- cifs_put_tlink(tlink);
- return rc;
- }
-
- /* Read header */
- io_parms.netfid = fid.netfid;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
- io_parms.offset = 0;
- io_parms.length = 24;
-
- rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
- &bytes_read, &pbuf, &buf_type);
- if ((rc == 0) && (bytes_read >= 8)) {
- if (memcmp("IntxBLK", pbuf, 8) == 0) {
- cifs_dbg(FYI, "Block device\n");
- fattr->cf_mode |= S_IFBLK;
- fattr->cf_dtype = DT_BLK;
- if (bytes_read == 24) {
- /* we have enough to decode dev num */
- __u64 mjr; /* major */
- __u64 mnr; /* minor */
- mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
- mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
- fattr->cf_rdev = MKDEV(mjr, mnr);
- }
- } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
- cifs_dbg(FYI, "Char device\n");
- fattr->cf_mode |= S_IFCHR;
- fattr->cf_dtype = DT_CHR;
- if (bytes_read == 24) {
- /* we have enough to decode dev num */
- __u64 mjr; /* major */
- __u64 mnr; /* minor */
- mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
- mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
- fattr->cf_rdev = MKDEV(mjr, mnr);
- }
- } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
- cifs_dbg(FYI, "Symlink\n");
- fattr->cf_mode |= S_IFLNK;
- fattr->cf_dtype = DT_LNK;
- } else {
- fattr->cf_mode |= S_IFREG; /* file? */
- fattr->cf_dtype = DT_REG;
- rc = -EOPNOTSUPP;
- }
- } else {
- fattr->cf_mode |= S_IFREG; /* then it is a file */
- fattr->cf_dtype = DT_REG;
- rc = -EOPNOTSUPP; /* or some unknown SFU type */
- }
-
- tcon->ses->server->ops->close(xid, tcon, &fid);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
-
-/*
- * Fetch mode bits as provided by SFU.
- *
- * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
- */
-static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
- struct cifs_sb_info *cifs_sb, unsigned int xid)
-{
-#ifdef CONFIG_CIFS_XATTR
- ssize_t rc;
- char ea_value[4];
- __u32 mode;
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
-
- if (tcon->ses->server->ops->query_all_EAs == NULL) {
- cifs_put_tlink(tlink);
- return -EOPNOTSUPP;
- }
-
- rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
- "SETFILEBITS", ea_value, 4 /* size of buf */,
- cifs_sb);
- cifs_put_tlink(tlink);
- if (rc < 0)
- return (int)rc;
- else if (rc > 3) {
- mode = le32_to_cpu(*((__le32 *)ea_value));
- fattr->cf_mode &= ~SFBITS_MASK;
- cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
- mode, fattr->cf_mode);
- fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
- cifs_dbg(FYI, "special mode bits 0%o\n", mode);
- }
-
- return 0;
-#else
- return -EOPNOTSUPP;
-#endif
-}
-
-/* Fill a cifs_fattr struct with info from POSIX info struct */
-static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,
- struct super_block *sb, bool adjust_tz, bool symlink)
-{
- struct smb311_posix_qinfo *info = &data->posix_fi;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
-
- memset(fattr, 0, sizeof(*fattr));
-
- /* no fattr->flags to set */
- fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
- fattr->cf_uniqueid = le64_to_cpu(info->Inode);
-
- if (info->LastAccessTime)
- fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
- else
- ktime_get_coarse_real_ts64(&fattr->cf_atime);
-
- fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
- fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
-
- if (adjust_tz) {
- fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
- fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
- }
-
- fattr->cf_eof = le64_to_cpu(info->EndOfFile);
- fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
- fattr->cf_createtime = le64_to_cpu(info->CreationTime);
-
- fattr->cf_nlink = le32_to_cpu(info->HardLinks);
- fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode);
- /* The srv fs device id is overridden on network mount so setting rdev isn't needed here */
- /* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */
-
- if (symlink) {
- fattr->cf_mode |= S_IFLNK;
- fattr->cf_dtype = DT_LNK;
- fattr->cf_symlink_target = data->symlink_target;
- data->symlink_target = NULL;
- } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
- fattr->cf_mode |= S_IFDIR;
- fattr->cf_dtype = DT_DIR;
- } else { /* file */
- fattr->cf_mode |= S_IFREG;
- fattr->cf_dtype = DT_REG;
- }
- /* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
-
- fattr->cf_uid = cifs_sb->ctx->linux_uid; /* TODO: map uid and gid from SID */
- fattr->cf_gid = cifs_sb->ctx->linux_gid;
-
- cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
- fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
-}
-
-static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,
- struct super_block *sb, bool adjust_tz, bool symlink,
- u32 reparse_tag)
-{
- struct smb2_file_all_info *info = &data->fi;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
-
- memset(fattr, 0, sizeof(*fattr));
- fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
- if (info->DeletePending)
- fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
-
- if (info->LastAccessTime)
- fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
- else
- ktime_get_coarse_real_ts64(&fattr->cf_atime);
-
- fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
- fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
-
- if (adjust_tz) {
- fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
- fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
- }
-
- fattr->cf_eof = le64_to_cpu(info->EndOfFile);
- fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
- fattr->cf_createtime = le64_to_cpu(info->CreationTime);
-
- fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
- if (reparse_tag == IO_REPARSE_TAG_LX_SYMLINK) {
- fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_LNK;
- } else if (reparse_tag == IO_REPARSE_TAG_LX_FIFO) {
- fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_FIFO;
- } else if (reparse_tag == IO_REPARSE_TAG_AF_UNIX) {
- fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_SOCK;
- } else if (reparse_tag == IO_REPARSE_TAG_LX_CHR) {
- fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_CHR;
- } else if (reparse_tag == IO_REPARSE_TAG_LX_BLK) {
- fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_BLK;
- } else if (symlink || reparse_tag == IO_REPARSE_TAG_SYMLINK ||
- reparse_tag == IO_REPARSE_TAG_NFS) {
- fattr->cf_mode = S_IFLNK;
- fattr->cf_dtype = DT_LNK;
- } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
- fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;
- fattr->cf_dtype = DT_DIR;
- /*
- * Server can return wrong NumberOfLinks value for directories
- * when Unix extensions are disabled - fake it.
- */
- if (!tcon->unix_ext)
- fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
- } else {
- fattr->cf_mode = S_IFREG | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_REG;
-
- /* clear write bits if ATTR_READONLY is set */
- if (fattr->cf_cifsattrs & ATTR_READONLY)
- fattr->cf_mode &= ~(S_IWUGO);
-
- /*
- * Don't accept zero nlink from non-unix servers unless
- * delete is pending. Instead mark it as unknown.
- */
- if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
- !info->DeletePending) {
- cifs_dbg(VFS, "bogus file nlink value %u\n",
- fattr->cf_nlink);
- fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
- }
- }
-
- if (S_ISLNK(fattr->cf_mode)) {
- fattr->cf_symlink_target = data->symlink_target;
- data->symlink_target = NULL;
- }
-
- fattr->cf_uid = cifs_sb->ctx->linux_uid;
- fattr->cf_gid = cifs_sb->ctx->linux_gid;
-}
-
-static int
-cifs_get_file_info(struct file *filp)
-{
- int rc;
- unsigned int xid;
- struct cifs_open_info_data data = {};
- struct cifs_fattr fattr;
- struct inode *inode = file_inode(filp);
- struct cifsFileInfo *cfile = filp->private_data;
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- struct TCP_Server_Info *server = tcon->ses->server;
- bool symlink = false;
- u32 tag = 0;
-
- if (!server->ops->query_file_info)
- return -ENOSYS;
-
- xid = get_xid();
- rc = server->ops->query_file_info(xid, tcon, cfile, &data);
- switch (rc) {
- case 0:
- /* TODO: add support to query reparse tag */
- if (data.symlink_target) {
- symlink = true;
- tag = IO_REPARSE_TAG_SYMLINK;
- }
- cifs_open_info_to_fattr(&fattr, &data, inode->i_sb, false, symlink, tag);
- break;
- case -EREMOTE:
- cifs_create_dfs_fattr(&fattr, inode->i_sb);
- rc = 0;
- break;
- case -EOPNOTSUPP:
- case -EINVAL:
- /*
- * FIXME: legacy server -- fall back to path-based call?
- * for now, just skip revalidating and mark inode for
- * immediate reval.
- */
- rc = 0;
- CIFS_I(inode)->time = 0;
- goto cgfi_exit;
- default:
- goto cgfi_exit;
- }
-
- /*
- * don't bother with SFU junk here -- just mark inode as needing
- * revalidation.
- */
- fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
- fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
- /* if filetype is different, return error */
- rc = cifs_fattr_to_inode(inode, &fattr);
-cgfi_exit:
- cifs_free_open_info(&data);
- free_xid(xid);
- return rc;
-}
-
-/* Simple function to return a 64 bit hash of string. Rarely called */
-static __u64 simple_hashstr(const char *str)
-{
- const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
- __u64 hash = 0;
-
- while (*str)
- hash = (hash + (__u64) *str++) * hash_mult;
-
- return hash;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-/**
- * cifs_backup_query_path_info - SMB1 fallback code to get ino
- *
- * Fallback code to get file metadata when we don't have access to
- * full_path (EACCES) and have backup creds.
- *
- * @xid: transaction id used to identify original request in logs
- * @tcon: information about the server share we have mounted
- * @sb: the superblock stores info such as disk space available
- * @full_path: name of the file we are getting the metadata for
- * @resp_buf: will be set to cifs resp buf and needs to be freed with
- * cifs_buf_release() when done with @data
- * @data: will be set to search info result buffer
- */
-static int
-cifs_backup_query_path_info(int xid,
- struct cifs_tcon *tcon,
- struct super_block *sb,
- const char *full_path,
- void **resp_buf,
- FILE_ALL_INFO **data)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifs_search_info info = {0};
- u16 flags;
- int rc;
-
- *resp_buf = NULL;
- info.endOfSearch = false;
- if (tcon->unix_ext)
- info.info_level = SMB_FIND_FILE_UNIX;
- else if ((tcon->ses->capabilities &
- tcon->ses->server->vals->cap_nt_find) == 0)
- info.info_level = SMB_FIND_FILE_INFO_STANDARD;
- else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
- info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
- else /* no srvino useful for fallback to some netapp */
- info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
-
- flags = CIFS_SEARCH_CLOSE_ALWAYS |
- CIFS_SEARCH_CLOSE_AT_END |
- CIFS_SEARCH_BACKUP_SEARCH;
-
- rc = CIFSFindFirst(xid, tcon, full_path,
- cifs_sb, NULL, flags, &info, false);
- if (rc)
- return rc;
-
- *resp_buf = (void *)info.ntwrk_buf_start;
- *data = (FILE_ALL_INFO *)info.srch_entries_start;
- return 0;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-static void cifs_set_fattr_ino(int xid, struct cifs_tcon *tcon, struct super_block *sb,
- struct inode **inode, const char *full_path,
- struct cifs_open_info_data *data, struct cifs_fattr *fattr)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct TCP_Server_Info *server = tcon->ses->server;
- int rc;
-
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
- if (*inode)
- fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
- else
- fattr->cf_uniqueid = iunique(sb, ROOT_I);
- return;
- }
-
- /*
- * If we have an inode pass a NULL tcon to ensure we don't
- * make a round trip to the server. This only works for SMB2+.
- */
- rc = server->ops->get_srv_inum(xid, *inode ? NULL : tcon, cifs_sb, full_path,
- &fattr->cf_uniqueid, data);
- if (rc) {
- /*
- * If that fails reuse existing ino or generate one
- * and disable server ones
- */
- if (*inode)
- fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
- else {
- fattr->cf_uniqueid = iunique(sb, ROOT_I);
- cifs_autodisable_serverino(cifs_sb);
- }
- return;
- }
-
- /* If no errors, check for zero root inode (invalid) */
- if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) {
- cifs_dbg(FYI, "Invalid (0) inodenum\n");
- if (*inode) {
- /* reuse */
- fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
- } else {
- /* make an ino by hashing the UNC */
- fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
- fattr->cf_uniqueid = simple_hashstr(tcon->tree_name);
- }
- }
-}
-
-static inline bool is_inode_cache_good(struct inode *ino)
-{
- return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
-}
-
-int cifs_get_inode_info(struct inode **inode, const char *full_path,
- struct cifs_open_info_data *data, struct super_block *sb, int xid,
- const struct cifs_fid *fid)
-{
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct tcon_link *tlink;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- bool adjust_tz = false;
- struct cifs_fattr fattr = {0};
- bool is_reparse_point = false;
- struct cifs_open_info_data tmp_data = {};
- void *smb1_backup_rsp_buf = NULL;
- int rc = 0;
- int tmprc = 0;
- __u32 reparse_tag = 0;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
- server = tcon->ses->server;
-
- /*
- * 1. Fetch file metadata if not provided (data)
- */
-
- if (!data) {
- if (is_inode_cache_good(*inode)) {
- cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
- goto out;
- }
- rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, &tmp_data,
- &adjust_tz, &is_reparse_point);
- data = &tmp_data;
- }
-
- /*
- * 2. Convert it to internal cifs metadata (fattr)
- */
-
- switch (rc) {
- case 0:
- /*
- * If the file is a reparse point, it is more complicated
- * since we have to check if its reparse tag matches a known
- * special file type e.g. symlink or fifo or char etc.
- */
- if (is_reparse_point && data->symlink_target) {
- reparse_tag = IO_REPARSE_TAG_SYMLINK;
- } else if ((le32_to_cpu(data->fi.Attributes) & ATTR_REPARSE) &&
- server->ops->query_reparse_tag) {
- tmprc = server->ops->query_reparse_tag(xid, tcon, cifs_sb, full_path,
- &reparse_tag);
- if (tmprc)
- cifs_dbg(FYI, "%s: query_reparse_tag: rc = %d\n", __func__, tmprc);
- if (server->ops->query_symlink) {
- tmprc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path,
- &data->symlink_target,
- is_reparse_point);
- if (tmprc)
- cifs_dbg(FYI, "%s: query_symlink: rc = %d\n", __func__,
- tmprc);
- }
- }
- cifs_open_info_to_fattr(&fattr, data, sb, adjust_tz, is_reparse_point, reparse_tag);
- break;
- case -EREMOTE:
- /* DFS link, no metadata available on this server */
- cifs_create_dfs_fattr(&fattr, sb);
- rc = 0;
- break;
- case -EACCES:
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- /*
- * perm errors, try again with backup flags if possible
- *
- * For SMB2 and later the backup intent flag
- * is already sent if needed on open and there
- * is no path based FindFirst operation to use
- * to retry with
- */
- if (backup_cred(cifs_sb) && is_smb1_server(server)) {
- /* for easier reading */
- FILE_ALL_INFO *fi;
- FILE_DIRECTORY_INFO *fdi;
- SEARCH_ID_FULL_DIR_INFO *si;
-
- rc = cifs_backup_query_path_info(xid, tcon, sb,
- full_path,
- &smb1_backup_rsp_buf,
- &fi);
- if (rc)
- goto out;
-
- move_cifs_info_to_smb2(&data->fi, fi);
- fdi = (FILE_DIRECTORY_INFO *)fi;
- si = (SEARCH_ID_FULL_DIR_INFO *)fi;
-
- cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);
- fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);
- /* uniqueid set, skip get inum step */
- goto handle_mnt_opt;
- } else {
- /* nothing we can do, bail out */
- goto out;
- }
-#else
- goto out;
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- break;
- default:
- cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
- goto out;
- }
-
- /*
- * 3. Get or update inode number (fattr.cf_uniqueid)
- */
-
- cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
-
- /*
- * 4. Tweak fattr based on mount options
- */
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-handle_mnt_opt:
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- /* query for SFU type info if supported and needed */
- if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
- cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
- tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
- if (tmprc)
- cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
- }
-
- /* fill in 0777 bits from ACL */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
- rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
- full_path, fid);
- if (rc == -EREMOTE)
- rc = 0;
- if (rc) {
- cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
- __func__, rc);
- goto out;
- }
- } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
- rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
- full_path, fid);
- if (rc == -EREMOTE)
- rc = 0;
- if (rc) {
- cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
- __func__, rc);
- goto out;
- }
- }
-
- /* fill in remaining high mode bits e.g. SUID, VTX */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
- cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
-
- /* check for Minshall+French symlinks */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
- tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
- full_path);
- if (tmprc)
- cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
- }
-
- /*
- * 5. Update inode with final fattr data
- */
-
- if (!*inode) {
- *inode = cifs_iget(sb, &fattr);
- if (!*inode)
- rc = -ENOMEM;
- } else {
- /* we already have inode, update it */
-
- /* if uniqueid is different, return error */
- if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
- CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
- CIFS_I(*inode)->time = 0; /* force reval */
- rc = -ESTALE;
- goto out;
- }
- /* if filetype is different, return error */
- rc = cifs_fattr_to_inode(*inode, &fattr);
- }
-out:
- cifs_buf_release(smb1_backup_rsp_buf);
- cifs_put_tlink(tlink);
- cifs_free_open_info(&tmp_data);
- kfree(fattr.cf_symlink_target);
- return rc;
-}
-
-int
-smb311_posix_get_inode_info(struct inode **inode,
- const char *full_path,
- struct super_block *sb, unsigned int xid)
-{
- struct cifs_tcon *tcon;
- struct tcon_link *tlink;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- bool adjust_tz = false;
- struct cifs_fattr fattr = {0};
- bool symlink = false;
- struct cifs_open_info_data data = {};
- int rc = 0;
- int tmprc = 0;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
-
- /*
- * 1. Fetch file metadata
- */
-
- if (is_inode_cache_good(*inode)) {
- cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
- goto out;
- }
-
- rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data, &adjust_tz,
- &symlink);
-
- /*
- * 2. Convert it to internal cifs metadata (fattr)
- */
-
- switch (rc) {
- case 0:
- smb311_posix_info_to_fattr(&fattr, &data, sb, adjust_tz, symlink);
- break;
- case -EREMOTE:
- /* DFS link, no metadata available on this server */
- cifs_create_dfs_fattr(&fattr, sb);
- rc = 0;
- break;
- case -EACCES:
- /*
- * For SMB2 and later the backup intent flag
- * is already sent if needed on open and there
- * is no path based FindFirst operation to use
- * to retry with so nothing we can do, bail out
- */
- goto out;
- default:
- cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
- goto out;
- }
-
-
- /*
- * 3. Tweak fattr based on mount options
- */
-
- /* check for Minshall+French symlinks */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
- tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
- full_path);
- if (tmprc)
- cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
- }
-
- /*
- * 4. Update inode with final fattr data
- */
-
- if (!*inode) {
- *inode = cifs_iget(sb, &fattr);
- if (!*inode)
- rc = -ENOMEM;
- } else {
- /* we already have inode, update it */
-
- /* if uniqueid is different, return error */
- if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
- CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
- CIFS_I(*inode)->time = 0; /* force reval */
- rc = -ESTALE;
- goto out;
- }
-
- /* if filetype is different, return error */
- rc = cifs_fattr_to_inode(*inode, &fattr);
- }
-out:
- cifs_put_tlink(tlink);
- cifs_free_open_info(&data);
- kfree(fattr.cf_symlink_target);
- return rc;
-}
-
-
-static const struct inode_operations cifs_ipc_inode_ops = {
- .lookup = cifs_lookup,
-};
-
-static int
-cifs_find_inode(struct inode *inode, void *opaque)
-{
- struct cifs_fattr *fattr = opaque;
-
- /* don't match inode with different uniqueid */
- if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
- return 0;
-
- /* use createtime like an i_generation field */
- if (CIFS_I(inode)->createtime != fattr->cf_createtime)
- return 0;
-
- /* don't match inode of different type */
- if (inode_wrong_type(inode, fattr->cf_mode))
- return 0;
-
- /* if it's not a directory or has no dentries, then flag it */
- if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
- fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
-
- return 1;
-}
-
-static int
-cifs_init_inode(struct inode *inode, void *opaque)
-{
- struct cifs_fattr *fattr = opaque;
-
- CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
- CIFS_I(inode)->createtime = fattr->cf_createtime;
- return 0;
-}
-
-/*
- * walk dentry list for an inode and report whether it has aliases that
- * are hashed. We use this to determine if a directory inode can actually
- * be used.
- */
-static bool
-inode_has_hashed_dentries(struct inode *inode)
-{
- struct dentry *dentry;
-
- spin_lock(&inode->i_lock);
- hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
- if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
- spin_unlock(&inode->i_lock);
- return true;
- }
- }
- spin_unlock(&inode->i_lock);
- return false;
-}
-
-/* Given fattrs, get a corresponding inode */
-struct inode *
-cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
-{
- unsigned long hash;
- struct inode *inode;
-
-retry_iget5_locked:
- cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
-
- /* hash down to 32-bits on 32-bit arch */
- hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
-
- inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
- if (inode) {
- /* was there a potentially problematic inode collision? */
- if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
- fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
-
- if (inode_has_hashed_dentries(inode)) {
- cifs_autodisable_serverino(CIFS_SB(sb));
- iput(inode);
- fattr->cf_uniqueid = iunique(sb, ROOT_I);
- goto retry_iget5_locked;
- }
- }
-
- /* can't fail - see cifs_find_inode() */
- cifs_fattr_to_inode(inode, fattr);
- if (sb->s_flags & SB_NOATIME)
- inode->i_flags |= S_NOATIME | S_NOCMTIME;
- if (inode->i_state & I_NEW) {
- inode->i_ino = hash;
- cifs_fscache_get_inode_cookie(inode);
- unlock_new_inode(inode);
- }
- }
-
- return inode;
-}
-
-/* gets root inode */
-struct inode *cifs_root_iget(struct super_block *sb)
-{
- unsigned int xid;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct inode *inode = NULL;
- long rc;
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- char *path = NULL;
- int len;
-
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
- && cifs_sb->prepath) {
- len = strlen(cifs_sb->prepath);
- path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
- if (path == NULL)
- return ERR_PTR(-ENOMEM);
- path[0] = '/';
- memcpy(path+1, cifs_sb->prepath, len);
- } else {
- path = kstrdup("", GFP_KERNEL);
- if (path == NULL)
- return ERR_PTR(-ENOMEM);
- }
-
- xid = get_xid();
- if (tcon->unix_ext) {
- rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
- /* some servers mistakenly claim POSIX support */
- if (rc != -EOPNOTSUPP)
- goto iget_no_retry;
- cifs_dbg(VFS, "server does not support POSIX extensions\n");
- tcon->unix_ext = false;
- }
-
- convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
- if (tcon->posix_extensions)
- rc = smb311_posix_get_inode_info(&inode, path, sb, xid);
- else
- rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
-
-iget_no_retry:
- if (!inode) {
- inode = ERR_PTR(rc);
- goto out;
- }
-
- if (rc && tcon->pipe) {
- cifs_dbg(FYI, "ipc connection - fake read inode\n");
- spin_lock(&inode->i_lock);
- inode->i_mode |= S_IFDIR;
- set_nlink(inode, 2);
- inode->i_op = &cifs_ipc_inode_ops;
- inode->i_fop = &simple_dir_operations;
- inode->i_uid = cifs_sb->ctx->linux_uid;
- inode->i_gid = cifs_sb->ctx->linux_gid;
- spin_unlock(&inode->i_lock);
- } else if (rc) {
- iget_failed(inode);
- inode = ERR_PTR(rc);
- }
-
-out:
- kfree(path);
- free_xid(xid);
- return inode;
-}
-
-int
-cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
- const char *full_path, __u32 dosattr)
-{
- bool set_time = false;
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct TCP_Server_Info *server;
- FILE_BASIC_INFO info_buf;
-
- if (attrs == NULL)
- return -EINVAL;
-
- server = cifs_sb_master_tcon(cifs_sb)->ses->server;
- if (!server->ops->set_file_info)
- return -ENOSYS;
-
- info_buf.Pad = 0;
-
- if (attrs->ia_valid & ATTR_ATIME) {
- set_time = true;
- info_buf.LastAccessTime =
- cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
- } else
- info_buf.LastAccessTime = 0;
-
- if (attrs->ia_valid & ATTR_MTIME) {
- set_time = true;
- info_buf.LastWriteTime =
- cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
- } else
- info_buf.LastWriteTime = 0;
-
- /*
- * Samba throws this field away, but windows may actually use it.
- * Do not set ctime unless other time stamps are changed explicitly
- * (i.e. by utimes()) since we would then have a mix of client and
- * server times.
- */
- if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
- cifs_dbg(FYI, "CIFS - CTIME changed\n");
- info_buf.ChangeTime =
- cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
- } else
- info_buf.ChangeTime = 0;
-
- info_buf.CreationTime = 0; /* don't change */
- info_buf.Attributes = cpu_to_le32(dosattr);
-
- return server->ops->set_file_info(inode, full_path, &info_buf, xid);
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-/*
- * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
- * and rename it to a random name that hopefully won't conflict with
- * anything else.
- */
-int
-cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
- const unsigned int xid)
-{
- int oplock = 0;
- int rc;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- struct inode *inode = d_inode(dentry);
- struct cifsInodeInfo *cifsInode = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- __u32 dosattr, origattr;
- FILE_BASIC_INFO *info_buf = NULL;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
-
- /*
- * We cannot rename the file if the server doesn't support
- * CAP_INFOLEVEL_PASSTHRU
- */
- if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
- rc = -EBUSY;
- goto out;
- }
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = DELETE | FILE_WRITE_ATTRIBUTES,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
- .disposition = FILE_OPEN,
- .path = full_path,
- .fid = &fid,
- };
-
- rc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (rc != 0)
- goto out;
-
- origattr = cifsInode->cifsAttrs;
- if (origattr == 0)
- origattr |= ATTR_NORMAL;
-
- dosattr = origattr & ~ATTR_READONLY;
- if (dosattr == 0)
- dosattr |= ATTR_NORMAL;
- dosattr |= ATTR_HIDDEN;
-
- /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
- if (dosattr != origattr) {
- info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
- if (info_buf == NULL) {
- rc = -ENOMEM;
- goto out_close;
- }
- info_buf->Attributes = cpu_to_le32(dosattr);
- rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
- current->tgid);
- /* although we would like to mark the file hidden
- if that fails we will still try to rename it */
- if (!rc)
- cifsInode->cifsAttrs = dosattr;
- else
- dosattr = origattr; /* since not able to change them */
- }
-
- /* rename the file */
- rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- if (rc != 0) {
- rc = -EBUSY;
- goto undo_setattr;
- }
-
- /* try to set DELETE_ON_CLOSE */
- if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
- rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
- current->tgid);
- /*
- * some samba versions return -ENOENT when we try to set the
- * file disposition here. Likely a samba bug, but work around
- * it for now. This means that some cifsXXX files may hang
- * around after they shouldn't.
- *
- * BB: remove this hack after more servers have the fix
- */
- if (rc == -ENOENT)
- rc = 0;
- else if (rc != 0) {
- rc = -EBUSY;
- goto undo_rename;
- }
- set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
- }
-
-out_close:
- CIFSSMBClose(xid, tcon, fid.netfid);
-out:
- kfree(info_buf);
- cifs_put_tlink(tlink);
- return rc;
-
- /*
- * reset everything back to the original state. Don't bother
- * dealing with errors here since we can't do anything about
- * them anyway.
- */
-undo_rename:
- CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
- cifs_sb->local_nls, cifs_remap(cifs_sb));
-undo_setattr:
- if (dosattr != origattr) {
- info_buf->Attributes = cpu_to_le32(origattr);
- if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
- current->tgid))
- cifsInode->cifsAttrs = origattr;
- }
-
- goto out_close;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-/* copied from fs/nfs/dir.c with small changes */
-static void
-cifs_drop_nlink(struct inode *inode)
-{
- spin_lock(&inode->i_lock);
- if (inode->i_nlink > 0)
- drop_nlink(inode);
- spin_unlock(&inode->i_lock);
-}
-
-/*
- * If d_inode(dentry) is null (usually meaning the cached dentry
- * is a negative dentry) then we would attempt a standard SMB delete, but
- * if that fails we can not attempt the fall back mechanisms on EACCES
- * but will return the EACCES to the caller. Note that the VFS does not call
- * unlink on negative dentries currently.
- */
-int cifs_unlink(struct inode *dir, struct dentry *dentry)
-{
- int rc = 0;
- unsigned int xid;
- const char *full_path;
- void *page;
- struct inode *inode = d_inode(dentry);
- struct cifsInodeInfo *cifs_inode;
- struct super_block *sb = dir->i_sb;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct iattr *attrs = NULL;
- __u32 dosattr = 0, origattr = 0;
-
- cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
-
- if (unlikely(cifs_forced_shutdown(cifs_sb)))
- return -EIO;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
- server = tcon->ses->server;
-
- xid = get_xid();
- page = alloc_dentry_path();
-
- if (tcon->nodelete) {
- rc = -EACCES;
- goto unlink_out;
- }
-
- /* Unlink can be called from rename so we can not take the
- * sb->s_vfs_rename_mutex here */
- full_path = build_path_from_dentry(dentry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto unlink_out;
- }
-
- cifs_close_deferred_file_under_dentry(tcon, full_path);
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))) {
- rc = CIFSPOSIXDelFile(xid, tcon, full_path,
- SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- cifs_dbg(FYI, "posix del rc %d\n", rc);
- if ((rc == 0) || (rc == -ENOENT))
- goto psx_del_no_retry;
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-retry_std_delete:
- if (!server->ops->unlink) {
- rc = -ENOSYS;
- goto psx_del_no_retry;
- }
-
- rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
-
-psx_del_no_retry:
- if (!rc) {
- if (inode)
- cifs_drop_nlink(inode);
- } else if (rc == -ENOENT) {
- d_drop(dentry);
- } else if (rc == -EBUSY) {
- if (server->ops->rename_pending_delete) {
- rc = server->ops->rename_pending_delete(full_path,
- dentry, xid);
- if (rc == 0)
- cifs_drop_nlink(inode);
- }
- } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
- attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
- if (attrs == NULL) {
- rc = -ENOMEM;
- goto out_reval;
- }
-
- /* try to reset dos attributes */
- cifs_inode = CIFS_I(inode);
- origattr = cifs_inode->cifsAttrs;
- if (origattr == 0)
- origattr |= ATTR_NORMAL;
- dosattr = origattr & ~ATTR_READONLY;
- if (dosattr == 0)
- dosattr |= ATTR_NORMAL;
- dosattr |= ATTR_HIDDEN;
-
- rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
- if (rc != 0)
- goto out_reval;
-
- goto retry_std_delete;
- }
-
- /* undo the setattr if we errored out and it's needed */
- if (rc != 0 && dosattr != 0)
- cifs_set_file_info(inode, attrs, xid, full_path, origattr);
-
-out_reval:
- if (inode) {
- cifs_inode = CIFS_I(inode);
- cifs_inode->time = 0; /* will force revalidate to get info
- when needed */
- inode->i_ctime = current_time(inode);
- }
- dir->i_ctime = dir->i_mtime = current_time(dir);
- cifs_inode = CIFS_I(dir);
- CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
-unlink_out:
- free_dentry_path(page);
- kfree(attrs);
- free_xid(xid);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-static int
-cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
- const char *full_path, struct cifs_sb_info *cifs_sb,
- struct cifs_tcon *tcon, const unsigned int xid)
-{
- int rc = 0;
- struct inode *inode = NULL;
-
- if (tcon->posix_extensions)
- rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- else if (tcon->unix_ext)
- rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
- xid);
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- else
- rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
- xid, NULL);
-
- if (rc)
- return rc;
-
- if (!S_ISDIR(inode->i_mode)) {
- /*
- * mkdir succeeded, but another client has managed to remove the
- * sucker and replace it with non-directory. Return success,
- * but don't leave the child in dcache.
- */
- iput(inode);
- d_drop(dentry);
- return 0;
- }
- /*
- * setting nlink not necessary except in cases where we failed to get it
- * from the server or was set bogus. Also, since this is a brand new
- * inode, no need to grab the i_lock before setting the i_nlink.
- */
- if (inode->i_nlink < 2)
- set_nlink(inode, 2);
- mode &= ~current_umask();
- /* must turn on setgid bit if parent dir has it */
- if (parent->i_mode & S_ISGID)
- mode |= S_ISGID;
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (tcon->unix_ext) {
- struct cifs_unix_set_info_args args = {
- .mode = mode,
- .ctime = NO_CHANGE_64,
- .atime = NO_CHANGE_64,
- .mtime = NO_CHANGE_64,
- .device = 0,
- };
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = current_fsuid();
- if (parent->i_mode & S_ISGID)
- args.gid = parent->i_gid;
- else
- args.gid = current_fsgid();
- } else {
- args.uid = INVALID_UID; /* no change */
- args.gid = INVALID_GID; /* no change */
- }
- CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- } else {
-#else
- {
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- struct TCP_Server_Info *server = tcon->ses->server;
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
- (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
- server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
- tcon, xid);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
- inode->i_mode = (mode | S_IFDIR);
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- inode->i_uid = current_fsuid();
- if (inode->i_mode & S_ISGID)
- inode->i_gid = parent->i_gid;
- else
- inode->i_gid = current_fsgid();
- }
- }
- d_instantiate(dentry, inode);
- return 0;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-static int
-cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
- const char *full_path, struct cifs_sb_info *cifs_sb,
- struct cifs_tcon *tcon, const unsigned int xid)
-{
- int rc = 0;
- u32 oplock = 0;
- FILE_UNIX_BASIC_INFO *info = NULL;
- struct inode *newinode = NULL;
- struct cifs_fattr fattr;
-
- info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
- if (info == NULL) {
- rc = -ENOMEM;
- goto posix_mkdir_out;
- }
-
- mode &= ~current_umask();
- rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
- NULL /* netfid */, info, &oplock, full_path,
- cifs_sb->local_nls, cifs_remap(cifs_sb));
- if (rc == -EOPNOTSUPP)
- goto posix_mkdir_out;
- else if (rc) {
- cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
- d_drop(dentry);
- goto posix_mkdir_out;
- }
-
- if (info->Type == cpu_to_le32(-1))
- /* no return info, go query for it */
- goto posix_mkdir_get_info;
- /*
- * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
- * need to set uid/gid.
- */
-
- cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
- cifs_fill_uniqueid(inode->i_sb, &fattr);
- newinode = cifs_iget(inode->i_sb, &fattr);
- if (!newinode)
- goto posix_mkdir_get_info;
-
- d_instantiate(dentry, newinode);
-
-#ifdef CONFIG_CIFS_DEBUG2
- cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
- dentry, dentry, newinode);
-
- if (newinode->i_nlink != 2)
- cifs_dbg(FYI, "unexpected number of links %d\n",
- newinode->i_nlink);
-#endif
-
-posix_mkdir_out:
- kfree(info);
- return rc;
-posix_mkdir_get_info:
- rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
- xid);
- goto posix_mkdir_out;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode,
- struct dentry *direntry, umode_t mode)
-{
- int rc = 0;
- unsigned int xid;
- struct cifs_sb_info *cifs_sb;
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- const char *full_path;
- void *page;
-
- cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
- mode, inode);
-
- cifs_sb = CIFS_SB(inode->i_sb);
- if (unlikely(cifs_forced_shutdown(cifs_sb)))
- return -EIO;
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
-
- xid = get_xid();
-
- page = alloc_dentry_path();
- full_path = build_path_from_dentry(direntry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto mkdir_out;
- }
-
- server = tcon->ses->server;
-
- if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
- rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
- cifs_sb);
- d_drop(direntry); /* for time being always refresh inode info */
- goto mkdir_out;
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
- le64_to_cpu(tcon->fsUnixInfo.Capability))) {
- rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
- tcon, xid);
- if (rc != -EOPNOTSUPP)
- goto mkdir_out;
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- if (!server->ops->mkdir) {
- rc = -ENOSYS;
- goto mkdir_out;
- }
-
- /* BB add setting the equivalent of mode via CreateX w/ACLs */
- rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
- if (rc) {
- cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
- d_drop(direntry);
- goto mkdir_out;
- }
-
- /* TODO: skip this for smb2/smb3 */
- rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
- xid);
-mkdir_out:
- /*
- * Force revalidate to get parent dir info when needed since cached
- * attributes are invalid now.
- */
- CIFS_I(inode)->time = 0;
- free_dentry_path(page);
- free_xid(xid);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-int cifs_rmdir(struct inode *inode, struct dentry *direntry)
-{
- int rc = 0;
- unsigned int xid;
- struct cifs_sb_info *cifs_sb;
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- const char *full_path;
- void *page = alloc_dentry_path();
- struct cifsInodeInfo *cifsInode;
-
- cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
-
- xid = get_xid();
-
- full_path = build_path_from_dentry(direntry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto rmdir_exit;
- }
-
- cifs_sb = CIFS_SB(inode->i_sb);
- if (unlikely(cifs_forced_shutdown(cifs_sb))) {
- rc = -EIO;
- goto rmdir_exit;
- }
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink)) {
- rc = PTR_ERR(tlink);
- goto rmdir_exit;
- }
- tcon = tlink_tcon(tlink);
- server = tcon->ses->server;
-
- if (!server->ops->rmdir) {
- rc = -ENOSYS;
- cifs_put_tlink(tlink);
- goto rmdir_exit;
- }
-
- if (tcon->nodelete) {
- rc = -EACCES;
- cifs_put_tlink(tlink);
- goto rmdir_exit;
- }
-
- rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
- cifs_put_tlink(tlink);
-
- if (!rc) {
- spin_lock(&d_inode(direntry)->i_lock);
- i_size_write(d_inode(direntry), 0);
- clear_nlink(d_inode(direntry));
- spin_unlock(&d_inode(direntry)->i_lock);
- }
-
- cifsInode = CIFS_I(d_inode(direntry));
- /* force revalidate to go get info when needed */
- cifsInode->time = 0;
-
- cifsInode = CIFS_I(inode);
- /*
- * Force revalidate to get parent dir info when needed since cached
- * attributes are invalid now.
- */
- cifsInode->time = 0;
-
- d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
- current_time(inode);
-
-rmdir_exit:
- free_dentry_path(page);
- free_xid(xid);
- return rc;
-}
-
-static int
-cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
- const char *from_path, struct dentry *to_dentry,
- const char *to_path)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- int oplock;
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- int rc;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
- server = tcon->ses->server;
-
- if (!server->ops->rename)
- return -ENOSYS;
-
- /* try path-based rename first */
- rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
-
- /*
- * Don't bother with rename by filehandle unless file is busy and
- * source. Note that cross directory moves do not work with
- * rename by filehandle to various Windows servers.
- */
- if (rc == 0 || rc != -EBUSY)
- goto do_rename_exit;
-
- /* Don't fall back to using SMB on SMB 2+ mount */
- if (server->vals->protocol_id != 0)
- goto do_rename_exit;
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- /* open-file renames don't work across directories */
- if (to_dentry->d_parent != from_dentry->d_parent)
- goto do_rename_exit;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- /* open the file to be renamed -- we need DELETE perms */
- .desired_access = DELETE,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
- .disposition = FILE_OPEN,
- .path = from_path,
- .fid = &fid,
- };
-
- rc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (rc == 0) {
- rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
- (const char *) to_dentry->d_name.name,
- cifs_sb->local_nls, cifs_remap(cifs_sb));
- CIFSSMBClose(xid, tcon, fid.netfid);
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-do_rename_exit:
- if (rc == 0)
- d_move(from_dentry, to_dentry);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-int
-cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
- struct dentry *source_dentry, struct inode *target_dir,
- struct dentry *target_dentry, unsigned int flags)
-{
- const char *from_name, *to_name;
- void *page1, *page2;
- struct cifs_sb_info *cifs_sb;
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- unsigned int xid;
- int rc, tmprc;
- int retry_count = 0;
- FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- FILE_UNIX_BASIC_INFO *info_buf_target;
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- if (flags & ~RENAME_NOREPLACE)
- return -EINVAL;
-
- cifs_sb = CIFS_SB(source_dir->i_sb);
- if (unlikely(cifs_forced_shutdown(cifs_sb)))
- return -EIO;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
-
- page1 = alloc_dentry_path();
- page2 = alloc_dentry_path();
- xid = get_xid();
-
- from_name = build_path_from_dentry(source_dentry, page1);
- if (IS_ERR(from_name)) {
- rc = PTR_ERR(from_name);
- goto cifs_rename_exit;
- }
-
- to_name = build_path_from_dentry(target_dentry, page2);
- if (IS_ERR(to_name)) {
- rc = PTR_ERR(to_name);
- goto cifs_rename_exit;
- }
-
- cifs_close_deferred_file_under_dentry(tcon, from_name);
- if (d_inode(target_dentry) != NULL)
- cifs_close_deferred_file_under_dentry(tcon, to_name);
-
- rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
- to_name);
-
- if (rc == -EACCES) {
- while (retry_count < 3) {
- cifs_close_all_deferred_files(tcon);
- rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
- to_name);
- if (rc != -EACCES)
- break;
- retry_count++;
- }
- }
-
- /*
- * No-replace is the natural behavior for CIFS, so skip unlink hacks.
- */
- if (flags & RENAME_NOREPLACE)
- goto cifs_rename_exit;
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (rc == -EEXIST && tcon->unix_ext) {
- /*
- * Are src and dst hardlinks of same inode? We can only tell
- * with unix extensions enabled.
- */
- info_buf_source =
- kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
- GFP_KERNEL);
- if (info_buf_source == NULL) {
- rc = -ENOMEM;
- goto cifs_rename_exit;
- }
-
- info_buf_target = info_buf_source + 1;
- tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
- info_buf_source,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- if (tmprc != 0)
- goto unlink_target;
-
- tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
- info_buf_target,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
-
- if (tmprc == 0 && (info_buf_source->UniqueId ==
- info_buf_target->UniqueId)) {
- /* same file, POSIX says that this is a noop */
- rc = 0;
- goto cifs_rename_exit;
- }
- }
- /*
- * else ... BB we could add the same check for Windows by
- * checking the UniqueId via FILE_INTERNAL_INFO
- */
-
-unlink_target:
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- /* Try unlinking the target dentry if it's not negative */
- if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
- if (d_is_dir(target_dentry))
- tmprc = cifs_rmdir(target_dir, target_dentry);
- else
- tmprc = cifs_unlink(target_dir, target_dentry);
- if (tmprc)
- goto cifs_rename_exit;
- rc = cifs_do_rename(xid, source_dentry, from_name,
- target_dentry, to_name);
- }
-
- /* force revalidate to go get info when needed */
- CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
-
- source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
- target_dir->i_mtime = current_time(source_dir);
-
-cifs_rename_exit:
- kfree(info_buf_source);
- free_dentry_path(page2);
- free_dentry_path(page1);
- free_xid(xid);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-static bool
-cifs_dentry_needs_reval(struct dentry *dentry)
-{
- struct inode *inode = d_inode(dentry);
- struct cifsInodeInfo *cifs_i = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- struct cached_fid *cfid = NULL;
-
- if (cifs_i->time == 0)
- return true;
-
- if (CIFS_CACHE_READ(cifs_i))
- return false;
-
- if (!lookupCacheEnabled)
- return true;
-
- if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {
- spin_lock(&cfid->fid_lock);
- if (cfid->time && cifs_i->time > cfid->time) {
- spin_unlock(&cfid->fid_lock);
- close_cached_dir(cfid);
- return false;
- }
- spin_unlock(&cfid->fid_lock);
- close_cached_dir(cfid);
- }
- /*
- * depending on inode type, check if attribute caching disabled for
- * files or directories
- */
- if (S_ISDIR(inode->i_mode)) {
- if (!cifs_sb->ctx->acdirmax)
- return true;
- if (!time_in_range(jiffies, cifs_i->time,
- cifs_i->time + cifs_sb->ctx->acdirmax))
- return true;
- } else { /* file */
- if (!cifs_sb->ctx->acregmax)
- return true;
- if (!time_in_range(jiffies, cifs_i->time,
- cifs_i->time + cifs_sb->ctx->acregmax))
- return true;
- }
-
- /* hardlinked files w/ noserverino get "special" treatment */
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
- S_ISREG(inode->i_mode) && inode->i_nlink != 1)
- return true;
-
- return false;
-}
-
-/*
- * Zap the cache. Called when invalid_mapping flag is set.
- */
-int
-cifs_invalidate_mapping(struct inode *inode)
-{
- int rc = 0;
-
- if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
- rc = invalidate_inode_pages2(inode->i_mapping);
- if (rc)
- cifs_dbg(VFS, "%s: Could not invalidate inode %p\n",
- __func__, inode);
- }
-
- return rc;
-}
-
-/**
- * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
- *
- * @key: currently unused
- * @mode: the task state to sleep in
- */
-static int
-cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
-{
- schedule();
- if (signal_pending_state(mode, current))
- return -ERESTARTSYS;
- return 0;
-}
-
-int
-cifs_revalidate_mapping(struct inode *inode)
-{
- int rc;
- unsigned long *flags = &CIFS_I(inode)->flags;
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-
- /* swapfiles are not supposed to be shared */
- if (IS_SWAPFILE(inode))
- return 0;
-
- rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
- TASK_KILLABLE|TASK_FREEZABLE_UNSAFE);
- if (rc)
- return rc;
-
- if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
- /* for cache=singleclient, do not invalidate */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
- goto skip_invalidate;
-
- rc = cifs_invalidate_mapping(inode);
- if (rc)
- set_bit(CIFS_INO_INVALID_MAPPING, flags);
- }
-
-skip_invalidate:
- clear_bit_unlock(CIFS_INO_LOCK, flags);
- smp_mb__after_atomic();
- wake_up_bit(flags, CIFS_INO_LOCK);
-
- return rc;
-}
-
-int
-cifs_zap_mapping(struct inode *inode)
-{
- set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
- return cifs_revalidate_mapping(inode);
-}
-
-int cifs_revalidate_file_attr(struct file *filp)
-{
- int rc = 0;
- struct dentry *dentry = file_dentry(filp);
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- if (!cifs_dentry_needs_reval(dentry))
- return rc;
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (tlink_tcon(cfile->tlink)->unix_ext)
- rc = cifs_get_file_info_unix(filp);
- else
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- rc = cifs_get_file_info(filp);
-
- return rc;
-}
-
-int cifs_revalidate_dentry_attr(struct dentry *dentry)
-{
- unsigned int xid;
- int rc = 0;
- struct inode *inode = d_inode(dentry);
- struct super_block *sb = dentry->d_sb;
- const char *full_path;
- void *page;
- int count = 0;
-
- if (inode == NULL)
- return -ENOENT;
-
- if (!cifs_dentry_needs_reval(dentry))
- return rc;
-
- xid = get_xid();
-
- page = alloc_dentry_path();
- full_path = build_path_from_dentry(dentry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto out;
- }
-
- cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
- full_path, inode, inode->i_count.counter,
- dentry, cifs_get_time(dentry), jiffies);
-
-again:
- if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
- rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
- else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
- rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
- else
- rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
- xid, NULL);
- if (rc == -EAGAIN && count++ < 10)
- goto again;
-out:
- free_dentry_path(page);
- free_xid(xid);
-
- return rc;
-}
-
-int cifs_revalidate_file(struct file *filp)
-{
- int rc;
- struct inode *inode = file_inode(filp);
-
- rc = cifs_revalidate_file_attr(filp);
- if (rc)
- return rc;
-
- return cifs_revalidate_mapping(inode);
-}
-
-/* revalidate a dentry's inode attributes */
-int cifs_revalidate_dentry(struct dentry *dentry)
-{
- int rc;
- struct inode *inode = d_inode(dentry);
-
- rc = cifs_revalidate_dentry_attr(dentry);
- if (rc)
- return rc;
-
- return cifs_revalidate_mapping(inode);
-}
-
-int cifs_getattr(struct user_namespace *mnt_userns, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
-{
- struct dentry *dentry = path->dentry;
- struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- struct inode *inode = d_inode(dentry);
- int rc;
-
- if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
- return -EIO;
-
- /*
- * We need to be sure that all dirty pages are written and the server
- * has actual ctime, mtime and file length.
- */
- if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE | STATX_BLOCKS)) &&
- !CIFS_CACHE_READ(CIFS_I(inode)) &&
- inode->i_mapping && inode->i_mapping->nrpages != 0) {
- rc = filemap_fdatawait(inode->i_mapping);
- if (rc) {
- mapping_set_error(inode->i_mapping, rc);
- return rc;
- }
- }
-
- if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC)
- CIFS_I(inode)->time = 0; /* force revalidate */
-
- /*
- * If the caller doesn't require syncing, only sync if
- * necessary (e.g. due to earlier truncate or setattr
- * invalidating the cached metadata)
- */
- if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) ||
- (CIFS_I(inode)->time == 0)) {
- rc = cifs_revalidate_dentry_attr(dentry);
- if (rc)
- return rc;
- }
-
- generic_fillattr(&init_user_ns, inode, stat);
- stat->blksize = cifs_sb->ctx->bsize;
- stat->ino = CIFS_I(inode)->uniqueid;
-
- /* old CIFS Unix Extensions doesn't return create time */
- if (CIFS_I(inode)->createtime) {
- stat->result_mask |= STATX_BTIME;
- stat->btime =
- cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
- }
-
- stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
- if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
- stat->attributes |= STATX_ATTR_COMPRESSED;
- if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
- stat->attributes |= STATX_ATTR_ENCRYPTED;
-
- /*
- * If on a multiuser mount without unix extensions or cifsacl being
- * enabled, and the admin hasn't overridden them, set the ownership
- * to the fsuid/fsgid of the current process.
- */
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
- !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
- !tcon->unix_ext) {
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
- stat->uid = current_fsuid();
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
- stat->gid = current_fsgid();
- }
- return 0;
-}
-
-int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
- u64 len)
-{
- struct cifsInodeInfo *cifs_i = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->netfs.inode.i_sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- struct TCP_Server_Info *server = tcon->ses->server;
- struct cifsFileInfo *cfile;
- int rc;
-
- if (unlikely(cifs_forced_shutdown(cifs_sb)))
- return -EIO;
-
- /*
- * We need to be sure that all dirty pages are written as they
- * might fill holes on the server.
- */
- if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
- inode->i_mapping->nrpages != 0) {
- rc = filemap_fdatawait(inode->i_mapping);
- if (rc) {
- mapping_set_error(inode->i_mapping, rc);
- return rc;
- }
- }
-
- cfile = find_readable_file(cifs_i, false);
- if (cfile == NULL)
- return -EINVAL;
-
- if (server->ops->fiemap) {
- rc = server->ops->fiemap(tcon, cfile, fei, start, len);
- cifsFileInfo_put(cfile);
- return rc;
- }
-
- cifsFileInfo_put(cfile);
- return -ENOTSUPP;
-}
-
-int cifs_truncate_page(struct address_space *mapping, loff_t from)
-{
- pgoff_t index = from >> PAGE_SHIFT;
- unsigned offset = from & (PAGE_SIZE - 1);
- struct page *page;
- int rc = 0;
-
- page = grab_cache_page(mapping, index);
- if (!page)
- return -ENOMEM;
-
- zero_user_segment(page, offset, PAGE_SIZE);
- unlock_page(page);
- put_page(page);
- return rc;
-}
-
-void cifs_setsize(struct inode *inode, loff_t offset)
-{
- struct cifsInodeInfo *cifs_i = CIFS_I(inode);
-
- spin_lock(&inode->i_lock);
- i_size_write(inode, offset);
- spin_unlock(&inode->i_lock);
-
- /* Cached inode must be refreshed on truncate */
- cifs_i->time = 0;
- truncate_pagecache(inode, offset);
-}
-
-static int
-cifs_set_file_size(struct inode *inode, struct iattr *attrs,
- unsigned int xid, const char *full_path)
-{
- int rc;
- struct cifsFileInfo *open_file;
- struct cifsInodeInfo *cifsInode = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink = NULL;
- struct cifs_tcon *tcon = NULL;
- struct TCP_Server_Info *server;
-
- /*
- * To avoid spurious oplock breaks from server, in the case of
- * inodes that we already have open, avoid doing path based
- * setting of file size if we can do it by handle.
- * This keeps our caching token (oplock) and avoids timeouts
- * when the local oplock break takes longer to flush
- * writebehind data than the SMB timeout for the SetPathInfo
- * request would allow
- */
- open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
- if (open_file) {
- tcon = tlink_tcon(open_file->tlink);
- server = tcon->ses->server;
- if (server->ops->set_file_size)
- rc = server->ops->set_file_size(xid, tcon, open_file,
- attrs->ia_size, false);
- else
- rc = -ENOSYS;
- cifsFileInfo_put(open_file);
- cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
- } else
- rc = -EINVAL;
-
- if (!rc)
- goto set_size_out;
-
- if (tcon == NULL) {
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
- server = tcon->ses->server;
- }
-
- /*
- * Set file size by pathname rather than by handle either because no
- * valid, writeable file handle for it was found or because there was
- * an error setting it by handle.
- */
- if (server->ops->set_path_size)
- rc = server->ops->set_path_size(xid, tcon, full_path,
- attrs->ia_size, cifs_sb, false);
- else
- rc = -ENOSYS;
- cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
-
- if (tlink)
- cifs_put_tlink(tlink);
-
-set_size_out:
- if (rc == 0) {
- cifsInode->server_eof = attrs->ia_size;
- cifs_setsize(inode, attrs->ia_size);
- /*
- * i_blocks is not related to (i_size / i_blksize), but instead
- * 512 byte (2**9) size is required for calculating num blocks.
- * Until we can query the server for actual allocation size,
- * this is best estimate we have for blocks allocated for a file
- * Number of blocks must be rounded up so size 1 is not 0 blocks
- */
- inode->i_blocks = (512 - 1 + attrs->ia_size) >> 9;
-
- /*
- * The man page of truncate says if the size changed,
- * then the st_ctime and st_mtime fields for the file
- * are updated.
- */
- attrs->ia_ctime = attrs->ia_mtime = current_time(inode);
- attrs->ia_valid |= ATTR_CTIME | ATTR_MTIME;
-
- cifs_truncate_page(inode->i_mapping, inode->i_size);
- }
-
- return rc;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-static int
-cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
-{
- int rc;
- unsigned int xid;
- const char *full_path;
- void *page = alloc_dentry_path();
- struct inode *inode = d_inode(direntry);
- struct cifsInodeInfo *cifsInode = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink;
- struct cifs_tcon *pTcon;
- struct cifs_unix_set_info_args *args = NULL;
- struct cifsFileInfo *open_file;
-
- cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
- direntry, attrs->ia_valid);
-
- xid = get_xid();
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
- attrs->ia_valid |= ATTR_FORCE;
-
- rc = setattr_prepare(&init_user_ns, direntry, attrs);
- if (rc < 0)
- goto out;
-
- full_path = build_path_from_dentry(direntry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto out;
- }
-
- /*
- * Attempt to flush data before changing attributes. We need to do
- * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
- * ownership or mode then we may also need to do this. Here, we take
- * the safe way out and just do the flush on all setattr requests. If
- * the flush returns error, store it to report later and continue.
- *
- * BB: This should be smarter. Why bother flushing pages that
- * will be truncated anyway? Also, should we error out here if
- * the flush returns error?
- */
- rc = filemap_write_and_wait(inode->i_mapping);
- if (is_interrupt_error(rc)) {
- rc = -ERESTARTSYS;
- goto out;
- }
-
- mapping_set_error(inode->i_mapping, rc);
- rc = 0;
-
- if (attrs->ia_valid & ATTR_SIZE) {
- rc = cifs_set_file_size(inode, attrs, xid, full_path);
- if (rc != 0)
- goto out;
- }
-
- /* skip mode change if it's just for clearing setuid/setgid */
- if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
- attrs->ia_valid &= ~ATTR_MODE;
-
- args = kmalloc(sizeof(*args), GFP_KERNEL);
- if (args == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- /* set up the struct */
- if (attrs->ia_valid & ATTR_MODE)
- args->mode = attrs->ia_mode;
- else
- args->mode = NO_CHANGE_64;
-
- if (attrs->ia_valid & ATTR_UID)
- args->uid = attrs->ia_uid;
- else
- args->uid = INVALID_UID; /* no change */
-
- if (attrs->ia_valid & ATTR_GID)
- args->gid = attrs->ia_gid;
- else
- args->gid = INVALID_GID; /* no change */
-
- if (attrs->ia_valid & ATTR_ATIME)
- args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
- else
- args->atime = NO_CHANGE_64;
-
- if (attrs->ia_valid & ATTR_MTIME)
- args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
- else
- args->mtime = NO_CHANGE_64;
-
- if (attrs->ia_valid & ATTR_CTIME)
- args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
- else
- args->ctime = NO_CHANGE_64;
-
- args->device = 0;
- open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
- if (open_file) {
- u16 nfid = open_file->fid.netfid;
- u32 npid = open_file->pid;
- pTcon = tlink_tcon(open_file->tlink);
- rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
- cifsFileInfo_put(open_file);
- } else {
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink)) {
- rc = PTR_ERR(tlink);
- goto out;
- }
- pTcon = tlink_tcon(tlink);
- rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- cifs_put_tlink(tlink);
- }
-
- if (rc)
- goto out;
-
- if ((attrs->ia_valid & ATTR_SIZE) &&
- attrs->ia_size != i_size_read(inode)) {
- truncate_setsize(inode, attrs->ia_size);
- fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size);
- }
-
- setattr_copy(&init_user_ns, inode, attrs);
- mark_inode_dirty(inode);
-
- /* force revalidate when any of these times are set since some
- of the fs types (eg ext3, fat) do not have fine enough
- time granularity to match protocol, and we do not have a
- a way (yet) to query the server fs's time granularity (and
- whether it rounds times down).
- */
- if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
- cifsInode->time = 0;
-out:
- kfree(args);
- free_dentry_path(page);
- free_xid(xid);
- return rc;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-static int
-cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
-{
- unsigned int xid;
- kuid_t uid = INVALID_UID;
- kgid_t gid = INVALID_GID;
- struct inode *inode = d_inode(direntry);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifsInodeInfo *cifsInode = CIFS_I(inode);
- struct cifsFileInfo *wfile;
- struct cifs_tcon *tcon;
- const char *full_path;
- void *page = alloc_dentry_path();
- int rc = -EACCES;
- __u32 dosattr = 0;
- __u64 mode = NO_CHANGE_64;
-
- xid = get_xid();
-
- cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
- direntry, attrs->ia_valid);
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
- attrs->ia_valid |= ATTR_FORCE;
-
- rc = setattr_prepare(&init_user_ns, direntry, attrs);
- if (rc < 0)
- goto cifs_setattr_exit;
-
- full_path = build_path_from_dentry(direntry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto cifs_setattr_exit;
- }
-
- /*
- * Attempt to flush data before changing attributes. We need to do
- * this for ATTR_SIZE and ATTR_MTIME. If the flush of the data
- * returns error, store it to report later and continue.
- *
- * BB: This should be smarter. Why bother flushing pages that
- * will be truncated anyway? Also, should we error out here if
- * the flush returns error? Do we need to check for ATTR_MTIME_SET flag?
- */
- if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) {
- rc = filemap_write_and_wait(inode->i_mapping);
- if (is_interrupt_error(rc)) {
- rc = -ERESTARTSYS;
- goto cifs_setattr_exit;
- }
- mapping_set_error(inode->i_mapping, rc);
- }
-
- rc = 0;
-
- if ((attrs->ia_valid & ATTR_MTIME) &&
- !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
- rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
- if (!rc) {
- tcon = tlink_tcon(wfile->tlink);
- rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
- cifsFileInfo_put(wfile);
- if (rc)
- goto cifs_setattr_exit;
- } else if (rc != -EBADF)
- goto cifs_setattr_exit;
- else
- rc = 0;
- }
-
- if (attrs->ia_valid & ATTR_SIZE) {
- rc = cifs_set_file_size(inode, attrs, xid, full_path);
- if (rc != 0)
- goto cifs_setattr_exit;
- }
-
- if (attrs->ia_valid & ATTR_UID)
- uid = attrs->ia_uid;
-
- if (attrs->ia_valid & ATTR_GID)
- gid = attrs->ia_gid;
-
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
- (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
- if (uid_valid(uid) || gid_valid(gid)) {
- mode = NO_CHANGE_64;
- rc = id_mode_to_cifs_acl(inode, full_path, &mode,
- uid, gid);
- if (rc) {
- cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
- __func__, rc);
- goto cifs_setattr_exit;
- }
- }
- } else
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
- attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
-
- /* skip mode change if it's just for clearing setuid/setgid */
- if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
- attrs->ia_valid &= ~ATTR_MODE;
-
- if (attrs->ia_valid & ATTR_MODE) {
- mode = attrs->ia_mode;
- rc = 0;
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
- (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
- rc = id_mode_to_cifs_acl(inode, full_path, &mode,
- INVALID_UID, INVALID_GID);
- if (rc) {
- cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
- __func__, rc);
- goto cifs_setattr_exit;
- }
-
- /*
- * In case of CIFS_MOUNT_CIFS_ACL, we cannot support all modes.
- * Pick up the actual mode bits that were set.
- */
- if (mode != attrs->ia_mode)
- attrs->ia_mode = mode;
- } else
- if (((mode & S_IWUGO) == 0) &&
- (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
-
- dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
-
- /* fix up mode if we're not using dynperm */
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
- attrs->ia_mode = inode->i_mode & ~S_IWUGO;
- } else if ((mode & S_IWUGO) &&
- (cifsInode->cifsAttrs & ATTR_READONLY)) {
-
- dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
- /* Attributes of 0 are ignored */
- if (dosattr == 0)
- dosattr |= ATTR_NORMAL;
-
- /* reset local inode permissions to normal */
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
- attrs->ia_mode &= ~(S_IALLUGO);
- if (S_ISDIR(inode->i_mode))
- attrs->ia_mode |=
- cifs_sb->ctx->dir_mode;
- else
- attrs->ia_mode |=
- cifs_sb->ctx->file_mode;
- }
- } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
- /* ignore mode change - ATTR_READONLY hasn't changed */
- attrs->ia_valid &= ~ATTR_MODE;
- }
- }
-
- if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
- ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
- rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
- /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
-
- /* Even if error on time set, no sense failing the call if
- the server would set the time to a reasonable value anyway,
- and this check ensures that we are not being called from
- sys_utimes in which case we ought to fail the call back to
- the user when the server rejects the call */
- if ((rc) && (attrs->ia_valid &
- (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
- rc = 0;
- }
-
- /* do not need local check to inode_check_ok since the server does
- that */
- if (rc)
- goto cifs_setattr_exit;
-
- if ((attrs->ia_valid & ATTR_SIZE) &&
- attrs->ia_size != i_size_read(inode)) {
- truncate_setsize(inode, attrs->ia_size);
- fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size);
- }
-
- setattr_copy(&init_user_ns, inode, attrs);
- mark_inode_dirty(inode);
-
-cifs_setattr_exit:
- free_xid(xid);
- free_dentry_path(page);
- return rc;
-}
-
-int
-cifs_setattr(struct user_namespace *mnt_userns, struct dentry *direntry,
- struct iattr *attrs)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
- int rc, retries = 0;
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
- if (unlikely(cifs_forced_shutdown(cifs_sb)))
- return -EIO;
-
- do {
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (pTcon->unix_ext)
- rc = cifs_setattr_unix(direntry, attrs);
- else
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- rc = cifs_setattr_nounix(direntry, attrs);
- retries++;
- } while (is_retryable_error(rc) && retries < 2);
-
- /* BB: add cifs_setattr_legacy for really old servers */
- return rc;
-}
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
deleted file mode 100644
index 6419ec47c2a8..000000000000
--- a/fs/cifs/ioctl.c
+++ /dev/null
@@ -1,526 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * vfs operations that deal with io control
- *
- * Copyright (C) International Business Machines Corp., 2005,2013
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/mount.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifsfs.h"
-#include "cifs_ioctl.h"
-#include "smb2proto.h"
-#include "smb2glob.h"
-#include <linux/btrfs.h>
-
-static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
- unsigned long p)
-{
- struct inode *inode = file_inode(filep);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- struct dentry *dentry = filep->f_path.dentry;
- const unsigned char *path;
- void *page = alloc_dentry_path();
- __le16 *utf16_path = NULL, root_path;
- int rc = 0;
-
- path = build_path_from_dentry(dentry, page);
- if (IS_ERR(path)) {
- free_dentry_path(page);
- return PTR_ERR(path);
- }
-
- cifs_dbg(FYI, "%s %s\n", __func__, path);
-
- if (!path[0]) {
- root_path = 0;
- utf16_path = &root_path;
- } else {
- utf16_path = cifs_convert_path_to_utf16(path + 1, cifs_sb);
- if (!utf16_path) {
- rc = -ENOMEM;
- goto ici_exit;
- }
- }
-
- if (tcon->ses->server->ops->ioctl_query_info)
- rc = tcon->ses->server->ops->ioctl_query_info(
- xid, tcon, cifs_sb, utf16_path,
- filep->private_data ? 0 : 1, p);
- else
- rc = -EOPNOTSUPP;
-
- ici_exit:
- if (utf16_path != &root_path)
- kfree(utf16_path);
- free_dentry_path(page);
- return rc;
-}
-
-static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
- unsigned long srcfd)
-{
- int rc;
- struct fd src_file;
- struct inode *src_inode;
-
- cifs_dbg(FYI, "ioctl copychunk range\n");
- /* the destination must be opened for writing */
- if (!(dst_file->f_mode & FMODE_WRITE)) {
- cifs_dbg(FYI, "file target not open for write\n");
- return -EINVAL;
- }
-
- /* check if target volume is readonly and take reference */
- rc = mnt_want_write_file(dst_file);
- if (rc) {
- cifs_dbg(FYI, "mnt_want_write failed with rc %d\n", rc);
- return rc;
- }
-
- src_file = fdget(srcfd);
- if (!src_file.file) {
- rc = -EBADF;
- goto out_drop_write;
- }
-
- if (src_file.file->f_op->unlocked_ioctl != cifs_ioctl) {
- rc = -EBADF;
- cifs_dbg(VFS, "src file seems to be from a different filesystem type\n");
- goto out_fput;
- }
-
- src_inode = file_inode(src_file.file);
- rc = -EINVAL;
- if (S_ISDIR(src_inode->i_mode))
- goto out_fput;
-
- rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
- src_inode->i_size, 0);
- if (rc > 0)
- rc = 0;
-out_fput:
- fdput(src_file);
-out_drop_write:
- mnt_drop_write_file(dst_file);
- return rc;
-}
-
-static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
- void __user *arg)
-{
- int rc = 0;
- struct smb_mnt_fs_info *fsinf;
-
- fsinf = kzalloc(sizeof(struct smb_mnt_fs_info), GFP_KERNEL);
- if (fsinf == NULL)
- return -ENOMEM;
-
- fsinf->version = 1;
- fsinf->protocol_id = tcon->ses->server->vals->protocol_id;
- fsinf->device_characteristics =
- le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics);
- fsinf->device_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
- fsinf->fs_attributes = le32_to_cpu(tcon->fsAttrInfo.Attributes);
- fsinf->max_path_component =
- le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength);
- fsinf->vol_serial_number = tcon->vol_serial_number;
- fsinf->vol_create_time = le64_to_cpu(tcon->vol_create_time);
- fsinf->share_flags = tcon->share_flags;
- fsinf->share_caps = le32_to_cpu(tcon->capabilities);
- fsinf->sector_flags = tcon->ss_flags;
- fsinf->optimal_sector_size = tcon->perf_sector_size;
- fsinf->max_bytes_chunk = tcon->max_bytes_chunk;
- fsinf->maximal_access = tcon->maximal_access;
- fsinf->cifs_posix_caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
-
- if (copy_to_user(arg, fsinf, sizeof(struct smb_mnt_fs_info)))
- rc = -EFAULT;
-
- kfree(fsinf);
- return rc;
-}
-
-static int cifs_shutdown(struct super_block *sb, unsigned long arg)
-{
- struct cifs_sb_info *sbi = CIFS_SB(sb);
- __u32 flags;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (get_user(flags, (__u32 __user *)arg))
- return -EFAULT;
-
- if (flags > CIFS_GOING_FLAGS_NOLOGFLUSH)
- return -EINVAL;
-
- if (cifs_forced_shutdown(sbi))
- return 0;
-
- cifs_dbg(VFS, "shut down requested (%d)", flags);
-/* trace_cifs_shutdown(sb, flags);*/
-
- /*
- * see:
- * https://man7.org/linux/man-pages/man2/ioctl_xfs_goingdown.2.html
- * for more information and description of original intent of the flags
- */
- switch (flags) {
- /*
- * We could add support later for default flag which requires:
- * "Flush all dirty data and metadata to disk"
- * would need to call syncfs or equivalent to flush page cache for
- * the mount and then issue fsync to server (if nostrictsync not set)
- */
- case CIFS_GOING_FLAGS_DEFAULT:
- cifs_dbg(FYI, "shutdown with default flag not supported\n");
- return -EINVAL;
- /*
- * FLAGS_LOGFLUSH is easy since it asks to write out metadata (not
- * data) but metadata writes are not cached on the client, so can treat
- * it similarly to NOLOGFLUSH
- */
- case CIFS_GOING_FLAGS_LOGFLUSH:
- case CIFS_GOING_FLAGS_NOLOGFLUSH:
- sbi->mnt_cifs_flags |= CIFS_MOUNT_SHUTDOWN;
- return 0;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug_info __user *in)
-{
- struct smb3_full_key_debug_info out;
- struct cifs_ses *ses;
- int rc = 0;
- bool found = false;
- u8 __user *end;
-
- if (!smb3_encryption_required(tcon)) {
- rc = -EOPNOTSUPP;
- goto out;
- }
-
- /* copy user input into our output buffer */
- if (copy_from_user(&out, in, sizeof(out))) {
- rc = -EINVAL;
- goto out;
- }
-
- if (!out.session_id) {
- /* if ses id is 0, use current user session */
- ses = tcon->ses;
- } else {
- /* otherwise if a session id is given, look for it in all our sessions */
- struct cifs_ses *ses_it = NULL;
- struct TCP_Server_Info *server_it = NULL;
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(server_it, &cifs_tcp_ses_list, tcp_ses_list) {
- list_for_each_entry(ses_it, &server_it->smb_ses_list, smb_ses_list) {
- if (ses_it->Suid == out.session_id) {
- ses = ses_it;
- /*
- * since we are using the session outside the crit
- * section, we need to make sure it won't be released
- * so increment its refcount
- */
- ses->ses_count++;
- found = true;
- goto search_end;
- }
- }
- }
-search_end:
- spin_unlock(&cifs_tcp_ses_lock);
- if (!found) {
- rc = -ENOENT;
- goto out;
- }
- }
-
- switch (ses->server->cipher_type) {
- case SMB2_ENCRYPTION_AES128_CCM:
- case SMB2_ENCRYPTION_AES128_GCM:
- out.session_key_length = CIFS_SESS_KEY_SIZE;
- out.server_in_key_length = out.server_out_key_length = SMB3_GCM128_CRYPTKEY_SIZE;
- break;
- case SMB2_ENCRYPTION_AES256_CCM:
- case SMB2_ENCRYPTION_AES256_GCM:
- out.session_key_length = CIFS_SESS_KEY_SIZE;
- out.server_in_key_length = out.server_out_key_length = SMB3_GCM256_CRYPTKEY_SIZE;
- break;
- default:
- rc = -EOPNOTSUPP;
- goto out;
- }
-
- /* check if user buffer is big enough to store all the keys */
- if (out.in_size < sizeof(out) + out.session_key_length + out.server_in_key_length
- + out.server_out_key_length) {
- rc = -ENOBUFS;
- goto out;
- }
-
- out.session_id = ses->Suid;
- out.cipher_type = le16_to_cpu(ses->server->cipher_type);
-
- /* overwrite user input with our output */
- if (copy_to_user(in, &out, sizeof(out))) {
- rc = -EINVAL;
- goto out;
- }
-
- /* append all the keys at the end of the user buffer */
- end = in->data;
- if (copy_to_user(end, ses->auth_key.response, out.session_key_length)) {
- rc = -EINVAL;
- goto out;
- }
- end += out.session_key_length;
-
- if (copy_to_user(end, ses->smb3encryptionkey, out.server_in_key_length)) {
- rc = -EINVAL;
- goto out;
- }
- end += out.server_in_key_length;
-
- if (copy_to_user(end, ses->smb3decryptionkey, out.server_out_key_length)) {
- rc = -EINVAL;
- goto out;
- }
-
-out:
- if (found)
- cifs_put_smb_ses(ses);
- return rc;
-}
-
-long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
-{
- struct inode *inode = file_inode(filep);
- struct smb3_key_debug_info pkey_inf;
- int rc = -ENOTTY; /* strange error - but the precedent */
- unsigned int xid;
- struct cifsFileInfo *pSMBFile = filep->private_data;
- struct cifs_tcon *tcon;
- struct tcon_link *tlink;
- struct cifs_sb_info *cifs_sb;
- __u64 ExtAttrBits = 0;
- __u64 caps;
-
- xid = get_xid();
-
- cifs_dbg(FYI, "cifs ioctl 0x%x\n", command);
- switch (command) {
- case FS_IOC_GETFLAGS:
- if (pSMBFile == NULL)
- break;
- tcon = tlink_tcon(pSMBFile->tlink);
- caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
-#ifdef CONFIG_CIFS_POSIX
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (CIFS_UNIX_EXTATTR_CAP & caps) {
- __u64 ExtAttrMask = 0;
- rc = CIFSGetExtAttr(xid, tcon,
- pSMBFile->fid.netfid,
- &ExtAttrBits, &ExtAttrMask);
- if (rc == 0)
- rc = put_user(ExtAttrBits &
- FS_FL_USER_VISIBLE,
- (int __user *)arg);
- if (rc != -EOPNOTSUPP)
- break;
- }
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-#endif /* CONFIG_CIFS_POSIX */
- rc = 0;
- if (CIFS_I(inode)->cifsAttrs & ATTR_COMPRESSED) {
- /* add in the compressed bit */
- ExtAttrBits = FS_COMPR_FL;
- rc = put_user(ExtAttrBits & FS_FL_USER_VISIBLE,
- (int __user *)arg);
- }
- break;
- case FS_IOC_SETFLAGS:
- if (pSMBFile == NULL)
- break;
- tcon = tlink_tcon(pSMBFile->tlink);
- /* caps = le64_to_cpu(tcon->fsUnixInfo.Capability); */
-
- if (get_user(ExtAttrBits, (int __user *)arg)) {
- rc = -EFAULT;
- break;
- }
-
- /*
- * if (CIFS_UNIX_EXTATTR_CAP & caps)
- * rc = CIFSSetExtAttr(xid, tcon,
- * pSMBFile->fid.netfid,
- * extAttrBits,
- * &ExtAttrMask);
- * if (rc != -EOPNOTSUPP)
- * break;
- */
-
- /* Currently only flag we can set is compressed flag */
- if ((ExtAttrBits & FS_COMPR_FL) == 0)
- break;
-
- /* Try to set compress flag */
- if (tcon->ses->server->ops->set_compression) {
- rc = tcon->ses->server->ops->set_compression(
- xid, tcon, pSMBFile);
- cifs_dbg(FYI, "set compress flag rc %d\n", rc);
- }
- break;
- case CIFS_IOC_COPYCHUNK_FILE:
- rc = cifs_ioctl_copychunk(xid, filep, arg);
- break;
- case CIFS_QUERY_INFO:
- rc = cifs_ioctl_query_info(xid, filep, arg);
- break;
- case CIFS_IOC_SET_INTEGRITY:
- if (pSMBFile == NULL)
- break;
- tcon = tlink_tcon(pSMBFile->tlink);
- if (tcon->ses->server->ops->set_integrity)
- rc = tcon->ses->server->ops->set_integrity(xid,
- tcon, pSMBFile);
- else
- rc = -EOPNOTSUPP;
- break;
- case CIFS_IOC_GET_MNT_INFO:
- if (pSMBFile == NULL)
- break;
- tcon = tlink_tcon(pSMBFile->tlink);
- rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
- break;
- case CIFS_ENUMERATE_SNAPSHOTS:
- if (pSMBFile == NULL)
- break;
- if (arg == 0) {
- rc = -EINVAL;
- goto cifs_ioc_exit;
- }
- tcon = tlink_tcon(pSMBFile->tlink);
- if (tcon->ses->server->ops->enum_snapshots)
- rc = tcon->ses->server->ops->enum_snapshots(xid, tcon,
- pSMBFile, (void __user *)arg);
- else
- rc = -EOPNOTSUPP;
- break;
- case CIFS_DUMP_KEY:
- /*
- * Dump encryption keys. This is an old ioctl that only
- * handles AES-128-{CCM,GCM}.
- */
- if (pSMBFile == NULL)
- break;
- if (!capable(CAP_SYS_ADMIN)) {
- rc = -EACCES;
- break;
- }
-
- tcon = tlink_tcon(pSMBFile->tlink);
- if (!smb3_encryption_required(tcon)) {
- rc = -EOPNOTSUPP;
- break;
- }
- pkey_inf.cipher_type =
- le16_to_cpu(tcon->ses->server->cipher_type);
- pkey_inf.Suid = tcon->ses->Suid;
- memcpy(pkey_inf.auth_key, tcon->ses->auth_key.response,
- 16 /* SMB2_NTLMV2_SESSKEY_SIZE */);
- memcpy(pkey_inf.smb3decryptionkey,
- tcon->ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE);
- memcpy(pkey_inf.smb3encryptionkey,
- tcon->ses->smb3encryptionkey, SMB3_SIGN_KEY_SIZE);
- if (copy_to_user((void __user *)arg, &pkey_inf,
- sizeof(struct smb3_key_debug_info)))
- rc = -EFAULT;
- else
- rc = 0;
- break;
- case CIFS_DUMP_FULL_KEY:
- /*
- * Dump encryption keys (handles any key sizes)
- */
- if (pSMBFile == NULL)
- break;
- if (!capable(CAP_SYS_ADMIN)) {
- rc = -EACCES;
- break;
- }
- tcon = tlink_tcon(pSMBFile->tlink);
- rc = cifs_dump_full_key(tcon, (void __user *)arg);
- break;
- case CIFS_IOC_NOTIFY:
- if (!S_ISDIR(inode->i_mode)) {
- /* Notify can only be done on directories */
- rc = -EOPNOTSUPP;
- break;
- }
- cifs_sb = CIFS_SB(inode->i_sb);
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink)) {
- rc = PTR_ERR(tlink);
- break;
- }
- tcon = tlink_tcon(tlink);
- if (tcon && tcon->ses->server->ops->notify) {
- rc = tcon->ses->server->ops->notify(xid,
- filep, (void __user *)arg,
- false /* no ret data */);
- cifs_dbg(FYI, "ioctl notify rc %d\n", rc);
- } else
- rc = -EOPNOTSUPP;
- cifs_put_tlink(tlink);
- break;
- case CIFS_IOC_NOTIFY_INFO:
- if (!S_ISDIR(inode->i_mode)) {
- /* Notify can only be done on directories */
- rc = -EOPNOTSUPP;
- break;
- }
- cifs_sb = CIFS_SB(inode->i_sb);
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink)) {
- rc = PTR_ERR(tlink);
- break;
- }
- tcon = tlink_tcon(tlink);
- if (tcon && tcon->ses->server->ops->notify) {
- rc = tcon->ses->server->ops->notify(xid,
- filep, (void __user *)arg,
- true /* return details */);
- cifs_dbg(FYI, "ioctl notify info rc %d\n", rc);
- } else
- rc = -EOPNOTSUPP;
- cifs_put_tlink(tlink);
- break;
- case CIFS_IOC_SHUTDOWN:
- rc = cifs_shutdown(inode->i_sb, arg);
- break;
- default:
- cifs_dbg(FYI, "unsupported ioctl\n");
- break;
- }
-cifs_ioc_exit:
- free_xid(xid);
- return rc;
-}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
deleted file mode 100644
index c0f101fc1e5d..000000000000
--- a/fs/cifs/link.c
+++ /dev/null
@@ -1,650 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002,2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/slab.h>
-#include <linux/namei.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "cifs_unicode.h"
-#include "smb2proto.h"
-#include "cifs_ioctl.h"
-
-/*
- * M-F Symlink Functions - Begin
- */
-
-#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
-#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
-#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
-#define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
-#define CIFS_MF_SYMLINK_FILE_SIZE \
- (CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
-
-#define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
-#define CIFS_MF_SYMLINK_MD5_FORMAT "%16phN\n"
-#define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) md5_hash
-
-static int
-symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
-{
- int rc;
- struct shash_desc *md5 = NULL;
-
- rc = cifs_alloc_hash("md5", &md5);
- if (rc)
- goto symlink_hash_err;
-
- rc = crypto_shash_init(md5);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__);
- goto symlink_hash_err;
- }
- rc = crypto_shash_update(md5, link_str, link_len);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
- goto symlink_hash_err;
- }
- rc = crypto_shash_final(md5, md5_hash);
- if (rc)
- cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
-
-symlink_hash_err:
- cifs_free_hash(&md5);
- return rc;
-}
-
-static int
-parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
- char **_link_str)
-{
- int rc;
- unsigned int link_len;
- const char *md5_str1;
- const char *link_str;
- u8 md5_hash[16];
- char md5_str2[34];
-
- if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
- return -EINVAL;
-
- md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
- link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
-
- rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
- if (rc != 1)
- return -EINVAL;
-
- if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
- return -EINVAL;
-
- rc = symlink_hash(link_len, link_str, md5_hash);
- if (rc) {
- cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
- return rc;
- }
-
- scnprintf(md5_str2, sizeof(md5_str2),
- CIFS_MF_SYMLINK_MD5_FORMAT,
- CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
-
- if (strncmp(md5_str1, md5_str2, 17) != 0)
- return -EINVAL;
-
- if (_link_str) {
- *_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
- if (!*_link_str)
- return -ENOMEM;
- }
-
- *_link_len = link_len;
- return 0;
-}
-
-static int
-format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
-{
- int rc;
- unsigned int link_len;
- unsigned int ofs;
- u8 md5_hash[16];
-
- if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
- return -EINVAL;
-
- link_len = strlen(link_str);
-
- if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
- return -ENAMETOOLONG;
-
- rc = symlink_hash(link_len, link_str, md5_hash);
- if (rc) {
- cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
- return rc;
- }
-
- scnprintf(buf, buf_len,
- CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
- link_len,
- CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
-
- ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
- memcpy(buf + ofs, link_str, link_len);
-
- ofs += link_len;
- if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
- buf[ofs] = '\n';
- ofs++;
- }
-
- while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
- buf[ofs] = ' ';
- ofs++;
- }
-
- return 0;
-}
-
-bool
-couldbe_mf_symlink(const struct cifs_fattr *fattr)
-{
- if (!S_ISREG(fattr->cf_mode))
- /* it's not a symlink */
- return false;
-
- if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
- /* it's not a symlink */
- return false;
-
- return true;
-}
-
-static int
-create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *fromName,
- const char *toName)
-{
- int rc;
- u8 *buf;
- unsigned int bytes_written = 0;
-
- buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
- if (rc)
- goto out;
-
- if (tcon->ses->server->ops->create_mf_symlink)
- rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon,
- cifs_sb, fromName, buf, &bytes_written);
- else
- rc = -EOPNOTSUPP;
-
- if (rc)
- goto out;
-
- if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
- rc = -EIO;
-out:
- kfree(buf);
- return rc;
-}
-
-int
-check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
- const unsigned char *path)
-{
- int rc;
- u8 *buf = NULL;
- unsigned int link_len = 0;
- unsigned int bytes_read = 0;
- char *symlink = NULL;
-
- if (!couldbe_mf_symlink(fattr))
- /* it's not a symlink */
- return 0;
-
- buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- if (tcon->ses->server->ops->query_mf_symlink)
- rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
- cifs_sb, path, buf, &bytes_read);
- else
- rc = -ENOSYS;
-
- if (rc)
- goto out;
-
- if (bytes_read == 0) /* not a symlink */
- goto out;
-
- rc = parse_mf_symlink(buf, bytes_read, &link_len, &symlink);
- if (rc == -EINVAL) {
- /* it's not a symlink */
- rc = 0;
- goto out;
- }
-
- if (rc != 0)
- goto out;
-
- /* it is a symlink */
- fattr->cf_eof = link_len;
- fattr->cf_mode &= ~S_IFMT;
- fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
- fattr->cf_dtype = DT_LNK;
- fattr->cf_symlink_target = symlink;
-out:
- kfree(buf);
- return rc;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-/*
- * SMB 1.0 Protocol specific functions
- */
-
-int
-cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const unsigned char *path,
- char *pbuf, unsigned int *pbytes_read)
-{
- int rc;
- int oplock = 0;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- struct cifs_io_parms io_parms = {0};
- int buf_type = CIFS_NO_BUFFER;
- FILE_ALL_INFO file_info;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = GENERIC_READ,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
- .disposition = FILE_OPEN,
- .path = path,
- .fid = &fid,
- };
-
- rc = CIFS_open(xid, &oparms, &oplock, &file_info);
- if (rc)
- return rc;
-
- if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
- rc = -ENOENT;
- /* it's not a symlink */
- goto out;
- }
-
- io_parms.netfid = fid.netfid;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
- io_parms.offset = 0;
- io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
-
- rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
-out:
- CIFSSMBClose(xid, tcon, fid.netfid);
- return rc;
-}
-
-int
-cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const unsigned char *path,
- char *pbuf, unsigned int *pbytes_written)
-{
- int rc;
- int oplock = 0;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- struct cifs_io_parms io_parms = {0};
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = GENERIC_WRITE,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
- .disposition = FILE_CREATE,
- .path = path,
- .fid = &fid,
- };
-
- rc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (rc)
- return rc;
-
- io_parms.netfid = fid.netfid;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
- io_parms.offset = 0;
- io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
-
- rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf);
- CIFSSMBClose(xid, tcon, fid.netfid);
- return rc;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-/*
- * SMB 2.1/SMB3 Protocol specific functions
- */
-int
-smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const unsigned char *path,
- char *pbuf, unsigned int *pbytes_read)
-{
- int rc;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- struct cifs_io_parms io_parms = {0};
- int buf_type = CIFS_NO_BUFFER;
- __le16 *utf16_path;
- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct smb2_file_all_info *pfile_info = NULL;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .path = path,
- .desired_access = GENERIC_READ,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
- .disposition = FILE_OPEN,
- .fid = &fid,
- };
-
- utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
- if (utf16_path == NULL)
- return -ENOMEM;
-
- pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
- GFP_KERNEL);
-
- if (pfile_info == NULL) {
- kfree(utf16_path);
- return -ENOMEM;
- }
-
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
- NULL, NULL);
- if (rc)
- goto qmf_out_open_fail;
-
- if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
- /* it's not a symlink */
- rc = -ENOENT; /* Is there a better rc to return? */
- goto qmf_out;
- }
-
- io_parms.netfid = fid.netfid;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
- io_parms.offset = 0;
- io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
- io_parms.persistent_fid = fid.persistent_fid;
- io_parms.volatile_fid = fid.volatile_fid;
- rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
-qmf_out:
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
-qmf_out_open_fail:
- kfree(utf16_path);
- kfree(pfile_info);
- return rc;
-}
-
-int
-smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const unsigned char *path,
- char *pbuf, unsigned int *pbytes_written)
-{
- int rc;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- struct cifs_io_parms io_parms = {0};
- __le16 *utf16_path;
- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct kvec iov[2];
-
- cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
-
- utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .path = path,
- .desired_access = GENERIC_WRITE,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
- .disposition = FILE_CREATE,
- .fid = &fid,
- .mode = 0644,
- };
-
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
- NULL, NULL);
- if (rc) {
- kfree(utf16_path);
- return rc;
- }
-
- io_parms.netfid = fid.netfid;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
- io_parms.offset = 0;
- io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
- io_parms.persistent_fid = fid.persistent_fid;
- io_parms.volatile_fid = fid.volatile_fid;
-
- /* iov[0] is reserved for smb header */
- iov[1].iov_base = pbuf;
- iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE;
-
- rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1);
-
- /* Make sure we wrote all of the symlink data */
- if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE))
- rc = -EIO;
-
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
-
- kfree(utf16_path);
- return rc;
-}
-
-/*
- * M-F Symlink Functions - End
- */
-
-int
-cifs_hardlink(struct dentry *old_file, struct inode *inode,
- struct dentry *direntry)
-{
- int rc = -EACCES;
- unsigned int xid;
- const char *from_name, *to_name;
- void *page1, *page2;
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
- struct cifsInodeInfo *cifsInode;
-
- if (unlikely(cifs_forced_shutdown(cifs_sb)))
- return -EIO;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
-
- xid = get_xid();
- page1 = alloc_dentry_path();
- page2 = alloc_dentry_path();
-
- from_name = build_path_from_dentry(old_file, page1);
- if (IS_ERR(from_name)) {
- rc = PTR_ERR(from_name);
- goto cifs_hl_exit;
- }
- to_name = build_path_from_dentry(direntry, page2);
- if (IS_ERR(to_name)) {
- rc = PTR_ERR(to_name);
- goto cifs_hl_exit;
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- if (tcon->unix_ext)
- rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- else {
-#else
- {
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- server = tcon->ses->server;
- if (!server->ops->create_hardlink) {
- rc = -ENOSYS;
- goto cifs_hl_exit;
- }
- rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
- cifs_sb);
- if ((rc == -EIO) || (rc == -EINVAL))
- rc = -EOPNOTSUPP;
- }
-
- d_drop(direntry); /* force new lookup from server of target */
-
- /*
- * if source file is cached (oplocked) revalidate will not go to server
- * until the file is closed or oplock broken so update nlinks locally
- */
- if (d_really_is_positive(old_file)) {
- cifsInode = CIFS_I(d_inode(old_file));
- if (rc == 0) {
- spin_lock(&d_inode(old_file)->i_lock);
- inc_nlink(d_inode(old_file));
- spin_unlock(&d_inode(old_file)->i_lock);
-
- /*
- * parent dir timestamps will update from srv within a
- * second, would it really be worth it to set the parent
- * dir cifs inode time to zero to force revalidate
- * (faster) for it too?
- */
- }
- /*
- * if not oplocked will force revalidate to get info on source
- * file from srv. Note Samba server prior to 4.2 has bug -
- * not updating src file ctime on hardlinks but Windows servers
- * handle it properly
- */
- cifsInode->time = 0;
-
- /*
- * Will update parent dir timestamps from srv within a second.
- * Would it really be worth it to set the parent dir (cifs
- * inode) time field to zero to force revalidate on parent
- * directory faster ie
- *
- * CIFS_I(inode)->time = 0;
- */
- }
-
-cifs_hl_exit:
- free_dentry_path(page1);
- free_dentry_path(page2);
- free_xid(xid);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-int
-cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
- struct dentry *direntry, const char *symname)
-{
- int rc = -EOPNOTSUPP;
- unsigned int xid;
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink;
- struct cifs_tcon *pTcon;
- const char *full_path;
- void *page;
- struct inode *newinode = NULL;
-
- if (unlikely(cifs_forced_shutdown(cifs_sb)))
- return -EIO;
-
- page = alloc_dentry_path();
- if (!page)
- return -ENOMEM;
-
- xid = get_xid();
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink)) {
- rc = PTR_ERR(tlink);
- goto symlink_exit;
- }
- pTcon = tlink_tcon(tlink);
-
- full_path = build_path_from_dentry(direntry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto symlink_exit;
- }
-
- cifs_dbg(FYI, "Full path: %s\n", full_path);
- cifs_dbg(FYI, "symname is %s\n", symname);
-
- /* BB what if DFS and this volume is on different share? BB */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
- rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- else if (pTcon->unix_ext)
- rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- /* else
- rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
- cifs_sb_target->local_nls); */
-
- if (rc == 0) {
- if (pTcon->posix_extensions)
- rc = smb311_posix_get_inode_info(&newinode, full_path, inode->i_sb, xid);
- else if (pTcon->unix_ext)
- rc = cifs_get_inode_info_unix(&newinode, full_path,
- inode->i_sb, xid);
- else
- rc = cifs_get_inode_info(&newinode, full_path, NULL,
- inode->i_sb, xid, NULL);
-
- if (rc != 0) {
- cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n",
- rc);
- } else {
- d_instantiate(direntry, newinode);
- }
- }
-symlink_exit:
- free_dentry_path(page);
- cifs_put_tlink(tlink);
- free_xid(xid);
- return rc;
-}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
deleted file mode 100644
index 31e06133acc3..000000000000
--- a/fs/cifs/misc.c
+++ /dev/null
@@ -1,1434 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002,2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/mempool.h>
-#include <linux/vmalloc.h>
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "smberr.h"
-#include "nterr.h"
-#include "cifs_unicode.h"
-#include "smb2pdu.h"
-#include "cifsfs.h"
-#ifdef CONFIG_CIFS_DFS_UPCALL
-#include "dns_resolve.h"
-#include "dfs_cache.h"
-#endif
-#include "fs_context.h"
-#include "cached_dir.h"
-
-extern mempool_t *cifs_sm_req_poolp;
-extern mempool_t *cifs_req_poolp;
-
-/* The xid serves as a useful identifier for each incoming vfs request,
- in a similar way to the mid which is useful to track each sent smb,
- and CurrentXid can also provide a running counter (although it
- will eventually wrap past zero) of the total vfs operations handled
- since the cifs fs was mounted */
-
-unsigned int
-_get_xid(void)
-{
- unsigned int xid;
-
- spin_lock(&GlobalMid_Lock);
- GlobalTotalActiveXid++;
-
- /* keep high water mark for number of simultaneous ops in filesystem */
- if (GlobalTotalActiveXid > GlobalMaxActiveXid)
- GlobalMaxActiveXid = GlobalTotalActiveXid;
- if (GlobalTotalActiveXid > 65000)
- cifs_dbg(FYI, "warning: more than 65000 requests active\n");
- xid = GlobalCurrentXid++;
- spin_unlock(&GlobalMid_Lock);
- return xid;
-}
-
-void
-_free_xid(unsigned int xid)
-{
- spin_lock(&GlobalMid_Lock);
- /* if (GlobalTotalActiveXid == 0)
- BUG(); */
- GlobalTotalActiveXid--;
- spin_unlock(&GlobalMid_Lock);
-}
-
-struct cifs_ses *
-sesInfoAlloc(void)
-{
- struct cifs_ses *ret_buf;
-
- ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL);
- if (ret_buf) {
- atomic_inc(&sesInfoAllocCount);
- spin_lock_init(&ret_buf->ses_lock);
- ret_buf->ses_status = SES_NEW;
- ++ret_buf->ses_count;
- INIT_LIST_HEAD(&ret_buf->smb_ses_list);
- INIT_LIST_HEAD(&ret_buf->tcon_list);
- mutex_init(&ret_buf->session_mutex);
- spin_lock_init(&ret_buf->iface_lock);
- INIT_LIST_HEAD(&ret_buf->iface_list);
- spin_lock_init(&ret_buf->chan_lock);
- }
- return ret_buf;
-}
-
-void
-sesInfoFree(struct cifs_ses *buf_to_free)
-{
- struct cifs_server_iface *iface = NULL, *niface = NULL;
-
- if (buf_to_free == NULL) {
- cifs_dbg(FYI, "Null buffer passed to sesInfoFree\n");
- return;
- }
-
- atomic_dec(&sesInfoAllocCount);
- kfree(buf_to_free->serverOS);
- kfree(buf_to_free->serverDomain);
- kfree(buf_to_free->serverNOS);
- kfree_sensitive(buf_to_free->password);
- kfree(buf_to_free->user_name);
- kfree(buf_to_free->domainName);
- kfree_sensitive(buf_to_free->auth_key.response);
- spin_lock(&buf_to_free->iface_lock);
- list_for_each_entry_safe(iface, niface, &buf_to_free->iface_list,
- iface_head)
- kref_put(&iface->refcount, release_iface);
- spin_unlock(&buf_to_free->iface_lock);
- kfree_sensitive(buf_to_free);
-}
-
-struct cifs_tcon *
-tconInfoAlloc(void)
-{
- struct cifs_tcon *ret_buf;
-
- ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
- if (!ret_buf)
- return NULL;
- ret_buf->cfids = init_cached_dirs();
- if (!ret_buf->cfids) {
- kfree(ret_buf);
- return NULL;
- }
-
- atomic_inc(&tconInfoAllocCount);
- ret_buf->status = TID_NEW;
- ++ret_buf->tc_count;
- spin_lock_init(&ret_buf->tc_lock);
- INIT_LIST_HEAD(&ret_buf->openFileList);
- INIT_LIST_HEAD(&ret_buf->tcon_list);
- spin_lock_init(&ret_buf->open_file_lock);
- spin_lock_init(&ret_buf->stat_lock);
- atomic_set(&ret_buf->num_local_opens, 0);
- atomic_set(&ret_buf->num_remote_opens, 0);
-
- return ret_buf;
-}
-
-void
-tconInfoFree(struct cifs_tcon *tcon)
-{
- if (tcon == NULL) {
- cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
- return;
- }
- free_cached_dirs(tcon->cfids);
- atomic_dec(&tconInfoAllocCount);
- kfree(tcon->nativeFileSystem);
- kfree_sensitive(tcon->password);
- kfree(tcon);
-}
-
-struct smb_hdr *
-cifs_buf_get(void)
-{
- struct smb_hdr *ret_buf = NULL;
- /*
- * SMB2 header is bigger than CIFS one - no problems to clean some
- * more bytes for CIFS.
- */
- size_t buf_size = sizeof(struct smb2_hdr);
-
- /*
- * We could use negotiated size instead of max_msgsize -
- * but it may be more efficient to always alloc same size
- * albeit slightly larger than necessary and maxbuffersize
- * defaults to this and can not be bigger.
- */
- ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS);
-
- /* clear the first few header bytes */
- /* for most paths, more is cleared in header_assemble */
- memset(ret_buf, 0, buf_size + 3);
- atomic_inc(&buf_alloc_count);
-#ifdef CONFIG_CIFS_STATS2
- atomic_inc(&total_buf_alloc_count);
-#endif /* CONFIG_CIFS_STATS2 */
-
- return ret_buf;
-}
-
-void
-cifs_buf_release(void *buf_to_free)
-{
- if (buf_to_free == NULL) {
- /* cifs_dbg(FYI, "Null buffer passed to cifs_buf_release\n");*/
- return;
- }
- mempool_free(buf_to_free, cifs_req_poolp);
-
- atomic_dec(&buf_alloc_count);
- return;
-}
-
-struct smb_hdr *
-cifs_small_buf_get(void)
-{
- struct smb_hdr *ret_buf = NULL;
-
-/* We could use negotiated size instead of max_msgsize -
- but it may be more efficient to always alloc same size
- albeit slightly larger than necessary and maxbuffersize
- defaults to this and can not be bigger */
- ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS);
- /* No need to clear memory here, cleared in header assemble */
- /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
- atomic_inc(&small_buf_alloc_count);
-#ifdef CONFIG_CIFS_STATS2
- atomic_inc(&total_small_buf_alloc_count);
-#endif /* CONFIG_CIFS_STATS2 */
-
- return ret_buf;
-}
-
-void
-cifs_small_buf_release(void *buf_to_free)
-{
-
- if (buf_to_free == NULL) {
- cifs_dbg(FYI, "Null buffer passed to cifs_small_buf_release\n");
- return;
- }
- mempool_free(buf_to_free, cifs_sm_req_poolp);
-
- atomic_dec(&small_buf_alloc_count);
- return;
-}
-
-void
-free_rsp_buf(int resp_buftype, void *rsp)
-{
- if (resp_buftype == CIFS_SMALL_BUFFER)
- cifs_small_buf_release(rsp);
- else if (resp_buftype == CIFS_LARGE_BUFFER)
- cifs_buf_release(rsp);
-}
-
-/* NB: MID can not be set if treeCon not passed in, in that
- case it is responsbility of caller to set the mid */
-void
-header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
- const struct cifs_tcon *treeCon, int word_count
- /* length of fixed section (word count) in two byte units */)
-{
- char *temp = (char *) buffer;
-
- memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
-
- buffer->smb_buf_length = cpu_to_be32(
- (2 * word_count) + sizeof(struct smb_hdr) -
- 4 /* RFC 1001 length field does not count */ +
- 2 /* for bcc field itself */) ;
-
- buffer->Protocol[0] = 0xFF;
- buffer->Protocol[1] = 'S';
- buffer->Protocol[2] = 'M';
- buffer->Protocol[3] = 'B';
- buffer->Command = smb_command;
- buffer->Flags = 0x00; /* case sensitive */
- buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
- buffer->Pid = cpu_to_le16((__u16)current->tgid);
- buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
- if (treeCon) {
- buffer->Tid = treeCon->tid;
- if (treeCon->ses) {
- if (treeCon->ses->capabilities & CAP_UNICODE)
- buffer->Flags2 |= SMBFLG2_UNICODE;
- if (treeCon->ses->capabilities & CAP_STATUS32)
- buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-
- /* Uid is not converted */
- buffer->Uid = treeCon->ses->Suid;
- if (treeCon->ses->server)
- buffer->Mid = get_next_mid(treeCon->ses->server);
- }
- if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
- buffer->Flags2 |= SMBFLG2_DFS;
- if (treeCon->nocase)
- buffer->Flags |= SMBFLG_CASELESS;
- if ((treeCon->ses) && (treeCon->ses->server))
- if (treeCon->ses->server->sign)
- buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
- }
-
-/* endian conversion of flags is now done just before sending */
- buffer->WordCount = (char) word_count;
- return;
-}
-
-static int
-check_smb_hdr(struct smb_hdr *smb)
-{
- /* does it have the right SMB "signature" ? */
- if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) {
- cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n",
- *(unsigned int *)smb->Protocol);
- return 1;
- }
-
- /* if it's a response then accept */
- if (smb->Flags & SMBFLG_RESPONSE)
- return 0;
-
- /* only one valid case where server sends us request */
- if (smb->Command == SMB_COM_LOCKING_ANDX)
- return 0;
-
- cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
- get_mid(smb));
- return 1;
-}
-
-int
-checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
-{
- struct smb_hdr *smb = (struct smb_hdr *)buf;
- __u32 rfclen = be32_to_cpu(smb->smb_buf_length);
- __u32 clc_len; /* calculated length */
- cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
- total_read, rfclen);
-
- /* is this frame too small to even get to a BCC? */
- if (total_read < 2 + sizeof(struct smb_hdr)) {
- if ((total_read >= sizeof(struct smb_hdr) - 1)
- && (smb->Status.CifsError != 0)) {
- /* it's an error return */
- smb->WordCount = 0;
- /* some error cases do not return wct and bcc */
- return 0;
- } else if ((total_read == sizeof(struct smb_hdr) + 1) &&
- (smb->WordCount == 0)) {
- char *tmp = (char *)smb;
- /* Need to work around a bug in two servers here */
- /* First, check if the part of bcc they sent was zero */
- if (tmp[sizeof(struct smb_hdr)] == 0) {
- /* some servers return only half of bcc
- * on simple responses (wct, bcc both zero)
- * in particular have seen this on
- * ulogoffX and FindClose. This leaves
- * one byte of bcc potentially unitialized
- */
- /* zero rest of bcc */
- tmp[sizeof(struct smb_hdr)+1] = 0;
- return 0;
- }
- cifs_dbg(VFS, "rcvd invalid byte count (bcc)\n");
- } else {
- cifs_dbg(VFS, "Length less than smb header size\n");
- }
- return -EIO;
- }
-
- /* otherwise, there is enough to get to the BCC */
- if (check_smb_hdr(smb))
- return -EIO;
- clc_len = smbCalcSize(smb);
-
- if (4 + rfclen != total_read) {
- cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n",
- rfclen);
- return -EIO;
- }
-
- if (4 + rfclen != clc_len) {
- __u16 mid = get_mid(smb);
- /* check if bcc wrapped around for large read responses */
- if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
- /* check if lengths match mod 64K */
- if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
- return 0; /* bcc wrapped */
- }
- cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
- clc_len, 4 + rfclen, mid);
-
- if (4 + rfclen < clc_len) {
- cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
- rfclen, mid);
- return -EIO;
- } else if (rfclen > clc_len + 512) {
- /*
- * Some servers (Windows XP in particular) send more
- * data than the lengths in the SMB packet would
- * indicate on certain calls (byte range locks and
- * trans2 find first calls in particular). While the
- * client can handle such a frame by ignoring the
- * trailing data, we choose limit the amount of extra
- * data to 512 bytes.
- */
- cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
- rfclen, mid);
- return -EIO;
- }
- }
- return 0;
-}
-
-bool
-is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
-{
- struct smb_hdr *buf = (struct smb_hdr *)buffer;
- struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
- struct cifsInodeInfo *pCifsInode;
- struct cifsFileInfo *netfile;
-
- cifs_dbg(FYI, "Checking for oplock break or dnotify response\n");
- if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
- (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
- struct smb_com_transaction_change_notify_rsp *pSMBr =
- (struct smb_com_transaction_change_notify_rsp *)buf;
- struct file_notify_information *pnotify;
- __u32 data_offset = 0;
- size_t len = srv->total_read - sizeof(pSMBr->hdr.smb_buf_length);
-
- if (get_bcc(buf) > sizeof(struct file_notify_information)) {
- data_offset = le32_to_cpu(pSMBr->DataOffset);
-
- if (data_offset >
- len - sizeof(struct file_notify_information)) {
- cifs_dbg(FYI, "Invalid data_offset %u\n",
- data_offset);
- return true;
- }
- pnotify = (struct file_notify_information *)
- ((char *)&pSMBr->hdr.Protocol + data_offset);
- cifs_dbg(FYI, "dnotify on %s Action: 0x%x\n",
- pnotify->FileName, pnotify->Action);
- /* cifs_dump_mem("Rcvd notify Data: ",buf,
- sizeof(struct smb_hdr)+60); */
- return true;
- }
- if (pSMBr->hdr.Status.CifsError) {
- cifs_dbg(FYI, "notify err 0x%x\n",
- pSMBr->hdr.Status.CifsError);
- return true;
- }
- return false;
- }
- if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
- return false;
- if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {
- /* no sense logging error on invalid handle on oplock
- break - harmless race between close request and oplock
- break response is expected from time to time writing out
- large dirty files cached on the client */
- if ((NT_STATUS_INVALID_HANDLE) ==
- le32_to_cpu(pSMB->hdr.Status.CifsError)) {
- cifs_dbg(FYI, "Invalid handle on oplock break\n");
- return true;
- } else if (ERRbadfid ==
- le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
- return true;
- } else {
- return false; /* on valid oplock brk we get "request" */
- }
- }
- if (pSMB->hdr.WordCount != 8)
- return false;
-
- cifs_dbg(FYI, "oplock type 0x%x level 0x%x\n",
- pSMB->LockType, pSMB->OplockLevel);
- if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
- return false;
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(srv) ? srv->primary_server : srv;
-
- /* look up tcon based on tid & uid */
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- if (tcon->tid != buf->Tid)
- continue;
-
- cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
- spin_lock(&tcon->open_file_lock);
- list_for_each_entry(netfile, &tcon->openFileList, tlist) {
- if (pSMB->Fid != netfile->fid.netfid)
- continue;
-
- cifs_dbg(FYI, "file id match, oplock break\n");
- pCifsInode = CIFS_I(d_inode(netfile->dentry));
-
- set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
- &pCifsInode->flags);
-
- netfile->oplock_epoch = 0;
- netfile->oplock_level = pSMB->OplockLevel;
- netfile->oplock_break_cancelled = false;
- cifs_queue_oplock_break(netfile);
-
- spin_unlock(&tcon->open_file_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- return true;
- }
- spin_unlock(&tcon->open_file_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- cifs_dbg(FYI, "No matching file for oplock break\n");
- return true;
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
- cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
- return true;
-}
-
-void
-dump_smb(void *buf, int smb_buf_length)
-{
- if (traceSMB == 0)
- return;
-
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 8, 2, buf,
- smb_buf_length, true);
-}
-
-void
-cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
-{
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- struct cifs_tcon *tcon = NULL;
-
- if (cifs_sb->master_tlink)
- tcon = cifs_sb_master_tcon(cifs_sb);
-
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
- cifs_sb->mnt_cifs_serverino_autodisabled = true;
- cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s\n",
- tcon ? tcon->tree_name : "new server");
- cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS)\n");
- cifs_dbg(VFS, "Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n");
-
- }
-}
-
-void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
-{
- oplock &= 0xF;
-
- if (oplock == OPLOCK_EXCLUSIVE) {
- cinode->oplock = CIFS_CACHE_WRITE_FLG | CIFS_CACHE_READ_FLG;
- cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
- &cinode->netfs.inode);
- } else if (oplock == OPLOCK_READ) {
- cinode->oplock = CIFS_CACHE_READ_FLG;
- cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
- &cinode->netfs.inode);
- } else
- cinode->oplock = 0;
-}
-
-/*
- * We wait for oplock breaks to be processed before we attempt to perform
- * writes.
- */
-int cifs_get_writer(struct cifsInodeInfo *cinode)
-{
- int rc;
-
-start:
- rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK,
- TASK_KILLABLE);
- if (rc)
- return rc;
-
- spin_lock(&cinode->writers_lock);
- if (!cinode->writers)
- set_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
- cinode->writers++;
- /* Check to see if we have started servicing an oplock break */
- if (test_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags)) {
- cinode->writers--;
- if (cinode->writers == 0) {
- clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
- wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
- }
- spin_unlock(&cinode->writers_lock);
- goto start;
- }
- spin_unlock(&cinode->writers_lock);
- return 0;
-}
-
-void cifs_put_writer(struct cifsInodeInfo *cinode)
-{
- spin_lock(&cinode->writers_lock);
- cinode->writers--;
- if (cinode->writers == 0) {
- clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
- wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
- }
- spin_unlock(&cinode->writers_lock);
-}
-
-/**
- * cifs_queue_oplock_break - queue the oplock break handler for cfile
- * @cfile: The file to break the oplock on
- *
- * This function is called from the demultiplex thread when it
- * receives an oplock break for @cfile.
- *
- * Assumes the tcon->open_file_lock is held.
- * Assumes cfile->file_info_lock is NOT held.
- */
-void cifs_queue_oplock_break(struct cifsFileInfo *cfile)
-{
- /*
- * Bump the handle refcount now while we hold the
- * open_file_lock to enforce the validity of it for the oplock
- * break handler. The matching put is done at the end of the
- * handler.
- */
- cifsFileInfo_get(cfile);
-
- queue_work(cifsoplockd_wq, &cfile->oplock_break);
-}
-
-void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
-{
- clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
- wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK);
-}
-
-bool
-backup_cred(struct cifs_sb_info *cifs_sb)
-{
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) {
- if (uid_eq(cifs_sb->ctx->backupuid, current_fsuid()))
- return true;
- }
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) {
- if (in_group_p(cifs_sb->ctx->backupgid))
- return true;
- }
-
- return false;
-}
-
-void
-cifs_del_pending_open(struct cifs_pending_open *open)
-{
- spin_lock(&tlink_tcon(open->tlink)->open_file_lock);
- list_del(&open->olist);
- spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
-}
-
-void
-cifs_add_pending_open_locked(struct cifs_fid *fid, struct tcon_link *tlink,
- struct cifs_pending_open *open)
-{
- memcpy(open->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
- open->oplock = CIFS_OPLOCK_NO_CHANGE;
- open->tlink = tlink;
- fid->pending_open = open;
- list_add_tail(&open->olist, &tlink_tcon(tlink)->pending_opens);
-}
-
-void
-cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
- struct cifs_pending_open *open)
-{
- spin_lock(&tlink_tcon(tlink)->open_file_lock);
- cifs_add_pending_open_locked(fid, tlink, open);
- spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
-}
-
-/*
- * Critical section which runs after acquiring deferred_lock.
- * As there is no reference count on cifs_deferred_close, pdclose
- * should not be used outside deferred_lock.
- */
-bool
-cifs_is_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close **pdclose)
-{
- struct cifs_deferred_close *dclose;
-
- list_for_each_entry(dclose, &CIFS_I(d_inode(cfile->dentry))->deferred_closes, dlist) {
- if ((dclose->netfid == cfile->fid.netfid) &&
- (dclose->persistent_fid == cfile->fid.persistent_fid) &&
- (dclose->volatile_fid == cfile->fid.volatile_fid)) {
- *pdclose = dclose;
- return true;
- }
- }
- return false;
-}
-
-/*
- * Critical section which runs after acquiring deferred_lock.
- */
-void
-cifs_add_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close *dclose)
-{
- bool is_deferred = false;
- struct cifs_deferred_close *pdclose;
-
- is_deferred = cifs_is_deferred_close(cfile, &pdclose);
- if (is_deferred) {
- kfree(dclose);
- return;
- }
-
- dclose->tlink = cfile->tlink;
- dclose->netfid = cfile->fid.netfid;
- dclose->persistent_fid = cfile->fid.persistent_fid;
- dclose->volatile_fid = cfile->fid.volatile_fid;
- list_add_tail(&dclose->dlist, &CIFS_I(d_inode(cfile->dentry))->deferred_closes);
-}
-
-/*
- * Critical section which runs after acquiring deferred_lock.
- */
-void
-cifs_del_deferred_close(struct cifsFileInfo *cfile)
-{
- bool is_deferred = false;
- struct cifs_deferred_close *dclose;
-
- is_deferred = cifs_is_deferred_close(cfile, &dclose);
- if (!is_deferred)
- return;
- list_del(&dclose->dlist);
- kfree(dclose);
-}
-
-void
-cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
-{
- struct cifsFileInfo *cfile = NULL;
- struct file_list *tmp_list, *tmp_next_list;
- struct list_head file_head;
-
- if (cifs_inode == NULL)
- return;
-
- INIT_LIST_HEAD(&file_head);
- spin_lock(&cifs_inode->open_file_lock);
- list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
- if (delayed_work_pending(&cfile->deferred)) {
- if (cancel_delayed_work(&cfile->deferred)) {
- spin_lock(&cifs_inode->deferred_lock);
- cifs_del_deferred_close(cfile);
- spin_unlock(&cifs_inode->deferred_lock);
-
- tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
- if (tmp_list == NULL)
- break;
- tmp_list->cfile = cfile;
- list_add_tail(&tmp_list->list, &file_head);
- }
- }
- }
- spin_unlock(&cifs_inode->open_file_lock);
-
- list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
- _cifsFileInfo_put(tmp_list->cfile, false, false);
- list_del(&tmp_list->list);
- kfree(tmp_list);
- }
-}
-
-void
-cifs_close_all_deferred_files(struct cifs_tcon *tcon)
-{
- struct cifsFileInfo *cfile;
- struct file_list *tmp_list, *tmp_next_list;
- struct list_head file_head;
-
- INIT_LIST_HEAD(&file_head);
- spin_lock(&tcon->open_file_lock);
- list_for_each_entry(cfile, &tcon->openFileList, tlist) {
- if (delayed_work_pending(&cfile->deferred)) {
- if (cancel_delayed_work(&cfile->deferred)) {
- spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
- cifs_del_deferred_close(cfile);
- spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
-
- tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
- if (tmp_list == NULL)
- break;
- tmp_list->cfile = cfile;
- list_add_tail(&tmp_list->list, &file_head);
- }
- }
- }
- spin_unlock(&tcon->open_file_lock);
-
- list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
- _cifsFileInfo_put(tmp_list->cfile, true, false);
- list_del(&tmp_list->list);
- kfree(tmp_list);
- }
-}
-void
-cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
-{
- struct cifsFileInfo *cfile;
- struct file_list *tmp_list, *tmp_next_list;
- struct list_head file_head;
- void *page;
- const char *full_path;
-
- INIT_LIST_HEAD(&file_head);
- page = alloc_dentry_path();
- spin_lock(&tcon->open_file_lock);
- list_for_each_entry(cfile, &tcon->openFileList, tlist) {
- full_path = build_path_from_dentry(cfile->dentry, page);
- if (strstr(full_path, path)) {
- if (delayed_work_pending(&cfile->deferred)) {
- if (cancel_delayed_work(&cfile->deferred)) {
- spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
- cifs_del_deferred_close(cfile);
- spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
-
- tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
- if (tmp_list == NULL)
- break;
- tmp_list->cfile = cfile;
- list_add_tail(&tmp_list->list, &file_head);
- }
- }
- }
- }
- spin_unlock(&tcon->open_file_lock);
-
- list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
- _cifsFileInfo_put(tmp_list->cfile, true, false);
- list_del(&tmp_list->list);
- kfree(tmp_list);
- }
- free_dentry_path(page);
-}
-
-/* parses DFS referral V3 structure
- * caller is responsible for freeing target_nodes
- * returns:
- * - on success - 0
- * - on failure - errno
- */
-int
-parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
- unsigned int *num_of_nodes,
- struct dfs_info3_param **target_nodes,
- const struct nls_table *nls_codepage, int remap,
- const char *searchName, bool is_unicode)
-{
- int i, rc = 0;
- char *data_end;
- struct dfs_referral_level_3 *ref;
-
- *num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals);
-
- if (*num_of_nodes < 1) {
- cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
- *num_of_nodes);
- rc = -EINVAL;
- goto parse_DFS_referrals_exit;
- }
-
- ref = (struct dfs_referral_level_3 *) &(rsp->referrals);
- if (ref->VersionNumber != cpu_to_le16(3)) {
- cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
- le16_to_cpu(ref->VersionNumber));
- rc = -EINVAL;
- goto parse_DFS_referrals_exit;
- }
-
- /* get the upper boundary of the resp buffer */
- data_end = (char *)rsp + rsp_size;
-
- cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
- *num_of_nodes, le32_to_cpu(rsp->DFSFlags));
-
- *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
- GFP_KERNEL);
- if (*target_nodes == NULL) {
- rc = -ENOMEM;
- goto parse_DFS_referrals_exit;
- }
-
- /* collect necessary data from referrals */
- for (i = 0; i < *num_of_nodes; i++) {
- char *temp;
- int max_len;
- struct dfs_info3_param *node = (*target_nodes)+i;
-
- node->flags = le32_to_cpu(rsp->DFSFlags);
- if (is_unicode) {
- __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
- GFP_KERNEL);
- if (tmp == NULL) {
- rc = -ENOMEM;
- goto parse_DFS_referrals_exit;
- }
- cifsConvertToUTF16((__le16 *) tmp, searchName,
- PATH_MAX, nls_codepage, remap);
- node->path_consumed = cifs_utf16_bytes(tmp,
- le16_to_cpu(rsp->PathConsumed),
- nls_codepage);
- kfree(tmp);
- } else
- node->path_consumed = le16_to_cpu(rsp->PathConsumed);
-
- node->server_type = le16_to_cpu(ref->ServerType);
- node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
-
- /* copy DfsPath */
- temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
- max_len = data_end - temp;
- node->path_name = cifs_strndup_from_utf16(temp, max_len,
- is_unicode, nls_codepage);
- if (!node->path_name) {
- rc = -ENOMEM;
- goto parse_DFS_referrals_exit;
- }
-
- /* copy link target UNC */
- temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
- max_len = data_end - temp;
- node->node_name = cifs_strndup_from_utf16(temp, max_len,
- is_unicode, nls_codepage);
- if (!node->node_name) {
- rc = -ENOMEM;
- goto parse_DFS_referrals_exit;
- }
-
- node->ttl = le32_to_cpu(ref->TimeToLive);
-
- ref++;
- }
-
-parse_DFS_referrals_exit:
- if (rc) {
- free_dfs_info_array(*target_nodes, *num_of_nodes);
- *target_nodes = NULL;
- *num_of_nodes = 0;
- }
- return rc;
-}
-
-struct cifs_aio_ctx *
-cifs_aio_ctx_alloc(void)
-{
- struct cifs_aio_ctx *ctx;
-
- /*
- * Must use kzalloc to initialize ctx->bv to NULL and ctx->direct_io
- * to false so that we know when we have to unreference pages within
- * cifs_aio_ctx_release()
- */
- ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL);
- if (!ctx)
- return NULL;
-
- INIT_LIST_HEAD(&ctx->list);
- mutex_init(&ctx->aio_mutex);
- init_completion(&ctx->done);
- kref_init(&ctx->refcount);
- return ctx;
-}
-
-void
-cifs_aio_ctx_release(struct kref *refcount)
-{
- struct cifs_aio_ctx *ctx = container_of(refcount,
- struct cifs_aio_ctx, refcount);
-
- cifsFileInfo_put(ctx->cfile);
-
- /*
- * ctx->bv is only set if setup_aio_ctx_iter() was call successfuly
- * which means that iov_iter_get_pages() was a success and thus that
- * we have taken reference on pages.
- */
- if (ctx->bv) {
- unsigned i;
-
- for (i = 0; i < ctx->npages; i++) {
- if (ctx->should_dirty)
- set_page_dirty(ctx->bv[i].bv_page);
- put_page(ctx->bv[i].bv_page);
- }
- kvfree(ctx->bv);
- }
-
- kfree(ctx);
-}
-
-#define CIFS_AIO_KMALLOC_LIMIT (1024 * 1024)
-
-int
-setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
-{
- ssize_t rc;
- unsigned int cur_npages;
- unsigned int npages = 0;
- unsigned int i;
- size_t len;
- size_t count = iov_iter_count(iter);
- unsigned int saved_len;
- size_t start;
- unsigned int max_pages = iov_iter_npages(iter, INT_MAX);
- struct page **pages = NULL;
- struct bio_vec *bv = NULL;
-
- if (iov_iter_is_kvec(iter)) {
- memcpy(&ctx->iter, iter, sizeof(*iter));
- ctx->len = count;
- iov_iter_advance(iter, count);
- return 0;
- }
-
- if (array_size(max_pages, sizeof(*bv)) <= CIFS_AIO_KMALLOC_LIMIT)
- bv = kmalloc_array(max_pages, sizeof(*bv), GFP_KERNEL);
-
- if (!bv) {
- bv = vmalloc(array_size(max_pages, sizeof(*bv)));
- if (!bv)
- return -ENOMEM;
- }
-
- if (array_size(max_pages, sizeof(*pages)) <= CIFS_AIO_KMALLOC_LIMIT)
- pages = kmalloc_array(max_pages, sizeof(*pages), GFP_KERNEL);
-
- if (!pages) {
- pages = vmalloc(array_size(max_pages, sizeof(*pages)));
- if (!pages) {
- kvfree(bv);
- return -ENOMEM;
- }
- }
-
- saved_len = count;
-
- while (count && npages < max_pages) {
- rc = iov_iter_get_pages2(iter, pages, count, max_pages, &start);
- if (rc < 0) {
- cifs_dbg(VFS, "Couldn't get user pages (rc=%zd)\n", rc);
- break;
- }
-
- if (rc > count) {
- cifs_dbg(VFS, "get pages rc=%zd more than %zu\n", rc,
- count);
- break;
- }
-
- count -= rc;
- rc += start;
- cur_npages = DIV_ROUND_UP(rc, PAGE_SIZE);
-
- if (npages + cur_npages > max_pages) {
- cifs_dbg(VFS, "out of vec array capacity (%u vs %u)\n",
- npages + cur_npages, max_pages);
- break;
- }
-
- for (i = 0; i < cur_npages; i++) {
- len = rc > PAGE_SIZE ? PAGE_SIZE : rc;
- bv[npages + i].bv_page = pages[i];
- bv[npages + i].bv_offset = start;
- bv[npages + i].bv_len = len - start;
- rc -= len;
- start = 0;
- }
-
- npages += cur_npages;
- }
-
- kvfree(pages);
- ctx->bv = bv;
- ctx->len = saved_len - count;
- ctx->npages = npages;
- iov_iter_bvec(&ctx->iter, rw, ctx->bv, npages, ctx->len);
- return 0;
-}
-
-/**
- * cifs_alloc_hash - allocate hash and hash context together
- * @name: The name of the crypto hash algo
- * @sdesc: SHASH descriptor where to put the pointer to the hash TFM
- *
- * The caller has to make sure @sdesc is initialized to either NULL or
- * a valid context. It can be freed via cifs_free_hash().
- */
-int
-cifs_alloc_hash(const char *name, struct shash_desc **sdesc)
-{
- int rc = 0;
- struct crypto_shash *alg = NULL;
-
- if (*sdesc)
- return 0;
-
- alg = crypto_alloc_shash(name, 0, 0);
- if (IS_ERR(alg)) {
- cifs_dbg(VFS, "Could not allocate shash TFM '%s'\n", name);
- rc = PTR_ERR(alg);
- *sdesc = NULL;
- return rc;
- }
-
- *sdesc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(alg), GFP_KERNEL);
- if (*sdesc == NULL) {
- cifs_dbg(VFS, "no memory left to allocate shash TFM '%s'\n", name);
- crypto_free_shash(alg);
- return -ENOMEM;
- }
-
- (*sdesc)->tfm = alg;
- return 0;
-}
-
-/**
- * cifs_free_hash - free hash and hash context together
- * @sdesc: Where to find the pointer to the hash TFM
- *
- * Freeing a NULL descriptor is safe.
- */
-void
-cifs_free_hash(struct shash_desc **sdesc)
-{
- if (unlikely(!sdesc) || !*sdesc)
- return;
-
- if ((*sdesc)->tfm) {
- crypto_free_shash((*sdesc)->tfm);
- (*sdesc)->tfm = NULL;
- }
-
- kfree_sensitive(*sdesc);
- *sdesc = NULL;
-}
-
-/**
- * rqst_page_get_length - obtain the length and offset for a page in smb_rqst
- * @rqst: The request descriptor
- * @page: The index of the page to query
- * @len: Where to store the length for this page:
- * @offset: Where to store the offset for this page
- */
-void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
- unsigned int *len, unsigned int *offset)
-{
- *len = rqst->rq_pagesz;
- *offset = (page == 0) ? rqst->rq_offset : 0;
-
- if (rqst->rq_npages == 1 || page == rqst->rq_npages-1)
- *len = rqst->rq_tailsz;
- else if (page == 0)
- *len = rqst->rq_pagesz - rqst->rq_offset;
-}
-
-void extract_unc_hostname(const char *unc, const char **h, size_t *len)
-{
- const char *end;
-
- /* skip initial slashes */
- while (*unc && (*unc == '\\' || *unc == '/'))
- unc++;
-
- end = unc;
-
- while (*end && !(*end == '\\' || *end == '/'))
- end++;
-
- *h = unc;
- *len = end - unc;
-}
-
-/**
- * copy_path_name - copy src path to dst, possibly truncating
- * @dst: The destination buffer
- * @src: The source name
- *
- * returns number of bytes written (including trailing nul)
- */
-int copy_path_name(char *dst, const char *src)
-{
- int name_len;
-
- /*
- * PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it
- * will truncate and strlen(dst) will be PATH_MAX-1
- */
- name_len = strscpy(dst, src, PATH_MAX);
- if (WARN_ON_ONCE(name_len < 0))
- name_len = PATH_MAX-1;
-
- /* we count the trailing nul */
- name_len++;
- return name_len;
-}
-
-struct super_cb_data {
- void *data;
- struct super_block *sb;
-};
-
-static void tcp_super_cb(struct super_block *sb, void *arg)
-{
- struct super_cb_data *sd = arg;
- struct TCP_Server_Info *server = sd->data;
- struct cifs_sb_info *cifs_sb;
- struct cifs_tcon *tcon;
-
- if (sd->sb)
- return;
-
- cifs_sb = CIFS_SB(sb);
- tcon = cifs_sb_master_tcon(cifs_sb);
- if (tcon->ses->server == server)
- sd->sb = sb;
-}
-
-static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *),
- void *data)
-{
- struct super_cb_data sd = {
- .data = data,
- .sb = NULL,
- };
- struct file_system_type **fs_type = (struct file_system_type *[]) {
- &cifs_fs_type, &smb3_fs_type, NULL,
- };
-
- for (; *fs_type; fs_type++) {
- iterate_supers_type(*fs_type, f, &sd);
- if (sd.sb) {
- /*
- * Grab an active reference in order to prevent automounts (DFS links)
- * of expiring and then freeing up our cifs superblock pointer while
- * we're doing failover.
- */
- cifs_sb_active(sd.sb);
- return sd.sb;
- }
- }
- return ERR_PTR(-EINVAL);
-}
-
-static void __cifs_put_super(struct super_block *sb)
-{
- if (!IS_ERR_OR_NULL(sb))
- cifs_sb_deactive(sb);
-}
-
-struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server)
-{
- return __cifs_get_super(tcp_super_cb, server);
-}
-
-void cifs_put_tcp_super(struct super_block *sb)
-{
- __cifs_put_super(sb);
-}
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
-int match_target_ip(struct TCP_Server_Info *server,
- const char *share, size_t share_len,
- bool *result)
-{
- int rc;
- char *target, *tip = NULL;
- struct sockaddr tipaddr;
-
- *result = false;
-
- target = kzalloc(share_len + 3, GFP_KERNEL);
- if (!target) {
- rc = -ENOMEM;
- goto out;
- }
-
- scnprintf(target, share_len + 3, "\\\\%.*s", (int)share_len, share);
-
- cifs_dbg(FYI, "%s: target name: %s\n", __func__, target + 2);
-
- rc = dns_resolve_server_name_to_ip(target, &tip, NULL);
- if (rc < 0)
- goto out;
-
- cifs_dbg(FYI, "%s: target ip: %s\n", __func__, tip);
-
- if (!cifs_convert_address(&tipaddr, tip, strlen(tip))) {
- cifs_dbg(VFS, "%s: failed to convert target ip address\n",
- __func__);
- rc = -EINVAL;
- goto out;
- }
-
- *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr,
- &tipaddr);
- cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result);
- rc = 0;
-
-out:
- kfree(target);
- kfree(tip);
-
- return rc;
-}
-
-int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
-{
- kfree(cifs_sb->prepath);
-
- if (prefix && *prefix) {
- cifs_sb->prepath = cifs_sanitize_prepath(prefix, GFP_ATOMIC);
- if (!cifs_sb->prepath)
- return -ENOMEM;
-
- convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
- } else
- cifs_sb->prepath = NULL;
-
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
- return 0;
-}
-
-/*
- * Handle weird Windows SMB server behaviour. It responds with
- * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request for
- * "\<server>\<dfsname>\<linkpath>" DFS reference, where <dfsname> contains
- * non-ASCII unicode symbols.
- */
-int cifs_inval_name_dfs_link_error(const unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- const char *full_path,
- bool *islink)
-{
- struct cifs_ses *ses = tcon->ses;
- size_t len;
- char *path;
- char *ref_path;
-
- *islink = false;
-
- /*
- * Fast path - skip check when @full_path doesn't have a prefix path to
- * look up or tcon is not DFS.
- */
- if (strlen(full_path) < 2 || !cifs_sb ||
- (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) ||
- !is_tcon_dfs(tcon) || !ses->server->origin_fullpath)
- return 0;
-
- /*
- * Slow path - tcon is DFS and @full_path has prefix path, so attempt
- * to get a referral to figure out whether it is an DFS link.
- */
- len = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1) + strlen(full_path) + 1;
- path = kmalloc(len, GFP_KERNEL);
- if (!path)
- return -ENOMEM;
-
- scnprintf(path, len, "%s%s", tcon->tree_name, full_path);
- ref_path = dfs_cache_canonical_path(path + 1, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- kfree(path);
-
- if (IS_ERR(ref_path)) {
- if (PTR_ERR(ref_path) != -EINVAL)
- return PTR_ERR(ref_path);
- } else {
- struct dfs_info3_param *refs = NULL;
- int num_refs = 0;
-
- /*
- * XXX: we are not using dfs_cache_find() here because we might
- * end filling all the DFS cache and thus potentially
- * removing cached DFS targets that the client would eventually
- * need during failover.
- */
- if (ses->server->ops->get_dfs_refer &&
- !ses->server->ops->get_dfs_refer(xid, ses, ref_path, &refs,
- &num_refs, cifs_sb->local_nls,
- cifs_remap(cifs_sb)))
- *islink = refs[0].server_type == DFS_TYPE_LINK;
- free_dfs_info_array(refs, num_refs);
- kfree(ref_path);
- }
- return 0;
-}
-#endif
-
-int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry)
-{
- int timeout = 10;
- int rc;
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus != CifsNeedReconnect) {
- spin_unlock(&server->srv_lock);
- return 0;
- }
- timeout *= server->nr_targets;
- spin_unlock(&server->srv_lock);
-
- /*
- * Give demultiplex thread up to 10 seconds to each target available for
- * reconnect -- should be greater than cifs socket timeout which is 7
- * seconds.
- *
- * On "soft" mounts we wait once. Hard mounts keep retrying until
- * process is killed or server comes back on-line.
- */
- do {
- rc = wait_event_interruptible_timeout(server->response_q,
- (server->tcpStatus != CifsNeedReconnect),
- timeout * HZ);
- if (rc < 0) {
- cifs_dbg(FYI, "%s: aborting reconnect due to received signal\n",
- __func__);
- return -ERESTARTSYS;
- }
-
- /* are we still trying to reconnect? */
- spin_lock(&server->srv_lock);
- if (server->tcpStatus != CifsNeedReconnect) {
- spin_unlock(&server->srv_lock);
- return 0;
- }
- spin_unlock(&server->srv_lock);
- } while (retry);
-
- cifs_dbg(FYI, "%s: gave up waiting on reconnect\n", __func__);
- return -EHOSTDOWN;
-}
diff --git a/fs/cifs/netlink.c b/fs/cifs/netlink.c
deleted file mode 100644
index 147d9409252c..000000000000
--- a/fs/cifs/netlink.c
+++ /dev/null
@@ -1,90 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Netlink routines for CIFS
- *
- * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
- */
-
-#include <net/genetlink.h>
-#include <uapi/linux/cifs/cifs_netlink.h>
-
-#include "netlink.h"
-#include "cifsglob.h"
-#include "cifs_debug.h"
-#include "cifs_swn.h"
-
-static const struct nla_policy cifs_genl_policy[CIFS_GENL_ATTR_MAX + 1] = {
- [CIFS_GENL_ATTR_SWN_REGISTRATION_ID] = { .type = NLA_U32 },
- [CIFS_GENL_ATTR_SWN_NET_NAME] = { .type = NLA_STRING },
- [CIFS_GENL_ATTR_SWN_SHARE_NAME] = { .type = NLA_STRING },
- [CIFS_GENL_ATTR_SWN_IP] = { .len = sizeof(struct sockaddr_storage) },
- [CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY] = { .type = NLA_FLAG },
- [CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY] = { .type = NLA_FLAG },
- [CIFS_GENL_ATTR_SWN_IP_NOTIFY] = { .type = NLA_FLAG },
- [CIFS_GENL_ATTR_SWN_KRB_AUTH] = { .type = NLA_FLAG },
- [CIFS_GENL_ATTR_SWN_USER_NAME] = { .type = NLA_STRING },
- [CIFS_GENL_ATTR_SWN_PASSWORD] = { .type = NLA_STRING },
- [CIFS_GENL_ATTR_SWN_DOMAIN_NAME] = { .type = NLA_STRING },
- [CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE] = { .type = NLA_U32 },
- [CIFS_GENL_ATTR_SWN_RESOURCE_STATE] = { .type = NLA_U32 },
- [CIFS_GENL_ATTR_SWN_RESOURCE_NAME] = { .type = NLA_STRING},
-};
-
-static const struct genl_ops cifs_genl_ops[] = {
- {
- .cmd = CIFS_GENL_CMD_SWN_NOTIFY,
- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
- .doit = cifs_swn_notify,
- },
-};
-
-static const struct genl_multicast_group cifs_genl_mcgrps[] = {
- [CIFS_GENL_MCGRP_SWN] = { .name = CIFS_GENL_MCGRP_SWN_NAME },
-};
-
-struct genl_family cifs_genl_family = {
- .name = CIFS_GENL_NAME,
- .version = CIFS_GENL_VERSION,
- .hdrsize = 0,
- .maxattr = CIFS_GENL_ATTR_MAX,
- .module = THIS_MODULE,
- .policy = cifs_genl_policy,
- .ops = cifs_genl_ops,
- .n_ops = ARRAY_SIZE(cifs_genl_ops),
- .resv_start_op = CIFS_GENL_CMD_SWN_NOTIFY + 1,
- .mcgrps = cifs_genl_mcgrps,
- .n_mcgrps = ARRAY_SIZE(cifs_genl_mcgrps),
-};
-
-/**
- * cifs_genl_init - Register generic netlink family
- *
- * Return zero if initialized successfully, otherwise non-zero.
- */
-int cifs_genl_init(void)
-{
- int ret;
-
- ret = genl_register_family(&cifs_genl_family);
- if (ret < 0) {
- cifs_dbg(VFS, "%s: failed to register netlink family\n",
- __func__);
- return ret;
- }
-
- return 0;
-}
-
-/**
- * cifs_genl_exit - Unregister generic netlink family
- */
-void cifs_genl_exit(void)
-{
- int ret;
-
- ret = genl_unregister_family(&cifs_genl_family);
- if (ret < 0) {
- cifs_dbg(VFS, "%s: failed to unregister netlink family\n",
- __func__);
- }
-}
diff --git a/fs/cifs/netlink.h b/fs/cifs/netlink.h
deleted file mode 100644
index e2fa8ed24c54..000000000000
--- a/fs/cifs/netlink.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Netlink routines for CIFS
- *
- * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
- */
-
-#ifndef _CIFS_NETLINK_H
-#define _CIFS_NETLINK_H
-
-extern struct genl_family cifs_genl_family;
-
-extern int cifs_genl_init(void);
-extern void cifs_genl_exit(void);
-
-#endif /* _CIFS_NETLINK_H */
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
deleted file mode 100644
index 1b52e6ac431c..000000000000
--- a/fs/cifs/netmisc.c
+++ /dev/null
@@ -1,1021 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * Copyright (c) International Business Machines Corp., 2002,2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- * Error mapping routines from Samba libsmb/errormap.c
- * Copyright (C) Andrew Tridgell 2001
- */
-
-#include <linux/net.h>
-#include <linux/string.h>
-#include <linux/in.h>
-#include <linux/ctype.h>
-#include <linux/fs.h>
-#include <asm/div64.h>
-#include <asm/byteorder.h>
-#include <linux/inet.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "smberr.h"
-#include "cifs_debug.h"
-#include "nterr.h"
-
-struct smb_to_posix_error {
- __u16 smb_err;
- int posix_code;
-};
-
-static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
- {ERRbadfunc, -EINVAL},
- {ERRbadfile, -ENOENT},
- {ERRbadpath, -ENOTDIR},
- {ERRnofids, -EMFILE},
- {ERRnoaccess, -EACCES},
- {ERRbadfid, -EBADF},
- {ERRbadmcb, -EIO},
- {ERRnomem, -EREMOTEIO},
- {ERRbadmem, -EFAULT},
- {ERRbadenv, -EFAULT},
- {ERRbadformat, -EINVAL},
- {ERRbadaccess, -EACCES},
- {ERRbaddata, -EIO},
- {ERRbaddrive, -ENXIO},
- {ERRremcd, -EACCES},
- {ERRdiffdevice, -EXDEV},
- {ERRnofiles, -ENOENT},
- {ERRwriteprot, -EROFS},
- {ERRbadshare, -EBUSY},
- {ERRlock, -EACCES},
- {ERRunsup, -EINVAL},
- {ERRnosuchshare, -ENXIO},
- {ERRfilexists, -EEXIST},
- {ERRinvparm, -EINVAL},
- {ERRdiskfull, -ENOSPC},
- {ERRinvname, -ENOENT},
- {ERRinvlevel, -EOPNOTSUPP},
- {ERRdirnotempty, -ENOTEMPTY},
- {ERRnotlocked, -ENOLCK},
- {ERRcancelviolation, -ENOLCK},
- {ERRalreadyexists, -EEXIST},
- {ERRmoredata, -EOVERFLOW},
- {ERReasnotsupported, -EOPNOTSUPP},
- {ErrQuota, -EDQUOT},
- {ErrNotALink, -ENOLINK},
- {ERRnetlogonNotStarted, -ENOPROTOOPT},
- {ERRsymlink, -EOPNOTSUPP},
- {ErrTooManyLinks, -EMLINK},
- {0, 0}
-};
-
-static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
- {ERRerror, -EIO},
- {ERRbadpw, -EACCES}, /* was EPERM */
- {ERRbadtype, -EREMOTE},
- {ERRaccess, -EACCES},
- {ERRinvtid, -ENXIO},
- {ERRinvnetname, -ENXIO},
- {ERRinvdevice, -ENXIO},
- {ERRqfull, -ENOSPC},
- {ERRqtoobig, -ENOSPC},
- {ERRqeof, -EIO},
- {ERRinvpfid, -EBADF},
- {ERRsmbcmd, -EBADRQC},
- {ERRsrverror, -EIO},
- {ERRbadBID, -EIO},
- {ERRfilespecs, -EINVAL},
- {ERRbadLink, -EIO},
- {ERRbadpermits, -EINVAL},
- {ERRbadPID, -ESRCH},
- {ERRsetattrmode, -EINVAL},
- {ERRpaused, -EHOSTDOWN},
- {ERRmsgoff, -EHOSTDOWN},
- {ERRnoroom, -ENOSPC},
- {ERRrmuns, -EUSERS},
- {ERRtimeout, -ETIME},
- {ERRnoresource, -EREMOTEIO},
- {ERRtoomanyuids, -EUSERS},
- {ERRbaduid, -EACCES},
- {ERRusempx, -EIO},
- {ERRusestd, -EIO},
- {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
- {ERRnoSuchUser, -EACCES},
-/* {ERRaccountexpired, -EACCES},
- {ERRbadclient, -EACCES},
- {ERRbadLogonTime, -EACCES},
- {ERRpasswordExpired, -EACCES},*/
- {ERRaccountexpired, -EKEYEXPIRED},
- {ERRbadclient, -EACCES},
- {ERRbadLogonTime, -EACCES},
- {ERRpasswordExpired, -EKEYEXPIRED},
-
- {ERRnosupport, -EINVAL},
- {0, 0}
-};
-
-/*
- * Convert a string containing text IPv4 or IPv6 address to binary form.
- *
- * Returns 0 on failure.
- */
-static int
-cifs_inet_pton(const int address_family, const char *cp, int len, void *dst)
-{
- int ret = 0;
-
- /* calculate length by finding first slash or NULL */
- if (address_family == AF_INET)
- ret = in4_pton(cp, len, dst, '\\', NULL);
- else if (address_family == AF_INET6)
- ret = in6_pton(cp, len, dst , '\\', NULL);
-
- cifs_dbg(NOISY, "address conversion returned %d for %*.*s\n",
- ret, len, len, cp);
- if (ret > 0)
- ret = 1;
- return ret;
-}
-
-/*
- * Try to convert a string to an IPv4 address and then attempt to convert
- * it to an IPv6 address if that fails. Set the family field if either
- * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to
- * treat the part following it as a numeric sin6_scope_id.
- *
- * Returns 0 on failure.
- */
-int
-cifs_convert_address(struct sockaddr *dst, const char *src, int len)
-{
- int rc, alen, slen;
- const char *pct;
- char scope_id[13];
- struct sockaddr_in *s4 = (struct sockaddr_in *) dst;
- struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst;
-
- /* IPv4 address */
- if (cifs_inet_pton(AF_INET, src, len, &s4->sin_addr.s_addr)) {
- s4->sin_family = AF_INET;
- return 1;
- }
-
- /* attempt to exclude the scope ID from the address part */
- pct = memchr(src, '%', len);
- alen = pct ? pct - src : len;
-
- rc = cifs_inet_pton(AF_INET6, src, alen, &s6->sin6_addr.s6_addr);
- if (!rc)
- return rc;
-
- s6->sin6_family = AF_INET6;
- if (pct) {
- /* grab the scope ID */
- slen = len - (alen + 1);
- if (slen <= 0 || slen > 12)
- return 0;
- memcpy(scope_id, pct + 1, slen);
- scope_id[slen] = '\0';
-
- rc = kstrtouint(scope_id, 0, &s6->sin6_scope_id);
- rc = (rc == 0) ? 1 : 0;
- }
-
- return rc;
-}
-
-void
-cifs_set_port(struct sockaddr *addr, const unsigned short int port)
-{
- switch (addr->sa_family) {
- case AF_INET:
- ((struct sockaddr_in *)addr)->sin_port = htons(port);
- break;
- case AF_INET6:
- ((struct sockaddr_in6 *)addr)->sin6_port = htons(port);
- break;
- }
-}
-
-/*****************************************************************************
-convert a NT status code to a dos class/code
- *****************************************************************************/
-/* NT status -> dos error map */
-static const struct {
- __u8 dos_class;
- __u16 dos_code;
- __u32 ntstatus;
-} ntstatus_to_dos_map[] = {
- {
- ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
- ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
- ERRDOS, ERRinvlevel, NT_STATUS_INVALID_INFO_CLASS}, {
- ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
- ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
- ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
- ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
- ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
- ERRDOS, 87, NT_STATUS_INVALID_CID}, {
- ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
- ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
- ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
- ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
- ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
- ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
- ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
- ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
-/* { This NT error code was 'sqashed'
- from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
- during the session setup } */
- {
- ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
- ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
- ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
- ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
- ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
- ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
- ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
- ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
- ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
- ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
- ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
-/* { This NT error code was 'sqashed'
- from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
- during the session setup } */
- {
- ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
- ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
- ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
- ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
- ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
- ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
- ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
- ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
- ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
- ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
- /* mapping changed since shell does lookup on * expects FileNotFound */
- ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, {
- ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
- ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
- ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
- ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
- ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
- ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
- ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
- ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
- ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
- ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
- ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
- ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
- ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
- ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
- ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
- ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
- ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
- ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
- ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
- ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
- ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
- ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
- ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
- ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
- ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
- ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
- ERRDOS, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED}, {
- ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
- ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
- ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
- ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
- ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
- ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
- ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
- ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
- ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
- ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
- ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
- ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
-/* { This NT error code was 'sqashed'
- from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
- during the session setup } */
- {
- ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */
- ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
- ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
- ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
- ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
-/* { This NT error code was 'sqashed'
- from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
- during the session setup } */
- {
- ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
- ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
- ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
- ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
- ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
- ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, {
- ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, {
- ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
- ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
- ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
- ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
- ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
- ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
- ERRDOS, 112, NT_STATUS_DISK_FULL}, {
- ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
- ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
- ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
- ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
- ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
- ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
- ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
- ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
- ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
- ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
- ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
- ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
- ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
- ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
- ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
- ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
- ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
- ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
-/* { This NT error code was 'sqashed'
- from NT_STATUS_INSUFFICIENT_RESOURCES to
- NT_STATUS_INSUFF_SERVER_RESOURCES during the session setup } */
- {
- ERRDOS, ERRnoresource, NT_STATUS_INSUFFICIENT_RESOURCES}, {
- ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
- ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
- ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
- ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
- ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
- ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
- ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
- ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
- ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
- ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
- ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
- ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
- ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
- ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
- ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
- ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
- ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
- ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
- ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
- ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
- ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
- ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
- ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
- ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
- ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
- ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
- ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
- ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
- ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
- ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
- ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
- ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
- ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
- ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
- ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
- ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
- ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
- ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
- ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
- ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
- ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
- ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
- ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
- ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
- ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
- ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
- ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
- ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
- ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
- ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
- ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
- ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
- ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
- ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
- ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
- ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
- ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
- ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
- ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
- ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
- ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
- ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
- ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
- ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
- ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
- ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
- ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
- ERRDOS, 203, 0xc0000100}, {
- ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
- ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
- ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
- ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
- ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
- ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
- ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
- ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
- ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
- ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
- ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
- ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
- ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
- ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
- ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
- ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
- ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
- ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
- ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
- ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
- ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
- ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
- ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
- ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
- ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
- ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
- ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
- ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
- ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
- ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
- ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
- ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
- ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
- ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
- ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
- ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
- ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
- ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
- ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
- ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
- ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
- ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
- ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
- ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
- ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
- ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
- ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
- ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
- ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
- ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
- ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
- ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
- ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
- ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
- ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
- ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
- ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
- ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
- ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
- ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
- ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
- ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
- ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
- ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
- ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
- ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
- ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
- ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
- ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
- ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
- ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
- ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
- ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
- ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
- ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
- ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
- ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
- ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
- ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
- ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
- ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
- ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
- ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
- ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
- ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
- ERRHRD, ERRgeneral, 0xc000016e}, {
- ERRHRD, ERRgeneral, 0xc000016f}, {
- ERRHRD, ERRgeneral, 0xc0000170}, {
- ERRHRD, ERRgeneral, 0xc0000171}, {
- ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
- ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
- ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
- ERRHRD, ERRgeneral, 0xc0000179}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
- ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
- ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
- ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
- ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
- ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
- ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
- ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
- ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
- ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
- ERRDOS, 19, NT_STATUS_TOO_LATE}, {
- ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
-/* { This NT error code was 'sqashed'
- from NT_STATUS_NO_TRUST_SAM_ACCOUNT to
- NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE during the session setup } */
- {
- ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
- ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
- ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
- ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
- ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
- ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
- ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
- ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
- ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, {
- ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
- ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
- ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
- ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
- ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
- ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
- ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
-/* { This NT error code was 'sqashed'
- from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
- during the session setup } */
- {
- ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
- ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
- ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
- ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
- ERRDOS, ERRnoresource, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
- ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
- ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
- ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
- ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
- ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
- ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
- ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
- ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
- ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
- ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
- ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
- ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
- ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
- ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
- ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
- ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
- ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
- ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
- ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
- ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
- ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
- ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
- ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
- ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
- ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
- ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
- ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_MUST_CHANGE}, {
- ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
- ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
- ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
- ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
- ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
- ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
- ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
- ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
- ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
- ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
- ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
- ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
- ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
- ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
- ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
- ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
- ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
- ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
- ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
- ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
- ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
- ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
- ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
- ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
- ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
- ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
- ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
- ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
- ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
- ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
- ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
- ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
- ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
- ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
- ERRHRD, ERRgeneral, 0xc000024a}, {
- ERRHRD, ERRgeneral, 0xc000024b}, {
- ERRHRD, ERRgeneral, 0xc000024c}, {
- ERRHRD, ERRgeneral, 0xc000024d}, {
- ERRHRD, ERRgeneral, 0xc000024e}, {
- ERRHRD, ERRgeneral, 0xc000024f}, {
- ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
- ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
- ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
- ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
- ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
- ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
- ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
- ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
- ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
- ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
- ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
- ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
- ERRHRD, ERRgeneral, 0xc000025d}, {
- ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
- ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
- ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
- ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
- ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
- ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
- ERRDOS, ErrTooManyLinks, NT_STATUS_TOO_MANY_LINKS}, {
- ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
- ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
- ERRDOS, 21, 0xc000026e}, {
- ERRDOS, 161, 0xc0000281}, {
- ERRDOS, ERRnoaccess, 0xc000028a}, {
- ERRDOS, ERRnoaccess, 0xc000028b}, {
- ERRHRD, ERRgeneral, 0xc000028c}, {
- ERRDOS, ERRnoaccess, 0xc000028d}, {
- ERRDOS, ERRnoaccess, 0xc000028e}, {
- ERRDOS, ERRnoaccess, 0xc000028f}, {
- ERRDOS, ERRnoaccess, 0xc0000290}, {
- ERRDOS, ERRbadfunc, 0xc000029c}, {
- ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
- ERRDOS, ERRinvlevel, 0x007c0001}, {
- 0, 0, 0 }
-};
-
-/*****************************************************************************
- Print an error message from the status code
- *****************************************************************************/
-static void
-cifs_print_status(__u32 status_code)
-{
- int idx = 0;
-
- while (nt_errs[idx].nt_errstr != NULL) {
- if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
- (status_code & 0xFFFFFF)) {
- pr_notice("Status code returned 0x%08x %s\n",
- status_code, nt_errs[idx].nt_errstr);
- }
- idx++;
- }
- return;
-}
-
-
-static void
-ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode)
-{
- int i;
- if (ntstatus == 0) {
- *eclass = 0;
- *ecode = 0;
- return;
- }
- for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
- if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
- *eclass = ntstatus_to_dos_map[i].dos_class;
- *ecode = ntstatus_to_dos_map[i].dos_code;
- return;
- }
- }
- *eclass = ERRHRD;
- *ecode = ERRgeneral;
-}
-
-int
-map_smb_to_linux_error(char *buf, bool logErr)
-{
- struct smb_hdr *smb = (struct smb_hdr *)buf;
- unsigned int i;
- int rc = -EIO; /* if transport error smb error may not be set */
- __u8 smberrclass;
- __u16 smberrcode;
-
- /* BB if NT Status codes - map NT BB */
-
- /* old style smb error codes */
- if (smb->Status.CifsError == 0)
- return 0;
-
- if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
- /* translate the newer STATUS codes to old style SMB errors
- * and then to POSIX errors */
- __u32 err = le32_to_cpu(smb->Status.CifsError);
- if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED)))
- cifs_print_status(err);
- else if (cifsFYI & CIFS_RC)
- cifs_print_status(err);
- ntstatus_to_dos(err, &smberrclass, &smberrcode);
- } else {
- smberrclass = smb->Status.DosError.ErrorClass;
- smberrcode = le16_to_cpu(smb->Status.DosError.Error);
- }
-
- /* old style errors */
-
- /* DOS class smb error codes - map DOS */
- if (smberrclass == ERRDOS) {
- /* 1 byte field no need to byte reverse */
- for (i = 0;
- i <
- sizeof(mapping_table_ERRDOS) /
- sizeof(struct smb_to_posix_error); i++) {
- if (mapping_table_ERRDOS[i].smb_err == 0)
- break;
- else if (mapping_table_ERRDOS[i].smb_err ==
- smberrcode) {
- rc = mapping_table_ERRDOS[i].posix_code;
- break;
- }
- /* else try next error mapping one to see if match */
- }
- } else if (smberrclass == ERRSRV) {
- /* server class of error codes */
- for (i = 0;
- i <
- sizeof(mapping_table_ERRSRV) /
- sizeof(struct smb_to_posix_error); i++) {
- if (mapping_table_ERRSRV[i].smb_err == 0)
- break;
- else if (mapping_table_ERRSRV[i].smb_err ==
- smberrcode) {
- rc = mapping_table_ERRSRV[i].posix_code;
- break;
- }
- /* else try next error mapping to see if match */
- }
- }
- /* else ERRHRD class errors or junk - return EIO */
-
- cifs_dbg(FYI, "Mapping smb error code 0x%x to POSIX err %d\n",
- le32_to_cpu(smb->Status.CifsError), rc);
-
- /* generic corrective action e.g. reconnect SMB session on
- * ERRbaduid could be added */
-
- return rc;
-}
-
-int
-map_and_check_smb_error(struct mid_q_entry *mid, bool logErr)
-{
- int rc;
- struct smb_hdr *smb = (struct smb_hdr *)mid->resp_buf;
-
- rc = map_smb_to_linux_error((char *)smb, logErr);
- if (rc == -EACCES && !(smb->Flags2 & SMBFLG2_ERR_STATUS)) {
- /* possible ERRBaduid */
- __u8 class = smb->Status.DosError.ErrorClass;
- __u16 code = le16_to_cpu(smb->Status.DosError.Error);
-
- /* switch can be used to handle different errors */
- if (class == ERRSRV && code == ERRbaduid) {
- cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n",
- code);
- cifs_signal_cifsd_for_reconnect(mid->server, false);
- }
- }
-
- return rc;
-}
-
-
-/*
- * calculate the size of the SMB message based on the fixed header
- * portion, the number of word parameters and the data portion of the message
- */
-unsigned int
-smbCalcSize(void *buf)
-{
- struct smb_hdr *ptr = buf;
- return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
- 2 /* size of the bcc field */ + get_bcc(ptr));
-}
-
-/* The following are taken from fs/ntfs/util.c */
-
-#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
-
-/*
- * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
- * into Unix UTC (based 1970-01-01, in seconds).
- */
-struct timespec64
-cifs_NTtimeToUnix(__le64 ntutc)
-{
- struct timespec64 ts;
- /* BB what about the timezone? BB */
-
- /* Subtract the NTFS time offset, then convert to 1s intervals. */
- s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
- u64 abs_t;
-
- /*
- * Unfortunately can not use normal 64 bit division on 32 bit arch, but
- * the alternative, do_div, does not work with negative numbers so have
- * to special case them
- */
- if (t < 0) {
- abs_t = -t;
- ts.tv_nsec = (time64_t)(do_div(abs_t, 10000000) * 100);
- ts.tv_nsec = -ts.tv_nsec;
- ts.tv_sec = -abs_t;
- } else {
- abs_t = t;
- ts.tv_nsec = (time64_t)do_div(abs_t, 10000000) * 100;
- ts.tv_sec = abs_t;
- }
-
- return ts;
-}
-
-/* Convert the Unix UTC into NT UTC. */
-u64
-cifs_UnixTimeToNT(struct timespec64 t)
-{
- /* Convert to 100ns intervals and then add the NTFS time offset. */
- return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET;
-}
-
-static const int total_days_of_prev_months[] = {
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
-};
-
-struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
-{
- struct timespec64 ts;
- time64_t sec, days;
- int min, day, month, year;
- u16 date = le16_to_cpu(le_date);
- u16 time = le16_to_cpu(le_time);
- SMB_TIME *st = (SMB_TIME *)&time;
- SMB_DATE *sd = (SMB_DATE *)&date;
-
- cifs_dbg(FYI, "date %d time %d\n", date, time);
-
- sec = 2 * st->TwoSeconds;
- min = st->Minutes;
- if ((sec > 59) || (min > 59))
- cifs_dbg(VFS, "Invalid time min %d sec %lld\n", min, sec);
- sec += (min * 60);
- sec += 60 * 60 * st->Hours;
- if (st->Hours > 24)
- cifs_dbg(VFS, "Invalid hours %d\n", st->Hours);
- day = sd->Day;
- month = sd->Month;
- if (day < 1 || day > 31 || month < 1 || month > 12) {
- cifs_dbg(VFS, "Invalid date, month %d day: %d\n", month, day);
- day = clamp(day, 1, 31);
- month = clamp(month, 1, 12);
- }
- month -= 1;
- days = day + total_days_of_prev_months[month];
- days += 3652; /* account for difference in days between 1980 and 1970 */
- year = sd->Year;
- days += year * 365;
- days += (year/4); /* leap year */
- /* generalized leap year calculation is more complex, ie no leap year
- for years/100 except for years/400, but since the maximum number for DOS
- year is 2**7, the last year is 1980+127, which means we need only
- consider 2 special case years, ie the years 2000 and 2100, and only
- adjust for the lack of leap year for the year 2100, as 2000 was a
- leap year (divisable by 400) */
- if (year >= 120) /* the year 2100 */
- days = days - 1; /* do not count leap year for the year 2100 */
-
- /* adjust for leap year where we are still before leap day */
- if (year != 120)
- days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
- sec += 24 * 60 * 60 * days;
-
- ts.tv_sec = sec + offset;
-
- /* cifs_dbg(FYI, "sec after cnvrt dos to unix time %d\n",sec); */
-
- ts.tv_nsec = 0;
- return ts;
-}
diff --git a/fs/cifs/nterr.c b/fs/cifs/nterr.c
deleted file mode 100644
index 358a766375b4..000000000000
--- a/fs/cifs/nterr.c
+++ /dev/null
@@ -1,674 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Unix SMB/Netbios implementation.
- * Version 1.9.
- * RPC Pipe client / server routines
- * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
- */
-
-/* NT error codes - see nterr.h */
-#include <linux/types.h>
-#include <linux/fs.h>
-#include "nterr.h"
-
-const struct nt_err_code_struct nt_errs[] = {
- {"NT_STATUS_OK", NT_STATUS_OK},
- {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
- {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
- {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
- {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
- {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
- {"NT_STATUS_BUFFER_OVERFLOW", NT_STATUS_BUFFER_OVERFLOW},
- {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
- {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
- {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
- {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
- {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
- {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
- {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
- {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
- {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
- {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
- {"NT_STATUS_INVALID_DEVICE_REQUEST",
- NT_STATUS_INVALID_DEVICE_REQUEST},
- {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
- {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
- {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
- {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
- {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
- {"NT_STATUS_MORE_PROCESSING_REQUIRED",
- NT_STATUS_MORE_PROCESSING_REQUIRED},
- {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
- {"NT_STATUS_CONFLICTING_ADDRESSES",
- NT_STATUS_CONFLICTING_ADDRESSES},
- {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
- {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
- {"NT_STATUS_UNABLE_TO_DELETE_SECTION",
- NT_STATUS_UNABLE_TO_DELETE_SECTION},
- {"NT_STATUS_INVALID_SYSTEM_SERVICE",
- NT_STATUS_INVALID_SYSTEM_SERVICE},
- {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
- {"NT_STATUS_INVALID_LOCK_SEQUENCE",
- NT_STATUS_INVALID_LOCK_SEQUENCE},
- {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
- {"NT_STATUS_INVALID_FILE_FOR_SECTION",
- NT_STATUS_INVALID_FILE_FOR_SECTION},
- {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
- {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
- {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
- {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
- {"NT_STATUS_NONCONTINUABLE_EXCEPTION",
- NT_STATUS_NONCONTINUABLE_EXCEPTION},
- {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
- {"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
- {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
- {"NT_STATUS_INVALID_UNWIND_TARGET",
- NT_STATUS_INVALID_UNWIND_TARGET},
- {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
- {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
- {"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
- NT_STATUS_UNABLE_TO_DECOMMIT_VM},
- {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
- {"NT_STATUS_INVALID_PORT_ATTRIBUTES",
- NT_STATUS_INVALID_PORT_ATTRIBUTES},
- {"NT_STATUS_PORT_MESSAGE_TOO_LONG",
- NT_STATUS_PORT_MESSAGE_TOO_LONG},
- {"NT_STATUS_INVALID_PARAMETER_MIX",
- NT_STATUS_INVALID_PARAMETER_MIX},
- {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
- {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
- {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
- {"NT_STATUS_OBJECT_NAME_NOT_FOUND",
- NT_STATUS_OBJECT_NAME_NOT_FOUND},
- {"NT_STATUS_OBJECT_NAME_COLLISION",
- NT_STATUS_OBJECT_NAME_COLLISION},
- {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
- {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
- {"NT_STATUS_DEVICE_ALREADY_ATTACHED",
- NT_STATUS_DEVICE_ALREADY_ATTACHED},
- {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
- {"NT_STATUS_OBJECT_PATH_NOT_FOUND",
- NT_STATUS_OBJECT_PATH_NOT_FOUND},
- {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
- NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
- {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
- {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
- {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
- {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
- {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
- {"NT_STATUS_PORT_CONNECTION_REFUSED",
- NT_STATUS_PORT_CONNECTION_REFUSED},
- {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
- {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
- {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
- {"NT_STATUS_INVALID_PAGE_PROTECTION",
- NT_STATUS_INVALID_PAGE_PROTECTION},
- {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
- {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
- NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
- {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
- {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
- {"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
- NT_STATUS_SUSPEND_COUNT_EXCEEDED},
- {"NT_STATUS_THREAD_IS_TERMINATING",
- NT_STATUS_THREAD_IS_TERMINATING},
- {"NT_STATUS_BAD_WORKING_SET_LIMIT",
- NT_STATUS_BAD_WORKING_SET_LIMIT},
- {"NT_STATUS_INCOMPATIBLE_FILE_MAP",
- NT_STATUS_INCOMPATIBLE_FILE_MAP},
- {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
- {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
- {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
- {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
- {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
- {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
- {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
- {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
- {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
- {"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
- NT_STATUS_CTL_FILE_NOT_SUPPORTED},
- {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
- {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
- {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
- {"NT_STATUS_INVALID_PRIMARY_GROUP",
- NT_STATUS_INVALID_PRIMARY_GROUP},
- {"NT_STATUS_NO_IMPERSONATION_TOKEN",
- NT_STATUS_NO_IMPERSONATION_TOKEN},
- {"NT_STATUS_CANT_DISABLE_MANDATORY",
- NT_STATUS_CANT_DISABLE_MANDATORY},
- {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
- {"NT_STATUS_NO_SUCH_LOGON_SESSION",
- NT_STATUS_NO_SUCH_LOGON_SESSION},
- {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
- {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
- {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
- {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
- {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
- {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
- {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
- {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
- {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
- {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
- {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
- {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
- {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
- {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
- {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
- {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
- {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
- {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
- {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
- {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
- {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
- NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
- {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
- {"NT_STATUS_INVALID_SUB_AUTHORITY",
- NT_STATUS_INVALID_SUB_AUTHORITY},
- {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
- {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
- {"NT_STATUS_INVALID_SECURITY_DESCR",
- NT_STATUS_INVALID_SECURITY_DESCR},
- {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
- {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
- {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
- {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
- {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
- {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
- {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
- {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
- {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
- NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
- {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
- {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
- {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
- {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
- {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
- {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
- {"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
- NT_STATUS_RESOURCE_DATA_NOT_FOUND},
- {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
- NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
- {"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
- NT_STATUS_RESOURCE_NAME_NOT_FOUND},
- {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
- NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
- {"NT_STATUS_FLOAT_DENORMAL_OPERAND",
- NT_STATUS_FLOAT_DENORMAL_OPERAND},
- {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
- {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
- {"NT_STATUS_FLOAT_INVALID_OPERATION",
- NT_STATUS_FLOAT_INVALID_OPERATION},
- {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
- {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
- {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
- {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
- NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
- {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
- {"NT_STATUS_PRIVILEGED_INSTRUCTION",
- NT_STATUS_PRIVILEGED_INSTRUCTION},
- {"NT_STATUS_TOO_MANY_PAGING_FILES",
- NT_STATUS_TOO_MANY_PAGING_FILES},
- {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
- {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
- NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
- {"NT_STATUS_INSUFFICIENT_RESOURCES",
- NT_STATUS_INSUFFICIENT_RESOURCES},
- {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
- {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
- {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
- {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
- {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
- {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
- {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
- {"NT_STATUS_MEDIA_WRITE_PROTECTED",
- NT_STATUS_MEDIA_WRITE_PROTECTED},
- {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
- {"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
- NT_STATUS_INVALID_GROUP_ATTRIBUTES},
- {"NT_STATUS_BAD_IMPERSONATION_LEVEL",
- NT_STATUS_BAD_IMPERSONATION_LEVEL},
- {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
- {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
- {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
- {"NT_STATUS_BAD_MASTER_BOOT_RECORD",
- NT_STATUS_BAD_MASTER_BOOT_RECORD},
- {"NT_STATUS_INSTRUCTION_MISALIGNMENT",
- NT_STATUS_INSTRUCTION_MISALIGNMENT},
- {"NT_STATUS_INSTANCE_NOT_AVAILABLE",
- NT_STATUS_INSTANCE_NOT_AVAILABLE},
- {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
- {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
- {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
- {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
- {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
- {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
- {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
- {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
- {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
- {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
- {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
- {"NT_STATUS_PROFILING_NOT_STARTED",
- NT_STATUS_PROFILING_NOT_STARTED},
- {"NT_STATUS_PROFILING_NOT_STOPPED",
- NT_STATUS_PROFILING_NOT_STOPPED},
- {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
- {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
- {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
- {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
- {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
- {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
- {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
- {"NT_STATUS_DEVICE_DOES_NOT_EXIST",
- NT_STATUS_DEVICE_DOES_NOT_EXIST},
- {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
- {"NT_STATUS_ADAPTER_HARDWARE_ERROR",
- NT_STATUS_ADAPTER_HARDWARE_ERROR},
- {"NT_STATUS_INVALID_NETWORK_RESPONSE",
- NT_STATUS_INVALID_NETWORK_RESPONSE},
- {"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
- NT_STATUS_UNEXPECTED_NETWORK_ERROR},
- {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
- {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
- {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
- {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
- {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
- {"NT_STATUS_NETWORK_ACCESS_DENIED",
- NT_STATUS_NETWORK_ACCESS_DENIED},
- {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
- {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
- {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
- {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
- {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
- {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
- {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
- {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
- {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
- {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
- {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
- {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
- NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
- {"NT_STATUS_NO_SECURITY_ON_OBJECT",
- NT_STATUS_NO_SECURITY_ON_OBJECT},
- {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
- {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
- {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
- NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
- {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
- {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
- {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
- {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
- {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
- {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
- {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
- NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
- {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
- {"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
- NT_STATUS_INVALID_OPLOCK_PROTOCOL},
- {"NT_STATUS_INTERNAL_DB_CORRUPTION",
- NT_STATUS_INTERNAL_DB_CORRUPTION},
- {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
- {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
- {"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
- NT_STATUS_BAD_DESCRIPTOR_FORMAT},
- {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
- {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
- {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
- NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
- {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
- NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
- {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
- NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
- {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
- {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
- {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
- {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
- {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
- {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
- {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
- {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
- {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
- {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
- {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
- {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
- {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
- {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
- {"NT_STATUS_REDIRECTOR_NOT_STARTED",
- NT_STATUS_REDIRECTOR_NOT_STARTED},
- {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
- {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
- {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
- {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
- {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
- {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
- {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
- {"NT_STATUS_BAD_LOGON_SESSION_STATE",
- NT_STATUS_BAD_LOGON_SESSION_STATE},
- {"NT_STATUS_LOGON_SESSION_COLLISION",
- NT_STATUS_LOGON_SESSION_COLLISION},
- {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
- {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
- {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
- {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
- {"NT_STATUS_PROCESS_IS_TERMINATING",
- NT_STATUS_PROCESS_IS_TERMINATING},
- {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
- {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
- {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
- {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
- {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
- {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
- {"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
- NT_STATUS_ABIOS_LID_ALREADY_OWNED},
- {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
- {"NT_STATUS_ABIOS_INVALID_COMMAND",
- NT_STATUS_ABIOS_INVALID_COMMAND},
- {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
- {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
- NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
- {"NT_STATUS_ABIOS_INVALID_SELECTOR",
- NT_STATUS_ABIOS_INVALID_SELECTOR},
- {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
- {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
- {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
- {"NT_STATUS_INVALID_LDT_DESCRIPTOR",
- NT_STATUS_INVALID_LDT_DESCRIPTOR},
- {"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
- NT_STATUS_INVALID_IMAGE_NE_FORMAT},
- {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
- {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
- {"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
- NT_STATUS_MAPPED_FILE_SIZE_ZERO},
- {"NT_STATUS_TOO_MANY_OPENED_FILES",
- NT_STATUS_TOO_MANY_OPENED_FILES},
- {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
- {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
- {"NT_STATUS_INVALID_COMPUTER_NAME",
- NT_STATUS_INVALID_COMPUTER_NAME},
- {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
- {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
- {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
- {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
- {"NT_STATUS_MEMBERS_PRIMARY_GROUP",
- NT_STATUS_MEMBERS_PRIMARY_GROUP},
- {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
- {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
- {"NT_STATUS_THREAD_NOT_IN_PROCESS",
- NT_STATUS_THREAD_NOT_IN_PROCESS},
- {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
- {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
- NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
- {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
- {"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
- NT_STATUS_INVALID_IMAGE_LE_FORMAT},
- {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
- {"NT_STATUS_INVALID_IMAGE_PROTECT",
- NT_STATUS_INVALID_IMAGE_PROTECT},
- {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
- {"NT_STATUS_LOGON_SERVER_CONFLICT",
- NT_STATUS_LOGON_SERVER_CONFLICT},
- {"NT_STATUS_TIME_DIFFERENCE_AT_DC",
- NT_STATUS_TIME_DIFFERENCE_AT_DC},
- {"NT_STATUS_SYNCHRONIZATION_REQUIRED",
- NT_STATUS_SYNCHRONIZATION_REQUIRED},
- {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
- {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
- {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
- {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
- {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
- {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
- {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
- {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
- {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
- {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
- {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
- {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
- {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
- {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
- {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
- {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
- {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
- {"NT_STATUS_PAGEFILE_CREATE_FAILED",
- NT_STATUS_PAGEFILE_CREATE_FAILED},
- {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
- {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
- {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
- {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
- NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
- {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
- {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
- {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
- {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
- {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
- {"NT_STATUS_SERIAL_NO_DEVICE_INITED",
- NT_STATUS_SERIAL_NO_DEVICE_INITED},
- {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
- {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
- {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
- {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
- {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
- {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
- {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
- {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
- {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
- {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
- {"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
- NT_STATUS_LOGON_TYPE_NOT_GRANTED},
- {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
- {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
- NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
- {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
- NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
- {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
- {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
- NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
- {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
- {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
- {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
- {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
- {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
- NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
- {"NT_STATUS_FLOPPY_WRONG_CYLINDER",
- NT_STATUS_FLOPPY_WRONG_CYLINDER},
- {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
- {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
- {"NT_STATUS_DISK_RECALIBRATE_FAILED",
- NT_STATUS_DISK_RECALIBRATE_FAILED},
- {"NT_STATUS_DISK_OPERATION_FAILED",
- NT_STATUS_DISK_OPERATION_FAILED},
- {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
- {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
- {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
- {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
- {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
- {"NT_STATUS_DEVICE_NOT_PARTITIONED",
- NT_STATUS_DEVICE_NOT_PARTITIONED},
- {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
- {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
- NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
- {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
- {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
- {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
- {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
- {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
- {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
- {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
- {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
- NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
- {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
- {"NT_STATUS_CHILD_MUST_BE_VOLATILE",
- NT_STATUS_CHILD_MUST_BE_VOLATILE},
- {"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
- NT_STATUS_DEVICE_CONFIGURATION_ERROR},
- {"NT_STATUS_DRIVER_INTERNAL_ERROR",
- NT_STATUS_DRIVER_INTERNAL_ERROR},
- {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
- {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
- {"NT_STATUS_DEVICE_PROTOCOL_ERROR",
- NT_STATUS_DEVICE_PROTOCOL_ERROR},
- {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
- {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
- {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
- {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
- {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
- {"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
- NT_STATUS_TRUSTED_DOMAIN_FAILURE},
- {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
- NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
- {"NT_STATUS_EVENTLOG_FILE_CORRUPT",
- NT_STATUS_EVENTLOG_FILE_CORRUPT},
- {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
- {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
- {"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
- NT_STATUS_MUTANT_LIMIT_EXCEEDED},
- {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
- {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
- {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
- {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
- NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
- {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
- {"NT_STATUS_EVENTLOG_FILE_CHANGED",
- NT_STATUS_EVENTLOG_FILE_CHANGED},
- {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
- NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
- {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
- NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
- {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
- NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
- {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
- NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
- {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
- {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
- {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
- {"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
- NT_STATUS_RESOURCE_LANG_NOT_FOUND},
- {"NT_STATUS_INSUFF_SERVER_RESOURCES",
- NT_STATUS_INSUFF_SERVER_RESOURCES},
- {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
- {"NT_STATUS_INVALID_ADDRESS_COMPONENT",
- NT_STATUS_INVALID_ADDRESS_COMPONENT},
- {"NT_STATUS_INVALID_ADDRESS_WILDCARD",
- NT_STATUS_INVALID_ADDRESS_WILDCARD},
- {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
- {"NT_STATUS_ADDRESS_ALREADY_EXISTS",
- NT_STATUS_ADDRESS_ALREADY_EXISTS},
- {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
- {"NT_STATUS_CONNECTION_DISCONNECTED",
- NT_STATUS_CONNECTION_DISCONNECTED},
- {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
- {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
- {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
- {"NT_STATUS_TRANSACTION_TIMED_OUT",
- NT_STATUS_TRANSACTION_TIMED_OUT},
- {"NT_STATUS_TRANSACTION_NO_RELEASE",
- NT_STATUS_TRANSACTION_NO_RELEASE},
- {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
- {"NT_STATUS_TRANSACTION_RESPONDED",
- NT_STATUS_TRANSACTION_RESPONDED},
- {"NT_STATUS_TRANSACTION_INVALID_ID",
- NT_STATUS_TRANSACTION_INVALID_ID},
- {"NT_STATUS_TRANSACTION_INVALID_TYPE",
- NT_STATUS_TRANSACTION_INVALID_TYPE},
- {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
- {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
- {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
- NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
- {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
- {"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
- NT_STATUS_SYSTEM_PROCESS_TERMINATED},
- {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
- {"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
- NT_STATUS_NO_BROWSER_SERVERS_FOUND},
- {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
- {"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
- NT_STATUS_DRIVER_CANCEL_TIMEOUT},
- {"NT_STATUS_REPLY_MESSAGE_MISMATCH",
- NT_STATUS_REPLY_MESSAGE_MISMATCH},
- {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
- {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
- NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
- {"NT_STATUS_LOST_WRITEBEHIND_DATA",
- NT_STATUS_LOST_WRITEBEHIND_DATA},
- {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
- NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
- {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
- {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
- {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
- {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
- {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
- {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
- {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
- {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
- {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
- {"NT_STATUS_RETRY", NT_STATUS_RETRY},
- {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
- {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
- {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
- {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
- {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
- {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
- NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
- {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
- {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
- {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
- {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
- {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
- NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
- {"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
- NT_STATUS_ADDRESS_NOT_ASSOCIATED},
- {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
- {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
- {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
- {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
- {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
- {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
- {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
- {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
- {"NT_STATUS_BAD_COMPRESSION_BUFFER",
- NT_STATUS_BAD_COMPRESSION_BUFFER},
- {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
- {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
- {"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
- NT_STATUS_TIMER_RESOLUTION_NOT_SET},
- {"NT_STATUS_CONNECTION_COUNT_LIMIT",
- NT_STATUS_CONNECTION_COUNT_LIMIT},
- {"NT_STATUS_LOGIN_TIME_RESTRICTION",
- NT_STATUS_LOGIN_TIME_RESTRICTION},
- {"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
- NT_STATUS_LOGIN_WKSTA_RESTRICTION},
- {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
- {"NT_STATUS_INSUFFICIENT_LOGON_INFO",
- NT_STATUS_INSUFFICIENT_LOGON_INFO},
- {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
- {"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
- NT_STATUS_BAD_SERVICE_ENTRYPOINT},
- {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
- {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
- {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
- {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
- {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
- {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
- {"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
- NT_STATUS_LICENSE_QUOTA_EXCEEDED},
- {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
- {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
- {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
- {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
- {"NT_STATUS_UNSUPPORTED_COMPRESSION",
- NT_STATUS_UNSUPPORTED_COMPRESSION},
- {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
- {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
- NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
- {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
- NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
- {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
- NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
- {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
- {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
- {"NT_STATUS_QUOTA_LIST_INCONSISTENT",
- NT_STATUS_QUOTA_LIST_INCONSISTENT},
- {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
- {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
- {"NT_STATUS_MORE_ENTRIES", NT_STATUS_MORE_ENTRIES},
- {"NT_STATUS_SOME_UNMAPPED", NT_STATUS_SOME_UNMAPPED},
- {NULL, 0}
-};
diff --git a/fs/cifs/nterr.h b/fs/cifs/nterr.h
deleted file mode 100644
index edd4741cab0a..000000000000
--- a/fs/cifs/nterr.h
+++ /dev/null
@@ -1,551 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NT error code constants
- Copyright (C) Andrew Tridgell 1992-2000
- Copyright (C) John H Terpstra 1996-2000
- Copyright (C) Luke Kenneth Casson Leighton 1996-2000
- Copyright (C) Paul Ashton 1998-2000
-
-*/
-
-
-
-#ifndef _NTERR_H
-#define _NTERR_H
-
-struct nt_err_code_struct {
- char *nt_errstr;
- __u32 nt_errcode;
-};
-
-extern const struct nt_err_code_struct nt_errs[];
-
-/* Win32 Status codes. */
-#define NT_STATUS_MORE_ENTRIES 0x0105
-#define NT_ERROR_INVALID_PARAMETER 0x0057
-#define NT_ERROR_INSUFFICIENT_BUFFER 0x007a
-#define NT_STATUS_1804 0x070c
-#define NT_STATUS_NOTIFY_ENUM_DIR 0x010c
-
-/*
- * Win32 Error codes extracted using a loop in smbclient then printing a netmon
- * sniff to a file.
- */
-
-#define NT_STATUS_OK 0x0000
-#define NT_STATUS_SOME_UNMAPPED 0x0107
-#define NT_STATUS_BUFFER_OVERFLOW 0x80000005
-#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
-#define NT_STATUS_MEDIA_CHANGED 0x8000001c
-#define NT_STATUS_END_OF_MEDIA 0x8000001e
-#define NT_STATUS_MEDIA_CHECK 0x80000020
-#define NT_STATUS_NO_DATA_DETECTED 0x8000001c
-#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d
-#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288
-#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288
-#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
-#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
-#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
-#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
-#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
-#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
-#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
-#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
-#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
-#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
-#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
-#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
-#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
-#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
-#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
-#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
-#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
-#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
-#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
-#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
-#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
-#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
-#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
-#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
-#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
-#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
-#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
-#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
-#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
-#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
-#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
-#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
-#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
-#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
-#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
-#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
-#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
-#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
-#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
-#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
-#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
-#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
-#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
-#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
-#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
-#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
-#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
-#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
-#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
-#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
-#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
-#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
-#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
-#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
-#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
-#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
-#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
-#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
-#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
-#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
-#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
-#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
-#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
-#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
-#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
-#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
-#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
-#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
-#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
-#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
-#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
-#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
-#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
-#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
-#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
-#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
-#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
-#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
-#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
-#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
-#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
-#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
-#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
-#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
-#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
-#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
-#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
-#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
-#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
-#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
-#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
-#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
-#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
-#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
-#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
-#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
-#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
-#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
-#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
-#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
-#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
-#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
-#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
-#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
-#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
-#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
-#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
-#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
-#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
-#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
-#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
-#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
-#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
-#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
-#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
-#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
-#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
-#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
-#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
-#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
-#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
-#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
-#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
-#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
-#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
-#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
-#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
-#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
-#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
-#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
-#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
-#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
-#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
-#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
-#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
-#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
-#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
-#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
-#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
-#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
-#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
-#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
-#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
-#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
-#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
-#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
-#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
-#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
-#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
-#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
-#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
-#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
-#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
-#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
-#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
-#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
-#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
-#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
-#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
-#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
-#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
-#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
-#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
-#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
-#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
-#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
-#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
-#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
-#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
-#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
-#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
-#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
-#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
-#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
-#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
-#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
-#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
-#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
-#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
-#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
-#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
-#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
-#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
-#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
-#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
-#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
-#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
-#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
-#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
-#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
-#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
-#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
-#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
-#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
-#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
-#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
-#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
-#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
-#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
-#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
-#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
-#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
-#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
-#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
-#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
-#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
-#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
-#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
-#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
-#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
-#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
-#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
-#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
-#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
-#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
-#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
-#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
-#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
-#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
-#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
-#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
-#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
-#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
-#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
-#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
-#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
-#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
-#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
-#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
-#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
-#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
-#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
-#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
-#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
-#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
-#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
-#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
-#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
-#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
-#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
-#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
-#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
-#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
-#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
-#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
-#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
-#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
-#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
-#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
-#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
-#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
-#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
-#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
-#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
-#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
-#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
-#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
-#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
-#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
-#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
-#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
-#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
-#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
-#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
-#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
-#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
-#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
-#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
-#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
-#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
-#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
-#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
-#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
-#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
-#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
-#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
-#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
-#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
-#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
-#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
-#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
-#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
-#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
-#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
-#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
-#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
-#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
-#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
-#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
-#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
-#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
-#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
-#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
-#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
-#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
-#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
-#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
-#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
-#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
-#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
-#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
-#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
-#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
-#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
-#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
-#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
-#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
-#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
-#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
-#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
-#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
-#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
-#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
-#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
-#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
-#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
-#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
-#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
-#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
-#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
-#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
-#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
-#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
-#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
-#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
-#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
-#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
-#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
-#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
-#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
-#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
-#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
-#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
-#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
-#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
-#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
-#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
-#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
-#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
-#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
-#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
-#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
-#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
-#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
-#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
-#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
-#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
-#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
-#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
-#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
-#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
-#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
-#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
-#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
-#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
-#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
-#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
-#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
-#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
-#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
-#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
-#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
-#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
-#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
-#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
-#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
-#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
-#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
-#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
-#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
-#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
-#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
-#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
-#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
-#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
-#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
-#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
-#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
-#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
-#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
-#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
-#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
-#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
-#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
-#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
-#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
-#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
-#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
-#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
-#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
-#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
-#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
-#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
-#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
-#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
-#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
-#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
-#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
-#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
-#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
-#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
-#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
-#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
-#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
-#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
-#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
-#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
-#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
-#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
-#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
-#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
-#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
-#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
-#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
-#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
-#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
-#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
-#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
-#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
-#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
-#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
-#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
-#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
-#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
-#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
-#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
-#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
-#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
-#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
-#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
-#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
-#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
-#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
-#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
-#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
-#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
-#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
-#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
-#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
-#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
-#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
-#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
-#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
-#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
-#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
-#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
-#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
-#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
-#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
-#define NT_STATUS_RETRY 0xC0000000 | 0x022d
-#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
-#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
-#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
-#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
-#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
-#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
-#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
-#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
-#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
-#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
-#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
-#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
-#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
-#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
-#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
-#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
-#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
-#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
-#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
-#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
-#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
-#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
-#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
-#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
-#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
-#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
-#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
-#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
-#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
-#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
-#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
-#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
-#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
-#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
-#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
-#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
-#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
-#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
-#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
-#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
-#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
-#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
-#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
-#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
-#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
-#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
-#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
-#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
-#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
-#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
-#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
-#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
-
-#endif /* _NTERR_H */
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
deleted file mode 100644
index 55758b9ec877..000000000000
--- a/fs/cifs/ntlmssp.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2002,2007
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#define NTLMSSP_SIGNATURE "NTLMSSP"
-/* Message Types */
-#define NtLmNegotiate cpu_to_le32(1)
-#define NtLmChallenge cpu_to_le32(2)
-#define NtLmAuthenticate cpu_to_le32(3)
-#define UnknownMessage cpu_to_le32(8)
-
-/* Negotiate Flags */
-#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */
-#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
-#define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */
-/* define reserved9 0x08 */
-#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */
-#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
-#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
-#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */
-/* defined reserved 8 0x0100 */
-#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
-#define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */
-#define NTLMSSP_ANONYMOUS 0x0800
-#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */
-#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
-#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */
-#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */
-#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
-#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
-#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
-#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/
-/* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */
-#define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000
-#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */
-#define NTLMSSP_REQUEST_NON_NT_KEY 0x400000
-#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
-/* #define reserved4 0x1000000 */
-#define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we only set for SMB2+ */
-/* #define reserved3 0x4000000 */
-/* #define reserved2 0x8000000 */
-/* #define reserved1 0x10000000 */
-#define NTLMSSP_NEGOTIATE_128 0x20000000
-#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
-#define NTLMSSP_NEGOTIATE_56 0x80000000
-
-/* Define AV Pair Field IDs */
-enum av_field_type {
- NTLMSSP_AV_EOL = 0,
- NTLMSSP_AV_NB_COMPUTER_NAME,
- NTLMSSP_AV_NB_DOMAIN_NAME,
- NTLMSSP_AV_DNS_COMPUTER_NAME,
- NTLMSSP_AV_DNS_DOMAIN_NAME,
- NTLMSSP_AV_DNS_TREE_NAME,
- NTLMSSP_AV_FLAGS,
- NTLMSSP_AV_TIMESTAMP,
- NTLMSSP_AV_RESTRICTION,
- NTLMSSP_AV_TARGET_NAME,
- NTLMSSP_AV_CHANNEL_BINDINGS
-};
-
-/* Although typedefs are not commonly used for structure definitions */
-/* in the Linux kernel, in this particular case they are useful */
-/* to more closely match the standards document for NTLMSSP from */
-/* OpenGroup and to make the code more closely match the standard in */
-/* appearance */
-
-typedef struct _SECURITY_BUFFER {
- __le16 Length;
- __le16 MaximumLength;
- __le32 BufferOffset; /* offset to buffer */
-} __attribute__((packed)) SECURITY_BUFFER;
-
-typedef struct _NEGOTIATE_MESSAGE {
- __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* NtLmNegotiate = 1 */
- __le32 NegotiateFlags;
- SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
- SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
- /* SECURITY_BUFFER for version info not present since we
- do not set the version is present flag */
- char DomainString[0];
- /* followed by WorkstationString */
-} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
-
-#define NTLMSSP_REVISION_W2K3 0x0F
-
-/* See MS-NLMP section 2.2.2.10 */
-struct ntlmssp_version {
- __u8 ProductMajorVersion;
- __u8 ProductMinorVersion;
- __le16 ProductBuild; /* we send the cifs.ko module version here */
- __u8 Reserved[3];
- __u8 NTLMRevisionCurrent; /* currently 0x0F */
-} __packed;
-
-/* see MS-NLMP section 2.2.1.1 */
-struct negotiate_message {
- __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* NtLmNegotiate = 1 */
- __le32 NegotiateFlags;
- SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
- SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
- struct ntlmssp_version Version;
- /* SECURITY_BUFFER */
- char DomainString[];
- /* followed by WorkstationString */
-} __packed;
-
-typedef struct _CHALLENGE_MESSAGE {
- __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* NtLmChallenge = 2 */
- SECURITY_BUFFER TargetName;
- __le32 NegotiateFlags;
- __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
- __u8 Reserved[8];
- SECURITY_BUFFER TargetInfoArray;
- /* SECURITY_BUFFER for version info not present since we
- do not set the version is present flag */
-} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
-
-typedef struct _AUTHENTICATE_MESSAGE {
- __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* NtLmsAuthenticate = 3 */
- SECURITY_BUFFER LmChallengeResponse;
- SECURITY_BUFFER NtChallengeResponse;
- SECURITY_BUFFER DomainName;
- SECURITY_BUFFER UserName;
- SECURITY_BUFFER WorkstationName;
- SECURITY_BUFFER SessionKey;
- __le32 NegotiateFlags;
- /* SECURITY_BUFFER for version info not present since we
- do not set the version is present flag */
- char UserString[0];
-} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
-
-/*
- * Size of the session key (crypto key encrypted with the password
- */
-
-int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses);
-int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp);
-int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer, u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp);
-int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
deleted file mode 100644
index 2d75ba5aaa8a..000000000000
--- a/fs/cifs/readdir.c
+++ /dev/null
@@ -1,1237 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Directory search handling
- *
- * Copyright (C) International Business Machines Corp., 2004, 2008
- * Copyright (C) Red Hat, Inc., 2011
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-#include <linux/fs.h>
-#include <linux/pagemap.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_unicode.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "cifsfs.h"
-#include "smb2proto.h"
-#include "fs_context.h"
-#include "cached_dir.h"
-
-/*
- * To be safe - for UCS to UTF-8 with strings loaded with the rare long
- * characters alloc more to account for such multibyte target UTF-8
- * characters.
- */
-#define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
-
-#ifdef CONFIG_CIFS_DEBUG2
-static void dump_cifs_file_struct(struct file *file, char *label)
-{
- struct cifsFileInfo *cf;
-
- if (file) {
- cf = file->private_data;
- if (cf == NULL) {
- cifs_dbg(FYI, "empty cifs private file data\n");
- return;
- }
- if (cf->invalidHandle)
- cifs_dbg(FYI, "Invalid handle\n");
- if (cf->srch_inf.endOfSearch)
- cifs_dbg(FYI, "end of search\n");
- if (cf->srch_inf.emptyDir)
- cifs_dbg(FYI, "empty dir\n");
- }
-}
-#else
-static inline void dump_cifs_file_struct(struct file *file, char *label)
-{
-}
-#endif /* DEBUG2 */
-
-/*
- * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT
- *
- * Find the dentry that matches "name". If there isn't one, create one. If it's
- * a negative dentry or the uniqueid or filetype(mode) changed,
- * then drop it and recreate it.
- */
-static void
-cifs_prime_dcache(struct dentry *parent, struct qstr *name,
- struct cifs_fattr *fattr)
-{
- struct dentry *dentry, *alias;
- struct inode *inode;
- struct super_block *sb = parent->d_sb;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
-
- cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
-
- dentry = d_hash_and_lookup(parent, name);
- if (!dentry) {
- /*
- * If we know that the inode will need to be revalidated
- * immediately, then don't create a new dentry for it.
- * We'll end up doing an on the wire call either way and
- * this spares us an invalidation.
- */
- if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
- return;
-retry:
- dentry = d_alloc_parallel(parent, name, &wq);
- }
- if (IS_ERR(dentry))
- return;
- if (!d_in_lookup(dentry)) {
- inode = d_inode(dentry);
- if (inode) {
- if (d_mountpoint(dentry)) {
- dput(dentry);
- return;
- }
- /*
- * If we're generating inode numbers, then we don't
- * want to clobber the existing one with the one that
- * the readdir code created.
- */
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
- fattr->cf_uniqueid = CIFS_I(inode)->uniqueid;
-
- /* update inode in place
- * if both i_ino and i_mode didn't change */
- if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid &&
- cifs_fattr_to_inode(inode, fattr) == 0) {
- dput(dentry);
- return;
- }
- }
- d_invalidate(dentry);
- dput(dentry);
- goto retry;
- } else {
- inode = cifs_iget(sb, fattr);
- if (!inode)
- inode = ERR_PTR(-ENOMEM);
- alias = d_splice_alias(inode, dentry);
- d_lookup_done(dentry);
- if (alias && !IS_ERR(alias))
- dput(alias);
- }
- dput(dentry);
-}
-
-static bool reparse_file_needs_reval(const struct cifs_fattr *fattr)
-{
- if (!(fattr->cf_cifsattrs & ATTR_REPARSE))
- return false;
- /*
- * The DFS tags should be only intepreted by server side as per
- * MS-FSCC 2.1.2.1, but let's include them anyway.
- *
- * Besides, if cf_cifstag is unset (0), then we still need it to be
- * revalidated to know exactly what reparse point it is.
- */
- switch (fattr->cf_cifstag) {
- case IO_REPARSE_TAG_DFS:
- case IO_REPARSE_TAG_DFSR:
- case IO_REPARSE_TAG_SYMLINK:
- case IO_REPARSE_TAG_NFS:
- case 0:
- return true;
- }
- return false;
-}
-
-static void
-cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
-{
- fattr->cf_uid = cifs_sb->ctx->linux_uid;
- fattr->cf_gid = cifs_sb->ctx->linux_gid;
-
- /*
- * The IO_REPARSE_TAG_LX_ tags originally were used by WSL but they
- * are preferred by the Linux client in some cases since, unlike
- * the NFS reparse tag (or EAs), they don't require an extra query
- * to determine which type of special file they represent.
- * TODO: go through all documented reparse tags to see if we can
- * reasonably map some of them to directories vs. files vs. symlinks
- */
- if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
- fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;
- fattr->cf_dtype = DT_DIR;
- } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_SYMLINK) {
- fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_LNK;
- } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_FIFO) {
- fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_FIFO;
- } else if (fattr->cf_cifstag == IO_REPARSE_TAG_AF_UNIX) {
- fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_SOCK;
- } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_CHR) {
- fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_CHR;
- } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_BLK) {
- fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_BLK;
- } else { /* TODO: should we mark some other reparse points (like DFSR) as directories? */
- fattr->cf_mode = S_IFREG | cifs_sb->ctx->file_mode;
- fattr->cf_dtype = DT_REG;
- }
-
- /*
- * We need to revalidate it further to make a decision about whether it
- * is a symbolic link, DFS referral or a reparse point with a direct
- * access like junctions, deduplicated files, NFS symlinks.
- */
- if (reparse_file_needs_reval(fattr))
- fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
-
- /* non-unix readdir doesn't provide nlink */
- fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
-
- if (fattr->cf_cifsattrs & ATTR_READONLY)
- fattr->cf_mode &= ~S_IWUGO;
-
- /*
- * We of course don't get ACL info in FIND_FIRST/NEXT results, so
- * mark it for revalidation so that "ls -l" will look right. It might
- * be super-slow, but if we don't do this then the ownership of files
- * may look wrong since the inodes may not have timed out by the time
- * "ls" does a stat() call on them.
- */
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
- (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID))
- fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
- fattr->cf_cifsattrs & ATTR_SYSTEM) {
- if (fattr->cf_eof == 0) {
- fattr->cf_mode &= ~S_IFMT;
- fattr->cf_mode |= S_IFIFO;
- fattr->cf_dtype = DT_FIFO;
- } else {
- /*
- * trying to get the type and mode via SFU can be slow,
- * so just call those regular files for now, and mark
- * for reval
- */
- fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
- }
- }
-}
-
-/* Fill a cifs_fattr struct with info from SMB_FIND_FILE_POSIX_INFO. */
-static void
-cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
- struct cifs_sb_info *cifs_sb)
-{
- struct smb2_posix_info_parsed parsed;
-
- posix_info_parse(info, NULL, &parsed);
-
- memset(fattr, 0, sizeof(*fattr));
- fattr->cf_uniqueid = le64_to_cpu(info->Inode);
- fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
- fattr->cf_eof = le64_to_cpu(info->EndOfFile);
-
- fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
- fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
- fattr->cf_ctime = cifs_NTtimeToUnix(info->CreationTime);
-
- fattr->cf_nlink = le32_to_cpu(info->HardLinks);
- fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
-
- /*
- * Since we set the inode type below we need to mask off
- * to avoid strange results if bits set above.
- * XXX: why not make server&client use the type bits?
- */
- fattr->cf_mode = le32_to_cpu(info->Mode) & ~S_IFMT;
-
- cifs_dbg(FYI, "posix fattr: dev %d, reparse %d, mode %o\n",
- le32_to_cpu(info->DeviceId),
- le32_to_cpu(info->ReparseTag),
- le32_to_cpu(info->Mode));
-
- if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
- fattr->cf_mode |= S_IFDIR;
- fattr->cf_dtype = DT_DIR;
- } else {
- /*
- * mark anything that is not a dir as regular
- * file. special files should have the REPARSE
- * attribute and will be marked as needing revaluation
- */
- fattr->cf_mode |= S_IFREG;
- fattr->cf_dtype = DT_REG;
- }
-
- if (reparse_file_needs_reval(fattr))
- fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
-
- sid_to_id(cifs_sb, &parsed.owner, fattr, SIDOWNER);
- sid_to_id(cifs_sb, &parsed.group, fattr, SIDGROUP);
-}
-
-static void __dir_info_to_fattr(struct cifs_fattr *fattr, const void *info)
-{
- const FILE_DIRECTORY_INFO *fi = info;
-
- memset(fattr, 0, sizeof(*fattr));
- fattr->cf_cifsattrs = le32_to_cpu(fi->ExtFileAttributes);
- fattr->cf_eof = le64_to_cpu(fi->EndOfFile);
- fattr->cf_bytes = le64_to_cpu(fi->AllocationSize);
- fattr->cf_createtime = le64_to_cpu(fi->CreationTime);
- fattr->cf_atime = cifs_NTtimeToUnix(fi->LastAccessTime);
- fattr->cf_ctime = cifs_NTtimeToUnix(fi->ChangeTime);
- fattr->cf_mtime = cifs_NTtimeToUnix(fi->LastWriteTime);
-}
-
-void
-cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
- struct cifs_sb_info *cifs_sb)
-{
- __dir_info_to_fattr(fattr, info);
- cifs_fill_common_info(fattr, cifs_sb);
-}
-
-static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr,
- SEARCH_ID_FULL_DIR_INFO *info,
- struct cifs_sb_info *cifs_sb)
-{
- __dir_info_to_fattr(fattr, info);
-
- /* See MS-FSCC 2.4.19 FileIdFullDirectoryInformation */
- if (fattr->cf_cifsattrs & ATTR_REPARSE)
- fattr->cf_cifstag = le32_to_cpu(info->EaSize);
- cifs_fill_common_info(fattr, cifs_sb);
-}
-
-static void
-cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
- struct cifs_sb_info *cifs_sb)
-{
- int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj;
-
- memset(fattr, 0, sizeof(*fattr));
- fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
- info->LastAccessTime, offset);
- fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
- info->LastWriteTime, offset);
- fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
- info->LastWriteTime, offset);
-
- fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
- fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
- fattr->cf_eof = le32_to_cpu(info->DataSize);
-
- cifs_fill_common_info(fattr, cifs_sb);
-}
-
-/* BB eventually need to add the following helper function to
- resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
- we try to do FindFirst on (NTFS) directory symlinks */
-/*
-int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
- unsigned int xid)
-{
- __u16 fid;
- int len;
- int oplock = 0;
- int rc;
- struct cifs_tcon *ptcon = cifs_sb_tcon(cifs_sb);
- char *tmpbuffer;
-
- rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
- OPEN_REPARSE_POINT, &fid, &oplock, NULL,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb);
- if (!rc) {
- tmpbuffer = kmalloc(maxpath);
- rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
- tmpbuffer,
- maxpath -1,
- fid,
- cifs_sb->local_nls);
- if (CIFSSMBClose(xid, ptcon, fid)) {
- cifs_dbg(FYI, "Error closing temporary reparsepoint open\n");
- }
- }
-}
- */
-
-static int
-_initiate_cifs_search(const unsigned int xid, struct file *file,
- const char *full_path)
-{
- __u16 search_flags;
- int rc = 0;
- struct cifsFileInfo *cifsFile;
- struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
- struct tcon_link *tlink = NULL;
- struct cifs_tcon *tcon;
- struct TCP_Server_Info *server;
-
- if (file->private_data == NULL) {
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
-
- cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
- if (cifsFile == NULL) {
- rc = -ENOMEM;
- goto error_exit;
- }
- spin_lock_init(&cifsFile->file_info_lock);
- file->private_data = cifsFile;
- cifsFile->tlink = cifs_get_tlink(tlink);
- tcon = tlink_tcon(tlink);
- } else {
- cifsFile = file->private_data;
- tcon = tlink_tcon(cifsFile->tlink);
- }
-
- server = tcon->ses->server;
-
- if (!server->ops->query_dir_first) {
- rc = -ENOSYS;
- goto error_exit;
- }
-
- cifsFile->invalidHandle = true;
- cifsFile->srch_inf.endOfSearch = false;
-
- cifs_dbg(FYI, "Full path: %s start at: %lld\n", full_path, file->f_pos);
-
-ffirst_retry:
- /* test for Unix extensions */
- /* but now check for them on the share/mount not on the SMB session */
- /* if (cap_unix(tcon->ses) { */
- if (tcon->unix_ext)
- cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
- else if (tcon->posix_extensions)
- cifsFile->srch_inf.info_level = SMB_FIND_FILE_POSIX_INFO;
- else if ((tcon->ses->capabilities &
- tcon->ses->server->vals->cap_nt_find) == 0) {
- cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
- } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
- } else /* not srvinos - BB fixme add check for backlevel? */ {
- cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
- }
-
- search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
- if (backup_cred(cifs_sb))
- search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
-
- rc = server->ops->query_dir_first(xid, tcon, full_path, cifs_sb,
- &cifsFile->fid, search_flags,
- &cifsFile->srch_inf);
-
- if (rc == 0)
- cifsFile->invalidHandle = false;
- /* BB add following call to handle readdir on new NTFS symlink errors
- else if STATUS_STOPPED_ON_SYMLINK
- call get_symlink_reparse_path and retry with new path */
- else if ((rc == -EOPNOTSUPP) &&
- (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
- goto ffirst_retry;
- }
-error_exit:
- cifs_put_tlink(tlink);
- return rc;
-}
-
-static int
-initiate_cifs_search(const unsigned int xid, struct file *file,
- const char *full_path)
-{
- int rc, retry_count = 0;
-
- do {
- rc = _initiate_cifs_search(xid, file, full_path);
- /*
- * If we don't have enough credits to start reading the
- * directory just try again after short wait.
- */
- if (rc != -EDEADLK)
- break;
-
- usleep_range(512, 2048);
- } while (retry_count++ < 5);
-
- return rc;
-}
-
-/* return length of unicode string in bytes */
-static int cifs_unicode_bytelen(const char *str)
-{
- int len;
- const __le16 *ustr = (const __le16 *)str;
-
- for (len = 0; len <= PATH_MAX; len++) {
- if (ustr[len] == 0)
- return len << 1;
- }
- cifs_dbg(FYI, "Unicode string longer than PATH_MAX found\n");
- return len << 1;
-}
-
-static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
-{
- char *new_entry;
- FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
-
- if (level == SMB_FIND_FILE_INFO_STANDARD) {
- FIND_FILE_STANDARD_INFO *pfData;
- pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
-
- new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
- pfData->FileNameLength;
- } else {
- u32 next_offset = le32_to_cpu(pDirInfo->NextEntryOffset);
-
- if (old_entry + next_offset < old_entry) {
- cifs_dbg(VFS, "Invalid offset %u\n", next_offset);
- return NULL;
- }
- new_entry = old_entry + next_offset;
- }
- cifs_dbg(FYI, "new entry %p old entry %p\n", new_entry, old_entry);
- /* validate that new_entry is not past end of SMB */
- if (new_entry >= end_of_smb) {
- cifs_dbg(VFS, "search entry %p began after end of SMB %p old entry %p\n",
- new_entry, end_of_smb, old_entry);
- return NULL;
- } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
- (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
- || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
- (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
- cifs_dbg(VFS, "search entry %p extends after end of SMB %p\n",
- new_entry, end_of_smb);
- return NULL;
- } else
- return new_entry;
-
-}
-
-struct cifs_dirent {
- const char *name;
- size_t namelen;
- u32 resume_key;
- u64 ino;
-};
-
-static void cifs_fill_dirent_posix(struct cifs_dirent *de,
- const struct smb2_posix_info *info)
-{
- struct smb2_posix_info_parsed parsed;
-
- /* payload should have already been checked at this point */
- if (posix_info_parse(info, NULL, &parsed) < 0) {
- cifs_dbg(VFS, "Invalid POSIX info payload\n");
- return;
- }
-
- de->name = parsed.name;
- de->namelen = parsed.name_len;
- de->resume_key = info->Ignored;
- de->ino = le64_to_cpu(info->Inode);
-}
-
-static void cifs_fill_dirent_unix(struct cifs_dirent *de,
- const FILE_UNIX_INFO *info, bool is_unicode)
-{
- de->name = &info->FileName[0];
- if (is_unicode)
- de->namelen = cifs_unicode_bytelen(de->name);
- else
- de->namelen = strnlen(de->name, PATH_MAX);
- de->resume_key = info->ResumeKey;
- de->ino = le64_to_cpu(info->basic.UniqueId);
-}
-
-static void cifs_fill_dirent_dir(struct cifs_dirent *de,
- const FILE_DIRECTORY_INFO *info)
-{
- de->name = &info->FileName[0];
- de->namelen = le32_to_cpu(info->FileNameLength);
- de->resume_key = info->FileIndex;
-}
-
-static void cifs_fill_dirent_full(struct cifs_dirent *de,
- const FILE_FULL_DIRECTORY_INFO *info)
-{
- de->name = &info->FileName[0];
- de->namelen = le32_to_cpu(info->FileNameLength);
- de->resume_key = info->FileIndex;
-}
-
-static void cifs_fill_dirent_search(struct cifs_dirent *de,
- const SEARCH_ID_FULL_DIR_INFO *info)
-{
- de->name = &info->FileName[0];
- de->namelen = le32_to_cpu(info->FileNameLength);
- de->resume_key = info->FileIndex;
- de->ino = le64_to_cpu(info->UniqueId);
-}
-
-static void cifs_fill_dirent_both(struct cifs_dirent *de,
- const FILE_BOTH_DIRECTORY_INFO *info)
-{
- de->name = &info->FileName[0];
- de->namelen = le32_to_cpu(info->FileNameLength);
- de->resume_key = info->FileIndex;
-}
-
-static void cifs_fill_dirent_std(struct cifs_dirent *de,
- const FIND_FILE_STANDARD_INFO *info)
-{
- de->name = &info->FileName[0];
- /* one byte length, no endianess conversion */
- de->namelen = info->FileNameLength;
- de->resume_key = info->ResumeKey;
-}
-
-static int cifs_fill_dirent(struct cifs_dirent *de, const void *info,
- u16 level, bool is_unicode)
-{
- memset(de, 0, sizeof(*de));
-
- switch (level) {
- case SMB_FIND_FILE_POSIX_INFO:
- cifs_fill_dirent_posix(de, info);
- break;
- case SMB_FIND_FILE_UNIX:
- cifs_fill_dirent_unix(de, info, is_unicode);
- break;
- case SMB_FIND_FILE_DIRECTORY_INFO:
- cifs_fill_dirent_dir(de, info);
- break;
- case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
- cifs_fill_dirent_full(de, info);
- break;
- case SMB_FIND_FILE_ID_FULL_DIR_INFO:
- cifs_fill_dirent_search(de, info);
- break;
- case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
- cifs_fill_dirent_both(de, info);
- break;
- case SMB_FIND_FILE_INFO_STANDARD:
- cifs_fill_dirent_std(de, info);
- break;
- default:
- cifs_dbg(FYI, "Unknown findfirst level %d\n", level);
- return -EINVAL;
- }
-
- return 0;
-}
-
-#define UNICODE_DOT cpu_to_le16(0x2e)
-
-/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
-static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode)
-{
- int rc = 0;
-
- if (!de->name)
- return 0;
-
- if (is_unicode) {
- __le16 *ufilename = (__le16 *)de->name;
- if (de->namelen == 2) {
- /* check for . */
- if (ufilename[0] == UNICODE_DOT)
- rc = 1;
- } else if (de->namelen == 4) {
- /* check for .. */
- if (ufilename[0] == UNICODE_DOT &&
- ufilename[1] == UNICODE_DOT)
- rc = 2;
- }
- } else /* ASCII */ {
- if (de->namelen == 1) {
- if (de->name[0] == '.')
- rc = 1;
- } else if (de->namelen == 2) {
- if (de->name[0] == '.' && de->name[1] == '.')
- rc = 2;
- }
- }
-
- return rc;
-}
-
-/* Check if directory that we are searching has changed so we can decide
- whether we can use the cached search results from the previous search */
-static int is_dir_changed(struct file *file)
-{
- struct inode *inode = file_inode(file);
- struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
-
- if (cifsInfo->time == 0)
- return 1; /* directory was changed, perhaps due to unlink */
- else
- return 0;
-
-}
-
-static int cifs_save_resume_key(const char *current_entry,
- struct cifsFileInfo *file_info)
-{
- struct cifs_dirent de;
- int rc;
-
- rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level,
- file_info->srch_inf.unicode);
- if (!rc) {
- file_info->srch_inf.presume_name = de.name;
- file_info->srch_inf.resume_name_len = de.namelen;
- file_info->srch_inf.resume_key = de.resume_key;
- }
- return rc;
-}
-
-/*
- * Find the corresponding entry in the search. Note that the SMB server returns
- * search entries for . and .. which complicates logic here if we choose to
- * parse for them and we do not assume that they are located in the findfirst
- * return buffer. We start counting in the buffer with entry 2 and increment for
- * every entry (do not increment for . or .. entry).
- */
-static int
-find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
- struct file *file, const char *full_path,
- char **current_entry, int *num_to_ret)
-{
- __u16 search_flags;
- int rc = 0;
- int pos_in_buf = 0;
- loff_t first_entry_in_buffer;
- loff_t index_to_find = pos;
- struct cifsFileInfo *cfile = file->private_data;
- struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
- struct TCP_Server_Info *server = tcon->ses->server;
- /* check if index in the buffer */
-
- if (!server->ops->query_dir_first || !server->ops->query_dir_next)
- return -ENOSYS;
-
- if ((cfile == NULL) || (current_entry == NULL) || (num_to_ret == NULL))
- return -ENOENT;
-
- *current_entry = NULL;
- first_entry_in_buffer = cfile->srch_inf.index_of_last_entry -
- cfile->srch_inf.entries_in_buffer;
-
- /*
- * If first entry in buf is zero then is first buffer
- * in search response data which means it is likely . and ..
- * will be in this buffer, although some servers do not return
- * . and .. for the root of a drive and for those we need
- * to start two entries earlier.
- */
-
- dump_cifs_file_struct(file, "In fce ");
- if (((index_to_find < cfile->srch_inf.index_of_last_entry) &&
- is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
- /* close and restart search */
- cifs_dbg(FYI, "search backing up - close and restart search\n");
- spin_lock(&cfile->file_info_lock);
- if (server->ops->dir_needs_close(cfile)) {
- cfile->invalidHandle = true;
- spin_unlock(&cfile->file_info_lock);
- if (server->ops->close_dir)
- server->ops->close_dir(xid, tcon, &cfile->fid);
- } else
- spin_unlock(&cfile->file_info_lock);
- if (cfile->srch_inf.ntwrk_buf_start) {
- cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n");
- if (cfile->srch_inf.smallBuf)
- cifs_small_buf_release(cfile->srch_inf.
- ntwrk_buf_start);
- else
- cifs_buf_release(cfile->srch_inf.
- ntwrk_buf_start);
- cfile->srch_inf.ntwrk_buf_start = NULL;
- }
- rc = initiate_cifs_search(xid, file, full_path);
- if (rc) {
- cifs_dbg(FYI, "error %d reinitiating a search on rewind\n",
- rc);
- return rc;
- }
- /* FindFirst/Next set last_entry to NULL on malformed reply */
- if (cfile->srch_inf.last_entry)
- cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
- }
-
- search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
- if (backup_cred(cifs_sb))
- search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
-
- while ((index_to_find >= cfile->srch_inf.index_of_last_entry) &&
- (rc == 0) && !cfile->srch_inf.endOfSearch) {
- cifs_dbg(FYI, "calling findnext2\n");
- rc = server->ops->query_dir_next(xid, tcon, &cfile->fid,
- search_flags,
- &cfile->srch_inf);
- /* FindFirst/Next set last_entry to NULL on malformed reply */
- if (cfile->srch_inf.last_entry)
- cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
- if (rc)
- return -ENOENT;
- }
- if (index_to_find < cfile->srch_inf.index_of_last_entry) {
- /* we found the buffer that contains the entry */
- /* scan and find it */
- int i;
- char *cur_ent;
- char *end_of_smb;
-
- if (cfile->srch_inf.ntwrk_buf_start == NULL) {
- cifs_dbg(VFS, "ntwrk_buf_start is NULL during readdir\n");
- return -EIO;
- }
-
- end_of_smb = cfile->srch_inf.ntwrk_buf_start +
- server->ops->calc_smb_size(
- cfile->srch_inf.ntwrk_buf_start);
-
- cur_ent = cfile->srch_inf.srch_entries_start;
- first_entry_in_buffer = cfile->srch_inf.index_of_last_entry
- - cfile->srch_inf.entries_in_buffer;
- pos_in_buf = index_to_find - first_entry_in_buffer;
- cifs_dbg(FYI, "found entry - pos_in_buf %d\n", pos_in_buf);
-
- for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) {
- /* go entry by entry figuring out which is first */
- cur_ent = nxt_dir_entry(cur_ent, end_of_smb,
- cfile->srch_inf.info_level);
- }
- if ((cur_ent == NULL) && (i < pos_in_buf)) {
- /* BB fixme - check if we should flag this error */
- cifs_dbg(VFS, "reached end of buf searching for pos in buf %d index to find %lld rc %d\n",
- pos_in_buf, index_to_find, rc);
- }
- rc = 0;
- *current_entry = cur_ent;
- } else {
- cifs_dbg(FYI, "index not in buffer - could not findnext into it\n");
- return 0;
- }
-
- if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) {
- cifs_dbg(FYI, "can not return entries pos_in_buf beyond last\n");
- *num_to_ret = 0;
- } else
- *num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf;
-
- return rc;
-}
-
-static bool emit_cached_dirents(struct cached_dirents *cde,
- struct dir_context *ctx)
-{
- struct cached_dirent *dirent;
- bool rc;
-
- list_for_each_entry(dirent, &cde->entries, entry) {
- /*
- * Skip all early entries prior to the current lseek()
- * position.
- */
- if (ctx->pos > dirent->pos)
- continue;
- /*
- * We recorded the current ->pos value for the dirent
- * when we stored it in the cache.
- * However, this sequence of ->pos values may have holes
- * in it, for example dot-dirs returned from the server
- * are suppressed.
- * Handle this bu forcing ctx->pos to be the same as the
- * ->pos of the current dirent we emit from the cache.
- * This means that when we emit these entries from the cache
- * we now emit them with the same ->pos value as in the
- * initial scan.
- */
- ctx->pos = dirent->pos;
- rc = dir_emit(ctx, dirent->name, dirent->namelen,
- dirent->fattr.cf_uniqueid,
- dirent->fattr.cf_dtype);
- if (!rc)
- return rc;
- ctx->pos++;
- }
- return true;
-}
-
-static void update_cached_dirents_count(struct cached_dirents *cde,
- struct dir_context *ctx)
-{
- if (cde->ctx != ctx)
- return;
- if (cde->is_valid || cde->is_failed)
- return;
-
- cde->pos++;
-}
-
-static void finished_cached_dirents_count(struct cached_dirents *cde,
- struct dir_context *ctx)
-{
- if (cde->ctx != ctx)
- return;
- if (cde->is_valid || cde->is_failed)
- return;
- if (ctx->pos != cde->pos)
- return;
-
- cde->is_valid = 1;
-}
-
-static void add_cached_dirent(struct cached_dirents *cde,
- struct dir_context *ctx,
- const char *name, int namelen,
- struct cifs_fattr *fattr)
-{
- struct cached_dirent *de;
-
- if (cde->ctx != ctx)
- return;
- if (cde->is_valid || cde->is_failed)
- return;
- if (ctx->pos != cde->pos) {
- cde->is_failed = 1;
- return;
- }
- de = kzalloc(sizeof(*de), GFP_ATOMIC);
- if (de == NULL) {
- cde->is_failed = 1;
- return;
- }
- de->namelen = namelen;
- de->name = kstrndup(name, namelen, GFP_ATOMIC);
- if (de->name == NULL) {
- kfree(de);
- cde->is_failed = 1;
- return;
- }
- de->pos = ctx->pos;
-
- memcpy(&de->fattr, fattr, sizeof(struct cifs_fattr));
-
- list_add_tail(&de->entry, &cde->entries);
-}
-
-static bool cifs_dir_emit(struct dir_context *ctx,
- const char *name, int namelen,
- struct cifs_fattr *fattr,
- struct cached_fid *cfid)
-{
- bool rc;
- ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
-
- rc = dir_emit(ctx, name, namelen, ino, fattr->cf_dtype);
- if (!rc)
- return rc;
-
- if (cfid) {
- mutex_lock(&cfid->dirents.de_mutex);
- add_cached_dirent(&cfid->dirents, ctx, name, namelen,
- fattr);
- mutex_unlock(&cfid->dirents.de_mutex);
- }
-
- return rc;
-}
-
-static int cifs_filldir(char *find_entry, struct file *file,
- struct dir_context *ctx,
- char *scratch_buf, unsigned int max_len,
- struct cached_fid *cfid)
-{
- struct cifsFileInfo *file_info = file->private_data;
- struct super_block *sb = file_inode(file)->i_sb;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifs_dirent de = { NULL, };
- struct cifs_fattr fattr;
- struct qstr name;
- int rc = 0;
-
- rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
- file_info->srch_inf.unicode);
- if (rc)
- return rc;
-
- if (de.namelen > max_len) {
- cifs_dbg(VFS, "bad search response length %zd past smb end\n",
- de.namelen);
- return -EINVAL;
- }
-
- /* skip . and .. since we added them first */
- if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
- return 0;
-
- if (file_info->srch_inf.unicode) {
- struct nls_table *nlt = cifs_sb->local_nls;
- int map_type;
-
- map_type = cifs_remap(cifs_sb);
- name.name = scratch_buf;
- name.len =
- cifs_from_utf16((char *)name.name, (__le16 *)de.name,
- UNICODE_NAME_MAX,
- min_t(size_t, de.namelen,
- (size_t)max_len), nlt, map_type);
- name.len -= nls_nullsize(nlt);
- } else {
- name.name = de.name;
- name.len = de.namelen;
- }
-
- switch (file_info->srch_inf.info_level) {
- case SMB_FIND_FILE_POSIX_INFO:
- cifs_posix_to_fattr(&fattr,
- (struct smb2_posix_info *)find_entry,
- cifs_sb);
- break;
- case SMB_FIND_FILE_UNIX:
- cifs_unix_basic_to_fattr(&fattr,
- &((FILE_UNIX_INFO *)find_entry)->basic,
- cifs_sb);
- if (S_ISLNK(fattr.cf_mode))
- fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
- break;
- case SMB_FIND_FILE_INFO_STANDARD:
- cifs_std_info_to_fattr(&fattr,
- (FIND_FILE_STANDARD_INFO *)find_entry,
- cifs_sb);
- break;
- case SMB_FIND_FILE_ID_FULL_DIR_INFO:
- cifs_fulldir_info_to_fattr(&fattr,
- (SEARCH_ID_FULL_DIR_INFO *)find_entry,
- cifs_sb);
- break;
- default:
- cifs_dir_info_to_fattr(&fattr,
- (FILE_DIRECTORY_INFO *)find_entry,
- cifs_sb);
- break;
- }
-
- if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
- fattr.cf_uniqueid = de.ino;
- } else {
- fattr.cf_uniqueid = iunique(sb, ROOT_I);
- cifs_autodisable_serverino(cifs_sb);
- }
-
- if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
- couldbe_mf_symlink(&fattr))
- /*
- * trying to get the type and mode can be slow,
- * so just call those regular files for now, and mark
- * for reval
- */
- fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
-
- cifs_prime_dcache(file_dentry(file), &name, &fattr);
-
- return !cifs_dir_emit(ctx, name.name, name.len,
- &fattr, cfid);
-}
-
-
-int cifs_readdir(struct file *file, struct dir_context *ctx)
-{
- int rc = 0;
- unsigned int xid;
- int i;
- struct tcon_link *tlink = NULL;
- struct cifs_tcon *tcon;
- struct cifsFileInfo *cifsFile;
- char *current_entry;
- int num_to_fill = 0;
- char *tmp_buf = NULL;
- char *end_of_smb;
- unsigned int max_len;
- const char *full_path;
- void *page = alloc_dentry_path();
- struct cached_fid *cfid = NULL;
- struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
-
- xid = get_xid();
-
- full_path = build_path_from_dentry(file_dentry(file), page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto rddir2_exit;
- }
-
- if (file->private_data == NULL) {
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- goto cache_not_found;
- tcon = tlink_tcon(tlink);
- } else {
- cifsFile = file->private_data;
- tcon = tlink_tcon(cifsFile->tlink);
- }
-
- rc = open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid);
- cifs_put_tlink(tlink);
- if (rc)
- goto cache_not_found;
-
- mutex_lock(&cfid->dirents.de_mutex);
- /*
- * If this was reading from the start of the directory
- * we need to initialize scanning and storing the
- * directory content.
- */
- if (ctx->pos == 0 && cfid->dirents.ctx == NULL) {
- cfid->dirents.ctx = ctx;
- cfid->dirents.pos = 2;
- }
- /*
- * If we already have the entire directory cached then
- * we can just serve the cache.
- */
- if (cfid->dirents.is_valid) {
- if (!dir_emit_dots(file, ctx)) {
- mutex_unlock(&cfid->dirents.de_mutex);
- goto rddir2_exit;
- }
- emit_cached_dirents(&cfid->dirents, ctx);
- mutex_unlock(&cfid->dirents.de_mutex);
- goto rddir2_exit;
- }
- mutex_unlock(&cfid->dirents.de_mutex);
-
- /* Drop the cache while calling initiate_cifs_search and
- * find_cifs_entry in case there will be reconnects during
- * query_directory.
- */
- close_cached_dir(cfid);
- cfid = NULL;
-
- cache_not_found:
- /*
- * Ensure FindFirst doesn't fail before doing filldir() for '.' and
- * '..'. Otherwise we won't be able to notify VFS in case of failure.
- */
- if (file->private_data == NULL) {
- rc = initiate_cifs_search(xid, file, full_path);
- cifs_dbg(FYI, "initiate cifs search rc %d\n", rc);
- if (rc)
- goto rddir2_exit;
- }
-
- if (!dir_emit_dots(file, ctx))
- goto rddir2_exit;
-
- /* 1) If search is active,
- is in current search buffer?
- if it before then restart search
- if after then keep searching till find it */
- cifsFile = file->private_data;
- if (cifsFile->srch_inf.endOfSearch) {
- if (cifsFile->srch_inf.emptyDir) {
- cifs_dbg(FYI, "End of search, empty dir\n");
- rc = 0;
- goto rddir2_exit;
- }
- } /* else {
- cifsFile->invalidHandle = true;
- tcon->ses->server->close(xid, tcon, &cifsFile->fid);
- } */
-
- tcon = tlink_tcon(cifsFile->tlink);
- rc = find_cifs_entry(xid, tcon, ctx->pos, file, full_path,
- ¤t_entry, &num_to_fill);
- open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid);
- if (rc) {
- cifs_dbg(FYI, "fce error %d\n", rc);
- goto rddir2_exit;
- } else if (current_entry != NULL) {
- cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
- } else {
- if (cfid) {
- mutex_lock(&cfid->dirents.de_mutex);
- finished_cached_dirents_count(&cfid->dirents, ctx);
- mutex_unlock(&cfid->dirents.de_mutex);
- }
- cifs_dbg(FYI, "Could not find entry\n");
- goto rddir2_exit;
- }
- cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
- num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
- max_len = tcon->ses->server->ops->calc_smb_size(
- cifsFile->srch_inf.ntwrk_buf_start);
- end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
-
- tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
- if (tmp_buf == NULL) {
- rc = -ENOMEM;
- goto rddir2_exit;
- }
-
- for (i = 0; i < num_to_fill; i++) {
- if (current_entry == NULL) {
- /* evaluate whether this case is an error */
- cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
- num_to_fill, i);
- break;
- }
- /*
- * if buggy server returns . and .. late do we want to
- * check for that here?
- */
- *tmp_buf = 0;
- rc = cifs_filldir(current_entry, file, ctx,
- tmp_buf, max_len, cfid);
- if (rc) {
- if (rc > 0)
- rc = 0;
- break;
- }
-
- ctx->pos++;
- if (cfid) {
- mutex_lock(&cfid->dirents.de_mutex);
- update_cached_dirents_count(&cfid->dirents, ctx);
- mutex_unlock(&cfid->dirents.de_mutex);
- }
-
- if (ctx->pos ==
- cifsFile->srch_inf.index_of_last_entry) {
- cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
- ctx->pos, tmp_buf);
- cifs_save_resume_key(current_entry, cifsFile);
- break;
- }
- current_entry =
- nxt_dir_entry(current_entry, end_of_smb,
- cifsFile->srch_inf.info_level);
- }
- kfree(tmp_buf);
-
-rddir2_exit:
- if (cfid)
- close_cached_dir(cfid);
- free_dentry_path(page);
- free_xid(xid);
- return rc;
-}
diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
deleted file mode 100644
index ae1d025da294..000000000000
--- a/fs/cifs/rfc1002pdu.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Protocol Data Unit definitions for RFC 1001/1002 support
- *
- * Copyright (c) International Business Machines Corp., 2004
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
-
- /* RFC 1002 session packet types */
-#define RFC1002_SESSION_MESSAGE 0x00
-#define RFC1002_SESSION_REQUEST 0x81
-#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
-#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
-#define RFC1002_RETARGET_SESSION_RESPONSE 0x84
-#define RFC1002_SESSION_KEEP_ALIVE 0x85
-
- /* RFC 1002 flags (only one defined */
-#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
-
-struct rfc1002_session_packet {
- __u8 type;
- __u8 flags;
- __u16 length;
- union {
- struct {
- __u8 called_len;
- __u8 called_name[32];
- __u8 scope1; /* null */
- __u8 calling_len;
- __u8 calling_name[32];
- __u8 scope2; /* null */
- } __attribute__((packed)) session_req;
- struct {
- __u32 retarget_ip_addr;
- __u16 port;
- } __attribute__((packed)) retarget_resp;
- __u8 neg_ses_resp_error_code;
- /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
- SESSION_KEEP_ALIVE packet also does not include a trailer.
- Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
- } __attribute__((packed)) trailer;
-} __attribute__((packed));
-
-/* Negative Session Response error codes */
-#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
-#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
-#define RFC1002_NOT_PRESENT 0x82 /* called name not present */
-#define RFC1002_INSUFFICIENT_RESOURCE 0x83
-#define RFC1002_UNSPECIFIED_ERROR 0x8F
-
-/* RFC 1002 Datagram service packets are not defined here as they
-are not needed for the network filesystem client unless we plan on
-implementing broadcast resolution of the server ip address (from
-server netbios name). Currently server names are resolved only via DNS
-(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
-
-#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
deleted file mode 100644
index 81be17845072..000000000000
--- a/fs/cifs/sess.c
+++ /dev/null
@@ -1,1858 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * SMB/CIFS session setup handling routines
- *
- * Copyright (c) International Business Machines Corp., 2006, 2009
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_unicode.h"
-#include "cifs_debug.h"
-#include "ntlmssp.h"
-#include "nterr.h"
-#include <linux/utsname.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-#include "cifsfs.h"
-#include "cifs_spnego.h"
-#include "smb2proto.h"
-#include "fs_context.h"
-
-static int
-cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
- struct cifs_server_iface *iface);
-
-bool
-is_server_using_iface(struct TCP_Server_Info *server,
- struct cifs_server_iface *iface)
-{
- struct sockaddr_in *i4 = (struct sockaddr_in *)&iface->sockaddr;
- struct sockaddr_in6 *i6 = (struct sockaddr_in6 *)&iface->sockaddr;
- struct sockaddr_in *s4 = (struct sockaddr_in *)&server->dstaddr;
- struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&server->dstaddr;
-
- if (server->dstaddr.ss_family != iface->sockaddr.ss_family)
- return false;
- if (server->dstaddr.ss_family == AF_INET) {
- if (s4->sin_addr.s_addr != i4->sin_addr.s_addr)
- return false;
- } else if (server->dstaddr.ss_family == AF_INET6) {
- if (memcmp(&s6->sin6_addr, &i6->sin6_addr,
- sizeof(i6->sin6_addr)) != 0)
- return false;
- } else {
- /* unknown family.. */
- return false;
- }
- return true;
-}
-
-bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
-{
- int i;
-
- spin_lock(&ses->chan_lock);
- for (i = 0; i < ses->chan_count; i++) {
- if (ses->chans[i].iface == iface) {
- spin_unlock(&ses->chan_lock);
- return true;
- }
- }
- spin_unlock(&ses->chan_lock);
- return false;
-}
-
-/* channel helper functions. assumed that chan_lock is held by caller. */
-
-unsigned int
-cifs_ses_get_chan_index(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- unsigned int i;
-
- for (i = 0; i < ses->chan_count; i++) {
- if (ses->chans[i].server == server)
- return i;
- }
-
- /* If we didn't find the channel, it is likely a bug */
- if (server)
- cifs_dbg(VFS, "unable to get chan index for server: 0x%llx",
- server->conn_id);
- WARN_ON(1);
- return 0;
-}
-
-void
-cifs_chan_set_in_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
-
- ses->chans[chan_index].in_reconnect = true;
-}
-
-void
-cifs_chan_clear_in_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
-
- ses->chans[chan_index].in_reconnect = false;
-}
-
-bool
-cifs_chan_in_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
-
- return CIFS_CHAN_IN_RECONNECT(ses, chan_index);
-}
-
-void
-cifs_chan_set_need_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
-
- set_bit(chan_index, &ses->chans_need_reconnect);
- cifs_dbg(FYI, "Set reconnect bitmask for chan %u; now 0x%lx\n",
- chan_index, ses->chans_need_reconnect);
-}
-
-void
-cifs_chan_clear_need_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
-
- clear_bit(chan_index, &ses->chans_need_reconnect);
- cifs_dbg(FYI, "Cleared reconnect bitmask for chan %u; now 0x%lx\n",
- chan_index, ses->chans_need_reconnect);
-}
-
-bool
-cifs_chan_needs_reconnect(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
-
- return CIFS_CHAN_NEEDS_RECONNECT(ses, chan_index);
-}
-
-bool
-cifs_chan_is_iface_active(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
-
- return ses->chans[chan_index].iface &&
- ses->chans[chan_index].iface->is_active;
-}
-
-/* returns number of channels added */
-int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
-{
- struct TCP_Server_Info *server = ses->server;
- int old_chan_count, new_chan_count;
- int left;
- int rc = 0;
- int tries = 0;
- struct cifs_server_iface *iface = NULL, *niface = NULL;
-
- spin_lock(&ses->chan_lock);
-
- new_chan_count = old_chan_count = ses->chan_count;
- left = ses->chan_max - ses->chan_count;
-
- if (left <= 0) {
- spin_unlock(&ses->chan_lock);
- cifs_dbg(FYI,
- "ses already at max_channels (%zu), nothing to open\n",
- ses->chan_max);
- return 0;
- }
-
- if (server->dialect < SMB30_PROT_ID) {
- spin_unlock(&ses->chan_lock);
- cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
- return 0;
- }
-
- if (!(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
- ses->chan_max = 1;
- spin_unlock(&ses->chan_lock);
- cifs_server_dbg(VFS, "no multichannel support\n");
- return 0;
- }
- spin_unlock(&ses->chan_lock);
-
- /*
- * Keep connecting to same, fastest, iface for all channels as
- * long as its RSS. Try next fastest one if not RSS or channel
- * creation fails.
- */
- spin_lock(&ses->iface_lock);
- iface = list_first_entry(&ses->iface_list, struct cifs_server_iface,
- iface_head);
- spin_unlock(&ses->iface_lock);
-
- while (left > 0) {
-
- tries++;
- if (tries > 3*ses->chan_max) {
- cifs_dbg(FYI, "too many channel open attempts (%d channels left to open)\n",
- left);
- break;
- }
-
- spin_lock(&ses->iface_lock);
- if (!ses->iface_count) {
- spin_unlock(&ses->iface_lock);
- break;
- }
-
- list_for_each_entry_safe_from(iface, niface, &ses->iface_list,
- iface_head) {
- /* skip ifaces that are unusable */
- if (!iface->is_active ||
- (is_ses_using_iface(ses, iface) &&
- !iface->rss_capable)) {
- continue;
- }
-
- /* take ref before unlock */
- kref_get(&iface->refcount);
-
- spin_unlock(&ses->iface_lock);
- rc = cifs_ses_add_channel(cifs_sb, ses, iface);
- spin_lock(&ses->iface_lock);
-
- if (rc) {
- cifs_dbg(VFS, "failed to open extra channel on iface:%pIS rc=%d\n",
- &iface->sockaddr,
- rc);
- kref_put(&iface->refcount, release_iface);
- continue;
- }
-
- cifs_dbg(FYI, "successfully opened new channel on iface:%pIS\n",
- &iface->sockaddr);
- break;
- }
- spin_unlock(&ses->iface_lock);
-
- left--;
- new_chan_count++;
- }
-
- return new_chan_count - old_chan_count;
-}
-
-/*
- * update the iface for the channel if necessary.
- * will return 0 when iface is updated, 1 if removed, 2 otherwise
- * Must be called with chan_lock held.
- */
-int
-cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
-{
- unsigned int chan_index;
- struct cifs_server_iface *iface = NULL;
- struct cifs_server_iface *old_iface = NULL;
- int rc = 0;
-
- spin_lock(&ses->chan_lock);
- chan_index = cifs_ses_get_chan_index(ses, server);
- if (!chan_index) {
- spin_unlock(&ses->chan_lock);
- return 0;
- }
-
- if (ses->chans[chan_index].iface) {
- old_iface = ses->chans[chan_index].iface;
- if (old_iface->is_active) {
- spin_unlock(&ses->chan_lock);
- return 1;
- }
- }
- spin_unlock(&ses->chan_lock);
-
- spin_lock(&ses->iface_lock);
- /* then look for a new one */
- list_for_each_entry(iface, &ses->iface_list, iface_head) {
- if (!iface->is_active ||
- (is_ses_using_iface(ses, iface) &&
- !iface->rss_capable)) {
- continue;
- }
- kref_get(&iface->refcount);
- break;
- }
-
- if (list_entry_is_head(iface, &ses->iface_list, iface_head)) {
- rc = 1;
- iface = NULL;
- cifs_dbg(FYI, "unable to find a suitable iface\n");
- }
-
- /* now drop the ref to the current iface */
- if (old_iface && iface) {
- cifs_dbg(FYI, "replacing iface: %pIS with %pIS\n",
- &old_iface->sockaddr,
- &iface->sockaddr);
- kref_put(&old_iface->refcount, release_iface);
- } else if (old_iface) {
- cifs_dbg(FYI, "releasing ref to iface: %pIS\n",
- &old_iface->sockaddr);
- kref_put(&old_iface->refcount, release_iface);
- } else {
- WARN_ON(!iface);
- cifs_dbg(FYI, "adding new iface: %pIS\n", &iface->sockaddr);
- }
- spin_unlock(&ses->iface_lock);
-
- spin_lock(&ses->chan_lock);
- chan_index = cifs_ses_get_chan_index(ses, server);
- ses->chans[chan_index].iface = iface;
-
- /* No iface is found. if secondary chan, drop connection */
- if (!iface && CIFS_SERVER_IS_CHAN(server))
- ses->chans[chan_index].server = NULL;
-
- spin_unlock(&ses->chan_lock);
-
- if (!iface && CIFS_SERVER_IS_CHAN(server))
- cifs_put_tcp_session(server, false);
-
- return rc;
-}
-
-/*
- * If server is a channel of ses, return the corresponding enclosing
- * cifs_chan otherwise return NULL.
- */
-struct cifs_chan *
-cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server)
-{
- int i;
-
- spin_lock(&ses->chan_lock);
- for (i = 0; i < ses->chan_count; i++) {
- if (ses->chans[i].server == server) {
- spin_unlock(&ses->chan_lock);
- return &ses->chans[i];
- }
- }
- spin_unlock(&ses->chan_lock);
- return NULL;
-}
-
-static int
-cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
- struct cifs_server_iface *iface)
-{
- struct TCP_Server_Info *chan_server;
- struct cifs_chan *chan;
- struct smb3_fs_context ctx = {NULL};
- static const char unc_fmt[] = "\\%s\\foo";
- char unc[sizeof(unc_fmt)+SERVER_NAME_LEN_WITH_NULL] = {0};
- struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
- struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
- int rc;
- unsigned int xid = get_xid();
-
- if (iface->sockaddr.ss_family == AF_INET)
- cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI4)\n",
- ses, iface->speed, iface->rdma_capable ? "yes" : "no",
- &ipv4->sin_addr);
- else
- cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI6)\n",
- ses, iface->speed, iface->rdma_capable ? "yes" : "no",
- &ipv6->sin6_addr);
-
- /*
- * Setup a ctx with mostly the same info as the existing
- * session and overwrite it with the requested iface data.
- *
- * We need to setup at least the fields used for negprot and
- * sesssetup.
- *
- * We only need the ctx here, so we can reuse memory from
- * the session and server without caring about memory
- * management.
- */
-
- /* Always make new connection for now (TODO?) */
- ctx.nosharesock = true;
-
- /* Auth */
- ctx.domainauto = ses->domainAuto;
- ctx.domainname = ses->domainName;
-
- /* no hostname for extra channels */
- ctx.server_hostname = "";
-
- ctx.username = ses->user_name;
- ctx.password = ses->password;
- ctx.sectype = ses->sectype;
- ctx.sign = ses->sign;
-
- /* UNC and paths */
- /* XXX: Use ses->server->hostname? */
- sprintf(unc, unc_fmt, ses->ip_addr);
- ctx.UNC = unc;
- ctx.prepath = "";
-
- /* Reuse same version as master connection */
- ctx.vals = ses->server->vals;
- ctx.ops = ses->server->ops;
-
- ctx.noblocksnd = ses->server->noblocksnd;
- ctx.noautotune = ses->server->noautotune;
- ctx.sockopt_tcp_nodelay = ses->server->tcp_nodelay;
- ctx.echo_interval = ses->server->echo_interval / HZ;
- ctx.max_credits = ses->server->max_credits;
-
- /*
- * This will be used for encoding/decoding user/domain/pw
- * during sess setup auth.
- */
- ctx.local_nls = cifs_sb->local_nls;
-
- /* Use RDMA if possible */
- ctx.rdma = iface->rdma_capable;
- memcpy(&ctx.dstaddr, &iface->sockaddr, sizeof(struct sockaddr_storage));
-
- /* reuse master con client guid */
- memcpy(&ctx.client_guid, ses->server->client_guid,
- SMB2_CLIENT_GUID_SIZE);
- ctx.use_client_guid = true;
-
- chan_server = cifs_get_tcp_session(&ctx, ses->server);
-
- spin_lock(&ses->chan_lock);
- chan = &ses->chans[ses->chan_count];
- chan->server = chan_server;
- if (IS_ERR(chan->server)) {
- rc = PTR_ERR(chan->server);
- chan->server = NULL;
- spin_unlock(&ses->chan_lock);
- goto out;
- }
- chan->iface = iface;
- ses->chan_count++;
- atomic_set(&ses->chan_seq, 0);
-
- /* Mark this channel as needing connect/setup */
- cifs_chan_set_need_reconnect(ses, chan->server);
-
- spin_unlock(&ses->chan_lock);
-
- mutex_lock(&ses->session_mutex);
- /*
- * We need to allocate the server crypto now as we will need
- * to sign packets before we generate the channel signing key
- * (we sign with the session key)
- */
- rc = smb311_crypto_shash_allocate(chan->server);
- if (rc) {
- cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
- mutex_unlock(&ses->session_mutex);
- goto out;
- }
-
- rc = cifs_negotiate_protocol(xid, ses, chan->server);
- if (!rc)
- rc = cifs_setup_session(xid, ses, chan->server, cifs_sb->local_nls);
-
- mutex_unlock(&ses->session_mutex);
-
-out:
- if (rc && chan->server) {
- /*
- * we should avoid race with these delayed works before we
- * remove this channel
- */
- cancel_delayed_work_sync(&chan->server->echo);
- cancel_delayed_work_sync(&chan->server->resolve);
- cancel_delayed_work_sync(&chan->server->reconnect);
-
- spin_lock(&ses->chan_lock);
- /* we rely on all bits beyond chan_count to be clear */
- cifs_chan_clear_need_reconnect(ses, chan->server);
- ses->chan_count--;
- /*
- * chan_count should never reach 0 as at least the primary
- * channel is always allocated
- */
- WARN_ON(ses->chan_count < 1);
- spin_unlock(&ses->chan_lock);
-
- cifs_put_tcp_session(chan->server, 0);
- }
-
- free_xid(xid);
- return rc;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-static __u32 cifs_ssetup_hdr(struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- SESSION_SETUP_ANDX *pSMB)
-{
- __u32 capabilities = 0;
-
- /* init fields common to all four types of SessSetup */
- /* Note that offsets for first seven fields in req struct are same */
- /* in CIFS Specs so does not matter which of 3 forms of struct */
- /* that we use in next few lines */
- /* Note that header is initialized to zero in header_assemble */
- pSMB->req.AndXCommand = 0xFF;
- pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32,
- CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
- USHRT_MAX));
- pSMB->req.MaxMpxCount = cpu_to_le16(server->maxReq);
- pSMB->req.VcNumber = cpu_to_le16(1);
-
- /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
-
- /* BB verify whether signing required on neg or just on auth frame
- (and NTLM case) */
-
- capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
- CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
-
- if (server->sign)
- pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- if (ses->capabilities & CAP_UNICODE) {
- pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
- capabilities |= CAP_UNICODE;
- }
- if (ses->capabilities & CAP_STATUS32) {
- pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
- capabilities |= CAP_STATUS32;
- }
- if (ses->capabilities & CAP_DFS) {
- pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
- capabilities |= CAP_DFS;
- }
- if (ses->capabilities & CAP_UNIX)
- capabilities |= CAP_UNIX;
-
- return capabilities;
-}
-
-static void
-unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
-{
- char *bcc_ptr = *pbcc_area;
- int bytes_ret = 0;
-
- /* Copy OS version */
- bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
- nls_cp);
- bcc_ptr += 2 * bytes_ret;
- bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
- 32, nls_cp);
- bcc_ptr += 2 * bytes_ret;
- bcc_ptr += 2; /* trailing null */
-
- bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
- 32, nls_cp);
- bcc_ptr += 2 * bytes_ret;
- bcc_ptr += 2; /* trailing null */
-
- *pbcc_area = bcc_ptr;
-}
-
-static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
- const struct nls_table *nls_cp)
-{
- char *bcc_ptr = *pbcc_area;
- int bytes_ret = 0;
-
- /* copy domain */
- if (ses->domainName == NULL) {
- /* Sending null domain better than using a bogus domain name (as
- we did briefly in 2.6.18) since server will use its default */
- *bcc_ptr = 0;
- *(bcc_ptr+1) = 0;
- bytes_ret = 0;
- } else
- bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
- CIFS_MAX_DOMAINNAME_LEN, nls_cp);
- bcc_ptr += 2 * bytes_ret;
- bcc_ptr += 2; /* account for null terminator */
-
- *pbcc_area = bcc_ptr;
-}
-
-static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
- const struct nls_table *nls_cp)
-{
- char *bcc_ptr = *pbcc_area;
- int bytes_ret = 0;
-
- /* BB FIXME add check that strings total less
- than 335 or will need to send them as arrays */
-
- /* copy user */
- if (ses->user_name == NULL) {
- /* null user mount */
- *bcc_ptr = 0;
- *(bcc_ptr+1) = 0;
- } else {
- bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
- CIFS_MAX_USERNAME_LEN, nls_cp);
- }
- bcc_ptr += 2 * bytes_ret;
- bcc_ptr += 2; /* account for null termination */
-
- unicode_domain_string(&bcc_ptr, ses, nls_cp);
- unicode_oslm_strings(&bcc_ptr, nls_cp);
-
- *pbcc_area = bcc_ptr;
-}
-
-static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
- const struct nls_table *nls_cp)
-{
- char *bcc_ptr = *pbcc_area;
- int len;
-
- /* copy user */
- /* BB what about null user mounts - check that we do this BB */
- /* copy user */
- if (ses->user_name != NULL) {
- len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
- if (WARN_ON_ONCE(len < 0))
- len = CIFS_MAX_USERNAME_LEN - 1;
- bcc_ptr += len;
- }
- /* else null user mount */
- *bcc_ptr = 0;
- bcc_ptr++; /* account for null termination */
-
- /* copy domain */
- if (ses->domainName != NULL) {
- len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
- if (WARN_ON_ONCE(len < 0))
- len = CIFS_MAX_DOMAINNAME_LEN - 1;
- bcc_ptr += len;
- } /* else we will send a null domain name
- so the server will default to its own domain */
- *bcc_ptr = 0;
- bcc_ptr++;
-
- /* BB check for overflow here */
-
- strcpy(bcc_ptr, "Linux version ");
- bcc_ptr += strlen("Linux version ");
- strcpy(bcc_ptr, init_utsname()->release);
- bcc_ptr += strlen(init_utsname()->release) + 1;
-
- strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
- bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
-
- *pbcc_area = bcc_ptr;
-}
-
-static void
-decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
- const struct nls_table *nls_cp)
-{
- int len;
- char *data = *pbcc_area;
-
- cifs_dbg(FYI, "bleft %d\n", bleft);
-
- kfree(ses->serverOS);
- ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
- cifs_dbg(FYI, "serverOS=%s\n", ses->serverOS);
- len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
- data += len;
- bleft -= len;
- if (bleft <= 0)
- return;
-
- kfree(ses->serverNOS);
- ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
- cifs_dbg(FYI, "serverNOS=%s\n", ses->serverNOS);
- len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
- data += len;
- bleft -= len;
- if (bleft <= 0)
- return;
-
- kfree(ses->serverDomain);
- ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
- cifs_dbg(FYI, "serverDomain=%s\n", ses->serverDomain);
-
- return;
-}
-
-static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
- struct cifs_ses *ses,
- const struct nls_table *nls_cp)
-{
- int len;
- char *bcc_ptr = *pbcc_area;
-
- cifs_dbg(FYI, "decode sessetup ascii. bleft %d\n", bleft);
-
- len = strnlen(bcc_ptr, bleft);
- if (len >= bleft)
- return;
-
- kfree(ses->serverOS);
-
- ses->serverOS = kmalloc(len + 1, GFP_KERNEL);
- if (ses->serverOS) {
- memcpy(ses->serverOS, bcc_ptr, len);
- ses->serverOS[len] = 0;
- if (strncmp(ses->serverOS, "OS/2", 4) == 0)
- cifs_dbg(FYI, "OS/2 server\n");
- }
-
- bcc_ptr += len + 1;
- bleft -= len + 1;
-
- len = strnlen(bcc_ptr, bleft);
- if (len >= bleft)
- return;
-
- kfree(ses->serverNOS);
-
- ses->serverNOS = kmalloc(len + 1, GFP_KERNEL);
- if (ses->serverNOS) {
- memcpy(ses->serverNOS, bcc_ptr, len);
- ses->serverNOS[len] = 0;
- }
-
- bcc_ptr += len + 1;
- bleft -= len + 1;
-
- len = strnlen(bcc_ptr, bleft);
- if (len > bleft)
- return;
-
- /* No domain field in LANMAN case. Domain is
- returned by old servers in the SMB negprot response */
- /* BB For newer servers which do not support Unicode,
- but thus do return domain here we could add parsing
- for it later, but it is not very important */
- cifs_dbg(FYI, "ascii: bytes left %d\n", bleft);
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
-
-int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
- struct cifs_ses *ses)
-{
- unsigned int tioffset; /* challenge message target info area */
- unsigned int tilen; /* challenge message target info area length */
- CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
- __u32 server_flags;
-
- if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
- cifs_dbg(VFS, "challenge blob len %d too small\n", blob_len);
- return -EINVAL;
- }
-
- if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
- cifs_dbg(VFS, "blob signature incorrect %s\n",
- pblob->Signature);
- return -EINVAL;
- }
- if (pblob->MessageType != NtLmChallenge) {
- cifs_dbg(VFS, "Incorrect message type %d\n",
- pblob->MessageType);
- return -EINVAL;
- }
-
- server_flags = le32_to_cpu(pblob->NegotiateFlags);
- cifs_dbg(FYI, "%s: negotiate=0x%08x challenge=0x%08x\n", __func__,
- ses->ntlmssp->client_flags, server_flags);
-
- if ((ses->ntlmssp->client_flags & (NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN)) &&
- (!(server_flags & NTLMSSP_NEGOTIATE_56) && !(server_flags & NTLMSSP_NEGOTIATE_128))) {
- cifs_dbg(VFS, "%s: requested signing/encryption but server did not return either 56-bit or 128-bit session key size\n",
- __func__);
- return -EINVAL;
- }
- if (!(server_flags & NTLMSSP_NEGOTIATE_NTLM) && !(server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) {
- cifs_dbg(VFS, "%s: server does not seem to support either NTLMv1 or NTLMv2\n", __func__);
- return -EINVAL;
- }
- if (ses->server->sign && !(server_flags & NTLMSSP_NEGOTIATE_SIGN)) {
- cifs_dbg(VFS, "%s: forced packet signing but server does not seem to support it\n",
- __func__);
- return -EOPNOTSUPP;
- }
- if ((ses->ntlmssp->client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
- !(server_flags & NTLMSSP_NEGOTIATE_KEY_XCH))
- pr_warn_once("%s: authentication has been weakened as server does not support key exchange\n",
- __func__);
-
- ses->ntlmssp->server_flags = server_flags;
-
- memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
- /* In particular we can examine sign flags */
- /* BB spec says that if AvId field of MsvAvTimestamp is populated then
- we must set the MIC field of the AUTHENTICATE_MESSAGE */
-
- tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
- tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
- if (tioffset > blob_len || tioffset + tilen > blob_len) {
- cifs_dbg(VFS, "tioffset + tilen too high %u + %u\n",
- tioffset, tilen);
- return -EINVAL;
- }
- if (tilen) {
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen,
- GFP_KERNEL);
- if (!ses->auth_key.response) {
- cifs_dbg(VFS, "Challenge target info alloc failure\n");
- return -ENOMEM;
- }
- ses->auth_key.len = tilen;
- }
-
- return 0;
-}
-
-static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size)
-{
- int sz = base_size + ses->auth_key.len
- - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
-
- if (ses->domainName)
- sz += sizeof(__le16) * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
- else
- sz += sizeof(__le16);
-
- if (ses->user_name)
- sz += sizeof(__le16) * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
- else
- sz += sizeof(__le16);
-
- if (ses->workstation_name[0])
- sz += sizeof(__le16) * strnlen(ses->workstation_name,
- ntlmssp_workstation_name_size(ses));
- else
- sz += sizeof(__le16);
-
- return sz;
-}
-
-static inline void cifs_security_buffer_from_str(SECURITY_BUFFER *pbuf,
- char *str_value,
- int str_length,
- unsigned char *pstart,
- unsigned char **pcur,
- const struct nls_table *nls_cp)
-{
- unsigned char *tmp = pstart;
- int len;
-
- if (!pbuf)
- return;
-
- if (!pcur)
- pcur = &tmp;
-
- if (!str_value) {
- pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
- pbuf->Length = 0;
- pbuf->MaximumLength = 0;
- *pcur += sizeof(__le16);
- } else {
- len = cifs_strtoUTF16((__le16 *)*pcur,
- str_value,
- str_length,
- nls_cp);
- len *= sizeof(__le16);
- pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
- pbuf->Length = cpu_to_le16(len);
- pbuf->MaximumLength = cpu_to_le16(len);
- *pcur += len;
- }
-}
-
-/* BB Move to ntlmssp.c eventually */
-
-int build_ntlmssp_negotiate_blob(unsigned char **pbuffer,
- u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp)
-{
- int rc = 0;
- NEGOTIATE_MESSAGE *sec_blob;
- __u32 flags;
- unsigned char *tmp;
- int len;
-
- len = size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE));
- *pbuffer = kmalloc(len, GFP_KERNEL);
- if (!*pbuffer) {
- rc = -ENOMEM;
- cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
- *buflen = 0;
- goto setup_ntlm_neg_ret;
- }
- sec_blob = (NEGOTIATE_MESSAGE *)*pbuffer;
-
- memset(*pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
- memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
- sec_blob->MessageType = NtLmNegotiate;
-
- /* BB is NTLMV2 session security format easier to use here? */
- flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
- NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
- NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
- NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
- NTLMSSP_NEGOTIATE_SIGN;
- if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
- flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
-
- tmp = *pbuffer + sizeof(NEGOTIATE_MESSAGE);
- ses->ntlmssp->client_flags = flags;
- sec_blob->NegotiateFlags = cpu_to_le32(flags);
-
- /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
- cifs_security_buffer_from_str(&sec_blob->DomainName,
- NULL,
- CIFS_MAX_DOMAINNAME_LEN,
- *pbuffer, &tmp,
- nls_cp);
-
- cifs_security_buffer_from_str(&sec_blob->WorkstationName,
- NULL,
- CIFS_MAX_WORKSTATION_LEN,
- *pbuffer, &tmp,
- nls_cp);
-
- *buflen = tmp - *pbuffer;
-setup_ntlm_neg_ret:
- return rc;
-}
-
-/*
- * Build ntlmssp blob with additional fields, such as version,
- * supported by modern servers. For safety limit to SMB3 or later
- * See notes in MS-NLMP Section 2.2.2.1 e.g.
- */
-int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer,
- u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp)
-{
- int rc = 0;
- struct negotiate_message *sec_blob;
- __u32 flags;
- unsigned char *tmp;
- int len;
-
- len = size_of_ntlmssp_blob(ses, sizeof(struct negotiate_message));
- *pbuffer = kmalloc(len, GFP_KERNEL);
- if (!*pbuffer) {
- rc = -ENOMEM;
- cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
- *buflen = 0;
- goto setup_ntlm_smb3_neg_ret;
- }
- sec_blob = (struct negotiate_message *)*pbuffer;
-
- memset(*pbuffer, 0, sizeof(struct negotiate_message));
- memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
- sec_blob->MessageType = NtLmNegotiate;
-
- /* BB is NTLMV2 session security format easier to use here? */
- flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
- NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
- NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
- NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
- NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION;
- if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
- flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
-
- sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR;
- sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL;
- sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD);
- sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
-
- tmp = *pbuffer + sizeof(struct negotiate_message);
- ses->ntlmssp->client_flags = flags;
- sec_blob->NegotiateFlags = cpu_to_le32(flags);
-
- /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
- cifs_security_buffer_from_str(&sec_blob->DomainName,
- NULL,
- CIFS_MAX_DOMAINNAME_LEN,
- *pbuffer, &tmp,
- nls_cp);
-
- cifs_security_buffer_from_str(&sec_blob->WorkstationName,
- NULL,
- CIFS_MAX_WORKSTATION_LEN,
- *pbuffer, &tmp,
- nls_cp);
-
- *buflen = tmp - *pbuffer;
-setup_ntlm_smb3_neg_ret:
- return rc;
-}
-
-
-int build_ntlmssp_auth_blob(unsigned char **pbuffer,
- u16 *buflen,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp)
-{
- int rc;
- AUTHENTICATE_MESSAGE *sec_blob;
- __u32 flags;
- unsigned char *tmp;
- int len;
-
- rc = setup_ntlmv2_rsp(ses, nls_cp);
- if (rc) {
- cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
- *buflen = 0;
- goto setup_ntlmv2_ret;
- }
-
- len = size_of_ntlmssp_blob(ses, sizeof(AUTHENTICATE_MESSAGE));
- *pbuffer = kmalloc(len, GFP_KERNEL);
- if (!*pbuffer) {
- rc = -ENOMEM;
- cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
- *buflen = 0;
- goto setup_ntlmv2_ret;
- }
- sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
-
- memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
- sec_blob->MessageType = NtLmAuthenticate;
-
- flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET |
- NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
-
- tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
- sec_blob->NegotiateFlags = cpu_to_le32(flags);
-
- sec_blob->LmChallengeResponse.BufferOffset =
- cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
- sec_blob->LmChallengeResponse.Length = 0;
- sec_blob->LmChallengeResponse.MaximumLength = 0;
-
- sec_blob->NtChallengeResponse.BufferOffset =
- cpu_to_le32(tmp - *pbuffer);
- if (ses->user_name != NULL) {
- memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
- ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
-
- sec_blob->NtChallengeResponse.Length =
- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- sec_blob->NtChallengeResponse.MaximumLength =
- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- } else {
- /*
- * don't send an NT Response for anonymous access
- */
- sec_blob->NtChallengeResponse.Length = 0;
- sec_blob->NtChallengeResponse.MaximumLength = 0;
- }
-
- cifs_security_buffer_from_str(&sec_blob->DomainName,
- ses->domainName,
- CIFS_MAX_DOMAINNAME_LEN,
- *pbuffer, &tmp,
- nls_cp);
-
- cifs_security_buffer_from_str(&sec_blob->UserName,
- ses->user_name,
- CIFS_MAX_USERNAME_LEN,
- *pbuffer, &tmp,
- nls_cp);
-
- cifs_security_buffer_from_str(&sec_blob->WorkstationName,
- ses->workstation_name,
- ntlmssp_workstation_name_size(ses),
- *pbuffer, &tmp,
- nls_cp);
-
- if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
- (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) &&
- !calc_seckey(ses)) {
- memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
- sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
- sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
- sec_blob->SessionKey.MaximumLength =
- cpu_to_le16(CIFS_CPHTXT_SIZE);
- tmp += CIFS_CPHTXT_SIZE;
- } else {
- sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
- sec_blob->SessionKey.Length = 0;
- sec_blob->SessionKey.MaximumLength = 0;
- }
-
- *buflen = tmp - *pbuffer;
-setup_ntlmv2_ret:
- return rc;
-}
-
-enum securityEnum
-cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
-{
- switch (server->negflavor) {
- case CIFS_NEGFLAVOR_EXTENDED:
- switch (requested) {
- case Kerberos:
- case RawNTLMSSP:
- return requested;
- case Unspecified:
- if (server->sec_ntlmssp &&
- (global_secflags & CIFSSEC_MAY_NTLMSSP))
- return RawNTLMSSP;
- if ((server->sec_kerberos || server->sec_mskerberos) &&
- (global_secflags & CIFSSEC_MAY_KRB5))
- return Kerberos;
- fallthrough;
- default:
- return Unspecified;
- }
- case CIFS_NEGFLAVOR_UNENCAP:
- switch (requested) {
- case NTLMv2:
- return requested;
- case Unspecified:
- if (global_secflags & CIFSSEC_MAY_NTLMV2)
- return NTLMv2;
- break;
- default:
- break;
- }
- fallthrough;
- default:
- return Unspecified;
- }
-}
-
-struct sess_data {
- unsigned int xid;
- struct cifs_ses *ses;
- struct TCP_Server_Info *server;
- struct nls_table *nls_cp;
- void (*func)(struct sess_data *);
- int result;
-
- /* we will send the SMB in three pieces:
- * a fixed length beginning part, an optional
- * SPNEGO blob (which can be zero length), and a
- * last part which will include the strings
- * and rest of bcc area. This allows us to avoid
- * a large buffer 17K allocation
- */
- int buf0_type;
- struct kvec iov[3];
-};
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-static int
-sess_alloc_buffer(struct sess_data *sess_data, int wct)
-{
- int rc;
- struct cifs_ses *ses = sess_data->ses;
- struct smb_hdr *smb_buf;
-
- rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
- (void **)&smb_buf);
-
- if (rc)
- return rc;
-
- sess_data->iov[0].iov_base = (char *)smb_buf;
- sess_data->iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
- /*
- * This variable will be used to clear the buffer
- * allocated above in case of any error in the calling function.
- */
- sess_data->buf0_type = CIFS_SMALL_BUFFER;
-
- /* 2000 big enough to fit max user, domain, NOS name etc. */
- sess_data->iov[2].iov_base = kmalloc(2000, GFP_KERNEL);
- if (!sess_data->iov[2].iov_base) {
- rc = -ENOMEM;
- goto out_free_smb_buf;
- }
-
- return 0;
-
-out_free_smb_buf:
- cifs_small_buf_release(smb_buf);
- sess_data->iov[0].iov_base = NULL;
- sess_data->iov[0].iov_len = 0;
- sess_data->buf0_type = CIFS_NO_BUFFER;
- return rc;
-}
-
-static void
-sess_free_buffer(struct sess_data *sess_data)
-{
- struct kvec *iov = sess_data->iov;
-
- /*
- * Zero the session data before freeing, as it might contain sensitive info (keys, etc).
- * Note that iov[1] is already freed by caller.
- */
- if (sess_data->buf0_type != CIFS_NO_BUFFER && iov[0].iov_base)
- memzero_explicit(iov[0].iov_base, iov[0].iov_len);
-
- free_rsp_buf(sess_data->buf0_type, iov[0].iov_base);
- sess_data->buf0_type = CIFS_NO_BUFFER;
- kfree_sensitive(iov[2].iov_base);
-}
-
-static int
-sess_establish_session(struct sess_data *sess_data)
-{
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
-
- cifs_server_lock(server);
- if (!server->session_estab) {
- if (server->sign) {
- server->session_key.response =
- kmemdup(ses->auth_key.response,
- ses->auth_key.len, GFP_KERNEL);
- if (!server->session_key.response) {
- cifs_server_unlock(server);
- return -ENOMEM;
- }
- server->session_key.len =
- ses->auth_key.len;
- }
- server->sequence_number = 0x2;
- server->session_estab = true;
- }
- cifs_server_unlock(server);
-
- cifs_dbg(FYI, "CIFS session established successfully\n");
- return 0;
-}
-
-static int
-sess_sendreceive(struct sess_data *sess_data)
-{
- int rc;
- struct smb_hdr *smb_buf = (struct smb_hdr *) sess_data->iov[0].iov_base;
- __u16 count;
- struct kvec rsp_iov = { NULL, 0 };
-
- count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len;
- be32_add_cpu(&smb_buf->smb_buf_length, count);
- put_bcc(count, smb_buf);
-
- rc = SendReceive2(sess_data->xid, sess_data->ses,
- sess_data->iov, 3 /* num_iovecs */,
- &sess_data->buf0_type,
- CIFS_LOG_ERROR, &rsp_iov);
- cifs_small_buf_release(sess_data->iov[0].iov_base);
- memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
-
- return rc;
-}
-
-static void
-sess_auth_ntlmv2(struct sess_data *sess_data)
-{
- int rc = 0;
- struct smb_hdr *smb_buf;
- SESSION_SETUP_ANDX *pSMB;
- char *bcc_ptr;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
- __u32 capabilities;
- __u16 bytes_remaining;
-
- /* old style NTLM sessionsetup */
- /* wct = 13 */
- rc = sess_alloc_buffer(sess_data, 13);
- if (rc)
- goto out;
-
- pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
- bcc_ptr = sess_data->iov[2].iov_base;
- capabilities = cifs_ssetup_hdr(ses, server, pSMB);
-
- pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
-
- /* LM2 password would be here if we supported it */
- pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
-
- if (ses->user_name != NULL) {
- /* calculate nlmv2 response and session key */
- rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
- if (rc) {
- cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
- goto out;
- }
-
- memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
- ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
-
- /* set case sensitive password length after tilen may get
- * assigned, tilen is 0 otherwise.
- */
- pSMB->req_no_secext.CaseSensitivePasswordLength =
- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- } else {
- pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
- }
-
- if (ses->capabilities & CAP_UNICODE) {
- if (!IS_ALIGNED(sess_data->iov[0].iov_len, 2)) {
- *bcc_ptr = 0;
- bcc_ptr++;
- }
- unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
- } else {
- ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
- }
-
-
- sess_data->iov[2].iov_len = (long) bcc_ptr -
- (long) sess_data->iov[2].iov_base;
-
- rc = sess_sendreceive(sess_data);
- if (rc)
- goto out;
-
- pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
- smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
-
- if (smb_buf->WordCount != 3) {
- rc = -EIO;
- cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
- goto out;
- }
-
- if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
- cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
-
- ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
- cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
-
- bytes_remaining = get_bcc(smb_buf);
- bcc_ptr = pByteArea(smb_buf);
-
- /* BB check if Unicode and decode strings */
- if (bytes_remaining == 0) {
- /* no string area to decode, do nothing */
- } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
- /* unicode string area must be word-aligned */
- if (!IS_ALIGNED((unsigned long)bcc_ptr - (unsigned long)smb_buf, 2)) {
- ++bcc_ptr;
- --bytes_remaining;
- }
- decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
- sess_data->nls_cp);
- } else {
- decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
- sess_data->nls_cp);
- }
-
- rc = sess_establish_session(sess_data);
-out:
- sess_data->result = rc;
- sess_data->func = NULL;
- sess_free_buffer(sess_data);
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.response = NULL;
-}
-
-#ifdef CONFIG_CIFS_UPCALL
-static void
-sess_auth_kerberos(struct sess_data *sess_data)
-{
- int rc = 0;
- struct smb_hdr *smb_buf;
- SESSION_SETUP_ANDX *pSMB;
- char *bcc_ptr;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
- __u32 capabilities;
- __u16 bytes_remaining;
- struct key *spnego_key = NULL;
- struct cifs_spnego_msg *msg;
- u16 blob_len;
-
- /* extended security */
- /* wct = 12 */
- rc = sess_alloc_buffer(sess_data, 12);
- if (rc)
- goto out;
-
- pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
- bcc_ptr = sess_data->iov[2].iov_base;
- capabilities = cifs_ssetup_hdr(ses, server, pSMB);
-
- spnego_key = cifs_get_spnego_key(ses, server);
- if (IS_ERR(spnego_key)) {
- rc = PTR_ERR(spnego_key);
- spnego_key = NULL;
- goto out;
- }
-
- msg = spnego_key->payload.data[0];
- /*
- * check version field to make sure that cifs.upcall is
- * sending us a response in an expected form
- */
- if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
- cifs_dbg(VFS, "incorrect version of cifs.upcall (expected %d but got %d)\n",
- CIFS_SPNEGO_UPCALL_VERSION, msg->version);
- rc = -EKEYREJECTED;
- goto out_put_spnego_key;
- }
-
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
- GFP_KERNEL);
- if (!ses->auth_key.response) {
- cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n",
- msg->sesskey_len);
- rc = -ENOMEM;
- goto out_put_spnego_key;
- }
- ses->auth_key.len = msg->sesskey_len;
-
- pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
- capabilities |= CAP_EXTENDED_SECURITY;
- pSMB->req.Capabilities = cpu_to_le32(capabilities);
- sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
- sess_data->iov[1].iov_len = msg->secblob_len;
- pSMB->req.SecurityBlobLength = cpu_to_le16(sess_data->iov[1].iov_len);
-
- if (ses->capabilities & CAP_UNICODE) {
- /* unicode strings must be word aligned */
- if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) {
- *bcc_ptr = 0;
- bcc_ptr++;
- }
- unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
- unicode_domain_string(&bcc_ptr, ses, sess_data->nls_cp);
- } else {
- /* BB: is this right? */
- ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
- }
-
- sess_data->iov[2].iov_len = (long) bcc_ptr -
- (long) sess_data->iov[2].iov_base;
-
- rc = sess_sendreceive(sess_data);
- if (rc)
- goto out_put_spnego_key;
-
- pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
- smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
-
- if (smb_buf->WordCount != 4) {
- rc = -EIO;
- cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
- goto out_put_spnego_key;
- }
-
- if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
- cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
-
- ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
- cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
-
- bytes_remaining = get_bcc(smb_buf);
- bcc_ptr = pByteArea(smb_buf);
-
- blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
- if (blob_len > bytes_remaining) {
- cifs_dbg(VFS, "bad security blob length %d\n",
- blob_len);
- rc = -EINVAL;
- goto out_put_spnego_key;
- }
- bcc_ptr += blob_len;
- bytes_remaining -= blob_len;
-
- /* BB check if Unicode and decode strings */
- if (bytes_remaining == 0) {
- /* no string area to decode, do nothing */
- } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
- /* unicode string area must be word-aligned */
- if (!IS_ALIGNED((unsigned long)bcc_ptr - (unsigned long)smb_buf, 2)) {
- ++bcc_ptr;
- --bytes_remaining;
- }
- decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
- sess_data->nls_cp);
- } else {
- decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
- sess_data->nls_cp);
- }
-
- rc = sess_establish_session(sess_data);
-out_put_spnego_key:
- key_invalidate(spnego_key);
- key_put(spnego_key);
-out:
- sess_data->result = rc;
- sess_data->func = NULL;
- sess_free_buffer(sess_data);
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.response = NULL;
-}
-
-#endif /* ! CONFIG_CIFS_UPCALL */
-
-/*
- * The required kvec buffers have to be allocated before calling this
- * function.
- */
-static int
-_sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
-{
- SESSION_SETUP_ANDX *pSMB;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
- __u32 capabilities;
- char *bcc_ptr;
-
- pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
-
- capabilities = cifs_ssetup_hdr(ses, server, pSMB);
- if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
- cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
- return -ENOSYS;
- }
-
- pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
- capabilities |= CAP_EXTENDED_SECURITY;
- pSMB->req.Capabilities |= cpu_to_le32(capabilities);
-
- bcc_ptr = sess_data->iov[2].iov_base;
- /* unicode strings must be word aligned */
- if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) {
- *bcc_ptr = 0;
- bcc_ptr++;
- }
- unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
-
- sess_data->iov[2].iov_len = (long) bcc_ptr -
- (long) sess_data->iov[2].iov_base;
-
- return 0;
-}
-
-static void
-sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data);
-
-static void
-sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
-{
- int rc;
- struct smb_hdr *smb_buf;
- SESSION_SETUP_ANDX *pSMB;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
- __u16 bytes_remaining;
- char *bcc_ptr;
- unsigned char *ntlmsspblob = NULL;
- u16 blob_len;
-
- cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
-
- /*
- * if memory allocation is successful, caller of this function
- * frees it.
- */
- ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
- if (!ses->ntlmssp) {
- rc = -ENOMEM;
- goto out;
- }
- ses->ntlmssp->sesskey_per_smbsess = false;
-
- /* wct = 12 */
- rc = sess_alloc_buffer(sess_data, 12);
- if (rc)
- goto out;
-
- pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
-
- /* Build security blob before we assemble the request */
- rc = build_ntlmssp_negotiate_blob(&ntlmsspblob,
- &blob_len, ses, server,
- sess_data->nls_cp);
- if (rc)
- goto out_free_ntlmsspblob;
-
- sess_data->iov[1].iov_len = blob_len;
- sess_data->iov[1].iov_base = ntlmsspblob;
- pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
-
- rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
- if (rc)
- goto out_free_ntlmsspblob;
-
- rc = sess_sendreceive(sess_data);
-
- pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
- smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
-
- /* If true, rc here is expected and not an error */
- if (sess_data->buf0_type != CIFS_NO_BUFFER &&
- smb_buf->Status.CifsError ==
- cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
- rc = 0;
-
- if (rc)
- goto out_free_ntlmsspblob;
-
- cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
-
- if (smb_buf->WordCount != 4) {
- rc = -EIO;
- cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
- goto out_free_ntlmsspblob;
- }
-
- ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
- cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
-
- bytes_remaining = get_bcc(smb_buf);
- bcc_ptr = pByteArea(smb_buf);
-
- blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
- if (blob_len > bytes_remaining) {
- cifs_dbg(VFS, "bad security blob length %d\n",
- blob_len);
- rc = -EINVAL;
- goto out_free_ntlmsspblob;
- }
-
- rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
-
-out_free_ntlmsspblob:
- kfree_sensitive(ntlmsspblob);
-out:
- sess_free_buffer(sess_data);
-
- if (!rc) {
- sess_data->func = sess_auth_rawntlmssp_authenticate;
- return;
- }
-
- /* Else error. Cleanup */
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.response = NULL;
- kfree_sensitive(ses->ntlmssp);
- ses->ntlmssp = NULL;
-
- sess_data->func = NULL;
- sess_data->result = rc;
-}
-
-static void
-sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
-{
- int rc;
- struct smb_hdr *smb_buf;
- SESSION_SETUP_ANDX *pSMB;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
- __u16 bytes_remaining;
- char *bcc_ptr;
- unsigned char *ntlmsspblob = NULL;
- u16 blob_len;
-
- cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
-
- /* wct = 12 */
- rc = sess_alloc_buffer(sess_data, 12);
- if (rc)
- goto out;
-
- /* Build security blob before we assemble the request */
- pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
- smb_buf = (struct smb_hdr *)pSMB;
- rc = build_ntlmssp_auth_blob(&ntlmsspblob,
- &blob_len, ses, server,
- sess_data->nls_cp);
- if (rc)
- goto out_free_ntlmsspblob;
- sess_data->iov[1].iov_len = blob_len;
- sess_data->iov[1].iov_base = ntlmsspblob;
- pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
- /*
- * Make sure that we tell the server that we are using
- * the uid that it just gave us back on the response
- * (challenge)
- */
- smb_buf->Uid = ses->Suid;
-
- rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
- if (rc)
- goto out_free_ntlmsspblob;
-
- rc = sess_sendreceive(sess_data);
- if (rc)
- goto out_free_ntlmsspblob;
-
- pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
- smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
- if (smb_buf->WordCount != 4) {
- rc = -EIO;
- cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
- goto out_free_ntlmsspblob;
- }
-
- if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
- cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
-
- if (ses->Suid != smb_buf->Uid) {
- ses->Suid = smb_buf->Uid;
- cifs_dbg(FYI, "UID changed! new UID = %llu\n", ses->Suid);
- }
-
- bytes_remaining = get_bcc(smb_buf);
- bcc_ptr = pByteArea(smb_buf);
- blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
- if (blob_len > bytes_remaining) {
- cifs_dbg(VFS, "bad security blob length %d\n",
- blob_len);
- rc = -EINVAL;
- goto out_free_ntlmsspblob;
- }
- bcc_ptr += blob_len;
- bytes_remaining -= blob_len;
-
-
- /* BB check if Unicode and decode strings */
- if (bytes_remaining == 0) {
- /* no string area to decode, do nothing */
- } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
- /* unicode string area must be word-aligned */
- if (!IS_ALIGNED((unsigned long)bcc_ptr - (unsigned long)smb_buf, 2)) {
- ++bcc_ptr;
- --bytes_remaining;
- }
- decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
- sess_data->nls_cp);
- } else {
- decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
- sess_data->nls_cp);
- }
-
-out_free_ntlmsspblob:
- kfree_sensitive(ntlmsspblob);
-out:
- sess_free_buffer(sess_data);
-
- if (!rc)
- rc = sess_establish_session(sess_data);
-
- /* Cleanup */
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.response = NULL;
- kfree_sensitive(ses->ntlmssp);
- ses->ntlmssp = NULL;
-
- sess_data->func = NULL;
- sess_data->result = rc;
-}
-
-static int select_sec(struct sess_data *sess_data)
-{
- int type;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
-
- type = cifs_select_sectype(server, ses->sectype);
- cifs_dbg(FYI, "sess setup type %d\n", type);
- if (type == Unspecified) {
- cifs_dbg(VFS, "Unable to select appropriate authentication method!\n");
- return -EINVAL;
- }
-
- switch (type) {
- case NTLMv2:
- sess_data->func = sess_auth_ntlmv2;
- break;
- case Kerberos:
-#ifdef CONFIG_CIFS_UPCALL
- sess_data->func = sess_auth_kerberos;
- break;
-#else
- cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
- return -ENOSYS;
-#endif /* CONFIG_CIFS_UPCALL */
- case RawNTLMSSP:
- sess_data->func = sess_auth_rawntlmssp_negotiate;
- break;
- default:
- cifs_dbg(VFS, "secType %d not supported!\n", type);
- return -ENOSYS;
- }
-
- return 0;
-}
-
-int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp)
-{
- int rc = 0;
- struct sess_data *sess_data;
-
- if (ses == NULL) {
- WARN(1, "%s: ses == NULL!", __func__);
- return -EINVAL;
- }
-
- sess_data = kzalloc(sizeof(struct sess_data), GFP_KERNEL);
- if (!sess_data)
- return -ENOMEM;
-
- sess_data->xid = xid;
- sess_data->ses = ses;
- sess_data->server = server;
- sess_data->buf0_type = CIFS_NO_BUFFER;
- sess_data->nls_cp = (struct nls_table *) nls_cp;
-
- rc = select_sec(sess_data);
- if (rc)
- goto out;
-
- while (sess_data->func)
- sess_data->func(sess_data);
-
- /* Store result before we free sess_data */
- rc = sess_data->result;
-
-out:
- kfree_sensitive(sess_data);
- return rc;
-}
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
deleted file mode 100644
index 7d1b3fc014d9..000000000000
--- a/fs/cifs/smb1ops.c
+++ /dev/null
@@ -1,1276 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * SMB1 (CIFS) version specific operations
- *
- * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
- */
-
-#include <linux/pagemap.h>
-#include <linux/vfs.h>
-#include <uapi/linux/magic.h>
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifspdu.h"
-#include "cifs_unicode.h"
-#include "fs_context.h"
-
-/*
- * An NT cancel request header looks just like the original request except:
- *
- * The Command is SMB_COM_NT_CANCEL
- * The WordCount is zeroed out
- * The ByteCount is zeroed out
- *
- * This function mangles an existing request buffer into a
- * SMB_COM_NT_CANCEL request and then sends it.
- */
-static int
-send_nt_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
- struct mid_q_entry *mid)
-{
- int rc = 0;
- struct smb_hdr *in_buf = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
-
- /* -4 for RFC1001 length and +2 for BCC field */
- in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2);
- in_buf->Command = SMB_COM_NT_CANCEL;
- in_buf->WordCount = 0;
- put_bcc(0, in_buf);
-
- cifs_server_lock(server);
- rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
- if (rc) {
- cifs_server_unlock(server);
- return rc;
- }
-
- /*
- * The response to this call was already factored into the sequence
- * number when the call went out, so we must adjust it back downward
- * after signing here.
- */
- --server->sequence_number;
- rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
- if (rc < 0)
- server->sequence_number--;
-
- cifs_server_unlock(server);
-
- cifs_dbg(FYI, "issued NT_CANCEL for mid %u, rc = %d\n",
- get_mid(in_buf), rc);
-
- return rc;
-}
-
-static bool
-cifs_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
-{
- return ob1->fid.netfid == ob2->fid.netfid;
-}
-
-static unsigned int
-cifs_read_data_offset(char *buf)
-{
- READ_RSP *rsp = (READ_RSP *)buf;
- return le16_to_cpu(rsp->DataOffset);
-}
-
-static unsigned int
-cifs_read_data_length(char *buf, bool in_remaining)
-{
- READ_RSP *rsp = (READ_RSP *)buf;
- /* It's a bug reading remaining data for SMB1 packets */
- WARN_ON(in_remaining);
- return (le16_to_cpu(rsp->DataLengthHigh) << 16) +
- le16_to_cpu(rsp->DataLength);
-}
-
-static struct mid_q_entry *
-cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
-{
- struct smb_hdr *buf = (struct smb_hdr *)buffer;
- struct mid_q_entry *mid;
-
- spin_lock(&server->mid_lock);
- list_for_each_entry(mid, &server->pending_mid_q, qhead) {
- if (compare_mid(mid->mid, buf) &&
- mid->mid_state == MID_REQUEST_SUBMITTED &&
- le16_to_cpu(mid->command) == buf->Command) {
- kref_get(&mid->refcount);
- spin_unlock(&server->mid_lock);
- return mid;
- }
- }
- spin_unlock(&server->mid_lock);
- return NULL;
-}
-
-static void
-cifs_add_credits(struct TCP_Server_Info *server,
- const struct cifs_credits *credits, const int optype)
-{
- spin_lock(&server->req_lock);
- server->credits += credits->value;
- server->in_flight--;
- spin_unlock(&server->req_lock);
- wake_up(&server->request_q);
-}
-
-static void
-cifs_set_credits(struct TCP_Server_Info *server, const int val)
-{
- spin_lock(&server->req_lock);
- server->credits = val;
- server->oplocks = val > 1 ? enable_oplocks : false;
- spin_unlock(&server->req_lock);
-}
-
-static int *
-cifs_get_credits_field(struct TCP_Server_Info *server, const int optype)
-{
- return &server->credits;
-}
-
-static unsigned int
-cifs_get_credits(struct mid_q_entry *mid)
-{
- return 1;
-}
-
-/*
- * Find a free multiplex id (SMB mid). Otherwise there could be
- * mid collisions which might cause problems, demultiplexing the
- * wrong response to this request. Multiplex ids could collide if
- * one of a series requests takes much longer than the others, or
- * if a very large number of long lived requests (byte range
- * locks or FindNotify requests) are pending. No more than
- * 64K-1 requests can be outstanding at one time. If no
- * mids are available, return zero. A future optimization
- * could make the combination of mids and uid the key we use
- * to demultiplex on (rather than mid alone).
- * In addition to the above check, the cifs demultiplex
- * code already used the command code as a secondary
- * check of the frame and if signing is negotiated the
- * response would be discarded if the mid were the same
- * but the signature was wrong. Since the mid is not put in the
- * pending queue until later (when it is about to be dispatched)
- * we do have to limit the number of outstanding requests
- * to somewhat less than 64K-1 although it is hard to imagine
- * so many threads being in the vfs at one time.
- */
-static __u64
-cifs_get_next_mid(struct TCP_Server_Info *server)
-{
- __u64 mid = 0;
- __u16 last_mid, cur_mid;
- bool collision, reconnect = false;
-
- spin_lock(&server->mid_lock);
-
- /* mid is 16 bit only for CIFS/SMB */
- cur_mid = (__u16)((server->CurrentMid) & 0xffff);
- /* we do not want to loop forever */
- last_mid = cur_mid;
- cur_mid++;
- /* avoid 0xFFFF MID */
- if (cur_mid == 0xffff)
- cur_mid++;
-
- /*
- * This nested loop looks more expensive than it is.
- * In practice the list of pending requests is short,
- * fewer than 50, and the mids are likely to be unique
- * on the first pass through the loop unless some request
- * takes longer than the 64 thousand requests before it
- * (and it would also have to have been a request that
- * did not time out).
- */
- while (cur_mid != last_mid) {
- struct mid_q_entry *mid_entry;
- unsigned int num_mids;
-
- collision = false;
- if (cur_mid == 0)
- cur_mid++;
-
- num_mids = 0;
- list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
- ++num_mids;
- if (mid_entry->mid == cur_mid &&
- mid_entry->mid_state == MID_REQUEST_SUBMITTED) {
- /* This mid is in use, try a different one */
- collision = true;
- break;
- }
- }
-
- /*
- * if we have more than 32k mids in the list, then something
- * is very wrong. Possibly a local user is trying to DoS the
- * box by issuing long-running calls and SIGKILL'ing them. If
- * we get to 2^16 mids then we're in big trouble as this
- * function could loop forever.
- *
- * Go ahead and assign out the mid in this situation, but force
- * an eventual reconnect to clean out the pending_mid_q.
- */
- if (num_mids > 32768)
- reconnect = true;
-
- if (!collision) {
- mid = (__u64)cur_mid;
- server->CurrentMid = mid;
- break;
- }
- cur_mid++;
- }
- spin_unlock(&server->mid_lock);
-
- if (reconnect) {
- cifs_signal_cifsd_for_reconnect(server, false);
- }
-
- return mid;
-}
-
-/*
- return codes:
- 0 not a transact2, or all data present
- >0 transact2 with that much data missing
- -EINVAL invalid transact2
- */
-static int
-check2ndT2(char *buf)
-{
- struct smb_hdr *pSMB = (struct smb_hdr *)buf;
- struct smb_t2_rsp *pSMBt;
- int remaining;
- __u16 total_data_size, data_in_this_rsp;
-
- if (pSMB->Command != SMB_COM_TRANSACTION2)
- return 0;
-
- /* check for plausible wct, bcc and t2 data and parm sizes */
- /* check for parm and data offset going beyond end of smb */
- if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
- cifs_dbg(FYI, "Invalid transact2 word count\n");
- return -EINVAL;
- }
-
- pSMBt = (struct smb_t2_rsp *)pSMB;
-
- total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
- data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
-
- if (total_data_size == data_in_this_rsp)
- return 0;
- else if (total_data_size < data_in_this_rsp) {
- cifs_dbg(FYI, "total data %d smaller than data in frame %d\n",
- total_data_size, data_in_this_rsp);
- return -EINVAL;
- }
-
- remaining = total_data_size - data_in_this_rsp;
-
- cifs_dbg(FYI, "missing %d bytes from transact2, check next response\n",
- remaining);
- if (total_data_size > CIFSMaxBufSize) {
- cifs_dbg(VFS, "TotalDataSize %d is over maximum buffer %d\n",
- total_data_size, CIFSMaxBufSize);
- return -EINVAL;
- }
- return remaining;
-}
-
-static int
-coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
-{
- struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
- struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
- char *data_area_of_tgt;
- char *data_area_of_src;
- int remaining;
- unsigned int byte_count, total_in_tgt;
- __u16 tgt_total_cnt, src_total_cnt, total_in_src;
-
- src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
- tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
-
- if (tgt_total_cnt != src_total_cnt)
- cifs_dbg(FYI, "total data count of primary and secondary t2 differ source=%hu target=%hu\n",
- src_total_cnt, tgt_total_cnt);
-
- total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
-
- remaining = tgt_total_cnt - total_in_tgt;
-
- if (remaining < 0) {
- cifs_dbg(FYI, "Server sent too much data. tgt_total_cnt=%hu total_in_tgt=%u\n",
- tgt_total_cnt, total_in_tgt);
- return -EPROTO;
- }
-
- if (remaining == 0) {
- /* nothing to do, ignore */
- cifs_dbg(FYI, "no more data remains\n");
- return 0;
- }
-
- total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
- if (remaining < total_in_src)
- cifs_dbg(FYI, "transact2 2nd response contains too much data\n");
-
- /* find end of first SMB data area */
- data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
- get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
-
- /* validate target area */
- data_area_of_src = (char *)&pSMBs->hdr.Protocol +
- get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
-
- data_area_of_tgt += total_in_tgt;
-
- total_in_tgt += total_in_src;
- /* is the result too big for the field? */
- if (total_in_tgt > USHRT_MAX) {
- cifs_dbg(FYI, "coalesced DataCount too large (%u)\n",
- total_in_tgt);
- return -EPROTO;
- }
- put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
-
- /* fix up the BCC */
- byte_count = get_bcc(target_hdr);
- byte_count += total_in_src;
- /* is the result too big for the field? */
- if (byte_count > USHRT_MAX) {
- cifs_dbg(FYI, "coalesced BCC too large (%u)\n", byte_count);
- return -EPROTO;
- }
- put_bcc(byte_count, target_hdr);
-
- byte_count = be32_to_cpu(target_hdr->smb_buf_length);
- byte_count += total_in_src;
- /* don't allow buffer to overflow */
- if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
- cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n",
- byte_count);
- return -ENOBUFS;
- }
- target_hdr->smb_buf_length = cpu_to_be32(byte_count);
-
- /* copy second buffer into end of first buffer */
- memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
-
- if (remaining != total_in_src) {
- /* more responses to go */
- cifs_dbg(FYI, "waiting for more secondary responses\n");
- return 1;
- }
-
- /* we are done */
- cifs_dbg(FYI, "found the last secondary response\n");
- return 0;
-}
-
-static void
-cifs_downgrade_oplock(struct TCP_Server_Info *server,
- struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
-{
- cifs_set_oplock_level(cinode, oplock);
-}
-
-static bool
-cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
- char *buf, int malformed)
-{
- if (malformed)
- return false;
- if (check2ndT2(buf) <= 0)
- return false;
- mid->multiRsp = true;
- if (mid->resp_buf) {
- /* merge response - fix up 1st*/
- malformed = coalesce_t2(buf, mid->resp_buf);
- if (malformed > 0)
- return true;
- /* All parts received or packet is malformed. */
- mid->multiEnd = true;
- dequeue_mid(mid, malformed);
- return true;
- }
- if (!server->large_buf) {
- /*FIXME: switch to already allocated largebuf?*/
- cifs_dbg(VFS, "1st trans2 resp needs bigbuf\n");
- } else {
- /* Have first buffer */
- mid->resp_buf = buf;
- mid->large_buf = true;
- server->bigbuf = NULL;
- }
- return true;
-}
-
-static bool
-cifs_need_neg(struct TCP_Server_Info *server)
-{
- return server->maxBuf == 0;
-}
-
-static int
-cifs_negotiate(const unsigned int xid,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- int rc;
- rc = CIFSSMBNegotiate(xid, ses, server);
- if (rc == -EAGAIN) {
- /* retry only once on 1st time connection */
- set_credits(server, 1);
- rc = CIFSSMBNegotiate(xid, ses, server);
- if (rc == -EAGAIN)
- rc = -EHOSTDOWN;
- }
- return rc;
-}
-
-static unsigned int
-cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
-{
- __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
- struct TCP_Server_Info *server = tcon->ses->server;
- unsigned int wsize;
-
- /* start with specified wsize, or default */
- if (ctx->wsize)
- wsize = ctx->wsize;
- else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
- wsize = CIFS_DEFAULT_IOSIZE;
- else
- wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
-
- /* can server support 24-bit write sizes? (via UNIX extensions) */
- if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
- wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
-
- /*
- * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
- * Limit it to max buffer offered by the server, minus the size of the
- * WRITEX header, not including the 4 byte RFC1001 length.
- */
- if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
- (!(server->capabilities & CAP_UNIX) && server->sign))
- wsize = min_t(unsigned int, wsize,
- server->maxBuf - sizeof(WRITE_REQ) + 4);
-
- /* hard limit of CIFS_MAX_WSIZE */
- wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
-
- return wsize;
-}
-
-static unsigned int
-cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
-{
- __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
- struct TCP_Server_Info *server = tcon->ses->server;
- unsigned int rsize, defsize;
-
- /*
- * Set default value...
- *
- * HACK alert! Ancient servers have very small buffers. Even though
- * MS-CIFS indicates that servers are only limited by the client's
- * bufsize for reads, testing against win98se shows that it throws
- * INVALID_PARAMETER errors if you try to request too large a read.
- * OS/2 just sends back short reads.
- *
- * If the server doesn't advertise CAP_LARGE_READ_X, then assume that
- * it can't handle a read request larger than its MaxBufferSize either.
- */
- if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
- defsize = CIFS_DEFAULT_IOSIZE;
- else if (server->capabilities & CAP_LARGE_READ_X)
- defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
- else
- defsize = server->maxBuf - sizeof(READ_RSP);
-
- rsize = ctx->rsize ? ctx->rsize : defsize;
-
- /*
- * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
- * the client's MaxBufferSize.
- */
- if (!(server->capabilities & CAP_LARGE_READ_X))
- rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
-
- /* hard limit of CIFS_MAX_RSIZE */
- rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
-
- return rsize;
-}
-
-static void
-cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb)
-{
- CIFSSMBQFSDeviceInfo(xid, tcon);
- CIFSSMBQFSAttributeInfo(xid, tcon);
-}
-
-static int
-cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path)
-{
- int rc;
- FILE_ALL_INFO *file_info;
-
- file_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
- if (file_info == NULL)
- return -ENOMEM;
-
- rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info,
- 0 /* not legacy */, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
-
- if (rc == -EOPNOTSUPP || rc == -EINVAL)
- rc = SMBQueryInformation(xid, tcon, full_path, file_info,
- cifs_sb->local_nls, cifs_remap(cifs_sb));
- kfree(file_info);
- return rc;
-}
-
-static int cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- struct cifs_open_info_data *data, bool *adjustTZ, bool *symlink)
-{
- int rc;
- FILE_ALL_INFO fi = {};
-
- *symlink = false;
-
- /* could do find first instead but this returns more info */
- rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- /*
- * BB optimize code so we do not make the above call when server claims
- * no NT SMB support and the above call failed at least once - set flag
- * in tcon or mount.
- */
- if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
- rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- *adjustTZ = true;
- }
-
- if (!rc) {
- int tmprc;
- int oplock = 0;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
-
- move_cifs_info_to_smb2(&data->fi, &fi);
-
- if (!(le32_to_cpu(fi.Attributes) & ATTR_REPARSE))
- return 0;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = FILE_READ_ATTRIBUTES,
- .create_options = cifs_create_options(cifs_sb, 0),
- .disposition = FILE_OPEN,
- .path = full_path,
- .fid = &fid,
- };
-
- /* Need to check if this is a symbolic link or not */
- tmprc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (tmprc == -EOPNOTSUPP)
- *symlink = true;
- else if (tmprc == 0)
- CIFSSMBClose(xid, tcon, fid.netfid);
- }
-
- return rc;
-}
-
-static int cifs_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- u64 *uniqueid, struct cifs_open_info_data *unused)
-{
- /*
- * We can not use the IndexNumber field by default from Windows or
- * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
- * CIFS spec claims that this value is unique within the scope of a
- * share, and the windows docs hint that it's actually unique
- * per-machine.
- *
- * There may be higher info levels that work but are there Windows
- * server or network appliances for which IndexNumber field is not
- * guaranteed unique?
- */
- return CIFSGetSrvInodeNumber(xid, tcon, full_path, uniqueid,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
-}
-
-static int cifs_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile, struct cifs_open_info_data *data)
-{
- int rc;
- FILE_ALL_INFO fi = {};
-
- if (cfile->symlink_target) {
- data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
- if (!data->symlink_target)
- return -ENOMEM;
- }
-
- rc = CIFSSMBQFileInfo(xid, tcon, cfile->fid.netfid, &fi);
- if (!rc)
- move_cifs_info_to_smb2(&data->fi, &fi);
- return rc;
-}
-
-static void
-cifs_clear_stats(struct cifs_tcon *tcon)
-{
- atomic_set(&tcon->stats.cifs_stats.num_writes, 0);
- atomic_set(&tcon->stats.cifs_stats.num_reads, 0);
- atomic_set(&tcon->stats.cifs_stats.num_flushes, 0);
- atomic_set(&tcon->stats.cifs_stats.num_oplock_brks, 0);
- atomic_set(&tcon->stats.cifs_stats.num_opens, 0);
- atomic_set(&tcon->stats.cifs_stats.num_posixopens, 0);
- atomic_set(&tcon->stats.cifs_stats.num_posixmkdirs, 0);
- atomic_set(&tcon->stats.cifs_stats.num_closes, 0);
- atomic_set(&tcon->stats.cifs_stats.num_deletes, 0);
- atomic_set(&tcon->stats.cifs_stats.num_mkdirs, 0);
- atomic_set(&tcon->stats.cifs_stats.num_rmdirs, 0);
- atomic_set(&tcon->stats.cifs_stats.num_renames, 0);
- atomic_set(&tcon->stats.cifs_stats.num_t2renames, 0);
- atomic_set(&tcon->stats.cifs_stats.num_ffirst, 0);
- atomic_set(&tcon->stats.cifs_stats.num_fnext, 0);
- atomic_set(&tcon->stats.cifs_stats.num_fclose, 0);
- atomic_set(&tcon->stats.cifs_stats.num_hardlinks, 0);
- atomic_set(&tcon->stats.cifs_stats.num_symlinks, 0);
- atomic_set(&tcon->stats.cifs_stats.num_locks, 0);
- atomic_set(&tcon->stats.cifs_stats.num_acl_get, 0);
- atomic_set(&tcon->stats.cifs_stats.num_acl_set, 0);
-}
-
-static void
-cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
-{
- seq_printf(m, " Oplocks breaks: %d",
- atomic_read(&tcon->stats.cifs_stats.num_oplock_brks));
- seq_printf(m, "\nReads: %d Bytes: %llu",
- atomic_read(&tcon->stats.cifs_stats.num_reads),
- (long long)(tcon->bytes_read));
- seq_printf(m, "\nWrites: %d Bytes: %llu",
- atomic_read(&tcon->stats.cifs_stats.num_writes),
- (long long)(tcon->bytes_written));
- seq_printf(m, "\nFlushes: %d",
- atomic_read(&tcon->stats.cifs_stats.num_flushes));
- seq_printf(m, "\nLocks: %d HardLinks: %d Symlinks: %d",
- atomic_read(&tcon->stats.cifs_stats.num_locks),
- atomic_read(&tcon->stats.cifs_stats.num_hardlinks),
- atomic_read(&tcon->stats.cifs_stats.num_symlinks));
- seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d",
- atomic_read(&tcon->stats.cifs_stats.num_opens),
- atomic_read(&tcon->stats.cifs_stats.num_closes),
- atomic_read(&tcon->stats.cifs_stats.num_deletes));
- seq_printf(m, "\nPosix Opens: %d Posix Mkdirs: %d",
- atomic_read(&tcon->stats.cifs_stats.num_posixopens),
- atomic_read(&tcon->stats.cifs_stats.num_posixmkdirs));
- seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
- atomic_read(&tcon->stats.cifs_stats.num_mkdirs),
- atomic_read(&tcon->stats.cifs_stats.num_rmdirs));
- seq_printf(m, "\nRenames: %d T2 Renames %d",
- atomic_read(&tcon->stats.cifs_stats.num_renames),
- atomic_read(&tcon->stats.cifs_stats.num_t2renames));
- seq_printf(m, "\nFindFirst: %d FNext %d FClose %d",
- atomic_read(&tcon->stats.cifs_stats.num_ffirst),
- atomic_read(&tcon->stats.cifs_stats.num_fnext),
- atomic_read(&tcon->stats.cifs_stats.num_fclose));
-}
-
-static void
-cifs_mkdir_setinfo(struct inode *inode, const char *full_path,
- struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
- const unsigned int xid)
-{
- FILE_BASIC_INFO info;
- struct cifsInodeInfo *cifsInode;
- u32 dosattrs;
- int rc;
-
- memset(&info, 0, sizeof(info));
- cifsInode = CIFS_I(inode);
- dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
- info.Attributes = cpu_to_le32(dosattrs);
- rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls,
- cifs_sb);
- if (rc == 0)
- cifsInode->cifsAttrs = dosattrs;
-}
-
-static int cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
- void *buf)
-{
- struct cifs_open_info_data *data = buf;
- FILE_ALL_INFO fi = {};
- int rc;
-
- if (!(oparms->tcon->ses->capabilities & CAP_NT_SMBS))
- rc = SMBLegacyOpen(xid, oparms->tcon, oparms->path,
- oparms->disposition,
- oparms->desired_access,
- oparms->create_options,
- &oparms->fid->netfid, oplock, &fi,
- oparms->cifs_sb->local_nls,
- cifs_remap(oparms->cifs_sb));
- else
- rc = CIFS_open(xid, oparms, oplock, &fi);
-
- if (!rc && data)
- move_cifs_info_to_smb2(&data->fi, &fi);
-
- return rc;
-}
-
-static void
-cifs_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
-{
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- cfile->fid.netfid = fid->netfid;
- cifs_set_oplock_level(cinode, oplock);
- cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
-}
-
-static void
-cifs_close_file(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_fid *fid)
-{
- CIFSSMBClose(xid, tcon, fid->netfid);
-}
-
-static int
-cifs_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_fid *fid)
-{
- return CIFSSMBFlush(xid, tcon, fid->netfid);
-}
-
-static int
-cifs_sync_read(const unsigned int xid, struct cifs_fid *pfid,
- struct cifs_io_parms *parms, unsigned int *bytes_read,
- char **buf, int *buf_type)
-{
- parms->netfid = pfid->netfid;
- return CIFSSMBRead(xid, parms, bytes_read, buf, buf_type);
-}
-
-static int
-cifs_sync_write(const unsigned int xid, struct cifs_fid *pfid,
- struct cifs_io_parms *parms, unsigned int *written,
- struct kvec *iov, unsigned long nr_segs)
-{
-
- parms->netfid = pfid->netfid;
- return CIFSSMBWrite2(xid, parms, written, iov, nr_segs);
-}
-
-static int
-smb_set_file_info(struct inode *inode, const char *full_path,
- FILE_BASIC_INFO *buf, const unsigned int xid)
-{
- int oplock = 0;
- int rc;
- __u32 netpid;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- struct cifsFileInfo *open_file;
- struct cifsInodeInfo *cinode = CIFS_I(inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink = NULL;
- struct cifs_tcon *tcon;
-
- /* if the file is already open for write, just use that fileid */
- open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
- if (open_file) {
- fid.netfid = open_file->fid.netfid;
- netpid = open_file->pid;
- tcon = tlink_tcon(open_file->tlink);
- goto set_via_filehandle;
- }
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink)) {
- rc = PTR_ERR(tlink);
- tlink = NULL;
- goto out;
- }
- tcon = tlink_tcon(tlink);
-
- rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls,
- cifs_sb);
- if (rc == 0) {
- cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
- goto out;
- } else if (rc != -EOPNOTSUPP && rc != -EINVAL) {
- goto out;
- }
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
- .disposition = FILE_OPEN,
- .path = full_path,
- .fid = &fid,
- };
-
- cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n");
- rc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (rc != 0) {
- if (rc == -EIO)
- rc = -EINVAL;
- goto out;
- }
-
- netpid = current->tgid;
-
-set_via_filehandle:
- rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid);
- if (!rc)
- cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
-
- if (open_file == NULL)
- CIFSSMBClose(xid, tcon, fid.netfid);
- else
- cifsFileInfo_put(open_file);
-out:
- if (tlink != NULL)
- cifs_put_tlink(tlink);
- return rc;
-}
-
-static int
-cifs_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile)
-{
- return CIFSSMB_set_compression(xid, tcon, cfile->fid.netfid);
-}
-
-static int
-cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
- const char *path, struct cifs_sb_info *cifs_sb,
- struct cifs_fid *fid, __u16 search_flags,
- struct cifs_search_info *srch_inf)
-{
- int rc;
-
- rc = CIFSFindFirst(xid, tcon, path, cifs_sb,
- &fid->netfid, search_flags, srch_inf, true);
- if (rc)
- cifs_dbg(FYI, "find first failed=%d\n", rc);
- return rc;
-}
-
-static int
-cifs_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_fid *fid, __u16 search_flags,
- struct cifs_search_info *srch_inf)
-{
- return CIFSFindNext(xid, tcon, fid->netfid, search_flags, srch_inf);
-}
-
-static int
-cifs_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_fid *fid)
-{
- return CIFSFindClose(xid, tcon, fid->netfid);
-}
-
-static int
-cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
- __u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
-{
- return CIFSSMBLock(0, tcon, net_fid, current->tgid, 0, 0, 0, 0,
- LOCKING_ANDX_OPLOCK_RELEASE, false, CIFS_CACHE_READ(cinode) ? 1 : 0);
-}
-
-static int
-cifs_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
-{
- int rc = -EOPNOTSUPP;
-
- buf->f_type = CIFS_SUPER_MAGIC;
-
- /*
- * We could add a second check for a QFS Unix capability bit
- */
- if ((tcon->ses->capabilities & CAP_UNIX) &&
- (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability)))
- rc = CIFSSMBQFSPosixInfo(xid, tcon, buf);
-
- /*
- * Only need to call the old QFSInfo if failed on newer one,
- * e.g. by OS/2.
- **/
- if (rc && (tcon->ses->capabilities & CAP_NT_SMBS))
- rc = CIFSSMBQFSInfo(xid, tcon, buf);
-
- /*
- * Some old Windows servers also do not support level 103, retry with
- * older level one if old server failed the previous call or we
- * bypassed it because we detected that this was an older LANMAN sess
- */
- if (rc)
- rc = SMBOldQFSInfo(xid, tcon, buf);
- return rc;
-}
-
-static int
-cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
- __u64 length, __u32 type, int lock, int unlock, bool wait)
-{
- return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->fid.netfid,
- current->tgid, length, offset, unlock, lock,
- (__u8)type, wait, 0);
-}
-
-static int
-cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *searchName, char **symlinkinfo,
- const struct nls_table *nls_codepage)
-{
-#ifdef CONFIG_CIFS_DFS_UPCALL
- int rc;
- struct dfs_info3_param referral = {0};
-
- rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage, &referral,
- 0);
-
- if (!rc) {
- *symlinkinfo = kstrdup(referral.node_name, GFP_KERNEL);
- free_dfs_info_param(&referral);
- if (!*symlinkinfo)
- rc = -ENOMEM;
- }
- return rc;
-#else /* No DFS support */
- return -EREMOTE;
-#endif
-}
-
-static int
-cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- char **target_path, bool is_reparse_point)
-{
- int rc;
- int oplock = 0;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
-
- cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
-
- if (is_reparse_point) {
- cifs_dbg(VFS, "reparse points not handled for SMB1 symlinks\n");
- return -EOPNOTSUPP;
- }
-
- /* Check for unix extensions */
- if (cap_unix(tcon->ses)) {
- rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- if (rc == -EREMOTE)
- rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
- target_path,
- cifs_sb->local_nls);
-
- goto out;
- }
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = FILE_READ_ATTRIBUTES,
- .create_options = cifs_create_options(cifs_sb,
- OPEN_REPARSE_POINT),
- .disposition = FILE_OPEN,
- .path = full_path,
- .fid = &fid,
- };
-
- rc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (rc)
- goto out;
-
- rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path,
- cifs_sb->local_nls);
- if (rc)
- goto out_close;
-
- convert_delimiter(*target_path, '/');
-out_close:
- CIFSSMBClose(xid, tcon, fid.netfid);
-out:
- if (!rc)
- cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
- return rc;
-}
-
-static bool
-cifs_is_read_op(__u32 oplock)
-{
- return oplock == OPLOCK_READ;
-}
-
-static unsigned int
-cifs_wp_retry_size(struct inode *inode)
-{
- return CIFS_SB(inode->i_sb)->ctx->wsize;
-}
-
-static bool
-cifs_dir_needs_close(struct cifsFileInfo *cfile)
-{
- return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
-}
-
-static bool
-cifs_can_echo(struct TCP_Server_Info *server)
-{
- if (server->tcpStatus == CifsGood)
- return true;
-
- return false;
-}
-
-static int
-cifs_make_node(unsigned int xid, struct inode *inode,
- struct dentry *dentry, struct cifs_tcon *tcon,
- const char *full_path, umode_t mode, dev_t dev)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct inode *newinode = NULL;
- int rc = -EPERM;
- struct cifs_open_info_data buf = {};
- struct cifs_io_parms io_parms;
- __u32 oplock = 0;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- unsigned int bytes_written;
- struct win_dev *pdev;
- struct kvec iov[2];
-
- if (tcon->unix_ext) {
- /*
- * SMB1 Unix Extensions: requires server support but
- * works with all special files
- */
- struct cifs_unix_set_info_args args = {
- .mode = mode & ~current_umask(),
- .ctime = NO_CHANGE_64,
- .atime = NO_CHANGE_64,
- .mtime = NO_CHANGE_64,
- .device = dev,
- };
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = current_fsuid();
- args.gid = current_fsgid();
- } else {
- args.uid = INVALID_UID; /* no change */
- args.gid = INVALID_GID; /* no change */
- }
- rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- if (rc)
- return rc;
-
- rc = cifs_get_inode_info_unix(&newinode, full_path,
- inode->i_sb, xid);
-
- if (rc == 0)
- d_instantiate(dentry, newinode);
- return rc;
- }
-
- /*
- * SMB1 SFU emulation: should work with all servers, but only
- * support block and char device (no socket & fifo)
- */
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
- return rc;
-
- if (!S_ISCHR(mode) && !S_ISBLK(mode))
- return rc;
-
- cifs_dbg(FYI, "sfu compat create special file\n");
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = GENERIC_WRITE,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
- CREATE_OPTION_SPECIAL),
- .disposition = FILE_CREATE,
- .path = full_path,
- .fid = &fid,
- };
-
- if (tcon->ses->server->oplocks)
- oplock = REQ_OPLOCK;
- else
- oplock = 0;
- rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
- if (rc)
- return rc;
-
- /*
- * BB Do not bother to decode buf since no local inode yet to put
- * timestamps in, but we can reuse it safely.
- */
-
- pdev = (struct win_dev *)&buf.fi;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
- io_parms.offset = 0;
- io_parms.length = sizeof(struct win_dev);
- iov[1].iov_base = &buf.fi;
- iov[1].iov_len = sizeof(struct win_dev);
- if (S_ISCHR(mode)) {
- memcpy(pdev->type, "IntxCHR", 8);
- pdev->major = cpu_to_le64(MAJOR(dev));
- pdev->minor = cpu_to_le64(MINOR(dev));
- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
- } else if (S_ISBLK(mode)) {
- memcpy(pdev->type, "IntxBLK", 8);
- pdev->major = cpu_to_le64(MAJOR(dev));
- pdev->minor = cpu_to_le64(MINOR(dev));
- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
- }
- tcon->ses->server->ops->close(xid, tcon, &fid);
- d_drop(dentry);
-
- /* FIXME: add code here to set EAs */
-
- cifs_free_open_info(&buf);
- return rc;
-}
-
-
-
-struct smb_version_operations smb1_operations = {
- .send_cancel = send_nt_cancel,
- .compare_fids = cifs_compare_fids,
- .setup_request = cifs_setup_request,
- .setup_async_request = cifs_setup_async_request,
- .check_receive = cifs_check_receive,
- .add_credits = cifs_add_credits,
- .set_credits = cifs_set_credits,
- .get_credits_field = cifs_get_credits_field,
- .get_credits = cifs_get_credits,
- .wait_mtu_credits = cifs_wait_mtu_credits,
- .get_next_mid = cifs_get_next_mid,
- .read_data_offset = cifs_read_data_offset,
- .read_data_length = cifs_read_data_length,
- .map_error = map_smb_to_linux_error,
- .find_mid = cifs_find_mid,
- .check_message = checkSMB,
- .dump_detail = cifs_dump_detail,
- .clear_stats = cifs_clear_stats,
- .print_stats = cifs_print_stats,
- .is_oplock_break = is_valid_oplock_break,
- .downgrade_oplock = cifs_downgrade_oplock,
- .check_trans2 = cifs_check_trans2,
- .need_neg = cifs_need_neg,
- .negotiate = cifs_negotiate,
- .negotiate_wsize = cifs_negotiate_wsize,
- .negotiate_rsize = cifs_negotiate_rsize,
- .sess_setup = CIFS_SessSetup,
- .logoff = CIFSSMBLogoff,
- .tree_connect = CIFSTCon,
- .tree_disconnect = CIFSSMBTDis,
- .get_dfs_refer = CIFSGetDFSRefer,
- .qfs_tcon = cifs_qfs_tcon,
- .is_path_accessible = cifs_is_path_accessible,
- .can_echo = cifs_can_echo,
- .query_path_info = cifs_query_path_info,
- .query_file_info = cifs_query_file_info,
- .get_srv_inum = cifs_get_srv_inum,
- .set_path_size = CIFSSMBSetEOF,
- .set_file_size = CIFSSMBSetFileSize,
- .set_file_info = smb_set_file_info,
- .set_compression = cifs_set_compression,
- .echo = CIFSSMBEcho,
- .mkdir = CIFSSMBMkDir,
- .mkdir_setinfo = cifs_mkdir_setinfo,
- .rmdir = CIFSSMBRmDir,
- .unlink = CIFSSMBDelFile,
- .rename_pending_delete = cifs_rename_pending_delete,
- .rename = CIFSSMBRename,
- .create_hardlink = CIFSCreateHardLink,
- .query_symlink = cifs_query_symlink,
- .open = cifs_open_file,
- .set_fid = cifs_set_fid,
- .close = cifs_close_file,
- .flush = cifs_flush_file,
- .async_readv = cifs_async_readv,
- .async_writev = cifs_async_writev,
- .sync_read = cifs_sync_read,
- .sync_write = cifs_sync_write,
- .query_dir_first = cifs_query_dir_first,
- .query_dir_next = cifs_query_dir_next,
- .close_dir = cifs_close_dir,
- .calc_smb_size = smbCalcSize,
- .oplock_response = cifs_oplock_response,
- .queryfs = cifs_queryfs,
- .mand_lock = cifs_mand_lock,
- .mand_unlock_range = cifs_unlock_range,
- .push_mand_locks = cifs_push_mandatory_locks,
- .query_mf_symlink = cifs_query_mf_symlink,
- .create_mf_symlink = cifs_create_mf_symlink,
- .is_read_op = cifs_is_read_op,
- .wp_retry_size = cifs_wp_retry_size,
- .dir_needs_close = cifs_dir_needs_close,
- .select_sectype = cifs_select_sectype,
-#ifdef CONFIG_CIFS_XATTR
- .query_all_EAs = CIFSSMBQAllEAs,
- .set_EA = CIFSSMBSetEA,
-#endif /* CIFS_XATTR */
- .get_acl = get_cifs_acl,
- .get_acl_by_fid = get_cifs_acl_by_fid,
- .set_acl = set_cifs_acl,
- .make_node = cifs_make_node,
-};
-
-struct smb_version_values smb1_values = {
- .version_string = SMB1_VERSION_STRING,
- .protocol_id = SMB10_PROT_ID,
- .large_lock_type = LOCKING_ANDX_LARGE_FILES,
- .exclusive_lock_type = 0,
- .shared_lock_type = LOCKING_ANDX_SHARED_LOCK,
- .unlock_lock_type = 0,
- .header_preamble_size = 4,
- .header_size = sizeof(struct smb_hdr),
- .max_header_size = MAX_CIFS_HDR_SIZE,
- .read_rsp_size = sizeof(READ_RSP),
- .lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX),
- .cap_unix = CAP_UNIX,
- .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND,
- .cap_large_files = CAP_LARGE_FILES,
- .signing_enabled = SECMODE_SIGN_ENABLED,
- .signing_required = SECMODE_SIGN_REQUIRED,
-};
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
deleted file mode 100644
index ba6cc50af390..000000000000
--- a/fs/cifs/smb2file.c
+++ /dev/null
@@ -1,371 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002, 2011
- * Author(s): Steve French (sfrench@us.ibm.com),
- * Pavel Shilovsky ((pshilovsky@samba.org) 2012
- *
- */
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <asm/div64.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "cifs_unicode.h"
-#include "fscache.h"
-#include "smb2proto.h"
-#include "smb2status.h"
-
-static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov)
-{
- struct smb2_err_rsp *err = iov->iov_base;
- struct smb2_symlink_err_rsp *sym = ERR_PTR(-EINVAL);
- u32 len;
-
- if (err->ErrorContextCount) {
- struct smb2_error_context_rsp *p, *end;
-
- len = (u32)err->ErrorContextCount * (offsetof(struct smb2_error_context_rsp,
- ErrorContextData) +
- sizeof(struct smb2_symlink_err_rsp));
- if (le32_to_cpu(err->ByteCount) < len || iov->iov_len < len + sizeof(*err))
- return ERR_PTR(-EINVAL);
-
- p = (struct smb2_error_context_rsp *)err->ErrorData;
- end = (struct smb2_error_context_rsp *)((u8 *)err + iov->iov_len);
- do {
- if (le32_to_cpu(p->ErrorId) == SMB2_ERROR_ID_DEFAULT) {
- sym = (struct smb2_symlink_err_rsp *)&p->ErrorContextData;
- break;
- }
- cifs_dbg(FYI, "%s: skipping unhandled error context: 0x%x\n",
- __func__, le32_to_cpu(p->ErrorId));
-
- len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8);
- p = (struct smb2_error_context_rsp *)((u8 *)&p->ErrorContextData + len);
- } while (p < end);
- } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) &&
- iov->iov_len >= SMB2_SYMLINK_STRUCT_SIZE) {
- sym = (struct smb2_symlink_err_rsp *)err->ErrorData;
- }
-
- if (!IS_ERR(sym) && (le32_to_cpu(sym->SymLinkErrorTag) != SYMLINK_ERROR_TAG ||
- le32_to_cpu(sym->ReparseTag) != IO_REPARSE_TAG_SYMLINK))
- sym = ERR_PTR(-EINVAL);
-
- return sym;
-}
-
-int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path)
-{
- struct smb2_symlink_err_rsp *sym;
- unsigned int sub_offs, sub_len;
- unsigned int print_offs, print_len;
- char *s;
-
- if (!cifs_sb || !iov || !iov->iov_base || !iov->iov_len || !path)
- return -EINVAL;
-
- sym = symlink_data(iov);
- if (IS_ERR(sym))
- return PTR_ERR(sym);
-
- sub_len = le16_to_cpu(sym->SubstituteNameLength);
- sub_offs = le16_to_cpu(sym->SubstituteNameOffset);
- print_len = le16_to_cpu(sym->PrintNameLength);
- print_offs = le16_to_cpu(sym->PrintNameOffset);
-
- if (iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offs + sub_len ||
- iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + print_offs + print_len)
- return -EINVAL;
-
- s = cifs_strndup_from_utf16((char *)sym->PathBuffer + sub_offs, sub_len, true,
- cifs_sb->local_nls);
- if (!s)
- return -ENOMEM;
- convert_delimiter(s, '/');
- cifs_dbg(FYI, "%s: symlink target: %s\n", __func__, s);
-
- *path = s;
- return 0;
-}
-
-int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, void *buf)
-{
- int rc;
- __le16 *smb2_path;
- __u8 smb2_oplock;
- struct cifs_open_info_data *data = buf;
- struct smb2_file_all_info file_info = {};
- struct smb2_file_all_info *smb2_data = data ? &file_info : NULL;
- struct kvec err_iov = {};
- int err_buftype = CIFS_NO_BUFFER;
- struct cifs_fid *fid = oparms->fid;
- struct network_resiliency_req nr_ioctl_req;
-
- smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb);
- if (smb2_path == NULL)
- return -ENOMEM;
-
- oparms->desired_access |= FILE_READ_ATTRIBUTES;
- smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH;
-
- rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov,
- &err_buftype);
- if (rc && data) {
- struct smb2_hdr *hdr = err_iov.iov_base;
-
- if (unlikely(!err_iov.iov_base || err_buftype == CIFS_NO_BUFFER))
- goto out;
- if (hdr->Status == STATUS_STOPPED_ON_SYMLINK) {
- rc = smb2_parse_symlink_response(oparms->cifs_sb, &err_iov,
- &data->symlink_target);
- if (!rc) {
- memset(smb2_data, 0, sizeof(*smb2_data));
- oparms->create_options |= OPEN_REPARSE_POINT;
- rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data,
- NULL, NULL, NULL);
- oparms->create_options &= ~OPEN_REPARSE_POINT;
- }
- }
- }
-
- if (rc)
- goto out;
-
- if (oparms->tcon->use_resilient) {
- /* default timeout is 0, servers pick default (120 seconds) */
- nr_ioctl_req.Timeout =
- cpu_to_le32(oparms->tcon->handle_timeout);
- nr_ioctl_req.Reserved = 0;
- rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
- fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
- (char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
- CIFSMaxBufSize, NULL, NULL /* no return info */);
- if (rc == -EOPNOTSUPP) {
- cifs_dbg(VFS,
- "resiliency not supported by server, disabling\n");
- oparms->tcon->use_resilient = false;
- } else if (rc)
- cifs_dbg(FYI, "error %d setting resiliency\n", rc);
-
- rc = 0;
- }
-
- if (smb2_data) {
- /* if open response does not have IndexNumber field - get it */
- if (smb2_data->IndexNumber == 0) {
- rc = SMB2_get_srv_num(xid, oparms->tcon,
- fid->persistent_fid,
- fid->volatile_fid,
- &smb2_data->IndexNumber);
- if (rc) {
- /*
- * let get_inode_info disable server inode
- * numbers
- */
- smb2_data->IndexNumber = 0;
- rc = 0;
- }
- }
- memcpy(&data->fi, smb2_data, sizeof(data->fi));
- }
-
- *oplock = smb2_oplock;
-out:
- free_rsp_buf(err_buftype, err_iov.iov_base);
- kfree(smb2_path);
- return rc;
-}
-
-int
-smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
- const unsigned int xid)
-{
- int rc = 0, stored_rc;
- unsigned int max_num, num = 0, max_buf;
- struct smb2_lock_element *buf, *cur;
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- struct cifsLockInfo *li, *tmp;
- __u64 length = 1 + flock->fl_end - flock->fl_start;
- struct list_head tmp_llist;
-
- INIT_LIST_HEAD(&tmp_llist);
-
- /*
- * Accessing maxBuf is racy with cifs_reconnect - need to store value
- * and check it before using.
- */
- max_buf = tcon->ses->server->maxBuf;
- if (max_buf < sizeof(struct smb2_lock_element))
- return -EINVAL;
-
- BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
- max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
- max_num = max_buf / sizeof(struct smb2_lock_element);
- buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- cur = buf;
-
- cifs_down_write(&cinode->lock_sem);
- list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
- if (flock->fl_start > li->offset ||
- (flock->fl_start + length) <
- (li->offset + li->length))
- continue;
- if (current->tgid != li->pid)
- /*
- * flock and OFD lock are associated with an open
- * file description, not the process.
- */
- if (!(flock->fl_flags & (FL_FLOCK | FL_OFDLCK)))
- continue;
- if (cinode->can_cache_brlcks) {
- /*
- * We can cache brlock requests - simply remove a lock
- * from the file's list.
- */
- list_del(&li->llist);
- cifs_del_lock_waiters(li);
- kfree(li);
- continue;
- }
- cur->Length = cpu_to_le64(li->length);
- cur->Offset = cpu_to_le64(li->offset);
- cur->Flags = cpu_to_le32(SMB2_LOCKFLAG_UNLOCK);
- /*
- * We need to save a lock here to let us add it again to the
- * file's list if the unlock range request fails on the server.
- */
- list_move(&li->llist, &tmp_llist);
- if (++num == max_num) {
- stored_rc = smb2_lockv(xid, tcon,
- cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- current->tgid, num, buf);
- if (stored_rc) {
- /*
- * We failed on the unlock range request - add
- * all locks from the tmp list to the head of
- * the file's list.
- */
- cifs_move_llist(&tmp_llist,
- &cfile->llist->locks);
- rc = stored_rc;
- } else
- /*
- * The unlock range request succeed - free the
- * tmp list.
- */
- cifs_free_llist(&tmp_llist);
- cur = buf;
- num = 0;
- } else
- cur++;
- }
- if (num) {
- stored_rc = smb2_lockv(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, current->tgid,
- num, buf);
- if (stored_rc) {
- cifs_move_llist(&tmp_llist, &cfile->llist->locks);
- rc = stored_rc;
- } else
- cifs_free_llist(&tmp_llist);
- }
- up_write(&cinode->lock_sem);
-
- kfree(buf);
- return rc;
-}
-
-static int
-smb2_push_mand_fdlocks(struct cifs_fid_locks *fdlocks, const unsigned int xid,
- struct smb2_lock_element *buf, unsigned int max_num)
-{
- int rc = 0, stored_rc;
- struct cifsFileInfo *cfile = fdlocks->cfile;
- struct cifsLockInfo *li;
- unsigned int num = 0;
- struct smb2_lock_element *cur = buf;
- struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
-
- list_for_each_entry(li, &fdlocks->locks, llist) {
- cur->Length = cpu_to_le64(li->length);
- cur->Offset = cpu_to_le64(li->offset);
- cur->Flags = cpu_to_le32(li->type |
- SMB2_LOCKFLAG_FAIL_IMMEDIATELY);
- if (++num == max_num) {
- stored_rc = smb2_lockv(xid, tcon,
- cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- current->tgid, num, buf);
- if (stored_rc)
- rc = stored_rc;
- cur = buf;
- num = 0;
- } else
- cur++;
- }
- if (num) {
- stored_rc = smb2_lockv(xid, tcon,
- cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- current->tgid, num, buf);
- if (stored_rc)
- rc = stored_rc;
- }
-
- return rc;
-}
-
-int
-smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
-{
- int rc = 0, stored_rc;
- unsigned int xid;
- unsigned int max_num, max_buf;
- struct smb2_lock_element *buf;
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- struct cifs_fid_locks *fdlocks;
-
- xid = get_xid();
-
- /*
- * Accessing maxBuf is racy with cifs_reconnect - need to store value
- * and check it for zero before using.
- */
- max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf;
- if (max_buf < sizeof(struct smb2_lock_element)) {
- free_xid(xid);
- return -EINVAL;
- }
-
- BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
- max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
- max_num = max_buf / sizeof(struct smb2_lock_element);
- buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
- if (!buf) {
- free_xid(xid);
- return -ENOMEM;
- }
-
- list_for_each_entry(fdlocks, &cinode->llist, llist) {
- stored_rc = smb2_push_mand_fdlocks(fdlocks, xid, buf, max_num);
- if (stored_rc)
- rc = stored_rc;
- }
-
- kfree(buf);
- free_xid(xid);
- return rc;
-}
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
deleted file mode 100644
index 82e916ad167c..000000000000
--- a/fs/cifs/smb2glob.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Definitions for various global variables and structures
- *
- * Copyright (C) International Business Machines Corp., 2002, 2011
- * Etersoft, 2012
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Jeremy Allison (jra@samba.org)
- * Pavel Shilovsky (pshilovsky@samba.org) 2012
- *
- */
-#ifndef _SMB2_GLOB_H
-#define _SMB2_GLOB_H
-
-/*
- *****************************************************************
- * Constants go here
- *****************************************************************
- */
-
-/*
- * Identifiers for functions that use the open, operation, close pattern
- * in smb2inode.c:smb2_compound_op()
- */
-#define SMB2_OP_SET_DELETE 1
-#define SMB2_OP_SET_INFO 2
-#define SMB2_OP_QUERY_INFO 3
-#define SMB2_OP_QUERY_DIR 4
-#define SMB2_OP_MKDIR 5
-#define SMB2_OP_RENAME 6
-#define SMB2_OP_DELETE 7
-#define SMB2_OP_HARDLINK 8
-#define SMB2_OP_SET_EOF 9
-#define SMB2_OP_RMDIR 10
-#define SMB2_OP_POSIX_QUERY_INFO 11
-
-/* Used when constructing chained read requests. */
-#define CHAINED_REQUEST 1
-#define START_OF_CHAIN 2
-#define END_OF_CHAIN 4
-#define RELATED_REQUEST 8
-
-#endif /* _SMB2_GLOB_H */
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
deleted file mode 100644
index c97e049e29dd..000000000000
--- a/fs/cifs/smb2inode.c
+++ /dev/null
@@ -1,799 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002, 2011
- * Etersoft, 2012
- * Author(s): Pavel Shilovsky (pshilovsky@samba.org),
- * Steve French (sfrench@us.ibm.com)
- *
- */
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <asm/div64.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "cifs_unicode.h"
-#include "fscache.h"
-#include "smb2glob.h"
-#include "smb2pdu.h"
-#include "smb2proto.h"
-#include "cached_dir.h"
-#include "smb2status.h"
-
-static void
-free_set_inf_compound(struct smb_rqst *rqst)
-{
- if (rqst[1].rq_iov)
- SMB2_set_info_free(&rqst[1]);
- if (rqst[2].rq_iov)
- SMB2_close_free(&rqst[2]);
-}
-
-
-struct cop_vars {
- struct cifs_open_parms oparms;
- struct kvec rsp_iov[3];
- struct smb_rqst rqst[3];
- struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
- struct kvec qi_iov[1];
- struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
- struct kvec close_iov[1];
- struct smb2_file_rename_info rename_info;
- struct smb2_file_link_info link_info;
-};
-
-/*
- * note: If cfile is passed, the reference to it is dropped here.
- * So make sure that you do not reuse cfile after return from this func.
- *
- * If passing @err_iov and @err_buftype, ensure to make them both large enough (>= 3) to hold all
- * error responses. Caller is also responsible for freeing them up.
- */
-static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- __u32 desired_access, __u32 create_disposition, __u32 create_options,
- umode_t mode, void *ptr, int command, struct cifsFileInfo *cfile,
- struct kvec *err_iov, int *err_buftype)
-{
- struct cop_vars *vars = NULL;
- struct kvec *rsp_iov;
- struct smb_rqst *rqst;
- int rc;
- __le16 *utf16_path = NULL;
- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_fid fid;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server;
- int num_rqst = 0;
- int resp_buftype[3];
- struct smb2_query_info_rsp *qi_rsp = NULL;
- struct cifs_open_info_data *idata;
- int flags = 0;
- __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0};
- unsigned int size[2];
- void *data[2];
- int len;
-
- vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
- if (vars == NULL)
- return -ENOMEM;
- rqst = &vars->rqst[0];
- rsp_iov = &vars->rsp_iov[0];
-
- server = cifs_pick_channel(ses);
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
-
- /* We already have a handle so we can skip the open */
- if (cfile)
- goto after_open;
-
- /* Open */
- utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
- if (!utf16_path) {
- rc = -ENOMEM;
- goto finished;
- }
-
- vars->oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = full_path,
- .desired_access = desired_access,
- .disposition = create_disposition,
- .create_options = cifs_create_options(cifs_sb, create_options),
- .fid = &fid,
- .mode = mode,
- .cifs_sb = cifs_sb,
- };
-
- rqst[num_rqst].rq_iov = &vars->open_iov[0];
- rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE;
- rc = SMB2_open_init(tcon, server,
- &rqst[num_rqst], &oplock, &vars->oparms,
- utf16_path);
- kfree(utf16_path);
- if (rc)
- goto finished;
-
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- after_open:
- num_rqst++;
- rc = 0;
-
- /* Operation */
- switch (command) {
- case SMB2_OP_QUERY_INFO:
- rqst[num_rqst].rq_iov = &vars->qi_iov[0];
- rqst[num_rqst].rq_nvec = 1;
-
- if (cfile)
- rc = SMB2_query_info_init(tcon, server,
- &rqst[num_rqst],
- cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- FILE_ALL_INFORMATION,
- SMB2_O_INFO_FILE, 0,
- sizeof(struct smb2_file_all_info) +
- PATH_MAX * 2, 0, NULL);
- else {
- rc = SMB2_query_info_init(tcon, server,
- &rqst[num_rqst],
- COMPOUND_FID,
- COMPOUND_FID,
- FILE_ALL_INFORMATION,
- SMB2_O_INFO_FILE, 0,
- sizeof(struct smb2_file_all_info) +
- PATH_MAX * 2, 0, NULL);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
- }
-
- if (rc)
- goto finished;
- num_rqst++;
- trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
- full_path);
- break;
- case SMB2_OP_POSIX_QUERY_INFO:
- rqst[num_rqst].rq_iov = &vars->qi_iov[0];
- rqst[num_rqst].rq_nvec = 1;
-
- if (cfile)
- rc = SMB2_query_info_init(tcon, server,
- &rqst[num_rqst],
- cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- SMB_FIND_FILE_POSIX_INFO,
- SMB2_O_INFO_FILE, 0,
- /* TBD: fix following to allow for longer SIDs */
- sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) +
- (sizeof(struct cifs_sid) * 2), 0, NULL);
- else {
- rc = SMB2_query_info_init(tcon, server,
- &rqst[num_rqst],
- COMPOUND_FID,
- COMPOUND_FID,
- SMB_FIND_FILE_POSIX_INFO,
- SMB2_O_INFO_FILE, 0,
- sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) +
- (sizeof(struct cifs_sid) * 2), 0, NULL);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
- }
-
- if (rc)
- goto finished;
- num_rqst++;
- trace_smb3_posix_query_info_compound_enter(xid, ses->Suid, tcon->tid, full_path);
- break;
- case SMB2_OP_DELETE:
- trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);
- break;
- case SMB2_OP_MKDIR:
- /*
- * Directories are created through parameters in the
- * SMB2_open() call.
- */
- trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path);
- break;
- case SMB2_OP_RMDIR:
- rqst[num_rqst].rq_iov = &vars->si_iov[0];
- rqst[num_rqst].rq_nvec = 1;
-
- size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
- data[0] = &delete_pending[0];
-
- rc = SMB2_set_info_init(tcon, server,
- &rqst[num_rqst], COMPOUND_FID,
- COMPOUND_FID, current->tgid,
- FILE_DISPOSITION_INFORMATION,
- SMB2_O_INFO_FILE, 0, data, size);
- if (rc)
- goto finished;
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst++]);
- trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path);
- break;
- case SMB2_OP_SET_EOF:
- rqst[num_rqst].rq_iov = &vars->si_iov[0];
- rqst[num_rqst].rq_nvec = 1;
-
- size[0] = 8; /* sizeof __le64 */
- data[0] = ptr;
-
- if (cfile) {
- rc = SMB2_set_info_init(tcon, server,
- &rqst[num_rqst],
- cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- current->tgid,
- FILE_END_OF_FILE_INFORMATION,
- SMB2_O_INFO_FILE, 0,
- data, size);
- } else {
- rc = SMB2_set_info_init(tcon, server,
- &rqst[num_rqst],
- COMPOUND_FID,
- COMPOUND_FID,
- current->tgid,
- FILE_END_OF_FILE_INFORMATION,
- SMB2_O_INFO_FILE, 0,
- data, size);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
- }
- if (rc)
- goto finished;
- num_rqst++;
- trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
- break;
- case SMB2_OP_SET_INFO:
- rqst[num_rqst].rq_iov = &vars->si_iov[0];
- rqst[num_rqst].rq_nvec = 1;
-
-
- size[0] = sizeof(FILE_BASIC_INFO);
- data[0] = ptr;
-
- if (cfile)
- rc = SMB2_set_info_init(tcon, server,
- &rqst[num_rqst],
- cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, current->tgid,
- FILE_BASIC_INFORMATION,
- SMB2_O_INFO_FILE, 0, data, size);
- else {
- rc = SMB2_set_info_init(tcon, server,
- &rqst[num_rqst],
- COMPOUND_FID,
- COMPOUND_FID, current->tgid,
- FILE_BASIC_INFORMATION,
- SMB2_O_INFO_FILE, 0, data, size);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
- }
-
- if (rc)
- goto finished;
- num_rqst++;
- trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid,
- full_path);
- break;
- case SMB2_OP_RENAME:
- rqst[num_rqst].rq_iov = &vars->si_iov[0];
- rqst[num_rqst].rq_nvec = 2;
-
- len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
-
- vars->rename_info.ReplaceIfExists = 1;
- vars->rename_info.RootDirectory = 0;
- vars->rename_info.FileNameLength = cpu_to_le32(len);
-
- size[0] = sizeof(struct smb2_file_rename_info);
- data[0] = &vars->rename_info;
-
- size[1] = len + 2 /* null */;
- data[1] = (__le16 *)ptr;
-
- if (cfile)
- rc = SMB2_set_info_init(tcon, server,
- &rqst[num_rqst],
- cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- current->tgid, FILE_RENAME_INFORMATION,
- SMB2_O_INFO_FILE, 0, data, size);
- else {
- rc = SMB2_set_info_init(tcon, server,
- &rqst[num_rqst],
- COMPOUND_FID, COMPOUND_FID,
- current->tgid, FILE_RENAME_INFORMATION,
- SMB2_O_INFO_FILE, 0, data, size);
- if (!rc) {
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst]);
- }
- }
- if (rc)
- goto finished;
- num_rqst++;
- trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
- break;
- case SMB2_OP_HARDLINK:
- rqst[num_rqst].rq_iov = &vars->si_iov[0];
- rqst[num_rqst].rq_nvec = 2;
-
- len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
-
- vars->link_info.ReplaceIfExists = 0;
- vars->link_info.RootDirectory = 0;
- vars->link_info.FileNameLength = cpu_to_le32(len);
-
- size[0] = sizeof(struct smb2_file_link_info);
- data[0] = &vars->link_info;
-
- size[1] = len + 2 /* null */;
- data[1] = (__le16 *)ptr;
-
- rc = SMB2_set_info_init(tcon, server,
- &rqst[num_rqst], COMPOUND_FID,
- COMPOUND_FID, current->tgid,
- FILE_LINK_INFORMATION,
- SMB2_O_INFO_FILE, 0, data, size);
- if (rc)
- goto finished;
- smb2_set_next_command(tcon, &rqst[num_rqst]);
- smb2_set_related(&rqst[num_rqst++]);
- trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path);
- break;
- default:
- cifs_dbg(VFS, "Invalid command\n");
- rc = -EINVAL;
- }
- if (rc)
- goto finished;
-
- /* We already have a handle so we can skip the close */
- if (cfile)
- goto after_close;
- /* Close */
- flags |= CIFS_CP_CREATE_CLOSE_OP;
- rqst[num_rqst].rq_iov = &vars->close_iov[0];
- rqst[num_rqst].rq_nvec = 1;
- rc = SMB2_close_init(tcon, server,
- &rqst[num_rqst], COMPOUND_FID,
- COMPOUND_FID, false);
- smb2_set_related(&rqst[num_rqst]);
- if (rc)
- goto finished;
- after_close:
- num_rqst++;
-
- if (cfile) {
- rc = compound_send_recv(xid, ses, server,
- flags, num_rqst - 2,
- &rqst[1], &resp_buftype[1],
- &rsp_iov[1]);
- } else
- rc = compound_send_recv(xid, ses, server,
- flags, num_rqst,
- rqst, resp_buftype,
- rsp_iov);
-
- finished:
- if (cfile)
- cifsFileInfo_put(cfile);
-
- SMB2_open_free(&rqst[0]);
- if (rc == -EREMCHG) {
- pr_warn_once("server share %s deleted\n", tcon->tree_name);
- tcon->need_reconnect = true;
- }
-
- switch (command) {
- case SMB2_OP_QUERY_INFO:
- idata = ptr;
- if (rc == 0 && cfile && cfile->symlink_target) {
- idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
- if (!idata->symlink_target)
- rc = -ENOMEM;
- }
- if (rc == 0) {
- qi_rsp = (struct smb2_query_info_rsp *)
- rsp_iov[1].iov_base;
- rc = smb2_validate_and_copy_iov(
- le16_to_cpu(qi_rsp->OutputBufferOffset),
- le32_to_cpu(qi_rsp->OutputBufferLength),
- &rsp_iov[1], sizeof(idata->fi), (char *)&idata->fi);
- }
- if (rqst[1].rq_iov)
- SMB2_query_info_free(&rqst[1]);
- if (rqst[2].rq_iov)
- SMB2_close_free(&rqst[2]);
- if (rc)
- trace_smb3_query_info_compound_err(xid, ses->Suid,
- tcon->tid, rc);
- else
- trace_smb3_query_info_compound_done(xid, ses->Suid,
- tcon->tid);
- break;
- case SMB2_OP_POSIX_QUERY_INFO:
- idata = ptr;
- if (rc == 0 && cfile && cfile->symlink_target) {
- idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
- if (!idata->symlink_target)
- rc = -ENOMEM;
- }
- if (rc == 0) {
- qi_rsp = (struct smb2_query_info_rsp *)
- rsp_iov[1].iov_base;
- rc = smb2_validate_and_copy_iov(
- le16_to_cpu(qi_rsp->OutputBufferOffset),
- le32_to_cpu(qi_rsp->OutputBufferLength),
- &rsp_iov[1], sizeof(idata->posix_fi) /* add SIDs */,
- (char *)&idata->posix_fi);
- }
- if (rqst[1].rq_iov)
- SMB2_query_info_free(&rqst[1]);
- if (rqst[2].rq_iov)
- SMB2_close_free(&rqst[2]);
- if (rc)
- trace_smb3_posix_query_info_compound_err(xid, ses->Suid, tcon->tid, rc);
- else
- trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid);
- break;
- case SMB2_OP_DELETE:
- if (rc)
- trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc);
- else
- trace_smb3_delete_done(xid, ses->Suid, tcon->tid);
- if (rqst[1].rq_iov)
- SMB2_close_free(&rqst[1]);
- break;
- case SMB2_OP_MKDIR:
- if (rc)
- trace_smb3_mkdir_err(xid, ses->Suid, tcon->tid, rc);
- else
- trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid);
- if (rqst[1].rq_iov)
- SMB2_close_free(&rqst[1]);
- break;
- case SMB2_OP_HARDLINK:
- if (rc)
- trace_smb3_hardlink_err(xid, ses->Suid, tcon->tid, rc);
- else
- trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid);
- free_set_inf_compound(rqst);
- break;
- case SMB2_OP_RENAME:
- if (rc)
- trace_smb3_rename_err(xid, ses->Suid, tcon->tid, rc);
- else
- trace_smb3_rename_done(xid, ses->Suid, tcon->tid);
- free_set_inf_compound(rqst);
- break;
- case SMB2_OP_RMDIR:
- if (rc)
- trace_smb3_rmdir_err(xid, ses->Suid, tcon->tid, rc);
- else
- trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid);
- free_set_inf_compound(rqst);
- break;
- case SMB2_OP_SET_EOF:
- if (rc)
- trace_smb3_set_eof_err(xid, ses->Suid, tcon->tid, rc);
- else
- trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid);
- free_set_inf_compound(rqst);
- break;
- case SMB2_OP_SET_INFO:
- if (rc)
- trace_smb3_set_info_compound_err(xid, ses->Suid,
- tcon->tid, rc);
- else
- trace_smb3_set_info_compound_done(xid, ses->Suid,
- tcon->tid);
- free_set_inf_compound(rqst);
- break;
- }
-
- if (rc && err_iov && err_buftype) {
- memcpy(err_iov, rsp_iov, 3 * sizeof(*err_iov));
- memcpy(err_buftype, resp_buftype, 3 * sizeof(*err_buftype));
- } else {
- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
- }
- kfree(vars);
- return rc;
-}
-
-int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse)
-{
- __u32 create_options = 0;
- struct cifsFileInfo *cfile;
- struct cached_fid *cfid = NULL;
- struct kvec err_iov[3] = {};
- int err_buftype[3] = {};
- bool islink;
- int rc, rc2;
-
- *adjust_tz = false;
- *reparse = false;
-
- if (strcmp(full_path, ""))
- rc = -ENOENT;
- else
- rc = open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid);
- /* If it is a root and its handle is cached then use it */
- if (!rc) {
- if (cfid->file_all_info_is_valid) {
- memcpy(&data->fi, &cfid->file_all_info, sizeof(data->fi));
- } else {
- rc = SMB2_query_info(xid, tcon, cfid->fid.persistent_fid,
- cfid->fid.volatile_fid, &data->fi);
- }
- close_cached_dir(cfid);
- return rc;
- }
-
- cifs_get_readable_path(tcon, full_path, &cfile);
- rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
- create_options, ACL_NO_MODE, data, SMB2_OP_QUERY_INFO, cfile,
- err_iov, err_buftype);
- if (rc) {
- struct smb2_hdr *hdr = err_iov[0].iov_base;
-
- if (unlikely(!hdr || err_buftype[0] == CIFS_NO_BUFFER))
- goto out;
- if (rc == -EOPNOTSUPP && hdr->Command == SMB2_CREATE &&
- hdr->Status == STATUS_STOPPED_ON_SYMLINK) {
- rc = smb2_parse_symlink_response(cifs_sb, err_iov,
- &data->symlink_target);
- if (rc)
- goto out;
-
- *reparse = true;
- create_options |= OPEN_REPARSE_POINT;
-
- /* Failed on a symbolic link - query a reparse point info */
- cifs_get_readable_path(tcon, full_path, &cfile);
- rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
- FILE_READ_ATTRIBUTES, FILE_OPEN,
- create_options, ACL_NO_MODE, data,
- SMB2_OP_QUERY_INFO, cfile, NULL, NULL);
- goto out;
- } else if (rc != -EREMOTE && hdr->Status == STATUS_OBJECT_NAME_INVALID) {
- rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
- full_path, &islink);
- if (rc2) {
- rc = rc2;
- goto out;
- }
- if (islink)
- rc = -EREMOTE;
- }
- if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb &&
- (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS))
- rc = -EOPNOTSUPP;
- }
-
-out:
- free_rsp_buf(err_buftype[0], err_iov[0].iov_base);
- free_rsp_buf(err_buftype[1], err_iov[1].iov_base);
- free_rsp_buf(err_buftype[2], err_iov[2].iov_base);
- return rc;
-}
-
-
-int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse)
-{
- int rc;
- __u32 create_options = 0;
- struct cifsFileInfo *cfile;
- struct kvec err_iov[3] = {};
- int err_buftype[3] = {};
-
- *adjust_tz = false;
- *reparse = false;
-
- /*
- * BB TODO: Add support for using the cached root handle.
- * Create SMB2_query_posix_info worker function to do non-compounded query
- * when we already have an open file handle for this. For now this is fast enough
- * (always using the compounded version).
- */
-
- cifs_get_readable_path(tcon, full_path, &cfile);
- rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
- create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile,
- err_iov, err_buftype);
- if (rc == -EOPNOTSUPP) {
- /* BB TODO: When support for special files added to Samba re-verify this path */
- if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER &&
- ((struct smb2_hdr *)err_iov[0].iov_base)->Command == SMB2_CREATE &&
- ((struct smb2_hdr *)err_iov[0].iov_base)->Status == STATUS_STOPPED_ON_SYMLINK) {
- rc = smb2_parse_symlink_response(cifs_sb, err_iov, &data->symlink_target);
- if (rc)
- goto out;
- }
- *reparse = true;
- create_options |= OPEN_REPARSE_POINT;
-
- /* Failed on a symbolic link - query a reparse point info */
- cifs_get_readable_path(tcon, full_path, &cfile);
- rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES,
- FILE_OPEN, create_options, ACL_NO_MODE, data,
- SMB2_OP_POSIX_QUERY_INFO, cfile, NULL, NULL);
- }
-
-out:
- free_rsp_buf(err_buftype[0], err_iov[0].iov_base);
- free_rsp_buf(err_buftype[1], err_iov[1].iov_base);
- free_rsp_buf(err_buftype[2], err_iov[2].iov_base);
- return rc;
-}
-
-int
-smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
- struct cifs_tcon *tcon, const char *name,
- struct cifs_sb_info *cifs_sb)
-{
- return smb2_compound_op(xid, tcon, cifs_sb, name,
- FILE_WRITE_ATTRIBUTES, FILE_CREATE,
- CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR,
- NULL, NULL, NULL);
-}
-
-void
-smb2_mkdir_setinfo(struct inode *inode, const char *name,
- struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
- const unsigned int xid)
-{
- FILE_BASIC_INFO data;
- struct cifsInodeInfo *cifs_i;
- struct cifsFileInfo *cfile;
- u32 dosattrs;
- int tmprc;
-
- memset(&data, 0, sizeof(data));
- cifs_i = CIFS_I(inode);
- dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
- data.Attributes = cpu_to_le32(dosattrs);
- cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
- tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
- FILE_WRITE_ATTRIBUTES, FILE_CREATE,
- CREATE_NOT_FILE, ACL_NO_MODE,
- &data, SMB2_OP_SET_INFO, cfile, NULL, NULL);
- if (tmprc == 0)
- cifs_i->cifsAttrs = dosattrs;
-}
-
-int
-smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
- struct cifs_sb_info *cifs_sb)
-{
- drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
- return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
- CREATE_NOT_FILE, ACL_NO_MODE,
- NULL, SMB2_OP_RMDIR, NULL, NULL, NULL);
-}
-
-int
-smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
- struct cifs_sb_info *cifs_sb)
-{
- return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
- CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
- ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL, NULL, NULL);
-}
-
-static int
-smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb, __u32 access, int command,
- struct cifsFileInfo *cfile)
-{
- __le16 *smb2_to_name = NULL;
- int rc;
-
- smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
- if (smb2_to_name == NULL) {
- rc = -ENOMEM;
- goto smb2_rename_path;
- }
- rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
- FILE_OPEN, 0, ACL_NO_MODE, smb2_to_name,
- command, cfile, NULL, NULL);
-smb2_rename_path:
- kfree(smb2_to_name);
- return rc;
-}
-
-int
-smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb)
-{
- struct cifsFileInfo *cfile;
-
- drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
- cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
-
- return smb2_set_path_attr(xid, tcon, from_name, to_name,
- cifs_sb, DELETE, SMB2_OP_RENAME, cfile);
-}
-
-int
-smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb)
-{
- return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
- FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK,
- NULL);
-}
-
-int
-smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
- const char *full_path, __u64 size,
- struct cifs_sb_info *cifs_sb, bool set_alloc)
-{
- __le64 eof = cpu_to_le64(size);
- struct cifsFileInfo *cfile;
-
- cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
- return smb2_compound_op(xid, tcon, cifs_sb, full_path,
- FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE,
- &eof, SMB2_OP_SET_EOF, cfile, NULL, NULL);
-}
-
-int
-smb2_set_file_info(struct inode *inode, const char *full_path,
- FILE_BASIC_INFO *buf, const unsigned int xid)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink;
- struct cifs_tcon *tcon;
- struct cifsFileInfo *cfile;
- int rc;
-
- if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
- (buf->LastWriteTime == 0) && (buf->ChangeTime == 0) &&
- (buf->Attributes == 0))
- return 0; /* would be a no op, no sense sending this */
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- tcon = tlink_tcon(tlink);
-
- cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
- rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
- FILE_WRITE_ATTRIBUTES, FILE_OPEN,
- 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, cfile,
- NULL, NULL);
- cifs_put_tlink(tlink);
- return rc;
-}
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
deleted file mode 100644
index 194799ddd382..000000000000
--- a/fs/cifs/smb2maperror.c
+++ /dev/null
@@ -1,2481 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Functions which do error mapping of SMB2 status codes to POSIX errors
- *
- * Copyright (C) International Business Machines Corp., 2009
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-#include <linux/errno.h>
-#include "cifsglob.h"
-#include "cifs_debug.h"
-#include "smb2pdu.h"
-#include "smb2proto.h"
-#include "smb2status.h"
-#include "smb2glob.h"
-#include "trace.h"
-
-struct status_to_posix_error {
- __le32 smb2_status;
- int posix_error;
- char *status_string;
-};
-
-static const struct status_to_posix_error smb2_error_map_table[] = {
- {STATUS_SUCCESS, 0, "STATUS_SUCCESS"},
- {STATUS_WAIT_0, 0, "STATUS_WAIT_0"},
- {STATUS_WAIT_1, -EIO, "STATUS_WAIT_1"},
- {STATUS_WAIT_2, -EIO, "STATUS_WAIT_2"},
- {STATUS_WAIT_3, -EIO, "STATUS_WAIT_3"},
- {STATUS_WAIT_63, -EIO, "STATUS_WAIT_63"},
- {STATUS_ABANDONED, -EIO, "STATUS_ABANDONED"},
- {STATUS_ABANDONED_WAIT_0, -EIO, "STATUS_ABANDONED_WAIT_0"},
- {STATUS_ABANDONED_WAIT_63, -EIO, "STATUS_ABANDONED_WAIT_63"},
- {STATUS_USER_APC, -EIO, "STATUS_USER_APC"},
- {STATUS_KERNEL_APC, -EIO, "STATUS_KERNEL_APC"},
- {STATUS_ALERTED, -EIO, "STATUS_ALERTED"},
- {STATUS_TIMEOUT, -ETIMEDOUT, "STATUS_TIMEOUT"},
- {STATUS_PENDING, -EIO, "STATUS_PENDING"},
- {STATUS_REPARSE, -EIO, "STATUS_REPARSE"},
- {STATUS_MORE_ENTRIES, -EIO, "STATUS_MORE_ENTRIES"},
- {STATUS_NOT_ALL_ASSIGNED, -EIO, "STATUS_NOT_ALL_ASSIGNED"},
- {STATUS_SOME_NOT_MAPPED, -EIO, "STATUS_SOME_NOT_MAPPED"},
- {STATUS_OPLOCK_BREAK_IN_PROGRESS, -EIO,
- "STATUS_OPLOCK_BREAK_IN_PROGRESS"},
- {STATUS_VOLUME_MOUNTED, -EIO, "STATUS_VOLUME_MOUNTED"},
- {STATUS_RXACT_COMMITTED, -EIO, "STATUS_RXACT_COMMITTED"},
- {STATUS_NOTIFY_CLEANUP, -EIO, "STATUS_NOTIFY_CLEANUP"},
- {STATUS_NOTIFY_ENUM_DIR, -EIO, "STATUS_NOTIFY_ENUM_DIR"},
- {STATUS_NO_QUOTAS_FOR_ACCOUNT, -EIO, "STATUS_NO_QUOTAS_FOR_ACCOUNT"},
- {STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED, -EIO,
- "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED"},
- {STATUS_PAGE_FAULT_TRANSITION, -EIO, "STATUS_PAGE_FAULT_TRANSITION"},
- {STATUS_PAGE_FAULT_DEMAND_ZERO, -EIO, "STATUS_PAGE_FAULT_DEMAND_ZERO"},
- {STATUS_PAGE_FAULT_COPY_ON_WRITE, -EIO,
- "STATUS_PAGE_FAULT_COPY_ON_WRITE"},
- {STATUS_PAGE_FAULT_GUARD_PAGE, -EIO, "STATUS_PAGE_FAULT_GUARD_PAGE"},
- {STATUS_PAGE_FAULT_PAGING_FILE, -EIO, "STATUS_PAGE_FAULT_PAGING_FILE"},
- {STATUS_CACHE_PAGE_LOCKED, -EIO, "STATUS_CACHE_PAGE_LOCKED"},
- {STATUS_CRASH_DUMP, -EIO, "STATUS_CRASH_DUMP"},
- {STATUS_BUFFER_ALL_ZEROS, -EIO, "STATUS_BUFFER_ALL_ZEROS"},
- {STATUS_REPARSE_OBJECT, -EIO, "STATUS_REPARSE_OBJECT"},
- {STATUS_RESOURCE_REQUIREMENTS_CHANGED, -EIO,
- "STATUS_RESOURCE_REQUIREMENTS_CHANGED"},
- {STATUS_TRANSLATION_COMPLETE, -EIO, "STATUS_TRANSLATION_COMPLETE"},
- {STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY, -EIO,
- "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY"},
- {STATUS_NOTHING_TO_TERMINATE, -EIO, "STATUS_NOTHING_TO_TERMINATE"},
- {STATUS_PROCESS_NOT_IN_JOB, -EIO, "STATUS_PROCESS_NOT_IN_JOB"},
- {STATUS_PROCESS_IN_JOB, -EIO, "STATUS_PROCESS_IN_JOB"},
- {STATUS_VOLSNAP_HIBERNATE_READY, -EIO,
- "STATUS_VOLSNAP_HIBERNATE_READY"},
- {STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY, -EIO,
- "STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY"},
- {STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED, -EIO,
- "STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED"},
- {STATUS_INTERRUPT_STILL_CONNECTED, -EIO,
- "STATUS_INTERRUPT_STILL_CONNECTED"},
- {STATUS_PROCESS_CLONED, -EIO, "STATUS_PROCESS_CLONED"},
- {STATUS_FILE_LOCKED_WITH_ONLY_READERS, -EIO,
- "STATUS_FILE_LOCKED_WITH_ONLY_READERS"},
- {STATUS_FILE_LOCKED_WITH_WRITERS, -EIO,
- "STATUS_FILE_LOCKED_WITH_WRITERS"},
- {STATUS_RESOURCEMANAGER_READ_ONLY, -EROFS,
- "STATUS_RESOURCEMANAGER_READ_ONLY"},
- {STATUS_WAIT_FOR_OPLOCK, -EIO, "STATUS_WAIT_FOR_OPLOCK"},
- {DBG_EXCEPTION_HANDLED, -EIO, "DBG_EXCEPTION_HANDLED"},
- {DBG_CONTINUE, -EIO, "DBG_CONTINUE"},
- {STATUS_FLT_IO_COMPLETE, -EIO, "STATUS_FLT_IO_COMPLETE"},
- {STATUS_OBJECT_NAME_EXISTS, -EIO, "STATUS_OBJECT_NAME_EXISTS"},
- {STATUS_THREAD_WAS_SUSPENDED, -EIO, "STATUS_THREAD_WAS_SUSPENDED"},
- {STATUS_WORKING_SET_LIMIT_RANGE, -EIO,
- "STATUS_WORKING_SET_LIMIT_RANGE"},
- {STATUS_IMAGE_NOT_AT_BASE, -EIO, "STATUS_IMAGE_NOT_AT_BASE"},
- {STATUS_RXACT_STATE_CREATED, -EIO, "STATUS_RXACT_STATE_CREATED"},
- {STATUS_SEGMENT_NOTIFICATION, -EIO, "STATUS_SEGMENT_NOTIFICATION"},
- {STATUS_LOCAL_USER_SESSION_KEY, -EIO, "STATUS_LOCAL_USER_SESSION_KEY"},
- {STATUS_BAD_CURRENT_DIRECTORY, -EIO, "STATUS_BAD_CURRENT_DIRECTORY"},
- {STATUS_SERIAL_MORE_WRITES, -EIO, "STATUS_SERIAL_MORE_WRITES"},
- {STATUS_REGISTRY_RECOVERED, -EIO, "STATUS_REGISTRY_RECOVERED"},
- {STATUS_FT_READ_RECOVERY_FROM_BACKUP, -EIO,
- "STATUS_FT_READ_RECOVERY_FROM_BACKUP"},
- {STATUS_FT_WRITE_RECOVERY, -EIO, "STATUS_FT_WRITE_RECOVERY"},
- {STATUS_SERIAL_COUNTER_TIMEOUT, -ETIMEDOUT,
- "STATUS_SERIAL_COUNTER_TIMEOUT"},
- {STATUS_NULL_LM_PASSWORD, -EIO, "STATUS_NULL_LM_PASSWORD"},
- {STATUS_IMAGE_MACHINE_TYPE_MISMATCH, -EIO,
- "STATUS_IMAGE_MACHINE_TYPE_MISMATCH"},
- {STATUS_RECEIVE_PARTIAL, -EIO, "STATUS_RECEIVE_PARTIAL"},
- {STATUS_RECEIVE_EXPEDITED, -EIO, "STATUS_RECEIVE_EXPEDITED"},
- {STATUS_RECEIVE_PARTIAL_EXPEDITED, -EIO,
- "STATUS_RECEIVE_PARTIAL_EXPEDITED"},
- {STATUS_EVENT_DONE, -EIO, "STATUS_EVENT_DONE"},
- {STATUS_EVENT_PENDING, -EIO, "STATUS_EVENT_PENDING"},
- {STATUS_CHECKING_FILE_SYSTEM, -EIO, "STATUS_CHECKING_FILE_SYSTEM"},
- {STATUS_FATAL_APP_EXIT, -EIO, "STATUS_FATAL_APP_EXIT"},
- {STATUS_PREDEFINED_HANDLE, -EIO, "STATUS_PREDEFINED_HANDLE"},
- {STATUS_WAS_UNLOCKED, -EIO, "STATUS_WAS_UNLOCKED"},
- {STATUS_SERVICE_NOTIFICATION, -EIO, "STATUS_SERVICE_NOTIFICATION"},
- {STATUS_WAS_LOCKED, -EIO, "STATUS_WAS_LOCKED"},
- {STATUS_LOG_HARD_ERROR, -EIO, "STATUS_LOG_HARD_ERROR"},
- {STATUS_ALREADY_WIN32, -EIO, "STATUS_ALREADY_WIN32"},
- {STATUS_WX86_UNSIMULATE, -EIO, "STATUS_WX86_UNSIMULATE"},
- {STATUS_WX86_CONTINUE, -EIO, "STATUS_WX86_CONTINUE"},
- {STATUS_WX86_SINGLE_STEP, -EIO, "STATUS_WX86_SINGLE_STEP"},
- {STATUS_WX86_BREAKPOINT, -EIO, "STATUS_WX86_BREAKPOINT"},
- {STATUS_WX86_EXCEPTION_CONTINUE, -EIO,
- "STATUS_WX86_EXCEPTION_CONTINUE"},
- {STATUS_WX86_EXCEPTION_LASTCHANCE, -EIO,
- "STATUS_WX86_EXCEPTION_LASTCHANCE"},
- {STATUS_WX86_EXCEPTION_CHAIN, -EIO, "STATUS_WX86_EXCEPTION_CHAIN"},
- {STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE, -EIO,
- "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE"},
- {STATUS_NO_YIELD_PERFORMED, -EIO, "STATUS_NO_YIELD_PERFORMED"},
- {STATUS_TIMER_RESUME_IGNORED, -EIO, "STATUS_TIMER_RESUME_IGNORED"},
- {STATUS_ARBITRATION_UNHANDLED, -EIO, "STATUS_ARBITRATION_UNHANDLED"},
- {STATUS_CARDBUS_NOT_SUPPORTED, -ENOSYS, "STATUS_CARDBUS_NOT_SUPPORTED"},
- {STATUS_WX86_CREATEWX86TIB, -EIO, "STATUS_WX86_CREATEWX86TIB"},
- {STATUS_MP_PROCESSOR_MISMATCH, -EIO, "STATUS_MP_PROCESSOR_MISMATCH"},
- {STATUS_HIBERNATED, -EIO, "STATUS_HIBERNATED"},
- {STATUS_RESUME_HIBERNATION, -EIO, "STATUS_RESUME_HIBERNATION"},
- {STATUS_FIRMWARE_UPDATED, -EIO, "STATUS_FIRMWARE_UPDATED"},
- {STATUS_DRIVERS_LEAKING_LOCKED_PAGES, -EIO,
- "STATUS_DRIVERS_LEAKING_LOCKED_PAGES"},
- {STATUS_MESSAGE_RETRIEVED, -EIO, "STATUS_MESSAGE_RETRIEVED"},
- {STATUS_SYSTEM_POWERSTATE_TRANSITION, -EIO,
- "STATUS_SYSTEM_POWERSTATE_TRANSITION"},
- {STATUS_ALPC_CHECK_COMPLETION_LIST, -EIO,
- "STATUS_ALPC_CHECK_COMPLETION_LIST"},
- {STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION, -EIO,
- "STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION"},
- {STATUS_ACCESS_AUDIT_BY_POLICY, -EIO, "STATUS_ACCESS_AUDIT_BY_POLICY"},
- {STATUS_ABANDON_HIBERFILE, -EIO, "STATUS_ABANDON_HIBERFILE"},
- {STATUS_BIZRULES_NOT_ENABLED, -EIO, "STATUS_BIZRULES_NOT_ENABLED"},
- {STATUS_WAKE_SYSTEM, -EIO, "STATUS_WAKE_SYSTEM"},
- {STATUS_DS_SHUTTING_DOWN, -EIO, "STATUS_DS_SHUTTING_DOWN"},
- {DBG_REPLY_LATER, -EIO, "DBG_REPLY_LATER"},
- {DBG_UNABLE_TO_PROVIDE_HANDLE, -EIO, "DBG_UNABLE_TO_PROVIDE_HANDLE"},
- {DBG_TERMINATE_THREAD, -EIO, "DBG_TERMINATE_THREAD"},
- {DBG_TERMINATE_PROCESS, -EIO, "DBG_TERMINATE_PROCESS"},
- {DBG_CONTROL_C, -EIO, "DBG_CONTROL_C"},
- {DBG_PRINTEXCEPTION_C, -EIO, "DBG_PRINTEXCEPTION_C"},
- {DBG_RIPEXCEPTION, -EIO, "DBG_RIPEXCEPTION"},
- {DBG_CONTROL_BREAK, -EIO, "DBG_CONTROL_BREAK"},
- {DBG_COMMAND_EXCEPTION, -EIO, "DBG_COMMAND_EXCEPTION"},
- {RPC_NT_UUID_LOCAL_ONLY, -EIO, "RPC_NT_UUID_LOCAL_ONLY"},
- {RPC_NT_SEND_INCOMPLETE, -EIO, "RPC_NT_SEND_INCOMPLETE"},
- {STATUS_CTX_CDM_CONNECT, -EIO, "STATUS_CTX_CDM_CONNECT"},
- {STATUS_CTX_CDM_DISCONNECT, -EIO, "STATUS_CTX_CDM_DISCONNECT"},
- {STATUS_SXS_RELEASE_ACTIVATION_CONTEXT, -EIO,
- "STATUS_SXS_RELEASE_ACTIVATION_CONTEXT"},
- {STATUS_RECOVERY_NOT_NEEDED, -EIO, "STATUS_RECOVERY_NOT_NEEDED"},
- {STATUS_RM_ALREADY_STARTED, -EIO, "STATUS_RM_ALREADY_STARTED"},
- {STATUS_LOG_NO_RESTART, -EIO, "STATUS_LOG_NO_RESTART"},
- {STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST, -EIO,
- "STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST"},
- {STATUS_GRAPHICS_PARTIAL_DATA_POPULATED, -EIO,
- "STATUS_GRAPHICS_PARTIAL_DATA_POPULATED"},
- {STATUS_GRAPHICS_DRIVER_MISMATCH, -EIO,
- "STATUS_GRAPHICS_DRIVER_MISMATCH"},
- {STATUS_GRAPHICS_MODE_NOT_PINNED, -EIO,
- "STATUS_GRAPHICS_MODE_NOT_PINNED"},
- {STATUS_GRAPHICS_NO_PREFERRED_MODE, -EIO,
- "STATUS_GRAPHICS_NO_PREFERRED_MODE"},
- {STATUS_GRAPHICS_DATASET_IS_EMPTY, -EIO,
- "STATUS_GRAPHICS_DATASET_IS_EMPTY"},
- {STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET, -EIO,
- "STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET"},
- {STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED, -EIO,
- "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED"},
- {STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS, -EIO,
- "STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS"},
- {STATUS_GRAPHICS_LEADLINK_START_DEFERRED, -EIO,
- "STATUS_GRAPHICS_LEADLINK_START_DEFERRED"},
- {STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY, -EIO,
- "STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY"},
- {STATUS_GRAPHICS_START_DEFERRED, -EIO,
- "STATUS_GRAPHICS_START_DEFERRED"},
- {STATUS_NDIS_INDICATION_REQUIRED, -EIO,
- "STATUS_NDIS_INDICATION_REQUIRED"},
- {STATUS_GUARD_PAGE_VIOLATION, -EIO, "STATUS_GUARD_PAGE_VIOLATION"},
- {STATUS_DATATYPE_MISALIGNMENT, -EIO, "STATUS_DATATYPE_MISALIGNMENT"},
- {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
- {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
- {STATUS_BUFFER_OVERFLOW, -E2BIG, "STATUS_BUFFER_OVERFLOW"},
- {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
- {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
- {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
- {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"},
- {STATUS_GUID_SUBSTITUTION_MADE, -EIO, "STATUS_GUID_SUBSTITUTION_MADE"},
- {STATUS_PARTIAL_COPY, -EIO, "STATUS_PARTIAL_COPY"},
- {STATUS_DEVICE_PAPER_EMPTY, -EIO, "STATUS_DEVICE_PAPER_EMPTY"},
- {STATUS_DEVICE_POWERED_OFF, -EIO, "STATUS_DEVICE_POWERED_OFF"},
- {STATUS_DEVICE_OFF_LINE, -EIO, "STATUS_DEVICE_OFF_LINE"},
- {STATUS_DEVICE_BUSY, -EBUSY, "STATUS_DEVICE_BUSY"},
- {STATUS_NO_MORE_EAS, -EIO, "STATUS_NO_MORE_EAS"},
- {STATUS_INVALID_EA_NAME, -EINVAL, "STATUS_INVALID_EA_NAME"},
- {STATUS_EA_LIST_INCONSISTENT, -EIO, "STATUS_EA_LIST_INCONSISTENT"},
- {STATUS_INVALID_EA_FLAG, -EINVAL, "STATUS_INVALID_EA_FLAG"},
- {STATUS_VERIFY_REQUIRED, -EIO, "STATUS_VERIFY_REQUIRED"},
- {STATUS_EXTRANEOUS_INFORMATION, -EIO, "STATUS_EXTRANEOUS_INFORMATION"},
- {STATUS_RXACT_COMMIT_NECESSARY, -EIO, "STATUS_RXACT_COMMIT_NECESSARY"},
- {STATUS_NO_MORE_ENTRIES, -EIO, "STATUS_NO_MORE_ENTRIES"},
- {STATUS_FILEMARK_DETECTED, -EIO, "STATUS_FILEMARK_DETECTED"},
- {STATUS_MEDIA_CHANGED, -EIO, "STATUS_MEDIA_CHANGED"},
- {STATUS_BUS_RESET, -EIO, "STATUS_BUS_RESET"},
- {STATUS_END_OF_MEDIA, -EIO, "STATUS_END_OF_MEDIA"},
- {STATUS_BEGINNING_OF_MEDIA, -EIO, "STATUS_BEGINNING_OF_MEDIA"},
- {STATUS_MEDIA_CHECK, -EIO, "STATUS_MEDIA_CHECK"},
- {STATUS_SETMARK_DETECTED, -EIO, "STATUS_SETMARK_DETECTED"},
- {STATUS_NO_DATA_DETECTED, -EIO, "STATUS_NO_DATA_DETECTED"},
- {STATUS_REDIRECTOR_HAS_OPEN_HANDLES, -EIO,
- "STATUS_REDIRECTOR_HAS_OPEN_HANDLES"},
- {STATUS_SERVER_HAS_OPEN_HANDLES, -EIO,
- "STATUS_SERVER_HAS_OPEN_HANDLES"},
- {STATUS_ALREADY_DISCONNECTED, -EIO, "STATUS_ALREADY_DISCONNECTED"},
- {STATUS_LONGJUMP, -EIO, "STATUS_LONGJUMP"},
- {STATUS_CLEANER_CARTRIDGE_INSTALLED, -EIO,
- "STATUS_CLEANER_CARTRIDGE_INSTALLED"},
- {STATUS_PLUGPLAY_QUERY_VETOED, -EIO, "STATUS_PLUGPLAY_QUERY_VETOED"},
- {STATUS_UNWIND_CONSOLIDATE, -EIO, "STATUS_UNWIND_CONSOLIDATE"},
- {STATUS_REGISTRY_HIVE_RECOVERED, -EIO,
- "STATUS_REGISTRY_HIVE_RECOVERED"},
- {STATUS_DLL_MIGHT_BE_INSECURE, -EIO, "STATUS_DLL_MIGHT_BE_INSECURE"},
- {STATUS_DLL_MIGHT_BE_INCOMPATIBLE, -EIO,
- "STATUS_DLL_MIGHT_BE_INCOMPATIBLE"},
- {STATUS_STOPPED_ON_SYMLINK, -EOPNOTSUPP, "STATUS_STOPPED_ON_SYMLINK"},
- {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EOPNOTSUPP,
- "STATUS_REPARSE_NOT_HANDLED"},
- {STATUS_DEVICE_REQUIRES_CLEANING, -EIO,
- "STATUS_DEVICE_REQUIRES_CLEANING"},
- {STATUS_DEVICE_DOOR_OPEN, -EIO, "STATUS_DEVICE_DOOR_OPEN"},
- {STATUS_DATA_LOST_REPAIR, -EIO, "STATUS_DATA_LOST_REPAIR"},
- {DBG_EXCEPTION_NOT_HANDLED, -EIO, "DBG_EXCEPTION_NOT_HANDLED"},
- {STATUS_CLUSTER_NODE_ALREADY_UP, -EIO,
- "STATUS_CLUSTER_NODE_ALREADY_UP"},
- {STATUS_CLUSTER_NODE_ALREADY_DOWN, -EIO,
- "STATUS_CLUSTER_NODE_ALREADY_DOWN"},
- {STATUS_CLUSTER_NETWORK_ALREADY_ONLINE, -EIO,
- "STATUS_CLUSTER_NETWORK_ALREADY_ONLINE"},
- {STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE, -EIO,
- "STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE"},
- {STATUS_CLUSTER_NODE_ALREADY_MEMBER, -EIO,
- "STATUS_CLUSTER_NODE_ALREADY_MEMBER"},
- {STATUS_COULD_NOT_RESIZE_LOG, -EIO, "STATUS_COULD_NOT_RESIZE_LOG"},
- {STATUS_NO_TXF_METADATA, -EIO, "STATUS_NO_TXF_METADATA"},
- {STATUS_CANT_RECOVER_WITH_HANDLE_OPEN, -EIO,
- "STATUS_CANT_RECOVER_WITH_HANDLE_OPEN"},
- {STATUS_TXF_METADATA_ALREADY_PRESENT, -EIO,
- "STATUS_TXF_METADATA_ALREADY_PRESENT"},
- {STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET, -EIO,
- "STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET"},
- {STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED, -EIO,
- "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED"},
- {STATUS_FLT_BUFFER_TOO_SMALL, -ENOBUFS, "STATUS_FLT_BUFFER_TOO_SMALL"},
- {STATUS_FVE_PARTIAL_METADATA, -EIO, "STATUS_FVE_PARTIAL_METADATA"},
- {STATUS_UNSUCCESSFUL, -EIO, "STATUS_UNSUCCESSFUL"},
- {STATUS_NOT_IMPLEMENTED, -EOPNOTSUPP, "STATUS_NOT_IMPLEMENTED"},
- {STATUS_INVALID_INFO_CLASS, -EIO, "STATUS_INVALID_INFO_CLASS"},
- {STATUS_INFO_LENGTH_MISMATCH, -EIO, "STATUS_INFO_LENGTH_MISMATCH"},
- {STATUS_ACCESS_VIOLATION, -EACCES, "STATUS_ACCESS_VIOLATION"},
- {STATUS_IN_PAGE_ERROR, -EFAULT, "STATUS_IN_PAGE_ERROR"},
- {STATUS_PAGEFILE_QUOTA, -EDQUOT, "STATUS_PAGEFILE_QUOTA"},
- {STATUS_INVALID_HANDLE, -EBADF, "STATUS_INVALID_HANDLE"},
- {STATUS_BAD_INITIAL_STACK, -EIO, "STATUS_BAD_INITIAL_STACK"},
- {STATUS_BAD_INITIAL_PC, -EIO, "STATUS_BAD_INITIAL_PC"},
- {STATUS_INVALID_CID, -EIO, "STATUS_INVALID_CID"},
- {STATUS_TIMER_NOT_CANCELED, -EIO, "STATUS_TIMER_NOT_CANCELED"},
- {STATUS_INVALID_PARAMETER, -EINVAL, "STATUS_INVALID_PARAMETER"},
- {STATUS_NO_SUCH_DEVICE, -ENODEV, "STATUS_NO_SUCH_DEVICE"},
- {STATUS_NO_SUCH_FILE, -ENOENT, "STATUS_NO_SUCH_FILE"},
- {STATUS_INVALID_DEVICE_REQUEST, -EOPNOTSUPP, "STATUS_INVALID_DEVICE_REQUEST"},
- {STATUS_END_OF_FILE, -ENODATA, "STATUS_END_OF_FILE"},
- {STATUS_WRONG_VOLUME, -EIO, "STATUS_WRONG_VOLUME"},
- {STATUS_NO_MEDIA_IN_DEVICE, -EIO, "STATUS_NO_MEDIA_IN_DEVICE"},
- {STATUS_UNRECOGNIZED_MEDIA, -EIO, "STATUS_UNRECOGNIZED_MEDIA"},
- {STATUS_NONEXISTENT_SECTOR, -EIO, "STATUS_NONEXISTENT_SECTOR"},
- {STATUS_MORE_PROCESSING_REQUIRED, -EIO,
- "STATUS_MORE_PROCESSING_REQUIRED"},
- {STATUS_NO_MEMORY, -EREMOTEIO, "STATUS_NO_MEMORY"},
- {STATUS_CONFLICTING_ADDRESSES, -EADDRINUSE,
- "STATUS_CONFLICTING_ADDRESSES"},
- {STATUS_NOT_MAPPED_VIEW, -EIO, "STATUS_NOT_MAPPED_VIEW"},
- {STATUS_UNABLE_TO_FREE_VM, -EIO, "STATUS_UNABLE_TO_FREE_VM"},
- {STATUS_UNABLE_TO_DELETE_SECTION, -EIO,
- "STATUS_UNABLE_TO_DELETE_SECTION"},
- {STATUS_INVALID_SYSTEM_SERVICE, -EIO, "STATUS_INVALID_SYSTEM_SERVICE"},
- {STATUS_ILLEGAL_INSTRUCTION, -EIO, "STATUS_ILLEGAL_INSTRUCTION"},
- {STATUS_INVALID_LOCK_SEQUENCE, -EIO, "STATUS_INVALID_LOCK_SEQUENCE"},
- {STATUS_INVALID_VIEW_SIZE, -EIO, "STATUS_INVALID_VIEW_SIZE"},
- {STATUS_INVALID_FILE_FOR_SECTION, -EIO,
- "STATUS_INVALID_FILE_FOR_SECTION"},
- {STATUS_ALREADY_COMMITTED, -EIO, "STATUS_ALREADY_COMMITTED"},
- {STATUS_ACCESS_DENIED, -EACCES, "STATUS_ACCESS_DENIED"},
- {STATUS_BUFFER_TOO_SMALL, -EIO, "STATUS_BUFFER_TOO_SMALL"},
- {STATUS_OBJECT_TYPE_MISMATCH, -EIO, "STATUS_OBJECT_TYPE_MISMATCH"},
- {STATUS_NONCONTINUABLE_EXCEPTION, -EIO,
- "STATUS_NONCONTINUABLE_EXCEPTION"},
- {STATUS_INVALID_DISPOSITION, -EIO, "STATUS_INVALID_DISPOSITION"},
- {STATUS_UNWIND, -EIO, "STATUS_UNWIND"},
- {STATUS_BAD_STACK, -EIO, "STATUS_BAD_STACK"},
- {STATUS_INVALID_UNWIND_TARGET, -EIO, "STATUS_INVALID_UNWIND_TARGET"},
- {STATUS_NOT_LOCKED, -EIO, "STATUS_NOT_LOCKED"},
- {STATUS_PARITY_ERROR, -EIO, "STATUS_PARITY_ERROR"},
- {STATUS_UNABLE_TO_DECOMMIT_VM, -EIO, "STATUS_UNABLE_TO_DECOMMIT_VM"},
- {STATUS_NOT_COMMITTED, -EIO, "STATUS_NOT_COMMITTED"},
- {STATUS_INVALID_PORT_ATTRIBUTES, -EIO,
- "STATUS_INVALID_PORT_ATTRIBUTES"},
- {STATUS_PORT_MESSAGE_TOO_LONG, -EIO, "STATUS_PORT_MESSAGE_TOO_LONG"},
- {STATUS_INVALID_PARAMETER_MIX, -EINVAL, "STATUS_INVALID_PARAMETER_MIX"},
- {STATUS_INVALID_QUOTA_LOWER, -EIO, "STATUS_INVALID_QUOTA_LOWER"},
- {STATUS_DISK_CORRUPT_ERROR, -EIO, "STATUS_DISK_CORRUPT_ERROR"},
- {STATUS_OBJECT_NAME_INVALID, -ENOENT, "STATUS_OBJECT_NAME_INVALID"},
- {STATUS_OBJECT_NAME_NOT_FOUND, -ENOENT, "STATUS_OBJECT_NAME_NOT_FOUND"},
- {STATUS_OBJECT_NAME_COLLISION, -EEXIST, "STATUS_OBJECT_NAME_COLLISION"},
- {STATUS_PORT_DISCONNECTED, -EIO, "STATUS_PORT_DISCONNECTED"},
- {STATUS_DEVICE_ALREADY_ATTACHED, -EIO,
- "STATUS_DEVICE_ALREADY_ATTACHED"},
- {STATUS_OBJECT_PATH_INVALID, -ENOTDIR, "STATUS_OBJECT_PATH_INVALID"},
- {STATUS_OBJECT_PATH_NOT_FOUND, -ENOENT, "STATUS_OBJECT_PATH_NOT_FOUND"},
- {STATUS_OBJECT_PATH_SYNTAX_BAD, -EIO, "STATUS_OBJECT_PATH_SYNTAX_BAD"},
- {STATUS_DATA_OVERRUN, -EIO, "STATUS_DATA_OVERRUN"},
- {STATUS_DATA_LATE_ERROR, -EIO, "STATUS_DATA_LATE_ERROR"},
- {STATUS_DATA_ERROR, -EIO, "STATUS_DATA_ERROR"},
- {STATUS_CRC_ERROR, -EIO, "STATUS_CRC_ERROR"},
- {STATUS_SECTION_TOO_BIG, -EIO, "STATUS_SECTION_TOO_BIG"},
- {STATUS_PORT_CONNECTION_REFUSED, -ECONNREFUSED,
- "STATUS_PORT_CONNECTION_REFUSED"},
- {STATUS_INVALID_PORT_HANDLE, -EIO, "STATUS_INVALID_PORT_HANDLE"},
- {STATUS_SHARING_VIOLATION, -EBUSY, "STATUS_SHARING_VIOLATION"},
- {STATUS_QUOTA_EXCEEDED, -EDQUOT, "STATUS_QUOTA_EXCEEDED"},
- {STATUS_INVALID_PAGE_PROTECTION, -EIO,
- "STATUS_INVALID_PAGE_PROTECTION"},
- {STATUS_MUTANT_NOT_OWNED, -EIO, "STATUS_MUTANT_NOT_OWNED"},
- {STATUS_SEMAPHORE_LIMIT_EXCEEDED, -EIO,
- "STATUS_SEMAPHORE_LIMIT_EXCEEDED"},
- {STATUS_PORT_ALREADY_SET, -EIO, "STATUS_PORT_ALREADY_SET"},
- {STATUS_SECTION_NOT_IMAGE, -EIO, "STATUS_SECTION_NOT_IMAGE"},
- {STATUS_SUSPEND_COUNT_EXCEEDED, -EIO, "STATUS_SUSPEND_COUNT_EXCEEDED"},
- {STATUS_THREAD_IS_TERMINATING, -EIO, "STATUS_THREAD_IS_TERMINATING"},
- {STATUS_BAD_WORKING_SET_LIMIT, -EIO, "STATUS_BAD_WORKING_SET_LIMIT"},
- {STATUS_INCOMPATIBLE_FILE_MAP, -EIO, "STATUS_INCOMPATIBLE_FILE_MAP"},
- {STATUS_SECTION_PROTECTION, -EIO, "STATUS_SECTION_PROTECTION"},
- {STATUS_EAS_NOT_SUPPORTED, -EOPNOTSUPP, "STATUS_EAS_NOT_SUPPORTED"},
- {STATUS_EA_TOO_LARGE, -EIO, "STATUS_EA_TOO_LARGE"},
- {STATUS_NONEXISTENT_EA_ENTRY, -EIO, "STATUS_NONEXISTENT_EA_ENTRY"},
- {STATUS_NO_EAS_ON_FILE, -ENODATA, "STATUS_NO_EAS_ON_FILE"},
- {STATUS_EA_CORRUPT_ERROR, -EIO, "STATUS_EA_CORRUPT_ERROR"},
- {STATUS_FILE_LOCK_CONFLICT, -EACCES, "STATUS_FILE_LOCK_CONFLICT"},
- {STATUS_LOCK_NOT_GRANTED, -EACCES, "STATUS_LOCK_NOT_GRANTED"},
- {STATUS_DELETE_PENDING, -ENOENT, "STATUS_DELETE_PENDING"},
- {STATUS_CTL_FILE_NOT_SUPPORTED, -ENOSYS,
- "STATUS_CTL_FILE_NOT_SUPPORTED"},
- {STATUS_UNKNOWN_REVISION, -EIO, "STATUS_UNKNOWN_REVISION"},
- {STATUS_REVISION_MISMATCH, -EIO, "STATUS_REVISION_MISMATCH"},
- {STATUS_INVALID_OWNER, -EIO, "STATUS_INVALID_OWNER"},
- {STATUS_INVALID_PRIMARY_GROUP, -EIO, "STATUS_INVALID_PRIMARY_GROUP"},
- {STATUS_NO_IMPERSONATION_TOKEN, -EIO, "STATUS_NO_IMPERSONATION_TOKEN"},
- {STATUS_CANT_DISABLE_MANDATORY, -EIO, "STATUS_CANT_DISABLE_MANDATORY"},
- {STATUS_NO_LOGON_SERVERS, -EIO, "STATUS_NO_LOGON_SERVERS"},
- {STATUS_NO_SUCH_LOGON_SESSION, -EIO, "STATUS_NO_SUCH_LOGON_SESSION"},
- {STATUS_NO_SUCH_PRIVILEGE, -EIO, "STATUS_NO_SUCH_PRIVILEGE"},
- {STATUS_PRIVILEGE_NOT_HELD, -EIO, "STATUS_PRIVILEGE_NOT_HELD"},
- {STATUS_INVALID_ACCOUNT_NAME, -EIO, "STATUS_INVALID_ACCOUNT_NAME"},
- {STATUS_USER_EXISTS, -EIO, "STATUS_USER_EXISTS"},
- {STATUS_NO_SUCH_USER, -EIO, "STATUS_NO_SUCH_USER"},
- {STATUS_GROUP_EXISTS, -EIO, "STATUS_GROUP_EXISTS"},
- {STATUS_NO_SUCH_GROUP, -EIO, "STATUS_NO_SUCH_GROUP"},
- {STATUS_MEMBER_IN_GROUP, -EIO, "STATUS_MEMBER_IN_GROUP"},
- {STATUS_MEMBER_NOT_IN_GROUP, -EIO, "STATUS_MEMBER_NOT_IN_GROUP"},
- {STATUS_LAST_ADMIN, -EIO, "STATUS_LAST_ADMIN"},
- {STATUS_WRONG_PASSWORD, -EACCES, "STATUS_WRONG_PASSWORD"},
- {STATUS_ILL_FORMED_PASSWORD, -EINVAL, "STATUS_ILL_FORMED_PASSWORD"},
- {STATUS_PASSWORD_RESTRICTION, -EACCES, "STATUS_PASSWORD_RESTRICTION"},
- {STATUS_LOGON_FAILURE, -EACCES, "STATUS_LOGON_FAILURE"},
- {STATUS_ACCOUNT_RESTRICTION, -EACCES, "STATUS_ACCOUNT_RESTRICTION"},
- {STATUS_INVALID_LOGON_HOURS, -EACCES, "STATUS_INVALID_LOGON_HOURS"},
- {STATUS_INVALID_WORKSTATION, -EACCES, "STATUS_INVALID_WORKSTATION"},
- {STATUS_PASSWORD_EXPIRED, -EKEYEXPIRED, "STATUS_PASSWORD_EXPIRED"},
- {STATUS_ACCOUNT_DISABLED, -EKEYREVOKED, "STATUS_ACCOUNT_DISABLED"},
- {STATUS_NONE_MAPPED, -EIO, "STATUS_NONE_MAPPED"},
- {STATUS_TOO_MANY_LUIDS_REQUESTED, -EIO,
- "STATUS_TOO_MANY_LUIDS_REQUESTED"},
- {STATUS_LUIDS_EXHAUSTED, -EIO, "STATUS_LUIDS_EXHAUSTED"},
- {STATUS_INVALID_SUB_AUTHORITY, -EIO, "STATUS_INVALID_SUB_AUTHORITY"},
- {STATUS_INVALID_ACL, -EIO, "STATUS_INVALID_ACL"},
- {STATUS_INVALID_SID, -EIO, "STATUS_INVALID_SID"},
- {STATUS_INVALID_SECURITY_DESCR, -EIO, "STATUS_INVALID_SECURITY_DESCR"},
- {STATUS_PROCEDURE_NOT_FOUND, -EIO, "STATUS_PROCEDURE_NOT_FOUND"},
- {STATUS_INVALID_IMAGE_FORMAT, -EIO, "STATUS_INVALID_IMAGE_FORMAT"},
- {STATUS_NO_TOKEN, -EIO, "STATUS_NO_TOKEN"},
- {STATUS_BAD_INHERITANCE_ACL, -EIO, "STATUS_BAD_INHERITANCE_ACL"},
- {STATUS_RANGE_NOT_LOCKED, -EIO, "STATUS_RANGE_NOT_LOCKED"},
- {STATUS_DISK_FULL, -ENOSPC, "STATUS_DISK_FULL"},
- {STATUS_SERVER_DISABLED, -EIO, "STATUS_SERVER_DISABLED"},
- {STATUS_SERVER_NOT_DISABLED, -EIO, "STATUS_SERVER_NOT_DISABLED"},
- {STATUS_TOO_MANY_GUIDS_REQUESTED, -EIO,
- "STATUS_TOO_MANY_GUIDS_REQUESTED"},
- {STATUS_GUIDS_EXHAUSTED, -EIO, "STATUS_GUIDS_EXHAUSTED"},
- {STATUS_INVALID_ID_AUTHORITY, -EIO, "STATUS_INVALID_ID_AUTHORITY"},
- {STATUS_AGENTS_EXHAUSTED, -EIO, "STATUS_AGENTS_EXHAUSTED"},
- {STATUS_INVALID_VOLUME_LABEL, -EIO, "STATUS_INVALID_VOLUME_LABEL"},
- {STATUS_SECTION_NOT_EXTENDED, -EIO, "STATUS_SECTION_NOT_EXTENDED"},
- {STATUS_NOT_MAPPED_DATA, -EIO, "STATUS_NOT_MAPPED_DATA"},
- {STATUS_RESOURCE_DATA_NOT_FOUND, -EIO,
- "STATUS_RESOURCE_DATA_NOT_FOUND"},
- {STATUS_RESOURCE_TYPE_NOT_FOUND, -EIO,
- "STATUS_RESOURCE_TYPE_NOT_FOUND"},
- {STATUS_RESOURCE_NAME_NOT_FOUND, -EIO,
- "STATUS_RESOURCE_NAME_NOT_FOUND"},
- {STATUS_ARRAY_BOUNDS_EXCEEDED, -EIO, "STATUS_ARRAY_BOUNDS_EXCEEDED"},
- {STATUS_FLOAT_DENORMAL_OPERAND, -EIO, "STATUS_FLOAT_DENORMAL_OPERAND"},
- {STATUS_FLOAT_DIVIDE_BY_ZERO, -EIO, "STATUS_FLOAT_DIVIDE_BY_ZERO"},
- {STATUS_FLOAT_INEXACT_RESULT, -EIO, "STATUS_FLOAT_INEXACT_RESULT"},
- {STATUS_FLOAT_INVALID_OPERATION, -EIO,
- "STATUS_FLOAT_INVALID_OPERATION"},
- {STATUS_FLOAT_OVERFLOW, -EIO, "STATUS_FLOAT_OVERFLOW"},
- {STATUS_FLOAT_STACK_CHECK, -EIO, "STATUS_FLOAT_STACK_CHECK"},
- {STATUS_FLOAT_UNDERFLOW, -EIO, "STATUS_FLOAT_UNDERFLOW"},
- {STATUS_INTEGER_DIVIDE_BY_ZERO, -EIO, "STATUS_INTEGER_DIVIDE_BY_ZERO"},
- {STATUS_INTEGER_OVERFLOW, -EIO, "STATUS_INTEGER_OVERFLOW"},
- {STATUS_PRIVILEGED_INSTRUCTION, -EIO, "STATUS_PRIVILEGED_INSTRUCTION"},
- {STATUS_TOO_MANY_PAGING_FILES, -EIO, "STATUS_TOO_MANY_PAGING_FILES"},
- {STATUS_FILE_INVALID, -EIO, "STATUS_FILE_INVALID"},
- {STATUS_ALLOTTED_SPACE_EXCEEDED, -EIO,
- "STATUS_ALLOTTED_SPACE_EXCEEDED"},
- {STATUS_INSUFFICIENT_RESOURCES, -EAGAIN,
- "STATUS_INSUFFICIENT_RESOURCES"},
- {STATUS_DFS_EXIT_PATH_FOUND, -EIO, "STATUS_DFS_EXIT_PATH_FOUND"},
- {STATUS_DEVICE_DATA_ERROR, -EIO, "STATUS_DEVICE_DATA_ERROR"},
- {STATUS_DEVICE_NOT_CONNECTED, -EIO, "STATUS_DEVICE_NOT_CONNECTED"},
- {STATUS_DEVICE_POWER_FAILURE, -EIO, "STATUS_DEVICE_POWER_FAILURE"},
- {STATUS_FREE_VM_NOT_AT_BASE, -EIO, "STATUS_FREE_VM_NOT_AT_BASE"},
- {STATUS_MEMORY_NOT_ALLOCATED, -EFAULT, "STATUS_MEMORY_NOT_ALLOCATED"},
- {STATUS_WORKING_SET_QUOTA, -EIO, "STATUS_WORKING_SET_QUOTA"},
- {STATUS_MEDIA_WRITE_PROTECTED, -EROFS, "STATUS_MEDIA_WRITE_PROTECTED"},
- {STATUS_DEVICE_NOT_READY, -EIO, "STATUS_DEVICE_NOT_READY"},
- {STATUS_INVALID_GROUP_ATTRIBUTES, -EIO,
- "STATUS_INVALID_GROUP_ATTRIBUTES"},
- {STATUS_BAD_IMPERSONATION_LEVEL, -EIO,
- "STATUS_BAD_IMPERSONATION_LEVEL"},
- {STATUS_CANT_OPEN_ANONYMOUS, -EIO, "STATUS_CANT_OPEN_ANONYMOUS"},
- {STATUS_BAD_VALIDATION_CLASS, -EIO, "STATUS_BAD_VALIDATION_CLASS"},
- {STATUS_BAD_TOKEN_TYPE, -EIO, "STATUS_BAD_TOKEN_TYPE"},
- {STATUS_BAD_MASTER_BOOT_RECORD, -EIO, "STATUS_BAD_MASTER_BOOT_RECORD"},
- {STATUS_INSTRUCTION_MISALIGNMENT, -EIO,
- "STATUS_INSTRUCTION_MISALIGNMENT"},
- {STATUS_INSTANCE_NOT_AVAILABLE, -EIO, "STATUS_INSTANCE_NOT_AVAILABLE"},
- {STATUS_PIPE_NOT_AVAILABLE, -EIO, "STATUS_PIPE_NOT_AVAILABLE"},
- {STATUS_INVALID_PIPE_STATE, -EIO, "STATUS_INVALID_PIPE_STATE"},
- {STATUS_PIPE_BUSY, -EBUSY, "STATUS_PIPE_BUSY"},
- {STATUS_ILLEGAL_FUNCTION, -EIO, "STATUS_ILLEGAL_FUNCTION"},
- {STATUS_PIPE_DISCONNECTED, -EPIPE, "STATUS_PIPE_DISCONNECTED"},
- {STATUS_PIPE_CLOSING, -EIO, "STATUS_PIPE_CLOSING"},
- {STATUS_PIPE_CONNECTED, -EIO, "STATUS_PIPE_CONNECTED"},
- {STATUS_PIPE_LISTENING, -EIO, "STATUS_PIPE_LISTENING"},
- {STATUS_INVALID_READ_MODE, -EIO, "STATUS_INVALID_READ_MODE"},
- {STATUS_IO_TIMEOUT, -EAGAIN, "STATUS_IO_TIMEOUT"},
- {STATUS_FILE_FORCED_CLOSED, -EIO, "STATUS_FILE_FORCED_CLOSED"},
- {STATUS_PROFILING_NOT_STARTED, -EIO, "STATUS_PROFILING_NOT_STARTED"},
- {STATUS_PROFILING_NOT_STOPPED, -EIO, "STATUS_PROFILING_NOT_STOPPED"},
- {STATUS_COULD_NOT_INTERPRET, -EIO, "STATUS_COULD_NOT_INTERPRET"},
- {STATUS_FILE_IS_A_DIRECTORY, -EISDIR, "STATUS_FILE_IS_A_DIRECTORY"},
- {STATUS_NOT_SUPPORTED, -EOPNOTSUPP, "STATUS_NOT_SUPPORTED"},
- {STATUS_REMOTE_NOT_LISTENING, -EHOSTDOWN,
- "STATUS_REMOTE_NOT_LISTENING"},
- {STATUS_DUPLICATE_NAME, -ENOTUNIQ, "STATUS_DUPLICATE_NAME"},
- {STATUS_BAD_NETWORK_PATH, -EINVAL, "STATUS_BAD_NETWORK_PATH"},
- {STATUS_NETWORK_BUSY, -EBUSY, "STATUS_NETWORK_BUSY"},
- {STATUS_DEVICE_DOES_NOT_EXIST, -ENODEV, "STATUS_DEVICE_DOES_NOT_EXIST"},
- {STATUS_TOO_MANY_COMMANDS, -EIO, "STATUS_TOO_MANY_COMMANDS"},
- {STATUS_ADAPTER_HARDWARE_ERROR, -EIO, "STATUS_ADAPTER_HARDWARE_ERROR"},
- {STATUS_INVALID_NETWORK_RESPONSE, -EIO,
- "STATUS_INVALID_NETWORK_RESPONSE"},
- {STATUS_UNEXPECTED_NETWORK_ERROR, -EIO,
- "STATUS_UNEXPECTED_NETWORK_ERROR"},
- {STATUS_BAD_REMOTE_ADAPTER, -EIO, "STATUS_BAD_REMOTE_ADAPTER"},
- {STATUS_PRINT_QUEUE_FULL, -EIO, "STATUS_PRINT_QUEUE_FULL"},
- {STATUS_NO_SPOOL_SPACE, -EIO, "STATUS_NO_SPOOL_SPACE"},
- {STATUS_PRINT_CANCELLED, -EIO, "STATUS_PRINT_CANCELLED"},
- {STATUS_NETWORK_NAME_DELETED, -EREMCHG, "STATUS_NETWORK_NAME_DELETED"},
- {STATUS_NETWORK_ACCESS_DENIED, -EACCES, "STATUS_NETWORK_ACCESS_DENIED"},
- {STATUS_BAD_DEVICE_TYPE, -EIO, "STATUS_BAD_DEVICE_TYPE"},
- {STATUS_BAD_NETWORK_NAME, -ENOENT, "STATUS_BAD_NETWORK_NAME"},
- {STATUS_TOO_MANY_NAMES, -EIO, "STATUS_TOO_MANY_NAMES"},
- {STATUS_TOO_MANY_SESSIONS, -EIO, "STATUS_TOO_MANY_SESSIONS"},
- {STATUS_SHARING_PAUSED, -EIO, "STATUS_SHARING_PAUSED"},
- {STATUS_REQUEST_NOT_ACCEPTED, -EIO, "STATUS_REQUEST_NOT_ACCEPTED"},
- {STATUS_REDIRECTOR_PAUSED, -EIO, "STATUS_REDIRECTOR_PAUSED"},
- {STATUS_NET_WRITE_FAULT, -EIO, "STATUS_NET_WRITE_FAULT"},
- {STATUS_PROFILING_AT_LIMIT, -EIO, "STATUS_PROFILING_AT_LIMIT"},
- {STATUS_NOT_SAME_DEVICE, -EXDEV, "STATUS_NOT_SAME_DEVICE"},
- {STATUS_FILE_RENAMED, -EIO, "STATUS_FILE_RENAMED"},
- {STATUS_VIRTUAL_CIRCUIT_CLOSED, -EIO, "STATUS_VIRTUAL_CIRCUIT_CLOSED"},
- {STATUS_NO_SECURITY_ON_OBJECT, -EIO, "STATUS_NO_SECURITY_ON_OBJECT"},
- {STATUS_CANT_WAIT, -EIO, "STATUS_CANT_WAIT"},
- {STATUS_PIPE_EMPTY, -EIO, "STATUS_PIPE_EMPTY"},
- {STATUS_CANT_ACCESS_DOMAIN_INFO, -EIO,
- "STATUS_CANT_ACCESS_DOMAIN_INFO"},
- {STATUS_CANT_TERMINATE_SELF, -EIO, "STATUS_CANT_TERMINATE_SELF"},
- {STATUS_INVALID_SERVER_STATE, -EIO, "STATUS_INVALID_SERVER_STATE"},
- {STATUS_INVALID_DOMAIN_STATE, -EIO, "STATUS_INVALID_DOMAIN_STATE"},
- {STATUS_INVALID_DOMAIN_ROLE, -EIO, "STATUS_INVALID_DOMAIN_ROLE"},
- {STATUS_NO_SUCH_DOMAIN, -EIO, "STATUS_NO_SUCH_DOMAIN"},
- {STATUS_DOMAIN_EXISTS, -EIO, "STATUS_DOMAIN_EXISTS"},
- {STATUS_DOMAIN_LIMIT_EXCEEDED, -EIO, "STATUS_DOMAIN_LIMIT_EXCEEDED"},
- {STATUS_OPLOCK_NOT_GRANTED, -EIO, "STATUS_OPLOCK_NOT_GRANTED"},
- {STATUS_INVALID_OPLOCK_PROTOCOL, -EIO,
- "STATUS_INVALID_OPLOCK_PROTOCOL"},
- {STATUS_INTERNAL_DB_CORRUPTION, -EIO, "STATUS_INTERNAL_DB_CORRUPTION"},
- {STATUS_INTERNAL_ERROR, -EIO, "STATUS_INTERNAL_ERROR"},
- {STATUS_GENERIC_NOT_MAPPED, -EIO, "STATUS_GENERIC_NOT_MAPPED"},
- {STATUS_BAD_DESCRIPTOR_FORMAT, -EIO, "STATUS_BAD_DESCRIPTOR_FORMAT"},
- {STATUS_INVALID_USER_BUFFER, -EIO, "STATUS_INVALID_USER_BUFFER"},
- {STATUS_UNEXPECTED_IO_ERROR, -EIO, "STATUS_UNEXPECTED_IO_ERROR"},
- {STATUS_UNEXPECTED_MM_CREATE_ERR, -EIO,
- "STATUS_UNEXPECTED_MM_CREATE_ERR"},
- {STATUS_UNEXPECTED_MM_MAP_ERROR, -EIO,
- "STATUS_UNEXPECTED_MM_MAP_ERROR"},
- {STATUS_UNEXPECTED_MM_EXTEND_ERR, -EIO,
- "STATUS_UNEXPECTED_MM_EXTEND_ERR"},
- {STATUS_NOT_LOGON_PROCESS, -EIO, "STATUS_NOT_LOGON_PROCESS"},
- {STATUS_LOGON_SESSION_EXISTS, -EIO, "STATUS_LOGON_SESSION_EXISTS"},
- {STATUS_INVALID_PARAMETER_1, -EINVAL, "STATUS_INVALID_PARAMETER_1"},
- {STATUS_INVALID_PARAMETER_2, -EINVAL, "STATUS_INVALID_PARAMETER_2"},
- {STATUS_INVALID_PARAMETER_3, -EINVAL, "STATUS_INVALID_PARAMETER_3"},
- {STATUS_INVALID_PARAMETER_4, -EINVAL, "STATUS_INVALID_PARAMETER_4"},
- {STATUS_INVALID_PARAMETER_5, -EINVAL, "STATUS_INVALID_PARAMETER_5"},
- {STATUS_INVALID_PARAMETER_6, -EINVAL, "STATUS_INVALID_PARAMETER_6"},
- {STATUS_INVALID_PARAMETER_7, -EINVAL, "STATUS_INVALID_PARAMETER_7"},
- {STATUS_INVALID_PARAMETER_8, -EINVAL, "STATUS_INVALID_PARAMETER_8"},
- {STATUS_INVALID_PARAMETER_9, -EINVAL, "STATUS_INVALID_PARAMETER_9"},
- {STATUS_INVALID_PARAMETER_10, -EINVAL, "STATUS_INVALID_PARAMETER_10"},
- {STATUS_INVALID_PARAMETER_11, -EINVAL, "STATUS_INVALID_PARAMETER_11"},
- {STATUS_INVALID_PARAMETER_12, -EINVAL, "STATUS_INVALID_PARAMETER_12"},
- {STATUS_REDIRECTOR_NOT_STARTED, -EIO, "STATUS_REDIRECTOR_NOT_STARTED"},
- {STATUS_REDIRECTOR_STARTED, -EIO, "STATUS_REDIRECTOR_STARTED"},
- {STATUS_STACK_OVERFLOW, -EIO, "STATUS_STACK_OVERFLOW"},
- {STATUS_NO_SUCH_PACKAGE, -EIO, "STATUS_NO_SUCH_PACKAGE"},
- {STATUS_BAD_FUNCTION_TABLE, -EIO, "STATUS_BAD_FUNCTION_TABLE"},
- {STATUS_VARIABLE_NOT_FOUND, -EIO, "STATUS_VARIABLE_NOT_FOUND"},
- {STATUS_DIRECTORY_NOT_EMPTY, -ENOTEMPTY, "STATUS_DIRECTORY_NOT_EMPTY"},
- {STATUS_FILE_CORRUPT_ERROR, -EIO, "STATUS_FILE_CORRUPT_ERROR"},
- {STATUS_NOT_A_DIRECTORY, -ENOTDIR, "STATUS_NOT_A_DIRECTORY"},
- {STATUS_BAD_LOGON_SESSION_STATE, -EIO,
- "STATUS_BAD_LOGON_SESSION_STATE"},
- {STATUS_LOGON_SESSION_COLLISION, -EIO,
- "STATUS_LOGON_SESSION_COLLISION"},
- {STATUS_NAME_TOO_LONG, -ENAMETOOLONG, "STATUS_NAME_TOO_LONG"},
- {STATUS_FILES_OPEN, -EIO, "STATUS_FILES_OPEN"},
- {STATUS_CONNECTION_IN_USE, -EIO, "STATUS_CONNECTION_IN_USE"},
- {STATUS_MESSAGE_NOT_FOUND, -EIO, "STATUS_MESSAGE_NOT_FOUND"},
- {STATUS_PROCESS_IS_TERMINATING, -EIO, "STATUS_PROCESS_IS_TERMINATING"},
- {STATUS_INVALID_LOGON_TYPE, -EIO, "STATUS_INVALID_LOGON_TYPE"},
- {STATUS_NO_GUID_TRANSLATION, -EIO, "STATUS_NO_GUID_TRANSLATION"},
- {STATUS_CANNOT_IMPERSONATE, -EIO, "STATUS_CANNOT_IMPERSONATE"},
- {STATUS_IMAGE_ALREADY_LOADED, -EIO, "STATUS_IMAGE_ALREADY_LOADED"},
- {STATUS_ABIOS_NOT_PRESENT, -EIO, "STATUS_ABIOS_NOT_PRESENT"},
- {STATUS_ABIOS_LID_NOT_EXIST, -EIO, "STATUS_ABIOS_LID_NOT_EXIST"},
- {STATUS_ABIOS_LID_ALREADY_OWNED, -EIO,
- "STATUS_ABIOS_LID_ALREADY_OWNED"},
- {STATUS_ABIOS_NOT_LID_OWNER, -EIO, "STATUS_ABIOS_NOT_LID_OWNER"},
- {STATUS_ABIOS_INVALID_COMMAND, -EIO, "STATUS_ABIOS_INVALID_COMMAND"},
- {STATUS_ABIOS_INVALID_LID, -EIO, "STATUS_ABIOS_INVALID_LID"},
- {STATUS_ABIOS_SELECTOR_NOT_AVAILABLE, -EIO,
- "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE"},
- {STATUS_ABIOS_INVALID_SELECTOR, -EIO, "STATUS_ABIOS_INVALID_SELECTOR"},
- {STATUS_NO_LDT, -EIO, "STATUS_NO_LDT"},
- {STATUS_INVALID_LDT_SIZE, -EIO, "STATUS_INVALID_LDT_SIZE"},
- {STATUS_INVALID_LDT_OFFSET, -EIO, "STATUS_INVALID_LDT_OFFSET"},
- {STATUS_INVALID_LDT_DESCRIPTOR, -EIO, "STATUS_INVALID_LDT_DESCRIPTOR"},
- {STATUS_INVALID_IMAGE_NE_FORMAT, -EIO,
- "STATUS_INVALID_IMAGE_NE_FORMAT"},
- {STATUS_RXACT_INVALID_STATE, -EIO, "STATUS_RXACT_INVALID_STATE"},
- {STATUS_RXACT_COMMIT_FAILURE, -EIO, "STATUS_RXACT_COMMIT_FAILURE"},
- {STATUS_MAPPED_FILE_SIZE_ZERO, -EIO, "STATUS_MAPPED_FILE_SIZE_ZERO"},
- {STATUS_TOO_MANY_OPENED_FILES, -EMFILE, "STATUS_TOO_MANY_OPENED_FILES"},
- {STATUS_CANCELLED, -EIO, "STATUS_CANCELLED"},
- {STATUS_CANNOT_DELETE, -EACCES, "STATUS_CANNOT_DELETE"},
- {STATUS_INVALID_COMPUTER_NAME, -EIO, "STATUS_INVALID_COMPUTER_NAME"},
- {STATUS_FILE_DELETED, -EIO, "STATUS_FILE_DELETED"},
- {STATUS_SPECIAL_ACCOUNT, -EIO, "STATUS_SPECIAL_ACCOUNT"},
- {STATUS_SPECIAL_GROUP, -EIO, "STATUS_SPECIAL_GROUP"},
- {STATUS_SPECIAL_USER, -EIO, "STATUS_SPECIAL_USER"},
- {STATUS_MEMBERS_PRIMARY_GROUP, -EIO, "STATUS_MEMBERS_PRIMARY_GROUP"},
- {STATUS_FILE_CLOSED, -EBADF, "STATUS_FILE_CLOSED"},
- {STATUS_TOO_MANY_THREADS, -EIO, "STATUS_TOO_MANY_THREADS"},
- {STATUS_THREAD_NOT_IN_PROCESS, -EIO, "STATUS_THREAD_NOT_IN_PROCESS"},
- {STATUS_TOKEN_ALREADY_IN_USE, -EIO, "STATUS_TOKEN_ALREADY_IN_USE"},
- {STATUS_PAGEFILE_QUOTA_EXCEEDED, -EDQUOT,
- "STATUS_PAGEFILE_QUOTA_EXCEEDED"},
- {STATUS_COMMITMENT_LIMIT, -EIO, "STATUS_COMMITMENT_LIMIT"},
- {STATUS_INVALID_IMAGE_LE_FORMAT, -EIO,
- "STATUS_INVALID_IMAGE_LE_FORMAT"},
- {STATUS_INVALID_IMAGE_NOT_MZ, -EIO, "STATUS_INVALID_IMAGE_NOT_MZ"},
- {STATUS_INVALID_IMAGE_PROTECT, -EIO, "STATUS_INVALID_IMAGE_PROTECT"},
- {STATUS_INVALID_IMAGE_WIN_16, -EIO, "STATUS_INVALID_IMAGE_WIN_16"},
- {STATUS_LOGON_SERVER_CONFLICT, -EIO, "STATUS_LOGON_SERVER_CONFLICT"},
- {STATUS_TIME_DIFFERENCE_AT_DC, -EIO, "STATUS_TIME_DIFFERENCE_AT_DC"},
- {STATUS_SYNCHRONIZATION_REQUIRED, -EIO,
- "STATUS_SYNCHRONIZATION_REQUIRED"},
- {STATUS_DLL_NOT_FOUND, -ENOENT, "STATUS_DLL_NOT_FOUND"},
- {STATUS_OPEN_FAILED, -EIO, "STATUS_OPEN_FAILED"},
- {STATUS_IO_PRIVILEGE_FAILED, -EIO, "STATUS_IO_PRIVILEGE_FAILED"},
- {STATUS_ORDINAL_NOT_FOUND, -EIO, "STATUS_ORDINAL_NOT_FOUND"},
- {STATUS_ENTRYPOINT_NOT_FOUND, -EIO, "STATUS_ENTRYPOINT_NOT_FOUND"},
- {STATUS_CONTROL_C_EXIT, -EIO, "STATUS_CONTROL_C_EXIT"},
- {STATUS_LOCAL_DISCONNECT, -EIO, "STATUS_LOCAL_DISCONNECT"},
- {STATUS_REMOTE_DISCONNECT, -ESHUTDOWN, "STATUS_REMOTE_DISCONNECT"},
- {STATUS_REMOTE_RESOURCES, -EIO, "STATUS_REMOTE_RESOURCES"},
- {STATUS_LINK_FAILED, -EXDEV, "STATUS_LINK_FAILED"},
- {STATUS_LINK_TIMEOUT, -ETIMEDOUT, "STATUS_LINK_TIMEOUT"},
- {STATUS_INVALID_CONNECTION, -EIO, "STATUS_INVALID_CONNECTION"},
- {STATUS_INVALID_ADDRESS, -EIO, "STATUS_INVALID_ADDRESS"},
- {STATUS_DLL_INIT_FAILED, -EIO, "STATUS_DLL_INIT_FAILED"},
- {STATUS_MISSING_SYSTEMFILE, -EIO, "STATUS_MISSING_SYSTEMFILE"},
- {STATUS_UNHANDLED_EXCEPTION, -EIO, "STATUS_UNHANDLED_EXCEPTION"},
- {STATUS_APP_INIT_FAILURE, -EIO, "STATUS_APP_INIT_FAILURE"},
- {STATUS_PAGEFILE_CREATE_FAILED, -EIO, "STATUS_PAGEFILE_CREATE_FAILED"},
- {STATUS_NO_PAGEFILE, -EIO, "STATUS_NO_PAGEFILE"},
- {STATUS_INVALID_LEVEL, -EIO, "STATUS_INVALID_LEVEL"},
- {STATUS_WRONG_PASSWORD_CORE, -EIO, "STATUS_WRONG_PASSWORD_CORE"},
- {STATUS_ILLEGAL_FLOAT_CONTEXT, -EIO, "STATUS_ILLEGAL_FLOAT_CONTEXT"},
- {STATUS_PIPE_BROKEN, -EPIPE, "STATUS_PIPE_BROKEN"},
- {STATUS_REGISTRY_CORRUPT, -EIO, "STATUS_REGISTRY_CORRUPT"},
- {STATUS_REGISTRY_IO_FAILED, -EIO, "STATUS_REGISTRY_IO_FAILED"},
- {STATUS_NO_EVENT_PAIR, -EIO, "STATUS_NO_EVENT_PAIR"},
- {STATUS_UNRECOGNIZED_VOLUME, -EIO, "STATUS_UNRECOGNIZED_VOLUME"},
- {STATUS_SERIAL_NO_DEVICE_INITED, -EIO,
- "STATUS_SERIAL_NO_DEVICE_INITED"},
- {STATUS_NO_SUCH_ALIAS, -EIO, "STATUS_NO_SUCH_ALIAS"},
- {STATUS_MEMBER_NOT_IN_ALIAS, -EIO, "STATUS_MEMBER_NOT_IN_ALIAS"},
- {STATUS_MEMBER_IN_ALIAS, -EIO, "STATUS_MEMBER_IN_ALIAS"},
- {STATUS_ALIAS_EXISTS, -EIO, "STATUS_ALIAS_EXISTS"},
- {STATUS_LOGON_NOT_GRANTED, -EIO, "STATUS_LOGON_NOT_GRANTED"},
- {STATUS_TOO_MANY_SECRETS, -EIO, "STATUS_TOO_MANY_SECRETS"},
- {STATUS_SECRET_TOO_LONG, -EIO, "STATUS_SECRET_TOO_LONG"},
- {STATUS_INTERNAL_DB_ERROR, -EIO, "STATUS_INTERNAL_DB_ERROR"},
- {STATUS_FULLSCREEN_MODE, -EIO, "STATUS_FULLSCREEN_MODE"},
- {STATUS_TOO_MANY_CONTEXT_IDS, -EIO, "STATUS_TOO_MANY_CONTEXT_IDS"},
- {STATUS_LOGON_TYPE_NOT_GRANTED, -EIO, "STATUS_LOGON_TYPE_NOT_GRANTED"},
- {STATUS_NOT_REGISTRY_FILE, -EIO, "STATUS_NOT_REGISTRY_FILE"},
- {STATUS_NT_CROSS_ENCRYPTION_REQUIRED, -EIO,
- "STATUS_NT_CROSS_ENCRYPTION_REQUIRED"},
- {STATUS_DOMAIN_CTRLR_CONFIG_ERROR, -EIO,
- "STATUS_DOMAIN_CTRLR_CONFIG_ERROR"},
- {STATUS_FT_MISSING_MEMBER, -EIO, "STATUS_FT_MISSING_MEMBER"},
- {STATUS_ILL_FORMED_SERVICE_ENTRY, -EIO,
- "STATUS_ILL_FORMED_SERVICE_ENTRY"},
- {STATUS_ILLEGAL_CHARACTER, -EIO, "STATUS_ILLEGAL_CHARACTER"},
- {STATUS_UNMAPPABLE_CHARACTER, -EIO, "STATUS_UNMAPPABLE_CHARACTER"},
- {STATUS_UNDEFINED_CHARACTER, -EIO, "STATUS_UNDEFINED_CHARACTER"},
- {STATUS_FLOPPY_VOLUME, -EIO, "STATUS_FLOPPY_VOLUME"},
- {STATUS_FLOPPY_ID_MARK_NOT_FOUND, -EIO,
- "STATUS_FLOPPY_ID_MARK_NOT_FOUND"},
- {STATUS_FLOPPY_WRONG_CYLINDER, -EIO, "STATUS_FLOPPY_WRONG_CYLINDER"},
- {STATUS_FLOPPY_UNKNOWN_ERROR, -EIO, "STATUS_FLOPPY_UNKNOWN_ERROR"},
- {STATUS_FLOPPY_BAD_REGISTERS, -EIO, "STATUS_FLOPPY_BAD_REGISTERS"},
- {STATUS_DISK_RECALIBRATE_FAILED, -EIO,
- "STATUS_DISK_RECALIBRATE_FAILED"},
- {STATUS_DISK_OPERATION_FAILED, -EIO, "STATUS_DISK_OPERATION_FAILED"},
- {STATUS_DISK_RESET_FAILED, -EIO, "STATUS_DISK_RESET_FAILED"},
- {STATUS_SHARED_IRQ_BUSY, -EBUSY, "STATUS_SHARED_IRQ_BUSY"},
- {STATUS_FT_ORPHANING, -EIO, "STATUS_FT_ORPHANING"},
- {STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT, -EIO,
- "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT"},
- {STATUS_PARTITION_FAILURE, -EIO, "STATUS_PARTITION_FAILURE"},
- {STATUS_INVALID_BLOCK_LENGTH, -EIO, "STATUS_INVALID_BLOCK_LENGTH"},
- {STATUS_DEVICE_NOT_PARTITIONED, -EIO, "STATUS_DEVICE_NOT_PARTITIONED"},
- {STATUS_UNABLE_TO_LOCK_MEDIA, -EIO, "STATUS_UNABLE_TO_LOCK_MEDIA"},
- {STATUS_UNABLE_TO_UNLOAD_MEDIA, -EIO, "STATUS_UNABLE_TO_UNLOAD_MEDIA"},
- {STATUS_EOM_OVERFLOW, -EIO, "STATUS_EOM_OVERFLOW"},
- {STATUS_NO_MEDIA, -EIO, "STATUS_NO_MEDIA"},
- {STATUS_NO_SUCH_MEMBER, -EIO, "STATUS_NO_SUCH_MEMBER"},
- {STATUS_INVALID_MEMBER, -EIO, "STATUS_INVALID_MEMBER"},
- {STATUS_KEY_DELETED, -EIO, "STATUS_KEY_DELETED"},
- {STATUS_NO_LOG_SPACE, -EIO, "STATUS_NO_LOG_SPACE"},
- {STATUS_TOO_MANY_SIDS, -EIO, "STATUS_TOO_MANY_SIDS"},
- {STATUS_LM_CROSS_ENCRYPTION_REQUIRED, -EIO,
- "STATUS_LM_CROSS_ENCRYPTION_REQUIRED"},
- {STATUS_KEY_HAS_CHILDREN, -EIO, "STATUS_KEY_HAS_CHILDREN"},
- {STATUS_CHILD_MUST_BE_VOLATILE, -EIO, "STATUS_CHILD_MUST_BE_VOLATILE"},
- {STATUS_DEVICE_CONFIGURATION_ERROR, -EIO,
- "STATUS_DEVICE_CONFIGURATION_ERROR"},
- {STATUS_DRIVER_INTERNAL_ERROR, -EIO, "STATUS_DRIVER_INTERNAL_ERROR"},
- {STATUS_INVALID_DEVICE_STATE, -EIO, "STATUS_INVALID_DEVICE_STATE"},
- {STATUS_IO_DEVICE_ERROR, -EIO, "STATUS_IO_DEVICE_ERROR"},
- {STATUS_DEVICE_PROTOCOL_ERROR, -EIO, "STATUS_DEVICE_PROTOCOL_ERROR"},
- {STATUS_BACKUP_CONTROLLER, -EIO, "STATUS_BACKUP_CONTROLLER"},
- {STATUS_LOG_FILE_FULL, -EIO, "STATUS_LOG_FILE_FULL"},
- {STATUS_TOO_LATE, -EIO, "STATUS_TOO_LATE"},
- {STATUS_NO_TRUST_LSA_SECRET, -EIO, "STATUS_NO_TRUST_LSA_SECRET"},
- {STATUS_NO_TRUST_SAM_ACCOUNT, -EIO, "STATUS_NO_TRUST_SAM_ACCOUNT"},
- {STATUS_TRUSTED_DOMAIN_FAILURE, -EIO, "STATUS_TRUSTED_DOMAIN_FAILURE"},
- {STATUS_TRUSTED_RELATIONSHIP_FAILURE, -EIO,
- "STATUS_TRUSTED_RELATIONSHIP_FAILURE"},
- {STATUS_EVENTLOG_FILE_CORRUPT, -EIO, "STATUS_EVENTLOG_FILE_CORRUPT"},
- {STATUS_EVENTLOG_CANT_START, -EIO, "STATUS_EVENTLOG_CANT_START"},
- {STATUS_TRUST_FAILURE, -EIO, "STATUS_TRUST_FAILURE"},
- {STATUS_MUTANT_LIMIT_EXCEEDED, -EIO, "STATUS_MUTANT_LIMIT_EXCEEDED"},
- {STATUS_NETLOGON_NOT_STARTED, -EIO, "STATUS_NETLOGON_NOT_STARTED"},
- {STATUS_ACCOUNT_EXPIRED, -EKEYEXPIRED, "STATUS_ACCOUNT_EXPIRED"},
- {STATUS_POSSIBLE_DEADLOCK, -EIO, "STATUS_POSSIBLE_DEADLOCK"},
- {STATUS_NETWORK_CREDENTIAL_CONFLICT, -EIO,
- "STATUS_NETWORK_CREDENTIAL_CONFLICT"},
- {STATUS_REMOTE_SESSION_LIMIT, -EIO, "STATUS_REMOTE_SESSION_LIMIT"},
- {STATUS_EVENTLOG_FILE_CHANGED, -EIO, "STATUS_EVENTLOG_FILE_CHANGED"},
- {STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT, -EIO,
- "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"},
- {STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, -EIO,
- "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"},
- {STATUS_NOLOGON_SERVER_TRUST_ACCOUNT, -EIO,
- "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"},
- {STATUS_DOMAIN_TRUST_INCONSISTENT, -EIO,
- "STATUS_DOMAIN_TRUST_INCONSISTENT"},
- {STATUS_FS_DRIVER_REQUIRED, -EOPNOTSUPP, "STATUS_FS_DRIVER_REQUIRED"},
- {STATUS_IMAGE_ALREADY_LOADED_AS_DLL, -EIO,
- "STATUS_IMAGE_ALREADY_LOADED_AS_DLL"},
- {STATUS_NETWORK_OPEN_RESTRICTION, -EIO,
- "STATUS_NETWORK_OPEN_RESTRICTION"},
- {STATUS_NO_USER_SESSION_KEY, -EIO, "STATUS_NO_USER_SESSION_KEY"},
- {STATUS_USER_SESSION_DELETED, -EIO, "STATUS_USER_SESSION_DELETED"},
- {STATUS_RESOURCE_LANG_NOT_FOUND, -EIO,
- "STATUS_RESOURCE_LANG_NOT_FOUND"},
- {STATUS_INSUFF_SERVER_RESOURCES, -EIO,
- "STATUS_INSUFF_SERVER_RESOURCES"},
- {STATUS_INVALID_BUFFER_SIZE, -EIO, "STATUS_INVALID_BUFFER_SIZE"},
- {STATUS_INVALID_ADDRESS_COMPONENT, -EIO,
- "STATUS_INVALID_ADDRESS_COMPONENT"},
- {STATUS_INVALID_ADDRESS_WILDCARD, -EIO,
- "STATUS_INVALID_ADDRESS_WILDCARD"},
- {STATUS_TOO_MANY_ADDRESSES, -EIO, "STATUS_TOO_MANY_ADDRESSES"},
- {STATUS_ADDRESS_ALREADY_EXISTS, -EADDRINUSE,
- "STATUS_ADDRESS_ALREADY_EXISTS"},
- {STATUS_ADDRESS_CLOSED, -EIO, "STATUS_ADDRESS_CLOSED"},
- {STATUS_CONNECTION_DISCONNECTED, -ECONNABORTED,
- "STATUS_CONNECTION_DISCONNECTED"},
- {STATUS_CONNECTION_RESET, -ENETRESET, "STATUS_CONNECTION_RESET"},
- {STATUS_TOO_MANY_NODES, -EIO, "STATUS_TOO_MANY_NODES"},
- {STATUS_TRANSACTION_ABORTED, -EIO, "STATUS_TRANSACTION_ABORTED"},
- {STATUS_TRANSACTION_TIMED_OUT, -EIO, "STATUS_TRANSACTION_TIMED_OUT"},
- {STATUS_TRANSACTION_NO_RELEASE, -EIO, "STATUS_TRANSACTION_NO_RELEASE"},
- {STATUS_TRANSACTION_NO_MATCH, -EIO, "STATUS_TRANSACTION_NO_MATCH"},
- {STATUS_TRANSACTION_RESPONDED, -EIO, "STATUS_TRANSACTION_RESPONDED"},
- {STATUS_TRANSACTION_INVALID_ID, -EIO, "STATUS_TRANSACTION_INVALID_ID"},
- {STATUS_TRANSACTION_INVALID_TYPE, -EIO,
- "STATUS_TRANSACTION_INVALID_TYPE"},
- {STATUS_NOT_SERVER_SESSION, -EIO, "STATUS_NOT_SERVER_SESSION"},
- {STATUS_NOT_CLIENT_SESSION, -EIO, "STATUS_NOT_CLIENT_SESSION"},
- {STATUS_CANNOT_LOAD_REGISTRY_FILE, -EIO,
- "STATUS_CANNOT_LOAD_REGISTRY_FILE"},
- {STATUS_DEBUG_ATTACH_FAILED, -EIO, "STATUS_DEBUG_ATTACH_FAILED"},
- {STATUS_SYSTEM_PROCESS_TERMINATED, -EIO,
- "STATUS_SYSTEM_PROCESS_TERMINATED"},
- {STATUS_DATA_NOT_ACCEPTED, -EIO, "STATUS_DATA_NOT_ACCEPTED"},
- {STATUS_NO_BROWSER_SERVERS_FOUND, -EIO,
- "STATUS_NO_BROWSER_SERVERS_FOUND"},
- {STATUS_VDM_HARD_ERROR, -EIO, "STATUS_VDM_HARD_ERROR"},
- {STATUS_DRIVER_CANCEL_TIMEOUT, -EIO, "STATUS_DRIVER_CANCEL_TIMEOUT"},
- {STATUS_REPLY_MESSAGE_MISMATCH, -EIO, "STATUS_REPLY_MESSAGE_MISMATCH"},
- {STATUS_MAPPED_ALIGNMENT, -EIO, "STATUS_MAPPED_ALIGNMENT"},
- {STATUS_IMAGE_CHECKSUM_MISMATCH, -EIO,
- "STATUS_IMAGE_CHECKSUM_MISMATCH"},
- {STATUS_LOST_WRITEBEHIND_DATA, -EIO, "STATUS_LOST_WRITEBEHIND_DATA"},
- {STATUS_CLIENT_SERVER_PARAMETERS_INVALID, -EIO,
- "STATUS_CLIENT_SERVER_PARAMETERS_INVALID"},
- {STATUS_PASSWORD_MUST_CHANGE, -EIO, "STATUS_PASSWORD_MUST_CHANGE"},
- {STATUS_NOT_FOUND, -ENOENT, "STATUS_NOT_FOUND"},
- {STATUS_NOT_TINY_STREAM, -EIO, "STATUS_NOT_TINY_STREAM"},
- {STATUS_RECOVERY_FAILURE, -EIO, "STATUS_RECOVERY_FAILURE"},
- {STATUS_STACK_OVERFLOW_READ, -EIO, "STATUS_STACK_OVERFLOW_READ"},
- {STATUS_FAIL_CHECK, -EIO, "STATUS_FAIL_CHECK"},
- {STATUS_DUPLICATE_OBJECTID, -EIO, "STATUS_DUPLICATE_OBJECTID"},
- {STATUS_OBJECTID_EXISTS, -EIO, "STATUS_OBJECTID_EXISTS"},
- {STATUS_CONVERT_TO_LARGE, -EIO, "STATUS_CONVERT_TO_LARGE"},
- {STATUS_RETRY, -EAGAIN, "STATUS_RETRY"},
- {STATUS_FOUND_OUT_OF_SCOPE, -EIO, "STATUS_FOUND_OUT_OF_SCOPE"},
- {STATUS_ALLOCATE_BUCKET, -EIO, "STATUS_ALLOCATE_BUCKET"},
- {STATUS_PROPSET_NOT_FOUND, -EIO, "STATUS_PROPSET_NOT_FOUND"},
- {STATUS_MARSHALL_OVERFLOW, -EIO, "STATUS_MARSHALL_OVERFLOW"},
- {STATUS_INVALID_VARIANT, -EIO, "STATUS_INVALID_VARIANT"},
- {STATUS_DOMAIN_CONTROLLER_NOT_FOUND, -EIO,
- "STATUS_DOMAIN_CONTROLLER_NOT_FOUND"},
- {STATUS_ACCOUNT_LOCKED_OUT, -EACCES, "STATUS_ACCOUNT_LOCKED_OUT"},
- {STATUS_HANDLE_NOT_CLOSABLE, -EIO, "STATUS_HANDLE_NOT_CLOSABLE"},
- {STATUS_CONNECTION_REFUSED, -EIO, "STATUS_CONNECTION_REFUSED"},
- {STATUS_GRACEFUL_DISCONNECT, -EIO, "STATUS_GRACEFUL_DISCONNECT"},
- {STATUS_ADDRESS_ALREADY_ASSOCIATED, -EIO,
- "STATUS_ADDRESS_ALREADY_ASSOCIATED"},
- {STATUS_ADDRESS_NOT_ASSOCIATED, -EIO, "STATUS_ADDRESS_NOT_ASSOCIATED"},
- {STATUS_CONNECTION_INVALID, -EIO, "STATUS_CONNECTION_INVALID"},
- {STATUS_CONNECTION_ACTIVE, -EIO, "STATUS_CONNECTION_ACTIVE"},
- {STATUS_NETWORK_UNREACHABLE, -ENETUNREACH,
- "STATUS_NETWORK_UNREACHABLE"},
- {STATUS_HOST_UNREACHABLE, -EHOSTDOWN, "STATUS_HOST_UNREACHABLE"},
- {STATUS_PROTOCOL_UNREACHABLE, -ENETUNREACH,
- "STATUS_PROTOCOL_UNREACHABLE"},
- {STATUS_PORT_UNREACHABLE, -ENETUNREACH, "STATUS_PORT_UNREACHABLE"},
- {STATUS_REQUEST_ABORTED, -EIO, "STATUS_REQUEST_ABORTED"},
- {STATUS_CONNECTION_ABORTED, -ECONNABORTED, "STATUS_CONNECTION_ABORTED"},
- {STATUS_BAD_COMPRESSION_BUFFER, -EIO, "STATUS_BAD_COMPRESSION_BUFFER"},
- {STATUS_USER_MAPPED_FILE, -EIO, "STATUS_USER_MAPPED_FILE"},
- {STATUS_AUDIT_FAILED, -EIO, "STATUS_AUDIT_FAILED"},
- {STATUS_TIMER_RESOLUTION_NOT_SET, -EIO,
- "STATUS_TIMER_RESOLUTION_NOT_SET"},
- {STATUS_CONNECTION_COUNT_LIMIT, -EIO, "STATUS_CONNECTION_COUNT_LIMIT"},
- {STATUS_LOGIN_TIME_RESTRICTION, -EACCES,
- "STATUS_LOGIN_TIME_RESTRICTION"},
- {STATUS_LOGIN_WKSTA_RESTRICTION, -EACCES,
- "STATUS_LOGIN_WKSTA_RESTRICTION"},
- {STATUS_IMAGE_MP_UP_MISMATCH, -EIO, "STATUS_IMAGE_MP_UP_MISMATCH"},
- {STATUS_INSUFFICIENT_LOGON_INFO, -EIO,
- "STATUS_INSUFFICIENT_LOGON_INFO"},
- {STATUS_BAD_DLL_ENTRYPOINT, -EIO, "STATUS_BAD_DLL_ENTRYPOINT"},
- {STATUS_BAD_SERVICE_ENTRYPOINT, -EIO, "STATUS_BAD_SERVICE_ENTRYPOINT"},
- {STATUS_LPC_REPLY_LOST, -EIO, "STATUS_LPC_REPLY_LOST"},
- {STATUS_IP_ADDRESS_CONFLICT1, -EIO, "STATUS_IP_ADDRESS_CONFLICT1"},
- {STATUS_IP_ADDRESS_CONFLICT2, -EIO, "STATUS_IP_ADDRESS_CONFLICT2"},
- {STATUS_REGISTRY_QUOTA_LIMIT, -EDQUOT, "STATUS_REGISTRY_QUOTA_LIMIT"},
- {STATUS_PATH_NOT_COVERED, -EREMOTE, "STATUS_PATH_NOT_COVERED"},
- {STATUS_NO_CALLBACK_ACTIVE, -EIO, "STATUS_NO_CALLBACK_ACTIVE"},
- {STATUS_LICENSE_QUOTA_EXCEEDED, -EACCES,
- "STATUS_LICENSE_QUOTA_EXCEEDED"},
- {STATUS_PWD_TOO_SHORT, -EIO, "STATUS_PWD_TOO_SHORT"},
- {STATUS_PWD_TOO_RECENT, -EIO, "STATUS_PWD_TOO_RECENT"},
- {STATUS_PWD_HISTORY_CONFLICT, -EIO, "STATUS_PWD_HISTORY_CONFLICT"},
- {STATUS_PLUGPLAY_NO_DEVICE, -EIO, "STATUS_PLUGPLAY_NO_DEVICE"},
- {STATUS_UNSUPPORTED_COMPRESSION, -EIO,
- "STATUS_UNSUPPORTED_COMPRESSION"},
- {STATUS_INVALID_HW_PROFILE, -EIO, "STATUS_INVALID_HW_PROFILE"},
- {STATUS_INVALID_PLUGPLAY_DEVICE_PATH, -EIO,
- "STATUS_INVALID_PLUGPLAY_DEVICE_PATH"},
- {STATUS_DRIVER_ORDINAL_NOT_FOUND, -EIO,
- "STATUS_DRIVER_ORDINAL_NOT_FOUND"},
- {STATUS_DRIVER_ENTRYPOINT_NOT_FOUND, -EIO,
- "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND"},
- {STATUS_RESOURCE_NOT_OWNED, -EIO, "STATUS_RESOURCE_NOT_OWNED"},
- {STATUS_TOO_MANY_LINKS, -EMLINK, "STATUS_TOO_MANY_LINKS"},
- {STATUS_QUOTA_LIST_INCONSISTENT, -EIO,
- "STATUS_QUOTA_LIST_INCONSISTENT"},
- {STATUS_FILE_IS_OFFLINE, -EIO, "STATUS_FILE_IS_OFFLINE"},
- {STATUS_EVALUATION_EXPIRATION, -EIO, "STATUS_EVALUATION_EXPIRATION"},
- {STATUS_ILLEGAL_DLL_RELOCATION, -EIO, "STATUS_ILLEGAL_DLL_RELOCATION"},
- {STATUS_LICENSE_VIOLATION, -EIO, "STATUS_LICENSE_VIOLATION"},
- {STATUS_DLL_INIT_FAILED_LOGOFF, -EIO, "STATUS_DLL_INIT_FAILED_LOGOFF"},
- {STATUS_DRIVER_UNABLE_TO_LOAD, -EIO, "STATUS_DRIVER_UNABLE_TO_LOAD"},
- {STATUS_DFS_UNAVAILABLE, -EIO, "STATUS_DFS_UNAVAILABLE"},
- {STATUS_VOLUME_DISMOUNTED, -EIO, "STATUS_VOLUME_DISMOUNTED"},
- {STATUS_WX86_INTERNAL_ERROR, -EIO, "STATUS_WX86_INTERNAL_ERROR"},
- {STATUS_WX86_FLOAT_STACK_CHECK, -EIO, "STATUS_WX86_FLOAT_STACK_CHECK"},
- {STATUS_VALIDATE_CONTINUE, -EIO, "STATUS_VALIDATE_CONTINUE"},
- {STATUS_NO_MATCH, -EIO, "STATUS_NO_MATCH"},
- {STATUS_NO_MORE_MATCHES, -EIO, "STATUS_NO_MORE_MATCHES"},
- {STATUS_NOT_A_REPARSE_POINT, -EIO, "STATUS_NOT_A_REPARSE_POINT"},
- {STATUS_IO_REPARSE_TAG_INVALID, -EIO, "STATUS_IO_REPARSE_TAG_INVALID"},
- {STATUS_IO_REPARSE_TAG_MISMATCH, -EIO,
- "STATUS_IO_REPARSE_TAG_MISMATCH"},
- {STATUS_IO_REPARSE_DATA_INVALID, -EIO,
- "STATUS_IO_REPARSE_DATA_INVALID"},
- {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EIO,
- "STATUS_IO_REPARSE_TAG_NOT_HANDLED"},
- {STATUS_REPARSE_POINT_NOT_RESOLVED, -EIO,
- "STATUS_REPARSE_POINT_NOT_RESOLVED"},
- {STATUS_DIRECTORY_IS_A_REPARSE_POINT, -EIO,
- "STATUS_DIRECTORY_IS_A_REPARSE_POINT"},
- {STATUS_RANGE_LIST_CONFLICT, -EIO, "STATUS_RANGE_LIST_CONFLICT"},
- {STATUS_SOURCE_ELEMENT_EMPTY, -EIO, "STATUS_SOURCE_ELEMENT_EMPTY"},
- {STATUS_DESTINATION_ELEMENT_FULL, -EIO,
- "STATUS_DESTINATION_ELEMENT_FULL"},
- {STATUS_ILLEGAL_ELEMENT_ADDRESS, -EIO,
- "STATUS_ILLEGAL_ELEMENT_ADDRESS"},
- {STATUS_MAGAZINE_NOT_PRESENT, -EIO, "STATUS_MAGAZINE_NOT_PRESENT"},
- {STATUS_REINITIALIZATION_NEEDED, -EIO,
- "STATUS_REINITIALIZATION_NEEDED"},
- {STATUS_ENCRYPTION_FAILED, -EIO, "STATUS_ENCRYPTION_FAILED"},
- {STATUS_DECRYPTION_FAILED, -EIO, "STATUS_DECRYPTION_FAILED"},
- {STATUS_RANGE_NOT_FOUND, -EIO, "STATUS_RANGE_NOT_FOUND"},
- {STATUS_NO_RECOVERY_POLICY, -EIO, "STATUS_NO_RECOVERY_POLICY"},
- {STATUS_NO_EFS, -EIO, "STATUS_NO_EFS"},
- {STATUS_WRONG_EFS, -EIO, "STATUS_WRONG_EFS"},
- {STATUS_NO_USER_KEYS, -EIO, "STATUS_NO_USER_KEYS"},
- {STATUS_FILE_NOT_ENCRYPTED, -EIO, "STATUS_FILE_NOT_ENCRYPTED"},
- {STATUS_NOT_EXPORT_FORMAT, -EIO, "STATUS_NOT_EXPORT_FORMAT"},
- {STATUS_FILE_ENCRYPTED, -EIO, "STATUS_FILE_ENCRYPTED"},
- {STATUS_WMI_GUID_NOT_FOUND, -EIO, "STATUS_WMI_GUID_NOT_FOUND"},
- {STATUS_WMI_INSTANCE_NOT_FOUND, -EIO, "STATUS_WMI_INSTANCE_NOT_FOUND"},
- {STATUS_WMI_ITEMID_NOT_FOUND, -EIO, "STATUS_WMI_ITEMID_NOT_FOUND"},
- {STATUS_WMI_TRY_AGAIN, -EIO, "STATUS_WMI_TRY_AGAIN"},
- {STATUS_SHARED_POLICY, -EIO, "STATUS_SHARED_POLICY"},
- {STATUS_POLICY_OBJECT_NOT_FOUND, -EIO,
- "STATUS_POLICY_OBJECT_NOT_FOUND"},
- {STATUS_POLICY_ONLY_IN_DS, -EIO, "STATUS_POLICY_ONLY_IN_DS"},
- {STATUS_VOLUME_NOT_UPGRADED, -EIO, "STATUS_VOLUME_NOT_UPGRADED"},
- {STATUS_REMOTE_STORAGE_NOT_ACTIVE, -EIO,
- "STATUS_REMOTE_STORAGE_NOT_ACTIVE"},
- {STATUS_REMOTE_STORAGE_MEDIA_ERROR, -EIO,
- "STATUS_REMOTE_STORAGE_MEDIA_ERROR"},
- {STATUS_NO_TRACKING_SERVICE, -EIO, "STATUS_NO_TRACKING_SERVICE"},
- {STATUS_SERVER_SID_MISMATCH, -EIO, "STATUS_SERVER_SID_MISMATCH"},
- {STATUS_DS_NO_ATTRIBUTE_OR_VALUE, -EIO,
- "STATUS_DS_NO_ATTRIBUTE_OR_VALUE"},
- {STATUS_DS_INVALID_ATTRIBUTE_SYNTAX, -EIO,
- "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX"},
- {STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED, -EIO,
- "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED"},
- {STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS, -EIO,
- "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS"},
- {STATUS_DS_BUSY, -EBUSY, "STATUS_DS_BUSY"},
- {STATUS_DS_UNAVAILABLE, -EIO, "STATUS_DS_UNAVAILABLE"},
- {STATUS_DS_NO_RIDS_ALLOCATED, -EIO, "STATUS_DS_NO_RIDS_ALLOCATED"},
- {STATUS_DS_NO_MORE_RIDS, -EIO, "STATUS_DS_NO_MORE_RIDS"},
- {STATUS_DS_INCORRECT_ROLE_OWNER, -EIO,
- "STATUS_DS_INCORRECT_ROLE_OWNER"},
- {STATUS_DS_RIDMGR_INIT_ERROR, -EIO, "STATUS_DS_RIDMGR_INIT_ERROR"},
- {STATUS_DS_OBJ_CLASS_VIOLATION, -EIO, "STATUS_DS_OBJ_CLASS_VIOLATION"},
- {STATUS_DS_CANT_ON_NON_LEAF, -EIO, "STATUS_DS_CANT_ON_NON_LEAF"},
- {STATUS_DS_CANT_ON_RDN, -EIO, "STATUS_DS_CANT_ON_RDN"},
- {STATUS_DS_CANT_MOD_OBJ_CLASS, -EIO, "STATUS_DS_CANT_MOD_OBJ_CLASS"},
- {STATUS_DS_CROSS_DOM_MOVE_FAILED, -EIO,
- "STATUS_DS_CROSS_DOM_MOVE_FAILED"},
- {STATUS_DS_GC_NOT_AVAILABLE, -EIO, "STATUS_DS_GC_NOT_AVAILABLE"},
- {STATUS_DIRECTORY_SERVICE_REQUIRED, -EIO,
- "STATUS_DIRECTORY_SERVICE_REQUIRED"},
- {STATUS_REPARSE_ATTRIBUTE_CONFLICT, -EIO,
- "STATUS_REPARSE_ATTRIBUTE_CONFLICT"},
- {STATUS_CANT_ENABLE_DENY_ONLY, -EIO, "STATUS_CANT_ENABLE_DENY_ONLY"},
- {STATUS_FLOAT_MULTIPLE_FAULTS, -EIO, "STATUS_FLOAT_MULTIPLE_FAULTS"},
- {STATUS_FLOAT_MULTIPLE_TRAPS, -EIO, "STATUS_FLOAT_MULTIPLE_TRAPS"},
- {STATUS_DEVICE_REMOVED, -EIO, "STATUS_DEVICE_REMOVED"},
- {STATUS_JOURNAL_DELETE_IN_PROGRESS, -EIO,
- "STATUS_JOURNAL_DELETE_IN_PROGRESS"},
- {STATUS_JOURNAL_NOT_ACTIVE, -EIO, "STATUS_JOURNAL_NOT_ACTIVE"},
- {STATUS_NOINTERFACE, -EIO, "STATUS_NOINTERFACE"},
- {STATUS_DS_ADMIN_LIMIT_EXCEEDED, -EIO,
- "STATUS_DS_ADMIN_LIMIT_EXCEEDED"},
- {STATUS_DRIVER_FAILED_SLEEP, -EIO, "STATUS_DRIVER_FAILED_SLEEP"},
- {STATUS_MUTUAL_AUTHENTICATION_FAILED, -EIO,
- "STATUS_MUTUAL_AUTHENTICATION_FAILED"},
- {STATUS_CORRUPT_SYSTEM_FILE, -EIO, "STATUS_CORRUPT_SYSTEM_FILE"},
- {STATUS_DATATYPE_MISALIGNMENT_ERROR, -EIO,
- "STATUS_DATATYPE_MISALIGNMENT_ERROR"},
- {STATUS_WMI_READ_ONLY, -EROFS, "STATUS_WMI_READ_ONLY"},
- {STATUS_WMI_SET_FAILURE, -EIO, "STATUS_WMI_SET_FAILURE"},
- {STATUS_COMMITMENT_MINIMUM, -EIO, "STATUS_COMMITMENT_MINIMUM"},
- {STATUS_REG_NAT_CONSUMPTION, -EIO, "STATUS_REG_NAT_CONSUMPTION"},
- {STATUS_TRANSPORT_FULL, -EIO, "STATUS_TRANSPORT_FULL"},
- {STATUS_DS_SAM_INIT_FAILURE, -EIO, "STATUS_DS_SAM_INIT_FAILURE"},
- {STATUS_ONLY_IF_CONNECTED, -EIO, "STATUS_ONLY_IF_CONNECTED"},
- {STATUS_DS_SENSITIVE_GROUP_VIOLATION, -EIO,
- "STATUS_DS_SENSITIVE_GROUP_VIOLATION"},
- {STATUS_PNP_RESTART_ENUMERATION, -EIO,
- "STATUS_PNP_RESTART_ENUMERATION"},
- {STATUS_JOURNAL_ENTRY_DELETED, -EIO, "STATUS_JOURNAL_ENTRY_DELETED"},
- {STATUS_DS_CANT_MOD_PRIMARYGROUPID, -EIO,
- "STATUS_DS_CANT_MOD_PRIMARYGROUPID"},
- {STATUS_SYSTEM_IMAGE_BAD_SIGNATURE, -EIO,
- "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE"},
- {STATUS_PNP_REBOOT_REQUIRED, -EIO, "STATUS_PNP_REBOOT_REQUIRED"},
- {STATUS_POWER_STATE_INVALID, -EIO, "STATUS_POWER_STATE_INVALID"},
- {STATUS_DS_INVALID_GROUP_TYPE, -EIO, "STATUS_DS_INVALID_GROUP_TYPE"},
- {STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN, -EIO,
- "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN"},
- {STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN, -EIO,
- "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN"},
- {STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER, -EIO,
- "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER"},
- {STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER, -EIO,
- "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER"},
- {STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER, -EIO,
- "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER"},
- {STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER, -EIO,
- "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER"},
- {STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER, -EIO,
- "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER"},
- {STATUS_DS_HAVE_PRIMARY_MEMBERS, -EIO,
- "STATUS_DS_HAVE_PRIMARY_MEMBERS"},
- {STATUS_WMI_NOT_SUPPORTED, -EOPNOTSUPP, "STATUS_WMI_NOT_SUPPORTED"},
- {STATUS_INSUFFICIENT_POWER, -EIO, "STATUS_INSUFFICIENT_POWER"},
- {STATUS_SAM_NEED_BOOTKEY_PASSWORD, -EIO,
- "STATUS_SAM_NEED_BOOTKEY_PASSWORD"},
- {STATUS_SAM_NEED_BOOTKEY_FLOPPY, -EIO,
- "STATUS_SAM_NEED_BOOTKEY_FLOPPY"},
- {STATUS_DS_CANT_START, -EIO, "STATUS_DS_CANT_START"},
- {STATUS_DS_INIT_FAILURE, -EIO, "STATUS_DS_INIT_FAILURE"},
- {STATUS_SAM_INIT_FAILURE, -EIO, "STATUS_SAM_INIT_FAILURE"},
- {STATUS_DS_GC_REQUIRED, -EIO, "STATUS_DS_GC_REQUIRED"},
- {STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY, -EIO,
- "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY"},
- {STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS, -EIO,
- "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS"},
- {STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED, -EDQUOT,
- "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED"},
- {STATUS_MULTIPLE_FAULT_VIOLATION, -EIO,
- "STATUS_MULTIPLE_FAULT_VIOLATION"},
- {STATUS_CURRENT_DOMAIN_NOT_ALLOWED, -EIO,
- "STATUS_CURRENT_DOMAIN_NOT_ALLOWED"},
- {STATUS_CANNOT_MAKE, -EIO, "STATUS_CANNOT_MAKE"},
- {STATUS_SYSTEM_SHUTDOWN, -EIO, "STATUS_SYSTEM_SHUTDOWN"},
- {STATUS_DS_INIT_FAILURE_CONSOLE, -EIO,
- "STATUS_DS_INIT_FAILURE_CONSOLE"},
- {STATUS_DS_SAM_INIT_FAILURE_CONSOLE, -EIO,
- "STATUS_DS_SAM_INIT_FAILURE_CONSOLE"},
- {STATUS_UNFINISHED_CONTEXT_DELETED, -EIO,
- "STATUS_UNFINISHED_CONTEXT_DELETED"},
- {STATUS_NO_TGT_REPLY, -EIO, "STATUS_NO_TGT_REPLY"},
- /* Note that ENOATTTR and ENODATA are the same errno */
- {STATUS_OBJECTID_NOT_FOUND, -ENODATA, "STATUS_OBJECTID_NOT_FOUND"},
- {STATUS_NO_IP_ADDRESSES, -EIO, "STATUS_NO_IP_ADDRESSES"},
- {STATUS_WRONG_CREDENTIAL_HANDLE, -EIO,
- "STATUS_WRONG_CREDENTIAL_HANDLE"},
- {STATUS_CRYPTO_SYSTEM_INVALID, -EIO, "STATUS_CRYPTO_SYSTEM_INVALID"},
- {STATUS_MAX_REFERRALS_EXCEEDED, -EIO, "STATUS_MAX_REFERRALS_EXCEEDED"},
- {STATUS_MUST_BE_KDC, -EIO, "STATUS_MUST_BE_KDC"},
- {STATUS_STRONG_CRYPTO_NOT_SUPPORTED, -EIO,
- "STATUS_STRONG_CRYPTO_NOT_SUPPORTED"},
- {STATUS_TOO_MANY_PRINCIPALS, -EIO, "STATUS_TOO_MANY_PRINCIPALS"},
- {STATUS_NO_PA_DATA, -EIO, "STATUS_NO_PA_DATA"},
- {STATUS_PKINIT_NAME_MISMATCH, -EIO, "STATUS_PKINIT_NAME_MISMATCH"},
- {STATUS_SMARTCARD_LOGON_REQUIRED, -EIO,
- "STATUS_SMARTCARD_LOGON_REQUIRED"},
- {STATUS_KDC_INVALID_REQUEST, -EIO, "STATUS_KDC_INVALID_REQUEST"},
- {STATUS_KDC_UNABLE_TO_REFER, -EIO, "STATUS_KDC_UNABLE_TO_REFER"},
- {STATUS_KDC_UNKNOWN_ETYPE, -EIO, "STATUS_KDC_UNKNOWN_ETYPE"},
- {STATUS_SHUTDOWN_IN_PROGRESS, -EIO, "STATUS_SHUTDOWN_IN_PROGRESS"},
- {STATUS_SERVER_SHUTDOWN_IN_PROGRESS, -EIO,
- "STATUS_SERVER_SHUTDOWN_IN_PROGRESS"},
- {STATUS_NOT_SUPPORTED_ON_SBS, -EOPNOTSUPP,
- "STATUS_NOT_SUPPORTED_ON_SBS"},
- {STATUS_WMI_GUID_DISCONNECTED, -EIO, "STATUS_WMI_GUID_DISCONNECTED"},
- {STATUS_WMI_ALREADY_DISABLED, -EIO, "STATUS_WMI_ALREADY_DISABLED"},
- {STATUS_WMI_ALREADY_ENABLED, -EIO, "STATUS_WMI_ALREADY_ENABLED"},
- {STATUS_MFT_TOO_FRAGMENTED, -EIO, "STATUS_MFT_TOO_FRAGMENTED"},
- {STATUS_COPY_PROTECTION_FAILURE, -EIO,
- "STATUS_COPY_PROTECTION_FAILURE"},
- {STATUS_CSS_AUTHENTICATION_FAILURE, -EIO,
- "STATUS_CSS_AUTHENTICATION_FAILURE"},
- {STATUS_CSS_KEY_NOT_PRESENT, -EIO, "STATUS_CSS_KEY_NOT_PRESENT"},
- {STATUS_CSS_KEY_NOT_ESTABLISHED, -EIO,
- "STATUS_CSS_KEY_NOT_ESTABLISHED"},
- {STATUS_CSS_SCRAMBLED_SECTOR, -EIO, "STATUS_CSS_SCRAMBLED_SECTOR"},
- {STATUS_CSS_REGION_MISMATCH, -EIO, "STATUS_CSS_REGION_MISMATCH"},
- {STATUS_CSS_RESETS_EXHAUSTED, -EIO, "STATUS_CSS_RESETS_EXHAUSTED"},
- {STATUS_PKINIT_FAILURE, -EIO, "STATUS_PKINIT_FAILURE"},
- {STATUS_SMARTCARD_SUBSYSTEM_FAILURE, -EIO,
- "STATUS_SMARTCARD_SUBSYSTEM_FAILURE"},
- {STATUS_NO_KERB_KEY, -EIO, "STATUS_NO_KERB_KEY"},
- {STATUS_HOST_DOWN, -EIO, "STATUS_HOST_DOWN"},
- {STATUS_UNSUPPORTED_PREAUTH, -EIO, "STATUS_UNSUPPORTED_PREAUTH"},
- {STATUS_EFS_ALG_BLOB_TOO_BIG, -EIO, "STATUS_EFS_ALG_BLOB_TOO_BIG"},
- {STATUS_PORT_NOT_SET, -EIO, "STATUS_PORT_NOT_SET"},
- {STATUS_DEBUGGER_INACTIVE, -EIO, "STATUS_DEBUGGER_INACTIVE"},
- {STATUS_DS_VERSION_CHECK_FAILURE, -EIO,
- "STATUS_DS_VERSION_CHECK_FAILURE"},
- {STATUS_AUDITING_DISABLED, -EIO, "STATUS_AUDITING_DISABLED"},
- {STATUS_PRENT4_MACHINE_ACCOUNT, -EIO, "STATUS_PRENT4_MACHINE_ACCOUNT"},
- {STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER, -EIO,
- "STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER"},
- {STATUS_INVALID_IMAGE_WIN_32, -EIO, "STATUS_INVALID_IMAGE_WIN_32"},
- {STATUS_INVALID_IMAGE_WIN_64, -EIO, "STATUS_INVALID_IMAGE_WIN_64"},
- {STATUS_BAD_BINDINGS, -EIO, "STATUS_BAD_BINDINGS"},
- {STATUS_NETWORK_SESSION_EXPIRED, -EIO,
- "STATUS_NETWORK_SESSION_EXPIRED"},
- {STATUS_APPHELP_BLOCK, -EIO, "STATUS_APPHELP_BLOCK"},
- {STATUS_ALL_SIDS_FILTERED, -EIO, "STATUS_ALL_SIDS_FILTERED"},
- {STATUS_NOT_SAFE_MODE_DRIVER, -EIO, "STATUS_NOT_SAFE_MODE_DRIVER"},
- {STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT, -EACCES,
- "STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT"},
- {STATUS_ACCESS_DISABLED_BY_POLICY_PATH, -EACCES,
- "STATUS_ACCESS_DISABLED_BY_POLICY_PATH"},
- {STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER, -EACCES,
- "STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER"},
- {STATUS_ACCESS_DISABLED_BY_POLICY_OTHER, -EACCES,
- "STATUS_ACCESS_DISABLED_BY_POLICY_OTHER"},
- {STATUS_FAILED_DRIVER_ENTRY, -EIO, "STATUS_FAILED_DRIVER_ENTRY"},
- {STATUS_DEVICE_ENUMERATION_ERROR, -EIO,
- "STATUS_DEVICE_ENUMERATION_ERROR"},
- {STATUS_MOUNT_POINT_NOT_RESOLVED, -EIO,
- "STATUS_MOUNT_POINT_NOT_RESOLVED"},
- {STATUS_INVALID_DEVICE_OBJECT_PARAMETER, -EIO,
- "STATUS_INVALID_DEVICE_OBJECT_PARAMETER"},
- {STATUS_MCA_OCCURED, -EIO, "STATUS_MCA_OCCURED"},
- {STATUS_DRIVER_BLOCKED_CRITICAL, -EIO,
- "STATUS_DRIVER_BLOCKED_CRITICAL"},
- {STATUS_DRIVER_BLOCKED, -EIO, "STATUS_DRIVER_BLOCKED"},
- {STATUS_DRIVER_DATABASE_ERROR, -EIO, "STATUS_DRIVER_DATABASE_ERROR"},
- {STATUS_SYSTEM_HIVE_TOO_LARGE, -EIO, "STATUS_SYSTEM_HIVE_TOO_LARGE"},
- {STATUS_INVALID_IMPORT_OF_NON_DLL, -EIO,
- "STATUS_INVALID_IMPORT_OF_NON_DLL"},
- {STATUS_NO_SECRETS, -EIO, "STATUS_NO_SECRETS"},
- {STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY, -EACCES,
- "STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY"},
- {STATUS_FAILED_STACK_SWITCH, -EIO, "STATUS_FAILED_STACK_SWITCH"},
- {STATUS_HEAP_CORRUPTION, -EIO, "STATUS_HEAP_CORRUPTION"},
- {STATUS_SMARTCARD_WRONG_PIN, -EIO, "STATUS_SMARTCARD_WRONG_PIN"},
- {STATUS_SMARTCARD_CARD_BLOCKED, -EIO, "STATUS_SMARTCARD_CARD_BLOCKED"},
- {STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED, -EIO,
- "STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED"},
- {STATUS_SMARTCARD_NO_CARD, -EIO, "STATUS_SMARTCARD_NO_CARD"},
- {STATUS_SMARTCARD_NO_KEY_CONTAINER, -EIO,
- "STATUS_SMARTCARD_NO_KEY_CONTAINER"},
- {STATUS_SMARTCARD_NO_CERTIFICATE, -EIO,
- "STATUS_SMARTCARD_NO_CERTIFICATE"},
- {STATUS_SMARTCARD_NO_KEYSET, -EIO, "STATUS_SMARTCARD_NO_KEYSET"},
- {STATUS_SMARTCARD_IO_ERROR, -EIO, "STATUS_SMARTCARD_IO_ERROR"},
- {STATUS_DOWNGRADE_DETECTED, -EIO, "STATUS_DOWNGRADE_DETECTED"},
- {STATUS_SMARTCARD_CERT_REVOKED, -EIO, "STATUS_SMARTCARD_CERT_REVOKED"},
- {STATUS_ISSUING_CA_UNTRUSTED, -EIO, "STATUS_ISSUING_CA_UNTRUSTED"},
- {STATUS_REVOCATION_OFFLINE_C, -EIO, "STATUS_REVOCATION_OFFLINE_C"},
- {STATUS_PKINIT_CLIENT_FAILURE, -EIO, "STATUS_PKINIT_CLIENT_FAILURE"},
- {STATUS_SMARTCARD_CERT_EXPIRED, -EIO, "STATUS_SMARTCARD_CERT_EXPIRED"},
- {STATUS_DRIVER_FAILED_PRIOR_UNLOAD, -EIO,
- "STATUS_DRIVER_FAILED_PRIOR_UNLOAD"},
- {STATUS_SMARTCARD_SILENT_CONTEXT, -EIO,
- "STATUS_SMARTCARD_SILENT_CONTEXT"},
- {STATUS_PER_USER_TRUST_QUOTA_EXCEEDED, -EDQUOT,
- "STATUS_PER_USER_TRUST_QUOTA_EXCEEDED"},
- {STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED, -EDQUOT,
- "STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED"},
- {STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED, -EDQUOT,
- "STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED"},
- {STATUS_DS_NAME_NOT_UNIQUE, -EIO, "STATUS_DS_NAME_NOT_UNIQUE"},
- {STATUS_DS_DUPLICATE_ID_FOUND, -EIO, "STATUS_DS_DUPLICATE_ID_FOUND"},
- {STATUS_DS_GROUP_CONVERSION_ERROR, -EIO,
- "STATUS_DS_GROUP_CONVERSION_ERROR"},
- {STATUS_VOLSNAP_PREPARE_HIBERNATE, -EIO,
- "STATUS_VOLSNAP_PREPARE_HIBERNATE"},
- {STATUS_USER2USER_REQUIRED, -EIO, "STATUS_USER2USER_REQUIRED"},
- {STATUS_STACK_BUFFER_OVERRUN, -EIO, "STATUS_STACK_BUFFER_OVERRUN"},
- {STATUS_NO_S4U_PROT_SUPPORT, -EIO, "STATUS_NO_S4U_PROT_SUPPORT"},
- {STATUS_CROSSREALM_DELEGATION_FAILURE, -EIO,
- "STATUS_CROSSREALM_DELEGATION_FAILURE"},
- {STATUS_REVOCATION_OFFLINE_KDC, -EIO, "STATUS_REVOCATION_OFFLINE_KDC"},
- {STATUS_ISSUING_CA_UNTRUSTED_KDC, -EIO,
- "STATUS_ISSUING_CA_UNTRUSTED_KDC"},
- {STATUS_KDC_CERT_EXPIRED, -EIO, "STATUS_KDC_CERT_EXPIRED"},
- {STATUS_KDC_CERT_REVOKED, -EIO, "STATUS_KDC_CERT_REVOKED"},
- {STATUS_PARAMETER_QUOTA_EXCEEDED, -EDQUOT,
- "STATUS_PARAMETER_QUOTA_EXCEEDED"},
- {STATUS_HIBERNATION_FAILURE, -EIO, "STATUS_HIBERNATION_FAILURE"},
- {STATUS_DELAY_LOAD_FAILED, -EIO, "STATUS_DELAY_LOAD_FAILED"},
- {STATUS_AUTHENTICATION_FIREWALL_FAILED, -EIO,
- "STATUS_AUTHENTICATION_FIREWALL_FAILED"},
- {STATUS_VDM_DISALLOWED, -EIO, "STATUS_VDM_DISALLOWED"},
- {STATUS_HUNG_DISPLAY_DRIVER_THREAD, -EIO,
- "STATUS_HUNG_DISPLAY_DRIVER_THREAD"},
- {STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE, -EIO,
- "STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE"},
- {STATUS_INVALID_CRUNTIME_PARAMETER, -EIO,
- "STATUS_INVALID_CRUNTIME_PARAMETER"},
- {STATUS_NTLM_BLOCKED, -EIO, "STATUS_NTLM_BLOCKED"},
- {STATUS_ASSERTION_FAILURE, -EIO, "STATUS_ASSERTION_FAILURE"},
- {STATUS_VERIFIER_STOP, -EIO, "STATUS_VERIFIER_STOP"},
- {STATUS_CALLBACK_POP_STACK, -EIO, "STATUS_CALLBACK_POP_STACK"},
- {STATUS_INCOMPATIBLE_DRIVER_BLOCKED, -EIO,
- "STATUS_INCOMPATIBLE_DRIVER_BLOCKED"},
- {STATUS_HIVE_UNLOADED, -EIO, "STATUS_HIVE_UNLOADED"},
- {STATUS_COMPRESSION_DISABLED, -EIO, "STATUS_COMPRESSION_DISABLED"},
- {STATUS_FILE_SYSTEM_LIMITATION, -EIO, "STATUS_FILE_SYSTEM_LIMITATION"},
- {STATUS_INVALID_IMAGE_HASH, -EIO, "STATUS_INVALID_IMAGE_HASH"},
- {STATUS_NOT_CAPABLE, -EIO, "STATUS_NOT_CAPABLE"},
- {STATUS_REQUEST_OUT_OF_SEQUENCE, -EIO,
- "STATUS_REQUEST_OUT_OF_SEQUENCE"},
- {STATUS_IMPLEMENTATION_LIMIT, -EIO, "STATUS_IMPLEMENTATION_LIMIT"},
- {STATUS_ELEVATION_REQUIRED, -EIO, "STATUS_ELEVATION_REQUIRED"},
- {STATUS_BEYOND_VDL, -EIO, "STATUS_BEYOND_VDL"},
- {STATUS_ENCOUNTERED_WRITE_IN_PROGRESS, -EIO,
- "STATUS_ENCOUNTERED_WRITE_IN_PROGRESS"},
- {STATUS_PTE_CHANGED, -EIO, "STATUS_PTE_CHANGED"},
- {STATUS_PURGE_FAILED, -EIO, "STATUS_PURGE_FAILED"},
- {STATUS_CRED_REQUIRES_CONFIRMATION, -EIO,
- "STATUS_CRED_REQUIRES_CONFIRMATION"},
- {STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE, -EIO,
- "STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE"},
- {STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER, -EIO,
- "STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER"},
- {STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE, -EIO,
- "STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE"},
- {STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE, -EIO,
- "STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE"},
- {STATUS_CS_ENCRYPTION_FILE_NOT_CSE, -EIO,
- "STATUS_CS_ENCRYPTION_FILE_NOT_CSE"},
- {STATUS_INVALID_LABEL, -EIO, "STATUS_INVALID_LABEL"},
- {STATUS_DRIVER_PROCESS_TERMINATED, -EIO,
- "STATUS_DRIVER_PROCESS_TERMINATED"},
- {STATUS_AMBIGUOUS_SYSTEM_DEVICE, -EIO,
- "STATUS_AMBIGUOUS_SYSTEM_DEVICE"},
- {STATUS_SYSTEM_DEVICE_NOT_FOUND, -EIO,
- "STATUS_SYSTEM_DEVICE_NOT_FOUND"},
- {STATUS_RESTART_BOOT_APPLICATION, -EIO,
- "STATUS_RESTART_BOOT_APPLICATION"},
- {STATUS_INVALID_TASK_NAME, -EIO, "STATUS_INVALID_TASK_NAME"},
- {STATUS_INVALID_TASK_INDEX, -EIO, "STATUS_INVALID_TASK_INDEX"},
- {STATUS_THREAD_ALREADY_IN_TASK, -EIO, "STATUS_THREAD_ALREADY_IN_TASK"},
- {STATUS_CALLBACK_BYPASS, -EIO, "STATUS_CALLBACK_BYPASS"},
- {STATUS_PORT_CLOSED, -EIO, "STATUS_PORT_CLOSED"},
- {STATUS_MESSAGE_LOST, -EIO, "STATUS_MESSAGE_LOST"},
- {STATUS_INVALID_MESSAGE, -EIO, "STATUS_INVALID_MESSAGE"},
- {STATUS_REQUEST_CANCELED, -EIO, "STATUS_REQUEST_CANCELED"},
- {STATUS_RECURSIVE_DISPATCH, -EIO, "STATUS_RECURSIVE_DISPATCH"},
- {STATUS_LPC_RECEIVE_BUFFER_EXPECTED, -EIO,
- "STATUS_LPC_RECEIVE_BUFFER_EXPECTED"},
- {STATUS_LPC_INVALID_CONNECTION_USAGE, -EIO,
- "STATUS_LPC_INVALID_CONNECTION_USAGE"},
- {STATUS_LPC_REQUESTS_NOT_ALLOWED, -EIO,
- "STATUS_LPC_REQUESTS_NOT_ALLOWED"},
- {STATUS_RESOURCE_IN_USE, -EIO, "STATUS_RESOURCE_IN_USE"},
- {STATUS_HARDWARE_MEMORY_ERROR, -EIO, "STATUS_HARDWARE_MEMORY_ERROR"},
- {STATUS_THREADPOOL_HANDLE_EXCEPTION, -EIO,
- "STATUS_THREADPOOL_HANDLE_EXCEPTION"},
- {STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED, -EIO,
- "STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED"},
- {STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED, -EIO,
- "STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED"},
- {STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED, -EIO,
- "STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED"},
- {STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED, -EIO,
- "STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED"},
- {STATUS_THREADPOOL_RELEASED_DURING_OPERATION, -EIO,
- "STATUS_THREADPOOL_RELEASED_DURING_OPERATION"},
- {STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING, -EIO,
- "STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING"},
- {STATUS_APC_RETURNED_WHILE_IMPERSONATING, -EIO,
- "STATUS_APC_RETURNED_WHILE_IMPERSONATING"},
- {STATUS_PROCESS_IS_PROTECTED, -EIO, "STATUS_PROCESS_IS_PROTECTED"},
- {STATUS_MCA_EXCEPTION, -EIO, "STATUS_MCA_EXCEPTION"},
- {STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE, -EIO,
- "STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE"},
- {STATUS_SYMLINK_CLASS_DISABLED, -EIO, "STATUS_SYMLINK_CLASS_DISABLED"},
- {STATUS_INVALID_IDN_NORMALIZATION, -EIO,
- "STATUS_INVALID_IDN_NORMALIZATION"},
- {STATUS_NO_UNICODE_TRANSLATION, -EIO, "STATUS_NO_UNICODE_TRANSLATION"},
- {STATUS_ALREADY_REGISTERED, -EIO, "STATUS_ALREADY_REGISTERED"},
- {STATUS_CONTEXT_MISMATCH, -EIO, "STATUS_CONTEXT_MISMATCH"},
- {STATUS_PORT_ALREADY_HAS_COMPLETION_LIST, -EIO,
- "STATUS_PORT_ALREADY_HAS_COMPLETION_LIST"},
- {STATUS_CALLBACK_RETURNED_THREAD_PRIORITY, -EIO,
- "STATUS_CALLBACK_RETURNED_THREAD_PRIORITY"},
- {STATUS_INVALID_THREAD, -EIO, "STATUS_INVALID_THREAD"},
- {STATUS_CALLBACK_RETURNED_TRANSACTION, -EIO,
- "STATUS_CALLBACK_RETURNED_TRANSACTION"},
- {STATUS_CALLBACK_RETURNED_LDR_LOCK, -EIO,
- "STATUS_CALLBACK_RETURNED_LDR_LOCK"},
- {STATUS_CALLBACK_RETURNED_LANG, -EIO, "STATUS_CALLBACK_RETURNED_LANG"},
- {STATUS_CALLBACK_RETURNED_PRI_BACK, -EIO,
- "STATUS_CALLBACK_RETURNED_PRI_BACK"},
- {STATUS_CALLBACK_RETURNED_THREAD_AFFINITY, -EIO,
- "STATUS_CALLBACK_RETURNED_THREAD_AFFINITY"},
- {STATUS_DISK_REPAIR_DISABLED, -EIO, "STATUS_DISK_REPAIR_DISABLED"},
- {STATUS_DS_DOMAIN_RENAME_IN_PROGRESS, -EIO,
- "STATUS_DS_DOMAIN_RENAME_IN_PROGRESS"},
- {STATUS_DISK_QUOTA_EXCEEDED, -EDQUOT, "STATUS_DISK_QUOTA_EXCEEDED"},
- {STATUS_CONTENT_BLOCKED, -EIO, "STATUS_CONTENT_BLOCKED"},
- {STATUS_BAD_CLUSTERS, -EIO, "STATUS_BAD_CLUSTERS"},
- {STATUS_VOLUME_DIRTY, -EIO, "STATUS_VOLUME_DIRTY"},
- {STATUS_FILE_CHECKED_OUT, -EIO, "STATUS_FILE_CHECKED_OUT"},
- {STATUS_CHECKOUT_REQUIRED, -EIO, "STATUS_CHECKOUT_REQUIRED"},
- {STATUS_BAD_FILE_TYPE, -EIO, "STATUS_BAD_FILE_TYPE"},
- {STATUS_FILE_TOO_LARGE, -EIO, "STATUS_FILE_TOO_LARGE"},
- {STATUS_FORMS_AUTH_REQUIRED, -EIO, "STATUS_FORMS_AUTH_REQUIRED"},
- {STATUS_VIRUS_INFECTED, -EIO, "STATUS_VIRUS_INFECTED"},
- {STATUS_VIRUS_DELETED, -EIO, "STATUS_VIRUS_DELETED"},
- {STATUS_BAD_MCFG_TABLE, -EIO, "STATUS_BAD_MCFG_TABLE"},
- {STATUS_WOW_ASSERTION, -EIO, "STATUS_WOW_ASSERTION"},
- {STATUS_INVALID_SIGNATURE, -EIO, "STATUS_INVALID_SIGNATURE"},
- {STATUS_HMAC_NOT_SUPPORTED, -EIO, "STATUS_HMAC_NOT_SUPPORTED"},
- {STATUS_IPSEC_QUEUE_OVERFLOW, -EIO, "STATUS_IPSEC_QUEUE_OVERFLOW"},
- {STATUS_ND_QUEUE_OVERFLOW, -EIO, "STATUS_ND_QUEUE_OVERFLOW"},
- {STATUS_HOPLIMIT_EXCEEDED, -EIO, "STATUS_HOPLIMIT_EXCEEDED"},
- {STATUS_PROTOCOL_NOT_SUPPORTED, -EOPNOTSUPP,
- "STATUS_PROTOCOL_NOT_SUPPORTED"},
- {STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED, -EIO,
- "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED"},
- {STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR, -EIO,
- "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR"},
- {STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR, -EIO,
- "STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR"},
- {STATUS_XML_PARSE_ERROR, -EIO, "STATUS_XML_PARSE_ERROR"},
- {STATUS_XMLDSIG_ERROR, -EIO, "STATUS_XMLDSIG_ERROR"},
- {STATUS_WRONG_COMPARTMENT, -EIO, "STATUS_WRONG_COMPARTMENT"},
- {STATUS_AUTHIP_FAILURE, -EIO, "STATUS_AUTHIP_FAILURE"},
- {DBG_NO_STATE_CHANGE, -EIO, "DBG_NO_STATE_CHANGE"},
- {DBG_APP_NOT_IDLE, -EIO, "DBG_APP_NOT_IDLE"},
- {RPC_NT_INVALID_STRING_BINDING, -EIO, "RPC_NT_INVALID_STRING_BINDING"},
- {RPC_NT_WRONG_KIND_OF_BINDING, -EIO, "RPC_NT_WRONG_KIND_OF_BINDING"},
- {RPC_NT_INVALID_BINDING, -EIO, "RPC_NT_INVALID_BINDING"},
- {RPC_NT_PROTSEQ_NOT_SUPPORTED, -EOPNOTSUPP,
- "RPC_NT_PROTSEQ_NOT_SUPPORTED"},
- {RPC_NT_INVALID_RPC_PROTSEQ, -EIO, "RPC_NT_INVALID_RPC_PROTSEQ"},
- {RPC_NT_INVALID_STRING_UUID, -EIO, "RPC_NT_INVALID_STRING_UUID"},
- {RPC_NT_INVALID_ENDPOINT_FORMAT, -EIO,
- "RPC_NT_INVALID_ENDPOINT_FORMAT"},
- {RPC_NT_INVALID_NET_ADDR, -EIO, "RPC_NT_INVALID_NET_ADDR"},
- {RPC_NT_NO_ENDPOINT_FOUND, -EIO, "RPC_NT_NO_ENDPOINT_FOUND"},
- {RPC_NT_INVALID_TIMEOUT, -EINVAL, "RPC_NT_INVALID_TIMEOUT"},
- {RPC_NT_OBJECT_NOT_FOUND, -ENOENT, "RPC_NT_OBJECT_NOT_FOUND"},
- {RPC_NT_ALREADY_REGISTERED, -EIO, "RPC_NT_ALREADY_REGISTERED"},
- {RPC_NT_TYPE_ALREADY_REGISTERED, -EIO,
- "RPC_NT_TYPE_ALREADY_REGISTERED"},
- {RPC_NT_ALREADY_LISTENING, -EIO, "RPC_NT_ALREADY_LISTENING"},
- {RPC_NT_NO_PROTSEQS_REGISTERED, -EIO, "RPC_NT_NO_PROTSEQS_REGISTERED"},
- {RPC_NT_NOT_LISTENING, -EIO, "RPC_NT_NOT_LISTENING"},
- {RPC_NT_UNKNOWN_MGR_TYPE, -EIO, "RPC_NT_UNKNOWN_MGR_TYPE"},
- {RPC_NT_UNKNOWN_IF, -EIO, "RPC_NT_UNKNOWN_IF"},
- {RPC_NT_NO_BINDINGS, -EIO, "RPC_NT_NO_BINDINGS"},
- {RPC_NT_NO_PROTSEQS, -EIO, "RPC_NT_NO_PROTSEQS"},
- {RPC_NT_CANT_CREATE_ENDPOINT, -EIO, "RPC_NT_CANT_CREATE_ENDPOINT"},
- {RPC_NT_OUT_OF_RESOURCES, -EIO, "RPC_NT_OUT_OF_RESOURCES"},
- {RPC_NT_SERVER_UNAVAILABLE, -EIO, "RPC_NT_SERVER_UNAVAILABLE"},
- {RPC_NT_SERVER_TOO_BUSY, -EBUSY, "RPC_NT_SERVER_TOO_BUSY"},
- {RPC_NT_INVALID_NETWORK_OPTIONS, -EIO,
- "RPC_NT_INVALID_NETWORK_OPTIONS"},
- {RPC_NT_NO_CALL_ACTIVE, -EIO, "RPC_NT_NO_CALL_ACTIVE"},
- {RPC_NT_CALL_FAILED, -EIO, "RPC_NT_CALL_FAILED"},
- {RPC_NT_CALL_FAILED_DNE, -EIO, "RPC_NT_CALL_FAILED_DNE"},
- {RPC_NT_PROTOCOL_ERROR, -EIO, "RPC_NT_PROTOCOL_ERROR"},
- {RPC_NT_UNSUPPORTED_TRANS_SYN, -EIO, "RPC_NT_UNSUPPORTED_TRANS_SYN"},
- {RPC_NT_UNSUPPORTED_TYPE, -EIO, "RPC_NT_UNSUPPORTED_TYPE"},
- {RPC_NT_INVALID_TAG, -EIO, "RPC_NT_INVALID_TAG"},
- {RPC_NT_INVALID_BOUND, -EIO, "RPC_NT_INVALID_BOUND"},
- {RPC_NT_NO_ENTRY_NAME, -EIO, "RPC_NT_NO_ENTRY_NAME"},
- {RPC_NT_INVALID_NAME_SYNTAX, -EIO, "RPC_NT_INVALID_NAME_SYNTAX"},
- {RPC_NT_UNSUPPORTED_NAME_SYNTAX, -EIO,
- "RPC_NT_UNSUPPORTED_NAME_SYNTAX"},
- {RPC_NT_UUID_NO_ADDRESS, -EIO, "RPC_NT_UUID_NO_ADDRESS"},
- {RPC_NT_DUPLICATE_ENDPOINT, -ENOTUNIQ, "RPC_NT_DUPLICATE_ENDPOINT"},
- {RPC_NT_UNKNOWN_AUTHN_TYPE, -EIO, "RPC_NT_UNKNOWN_AUTHN_TYPE"},
- {RPC_NT_MAX_CALLS_TOO_SMALL, -EIO, "RPC_NT_MAX_CALLS_TOO_SMALL"},
- {RPC_NT_STRING_TOO_LONG, -EIO, "RPC_NT_STRING_TOO_LONG"},
- {RPC_NT_PROTSEQ_NOT_FOUND, -EIO, "RPC_NT_PROTSEQ_NOT_FOUND"},
- {RPC_NT_PROCNUM_OUT_OF_RANGE, -EIO, "RPC_NT_PROCNUM_OUT_OF_RANGE"},
- {RPC_NT_BINDING_HAS_NO_AUTH, -EIO, "RPC_NT_BINDING_HAS_NO_AUTH"},
- {RPC_NT_UNKNOWN_AUTHN_SERVICE, -EIO, "RPC_NT_UNKNOWN_AUTHN_SERVICE"},
- {RPC_NT_UNKNOWN_AUTHN_LEVEL, -EIO, "RPC_NT_UNKNOWN_AUTHN_LEVEL"},
- {RPC_NT_INVALID_AUTH_IDENTITY, -EIO, "RPC_NT_INVALID_AUTH_IDENTITY"},
- {RPC_NT_UNKNOWN_AUTHZ_SERVICE, -EIO, "RPC_NT_UNKNOWN_AUTHZ_SERVICE"},
- {EPT_NT_INVALID_ENTRY, -EIO, "EPT_NT_INVALID_ENTRY"},
- {EPT_NT_CANT_PERFORM_OP, -EIO, "EPT_NT_CANT_PERFORM_OP"},
- {EPT_NT_NOT_REGISTERED, -EIO, "EPT_NT_NOT_REGISTERED"},
- {RPC_NT_NOTHING_TO_EXPORT, -EIO, "RPC_NT_NOTHING_TO_EXPORT"},
- {RPC_NT_INCOMPLETE_NAME, -EIO, "RPC_NT_INCOMPLETE_NAME"},
- {RPC_NT_INVALID_VERS_OPTION, -EIO, "RPC_NT_INVALID_VERS_OPTION"},
- {RPC_NT_NO_MORE_MEMBERS, -EIO, "RPC_NT_NO_MORE_MEMBERS"},
- {RPC_NT_NOT_ALL_OBJS_UNEXPORTED, -EIO,
- "RPC_NT_NOT_ALL_OBJS_UNEXPORTED"},
- {RPC_NT_INTERFACE_NOT_FOUND, -EIO, "RPC_NT_INTERFACE_NOT_FOUND"},
- {RPC_NT_ENTRY_ALREADY_EXISTS, -EIO, "RPC_NT_ENTRY_ALREADY_EXISTS"},
- {RPC_NT_ENTRY_NOT_FOUND, -EIO, "RPC_NT_ENTRY_NOT_FOUND"},
- {RPC_NT_NAME_SERVICE_UNAVAILABLE, -EIO,
- "RPC_NT_NAME_SERVICE_UNAVAILABLE"},
- {RPC_NT_INVALID_NAF_ID, -EIO, "RPC_NT_INVALID_NAF_ID"},
- {RPC_NT_CANNOT_SUPPORT, -EOPNOTSUPP, "RPC_NT_CANNOT_SUPPORT"},
- {RPC_NT_NO_CONTEXT_AVAILABLE, -EIO, "RPC_NT_NO_CONTEXT_AVAILABLE"},
- {RPC_NT_INTERNAL_ERROR, -EIO, "RPC_NT_INTERNAL_ERROR"},
- {RPC_NT_ZERO_DIVIDE, -EIO, "RPC_NT_ZERO_DIVIDE"},
- {RPC_NT_ADDRESS_ERROR, -EIO, "RPC_NT_ADDRESS_ERROR"},
- {RPC_NT_FP_DIV_ZERO, -EIO, "RPC_NT_FP_DIV_ZERO"},
- {RPC_NT_FP_UNDERFLOW, -EIO, "RPC_NT_FP_UNDERFLOW"},
- {RPC_NT_FP_OVERFLOW, -EIO, "RPC_NT_FP_OVERFLOW"},
- {RPC_NT_CALL_IN_PROGRESS, -EIO, "RPC_NT_CALL_IN_PROGRESS"},
- {RPC_NT_NO_MORE_BINDINGS, -EIO, "RPC_NT_NO_MORE_BINDINGS"},
- {RPC_NT_GROUP_MEMBER_NOT_FOUND, -EIO, "RPC_NT_GROUP_MEMBER_NOT_FOUND"},
- {EPT_NT_CANT_CREATE, -EIO, "EPT_NT_CANT_CREATE"},
- {RPC_NT_INVALID_OBJECT, -EIO, "RPC_NT_INVALID_OBJECT"},
- {RPC_NT_NO_INTERFACES, -EIO, "RPC_NT_NO_INTERFACES"},
- {RPC_NT_CALL_CANCELLED, -EIO, "RPC_NT_CALL_CANCELLED"},
- {RPC_NT_BINDING_INCOMPLETE, -EIO, "RPC_NT_BINDING_INCOMPLETE"},
- {RPC_NT_COMM_FAILURE, -EIO, "RPC_NT_COMM_FAILURE"},
- {RPC_NT_UNSUPPORTED_AUTHN_LEVEL, -EIO,
- "RPC_NT_UNSUPPORTED_AUTHN_LEVEL"},
- {RPC_NT_NO_PRINC_NAME, -EIO, "RPC_NT_NO_PRINC_NAME"},
- {RPC_NT_NOT_RPC_ERROR, -EIO, "RPC_NT_NOT_RPC_ERROR"},
- {RPC_NT_SEC_PKG_ERROR, -EIO, "RPC_NT_SEC_PKG_ERROR"},
- {RPC_NT_NOT_CANCELLED, -EIO, "RPC_NT_NOT_CANCELLED"},
- {RPC_NT_INVALID_ASYNC_HANDLE, -EIO, "RPC_NT_INVALID_ASYNC_HANDLE"},
- {RPC_NT_INVALID_ASYNC_CALL, -EIO, "RPC_NT_INVALID_ASYNC_CALL"},
- {RPC_NT_PROXY_ACCESS_DENIED, -EACCES, "RPC_NT_PROXY_ACCESS_DENIED"},
- {RPC_NT_NO_MORE_ENTRIES, -EIO, "RPC_NT_NO_MORE_ENTRIES"},
- {RPC_NT_SS_CHAR_TRANS_OPEN_FAIL, -EIO,
- "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL"},
- {RPC_NT_SS_CHAR_TRANS_SHORT_FILE, -EIO,
- "RPC_NT_SS_CHAR_TRANS_SHORT_FILE"},
- {RPC_NT_SS_IN_NULL_CONTEXT, -EIO, "RPC_NT_SS_IN_NULL_CONTEXT"},
- {RPC_NT_SS_CONTEXT_MISMATCH, -EIO, "RPC_NT_SS_CONTEXT_MISMATCH"},
- {RPC_NT_SS_CONTEXT_DAMAGED, -EIO, "RPC_NT_SS_CONTEXT_DAMAGED"},
- {RPC_NT_SS_HANDLES_MISMATCH, -EIO, "RPC_NT_SS_HANDLES_MISMATCH"},
- {RPC_NT_SS_CANNOT_GET_CALL_HANDLE, -EIO,
- "RPC_NT_SS_CANNOT_GET_CALL_HANDLE"},
- {RPC_NT_NULL_REF_POINTER, -EIO, "RPC_NT_NULL_REF_POINTER"},
- {RPC_NT_ENUM_VALUE_OUT_OF_RANGE, -EIO,
- "RPC_NT_ENUM_VALUE_OUT_OF_RANGE"},
- {RPC_NT_BYTE_COUNT_TOO_SMALL, -EIO, "RPC_NT_BYTE_COUNT_TOO_SMALL"},
- {RPC_NT_BAD_STUB_DATA, -EIO, "RPC_NT_BAD_STUB_DATA"},
- {RPC_NT_INVALID_ES_ACTION, -EIO, "RPC_NT_INVALID_ES_ACTION"},
- {RPC_NT_WRONG_ES_VERSION, -EIO, "RPC_NT_WRONG_ES_VERSION"},
- {RPC_NT_WRONG_STUB_VERSION, -EIO, "RPC_NT_WRONG_STUB_VERSION"},
- {RPC_NT_INVALID_PIPE_OBJECT, -EIO, "RPC_NT_INVALID_PIPE_OBJECT"},
- {RPC_NT_INVALID_PIPE_OPERATION, -EIO, "RPC_NT_INVALID_PIPE_OPERATION"},
- {RPC_NT_WRONG_PIPE_VERSION, -EIO, "RPC_NT_WRONG_PIPE_VERSION"},
- {RPC_NT_PIPE_CLOSED, -EIO, "RPC_NT_PIPE_CLOSED"},
- {RPC_NT_PIPE_DISCIPLINE_ERROR, -EIO, "RPC_NT_PIPE_DISCIPLINE_ERROR"},
- {RPC_NT_PIPE_EMPTY, -EIO, "RPC_NT_PIPE_EMPTY"},
- {STATUS_PNP_BAD_MPS_TABLE, -EIO, "STATUS_PNP_BAD_MPS_TABLE"},
- {STATUS_PNP_TRANSLATION_FAILED, -EIO, "STATUS_PNP_TRANSLATION_FAILED"},
- {STATUS_PNP_IRQ_TRANSLATION_FAILED, -EIO,
- "STATUS_PNP_IRQ_TRANSLATION_FAILED"},
- {STATUS_PNP_INVALID_ID, -EIO, "STATUS_PNP_INVALID_ID"},
- {STATUS_IO_REISSUE_AS_CACHED, -EIO, "STATUS_IO_REISSUE_AS_CACHED"},
- {STATUS_CTX_WINSTATION_NAME_INVALID, -EIO,
- "STATUS_CTX_WINSTATION_NAME_INVALID"},
- {STATUS_CTX_INVALID_PD, -EIO, "STATUS_CTX_INVALID_PD"},
- {STATUS_CTX_PD_NOT_FOUND, -EIO, "STATUS_CTX_PD_NOT_FOUND"},
- {STATUS_CTX_CLOSE_PENDING, -EIO, "STATUS_CTX_CLOSE_PENDING"},
- {STATUS_CTX_NO_OUTBUF, -EIO, "STATUS_CTX_NO_OUTBUF"},
- {STATUS_CTX_MODEM_INF_NOT_FOUND, -EIO,
- "STATUS_CTX_MODEM_INF_NOT_FOUND"},
- {STATUS_CTX_INVALID_MODEMNAME, -EIO, "STATUS_CTX_INVALID_MODEMNAME"},
- {STATUS_CTX_RESPONSE_ERROR, -EIO, "STATUS_CTX_RESPONSE_ERROR"},
- {STATUS_CTX_MODEM_RESPONSE_TIMEOUT, -ETIMEDOUT,
- "STATUS_CTX_MODEM_RESPONSE_TIMEOUT"},
- {STATUS_CTX_MODEM_RESPONSE_NO_CARRIER, -EIO,
- "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER"},
- {STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE, -EIO,
- "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE"},
- {STATUS_CTX_MODEM_RESPONSE_BUSY, -EBUSY,
- "STATUS_CTX_MODEM_RESPONSE_BUSY"},
- {STATUS_CTX_MODEM_RESPONSE_VOICE, -EIO,
- "STATUS_CTX_MODEM_RESPONSE_VOICE"},
- {STATUS_CTX_TD_ERROR, -EIO, "STATUS_CTX_TD_ERROR"},
- {STATUS_CTX_LICENSE_CLIENT_INVALID, -EIO,
- "STATUS_CTX_LICENSE_CLIENT_INVALID"},
- {STATUS_CTX_LICENSE_NOT_AVAILABLE, -EIO,
- "STATUS_CTX_LICENSE_NOT_AVAILABLE"},
- {STATUS_CTX_LICENSE_EXPIRED, -EIO, "STATUS_CTX_LICENSE_EXPIRED"},
- {STATUS_CTX_WINSTATION_NOT_FOUND, -EIO,
- "STATUS_CTX_WINSTATION_NOT_FOUND"},
- {STATUS_CTX_WINSTATION_NAME_COLLISION, -EIO,
- "STATUS_CTX_WINSTATION_NAME_COLLISION"},
- {STATUS_CTX_WINSTATION_BUSY, -EBUSY, "STATUS_CTX_WINSTATION_BUSY"},
- {STATUS_CTX_BAD_VIDEO_MODE, -EIO, "STATUS_CTX_BAD_VIDEO_MODE"},
- {STATUS_CTX_GRAPHICS_INVALID, -EIO, "STATUS_CTX_GRAPHICS_INVALID"},
- {STATUS_CTX_NOT_CONSOLE, -EIO, "STATUS_CTX_NOT_CONSOLE"},
- {STATUS_CTX_CLIENT_QUERY_TIMEOUT, -EIO,
- "STATUS_CTX_CLIENT_QUERY_TIMEOUT"},
- {STATUS_CTX_CONSOLE_DISCONNECT, -EIO, "STATUS_CTX_CONSOLE_DISCONNECT"},
- {STATUS_CTX_CONSOLE_CONNECT, -EIO, "STATUS_CTX_CONSOLE_CONNECT"},
- {STATUS_CTX_SHADOW_DENIED, -EIO, "STATUS_CTX_SHADOW_DENIED"},
- {STATUS_CTX_WINSTATION_ACCESS_DENIED, -EACCES,
- "STATUS_CTX_WINSTATION_ACCESS_DENIED"},
- {STATUS_CTX_INVALID_WD, -EIO, "STATUS_CTX_INVALID_WD"},
- {STATUS_CTX_WD_NOT_FOUND, -EIO, "STATUS_CTX_WD_NOT_FOUND"},
- {STATUS_CTX_SHADOW_INVALID, -EIO, "STATUS_CTX_SHADOW_INVALID"},
- {STATUS_CTX_SHADOW_DISABLED, -EIO, "STATUS_CTX_SHADOW_DISABLED"},
- {STATUS_RDP_PROTOCOL_ERROR, -EIO, "STATUS_RDP_PROTOCOL_ERROR"},
- {STATUS_CTX_CLIENT_LICENSE_NOT_SET, -EIO,
- "STATUS_CTX_CLIENT_LICENSE_NOT_SET"},
- {STATUS_CTX_CLIENT_LICENSE_IN_USE, -EIO,
- "STATUS_CTX_CLIENT_LICENSE_IN_USE"},
- {STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE, -EIO,
- "STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE"},
- {STATUS_CTX_SHADOW_NOT_RUNNING, -EIO, "STATUS_CTX_SHADOW_NOT_RUNNING"},
- {STATUS_CTX_LOGON_DISABLED, -EIO, "STATUS_CTX_LOGON_DISABLED"},
- {STATUS_CTX_SECURITY_LAYER_ERROR, -EIO,
- "STATUS_CTX_SECURITY_LAYER_ERROR"},
- {STATUS_TS_INCOMPATIBLE_SESSIONS, -EIO,
- "STATUS_TS_INCOMPATIBLE_SESSIONS"},
- {STATUS_MUI_FILE_NOT_FOUND, -EIO, "STATUS_MUI_FILE_NOT_FOUND"},
- {STATUS_MUI_INVALID_FILE, -EIO, "STATUS_MUI_INVALID_FILE"},
- {STATUS_MUI_INVALID_RC_CONFIG, -EIO, "STATUS_MUI_INVALID_RC_CONFIG"},
- {STATUS_MUI_INVALID_LOCALE_NAME, -EIO,
- "STATUS_MUI_INVALID_LOCALE_NAME"},
- {STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME, -EIO,
- "STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME"},
- {STATUS_MUI_FILE_NOT_LOADED, -EIO, "STATUS_MUI_FILE_NOT_LOADED"},
- {STATUS_RESOURCE_ENUM_USER_STOP, -EIO,
- "STATUS_RESOURCE_ENUM_USER_STOP"},
- {STATUS_CLUSTER_INVALID_NODE, -EIO, "STATUS_CLUSTER_INVALID_NODE"},
- {STATUS_CLUSTER_NODE_EXISTS, -EIO, "STATUS_CLUSTER_NODE_EXISTS"},
- {STATUS_CLUSTER_JOIN_IN_PROGRESS, -EIO,
- "STATUS_CLUSTER_JOIN_IN_PROGRESS"},
- {STATUS_CLUSTER_NODE_NOT_FOUND, -EIO, "STATUS_CLUSTER_NODE_NOT_FOUND"},
- {STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND, -EIO,
- "STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND"},
- {STATUS_CLUSTER_NETWORK_EXISTS, -EIO, "STATUS_CLUSTER_NETWORK_EXISTS"},
- {STATUS_CLUSTER_NETWORK_NOT_FOUND, -EIO,
- "STATUS_CLUSTER_NETWORK_NOT_FOUND"},
- {STATUS_CLUSTER_NETINTERFACE_EXISTS, -EIO,
- "STATUS_CLUSTER_NETINTERFACE_EXISTS"},
- {STATUS_CLUSTER_NETINTERFACE_NOT_FOUND, -EIO,
- "STATUS_CLUSTER_NETINTERFACE_NOT_FOUND"},
- {STATUS_CLUSTER_INVALID_REQUEST, -EIO,
- "STATUS_CLUSTER_INVALID_REQUEST"},
- {STATUS_CLUSTER_INVALID_NETWORK_PROVIDER, -EIO,
- "STATUS_CLUSTER_INVALID_NETWORK_PROVIDER"},
- {STATUS_CLUSTER_NODE_DOWN, -EIO, "STATUS_CLUSTER_NODE_DOWN"},
- {STATUS_CLUSTER_NODE_UNREACHABLE, -EIO,
- "STATUS_CLUSTER_NODE_UNREACHABLE"},
- {STATUS_CLUSTER_NODE_NOT_MEMBER, -EIO,
- "STATUS_CLUSTER_NODE_NOT_MEMBER"},
- {STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS, -EIO,
- "STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS"},
- {STATUS_CLUSTER_INVALID_NETWORK, -EIO,
- "STATUS_CLUSTER_INVALID_NETWORK"},
- {STATUS_CLUSTER_NO_NET_ADAPTERS, -EIO,
- "STATUS_CLUSTER_NO_NET_ADAPTERS"},
- {STATUS_CLUSTER_NODE_UP, -EIO, "STATUS_CLUSTER_NODE_UP"},
- {STATUS_CLUSTER_NODE_PAUSED, -EIO, "STATUS_CLUSTER_NODE_PAUSED"},
- {STATUS_CLUSTER_NODE_NOT_PAUSED, -EIO,
- "STATUS_CLUSTER_NODE_NOT_PAUSED"},
- {STATUS_CLUSTER_NO_SECURITY_CONTEXT, -EIO,
- "STATUS_CLUSTER_NO_SECURITY_CONTEXT"},
- {STATUS_CLUSTER_NETWORK_NOT_INTERNAL, -EIO,
- "STATUS_CLUSTER_NETWORK_NOT_INTERNAL"},
- {STATUS_CLUSTER_POISONED, -EIO, "STATUS_CLUSTER_POISONED"},
- {STATUS_ACPI_INVALID_OPCODE, -EIO, "STATUS_ACPI_INVALID_OPCODE"},
- {STATUS_ACPI_STACK_OVERFLOW, -EIO, "STATUS_ACPI_STACK_OVERFLOW"},
- {STATUS_ACPI_ASSERT_FAILED, -EIO, "STATUS_ACPI_ASSERT_FAILED"},
- {STATUS_ACPI_INVALID_INDEX, -EIO, "STATUS_ACPI_INVALID_INDEX"},
- {STATUS_ACPI_INVALID_ARGUMENT, -EIO, "STATUS_ACPI_INVALID_ARGUMENT"},
- {STATUS_ACPI_FATAL, -EIO, "STATUS_ACPI_FATAL"},
- {STATUS_ACPI_INVALID_SUPERNAME, -EIO, "STATUS_ACPI_INVALID_SUPERNAME"},
- {STATUS_ACPI_INVALID_ARGTYPE, -EIO, "STATUS_ACPI_INVALID_ARGTYPE"},
- {STATUS_ACPI_INVALID_OBJTYPE, -EIO, "STATUS_ACPI_INVALID_OBJTYPE"},
- {STATUS_ACPI_INVALID_TARGETTYPE, -EIO,
- "STATUS_ACPI_INVALID_TARGETTYPE"},
- {STATUS_ACPI_INCORRECT_ARGUMENT_COUNT, -EIO,
- "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT"},
- {STATUS_ACPI_ADDRESS_NOT_MAPPED, -EIO,
- "STATUS_ACPI_ADDRESS_NOT_MAPPED"},
- {STATUS_ACPI_INVALID_EVENTTYPE, -EIO, "STATUS_ACPI_INVALID_EVENTTYPE"},
- {STATUS_ACPI_HANDLER_COLLISION, -EIO, "STATUS_ACPI_HANDLER_COLLISION"},
- {STATUS_ACPI_INVALID_DATA, -EIO, "STATUS_ACPI_INVALID_DATA"},
- {STATUS_ACPI_INVALID_REGION, -EIO, "STATUS_ACPI_INVALID_REGION"},
- {STATUS_ACPI_INVALID_ACCESS_SIZE, -EIO,
- "STATUS_ACPI_INVALID_ACCESS_SIZE"},
- {STATUS_ACPI_ACQUIRE_GLOBAL_LOCK, -EIO,
- "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK"},
- {STATUS_ACPI_ALREADY_INITIALIZED, -EIO,
- "STATUS_ACPI_ALREADY_INITIALIZED"},
- {STATUS_ACPI_NOT_INITIALIZED, -EIO, "STATUS_ACPI_NOT_INITIALIZED"},
- {STATUS_ACPI_INVALID_MUTEX_LEVEL, -EIO,
- "STATUS_ACPI_INVALID_MUTEX_LEVEL"},
- {STATUS_ACPI_MUTEX_NOT_OWNED, -EIO, "STATUS_ACPI_MUTEX_NOT_OWNED"},
- {STATUS_ACPI_MUTEX_NOT_OWNER, -EIO, "STATUS_ACPI_MUTEX_NOT_OWNER"},
- {STATUS_ACPI_RS_ACCESS, -EIO, "STATUS_ACPI_RS_ACCESS"},
- {STATUS_ACPI_INVALID_TABLE, -EIO, "STATUS_ACPI_INVALID_TABLE"},
- {STATUS_ACPI_REG_HANDLER_FAILED, -EIO,
- "STATUS_ACPI_REG_HANDLER_FAILED"},
- {STATUS_ACPI_POWER_REQUEST_FAILED, -EIO,
- "STATUS_ACPI_POWER_REQUEST_FAILED"},
- {STATUS_SXS_SECTION_NOT_FOUND, -EIO, "STATUS_SXS_SECTION_NOT_FOUND"},
- {STATUS_SXS_CANT_GEN_ACTCTX, -EIO, "STATUS_SXS_CANT_GEN_ACTCTX"},
- {STATUS_SXS_INVALID_ACTCTXDATA_FORMAT, -EIO,
- "STATUS_SXS_INVALID_ACTCTXDATA_FORMAT"},
- {STATUS_SXS_ASSEMBLY_NOT_FOUND, -EIO, "STATUS_SXS_ASSEMBLY_NOT_FOUND"},
- {STATUS_SXS_MANIFEST_FORMAT_ERROR, -EIO,
- "STATUS_SXS_MANIFEST_FORMAT_ERROR"},
- {STATUS_SXS_MANIFEST_PARSE_ERROR, -EIO,
- "STATUS_SXS_MANIFEST_PARSE_ERROR"},
- {STATUS_SXS_ACTIVATION_CONTEXT_DISABLED, -EIO,
- "STATUS_SXS_ACTIVATION_CONTEXT_DISABLED"},
- {STATUS_SXS_KEY_NOT_FOUND, -EIO, "STATUS_SXS_KEY_NOT_FOUND"},
- {STATUS_SXS_VERSION_CONFLICT, -EIO, "STATUS_SXS_VERSION_CONFLICT"},
- {STATUS_SXS_WRONG_SECTION_TYPE, -EIO, "STATUS_SXS_WRONG_SECTION_TYPE"},
- {STATUS_SXS_THREAD_QUERIES_DISABLED, -EIO,
- "STATUS_SXS_THREAD_QUERIES_DISABLED"},
- {STATUS_SXS_ASSEMBLY_MISSING, -EIO, "STATUS_SXS_ASSEMBLY_MISSING"},
- {STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET, -EIO,
- "STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET"},
- {STATUS_SXS_EARLY_DEACTIVATION, -EIO, "STATUS_SXS_EARLY_DEACTIVATION"},
- {STATUS_SXS_INVALID_DEACTIVATION, -EIO,
- "STATUS_SXS_INVALID_DEACTIVATION"},
- {STATUS_SXS_MULTIPLE_DEACTIVATION, -EIO,
- "STATUS_SXS_MULTIPLE_DEACTIVATION"},
- {STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY, -EIO,
- "STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY"},
- {STATUS_SXS_PROCESS_TERMINATION_REQUESTED, -EIO,
- "STATUS_SXS_PROCESS_TERMINATION_REQUESTED"},
- {STATUS_SXS_CORRUPT_ACTIVATION_STACK, -EIO,
- "STATUS_SXS_CORRUPT_ACTIVATION_STACK"},
- {STATUS_SXS_CORRUPTION, -EIO, "STATUS_SXS_CORRUPTION"},
- {STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE, -EIO,
- "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE"},
- {STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME, -EIO,
- "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME"},
- {STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE, -EIO,
- "STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE"},
- {STATUS_SXS_IDENTITY_PARSE_ERROR, -EIO,
- "STATUS_SXS_IDENTITY_PARSE_ERROR"},
- {STATUS_SXS_COMPONENT_STORE_CORRUPT, -EIO,
- "STATUS_SXS_COMPONENT_STORE_CORRUPT"},
- {STATUS_SXS_FILE_HASH_MISMATCH, -EIO, "STATUS_SXS_FILE_HASH_MISMATCH"},
- {STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT, -EIO,
- "STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT"},
- {STATUS_SXS_IDENTITIES_DIFFERENT, -EIO,
- "STATUS_SXS_IDENTITIES_DIFFERENT"},
- {STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT, -EIO,
- "STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT"},
- {STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY, -EIO,
- "STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY"},
- {STATUS_ADVANCED_INSTALLER_FAILED, -EIO,
- "STATUS_ADVANCED_INSTALLER_FAILED"},
- {STATUS_XML_ENCODING_MISMATCH, -EIO, "STATUS_XML_ENCODING_MISMATCH"},
- {STATUS_SXS_MANIFEST_TOO_BIG, -EIO, "STATUS_SXS_MANIFEST_TOO_BIG"},
- {STATUS_SXS_SETTING_NOT_REGISTERED, -EIO,
- "STATUS_SXS_SETTING_NOT_REGISTERED"},
- {STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE, -EIO,
- "STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE"},
- {STATUS_SMI_PRIMITIVE_INSTALLER_FAILED, -EIO,
- "STATUS_SMI_PRIMITIVE_INSTALLER_FAILED"},
- {STATUS_GENERIC_COMMAND_FAILED, -EIO, "STATUS_GENERIC_COMMAND_FAILED"},
- {STATUS_SXS_FILE_HASH_MISSING, -EIO, "STATUS_SXS_FILE_HASH_MISSING"},
- {STATUS_TRANSACTIONAL_CONFLICT, -EIO, "STATUS_TRANSACTIONAL_CONFLICT"},
- {STATUS_INVALID_TRANSACTION, -EIO, "STATUS_INVALID_TRANSACTION"},
- {STATUS_TRANSACTION_NOT_ACTIVE, -EIO, "STATUS_TRANSACTION_NOT_ACTIVE"},
- {STATUS_TM_INITIALIZATION_FAILED, -EIO,
- "STATUS_TM_INITIALIZATION_FAILED"},
- {STATUS_RM_NOT_ACTIVE, -EIO, "STATUS_RM_NOT_ACTIVE"},
- {STATUS_RM_METADATA_CORRUPT, -EIO, "STATUS_RM_METADATA_CORRUPT"},
- {STATUS_TRANSACTION_NOT_JOINED, -EIO, "STATUS_TRANSACTION_NOT_JOINED"},
- {STATUS_DIRECTORY_NOT_RM, -EIO, "STATUS_DIRECTORY_NOT_RM"},
- {STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE, -EIO,
- "STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE"},
- {STATUS_LOG_RESIZE_INVALID_SIZE, -EIO,
- "STATUS_LOG_RESIZE_INVALID_SIZE"},
- {STATUS_REMOTE_FILE_VERSION_MISMATCH, -EIO,
- "STATUS_REMOTE_FILE_VERSION_MISMATCH"},
- {STATUS_CRM_PROTOCOL_ALREADY_EXISTS, -EIO,
- "STATUS_CRM_PROTOCOL_ALREADY_EXISTS"},
- {STATUS_TRANSACTION_PROPAGATION_FAILED, -EIO,
- "STATUS_TRANSACTION_PROPAGATION_FAILED"},
- {STATUS_CRM_PROTOCOL_NOT_FOUND, -EIO, "STATUS_CRM_PROTOCOL_NOT_FOUND"},
- {STATUS_TRANSACTION_SUPERIOR_EXISTS, -EIO,
- "STATUS_TRANSACTION_SUPERIOR_EXISTS"},
- {STATUS_TRANSACTION_REQUEST_NOT_VALID, -EIO,
- "STATUS_TRANSACTION_REQUEST_NOT_VALID"},
- {STATUS_TRANSACTION_NOT_REQUESTED, -EIO,
- "STATUS_TRANSACTION_NOT_REQUESTED"},
- {STATUS_TRANSACTION_ALREADY_ABORTED, -EIO,
- "STATUS_TRANSACTION_ALREADY_ABORTED"},
- {STATUS_TRANSACTION_ALREADY_COMMITTED, -EIO,
- "STATUS_TRANSACTION_ALREADY_COMMITTED"},
- {STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER, -EIO,
- "STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER"},
- {STATUS_CURRENT_TRANSACTION_NOT_VALID, -EIO,
- "STATUS_CURRENT_TRANSACTION_NOT_VALID"},
- {STATUS_LOG_GROWTH_FAILED, -EIO, "STATUS_LOG_GROWTH_FAILED"},
- {STATUS_OBJECT_NO_LONGER_EXISTS, -EIO,
- "STATUS_OBJECT_NO_LONGER_EXISTS"},
- {STATUS_STREAM_MINIVERSION_NOT_FOUND, -EIO,
- "STATUS_STREAM_MINIVERSION_NOT_FOUND"},
- {STATUS_STREAM_MINIVERSION_NOT_VALID, -EIO,
- "STATUS_STREAM_MINIVERSION_NOT_VALID"},
- {STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION, -EIO,
- "STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION"},
- {STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT, -EIO,
- "STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT"},
- {STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS, -EIO,
- "STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS"},
- {STATUS_HANDLE_NO_LONGER_VALID, -EIO, "STATUS_HANDLE_NO_LONGER_VALID"},
- {STATUS_LOG_CORRUPTION_DETECTED, -EIO,
- "STATUS_LOG_CORRUPTION_DETECTED"},
- {STATUS_RM_DISCONNECTED, -EIO, "STATUS_RM_DISCONNECTED"},
- {STATUS_ENLISTMENT_NOT_SUPERIOR, -EIO,
- "STATUS_ENLISTMENT_NOT_SUPERIOR"},
- {STATUS_FILE_IDENTITY_NOT_PERSISTENT, -EIO,
- "STATUS_FILE_IDENTITY_NOT_PERSISTENT"},
- {STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY, -EIO,
- "STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY"},
- {STATUS_CANT_CROSS_RM_BOUNDARY, -EIO, "STATUS_CANT_CROSS_RM_BOUNDARY"},
- {STATUS_TXF_DIR_NOT_EMPTY, -EIO, "STATUS_TXF_DIR_NOT_EMPTY"},
- {STATUS_INDOUBT_TRANSACTIONS_EXIST, -EIO,
- "STATUS_INDOUBT_TRANSACTIONS_EXIST"},
- {STATUS_TM_VOLATILE, -EIO, "STATUS_TM_VOLATILE"},
- {STATUS_ROLLBACK_TIMER_EXPIRED, -EIO, "STATUS_ROLLBACK_TIMER_EXPIRED"},
- {STATUS_TXF_ATTRIBUTE_CORRUPT, -EIO, "STATUS_TXF_ATTRIBUTE_CORRUPT"},
- {STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION, -EIO,
- "STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION"},
- {STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED, -EIO,
- "STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED"},
- {STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE, -EIO,
- "STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE"},
- {STATUS_TRANSACTION_REQUIRED_PROMOTION, -EIO,
- "STATUS_TRANSACTION_REQUIRED_PROMOTION"},
- {STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION, -EIO,
- "STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION"},
- {STATUS_TRANSACTIONS_NOT_FROZEN, -EIO,
- "STATUS_TRANSACTIONS_NOT_FROZEN"},
- {STATUS_TRANSACTION_FREEZE_IN_PROGRESS, -EIO,
- "STATUS_TRANSACTION_FREEZE_IN_PROGRESS"},
- {STATUS_NOT_SNAPSHOT_VOLUME, -EIO, "STATUS_NOT_SNAPSHOT_VOLUME"},
- {STATUS_NO_SAVEPOINT_WITH_OPEN_FILES, -EIO,
- "STATUS_NO_SAVEPOINT_WITH_OPEN_FILES"},
- {STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION, -EIO,
- "STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION"},
- {STATUS_TM_IDENTITY_MISMATCH, -EIO, "STATUS_TM_IDENTITY_MISMATCH"},
- {STATUS_FLOATED_SECTION, -EIO, "STATUS_FLOATED_SECTION"},
- {STATUS_CANNOT_ACCEPT_TRANSACTED_WORK, -EIO,
- "STATUS_CANNOT_ACCEPT_TRANSACTED_WORK"},
- {STATUS_CANNOT_ABORT_TRANSACTIONS, -EIO,
- "STATUS_CANNOT_ABORT_TRANSACTIONS"},
- {STATUS_TRANSACTION_NOT_FOUND, -EIO, "STATUS_TRANSACTION_NOT_FOUND"},
- {STATUS_RESOURCEMANAGER_NOT_FOUND, -EIO,
- "STATUS_RESOURCEMANAGER_NOT_FOUND"},
- {STATUS_ENLISTMENT_NOT_FOUND, -EIO, "STATUS_ENLISTMENT_NOT_FOUND"},
- {STATUS_TRANSACTIONMANAGER_NOT_FOUND, -EIO,
- "STATUS_TRANSACTIONMANAGER_NOT_FOUND"},
- {STATUS_TRANSACTIONMANAGER_NOT_ONLINE, -EIO,
- "STATUS_TRANSACTIONMANAGER_NOT_ONLINE"},
- {STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION, -EIO,
- "STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION"},
- {STATUS_TRANSACTION_NOT_ROOT, -EIO, "STATUS_TRANSACTION_NOT_ROOT"},
- {STATUS_TRANSACTION_OBJECT_EXPIRED, -EIO,
- "STATUS_TRANSACTION_OBJECT_EXPIRED"},
- {STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION, -EIO,
- "STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION"},
- {STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED, -EIO,
- "STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED"},
- {STATUS_TRANSACTION_RECORD_TOO_LONG, -EIO,
- "STATUS_TRANSACTION_RECORD_TOO_LONG"},
- {STATUS_NO_LINK_TRACKING_IN_TRANSACTION, -EIO,
- "STATUS_NO_LINK_TRACKING_IN_TRANSACTION"},
- {STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION, -EOPNOTSUPP,
- "STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION"},
- {STATUS_TRANSACTION_INTEGRITY_VIOLATED, -EIO,
- "STATUS_TRANSACTION_INTEGRITY_VIOLATED"},
- {STATUS_LOG_SECTOR_INVALID, -EIO, "STATUS_LOG_SECTOR_INVALID"},
- {STATUS_LOG_SECTOR_PARITY_INVALID, -EIO,
- "STATUS_LOG_SECTOR_PARITY_INVALID"},
- {STATUS_LOG_SECTOR_REMAPPED, -EIO, "STATUS_LOG_SECTOR_REMAPPED"},
- {STATUS_LOG_BLOCK_INCOMPLETE, -EIO, "STATUS_LOG_BLOCK_INCOMPLETE"},
- {STATUS_LOG_INVALID_RANGE, -EIO, "STATUS_LOG_INVALID_RANGE"},
- {STATUS_LOG_BLOCKS_EXHAUSTED, -EIO, "STATUS_LOG_BLOCKS_EXHAUSTED"},
- {STATUS_LOG_READ_CONTEXT_INVALID, -EIO,
- "STATUS_LOG_READ_CONTEXT_INVALID"},
- {STATUS_LOG_RESTART_INVALID, -EIO, "STATUS_LOG_RESTART_INVALID"},
- {STATUS_LOG_BLOCK_VERSION, -EIO, "STATUS_LOG_BLOCK_VERSION"},
- {STATUS_LOG_BLOCK_INVALID, -EIO, "STATUS_LOG_BLOCK_INVALID"},
- {STATUS_LOG_READ_MODE_INVALID, -EIO, "STATUS_LOG_READ_MODE_INVALID"},
- {STATUS_LOG_METADATA_CORRUPT, -EIO, "STATUS_LOG_METADATA_CORRUPT"},
- {STATUS_LOG_METADATA_INVALID, -EIO, "STATUS_LOG_METADATA_INVALID"},
- {STATUS_LOG_METADATA_INCONSISTENT, -EIO,
- "STATUS_LOG_METADATA_INCONSISTENT"},
- {STATUS_LOG_RESERVATION_INVALID, -EIO,
- "STATUS_LOG_RESERVATION_INVALID"},
- {STATUS_LOG_CANT_DELETE, -EIO, "STATUS_LOG_CANT_DELETE"},
- {STATUS_LOG_CONTAINER_LIMIT_EXCEEDED, -EIO,
- "STATUS_LOG_CONTAINER_LIMIT_EXCEEDED"},
- {STATUS_LOG_START_OF_LOG, -EIO, "STATUS_LOG_START_OF_LOG"},
- {STATUS_LOG_POLICY_ALREADY_INSTALLED, -EIO,
- "STATUS_LOG_POLICY_ALREADY_INSTALLED"},
- {STATUS_LOG_POLICY_NOT_INSTALLED, -EIO,
- "STATUS_LOG_POLICY_NOT_INSTALLED"},
- {STATUS_LOG_POLICY_INVALID, -EIO, "STATUS_LOG_POLICY_INVALID"},
- {STATUS_LOG_POLICY_CONFLICT, -EIO, "STATUS_LOG_POLICY_CONFLICT"},
- {STATUS_LOG_PINNED_ARCHIVE_TAIL, -EIO,
- "STATUS_LOG_PINNED_ARCHIVE_TAIL"},
- {STATUS_LOG_RECORD_NONEXISTENT, -EIO, "STATUS_LOG_RECORD_NONEXISTENT"},
- {STATUS_LOG_RECORDS_RESERVED_INVALID, -EIO,
- "STATUS_LOG_RECORDS_RESERVED_INVALID"},
- {STATUS_LOG_SPACE_RESERVED_INVALID, -EIO,
- "STATUS_LOG_SPACE_RESERVED_INVALID"},
- {STATUS_LOG_TAIL_INVALID, -EIO, "STATUS_LOG_TAIL_INVALID"},
- {STATUS_LOG_FULL, -EIO, "STATUS_LOG_FULL"},
- {STATUS_LOG_MULTIPLEXED, -EIO, "STATUS_LOG_MULTIPLEXED"},
- {STATUS_LOG_DEDICATED, -EIO, "STATUS_LOG_DEDICATED"},
- {STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS, -EIO,
- "STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS"},
- {STATUS_LOG_ARCHIVE_IN_PROGRESS, -EIO,
- "STATUS_LOG_ARCHIVE_IN_PROGRESS"},
- {STATUS_LOG_EPHEMERAL, -EIO, "STATUS_LOG_EPHEMERAL"},
- {STATUS_LOG_NOT_ENOUGH_CONTAINERS, -EIO,
- "STATUS_LOG_NOT_ENOUGH_CONTAINERS"},
- {STATUS_LOG_CLIENT_ALREADY_REGISTERED, -EIO,
- "STATUS_LOG_CLIENT_ALREADY_REGISTERED"},
- {STATUS_LOG_CLIENT_NOT_REGISTERED, -EIO,
- "STATUS_LOG_CLIENT_NOT_REGISTERED"},
- {STATUS_LOG_FULL_HANDLER_IN_PROGRESS, -EIO,
- "STATUS_LOG_FULL_HANDLER_IN_PROGRESS"},
- {STATUS_LOG_CONTAINER_READ_FAILED, -EIO,
- "STATUS_LOG_CONTAINER_READ_FAILED"},
- {STATUS_LOG_CONTAINER_WRITE_FAILED, -EIO,
- "STATUS_LOG_CONTAINER_WRITE_FAILED"},
- {STATUS_LOG_CONTAINER_OPEN_FAILED, -EIO,
- "STATUS_LOG_CONTAINER_OPEN_FAILED"},
- {STATUS_LOG_CONTAINER_STATE_INVALID, -EIO,
- "STATUS_LOG_CONTAINER_STATE_INVALID"},
- {STATUS_LOG_STATE_INVALID, -EIO, "STATUS_LOG_STATE_INVALID"},
- {STATUS_LOG_PINNED, -EIO, "STATUS_LOG_PINNED"},
- {STATUS_LOG_METADATA_FLUSH_FAILED, -EIO,
- "STATUS_LOG_METADATA_FLUSH_FAILED"},
- {STATUS_LOG_INCONSISTENT_SECURITY, -EIO,
- "STATUS_LOG_INCONSISTENT_SECURITY"},
- {STATUS_LOG_APPENDED_FLUSH_FAILED, -EIO,
- "STATUS_LOG_APPENDED_FLUSH_FAILED"},
- {STATUS_LOG_PINNED_RESERVATION, -EIO, "STATUS_LOG_PINNED_RESERVATION"},
- {STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD, -EIO,
- "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD"},
- {STATUS_FLT_NO_HANDLER_DEFINED, -EIO, "STATUS_FLT_NO_HANDLER_DEFINED"},
- {STATUS_FLT_CONTEXT_ALREADY_DEFINED, -EIO,
- "STATUS_FLT_CONTEXT_ALREADY_DEFINED"},
- {STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST, -EIO,
- "STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST"},
- {STATUS_FLT_DISALLOW_FAST_IO, -EIO, "STATUS_FLT_DISALLOW_FAST_IO"},
- {STATUS_FLT_INVALID_NAME_REQUEST, -EIO,
- "STATUS_FLT_INVALID_NAME_REQUEST"},
- {STATUS_FLT_NOT_SAFE_TO_POST_OPERATION, -EIO,
- "STATUS_FLT_NOT_SAFE_TO_POST_OPERATION"},
- {STATUS_FLT_NOT_INITIALIZED, -EIO, "STATUS_FLT_NOT_INITIALIZED"},
- {STATUS_FLT_FILTER_NOT_READY, -EIO, "STATUS_FLT_FILTER_NOT_READY"},
- {STATUS_FLT_POST_OPERATION_CLEANUP, -EIO,
- "STATUS_FLT_POST_OPERATION_CLEANUP"},
- {STATUS_FLT_INTERNAL_ERROR, -EIO, "STATUS_FLT_INTERNAL_ERROR"},
- {STATUS_FLT_DELETING_OBJECT, -EIO, "STATUS_FLT_DELETING_OBJECT"},
- {STATUS_FLT_MUST_BE_NONPAGED_POOL, -EIO,
- "STATUS_FLT_MUST_BE_NONPAGED_POOL"},
- {STATUS_FLT_DUPLICATE_ENTRY, -EIO, "STATUS_FLT_DUPLICATE_ENTRY"},
- {STATUS_FLT_CBDQ_DISABLED, -EIO, "STATUS_FLT_CBDQ_DISABLED"},
- {STATUS_FLT_DO_NOT_ATTACH, -EIO, "STATUS_FLT_DO_NOT_ATTACH"},
- {STATUS_FLT_DO_NOT_DETACH, -EIO, "STATUS_FLT_DO_NOT_DETACH"},
- {STATUS_FLT_INSTANCE_ALTITUDE_COLLISION, -EIO,
- "STATUS_FLT_INSTANCE_ALTITUDE_COLLISION"},
- {STATUS_FLT_INSTANCE_NAME_COLLISION, -EIO,
- "STATUS_FLT_INSTANCE_NAME_COLLISION"},
- {STATUS_FLT_FILTER_NOT_FOUND, -EIO, "STATUS_FLT_FILTER_NOT_FOUND"},
- {STATUS_FLT_VOLUME_NOT_FOUND, -EIO, "STATUS_FLT_VOLUME_NOT_FOUND"},
- {STATUS_FLT_INSTANCE_NOT_FOUND, -EIO, "STATUS_FLT_INSTANCE_NOT_FOUND"},
- {STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND, -EIO,
- "STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND"},
- {STATUS_FLT_INVALID_CONTEXT_REGISTRATION, -EIO,
- "STATUS_FLT_INVALID_CONTEXT_REGISTRATION"},
- {STATUS_FLT_NAME_CACHE_MISS, -EIO, "STATUS_FLT_NAME_CACHE_MISS"},
- {STATUS_FLT_NO_DEVICE_OBJECT, -EIO, "STATUS_FLT_NO_DEVICE_OBJECT"},
- {STATUS_FLT_VOLUME_ALREADY_MOUNTED, -EIO,
- "STATUS_FLT_VOLUME_ALREADY_MOUNTED"},
- {STATUS_FLT_ALREADY_ENLISTED, -EIO, "STATUS_FLT_ALREADY_ENLISTED"},
- {STATUS_FLT_CONTEXT_ALREADY_LINKED, -EIO,
- "STATUS_FLT_CONTEXT_ALREADY_LINKED"},
- {STATUS_FLT_NO_WAITER_FOR_REPLY, -EIO,
- "STATUS_FLT_NO_WAITER_FOR_REPLY"},
- {STATUS_MONITOR_NO_DESCRIPTOR, -EIO, "STATUS_MONITOR_NO_DESCRIPTOR"},
- {STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT, -EIO,
- "STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT"},
- {STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM, -EIO,
- "STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM"},
- {STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK, -EIO,
- "STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK"},
- {STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED, -EIO,
- "STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED"},
- {STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK, -EIO,
- "STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK"},
- {STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK, -EIO,
- "STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK"},
- {STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA, -EIO,
- "STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA"},
- {STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK, -EIO,
- "STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK"},
- {STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER, -EIO,
- "STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER"},
- {STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER, -EIO,
- "STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER"},
- {STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER, -EIO,
- "STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER"},
- {STATUS_GRAPHICS_ADAPTER_WAS_RESET, -EIO,
- "STATUS_GRAPHICS_ADAPTER_WAS_RESET"},
- {STATUS_GRAPHICS_INVALID_DRIVER_MODEL, -EIO,
- "STATUS_GRAPHICS_INVALID_DRIVER_MODEL"},
- {STATUS_GRAPHICS_PRESENT_MODE_CHANGED, -EIO,
- "STATUS_GRAPHICS_PRESENT_MODE_CHANGED"},
- {STATUS_GRAPHICS_PRESENT_OCCLUDED, -EIO,
- "STATUS_GRAPHICS_PRESENT_OCCLUDED"},
- {STATUS_GRAPHICS_PRESENT_DENIED, -EIO,
- "STATUS_GRAPHICS_PRESENT_DENIED"},
- {STATUS_GRAPHICS_CANNOTCOLORCONVERT, -EIO,
- "STATUS_GRAPHICS_CANNOTCOLORCONVERT"},
- {STATUS_GRAPHICS_NO_VIDEO_MEMORY, -EIO,
- "STATUS_GRAPHICS_NO_VIDEO_MEMORY"},
- {STATUS_GRAPHICS_CANT_LOCK_MEMORY, -EIO,
- "STATUS_GRAPHICS_CANT_LOCK_MEMORY"},
- {STATUS_GRAPHICS_ALLOCATION_BUSY, -EBUSY,
- "STATUS_GRAPHICS_ALLOCATION_BUSY"},
- {STATUS_GRAPHICS_TOO_MANY_REFERENCES, -EIO,
- "STATUS_GRAPHICS_TOO_MANY_REFERENCES"},
- {STATUS_GRAPHICS_TRY_AGAIN_LATER, -EIO,
- "STATUS_GRAPHICS_TRY_AGAIN_LATER"},
- {STATUS_GRAPHICS_TRY_AGAIN_NOW, -EIO, "STATUS_GRAPHICS_TRY_AGAIN_NOW"},
- {STATUS_GRAPHICS_ALLOCATION_INVALID, -EIO,
- "STATUS_GRAPHICS_ALLOCATION_INVALID"},
- {STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE, -EIO,
- "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE"},
- {STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED, -EIO,
- "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED"},
- {STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION, -EIO,
- "STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION"},
- {STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE, -EIO,
- "STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE"},
- {STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION, -EIO,
- "STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION"},
- {STATUS_GRAPHICS_ALLOCATION_CLOSED, -EIO,
- "STATUS_GRAPHICS_ALLOCATION_CLOSED"},
- {STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE, -EIO,
- "STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE"},
- {STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE, -EIO,
- "STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE"},
- {STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE, -EIO,
- "STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE"},
- {STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST, -EIO,
- "STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST"},
- {STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE, -EIO,
- "STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE"},
- {STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY"},
- {STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_INVALID_VIDPN, -EIO, "STATUS_GRAPHICS_INVALID_VIDPN"},
- {STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE"},
- {STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET"},
- {STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET"},
- {STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET"},
- {STATUS_GRAPHICS_INVALID_FREQUENCY, -EIO,
- "STATUS_GRAPHICS_INVALID_FREQUENCY"},
- {STATUS_GRAPHICS_INVALID_ACTIVE_REGION, -EIO,
- "STATUS_GRAPHICS_INVALID_ACTIVE_REGION"},
- {STATUS_GRAPHICS_INVALID_TOTAL_REGION, -EIO,
- "STATUS_GRAPHICS_INVALID_TOTAL_REGION"},
- {STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE"},
- {STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE"},
- {STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET, -EIO,
- "STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET"},
- {STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY, -EIO,
- "STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY"},
- {STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET, -EIO,
- "STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET"},
- {STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET"},
- {STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET"},
- {STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET, -EIO,
- "STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET"},
- {STATUS_GRAPHICS_TARGET_ALREADY_IN_SET, -EIO,
- "STATUS_GRAPHICS_TARGET_ALREADY_IN_SET"},
- {STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH"},
- {STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY, -EIO,
- "STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY"},
- {STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET, -EIO,
- "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET"},
- {STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE, -EIO,
- "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE"},
- {STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET, -EIO,
- "STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET"},
- {STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET, -EIO,
- "STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET"},
- {STATUS_GRAPHICS_STALE_MODESET, -EIO, "STATUS_GRAPHICS_STALE_MODESET"},
- {STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET, -EIO,
- "STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET"},
- {STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE, -EIO,
- "STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE"},
- {STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN, -EIO,
- "STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN"},
- {STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE, -EIO,
- "STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE"},
- {STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION, -EIO,
- "STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION"},
- {STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES, -EIO,
- "STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES"},
- {STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY, -EIO,
- "STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY"},
- {STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE, -EIO,
- "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE"},
- {STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET, -EIO,
- "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET"},
- {STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET, -EIO,
- "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET"},
- {STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR, -EIO,
- "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR"},
- {STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET, -EIO,
- "STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET"},
- {STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET, -EIO,
- "STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET"},
- {STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE, -EIO,
- "STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE"},
- {STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE"},
- {STATUS_GRAPHICS_RESOURCES_NOT_RELATED, -EIO,
- "STATUS_GRAPHICS_RESOURCES_NOT_RELATED"},
- {STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE, -EIO,
- "STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE"},
- {STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE, -EIO,
- "STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE"},
- {STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET, -EIO,
- "STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET"},
- {STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER, -EIO,
- "STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER"},
- {STATUS_GRAPHICS_NO_VIDPNMGR, -EIO, "STATUS_GRAPHICS_NO_VIDPNMGR"},
- {STATUS_GRAPHICS_NO_ACTIVE_VIDPN, -EIO,
- "STATUS_GRAPHICS_NO_ACTIVE_VIDPN"},
- {STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY, -EIO,
- "STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY"},
- {STATUS_GRAPHICS_MONITOR_NOT_CONNECTED, -EIO,
- "STATUS_GRAPHICS_MONITOR_NOT_CONNECTED"},
- {STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY, -EIO,
- "STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY"},
- {STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE, -EIO,
- "STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE"},
- {STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE, -EIO,
- "STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE"},
- {STATUS_GRAPHICS_INVALID_STRIDE, -EIO,
- "STATUS_GRAPHICS_INVALID_STRIDE"},
- {STATUS_GRAPHICS_INVALID_PIXELFORMAT, -EIO,
- "STATUS_GRAPHICS_INVALID_PIXELFORMAT"},
- {STATUS_GRAPHICS_INVALID_COLORBASIS, -EIO,
- "STATUS_GRAPHICS_INVALID_COLORBASIS"},
- {STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE, -EIO,
- "STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE"},
- {STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY, -EIO,
- "STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY"},
- {STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT, -EIO,
- "STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT"},
- {STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, -EIO,
- "STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE"},
- {STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN, -EIO,
- "STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN"},
- {STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL, -EIO,
- "STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL"},
- {STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION, -EIO,
- "STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION"},
- {STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED,
- -EIO,
- "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_INVALID_GAMMA_RAMP, -EIO,
- "STATUS_GRAPHICS_INVALID_GAMMA_RAMP"},
- {STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_MODE_NOT_IN_MODESET, -EIO,
- "STATUS_GRAPHICS_MODE_NOT_IN_MODESET"},
- {STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON, -EIO,
- "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON"},
- {STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE, -EIO,
- "STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE"},
- {STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE, -EIO,
- "STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE"},
- {STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS, -EIO,
- "STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS"},
- {STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING, -EIO,
- "STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING"},
- {STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED, -EIO,
- "STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED"},
- {STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS, -EIO,
- "STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS"},
- {STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT, -EIO,
- "STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT"},
- {STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM, -EIO,
- "STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM"},
- {STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN, -EIO,
- "STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN"},
- {STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT, -EIO,
- "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT"},
- {STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED, -EIO,
- "STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED"},
- {STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION, -EIO,
- "STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION"},
- {STATUS_GRAPHICS_INVALID_CLIENT_TYPE, -EIO,
- "STATUS_GRAPHICS_INVALID_CLIENT_TYPE"},
- {STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET, -EIO,
- "STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET"},
- {STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED, -EIO,
- "STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED"},
- {STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER, -EIO,
- "STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER"},
- {STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED, -EIO,
- "STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED"},
- {STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED, -EIO,
- "STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED"},
- {STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY, -EIO,
- "STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY"},
- {STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED, -EIO,
- "STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED"},
- {STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON, -EIO,
- "STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON"},
- {STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE, -EIO,
- "STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE"},
- {STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER, -EIO,
- "STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER"},
- {STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED, -EIO,
- "STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED"},
- {STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS,
- -EIO,
- "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS"},
- {STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST, -EIO,
- "STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST"},
- {STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR, -EIO,
- "STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR"},
- {STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS, -EIO,
- "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS"},
- {STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST, -EIO,
- "STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST"},
- {STATUS_GRAPHICS_OPM_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_OPM_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_COPP_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_COPP_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_UAB_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_UAB_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS, -EIO,
- "STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS"},
- {STATUS_GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL, -EIO,
- "STATUS_GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL"},
- {STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST, -EIO,
- "STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST"},
- {STATUS_GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME, -EIO,
- "STATUS_GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME"},
- {STATUS_GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP, -EIO,
- "STATUS_GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP"},
- {STATUS_GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_OPM_INVALID_POINTER, -EIO,
- "STATUS_GRAPHICS_OPM_INVALID_POINTER"},
- {STATUS_GRAPHICS_OPM_INTERNAL_ERROR, -EIO,
- "STATUS_GRAPHICS_OPM_INTERNAL_ERROR"},
- {STATUS_GRAPHICS_OPM_INVALID_HANDLE, -EIO,
- "STATUS_GRAPHICS_OPM_INVALID_HANDLE"},
- {STATUS_GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE, -EIO,
- "STATUS_GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE"},
- {STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH, -EIO,
- "STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH"},
- {STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED, -EIO,
- "STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED"},
- {STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED, -EIO,
- "STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED"},
- {STATUS_GRAPHICS_PVP_HFS_FAILED, -EIO,
- "STATUS_GRAPHICS_PVP_HFS_FAILED"},
- {STATUS_GRAPHICS_OPM_INVALID_SRM, -EIO,
- "STATUS_GRAPHICS_OPM_INVALID_SRM"},
- {STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP, -EIO,
- "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP"},
- {STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP, -EIO,
- "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP"},
- {STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA, -EIO,
- "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA"},
- {STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET, -EIO,
- "STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET"},
- {STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH, -EIO,
- "STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH"},
- {STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE, -EIO,
- "STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE"},
- {STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS, -EIO,
- "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS"},
- {STATUS_GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS, -EIO,
- "STATUS_GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS"},
- {STATUS_GRAPHICS_I2C_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_I2C_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST, -EIO,
- "STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST"},
- {STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA, -EIO,
- "STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA"},
- {STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA, -EIO,
- "STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA"},
- {STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_DDCCI_INVALID_DATA, -EIO,
- "STATUS_GRAPHICS_DDCCI_INVALID_DATA"},
- {STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE,
- -EIO,
- "STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE"},
- {STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING, -EIO,
- "STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING"},
- {STATUS_GRAPHICS_MCA_INTERNAL_ERROR, -EIO,
- "STATUS_GRAPHICS_MCA_INTERNAL_ERROR"},
- {STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND, -EIO,
- "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND"},
- {STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH, -EIO,
- "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH"},
- {STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM, -EIO,
- "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM"},
- {STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE, -EIO,
- "STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE"},
- {STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS, -EIO,
- "STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS"},
- {STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED"},
- {STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME, -EIO,
- "STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME"},
- {STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP, -EIO,
- "STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP"},
- {STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED, -EIO,
- "STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED"},
- {STATUS_GRAPHICS_INVALID_POINTER, -EIO,
- "STATUS_GRAPHICS_INVALID_POINTER"},
- {STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE, -EIO,
- "STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE"},
- {STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL, -EIO,
- "STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL"},
- {STATUS_GRAPHICS_INTERNAL_ERROR, -EIO,
- "STATUS_GRAPHICS_INTERNAL_ERROR"},
- {STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS, -EIO,
- "STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS"},
- {STATUS_FVE_LOCKED_VOLUME, -EIO, "STATUS_FVE_LOCKED_VOLUME"},
- {STATUS_FVE_NOT_ENCRYPTED, -EIO, "STATUS_FVE_NOT_ENCRYPTED"},
- {STATUS_FVE_BAD_INFORMATION, -EIO, "STATUS_FVE_BAD_INFORMATION"},
- {STATUS_FVE_TOO_SMALL, -EIO, "STATUS_FVE_TOO_SMALL"},
- {STATUS_FVE_FAILED_WRONG_FS, -EIO, "STATUS_FVE_FAILED_WRONG_FS"},
- {STATUS_FVE_FAILED_BAD_FS, -EIO, "STATUS_FVE_FAILED_BAD_FS"},
- {STATUS_FVE_FS_NOT_EXTENDED, -EIO, "STATUS_FVE_FS_NOT_EXTENDED"},
- {STATUS_FVE_FS_MOUNTED, -EIO, "STATUS_FVE_FS_MOUNTED"},
- {STATUS_FVE_NO_LICENSE, -EIO, "STATUS_FVE_NO_LICENSE"},
- {STATUS_FVE_ACTION_NOT_ALLOWED, -EIO, "STATUS_FVE_ACTION_NOT_ALLOWED"},
- {STATUS_FVE_BAD_DATA, -EIO, "STATUS_FVE_BAD_DATA"},
- {STATUS_FVE_VOLUME_NOT_BOUND, -EIO, "STATUS_FVE_VOLUME_NOT_BOUND"},
- {STATUS_FVE_NOT_DATA_VOLUME, -EIO, "STATUS_FVE_NOT_DATA_VOLUME"},
- {STATUS_FVE_CONV_READ_ERROR, -EIO, "STATUS_FVE_CONV_READ_ERROR"},
- {STATUS_FVE_CONV_WRITE_ERROR, -EIO, "STATUS_FVE_CONV_WRITE_ERROR"},
- {STATUS_FVE_OVERLAPPED_UPDATE, -EIO, "STATUS_FVE_OVERLAPPED_UPDATE"},
- {STATUS_FVE_FAILED_SECTOR_SIZE, -EIO, "STATUS_FVE_FAILED_SECTOR_SIZE"},
- {STATUS_FVE_FAILED_AUTHENTICATION, -EIO,
- "STATUS_FVE_FAILED_AUTHENTICATION"},
- {STATUS_FVE_NOT_OS_VOLUME, -EIO, "STATUS_FVE_NOT_OS_VOLUME"},
- {STATUS_FVE_KEYFILE_NOT_FOUND, -EIO, "STATUS_FVE_KEYFILE_NOT_FOUND"},
- {STATUS_FVE_KEYFILE_INVALID, -EIO, "STATUS_FVE_KEYFILE_INVALID"},
- {STATUS_FVE_KEYFILE_NO_VMK, -EIO, "STATUS_FVE_KEYFILE_NO_VMK"},
- {STATUS_FVE_TPM_DISABLED, -EIO, "STATUS_FVE_TPM_DISABLED"},
- {STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO, -EIO,
- "STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO"},
- {STATUS_FVE_TPM_INVALID_PCR, -EIO, "STATUS_FVE_TPM_INVALID_PCR"},
- {STATUS_FVE_TPM_NO_VMK, -EIO, "STATUS_FVE_TPM_NO_VMK"},
- {STATUS_FVE_PIN_INVALID, -EIO, "STATUS_FVE_PIN_INVALID"},
- {STATUS_FVE_AUTH_INVALID_APPLICATION, -EIO,
- "STATUS_FVE_AUTH_INVALID_APPLICATION"},
- {STATUS_FVE_AUTH_INVALID_CONFIG, -EIO,
- "STATUS_FVE_AUTH_INVALID_CONFIG"},
- {STATUS_FVE_DEBUGGER_ENABLED, -EIO, "STATUS_FVE_DEBUGGER_ENABLED"},
- {STATUS_FVE_DRY_RUN_FAILED, -EIO, "STATUS_FVE_DRY_RUN_FAILED"},
- {STATUS_FVE_BAD_METADATA_POINTER, -EIO,
- "STATUS_FVE_BAD_METADATA_POINTER"},
- {STATUS_FVE_OLD_METADATA_COPY, -EIO, "STATUS_FVE_OLD_METADATA_COPY"},
- {STATUS_FVE_REBOOT_REQUIRED, -EIO, "STATUS_FVE_REBOOT_REQUIRED"},
- {STATUS_FVE_RAW_ACCESS, -EIO, "STATUS_FVE_RAW_ACCESS"},
- {STATUS_FVE_RAW_BLOCKED, -EIO, "STATUS_FVE_RAW_BLOCKED"},
- {STATUS_FWP_CALLOUT_NOT_FOUND, -EIO, "STATUS_FWP_CALLOUT_NOT_FOUND"},
- {STATUS_FWP_CONDITION_NOT_FOUND, -EIO,
- "STATUS_FWP_CONDITION_NOT_FOUND"},
- {STATUS_FWP_FILTER_NOT_FOUND, -EIO, "STATUS_FWP_FILTER_NOT_FOUND"},
- {STATUS_FWP_LAYER_NOT_FOUND, -EIO, "STATUS_FWP_LAYER_NOT_FOUND"},
- {STATUS_FWP_PROVIDER_NOT_FOUND, -EIO, "STATUS_FWP_PROVIDER_NOT_FOUND"},
- {STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND, -EIO,
- "STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND"},
- {STATUS_FWP_SUBLAYER_NOT_FOUND, -EIO, "STATUS_FWP_SUBLAYER_NOT_FOUND"},
- {STATUS_FWP_NOT_FOUND, -EIO, "STATUS_FWP_NOT_FOUND"},
- {STATUS_FWP_ALREADY_EXISTS, -EIO, "STATUS_FWP_ALREADY_EXISTS"},
- {STATUS_FWP_IN_USE, -EIO, "STATUS_FWP_IN_USE"},
- {STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS, -EIO,
- "STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS"},
- {STATUS_FWP_WRONG_SESSION, -EIO, "STATUS_FWP_WRONG_SESSION"},
- {STATUS_FWP_NO_TXN_IN_PROGRESS, -EIO, "STATUS_FWP_NO_TXN_IN_PROGRESS"},
- {STATUS_FWP_TXN_IN_PROGRESS, -EIO, "STATUS_FWP_TXN_IN_PROGRESS"},
- {STATUS_FWP_TXN_ABORTED, -EIO, "STATUS_FWP_TXN_ABORTED"},
- {STATUS_FWP_SESSION_ABORTED, -EIO, "STATUS_FWP_SESSION_ABORTED"},
- {STATUS_FWP_INCOMPATIBLE_TXN, -EIO, "STATUS_FWP_INCOMPATIBLE_TXN"},
- {STATUS_FWP_TIMEOUT, -ETIMEDOUT, "STATUS_FWP_TIMEOUT"},
- {STATUS_FWP_NET_EVENTS_DISABLED, -EIO,
- "STATUS_FWP_NET_EVENTS_DISABLED"},
- {STATUS_FWP_INCOMPATIBLE_LAYER, -EIO, "STATUS_FWP_INCOMPATIBLE_LAYER"},
- {STATUS_FWP_KM_CLIENTS_ONLY, -EIO, "STATUS_FWP_KM_CLIENTS_ONLY"},
- {STATUS_FWP_LIFETIME_MISMATCH, -EIO, "STATUS_FWP_LIFETIME_MISMATCH"},
- {STATUS_FWP_BUILTIN_OBJECT, -EIO, "STATUS_FWP_BUILTIN_OBJECT"},
- {STATUS_FWP_TOO_MANY_BOOTTIME_FILTERS, -EIO,
- "STATUS_FWP_TOO_MANY_BOOTTIME_FILTERS"},
- {STATUS_FWP_TOO_MANY_CALLOUTS, -EIO, "STATUS_FWP_TOO_MANY_CALLOUTS"},
- {STATUS_FWP_NOTIFICATION_DROPPED, -EIO,
- "STATUS_FWP_NOTIFICATION_DROPPED"},
- {STATUS_FWP_TRAFFIC_MISMATCH, -EIO, "STATUS_FWP_TRAFFIC_MISMATCH"},
- {STATUS_FWP_INCOMPATIBLE_SA_STATE, -EIO,
- "STATUS_FWP_INCOMPATIBLE_SA_STATE"},
- {STATUS_FWP_NULL_POINTER, -EIO, "STATUS_FWP_NULL_POINTER"},
- {STATUS_FWP_INVALID_ENUMERATOR, -EIO, "STATUS_FWP_INVALID_ENUMERATOR"},
- {STATUS_FWP_INVALID_FLAGS, -EIO, "STATUS_FWP_INVALID_FLAGS"},
- {STATUS_FWP_INVALID_NET_MASK, -EIO, "STATUS_FWP_INVALID_NET_MASK"},
- {STATUS_FWP_INVALID_RANGE, -EIO, "STATUS_FWP_INVALID_RANGE"},
- {STATUS_FWP_INVALID_INTERVAL, -EIO, "STATUS_FWP_INVALID_INTERVAL"},
- {STATUS_FWP_ZERO_LENGTH_ARRAY, -EIO, "STATUS_FWP_ZERO_LENGTH_ARRAY"},
- {STATUS_FWP_NULL_DISPLAY_NAME, -EIO, "STATUS_FWP_NULL_DISPLAY_NAME"},
- {STATUS_FWP_INVALID_ACTION_TYPE, -EIO,
- "STATUS_FWP_INVALID_ACTION_TYPE"},
- {STATUS_FWP_INVALID_WEIGHT, -EIO, "STATUS_FWP_INVALID_WEIGHT"},
- {STATUS_FWP_MATCH_TYPE_MISMATCH, -EIO,
- "STATUS_FWP_MATCH_TYPE_MISMATCH"},
- {STATUS_FWP_TYPE_MISMATCH, -EIO, "STATUS_FWP_TYPE_MISMATCH"},
- {STATUS_FWP_OUT_OF_BOUNDS, -EIO, "STATUS_FWP_OUT_OF_BOUNDS"},
- {STATUS_FWP_RESERVED, -EIO, "STATUS_FWP_RESERVED"},
- {STATUS_FWP_DUPLICATE_CONDITION, -EIO,
- "STATUS_FWP_DUPLICATE_CONDITION"},
- {STATUS_FWP_DUPLICATE_KEYMOD, -EIO, "STATUS_FWP_DUPLICATE_KEYMOD"},
- {STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER, -EIO,
- "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER"},
- {STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER, -EIO,
- "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER"},
- {STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER, -EIO,
- "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER"},
- {STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT, -EIO,
- "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT"},
- {STATUS_FWP_INCOMPATIBLE_AUTH_METHOD, -EIO,
- "STATUS_FWP_INCOMPATIBLE_AUTH_METHOD"},
- {STATUS_FWP_INCOMPATIBLE_DH_GROUP, -EIO,
- "STATUS_FWP_INCOMPATIBLE_DH_GROUP"},
- {STATUS_FWP_EM_NOT_SUPPORTED, -EOPNOTSUPP,
- "STATUS_FWP_EM_NOT_SUPPORTED"},
- {STATUS_FWP_NEVER_MATCH, -EIO, "STATUS_FWP_NEVER_MATCH"},
- {STATUS_FWP_PROVIDER_CONTEXT_MISMATCH, -EIO,
- "STATUS_FWP_PROVIDER_CONTEXT_MISMATCH"},
- {STATUS_FWP_INVALID_PARAMETER, -EIO, "STATUS_FWP_INVALID_PARAMETER"},
- {STATUS_FWP_TOO_MANY_SUBLAYERS, -EIO, "STATUS_FWP_TOO_MANY_SUBLAYERS"},
- {STATUS_FWP_CALLOUT_NOTIFICATION_FAILED, -EIO,
- "STATUS_FWP_CALLOUT_NOTIFICATION_FAILED"},
- {STATUS_FWP_INCOMPATIBLE_AUTH_CONFIG, -EIO,
- "STATUS_FWP_INCOMPATIBLE_AUTH_CONFIG"},
- {STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG, -EIO,
- "STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG"},
- {STATUS_FWP_TCPIP_NOT_READY, -EIO, "STATUS_FWP_TCPIP_NOT_READY"},
- {STATUS_FWP_INJECT_HANDLE_CLOSING, -EIO,
- "STATUS_FWP_INJECT_HANDLE_CLOSING"},
- {STATUS_FWP_INJECT_HANDLE_STALE, -EIO,
- "STATUS_FWP_INJECT_HANDLE_STALE"},
- {STATUS_FWP_CANNOT_PEND, -EIO, "STATUS_FWP_CANNOT_PEND"},
- {STATUS_NDIS_CLOSING, -EIO, "STATUS_NDIS_CLOSING"},
- {STATUS_NDIS_BAD_VERSION, -EIO, "STATUS_NDIS_BAD_VERSION"},
- {STATUS_NDIS_BAD_CHARACTERISTICS, -EIO,
- "STATUS_NDIS_BAD_CHARACTERISTICS"},
- {STATUS_NDIS_ADAPTER_NOT_FOUND, -EIO, "STATUS_NDIS_ADAPTER_NOT_FOUND"},
- {STATUS_NDIS_OPEN_FAILED, -EIO, "STATUS_NDIS_OPEN_FAILED"},
- {STATUS_NDIS_DEVICE_FAILED, -EIO, "STATUS_NDIS_DEVICE_FAILED"},
- {STATUS_NDIS_MULTICAST_FULL, -EIO, "STATUS_NDIS_MULTICAST_FULL"},
- {STATUS_NDIS_MULTICAST_EXISTS, -EIO, "STATUS_NDIS_MULTICAST_EXISTS"},
- {STATUS_NDIS_MULTICAST_NOT_FOUND, -EIO,
- "STATUS_NDIS_MULTICAST_NOT_FOUND"},
- {STATUS_NDIS_REQUEST_ABORTED, -EIO, "STATUS_NDIS_REQUEST_ABORTED"},
- {STATUS_NDIS_RESET_IN_PROGRESS, -EIO, "STATUS_NDIS_RESET_IN_PROGRESS"},
- {STATUS_NDIS_INVALID_PACKET, -EIO, "STATUS_NDIS_INVALID_PACKET"},
- {STATUS_NDIS_INVALID_DEVICE_REQUEST, -EIO,
- "STATUS_NDIS_INVALID_DEVICE_REQUEST"},
- {STATUS_NDIS_ADAPTER_NOT_READY, -EIO, "STATUS_NDIS_ADAPTER_NOT_READY"},
- {STATUS_NDIS_INVALID_LENGTH, -EIO, "STATUS_NDIS_INVALID_LENGTH"},
- {STATUS_NDIS_INVALID_DATA, -EIO, "STATUS_NDIS_INVALID_DATA"},
- {STATUS_NDIS_BUFFER_TOO_SHORT, -ENOBUFS,
- "STATUS_NDIS_BUFFER_TOO_SHORT"},
- {STATUS_NDIS_INVALID_OID, -EIO, "STATUS_NDIS_INVALID_OID"},
- {STATUS_NDIS_ADAPTER_REMOVED, -EIO, "STATUS_NDIS_ADAPTER_REMOVED"},
- {STATUS_NDIS_UNSUPPORTED_MEDIA, -EIO, "STATUS_NDIS_UNSUPPORTED_MEDIA"},
- {STATUS_NDIS_GROUP_ADDRESS_IN_USE, -EIO,
- "STATUS_NDIS_GROUP_ADDRESS_IN_USE"},
- {STATUS_NDIS_FILE_NOT_FOUND, -EIO, "STATUS_NDIS_FILE_NOT_FOUND"},
- {STATUS_NDIS_ERROR_READING_FILE, -EIO,
- "STATUS_NDIS_ERROR_READING_FILE"},
- {STATUS_NDIS_ALREADY_MAPPED, -EIO, "STATUS_NDIS_ALREADY_MAPPED"},
- {STATUS_NDIS_RESOURCE_CONFLICT, -EIO, "STATUS_NDIS_RESOURCE_CONFLICT"},
- {STATUS_NDIS_MEDIA_DISCONNECTED, -EIO,
- "STATUS_NDIS_MEDIA_DISCONNECTED"},
- {STATUS_NDIS_INVALID_ADDRESS, -EIO, "STATUS_NDIS_INVALID_ADDRESS"},
- {STATUS_NDIS_PAUSED, -EIO, "STATUS_NDIS_PAUSED"},
- {STATUS_NDIS_INTERFACE_NOT_FOUND, -EIO,
- "STATUS_NDIS_INTERFACE_NOT_FOUND"},
- {STATUS_NDIS_UNSUPPORTED_REVISION, -EIO,
- "STATUS_NDIS_UNSUPPORTED_REVISION"},
- {STATUS_NDIS_INVALID_PORT, -EIO, "STATUS_NDIS_INVALID_PORT"},
- {STATUS_NDIS_INVALID_PORT_STATE, -EIO,
- "STATUS_NDIS_INVALID_PORT_STATE"},
- {STATUS_NDIS_LOW_POWER_STATE, -EIO, "STATUS_NDIS_LOW_POWER_STATE"},
- {STATUS_NDIS_NOT_SUPPORTED, -ENOSYS, "STATUS_NDIS_NOT_SUPPORTED"},
- {STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED, -EIO,
- "STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED"},
- {STATUS_NDIS_DOT11_MEDIA_IN_USE, -EIO,
- "STATUS_NDIS_DOT11_MEDIA_IN_USE"},
- {STATUS_NDIS_DOT11_POWER_STATE_INVALID, -EIO,
- "STATUS_NDIS_DOT11_POWER_STATE_INVALID"},
- {STATUS_IPSEC_BAD_SPI, -EIO, "STATUS_IPSEC_BAD_SPI"},
- {STATUS_IPSEC_SA_LIFETIME_EXPIRED, -EIO,
- "STATUS_IPSEC_SA_LIFETIME_EXPIRED"},
- {STATUS_IPSEC_WRONG_SA, -EIO, "STATUS_IPSEC_WRONG_SA"},
- {STATUS_IPSEC_REPLAY_CHECK_FAILED, -EIO,
- "STATUS_IPSEC_REPLAY_CHECK_FAILED"},
- {STATUS_IPSEC_INVALID_PACKET, -EIO, "STATUS_IPSEC_INVALID_PACKET"},
- {STATUS_IPSEC_INTEGRITY_CHECK_FAILED, -EIO,
- "STATUS_IPSEC_INTEGRITY_CHECK_FAILED"},
- {STATUS_IPSEC_CLEAR_TEXT_DROP, -EIO, "STATUS_IPSEC_CLEAR_TEXT_DROP"},
- {0, 0, NULL}
-};
-
-/*****************************************************************************
- Print an error message from the status code
- *****************************************************************************/
-static void
-smb2_print_status(__le32 status)
-{
- int idx = 0;
-
- while (smb2_error_map_table[idx].status_string != NULL) {
- if ((smb2_error_map_table[idx].smb2_status) == status) {
- pr_notice("Status code returned 0x%08x %s\n", status,
- smb2_error_map_table[idx].status_string);
- }
- idx++;
- }
- return;
-}
-
-int
-map_smb2_to_linux_error(char *buf, bool log_err)
-{
- struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
- unsigned int i;
- int rc = -EIO;
- __le32 smb2err = shdr->Status;
-
- if (smb2err == 0) {
- trace_smb3_cmd_done(le32_to_cpu(shdr->Id.SyncId.TreeId),
- le64_to_cpu(shdr->SessionId),
- le16_to_cpu(shdr->Command),
- le64_to_cpu(shdr->MessageId));
- return 0;
- }
-
- /* mask facility */
- if (log_err && (smb2err != STATUS_MORE_PROCESSING_REQUIRED) &&
- (smb2err != STATUS_END_OF_FILE))
- smb2_print_status(smb2err);
- else if (cifsFYI & CIFS_RC)
- smb2_print_status(smb2err);
-
- for (i = 0; i < sizeof(smb2_error_map_table) /
- sizeof(struct status_to_posix_error); i++) {
- if (smb2_error_map_table[i].smb2_status == smb2err) {
- rc = smb2_error_map_table[i].posix_error;
- break;
- }
- }
-
- /* on error mapping not found - return EIO */
-
- cifs_dbg(FYI, "Mapping SMB2 status code 0x%08x to POSIX err %d\n",
- __le32_to_cpu(smb2err), rc);
-
- trace_smb3_cmd_err(le32_to_cpu(shdr->Id.SyncId.TreeId),
- le64_to_cpu(shdr->SessionId),
- le16_to_cpu(shdr->Command),
- le64_to_cpu(shdr->MessageId),
- le32_to_cpu(smb2err), rc);
- return rc;
-}
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
deleted file mode 100644
index 572293c18e16..000000000000
--- a/fs/cifs/smb2misc.c
+++ /dev/null
@@ -1,944 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002,2011
- * Etersoft, 2012
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Pavel Shilovsky (pshilovsky@samba.org) 2012
- *
- */
-#include <linux/ctype.h>
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "smb2proto.h"
-#include "cifs_debug.h"
-#include "cifs_unicode.h"
-#include "smb2status.h"
-#include "smb2glob.h"
-#include "nterr.h"
-#include "cached_dir.h"
-
-static int
-check_smb2_hdr(struct smb2_hdr *shdr, __u64 mid)
-{
- __u64 wire_mid = le64_to_cpu(shdr->MessageId);
-
- /*
- * Make sure that this really is an SMB, that it is a response,
- * and that the message ids match.
- */
- if ((shdr->ProtocolId == SMB2_PROTO_NUMBER) &&
- (mid == wire_mid)) {
- if (shdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
- return 0;
- else {
- /* only one valid case where server sends us request */
- if (shdr->Command == SMB2_OPLOCK_BREAK)
- return 0;
- else
- cifs_dbg(VFS, "Received Request not response\n");
- }
- } else { /* bad signature or mid */
- if (shdr->ProtocolId != SMB2_PROTO_NUMBER)
- cifs_dbg(VFS, "Bad protocol string signature header %x\n",
- le32_to_cpu(shdr->ProtocolId));
- if (mid != wire_mid)
- cifs_dbg(VFS, "Mids do not match: %llu and %llu\n",
- mid, wire_mid);
- }
- cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu\n", wire_mid);
- return 1;
-}
-
-/*
- * The following table defines the expected "StructureSize" of SMB2 responses
- * in order by SMB2 command. This is similar to "wct" in SMB/CIFS responses.
- *
- * Note that commands are defined in smb2pdu.h in le16 but the array below is
- * indexed by command in host byte order
- */
-static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
- /* SMB2_NEGOTIATE */ cpu_to_le16(65),
- /* SMB2_SESSION_SETUP */ cpu_to_le16(9),
- /* SMB2_LOGOFF */ cpu_to_le16(4),
- /* SMB2_TREE_CONNECT */ cpu_to_le16(16),
- /* SMB2_TREE_DISCONNECT */ cpu_to_le16(4),
- /* SMB2_CREATE */ cpu_to_le16(89),
- /* SMB2_CLOSE */ cpu_to_le16(60),
- /* SMB2_FLUSH */ cpu_to_le16(4),
- /* SMB2_READ */ cpu_to_le16(17),
- /* SMB2_WRITE */ cpu_to_le16(17),
- /* SMB2_LOCK */ cpu_to_le16(4),
- /* SMB2_IOCTL */ cpu_to_le16(49),
- /* BB CHECK this ... not listed in documentation */
- /* SMB2_CANCEL */ cpu_to_le16(0),
- /* SMB2_ECHO */ cpu_to_le16(4),
- /* SMB2_QUERY_DIRECTORY */ cpu_to_le16(9),
- /* SMB2_CHANGE_NOTIFY */ cpu_to_le16(9),
- /* SMB2_QUERY_INFO */ cpu_to_le16(9),
- /* SMB2_SET_INFO */ cpu_to_le16(2),
- /* BB FIXME can also be 44 for lease break */
- /* SMB2_OPLOCK_BREAK */ cpu_to_le16(24)
-};
-
-#define SMB311_NEGPROT_BASE_SIZE (sizeof(struct smb2_hdr) + sizeof(struct smb2_negotiate_rsp))
-
-static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len,
- __u32 non_ctxlen)
-{
- __u16 neg_count;
- __u32 nc_offset, size_of_pad_before_neg_ctxts;
- struct smb2_negotiate_rsp *pneg_rsp = (struct smb2_negotiate_rsp *)hdr;
-
- /* Negotiate contexts are only valid for latest dialect SMB3.11 */
- neg_count = le16_to_cpu(pneg_rsp->NegotiateContextCount);
- if ((neg_count == 0) ||
- (pneg_rsp->DialectRevision != cpu_to_le16(SMB311_PROT_ID)))
- return 0;
-
- /*
- * if SPNEGO blob present (ie the RFC2478 GSS info which indicates
- * which security mechanisms the server supports) make sure that
- * the negotiate contexts start after it
- */
- nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset);
- /*
- * non_ctxlen is at least shdr->StructureSize + pdu->StructureSize2
- * and the latter is 1 byte bigger than the fix-sized area of the
- * NEGOTIATE response
- */
- if (nc_offset + 1 < non_ctxlen) {
- pr_warn_once("Invalid negotiate context offset %d\n", nc_offset);
- return 0;
- } else if (nc_offset + 1 == non_ctxlen) {
- cifs_dbg(FYI, "no SPNEGO security blob in negprot rsp\n");
- size_of_pad_before_neg_ctxts = 0;
- } else if (non_ctxlen == SMB311_NEGPROT_BASE_SIZE)
- /* has padding, but no SPNEGO blob */
- size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen + 1;
- else
- size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen;
-
- /* Verify that at least minimal negotiate contexts fit within frame */
- if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) {
- pr_warn_once("negotiate context goes beyond end\n");
- return 0;
- }
-
- cifs_dbg(FYI, "length of negcontexts %d pad %d\n",
- len - nc_offset, size_of_pad_before_neg_ctxts);
-
- /* length of negcontexts including pad from end of sec blob to them */
- return (len - nc_offset) + size_of_pad_before_neg_ctxts;
-}
-
-int
-smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)
-{
- struct TCP_Server_Info *pserver;
- struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
- struct smb2_pdu *pdu = (struct smb2_pdu *)shdr;
- int hdr_size = sizeof(struct smb2_hdr);
- int pdu_size = sizeof(struct smb2_pdu);
- int command;
- __u32 calc_len; /* calculated length */
- __u64 mid;
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
- /*
- * Add function to do table lookup of StructureSize by command
- * ie Validate the wct via smb2_struct_sizes table above
- */
- if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
- struct smb2_transform_hdr *thdr =
- (struct smb2_transform_hdr *)buf;
- struct cifs_ses *ses = NULL;
- struct cifs_ses *iter;
-
- /* decrypt frame now that it is completely read in */
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(iter, &pserver->smb_ses_list, smb_ses_list) {
- if (iter->Suid == le64_to_cpu(thdr->SessionId)) {
- ses = iter;
- break;
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
- if (!ses) {
- cifs_dbg(VFS, "no decryption - session id not found\n");
- return 1;
- }
- }
-
- mid = le64_to_cpu(shdr->MessageId);
- if (len < pdu_size) {
- if ((len >= hdr_size)
- && (shdr->Status != 0)) {
- pdu->StructureSize2 = 0;
- /*
- * As with SMB/CIFS, on some error cases servers may
- * not return wct properly
- */
- return 0;
- } else {
- cifs_dbg(VFS, "Length less than SMB header size\n");
- }
- return 1;
- }
- if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) {
- cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n",
- mid);
- return 1;
- }
-
- if (check_smb2_hdr(shdr, mid))
- return 1;
-
- if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
- cifs_dbg(VFS, "Invalid structure size %u\n",
- le16_to_cpu(shdr->StructureSize));
- return 1;
- }
-
- command = le16_to_cpu(shdr->Command);
- if (command >= NUMBER_OF_SMB2_COMMANDS) {
- cifs_dbg(VFS, "Invalid SMB2 command %d\n", command);
- return 1;
- }
-
- if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) {
- if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 ||
- pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2_LE)) {
- /* error packets have 9 byte structure size */
- cifs_dbg(VFS, "Invalid response size %u for command %d\n",
- le16_to_cpu(pdu->StructureSize2), command);
- return 1;
- } else if (command == SMB2_OPLOCK_BREAK_HE
- && (shdr->Status == 0)
- && (le16_to_cpu(pdu->StructureSize2) != 44)
- && (le16_to_cpu(pdu->StructureSize2) != 36)) {
- /* special case for SMB2.1 lease break message */
- cifs_dbg(VFS, "Invalid response size %d for oplock break\n",
- le16_to_cpu(pdu->StructureSize2));
- return 1;
- }
- }
-
- calc_len = smb2_calc_size(buf);
-
- /* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might
- * be 0, and not a real miscalculation */
- if (command == SMB2_IOCTL_HE && calc_len == 0)
- return 0;
-
- if (command == SMB2_NEGOTIATE_HE)
- calc_len += get_neg_ctxt_len(shdr, len, calc_len);
-
- if (len != calc_len) {
- /* create failed on symlink */
- if (command == SMB2_CREATE_HE &&
- shdr->Status == STATUS_STOPPED_ON_SYMLINK)
- return 0;
- /* Windows 7 server returns 24 bytes more */
- if (calc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)
- return 0;
- /* server can return one byte more due to implied bcc[0] */
- if (calc_len == len + 1)
- return 0;
-
- /*
- * Some windows servers (win2016) will pad also the final
- * PDU in a compound to 8 bytes.
- */
- if (ALIGN(calc_len, 8) == len)
- return 0;
-
- /*
- * MacOS server pads after SMB2.1 write response with 3 bytes
- * of junk. Other servers match RFC1001 len to actual
- * SMB2/SMB3 frame length (header + smb2 response specific data)
- * Some windows servers also pad up to 8 bytes when compounding.
- */
- if (calc_len < len)
- return 0;
-
- /* Only log a message if len was really miscalculated */
- if (unlikely(cifsFYI))
- cifs_dbg(FYI, "Server response too short: calculated "
- "length %u doesn't match read length %u (cmd=%d, mid=%llu)\n",
- calc_len, len, command, mid);
- else
- pr_warn("Server response too short: calculated length "
- "%u doesn't match read length %u (cmd=%d, mid=%llu)\n",
- calc_len, len, command, mid);
-
- return 1;
- }
- return 0;
-}
-
-/*
- * The size of the variable area depends on the offset and length fields
- * located in different fields for various SMB2 responses. SMB2 responses
- * with no variable length info, show an offset of zero for the offset field.
- */
-static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
- /* SMB2_NEGOTIATE */ true,
- /* SMB2_SESSION_SETUP */ true,
- /* SMB2_LOGOFF */ false,
- /* SMB2_TREE_CONNECT */ false,
- /* SMB2_TREE_DISCONNECT */ false,
- /* SMB2_CREATE */ true,
- /* SMB2_CLOSE */ false,
- /* SMB2_FLUSH */ false,
- /* SMB2_READ */ true,
- /* SMB2_WRITE */ false,
- /* SMB2_LOCK */ false,
- /* SMB2_IOCTL */ true,
- /* SMB2_CANCEL */ false, /* BB CHECK this not listed in documentation */
- /* SMB2_ECHO */ false,
- /* SMB2_QUERY_DIRECTORY */ true,
- /* SMB2_CHANGE_NOTIFY */ true,
- /* SMB2_QUERY_INFO */ true,
- /* SMB2_SET_INFO */ false,
- /* SMB2_OPLOCK_BREAK */ false
-};
-
-/*
- * Returns the pointer to the beginning of the data area. Length of the data
- * area and the offset to it (from the beginning of the smb are also returned.
- */
-char *
-smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *shdr)
-{
- *off = 0;
- *len = 0;
-
- /* error responses do not have data area */
- if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
- (((struct smb2_err_rsp *)shdr)->StructureSize) ==
- SMB2_ERROR_STRUCTURE_SIZE2_LE)
- return NULL;
-
- /*
- * Following commands have data areas so we have to get the location
- * of the data buffer offset and data buffer length for the particular
- * command.
- */
- switch (shdr->Command) {
- case SMB2_NEGOTIATE:
- *off = le16_to_cpu(
- ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferOffset);
- *len = le16_to_cpu(
- ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferLength);
- break;
- case SMB2_SESSION_SETUP:
- *off = le16_to_cpu(
- ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
- *len = le16_to_cpu(
- ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
- break;
- case SMB2_CREATE:
- *off = le32_to_cpu(
- ((struct smb2_create_rsp *)shdr)->CreateContextsOffset);
- *len = le32_to_cpu(
- ((struct smb2_create_rsp *)shdr)->CreateContextsLength);
- break;
- case SMB2_QUERY_INFO:
- *off = le16_to_cpu(
- ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset);
- *len = le32_to_cpu(
- ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength);
- break;
- case SMB2_READ:
- /* TODO: is this a bug ? */
- *off = ((struct smb2_read_rsp *)shdr)->DataOffset;
- *len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength);
- break;
- case SMB2_QUERY_DIRECTORY:
- *off = le16_to_cpu(
- ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset);
- *len = le32_to_cpu(
- ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength);
- break;
- case SMB2_IOCTL:
- *off = le32_to_cpu(
- ((struct smb2_ioctl_rsp *)shdr)->OutputOffset);
- *len = le32_to_cpu(
- ((struct smb2_ioctl_rsp *)shdr)->OutputCount);
- break;
- case SMB2_CHANGE_NOTIFY:
- *off = le16_to_cpu(
- ((struct smb2_change_notify_rsp *)shdr)->OutputBufferOffset);
- *len = le32_to_cpu(
- ((struct smb2_change_notify_rsp *)shdr)->OutputBufferLength);
- break;
- default:
- cifs_dbg(VFS, "no length check for command %d\n", le16_to_cpu(shdr->Command));
- break;
- }
-
- /*
- * Invalid length or offset probably means data area is invalid, but
- * we have little choice but to ignore the data area in this case.
- */
- if (*off > 4096) {
- cifs_dbg(VFS, "offset %d too large, data area ignored\n", *off);
- *len = 0;
- *off = 0;
- } else if (*off < 0) {
- cifs_dbg(VFS, "negative offset %d to data invalid ignore data area\n",
- *off);
- *off = 0;
- *len = 0;
- } else if (*len < 0) {
- cifs_dbg(VFS, "negative data length %d invalid, data area ignored\n",
- *len);
- *len = 0;
- } else if (*len > 128 * 1024) {
- cifs_dbg(VFS, "data area larger than 128K: %d\n", *len);
- *len = 0;
- }
-
- /* return pointer to beginning of data area, ie offset from SMB start */
- if ((*off != 0) && (*len != 0))
- return (char *)shdr + *off;
- else
- return NULL;
-}
-
-/*
- * Calculate the size of the SMB message based on the fixed header
- * portion, the number of word parameters and the data portion of the message.
- */
-unsigned int
-smb2_calc_size(void *buf)
-{
- struct smb2_pdu *pdu = buf;
- struct smb2_hdr *shdr = &pdu->hdr;
- int offset; /* the offset from the beginning of SMB to data area */
- int data_length; /* the length of the variable length data area */
- /* Structure Size has already been checked to make sure it is 64 */
- int len = le16_to_cpu(shdr->StructureSize);
-
- /*
- * StructureSize2, ie length of fixed parameter area has already
- * been checked to make sure it is the correct length.
- */
- len += le16_to_cpu(pdu->StructureSize2);
-
- if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
- goto calc_size_exit;
-
- smb2_get_data_area_len(&offset, &data_length, shdr);
- cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset);
-
- if (data_length > 0) {
- /*
- * Check to make sure that data area begins after fixed area,
- * Note that last byte of the fixed area is part of data area
- * for some commands, typically those with odd StructureSize,
- * so we must add one to the calculation.
- */
- if (offset + 1 < len) {
- cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n",
- offset + 1, len);
- data_length = 0;
- } else {
- len = offset + data_length;
- }
- }
-calc_size_exit:
- cifs_dbg(FYI, "SMB2 len %d\n", len);
- return len;
-}
-
-/* Note: caller must free return buffer */
-__le16 *
-cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
-{
- int len;
- const char *start_of_path;
- __le16 *to;
- int map_type;
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
- map_type = SFM_MAP_UNI_RSVD;
- else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
- map_type = SFU_MAP_UNI_RSVD;
- else
- map_type = NO_MAP_UNI_RSVD;
-
- /* Windows doesn't allow paths beginning with \ */
- if (from[0] == '\\')
- start_of_path = from + 1;
-
- /* SMB311 POSIX extensions paths do not include leading slash */
- else if (cifs_sb_master_tlink(cifs_sb) &&
- cifs_sb_master_tcon(cifs_sb)->posix_extensions &&
- (from[0] == '/')) {
- start_of_path = from + 1;
- } else
- start_of_path = from;
-
- to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
- cifs_sb->local_nls, map_type);
- return to;
-}
-
-__le32
-smb2_get_lease_state(struct cifsInodeInfo *cinode)
-{
- __le32 lease = 0;
-
- if (CIFS_CACHE_WRITE(cinode))
- lease |= SMB2_LEASE_WRITE_CACHING_LE;
- if (CIFS_CACHE_HANDLE(cinode))
- lease |= SMB2_LEASE_HANDLE_CACHING_LE;
- if (CIFS_CACHE_READ(cinode))
- lease |= SMB2_LEASE_READ_CACHING_LE;
- return lease;
-}
-
-struct smb2_lease_break_work {
- struct work_struct lease_break;
- struct tcon_link *tlink;
- __u8 lease_key[16];
- __le32 lease_state;
-};
-
-static void
-cifs_ses_oplock_break(struct work_struct *work)
-{
- struct smb2_lease_break_work *lw = container_of(work,
- struct smb2_lease_break_work, lease_break);
- int rc = 0;
-
- rc = SMB2_lease_break(0, tlink_tcon(lw->tlink), lw->lease_key,
- lw->lease_state);
-
- cifs_dbg(FYI, "Lease release rc %d\n", rc);
- cifs_put_tlink(lw->tlink);
- kfree(lw);
-}
-
-static void
-smb2_queue_pending_open_break(struct tcon_link *tlink, __u8 *lease_key,
- __le32 new_lease_state)
-{
- struct smb2_lease_break_work *lw;
-
- lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL);
- if (!lw) {
- cifs_put_tlink(tlink);
- return;
- }
-
- INIT_WORK(&lw->lease_break, cifs_ses_oplock_break);
- lw->tlink = tlink;
- lw->lease_state = new_lease_state;
- memcpy(lw->lease_key, lease_key, SMB2_LEASE_KEY_SIZE);
- queue_work(cifsiod_wq, &lw->lease_break);
-}
-
-static bool
-smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp)
-{
- __u8 lease_state;
- struct cifsFileInfo *cfile;
- struct cifsInodeInfo *cinode;
- int ack_req = le32_to_cpu(rsp->Flags &
- SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
-
- lease_state = le32_to_cpu(rsp->NewLeaseState);
-
- list_for_each_entry(cfile, &tcon->openFileList, tlist) {
- cinode = CIFS_I(d_inode(cfile->dentry));
-
- if (memcmp(cinode->lease_key, rsp->LeaseKey,
- SMB2_LEASE_KEY_SIZE))
- continue;
-
- cifs_dbg(FYI, "found in the open list\n");
- cifs_dbg(FYI, "lease key match, lease break 0x%x\n",
- lease_state);
-
- if (ack_req)
- cfile->oplock_break_cancelled = false;
- else
- cfile->oplock_break_cancelled = true;
-
- set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
-
- cfile->oplock_epoch = le16_to_cpu(rsp->Epoch);
- cfile->oplock_level = lease_state;
-
- cifs_queue_oplock_break(cfile);
- return true;
- }
-
- return false;
-}
-
-static struct cifs_pending_open *
-smb2_tcon_find_pending_open_lease(struct cifs_tcon *tcon,
- struct smb2_lease_break *rsp)
-{
- __u8 lease_state = le32_to_cpu(rsp->NewLeaseState);
- int ack_req = le32_to_cpu(rsp->Flags &
- SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
- struct cifs_pending_open *open;
- struct cifs_pending_open *found = NULL;
-
- list_for_each_entry(open, &tcon->pending_opens, olist) {
- if (memcmp(open->lease_key, rsp->LeaseKey,
- SMB2_LEASE_KEY_SIZE))
- continue;
-
- if (!found && ack_req) {
- found = open;
- }
-
- cifs_dbg(FYI, "found in the pending open list\n");
- cifs_dbg(FYI, "lease key match, lease break 0x%x\n",
- lease_state);
-
- open->oplock = lease_state;
- }
-
- return found;
-}
-
-static bool
-smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
-{
- struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer;
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
- struct cifs_pending_open *open;
-
- cifs_dbg(FYI, "Checking for lease break\n");
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
- /* look up tcon based on tid & uid */
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- spin_lock(&tcon->open_file_lock);
- cifs_stats_inc(
- &tcon->stats.cifs_stats.num_oplock_brks);
- if (smb2_tcon_has_lease(tcon, rsp)) {
- spin_unlock(&tcon->open_file_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- return true;
- }
- open = smb2_tcon_find_pending_open_lease(tcon,
- rsp);
- if (open) {
- __u8 lease_key[SMB2_LEASE_KEY_SIZE];
- struct tcon_link *tlink;
-
- tlink = cifs_get_tlink(open->tlink);
- memcpy(lease_key, open->lease_key,
- SMB2_LEASE_KEY_SIZE);
- spin_unlock(&tcon->open_file_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- smb2_queue_pending_open_break(tlink,
- lease_key,
- rsp->NewLeaseState);
- return true;
- }
- spin_unlock(&tcon->open_file_lock);
-
- if (cached_dir_lease_break(tcon, rsp->LeaseKey)) {
- spin_unlock(&cifs_tcp_ses_lock);
- return true;
- }
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
- cifs_dbg(FYI, "Can not process lease break - no lease matched\n");
- trace_smb3_lease_not_found(le32_to_cpu(rsp->CurrentLeaseState),
- le32_to_cpu(rsp->hdr.Id.SyncId.TreeId),
- le64_to_cpu(rsp->hdr.SessionId),
- *((u64 *)rsp->LeaseKey),
- *((u64 *)&rsp->LeaseKey[8]));
-
- return false;
-}
-
-bool
-smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
-{
- struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
- struct cifsInodeInfo *cinode;
- struct cifsFileInfo *cfile;
-
- cifs_dbg(FYI, "Checking for oplock break\n");
-
- if (rsp->hdr.Command != SMB2_OPLOCK_BREAK)
- return false;
-
- if (rsp->StructureSize !=
- smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
- if (le16_to_cpu(rsp->StructureSize) == 44)
- return smb2_is_valid_lease_break(buffer, server);
- else
- return false;
- }
-
- cifs_dbg(FYI, "oplock level 0x%x\n", rsp->OplockLevel);
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
- /* look up tcon based on tid & uid */
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
-
- spin_lock(&tcon->open_file_lock);
- list_for_each_entry(cfile, &tcon->openFileList, tlist) {
- if (rsp->PersistentFid !=
- cfile->fid.persistent_fid ||
- rsp->VolatileFid !=
- cfile->fid.volatile_fid)
- continue;
-
- cifs_dbg(FYI, "file id match, oplock break\n");
- cifs_stats_inc(
- &tcon->stats.cifs_stats.num_oplock_brks);
- cinode = CIFS_I(d_inode(cfile->dentry));
- spin_lock(&cfile->file_info_lock);
- if (!CIFS_CACHE_WRITE(cinode) &&
- rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE)
- cfile->oplock_break_cancelled = true;
- else
- cfile->oplock_break_cancelled = false;
-
- set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
- &cinode->flags);
-
- cfile->oplock_epoch = 0;
- cfile->oplock_level = rsp->OplockLevel;
-
- spin_unlock(&cfile->file_info_lock);
-
- cifs_queue_oplock_break(cfile);
-
- spin_unlock(&tcon->open_file_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- return true;
- }
- spin_unlock(&tcon->open_file_lock);
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
- cifs_dbg(FYI, "No file id matched, oplock break ignored\n");
- trace_smb3_oplock_not_found(0 /* no xid */, rsp->PersistentFid,
- le32_to_cpu(rsp->hdr.Id.SyncId.TreeId),
- le64_to_cpu(rsp->hdr.SessionId));
-
- return true;
-}
-
-void
-smb2_cancelled_close_fid(struct work_struct *work)
-{
- struct close_cancelled_open *cancelled = container_of(work,
- struct close_cancelled_open, work);
- struct cifs_tcon *tcon = cancelled->tcon;
- int rc;
-
- if (cancelled->mid)
- cifs_tcon_dbg(VFS, "Close unmatched open for MID:%llu\n",
- cancelled->mid);
- else
- cifs_tcon_dbg(VFS, "Close interrupted close\n");
-
- rc = SMB2_close(0, tcon, cancelled->fid.persistent_fid,
- cancelled->fid.volatile_fid);
- if (rc)
- cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc);
-
- cifs_put_tcon(tcon);
- kfree(cancelled);
-}
-
-/*
- * Caller should already has an extra reference to @tcon
- * This function is used to queue work to close a handle to prevent leaks
- * on the server.
- * We handle two cases. If an open was interrupted after we sent the
- * SMB2_CREATE to the server but before we processed the reply, and second
- * if a close was interrupted before we sent the SMB2_CLOSE to the server.
- */
-static int
-__smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid,
- __u64 persistent_fid, __u64 volatile_fid)
-{
- struct close_cancelled_open *cancelled;
-
- cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC);
- if (!cancelled)
- return -ENOMEM;
-
- cancelled->fid.persistent_fid = persistent_fid;
- cancelled->fid.volatile_fid = volatile_fid;
- cancelled->tcon = tcon;
- cancelled->cmd = cmd;
- cancelled->mid = mid;
- INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
- WARN_ON(queue_work(cifsiod_wq, &cancelled->work) == false);
-
- return 0;
-}
-
-int
-smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
- __u64 volatile_fid)
-{
- int rc;
-
- cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
- spin_lock(&cifs_tcp_ses_lock);
- if (tcon->tc_count <= 0) {
- struct TCP_Server_Info *server = NULL;
-
- WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
- spin_unlock(&cifs_tcp_ses_lock);
-
- if (tcon->ses)
- server = tcon->ses->server;
-
- cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n",
- tcon->tid, persistent_fid, volatile_fid);
-
- return 0;
- }
- tcon->tc_count++;
- spin_unlock(&cifs_tcp_ses_lock);
-
- rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
- persistent_fid, volatile_fid);
- if (rc)
- cifs_put_tcon(tcon);
-
- return rc;
-}
-
-int
-smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server)
-{
- struct smb2_hdr *hdr = mid->resp_buf;
- struct smb2_create_rsp *rsp = mid->resp_buf;
- struct cifs_tcon *tcon;
- int rc;
-
- if ((mid->optype & CIFS_CP_CREATE_CLOSE_OP) || hdr->Command != SMB2_CREATE ||
- hdr->Status != STATUS_SUCCESS)
- return 0;
-
- tcon = smb2_find_smb_tcon(server, le64_to_cpu(hdr->SessionId),
- le32_to_cpu(hdr->Id.SyncId.TreeId));
- if (!tcon)
- return -ENOENT;
-
- rc = __smb2_handle_cancelled_cmd(tcon,
- le16_to_cpu(hdr->Command),
- le64_to_cpu(hdr->MessageId),
- rsp->PersistentFileId,
- rsp->VolatileFileId);
- if (rc)
- cifs_put_tcon(tcon);
-
- return rc;
-}
-
-/**
- * smb311_update_preauth_hash - update @ses hash with the packet data in @iov
- *
- * Assumes @iov does not contain the rfc1002 length and iov[0] has the
- * SMB2 header.
- *
- * @ses: server session structure
- * @server: pointer to server info
- * @iov: array containing the SMB request we will send to the server
- * @nvec: number of array entries for the iov
- */
-int
-smb311_update_preauth_hash(struct cifs_ses *ses, struct TCP_Server_Info *server,
- struct kvec *iov, int nvec)
-{
- int i, rc;
- struct smb2_hdr *hdr;
- struct shash_desc *sha512 = NULL;
-
- hdr = (struct smb2_hdr *)iov[0].iov_base;
- /* neg prot are always taken */
- if (hdr->Command == SMB2_NEGOTIATE)
- goto ok;
-
- /*
- * If we process a command which wasn't a negprot it means the
- * neg prot was already done, so the server dialect was set
- * and we can test it. Preauth requires 3.1.1 for now.
- */
- if (server->dialect != SMB311_PROT_ID)
- return 0;
-
- if (hdr->Command != SMB2_SESSION_SETUP)
- return 0;
-
- /* skip last sess setup response */
- if ((hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
- && (hdr->Status == NT_STATUS_OK
- || (hdr->Status !=
- cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))))
- return 0;
-
-ok:
- rc = smb311_crypto_shash_allocate(server);
- if (rc)
- return rc;
-
- sha512 = server->secmech.sha512;
- rc = crypto_shash_init(sha512);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not init sha512 shash\n", __func__);
- return rc;
- }
-
- rc = crypto_shash_update(sha512, ses->preauth_sha_hash,
- SMB2_PREAUTH_HASH_SIZE);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update sha512 shash\n", __func__);
- return rc;
- }
-
- for (i = 0; i < nvec; i++) {
- rc = crypto_shash_update(sha512, iov[i].iov_base, iov[i].iov_len);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update sha512 shash\n",
- __func__);
- return rc;
- }
- }
-
- rc = crypto_shash_final(sha512, ses->preauth_sha_hash);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not finalize sha512 shash\n",
- __func__);
- return rc;
- }
-
- return 0;
-}
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
deleted file mode 100644
index d512440d35b6..000000000000
--- a/fs/cifs/smb2ops.c
+++ /dev/null
@@ -1,5805 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * SMB2 version specific operations
- *
- * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
- */
-
-#include <linux/pagemap.h>
-#include <linux/vfs.h>
-#include <linux/falloc.h>
-#include <linux/scatterlist.h>
-#include <linux/uuid.h>
-#include <linux/sort.h>
-#include <crypto/aead.h>
-#include <linux/fiemap.h>
-#include <uapi/linux/magic.h>
-#include "cifsfs.h"
-#include "cifsglob.h"
-#include "smb2pdu.h"
-#include "smb2proto.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifs_unicode.h"
-#include "smb2status.h"
-#include "smb2glob.h"
-#include "cifs_ioctl.h"
-#include "smbdirect.h"
-#include "fscache.h"
-#include "fs_context.h"
-#include "cached_dir.h"
-
-/* Change credits for different ops and return the total number of credits */
-static int
-change_conf(struct TCP_Server_Info *server)
-{
- server->credits += server->echo_credits + server->oplock_credits;
- server->oplock_credits = server->echo_credits = 0;
- switch (server->credits) {
- case 0:
- return 0;
- case 1:
- server->echoes = false;
- server->oplocks = false;
- break;
- case 2:
- server->echoes = true;
- server->oplocks = false;
- server->echo_credits = 1;
- break;
- default:
- server->echoes = true;
- if (enable_oplocks) {
- server->oplocks = true;
- server->oplock_credits = 1;
- } else
- server->oplocks = false;
-
- server->echo_credits = 1;
- }
- server->credits -= server->echo_credits + server->oplock_credits;
- return server->credits + server->echo_credits + server->oplock_credits;
-}
-
-static void
-smb2_add_credits(struct TCP_Server_Info *server,
- const struct cifs_credits *credits, const int optype)
-{
- int *val, rc = -1;
- int scredits, in_flight;
- unsigned int add = credits->value;
- unsigned int instance = credits->instance;
- bool reconnect_detected = false;
- bool reconnect_with_invalid_credits = false;
-
- spin_lock(&server->req_lock);
- val = server->ops->get_credits_field(server, optype);
-
- /* eg found case where write overlapping reconnect messed up credits */
- if (((optype & CIFS_OP_MASK) == CIFS_NEG_OP) && (*val != 0))
- reconnect_with_invalid_credits = true;
-
- if ((instance == 0) || (instance == server->reconnect_instance))
- *val += add;
- else
- reconnect_detected = true;
-
- if (*val > 65000) {
- *val = 65000; /* Don't get near 64K credits, avoid srv bugs */
- pr_warn_once("server overflowed SMB3 credits\n");
- trace_smb3_overflow_credits(server->CurrentMid,
- server->conn_id, server->hostname, *val,
- add, server->in_flight);
- }
- server->in_flight--;
- if (server->in_flight == 0 &&
- ((optype & CIFS_OP_MASK) != CIFS_NEG_OP) &&
- ((optype & CIFS_OP_MASK) != CIFS_SESS_OP))
- rc = change_conf(server);
- /*
- * Sometimes server returns 0 credits on oplock break ack - we need to
- * rebalance credits in this case.
- */
- else if (server->in_flight > 0 && server->oplock_credits == 0 &&
- server->oplocks) {
- if (server->credits > 1) {
- server->credits--;
- server->oplock_credits++;
- }
- }
- scredits = *val;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
- wake_up(&server->request_q);
-
- if (reconnect_detected) {
- trace_smb3_reconnect_detected(server->CurrentMid,
- server->conn_id, server->hostname, scredits, add, in_flight);
-
- cifs_dbg(FYI, "trying to put %d credits from the old server instance %d\n",
- add, instance);
- }
-
- if (reconnect_with_invalid_credits) {
- trace_smb3_reconnect_with_invalid_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits, add, in_flight);
- cifs_dbg(FYI, "Negotiate operation when server credits is non-zero. Optype: %d, server credits: %d, credits added: %d\n",
- optype, scredits, add);
- }
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsNeedReconnect
- || server->tcpStatus == CifsExiting) {
- spin_unlock(&server->srv_lock);
- return;
- }
- spin_unlock(&server->srv_lock);
-
- switch (rc) {
- case -1:
- /* change_conf hasn't been executed */
- break;
- case 0:
- cifs_server_dbg(VFS, "Possible client or server bug - zero credits\n");
- break;
- case 1:
- cifs_server_dbg(VFS, "disabling echoes and oplocks\n");
- break;
- case 2:
- cifs_dbg(FYI, "disabling oplocks\n");
- break;
- default:
- /* change_conf rebalanced credits for different types */
- break;
- }
-
- trace_smb3_add_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits, add, in_flight);
- cifs_dbg(FYI, "%s: added %u credits total=%d\n", __func__, add, scredits);
-}
-
-static void
-smb2_set_credits(struct TCP_Server_Info *server, const int val)
-{
- int scredits, in_flight;
-
- spin_lock(&server->req_lock);
- server->credits = val;
- if (val == 1)
- server->reconnect_instance++;
- scredits = server->credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
-
- trace_smb3_set_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits, val, in_flight);
- cifs_dbg(FYI, "%s: set %u credits\n", __func__, val);
-
- /* don't log while holding the lock */
- if (val == 1)
- cifs_dbg(FYI, "set credits to 1 due to smb2 reconnect\n");
-}
-
-static int *
-smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
-{
- switch (optype) {
- case CIFS_ECHO_OP:
- return &server->echo_credits;
- case CIFS_OBREAK_OP:
- return &server->oplock_credits;
- default:
- return &server->credits;
- }
-}
-
-static unsigned int
-smb2_get_credits(struct mid_q_entry *mid)
-{
- return mid->credits_received;
-}
-
-static int
-smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
- unsigned int *num, struct cifs_credits *credits)
-{
- int rc = 0;
- unsigned int scredits, in_flight;
-
- spin_lock(&server->req_lock);
- while (1) {
- if (server->credits <= 0) {
- spin_unlock(&server->req_lock);
- cifs_num_waiters_inc(server);
- rc = wait_event_killable(server->request_q,
- has_credits(server, &server->credits, 1));
- cifs_num_waiters_dec(server);
- if (rc)
- return rc;
- spin_lock(&server->req_lock);
- } else {
- spin_unlock(&server->req_lock);
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsExiting) {
- spin_unlock(&server->srv_lock);
- return -ENOENT;
- }
- spin_unlock(&server->srv_lock);
-
- spin_lock(&server->req_lock);
- scredits = server->credits;
- /* can deadlock with reopen */
- if (scredits <= 8) {
- *num = SMB2_MAX_BUFFER_SIZE;
- credits->value = 0;
- credits->instance = 0;
- break;
- }
-
- /* leave some credits for reopen and other ops */
- scredits -= 8;
- *num = min_t(unsigned int, size,
- scredits * SMB2_MAX_BUFFER_SIZE);
-
- credits->value =
- DIV_ROUND_UP(*num, SMB2_MAX_BUFFER_SIZE);
- credits->instance = server->reconnect_instance;
- server->credits -= credits->value;
- server->in_flight++;
- if (server->in_flight > server->max_in_flight)
- server->max_in_flight = server->in_flight;
- break;
- }
- }
- scredits = server->credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
-
- trace_smb3_wait_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits, -(credits->value), in_flight);
- cifs_dbg(FYI, "%s: removed %u credits total=%d\n",
- __func__, credits->value, scredits);
-
- return rc;
-}
-
-static int
-smb2_adjust_credits(struct TCP_Server_Info *server,
- struct cifs_credits *credits,
- const unsigned int payload_size)
-{
- int new_val = DIV_ROUND_UP(payload_size, SMB2_MAX_BUFFER_SIZE);
- int scredits, in_flight;
-
- if (!credits->value || credits->value == new_val)
- return 0;
-
- if (credits->value < new_val) {
- trace_smb3_too_many_credits(server->CurrentMid,
- server->conn_id, server->hostname, 0, credits->value - new_val, 0);
- cifs_server_dbg(VFS, "request has less credits (%d) than required (%d)",
- credits->value, new_val);
-
- return -ENOTSUPP;
- }
-
- spin_lock(&server->req_lock);
-
- if (server->reconnect_instance != credits->instance) {
- scredits = server->credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
-
- trace_smb3_reconnect_detected(server->CurrentMid,
- server->conn_id, server->hostname, scredits,
- credits->value - new_val, in_flight);
- cifs_server_dbg(VFS, "trying to return %d credits to old session\n",
- credits->value - new_val);
- return -EAGAIN;
- }
-
- server->credits += credits->value - new_val;
- scredits = server->credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
- wake_up(&server->request_q);
-
- trace_smb3_adj_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits,
- credits->value - new_val, in_flight);
- cifs_dbg(FYI, "%s: adjust added %u credits total=%d\n",
- __func__, credits->value - new_val, scredits);
-
- credits->value = new_val;
-
- return 0;
-}
-
-static __u64
-smb2_get_next_mid(struct TCP_Server_Info *server)
-{
- __u64 mid;
- /* for SMB2 we need the current value */
- spin_lock(&server->mid_lock);
- mid = server->CurrentMid++;
- spin_unlock(&server->mid_lock);
- return mid;
-}
-
-static void
-smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
-{
- spin_lock(&server->mid_lock);
- if (server->CurrentMid >= val)
- server->CurrentMid -= val;
- spin_unlock(&server->mid_lock);
-}
-
-static struct mid_q_entry *
-__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
-{
- struct mid_q_entry *mid;
- struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
- __u64 wire_mid = le64_to_cpu(shdr->MessageId);
-
- if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
- cifs_server_dbg(VFS, "Encrypted frame parsing not supported yet\n");
- return NULL;
- }
-
- spin_lock(&server->mid_lock);
- list_for_each_entry(mid, &server->pending_mid_q, qhead) {
- if ((mid->mid == wire_mid) &&
- (mid->mid_state == MID_REQUEST_SUBMITTED) &&
- (mid->command == shdr->Command)) {
- kref_get(&mid->refcount);
- if (dequeue) {
- list_del_init(&mid->qhead);
- mid->mid_flags |= MID_DELETED;
- }
- spin_unlock(&server->mid_lock);
- return mid;
- }
- }
- spin_unlock(&server->mid_lock);
- return NULL;
-}
-
-static struct mid_q_entry *
-smb2_find_mid(struct TCP_Server_Info *server, char *buf)
-{
- return __smb2_find_mid(server, buf, false);
-}
-
-static struct mid_q_entry *
-smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf)
-{
- return __smb2_find_mid(server, buf, true);
-}
-
-static void
-smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
-{
-#ifdef CONFIG_CIFS_DEBUG2
- struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
-
- cifs_server_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
- shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
- shdr->Id.SyncId.ProcessId);
- cifs_server_dbg(VFS, "smb buf %p len %u\n", buf,
- server->ops->calc_smb_size(buf));
-#endif
-}
-
-static bool
-smb2_need_neg(struct TCP_Server_Info *server)
-{
- return server->max_read == 0;
-}
-
-static int
-smb2_negotiate(const unsigned int xid,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- int rc;
-
- spin_lock(&server->mid_lock);
- server->CurrentMid = 0;
- spin_unlock(&server->mid_lock);
- rc = SMB2_negotiate(xid, ses, server);
- /* BB we probably don't need to retry with modern servers */
- if (rc == -EAGAIN)
- rc = -EHOSTDOWN;
- return rc;
-}
-
-static unsigned int
-smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
-{
- struct TCP_Server_Info *server = tcon->ses->server;
- unsigned int wsize;
-
- /* start with specified wsize, or default */
- wsize = ctx->wsize ? ctx->wsize : CIFS_DEFAULT_IOSIZE;
- wsize = min_t(unsigned int, wsize, server->max_write);
- if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
- wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
-
- return wsize;
-}
-
-static unsigned int
-smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
-{
- struct TCP_Server_Info *server = tcon->ses->server;
- unsigned int wsize;
-
- /* start with specified wsize, or default */
- wsize = ctx->wsize ? ctx->wsize : SMB3_DEFAULT_IOSIZE;
- wsize = min_t(unsigned int, wsize, server->max_write);
-#ifdef CONFIG_CIFS_SMB_DIRECT
- if (server->rdma) {
- if (server->sign)
- /*
- * Account for SMB2 data transfer packet header and
- * possible encryption header
- */
- wsize = min_t(unsigned int,
- wsize,
- server->smbd_conn->max_fragmented_send_size -
- SMB2_READWRITE_PDU_HEADER_SIZE -
- sizeof(struct smb2_transform_hdr));
- else
- wsize = min_t(unsigned int,
- wsize, server->smbd_conn->max_readwrite_size);
- }
-#endif
- if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
- wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
-
- return wsize;
-}
-
-static unsigned int
-smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
-{
- struct TCP_Server_Info *server = tcon->ses->server;
- unsigned int rsize;
-
- /* start with specified rsize, or default */
- rsize = ctx->rsize ? ctx->rsize : CIFS_DEFAULT_IOSIZE;
- rsize = min_t(unsigned int, rsize, server->max_read);
-
- if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
- rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
-
- return rsize;
-}
-
-static unsigned int
-smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
-{
- struct TCP_Server_Info *server = tcon->ses->server;
- unsigned int rsize;
-
- /* start with specified rsize, or default */
- rsize = ctx->rsize ? ctx->rsize : SMB3_DEFAULT_IOSIZE;
- rsize = min_t(unsigned int, rsize, server->max_read);
-#ifdef CONFIG_CIFS_SMB_DIRECT
- if (server->rdma) {
- if (server->sign)
- /*
- * Account for SMB2 data transfer packet header and
- * possible encryption header
- */
- rsize = min_t(unsigned int,
- rsize,
- server->smbd_conn->max_fragmented_recv_size -
- SMB2_READWRITE_PDU_HEADER_SIZE -
- sizeof(struct smb2_transform_hdr));
- else
- rsize = min_t(unsigned int,
- rsize, server->smbd_conn->max_readwrite_size);
- }
-#endif
-
- if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
- rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
-
- return rsize;
-}
-
-static int
-parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
- size_t buf_len, struct cifs_ses *ses, bool in_mount)
-{
- struct network_interface_info_ioctl_rsp *p;
- struct sockaddr_in *addr4;
- struct sockaddr_in6 *addr6;
- struct iface_info_ipv4 *p4;
- struct iface_info_ipv6 *p6;
- struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL;
- struct cifs_server_iface tmp_iface;
- ssize_t bytes_left;
- size_t next = 0;
- int nb_iface = 0;
- int rc = 0, ret = 0;
-
- bytes_left = buf_len;
- p = buf;
-
- spin_lock(&ses->iface_lock);
- /* do not query too frequently, this time with lock held */
- if (ses->iface_last_update &&
- time_before(jiffies, ses->iface_last_update +
- (SMB_INTERFACE_POLL_INTERVAL * HZ))) {
- spin_unlock(&ses->iface_lock);
- return 0;
- }
-
- /*
- * Go through iface_list and do kref_put to remove
- * any unused ifaces. ifaces in use will be removed
- * when the last user calls a kref_put on it
- */
- list_for_each_entry_safe(iface, niface, &ses->iface_list,
- iface_head) {
- iface->is_active = 0;
- kref_put(&iface->refcount, release_iface);
- ses->iface_count--;
- }
- spin_unlock(&ses->iface_lock);
-
- /*
- * Samba server e.g. can return an empty interface list in some cases,
- * which would only be a problem if we were requesting multichannel
- */
- if (bytes_left == 0) {
- /* avoid spamming logs every 10 minutes, so log only in mount */
- if ((ses->chan_max > 1) && in_mount)
- cifs_dbg(VFS,
- "multichannel not available\n"
- "Empty network interface list returned by server %s\n",
- ses->server->hostname);
- rc = -EINVAL;
- goto out;
- }
-
- while (bytes_left >= sizeof(*p)) {
- memset(&tmp_iface, 0, sizeof(tmp_iface));
- tmp_iface.speed = le64_to_cpu(p->LinkSpeed);
- tmp_iface.rdma_capable = le32_to_cpu(p->Capability & RDMA_CAPABLE) ? 1 : 0;
- tmp_iface.rss_capable = le32_to_cpu(p->Capability & RSS_CAPABLE) ? 1 : 0;
-
- switch (p->Family) {
- /*
- * The kernel and wire socket structures have the same
- * layout and use network byte order but make the
- * conversion explicit in case either one changes.
- */
- case INTERNETWORK:
- addr4 = (struct sockaddr_in *)&tmp_iface.sockaddr;
- p4 = (struct iface_info_ipv4 *)p->Buffer;
- addr4->sin_family = AF_INET;
- memcpy(&addr4->sin_addr, &p4->IPv4Address, 4);
-
- /* [MS-SMB2] 2.2.32.5.1.1 Clients MUST ignore these */
- addr4->sin_port = cpu_to_be16(CIFS_PORT);
-
- cifs_dbg(FYI, "%s: ipv4 %pI4\n", __func__,
- &addr4->sin_addr);
- break;
- case INTERNETWORKV6:
- addr6 = (struct sockaddr_in6 *)&tmp_iface.sockaddr;
- p6 = (struct iface_info_ipv6 *)p->Buffer;
- addr6->sin6_family = AF_INET6;
- memcpy(&addr6->sin6_addr, &p6->IPv6Address, 16);
-
- /* [MS-SMB2] 2.2.32.5.1.2 Clients MUST ignore these */
- addr6->sin6_flowinfo = 0;
- addr6->sin6_scope_id = 0;
- addr6->sin6_port = cpu_to_be16(CIFS_PORT);
-
- cifs_dbg(FYI, "%s: ipv6 %pI6\n", __func__,
- &addr6->sin6_addr);
- break;
- default:
- cifs_dbg(VFS,
- "%s: skipping unsupported socket family\n",
- __func__);
- goto next_iface;
- }
-
- /*
- * The iface_list is assumed to be sorted by speed.
- * Check if the new interface exists in that list.
- * NEVER change iface. it could be in use.
- * Add a new one instead
- */
- spin_lock(&ses->iface_lock);
- iface = niface = NULL;
- list_for_each_entry_safe(iface, niface, &ses->iface_list,
- iface_head) {
- ret = iface_cmp(iface, &tmp_iface);
- if (!ret) {
- /* just get a ref so that it doesn't get picked/freed */
- iface->is_active = 1;
- kref_get(&iface->refcount);
- ses->iface_count++;
- spin_unlock(&ses->iface_lock);
- goto next_iface;
- } else if (ret < 0) {
- /* all remaining ifaces are slower */
- kref_get(&iface->refcount);
- break;
- }
- }
- spin_unlock(&ses->iface_lock);
-
- /* no match. insert the entry in the list */
- info = kmalloc(sizeof(struct cifs_server_iface),
- GFP_KERNEL);
- if (!info) {
- rc = -ENOMEM;
- goto out;
- }
- memcpy(info, &tmp_iface, sizeof(tmp_iface));
-
- /* add this new entry to the list */
- kref_init(&info->refcount);
- info->is_active = 1;
-
- cifs_dbg(FYI, "%s: adding iface %zu\n", __func__, ses->iface_count);
- cifs_dbg(FYI, "%s: speed %zu bps\n", __func__, info->speed);
- cifs_dbg(FYI, "%s: capabilities 0x%08x\n", __func__,
- le32_to_cpu(p->Capability));
-
- spin_lock(&ses->iface_lock);
- if (!list_entry_is_head(iface, &ses->iface_list, iface_head)) {
- list_add_tail(&info->iface_head, &iface->iface_head);
- kref_put(&iface->refcount, release_iface);
- } else
- list_add_tail(&info->iface_head, &ses->iface_list);
-
- ses->iface_count++;
- spin_unlock(&ses->iface_lock);
- ses->iface_last_update = jiffies;
-next_iface:
- nb_iface++;
- next = le32_to_cpu(p->Next);
- if (!next) {
- bytes_left -= sizeof(*p);
- break;
- }
- p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next);
- bytes_left -= next;
- }
-
- if (!nb_iface) {
- cifs_dbg(VFS, "%s: malformed interface info\n", __func__);
- rc = -EINVAL;
- goto out;
- }
-
- /* Azure rounds the buffer size up 8, to a 16 byte boundary */
- if ((bytes_left > 8) || p->Next)
- cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);
-
-
- if (!ses->iface_count) {
- rc = -EINVAL;
- goto out;
- }
-
-out:
- return rc;
-}
-
-int
-SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount)
-{
- int rc;
- unsigned int ret_data_len = 0;
- struct network_interface_info_ioctl_rsp *out_buf = NULL;
- struct cifs_ses *ses = tcon->ses;
-
- /* do not query too frequently */
- if (ses->iface_last_update &&
- time_before(jiffies, ses->iface_last_update +
- (SMB_INTERFACE_POLL_INTERVAL * HZ)))
- return 0;
-
- rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
- FSCTL_QUERY_NETWORK_INTERFACE_INFO,
- NULL /* no data input */, 0 /* no data input */,
- CIFSMaxBufSize, (char **)&out_buf, &ret_data_len);
- if (rc == -EOPNOTSUPP) {
- cifs_dbg(FYI,
- "server does not support query network interfaces\n");
- ret_data_len = 0;
- } else if (rc != 0) {
- cifs_tcon_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
- goto out;
- }
-
- rc = parse_server_interfaces(out_buf, ret_data_len, ses, in_mount);
- if (rc)
- goto out;
-
-out:
- kfree(out_buf);
- return rc;
-}
-
-static void
-smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb)
-{
- int rc;
- __le16 srch_path = 0; /* Null - open root of share */
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
- struct cached_fid *cfid = NULL;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = "",
- .desired_access = FILE_READ_ATTRIBUTES,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, 0),
- .fid = &fid,
- };
-
- rc = open_cached_dir(xid, tcon, "", cifs_sb, false, &cfid);
- if (rc == 0)
- memcpy(&fid, &cfid->fid, sizeof(struct cifs_fid));
- else
- rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
- NULL, NULL);
- if (rc)
- return;
-
- SMB3_request_interfaces(xid, tcon, true /* called during mount */);
-
- SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
- FS_ATTRIBUTE_INFORMATION);
- SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
- FS_DEVICE_INFORMATION);
- SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
- FS_VOLUME_INFORMATION);
- SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
- FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
- if (cfid == NULL)
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
- else
- close_cached_dir(cfid);
-}
-
-static void
-smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb)
-{
- int rc;
- __le16 srch_path = 0; /* Null - open root of share */
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = "",
- .desired_access = FILE_READ_ATTRIBUTES,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, 0),
- .fid = &fid,
- };
-
- rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
- NULL, NULL);
- if (rc)
- return;
-
- SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
- FS_ATTRIBUTE_INFORMATION);
- SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
- FS_DEVICE_INFORMATION);
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
-}
-
-static int
-smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path)
-{
- __le16 *utf16_path;
- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- int err_buftype = CIFS_NO_BUFFER;
- struct cifs_open_parms oparms;
- struct kvec err_iov = {};
- struct cifs_fid fid;
- struct cached_fid *cfid;
- bool islink;
- int rc, rc2;
-
- rc = open_cached_dir(xid, tcon, full_path, cifs_sb, true, &cfid);
- if (!rc) {
- if (cfid->has_lease) {
- close_cached_dir(cfid);
- return 0;
- }
- close_cached_dir(cfid);
- }
-
- utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = full_path,
- .desired_access = FILE_READ_ATTRIBUTES,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, 0),
- .fid = &fid,
- };
-
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
- &err_iov, &err_buftype);
- if (rc) {
- struct smb2_hdr *hdr = err_iov.iov_base;
-
- if (unlikely(!hdr || err_buftype == CIFS_NO_BUFFER))
- goto out;
-
- if (rc != -EREMOTE && hdr->Status == STATUS_OBJECT_NAME_INVALID) {
- rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
- full_path, &islink);
- if (rc2) {
- rc = rc2;
- goto out;
- }
- if (islink)
- rc = -EREMOTE;
- }
- if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb &&
- (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS))
- rc = -EOPNOTSUPP;
- goto out;
- }
-
- rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
-
-out:
- free_rsp_buf(err_buftype, err_iov.iov_base);
- kfree(utf16_path);
- return rc;
-}
-
-static int smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- u64 *uniqueid, struct cifs_open_info_data *data)
-{
- *uniqueid = le64_to_cpu(data->fi.IndexNumber);
- return 0;
-}
-
-static int smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile, struct cifs_open_info_data *data)
-{
- struct cifs_fid *fid = &cfile->fid;
-
- if (cfile->symlink_target) {
- data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
- if (!data->symlink_target)
- return -ENOMEM;
- }
- return SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid, &data->fi);
-}
-
-#ifdef CONFIG_CIFS_XATTR
-static ssize_t
-move_smb2_ea_to_cifs(char *dst, size_t dst_size,
- struct smb2_file_full_ea_info *src, size_t src_size,
- const unsigned char *ea_name)
-{
- int rc = 0;
- unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
- char *name, *value;
- size_t buf_size = dst_size;
- size_t name_len, value_len, user_name_len;
-
- while (src_size > 0) {
- name_len = (size_t)src->ea_name_length;
- value_len = (size_t)le16_to_cpu(src->ea_value_length);
-
- if (name_len == 0)
- break;
-
- if (src_size < 8 + name_len + 1 + value_len) {
- cifs_dbg(FYI, "EA entry goes beyond length of list\n");
- rc = -EIO;
- goto out;
- }
-
- name = &src->ea_data[0];
- value = &src->ea_data[src->ea_name_length + 1];
-
- if (ea_name) {
- if (ea_name_len == name_len &&
- memcmp(ea_name, name, name_len) == 0) {
- rc = value_len;
- if (dst_size == 0)
- goto out;
- if (dst_size < value_len) {
- rc = -ERANGE;
- goto out;
- }
- memcpy(dst, value, value_len);
- goto out;
- }
- } else {
- /* 'user.' plus a terminating null */
- user_name_len = 5 + 1 + name_len;
-
- if (buf_size == 0) {
- /* skip copy - calc size only */
- rc += user_name_len;
- } else if (dst_size >= user_name_len) {
- dst_size -= user_name_len;
- memcpy(dst, "user.", 5);
- dst += 5;
- memcpy(dst, src->ea_data, name_len);
- dst += name_len;
- *dst = 0;
- ++dst;
- rc += user_name_len;
- } else {
- /* stop before overrun buffer */
- rc = -ERANGE;
- break;
- }
- }
-
- if (!src->next_entry_offset)
- break;
-
- if (src_size < le32_to_cpu(src->next_entry_offset)) {
- /* stop before overrun buffer */
- rc = -ERANGE;
- break;
- }
- src_size -= le32_to_cpu(src->next_entry_offset);
- src = (void *)((char *)src +
- le32_to_cpu(src->next_entry_offset));
- }
-
- /* didn't find the named attribute */
- if (ea_name)
- rc = -ENODATA;
-
-out:
- return (ssize_t)rc;
-}
-
-static ssize_t
-smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
- const unsigned char *path, const unsigned char *ea_name,
- char *ea_data, size_t buf_size,
- struct cifs_sb_info *cifs_sb)
-{
- int rc;
- struct kvec rsp_iov = {NULL, 0};
- int buftype = CIFS_NO_BUFFER;
- struct smb2_query_info_rsp *rsp;
- struct smb2_file_full_ea_info *info = NULL;
-
- rc = smb2_query_info_compound(xid, tcon, path,
- FILE_READ_EA,
- FILE_FULL_EA_INFORMATION,
- SMB2_O_INFO_FILE,
- CIFSMaxBufSize -
- MAX_SMB2_CREATE_RESPONSE_SIZE -
- MAX_SMB2_CLOSE_RESPONSE_SIZE,
- &rsp_iov, &buftype, cifs_sb);
- if (rc) {
- /*
- * If ea_name is NULL (listxattr) and there are no EAs,
- * return 0 as it's not an error. Otherwise, the specified
- * ea_name was not found.
- */
- if (!ea_name && rc == -ENODATA)
- rc = 0;
- goto qeas_exit;
- }
-
- rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
- rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
- le32_to_cpu(rsp->OutputBufferLength),
- &rsp_iov,
- sizeof(struct smb2_file_full_ea_info));
- if (rc)
- goto qeas_exit;
-
- info = (struct smb2_file_full_ea_info *)(
- le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
- rc = move_smb2_ea_to_cifs(ea_data, buf_size, info,
- le32_to_cpu(rsp->OutputBufferLength), ea_name);
-
- qeas_exit:
- free_rsp_buf(buftype, rsp_iov.iov_base);
- return rc;
-}
-
-
-static int
-smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
- const char *path, const char *ea_name, const void *ea_value,
- const __u16 ea_value_len, const struct nls_table *nls_codepage,
- struct cifs_sb_info *cifs_sb)
-{
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- __le16 *utf16_path = NULL;
- int ea_name_len = strlen(ea_name);
- int flags = CIFS_CP_CREATE_CLOSE_OP;
- int len;
- struct smb_rqst rqst[3];
- int resp_buftype[3];
- struct kvec rsp_iov[3];
- struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
- struct cifs_open_parms oparms;
- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_fid fid;
- struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
- unsigned int size[1];
- void *data[1];
- struct smb2_file_full_ea_info *ea = NULL;
- struct kvec close_iov[1];
- struct smb2_query_info_rsp *rsp;
- int rc, used_len = 0;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- if (ea_name_len > 255)
- return -EINVAL;
-
- utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
-
- memset(rqst, 0, sizeof(rqst));
- resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
- memset(rsp_iov, 0, sizeof(rsp_iov));
-
- if (ses->server->ops->query_all_EAs) {
- if (!ea_value) {
- rc = ses->server->ops->query_all_EAs(xid, tcon, path,
- ea_name, NULL, 0,
- cifs_sb);
- if (rc == -ENODATA)
- goto sea_exit;
- } else {
- /* If we are adding a attribute we should first check
- * if there will be enough space available to store
- * the new EA. If not we should not add it since we
- * would not be able to even read the EAs back.
- */
- rc = smb2_query_info_compound(xid, tcon, path,
- FILE_READ_EA,
- FILE_FULL_EA_INFORMATION,
- SMB2_O_INFO_FILE,
- CIFSMaxBufSize -
- MAX_SMB2_CREATE_RESPONSE_SIZE -
- MAX_SMB2_CLOSE_RESPONSE_SIZE,
- &rsp_iov[1], &resp_buftype[1], cifs_sb);
- if (rc == 0) {
- rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
- used_len = le32_to_cpu(rsp->OutputBufferLength);
- }
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- resp_buftype[1] = CIFS_NO_BUFFER;
- memset(&rsp_iov[1], 0, sizeof(rsp_iov[1]));
- rc = 0;
-
- /* Use a fudge factor of 256 bytes in case we collide
- * with a different set_EAs command.
- */
- if(CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE -
- MAX_SMB2_CLOSE_RESPONSE_SIZE - 256 <
- used_len + ea_name_len + ea_value_len + 1) {
- rc = -ENOSPC;
- goto sea_exit;
- }
- }
- }
-
- /* Open */
- memset(&open_iov, 0, sizeof(open_iov));
- rqst[0].rq_iov = open_iov;
- rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = path,
- .desired_access = FILE_WRITE_EA,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, 0),
- .fid = &fid,
- };
-
- rc = SMB2_open_init(tcon, server,
- &rqst[0], &oplock, &oparms, utf16_path);
- if (rc)
- goto sea_exit;
- smb2_set_next_command(tcon, &rqst[0]);
-
-
- /* Set Info */
- memset(&si_iov, 0, sizeof(si_iov));
- rqst[1].rq_iov = si_iov;
- rqst[1].rq_nvec = 1;
-
- len = sizeof(*ea) + ea_name_len + ea_value_len + 1;
- ea = kzalloc(len, GFP_KERNEL);
- if (ea == NULL) {
- rc = -ENOMEM;
- goto sea_exit;
- }
-
- ea->ea_name_length = ea_name_len;
- ea->ea_value_length = cpu_to_le16(ea_value_len);
- memcpy(ea->ea_data, ea_name, ea_name_len + 1);
- memcpy(ea->ea_data + ea_name_len + 1, ea_value, ea_value_len);
-
- size[0] = len;
- data[0] = ea;
-
- rc = SMB2_set_info_init(tcon, server,
- &rqst[1], COMPOUND_FID,
- COMPOUND_FID, current->tgid,
- FILE_FULL_EA_INFORMATION,
- SMB2_O_INFO_FILE, 0, data, size);
- if (rc)
- goto sea_exit;
- smb2_set_next_command(tcon, &rqst[1]);
- smb2_set_related(&rqst[1]);
-
-
- /* Close */
- memset(&close_iov, 0, sizeof(close_iov));
- rqst[2].rq_iov = close_iov;
- rqst[2].rq_nvec = 1;
- rc = SMB2_close_init(tcon, server,
- &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
- if (rc)
- goto sea_exit;
- smb2_set_related(&rqst[2]);
-
- rc = compound_send_recv(xid, ses, server,
- flags, 3, rqst,
- resp_buftype, rsp_iov);
- /* no need to bump num_remote_opens because handle immediately closed */
-
- sea_exit:
- kfree(ea);
- kfree(utf16_path);
- SMB2_open_free(&rqst[0]);
- SMB2_set_info_free(&rqst[1]);
- SMB2_close_free(&rqst[2]);
- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
- return rc;
-}
-#endif
-
-static bool
-smb2_can_echo(struct TCP_Server_Info *server)
-{
- return server->echoes;
-}
-
-static void
-smb2_clear_stats(struct cifs_tcon *tcon)
-{
- int i;
-
- for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
- atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0);
- atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0);
- }
-}
-
-static void
-smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon)
-{
- seq_puts(m, "\n\tShare Capabilities:");
- if (tcon->capabilities & SMB2_SHARE_CAP_DFS)
- seq_puts(m, " DFS,");
- if (tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
- seq_puts(m, " CONTINUOUS AVAILABILITY,");
- if (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT)
- seq_puts(m, " SCALEOUT,");
- if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER)
- seq_puts(m, " CLUSTER,");
- if (tcon->capabilities & SMB2_SHARE_CAP_ASYMMETRIC)
- seq_puts(m, " ASYMMETRIC,");
- if (tcon->capabilities == 0)
- seq_puts(m, " None");
- if (tcon->ss_flags & SSINFO_FLAGS_ALIGNED_DEVICE)
- seq_puts(m, " Aligned,");
- if (tcon->ss_flags & SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE)
- seq_puts(m, " Partition Aligned,");
- if (tcon->ss_flags & SSINFO_FLAGS_NO_SEEK_PENALTY)
- seq_puts(m, " SSD,");
- if (tcon->ss_flags & SSINFO_FLAGS_TRIM_ENABLED)
- seq_puts(m, " TRIM-support,");
-
- seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags);
- seq_printf(m, "\n\ttid: 0x%x", tcon->tid);
- if (tcon->perf_sector_size)
- seq_printf(m, "\tOptimal sector size: 0x%x",
- tcon->perf_sector_size);
- seq_printf(m, "\tMaximal Access: 0x%x", tcon->maximal_access);
-}
-
-static void
-smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
-{
- atomic_t *sent = tcon->stats.smb2_stats.smb2_com_sent;
- atomic_t *failed = tcon->stats.smb2_stats.smb2_com_failed;
-
- /*
- * Can't display SMB2_NEGOTIATE, SESSION_SETUP, LOGOFF, CANCEL and ECHO
- * totals (requests sent) since those SMBs are per-session not per tcon
- */
- seq_printf(m, "\nBytes read: %llu Bytes written: %llu",
- (long long)(tcon->bytes_read),
- (long long)(tcon->bytes_written));
- seq_printf(m, "\nOpen files: %d total (local), %d open on server",
- atomic_read(&tcon->num_local_opens),
- atomic_read(&tcon->num_remote_opens));
- seq_printf(m, "\nTreeConnects: %d total %d failed",
- atomic_read(&sent[SMB2_TREE_CONNECT_HE]),
- atomic_read(&failed[SMB2_TREE_CONNECT_HE]));
- seq_printf(m, "\nTreeDisconnects: %d total %d failed",
- atomic_read(&sent[SMB2_TREE_DISCONNECT_HE]),
- atomic_read(&failed[SMB2_TREE_DISCONNECT_HE]));
- seq_printf(m, "\nCreates: %d total %d failed",
- atomic_read(&sent[SMB2_CREATE_HE]),
- atomic_read(&failed[SMB2_CREATE_HE]));
- seq_printf(m, "\nCloses: %d total %d failed",
- atomic_read(&sent[SMB2_CLOSE_HE]),
- atomic_read(&failed[SMB2_CLOSE_HE]));
- seq_printf(m, "\nFlushes: %d total %d failed",
- atomic_read(&sent[SMB2_FLUSH_HE]),
- atomic_read(&failed[SMB2_FLUSH_HE]));
- seq_printf(m, "\nReads: %d total %d failed",
- atomic_read(&sent[SMB2_READ_HE]),
- atomic_read(&failed[SMB2_READ_HE]));
- seq_printf(m, "\nWrites: %d total %d failed",
- atomic_read(&sent[SMB2_WRITE_HE]),
- atomic_read(&failed[SMB2_WRITE_HE]));
- seq_printf(m, "\nLocks: %d total %d failed",
- atomic_read(&sent[SMB2_LOCK_HE]),
- atomic_read(&failed[SMB2_LOCK_HE]));
- seq_printf(m, "\nIOCTLs: %d total %d failed",
- atomic_read(&sent[SMB2_IOCTL_HE]),
- atomic_read(&failed[SMB2_IOCTL_HE]));
- seq_printf(m, "\nQueryDirectories: %d total %d failed",
- atomic_read(&sent[SMB2_QUERY_DIRECTORY_HE]),
- atomic_read(&failed[SMB2_QUERY_DIRECTORY_HE]));
- seq_printf(m, "\nChangeNotifies: %d total %d failed",
- atomic_read(&sent[SMB2_CHANGE_NOTIFY_HE]),
- atomic_read(&failed[SMB2_CHANGE_NOTIFY_HE]));
- seq_printf(m, "\nQueryInfos: %d total %d failed",
- atomic_read(&sent[SMB2_QUERY_INFO_HE]),
- atomic_read(&failed[SMB2_QUERY_INFO_HE]));
- seq_printf(m, "\nSetInfos: %d total %d failed",
- atomic_read(&sent[SMB2_SET_INFO_HE]),
- atomic_read(&failed[SMB2_SET_INFO_HE]));
- seq_printf(m, "\nOplockBreaks: %d sent %d failed",
- atomic_read(&sent[SMB2_OPLOCK_BREAK_HE]),
- atomic_read(&failed[SMB2_OPLOCK_BREAK_HE]));
-}
-
-static void
-smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
-{
- struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
- struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
-
- cfile->fid.persistent_fid = fid->persistent_fid;
- cfile->fid.volatile_fid = fid->volatile_fid;
- cfile->fid.access = fid->access;
-#ifdef CONFIG_CIFS_DEBUG2
- cfile->fid.mid = fid->mid;
-#endif /* CIFS_DEBUG2 */
- server->ops->set_oplock_level(cinode, oplock, fid->epoch,
- &fid->purge_cache);
- cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
- memcpy(cfile->fid.create_guid, fid->create_guid, 16);
-}
-
-static void
-smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_fid *fid)
-{
- SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
-}
-
-static void
-smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile)
-{
- struct smb2_file_network_open_info file_inf;
- struct inode *inode;
- int rc;
-
- rc = __SMB2_close(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, &file_inf);
- if (rc)
- return;
-
- inode = d_inode(cfile->dentry);
-
- spin_lock(&inode->i_lock);
- CIFS_I(inode)->time = jiffies;
-
- /* Creation time should not need to be updated on close */
- if (file_inf.LastWriteTime)
- inode->i_mtime = cifs_NTtimeToUnix(file_inf.LastWriteTime);
- if (file_inf.ChangeTime)
- inode->i_ctime = cifs_NTtimeToUnix(file_inf.ChangeTime);
- if (file_inf.LastAccessTime)
- inode->i_atime = cifs_NTtimeToUnix(file_inf.LastAccessTime);
-
- /*
- * i_blocks is not related to (i_size / i_blksize),
- * but instead 512 byte (2**9) size is required for
- * calculating num blocks.
- */
- if (le64_to_cpu(file_inf.AllocationSize) > 4096)
- inode->i_blocks =
- (512 - 1 + le64_to_cpu(file_inf.AllocationSize)) >> 9;
-
- /* End of file and Attributes should not have to be updated on close */
- spin_unlock(&inode->i_lock);
-}
-
-static int
-SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- struct copychunk_ioctl *pcchunk)
-{
- int rc;
- unsigned int ret_data_len;
- struct resume_key_req *res_key;
-
- rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
- FSCTL_SRV_REQUEST_RESUME_KEY, NULL, 0 /* no input */,
- CIFSMaxBufSize, (char **)&res_key, &ret_data_len);
-
- if (rc == -EOPNOTSUPP) {
- pr_warn_once("Server share %s does not support copy range\n", tcon->tree_name);
- goto req_res_key_exit;
- } else if (rc) {
- cifs_tcon_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc);
- goto req_res_key_exit;
- }
- if (ret_data_len < sizeof(struct resume_key_req)) {
- cifs_tcon_dbg(VFS, "Invalid refcopy resume key length\n");
- rc = -EINVAL;
- goto req_res_key_exit;
- }
- memcpy(pcchunk->SourceKey, res_key->ResumeKey, COPY_CHUNK_RES_KEY_SIZE);
-
-req_res_key_exit:
- kfree(res_key);
- return rc;
-}
-
-struct iqi_vars {
- struct smb_rqst rqst[3];
- struct kvec rsp_iov[3];
- struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
- struct kvec qi_iov[1];
- struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
- struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
- struct kvec close_iov[1];
-};
-
-static int
-smb2_ioctl_query_info(const unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- __le16 *path, int is_dir,
- unsigned long p)
-{
- struct iqi_vars *vars;
- struct smb_rqst *rqst;
- struct kvec *rsp_iov;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- char __user *arg = (char __user *)p;
- struct smb_query_info qi;
- struct smb_query_info __user *pqi;
- int rc = 0;
- int flags = CIFS_CP_CREATE_CLOSE_OP;
- struct smb2_query_info_rsp *qi_rsp = NULL;
- struct smb2_ioctl_rsp *io_rsp = NULL;
- void *buffer = NULL;
- int resp_buftype[3];
- struct cifs_open_parms oparms;
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_fid fid;
- unsigned int size[2];
- void *data[2];
- int create_options = is_dir ? CREATE_NOT_FILE : CREATE_NOT_DIR;
- void (*free_req1_func)(struct smb_rqst *r);
-
- vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
- if (vars == NULL)
- return -ENOMEM;
- rqst = &vars->rqst[0];
- rsp_iov = &vars->rsp_iov[0];
-
- resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
-
- if (copy_from_user(&qi, arg, sizeof(struct smb_query_info))) {
- rc = -EFAULT;
- goto free_vars;
- }
- if (qi.output_buffer_length > 1024) {
- rc = -EINVAL;
- goto free_vars;
- }
-
- if (!ses || !server) {
- rc = -EIO;
- goto free_vars;
- }
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- if (qi.output_buffer_length) {
- buffer = memdup_user(arg + sizeof(struct smb_query_info), qi.output_buffer_length);
- if (IS_ERR(buffer)) {
- rc = PTR_ERR(buffer);
- goto free_vars;
- }
- }
-
- /* Open */
- rqst[0].rq_iov = &vars->open_iov[0];
- rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, create_options),
- .fid = &fid,
- };
-
- if (qi.flags & PASSTHRU_FSCTL) {
- switch (qi.info_type & FSCTL_DEVICE_ACCESS_MASK) {
- case FSCTL_DEVICE_ACCESS_FILE_READ_WRITE_ACCESS:
- oparms.desired_access = FILE_READ_DATA | FILE_WRITE_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE;
- break;
- case FSCTL_DEVICE_ACCESS_FILE_ANY_ACCESS:
- oparms.desired_access = GENERIC_ALL;
- break;
- case FSCTL_DEVICE_ACCESS_FILE_READ_ACCESS:
- oparms.desired_access = GENERIC_READ;
- break;
- case FSCTL_DEVICE_ACCESS_FILE_WRITE_ACCESS:
- oparms.desired_access = GENERIC_WRITE;
- break;
- }
- } else if (qi.flags & PASSTHRU_SET_INFO) {
- oparms.desired_access = GENERIC_WRITE;
- } else {
- oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL;
- }
-
- rc = SMB2_open_init(tcon, server,
- &rqst[0], &oplock, &oparms, path);
- if (rc)
- goto free_output_buffer;
- smb2_set_next_command(tcon, &rqst[0]);
-
- /* Query */
- if (qi.flags & PASSTHRU_FSCTL) {
- /* Can eventually relax perm check since server enforces too */
- if (!capable(CAP_SYS_ADMIN)) {
- rc = -EPERM;
- goto free_open_req;
- }
- rqst[1].rq_iov = &vars->io_iov[0];
- rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
-
- rc = SMB2_ioctl_init(tcon, server, &rqst[1], COMPOUND_FID, COMPOUND_FID,
- qi.info_type, buffer, qi.output_buffer_length,
- CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE -
- MAX_SMB2_CLOSE_RESPONSE_SIZE);
- free_req1_func = SMB2_ioctl_free;
- } else if (qi.flags == PASSTHRU_SET_INFO) {
- /* Can eventually relax perm check since server enforces too */
- if (!capable(CAP_SYS_ADMIN)) {
- rc = -EPERM;
- goto free_open_req;
- }
- if (qi.output_buffer_length < 8) {
- rc = -EINVAL;
- goto free_open_req;
- }
- rqst[1].rq_iov = &vars->si_iov[0];
- rqst[1].rq_nvec = 1;
-
- /* MS-FSCC 2.4.13 FileEndOfFileInformation */
- size[0] = 8;
- data[0] = buffer;
-
- rc = SMB2_set_info_init(tcon, server, &rqst[1], COMPOUND_FID, COMPOUND_FID,
- current->tgid, FILE_END_OF_FILE_INFORMATION,
- SMB2_O_INFO_FILE, 0, data, size);
- free_req1_func = SMB2_set_info_free;
- } else if (qi.flags == PASSTHRU_QUERY_INFO) {
- rqst[1].rq_iov = &vars->qi_iov[0];
- rqst[1].rq_nvec = 1;
-
- rc = SMB2_query_info_init(tcon, server,
- &rqst[1], COMPOUND_FID,
- COMPOUND_FID, qi.file_info_class,
- qi.info_type, qi.additional_information,
- qi.input_buffer_length,
- qi.output_buffer_length, buffer);
- free_req1_func = SMB2_query_info_free;
- } else { /* unknown flags */
- cifs_tcon_dbg(VFS, "Invalid passthru query flags: 0x%x\n",
- qi.flags);
- rc = -EINVAL;
- }
-
- if (rc)
- goto free_open_req;
- smb2_set_next_command(tcon, &rqst[1]);
- smb2_set_related(&rqst[1]);
-
- /* Close */
- rqst[2].rq_iov = &vars->close_iov[0];
- rqst[2].rq_nvec = 1;
-
- rc = SMB2_close_init(tcon, server,
- &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
- if (rc)
- goto free_req_1;
- smb2_set_related(&rqst[2]);
-
- rc = compound_send_recv(xid, ses, server,
- flags, 3, rqst,
- resp_buftype, rsp_iov);
- if (rc)
- goto out;
-
- /* No need to bump num_remote_opens since handle immediately closed */
- if (qi.flags & PASSTHRU_FSCTL) {
- pqi = (struct smb_query_info __user *)arg;
- io_rsp = (struct smb2_ioctl_rsp *)rsp_iov[1].iov_base;
- if (le32_to_cpu(io_rsp->OutputCount) < qi.input_buffer_length)
- qi.input_buffer_length = le32_to_cpu(io_rsp->OutputCount);
- if (qi.input_buffer_length > 0 &&
- le32_to_cpu(io_rsp->OutputOffset) + qi.input_buffer_length
- > rsp_iov[1].iov_len) {
- rc = -EFAULT;
- goto out;
- }
-
- if (copy_to_user(&pqi->input_buffer_length,
- &qi.input_buffer_length,
- sizeof(qi.input_buffer_length))) {
- rc = -EFAULT;
- goto out;
- }
-
- if (copy_to_user((void __user *)pqi + sizeof(struct smb_query_info),
- (const void *)io_rsp + le32_to_cpu(io_rsp->OutputOffset),
- qi.input_buffer_length))
- rc = -EFAULT;
- } else {
- pqi = (struct smb_query_info __user *)arg;
- qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
- if (le32_to_cpu(qi_rsp->OutputBufferLength) < qi.input_buffer_length)
- qi.input_buffer_length = le32_to_cpu(qi_rsp->OutputBufferLength);
- if (copy_to_user(&pqi->input_buffer_length,
- &qi.input_buffer_length,
- sizeof(qi.input_buffer_length))) {
- rc = -EFAULT;
- goto out;
- }
-
- if (copy_to_user(pqi + 1, qi_rsp->Buffer,
- qi.input_buffer_length))
- rc = -EFAULT;
- }
-
-out:
- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
- SMB2_close_free(&rqst[2]);
-free_req_1:
- free_req1_func(&rqst[1]);
-free_open_req:
- SMB2_open_free(&rqst[0]);
-free_output_buffer:
- kfree(buffer);
-free_vars:
- kfree(vars);
- return rc;
-}
-
-static ssize_t
-smb2_copychunk_range(const unsigned int xid,
- struct cifsFileInfo *srcfile,
- struct cifsFileInfo *trgtfile, u64 src_off,
- u64 len, u64 dest_off)
-{
- int rc;
- unsigned int ret_data_len;
- struct copychunk_ioctl *pcchunk;
- struct copychunk_ioctl_rsp *retbuf = NULL;
- struct cifs_tcon *tcon;
- int chunks_copied = 0;
- bool chunk_sizes_updated = false;
- ssize_t bytes_written, total_bytes_written = 0;
-
- pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);
- if (pcchunk == NULL)
- return -ENOMEM;
-
- cifs_dbg(FYI, "%s: about to call request res key\n", __func__);
- /* Request a key from the server to identify the source of the copy */
- rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink),
- srcfile->fid.persistent_fid,
- srcfile->fid.volatile_fid, pcchunk);
-
- /* Note: request_res_key sets res_key null only if rc !=0 */
- if (rc)
- goto cchunk_out;
-
- /* For now array only one chunk long, will make more flexible later */
- pcchunk->ChunkCount = cpu_to_le32(1);
- pcchunk->Reserved = 0;
- pcchunk->Reserved2 = 0;
-
- tcon = tlink_tcon(trgtfile->tlink);
-
- while (len > 0) {
- pcchunk->SourceOffset = cpu_to_le64(src_off);
- pcchunk->TargetOffset = cpu_to_le64(dest_off);
- pcchunk->Length =
- cpu_to_le32(min_t(u64, len, tcon->max_bytes_chunk));
-
- /* Request server copy to target from src identified by key */
- kfree(retbuf);
- retbuf = NULL;
- rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
- trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
- (char *)pcchunk, sizeof(struct copychunk_ioctl),
- CIFSMaxBufSize, (char **)&retbuf, &ret_data_len);
- if (rc == 0) {
- if (ret_data_len !=
- sizeof(struct copychunk_ioctl_rsp)) {
- cifs_tcon_dbg(VFS, "Invalid cchunk response size\n");
- rc = -EIO;
- goto cchunk_out;
- }
- if (retbuf->TotalBytesWritten == 0) {
- cifs_dbg(FYI, "no bytes copied\n");
- rc = -EIO;
- goto cchunk_out;
- }
- /*
- * Check if server claimed to write more than we asked
- */
- if (le32_to_cpu(retbuf->TotalBytesWritten) >
- le32_to_cpu(pcchunk->Length)) {
- cifs_tcon_dbg(VFS, "Invalid copy chunk response\n");
- rc = -EIO;
- goto cchunk_out;
- }
- if (le32_to_cpu(retbuf->ChunksWritten) != 1) {
- cifs_tcon_dbg(VFS, "Invalid num chunks written\n");
- rc = -EIO;
- goto cchunk_out;
- }
- chunks_copied++;
-
- bytes_written = le32_to_cpu(retbuf->TotalBytesWritten);
- src_off += bytes_written;
- dest_off += bytes_written;
- len -= bytes_written;
- total_bytes_written += bytes_written;
-
- cifs_dbg(FYI, "Chunks %d PartialChunk %d Total %zu\n",
- le32_to_cpu(retbuf->ChunksWritten),
- le32_to_cpu(retbuf->ChunkBytesWritten),
- bytes_written);
- } else if (rc == -EINVAL) {
- if (ret_data_len != sizeof(struct copychunk_ioctl_rsp))
- goto cchunk_out;
-
- cifs_dbg(FYI, "MaxChunks %d BytesChunk %d MaxCopy %d\n",
- le32_to_cpu(retbuf->ChunksWritten),
- le32_to_cpu(retbuf->ChunkBytesWritten),
- le32_to_cpu(retbuf->TotalBytesWritten));
-
- /*
- * Check if this is the first request using these sizes,
- * (ie check if copy succeed once with original sizes
- * and check if the server gave us different sizes after
- * we already updated max sizes on previous request).
- * if not then why is the server returning an error now
- */
- if ((chunks_copied != 0) || chunk_sizes_updated)
- goto cchunk_out;
-
- /* Check that server is not asking us to grow size */
- if (le32_to_cpu(retbuf->ChunkBytesWritten) <
- tcon->max_bytes_chunk)
- tcon->max_bytes_chunk =
- le32_to_cpu(retbuf->ChunkBytesWritten);
- else
- goto cchunk_out; /* server gave us bogus size */
-
- /* No need to change MaxChunks since already set to 1 */
- chunk_sizes_updated = true;
- } else
- goto cchunk_out;
- }
-
-cchunk_out:
- kfree(pcchunk);
- kfree(retbuf);
- if (rc)
- return rc;
- else
- return total_bytes_written;
-}
-
-static int
-smb2_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_fid *fid)
-{
- return SMB2_flush(xid, tcon, fid->persistent_fid, fid->volatile_fid);
-}
-
-static unsigned int
-smb2_read_data_offset(char *buf)
-{
- struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
-
- return rsp->DataOffset;
-}
-
-static unsigned int
-smb2_read_data_length(char *buf, bool in_remaining)
-{
- struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
-
- if (in_remaining)
- return le32_to_cpu(rsp->DataRemaining);
-
- return le32_to_cpu(rsp->DataLength);
-}
-
-
-static int
-smb2_sync_read(const unsigned int xid, struct cifs_fid *pfid,
- struct cifs_io_parms *parms, unsigned int *bytes_read,
- char **buf, int *buf_type)
-{
- parms->persistent_fid = pfid->persistent_fid;
- parms->volatile_fid = pfid->volatile_fid;
- return SMB2_read(xid, parms, bytes_read, buf, buf_type);
-}
-
-static int
-smb2_sync_write(const unsigned int xid, struct cifs_fid *pfid,
- struct cifs_io_parms *parms, unsigned int *written,
- struct kvec *iov, unsigned long nr_segs)
-{
-
- parms->persistent_fid = pfid->persistent_fid;
- parms->volatile_fid = pfid->volatile_fid;
- return SMB2_write(xid, parms, written, iov, nr_segs);
-}
-
-/* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */
-static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse)
-{
- struct cifsInodeInfo *cifsi;
- int rc;
-
- cifsi = CIFS_I(inode);
-
- /* if file already sparse don't bother setting sparse again */
- if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && setsparse)
- return true; /* already sparse */
-
- if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && !setsparse)
- return true; /* already not sparse */
-
- /*
- * Can't check for sparse support on share the usual way via the
- * FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share
- * since Samba server doesn't set the flag on the share, yet
- * supports the set sparse FSCTL and returns sparse correctly
- * in the file attributes. If we fail setting sparse though we
- * mark that server does not support sparse files for this share
- * to avoid repeatedly sending the unsupported fsctl to server
- * if the file is repeatedly extended.
- */
- if (tcon->broken_sparse_sup)
- return false;
-
- rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
- &setsparse, 1, CIFSMaxBufSize, NULL, NULL);
- if (rc) {
- tcon->broken_sparse_sup = true;
- cifs_dbg(FYI, "set sparse rc = %d\n", rc);
- return false;
- }
-
- if (setsparse)
- cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE;
- else
- cifsi->cifsAttrs &= (~FILE_ATTRIBUTE_SPARSE_FILE);
-
- return true;
-}
-
-static int
-smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile, __u64 size, bool set_alloc)
-{
- __le64 eof = cpu_to_le64(size);
- struct inode *inode;
-
- /*
- * If extending file more than one page make sparse. Many Linux fs
- * make files sparse by default when extending via ftruncate
- */
- inode = d_inode(cfile->dentry);
-
- if (!set_alloc && (size > inode->i_size + 8192)) {
- __u8 set_sparse = 1;
-
- /* whether set sparse succeeds or not, extend the file */
- smb2_set_sparse(xid, tcon, cfile, inode, set_sparse);
- }
-
- return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, cfile->pid, &eof);
-}
-
-static int
-smb2_duplicate_extents(const unsigned int xid,
- struct cifsFileInfo *srcfile,
- struct cifsFileInfo *trgtfile, u64 src_off,
- u64 len, u64 dest_off)
-{
- int rc;
- unsigned int ret_data_len;
- struct inode *inode;
- struct duplicate_extents_to_file dup_ext_buf;
- struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
-
- /* server fileays advertise duplicate extent support with this flag */
- if ((le32_to_cpu(tcon->fsAttrInfo.Attributes) &
- FILE_SUPPORTS_BLOCK_REFCOUNTING) == 0)
- return -EOPNOTSUPP;
-
- dup_ext_buf.VolatileFileHandle = srcfile->fid.volatile_fid;
- dup_ext_buf.PersistentFileHandle = srcfile->fid.persistent_fid;
- dup_ext_buf.SourceFileOffset = cpu_to_le64(src_off);
- dup_ext_buf.TargetFileOffset = cpu_to_le64(dest_off);
- dup_ext_buf.ByteCount = cpu_to_le64(len);
- cifs_dbg(FYI, "Duplicate extents: src off %lld dst off %lld len %lld\n",
- src_off, dest_off, len);
-
- inode = d_inode(trgtfile->dentry);
- if (inode->i_size < dest_off + len) {
- rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
- if (rc)
- goto duplicate_extents_out;
-
- /*
- * Although also could set plausible allocation size (i_blocks)
- * here in addition to setting the file size, in reflink
- * it is likely that the target file is sparse. Its allocation
- * size will be queried on next revalidate, but it is important
- * to make sure that file's cached size is updated immediately
- */
- cifs_setsize(inode, dest_off + len);
- }
- rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
- trgtfile->fid.volatile_fid,
- FSCTL_DUPLICATE_EXTENTS_TO_FILE,
- (char *)&dup_ext_buf,
- sizeof(struct duplicate_extents_to_file),
- CIFSMaxBufSize, NULL,
- &ret_data_len);
-
- if (ret_data_len > 0)
- cifs_dbg(FYI, "Non-zero response length in duplicate extents\n");
-
-duplicate_extents_out:
- return rc;
-}
-
-static int
-smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile)
-{
- return SMB2_set_compression(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid);
-}
-
-static int
-smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile)
-{
- struct fsctl_set_integrity_information_req integr_info;
- unsigned int ret_data_len;
-
- integr_info.ChecksumAlgorithm = cpu_to_le16(CHECKSUM_TYPE_UNCHANGED);
- integr_info.Flags = 0;
- integr_info.Reserved = 0;
-
- return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- FSCTL_SET_INTEGRITY_INFORMATION,
- (char *)&integr_info,
- sizeof(struct fsctl_set_integrity_information_req),
- CIFSMaxBufSize, NULL,
- &ret_data_len);
-
-}
-
-/* GMT Token is @GMT-YYYY.MM.DD-HH.MM.SS Unicode which is 48 bytes + null */
-#define GMT_TOKEN_SIZE 50
-
-#define MIN_SNAPSHOT_ARRAY_SIZE 16 /* See MS-SMB2 section 3.3.5.15.1 */
-
-/*
- * Input buffer contains (empty) struct smb_snapshot array with size filled in
- * For output see struct SRV_SNAPSHOT_ARRAY in MS-SMB2 section 2.2.32.2
- */
-static int
-smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile, void __user *ioc_buf)
-{
- char *retbuf = NULL;
- unsigned int ret_data_len = 0;
- int rc;
- u32 max_response_size;
- struct smb_snapshot_array snapshot_in;
-
- /*
- * On the first query to enumerate the list of snapshots available
- * for this volume the buffer begins with 0 (number of snapshots
- * which can be returned is zero since at that point we do not know
- * how big the buffer needs to be). On the second query,
- * it (ret_data_len) is set to number of snapshots so we can
- * know to set the maximum response size larger (see below).
- */
- if (get_user(ret_data_len, (unsigned int __user *)ioc_buf))
- return -EFAULT;
-
- /*
- * Note that for snapshot queries that servers like Azure expect that
- * the first query be minimal size (and just used to get the number/size
- * of previous versions) so response size must be specified as EXACTLY
- * sizeof(struct snapshot_array) which is 16 when rounded up to multiple
- * of eight bytes.
- */
- if (ret_data_len == 0)
- max_response_size = MIN_SNAPSHOT_ARRAY_SIZE;
- else
- max_response_size = CIFSMaxBufSize;
-
- rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- FSCTL_SRV_ENUMERATE_SNAPSHOTS,
- NULL, 0 /* no input data */, max_response_size,
- (char **)&retbuf,
- &ret_data_len);
- cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
- rc, ret_data_len);
- if (rc)
- return rc;
-
- if (ret_data_len && (ioc_buf != NULL) && (retbuf != NULL)) {
- /* Fixup buffer */
- if (copy_from_user(&snapshot_in, ioc_buf,
- sizeof(struct smb_snapshot_array))) {
- rc = -EFAULT;
- kfree(retbuf);
- return rc;
- }
-
- /*
- * Check for min size, ie not large enough to fit even one GMT
- * token (snapshot). On the first ioctl some users may pass in
- * smaller size (or zero) to simply get the size of the array
- * so the user space caller can allocate sufficient memory
- * and retry the ioctl again with larger array size sufficient
- * to hold all of the snapshot GMT tokens on the second try.
- */
- if (snapshot_in.snapshot_array_size < GMT_TOKEN_SIZE)
- ret_data_len = sizeof(struct smb_snapshot_array);
-
- /*
- * We return struct SRV_SNAPSHOT_ARRAY, followed by
- * the snapshot array (of 50 byte GMT tokens) each
- * representing an available previous version of the data
- */
- if (ret_data_len > (snapshot_in.snapshot_array_size +
- sizeof(struct smb_snapshot_array)))
- ret_data_len = snapshot_in.snapshot_array_size +
- sizeof(struct smb_snapshot_array);
-
- if (copy_to_user(ioc_buf, retbuf, ret_data_len))
- rc = -EFAULT;
- }
-
- kfree(retbuf);
- return rc;
-}
-
-
-
-static int
-smb3_notify(const unsigned int xid, struct file *pfile,
- void __user *ioc_buf, bool return_changes)
-{
- struct smb3_notify_info notify;
- struct smb3_notify_info __user *pnotify_buf;
- struct dentry *dentry = pfile->f_path.dentry;
- struct inode *inode = file_inode(pfile);
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
- struct cifs_tcon *tcon;
- const unsigned char *path;
- char *returned_ioctl_info = NULL;
- void *page = alloc_dentry_path();
- __le16 *utf16_path = NULL;
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- int rc = 0;
- __u32 ret_len = 0;
-
- path = build_path_from_dentry(dentry, page);
- if (IS_ERR(path)) {
- rc = PTR_ERR(path);
- goto notify_exit;
- }
-
- utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
- if (utf16_path == NULL) {
- rc = -ENOMEM;
- goto notify_exit;
- }
-
- if (return_changes) {
- if (copy_from_user(¬ify, ioc_buf, sizeof(struct smb3_notify_info))) {
- rc = -EFAULT;
- goto notify_exit;
- }
- } else {
- if (copy_from_user(¬ify, ioc_buf, sizeof(struct smb3_notify))) {
- rc = -EFAULT;
- goto notify_exit;
- }
- notify.data_len = 0;
- }
-
- tcon = cifs_sb_master_tcon(cifs_sb);
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = path,
- .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, 0),
- .fid = &fid,
- };
-
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL,
- NULL);
- if (rc)
- goto notify_exit;
-
- rc = SMB2_change_notify(xid, tcon, fid.persistent_fid, fid.volatile_fid,
- notify.watch_tree, notify.completion_filter,
- notify.data_len, &returned_ioctl_info, &ret_len);
-
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
-
- cifs_dbg(FYI, "change notify for path %s rc %d\n", path, rc);
- if (return_changes && (ret_len > 0) && (notify.data_len > 0)) {
- if (ret_len > notify.data_len)
- ret_len = notify.data_len;
- pnotify_buf = (struct smb3_notify_info __user *)ioc_buf;
- if (copy_to_user(pnotify_buf->notify_data, returned_ioctl_info, ret_len))
- rc = -EFAULT;
- else if (copy_to_user(&pnotify_buf->data_len, &ret_len, sizeof(ret_len)))
- rc = -EFAULT;
- }
- kfree(returned_ioctl_info);
-notify_exit:
- free_dentry_path(page);
- kfree(utf16_path);
- return rc;
-}
-
-static int
-smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
- const char *path, struct cifs_sb_info *cifs_sb,
- struct cifs_fid *fid, __u16 search_flags,
- struct cifs_search_info *srch_inf)
-{
- __le16 *utf16_path;
- struct smb_rqst rqst[2];
- struct kvec rsp_iov[2];
- int resp_buftype[2];
- struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
- struct kvec qd_iov[SMB2_QUERY_DIRECTORY_IOV_SIZE];
- int rc, flags = 0;
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct smb2_query_directory_rsp *qd_rsp = NULL;
- struct smb2_create_rsp *op_rsp = NULL;
- struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
- int retry_count = 0;
-
- utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(rqst, 0, sizeof(rqst));
- resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER;
- memset(rsp_iov, 0, sizeof(rsp_iov));
-
- /* Open */
- memset(&open_iov, 0, sizeof(open_iov));
- rqst[0].rq_iov = open_iov;
- rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = path,
- .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, 0),
- .fid = fid,
- };
-
- rc = SMB2_open_init(tcon, server,
- &rqst[0], &oplock, &oparms, utf16_path);
- if (rc)
- goto qdf_free;
- smb2_set_next_command(tcon, &rqst[0]);
-
- /* Query directory */
- srch_inf->entries_in_buffer = 0;
- srch_inf->index_of_last_entry = 2;
-
- memset(&qd_iov, 0, sizeof(qd_iov));
- rqst[1].rq_iov = qd_iov;
- rqst[1].rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE;
-
- rc = SMB2_query_directory_init(xid, tcon, server,
- &rqst[1],
- COMPOUND_FID, COMPOUND_FID,
- 0, srch_inf->info_level);
- if (rc)
- goto qdf_free;
-
- smb2_set_related(&rqst[1]);
-
-again:
- rc = compound_send_recv(xid, tcon->ses, server,
- flags, 2, rqst,
- resp_buftype, rsp_iov);
-
- if (rc == -EAGAIN && retry_count++ < 10)
- goto again;
-
- /* If the open failed there is nothing to do */
- op_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
- if (op_rsp == NULL || op_rsp->hdr.Status != STATUS_SUCCESS) {
- cifs_dbg(FYI, "query_dir_first: open failed rc=%d\n", rc);
- goto qdf_free;
- }
- fid->persistent_fid = op_rsp->PersistentFileId;
- fid->volatile_fid = op_rsp->VolatileFileId;
-
- /* Anything else than ENODATA means a genuine error */
- if (rc && rc != -ENODATA) {
- SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
- cifs_dbg(FYI, "query_dir_first: query directory failed rc=%d\n", rc);
- trace_smb3_query_dir_err(xid, fid->persistent_fid,
- tcon->tid, tcon->ses->Suid, 0, 0, rc);
- goto qdf_free;
- }
-
- atomic_inc(&tcon->num_remote_opens);
-
- qd_rsp = (struct smb2_query_directory_rsp *)rsp_iov[1].iov_base;
- if (qd_rsp->hdr.Status == STATUS_NO_MORE_FILES) {
- trace_smb3_query_dir_done(xid, fid->persistent_fid,
- tcon->tid, tcon->ses->Suid, 0, 0);
- srch_inf->endOfSearch = true;
- rc = 0;
- goto qdf_free;
- }
-
- rc = smb2_parse_query_directory(tcon, &rsp_iov[1], resp_buftype[1],
- srch_inf);
- if (rc) {
- trace_smb3_query_dir_err(xid, fid->persistent_fid, tcon->tid,
- tcon->ses->Suid, 0, 0, rc);
- goto qdf_free;
- }
- resp_buftype[1] = CIFS_NO_BUFFER;
-
- trace_smb3_query_dir_done(xid, fid->persistent_fid, tcon->tid,
- tcon->ses->Suid, 0, srch_inf->entries_in_buffer);
-
- qdf_free:
- kfree(utf16_path);
- SMB2_open_free(&rqst[0]);
- SMB2_query_directory_free(&rqst[1]);
- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- return rc;
-}
-
-static int
-smb2_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_fid *fid, __u16 search_flags,
- struct cifs_search_info *srch_inf)
-{
- return SMB2_query_directory(xid, tcon, fid->persistent_fid,
- fid->volatile_fid, 0, srch_inf);
-}
-
-static int
-smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_fid *fid)
-{
- return SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
-}
-
-/*
- * If we negotiate SMB2 protocol and get STATUS_PENDING - update
- * the number of credits and return true. Otherwise - return false.
- */
-static bool
-smb2_is_status_pending(char *buf, struct TCP_Server_Info *server)
-{
- struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
- int scredits, in_flight;
-
- if (shdr->Status != STATUS_PENDING)
- return false;
-
- if (shdr->CreditRequest) {
- spin_lock(&server->req_lock);
- server->credits += le16_to_cpu(shdr->CreditRequest);
- scredits = server->credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
- wake_up(&server->request_q);
-
- trace_smb3_pend_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits,
- le16_to_cpu(shdr->CreditRequest), in_flight);
- cifs_dbg(FYI, "%s: status pending add %u credits total=%d\n",
- __func__, le16_to_cpu(shdr->CreditRequest), scredits);
- }
-
- return true;
-}
-
-static bool
-smb2_is_session_expired(char *buf)
-{
- struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
-
- if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED &&
- shdr->Status != STATUS_USER_SESSION_DELETED)
- return false;
-
- trace_smb3_ses_expired(le32_to_cpu(shdr->Id.SyncId.TreeId),
- le64_to_cpu(shdr->SessionId),
- le16_to_cpu(shdr->Command),
- le64_to_cpu(shdr->MessageId));
- cifs_dbg(FYI, "Session expired or deleted\n");
-
- return true;
-}
-
-static bool
-smb2_is_status_io_timeout(char *buf)
-{
- struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
-
- if (shdr->Status == STATUS_IO_TIMEOUT)
- return true;
- else
- return false;
-}
-
-static void
-smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
-{
- struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
-
- if (shdr->Status != STATUS_NETWORK_NAME_DELETED)
- return;
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- if (tcon->tid == le32_to_cpu(shdr->Id.SyncId.TreeId)) {
- spin_lock(&tcon->tc_lock);
- tcon->need_reconnect = true;
- spin_unlock(&tcon->tc_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- pr_warn_once("Server share %s deleted.\n",
- tcon->tree_name);
- return;
- }
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
-}
-
-static int
-smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
- __u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
-{
- if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
- return SMB2_lease_break(0, tcon, cinode->lease_key,
- smb2_get_lease_state(cinode));
-
- return SMB2_oplock_break(0, tcon, persistent_fid, volatile_fid,
- CIFS_CACHE_READ(cinode) ? 1 : 0);
-}
-
-void
-smb2_set_related(struct smb_rqst *rqst)
-{
- struct smb2_hdr *shdr;
-
- shdr = (struct smb2_hdr *)(rqst->rq_iov[0].iov_base);
- if (shdr == NULL) {
- cifs_dbg(FYI, "shdr NULL in smb2_set_related\n");
- return;
- }
- shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
-}
-
-char smb2_padding[7] = {0, 0, 0, 0, 0, 0, 0};
-
-void
-smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
-{
- struct smb2_hdr *shdr;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = ses->server;
- unsigned long len = smb_rqst_len(server, rqst);
- int i, num_padding;
-
- shdr = (struct smb2_hdr *)(rqst->rq_iov[0].iov_base);
- if (shdr == NULL) {
- cifs_dbg(FYI, "shdr NULL in smb2_set_next_command\n");
- return;
- }
-
- /* SMB headers in a compound are 8 byte aligned. */
-
- /* No padding needed */
- if (!(len & 7))
- goto finished;
-
- num_padding = 8 - (len & 7);
- if (!smb3_encryption_required(tcon)) {
- /*
- * If we do not have encryption then we can just add an extra
- * iov for the padding.
- */
- rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding;
- rqst->rq_iov[rqst->rq_nvec].iov_len = num_padding;
- rqst->rq_nvec++;
- len += num_padding;
- } else {
- /*
- * We can not add a small padding iov for the encryption case
- * because the encryption framework can not handle the padding
- * iovs.
- * We have to flatten this into a single buffer and add
- * the padding to it.
- */
- for (i = 1; i < rqst->rq_nvec; i++) {
- memcpy(rqst->rq_iov[0].iov_base +
- rqst->rq_iov[0].iov_len,
- rqst->rq_iov[i].iov_base,
- rqst->rq_iov[i].iov_len);
- rqst->rq_iov[0].iov_len += rqst->rq_iov[i].iov_len;
- }
- memset(rqst->rq_iov[0].iov_base + rqst->rq_iov[0].iov_len,
- 0, num_padding);
- rqst->rq_iov[0].iov_len += num_padding;
- len += num_padding;
- rqst->rq_nvec = 1;
- }
-
- finished:
- shdr->NextCommand = cpu_to_le32(len);
-}
-
-/*
- * Passes the query info response back to the caller on success.
- * Caller need to free this with free_rsp_buf().
- */
-int
-smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
- const char *path, u32 desired_access,
- u32 class, u32 type, u32 output_len,
- struct kvec *rsp, int *buftype,
- struct cifs_sb_info *cifs_sb)
-{
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- int flags = CIFS_CP_CREATE_CLOSE_OP;
- struct smb_rqst rqst[3];
- int resp_buftype[3];
- struct kvec rsp_iov[3];
- struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
- struct kvec qi_iov[1];
- struct kvec close_iov[1];
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
- int rc;
- __le16 *utf16_path;
- struct cached_fid *cfid = NULL;
-
- if (!path)
- path = "";
- utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(rqst, 0, sizeof(rqst));
- resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
- memset(rsp_iov, 0, sizeof(rsp_iov));
-
- /*
- * We can only call this for things we know are directories.
- */
- if (!strcmp(path, ""))
- open_cached_dir(xid, tcon, path, cifs_sb, false,
- &cfid); /* cfid null if open dir failed */
-
- memset(&open_iov, 0, sizeof(open_iov));
- rqst[0].rq_iov = open_iov;
- rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = path,
- .desired_access = desired_access,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, 0),
- .fid = &fid,
- };
-
- rc = SMB2_open_init(tcon, server,
- &rqst[0], &oplock, &oparms, utf16_path);
- if (rc)
- goto qic_exit;
- smb2_set_next_command(tcon, &rqst[0]);
-
- memset(&qi_iov, 0, sizeof(qi_iov));
- rqst[1].rq_iov = qi_iov;
- rqst[1].rq_nvec = 1;
-
- if (cfid) {
- rc = SMB2_query_info_init(tcon, server,
- &rqst[1],
- cfid->fid.persistent_fid,
- cfid->fid.volatile_fid,
- class, type, 0,
- output_len, 0,
- NULL);
- } else {
- rc = SMB2_query_info_init(tcon, server,
- &rqst[1],
- COMPOUND_FID,
- COMPOUND_FID,
- class, type, 0,
- output_len, 0,
- NULL);
- }
- if (rc)
- goto qic_exit;
- if (!cfid) {
- smb2_set_next_command(tcon, &rqst[1]);
- smb2_set_related(&rqst[1]);
- }
-
- memset(&close_iov, 0, sizeof(close_iov));
- rqst[2].rq_iov = close_iov;
- rqst[2].rq_nvec = 1;
-
- rc = SMB2_close_init(tcon, server,
- &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
- if (rc)
- goto qic_exit;
- smb2_set_related(&rqst[2]);
-
- if (cfid) {
- rc = compound_send_recv(xid, ses, server,
- flags, 1, &rqst[1],
- &resp_buftype[1], &rsp_iov[1]);
- } else {
- rc = compound_send_recv(xid, ses, server,
- flags, 3, rqst,
- resp_buftype, rsp_iov);
- }
- if (rc) {
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- if (rc == -EREMCHG) {
- tcon->need_reconnect = true;
- pr_warn_once("server share %s deleted\n",
- tcon->tree_name);
- }
- goto qic_exit;
- }
- *rsp = rsp_iov[1];
- *buftype = resp_buftype[1];
-
- qic_exit:
- kfree(utf16_path);
- SMB2_open_free(&rqst[0]);
- SMB2_query_info_free(&rqst[1]);
- SMB2_close_free(&rqst[2]);
- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
- free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
- if (cfid)
- close_cached_dir(cfid);
- return rc;
-}
-
-static int
-smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
-{
- struct smb2_query_info_rsp *rsp;
- struct smb2_fs_full_size_info *info = NULL;
- struct kvec rsp_iov = {NULL, 0};
- int buftype = CIFS_NO_BUFFER;
- int rc;
-
-
- rc = smb2_query_info_compound(xid, tcon, "",
- FILE_READ_ATTRIBUTES,
- FS_FULL_SIZE_INFORMATION,
- SMB2_O_INFO_FILESYSTEM,
- sizeof(struct smb2_fs_full_size_info),
- &rsp_iov, &buftype, cifs_sb);
- if (rc)
- goto qfs_exit;
-
- rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
- buf->f_type = SMB2_SUPER_MAGIC;
- info = (struct smb2_fs_full_size_info *)(
- le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
- rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
- le32_to_cpu(rsp->OutputBufferLength),
- &rsp_iov,
- sizeof(struct smb2_fs_full_size_info));
- if (!rc)
- smb2_copy_fs_info_to_kstatfs(info, buf);
-
-qfs_exit:
- free_rsp_buf(buftype, rsp_iov.iov_base);
- return rc;
-}
-
-static int
-smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
-{
- int rc;
- __le16 srch_path = 0; /* Null - open root of share */
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
-
- if (!tcon->posix_extensions)
- return smb2_queryfs(xid, tcon, cifs_sb, buf);
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = "",
- .desired_access = FILE_READ_ATTRIBUTES,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, 0),
- .fid = &fid,
- };
-
- rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
- NULL, NULL);
- if (rc)
- return rc;
-
- rc = SMB311_posix_qfs_info(xid, tcon, fid.persistent_fid,
- fid.volatile_fid, buf);
- buf->f_type = SMB2_SUPER_MAGIC;
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
- return rc;
-}
-
-static bool
-smb2_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
-{
- return ob1->fid.persistent_fid == ob2->fid.persistent_fid &&
- ob1->fid.volatile_fid == ob2->fid.volatile_fid;
-}
-
-static int
-smb2_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
- __u64 length, __u32 type, int lock, int unlock, bool wait)
-{
- if (unlock && !lock)
- type = SMB2_LOCKFLAG_UNLOCK;
- return SMB2_lock(xid, tlink_tcon(cfile->tlink),
- cfile->fid.persistent_fid, cfile->fid.volatile_fid,
- current->tgid, length, offset, type, wait);
-}
-
-static void
-smb2_get_lease_key(struct inode *inode, struct cifs_fid *fid)
-{
- memcpy(fid->lease_key, CIFS_I(inode)->lease_key, SMB2_LEASE_KEY_SIZE);
-}
-
-static void
-smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
-{
- memcpy(CIFS_I(inode)->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
-}
-
-static void
-smb2_new_lease_key(struct cifs_fid *fid)
-{
- generate_random_uuid(fid->lease_key);
-}
-
-static int
-smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
- const char *search_name,
- struct dfs_info3_param **target_nodes,
- unsigned int *num_of_nodes,
- const struct nls_table *nls_codepage, int remap)
-{
- int rc;
- __le16 *utf16_path = NULL;
- int utf16_path_len = 0;
- struct cifs_tcon *tcon;
- struct fsctl_get_dfs_referral_req *dfs_req = NULL;
- struct get_dfs_referral_rsp *dfs_rsp = NULL;
- u32 dfs_req_size = 0, dfs_rsp_size = 0;
- int retry_count = 0;
-
- cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name);
-
- /*
- * Try to use the IPC tcon, otherwise just use any
- */
- tcon = ses->tcon_ipc;
- if (tcon == NULL) {
- spin_lock(&cifs_tcp_ses_lock);
- tcon = list_first_entry_or_null(&ses->tcon_list,
- struct cifs_tcon,
- tcon_list);
- if (tcon)
- tcon->tc_count++;
- spin_unlock(&cifs_tcp_ses_lock);
- }
-
- if (tcon == NULL) {
- cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
- ses);
- rc = -ENOTCONN;
- goto out;
- }
-
- utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
- &utf16_path_len,
- nls_codepage, remap);
- if (!utf16_path) {
- rc = -ENOMEM;
- goto out;
- }
-
- dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
- dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
- if (!dfs_req) {
- rc = -ENOMEM;
- goto out;
- }
-
- /* Highest DFS referral version understood */
- dfs_req->MaxReferralLevel = DFS_VERSION;
-
- /* Path to resolve in an UTF-16 null-terminated string */
- memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
-
- do {
- rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
- FSCTL_DFS_GET_REFERRALS,
- (char *)dfs_req, dfs_req_size, CIFSMaxBufSize,
- (char **)&dfs_rsp, &dfs_rsp_size);
- if (!is_retryable_error(rc))
- break;
- usleep_range(512, 2048);
- } while (++retry_count < 5);
-
- if (rc) {
- if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP)
- cifs_tcon_dbg(VFS, "%s: ioctl error: rc=%d\n", __func__, rc);
- goto out;
- }
-
- rc = parse_dfs_referrals(dfs_rsp, dfs_rsp_size,
- num_of_nodes, target_nodes,
- nls_codepage, remap, search_name,
- true /* is_unicode */);
- if (rc) {
- cifs_tcon_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc);
- goto out;
- }
-
- out:
- if (tcon && !tcon->ipc) {
- /* ipc tcons are not refcounted */
- spin_lock(&cifs_tcp_ses_lock);
- tcon->tc_count--;
- /* tc_count can never go negative */
- WARN_ON(tcon->tc_count < 0);
- spin_unlock(&cifs_tcp_ses_lock);
- }
- kfree(utf16_path);
- kfree(dfs_req);
- kfree(dfs_rsp);
- return rc;
-}
-
-static int
-parse_reparse_posix(struct reparse_posix_data *symlink_buf,
- u32 plen, char **target_path,
- struct cifs_sb_info *cifs_sb)
-{
- unsigned int len;
-
- /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */
- len = le16_to_cpu(symlink_buf->ReparseDataLength);
-
- if (le64_to_cpu(symlink_buf->InodeType) != NFS_SPECFILE_LNK) {
- cifs_dbg(VFS, "%lld not a supported symlink type\n",
- le64_to_cpu(symlink_buf->InodeType));
- return -EOPNOTSUPP;
- }
-
- *target_path = cifs_strndup_from_utf16(
- symlink_buf->PathBuffer,
- len, true, cifs_sb->local_nls);
- if (!(*target_path))
- return -ENOMEM;
-
- convert_delimiter(*target_path, '/');
- cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
-
- return 0;
-}
-
-static int
-parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
- u32 plen, char **target_path,
- struct cifs_sb_info *cifs_sb)
-{
- unsigned int sub_len;
- unsigned int sub_offset;
-
- /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */
-
- sub_offset = le16_to_cpu(symlink_buf->SubstituteNameOffset);
- sub_len = le16_to_cpu(symlink_buf->SubstituteNameLength);
- if (sub_offset + 20 > plen ||
- sub_offset + sub_len + 20 > plen) {
- cifs_dbg(VFS, "srv returned malformed symlink buffer\n");
- return -EIO;
- }
-
- *target_path = cifs_strndup_from_utf16(
- symlink_buf->PathBuffer + sub_offset,
- sub_len, true, cifs_sb->local_nls);
- if (!(*target_path))
- return -ENOMEM;
-
- convert_delimiter(*target_path, '/');
- cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
-
- return 0;
-}
-
-static int
-parse_reparse_point(struct reparse_data_buffer *buf,
- u32 plen, char **target_path,
- struct cifs_sb_info *cifs_sb)
-{
- if (plen < sizeof(struct reparse_data_buffer)) {
- cifs_dbg(VFS, "reparse buffer is too small. Must be at least 8 bytes but was %d\n",
- plen);
- return -EIO;
- }
-
- if (plen < le16_to_cpu(buf->ReparseDataLength) +
- sizeof(struct reparse_data_buffer)) {
- cifs_dbg(VFS, "srv returned invalid reparse buf length: %d\n",
- plen);
- return -EIO;
- }
-
- /* See MS-FSCC 2.1.2 */
- switch (le32_to_cpu(buf->ReparseTag)) {
- case IO_REPARSE_TAG_NFS:
- return parse_reparse_posix(
- (struct reparse_posix_data *)buf,
- plen, target_path, cifs_sb);
- case IO_REPARSE_TAG_SYMLINK:
- return parse_reparse_symlink(
- (struct reparse_symlink_data_buffer *)buf,
- plen, target_path, cifs_sb);
- default:
- cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n",
- le32_to_cpu(buf->ReparseTag));
- return -EOPNOTSUPP;
- }
-}
-
-static int
-smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- char **target_path, bool is_reparse_point)
-{
- int rc;
- __le16 *utf16_path = NULL;
- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
- struct kvec err_iov = {NULL, 0};
- struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
- int flags = CIFS_CP_CREATE_CLOSE_OP;
- struct smb_rqst rqst[3];
- int resp_buftype[3];
- struct kvec rsp_iov[3];
- struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
- struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
- struct kvec close_iov[1];
- struct smb2_create_rsp *create_rsp;
- struct smb2_ioctl_rsp *ioctl_rsp;
- struct reparse_data_buffer *reparse_buf;
- int create_options = is_reparse_point ? OPEN_REPARSE_POINT : 0;
- u32 plen;
-
- cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
-
- *target_path = NULL;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(rqst, 0, sizeof(rqst));
- resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
- memset(rsp_iov, 0, sizeof(rsp_iov));
-
- utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
-
- /* Open */
- memset(&open_iov, 0, sizeof(open_iov));
- rqst[0].rq_iov = open_iov;
- rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = full_path,
- .desired_access = FILE_READ_ATTRIBUTES,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, create_options),
- .fid = &fid,
- };
-
- rc = SMB2_open_init(tcon, server,
- &rqst[0], &oplock, &oparms, utf16_path);
- if (rc)
- goto querty_exit;
- smb2_set_next_command(tcon, &rqst[0]);
-
-
- /* IOCTL */
- memset(&io_iov, 0, sizeof(io_iov));
- rqst[1].rq_iov = io_iov;
- rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
-
- rc = SMB2_ioctl_init(tcon, server,
- &rqst[1], fid.persistent_fid,
- fid.volatile_fid, FSCTL_GET_REPARSE_POINT, NULL, 0,
- CIFSMaxBufSize -
- MAX_SMB2_CREATE_RESPONSE_SIZE -
- MAX_SMB2_CLOSE_RESPONSE_SIZE);
- if (rc)
- goto querty_exit;
-
- smb2_set_next_command(tcon, &rqst[1]);
- smb2_set_related(&rqst[1]);
-
-
- /* Close */
- memset(&close_iov, 0, sizeof(close_iov));
- rqst[2].rq_iov = close_iov;
- rqst[2].rq_nvec = 1;
-
- rc = SMB2_close_init(tcon, server,
- &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
- if (rc)
- goto querty_exit;
-
- smb2_set_related(&rqst[2]);
-
- rc = compound_send_recv(xid, tcon->ses, server,
- flags, 3, rqst,
- resp_buftype, rsp_iov);
-
- create_rsp = rsp_iov[0].iov_base;
- if (create_rsp && create_rsp->hdr.Status)
- err_iov = rsp_iov[0];
- ioctl_rsp = rsp_iov[1].iov_base;
-
- /*
- * Open was successful and we got an ioctl response.
- */
- if ((rc == 0) && (is_reparse_point)) {
- /* See MS-FSCC 2.3.23 */
-
- reparse_buf = (struct reparse_data_buffer *)
- ((char *)ioctl_rsp +
- le32_to_cpu(ioctl_rsp->OutputOffset));
- plen = le32_to_cpu(ioctl_rsp->OutputCount);
-
- if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
- rsp_iov[1].iov_len) {
- cifs_tcon_dbg(VFS, "srv returned invalid ioctl len: %d\n",
- plen);
- rc = -EIO;
- goto querty_exit;
- }
-
- rc = parse_reparse_point(reparse_buf, plen, target_path,
- cifs_sb);
- goto querty_exit;
- }
-
- if (!rc || !err_iov.iov_base) {
- rc = -ENOENT;
- goto querty_exit;
- }
-
- rc = smb2_parse_symlink_response(cifs_sb, &err_iov, target_path);
-
- querty_exit:
- cifs_dbg(FYI, "query symlink rc %d\n", rc);
- kfree(utf16_path);
- SMB2_open_free(&rqst[0]);
- SMB2_ioctl_free(&rqst[1]);
- SMB2_close_free(&rqst[2]);
- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
- return rc;
-}
-
-int
-smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- __u32 *tag)
-{
- int rc;
- __le16 *utf16_path = NULL;
- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
- struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
- int flags = CIFS_CP_CREATE_CLOSE_OP;
- struct smb_rqst rqst[3];
- int resp_buftype[3];
- struct kvec rsp_iov[3];
- struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
- struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
- struct kvec close_iov[1];
- struct smb2_ioctl_rsp *ioctl_rsp;
- struct reparse_data_buffer *reparse_buf;
- u32 plen;
-
- cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(rqst, 0, sizeof(rqst));
- resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
- memset(rsp_iov, 0, sizeof(rsp_iov));
-
- utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
-
- /*
- * setup smb2open - TODO add optimization to call cifs_get_readable_path
- * to see if there is a handle already open that we can use
- */
- memset(&open_iov, 0, sizeof(open_iov));
- rqst[0].rq_iov = open_iov;
- rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = full_path,
- .desired_access = FILE_READ_ATTRIBUTES,
- .disposition = FILE_OPEN,
- .create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT),
- .fid = &fid,
- };
-
- rc = SMB2_open_init(tcon, server,
- &rqst[0], &oplock, &oparms, utf16_path);
- if (rc)
- goto query_rp_exit;
- smb2_set_next_command(tcon, &rqst[0]);
-
-
- /* IOCTL */
- memset(&io_iov, 0, sizeof(io_iov));
- rqst[1].rq_iov = io_iov;
- rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
-
- rc = SMB2_ioctl_init(tcon, server,
- &rqst[1], COMPOUND_FID,
- COMPOUND_FID, FSCTL_GET_REPARSE_POINT, NULL, 0,
- CIFSMaxBufSize -
- MAX_SMB2_CREATE_RESPONSE_SIZE -
- MAX_SMB2_CLOSE_RESPONSE_SIZE);
- if (rc)
- goto query_rp_exit;
-
- smb2_set_next_command(tcon, &rqst[1]);
- smb2_set_related(&rqst[1]);
-
-
- /* Close */
- memset(&close_iov, 0, sizeof(close_iov));
- rqst[2].rq_iov = close_iov;
- rqst[2].rq_nvec = 1;
-
- rc = SMB2_close_init(tcon, server,
- &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
- if (rc)
- goto query_rp_exit;
-
- smb2_set_related(&rqst[2]);
-
- rc = compound_send_recv(xid, tcon->ses, server,
- flags, 3, rqst,
- resp_buftype, rsp_iov);
-
- ioctl_rsp = rsp_iov[1].iov_base;
-
- /*
- * Open was successful and we got an ioctl response.
- */
- if (rc == 0) {
- /* See MS-FSCC 2.3.23 */
-
- reparse_buf = (struct reparse_data_buffer *)
- ((char *)ioctl_rsp +
- le32_to_cpu(ioctl_rsp->OutputOffset));
- plen = le32_to_cpu(ioctl_rsp->OutputCount);
-
- if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
- rsp_iov[1].iov_len) {
- cifs_tcon_dbg(FYI, "srv returned invalid ioctl len: %d\n",
- plen);
- rc = -EIO;
- goto query_rp_exit;
- }
- *tag = le32_to_cpu(reparse_buf->ReparseTag);
- }
-
- query_rp_exit:
- kfree(utf16_path);
- SMB2_open_free(&rqst[0]);
- SMB2_ioctl_free(&rqst[1]);
- SMB2_close_free(&rqst[2]);
- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
- free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
- return rc;
-}
-
-static struct cifs_ntsd *
-get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
- const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
-{
- struct cifs_ntsd *pntsd = NULL;
- unsigned int xid;
- int rc = -EOPNOTSUPP;
- struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
-
- if (IS_ERR(tlink))
- return ERR_CAST(tlink);
-
- xid = get_xid();
- cifs_dbg(FYI, "trying to get acl\n");
-
- rc = SMB2_query_acl(xid, tlink_tcon(tlink), cifsfid->persistent_fid,
- cifsfid->volatile_fid, (void **)&pntsd, pacllen,
- info);
- free_xid(xid);
-
- cifs_put_tlink(tlink);
-
- cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
- if (rc)
- return ERR_PTR(rc);
- return pntsd;
-
-}
-
-static struct cifs_ntsd *
-get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
- const char *path, u32 *pacllen, u32 info)
-{
- struct cifs_ntsd *pntsd = NULL;
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- unsigned int xid;
- int rc;
- struct cifs_tcon *tcon;
- struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- __le16 *utf16_path;
-
- cifs_dbg(FYI, "get smb3 acl for path %s\n", path);
- if (IS_ERR(tlink))
- return ERR_CAST(tlink);
-
- tcon = tlink_tcon(tlink);
- xid = get_xid();
-
- utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
- if (!utf16_path) {
- rc = -ENOMEM;
- free_xid(xid);
- return ERR_PTR(rc);
- }
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .path = path,
- .desired_access = READ_CONTROL,
- .disposition = FILE_OPEN,
- /*
- * When querying an ACL, even if the file is a symlink
- * we want to open the source not the target, and so
- * the protocol requires that the client specify this
- * flag when opening a reparse point
- */
- .create_options = cifs_create_options(cifs_sb, 0) |
- OPEN_REPARSE_POINT,
- .fid = &fid,
- };
-
- if (info & SACL_SECINFO)
- oparms.desired_access |= SYSTEM_SECURITY;
-
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL,
- NULL);
- kfree(utf16_path);
- if (!rc) {
- rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
- fid.volatile_fid, (void **)&pntsd, pacllen,
- info);
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
- }
-
- cifs_put_tlink(tlink);
- free_xid(xid);
-
- cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
- if (rc)
- return ERR_PTR(rc);
- return pntsd;
-}
-
-static int
-set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
- struct inode *inode, const char *path, int aclflag)
-{
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- unsigned int xid;
- int rc, access_flags = 0;
- struct cifs_tcon *tcon;
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- __le16 *utf16_path;
-
- cifs_dbg(FYI, "set smb3 acl for path %s\n", path);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
-
- tcon = tlink_tcon(tlink);
- xid = get_xid();
-
- if (aclflag & CIFS_ACL_OWNER || aclflag & CIFS_ACL_GROUP)
- access_flags |= WRITE_OWNER;
- if (aclflag & CIFS_ACL_SACL)
- access_flags |= SYSTEM_SECURITY;
- if (aclflag & CIFS_ACL_DACL)
- access_flags |= WRITE_DAC;
-
- utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
- if (!utf16_path) {
- rc = -ENOMEM;
- free_xid(xid);
- return rc;
- }
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .desired_access = access_flags,
- .create_options = cifs_create_options(cifs_sb, 0),
- .disposition = FILE_OPEN,
- .path = path,
- .fid = &fid,
- };
-
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
- NULL, NULL);
- kfree(utf16_path);
- if (!rc) {
- rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
- fid.volatile_fid, pnntsd, acllen, aclflag);
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
- }
-
- cifs_put_tlink(tlink);
- free_xid(xid);
- return rc;
-}
-
-/* Retrieve an ACL from the server */
-static struct cifs_ntsd *
-get_smb2_acl(struct cifs_sb_info *cifs_sb,
- struct inode *inode, const char *path,
- u32 *pacllen, u32 info)
-{
- struct cifs_ntsd *pntsd = NULL;
- struct cifsFileInfo *open_file = NULL;
-
- if (inode && !(info & SACL_SECINFO))
- open_file = find_readable_file(CIFS_I(inode), true);
- if (!open_file || (info & SACL_SECINFO))
- return get_smb2_acl_by_path(cifs_sb, path, pacllen, info);
-
- pntsd = get_smb2_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
- cifsFileInfo_put(open_file);
- return pntsd;
-}
-
-static long smb3_zero_data(struct file *file, struct cifs_tcon *tcon,
- loff_t offset, loff_t len, unsigned int xid)
-{
- struct cifsFileInfo *cfile = file->private_data;
- struct file_zero_data_information fsctl_buf;
-
- cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
-
- fsctl_buf.FileOffset = cpu_to_le64(offset);
- fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
-
- return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
- (char *)&fsctl_buf,
- sizeof(struct file_zero_data_information),
- 0, NULL, NULL);
-}
-
-static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
- loff_t offset, loff_t len, bool keep_size)
-{
- struct cifs_ses *ses = tcon->ses;
- struct inode *inode = file_inode(file);
- struct cifsInodeInfo *cifsi = CIFS_I(inode);
- struct cifsFileInfo *cfile = file->private_data;
- long rc;
- unsigned int xid;
- __le64 eof;
-
- xid = get_xid();
-
- trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid,
- ses->Suid, offset, len);
-
- inode_lock(inode);
- filemap_invalidate_lock(inode->i_mapping);
-
- /*
- * We zero the range through ioctl, so we need remove the page caches
- * first, otherwise the data may be inconsistent with the server.
- */
- truncate_pagecache_range(inode, offset, offset + len - 1);
-
- /* if file not oplocked can't be sure whether asking to extend size */
- rc = -EOPNOTSUPP;
- if (keep_size == false && !CIFS_CACHE_READ(cifsi))
- goto zero_range_exit;
-
- rc = smb3_zero_data(file, tcon, offset, len, xid);
- if (rc < 0)
- goto zero_range_exit;
-
- /*
- * do we also need to change the size of the file?
- */
- if (keep_size == false && i_size_read(inode) < offset + len) {
- eof = cpu_to_le64(offset + len);
- rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, cfile->pid, &eof);
- }
-
- zero_range_exit:
- filemap_invalidate_unlock(inode->i_mapping);
- inode_unlock(inode);
- free_xid(xid);
- if (rc)
- trace_smb3_zero_err(xid, cfile->fid.persistent_fid, tcon->tid,
- ses->Suid, offset, len, rc);
- else
- trace_smb3_zero_done(xid, cfile->fid.persistent_fid, tcon->tid,
- ses->Suid, offset, len);
- return rc;
-}
-
-static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
- loff_t offset, loff_t len)
-{
- struct inode *inode = file_inode(file);
- struct cifsFileInfo *cfile = file->private_data;
- struct file_zero_data_information fsctl_buf;
- long rc;
- unsigned int xid;
- __u8 set_sparse = 1;
-
- xid = get_xid();
-
- inode_lock(inode);
- /* Need to make file sparse, if not already, before freeing range. */
- /* Consider adding equivalent for compressed since it could also work */
- if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) {
- rc = -EOPNOTSUPP;
- goto out;
- }
-
- filemap_invalidate_lock(inode->i_mapping);
- /*
- * We implement the punch hole through ioctl, so we need remove the page
- * caches first, otherwise the data may be inconsistent with the server.
- */
- truncate_pagecache_range(inode, offset, offset + len - 1);
-
- cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
-
- fsctl_buf.FileOffset = cpu_to_le64(offset);
- fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
-
- rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
- (char *)&fsctl_buf,
- sizeof(struct file_zero_data_information),
- CIFSMaxBufSize, NULL, NULL);
- filemap_invalidate_unlock(inode->i_mapping);
-out:
- inode_unlock(inode);
- free_xid(xid);
- return rc;
-}
-
-static int smb3_simple_fallocate_write_range(unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile,
- loff_t off, loff_t len,
- char *buf)
-{
- struct cifs_io_parms io_parms = {0};
- int nbytes;
- int rc = 0;
- struct kvec iov[2];
-
- io_parms.netfid = cfile->fid.netfid;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
- io_parms.persistent_fid = cfile->fid.persistent_fid;
- io_parms.volatile_fid = cfile->fid.volatile_fid;
-
- while (len) {
- io_parms.offset = off;
- io_parms.length = len;
- if (io_parms.length > SMB2_MAX_BUFFER_SIZE)
- io_parms.length = SMB2_MAX_BUFFER_SIZE;
- /* iov[0] is reserved for smb header */
- iov[1].iov_base = buf;
- iov[1].iov_len = io_parms.length;
- rc = SMB2_write(xid, &io_parms, &nbytes, iov, 1);
- if (rc)
- break;
- if (nbytes > len)
- return -EINVAL;
- buf += nbytes;
- off += nbytes;
- len -= nbytes;
- }
- return rc;
-}
-
-static int smb3_simple_fallocate_range(unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile,
- loff_t off, loff_t len)
-{
- struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data;
- u32 out_data_len;
- char *buf = NULL;
- loff_t l;
- int rc;
-
- in_data.file_offset = cpu_to_le64(off);
- in_data.length = cpu_to_le64(len);
- rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- FSCTL_QUERY_ALLOCATED_RANGES,
- (char *)&in_data, sizeof(in_data),
- 1024 * sizeof(struct file_allocated_range_buffer),
- (char **)&out_data, &out_data_len);
- if (rc)
- goto out;
-
- buf = kzalloc(1024 * 1024, GFP_KERNEL);
- if (buf == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- tmp_data = out_data;
- while (len) {
- /*
- * The rest of the region is unmapped so write it all.
- */
- if (out_data_len == 0) {
- rc = smb3_simple_fallocate_write_range(xid, tcon,
- cfile, off, len, buf);
- goto out;
- }
-
- if (out_data_len < sizeof(struct file_allocated_range_buffer)) {
- rc = -EINVAL;
- goto out;
- }
-
- if (off < le64_to_cpu(tmp_data->file_offset)) {
- /*
- * We are at a hole. Write until the end of the region
- * or until the next allocated data,
- * whichever comes next.
- */
- l = le64_to_cpu(tmp_data->file_offset) - off;
- if (len < l)
- l = len;
- rc = smb3_simple_fallocate_write_range(xid, tcon,
- cfile, off, l, buf);
- if (rc)
- goto out;
- off = off + l;
- len = len - l;
- if (len == 0)
- goto out;
- }
- /*
- * We are at a section of allocated data, just skip forward
- * until the end of the data or the end of the region
- * we are supposed to fallocate, whichever comes first.
- */
- l = le64_to_cpu(tmp_data->length);
- if (len < l)
- l = len;
- off += l;
- len -= l;
-
- tmp_data = &tmp_data[1];
- out_data_len -= sizeof(struct file_allocated_range_buffer);
- }
-
- out:
- kfree(out_data);
- kfree(buf);
- return rc;
-}
-
-
-static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
- loff_t off, loff_t len, bool keep_size)
-{
- struct inode *inode;
- struct cifsInodeInfo *cifsi;
- struct cifsFileInfo *cfile = file->private_data;
- long rc = -EOPNOTSUPP;
- unsigned int xid;
- __le64 eof;
-
- xid = get_xid();
-
- inode = d_inode(cfile->dentry);
- cifsi = CIFS_I(inode);
-
- trace_smb3_falloc_enter(xid, cfile->fid.persistent_fid, tcon->tid,
- tcon->ses->Suid, off, len);
- /* if file not oplocked can't be sure whether asking to extend size */
- if (!CIFS_CACHE_READ(cifsi))
- if (keep_size == false) {
- trace_smb3_falloc_err(xid, cfile->fid.persistent_fid,
- tcon->tid, tcon->ses->Suid, off, len, rc);
- free_xid(xid);
- return rc;
- }
-
- /*
- * Extending the file
- */
- if ((keep_size == false) && i_size_read(inode) < off + len) {
- rc = inode_newsize_ok(inode, off + len);
- if (rc)
- goto out;
-
- if (cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)
- smb2_set_sparse(xid, tcon, cfile, inode, false);
-
- eof = cpu_to_le64(off + len);
- rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, cfile->pid, &eof);
- if (rc == 0) {
- cifsi->server_eof = off + len;
- cifs_setsize(inode, off + len);
- cifs_truncate_page(inode->i_mapping, inode->i_size);
- truncate_setsize(inode, off + len);
- }
- goto out;
- }
-
- /*
- * Files are non-sparse by default so falloc may be a no-op
- * Must check if file sparse. If not sparse, and since we are not
- * extending then no need to do anything since file already allocated
- */
- if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
- rc = 0;
- goto out;
- }
-
- if (keep_size == true) {
- /*
- * We can not preallocate pages beyond the end of the file
- * in SMB2
- */
- if (off >= i_size_read(inode)) {
- rc = 0;
- goto out;
- }
- /*
- * For fallocates that are partially beyond the end of file,
- * clamp len so we only fallocate up to the end of file.
- */
- if (off + len > i_size_read(inode)) {
- len = i_size_read(inode) - off;
- }
- }
-
- if ((keep_size == true) || (i_size_read(inode) >= off + len)) {
- /*
- * At this point, we are trying to fallocate an internal
- * regions of a sparse file. Since smb2 does not have a
- * fallocate command we have two otions on how to emulate this.
- * We can either turn the entire file to become non-sparse
- * which we only do if the fallocate is for virtually
- * the whole file, or we can overwrite the region with zeroes
- * using SMB2_write, which could be prohibitevly expensive
- * if len is large.
- */
- /*
- * We are only trying to fallocate a small region so
- * just write it with zero.
- */
- if (len <= 1024 * 1024) {
- rc = smb3_simple_fallocate_range(xid, tcon, cfile,
- off, len);
- goto out;
- }
-
- /*
- * Check if falloc starts within first few pages of file
- * and ends within a few pages of the end of file to
- * ensure that most of file is being forced to be
- * fallocated now. If so then setting whole file sparse
- * ie potentially making a few extra pages at the beginning
- * or end of the file non-sparse via set_sparse is harmless.
- */
- if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) {
- rc = -EOPNOTSUPP;
- goto out;
- }
- }
-
- smb2_set_sparse(xid, tcon, cfile, inode, false);
- rc = 0;
-
-out:
- if (rc)
- trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, tcon->tid,
- tcon->ses->Suid, off, len, rc);
- else
- trace_smb3_falloc_done(xid, cfile->fid.persistent_fid, tcon->tid,
- tcon->ses->Suid, off, len);
-
- free_xid(xid);
- return rc;
-}
-
-static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
- loff_t off, loff_t len)
-{
- int rc;
- unsigned int xid;
- struct inode *inode = file_inode(file);
- struct cifsFileInfo *cfile = file->private_data;
- struct cifsInodeInfo *cifsi = CIFS_I(inode);
- __le64 eof;
- loff_t old_eof;
-
- xid = get_xid();
-
- inode_lock(inode);
-
- old_eof = i_size_read(inode);
- if ((off >= old_eof) ||
- off + len >= old_eof) {
- rc = -EINVAL;
- goto out;
- }
-
- filemap_invalidate_lock(inode->i_mapping);
- rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof - 1);
- if (rc < 0)
- goto out_2;
-
- truncate_pagecache_range(inode, off, old_eof);
-
- rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
- old_eof - off - len, off);
- if (rc < 0)
- goto out_2;
-
- eof = cpu_to_le64(old_eof - len);
- rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, cfile->pid, &eof);
- if (rc < 0)
- goto out_2;
-
- rc = 0;
-
- cifsi->server_eof = i_size_read(inode) - len;
- truncate_setsize(inode, cifsi->server_eof);
- fscache_resize_cookie(cifs_inode_cookie(inode), cifsi->server_eof);
-out_2:
- filemap_invalidate_unlock(inode->i_mapping);
- out:
- inode_unlock(inode);
- free_xid(xid);
- return rc;
-}
-
-static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
- loff_t off, loff_t len)
-{
- int rc;
- unsigned int xid;
- struct cifsFileInfo *cfile = file->private_data;
- struct inode *inode = file_inode(file);
- __le64 eof;
- __u64 count, old_eof;
-
- xid = get_xid();
-
- inode_lock(inode);
-
- old_eof = i_size_read(inode);
- if (off >= old_eof) {
- rc = -EINVAL;
- goto out;
- }
-
- count = old_eof - off;
- eof = cpu_to_le64(old_eof + len);
-
- filemap_invalidate_lock(inode->i_mapping);
- rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof + len - 1);
- if (rc < 0)
- goto out_2;
- truncate_pagecache_range(inode, off, old_eof);
-
- rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid, cfile->pid, &eof);
- if (rc < 0)
- goto out_2;
-
- rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
- if (rc < 0)
- goto out_2;
-
- rc = smb3_zero_data(file, tcon, off, len, xid);
- if (rc < 0)
- goto out_2;
-
- rc = 0;
-out_2:
- filemap_invalidate_unlock(inode->i_mapping);
- out:
- inode_unlock(inode);
- free_xid(xid);
- return rc;
-}
-
-static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offset, int whence)
-{
- struct cifsFileInfo *wrcfile, *cfile = file->private_data;
- struct cifsInodeInfo *cifsi;
- struct inode *inode;
- int rc = 0;
- struct file_allocated_range_buffer in_data, *out_data = NULL;
- u32 out_data_len;
- unsigned int xid;
-
- if (whence != SEEK_HOLE && whence != SEEK_DATA)
- return generic_file_llseek(file, offset, whence);
-
- inode = d_inode(cfile->dentry);
- cifsi = CIFS_I(inode);
-
- if (offset < 0 || offset >= i_size_read(inode))
- return -ENXIO;
-
- xid = get_xid();
- /*
- * We need to be sure that all dirty pages are written as they
- * might fill holes on the server.
- * Note that we also MUST flush any written pages since at least
- * some servers (Windows2016) will not reflect recent writes in
- * QUERY_ALLOCATED_RANGES until SMB2_flush is called.
- */
- wrcfile = find_writable_file(cifsi, FIND_WR_ANY);
- if (wrcfile) {
- filemap_write_and_wait(inode->i_mapping);
- smb2_flush_file(xid, tcon, &wrcfile->fid);
- cifsFileInfo_put(wrcfile);
- }
-
- if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) {
- if (whence == SEEK_HOLE)
- offset = i_size_read(inode);
- goto lseek_exit;
- }
-
- in_data.file_offset = cpu_to_le64(offset);
- in_data.length = cpu_to_le64(i_size_read(inode));
-
- rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- FSCTL_QUERY_ALLOCATED_RANGES,
- (char *)&in_data, sizeof(in_data),
- sizeof(struct file_allocated_range_buffer),
- (char **)&out_data, &out_data_len);
- if (rc == -E2BIG)
- rc = 0;
- if (rc)
- goto lseek_exit;
-
- if (whence == SEEK_HOLE && out_data_len == 0)
- goto lseek_exit;
-
- if (whence == SEEK_DATA && out_data_len == 0) {
- rc = -ENXIO;
- goto lseek_exit;
- }
-
- if (out_data_len < sizeof(struct file_allocated_range_buffer)) {
- rc = -EINVAL;
- goto lseek_exit;
- }
- if (whence == SEEK_DATA) {
- offset = le64_to_cpu(out_data->file_offset);
- goto lseek_exit;
- }
- if (offset < le64_to_cpu(out_data->file_offset))
- goto lseek_exit;
-
- offset = le64_to_cpu(out_data->file_offset) + le64_to_cpu(out_data->length);
-
- lseek_exit:
- free_xid(xid);
- kfree(out_data);
- if (!rc)
- return vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
- else
- return rc;
-}
-
-static int smb3_fiemap(struct cifs_tcon *tcon,
- struct cifsFileInfo *cfile,
- struct fiemap_extent_info *fei, u64 start, u64 len)
-{
- unsigned int xid;
- struct file_allocated_range_buffer in_data, *out_data;
- u32 out_data_len;
- int i, num, rc, flags, last_blob;
- u64 next;
-
- rc = fiemap_prep(d_inode(cfile->dentry), fei, start, &len, 0);
- if (rc)
- return rc;
-
- xid = get_xid();
- again:
- in_data.file_offset = cpu_to_le64(start);
- in_data.length = cpu_to_le64(len);
-
- rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
- cfile->fid.volatile_fid,
- FSCTL_QUERY_ALLOCATED_RANGES,
- (char *)&in_data, sizeof(in_data),
- 1024 * sizeof(struct file_allocated_range_buffer),
- (char **)&out_data, &out_data_len);
- if (rc == -E2BIG) {
- last_blob = 0;
- rc = 0;
- } else
- last_blob = 1;
- if (rc)
- goto out;
-
- if (out_data_len && out_data_len < sizeof(struct file_allocated_range_buffer)) {
- rc = -EINVAL;
- goto out;
- }
- if (out_data_len % sizeof(struct file_allocated_range_buffer)) {
- rc = -EINVAL;
- goto out;
- }
-
- num = out_data_len / sizeof(struct file_allocated_range_buffer);
- for (i = 0; i < num; i++) {
- flags = 0;
- if (i == num - 1 && last_blob)
- flags |= FIEMAP_EXTENT_LAST;
-
- rc = fiemap_fill_next_extent(fei,
- le64_to_cpu(out_data[i].file_offset),
- le64_to_cpu(out_data[i].file_offset),
- le64_to_cpu(out_data[i].length),
- flags);
- if (rc < 0)
- goto out;
- if (rc == 1) {
- rc = 0;
- goto out;
- }
- }
-
- if (!last_blob) {
- next = le64_to_cpu(out_data[num - 1].file_offset) +
- le64_to_cpu(out_data[num - 1].length);
- len = len - (next - start);
- start = next;
- goto again;
- }
-
- out:
- free_xid(xid);
- kfree(out_data);
- return rc;
-}
-
-static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
- loff_t off, loff_t len)
-{
- /* KEEP_SIZE already checked for by do_fallocate */
- if (mode & FALLOC_FL_PUNCH_HOLE)
- return smb3_punch_hole(file, tcon, off, len);
- else if (mode & FALLOC_FL_ZERO_RANGE) {
- if (mode & FALLOC_FL_KEEP_SIZE)
- return smb3_zero_range(file, tcon, off, len, true);
- return smb3_zero_range(file, tcon, off, len, false);
- } else if (mode == FALLOC_FL_KEEP_SIZE)
- return smb3_simple_falloc(file, tcon, off, len, true);
- else if (mode == FALLOC_FL_COLLAPSE_RANGE)
- return smb3_collapse_range(file, tcon, off, len);
- else if (mode == FALLOC_FL_INSERT_RANGE)
- return smb3_insert_range(file, tcon, off, len);
- else if (mode == 0)
- return smb3_simple_falloc(file, tcon, off, len, false);
-
- return -EOPNOTSUPP;
-}
-
-static void
-smb2_downgrade_oplock(struct TCP_Server_Info *server,
- struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
-{
- server->ops->set_oplock_level(cinode, oplock, 0, NULL);
-}
-
-static void
-smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache);
-
-static void
-smb3_downgrade_oplock(struct TCP_Server_Info *server,
- struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
-{
- unsigned int old_state = cinode->oplock;
- unsigned int old_epoch = cinode->epoch;
- unsigned int new_state;
-
- if (epoch > old_epoch) {
- smb21_set_oplock_level(cinode, oplock, 0, NULL);
- cinode->epoch = epoch;
- }
-
- new_state = cinode->oplock;
- *purge_cache = false;
-
- if ((old_state & CIFS_CACHE_READ_FLG) != 0 &&
- (new_state & CIFS_CACHE_READ_FLG) == 0)
- *purge_cache = true;
- else if (old_state == new_state && (epoch - old_epoch > 1))
- *purge_cache = true;
-}
-
-static void
-smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
-{
- oplock &= 0xFF;
- cinode->lease_granted = false;
- if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
- return;
- if (oplock == SMB2_OPLOCK_LEVEL_BATCH) {
- cinode->oplock = CIFS_CACHE_RHW_FLG;
- cifs_dbg(FYI, "Batch Oplock granted on inode %p\n",
- &cinode->netfs.inode);
- } else if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
- cinode->oplock = CIFS_CACHE_RW_FLG;
- cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
- &cinode->netfs.inode);
- } else if (oplock == SMB2_OPLOCK_LEVEL_II) {
- cinode->oplock = CIFS_CACHE_READ_FLG;
- cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
- &cinode->netfs.inode);
- } else
- cinode->oplock = 0;
-}
-
-static void
-smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
-{
- char message[5] = {0};
- unsigned int new_oplock = 0;
-
- oplock &= 0xFF;
- cinode->lease_granted = true;
- if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
- return;
-
- /* Check if the server granted an oplock rather than a lease */
- if (oplock & SMB2_OPLOCK_LEVEL_EXCLUSIVE)
- return smb2_set_oplock_level(cinode, oplock, epoch,
- purge_cache);
-
- if (oplock & SMB2_LEASE_READ_CACHING_HE) {
- new_oplock |= CIFS_CACHE_READ_FLG;
- strcat(message, "R");
- }
- if (oplock & SMB2_LEASE_HANDLE_CACHING_HE) {
- new_oplock |= CIFS_CACHE_HANDLE_FLG;
- strcat(message, "H");
- }
- if (oplock & SMB2_LEASE_WRITE_CACHING_HE) {
- new_oplock |= CIFS_CACHE_WRITE_FLG;
- strcat(message, "W");
- }
- if (!new_oplock)
- strncpy(message, "None", sizeof(message));
-
- cinode->oplock = new_oplock;
- cifs_dbg(FYI, "%s Lease granted on inode %p\n", message,
- &cinode->netfs.inode);
-}
-
-static void
-smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
- unsigned int epoch, bool *purge_cache)
-{
- unsigned int old_oplock = cinode->oplock;
-
- smb21_set_oplock_level(cinode, oplock, epoch, purge_cache);
-
- if (purge_cache) {
- *purge_cache = false;
- if (old_oplock == CIFS_CACHE_READ_FLG) {
- if (cinode->oplock == CIFS_CACHE_READ_FLG &&
- (epoch - cinode->epoch > 0))
- *purge_cache = true;
- else if (cinode->oplock == CIFS_CACHE_RH_FLG &&
- (epoch - cinode->epoch > 1))
- *purge_cache = true;
- else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
- (epoch - cinode->epoch > 1))
- *purge_cache = true;
- else if (cinode->oplock == 0 &&
- (epoch - cinode->epoch > 0))
- *purge_cache = true;
- } else if (old_oplock == CIFS_CACHE_RH_FLG) {
- if (cinode->oplock == CIFS_CACHE_RH_FLG &&
- (epoch - cinode->epoch > 0))
- *purge_cache = true;
- else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
- (epoch - cinode->epoch > 1))
- *purge_cache = true;
- }
- cinode->epoch = epoch;
- }
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-static bool
-smb2_is_read_op(__u32 oplock)
-{
- return oplock == SMB2_OPLOCK_LEVEL_II;
-}
-#endif /* CIFS_ALLOW_INSECURE_LEGACY */
-
-static bool
-smb21_is_read_op(__u32 oplock)
-{
- return (oplock & SMB2_LEASE_READ_CACHING_HE) &&
- !(oplock & SMB2_LEASE_WRITE_CACHING_HE);
-}
-
-static __le32
-map_oplock_to_lease(u8 oplock)
-{
- if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
- return SMB2_LEASE_WRITE_CACHING_LE | SMB2_LEASE_READ_CACHING_LE;
- else if (oplock == SMB2_OPLOCK_LEVEL_II)
- return SMB2_LEASE_READ_CACHING_LE;
- else if (oplock == SMB2_OPLOCK_LEVEL_BATCH)
- return SMB2_LEASE_HANDLE_CACHING_LE | SMB2_LEASE_READ_CACHING_LE |
- SMB2_LEASE_WRITE_CACHING_LE;
- return 0;
-}
-
-static char *
-smb2_create_lease_buf(u8 *lease_key, u8 oplock)
-{
- struct create_lease *buf;
-
- buf = kzalloc(sizeof(struct create_lease), GFP_KERNEL);
- if (!buf)
- return NULL;
-
- memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
- buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
-
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_lease, lcontext));
- buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_lease, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
- buf->Name[0] = 'R';
- buf->Name[1] = 'q';
- buf->Name[2] = 'L';
- buf->Name[3] = 's';
- return (char *)buf;
-}
-
-static char *
-smb3_create_lease_buf(u8 *lease_key, u8 oplock)
-{
- struct create_lease_v2 *buf;
-
- buf = kzalloc(sizeof(struct create_lease_v2), GFP_KERNEL);
- if (!buf)
- return NULL;
-
- memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
- buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
-
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_lease_v2, lcontext));
- buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_lease_v2, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
- buf->Name[0] = 'R';
- buf->Name[1] = 'q';
- buf->Name[2] = 'L';
- buf->Name[3] = 's';
- return (char *)buf;
-}
-
-static __u8
-smb2_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key)
-{
- struct create_lease *lc = (struct create_lease *)buf;
-
- *epoch = 0; /* not used */
- if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE)
- return SMB2_OPLOCK_LEVEL_NOCHANGE;
- return le32_to_cpu(lc->lcontext.LeaseState);
-}
-
-static __u8
-smb3_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key)
-{
- struct create_lease_v2 *lc = (struct create_lease_v2 *)buf;
-
- *epoch = le16_to_cpu(lc->lcontext.Epoch);
- if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE)
- return SMB2_OPLOCK_LEVEL_NOCHANGE;
- if (lease_key)
- memcpy(lease_key, &lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
- return le32_to_cpu(lc->lcontext.LeaseState);
-}
-
-static unsigned int
-smb2_wp_retry_size(struct inode *inode)
-{
- return min_t(unsigned int, CIFS_SB(inode->i_sb)->ctx->wsize,
- SMB2_MAX_BUFFER_SIZE);
-}
-
-static bool
-smb2_dir_needs_close(struct cifsFileInfo *cfile)
-{
- return !cfile->invalidHandle;
-}
-
-static void
-fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
- struct smb_rqst *old_rq, __le16 cipher_type)
-{
- struct smb2_hdr *shdr =
- (struct smb2_hdr *)old_rq->rq_iov[0].iov_base;
-
- memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
- tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
- tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
- tr_hdr->Flags = cpu_to_le16(0x01);
- if ((cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
- (cipher_type == SMB2_ENCRYPTION_AES256_GCM))
- get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
- else
- get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
- memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
-}
-
-static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct smb_rqst *rqst,
- int num_rqst, const u8 *sig, u8 **iv,
- struct aead_request **req, struct scatterlist **sgl,
- unsigned int *num_sgs)
-{
- unsigned int req_size = sizeof(**req) + crypto_aead_reqsize(tfm);
- unsigned int iv_size = crypto_aead_ivsize(tfm);
- unsigned int len;
- u8 *p;
-
- *num_sgs = cifs_get_num_sgs(rqst, num_rqst, sig);
-
- len = iv_size;
- len += crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1);
- len = ALIGN(len, crypto_tfm_ctx_alignment());
- len += req_size;
- len = ALIGN(len, __alignof__(struct scatterlist));
- len += *num_sgs * sizeof(**sgl);
-
- p = kmalloc(len, GFP_ATOMIC);
- if (!p)
- return NULL;
-
- *iv = (u8 *)PTR_ALIGN(p, crypto_aead_alignmask(tfm) + 1);
- *req = (struct aead_request *)PTR_ALIGN(*iv + iv_size,
- crypto_tfm_ctx_alignment());
- *sgl = (struct scatterlist *)PTR_ALIGN((u8 *)*req + req_size,
- __alignof__(struct scatterlist));
- return p;
-}
-
-static void *smb2_get_aead_req(struct crypto_aead *tfm, const struct smb_rqst *rqst,
- int num_rqst, const u8 *sig, u8 **iv,
- struct aead_request **req, struct scatterlist **sgl)
-{
- unsigned int off, len, skip;
- struct scatterlist *sg;
- unsigned int num_sgs;
- unsigned long addr;
- int i, j;
- void *p;
-
- p = smb2_aead_req_alloc(tfm, rqst, num_rqst, sig, iv, req, sgl, &num_sgs);
- if (!p)
- return NULL;
-
- sg_init_table(*sgl, num_sgs);
- sg = *sgl;
-
- /* Assumes the first rqst has a transform header as the first iov.
- * I.e.
- * rqst[0].rq_iov[0] is transform header
- * rqst[0].rq_iov[1+] data to be encrypted/decrypted
- * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
- */
- for (i = 0; i < num_rqst; i++) {
- /*
- * The first rqst has a transform header where the
- * first 20 bytes are not part of the encrypted blob.
- */
- for (j = 0; j < rqst[i].rq_nvec; j++) {
- struct kvec *iov = &rqst[i].rq_iov[j];
-
- skip = (i == 0) && (j == 0) ? 20 : 0;
- addr = (unsigned long)iov->iov_base + skip;
- len = iov->iov_len - skip;
- sg = cifs_sg_set_buf(sg, (void *)addr, len);
- }
- for (j = 0; j < rqst[i].rq_npages; j++) {
- rqst_page_get_length(&rqst[i], j, &len, &off);
- sg_set_page(sg++, rqst[i].rq_pages[j], len, off);
- }
- }
- cifs_sg_set_buf(sg, sig, SMB2_SIGNATURE_SIZE);
-
- return p;
-}
-
-static int
-smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
-{
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses;
- u8 *ses_enc_key;
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
- if (ses->Suid == ses_id) {
- spin_lock(&ses->ses_lock);
- ses_enc_key = enc ? ses->smb3encryptionkey :
- ses->smb3decryptionkey;
- memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
- spin_unlock(&ses->ses_lock);
- spin_unlock(&cifs_tcp_ses_lock);
- return 0;
- }
- }
- spin_unlock(&cifs_tcp_ses_lock);
-
- return -EAGAIN;
-}
-/*
- * Encrypt or decrypt @rqst message. @rqst[0] has the following format:
- * iov[0] - transform header (associate data),
- * iov[1-N] - SMB2 header and pages - data to encrypt.
- * On success return encrypted data in iov[1-N] and pages, leave iov[0]
- * untouched.
- */
-static int
-crypt_message(struct TCP_Server_Info *server, int num_rqst,
- struct smb_rqst *rqst, int enc)
-{
- struct smb2_transform_hdr *tr_hdr =
- (struct smb2_transform_hdr *)rqst[0].rq_iov[0].iov_base;
- unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
- int rc = 0;
- struct scatterlist *sg;
- u8 sign[SMB2_SIGNATURE_SIZE] = {};
- u8 key[SMB3_ENC_DEC_KEY_SIZE];
- struct aead_request *req;
- u8 *iv;
- DECLARE_CRYPTO_WAIT(wait);
- struct crypto_aead *tfm;
- unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
- void *creq;
-
- rc = smb2_get_enc_key(server, le64_to_cpu(tr_hdr->SessionId), enc, key);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not get %scryption key\n", __func__,
- enc ? "en" : "de");
- return rc;
- }
-
- rc = smb3_crypto_aead_allocate(server);
- if (rc) {
- cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
- return rc;
- }
-
- tfm = enc ? server->secmech.enc : server->secmech.dec;
-
- if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
- (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
- rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
- else
- rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
-
- if (rc) {
- cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
- return rc;
- }
-
- rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc);
- return rc;
- }
-
- creq = smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg);
- if (unlikely(!creq))
- return -ENOMEM;
-
- if (!enc) {
- memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
- crypt_len += SMB2_SIGNATURE_SIZE;
- }
-
- if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
- (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
- memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
- else {
- iv[0] = 3;
- memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
- }
-
- aead_request_set_tfm(req, tfm);
- aead_request_set_crypt(req, sg, sg, crypt_len, iv);
- aead_request_set_ad(req, assoc_data_len);
-
- aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- crypto_req_done, &wait);
-
- rc = crypto_wait_req(enc ? crypto_aead_encrypt(req)
- : crypto_aead_decrypt(req), &wait);
-
- if (!rc && enc)
- memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
-
- kfree_sensitive(creq);
- return rc;
-}
-
-void
-smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst)
-{
- int i, j;
-
- for (i = 0; i < num_rqst; i++) {
- if (rqst[i].rq_pages) {
- for (j = rqst[i].rq_npages - 1; j >= 0; j--)
- put_page(rqst[i].rq_pages[j]);
- kfree(rqst[i].rq_pages);
- }
- }
-}
-
-/*
- * This function will initialize new_rq and encrypt the content.
- * The first entry, new_rq[0], only contains a single iov which contains
- * a smb2_transform_hdr and is pre-allocated by the caller.
- * This function then populates new_rq[1+] with the content from olq_rq[0+].
- *
- * The end result is an array of smb_rqst structures where the first structure
- * only contains a single iov for the transform header which we then can pass
- * to crypt_message().
- *
- * new_rq[0].rq_iov[0] : smb2_transform_hdr pre-allocated by the caller
- * new_rq[1+].rq_iov[*] == old_rq[0+].rq_iov[*] : SMB2/3 requests
- */
-static int
-smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
- struct smb_rqst *new_rq, struct smb_rqst *old_rq)
-{
- struct page **pages;
- struct smb2_transform_hdr *tr_hdr = new_rq[0].rq_iov[0].iov_base;
- unsigned int npages;
- unsigned int orig_len = 0;
- int i, j;
- int rc = -ENOMEM;
-
- for (i = 1; i < num_rqst; i++) {
- npages = old_rq[i - 1].rq_npages;
- pages = kmalloc_array(npages, sizeof(struct page *),
- GFP_KERNEL);
- if (!pages)
- goto err_free;
-
- new_rq[i].rq_pages = pages;
- new_rq[i].rq_npages = npages;
- new_rq[i].rq_offset = old_rq[i - 1].rq_offset;
- new_rq[i].rq_pagesz = old_rq[i - 1].rq_pagesz;
- new_rq[i].rq_tailsz = old_rq[i - 1].rq_tailsz;
- new_rq[i].rq_iov = old_rq[i - 1].rq_iov;
- new_rq[i].rq_nvec = old_rq[i - 1].rq_nvec;
-
- orig_len += smb_rqst_len(server, &old_rq[i - 1]);
-
- for (j = 0; j < npages; j++) {
- pages[j] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
- if (!pages[j])
- goto err_free;
- }
-
- /* copy pages form the old */
- for (j = 0; j < npages; j++) {
- char *dst, *src;
- unsigned int offset, len;
-
- rqst_page_get_length(&new_rq[i], j, &len, &offset);
-
- dst = (char *) kmap(new_rq[i].rq_pages[j]) + offset;
- src = (char *) kmap(old_rq[i - 1].rq_pages[j]) + offset;
-
- memcpy(dst, src, len);
- kunmap(new_rq[i].rq_pages[j]);
- kunmap(old_rq[i - 1].rq_pages[j]);
- }
- }
-
- /* fill the 1st iov with a transform header */
- fill_transform_hdr(tr_hdr, orig_len, old_rq, server->cipher_type);
-
- rc = crypt_message(server, num_rqst, new_rq, 1);
- cifs_dbg(FYI, "Encrypt message returned %d\n", rc);
- if (rc)
- goto err_free;
-
- return rc;
-
-err_free:
- smb3_free_compound_rqst(num_rqst - 1, &new_rq[1]);
- return rc;
-}
-
-static int
-smb3_is_transform_hdr(void *buf)
-{
- struct smb2_transform_hdr *trhdr = buf;
-
- return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
-}
-
-static int
-decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
- unsigned int buf_data_size, struct page **pages,
- unsigned int npages, unsigned int page_data_size,
- bool is_offloaded)
-{
- struct kvec iov[2];
- struct smb_rqst rqst = {NULL};
- int rc;
-
- iov[0].iov_base = buf;
- iov[0].iov_len = sizeof(struct smb2_transform_hdr);
- iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
- iov[1].iov_len = buf_data_size;
-
- rqst.rq_iov = iov;
- rqst.rq_nvec = 2;
- rqst.rq_pages = pages;
- rqst.rq_npages = npages;
- rqst.rq_pagesz = PAGE_SIZE;
- rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE;
-
- rc = crypt_message(server, 1, &rqst, 0);
- cifs_dbg(FYI, "Decrypt message returned %d\n", rc);
-
- if (rc)
- return rc;
-
- memmove(buf, iov[1].iov_base, buf_data_size);
-
- if (!is_offloaded)
- server->total_read = buf_data_size + page_data_size;
-
- return rc;
-}
-
-static int
-read_data_into_pages(struct TCP_Server_Info *server, struct page **pages,
- unsigned int npages, unsigned int len)
-{
- int i;
- int length;
-
- for (i = 0; i < npages; i++) {
- struct page *page = pages[i];
- size_t n;
-
- n = len;
- if (len >= PAGE_SIZE) {
- /* enough data to fill the page */
- n = PAGE_SIZE;
- len -= n;
- } else {
- zero_user(page, len, PAGE_SIZE - len);
- len = 0;
- }
- length = cifs_read_page_from_socket(server, page, 0, n);
- if (length < 0)
- return length;
- server->total_read += length;
- }
-
- return 0;
-}
-
-static int
-init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size,
- unsigned int cur_off, struct bio_vec **page_vec)
-{
- struct bio_vec *bvec;
- int i;
-
- bvec = kcalloc(npages, sizeof(struct bio_vec), GFP_KERNEL);
- if (!bvec)
- return -ENOMEM;
-
- for (i = 0; i < npages; i++) {
- bvec[i].bv_page = pages[i];
- bvec[i].bv_offset = (i == 0) ? cur_off : 0;
- bvec[i].bv_len = min_t(unsigned int, PAGE_SIZE, data_size);
- data_size -= bvec[i].bv_len;
- }
-
- if (data_size != 0) {
- cifs_dbg(VFS, "%s: something went wrong\n", __func__);
- kfree(bvec);
- return -EIO;
- }
-
- *page_vec = bvec;
- return 0;
-}
-
-static int
-handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
- char *buf, unsigned int buf_len, struct page **pages,
- unsigned int npages, unsigned int page_data_size,
- bool is_offloaded)
-{
- unsigned int data_offset;
- unsigned int data_len;
- unsigned int cur_off;
- unsigned int cur_page_idx;
- unsigned int pad_len;
- struct cifs_readdata *rdata = mid->callback_data;
- struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
- struct bio_vec *bvec = NULL;
- struct iov_iter iter;
- struct kvec iov;
- int length;
- bool use_rdma_mr = false;
-
- if (shdr->Command != SMB2_READ) {
- cifs_server_dbg(VFS, "only big read responses are supported\n");
- return -ENOTSUPP;
- }
-
- if (server->ops->is_session_expired &&
- server->ops->is_session_expired(buf)) {
- if (!is_offloaded)
- cifs_reconnect(server, true);
- return -1;
- }
-
- if (server->ops->is_status_pending &&
- server->ops->is_status_pending(buf, server))
- return -1;
-
- /* set up first two iov to get credits */
- rdata->iov[0].iov_base = buf;
- rdata->iov[0].iov_len = 0;
- rdata->iov[1].iov_base = buf;
- rdata->iov[1].iov_len =
- min_t(unsigned int, buf_len, server->vals->read_rsp_size);
- cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
- rdata->iov[0].iov_base, rdata->iov[0].iov_len);
- cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
- rdata->iov[1].iov_base, rdata->iov[1].iov_len);
-
- rdata->result = server->ops->map_error(buf, true);
- if (rdata->result != 0) {
- cifs_dbg(FYI, "%s: server returned error %d\n",
- __func__, rdata->result);
- /* normal error on read response */
- if (is_offloaded)
- mid->mid_state = MID_RESPONSE_RECEIVED;
- else
- dequeue_mid(mid, false);
- return 0;
- }
-
- data_offset = server->ops->read_data_offset(buf);
-#ifdef CONFIG_CIFS_SMB_DIRECT
- use_rdma_mr = rdata->mr;
-#endif
- data_len = server->ops->read_data_length(buf, use_rdma_mr);
-
- if (data_offset < server->vals->read_rsp_size) {
- /*
- * win2k8 sometimes sends an offset of 0 when the read
- * is beyond the EOF. Treat it as if the data starts just after
- * the header.
- */
- cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
- __func__, data_offset);
- data_offset = server->vals->read_rsp_size;
- } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
- /* data_offset is beyond the end of smallbuf */
- cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
- __func__, data_offset);
- rdata->result = -EIO;
- if (is_offloaded)
- mid->mid_state = MID_RESPONSE_MALFORMED;
- else
- dequeue_mid(mid, rdata->result);
- return 0;
- }
-
- pad_len = data_offset - server->vals->read_rsp_size;
-
- if (buf_len <= data_offset) {
- /* read response payload is in pages */
- cur_page_idx = pad_len / PAGE_SIZE;
- cur_off = pad_len % PAGE_SIZE;
-
- if (cur_page_idx != 0) {
- /* data offset is beyond the 1st page of response */
- cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
- __func__, data_offset);
- rdata->result = -EIO;
- if (is_offloaded)
- mid->mid_state = MID_RESPONSE_MALFORMED;
- else
- dequeue_mid(mid, rdata->result);
- return 0;
- }
-
- if (data_len > page_data_size - pad_len) {
- /* data_len is corrupt -- discard frame */
- rdata->result = -EIO;
- if (is_offloaded)
- mid->mid_state = MID_RESPONSE_MALFORMED;
- else
- dequeue_mid(mid, rdata->result);
- return 0;
- }
-
- rdata->result = init_read_bvec(pages, npages, page_data_size,
- cur_off, &bvec);
- if (rdata->result != 0) {
- if (is_offloaded)
- mid->mid_state = MID_RESPONSE_MALFORMED;
- else
- dequeue_mid(mid, rdata->result);
- return 0;
- }
-
- iov_iter_bvec(&iter, ITER_SOURCE, bvec, npages, data_len);
- } else if (buf_len >= data_offset + data_len) {
- /* read response payload is in buf */
- WARN_ONCE(npages > 0, "read data can be either in buf or in pages");
- iov.iov_base = buf + data_offset;
- iov.iov_len = data_len;
- iov_iter_kvec(&iter, ITER_SOURCE, &iov, 1, data_len);
- } else {
- /* read response payload cannot be in both buf and pages */
- WARN_ONCE(1, "buf can not contain only a part of read data");
- rdata->result = -EIO;
- if (is_offloaded)
- mid->mid_state = MID_RESPONSE_MALFORMED;
- else
- dequeue_mid(mid, rdata->result);
- return 0;
- }
-
- length = rdata->copy_into_pages(server, rdata, &iter);
-
- kfree(bvec);
-
- if (length < 0)
- return length;
-
- if (is_offloaded)
- mid->mid_state = MID_RESPONSE_RECEIVED;
- else
- dequeue_mid(mid, false);
- return length;
-}
-
-struct smb2_decrypt_work {
- struct work_struct decrypt;
- struct TCP_Server_Info *server;
- struct page **ppages;
- char *buf;
- unsigned int npages;
- unsigned int len;
-};
-
-
-static void smb2_decrypt_offload(struct work_struct *work)
-{
- struct smb2_decrypt_work *dw = container_of(work,
- struct smb2_decrypt_work, decrypt);
- int i, rc;
- struct mid_q_entry *mid;
-
- rc = decrypt_raw_data(dw->server, dw->buf, dw->server->vals->read_rsp_size,
- dw->ppages, dw->npages, dw->len, true);
- if (rc) {
- cifs_dbg(VFS, "error decrypting rc=%d\n", rc);
- goto free_pages;
- }
-
- dw->server->lstrp = jiffies;
- mid = smb2_find_dequeue_mid(dw->server, dw->buf);
- if (mid == NULL)
- cifs_dbg(FYI, "mid not found\n");
- else {
- mid->decrypted = true;
- rc = handle_read_data(dw->server, mid, dw->buf,
- dw->server->vals->read_rsp_size,
- dw->ppages, dw->npages, dw->len,
- true);
- if (rc >= 0) {
-#ifdef CONFIG_CIFS_STATS2
- mid->when_received = jiffies;
-#endif
- if (dw->server->ops->is_network_name_deleted)
- dw->server->ops->is_network_name_deleted(dw->buf,
- dw->server);
-
- mid->callback(mid);
- } else {
- spin_lock(&dw->server->srv_lock);
- if (dw->server->tcpStatus == CifsNeedReconnect) {
- spin_lock(&dw->server->mid_lock);
- mid->mid_state = MID_RETRY_NEEDED;
- spin_unlock(&dw->server->mid_lock);
- spin_unlock(&dw->server->srv_lock);
- mid->callback(mid);
- } else {
- spin_lock(&dw->server->mid_lock);
- mid->mid_state = MID_REQUEST_SUBMITTED;
- mid->mid_flags &= ~(MID_DELETED);
- list_add_tail(&mid->qhead,
- &dw->server->pending_mid_q);
- spin_unlock(&dw->server->mid_lock);
- spin_unlock(&dw->server->srv_lock);
- }
- }
- release_mid(mid);
- }
-
-free_pages:
- for (i = dw->npages-1; i >= 0; i--)
- put_page(dw->ppages[i]);
-
- kfree(dw->ppages);
- cifs_small_buf_release(dw->buf);
- kfree(dw);
-}
-
-
-static int
-receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
- int *num_mids)
-{
- char *buf = server->smallbuf;
- struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
- unsigned int npages;
- struct page **pages;
- unsigned int len;
- unsigned int buflen = server->pdu_size;
- int rc;
- int i = 0;
- struct smb2_decrypt_work *dw;
-
- *num_mids = 1;
- len = min_t(unsigned int, buflen, server->vals->read_rsp_size +
- sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1;
-
- rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len);
- if (rc < 0)
- return rc;
- server->total_read += rc;
-
- len = le32_to_cpu(tr_hdr->OriginalMessageSize) -
- server->vals->read_rsp_size;
- npages = DIV_ROUND_UP(len, PAGE_SIZE);
-
- pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
- if (!pages) {
- rc = -ENOMEM;
- goto discard_data;
- }
-
- for (; i < npages; i++) {
- pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
- if (!pages[i]) {
- rc = -ENOMEM;
- goto discard_data;
- }
- }
-
- /* read read data into pages */
- rc = read_data_into_pages(server, pages, npages, len);
- if (rc)
- goto free_pages;
-
- rc = cifs_discard_remaining_data(server);
- if (rc)
- goto free_pages;
-
- /*
- * For large reads, offload to different thread for better performance,
- * use more cores decrypting which can be expensive
- */
-
- if ((server->min_offload) && (server->in_flight > 1) &&
- (server->pdu_size >= server->min_offload)) {
- dw = kmalloc(sizeof(struct smb2_decrypt_work), GFP_KERNEL);
- if (dw == NULL)
- goto non_offloaded_decrypt;
-
- dw->buf = server->smallbuf;
- server->smallbuf = (char *)cifs_small_buf_get();
-
- INIT_WORK(&dw->decrypt, smb2_decrypt_offload);
-
- dw->npages = npages;
- dw->server = server;
- dw->ppages = pages;
- dw->len = len;
- queue_work(decrypt_wq, &dw->decrypt);
- *num_mids = 0; /* worker thread takes care of finding mid */
- return -1;
- }
-
-non_offloaded_decrypt:
- rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size,
- pages, npages, len, false);
- if (rc)
- goto free_pages;
-
- *mid = smb2_find_mid(server, buf);
- if (*mid == NULL)
- cifs_dbg(FYI, "mid not found\n");
- else {
- cifs_dbg(FYI, "mid found\n");
- (*mid)->decrypted = true;
- rc = handle_read_data(server, *mid, buf,
- server->vals->read_rsp_size,
- pages, npages, len, false);
- if (rc >= 0) {
- if (server->ops->is_network_name_deleted) {
- server->ops->is_network_name_deleted(buf,
- server);
- }
- }
- }
-
-free_pages:
- for (i = i - 1; i >= 0; i--)
- put_page(pages[i]);
- kfree(pages);
- return rc;
-discard_data:
- cifs_discard_remaining_data(server);
- goto free_pages;
-}
-
-static int
-receive_encrypted_standard(struct TCP_Server_Info *server,
- struct mid_q_entry **mids, char **bufs,
- int *num_mids)
-{
- int ret, length;
- char *buf = server->smallbuf;
- struct smb2_hdr *shdr;
- unsigned int pdu_length = server->pdu_size;
- unsigned int buf_size;
- struct mid_q_entry *mid_entry;
- int next_is_large;
- char *next_buffer = NULL;
-
- *num_mids = 0;
-
- /* switch to large buffer if too big for a small one */
- if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE) {
- server->large_buf = true;
- memcpy(server->bigbuf, buf, server->total_read);
- buf = server->bigbuf;
- }
-
- /* now read the rest */
- length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
- pdu_length - HEADER_SIZE(server) + 1);
- if (length < 0)
- return length;
- server->total_read += length;
-
- buf_size = pdu_length - sizeof(struct smb2_transform_hdr);
- length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0, false);
- if (length)
- return length;
-
- next_is_large = server->large_buf;
-one_more:
- shdr = (struct smb2_hdr *)buf;
- if (shdr->NextCommand) {
- if (next_is_large)
- next_buffer = (char *)cifs_buf_get();
- else
- next_buffer = (char *)cifs_small_buf_get();
- memcpy(next_buffer,
- buf + le32_to_cpu(shdr->NextCommand),
- pdu_length - le32_to_cpu(shdr->NextCommand));
- }
-
- mid_entry = smb2_find_mid(server, buf);
- if (mid_entry == NULL)
- cifs_dbg(FYI, "mid not found\n");
- else {
- cifs_dbg(FYI, "mid found\n");
- mid_entry->decrypted = true;
- mid_entry->resp_buf_size = server->pdu_size;
- }
-
- if (*num_mids >= MAX_COMPOUND) {
- cifs_server_dbg(VFS, "too many PDUs in compound\n");
- return -1;
- }
- bufs[*num_mids] = buf;
- mids[(*num_mids)++] = mid_entry;
-
- if (mid_entry && mid_entry->handle)
- ret = mid_entry->handle(server, mid_entry);
- else
- ret = cifs_handle_standard(server, mid_entry);
-
- if (ret == 0 && shdr->NextCommand) {
- pdu_length -= le32_to_cpu(shdr->NextCommand);
- server->large_buf = next_is_large;
- if (next_is_large)
- server->bigbuf = buf = next_buffer;
- else
- server->smallbuf = buf = next_buffer;
- goto one_more;
- } else if (ret != 0) {
- /*
- * ret != 0 here means that we didn't get to handle_mid() thus
- * server->smallbuf and server->bigbuf are still valid. We need
- * to free next_buffer because it is not going to be used
- * anywhere.
- */
- if (next_is_large)
- free_rsp_buf(CIFS_LARGE_BUFFER, next_buffer);
- else
- free_rsp_buf(CIFS_SMALL_BUFFER, next_buffer);
- }
-
- return ret;
-}
-
-static int
-smb3_receive_transform(struct TCP_Server_Info *server,
- struct mid_q_entry **mids, char **bufs, int *num_mids)
-{
- char *buf = server->smallbuf;
- unsigned int pdu_length = server->pdu_size;
- struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
- unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
-
- if (pdu_length < sizeof(struct smb2_transform_hdr) +
- sizeof(struct smb2_hdr)) {
- cifs_server_dbg(VFS, "Transform message is too small (%u)\n",
- pdu_length);
- cifs_reconnect(server, true);
- return -ECONNABORTED;
- }
-
- if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) {
- cifs_server_dbg(VFS, "Transform message is broken\n");
- cifs_reconnect(server, true);
- return -ECONNABORTED;
- }
-
- /* TODO: add support for compounds containing READ. */
- if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) {
- return receive_encrypted_read(server, &mids[0], num_mids);
- }
-
- return receive_encrypted_standard(server, mids, bufs, num_mids);
-}
-
-int
-smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
-{
- char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
-
- return handle_read_data(server, mid, buf, server->pdu_size,
- NULL, 0, 0, false);
-}
-
-static int
-smb2_next_header(char *buf)
-{
- struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
- struct smb2_transform_hdr *t_hdr = (struct smb2_transform_hdr *)buf;
-
- if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM)
- return sizeof(struct smb2_transform_hdr) +
- le32_to_cpu(t_hdr->OriginalMessageSize);
-
- return le32_to_cpu(hdr->NextCommand);
-}
-
-static int
-smb2_make_node(unsigned int xid, struct inode *inode,
- struct dentry *dentry, struct cifs_tcon *tcon,
- const char *full_path, umode_t mode, dev_t dev)
-{
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- int rc = -EPERM;
- struct cifs_open_info_data buf = {};
- struct cifs_io_parms io_parms = {0};
- __u32 oplock = 0;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- unsigned int bytes_written;
- struct win_dev *pdev;
- struct kvec iov[2];
-
- /*
- * Check if mounted with mount parm 'sfu' mount parm.
- * SFU emulation should work with all servers, but only
- * supports block and char device (no socket & fifo),
- * and was used by default in earlier versions of Windows
- */
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
- return rc;
-
- /*
- * TODO: Add ability to create instead via reparse point. Windows (e.g.
- * their current NFS server) uses this approach to expose special files
- * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
- */
-
- if (!S_ISCHR(mode) && !S_ISBLK(mode))
- return rc;
-
- cifs_dbg(FYI, "sfu compat create special file\n");
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = GENERIC_WRITE,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
- CREATE_OPTION_SPECIAL),
- .disposition = FILE_CREATE,
- .path = full_path,
- .fid = &fid,
- };
-
- if (tcon->ses->server->oplocks)
- oplock = REQ_OPLOCK;
- else
- oplock = 0;
- rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
- if (rc)
- return rc;
-
- /*
- * BB Do not bother to decode buf since no local inode yet to put
- * timestamps in, but we can reuse it safely.
- */
-
- pdev = (struct win_dev *)&buf.fi;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
- io_parms.offset = 0;
- io_parms.length = sizeof(struct win_dev);
- iov[1].iov_base = &buf.fi;
- iov[1].iov_len = sizeof(struct win_dev);
- if (S_ISCHR(mode)) {
- memcpy(pdev->type, "IntxCHR", 8);
- pdev->major = cpu_to_le64(MAJOR(dev));
- pdev->minor = cpu_to_le64(MINOR(dev));
- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
- } else if (S_ISBLK(mode)) {
- memcpy(pdev->type, "IntxBLK", 8);
- pdev->major = cpu_to_le64(MAJOR(dev));
- pdev->minor = cpu_to_le64(MINOR(dev));
- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
- }
- tcon->ses->server->ops->close(xid, tcon, &fid);
- d_drop(dentry);
-
- /* FIXME: add code here to set EAs */
-
- cifs_free_open_info(&buf);
- return rc;
-}
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-struct smb_version_operations smb20_operations = {
- .compare_fids = smb2_compare_fids,
- .setup_request = smb2_setup_request,
- .setup_async_request = smb2_setup_async_request,
- .check_receive = smb2_check_receive,
- .add_credits = smb2_add_credits,
- .set_credits = smb2_set_credits,
- .get_credits_field = smb2_get_credits_field,
- .get_credits = smb2_get_credits,
- .wait_mtu_credits = cifs_wait_mtu_credits,
- .get_next_mid = smb2_get_next_mid,
- .revert_current_mid = smb2_revert_current_mid,
- .read_data_offset = smb2_read_data_offset,
- .read_data_length = smb2_read_data_length,
- .map_error = map_smb2_to_linux_error,
- .find_mid = smb2_find_mid,
- .check_message = smb2_check_message,
- .dump_detail = smb2_dump_detail,
- .clear_stats = smb2_clear_stats,
- .print_stats = smb2_print_stats,
- .is_oplock_break = smb2_is_valid_oplock_break,
- .handle_cancelled_mid = smb2_handle_cancelled_mid,
- .downgrade_oplock = smb2_downgrade_oplock,
- .need_neg = smb2_need_neg,
- .negotiate = smb2_negotiate,
- .negotiate_wsize = smb2_negotiate_wsize,
- .negotiate_rsize = smb2_negotiate_rsize,
- .sess_setup = SMB2_sess_setup,
- .logoff = SMB2_logoff,
- .tree_connect = SMB2_tcon,
- .tree_disconnect = SMB2_tdis,
- .qfs_tcon = smb2_qfs_tcon,
- .is_path_accessible = smb2_is_path_accessible,
- .can_echo = smb2_can_echo,
- .echo = SMB2_echo,
- .query_path_info = smb2_query_path_info,
- .get_srv_inum = smb2_get_srv_inum,
- .query_file_info = smb2_query_file_info,
- .set_path_size = smb2_set_path_size,
- .set_file_size = smb2_set_file_size,
- .set_file_info = smb2_set_file_info,
- .set_compression = smb2_set_compression,
- .mkdir = smb2_mkdir,
- .mkdir_setinfo = smb2_mkdir_setinfo,
- .rmdir = smb2_rmdir,
- .unlink = smb2_unlink,
- .rename = smb2_rename_path,
- .create_hardlink = smb2_create_hardlink,
- .query_symlink = smb2_query_symlink,
- .query_mf_symlink = smb3_query_mf_symlink,
- .create_mf_symlink = smb3_create_mf_symlink,
- .open = smb2_open_file,
- .set_fid = smb2_set_fid,
- .close = smb2_close_file,
- .flush = smb2_flush_file,
- .async_readv = smb2_async_readv,
- .async_writev = smb2_async_writev,
- .sync_read = smb2_sync_read,
- .sync_write = smb2_sync_write,
- .query_dir_first = smb2_query_dir_first,
- .query_dir_next = smb2_query_dir_next,
- .close_dir = smb2_close_dir,
- .calc_smb_size = smb2_calc_size,
- .is_status_pending = smb2_is_status_pending,
- .is_session_expired = smb2_is_session_expired,
- .oplock_response = smb2_oplock_response,
- .queryfs = smb2_queryfs,
- .mand_lock = smb2_mand_lock,
- .mand_unlock_range = smb2_unlock_range,
- .push_mand_locks = smb2_push_mandatory_locks,
- .get_lease_key = smb2_get_lease_key,
- .set_lease_key = smb2_set_lease_key,
- .new_lease_key = smb2_new_lease_key,
- .calc_signature = smb2_calc_signature,
- .is_read_op = smb2_is_read_op,
- .set_oplock_level = smb2_set_oplock_level,
- .create_lease_buf = smb2_create_lease_buf,
- .parse_lease_buf = smb2_parse_lease_buf,
- .copychunk_range = smb2_copychunk_range,
- .wp_retry_size = smb2_wp_retry_size,
- .dir_needs_close = smb2_dir_needs_close,
- .get_dfs_refer = smb2_get_dfs_refer,
- .select_sectype = smb2_select_sectype,
-#ifdef CONFIG_CIFS_XATTR
- .query_all_EAs = smb2_query_eas,
- .set_EA = smb2_set_ea,
-#endif /* CIFS_XATTR */
- .get_acl = get_smb2_acl,
- .get_acl_by_fid = get_smb2_acl_by_fid,
- .set_acl = set_smb2_acl,
- .next_header = smb2_next_header,
- .ioctl_query_info = smb2_ioctl_query_info,
- .make_node = smb2_make_node,
- .fiemap = smb3_fiemap,
- .llseek = smb3_llseek,
- .is_status_io_timeout = smb2_is_status_io_timeout,
- .is_network_name_deleted = smb2_is_network_name_deleted,
-};
-#endif /* CIFS_ALLOW_INSECURE_LEGACY */
-
-struct smb_version_operations smb21_operations = {
- .compare_fids = smb2_compare_fids,
- .setup_request = smb2_setup_request,
- .setup_async_request = smb2_setup_async_request,
- .check_receive = smb2_check_receive,
- .add_credits = smb2_add_credits,
- .set_credits = smb2_set_credits,
- .get_credits_field = smb2_get_credits_field,
- .get_credits = smb2_get_credits,
- .wait_mtu_credits = smb2_wait_mtu_credits,
- .adjust_credits = smb2_adjust_credits,
- .get_next_mid = smb2_get_next_mid,
- .revert_current_mid = smb2_revert_current_mid,
- .read_data_offset = smb2_read_data_offset,
- .read_data_length = smb2_read_data_length,
- .map_error = map_smb2_to_linux_error,
- .find_mid = smb2_find_mid,
- .check_message = smb2_check_message,
- .dump_detail = smb2_dump_detail,
- .clear_stats = smb2_clear_stats,
- .print_stats = smb2_print_stats,
- .is_oplock_break = smb2_is_valid_oplock_break,
- .handle_cancelled_mid = smb2_handle_cancelled_mid,
- .downgrade_oplock = smb2_downgrade_oplock,
- .need_neg = smb2_need_neg,
- .negotiate = smb2_negotiate,
- .negotiate_wsize = smb2_negotiate_wsize,
- .negotiate_rsize = smb2_negotiate_rsize,
- .sess_setup = SMB2_sess_setup,
- .logoff = SMB2_logoff,
- .tree_connect = SMB2_tcon,
- .tree_disconnect = SMB2_tdis,
- .qfs_tcon = smb2_qfs_tcon,
- .is_path_accessible = smb2_is_path_accessible,
- .can_echo = smb2_can_echo,
- .echo = SMB2_echo,
- .query_path_info = smb2_query_path_info,
- .get_srv_inum = smb2_get_srv_inum,
- .query_file_info = smb2_query_file_info,
- .set_path_size = smb2_set_path_size,
- .set_file_size = smb2_set_file_size,
- .set_file_info = smb2_set_file_info,
- .set_compression = smb2_set_compression,
- .mkdir = smb2_mkdir,
- .mkdir_setinfo = smb2_mkdir_setinfo,
- .rmdir = smb2_rmdir,
- .unlink = smb2_unlink,
- .rename = smb2_rename_path,
- .create_hardlink = smb2_create_hardlink,
- .query_symlink = smb2_query_symlink,
- .query_mf_symlink = smb3_query_mf_symlink,
- .create_mf_symlink = smb3_create_mf_symlink,
- .open = smb2_open_file,
- .set_fid = smb2_set_fid,
- .close = smb2_close_file,
- .flush = smb2_flush_file,
- .async_readv = smb2_async_readv,
- .async_writev = smb2_async_writev,
- .sync_read = smb2_sync_read,
- .sync_write = smb2_sync_write,
- .query_dir_first = smb2_query_dir_first,
- .query_dir_next = smb2_query_dir_next,
- .close_dir = smb2_close_dir,
- .calc_smb_size = smb2_calc_size,
- .is_status_pending = smb2_is_status_pending,
- .is_session_expired = smb2_is_session_expired,
- .oplock_response = smb2_oplock_response,
- .queryfs = smb2_queryfs,
- .mand_lock = smb2_mand_lock,
- .mand_unlock_range = smb2_unlock_range,
- .push_mand_locks = smb2_push_mandatory_locks,
- .get_lease_key = smb2_get_lease_key,
- .set_lease_key = smb2_set_lease_key,
- .new_lease_key = smb2_new_lease_key,
- .calc_signature = smb2_calc_signature,
- .is_read_op = smb21_is_read_op,
- .set_oplock_level = smb21_set_oplock_level,
- .create_lease_buf = smb2_create_lease_buf,
- .parse_lease_buf = smb2_parse_lease_buf,
- .copychunk_range = smb2_copychunk_range,
- .wp_retry_size = smb2_wp_retry_size,
- .dir_needs_close = smb2_dir_needs_close,
- .enum_snapshots = smb3_enum_snapshots,
- .notify = smb3_notify,
- .get_dfs_refer = smb2_get_dfs_refer,
- .select_sectype = smb2_select_sectype,
-#ifdef CONFIG_CIFS_XATTR
- .query_all_EAs = smb2_query_eas,
- .set_EA = smb2_set_ea,
-#endif /* CIFS_XATTR */
- .get_acl = get_smb2_acl,
- .get_acl_by_fid = get_smb2_acl_by_fid,
- .set_acl = set_smb2_acl,
- .next_header = smb2_next_header,
- .ioctl_query_info = smb2_ioctl_query_info,
- .make_node = smb2_make_node,
- .fiemap = smb3_fiemap,
- .llseek = smb3_llseek,
- .is_status_io_timeout = smb2_is_status_io_timeout,
- .is_network_name_deleted = smb2_is_network_name_deleted,
-};
-
-struct smb_version_operations smb30_operations = {
- .compare_fids = smb2_compare_fids,
- .setup_request = smb2_setup_request,
- .setup_async_request = smb2_setup_async_request,
- .check_receive = smb2_check_receive,
- .add_credits = smb2_add_credits,
- .set_credits = smb2_set_credits,
- .get_credits_field = smb2_get_credits_field,
- .get_credits = smb2_get_credits,
- .wait_mtu_credits = smb2_wait_mtu_credits,
- .adjust_credits = smb2_adjust_credits,
- .get_next_mid = smb2_get_next_mid,
- .revert_current_mid = smb2_revert_current_mid,
- .read_data_offset = smb2_read_data_offset,
- .read_data_length = smb2_read_data_length,
- .map_error = map_smb2_to_linux_error,
- .find_mid = smb2_find_mid,
- .check_message = smb2_check_message,
- .dump_detail = smb2_dump_detail,
- .clear_stats = smb2_clear_stats,
- .print_stats = smb2_print_stats,
- .dump_share_caps = smb2_dump_share_caps,
- .is_oplock_break = smb2_is_valid_oplock_break,
- .handle_cancelled_mid = smb2_handle_cancelled_mid,
- .downgrade_oplock = smb3_downgrade_oplock,
- .need_neg = smb2_need_neg,
- .negotiate = smb2_negotiate,
- .negotiate_wsize = smb3_negotiate_wsize,
- .negotiate_rsize = smb3_negotiate_rsize,
- .sess_setup = SMB2_sess_setup,
- .logoff = SMB2_logoff,
- .tree_connect = SMB2_tcon,
- .tree_disconnect = SMB2_tdis,
- .qfs_tcon = smb3_qfs_tcon,
- .is_path_accessible = smb2_is_path_accessible,
- .can_echo = smb2_can_echo,
- .echo = SMB2_echo,
- .query_path_info = smb2_query_path_info,
- /* WSL tags introduced long after smb2.1, enable for SMB3, 3.11 only */
- .query_reparse_tag = smb2_query_reparse_tag,
- .get_srv_inum = smb2_get_srv_inum,
- .query_file_info = smb2_query_file_info,
- .set_path_size = smb2_set_path_size,
- .set_file_size = smb2_set_file_size,
- .set_file_info = smb2_set_file_info,
- .set_compression = smb2_set_compression,
- .mkdir = smb2_mkdir,
- .mkdir_setinfo = smb2_mkdir_setinfo,
- .rmdir = smb2_rmdir,
- .unlink = smb2_unlink,
- .rename = smb2_rename_path,
- .create_hardlink = smb2_create_hardlink,
- .query_symlink = smb2_query_symlink,
- .query_mf_symlink = smb3_query_mf_symlink,
- .create_mf_symlink = smb3_create_mf_symlink,
- .open = smb2_open_file,
- .set_fid = smb2_set_fid,
- .close = smb2_close_file,
- .close_getattr = smb2_close_getattr,
- .flush = smb2_flush_file,
- .async_readv = smb2_async_readv,
- .async_writev = smb2_async_writev,
- .sync_read = smb2_sync_read,
- .sync_write = smb2_sync_write,
- .query_dir_first = smb2_query_dir_first,
- .query_dir_next = smb2_query_dir_next,
- .close_dir = smb2_close_dir,
- .calc_smb_size = smb2_calc_size,
- .is_status_pending = smb2_is_status_pending,
- .is_session_expired = smb2_is_session_expired,
- .oplock_response = smb2_oplock_response,
- .queryfs = smb2_queryfs,
- .mand_lock = smb2_mand_lock,
- .mand_unlock_range = smb2_unlock_range,
- .push_mand_locks = smb2_push_mandatory_locks,
- .get_lease_key = smb2_get_lease_key,
- .set_lease_key = smb2_set_lease_key,
- .new_lease_key = smb2_new_lease_key,
- .generate_signingkey = generate_smb30signingkey,
- .calc_signature = smb3_calc_signature,
- .set_integrity = smb3_set_integrity,
- .is_read_op = smb21_is_read_op,
- .set_oplock_level = smb3_set_oplock_level,
- .create_lease_buf = smb3_create_lease_buf,
- .parse_lease_buf = smb3_parse_lease_buf,
- .copychunk_range = smb2_copychunk_range,
- .duplicate_extents = smb2_duplicate_extents,
- .validate_negotiate = smb3_validate_negotiate,
- .wp_retry_size = smb2_wp_retry_size,
- .dir_needs_close = smb2_dir_needs_close,
- .fallocate = smb3_fallocate,
- .enum_snapshots = smb3_enum_snapshots,
- .notify = smb3_notify,
- .init_transform_rq = smb3_init_transform_rq,
- .is_transform_hdr = smb3_is_transform_hdr,
- .receive_transform = smb3_receive_transform,
- .get_dfs_refer = smb2_get_dfs_refer,
- .select_sectype = smb2_select_sectype,
-#ifdef CONFIG_CIFS_XATTR
- .query_all_EAs = smb2_query_eas,
- .set_EA = smb2_set_ea,
-#endif /* CIFS_XATTR */
- .get_acl = get_smb2_acl,
- .get_acl_by_fid = get_smb2_acl_by_fid,
- .set_acl = set_smb2_acl,
- .next_header = smb2_next_header,
- .ioctl_query_info = smb2_ioctl_query_info,
- .make_node = smb2_make_node,
- .fiemap = smb3_fiemap,
- .llseek = smb3_llseek,
- .is_status_io_timeout = smb2_is_status_io_timeout,
- .is_network_name_deleted = smb2_is_network_name_deleted,
-};
-
-struct smb_version_operations smb311_operations = {
- .compare_fids = smb2_compare_fids,
- .setup_request = smb2_setup_request,
- .setup_async_request = smb2_setup_async_request,
- .check_receive = smb2_check_receive,
- .add_credits = smb2_add_credits,
- .set_credits = smb2_set_credits,
- .get_credits_field = smb2_get_credits_field,
- .get_credits = smb2_get_credits,
- .wait_mtu_credits = smb2_wait_mtu_credits,
- .adjust_credits = smb2_adjust_credits,
- .get_next_mid = smb2_get_next_mid,
- .revert_current_mid = smb2_revert_current_mid,
- .read_data_offset = smb2_read_data_offset,
- .read_data_length = smb2_read_data_length,
- .map_error = map_smb2_to_linux_error,
- .find_mid = smb2_find_mid,
- .check_message = smb2_check_message,
- .dump_detail = smb2_dump_detail,
- .clear_stats = smb2_clear_stats,
- .print_stats = smb2_print_stats,
- .dump_share_caps = smb2_dump_share_caps,
- .is_oplock_break = smb2_is_valid_oplock_break,
- .handle_cancelled_mid = smb2_handle_cancelled_mid,
- .downgrade_oplock = smb3_downgrade_oplock,
- .need_neg = smb2_need_neg,
- .negotiate = smb2_negotiate,
- .negotiate_wsize = smb3_negotiate_wsize,
- .negotiate_rsize = smb3_negotiate_rsize,
- .sess_setup = SMB2_sess_setup,
- .logoff = SMB2_logoff,
- .tree_connect = SMB2_tcon,
- .tree_disconnect = SMB2_tdis,
- .qfs_tcon = smb3_qfs_tcon,
- .is_path_accessible = smb2_is_path_accessible,
- .can_echo = smb2_can_echo,
- .echo = SMB2_echo,
- .query_path_info = smb2_query_path_info,
- .query_reparse_tag = smb2_query_reparse_tag,
- .get_srv_inum = smb2_get_srv_inum,
- .query_file_info = smb2_query_file_info,
- .set_path_size = smb2_set_path_size,
- .set_file_size = smb2_set_file_size,
- .set_file_info = smb2_set_file_info,
- .set_compression = smb2_set_compression,
- .mkdir = smb2_mkdir,
- .mkdir_setinfo = smb2_mkdir_setinfo,
- .posix_mkdir = smb311_posix_mkdir,
- .rmdir = smb2_rmdir,
- .unlink = smb2_unlink,
- .rename = smb2_rename_path,
- .create_hardlink = smb2_create_hardlink,
- .query_symlink = smb2_query_symlink,
- .query_mf_symlink = smb3_query_mf_symlink,
- .create_mf_symlink = smb3_create_mf_symlink,
- .open = smb2_open_file,
- .set_fid = smb2_set_fid,
- .close = smb2_close_file,
- .close_getattr = smb2_close_getattr,
- .flush = smb2_flush_file,
- .async_readv = smb2_async_readv,
- .async_writev = smb2_async_writev,
- .sync_read = smb2_sync_read,
- .sync_write = smb2_sync_write,
- .query_dir_first = smb2_query_dir_first,
- .query_dir_next = smb2_query_dir_next,
- .close_dir = smb2_close_dir,
- .calc_smb_size = smb2_calc_size,
- .is_status_pending = smb2_is_status_pending,
- .is_session_expired = smb2_is_session_expired,
- .oplock_response = smb2_oplock_response,
- .queryfs = smb311_queryfs,
- .mand_lock = smb2_mand_lock,
- .mand_unlock_range = smb2_unlock_range,
- .push_mand_locks = smb2_push_mandatory_locks,
- .get_lease_key = smb2_get_lease_key,
- .set_lease_key = smb2_set_lease_key,
- .new_lease_key = smb2_new_lease_key,
- .generate_signingkey = generate_smb311signingkey,
- .calc_signature = smb3_calc_signature,
- .set_integrity = smb3_set_integrity,
- .is_read_op = smb21_is_read_op,
- .set_oplock_level = smb3_set_oplock_level,
- .create_lease_buf = smb3_create_lease_buf,
- .parse_lease_buf = smb3_parse_lease_buf,
- .copychunk_range = smb2_copychunk_range,
- .duplicate_extents = smb2_duplicate_extents,
-/* .validate_negotiate = smb3_validate_negotiate, */ /* not used in 3.11 */
- .wp_retry_size = smb2_wp_retry_size,
- .dir_needs_close = smb2_dir_needs_close,
- .fallocate = smb3_fallocate,
- .enum_snapshots = smb3_enum_snapshots,
- .notify = smb3_notify,
- .init_transform_rq = smb3_init_transform_rq,
- .is_transform_hdr = smb3_is_transform_hdr,
- .receive_transform = smb3_receive_transform,
- .get_dfs_refer = smb2_get_dfs_refer,
- .select_sectype = smb2_select_sectype,
-#ifdef CONFIG_CIFS_XATTR
- .query_all_EAs = smb2_query_eas,
- .set_EA = smb2_set_ea,
-#endif /* CIFS_XATTR */
- .get_acl = get_smb2_acl,
- .get_acl_by_fid = get_smb2_acl_by_fid,
- .set_acl = set_smb2_acl,
- .next_header = smb2_next_header,
- .ioctl_query_info = smb2_ioctl_query_info,
- .make_node = smb2_make_node,
- .fiemap = smb3_fiemap,
- .llseek = smb3_llseek,
- .is_status_io_timeout = smb2_is_status_io_timeout,
- .is_network_name_deleted = smb2_is_network_name_deleted,
-};
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-struct smb_version_values smb20_values = {
- .version_string = SMB20_VERSION_STRING,
- .protocol_id = SMB20_PROT_ID,
- .req_capabilities = 0, /* MBZ */
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .header_preamble_size = 0,
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .create_lease_size = sizeof(struct create_lease),
-};
-#endif /* ALLOW_INSECURE_LEGACY */
-
-struct smb_version_values smb21_values = {
- .version_string = SMB21_VERSION_STRING,
- .protocol_id = SMB21_PROT_ID,
- .req_capabilities = 0, /* MBZ on negotiate req until SMB3 dialect */
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .header_preamble_size = 0,
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .create_lease_size = sizeof(struct create_lease),
-};
-
-struct smb_version_values smb3any_values = {
- .version_string = SMB3ANY_VERSION_STRING,
- .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
- .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .header_preamble_size = 0,
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .create_lease_size = sizeof(struct create_lease_v2),
-};
-
-struct smb_version_values smbdefault_values = {
- .version_string = SMBDEFAULT_VERSION_STRING,
- .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
- .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .header_preamble_size = 0,
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .create_lease_size = sizeof(struct create_lease_v2),
-};
-
-struct smb_version_values smb30_values = {
- .version_string = SMB30_VERSION_STRING,
- .protocol_id = SMB30_PROT_ID,
- .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .header_preamble_size = 0,
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .create_lease_size = sizeof(struct create_lease_v2),
-};
-
-struct smb_version_values smb302_values = {
- .version_string = SMB302_VERSION_STRING,
- .protocol_id = SMB302_PROT_ID,
- .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .header_preamble_size = 0,
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .create_lease_size = sizeof(struct create_lease_v2),
-};
-
-struct smb_version_values smb311_values = {
- .version_string = SMB311_VERSION_STRING,
- .protocol_id = SMB311_PROT_ID,
- .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .header_preamble_size = 0,
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
- .create_lease_size = sizeof(struct create_lease_v2),
-};
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
deleted file mode 100644
index 537e8679900b..000000000000
--- a/fs/cifs/smb2pdu.c
+++ /dev/null
@@ -1,5722 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2009, 2013
- * Etersoft, 2012
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Pavel Shilovsky (pshilovsky@samba.org) 2012
- *
- * Contains the routines for constructing the SMB2 PDUs themselves
- *
- */
-
- /* SMB2 PDU handling routines here - except for leftovers (eg session setup) */
- /* Note that there are handle based routines which must be */
- /* treated slightly differently for reconnection purposes since we never */
- /* want to reuse a stale file handle and only the caller knows the file info */
-
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/vfs.h>
-#include <linux/task_io_accounting_ops.h>
-#include <linux/uaccess.h>
-#include <linux/uuid.h>
-#include <linux/pagemap.h>
-#include <linux/xattr.h>
-#include "cifsglob.h"
-#include "cifsacl.h"
-#include "cifsproto.h"
-#include "smb2proto.h"
-#include "cifs_unicode.h"
-#include "cifs_debug.h"
-#include "ntlmssp.h"
-#include "smb2status.h"
-#include "smb2glob.h"
-#include "cifspdu.h"
-#include "cifs_spnego.h"
-#include "smbdirect.h"
-#include "trace.h"
-#ifdef CONFIG_CIFS_DFS_UPCALL
-#include "dfs_cache.h"
-#endif
-#include "cached_dir.h"
-
-/*
- * The following table defines the expected "StructureSize" of SMB2 requests
- * in order by SMB2 command. This is similar to "wct" in SMB/CIFS requests.
- *
- * Note that commands are defined in smb2pdu.h in le16 but the array below is
- * indexed by command in host byte order.
- */
-static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
- /* SMB2_NEGOTIATE */ 36,
- /* SMB2_SESSION_SETUP */ 25,
- /* SMB2_LOGOFF */ 4,
- /* SMB2_TREE_CONNECT */ 9,
- /* SMB2_TREE_DISCONNECT */ 4,
- /* SMB2_CREATE */ 57,
- /* SMB2_CLOSE */ 24,
- /* SMB2_FLUSH */ 24,
- /* SMB2_READ */ 49,
- /* SMB2_WRITE */ 49,
- /* SMB2_LOCK */ 48,
- /* SMB2_IOCTL */ 57,
- /* SMB2_CANCEL */ 4,
- /* SMB2_ECHO */ 4,
- /* SMB2_QUERY_DIRECTORY */ 33,
- /* SMB2_CHANGE_NOTIFY */ 32,
- /* SMB2_QUERY_INFO */ 41,
- /* SMB2_SET_INFO */ 33,
- /* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */
-};
-
-int smb3_encryption_required(const struct cifs_tcon *tcon)
-{
- if (!tcon || !tcon->ses)
- return 0;
- if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
- (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
- return 1;
- if (tcon->seal &&
- (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
- return 1;
- return 0;
-}
-
-static void
-smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd,
- const struct cifs_tcon *tcon,
- struct TCP_Server_Info *server)
-{
- shdr->ProtocolId = SMB2_PROTO_NUMBER;
- shdr->StructureSize = cpu_to_le16(64);
- shdr->Command = smb2_cmd;
- if (server) {
- spin_lock(&server->req_lock);
- /* Request up to 10 credits but don't go over the limit. */
- if (server->credits >= server->max_credits)
- shdr->CreditRequest = cpu_to_le16(0);
- else
- shdr->CreditRequest = cpu_to_le16(
- min_t(int, server->max_credits -
- server->credits, 10));
- spin_unlock(&server->req_lock);
- } else {
- shdr->CreditRequest = cpu_to_le16(2);
- }
- shdr->Id.SyncId.ProcessId = cpu_to_le32((__u16)current->tgid);
-
- if (!tcon)
- goto out;
-
- /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */
- /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */
- if (server && (server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
- shdr->CreditCharge = cpu_to_le16(1);
- /* else CreditCharge MBZ */
-
- shdr->Id.SyncId.TreeId = cpu_to_le32(tcon->tid);
- /* Uid is not converted */
- if (tcon->ses)
- shdr->SessionId = cpu_to_le64(tcon->ses->Suid);
-
- /*
- * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have
- * to pass the path on the Open SMB prefixed by \\server\share.
- * Not sure when we would need to do the augmented path (if ever) and
- * setting this flag breaks the SMB2 open operation since it is
- * illegal to send an empty path name (without \\server\share prefix)
- * when the DFS flag is set in the SMB open header. We could
- * consider setting the flag on all operations other than open
- * but it is safer to net set it for now.
- */
-/* if (tcon->share_flags & SHI1005_FLAGS_DFS)
- shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */
-
- if (server && server->sign && !smb3_encryption_required(tcon))
- shdr->Flags |= SMB2_FLAGS_SIGNED;
-out:
- return;
-}
-
-static int
-smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
- struct TCP_Server_Info *server)
-{
- int rc = 0;
- struct nls_table *nls_codepage = NULL;
- struct cifs_ses *ses;
-
- /*
- * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
- * check for tcp and smb session status done differently
- * for those three - in the calling routine.
- */
- if (tcon == NULL)
- return 0;
-
- /*
- * Need to also skip SMB2_IOCTL because it is used for checking nested dfs links in
- * cifs_tree_connect().
- */
- if (smb2_command == SMB2_TREE_CONNECT || smb2_command == SMB2_IOCTL)
- return 0;
-
- spin_lock(&tcon->tc_lock);
- if (tcon->status == TID_EXITING) {
- /*
- * only tree disconnect allowed when disconnecting ...
- */
- if (smb2_command != SMB2_TREE_DISCONNECT) {
- spin_unlock(&tcon->tc_lock);
- cifs_dbg(FYI, "can not send cmd %d while umounting\n",
- smb2_command);
- return -ENODEV;
- }
- }
- spin_unlock(&tcon->tc_lock);
-
- ses = tcon->ses;
- if (!ses)
- return -EIO;
- spin_lock(&ses->ses_lock);
- if (ses->ses_status == SES_EXITING) {
- spin_unlock(&ses->ses_lock);
- return -EIO;
- }
- spin_unlock(&ses->ses_lock);
- if (!ses->server || !server)
- return -EIO;
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsNeedReconnect) {
- /*
- * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE
- * here since they are implicitly done when session drops.
- */
- switch (smb2_command) {
- /*
- * BB Should we keep oplock break and add flush to exceptions?
- */
- case SMB2_TREE_DISCONNECT:
- case SMB2_CANCEL:
- case SMB2_CLOSE:
- case SMB2_OPLOCK_BREAK:
- spin_unlock(&server->srv_lock);
- return -EAGAIN;
- }
- }
- spin_unlock(&server->srv_lock);
-
-again:
- rc = cifs_wait_for_server_reconnect(server, tcon->retry);
- if (rc)
- return rc;
-
- spin_lock(&ses->chan_lock);
- if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
- spin_unlock(&ses->chan_lock);
- return 0;
- }
- spin_unlock(&ses->chan_lock);
- cifs_dbg(FYI, "sess reconnect mask: 0x%lx, tcon reconnect: %d",
- tcon->ses->chans_need_reconnect,
- tcon->need_reconnect);
-
- mutex_lock(&ses->session_mutex);
- /*
- * Recheck after acquire mutex. If another thread is negotiating
- * and the server never sends an answer the socket will be closed
- * and tcpStatus set to reconnect.
- */
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsNeedReconnect) {
- spin_unlock(&server->srv_lock);
- mutex_unlock(&ses->session_mutex);
-
- if (tcon->retry)
- goto again;
-
- rc = -EHOSTDOWN;
- goto out;
- }
- spin_unlock(&server->srv_lock);
-
- nls_codepage = load_nls_default();
-
- /*
- * need to prevent multiple threads trying to simultaneously
- * reconnect the same SMB session
- */
- spin_lock(&ses->ses_lock);
- spin_lock(&ses->chan_lock);
- if (!cifs_chan_needs_reconnect(ses, server) &&
- ses->ses_status == SES_GOOD) {
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
- /* this means that we only need to tree connect */
- if (tcon->need_reconnect)
- goto skip_sess_setup;
-
- mutex_unlock(&ses->session_mutex);
- goto out;
- }
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
-
- rc = cifs_negotiate_protocol(0, ses, server);
- if (!rc) {
- rc = cifs_setup_session(0, ses, server, nls_codepage);
- if ((rc == -EACCES) && !tcon->retry) {
- mutex_unlock(&ses->session_mutex);
- rc = -EHOSTDOWN;
- goto failed;
- } else if (rc) {
- mutex_unlock(&ses->session_mutex);
- goto out;
- }
- } else {
- mutex_unlock(&ses->session_mutex);
- goto out;
- }
-
-skip_sess_setup:
- if (!tcon->need_reconnect) {
- mutex_unlock(&ses->session_mutex);
- goto out;
- }
- cifs_mark_open_files_invalid(tcon);
- if (tcon->use_persistent)
- tcon->need_reopen_files = true;
-
- rc = cifs_tree_connect(0, tcon, nls_codepage);
- mutex_unlock(&ses->session_mutex);
-
- cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
- if (rc) {
- /* If sess reconnected but tcon didn't, something strange ... */
- cifs_dbg(VFS, "reconnect tcon failed rc = %d\n", rc);
- goto out;
- }
-
- if (smb2_command != SMB2_INTERNAL_CMD)
- mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
-
- atomic_inc(&tconInfoReconnectCount);
-out:
- /*
- * Check if handle based operation so we know whether we can continue
- * or not without returning to caller to reset file handle.
- */
- /*
- * BB Is flush done by server on drop of tcp session? Should we special
- * case it and skip above?
- */
- switch (smb2_command) {
- case SMB2_FLUSH:
- case SMB2_READ:
- case SMB2_WRITE:
- case SMB2_LOCK:
- case SMB2_IOCTL:
- case SMB2_QUERY_DIRECTORY:
- case SMB2_CHANGE_NOTIFY:
- case SMB2_QUERY_INFO:
- case SMB2_SET_INFO:
- rc = -EAGAIN;
- }
-failed:
- unload_nls(nls_codepage);
- return rc;
-}
-
-static void
-fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- void *buf,
- unsigned int *total_len)
-{
- struct smb2_pdu *spdu = buf;
- /* lookup word count ie StructureSize from table */
- __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_command)];
-
- /*
- * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of
- * largest operations (Create)
- */
- memset(buf, 0, 256);
-
- smb2_hdr_assemble(&spdu->hdr, smb2_command, tcon, server);
- spdu->StructureSize2 = cpu_to_le16(parmsize);
-
- *total_len = parmsize + sizeof(struct smb2_hdr);
-}
-
-/*
- * Allocate and return pointer to an SMB request hdr, and set basic
- * SMB information in the SMB header. If the return code is zero, this
- * function must have filled in request_buf pointer.
- */
-static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- void **request_buf, unsigned int *total_len)
-{
- /* BB eventually switch this to SMB2 specific small buf size */
- if (smb2_command == SMB2_SET_INFO)
- *request_buf = cifs_buf_get();
- else
- *request_buf = cifs_small_buf_get();
- if (*request_buf == NULL) {
- /* BB should we add a retry in here if not a writepage? */
- return -ENOMEM;
- }
-
- fill_small_buf(smb2_command, tcon, server,
- (struct smb2_hdr *)(*request_buf),
- total_len);
-
- if (tcon != NULL) {
- uint16_t com_code = le16_to_cpu(smb2_command);
- cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
- cifs_stats_inc(&tcon->num_smbs_sent);
- }
-
- return 0;
-}
-
-static int smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- void **request_buf, unsigned int *total_len)
-{
- int rc;
-
- rc = smb2_reconnect(smb2_command, tcon, server);
- if (rc)
- return rc;
-
- return __smb2_plain_req_init(smb2_command, tcon, server, request_buf,
- total_len);
-}
-
-static int smb2_ioctl_req_init(u32 opcode, struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- void **request_buf, unsigned int *total_len)
-{
- /* Skip reconnect only for FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs */
- if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) {
- return __smb2_plain_req_init(SMB2_IOCTL, tcon, server,
- request_buf, total_len);
- }
- return smb2_plain_req_init(SMB2_IOCTL, tcon, server,
- request_buf, total_len);
-}
-
-/* For explanation of negotiate contexts see MS-SMB2 section 2.2.3.1 */
-
-static void
-build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt)
-{
- pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES;
- pneg_ctxt->DataLength = cpu_to_le16(38);
- pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1);
- pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE);
- get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE);
- pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512;
-}
-
-static void
-build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt)
-{
- pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES;
- pneg_ctxt->DataLength =
- cpu_to_le16(sizeof(struct smb2_compression_capabilities_context)
- - sizeof(struct smb2_neg_context));
- pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(3);
- pneg_ctxt->CompressionAlgorithms[0] = SMB3_COMPRESS_LZ77;
- pneg_ctxt->CompressionAlgorithms[1] = SMB3_COMPRESS_LZ77_HUFF;
- pneg_ctxt->CompressionAlgorithms[2] = SMB3_COMPRESS_LZNT1;
-}
-
-static unsigned int
-build_signing_ctxt(struct smb2_signing_capabilities *pneg_ctxt)
-{
- unsigned int ctxt_len = sizeof(struct smb2_signing_capabilities);
- unsigned short num_algs = 1; /* number of signing algorithms sent */
-
- pneg_ctxt->ContextType = SMB2_SIGNING_CAPABILITIES;
- /*
- * Context Data length must be rounded to multiple of 8 for some servers
- */
- pneg_ctxt->DataLength = cpu_to_le16(ALIGN(sizeof(struct smb2_signing_capabilities) -
- sizeof(struct smb2_neg_context) +
- (num_algs * sizeof(u16)), 8));
- pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(num_algs);
- pneg_ctxt->SigningAlgorithms[0] = cpu_to_le16(SIGNING_ALG_AES_CMAC);
-
- ctxt_len += sizeof(__le16) * num_algs;
- ctxt_len = ALIGN(ctxt_len, 8);
- return ctxt_len;
- /* TBD add SIGNING_ALG_AES_GMAC and/or SIGNING_ALG_HMAC_SHA256 */
-}
-
-static void
-build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
-{
- pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
- if (require_gcm_256) {
- pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + 1 cipher */
- pneg_ctxt->CipherCount = cpu_to_le16(1);
- pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES256_GCM;
- } else if (enable_gcm_256) {
- pneg_ctxt->DataLength = cpu_to_le16(8); /* Cipher Count + 3 ciphers */
- pneg_ctxt->CipherCount = cpu_to_le16(3);
- pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;
- pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES256_GCM;
- pneg_ctxt->Ciphers[2] = SMB2_ENCRYPTION_AES128_CCM;
- } else {
- pneg_ctxt->DataLength = cpu_to_le16(6); /* Cipher Count + 2 ciphers */
- pneg_ctxt->CipherCount = cpu_to_le16(2);
- pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;
- pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES128_CCM;
- }
-}
-
-static unsigned int
-build_netname_ctxt(struct smb2_netname_neg_context *pneg_ctxt, char *hostname)
-{
- struct nls_table *cp = load_nls_default();
-
- pneg_ctxt->ContextType = SMB2_NETNAME_NEGOTIATE_CONTEXT_ID;
-
- /* copy up to max of first 100 bytes of server name to NetName field */
- pneg_ctxt->DataLength = cpu_to_le16(2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp));
- /* context size is DataLength + minimal smb2_neg_context */
- return ALIGN(le16_to_cpu(pneg_ctxt->DataLength) + sizeof(struct smb2_neg_context), 8);
-}
-
-static void
-build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
-{
- pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE;
- pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
- /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
- pneg_ctxt->Name[0] = 0x93;
- pneg_ctxt->Name[1] = 0xAD;
- pneg_ctxt->Name[2] = 0x25;
- pneg_ctxt->Name[3] = 0x50;
- pneg_ctxt->Name[4] = 0x9C;
- pneg_ctxt->Name[5] = 0xB4;
- pneg_ctxt->Name[6] = 0x11;
- pneg_ctxt->Name[7] = 0xE7;
- pneg_ctxt->Name[8] = 0xB4;
- pneg_ctxt->Name[9] = 0x23;
- pneg_ctxt->Name[10] = 0x83;
- pneg_ctxt->Name[11] = 0xDE;
- pneg_ctxt->Name[12] = 0x96;
- pneg_ctxt->Name[13] = 0x8B;
- pneg_ctxt->Name[14] = 0xCD;
- pneg_ctxt->Name[15] = 0x7C;
-}
-
-static void
-assemble_neg_contexts(struct smb2_negotiate_req *req,
- struct TCP_Server_Info *server, unsigned int *total_len)
-{
- unsigned int ctxt_len, neg_context_count;
- struct TCP_Server_Info *pserver;
- char *pneg_ctxt;
- char *hostname;
-
- if (*total_len > 200) {
- /* In case length corrupted don't want to overrun smb buffer */
- cifs_server_dbg(VFS, "Bad frame length assembling neg contexts\n");
- return;
- }
-
- /*
- * round up total_len of fixed part of SMB3 negotiate request to 8
- * byte boundary before adding negotiate contexts
- */
- *total_len = ALIGN(*total_len, 8);
-
- pneg_ctxt = (*total_len) + (char *)req;
- req->NegotiateContextOffset = cpu_to_le32(*total_len);
-
- build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt);
- ctxt_len = ALIGN(sizeof(struct smb2_preauth_neg_context), 8);
- *total_len += ctxt_len;
- pneg_ctxt += ctxt_len;
-
- build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt);
- ctxt_len = ALIGN(sizeof(struct smb2_encryption_neg_context), 8);
- *total_len += ctxt_len;
- pneg_ctxt += ctxt_len;
-
- /*
- * secondary channels don't have the hostname field populated
- * use the hostname field in the primary channel instead
- */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
- cifs_server_lock(pserver);
- hostname = pserver->hostname;
- if (hostname && (hostname[0] != 0)) {
- ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt,
- hostname);
- *total_len += ctxt_len;
- pneg_ctxt += ctxt_len;
- neg_context_count = 3;
- } else
- neg_context_count = 2;
- cifs_server_unlock(pserver);
-
- build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
- *total_len += sizeof(struct smb2_posix_neg_context);
- pneg_ctxt += sizeof(struct smb2_posix_neg_context);
- neg_context_count++;
-
- if (server->compress_algorithm) {
- build_compression_ctxt((struct smb2_compression_capabilities_context *)
- pneg_ctxt);
- ctxt_len = ALIGN(sizeof(struct smb2_compression_capabilities_context), 8);
- *total_len += ctxt_len;
- pneg_ctxt += ctxt_len;
- neg_context_count++;
- }
-
- if (enable_negotiate_signing) {
- ctxt_len = build_signing_ctxt((struct smb2_signing_capabilities *)
- pneg_ctxt);
- *total_len += ctxt_len;
- pneg_ctxt += ctxt_len;
- neg_context_count++;
- }
-
- /* check for and add transport_capabilities and signing capabilities */
- req->NegotiateContextCount = cpu_to_le16(neg_context_count);
-
-}
-
-/* If invalid preauth context warn but use what we requested, SHA-512 */
-static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
-{
- unsigned int len = le16_to_cpu(ctxt->DataLength);
-
- /*
- * Caller checked that DataLength remains within SMB boundary. We still
- * need to confirm that one HashAlgorithms member is accounted for.
- */
- if (len < MIN_PREAUTH_CTXT_DATA_LEN) {
- pr_warn_once("server sent bad preauth context\n");
- return;
- } else if (len < MIN_PREAUTH_CTXT_DATA_LEN + le16_to_cpu(ctxt->SaltLength)) {
- pr_warn_once("server sent invalid SaltLength\n");
- return;
- }
- if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1)
- pr_warn_once("Invalid SMB3 hash algorithm count\n");
- if (ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
- pr_warn_once("unknown SMB3 hash algorithm\n");
-}
-
-static void decode_compress_ctx(struct TCP_Server_Info *server,
- struct smb2_compression_capabilities_context *ctxt)
-{
- unsigned int len = le16_to_cpu(ctxt->DataLength);
-
- /*
- * Caller checked that DataLength remains within SMB boundary. We still
- * need to confirm that one CompressionAlgorithms member is accounted
- * for.
- */
- if (len < 10) {
- pr_warn_once("server sent bad compression cntxt\n");
- return;
- }
- if (le16_to_cpu(ctxt->CompressionAlgorithmCount) != 1) {
- pr_warn_once("Invalid SMB3 compress algorithm count\n");
- return;
- }
- if (le16_to_cpu(ctxt->CompressionAlgorithms[0]) > 3) {
- pr_warn_once("unknown compression algorithm\n");
- return;
- }
- server->compress_algorithm = ctxt->CompressionAlgorithms[0];
-}
-
-static int decode_encrypt_ctx(struct TCP_Server_Info *server,
- struct smb2_encryption_neg_context *ctxt)
-{
- unsigned int len = le16_to_cpu(ctxt->DataLength);
-
- cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d\n", len);
- /*
- * Caller checked that DataLength remains within SMB boundary. We still
- * need to confirm that one Cipher flexible array member is accounted
- * for.
- */
- if (len < MIN_ENCRYPT_CTXT_DATA_LEN) {
- pr_warn_once("server sent bad crypto ctxt len\n");
- return -EINVAL;
- }
-
- if (le16_to_cpu(ctxt->CipherCount) != 1) {
- pr_warn_once("Invalid SMB3.11 cipher count\n");
- return -EINVAL;
- }
- cifs_dbg(FYI, "SMB311 cipher type:%d\n", le16_to_cpu(ctxt->Ciphers[0]));
- if (require_gcm_256) {
- if (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES256_GCM) {
- cifs_dbg(VFS, "Server does not support requested encryption type (AES256 GCM)\n");
- return -EOPNOTSUPP;
- }
- } else if (ctxt->Ciphers[0] == 0) {
- /*
- * e.g. if server only supported AES256_CCM (very unlikely)
- * or server supported no encryption types or had all disabled.
- * Since GLOBAL_CAP_ENCRYPTION will be not set, in the case
- * in which mount requested encryption ("seal") checks later
- * on during tree connection will return proper rc, but if
- * seal not requested by client, since server is allowed to
- * return 0 to indicate no supported cipher, we can't fail here
- */
- server->cipher_type = 0;
- server->capabilities &= ~SMB2_GLOBAL_CAP_ENCRYPTION;
- pr_warn_once("Server does not support requested encryption types\n");
- return 0;
- } else if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) &&
- (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM) &&
- (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES256_GCM)) {
- /* server returned a cipher we didn't ask for */
- pr_warn_once("Invalid SMB3.11 cipher returned\n");
- return -EINVAL;
- }
- server->cipher_type = ctxt->Ciphers[0];
- server->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
- return 0;
-}
-
-static void decode_signing_ctx(struct TCP_Server_Info *server,
- struct smb2_signing_capabilities *pctxt)
-{
- unsigned int len = le16_to_cpu(pctxt->DataLength);
-
- /*
- * Caller checked that DataLength remains within SMB boundary. We still
- * need to confirm that one SigningAlgorithms flexible array member is
- * accounted for.
- */
- if ((len < 4) || (len > 16)) {
- pr_warn_once("server sent bad signing negcontext\n");
- return;
- }
- if (le16_to_cpu(pctxt->SigningAlgorithmCount) != 1) {
- pr_warn_once("Invalid signing algorithm count\n");
- return;
- }
- if (le16_to_cpu(pctxt->SigningAlgorithms[0]) > 2) {
- pr_warn_once("unknown signing algorithm\n");
- return;
- }
-
- server->signing_negotiated = true;
- server->signing_algorithm = le16_to_cpu(pctxt->SigningAlgorithms[0]);
- cifs_dbg(FYI, "signing algorithm %d chosen\n",
- server->signing_algorithm);
-}
-
-
-static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
- struct TCP_Server_Info *server,
- unsigned int len_of_smb)
-{
- struct smb2_neg_context *pctx;
- unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset);
- unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount);
- unsigned int len_of_ctxts, i;
- int rc = 0;
-
- cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt);
- if (len_of_smb <= offset) {
- cifs_server_dbg(VFS, "Invalid response: negotiate context offset\n");
- return -EINVAL;
- }
-
- len_of_ctxts = len_of_smb - offset;
-
- for (i = 0; i < ctxt_cnt; i++) {
- int clen;
- /* check that offset is not beyond end of SMB */
- if (len_of_ctxts < sizeof(struct smb2_neg_context))
- break;
-
- pctx = (struct smb2_neg_context *)(offset + (char *)rsp);
- clen = sizeof(struct smb2_neg_context)
- + le16_to_cpu(pctx->DataLength);
- /*
- * 2.2.4 SMB2 NEGOTIATE Response
- * Subsequent negotiate contexts MUST appear at the first 8-byte
- * aligned offset following the previous negotiate context.
- */
- if (i + 1 != ctxt_cnt)
- clen = ALIGN(clen, 8);
- if (clen > len_of_ctxts)
- break;
-
- if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES)
- decode_preauth_context(
- (struct smb2_preauth_neg_context *)pctx);
- else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES)
- rc = decode_encrypt_ctx(server,
- (struct smb2_encryption_neg_context *)pctx);
- else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES)
- decode_compress_ctx(server,
- (struct smb2_compression_capabilities_context *)pctx);
- else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE)
- server->posix_ext_supported = true;
- else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES)
- decode_signing_ctx(server,
- (struct smb2_signing_capabilities *)pctx);
- else
- cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n",
- le16_to_cpu(pctx->ContextType));
- if (rc)
- break;
-
- offset += clen;
- len_of_ctxts -= clen;
- }
- return rc;
-}
-
-static struct create_posix *
-create_posix_buf(umode_t mode)
-{
- struct create_posix *buf;
-
- buf = kzalloc(sizeof(struct create_posix),
- GFP_KERNEL);
- if (!buf)
- return NULL;
-
- buf->ccontext.DataOffset =
- cpu_to_le16(offsetof(struct create_posix, Mode));
- buf->ccontext.DataLength = cpu_to_le32(4);
- buf->ccontext.NameOffset =
- cpu_to_le16(offsetof(struct create_posix, Name));
- buf->ccontext.NameLength = cpu_to_le16(16);
-
- /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
- buf->Name[0] = 0x93;
- buf->Name[1] = 0xAD;
- buf->Name[2] = 0x25;
- buf->Name[3] = 0x50;
- buf->Name[4] = 0x9C;
- buf->Name[5] = 0xB4;
- buf->Name[6] = 0x11;
- buf->Name[7] = 0xE7;
- buf->Name[8] = 0xB4;
- buf->Name[9] = 0x23;
- buf->Name[10] = 0x83;
- buf->Name[11] = 0xDE;
- buf->Name[12] = 0x96;
- buf->Name[13] = 0x8B;
- buf->Name[14] = 0xCD;
- buf->Name[15] = 0x7C;
- buf->Mode = cpu_to_le32(mode);
- cifs_dbg(FYI, "mode on posix create 0%o\n", mode);
- return buf;
-}
-
-static int
-add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
-{
- struct smb2_create_req *req = iov[0].iov_base;
- unsigned int num = *num_iovec;
-
- iov[num].iov_base = create_posix_buf(mode);
- if (mode == ACL_NO_MODE)
- cifs_dbg(FYI, "Invalid mode\n");
- if (iov[num].iov_base == NULL)
- return -ENOMEM;
- iov[num].iov_len = sizeof(struct create_posix);
- if (!req->CreateContextsOffset)
- req->CreateContextsOffset = cpu_to_le32(
- sizeof(struct smb2_create_req) +
- iov[num - 1].iov_len);
- le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_posix));
- *num_iovec = num + 1;
- return 0;
-}
-
-
-/*
- *
- * SMB2 Worker functions follow:
- *
- * The general structure of the worker functions is:
- * 1) Call smb2_init (assembles SMB2 header)
- * 2) Initialize SMB2 command specific fields in fixed length area of SMB
- * 3) Call smb_sendrcv2 (sends request on socket and waits for response)
- * 4) Decode SMB2 command specific fields in the fixed length area
- * 5) Decode variable length data area (if any for this SMB2 command type)
- * 6) Call free smb buffer
- * 7) return
- *
- */
-
-int
-SMB2_negotiate(const unsigned int xid,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-{
- struct smb_rqst rqst;
- struct smb2_negotiate_req *req;
- struct smb2_negotiate_rsp *rsp;
- struct kvec iov[1];
- struct kvec rsp_iov;
- int rc;
- int resp_buftype;
- int blob_offset, blob_length;
- char *security_blob;
- int flags = CIFS_NEG_OP;
- unsigned int total_len;
-
- cifs_dbg(FYI, "Negotiate protocol\n");
-
- if (!server) {
- WARN(1, "%s: server is NULL!\n", __func__);
- return -EIO;
- }
-
- rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- req->hdr.SessionId = 0;
-
- memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
- memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
-
- if (strcmp(server->vals->version_string,
- SMB3ANY_VERSION_STRING) == 0) {
- req->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
- req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
- req->Dialects[2] = cpu_to_le16(SMB311_PROT_ID);
- req->DialectCount = cpu_to_le16(3);
- total_len += 6;
- } else if (strcmp(server->vals->version_string,
- SMBDEFAULT_VERSION_STRING) == 0) {
- req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
- req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
- req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
- req->Dialects[3] = cpu_to_le16(SMB311_PROT_ID);
- req->DialectCount = cpu_to_le16(4);
- total_len += 8;
- } else {
- /* otherwise send specific dialect */
- req->Dialects[0] = cpu_to_le16(server->vals->protocol_id);
- req->DialectCount = cpu_to_le16(1);
- total_len += 2;
- }
-
- /* only one of SMB2 signing flags may be set in SMB2 request */
- if (ses->sign)
- req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
- else if (global_secflags & CIFSSEC_MAY_SIGN)
- req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
- else
- req->SecurityMode = 0;
-
- req->Capabilities = cpu_to_le32(server->vals->req_capabilities);
- if (ses->chan_max > 1)
- req->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL);
-
- /* ClientGUID must be zero for SMB2.02 dialect */
- if (server->vals->protocol_id == SMB20_PROT_ID)
- memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE);
- else {
- memcpy(req->ClientGUID, server->client_guid,
- SMB2_CLIENT_GUID_SIZE);
- if ((server->vals->protocol_id == SMB311_PROT_ID) ||
- (strcmp(server->vals->version_string,
- SMB3ANY_VERSION_STRING) == 0) ||
- (strcmp(server->vals->version_string,
- SMBDEFAULT_VERSION_STRING) == 0))
- assemble_neg_contexts(req, server, &total_len);
- }
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- cifs_small_buf_release(req);
- rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base;
- /*
- * No tcon so can't do
- * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
- */
- if (rc == -EOPNOTSUPP) {
- cifs_server_dbg(VFS, "Dialect not supported by server. Consider specifying vers=1.0 or vers=2.0 on mount for accessing older servers\n");
- goto neg_exit;
- } else if (rc != 0)
- goto neg_exit;
-
- rc = -EIO;
- if (strcmp(server->vals->version_string,
- SMB3ANY_VERSION_STRING) == 0) {
- if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
- cifs_server_dbg(VFS,
- "SMB2 dialect returned but not requested\n");
- goto neg_exit;
- } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
- cifs_server_dbg(VFS,
- "SMB2.1 dialect returned but not requested\n");
- goto neg_exit;
- } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
- /* ops set to 3.0 by default for default so update */
- server->ops = &smb311_operations;
- server->vals = &smb311_values;
- }
- } else if (strcmp(server->vals->version_string,
- SMBDEFAULT_VERSION_STRING) == 0) {
- if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
- cifs_server_dbg(VFS,
- "SMB2 dialect returned but not requested\n");
- goto neg_exit;
- } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
- /* ops set to 3.0 by default for default so update */
- server->ops = &smb21_operations;
- server->vals = &smb21_values;
- } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
- server->ops = &smb311_operations;
- server->vals = &smb311_values;
- }
- } else if (le16_to_cpu(rsp->DialectRevision) !=
- server->vals->protocol_id) {
- /* if requested single dialect ensure returned dialect matched */
- cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n",
- le16_to_cpu(rsp->DialectRevision));
- goto neg_exit;
- }
-
- cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
-
- if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID))
- cifs_dbg(FYI, "negotiated smb2.0 dialect\n");
- else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID))
- cifs_dbg(FYI, "negotiated smb2.1 dialect\n");
- else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID))
- cifs_dbg(FYI, "negotiated smb3.0 dialect\n");
- else if (rsp->DialectRevision == cpu_to_le16(SMB302_PROT_ID))
- cifs_dbg(FYI, "negotiated smb3.02 dialect\n");
- else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID))
- cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n");
- else {
- cifs_server_dbg(VFS, "Invalid dialect returned by server 0x%x\n",
- le16_to_cpu(rsp->DialectRevision));
- goto neg_exit;
- }
-
- rc = 0;
- server->dialect = le16_to_cpu(rsp->DialectRevision);
-
- /*
- * Keep a copy of the hash after negprot. This hash will be
- * the starting hash value for all sessions made from this
- * server.
- */
- memcpy(server->preauth_sha_hash, ses->preauth_sha_hash,
- SMB2_PREAUTH_HASH_SIZE);
-
- /* SMB2 only has an extended negflavor */
- server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
- /* set it to the maximum buffer size value we can send with 1 credit */
- server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize),
- SMB2_MAX_BUFFER_SIZE);
- server->max_read = le32_to_cpu(rsp->MaxReadSize);
- server->max_write = le32_to_cpu(rsp->MaxWriteSize);
- server->sec_mode = le16_to_cpu(rsp->SecurityMode);
- if ((server->sec_mode & SMB2_SEC_MODE_FLAGS_ALL) != server->sec_mode)
- cifs_dbg(FYI, "Server returned unexpected security mode 0x%x\n",
- server->sec_mode);
- server->capabilities = le32_to_cpu(rsp->Capabilities);
- /* Internal types */
- server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
-
- /*
- * SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
- * Set the cipher type manually.
- */
- if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
- server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
-
- security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
- (struct smb2_hdr *)rsp);
- /*
- * See MS-SMB2 section 2.2.4: if no blob, client picks default which
- * for us will be
- * ses->sectype = RawNTLMSSP;
- * but for time being this is our only auth choice so doesn't matter.
- * We just found a server which sets blob length to zero expecting raw.
- */
- if (blob_length == 0) {
- cifs_dbg(FYI, "missing security blob on negprot\n");
- server->sec_ntlmssp = true;
- }
-
- rc = cifs_enable_signing(server, ses->sign);
- if (rc)
- goto neg_exit;
- if (blob_length) {
- rc = decode_negTokenInit(security_blob, blob_length, server);
- if (rc == 1)
- rc = 0;
- else if (rc == 0)
- rc = -EIO;
- }
-
- if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
- if (rsp->NegotiateContextCount)
- rc = smb311_decode_neg_context(rsp, server,
- rsp_iov.iov_len);
- else
- cifs_server_dbg(VFS, "Missing expected negotiate contexts\n");
- }
-neg_exit:
- free_rsp_buf(resp_buftype, rsp);
- return rc;
-}
-
-int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
-{
- int rc;
- struct validate_negotiate_info_req *pneg_inbuf;
- struct validate_negotiate_info_rsp *pneg_rsp = NULL;
- u32 rsplen;
- u32 inbuflen; /* max of 4 dialects */
- struct TCP_Server_Info *server = tcon->ses->server;
-
- cifs_dbg(FYI, "validate negotiate\n");
-
- /* In SMB3.11 preauth integrity supersedes validate negotiate */
- if (server->dialect == SMB311_PROT_ID)
- return 0;
-
- /*
- * validation ioctl must be signed, so no point sending this if we
- * can not sign it (ie are not known user). Even if signing is not
- * required (enabled but not negotiated), in those cases we selectively
- * sign just this, the first and only signed request on a connection.
- * Having validation of negotiate info helps reduce attack vectors.
- */
- if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
- return 0; /* validation requires signing */
-
- if (tcon->ses->user_name == NULL) {
- cifs_dbg(FYI, "Can't validate negotiate: null user mount\n");
- return 0; /* validation requires signing */
- }
-
- if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
- cifs_tcon_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n");
-
- pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS);
- if (!pneg_inbuf)
- return -ENOMEM;
-
- pneg_inbuf->Capabilities =
- cpu_to_le32(server->vals->req_capabilities);
- if (tcon->ses->chan_max > 1)
- pneg_inbuf->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL);
-
- memcpy(pneg_inbuf->Guid, server->client_guid,
- SMB2_CLIENT_GUID_SIZE);
-
- if (tcon->ses->sign)
- pneg_inbuf->SecurityMode =
- cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
- else if (global_secflags & CIFSSEC_MAY_SIGN)
- pneg_inbuf->SecurityMode =
- cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
- else
- pneg_inbuf->SecurityMode = 0;
-
-
- if (strcmp(server->vals->version_string,
- SMB3ANY_VERSION_STRING) == 0) {
- pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
- pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
- pneg_inbuf->Dialects[2] = cpu_to_le16(SMB311_PROT_ID);
- pneg_inbuf->DialectCount = cpu_to_le16(3);
- /* SMB 2.1 not included so subtract one dialect from len */
- inbuflen = sizeof(*pneg_inbuf) -
- (sizeof(pneg_inbuf->Dialects[0]));
- } else if (strcmp(server->vals->version_string,
- SMBDEFAULT_VERSION_STRING) == 0) {
- pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
- pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
- pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
- pneg_inbuf->Dialects[3] = cpu_to_le16(SMB311_PROT_ID);
- pneg_inbuf->DialectCount = cpu_to_le16(4);
- /* structure is big enough for 4 dialects */
- inbuflen = sizeof(*pneg_inbuf);
- } else {
- /* otherwise specific dialect was requested */
- pneg_inbuf->Dialects[0] =
- cpu_to_le16(server->vals->protocol_id);
- pneg_inbuf->DialectCount = cpu_to_le16(1);
- /* structure is big enough for 4 dialects, sending only 1 */
- inbuflen = sizeof(*pneg_inbuf) -
- sizeof(pneg_inbuf->Dialects[0]) * 3;
- }
-
- rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
- FSCTL_VALIDATE_NEGOTIATE_INFO,
- (char *)pneg_inbuf, inbuflen, CIFSMaxBufSize,
- (char **)&pneg_rsp, &rsplen);
- if (rc == -EOPNOTSUPP) {
- /*
- * Old Windows versions or Netapp SMB server can return
- * not supported error. Client should accept it.
- */
- cifs_tcon_dbg(VFS, "Server does not support validate negotiate\n");
- rc = 0;
- goto out_free_inbuf;
- } else if (rc != 0) {
- cifs_tcon_dbg(VFS, "validate protocol negotiate failed: %d\n",
- rc);
- rc = -EIO;
- goto out_free_inbuf;
- }
-
- rc = -EIO;
- if (rsplen != sizeof(*pneg_rsp)) {
- cifs_tcon_dbg(VFS, "Invalid protocol negotiate response size: %d\n",
- rsplen);
-
- /* relax check since Mac returns max bufsize allowed on ioctl */
- if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp))
- goto out_free_rsp;
- }
-
- /* check validate negotiate info response matches what we got earlier */
- if (pneg_rsp->Dialect != cpu_to_le16(server->dialect))
- goto vneg_out;
-
- if (pneg_rsp->SecurityMode != cpu_to_le16(server->sec_mode))
- goto vneg_out;
-
- /* do not validate server guid because not saved at negprot time yet */
-
- if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND |
- SMB2_LARGE_FILES) != server->capabilities)
- goto vneg_out;
-
- /* validate negotiate successful */
- rc = 0;
- cifs_dbg(FYI, "validate negotiate info successful\n");
- goto out_free_rsp;
-
-vneg_out:
- cifs_tcon_dbg(VFS, "protocol revalidation - security settings mismatch\n");
-out_free_rsp:
- kfree(pneg_rsp);
-out_free_inbuf:
- kfree(pneg_inbuf);
- return rc;
-}
-
-enum securityEnum
-smb2_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
-{
- switch (requested) {
- case Kerberos:
- case RawNTLMSSP:
- return requested;
- case NTLMv2:
- return RawNTLMSSP;
- case Unspecified:
- if (server->sec_ntlmssp &&
- (global_secflags & CIFSSEC_MAY_NTLMSSP))
- return RawNTLMSSP;
- if ((server->sec_kerberos || server->sec_mskerberos) &&
- (global_secflags & CIFSSEC_MAY_KRB5))
- return Kerberos;
- fallthrough;
- default:
- return Unspecified;
- }
-}
-
-struct SMB2_sess_data {
- unsigned int xid;
- struct cifs_ses *ses;
- struct TCP_Server_Info *server;
- struct nls_table *nls_cp;
- void (*func)(struct SMB2_sess_data *);
- int result;
- u64 previous_session;
-
- /* we will send the SMB in three pieces:
- * a fixed length beginning part, an optional
- * SPNEGO blob (which can be zero length), and a
- * last part which will include the strings
- * and rest of bcc area. This allows us to avoid
- * a large buffer 17K allocation
- */
- int buf0_type;
- struct kvec iov[2];
-};
-
-static int
-SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
-{
- int rc;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
- struct smb2_sess_setup_req *req;
- unsigned int total_len;
- bool is_binding = false;
-
- rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server,
- (void **) &req,
- &total_len);
- if (rc)
- return rc;
-
- spin_lock(&ses->ses_lock);
- is_binding = (ses->ses_status == SES_GOOD);
- spin_unlock(&ses->ses_lock);
-
- if (is_binding) {
- req->hdr.SessionId = cpu_to_le64(ses->Suid);
- req->hdr.Flags |= SMB2_FLAGS_SIGNED;
- req->PreviousSessionId = 0;
- req->Flags = SMB2_SESSION_REQ_FLAG_BINDING;
- cifs_dbg(FYI, "Binding to sess id: %llx\n", ses->Suid);
- } else {
- /* First session, not a reauthenticate */
- req->hdr.SessionId = 0;
- /*
- * if reconnect, we need to send previous sess id
- * otherwise it is 0
- */
- req->PreviousSessionId = cpu_to_le64(sess_data->previous_session);
- req->Flags = 0; /* MBZ */
- cifs_dbg(FYI, "Fresh session. Previous: %llx\n",
- sess_data->previous_session);
- }
-
- /* enough to enable echos and oplocks and one max size write */
- req->hdr.CreditRequest = cpu_to_le16(130);
-
- /* only one of SMB2 signing flags may be set in SMB2 request */
- if (server->sign)
- req->SecurityMode = SMB2_NEGOTIATE_SIGNING_REQUIRED;
- else if (global_secflags & CIFSSEC_MAY_SIGN) /* one flag unlike MUST_ */
- req->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED;
- else
- req->SecurityMode = 0;
-
-#ifdef CONFIG_CIFS_DFS_UPCALL
- req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
-#else
- req->Capabilities = 0;
-#endif /* DFS_UPCALL */
-
- req->Channel = 0; /* MBZ */
-
- sess_data->iov[0].iov_base = (char *)req;
- /* 1 for pad */
- sess_data->iov[0].iov_len = total_len - 1;
- /*
- * This variable will be used to clear the buffer
- * allocated above in case of any error in the calling function.
- */
- sess_data->buf0_type = CIFS_SMALL_BUFFER;
-
- return 0;
-}
-
-static void
-SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data)
-{
- struct kvec *iov = sess_data->iov;
-
- /* iov[1] is already freed by caller */
- if (sess_data->buf0_type != CIFS_NO_BUFFER && iov[0].iov_base)
- memzero_explicit(iov[0].iov_base, iov[0].iov_len);
-
- free_rsp_buf(sess_data->buf0_type, iov[0].iov_base);
- sess_data->buf0_type = CIFS_NO_BUFFER;
-}
-
-static int
-SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
-{
- int rc;
- struct smb_rqst rqst;
- struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base;
- struct kvec rsp_iov = { NULL, 0 };
-
- /* Testing shows that buffer offset must be at location of Buffer[0] */
- req->SecurityBufferOffset =
- cpu_to_le16(sizeof(struct smb2_sess_setup_req) - 1 /* pad */);
- req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len);
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = sess_data->iov;
- rqst.rq_nvec = 2;
-
- /* BB add code to build os and lm fields */
- rc = cifs_send_recv(sess_data->xid, sess_data->ses,
- sess_data->server,
- &rqst,
- &sess_data->buf0_type,
- CIFS_LOG_ERROR | CIFS_SESS_OP, &rsp_iov);
- cifs_small_buf_release(sess_data->iov[0].iov_base);
- memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
-
- return rc;
-}
-
-static int
-SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
-{
- int rc = 0;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
-
- cifs_server_lock(server);
- if (server->ops->generate_signingkey) {
- rc = server->ops->generate_signingkey(ses, server);
- if (rc) {
- cifs_dbg(FYI,
- "SMB3 session key generation failed\n");
- cifs_server_unlock(server);
- return rc;
- }
- }
- if (!server->session_estab) {
- server->sequence_number = 0x2;
- server->session_estab = true;
- }
- cifs_server_unlock(server);
-
- cifs_dbg(FYI, "SMB2/3 session established successfully\n");
- return rc;
-}
-
-#ifdef CONFIG_CIFS_UPCALL
-static void
-SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
-{
- int rc;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
- struct cifs_spnego_msg *msg;
- struct key *spnego_key = NULL;
- struct smb2_sess_setup_rsp *rsp = NULL;
- bool is_binding = false;
-
- rc = SMB2_sess_alloc_buffer(sess_data);
- if (rc)
- goto out;
-
- spnego_key = cifs_get_spnego_key(ses, server);
- if (IS_ERR(spnego_key)) {
- rc = PTR_ERR(spnego_key);
- if (rc == -ENOKEY)
- cifs_dbg(VFS, "Verify user has a krb5 ticket and keyutils is installed\n");
- spnego_key = NULL;
- goto out;
- }
-
- msg = spnego_key->payload.data[0];
- /*
- * check version field to make sure that cifs.upcall is
- * sending us a response in an expected form
- */
- if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
- cifs_dbg(VFS, "bad cifs.upcall version. Expected %d got %d\n",
- CIFS_SPNEGO_UPCALL_VERSION, msg->version);
- rc = -EKEYREJECTED;
- goto out_put_spnego_key;
- }
-
- spin_lock(&ses->ses_lock);
- is_binding = (ses->ses_status == SES_GOOD);
- spin_unlock(&ses->ses_lock);
-
- /* keep session key if binding */
- if (!is_binding) {
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
- GFP_KERNEL);
- if (!ses->auth_key.response) {
- cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n",
- msg->sesskey_len);
- rc = -ENOMEM;
- goto out_put_spnego_key;
- }
- ses->auth_key.len = msg->sesskey_len;
- }
-
- sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
- sess_data->iov[1].iov_len = msg->secblob_len;
-
- rc = SMB2_sess_sendreceive(sess_data);
- if (rc)
- goto out_put_spnego_key;
-
- rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
- /* keep session id and flags if binding */
- if (!is_binding) {
- ses->Suid = le64_to_cpu(rsp->hdr.SessionId);
- ses->session_flags = le16_to_cpu(rsp->SessionFlags);
- }
-
- rc = SMB2_sess_establish_session(sess_data);
-out_put_spnego_key:
- key_invalidate(spnego_key);
- key_put(spnego_key);
- if (rc) {
- kfree_sensitive(ses->auth_key.response);
- ses->auth_key.response = NULL;
- ses->auth_key.len = 0;
- }
-out:
- sess_data->result = rc;
- sess_data->func = NULL;
- SMB2_sess_free_buffer(sess_data);
-}
-#else
-static void
-SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
-{
- cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
- sess_data->result = -EOPNOTSUPP;
- sess_data->func = NULL;
-}
-#endif
-
-static void
-SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data);
-
-static void
-SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
-{
- int rc;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
- struct smb2_sess_setup_rsp *rsp = NULL;
- unsigned char *ntlmssp_blob = NULL;
- bool use_spnego = false; /* else use raw ntlmssp */
- u16 blob_length = 0;
- bool is_binding = false;
-
- /*
- * If memory allocation is successful, caller of this function
- * frees it.
- */
- ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
- if (!ses->ntlmssp) {
- rc = -ENOMEM;
- goto out_err;
- }
- ses->ntlmssp->sesskey_per_smbsess = true;
-
- rc = SMB2_sess_alloc_buffer(sess_data);
- if (rc)
- goto out_err;
-
- rc = build_ntlmssp_smb3_negotiate_blob(&ntlmssp_blob,
- &blob_length, ses, server,
- sess_data->nls_cp);
- if (rc)
- goto out;
-
- if (use_spnego) {
- /* BB eventually need to add this */
- cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
- rc = -EOPNOTSUPP;
- goto out;
- }
- sess_data->iov[1].iov_base = ntlmssp_blob;
- sess_data->iov[1].iov_len = blob_length;
-
- rc = SMB2_sess_sendreceive(sess_data);
- rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
-
- /* If true, rc here is expected and not an error */
- if (sess_data->buf0_type != CIFS_NO_BUFFER &&
- rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
- rc = 0;
-
- if (rc)
- goto out;
-
- if (offsetof(struct smb2_sess_setup_rsp, Buffer) !=
- le16_to_cpu(rsp->SecurityBufferOffset)) {
- cifs_dbg(VFS, "Invalid security buffer offset %d\n",
- le16_to_cpu(rsp->SecurityBufferOffset));
- rc = -EIO;
- goto out;
- }
- rc = decode_ntlmssp_challenge(rsp->Buffer,
- le16_to_cpu(rsp->SecurityBufferLength), ses);
- if (rc)
- goto out;
-
- cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
-
- spin_lock(&ses->ses_lock);
- is_binding = (ses->ses_status == SES_GOOD);
- spin_unlock(&ses->ses_lock);
-
- /* keep existing ses id and flags if binding */
- if (!is_binding) {
- ses->Suid = le64_to_cpu(rsp->hdr.SessionId);
- ses->session_flags = le16_to_cpu(rsp->SessionFlags);
- }
-
-out:
- kfree_sensitive(ntlmssp_blob);
- SMB2_sess_free_buffer(sess_data);
- if (!rc) {
- sess_data->result = 0;
- sess_data->func = SMB2_sess_auth_rawntlmssp_authenticate;
- return;
- }
-out_err:
- kfree_sensitive(ses->ntlmssp);
- ses->ntlmssp = NULL;
- sess_data->result = rc;
- sess_data->func = NULL;
-}
-
-static void
-SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
-{
- int rc;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
- struct smb2_sess_setup_req *req;
- struct smb2_sess_setup_rsp *rsp = NULL;
- unsigned char *ntlmssp_blob = NULL;
- bool use_spnego = false; /* else use raw ntlmssp */
- u16 blob_length = 0;
- bool is_binding = false;
-
- rc = SMB2_sess_alloc_buffer(sess_data);
- if (rc)
- goto out;
-
- req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base;
- req->hdr.SessionId = cpu_to_le64(ses->Suid);
-
- rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length,
- ses, server,
- sess_data->nls_cp);
- if (rc) {
- cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", rc);
- goto out;
- }
-
- if (use_spnego) {
- /* BB eventually need to add this */
- cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
- rc = -EOPNOTSUPP;
- goto out;
- }
- sess_data->iov[1].iov_base = ntlmssp_blob;
- sess_data->iov[1].iov_len = blob_length;
-
- rc = SMB2_sess_sendreceive(sess_data);
- if (rc)
- goto out;
-
- rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
-
- spin_lock(&ses->ses_lock);
- is_binding = (ses->ses_status == SES_GOOD);
- spin_unlock(&ses->ses_lock);
-
- /* keep existing ses id and flags if binding */
- if (!is_binding) {
- ses->Suid = le64_to_cpu(rsp->hdr.SessionId);
- ses->session_flags = le16_to_cpu(rsp->SessionFlags);
- }
-
- rc = SMB2_sess_establish_session(sess_data);
-#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
- if (ses->server->dialect < SMB30_PROT_ID) {
- cifs_dbg(VFS, "%s: dumping generated SMB2 session keys\n", __func__);
- /*
- * The session id is opaque in terms of endianness, so we can't
- * print it as a long long. we dump it as we got it on the wire
- */
- cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid),
- &ses->Suid);
- cifs_dbg(VFS, "Session Key %*ph\n",
- SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
- cifs_dbg(VFS, "Signing Key %*ph\n",
- SMB3_SIGN_KEY_SIZE, ses->auth_key.response);
- }
-#endif
-out:
- kfree_sensitive(ntlmssp_blob);
- SMB2_sess_free_buffer(sess_data);
- kfree_sensitive(ses->ntlmssp);
- ses->ntlmssp = NULL;
- sess_data->result = rc;
- sess_data->func = NULL;
-}
-
-static int
-SMB2_select_sec(struct SMB2_sess_data *sess_data)
-{
- int type;
- struct cifs_ses *ses = sess_data->ses;
- struct TCP_Server_Info *server = sess_data->server;
-
- type = smb2_select_sectype(server, ses->sectype);
- cifs_dbg(FYI, "sess setup type %d\n", type);
- if (type == Unspecified) {
- cifs_dbg(VFS, "Unable to select appropriate authentication method!\n");
- return -EINVAL;
- }
-
- switch (type) {
- case Kerberos:
- sess_data->func = SMB2_auth_kerberos;
- break;
- case RawNTLMSSP:
- sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate;
- break;
- default:
- cifs_dbg(VFS, "secType %d not supported!\n", type);
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-int
-SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp)
-{
- int rc = 0;
- struct SMB2_sess_data *sess_data;
-
- cifs_dbg(FYI, "Session Setup\n");
-
- if (!server) {
- WARN(1, "%s: server is NULL!\n", __func__);
- return -EIO;
- }
-
- sess_data = kzalloc(sizeof(struct SMB2_sess_data), GFP_KERNEL);
- if (!sess_data)
- return -ENOMEM;
-
- sess_data->xid = xid;
- sess_data->ses = ses;
- sess_data->server = server;
- sess_data->buf0_type = CIFS_NO_BUFFER;
- sess_data->nls_cp = (struct nls_table *) nls_cp;
- sess_data->previous_session = ses->Suid;
-
- rc = SMB2_select_sec(sess_data);
- if (rc)
- goto out;
-
- /*
- * Initialize the session hash with the server one.
- */
- memcpy(ses->preauth_sha_hash, server->preauth_sha_hash,
- SMB2_PREAUTH_HASH_SIZE);
-
- while (sess_data->func)
- sess_data->func(sess_data);
-
- if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign))
- cifs_server_dbg(VFS, "signing requested but authenticated as guest\n");
- rc = sess_data->result;
-out:
- kfree_sensitive(sess_data);
- return rc;
-}
-
-int
-SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
-{
- struct smb_rqst rqst;
- struct smb2_logoff_req *req; /* response is also trivial struct */
- int rc = 0;
- struct TCP_Server_Info *server;
- int flags = 0;
- unsigned int total_len;
- struct kvec iov[1];
- struct kvec rsp_iov;
- int resp_buf_type;
-
- cifs_dbg(FYI, "disconnect session %p\n", ses);
-
- if (ses && (ses->server))
- server = ses->server;
- else
- return -EIO;
-
- /* no need to send SMB logoff if uid already closed due to reconnect */
- spin_lock(&ses->chan_lock);
- if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
- spin_unlock(&ses->chan_lock);
- goto smb2_session_already_dead;
- }
- spin_unlock(&ses->chan_lock);
-
- rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, ses->server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- /* since no tcon, smb2_init can not do this, so do here */
- req->hdr.SessionId = cpu_to_le64(ses->Suid);
-
- if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
- flags |= CIFS_TRANSFORM_REQ;
- else if (server->sign)
- req->hdr.Flags |= SMB2_FLAGS_SIGNED;
-
- flags |= CIFS_NO_RSP_BUF;
-
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- rc = cifs_send_recv(xid, ses, ses->server,
- &rqst, &resp_buf_type, flags, &rsp_iov);
- cifs_small_buf_release(req);
- /*
- * No tcon so can't do
- * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
- */
-
-smb2_session_already_dead:
- return rc;
-}
-
-static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code)
-{
- cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_failed[code]);
-}
-
-#define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */)
-
-/* These are similar values to what Windows uses */
-static inline void init_copy_chunk_defaults(struct cifs_tcon *tcon)
-{
- tcon->max_chunks = 256;
- tcon->max_bytes_chunk = 1048576;
- tcon->max_bytes_copy = 16777216;
-}
-
-int
-SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
- struct cifs_tcon *tcon, const struct nls_table *cp)
-{
- struct smb_rqst rqst;
- struct smb2_tree_connect_req *req;
- struct smb2_tree_connect_rsp *rsp = NULL;
- struct kvec iov[2];
- struct kvec rsp_iov = { NULL, 0 };
- int rc = 0;
- int resp_buftype;
- int unc_path_len;
- __le16 *unc_path = NULL;
- int flags = 0;
- unsigned int total_len;
- struct TCP_Server_Info *server;
-
- /* always use master channel */
- server = ses->server;
-
- cifs_dbg(FYI, "TCON\n");
-
- if (!server || !tree)
- return -EIO;
-
- unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
- if (unc_path == NULL)
- return -ENOMEM;
-
- unc_path_len = cifs_strtoUTF16(unc_path, tree, strlen(tree), cp) + 1;
- unc_path_len *= 2;
- if (unc_path_len < 2) {
- kfree(unc_path);
- return -EINVAL;
- }
-
- /* SMB2 TREE_CONNECT request must be called with TreeId == 0 */
- tcon->tid = 0;
- atomic_set(&tcon->num_remote_opens, 0);
- rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, server,
- (void **) &req, &total_len);
- if (rc) {
- kfree(unc_path);
- return rc;
- }
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- iov[0].iov_base = (char *)req;
- /* 1 for pad */
- iov[0].iov_len = total_len - 1;
-
- /* Testing shows that buffer offset must be at location of Buffer[0] */
- req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req)
- - 1 /* pad */);
- req->PathLength = cpu_to_le16(unc_path_len - 2);
- iov[1].iov_base = unc_path;
- iov[1].iov_len = unc_path_len;
-
- /*
- * 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1
- * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1
- * (Samba servers don't always set the flag so also check if null user)
- */
- if ((server->dialect == SMB311_PROT_ID) &&
- !smb3_encryption_required(tcon) &&
- !(ses->session_flags &
- (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) &&
- ((ses->user_name != NULL) || (ses->sectype == Kerberos)))
- req->hdr.Flags |= SMB2_FLAGS_SIGNED;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 2;
-
- /* Need 64 for max size write so ask for more in case not there yet */
- req->hdr.CreditRequest = cpu_to_le16(64);
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- cifs_small_buf_release(req);
- rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base;
- trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc);
- if ((rc != 0) || (rsp == NULL)) {
- cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE);
- tcon->need_reconnect = true;
- goto tcon_error_exit;
- }
-
- switch (rsp->ShareType) {
- case SMB2_SHARE_TYPE_DISK:
- cifs_dbg(FYI, "connection to disk share\n");
- break;
- case SMB2_SHARE_TYPE_PIPE:
- tcon->pipe = true;
- cifs_dbg(FYI, "connection to pipe share\n");
- break;
- case SMB2_SHARE_TYPE_PRINT:
- tcon->print = true;
- cifs_dbg(FYI, "connection to printer\n");
- break;
- default:
- cifs_server_dbg(VFS, "unknown share type %d\n", rsp->ShareType);
- rc = -EOPNOTSUPP;
- goto tcon_error_exit;
- }
-
- tcon->share_flags = le32_to_cpu(rsp->ShareFlags);
- tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */
- tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
- tcon->tid = le32_to_cpu(rsp->hdr.Id.SyncId.TreeId);
- strscpy(tcon->tree_name, tree, sizeof(tcon->tree_name));
-
- if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
- ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
- cifs_tcon_dbg(VFS, "DFS capability contradicts DFS flag\n");
-
- if (tcon->seal &&
- !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
- cifs_tcon_dbg(VFS, "Encryption is requested but not supported\n");
-
- init_copy_chunk_defaults(tcon);
- if (server->ops->validate_negotiate)
- rc = server->ops->validate_negotiate(xid, tcon);
-tcon_exit:
-
- free_rsp_buf(resp_buftype, rsp);
- kfree(unc_path);
- return rc;
-
-tcon_error_exit:
- if (rsp && rsp->hdr.Status == STATUS_BAD_NETWORK_NAME)
- cifs_tcon_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
- goto tcon_exit;
-}
-
-int
-SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
-{
- struct smb_rqst rqst;
- struct smb2_tree_disconnect_req *req; /* response is trivial */
- int rc = 0;
- struct cifs_ses *ses = tcon->ses;
- int flags = 0;
- unsigned int total_len;
- struct kvec iov[1];
- struct kvec rsp_iov;
- int resp_buf_type;
-
- cifs_dbg(FYI, "Tree Disconnect\n");
-
- if (!ses || !(ses->server))
- return -EIO;
-
- trace_smb3_tdis_enter(xid, tcon->tid, ses->Suid, tcon->tree_name);
- spin_lock(&ses->chan_lock);
- if ((tcon->need_reconnect) ||
- (CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses))) {
- spin_unlock(&ses->chan_lock);
- return 0;
- }
- spin_unlock(&ses->chan_lock);
-
- invalidate_all_cached_dirs(tcon);
-
- rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, ses->server,
- (void **) &req,
- &total_len);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- flags |= CIFS_NO_RSP_BUF;
-
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- rc = cifs_send_recv(xid, ses, ses->server,
- &rqst, &resp_buf_type, flags, &rsp_iov);
- cifs_small_buf_release(req);
- if (rc) {
- cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE);
- trace_smb3_tdis_err(xid, tcon->tid, ses->Suid, rc);
- }
- trace_smb3_tdis_done(xid, tcon->tid, ses->Suid);
-
- return rc;
-}
-
-
-static struct create_durable *
-create_durable_buf(void)
-{
- struct create_durable *buf;
-
- buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
- if (!buf)
- return NULL;
-
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_durable, Data));
- buf->ccontext.DataLength = cpu_to_le32(16);
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_durable, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */
- buf->Name[0] = 'D';
- buf->Name[1] = 'H';
- buf->Name[2] = 'n';
- buf->Name[3] = 'Q';
- return buf;
-}
-
-static struct create_durable *
-create_reconnect_durable_buf(struct cifs_fid *fid)
-{
- struct create_durable *buf;
-
- buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
- if (!buf)
- return NULL;
-
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_durable, Data));
- buf->ccontext.DataLength = cpu_to_le32(16);
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_durable, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- buf->Data.Fid.PersistentFileId = fid->persistent_fid;
- buf->Data.Fid.VolatileFileId = fid->volatile_fid;
- /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT is "DHnC" */
- buf->Name[0] = 'D';
- buf->Name[1] = 'H';
- buf->Name[2] = 'n';
- buf->Name[3] = 'C';
- return buf;
-}
-
-static void
-parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf)
-{
- struct create_on_disk_id *pdisk_id = (struct create_on_disk_id *)cc;
-
- cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n",
- pdisk_id->DiskFileId, pdisk_id->VolumeId);
- buf->IndexNumber = pdisk_id->DiskFileId;
-}
-
-static void
-parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info,
- struct create_posix_rsp *posix)
-{
- int sid_len;
- u8 *beg = (u8 *)cc + le16_to_cpu(cc->DataOffset);
- u8 *end = beg + le32_to_cpu(cc->DataLength);
- u8 *sid;
-
- memset(posix, 0, sizeof(*posix));
-
- posix->nlink = le32_to_cpu(*(__le32 *)(beg + 0));
- posix->reparse_tag = le32_to_cpu(*(__le32 *)(beg + 4));
- posix->mode = le32_to_cpu(*(__le32 *)(beg + 8));
-
- sid = beg + 12;
- sid_len = posix_info_sid_size(sid, end);
- if (sid_len < 0) {
- cifs_dbg(VFS, "bad owner sid in posix create response\n");
- return;
- }
- memcpy(&posix->owner, sid, sid_len);
-
- sid = sid + sid_len;
- sid_len = posix_info_sid_size(sid, end);
- if (sid_len < 0) {
- cifs_dbg(VFS, "bad group sid in posix create response\n");
- return;
- }
- memcpy(&posix->group, sid, sid_len);
-
- cifs_dbg(FYI, "nlink=%d mode=%o reparse_tag=%x\n",
- posix->nlink, posix->mode, posix->reparse_tag);
-}
-
-void
-smb2_parse_contexts(struct TCP_Server_Info *server,
- struct smb2_create_rsp *rsp,
- unsigned int *epoch, char *lease_key, __u8 *oplock,
- struct smb2_file_all_info *buf,
- struct create_posix_rsp *posix)
-{
- char *data_offset;
- struct create_context *cc;
- unsigned int next;
- unsigned int remaining;
- char *name;
- static const char smb3_create_tag_posix[] = {
- 0x93, 0xAD, 0x25, 0x50, 0x9C,
- 0xB4, 0x11, 0xE7, 0xB4, 0x23, 0x83,
- 0xDE, 0x96, 0x8B, 0xCD, 0x7C
- };
-
- *oplock = 0;
- data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
- remaining = le32_to_cpu(rsp->CreateContextsLength);
- cc = (struct create_context *)data_offset;
-
- /* Initialize inode number to 0 in case no valid data in qfid context */
- if (buf)
- buf->IndexNumber = 0;
-
- while (remaining >= sizeof(struct create_context)) {
- name = le16_to_cpu(cc->NameOffset) + (char *)cc;
- if (le16_to_cpu(cc->NameLength) == 4 &&
- strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0)
- *oplock = server->ops->parse_lease_buf(cc, epoch,
- lease_key);
- else if (buf && (le16_to_cpu(cc->NameLength) == 4) &&
- strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0)
- parse_query_id_ctxt(cc, buf);
- else if ((le16_to_cpu(cc->NameLength) == 16)) {
- if (posix &&
- memcmp(name, smb3_create_tag_posix, 16) == 0)
- parse_posix_ctxt(cc, buf, posix);
- }
- /* else {
- cifs_dbg(FYI, "Context not matched with len %d\n",
- le16_to_cpu(cc->NameLength));
- cifs_dump_mem("Cctxt name: ", name, 4);
- } */
-
- next = le32_to_cpu(cc->Next);
- if (!next)
- break;
- remaining -= next;
- cc = (struct create_context *)((char *)cc + next);
- }
-
- if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
- *oplock = rsp->OplockLevel;
-
- return;
-}
-
-static int
-add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
- unsigned int *num_iovec, u8 *lease_key, __u8 *oplock)
-{
- struct smb2_create_req *req = iov[0].iov_base;
- unsigned int num = *num_iovec;
-
- iov[num].iov_base = server->ops->create_lease_buf(lease_key, *oplock);
- if (iov[num].iov_base == NULL)
- return -ENOMEM;
- iov[num].iov_len = server->vals->create_lease_size;
- req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
- if (!req->CreateContextsOffset)
- req->CreateContextsOffset = cpu_to_le32(
- sizeof(struct smb2_create_req) +
- iov[num - 1].iov_len);
- le32_add_cpu(&req->CreateContextsLength,
- server->vals->create_lease_size);
- *num_iovec = num + 1;
- return 0;
-}
-
-static struct create_durable_v2 *
-create_durable_v2_buf(struct cifs_open_parms *oparms)
-{
- struct cifs_fid *pfid = oparms->fid;
- struct create_durable_v2 *buf;
-
- buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL);
- if (!buf)
- return NULL;
-
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_durable_v2, dcontext));
- buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2));
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_durable_v2, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
-
- /*
- * NB: Handle timeout defaults to 0, which allows server to choose
- * (most servers default to 120 seconds) and most clients default to 0.
- * This can be overridden at mount ("handletimeout=") if the user wants
- * a different persistent (or resilient) handle timeout for all opens
- * opens on a particular SMB3 mount.
- */
- buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
- buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
- generate_random_uuid(buf->dcontext.CreateGuid);
- memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
-
- /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
- buf->Name[0] = 'D';
- buf->Name[1] = 'H';
- buf->Name[2] = '2';
- buf->Name[3] = 'Q';
- return buf;
-}
-
-static struct create_durable_handle_reconnect_v2 *
-create_reconnect_durable_v2_buf(struct cifs_fid *fid)
-{
- struct create_durable_handle_reconnect_v2 *buf;
-
- buf = kzalloc(sizeof(struct create_durable_handle_reconnect_v2),
- GFP_KERNEL);
- if (!buf)
- return NULL;
-
- buf->ccontext.DataOffset =
- cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
- dcontext));
- buf->ccontext.DataLength =
- cpu_to_le32(sizeof(struct durable_reconnect_context_v2));
- buf->ccontext.NameOffset =
- cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
- Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
-
- buf->dcontext.Fid.PersistentFileId = fid->persistent_fid;
- buf->dcontext.Fid.VolatileFileId = fid->volatile_fid;
- buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
- memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16);
-
- /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */
- buf->Name[0] = 'D';
- buf->Name[1] = 'H';
- buf->Name[2] = '2';
- buf->Name[3] = 'C';
- return buf;
-}
-
-static int
-add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
- struct cifs_open_parms *oparms)
-{
- struct smb2_create_req *req = iov[0].iov_base;
- unsigned int num = *num_iovec;
-
- iov[num].iov_base = create_durable_v2_buf(oparms);
- if (iov[num].iov_base == NULL)
- return -ENOMEM;
- iov[num].iov_len = sizeof(struct create_durable_v2);
- if (!req->CreateContextsOffset)
- req->CreateContextsOffset =
- cpu_to_le32(sizeof(struct smb2_create_req) +
- iov[1].iov_len);
- le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_v2));
- *num_iovec = num + 1;
- return 0;
-}
-
-static int
-add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec,
- struct cifs_open_parms *oparms)
-{
- struct smb2_create_req *req = iov[0].iov_base;
- unsigned int num = *num_iovec;
-
- /* indicate that we don't need to relock the file */
- oparms->reconnect = false;
-
- iov[num].iov_base = create_reconnect_durable_v2_buf(oparms->fid);
- if (iov[num].iov_base == NULL)
- return -ENOMEM;
- iov[num].iov_len = sizeof(struct create_durable_handle_reconnect_v2);
- if (!req->CreateContextsOffset)
- req->CreateContextsOffset =
- cpu_to_le32(sizeof(struct smb2_create_req) +
- iov[1].iov_len);
- le32_add_cpu(&req->CreateContextsLength,
- sizeof(struct create_durable_handle_reconnect_v2));
- *num_iovec = num + 1;
- return 0;
-}
-
-static int
-add_durable_context(struct kvec *iov, unsigned int *num_iovec,
- struct cifs_open_parms *oparms, bool use_persistent)
-{
- struct smb2_create_req *req = iov[0].iov_base;
- unsigned int num = *num_iovec;
-
- if (use_persistent) {
- if (oparms->reconnect)
- return add_durable_reconnect_v2_context(iov, num_iovec,
- oparms);
- else
- return add_durable_v2_context(iov, num_iovec, oparms);
- }
-
- if (oparms->reconnect) {
- iov[num].iov_base = create_reconnect_durable_buf(oparms->fid);
- /* indicate that we don't need to relock the file */
- oparms->reconnect = false;
- } else
- iov[num].iov_base = create_durable_buf();
- if (iov[num].iov_base == NULL)
- return -ENOMEM;
- iov[num].iov_len = sizeof(struct create_durable);
- if (!req->CreateContextsOffset)
- req->CreateContextsOffset =
- cpu_to_le32(sizeof(struct smb2_create_req) +
- iov[1].iov_len);
- le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable));
- *num_iovec = num + 1;
- return 0;
-}
-
-/* See MS-SMB2 2.2.13.2.7 */
-static struct crt_twarp_ctxt *
-create_twarp_buf(__u64 timewarp)
-{
- struct crt_twarp_ctxt *buf;
-
- buf = kzalloc(sizeof(struct crt_twarp_ctxt), GFP_KERNEL);
- if (!buf)
- return NULL;
-
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct crt_twarp_ctxt, Timestamp));
- buf->ccontext.DataLength = cpu_to_le32(8);
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct crt_twarp_ctxt, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_TIMEWARP_TOKEN is "TWrp" */
- buf->Name[0] = 'T';
- buf->Name[1] = 'W';
- buf->Name[2] = 'r';
- buf->Name[3] = 'p';
- buf->Timestamp = cpu_to_le64(timewarp);
- return buf;
-}
-
-/* See MS-SMB2 2.2.13.2.7 */
-static int
-add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
-{
- struct smb2_create_req *req = iov[0].iov_base;
- unsigned int num = *num_iovec;
-
- iov[num].iov_base = create_twarp_buf(timewarp);
- if (iov[num].iov_base == NULL)
- return -ENOMEM;
- iov[num].iov_len = sizeof(struct crt_twarp_ctxt);
- if (!req->CreateContextsOffset)
- req->CreateContextsOffset = cpu_to_le32(
- sizeof(struct smb2_create_req) +
- iov[num - 1].iov_len);
- le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_twarp_ctxt));
- *num_iovec = num + 1;
- return 0;
-}
-
-/* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */
-static void setup_owner_group_sids(char *buf)
-{
- struct owner_group_sids *sids = (struct owner_group_sids *)buf;
-
- /* Populate the user ownership fields S-1-5-88-1 */
- sids->owner.Revision = 1;
- sids->owner.NumAuth = 3;
- sids->owner.Authority[5] = 5;
- sids->owner.SubAuthorities[0] = cpu_to_le32(88);
- sids->owner.SubAuthorities[1] = cpu_to_le32(1);
- sids->owner.SubAuthorities[2] = cpu_to_le32(current_fsuid().val);
-
- /* Populate the group ownership fields S-1-5-88-2 */
- sids->group.Revision = 1;
- sids->group.NumAuth = 3;
- sids->group.Authority[5] = 5;
- sids->group.SubAuthorities[0] = cpu_to_le32(88);
- sids->group.SubAuthorities[1] = cpu_to_le32(2);
- sids->group.SubAuthorities[2] = cpu_to_le32(current_fsgid().val);
-
- cifs_dbg(FYI, "owner S-1-5-88-1-%d, group S-1-5-88-2-%d\n", current_fsuid().val, current_fsgid().val);
-}
-
-/* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */
-static struct crt_sd_ctxt *
-create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
-{
- struct crt_sd_ctxt *buf;
- __u8 *ptr, *aclptr;
- unsigned int acelen, acl_size, ace_count;
- unsigned int owner_offset = 0;
- unsigned int group_offset = 0;
- struct smb3_acl acl = {};
-
- *len = round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8);
-
- if (set_owner) {
- /* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */
- *len += sizeof(struct owner_group_sids);
- }
-
- buf = kzalloc(*len, GFP_KERNEL);
- if (buf == NULL)
- return buf;
-
- ptr = (__u8 *)&buf[1];
- if (set_owner) {
- /* offset fields are from beginning of security descriptor not of create context */
- owner_offset = ptr - (__u8 *)&buf->sd;
- buf->sd.OffsetOwner = cpu_to_le32(owner_offset);
- group_offset = owner_offset + offsetof(struct owner_group_sids, group);
- buf->sd.OffsetGroup = cpu_to_le32(group_offset);
-
- setup_owner_group_sids(ptr);
- ptr += sizeof(struct owner_group_sids);
- } else {
- buf->sd.OffsetOwner = 0;
- buf->sd.OffsetGroup = 0;
- }
-
- buf->ccontext.DataOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, sd));
- buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */
- buf->Name[0] = 'S';
- buf->Name[1] = 'e';
- buf->Name[2] = 'c';
- buf->Name[3] = 'D';
- buf->sd.Revision = 1; /* Must be one see MS-DTYP 2.4.6 */
-
- /*
- * ACL is "self relative" ie ACL is stored in contiguous block of memory
- * and "DP" ie the DACL is present
- */
- buf->sd.Control = cpu_to_le16(ACL_CONTROL_SR | ACL_CONTROL_DP);
-
- /* offset owner, group and Sbz1 and SACL are all zero */
- buf->sd.OffsetDacl = cpu_to_le32(ptr - (__u8 *)&buf->sd);
- /* Ship the ACL for now. we will copy it into buf later. */
- aclptr = ptr;
- ptr += sizeof(struct smb3_acl);
-
- /* create one ACE to hold the mode embedded in reserved special SID */
- acelen = setup_special_mode_ACE((struct cifs_ace *)ptr, (__u64)mode);
- ptr += acelen;
- acl_size = acelen + sizeof(struct smb3_acl);
- ace_count = 1;
-
- if (set_owner) {
- /* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
- acelen = setup_special_user_owner_ACE((struct cifs_ace *)ptr);
- ptr += acelen;
- acl_size += acelen;
- ace_count += 1;
- }
-
- /* and one more ACE to allow access for authenticated users */
- acelen = setup_authusers_ACE((struct cifs_ace *)ptr);
- ptr += acelen;
- acl_size += acelen;
- ace_count += 1;
-
- acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */
- acl.AclSize = cpu_to_le16(acl_size);
- acl.AceCount = cpu_to_le16(ace_count);
- /* acl.Sbz1 and Sbz2 MBZ so are not set here, but initialized above */
- memcpy(aclptr, &acl, sizeof(struct smb3_acl));
-
- buf->ccontext.DataLength = cpu_to_le32(ptr - (__u8 *)&buf->sd);
- *len = round_up((unsigned int)(ptr - (__u8 *)buf), 8);
-
- return buf;
-}
-
-static int
-add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner)
-{
- struct smb2_create_req *req = iov[0].iov_base;
- unsigned int num = *num_iovec;
- unsigned int len = 0;
-
- iov[num].iov_base = create_sd_buf(mode, set_owner, &len);
- if (iov[num].iov_base == NULL)
- return -ENOMEM;
- iov[num].iov_len = len;
- if (!req->CreateContextsOffset)
- req->CreateContextsOffset = cpu_to_le32(
- sizeof(struct smb2_create_req) +
- iov[num - 1].iov_len);
- le32_add_cpu(&req->CreateContextsLength, len);
- *num_iovec = num + 1;
- return 0;
-}
-
-static struct crt_query_id_ctxt *
-create_query_id_buf(void)
-{
- struct crt_query_id_ctxt *buf;
-
- buf = kzalloc(sizeof(struct crt_query_id_ctxt), GFP_KERNEL);
- if (!buf)
- return NULL;
-
- buf->ccontext.DataOffset = cpu_to_le16(0);
- buf->ccontext.DataLength = cpu_to_le32(0);
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct crt_query_id_ctxt, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_QUERY_ON_DISK_ID is "QFid" */
- buf->Name[0] = 'Q';
- buf->Name[1] = 'F';
- buf->Name[2] = 'i';
- buf->Name[3] = 'd';
- return buf;
-}
-
-/* See MS-SMB2 2.2.13.2.9 */
-static int
-add_query_id_context(struct kvec *iov, unsigned int *num_iovec)
-{
- struct smb2_create_req *req = iov[0].iov_base;
- unsigned int num = *num_iovec;
-
- iov[num].iov_base = create_query_id_buf();
- if (iov[num].iov_base == NULL)
- return -ENOMEM;
- iov[num].iov_len = sizeof(struct crt_query_id_ctxt);
- if (!req->CreateContextsOffset)
- req->CreateContextsOffset = cpu_to_le32(
- sizeof(struct smb2_create_req) +
- iov[num - 1].iov_len);
- le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_query_id_ctxt));
- *num_iovec = num + 1;
- return 0;
-}
-
-static int
-alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
- const char *treename, const __le16 *path)
-{
- int treename_len, path_len;
- struct nls_table *cp;
- const __le16 sep[] = {cpu_to_le16('\\'), cpu_to_le16(0x0000)};
-
- /*
- * skip leading "\\"
- */
- treename_len = strlen(treename);
- if (treename_len < 2 || !(treename[0] == '\\' && treename[1] == '\\'))
- return -EINVAL;
-
- treename += 2;
- treename_len -= 2;
-
- path_len = UniStrnlen((wchar_t *)path, PATH_MAX);
-
- /* make room for one path separator only if @path isn't empty */
- *out_len = treename_len + (path[0] ? 1 : 0) + path_len;
-
- /*
- * final path needs to be 8-byte aligned as specified in
- * MS-SMB2 2.2.13 SMB2 CREATE Request.
- */
- *out_size = round_up(*out_len * sizeof(__le16), 8);
- *out_path = kzalloc(*out_size + sizeof(__le16) /* null */, GFP_KERNEL);
- if (!*out_path)
- return -ENOMEM;
-
- cp = load_nls_default();
- cifs_strtoUTF16(*out_path, treename, treename_len, cp);
-
- /* Do not append the separator if the path is empty */
- if (path[0] != cpu_to_le16(0x0000)) {
- UniStrcat(*out_path, sep);
- UniStrcat(*out_path, path);
- }
-
- unload_nls(cp);
-
- return 0;
-}
-
-int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
- umode_t mode, struct cifs_tcon *tcon,
- const char *full_path,
- struct cifs_sb_info *cifs_sb)
-{
- struct smb_rqst rqst;
- struct smb2_create_req *req;
- struct smb2_create_rsp *rsp = NULL;
- struct cifs_ses *ses = tcon->ses;
- struct kvec iov[3]; /* make sure at least one for each open context */
- struct kvec rsp_iov = {NULL, 0};
- int resp_buftype;
- int uni_path_len;
- __le16 *copy_path = NULL;
- int copy_size;
- int rc = 0;
- unsigned int n_iov = 2;
- __u32 file_attributes = 0;
- char *pc_buf = NULL;
- int flags = 0;
- unsigned int total_len;
- __le16 *utf16_path = NULL;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
-
- cifs_dbg(FYI, "mkdir\n");
-
- /* resource #1: path allocation */
- utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
-
- if (!ses || !server) {
- rc = -EIO;
- goto err_free_path;
- }
-
- /* resource #2: request */
- rc = smb2_plain_req_init(SMB2_CREATE, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- goto err_free_path;
-
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- req->ImpersonationLevel = IL_IMPERSONATION;
- req->DesiredAccess = cpu_to_le32(FILE_WRITE_ATTRIBUTES);
- /* File attributes ignored on open (used in create though) */
- req->FileAttributes = cpu_to_le32(file_attributes);
- req->ShareAccess = FILE_SHARE_ALL_LE;
- req->CreateDisposition = cpu_to_le32(FILE_CREATE);
- req->CreateOptions = cpu_to_le32(CREATE_NOT_FILE);
-
- iov[0].iov_base = (char *)req;
- /* -1 since last byte is buf[0] which is sent below (path) */
- iov[0].iov_len = total_len - 1;
-
- req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
-
- /* [MS-SMB2] 2.2.13 NameOffset:
- * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
- * the SMB2 header, the file name includes a prefix that will
- * be processed during DFS name normalization as specified in
- * section 3.3.5.9. Otherwise, the file name is relative to
- * the share that is identified by the TreeId in the SMB2
- * header.
- */
- if (tcon->share_flags & SHI1005_FLAGS_DFS) {
- int name_len;
-
- req->hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
- rc = alloc_path_with_tree_prefix(©_path, ©_size,
- &name_len,
- tcon->tree_name, utf16_path);
- if (rc)
- goto err_free_req;
-
- req->NameLength = cpu_to_le16(name_len * 2);
- uni_path_len = copy_size;
- /* free before overwriting resource */
- kfree(utf16_path);
- utf16_path = copy_path;
- } else {
- uni_path_len = (2 * UniStrnlen((wchar_t *)utf16_path, PATH_MAX)) + 2;
- /* MUST set path len (NameLength) to 0 opening root of share */
- req->NameLength = cpu_to_le16(uni_path_len - 2);
- if (uni_path_len % 8 != 0) {
- copy_size = roundup(uni_path_len, 8);
- copy_path = kzalloc(copy_size, GFP_KERNEL);
- if (!copy_path) {
- rc = -ENOMEM;
- goto err_free_req;
- }
- memcpy((char *)copy_path, (const char *)utf16_path,
- uni_path_len);
- uni_path_len = copy_size;
- /* free before overwriting resource */
- kfree(utf16_path);
- utf16_path = copy_path;
- }
- }
-
- iov[1].iov_len = uni_path_len;
- iov[1].iov_base = utf16_path;
- req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE;
-
- if (tcon->posix_extensions) {
- /* resource #3: posix buf */
- rc = add_posix_context(iov, &n_iov, mode);
- if (rc)
- goto err_free_req;
- pc_buf = iov[n_iov-1].iov_base;
- }
-
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = n_iov;
-
- /* no need to inc num_remote_opens because we close it just below */
- trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, full_path, CREATE_NOT_FILE,
- FILE_WRITE_ATTRIBUTES);
- /* resource #4: response buffer */
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- if (rc) {
- cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
- trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid,
- CREATE_NOT_FILE,
- FILE_WRITE_ATTRIBUTES, rc);
- goto err_free_rsp_buf;
- }
-
- /*
- * Although unlikely to be possible for rsp to be null and rc not set,
- * adding check below is slightly safer long term (and quiets Coverity
- * warning)
- */
- rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
- if (rsp == NULL) {
- rc = -EIO;
- kfree(pc_buf);
- goto err_free_req;
- }
-
- trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid,
- CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES);
-
- SMB2_close(xid, tcon, rsp->PersistentFileId, rsp->VolatileFileId);
-
- /* Eventually save off posix specific response info and timestaps */
-
-err_free_rsp_buf:
- free_rsp_buf(resp_buftype, rsp);
- kfree(pc_buf);
-err_free_req:
- cifs_small_buf_release(req);
-err_free_path:
- kfree(utf16_path);
- return rc;
-}
-
-int
-SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
- struct smb_rqst *rqst, __u8 *oplock,
- struct cifs_open_parms *oparms, __le16 *path)
-{
- struct smb2_create_req *req;
- unsigned int n_iov = 2;
- __u32 file_attributes = 0;
- int copy_size;
- int uni_path_len;
- unsigned int total_len;
- struct kvec *iov = rqst->rq_iov;
- __le16 *copy_path;
- int rc;
-
- rc = smb2_plain_req_init(SMB2_CREATE, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- iov[0].iov_base = (char *)req;
- /* -1 since last byte is buf[0] which is sent below (path) */
- iov[0].iov_len = total_len - 1;
-
- if (oparms->create_options & CREATE_OPTION_READONLY)
- file_attributes |= ATTR_READONLY;
- if (oparms->create_options & CREATE_OPTION_SPECIAL)
- file_attributes |= ATTR_SYSTEM;
-
- req->ImpersonationLevel = IL_IMPERSONATION;
- req->DesiredAccess = cpu_to_le32(oparms->desired_access);
- /* File attributes ignored on open (used in create though) */
- req->FileAttributes = cpu_to_le32(file_attributes);
- req->ShareAccess = FILE_SHARE_ALL_LE;
-
- req->CreateDisposition = cpu_to_le32(oparms->disposition);
- req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK);
- req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
-
- /* [MS-SMB2] 2.2.13 NameOffset:
- * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
- * the SMB2 header, the file name includes a prefix that will
- * be processed during DFS name normalization as specified in
- * section 3.3.5.9. Otherwise, the file name is relative to
- * the share that is identified by the TreeId in the SMB2
- * header.
- */
- if (tcon->share_flags & SHI1005_FLAGS_DFS) {
- int name_len;
-
- req->hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
- rc = alloc_path_with_tree_prefix(©_path, ©_size,
- &name_len,
- tcon->tree_name, path);
- if (rc)
- return rc;
- req->NameLength = cpu_to_le16(name_len * 2);
- uni_path_len = copy_size;
- path = copy_path;
- } else {
- uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
- /* MUST set path len (NameLength) to 0 opening root of share */
- req->NameLength = cpu_to_le16(uni_path_len - 2);
- copy_size = round_up(uni_path_len, 8);
- copy_path = kzalloc(copy_size, GFP_KERNEL);
- if (!copy_path)
- return -ENOMEM;
- memcpy((char *)copy_path, (const char *)path,
- uni_path_len);
- uni_path_len = copy_size;
- path = copy_path;
- }
-
- iov[1].iov_len = uni_path_len;
- iov[1].iov_base = path;
-
- if ((!server->oplocks) || (tcon->no_lease))
- *oplock = SMB2_OPLOCK_LEVEL_NONE;
-
- if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) ||
- *oplock == SMB2_OPLOCK_LEVEL_NONE)
- req->RequestedOplockLevel = *oplock;
- else if (!(server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) &&
- (oparms->create_options & CREATE_NOT_FILE))
- req->RequestedOplockLevel = *oplock; /* no srv lease support */
- else {
- rc = add_lease_context(server, iov, &n_iov,
- oparms->fid->lease_key, oplock);
- if (rc)
- return rc;
- }
-
- if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) {
- /* need to set Next field of lease context if we request it */
- if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) {
- struct create_context *ccontext =
- (struct create_context *)iov[n_iov-1].iov_base;
- ccontext->Next =
- cpu_to_le32(server->vals->create_lease_size);
- }
-
- rc = add_durable_context(iov, &n_iov, oparms,
- tcon->use_persistent);
- if (rc)
- return rc;
- }
-
- if (tcon->posix_extensions) {
- if (n_iov > 2) {
- struct create_context *ccontext =
- (struct create_context *)iov[n_iov-1].iov_base;
- ccontext->Next =
- cpu_to_le32(iov[n_iov-1].iov_len);
- }
-
- rc = add_posix_context(iov, &n_iov, oparms->mode);
- if (rc)
- return rc;
- }
-
- if (tcon->snapshot_time) {
- cifs_dbg(FYI, "adding snapshot context\n");
- if (n_iov > 2) {
- struct create_context *ccontext =
- (struct create_context *)iov[n_iov-1].iov_base;
- ccontext->Next =
- cpu_to_le32(iov[n_iov-1].iov_len);
- }
-
- rc = add_twarp_context(iov, &n_iov, tcon->snapshot_time);
- if (rc)
- return rc;
- }
-
- if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) {
- bool set_mode;
- bool set_owner;
-
- if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
- (oparms->mode != ACL_NO_MODE))
- set_mode = true;
- else {
- set_mode = false;
- oparms->mode = ACL_NO_MODE;
- }
-
- if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
- set_owner = true;
- else
- set_owner = false;
-
- if (set_owner | set_mode) {
- if (n_iov > 2) {
- struct create_context *ccontext =
- (struct create_context *)iov[n_iov-1].iov_base;
- ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
- }
-
- cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
- rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner);
- if (rc)
- return rc;
- }
- }
-
- if (n_iov > 2) {
- struct create_context *ccontext =
- (struct create_context *)iov[n_iov-1].iov_base;
- ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
- }
- add_query_id_context(iov, &n_iov);
-
- rqst->rq_nvec = n_iov;
- return 0;
-}
-
-/* rq_iov[0] is the request and is released by cifs_small_buf_release().
- * All other vectors are freed by kfree().
- */
-void
-SMB2_open_free(struct smb_rqst *rqst)
-{
- int i;
-
- if (rqst && rqst->rq_iov) {
- cifs_small_buf_release(rqst->rq_iov[0].iov_base);
- for (i = 1; i < rqst->rq_nvec; i++)
- if (rqst->rq_iov[i].iov_base != smb2_padding)
- kfree(rqst->rq_iov[i].iov_base);
- }
-}
-
-int
-SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
- __u8 *oplock, struct smb2_file_all_info *buf,
- struct create_posix_rsp *posix,
- struct kvec *err_iov, int *buftype)
-{
- struct smb_rqst rqst;
- struct smb2_create_rsp *rsp = NULL;
- struct cifs_tcon *tcon = oparms->tcon;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- struct kvec iov[SMB2_CREATE_IOV_SIZE];
- struct kvec rsp_iov = {NULL, 0};
- int resp_buftype = CIFS_NO_BUFFER;
- int rc = 0;
- int flags = 0;
-
- cifs_dbg(FYI, "create/open\n");
- if (!ses || !server)
- return -EIO;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- memset(&iov, 0, sizeof(iov));
- rqst.rq_iov = iov;
- rqst.rq_nvec = SMB2_CREATE_IOV_SIZE;
-
- rc = SMB2_open_init(tcon, server,
- &rqst, oplock, oparms, path);
- if (rc)
- goto creat_exit;
-
- trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, oparms->path,
- oparms->create_options, oparms->desired_access);
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags,
- &rsp_iov);
- rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
-
- if (rc != 0) {
- cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
- if (err_iov && rsp) {
- *err_iov = rsp_iov;
- *buftype = resp_buftype;
- resp_buftype = CIFS_NO_BUFFER;
- rsp = NULL;
- }
- trace_smb3_open_err(xid, tcon->tid, ses->Suid,
- oparms->create_options, oparms->desired_access, rc);
- if (rc == -EREMCHG) {
- pr_warn_once("server share %s deleted\n",
- tcon->tree_name);
- tcon->need_reconnect = true;
- }
- goto creat_exit;
- } else if (rsp == NULL) /* unlikely to happen, but safer to check */
- goto creat_exit;
- else
- trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid,
- oparms->create_options, oparms->desired_access);
-
- atomic_inc(&tcon->num_remote_opens);
- oparms->fid->persistent_fid = rsp->PersistentFileId;
- oparms->fid->volatile_fid = rsp->VolatileFileId;
- oparms->fid->access = oparms->desired_access;
-#ifdef CONFIG_CIFS_DEBUG2
- oparms->fid->mid = le64_to_cpu(rsp->hdr.MessageId);
-#endif /* CIFS_DEBUG2 */
-
- if (buf) {
- buf->CreationTime = rsp->CreationTime;
- buf->LastAccessTime = rsp->LastAccessTime;
- buf->LastWriteTime = rsp->LastWriteTime;
- buf->ChangeTime = rsp->ChangeTime;
- buf->AllocationSize = rsp->AllocationSize;
- buf->EndOfFile = rsp->EndofFile;
- buf->Attributes = rsp->FileAttributes;
- buf->NumberOfLinks = cpu_to_le32(1);
- buf->DeletePending = 0;
- }
-
-
- smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
- oparms->fid->lease_key, oplock, buf, posix);
-creat_exit:
- SMB2_open_free(&rqst);
- free_rsp_buf(resp_buftype, rsp);
- return rc;
-}
-
-int
-SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid, u32 opcode,
- char *in_data, u32 indatalen,
- __u32 max_response_size)
-{
- struct smb2_ioctl_req *req;
- struct kvec *iov = rqst->rq_iov;
- unsigned int total_len;
- int rc;
- char *in_data_buf;
-
- rc = smb2_ioctl_req_init(opcode, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- if (indatalen) {
- /*
- * indatalen is usually small at a couple of bytes max, so
- * just allocate through generic pool
- */
- in_data_buf = kmemdup(in_data, indatalen, GFP_NOFS);
- if (!in_data_buf) {
- cifs_small_buf_release(req);
- return -ENOMEM;
- }
- }
-
- req->CtlCode = cpu_to_le32(opcode);
- req->PersistentFileId = persistent_fid;
- req->VolatileFileId = volatile_fid;
-
- iov[0].iov_base = (char *)req;
- /*
- * If no input data, the size of ioctl struct in
- * protocol spec still includes a 1 byte data buffer,
- * but if input data passed to ioctl, we do not
- * want to double count this, so we do not send
- * the dummy one byte of data in iovec[0] if sending
- * input data (in iovec[1]).
- */
- if (indatalen) {
- req->InputCount = cpu_to_le32(indatalen);
- /* do not set InputOffset if no input data */
- req->InputOffset =
- cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer));
- rqst->rq_nvec = 2;
- iov[0].iov_len = total_len - 1;
- iov[1].iov_base = in_data_buf;
- iov[1].iov_len = indatalen;
- } else {
- rqst->rq_nvec = 1;
- iov[0].iov_len = total_len;
- }
-
- req->OutputOffset = 0;
- req->OutputCount = 0; /* MBZ */
-
- /*
- * In most cases max_response_size is set to 16K (CIFSMaxBufSize)
- * We Could increase default MaxOutputResponse, but that could require
- * more credits. Windows typically sets this smaller, but for some
- * ioctls it may be useful to allow server to send more. No point
- * limiting what the server can send as long as fits in one credit
- * We can not handle more than CIFS_MAX_BUF_SIZE yet but may want
- * to increase this limit up in the future.
- * Note that for snapshot queries that servers like Azure expect that
- * the first query be minimal size (and just used to get the number/size
- * of previous versions) so response size must be specified as EXACTLY
- * sizeof(struct snapshot_array) which is 16 when rounded up to multiple
- * of eight bytes. Currently that is the only case where we set max
- * response size smaller.
- */
- req->MaxOutputResponse = cpu_to_le32(max_response_size);
- req->hdr.CreditCharge =
- cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size),
- SMB2_MAX_BUFFER_SIZE));
- /* always an FSCTL (for now) */
- req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
-
- /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
- if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
- req->hdr.Flags |= SMB2_FLAGS_SIGNED;
-
- return 0;
-}
-
-void
-SMB2_ioctl_free(struct smb_rqst *rqst)
-{
- int i;
- if (rqst && rqst->rq_iov) {
- cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
- for (i = 1; i < rqst->rq_nvec; i++)
- if (rqst->rq_iov[i].iov_base != smb2_padding)
- kfree(rqst->rq_iov[i].iov_base);
- }
-}
-
-
-/*
- * SMB2 IOCTL is used for both IOCTLs and FSCTLs
- */
-int
-SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
- u64 volatile_fid, u32 opcode, char *in_data, u32 indatalen,
- u32 max_out_data_len, char **out_data,
- u32 *plen /* returned data len */)
-{
- struct smb_rqst rqst;
- struct smb2_ioctl_rsp *rsp = NULL;
- struct cifs_ses *ses;
- struct TCP_Server_Info *server;
- struct kvec iov[SMB2_IOCTL_IOV_SIZE];
- struct kvec rsp_iov = {NULL, 0};
- int resp_buftype = CIFS_NO_BUFFER;
- int rc = 0;
- int flags = 0;
-
- cifs_dbg(FYI, "SMB2 IOCTL\n");
-
- if (out_data != NULL)
- *out_data = NULL;
-
- /* zero out returned data len, in case of error */
- if (plen)
- *plen = 0;
-
- if (!tcon)
- return -EIO;
-
- ses = tcon->ses;
- if (!ses)
- return -EIO;
-
- server = cifs_pick_channel(ses);
- if (!server)
- return -EIO;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- memset(&iov, 0, sizeof(iov));
- rqst.rq_iov = iov;
- rqst.rq_nvec = SMB2_IOCTL_IOV_SIZE;
-
- rc = SMB2_ioctl_init(tcon, server,
- &rqst, persistent_fid, volatile_fid, opcode,
- in_data, indatalen, max_out_data_len);
- if (rc)
- goto ioctl_exit;
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags,
- &rsp_iov);
- rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base;
-
- if (rc != 0)
- trace_smb3_fsctl_err(xid, persistent_fid, tcon->tid,
- ses->Suid, 0, opcode, rc);
-
- if ((rc != 0) && (rc != -EINVAL) && (rc != -E2BIG)) {
- cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
- goto ioctl_exit;
- } else if (rc == -EINVAL) {
- if ((opcode != FSCTL_SRV_COPYCHUNK_WRITE) &&
- (opcode != FSCTL_SRV_COPYCHUNK)) {
- cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
- goto ioctl_exit;
- }
- } else if (rc == -E2BIG) {
- if (opcode != FSCTL_QUERY_ALLOCATED_RANGES) {
- cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
- goto ioctl_exit;
- }
- }
-
- /* check if caller wants to look at return data or just return rc */
- if ((plen == NULL) || (out_data == NULL))
- goto ioctl_exit;
-
- /*
- * Although unlikely to be possible for rsp to be null and rc not set,
- * adding check below is slightly safer long term (and quiets Coverity
- * warning)
- */
- if (rsp == NULL) {
- rc = -EIO;
- goto ioctl_exit;
- }
-
- *plen = le32_to_cpu(rsp->OutputCount);
-
- /* We check for obvious errors in the output buffer length and offset */
- if (*plen == 0)
- goto ioctl_exit; /* server returned no data */
- else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) {
- cifs_tcon_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen);
- *plen = 0;
- rc = -EIO;
- goto ioctl_exit;
- }
-
- if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) {
- cifs_tcon_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
- le32_to_cpu(rsp->OutputOffset));
- *plen = 0;
- rc = -EIO;
- goto ioctl_exit;
- }
-
- *out_data = kmemdup((char *)rsp + le32_to_cpu(rsp->OutputOffset),
- *plen, GFP_KERNEL);
- if (*out_data == NULL) {
- rc = -ENOMEM;
- goto ioctl_exit;
- }
-
-ioctl_exit:
- SMB2_ioctl_free(&rqst);
- free_rsp_buf(resp_buftype, rsp);
- return rc;
-}
-
-/*
- * Individual callers to ioctl worker function follow
- */
-
-int
-SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid)
-{
- int rc;
- struct compress_ioctl fsctl_input;
- char *ret_data = NULL;
-
- fsctl_input.CompressionState =
- cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
-
- rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
- FSCTL_SET_COMPRESSION,
- (char *)&fsctl_input /* data input */,
- 2 /* in data len */, CIFSMaxBufSize /* max out data */,
- &ret_data /* out data */, NULL);
-
- cifs_dbg(FYI, "set compression rc %d\n", rc);
-
- return rc;
-}
-
-int
-SMB2_close_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid, bool query_attrs)
-{
- struct smb2_close_req *req;
- struct kvec *iov = rqst->rq_iov;
- unsigned int total_len;
- int rc;
-
- rc = smb2_plain_req_init(SMB2_CLOSE, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- req->PersistentFileId = persistent_fid;
- req->VolatileFileId = volatile_fid;
- if (query_attrs)
- req->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB;
- else
- req->Flags = 0;
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
-
- return 0;
-}
-
-void
-SMB2_close_free(struct smb_rqst *rqst)
-{
- if (rqst && rqst->rq_iov)
- cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
-}
-
-int
-__SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- struct smb2_file_network_open_info *pbuf)
-{
- struct smb_rqst rqst;
- struct smb2_close_rsp *rsp = NULL;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- struct kvec iov[1];
- struct kvec rsp_iov;
- int resp_buftype = CIFS_NO_BUFFER;
- int rc = 0;
- int flags = 0;
- bool query_attrs = false;
-
- cifs_dbg(FYI, "Close\n");
-
- if (!ses || !server)
- return -EIO;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- memset(&iov, 0, sizeof(iov));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- /* check if need to ask server to return timestamps in close response */
- if (pbuf)
- query_attrs = true;
-
- trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid);
- rc = SMB2_close_init(tcon, server,
- &rqst, persistent_fid, volatile_fid,
- query_attrs);
- if (rc)
- goto close_exit;
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- rsp = (struct smb2_close_rsp *)rsp_iov.iov_base;
-
- if (rc != 0) {
- cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
- trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid,
- rc);
- goto close_exit;
- } else {
- trace_smb3_close_done(xid, persistent_fid, tcon->tid,
- ses->Suid);
- /*
- * Note that have to subtract 4 since struct network_open_info
- * has a final 4 byte pad that close response does not have
- */
- if (pbuf)
- memcpy(pbuf, (char *)&rsp->CreationTime, sizeof(*pbuf) - 4);
- }
-
- atomic_dec(&tcon->num_remote_opens);
-close_exit:
- SMB2_close_free(&rqst);
- free_rsp_buf(resp_buftype, rsp);
-
- /* retry close in a worker thread if this one is interrupted */
- if (is_interrupt_error(rc)) {
- int tmp_rc;
-
- tmp_rc = smb2_handle_cancelled_close(tcon, persistent_fid,
- volatile_fid);
- if (tmp_rc)
- cifs_dbg(VFS, "handle cancelled close fid 0x%llx returned error %d\n",
- persistent_fid, tmp_rc);
- }
- return rc;
-}
-
-int
-SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid)
-{
- return __SMB2_close(xid, tcon, persistent_fid, volatile_fid, NULL);
-}
-
-int
-smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
- struct kvec *iov, unsigned int min_buf_size)
-{
- unsigned int smb_len = iov->iov_len;
- char *end_of_smb = smb_len + (char *)iov->iov_base;
- char *begin_of_buf = offset + (char *)iov->iov_base;
- char *end_of_buf = begin_of_buf + buffer_length;
-
-
- if (buffer_length < min_buf_size) {
- cifs_dbg(VFS, "buffer length %d smaller than minimum size %d\n",
- buffer_length, min_buf_size);
- return -EINVAL;
- }
-
- /* check if beyond RFC1001 maximum length */
- if ((smb_len > 0x7FFFFF) || (buffer_length > 0x7FFFFF)) {
- cifs_dbg(VFS, "buffer length %d or smb length %d too large\n",
- buffer_length, smb_len);
- return -EINVAL;
- }
-
- if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) {
- cifs_dbg(VFS, "Invalid server response, bad offset to data\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * If SMB buffer fields are valid, copy into temporary buffer to hold result.
- * Caller must free buffer.
- */
-int
-smb2_validate_and_copy_iov(unsigned int offset, unsigned int buffer_length,
- struct kvec *iov, unsigned int minbufsize,
- char *data)
-{
- char *begin_of_buf = offset + (char *)iov->iov_base;
- int rc;
-
- if (!data)
- return -EINVAL;
-
- rc = smb2_validate_iov(offset, buffer_length, iov, minbufsize);
- if (rc)
- return rc;
-
- memcpy(data, begin_of_buf, minbufsize);
-
- return 0;
-}
-
-int
-SMB2_query_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid,
- u8 info_class, u8 info_type, u32 additional_info,
- size_t output_len, size_t input_len, void *input)
-{
- struct smb2_query_info_req *req;
- struct kvec *iov = rqst->rq_iov;
- unsigned int total_len;
- int rc;
-
- rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- req->InfoType = info_type;
- req->FileInfoClass = info_class;
- req->PersistentFileId = persistent_fid;
- req->VolatileFileId = volatile_fid;
- req->AdditionalInformation = cpu_to_le32(additional_info);
-
- req->OutputBufferLength = cpu_to_le32(output_len);
- if (input_len) {
- req->InputBufferLength = cpu_to_le32(input_len);
- /* total_len for smb query request never close to le16 max */
- req->InputBufferOffset = cpu_to_le16(total_len - 1);
- memcpy(req->Buffer, input, input_len);
- }
-
- iov[0].iov_base = (char *)req;
- /* 1 for Buffer */
- iov[0].iov_len = total_len - 1 + input_len;
- return 0;
-}
-
-void
-SMB2_query_info_free(struct smb_rqst *rqst)
-{
- if (rqst && rqst->rq_iov)
- cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
-}
-
-static int
-query_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, u8 info_class, u8 info_type,
- u32 additional_info, size_t output_len, size_t min_len, void **data,
- u32 *dlen)
-{
- struct smb_rqst rqst;
- struct smb2_query_info_rsp *rsp = NULL;
- struct kvec iov[1];
- struct kvec rsp_iov;
- int rc = 0;
- int resp_buftype = CIFS_NO_BUFFER;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server;
- int flags = 0;
- bool allocated = false;
-
- cifs_dbg(FYI, "Query Info\n");
-
- if (!ses)
- return -EIO;
- server = cifs_pick_channel(ses);
- if (!server)
- return -EIO;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- memset(&iov, 0, sizeof(iov));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- rc = SMB2_query_info_init(tcon, server,
- &rqst, persistent_fid, volatile_fid,
- info_class, info_type, additional_info,
- output_len, 0, NULL);
- if (rc)
- goto qinf_exit;
-
- trace_smb3_query_info_enter(xid, persistent_fid, tcon->tid,
- ses->Suid, info_class, (__u32)info_type);
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
-
- if (rc) {
- cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
- trace_smb3_query_info_err(xid, persistent_fid, tcon->tid,
- ses->Suid, info_class, (__u32)info_type, rc);
- goto qinf_exit;
- }
-
- trace_smb3_query_info_done(xid, persistent_fid, tcon->tid,
- ses->Suid, info_class, (__u32)info_type);
-
- if (dlen) {
- *dlen = le32_to_cpu(rsp->OutputBufferLength);
- if (!*data) {
- *data = kmalloc(*dlen, GFP_KERNEL);
- if (!*data) {
- cifs_tcon_dbg(VFS,
- "Error %d allocating memory for acl\n",
- rc);
- *dlen = 0;
- rc = -ENOMEM;
- goto qinf_exit;
- }
- allocated = true;
- }
- }
-
- rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
- le32_to_cpu(rsp->OutputBufferLength),
- &rsp_iov, dlen ? *dlen : min_len, *data);
- if (rc && allocated) {
- kfree(*data);
- *data = NULL;
- *dlen = 0;
- }
-
-qinf_exit:
- SMB2_query_info_free(&rqst);
- free_rsp_buf(resp_buftype, rsp);
- return rc;
-}
-
-int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, struct smb2_file_all_info *data)
-{
- return query_info(xid, tcon, persistent_fid, volatile_fid,
- FILE_ALL_INFORMATION, SMB2_O_INFO_FILE, 0,
- sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
- sizeof(struct smb2_file_all_info), (void **)&data,
- NULL);
-}
-
-#if 0
-/* currently unused, as now we are doing compounding instead (see smb311_posix_query_path_info) */
-int
-SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen)
-{
- size_t output_len = sizeof(struct smb311_posix_qinfo *) +
- (sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2);
- *plen = 0;
-
- return query_info(xid, tcon, persistent_fid, volatile_fid,
- SMB_FIND_FILE_POSIX_INFO, SMB2_O_INFO_FILE, 0,
- output_len, sizeof(struct smb311_posix_qinfo), (void **)&data, plen);
- /* Note caller must free "data" (passed in above). It may be allocated in query_info call */
-}
-#endif
-
-int
-SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- void **data, u32 *plen, u32 extra_info)
-{
- __u32 additional_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
- extra_info;
- *plen = 0;
-
- return query_info(xid, tcon, persistent_fid, volatile_fid,
- 0, SMB2_O_INFO_SECURITY, additional_info,
- SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen);
-}
-
-int
-SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, __le64 *uniqueid)
-{
- return query_info(xid, tcon, persistent_fid, volatile_fid,
- FILE_INTERNAL_INFORMATION, SMB2_O_INFO_FILE, 0,
- sizeof(struct smb2_file_internal_info),
- sizeof(struct smb2_file_internal_info),
- (void **)&uniqueid, NULL);
-}
-
-/*
- * CHANGE_NOTIFY Request is sent to get notifications on changes to a directory
- * See MS-SMB2 2.2.35 and 2.2.36
- */
-
-static int
-SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst,
- struct cifs_tcon *tcon, struct TCP_Server_Info *server,
- u64 persistent_fid, u64 volatile_fid,
- u32 completion_filter, bool watch_tree)
-{
- struct smb2_change_notify_req *req;
- struct kvec *iov = rqst->rq_iov;
- unsigned int total_len;
- int rc;
-
- rc = smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- req->PersistentFileId = persistent_fid;
- req->VolatileFileId = volatile_fid;
- /* See note 354 of MS-SMB2, 64K max */
- req->OutputBufferLength =
- cpu_to_le32(SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE);
- req->CompletionFilter = cpu_to_le32(completion_filter);
- if (watch_tree)
- req->Flags = cpu_to_le16(SMB2_WATCH_TREE);
- else
- req->Flags = 0;
-
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
-
- return 0;
-}
-
-int
-SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, bool watch_tree,
- u32 completion_filter, u32 max_out_data_len, char **out_data,
- u32 *plen /* returned data len */)
-{
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- struct smb_rqst rqst;
- struct smb2_change_notify_rsp *smb_rsp;
- struct kvec iov[1];
- struct kvec rsp_iov = {NULL, 0};
- int resp_buftype = CIFS_NO_BUFFER;
- int flags = 0;
- int rc = 0;
-
- cifs_dbg(FYI, "change notify\n");
- if (!ses || !server)
- return -EIO;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- memset(&iov, 0, sizeof(iov));
- if (plen)
- *plen = 0;
-
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- rc = SMB2_notify_init(xid, &rqst, tcon, server,
- persistent_fid, volatile_fid,
- completion_filter, watch_tree);
- if (rc)
- goto cnotify_exit;
-
- trace_smb3_notify_enter(xid, persistent_fid, tcon->tid, ses->Suid,
- (u8)watch_tree, completion_filter);
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
-
- if (rc != 0) {
- cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE);
- trace_smb3_notify_err(xid, persistent_fid, tcon->tid, ses->Suid,
- (u8)watch_tree, completion_filter, rc);
- } else {
- trace_smb3_notify_done(xid, persistent_fid, tcon->tid,
- ses->Suid, (u8)watch_tree, completion_filter);
- /* validate that notify information is plausible */
- if ((rsp_iov.iov_base == NULL) ||
- (rsp_iov.iov_len < sizeof(struct smb2_change_notify_rsp)))
- goto cnotify_exit;
-
- smb_rsp = (struct smb2_change_notify_rsp *)rsp_iov.iov_base;
-
- smb2_validate_iov(le16_to_cpu(smb_rsp->OutputBufferOffset),
- le32_to_cpu(smb_rsp->OutputBufferLength), &rsp_iov,
- sizeof(struct file_notify_information));
-
- *out_data = kmemdup((char *)smb_rsp + le16_to_cpu(smb_rsp->OutputBufferOffset),
- le32_to_cpu(smb_rsp->OutputBufferLength), GFP_KERNEL);
- if (*out_data == NULL) {
- rc = -ENOMEM;
- goto cnotify_exit;
- } else
- *plen = le32_to_cpu(smb_rsp->OutputBufferLength);
- }
-
- cnotify_exit:
- if (rqst.rq_iov)
- cifs_small_buf_release(rqst.rq_iov[0].iov_base); /* request */
- free_rsp_buf(resp_buftype, rsp_iov.iov_base);
- return rc;
-}
-
-
-
-/*
- * This is a no-op for now. We're not really interested in the reply, but
- * rather in the fact that the server sent one and that server->lstrp
- * gets updated.
- *
- * FIXME: maybe we should consider checking that the reply matches request?
- */
-static void
-smb2_echo_callback(struct mid_q_entry *mid)
-{
- struct TCP_Server_Info *server = mid->callback_data;
- struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
- struct cifs_credits credits = { .value = 0, .instance = 0 };
-
- if (mid->mid_state == MID_RESPONSE_RECEIVED
- || mid->mid_state == MID_RESPONSE_MALFORMED) {
- credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
- credits.instance = server->reconnect_instance;
- }
-
- release_mid(mid);
- add_credits(server, &credits, CIFS_ECHO_OP);
-}
-
-void smb2_reconnect_server(struct work_struct *work)
-{
- struct TCP_Server_Info *server = container_of(work,
- struct TCP_Server_Info, reconnect.work);
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses, *ses2;
- struct cifs_tcon *tcon, *tcon2;
- struct list_head tmp_list, tmp_ses_list;
- bool tcon_exist = false, ses_exist = false;
- bool tcon_selected = false;
- int rc;
- bool resched = false;
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
- /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
- mutex_lock(&pserver->reconnect_mutex);
-
- INIT_LIST_HEAD(&tmp_list);
- INIT_LIST_HEAD(&tmp_ses_list);
- cifs_dbg(FYI, "Reconnecting tcons and channels\n");
-
- spin_lock(&cifs_tcp_ses_lock);
- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
-
- tcon_selected = false;
-
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- if (tcon->need_reconnect || tcon->need_reopen_files) {
- tcon->tc_count++;
- list_add_tail(&tcon->rlist, &tmp_list);
- tcon_selected = tcon_exist = true;
- }
- }
- /*
- * IPC has the same lifetime as its session and uses its
- * refcount.
- */
- if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) {
- list_add_tail(&ses->tcon_ipc->rlist, &tmp_list);
- tcon_selected = tcon_exist = true;
- ses->ses_count++;
- }
- /*
- * handle the case where channel needs to reconnect
- * binding session, but tcon is healthy (some other channel
- * is active)
- */
- spin_lock(&ses->chan_lock);
- if (!tcon_selected && cifs_chan_needs_reconnect(ses, server)) {
- list_add_tail(&ses->rlist, &tmp_ses_list);
- ses_exist = true;
- ses->ses_count++;
- }
- spin_unlock(&ses->chan_lock);
- }
- /*
- * Get the reference to server struct to be sure that the last call of
- * cifs_put_tcon() in the loop below won't release the server pointer.
- */
- if (tcon_exist || ses_exist)
- server->srv_count++;
-
- spin_unlock(&cifs_tcp_ses_lock);
-
- list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
- rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server);
- if (!rc)
- cifs_reopen_persistent_handles(tcon);
- else
- resched = true;
- list_del_init(&tcon->rlist);
- if (tcon->ipc)
- cifs_put_smb_ses(tcon->ses);
- else
- cifs_put_tcon(tcon);
- }
-
- if (!ses_exist)
- goto done;
-
- /* allocate a dummy tcon struct used for reconnect */
- tcon = tconInfoAlloc();
- if (!tcon) {
- resched = true;
- list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
- list_del_init(&ses->rlist);
- cifs_put_smb_ses(ses);
- }
- goto done;
- }
-
- tcon->status = TID_GOOD;
- tcon->retry = false;
- tcon->need_reconnect = false;
-
- /* now reconnect sessions for necessary channels */
- list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
- tcon->ses = ses;
- rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server);
- if (rc)
- resched = true;
- list_del_init(&ses->rlist);
- cifs_put_smb_ses(ses);
- }
- tconInfoFree(tcon);
-
-done:
- cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");
- if (resched)
- queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
- mutex_unlock(&pserver->reconnect_mutex);
-
- /* now we can safely release srv struct */
- if (tcon_exist || ses_exist)
- cifs_put_tcp_session(server, 1);
-}
-
-int
-SMB2_echo(struct TCP_Server_Info *server)
-{
- struct smb2_echo_req *req;
- int rc = 0;
- struct kvec iov[1];
- struct smb_rqst rqst = { .rq_iov = iov,
- .rq_nvec = 1 };
- unsigned int total_len;
-
- cifs_dbg(FYI, "In echo request for conn_id %lld\n", server->conn_id);
-
- spin_lock(&server->srv_lock);
- if (server->ops->need_neg &&
- server->ops->need_neg(server)) {
- spin_unlock(&server->srv_lock);
- /* No need to send echo on newly established connections */
- mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
- return rc;
- }
- spin_unlock(&server->srv_lock);
-
- rc = smb2_plain_req_init(SMB2_ECHO, NULL, server,
- (void **)&req, &total_len);
- if (rc)
- return rc;
-
- req->hdr.CreditRequest = cpu_to_le16(1);
-
- iov[0].iov_len = total_len;
- iov[0].iov_base = (char *)req;
-
- rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL,
- server, CIFS_ECHO_OP, NULL);
- if (rc)
- cifs_dbg(FYI, "Echo request failed: %d\n", rc);
-
- cifs_small_buf_release(req);
- return rc;
-}
-
-void
-SMB2_flush_free(struct smb_rqst *rqst)
-{
- if (rqst && rqst->rq_iov)
- cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
-}
-
-int
-SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst,
- struct cifs_tcon *tcon, struct TCP_Server_Info *server,
- u64 persistent_fid, u64 volatile_fid)
-{
- struct smb2_flush_req *req;
- struct kvec *iov = rqst->rq_iov;
- unsigned int total_len;
- int rc;
-
- rc = smb2_plain_req_init(SMB2_FLUSH, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- req->PersistentFileId = persistent_fid;
- req->VolatileFileId = volatile_fid;
-
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
-
- return 0;
-}
-
-int
-SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
- u64 volatile_fid)
-{
- struct cifs_ses *ses = tcon->ses;
- struct smb_rqst rqst;
- struct kvec iov[1];
- struct kvec rsp_iov = {NULL, 0};
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- int resp_buftype = CIFS_NO_BUFFER;
- int flags = 0;
- int rc = 0;
-
- cifs_dbg(FYI, "flush\n");
- if (!ses || !(ses->server))
- return -EIO;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- memset(&iov, 0, sizeof(iov));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- rc = SMB2_flush_init(xid, &rqst, tcon, server,
- persistent_fid, volatile_fid);
- if (rc)
- goto flush_exit;
-
- trace_smb3_flush_enter(xid, persistent_fid, tcon->tid, ses->Suid);
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
-
- if (rc != 0) {
- cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE);
- trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid,
- rc);
- } else
- trace_smb3_flush_done(xid, persistent_fid, tcon->tid,
- ses->Suid);
-
- flush_exit:
- SMB2_flush_free(&rqst);
- free_rsp_buf(resp_buftype, rsp_iov.iov_base);
- return rc;
-}
-
-#ifdef CONFIG_CIFS_SMB_DIRECT
-static inline bool smb3_use_rdma_offload(struct cifs_io_parms *io_parms)
-{
- struct TCP_Server_Info *server = io_parms->server;
- struct cifs_tcon *tcon = io_parms->tcon;
-
- /* we can only offload if we're connected */
- if (!server || !tcon)
- return false;
-
- /* we can only offload on an rdma connection */
- if (!server->rdma || !server->smbd_conn)
- return false;
-
- /* we don't support signed offload yet */
- if (server->sign)
- return false;
-
- /* we don't support encrypted offload yet */
- if (smb3_encryption_required(tcon))
- return false;
-
- /* offload also has its overhead, so only do it if desired */
- if (io_parms->length < server->smbd_conn->rdma_readwrite_threshold)
- return false;
-
- return true;
-}
-#endif /* CONFIG_CIFS_SMB_DIRECT */
-
-/*
- * To form a chain of read requests, any read requests after the first should
- * have the end_of_chain boolean set to true.
- */
-static int
-smb2_new_read_req(void **buf, unsigned int *total_len,
- struct cifs_io_parms *io_parms, struct cifs_readdata *rdata,
- unsigned int remaining_bytes, int request_type)
-{
- int rc = -EACCES;
- struct smb2_read_req *req = NULL;
- struct smb2_hdr *shdr;
- struct TCP_Server_Info *server = io_parms->server;
-
- rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, server,
- (void **) &req, total_len);
- if (rc)
- return rc;
-
- if (server == NULL)
- return -ECONNABORTED;
-
- shdr = &req->hdr;
- shdr->Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid);
-
- req->PersistentFileId = io_parms->persistent_fid;
- req->VolatileFileId = io_parms->volatile_fid;
- req->ReadChannelInfoOffset = 0; /* reserved */
- req->ReadChannelInfoLength = 0; /* reserved */
- req->Channel = 0; /* reserved */
- req->MinimumCount = 0;
- req->Length = cpu_to_le32(io_parms->length);
- req->Offset = cpu_to_le64(io_parms->offset);
-
- trace_smb3_read_enter(0 /* xid */,
- io_parms->persistent_fid,
- io_parms->tcon->tid, io_parms->tcon->ses->Suid,
- io_parms->offset, io_parms->length);
-#ifdef CONFIG_CIFS_SMB_DIRECT
- /*
- * If we want to do a RDMA write, fill in and append
- * smbd_buffer_descriptor_v1 to the end of read request
- */
- if (smb3_use_rdma_offload(io_parms)) {
- struct smbd_buffer_descriptor_v1 *v1;
- bool need_invalidate = server->dialect == SMB30_PROT_ID;
-
- rdata->mr = smbd_register_mr(
- server->smbd_conn, rdata->pages,
- rdata->nr_pages, rdata->page_offset,
- rdata->tailsz, true, need_invalidate);
- if (!rdata->mr)
- return -EAGAIN;
-
- req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
- if (need_invalidate)
- req->Channel = SMB2_CHANNEL_RDMA_V1;
- req->ReadChannelInfoOffset =
- cpu_to_le16(offsetof(struct smb2_read_req, Buffer));
- req->ReadChannelInfoLength =
- cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
- v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
- v1->offset = cpu_to_le64(rdata->mr->mr->iova);
- v1->token = cpu_to_le32(rdata->mr->mr->rkey);
- v1->length = cpu_to_le32(rdata->mr->mr->length);
-
- *total_len += sizeof(*v1) - 1;
- }
-#endif
- if (request_type & CHAINED_REQUEST) {
- if (!(request_type & END_OF_CHAIN)) {
- /* next 8-byte aligned request */
- *total_len = ALIGN(*total_len, 8);
- shdr->NextCommand = cpu_to_le32(*total_len);
- } else /* END_OF_CHAIN */
- shdr->NextCommand = 0;
- if (request_type & RELATED_REQUEST) {
- shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
- /*
- * Related requests use info from previous read request
- * in chain.
- */
- shdr->SessionId = cpu_to_le64(0xFFFFFFFFFFFFFFFF);
- shdr->Id.SyncId.TreeId = cpu_to_le32(0xFFFFFFFF);
- req->PersistentFileId = (u64)-1;
- req->VolatileFileId = (u64)-1;
- }
- }
- if (remaining_bytes > io_parms->length)
- req->RemainingBytes = cpu_to_le32(remaining_bytes);
- else
- req->RemainingBytes = 0;
-
- *buf = req;
- return rc;
-}
-
-static void
-smb2_readv_callback(struct mid_q_entry *mid)
-{
- struct cifs_readdata *rdata = mid->callback_data;
- struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
- struct TCP_Server_Info *server = rdata->server;
- struct smb2_hdr *shdr =
- (struct smb2_hdr *)rdata->iov[0].iov_base;
- struct cifs_credits credits = { .value = 0, .instance = 0 };
- struct smb_rqst rqst = { .rq_iov = &rdata->iov[1],
- .rq_nvec = 1, };
-
- if (rdata->got_bytes) {
- rqst.rq_pages = rdata->pages;
- rqst.rq_offset = rdata->page_offset;
- rqst.rq_npages = rdata->nr_pages;
- rqst.rq_pagesz = rdata->pagesz;
- rqst.rq_tailsz = rdata->tailsz;
- }
-
- WARN_ONCE(rdata->server != mid->server,
- "rdata server %p != mid server %p",
- rdata->server, mid->server);
-
- cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
- __func__, mid->mid, mid->mid_state, rdata->result,
- rdata->bytes);
-
- switch (mid->mid_state) {
- case MID_RESPONSE_RECEIVED:
- credits.value = le16_to_cpu(shdr->CreditRequest);
- credits.instance = server->reconnect_instance;
- /* result already set, check signature */
- if (server->sign && !mid->decrypted) {
- int rc;
-
- rc = smb2_verify_signature(&rqst, server);
- if (rc)
- cifs_tcon_dbg(VFS, "SMB signature verification returned error = %d\n",
- rc);
- }
- /* FIXME: should this be counted toward the initiating task? */
- task_io_account_read(rdata->got_bytes);
- cifs_stats_bytes_read(tcon, rdata->got_bytes);
- break;
- case MID_REQUEST_SUBMITTED:
- case MID_RETRY_NEEDED:
- rdata->result = -EAGAIN;
- if (server->sign && rdata->got_bytes)
- /* reset bytes number since we can not check a sign */
- rdata->got_bytes = 0;
- /* FIXME: should this be counted toward the initiating task? */
- task_io_account_read(rdata->got_bytes);
- cifs_stats_bytes_read(tcon, rdata->got_bytes);
- break;
- case MID_RESPONSE_MALFORMED:
- credits.value = le16_to_cpu(shdr->CreditRequest);
- credits.instance = server->reconnect_instance;
- fallthrough;
- default:
- rdata->result = -EIO;
- }
-#ifdef CONFIG_CIFS_SMB_DIRECT
- /*
- * If this rdata has a memmory registered, the MR can be freed
- * MR needs to be freed as soon as I/O finishes to prevent deadlock
- * because they have limited number and are used for future I/Os
- */
- if (rdata->mr) {
- smbd_deregister_mr(rdata->mr);
- rdata->mr = NULL;
- }
-#endif
- if (rdata->result && rdata->result != -ENODATA) {
- cifs_stats_fail_inc(tcon, SMB2_READ_HE);
- trace_smb3_read_err(0 /* xid */,
- rdata->cfile->fid.persistent_fid,
- tcon->tid, tcon->ses->Suid, rdata->offset,
- rdata->bytes, rdata->result);
- } else
- trace_smb3_read_done(0 /* xid */,
- rdata->cfile->fid.persistent_fid,
- tcon->tid, tcon->ses->Suid,
- rdata->offset, rdata->got_bytes);
-
- queue_work(cifsiod_wq, &rdata->work);
- release_mid(mid);
- add_credits(server, &credits, 0);
-}
-
-/* smb2_async_readv - send an async read, and set up mid to handle result */
-int
-smb2_async_readv(struct cifs_readdata *rdata)
-{
- int rc, flags = 0;
- char *buf;
- struct smb2_hdr *shdr;
- struct cifs_io_parms io_parms;
- struct smb_rqst rqst = { .rq_iov = rdata->iov,
- .rq_nvec = 1 };
- struct TCP_Server_Info *server;
- struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
- unsigned int total_len;
-
- cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
- __func__, rdata->offset, rdata->bytes);
-
- if (!rdata->server)
- rdata->server = cifs_pick_channel(tcon->ses);
-
- io_parms.tcon = tlink_tcon(rdata->cfile->tlink);
- io_parms.server = server = rdata->server;
- io_parms.offset = rdata->offset;
- io_parms.length = rdata->bytes;
- io_parms.persistent_fid = rdata->cfile->fid.persistent_fid;
- io_parms.volatile_fid = rdata->cfile->fid.volatile_fid;
- io_parms.pid = rdata->pid;
-
- rc = smb2_new_read_req(
- (void **) &buf, &total_len, &io_parms, rdata, 0, 0);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(io_parms.tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- rdata->iov[0].iov_base = buf;
- rdata->iov[0].iov_len = total_len;
-
- shdr = (struct smb2_hdr *)buf;
-
- if (rdata->credits.value > 0) {
- shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
- SMB2_MAX_BUFFER_SIZE));
- shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8);
-
- rc = adjust_credits(server, &rdata->credits, rdata->bytes);
- if (rc)
- goto async_readv_out;
-
- flags |= CIFS_HAS_CREDITS;
- }
-
- kref_get(&rdata->refcount);
- rc = cifs_call_async(server, &rqst,
- cifs_readv_receive, smb2_readv_callback,
- smb3_handle_read_data, rdata, flags,
- &rdata->credits);
- if (rc) {
- kref_put(&rdata->refcount, cifs_readdata_release);
- cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
- trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
- io_parms.tcon->tid,
- io_parms.tcon->ses->Suid,
- io_parms.offset, io_parms.length, rc);
- }
-
-async_readv_out:
- cifs_small_buf_release(buf);
- return rc;
-}
-
-int
-SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, char **buf, int *buf_type)
-{
- struct smb_rqst rqst;
- int resp_buftype, rc;
- struct smb2_read_req *req = NULL;
- struct smb2_read_rsp *rsp = NULL;
- struct kvec iov[1];
- struct kvec rsp_iov;
- unsigned int total_len;
- int flags = CIFS_LOG_ERROR;
- struct cifs_ses *ses = io_parms->tcon->ses;
-
- if (!io_parms->server)
- io_parms->server = cifs_pick_channel(io_parms->tcon->ses);
-
- *nbytes = 0;
- rc = smb2_new_read_req((void **)&req, &total_len, io_parms, NULL, 0, 0);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(io_parms->tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- rc = cifs_send_recv(xid, ses, io_parms->server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- rsp = (struct smb2_read_rsp *)rsp_iov.iov_base;
-
- if (rc) {
- if (rc != -ENODATA) {
- cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
- cifs_dbg(VFS, "Send error in read = %d\n", rc);
- trace_smb3_read_err(xid,
- req->PersistentFileId,
- io_parms->tcon->tid, ses->Suid,
- io_parms->offset, io_parms->length,
- rc);
- } else
- trace_smb3_read_done(xid, req->PersistentFileId, io_parms->tcon->tid,
- ses->Suid, io_parms->offset, 0);
- free_rsp_buf(resp_buftype, rsp_iov.iov_base);
- cifs_small_buf_release(req);
- return rc == -ENODATA ? 0 : rc;
- } else
- trace_smb3_read_done(xid,
- req->PersistentFileId,
- io_parms->tcon->tid, ses->Suid,
- io_parms->offset, io_parms->length);
-
- cifs_small_buf_release(req);
-
- *nbytes = le32_to_cpu(rsp->DataLength);
- if ((*nbytes > CIFS_MAX_MSGSIZE) ||
- (*nbytes > io_parms->length)) {
- cifs_dbg(FYI, "bad length %d for count %d\n",
- *nbytes, io_parms->length);
- rc = -EIO;
- *nbytes = 0;
- }
-
- if (*buf) {
- memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
- free_rsp_buf(resp_buftype, rsp_iov.iov_base);
- } else if (resp_buftype != CIFS_NO_BUFFER) {
- *buf = rsp_iov.iov_base;
- if (resp_buftype == CIFS_SMALL_BUFFER)
- *buf_type = CIFS_SMALL_BUFFER;
- else if (resp_buftype == CIFS_LARGE_BUFFER)
- *buf_type = CIFS_LARGE_BUFFER;
- }
- return rc;
-}
-
-/*
- * Check the mid_state and signature on received buffer (if any), and queue the
- * workqueue completion task.
- */
-static void
-smb2_writev_callback(struct mid_q_entry *mid)
-{
- struct cifs_writedata *wdata = mid->callback_data;
- struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
- struct TCP_Server_Info *server = wdata->server;
- unsigned int written;
- struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
- struct cifs_credits credits = { .value = 0, .instance = 0 };
-
- WARN_ONCE(wdata->server != mid->server,
- "wdata server %p != mid server %p",
- wdata->server, mid->server);
-
- switch (mid->mid_state) {
- case MID_RESPONSE_RECEIVED:
- credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
- credits.instance = server->reconnect_instance;
- wdata->result = smb2_check_receive(mid, server, 0);
- if (wdata->result != 0)
- break;
-
- written = le32_to_cpu(rsp->DataLength);
- /*
- * Mask off high 16 bits when bytes written as returned
- * by the server is greater than bytes requested by the
- * client. OS/2 servers are known to set incorrect
- * CountHigh values.
- */
- if (written > wdata->bytes)
- written &= 0xFFFF;
-
- if (written < wdata->bytes)
- wdata->result = -ENOSPC;
- else
- wdata->bytes = written;
- break;
- case MID_REQUEST_SUBMITTED:
- case MID_RETRY_NEEDED:
- wdata->result = -EAGAIN;
- break;
- case MID_RESPONSE_MALFORMED:
- credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
- credits.instance = server->reconnect_instance;
- fallthrough;
- default:
- wdata->result = -EIO;
- break;
- }
-#ifdef CONFIG_CIFS_SMB_DIRECT
- /*
- * If this wdata has a memory registered, the MR can be freed
- * The number of MRs available is limited, it's important to recover
- * used MR as soon as I/O is finished. Hold MR longer in the later
- * I/O process can possibly result in I/O deadlock due to lack of MR
- * to send request on I/O retry
- */
- if (wdata->mr) {
- smbd_deregister_mr(wdata->mr);
- wdata->mr = NULL;
- }
-#endif
- if (wdata->result) {
- cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
- trace_smb3_write_err(0 /* no xid */,
- wdata->cfile->fid.persistent_fid,
- tcon->tid, tcon->ses->Suid, wdata->offset,
- wdata->bytes, wdata->result);
- if (wdata->result == -ENOSPC)
- pr_warn_once("Out of space writing to %s\n",
- tcon->tree_name);
- } else
- trace_smb3_write_done(0 /* no xid */,
- wdata->cfile->fid.persistent_fid,
- tcon->tid, tcon->ses->Suid,
- wdata->offset, wdata->bytes);
-
- queue_work(cifsiod_wq, &wdata->work);
- release_mid(mid);
- add_credits(server, &credits, 0);
-}
-
-/* smb2_async_writev - send an async write, and set up mid to handle result */
-int
-smb2_async_writev(struct cifs_writedata *wdata,
- void (*release)(struct kref *kref))
-{
- int rc = -EACCES, flags = 0;
- struct smb2_write_req *req = NULL;
- struct smb2_hdr *shdr;
- struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
- struct TCP_Server_Info *server = wdata->server;
- struct kvec iov[1];
- struct smb_rqst rqst = { };
- unsigned int total_len;
- struct cifs_io_parms _io_parms;
- struct cifs_io_parms *io_parms = NULL;
-
- if (!wdata->server)
- server = wdata->server = cifs_pick_channel(tcon->ses);
-
- /*
- * in future we may get cifs_io_parms passed in from the caller,
- * but for now we construct it here...
- */
- _io_parms = (struct cifs_io_parms) {
- .tcon = tcon,
- .server = server,
- .offset = wdata->offset,
- .length = wdata->bytes,
- .persistent_fid = wdata->cfile->fid.persistent_fid,
- .volatile_fid = wdata->cfile->fid.volatile_fid,
- .pid = wdata->pid,
- };
- io_parms = &_io_parms;
-
- rc = smb2_plain_req_init(SMB2_WRITE, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- shdr = (struct smb2_hdr *)req;
- shdr->Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid);
-
- req->PersistentFileId = io_parms->persistent_fid;
- req->VolatileFileId = io_parms->volatile_fid;
- req->WriteChannelInfoOffset = 0;
- req->WriteChannelInfoLength = 0;
- req->Channel = 0;
- req->Offset = cpu_to_le64(io_parms->offset);
- req->DataOffset = cpu_to_le16(
- offsetof(struct smb2_write_req, Buffer));
- req->RemainingBytes = 0;
-
- trace_smb3_write_enter(0 /* xid */,
- io_parms->persistent_fid,
- io_parms->tcon->tid,
- io_parms->tcon->ses->Suid,
- io_parms->offset,
- io_parms->length);
-
-#ifdef CONFIG_CIFS_SMB_DIRECT
- /*
- * If we want to do a server RDMA read, fill in and append
- * smbd_buffer_descriptor_v1 to the end of write request
- */
- if (smb3_use_rdma_offload(io_parms)) {
- struct smbd_buffer_descriptor_v1 *v1;
- bool need_invalidate = server->dialect == SMB30_PROT_ID;
-
- wdata->mr = smbd_register_mr(
- server->smbd_conn, wdata->pages,
- wdata->nr_pages, wdata->page_offset,
- wdata->tailsz, false, need_invalidate);
- if (!wdata->mr) {
- rc = -EAGAIN;
- goto async_writev_out;
- }
- req->Length = 0;
- req->DataOffset = 0;
- if (wdata->nr_pages > 1)
- req->RemainingBytes =
- cpu_to_le32(
- (wdata->nr_pages - 1) * wdata->pagesz -
- wdata->page_offset + wdata->tailsz
- );
- else
- req->RemainingBytes = cpu_to_le32(wdata->tailsz);
- req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
- if (need_invalidate)
- req->Channel = SMB2_CHANNEL_RDMA_V1;
- req->WriteChannelInfoOffset =
- cpu_to_le16(offsetof(struct smb2_write_req, Buffer));
- req->WriteChannelInfoLength =
- cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
- v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
- v1->offset = cpu_to_le64(wdata->mr->mr->iova);
- v1->token = cpu_to_le32(wdata->mr->mr->rkey);
- v1->length = cpu_to_le32(wdata->mr->mr->length);
- }
-#endif
- iov[0].iov_len = total_len - 1;
- iov[0].iov_base = (char *)req;
-
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
- rqst.rq_pages = wdata->pages;
- rqst.rq_offset = wdata->page_offset;
- rqst.rq_npages = wdata->nr_pages;
- rqst.rq_pagesz = wdata->pagesz;
- rqst.rq_tailsz = wdata->tailsz;
-#ifdef CONFIG_CIFS_SMB_DIRECT
- if (wdata->mr) {
- iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1);
- rqst.rq_npages = 0;
- }
-#endif
- cifs_dbg(FYI, "async write at %llu %u bytes\n",
- io_parms->offset, io_parms->length);
-
-#ifdef CONFIG_CIFS_SMB_DIRECT
- /* For RDMA read, I/O size is in RemainingBytes not in Length */
- if (!wdata->mr)
- req->Length = cpu_to_le32(io_parms->length);
-#else
- req->Length = cpu_to_le32(io_parms->length);
-#endif
-
- if (wdata->credits.value > 0) {
- shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
- SMB2_MAX_BUFFER_SIZE));
- shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8);
-
- rc = adjust_credits(server, &wdata->credits, io_parms->length);
- if (rc)
- goto async_writev_out;
-
- flags |= CIFS_HAS_CREDITS;
- }
-
- kref_get(&wdata->refcount);
- rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
- wdata, flags, &wdata->credits);
-
- if (rc) {
- trace_smb3_write_err(0 /* no xid */,
- io_parms->persistent_fid,
- io_parms->tcon->tid,
- io_parms->tcon->ses->Suid,
- io_parms->offset,
- io_parms->length,
- rc);
- kref_put(&wdata->refcount, release);
- cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
- }
-
-async_writev_out:
- cifs_small_buf_release(req);
- return rc;
-}
-
-/*
- * SMB2_write function gets iov pointer to kvec array with n_vec as a length.
- * The length field from io_parms must be at least 1 and indicates a number of
- * elements with data to write that begins with position 1 in iov array. All
- * data length is specified by count.
- */
-int
-SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, struct kvec *iov, int n_vec)
-{
- struct smb_rqst rqst;
- int rc = 0;
- struct smb2_write_req *req = NULL;
- struct smb2_write_rsp *rsp = NULL;
- int resp_buftype;
- struct kvec rsp_iov;
- int flags = 0;
- unsigned int total_len;
- struct TCP_Server_Info *server;
-
- *nbytes = 0;
-
- if (n_vec < 1)
- return rc;
-
- if (!io_parms->server)
- io_parms->server = cifs_pick_channel(io_parms->tcon->ses);
- server = io_parms->server;
- if (server == NULL)
- return -ECONNABORTED;
-
- rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(io_parms->tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- req->hdr.Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid);
-
- req->PersistentFileId = io_parms->persistent_fid;
- req->VolatileFileId = io_parms->volatile_fid;
- req->WriteChannelInfoOffset = 0;
- req->WriteChannelInfoLength = 0;
- req->Channel = 0;
- req->Length = cpu_to_le32(io_parms->length);
- req->Offset = cpu_to_le64(io_parms->offset);
- req->DataOffset = cpu_to_le16(
- offsetof(struct smb2_write_req, Buffer));
- req->RemainingBytes = 0;
-
- trace_smb3_write_enter(xid, io_parms->persistent_fid,
- io_parms->tcon->tid, io_parms->tcon->ses->Suid,
- io_parms->offset, io_parms->length);
-
- iov[0].iov_base = (char *)req;
- /* 1 for Buffer */
- iov[0].iov_len = total_len - 1;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = n_vec + 1;
-
- rc = cifs_send_recv(xid, io_parms->tcon->ses, server,
- &rqst,
- &resp_buftype, flags, &rsp_iov);
- rsp = (struct smb2_write_rsp *)rsp_iov.iov_base;
-
- if (rc) {
- trace_smb3_write_err(xid,
- req->PersistentFileId,
- io_parms->tcon->tid,
- io_parms->tcon->ses->Suid,
- io_parms->offset, io_parms->length, rc);
- cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE);
- cifs_dbg(VFS, "Send error in write = %d\n", rc);
- } else {
- *nbytes = le32_to_cpu(rsp->DataLength);
- trace_smb3_write_done(xid,
- req->PersistentFileId,
- io_parms->tcon->tid,
- io_parms->tcon->ses->Suid,
- io_parms->offset, *nbytes);
- }
-
- cifs_small_buf_release(req);
- free_rsp_buf(resp_buftype, rsp);
- return rc;
-}
-
-int posix_info_sid_size(const void *beg, const void *end)
-{
- size_t subauth;
- int total;
-
- if (beg + 1 > end)
- return -1;
-
- subauth = *(u8 *)(beg+1);
- if (subauth < 1 || subauth > 15)
- return -1;
-
- total = 1 + 1 + 6 + 4*subauth;
- if (beg + total > end)
- return -1;
-
- return total;
-}
-
-int posix_info_parse(const void *beg, const void *end,
- struct smb2_posix_info_parsed *out)
-
-{
- int total_len = 0;
- int owner_len, group_len;
- int name_len;
- const void *owner_sid;
- const void *group_sid;
- const void *name;
-
- /* if no end bound given, assume payload to be correct */
- if (!end) {
- const struct smb2_posix_info *p = beg;
-
- end = beg + le32_to_cpu(p->NextEntryOffset);
- /* last element will have a 0 offset, pick a sensible bound */
- if (end == beg)
- end += 0xFFFF;
- }
-
- /* check base buf */
- if (beg + sizeof(struct smb2_posix_info) > end)
- return -1;
- total_len = sizeof(struct smb2_posix_info);
-
- /* check owner sid */
- owner_sid = beg + total_len;
- owner_len = posix_info_sid_size(owner_sid, end);
- if (owner_len < 0)
- return -1;
- total_len += owner_len;
-
- /* check group sid */
- group_sid = beg + total_len;
- group_len = posix_info_sid_size(group_sid, end);
- if (group_len < 0)
- return -1;
- total_len += group_len;
-
- /* check name len */
- if (beg + total_len + 4 > end)
- return -1;
- name_len = le32_to_cpu(*(__le32 *)(beg + total_len));
- if (name_len < 1 || name_len > 0xFFFF)
- return -1;
- total_len += 4;
-
- /* check name */
- name = beg + total_len;
- if (name + name_len > end)
- return -1;
- total_len += name_len;
-
- if (out) {
- out->base = beg;
- out->size = total_len;
- out->name_len = name_len;
- out->name = name;
- memcpy(&out->owner, owner_sid, owner_len);
- memcpy(&out->group, group_sid, group_len);
- }
- return total_len;
-}
-
-static int posix_info_extra_size(const void *beg, const void *end)
-{
- int len = posix_info_parse(beg, end, NULL);
-
- if (len < 0)
- return -1;
- return len - sizeof(struct smb2_posix_info);
-}
-
-static unsigned int
-num_entries(int infotype, char *bufstart, char *end_of_buf, char **lastentry,
- size_t size)
-{
- int len;
- unsigned int entrycount = 0;
- unsigned int next_offset = 0;
- char *entryptr;
- FILE_DIRECTORY_INFO *dir_info;
-
- if (bufstart == NULL)
- return 0;
-
- entryptr = bufstart;
-
- while (1) {
- if (entryptr + next_offset < entryptr ||
- entryptr + next_offset > end_of_buf ||
- entryptr + next_offset + size > end_of_buf) {
- cifs_dbg(VFS, "malformed search entry would overflow\n");
- break;
- }
-
- entryptr = entryptr + next_offset;
- dir_info = (FILE_DIRECTORY_INFO *)entryptr;
-
- if (infotype == SMB_FIND_FILE_POSIX_INFO)
- len = posix_info_extra_size(entryptr, end_of_buf);
- else
- len = le32_to_cpu(dir_info->FileNameLength);
-
- if (len < 0 ||
- entryptr + len < entryptr ||
- entryptr + len > end_of_buf ||
- entryptr + len + size > end_of_buf) {
- cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n",
- end_of_buf);
- break;
- }
-
- *lastentry = entryptr;
- entrycount++;
-
- next_offset = le32_to_cpu(dir_info->NextEntryOffset);
- if (!next_offset)
- break;
- }
-
- return entrycount;
-}
-
-/*
- * Readdir/FindFirst
- */
-int SMB2_query_directory_init(const unsigned int xid,
- struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid,
- int index, int info_level)
-{
- struct smb2_query_directory_req *req;
- unsigned char *bufptr;
- __le16 asteriks = cpu_to_le16('*');
- unsigned int output_size = CIFSMaxBufSize -
- MAX_SMB2_CREATE_RESPONSE_SIZE -
- MAX_SMB2_CLOSE_RESPONSE_SIZE;
- unsigned int total_len;
- struct kvec *iov = rqst->rq_iov;
- int len, rc;
-
- rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- switch (info_level) {
- case SMB_FIND_FILE_DIRECTORY_INFO:
- req->FileInformationClass = FILE_DIRECTORY_INFORMATION;
- break;
- case SMB_FIND_FILE_ID_FULL_DIR_INFO:
- req->FileInformationClass = FILEID_FULL_DIRECTORY_INFORMATION;
- break;
- case SMB_FIND_FILE_POSIX_INFO:
- req->FileInformationClass = SMB_FIND_FILE_POSIX_INFO;
- break;
- default:
- cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
- info_level);
- return -EINVAL;
- }
-
- req->FileIndex = cpu_to_le32(index);
- req->PersistentFileId = persistent_fid;
- req->VolatileFileId = volatile_fid;
-
- len = 0x2;
- bufptr = req->Buffer;
- memcpy(bufptr, &asteriks, len);
-
- req->FileNameOffset =
- cpu_to_le16(sizeof(struct smb2_query_directory_req) - 1);
- req->FileNameLength = cpu_to_le16(len);
- /*
- * BB could be 30 bytes or so longer if we used SMB2 specific
- * buffer lengths, but this is safe and close enough.
- */
- output_size = min_t(unsigned int, output_size, server->maxBuf);
- output_size = min_t(unsigned int, output_size, 2 << 15);
- req->OutputBufferLength = cpu_to_le32(output_size);
-
- iov[0].iov_base = (char *)req;
- /* 1 for Buffer */
- iov[0].iov_len = total_len - 1;
-
- iov[1].iov_base = (char *)(req->Buffer);
- iov[1].iov_len = len;
-
- trace_smb3_query_dir_enter(xid, persistent_fid, tcon->tid,
- tcon->ses->Suid, index, output_size);
-
- return 0;
-}
-
-void SMB2_query_directory_free(struct smb_rqst *rqst)
-{
- if (rqst && rqst->rq_iov) {
- cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
- }
-}
-
-int
-smb2_parse_query_directory(struct cifs_tcon *tcon,
- struct kvec *rsp_iov,
- int resp_buftype,
- struct cifs_search_info *srch_inf)
-{
- struct smb2_query_directory_rsp *rsp;
- size_t info_buf_size;
- char *end_of_smb;
- int rc;
-
- rsp = (struct smb2_query_directory_rsp *)rsp_iov->iov_base;
-
- switch (srch_inf->info_level) {
- case SMB_FIND_FILE_DIRECTORY_INFO:
- info_buf_size = sizeof(FILE_DIRECTORY_INFO) - 1;
- break;
- case SMB_FIND_FILE_ID_FULL_DIR_INFO:
- info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1;
- break;
- case SMB_FIND_FILE_POSIX_INFO:
- /* note that posix payload are variable size */
- info_buf_size = sizeof(struct smb2_posix_info);
- break;
- default:
- cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
- srch_inf->info_level);
- return -EINVAL;
- }
-
- rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
- le32_to_cpu(rsp->OutputBufferLength), rsp_iov,
- info_buf_size);
- if (rc) {
- cifs_tcon_dbg(VFS, "bad info payload");
- return rc;
- }
-
- srch_inf->unicode = true;
-
- if (srch_inf->ntwrk_buf_start) {
- if (srch_inf->smallBuf)
- cifs_small_buf_release(srch_inf->ntwrk_buf_start);
- else
- cifs_buf_release(srch_inf->ntwrk_buf_start);
- }
- srch_inf->ntwrk_buf_start = (char *)rsp;
- srch_inf->srch_entries_start = srch_inf->last_entry =
- (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset);
- end_of_smb = rsp_iov->iov_len + (char *)rsp;
-
- srch_inf->entries_in_buffer = num_entries(
- srch_inf->info_level,
- srch_inf->srch_entries_start,
- end_of_smb,
- &srch_inf->last_entry,
- info_buf_size);
-
- srch_inf->index_of_last_entry += srch_inf->entries_in_buffer;
- cifs_dbg(FYI, "num entries %d last_index %lld srch start %p srch end %p\n",
- srch_inf->entries_in_buffer, srch_inf->index_of_last_entry,
- srch_inf->srch_entries_start, srch_inf->last_entry);
- if (resp_buftype == CIFS_LARGE_BUFFER)
- srch_inf->smallBuf = false;
- else if (resp_buftype == CIFS_SMALL_BUFFER)
- srch_inf->smallBuf = true;
- else
- cifs_tcon_dbg(VFS, "Invalid search buffer type\n");
-
- return 0;
-}
-
-int
-SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, int index,
- struct cifs_search_info *srch_inf)
-{
- struct smb_rqst rqst;
- struct kvec iov[SMB2_QUERY_DIRECTORY_IOV_SIZE];
- struct smb2_query_directory_rsp *rsp = NULL;
- int resp_buftype = CIFS_NO_BUFFER;
- struct kvec rsp_iov;
- int rc = 0;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- int flags = 0;
-
- if (!ses || !(ses->server))
- return -EIO;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- memset(&iov, 0, sizeof(iov));
- rqst.rq_iov = iov;
- rqst.rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE;
-
- rc = SMB2_query_directory_init(xid, tcon, server,
- &rqst, persistent_fid,
- volatile_fid, index,
- srch_inf->info_level);
- if (rc)
- goto qdir_exit;
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base;
-
- if (rc) {
- if (rc == -ENODATA &&
- rsp->hdr.Status == STATUS_NO_MORE_FILES) {
- trace_smb3_query_dir_done(xid, persistent_fid,
- tcon->tid, tcon->ses->Suid, index, 0);
- srch_inf->endOfSearch = true;
- rc = 0;
- } else {
- trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid,
- tcon->ses->Suid, index, 0, rc);
- cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
- }
- goto qdir_exit;
- }
-
- rc = smb2_parse_query_directory(tcon, &rsp_iov, resp_buftype,
- srch_inf);
- if (rc) {
- trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid,
- tcon->ses->Suid, index, 0, rc);
- goto qdir_exit;
- }
- resp_buftype = CIFS_NO_BUFFER;
-
- trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid,
- tcon->ses->Suid, index, srch_inf->entries_in_buffer);
-
-qdir_exit:
- SMB2_query_directory_free(&rqst);
- free_rsp_buf(resp_buftype, rsp);
- return rc;
-}
-
-int
-SMB2_set_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid, u32 pid,
- u8 info_class, u8 info_type, u32 additional_info,
- void **data, unsigned int *size)
-{
- struct smb2_set_info_req *req;
- struct kvec *iov = rqst->rq_iov;
- unsigned int i, total_len;
- int rc;
-
- rc = smb2_plain_req_init(SMB2_SET_INFO, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- req->hdr.Id.SyncId.ProcessId = cpu_to_le32(pid);
- req->InfoType = info_type;
- req->FileInfoClass = info_class;
- req->PersistentFileId = persistent_fid;
- req->VolatileFileId = volatile_fid;
- req->AdditionalInformation = cpu_to_le32(additional_info);
-
- req->BufferOffset =
- cpu_to_le16(sizeof(struct smb2_set_info_req) - 1);
- req->BufferLength = cpu_to_le32(*size);
-
- memcpy(req->Buffer, *data, *size);
- total_len += *size;
-
- iov[0].iov_base = (char *)req;
- /* 1 for Buffer */
- iov[0].iov_len = total_len - 1;
-
- for (i = 1; i < rqst->rq_nvec; i++) {
- le32_add_cpu(&req->BufferLength, size[i]);
- iov[i].iov_base = (char *)data[i];
- iov[i].iov_len = size[i];
- }
-
- return 0;
-}
-
-void
-SMB2_set_info_free(struct smb_rqst *rqst)
-{
- if (rqst && rqst->rq_iov)
- cifs_buf_release(rqst->rq_iov[0].iov_base); /* request */
-}
-
-static int
-send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, u32 pid, u8 info_class,
- u8 info_type, u32 additional_info, unsigned int num,
- void **data, unsigned int *size)
-{
- struct smb_rqst rqst;
- struct smb2_set_info_rsp *rsp = NULL;
- struct kvec *iov;
- struct kvec rsp_iov;
- int rc = 0;
- int resp_buftype;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- int flags = 0;
-
- if (!ses || !server)
- return -EIO;
-
- if (!num)
- return -EINVAL;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL);
- if (!iov)
- return -ENOMEM;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = num;
-
- rc = SMB2_set_info_init(tcon, server,
- &rqst, persistent_fid, volatile_fid, pid,
- info_class, info_type, additional_info,
- data, size);
- if (rc) {
- kfree(iov);
- return rc;
- }
-
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags,
- &rsp_iov);
- SMB2_set_info_free(&rqst);
- rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base;
-
- if (rc != 0) {
- cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE);
- trace_smb3_set_info_err(xid, persistent_fid, tcon->tid,
- ses->Suid, info_class, (__u32)info_type, rc);
- }
-
- free_rsp_buf(resp_buftype, rsp);
- kfree(iov);
- return rc;
-}
-
-int
-SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
- u64 volatile_fid, u32 pid, __le64 *eof)
-{
- struct smb2_file_eof_info info;
- void *data;
- unsigned int size;
-
- info.EndOfFile = *eof;
-
- data = &info;
- size = sizeof(struct smb2_file_eof_info);
-
- trace_smb3_set_eof(xid, persistent_fid, tcon->tid, tcon->ses->Suid, le64_to_cpu(*eof));
-
- return send_set_info(xid, tcon, persistent_fid, volatile_fid,
- pid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE,
- 0, 1, &data, &size);
-}
-
-int
-SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- struct cifs_ntsd *pnntsd, int pacllen, int aclflag)
-{
- return send_set_info(xid, tcon, persistent_fid, volatile_fid,
- current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag,
- 1, (void **)&pnntsd, &pacllen);
-}
-
-int
-SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- struct smb2_file_full_ea_info *buf, int len)
-{
- return send_set_info(xid, tcon, persistent_fid, volatile_fid,
- current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE,
- 0, 1, (void **)&buf, &len);
-}
-
-int
-SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
- const u64 persistent_fid, const u64 volatile_fid,
- __u8 oplock_level)
-{
- struct smb_rqst rqst;
- int rc;
- struct smb2_oplock_break *req = NULL;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- int flags = CIFS_OBREAK_OP;
- unsigned int total_len;
- struct kvec iov[1];
- struct kvec rsp_iov;
- int resp_buf_type;
-
- cifs_dbg(FYI, "SMB2_oplock_break\n");
- rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- req->VolatileFid = volatile_fid;
- req->PersistentFid = persistent_fid;
- req->OplockLevel = oplock_level;
- req->hdr.CreditRequest = cpu_to_le16(1);
-
- flags |= CIFS_NO_RSP_BUF;
-
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buf_type, flags, &rsp_iov);
- cifs_small_buf_release(req);
-
- if (rc) {
- cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
- cifs_dbg(FYI, "Send error in Oplock Break = %d\n", rc);
- }
-
- return rc;
-}
-
-void
-smb2_copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf,
- struct kstatfs *kst)
-{
- kst->f_bsize = le32_to_cpu(pfs_inf->BytesPerSector) *
- le32_to_cpu(pfs_inf->SectorsPerAllocationUnit);
- kst->f_blocks = le64_to_cpu(pfs_inf->TotalAllocationUnits);
- kst->f_bfree = kst->f_bavail =
- le64_to_cpu(pfs_inf->CallerAvailableAllocationUnits);
- return;
-}
-
-static void
-copy_posix_fs_info_to_kstatfs(FILE_SYSTEM_POSIX_INFO *response_data,
- struct kstatfs *kst)
-{
- kst->f_bsize = le32_to_cpu(response_data->BlockSize);
- kst->f_blocks = le64_to_cpu(response_data->TotalBlocks);
- kst->f_bfree = le64_to_cpu(response_data->BlocksAvail);
- if (response_data->UserBlocksAvail == cpu_to_le64(-1))
- kst->f_bavail = kst->f_bfree;
- else
- kst->f_bavail = le64_to_cpu(response_data->UserBlocksAvail);
- if (response_data->TotalFileNodes != cpu_to_le64(-1))
- kst->f_files = le64_to_cpu(response_data->TotalFileNodes);
- if (response_data->FreeFileNodes != cpu_to_le64(-1))
- kst->f_ffree = le64_to_cpu(response_data->FreeFileNodes);
-
- return;
-}
-
-static int
-build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- int level, int outbuf_len, u64 persistent_fid,
- u64 volatile_fid)
-{
- int rc;
- struct smb2_query_info_req *req;
- unsigned int total_len;
-
- cifs_dbg(FYI, "Query FSInfo level %d\n", level);
-
- if ((tcon->ses == NULL) || server == NULL)
- return -EIO;
-
- rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- req->InfoType = SMB2_O_INFO_FILESYSTEM;
- req->FileInfoClass = level;
- req->PersistentFileId = persistent_fid;
- req->VolatileFileId = volatile_fid;
- /* 1 for pad */
- req->InputBufferOffset =
- cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
- req->OutputBufferLength = cpu_to_le32(
- outbuf_len + sizeof(struct smb2_query_info_rsp) - 1);
-
- iov->iov_base = (char *)req;
- iov->iov_len = total_len;
- return 0;
-}
-
-int
-SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
-{
- struct smb_rqst rqst;
- struct smb2_query_info_rsp *rsp = NULL;
- struct kvec iov;
- struct kvec rsp_iov;
- int rc = 0;
- int resp_buftype;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- FILE_SYSTEM_POSIX_INFO *info = NULL;
- int flags = 0;
-
- rc = build_qfs_info_req(&iov, tcon, server,
- FS_POSIX_INFORMATION,
- sizeof(FILE_SYSTEM_POSIX_INFO),
- persistent_fid, volatile_fid);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = &iov;
- rqst.rq_nvec = 1;
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- cifs_small_buf_release(iov.iov_base);
- if (rc) {
- cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
- goto posix_qfsinf_exit;
- }
- rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
-
- info = (FILE_SYSTEM_POSIX_INFO *)(
- le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
- rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
- le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
- sizeof(FILE_SYSTEM_POSIX_INFO));
- if (!rc)
- copy_posix_fs_info_to_kstatfs(info, fsdata);
-
-posix_qfsinf_exit:
- free_rsp_buf(resp_buftype, rsp_iov.iov_base);
- return rc;
-}
-
-int
-SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
-{
- struct smb_rqst rqst;
- struct smb2_query_info_rsp *rsp = NULL;
- struct kvec iov;
- struct kvec rsp_iov;
- int rc = 0;
- int resp_buftype;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- struct smb2_fs_full_size_info *info = NULL;
- int flags = 0;
-
- rc = build_qfs_info_req(&iov, tcon, server,
- FS_FULL_SIZE_INFORMATION,
- sizeof(struct smb2_fs_full_size_info),
- persistent_fid, volatile_fid);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = &iov;
- rqst.rq_nvec = 1;
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- cifs_small_buf_release(iov.iov_base);
- if (rc) {
- cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
- goto qfsinf_exit;
- }
- rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
-
- info = (struct smb2_fs_full_size_info *)(
- le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
- rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
- le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
- sizeof(struct smb2_fs_full_size_info));
- if (!rc)
- smb2_copy_fs_info_to_kstatfs(info, fsdata);
-
-qfsinf_exit:
- free_rsp_buf(resp_buftype, rsp_iov.iov_base);
- return rc;
-}
-
-int
-SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, int level)
-{
- struct smb_rqst rqst;
- struct smb2_query_info_rsp *rsp = NULL;
- struct kvec iov;
- struct kvec rsp_iov;
- int rc = 0;
- int resp_buftype, max_len, min_len;
- struct cifs_ses *ses = tcon->ses;
- struct TCP_Server_Info *server = cifs_pick_channel(ses);
- unsigned int rsp_len, offset;
- int flags = 0;
-
- if (level == FS_DEVICE_INFORMATION) {
- max_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
- min_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
- } else if (level == FS_ATTRIBUTE_INFORMATION) {
- max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO);
- min_len = MIN_FS_ATTR_INFO_SIZE;
- } else if (level == FS_SECTOR_SIZE_INFORMATION) {
- max_len = sizeof(struct smb3_fs_ss_info);
- min_len = sizeof(struct smb3_fs_ss_info);
- } else if (level == FS_VOLUME_INFORMATION) {
- max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN;
- min_len = sizeof(struct smb3_fs_vol_info);
- } else {
- cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level);
- return -EINVAL;
- }
-
- rc = build_qfs_info_req(&iov, tcon, server,
- level, max_len,
- persistent_fid, volatile_fid);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = &iov;
- rqst.rq_nvec = 1;
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- cifs_small_buf_release(iov.iov_base);
- if (rc) {
- cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
- goto qfsattr_exit;
- }
- rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
-
- rsp_len = le32_to_cpu(rsp->OutputBufferLength);
- offset = le16_to_cpu(rsp->OutputBufferOffset);
- rc = smb2_validate_iov(offset, rsp_len, &rsp_iov, min_len);
- if (rc)
- goto qfsattr_exit;
-
- if (level == FS_ATTRIBUTE_INFORMATION)
- memcpy(&tcon->fsAttrInfo, offset
- + (char *)rsp, min_t(unsigned int,
- rsp_len, max_len));
- else if (level == FS_DEVICE_INFORMATION)
- memcpy(&tcon->fsDevInfo, offset
- + (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO));
- else if (level == FS_SECTOR_SIZE_INFORMATION) {
- struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
- (offset + (char *)rsp);
- tcon->ss_flags = le32_to_cpu(ss_info->Flags);
- tcon->perf_sector_size =
- le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
- } else if (level == FS_VOLUME_INFORMATION) {
- struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *)
- (offset + (char *)rsp);
- tcon->vol_serial_number = vol_info->VolumeSerialNumber;
- tcon->vol_create_time = vol_info->VolumeCreationTime;
- }
-
-qfsattr_exit:
- free_rsp_buf(resp_buftype, rsp_iov.iov_base);
- return rc;
-}
-
-int
-smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
- const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid,
- const __u32 num_lock, struct smb2_lock_element *buf)
-{
- struct smb_rqst rqst;
- int rc = 0;
- struct smb2_lock_req *req = NULL;
- struct kvec iov[2];
- struct kvec rsp_iov;
- int resp_buf_type;
- unsigned int count;
- int flags = CIFS_NO_RSP_BUF;
- unsigned int total_len;
- struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
-
- cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock);
-
- rc = smb2_plain_req_init(SMB2_LOCK, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- req->hdr.Id.SyncId.ProcessId = cpu_to_le32(pid);
- req->LockCount = cpu_to_le16(num_lock);
-
- req->PersistentFileId = persist_fid;
- req->VolatileFileId = volatile_fid;
-
- count = num_lock * sizeof(struct smb2_lock_element);
-
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len - sizeof(struct smb2_lock_element);
- iov[1].iov_base = (char *)buf;
- iov[1].iov_len = count;
-
- cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 2;
-
- rc = cifs_send_recv(xid, tcon->ses, server,
- &rqst, &resp_buf_type, flags,
- &rsp_iov);
- cifs_small_buf_release(req);
- if (rc) {
- cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc);
- cifs_stats_fail_inc(tcon, SMB2_LOCK_HE);
- trace_smb3_lock_err(xid, persist_fid, tcon->tid,
- tcon->ses->Suid, rc);
- }
-
- return rc;
-}
-
-int
-SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon,
- const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid,
- const __u64 length, const __u64 offset, const __u32 lock_flags,
- const bool wait)
-{
- struct smb2_lock_element lock;
-
- lock.Offset = cpu_to_le64(offset);
- lock.Length = cpu_to_le64(length);
- lock.Flags = cpu_to_le32(lock_flags);
- if (!wait && lock_flags != SMB2_LOCKFLAG_UNLOCK)
- lock.Flags |= cpu_to_le32(SMB2_LOCKFLAG_FAIL_IMMEDIATELY);
-
- return smb2_lockv(xid, tcon, persist_fid, volatile_fid, pid, 1, &lock);
-}
-
-int
-SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
- __u8 *lease_key, const __le32 lease_state)
-{
- struct smb_rqst rqst;
- int rc;
- struct smb2_lease_ack *req = NULL;
- struct cifs_ses *ses = tcon->ses;
- int flags = CIFS_OBREAK_OP;
- unsigned int total_len;
- struct kvec iov[1];
- struct kvec rsp_iov;
- int resp_buf_type;
- __u64 *please_key_high;
- __u64 *please_key_low;
- struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
-
- cifs_dbg(FYI, "SMB2_lease_break\n");
- rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server,
- (void **) &req, &total_len);
- if (rc)
- return rc;
-
- if (smb3_encryption_required(tcon))
- flags |= CIFS_TRANSFORM_REQ;
-
- req->hdr.CreditRequest = cpu_to_le16(1);
- req->StructureSize = cpu_to_le16(36);
- total_len += 12;
-
- memcpy(req->LeaseKey, lease_key, 16);
- req->LeaseState = lease_state;
-
- flags |= CIFS_NO_RSP_BUF;
-
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
-
- rc = cifs_send_recv(xid, ses, server,
- &rqst, &resp_buf_type, flags, &rsp_iov);
- cifs_small_buf_release(req);
-
- please_key_low = (__u64 *)lease_key;
- please_key_high = (__u64 *)(lease_key+8);
- if (rc) {
- cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
- trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid,
- ses->Suid, *please_key_low, *please_key_high, rc);
- cifs_dbg(FYI, "Send error in Lease Break = %d\n", rc);
- } else
- trace_smb3_lease_done(le32_to_cpu(lease_state), tcon->tid,
- ses->Suid, *please_key_low, *please_key_high);
-
- return rc;
-}
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
deleted file mode 100644
index 1237bb86e93a..000000000000
--- a/fs/cifs/smb2pdu.h
+++ /dev/null
@@ -1,434 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2009, 2013
- * Etersoft, 2012
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Pavel Shilovsky (pshilovsky@samba.org) 2012
- *
- */
-
-#ifndef _SMB2PDU_H
-#define _SMB2PDU_H
-
-#include <net/sock.h>
-#include "cifsacl.h"
-
-/* 52 transform hdr + 64 hdr + 88 create rsp */
-#define SMB2_TRANSFORM_HEADER_SIZE 52
-#define MAX_SMB2_HDR_SIZE 204
-
-/* The total header size for SMB2 read and write */
-#define SMB2_READWRITE_PDU_HEADER_SIZE (48 + sizeof(struct smb2_hdr))
-
-/* See MS-SMB2 2.2.43 */
-struct smb2_rdma_transform {
- __le16 RdmaDescriptorOffset;
- __le16 RdmaDescriptorLength;
- __le32 Channel; /* for values see channel description in smb2 read above */
- __le16 TransformCount;
- __le16 Reserved1;
- __le32 Reserved2;
-} __packed;
-
-/* TransformType */
-#define SMB2_RDMA_TRANSFORM_TYPE_ENCRYPTION 0x0001
-#define SMB2_RDMA_TRANSFORM_TYPE_SIGNING 0x0002
-
-struct smb2_rdma_crypto_transform {
- __le16 TransformType;
- __le16 SignatureLength;
- __le16 NonceLength;
- __u16 Reserved;
- __u8 Signature[]; /* variable length */
- /* u8 Nonce[] */
- /* followed by padding */
-} __packed;
-
-/*
- * Definitions for SMB2 Protocol Data Units (network frames)
- *
- * See MS-SMB2.PDF specification for protocol details.
- * The Naming convention is the lower case version of the SMB2
- * command code name for the struct. Note that structures must be packed.
- *
- */
-
-#define COMPOUND_FID 0xFFFFFFFFFFFFFFFFULL
-
-#define SMB2_SYMLINK_STRUCT_SIZE \
- (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
-
-#define SYMLINK_ERROR_TAG 0x4c4d5953
-
-struct smb2_symlink_err_rsp {
- __le32 SymLinkLength;
- __le32 SymLinkErrorTag;
- __le32 ReparseTag;
- __le16 ReparseDataLength;
- __le16 UnparsedPathLength;
- __le16 SubstituteNameOffset;
- __le16 SubstituteNameLength;
- __le16 PrintNameOffset;
- __le16 PrintNameLength;
- __le32 Flags;
- __u8 PathBuffer[];
-} __packed;
-
-/* SMB 3.1.1 and later dialects. See MS-SMB2 section 2.2.2.1 */
-struct smb2_error_context_rsp {
- __le32 ErrorDataLength;
- __le32 ErrorId;
- __u8 ErrorContextData; /* ErrorDataLength long array */
-} __packed;
-
-/* ErrorId values */
-#define SMB2_ERROR_ID_DEFAULT 0x00000000
-#define SMB2_ERROR_ID_SHARE_REDIRECT cpu_to_le32(0x72645253) /* "rdRS" */
-
-/* Defines for Type field below (see MS-SMB2 2.2.2.2.2.1) */
-#define MOVE_DST_IPADDR_V4 cpu_to_le32(0x00000001)
-#define MOVE_DST_IPADDR_V6 cpu_to_le32(0x00000002)
-
-struct move_dst_ipaddr {
- __le32 Type;
- __u32 Reserved;
- __u8 address[16]; /* IPv4 followed by 12 bytes rsvd or IPv6 address */
-} __packed;
-
-struct share_redirect_error_context_rsp {
- __le32 StructureSize;
- __le32 NotificationType;
- __le32 ResourceNameOffset;
- __le32 ResourceNameLength;
- __le16 Reserved;
- __le16 TargetType;
- __le32 IPAddrCount;
- struct move_dst_ipaddr IpAddrMoveList[];
- /* __u8 ResourceName[] */ /* Name of share as counted Unicode string */
-} __packed;
-
-/*
- * Maximum number of iovs we need for an open/create request.
- * [0] : struct smb2_create_req
- * [1] : path
- * [2] : lease context
- * [3] : durable context
- * [4] : posix context
- * [5] : time warp context
- * [6] : query id context
- * [7] : compound padding
- */
-#define SMB2_CREATE_IOV_SIZE 8
-
-/*
- * Maximum size of a SMB2_CREATE response is 64 (smb2 header) +
- * 88 (fixed part of create response) + 520 (path) + 208 (contexts) +
- * 2 bytes of padding.
- */
-#define MAX_SMB2_CREATE_RESPONSE_SIZE 880
-
-#define SMB2_LEASE_READ_CACHING_HE 0x01
-#define SMB2_LEASE_HANDLE_CACHING_HE 0x02
-#define SMB2_LEASE_WRITE_CACHING_HE 0x04
-
-struct create_durable {
- struct create_context ccontext;
- __u8 Name[8];
- union {
- __u8 Reserved[16];
- struct {
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- } Fid;
- } Data;
-} __packed;
-
-/* See MS-SMB2 2.2.13.2.11 */
-/* Flags */
-#define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002
-struct durable_context_v2 {
- __le32 Timeout;
- __le32 Flags;
- __u64 Reserved;
- __u8 CreateGuid[16];
-} __packed;
-
-struct create_durable_v2 {
- struct create_context ccontext;
- __u8 Name[8];
- struct durable_context_v2 dcontext;
-} __packed;
-
-/* See MS-SMB2 2.2.13.2.12 */
-struct durable_reconnect_context_v2 {
- struct {
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- } Fid;
- __u8 CreateGuid[16];
- __le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
-} __packed;
-
-/* See MS-SMB2 2.2.14.2.9 */
-struct create_on_disk_id {
- struct create_context ccontext;
- __u8 Name[8];
- __le64 DiskFileId;
- __le64 VolumeId;
- __u32 Reserved[4];
-} __packed;
-
-/* See MS-SMB2 2.2.14.2.12 */
-struct durable_reconnect_context_v2_rsp {
- __le32 Timeout;
- __le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
-} __packed;
-
-struct create_durable_handle_reconnect_v2 {
- struct create_context ccontext;
- __u8 Name[8];
- struct durable_reconnect_context_v2 dcontext;
- __u8 Pad[4];
-} __packed;
-
-/* See MS-SMB2 2.2.13.2.5 */
-struct crt_twarp_ctxt {
- struct create_context ccontext;
- __u8 Name[8];
- __le64 Timestamp;
-
-} __packed;
-
-/* See MS-SMB2 2.2.13.2.9 */
-struct crt_query_id_ctxt {
- struct create_context ccontext;
- __u8 Name[8];
-} __packed;
-
-struct crt_sd_ctxt {
- struct create_context ccontext;
- __u8 Name[8];
- struct smb3_sd sd;
-} __packed;
-
-
-#define COPY_CHUNK_RES_KEY_SIZE 24
-struct resume_key_req {
- char ResumeKey[COPY_CHUNK_RES_KEY_SIZE];
- __le32 ContextLength; /* MBZ */
- char Context[]; /* ignored, Windows sets to 4 bytes of zero */
-} __packed;
-
-/* this goes in the ioctl buffer when doing a copychunk request */
-struct copychunk_ioctl {
- char SourceKey[COPY_CHUNK_RES_KEY_SIZE];
- __le32 ChunkCount; /* we are only sending 1 */
- __le32 Reserved;
- /* array will only be one chunk long for us */
- __le64 SourceOffset;
- __le64 TargetOffset;
- __le32 Length; /* how many bytes to copy */
- __u32 Reserved2;
-} __packed;
-
-struct copychunk_ioctl_rsp {
- __le32 ChunksWritten;
- __le32 ChunkBytesWritten;
- __le32 TotalBytesWritten;
-} __packed;
-
-/* See MS-FSCC 2.3.29 and 2.3.30 */
-struct get_retrieval_pointer_count_req {
- __le64 StartingVcn; /* virtual cluster number (signed) */
-} __packed;
-
-struct get_retrieval_pointer_count_rsp {
- __le32 ExtentCount;
-} __packed;
-
-/*
- * See MS-FSCC 2.3.33 and 2.3.34
- * request is the same as get_retrieval_point_count_req struct above
- */
-struct smb3_extents {
- __le64 NextVcn;
- __le64 Lcn; /* logical cluster number */
-} __packed;
-
-struct get_retrieval_pointers_refcount_rsp {
- __le32 ExtentCount;
- __u32 Reserved;
- __le64 StartingVcn;
- struct smb3_extents extents[];
-} __packed;
-
-/* See MS-DFSC 2.2.2 */
-struct fsctl_get_dfs_referral_req {
- __le16 MaxReferralLevel;
- __u8 RequestFileName[];
-} __packed;
-
-/* DFS response is struct get_dfs_refer_rsp */
-
-/* See MS-SMB2 2.2.31.3 */
-struct network_resiliency_req {
- __le32 Timeout;
- __le32 Reserved;
-} __packed;
-/* There is no buffer for the response ie no struct network_resiliency_rsp */
-
-#define RSS_CAPABLE cpu_to_le32(0x00000001)
-#define RDMA_CAPABLE cpu_to_le32(0x00000002)
-
-#define INTERNETWORK cpu_to_le16(0x0002)
-#define INTERNETWORKV6 cpu_to_le16(0x0017)
-
-struct network_interface_info_ioctl_rsp {
- __le32 Next; /* next interface. zero if this is last one */
- __le32 IfIndex;
- __le32 Capability; /* RSS or RDMA Capable */
- __le32 Reserved;
- __le64 LinkSpeed;
- __le16 Family;
- __u8 Buffer[126];
-} __packed;
-
-struct iface_info_ipv4 {
- __be16 Port;
- __be32 IPv4Address;
- __be64 Reserved;
-} __packed;
-
-struct iface_info_ipv6 {
- __be16 Port;
- __be32 FlowInfo;
- __u8 IPv6Address[16];
- __be32 ScopeId;
-} __packed;
-
-#define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL /* general ioctls to srv not to file */
-
-struct compress_ioctl {
- __le16 CompressionState; /* See cifspdu.h for possible flag values */
-} __packed;
-
-/*
- * Maximum number of iovs we need for an ioctl request.
- * [0] : struct smb2_ioctl_req
- * [1] : in_data
- */
-#define SMB2_IOCTL_IOV_SIZE 2
-
-/*
- * PDU query infolevel structure definitions
- * BB consider moving to a different header
- */
-
-struct smb2_file_full_ea_info { /* encoding of response for level 15 */
- __le32 next_entry_offset;
- __u8 flags;
- __u8 ea_name_length;
- __le16 ea_value_length;
- char ea_data[]; /* \0 terminated name plus value */
-} __packed; /* level 15 Set */
-
-struct smb2_file_reparse_point_info {
- __le64 IndexNumber;
- __le32 Tag;
-} __packed;
-
-struct smb2_file_network_open_info {
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 AllocationSize;
- __le64 EndOfFile;
- __le32 Attributes;
- __le32 Reserved;
-} __packed; /* level 34 Query also similar returned in close rsp and open rsp */
-
-/* See MS-FSCC 2.4.21 */
-struct smb2_file_id_information {
- __le64 VolumeSerialNumber;
- __u64 PersistentFileId; /* opaque endianness */
- __u64 VolatileFileId; /* opaque endianness */
-} __packed; /* level 59 */
-
-/* See MS-FSCC 2.4.18 */
-struct smb2_file_id_extd_directory_info {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 FileAttributes;
- __le32 FileNameLength;
- __le32 EaSize; /* EA size */
- __le32 ReparsePointTag; /* valid if FILE_ATTR_REPARSE_POINT set in FileAttributes */
- __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit */
- char FileName[1];
-} __packed; /* level 60 */
-
-extern char smb2_padding[7];
-
-/* equivalent of the contents of SMB3.1.1 POSIX open context response */
-struct create_posix_rsp {
- u32 nlink;
- u32 reparse_tag;
- u32 mode;
- struct cifs_sid owner; /* var-sized on the wire */
- struct cifs_sid group; /* var-sized on the wire */
-} __packed;
-
-#define SMB2_QUERY_DIRECTORY_IOV_SIZE 2
-
-/*
- * SMB2-only POSIX info level for query dir
- *
- * See posix_info_sid_size(), posix_info_extra_size() and
- * posix_info_parse() to help with the handling of this struct.
- */
-struct smb2_posix_info {
- __le32 NextEntryOffset;
- __u32 Ignored;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 DosAttributes;
- __le64 Inode;
- __le32 DeviceId;
- __le32 Zero;
- /* beginning of POSIX Create Context Response */
- __le32 HardLinks;
- __le32 ReparseTag;
- __le32 Mode;
- /*
- * var sized owner SID
- * var sized group SID
- * le32 filenamelength
- * u8 filename[]
- */
-} __packed;
-
-/*
- * Parsed version of the above struct. Allows direct access to the
- * variable length fields
- */
-struct smb2_posix_info_parsed {
- const struct smb2_posix_info *base;
- size_t size;
- struct cifs_sid owner;
- struct cifs_sid group;
- int name_len;
- const u8 *name;
-};
-
-#endif /* _SMB2PDU_H */
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
deleted file mode 100644
index be21b5d26f67..000000000000
--- a/fs/cifs/smb2proto.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2002, 2011
- * Etersoft, 2012
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Pavel Shilovsky (pshilovsky@samba.org) 2012
- *
- */
-#ifndef _SMB2PROTO_H
-#define _SMB2PROTO_H
-#include <linux/nls.h>
-#include <linux/key-type.h>
-
-struct statfs;
-struct smb_rqst;
-
-/*
- *****************************************************************
- * All Prototypes
- *****************************************************************
- */
-extern int map_smb2_to_linux_error(char *buf, bool log_err);
-extern int smb2_check_message(char *buf, unsigned int length,
- struct TCP_Server_Info *server);
-extern unsigned int smb2_calc_size(void *buf);
-extern char *smb2_get_data_area_len(int *off, int *len,
- struct smb2_hdr *shdr);
-extern __le16 *cifs_convert_path_to_utf16(const char *from,
- struct cifs_sb_info *cifs_sb);
-
-extern int smb2_verify_signature(struct smb_rqst *, struct TCP_Server_Info *);
-extern int smb2_check_receive(struct mid_q_entry *mid,
- struct TCP_Server_Info *server, bool log_error);
-extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
- struct TCP_Server_Info *,
- struct smb_rqst *rqst);
-extern struct mid_q_entry *smb2_setup_async_request(
- struct TCP_Server_Info *server, struct smb_rqst *rqst);
-extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
- __u64 ses_id);
-extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
- __u64 ses_id, __u32 tid);
-extern int smb2_calc_signature(struct smb_rqst *rqst,
- struct TCP_Server_Info *server,
- bool allocate_crypto);
-extern int smb3_calc_signature(struct smb_rqst *rqst,
- struct TCP_Server_Info *server,
- bool allocate_crypto);
-extern void smb2_echo_request(struct work_struct *work);
-extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode);
-extern bool smb2_is_valid_oplock_break(char *buffer,
- struct TCP_Server_Info *srv);
-extern int smb3_handle_read_data(struct TCP_Server_Info *server,
- struct mid_q_entry *mid);
-extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *path,
- __u32 *reparse_tag);
-int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
-extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
- const char *full_path, __u64 size,
- struct cifs_sb_info *cifs_sb, bool set_alloc);
-extern int smb2_set_file_info(struct inode *inode, const char *full_path,
- FILE_BASIC_INFO *buf, const unsigned int xid);
-extern int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
- umode_t mode, struct cifs_tcon *tcon,
- const char *full_path,
- struct cifs_sb_info *cifs_sb);
-extern int smb2_mkdir(const unsigned int xid, struct inode *inode,
- umode_t mode, struct cifs_tcon *tcon,
- const char *name, struct cifs_sb_info *cifs_sb);
-extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path,
- struct cifs_sb_info *cifs_sb,
- struct cifs_tcon *tcon, const unsigned int xid);
-extern int smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
- const char *name, struct cifs_sb_info *cifs_sb);
-extern int smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon,
- const char *name, struct cifs_sb_info *cifs_sb);
-extern int smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb);
-extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb);
-extern int smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const unsigned char *path,
- char *pbuf, unsigned int *pbytes_written);
-extern int smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- const unsigned char *path, char *pbuf,
- unsigned int *pbytes_read);
-int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path);
-int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
- void *buf);
-extern int smb2_unlock_range(struct cifsFileInfo *cfile,
- struct file_lock *flock, const unsigned int xid);
-extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
-extern void smb2_reconnect_server(struct work_struct *work);
-extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server);
-extern unsigned long smb_rqst_len(struct TCP_Server_Info *server,
- struct smb_rqst *rqst);
-extern void smb2_set_next_command(struct cifs_tcon *tcon,
- struct smb_rqst *rqst);
-extern void smb2_set_related(struct smb_rqst *rqst);
-
-/*
- * SMB2 Worker functions - most of protocol specific implementation details
- * are contained within these calls.
- */
-extern int SMB2_negotiate(const unsigned int xid,
- struct cifs_ses *ses,
- struct TCP_Server_Info *server);
-extern int SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct nls_table *nls_cp);
-extern int SMB2_logoff(const unsigned int xid, struct cifs_ses *ses);
-extern int SMB2_tcon(const unsigned int xid, struct cifs_ses *ses,
- const char *tree, struct cifs_tcon *tcon,
- const struct nls_table *);
-extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
-extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
- __le16 *path, __u8 *oplock,
- struct smb2_file_all_info *buf,
- struct create_posix_rsp *posix,
- struct kvec *err_iov, int *resp_buftype);
-extern int SMB2_open_init(struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- __u8 *oplock, struct cifs_open_parms *oparms,
- __le16 *path);
-extern void SMB2_open_free(struct smb_rqst *rqst);
-extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, u32 opcode,
- char *in_data, u32 indatalen, u32 maxoutlen,
- char **out_data, u32 *plen /* returned data len */);
-extern int SMB2_ioctl_init(struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid, u32 opcode,
- char *in_data, u32 indatalen,
- __u32 max_response_size);
-extern void SMB2_ioctl_free(struct smb_rqst *rqst);
-extern int SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, bool watch_tree,
- u32 completion_filter, u32 max_out_data_len,
- char **out_data, u32 *plen /* returned data len */);
-
-extern int __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- struct smb2_file_network_open_info *pbuf);
-extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_file_id, u64 volatile_file_id);
-extern int SMB2_close_init(struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid,
- bool query_attrs);
-extern void SMB2_close_free(struct smb_rqst *rqst);
-extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_file_id, u64 volatile_file_id);
-extern int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst,
- struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- u64 persistent_file_id, u64 volatile_file_id);
-extern void SMB2_flush_free(struct smb_rqst *rqst);
-extern int SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen);
-extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_file_id, u64 volatile_file_id,
- struct smb2_file_all_info *data);
-extern int SMB2_query_info_init(struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid,
- u8 info_class, u8 info_type,
- u32 additional_info, size_t output_len,
- size_t input_len, void *input);
-extern void SMB2_query_info_free(struct smb_rqst *rqst);
-extern int SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_file_id, u64 volatile_file_id,
- void **data, unsigned int *plen, u32 info);
-extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- __le64 *uniqueid);
-extern int smb2_async_readv(struct cifs_readdata *rdata);
-extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, char **buf, int *buf_type);
-extern int smb2_async_writev(struct cifs_writedata *wdata,
- void (*release)(struct kref *kref));
-extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
- unsigned int *nbytes, struct kvec *iov, int n_vec);
-extern int SMB2_echo(struct TCP_Server_Info *server);
-extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, int index,
- struct cifs_search_info *srch_inf);
-extern int SMB2_query_directory_init(unsigned int xid, struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid,
- int index, int info_level);
-extern void SMB2_query_directory_free(struct smb_rqst *rqst);
-extern int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, u32 pid,
- __le64 *eof);
-extern int SMB2_set_info_init(struct cifs_tcon *tcon,
- struct TCP_Server_Info *server,
- struct smb_rqst *rqst,
- u64 persistent_fid, u64 volatile_fid, u32 pid,
- u8 info_class, u8 info_type, u32 additional_info,
- void **data, unsigned int *size);
-extern void SMB2_set_info_free(struct smb_rqst *rqst);
-extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- struct cifs_ntsd *pnntsd, int pacllen, int aclflag);
-extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid,
- struct smb2_file_full_ea_info *buf, int len);
-extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid);
-extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
- const u64 persistent_fid, const u64 volatile_fid,
- const __u8 oplock_level);
-extern int smb2_handle_cancelled_close(struct cifs_tcon *tcon,
- __u64 persistent_fid,
- __u64 volatile_fid);
-extern int smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server);
-void smb2_cancelled_close_fid(struct work_struct *work);
-extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_file_id, u64 volatile_file_id,
- struct kstatfs *FSData);
-extern int SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_file_id, u64 volatile_file_id,
- struct kstatfs *FSData);
-extern int SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_file_id, u64 volatile_file_id, int lvl);
-extern int SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon,
- const __u64 persist_fid, const __u64 volatile_fid,
- const __u32 pid, const __u64 length, const __u64 offset,
- const __u32 lockFlags, const bool wait);
-extern int smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
- const __u64 persist_fid, const __u64 volatile_fid,
- const __u32 pid, const __u32 num_lock,
- struct smb2_lock_element *buf);
-extern int SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
- __u8 *lease_key, const __le32 lease_state);
-extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *);
-
-extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
- enum securityEnum);
-extern void smb2_parse_contexts(struct TCP_Server_Info *server,
- struct smb2_create_rsp *rsp,
- unsigned int *epoch, char *lease_key,
- __u8 *oplock, struct smb2_file_all_info *buf,
- struct create_posix_rsp *posix);
-extern int smb3_encryption_required(const struct cifs_tcon *tcon);
-extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
- struct kvec *iov, unsigned int min_buf_size);
-extern int smb2_validate_and_copy_iov(unsigned int offset,
- unsigned int buffer_length,
- struct kvec *iov,
- unsigned int minbufsize, char *data);
-extern void smb2_copy_fs_info_to_kstatfs(
- struct smb2_fs_full_size_info *pfs_inf,
- struct kstatfs *kst);
-extern int smb311_crypto_shash_allocate(struct TCP_Server_Info *server);
-extern int smb311_update_preauth_hash(struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- struct kvec *iov, int nvec);
-extern int smb2_query_info_compound(const unsigned int xid,
- struct cifs_tcon *tcon,
- const char *path, u32 desired_access,
- u32 class, u32 type, u32 output_len,
- struct kvec *rsp, int *buftype,
- struct cifs_sb_info *cifs_sb);
-/* query path info from the server using SMB311 POSIX extensions*/
-int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *full_path,
- struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
-int posix_info_parse(const void *beg, const void *end,
- struct smb2_posix_info_parsed *out);
-int posix_info_sid_size(const void *beg, const void *end);
-#endif /* _SMB2PROTO_H */
diff --git a/fs/cifs/smb2status.h b/fs/cifs/smb2status.h
deleted file mode 100644
index a9e958166fc5..000000000000
--- a/fs/cifs/smb2status.h
+++ /dev/null
@@ -1,1769 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * SMB2 Status code (network error) definitions
- * Definitions are from MS-ERREF
- *
- * Copyright (c) International Business Machines Corp., 2009,2011
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-/*
- * 0 1 2 3 4 5 6 7 8 9 0 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
- * SEV C N <-------Facility--------> <------Error Status Code------>
- *
- * C is set if "customer defined" error, N bit is reserved and MBZ
- */
-
-#define STATUS_SEVERITY_SUCCESS __constant_cpu_to_le32(0x0000)
-#define STATUS_SEVERITY_INFORMATIONAL cpu_to_le32(0x0001)
-#define STATUS_SEVERITY_WARNING cpu_to_le32(0x0002)
-#define STATUS_SEVERITY_ERROR cpu_to_le32(0x0003)
-
-struct ntstatus {
- /* Facility is the high 12 bits of the following field */
- __le32 Facility; /* low 2 bits Severity, next is Customer, then rsrvd */
- __le32 Code;
-};
-
-#define STATUS_SUCCESS cpu_to_le32(0x00000000)
-#define STATUS_WAIT_0 cpu_to_le32(0x00000000)
-#define STATUS_WAIT_1 cpu_to_le32(0x00000001)
-#define STATUS_WAIT_2 cpu_to_le32(0x00000002)
-#define STATUS_WAIT_3 cpu_to_le32(0x00000003)
-#define STATUS_WAIT_63 cpu_to_le32(0x0000003F)
-#define STATUS_ABANDONED cpu_to_le32(0x00000080)
-#define STATUS_ABANDONED_WAIT_0 cpu_to_le32(0x00000080)
-#define STATUS_ABANDONED_WAIT_63 cpu_to_le32(0x000000BF)
-#define STATUS_USER_APC cpu_to_le32(0x000000C0)
-#define STATUS_KERNEL_APC cpu_to_le32(0x00000100)
-#define STATUS_ALERTED cpu_to_le32(0x00000101)
-#define STATUS_TIMEOUT cpu_to_le32(0x00000102)
-#define STATUS_PENDING cpu_to_le32(0x00000103)
-#define STATUS_REPARSE cpu_to_le32(0x00000104)
-#define STATUS_MORE_ENTRIES cpu_to_le32(0x00000105)
-#define STATUS_NOT_ALL_ASSIGNED cpu_to_le32(0x00000106)
-#define STATUS_SOME_NOT_MAPPED cpu_to_le32(0x00000107)
-#define STATUS_OPLOCK_BREAK_IN_PROGRESS cpu_to_le32(0x00000108)
-#define STATUS_VOLUME_MOUNTED cpu_to_le32(0x00000109)
-#define STATUS_RXACT_COMMITTED cpu_to_le32(0x0000010A)
-#define STATUS_NOTIFY_CLEANUP cpu_to_le32(0x0000010B)
-#define STATUS_NOTIFY_ENUM_DIR cpu_to_le32(0x0000010C)
-#define STATUS_NO_QUOTAS_FOR_ACCOUNT cpu_to_le32(0x0000010D)
-#define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED cpu_to_le32(0x0000010E)
-#define STATUS_PAGE_FAULT_TRANSITION cpu_to_le32(0x00000110)
-#define STATUS_PAGE_FAULT_DEMAND_ZERO cpu_to_le32(0x00000111)
-#define STATUS_PAGE_FAULT_COPY_ON_WRITE cpu_to_le32(0x00000112)
-#define STATUS_PAGE_FAULT_GUARD_PAGE cpu_to_le32(0x00000113)
-#define STATUS_PAGE_FAULT_PAGING_FILE cpu_to_le32(0x00000114)
-#define STATUS_CACHE_PAGE_LOCKED cpu_to_le32(0x00000115)
-#define STATUS_CRASH_DUMP cpu_to_le32(0x00000116)
-#define STATUS_BUFFER_ALL_ZEROS cpu_to_le32(0x00000117)
-#define STATUS_REPARSE_OBJECT cpu_to_le32(0x00000118)
-#define STATUS_RESOURCE_REQUIREMENTS_CHANGED cpu_to_le32(0x00000119)
-#define STATUS_TRANSLATION_COMPLETE cpu_to_le32(0x00000120)
-#define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY cpu_to_le32(0x00000121)
-#define STATUS_NOTHING_TO_TERMINATE cpu_to_le32(0x00000122)
-#define STATUS_PROCESS_NOT_IN_JOB cpu_to_le32(0x00000123)
-#define STATUS_PROCESS_IN_JOB cpu_to_le32(0x00000124)
-#define STATUS_VOLSNAP_HIBERNATE_READY cpu_to_le32(0x00000125)
-#define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY cpu_to_le32(0x00000126)
-#define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED cpu_to_le32(0x00000127)
-#define STATUS_INTERRUPT_STILL_CONNECTED cpu_to_le32(0x00000128)
-#define STATUS_PROCESS_CLONED cpu_to_le32(0x00000129)
-#define STATUS_FILE_LOCKED_WITH_ONLY_READERS cpu_to_le32(0x0000012A)
-#define STATUS_FILE_LOCKED_WITH_WRITERS cpu_to_le32(0x0000012B)
-#define STATUS_RESOURCEMANAGER_READ_ONLY cpu_to_le32(0x00000202)
-#define STATUS_WAIT_FOR_OPLOCK cpu_to_le32(0x00000367)
-#define DBG_EXCEPTION_HANDLED cpu_to_le32(0x00010001)
-#define DBG_CONTINUE cpu_to_le32(0x00010002)
-#define STATUS_FLT_IO_COMPLETE cpu_to_le32(0x001C0001)
-#define STATUS_OBJECT_NAME_EXISTS cpu_to_le32(0x40000000)
-#define STATUS_THREAD_WAS_SUSPENDED cpu_to_le32(0x40000001)
-#define STATUS_WORKING_SET_LIMIT_RANGE cpu_to_le32(0x40000002)
-#define STATUS_IMAGE_NOT_AT_BASE cpu_to_le32(0x40000003)
-#define STATUS_RXACT_STATE_CREATED cpu_to_le32(0x40000004)
-#define STATUS_SEGMENT_NOTIFICATION cpu_to_le32(0x40000005)
-#define STATUS_LOCAL_USER_SESSION_KEY cpu_to_le32(0x40000006)
-#define STATUS_BAD_CURRENT_DIRECTORY cpu_to_le32(0x40000007)
-#define STATUS_SERIAL_MORE_WRITES cpu_to_le32(0x40000008)
-#define STATUS_REGISTRY_RECOVERED cpu_to_le32(0x40000009)
-#define STATUS_FT_READ_RECOVERY_FROM_BACKUP cpu_to_le32(0x4000000A)
-#define STATUS_FT_WRITE_RECOVERY cpu_to_le32(0x4000000B)
-#define STATUS_SERIAL_COUNTER_TIMEOUT cpu_to_le32(0x4000000C)
-#define STATUS_NULL_LM_PASSWORD cpu_to_le32(0x4000000D)
-#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH cpu_to_le32(0x4000000E)
-#define STATUS_RECEIVE_PARTIAL cpu_to_le32(0x4000000F)
-#define STATUS_RECEIVE_EXPEDITED cpu_to_le32(0x40000010)
-#define STATUS_RECEIVE_PARTIAL_EXPEDITED cpu_to_le32(0x40000011)
-#define STATUS_EVENT_DONE cpu_to_le32(0x40000012)
-#define STATUS_EVENT_PENDING cpu_to_le32(0x40000013)
-#define STATUS_CHECKING_FILE_SYSTEM cpu_to_le32(0x40000014)
-#define STATUS_FATAL_APP_EXIT cpu_to_le32(0x40000015)
-#define STATUS_PREDEFINED_HANDLE cpu_to_le32(0x40000016)
-#define STATUS_WAS_UNLOCKED cpu_to_le32(0x40000017)
-#define STATUS_SERVICE_NOTIFICATION cpu_to_le32(0x40000018)
-#define STATUS_WAS_LOCKED cpu_to_le32(0x40000019)
-#define STATUS_LOG_HARD_ERROR cpu_to_le32(0x4000001A)
-#define STATUS_ALREADY_WIN32 cpu_to_le32(0x4000001B)
-#define STATUS_WX86_UNSIMULATE cpu_to_le32(0x4000001C)
-#define STATUS_WX86_CONTINUE cpu_to_le32(0x4000001D)
-#define STATUS_WX86_SINGLE_STEP cpu_to_le32(0x4000001E)
-#define STATUS_WX86_BREAKPOINT cpu_to_le32(0x4000001F)
-#define STATUS_WX86_EXCEPTION_CONTINUE cpu_to_le32(0x40000020)
-#define STATUS_WX86_EXCEPTION_LASTCHANCE cpu_to_le32(0x40000021)
-#define STATUS_WX86_EXCEPTION_CHAIN cpu_to_le32(0x40000022)
-#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE cpu_to_le32(0x40000023)
-#define STATUS_NO_YIELD_PERFORMED cpu_to_le32(0x40000024)
-#define STATUS_TIMER_RESUME_IGNORED cpu_to_le32(0x40000025)
-#define STATUS_ARBITRATION_UNHANDLED cpu_to_le32(0x40000026)
-#define STATUS_CARDBUS_NOT_SUPPORTED cpu_to_le32(0x40000027)
-#define STATUS_WX86_CREATEWX86TIB cpu_to_le32(0x40000028)
-#define STATUS_MP_PROCESSOR_MISMATCH cpu_to_le32(0x40000029)
-#define STATUS_HIBERNATED cpu_to_le32(0x4000002A)
-#define STATUS_RESUME_HIBERNATION cpu_to_le32(0x4000002B)
-#define STATUS_FIRMWARE_UPDATED cpu_to_le32(0x4000002C)
-#define STATUS_DRIVERS_LEAKING_LOCKED_PAGES cpu_to_le32(0x4000002D)
-#define STATUS_MESSAGE_RETRIEVED cpu_to_le32(0x4000002E)
-#define STATUS_SYSTEM_POWERSTATE_TRANSITION cpu_to_le32(0x4000002F)
-#define STATUS_ALPC_CHECK_COMPLETION_LIST cpu_to_le32(0x40000030)
-#define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION cpu_to_le32(0x40000031)
-#define STATUS_ACCESS_AUDIT_BY_POLICY cpu_to_le32(0x40000032)
-#define STATUS_ABANDON_HIBERFILE cpu_to_le32(0x40000033)
-#define STATUS_BIZRULES_NOT_ENABLED cpu_to_le32(0x40000034)
-#define STATUS_WAKE_SYSTEM cpu_to_le32(0x40000294)
-#define STATUS_DS_SHUTTING_DOWN cpu_to_le32(0x40000370)
-#define DBG_REPLY_LATER cpu_to_le32(0x40010001)
-#define DBG_UNABLE_TO_PROVIDE_HANDLE cpu_to_le32(0x40010002)
-#define DBG_TERMINATE_THREAD cpu_to_le32(0x40010003)
-#define DBG_TERMINATE_PROCESS cpu_to_le32(0x40010004)
-#define DBG_CONTROL_C cpu_to_le32(0x40010005)
-#define DBG_PRINTEXCEPTION_C cpu_to_le32(0x40010006)
-#define DBG_RIPEXCEPTION cpu_to_le32(0x40010007)
-#define DBG_CONTROL_BREAK cpu_to_le32(0x40010008)
-#define DBG_COMMAND_EXCEPTION cpu_to_le32(0x40010009)
-#define RPC_NT_UUID_LOCAL_ONLY cpu_to_le32(0x40020056)
-#define RPC_NT_SEND_INCOMPLETE cpu_to_le32(0x400200AF)
-#define STATUS_CTX_CDM_CONNECT cpu_to_le32(0x400A0004)
-#define STATUS_CTX_CDM_DISCONNECT cpu_to_le32(0x400A0005)
-#define STATUS_SXS_RELEASE_ACTIVATION_CONTEXT cpu_to_le32(0x4015000D)
-#define STATUS_RECOVERY_NOT_NEEDED cpu_to_le32(0x40190034)
-#define STATUS_RM_ALREADY_STARTED cpu_to_le32(0x40190035)
-#define STATUS_LOG_NO_RESTART cpu_to_le32(0x401A000C)
-#define STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST cpu_to_le32(0x401B00EC)
-#define STATUS_GRAPHICS_PARTIAL_DATA_POPULATED cpu_to_le32(0x401E000A)
-#define STATUS_GRAPHICS_DRIVER_MISMATCH cpu_to_le32(0x401E0117)
-#define STATUS_GRAPHICS_MODE_NOT_PINNED cpu_to_le32(0x401E0307)
-#define STATUS_GRAPHICS_NO_PREFERRED_MODE cpu_to_le32(0x401E031E)
-#define STATUS_GRAPHICS_DATASET_IS_EMPTY cpu_to_le32(0x401E034B)
-#define STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET cpu_to_le32(0x401E034C)
-#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED cpu_to_le32(0x401E0351)
-#define STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS cpu_to_le32(0x401E042F)
-#define STATUS_GRAPHICS_LEADLINK_START_DEFERRED cpu_to_le32(0x401E0437)
-#define STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY cpu_to_le32(0x401E0439)
-#define STATUS_GRAPHICS_START_DEFERRED cpu_to_le32(0x401E043A)
-#define STATUS_NDIS_INDICATION_REQUIRED cpu_to_le32(0x40230001)
-#define STATUS_GUARD_PAGE_VIOLATION cpu_to_le32(0x80000001)
-#define STATUS_DATATYPE_MISALIGNMENT cpu_to_le32(0x80000002)
-#define STATUS_BREAKPOINT cpu_to_le32(0x80000003)
-#define STATUS_SINGLE_STEP cpu_to_le32(0x80000004)
-#define STATUS_BUFFER_OVERFLOW cpu_to_le32(0x80000005)
-#define STATUS_NO_MORE_FILES cpu_to_le32(0x80000006)
-#define STATUS_WAKE_SYSTEM_DEBUGGER cpu_to_le32(0x80000007)
-#define STATUS_HANDLES_CLOSED cpu_to_le32(0x8000000A)
-#define STATUS_NO_INHERITANCE cpu_to_le32(0x8000000B)
-#define STATUS_GUID_SUBSTITUTION_MADE cpu_to_le32(0x8000000C)
-#define STATUS_PARTIAL_COPY cpu_to_le32(0x8000000D)
-#define STATUS_DEVICE_PAPER_EMPTY cpu_to_le32(0x8000000E)
-#define STATUS_DEVICE_POWERED_OFF cpu_to_le32(0x8000000F)
-#define STATUS_DEVICE_OFF_LINE cpu_to_le32(0x80000010)
-#define STATUS_DEVICE_BUSY cpu_to_le32(0x80000011)
-#define STATUS_NO_MORE_EAS cpu_to_le32(0x80000012)
-#define STATUS_INVALID_EA_NAME cpu_to_le32(0x80000013)
-#define STATUS_EA_LIST_INCONSISTENT cpu_to_le32(0x80000014)
-#define STATUS_INVALID_EA_FLAG cpu_to_le32(0x80000015)
-#define STATUS_VERIFY_REQUIRED cpu_to_le32(0x80000016)
-#define STATUS_EXTRANEOUS_INFORMATION cpu_to_le32(0x80000017)
-#define STATUS_RXACT_COMMIT_NECESSARY cpu_to_le32(0x80000018)
-#define STATUS_NO_MORE_ENTRIES cpu_to_le32(0x8000001A)
-#define STATUS_FILEMARK_DETECTED cpu_to_le32(0x8000001B)
-#define STATUS_MEDIA_CHANGED cpu_to_le32(0x8000001C)
-#define STATUS_BUS_RESET cpu_to_le32(0x8000001D)
-#define STATUS_END_OF_MEDIA cpu_to_le32(0x8000001E)
-#define STATUS_BEGINNING_OF_MEDIA cpu_to_le32(0x8000001F)
-#define STATUS_MEDIA_CHECK cpu_to_le32(0x80000020)
-#define STATUS_SETMARK_DETECTED cpu_to_le32(0x80000021)
-#define STATUS_NO_DATA_DETECTED cpu_to_le32(0x80000022)
-#define STATUS_REDIRECTOR_HAS_OPEN_HANDLES cpu_to_le32(0x80000023)
-#define STATUS_SERVER_HAS_OPEN_HANDLES cpu_to_le32(0x80000024)
-#define STATUS_ALREADY_DISCONNECTED cpu_to_le32(0x80000025)
-#define STATUS_LONGJUMP cpu_to_le32(0x80000026)
-#define STATUS_CLEANER_CARTRIDGE_INSTALLED cpu_to_le32(0x80000027)
-#define STATUS_PLUGPLAY_QUERY_VETOED cpu_to_le32(0x80000028)
-#define STATUS_UNWIND_CONSOLIDATE cpu_to_le32(0x80000029)
-#define STATUS_REGISTRY_HIVE_RECOVERED cpu_to_le32(0x8000002A)
-#define STATUS_DLL_MIGHT_BE_INSECURE cpu_to_le32(0x8000002B)
-#define STATUS_DLL_MIGHT_BE_INCOMPATIBLE cpu_to_le32(0x8000002C)
-#define STATUS_STOPPED_ON_SYMLINK cpu_to_le32(0x8000002D)
-#define STATUS_DEVICE_REQUIRES_CLEANING cpu_to_le32(0x80000288)
-#define STATUS_DEVICE_DOOR_OPEN cpu_to_le32(0x80000289)
-#define STATUS_DATA_LOST_REPAIR cpu_to_le32(0x80000803)
-#define DBG_EXCEPTION_NOT_HANDLED cpu_to_le32(0x80010001)
-#define STATUS_CLUSTER_NODE_ALREADY_UP cpu_to_le32(0x80130001)
-#define STATUS_CLUSTER_NODE_ALREADY_DOWN cpu_to_le32(0x80130002)
-#define STATUS_CLUSTER_NETWORK_ALREADY_ONLINE cpu_to_le32(0x80130003)
-#define STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE cpu_to_le32(0x80130004)
-#define STATUS_CLUSTER_NODE_ALREADY_MEMBER cpu_to_le32(0x80130005)
-#define STATUS_COULD_NOT_RESIZE_LOG cpu_to_le32(0x80190009)
-#define STATUS_NO_TXF_METADATA cpu_to_le32(0x80190029)
-#define STATUS_CANT_RECOVER_WITH_HANDLE_OPEN cpu_to_le32(0x80190031)
-#define STATUS_TXF_METADATA_ALREADY_PRESENT cpu_to_le32(0x80190041)
-#define STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET cpu_to_le32(0x80190042)
-#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED cpu_to_le32(0x801B00EB)
-#define STATUS_FLT_BUFFER_TOO_SMALL cpu_to_le32(0x801C0001)
-#define STATUS_FVE_PARTIAL_METADATA cpu_to_le32(0x80210001)
-#define STATUS_UNSUCCESSFUL cpu_to_le32(0xC0000001)
-#define STATUS_NOT_IMPLEMENTED cpu_to_le32(0xC0000002)
-#define STATUS_INVALID_INFO_CLASS cpu_to_le32(0xC0000003)
-#define STATUS_INFO_LENGTH_MISMATCH cpu_to_le32(0xC0000004)
-#define STATUS_ACCESS_VIOLATION cpu_to_le32(0xC0000005)
-#define STATUS_IN_PAGE_ERROR cpu_to_le32(0xC0000006)
-#define STATUS_PAGEFILE_QUOTA cpu_to_le32(0xC0000007)
-#define STATUS_INVALID_HANDLE cpu_to_le32(0xC0000008)
-#define STATUS_BAD_INITIAL_STACK cpu_to_le32(0xC0000009)
-#define STATUS_BAD_INITIAL_PC cpu_to_le32(0xC000000A)
-#define STATUS_INVALID_CID cpu_to_le32(0xC000000B)
-#define STATUS_TIMER_NOT_CANCELED cpu_to_le32(0xC000000C)
-#define STATUS_INVALID_PARAMETER cpu_to_le32(0xC000000D)
-#define STATUS_NO_SUCH_DEVICE cpu_to_le32(0xC000000E)
-#define STATUS_NO_SUCH_FILE cpu_to_le32(0xC000000F)
-#define STATUS_INVALID_DEVICE_REQUEST cpu_to_le32(0xC0000010)
-#define STATUS_END_OF_FILE cpu_to_le32(0xC0000011)
-#define STATUS_WRONG_VOLUME cpu_to_le32(0xC0000012)
-#define STATUS_NO_MEDIA_IN_DEVICE cpu_to_le32(0xC0000013)
-#define STATUS_UNRECOGNIZED_MEDIA cpu_to_le32(0xC0000014)
-#define STATUS_NONEXISTENT_SECTOR cpu_to_le32(0xC0000015)
-#define STATUS_MORE_PROCESSING_REQUIRED cpu_to_le32(0xC0000016)
-#define STATUS_NO_MEMORY cpu_to_le32(0xC0000017)
-#define STATUS_CONFLICTING_ADDRESSES cpu_to_le32(0xC0000018)
-#define STATUS_NOT_MAPPED_VIEW cpu_to_le32(0xC0000019)
-#define STATUS_UNABLE_TO_FREE_VM cpu_to_le32(0xC000001A)
-#define STATUS_UNABLE_TO_DELETE_SECTION cpu_to_le32(0xC000001B)
-#define STATUS_INVALID_SYSTEM_SERVICE cpu_to_le32(0xC000001C)
-#define STATUS_ILLEGAL_INSTRUCTION cpu_to_le32(0xC000001D)
-#define STATUS_INVALID_LOCK_SEQUENCE cpu_to_le32(0xC000001E)
-#define STATUS_INVALID_VIEW_SIZE cpu_to_le32(0xC000001F)
-#define STATUS_INVALID_FILE_FOR_SECTION cpu_to_le32(0xC0000020)
-#define STATUS_ALREADY_COMMITTED cpu_to_le32(0xC0000021)
-#define STATUS_ACCESS_DENIED cpu_to_le32(0xC0000022)
-#define STATUS_BUFFER_TOO_SMALL cpu_to_le32(0xC0000023)
-#define STATUS_OBJECT_TYPE_MISMATCH cpu_to_le32(0xC0000024)
-#define STATUS_NONCONTINUABLE_EXCEPTION cpu_to_le32(0xC0000025)
-#define STATUS_INVALID_DISPOSITION cpu_to_le32(0xC0000026)
-#define STATUS_UNWIND cpu_to_le32(0xC0000027)
-#define STATUS_BAD_STACK cpu_to_le32(0xC0000028)
-#define STATUS_INVALID_UNWIND_TARGET cpu_to_le32(0xC0000029)
-#define STATUS_NOT_LOCKED cpu_to_le32(0xC000002A)
-#define STATUS_PARITY_ERROR cpu_to_le32(0xC000002B)
-#define STATUS_UNABLE_TO_DECOMMIT_VM cpu_to_le32(0xC000002C)
-#define STATUS_NOT_COMMITTED cpu_to_le32(0xC000002D)
-#define STATUS_INVALID_PORT_ATTRIBUTES cpu_to_le32(0xC000002E)
-#define STATUS_PORT_MESSAGE_TOO_LONG cpu_to_le32(0xC000002F)
-#define STATUS_INVALID_PARAMETER_MIX cpu_to_le32(0xC0000030)
-#define STATUS_INVALID_QUOTA_LOWER cpu_to_le32(0xC0000031)
-#define STATUS_DISK_CORRUPT_ERROR cpu_to_le32(0xC0000032)
-#define STATUS_OBJECT_NAME_INVALID cpu_to_le32(0xC0000033)
-#define STATUS_OBJECT_NAME_NOT_FOUND cpu_to_le32(0xC0000034)
-#define STATUS_OBJECT_NAME_COLLISION cpu_to_le32(0xC0000035)
-#define STATUS_PORT_DISCONNECTED cpu_to_le32(0xC0000037)
-#define STATUS_DEVICE_ALREADY_ATTACHED cpu_to_le32(0xC0000038)
-#define STATUS_OBJECT_PATH_INVALID cpu_to_le32(0xC0000039)
-#define STATUS_OBJECT_PATH_NOT_FOUND cpu_to_le32(0xC000003A)
-#define STATUS_OBJECT_PATH_SYNTAX_BAD cpu_to_le32(0xC000003B)
-#define STATUS_DATA_OVERRUN cpu_to_le32(0xC000003C)
-#define STATUS_DATA_LATE_ERROR cpu_to_le32(0xC000003D)
-#define STATUS_DATA_ERROR cpu_to_le32(0xC000003E)
-#define STATUS_CRC_ERROR cpu_to_le32(0xC000003F)
-#define STATUS_SECTION_TOO_BIG cpu_to_le32(0xC0000040)
-#define STATUS_PORT_CONNECTION_REFUSED cpu_to_le32(0xC0000041)
-#define STATUS_INVALID_PORT_HANDLE cpu_to_le32(0xC0000042)
-#define STATUS_SHARING_VIOLATION cpu_to_le32(0xC0000043)
-#define STATUS_QUOTA_EXCEEDED cpu_to_le32(0xC0000044)
-#define STATUS_INVALID_PAGE_PROTECTION cpu_to_le32(0xC0000045)
-#define STATUS_MUTANT_NOT_OWNED cpu_to_le32(0xC0000046)
-#define STATUS_SEMAPHORE_LIMIT_EXCEEDED cpu_to_le32(0xC0000047)
-#define STATUS_PORT_ALREADY_SET cpu_to_le32(0xC0000048)
-#define STATUS_SECTION_NOT_IMAGE cpu_to_le32(0xC0000049)
-#define STATUS_SUSPEND_COUNT_EXCEEDED cpu_to_le32(0xC000004A)
-#define STATUS_THREAD_IS_TERMINATING cpu_to_le32(0xC000004B)
-#define STATUS_BAD_WORKING_SET_LIMIT cpu_to_le32(0xC000004C)
-#define STATUS_INCOMPATIBLE_FILE_MAP cpu_to_le32(0xC000004D)
-#define STATUS_SECTION_PROTECTION cpu_to_le32(0xC000004E)
-#define STATUS_EAS_NOT_SUPPORTED cpu_to_le32(0xC000004F)
-#define STATUS_EA_TOO_LARGE cpu_to_le32(0xC0000050)
-#define STATUS_NONEXISTENT_EA_ENTRY cpu_to_le32(0xC0000051)
-#define STATUS_NO_EAS_ON_FILE cpu_to_le32(0xC0000052)
-#define STATUS_EA_CORRUPT_ERROR cpu_to_le32(0xC0000053)
-#define STATUS_FILE_LOCK_CONFLICT cpu_to_le32(0xC0000054)
-#define STATUS_LOCK_NOT_GRANTED cpu_to_le32(0xC0000055)
-#define STATUS_DELETE_PENDING cpu_to_le32(0xC0000056)
-#define STATUS_CTL_FILE_NOT_SUPPORTED cpu_to_le32(0xC0000057)
-#define STATUS_UNKNOWN_REVISION cpu_to_le32(0xC0000058)
-#define STATUS_REVISION_MISMATCH cpu_to_le32(0xC0000059)
-#define STATUS_INVALID_OWNER cpu_to_le32(0xC000005A)
-#define STATUS_INVALID_PRIMARY_GROUP cpu_to_le32(0xC000005B)
-#define STATUS_NO_IMPERSONATION_TOKEN cpu_to_le32(0xC000005C)
-#define STATUS_CANT_DISABLE_MANDATORY cpu_to_le32(0xC000005D)
-#define STATUS_NO_LOGON_SERVERS cpu_to_le32(0xC000005E)
-#define STATUS_NO_SUCH_LOGON_SESSION cpu_to_le32(0xC000005F)
-#define STATUS_NO_SUCH_PRIVILEGE cpu_to_le32(0xC0000060)
-#define STATUS_PRIVILEGE_NOT_HELD cpu_to_le32(0xC0000061)
-#define STATUS_INVALID_ACCOUNT_NAME cpu_to_le32(0xC0000062)
-#define STATUS_USER_EXISTS cpu_to_le32(0xC0000063)
-#define STATUS_NO_SUCH_USER cpu_to_le32(0xC0000064)
-#define STATUS_GROUP_EXISTS cpu_to_le32(0xC0000065)
-#define STATUS_NO_SUCH_GROUP cpu_to_le32(0xC0000066)
-#define STATUS_MEMBER_IN_GROUP cpu_to_le32(0xC0000067)
-#define STATUS_MEMBER_NOT_IN_GROUP cpu_to_le32(0xC0000068)
-#define STATUS_LAST_ADMIN cpu_to_le32(0xC0000069)
-#define STATUS_WRONG_PASSWORD cpu_to_le32(0xC000006A)
-#define STATUS_ILL_FORMED_PASSWORD cpu_to_le32(0xC000006B)
-#define STATUS_PASSWORD_RESTRICTION cpu_to_le32(0xC000006C)
-#define STATUS_LOGON_FAILURE cpu_to_le32(0xC000006D)
-#define STATUS_ACCOUNT_RESTRICTION cpu_to_le32(0xC000006E)
-#define STATUS_INVALID_LOGON_HOURS cpu_to_le32(0xC000006F)
-#define STATUS_INVALID_WORKSTATION cpu_to_le32(0xC0000070)
-#define STATUS_PASSWORD_EXPIRED cpu_to_le32(0xC0000071)
-#define STATUS_ACCOUNT_DISABLED cpu_to_le32(0xC0000072)
-#define STATUS_NONE_MAPPED cpu_to_le32(0xC0000073)
-#define STATUS_TOO_MANY_LUIDS_REQUESTED cpu_to_le32(0xC0000074)
-#define STATUS_LUIDS_EXHAUSTED cpu_to_le32(0xC0000075)
-#define STATUS_INVALID_SUB_AUTHORITY cpu_to_le32(0xC0000076)
-#define STATUS_INVALID_ACL cpu_to_le32(0xC0000077)
-#define STATUS_INVALID_SID cpu_to_le32(0xC0000078)
-#define STATUS_INVALID_SECURITY_DESCR cpu_to_le32(0xC0000079)
-#define STATUS_PROCEDURE_NOT_FOUND cpu_to_le32(0xC000007A)
-#define STATUS_INVALID_IMAGE_FORMAT cpu_to_le32(0xC000007B)
-#define STATUS_NO_TOKEN cpu_to_le32(0xC000007C)
-#define STATUS_BAD_INHERITANCE_ACL cpu_to_le32(0xC000007D)
-#define STATUS_RANGE_NOT_LOCKED cpu_to_le32(0xC000007E)
-#define STATUS_DISK_FULL cpu_to_le32(0xC000007F)
-#define STATUS_SERVER_DISABLED cpu_to_le32(0xC0000080)
-#define STATUS_SERVER_NOT_DISABLED cpu_to_le32(0xC0000081)
-#define STATUS_TOO_MANY_GUIDS_REQUESTED cpu_to_le32(0xC0000082)
-#define STATUS_GUIDS_EXHAUSTED cpu_to_le32(0xC0000083)
-#define STATUS_INVALID_ID_AUTHORITY cpu_to_le32(0xC0000084)
-#define STATUS_AGENTS_EXHAUSTED cpu_to_le32(0xC0000085)
-#define STATUS_INVALID_VOLUME_LABEL cpu_to_le32(0xC0000086)
-#define STATUS_SECTION_NOT_EXTENDED cpu_to_le32(0xC0000087)
-#define STATUS_NOT_MAPPED_DATA cpu_to_le32(0xC0000088)
-#define STATUS_RESOURCE_DATA_NOT_FOUND cpu_to_le32(0xC0000089)
-#define STATUS_RESOURCE_TYPE_NOT_FOUND cpu_to_le32(0xC000008A)
-#define STATUS_RESOURCE_NAME_NOT_FOUND cpu_to_le32(0xC000008B)
-#define STATUS_ARRAY_BOUNDS_EXCEEDED cpu_to_le32(0xC000008C)
-#define STATUS_FLOAT_DENORMAL_OPERAND cpu_to_le32(0xC000008D)
-#define STATUS_FLOAT_DIVIDE_BY_ZERO cpu_to_le32(0xC000008E)
-#define STATUS_FLOAT_INEXACT_RESULT cpu_to_le32(0xC000008F)
-#define STATUS_FLOAT_INVALID_OPERATION cpu_to_le32(0xC0000090)
-#define STATUS_FLOAT_OVERFLOW cpu_to_le32(0xC0000091)
-#define STATUS_FLOAT_STACK_CHECK cpu_to_le32(0xC0000092)
-#define STATUS_FLOAT_UNDERFLOW cpu_to_le32(0xC0000093)
-#define STATUS_INTEGER_DIVIDE_BY_ZERO cpu_to_le32(0xC0000094)
-#define STATUS_INTEGER_OVERFLOW cpu_to_le32(0xC0000095)
-#define STATUS_PRIVILEGED_INSTRUCTION cpu_to_le32(0xC0000096)
-#define STATUS_TOO_MANY_PAGING_FILES cpu_to_le32(0xC0000097)
-#define STATUS_FILE_INVALID cpu_to_le32(0xC0000098)
-#define STATUS_ALLOTTED_SPACE_EXCEEDED cpu_to_le32(0xC0000099)
-#define STATUS_INSUFFICIENT_RESOURCES cpu_to_le32(0xC000009A)
-#define STATUS_DFS_EXIT_PATH_FOUND cpu_to_le32(0xC000009B)
-#define STATUS_DEVICE_DATA_ERROR cpu_to_le32(0xC000009C)
-#define STATUS_DEVICE_NOT_CONNECTED cpu_to_le32(0xC000009D)
-#define STATUS_DEVICE_POWER_FAILURE cpu_to_le32(0xC000009E)
-#define STATUS_FREE_VM_NOT_AT_BASE cpu_to_le32(0xC000009F)
-#define STATUS_MEMORY_NOT_ALLOCATED cpu_to_le32(0xC00000A0)
-#define STATUS_WORKING_SET_QUOTA cpu_to_le32(0xC00000A1)
-#define STATUS_MEDIA_WRITE_PROTECTED cpu_to_le32(0xC00000A2)
-#define STATUS_DEVICE_NOT_READY cpu_to_le32(0xC00000A3)
-#define STATUS_INVALID_GROUP_ATTRIBUTES cpu_to_le32(0xC00000A4)
-#define STATUS_BAD_IMPERSONATION_LEVEL cpu_to_le32(0xC00000A5)
-#define STATUS_CANT_OPEN_ANONYMOUS cpu_to_le32(0xC00000A6)
-#define STATUS_BAD_VALIDATION_CLASS cpu_to_le32(0xC00000A7)
-#define STATUS_BAD_TOKEN_TYPE cpu_to_le32(0xC00000A8)
-#define STATUS_BAD_MASTER_BOOT_RECORD cpu_to_le32(0xC00000A9)
-#define STATUS_INSTRUCTION_MISALIGNMENT cpu_to_le32(0xC00000AA)
-#define STATUS_INSTANCE_NOT_AVAILABLE cpu_to_le32(0xC00000AB)
-#define STATUS_PIPE_NOT_AVAILABLE cpu_to_le32(0xC00000AC)
-#define STATUS_INVALID_PIPE_STATE cpu_to_le32(0xC00000AD)
-#define STATUS_PIPE_BUSY cpu_to_le32(0xC00000AE)
-#define STATUS_ILLEGAL_FUNCTION cpu_to_le32(0xC00000AF)
-#define STATUS_PIPE_DISCONNECTED cpu_to_le32(0xC00000B0)
-#define STATUS_PIPE_CLOSING cpu_to_le32(0xC00000B1)
-#define STATUS_PIPE_CONNECTED cpu_to_le32(0xC00000B2)
-#define STATUS_PIPE_LISTENING cpu_to_le32(0xC00000B3)
-#define STATUS_INVALID_READ_MODE cpu_to_le32(0xC00000B4)
-#define STATUS_IO_TIMEOUT cpu_to_le32(0xC00000B5)
-#define STATUS_FILE_FORCED_CLOSED cpu_to_le32(0xC00000B6)
-#define STATUS_PROFILING_NOT_STARTED cpu_to_le32(0xC00000B7)
-#define STATUS_PROFILING_NOT_STOPPED cpu_to_le32(0xC00000B8)
-#define STATUS_COULD_NOT_INTERPRET cpu_to_le32(0xC00000B9)
-#define STATUS_FILE_IS_A_DIRECTORY cpu_to_le32(0xC00000BA)
-#define STATUS_NOT_SUPPORTED cpu_to_le32(0xC00000BB)
-#define STATUS_REMOTE_NOT_LISTENING cpu_to_le32(0xC00000BC)
-#define STATUS_DUPLICATE_NAME cpu_to_le32(0xC00000BD)
-#define STATUS_BAD_NETWORK_PATH cpu_to_le32(0xC00000BE)
-#define STATUS_NETWORK_BUSY cpu_to_le32(0xC00000BF)
-#define STATUS_DEVICE_DOES_NOT_EXIST cpu_to_le32(0xC00000C0)
-#define STATUS_TOO_MANY_COMMANDS cpu_to_le32(0xC00000C1)
-#define STATUS_ADAPTER_HARDWARE_ERROR cpu_to_le32(0xC00000C2)
-#define STATUS_INVALID_NETWORK_RESPONSE cpu_to_le32(0xC00000C3)
-#define STATUS_UNEXPECTED_NETWORK_ERROR cpu_to_le32(0xC00000C4)
-#define STATUS_BAD_REMOTE_ADAPTER cpu_to_le32(0xC00000C5)
-#define STATUS_PRINT_QUEUE_FULL cpu_to_le32(0xC00000C6)
-#define STATUS_NO_SPOOL_SPACE cpu_to_le32(0xC00000C7)
-#define STATUS_PRINT_CANCELLED cpu_to_le32(0xC00000C8)
-#define STATUS_NETWORK_NAME_DELETED cpu_to_le32(0xC00000C9)
-#define STATUS_NETWORK_ACCESS_DENIED cpu_to_le32(0xC00000CA)
-#define STATUS_BAD_DEVICE_TYPE cpu_to_le32(0xC00000CB)
-#define STATUS_BAD_NETWORK_NAME cpu_to_le32(0xC00000CC)
-#define STATUS_TOO_MANY_NAMES cpu_to_le32(0xC00000CD)
-#define STATUS_TOO_MANY_SESSIONS cpu_to_le32(0xC00000CE)
-#define STATUS_SHARING_PAUSED cpu_to_le32(0xC00000CF)
-#define STATUS_REQUEST_NOT_ACCEPTED cpu_to_le32(0xC00000D0)
-#define STATUS_REDIRECTOR_PAUSED cpu_to_le32(0xC00000D1)
-#define STATUS_NET_WRITE_FAULT cpu_to_le32(0xC00000D2)
-#define STATUS_PROFILING_AT_LIMIT cpu_to_le32(0xC00000D3)
-#define STATUS_NOT_SAME_DEVICE cpu_to_le32(0xC00000D4)
-#define STATUS_FILE_RENAMED cpu_to_le32(0xC00000D5)
-#define STATUS_VIRTUAL_CIRCUIT_CLOSED cpu_to_le32(0xC00000D6)
-#define STATUS_NO_SECURITY_ON_OBJECT cpu_to_le32(0xC00000D7)
-#define STATUS_CANT_WAIT cpu_to_le32(0xC00000D8)
-#define STATUS_PIPE_EMPTY cpu_to_le32(0xC00000D9)
-#define STATUS_CANT_ACCESS_DOMAIN_INFO cpu_to_le32(0xC00000DA)
-#define STATUS_CANT_TERMINATE_SELF cpu_to_le32(0xC00000DB)
-#define STATUS_INVALID_SERVER_STATE cpu_to_le32(0xC00000DC)
-#define STATUS_INVALID_DOMAIN_STATE cpu_to_le32(0xC00000DD)
-#define STATUS_INVALID_DOMAIN_ROLE cpu_to_le32(0xC00000DE)
-#define STATUS_NO_SUCH_DOMAIN cpu_to_le32(0xC00000DF)
-#define STATUS_DOMAIN_EXISTS cpu_to_le32(0xC00000E0)
-#define STATUS_DOMAIN_LIMIT_EXCEEDED cpu_to_le32(0xC00000E1)
-#define STATUS_OPLOCK_NOT_GRANTED cpu_to_le32(0xC00000E2)
-#define STATUS_INVALID_OPLOCK_PROTOCOL cpu_to_le32(0xC00000E3)
-#define STATUS_INTERNAL_DB_CORRUPTION cpu_to_le32(0xC00000E4)
-#define STATUS_INTERNAL_ERROR cpu_to_le32(0xC00000E5)
-#define STATUS_GENERIC_NOT_MAPPED cpu_to_le32(0xC00000E6)
-#define STATUS_BAD_DESCRIPTOR_FORMAT cpu_to_le32(0xC00000E7)
-#define STATUS_INVALID_USER_BUFFER cpu_to_le32(0xC00000E8)
-#define STATUS_UNEXPECTED_IO_ERROR cpu_to_le32(0xC00000E9)
-#define STATUS_UNEXPECTED_MM_CREATE_ERR cpu_to_le32(0xC00000EA)
-#define STATUS_UNEXPECTED_MM_MAP_ERROR cpu_to_le32(0xC00000EB)
-#define STATUS_UNEXPECTED_MM_EXTEND_ERR cpu_to_le32(0xC00000EC)
-#define STATUS_NOT_LOGON_PROCESS cpu_to_le32(0xC00000ED)
-#define STATUS_LOGON_SESSION_EXISTS cpu_to_le32(0xC00000EE)
-#define STATUS_INVALID_PARAMETER_1 cpu_to_le32(0xC00000EF)
-#define STATUS_INVALID_PARAMETER_2 cpu_to_le32(0xC00000F0)
-#define STATUS_INVALID_PARAMETER_3 cpu_to_le32(0xC00000F1)
-#define STATUS_INVALID_PARAMETER_4 cpu_to_le32(0xC00000F2)
-#define STATUS_INVALID_PARAMETER_5 cpu_to_le32(0xC00000F3)
-#define STATUS_INVALID_PARAMETER_6 cpu_to_le32(0xC00000F4)
-#define STATUS_INVALID_PARAMETER_7 cpu_to_le32(0xC00000F5)
-#define STATUS_INVALID_PARAMETER_8 cpu_to_le32(0xC00000F6)
-#define STATUS_INVALID_PARAMETER_9 cpu_to_le32(0xC00000F7)
-#define STATUS_INVALID_PARAMETER_10 cpu_to_le32(0xC00000F8)
-#define STATUS_INVALID_PARAMETER_11 cpu_to_le32(0xC00000F9)
-#define STATUS_INVALID_PARAMETER_12 cpu_to_le32(0xC00000FA)
-#define STATUS_REDIRECTOR_NOT_STARTED cpu_to_le32(0xC00000FB)
-#define STATUS_REDIRECTOR_STARTED cpu_to_le32(0xC00000FC)
-#define STATUS_STACK_OVERFLOW cpu_to_le32(0xC00000FD)
-#define STATUS_NO_SUCH_PACKAGE cpu_to_le32(0xC00000FE)
-#define STATUS_BAD_FUNCTION_TABLE cpu_to_le32(0xC00000FF)
-#define STATUS_VARIABLE_NOT_FOUND cpu_to_le32(0xC0000100)
-#define STATUS_DIRECTORY_NOT_EMPTY cpu_to_le32(0xC0000101)
-#define STATUS_FILE_CORRUPT_ERROR cpu_to_le32(0xC0000102)
-#define STATUS_NOT_A_DIRECTORY cpu_to_le32(0xC0000103)
-#define STATUS_BAD_LOGON_SESSION_STATE cpu_to_le32(0xC0000104)
-#define STATUS_LOGON_SESSION_COLLISION cpu_to_le32(0xC0000105)
-#define STATUS_NAME_TOO_LONG cpu_to_le32(0xC0000106)
-#define STATUS_FILES_OPEN cpu_to_le32(0xC0000107)
-#define STATUS_CONNECTION_IN_USE cpu_to_le32(0xC0000108)
-#define STATUS_MESSAGE_NOT_FOUND cpu_to_le32(0xC0000109)
-#define STATUS_PROCESS_IS_TERMINATING cpu_to_le32(0xC000010A)
-#define STATUS_INVALID_LOGON_TYPE cpu_to_le32(0xC000010B)
-#define STATUS_NO_GUID_TRANSLATION cpu_to_le32(0xC000010C)
-#define STATUS_CANNOT_IMPERSONATE cpu_to_le32(0xC000010D)
-#define STATUS_IMAGE_ALREADY_LOADED cpu_to_le32(0xC000010E)
-#define STATUS_ABIOS_NOT_PRESENT cpu_to_le32(0xC000010F)
-#define STATUS_ABIOS_LID_NOT_EXIST cpu_to_le32(0xC0000110)
-#define STATUS_ABIOS_LID_ALREADY_OWNED cpu_to_le32(0xC0000111)
-#define STATUS_ABIOS_NOT_LID_OWNER cpu_to_le32(0xC0000112)
-#define STATUS_ABIOS_INVALID_COMMAND cpu_to_le32(0xC0000113)
-#define STATUS_ABIOS_INVALID_LID cpu_to_le32(0xC0000114)
-#define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE cpu_to_le32(0xC0000115)
-#define STATUS_ABIOS_INVALID_SELECTOR cpu_to_le32(0xC0000116)
-#define STATUS_NO_LDT cpu_to_le32(0xC0000117)
-#define STATUS_INVALID_LDT_SIZE cpu_to_le32(0xC0000118)
-#define STATUS_INVALID_LDT_OFFSET cpu_to_le32(0xC0000119)
-#define STATUS_INVALID_LDT_DESCRIPTOR cpu_to_le32(0xC000011A)
-#define STATUS_INVALID_IMAGE_NE_FORMAT cpu_to_le32(0xC000011B)
-#define STATUS_RXACT_INVALID_STATE cpu_to_le32(0xC000011C)
-#define STATUS_RXACT_COMMIT_FAILURE cpu_to_le32(0xC000011D)
-#define STATUS_MAPPED_FILE_SIZE_ZERO cpu_to_le32(0xC000011E)
-#define STATUS_TOO_MANY_OPENED_FILES cpu_to_le32(0xC000011F)
-#define STATUS_CANCELLED cpu_to_le32(0xC0000120)
-#define STATUS_CANNOT_DELETE cpu_to_le32(0xC0000121)
-#define STATUS_INVALID_COMPUTER_NAME cpu_to_le32(0xC0000122)
-#define STATUS_FILE_DELETED cpu_to_le32(0xC0000123)
-#define STATUS_SPECIAL_ACCOUNT cpu_to_le32(0xC0000124)
-#define STATUS_SPECIAL_GROUP cpu_to_le32(0xC0000125)
-#define STATUS_SPECIAL_USER cpu_to_le32(0xC0000126)
-#define STATUS_MEMBERS_PRIMARY_GROUP cpu_to_le32(0xC0000127)
-#define STATUS_FILE_CLOSED cpu_to_le32(0xC0000128)
-#define STATUS_TOO_MANY_THREADS cpu_to_le32(0xC0000129)
-#define STATUS_THREAD_NOT_IN_PROCESS cpu_to_le32(0xC000012A)
-#define STATUS_TOKEN_ALREADY_IN_USE cpu_to_le32(0xC000012B)
-#define STATUS_PAGEFILE_QUOTA_EXCEEDED cpu_to_le32(0xC000012C)
-#define STATUS_COMMITMENT_LIMIT cpu_to_le32(0xC000012D)
-#define STATUS_INVALID_IMAGE_LE_FORMAT cpu_to_le32(0xC000012E)
-#define STATUS_INVALID_IMAGE_NOT_MZ cpu_to_le32(0xC000012F)
-#define STATUS_INVALID_IMAGE_PROTECT cpu_to_le32(0xC0000130)
-#define STATUS_INVALID_IMAGE_WIN_16 cpu_to_le32(0xC0000131)
-#define STATUS_LOGON_SERVER_CONFLICT cpu_to_le32(0xC0000132)
-#define STATUS_TIME_DIFFERENCE_AT_DC cpu_to_le32(0xC0000133)
-#define STATUS_SYNCHRONIZATION_REQUIRED cpu_to_le32(0xC0000134)
-#define STATUS_DLL_NOT_FOUND cpu_to_le32(0xC0000135)
-#define STATUS_OPEN_FAILED cpu_to_le32(0xC0000136)
-#define STATUS_IO_PRIVILEGE_FAILED cpu_to_le32(0xC0000137)
-#define STATUS_ORDINAL_NOT_FOUND cpu_to_le32(0xC0000138)
-#define STATUS_ENTRYPOINT_NOT_FOUND cpu_to_le32(0xC0000139)
-#define STATUS_CONTROL_C_EXIT cpu_to_le32(0xC000013A)
-#define STATUS_LOCAL_DISCONNECT cpu_to_le32(0xC000013B)
-#define STATUS_REMOTE_DISCONNECT cpu_to_le32(0xC000013C)
-#define STATUS_REMOTE_RESOURCES cpu_to_le32(0xC000013D)
-#define STATUS_LINK_FAILED cpu_to_le32(0xC000013E)
-#define STATUS_LINK_TIMEOUT cpu_to_le32(0xC000013F)
-#define STATUS_INVALID_CONNECTION cpu_to_le32(0xC0000140)
-#define STATUS_INVALID_ADDRESS cpu_to_le32(0xC0000141)
-#define STATUS_DLL_INIT_FAILED cpu_to_le32(0xC0000142)
-#define STATUS_MISSING_SYSTEMFILE cpu_to_le32(0xC0000143)
-#define STATUS_UNHANDLED_EXCEPTION cpu_to_le32(0xC0000144)
-#define STATUS_APP_INIT_FAILURE cpu_to_le32(0xC0000145)
-#define STATUS_PAGEFILE_CREATE_FAILED cpu_to_le32(0xC0000146)
-#define STATUS_NO_PAGEFILE cpu_to_le32(0xC0000147)
-#define STATUS_INVALID_LEVEL cpu_to_le32(0xC0000148)
-#define STATUS_WRONG_PASSWORD_CORE cpu_to_le32(0xC0000149)
-#define STATUS_ILLEGAL_FLOAT_CONTEXT cpu_to_le32(0xC000014A)
-#define STATUS_PIPE_BROKEN cpu_to_le32(0xC000014B)
-#define STATUS_REGISTRY_CORRUPT cpu_to_le32(0xC000014C)
-#define STATUS_REGISTRY_IO_FAILED cpu_to_le32(0xC000014D)
-#define STATUS_NO_EVENT_PAIR cpu_to_le32(0xC000014E)
-#define STATUS_UNRECOGNIZED_VOLUME cpu_to_le32(0xC000014F)
-#define STATUS_SERIAL_NO_DEVICE_INITED cpu_to_le32(0xC0000150)
-#define STATUS_NO_SUCH_ALIAS cpu_to_le32(0xC0000151)
-#define STATUS_MEMBER_NOT_IN_ALIAS cpu_to_le32(0xC0000152)
-#define STATUS_MEMBER_IN_ALIAS cpu_to_le32(0xC0000153)
-#define STATUS_ALIAS_EXISTS cpu_to_le32(0xC0000154)
-#define STATUS_LOGON_NOT_GRANTED cpu_to_le32(0xC0000155)
-#define STATUS_TOO_MANY_SECRETS cpu_to_le32(0xC0000156)
-#define STATUS_SECRET_TOO_LONG cpu_to_le32(0xC0000157)
-#define STATUS_INTERNAL_DB_ERROR cpu_to_le32(0xC0000158)
-#define STATUS_FULLSCREEN_MODE cpu_to_le32(0xC0000159)
-#define STATUS_TOO_MANY_CONTEXT_IDS cpu_to_le32(0xC000015A)
-#define STATUS_LOGON_TYPE_NOT_GRANTED cpu_to_le32(0xC000015B)
-#define STATUS_NOT_REGISTRY_FILE cpu_to_le32(0xC000015C)
-#define STATUS_NT_CROSS_ENCRYPTION_REQUIRED cpu_to_le32(0xC000015D)
-#define STATUS_DOMAIN_CTRLR_CONFIG_ERROR cpu_to_le32(0xC000015E)
-#define STATUS_FT_MISSING_MEMBER cpu_to_le32(0xC000015F)
-#define STATUS_ILL_FORMED_SERVICE_ENTRY cpu_to_le32(0xC0000160)
-#define STATUS_ILLEGAL_CHARACTER cpu_to_le32(0xC0000161)
-#define STATUS_UNMAPPABLE_CHARACTER cpu_to_le32(0xC0000162)
-#define STATUS_UNDEFINED_CHARACTER cpu_to_le32(0xC0000163)
-#define STATUS_FLOPPY_VOLUME cpu_to_le32(0xC0000164)
-#define STATUS_FLOPPY_ID_MARK_NOT_FOUND cpu_to_le32(0xC0000165)
-#define STATUS_FLOPPY_WRONG_CYLINDER cpu_to_le32(0xC0000166)
-#define STATUS_FLOPPY_UNKNOWN_ERROR cpu_to_le32(0xC0000167)
-#define STATUS_FLOPPY_BAD_REGISTERS cpu_to_le32(0xC0000168)
-#define STATUS_DISK_RECALIBRATE_FAILED cpu_to_le32(0xC0000169)
-#define STATUS_DISK_OPERATION_FAILED cpu_to_le32(0xC000016A)
-#define STATUS_DISK_RESET_FAILED cpu_to_le32(0xC000016B)
-#define STATUS_SHARED_IRQ_BUSY cpu_to_le32(0xC000016C)
-#define STATUS_FT_ORPHANING cpu_to_le32(0xC000016D)
-#define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT cpu_to_le32(0xC000016E)
-#define STATUS_PARTITION_FAILURE cpu_to_le32(0xC0000172)
-#define STATUS_INVALID_BLOCK_LENGTH cpu_to_le32(0xC0000173)
-#define STATUS_DEVICE_NOT_PARTITIONED cpu_to_le32(0xC0000174)
-#define STATUS_UNABLE_TO_LOCK_MEDIA cpu_to_le32(0xC0000175)
-#define STATUS_UNABLE_TO_UNLOAD_MEDIA cpu_to_le32(0xC0000176)
-#define STATUS_EOM_OVERFLOW cpu_to_le32(0xC0000177)
-#define STATUS_NO_MEDIA cpu_to_le32(0xC0000178)
-#define STATUS_NO_SUCH_MEMBER cpu_to_le32(0xC000017A)
-#define STATUS_INVALID_MEMBER cpu_to_le32(0xC000017B)
-#define STATUS_KEY_DELETED cpu_to_le32(0xC000017C)
-#define STATUS_NO_LOG_SPACE cpu_to_le32(0xC000017D)
-#define STATUS_TOO_MANY_SIDS cpu_to_le32(0xC000017E)
-#define STATUS_LM_CROSS_ENCRYPTION_REQUIRED cpu_to_le32(0xC000017F)
-#define STATUS_KEY_HAS_CHILDREN cpu_to_le32(0xC0000180)
-#define STATUS_CHILD_MUST_BE_VOLATILE cpu_to_le32(0xC0000181)
-#define STATUS_DEVICE_CONFIGURATION_ERROR cpu_to_le32(0xC0000182)
-#define STATUS_DRIVER_INTERNAL_ERROR cpu_to_le32(0xC0000183)
-#define STATUS_INVALID_DEVICE_STATE cpu_to_le32(0xC0000184)
-#define STATUS_IO_DEVICE_ERROR cpu_to_le32(0xC0000185)
-#define STATUS_DEVICE_PROTOCOL_ERROR cpu_to_le32(0xC0000186)
-#define STATUS_BACKUP_CONTROLLER cpu_to_le32(0xC0000187)
-#define STATUS_LOG_FILE_FULL cpu_to_le32(0xC0000188)
-#define STATUS_TOO_LATE cpu_to_le32(0xC0000189)
-#define STATUS_NO_TRUST_LSA_SECRET cpu_to_le32(0xC000018A)
-#define STATUS_NO_TRUST_SAM_ACCOUNT cpu_to_le32(0xC000018B)
-#define STATUS_TRUSTED_DOMAIN_FAILURE cpu_to_le32(0xC000018C)
-#define STATUS_TRUSTED_RELATIONSHIP_FAILURE cpu_to_le32(0xC000018D)
-#define STATUS_EVENTLOG_FILE_CORRUPT cpu_to_le32(0xC000018E)
-#define STATUS_EVENTLOG_CANT_START cpu_to_le32(0xC000018F)
-#define STATUS_TRUST_FAILURE cpu_to_le32(0xC0000190)
-#define STATUS_MUTANT_LIMIT_EXCEEDED cpu_to_le32(0xC0000191)
-#define STATUS_NETLOGON_NOT_STARTED cpu_to_le32(0xC0000192)
-#define STATUS_ACCOUNT_EXPIRED cpu_to_le32(0xC0000193)
-#define STATUS_POSSIBLE_DEADLOCK cpu_to_le32(0xC0000194)
-#define STATUS_NETWORK_CREDENTIAL_CONFLICT cpu_to_le32(0xC0000195)
-#define STATUS_REMOTE_SESSION_LIMIT cpu_to_le32(0xC0000196)
-#define STATUS_EVENTLOG_FILE_CHANGED cpu_to_le32(0xC0000197)
-#define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT cpu_to_le32(0xC0000198)
-#define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT cpu_to_le32(0xC0000199)
-#define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT cpu_to_le32(0xC000019A)
-#define STATUS_DOMAIN_TRUST_INCONSISTENT cpu_to_le32(0xC000019B)
-#define STATUS_FS_DRIVER_REQUIRED cpu_to_le32(0xC000019C)
-#define STATUS_IMAGE_ALREADY_LOADED_AS_DLL cpu_to_le32(0xC000019D)
-#define STATUS_NETWORK_OPEN_RESTRICTION cpu_to_le32(0xC0000201)
-#define STATUS_NO_USER_SESSION_KEY cpu_to_le32(0xC0000202)
-#define STATUS_USER_SESSION_DELETED cpu_to_le32(0xC0000203)
-#define STATUS_RESOURCE_LANG_NOT_FOUND cpu_to_le32(0xC0000204)
-#define STATUS_INSUFF_SERVER_RESOURCES cpu_to_le32(0xC0000205)
-#define STATUS_INVALID_BUFFER_SIZE cpu_to_le32(0xC0000206)
-#define STATUS_INVALID_ADDRESS_COMPONENT cpu_to_le32(0xC0000207)
-#define STATUS_INVALID_ADDRESS_WILDCARD cpu_to_le32(0xC0000208)
-#define STATUS_TOO_MANY_ADDRESSES cpu_to_le32(0xC0000209)
-#define STATUS_ADDRESS_ALREADY_EXISTS cpu_to_le32(0xC000020A)
-#define STATUS_ADDRESS_CLOSED cpu_to_le32(0xC000020B)
-#define STATUS_CONNECTION_DISCONNECTED cpu_to_le32(0xC000020C)
-#define STATUS_CONNECTION_RESET cpu_to_le32(0xC000020D)
-#define STATUS_TOO_MANY_NODES cpu_to_le32(0xC000020E)
-#define STATUS_TRANSACTION_ABORTED cpu_to_le32(0xC000020F)
-#define STATUS_TRANSACTION_TIMED_OUT cpu_to_le32(0xC0000210)
-#define STATUS_TRANSACTION_NO_RELEASE cpu_to_le32(0xC0000211)
-#define STATUS_TRANSACTION_NO_MATCH cpu_to_le32(0xC0000212)
-#define STATUS_TRANSACTION_RESPONDED cpu_to_le32(0xC0000213)
-#define STATUS_TRANSACTION_INVALID_ID cpu_to_le32(0xC0000214)
-#define STATUS_TRANSACTION_INVALID_TYPE cpu_to_le32(0xC0000215)
-#define STATUS_NOT_SERVER_SESSION cpu_to_le32(0xC0000216)
-#define STATUS_NOT_CLIENT_SESSION cpu_to_le32(0xC0000217)
-#define STATUS_CANNOT_LOAD_REGISTRY_FILE cpu_to_le32(0xC0000218)
-#define STATUS_DEBUG_ATTACH_FAILED cpu_to_le32(0xC0000219)
-#define STATUS_SYSTEM_PROCESS_TERMINATED cpu_to_le32(0xC000021A)
-#define STATUS_DATA_NOT_ACCEPTED cpu_to_le32(0xC000021B)
-#define STATUS_NO_BROWSER_SERVERS_FOUND cpu_to_le32(0xC000021C)
-#define STATUS_VDM_HARD_ERROR cpu_to_le32(0xC000021D)
-#define STATUS_DRIVER_CANCEL_TIMEOUT cpu_to_le32(0xC000021E)
-#define STATUS_REPLY_MESSAGE_MISMATCH cpu_to_le32(0xC000021F)
-#define STATUS_MAPPED_ALIGNMENT cpu_to_le32(0xC0000220)
-#define STATUS_IMAGE_CHECKSUM_MISMATCH cpu_to_le32(0xC0000221)
-#define STATUS_LOST_WRITEBEHIND_DATA cpu_to_le32(0xC0000222)
-#define STATUS_CLIENT_SERVER_PARAMETERS_INVALID cpu_to_le32(0xC0000223)
-#define STATUS_PASSWORD_MUST_CHANGE cpu_to_le32(0xC0000224)
-#define STATUS_NOT_FOUND cpu_to_le32(0xC0000225)
-#define STATUS_NOT_TINY_STREAM cpu_to_le32(0xC0000226)
-#define STATUS_RECOVERY_FAILURE cpu_to_le32(0xC0000227)
-#define STATUS_STACK_OVERFLOW_READ cpu_to_le32(0xC0000228)
-#define STATUS_FAIL_CHECK cpu_to_le32(0xC0000229)
-#define STATUS_DUPLICATE_OBJECTID cpu_to_le32(0xC000022A)
-#define STATUS_OBJECTID_EXISTS cpu_to_le32(0xC000022B)
-#define STATUS_CONVERT_TO_LARGE cpu_to_le32(0xC000022C)
-#define STATUS_RETRY cpu_to_le32(0xC000022D)
-#define STATUS_FOUND_OUT_OF_SCOPE cpu_to_le32(0xC000022E)
-#define STATUS_ALLOCATE_BUCKET cpu_to_le32(0xC000022F)
-#define STATUS_PROPSET_NOT_FOUND cpu_to_le32(0xC0000230)
-#define STATUS_MARSHALL_OVERFLOW cpu_to_le32(0xC0000231)
-#define STATUS_INVALID_VARIANT cpu_to_le32(0xC0000232)
-#define STATUS_DOMAIN_CONTROLLER_NOT_FOUND cpu_to_le32(0xC0000233)
-#define STATUS_ACCOUNT_LOCKED_OUT cpu_to_le32(0xC0000234)
-#define STATUS_HANDLE_NOT_CLOSABLE cpu_to_le32(0xC0000235)
-#define STATUS_CONNECTION_REFUSED cpu_to_le32(0xC0000236)
-#define STATUS_GRACEFUL_DISCONNECT cpu_to_le32(0xC0000237)
-#define STATUS_ADDRESS_ALREADY_ASSOCIATED cpu_to_le32(0xC0000238)
-#define STATUS_ADDRESS_NOT_ASSOCIATED cpu_to_le32(0xC0000239)
-#define STATUS_CONNECTION_INVALID cpu_to_le32(0xC000023A)
-#define STATUS_CONNECTION_ACTIVE cpu_to_le32(0xC000023B)
-#define STATUS_NETWORK_UNREACHABLE cpu_to_le32(0xC000023C)
-#define STATUS_HOST_UNREACHABLE cpu_to_le32(0xC000023D)
-#define STATUS_PROTOCOL_UNREACHABLE cpu_to_le32(0xC000023E)
-#define STATUS_PORT_UNREACHABLE cpu_to_le32(0xC000023F)
-#define STATUS_REQUEST_ABORTED cpu_to_le32(0xC0000240)
-#define STATUS_CONNECTION_ABORTED cpu_to_le32(0xC0000241)
-#define STATUS_BAD_COMPRESSION_BUFFER cpu_to_le32(0xC0000242)
-#define STATUS_USER_MAPPED_FILE cpu_to_le32(0xC0000243)
-#define STATUS_AUDIT_FAILED cpu_to_le32(0xC0000244)
-#define STATUS_TIMER_RESOLUTION_NOT_SET cpu_to_le32(0xC0000245)
-#define STATUS_CONNECTION_COUNT_LIMIT cpu_to_le32(0xC0000246)
-#define STATUS_LOGIN_TIME_RESTRICTION cpu_to_le32(0xC0000247)
-#define STATUS_LOGIN_WKSTA_RESTRICTION cpu_to_le32(0xC0000248)
-#define STATUS_IMAGE_MP_UP_MISMATCH cpu_to_le32(0xC0000249)
-#define STATUS_INSUFFICIENT_LOGON_INFO cpu_to_le32(0xC0000250)
-#define STATUS_BAD_DLL_ENTRYPOINT cpu_to_le32(0xC0000251)
-#define STATUS_BAD_SERVICE_ENTRYPOINT cpu_to_le32(0xC0000252)
-#define STATUS_LPC_REPLY_LOST cpu_to_le32(0xC0000253)
-#define STATUS_IP_ADDRESS_CONFLICT1 cpu_to_le32(0xC0000254)
-#define STATUS_IP_ADDRESS_CONFLICT2 cpu_to_le32(0xC0000255)
-#define STATUS_REGISTRY_QUOTA_LIMIT cpu_to_le32(0xC0000256)
-#define STATUS_PATH_NOT_COVERED cpu_to_le32(0xC0000257)
-#define STATUS_NO_CALLBACK_ACTIVE cpu_to_le32(0xC0000258)
-#define STATUS_LICENSE_QUOTA_EXCEEDED cpu_to_le32(0xC0000259)
-#define STATUS_PWD_TOO_SHORT cpu_to_le32(0xC000025A)
-#define STATUS_PWD_TOO_RECENT cpu_to_le32(0xC000025B)
-#define STATUS_PWD_HISTORY_CONFLICT cpu_to_le32(0xC000025C)
-#define STATUS_PLUGPLAY_NO_DEVICE cpu_to_le32(0xC000025E)
-#define STATUS_UNSUPPORTED_COMPRESSION cpu_to_le32(0xC000025F)
-#define STATUS_INVALID_HW_PROFILE cpu_to_le32(0xC0000260)
-#define STATUS_INVALID_PLUGPLAY_DEVICE_PATH cpu_to_le32(0xC0000261)
-#define STATUS_DRIVER_ORDINAL_NOT_FOUND cpu_to_le32(0xC0000262)
-#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND cpu_to_le32(0xC0000263)
-#define STATUS_RESOURCE_NOT_OWNED cpu_to_le32(0xC0000264)
-#define STATUS_TOO_MANY_LINKS cpu_to_le32(0xC0000265)
-#define STATUS_QUOTA_LIST_INCONSISTENT cpu_to_le32(0xC0000266)
-#define STATUS_FILE_IS_OFFLINE cpu_to_le32(0xC0000267)
-#define STATUS_EVALUATION_EXPIRATION cpu_to_le32(0xC0000268)
-#define STATUS_ILLEGAL_DLL_RELOCATION cpu_to_le32(0xC0000269)
-#define STATUS_LICENSE_VIOLATION cpu_to_le32(0xC000026A)
-#define STATUS_DLL_INIT_FAILED_LOGOFF cpu_to_le32(0xC000026B)
-#define STATUS_DRIVER_UNABLE_TO_LOAD cpu_to_le32(0xC000026C)
-#define STATUS_DFS_UNAVAILABLE cpu_to_le32(0xC000026D)
-#define STATUS_VOLUME_DISMOUNTED cpu_to_le32(0xC000026E)
-#define STATUS_WX86_INTERNAL_ERROR cpu_to_le32(0xC000026F)
-#define STATUS_WX86_FLOAT_STACK_CHECK cpu_to_le32(0xC0000270)
-#define STATUS_VALIDATE_CONTINUE cpu_to_le32(0xC0000271)
-#define STATUS_NO_MATCH cpu_to_le32(0xC0000272)
-#define STATUS_NO_MORE_MATCHES cpu_to_le32(0xC0000273)
-#define STATUS_NOT_A_REPARSE_POINT cpu_to_le32(0xC0000275)
-#define STATUS_IO_REPARSE_TAG_INVALID cpu_to_le32(0xC0000276)
-#define STATUS_IO_REPARSE_TAG_MISMATCH cpu_to_le32(0xC0000277)
-#define STATUS_IO_REPARSE_DATA_INVALID cpu_to_le32(0xC0000278)
-#define STATUS_IO_REPARSE_TAG_NOT_HANDLED cpu_to_le32(0xC0000279)
-#define STATUS_REPARSE_POINT_NOT_RESOLVED cpu_to_le32(0xC0000280)
-#define STATUS_DIRECTORY_IS_A_REPARSE_POINT cpu_to_le32(0xC0000281)
-#define STATUS_RANGE_LIST_CONFLICT cpu_to_le32(0xC0000282)
-#define STATUS_SOURCE_ELEMENT_EMPTY cpu_to_le32(0xC0000283)
-#define STATUS_DESTINATION_ELEMENT_FULL cpu_to_le32(0xC0000284)
-#define STATUS_ILLEGAL_ELEMENT_ADDRESS cpu_to_le32(0xC0000285)
-#define STATUS_MAGAZINE_NOT_PRESENT cpu_to_le32(0xC0000286)
-#define STATUS_REINITIALIZATION_NEEDED cpu_to_le32(0xC0000287)
-#define STATUS_ENCRYPTION_FAILED cpu_to_le32(0xC000028A)
-#define STATUS_DECRYPTION_FAILED cpu_to_le32(0xC000028B)
-#define STATUS_RANGE_NOT_FOUND cpu_to_le32(0xC000028C)
-#define STATUS_NO_RECOVERY_POLICY cpu_to_le32(0xC000028D)
-#define STATUS_NO_EFS cpu_to_le32(0xC000028E)
-#define STATUS_WRONG_EFS cpu_to_le32(0xC000028F)
-#define STATUS_NO_USER_KEYS cpu_to_le32(0xC0000290)
-#define STATUS_FILE_NOT_ENCRYPTED cpu_to_le32(0xC0000291)
-#define STATUS_NOT_EXPORT_FORMAT cpu_to_le32(0xC0000292)
-#define STATUS_FILE_ENCRYPTED cpu_to_le32(0xC0000293)
-#define STATUS_WMI_GUID_NOT_FOUND cpu_to_le32(0xC0000295)
-#define STATUS_WMI_INSTANCE_NOT_FOUND cpu_to_le32(0xC0000296)
-#define STATUS_WMI_ITEMID_NOT_FOUND cpu_to_le32(0xC0000297)
-#define STATUS_WMI_TRY_AGAIN cpu_to_le32(0xC0000298)
-#define STATUS_SHARED_POLICY cpu_to_le32(0xC0000299)
-#define STATUS_POLICY_OBJECT_NOT_FOUND cpu_to_le32(0xC000029A)
-#define STATUS_POLICY_ONLY_IN_DS cpu_to_le32(0xC000029B)
-#define STATUS_VOLUME_NOT_UPGRADED cpu_to_le32(0xC000029C)
-#define STATUS_REMOTE_STORAGE_NOT_ACTIVE cpu_to_le32(0xC000029D)
-#define STATUS_REMOTE_STORAGE_MEDIA_ERROR cpu_to_le32(0xC000029E)
-#define STATUS_NO_TRACKING_SERVICE cpu_to_le32(0xC000029F)
-#define STATUS_SERVER_SID_MISMATCH cpu_to_le32(0xC00002A0)
-#define STATUS_DS_NO_ATTRIBUTE_OR_VALUE cpu_to_le32(0xC00002A1)
-#define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX cpu_to_le32(0xC00002A2)
-#define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED cpu_to_le32(0xC00002A3)
-#define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS cpu_to_le32(0xC00002A4)
-#define STATUS_DS_BUSY cpu_to_le32(0xC00002A5)
-#define STATUS_DS_UNAVAILABLE cpu_to_le32(0xC00002A6)
-#define STATUS_DS_NO_RIDS_ALLOCATED cpu_to_le32(0xC00002A7)
-#define STATUS_DS_NO_MORE_RIDS cpu_to_le32(0xC00002A8)
-#define STATUS_DS_INCORRECT_ROLE_OWNER cpu_to_le32(0xC00002A9)
-#define STATUS_DS_RIDMGR_INIT_ERROR cpu_to_le32(0xC00002AA)
-#define STATUS_DS_OBJ_CLASS_VIOLATION cpu_to_le32(0xC00002AB)
-#define STATUS_DS_CANT_ON_NON_LEAF cpu_to_le32(0xC00002AC)
-#define STATUS_DS_CANT_ON_RDN cpu_to_le32(0xC00002AD)
-#define STATUS_DS_CANT_MOD_OBJ_CLASS cpu_to_le32(0xC00002AE)
-#define STATUS_DS_CROSS_DOM_MOVE_FAILED cpu_to_le32(0xC00002AF)
-#define STATUS_DS_GC_NOT_AVAILABLE cpu_to_le32(0xC00002B0)
-#define STATUS_DIRECTORY_SERVICE_REQUIRED cpu_to_le32(0xC00002B1)
-#define STATUS_REPARSE_ATTRIBUTE_CONFLICT cpu_to_le32(0xC00002B2)
-#define STATUS_CANT_ENABLE_DENY_ONLY cpu_to_le32(0xC00002B3)
-#define STATUS_FLOAT_MULTIPLE_FAULTS cpu_to_le32(0xC00002B4)
-#define STATUS_FLOAT_MULTIPLE_TRAPS cpu_to_le32(0xC00002B5)
-#define STATUS_DEVICE_REMOVED cpu_to_le32(0xC00002B6)
-#define STATUS_JOURNAL_DELETE_IN_PROGRESS cpu_to_le32(0xC00002B7)
-#define STATUS_JOURNAL_NOT_ACTIVE cpu_to_le32(0xC00002B8)
-#define STATUS_NOINTERFACE cpu_to_le32(0xC00002B9)
-#define STATUS_DS_ADMIN_LIMIT_EXCEEDED cpu_to_le32(0xC00002C1)
-#define STATUS_DRIVER_FAILED_SLEEP cpu_to_le32(0xC00002C2)
-#define STATUS_MUTUAL_AUTHENTICATION_FAILED cpu_to_le32(0xC00002C3)
-#define STATUS_CORRUPT_SYSTEM_FILE cpu_to_le32(0xC00002C4)
-#define STATUS_DATATYPE_MISALIGNMENT_ERROR cpu_to_le32(0xC00002C5)
-#define STATUS_WMI_READ_ONLY cpu_to_le32(0xC00002C6)
-#define STATUS_WMI_SET_FAILURE cpu_to_le32(0xC00002C7)
-#define STATUS_COMMITMENT_MINIMUM cpu_to_le32(0xC00002C8)
-#define STATUS_REG_NAT_CONSUMPTION cpu_to_le32(0xC00002C9)
-#define STATUS_TRANSPORT_FULL cpu_to_le32(0xC00002CA)
-#define STATUS_DS_SAM_INIT_FAILURE cpu_to_le32(0xC00002CB)
-#define STATUS_ONLY_IF_CONNECTED cpu_to_le32(0xC00002CC)
-#define STATUS_DS_SENSITIVE_GROUP_VIOLATION cpu_to_le32(0xC00002CD)
-#define STATUS_PNP_RESTART_ENUMERATION cpu_to_le32(0xC00002CE)
-#define STATUS_JOURNAL_ENTRY_DELETED cpu_to_le32(0xC00002CF)
-#define STATUS_DS_CANT_MOD_PRIMARYGROUPID cpu_to_le32(0xC00002D0)
-#define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE cpu_to_le32(0xC00002D1)
-#define STATUS_PNP_REBOOT_REQUIRED cpu_to_le32(0xC00002D2)
-#define STATUS_POWER_STATE_INVALID cpu_to_le32(0xC00002D3)
-#define STATUS_DS_INVALID_GROUP_TYPE cpu_to_le32(0xC00002D4)
-#define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN cpu_to_le32(0xC00002D5)
-#define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN cpu_to_le32(0xC00002D6)
-#define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER cpu_to_le32(0xC00002D7)
-#define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER cpu_to_le32(0xC00002D8)
-#define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER cpu_to_le32(0xC00002D9)
-#define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER cpu_to_le32(0xC00002DA)
-#define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER cpu_to_le32(0xC00002DB)
-#define STATUS_DS_HAVE_PRIMARY_MEMBERS cpu_to_le32(0xC00002DC)
-#define STATUS_WMI_NOT_SUPPORTED cpu_to_le32(0xC00002DD)
-#define STATUS_INSUFFICIENT_POWER cpu_to_le32(0xC00002DE)
-#define STATUS_SAM_NEED_BOOTKEY_PASSWORD cpu_to_le32(0xC00002DF)
-#define STATUS_SAM_NEED_BOOTKEY_FLOPPY cpu_to_le32(0xC00002E0)
-#define STATUS_DS_CANT_START cpu_to_le32(0xC00002E1)
-#define STATUS_DS_INIT_FAILURE cpu_to_le32(0xC00002E2)
-#define STATUS_SAM_INIT_FAILURE cpu_to_le32(0xC00002E3)
-#define STATUS_DS_GC_REQUIRED cpu_to_le32(0xC00002E4)
-#define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY cpu_to_le32(0xC00002E5)
-#define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS cpu_to_le32(0xC00002E6)
-#define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED cpu_to_le32(0xC00002E7)
-#define STATUS_MULTIPLE_FAULT_VIOLATION cpu_to_le32(0xC00002E8)
-#define STATUS_CURRENT_DOMAIN_NOT_ALLOWED cpu_to_le32(0xC00002E9)
-#define STATUS_CANNOT_MAKE cpu_to_le32(0xC00002EA)
-#define STATUS_SYSTEM_SHUTDOWN cpu_to_le32(0xC00002EB)
-#define STATUS_DS_INIT_FAILURE_CONSOLE cpu_to_le32(0xC00002EC)
-#define STATUS_DS_SAM_INIT_FAILURE_CONSOLE cpu_to_le32(0xC00002ED)
-#define STATUS_UNFINISHED_CONTEXT_DELETED cpu_to_le32(0xC00002EE)
-#define STATUS_NO_TGT_REPLY cpu_to_le32(0xC00002EF)
-#define STATUS_OBJECTID_NOT_FOUND cpu_to_le32(0xC00002F0)
-#define STATUS_NO_IP_ADDRESSES cpu_to_le32(0xC00002F1)
-#define STATUS_WRONG_CREDENTIAL_HANDLE cpu_to_le32(0xC00002F2)
-#define STATUS_CRYPTO_SYSTEM_INVALID cpu_to_le32(0xC00002F3)
-#define STATUS_MAX_REFERRALS_EXCEEDED cpu_to_le32(0xC00002F4)
-#define STATUS_MUST_BE_KDC cpu_to_le32(0xC00002F5)
-#define STATUS_STRONG_CRYPTO_NOT_SUPPORTED cpu_to_le32(0xC00002F6)
-#define STATUS_TOO_MANY_PRINCIPALS cpu_to_le32(0xC00002F7)
-#define STATUS_NO_PA_DATA cpu_to_le32(0xC00002F8)
-#define STATUS_PKINIT_NAME_MISMATCH cpu_to_le32(0xC00002F9)
-#define STATUS_SMARTCARD_LOGON_REQUIRED cpu_to_le32(0xC00002FA)
-#define STATUS_KDC_INVALID_REQUEST cpu_to_le32(0xC00002FB)
-#define STATUS_KDC_UNABLE_TO_REFER cpu_to_le32(0xC00002FC)
-#define STATUS_KDC_UNKNOWN_ETYPE cpu_to_le32(0xC00002FD)
-#define STATUS_SHUTDOWN_IN_PROGRESS cpu_to_le32(0xC00002FE)
-#define STATUS_SERVER_SHUTDOWN_IN_PROGRESS cpu_to_le32(0xC00002FF)
-#define STATUS_NOT_SUPPORTED_ON_SBS cpu_to_le32(0xC0000300)
-#define STATUS_WMI_GUID_DISCONNECTED cpu_to_le32(0xC0000301)
-#define STATUS_WMI_ALREADY_DISABLED cpu_to_le32(0xC0000302)
-#define STATUS_WMI_ALREADY_ENABLED cpu_to_le32(0xC0000303)
-#define STATUS_MFT_TOO_FRAGMENTED cpu_to_le32(0xC0000304)
-#define STATUS_COPY_PROTECTION_FAILURE cpu_to_le32(0xC0000305)
-#define STATUS_CSS_AUTHENTICATION_FAILURE cpu_to_le32(0xC0000306)
-#define STATUS_CSS_KEY_NOT_PRESENT cpu_to_le32(0xC0000307)
-#define STATUS_CSS_KEY_NOT_ESTABLISHED cpu_to_le32(0xC0000308)
-#define STATUS_CSS_SCRAMBLED_SECTOR cpu_to_le32(0xC0000309)
-#define STATUS_CSS_REGION_MISMATCH cpu_to_le32(0xC000030A)
-#define STATUS_CSS_RESETS_EXHAUSTED cpu_to_le32(0xC000030B)
-#define STATUS_PKINIT_FAILURE cpu_to_le32(0xC0000320)
-#define STATUS_SMARTCARD_SUBSYSTEM_FAILURE cpu_to_le32(0xC0000321)
-#define STATUS_NO_KERB_KEY cpu_to_le32(0xC0000322)
-#define STATUS_HOST_DOWN cpu_to_le32(0xC0000350)
-#define STATUS_UNSUPPORTED_PREAUTH cpu_to_le32(0xC0000351)
-#define STATUS_EFS_ALG_BLOB_TOO_BIG cpu_to_le32(0xC0000352)
-#define STATUS_PORT_NOT_SET cpu_to_le32(0xC0000353)
-#define STATUS_DEBUGGER_INACTIVE cpu_to_le32(0xC0000354)
-#define STATUS_DS_VERSION_CHECK_FAILURE cpu_to_le32(0xC0000355)
-#define STATUS_AUDITING_DISABLED cpu_to_le32(0xC0000356)
-#define STATUS_PRENT4_MACHINE_ACCOUNT cpu_to_le32(0xC0000357)
-#define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER cpu_to_le32(0xC0000358)
-#define STATUS_INVALID_IMAGE_WIN_32 cpu_to_le32(0xC0000359)
-#define STATUS_INVALID_IMAGE_WIN_64 cpu_to_le32(0xC000035A)
-#define STATUS_BAD_BINDINGS cpu_to_le32(0xC000035B)
-#define STATUS_NETWORK_SESSION_EXPIRED cpu_to_le32(0xC000035C)
-#define STATUS_APPHELP_BLOCK cpu_to_le32(0xC000035D)
-#define STATUS_ALL_SIDS_FILTERED cpu_to_le32(0xC000035E)
-#define STATUS_NOT_SAFE_MODE_DRIVER cpu_to_le32(0xC000035F)
-#define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT cpu_to_le32(0xC0000361)
-#define STATUS_ACCESS_DISABLED_BY_POLICY_PATH cpu_to_le32(0xC0000362)
-#define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER cpu_to_le32(0xC0000363)
-#define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER cpu_to_le32(0xC0000364)
-#define STATUS_FAILED_DRIVER_ENTRY cpu_to_le32(0xC0000365)
-#define STATUS_DEVICE_ENUMERATION_ERROR cpu_to_le32(0xC0000366)
-#define STATUS_MOUNT_POINT_NOT_RESOLVED cpu_to_le32(0xC0000368)
-#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER cpu_to_le32(0xC0000369)
-#define STATUS_MCA_OCCURED cpu_to_le32(0xC000036A)
-#define STATUS_DRIVER_BLOCKED_CRITICAL cpu_to_le32(0xC000036B)
-#define STATUS_DRIVER_BLOCKED cpu_to_le32(0xC000036C)
-#define STATUS_DRIVER_DATABASE_ERROR cpu_to_le32(0xC000036D)
-#define STATUS_SYSTEM_HIVE_TOO_LARGE cpu_to_le32(0xC000036E)
-#define STATUS_INVALID_IMPORT_OF_NON_DLL cpu_to_le32(0xC000036F)
-#define STATUS_NO_SECRETS cpu_to_le32(0xC0000371)
-#define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY cpu_to_le32(0xC0000372)
-#define STATUS_FAILED_STACK_SWITCH cpu_to_le32(0xC0000373)
-#define STATUS_HEAP_CORRUPTION cpu_to_le32(0xC0000374)
-#define STATUS_SMARTCARD_WRONG_PIN cpu_to_le32(0xC0000380)
-#define STATUS_SMARTCARD_CARD_BLOCKED cpu_to_le32(0xC0000381)
-#define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED cpu_to_le32(0xC0000382)
-#define STATUS_SMARTCARD_NO_CARD cpu_to_le32(0xC0000383)
-#define STATUS_SMARTCARD_NO_KEY_CONTAINER cpu_to_le32(0xC0000384)
-#define STATUS_SMARTCARD_NO_CERTIFICATE cpu_to_le32(0xC0000385)
-#define STATUS_SMARTCARD_NO_KEYSET cpu_to_le32(0xC0000386)
-#define STATUS_SMARTCARD_IO_ERROR cpu_to_le32(0xC0000387)
-#define STATUS_DOWNGRADE_DETECTED cpu_to_le32(0xC0000388)
-#define STATUS_SMARTCARD_CERT_REVOKED cpu_to_le32(0xC0000389)
-#define STATUS_ISSUING_CA_UNTRUSTED cpu_to_le32(0xC000038A)
-#define STATUS_REVOCATION_OFFLINE_C cpu_to_le32(0xC000038B)
-#define STATUS_PKINIT_CLIENT_FAILURE cpu_to_le32(0xC000038C)
-#define STATUS_SMARTCARD_CERT_EXPIRED cpu_to_le32(0xC000038D)
-#define STATUS_DRIVER_FAILED_PRIOR_UNLOAD cpu_to_le32(0xC000038E)
-#define STATUS_SMARTCARD_SILENT_CONTEXT cpu_to_le32(0xC000038F)
-#define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000401)
-#define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000402)
-#define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000403)
-#define STATUS_DS_NAME_NOT_UNIQUE cpu_to_le32(0xC0000404)
-#define STATUS_DS_DUPLICATE_ID_FOUND cpu_to_le32(0xC0000405)
-#define STATUS_DS_GROUP_CONVERSION_ERROR cpu_to_le32(0xC0000406)
-#define STATUS_VOLSNAP_PREPARE_HIBERNATE cpu_to_le32(0xC0000407)
-#define STATUS_USER2USER_REQUIRED cpu_to_le32(0xC0000408)
-#define STATUS_STACK_BUFFER_OVERRUN cpu_to_le32(0xC0000409)
-#define STATUS_NO_S4U_PROT_SUPPORT cpu_to_le32(0xC000040A)
-#define STATUS_CROSSREALM_DELEGATION_FAILURE cpu_to_le32(0xC000040B)
-#define STATUS_REVOCATION_OFFLINE_KDC cpu_to_le32(0xC000040C)
-#define STATUS_ISSUING_CA_UNTRUSTED_KDC cpu_to_le32(0xC000040D)
-#define STATUS_KDC_CERT_EXPIRED cpu_to_le32(0xC000040E)
-#define STATUS_KDC_CERT_REVOKED cpu_to_le32(0xC000040F)
-#define STATUS_PARAMETER_QUOTA_EXCEEDED cpu_to_le32(0xC0000410)
-#define STATUS_HIBERNATION_FAILURE cpu_to_le32(0xC0000411)
-#define STATUS_DELAY_LOAD_FAILED cpu_to_le32(0xC0000412)
-#define STATUS_AUTHENTICATION_FIREWALL_FAILED cpu_to_le32(0xC0000413)
-#define STATUS_VDM_DISALLOWED cpu_to_le32(0xC0000414)
-#define STATUS_HUNG_DISPLAY_DRIVER_THREAD cpu_to_le32(0xC0000415)
-#define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE cpu_to_le32(0xC0000416)
-#define STATUS_INVALID_CRUNTIME_PARAMETER cpu_to_le32(0xC0000417)
-#define STATUS_NTLM_BLOCKED cpu_to_le32(0xC0000418)
-#define STATUS_ASSERTION_FAILURE cpu_to_le32(0xC0000420)
-#define STATUS_VERIFIER_STOP cpu_to_le32(0xC0000421)
-#define STATUS_CALLBACK_POP_STACK cpu_to_le32(0xC0000423)
-#define STATUS_INCOMPATIBLE_DRIVER_BLOCKED cpu_to_le32(0xC0000424)
-#define STATUS_HIVE_UNLOADED cpu_to_le32(0xC0000425)
-#define STATUS_COMPRESSION_DISABLED cpu_to_le32(0xC0000426)
-#define STATUS_FILE_SYSTEM_LIMITATION cpu_to_le32(0xC0000427)
-#define STATUS_INVALID_IMAGE_HASH cpu_to_le32(0xC0000428)
-#define STATUS_NOT_CAPABLE cpu_to_le32(0xC0000429)
-#define STATUS_REQUEST_OUT_OF_SEQUENCE cpu_to_le32(0xC000042A)
-#define STATUS_IMPLEMENTATION_LIMIT cpu_to_le32(0xC000042B)
-#define STATUS_ELEVATION_REQUIRED cpu_to_le32(0xC000042C)
-#define STATUS_BEYOND_VDL cpu_to_le32(0xC0000432)
-#define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS cpu_to_le32(0xC0000433)
-#define STATUS_PTE_CHANGED cpu_to_le32(0xC0000434)
-#define STATUS_PURGE_FAILED cpu_to_le32(0xC0000435)
-#define STATUS_CRED_REQUIRES_CONFIRMATION cpu_to_le32(0xC0000440)
-#define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE cpu_to_le32(0xC0000441)
-#define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER cpu_to_le32(0xC0000442)
-#define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE cpu_to_le32(0xC0000443)
-#define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE cpu_to_le32(0xC0000444)
-#define STATUS_CS_ENCRYPTION_FILE_NOT_CSE cpu_to_le32(0xC0000445)
-#define STATUS_INVALID_LABEL cpu_to_le32(0xC0000446)
-#define STATUS_DRIVER_PROCESS_TERMINATED cpu_to_le32(0xC0000450)
-#define STATUS_AMBIGUOUS_SYSTEM_DEVICE cpu_to_le32(0xC0000451)
-#define STATUS_SYSTEM_DEVICE_NOT_FOUND cpu_to_le32(0xC0000452)
-#define STATUS_RESTART_BOOT_APPLICATION cpu_to_le32(0xC0000453)
-#define STATUS_INVALID_TASK_NAME cpu_to_le32(0xC0000500)
-#define STATUS_INVALID_TASK_INDEX cpu_to_le32(0xC0000501)
-#define STATUS_THREAD_ALREADY_IN_TASK cpu_to_le32(0xC0000502)
-#define STATUS_CALLBACK_BYPASS cpu_to_le32(0xC0000503)
-#define STATUS_PORT_CLOSED cpu_to_le32(0xC0000700)
-#define STATUS_MESSAGE_LOST cpu_to_le32(0xC0000701)
-#define STATUS_INVALID_MESSAGE cpu_to_le32(0xC0000702)
-#define STATUS_REQUEST_CANCELED cpu_to_le32(0xC0000703)
-#define STATUS_RECURSIVE_DISPATCH cpu_to_le32(0xC0000704)
-#define STATUS_LPC_RECEIVE_BUFFER_EXPECTED cpu_to_le32(0xC0000705)
-#define STATUS_LPC_INVALID_CONNECTION_USAGE cpu_to_le32(0xC0000706)
-#define STATUS_LPC_REQUESTS_NOT_ALLOWED cpu_to_le32(0xC0000707)
-#define STATUS_RESOURCE_IN_USE cpu_to_le32(0xC0000708)
-#define STATUS_HARDWARE_MEMORY_ERROR cpu_to_le32(0xC0000709)
-#define STATUS_THREADPOOL_HANDLE_EXCEPTION cpu_to_le32(0xC000070A)
-#define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED cpu_to_le32(0xC000070B)
-#define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED cpu_to_le32(0xC000070C)
-#define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED cpu_to_le32(0xC000070D)
-#define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED cpu_to_le32(0xC000070E)
-#define STATUS_THREADPOOL_RELEASED_DURING_OPERATION cpu_to_le32(0xC000070F)
-#define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING cpu_to_le32(0xC0000710)
-#define STATUS_APC_RETURNED_WHILE_IMPERSONATING cpu_to_le32(0xC0000711)
-#define STATUS_PROCESS_IS_PROTECTED cpu_to_le32(0xC0000712)
-#define STATUS_MCA_EXCEPTION cpu_to_le32(0xC0000713)
-#define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE cpu_to_le32(0xC0000714)
-#define STATUS_SYMLINK_CLASS_DISABLED cpu_to_le32(0xC0000715)
-#define STATUS_INVALID_IDN_NORMALIZATION cpu_to_le32(0xC0000716)
-#define STATUS_NO_UNICODE_TRANSLATION cpu_to_le32(0xC0000717)
-#define STATUS_ALREADY_REGISTERED cpu_to_le32(0xC0000718)
-#define STATUS_CONTEXT_MISMATCH cpu_to_le32(0xC0000719)
-#define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST cpu_to_le32(0xC000071A)
-#define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY cpu_to_le32(0xC000071B)
-#define STATUS_INVALID_THREAD cpu_to_le32(0xC000071C)
-#define STATUS_CALLBACK_RETURNED_TRANSACTION cpu_to_le32(0xC000071D)
-#define STATUS_CALLBACK_RETURNED_LDR_LOCK cpu_to_le32(0xC000071E)
-#define STATUS_CALLBACK_RETURNED_LANG cpu_to_le32(0xC000071F)
-#define STATUS_CALLBACK_RETURNED_PRI_BACK cpu_to_le32(0xC0000720)
-#define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY cpu_to_le32(0xC0000721)
-#define STATUS_DISK_REPAIR_DISABLED cpu_to_le32(0xC0000800)
-#define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS cpu_to_le32(0xC0000801)
-#define STATUS_DISK_QUOTA_EXCEEDED cpu_to_le32(0xC0000802)
-#define STATUS_CONTENT_BLOCKED cpu_to_le32(0xC0000804)
-#define STATUS_BAD_CLUSTERS cpu_to_le32(0xC0000805)
-#define STATUS_VOLUME_DIRTY cpu_to_le32(0xC0000806)
-#define STATUS_FILE_CHECKED_OUT cpu_to_le32(0xC0000901)
-#define STATUS_CHECKOUT_REQUIRED cpu_to_le32(0xC0000902)
-#define STATUS_BAD_FILE_TYPE cpu_to_le32(0xC0000903)
-#define STATUS_FILE_TOO_LARGE cpu_to_le32(0xC0000904)
-#define STATUS_FORMS_AUTH_REQUIRED cpu_to_le32(0xC0000905)
-#define STATUS_VIRUS_INFECTED cpu_to_le32(0xC0000906)
-#define STATUS_VIRUS_DELETED cpu_to_le32(0xC0000907)
-#define STATUS_BAD_MCFG_TABLE cpu_to_le32(0xC0000908)
-#define STATUS_WOW_ASSERTION cpu_to_le32(0xC0009898)
-#define STATUS_INVALID_SIGNATURE cpu_to_le32(0xC000A000)
-#define STATUS_HMAC_NOT_SUPPORTED cpu_to_le32(0xC000A001)
-#define STATUS_IPSEC_QUEUE_OVERFLOW cpu_to_le32(0xC000A010)
-#define STATUS_ND_QUEUE_OVERFLOW cpu_to_le32(0xC000A011)
-#define STATUS_HOPLIMIT_EXCEEDED cpu_to_le32(0xC000A012)
-#define STATUS_PROTOCOL_NOT_SUPPORTED cpu_to_le32(0xC000A013)
-#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED cpu_to_le32(0xC000A080)
-#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR cpu_to_le32(0xC000A081)
-#define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR cpu_to_le32(0xC000A082)
-#define STATUS_XML_PARSE_ERROR cpu_to_le32(0xC000A083)
-#define STATUS_XMLDSIG_ERROR cpu_to_le32(0xC000A084)
-#define STATUS_WRONG_COMPARTMENT cpu_to_le32(0xC000A085)
-#define STATUS_AUTHIP_FAILURE cpu_to_le32(0xC000A086)
-#define DBG_NO_STATE_CHANGE cpu_to_le32(0xC0010001)
-#define DBG_APP_NOT_IDLE cpu_to_le32(0xC0010002)
-#define RPC_NT_INVALID_STRING_BINDING cpu_to_le32(0xC0020001)
-#define RPC_NT_WRONG_KIND_OF_BINDING cpu_to_le32(0xC0020002)
-#define RPC_NT_INVALID_BINDING cpu_to_le32(0xC0020003)
-#define RPC_NT_PROTSEQ_NOT_SUPPORTED cpu_to_le32(0xC0020004)
-#define RPC_NT_INVALID_RPC_PROTSEQ cpu_to_le32(0xC0020005)
-#define RPC_NT_INVALID_STRING_UUID cpu_to_le32(0xC0020006)
-#define RPC_NT_INVALID_ENDPOINT_FORMAT cpu_to_le32(0xC0020007)
-#define RPC_NT_INVALID_NET_ADDR cpu_to_le32(0xC0020008)
-#define RPC_NT_NO_ENDPOINT_FOUND cpu_to_le32(0xC0020009)
-#define RPC_NT_INVALID_TIMEOUT cpu_to_le32(0xC002000A)
-#define RPC_NT_OBJECT_NOT_FOUND cpu_to_le32(0xC002000B)
-#define RPC_NT_ALREADY_REGISTERED cpu_to_le32(0xC002000C)
-#define RPC_NT_TYPE_ALREADY_REGISTERED cpu_to_le32(0xC002000D)
-#define RPC_NT_ALREADY_LISTENING cpu_to_le32(0xC002000E)
-#define RPC_NT_NO_PROTSEQS_REGISTERED cpu_to_le32(0xC002000F)
-#define RPC_NT_NOT_LISTENING cpu_to_le32(0xC0020010)
-#define RPC_NT_UNKNOWN_MGR_TYPE cpu_to_le32(0xC0020011)
-#define RPC_NT_UNKNOWN_IF cpu_to_le32(0xC0020012)
-#define RPC_NT_NO_BINDINGS cpu_to_le32(0xC0020013)
-#define RPC_NT_NO_PROTSEQS cpu_to_le32(0xC0020014)
-#define RPC_NT_CANT_CREATE_ENDPOINT cpu_to_le32(0xC0020015)
-#define RPC_NT_OUT_OF_RESOURCES cpu_to_le32(0xC0020016)
-#define RPC_NT_SERVER_UNAVAILABLE cpu_to_le32(0xC0020017)
-#define RPC_NT_SERVER_TOO_BUSY cpu_to_le32(0xC0020018)
-#define RPC_NT_INVALID_NETWORK_OPTIONS cpu_to_le32(0xC0020019)
-#define RPC_NT_NO_CALL_ACTIVE cpu_to_le32(0xC002001A)
-#define RPC_NT_CALL_FAILED cpu_to_le32(0xC002001B)
-#define RPC_NT_CALL_FAILED_DNE cpu_to_le32(0xC002001C)
-#define RPC_NT_PROTOCOL_ERROR cpu_to_le32(0xC002001D)
-#define RPC_NT_UNSUPPORTED_TRANS_SYN cpu_to_le32(0xC002001F)
-#define RPC_NT_UNSUPPORTED_TYPE cpu_to_le32(0xC0020021)
-#define RPC_NT_INVALID_TAG cpu_to_le32(0xC0020022)
-#define RPC_NT_INVALID_BOUND cpu_to_le32(0xC0020023)
-#define RPC_NT_NO_ENTRY_NAME cpu_to_le32(0xC0020024)
-#define RPC_NT_INVALID_NAME_SYNTAX cpu_to_le32(0xC0020025)
-#define RPC_NT_UNSUPPORTED_NAME_SYNTAX cpu_to_le32(0xC0020026)
-#define RPC_NT_UUID_NO_ADDRESS cpu_to_le32(0xC0020028)
-#define RPC_NT_DUPLICATE_ENDPOINT cpu_to_le32(0xC0020029)
-#define RPC_NT_UNKNOWN_AUTHN_TYPE cpu_to_le32(0xC002002A)
-#define RPC_NT_MAX_CALLS_TOO_SMALL cpu_to_le32(0xC002002B)
-#define RPC_NT_STRING_TOO_LONG cpu_to_le32(0xC002002C)
-#define RPC_NT_PROTSEQ_NOT_FOUND cpu_to_le32(0xC002002D)
-#define RPC_NT_PROCNUM_OUT_OF_RANGE cpu_to_le32(0xC002002E)
-#define RPC_NT_BINDING_HAS_NO_AUTH cpu_to_le32(0xC002002F)
-#define RPC_NT_UNKNOWN_AUTHN_SERVICE cpu_to_le32(0xC0020030)
-#define RPC_NT_UNKNOWN_AUTHN_LEVEL cpu_to_le32(0xC0020031)
-#define RPC_NT_INVALID_AUTH_IDENTITY cpu_to_le32(0xC0020032)
-#define RPC_NT_UNKNOWN_AUTHZ_SERVICE cpu_to_le32(0xC0020033)
-#define EPT_NT_INVALID_ENTRY cpu_to_le32(0xC0020034)
-#define EPT_NT_CANT_PERFORM_OP cpu_to_le32(0xC0020035)
-#define EPT_NT_NOT_REGISTERED cpu_to_le32(0xC0020036)
-#define RPC_NT_NOTHING_TO_EXPORT cpu_to_le32(0xC0020037)
-#define RPC_NT_INCOMPLETE_NAME cpu_to_le32(0xC0020038)
-#define RPC_NT_INVALID_VERS_OPTION cpu_to_le32(0xC0020039)
-#define RPC_NT_NO_MORE_MEMBERS cpu_to_le32(0xC002003A)
-#define RPC_NT_NOT_ALL_OBJS_UNEXPORTED cpu_to_le32(0xC002003B)
-#define RPC_NT_INTERFACE_NOT_FOUND cpu_to_le32(0xC002003C)
-#define RPC_NT_ENTRY_ALREADY_EXISTS cpu_to_le32(0xC002003D)
-#define RPC_NT_ENTRY_NOT_FOUND cpu_to_le32(0xC002003E)
-#define RPC_NT_NAME_SERVICE_UNAVAILABLE cpu_to_le32(0xC002003F)
-#define RPC_NT_INVALID_NAF_ID cpu_to_le32(0xC0020040)
-#define RPC_NT_CANNOT_SUPPORT cpu_to_le32(0xC0020041)
-#define RPC_NT_NO_CONTEXT_AVAILABLE cpu_to_le32(0xC0020042)
-#define RPC_NT_INTERNAL_ERROR cpu_to_le32(0xC0020043)
-#define RPC_NT_ZERO_DIVIDE cpu_to_le32(0xC0020044)
-#define RPC_NT_ADDRESS_ERROR cpu_to_le32(0xC0020045)
-#define RPC_NT_FP_DIV_ZERO cpu_to_le32(0xC0020046)
-#define RPC_NT_FP_UNDERFLOW cpu_to_le32(0xC0020047)
-#define RPC_NT_FP_OVERFLOW cpu_to_le32(0xC0020048)
-#define RPC_NT_CALL_IN_PROGRESS cpu_to_le32(0xC0020049)
-#define RPC_NT_NO_MORE_BINDINGS cpu_to_le32(0xC002004A)
-#define RPC_NT_GROUP_MEMBER_NOT_FOUND cpu_to_le32(0xC002004B)
-#define EPT_NT_CANT_CREATE cpu_to_le32(0xC002004C)
-#define RPC_NT_INVALID_OBJECT cpu_to_le32(0xC002004D)
-#define RPC_NT_NO_INTERFACES cpu_to_le32(0xC002004F)
-#define RPC_NT_CALL_CANCELLED cpu_to_le32(0xC0020050)
-#define RPC_NT_BINDING_INCOMPLETE cpu_to_le32(0xC0020051)
-#define RPC_NT_COMM_FAILURE cpu_to_le32(0xC0020052)
-#define RPC_NT_UNSUPPORTED_AUTHN_LEVEL cpu_to_le32(0xC0020053)
-#define RPC_NT_NO_PRINC_NAME cpu_to_le32(0xC0020054)
-#define RPC_NT_NOT_RPC_ERROR cpu_to_le32(0xC0020055)
-#define RPC_NT_SEC_PKG_ERROR cpu_to_le32(0xC0020057)
-#define RPC_NT_NOT_CANCELLED cpu_to_le32(0xC0020058)
-#define RPC_NT_INVALID_ASYNC_HANDLE cpu_to_le32(0xC0020062)
-#define RPC_NT_INVALID_ASYNC_CALL cpu_to_le32(0xC0020063)
-#define RPC_NT_PROXY_ACCESS_DENIED cpu_to_le32(0xC0020064)
-#define RPC_NT_NO_MORE_ENTRIES cpu_to_le32(0xC0030001)
-#define RPC_NT_SS_CHAR_TRANS_OPEN_FAIL cpu_to_le32(0xC0030002)
-#define RPC_NT_SS_CHAR_TRANS_SHORT_FILE cpu_to_le32(0xC0030003)
-#define RPC_NT_SS_IN_NULL_CONTEXT cpu_to_le32(0xC0030004)
-#define RPC_NT_SS_CONTEXT_MISMATCH cpu_to_le32(0xC0030005)
-#define RPC_NT_SS_CONTEXT_DAMAGED cpu_to_le32(0xC0030006)
-#define RPC_NT_SS_HANDLES_MISMATCH cpu_to_le32(0xC0030007)
-#define RPC_NT_SS_CANNOT_GET_CALL_HANDLE cpu_to_le32(0xC0030008)
-#define RPC_NT_NULL_REF_POINTER cpu_to_le32(0xC0030009)
-#define RPC_NT_ENUM_VALUE_OUT_OF_RANGE cpu_to_le32(0xC003000A)
-#define RPC_NT_BYTE_COUNT_TOO_SMALL cpu_to_le32(0xC003000B)
-#define RPC_NT_BAD_STUB_DATA cpu_to_le32(0xC003000C)
-#define RPC_NT_INVALID_ES_ACTION cpu_to_le32(0xC0030059)
-#define RPC_NT_WRONG_ES_VERSION cpu_to_le32(0xC003005A)
-#define RPC_NT_WRONG_STUB_VERSION cpu_to_le32(0xC003005B)
-#define RPC_NT_INVALID_PIPE_OBJECT cpu_to_le32(0xC003005C)
-#define RPC_NT_INVALID_PIPE_OPERATION cpu_to_le32(0xC003005D)
-#define RPC_NT_WRONG_PIPE_VERSION cpu_to_le32(0xC003005E)
-#define RPC_NT_PIPE_CLOSED cpu_to_le32(0xC003005F)
-#define RPC_NT_PIPE_DISCIPLINE_ERROR cpu_to_le32(0xC0030060)
-#define RPC_NT_PIPE_EMPTY cpu_to_le32(0xC0030061)
-#define STATUS_PNP_BAD_MPS_TABLE cpu_to_le32(0xC0040035)
-#define STATUS_PNP_TRANSLATION_FAILED cpu_to_le32(0xC0040036)
-#define STATUS_PNP_IRQ_TRANSLATION_FAILED cpu_to_le32(0xC0040037)
-#define STATUS_PNP_INVALID_ID cpu_to_le32(0xC0040038)
-#define STATUS_IO_REISSUE_AS_CACHED cpu_to_le32(0xC0040039)
-#define STATUS_CTX_WINSTATION_NAME_INVALID cpu_to_le32(0xC00A0001)
-#define STATUS_CTX_INVALID_PD cpu_to_le32(0xC00A0002)
-#define STATUS_CTX_PD_NOT_FOUND cpu_to_le32(0xC00A0003)
-#define STATUS_CTX_CLOSE_PENDING cpu_to_le32(0xC00A0006)
-#define STATUS_CTX_NO_OUTBUF cpu_to_le32(0xC00A0007)
-#define STATUS_CTX_MODEM_INF_NOT_FOUND cpu_to_le32(0xC00A0008)
-#define STATUS_CTX_INVALID_MODEMNAME cpu_to_le32(0xC00A0009)
-#define STATUS_CTX_RESPONSE_ERROR cpu_to_le32(0xC00A000A)
-#define STATUS_CTX_MODEM_RESPONSE_TIMEOUT cpu_to_le32(0xC00A000B)
-#define STATUS_CTX_MODEM_RESPONSE_NO_CARRIER cpu_to_le32(0xC00A000C)
-#define STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE cpu_to_le32(0xC00A000D)
-#define STATUS_CTX_MODEM_RESPONSE_BUSY cpu_to_le32(0xC00A000E)
-#define STATUS_CTX_MODEM_RESPONSE_VOICE cpu_to_le32(0xC00A000F)
-#define STATUS_CTX_TD_ERROR cpu_to_le32(0xC00A0010)
-#define STATUS_CTX_LICENSE_CLIENT_INVALID cpu_to_le32(0xC00A0012)
-#define STATUS_CTX_LICENSE_NOT_AVAILABLE cpu_to_le32(0xC00A0013)
-#define STATUS_CTX_LICENSE_EXPIRED cpu_to_le32(0xC00A0014)
-#define STATUS_CTX_WINSTATION_NOT_FOUND cpu_to_le32(0xC00A0015)
-#define STATUS_CTX_WINSTATION_NAME_COLLISION cpu_to_le32(0xC00A0016)
-#define STATUS_CTX_WINSTATION_BUSY cpu_to_le32(0xC00A0017)
-#define STATUS_CTX_BAD_VIDEO_MODE cpu_to_le32(0xC00A0018)
-#define STATUS_CTX_GRAPHICS_INVALID cpu_to_le32(0xC00A0022)
-#define STATUS_CTX_NOT_CONSOLE cpu_to_le32(0xC00A0024)
-#define STATUS_CTX_CLIENT_QUERY_TIMEOUT cpu_to_le32(0xC00A0026)
-#define STATUS_CTX_CONSOLE_DISCONNECT cpu_to_le32(0xC00A0027)
-#define STATUS_CTX_CONSOLE_CONNECT cpu_to_le32(0xC00A0028)
-#define STATUS_CTX_SHADOW_DENIED cpu_to_le32(0xC00A002A)
-#define STATUS_CTX_WINSTATION_ACCESS_DENIED cpu_to_le32(0xC00A002B)
-#define STATUS_CTX_INVALID_WD cpu_to_le32(0xC00A002E)
-#define STATUS_CTX_WD_NOT_FOUND cpu_to_le32(0xC00A002F)
-#define STATUS_CTX_SHADOW_INVALID cpu_to_le32(0xC00A0030)
-#define STATUS_CTX_SHADOW_DISABLED cpu_to_le32(0xC00A0031)
-#define STATUS_RDP_PROTOCOL_ERROR cpu_to_le32(0xC00A0032)
-#define STATUS_CTX_CLIENT_LICENSE_NOT_SET cpu_to_le32(0xC00A0033)
-#define STATUS_CTX_CLIENT_LICENSE_IN_USE cpu_to_le32(0xC00A0034)
-#define STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE cpu_to_le32(0xC00A0035)
-#define STATUS_CTX_SHADOW_NOT_RUNNING cpu_to_le32(0xC00A0036)
-#define STATUS_CTX_LOGON_DISABLED cpu_to_le32(0xC00A0037)
-#define STATUS_CTX_SECURITY_LAYER_ERROR cpu_to_le32(0xC00A0038)
-#define STATUS_TS_INCOMPATIBLE_SESSIONS cpu_to_le32(0xC00A0039)
-#define STATUS_MUI_FILE_NOT_FOUND cpu_to_le32(0xC00B0001)
-#define STATUS_MUI_INVALID_FILE cpu_to_le32(0xC00B0002)
-#define STATUS_MUI_INVALID_RC_CONFIG cpu_to_le32(0xC00B0003)
-#define STATUS_MUI_INVALID_LOCALE_NAME cpu_to_le32(0xC00B0004)
-#define STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME cpu_to_le32(0xC00B0005)
-#define STATUS_MUI_FILE_NOT_LOADED cpu_to_le32(0xC00B0006)
-#define STATUS_RESOURCE_ENUM_USER_STOP cpu_to_le32(0xC00B0007)
-#define STATUS_CLUSTER_INVALID_NODE cpu_to_le32(0xC0130001)
-#define STATUS_CLUSTER_NODE_EXISTS cpu_to_le32(0xC0130002)
-#define STATUS_CLUSTER_JOIN_IN_PROGRESS cpu_to_le32(0xC0130003)
-#define STATUS_CLUSTER_NODE_NOT_FOUND cpu_to_le32(0xC0130004)
-#define STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND cpu_to_le32(0xC0130005)
-#define STATUS_CLUSTER_NETWORK_EXISTS cpu_to_le32(0xC0130006)
-#define STATUS_CLUSTER_NETWORK_NOT_FOUND cpu_to_le32(0xC0130007)
-#define STATUS_CLUSTER_NETINTERFACE_EXISTS cpu_to_le32(0xC0130008)
-#define STATUS_CLUSTER_NETINTERFACE_NOT_FOUND cpu_to_le32(0xC0130009)
-#define STATUS_CLUSTER_INVALID_REQUEST cpu_to_le32(0xC013000A)
-#define STATUS_CLUSTER_INVALID_NETWORK_PROVIDER cpu_to_le32(0xC013000B)
-#define STATUS_CLUSTER_NODE_DOWN cpu_to_le32(0xC013000C)
-#define STATUS_CLUSTER_NODE_UNREACHABLE cpu_to_le32(0xC013000D)
-#define STATUS_CLUSTER_NODE_NOT_MEMBER cpu_to_le32(0xC013000E)
-#define STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS cpu_to_le32(0xC013000F)
-#define STATUS_CLUSTER_INVALID_NETWORK cpu_to_le32(0xC0130010)
-#define STATUS_CLUSTER_NO_NET_ADAPTERS cpu_to_le32(0xC0130011)
-#define STATUS_CLUSTER_NODE_UP cpu_to_le32(0xC0130012)
-#define STATUS_CLUSTER_NODE_PAUSED cpu_to_le32(0xC0130013)
-#define STATUS_CLUSTER_NODE_NOT_PAUSED cpu_to_le32(0xC0130014)
-#define STATUS_CLUSTER_NO_SECURITY_CONTEXT cpu_to_le32(0xC0130015)
-#define STATUS_CLUSTER_NETWORK_NOT_INTERNAL cpu_to_le32(0xC0130016)
-#define STATUS_CLUSTER_POISONED cpu_to_le32(0xC0130017)
-#define STATUS_ACPI_INVALID_OPCODE cpu_to_le32(0xC0140001)
-#define STATUS_ACPI_STACK_OVERFLOW cpu_to_le32(0xC0140002)
-#define STATUS_ACPI_ASSERT_FAILED cpu_to_le32(0xC0140003)
-#define STATUS_ACPI_INVALID_INDEX cpu_to_le32(0xC0140004)
-#define STATUS_ACPI_INVALID_ARGUMENT cpu_to_le32(0xC0140005)
-#define STATUS_ACPI_FATAL cpu_to_le32(0xC0140006)
-#define STATUS_ACPI_INVALID_SUPERNAME cpu_to_le32(0xC0140007)
-#define STATUS_ACPI_INVALID_ARGTYPE cpu_to_le32(0xC0140008)
-#define STATUS_ACPI_INVALID_OBJTYPE cpu_to_le32(0xC0140009)
-#define STATUS_ACPI_INVALID_TARGETTYPE cpu_to_le32(0xC014000A)
-#define STATUS_ACPI_INCORRECT_ARGUMENT_COUNT cpu_to_le32(0xC014000B)
-#define STATUS_ACPI_ADDRESS_NOT_MAPPED cpu_to_le32(0xC014000C)
-#define STATUS_ACPI_INVALID_EVENTTYPE cpu_to_le32(0xC014000D)
-#define STATUS_ACPI_HANDLER_COLLISION cpu_to_le32(0xC014000E)
-#define STATUS_ACPI_INVALID_DATA cpu_to_le32(0xC014000F)
-#define STATUS_ACPI_INVALID_REGION cpu_to_le32(0xC0140010)
-#define STATUS_ACPI_INVALID_ACCESS_SIZE cpu_to_le32(0xC0140011)
-#define STATUS_ACPI_ACQUIRE_GLOBAL_LOCK cpu_to_le32(0xC0140012)
-#define STATUS_ACPI_ALREADY_INITIALIZED cpu_to_le32(0xC0140013)
-#define STATUS_ACPI_NOT_INITIALIZED cpu_to_le32(0xC0140014)
-#define STATUS_ACPI_INVALID_MUTEX_LEVEL cpu_to_le32(0xC0140015)
-#define STATUS_ACPI_MUTEX_NOT_OWNED cpu_to_le32(0xC0140016)
-#define STATUS_ACPI_MUTEX_NOT_OWNER cpu_to_le32(0xC0140017)
-#define STATUS_ACPI_RS_ACCESS cpu_to_le32(0xC0140018)
-#define STATUS_ACPI_INVALID_TABLE cpu_to_le32(0xC0140019)
-#define STATUS_ACPI_REG_HANDLER_FAILED cpu_to_le32(0xC0140020)
-#define STATUS_ACPI_POWER_REQUEST_FAILED cpu_to_le32(0xC0140021)
-#define STATUS_SXS_SECTION_NOT_FOUND cpu_to_le32(0xC0150001)
-#define STATUS_SXS_CANT_GEN_ACTCTX cpu_to_le32(0xC0150002)
-#define STATUS_SXS_INVALID_ACTCTXDATA_FORMAT cpu_to_le32(0xC0150003)
-#define STATUS_SXS_ASSEMBLY_NOT_FOUND cpu_to_le32(0xC0150004)
-#define STATUS_SXS_MANIFEST_FORMAT_ERROR cpu_to_le32(0xC0150005)
-#define STATUS_SXS_MANIFEST_PARSE_ERROR cpu_to_le32(0xC0150006)
-#define STATUS_SXS_ACTIVATION_CONTEXT_DISABLED cpu_to_le32(0xC0150007)
-#define STATUS_SXS_KEY_NOT_FOUND cpu_to_le32(0xC0150008)
-#define STATUS_SXS_VERSION_CONFLICT cpu_to_le32(0xC0150009)
-#define STATUS_SXS_WRONG_SECTION_TYPE cpu_to_le32(0xC015000A)
-#define STATUS_SXS_THREAD_QUERIES_DISABLED cpu_to_le32(0xC015000B)
-#define STATUS_SXS_ASSEMBLY_MISSING cpu_to_le32(0xC015000C)
-#define STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET cpu_to_le32(0xC015000E)
-#define STATUS_SXS_EARLY_DEACTIVATION cpu_to_le32(0xC015000F)
-#define STATUS_SXS_INVALID_DEACTIVATION cpu_to_le32(0xC0150010)
-#define STATUS_SXS_MULTIPLE_DEACTIVATION cpu_to_le32(0xC0150011)
-#define STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY cpu_to_le32(0xC0150012)
-#define STATUS_SXS_PROCESS_TERMINATION_REQUESTED cpu_to_le32(0xC0150013)
-#define STATUS_SXS_CORRUPT_ACTIVATION_STACK cpu_to_le32(0xC0150014)
-#define STATUS_SXS_CORRUPTION cpu_to_le32(0xC0150015)
-#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE cpu_to_le32(0xC0150016)
-#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME cpu_to_le32(0xC0150017)
-#define STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE cpu_to_le32(0xC0150018)
-#define STATUS_SXS_IDENTITY_PARSE_ERROR cpu_to_le32(0xC0150019)
-#define STATUS_SXS_COMPONENT_STORE_CORRUPT cpu_to_le32(0xC015001A)
-#define STATUS_SXS_FILE_HASH_MISMATCH cpu_to_le32(0xC015001B)
-#define STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT cpu_to_le32(0xC015001C)
-#define STATUS_SXS_IDENTITIES_DIFFERENT cpu_to_le32(0xC015001D)
-#define STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT cpu_to_le32(0xC015001E)
-#define STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY cpu_to_le32(0xC015001F)
-#define STATUS_ADVANCED_INSTALLER_FAILED cpu_to_le32(0xC0150020)
-#define STATUS_XML_ENCODING_MISMATCH cpu_to_le32(0xC0150021)
-#define STATUS_SXS_MANIFEST_TOO_BIG cpu_to_le32(0xC0150022)
-#define STATUS_SXS_SETTING_NOT_REGISTERED cpu_to_le32(0xC0150023)
-#define STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE cpu_to_le32(0xC0150024)
-#define STATUS_SMI_PRIMITIVE_INSTALLER_FAILED cpu_to_le32(0xC0150025)
-#define STATUS_GENERIC_COMMAND_FAILED cpu_to_le32(0xC0150026)
-#define STATUS_SXS_FILE_HASH_MISSING cpu_to_le32(0xC0150027)
-#define STATUS_TRANSACTIONAL_CONFLICT cpu_to_le32(0xC0190001)
-#define STATUS_INVALID_TRANSACTION cpu_to_le32(0xC0190002)
-#define STATUS_TRANSACTION_NOT_ACTIVE cpu_to_le32(0xC0190003)
-#define STATUS_TM_INITIALIZATION_FAILED cpu_to_le32(0xC0190004)
-#define STATUS_RM_NOT_ACTIVE cpu_to_le32(0xC0190005)
-#define STATUS_RM_METADATA_CORRUPT cpu_to_le32(0xC0190006)
-#define STATUS_TRANSACTION_NOT_JOINED cpu_to_le32(0xC0190007)
-#define STATUS_DIRECTORY_NOT_RM cpu_to_le32(0xC0190008)
-#define STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE cpu_to_le32(0xC019000A)
-#define STATUS_LOG_RESIZE_INVALID_SIZE cpu_to_le32(0xC019000B)
-#define STATUS_REMOTE_FILE_VERSION_MISMATCH cpu_to_le32(0xC019000C)
-#define STATUS_CRM_PROTOCOL_ALREADY_EXISTS cpu_to_le32(0xC019000F)
-#define STATUS_TRANSACTION_PROPAGATION_FAILED cpu_to_le32(0xC0190010)
-#define STATUS_CRM_PROTOCOL_NOT_FOUND cpu_to_le32(0xC0190011)
-#define STATUS_TRANSACTION_SUPERIOR_EXISTS cpu_to_le32(0xC0190012)
-#define STATUS_TRANSACTION_REQUEST_NOT_VALID cpu_to_le32(0xC0190013)
-#define STATUS_TRANSACTION_NOT_REQUESTED cpu_to_le32(0xC0190014)
-#define STATUS_TRANSACTION_ALREADY_ABORTED cpu_to_le32(0xC0190015)
-#define STATUS_TRANSACTION_ALREADY_COMMITTED cpu_to_le32(0xC0190016)
-#define STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER cpu_to_le32(0xC0190017)
-#define STATUS_CURRENT_TRANSACTION_NOT_VALID cpu_to_le32(0xC0190018)
-#define STATUS_LOG_GROWTH_FAILED cpu_to_le32(0xC0190019)
-#define STATUS_OBJECT_NO_LONGER_EXISTS cpu_to_le32(0xC0190021)
-#define STATUS_STREAM_MINIVERSION_NOT_FOUND cpu_to_le32(0xC0190022)
-#define STATUS_STREAM_MINIVERSION_NOT_VALID cpu_to_le32(0xC0190023)
-#define STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION cpu_to_le32(0xC0190024)
-#define STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT cpu_to_le32(0xC0190025)
-#define STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS cpu_to_le32(0xC0190026)
-#define STATUS_HANDLE_NO_LONGER_VALID cpu_to_le32(0xC0190028)
-#define STATUS_LOG_CORRUPTION_DETECTED cpu_to_le32(0xC0190030)
-#define STATUS_RM_DISCONNECTED cpu_to_le32(0xC0190032)
-#define STATUS_ENLISTMENT_NOT_SUPERIOR cpu_to_le32(0xC0190033)
-#define STATUS_FILE_IDENTITY_NOT_PERSISTENT cpu_to_le32(0xC0190036)
-#define STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY cpu_to_le32(0xC0190037)
-#define STATUS_CANT_CROSS_RM_BOUNDARY cpu_to_le32(0xC0190038)
-#define STATUS_TXF_DIR_NOT_EMPTY cpu_to_le32(0xC0190039)
-#define STATUS_INDOUBT_TRANSACTIONS_EXIST cpu_to_le32(0xC019003A)
-#define STATUS_TM_VOLATILE cpu_to_le32(0xC019003B)
-#define STATUS_ROLLBACK_TIMER_EXPIRED cpu_to_le32(0xC019003C)
-#define STATUS_TXF_ATTRIBUTE_CORRUPT cpu_to_le32(0xC019003D)
-#define STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC019003E)
-#define STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED cpu_to_le32(0xC019003F)
-#define STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE cpu_to_le32(0xC0190040)
-#define STATUS_TRANSACTION_REQUIRED_PROMOTION cpu_to_le32(0xC0190043)
-#define STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION cpu_to_le32(0xC0190044)
-#define STATUS_TRANSACTIONS_NOT_FROZEN cpu_to_le32(0xC0190045)
-#define STATUS_TRANSACTION_FREEZE_IN_PROGRESS cpu_to_le32(0xC0190046)
-#define STATUS_NOT_SNAPSHOT_VOLUME cpu_to_le32(0xC0190047)
-#define STATUS_NO_SAVEPOINT_WITH_OPEN_FILES cpu_to_le32(0xC0190048)
-#define STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC0190049)
-#define STATUS_TM_IDENTITY_MISMATCH cpu_to_le32(0xC019004A)
-#define STATUS_FLOATED_SECTION cpu_to_le32(0xC019004B)
-#define STATUS_CANNOT_ACCEPT_TRANSACTED_WORK cpu_to_le32(0xC019004C)
-#define STATUS_CANNOT_ABORT_TRANSACTIONS cpu_to_le32(0xC019004D)
-#define STATUS_TRANSACTION_NOT_FOUND cpu_to_le32(0xC019004E)
-#define STATUS_RESOURCEMANAGER_NOT_FOUND cpu_to_le32(0xC019004F)
-#define STATUS_ENLISTMENT_NOT_FOUND cpu_to_le32(0xC0190050)
-#define STATUS_TRANSACTIONMANAGER_NOT_FOUND cpu_to_le32(0xC0190051)
-#define STATUS_TRANSACTIONMANAGER_NOT_ONLINE cpu_to_le32(0xC0190052)
-#define STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION cpu_to_le32(0xC0190053)
-#define STATUS_TRANSACTION_NOT_ROOT cpu_to_le32(0xC0190054)
-#define STATUS_TRANSACTION_OBJECT_EXPIRED cpu_to_le32(0xC0190055)
-#define STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC0190056)
-#define STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED cpu_to_le32(0xC0190057)
-#define STATUS_TRANSACTION_RECORD_TOO_LONG cpu_to_le32(0xC0190058)
-#define STATUS_NO_LINK_TRACKING_IN_TRANSACTION cpu_to_le32(0xC0190059)
-#define STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION cpu_to_le32(0xC019005A)
-#define STATUS_TRANSACTION_INTEGRITY_VIOLATED cpu_to_le32(0xC019005B)
-#define STATUS_LOG_SECTOR_INVALID cpu_to_le32(0xC01A0001)
-#define STATUS_LOG_SECTOR_PARITY_INVALID cpu_to_le32(0xC01A0002)
-#define STATUS_LOG_SECTOR_REMAPPED cpu_to_le32(0xC01A0003)
-#define STATUS_LOG_BLOCK_INCOMPLETE cpu_to_le32(0xC01A0004)
-#define STATUS_LOG_INVALID_RANGE cpu_to_le32(0xC01A0005)
-#define STATUS_LOG_BLOCKS_EXHAUSTED cpu_to_le32(0xC01A0006)
-#define STATUS_LOG_READ_CONTEXT_INVALID cpu_to_le32(0xC01A0007)
-#define STATUS_LOG_RESTART_INVALID cpu_to_le32(0xC01A0008)
-#define STATUS_LOG_BLOCK_VERSION cpu_to_le32(0xC01A0009)
-#define STATUS_LOG_BLOCK_INVALID cpu_to_le32(0xC01A000A)
-#define STATUS_LOG_READ_MODE_INVALID cpu_to_le32(0xC01A000B)
-#define STATUS_LOG_METADATA_CORRUPT cpu_to_le32(0xC01A000D)
-#define STATUS_LOG_METADATA_INVALID cpu_to_le32(0xC01A000E)
-#define STATUS_LOG_METADATA_INCONSISTENT cpu_to_le32(0xC01A000F)
-#define STATUS_LOG_RESERVATION_INVALID cpu_to_le32(0xC01A0010)
-#define STATUS_LOG_CANT_DELETE cpu_to_le32(0xC01A0011)
-#define STATUS_LOG_CONTAINER_LIMIT_EXCEEDED cpu_to_le32(0xC01A0012)
-#define STATUS_LOG_START_OF_LOG cpu_to_le32(0xC01A0013)
-#define STATUS_LOG_POLICY_ALREADY_INSTALLED cpu_to_le32(0xC01A0014)
-#define STATUS_LOG_POLICY_NOT_INSTALLED cpu_to_le32(0xC01A0015)
-#define STATUS_LOG_POLICY_INVALID cpu_to_le32(0xC01A0016)
-#define STATUS_LOG_POLICY_CONFLICT cpu_to_le32(0xC01A0017)
-#define STATUS_LOG_PINNED_ARCHIVE_TAIL cpu_to_le32(0xC01A0018)
-#define STATUS_LOG_RECORD_NONEXISTENT cpu_to_le32(0xC01A0019)
-#define STATUS_LOG_RECORDS_RESERVED_INVALID cpu_to_le32(0xC01A001A)
-#define STATUS_LOG_SPACE_RESERVED_INVALID cpu_to_le32(0xC01A001B)
-#define STATUS_LOG_TAIL_INVALID cpu_to_le32(0xC01A001C)
-#define STATUS_LOG_FULL cpu_to_le32(0xC01A001D)
-#define STATUS_LOG_MULTIPLEXED cpu_to_le32(0xC01A001E)
-#define STATUS_LOG_DEDICATED cpu_to_le32(0xC01A001F)
-#define STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS cpu_to_le32(0xC01A0020)
-#define STATUS_LOG_ARCHIVE_IN_PROGRESS cpu_to_le32(0xC01A0021)
-#define STATUS_LOG_EPHEMERAL cpu_to_le32(0xC01A0022)
-#define STATUS_LOG_NOT_ENOUGH_CONTAINERS cpu_to_le32(0xC01A0023)
-#define STATUS_LOG_CLIENT_ALREADY_REGISTERED cpu_to_le32(0xC01A0024)
-#define STATUS_LOG_CLIENT_NOT_REGISTERED cpu_to_le32(0xC01A0025)
-#define STATUS_LOG_FULL_HANDLER_IN_PROGRESS cpu_to_le32(0xC01A0026)
-#define STATUS_LOG_CONTAINER_READ_FAILED cpu_to_le32(0xC01A0027)
-#define STATUS_LOG_CONTAINER_WRITE_FAILED cpu_to_le32(0xC01A0028)
-#define STATUS_LOG_CONTAINER_OPEN_FAILED cpu_to_le32(0xC01A0029)
-#define STATUS_LOG_CONTAINER_STATE_INVALID cpu_to_le32(0xC01A002A)
-#define STATUS_LOG_STATE_INVALID cpu_to_le32(0xC01A002B)
-#define STATUS_LOG_PINNED cpu_to_le32(0xC01A002C)
-#define STATUS_LOG_METADATA_FLUSH_FAILED cpu_to_le32(0xC01A002D)
-#define STATUS_LOG_INCONSISTENT_SECURITY cpu_to_le32(0xC01A002E)
-#define STATUS_LOG_APPENDED_FLUSH_FAILED cpu_to_le32(0xC01A002F)
-#define STATUS_LOG_PINNED_RESERVATION cpu_to_le32(0xC01A0030)
-#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD cpu_to_le32(0xC01B00EA)
-#define STATUS_FLT_NO_HANDLER_DEFINED cpu_to_le32(0xC01C0001)
-#define STATUS_FLT_CONTEXT_ALREADY_DEFINED cpu_to_le32(0xC01C0002)
-#define STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST cpu_to_le32(0xC01C0003)
-#define STATUS_FLT_DISALLOW_FAST_IO cpu_to_le32(0xC01C0004)
-#define STATUS_FLT_INVALID_NAME_REQUEST cpu_to_le32(0xC01C0005)
-#define STATUS_FLT_NOT_SAFE_TO_POST_OPERATION cpu_to_le32(0xC01C0006)
-#define STATUS_FLT_NOT_INITIALIZED cpu_to_le32(0xC01C0007)
-#define STATUS_FLT_FILTER_NOT_READY cpu_to_le32(0xC01C0008)
-#define STATUS_FLT_POST_OPERATION_CLEANUP cpu_to_le32(0xC01C0009)
-#define STATUS_FLT_INTERNAL_ERROR cpu_to_le32(0xC01C000A)
-#define STATUS_FLT_DELETING_OBJECT cpu_to_le32(0xC01C000B)
-#define STATUS_FLT_MUST_BE_NONPAGED_POOL cpu_to_le32(0xC01C000C)
-#define STATUS_FLT_DUPLICATE_ENTRY cpu_to_le32(0xC01C000D)
-#define STATUS_FLT_CBDQ_DISABLED cpu_to_le32(0xC01C000E)
-#define STATUS_FLT_DO_NOT_ATTACH cpu_to_le32(0xC01C000F)
-#define STATUS_FLT_DO_NOT_DETACH cpu_to_le32(0xC01C0010)
-#define STATUS_FLT_INSTANCE_ALTITUDE_COLLISION cpu_to_le32(0xC01C0011)
-#define STATUS_FLT_INSTANCE_NAME_COLLISION cpu_to_le32(0xC01C0012)
-#define STATUS_FLT_FILTER_NOT_FOUND cpu_to_le32(0xC01C0013)
-#define STATUS_FLT_VOLUME_NOT_FOUND cpu_to_le32(0xC01C0014)
-#define STATUS_FLT_INSTANCE_NOT_FOUND cpu_to_le32(0xC01C0015)
-#define STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND cpu_to_le32(0xC01C0016)
-#define STATUS_FLT_INVALID_CONTEXT_REGISTRATION cpu_to_le32(0xC01C0017)
-#define STATUS_FLT_NAME_CACHE_MISS cpu_to_le32(0xC01C0018)
-#define STATUS_FLT_NO_DEVICE_OBJECT cpu_to_le32(0xC01C0019)
-#define STATUS_FLT_VOLUME_ALREADY_MOUNTED cpu_to_le32(0xC01C001A)
-#define STATUS_FLT_ALREADY_ENLISTED cpu_to_le32(0xC01C001B)
-#define STATUS_FLT_CONTEXT_ALREADY_LINKED cpu_to_le32(0xC01C001C)
-#define STATUS_FLT_NO_WAITER_FOR_REPLY cpu_to_le32(0xC01C0020)
-#define STATUS_MONITOR_NO_DESCRIPTOR cpu_to_le32(0xC01D0001)
-#define STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT cpu_to_le32(0xC01D0002)
-#define STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM cpu_to_le32(0xC01D0003)
-#define STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK cpu_to_le32(0xC01D0004)
-#define STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED cpu_to_le32(0xC01D0005)
-#define STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK cpu_to_le32(0xC01D0006)
-#define STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK cpu_to_le32(0xC01D0007)
-#define STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA cpu_to_le32(0xC01D0008)
-#define STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK cpu_to_le32(0xC01D0009)
-#define STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER cpu_to_le32(0xC01E0000)
-#define STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER cpu_to_le32(0xC01E0001)
-#define STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER cpu_to_le32(0xC01E0002)
-#define STATUS_GRAPHICS_ADAPTER_WAS_RESET cpu_to_le32(0xC01E0003)
-#define STATUS_GRAPHICS_INVALID_DRIVER_MODEL cpu_to_le32(0xC01E0004)
-#define STATUS_GRAPHICS_PRESENT_MODE_CHANGED cpu_to_le32(0xC01E0005)
-#define STATUS_GRAPHICS_PRESENT_OCCLUDED cpu_to_le32(0xC01E0006)
-#define STATUS_GRAPHICS_PRESENT_DENIED cpu_to_le32(0xC01E0007)
-#define STATUS_GRAPHICS_CANNOTCOLORCONVERT cpu_to_le32(0xC01E0008)
-#define STATUS_GRAPHICS_NO_VIDEO_MEMORY cpu_to_le32(0xC01E0100)
-#define STATUS_GRAPHICS_CANT_LOCK_MEMORY cpu_to_le32(0xC01E0101)
-#define STATUS_GRAPHICS_ALLOCATION_BUSY cpu_to_le32(0xC01E0102)
-#define STATUS_GRAPHICS_TOO_MANY_REFERENCES cpu_to_le32(0xC01E0103)
-#define STATUS_GRAPHICS_TRY_AGAIN_LATER cpu_to_le32(0xC01E0104)
-#define STATUS_GRAPHICS_TRY_AGAIN_NOW cpu_to_le32(0xC01E0105)
-#define STATUS_GRAPHICS_ALLOCATION_INVALID cpu_to_le32(0xC01E0106)
-#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE cpu_to_le32(0xC01E0107)
-#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED cpu_to_le32(0xC01E0108)
-#define STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION cpu_to_le32(0xC01E0109)
-#define STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE cpu_to_le32(0xC01E0110)
-#define STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION cpu_to_le32(0xC01E0111)
-#define STATUS_GRAPHICS_ALLOCATION_CLOSED cpu_to_le32(0xC01E0112)
-#define STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE cpu_to_le32(0xC01E0113)
-#define STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE cpu_to_le32(0xC01E0114)
-#define STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE cpu_to_le32(0xC01E0115)
-#define STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST cpu_to_le32(0xC01E0116)
-#define STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE cpu_to_le32(0xC01E0200)
-#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY cpu_to_le32(0xC01E0300)
-#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED cpu_to_le32(0xC01E0301)
-#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED cpu_to_le32(0xC01E0302)
-#define STATUS_GRAPHICS_INVALID_VIDPN cpu_to_le32(0xC01E0303)
-#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE cpu_to_le32(0xC01E0304)
-#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET cpu_to_le32(0xC01E0305)
-#define STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED cpu_to_le32(0xC01E0306)
-#define STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET cpu_to_le32(0xC01E0308)
-#define STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET cpu_to_le32(0xC01E0309)
-#define STATUS_GRAPHICS_INVALID_FREQUENCY cpu_to_le32(0xC01E030A)
-#define STATUS_GRAPHICS_INVALID_ACTIVE_REGION cpu_to_le32(0xC01E030B)
-#define STATUS_GRAPHICS_INVALID_TOTAL_REGION cpu_to_le32(0xC01E030C)
-#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE cpu_to_le32(0xC01E0310)
-#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE cpu_to_le32(0xC01E0311)
-#define STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET cpu_to_le32(0xC01E0312)
-#define STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY cpu_to_le32(0xC01E0313)
-#define STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET cpu_to_le32(0xC01E0314)
-#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET cpu_to_le32(0xC01E0315)
-#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET cpu_to_le32(0xC01E0316)
-#define STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET cpu_to_le32(0xC01E0317)
-#define STATUS_GRAPHICS_TARGET_ALREADY_IN_SET cpu_to_le32(0xC01E0318)
-#define STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH cpu_to_le32(0xC01E0319)
-#define STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY cpu_to_le32(0xC01E031A)
-#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET cpu_to_le32(0xC01E031B)
-#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE cpu_to_le32(0xC01E031C)
-#define STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET cpu_to_le32(0xC01E031D)
-#define STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET cpu_to_le32(0xC01E031F)
-#define STATUS_GRAPHICS_STALE_MODESET cpu_to_le32(0xC01E0320)
-#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET cpu_to_le32(0xC01E0321)
-#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE cpu_to_le32(0xC01E0322)
-#define STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN cpu_to_le32(0xC01E0323)
-#define STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0324)
-#define STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION cpu_to_le32(0xC01E0325)
-#define STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES cpu_to_le32(0xC01E0326)
-#define STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0327)
-#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE cpu_to_le32(0xC01E0328)
-#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET cpu_to_le32(0xC01E0329)
-#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET cpu_to_le32(0xC01E032A)
-#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR cpu_to_le32(0xC01E032B)
-#define STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET cpu_to_le32(0xC01E032C)
-#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET cpu_to_le32(0xC01E032D)
-#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E032E)
-#define STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE cpu_to_le32(0xC01E032F)
-#define STATUS_GRAPHICS_RESOURCES_NOT_RELATED cpu_to_le32(0xC01E0330)
-#define STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0331)
-#define STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0332)
-#define STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET cpu_to_le32(0xC01E0333)
-#define STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER cpu_to_le32(0xC01E0334)
-#define STATUS_GRAPHICS_NO_VIDPNMGR cpu_to_le32(0xC01E0335)
-#define STATUS_GRAPHICS_NO_ACTIVE_VIDPN cpu_to_le32(0xC01E0336)
-#define STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY cpu_to_le32(0xC01E0337)
-#define STATUS_GRAPHICS_MONITOR_NOT_CONNECTED cpu_to_le32(0xC01E0338)
-#define STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0339)
-#define STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE cpu_to_le32(0xC01E033A)
-#define STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE cpu_to_le32(0xC01E033B)
-#define STATUS_GRAPHICS_INVALID_STRIDE cpu_to_le32(0xC01E033C)
-#define STATUS_GRAPHICS_INVALID_PIXELFORMAT cpu_to_le32(0xC01E033D)
-#define STATUS_GRAPHICS_INVALID_COLORBASIS cpu_to_le32(0xC01E033E)
-#define STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE cpu_to_le32(0xC01E033F)
-#define STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0340)
-#define STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT cpu_to_le32(0xC01E0341)
-#define STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE cpu_to_le32(0xC01E0342)
-#define STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN cpu_to_le32(0xC01E0343)
-#define STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL cpu_to_le32(0xC01E0344)
-#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION cpu_to_le32(0xC01E0345)
-#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED cpu_to_le32(0xC01E0346)
-#define STATUS_GRAPHICS_INVALID_GAMMA_RAMP cpu_to_le32(0xC01E0347)
-#define STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED cpu_to_le32(0xC01E0348)
-#define STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED cpu_to_le32(0xC01E0349)
-#define STATUS_GRAPHICS_MODE_NOT_IN_MODESET cpu_to_le32(0xC01E034A)
-#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON cpu_to_le32(0xC01E034D)
-#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE cpu_to_le32(0xC01E034E)
-#define STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE cpu_to_le32(0xC01E034F)
-#define STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS cpu_to_le32(0xC01E0350)
-#define STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING cpu_to_le32(0xC01E0352)
-#define STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED cpu_to_le32(0xC01E0353)
-#define STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS cpu_to_le32(0xC01E0354)
-#define STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT cpu_to_le32(0xC01E0355)
-#define STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM cpu_to_le32(0xC01E0356)
-#define STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN cpu_to_le32(0xC01E0357)
-#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT cpu_to_le32(0xC01E0358)
-#define STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED cpu_to_le32(0xC01E0359)
-#define STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION cpu_to_le32(0xC01E035A)
-#define STATUS_GRAPHICS_INVALID_CLIENT_TYPE cpu_to_le32(0xC01E035B)
-#define STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET cpu_to_le32(0xC01E035C)
-#define STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED cpu_to_le32(0xC01E0400)
-#define STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED cpu_to_le32(0xC01E0401)
-#define STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER cpu_to_le32(0xC01E0430)
-#define STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED cpu_to_le32(0xC01E0431)
-#define STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED cpu_to_le32(0xC01E0432)
-#define STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY cpu_to_le32(0xC01E0433)
-#define STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED cpu_to_le32(0xC01E0434)
-#define STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON cpu_to_le32(0xC01E0435)
-#define STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE cpu_to_le32(0xC01E0436)
-#define STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER cpu_to_le32(0xC01E0438)
-#define STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED cpu_to_le32(0xC01E043B)
-#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS cpu_to_le32(0xC01E051C)
-#define STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST cpu_to_le32(0xC01E051D)
-#define STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR cpu_to_le32(0xC01E051E)
-#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS cpu_to_le32(0xC01E051F)
-#define STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED cpu_to_le32(0xC01E0520)
-#define STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST cpu_to_le32(0xC01E0521)
-#define STATUS_GRAPHICS_OPM_NOT_SUPPORTED cpu_to_le32(0xC01E0500)
-#define STATUS_GRAPHICS_COPP_NOT_SUPPORTED cpu_to_le32(0xC01E0501)
-#define STATUS_GRAPHICS_UAB_NOT_SUPPORTED cpu_to_le32(0xC01E0502)
-#define STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS cpu_to_le32(0xC01E0503)
-#define STATUS_GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL cpu_to_le32(0xC01E0504)
-#define STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST cpu_to_le32(0xC01E0505)
-#define STATUS_GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME cpu_to_le32(0xC01E0506)
-#define STATUS_GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP cpu_to_le32(0xC01E0507)
-#define STATUS_GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED cpu_to_le32(0xC01E0508)
-#define STATUS_GRAPHICS_OPM_INVALID_POINTER cpu_to_le32(0xC01E050A)
-#define STATUS_GRAPHICS_OPM_INTERNAL_ERROR cpu_to_le32(0xC01E050B)
-#define STATUS_GRAPHICS_OPM_INVALID_HANDLE cpu_to_le32(0xC01E050C)
-#define STATUS_GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE cpu_to_le32(0xC01E050D)
-#define STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH cpu_to_le32(0xC01E050E)
-#define STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED cpu_to_le32(0xC01E050F)
-#define STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED cpu_to_le32(0xC01E0510)
-#define STATUS_GRAPHICS_PVP_HFS_FAILED cpu_to_le32(0xC01E0511)
-#define STATUS_GRAPHICS_OPM_INVALID_SRM cpu_to_le32(0xC01E0512)
-#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP cpu_to_le32(0xC01E0513)
-#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP cpu_to_le32(0xC01E0514)
-#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA cpu_to_le32(0xC01E0515)
-#define STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET cpu_to_le32(0xC01E0516)
-#define STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH cpu_to_le32(0xC01E0517)
-#define STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE cpu_to_le32(0xC01E0518)
-#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS cpu_to_le32(0xC01E051A)
-#define STATUS_GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS cpu_to_le32(0xC01E051B)
-#define STATUS_GRAPHICS_I2C_NOT_SUPPORTED cpu_to_le32(0xC01E0580)
-#define STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST cpu_to_le32(0xC01E0581)
-#define STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA cpu_to_le32(0xC01E0582)
-#define STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA cpu_to_le32(0xC01E0583)
-#define STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED cpu_to_le32(0xC01E0584)
-#define STATUS_GRAPHICS_DDCCI_INVALID_DATA cpu_to_le32(0xC01E0585)
-#define STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE cpu_to_le32(0xC01E0586)
-#define STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING cpu_to_le32(0xC01E0587)
-#define STATUS_GRAPHICS_MCA_INTERNAL_ERROR cpu_to_le32(0xC01E0588)
-#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND cpu_to_le32(0xC01E0589)
-#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH cpu_to_le32(0xC01E058A)
-#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM cpu_to_le32(0xC01E058B)
-#define STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE cpu_to_le32(0xC01E058C)
-#define STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS cpu_to_le32(0xC01E058D)
-#define STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED cpu_to_le32(0xC01E05E0)
-#define STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME cpu_to_le32(0xC01E05E1)
-#define STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP cpu_to_le32(0xC01E05E2)
-#define STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED cpu_to_le32(0xC01E05E3)
-#define STATUS_GRAPHICS_INVALID_POINTER cpu_to_le32(0xC01E05E4)
-#define STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE cpu_to_le32(0xC01E05E5)
-#define STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL cpu_to_le32(0xC01E05E6)
-#define STATUS_GRAPHICS_INTERNAL_ERROR cpu_to_le32(0xC01E05E7)
-#define STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS cpu_to_le32(0xC01E05E8)
-#define STATUS_FVE_LOCKED_VOLUME cpu_to_le32(0xC0210000)
-#define STATUS_FVE_NOT_ENCRYPTED cpu_to_le32(0xC0210001)
-#define STATUS_FVE_BAD_INFORMATION cpu_to_le32(0xC0210002)
-#define STATUS_FVE_TOO_SMALL cpu_to_le32(0xC0210003)
-#define STATUS_FVE_FAILED_WRONG_FS cpu_to_le32(0xC0210004)
-#define STATUS_FVE_FAILED_BAD_FS cpu_to_le32(0xC0210005)
-#define STATUS_FVE_FS_NOT_EXTENDED cpu_to_le32(0xC0210006)
-#define STATUS_FVE_FS_MOUNTED cpu_to_le32(0xC0210007)
-#define STATUS_FVE_NO_LICENSE cpu_to_le32(0xC0210008)
-#define STATUS_FVE_ACTION_NOT_ALLOWED cpu_to_le32(0xC0210009)
-#define STATUS_FVE_BAD_DATA cpu_to_le32(0xC021000A)
-#define STATUS_FVE_VOLUME_NOT_BOUND cpu_to_le32(0xC021000B)
-#define STATUS_FVE_NOT_DATA_VOLUME cpu_to_le32(0xC021000C)
-#define STATUS_FVE_CONV_READ_ERROR cpu_to_le32(0xC021000D)
-#define STATUS_FVE_CONV_WRITE_ERROR cpu_to_le32(0xC021000E)
-#define STATUS_FVE_OVERLAPPED_UPDATE cpu_to_le32(0xC021000F)
-#define STATUS_FVE_FAILED_SECTOR_SIZE cpu_to_le32(0xC0210010)
-#define STATUS_FVE_FAILED_AUTHENTICATION cpu_to_le32(0xC0210011)
-#define STATUS_FVE_NOT_OS_VOLUME cpu_to_le32(0xC0210012)
-#define STATUS_FVE_KEYFILE_NOT_FOUND cpu_to_le32(0xC0210013)
-#define STATUS_FVE_KEYFILE_INVALID cpu_to_le32(0xC0210014)
-#define STATUS_FVE_KEYFILE_NO_VMK cpu_to_le32(0xC0210015)
-#define STATUS_FVE_TPM_DISABLED cpu_to_le32(0xC0210016)
-#define STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO cpu_to_le32(0xC0210017)
-#define STATUS_FVE_TPM_INVALID_PCR cpu_to_le32(0xC0210018)
-#define STATUS_FVE_TPM_NO_VMK cpu_to_le32(0xC0210019)
-#define STATUS_FVE_PIN_INVALID cpu_to_le32(0xC021001A)
-#define STATUS_FVE_AUTH_INVALID_APPLICATION cpu_to_le32(0xC021001B)
-#define STATUS_FVE_AUTH_INVALID_CONFIG cpu_to_le32(0xC021001C)
-#define STATUS_FVE_DEBUGGER_ENABLED cpu_to_le32(0xC021001D)
-#define STATUS_FVE_DRY_RUN_FAILED cpu_to_le32(0xC021001E)
-#define STATUS_FVE_BAD_METADATA_POINTER cpu_to_le32(0xC021001F)
-#define STATUS_FVE_OLD_METADATA_COPY cpu_to_le32(0xC0210020)
-#define STATUS_FVE_REBOOT_REQUIRED cpu_to_le32(0xC0210021)
-#define STATUS_FVE_RAW_ACCESS cpu_to_le32(0xC0210022)
-#define STATUS_FVE_RAW_BLOCKED cpu_to_le32(0xC0210023)
-#define STATUS_FWP_CALLOUT_NOT_FOUND cpu_to_le32(0xC0220001)
-#define STATUS_FWP_CONDITION_NOT_FOUND cpu_to_le32(0xC0220002)
-#define STATUS_FWP_FILTER_NOT_FOUND cpu_to_le32(0xC0220003)
-#define STATUS_FWP_LAYER_NOT_FOUND cpu_to_le32(0xC0220004)
-#define STATUS_FWP_PROVIDER_NOT_FOUND cpu_to_le32(0xC0220005)
-#define STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND cpu_to_le32(0xC0220006)
-#define STATUS_FWP_SUBLAYER_NOT_FOUND cpu_to_le32(0xC0220007)
-#define STATUS_FWP_NOT_FOUND cpu_to_le32(0xC0220008)
-#define STATUS_FWP_ALREADY_EXISTS cpu_to_le32(0xC0220009)
-#define STATUS_FWP_IN_USE cpu_to_le32(0xC022000A)
-#define STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS cpu_to_le32(0xC022000B)
-#define STATUS_FWP_WRONG_SESSION cpu_to_le32(0xC022000C)
-#define STATUS_FWP_NO_TXN_IN_PROGRESS cpu_to_le32(0xC022000D)
-#define STATUS_FWP_TXN_IN_PROGRESS cpu_to_le32(0xC022000E)
-#define STATUS_FWP_TXN_ABORTED cpu_to_le32(0xC022000F)
-#define STATUS_FWP_SESSION_ABORTED cpu_to_le32(0xC0220010)
-#define STATUS_FWP_INCOMPATIBLE_TXN cpu_to_le32(0xC0220011)
-#define STATUS_FWP_TIMEOUT cpu_to_le32(0xC0220012)
-#define STATUS_FWP_NET_EVENTS_DISABLED cpu_to_le32(0xC0220013)
-#define STATUS_FWP_INCOMPATIBLE_LAYER cpu_to_le32(0xC0220014)
-#define STATUS_FWP_KM_CLIENTS_ONLY cpu_to_le32(0xC0220015)
-#define STATUS_FWP_LIFETIME_MISMATCH cpu_to_le32(0xC0220016)
-#define STATUS_FWP_BUILTIN_OBJECT cpu_to_le32(0xC0220017)
-#define STATUS_FWP_TOO_MANY_BOOTTIME_FILTERS cpu_to_le32(0xC0220018)
-#define STATUS_FWP_TOO_MANY_CALLOUTS cpu_to_le32(0xC0220018)
-#define STATUS_FWP_NOTIFICATION_DROPPED cpu_to_le32(0xC0220019)
-#define STATUS_FWP_TRAFFIC_MISMATCH cpu_to_le32(0xC022001A)
-#define STATUS_FWP_INCOMPATIBLE_SA_STATE cpu_to_le32(0xC022001B)
-#define STATUS_FWP_NULL_POINTER cpu_to_le32(0xC022001C)
-#define STATUS_FWP_INVALID_ENUMERATOR cpu_to_le32(0xC022001D)
-#define STATUS_FWP_INVALID_FLAGS cpu_to_le32(0xC022001E)
-#define STATUS_FWP_INVALID_NET_MASK cpu_to_le32(0xC022001F)
-#define STATUS_FWP_INVALID_RANGE cpu_to_le32(0xC0220020)
-#define STATUS_FWP_INVALID_INTERVAL cpu_to_le32(0xC0220021)
-#define STATUS_FWP_ZERO_LENGTH_ARRAY cpu_to_le32(0xC0220022)
-#define STATUS_FWP_NULL_DISPLAY_NAME cpu_to_le32(0xC0220023)
-#define STATUS_FWP_INVALID_ACTION_TYPE cpu_to_le32(0xC0220024)
-#define STATUS_FWP_INVALID_WEIGHT cpu_to_le32(0xC0220025)
-#define STATUS_FWP_MATCH_TYPE_MISMATCH cpu_to_le32(0xC0220026)
-#define STATUS_FWP_TYPE_MISMATCH cpu_to_le32(0xC0220027)
-#define STATUS_FWP_OUT_OF_BOUNDS cpu_to_le32(0xC0220028)
-#define STATUS_FWP_RESERVED cpu_to_le32(0xC0220029)
-#define STATUS_FWP_DUPLICATE_CONDITION cpu_to_le32(0xC022002A)
-#define STATUS_FWP_DUPLICATE_KEYMOD cpu_to_le32(0xC022002B)
-#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER cpu_to_le32(0xC022002C)
-#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER cpu_to_le32(0xC022002D)
-#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER cpu_to_le32(0xC022002E)
-#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT cpu_to_le32(0xC022002F)
-#define STATUS_FWP_INCOMPATIBLE_AUTH_METHOD cpu_to_le32(0xC0220030)
-#define STATUS_FWP_INCOMPATIBLE_DH_GROUP cpu_to_le32(0xC0220031)
-#define STATUS_FWP_EM_NOT_SUPPORTED cpu_to_le32(0xC0220032)
-#define STATUS_FWP_NEVER_MATCH cpu_to_le32(0xC0220033)
-#define STATUS_FWP_PROVIDER_CONTEXT_MISMATCH cpu_to_le32(0xC0220034)
-#define STATUS_FWP_INVALID_PARAMETER cpu_to_le32(0xC0220035)
-#define STATUS_FWP_TOO_MANY_SUBLAYERS cpu_to_le32(0xC0220036)
-#define STATUS_FWP_CALLOUT_NOTIFICATION_FAILED cpu_to_le32(0xC0220037)
-#define STATUS_FWP_INCOMPATIBLE_AUTH_CONFIG cpu_to_le32(0xC0220038)
-#define STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG cpu_to_le32(0xC0220039)
-#define STATUS_FWP_TCPIP_NOT_READY cpu_to_le32(0xC0220100)
-#define STATUS_FWP_INJECT_HANDLE_CLOSING cpu_to_le32(0xC0220101)
-#define STATUS_FWP_INJECT_HANDLE_STALE cpu_to_le32(0xC0220102)
-#define STATUS_FWP_CANNOT_PEND cpu_to_le32(0xC0220103)
-#define STATUS_NDIS_CLOSING cpu_to_le32(0xC0230002)
-#define STATUS_NDIS_BAD_VERSION cpu_to_le32(0xC0230004)
-#define STATUS_NDIS_BAD_CHARACTERISTICS cpu_to_le32(0xC0230005)
-#define STATUS_NDIS_ADAPTER_NOT_FOUND cpu_to_le32(0xC0230006)
-#define STATUS_NDIS_OPEN_FAILED cpu_to_le32(0xC0230007)
-#define STATUS_NDIS_DEVICE_FAILED cpu_to_le32(0xC0230008)
-#define STATUS_NDIS_MULTICAST_FULL cpu_to_le32(0xC0230009)
-#define STATUS_NDIS_MULTICAST_EXISTS cpu_to_le32(0xC023000A)
-#define STATUS_NDIS_MULTICAST_NOT_FOUND cpu_to_le32(0xC023000B)
-#define STATUS_NDIS_REQUEST_ABORTED cpu_to_le32(0xC023000C)
-#define STATUS_NDIS_RESET_IN_PROGRESS cpu_to_le32(0xC023000D)
-#define STATUS_NDIS_INVALID_PACKET cpu_to_le32(0xC023000F)
-#define STATUS_NDIS_INVALID_DEVICE_REQUEST cpu_to_le32(0xC0230010)
-#define STATUS_NDIS_ADAPTER_NOT_READY cpu_to_le32(0xC0230011)
-#define STATUS_NDIS_INVALID_LENGTH cpu_to_le32(0xC0230014)
-#define STATUS_NDIS_INVALID_DATA cpu_to_le32(0xC0230015)
-#define STATUS_NDIS_BUFFER_TOO_SHORT cpu_to_le32(0xC0230016)
-#define STATUS_NDIS_INVALID_OID cpu_to_le32(0xC0230017)
-#define STATUS_NDIS_ADAPTER_REMOVED cpu_to_le32(0xC0230018)
-#define STATUS_NDIS_UNSUPPORTED_MEDIA cpu_to_le32(0xC0230019)
-#define STATUS_NDIS_GROUP_ADDRESS_IN_USE cpu_to_le32(0xC023001A)
-#define STATUS_NDIS_FILE_NOT_FOUND cpu_to_le32(0xC023001B)
-#define STATUS_NDIS_ERROR_READING_FILE cpu_to_le32(0xC023001C)
-#define STATUS_NDIS_ALREADY_MAPPED cpu_to_le32(0xC023001D)
-#define STATUS_NDIS_RESOURCE_CONFLICT cpu_to_le32(0xC023001E)
-#define STATUS_NDIS_MEDIA_DISCONNECTED cpu_to_le32(0xC023001F)
-#define STATUS_NDIS_INVALID_ADDRESS cpu_to_le32(0xC0230022)
-#define STATUS_NDIS_PAUSED cpu_to_le32(0xC023002A)
-#define STATUS_NDIS_INTERFACE_NOT_FOUND cpu_to_le32(0xC023002B)
-#define STATUS_NDIS_UNSUPPORTED_REVISION cpu_to_le32(0xC023002C)
-#define STATUS_NDIS_INVALID_PORT cpu_to_le32(0xC023002D)
-#define STATUS_NDIS_INVALID_PORT_STATE cpu_to_le32(0xC023002E)
-#define STATUS_NDIS_LOW_POWER_STATE cpu_to_le32(0xC023002F)
-#define STATUS_NDIS_NOT_SUPPORTED cpu_to_le32(0xC02300BB)
-#define STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED cpu_to_le32(0xC0232000)
-#define STATUS_NDIS_DOT11_MEDIA_IN_USE cpu_to_le32(0xC0232001)
-#define STATUS_NDIS_DOT11_POWER_STATE_INVALID cpu_to_le32(0xC0232002)
-#define STATUS_IPSEC_BAD_SPI cpu_to_le32(0xC0360001)
-#define STATUS_IPSEC_SA_LIFETIME_EXPIRED cpu_to_le32(0xC0360002)
-#define STATUS_IPSEC_WRONG_SA cpu_to_le32(0xC0360003)
-#define STATUS_IPSEC_REPLAY_CHECK_FAILED cpu_to_le32(0xC0360004)
-#define STATUS_IPSEC_INVALID_PACKET cpu_to_le32(0xC0360005)
-#define STATUS_IPSEC_INTEGRITY_CHECK_FAILED cpu_to_le32(0xC0360006)
-#define STATUS_IPSEC_CLEAR_TEXT_DROP cpu_to_le32(0xC0360007)
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
deleted file mode 100644
index 790acf65a092..000000000000
--- a/fs/cifs/smb2transport.c
+++ /dev/null
@@ -1,934 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002, 2011
- * Etersoft, 2012
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Jeremy Allison (jra@samba.org) 2006
- * Pavel Shilovsky (pshilovsky@samba.org) 2012
- *
- */
-
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/wait.h>
-#include <linux/net.h>
-#include <linux/delay.h>
-#include <linux/uaccess.h>
-#include <asm/processor.h>
-#include <linux/mempool.h>
-#include <linux/highmem.h>
-#include <crypto/aead.h>
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "smb2proto.h"
-#include "cifs_debug.h"
-#include "smb2status.h"
-#include "smb2glob.h"
-
-static int
-smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
-{
- struct cifs_secmech *p = &server->secmech;
- int rc;
-
- rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);
- if (rc)
- goto err;
-
- rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);
- if (rc)
- goto err;
-
- return 0;
-err:
- cifs_free_hash(&p->hmacsha256);
- return rc;
-}
-
-int
-smb311_crypto_shash_allocate(struct TCP_Server_Info *server)
-{
- struct cifs_secmech *p = &server->secmech;
- int rc = 0;
-
- rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);
- if (rc)
- return rc;
-
- rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);
- if (rc)
- goto err;
-
- rc = cifs_alloc_hash("sha512", &p->sha512);
- if (rc)
- goto err;
-
- return 0;
-
-err:
- cifs_free_hash(&p->aes_cmac);
- cifs_free_hash(&p->hmacsha256);
- return rc;
-}
-
-
-static
-int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
-{
- struct cifs_chan *chan;
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses = NULL;
- int i;
- int rc = 0;
- bool is_binding = false;
-
- spin_lock(&cifs_tcp_ses_lock);
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
- if (ses->Suid == ses_id)
- goto found;
- }
- cifs_server_dbg(VFS, "%s: Could not find session 0x%llx\n",
- __func__, ses_id);
- rc = -ENOENT;
- goto out;
-
-found:
- spin_lock(&ses->ses_lock);
- spin_lock(&ses->chan_lock);
-
- is_binding = (cifs_chan_needs_reconnect(ses, server) &&
- ses->ses_status == SES_GOOD);
- if (is_binding) {
- /*
- * If we are in the process of binding a new channel
- * to an existing session, use the master connection
- * session key
- */
- memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
- goto out;
- }
-
- /*
- * Otherwise, use the channel key.
- */
-
- for (i = 0; i < ses->chan_count; i++) {
- chan = ses->chans + i;
- if (chan->server == server) {
- memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
- goto out;
- }
- }
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
-
- cifs_dbg(VFS,
- "%s: Could not find channel signing key for session 0x%llx\n",
- __func__, ses_id);
- rc = -ENOENT;
-
-out:
- spin_unlock(&cifs_tcp_ses_lock);
- return rc;
-}
-
-static struct cifs_ses *
-smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
-{
- struct TCP_Server_Info *pserver;
- struct cifs_ses *ses;
-
- /* If server is a channel, select the primary channel */
- pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
-
- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
- if (ses->Suid != ses_id)
- continue;
- ++ses->ses_count;
- return ses;
- }
-
- return NULL;
-}
-
-struct cifs_ses *
-smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
-{
- struct cifs_ses *ses;
-
- spin_lock(&cifs_tcp_ses_lock);
- ses = smb2_find_smb_ses_unlocked(server, ses_id);
- spin_unlock(&cifs_tcp_ses_lock);
-
- return ses;
-}
-
-static struct cifs_tcon *
-smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
-{
- struct cifs_tcon *tcon;
-
- list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
- if (tcon->tid != tid)
- continue;
- ++tcon->tc_count;
- return tcon;
- }
-
- return NULL;
-}
-
-/*
- * Obtain tcon corresponding to the tid in the given
- * cifs_ses
- */
-
-struct cifs_tcon *
-smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
-{
- struct cifs_ses *ses;
- struct cifs_tcon *tcon;
-
- spin_lock(&cifs_tcp_ses_lock);
- ses = smb2_find_smb_ses_unlocked(server, ses_id);
- if (!ses) {
- spin_unlock(&cifs_tcp_ses_lock);
- return NULL;
- }
- tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
- if (!tcon) {
- cifs_put_smb_ses(ses);
- spin_unlock(&cifs_tcp_ses_lock);
- return NULL;
- }
- spin_unlock(&cifs_tcp_ses_lock);
- /* tcon already has a ref to ses, so we don't need ses anymore */
- cifs_put_smb_ses(ses);
-
- return tcon;
-}
-
-int
-smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
- bool allocate_crypto)
-{
- int rc;
- unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
- unsigned char *sigptr = smb2_signature;
- struct kvec *iov = rqst->rq_iov;
- struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
- struct cifs_ses *ses;
- struct shash_desc *shash = NULL;
- struct smb_rqst drqst;
-
- ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId));
- if (unlikely(!ses)) {
- cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
- return -ENOENT;
- }
-
- memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
- memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
-
- if (allocate_crypto) {
- rc = cifs_alloc_hash("hmac(sha256)", &shash);
- if (rc) {
- cifs_server_dbg(VFS,
- "%s: sha256 alloc failed\n", __func__);
- goto out;
- }
- } else {
- shash = server->secmech.hmacsha256;
- }
-
- rc = crypto_shash_setkey(shash->tfm, ses->auth_key.response,
- SMB2_NTLMV2_SESSKEY_SIZE);
- if (rc) {
- cifs_server_dbg(VFS,
- "%s: Could not update with response\n",
- __func__);
- goto out;
- }
-
- rc = crypto_shash_init(shash);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);
- goto out;
- }
-
- /*
- * For SMB2+, __cifs_calc_signature() expects to sign only the actual
- * data, that is, iov[0] should not contain a rfc1002 length.
- *
- * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
- * __cifs_calc_signature().
- */
- drqst = *rqst;
- if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
- rc = crypto_shash_update(shash, iov[0].iov_base,
- iov[0].iov_len);
- if (rc) {
- cifs_server_dbg(VFS,
- "%s: Could not update with payload\n",
- __func__);
- goto out;
- }
- drqst.rq_iov++;
- drqst.rq_nvec--;
- }
-
- rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
- if (!rc)
- memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
-
-out:
- if (allocate_crypto)
- cifs_free_hash(&shash);
- if (ses)
- cifs_put_smb_ses(ses);
- return rc;
-}
-
-static int generate_key(struct cifs_ses *ses, struct kvec label,
- struct kvec context, __u8 *key, unsigned int key_size)
-{
- unsigned char zero = 0x0;
- __u8 i[4] = {0, 0, 0, 1};
- __u8 L128[4] = {0, 0, 0, 128};
- __u8 L256[4] = {0, 0, 1, 0};
- int rc = 0;
- unsigned char prfhash[SMB2_HMACSHA256_SIZE];
- unsigned char *hashptr = prfhash;
- struct TCP_Server_Info *server = ses->server;
-
- memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
- memset(key, 0x0, key_size);
-
- rc = smb3_crypto_shash_allocate(server);
- if (rc) {
- cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_setkey(server->secmech.hmacsha256->tfm,
- ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__);
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_init(server->secmech.hmacsha256);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_update(server->secmech.hmacsha256, i, 4);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__);
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_update(server->secmech.hmacsha256, label.iov_base, label.iov_len);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__);
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_update(server->secmech.hmacsha256, &zero, 1);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__);
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_update(server->secmech.hmacsha256, context.iov_base, context.iov_len);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__);
- goto smb3signkey_ret;
- }
-
- if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
- (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
- rc = crypto_shash_update(server->secmech.hmacsha256, L256, 4);
- } else {
- rc = crypto_shash_update(server->secmech.hmacsha256, L128, 4);
- }
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_final(server->secmech.hmacsha256, hashptr);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
- goto smb3signkey_ret;
- }
-
- memcpy(key, hashptr, key_size);
-
-smb3signkey_ret:
- return rc;
-}
-
-struct derivation {
- struct kvec label;
- struct kvec context;
-};
-
-struct derivation_triplet {
- struct derivation signing;
- struct derivation encryption;
- struct derivation decryption;
-};
-
-static int
-generate_smb3signingkey(struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const struct derivation_triplet *ptriplet)
-{
- int rc;
- bool is_binding = false;
- int chan_index = 0;
-
- spin_lock(&ses->ses_lock);
- spin_lock(&ses->chan_lock);
- is_binding = (cifs_chan_needs_reconnect(ses, server) &&
- ses->ses_status == SES_GOOD);
-
- chan_index = cifs_ses_get_chan_index(ses, server);
- /* TODO: introduce ref counting for channels when the can be freed */
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
-
- /*
- * All channels use the same encryption/decryption keys but
- * they have their own signing key.
- *
- * When we generate the keys, check if it is for a new channel
- * (binding) in which case we only need to generate a signing
- * key and store it in the channel as to not overwrite the
- * master connection signing key stored in the session
- */
-
- if (is_binding) {
- rc = generate_key(ses, ptriplet->signing.label,
- ptriplet->signing.context,
- ses->chans[chan_index].signkey,
- SMB3_SIGN_KEY_SIZE);
- if (rc)
- return rc;
- } else {
- rc = generate_key(ses, ptriplet->signing.label,
- ptriplet->signing.context,
- ses->smb3signingkey,
- SMB3_SIGN_KEY_SIZE);
- if (rc)
- return rc;
-
- /* safe to access primary channel, since it will never go away */
- spin_lock(&ses->chan_lock);
- memcpy(ses->chans[chan_index].signkey, ses->smb3signingkey,
- SMB3_SIGN_KEY_SIZE);
- spin_unlock(&ses->chan_lock);
-
- rc = generate_key(ses, ptriplet->encryption.label,
- ptriplet->encryption.context,
- ses->smb3encryptionkey,
- SMB3_ENC_DEC_KEY_SIZE);
- rc = generate_key(ses, ptriplet->decryption.label,
- ptriplet->decryption.context,
- ses->smb3decryptionkey,
- SMB3_ENC_DEC_KEY_SIZE);
- if (rc)
- return rc;
- }
-
- if (rc)
- return rc;
-
-#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
- cifs_dbg(VFS, "%s: dumping generated AES session keys\n", __func__);
- /*
- * The session id is opaque in terms of endianness, so we can't
- * print it as a long long. we dump it as we got it on the wire
- */
- cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid),
- &ses->Suid);
- cifs_dbg(VFS, "Cipher type %d\n", server->cipher_type);
- cifs_dbg(VFS, "Session Key %*ph\n",
- SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
- cifs_dbg(VFS, "Signing Key %*ph\n",
- SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
- if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
- (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
- cifs_dbg(VFS, "ServerIn Key %*ph\n",
- SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3encryptionkey);
- cifs_dbg(VFS, "ServerOut Key %*ph\n",
- SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3decryptionkey);
- } else {
- cifs_dbg(VFS, "ServerIn Key %*ph\n",
- SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);
- cifs_dbg(VFS, "ServerOut Key %*ph\n",
- SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey);
- }
-#endif
- return rc;
-}
-
-int
-generate_smb30signingkey(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-
-{
- struct derivation_triplet triplet;
- struct derivation *d;
-
- d = &triplet.signing;
- d->label.iov_base = "SMB2AESCMAC";
- d->label.iov_len = 12;
- d->context.iov_base = "SmbSign";
- d->context.iov_len = 8;
-
- d = &triplet.encryption;
- d->label.iov_base = "SMB2AESCCM";
- d->label.iov_len = 11;
- d->context.iov_base = "ServerIn ";
- d->context.iov_len = 10;
-
- d = &triplet.decryption;
- d->label.iov_base = "SMB2AESCCM";
- d->label.iov_len = 11;
- d->context.iov_base = "ServerOut";
- d->context.iov_len = 10;
-
- return generate_smb3signingkey(ses, server, &triplet);
-}
-
-int
-generate_smb311signingkey(struct cifs_ses *ses,
- struct TCP_Server_Info *server)
-
-{
- struct derivation_triplet triplet;
- struct derivation *d;
-
- d = &triplet.signing;
- d->label.iov_base = "SMBSigningKey";
- d->label.iov_len = 14;
- d->context.iov_base = ses->preauth_sha_hash;
- d->context.iov_len = 64;
-
- d = &triplet.encryption;
- d->label.iov_base = "SMBC2SCipherKey";
- d->label.iov_len = 16;
- d->context.iov_base = ses->preauth_sha_hash;
- d->context.iov_len = 64;
-
- d = &triplet.decryption;
- d->label.iov_base = "SMBS2CCipherKey";
- d->label.iov_len = 16;
- d->context.iov_base = ses->preauth_sha_hash;
- d->context.iov_len = 64;
-
- return generate_smb3signingkey(ses, server, &triplet);
-}
-
-int
-smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
- bool allocate_crypto)
-{
- int rc;
- unsigned char smb3_signature[SMB2_CMACAES_SIZE];
- unsigned char *sigptr = smb3_signature;
- struct kvec *iov = rqst->rq_iov;
- struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
- struct shash_desc *shash = NULL;
- struct smb_rqst drqst;
- u8 key[SMB3_SIGN_KEY_SIZE];
-
- rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key);
- if (unlikely(rc)) {
- cifs_server_dbg(VFS, "%s: Could not get signing key\n", __func__);
- return rc;
- }
-
- if (allocate_crypto) {
- rc = cifs_alloc_hash("cmac(aes)", &shash);
- if (rc)
- return rc;
- } else {
- shash = server->secmech.aes_cmac;
- }
-
- memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
- memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
-
- rc = crypto_shash_setkey(shash->tfm, key, SMB2_CMACAES_SIZE);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
- goto out;
- }
-
- /*
- * we already allocate aes_cmac when we init smb3 signing key,
- * so unlike smb2 case we do not have to check here if secmech are
- * initialized
- */
- rc = crypto_shash_init(shash);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
- goto out;
- }
-
- /*
- * For SMB2+, __cifs_calc_signature() expects to sign only the actual
- * data, that is, iov[0] should not contain a rfc1002 length.
- *
- * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
- * __cifs_calc_signature().
- */
- drqst = *rqst;
- if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
- rc = crypto_shash_update(shash, iov[0].iov_base,
- iov[0].iov_len);
- if (rc) {
- cifs_server_dbg(VFS, "%s: Could not update with payload\n",
- __func__);
- goto out;
- }
- drqst.rq_iov++;
- drqst.rq_nvec--;
- }
-
- rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
- if (!rc)
- memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
-
-out:
- if (allocate_crypto)
- cifs_free_hash(&shash);
- return rc;
-}
-
-/* must be called with server->srv_mutex held */
-static int
-smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
-{
- int rc = 0;
- struct smb2_hdr *shdr;
- struct smb2_sess_setup_req *ssr;
- bool is_binding;
- bool is_signed;
-
- shdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
- ssr = (struct smb2_sess_setup_req *)shdr;
-
- is_binding = shdr->Command == SMB2_SESSION_SETUP &&
- (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING);
- is_signed = shdr->Flags & SMB2_FLAGS_SIGNED;
-
- if (!is_signed)
- return 0;
- spin_lock(&server->srv_lock);
- if (server->ops->need_neg &&
- server->ops->need_neg(server)) {
- spin_unlock(&server->srv_lock);
- return 0;
- }
- spin_unlock(&server->srv_lock);
- if (!is_binding && !server->session_estab) {
- strncpy(shdr->Signature, "BSRSPYL", 8);
- return 0;
- }
-
- rc = server->ops->calc_signature(rqst, server, false);
-
- return rc;
-}
-
-int
-smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
-{
- unsigned int rc;
- char server_response_sig[SMB2_SIGNATURE_SIZE];
- struct smb2_hdr *shdr =
- (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
-
- if ((shdr->Command == SMB2_NEGOTIATE) ||
- (shdr->Command == SMB2_SESSION_SETUP) ||
- (shdr->Command == SMB2_OPLOCK_BREAK) ||
- server->ignore_signature ||
- (!server->session_estab))
- return 0;
-
- /*
- * BB what if signatures are supposed to be on for session but
- * server does not send one? BB
- */
-
- /* Do not need to verify session setups with signature "BSRSPYL " */
- if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
- cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
- shdr->Command);
-
- /*
- * Save off the origiginal signature so we can modify the smb and check
- * our calculated signature against what the server sent.
- */
- memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);
-
- memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
-
- rc = server->ops->calc_signature(rqst, server, true);
-
- if (rc)
- return rc;
-
- if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE)) {
- cifs_dbg(VFS, "sign fail cmd 0x%x message id 0x%llx\n",
- shdr->Command, shdr->MessageId);
- return -EACCES;
- } else
- return 0;
-}
-
-/*
- * Set message id for the request. Should be called after wait_for_free_request
- * and when srv_mutex is held.
- */
-static inline void
-smb2_seq_num_into_buf(struct TCP_Server_Info *server,
- struct smb2_hdr *shdr)
-{
- unsigned int i, num = le16_to_cpu(shdr->CreditCharge);
-
- shdr->MessageId = get_next_mid64(server);
- /* skip message numbers according to CreditCharge field */
- for (i = 1; i < num; i++)
- get_next_mid(server);
-}
-
-static struct mid_q_entry *
-smb2_mid_entry_alloc(const struct smb2_hdr *shdr,
- struct TCP_Server_Info *server)
-{
- struct mid_q_entry *temp;
- unsigned int credits = le16_to_cpu(shdr->CreditCharge);
-
- if (server == NULL) {
- cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
- return NULL;
- }
-
- temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
- memset(temp, 0, sizeof(struct mid_q_entry));
- kref_init(&temp->refcount);
- temp->mid = le64_to_cpu(shdr->MessageId);
- temp->credits = credits > 0 ? credits : 1;
- temp->pid = current->pid;
- temp->command = shdr->Command; /* Always LE */
- temp->when_alloc = jiffies;
- temp->server = server;
-
- /*
- * The default is for the mid to be synchronous, so the
- * default callback just wakes up the current task.
- */
- get_task_struct(current);
- temp->creator = current;
- temp->callback = cifs_wake_up_task;
- temp->callback_data = current;
-
- atomic_inc(&mid_count);
- temp->mid_state = MID_REQUEST_ALLOCATED;
- trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId),
- le64_to_cpu(shdr->SessionId),
- le16_to_cpu(shdr->Command), temp->mid);
- return temp;
-}
-
-static int
-smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server,
- struct smb2_hdr *shdr, struct mid_q_entry **mid)
-{
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsExiting) {
- spin_unlock(&server->srv_lock);
- return -ENOENT;
- }
-
- if (server->tcpStatus == CifsNeedReconnect) {
- spin_unlock(&server->srv_lock);
- cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
- return -EAGAIN;
- }
-
- if (server->tcpStatus == CifsNeedNegotiate &&
- shdr->Command != SMB2_NEGOTIATE) {
- spin_unlock(&server->srv_lock);
- return -EAGAIN;
- }
- spin_unlock(&server->srv_lock);
-
- spin_lock(&ses->ses_lock);
- if (ses->ses_status == SES_NEW) {
- if ((shdr->Command != SMB2_SESSION_SETUP) &&
- (shdr->Command != SMB2_NEGOTIATE)) {
- spin_unlock(&ses->ses_lock);
- return -EAGAIN;
- }
- /* else ok - we are setting up session */
- }
-
- if (ses->ses_status == SES_EXITING) {
- if (shdr->Command != SMB2_LOGOFF) {
- spin_unlock(&ses->ses_lock);
- return -EAGAIN;
- }
- /* else ok - we are shutting down the session */
- }
- spin_unlock(&ses->ses_lock);
-
- *mid = smb2_mid_entry_alloc(shdr, server);
- if (*mid == NULL)
- return -ENOMEM;
- spin_lock(&server->mid_lock);
- list_add_tail(&(*mid)->qhead, &server->pending_mid_q);
- spin_unlock(&server->mid_lock);
-
- return 0;
-}
-
-int
-smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
- bool log_error)
-{
- unsigned int len = mid->resp_buf_size;
- struct kvec iov[1];
- struct smb_rqst rqst = { .rq_iov = iov,
- .rq_nvec = 1 };
-
- iov[0].iov_base = (char *)mid->resp_buf;
- iov[0].iov_len = len;
-
- dump_smb(mid->resp_buf, min_t(u32, 80, len));
- /* convert the length into a more usable form */
- if (len > 24 && server->sign && !mid->decrypted) {
- int rc;
-
- rc = smb2_verify_signature(&rqst, server);
- if (rc)
- cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",
- rc);
- }
-
- return map_smb2_to_linux_error(mid->resp_buf, log_error);
-}
-
-struct mid_q_entry *
-smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server,
- struct smb_rqst *rqst)
-{
- int rc;
- struct smb2_hdr *shdr =
- (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
- struct mid_q_entry *mid;
-
- smb2_seq_num_into_buf(server, shdr);
-
- rc = smb2_get_mid_entry(ses, server, shdr, &mid);
- if (rc) {
- revert_current_mid_from_hdr(server, shdr);
- return ERR_PTR(rc);
- }
-
- rc = smb2_sign_rqst(rqst, server);
- if (rc) {
- revert_current_mid_from_hdr(server, shdr);
- delete_mid(mid);
- return ERR_PTR(rc);
- }
-
- return mid;
-}
-
-struct mid_q_entry *
-smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
-{
- int rc;
- struct smb2_hdr *shdr =
- (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
- struct mid_q_entry *mid;
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsNeedNegotiate &&
- shdr->Command != SMB2_NEGOTIATE) {
- spin_unlock(&server->srv_lock);
- return ERR_PTR(-EAGAIN);
- }
- spin_unlock(&server->srv_lock);
-
- smb2_seq_num_into_buf(server, shdr);
-
- mid = smb2_mid_entry_alloc(shdr, server);
- if (mid == NULL) {
- revert_current_mid_from_hdr(server, shdr);
- return ERR_PTR(-ENOMEM);
- }
-
- rc = smb2_sign_rqst(rqst, server);
- if (rc) {
- revert_current_mid_from_hdr(server, shdr);
- release_mid(mid);
- return ERR_PTR(rc);
- }
-
- return mid;
-}
-
-int
-smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
-{
- struct crypto_aead *tfm;
-
- if (!server->secmech.enc) {
- if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
- (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
- tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
- else
- tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
- if (IS_ERR(tfm)) {
- cifs_server_dbg(VFS, "%s: Failed alloc encrypt aead\n",
- __func__);
- return PTR_ERR(tfm);
- }
- server->secmech.enc = tfm;
- }
-
- if (!server->secmech.dec) {
- if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
- (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
- tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
- else
- tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
- if (IS_ERR(tfm)) {
- crypto_free_aead(server->secmech.enc);
- server->secmech.enc = NULL;
- cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
- __func__);
- return PTR_ERR(tfm);
- }
- server->secmech.dec = tfm;
- }
-
- return 0;
-}
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
deleted file mode 100644
index cf923f211c51..000000000000
--- a/fs/cifs/smbdirect.c
+++ /dev/null
@@ -1,2494 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2017, Microsoft Corporation.
- *
- * Author(s): Long Li <longli@microsoft.com>
- */
-#include <linux/module.h>
-#include <linux/highmem.h>
-#include "smbdirect.h"
-#include "cifs_debug.h"
-#include "cifsproto.h"
-#include "smb2proto.h"
-
-static struct smbd_response *get_empty_queue_buffer(
- struct smbd_connection *info);
-static struct smbd_response *get_receive_buffer(
- struct smbd_connection *info);
-static void put_receive_buffer(
- struct smbd_connection *info,
- struct smbd_response *response);
-static int allocate_receive_buffers(struct smbd_connection *info, int num_buf);
-static void destroy_receive_buffers(struct smbd_connection *info);
-
-static void put_empty_packet(
- struct smbd_connection *info, struct smbd_response *response);
-static void enqueue_reassembly(
- struct smbd_connection *info,
- struct smbd_response *response, int data_length);
-static struct smbd_response *_get_first_reassembly(
- struct smbd_connection *info);
-
-static int smbd_post_recv(
- struct smbd_connection *info,
- struct smbd_response *response);
-
-static int smbd_post_send_empty(struct smbd_connection *info);
-static int smbd_post_send_data(
- struct smbd_connection *info,
- struct kvec *iov, int n_vec, int remaining_data_length);
-static int smbd_post_send_page(struct smbd_connection *info,
- struct page *page, unsigned long offset,
- size_t size, int remaining_data_length);
-
-static void destroy_mr_list(struct smbd_connection *info);
-static int allocate_mr_list(struct smbd_connection *info);
-
-/* SMBD version number */
-#define SMBD_V1 0x0100
-
-/* Port numbers for SMBD transport */
-#define SMB_PORT 445
-#define SMBD_PORT 5445
-
-/* Address lookup and resolve timeout in ms */
-#define RDMA_RESOLVE_TIMEOUT 5000
-
-/* SMBD negotiation timeout in seconds */
-#define SMBD_NEGOTIATE_TIMEOUT 120
-
-/* SMBD minimum receive size and fragmented sized defined in [MS-SMBD] */
-#define SMBD_MIN_RECEIVE_SIZE 128
-#define SMBD_MIN_FRAGMENTED_SIZE 131072
-
-/*
- * Default maximum number of RDMA read/write outstanding on this connection
- * This value is possibly decreased during QP creation on hardware limit
- */
-#define SMBD_CM_RESPONDER_RESOURCES 32
-
-/* Maximum number of retries on data transfer operations */
-#define SMBD_CM_RETRY 6
-/* No need to retry on Receiver Not Ready since SMBD manages credits */
-#define SMBD_CM_RNR_RETRY 0
-
-/*
- * User configurable initial values per SMBD transport connection
- * as defined in [MS-SMBD] 3.1.1.1
- * Those may change after a SMBD negotiation
- */
-/* The local peer's maximum number of credits to grant to the peer */
-int smbd_receive_credit_max = 255;
-
-/* The remote peer's credit request of local peer */
-int smbd_send_credit_target = 255;
-
-/* The maximum single message size can be sent to remote peer */
-int smbd_max_send_size = 1364;
-
-/* The maximum fragmented upper-layer payload receive size supported */
-int smbd_max_fragmented_recv_size = 1024 * 1024;
-
-/* The maximum single-message size which can be received */
-int smbd_max_receive_size = 1364;
-
-/* The timeout to initiate send of a keepalive message on idle */
-int smbd_keep_alive_interval = 120;
-
-/*
- * User configurable initial values for RDMA transport
- * The actual values used may be lower and are limited to hardware capabilities
- */
-/* Default maximum number of pages in a single RDMA write/read */
-int smbd_max_frmr_depth = 2048;
-
-/* If payload is less than this byte, use RDMA send/recv not read/write */
-int rdma_readwrite_threshold = 4096;
-
-/* Transport logging functions
- * Logging are defined as classes. They can be OR'ed to define the actual
- * logging level via module parameter smbd_logging_class
- * e.g. cifs.smbd_logging_class=0xa0 will log all log_rdma_recv() and
- * log_rdma_event()
- */
-#define LOG_OUTGOING 0x1
-#define LOG_INCOMING 0x2
-#define LOG_READ 0x4
-#define LOG_WRITE 0x8
-#define LOG_RDMA_SEND 0x10
-#define LOG_RDMA_RECV 0x20
-#define LOG_KEEP_ALIVE 0x40
-#define LOG_RDMA_EVENT 0x80
-#define LOG_RDMA_MR 0x100
-static unsigned int smbd_logging_class;
-module_param(smbd_logging_class, uint, 0644);
-MODULE_PARM_DESC(smbd_logging_class,
- "Logging class for SMBD transport 0x0 to 0x100");
-
-#define ERR 0x0
-#define INFO 0x1
-static unsigned int smbd_logging_level = ERR;
-module_param(smbd_logging_level, uint, 0644);
-MODULE_PARM_DESC(smbd_logging_level,
- "Logging level for SMBD transport, 0 (default): error, 1: info");
-
-#define log_rdma(level, class, fmt, args...) \
-do { \
- if (level <= smbd_logging_level || class & smbd_logging_class) \
- cifs_dbg(VFS, "%s:%d " fmt, __func__, __LINE__, ##args);\
-} while (0)
-
-#define log_outgoing(level, fmt, args...) \
- log_rdma(level, LOG_OUTGOING, fmt, ##args)
-#define log_incoming(level, fmt, args...) \
- log_rdma(level, LOG_INCOMING, fmt, ##args)
-#define log_read(level, fmt, args...) log_rdma(level, LOG_READ, fmt, ##args)
-#define log_write(level, fmt, args...) log_rdma(level, LOG_WRITE, fmt, ##args)
-#define log_rdma_send(level, fmt, args...) \
- log_rdma(level, LOG_RDMA_SEND, fmt, ##args)
-#define log_rdma_recv(level, fmt, args...) \
- log_rdma(level, LOG_RDMA_RECV, fmt, ##args)
-#define log_keep_alive(level, fmt, args...) \
- log_rdma(level, LOG_KEEP_ALIVE, fmt, ##args)
-#define log_rdma_event(level, fmt, args...) \
- log_rdma(level, LOG_RDMA_EVENT, fmt, ##args)
-#define log_rdma_mr(level, fmt, args...) \
- log_rdma(level, LOG_RDMA_MR, fmt, ##args)
-
-static void smbd_disconnect_rdma_work(struct work_struct *work)
-{
- struct smbd_connection *info =
- container_of(work, struct smbd_connection, disconnect_work);
-
- if (info->transport_status == SMBD_CONNECTED) {
- info->transport_status = SMBD_DISCONNECTING;
- rdma_disconnect(info->id);
- }
-}
-
-static void smbd_disconnect_rdma_connection(struct smbd_connection *info)
-{
- queue_work(info->workqueue, &info->disconnect_work);
-}
-
-/* Upcall from RDMA CM */
-static int smbd_conn_upcall(
- struct rdma_cm_id *id, struct rdma_cm_event *event)
-{
- struct smbd_connection *info = id->context;
-
- log_rdma_event(INFO, "event=%d status=%d\n",
- event->event, event->status);
-
- switch (event->event) {
- case RDMA_CM_EVENT_ADDR_RESOLVED:
- case RDMA_CM_EVENT_ROUTE_RESOLVED:
- info->ri_rc = 0;
- complete(&info->ri_done);
- break;
-
- case RDMA_CM_EVENT_ADDR_ERROR:
- info->ri_rc = -EHOSTUNREACH;
- complete(&info->ri_done);
- break;
-
- case RDMA_CM_EVENT_ROUTE_ERROR:
- info->ri_rc = -ENETUNREACH;
- complete(&info->ri_done);
- break;
-
- case RDMA_CM_EVENT_ESTABLISHED:
- log_rdma_event(INFO, "connected event=%d\n", event->event);
- info->transport_status = SMBD_CONNECTED;
- wake_up_interruptible(&info->conn_wait);
- break;
-
- case RDMA_CM_EVENT_CONNECT_ERROR:
- case RDMA_CM_EVENT_UNREACHABLE:
- case RDMA_CM_EVENT_REJECTED:
- log_rdma_event(INFO, "connecting failed event=%d\n", event->event);
- info->transport_status = SMBD_DISCONNECTED;
- wake_up_interruptible(&info->conn_wait);
- break;
-
- case RDMA_CM_EVENT_DEVICE_REMOVAL:
- case RDMA_CM_EVENT_DISCONNECTED:
- /* This happenes when we fail the negotiation */
- if (info->transport_status == SMBD_NEGOTIATE_FAILED) {
- info->transport_status = SMBD_DISCONNECTED;
- wake_up(&info->conn_wait);
- break;
- }
-
- info->transport_status = SMBD_DISCONNECTED;
- wake_up_interruptible(&info->disconn_wait);
- wake_up_interruptible(&info->wait_reassembly_queue);
- wake_up_interruptible_all(&info->wait_send_queue);
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-/* Upcall from RDMA QP */
-static void
-smbd_qp_async_error_upcall(struct ib_event *event, void *context)
-{
- struct smbd_connection *info = context;
-
- log_rdma_event(ERR, "%s on device %s info %p\n",
- ib_event_msg(event->event), event->device->name, info);
-
- switch (event->event) {
- case IB_EVENT_CQ_ERR:
- case IB_EVENT_QP_FATAL:
- smbd_disconnect_rdma_connection(info);
- break;
-
- default:
- break;
- }
-}
-
-static inline void *smbd_request_payload(struct smbd_request *request)
-{
- return (void *)request->packet;
-}
-
-static inline void *smbd_response_payload(struct smbd_response *response)
-{
- return (void *)response->packet;
-}
-
-/* Called when a RDMA send is done */
-static void send_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- int i;
- struct smbd_request *request =
- container_of(wc->wr_cqe, struct smbd_request, cqe);
-
- log_rdma_send(INFO, "smbd_request 0x%p completed wc->status=%d\n",
- request, wc->status);
-
- if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
- log_rdma_send(ERR, "wc->status=%d wc->opcode=%d\n",
- wc->status, wc->opcode);
- smbd_disconnect_rdma_connection(request->info);
- }
-
- for (i = 0; i < request->num_sge; i++)
- ib_dma_unmap_single(request->info->id->device,
- request->sge[i].addr,
- request->sge[i].length,
- DMA_TO_DEVICE);
-
- if (atomic_dec_and_test(&request->info->send_pending))
- wake_up(&request->info->wait_send_pending);
-
- wake_up(&request->info->wait_post_send);
-
- mempool_free(request, request->info->request_mempool);
-}
-
-static void dump_smbd_negotiate_resp(struct smbd_negotiate_resp *resp)
-{
- log_rdma_event(INFO, "resp message min_version %u max_version %u negotiated_version %u credits_requested %u credits_granted %u status %u max_readwrite_size %u preferred_send_size %u max_receive_size %u max_fragmented_size %u\n",
- resp->min_version, resp->max_version,
- resp->negotiated_version, resp->credits_requested,
- resp->credits_granted, resp->status,
- resp->max_readwrite_size, resp->preferred_send_size,
- resp->max_receive_size, resp->max_fragmented_size);
-}
-
-/*
- * Process a negotiation response message, according to [MS-SMBD]3.1.5.7
- * response, packet_length: the negotiation response message
- * return value: true if negotiation is a success, false if failed
- */
-static bool process_negotiation_response(
- struct smbd_response *response, int packet_length)
-{
- struct smbd_connection *info = response->info;
- struct smbd_negotiate_resp *packet = smbd_response_payload(response);
-
- if (packet_length < sizeof(struct smbd_negotiate_resp)) {
- log_rdma_event(ERR,
- "error: packet_length=%d\n", packet_length);
- return false;
- }
-
- if (le16_to_cpu(packet->negotiated_version) != SMBD_V1) {
- log_rdma_event(ERR, "error: negotiated_version=%x\n",
- le16_to_cpu(packet->negotiated_version));
- return false;
- }
- info->protocol = le16_to_cpu(packet->negotiated_version);
-
- if (packet->credits_requested == 0) {
- log_rdma_event(ERR, "error: credits_requested==0\n");
- return false;
- }
- info->receive_credit_target = le16_to_cpu(packet->credits_requested);
-
- if (packet->credits_granted == 0) {
- log_rdma_event(ERR, "error: credits_granted==0\n");
- return false;
- }
- atomic_set(&info->send_credits, le16_to_cpu(packet->credits_granted));
-
- atomic_set(&info->receive_credits, 0);
-
- if (le32_to_cpu(packet->preferred_send_size) > info->max_receive_size) {
- log_rdma_event(ERR, "error: preferred_send_size=%d\n",
- le32_to_cpu(packet->preferred_send_size));
- return false;
- }
- info->max_receive_size = le32_to_cpu(packet->preferred_send_size);
-
- if (le32_to_cpu(packet->max_receive_size) < SMBD_MIN_RECEIVE_SIZE) {
- log_rdma_event(ERR, "error: max_receive_size=%d\n",
- le32_to_cpu(packet->max_receive_size));
- return false;
- }
- info->max_send_size = min_t(int, info->max_send_size,
- le32_to_cpu(packet->max_receive_size));
-
- if (le32_to_cpu(packet->max_fragmented_size) <
- SMBD_MIN_FRAGMENTED_SIZE) {
- log_rdma_event(ERR, "error: max_fragmented_size=%d\n",
- le32_to_cpu(packet->max_fragmented_size));
- return false;
- }
- info->max_fragmented_send_size =
- le32_to_cpu(packet->max_fragmented_size);
- info->rdma_readwrite_threshold =
- rdma_readwrite_threshold > info->max_fragmented_send_size ?
- info->max_fragmented_send_size :
- rdma_readwrite_threshold;
-
-
- info->max_readwrite_size = min_t(u32,
- le32_to_cpu(packet->max_readwrite_size),
- info->max_frmr_depth * PAGE_SIZE);
- info->max_frmr_depth = info->max_readwrite_size / PAGE_SIZE;
-
- return true;
-}
-
-static void smbd_post_send_credits(struct work_struct *work)
-{
- int ret = 0;
- int use_receive_queue = 1;
- int rc;
- struct smbd_response *response;
- struct smbd_connection *info =
- container_of(work, struct smbd_connection,
- post_send_credits_work);
-
- if (info->transport_status != SMBD_CONNECTED) {
- wake_up(&info->wait_receive_queues);
- return;
- }
-
- if (info->receive_credit_target >
- atomic_read(&info->receive_credits)) {
- while (true) {
- if (use_receive_queue)
- response = get_receive_buffer(info);
- else
- response = get_empty_queue_buffer(info);
- if (!response) {
- /* now switch to emtpy packet queue */
- if (use_receive_queue) {
- use_receive_queue = 0;
- continue;
- } else
- break;
- }
-
- response->type = SMBD_TRANSFER_DATA;
- response->first_segment = false;
- rc = smbd_post_recv(info, response);
- if (rc) {
- log_rdma_recv(ERR,
- "post_recv failed rc=%d\n", rc);
- put_receive_buffer(info, response);
- break;
- }
-
- ret++;
- }
- }
-
- spin_lock(&info->lock_new_credits_offered);
- info->new_credits_offered += ret;
- spin_unlock(&info->lock_new_credits_offered);
-
- /* Promptly send an immediate packet as defined in [MS-SMBD] 3.1.1.1 */
- info->send_immediate = true;
- if (atomic_read(&info->receive_credits) <
- info->receive_credit_target - 1) {
- if (info->keep_alive_requested == KEEP_ALIVE_PENDING ||
- info->send_immediate) {
- log_keep_alive(INFO, "send an empty message\n");
- smbd_post_send_empty(info);
- }
- }
-}
-
-/* Called from softirq, when recv is done */
-static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smbd_data_transfer *data_transfer;
- struct smbd_response *response =
- container_of(wc->wr_cqe, struct smbd_response, cqe);
- struct smbd_connection *info = response->info;
- int data_length = 0;
-
- log_rdma_recv(INFO, "response=0x%p type=%d wc status=%d wc opcode %d byte_len=%d pkey_index=%u\n",
- response, response->type, wc->status, wc->opcode,
- wc->byte_len, wc->pkey_index);
-
- if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
- log_rdma_recv(INFO, "wc->status=%d opcode=%d\n",
- wc->status, wc->opcode);
- smbd_disconnect_rdma_connection(info);
- goto error;
- }
-
- ib_dma_sync_single_for_cpu(
- wc->qp->device,
- response->sge.addr,
- response->sge.length,
- DMA_FROM_DEVICE);
-
- switch (response->type) {
- /* SMBD negotiation response */
- case SMBD_NEGOTIATE_RESP:
- dump_smbd_negotiate_resp(smbd_response_payload(response));
- info->full_packet_received = true;
- info->negotiate_done =
- process_negotiation_response(response, wc->byte_len);
- complete(&info->negotiate_completion);
- break;
-
- /* SMBD data transfer packet */
- case SMBD_TRANSFER_DATA:
- data_transfer = smbd_response_payload(response);
- data_length = le32_to_cpu(data_transfer->data_length);
-
- /*
- * If this is a packet with data playload place the data in
- * reassembly queue and wake up the reading thread
- */
- if (data_length) {
- if (info->full_packet_received)
- response->first_segment = true;
-
- if (le32_to_cpu(data_transfer->remaining_data_length))
- info->full_packet_received = false;
- else
- info->full_packet_received = true;
-
- enqueue_reassembly(
- info,
- response,
- data_length);
- } else
- put_empty_packet(info, response);
-
- if (data_length)
- wake_up_interruptible(&info->wait_reassembly_queue);
-
- atomic_dec(&info->receive_credits);
- info->receive_credit_target =
- le16_to_cpu(data_transfer->credits_requested);
- if (le16_to_cpu(data_transfer->credits_granted)) {
- atomic_add(le16_to_cpu(data_transfer->credits_granted),
- &info->send_credits);
- /*
- * We have new send credits granted from remote peer
- * If any sender is waiting for credits, unblock it
- */
- wake_up_interruptible(&info->wait_send_queue);
- }
-
- log_incoming(INFO, "data flags %d data_offset %d data_length %d remaining_data_length %d\n",
- le16_to_cpu(data_transfer->flags),
- le32_to_cpu(data_transfer->data_offset),
- le32_to_cpu(data_transfer->data_length),
- le32_to_cpu(data_transfer->remaining_data_length));
-
- /* Send a KEEP_ALIVE response right away if requested */
- info->keep_alive_requested = KEEP_ALIVE_NONE;
- if (le16_to_cpu(data_transfer->flags) &
- SMB_DIRECT_RESPONSE_REQUESTED) {
- info->keep_alive_requested = KEEP_ALIVE_PENDING;
- }
-
- return;
-
- default:
- log_rdma_recv(ERR,
- "unexpected response type=%d\n", response->type);
- }
-
-error:
- put_receive_buffer(info, response);
-}
-
-static struct rdma_cm_id *smbd_create_id(
- struct smbd_connection *info,
- struct sockaddr *dstaddr, int port)
-{
- struct rdma_cm_id *id;
- int rc;
- __be16 *sport;
-
- id = rdma_create_id(&init_net, smbd_conn_upcall, info,
- RDMA_PS_TCP, IB_QPT_RC);
- if (IS_ERR(id)) {
- rc = PTR_ERR(id);
- log_rdma_event(ERR, "rdma_create_id() failed %i\n", rc);
- return id;
- }
-
- if (dstaddr->sa_family == AF_INET6)
- sport = &((struct sockaddr_in6 *)dstaddr)->sin6_port;
- else
- sport = &((struct sockaddr_in *)dstaddr)->sin_port;
-
- *sport = htons(port);
-
- init_completion(&info->ri_done);
- info->ri_rc = -ETIMEDOUT;
-
- rc = rdma_resolve_addr(id, NULL, (struct sockaddr *)dstaddr,
- RDMA_RESOLVE_TIMEOUT);
- if (rc) {
- log_rdma_event(ERR, "rdma_resolve_addr() failed %i\n", rc);
- goto out;
- }
- rc = wait_for_completion_interruptible_timeout(
- &info->ri_done, msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT));
- /* e.g. if interrupted returns -ERESTARTSYS */
- if (rc < 0) {
- log_rdma_event(ERR, "rdma_resolve_addr timeout rc: %i\n", rc);
- goto out;
- }
- rc = info->ri_rc;
- if (rc) {
- log_rdma_event(ERR, "rdma_resolve_addr() completed %i\n", rc);
- goto out;
- }
-
- info->ri_rc = -ETIMEDOUT;
- rc = rdma_resolve_route(id, RDMA_RESOLVE_TIMEOUT);
- if (rc) {
- log_rdma_event(ERR, "rdma_resolve_route() failed %i\n", rc);
- goto out;
- }
- rc = wait_for_completion_interruptible_timeout(
- &info->ri_done, msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT));
- /* e.g. if interrupted returns -ERESTARTSYS */
- if (rc < 0) {
- log_rdma_event(ERR, "rdma_resolve_addr timeout rc: %i\n", rc);
- goto out;
- }
- rc = info->ri_rc;
- if (rc) {
- log_rdma_event(ERR, "rdma_resolve_route() completed %i\n", rc);
- goto out;
- }
-
- return id;
-
-out:
- rdma_destroy_id(id);
- return ERR_PTR(rc);
-}
-
-/*
- * Test if FRWR (Fast Registration Work Requests) is supported on the device
- * This implementation requries FRWR on RDMA read/write
- * return value: true if it is supported
- */
-static bool frwr_is_supported(struct ib_device_attr *attrs)
-{
- if (!(attrs->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS))
- return false;
- if (attrs->max_fast_reg_page_list_len == 0)
- return false;
- return true;
-}
-
-static int smbd_ia_open(
- struct smbd_connection *info,
- struct sockaddr *dstaddr, int port)
-{
- int rc;
-
- info->id = smbd_create_id(info, dstaddr, port);
- if (IS_ERR(info->id)) {
- rc = PTR_ERR(info->id);
- goto out1;
- }
-
- if (!frwr_is_supported(&info->id->device->attrs)) {
- log_rdma_event(ERR, "Fast Registration Work Requests (FRWR) is not supported\n");
- log_rdma_event(ERR, "Device capability flags = %llx max_fast_reg_page_list_len = %u\n",
- info->id->device->attrs.device_cap_flags,
- info->id->device->attrs.max_fast_reg_page_list_len);
- rc = -EPROTONOSUPPORT;
- goto out2;
- }
- info->max_frmr_depth = min_t(int,
- smbd_max_frmr_depth,
- info->id->device->attrs.max_fast_reg_page_list_len);
- info->mr_type = IB_MR_TYPE_MEM_REG;
- if (info->id->device->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
- info->mr_type = IB_MR_TYPE_SG_GAPS;
-
- info->pd = ib_alloc_pd(info->id->device, 0);
- if (IS_ERR(info->pd)) {
- rc = PTR_ERR(info->pd);
- log_rdma_event(ERR, "ib_alloc_pd() returned %d\n", rc);
- goto out2;
- }
-
- return 0;
-
-out2:
- rdma_destroy_id(info->id);
- info->id = NULL;
-
-out1:
- return rc;
-}
-
-/*
- * Send a negotiation request message to the peer
- * The negotiation procedure is in [MS-SMBD] 3.1.5.2 and 3.1.5.3
- * After negotiation, the transport is connected and ready for
- * carrying upper layer SMB payload
- */
-static int smbd_post_send_negotiate_req(struct smbd_connection *info)
-{
- struct ib_send_wr send_wr;
- int rc = -ENOMEM;
- struct smbd_request *request;
- struct smbd_negotiate_req *packet;
-
- request = mempool_alloc(info->request_mempool, GFP_KERNEL);
- if (!request)
- return rc;
-
- request->info = info;
-
- packet = smbd_request_payload(request);
- packet->min_version = cpu_to_le16(SMBD_V1);
- packet->max_version = cpu_to_le16(SMBD_V1);
- packet->reserved = 0;
- packet->credits_requested = cpu_to_le16(info->send_credit_target);
- packet->preferred_send_size = cpu_to_le32(info->max_send_size);
- packet->max_receive_size = cpu_to_le32(info->max_receive_size);
- packet->max_fragmented_size =
- cpu_to_le32(info->max_fragmented_recv_size);
-
- request->num_sge = 1;
- request->sge[0].addr = ib_dma_map_single(
- info->id->device, (void *)packet,
- sizeof(*packet), DMA_TO_DEVICE);
- if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) {
- rc = -EIO;
- goto dma_mapping_failed;
- }
-
- request->sge[0].length = sizeof(*packet);
- request->sge[0].lkey = info->pd->local_dma_lkey;
-
- ib_dma_sync_single_for_device(
- info->id->device, request->sge[0].addr,
- request->sge[0].length, DMA_TO_DEVICE);
-
- request->cqe.done = send_done;
-
- send_wr.next = NULL;
- send_wr.wr_cqe = &request->cqe;
- send_wr.sg_list = request->sge;
- send_wr.num_sge = request->num_sge;
- send_wr.opcode = IB_WR_SEND;
- send_wr.send_flags = IB_SEND_SIGNALED;
-
- log_rdma_send(INFO, "sge addr=0x%llx length=%u lkey=0x%x\n",
- request->sge[0].addr,
- request->sge[0].length, request->sge[0].lkey);
-
- atomic_inc(&info->send_pending);
- rc = ib_post_send(info->id->qp, &send_wr, NULL);
- if (!rc)
- return 0;
-
- /* if we reach here, post send failed */
- log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
- atomic_dec(&info->send_pending);
- ib_dma_unmap_single(info->id->device, request->sge[0].addr,
- request->sge[0].length, DMA_TO_DEVICE);
-
- smbd_disconnect_rdma_connection(info);
-
-dma_mapping_failed:
- mempool_free(request, info->request_mempool);
- return rc;
-}
-
-/*
- * Extend the credits to remote peer
- * This implements [MS-SMBD] 3.1.5.9
- * The idea is that we should extend credits to remote peer as quickly as
- * it's allowed, to maintain data flow. We allocate as much receive
- * buffer as possible, and extend the receive credits to remote peer
- * return value: the new credtis being granted.
- */
-static int manage_credits_prior_sending(struct smbd_connection *info)
-{
- int new_credits;
-
- spin_lock(&info->lock_new_credits_offered);
- new_credits = info->new_credits_offered;
- info->new_credits_offered = 0;
- spin_unlock(&info->lock_new_credits_offered);
-
- return new_credits;
-}
-
-/*
- * Check if we need to send a KEEP_ALIVE message
- * The idle connection timer triggers a KEEP_ALIVE message when expires
- * SMB_DIRECT_RESPONSE_REQUESTED is set in the message flag to have peer send
- * back a response.
- * return value:
- * 1 if SMB_DIRECT_RESPONSE_REQUESTED needs to be set
- * 0: otherwise
- */
-static int manage_keep_alive_before_sending(struct smbd_connection *info)
-{
- if (info->keep_alive_requested == KEEP_ALIVE_PENDING) {
- info->keep_alive_requested = KEEP_ALIVE_SENT;
- return 1;
- }
- return 0;
-}
-
-/* Post the send request */
-static int smbd_post_send(struct smbd_connection *info,
- struct smbd_request *request)
-{
- struct ib_send_wr send_wr;
- int rc, i;
-
- for (i = 0; i < request->num_sge; i++) {
- log_rdma_send(INFO,
- "rdma_request sge[%d] addr=0x%llx length=%u\n",
- i, request->sge[i].addr, request->sge[i].length);
- ib_dma_sync_single_for_device(
- info->id->device,
- request->sge[i].addr,
- request->sge[i].length,
- DMA_TO_DEVICE);
- }
-
- request->cqe.done = send_done;
-
- send_wr.next = NULL;
- send_wr.wr_cqe = &request->cqe;
- send_wr.sg_list = request->sge;
- send_wr.num_sge = request->num_sge;
- send_wr.opcode = IB_WR_SEND;
- send_wr.send_flags = IB_SEND_SIGNALED;
-
- rc = ib_post_send(info->id->qp, &send_wr, NULL);
- if (rc) {
- log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
- smbd_disconnect_rdma_connection(info);
- rc = -EAGAIN;
- } else
- /* Reset timer for idle connection after packet is sent */
- mod_delayed_work(info->workqueue, &info->idle_timer_work,
- info->keep_alive_interval*HZ);
-
- return rc;
-}
-
-static int smbd_post_send_sgl(struct smbd_connection *info,
- struct scatterlist *sgl, int data_length, int remaining_data_length)
-{
- int num_sgs;
- int i, rc;
- int header_length;
- struct smbd_request *request;
- struct smbd_data_transfer *packet;
- int new_credits;
- struct scatterlist *sg;
-
-wait_credit:
- /* Wait for send credits. A SMBD packet needs one credit */
- rc = wait_event_interruptible(info->wait_send_queue,
- atomic_read(&info->send_credits) > 0 ||
- info->transport_status != SMBD_CONNECTED);
- if (rc)
- goto err_wait_credit;
-
- if (info->transport_status != SMBD_CONNECTED) {
- log_outgoing(ERR, "disconnected not sending on wait_credit\n");
- rc = -EAGAIN;
- goto err_wait_credit;
- }
- if (unlikely(atomic_dec_return(&info->send_credits) < 0)) {
- atomic_inc(&info->send_credits);
- goto wait_credit;
- }
-
-wait_send_queue:
- wait_event(info->wait_post_send,
- atomic_read(&info->send_pending) < info->send_credit_target ||
- info->transport_status != SMBD_CONNECTED);
-
- if (info->transport_status != SMBD_CONNECTED) {
- log_outgoing(ERR, "disconnected not sending on wait_send_queue\n");
- rc = -EAGAIN;
- goto err_wait_send_queue;
- }
-
- if (unlikely(atomic_inc_return(&info->send_pending) >
- info->send_credit_target)) {
- atomic_dec(&info->send_pending);
- goto wait_send_queue;
- }
-
- request = mempool_alloc(info->request_mempool, GFP_KERNEL);
- if (!request) {
- rc = -ENOMEM;
- goto err_alloc;
- }
-
- request->info = info;
-
- /* Fill in the packet header */
- packet = smbd_request_payload(request);
- packet->credits_requested = cpu_to_le16(info->send_credit_target);
-
- new_credits = manage_credits_prior_sending(info);
- atomic_add(new_credits, &info->receive_credits);
- packet->credits_granted = cpu_to_le16(new_credits);
-
- info->send_immediate = false;
-
- packet->flags = 0;
- if (manage_keep_alive_before_sending(info))
- packet->flags |= cpu_to_le16(SMB_DIRECT_RESPONSE_REQUESTED);
-
- packet->reserved = 0;
- if (!data_length)
- packet->data_offset = 0;
- else
- packet->data_offset = cpu_to_le32(24);
- packet->data_length = cpu_to_le32(data_length);
- packet->remaining_data_length = cpu_to_le32(remaining_data_length);
- packet->padding = 0;
-
- log_outgoing(INFO, "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n",
- le16_to_cpu(packet->credits_requested),
- le16_to_cpu(packet->credits_granted),
- le32_to_cpu(packet->data_offset),
- le32_to_cpu(packet->data_length),
- le32_to_cpu(packet->remaining_data_length));
-
- /* Map the packet to DMA */
- header_length = sizeof(struct smbd_data_transfer);
- /* If this is a packet without payload, don't send padding */
- if (!data_length)
- header_length = offsetof(struct smbd_data_transfer, padding);
-
- request->num_sge = 1;
- request->sge[0].addr = ib_dma_map_single(info->id->device,
- (void *)packet,
- header_length,
- DMA_TO_DEVICE);
- if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) {
- rc = -EIO;
- request->sge[0].addr = 0;
- goto err_dma;
- }
-
- request->sge[0].length = header_length;
- request->sge[0].lkey = info->pd->local_dma_lkey;
-
- /* Fill in the packet data payload */
- num_sgs = sgl ? sg_nents(sgl) : 0;
- for_each_sg(sgl, sg, num_sgs, i) {
- request->sge[i+1].addr =
- ib_dma_map_page(info->id->device, sg_page(sg),
- sg->offset, sg->length, DMA_TO_DEVICE);
- if (ib_dma_mapping_error(
- info->id->device, request->sge[i+1].addr)) {
- rc = -EIO;
- request->sge[i+1].addr = 0;
- goto err_dma;
- }
- request->sge[i+1].length = sg->length;
- request->sge[i+1].lkey = info->pd->local_dma_lkey;
- request->num_sge++;
- }
-
- rc = smbd_post_send(info, request);
- if (!rc)
- return 0;
-
-err_dma:
- for (i = 0; i < request->num_sge; i++)
- if (request->sge[i].addr)
- ib_dma_unmap_single(info->id->device,
- request->sge[i].addr,
- request->sge[i].length,
- DMA_TO_DEVICE);
- mempool_free(request, info->request_mempool);
-
- /* roll back receive credits and credits to be offered */
- spin_lock(&info->lock_new_credits_offered);
- info->new_credits_offered += new_credits;
- spin_unlock(&info->lock_new_credits_offered);
- atomic_sub(new_credits, &info->receive_credits);
-
-err_alloc:
- if (atomic_dec_and_test(&info->send_pending))
- wake_up(&info->wait_send_pending);
-
-err_wait_send_queue:
- /* roll back send credits and pending */
- atomic_inc(&info->send_credits);
-
-err_wait_credit:
- return rc;
-}
-
-/*
- * Send a page
- * page: the page to send
- * offset: offset in the page to send
- * size: length in the page to send
- * remaining_data_length: remaining data to send in this payload
- */
-static int smbd_post_send_page(struct smbd_connection *info, struct page *page,
- unsigned long offset, size_t size, int remaining_data_length)
-{
- struct scatterlist sgl;
-
- sg_init_table(&sgl, 1);
- sg_set_page(&sgl, page, size, offset);
-
- return smbd_post_send_sgl(info, &sgl, size, remaining_data_length);
-}
-
-/*
- * Send an empty message
- * Empty message is used to extend credits to peer to for keep live
- * while there is no upper layer payload to send at the time
- */
-static int smbd_post_send_empty(struct smbd_connection *info)
-{
- info->count_send_empty++;
- return smbd_post_send_sgl(info, NULL, 0, 0);
-}
-
-/*
- * Send a data buffer
- * iov: the iov array describing the data buffers
- * n_vec: number of iov array
- * remaining_data_length: remaining data to send following this packet
- * in segmented SMBD packet
- */
-static int smbd_post_send_data(
- struct smbd_connection *info, struct kvec *iov, int n_vec,
- int remaining_data_length)
-{
- int i;
- u32 data_length = 0;
- struct scatterlist sgl[SMBDIRECT_MAX_SEND_SGE - 1];
-
- if (n_vec > SMBDIRECT_MAX_SEND_SGE - 1) {
- cifs_dbg(VFS, "Can't fit data to SGL, n_vec=%d\n", n_vec);
- return -EINVAL;
- }
-
- sg_init_table(sgl, n_vec);
- for (i = 0; i < n_vec; i++) {
- data_length += iov[i].iov_len;
- sg_set_buf(&sgl[i], iov[i].iov_base, iov[i].iov_len);
- }
-
- return smbd_post_send_sgl(info, sgl, data_length, remaining_data_length);
-}
-
-/*
- * Post a receive request to the transport
- * The remote peer can only send data when a receive request is posted
- * The interaction is controlled by send/receive credit system
- */
-static int smbd_post_recv(
- struct smbd_connection *info, struct smbd_response *response)
-{
- struct ib_recv_wr recv_wr;
- int rc = -EIO;
-
- response->sge.addr = ib_dma_map_single(
- info->id->device, response->packet,
- info->max_receive_size, DMA_FROM_DEVICE);
- if (ib_dma_mapping_error(info->id->device, response->sge.addr))
- return rc;
-
- response->sge.length = info->max_receive_size;
- response->sge.lkey = info->pd->local_dma_lkey;
-
- response->cqe.done = recv_done;
-
- recv_wr.wr_cqe = &response->cqe;
- recv_wr.next = NULL;
- recv_wr.sg_list = &response->sge;
- recv_wr.num_sge = 1;
-
- rc = ib_post_recv(info->id->qp, &recv_wr, NULL);
- if (rc) {
- ib_dma_unmap_single(info->id->device, response->sge.addr,
- response->sge.length, DMA_FROM_DEVICE);
- smbd_disconnect_rdma_connection(info);
- log_rdma_recv(ERR, "ib_post_recv failed rc=%d\n", rc);
- }
-
- return rc;
-}
-
-/* Perform SMBD negotiate according to [MS-SMBD] 3.1.5.2 */
-static int smbd_negotiate(struct smbd_connection *info)
-{
- int rc;
- struct smbd_response *response = get_receive_buffer(info);
-
- response->type = SMBD_NEGOTIATE_RESP;
- rc = smbd_post_recv(info, response);
- log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=0x%llx iov.length=%u iov.lkey=0x%x\n",
- rc, response->sge.addr,
- response->sge.length, response->sge.lkey);
- if (rc)
- return rc;
-
- init_completion(&info->negotiate_completion);
- info->negotiate_done = false;
- rc = smbd_post_send_negotiate_req(info);
- if (rc)
- return rc;
-
- rc = wait_for_completion_interruptible_timeout(
- &info->negotiate_completion, SMBD_NEGOTIATE_TIMEOUT * HZ);
- log_rdma_event(INFO, "wait_for_completion_timeout rc=%d\n", rc);
-
- if (info->negotiate_done)
- return 0;
-
- if (rc == 0)
- rc = -ETIMEDOUT;
- else if (rc == -ERESTARTSYS)
- rc = -EINTR;
- else
- rc = -ENOTCONN;
-
- return rc;
-}
-
-static void put_empty_packet(
- struct smbd_connection *info, struct smbd_response *response)
-{
- spin_lock(&info->empty_packet_queue_lock);
- list_add_tail(&response->list, &info->empty_packet_queue);
- info->count_empty_packet_queue++;
- spin_unlock(&info->empty_packet_queue_lock);
-
- queue_work(info->workqueue, &info->post_send_credits_work);
-}
-
-/*
- * Implement Connection.FragmentReassemblyBuffer defined in [MS-SMBD] 3.1.1.1
- * This is a queue for reassembling upper layer payload and present to upper
- * layer. All the inncoming payload go to the reassembly queue, regardless of
- * if reassembly is required. The uuper layer code reads from the queue for all
- * incoming payloads.
- * Put a received packet to the reassembly queue
- * response: the packet received
- * data_length: the size of payload in this packet
- */
-static void enqueue_reassembly(
- struct smbd_connection *info,
- struct smbd_response *response,
- int data_length)
-{
- spin_lock(&info->reassembly_queue_lock);
- list_add_tail(&response->list, &info->reassembly_queue);
- info->reassembly_queue_length++;
- /*
- * Make sure reassembly_data_length is updated after list and
- * reassembly_queue_length are updated. On the dequeue side
- * reassembly_data_length is checked without a lock to determine
- * if reassembly_queue_length and list is up to date
- */
- virt_wmb();
- info->reassembly_data_length += data_length;
- spin_unlock(&info->reassembly_queue_lock);
- info->count_reassembly_queue++;
- info->count_enqueue_reassembly_queue++;
-}
-
-/*
- * Get the first entry at the front of reassembly queue
- * Caller is responsible for locking
- * return value: the first entry if any, NULL if queue is empty
- */
-static struct smbd_response *_get_first_reassembly(struct smbd_connection *info)
-{
- struct smbd_response *ret = NULL;
-
- if (!list_empty(&info->reassembly_queue)) {
- ret = list_first_entry(
- &info->reassembly_queue,
- struct smbd_response, list);
- }
- return ret;
-}
-
-static struct smbd_response *get_empty_queue_buffer(
- struct smbd_connection *info)
-{
- struct smbd_response *ret = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&info->empty_packet_queue_lock, flags);
- if (!list_empty(&info->empty_packet_queue)) {
- ret = list_first_entry(
- &info->empty_packet_queue,
- struct smbd_response, list);
- list_del(&ret->list);
- info->count_empty_packet_queue--;
- }
- spin_unlock_irqrestore(&info->empty_packet_queue_lock, flags);
-
- return ret;
-}
-
-/*
- * Get a receive buffer
- * For each remote send, we need to post a receive. The receive buffers are
- * pre-allocated in advance.
- * return value: the receive buffer, NULL if none is available
- */
-static struct smbd_response *get_receive_buffer(struct smbd_connection *info)
-{
- struct smbd_response *ret = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&info->receive_queue_lock, flags);
- if (!list_empty(&info->receive_queue)) {
- ret = list_first_entry(
- &info->receive_queue,
- struct smbd_response, list);
- list_del(&ret->list);
- info->count_receive_queue--;
- info->count_get_receive_buffer++;
- }
- spin_unlock_irqrestore(&info->receive_queue_lock, flags);
-
- return ret;
-}
-
-/*
- * Return a receive buffer
- * Upon returning of a receive buffer, we can post new receive and extend
- * more receive credits to remote peer. This is done immediately after a
- * receive buffer is returned.
- */
-static void put_receive_buffer(
- struct smbd_connection *info, struct smbd_response *response)
-{
- unsigned long flags;
-
- ib_dma_unmap_single(info->id->device, response->sge.addr,
- response->sge.length, DMA_FROM_DEVICE);
-
- spin_lock_irqsave(&info->receive_queue_lock, flags);
- list_add_tail(&response->list, &info->receive_queue);
- info->count_receive_queue++;
- info->count_put_receive_buffer++;
- spin_unlock_irqrestore(&info->receive_queue_lock, flags);
-
- queue_work(info->workqueue, &info->post_send_credits_work);
-}
-
-/* Preallocate all receive buffer on transport establishment */
-static int allocate_receive_buffers(struct smbd_connection *info, int num_buf)
-{
- int i;
- struct smbd_response *response;
-
- INIT_LIST_HEAD(&info->reassembly_queue);
- spin_lock_init(&info->reassembly_queue_lock);
- info->reassembly_data_length = 0;
- info->reassembly_queue_length = 0;
-
- INIT_LIST_HEAD(&info->receive_queue);
- spin_lock_init(&info->receive_queue_lock);
- info->count_receive_queue = 0;
-
- INIT_LIST_HEAD(&info->empty_packet_queue);
- spin_lock_init(&info->empty_packet_queue_lock);
- info->count_empty_packet_queue = 0;
-
- init_waitqueue_head(&info->wait_receive_queues);
-
- for (i = 0; i < num_buf; i++) {
- response = mempool_alloc(info->response_mempool, GFP_KERNEL);
- if (!response)
- goto allocate_failed;
-
- response->info = info;
- list_add_tail(&response->list, &info->receive_queue);
- info->count_receive_queue++;
- }
-
- return 0;
-
-allocate_failed:
- while (!list_empty(&info->receive_queue)) {
- response = list_first_entry(
- &info->receive_queue,
- struct smbd_response, list);
- list_del(&response->list);
- info->count_receive_queue--;
-
- mempool_free(response, info->response_mempool);
- }
- return -ENOMEM;
-}
-
-static void destroy_receive_buffers(struct smbd_connection *info)
-{
- struct smbd_response *response;
-
- while ((response = get_receive_buffer(info)))
- mempool_free(response, info->response_mempool);
-
- while ((response = get_empty_queue_buffer(info)))
- mempool_free(response, info->response_mempool);
-}
-
-/* Implement idle connection timer [MS-SMBD] 3.1.6.2 */
-static void idle_connection_timer(struct work_struct *work)
-{
- struct smbd_connection *info = container_of(
- work, struct smbd_connection,
- idle_timer_work.work);
-
- if (info->keep_alive_requested != KEEP_ALIVE_NONE) {
- log_keep_alive(ERR,
- "error status info->keep_alive_requested=%d\n",
- info->keep_alive_requested);
- smbd_disconnect_rdma_connection(info);
- return;
- }
-
- log_keep_alive(INFO, "about to send an empty idle message\n");
- smbd_post_send_empty(info);
-
- /* Setup the next idle timeout work */
- queue_delayed_work(info->workqueue, &info->idle_timer_work,
- info->keep_alive_interval*HZ);
-}
-
-/*
- * Destroy the transport and related RDMA and memory resources
- * Need to go through all the pending counters and make sure on one is using
- * the transport while it is destroyed
- */
-void smbd_destroy(struct TCP_Server_Info *server)
-{
- struct smbd_connection *info = server->smbd_conn;
- struct smbd_response *response;
- unsigned long flags;
-
- if (!info) {
- log_rdma_event(INFO, "rdma session already destroyed\n");
- return;
- }
-
- log_rdma_event(INFO, "destroying rdma session\n");
- if (info->transport_status != SMBD_DISCONNECTED) {
- rdma_disconnect(server->smbd_conn->id);
- log_rdma_event(INFO, "wait for transport being disconnected\n");
- wait_event_interruptible(
- info->disconn_wait,
- info->transport_status == SMBD_DISCONNECTED);
- }
-
- log_rdma_event(INFO, "destroying qp\n");
- ib_drain_qp(info->id->qp);
- rdma_destroy_qp(info->id);
-
- log_rdma_event(INFO, "cancelling idle timer\n");
- cancel_delayed_work_sync(&info->idle_timer_work);
-
- log_rdma_event(INFO, "wait for all send posted to IB to finish\n");
- wait_event(info->wait_send_pending,
- atomic_read(&info->send_pending) == 0);
-
- /* It's not possible for upper layer to get to reassembly */
- log_rdma_event(INFO, "drain the reassembly queue\n");
- do {
- spin_lock_irqsave(&info->reassembly_queue_lock, flags);
- response = _get_first_reassembly(info);
- if (response) {
- list_del(&response->list);
- spin_unlock_irqrestore(
- &info->reassembly_queue_lock, flags);
- put_receive_buffer(info, response);
- } else
- spin_unlock_irqrestore(
- &info->reassembly_queue_lock, flags);
- } while (response);
- info->reassembly_data_length = 0;
-
- log_rdma_event(INFO, "free receive buffers\n");
- wait_event(info->wait_receive_queues,
- info->count_receive_queue + info->count_empty_packet_queue
- == info->receive_credit_max);
- destroy_receive_buffers(info);
-
- /*
- * For performance reasons, memory registration and deregistration
- * are not locked by srv_mutex. It is possible some processes are
- * blocked on transport srv_mutex while holding memory registration.
- * Release the transport srv_mutex to allow them to hit the failure
- * path when sending data, and then release memory registartions.
- */
- log_rdma_event(INFO, "freeing mr list\n");
- wake_up_interruptible_all(&info->wait_mr);
- while (atomic_read(&info->mr_used_count)) {
- cifs_server_unlock(server);
- msleep(1000);
- cifs_server_lock(server);
- }
- destroy_mr_list(info);
-
- ib_free_cq(info->send_cq);
- ib_free_cq(info->recv_cq);
- ib_dealloc_pd(info->pd);
- rdma_destroy_id(info->id);
-
- /* free mempools */
- mempool_destroy(info->request_mempool);
- kmem_cache_destroy(info->request_cache);
-
- mempool_destroy(info->response_mempool);
- kmem_cache_destroy(info->response_cache);
-
- info->transport_status = SMBD_DESTROYED;
-
- destroy_workqueue(info->workqueue);
- log_rdma_event(INFO, "rdma session destroyed\n");
- kfree(info);
- server->smbd_conn = NULL;
-}
-
-/*
- * Reconnect this SMBD connection, called from upper layer
- * return value: 0 on success, or actual error code
- */
-int smbd_reconnect(struct TCP_Server_Info *server)
-{
- log_rdma_event(INFO, "reconnecting rdma session\n");
-
- if (!server->smbd_conn) {
- log_rdma_event(INFO, "rdma session already destroyed\n");
- goto create_conn;
- }
-
- /*
- * This is possible if transport is disconnected and we haven't received
- * notification from RDMA, but upper layer has detected timeout
- */
- if (server->smbd_conn->transport_status == SMBD_CONNECTED) {
- log_rdma_event(INFO, "disconnecting transport\n");
- smbd_destroy(server);
- }
-
-create_conn:
- log_rdma_event(INFO, "creating rdma session\n");
- server->smbd_conn = smbd_get_connection(
- server, (struct sockaddr *) &server->dstaddr);
-
- if (server->smbd_conn)
- cifs_dbg(VFS, "RDMA transport re-established\n");
-
- return server->smbd_conn ? 0 : -ENOENT;
-}
-
-static void destroy_caches_and_workqueue(struct smbd_connection *info)
-{
- destroy_receive_buffers(info);
- destroy_workqueue(info->workqueue);
- mempool_destroy(info->response_mempool);
- kmem_cache_destroy(info->response_cache);
- mempool_destroy(info->request_mempool);
- kmem_cache_destroy(info->request_cache);
-}
-
-#define MAX_NAME_LEN 80
-static int allocate_caches_and_workqueue(struct smbd_connection *info)
-{
- char name[MAX_NAME_LEN];
- int rc;
-
- scnprintf(name, MAX_NAME_LEN, "smbd_request_%p", info);
- info->request_cache =
- kmem_cache_create(
- name,
- sizeof(struct smbd_request) +
- sizeof(struct smbd_data_transfer),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!info->request_cache)
- return -ENOMEM;
-
- info->request_mempool =
- mempool_create(info->send_credit_target, mempool_alloc_slab,
- mempool_free_slab, info->request_cache);
- if (!info->request_mempool)
- goto out1;
-
- scnprintf(name, MAX_NAME_LEN, "smbd_response_%p", info);
- info->response_cache =
- kmem_cache_create(
- name,
- sizeof(struct smbd_response) +
- info->max_receive_size,
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!info->response_cache)
- goto out2;
-
- info->response_mempool =
- mempool_create(info->receive_credit_max, mempool_alloc_slab,
- mempool_free_slab, info->response_cache);
- if (!info->response_mempool)
- goto out3;
-
- scnprintf(name, MAX_NAME_LEN, "smbd_%p", info);
- info->workqueue = create_workqueue(name);
- if (!info->workqueue)
- goto out4;
-
- rc = allocate_receive_buffers(info, info->receive_credit_max);
- if (rc) {
- log_rdma_event(ERR, "failed to allocate receive buffers\n");
- goto out5;
- }
-
- return 0;
-
-out5:
- destroy_workqueue(info->workqueue);
-out4:
- mempool_destroy(info->response_mempool);
-out3:
- kmem_cache_destroy(info->response_cache);
-out2:
- mempool_destroy(info->request_mempool);
-out1:
- kmem_cache_destroy(info->request_cache);
- return -ENOMEM;
-}
-
-/* Create a SMBD connection, called by upper layer */
-static struct smbd_connection *_smbd_get_connection(
- struct TCP_Server_Info *server, struct sockaddr *dstaddr, int port)
-{
- int rc;
- struct smbd_connection *info;
- struct rdma_conn_param conn_param;
- struct ib_qp_init_attr qp_attr;
- struct sockaddr_in *addr_in = (struct sockaddr_in *) dstaddr;
- struct ib_port_immutable port_immutable;
- u32 ird_ord_hdr[2];
-
- info = kzalloc(sizeof(struct smbd_connection), GFP_KERNEL);
- if (!info)
- return NULL;
-
- info->transport_status = SMBD_CONNECTING;
- rc = smbd_ia_open(info, dstaddr, port);
- if (rc) {
- log_rdma_event(INFO, "smbd_ia_open rc=%d\n", rc);
- goto create_id_failed;
- }
-
- if (smbd_send_credit_target > info->id->device->attrs.max_cqe ||
- smbd_send_credit_target > info->id->device->attrs.max_qp_wr) {
- log_rdma_event(ERR, "consider lowering send_credit_target = %d. Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
- smbd_send_credit_target,
- info->id->device->attrs.max_cqe,
- info->id->device->attrs.max_qp_wr);
- goto config_failed;
- }
-
- if (smbd_receive_credit_max > info->id->device->attrs.max_cqe ||
- smbd_receive_credit_max > info->id->device->attrs.max_qp_wr) {
- log_rdma_event(ERR, "consider lowering receive_credit_max = %d. Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
- smbd_receive_credit_max,
- info->id->device->attrs.max_cqe,
- info->id->device->attrs.max_qp_wr);
- goto config_failed;
- }
-
- info->receive_credit_max = smbd_receive_credit_max;
- info->send_credit_target = smbd_send_credit_target;
- info->max_send_size = smbd_max_send_size;
- info->max_fragmented_recv_size = smbd_max_fragmented_recv_size;
- info->max_receive_size = smbd_max_receive_size;
- info->keep_alive_interval = smbd_keep_alive_interval;
-
- if (info->id->device->attrs.max_send_sge < SMBDIRECT_MAX_SEND_SGE ||
- info->id->device->attrs.max_recv_sge < SMBDIRECT_MAX_RECV_SGE) {
- log_rdma_event(ERR,
- "device %.*s max_send_sge/max_recv_sge = %d/%d too small\n",
- IB_DEVICE_NAME_MAX,
- info->id->device->name,
- info->id->device->attrs.max_send_sge,
- info->id->device->attrs.max_recv_sge);
- goto config_failed;
- }
-
- info->send_cq = NULL;
- info->recv_cq = NULL;
- info->send_cq =
- ib_alloc_cq_any(info->id->device, info,
- info->send_credit_target, IB_POLL_SOFTIRQ);
- if (IS_ERR(info->send_cq)) {
- info->send_cq = NULL;
- goto alloc_cq_failed;
- }
-
- info->recv_cq =
- ib_alloc_cq_any(info->id->device, info,
- info->receive_credit_max, IB_POLL_SOFTIRQ);
- if (IS_ERR(info->recv_cq)) {
- info->recv_cq = NULL;
- goto alloc_cq_failed;
- }
-
- memset(&qp_attr, 0, sizeof(qp_attr));
- qp_attr.event_handler = smbd_qp_async_error_upcall;
- qp_attr.qp_context = info;
- qp_attr.cap.max_send_wr = info->send_credit_target;
- qp_attr.cap.max_recv_wr = info->receive_credit_max;
- qp_attr.cap.max_send_sge = SMBDIRECT_MAX_SEND_SGE;
- qp_attr.cap.max_recv_sge = SMBDIRECT_MAX_RECV_SGE;
- qp_attr.cap.max_inline_data = 0;
- qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
- qp_attr.qp_type = IB_QPT_RC;
- qp_attr.send_cq = info->send_cq;
- qp_attr.recv_cq = info->recv_cq;
- qp_attr.port_num = ~0;
-
- rc = rdma_create_qp(info->id, info->pd, &qp_attr);
- if (rc) {
- log_rdma_event(ERR, "rdma_create_qp failed %i\n", rc);
- goto create_qp_failed;
- }
-
- memset(&conn_param, 0, sizeof(conn_param));
- conn_param.initiator_depth = 0;
-
- conn_param.responder_resources =
- info->id->device->attrs.max_qp_rd_atom
- < SMBD_CM_RESPONDER_RESOURCES ?
- info->id->device->attrs.max_qp_rd_atom :
- SMBD_CM_RESPONDER_RESOURCES;
- info->responder_resources = conn_param.responder_resources;
- log_rdma_mr(INFO, "responder_resources=%d\n",
- info->responder_resources);
-
- /* Need to send IRD/ORD in private data for iWARP */
- info->id->device->ops.get_port_immutable(
- info->id->device, info->id->port_num, &port_immutable);
- if (port_immutable.core_cap_flags & RDMA_CORE_PORT_IWARP) {
- ird_ord_hdr[0] = info->responder_resources;
- ird_ord_hdr[1] = 1;
- conn_param.private_data = ird_ord_hdr;
- conn_param.private_data_len = sizeof(ird_ord_hdr);
- } else {
- conn_param.private_data = NULL;
- conn_param.private_data_len = 0;
- }
-
- conn_param.retry_count = SMBD_CM_RETRY;
- conn_param.rnr_retry_count = SMBD_CM_RNR_RETRY;
- conn_param.flow_control = 0;
-
- log_rdma_event(INFO, "connecting to IP %pI4 port %d\n",
- &addr_in->sin_addr, port);
-
- init_waitqueue_head(&info->conn_wait);
- init_waitqueue_head(&info->disconn_wait);
- init_waitqueue_head(&info->wait_reassembly_queue);
- rc = rdma_connect(info->id, &conn_param);
- if (rc) {
- log_rdma_event(ERR, "rdma_connect() failed with %i\n", rc);
- goto rdma_connect_failed;
- }
-
- wait_event_interruptible(
- info->conn_wait, info->transport_status != SMBD_CONNECTING);
-
- if (info->transport_status != SMBD_CONNECTED) {
- log_rdma_event(ERR, "rdma_connect failed port=%d\n", port);
- goto rdma_connect_failed;
- }
-
- log_rdma_event(INFO, "rdma_connect connected\n");
-
- rc = allocate_caches_and_workqueue(info);
- if (rc) {
- log_rdma_event(ERR, "cache allocation failed\n");
- goto allocate_cache_failed;
- }
-
- init_waitqueue_head(&info->wait_send_queue);
- INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer);
- queue_delayed_work(info->workqueue, &info->idle_timer_work,
- info->keep_alive_interval*HZ);
-
- init_waitqueue_head(&info->wait_send_pending);
- atomic_set(&info->send_pending, 0);
-
- init_waitqueue_head(&info->wait_post_send);
-
- INIT_WORK(&info->disconnect_work, smbd_disconnect_rdma_work);
- INIT_WORK(&info->post_send_credits_work, smbd_post_send_credits);
- info->new_credits_offered = 0;
- spin_lock_init(&info->lock_new_credits_offered);
-
- rc = smbd_negotiate(info);
- if (rc) {
- log_rdma_event(ERR, "smbd_negotiate rc=%d\n", rc);
- goto negotiation_failed;
- }
-
- rc = allocate_mr_list(info);
- if (rc) {
- log_rdma_mr(ERR, "memory registration allocation failed\n");
- goto allocate_mr_failed;
- }
-
- return info;
-
-allocate_mr_failed:
- /* At this point, need to a full transport shutdown */
- server->smbd_conn = info;
- smbd_destroy(server);
- return NULL;
-
-negotiation_failed:
- cancel_delayed_work_sync(&info->idle_timer_work);
- destroy_caches_and_workqueue(info);
- info->transport_status = SMBD_NEGOTIATE_FAILED;
- init_waitqueue_head(&info->conn_wait);
- rdma_disconnect(info->id);
- wait_event(info->conn_wait,
- info->transport_status == SMBD_DISCONNECTED);
-
-allocate_cache_failed:
-rdma_connect_failed:
- rdma_destroy_qp(info->id);
-
-create_qp_failed:
-alloc_cq_failed:
- if (info->send_cq)
- ib_free_cq(info->send_cq);
- if (info->recv_cq)
- ib_free_cq(info->recv_cq);
-
-config_failed:
- ib_dealloc_pd(info->pd);
- rdma_destroy_id(info->id);
-
-create_id_failed:
- kfree(info);
- return NULL;
-}
-
-struct smbd_connection *smbd_get_connection(
- struct TCP_Server_Info *server, struct sockaddr *dstaddr)
-{
- struct smbd_connection *ret;
- int port = SMBD_PORT;
-
-try_again:
- ret = _smbd_get_connection(server, dstaddr, port);
-
- /* Try SMB_PORT if SMBD_PORT doesn't work */
- if (!ret && port == SMBD_PORT) {
- port = SMB_PORT;
- goto try_again;
- }
- return ret;
-}
-
-/*
- * Receive data from receive reassembly queue
- * All the incoming data packets are placed in reassembly queue
- * buf: the buffer to read data into
- * size: the length of data to read
- * return value: actual data read
- * Note: this implementation copies the data from reassebmly queue to receive
- * buffers used by upper layer. This is not the optimal code path. A better way
- * to do it is to not have upper layer allocate its receive buffers but rather
- * borrow the buffer from reassembly queue, and return it after data is
- * consumed. But this will require more changes to upper layer code, and also
- * need to consider packet boundaries while they still being reassembled.
- */
-static int smbd_recv_buf(struct smbd_connection *info, char *buf,
- unsigned int size)
-{
- struct smbd_response *response;
- struct smbd_data_transfer *data_transfer;
- int to_copy, to_read, data_read, offset;
- u32 data_length, remaining_data_length, data_offset;
- int rc;
-
-again:
- /*
- * No need to hold the reassembly queue lock all the time as we are
- * the only one reading from the front of the queue. The transport
- * may add more entries to the back of the queue at the same time
- */
- log_read(INFO, "size=%d info->reassembly_data_length=%d\n", size,
- info->reassembly_data_length);
- if (info->reassembly_data_length >= size) {
- int queue_length;
- int queue_removed = 0;
-
- /*
- * Need to make sure reassembly_data_length is read before
- * reading reassembly_queue_length and calling
- * _get_first_reassembly. This call is lock free
- * as we never read at the end of the queue which are being
- * updated in SOFTIRQ as more data is received
- */
- virt_rmb();
- queue_length = info->reassembly_queue_length;
- data_read = 0;
- to_read = size;
- offset = info->first_entry_offset;
- while (data_read < size) {
- response = _get_first_reassembly(info);
- data_transfer = smbd_response_payload(response);
- data_length = le32_to_cpu(data_transfer->data_length);
- remaining_data_length =
- le32_to_cpu(
- data_transfer->remaining_data_length);
- data_offset = le32_to_cpu(data_transfer->data_offset);
-
- /*
- * The upper layer expects RFC1002 length at the
- * beginning of the payload. Return it to indicate
- * the total length of the packet. This minimize the
- * change to upper layer packet processing logic. This
- * will be eventually remove when an intermediate
- * transport layer is added
- */
- if (response->first_segment && size == 4) {
- unsigned int rfc1002_len =
- data_length + remaining_data_length;
- *((__be32 *)buf) = cpu_to_be32(rfc1002_len);
- data_read = 4;
- response->first_segment = false;
- log_read(INFO, "returning rfc1002 length %d\n",
- rfc1002_len);
- goto read_rfc1002_done;
- }
-
- to_copy = min_t(int, data_length - offset, to_read);
- memcpy(
- buf + data_read,
- (char *)data_transfer + data_offset + offset,
- to_copy);
-
- /* move on to the next buffer? */
- if (to_copy == data_length - offset) {
- queue_length--;
- /*
- * No need to lock if we are not at the
- * end of the queue
- */
- if (queue_length)
- list_del(&response->list);
- else {
- spin_lock_irq(
- &info->reassembly_queue_lock);
- list_del(&response->list);
- spin_unlock_irq(
- &info->reassembly_queue_lock);
- }
- queue_removed++;
- info->count_reassembly_queue--;
- info->count_dequeue_reassembly_queue++;
- put_receive_buffer(info, response);
- offset = 0;
- log_read(INFO, "put_receive_buffer offset=0\n");
- } else
- offset += to_copy;
-
- to_read -= to_copy;
- data_read += to_copy;
-
- log_read(INFO, "_get_first_reassembly memcpy %d bytes data_transfer_length-offset=%d after that to_read=%d data_read=%d offset=%d\n",
- to_copy, data_length - offset,
- to_read, data_read, offset);
- }
-
- spin_lock_irq(&info->reassembly_queue_lock);
- info->reassembly_data_length -= data_read;
- info->reassembly_queue_length -= queue_removed;
- spin_unlock_irq(&info->reassembly_queue_lock);
-
- info->first_entry_offset = offset;
- log_read(INFO, "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n",
- data_read, info->reassembly_data_length,
- info->first_entry_offset);
-read_rfc1002_done:
- return data_read;
- }
-
- log_read(INFO, "wait_event on more data\n");
- rc = wait_event_interruptible(
- info->wait_reassembly_queue,
- info->reassembly_data_length >= size ||
- info->transport_status != SMBD_CONNECTED);
- /* Don't return any data if interrupted */
- if (rc)
- return rc;
-
- if (info->transport_status != SMBD_CONNECTED) {
- log_read(ERR, "disconnected\n");
- return -ECONNABORTED;
- }
-
- goto again;
-}
-
-/*
- * Receive a page from receive reassembly queue
- * page: the page to read data into
- * to_read: the length of data to read
- * return value: actual data read
- */
-static int smbd_recv_page(struct smbd_connection *info,
- struct page *page, unsigned int page_offset,
- unsigned int to_read)
-{
- int ret;
- char *to_address;
- void *page_address;
-
- /* make sure we have the page ready for read */
- ret = wait_event_interruptible(
- info->wait_reassembly_queue,
- info->reassembly_data_length >= to_read ||
- info->transport_status != SMBD_CONNECTED);
- if (ret)
- return ret;
-
- /* now we can read from reassembly queue and not sleep */
- page_address = kmap_atomic(page);
- to_address = (char *) page_address + page_offset;
-
- log_read(INFO, "reading from page=%p address=%p to_read=%d\n",
- page, to_address, to_read);
-
- ret = smbd_recv_buf(info, to_address, to_read);
- kunmap_atomic(page_address);
-
- return ret;
-}
-
-/*
- * Receive data from transport
- * msg: a msghdr point to the buffer, can be ITER_KVEC or ITER_BVEC
- * return: total bytes read, or 0. SMB Direct will not do partial read.
- */
-int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
-{
- char *buf;
- struct page *page;
- unsigned int to_read, page_offset;
- int rc;
-
- if (iov_iter_rw(&msg->msg_iter) == WRITE) {
- /* It's a bug in upper layer to get there */
- cifs_dbg(VFS, "Invalid msg iter dir %u\n",
- iov_iter_rw(&msg->msg_iter));
- rc = -EINVAL;
- goto out;
- }
-
- switch (iov_iter_type(&msg->msg_iter)) {
- case ITER_KVEC:
- buf = msg->msg_iter.kvec->iov_base;
- to_read = msg->msg_iter.kvec->iov_len;
- rc = smbd_recv_buf(info, buf, to_read);
- break;
-
- case ITER_BVEC:
- page = msg->msg_iter.bvec->bv_page;
- page_offset = msg->msg_iter.bvec->bv_offset;
- to_read = msg->msg_iter.bvec->bv_len;
- rc = smbd_recv_page(info, page, page_offset, to_read);
- break;
-
- default:
- /* It's a bug in upper layer to get there */
- cifs_dbg(VFS, "Invalid msg type %d\n",
- iov_iter_type(&msg->msg_iter));
- rc = -EINVAL;
- }
-
-out:
- /* SMBDirect will read it all or nothing */
- if (rc > 0)
- msg->msg_iter.count = 0;
- return rc;
-}
-
-/*
- * Send data to transport
- * Each rqst is transported as a SMBDirect payload
- * rqst: the data to write
- * return value: 0 if successfully write, otherwise error code
- */
-int smbd_send(struct TCP_Server_Info *server,
- int num_rqst, struct smb_rqst *rqst_array)
-{
- struct smbd_connection *info = server->smbd_conn;
- struct kvec vecs[SMBDIRECT_MAX_SEND_SGE - 1];
- int nvecs;
- int size;
- unsigned int buflen, remaining_data_length;
- unsigned int offset, remaining_vec_data_length;
- int start, i, j;
- int max_iov_size =
- info->max_send_size - sizeof(struct smbd_data_transfer);
- struct kvec *iov;
- int rc;
- struct smb_rqst *rqst;
- int rqst_idx;
-
- if (info->transport_status != SMBD_CONNECTED)
- return -EAGAIN;
-
- /*
- * Add in the page array if there is one. The caller needs to set
- * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and
- * ends at page boundary
- */
- remaining_data_length = 0;
- for (i = 0; i < num_rqst; i++)
- remaining_data_length += smb_rqst_len(server, &rqst_array[i]);
-
- if (unlikely(remaining_data_length > info->max_fragmented_send_size)) {
- /* assertion: payload never exceeds negotiated maximum */
- log_write(ERR, "payload size %d > max size %d\n",
- remaining_data_length, info->max_fragmented_send_size);
- return -EINVAL;
- }
-
- log_write(INFO, "num_rqst=%d total length=%u\n",
- num_rqst, remaining_data_length);
-
- rqst_idx = 0;
- do {
- rqst = &rqst_array[rqst_idx];
- iov = rqst->rq_iov;
-
- cifs_dbg(FYI, "Sending smb (RDMA): idx=%d smb_len=%lu\n",
- rqst_idx, smb_rqst_len(server, rqst));
- remaining_vec_data_length = 0;
- for (i = 0; i < rqst->rq_nvec; i++) {
- remaining_vec_data_length += iov[i].iov_len;
- dump_smb(iov[i].iov_base, iov[i].iov_len);
- }
-
- log_write(INFO, "rqst_idx=%d nvec=%d rqst->rq_npages=%d rq_pagesz=%d rq_tailsz=%d buflen=%lu\n",
- rqst_idx, rqst->rq_nvec,
- rqst->rq_npages, rqst->rq_pagesz,
- rqst->rq_tailsz, smb_rqst_len(server, rqst));
-
- start = 0;
- offset = 0;
- do {
- buflen = 0;
- i = start;
- j = 0;
- while (i < rqst->rq_nvec &&
- j < SMBDIRECT_MAX_SEND_SGE - 1 &&
- buflen < max_iov_size) {
-
- vecs[j].iov_base = iov[i].iov_base + offset;
- if (buflen + iov[i].iov_len > max_iov_size) {
- vecs[j].iov_len =
- max_iov_size - iov[i].iov_len;
- buflen = max_iov_size;
- offset = vecs[j].iov_len;
- } else {
- vecs[j].iov_len =
- iov[i].iov_len - offset;
- buflen += vecs[j].iov_len;
- offset = 0;
- ++i;
- }
- ++j;
- }
-
- remaining_vec_data_length -= buflen;
- remaining_data_length -= buflen;
- log_write(INFO, "sending %s iov[%d] from start=%d nvecs=%d remaining_data_length=%d\n",
- remaining_vec_data_length > 0 ?
- "partial" : "complete",
- rqst->rq_nvec, start, j,
- remaining_data_length);
-
- start = i;
- rc = smbd_post_send_data(info, vecs, j, remaining_data_length);
- if (rc)
- goto done;
- } while (remaining_vec_data_length > 0);
-
- /* now sending pages if there are any */
- for (i = 0; i < rqst->rq_npages; i++) {
- rqst_page_get_length(rqst, i, &buflen, &offset);
- nvecs = (buflen + max_iov_size - 1) / max_iov_size;
- log_write(INFO, "sending pages buflen=%d nvecs=%d\n",
- buflen, nvecs);
- for (j = 0; j < nvecs; j++) {
- size = min_t(unsigned int, max_iov_size, remaining_data_length);
- remaining_data_length -= size;
- log_write(INFO, "sending pages i=%d offset=%d size=%d remaining_data_length=%d\n",
- i, j * max_iov_size + offset, size,
- remaining_data_length);
- rc = smbd_post_send_page(
- info, rqst->rq_pages[i],
- j*max_iov_size + offset,
- size, remaining_data_length);
- if (rc)
- goto done;
- }
- }
- } while (++rqst_idx < num_rqst);
-
-done:
- /*
- * As an optimization, we don't wait for individual I/O to finish
- * before sending the next one.
- * Send them all and wait for pending send count to get to 0
- * that means all the I/Os have been out and we are good to return
- */
-
- wait_event(info->wait_send_pending,
- atomic_read(&info->send_pending) == 0);
-
- return rc;
-}
-
-static void register_mr_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smbd_mr *mr;
- struct ib_cqe *cqe;
-
- if (wc->status) {
- log_rdma_mr(ERR, "status=%d\n", wc->status);
- cqe = wc->wr_cqe;
- mr = container_of(cqe, struct smbd_mr, cqe);
- smbd_disconnect_rdma_connection(mr->conn);
- }
-}
-
-/*
- * The work queue function that recovers MRs
- * We need to call ib_dereg_mr() and ib_alloc_mr() before this MR can be used
- * again. Both calls are slow, so finish them in a workqueue. This will not
- * block I/O path.
- * There is one workqueue that recovers MRs, there is no need to lock as the
- * I/O requests calling smbd_register_mr will never update the links in the
- * mr_list.
- */
-static void smbd_mr_recovery_work(struct work_struct *work)
-{
- struct smbd_connection *info =
- container_of(work, struct smbd_connection, mr_recovery_work);
- struct smbd_mr *smbdirect_mr;
- int rc;
-
- list_for_each_entry(smbdirect_mr, &info->mr_list, list) {
- if (smbdirect_mr->state == MR_ERROR) {
-
- /* recover this MR entry */
- rc = ib_dereg_mr(smbdirect_mr->mr);
- if (rc) {
- log_rdma_mr(ERR,
- "ib_dereg_mr failed rc=%x\n",
- rc);
- smbd_disconnect_rdma_connection(info);
- continue;
- }
-
- smbdirect_mr->mr = ib_alloc_mr(
- info->pd, info->mr_type,
- info->max_frmr_depth);
- if (IS_ERR(smbdirect_mr->mr)) {
- log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x max_frmr_depth=%x\n",
- info->mr_type,
- info->max_frmr_depth);
- smbd_disconnect_rdma_connection(info);
- continue;
- }
- } else
- /* This MR is being used, don't recover it */
- continue;
-
- smbdirect_mr->state = MR_READY;
-
- /* smbdirect_mr->state is updated by this function
- * and is read and updated by I/O issuing CPUs trying
- * to get a MR, the call to atomic_inc_return
- * implicates a memory barrier and guarantees this
- * value is updated before waking up any calls to
- * get_mr() from the I/O issuing CPUs
- */
- if (atomic_inc_return(&info->mr_ready_count) == 1)
- wake_up_interruptible(&info->wait_mr);
- }
-}
-
-static void destroy_mr_list(struct smbd_connection *info)
-{
- struct smbd_mr *mr, *tmp;
-
- cancel_work_sync(&info->mr_recovery_work);
- list_for_each_entry_safe(mr, tmp, &info->mr_list, list) {
- if (mr->state == MR_INVALIDATED)
- ib_dma_unmap_sg(info->id->device, mr->sgl,
- mr->sgl_count, mr->dir);
- ib_dereg_mr(mr->mr);
- kfree(mr->sgl);
- kfree(mr);
- }
-}
-
-/*
- * Allocate MRs used for RDMA read/write
- * The number of MRs will not exceed hardware capability in responder_resources
- * All MRs are kept in mr_list. The MR can be recovered after it's used
- * Recovery is done in smbd_mr_recovery_work. The content of list entry changes
- * as MRs are used and recovered for I/O, but the list links will not change
- */
-static int allocate_mr_list(struct smbd_connection *info)
-{
- int i;
- struct smbd_mr *smbdirect_mr, *tmp;
-
- INIT_LIST_HEAD(&info->mr_list);
- init_waitqueue_head(&info->wait_mr);
- spin_lock_init(&info->mr_list_lock);
- atomic_set(&info->mr_ready_count, 0);
- atomic_set(&info->mr_used_count, 0);
- init_waitqueue_head(&info->wait_for_mr_cleanup);
- INIT_WORK(&info->mr_recovery_work, smbd_mr_recovery_work);
- /* Allocate more MRs (2x) than hardware responder_resources */
- for (i = 0; i < info->responder_resources * 2; i++) {
- smbdirect_mr = kzalloc(sizeof(*smbdirect_mr), GFP_KERNEL);
- if (!smbdirect_mr)
- goto out;
- smbdirect_mr->mr = ib_alloc_mr(info->pd, info->mr_type,
- info->max_frmr_depth);
- if (IS_ERR(smbdirect_mr->mr)) {
- log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x max_frmr_depth=%x\n",
- info->mr_type, info->max_frmr_depth);
- goto out;
- }
- smbdirect_mr->sgl = kcalloc(
- info->max_frmr_depth,
- sizeof(struct scatterlist),
- GFP_KERNEL);
- if (!smbdirect_mr->sgl) {
- log_rdma_mr(ERR, "failed to allocate sgl\n");
- ib_dereg_mr(smbdirect_mr->mr);
- goto out;
- }
- smbdirect_mr->state = MR_READY;
- smbdirect_mr->conn = info;
-
- list_add_tail(&smbdirect_mr->list, &info->mr_list);
- atomic_inc(&info->mr_ready_count);
- }
- return 0;
-
-out:
- kfree(smbdirect_mr);
-
- list_for_each_entry_safe(smbdirect_mr, tmp, &info->mr_list, list) {
- list_del(&smbdirect_mr->list);
- ib_dereg_mr(smbdirect_mr->mr);
- kfree(smbdirect_mr->sgl);
- kfree(smbdirect_mr);
- }
- return -ENOMEM;
-}
-
-/*
- * Get a MR from mr_list. This function waits until there is at least one
- * MR available in the list. It may access the list while the
- * smbd_mr_recovery_work is recovering the MR list. This doesn't need a lock
- * as they never modify the same places. However, there may be several CPUs
- * issueing I/O trying to get MR at the same time, mr_list_lock is used to
- * protect this situation.
- */
-static struct smbd_mr *get_mr(struct smbd_connection *info)
-{
- struct smbd_mr *ret;
- int rc;
-again:
- rc = wait_event_interruptible(info->wait_mr,
- atomic_read(&info->mr_ready_count) ||
- info->transport_status != SMBD_CONNECTED);
- if (rc) {
- log_rdma_mr(ERR, "wait_event_interruptible rc=%x\n", rc);
- return NULL;
- }
-
- if (info->transport_status != SMBD_CONNECTED) {
- log_rdma_mr(ERR, "info->transport_status=%x\n",
- info->transport_status);
- return NULL;
- }
-
- spin_lock(&info->mr_list_lock);
- list_for_each_entry(ret, &info->mr_list, list) {
- if (ret->state == MR_READY) {
- ret->state = MR_REGISTERED;
- spin_unlock(&info->mr_list_lock);
- atomic_dec(&info->mr_ready_count);
- atomic_inc(&info->mr_used_count);
- return ret;
- }
- }
-
- spin_unlock(&info->mr_list_lock);
- /*
- * It is possible that we could fail to get MR because other processes may
- * try to acquire a MR at the same time. If this is the case, retry it.
- */
- goto again;
-}
-
-/*
- * Register memory for RDMA read/write
- * pages[]: the list of pages to register memory with
- * num_pages: the number of pages to register
- * tailsz: if non-zero, the bytes to register in the last page
- * writing: true if this is a RDMA write (SMB read), false for RDMA read
- * need_invalidate: true if this MR needs to be locally invalidated after I/O
- * return value: the MR registered, NULL if failed.
- */
-struct smbd_mr *smbd_register_mr(
- struct smbd_connection *info, struct page *pages[], int num_pages,
- int offset, int tailsz, bool writing, bool need_invalidate)
-{
- struct smbd_mr *smbdirect_mr;
- int rc, i;
- enum dma_data_direction dir;
- struct ib_reg_wr *reg_wr;
-
- if (num_pages > info->max_frmr_depth) {
- log_rdma_mr(ERR, "num_pages=%d max_frmr_depth=%d\n",
- num_pages, info->max_frmr_depth);
- return NULL;
- }
-
- smbdirect_mr = get_mr(info);
- if (!smbdirect_mr) {
- log_rdma_mr(ERR, "get_mr returning NULL\n");
- return NULL;
- }
- smbdirect_mr->need_invalidate = need_invalidate;
- smbdirect_mr->sgl_count = num_pages;
- sg_init_table(smbdirect_mr->sgl, num_pages);
-
- log_rdma_mr(INFO, "num_pages=0x%x offset=0x%x tailsz=0x%x\n",
- num_pages, offset, tailsz);
-
- if (num_pages == 1) {
- sg_set_page(&smbdirect_mr->sgl[0], pages[0], tailsz, offset);
- goto skip_multiple_pages;
- }
-
- /* We have at least two pages to register */
- sg_set_page(
- &smbdirect_mr->sgl[0], pages[0], PAGE_SIZE - offset, offset);
- i = 1;
- while (i < num_pages - 1) {
- sg_set_page(&smbdirect_mr->sgl[i], pages[i], PAGE_SIZE, 0);
- i++;
- }
- sg_set_page(&smbdirect_mr->sgl[i], pages[i],
- tailsz ? tailsz : PAGE_SIZE, 0);
-
-skip_multiple_pages:
- dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
- smbdirect_mr->dir = dir;
- rc = ib_dma_map_sg(info->id->device, smbdirect_mr->sgl, num_pages, dir);
- if (!rc) {
- log_rdma_mr(ERR, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",
- num_pages, dir, rc);
- goto dma_map_error;
- }
-
- rc = ib_map_mr_sg(smbdirect_mr->mr, smbdirect_mr->sgl, num_pages,
- NULL, PAGE_SIZE);
- if (rc != num_pages) {
- log_rdma_mr(ERR,
- "ib_map_mr_sg failed rc = %d num_pages = %x\n",
- rc, num_pages);
- goto map_mr_error;
- }
-
- ib_update_fast_reg_key(smbdirect_mr->mr,
- ib_inc_rkey(smbdirect_mr->mr->rkey));
- reg_wr = &smbdirect_mr->wr;
- reg_wr->wr.opcode = IB_WR_REG_MR;
- smbdirect_mr->cqe.done = register_mr_done;
- reg_wr->wr.wr_cqe = &smbdirect_mr->cqe;
- reg_wr->wr.num_sge = 0;
- reg_wr->wr.send_flags = IB_SEND_SIGNALED;
- reg_wr->mr = smbdirect_mr->mr;
- reg_wr->key = smbdirect_mr->mr->rkey;
- reg_wr->access = writing ?
- IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
- IB_ACCESS_REMOTE_READ;
-
- /*
- * There is no need for waiting for complemtion on ib_post_send
- * on IB_WR_REG_MR. Hardware enforces a barrier and order of execution
- * on the next ib_post_send when we actaully send I/O to remote peer
- */
- rc = ib_post_send(info->id->qp, ®_wr->wr, NULL);
- if (!rc)
- return smbdirect_mr;
-
- log_rdma_mr(ERR, "ib_post_send failed rc=%x reg_wr->key=%x\n",
- rc, reg_wr->key);
-
- /* If all failed, attempt to recover this MR by setting it MR_ERROR*/
-map_mr_error:
- ib_dma_unmap_sg(info->id->device, smbdirect_mr->sgl,
- smbdirect_mr->sgl_count, smbdirect_mr->dir);
-
-dma_map_error:
- smbdirect_mr->state = MR_ERROR;
- if (atomic_dec_and_test(&info->mr_used_count))
- wake_up(&info->wait_for_mr_cleanup);
-
- smbd_disconnect_rdma_connection(info);
-
- return NULL;
-}
-
-static void local_inv_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smbd_mr *smbdirect_mr;
- struct ib_cqe *cqe;
-
- cqe = wc->wr_cqe;
- smbdirect_mr = container_of(cqe, struct smbd_mr, cqe);
- smbdirect_mr->state = MR_INVALIDATED;
- if (wc->status != IB_WC_SUCCESS) {
- log_rdma_mr(ERR, "invalidate failed status=%x\n", wc->status);
- smbdirect_mr->state = MR_ERROR;
- }
- complete(&smbdirect_mr->invalidate_done);
-}
-
-/*
- * Deregister a MR after I/O is done
- * This function may wait if remote invalidation is not used
- * and we have to locally invalidate the buffer to prevent data is being
- * modified by remote peer after upper layer consumes it
- */
-int smbd_deregister_mr(struct smbd_mr *smbdirect_mr)
-{
- struct ib_send_wr *wr;
- struct smbd_connection *info = smbdirect_mr->conn;
- int rc = 0;
-
- if (smbdirect_mr->need_invalidate) {
- /* Need to finish local invalidation before returning */
- wr = &smbdirect_mr->inv_wr;
- wr->opcode = IB_WR_LOCAL_INV;
- smbdirect_mr->cqe.done = local_inv_done;
- wr->wr_cqe = &smbdirect_mr->cqe;
- wr->num_sge = 0;
- wr->ex.invalidate_rkey = smbdirect_mr->mr->rkey;
- wr->send_flags = IB_SEND_SIGNALED;
-
- init_completion(&smbdirect_mr->invalidate_done);
- rc = ib_post_send(info->id->qp, wr, NULL);
- if (rc) {
- log_rdma_mr(ERR, "ib_post_send failed rc=%x\n", rc);
- smbd_disconnect_rdma_connection(info);
- goto done;
- }
- wait_for_completion(&smbdirect_mr->invalidate_done);
- smbdirect_mr->need_invalidate = false;
- } else
- /*
- * For remote invalidation, just set it to MR_INVALIDATED
- * and defer to mr_recovery_work to recover the MR for next use
- */
- smbdirect_mr->state = MR_INVALIDATED;
-
- if (smbdirect_mr->state == MR_INVALIDATED) {
- ib_dma_unmap_sg(
- info->id->device, smbdirect_mr->sgl,
- smbdirect_mr->sgl_count,
- smbdirect_mr->dir);
- smbdirect_mr->state = MR_READY;
- if (atomic_inc_return(&info->mr_ready_count) == 1)
- wake_up_interruptible(&info->wait_mr);
- } else
- /*
- * Schedule the work to do MR recovery for future I/Os MR
- * recovery is slow and don't want it to block current I/O
- */
- queue_work(info->workqueue, &info->mr_recovery_work);
-
-done:
- if (atomic_dec_and_test(&info->mr_used_count))
- wake_up(&info->wait_for_mr_cleanup);
-
- return rc;
-}
diff --git a/fs/cifs/smbdirect.h b/fs/cifs/smbdirect.h
deleted file mode 100644
index 207ef979cd51..000000000000
--- a/fs/cifs/smbdirect.h
+++ /dev/null
@@ -1,320 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2017, Microsoft Corporation.
- *
- * Author(s): Long Li <longli@microsoft.com>
- */
-#ifndef _SMBDIRECT_H
-#define _SMBDIRECT_H
-
-#ifdef CONFIG_CIFS_SMB_DIRECT
-#define cifs_rdma_enabled(server) ((server)->rdma)
-
-#include "cifsglob.h"
-#include <rdma/ib_verbs.h>
-#include <rdma/rdma_cm.h>
-#include <linux/mempool.h>
-
-extern int rdma_readwrite_threshold;
-extern int smbd_max_frmr_depth;
-extern int smbd_keep_alive_interval;
-extern int smbd_max_receive_size;
-extern int smbd_max_fragmented_recv_size;
-extern int smbd_max_send_size;
-extern int smbd_send_credit_target;
-extern int smbd_receive_credit_max;
-
-enum keep_alive_status {
- KEEP_ALIVE_NONE,
- KEEP_ALIVE_PENDING,
- KEEP_ALIVE_SENT,
-};
-
-enum smbd_connection_status {
- SMBD_CREATED,
- SMBD_CONNECTING,
- SMBD_CONNECTED,
- SMBD_NEGOTIATE_FAILED,
- SMBD_DISCONNECTING,
- SMBD_DISCONNECTED,
- SMBD_DESTROYED
-};
-
-/*
- * The context for the SMBDirect transport
- * Everything related to the transport is here. It has several logical parts
- * 1. RDMA related structures
- * 2. SMBDirect connection parameters
- * 3. Memory registrations
- * 4. Receive and reassembly queues for data receive path
- * 5. mempools for allocating packets
- */
-struct smbd_connection {
- enum smbd_connection_status transport_status;
-
- /* RDMA related */
- struct rdma_cm_id *id;
- struct ib_qp_init_attr qp_attr;
- struct ib_pd *pd;
- struct ib_cq *send_cq, *recv_cq;
- struct ib_device_attr dev_attr;
- int ri_rc;
- struct completion ri_done;
- wait_queue_head_t conn_wait;
- wait_queue_head_t disconn_wait;
-
- struct completion negotiate_completion;
- bool negotiate_done;
-
- struct work_struct disconnect_work;
- struct work_struct post_send_credits_work;
-
- spinlock_t lock_new_credits_offered;
- int new_credits_offered;
-
- /* Connection parameters defined in [MS-SMBD] 3.1.1.1 */
- int receive_credit_max;
- int send_credit_target;
- int max_send_size;
- int max_fragmented_recv_size;
- int max_fragmented_send_size;
- int max_receive_size;
- int keep_alive_interval;
- int max_readwrite_size;
- enum keep_alive_status keep_alive_requested;
- int protocol;
- atomic_t send_credits;
- atomic_t receive_credits;
- int receive_credit_target;
- int fragment_reassembly_remaining;
-
- /* Memory registrations */
- /* Maximum number of RDMA read/write outstanding on this connection */
- int responder_resources;
- /* Maximum number of pages in a single RDMA write/read on this connection */
- int max_frmr_depth;
- /*
- * If payload is less than or equal to the threshold,
- * use RDMA send/recv to send upper layer I/O.
- * If payload is more than the threshold,
- * use RDMA read/write through memory registration for I/O.
- */
- int rdma_readwrite_threshold;
- enum ib_mr_type mr_type;
- struct list_head mr_list;
- spinlock_t mr_list_lock;
- /* The number of available MRs ready for memory registration */
- atomic_t mr_ready_count;
- atomic_t mr_used_count;
- wait_queue_head_t wait_mr;
- struct work_struct mr_recovery_work;
- /* Used by transport to wait until all MRs are returned */
- wait_queue_head_t wait_for_mr_cleanup;
-
- /* Activity accoutning */
- atomic_t send_pending;
- wait_queue_head_t wait_send_pending;
- wait_queue_head_t wait_post_send;
-
- /* Receive queue */
- struct list_head receive_queue;
- int count_receive_queue;
- spinlock_t receive_queue_lock;
-
- struct list_head empty_packet_queue;
- int count_empty_packet_queue;
- spinlock_t empty_packet_queue_lock;
-
- wait_queue_head_t wait_receive_queues;
-
- /* Reassembly queue */
- struct list_head reassembly_queue;
- spinlock_t reassembly_queue_lock;
- wait_queue_head_t wait_reassembly_queue;
-
- /* total data length of reassembly queue */
- int reassembly_data_length;
- int reassembly_queue_length;
- /* the offset to first buffer in reassembly queue */
- int first_entry_offset;
-
- bool send_immediate;
-
- wait_queue_head_t wait_send_queue;
-
- /*
- * Indicate if we have received a full packet on the connection
- * This is used to identify the first SMBD packet of a assembled
- * payload (SMB packet) in reassembly queue so we can return a
- * RFC1002 length to upper layer to indicate the length of the SMB
- * packet received
- */
- bool full_packet_received;
-
- struct workqueue_struct *workqueue;
- struct delayed_work idle_timer_work;
-
- /* Memory pool for preallocating buffers */
- /* request pool for RDMA send */
- struct kmem_cache *request_cache;
- mempool_t *request_mempool;
-
- /* response pool for RDMA receive */
- struct kmem_cache *response_cache;
- mempool_t *response_mempool;
-
- /* for debug purposes */
- unsigned int count_get_receive_buffer;
- unsigned int count_put_receive_buffer;
- unsigned int count_reassembly_queue;
- unsigned int count_enqueue_reassembly_queue;
- unsigned int count_dequeue_reassembly_queue;
- unsigned int count_send_empty;
-};
-
-enum smbd_message_type {
- SMBD_NEGOTIATE_RESP,
- SMBD_TRANSFER_DATA,
-};
-
-#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
-
-/* SMBD negotiation request packet [MS-SMBD] 2.2.1 */
-struct smbd_negotiate_req {
- __le16 min_version;
- __le16 max_version;
- __le16 reserved;
- __le16 credits_requested;
- __le32 preferred_send_size;
- __le32 max_receive_size;
- __le32 max_fragmented_size;
-} __packed;
-
-/* SMBD negotiation response packet [MS-SMBD] 2.2.2 */
-struct smbd_negotiate_resp {
- __le16 min_version;
- __le16 max_version;
- __le16 negotiated_version;
- __le16 reserved;
- __le16 credits_requested;
- __le16 credits_granted;
- __le32 status;
- __le32 max_readwrite_size;
- __le32 preferred_send_size;
- __le32 max_receive_size;
- __le32 max_fragmented_size;
-} __packed;
-
-/* SMBD data transfer packet with payload [MS-SMBD] 2.2.3 */
-struct smbd_data_transfer {
- __le16 credits_requested;
- __le16 credits_granted;
- __le16 flags;
- __le16 reserved;
- __le32 remaining_data_length;
- __le32 data_offset;
- __le32 data_length;
- __le32 padding;
- __u8 buffer[];
-} __packed;
-
-/* The packet fields for a registered RDMA buffer */
-struct smbd_buffer_descriptor_v1 {
- __le64 offset;
- __le32 token;
- __le32 length;
-} __packed;
-
-/* Maximum number of SGEs used by smbdirect.c in any send work request */
-#define SMBDIRECT_MAX_SEND_SGE 6
-
-/* The context for a SMBD request */
-struct smbd_request {
- struct smbd_connection *info;
- struct ib_cqe cqe;
-
- /* the SGE entries for this work request */
- struct ib_sge sge[SMBDIRECT_MAX_SEND_SGE];
- int num_sge;
-
- /* SMBD packet header follows this structure */
- u8 packet[];
-};
-
-/* Maximum number of SGEs used by smbdirect.c in any receive work request */
-#define SMBDIRECT_MAX_RECV_SGE 1
-
-/* The context for a SMBD response */
-struct smbd_response {
- struct smbd_connection *info;
- struct ib_cqe cqe;
- struct ib_sge sge;
-
- enum smbd_message_type type;
-
- /* Link to receive queue or reassembly queue */
- struct list_head list;
-
- /* Indicate if this is the 1st packet of a payload */
- bool first_segment;
-
- /* SMBD packet header and payload follows this structure */
- u8 packet[];
-};
-
-/* Create a SMBDirect session */
-struct smbd_connection *smbd_get_connection(
- struct TCP_Server_Info *server, struct sockaddr *dstaddr);
-
-/* Reconnect SMBDirect session */
-int smbd_reconnect(struct TCP_Server_Info *server);
-/* Destroy SMBDirect session */
-void smbd_destroy(struct TCP_Server_Info *server);
-
-/* Interface for carrying upper layer I/O through send/recv */
-int smbd_recv(struct smbd_connection *info, struct msghdr *msg);
-int smbd_send(struct TCP_Server_Info *server,
- int num_rqst, struct smb_rqst *rqst);
-
-enum mr_state {
- MR_READY,
- MR_REGISTERED,
- MR_INVALIDATED,
- MR_ERROR
-};
-
-struct smbd_mr {
- struct smbd_connection *conn;
- struct list_head list;
- enum mr_state state;
- struct ib_mr *mr;
- struct scatterlist *sgl;
- int sgl_count;
- enum dma_data_direction dir;
- union {
- struct ib_reg_wr wr;
- struct ib_send_wr inv_wr;
- };
- struct ib_cqe cqe;
- bool need_invalidate;
- struct completion invalidate_done;
-};
-
-/* Interfaces to register and deregister MR for RDMA read/write */
-struct smbd_mr *smbd_register_mr(
- struct smbd_connection *info, struct page *pages[], int num_pages,
- int offset, int tailsz, bool writing, bool need_invalidate);
-int smbd_deregister_mr(struct smbd_mr *mr);
-
-#else
-#define cifs_rdma_enabled(server) 0
-struct smbd_connection {};
-static inline void *smbd_get_connection(
- struct TCP_Server_Info *server, struct sockaddr *dstaddr) {return NULL;}
-static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1; }
-static inline void smbd_destroy(struct TCP_Server_Info *server) {}
-static inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1; }
-static inline int smbd_send(struct TCP_Server_Info *server, int num_rqst, struct smb_rqst *rqst) {return -1; }
-#endif
-
-#endif
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
deleted file mode 100644
index 4a0487753869..000000000000
--- a/fs/cifs/smbencrypt.c
+++ /dev/null
@@ -1,91 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- SMB parameters and setup
- Copyright (C) Andrew Tridgell 1992-2000
- Copyright (C) Luke Kenneth Casson Leighton 1996-2000
- Modified by Jeremy Allison 1995.
- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
- Modified by Steve French (sfrench@us.ibm.com) 2002-2003
-
-*/
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/fips.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/random.h>
-#include "cifs_fs_sb.h"
-#include "cifs_unicode.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifs_debug.h"
-#include "cifsproto.h"
-#include "../smbfs_common/md4.h"
-
-#ifndef false
-#define false 0
-#endif
-#ifndef true
-#define true 1
-#endif
-
-/* following came from the other byteorder.h to avoid include conflicts */
-#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
-#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
-#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
-
-/* produce a md4 message digest from data of length n bytes */
-static int
-mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
-{
- int rc;
- struct md4_ctx mctx;
-
- rc = cifs_md4_init(&mctx);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not init MD4\n", __func__);
- goto mdfour_err;
- }
- rc = cifs_md4_update(&mctx, link_str, link_len);
- if (rc) {
- cifs_dbg(VFS, "%s: Could not update MD4\n", __func__);
- goto mdfour_err;
- }
- rc = cifs_md4_final(&mctx, md4_hash);
- if (rc)
- cifs_dbg(VFS, "%s: Could not finalize MD4\n", __func__);
-
-
-mdfour_err:
- return rc;
-}
-
-/*
- * Creates the MD4 Hash of the users password in NT UNICODE.
- */
-
-int
-E_md4hash(const unsigned char *passwd, unsigned char *p16,
- const struct nls_table *codepage)
-{
- int rc;
- int len;
- __le16 wpwd[129];
-
- /* Password cannot be longer than 128 characters */
- if (passwd) /* Password must be converted to NT unicode */
- len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
- else {
- len = 0;
- *wpwd = 0; /* Ensure string is null terminated */
- }
-
- rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__le16));
- memzero_explicit(wpwd, sizeof(wpwd));
-
- return rc;
-}
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
deleted file mode 100644
index aeffdad829e2..000000000000
--- a/fs/cifs/smberr.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-/*
- *
- * Copyright (c) International Business Machines Corp., 2002,2004
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- * See Error Codes section of the SNIA CIFS Specification
- * for more information
- *
- */
-
-#define SUCCESS 0x00 /* The request was successful. */
-#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
-#define ERRSRV 0x02 /* Error is generated by the file server daemon */
-#define ERRHRD 0x03 /* Error is a hardware error. */
-#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
-
-/* The following error codes may be generated with the SUCCESS error class.*/
-
-/*#define SUCCESS 0 The request was successful. */
-
-/* The following error codes may be generated with the ERRDOS error class.*/
-
-#define ERRbadfunc 1 /* Invalid function. The server did not
- recognize or could not perform a
- system call generated by the server,
- e.g., set the DIRECTORY attribute on
- a data file, invalid seek mode. */
-#define ERRbadfile 2 /* File not found. The last component
- of a file's pathname could not be
- found. */
-#define ERRbadpath 3 /* Directory invalid. A directory
- component in a pathname could not be
- found. */
-#define ERRnofids 4 /* Too many open files. The server has
- no file handles available. */
-#define ERRnoaccess 5 /* Access denied, the client's context
- does not permit the requested
- function. This includes the
- following conditions: invalid rename
- command, write to Fid open for read
- only, read on Fid open for write
- only, attempt to delete a non-empty
- directory */
-#define ERRbadfid 6 /* Invalid file handle. The file handle
- specified was not recognized by the
- server. */
-#define ERRbadmcb 7 /* Memory control blocks destroyed. */
-#define ERRnomem 8 /* Insufficient server memory to
- perform the requested function. */
-#define ERRbadmem 9 /* Invalid memory block address. */
-#define ERRbadenv 10 /* Invalid environment. */
-#define ERRbadformat 11 /* Invalid format. */
-#define ERRbadaccess 12 /* Invalid open mode. */
-#define ERRbaddata 13 /* Invalid data (generated only by
- IOCTL calls within the server). */
-#define ERRbaddrive 15 /* Invalid drive specified. */
-#define ERRremcd 16 /* A Delete Directory request attempted
- to remove the server's current
- directory. */
-#define ERRdiffdevice 17 /* Not same device (e.g., a cross
- volume rename was attempted */
-#define ERRnofiles 18 /* A File Search command can find no
- more files matching the specified
- criteria. */
-#define ERRwriteprot 19 /* media is write protected */
-#define ERRgeneral 31
-#define ERRbadshare 32 /* The sharing mode specified for an
- Open conflicts with existing FIDs on
- the file. */
-#define ERRlock 33 /* A Lock request conflicted with an
- existing lock or specified an
- invalid mode, or an Unlock requested
- attempted to remove a lock held by
- another process. */
-#define ERRunsup 50
-#define ERRnosuchshare 67
-#define ERRfilexists 80 /* The file named in the request
- already exists. */
-#define ERRinvparm 87
-#define ERRdiskfull 112
-#define ERRinvname 123
-#define ERRinvlevel 124
-#define ERRdirnotempty 145
-#define ERRnotlocked 158
-#define ERRcancelviolation 173
-#define ERRalreadyexists 183
-#define ERRbadpipe 230
-#define ERRpipebusy 231
-#define ERRpipeclosing 232
-#define ERRnotconnected 233
-#define ERRmoredata 234
-#define ERReasnotsupported 282
-#define ErrQuota 0x200 /* The operation would cause a quota
- limit to be exceeded. */
-#define ErrNotALink 0x201 /* A link operation was performed on a
- pathname that was not a link. */
-
-/* Below errors are used internally (do not come over the wire) for passthrough
- from STATUS codes to POSIX only */
-#define ERRsymlink 0xFFFD
-#define ErrTooManyLinks 0xFFFE
-
-/* Following error codes may be generated with the ERRSRV error class.*/
-
-#define ERRerror 1 /* Non-specific error code. It is
- returned under the following
- conditions: resource other than disk
- space exhausted (e.g. TIDs), first
- SMB command was not negotiate,
- multiple negotiates attempted, and
- internal server error. */
-#define ERRbadpw 2 /* Bad password - name/password pair in
- a TreeConnect or Session Setup are
- invalid. */
-#define ERRbadtype 3 /* used for indicating DFS referral
- needed */
-#define ERRaccess 4 /* The client does not have the
- necessary access rights within the
- specified context for requested
- function. */
-#define ERRinvtid 5 /* The Tid specified in a command was
- invalid. */
-#define ERRinvnetname 6 /* Invalid network name in tree
- connect. */
-#define ERRinvdevice 7 /* Invalid device - printer request
- made to non-printer connection or
- non-printer request made to printer
- connection. */
-#define ERRqfull 49 /* Print queue full (files) -- returned
- by open print file. */
-#define ERRqtoobig 50 /* Print queue full -- no space. */
-#define ERRqeof 51 /* EOF on print queue dump */
-#define ERRinvpfid 52 /* Invalid print file FID. */
-#define ERRsmbcmd 64 /* The server did not recognize the
- command received. */
-#define ERRsrverror 65 /* The server encountered an internal
- error, e.g., system file
- unavailable. */
-#define ERRbadBID 66 /* (obsolete) */
-#define ERRfilespecs 67 /* The Fid and pathname parameters
- contained an invalid combination of
- values. */
-#define ERRbadLink 68 /* (obsolete) */
-#define ERRbadpermits 69 /* The access permissions specified for
- a file or directory are not a valid
- combination. */
-#define ERRbadPID 70
-#define ERRsetattrmode 71 /* attribute (mode) is invalid */
-#define ERRpaused 81 /* Server is paused */
-#define ERRmsgoff 82 /* reserved - messaging off */
-#define ERRnoroom 83 /* reserved - no room for message */
-#define ERRrmuns 87 /* reserved - too many remote names */
-#define ERRtimeout 88 /* operation timed out */
-#define ERRnoresource 89 /* No resources available for request
- */
-#define ERRtoomanyuids 90 /* Too many UIDs active on this session
- */
-#define ERRbaduid 91 /* The UID is not known as a valid user
- */
-#define ERRusempx 250 /* temporarily unable to use raw */
-#define ERRusestd 251 /* temporarily unable to use either raw
- or mpx */
-#define ERR_NOTIFY_ENUM_DIR 1024
-#define ERRnoSuchUser 2238 /* user account does not exist */
-#define ERRaccountexpired 2239
-#define ERRbadclient 2240 /* can not logon from this client */
-#define ERRbadLogonTime 2241 /* logon hours do not allow this */
-#define ERRpasswordExpired 2242
-#define ERRnetlogonNotStarted 2455
-#define ERRnosupport 0xFFFF
diff --git a/fs/cifs/trace.c b/fs/cifs/trace.c
deleted file mode 100644
index 465483787193..000000000000
--- a/fs/cifs/trace.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2018, Microsoft Corporation.
- *
- * Author(s): Steve French <stfrench@microsoft.com>
- */
-#define CREATE_TRACE_POINTS
-#include "trace.h"
diff --git a/fs/cifs/trace.h b/fs/cifs/trace.h
deleted file mode 100644
index d3053bd8ae73..000000000000
--- a/fs/cifs/trace.h
+++ /dev/null
@@ -1,1070 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2018, Microsoft Corporation.
- *
- * Author(s): Steve French <stfrench@microsoft.com>
- */
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM cifs
-
-#if !defined(_CIFS_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _CIFS_TRACE_H
-
-#include <linux/tracepoint.h>
-#include <linux/net.h>
-#include <linux/inet.h>
-
-/*
- * Please use this 3-part article as a reference for writing new tracepoints:
- * https://lwn.net/Articles/379903/
- */
-
-/* For logging errors in read or write */
-DECLARE_EVENT_CLASS(smb3_rw_err_class,
- TP_PROTO(unsigned int xid,
- __u64 fid,
- __u32 tid,
- __u64 sesid,
- __u64 offset,
- __u32 len,
- int rc),
- TP_ARGS(xid, fid, tid, sesid, offset, len, rc),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u64, fid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(__u64, offset)
- __field(__u32, len)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->fid = fid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->offset = offset;
- __entry->len = len;
- __entry->rc = rc;
- ),
- TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d",
- __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
- __entry->offset, __entry->len, __entry->rc)
-)
-
-#define DEFINE_SMB3_RW_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_rw_err_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u64 fid, \
- __u32 tid, \
- __u64 sesid, \
- __u64 offset, \
- __u32 len, \
- int rc), \
- TP_ARGS(xid, fid, tid, sesid, offset, len, rc))
-
-DEFINE_SMB3_RW_ERR_EVENT(write_err);
-DEFINE_SMB3_RW_ERR_EVENT(read_err);
-DEFINE_SMB3_RW_ERR_EVENT(query_dir_err);
-DEFINE_SMB3_RW_ERR_EVENT(zero_err);
-DEFINE_SMB3_RW_ERR_EVENT(falloc_err);
-
-
-/* For logging successful read or write */
-DECLARE_EVENT_CLASS(smb3_rw_done_class,
- TP_PROTO(unsigned int xid,
- __u64 fid,
- __u32 tid,
- __u64 sesid,
- __u64 offset,
- __u32 len),
- TP_ARGS(xid, fid, tid, sesid, offset, len),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u64, fid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(__u64, offset)
- __field(__u32, len)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->fid = fid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->offset = offset;
- __entry->len = len;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x",
- __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
- __entry->offset, __entry->len)
-)
-
-#define DEFINE_SMB3_RW_DONE_EVENT(name) \
-DEFINE_EVENT(smb3_rw_done_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u64 fid, \
- __u32 tid, \
- __u64 sesid, \
- __u64 offset, \
- __u32 len), \
- TP_ARGS(xid, fid, tid, sesid, offset, len))
-
-DEFINE_SMB3_RW_DONE_EVENT(write_enter);
-DEFINE_SMB3_RW_DONE_EVENT(read_enter);
-DEFINE_SMB3_RW_DONE_EVENT(query_dir_enter);
-DEFINE_SMB3_RW_DONE_EVENT(zero_enter);
-DEFINE_SMB3_RW_DONE_EVENT(falloc_enter);
-DEFINE_SMB3_RW_DONE_EVENT(write_done);
-DEFINE_SMB3_RW_DONE_EVENT(read_done);
-DEFINE_SMB3_RW_DONE_EVENT(query_dir_done);
-DEFINE_SMB3_RW_DONE_EVENT(zero_done);
-DEFINE_SMB3_RW_DONE_EVENT(falloc_done);
-
-/* For logging successful set EOF (truncate) */
-DECLARE_EVENT_CLASS(smb3_eof_class,
- TP_PROTO(unsigned int xid,
- __u64 fid,
- __u32 tid,
- __u64 sesid,
- __u64 offset),
- TP_ARGS(xid, fid, tid, sesid, offset),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u64, fid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(__u64, offset)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->fid = fid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->offset = offset;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx",
- __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
- __entry->offset)
-)
-
-#define DEFINE_SMB3_EOF_EVENT(name) \
-DEFINE_EVENT(smb3_eof_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u64 fid, \
- __u32 tid, \
- __u64 sesid, \
- __u64 offset), \
- TP_ARGS(xid, fid, tid, sesid, offset))
-
-DEFINE_SMB3_EOF_EVENT(set_eof);
-
-/*
- * For handle based calls other than read and write, and get/set info
- */
-DECLARE_EVENT_CLASS(smb3_fd_class,
- TP_PROTO(unsigned int xid,
- __u64 fid,
- __u32 tid,
- __u64 sesid),
- TP_ARGS(xid, fid, tid, sesid),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u64, fid)
- __field(__u32, tid)
- __field(__u64, sesid)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->fid = fid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- ),
- TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx",
- __entry->xid, __entry->sesid, __entry->tid, __entry->fid)
-)
-
-#define DEFINE_SMB3_FD_EVENT(name) \
-DEFINE_EVENT(smb3_fd_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u64 fid, \
- __u32 tid, \
- __u64 sesid), \
- TP_ARGS(xid, fid, tid, sesid))
-
-DEFINE_SMB3_FD_EVENT(flush_enter);
-DEFINE_SMB3_FD_EVENT(flush_done);
-DEFINE_SMB3_FD_EVENT(close_enter);
-DEFINE_SMB3_FD_EVENT(close_done);
-DEFINE_SMB3_FD_EVENT(oplock_not_found);
-
-DECLARE_EVENT_CLASS(smb3_fd_err_class,
- TP_PROTO(unsigned int xid,
- __u64 fid,
- __u32 tid,
- __u64 sesid,
- int rc),
- TP_ARGS(xid, fid, tid, sesid, rc),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u64, fid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->fid = fid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->rc = rc;
- ),
- TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx rc=%d",
- __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
- __entry->rc)
-)
-
-#define DEFINE_SMB3_FD_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_fd_err_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u64 fid, \
- __u32 tid, \
- __u64 sesid, \
- int rc), \
- TP_ARGS(xid, fid, tid, sesid, rc))
-
-DEFINE_SMB3_FD_ERR_EVENT(flush_err);
-DEFINE_SMB3_FD_ERR_EVENT(lock_err);
-DEFINE_SMB3_FD_ERR_EVENT(close_err);
-
-/*
- * For handle based query/set info calls
- */
-DECLARE_EVENT_CLASS(smb3_inf_enter_class,
- TP_PROTO(unsigned int xid,
- __u64 fid,
- __u32 tid,
- __u64 sesid,
- __u8 infclass,
- __u32 type),
- TP_ARGS(xid, fid, tid, sesid, infclass, type),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u64, fid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(__u8, infclass)
- __field(__u32, type)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->fid = fid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->infclass = infclass;
- __entry->type = type;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx class=%u type=0x%x",
- __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
- __entry->infclass, __entry->type)
-)
-
-#define DEFINE_SMB3_INF_ENTER_EVENT(name) \
-DEFINE_EVENT(smb3_inf_enter_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u64 fid, \
- __u32 tid, \
- __u64 sesid, \
- __u8 infclass, \
- __u32 type), \
- TP_ARGS(xid, fid, tid, sesid, infclass, type))
-
-DEFINE_SMB3_INF_ENTER_EVENT(query_info_enter);
-DEFINE_SMB3_INF_ENTER_EVENT(query_info_done);
-DEFINE_SMB3_INF_ENTER_EVENT(notify_enter);
-DEFINE_SMB3_INF_ENTER_EVENT(notify_done);
-
-DECLARE_EVENT_CLASS(smb3_inf_err_class,
- TP_PROTO(unsigned int xid,
- __u64 fid,
- __u32 tid,
- __u64 sesid,
- __u8 infclass,
- __u32 type,
- int rc),
- TP_ARGS(xid, fid, tid, sesid, infclass, type, rc),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u64, fid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(__u8, infclass)
- __field(__u32, type)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->fid = fid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->infclass = infclass;
- __entry->type = type;
- __entry->rc = rc;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx class=%u type=0x%x rc=%d",
- __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
- __entry->infclass, __entry->type, __entry->rc)
-)
-
-#define DEFINE_SMB3_INF_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_inf_err_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u64 fid, \
- __u32 tid, \
- __u64 sesid, \
- __u8 infclass, \
- __u32 type, \
- int rc), \
- TP_ARGS(xid, fid, tid, sesid, infclass, type, rc))
-
-DEFINE_SMB3_INF_ERR_EVENT(query_info_err);
-DEFINE_SMB3_INF_ERR_EVENT(set_info_err);
-DEFINE_SMB3_INF_ERR_EVENT(notify_err);
-DEFINE_SMB3_INF_ERR_EVENT(fsctl_err);
-
-DECLARE_EVENT_CLASS(smb3_inf_compound_enter_class,
- TP_PROTO(unsigned int xid,
- __u32 tid,
- __u64 sesid,
- const char *full_path),
- TP_ARGS(xid, tid, sesid, full_path),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __string(path, full_path)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __assign_str(path, full_path);
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x path=%s",
- __entry->xid, __entry->sesid, __entry->tid,
- __get_str(path))
-)
-
-#define DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(name) \
-DEFINE_EVENT(smb3_inf_compound_enter_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u32 tid, \
- __u64 sesid, \
- const char *full_path), \
- TP_ARGS(xid, tid, sesid, full_path))
-
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_info_compound_enter);
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(posix_query_info_compound_enter);
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter);
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter);
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter);
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_eof_enter);
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_info_compound_enter);
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(delete_enter);
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mkdir_enter);
-DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(tdis_enter);
-
-
-DECLARE_EVENT_CLASS(smb3_inf_compound_done_class,
- TP_PROTO(unsigned int xid,
- __u32 tid,
- __u64 sesid),
- TP_ARGS(xid, tid, sesid),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u32, tid)
- __field(__u64, sesid)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x",
- __entry->xid, __entry->sesid, __entry->tid)
-)
-
-#define DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(name) \
-DEFINE_EVENT(smb3_inf_compound_done_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u32 tid, \
- __u64 sesid), \
- TP_ARGS(xid, tid, sesid))
-
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_info_compound_done);
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(posix_query_info_compound_done);
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done);
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done);
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done);
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_eof_done);
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_info_compound_done);
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(delete_done);
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mkdir_done);
-DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(tdis_done);
-
-
-DECLARE_EVENT_CLASS(smb3_inf_compound_err_class,
- TP_PROTO(unsigned int xid,
- __u32 tid,
- __u64 sesid,
- int rc),
- TP_ARGS(xid, tid, sesid, rc),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->rc = rc;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x rc=%d",
- __entry->xid, __entry->sesid, __entry->tid,
- __entry->rc)
-)
-
-#define DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_inf_compound_err_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u32 tid, \
- __u64 sesid, \
- int rc), \
- TP_ARGS(xid, tid, sesid, rc))
-
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_info_compound_err);
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(posix_query_info_compound_err);
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err);
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err);
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err);
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_eof_err);
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_info_compound_err);
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mkdir_err);
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(delete_err);
-DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(tdis_err);
-
-/*
- * For logging SMB3 Status code and Command for responses which return errors
- */
-DECLARE_EVENT_CLASS(smb3_cmd_err_class,
- TP_PROTO(__u32 tid,
- __u64 sesid,
- __u16 cmd,
- __u64 mid,
- __u32 status,
- int rc),
- TP_ARGS(tid, sesid, cmd, mid, status, rc),
- TP_STRUCT__entry(
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(__u16, cmd)
- __field(__u64, mid)
- __field(__u32, status)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->cmd = cmd;
- __entry->mid = mid;
- __entry->status = status;
- __entry->rc = rc;
- ),
- TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu status=0x%x rc=%d",
- __entry->sesid, __entry->tid, __entry->cmd, __entry->mid,
- __entry->status, __entry->rc)
-)
-
-#define DEFINE_SMB3_CMD_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_cmd_err_class, smb3_##name, \
- TP_PROTO(__u32 tid, \
- __u64 sesid, \
- __u16 cmd, \
- __u64 mid, \
- __u32 status, \
- int rc), \
- TP_ARGS(tid, sesid, cmd, mid, status, rc))
-
-DEFINE_SMB3_CMD_ERR_EVENT(cmd_err);
-
-DECLARE_EVENT_CLASS(smb3_cmd_done_class,
- TP_PROTO(__u32 tid,
- __u64 sesid,
- __u16 cmd,
- __u64 mid),
- TP_ARGS(tid, sesid, cmd, mid),
- TP_STRUCT__entry(
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(__u16, cmd)
- __field(__u64, mid)
- ),
- TP_fast_assign(
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->cmd = cmd;
- __entry->mid = mid;
- ),
- TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu",
- __entry->sesid, __entry->tid,
- __entry->cmd, __entry->mid)
-)
-
-#define DEFINE_SMB3_CMD_DONE_EVENT(name) \
-DEFINE_EVENT(smb3_cmd_done_class, smb3_##name, \
- TP_PROTO(__u32 tid, \
- __u64 sesid, \
- __u16 cmd, \
- __u64 mid), \
- TP_ARGS(tid, sesid, cmd, mid))
-
-DEFINE_SMB3_CMD_DONE_EVENT(cmd_enter);
-DEFINE_SMB3_CMD_DONE_EVENT(cmd_done);
-DEFINE_SMB3_CMD_DONE_EVENT(ses_expired);
-
-DECLARE_EVENT_CLASS(smb3_mid_class,
- TP_PROTO(__u16 cmd,
- __u64 mid,
- __u32 pid,
- unsigned long when_sent,
- unsigned long when_received),
- TP_ARGS(cmd, mid, pid, when_sent, when_received),
- TP_STRUCT__entry(
- __field(__u16, cmd)
- __field(__u64, mid)
- __field(__u32, pid)
- __field(unsigned long, when_sent)
- __field(unsigned long, when_received)
- ),
- TP_fast_assign(
- __entry->cmd = cmd;
- __entry->mid = mid;
- __entry->pid = pid;
- __entry->when_sent = when_sent;
- __entry->when_received = when_received;
- ),
- TP_printk("\tcmd=%u mid=%llu pid=%u, when_sent=%lu when_rcv=%lu",
- __entry->cmd, __entry->mid, __entry->pid, __entry->when_sent,
- __entry->when_received)
-)
-
-#define DEFINE_SMB3_MID_EVENT(name) \
-DEFINE_EVENT(smb3_mid_class, smb3_##name, \
- TP_PROTO(__u16 cmd, \
- __u64 mid, \
- __u32 pid, \
- unsigned long when_sent, \
- unsigned long when_received), \
- TP_ARGS(cmd, mid, pid, when_sent, when_received))
-
-DEFINE_SMB3_MID_EVENT(slow_rsp);
-
-DECLARE_EVENT_CLASS(smb3_exit_err_class,
- TP_PROTO(unsigned int xid,
- const char *func_name,
- int rc),
- TP_ARGS(xid, func_name, rc),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __string(func_name, func_name)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __assign_str(func_name, func_name);
- __entry->rc = rc;
- ),
- TP_printk("\t%s: xid=%u rc=%d",
- __get_str(func_name), __entry->xid, __entry->rc)
-)
-
-#define DEFINE_SMB3_EXIT_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_exit_err_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- const char *func_name, \
- int rc), \
- TP_ARGS(xid, func_name, rc))
-
-DEFINE_SMB3_EXIT_ERR_EVENT(exit_err);
-
-
-DECLARE_EVENT_CLASS(smb3_sync_err_class,
- TP_PROTO(unsigned long ino,
- int rc),
- TP_ARGS(ino, rc),
- TP_STRUCT__entry(
- __field(unsigned long, ino)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->ino = ino;
- __entry->rc = rc;
- ),
- TP_printk("\tino=%lu rc=%d",
- __entry->ino, __entry->rc)
-)
-
-#define DEFINE_SMB3_SYNC_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_sync_err_class, cifs_##name, \
- TP_PROTO(unsigned long ino, \
- int rc), \
- TP_ARGS(ino, rc))
-
-DEFINE_SMB3_SYNC_ERR_EVENT(fsync_err);
-DEFINE_SMB3_SYNC_ERR_EVENT(flush_err);
-
-
-DECLARE_EVENT_CLASS(smb3_enter_exit_class,
- TP_PROTO(unsigned int xid,
- const char *func_name),
- TP_ARGS(xid, func_name),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __string(func_name, func_name)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __assign_str(func_name, func_name);
- ),
- TP_printk("\t%s: xid=%u",
- __get_str(func_name), __entry->xid)
-)
-
-#define DEFINE_SMB3_ENTER_EXIT_EVENT(name) \
-DEFINE_EVENT(smb3_enter_exit_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- const char *func_name), \
- TP_ARGS(xid, func_name))
-
-DEFINE_SMB3_ENTER_EXIT_EVENT(enter);
-DEFINE_SMB3_ENTER_EXIT_EVENT(exit_done);
-
-/*
- * For SMB2/SMB3 tree connect
- */
-
-DECLARE_EVENT_CLASS(smb3_tcon_class,
- TP_PROTO(unsigned int xid,
- __u32 tid,
- __u64 sesid,
- const char *unc_name,
- int rc),
- TP_ARGS(xid, tid, sesid, unc_name, rc),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __string(name, unc_name)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __assign_str(name, unc_name);
- __entry->rc = rc;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x unc_name=%s rc=%d",
- __entry->xid, __entry->sesid, __entry->tid,
- __get_str(name), __entry->rc)
-)
-
-#define DEFINE_SMB3_TCON_EVENT(name) \
-DEFINE_EVENT(smb3_tcon_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u32 tid, \
- __u64 sesid, \
- const char *unc_name, \
- int rc), \
- TP_ARGS(xid, tid, sesid, unc_name, rc))
-
-DEFINE_SMB3_TCON_EVENT(tcon);
-
-
-/*
- * For smb2/smb3 open (including create and mkdir) calls
- */
-
-DECLARE_EVENT_CLASS(smb3_open_enter_class,
- TP_PROTO(unsigned int xid,
- __u32 tid,
- __u64 sesid,
- const char *full_path,
- int create_options,
- int desired_access),
- TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __string(path, full_path)
- __field(int, create_options)
- __field(int, desired_access)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __assign_str(path, full_path);
- __entry->create_options = create_options;
- __entry->desired_access = desired_access;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x path=%s cr_opts=0x%x des_access=0x%x",
- __entry->xid, __entry->sesid, __entry->tid, __get_str(path),
- __entry->create_options, __entry->desired_access)
-)
-
-#define DEFINE_SMB3_OPEN_ENTER_EVENT(name) \
-DEFINE_EVENT(smb3_open_enter_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u32 tid, \
- __u64 sesid, \
- const char *full_path, \
- int create_options, \
- int desired_access), \
- TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access))
-
-DEFINE_SMB3_OPEN_ENTER_EVENT(open_enter);
-DEFINE_SMB3_OPEN_ENTER_EVENT(posix_mkdir_enter);
-
-DECLARE_EVENT_CLASS(smb3_open_err_class,
- TP_PROTO(unsigned int xid,
- __u32 tid,
- __u64 sesid,
- int create_options,
- int desired_access,
- int rc),
- TP_ARGS(xid, tid, sesid, create_options, desired_access, rc),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(int, create_options)
- __field(int, desired_access)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->create_options = create_options;
- __entry->desired_access = desired_access;
- __entry->rc = rc;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x cr_opts=0x%x des_access=0x%x rc=%d",
- __entry->xid, __entry->sesid, __entry->tid,
- __entry->create_options, __entry->desired_access, __entry->rc)
-)
-
-#define DEFINE_SMB3_OPEN_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_open_err_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u32 tid, \
- __u64 sesid, \
- int create_options, \
- int desired_access, \
- int rc), \
- TP_ARGS(xid, tid, sesid, create_options, desired_access, rc))
-
-DEFINE_SMB3_OPEN_ERR_EVENT(open_err);
-DEFINE_SMB3_OPEN_ERR_EVENT(posix_mkdir_err);
-
-DECLARE_EVENT_CLASS(smb3_open_done_class,
- TP_PROTO(unsigned int xid,
- __u64 fid,
- __u32 tid,
- __u64 sesid,
- int create_options,
- int desired_access),
- TP_ARGS(xid, fid, tid, sesid, create_options, desired_access),
- TP_STRUCT__entry(
- __field(unsigned int, xid)
- __field(__u64, fid)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(int, create_options)
- __field(int, desired_access)
- ),
- TP_fast_assign(
- __entry->xid = xid;
- __entry->fid = fid;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->create_options = create_options;
- __entry->desired_access = desired_access;
- ),
- TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx cr_opts=0x%x des_access=0x%x",
- __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
- __entry->create_options, __entry->desired_access)
-)
-
-#define DEFINE_SMB3_OPEN_DONE_EVENT(name) \
-DEFINE_EVENT(smb3_open_done_class, smb3_##name, \
- TP_PROTO(unsigned int xid, \
- __u64 fid, \
- __u32 tid, \
- __u64 sesid, \
- int create_options, \
- int desired_access), \
- TP_ARGS(xid, fid, tid, sesid, create_options, desired_access))
-
-DEFINE_SMB3_OPEN_DONE_EVENT(open_done);
-DEFINE_SMB3_OPEN_DONE_EVENT(posix_mkdir_done);
-
-
-DECLARE_EVENT_CLASS(smb3_lease_done_class,
- TP_PROTO(__u32 lease_state,
- __u32 tid,
- __u64 sesid,
- __u64 lease_key_low,
- __u64 lease_key_high),
- TP_ARGS(lease_state, tid, sesid, lease_key_low, lease_key_high),
- TP_STRUCT__entry(
- __field(__u32, lease_state)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(__u64, lease_key_low)
- __field(__u64, lease_key_high)
- ),
- TP_fast_assign(
- __entry->lease_state = lease_state;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->lease_key_low = lease_key_low;
- __entry->lease_key_high = lease_key_high;
- ),
- TP_printk("sid=0x%llx tid=0x%x lease_key=0x%llx%llx lease_state=0x%x",
- __entry->sesid, __entry->tid, __entry->lease_key_high,
- __entry->lease_key_low, __entry->lease_state)
-)
-
-#define DEFINE_SMB3_LEASE_DONE_EVENT(name) \
-DEFINE_EVENT(smb3_lease_done_class, smb3_##name, \
- TP_PROTO(__u32 lease_state, \
- __u32 tid, \
- __u64 sesid, \
- __u64 lease_key_low, \
- __u64 lease_key_high), \
- TP_ARGS(lease_state, tid, sesid, lease_key_low, lease_key_high))
-
-DEFINE_SMB3_LEASE_DONE_EVENT(lease_done);
-DEFINE_SMB3_LEASE_DONE_EVENT(lease_not_found);
-
-DECLARE_EVENT_CLASS(smb3_lease_err_class,
- TP_PROTO(__u32 lease_state,
- __u32 tid,
- __u64 sesid,
- __u64 lease_key_low,
- __u64 lease_key_high,
- int rc),
- TP_ARGS(lease_state, tid, sesid, lease_key_low, lease_key_high, rc),
- TP_STRUCT__entry(
- __field(__u32, lease_state)
- __field(__u32, tid)
- __field(__u64, sesid)
- __field(__u64, lease_key_low)
- __field(__u64, lease_key_high)
- __field(int, rc)
- ),
- TP_fast_assign(
- __entry->lease_state = lease_state;
- __entry->tid = tid;
- __entry->sesid = sesid;
- __entry->lease_key_low = lease_key_low;
- __entry->lease_key_high = lease_key_high;
- __entry->rc = rc;
- ),
- TP_printk("sid=0x%llx tid=0x%x lease_key=0x%llx%llx lease_state=0x%x rc=%d",
- __entry->sesid, __entry->tid, __entry->lease_key_high,
- __entry->lease_key_low, __entry->lease_state, __entry->rc)
-)
-
-#define DEFINE_SMB3_LEASE_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_lease_err_class, smb3_##name, \
- TP_PROTO(__u32 lease_state, \
- __u32 tid, \
- __u64 sesid, \
- __u64 lease_key_low, \
- __u64 lease_key_high, \
- int rc), \
- TP_ARGS(lease_state, tid, sesid, lease_key_low, lease_key_high, rc))
-
-DEFINE_SMB3_LEASE_ERR_EVENT(lease_err);
-
-DECLARE_EVENT_CLASS(smb3_connect_class,
- TP_PROTO(char *hostname,
- __u64 conn_id,
- const struct __kernel_sockaddr_storage *dst_addr),
- TP_ARGS(hostname, conn_id, dst_addr),
- TP_STRUCT__entry(
- __string(hostname, hostname)
- __field(__u64, conn_id)
- __array(__u8, dst_addr, sizeof(struct sockaddr_storage))
- ),
- TP_fast_assign(
- struct sockaddr_storage *pss = NULL;
-
- __entry->conn_id = conn_id;
- pss = (struct sockaddr_storage *)__entry->dst_addr;
- *pss = *dst_addr;
- __assign_str(hostname, hostname);
- ),
- TP_printk("conn_id=0x%llx server=%s addr=%pISpsfc",
- __entry->conn_id,
- __get_str(hostname),
- __entry->dst_addr)
-)
-
-#define DEFINE_SMB3_CONNECT_EVENT(name) \
-DEFINE_EVENT(smb3_connect_class, smb3_##name, \
- TP_PROTO(char *hostname, \
- __u64 conn_id, \
- const struct __kernel_sockaddr_storage *addr), \
- TP_ARGS(hostname, conn_id, addr))
-
-DEFINE_SMB3_CONNECT_EVENT(connect_done);
-
-DECLARE_EVENT_CLASS(smb3_connect_err_class,
- TP_PROTO(char *hostname, __u64 conn_id,
- const struct __kernel_sockaddr_storage *dst_addr, int rc),
- TP_ARGS(hostname, conn_id, dst_addr, rc),
- TP_STRUCT__entry(
- __string(hostname, hostname)
- __field(__u64, conn_id)
- __array(__u8, dst_addr, sizeof(struct sockaddr_storage))
- __field(int, rc)
- ),
- TP_fast_assign(
- struct sockaddr_storage *pss = NULL;
-
- __entry->conn_id = conn_id;
- __entry->rc = rc;
- pss = (struct sockaddr_storage *)__entry->dst_addr;
- *pss = *dst_addr;
- __assign_str(hostname, hostname);
- ),
- TP_printk("rc=%d conn_id=0x%llx server=%s addr=%pISpsfc",
- __entry->rc,
- __entry->conn_id,
- __get_str(hostname),
- __entry->dst_addr)
-)
-
-#define DEFINE_SMB3_CONNECT_ERR_EVENT(name) \
-DEFINE_EVENT(smb3_connect_err_class, smb3_##name, \
- TP_PROTO(char *hostname, \
- __u64 conn_id, \
- const struct __kernel_sockaddr_storage *addr, \
- int rc), \
- TP_ARGS(hostname, conn_id, addr, rc))
-
-DEFINE_SMB3_CONNECT_ERR_EVENT(connect_err);
-
-DECLARE_EVENT_CLASS(smb3_reconnect_class,
- TP_PROTO(__u64 currmid,
- __u64 conn_id,
- char *hostname),
- TP_ARGS(currmid, conn_id, hostname),
- TP_STRUCT__entry(
- __field(__u64, currmid)
- __field(__u64, conn_id)
- __string(hostname, hostname)
- ),
- TP_fast_assign(
- __entry->currmid = currmid;
- __entry->conn_id = conn_id;
- __assign_str(hostname, hostname);
- ),
- TP_printk("conn_id=0x%llx server=%s current_mid=%llu",
- __entry->conn_id,
- __get_str(hostname),
- __entry->currmid)
-)
-
-#define DEFINE_SMB3_RECONNECT_EVENT(name) \
-DEFINE_EVENT(smb3_reconnect_class, smb3_##name, \
- TP_PROTO(__u64 currmid, \
- __u64 conn_id, \
- char *hostname), \
- TP_ARGS(currmid, conn_id, hostname))
-
-DEFINE_SMB3_RECONNECT_EVENT(reconnect);
-DEFINE_SMB3_RECONNECT_EVENT(partial_send_reconnect);
-
-DECLARE_EVENT_CLASS(smb3_credit_class,
- TP_PROTO(__u64 currmid,
- __u64 conn_id,
- char *hostname,
- int credits,
- int credits_to_add,
- int in_flight),
- TP_ARGS(currmid, conn_id, hostname, credits, credits_to_add, in_flight),
- TP_STRUCT__entry(
- __field(__u64, currmid)
- __field(__u64, conn_id)
- __string(hostname, hostname)
- __field(int, credits)
- __field(int, credits_to_add)
- __field(int, in_flight)
- ),
- TP_fast_assign(
- __entry->currmid = currmid;
- __entry->conn_id = conn_id;
- __assign_str(hostname, hostname);
- __entry->credits = credits;
- __entry->credits_to_add = credits_to_add;
- __entry->in_flight = in_flight;
- ),
- TP_printk("conn_id=0x%llx server=%s current_mid=%llu "
- "credits=%d credit_change=%d in_flight=%d",
- __entry->conn_id,
- __get_str(hostname),
- __entry->currmid,
- __entry->credits,
- __entry->credits_to_add,
- __entry->in_flight)
-)
-
-#define DEFINE_SMB3_CREDIT_EVENT(name) \
-DEFINE_EVENT(smb3_credit_class, smb3_##name, \
- TP_PROTO(__u64 currmid, \
- __u64 conn_id, \
- char *hostname, \
- int credits, \
- int credits_to_add, \
- int in_flight), \
- TP_ARGS(currmid, conn_id, hostname, credits, credits_to_add, in_flight))
-
-DEFINE_SMB3_CREDIT_EVENT(reconnect_with_invalid_credits);
-DEFINE_SMB3_CREDIT_EVENT(reconnect_detected);
-DEFINE_SMB3_CREDIT_EVENT(credit_timeout);
-DEFINE_SMB3_CREDIT_EVENT(insufficient_credits);
-DEFINE_SMB3_CREDIT_EVENT(too_many_credits);
-DEFINE_SMB3_CREDIT_EVENT(add_credits);
-DEFINE_SMB3_CREDIT_EVENT(adj_credits);
-DEFINE_SMB3_CREDIT_EVENT(hdr_credits);
-DEFINE_SMB3_CREDIT_EVENT(nblk_credits);
-DEFINE_SMB3_CREDIT_EVENT(pend_credits);
-DEFINE_SMB3_CREDIT_EVENT(wait_credits);
-DEFINE_SMB3_CREDIT_EVENT(waitff_credits);
-DEFINE_SMB3_CREDIT_EVENT(overflow_credits);
-DEFINE_SMB3_CREDIT_EVENT(set_credits);
-
-#endif /* _CIFS_TRACE_H */
-
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#define TRACE_INCLUDE_FILE trace
-#include <trace/define_trace.h>
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
deleted file mode 100644
index c961b90f92b9..000000000000
--- a/fs/cifs/transport.c
+++ /dev/null
@@ -1,1807 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (C) International Business Machines Corp., 2002,2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Jeremy Allison (jra@samba.org) 2006.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/gfp.h>
-#include <linux/wait.h>
-#include <linux/net.h>
-#include <linux/delay.h>
-#include <linux/freezer.h>
-#include <linux/tcp.h>
-#include <linux/bvec.h>
-#include <linux/highmem.h>
-#include <linux/uaccess.h>
-#include <asm/processor.h>
-#include <linux/mempool.h>
-#include <linux/sched/signal.h>
-#include <linux/task_io_accounting_ops.h>
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "smb2proto.h"
-#include "smbdirect.h"
-
-/* Max number of iovectors we can use off the stack when sending requests. */
-#define CIFS_MAX_IOV_SIZE 8
-
-void
-cifs_wake_up_task(struct mid_q_entry *mid)
-{
- wake_up_process(mid->callback_data);
-}
-
-static struct mid_q_entry *
-alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
-{
- struct mid_q_entry *temp;
-
- if (server == NULL) {
- cifs_dbg(VFS, "%s: null TCP session\n", __func__);
- return NULL;
- }
-
- temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
- memset(temp, 0, sizeof(struct mid_q_entry));
- kref_init(&temp->refcount);
- temp->mid = get_mid(smb_buffer);
- temp->pid = current->pid;
- temp->command = cpu_to_le16(smb_buffer->Command);
- cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);
- /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
- /* when mid allocated can be before when sent */
- temp->when_alloc = jiffies;
- temp->server = server;
-
- /*
- * The default is for the mid to be synchronous, so the
- * default callback just wakes up the current task.
- */
- get_task_struct(current);
- temp->creator = current;
- temp->callback = cifs_wake_up_task;
- temp->callback_data = current;
-
- atomic_inc(&mid_count);
- temp->mid_state = MID_REQUEST_ALLOCATED;
- return temp;
-}
-
-static void __release_mid(struct kref *refcount)
-{
- struct mid_q_entry *midEntry =
- container_of(refcount, struct mid_q_entry, refcount);
-#ifdef CONFIG_CIFS_STATS2
- __le16 command = midEntry->server->vals->lock_cmd;
- __u16 smb_cmd = le16_to_cpu(midEntry->command);
- unsigned long now;
- unsigned long roundtrip_time;
-#endif
- struct TCP_Server_Info *server = midEntry->server;
-
- if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) &&
- midEntry->mid_state == MID_RESPONSE_RECEIVED &&
- server->ops->handle_cancelled_mid)
- server->ops->handle_cancelled_mid(midEntry, server);
-
- midEntry->mid_state = MID_FREE;
- atomic_dec(&mid_count);
- if (midEntry->large_buf)
- cifs_buf_release(midEntry->resp_buf);
- else
- cifs_small_buf_release(midEntry->resp_buf);
-#ifdef CONFIG_CIFS_STATS2
- now = jiffies;
- if (now < midEntry->when_alloc)
- cifs_server_dbg(VFS, "Invalid mid allocation time\n");
- roundtrip_time = now - midEntry->when_alloc;
-
- if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) {
- if (atomic_read(&server->num_cmds[smb_cmd]) == 0) {
- server->slowest_cmd[smb_cmd] = roundtrip_time;
- server->fastest_cmd[smb_cmd] = roundtrip_time;
- } else {
- if (server->slowest_cmd[smb_cmd] < roundtrip_time)
- server->slowest_cmd[smb_cmd] = roundtrip_time;
- else if (server->fastest_cmd[smb_cmd] > roundtrip_time)
- server->fastest_cmd[smb_cmd] = roundtrip_time;
- }
- cifs_stats_inc(&server->num_cmds[smb_cmd]);
- server->time_per_cmd[smb_cmd] += roundtrip_time;
- }
- /*
- * commands taking longer than one second (default) can be indications
- * that something is wrong, unless it is quite a slow link or a very
- * busy server. Note that this calc is unlikely or impossible to wrap
- * as long as slow_rsp_threshold is not set way above recommended max
- * value (32767 ie 9 hours) and is generally harmless even if wrong
- * since only affects debug counters - so leaving the calc as simple
- * comparison rather than doing multiple conversions and overflow
- * checks
- */
- if ((slow_rsp_threshold != 0) &&
- time_after(now, midEntry->when_alloc + (slow_rsp_threshold * HZ)) &&
- (midEntry->command != command)) {
- /*
- * smb2slowcmd[NUMBER_OF_SMB2_COMMANDS] counts by command
- * NB: le16_to_cpu returns unsigned so can not be negative below
- */
- if (smb_cmd < NUMBER_OF_SMB2_COMMANDS)
- cifs_stats_inc(&server->smb2slowcmd[smb_cmd]);
-
- trace_smb3_slow_rsp(smb_cmd, midEntry->mid, midEntry->pid,
- midEntry->when_sent, midEntry->when_received);
- if (cifsFYI & CIFS_TIMER) {
- pr_debug("slow rsp: cmd %d mid %llu",
- midEntry->command, midEntry->mid);
- cifs_info("A: 0x%lx S: 0x%lx R: 0x%lx\n",
- now - midEntry->when_alloc,
- now - midEntry->when_sent,
- now - midEntry->when_received);
- }
- }
-#endif
- put_task_struct(midEntry->creator);
-
- mempool_free(midEntry, cifs_mid_poolp);
-}
-
-void release_mid(struct mid_q_entry *mid)
-{
- struct TCP_Server_Info *server = mid->server;
-
- spin_lock(&server->mid_lock);
- kref_put(&mid->refcount, __release_mid);
- spin_unlock(&server->mid_lock);
-}
-
-void
-delete_mid(struct mid_q_entry *mid)
-{
- spin_lock(&mid->server->mid_lock);
- if (!(mid->mid_flags & MID_DELETED)) {
- list_del_init(&mid->qhead);
- mid->mid_flags |= MID_DELETED;
- }
- spin_unlock(&mid->server->mid_lock);
-
- release_mid(mid);
-}
-
-/*
- * smb_send_kvec - send an array of kvecs to the server
- * @server: Server to send the data to
- * @smb_msg: Message to send
- * @sent: amount of data sent on socket is stored here
- *
- * Our basic "send data to server" function. Should be called with srv_mutex
- * held. The caller is responsible for handling the results.
- */
-static int
-smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
- size_t *sent)
-{
- int rc = 0;
- int retries = 0;
- struct socket *ssocket = server->ssocket;
-
- *sent = 0;
-
- if (server->noblocksnd)
- smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
- else
- smb_msg->msg_flags = MSG_NOSIGNAL;
-
- while (msg_data_left(smb_msg)) {
- /*
- * If blocking send, we try 3 times, since each can block
- * for 5 seconds. For nonblocking we have to try more
- * but wait increasing amounts of time allowing time for
- * socket to clear. The overall time we wait in either
- * case to send on the socket is about 15 seconds.
- * Similarly we wait for 15 seconds for a response from
- * the server in SendReceive[2] for the server to send
- * a response back for most types of requests (except
- * SMB Write past end of file which can be slow, and
- * blocking lock operations). NFS waits slightly longer
- * than CIFS, but this can make it take longer for
- * nonresponsive servers to be detected and 15 seconds
- * is more than enough time for modern networks to
- * send a packet. In most cases if we fail to send
- * after the retries we will kill the socket and
- * reconnect which may clear the network problem.
- */
- rc = sock_sendmsg(ssocket, smb_msg);
- if (rc == -EAGAIN) {
- retries++;
- if (retries >= 14 ||
- (!server->noblocksnd && (retries > 2))) {
- cifs_server_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
- ssocket);
- return -EAGAIN;
- }
- msleep(1 << retries);
- continue;
- }
-
- if (rc < 0)
- return rc;
-
- if (rc == 0) {
- /* should never happen, letting socket clear before
- retrying is our only obvious option here */
- cifs_server_dbg(VFS, "tcp sent no data\n");
- msleep(500);
- continue;
- }
-
- /* send was at least partially successful */
- *sent += rc;
- retries = 0; /* in case we get ENOSPC on the next send */
- }
- return 0;
-}
-
-unsigned long
-smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst)
-{
- unsigned int i;
- struct kvec *iov;
- int nvec;
- unsigned long buflen = 0;
-
- if (!is_smb1(server) && rqst->rq_nvec >= 2 &&
- rqst->rq_iov[0].iov_len == 4) {
- iov = &rqst->rq_iov[1];
- nvec = rqst->rq_nvec - 1;
- } else {
- iov = rqst->rq_iov;
- nvec = rqst->rq_nvec;
- }
-
- /* total up iov array first */
- for (i = 0; i < nvec; i++)
- buflen += iov[i].iov_len;
-
- /*
- * Add in the page array if there is one. The caller needs to make
- * sure rq_offset and rq_tailsz are set correctly. If a buffer of
- * multiple pages ends at page boundary, rq_tailsz needs to be set to
- * PAGE_SIZE.
- */
- if (rqst->rq_npages) {
- if (rqst->rq_npages == 1)
- buflen += rqst->rq_tailsz;
- else {
- /*
- * If there is more than one page, calculate the
- * buffer length based on rq_offset and rq_tailsz
- */
- buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
- rqst->rq_offset;
- buflen += rqst->rq_tailsz;
- }
- }
-
- return buflen;
-}
-
-static int
-__smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
- struct smb_rqst *rqst)
-{
- int rc;
- struct kvec *iov;
- int n_vec;
- unsigned int send_length = 0;
- unsigned int i, j;
- sigset_t mask, oldmask;
- size_t total_len = 0, sent, size;
- struct socket *ssocket = server->ssocket;
- struct msghdr smb_msg = {};
- __be32 rfc1002_marker;
-
- cifs_in_send_inc(server);
- if (cifs_rdma_enabled(server)) {
- /* return -EAGAIN when connecting or reconnecting */
- rc = -EAGAIN;
- if (server->smbd_conn)
- rc = smbd_send(server, num_rqst, rqst);
- goto smbd_done;
- }
-
- rc = -EAGAIN;
- if (ssocket == NULL)
- goto out;
-
- rc = -ERESTARTSYS;
- if (fatal_signal_pending(current)) {
- cifs_dbg(FYI, "signal pending before send request\n");
- goto out;
- }
-
- rc = 0;
- /* cork the socket */
- tcp_sock_set_cork(ssocket->sk, true);
-
- for (j = 0; j < num_rqst; j++)
- send_length += smb_rqst_len(server, &rqst[j]);
- rfc1002_marker = cpu_to_be32(send_length);
-
- /*
- * We should not allow signals to interrupt the network send because
- * any partial send will cause session reconnects thus increasing
- * latency of system calls and overload a server with unnecessary
- * requests.
- */
-
- sigfillset(&mask);
- sigprocmask(SIG_BLOCK, &mask, &oldmask);
-
- /* Generate a rfc1002 marker for SMB2+ */
- if (!is_smb1(server)) {
- struct kvec hiov = {
- .iov_base = &rfc1002_marker,
- .iov_len = 4
- };
- iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, &hiov, 1, 4);
- rc = smb_send_kvec(server, &smb_msg, &sent);
- if (rc < 0)
- goto unmask;
-
- total_len += sent;
- send_length += 4;
- }
-
- cifs_dbg(FYI, "Sending smb: smb_len=%u\n", send_length);
-
- for (j = 0; j < num_rqst; j++) {
- iov = rqst[j].rq_iov;
- n_vec = rqst[j].rq_nvec;
-
- size = 0;
- for (i = 0; i < n_vec; i++) {
- dump_smb(iov[i].iov_base, iov[i].iov_len);
- size += iov[i].iov_len;
- }
-
- iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, iov, n_vec, size);
-
- rc = smb_send_kvec(server, &smb_msg, &sent);
- if (rc < 0)
- goto unmask;
-
- total_len += sent;
-
- /* now walk the page array and send each page in it */
- for (i = 0; i < rqst[j].rq_npages; i++) {
- struct bio_vec bvec;
-
- bvec.bv_page = rqst[j].rq_pages[i];
- rqst_page_get_length(&rqst[j], i, &bvec.bv_len,
- &bvec.bv_offset);
-
- iov_iter_bvec(&smb_msg.msg_iter, ITER_SOURCE,
- &bvec, 1, bvec.bv_len);
- rc = smb_send_kvec(server, &smb_msg, &sent);
- if (rc < 0)
- break;
-
- total_len += sent;
- }
- }
-
-unmask:
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
-
- /*
- * If signal is pending but we have already sent the whole packet to
- * the server we need to return success status to allow a corresponding
- * mid entry to be kept in the pending requests queue thus allowing
- * to handle responses from the server by the client.
- *
- * If only part of the packet has been sent there is no need to hide
- * interrupt because the session will be reconnected anyway, so there
- * won't be any response from the server to handle.
- */
-
- if (signal_pending(current) && (total_len != send_length)) {
- cifs_dbg(FYI, "signal is pending after attempt to send\n");
- rc = -ERESTARTSYS;
- }
-
- /* uncork it */
- tcp_sock_set_cork(ssocket->sk, false);
-
- if ((total_len > 0) && (total_len != send_length)) {
- cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
- send_length, total_len);
- /*
- * If we have only sent part of an SMB then the next SMB could
- * be taken as the remainder of this one. We need to kill the
- * socket so the server throws away the partial SMB
- */
- cifs_signal_cifsd_for_reconnect(server, false);
- trace_smb3_partial_send_reconnect(server->CurrentMid,
- server->conn_id, server->hostname);
- }
-smbd_done:
- if (rc < 0 && rc != -EINTR)
- cifs_server_dbg(VFS, "Error %d sending data on socket to server\n",
- rc);
- else if (rc > 0)
- rc = 0;
-out:
- cifs_in_send_dec(server);
- return rc;
-}
-
-static int
-smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
- struct smb_rqst *rqst, int flags)
-{
- struct kvec iov;
- struct smb2_transform_hdr *tr_hdr;
- struct smb_rqst cur_rqst[MAX_COMPOUND];
- int rc;
-
- if (!(flags & CIFS_TRANSFORM_REQ))
- return __smb_send_rqst(server, num_rqst, rqst);
-
- if (num_rqst > MAX_COMPOUND - 1)
- return -ENOMEM;
-
- if (!server->ops->init_transform_rq) {
- cifs_server_dbg(VFS, "Encryption requested but transform callback is missing\n");
- return -EIO;
- }
-
- tr_hdr = kzalloc(sizeof(*tr_hdr), GFP_NOFS);
- if (!tr_hdr)
- return -ENOMEM;
-
- memset(&cur_rqst[0], 0, sizeof(cur_rqst));
- memset(&iov, 0, sizeof(iov));
-
- iov.iov_base = tr_hdr;
- iov.iov_len = sizeof(*tr_hdr);
- cur_rqst[0].rq_iov = &iov;
- cur_rqst[0].rq_nvec = 1;
-
- rc = server->ops->init_transform_rq(server, num_rqst + 1,
- &cur_rqst[0], rqst);
- if (rc)
- goto out;
-
- rc = __smb_send_rqst(server, num_rqst + 1, &cur_rqst[0]);
- smb3_free_compound_rqst(num_rqst, &cur_rqst[1]);
-out:
- kfree(tr_hdr);
- return rc;
-}
-
-int
-smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
- unsigned int smb_buf_length)
-{
- struct kvec iov[2];
- struct smb_rqst rqst = { .rq_iov = iov,
- .rq_nvec = 2 };
-
- iov[0].iov_base = smb_buffer;
- iov[0].iov_len = 4;
- iov[1].iov_base = (char *)smb_buffer + 4;
- iov[1].iov_len = smb_buf_length;
-
- return __smb_send_rqst(server, 1, &rqst);
-}
-
-static int
-wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
- const int timeout, const int flags,
- unsigned int *instance)
-{
- long rc;
- int *credits;
- int optype;
- long int t;
- int scredits, in_flight;
-
- if (timeout < 0)
- t = MAX_JIFFY_OFFSET;
- else
- t = msecs_to_jiffies(timeout);
-
- optype = flags & CIFS_OP_MASK;
-
- *instance = 0;
-
- credits = server->ops->get_credits_field(server, optype);
- /* Since an echo is already inflight, no need to wait to send another */
- if (*credits <= 0 && optype == CIFS_ECHO_OP)
- return -EAGAIN;
-
- spin_lock(&server->req_lock);
- if ((flags & CIFS_TIMEOUT_MASK) == CIFS_NON_BLOCKING) {
- /* oplock breaks must not be held up */
- server->in_flight++;
- if (server->in_flight > server->max_in_flight)
- server->max_in_flight = server->in_flight;
- *credits -= 1;
- *instance = server->reconnect_instance;
- scredits = *credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
-
- trace_smb3_nblk_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits, -1, in_flight);
- cifs_dbg(FYI, "%s: remove %u credits total=%d\n",
- __func__, 1, scredits);
-
- return 0;
- }
-
- while (1) {
- if (*credits < num_credits) {
- scredits = *credits;
- spin_unlock(&server->req_lock);
-
- cifs_num_waiters_inc(server);
- rc = wait_event_killable_timeout(server->request_q,
- has_credits(server, credits, num_credits), t);
- cifs_num_waiters_dec(server);
- if (!rc) {
- spin_lock(&server->req_lock);
- scredits = *credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
-
- trace_smb3_credit_timeout(server->CurrentMid,
- server->conn_id, server->hostname, scredits,
- num_credits, in_flight);
- cifs_server_dbg(VFS, "wait timed out after %d ms\n",
- timeout);
- return -EBUSY;
- }
- if (rc == -ERESTARTSYS)
- return -ERESTARTSYS;
- spin_lock(&server->req_lock);
- } else {
- spin_unlock(&server->req_lock);
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsExiting) {
- spin_unlock(&server->srv_lock);
- return -ENOENT;
- }
- spin_unlock(&server->srv_lock);
-
- /*
- * For normal commands, reserve the last MAX_COMPOUND
- * credits to compound requests.
- * Otherwise these compounds could be permanently
- * starved for credits by single-credit requests.
- *
- * To prevent spinning CPU, block this thread until
- * there are >MAX_COMPOUND credits available.
- * But only do this is we already have a lot of
- * credits in flight to avoid triggering this check
- * for servers that are slow to hand out credits on
- * new sessions.
- */
- spin_lock(&server->req_lock);
- if (!optype && num_credits == 1 &&
- server->in_flight > 2 * MAX_COMPOUND &&
- *credits <= MAX_COMPOUND) {
- spin_unlock(&server->req_lock);
-
- cifs_num_waiters_inc(server);
- rc = wait_event_killable_timeout(
- server->request_q,
- has_credits(server, credits,
- MAX_COMPOUND + 1),
- t);
- cifs_num_waiters_dec(server);
- if (!rc) {
- spin_lock(&server->req_lock);
- scredits = *credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
-
- trace_smb3_credit_timeout(
- server->CurrentMid,
- server->conn_id, server->hostname,
- scredits, num_credits, in_flight);
- cifs_server_dbg(VFS, "wait timed out after %d ms\n",
- timeout);
- return -EBUSY;
- }
- if (rc == -ERESTARTSYS)
- return -ERESTARTSYS;
- spin_lock(&server->req_lock);
- continue;
- }
-
- /*
- * Can not count locking commands against total
- * as they are allowed to block on server.
- */
-
- /* update # of requests on the wire to server */
- if ((flags & CIFS_TIMEOUT_MASK) != CIFS_BLOCKING_OP) {
- *credits -= num_credits;
- server->in_flight += num_credits;
- if (server->in_flight > server->max_in_flight)
- server->max_in_flight = server->in_flight;
- *instance = server->reconnect_instance;
- }
- scredits = *credits;
- in_flight = server->in_flight;
- spin_unlock(&server->req_lock);
-
- trace_smb3_waitff_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits,
- -(num_credits), in_flight);
- cifs_dbg(FYI, "%s: remove %u credits total=%d\n",
- __func__, num_credits, scredits);
- break;
- }
- }
- return 0;
-}
-
-static int
-wait_for_free_request(struct TCP_Server_Info *server, const int flags,
- unsigned int *instance)
-{
- return wait_for_free_credits(server, 1, -1, flags,
- instance);
-}
-
-static int
-wait_for_compound_request(struct TCP_Server_Info *server, int num,
- const int flags, unsigned int *instance)
-{
- int *credits;
- int scredits, in_flight;
-
- credits = server->ops->get_credits_field(server, flags & CIFS_OP_MASK);
-
- spin_lock(&server->req_lock);
- scredits = *credits;
- in_flight = server->in_flight;
-
- if (*credits < num) {
- /*
- * If the server is tight on resources or just gives us less
- * credits for other reasons (e.g. requests are coming out of
- * order and the server delays granting more credits until it
- * processes a missing mid) and we exhausted most available
- * credits there may be situations when we try to send
- * a compound request but we don't have enough credits. At this
- * point the client needs to decide if it should wait for
- * additional credits or fail the request. If at least one
- * request is in flight there is a high probability that the
- * server will return enough credits to satisfy this compound
- * request.
- *
- * Return immediately if no requests in flight since we will be
- * stuck on waiting for credits.
- */
- if (server->in_flight == 0) {
- spin_unlock(&server->req_lock);
- trace_smb3_insufficient_credits(server->CurrentMid,
- server->conn_id, server->hostname, scredits,
- num, in_flight);
- cifs_dbg(FYI, "%s: %d requests in flight, needed %d total=%d\n",
- __func__, in_flight, num, scredits);
- return -EDEADLK;
- }
- }
- spin_unlock(&server->req_lock);
-
- return wait_for_free_credits(server, num, 60000, flags,
- instance);
-}
-
-int
-cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
- unsigned int *num, struct cifs_credits *credits)
-{
- *num = size;
- credits->value = 0;
- credits->instance = server->reconnect_instance;
- return 0;
-}
-
-static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
- struct mid_q_entry **ppmidQ)
-{
- spin_lock(&ses->ses_lock);
- if (ses->ses_status == SES_NEW) {
- if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
- (in_buf->Command != SMB_COM_NEGOTIATE)) {
- spin_unlock(&ses->ses_lock);
- return -EAGAIN;
- }
- /* else ok - we are setting up session */
- }
-
- if (ses->ses_status == SES_EXITING) {
- /* check if SMB session is bad because we are setting it up */
- if (in_buf->Command != SMB_COM_LOGOFF_ANDX) {
- spin_unlock(&ses->ses_lock);
- return -EAGAIN;
- }
- /* else ok - we are shutting down session */
- }
- spin_unlock(&ses->ses_lock);
-
- *ppmidQ = alloc_mid(in_buf, ses->server);
- if (*ppmidQ == NULL)
- return -ENOMEM;
- spin_lock(&ses->server->mid_lock);
- list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
- spin_unlock(&ses->server->mid_lock);
- return 0;
-}
-
-static int
-wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
-{
- int error;
-
- error = wait_event_state(server->response_q,
- midQ->mid_state != MID_REQUEST_SUBMITTED,
- (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE));
- if (error < 0)
- return -ERESTARTSYS;
-
- return 0;
-}
-
-struct mid_q_entry *
-cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
-{
- int rc;
- struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
- struct mid_q_entry *mid;
-
- if (rqst->rq_iov[0].iov_len != 4 ||
- rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
- return ERR_PTR(-EIO);
-
- /* enable signing if server requires it */
- if (server->sign)
- hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- mid = alloc_mid(hdr, server);
- if (mid == NULL)
- return ERR_PTR(-ENOMEM);
-
- rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
- if (rc) {
- release_mid(mid);
- return ERR_PTR(rc);
- }
-
- return mid;
-}
-
-/*
- * Send a SMB request and set the callback function in the mid to handle
- * the result. Caller is responsible for dealing with timeouts.
- */
-int
-cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
- mid_receive_t *receive, mid_callback_t *callback,
- mid_handle_t *handle, void *cbdata, const int flags,
- const struct cifs_credits *exist_credits)
-{
- int rc;
- struct mid_q_entry *mid;
- struct cifs_credits credits = { .value = 0, .instance = 0 };
- unsigned int instance;
- int optype;
-
- optype = flags & CIFS_OP_MASK;
-
- if ((flags & CIFS_HAS_CREDITS) == 0) {
- rc = wait_for_free_request(server, flags, &instance);
- if (rc)
- return rc;
- credits.value = 1;
- credits.instance = instance;
- } else
- instance = exist_credits->instance;
-
- cifs_server_lock(server);
-
- /*
- * We can't use credits obtained from the previous session to send this
- * request. Check if there were reconnects after we obtained credits and
- * return -EAGAIN in such cases to let callers handle it.
- */
- if (instance != server->reconnect_instance) {
- cifs_server_unlock(server);
- add_credits_and_wake_if(server, &credits, optype);
- return -EAGAIN;
- }
-
- mid = server->ops->setup_async_request(server, rqst);
- if (IS_ERR(mid)) {
- cifs_server_unlock(server);
- add_credits_and_wake_if(server, &credits, optype);
- return PTR_ERR(mid);
- }
-
- mid->receive = receive;
- mid->callback = callback;
- mid->callback_data = cbdata;
- mid->handle = handle;
- mid->mid_state = MID_REQUEST_SUBMITTED;
-
- /* put it on the pending_mid_q */
- spin_lock(&server->mid_lock);
- list_add_tail(&mid->qhead, &server->pending_mid_q);
- spin_unlock(&server->mid_lock);
-
- /*
- * Need to store the time in mid before calling I/O. For call_async,
- * I/O response may come back and free the mid entry on another thread.
- */
- cifs_save_when_sent(mid);
- rc = smb_send_rqst(server, 1, rqst, flags);
-
- if (rc < 0) {
- revert_current_mid(server, mid->credits);
- server->sequence_number -= 2;
- delete_mid(mid);
- }
-
- cifs_server_unlock(server);
-
- if (rc == 0)
- return 0;
-
- add_credits_and_wake_if(server, &credits, optype);
- return rc;
-}
-
-/*
- *
- * Send an SMB Request. No response info (other than return code)
- * needs to be parsed.
- *
- * flags indicate the type of request buffer and how long to wait
- * and whether to log NT STATUS code (error) before mapping it to POSIX error
- *
- */
-int
-SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
- char *in_buf, int flags)
-{
- int rc;
- struct kvec iov[1];
- struct kvec rsp_iov;
- int resp_buf_type;
-
- iov[0].iov_base = in_buf;
- iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
- flags |= CIFS_NO_RSP_BUF;
- rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
- cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
-
- return rc;
-}
-
-static int
-cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
-{
- int rc = 0;
-
- cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n",
- __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state);
-
- spin_lock(&server->mid_lock);
- switch (mid->mid_state) {
- case MID_RESPONSE_RECEIVED:
- spin_unlock(&server->mid_lock);
- return rc;
- case MID_RETRY_NEEDED:
- rc = -EAGAIN;
- break;
- case MID_RESPONSE_MALFORMED:
- rc = -EIO;
- break;
- case MID_SHUTDOWN:
- rc = -EHOSTDOWN;
- break;
- default:
- if (!(mid->mid_flags & MID_DELETED)) {
- list_del_init(&mid->qhead);
- mid->mid_flags |= MID_DELETED;
- }
- cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
- __func__, mid->mid, mid->mid_state);
- rc = -EIO;
- }
- spin_unlock(&server->mid_lock);
-
- release_mid(mid);
- return rc;
-}
-
-static inline int
-send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
- struct mid_q_entry *mid)
-{
- return server->ops->send_cancel ?
- server->ops->send_cancel(server, rqst, mid) : 0;
-}
-
-int
-cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
- bool log_error)
-{
- unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
-
- dump_smb(mid->resp_buf, min_t(u32, 92, len));
-
- /* convert the length into a more usable form */
- if (server->sign) {
- struct kvec iov[2];
- int rc = 0;
- struct smb_rqst rqst = { .rq_iov = iov,
- .rq_nvec = 2 };
-
- iov[0].iov_base = mid->resp_buf;
- iov[0].iov_len = 4;
- iov[1].iov_base = (char *)mid->resp_buf + 4;
- iov[1].iov_len = len - 4;
- /* FIXME: add code to kill session */
- rc = cifs_verify_signature(&rqst, server,
- mid->sequence_number);
- if (rc)
- cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",
- rc);
- }
-
- /* BB special case reconnect tid and uid here? */
- return map_and_check_smb_error(mid, log_error);
-}
-
-struct mid_q_entry *
-cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored,
- struct smb_rqst *rqst)
-{
- int rc;
- struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
- struct mid_q_entry *mid;
-
- if (rqst->rq_iov[0].iov_len != 4 ||
- rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
- return ERR_PTR(-EIO);
-
- rc = allocate_mid(ses, hdr, &mid);
- if (rc)
- return ERR_PTR(rc);
- rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
- if (rc) {
- delete_mid(mid);
- return ERR_PTR(rc);
- }
- return mid;
-}
-
-static void
-cifs_compound_callback(struct mid_q_entry *mid)
-{
- struct TCP_Server_Info *server = mid->server;
- struct cifs_credits credits;
-
- credits.value = server->ops->get_credits(mid);
- credits.instance = server->reconnect_instance;
-
- add_credits(server, &credits, mid->optype);
-}
-
-static void
-cifs_compound_last_callback(struct mid_q_entry *mid)
-{
- cifs_compound_callback(mid);
- cifs_wake_up_task(mid);
-}
-
-static void
-cifs_cancelled_callback(struct mid_q_entry *mid)
-{
- cifs_compound_callback(mid);
- release_mid(mid);
-}
-
-/*
- * Return a channel (master if none) of @ses that can be used to send
- * regular requests.
- *
- * If we are currently binding a new channel (negprot/sess.setup),
- * return the new incomplete channel.
- */
-struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
-{
- uint index = 0;
-
- if (!ses)
- return NULL;
-
- /* round robin */
- index = (uint)atomic_inc_return(&ses->chan_seq);
-
- spin_lock(&ses->chan_lock);
- index %= ses->chan_count;
- spin_unlock(&ses->chan_lock);
-
- return ses->chans[index].server;
-}
-
-int
-compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- const int flags, const int num_rqst, struct smb_rqst *rqst,
- int *resp_buf_type, struct kvec *resp_iov)
-{
- int i, j, optype, rc = 0;
- struct mid_q_entry *midQ[MAX_COMPOUND];
- bool cancelled_mid[MAX_COMPOUND] = {false};
- struct cifs_credits credits[MAX_COMPOUND] = {
- { .value = 0, .instance = 0 }
- };
- unsigned int instance;
- char *buf;
-
- optype = flags & CIFS_OP_MASK;
-
- for (i = 0; i < num_rqst; i++)
- resp_buf_type[i] = CIFS_NO_BUFFER; /* no response buf yet */
-
- if (!ses || !ses->server || !server) {
- cifs_dbg(VFS, "Null session\n");
- return -EIO;
- }
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsExiting) {
- spin_unlock(&server->srv_lock);
- return -ENOENT;
- }
- spin_unlock(&server->srv_lock);
-
- /*
- * Wait for all the requests to become available.
- * This approach still leaves the possibility to be stuck waiting for
- * credits if the server doesn't grant credits to the outstanding
- * requests and if the client is completely idle, not generating any
- * other requests.
- * This can be handled by the eventual session reconnect.
- */
- rc = wait_for_compound_request(server, num_rqst, flags,
- &instance);
- if (rc)
- return rc;
-
- for (i = 0; i < num_rqst; i++) {
- credits[i].value = 1;
- credits[i].instance = instance;
- }
-
- /*
- * Make sure that we sign in the same order that we send on this socket
- * and avoid races inside tcp sendmsg code that could cause corruption
- * of smb data.
- */
-
- cifs_server_lock(server);
-
- /*
- * All the parts of the compound chain belong obtained credits from the
- * same session. We can not use credits obtained from the previous
- * session to send this request. Check if there were reconnects after
- * we obtained credits and return -EAGAIN in such cases to let callers
- * handle it.
- */
- if (instance != server->reconnect_instance) {
- cifs_server_unlock(server);
- for (j = 0; j < num_rqst; j++)
- add_credits(server, &credits[j], optype);
- return -EAGAIN;
- }
-
- for (i = 0; i < num_rqst; i++) {
- midQ[i] = server->ops->setup_request(ses, server, &rqst[i]);
- if (IS_ERR(midQ[i])) {
- revert_current_mid(server, i);
- for (j = 0; j < i; j++)
- delete_mid(midQ[j]);
- cifs_server_unlock(server);
-
- /* Update # of requests on wire to server */
- for (j = 0; j < num_rqst; j++)
- add_credits(server, &credits[j], optype);
- return PTR_ERR(midQ[i]);
- }
-
- midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
- midQ[i]->optype = optype;
- /*
- * Invoke callback for every part of the compound chain
- * to calculate credits properly. Wake up this thread only when
- * the last element is received.
- */
- if (i < num_rqst - 1)
- midQ[i]->callback = cifs_compound_callback;
- else
- midQ[i]->callback = cifs_compound_last_callback;
- }
- rc = smb_send_rqst(server, num_rqst, rqst, flags);
-
- for (i = 0; i < num_rqst; i++)
- cifs_save_when_sent(midQ[i]);
-
- if (rc < 0) {
- revert_current_mid(server, num_rqst);
- server->sequence_number -= 2;
- }
-
- cifs_server_unlock(server);
-
- /*
- * If sending failed for some reason or it is an oplock break that we
- * will not receive a response to - return credits back
- */
- if (rc < 0 || (flags & CIFS_NO_SRV_RSP)) {
- for (i = 0; i < num_rqst; i++)
- add_credits(server, &credits[i], optype);
- goto out;
- }
-
- /*
- * At this point the request is passed to the network stack - we assume
- * that any credits taken from the server structure on the client have
- * been spent and we can't return them back. Once we receive responses
- * we will collect credits granted by the server in the mid callbacks
- * and add those credits to the server structure.
- */
-
- /*
- * Compounding is never used during session establish.
- */
- spin_lock(&ses->ses_lock);
- if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) {
- spin_unlock(&ses->ses_lock);
-
- cifs_server_lock(server);
- smb311_update_preauth_hash(ses, server, rqst[0].rq_iov, rqst[0].rq_nvec);
- cifs_server_unlock(server);
-
- spin_lock(&ses->ses_lock);
- }
- spin_unlock(&ses->ses_lock);
-
- for (i = 0; i < num_rqst; i++) {
- rc = wait_for_response(server, midQ[i]);
- if (rc != 0)
- break;
- }
- if (rc != 0) {
- for (; i < num_rqst; i++) {
- cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n",
- midQ[i]->mid, le16_to_cpu(midQ[i]->command));
- send_cancel(server, &rqst[i], midQ[i]);
- spin_lock(&server->mid_lock);
- midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
- if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
- midQ[i]->callback = cifs_cancelled_callback;
- cancelled_mid[i] = true;
- credits[i].value = 0;
- }
- spin_unlock(&server->mid_lock);
- }
- }
-
- for (i = 0; i < num_rqst; i++) {
- if (rc < 0)
- goto out;
-
- rc = cifs_sync_mid_result(midQ[i], server);
- if (rc != 0) {
- /* mark this mid as cancelled to not free it below */
- cancelled_mid[i] = true;
- goto out;
- }
-
- if (!midQ[i]->resp_buf ||
- midQ[i]->mid_state != MID_RESPONSE_RECEIVED) {
- rc = -EIO;
- cifs_dbg(FYI, "Bad MID state?\n");
- goto out;
- }
-
- buf = (char *)midQ[i]->resp_buf;
- resp_iov[i].iov_base = buf;
- resp_iov[i].iov_len = midQ[i]->resp_buf_size +
- HEADER_PREAMBLE_SIZE(server);
-
- if (midQ[i]->large_buf)
- resp_buf_type[i] = CIFS_LARGE_BUFFER;
- else
- resp_buf_type[i] = CIFS_SMALL_BUFFER;
-
- rc = server->ops->check_receive(midQ[i], server,
- flags & CIFS_LOG_ERROR);
-
- /* mark it so buf will not be freed by delete_mid */
- if ((flags & CIFS_NO_RSP_BUF) == 0)
- midQ[i]->resp_buf = NULL;
-
- }
-
- /*
- * Compounding is never used during session establish.
- */
- spin_lock(&ses->ses_lock);
- if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) {
- struct kvec iov = {
- .iov_base = resp_iov[0].iov_base,
- .iov_len = resp_iov[0].iov_len
- };
- spin_unlock(&ses->ses_lock);
- cifs_server_lock(server);
- smb311_update_preauth_hash(ses, server, &iov, 1);
- cifs_server_unlock(server);
- spin_lock(&ses->ses_lock);
- }
- spin_unlock(&ses->ses_lock);
-
-out:
- /*
- * This will dequeue all mids. After this it is important that the
- * demultiplex_thread will not process any of these mids any futher.
- * This is prevented above by using a noop callback that will not
- * wake this thread except for the very last PDU.
- */
- for (i = 0; i < num_rqst; i++) {
- if (!cancelled_mid[i])
- delete_mid(midQ[i]);
- }
-
- return rc;
-}
-
-int
-cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
- struct TCP_Server_Info *server,
- struct smb_rqst *rqst, int *resp_buf_type, const int flags,
- struct kvec *resp_iov)
-{
- return compound_send_recv(xid, ses, server, flags, 1,
- rqst, resp_buf_type, resp_iov);
-}
-
-int
-SendReceive2(const unsigned int xid, struct cifs_ses *ses,
- struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
- const int flags, struct kvec *resp_iov)
-{
- struct smb_rqst rqst;
- struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
- int rc;
-
- if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
- new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec),
- GFP_KERNEL);
- if (!new_iov) {
- /* otherwise cifs_send_recv below sets resp_buf_type */
- *resp_buf_type = CIFS_NO_BUFFER;
- return -ENOMEM;
- }
- } else
- new_iov = s_iov;
-
- /* 1st iov is a RFC1001 length followed by the rest of the packet */
- memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
-
- new_iov[0].iov_base = new_iov[1].iov_base;
- new_iov[0].iov_len = 4;
- new_iov[1].iov_base += 4;
- new_iov[1].iov_len -= 4;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = new_iov;
- rqst.rq_nvec = n_vec + 1;
-
- rc = cifs_send_recv(xid, ses, ses->server,
- &rqst, resp_buf_type, flags, resp_iov);
- if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
- kfree(new_iov);
- return rc;
-}
-
-int
-SendReceive(const unsigned int xid, struct cifs_ses *ses,
- struct smb_hdr *in_buf, struct smb_hdr *out_buf,
- int *pbytes_returned, const int flags)
-{
- int rc = 0;
- struct mid_q_entry *midQ;
- unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
- struct kvec iov = { .iov_base = in_buf, .iov_len = len };
- struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
- struct cifs_credits credits = { .value = 1, .instance = 0 };
- struct TCP_Server_Info *server;
-
- if (ses == NULL) {
- cifs_dbg(VFS, "Null smb session\n");
- return -EIO;
- }
- server = ses->server;
- if (server == NULL) {
- cifs_dbg(VFS, "Null tcp session\n");
- return -EIO;
- }
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsExiting) {
- spin_unlock(&server->srv_lock);
- return -ENOENT;
- }
- spin_unlock(&server->srv_lock);
-
- /* Ensure that we do not send more than 50 overlapping requests
- to the same server. We may make this configurable later or
- use ses->maxReq */
-
- if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
- cifs_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
- len);
- return -EIO;
- }
-
- rc = wait_for_free_request(server, flags, &credits.instance);
- if (rc)
- return rc;
-
- /* make sure that we sign in the same order that we send on this socket
- and avoid races inside tcp sendmsg code that could cause corruption
- of smb data */
-
- cifs_server_lock(server);
-
- rc = allocate_mid(ses, in_buf, &midQ);
- if (rc) {
- cifs_server_unlock(server);
- /* Update # of requests on wire to server */
- add_credits(server, &credits, 0);
- return rc;
- }
-
- rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
- if (rc) {
- cifs_server_unlock(server);
- goto out;
- }
-
- midQ->mid_state = MID_REQUEST_SUBMITTED;
-
- rc = smb_send(server, in_buf, len);
- cifs_save_when_sent(midQ);
-
- if (rc < 0)
- server->sequence_number -= 2;
-
- cifs_server_unlock(server);
-
- if (rc < 0)
- goto out;
-
- rc = wait_for_response(server, midQ);
- if (rc != 0) {
- send_cancel(server, &rqst, midQ);
- spin_lock(&server->mid_lock);
- if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
- /* no longer considered to be "in-flight" */
- midQ->callback = release_mid;
- spin_unlock(&server->mid_lock);
- add_credits(server, &credits, 0);
- return rc;
- }
- spin_unlock(&server->mid_lock);
- }
-
- rc = cifs_sync_mid_result(midQ, server);
- if (rc != 0) {
- add_credits(server, &credits, 0);
- return rc;
- }
-
- if (!midQ->resp_buf || !out_buf ||
- midQ->mid_state != MID_RESPONSE_RECEIVED) {
- rc = -EIO;
- cifs_server_dbg(VFS, "Bad MID state?\n");
- goto out;
- }
-
- *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
- memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
- rc = cifs_check_receive(midQ, server, 0);
-out:
- delete_mid(midQ);
- add_credits(server, &credits, 0);
-
- return rc;
-}
-
-/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
- blocking lock to return. */
-
-static int
-send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
- struct smb_hdr *in_buf,
- struct smb_hdr *out_buf)
-{
- int bytes_returned;
- struct cifs_ses *ses = tcon->ses;
- LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
-
- /* We just modify the current in_buf to change
- the type of lock from LOCKING_ANDX_SHARED_LOCK
- or LOCKING_ANDX_EXCLUSIVE_LOCK to
- LOCKING_ANDX_CANCEL_LOCK. */
-
- pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
- pSMB->Timeout = 0;
- pSMB->hdr.Mid = get_next_mid(ses->server);
-
- return SendReceive(xid, ses, in_buf, out_buf,
- &bytes_returned, 0);
-}
-
-int
-SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
- struct smb_hdr *in_buf, struct smb_hdr *out_buf,
- int *pbytes_returned)
-{
- int rc = 0;
- int rstart = 0;
- struct mid_q_entry *midQ;
- struct cifs_ses *ses;
- unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
- struct kvec iov = { .iov_base = in_buf, .iov_len = len };
- struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
- unsigned int instance;
- struct TCP_Server_Info *server;
-
- if (tcon == NULL || tcon->ses == NULL) {
- cifs_dbg(VFS, "Null smb session\n");
- return -EIO;
- }
- ses = tcon->ses;
- server = ses->server;
-
- if (server == NULL) {
- cifs_dbg(VFS, "Null tcp session\n");
- return -EIO;
- }
-
- spin_lock(&server->srv_lock);
- if (server->tcpStatus == CifsExiting) {
- spin_unlock(&server->srv_lock);
- return -ENOENT;
- }
- spin_unlock(&server->srv_lock);
-
- /* Ensure that we do not send more than 50 overlapping requests
- to the same server. We may make this configurable later or
- use ses->maxReq */
-
- if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
- cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
- len);
- return -EIO;
- }
-
- rc = wait_for_free_request(server, CIFS_BLOCKING_OP, &instance);
- if (rc)
- return rc;
-
- /* make sure that we sign in the same order that we send on this socket
- and avoid races inside tcp sendmsg code that could cause corruption
- of smb data */
-
- cifs_server_lock(server);
-
- rc = allocate_mid(ses, in_buf, &midQ);
- if (rc) {
- cifs_server_unlock(server);
- return rc;
- }
-
- rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
- if (rc) {
- delete_mid(midQ);
- cifs_server_unlock(server);
- return rc;
- }
-
- midQ->mid_state = MID_REQUEST_SUBMITTED;
- rc = smb_send(server, in_buf, len);
- cifs_save_when_sent(midQ);
-
- if (rc < 0)
- server->sequence_number -= 2;
-
- cifs_server_unlock(server);
-
- if (rc < 0) {
- delete_mid(midQ);
- return rc;
- }
-
- /* Wait for a reply - allow signals to interrupt. */
- rc = wait_event_interruptible(server->response_q,
- (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
- ((server->tcpStatus != CifsGood) &&
- (server->tcpStatus != CifsNew)));
-
- /* Were we interrupted by a signal ? */
- spin_lock(&server->srv_lock);
- if ((rc == -ERESTARTSYS) &&
- (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
- ((server->tcpStatus == CifsGood) ||
- (server->tcpStatus == CifsNew))) {
- spin_unlock(&server->srv_lock);
-
- if (in_buf->Command == SMB_COM_TRANSACTION2) {
- /* POSIX lock. We send a NT_CANCEL SMB to cause the
- blocking lock to return. */
- rc = send_cancel(server, &rqst, midQ);
- if (rc) {
- delete_mid(midQ);
- return rc;
- }
- } else {
- /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
- to cause the blocking lock to return. */
-
- rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
-
- /* If we get -ENOLCK back the lock may have
- already been removed. Don't exit in this case. */
- if (rc && rc != -ENOLCK) {
- delete_mid(midQ);
- return rc;
- }
- }
-
- rc = wait_for_response(server, midQ);
- if (rc) {
- send_cancel(server, &rqst, midQ);
- spin_lock(&server->mid_lock);
- if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
- /* no longer considered to be "in-flight" */
- midQ->callback = release_mid;
- spin_unlock(&server->mid_lock);
- return rc;
- }
- spin_unlock(&server->mid_lock);
- }
-
- /* We got the response - restart system call. */
- rstart = 1;
- spin_lock(&server->srv_lock);
- }
- spin_unlock(&server->srv_lock);
-
- rc = cifs_sync_mid_result(midQ, server);
- if (rc != 0)
- return rc;
-
- /* rcvd frame is ok */
- if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
- rc = -EIO;
- cifs_tcon_dbg(VFS, "Bad MID state?\n");
- goto out;
- }
-
- *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
- memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
- rc = cifs_check_receive(midQ, server, 0);
-out:
- delete_mid(midQ);
- if (rstart && rc == -EACCES)
- return -ERESTARTSYS;
- return rc;
-}
-
-/*
- * Discard any remaining data in the current SMB. To do this, we borrow the
- * current bigbuf.
- */
-int
-cifs_discard_remaining_data(struct TCP_Server_Info *server)
-{
- unsigned int rfclen = server->pdu_size;
- int remaining = rfclen + HEADER_PREAMBLE_SIZE(server) -
- server->total_read;
-
- while (remaining > 0) {
- int length;
-
- length = cifs_discard_from_socket(server,
- min_t(size_t, remaining,
- CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
- if (length < 0)
- return length;
- server->total_read += length;
- remaining -= length;
- }
-
- return 0;
-}
-
-static int
-__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
- bool malformed)
-{
- int length;
-
- length = cifs_discard_remaining_data(server);
- dequeue_mid(mid, malformed);
- mid->resp_buf = server->smallbuf;
- server->smallbuf = NULL;
- return length;
-}
-
-static int
-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
-{
- struct cifs_readdata *rdata = mid->callback_data;
-
- return __cifs_readv_discard(server, mid, rdata->result);
-}
-
-int
-cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
-{
- int length, len;
- unsigned int data_offset, data_len;
- struct cifs_readdata *rdata = mid->callback_data;
- char *buf = server->smallbuf;
- unsigned int buflen = server->pdu_size + HEADER_PREAMBLE_SIZE(server);
- bool use_rdma_mr = false;
-
- cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
- __func__, mid->mid, rdata->offset, rdata->bytes);
-
- /*
- * read the rest of READ_RSP header (sans Data array), or whatever we
- * can if there's not enough data. At this point, we've read down to
- * the Mid.
- */
- len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
- HEADER_SIZE(server) + 1;
-
- length = cifs_read_from_socket(server,
- buf + HEADER_SIZE(server) - 1, len);
- if (length < 0)
- return length;
- server->total_read += length;
-
- if (server->ops->is_session_expired &&
- server->ops->is_session_expired(buf)) {
- cifs_reconnect(server, true);
- return -1;
- }
-
- if (server->ops->is_status_pending &&
- server->ops->is_status_pending(buf, server)) {
- cifs_discard_remaining_data(server);
- return -1;
- }
-
- /* set up first two iov for signature check and to get credits */
- rdata->iov[0].iov_base = buf;
- rdata->iov[0].iov_len = HEADER_PREAMBLE_SIZE(server);
- rdata->iov[1].iov_base = buf + HEADER_PREAMBLE_SIZE(server);
- rdata->iov[1].iov_len =
- server->total_read - HEADER_PREAMBLE_SIZE(server);
- cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
- rdata->iov[0].iov_base, rdata->iov[0].iov_len);
- cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
- rdata->iov[1].iov_base, rdata->iov[1].iov_len);
-
- /* Was the SMB read successful? */
- rdata->result = server->ops->map_error(buf, false);
- if (rdata->result != 0) {
- cifs_dbg(FYI, "%s: server returned error %d\n",
- __func__, rdata->result);
- /* normal error on read response */
- return __cifs_readv_discard(server, mid, false);
- }
-
- /* Is there enough to get to the rest of the READ_RSP header? */
- if (server->total_read < server->vals->read_rsp_size) {
- cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
- __func__, server->total_read,
- server->vals->read_rsp_size);
- rdata->result = -EIO;
- return cifs_readv_discard(server, mid);
- }
-
- data_offset = server->ops->read_data_offset(buf) +
- HEADER_PREAMBLE_SIZE(server);
- if (data_offset < server->total_read) {
- /*
- * win2k8 sometimes sends an offset of 0 when the read
- * is beyond the EOF. Treat it as if the data starts just after
- * the header.
- */
- cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
- __func__, data_offset);
- data_offset = server->total_read;
- } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
- /* data_offset is beyond the end of smallbuf */
- cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
- __func__, data_offset);
- rdata->result = -EIO;
- return cifs_readv_discard(server, mid);
- }
-
- cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
- __func__, server->total_read, data_offset);
-
- len = data_offset - server->total_read;
- if (len > 0) {
- /* read any junk before data into the rest of smallbuf */
- length = cifs_read_from_socket(server,
- buf + server->total_read, len);
- if (length < 0)
- return length;
- server->total_read += length;
- }
-
- /* how much data is in the response? */
-#ifdef CONFIG_CIFS_SMB_DIRECT
- use_rdma_mr = rdata->mr;
-#endif
- data_len = server->ops->read_data_length(buf, use_rdma_mr);
- if (!use_rdma_mr && (data_offset + data_len > buflen)) {
- /* data_len is corrupt -- discard frame */
- rdata->result = -EIO;
- return cifs_readv_discard(server, mid);
- }
-
- length = rdata->read_into_pages(server, rdata, data_len);
- if (length < 0)
- return length;
-
- server->total_read += length;
-
- cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
- server->total_read, buflen, data_len);
-
- /* discard anything left over */
- if (server->total_read < buflen)
- return cifs_readv_discard(server, mid);
-
- dequeue_mid(mid, false);
- mid->resp_buf = server->smallbuf;
- server->smallbuf = NULL;
- return length;
-}
diff --git a/fs/cifs/unc.c b/fs/cifs/unc.c
deleted file mode 100644
index f6fc5e343ea4..000000000000
--- a/fs/cifs/unc.c
+++ /dev/null
@@ -1,69 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2020, Microsoft Corporation.
- *
- * Author(s): Steve French <stfrench@microsoft.com>
- * Suresh Jayaraman <sjayaraman@suse.de>
- * Jeff Layton <jlayton@kernel.org>
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/inet.h>
-#include <linux/ctype.h>
-#include "cifsglob.h"
-#include "cifsproto.h"
-
-/* extract the host portion of the UNC string */
-char *extract_hostname(const char *unc)
-{
- const char *src;
- char *dst, *delim;
- unsigned int len;
-
- /* skip double chars at beginning of string */
- /* BB: check validity of these bytes? */
- if (strlen(unc) < 3)
- return ERR_PTR(-EINVAL);
- for (src = unc; *src && *src == '\\'; src++)
- ;
- if (!*src)
- return ERR_PTR(-EINVAL);
-
- /* delimiter between hostname and sharename is always '\\' now */
- delim = strchr(src, '\\');
- if (!delim)
- return ERR_PTR(-EINVAL);
-
- len = delim - src;
- dst = kmalloc((len + 1), GFP_KERNEL);
- if (dst == NULL)
- return ERR_PTR(-ENOMEM);
-
- memcpy(dst, src, len);
- dst[len] = '\0';
-
- return dst;
-}
-
-char *extract_sharename(const char *unc)
-{
- const char *src;
- char *delim, *dst;
-
- /* skip double chars at the beginning */
- src = unc + 2;
-
- /* share name is always preceded by '\\' now */
- delim = strchr(src, '\\');
- if (!delim)
- return ERR_PTR(-EINVAL);
- delim++;
-
- /* caller has to free the memory */
- dst = kstrdup(delim, GFP_KERNEL);
- if (!dst)
- return ERR_PTR(-ENOMEM);
-
- return dst;
-}
diff --git a/fs/cifs/winucase.c b/fs/cifs/winucase.c
deleted file mode 100644
index 2f075b5b50df..000000000000
--- a/fs/cifs/winucase.c
+++ /dev/null
@@ -1,649 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * Copyright (c) Jeffrey Layton <jlayton@redhat.com>, 2013
- *
- * The const tables in this file were converted from the following info
- * provided by Microsoft:
- *
- * 3.1.5.3 Mapping UTF-16 Strings to Upper Case:
- *
- * https://msdn.microsoft.com/en-us/library/hh877830.aspx
- * http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=10921
- *
- * In particular, the table in "Windows 8 Upper Case Mapping Table.txt" was
- * post-processed using the winucase_convert.pl script.
- */
-
-#include <linux/nls.h>
-
-wchar_t cifs_toupper(wchar_t in); /* quiet sparse */
-
-static const wchar_t t2_00[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x0058, 0x0059, 0x005a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
- 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
- 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0000,
- 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178,
-};
-
-static const wchar_t t2_01[256] = {
- 0x0000, 0x0100, 0x0000, 0x0102, 0x0000, 0x0104, 0x0000, 0x0106,
- 0x0000, 0x0108, 0x0000, 0x010a, 0x0000, 0x010c, 0x0000, 0x010e,
- 0x0000, 0x0110, 0x0000, 0x0112, 0x0000, 0x0114, 0x0000, 0x0116,
- 0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x011c, 0x0000, 0x011e,
- 0x0000, 0x0120, 0x0000, 0x0122, 0x0000, 0x0124, 0x0000, 0x0126,
- 0x0000, 0x0128, 0x0000, 0x012a, 0x0000, 0x012c, 0x0000, 0x012e,
- 0x0000, 0x0000, 0x0000, 0x0132, 0x0000, 0x0134, 0x0000, 0x0136,
- 0x0000, 0x0000, 0x0139, 0x0000, 0x013b, 0x0000, 0x013d, 0x0000,
- 0x013f, 0x0000, 0x0141, 0x0000, 0x0143, 0x0000, 0x0145, 0x0000,
- 0x0147, 0x0000, 0x0000, 0x014a, 0x0000, 0x014c, 0x0000, 0x014e,
- 0x0000, 0x0150, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156,
- 0x0000, 0x0158, 0x0000, 0x015a, 0x0000, 0x015c, 0x0000, 0x015e,
- 0x0000, 0x0160, 0x0000, 0x0162, 0x0000, 0x0164, 0x0000, 0x0166,
- 0x0000, 0x0168, 0x0000, 0x016a, 0x0000, 0x016c, 0x0000, 0x016e,
- 0x0000, 0x0170, 0x0000, 0x0172, 0x0000, 0x0174, 0x0000, 0x0176,
- 0x0000, 0x0000, 0x0179, 0x0000, 0x017b, 0x0000, 0x017d, 0x0000,
- 0x0243, 0x0000, 0x0000, 0x0182, 0x0000, 0x0184, 0x0000, 0x0000,
- 0x0187, 0x0000, 0x0000, 0x0000, 0x018b, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0191, 0x0000, 0x0000, 0x01f6, 0x0000, 0x0000,
- 0x0000, 0x0198, 0x023d, 0x0000, 0x0000, 0x0000, 0x0220, 0x0000,
- 0x0000, 0x01a0, 0x0000, 0x01a2, 0x0000, 0x01a4, 0x0000, 0x0000,
- 0x01a7, 0x0000, 0x0000, 0x0000, 0x0000, 0x01ac, 0x0000, 0x0000,
- 0x01af, 0x0000, 0x0000, 0x0000, 0x01b3, 0x0000, 0x01b5, 0x0000,
- 0x0000, 0x01b8, 0x0000, 0x0000, 0x0000, 0x01bc, 0x0000, 0x01f7,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01c4, 0x0000,
- 0x0000, 0x01c7, 0x0000, 0x0000, 0x01ca, 0x0000, 0x01cd, 0x0000,
- 0x01cf, 0x0000, 0x01d1, 0x0000, 0x01d3, 0x0000, 0x01d5, 0x0000,
- 0x01d7, 0x0000, 0x01d9, 0x0000, 0x01db, 0x018e, 0x0000, 0x01de,
- 0x0000, 0x01e0, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6,
- 0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x0000, 0x01ee,
- 0x0000, 0x0000, 0x0000, 0x01f1, 0x0000, 0x01f4, 0x0000, 0x0000,
- 0x0000, 0x01f8, 0x0000, 0x01fa, 0x0000, 0x01fc, 0x0000, 0x01fe,
-};
-
-static const wchar_t t2_02[256] = {
- 0x0000, 0x0200, 0x0000, 0x0202, 0x0000, 0x0204, 0x0000, 0x0206,
- 0x0000, 0x0208, 0x0000, 0x020a, 0x0000, 0x020c, 0x0000, 0x020e,
- 0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0214, 0x0000, 0x0216,
- 0x0000, 0x0218, 0x0000, 0x021a, 0x0000, 0x021c, 0x0000, 0x021e,
- 0x0000, 0x0000, 0x0000, 0x0222, 0x0000, 0x0224, 0x0000, 0x0226,
- 0x0000, 0x0228, 0x0000, 0x022a, 0x0000, 0x022c, 0x0000, 0x022e,
- 0x0000, 0x0230, 0x0000, 0x0232, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x023b, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0241, 0x0000, 0x0000, 0x0000, 0x0000, 0x0246,
- 0x0000, 0x0248, 0x0000, 0x024a, 0x0000, 0x024c, 0x0000, 0x024e,
- 0x2c6f, 0x2c6d, 0x0000, 0x0181, 0x0186, 0x0000, 0x0189, 0x018a,
- 0x0000, 0x018f, 0x0000, 0x0190, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0193, 0x0000, 0x0000, 0x0194, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0197, 0x0196, 0x0000, 0x2c62, 0x0000, 0x0000, 0x0000, 0x019c,
- 0x0000, 0x2c6e, 0x019d, 0x0000, 0x0000, 0x019f, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2c64, 0x0000, 0x0000,
- 0x01a6, 0x0000, 0x0000, 0x01a9, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x01ae, 0x0244, 0x01b1, 0x01b2, 0x0245, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x01b7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_03[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0370, 0x0000, 0x0372, 0x0000, 0x0000, 0x0000, 0x0376,
- 0x0000, 0x0000, 0x0000, 0x03fd, 0x03fe, 0x03ff, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0386, 0x0388, 0x0389, 0x038a,
- 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
- 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
- 0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
- 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x038c, 0x038e, 0x038f, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03cf,
- 0x0000, 0x03d8, 0x0000, 0x03da, 0x0000, 0x03dc, 0x0000, 0x03de,
- 0x0000, 0x03e0, 0x0000, 0x03e2, 0x0000, 0x03e4, 0x0000, 0x03e6,
- 0x0000, 0x03e8, 0x0000, 0x03ea, 0x0000, 0x03ec, 0x0000, 0x03ee,
- 0x0000, 0x0000, 0x03f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x03f7, 0x0000, 0x0000, 0x03fa, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_04[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
- 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
- 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
- 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
- 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
- 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
- 0x0000, 0x0460, 0x0000, 0x0462, 0x0000, 0x0464, 0x0000, 0x0466,
- 0x0000, 0x0468, 0x0000, 0x046a, 0x0000, 0x046c, 0x0000, 0x046e,
- 0x0000, 0x0470, 0x0000, 0x0472, 0x0000, 0x0474, 0x0000, 0x0476,
- 0x0000, 0x0478, 0x0000, 0x047a, 0x0000, 0x047c, 0x0000, 0x047e,
- 0x0000, 0x0480, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x048a, 0x0000, 0x048c, 0x0000, 0x048e,
- 0x0000, 0x0490, 0x0000, 0x0492, 0x0000, 0x0494, 0x0000, 0x0496,
- 0x0000, 0x0498, 0x0000, 0x049a, 0x0000, 0x049c, 0x0000, 0x049e,
- 0x0000, 0x04a0, 0x0000, 0x04a2, 0x0000, 0x04a4, 0x0000, 0x04a6,
- 0x0000, 0x04a8, 0x0000, 0x04aa, 0x0000, 0x04ac, 0x0000, 0x04ae,
- 0x0000, 0x04b0, 0x0000, 0x04b2, 0x0000, 0x04b4, 0x0000, 0x04b6,
- 0x0000, 0x04b8, 0x0000, 0x04ba, 0x0000, 0x04bc, 0x0000, 0x04be,
- 0x0000, 0x0000, 0x04c1, 0x0000, 0x04c3, 0x0000, 0x04c5, 0x0000,
- 0x04c7, 0x0000, 0x04c9, 0x0000, 0x04cb, 0x0000, 0x04cd, 0x04c0,
- 0x0000, 0x04d0, 0x0000, 0x04d2, 0x0000, 0x04d4, 0x0000, 0x04d6,
- 0x0000, 0x04d8, 0x0000, 0x04da, 0x0000, 0x04dc, 0x0000, 0x04de,
- 0x0000, 0x04e0, 0x0000, 0x04e2, 0x0000, 0x04e4, 0x0000, 0x04e6,
- 0x0000, 0x04e8, 0x0000, 0x04ea, 0x0000, 0x04ec, 0x0000, 0x04ee,
- 0x0000, 0x04f0, 0x0000, 0x04f2, 0x0000, 0x04f4, 0x0000, 0x04f6,
- 0x0000, 0x04f8, 0x0000, 0x04fa, 0x0000, 0x04fc, 0x0000, 0x04fe,
-};
-
-static const wchar_t t2_05[256] = {
- 0x0000, 0x0500, 0x0000, 0x0502, 0x0000, 0x0504, 0x0000, 0x0506,
- 0x0000, 0x0508, 0x0000, 0x050a, 0x0000, 0x050c, 0x0000, 0x050e,
- 0x0000, 0x0510, 0x0000, 0x0512, 0x0000, 0x0514, 0x0000, 0x0516,
- 0x0000, 0x0518, 0x0000, 0x051a, 0x0000, 0x051c, 0x0000, 0x051e,
- 0x0000, 0x0520, 0x0000, 0x0522, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
- 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f,
- 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
- 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f,
- 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_1d[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0xa77d, 0x0000, 0x0000, 0x0000, 0x2c63, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_1e[256] = {
- 0x0000, 0x1e00, 0x0000, 0x1e02, 0x0000, 0x1e04, 0x0000, 0x1e06,
- 0x0000, 0x1e08, 0x0000, 0x1e0a, 0x0000, 0x1e0c, 0x0000, 0x1e0e,
- 0x0000, 0x1e10, 0x0000, 0x1e12, 0x0000, 0x1e14, 0x0000, 0x1e16,
- 0x0000, 0x1e18, 0x0000, 0x1e1a, 0x0000, 0x1e1c, 0x0000, 0x1e1e,
- 0x0000, 0x1e20, 0x0000, 0x1e22, 0x0000, 0x1e24, 0x0000, 0x1e26,
- 0x0000, 0x1e28, 0x0000, 0x1e2a, 0x0000, 0x1e2c, 0x0000, 0x1e2e,
- 0x0000, 0x1e30, 0x0000, 0x1e32, 0x0000, 0x1e34, 0x0000, 0x1e36,
- 0x0000, 0x1e38, 0x0000, 0x1e3a, 0x0000, 0x1e3c, 0x0000, 0x1e3e,
- 0x0000, 0x1e40, 0x0000, 0x1e42, 0x0000, 0x1e44, 0x0000, 0x1e46,
- 0x0000, 0x1e48, 0x0000, 0x1e4a, 0x0000, 0x1e4c, 0x0000, 0x1e4e,
- 0x0000, 0x1e50, 0x0000, 0x1e52, 0x0000, 0x1e54, 0x0000, 0x1e56,
- 0x0000, 0x1e58, 0x0000, 0x1e5a, 0x0000, 0x1e5c, 0x0000, 0x1e5e,
- 0x0000, 0x1e60, 0x0000, 0x1e62, 0x0000, 0x1e64, 0x0000, 0x1e66,
- 0x0000, 0x1e68, 0x0000, 0x1e6a, 0x0000, 0x1e6c, 0x0000, 0x1e6e,
- 0x0000, 0x1e70, 0x0000, 0x1e72, 0x0000, 0x1e74, 0x0000, 0x1e76,
- 0x0000, 0x1e78, 0x0000, 0x1e7a, 0x0000, 0x1e7c, 0x0000, 0x1e7e,
- 0x0000, 0x1e80, 0x0000, 0x1e82, 0x0000, 0x1e84, 0x0000, 0x1e86,
- 0x0000, 0x1e88, 0x0000, 0x1e8a, 0x0000, 0x1e8c, 0x0000, 0x1e8e,
- 0x0000, 0x1e90, 0x0000, 0x1e92, 0x0000, 0x1e94, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x1ea0, 0x0000, 0x1ea2, 0x0000, 0x1ea4, 0x0000, 0x1ea6,
- 0x0000, 0x1ea8, 0x0000, 0x1eaa, 0x0000, 0x1eac, 0x0000, 0x1eae,
- 0x0000, 0x1eb0, 0x0000, 0x1eb2, 0x0000, 0x1eb4, 0x0000, 0x1eb6,
- 0x0000, 0x1eb8, 0x0000, 0x1eba, 0x0000, 0x1ebc, 0x0000, 0x1ebe,
- 0x0000, 0x1ec0, 0x0000, 0x1ec2, 0x0000, 0x1ec4, 0x0000, 0x1ec6,
- 0x0000, 0x1ec8, 0x0000, 0x1eca, 0x0000, 0x1ecc, 0x0000, 0x1ece,
- 0x0000, 0x1ed0, 0x0000, 0x1ed2, 0x0000, 0x1ed4, 0x0000, 0x1ed6,
- 0x0000, 0x1ed8, 0x0000, 0x1eda, 0x0000, 0x1edc, 0x0000, 0x1ede,
- 0x0000, 0x1ee0, 0x0000, 0x1ee2, 0x0000, 0x1ee4, 0x0000, 0x1ee6,
- 0x0000, 0x1ee8, 0x0000, 0x1eea, 0x0000, 0x1eec, 0x0000, 0x1eee,
- 0x0000, 0x1ef0, 0x0000, 0x1ef2, 0x0000, 0x1ef4, 0x0000, 0x1ef6,
- 0x0000, 0x1ef8, 0x0000, 0x1efa, 0x0000, 0x1efc, 0x0000, 0x1efe,
-};
-
-static const wchar_t t2_1f[256] = {
- 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, 0x1f1c, 0x1f1d, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, 0x1f4c, 0x1f4d, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x1f59, 0x0000, 0x1f5b, 0x0000, 0x1f5d, 0x0000, 0x1f5f,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1fba, 0x1fbb, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, 0x1fda, 0x1fdb,
- 0x1ff8, 0x1ff9, 0x1fea, 0x1feb, 0x1ffa, 0x1ffb, 0x0000, 0x0000,
- 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1fb8, 0x1fb9, 0x0000, 0x1fbc, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x1fcc, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1fd8, 0x1fd9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x1fe8, 0x1fe9, 0x0000, 0x0000, 0x0000, 0x1fec, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x1ffc, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_21[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2132, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,
- 0x2168, 0x2169, 0x216a, 0x216b, 0x216c, 0x216d, 0x216e, 0x216f,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x2183, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_24[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba, 0x24bb, 0x24bc, 0x24bd,
- 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2, 0x24c3, 0x24c4, 0x24c5,
- 0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca, 0x24cb, 0x24cc, 0x24cd,
- 0x24ce, 0x24cf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_2c[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x2c00, 0x2c01, 0x2c02, 0x2c03, 0x2c04, 0x2c05, 0x2c06, 0x2c07,
- 0x2c08, 0x2c09, 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c0e, 0x2c0f,
- 0x2c10, 0x2c11, 0x2c12, 0x2c13, 0x2c14, 0x2c15, 0x2c16, 0x2c17,
- 0x2c18, 0x2c19, 0x2c1a, 0x2c1b, 0x2c1c, 0x2c1d, 0x2c1e, 0x2c1f,
- 0x2c20, 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c27,
- 0x2c28, 0x2c29, 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x0000,
- 0x0000, 0x2c60, 0x0000, 0x0000, 0x0000, 0x023a, 0x023e, 0x0000,
- 0x2c67, 0x0000, 0x2c69, 0x0000, 0x2c6b, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x2c72, 0x0000, 0x0000, 0x2c75, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x2c80, 0x0000, 0x2c82, 0x0000, 0x2c84, 0x0000, 0x2c86,
- 0x0000, 0x2c88, 0x0000, 0x2c8a, 0x0000, 0x2c8c, 0x0000, 0x2c8e,
- 0x0000, 0x2c90, 0x0000, 0x2c92, 0x0000, 0x2c94, 0x0000, 0x2c96,
- 0x0000, 0x2c98, 0x0000, 0x2c9a, 0x0000, 0x2c9c, 0x0000, 0x2c9e,
- 0x0000, 0x2ca0, 0x0000, 0x2ca2, 0x0000, 0x2ca4, 0x0000, 0x2ca6,
- 0x0000, 0x2ca8, 0x0000, 0x2caa, 0x0000, 0x2cac, 0x0000, 0x2cae,
- 0x0000, 0x2cb0, 0x0000, 0x2cb2, 0x0000, 0x2cb4, 0x0000, 0x2cb6,
- 0x0000, 0x2cb8, 0x0000, 0x2cba, 0x0000, 0x2cbc, 0x0000, 0x2cbe,
- 0x0000, 0x2cc0, 0x0000, 0x2cc2, 0x0000, 0x2cc4, 0x0000, 0x2cc6,
- 0x0000, 0x2cc8, 0x0000, 0x2cca, 0x0000, 0x2ccc, 0x0000, 0x2cce,
- 0x0000, 0x2cd0, 0x0000, 0x2cd2, 0x0000, 0x2cd4, 0x0000, 0x2cd6,
- 0x0000, 0x2cd8, 0x0000, 0x2cda, 0x0000, 0x2cdc, 0x0000, 0x2cde,
- 0x0000, 0x2ce0, 0x0000, 0x2ce2, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_2d[256] = {
- 0x10a0, 0x10a1, 0x10a2, 0x10a3, 0x10a4, 0x10a5, 0x10a6, 0x10a7,
- 0x10a8, 0x10a9, 0x10aa, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af,
- 0x10b0, 0x10b1, 0x10b2, 0x10b3, 0x10b4, 0x10b5, 0x10b6, 0x10b7,
- 0x10b8, 0x10b9, 0x10ba, 0x10bb, 0x10bc, 0x10bd, 0x10be, 0x10bf,
- 0x10c0, 0x10c1, 0x10c2, 0x10c3, 0x10c4, 0x10c5, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_a6[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0xa640, 0x0000, 0xa642, 0x0000, 0xa644, 0x0000, 0xa646,
- 0x0000, 0xa648, 0x0000, 0xa64a, 0x0000, 0xa64c, 0x0000, 0xa64e,
- 0x0000, 0xa650, 0x0000, 0xa652, 0x0000, 0xa654, 0x0000, 0xa656,
- 0x0000, 0xa658, 0x0000, 0xa65a, 0x0000, 0xa65c, 0x0000, 0xa65e,
- 0x0000, 0x0000, 0x0000, 0xa662, 0x0000, 0xa664, 0x0000, 0xa666,
- 0x0000, 0xa668, 0x0000, 0xa66a, 0x0000, 0xa66c, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0xa680, 0x0000, 0xa682, 0x0000, 0xa684, 0x0000, 0xa686,
- 0x0000, 0xa688, 0x0000, 0xa68a, 0x0000, 0xa68c, 0x0000, 0xa68e,
- 0x0000, 0xa690, 0x0000, 0xa692, 0x0000, 0xa694, 0x0000, 0xa696,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_a7[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0xa722, 0x0000, 0xa724, 0x0000, 0xa726,
- 0x0000, 0xa728, 0x0000, 0xa72a, 0x0000, 0xa72c, 0x0000, 0xa72e,
- 0x0000, 0x0000, 0x0000, 0xa732, 0x0000, 0xa734, 0x0000, 0xa736,
- 0x0000, 0xa738, 0x0000, 0xa73a, 0x0000, 0xa73c, 0x0000, 0xa73e,
- 0x0000, 0xa740, 0x0000, 0xa742, 0x0000, 0xa744, 0x0000, 0xa746,
- 0x0000, 0xa748, 0x0000, 0xa74a, 0x0000, 0xa74c, 0x0000, 0xa74e,
- 0x0000, 0xa750, 0x0000, 0xa752, 0x0000, 0xa754, 0x0000, 0xa756,
- 0x0000, 0xa758, 0x0000, 0xa75a, 0x0000, 0xa75c, 0x0000, 0xa75e,
- 0x0000, 0xa760, 0x0000, 0xa762, 0x0000, 0xa764, 0x0000, 0xa766,
- 0x0000, 0xa768, 0x0000, 0xa76a, 0x0000, 0xa76c, 0x0000, 0xa76e,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0xa779, 0x0000, 0xa77b, 0x0000, 0x0000, 0xa77e,
- 0x0000, 0xa780, 0x0000, 0xa782, 0x0000, 0xa784, 0x0000, 0xa786,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xa78b, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t t2_ff[256] = {
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27,
- 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f,
- 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37,
- 0xff38, 0xff39, 0xff3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-};
-
-static const wchar_t *const toplevel[256] = {
- t2_00, t2_01, t2_02, t2_03, t2_04, t2_05, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, t2_1d, t2_1e, t2_1f,
- NULL, t2_21, NULL, NULL, t2_24, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, t2_2c, t2_2d, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, t2_a6, t2_a7,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, t2_ff,
-};
-
-/**
- * cifs_toupper - convert a wchar_t from lower to uppercase
- * @in: character to convert from lower to uppercase
- *
- * This function consults the static tables above to convert a wchar_t from
- * lower to uppercase. In the event that there is no mapping, the original
- * "in" character is returned.
- */
-wchar_t
-cifs_toupper(wchar_t in)
-{
- unsigned char idx;
- const wchar_t *tbl;
- wchar_t out;
-
- /* grab upper byte */
- idx = (in & 0xff00) >> 8;
-
- /* find pointer to 2nd layer table */
- tbl = toplevel[idx];
- if (!tbl)
- return in;
-
- /* grab lower byte */
- idx = in & 0xff;
-
- /* look up character in table */
- out = tbl[idx];
- if (out)
- return out;
-
- return in;
-}
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
deleted file mode 100644
index 998fa51f9b68..000000000000
--- a/fs/cifs/xattr.c
+++ /dev/null
@@ -1,555 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1
-/*
- *
- * Copyright (c) International Business Machines Corp., 2003, 2007
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-#include <linux/fs.h>
-#include <linux/posix_acl_xattr.h>
-#include <linux/slab.h>
-#include <linux/xattr.h>
-#include "cifsfs.h"
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_debug.h"
-#include "cifs_fs_sb.h"
-#include "cifs_unicode.h"
-#include "cifs_ioctl.h"
-
-#define MAX_EA_VALUE_SIZE CIFSMaxBufSize
-#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" /* DACL only */
-#define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd" /* owner plus DACL */
-#define CIFS_XATTR_CIFS_NTSD_FULL "system.cifs_ntsd_full" /* owner/DACL/SACL */
-#define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */
-#define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */
-/*
- * Although these three are just aliases for the above, need to move away from
- * confusing users and using the 20+ year old term 'cifs' when it is no longer
- * secure, replaced by SMB2 (then even more highly secure SMB3) many years ago
- */
-#define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */
-#define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */
-#define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */
-#define SMB3_XATTR_ATTRIB "smb3.dosattrib" /* full name: user.smb3.dosattrib */
-#define SMB3_XATTR_CREATETIME "smb3.creationtime" /* user.smb3.creationtime */
-/* BB need to add server (Samba e.g) support for security and trusted prefix */
-
-enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
- XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
-
-static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon,
- struct inode *inode, const char *full_path,
- const void *value, size_t size)
-{
- ssize_t rc = -EOPNOTSUPP;
- __u32 *pattrib = (__u32 *)value;
- __u32 attrib;
- FILE_BASIC_INFO info_buf;
-
- if ((value == NULL) || (size != sizeof(__u32)))
- return -ERANGE;
-
- memset(&info_buf, 0, sizeof(info_buf));
- attrib = *pattrib;
- info_buf.Attributes = cpu_to_le32(attrib);
- if (pTcon->ses->server->ops->set_file_info)
- rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
- &info_buf, xid);
- if (rc == 0)
- CIFS_I(inode)->cifsAttrs = attrib;
-
- return rc;
-}
-
-static int cifs_creation_time_set(unsigned int xid, struct cifs_tcon *pTcon,
- struct inode *inode, const char *full_path,
- const void *value, size_t size)
-{
- ssize_t rc = -EOPNOTSUPP;
- __u64 *pcreation_time = (__u64 *)value;
- __u64 creation_time;
- FILE_BASIC_INFO info_buf;
-
- if ((value == NULL) || (size != sizeof(__u64)))
- return -ERANGE;
-
- memset(&info_buf, 0, sizeof(info_buf));
- creation_time = *pcreation_time;
- info_buf.CreationTime = cpu_to_le64(creation_time);
- if (pTcon->ses->server->ops->set_file_info)
- rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
- &info_buf, xid);
- if (rc == 0)
- CIFS_I(inode)->createtime = creation_time;
-
- return rc;
-}
-
-static int cifs_xattr_set(const struct xattr_handler *handler,
- struct user_namespace *mnt_userns,
- struct dentry *dentry, struct inode *inode,
- const char *name, const void *value,
- size_t size, int flags)
-{
- int rc = -EOPNOTSUPP;
- unsigned int xid;
- struct super_block *sb = dentry->d_sb;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct tcon_link *tlink;
- struct cifs_tcon *pTcon;
- const char *full_path;
- void *page;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- pTcon = tlink_tcon(tlink);
-
- xid = get_xid();
- page = alloc_dentry_path();
-
- full_path = build_path_from_dentry(dentry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto out;
- }
- /* return dos attributes as pseudo xattr */
- /* return alt name if available as pseudo attr */
-
- /* if proc/fs/cifs/streamstoxattr is set then
- search server for EAs or streams to
- returns as xattrs */
- if (size > MAX_EA_VALUE_SIZE) {
- cifs_dbg(FYI, "size of EA value too large\n");
- rc = -EOPNOTSUPP;
- goto out;
- }
-
- switch (handler->flags) {
- case XATTR_USER:
- cifs_dbg(FYI, "%s:setting user xattr %s\n", __func__, name);
- if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
- (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
- rc = cifs_attrib_set(xid, pTcon, inode, full_path,
- value, size);
- if (rc == 0) /* force revalidate of the inode */
- CIFS_I(inode)->time = 0;
- break;
- } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
- (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
- rc = cifs_creation_time_set(xid, pTcon, inode,
- full_path, value, size);
- if (rc == 0) /* force revalidate of the inode */
- CIFS_I(inode)->time = 0;
- break;
- }
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
- goto out;
-
- if (pTcon->ses->server->ops->set_EA)
- rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
- full_path, name, value, (__u16)size,
- cifs_sb->local_nls, cifs_sb);
- break;
-
- case XATTR_CIFS_ACL:
- case XATTR_CIFS_NTSD:
- case XATTR_CIFS_NTSD_FULL: {
- struct cifs_ntsd *pacl;
-
- if (!value)
- goto out;
- pacl = kmalloc(size, GFP_KERNEL);
- if (!pacl) {
- rc = -ENOMEM;
- } else {
- memcpy(pacl, value, size);
- if (pTcon->ses->server->ops->set_acl) {
- int aclflags = 0;
- rc = 0;
-
- switch (handler->flags) {
- case XATTR_CIFS_NTSD_FULL:
- aclflags = (CIFS_ACL_OWNER |
- CIFS_ACL_GROUP |
- CIFS_ACL_DACL |
- CIFS_ACL_SACL);
- break;
- case XATTR_CIFS_NTSD:
- aclflags = (CIFS_ACL_OWNER |
- CIFS_ACL_GROUP |
- CIFS_ACL_DACL);
- break;
- case XATTR_CIFS_ACL:
- default:
- aclflags = CIFS_ACL_DACL;
- }
-
- rc = pTcon->ses->server->ops->set_acl(pacl,
- size, inode, full_path, aclflags);
- } else {
- rc = -EOPNOTSUPP;
- }
- if (rc == 0) /* force revalidate of the inode */
- CIFS_I(inode)->time = 0;
- kfree(pacl);
- }
- break;
- }
-
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- case XATTR_ACL_ACCESS:
-#ifdef CONFIG_CIFS_POSIX
- if (!value)
- goto out;
- if (sb->s_flags & SB_POSIXACL)
- rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
- value, (const int)size,
- ACL_TYPE_ACCESS, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
-#endif /* CONFIG_CIFS_POSIX */
- break;
-
- case XATTR_ACL_DEFAULT:
-#ifdef CONFIG_CIFS_POSIX
- if (!value)
- goto out;
- if (sb->s_flags & SB_POSIXACL)
- rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
- value, (const int)size,
- ACL_TYPE_DEFAULT, cifs_sb->local_nls,
- cifs_remap(cifs_sb));
-#endif /* CONFIG_CIFS_POSIX */
- break;
-#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- }
-
-out:
- free_dentry_path(page);
- free_xid(xid);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-static int cifs_attrib_get(struct dentry *dentry,
- struct inode *inode, void *value,
- size_t size)
-{
- ssize_t rc;
- __u32 *pattribute;
-
- rc = cifs_revalidate_dentry_attr(dentry);
-
- if (rc)
- return rc;
-
- if ((value == NULL) || (size == 0))
- return sizeof(__u32);
- else if (size < sizeof(__u32))
- return -ERANGE;
-
- /* return dos attributes as pseudo xattr */
- pattribute = (__u32 *)value;
- *pattribute = CIFS_I(inode)->cifsAttrs;
-
- return sizeof(__u32);
-}
-
-static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
- void *value, size_t size)
-{
- ssize_t rc;
- __u64 *pcreatetime;
-
- rc = cifs_revalidate_dentry_attr(dentry);
- if (rc)
- return rc;
-
- if ((value == NULL) || (size == 0))
- return sizeof(__u64);
- else if (size < sizeof(__u64))
- return -ERANGE;
-
- /* return dos attributes as pseudo xattr */
- pcreatetime = (__u64 *)value;
- *pcreatetime = CIFS_I(inode)->createtime;
- return sizeof(__u64);
-}
-
-
-static int cifs_xattr_get(const struct xattr_handler *handler,
- struct dentry *dentry, struct inode *inode,
- const char *name, void *value, size_t size)
-{
- ssize_t rc = -EOPNOTSUPP;
- unsigned int xid;
- struct super_block *sb = dentry->d_sb;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct tcon_link *tlink;
- struct cifs_tcon *pTcon;
- const char *full_path;
- void *page;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- pTcon = tlink_tcon(tlink);
-
- xid = get_xid();
- page = alloc_dentry_path();
-
- full_path = build_path_from_dentry(dentry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto out;
- }
-
- /* return alt name if available as pseudo attr */
- switch (handler->flags) {
- case XATTR_USER:
- cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
- if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
- (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
- rc = cifs_attrib_get(dentry, inode, value, size);
- break;
- } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
- (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
- rc = cifs_creation_time_get(dentry, inode, value, size);
- break;
- }
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
- goto out;
-
- if (pTcon->ses->server->ops->query_all_EAs)
- rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
- full_path, name, value, size, cifs_sb);
- break;
-
- case XATTR_CIFS_ACL:
- case XATTR_CIFS_NTSD:
- case XATTR_CIFS_NTSD_FULL: {
- /*
- * fetch owner, DACL, and SACL if asked for full descriptor,
- * fetch owner and DACL otherwise
- */
- u32 acllen, extra_info;
- struct cifs_ntsd *pacl;
-
- if (pTcon->ses->server->ops->get_acl == NULL)
- goto out; /* rc already EOPNOTSUPP */
-
- if (handler->flags == XATTR_CIFS_NTSD_FULL) {
- extra_info = SACL_SECINFO;
- } else {
- extra_info = 0;
- }
- pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
- inode, full_path, &acllen, extra_info);
- if (IS_ERR(pacl)) {
- rc = PTR_ERR(pacl);
- cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
- __func__, rc);
- } else {
- if (value) {
- if (acllen > size)
- acllen = -ERANGE;
- else
- memcpy(value, pacl, acllen);
- }
- rc = acllen;
- kfree(pacl);
- }
- break;
- }
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
- case XATTR_ACL_ACCESS:
-#ifdef CONFIG_CIFS_POSIX
- if (sb->s_flags & SB_POSIXACL)
- rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
- value, size, ACL_TYPE_ACCESS,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
-#endif /* CONFIG_CIFS_POSIX */
- break;
-
- case XATTR_ACL_DEFAULT:
-#ifdef CONFIG_CIFS_POSIX
- if (sb->s_flags & SB_POSIXACL)
- rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
- value, size, ACL_TYPE_DEFAULT,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
-#endif /* CONFIG_CIFS_POSIX */
- break;
-#endif /* ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
- }
-
- /* We could add an additional check for streams ie
- if proc/fs/cifs/streamstoxattr is set then
- search server for EAs or streams to
- returns as xattrs */
-
- if (rc == -EINVAL)
- rc = -EOPNOTSUPP;
-
-out:
- free_dentry_path(page);
- free_xid(xid);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
-{
- ssize_t rc = -EOPNOTSUPP;
- unsigned int xid;
- struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
- struct tcon_link *tlink;
- struct cifs_tcon *pTcon;
- const char *full_path;
- void *page;
-
- if (unlikely(cifs_forced_shutdown(cifs_sb)))
- return -EIO;
-
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
- return -EOPNOTSUPP;
-
- tlink = cifs_sb_tlink(cifs_sb);
- if (IS_ERR(tlink))
- return PTR_ERR(tlink);
- pTcon = tlink_tcon(tlink);
-
- xid = get_xid();
- page = alloc_dentry_path();
-
- full_path = build_path_from_dentry(direntry, page);
- if (IS_ERR(full_path)) {
- rc = PTR_ERR(full_path);
- goto list_ea_exit;
- }
- /* return dos attributes as pseudo xattr */
- /* return alt name if available as pseudo attr */
-
- /* if proc/fs/cifs/streamstoxattr is set then
- search server for EAs or streams to
- returns as xattrs */
-
- if (pTcon->ses->server->ops->query_all_EAs)
- rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
- full_path, NULL, data, buf_size, cifs_sb);
-list_ea_exit:
- free_dentry_path(page);
- free_xid(xid);
- cifs_put_tlink(tlink);
- return rc;
-}
-
-static const struct xattr_handler cifs_user_xattr_handler = {
- .prefix = XATTR_USER_PREFIX,
- .flags = XATTR_USER,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-/* os2.* attributes are treated like user.* attributes */
-static const struct xattr_handler cifs_os2_xattr_handler = {
- .prefix = XATTR_OS2_PREFIX,
- .flags = XATTR_USER,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-static const struct xattr_handler cifs_cifs_acl_xattr_handler = {
- .name = CIFS_XATTR_CIFS_ACL,
- .flags = XATTR_CIFS_ACL,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-/*
- * Although this is just an alias for the above, need to move away from
- * confusing users and using the 20 year old term 'cifs' when it is no
- * longer secure and was replaced by SMB2/SMB3 a long time ago, and
- * SMB3 and later are highly secure.
- */
-static const struct xattr_handler smb3_acl_xattr_handler = {
- .name = SMB3_XATTR_CIFS_ACL,
- .flags = XATTR_CIFS_ACL,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-static const struct xattr_handler cifs_cifs_ntsd_xattr_handler = {
- .name = CIFS_XATTR_CIFS_NTSD,
- .flags = XATTR_CIFS_NTSD,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-/*
- * Although this is just an alias for the above, need to move away from
- * confusing users and using the 20 year old term 'cifs' when it is no
- * longer secure and was replaced by SMB2/SMB3 a long time ago, and
- * SMB3 and later are highly secure.
- */
-static const struct xattr_handler smb3_ntsd_xattr_handler = {
- .name = SMB3_XATTR_CIFS_NTSD,
- .flags = XATTR_CIFS_NTSD,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-static const struct xattr_handler cifs_cifs_ntsd_full_xattr_handler = {
- .name = CIFS_XATTR_CIFS_NTSD_FULL,
- .flags = XATTR_CIFS_NTSD_FULL,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-/*
- * Although this is just an alias for the above, need to move away from
- * confusing users and using the 20 year old term 'cifs' when it is no
- * longer secure and was replaced by SMB2/SMB3 a long time ago, and
- * SMB3 and later are highly secure.
- */
-static const struct xattr_handler smb3_ntsd_full_xattr_handler = {
- .name = SMB3_XATTR_CIFS_NTSD_FULL,
- .flags = XATTR_CIFS_NTSD_FULL,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-
-static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
- .name = XATTR_NAME_POSIX_ACL_ACCESS,
- .flags = XATTR_ACL_ACCESS,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-static const struct xattr_handler cifs_posix_acl_default_xattr_handler = {
- .name = XATTR_NAME_POSIX_ACL_DEFAULT,
- .flags = XATTR_ACL_DEFAULT,
- .get = cifs_xattr_get,
- .set = cifs_xattr_set,
-};
-
-const struct xattr_handler *cifs_xattr_handlers[] = {
- &cifs_user_xattr_handler,
- &cifs_os2_xattr_handler,
- &cifs_cifs_acl_xattr_handler,
- &smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */
- &cifs_cifs_ntsd_xattr_handler,
- &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */
- &cifs_cifs_ntsd_full_xattr_handler,
- &smb3_ntsd_full_xattr_handler, /* alias for above since avoiding "cifs" */
- &cifs_posix_acl_access_xattr_handler,
- &cifs_posix_acl_default_xattr_handler,
- NULL
-};
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 60c6fb91fb58..bc6cd5f4b107 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -783,9 +783,13 @@ static inline bool should_fault_in_pages(struct iov_iter *i,
if (!user_backed_iter(i))
return false;
+ /*
+ * Try to fault in multiple pages initially. When that doesn't result
+ * in any progress, fall back to a single page.
+ */
size = PAGE_SIZE;
offs = offset_in_page(iocb->ki_pos);
- if (*prev_count != count || !*window_size) {
+ if (*prev_count != count) {
size_t nr_dirtied;
nr_dirtied = max(current->nr_dirtied_pause -
@@ -869,6 +873,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
struct gfs2_inode *ip = GFS2_I(inode);
size_t prev_count = 0, window_size = 0;
size_t written = 0;
+ bool enough_retries;
ssize_t ret;
/*
@@ -912,11 +917,17 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
if (ret > 0)
written = ret;
+ enough_retries = prev_count == iov_iter_count(from) &&
+ window_size <= PAGE_SIZE;
if (should_fault_in_pages(from, iocb, &prev_count, &window_size)) {
gfs2_glock_dq(gh);
window_size -= fault_in_iov_iter_readable(from, window_size);
- if (window_size)
- goto retry;
+ if (window_size) {
+ if (!enough_retries)
+ goto retry;
+ /* fall back to buffered I/O */
+ ret = 0;
+ }
}
out_unlock:
if (gfs2_holder_queued(gh))
diff --git a/fs/ksmbd/Kconfig b/fs/ksmbd/Kconfig
deleted file mode 100644
index e1fe17747ed6..000000000000
--- a/fs/ksmbd/Kconfig
+++ /dev/null
@@ -1,68 +0,0 @@
-config SMB_SERVER
- tristate "SMB3 server support (EXPERIMENTAL)"
- depends on INET
- depends on MULTIUSER
- depends on FILE_LOCKING
- select NLS
- select NLS_UTF8
- select CRYPTO
- select CRYPTO_MD5
- select CRYPTO_HMAC
- select CRYPTO_ECB
- select CRYPTO_LIB_DES
- select CRYPTO_SHA256
- select CRYPTO_CMAC
- select CRYPTO_SHA512
- select CRYPTO_AEAD2
- select CRYPTO_CCM
- select CRYPTO_GCM
- select ASN1
- select OID_REGISTRY
- select CRC32
- default n
- help
- Choose Y here if you want to allow SMB3 compliant clients
- to access files residing on this system using SMB3 protocol.
- To compile the SMB3 server support as a module,
- choose M here: the module will be called ksmbd.
-
- You may choose to use a samba server instead, in which
- case you can choose N here.
-
- You also need to install user space programs which can be found
- in ksmbd-tools, available from
- https://github.com/cifsd-team/ksmbd-tools.
- More detail about how to run the ksmbd kernel server is
- available via README file
- (https://github.com/cifsd-team/ksmbd-tools/blob/master/README).
-
- ksmbd kernel server includes support for auto-negotiation,
- Secure negotiate, Pre-authentication integrity, oplock/lease,
- compound requests, multi-credit, packet signing, RDMA(smbdirect),
- smb3 encryption, copy-offload, secure per-user session
- establishment via NTLM or NTLMv2.
-
-config SMB_SERVER_SMBDIRECT
- bool "Support for SMB Direct protocol"
- depends on SMB_SERVER=m && INFINIBAND && INFINIBAND_ADDR_TRANS || SMB_SERVER=y && INFINIBAND=y && INFINIBAND_ADDR_TRANS=y
- select SG_POOL
- default n
-
- help
- Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1.
-
- SMB Direct allows transferring SMB packets over RDMA. If unsure,
- say N.
-
-config SMB_SERVER_CHECK_CAP_NET_ADMIN
- bool "Enable check network administration capability"
- depends on SMB_SERVER
- default y
-
- help
- Prevent unprivileged processes to start the ksmbd kernel server.
-
-config SMB_SERVER_KERBEROS5
- bool "Support for Kerberos 5"
- depends on SMB_SERVER
- default n
diff --git a/fs/ksmbd/Makefile b/fs/ksmbd/Makefile
deleted file mode 100644
index 7d6337a7dee4..000000000000
--- a/fs/ksmbd/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-#
-# Makefile for Linux SMB3 kernel server
-#
-obj-$(CONFIG_SMB_SERVER) += ksmbd.o
-
-ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o ndr.o \
- misc.o oplock.o connection.o ksmbd_work.o crypto_ctx.o \
- mgmt/ksmbd_ida.o mgmt/user_config.o mgmt/share_config.o \
- mgmt/tree_connect.o mgmt/user_session.o smb_common.o \
- transport_tcp.o transport_ipc.o smbacl.o smb2pdu.o \
- smb2ops.o smb2misc.o ksmbd_spnego_negtokeninit.asn1.o \
- ksmbd_spnego_negtokentarg.asn1.o asn1.o
-
-$(obj)/asn1.o: $(obj)/ksmbd_spnego_negtokeninit.asn1.h $(obj)/ksmbd_spnego_negtokentarg.asn1.h
-
-$(obj)/ksmbd_spnego_negtokeninit.asn1.o: $(obj)/ksmbd_spnego_negtokeninit.asn1.c $(obj)/ksmbd_spnego_negtokeninit.asn1.h
-$(obj)/ksmbd_spnego_negtokentarg.asn1.o: $(obj)/ksmbd_spnego_negtokentarg.asn1.c $(obj)/ksmbd_spnego_negtokentarg.asn1.h
-
-ksmbd-$(CONFIG_SMB_SERVER_SMBDIRECT) += transport_rdma.o
diff --git a/fs/ksmbd/asn1.c b/fs/ksmbd/asn1.c
deleted file mode 100644
index c03eba090368..000000000000
--- a/fs/ksmbd/asn1.c
+++ /dev/null
@@ -1,239 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
- * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
- *
- * Copyright (c) 2000 RP Internet (www.rpi.net.au).
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/oid_registry.h>
-
-#include "glob.h"
-
-#include "asn1.h"
-#include "connection.h"
-#include "auth.h"
-#include "ksmbd_spnego_negtokeninit.asn1.h"
-#include "ksmbd_spnego_negtokentarg.asn1.h"
-
-#define NTLMSSP_OID_LEN 10
-
-static char NTLMSSP_OID_STR[NTLMSSP_OID_LEN] = { 0x2b, 0x06, 0x01, 0x04, 0x01,
- 0x82, 0x37, 0x02, 0x02, 0x0a };
-
-int
-ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
- struct ksmbd_conn *conn)
-{
- return asn1_ber_decoder(&ksmbd_spnego_negtokeninit_decoder, conn,
- security_blob, length);
-}
-
-int
-ksmbd_decode_negTokenTarg(unsigned char *security_blob, int length,
- struct ksmbd_conn *conn)
-{
- return asn1_ber_decoder(&ksmbd_spnego_negtokentarg_decoder, conn,
- security_blob, length);
-}
-
-static int compute_asn_hdr_len_bytes(int len)
-{
- if (len > 0xFFFFFF)
- return 4;
- else if (len > 0xFFFF)
- return 3;
- else if (len > 0xFF)
- return 2;
- else if (len > 0x7F)
- return 1;
- else
- return 0;
-}
-
-static void encode_asn_tag(char *buf, unsigned int *ofs, char tag, char seq,
- int length)
-{
- int i;
- int index = *ofs;
- char hdr_len = compute_asn_hdr_len_bytes(length);
- int len = length + 2 + hdr_len;
-
- /* insert tag */
- buf[index++] = tag;
-
- if (!hdr_len) {
- buf[index++] = len;
- } else {
- buf[index++] = 0x80 | hdr_len;
- for (i = hdr_len - 1; i >= 0; i--)
- buf[index++] = (len >> (i * 8)) & 0xFF;
- }
-
- /* insert seq */
- len = len - (index - *ofs);
- buf[index++] = seq;
-
- if (!hdr_len) {
- buf[index++] = len;
- } else {
- buf[index++] = 0x80 | hdr_len;
- for (i = hdr_len - 1; i >= 0; i--)
- buf[index++] = (len >> (i * 8)) & 0xFF;
- }
-
- *ofs += (index - *ofs);
-}
-
-int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
- char *ntlm_blob, int ntlm_blob_len)
-{
- char *buf;
- unsigned int ofs = 0;
- int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
- int oid_len = 4 + compute_asn_hdr_len_bytes(NTLMSSP_OID_LEN) * 2 +
- NTLMSSP_OID_LEN;
- int ntlmssp_len = 4 + compute_asn_hdr_len_bytes(ntlm_blob_len) * 2 +
- ntlm_blob_len;
- int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len +
- oid_len + ntlmssp_len) * 2 +
- neg_result_len + oid_len + ntlmssp_len;
-
- buf = kmalloc(total_len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- /* insert main gss header */
- encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len + oid_len +
- ntlmssp_len);
-
- /* insert neg result */
- encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
- buf[ofs++] = 1;
-
- /* insert oid */
- encode_asn_tag(buf, &ofs, 0xa1, 0x06, NTLMSSP_OID_LEN);
- memcpy(buf + ofs, NTLMSSP_OID_STR, NTLMSSP_OID_LEN);
- ofs += NTLMSSP_OID_LEN;
-
- /* insert response token - ntlmssp blob */
- encode_asn_tag(buf, &ofs, 0xa2, 0x04, ntlm_blob_len);
- memcpy(buf + ofs, ntlm_blob, ntlm_blob_len);
- ofs += ntlm_blob_len;
-
- *pbuffer = buf;
- *buflen = total_len;
- return 0;
-}
-
-int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
- int neg_result)
-{
- char *buf;
- unsigned int ofs = 0;
- int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
- int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len) * 2 +
- neg_result_len;
-
- buf = kmalloc(total_len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- /* insert main gss header */
- encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len);
-
- /* insert neg result */
- encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
- if (neg_result)
- buf[ofs++] = 2;
- else
- buf[ofs++] = 0;
-
- *pbuffer = buf;
- *buflen = total_len;
- return 0;
-}
-
-int ksmbd_gssapi_this_mech(void *context, size_t hdrlen, unsigned char tag,
- const void *value, size_t vlen)
-{
- enum OID oid;
-
- oid = look_up_OID(value, vlen);
- if (oid != OID_spnego) {
- char buf[50];
-
- sprint_oid(value, vlen, buf, sizeof(buf));
- ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
- return -EBADMSG;
- }
-
- return 0;
-}
-
-int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
- unsigned char tag, const void *value,
- size_t vlen)
-{
- struct ksmbd_conn *conn = context;
- enum OID oid;
- int mech_type;
-
- oid = look_up_OID(value, vlen);
- if (oid == OID_ntlmssp) {
- mech_type = KSMBD_AUTH_NTLMSSP;
- } else if (oid == OID_mskrb5) {
- mech_type = KSMBD_AUTH_MSKRB5;
- } else if (oid == OID_krb5) {
- mech_type = KSMBD_AUTH_KRB5;
- } else if (oid == OID_krb5u2u) {
- mech_type = KSMBD_AUTH_KRB5U2U;
- } else {
- char buf[50];
-
- sprint_oid(value, vlen, buf, sizeof(buf));
- ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
- return -EBADMSG;
- }
-
- conn->auth_mechs |= mech_type;
- if (conn->preferred_auth_mech == 0)
- conn->preferred_auth_mech = mech_type;
-
- return 0;
-}
-
-int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
- unsigned char tag, const void *value,
- size_t vlen)
-{
- struct ksmbd_conn *conn = context;
-
- conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
- if (!conn->mechToken)
- return -ENOMEM;
-
- memcpy(conn->mechToken, value, vlen);
- conn->mechToken[vlen] = '\0';
- return 0;
-}
-
-int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
- unsigned char tag, const void *value,
- size_t vlen)
-{
- struct ksmbd_conn *conn = context;
-
- conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
- if (!conn->mechToken)
- return -ENOMEM;
-
- memcpy(conn->mechToken, value, vlen);
- conn->mechToken[vlen] = '\0';
- return 0;
-}
diff --git a/fs/ksmbd/asn1.h b/fs/ksmbd/asn1.h
deleted file mode 100644
index ce105f4ce305..000000000000
--- a/fs/ksmbd/asn1.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
- * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
- *
- * Copyright (c) 2000 RP Internet (www.rpi.net.au).
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __ASN1_H__
-#define __ASN1_H__
-
-int ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
- struct ksmbd_conn *conn);
-int ksmbd_decode_negTokenTarg(unsigned char *security_blob, int length,
- struct ksmbd_conn *conn);
-int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
- char *ntlm_blob, int ntlm_blob_len);
-int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
- int neg_result);
-#endif /* __ASN1_H__ */
diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c
deleted file mode 100644
index df8fb076f6f1..000000000000
--- a/fs/ksmbd/auth.c
+++ /dev/null
@@ -1,1206 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-#include <linux/backing-dev.h>
-#include <linux/writeback.h>
-#include <linux/uio.h>
-#include <linux/xattr.h>
-#include <crypto/hash.h>
-#include <crypto/aead.h>
-#include <linux/random.h>
-#include <linux/scatterlist.h>
-
-#include "auth.h"
-#include "glob.h"
-
-#include <linux/fips.h>
-#include <crypto/des.h>
-
-#include "server.h"
-#include "smb_common.h"
-#include "connection.h"
-#include "mgmt/user_session.h"
-#include "mgmt/user_config.h"
-#include "crypto_ctx.h"
-#include "transport_ipc.h"
-#include "../smbfs_common/arc4.h"
-
-/*
- * Fixed format data defining GSS header and fixed string
- * "not_defined_in_RFC4178@please_ignore".
- * So sec blob data in neg phase could be generated statically.
- */
-static char NEGOTIATE_GSS_HEADER[AUTH_GSS_LENGTH] = {
-#ifdef CONFIG_SMB_SERVER_KERBEROS5
- 0x60, 0x5e, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
- 0x05, 0x02, 0xa0, 0x54, 0x30, 0x52, 0xa0, 0x24,
- 0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x09, 0x2a,
- 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02,
- 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
- 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a, 0x30, 0x28,
- 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f, 0x74, 0x5f,
- 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f,
- 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43, 0x34, 0x31,
- 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65, 0x61, 0x73,
- 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65
-#else
- 0x60, 0x48, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
- 0x05, 0x02, 0xa0, 0x3e, 0x30, 0x3c, 0xa0, 0x0e,
- 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
- 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a,
- 0x30, 0x28, 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f,
- 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
- 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43,
- 0x34, 0x31, 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65,
- 0x61, 0x73, 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f,
- 0x72, 0x65
-#endif
-};
-
-void ksmbd_copy_gss_neg_header(void *buf)
-{
- memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH);
-}
-
-/**
- * ksmbd_gen_sess_key() - function to generate session key
- * @sess: session of connection
- * @hash: source hash value to be used for find session key
- * @hmac: source hmac value to be used for finding session key
- *
- */
-static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash,
- char *hmac)
-{
- struct ksmbd_crypto_ctx *ctx;
- int rc;
-
- ctx = ksmbd_crypto_ctx_find_hmacmd5();
- if (!ctx) {
- ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
- return -ENOMEM;
- }
-
- rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
- hash,
- CIFS_HMAC_MD5_HASH_SIZE);
- if (rc) {
- ksmbd_debug(AUTH, "hmacmd5 set key fail error %d\n", rc);
- goto out;
- }
-
- rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
- if (rc) {
- ksmbd_debug(AUTH, "could not init hmacmd5 error %d\n", rc);
- goto out;
- }
-
- rc = crypto_shash_update(CRYPTO_HMACMD5(ctx),
- hmac,
- SMB2_NTLMV2_SESSKEY_SIZE);
- if (rc) {
- ksmbd_debug(AUTH, "Could not update with response error %d\n", rc);
- goto out;
- }
-
- rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), sess->sess_key);
- if (rc) {
- ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n", rc);
- goto out;
- }
-
-out:
- ksmbd_release_crypto_ctx(ctx);
- return rc;
-}
-
-static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
- char *ntlmv2_hash, char *dname)
-{
- int ret, len, conv_len;
- wchar_t *domain = NULL;
- __le16 *uniname = NULL;
- struct ksmbd_crypto_ctx *ctx;
-
- ctx = ksmbd_crypto_ctx_find_hmacmd5();
- if (!ctx) {
- ksmbd_debug(AUTH, "can't generate ntlmv2 hash\n");
- return -ENOMEM;
- }
-
- ret = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
- user_passkey(sess->user),
- CIFS_ENCPWD_SIZE);
- if (ret) {
- ksmbd_debug(AUTH, "Could not set NT Hash as a key\n");
- goto out;
- }
-
- ret = crypto_shash_init(CRYPTO_HMACMD5(ctx));
- if (ret) {
- ksmbd_debug(AUTH, "could not init hmacmd5\n");
- goto out;
- }
-
- /* convert user_name to unicode */
- len = strlen(user_name(sess->user));
- uniname = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
- if (!uniname) {
- ret = -ENOMEM;
- goto out;
- }
-
- conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len,
- conn->local_nls);
- if (conv_len < 0 || conv_len > len) {
- ret = -EINVAL;
- goto out;
- }
- UniStrupr(uniname);
-
- ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
- (char *)uniname,
- UNICODE_LEN(conv_len));
- if (ret) {
- ksmbd_debug(AUTH, "Could not update with user\n");
- goto out;
- }
-
- /* Convert domain name or conn name to unicode and uppercase */
- len = strlen(dname);
- domain = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
- if (!domain) {
- ret = -ENOMEM;
- goto out;
- }
-
- conv_len = smb_strtoUTF16((__le16 *)domain, dname, len,
- conn->local_nls);
- if (conv_len < 0 || conv_len > len) {
- ret = -EINVAL;
- goto out;
- }
-
- ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
- (char *)domain,
- UNICODE_LEN(conv_len));
- if (ret) {
- ksmbd_debug(AUTH, "Could not update with domain\n");
- goto out;
- }
-
- ret = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_hash);
- if (ret)
- ksmbd_debug(AUTH, "Could not generate md5 hash\n");
-out:
- kfree(uniname);
- kfree(domain);
- ksmbd_release_crypto_ctx(ctx);
- return ret;
-}
-
-/**
- * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
- * @sess: session of connection
- * @ntlmv2: NTLMv2 challenge response
- * @blen: NTLMv2 blob length
- * @domain_name: domain name
- *
- * Return: 0 on success, error number on error
- */
-int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
- struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
- char *cryptkey)
-{
- char ntlmv2_hash[CIFS_ENCPWD_SIZE];
- char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
- struct ksmbd_crypto_ctx *ctx = NULL;
- char *construct = NULL;
- int rc, len;
-
- rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name);
- if (rc) {
- ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
- goto out;
- }
-
- ctx = ksmbd_crypto_ctx_find_hmacmd5();
- if (!ctx) {
- ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
- return -ENOMEM;
- }
-
- rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
- ntlmv2_hash,
- CIFS_HMAC_MD5_HASH_SIZE);
- if (rc) {
- ksmbd_debug(AUTH, "Could not set NTLMV2 Hash as a key\n");
- goto out;
- }
-
- rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
- if (rc) {
- ksmbd_debug(AUTH, "Could not init hmacmd5\n");
- goto out;
- }
-
- len = CIFS_CRYPTO_KEY_SIZE + blen;
- construct = kzalloc(len, GFP_KERNEL);
- if (!construct) {
- rc = -ENOMEM;
- goto out;
- }
-
- memcpy(construct, cryptkey, CIFS_CRYPTO_KEY_SIZE);
- memcpy(construct + CIFS_CRYPTO_KEY_SIZE, &ntlmv2->blob_signature, blen);
-
- rc = crypto_shash_update(CRYPTO_HMACMD5(ctx), construct, len);
- if (rc) {
- ksmbd_debug(AUTH, "Could not update with response\n");
- goto out;
- }
-
- rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_rsp);
- if (rc) {
- ksmbd_debug(AUTH, "Could not generate md5 hash\n");
- goto out;
- }
- ksmbd_release_crypto_ctx(ctx);
- ctx = NULL;
-
- rc = ksmbd_gen_sess_key(sess, ntlmv2_hash, ntlmv2_rsp);
- if (rc) {
- ksmbd_debug(AUTH, "Could not generate sess key\n");
- goto out;
- }
-
- if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0)
- rc = -EINVAL;
-out:
- if (ctx)
- ksmbd_release_crypto_ctx(ctx);
- kfree(construct);
- return rc;
-}
-
-/**
- * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
- * authenticate blob
- * @authblob: authenticate blob source pointer
- * @usr: user details
- * @sess: session of connection
- *
- * Return: 0 on success, error number on error
- */
-int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
- int blob_len, struct ksmbd_conn *conn,
- struct ksmbd_session *sess)
-{
- char *domain_name;
- unsigned int nt_off, dn_off;
- unsigned short nt_len, dn_len;
- int ret;
-
- if (blob_len < sizeof(struct authenticate_message)) {
- ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
- blob_len);
- return -EINVAL;
- }
-
- if (memcmp(authblob->Signature, "NTLMSSP", 8)) {
- ksmbd_debug(AUTH, "blob signature incorrect %s\n",
- authblob->Signature);
- return -EINVAL;
- }
-
- nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset);
- nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length);
- dn_off = le32_to_cpu(authblob->DomainName.BufferOffset);
- dn_len = le16_to_cpu(authblob->DomainName.Length);
-
- if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len ||
- nt_len < CIFS_ENCPWD_SIZE)
- return -EINVAL;
-
- /* TODO : use domain name that imported from configuration file */
- domain_name = smb_strndup_from_utf16((const char *)authblob + dn_off,
- dn_len, true, conn->local_nls);
- if (IS_ERR(domain_name))
- return PTR_ERR(domain_name);
-
- /* process NTLMv2 authentication */
- ksmbd_debug(AUTH, "decode_ntlmssp_authenticate_blob dname%s\n",
- domain_name);
- ret = ksmbd_auth_ntlmv2(conn, sess,
- (struct ntlmv2_resp *)((char *)authblob + nt_off),
- nt_len - CIFS_ENCPWD_SIZE,
- domain_name, conn->ntlmssp.cryptkey);
- kfree(domain_name);
-
- /* The recovered secondary session key */
- if (conn->ntlmssp.client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) {
- struct arc4_ctx *ctx_arc4;
- unsigned int sess_key_off, sess_key_len;
-
- sess_key_off = le32_to_cpu(authblob->SessionKey.BufferOffset);
- sess_key_len = le16_to_cpu(authblob->SessionKey.Length);
-
- if (blob_len < (u64)sess_key_off + sess_key_len)
- return -EINVAL;
-
- ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
- if (!ctx_arc4)
- return -ENOMEM;
-
- cifs_arc4_setkey(ctx_arc4, sess->sess_key,
- SMB2_NTLMV2_SESSKEY_SIZE);
- cifs_arc4_crypt(ctx_arc4, sess->sess_key,
- (char *)authblob + sess_key_off, sess_key_len);
- kfree_sensitive(ctx_arc4);
- }
-
- return ret;
-}
-
-/**
- * ksmbd_decode_ntlmssp_neg_blob() - helper function to construct
- * negotiate blob
- * @negblob: negotiate blob source pointer
- * @rsp: response header pointer to be updated
- * @sess: session of connection
- *
- */
-int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
- int blob_len, struct ksmbd_conn *conn)
-{
- if (blob_len < sizeof(struct negotiate_message)) {
- ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
- blob_len);
- return -EINVAL;
- }
-
- if (memcmp(negblob->Signature, "NTLMSSP", 8)) {
- ksmbd_debug(AUTH, "blob signature incorrect %s\n",
- negblob->Signature);
- return -EINVAL;
- }
-
- conn->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags);
- return 0;
-}
-
-/**
- * ksmbd_build_ntlmssp_challenge_blob() - helper function to construct
- * challenge blob
- * @chgblob: challenge blob source pointer to initialize
- * @rsp: response header pointer to be updated
- * @sess: session of connection
- *
- */
-unsigned int
-ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
- struct ksmbd_conn *conn)
-{
- struct target_info *tinfo;
- wchar_t *name;
- __u8 *target_name;
- unsigned int flags, blob_off, blob_len, type, target_info_len = 0;
- int len, uni_len, conv_len;
- int cflags = conn->ntlmssp.client_flags;
-
- memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8);
- chgblob->MessageType = NtLmChallenge;
-
- flags = NTLMSSP_NEGOTIATE_UNICODE |
- NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_TARGET_TYPE_SERVER |
- NTLMSSP_NEGOTIATE_TARGET_INFO;
-
- if (cflags & NTLMSSP_NEGOTIATE_SIGN) {
- flags |= NTLMSSP_NEGOTIATE_SIGN;
- flags |= cflags & (NTLMSSP_NEGOTIATE_128 |
- NTLMSSP_NEGOTIATE_56);
- }
-
- if (cflags & NTLMSSP_NEGOTIATE_SEAL && smb3_encryption_negotiated(conn))
- flags |= NTLMSSP_NEGOTIATE_SEAL;
-
- if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
- flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
-
- if (cflags & NTLMSSP_REQUEST_TARGET)
- flags |= NTLMSSP_REQUEST_TARGET;
-
- if (conn->use_spnego &&
- (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
- flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
-
- if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH)
- flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
-
- chgblob->NegotiateFlags = cpu_to_le32(flags);
- len = strlen(ksmbd_netbios_name());
- name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
- if (!name)
- return -ENOMEM;
-
- conv_len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len,
- conn->local_nls);
- if (conv_len < 0 || conv_len > len) {
- kfree(name);
- return -EINVAL;
- }
-
- uni_len = UNICODE_LEN(conv_len);
-
- blob_off = sizeof(struct challenge_message);
- blob_len = blob_off + uni_len;
-
- chgblob->TargetName.Length = cpu_to_le16(uni_len);
- chgblob->TargetName.MaximumLength = cpu_to_le16(uni_len);
- chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off);
-
- /* Initialize random conn challenge */
- get_random_bytes(conn->ntlmssp.cryptkey, sizeof(__u64));
- memcpy(chgblob->Challenge, conn->ntlmssp.cryptkey,
- CIFS_CRYPTO_KEY_SIZE);
-
- /* Add Target Information to security buffer */
- chgblob->TargetInfoArray.BufferOffset = cpu_to_le32(blob_len);
-
- target_name = (__u8 *)chgblob + blob_off;
- memcpy(target_name, name, uni_len);
- tinfo = (struct target_info *)(target_name + uni_len);
-
- chgblob->TargetInfoArray.Length = 0;
- /* Add target info list for NetBIOS/DNS settings */
- for (type = NTLMSSP_AV_NB_COMPUTER_NAME;
- type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) {
- tinfo->Type = cpu_to_le16(type);
- tinfo->Length = cpu_to_le16(uni_len);
- memcpy(tinfo->Content, name, uni_len);
- tinfo = (struct target_info *)((char *)tinfo + 4 + uni_len);
- target_info_len += 4 + uni_len;
- }
-
- /* Add terminator subblock */
- tinfo->Type = 0;
- tinfo->Length = 0;
- target_info_len += 4;
-
- chgblob->TargetInfoArray.Length = cpu_to_le16(target_info_len);
- chgblob->TargetInfoArray.MaximumLength = cpu_to_le16(target_info_len);
- blob_len += target_info_len;
- kfree(name);
- ksmbd_debug(AUTH, "NTLMSSP SecurityBufferLength %d\n", blob_len);
- return blob_len;
-}
-
-#ifdef CONFIG_SMB_SERVER_KERBEROS5
-int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
- int in_len, char *out_blob, int *out_len)
-{
- struct ksmbd_spnego_authen_response *resp;
- struct ksmbd_user *user = NULL;
- int retval;
-
- resp = ksmbd_ipc_spnego_authen_request(in_blob, in_len);
- if (!resp) {
- ksmbd_debug(AUTH, "SPNEGO_AUTHEN_REQUEST failure\n");
- return -EINVAL;
- }
-
- if (!(resp->login_response.status & KSMBD_USER_FLAG_OK)) {
- ksmbd_debug(AUTH, "krb5 authentication failure\n");
- retval = -EPERM;
- goto out;
- }
-
- if (*out_len <= resp->spnego_blob_len) {
- ksmbd_debug(AUTH, "buf len %d, but blob len %d\n",
- *out_len, resp->spnego_blob_len);
- retval = -EINVAL;
- goto out;
- }
-
- if (resp->session_key_len > sizeof(sess->sess_key)) {
- ksmbd_debug(AUTH, "session key is too long\n");
- retval = -EINVAL;
- goto out;
- }
-
- user = ksmbd_alloc_user(&resp->login_response);
- if (!user) {
- ksmbd_debug(AUTH, "login failure\n");
- retval = -ENOMEM;
- goto out;
- }
- sess->user = user;
-
- memcpy(sess->sess_key, resp->payload, resp->session_key_len);
- memcpy(out_blob, resp->payload + resp->session_key_len,
- resp->spnego_blob_len);
- *out_len = resp->spnego_blob_len;
- retval = 0;
-out:
- kvfree(resp);
- return retval;
-}
-#else
-int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
- int in_len, char *out_blob, int *out_len)
-{
- return -EOPNOTSUPP;
-}
-#endif
-
-/**
- * ksmbd_sign_smb2_pdu() - function to generate packet signing
- * @conn: connection
- * @key: signing key
- * @iov: buffer iov array
- * @n_vec: number of iovecs
- * @sig: signature value generated for client request packet
- *
- */
-int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
- int n_vec, char *sig)
-{
- struct ksmbd_crypto_ctx *ctx;
- int rc, i;
-
- ctx = ksmbd_crypto_ctx_find_hmacsha256();
- if (!ctx) {
- ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
- return -ENOMEM;
- }
-
- rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
- key,
- SMB2_NTLMV2_SESSKEY_SIZE);
- if (rc)
- goto out;
-
- rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
- if (rc) {
- ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
- goto out;
- }
-
- for (i = 0; i < n_vec; i++) {
- rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
- iov[i].iov_base,
- iov[i].iov_len);
- if (rc) {
- ksmbd_debug(AUTH, "hmacsha256 update error %d\n", rc);
- goto out;
- }
- }
-
- rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), sig);
- if (rc)
- ksmbd_debug(AUTH, "hmacsha256 generation error %d\n", rc);
-out:
- ksmbd_release_crypto_ctx(ctx);
- return rc;
-}
-
-/**
- * ksmbd_sign_smb3_pdu() - function to generate packet signing
- * @conn: connection
- * @key: signing key
- * @iov: buffer iov array
- * @n_vec: number of iovecs
- * @sig: signature value generated for client request packet
- *
- */
-int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
- int n_vec, char *sig)
-{
- struct ksmbd_crypto_ctx *ctx;
- int rc, i;
-
- ctx = ksmbd_crypto_ctx_find_cmacaes();
- if (!ctx) {
- ksmbd_debug(AUTH, "could not crypto alloc cmac\n");
- return -ENOMEM;
- }
-
- rc = crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx),
- key,
- SMB2_CMACAES_SIZE);
- if (rc)
- goto out;
-
- rc = crypto_shash_init(CRYPTO_CMACAES(ctx));
- if (rc) {
- ksmbd_debug(AUTH, "cmaces init error %d\n", rc);
- goto out;
- }
-
- for (i = 0; i < n_vec; i++) {
- rc = crypto_shash_update(CRYPTO_CMACAES(ctx),
- iov[i].iov_base,
- iov[i].iov_len);
- if (rc) {
- ksmbd_debug(AUTH, "cmaces update error %d\n", rc);
- goto out;
- }
- }
-
- rc = crypto_shash_final(CRYPTO_CMACAES(ctx), sig);
- if (rc)
- ksmbd_debug(AUTH, "cmaces generation error %d\n", rc);
-out:
- ksmbd_release_crypto_ctx(ctx);
- return rc;
-}
-
-struct derivation {
- struct kvec label;
- struct kvec context;
- bool binding;
-};
-
-static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
- struct kvec label, struct kvec context, __u8 *key,
- unsigned int key_size)
-{
- unsigned char zero = 0x0;
- __u8 i[4] = {0, 0, 0, 1};
- __u8 L128[4] = {0, 0, 0, 128};
- __u8 L256[4] = {0, 0, 1, 0};
- int rc;
- unsigned char prfhash[SMB2_HMACSHA256_SIZE];
- unsigned char *hashptr = prfhash;
- struct ksmbd_crypto_ctx *ctx;
-
- memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
- memset(key, 0x0, key_size);
-
- ctx = ksmbd_crypto_ctx_find_hmacsha256();
- if (!ctx) {
- ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
- return -ENOMEM;
- }
-
- rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
- sess->sess_key,
- SMB2_NTLMV2_SESSKEY_SIZE);
- if (rc)
- goto smb3signkey_ret;
-
- rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
- if (rc) {
- ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), i, 4);
- if (rc) {
- ksmbd_debug(AUTH, "could not update with n\n");
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
- label.iov_base,
- label.iov_len);
- if (rc) {
- ksmbd_debug(AUTH, "could not update with label\n");
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), &zero, 1);
- if (rc) {
- ksmbd_debug(AUTH, "could not update with zero\n");
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
- context.iov_base,
- context.iov_len);
- if (rc) {
- ksmbd_debug(AUTH, "could not update with context\n");
- goto smb3signkey_ret;
- }
-
- if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
- (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
- rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
- else
- rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
- if (rc) {
- ksmbd_debug(AUTH, "could not update with L\n");
- goto smb3signkey_ret;
- }
-
- rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), hashptr);
- if (rc) {
- ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n",
- rc);
- goto smb3signkey_ret;
- }
-
- memcpy(key, hashptr, key_size);
-
-smb3signkey_ret:
- ksmbd_release_crypto_ctx(ctx);
- return rc;
-}
-
-static int generate_smb3signingkey(struct ksmbd_session *sess,
- struct ksmbd_conn *conn,
- const struct derivation *signing)
-{
- int rc;
- struct channel *chann;
- char *key;
-
- chann = lookup_chann_list(sess, conn);
- if (!chann)
- return 0;
-
- if (conn->dialect >= SMB30_PROT_ID && signing->binding)
- key = chann->smb3signingkey;
- else
- key = sess->smb3signingkey;
-
- rc = generate_key(conn, sess, signing->label, signing->context, key,
- SMB3_SIGN_KEY_SIZE);
- if (rc)
- return rc;
-
- if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
- memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
-
- ksmbd_debug(AUTH, "dumping generated AES signing keys\n");
- ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
- ksmbd_debug(AUTH, "Session Key %*ph\n",
- SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
- ksmbd_debug(AUTH, "Signing Key %*ph\n",
- SMB3_SIGN_KEY_SIZE, key);
- return 0;
-}
-
-int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
- struct ksmbd_conn *conn)
-{
- struct derivation d;
-
- d.label.iov_base = "SMB2AESCMAC";
- d.label.iov_len = 12;
- d.context.iov_base = "SmbSign";
- d.context.iov_len = 8;
- d.binding = conn->binding;
-
- return generate_smb3signingkey(sess, conn, &d);
-}
-
-int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
- struct ksmbd_conn *conn)
-{
- struct derivation d;
-
- d.label.iov_base = "SMBSigningKey";
- d.label.iov_len = 14;
- if (conn->binding) {
- struct preauth_session *preauth_sess;
-
- preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
- if (!preauth_sess)
- return -ENOENT;
- d.context.iov_base = preauth_sess->Preauth_HashValue;
- } else {
- d.context.iov_base = sess->Preauth_HashValue;
- }
- d.context.iov_len = 64;
- d.binding = conn->binding;
-
- return generate_smb3signingkey(sess, conn, &d);
-}
-
-struct derivation_twin {
- struct derivation encryption;
- struct derivation decryption;
-};
-
-static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
- struct ksmbd_session *sess,
- const struct derivation_twin *ptwin)
-{
- int rc;
-
- rc = generate_key(conn, sess, ptwin->encryption.label,
- ptwin->encryption.context, sess->smb3encryptionkey,
- SMB3_ENC_DEC_KEY_SIZE);
- if (rc)
- return rc;
-
- rc = generate_key(conn, sess, ptwin->decryption.label,
- ptwin->decryption.context,
- sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
- if (rc)
- return rc;
-
- ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
- ksmbd_debug(AUTH, "Cipher type %d\n", conn->cipher_type);
- ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
- ksmbd_debug(AUTH, "Session Key %*ph\n",
- SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
- if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
- ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
- SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey);
- ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
- SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3decryptionkey);
- } else {
- ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
- SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3encryptionkey);
- ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
- SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
- }
- return 0;
-}
-
-int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
- struct ksmbd_session *sess)
-{
- struct derivation_twin twin;
- struct derivation *d;
-
- d = &twin.encryption;
- d->label.iov_base = "SMB2AESCCM";
- d->label.iov_len = 11;
- d->context.iov_base = "ServerOut";
- d->context.iov_len = 10;
-
- d = &twin.decryption;
- d->label.iov_base = "SMB2AESCCM";
- d->label.iov_len = 11;
- d->context.iov_base = "ServerIn ";
- d->context.iov_len = 10;
-
- return generate_smb3encryptionkey(conn, sess, &twin);
-}
-
-int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
- struct ksmbd_session *sess)
-{
- struct derivation_twin twin;
- struct derivation *d;
-
- d = &twin.encryption;
- d->label.iov_base = "SMBS2CCipherKey";
- d->label.iov_len = 16;
- d->context.iov_base = sess->Preauth_HashValue;
- d->context.iov_len = 64;
-
- d = &twin.decryption;
- d->label.iov_base = "SMBC2SCipherKey";
- d->label.iov_len = 16;
- d->context.iov_base = sess->Preauth_HashValue;
- d->context.iov_len = 64;
-
- return generate_smb3encryptionkey(conn, sess, &twin);
-}
-
-int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
- __u8 *pi_hash)
-{
- int rc;
- struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
- char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
- int msg_size = get_rfc1002_len(buf);
- struct ksmbd_crypto_ctx *ctx = NULL;
-
- if (conn->preauth_info->Preauth_HashId !=
- SMB2_PREAUTH_INTEGRITY_SHA512)
- return -EINVAL;
-
- ctx = ksmbd_crypto_ctx_find_sha512();
- if (!ctx) {
- ksmbd_debug(AUTH, "could not alloc sha512\n");
- return -ENOMEM;
- }
-
- rc = crypto_shash_init(CRYPTO_SHA512(ctx));
- if (rc) {
- ksmbd_debug(AUTH, "could not init shashn");
- goto out;
- }
-
- rc = crypto_shash_update(CRYPTO_SHA512(ctx), pi_hash, 64);
- if (rc) {
- ksmbd_debug(AUTH, "could not update with n\n");
- goto out;
- }
-
- rc = crypto_shash_update(CRYPTO_SHA512(ctx), all_bytes_msg, msg_size);
- if (rc) {
- ksmbd_debug(AUTH, "could not update with n\n");
- goto out;
- }
-
- rc = crypto_shash_final(CRYPTO_SHA512(ctx), pi_hash);
- if (rc) {
- ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
- goto out;
- }
-out:
- ksmbd_release_crypto_ctx(ctx);
- return rc;
-}
-
-int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
- __u8 *pi_hash)
-{
- int rc;
- struct ksmbd_crypto_ctx *ctx = NULL;
-
- ctx = ksmbd_crypto_ctx_find_sha256();
- if (!ctx) {
- ksmbd_debug(AUTH, "could not alloc sha256\n");
- return -ENOMEM;
- }
-
- rc = crypto_shash_init(CRYPTO_SHA256(ctx));
- if (rc) {
- ksmbd_debug(AUTH, "could not init shashn");
- goto out;
- }
-
- rc = crypto_shash_update(CRYPTO_SHA256(ctx), sd_buf, len);
- if (rc) {
- ksmbd_debug(AUTH, "could not update with n\n");
- goto out;
- }
-
- rc = crypto_shash_final(CRYPTO_SHA256(ctx), pi_hash);
- if (rc) {
- ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
- goto out;
- }
-out:
- ksmbd_release_crypto_ctx(ctx);
- return rc;
-}
-
-static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
- int enc, u8 *key)
-{
- struct ksmbd_session *sess;
- u8 *ses_enc_key;
-
- if (enc)
- sess = work->sess;
- else
- sess = ksmbd_session_lookup_all(work->conn, ses_id);
- if (!sess)
- return -EINVAL;
-
- ses_enc_key = enc ? sess->smb3encryptionkey :
- sess->smb3decryptionkey;
- memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
-
- return 0;
-}
-
-static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
- unsigned int buflen)
-{
- void *addr;
-
- if (is_vmalloc_addr(buf))
- addr = vmalloc_to_page(buf);
- else
- addr = virt_to_page(buf);
- sg_set_page(sg, addr, buflen, offset_in_page(buf));
-}
-
-static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
- u8 *sign)
-{
- struct scatterlist *sg;
- unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
- int i, nr_entries[3] = {0}, total_entries = 0, sg_idx = 0;
-
- if (!nvec)
- return NULL;
-
- for (i = 0; i < nvec - 1; i++) {
- unsigned long kaddr = (unsigned long)iov[i + 1].iov_base;
-
- if (is_vmalloc_addr(iov[i + 1].iov_base)) {
- nr_entries[i] = ((kaddr + iov[i + 1].iov_len +
- PAGE_SIZE - 1) >> PAGE_SHIFT) -
- (kaddr >> PAGE_SHIFT);
- } else {
- nr_entries[i]++;
- }
- total_entries += nr_entries[i];
- }
-
- /* Add two entries for transform header and signature */
- total_entries += 2;
-
- sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL);
- if (!sg)
- return NULL;
-
- sg_init_table(sg, total_entries);
- smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len);
- for (i = 0; i < nvec - 1; i++) {
- void *data = iov[i + 1].iov_base;
- int len = iov[i + 1].iov_len;
-
- if (is_vmalloc_addr(data)) {
- int j, offset = offset_in_page(data);
-
- for (j = 0; j < nr_entries[i]; j++) {
- unsigned int bytes = PAGE_SIZE - offset;
-
- if (!len)
- break;
-
- if (bytes > len)
- bytes = len;
-
- sg_set_page(&sg[sg_idx++],
- vmalloc_to_page(data), bytes,
- offset_in_page(data));
-
- data += bytes;
- len -= bytes;
- offset = 0;
- }
- } else {
- sg_set_page(&sg[sg_idx++], virt_to_page(data), len,
- offset_in_page(data));
- }
- }
- smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
- return sg;
-}
-
-int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
- unsigned int nvec, int enc)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
- unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
- int rc;
- struct scatterlist *sg;
- u8 sign[SMB2_SIGNATURE_SIZE] = {};
- u8 key[SMB3_ENC_DEC_KEY_SIZE];
- struct aead_request *req;
- char *iv;
- unsigned int iv_len;
- struct crypto_aead *tfm;
- unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
- struct ksmbd_crypto_ctx *ctx;
-
- rc = ksmbd_get_encryption_key(work,
- le64_to_cpu(tr_hdr->SessionId),
- enc,
- key);
- if (rc) {
- pr_err("Could not get %scryption key\n", enc ? "en" : "de");
- return rc;
- }
-
- if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
- ctx = ksmbd_crypto_ctx_find_gcm();
- else
- ctx = ksmbd_crypto_ctx_find_ccm();
- if (!ctx) {
- pr_err("crypto alloc failed\n");
- return -ENOMEM;
- }
-
- if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
- tfm = CRYPTO_GCM(ctx);
- else
- tfm = CRYPTO_CCM(ctx);
-
- if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
- rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
- else
- rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
- if (rc) {
- pr_err("Failed to set aead key %d\n", rc);
- goto free_ctx;
- }
-
- rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
- if (rc) {
- pr_err("Failed to set authsize %d\n", rc);
- goto free_ctx;
- }
-
- req = aead_request_alloc(tfm, GFP_KERNEL);
- if (!req) {
- rc = -ENOMEM;
- goto free_ctx;
- }
-
- if (!enc) {
- memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
- crypt_len += SMB2_SIGNATURE_SIZE;
- }
-
- sg = ksmbd_init_sg(iov, nvec, sign);
- if (!sg) {
- pr_err("Failed to init sg\n");
- rc = -ENOMEM;
- goto free_req;
- }
-
- iv_len = crypto_aead_ivsize(tfm);
- iv = kzalloc(iv_len, GFP_KERNEL);
- if (!iv) {
- rc = -ENOMEM;
- goto free_sg;
- }
-
- if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
- conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
- memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
- } else {
- iv[0] = 3;
- memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
- }
-
- aead_request_set_crypt(req, sg, sg, crypt_len, iv);
- aead_request_set_ad(req, assoc_data_len);
- aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
-
- if (enc)
- rc = crypto_aead_encrypt(req);
- else
- rc = crypto_aead_decrypt(req);
- if (rc)
- goto free_iv;
-
- if (enc)
- memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
-
-free_iv:
- kfree(iv);
-free_sg:
- kfree(sg);
-free_req:
- kfree(req);
-free_ctx:
- ksmbd_release_crypto_ctx(ctx);
- return rc;
-}
diff --git a/fs/ksmbd/auth.h b/fs/ksmbd/auth.h
deleted file mode 100644
index 362b6159a6cf..000000000000
--- a/fs/ksmbd/auth.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __AUTH_H__
-#define __AUTH_H__
-
-#include "ntlmssp.h"
-
-#ifdef CONFIG_SMB_SERVER_KERBEROS5
-#define AUTH_GSS_LENGTH 96
-#define AUTH_GSS_PADDING 0
-#else
-#define AUTH_GSS_LENGTH 74
-#define AUTH_GSS_PADDING 6
-#endif
-
-#define CIFS_HMAC_MD5_HASH_SIZE (16)
-#define CIFS_NTHASH_SIZE (16)
-
-/*
- * Size of the ntlm client response
- */
-#define CIFS_AUTH_RESP_SIZE 24
-#define CIFS_SMB1_SIGNATURE_SIZE 8
-#define CIFS_SMB1_SESSKEY_SIZE 16
-
-#define KSMBD_AUTH_NTLMSSP 0x0001
-#define KSMBD_AUTH_KRB5 0x0002
-#define KSMBD_AUTH_MSKRB5 0x0004
-#define KSMBD_AUTH_KRB5U2U 0x0008
-
-struct ksmbd_session;
-struct ksmbd_conn;
-struct ksmbd_work;
-struct kvec;
-
-int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
- unsigned int nvec, int enc);
-void ksmbd_copy_gss_neg_header(void *buf);
-int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
- struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
- char *cryptkey);
-int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
- int blob_len, struct ksmbd_conn *conn,
- struct ksmbd_session *sess);
-int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
- int blob_len, struct ksmbd_conn *conn);
-unsigned int
-ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
- struct ksmbd_conn *conn);
-int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
- int in_len, char *out_blob, int *out_len);
-int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
- int n_vec, char *sig);
-int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
- int n_vec, char *sig);
-int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
- struct ksmbd_conn *conn);
-int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
- struct ksmbd_conn *conn);
-int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
- struct ksmbd_session *sess);
-int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
- struct ksmbd_session *sess);
-int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
- __u8 *pi_hash);
-int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
- __u8 *pi_hash);
-#endif
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
deleted file mode 100644
index e1d2be19cddf..000000000000
--- a/fs/ksmbd/connection.c
+++ /dev/null
@@ -1,485 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <namjae.jeon@protocolfreedom.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/mutex.h>
-#include <linux/freezer.h>
-#include <linux/module.h>
-
-#include "server.h"
-#include "smb_common.h"
-#include "mgmt/ksmbd_ida.h"
-#include "connection.h"
-#include "transport_tcp.h"
-#include "transport_rdma.h"
-
-static DEFINE_MUTEX(init_lock);
-
-static struct ksmbd_conn_ops default_conn_ops;
-
-LIST_HEAD(conn_list);
-DECLARE_RWSEM(conn_list_lock);
-
-/**
- * ksmbd_conn_free() - free resources of the connection instance
- *
- * @conn: connection instance to be cleand up
- *
- * During the thread termination, the corresponding conn instance
- * resources(sock/memory) are released and finally the conn object is freed.
- */
-void ksmbd_conn_free(struct ksmbd_conn *conn)
-{
- down_write(&conn_list_lock);
- list_del(&conn->conns_list);
- up_write(&conn_list_lock);
-
- xa_destroy(&conn->sessions);
- kvfree(conn->request_buf);
- kfree(conn->preauth_info);
- kfree(conn);
-}
-
-/**
- * ksmbd_conn_alloc() - initialize a new connection instance
- *
- * Return: ksmbd_conn struct on success, otherwise NULL
- */
-struct ksmbd_conn *ksmbd_conn_alloc(void)
-{
- struct ksmbd_conn *conn;
-
- conn = kzalloc(sizeof(struct ksmbd_conn), GFP_KERNEL);
- if (!conn)
- return NULL;
-
- conn->need_neg = true;
- ksmbd_conn_set_new(conn);
- conn->local_nls = load_nls("utf8");
- if (!conn->local_nls)
- conn->local_nls = load_nls_default();
- if (IS_ENABLED(CONFIG_UNICODE))
- conn->um = utf8_load(UNICODE_AGE(12, 1, 0));
- else
- conn->um = ERR_PTR(-EOPNOTSUPP);
- if (IS_ERR(conn->um))
- conn->um = NULL;
- atomic_set(&conn->req_running, 0);
- atomic_set(&conn->r_count, 0);
- conn->total_credits = 1;
- conn->outstanding_credits = 0;
-
- init_waitqueue_head(&conn->req_running_q);
- init_waitqueue_head(&conn->r_count_q);
- INIT_LIST_HEAD(&conn->conns_list);
- INIT_LIST_HEAD(&conn->requests);
- INIT_LIST_HEAD(&conn->async_requests);
- spin_lock_init(&conn->request_lock);
- spin_lock_init(&conn->credits_lock);
- ida_init(&conn->async_ida);
- xa_init(&conn->sessions);
-
- spin_lock_init(&conn->llist_lock);
- INIT_LIST_HEAD(&conn->lock_list);
-
- down_write(&conn_list_lock);
- list_add(&conn->conns_list, &conn_list);
- up_write(&conn_list_lock);
- return conn;
-}
-
-bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)
-{
- struct ksmbd_conn *t;
- bool ret = false;
-
- down_read(&conn_list_lock);
- list_for_each_entry(t, &conn_list, conns_list) {
- if (memcmp(t->ClientGUID, c->ClientGUID, SMB2_CLIENT_GUID_SIZE))
- continue;
-
- ret = true;
- break;
- }
- up_read(&conn_list_lock);
- return ret;
-}
-
-void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct list_head *requests_queue = NULL;
-
- if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
- requests_queue = &conn->requests;
- work->syncronous = true;
- }
-
- if (requests_queue) {
- atomic_inc(&conn->req_running);
- spin_lock(&conn->request_lock);
- list_add_tail(&work->request_entry, requests_queue);
- spin_unlock(&conn->request_lock);
- }
-}
-
-int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- int ret = 1;
-
- if (list_empty(&work->request_entry) &&
- list_empty(&work->async_request_entry))
- return 0;
-
- if (!work->multiRsp)
- atomic_dec(&conn->req_running);
- spin_lock(&conn->request_lock);
- if (!work->multiRsp) {
- list_del_init(&work->request_entry);
- if (work->syncronous == false)
- list_del_init(&work->async_request_entry);
- ret = 0;
- }
- spin_unlock(&conn->request_lock);
-
- wake_up_all(&conn->req_running_q);
- return ret;
-}
-
-void ksmbd_conn_lock(struct ksmbd_conn *conn)
-{
- mutex_lock(&conn->srv_mutex);
-}
-
-void ksmbd_conn_unlock(struct ksmbd_conn *conn)
-{
- mutex_unlock(&conn->srv_mutex);
-}
-
-void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
-{
- struct ksmbd_conn *conn;
-
- down_read(&conn_list_lock);
- list_for_each_entry(conn, &conn_list, conns_list) {
- if (conn->binding || xa_load(&conn->sessions, sess_id))
- WRITE_ONCE(conn->status, status);
- }
- up_read(&conn_list_lock);
-}
-
-void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
-{
- struct ksmbd_conn *bind_conn;
-
- wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
-
- down_read(&conn_list_lock);
- list_for_each_entry(bind_conn, &conn_list, conns_list) {
- if (bind_conn == conn)
- continue;
-
- if ((bind_conn->binding || xa_load(&bind_conn->sessions, sess_id)) &&
- !ksmbd_conn_releasing(bind_conn) &&
- atomic_read(&bind_conn->req_running)) {
- wait_event(bind_conn->req_running_q,
- atomic_read(&bind_conn->req_running) == 0);
- }
- }
- up_read(&conn_list_lock);
-}
-
-int ksmbd_conn_write(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- size_t len = 0;
- int sent;
- struct kvec iov[3];
- int iov_idx = 0;
-
- if (!work->response_buf) {
- pr_err("NULL response header\n");
- return -EINVAL;
- }
-
- if (work->tr_buf) {
- iov[iov_idx] = (struct kvec) { work->tr_buf,
- sizeof(struct smb2_transform_hdr) + 4 };
- len += iov[iov_idx++].iov_len;
- }
-
- if (work->aux_payload_sz) {
- iov[iov_idx] = (struct kvec) { work->response_buf, work->resp_hdr_sz };
- len += iov[iov_idx++].iov_len;
- iov[iov_idx] = (struct kvec) { work->aux_payload_buf, work->aux_payload_sz };
- len += iov[iov_idx++].iov_len;
- } else {
- if (work->tr_buf)
- iov[iov_idx].iov_len = work->resp_hdr_sz;
- else
- iov[iov_idx].iov_len = get_rfc1002_len(work->response_buf) + 4;
- iov[iov_idx].iov_base = work->response_buf;
- len += iov[iov_idx++].iov_len;
- }
-
- ksmbd_conn_lock(conn);
- sent = conn->transport->ops->writev(conn->transport, &iov[0],
- iov_idx, len,
- work->need_invalidate_rkey,
- work->remote_key);
- ksmbd_conn_unlock(conn);
-
- if (sent < 0) {
- pr_err("Failed to send message: %d\n", sent);
- return sent;
- }
-
- return 0;
-}
-
-int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
- void *buf, unsigned int buflen,
- struct smb2_buffer_desc_v1 *desc,
- unsigned int desc_len)
-{
- int ret = -EINVAL;
-
- if (conn->transport->ops->rdma_read)
- ret = conn->transport->ops->rdma_read(conn->transport,
- buf, buflen,
- desc, desc_len);
- return ret;
-}
-
-int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
- void *buf, unsigned int buflen,
- struct smb2_buffer_desc_v1 *desc,
- unsigned int desc_len)
-{
- int ret = -EINVAL;
-
- if (conn->transport->ops->rdma_write)
- ret = conn->transport->ops->rdma_write(conn->transport,
- buf, buflen,
- desc, desc_len);
- return ret;
-}
-
-bool ksmbd_conn_alive(struct ksmbd_conn *conn)
-{
- if (!ksmbd_server_running())
- return false;
-
- if (ksmbd_conn_exiting(conn))
- return false;
-
- if (kthread_should_stop())
- return false;
-
- if (atomic_read(&conn->stats.open_files_count) > 0)
- return true;
-
- /*
- * Stop current session if the time that get last request from client
- * is bigger than deadtime user configured and opening file count is
- * zero.
- */
- if (server_conf.deadtime > 0 &&
- time_after(jiffies, conn->last_active + server_conf.deadtime)) {
- ksmbd_debug(CONN, "No response from client in %lu minutes\n",
- server_conf.deadtime / SMB_ECHO_INTERVAL);
- return false;
- }
- return true;
-}
-
-#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr))
-#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)
-
-/**
- * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
- * @p: connection instance
- *
- * One thread each per connection
- *
- * Return: 0 on success
- */
-int ksmbd_conn_handler_loop(void *p)
-{
- struct ksmbd_conn *conn = (struct ksmbd_conn *)p;
- struct ksmbd_transport *t = conn->transport;
- unsigned int pdu_size, max_allowed_pdu_size;
- char hdr_buf[4] = {0,};
- int size;
-
- mutex_init(&conn->srv_mutex);
- __module_get(THIS_MODULE);
-
- if (t->ops->prepare && t->ops->prepare(t))
- goto out;
-
- conn->last_active = jiffies;
- while (ksmbd_conn_alive(conn)) {
- if (try_to_freeze())
- continue;
-
- kvfree(conn->request_buf);
- conn->request_buf = NULL;
-
- size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
- if (size != sizeof(hdr_buf))
- break;
-
- pdu_size = get_rfc1002_len(hdr_buf);
- ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);
-
- if (ksmbd_conn_good(conn))
- max_allowed_pdu_size =
- SMB3_MAX_MSGSIZE + conn->vals->max_write_size;
- else
- max_allowed_pdu_size = SMB3_MAX_MSGSIZE;
-
- if (pdu_size > max_allowed_pdu_size) {
- pr_err_ratelimited("PDU length(%u) excceed maximum allowed pdu size(%u) on connection(%d)\n",
- pdu_size, max_allowed_pdu_size,
- READ_ONCE(conn->status));
- break;
- }
-
- /*
- * Check maximum pdu size(0x00FFFFFF).
- */
- if (pdu_size > MAX_STREAM_PROT_LEN)
- break;
-
- if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE)
- break;
-
- /* 4 for rfc1002 length field */
- /* 1 for implied bcc[0] */
- size = pdu_size + 4 + 1;
- conn->request_buf = kvmalloc(size, GFP_KERNEL);
- if (!conn->request_buf)
- break;
-
- memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));
-
- /*
- * We already read 4 bytes to find out PDU size, now
- * read in PDU
- */
- size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);
- if (size < 0) {
- pr_err("sock_read failed: %d\n", size);
- break;
- }
-
- if (size != pdu_size) {
- pr_err("PDU error. Read: %d, Expected: %d\n",
- size, pdu_size);
- continue;
- }
-
- if (!ksmbd_smb_request(conn))
- break;
-
- if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
- SMB2_PROTO_NUMBER) {
- if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
- break;
- }
-
- if (!default_conn_ops.process_fn) {
- pr_err("No connection request callback\n");
- break;
- }
-
- if (default_conn_ops.process_fn(conn)) {
- pr_err("Cannot handle request\n");
- break;
- }
- }
-
-out:
- ksmbd_conn_set_releasing(conn);
- /* Wait till all reference dropped to the Server object*/
- wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
-
- if (IS_ENABLED(CONFIG_UNICODE))
- utf8_unload(conn->um);
- unload_nls(conn->local_nls);
- if (default_conn_ops.terminate_fn)
- default_conn_ops.terminate_fn(conn);
- t->ops->disconnect(t);
- module_put(THIS_MODULE);
- return 0;
-}
-
-void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops)
-{
- default_conn_ops.process_fn = ops->process_fn;
- default_conn_ops.terminate_fn = ops->terminate_fn;
-}
-
-int ksmbd_conn_transport_init(void)
-{
- int ret;
-
- mutex_lock(&init_lock);
- ret = ksmbd_tcp_init();
- if (ret) {
- pr_err("Failed to init TCP subsystem: %d\n", ret);
- goto out;
- }
-
- ret = ksmbd_rdma_init();
- if (ret) {
- pr_err("Failed to init RDMA subsystem: %d\n", ret);
- goto out;
- }
-out:
- mutex_unlock(&init_lock);
- return ret;
-}
-
-static void stop_sessions(void)
-{
- struct ksmbd_conn *conn;
- struct ksmbd_transport *t;
-
-again:
- down_read(&conn_list_lock);
- list_for_each_entry(conn, &conn_list, conns_list) {
- struct task_struct *task;
-
- t = conn->transport;
- task = t->handler;
- if (task)
- ksmbd_debug(CONN, "Stop session handler %s/%d\n",
- task->comm, task_pid_nr(task));
- ksmbd_conn_set_exiting(conn);
- if (t->ops->shutdown) {
- up_read(&conn_list_lock);
- t->ops->shutdown(t);
- down_read(&conn_list_lock);
- }
- }
- up_read(&conn_list_lock);
-
- if (!list_empty(&conn_list)) {
- schedule_timeout_interruptible(HZ / 10); /* 100ms */
- goto again;
- }
-}
-
-void ksmbd_conn_transport_destroy(void)
-{
- mutex_lock(&init_lock);
- ksmbd_tcp_destroy();
- ksmbd_rdma_destroy();
- stop_sessions();
- mutex_unlock(&init_lock);
-}
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
deleted file mode 100644
index ad8dfaa48ffb..000000000000
--- a/fs/ksmbd/connection.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_CONNECTION_H__
-#define __KSMBD_CONNECTION_H__
-
-#include <linux/list.h>
-#include <linux/ip.h>
-#include <net/sock.h>
-#include <net/tcp.h>
-#include <net/inet_connection_sock.h>
-#include <net/request_sock.h>
-#include <linux/kthread.h>
-#include <linux/nls.h>
-#include <linux/unicode.h>
-
-#include "smb_common.h"
-#include "ksmbd_work.h"
-
-#define KSMBD_SOCKET_BACKLOG 16
-
-enum {
- KSMBD_SESS_NEW = 0,
- KSMBD_SESS_GOOD,
- KSMBD_SESS_EXITING,
- KSMBD_SESS_NEED_RECONNECT,
- KSMBD_SESS_NEED_NEGOTIATE,
- KSMBD_SESS_RELEASING
-};
-
-struct ksmbd_stats {
- atomic_t open_files_count;
- atomic64_t request_served;
-};
-
-struct ksmbd_transport;
-
-struct ksmbd_conn {
- struct smb_version_values *vals;
- struct smb_version_ops *ops;
- struct smb_version_cmds *cmds;
- unsigned int max_cmds;
- struct mutex srv_mutex;
- int status;
- unsigned int cli_cap;
- char *request_buf;
- struct ksmbd_transport *transport;
- struct nls_table *local_nls;
- struct unicode_map *um;
- struct list_head conns_list;
- /* smb session 1 per user */
- struct xarray sessions;
- unsigned long last_active;
- /* How many request are running currently */
- atomic_t req_running;
- /* References which are made for this Server object*/
- atomic_t r_count;
- unsigned int total_credits;
- unsigned int outstanding_credits;
- spinlock_t credits_lock;
- wait_queue_head_t req_running_q;
- wait_queue_head_t r_count_q;
- /* Lock to protect requests list*/
- spinlock_t request_lock;
- struct list_head requests;
- struct list_head async_requests;
- int connection_type;
- struct ksmbd_stats stats;
- char ClientGUID[SMB2_CLIENT_GUID_SIZE];
- struct ntlmssp_auth ntlmssp;
-
- spinlock_t llist_lock;
- struct list_head lock_list;
-
- struct preauth_integrity_info *preauth_info;
-
- bool need_neg;
- unsigned int auth_mechs;
- unsigned int preferred_auth_mech;
- bool sign;
- bool use_spnego:1;
- __u16 cli_sec_mode;
- __u16 srv_sec_mode;
- /* dialect index that server chose */
- __u16 dialect;
-
- char *mechToken;
-
- struct ksmbd_conn_ops *conn_ops;
-
- /* Preauth Session Table */
- struct list_head preauth_sess_table;
-
- struct sockaddr_storage peer_addr;
-
- /* Identifier for async message */
- struct ida async_ida;
-
- __le16 cipher_type;
- __le16 compress_algorithm;
- bool posix_ext_supported;
- bool signing_negotiated;
- __le16 signing_algorithm;
- bool binding;
-};
-
-struct ksmbd_conn_ops {
- int (*process_fn)(struct ksmbd_conn *conn);
- int (*terminate_fn)(struct ksmbd_conn *conn);
-};
-
-struct ksmbd_transport_ops {
- int (*prepare)(struct ksmbd_transport *t);
- void (*disconnect)(struct ksmbd_transport *t);
- void (*shutdown)(struct ksmbd_transport *t);
- int (*read)(struct ksmbd_transport *t, char *buf,
- unsigned int size, int max_retries);
- int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
- int size, bool need_invalidate_rkey,
- unsigned int remote_key);
- int (*rdma_read)(struct ksmbd_transport *t,
- void *buf, unsigned int len,
- struct smb2_buffer_desc_v1 *desc,
- unsigned int desc_len);
- int (*rdma_write)(struct ksmbd_transport *t,
- void *buf, unsigned int len,
- struct smb2_buffer_desc_v1 *desc,
- unsigned int desc_len);
-};
-
-struct ksmbd_transport {
- struct ksmbd_conn *conn;
- struct ksmbd_transport_ops *ops;
- struct task_struct *handler;
-};
-
-#define KSMBD_TCP_RECV_TIMEOUT (7 * HZ)
-#define KSMBD_TCP_SEND_TIMEOUT (5 * HZ)
-#define KSMBD_TCP_PEER_SOCKADDR(c) ((struct sockaddr *)&((c)->peer_addr))
-
-extern struct list_head conn_list;
-extern struct rw_semaphore conn_list_lock;
-
-bool ksmbd_conn_alive(struct ksmbd_conn *conn);
-void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id);
-struct ksmbd_conn *ksmbd_conn_alloc(void);
-void ksmbd_conn_free(struct ksmbd_conn *conn);
-bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
-int ksmbd_conn_write(struct ksmbd_work *work);
-int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
- void *buf, unsigned int buflen,
- struct smb2_buffer_desc_v1 *desc,
- unsigned int desc_len);
-int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
- void *buf, unsigned int buflen,
- struct smb2_buffer_desc_v1 *desc,
- unsigned int desc_len);
-void ksmbd_conn_enqueue_request(struct ksmbd_work *work);
-int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
-void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);
-int ksmbd_conn_handler_loop(void *p);
-int ksmbd_conn_transport_init(void);
-void ksmbd_conn_transport_destroy(void);
-void ksmbd_conn_lock(struct ksmbd_conn *conn);
-void ksmbd_conn_unlock(struct ksmbd_conn *conn);
-
-/*
- * WARNING
- *
- * This is a hack. We will move status to a proper place once we land
- * a multi-sessions support.
- */
-static inline bool ksmbd_conn_good(struct ksmbd_conn *conn)
-{
- return READ_ONCE(conn->status) == KSMBD_SESS_GOOD;
-}
-
-static inline bool ksmbd_conn_need_negotiate(struct ksmbd_conn *conn)
-{
- return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE;
-}
-
-static inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn)
-{
- return READ_ONCE(conn->status) == KSMBD_SESS_NEED_RECONNECT;
-}
-
-static inline bool ksmbd_conn_exiting(struct ksmbd_conn *conn)
-{
- return READ_ONCE(conn->status) == KSMBD_SESS_EXITING;
-}
-
-static inline bool ksmbd_conn_releasing(struct ksmbd_conn *conn)
-{
- return READ_ONCE(conn->status) == KSMBD_SESS_RELEASING;
-}
-
-static inline void ksmbd_conn_set_new(struct ksmbd_conn *conn)
-{
- WRITE_ONCE(conn->status, KSMBD_SESS_NEW);
-}
-
-static inline void ksmbd_conn_set_good(struct ksmbd_conn *conn)
-{
- WRITE_ONCE(conn->status, KSMBD_SESS_GOOD);
-}
-
-static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_conn *conn)
-{
- WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE);
-}
-
-static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn)
-{
- WRITE_ONCE(conn->status, KSMBD_SESS_NEED_RECONNECT);
-}
-
-static inline void ksmbd_conn_set_exiting(struct ksmbd_conn *conn)
-{
- WRITE_ONCE(conn->status, KSMBD_SESS_EXITING);
-}
-
-static inline void ksmbd_conn_set_releasing(struct ksmbd_conn *conn)
-{
- WRITE_ONCE(conn->status, KSMBD_SESS_RELEASING);
-}
-
-void ksmbd_all_conn_set_status(u64 sess_id, u32 status);
-#endif /* __CONNECTION_H__ */
diff --git a/fs/ksmbd/crypto_ctx.c b/fs/ksmbd/crypto_ctx.c
deleted file mode 100644
index 81488d04199d..000000000000
--- a/fs/ksmbd/crypto_ctx.c
+++ /dev/null
@@ -1,266 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2019 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-
-#include "glob.h"
-#include "crypto_ctx.h"
-
-struct crypto_ctx_list {
- spinlock_t ctx_lock;
- int avail_ctx;
- struct list_head idle_ctx;
- wait_queue_head_t ctx_wait;
-};
-
-static struct crypto_ctx_list ctx_list;
-
-static inline void free_aead(struct crypto_aead *aead)
-{
- if (aead)
- crypto_free_aead(aead);
-}
-
-static void free_shash(struct shash_desc *shash)
-{
- if (shash) {
- crypto_free_shash(shash->tfm);
- kfree(shash);
- }
-}
-
-static struct crypto_aead *alloc_aead(int id)
-{
- struct crypto_aead *tfm = NULL;
-
- switch (id) {
- case CRYPTO_AEAD_AES_GCM:
- tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
- break;
- case CRYPTO_AEAD_AES_CCM:
- tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
- break;
- default:
- pr_err("Does not support encrypt ahead(id : %d)\n", id);
- return NULL;
- }
-
- if (IS_ERR(tfm)) {
- pr_err("Failed to alloc encrypt aead : %ld\n", PTR_ERR(tfm));
- return NULL;
- }
-
- return tfm;
-}
-
-static struct shash_desc *alloc_shash_desc(int id)
-{
- struct crypto_shash *tfm = NULL;
- struct shash_desc *shash;
-
- switch (id) {
- case CRYPTO_SHASH_HMACMD5:
- tfm = crypto_alloc_shash("hmac(md5)", 0, 0);
- break;
- case CRYPTO_SHASH_HMACSHA256:
- tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
- break;
- case CRYPTO_SHASH_CMACAES:
- tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
- break;
- case CRYPTO_SHASH_SHA256:
- tfm = crypto_alloc_shash("sha256", 0, 0);
- break;
- case CRYPTO_SHASH_SHA512:
- tfm = crypto_alloc_shash("sha512", 0, 0);
- break;
- default:
- return NULL;
- }
-
- if (IS_ERR(tfm))
- return NULL;
-
- shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
- GFP_KERNEL);
- if (!shash)
- crypto_free_shash(tfm);
- else
- shash->tfm = tfm;
- return shash;
-}
-
-static void ctx_free(struct ksmbd_crypto_ctx *ctx)
-{
- int i;
-
- for (i = 0; i < CRYPTO_SHASH_MAX; i++)
- free_shash(ctx->desc[i]);
- for (i = 0; i < CRYPTO_AEAD_MAX; i++)
- free_aead(ctx->ccmaes[i]);
- kfree(ctx);
-}
-
-static struct ksmbd_crypto_ctx *ksmbd_find_crypto_ctx(void)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- while (1) {
- spin_lock(&ctx_list.ctx_lock);
- if (!list_empty(&ctx_list.idle_ctx)) {
- ctx = list_entry(ctx_list.idle_ctx.next,
- struct ksmbd_crypto_ctx,
- list);
- list_del(&ctx->list);
- spin_unlock(&ctx_list.ctx_lock);
- return ctx;
- }
-
- if (ctx_list.avail_ctx > num_online_cpus()) {
- spin_unlock(&ctx_list.ctx_lock);
- wait_event(ctx_list.ctx_wait,
- !list_empty(&ctx_list.idle_ctx));
- continue;
- }
-
- ctx_list.avail_ctx++;
- spin_unlock(&ctx_list.ctx_lock);
-
- ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
- if (!ctx) {
- spin_lock(&ctx_list.ctx_lock);
- ctx_list.avail_ctx--;
- spin_unlock(&ctx_list.ctx_lock);
- wait_event(ctx_list.ctx_wait,
- !list_empty(&ctx_list.idle_ctx));
- continue;
- }
- break;
- }
- return ctx;
-}
-
-void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx)
-{
- if (!ctx)
- return;
-
- spin_lock(&ctx_list.ctx_lock);
- if (ctx_list.avail_ctx <= num_online_cpus()) {
- list_add(&ctx->list, &ctx_list.idle_ctx);
- spin_unlock(&ctx_list.ctx_lock);
- wake_up(&ctx_list.ctx_wait);
- return;
- }
-
- ctx_list.avail_ctx--;
- spin_unlock(&ctx_list.ctx_lock);
- ctx_free(ctx);
-}
-
-static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- if (id >= CRYPTO_SHASH_MAX)
- return NULL;
-
- ctx = ksmbd_find_crypto_ctx();
- if (ctx->desc[id])
- return ctx;
-
- ctx->desc[id] = alloc_shash_desc(id);
- if (ctx->desc[id])
- return ctx;
- ksmbd_release_crypto_ctx(ctx);
- return NULL;
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void)
-{
- return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACMD5);
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void)
-{
- return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACSHA256);
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void)
-{
- return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES);
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void)
-{
- return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA256);
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void)
-{
- return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512);
-}
-
-static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- if (id >= CRYPTO_AEAD_MAX)
- return NULL;
-
- ctx = ksmbd_find_crypto_ctx();
- if (ctx->ccmaes[id])
- return ctx;
-
- ctx->ccmaes[id] = alloc_aead(id);
- if (ctx->ccmaes[id])
- return ctx;
- ksmbd_release_crypto_ctx(ctx);
- return NULL;
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void)
-{
- return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_GCM);
-}
-
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void)
-{
- return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_CCM);
-}
-
-void ksmbd_crypto_destroy(void)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- while (!list_empty(&ctx_list.idle_ctx)) {
- ctx = list_entry(ctx_list.idle_ctx.next,
- struct ksmbd_crypto_ctx,
- list);
- list_del(&ctx->list);
- ctx_free(ctx);
- }
-}
-
-int ksmbd_crypto_create(void)
-{
- struct ksmbd_crypto_ctx *ctx;
-
- spin_lock_init(&ctx_list.ctx_lock);
- INIT_LIST_HEAD(&ctx_list.idle_ctx);
- init_waitqueue_head(&ctx_list.ctx_wait);
- ctx_list.avail_ctx = 1;
-
- ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
- list_add(&ctx->list, &ctx_list.idle_ctx);
- return 0;
-}
diff --git a/fs/ksmbd/crypto_ctx.h b/fs/ksmbd/crypto_ctx.h
deleted file mode 100644
index 4a367c62f653..000000000000
--- a/fs/ksmbd/crypto_ctx.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2019 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __CRYPTO_CTX_H__
-#define __CRYPTO_CTX_H__
-
-#include <crypto/hash.h>
-#include <crypto/aead.h>
-
-enum {
- CRYPTO_SHASH_HMACMD5 = 0,
- CRYPTO_SHASH_HMACSHA256,
- CRYPTO_SHASH_CMACAES,
- CRYPTO_SHASH_SHA256,
- CRYPTO_SHASH_SHA512,
- CRYPTO_SHASH_MAX,
-};
-
-enum {
- CRYPTO_AEAD_AES_GCM = 16,
- CRYPTO_AEAD_AES_CCM,
- CRYPTO_AEAD_MAX,
-};
-
-enum {
- CRYPTO_BLK_ECBDES = 32,
- CRYPTO_BLK_MAX,
-};
-
-struct ksmbd_crypto_ctx {
- struct list_head list;
-
- struct shash_desc *desc[CRYPTO_SHASH_MAX];
- struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX];
-};
-
-#define CRYPTO_HMACMD5(c) ((c)->desc[CRYPTO_SHASH_HMACMD5])
-#define CRYPTO_HMACSHA256(c) ((c)->desc[CRYPTO_SHASH_HMACSHA256])
-#define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES])
-#define CRYPTO_SHA256(c) ((c)->desc[CRYPTO_SHASH_SHA256])
-#define CRYPTO_SHA512(c) ((c)->desc[CRYPTO_SHASH_SHA512])
-
-#define CRYPTO_HMACMD5_TFM(c) ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm)
-#define CRYPTO_HMACSHA256_TFM(c)\
- ((c)->desc[CRYPTO_SHASH_HMACSHA256]->tfm)
-#define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm)
-#define CRYPTO_SHA256_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA256]->tfm)
-#define CRYPTO_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm)
-
-#define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM])
-#define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM])
-
-void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
-void ksmbd_crypto_destroy(void);
-int ksmbd_crypto_create(void);
-
-#endif /* __CRYPTO_CTX_H__ */
diff --git a/fs/ksmbd/glob.h b/fs/ksmbd/glob.h
deleted file mode 100644
index 5b8f3e0ebdb3..000000000000
--- a/fs/ksmbd/glob.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_GLOB_H
-#define __KSMBD_GLOB_H
-
-#include <linux/ctype.h>
-
-#include "unicode.h"
-#include "vfs_cache.h"
-
-#define KSMBD_VERSION "3.4.2"
-
-extern int ksmbd_debug_types;
-
-#define KSMBD_DEBUG_SMB BIT(0)
-#define KSMBD_DEBUG_AUTH BIT(1)
-#define KSMBD_DEBUG_VFS BIT(2)
-#define KSMBD_DEBUG_OPLOCK BIT(3)
-#define KSMBD_DEBUG_IPC BIT(4)
-#define KSMBD_DEBUG_CONN BIT(5)
-#define KSMBD_DEBUG_RDMA BIT(6)
-#define KSMBD_DEBUG_ALL (KSMBD_DEBUG_SMB | KSMBD_DEBUG_AUTH | \
- KSMBD_DEBUG_VFS | KSMBD_DEBUG_OPLOCK | \
- KSMBD_DEBUG_IPC | KSMBD_DEBUG_CONN | \
- KSMBD_DEBUG_RDMA)
-
-#ifdef pr_fmt
-#undef pr_fmt
-#endif
-
-#ifdef SUBMOD_NAME
-#define pr_fmt(fmt) "ksmbd: " SUBMOD_NAME ": " fmt
-#else
-#define pr_fmt(fmt) "ksmbd: " fmt
-#endif
-
-#define ksmbd_debug(type, fmt, ...) \
- do { \
- if (ksmbd_debug_types & KSMBD_DEBUG_##type) \
- pr_info(fmt, ##__VA_ARGS__); \
- } while (0)
-
-#define UNICODE_LEN(x) ((x) * 2)
-
-#endif /* __KSMBD_GLOB_H */
diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h
deleted file mode 100644
index ce866ff159bf..000000000000
--- a/fs/ksmbd/ksmbd_netlink.h
+++ /dev/null
@@ -1,412 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- *
- * linux-ksmbd-devel@lists.sourceforge.net
- */
-
-#ifndef _LINUX_KSMBD_SERVER_H
-#define _LINUX_KSMBD_SERVER_H
-
-#include <linux/types.h>
-
-/*
- * This is a userspace ABI to communicate data between ksmbd and user IPC
- * daemon using netlink. This is added to track and cache user account DB
- * and share configuration info from userspace.
- *
- * - KSMBD_EVENT_HEARTBEAT_REQUEST(ksmbd_heartbeat)
- * This event is to check whether user IPC daemon is alive. If user IPC
- * daemon is dead, ksmbd keep existing connection till disconnecting and
- * new connection will be denied.
- *
- * - KSMBD_EVENT_STARTING_UP(ksmbd_startup_request)
- * This event is to receive the information that initializes the ksmbd
- * server from the user IPC daemon and to start the server. The global
- * section parameters are given from smb.conf as initialization
- * information.
- *
- * - KSMBD_EVENT_SHUTTING_DOWN(ksmbd_shutdown_request)
- * This event is to shutdown ksmbd server.
- *
- * - KSMBD_EVENT_LOGIN_REQUEST/RESPONSE(ksmbd_login_request/response)
- * This event is to get user account info to user IPC daemon.
- *
- * - KSMBD_EVENT_SHARE_CONFIG_REQUEST/RESPONSE(ksmbd_share_config_request/response)
- * This event is to get net share configuration info.
- *
- * - KSMBD_EVENT_TREE_CONNECT_REQUEST/RESPONSE(ksmbd_tree_connect_request/response)
- * This event is to get session and tree connect info.
- *
- * - KSMBD_EVENT_TREE_DISCONNECT_REQUEST(ksmbd_tree_disconnect_request)
- * This event is to send tree disconnect info to user IPC daemon.
- *
- * - KSMBD_EVENT_LOGOUT_REQUEST(ksmbd_logout_request)
- * This event is to send logout request to user IPC daemon.
- *
- * - KSMBD_EVENT_RPC_REQUEST/RESPONSE(ksmbd_rpc_command)
- * This event is to make DCE/RPC request like srvsvc, wkssvc, lsarpc,
- * samr to be processed in userspace.
- *
- * - KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST/RESPONSE(ksmbd_spnego_authen_request/response)
- * This event is to make kerberos authentication to be processed in
- * userspace.
- */
-
-#define KSMBD_GENL_NAME "SMBD_GENL"
-#define KSMBD_GENL_VERSION 0x01
-
-#define KSMBD_REQ_MAX_ACCOUNT_NAME_SZ 48
-#define KSMBD_REQ_MAX_HASH_SZ 18
-#define KSMBD_REQ_MAX_SHARE_NAME 64
-
-/*
- * IPC heartbeat frame to check whether user IPC daemon is alive.
- */
-struct ksmbd_heartbeat {
- __u32 handle;
-};
-
-/*
- * Global config flags.
- */
-#define KSMBD_GLOBAL_FLAG_INVALID (0)
-#define KSMBD_GLOBAL_FLAG_SMB2_LEASES BIT(0)
-#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION BIT(1)
-#define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL BIT(2)
-
-/*
- * IPC request for ksmbd server startup
- */
-struct ksmbd_startup_request {
- __u32 flags; /* Flags for global config */
- __s32 signing; /* Signing enabled */
- __s8 min_prot[16]; /* The minimum SMB protocol version */
- __s8 max_prot[16]; /* The maximum SMB protocol version */
- __s8 netbios_name[16];
- __s8 work_group[64]; /* Workgroup */
- __s8 server_string[64]; /* Server string */
- __u16 tcp_port; /* tcp port */
- __u16 ipc_timeout; /*
- * specifies the number of seconds
- * server will wait for the userspace to
- * reply to heartbeat frames.
- */
- __u32 deadtime; /* Number of minutes of inactivity */
- __u32 file_max; /* Limits the maximum number of open files */
- __u32 smb2_max_write; /* MAX write size */
- __u32 smb2_max_read; /* MAX read size */
- __u32 smb2_max_trans; /* MAX trans size */
- __u32 share_fake_fscaps; /*
- * Support some special application that
- * makes QFSINFO calls to check whether
- * we set the SPARSE_FILES bit (0x40).
- */
- __u32 sub_auth[3]; /* Subauth value for Security ID */
- __u32 smb2_max_credits; /* MAX credits */
- __u32 smbd_max_io_size; /* smbd read write size */
- __u32 max_connections; /* Number of maximum simultaneous connections */
- __u32 reserved[126]; /* Reserved room */
- __u32 ifc_list_sz; /* interfaces list size */
- __s8 ____payload[];
-};
-
-#define KSMBD_STARTUP_CONFIG_INTERFACES(s) ((s)->____payload)
-
-/*
- * IPC request to shutdown ksmbd server.
- */
-struct ksmbd_shutdown_request {
- __s32 reserved[16];
-};
-
-/*
- * IPC user login request.
- */
-struct ksmbd_login_request {
- __u32 handle;
- __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
- __u32 reserved[16]; /* Reserved room */
-};
-
-/*
- * IPC user login response.
- */
-struct ksmbd_login_response {
- __u32 handle;
- __u32 gid; /* group id */
- __u32 uid; /* user id */
- __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
- __u16 status;
- __u16 hash_sz; /* hash size */
- __s8 hash[KSMBD_REQ_MAX_HASH_SZ]; /* password hash */
- __u32 reserved[16]; /* Reserved room */
-};
-
-/*
- * IPC request to fetch net share config.
- */
-struct ksmbd_share_config_request {
- __u32 handle;
- __s8 share_name[KSMBD_REQ_MAX_SHARE_NAME]; /* share name */
- __u32 reserved[16]; /* Reserved room */
-};
-
-/*
- * IPC response to the net share config request.
- */
-struct ksmbd_share_config_response {
- __u32 handle;
- __u32 flags;
- __u16 create_mask;
- __u16 directory_mask;
- __u16 force_create_mode;
- __u16 force_directory_mode;
- __u16 force_uid;
- __u16 force_gid;
- __s8 share_name[KSMBD_REQ_MAX_SHARE_NAME];
- __u32 reserved[112]; /* Reserved room */
- __u32 veto_list_sz;
- __s8 ____payload[];
-};
-
-#define KSMBD_SHARE_CONFIG_VETO_LIST(s) ((s)->____payload)
-
-static inline char *
-ksmbd_share_config_path(struct ksmbd_share_config_response *sc)
-{
- char *p = sc->____payload;
-
- if (sc->veto_list_sz)
- p += sc->veto_list_sz + 1;
-
- return p;
-}
-
-/*
- * IPC request for tree connection. This request include session and tree
- * connect info from client.
- */
-struct ksmbd_tree_connect_request {
- __u32 handle;
- __u16 account_flags;
- __u16 flags;
- __u64 session_id;
- __u64 connect_id;
- __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ];
- __s8 share[KSMBD_REQ_MAX_SHARE_NAME];
- __s8 peer_addr[64];
- __u32 reserved[16]; /* Reserved room */
-};
-
-/*
- * IPC Response structure for tree connection.
- */
-struct ksmbd_tree_connect_response {
- __u32 handle;
- __u16 status;
- __u16 connection_flags;
- __u32 reserved[16]; /* Reserved room */
-};
-
-/*
- * IPC Request struture to disconnect tree connection.
- */
-struct ksmbd_tree_disconnect_request {
- __u64 session_id; /* session id */
- __u64 connect_id; /* tree connection id */
- __u32 reserved[16]; /* Reserved room */
-};
-
-/*
- * IPC Response structure to logout user account.
- */
-struct ksmbd_logout_request {
- __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
- __u32 account_flags;
- __u32 reserved[16]; /* Reserved room */
-};
-
-/*
- * RPC command structure to send rpc request like srvsvc or wkssvc to
- * IPC user daemon.
- */
-struct ksmbd_rpc_command {
- __u32 handle;
- __u32 flags;
- __u32 payload_sz;
- __u8 payload[];
-};
-
-/*
- * IPC Request Kerberos authentication
- */
-struct ksmbd_spnego_authen_request {
- __u32 handle;
- __u16 spnego_blob_len; /* the length of spnego_blob */
- __u8 spnego_blob[]; /*
- * the GSS token from SecurityBuffer of
- * SMB2 SESSION SETUP request
- */
-};
-
-/*
- * Response data which includes the GSS token and the session key generated by
- * user daemon.
- */
-struct ksmbd_spnego_authen_response {
- __u32 handle;
- struct ksmbd_login_response login_response; /*
- * the login response with
- * a user identified by the
- * GSS token from a client
- */
- __u16 session_key_len; /* the length of the session key */
- __u16 spnego_blob_len; /*
- * the length of the GSS token which will be
- * stored in SecurityBuffer of SMB2 SESSION
- * SETUP response
- */
- __u8 payload[]; /* session key + AP_REP */
-};
-
-/*
- * This also used as NETLINK attribute type value.
- *
- * NOTE:
- * Response message type value should be equal to
- * request message type value + 1.
- */
-enum ksmbd_event {
- KSMBD_EVENT_UNSPEC = 0,
- KSMBD_EVENT_HEARTBEAT_REQUEST,
-
- KSMBD_EVENT_STARTING_UP,
- KSMBD_EVENT_SHUTTING_DOWN,
-
- KSMBD_EVENT_LOGIN_REQUEST,
- KSMBD_EVENT_LOGIN_RESPONSE = 5,
-
- KSMBD_EVENT_SHARE_CONFIG_REQUEST,
- KSMBD_EVENT_SHARE_CONFIG_RESPONSE,
-
- KSMBD_EVENT_TREE_CONNECT_REQUEST,
- KSMBD_EVENT_TREE_CONNECT_RESPONSE,
-
- KSMBD_EVENT_TREE_DISCONNECT_REQUEST = 10,
-
- KSMBD_EVENT_LOGOUT_REQUEST,
-
- KSMBD_EVENT_RPC_REQUEST,
- KSMBD_EVENT_RPC_RESPONSE,
-
- KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST,
- KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE = 15,
-
- KSMBD_EVENT_MAX
-};
-
-/*
- * Enumeration for IPC tree connect status.
- */
-enum KSMBD_TREE_CONN_STATUS {
- KSMBD_TREE_CONN_STATUS_OK = 0,
- KSMBD_TREE_CONN_STATUS_NOMEM,
- KSMBD_TREE_CONN_STATUS_NO_SHARE,
- KSMBD_TREE_CONN_STATUS_NO_USER,
- KSMBD_TREE_CONN_STATUS_INVALID_USER,
- KSMBD_TREE_CONN_STATUS_HOST_DENIED = 5,
- KSMBD_TREE_CONN_STATUS_CONN_EXIST,
- KSMBD_TREE_CONN_STATUS_TOO_MANY_CONNS,
- KSMBD_TREE_CONN_STATUS_TOO_MANY_SESSIONS,
- KSMBD_TREE_CONN_STATUS_ERROR,
-};
-
-/*
- * User config flags.
- */
-#define KSMBD_USER_FLAG_INVALID (0)
-#define KSMBD_USER_FLAG_OK BIT(0)
-#define KSMBD_USER_FLAG_BAD_PASSWORD BIT(1)
-#define KSMBD_USER_FLAG_BAD_UID BIT(2)
-#define KSMBD_USER_FLAG_BAD_USER BIT(3)
-#define KSMBD_USER_FLAG_GUEST_ACCOUNT BIT(4)
-#define KSMBD_USER_FLAG_DELAY_SESSION BIT(5)
-
-/*
- * Share config flags.
- */
-#define KSMBD_SHARE_FLAG_INVALID (0)
-#define KSMBD_SHARE_FLAG_AVAILABLE BIT(0)
-#define KSMBD_SHARE_FLAG_BROWSEABLE BIT(1)
-#define KSMBD_SHARE_FLAG_WRITEABLE BIT(2)
-#define KSMBD_SHARE_FLAG_READONLY BIT(3)
-#define KSMBD_SHARE_FLAG_GUEST_OK BIT(4)
-#define KSMBD_SHARE_FLAG_GUEST_ONLY BIT(5)
-#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS BIT(6)
-#define KSMBD_SHARE_FLAG_OPLOCKS BIT(7)
-#define KSMBD_SHARE_FLAG_PIPE BIT(8)
-#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES BIT(9)
-#define KSMBD_SHARE_FLAG_INHERIT_OWNER BIT(10)
-#define KSMBD_SHARE_FLAG_STREAMS BIT(11)
-#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12)
-#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13)
-#define KSMBD_SHARE_FLAG_UPDATE BIT(14)
-
-/*
- * Tree connect request flags.
- */
-#define KSMBD_TREE_CONN_FLAG_REQUEST_SMB1 (0)
-#define KSMBD_TREE_CONN_FLAG_REQUEST_IPV6 BIT(0)
-#define KSMBD_TREE_CONN_FLAG_REQUEST_SMB2 BIT(1)
-
-/*
- * Tree connect flags.
- */
-#define KSMBD_TREE_CONN_FLAG_GUEST_ACCOUNT BIT(0)
-#define KSMBD_TREE_CONN_FLAG_READ_ONLY BIT(1)
-#define KSMBD_TREE_CONN_FLAG_WRITABLE BIT(2)
-#define KSMBD_TREE_CONN_FLAG_ADMIN_ACCOUNT BIT(3)
-#define KSMBD_TREE_CONN_FLAG_UPDATE BIT(4)
-
-/*
- * RPC over IPC.
- */
-#define KSMBD_RPC_METHOD_RETURN BIT(0)
-#define KSMBD_RPC_SRVSVC_METHOD_INVOKE BIT(1)
-#define KSMBD_RPC_SRVSVC_METHOD_RETURN (KSMBD_RPC_SRVSVC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
-#define KSMBD_RPC_WKSSVC_METHOD_INVOKE BIT(2)
-#define KSMBD_RPC_WKSSVC_METHOD_RETURN (KSMBD_RPC_WKSSVC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
-#define KSMBD_RPC_IOCTL_METHOD (BIT(3) | KSMBD_RPC_METHOD_RETURN)
-#define KSMBD_RPC_OPEN_METHOD BIT(4)
-#define KSMBD_RPC_WRITE_METHOD BIT(5)
-#define KSMBD_RPC_READ_METHOD (BIT(6) | KSMBD_RPC_METHOD_RETURN)
-#define KSMBD_RPC_CLOSE_METHOD BIT(7)
-#define KSMBD_RPC_RAP_METHOD (BIT(8) | KSMBD_RPC_METHOD_RETURN)
-#define KSMBD_RPC_RESTRICTED_CONTEXT BIT(9)
-#define KSMBD_RPC_SAMR_METHOD_INVOKE BIT(10)
-#define KSMBD_RPC_SAMR_METHOD_RETURN (KSMBD_RPC_SAMR_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
-#define KSMBD_RPC_LSARPC_METHOD_INVOKE BIT(11)
-#define KSMBD_RPC_LSARPC_METHOD_RETURN (KSMBD_RPC_LSARPC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
-
-/*
- * RPC status definitions.
- */
-#define KSMBD_RPC_OK 0
-#define KSMBD_RPC_EBAD_FUNC 0x00000001
-#define KSMBD_RPC_EACCESS_DENIED 0x00000005
-#define KSMBD_RPC_EBAD_FID 0x00000006
-#define KSMBD_RPC_ENOMEM 0x00000008
-#define KSMBD_RPC_EBAD_DATA 0x0000000D
-#define KSMBD_RPC_ENOTIMPLEMENTED 0x00000040
-#define KSMBD_RPC_EINVALID_PARAMETER 0x00000057
-#define KSMBD_RPC_EMORE_DATA 0x000000EA
-#define KSMBD_RPC_EINVALID_LEVEL 0x0000007C
-#define KSMBD_RPC_SOME_NOT_MAPPED 0x00000107
-
-#define KSMBD_CONFIG_OPT_DISABLED 0
-#define KSMBD_CONFIG_OPT_ENABLED 1
-#define KSMBD_CONFIG_OPT_AUTO 2
-#define KSMBD_CONFIG_OPT_MANDATORY 3
-
-#endif /* _LINUX_KSMBD_SERVER_H */
diff --git a/fs/ksmbd/ksmbd_spnego_negtokeninit.asn1 b/fs/ksmbd/ksmbd_spnego_negtokeninit.asn1
deleted file mode 100644
index 0065f191b54b..000000000000
--- a/fs/ksmbd/ksmbd_spnego_negtokeninit.asn1
+++ /dev/null
@@ -1,31 +0,0 @@
-GSSAPI ::=
- [APPLICATION 0] IMPLICIT SEQUENCE {
- thisMech
- OBJECT IDENTIFIER ({ksmbd_gssapi_this_mech}),
- negotiationToken
- NegotiationToken
- }
-
-MechType ::= OBJECT IDENTIFIER ({ksmbd_neg_token_init_mech_type})
-
-MechTypeList ::= SEQUENCE OF MechType
-
-NegTokenInit ::=
- SEQUENCE {
- mechTypes
- [0] MechTypeList,
- reqFlags
- [1] BIT STRING OPTIONAL,
- mechToken
- [2] OCTET STRING OPTIONAL ({ksmbd_neg_token_init_mech_token}),
- mechListMIC
- [3] OCTET STRING OPTIONAL
- }
-
-NegotiationToken ::=
- CHOICE {
- negTokenInit
- [0] NegTokenInit,
- negTokenTarg
- [1] ANY
- }
diff --git a/fs/ksmbd/ksmbd_spnego_negtokentarg.asn1 b/fs/ksmbd/ksmbd_spnego_negtokentarg.asn1
deleted file mode 100644
index 1151933e7b9c..000000000000
--- a/fs/ksmbd/ksmbd_spnego_negtokentarg.asn1
+++ /dev/null
@@ -1,19 +0,0 @@
-GSSAPI ::=
- CHOICE {
- negTokenInit
- [0] ANY,
- negTokenTarg
- [1] NegTokenTarg
- }
-
-NegTokenTarg ::=
- SEQUENCE {
- negResult
- [0] ENUMERATED OPTIONAL,
- supportedMech
- [1] OBJECT IDENTIFIER OPTIONAL,
- responseToken
- [2] OCTET STRING OPTIONAL ({ksmbd_neg_token_targ_resp_token}),
- mechListMIC
- [3] OCTET STRING OPTIONAL
- }
diff --git a/fs/ksmbd/ksmbd_work.c b/fs/ksmbd/ksmbd_work.c
deleted file mode 100644
index 14b9caebf7a4..000000000000
--- a/fs/ksmbd/ksmbd_work.c
+++ /dev/null
@@ -1,79 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2019 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-
-#include "server.h"
-#include "connection.h"
-#include "ksmbd_work.h"
-#include "mgmt/ksmbd_ida.h"
-
-static struct kmem_cache *work_cache;
-static struct workqueue_struct *ksmbd_wq;
-
-struct ksmbd_work *ksmbd_alloc_work_struct(void)
-{
- struct ksmbd_work *work = kmem_cache_zalloc(work_cache, GFP_KERNEL);
-
- if (work) {
- work->compound_fid = KSMBD_NO_FID;
- work->compound_pfid = KSMBD_NO_FID;
- INIT_LIST_HEAD(&work->request_entry);
- INIT_LIST_HEAD(&work->async_request_entry);
- INIT_LIST_HEAD(&work->fp_entry);
- INIT_LIST_HEAD(&work->interim_entry);
- }
- return work;
-}
-
-void ksmbd_free_work_struct(struct ksmbd_work *work)
-{
- WARN_ON(work->saved_cred != NULL);
-
- kvfree(work->response_buf);
- kvfree(work->aux_payload_buf);
- kfree(work->tr_buf);
- kvfree(work->request_buf);
- if (work->async_id)
- ksmbd_release_id(&work->conn->async_ida, work->async_id);
- kmem_cache_free(work_cache, work);
-}
-
-void ksmbd_work_pool_destroy(void)
-{
- kmem_cache_destroy(work_cache);
-}
-
-int ksmbd_work_pool_init(void)
-{
- work_cache = kmem_cache_create("ksmbd_work_cache",
- sizeof(struct ksmbd_work), 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (!work_cache)
- return -ENOMEM;
- return 0;
-}
-
-int ksmbd_workqueue_init(void)
-{
- ksmbd_wq = alloc_workqueue("ksmbd-io", 0, 0);
- if (!ksmbd_wq)
- return -ENOMEM;
- return 0;
-}
-
-void ksmbd_workqueue_destroy(void)
-{
- destroy_workqueue(ksmbd_wq);
- ksmbd_wq = NULL;
-}
-
-bool ksmbd_queue_work(struct ksmbd_work *work)
-{
- return queue_work(ksmbd_wq, &work->work);
-}
diff --git a/fs/ksmbd/ksmbd_work.h b/fs/ksmbd/ksmbd_work.h
deleted file mode 100644
index 5ece58e40c97..000000000000
--- a/fs/ksmbd/ksmbd_work.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2019 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_WORK_H__
-#define __KSMBD_WORK_H__
-
-#include <linux/ctype.h>
-#include <linux/workqueue.h>
-
-struct ksmbd_conn;
-struct ksmbd_session;
-struct ksmbd_tree_connect;
-
-enum {
- KSMBD_WORK_ACTIVE = 0,
- KSMBD_WORK_CANCELLED,
- KSMBD_WORK_CLOSED,
-};
-
-/* one of these for every pending CIFS request at the connection */
-struct ksmbd_work {
- /* Server corresponding to this mid */
- struct ksmbd_conn *conn;
- struct ksmbd_session *sess;
- struct ksmbd_tree_connect *tcon;
-
- /* Pointer to received SMB header */
- void *request_buf;
- /* Response buffer */
- void *response_buf;
-
- /* Read data buffer */
- void *aux_payload_buf;
-
- /* Next cmd hdr in compound req buf*/
- int next_smb2_rcv_hdr_off;
- /* Next cmd hdr in compound rsp buf*/
- int next_smb2_rsp_hdr_off;
-
- /*
- * Current Local FID assigned compound response if SMB2 CREATE
- * command is present in compound request
- */
- u64 compound_fid;
- u64 compound_pfid;
- u64 compound_sid;
-
- const struct cred *saved_cred;
-
- /* Number of granted credits */
- unsigned int credits_granted;
-
- /* response smb header size */
- unsigned int resp_hdr_sz;
- unsigned int response_sz;
- /* Read data count */
- unsigned int aux_payload_sz;
-
- void *tr_buf;
-
- unsigned char state;
- /* Multiple responses for one request e.g. SMB ECHO */
- bool multiRsp:1;
- /* No response for cancelled request */
- bool send_no_response:1;
- /* Request is encrypted */
- bool encrypted:1;
- /* Is this SYNC or ASYNC ksmbd_work */
- bool syncronous:1;
- bool need_invalidate_rkey:1;
-
- unsigned int remote_key;
- /* cancel works */
- int async_id;
- void **cancel_argv;
- void (*cancel_fn)(void **argv);
-
- struct work_struct work;
- /* List head at conn->requests */
- struct list_head request_entry;
- /* List head at conn->async_requests */
- struct list_head async_request_entry;
- struct list_head fp_entry;
- struct list_head interim_entry;
-};
-
-/**
- * ksmbd_resp_buf_next - Get next buffer on compound response.
- * @work: smb work containing response buffer
- */
-static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work)
-{
- return work->response_buf + work->next_smb2_rsp_hdr_off + 4;
-}
-
-/**
- * ksmbd_req_buf_next - Get next buffer on compound request.
- * @work: smb work containing response buffer
- */
-static inline void *ksmbd_req_buf_next(struct ksmbd_work *work)
-{
- return work->request_buf + work->next_smb2_rcv_hdr_off + 4;
-}
-
-struct ksmbd_work *ksmbd_alloc_work_struct(void);
-void ksmbd_free_work_struct(struct ksmbd_work *work);
-
-void ksmbd_work_pool_destroy(void);
-int ksmbd_work_pool_init(void);
-
-int ksmbd_workqueue_init(void);
-void ksmbd_workqueue_destroy(void);
-bool ksmbd_queue_work(struct ksmbd_work *work);
-
-#endif /* __KSMBD_WORK_H__ */
diff --git a/fs/ksmbd/mgmt/ksmbd_ida.c b/fs/ksmbd/mgmt/ksmbd_ida.c
deleted file mode 100644
index 54194d959a5e..000000000000
--- a/fs/ksmbd/mgmt/ksmbd_ida.c
+++ /dev/null
@@ -1,46 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include "ksmbd_ida.h"
-
-static inline int __acquire_id(struct ida *ida, int from, int to)
-{
- return ida_simple_get(ida, from, to, GFP_KERNEL);
-}
-
-int ksmbd_acquire_smb2_tid(struct ida *ida)
-{
- int id;
-
- id = __acquire_id(ida, 1, 0xFFFFFFFF);
-
- return id;
-}
-
-int ksmbd_acquire_smb2_uid(struct ida *ida)
-{
- int id;
-
- id = __acquire_id(ida, 1, 0);
- if (id == 0xFFFE)
- id = __acquire_id(ida, 1, 0);
-
- return id;
-}
-
-int ksmbd_acquire_async_msg_id(struct ida *ida)
-{
- return __acquire_id(ida, 1, 0);
-}
-
-int ksmbd_acquire_id(struct ida *ida)
-{
- return __acquire_id(ida, 0, 0);
-}
-
-void ksmbd_release_id(struct ida *ida, int id)
-{
- ida_simple_remove(ida, id);
-}
diff --git a/fs/ksmbd/mgmt/ksmbd_ida.h b/fs/ksmbd/mgmt/ksmbd_ida.h
deleted file mode 100644
index 2bc07b16cfde..000000000000
--- a/fs/ksmbd/mgmt/ksmbd_ida.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_IDA_MANAGEMENT_H__
-#define __KSMBD_IDA_MANAGEMENT_H__
-
-#include <linux/slab.h>
-#include <linux/idr.h>
-
-/*
- * 2.2.1.6.7 TID Generation
- * The value 0xFFFF MUST NOT be used as a valid TID. All other
- * possible values for TID, including zero (0x0000), are valid.
- * The value 0xFFFF is used to specify all TIDs or no TID,
- * depending upon the context in which it is used.
- */
-int ksmbd_acquire_smb2_tid(struct ida *ida);
-
-/*
- * 2.2.1.6.8 UID Generation
- * The value 0xFFFE was declared reserved in the LAN Manager 1.0
- * documentation, so a value of 0xFFFE SHOULD NOT be used as a
- * valid UID.<21> All other possible values for a UID, excluding
- * zero (0x0000), are valid.
- */
-int ksmbd_acquire_smb2_uid(struct ida *ida);
-int ksmbd_acquire_async_msg_id(struct ida *ida);
-
-int ksmbd_acquire_id(struct ida *ida);
-
-void ksmbd_release_id(struct ida *ida, int id);
-#endif /* __KSMBD_IDA_MANAGEMENT_H__ */
diff --git a/fs/ksmbd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c
deleted file mode 100644
index 328a412259dc..000000000000
--- a/fs/ksmbd/mgmt/share_config.c
+++ /dev/null
@@ -1,234 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/list.h>
-#include <linux/jhash.h>
-#include <linux/slab.h>
-#include <linux/rwsem.h>
-#include <linux/parser.h>
-#include <linux/namei.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-#include "share_config.h"
-#include "user_config.h"
-#include "user_session.h"
-#include "../transport_ipc.h"
-#include "../misc.h"
-
-#define SHARE_HASH_BITS 3
-static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
-static DECLARE_RWSEM(shares_table_lock);
-
-struct ksmbd_veto_pattern {
- char *pattern;
- struct list_head list;
-};
-
-static unsigned int share_name_hash(const char *name)
-{
- return jhash(name, strlen(name), 0);
-}
-
-static void kill_share(struct ksmbd_share_config *share)
-{
- while (!list_empty(&share->veto_list)) {
- struct ksmbd_veto_pattern *p;
-
- p = list_entry(share->veto_list.next,
- struct ksmbd_veto_pattern,
- list);
- list_del(&p->list);
- kfree(p->pattern);
- kfree(p);
- }
-
- if (share->path)
- path_put(&share->vfs_path);
- kfree(share->name);
- kfree(share->path);
- kfree(share);
-}
-
-void ksmbd_share_config_del(struct ksmbd_share_config *share)
-{
- down_write(&shares_table_lock);
- hash_del(&share->hlist);
- up_write(&shares_table_lock);
-}
-
-void __ksmbd_share_config_put(struct ksmbd_share_config *share)
-{
- ksmbd_share_config_del(share);
- kill_share(share);
-}
-
-static struct ksmbd_share_config *
-__get_share_config(struct ksmbd_share_config *share)
-{
- if (!atomic_inc_not_zero(&share->refcount))
- return NULL;
- return share;
-}
-
-static struct ksmbd_share_config *__share_lookup(const char *name)
-{
- struct ksmbd_share_config *share;
- unsigned int key = share_name_hash(name);
-
- hash_for_each_possible(shares_table, share, hlist, key) {
- if (!strcmp(name, share->name))
- return share;
- }
- return NULL;
-}
-
-static int parse_veto_list(struct ksmbd_share_config *share,
- char *veto_list,
- int veto_list_sz)
-{
- int sz = 0;
-
- if (!veto_list_sz)
- return 0;
-
- while (veto_list_sz > 0) {
- struct ksmbd_veto_pattern *p;
-
- sz = strlen(veto_list);
- if (!sz)
- break;
-
- p = kzalloc(sizeof(struct ksmbd_veto_pattern), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
-
- p->pattern = kstrdup(veto_list, GFP_KERNEL);
- if (!p->pattern) {
- kfree(p);
- return -ENOMEM;
- }
-
- list_add(&p->list, &share->veto_list);
-
- veto_list += sz + 1;
- veto_list_sz -= (sz + 1);
- }
-
- return 0;
-}
-
-static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
- const char *name)
-{
- struct ksmbd_share_config_response *resp;
- struct ksmbd_share_config *share = NULL;
- struct ksmbd_share_config *lookup;
- int ret;
-
- resp = ksmbd_ipc_share_config_request(name);
- if (!resp)
- return NULL;
-
- if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
- goto out;
-
- if (*resp->share_name) {
- char *cf_resp_name;
- bool equal;
-
- cf_resp_name = ksmbd_casefold_sharename(um, resp->share_name);
- if (IS_ERR(cf_resp_name))
- goto out;
- equal = !strcmp(cf_resp_name, name);
- kfree(cf_resp_name);
- if (!equal)
- goto out;
- }
-
- share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
- if (!share)
- goto out;
-
- share->flags = resp->flags;
- atomic_set(&share->refcount, 1);
- INIT_LIST_HEAD(&share->veto_list);
- share->name = kstrdup(name, GFP_KERNEL);
-
- if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
- share->path = kstrdup(ksmbd_share_config_path(resp),
- GFP_KERNEL);
- if (share->path)
- share->path_sz = strlen(share->path);
- share->create_mask = resp->create_mask;
- share->directory_mask = resp->directory_mask;
- share->force_create_mode = resp->force_create_mode;
- share->force_directory_mode = resp->force_directory_mode;
- share->force_uid = resp->force_uid;
- share->force_gid = resp->force_gid;
- ret = parse_veto_list(share,
- KSMBD_SHARE_CONFIG_VETO_LIST(resp),
- resp->veto_list_sz);
- if (!ret && share->path) {
- ret = kern_path(share->path, 0, &share->vfs_path);
- if (ret) {
- ksmbd_debug(SMB, "failed to access '%s'\n",
- share->path);
- /* Avoid put_path() */
- kfree(share->path);
- share->path = NULL;
- }
- }
- if (ret || !share->name) {
- kill_share(share);
- share = NULL;
- goto out;
- }
- }
-
- down_write(&shares_table_lock);
- lookup = __share_lookup(name);
- if (lookup)
- lookup = __get_share_config(lookup);
- if (!lookup) {
- hash_add(shares_table, &share->hlist, share_name_hash(name));
- } else {
- kill_share(share);
- share = lookup;
- }
- up_write(&shares_table_lock);
-
-out:
- kvfree(resp);
- return share;
-}
-
-struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
- const char *name)
-{
- struct ksmbd_share_config *share;
-
- down_read(&shares_table_lock);
- share = __share_lookup(name);
- if (share)
- share = __get_share_config(share);
- up_read(&shares_table_lock);
-
- if (share)
- return share;
- return share_config_request(um, name);
-}
-
-bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
- const char *filename)
-{
- struct ksmbd_veto_pattern *p;
-
- list_for_each_entry(p, &share->veto_list, list) {
- if (match_wildcard(p->pattern, filename))
- return true;
- }
- return false;
-}
diff --git a/fs/ksmbd/mgmt/share_config.h b/fs/ksmbd/mgmt/share_config.h
deleted file mode 100644
index 3fd338293942..000000000000
--- a/fs/ksmbd/mgmt/share_config.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __SHARE_CONFIG_MANAGEMENT_H__
-#define __SHARE_CONFIG_MANAGEMENT_H__
-
-#include <linux/workqueue.h>
-#include <linux/hashtable.h>
-#include <linux/path.h>
-#include <linux/unicode.h>
-
-struct ksmbd_share_config {
- char *name;
- char *path;
-
- unsigned int path_sz;
- unsigned int flags;
- struct list_head veto_list;
-
- struct path vfs_path;
-
- atomic_t refcount;
- struct hlist_node hlist;
- unsigned short create_mask;
- unsigned short directory_mask;
- unsigned short force_create_mode;
- unsigned short force_directory_mode;
- unsigned short force_uid;
- unsigned short force_gid;
-};
-
-#define KSMBD_SHARE_INVALID_UID ((__u16)-1)
-#define KSMBD_SHARE_INVALID_GID ((__u16)-1)
-
-static inline int share_config_create_mode(struct ksmbd_share_config *share,
- umode_t posix_mode)
-{
- if (!share->force_create_mode) {
- if (!posix_mode)
- return share->create_mask;
- else
- return posix_mode & share->create_mask;
- }
- return share->force_create_mode & share->create_mask;
-}
-
-static inline int share_config_directory_mode(struct ksmbd_share_config *share,
- umode_t posix_mode)
-{
- if (!share->force_directory_mode) {
- if (!posix_mode)
- return share->directory_mask;
- else
- return posix_mode & share->directory_mask;
- }
-
- return share->force_directory_mode & share->directory_mask;
-}
-
-static inline int test_share_config_flag(struct ksmbd_share_config *share,
- int flag)
-{
- return share->flags & flag;
-}
-
-void ksmbd_share_config_del(struct ksmbd_share_config *share);
-void __ksmbd_share_config_put(struct ksmbd_share_config *share);
-
-static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
-{
- if (!atomic_dec_and_test(&share->refcount))
- return;
- __ksmbd_share_config_put(share);
-}
-
-struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
- const char *name);
-bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
- const char *filename);
-#endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c
deleted file mode 100644
index f07a05f37651..000000000000
--- a/fs/ksmbd/mgmt/tree_connect.c
+++ /dev/null
@@ -1,147 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/xarray.h>
-
-#include "../transport_ipc.h"
-#include "../connection.h"
-
-#include "tree_connect.h"
-#include "user_config.h"
-#include "share_config.h"
-#include "user_session.h"
-
-struct ksmbd_tree_conn_status
-ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
- const char *share_name)
-{
- struct ksmbd_tree_conn_status status = {-ENOENT, NULL};
- struct ksmbd_tree_connect_response *resp = NULL;
- struct ksmbd_share_config *sc;
- struct ksmbd_tree_connect *tree_conn = NULL;
- struct sockaddr *peer_addr;
- int ret;
-
- sc = ksmbd_share_config_get(conn->um, share_name);
- if (!sc)
- return status;
-
- tree_conn = kzalloc(sizeof(struct ksmbd_tree_connect), GFP_KERNEL);
- if (!tree_conn) {
- status.ret = -ENOMEM;
- goto out_error;
- }
-
- tree_conn->id = ksmbd_acquire_tree_conn_id(sess);
- if (tree_conn->id < 0) {
- status.ret = -EINVAL;
- goto out_error;
- }
-
- peer_addr = KSMBD_TCP_PEER_SOCKADDR(conn);
- resp = ksmbd_ipc_tree_connect_request(sess,
- sc,
- tree_conn,
- peer_addr);
- if (!resp) {
- status.ret = -EINVAL;
- goto out_error;
- }
-
- status.ret = resp->status;
- if (status.ret != KSMBD_TREE_CONN_STATUS_OK)
- goto out_error;
-
- tree_conn->flags = resp->connection_flags;
- if (test_tree_conn_flag(tree_conn, KSMBD_TREE_CONN_FLAG_UPDATE)) {
- struct ksmbd_share_config *new_sc;
-
- ksmbd_share_config_del(sc);
- new_sc = ksmbd_share_config_get(conn->um, share_name);
- if (!new_sc) {
- pr_err("Failed to update stale share config\n");
- status.ret = -ESTALE;
- goto out_error;
- }
- ksmbd_share_config_put(sc);
- sc = new_sc;
- }
-
- tree_conn->user = sess->user;
- tree_conn->share_conf = sc;
- status.tree_conn = tree_conn;
-
- ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn,
- GFP_KERNEL));
- if (ret) {
- status.ret = -ENOMEM;
- goto out_error;
- }
- kvfree(resp);
- return status;
-
-out_error:
- if (tree_conn)
- ksmbd_release_tree_conn_id(sess, tree_conn->id);
- ksmbd_share_config_put(sc);
- kfree(tree_conn);
- kvfree(resp);
- return status;
-}
-
-int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
- struct ksmbd_tree_connect *tree_conn)
-{
- int ret;
-
- ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
- ksmbd_release_tree_conn_id(sess, tree_conn->id);
- xa_erase(&sess->tree_conns, tree_conn->id);
- ksmbd_share_config_put(tree_conn->share_conf);
- kfree(tree_conn);
- return ret;
-}
-
-struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
- unsigned int id)
-{
- struct ksmbd_tree_connect *tcon;
-
- tcon = xa_load(&sess->tree_conns, id);
- if (tcon) {
- if (test_bit(TREE_CONN_EXPIRE, &tcon->status))
- tcon = NULL;
- }
-
- return tcon;
-}
-
-struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
- unsigned int id)
-{
- struct ksmbd_tree_connect *tc;
-
- tc = ksmbd_tree_conn_lookup(sess, id);
- if (tc)
- return tc->share_conf;
- return NULL;
-}
-
-int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
-{
- int ret = 0;
- struct ksmbd_tree_connect *tc;
- unsigned long id;
-
- if (!sess)
- return -EINVAL;
-
- xa_for_each(&sess->tree_conns, id, tc)
- ret |= ksmbd_tree_conn_disconnect(sess, tc);
- xa_destroy(&sess->tree_conns);
- return ret;
-}
diff --git a/fs/ksmbd/mgmt/tree_connect.h b/fs/ksmbd/mgmt/tree_connect.h
deleted file mode 100644
index 700df36cf3e3..000000000000
--- a/fs/ksmbd/mgmt/tree_connect.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __TREE_CONNECT_MANAGEMENT_H__
-#define __TREE_CONNECT_MANAGEMENT_H__
-
-#include <linux/hashtable.h>
-
-#include "../ksmbd_netlink.h"
-
-struct ksmbd_share_config;
-struct ksmbd_user;
-struct ksmbd_conn;
-
-#define TREE_CONN_EXPIRE 1
-
-struct ksmbd_tree_connect {
- int id;
-
- unsigned int flags;
- struct ksmbd_share_config *share_conf;
- struct ksmbd_user *user;
-
- struct list_head list;
-
- int maximal_access;
- bool posix_extensions;
- unsigned long status;
-};
-
-struct ksmbd_tree_conn_status {
- unsigned int ret;
- struct ksmbd_tree_connect *tree_conn;
-};
-
-static inline int test_tree_conn_flag(struct ksmbd_tree_connect *tree_conn,
- int flag)
-{
- return tree_conn->flags & flag;
-}
-
-struct ksmbd_session;
-
-struct ksmbd_tree_conn_status
-ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
- const char *share_name);
-
-int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
- struct ksmbd_tree_connect *tree_conn);
-
-struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
- unsigned int id);
-
-struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
- unsigned int id);
-
-int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess);
-
-#endif /* __TREE_CONNECT_MANAGEMENT_H__ */
diff --git a/fs/ksmbd/mgmt/user_config.c b/fs/ksmbd/mgmt/user_config.c
deleted file mode 100644
index 279d00feff21..000000000000
--- a/fs/ksmbd/mgmt/user_config.c
+++ /dev/null
@@ -1,79 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/slab.h>
-#include <linux/mm.h>
-
-#include "user_config.h"
-#include "../transport_ipc.h"
-
-struct ksmbd_user *ksmbd_login_user(const char *account)
-{
- struct ksmbd_login_response *resp;
- struct ksmbd_user *user = NULL;
-
- resp = ksmbd_ipc_login_request(account);
- if (!resp)
- return NULL;
-
- if (!(resp->status & KSMBD_USER_FLAG_OK))
- goto out;
-
- user = ksmbd_alloc_user(resp);
-out:
- kvfree(resp);
- return user;
-}
-
-struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp)
-{
- struct ksmbd_user *user = NULL;
-
- user = kmalloc(sizeof(struct ksmbd_user), GFP_KERNEL);
- if (!user)
- return NULL;
-
- user->name = kstrdup(resp->account, GFP_KERNEL);
- user->flags = resp->status;
- user->gid = resp->gid;
- user->uid = resp->uid;
- user->passkey_sz = resp->hash_sz;
- user->passkey = kmalloc(resp->hash_sz, GFP_KERNEL);
- if (user->passkey)
- memcpy(user->passkey, resp->hash, resp->hash_sz);
-
- if (!user->name || !user->passkey) {
- kfree(user->name);
- kfree(user->passkey);
- kfree(user);
- user = NULL;
- }
- return user;
-}
-
-void ksmbd_free_user(struct ksmbd_user *user)
-{
- ksmbd_ipc_logout_request(user->name, user->flags);
- kfree(user->name);
- kfree(user->passkey);
- kfree(user);
-}
-
-int ksmbd_anonymous_user(struct ksmbd_user *user)
-{
- if (user->name[0] == '\0')
- return 1;
- return 0;
-}
-
-bool ksmbd_compare_user(struct ksmbd_user *u1, struct ksmbd_user *u2)
-{
- if (strcmp(u1->name, u2->name))
- return false;
- if (memcmp(u1->passkey, u2->passkey, u1->passkey_sz))
- return false;
-
- return true;
-}
diff --git a/fs/ksmbd/mgmt/user_config.h b/fs/ksmbd/mgmt/user_config.h
deleted file mode 100644
index 6a44109617f1..000000000000
--- a/fs/ksmbd/mgmt/user_config.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __USER_CONFIG_MANAGEMENT_H__
-#define __USER_CONFIG_MANAGEMENT_H__
-
-#include "../glob.h"
-
-struct ksmbd_user {
- unsigned short flags;
-
- unsigned int uid;
- unsigned int gid;
-
- char *name;
-
- size_t passkey_sz;
- char *passkey;
- unsigned int failed_login_count;
-};
-
-static inline bool user_guest(struct ksmbd_user *user)
-{
- return user->flags & KSMBD_USER_FLAG_GUEST_ACCOUNT;
-}
-
-static inline void set_user_flag(struct ksmbd_user *user, int flag)
-{
- user->flags |= flag;
-}
-
-static inline int test_user_flag(struct ksmbd_user *user, int flag)
-{
- return user->flags & flag;
-}
-
-static inline void set_user_guest(struct ksmbd_user *user)
-{
-}
-
-static inline char *user_passkey(struct ksmbd_user *user)
-{
- return user->passkey;
-}
-
-static inline char *user_name(struct ksmbd_user *user)
-{
- return user->name;
-}
-
-static inline unsigned int user_uid(struct ksmbd_user *user)
-{
- return user->uid;
-}
-
-static inline unsigned int user_gid(struct ksmbd_user *user)
-{
- return user->gid;
-}
-
-struct ksmbd_user *ksmbd_login_user(const char *account);
-struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp);
-void ksmbd_free_user(struct ksmbd_user *user);
-int ksmbd_anonymous_user(struct ksmbd_user *user);
-bool ksmbd_compare_user(struct ksmbd_user *u1, struct ksmbd_user *u2);
-#endif /* __USER_CONFIG_MANAGEMENT_H__ */
diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
deleted file mode 100644
index ea4b56d570fb..000000000000
--- a/fs/ksmbd/mgmt/user_session.c
+++ /dev/null
@@ -1,400 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/rwsem.h>
-#include <linux/xarray.h>
-
-#include "ksmbd_ida.h"
-#include "user_session.h"
-#include "user_config.h"
-#include "tree_connect.h"
-#include "../transport_ipc.h"
-#include "../connection.h"
-#include "../vfs_cache.h"
-
-static DEFINE_IDA(session_ida);
-
-#define SESSION_HASH_BITS 3
-static DEFINE_HASHTABLE(sessions_table, SESSION_HASH_BITS);
-static DECLARE_RWSEM(sessions_table_lock);
-
-struct ksmbd_session_rpc {
- int id;
- unsigned int method;
- struct list_head list;
-};
-
-static void free_channel_list(struct ksmbd_session *sess)
-{
- struct channel *chann;
- unsigned long index;
-
- xa_for_each(&sess->ksmbd_chann_list, index, chann) {
- xa_erase(&sess->ksmbd_chann_list, index);
- kfree(chann);
- }
-
- xa_destroy(&sess->ksmbd_chann_list);
-}
-
-static void __session_rpc_close(struct ksmbd_session *sess,
- struct ksmbd_session_rpc *entry)
-{
- struct ksmbd_rpc_command *resp;
-
- resp = ksmbd_rpc_close(sess, entry->id);
- if (!resp)
- pr_err("Unable to close RPC pipe %d\n", entry->id);
-
- kvfree(resp);
- ksmbd_rpc_id_free(entry->id);
- kfree(entry);
-}
-
-static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
-{
- struct ksmbd_session_rpc *entry;
-
- while (!list_empty(&sess->rpc_handle_list)) {
- entry = list_entry(sess->rpc_handle_list.next,
- struct ksmbd_session_rpc,
- list);
-
- list_del(&entry->list);
- __session_rpc_close(sess, entry);
- }
-}
-
-static int __rpc_method(char *rpc_name)
-{
- if (!strcmp(rpc_name, "\\srvsvc") || !strcmp(rpc_name, "srvsvc"))
- return KSMBD_RPC_SRVSVC_METHOD_INVOKE;
-
- if (!strcmp(rpc_name, "\\wkssvc") || !strcmp(rpc_name, "wkssvc"))
- return KSMBD_RPC_WKSSVC_METHOD_INVOKE;
-
- if (!strcmp(rpc_name, "LANMAN") || !strcmp(rpc_name, "lanman"))
- return KSMBD_RPC_RAP_METHOD;
-
- if (!strcmp(rpc_name, "\\samr") || !strcmp(rpc_name, "samr"))
- return KSMBD_RPC_SAMR_METHOD_INVOKE;
-
- if (!strcmp(rpc_name, "\\lsarpc") || !strcmp(rpc_name, "lsarpc"))
- return KSMBD_RPC_LSARPC_METHOD_INVOKE;
-
- pr_err("Unsupported RPC: %s\n", rpc_name);
- return 0;
-}
-
-int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
-{
- struct ksmbd_session_rpc *entry;
- struct ksmbd_rpc_command *resp;
- int method;
-
- method = __rpc_method(rpc_name);
- if (!method)
- return -EINVAL;
-
- entry = kzalloc(sizeof(struct ksmbd_session_rpc), GFP_KERNEL);
- if (!entry)
- return -EINVAL;
-
- list_add(&entry->list, &sess->rpc_handle_list);
- entry->method = method;
- entry->id = ksmbd_ipc_id_alloc();
- if (entry->id < 0)
- goto free_entry;
-
- resp = ksmbd_rpc_open(sess, entry->id);
- if (!resp)
- goto free_id;
-
- kvfree(resp);
- return entry->id;
-free_id:
- ksmbd_rpc_id_free(entry->id);
-free_entry:
- list_del(&entry->list);
- kfree(entry);
- return -EINVAL;
-}
-
-void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
-{
- struct ksmbd_session_rpc *entry;
-
- list_for_each_entry(entry, &sess->rpc_handle_list, list) {
- if (entry->id == id) {
- list_del(&entry->list);
- __session_rpc_close(sess, entry);
- break;
- }
- }
-}
-
-int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
-{
- struct ksmbd_session_rpc *entry;
-
- list_for_each_entry(entry, &sess->rpc_handle_list, list) {
- if (entry->id == id)
- return entry->method;
- }
- return 0;
-}
-
-void ksmbd_session_destroy(struct ksmbd_session *sess)
-{
- if (!sess)
- return;
-
- if (sess->user)
- ksmbd_free_user(sess->user);
-
- ksmbd_tree_conn_session_logoff(sess);
- ksmbd_destroy_file_table(&sess->file_table);
- ksmbd_session_rpc_clear_list(sess);
- free_channel_list(sess);
- kfree(sess->Preauth_HashValue);
- ksmbd_release_id(&session_ida, sess->id);
- kfree(sess);
-}
-
-static struct ksmbd_session *__session_lookup(unsigned long long id)
-{
- struct ksmbd_session *sess;
-
- hash_for_each_possible(sessions_table, sess, hlist, id) {
- if (id == sess->id) {
- sess->last_active = jiffies;
- return sess;
- }
- }
- return NULL;
-}
-
-static void ksmbd_expire_session(struct ksmbd_conn *conn)
-{
- unsigned long id;
- struct ksmbd_session *sess;
-
- down_write(&sessions_table_lock);
- xa_for_each(&conn->sessions, id, sess) {
- if (sess->state != SMB2_SESSION_VALID ||
- time_after(jiffies,
- sess->last_active + SMB2_SESSION_TIMEOUT)) {
- xa_erase(&conn->sessions, sess->id);
- hash_del(&sess->hlist);
- ksmbd_session_destroy(sess);
- continue;
- }
- }
- up_write(&sessions_table_lock);
-}
-
-int ksmbd_session_register(struct ksmbd_conn *conn,
- struct ksmbd_session *sess)
-{
- sess->dialect = conn->dialect;
- memcpy(sess->ClientGUID, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
- ksmbd_expire_session(conn);
- return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL));
-}
-
-static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
-{
- struct channel *chann;
-
- chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
- if (!chann)
- return -ENOENT;
-
- kfree(chann);
- return 0;
-}
-
-void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
-{
- struct ksmbd_session *sess;
- unsigned long id;
-
- down_write(&sessions_table_lock);
- if (conn->binding) {
- int bkt;
- struct hlist_node *tmp;
-
- hash_for_each_safe(sessions_table, bkt, tmp, sess, hlist) {
- if (!ksmbd_chann_del(conn, sess) &&
- xa_empty(&sess->ksmbd_chann_list)) {
- hash_del(&sess->hlist);
- ksmbd_session_destroy(sess);
- }
- }
- }
-
- xa_for_each(&conn->sessions, id, sess) {
- unsigned long chann_id;
- struct channel *chann;
-
- xa_for_each(&sess->ksmbd_chann_list, chann_id, chann) {
- if (chann->conn != conn)
- ksmbd_conn_set_exiting(chann->conn);
- }
-
- ksmbd_chann_del(conn, sess);
- if (xa_empty(&sess->ksmbd_chann_list)) {
- xa_erase(&conn->sessions, sess->id);
- hash_del(&sess->hlist);
- ksmbd_session_destroy(sess);
- }
- }
- up_write(&sessions_table_lock);
-}
-
-struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
- unsigned long long id)
-{
- struct ksmbd_session *sess;
-
- sess = xa_load(&conn->sessions, id);
- if (sess)
- sess->last_active = jiffies;
- return sess;
-}
-
-struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
-{
- struct ksmbd_session *sess;
-
- down_read(&sessions_table_lock);
- sess = __session_lookup(id);
- if (sess)
- sess->last_active = jiffies;
- up_read(&sessions_table_lock);
-
- return sess;
-}
-
-struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
- unsigned long long id)
-{
- struct ksmbd_session *sess;
-
- sess = ksmbd_session_lookup(conn, id);
- if (!sess && conn->binding)
- sess = ksmbd_session_lookup_slowpath(id);
- if (sess && sess->state != SMB2_SESSION_VALID)
- sess = NULL;
- return sess;
-}
-
-struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
- u64 sess_id)
-{
- struct preauth_session *sess;
-
- sess = kmalloc(sizeof(struct preauth_session), GFP_KERNEL);
- if (!sess)
- return NULL;
-
- sess->id = sess_id;
- memcpy(sess->Preauth_HashValue, conn->preauth_info->Preauth_HashValue,
- PREAUTH_HASHVALUE_SIZE);
- list_add(&sess->preauth_entry, &conn->preauth_sess_table);
-
- return sess;
-}
-
-static bool ksmbd_preauth_session_id_match(struct preauth_session *sess,
- unsigned long long id)
-{
- return sess->id == id;
-}
-
-struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
- unsigned long long id)
-{
- struct preauth_session *sess = NULL;
-
- list_for_each_entry(sess, &conn->preauth_sess_table, preauth_entry) {
- if (ksmbd_preauth_session_id_match(sess, id))
- return sess;
- }
- return NULL;
-}
-
-static int __init_smb2_session(struct ksmbd_session *sess)
-{
- int id = ksmbd_acquire_smb2_uid(&session_ida);
-
- if (id < 0)
- return -EINVAL;
- sess->id = id;
- return 0;
-}
-
-static struct ksmbd_session *__session_create(int protocol)
-{
- struct ksmbd_session *sess;
- int ret;
-
- if (protocol != CIFDS_SESSION_FLAG_SMB2)
- return NULL;
-
- sess = kzalloc(sizeof(struct ksmbd_session), GFP_KERNEL);
- if (!sess)
- return NULL;
-
- if (ksmbd_init_file_table(&sess->file_table))
- goto error;
-
- sess->last_active = jiffies;
- sess->state = SMB2_SESSION_IN_PROGRESS;
- set_session_flag(sess, protocol);
- xa_init(&sess->tree_conns);
- xa_init(&sess->ksmbd_chann_list);
- INIT_LIST_HEAD(&sess->rpc_handle_list);
- sess->sequence_number = 1;
-
- ret = __init_smb2_session(sess);
- if (ret)
- goto error;
-
- ida_init(&sess->tree_conn_ida);
-
- down_write(&sessions_table_lock);
- hash_add(sessions_table, &sess->hlist, sess->id);
- up_write(&sessions_table_lock);
-
- return sess;
-
-error:
- ksmbd_session_destroy(sess);
- return NULL;
-}
-
-struct ksmbd_session *ksmbd_smb2_session_create(void)
-{
- return __session_create(CIFDS_SESSION_FLAG_SMB2);
-}
-
-int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess)
-{
- int id = -EINVAL;
-
- if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
- id = ksmbd_acquire_smb2_tid(&sess->tree_conn_ida);
-
- return id;
-}
-
-void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id)
-{
- if (id >= 0)
- ksmbd_release_id(&sess->tree_conn_ida, id);
-}
diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h
deleted file mode 100644
index 51f38e5b61ab..000000000000
--- a/fs/ksmbd/mgmt/user_session.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __USER_SESSION_MANAGEMENT_H__
-#define __USER_SESSION_MANAGEMENT_H__
-
-#include <linux/hashtable.h>
-#include <linux/xarray.h>
-
-#include "../smb_common.h"
-#include "../ntlmssp.h"
-
-#define CIFDS_SESSION_FLAG_SMB2 BIT(1)
-
-#define PREAUTH_HASHVALUE_SIZE 64
-
-struct ksmbd_file_table;
-
-struct channel {
- __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
- struct ksmbd_conn *conn;
-};
-
-struct preauth_session {
- __u8 Preauth_HashValue[PREAUTH_HASHVALUE_SIZE];
- u64 id;
- struct list_head preauth_entry;
-};
-
-struct ksmbd_session {
- u64 id;
-
- __u16 dialect;
- char ClientGUID[SMB2_CLIENT_GUID_SIZE];
-
- struct ksmbd_user *user;
- unsigned int sequence_number;
- unsigned int flags;
-
- bool sign;
- bool enc;
- bool is_anonymous;
-
- int state;
- __u8 *Preauth_HashValue;
-
- char sess_key[CIFS_KEY_SIZE];
-
- struct hlist_node hlist;
- struct xarray ksmbd_chann_list;
- struct xarray tree_conns;
- struct ida tree_conn_ida;
- struct list_head rpc_handle_list;
-
- __u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
- __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
- __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
-
- struct ksmbd_file_table file_table;
- unsigned long last_active;
-};
-
-static inline int test_session_flag(struct ksmbd_session *sess, int bit)
-{
- return sess->flags & bit;
-}
-
-static inline void set_session_flag(struct ksmbd_session *sess, int bit)
-{
- sess->flags |= bit;
-}
-
-static inline void clear_session_flag(struct ksmbd_session *sess, int bit)
-{
- sess->flags &= ~bit;
-}
-
-struct ksmbd_session *ksmbd_smb2_session_create(void);
-
-void ksmbd_session_destroy(struct ksmbd_session *sess);
-
-struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id);
-struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
- unsigned long long id);
-int ksmbd_session_register(struct ksmbd_conn *conn,
- struct ksmbd_session *sess);
-void ksmbd_sessions_deregister(struct ksmbd_conn *conn);
-struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
- unsigned long long id);
-struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
- u64 sess_id);
-struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
- unsigned long long id);
-
-int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess);
-void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id);
-
-int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name);
-void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id);
-int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id);
-#endif /* __USER_SESSION_MANAGEMENT_H__ */
diff --git a/fs/ksmbd/misc.c b/fs/ksmbd/misc.c
deleted file mode 100644
index 9e8afaa686e3..000000000000
--- a/fs/ksmbd/misc.c
+++ /dev/null
@@ -1,381 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/kernel.h>
-#include <linux/xattr.h>
-#include <linux/fs.h>
-#include <linux/unicode.h>
-
-#include "misc.h"
-#include "smb_common.h"
-#include "connection.h"
-#include "vfs.h"
-
-#include "mgmt/share_config.h"
-
-/**
- * match_pattern() - compare a string with a pattern which might include
- * wildcard '*' and '?'
- * TODO : implement consideration about DOS_DOT, DOS_QM and DOS_STAR
- *
- * @str: string to compare with a pattern
- * @len: string length
- * @pattern: pattern string which might include wildcard '*' and '?'
- *
- * Return: 0 if pattern matched with the string, otherwise non zero value
- */
-int match_pattern(const char *str, size_t len, const char *pattern)
-{
- const char *s = str;
- const char *p = pattern;
- bool star = false;
-
- while (*s && len) {
- switch (*p) {
- case '?':
- s++;
- len--;
- p++;
- break;
- case '*':
- star = true;
- str = s;
- if (!*++p)
- return true;
- pattern = p;
- break;
- default:
- if (tolower(*s) == tolower(*p)) {
- s++;
- len--;
- p++;
- } else {
- if (!star)
- return false;
- str++;
- s = str;
- p = pattern;
- }
- break;
- }
- }
-
- if (*p == '*')
- ++p;
- return !*p;
-}
-
-/*
- * is_char_allowed() - check for valid character
- * @ch: input character to be checked
- *
- * Return: 1 if char is allowed, otherwise 0
- */
-static inline int is_char_allowed(char ch)
-{
- /* check for control chars, wildcards etc. */
- if (!(ch & 0x80) &&
- (ch <= 0x1f ||
- ch == '?' || ch == '"' || ch == '<' ||
- ch == '>' || ch == '|' || ch == '*'))
- return 0;
-
- return 1;
-}
-
-int ksmbd_validate_filename(char *filename)
-{
- while (*filename) {
- char c = *filename;
-
- filename++;
- if (!is_char_allowed(c)) {
- ksmbd_debug(VFS, "File name validation failed: 0x%x\n", c);
- return -ENOENT;
- }
- }
-
- return 0;
-}
-
-static int ksmbd_validate_stream_name(char *stream_name)
-{
- while (*stream_name) {
- char c = *stream_name;
-
- stream_name++;
- if (c == '/' || c == ':' || c == '\\') {
- pr_err("Stream name validation failed: %c\n", c);
- return -ENOENT;
- }
- }
-
- return 0;
-}
-
-int parse_stream_name(char *filename, char **stream_name, int *s_type)
-{
- char *stream_type;
- char *s_name;
- int rc = 0;
-
- s_name = filename;
- filename = strsep(&s_name, ":");
- ksmbd_debug(SMB, "filename : %s, streams : %s\n", filename, s_name);
- if (strchr(s_name, ':')) {
- stream_type = s_name;
- s_name = strsep(&stream_type, ":");
-
- rc = ksmbd_validate_stream_name(s_name);
- if (rc < 0) {
- rc = -ENOENT;
- goto out;
- }
-
- ksmbd_debug(SMB, "stream name : %s, stream type : %s\n", s_name,
- stream_type);
- if (!strncasecmp("$data", stream_type, 5))
- *s_type = DATA_STREAM;
- else if (!strncasecmp("$index_allocation", stream_type, 17))
- *s_type = DIR_STREAM;
- else
- rc = -ENOENT;
- }
-
- *stream_name = s_name;
-out:
- return rc;
-}
-
-/**
- * convert_to_nt_pathname() - extract and return windows path string
- * whose share directory prefix was removed from file path
- * @share: ksmbd_share_config pointer
- * @path: path to report
- *
- * Return : windows path string or error
- */
-
-char *convert_to_nt_pathname(struct ksmbd_share_config *share,
- const struct path *path)
-{
- char *pathname, *ab_pathname, *nt_pathname;
- int share_path_len = share->path_sz;
-
- pathname = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!pathname)
- return ERR_PTR(-EACCES);
-
- ab_pathname = d_path(path, pathname, PATH_MAX);
- if (IS_ERR(ab_pathname)) {
- nt_pathname = ERR_PTR(-EACCES);
- goto free_pathname;
- }
-
- if (strncmp(ab_pathname, share->path, share_path_len)) {
- nt_pathname = ERR_PTR(-EACCES);
- goto free_pathname;
- }
-
- nt_pathname = kzalloc(strlen(&ab_pathname[share_path_len]) + 2, GFP_KERNEL);
- if (!nt_pathname) {
- nt_pathname = ERR_PTR(-ENOMEM);
- goto free_pathname;
- }
- if (ab_pathname[share_path_len] == '\0')
- strcpy(nt_pathname, "/");
- strcat(nt_pathname, &ab_pathname[share_path_len]);
-
- ksmbd_conv_path_to_windows(nt_pathname);
-
-free_pathname:
- kfree(pathname);
- return nt_pathname;
-}
-
-int get_nlink(struct kstat *st)
-{
- int nlink;
-
- nlink = st->nlink;
- if (S_ISDIR(st->mode))
- nlink--;
-
- return nlink;
-}
-
-void ksmbd_conv_path_to_unix(char *path)
-{
- strreplace(path, '\\', '/');
-}
-
-void ksmbd_strip_last_slash(char *path)
-{
- int len = strlen(path);
-
- while (len && path[len - 1] == '/') {
- path[len - 1] = '\0';
- len--;
- }
-}
-
-void ksmbd_conv_path_to_windows(char *path)
-{
- strreplace(path, '/', '\\');
-}
-
-char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name)
-{
- char *cf_name;
- int cf_len;
-
- cf_name = kzalloc(KSMBD_REQ_MAX_SHARE_NAME, GFP_KERNEL);
- if (!cf_name)
- return ERR_PTR(-ENOMEM);
-
- if (IS_ENABLED(CONFIG_UNICODE) && um) {
- const struct qstr q_name = {.name = name, .len = strlen(name)};
-
- cf_len = utf8_casefold(um, &q_name, cf_name,
- KSMBD_REQ_MAX_SHARE_NAME);
- if (cf_len < 0)
- goto out_ascii;
-
- return cf_name;
- }
-
-out_ascii:
- cf_len = strscpy(cf_name, name, KSMBD_REQ_MAX_SHARE_NAME);
- if (cf_len < 0) {
- kfree(cf_name);
- return ERR_PTR(-E2BIG);
- }
-
- for (; *cf_name; ++cf_name)
- *cf_name = isascii(*cf_name) ? tolower(*cf_name) : *cf_name;
- return cf_name - cf_len;
-}
-
-/**
- * ksmbd_extract_sharename() - get share name from tree connect request
- * @treename: buffer containing tree name and share name
- *
- * Return: share name on success, otherwise error
- */
-char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename)
-{
- const char *name = treename, *pos = strrchr(name, '\\');
-
- if (pos)
- name = (pos + 1);
-
- /* caller has to free the memory */
- return ksmbd_casefold_sharename(um, name);
-}
-
-/**
- * convert_to_unix_name() - convert windows name to unix format
- * @share: ksmbd_share_config pointer
- * @name: file name that is relative to share
- *
- * Return: converted name on success, otherwise NULL
- */
-char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name)
-{
- int no_slash = 0, name_len, path_len;
- char *new_name;
-
- if (name[0] == '/')
- name++;
-
- path_len = share->path_sz;
- name_len = strlen(name);
- new_name = kmalloc(path_len + name_len + 2, GFP_KERNEL);
- if (!new_name)
- return new_name;
-
- memcpy(new_name, share->path, path_len);
- if (new_name[path_len - 1] != '/') {
- new_name[path_len] = '/';
- no_slash = 1;
- }
-
- memcpy(new_name + path_len + no_slash, name, name_len);
- path_len += name_len + no_slash;
- new_name[path_len] = 0x00;
- return new_name;
-}
-
-char *ksmbd_convert_dir_info_name(struct ksmbd_dir_info *d_info,
- const struct nls_table *local_nls,
- int *conv_len)
-{
- char *conv;
- int sz = min(4 * d_info->name_len, PATH_MAX);
-
- if (!sz)
- return NULL;
-
- conv = kmalloc(sz, GFP_KERNEL);
- if (!conv)
- return NULL;
-
- /* XXX */
- *conv_len = smbConvertToUTF16((__le16 *)conv, d_info->name,
- d_info->name_len, local_nls, 0);
- *conv_len *= 2;
-
- /* We allocate buffer twice bigger than needed. */
- conv[*conv_len] = 0x00;
- conv[*conv_len + 1] = 0x00;
- return conv;
-}
-
-/*
- * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
- * into Unix UTC (based 1970-01-01, in seconds).
- */
-struct timespec64 ksmbd_NTtimeToUnix(__le64 ntutc)
-{
- struct timespec64 ts;
-
- /* Subtract the NTFS time offset, then convert to 1s intervals. */
- s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
- u64 abs_t;
-
- /*
- * Unfortunately can not use normal 64 bit division on 32 bit arch, but
- * the alternative, do_div, does not work with negative numbers so have
- * to special case them
- */
- if (t < 0) {
- abs_t = -t;
- ts.tv_nsec = do_div(abs_t, 10000000) * 100;
- ts.tv_nsec = -ts.tv_nsec;
- ts.tv_sec = -abs_t;
- } else {
- abs_t = t;
- ts.tv_nsec = do_div(abs_t, 10000000) * 100;
- ts.tv_sec = abs_t;
- }
-
- return ts;
-}
-
-/* Convert the Unix UTC into NT UTC. */
-inline u64 ksmbd_UnixTimeToNT(struct timespec64 t)
-{
- /* Convert to 100ns intervals and then add the NTFS time offset. */
- return (u64)t.tv_sec * 10000000 + t.tv_nsec / 100 + NTFS_TIME_OFFSET;
-}
-
-inline long long ksmbd_systime(void)
-{
- struct timespec64 ts;
-
- ktime_get_real_ts64(&ts);
- return ksmbd_UnixTimeToNT(ts);
-}
diff --git a/fs/ksmbd/misc.h b/fs/ksmbd/misc.h
deleted file mode 100644
index 1facfcd21200..000000000000
--- a/fs/ksmbd/misc.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_MISC_H__
-#define __KSMBD_MISC_H__
-
-struct ksmbd_share_config;
-struct nls_table;
-struct kstat;
-struct ksmbd_file;
-
-int match_pattern(const char *str, size_t len, const char *pattern);
-int ksmbd_validate_filename(char *filename);
-int parse_stream_name(char *filename, char **stream_name, int *s_type);
-char *convert_to_nt_pathname(struct ksmbd_share_config *share,
- const struct path *path);
-int get_nlink(struct kstat *st);
-void ksmbd_conv_path_to_unix(char *path);
-void ksmbd_strip_last_slash(char *path);
-void ksmbd_conv_path_to_windows(char *path);
-char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name);
-char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
-char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);
-
-#define KSMBD_DIR_INFO_ALIGNMENT 8
-struct ksmbd_dir_info;
-char *ksmbd_convert_dir_info_name(struct ksmbd_dir_info *d_info,
- const struct nls_table *local_nls,
- int *conv_len);
-
-#define NTFS_TIME_OFFSET ((u64)(369 * 365 + 89) * 24 * 3600 * 10000000)
-struct timespec64 ksmbd_NTtimeToUnix(__le64 ntutc);
-u64 ksmbd_UnixTimeToNT(struct timespec64 t);
-long long ksmbd_systime(void);
-#endif /* __KSMBD_MISC_H__ */
diff --git a/fs/ksmbd/ndr.c b/fs/ksmbd/ndr.c
deleted file mode 100644
index 4d9e0b54e3db..000000000000
--- a/fs/ksmbd/ndr.c
+++ /dev/null
@@ -1,514 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2021 Samsung Electronics Co., Ltd.
- * Author(s): Namjae Jeon <linkinjeon@kernel.org>
- */
-
-#include <linux/fs.h>
-
-#include "glob.h"
-#include "ndr.h"
-
-static inline char *ndr_get_field(struct ndr *n)
-{
- return n->data + n->offset;
-}
-
-static int try_to_realloc_ndr_blob(struct ndr *n, size_t sz)
-{
- char *data;
-
- data = krealloc(n->data, n->offset + sz + 1024, GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- n->data = data;
- n->length += 1024;
- memset(n->data + n->offset, 0, 1024);
- return 0;
-}
-
-static int ndr_write_int16(struct ndr *n, __u16 value)
-{
- if (n->length <= n->offset + sizeof(value)) {
- int ret;
-
- ret = try_to_realloc_ndr_blob(n, sizeof(value));
- if (ret)
- return ret;
- }
-
- *(__le16 *)ndr_get_field(n) = cpu_to_le16(value);
- n->offset += sizeof(value);
- return 0;
-}
-
-static int ndr_write_int32(struct ndr *n, __u32 value)
-{
- if (n->length <= n->offset + sizeof(value)) {
- int ret;
-
- ret = try_to_realloc_ndr_blob(n, sizeof(value));
- if (ret)
- return ret;
- }
-
- *(__le32 *)ndr_get_field(n) = cpu_to_le32(value);
- n->offset += sizeof(value);
- return 0;
-}
-
-static int ndr_write_int64(struct ndr *n, __u64 value)
-{
- if (n->length <= n->offset + sizeof(value)) {
- int ret;
-
- ret = try_to_realloc_ndr_blob(n, sizeof(value));
- if (ret)
- return ret;
- }
-
- *(__le64 *)ndr_get_field(n) = cpu_to_le64(value);
- n->offset += sizeof(value);
- return 0;
-}
-
-static int ndr_write_bytes(struct ndr *n, void *value, size_t sz)
-{
- if (n->length <= n->offset + sz) {
- int ret;
-
- ret = try_to_realloc_ndr_blob(n, sz);
- if (ret)
- return ret;
- }
-
- memcpy(ndr_get_field(n), value, sz);
- n->offset += sz;
- return 0;
-}
-
-static int ndr_write_string(struct ndr *n, char *value)
-{
- size_t sz;
-
- sz = strlen(value) + 1;
- if (n->length <= n->offset + sz) {
- int ret;
-
- ret = try_to_realloc_ndr_blob(n, sz);
- if (ret)
- return ret;
- }
-
- memcpy(ndr_get_field(n), value, sz);
- n->offset += sz;
- n->offset = ALIGN(n->offset, 2);
- return 0;
-}
-
-static int ndr_read_string(struct ndr *n, void *value, size_t sz)
-{
- int len;
-
- if (n->offset + sz > n->length)
- return -EINVAL;
-
- len = strnlen(ndr_get_field(n), sz);
- if (value)
- memcpy(value, ndr_get_field(n), len);
- len++;
- n->offset += len;
- n->offset = ALIGN(n->offset, 2);
- return 0;
-}
-
-static int ndr_read_bytes(struct ndr *n, void *value, size_t sz)
-{
- if (n->offset + sz > n->length)
- return -EINVAL;
-
- if (value)
- memcpy(value, ndr_get_field(n), sz);
- n->offset += sz;
- return 0;
-}
-
-static int ndr_read_int16(struct ndr *n, __u16 *value)
-{
- if (n->offset + sizeof(__u16) > n->length)
- return -EINVAL;
-
- if (value)
- *value = le16_to_cpu(*(__le16 *)ndr_get_field(n));
- n->offset += sizeof(__u16);
- return 0;
-}
-
-static int ndr_read_int32(struct ndr *n, __u32 *value)
-{
- if (n->offset + sizeof(__u32) > n->length)
- return -EINVAL;
-
- if (value)
- *value = le32_to_cpu(*(__le32 *)ndr_get_field(n));
- n->offset += sizeof(__u32);
- return 0;
-}
-
-static int ndr_read_int64(struct ndr *n, __u64 *value)
-{
- if (n->offset + sizeof(__u64) > n->length)
- return -EINVAL;
-
- if (value)
- *value = le64_to_cpu(*(__le64 *)ndr_get_field(n));
- n->offset += sizeof(__u64);
- return 0;
-}
-
-int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
-{
- char hex_attr[12] = {0};
- int ret;
-
- n->offset = 0;
- n->length = 1024;
- n->data = kzalloc(n->length, GFP_KERNEL);
- if (!n->data)
- return -ENOMEM;
-
- if (da->version == 3) {
- snprintf(hex_attr, 10, "0x%x", da->attr);
- ret = ndr_write_string(n, hex_attr);
- } else {
- ret = ndr_write_string(n, "");
- }
- if (ret)
- return ret;
-
- ret = ndr_write_int16(n, da->version);
- if (ret)
- return ret;
-
- ret = ndr_write_int32(n, da->version);
- if (ret)
- return ret;
-
- ret = ndr_write_int32(n, da->flags);
- if (ret)
- return ret;
-
- ret = ndr_write_int32(n, da->attr);
- if (ret)
- return ret;
-
- if (da->version == 3) {
- ret = ndr_write_int32(n, da->ea_size);
- if (ret)
- return ret;
- ret = ndr_write_int64(n, da->size);
- if (ret)
- return ret;
- ret = ndr_write_int64(n, da->alloc_size);
- } else {
- ret = ndr_write_int64(n, da->itime);
- }
- if (ret)
- return ret;
-
- ret = ndr_write_int64(n, da->create_time);
- if (ret)
- return ret;
-
- if (da->version == 3)
- ret = ndr_write_int64(n, da->change_time);
- return ret;
-}
-
-int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
-{
- char hex_attr[12];
- unsigned int version2;
- int ret;
-
- n->offset = 0;
- ret = ndr_read_string(n, hex_attr, sizeof(hex_attr));
- if (ret)
- return ret;
-
- ret = ndr_read_int16(n, &da->version);
- if (ret)
- return ret;
-
- if (da->version != 3 && da->version != 4) {
- ksmbd_debug(VFS, "v%d version is not supported\n", da->version);
- return -EINVAL;
- }
-
- ret = ndr_read_int32(n, &version2);
- if (ret)
- return ret;
-
- if (da->version != version2) {
- ksmbd_debug(VFS, "ndr version mismatched(version: %d, version2: %d)\n",
- da->version, version2);
- return -EINVAL;
- }
-
- ret = ndr_read_int32(n, NULL);
- if (ret)
- return ret;
-
- ret = ndr_read_int32(n, &da->attr);
- if (ret)
- return ret;
-
- if (da->version == 4) {
- ret = ndr_read_int64(n, &da->itime);
- if (ret)
- return ret;
-
- ret = ndr_read_int64(n, &da->create_time);
- } else {
- ret = ndr_read_int32(n, NULL);
- if (ret)
- return ret;
-
- ret = ndr_read_int64(n, NULL);
- if (ret)
- return ret;
-
- ret = ndr_read_int64(n, NULL);
- if (ret)
- return ret;
-
- ret = ndr_read_int64(n, &da->create_time);
- if (ret)
- return ret;
-
- ret = ndr_read_int64(n, NULL);
- }
-
- return ret;
-}
-
-static int ndr_encode_posix_acl_entry(struct ndr *n, struct xattr_smb_acl *acl)
-{
- int i, ret;
-
- ret = ndr_write_int32(n, acl->count);
- if (ret)
- return ret;
-
- n->offset = ALIGN(n->offset, 8);
- ret = ndr_write_int32(n, acl->count);
- if (ret)
- return ret;
-
- ret = ndr_write_int32(n, 0);
- if (ret)
- return ret;
-
- for (i = 0; i < acl->count; i++) {
- n->offset = ALIGN(n->offset, 8);
- ret = ndr_write_int16(n, acl->entries[i].type);
- if (ret)
- return ret;
-
- ret = ndr_write_int16(n, acl->entries[i].type);
- if (ret)
- return ret;
-
- if (acl->entries[i].type == SMB_ACL_USER) {
- n->offset = ALIGN(n->offset, 8);
- ret = ndr_write_int64(n, acl->entries[i].uid);
- } else if (acl->entries[i].type == SMB_ACL_GROUP) {
- n->offset = ALIGN(n->offset, 8);
- ret = ndr_write_int64(n, acl->entries[i].gid);
- }
- if (ret)
- return ret;
-
- /* push permission */
- ret = ndr_write_int32(n, acl->entries[i].perm);
- }
-
- return ret;
-}
-
-int ndr_encode_posix_acl(struct ndr *n,
- struct user_namespace *user_ns,
- struct inode *inode,
- struct xattr_smb_acl *acl,
- struct xattr_smb_acl *def_acl)
-{
- unsigned int ref_id = 0x00020000;
- int ret;
- vfsuid_t vfsuid;
- vfsgid_t vfsgid;
-
- n->offset = 0;
- n->length = 1024;
- n->data = kzalloc(n->length, GFP_KERNEL);
- if (!n->data)
- return -ENOMEM;
-
- if (acl) {
- /* ACL ACCESS */
- ret = ndr_write_int32(n, ref_id);
- ref_id += 4;
- } else {
- ret = ndr_write_int32(n, 0);
- }
- if (ret)
- return ret;
-
- if (def_acl) {
- /* DEFAULT ACL ACCESS */
- ret = ndr_write_int32(n, ref_id);
- ref_id += 4;
- } else {
- ret = ndr_write_int32(n, 0);
- }
- if (ret)
- return ret;
-
- vfsuid = i_uid_into_vfsuid(user_ns, inode);
- ret = ndr_write_int64(n, from_kuid(&init_user_ns, vfsuid_into_kuid(vfsuid)));
- if (ret)
- return ret;
- vfsgid = i_gid_into_vfsgid(user_ns, inode);
- ret = ndr_write_int64(n, from_kgid(&init_user_ns, vfsgid_into_kgid(vfsgid)));
- if (ret)
- return ret;
- ret = ndr_write_int32(n, inode->i_mode);
- if (ret)
- return ret;
-
- if (acl) {
- ret = ndr_encode_posix_acl_entry(n, acl);
- if (def_acl && !ret)
- ret = ndr_encode_posix_acl_entry(n, def_acl);
- }
- return ret;
-}
-
-int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
-{
- unsigned int ref_id = 0x00020004;
- int ret;
-
- n->offset = 0;
- n->length = 2048;
- n->data = kzalloc(n->length, GFP_KERNEL);
- if (!n->data)
- return -ENOMEM;
-
- ret = ndr_write_int16(n, acl->version);
- if (ret)
- return ret;
-
- ret = ndr_write_int32(n, acl->version);
- if (ret)
- return ret;
-
- ret = ndr_write_int16(n, 2);
- if (ret)
- return ret;
-
- ret = ndr_write_int32(n, ref_id);
- if (ret)
- return ret;
-
- /* push hash type and hash 64bytes */
- ret = ndr_write_int16(n, acl->hash_type);
- if (ret)
- return ret;
-
- ret = ndr_write_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
- if (ret)
- return ret;
-
- ret = ndr_write_bytes(n, acl->desc, acl->desc_len);
- if (ret)
- return ret;
-
- ret = ndr_write_int64(n, acl->current_time);
- if (ret)
- return ret;
-
- ret = ndr_write_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
- if (ret)
- return ret;
-
- /* push ndr for security descriptor */
- ret = ndr_write_bytes(n, acl->sd_buf, acl->sd_size);
- return ret;
-}
-
-int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
-{
- unsigned int version2;
- int ret;
-
- n->offset = 0;
- ret = ndr_read_int16(n, &acl->version);
- if (ret)
- return ret;
- if (acl->version != 4) {
- ksmbd_debug(VFS, "v%d version is not supported\n", acl->version);
- return -EINVAL;
- }
-
- ret = ndr_read_int32(n, &version2);
- if (ret)
- return ret;
- if (acl->version != version2) {
- ksmbd_debug(VFS, "ndr version mismatched(version: %d, version2: %d)\n",
- acl->version, version2);
- return -EINVAL;
- }
-
- /* Read Level */
- ret = ndr_read_int16(n, NULL);
- if (ret)
- return ret;
-
- /* Read Ref Id */
- ret = ndr_read_int32(n, NULL);
- if (ret)
- return ret;
-
- ret = ndr_read_int16(n, &acl->hash_type);
- if (ret)
- return ret;
-
- ret = ndr_read_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
- if (ret)
- return ret;
-
- ndr_read_bytes(n, acl->desc, 10);
- if (strncmp(acl->desc, "posix_acl", 9)) {
- pr_err("Invalid acl description : %s\n", acl->desc);
- return -EINVAL;
- }
-
- /* Read Time */
- ret = ndr_read_int64(n, NULL);
- if (ret)
- return ret;
-
- /* Read Posix ACL hash */
- ret = ndr_read_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
- if (ret)
- return ret;
-
- acl->sd_size = n->length - n->offset;
- acl->sd_buf = kzalloc(acl->sd_size, GFP_KERNEL);
- if (!acl->sd_buf)
- return -ENOMEM;
-
- ret = ndr_read_bytes(n, acl->sd_buf, acl->sd_size);
- return ret;
-}
diff --git a/fs/ksmbd/ndr.h b/fs/ksmbd/ndr.h
deleted file mode 100644
index 60ca265d1bb0..000000000000
--- a/fs/ksmbd/ndr.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2020 Samsung Electronics Co., Ltd.
- * Author(s): Namjae Jeon <linkinjeon@kernel.org>
- */
-
-struct ndr {
- char *data;
- int offset;
- int length;
-};
-
-#define NDR_NTSD_OFFSETOF 0xA0
-
-int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
-int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
-int ndr_encode_posix_acl(struct ndr *n, struct user_namespace *user_ns,
- struct inode *inode, struct xattr_smb_acl *acl,
- struct xattr_smb_acl *def_acl);
-int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl);
-int ndr_encode_v3_ntacl(struct ndr *n, struct xattr_ntacl *acl);
-int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl);
diff --git a/fs/ksmbd/nterr.h b/fs/ksmbd/nterr.h
deleted file mode 100644
index 2f358f88a018..000000000000
--- a/fs/ksmbd/nterr.h
+++ /dev/null
@@ -1,543 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Unix SMB/Netbios implementation.
- * Version 1.9.
- * NT error code constants
- * Copyright (C) Andrew Tridgell 1992-2000
- * Copyright (C) John H Terpstra 1996-2000
- * Copyright (C) Luke Kenneth Casson Leighton 1996-2000
- * Copyright (C) Paul Ashton 1998-2000
- */
-
-#ifndef _NTERR_H
-#define _NTERR_H
-
-/* Win32 Status codes. */
-#define NT_STATUS_MORE_ENTRIES 0x0105
-#define NT_ERROR_INVALID_PARAMETER 0x0057
-#define NT_ERROR_INSUFFICIENT_BUFFER 0x007a
-#define NT_STATUS_1804 0x070c
-#define NT_STATUS_NOTIFY_ENUM_DIR 0x010c
-#define NT_STATUS_INVALID_LOCK_RANGE (0xC0000000 | 0x01a1)
-/*
- * Win32 Error codes extracted using a loop in smbclient then printing a netmon
- * sniff to a file.
- */
-
-#define NT_STATUS_OK 0x0000
-#define NT_STATUS_SOME_UNMAPPED 0x0107
-#define NT_STATUS_BUFFER_OVERFLOW 0x80000005
-#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
-#define NT_STATUS_MEDIA_CHANGED 0x8000001c
-#define NT_STATUS_END_OF_MEDIA 0x8000001e
-#define NT_STATUS_MEDIA_CHECK 0x80000020
-#define NT_STATUS_NO_DATA_DETECTED 0x8000001c
-#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d
-#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288
-#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288
-#define NT_STATUS_UNSUCCESSFUL (0xC0000000 | 0x0001)
-#define NT_STATUS_NOT_IMPLEMENTED (0xC0000000 | 0x0002)
-#define NT_STATUS_INVALID_INFO_CLASS (0xC0000000 | 0x0003)
-#define NT_STATUS_INFO_LENGTH_MISMATCH (0xC0000000 | 0x0004)
-#define NT_STATUS_ACCESS_VIOLATION (0xC0000000 | 0x0005)
-#define NT_STATUS_IN_PAGE_ERROR (0xC0000000 | 0x0006)
-#define NT_STATUS_PAGEFILE_QUOTA (0xC0000000 | 0x0007)
-#define NT_STATUS_INVALID_HANDLE (0xC0000000 | 0x0008)
-#define NT_STATUS_BAD_INITIAL_STACK (0xC0000000 | 0x0009)
-#define NT_STATUS_BAD_INITIAL_PC (0xC0000000 | 0x000a)
-#define NT_STATUS_INVALID_CID (0xC0000000 | 0x000b)
-#define NT_STATUS_TIMER_NOT_CANCELED (0xC0000000 | 0x000c)
-#define NT_STATUS_INVALID_PARAMETER (0xC0000000 | 0x000d)
-#define NT_STATUS_NO_SUCH_DEVICE (0xC0000000 | 0x000e)
-#define NT_STATUS_NO_SUCH_FILE (0xC0000000 | 0x000f)
-#define NT_STATUS_INVALID_DEVICE_REQUEST (0xC0000000 | 0x0010)
-#define NT_STATUS_END_OF_FILE (0xC0000000 | 0x0011)
-#define NT_STATUS_WRONG_VOLUME (0xC0000000 | 0x0012)
-#define NT_STATUS_NO_MEDIA_IN_DEVICE (0xC0000000 | 0x0013)
-#define NT_STATUS_UNRECOGNIZED_MEDIA (0xC0000000 | 0x0014)
-#define NT_STATUS_NONEXISTENT_SECTOR (0xC0000000 | 0x0015)
-#define NT_STATUS_MORE_PROCESSING_REQUIRED (0xC0000000 | 0x0016)
-#define NT_STATUS_NO_MEMORY (0xC0000000 | 0x0017)
-#define NT_STATUS_CONFLICTING_ADDRESSES (0xC0000000 | 0x0018)
-#define NT_STATUS_NOT_MAPPED_VIEW (0xC0000000 | 0x0019)
-#define NT_STATUS_UNABLE_TO_FREE_VM (0x80000000 | 0x001a)
-#define NT_STATUS_UNABLE_TO_DELETE_SECTION (0xC0000000 | 0x001b)
-#define NT_STATUS_INVALID_SYSTEM_SERVICE (0xC0000000 | 0x001c)
-#define NT_STATUS_ILLEGAL_INSTRUCTION (0xC0000000 | 0x001d)
-#define NT_STATUS_INVALID_LOCK_SEQUENCE (0xC0000000 | 0x001e)
-#define NT_STATUS_INVALID_VIEW_SIZE (0xC0000000 | 0x001f)
-#define NT_STATUS_INVALID_FILE_FOR_SECTION (0xC0000000 | 0x0020)
-#define NT_STATUS_ALREADY_COMMITTED (0xC0000000 | 0x0021)
-#define NT_STATUS_ACCESS_DENIED (0xC0000000 | 0x0022)
-#define NT_STATUS_BUFFER_TOO_SMALL (0xC0000000 | 0x0023)
-#define NT_STATUS_OBJECT_TYPE_MISMATCH (0xC0000000 | 0x0024)
-#define NT_STATUS_NONCONTINUABLE_EXCEPTION (0xC0000000 | 0x0025)
-#define NT_STATUS_INVALID_DISPOSITION (0xC0000000 | 0x0026)
-#define NT_STATUS_UNWIND (0xC0000000 | 0x0027)
-#define NT_STATUS_BAD_STACK (0xC0000000 | 0x0028)
-#define NT_STATUS_INVALID_UNWIND_TARGET (0xC0000000 | 0x0029)
-#define NT_STATUS_NOT_LOCKED (0xC0000000 | 0x002a)
-#define NT_STATUS_PARITY_ERROR (0xC0000000 | 0x002b)
-#define NT_STATUS_UNABLE_TO_DECOMMIT_VM (0xC0000000 | 0x002c)
-#define NT_STATUS_NOT_COMMITTED (0xC0000000 | 0x002d)
-#define NT_STATUS_INVALID_PORT_ATTRIBUTES (0xC0000000 | 0x002e)
-#define NT_STATUS_PORT_MESSAGE_TOO_LONG (0xC0000000 | 0x002f)
-#define NT_STATUS_INVALID_PARAMETER_MIX (0xC0000000 | 0x0030)
-#define NT_STATUS_INVALID_QUOTA_LOWER (0xC0000000 | 0x0031)
-#define NT_STATUS_DISK_CORRUPT_ERROR (0xC0000000 | 0x0032)
-#define NT_STATUS_OBJECT_NAME_INVALID (0xC0000000 | 0x0033)
-#define NT_STATUS_OBJECT_NAME_NOT_FOUND (0xC0000000 | 0x0034)
-#define NT_STATUS_OBJECT_NAME_COLLISION (0xC0000000 | 0x0035)
-#define NT_STATUS_HANDLE_NOT_WAITABLE (0xC0000000 | 0x0036)
-#define NT_STATUS_PORT_DISCONNECTED (0xC0000000 | 0x0037)
-#define NT_STATUS_DEVICE_ALREADY_ATTACHED (0xC0000000 | 0x0038)
-#define NT_STATUS_OBJECT_PATH_INVALID (0xC0000000 | 0x0039)
-#define NT_STATUS_OBJECT_PATH_NOT_FOUND (0xC0000000 | 0x003a)
-#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD (0xC0000000 | 0x003b)
-#define NT_STATUS_DATA_OVERRUN (0xC0000000 | 0x003c)
-#define NT_STATUS_DATA_LATE_ERROR (0xC0000000 | 0x003d)
-#define NT_STATUS_DATA_ERROR (0xC0000000 | 0x003e)
-#define NT_STATUS_CRC_ERROR (0xC0000000 | 0x003f)
-#define NT_STATUS_SECTION_TOO_BIG (0xC0000000 | 0x0040)
-#define NT_STATUS_PORT_CONNECTION_REFUSED (0xC0000000 | 0x0041)
-#define NT_STATUS_INVALID_PORT_HANDLE (0xC0000000 | 0x0042)
-#define NT_STATUS_SHARING_VIOLATION (0xC0000000 | 0x0043)
-#define NT_STATUS_QUOTA_EXCEEDED (0xC0000000 | 0x0044)
-#define NT_STATUS_INVALID_PAGE_PROTECTION (0xC0000000 | 0x0045)
-#define NT_STATUS_MUTANT_NOT_OWNED (0xC0000000 | 0x0046)
-#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED (0xC0000000 | 0x0047)
-#define NT_STATUS_PORT_ALREADY_SET (0xC0000000 | 0x0048)
-#define NT_STATUS_SECTION_NOT_IMAGE (0xC0000000 | 0x0049)
-#define NT_STATUS_SUSPEND_COUNT_EXCEEDED (0xC0000000 | 0x004a)
-#define NT_STATUS_THREAD_IS_TERMINATING (0xC0000000 | 0x004b)
-#define NT_STATUS_BAD_WORKING_SET_LIMIT (0xC0000000 | 0x004c)
-#define NT_STATUS_INCOMPATIBLE_FILE_MAP (0xC0000000 | 0x004d)
-#define NT_STATUS_SECTION_PROTECTION (0xC0000000 | 0x004e)
-#define NT_STATUS_EAS_NOT_SUPPORTED (0xC0000000 | 0x004f)
-#define NT_STATUS_EA_TOO_LARGE (0xC0000000 | 0x0050)
-#define NT_STATUS_NONEXISTENT_EA_ENTRY (0xC0000000 | 0x0051)
-#define NT_STATUS_NO_EAS_ON_FILE (0xC0000000 | 0x0052)
-#define NT_STATUS_EA_CORRUPT_ERROR (0xC0000000 | 0x0053)
-#define NT_STATUS_FILE_LOCK_CONFLICT (0xC0000000 | 0x0054)
-#define NT_STATUS_LOCK_NOT_GRANTED (0xC0000000 | 0x0055)
-#define NT_STATUS_DELETE_PENDING (0xC0000000 | 0x0056)
-#define NT_STATUS_CTL_FILE_NOT_SUPPORTED (0xC0000000 | 0x0057)
-#define NT_STATUS_UNKNOWN_REVISION (0xC0000000 | 0x0058)
-#define NT_STATUS_REVISION_MISMATCH (0xC0000000 | 0x0059)
-#define NT_STATUS_INVALID_OWNER (0xC0000000 | 0x005a)
-#define NT_STATUS_INVALID_PRIMARY_GROUP (0xC0000000 | 0x005b)
-#define NT_STATUS_NO_IMPERSONATION_TOKEN (0xC0000000 | 0x005c)
-#define NT_STATUS_CANT_DISABLE_MANDATORY (0xC0000000 | 0x005d)
-#define NT_STATUS_NO_LOGON_SERVERS (0xC0000000 | 0x005e)
-#define NT_STATUS_NO_SUCH_LOGON_SESSION (0xC0000000 | 0x005f)
-#define NT_STATUS_NO_SUCH_PRIVILEGE (0xC0000000 | 0x0060)
-#define NT_STATUS_PRIVILEGE_NOT_HELD (0xC0000000 | 0x0061)
-#define NT_STATUS_INVALID_ACCOUNT_NAME (0xC0000000 | 0x0062)
-#define NT_STATUS_USER_EXISTS (0xC0000000 | 0x0063)
-#define NT_STATUS_NO_SUCH_USER (0xC0000000 | 0x0064)
-#define NT_STATUS_GROUP_EXISTS (0xC0000000 | 0x0065)
-#define NT_STATUS_NO_SUCH_GROUP (0xC0000000 | 0x0066)
-#define NT_STATUS_MEMBER_IN_GROUP (0xC0000000 | 0x0067)
-#define NT_STATUS_MEMBER_NOT_IN_GROUP (0xC0000000 | 0x0068)
-#define NT_STATUS_LAST_ADMIN (0xC0000000 | 0x0069)
-#define NT_STATUS_WRONG_PASSWORD (0xC0000000 | 0x006a)
-#define NT_STATUS_ILL_FORMED_PASSWORD (0xC0000000 | 0x006b)
-#define NT_STATUS_PASSWORD_RESTRICTION (0xC0000000 | 0x006c)
-#define NT_STATUS_LOGON_FAILURE (0xC0000000 | 0x006d)
-#define NT_STATUS_ACCOUNT_RESTRICTION (0xC0000000 | 0x006e)
-#define NT_STATUS_INVALID_LOGON_HOURS (0xC0000000 | 0x006f)
-#define NT_STATUS_INVALID_WORKSTATION (0xC0000000 | 0x0070)
-#define NT_STATUS_PASSWORD_EXPIRED (0xC0000000 | 0x0071)
-#define NT_STATUS_ACCOUNT_DISABLED (0xC0000000 | 0x0072)
-#define NT_STATUS_NONE_MAPPED (0xC0000000 | 0x0073)
-#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED (0xC0000000 | 0x0074)
-#define NT_STATUS_LUIDS_EXHAUSTED (0xC0000000 | 0x0075)
-#define NT_STATUS_INVALID_SUB_AUTHORITY (0xC0000000 | 0x0076)
-#define NT_STATUS_INVALID_ACL (0xC0000000 | 0x0077)
-#define NT_STATUS_INVALID_SID (0xC0000000 | 0x0078)
-#define NT_STATUS_INVALID_SECURITY_DESCR (0xC0000000 | 0x0079)
-#define NT_STATUS_PROCEDURE_NOT_FOUND (0xC0000000 | 0x007a)
-#define NT_STATUS_INVALID_IMAGE_FORMAT (0xC0000000 | 0x007b)
-#define NT_STATUS_NO_TOKEN (0xC0000000 | 0x007c)
-#define NT_STATUS_BAD_INHERITANCE_ACL (0xC0000000 | 0x007d)
-#define NT_STATUS_RANGE_NOT_LOCKED (0xC0000000 | 0x007e)
-#define NT_STATUS_DISK_FULL (0xC0000000 | 0x007f)
-#define NT_STATUS_SERVER_DISABLED (0xC0000000 | 0x0080)
-#define NT_STATUS_SERVER_NOT_DISABLED (0xC0000000 | 0x0081)
-#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED (0xC0000000 | 0x0082)
-#define NT_STATUS_GUIDS_EXHAUSTED (0xC0000000 | 0x0083)
-#define NT_STATUS_INVALID_ID_AUTHORITY (0xC0000000 | 0x0084)
-#define NT_STATUS_AGENTS_EXHAUSTED (0xC0000000 | 0x0085)
-#define NT_STATUS_INVALID_VOLUME_LABEL (0xC0000000 | 0x0086)
-#define NT_STATUS_SECTION_NOT_EXTENDED (0xC0000000 | 0x0087)
-#define NT_STATUS_NOT_MAPPED_DATA (0xC0000000 | 0x0088)
-#define NT_STATUS_RESOURCE_DATA_NOT_FOUND (0xC0000000 | 0x0089)
-#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND (0xC0000000 | 0x008a)
-#define NT_STATUS_RESOURCE_NAME_NOT_FOUND (0xC0000000 | 0x008b)
-#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED (0xC0000000 | 0x008c)
-#define NT_STATUS_FLOAT_DENORMAL_OPERAND (0xC0000000 | 0x008d)
-#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO (0xC0000000 | 0x008e)
-#define NT_STATUS_FLOAT_INEXACT_RESULT (0xC0000000 | 0x008f)
-#define NT_STATUS_FLOAT_INVALID_OPERATION (0xC0000000 | 0x0090)
-#define NT_STATUS_FLOAT_OVERFLOW (0xC0000000 | 0x0091)
-#define NT_STATUS_FLOAT_STACK_CHECK (0xC0000000 | 0x0092)
-#define NT_STATUS_FLOAT_UNDERFLOW (0xC0000000 | 0x0093)
-#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO (0xC0000000 | 0x0094)
-#define NT_STATUS_INTEGER_OVERFLOW (0xC0000000 | 0x0095)
-#define NT_STATUS_PRIVILEGED_INSTRUCTION (0xC0000000 | 0x0096)
-#define NT_STATUS_TOO_MANY_PAGING_FILES (0xC0000000 | 0x0097)
-#define NT_STATUS_FILE_INVALID (0xC0000000 | 0x0098)
-#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED (0xC0000000 | 0x0099)
-#define NT_STATUS_INSUFFICIENT_RESOURCES (0xC0000000 | 0x009a)
-#define NT_STATUS_DFS_EXIT_PATH_FOUND (0xC0000000 | 0x009b)
-#define NT_STATUS_DEVICE_DATA_ERROR (0xC0000000 | 0x009c)
-#define NT_STATUS_DEVICE_NOT_CONNECTED (0xC0000000 | 0x009d)
-#define NT_STATUS_DEVICE_POWER_FAILURE (0xC0000000 | 0x009e)
-#define NT_STATUS_FREE_VM_NOT_AT_BASE (0xC0000000 | 0x009f)
-#define NT_STATUS_MEMORY_NOT_ALLOCATED (0xC0000000 | 0x00a0)
-#define NT_STATUS_WORKING_SET_QUOTA (0xC0000000 | 0x00a1)
-#define NT_STATUS_MEDIA_WRITE_PROTECTED (0xC0000000 | 0x00a2)
-#define NT_STATUS_DEVICE_NOT_READY (0xC0000000 | 0x00a3)
-#define NT_STATUS_INVALID_GROUP_ATTRIBUTES (0xC0000000 | 0x00a4)
-#define NT_STATUS_BAD_IMPERSONATION_LEVEL (0xC0000000 | 0x00a5)
-#define NT_STATUS_CANT_OPEN_ANONYMOUS (0xC0000000 | 0x00a6)
-#define NT_STATUS_BAD_VALIDATION_CLASS (0xC0000000 | 0x00a7)
-#define NT_STATUS_BAD_TOKEN_TYPE (0xC0000000 | 0x00a8)
-#define NT_STATUS_BAD_MASTER_BOOT_RECORD (0xC0000000 | 0x00a9)
-#define NT_STATUS_INSTRUCTION_MISALIGNMENT (0xC0000000 | 0x00aa)
-#define NT_STATUS_INSTANCE_NOT_AVAILABLE (0xC0000000 | 0x00ab)
-#define NT_STATUS_PIPE_NOT_AVAILABLE (0xC0000000 | 0x00ac)
-#define NT_STATUS_INVALID_PIPE_STATE (0xC0000000 | 0x00ad)
-#define NT_STATUS_PIPE_BUSY (0xC0000000 | 0x00ae)
-#define NT_STATUS_ILLEGAL_FUNCTION (0xC0000000 | 0x00af)
-#define NT_STATUS_PIPE_DISCONNECTED (0xC0000000 | 0x00b0)
-#define NT_STATUS_PIPE_CLOSING (0xC0000000 | 0x00b1)
-#define NT_STATUS_PIPE_CONNECTED (0xC0000000 | 0x00b2)
-#define NT_STATUS_PIPE_LISTENING (0xC0000000 | 0x00b3)
-#define NT_STATUS_INVALID_READ_MODE (0xC0000000 | 0x00b4)
-#define NT_STATUS_IO_TIMEOUT (0xC0000000 | 0x00b5)
-#define NT_STATUS_FILE_FORCED_CLOSED (0xC0000000 | 0x00b6)
-#define NT_STATUS_PROFILING_NOT_STARTED (0xC0000000 | 0x00b7)
-#define NT_STATUS_PROFILING_NOT_STOPPED (0xC0000000 | 0x00b8)
-#define NT_STATUS_COULD_NOT_INTERPRET (0xC0000000 | 0x00b9)
-#define NT_STATUS_FILE_IS_A_DIRECTORY (0xC0000000 | 0x00ba)
-#define NT_STATUS_NOT_SUPPORTED (0xC0000000 | 0x00bb)
-#define NT_STATUS_REMOTE_NOT_LISTENING (0xC0000000 | 0x00bc)
-#define NT_STATUS_DUPLICATE_NAME (0xC0000000 | 0x00bd)
-#define NT_STATUS_BAD_NETWORK_PATH (0xC0000000 | 0x00be)
-#define NT_STATUS_NETWORK_BUSY (0xC0000000 | 0x00bf)
-#define NT_STATUS_DEVICE_DOES_NOT_EXIST (0xC0000000 | 0x00c0)
-#define NT_STATUS_TOO_MANY_COMMANDS (0xC0000000 | 0x00c1)
-#define NT_STATUS_ADAPTER_HARDWARE_ERROR (0xC0000000 | 0x00c2)
-#define NT_STATUS_INVALID_NETWORK_RESPONSE (0xC0000000 | 0x00c3)
-#define NT_STATUS_UNEXPECTED_NETWORK_ERROR (0xC0000000 | 0x00c4)
-#define NT_STATUS_BAD_REMOTE_ADAPTER (0xC0000000 | 0x00c5)
-#define NT_STATUS_PRINT_QUEUE_FULL (0xC0000000 | 0x00c6)
-#define NT_STATUS_NO_SPOOL_SPACE (0xC0000000 | 0x00c7)
-#define NT_STATUS_PRINT_CANCELLED (0xC0000000 | 0x00c8)
-#define NT_STATUS_NETWORK_NAME_DELETED (0xC0000000 | 0x00c9)
-#define NT_STATUS_NETWORK_ACCESS_DENIED (0xC0000000 | 0x00ca)
-#define NT_STATUS_BAD_DEVICE_TYPE (0xC0000000 | 0x00cb)
-#define NT_STATUS_BAD_NETWORK_NAME (0xC0000000 | 0x00cc)
-#define NT_STATUS_TOO_MANY_NAMES (0xC0000000 | 0x00cd)
-#define NT_STATUS_TOO_MANY_SESSIONS (0xC0000000 | 0x00ce)
-#define NT_STATUS_SHARING_PAUSED (0xC0000000 | 0x00cf)
-#define NT_STATUS_REQUEST_NOT_ACCEPTED (0xC0000000 | 0x00d0)
-#define NT_STATUS_REDIRECTOR_PAUSED (0xC0000000 | 0x00d1)
-#define NT_STATUS_NET_WRITE_FAULT (0xC0000000 | 0x00d2)
-#define NT_STATUS_PROFILING_AT_LIMIT (0xC0000000 | 0x00d3)
-#define NT_STATUS_NOT_SAME_DEVICE (0xC0000000 | 0x00d4)
-#define NT_STATUS_FILE_RENAMED (0xC0000000 | 0x00d5)
-#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED (0xC0000000 | 0x00d6)
-#define NT_STATUS_NO_SECURITY_ON_OBJECT (0xC0000000 | 0x00d7)
-#define NT_STATUS_CANT_WAIT (0xC0000000 | 0x00d8)
-#define NT_STATUS_PIPE_EMPTY (0xC0000000 | 0x00d9)
-#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO (0xC0000000 | 0x00da)
-#define NT_STATUS_CANT_TERMINATE_SELF (0xC0000000 | 0x00db)
-#define NT_STATUS_INVALID_SERVER_STATE (0xC0000000 | 0x00dc)
-#define NT_STATUS_INVALID_DOMAIN_STATE (0xC0000000 | 0x00dd)
-#define NT_STATUS_INVALID_DOMAIN_ROLE (0xC0000000 | 0x00de)
-#define NT_STATUS_NO_SUCH_DOMAIN (0xC0000000 | 0x00df)
-#define NT_STATUS_DOMAIN_EXISTS (0xC0000000 | 0x00e0)
-#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED (0xC0000000 | 0x00e1)
-#define NT_STATUS_OPLOCK_NOT_GRANTED (0xC0000000 | 0x00e2)
-#define NT_STATUS_INVALID_OPLOCK_PROTOCOL (0xC0000000 | 0x00e3)
-#define NT_STATUS_INTERNAL_DB_CORRUPTION (0xC0000000 | 0x00e4)
-#define NT_STATUS_INTERNAL_ERROR (0xC0000000 | 0x00e5)
-#define NT_STATUS_GENERIC_NOT_MAPPED (0xC0000000 | 0x00e6)
-#define NT_STATUS_BAD_DESCRIPTOR_FORMAT (0xC0000000 | 0x00e7)
-#define NT_STATUS_INVALID_USER_BUFFER (0xC0000000 | 0x00e8)
-#define NT_STATUS_UNEXPECTED_IO_ERROR (0xC0000000 | 0x00e9)
-#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR (0xC0000000 | 0x00ea)
-#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR (0xC0000000 | 0x00eb)
-#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR (0xC0000000 | 0x00ec)
-#define NT_STATUS_NOT_LOGON_PROCESS (0xC0000000 | 0x00ed)
-#define NT_STATUS_LOGON_SESSION_EXISTS (0xC0000000 | 0x00ee)
-#define NT_STATUS_INVALID_PARAMETER_1 (0xC0000000 | 0x00ef)
-#define NT_STATUS_INVALID_PARAMETER_2 (0xC0000000 | 0x00f0)
-#define NT_STATUS_INVALID_PARAMETER_3 (0xC0000000 | 0x00f1)
-#define NT_STATUS_INVALID_PARAMETER_4 (0xC0000000 | 0x00f2)
-#define NT_STATUS_INVALID_PARAMETER_5 (0xC0000000 | 0x00f3)
-#define NT_STATUS_INVALID_PARAMETER_6 (0xC0000000 | 0x00f4)
-#define NT_STATUS_INVALID_PARAMETER_7 (0xC0000000 | 0x00f5)
-#define NT_STATUS_INVALID_PARAMETER_8 (0xC0000000 | 0x00f6)
-#define NT_STATUS_INVALID_PARAMETER_9 (0xC0000000 | 0x00f7)
-#define NT_STATUS_INVALID_PARAMETER_10 (0xC0000000 | 0x00f8)
-#define NT_STATUS_INVALID_PARAMETER_11 (0xC0000000 | 0x00f9)
-#define NT_STATUS_INVALID_PARAMETER_12 (0xC0000000 | 0x00fa)
-#define NT_STATUS_REDIRECTOR_NOT_STARTED (0xC0000000 | 0x00fb)
-#define NT_STATUS_REDIRECTOR_STARTED (0xC0000000 | 0x00fc)
-#define NT_STATUS_STACK_OVERFLOW (0xC0000000 | 0x00fd)
-#define NT_STATUS_NO_SUCH_PACKAGE (0xC0000000 | 0x00fe)
-#define NT_STATUS_BAD_FUNCTION_TABLE (0xC0000000 | 0x00ff)
-#define NT_STATUS_DIRECTORY_NOT_EMPTY (0xC0000000 | 0x0101)
-#define NT_STATUS_FILE_CORRUPT_ERROR (0xC0000000 | 0x0102)
-#define NT_STATUS_NOT_A_DIRECTORY (0xC0000000 | 0x0103)
-#define NT_STATUS_BAD_LOGON_SESSION_STATE (0xC0000000 | 0x0104)
-#define NT_STATUS_LOGON_SESSION_COLLISION (0xC0000000 | 0x0105)
-#define NT_STATUS_NAME_TOO_LONG (0xC0000000 | 0x0106)
-#define NT_STATUS_FILES_OPEN (0xC0000000 | 0x0107)
-#define NT_STATUS_CONNECTION_IN_USE (0xC0000000 | 0x0108)
-#define NT_STATUS_MESSAGE_NOT_FOUND (0xC0000000 | 0x0109)
-#define NT_STATUS_PROCESS_IS_TERMINATING (0xC0000000 | 0x010a)
-#define NT_STATUS_INVALID_LOGON_TYPE (0xC0000000 | 0x010b)
-#define NT_STATUS_NO_GUID_TRANSLATION (0xC0000000 | 0x010c)
-#define NT_STATUS_CANNOT_IMPERSONATE (0xC0000000 | 0x010d)
-#define NT_STATUS_IMAGE_ALREADY_LOADED (0xC0000000 | 0x010e)
-#define NT_STATUS_ABIOS_NOT_PRESENT (0xC0000000 | 0x010f)
-#define NT_STATUS_ABIOS_LID_NOT_EXIST (0xC0000000 | 0x0110)
-#define NT_STATUS_ABIOS_LID_ALREADY_OWNED (0xC0000000 | 0x0111)
-#define NT_STATUS_ABIOS_NOT_LID_OWNER (0xC0000000 | 0x0112)
-#define NT_STATUS_ABIOS_INVALID_COMMAND (0xC0000000 | 0x0113)
-#define NT_STATUS_ABIOS_INVALID_LID (0xC0000000 | 0x0114)
-#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE (0xC0000000 | 0x0115)
-#define NT_STATUS_ABIOS_INVALID_SELECTOR (0xC0000000 | 0x0116)
-#define NT_STATUS_NO_LDT (0xC0000000 | 0x0117)
-#define NT_STATUS_INVALID_LDT_SIZE (0xC0000000 | 0x0118)
-#define NT_STATUS_INVALID_LDT_OFFSET (0xC0000000 | 0x0119)
-#define NT_STATUS_INVALID_LDT_DESCRIPTOR (0xC0000000 | 0x011a)
-#define NT_STATUS_INVALID_IMAGE_NE_FORMAT (0xC0000000 | 0x011b)
-#define NT_STATUS_RXACT_INVALID_STATE (0xC0000000 | 0x011c)
-#define NT_STATUS_RXACT_COMMIT_FAILURE (0xC0000000 | 0x011d)
-#define NT_STATUS_MAPPED_FILE_SIZE_ZERO (0xC0000000 | 0x011e)
-#define NT_STATUS_TOO_MANY_OPENED_FILES (0xC0000000 | 0x011f)
-#define NT_STATUS_CANCELLED (0xC0000000 | 0x0120)
-#define NT_STATUS_CANNOT_DELETE (0xC0000000 | 0x0121)
-#define NT_STATUS_INVALID_COMPUTER_NAME (0xC0000000 | 0x0122)
-#define NT_STATUS_FILE_DELETED (0xC0000000 | 0x0123)
-#define NT_STATUS_SPECIAL_ACCOUNT (0xC0000000 | 0x0124)
-#define NT_STATUS_SPECIAL_GROUP (0xC0000000 | 0x0125)
-#define NT_STATUS_SPECIAL_USER (0xC0000000 | 0x0126)
-#define NT_STATUS_MEMBERS_PRIMARY_GROUP (0xC0000000 | 0x0127)
-#define NT_STATUS_FILE_CLOSED (0xC0000000 | 0x0128)
-#define NT_STATUS_TOO_MANY_THREADS (0xC0000000 | 0x0129)
-#define NT_STATUS_THREAD_NOT_IN_PROCESS (0xC0000000 | 0x012a)
-#define NT_STATUS_TOKEN_ALREADY_IN_USE (0xC0000000 | 0x012b)
-#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED (0xC0000000 | 0x012c)
-#define NT_STATUS_COMMITMENT_LIMIT (0xC0000000 | 0x012d)
-#define NT_STATUS_INVALID_IMAGE_LE_FORMAT (0xC0000000 | 0x012e)
-#define NT_STATUS_INVALID_IMAGE_NOT_MZ (0xC0000000 | 0x012f)
-#define NT_STATUS_INVALID_IMAGE_PROTECT (0xC0000000 | 0x0130)
-#define NT_STATUS_INVALID_IMAGE_WIN_16 (0xC0000000 | 0x0131)
-#define NT_STATUS_LOGON_SERVER_CONFLICT (0xC0000000 | 0x0132)
-#define NT_STATUS_TIME_DIFFERENCE_AT_DC (0xC0000000 | 0x0133)
-#define NT_STATUS_SYNCHRONIZATION_REQUIRED (0xC0000000 | 0x0134)
-#define NT_STATUS_DLL_NOT_FOUND (0xC0000000 | 0x0135)
-#define NT_STATUS_OPEN_FAILED (0xC0000000 | 0x0136)
-#define NT_STATUS_IO_PRIVILEGE_FAILED (0xC0000000 | 0x0137)
-#define NT_STATUS_ORDINAL_NOT_FOUND (0xC0000000 | 0x0138)
-#define NT_STATUS_ENTRYPOINT_NOT_FOUND (0xC0000000 | 0x0139)
-#define NT_STATUS_CONTROL_C_EXIT (0xC0000000 | 0x013a)
-#define NT_STATUS_LOCAL_DISCONNECT (0xC0000000 | 0x013b)
-#define NT_STATUS_REMOTE_DISCONNECT (0xC0000000 | 0x013c)
-#define NT_STATUS_REMOTE_RESOURCES (0xC0000000 | 0x013d)
-#define NT_STATUS_LINK_FAILED (0xC0000000 | 0x013e)
-#define NT_STATUS_LINK_TIMEOUT (0xC0000000 | 0x013f)
-#define NT_STATUS_INVALID_CONNECTION (0xC0000000 | 0x0140)
-#define NT_STATUS_INVALID_ADDRESS (0xC0000000 | 0x0141)
-#define NT_STATUS_DLL_INIT_FAILED (0xC0000000 | 0x0142)
-#define NT_STATUS_MISSING_SYSTEMFILE (0xC0000000 | 0x0143)
-#define NT_STATUS_UNHANDLED_EXCEPTION (0xC0000000 | 0x0144)
-#define NT_STATUS_APP_INIT_FAILURE (0xC0000000 | 0x0145)
-#define NT_STATUS_PAGEFILE_CREATE_FAILED (0xC0000000 | 0x0146)
-#define NT_STATUS_NO_PAGEFILE (0xC0000000 | 0x0147)
-#define NT_STATUS_INVALID_LEVEL (0xC0000000 | 0x0148)
-#define NT_STATUS_WRONG_PASSWORD_CORE (0xC0000000 | 0x0149)
-#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT (0xC0000000 | 0x014a)
-#define NT_STATUS_PIPE_BROKEN (0xC0000000 | 0x014b)
-#define NT_STATUS_REGISTRY_CORRUPT (0xC0000000 | 0x014c)
-#define NT_STATUS_REGISTRY_IO_FAILED (0xC0000000 | 0x014d)
-#define NT_STATUS_NO_EVENT_PAIR (0xC0000000 | 0x014e)
-#define NT_STATUS_UNRECOGNIZED_VOLUME (0xC0000000 | 0x014f)
-#define NT_STATUS_SERIAL_NO_DEVICE_INITED (0xC0000000 | 0x0150)
-#define NT_STATUS_NO_SUCH_ALIAS (0xC0000000 | 0x0151)
-#define NT_STATUS_MEMBER_NOT_IN_ALIAS (0xC0000000 | 0x0152)
-#define NT_STATUS_MEMBER_IN_ALIAS (0xC0000000 | 0x0153)
-#define NT_STATUS_ALIAS_EXISTS (0xC0000000 | 0x0154)
-#define NT_STATUS_LOGON_NOT_GRANTED (0xC0000000 | 0x0155)
-#define NT_STATUS_TOO_MANY_SECRETS (0xC0000000 | 0x0156)
-#define NT_STATUS_SECRET_TOO_LONG (0xC0000000 | 0x0157)
-#define NT_STATUS_INTERNAL_DB_ERROR (0xC0000000 | 0x0158)
-#define NT_STATUS_FULLSCREEN_MODE (0xC0000000 | 0x0159)
-#define NT_STATUS_TOO_MANY_CONTEXT_IDS (0xC0000000 | 0x015a)
-#define NT_STATUS_LOGON_TYPE_NOT_GRANTED (0xC0000000 | 0x015b)
-#define NT_STATUS_NOT_REGISTRY_FILE (0xC0000000 | 0x015c)
-#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED (0xC0000000 | 0x015d)
-#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR (0xC0000000 | 0x015e)
-#define NT_STATUS_FT_MISSING_MEMBER (0xC0000000 | 0x015f)
-#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY (0xC0000000 | 0x0160)
-#define NT_STATUS_ILLEGAL_CHARACTER (0xC0000000 | 0x0161)
-#define NT_STATUS_UNMAPPABLE_CHARACTER (0xC0000000 | 0x0162)
-#define NT_STATUS_UNDEFINED_CHARACTER (0xC0000000 | 0x0163)
-#define NT_STATUS_FLOPPY_VOLUME (0xC0000000 | 0x0164)
-#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND (0xC0000000 | 0x0165)
-#define NT_STATUS_FLOPPY_WRONG_CYLINDER (0xC0000000 | 0x0166)
-#define NT_STATUS_FLOPPY_UNKNOWN_ERROR (0xC0000000 | 0x0167)
-#define NT_STATUS_FLOPPY_BAD_REGISTERS (0xC0000000 | 0x0168)
-#define NT_STATUS_DISK_RECALIBRATE_FAILED (0xC0000000 | 0x0169)
-#define NT_STATUS_DISK_OPERATION_FAILED (0xC0000000 | 0x016a)
-#define NT_STATUS_DISK_RESET_FAILED (0xC0000000 | 0x016b)
-#define NT_STATUS_SHARED_IRQ_BUSY (0xC0000000 | 0x016c)
-#define NT_STATUS_FT_ORPHANING (0xC0000000 | 0x016d)
-#define NT_STATUS_PARTITION_FAILURE (0xC0000000 | 0x0172)
-#define NT_STATUS_INVALID_BLOCK_LENGTH (0xC0000000 | 0x0173)
-#define NT_STATUS_DEVICE_NOT_PARTITIONED (0xC0000000 | 0x0174)
-#define NT_STATUS_UNABLE_TO_LOCK_MEDIA (0xC0000000 | 0x0175)
-#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA (0xC0000000 | 0x0176)
-#define NT_STATUS_EOM_OVERFLOW (0xC0000000 | 0x0177)
-#define NT_STATUS_NO_MEDIA (0xC0000000 | 0x0178)
-#define NT_STATUS_NO_SUCH_MEMBER (0xC0000000 | 0x017a)
-#define NT_STATUS_INVALID_MEMBER (0xC0000000 | 0x017b)
-#define NT_STATUS_KEY_DELETED (0xC0000000 | 0x017c)
-#define NT_STATUS_NO_LOG_SPACE (0xC0000000 | 0x017d)
-#define NT_STATUS_TOO_MANY_SIDS (0xC0000000 | 0x017e)
-#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED (0xC0000000 | 0x017f)
-#define NT_STATUS_KEY_HAS_CHILDREN (0xC0000000 | 0x0180)
-#define NT_STATUS_CHILD_MUST_BE_VOLATILE (0xC0000000 | 0x0181)
-#define NT_STATUS_DEVICE_CONFIGURATION_ERROR (0xC0000000 | 0x0182)
-#define NT_STATUS_DRIVER_INTERNAL_ERROR (0xC0000000 | 0x0183)
-#define NT_STATUS_INVALID_DEVICE_STATE (0xC0000000 | 0x0184)
-#define NT_STATUS_IO_DEVICE_ERROR (0xC0000000 | 0x0185)
-#define NT_STATUS_DEVICE_PROTOCOL_ERROR (0xC0000000 | 0x0186)
-#define NT_STATUS_BACKUP_CONTROLLER (0xC0000000 | 0x0187)
-#define NT_STATUS_LOG_FILE_FULL (0xC0000000 | 0x0188)
-#define NT_STATUS_TOO_LATE (0xC0000000 | 0x0189)
-#define NT_STATUS_NO_TRUST_LSA_SECRET (0xC0000000 | 0x018a)
-#define NT_STATUS_NO_TRUST_SAM_ACCOUNT (0xC0000000 | 0x018b)
-#define NT_STATUS_TRUSTED_DOMAIN_FAILURE (0xC0000000 | 0x018c)
-#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE (0xC0000000 | 0x018d)
-#define NT_STATUS_EVENTLOG_FILE_CORRUPT (0xC0000000 | 0x018e)
-#define NT_STATUS_EVENTLOG_CANT_START (0xC0000000 | 0x018f)
-#define NT_STATUS_TRUST_FAILURE (0xC0000000 | 0x0190)
-#define NT_STATUS_MUTANT_LIMIT_EXCEEDED (0xC0000000 | 0x0191)
-#define NT_STATUS_NETLOGON_NOT_STARTED (0xC0000000 | 0x0192)
-#define NT_STATUS_ACCOUNT_EXPIRED (0xC0000000 | 0x0193)
-#define NT_STATUS_POSSIBLE_DEADLOCK (0xC0000000 | 0x0194)
-#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT (0xC0000000 | 0x0195)
-#define NT_STATUS_REMOTE_SESSION_LIMIT (0xC0000000 | 0x0196)
-#define NT_STATUS_EVENTLOG_FILE_CHANGED (0xC0000000 | 0x0197)
-#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT (0xC0000000 | 0x0198)
-#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT (0xC0000000 | 0x0199)
-#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT (0xC0000000 | 0x019a)
-#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT (0xC0000000 | 0x019b)
-#define NT_STATUS_FS_DRIVER_REQUIRED (0xC0000000 | 0x019c)
-#define NT_STATUS_NO_USER_SESSION_KEY (0xC0000000 | 0x0202)
-#define NT_STATUS_USER_SESSION_DELETED (0xC0000000 | 0x0203)
-#define NT_STATUS_RESOURCE_LANG_NOT_FOUND (0xC0000000 | 0x0204)
-#define NT_STATUS_INSUFF_SERVER_RESOURCES (0xC0000000 | 0x0205)
-#define NT_STATUS_INVALID_BUFFER_SIZE (0xC0000000 | 0x0206)
-#define NT_STATUS_INVALID_ADDRESS_COMPONENT (0xC0000000 | 0x0207)
-#define NT_STATUS_INVALID_ADDRESS_WILDCARD (0xC0000000 | 0x0208)
-#define NT_STATUS_TOO_MANY_ADDRESSES (0xC0000000 | 0x0209)
-#define NT_STATUS_ADDRESS_ALREADY_EXISTS (0xC0000000 | 0x020a)
-#define NT_STATUS_ADDRESS_CLOSED (0xC0000000 | 0x020b)
-#define NT_STATUS_CONNECTION_DISCONNECTED (0xC0000000 | 0x020c)
-#define NT_STATUS_CONNECTION_RESET (0xC0000000 | 0x020d)
-#define NT_STATUS_TOO_MANY_NODES (0xC0000000 | 0x020e)
-#define NT_STATUS_TRANSACTION_ABORTED (0xC0000000 | 0x020f)
-#define NT_STATUS_TRANSACTION_TIMED_OUT (0xC0000000 | 0x0210)
-#define NT_STATUS_TRANSACTION_NO_RELEASE (0xC0000000 | 0x0211)
-#define NT_STATUS_TRANSACTION_NO_MATCH (0xC0000000 | 0x0212)
-#define NT_STATUS_TRANSACTION_RESPONDED (0xC0000000 | 0x0213)
-#define NT_STATUS_TRANSACTION_INVALID_ID (0xC0000000 | 0x0214)
-#define NT_STATUS_TRANSACTION_INVALID_TYPE (0xC0000000 | 0x0215)
-#define NT_STATUS_NOT_SERVER_SESSION (0xC0000000 | 0x0216)
-#define NT_STATUS_NOT_CLIENT_SESSION (0xC0000000 | 0x0217)
-#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE (0xC0000000 | 0x0218)
-#define NT_STATUS_DEBUG_ATTACH_FAILED (0xC0000000 | 0x0219)
-#define NT_STATUS_SYSTEM_PROCESS_TERMINATED (0xC0000000 | 0x021a)
-#define NT_STATUS_DATA_NOT_ACCEPTED (0xC0000000 | 0x021b)
-#define NT_STATUS_NO_BROWSER_SERVERS_FOUND (0xC0000000 | 0x021c)
-#define NT_STATUS_VDM_HARD_ERROR (0xC0000000 | 0x021d)
-#define NT_STATUS_DRIVER_CANCEL_TIMEOUT (0xC0000000 | 0x021e)
-#define NT_STATUS_REPLY_MESSAGE_MISMATCH (0xC0000000 | 0x021f)
-#define NT_STATUS_MAPPED_ALIGNMENT (0xC0000000 | 0x0220)
-#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH (0xC0000000 | 0x0221)
-#define NT_STATUS_LOST_WRITEBEHIND_DATA (0xC0000000 | 0x0222)
-#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID (0xC0000000 | 0x0223)
-#define NT_STATUS_PASSWORD_MUST_CHANGE (0xC0000000 | 0x0224)
-#define NT_STATUS_NOT_FOUND (0xC0000000 | 0x0225)
-#define NT_STATUS_NOT_TINY_STREAM (0xC0000000 | 0x0226)
-#define NT_STATUS_RECOVERY_FAILURE (0xC0000000 | 0x0227)
-#define NT_STATUS_STACK_OVERFLOW_READ (0xC0000000 | 0x0228)
-#define NT_STATUS_FAIL_CHECK (0xC0000000 | 0x0229)
-#define NT_STATUS_DUPLICATE_OBJECTID (0xC0000000 | 0x022a)
-#define NT_STATUS_OBJECTID_EXISTS (0xC0000000 | 0x022b)
-#define NT_STATUS_CONVERT_TO_LARGE (0xC0000000 | 0x022c)
-#define NT_STATUS_RETRY (0xC0000000 | 0x022d)
-#define NT_STATUS_FOUND_OUT_OF_SCOPE (0xC0000000 | 0x022e)
-#define NT_STATUS_ALLOCATE_BUCKET (0xC0000000 | 0x022f)
-#define NT_STATUS_PROPSET_NOT_FOUND (0xC0000000 | 0x0230)
-#define NT_STATUS_MARSHALL_OVERFLOW (0xC0000000 | 0x0231)
-#define NT_STATUS_INVALID_VARIANT (0xC0000000 | 0x0232)
-#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND (0xC0000000 | 0x0233)
-#define NT_STATUS_ACCOUNT_LOCKED_OUT (0xC0000000 | 0x0234)
-#define NT_STATUS_HANDLE_NOT_CLOSABLE (0xC0000000 | 0x0235)
-#define NT_STATUS_CONNECTION_REFUSED (0xC0000000 | 0x0236)
-#define NT_STATUS_GRACEFUL_DISCONNECT (0xC0000000 | 0x0237)
-#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED (0xC0000000 | 0x0238)
-#define NT_STATUS_ADDRESS_NOT_ASSOCIATED (0xC0000000 | 0x0239)
-#define NT_STATUS_CONNECTION_INVALID (0xC0000000 | 0x023a)
-#define NT_STATUS_CONNECTION_ACTIVE (0xC0000000 | 0x023b)
-#define NT_STATUS_NETWORK_UNREACHABLE (0xC0000000 | 0x023c)
-#define NT_STATUS_HOST_UNREACHABLE (0xC0000000 | 0x023d)
-#define NT_STATUS_PROTOCOL_UNREACHABLE (0xC0000000 | 0x023e)
-#define NT_STATUS_PORT_UNREACHABLE (0xC0000000 | 0x023f)
-#define NT_STATUS_REQUEST_ABORTED (0xC0000000 | 0x0240)
-#define NT_STATUS_CONNECTION_ABORTED (0xC0000000 | 0x0241)
-#define NT_STATUS_BAD_COMPRESSION_BUFFER (0xC0000000 | 0x0242)
-#define NT_STATUS_USER_MAPPED_FILE (0xC0000000 | 0x0243)
-#define NT_STATUS_AUDIT_FAILED (0xC0000000 | 0x0244)
-#define NT_STATUS_TIMER_RESOLUTION_NOT_SET (0xC0000000 | 0x0245)
-#define NT_STATUS_CONNECTION_COUNT_LIMIT (0xC0000000 | 0x0246)
-#define NT_STATUS_LOGIN_TIME_RESTRICTION (0xC0000000 | 0x0247)
-#define NT_STATUS_LOGIN_WKSTA_RESTRICTION (0xC0000000 | 0x0248)
-#define NT_STATUS_IMAGE_MP_UP_MISMATCH (0xC0000000 | 0x0249)
-#define NT_STATUS_INSUFFICIENT_LOGON_INFO (0xC0000000 | 0x0250)
-#define NT_STATUS_BAD_DLL_ENTRYPOINT (0xC0000000 | 0x0251)
-#define NT_STATUS_BAD_SERVICE_ENTRYPOINT (0xC0000000 | 0x0252)
-#define NT_STATUS_LPC_REPLY_LOST (0xC0000000 | 0x0253)
-#define NT_STATUS_IP_ADDRESS_CONFLICT1 (0xC0000000 | 0x0254)
-#define NT_STATUS_IP_ADDRESS_CONFLICT2 (0xC0000000 | 0x0255)
-#define NT_STATUS_REGISTRY_QUOTA_LIMIT (0xC0000000 | 0x0256)
-#define NT_STATUS_PATH_NOT_COVERED (0xC0000000 | 0x0257)
-#define NT_STATUS_NO_CALLBACK_ACTIVE (0xC0000000 | 0x0258)
-#define NT_STATUS_LICENSE_QUOTA_EXCEEDED (0xC0000000 | 0x0259)
-#define NT_STATUS_PWD_TOO_SHORT (0xC0000000 | 0x025a)
-#define NT_STATUS_PWD_TOO_RECENT (0xC0000000 | 0x025b)
-#define NT_STATUS_PWD_HISTORY_CONFLICT (0xC0000000 | 0x025c)
-#define NT_STATUS_PLUGPLAY_NO_DEVICE (0xC0000000 | 0x025e)
-#define NT_STATUS_UNSUPPORTED_COMPRESSION (0xC0000000 | 0x025f)
-#define NT_STATUS_INVALID_HW_PROFILE (0xC0000000 | 0x0260)
-#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH (0xC0000000 | 0x0261)
-#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND (0xC0000000 | 0x0262)
-#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND (0xC0000000 | 0x0263)
-#define NT_STATUS_RESOURCE_NOT_OWNED (0xC0000000 | 0x0264)
-#define NT_STATUS_TOO_MANY_LINKS (0xC0000000 | 0x0265)
-#define NT_STATUS_QUOTA_LIST_INCONSISTENT (0xC0000000 | 0x0266)
-#define NT_STATUS_FILE_IS_OFFLINE (0xC0000000 | 0x0267)
-#define NT_STATUS_NETWORK_SESSION_EXPIRED (0xC0000000 | 0x035c)
-#define NT_STATUS_NO_SUCH_JOB (0xC0000000 | 0xEDE) /* scheduler */
-#define NT_STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP (0xC0000000 | 0x5D0000)
-#define NT_STATUS_PENDING 0x00000103
-#endif /* _NTERR_H */
diff --git a/fs/ksmbd/ntlmssp.h b/fs/ksmbd/ntlmssp.h
deleted file mode 100644
index f13153c18b4e..000000000000
--- a/fs/ksmbd/ntlmssp.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * Copyright (c) International Business Machines Corp., 2002,2007
- * Author(s): Steve French (sfrench@us.ibm.com)
- */
-
-#ifndef __KSMBD_NTLMSSP_H
-#define __KSMBD_NTLMSSP_H
-
-#define NTLMSSP_SIGNATURE "NTLMSSP"
-
-/* Security blob target info data */
-#define TGT_Name "KSMBD"
-
-/*
- * Size of the crypto key returned on the negotiate SMB in bytes
- */
-#define CIFS_CRYPTO_KEY_SIZE (8)
-#define CIFS_KEY_SIZE (40)
-
-/*
- * Size of encrypted user password in bytes
- */
-#define CIFS_ENCPWD_SIZE (16)
-#define CIFS_CPHTXT_SIZE (16)
-
-/* Message Types */
-#define NtLmNegotiate cpu_to_le32(1)
-#define NtLmChallenge cpu_to_le32(2)
-#define NtLmAuthenticate cpu_to_le32(3)
-#define UnknownMessage cpu_to_le32(8)
-
-/* Negotiate Flags */
-#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */
-#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
-#define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */
-/* define reserved9 0x08 */
-#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */
-#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
-#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
-#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */
-/* defined reserved 8 0x0100 */
-#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
-#define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */
-#define NTLMSSP_ANONYMOUS 0x0800
-#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */
-#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
-#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */
-#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */
-#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
-#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
-#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
-#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/
-/* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */
-#define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000
-#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */
-#define NTLMSSP_REQUEST_NON_NT_KEY 0x400000
-#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
-/* #define reserved4 0x1000000 */
-#define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we do not set */
-/* #define reserved3 0x4000000 */
-/* #define reserved2 0x8000000 */
-/* #define reserved1 0x10000000 */
-#define NTLMSSP_NEGOTIATE_128 0x20000000
-#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
-#define NTLMSSP_NEGOTIATE_56 0x80000000
-
-/* Define AV Pair Field IDs */
-enum av_field_type {
- NTLMSSP_AV_EOL = 0,
- NTLMSSP_AV_NB_COMPUTER_NAME,
- NTLMSSP_AV_NB_DOMAIN_NAME,
- NTLMSSP_AV_DNS_COMPUTER_NAME,
- NTLMSSP_AV_DNS_DOMAIN_NAME,
- NTLMSSP_AV_DNS_TREE_NAME,
- NTLMSSP_AV_FLAGS,
- NTLMSSP_AV_TIMESTAMP,
- NTLMSSP_AV_RESTRICTION,
- NTLMSSP_AV_TARGET_NAME,
- NTLMSSP_AV_CHANNEL_BINDINGS
-};
-
-/* Although typedefs are not commonly used for structure definitions */
-/* in the Linux kernel, in this particular case they are useful */
-/* to more closely match the standards document for NTLMSSP from */
-/* OpenGroup and to make the code more closely match the standard in */
-/* appearance */
-
-struct security_buffer {
- __le16 Length;
- __le16 MaximumLength;
- __le32 BufferOffset; /* offset to buffer */
-} __packed;
-
-struct target_info {
- __le16 Type;
- __le16 Length;
- __u8 Content[];
-} __packed;
-
-struct negotiate_message {
- __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* NtLmNegotiate = 1 */
- __le32 NegotiateFlags;
- struct security_buffer DomainName; /* RFC 1001 style and ASCII */
- struct security_buffer WorkstationName; /* RFC 1001 and ASCII */
- /*
- * struct security_buffer for version info not present since we
- * do not set the version is present flag
- */
- char DomainString[];
- /* followed by WorkstationString */
-} __packed;
-
-struct challenge_message {
- __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* NtLmChallenge = 2 */
- struct security_buffer TargetName;
- __le32 NegotiateFlags;
- __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
- __u8 Reserved[8];
- struct security_buffer TargetInfoArray;
- /*
- * struct security_buffer for version info not present since we
- * do not set the version is present flag
- */
-} __packed;
-
-struct authenticate_message {
- __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* NtLmsAuthenticate = 3 */
- struct security_buffer LmChallengeResponse;
- struct security_buffer NtChallengeResponse;
- struct security_buffer DomainName;
- struct security_buffer UserName;
- struct security_buffer WorkstationName;
- struct security_buffer SessionKey;
- __le32 NegotiateFlags;
- /*
- * struct security_buffer for version info not present since we
- * do not set the version is present flag
- */
- char UserString[];
-} __packed;
-
-struct ntlmv2_resp {
- char ntlmv2_hash[CIFS_ENCPWD_SIZE];
- __le32 blob_signature;
- __u32 reserved;
- __le64 time;
- __u64 client_chal; /* random */
- __u32 reserved2;
- /* array of name entries could follow ending in minimum 4 byte struct */
-} __packed;
-
-/* per smb session structure/fields */
-struct ntlmssp_auth {
- /* whether session key is per smb session */
- bool sesskey_per_smbsess;
- /* sent by client in type 1 ntlmsssp exchange */
- __u32 client_flags;
- /* sent by server in type 2 ntlmssp exchange */
- __u32 conn_flags;
- /* sent to server */
- unsigned char ciphertext[CIFS_CPHTXT_SIZE];
- /* used by ntlmssp */
- char cryptkey[CIFS_CRYPTO_KEY_SIZE];
-};
-#endif /* __KSMBD_NTLMSSP_H */
diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c
deleted file mode 100644
index 4b210cdd7556..000000000000
--- a/fs/ksmbd/oplock.c
+++ /dev/null
@@ -1,1722 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/moduleparam.h>
-
-#include "glob.h"
-#include "oplock.h"
-
-#include "smb_common.h"
-#include "smbstatus.h"
-#include "connection.h"
-#include "mgmt/user_session.h"
-#include "mgmt/share_config.h"
-#include "mgmt/tree_connect.h"
-
-static LIST_HEAD(lease_table_list);
-static DEFINE_RWLOCK(lease_list_lock);
-
-/**
- * alloc_opinfo() - allocate a new opinfo object for oplock info
- * @work: smb work
- * @id: fid of open file
- * @Tid: tree id of connection
- *
- * Return: allocated opinfo object on success, otherwise NULL
- */
-static struct oplock_info *alloc_opinfo(struct ksmbd_work *work,
- u64 id, __u16 Tid)
-{
- struct ksmbd_conn *conn = work->conn;
- struct ksmbd_session *sess = work->sess;
- struct oplock_info *opinfo;
-
- opinfo = kzalloc(sizeof(struct oplock_info), GFP_KERNEL);
- if (!opinfo)
- return NULL;
-
- opinfo->sess = sess;
- opinfo->conn = conn;
- opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
- opinfo->op_state = OPLOCK_STATE_NONE;
- opinfo->pending_break = 0;
- opinfo->fid = id;
- opinfo->Tid = Tid;
- INIT_LIST_HEAD(&opinfo->op_entry);
- INIT_LIST_HEAD(&opinfo->interim_list);
- init_waitqueue_head(&opinfo->oplock_q);
- init_waitqueue_head(&opinfo->oplock_brk);
- atomic_set(&opinfo->refcount, 1);
- atomic_set(&opinfo->breaking_cnt, 0);
-
- return opinfo;
-}
-
-static void lease_add_list(struct oplock_info *opinfo)
-{
- struct lease_table *lb = opinfo->o_lease->l_lb;
-
- spin_lock(&lb->lb_lock);
- list_add_rcu(&opinfo->lease_entry, &lb->lease_list);
- spin_unlock(&lb->lb_lock);
-}
-
-static void lease_del_list(struct oplock_info *opinfo)
-{
- struct lease_table *lb = opinfo->o_lease->l_lb;
-
- if (!lb)
- return;
-
- spin_lock(&lb->lb_lock);
- if (list_empty(&opinfo->lease_entry)) {
- spin_unlock(&lb->lb_lock);
- return;
- }
-
- list_del_init(&opinfo->lease_entry);
- opinfo->o_lease->l_lb = NULL;
- spin_unlock(&lb->lb_lock);
-}
-
-static void lb_add(struct lease_table *lb)
-{
- write_lock(&lease_list_lock);
- list_add(&lb->l_entry, &lease_table_list);
- write_unlock(&lease_list_lock);
-}
-
-static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx)
-{
- struct lease *lease;
-
- lease = kmalloc(sizeof(struct lease), GFP_KERNEL);
- if (!lease)
- return -ENOMEM;
-
- memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);
- lease->state = lctx->req_state;
- lease->new_state = 0;
- lease->flags = lctx->flags;
- lease->duration = lctx->duration;
- memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE);
- lease->version = lctx->version;
- lease->epoch = 0;
- INIT_LIST_HEAD(&opinfo->lease_entry);
- opinfo->o_lease = lease;
-
- return 0;
-}
-
-static void free_lease(struct oplock_info *opinfo)
-{
- struct lease *lease;
-
- lease = opinfo->o_lease;
- kfree(lease);
-}
-
-static void free_opinfo(struct oplock_info *opinfo)
-{
- if (opinfo->is_lease)
- free_lease(opinfo);
- kfree(opinfo);
-}
-
-static inline void opinfo_free_rcu(struct rcu_head *rcu_head)
-{
- struct oplock_info *opinfo;
-
- opinfo = container_of(rcu_head, struct oplock_info, rcu_head);
- free_opinfo(opinfo);
-}
-
-struct oplock_info *opinfo_get(struct ksmbd_file *fp)
-{
- struct oplock_info *opinfo;
-
- rcu_read_lock();
- opinfo = rcu_dereference(fp->f_opinfo);
- if (opinfo && !atomic_inc_not_zero(&opinfo->refcount))
- opinfo = NULL;
- rcu_read_unlock();
-
- return opinfo;
-}
-
-static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
-{
- struct oplock_info *opinfo;
-
- if (list_empty(&ci->m_op_list))
- return NULL;
-
- rcu_read_lock();
- opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info,
- op_entry);
- if (opinfo) {
- if (!atomic_inc_not_zero(&opinfo->refcount))
- opinfo = NULL;
- else {
- atomic_inc(&opinfo->conn->r_count);
- if (ksmbd_conn_releasing(opinfo->conn)) {
- atomic_dec(&opinfo->conn->r_count);
- atomic_dec(&opinfo->refcount);
- opinfo = NULL;
- }
- }
- }
-
- rcu_read_unlock();
-
- return opinfo;
-}
-
-static void opinfo_conn_put(struct oplock_info *opinfo)
-{
- struct ksmbd_conn *conn;
-
- if (!opinfo)
- return;
-
- conn = opinfo->conn;
- /*
- * Checking waitqueue to dropping pending requests on
- * disconnection. waitqueue_active is safe because it
- * uses atomic operation for condition.
- */
- if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
- wake_up(&conn->r_count_q);
- opinfo_put(opinfo);
-}
-
-void opinfo_put(struct oplock_info *opinfo)
-{
- if (!atomic_dec_and_test(&opinfo->refcount))
- return;
-
- call_rcu(&opinfo->rcu_head, opinfo_free_rcu);
-}
-
-static void opinfo_add(struct oplock_info *opinfo)
-{
- struct ksmbd_inode *ci = opinfo->o_fp->f_ci;
-
- write_lock(&ci->m_lock);
- list_add_rcu(&opinfo->op_entry, &ci->m_op_list);
- write_unlock(&ci->m_lock);
-}
-
-static void opinfo_del(struct oplock_info *opinfo)
-{
- struct ksmbd_inode *ci = opinfo->o_fp->f_ci;
-
- if (opinfo->is_lease) {
- write_lock(&lease_list_lock);
- lease_del_list(opinfo);
- write_unlock(&lease_list_lock);
- }
- write_lock(&ci->m_lock);
- list_del_rcu(&opinfo->op_entry);
- write_unlock(&ci->m_lock);
-}
-
-static unsigned long opinfo_count(struct ksmbd_file *fp)
-{
- if (ksmbd_stream_fd(fp))
- return atomic_read(&fp->f_ci->sop_count);
- else
- return atomic_read(&fp->f_ci->op_count);
-}
-
-static void opinfo_count_inc(struct ksmbd_file *fp)
-{
- if (ksmbd_stream_fd(fp))
- return atomic_inc(&fp->f_ci->sop_count);
- else
- return atomic_inc(&fp->f_ci->op_count);
-}
-
-static void opinfo_count_dec(struct ksmbd_file *fp)
-{
- if (ksmbd_stream_fd(fp))
- return atomic_dec(&fp->f_ci->sop_count);
- else
- return atomic_dec(&fp->f_ci->op_count);
-}
-
-/**
- * opinfo_write_to_read() - convert a write oplock to read oplock
- * @opinfo: current oplock info
- *
- * Return: 0 on success, otherwise -EINVAL
- */
-int opinfo_write_to_read(struct oplock_info *opinfo)
-{
- struct lease *lease = opinfo->o_lease;
-
- if (!(opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||
- opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) {
- pr_err("bad oplock(0x%x)\n", opinfo->level);
- if (opinfo->is_lease)
- pr_err("lease state(0x%x)\n", lease->state);
- return -EINVAL;
- }
- opinfo->level = SMB2_OPLOCK_LEVEL_II;
-
- if (opinfo->is_lease)
- lease->state = lease->new_state;
- return 0;
-}
-
-/**
- * opinfo_read_handle_to_read() - convert a read/handle oplock to read oplock
- * @opinfo: current oplock info
- *
- * Return: 0 on success, otherwise -EINVAL
- */
-int opinfo_read_handle_to_read(struct oplock_info *opinfo)
-{
- struct lease *lease = opinfo->o_lease;
-
- lease->state = lease->new_state;
- opinfo->level = SMB2_OPLOCK_LEVEL_II;
- return 0;
-}
-
-/**
- * opinfo_write_to_none() - convert a write oplock to none
- * @opinfo: current oplock info
- *
- * Return: 0 on success, otherwise -EINVAL
- */
-int opinfo_write_to_none(struct oplock_info *opinfo)
-{
- struct lease *lease = opinfo->o_lease;
-
- if (!(opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||
- opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) {
- pr_err("bad oplock(0x%x)\n", opinfo->level);
- if (opinfo->is_lease)
- pr_err("lease state(0x%x)\n", lease->state);
- return -EINVAL;
- }
- opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
- if (opinfo->is_lease)
- lease->state = lease->new_state;
- return 0;
-}
-
-/**
- * opinfo_read_to_none() - convert a write read to none
- * @opinfo: current oplock info
- *
- * Return: 0 on success, otherwise -EINVAL
- */
-int opinfo_read_to_none(struct oplock_info *opinfo)
-{
- struct lease *lease = opinfo->o_lease;
-
- if (opinfo->level != SMB2_OPLOCK_LEVEL_II) {
- pr_err("bad oplock(0x%x)\n", opinfo->level);
- if (opinfo->is_lease)
- pr_err("lease state(0x%x)\n", lease->state);
- return -EINVAL;
- }
- opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
- if (opinfo->is_lease)
- lease->state = lease->new_state;
- return 0;
-}
-
-/**
- * lease_read_to_write() - upgrade lease state from read to write
- * @opinfo: current lease info
- *
- * Return: 0 on success, otherwise -EINVAL
- */
-int lease_read_to_write(struct oplock_info *opinfo)
-{
- struct lease *lease = opinfo->o_lease;
-
- if (!(lease->state & SMB2_LEASE_READ_CACHING_LE)) {
- ksmbd_debug(OPLOCK, "bad lease state(0x%x)\n", lease->state);
- return -EINVAL;
- }
-
- lease->new_state = SMB2_LEASE_NONE_LE;
- lease->state |= SMB2_LEASE_WRITE_CACHING_LE;
- if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
- opinfo->level = SMB2_OPLOCK_LEVEL_BATCH;
- else
- opinfo->level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
- return 0;
-}
-
-/**
- * lease_none_upgrade() - upgrade lease state from none
- * @opinfo: current lease info
- * @new_state: new lease state
- *
- * Return: 0 on success, otherwise -EINVAL
- */
-static int lease_none_upgrade(struct oplock_info *opinfo, __le32 new_state)
-{
- struct lease *lease = opinfo->o_lease;
-
- if (!(lease->state == SMB2_LEASE_NONE_LE)) {
- ksmbd_debug(OPLOCK, "bad lease state(0x%x)\n", lease->state);
- return -EINVAL;
- }
-
- lease->new_state = SMB2_LEASE_NONE_LE;
- lease->state = new_state;
- if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
- if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
- opinfo->level = SMB2_OPLOCK_LEVEL_BATCH;
- else
- opinfo->level = SMB2_OPLOCK_LEVEL_II;
- else if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
- opinfo->level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
- else if (lease->state & SMB2_LEASE_READ_CACHING_LE)
- opinfo->level = SMB2_OPLOCK_LEVEL_II;
-
- return 0;
-}
-
-/**
- * close_id_del_oplock() - release oplock object at file close time
- * @fp: ksmbd file pointer
- */
-void close_id_del_oplock(struct ksmbd_file *fp)
-{
- struct oplock_info *opinfo;
-
- if (S_ISDIR(file_inode(fp->filp)->i_mode))
- return;
-
- opinfo = opinfo_get(fp);
- if (!opinfo)
- return;
-
- opinfo_del(opinfo);
-
- rcu_assign_pointer(fp->f_opinfo, NULL);
- if (opinfo->op_state == OPLOCK_ACK_WAIT) {
- opinfo->op_state = OPLOCK_CLOSING;
- wake_up_interruptible_all(&opinfo->oplock_q);
- if (opinfo->is_lease) {
- atomic_set(&opinfo->breaking_cnt, 0);
- wake_up_interruptible_all(&opinfo->oplock_brk);
- }
- }
-
- opinfo_count_dec(fp);
- atomic_dec(&opinfo->refcount);
- opinfo_put(opinfo);
-}
-
-/**
- * grant_write_oplock() - grant exclusive/batch oplock or write lease
- * @opinfo_new: new oplock info object
- * @req_oplock: request oplock
- * @lctx: lease context information
- *
- * Return: 0
- */
-static void grant_write_oplock(struct oplock_info *opinfo_new, int req_oplock,
- struct lease_ctx_info *lctx)
-{
- struct lease *lease = opinfo_new->o_lease;
-
- if (req_oplock == SMB2_OPLOCK_LEVEL_BATCH)
- opinfo_new->level = SMB2_OPLOCK_LEVEL_BATCH;
- else
- opinfo_new->level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
-
- if (lctx) {
- lease->state = lctx->req_state;
- memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);
- }
-}
-
-/**
- * grant_read_oplock() - grant level2 oplock or read lease
- * @opinfo_new: new oplock info object
- * @lctx: lease context information
- *
- * Return: 0
- */
-static void grant_read_oplock(struct oplock_info *opinfo_new,
- struct lease_ctx_info *lctx)
-{
- struct lease *lease = opinfo_new->o_lease;
-
- opinfo_new->level = SMB2_OPLOCK_LEVEL_II;
-
- if (lctx) {
- lease->state = SMB2_LEASE_READ_CACHING_LE;
- if (lctx->req_state & SMB2_LEASE_HANDLE_CACHING_LE)
- lease->state |= SMB2_LEASE_HANDLE_CACHING_LE;
- memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);
- }
-}
-
-/**
- * grant_none_oplock() - grant none oplock or none lease
- * @opinfo_new: new oplock info object
- * @lctx: lease context information
- *
- * Return: 0
- */
-static void grant_none_oplock(struct oplock_info *opinfo_new,
- struct lease_ctx_info *lctx)
-{
- struct lease *lease = opinfo_new->o_lease;
-
- opinfo_new->level = SMB2_OPLOCK_LEVEL_NONE;
-
- if (lctx) {
- lease->state = 0;
- memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);
- }
-}
-
-static inline int compare_guid_key(struct oplock_info *opinfo,
- const char *guid1, const char *key1)
-{
- const char *guid2, *key2;
-
- guid2 = opinfo->conn->ClientGUID;
- key2 = opinfo->o_lease->lease_key;
- if (!memcmp(guid1, guid2, SMB2_CLIENT_GUID_SIZE) &&
- !memcmp(key1, key2, SMB2_LEASE_KEY_SIZE))
- return 1;
-
- return 0;
-}
-
-/**
- * same_client_has_lease() - check whether current lease request is
- * from lease owner of file
- * @ci: master file pointer
- * @client_guid: Client GUID
- * @lctx: lease context information
- *
- * Return: oplock(lease) object on success, otherwise NULL
- */
-static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
- char *client_guid,
- struct lease_ctx_info *lctx)
-{
- int ret;
- struct lease *lease;
- struct oplock_info *opinfo;
- struct oplock_info *m_opinfo = NULL;
-
- if (!lctx)
- return NULL;
-
- /*
- * Compare lease key and client_guid to know request from same owner
- * of same client
- */
- read_lock(&ci->m_lock);
- list_for_each_entry(opinfo, &ci->m_op_list, op_entry) {
- if (!opinfo->is_lease)
- continue;
- read_unlock(&ci->m_lock);
- lease = opinfo->o_lease;
-
- ret = compare_guid_key(opinfo, client_guid, lctx->lease_key);
- if (ret) {
- m_opinfo = opinfo;
- /* skip upgrading lease about breaking lease */
- if (atomic_read(&opinfo->breaking_cnt)) {
- read_lock(&ci->m_lock);
- continue;
- }
-
- /* upgrading lease */
- if ((atomic_read(&ci->op_count) +
- atomic_read(&ci->sop_count)) == 1) {
- if (lease->state ==
- (lctx->req_state & lease->state)) {
- lease->state |= lctx->req_state;
- if (lctx->req_state &
- SMB2_LEASE_WRITE_CACHING_LE)
- lease_read_to_write(opinfo);
- }
- } else if ((atomic_read(&ci->op_count) +
- atomic_read(&ci->sop_count)) > 1) {
- if (lctx->req_state ==
- (SMB2_LEASE_READ_CACHING_LE |
- SMB2_LEASE_HANDLE_CACHING_LE))
- lease->state = lctx->req_state;
- }
-
- if (lctx->req_state && lease->state ==
- SMB2_LEASE_NONE_LE)
- lease_none_upgrade(opinfo, lctx->req_state);
- }
- read_lock(&ci->m_lock);
- }
- read_unlock(&ci->m_lock);
-
- return m_opinfo;
-}
-
-static void wait_for_break_ack(struct oplock_info *opinfo)
-{
- int rc = 0;
-
- rc = wait_event_interruptible_timeout(opinfo->oplock_q,
- opinfo->op_state == OPLOCK_STATE_NONE ||
- opinfo->op_state == OPLOCK_CLOSING,
- OPLOCK_WAIT_TIME);
-
- /* is this a timeout ? */
- if (!rc) {
- if (opinfo->is_lease)
- opinfo->o_lease->state = SMB2_LEASE_NONE_LE;
- opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
- opinfo->op_state = OPLOCK_STATE_NONE;
- }
-}
-
-static void wake_up_oplock_break(struct oplock_info *opinfo)
-{
- clear_bit_unlock(0, &opinfo->pending_break);
- /* memory barrier is needed for wake_up_bit() */
- smp_mb__after_atomic();
- wake_up_bit(&opinfo->pending_break, 0);
-}
-
-static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)
-{
- while (test_and_set_bit(0, &opinfo->pending_break)) {
- wait_on_bit(&opinfo->pending_break, 0, TASK_UNINTERRUPTIBLE);
-
- /* Not immediately break to none. */
- opinfo->open_trunc = 0;
-
- if (opinfo->op_state == OPLOCK_CLOSING)
- return -ENOENT;
- else if (!opinfo->is_lease && opinfo->level <= req_op_level)
- return 1;
- }
-
- if (!opinfo->is_lease && opinfo->level <= req_op_level) {
- wake_up_oplock_break(opinfo);
- return 1;
- }
- return 0;
-}
-
-static inline int allocate_oplock_break_buf(struct ksmbd_work *work)
-{
- work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, GFP_KERNEL);
- if (!work->response_buf)
- return -ENOMEM;
- work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
- return 0;
-}
-
-/**
- * __smb2_oplock_break_noti() - send smb2 oplock break cmd from conn
- * to client
- * @wk: smb work object
- *
- * There are two ways this function can be called. 1- while file open we break
- * from exclusive/batch lock to levelII oplock and 2- while file write/truncate
- * we break from levelII oplock no oplock.
- * work->request_buf contains oplock_info.
- */
-static void __smb2_oplock_break_noti(struct work_struct *wk)
-{
- struct smb2_oplock_break *rsp = NULL;
- struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
- struct ksmbd_conn *conn = work->conn;
- struct oplock_break_info *br_info = work->request_buf;
- struct smb2_hdr *rsp_hdr;
- struct ksmbd_file *fp;
-
- fp = ksmbd_lookup_durable_fd(br_info->fid);
- if (!fp)
- goto out;
-
- if (allocate_oplock_break_buf(work)) {
- pr_err("smb2_allocate_rsp_buf failed! ");
- ksmbd_fd_put(work, fp);
- goto out;
- }
-
- rsp_hdr = smb2_get_msg(work->response_buf);
- memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- *(__be32 *)work->response_buf =
- cpu_to_be32(conn->vals->header_size);
- rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
- rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
- rsp_hdr->CreditRequest = cpu_to_le16(0);
- rsp_hdr->Command = SMB2_OPLOCK_BREAK;
- rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
- rsp_hdr->NextCommand = 0;
- rsp_hdr->MessageId = cpu_to_le64(-1);
- rsp_hdr->Id.SyncId.ProcessId = 0;
- rsp_hdr->Id.SyncId.TreeId = 0;
- rsp_hdr->SessionId = 0;
- memset(rsp_hdr->Signature, 0, 16);
-
- rsp = smb2_get_msg(work->response_buf);
-
- rsp->StructureSize = cpu_to_le16(24);
- if (!br_info->open_trunc &&
- (br_info->level == SMB2_OPLOCK_LEVEL_BATCH ||
- br_info->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE))
- rsp->OplockLevel = SMB2_OPLOCK_LEVEL_II;
- else
- rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE;
- rsp->Reserved = 0;
- rsp->Reserved2 = 0;
- rsp->PersistentFid = fp->persistent_id;
- rsp->VolatileFid = fp->volatile_id;
-
- inc_rfc1001_len(work->response_buf, 24);
-
- ksmbd_debug(OPLOCK,
- "sending oplock break v_id %llu p_id = %llu lock level = %d\n",
- rsp->VolatileFid, rsp->PersistentFid, rsp->OplockLevel);
-
- ksmbd_fd_put(work, fp);
- ksmbd_conn_write(work);
-
-out:
- ksmbd_free_work_struct(work);
-}
-
-/**
- * smb2_oplock_break_noti() - send smb2 exclusive/batch to level2 oplock
- * break command from server to client
- * @opinfo: oplock info object
- *
- * Return: 0 on success, otherwise error
- */
-static int smb2_oplock_break_noti(struct oplock_info *opinfo)
-{
- struct ksmbd_conn *conn = opinfo->conn;
- struct oplock_break_info *br_info;
- int ret = 0;
- struct ksmbd_work *work = ksmbd_alloc_work_struct();
-
- if (!work)
- return -ENOMEM;
-
- br_info = kmalloc(sizeof(struct oplock_break_info), GFP_KERNEL);
- if (!br_info) {
- ksmbd_free_work_struct(work);
- return -ENOMEM;
- }
-
- br_info->level = opinfo->level;
- br_info->fid = opinfo->fid;
- br_info->open_trunc = opinfo->open_trunc;
-
- work->request_buf = (char *)br_info;
- work->conn = conn;
- work->sess = opinfo->sess;
-
- if (opinfo->op_state == OPLOCK_ACK_WAIT) {
- INIT_WORK(&work->work, __smb2_oplock_break_noti);
- ksmbd_queue_work(work);
-
- wait_for_break_ack(opinfo);
- } else {
- __smb2_oplock_break_noti(&work->work);
- if (opinfo->level == SMB2_OPLOCK_LEVEL_II)
- opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
- }
- return ret;
-}
-
-/**
- * __smb2_lease_break_noti() - send lease break command from server
- * to client
- * @wk: smb work object
- */
-static void __smb2_lease_break_noti(struct work_struct *wk)
-{
- struct smb2_lease_break *rsp = NULL;
- struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
- struct lease_break_info *br_info = work->request_buf;
- struct ksmbd_conn *conn = work->conn;
- struct smb2_hdr *rsp_hdr;
-
- if (allocate_oplock_break_buf(work)) {
- ksmbd_debug(OPLOCK, "smb2_allocate_rsp_buf failed! ");
- goto out;
- }
-
- rsp_hdr = smb2_get_msg(work->response_buf);
- memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- *(__be32 *)work->response_buf =
- cpu_to_be32(conn->vals->header_size);
- rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
- rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
- rsp_hdr->CreditRequest = cpu_to_le16(0);
- rsp_hdr->Command = SMB2_OPLOCK_BREAK;
- rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
- rsp_hdr->NextCommand = 0;
- rsp_hdr->MessageId = cpu_to_le64(-1);
- rsp_hdr->Id.SyncId.ProcessId = 0;
- rsp_hdr->Id.SyncId.TreeId = 0;
- rsp_hdr->SessionId = 0;
- memset(rsp_hdr->Signature, 0, 16);
-
- rsp = smb2_get_msg(work->response_buf);
- rsp->StructureSize = cpu_to_le16(44);
- rsp->Epoch = br_info->epoch;
- rsp->Flags = 0;
-
- if (br_info->curr_state & (SMB2_LEASE_WRITE_CACHING_LE |
- SMB2_LEASE_HANDLE_CACHING_LE))
- rsp->Flags = SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;
-
- memcpy(rsp->LeaseKey, br_info->lease_key, SMB2_LEASE_KEY_SIZE);
- rsp->CurrentLeaseState = br_info->curr_state;
- rsp->NewLeaseState = br_info->new_state;
- rsp->BreakReason = 0;
- rsp->AccessMaskHint = 0;
- rsp->ShareMaskHint = 0;
-
- inc_rfc1001_len(work->response_buf, 44);
-
- ksmbd_conn_write(work);
-
-out:
- ksmbd_free_work_struct(work);
-}
-
-/**
- * smb2_lease_break_noti() - break lease when a new client request
- * write lease
- * @opinfo: conains lease state information
- *
- * Return: 0 on success, otherwise error
- */
-static int smb2_lease_break_noti(struct oplock_info *opinfo)
-{
- struct ksmbd_conn *conn = opinfo->conn;
- struct list_head *tmp, *t;
- struct ksmbd_work *work;
- struct lease_break_info *br_info;
- struct lease *lease = opinfo->o_lease;
-
- work = ksmbd_alloc_work_struct();
- if (!work)
- return -ENOMEM;
-
- br_info = kmalloc(sizeof(struct lease_break_info), GFP_KERNEL);
- if (!br_info) {
- ksmbd_free_work_struct(work);
- return -ENOMEM;
- }
-
- br_info->curr_state = lease->state;
- br_info->new_state = lease->new_state;
- if (lease->version == 2)
- br_info->epoch = cpu_to_le16(++lease->epoch);
- else
- br_info->epoch = 0;
- memcpy(br_info->lease_key, lease->lease_key, SMB2_LEASE_KEY_SIZE);
-
- work->request_buf = (char *)br_info;
- work->conn = conn;
- work->sess = opinfo->sess;
-
- if (opinfo->op_state == OPLOCK_ACK_WAIT) {
- list_for_each_safe(tmp, t, &opinfo->interim_list) {
- struct ksmbd_work *in_work;
-
- in_work = list_entry(tmp, struct ksmbd_work,
- interim_entry);
- setup_async_work(in_work, NULL, NULL);
- smb2_send_interim_resp(in_work, STATUS_PENDING);
- list_del(&in_work->interim_entry);
- }
- INIT_WORK(&work->work, __smb2_lease_break_noti);
- ksmbd_queue_work(work);
- wait_for_break_ack(opinfo);
- } else {
- __smb2_lease_break_noti(&work->work);
- if (opinfo->o_lease->new_state == SMB2_LEASE_NONE_LE) {
- opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
- opinfo->o_lease->state = SMB2_LEASE_NONE_LE;
- }
- }
- return 0;
-}
-
-static void wait_lease_breaking(struct oplock_info *opinfo)
-{
- if (!opinfo->is_lease)
- return;
-
- wake_up_interruptible_all(&opinfo->oplock_brk);
- if (atomic_read(&opinfo->breaking_cnt)) {
- int ret = 0;
-
- ret = wait_event_interruptible_timeout(opinfo->oplock_brk,
- atomic_read(&opinfo->breaking_cnt) == 0,
- HZ);
- if (!ret)
- atomic_set(&opinfo->breaking_cnt, 0);
- }
-}
-
-static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level)
-{
- int err = 0;
-
- /* Need to break exclusive/batch oplock, write lease or overwrite_if */
- ksmbd_debug(OPLOCK,
- "request to send oplock(level : 0x%x) break notification\n",
- brk_opinfo->level);
-
- if (brk_opinfo->is_lease) {
- struct lease *lease = brk_opinfo->o_lease;
-
- atomic_inc(&brk_opinfo->breaking_cnt);
-
- err = oplock_break_pending(brk_opinfo, req_op_level);
- if (err)
- return err < 0 ? err : 0;
-
- if (brk_opinfo->open_trunc) {
- /*
- * Create overwrite break trigger the lease break to
- * none.
- */
- lease->new_state = SMB2_LEASE_NONE_LE;
- } else {
- if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) {
- if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
- lease->new_state =
- SMB2_LEASE_READ_CACHING_LE |
- SMB2_LEASE_HANDLE_CACHING_LE;
- else
- lease->new_state =
- SMB2_LEASE_READ_CACHING_LE;
- } else {
- if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
- lease->new_state =
- SMB2_LEASE_READ_CACHING_LE;
- else
- lease->new_state = SMB2_LEASE_NONE_LE;
- }
- }
-
- if (lease->state & (SMB2_LEASE_WRITE_CACHING_LE |
- SMB2_LEASE_HANDLE_CACHING_LE))
- brk_opinfo->op_state = OPLOCK_ACK_WAIT;
- else
- atomic_dec(&brk_opinfo->breaking_cnt);
- } else {
- err = oplock_break_pending(brk_opinfo, req_op_level);
- if (err)
- return err < 0 ? err : 0;
-
- if (brk_opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||
- brk_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
- brk_opinfo->op_state = OPLOCK_ACK_WAIT;
- }
-
- if (brk_opinfo->is_lease)
- err = smb2_lease_break_noti(brk_opinfo);
- else
- err = smb2_oplock_break_noti(brk_opinfo);
-
- ksmbd_debug(OPLOCK, "oplock granted = %d\n", brk_opinfo->level);
- if (brk_opinfo->op_state == OPLOCK_CLOSING)
- err = -ENOENT;
- wake_up_oplock_break(brk_opinfo);
-
- wait_lease_breaking(brk_opinfo);
-
- return err;
-}
-
-void destroy_lease_table(struct ksmbd_conn *conn)
-{
- struct lease_table *lb, *lbtmp;
- struct oplock_info *opinfo;
-
- write_lock(&lease_list_lock);
- if (list_empty(&lease_table_list)) {
- write_unlock(&lease_list_lock);
- return;
- }
-
- list_for_each_entry_safe(lb, lbtmp, &lease_table_list, l_entry) {
- if (conn && memcmp(lb->client_guid, conn->ClientGUID,
- SMB2_CLIENT_GUID_SIZE))
- continue;
-again:
- rcu_read_lock();
- list_for_each_entry_rcu(opinfo, &lb->lease_list,
- lease_entry) {
- rcu_read_unlock();
- lease_del_list(opinfo);
- goto again;
- }
- rcu_read_unlock();
- list_del(&lb->l_entry);
- kfree(lb);
- }
- write_unlock(&lease_list_lock);
-}
-
-int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
- struct lease_ctx_info *lctx)
-{
- struct oplock_info *opinfo;
- int err = 0;
- struct lease_table *lb;
-
- if (!lctx)
- return err;
-
- read_lock(&lease_list_lock);
- if (list_empty(&lease_table_list)) {
- read_unlock(&lease_list_lock);
- return 0;
- }
-
- list_for_each_entry(lb, &lease_table_list, l_entry) {
- if (!memcmp(lb->client_guid, sess->ClientGUID,
- SMB2_CLIENT_GUID_SIZE))
- goto found;
- }
- read_unlock(&lease_list_lock);
-
- return 0;
-
-found:
- rcu_read_lock();
- list_for_each_entry_rcu(opinfo, &lb->lease_list, lease_entry) {
- if (!atomic_inc_not_zero(&opinfo->refcount))
- continue;
- rcu_read_unlock();
- if (opinfo->o_fp->f_ci == ci)
- goto op_next;
- err = compare_guid_key(opinfo, sess->ClientGUID,
- lctx->lease_key);
- if (err) {
- err = -EINVAL;
- ksmbd_debug(OPLOCK,
- "found same lease key is already used in other files\n");
- opinfo_put(opinfo);
- goto out;
- }
-op_next:
- opinfo_put(opinfo);
- rcu_read_lock();
- }
- rcu_read_unlock();
-
-out:
- read_unlock(&lease_list_lock);
- return err;
-}
-
-static void copy_lease(struct oplock_info *op1, struct oplock_info *op2)
-{
- struct lease *lease1 = op1->o_lease;
- struct lease *lease2 = op2->o_lease;
-
- op2->level = op1->level;
- lease2->state = lease1->state;
- memcpy(lease2->lease_key, lease1->lease_key,
- SMB2_LEASE_KEY_SIZE);
- lease2->duration = lease1->duration;
- lease2->flags = lease1->flags;
-}
-
-static int add_lease_global_list(struct oplock_info *opinfo)
-{
- struct lease_table *lb;
-
- read_lock(&lease_list_lock);
- list_for_each_entry(lb, &lease_table_list, l_entry) {
- if (!memcmp(lb->client_guid, opinfo->conn->ClientGUID,
- SMB2_CLIENT_GUID_SIZE)) {
- opinfo->o_lease->l_lb = lb;
- lease_add_list(opinfo);
- read_unlock(&lease_list_lock);
- return 0;
- }
- }
- read_unlock(&lease_list_lock);
-
- lb = kmalloc(sizeof(struct lease_table), GFP_KERNEL);
- if (!lb)
- return -ENOMEM;
-
- memcpy(lb->client_guid, opinfo->conn->ClientGUID,
- SMB2_CLIENT_GUID_SIZE);
- INIT_LIST_HEAD(&lb->lease_list);
- spin_lock_init(&lb->lb_lock);
- opinfo->o_lease->l_lb = lb;
- lease_add_list(opinfo);
- lb_add(lb);
- return 0;
-}
-
-static void set_oplock_level(struct oplock_info *opinfo, int level,
- struct lease_ctx_info *lctx)
-{
- switch (level) {
- case SMB2_OPLOCK_LEVEL_BATCH:
- case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
- grant_write_oplock(opinfo, level, lctx);
- break;
- case SMB2_OPLOCK_LEVEL_II:
- grant_read_oplock(opinfo, lctx);
- break;
- default:
- grant_none_oplock(opinfo, lctx);
- break;
- }
-}
-
-/**
- * smb_grant_oplock() - handle oplock/lease request on file open
- * @work: smb work
- * @req_op_level: oplock level
- * @pid: id of open file
- * @fp: ksmbd file pointer
- * @tid: Tree id of connection
- * @lctx: lease context information on file open
- * @share_ret: share mode
- *
- * Return: 0 on success, otherwise error
- */
-int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
- struct ksmbd_file *fp, __u16 tid,
- struct lease_ctx_info *lctx, int share_ret)
-{
- struct ksmbd_session *sess = work->sess;
- int err = 0;
- struct oplock_info *opinfo = NULL, *prev_opinfo = NULL;
- struct ksmbd_inode *ci = fp->f_ci;
- bool prev_op_has_lease;
- __le32 prev_op_state = 0;
-
- /* not support directory lease */
- if (S_ISDIR(file_inode(fp->filp)->i_mode))
- return 0;
-
- opinfo = alloc_opinfo(work, pid, tid);
- if (!opinfo)
- return -ENOMEM;
-
- if (lctx) {
- err = alloc_lease(opinfo, lctx);
- if (err)
- goto err_out;
- opinfo->is_lease = 1;
- }
-
- /* ci does not have any oplock */
- if (!opinfo_count(fp))
- goto set_lev;
-
- /* grant none-oplock if second open is trunc */
- if (fp->attrib_only && fp->cdoption != FILE_OVERWRITE_IF_LE &&
- fp->cdoption != FILE_OVERWRITE_LE &&
- fp->cdoption != FILE_SUPERSEDE_LE) {
- req_op_level = SMB2_OPLOCK_LEVEL_NONE;
- goto set_lev;
- }
-
- if (lctx) {
- struct oplock_info *m_opinfo;
-
- /* is lease already granted ? */
- m_opinfo = same_client_has_lease(ci, sess->ClientGUID,
- lctx);
- if (m_opinfo) {
- copy_lease(m_opinfo, opinfo);
- if (atomic_read(&m_opinfo->breaking_cnt))
- opinfo->o_lease->flags =
- SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE;
- goto out;
- }
- }
- prev_opinfo = opinfo_get_list(ci);
- if (!prev_opinfo ||
- (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx)) {
- opinfo_conn_put(prev_opinfo);
- goto set_lev;
- }
- prev_op_has_lease = prev_opinfo->is_lease;
- if (prev_op_has_lease)
- prev_op_state = prev_opinfo->o_lease->state;
-
- if (share_ret < 0 &&
- prev_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
- err = share_ret;
- opinfo_conn_put(prev_opinfo);
- goto err_out;
- }
-
- if (prev_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
- prev_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
- opinfo_conn_put(prev_opinfo);
- goto op_break_not_needed;
- }
-
- list_add(&work->interim_entry, &prev_opinfo->interim_list);
- err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II);
- opinfo_conn_put(prev_opinfo);
- if (err == -ENOENT)
- goto set_lev;
- /* Check all oplock was freed by close */
- else if (err < 0)
- goto err_out;
-
-op_break_not_needed:
- if (share_ret < 0) {
- err = share_ret;
- goto err_out;
- }
-
- if (req_op_level != SMB2_OPLOCK_LEVEL_NONE)
- req_op_level = SMB2_OPLOCK_LEVEL_II;
-
- /* grant fixed oplock on stacked locking between lease and oplock */
- if (prev_op_has_lease && !lctx)
- if (prev_op_state & SMB2_LEASE_HANDLE_CACHING_LE)
- req_op_level = SMB2_OPLOCK_LEVEL_NONE;
-
- if (!prev_op_has_lease && lctx) {
- req_op_level = SMB2_OPLOCK_LEVEL_II;
- lctx->req_state = SMB2_LEASE_READ_CACHING_LE;
- }
-
-set_lev:
- set_oplock_level(opinfo, req_op_level, lctx);
-
-out:
- rcu_assign_pointer(fp->f_opinfo, opinfo);
- opinfo->o_fp = fp;
-
- opinfo_count_inc(fp);
- opinfo_add(opinfo);
- if (opinfo->is_lease) {
- err = add_lease_global_list(opinfo);
- if (err)
- goto err_out;
- }
-
- return 0;
-err_out:
- free_opinfo(opinfo);
- return err;
-}
-
-/**
- * smb_break_all_write_oplock() - break batch/exclusive oplock to level2
- * @work: smb work
- * @fp: ksmbd file pointer
- * @is_trunc: truncate on open
- */
-static void smb_break_all_write_oplock(struct ksmbd_work *work,
- struct ksmbd_file *fp, int is_trunc)
-{
- struct oplock_info *brk_opinfo;
-
- brk_opinfo = opinfo_get_list(fp->f_ci);
- if (!brk_opinfo)
- return;
- if (brk_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
- brk_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
- opinfo_conn_put(brk_opinfo);
- return;
- }
-
- brk_opinfo->open_trunc = is_trunc;
- list_add(&work->interim_entry, &brk_opinfo->interim_list);
- oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II);
- opinfo_conn_put(brk_opinfo);
-}
-
-/**
- * smb_break_all_levII_oplock() - send level2 oplock or read lease break command
- * from server to client
- * @work: smb work
- * @fp: ksmbd file pointer
- * @is_trunc: truncate on open
- */
-void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
- int is_trunc)
-{
- struct oplock_info *op, *brk_op;
- struct ksmbd_inode *ci;
- struct ksmbd_conn *conn = work->conn;
-
- if (!test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_OPLOCKS))
- return;
-
- ci = fp->f_ci;
- op = opinfo_get(fp);
-
- rcu_read_lock();
- list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) {
- if (!atomic_inc_not_zero(&brk_op->refcount))
- continue;
-
- atomic_inc(&brk_op->conn->r_count);
- if (ksmbd_conn_releasing(brk_op->conn)) {
- atomic_dec(&brk_op->conn->r_count);
- continue;
- }
-
- rcu_read_unlock();
- if (brk_op->is_lease && (brk_op->o_lease->state &
- (~(SMB2_LEASE_READ_CACHING_LE |
- SMB2_LEASE_HANDLE_CACHING_LE)))) {
- ksmbd_debug(OPLOCK, "unexpected lease state(0x%x)\n",
- brk_op->o_lease->state);
- goto next;
- } else if (brk_op->level !=
- SMB2_OPLOCK_LEVEL_II) {
- ksmbd_debug(OPLOCK, "unexpected oplock(0x%x)\n",
- brk_op->level);
- goto next;
- }
-
- /* Skip oplock being break to none */
- if (brk_op->is_lease &&
- brk_op->o_lease->new_state == SMB2_LEASE_NONE_LE &&
- atomic_read(&brk_op->breaking_cnt))
- goto next;
-
- if (op && op->is_lease && brk_op->is_lease &&
- !memcmp(conn->ClientGUID, brk_op->conn->ClientGUID,
- SMB2_CLIENT_GUID_SIZE) &&
- !memcmp(op->o_lease->lease_key, brk_op->o_lease->lease_key,
- SMB2_LEASE_KEY_SIZE))
- goto next;
- brk_op->open_trunc = is_trunc;
- oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE);
-next:
- opinfo_conn_put(brk_op);
- rcu_read_lock();
- }
- rcu_read_unlock();
-
- if (op)
- opinfo_put(op);
-}
-
-/**
- * smb_break_all_oplock() - break both batch/exclusive and level2 oplock
- * @work: smb work
- * @fp: ksmbd file pointer
- */
-void smb_break_all_oplock(struct ksmbd_work *work, struct ksmbd_file *fp)
-{
- if (!test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_OPLOCKS))
- return;
-
- smb_break_all_write_oplock(work, fp, 1);
- smb_break_all_levII_oplock(work, fp, 1);
-}
-
-/**
- * smb2_map_lease_to_oplock() - map lease state to corresponding oplock type
- * @lease_state: lease type
- *
- * Return: 0 if no mapping, otherwise corresponding oplock type
- */
-__u8 smb2_map_lease_to_oplock(__le32 lease_state)
-{
- if (lease_state == (SMB2_LEASE_HANDLE_CACHING_LE |
- SMB2_LEASE_READ_CACHING_LE |
- SMB2_LEASE_WRITE_CACHING_LE)) {
- return SMB2_OPLOCK_LEVEL_BATCH;
- } else if (lease_state != SMB2_LEASE_WRITE_CACHING_LE &&
- lease_state & SMB2_LEASE_WRITE_CACHING_LE) {
- if (!(lease_state & SMB2_LEASE_HANDLE_CACHING_LE))
- return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
- } else if (lease_state & SMB2_LEASE_READ_CACHING_LE) {
- return SMB2_OPLOCK_LEVEL_II;
- }
- return 0;
-}
-
-/**
- * create_lease_buf() - create lease context for open cmd response
- * @rbuf: buffer to create lease context response
- * @lease: buffer to stored parsed lease state information
- */
-void create_lease_buf(u8 *rbuf, struct lease *lease)
-{
- if (lease->version == 2) {
- struct create_lease_v2 *buf = (struct create_lease_v2 *)rbuf;
-
- memset(buf, 0, sizeof(struct create_lease_v2));
- memcpy(buf->lcontext.LeaseKey, lease->lease_key,
- SMB2_LEASE_KEY_SIZE);
- buf->lcontext.LeaseFlags = lease->flags;
- buf->lcontext.LeaseState = lease->state;
- memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
- SMB2_LEASE_KEY_SIZE);
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_lease_v2, lcontext));
- buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_lease_v2, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- buf->Name[0] = 'R';
- buf->Name[1] = 'q';
- buf->Name[2] = 'L';
- buf->Name[3] = 's';
- } else {
- struct create_lease *buf = (struct create_lease *)rbuf;
-
- memset(buf, 0, sizeof(struct create_lease));
- memcpy(buf->lcontext.LeaseKey, lease->lease_key, SMB2_LEASE_KEY_SIZE);
- buf->lcontext.LeaseFlags = lease->flags;
- buf->lcontext.LeaseState = lease->state;
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_lease, lcontext));
- buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_lease, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- buf->Name[0] = 'R';
- buf->Name[1] = 'q';
- buf->Name[2] = 'L';
- buf->Name[3] = 's';
- }
-}
-
-/**
- * parse_lease_state() - parse lease context containted in file open request
- * @open_req: buffer containing smb2 file open(create) request
- *
- * Return: oplock state, -ENOENT if create lease context not found
- */
-struct lease_ctx_info *parse_lease_state(void *open_req)
-{
- struct create_context *cc;
- struct smb2_create_req *req = (struct smb2_create_req *)open_req;
- struct lease_ctx_info *lreq;
-
- cc = smb2_find_context_vals(req, SMB2_CREATE_REQUEST_LEASE, 4);
- if (IS_ERR_OR_NULL(cc))
- return NULL;
-
- lreq = kzalloc(sizeof(struct lease_ctx_info), GFP_KERNEL);
- if (!lreq)
- return NULL;
-
- if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
- struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
-
- memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
- lreq->req_state = lc->lcontext.LeaseState;
- lreq->flags = lc->lcontext.LeaseFlags;
- lreq->duration = lc->lcontext.LeaseDuration;
- memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
- SMB2_LEASE_KEY_SIZE);
- lreq->version = 2;
- } else {
- struct create_lease *lc = (struct create_lease *)cc;
-
- memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
- lreq->req_state = lc->lcontext.LeaseState;
- lreq->flags = lc->lcontext.LeaseFlags;
- lreq->duration = lc->lcontext.LeaseDuration;
- lreq->version = 1;
- }
- return lreq;
-}
-
-/**
- * smb2_find_context_vals() - find a particular context info in open request
- * @open_req: buffer containing smb2 file open(create) request
- * @tag: context name to search for
- * @tag_len: the length of tag
- *
- * Return: pointer to requested context, NULL if @str context not found
- * or error pointer if name length is invalid.
- */
-struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len)
-{
- struct create_context *cc;
- unsigned int next = 0;
- char *name;
- struct smb2_create_req *req = (struct smb2_create_req *)open_req;
- unsigned int remain_len, name_off, name_len, value_off, value_len,
- cc_len;
-
- /*
- * CreateContextsOffset and CreateContextsLength are guaranteed to
- * be valid because of ksmbd_smb2_check_message().
- */
- cc = (struct create_context *)((char *)req +
- le32_to_cpu(req->CreateContextsOffset));
- remain_len = le32_to_cpu(req->CreateContextsLength);
- do {
- cc = (struct create_context *)((char *)cc + next);
- if (remain_len < offsetof(struct create_context, Buffer))
- return ERR_PTR(-EINVAL);
-
- next = le32_to_cpu(cc->Next);
- name_off = le16_to_cpu(cc->NameOffset);
- name_len = le16_to_cpu(cc->NameLength);
- value_off = le16_to_cpu(cc->DataOffset);
- value_len = le32_to_cpu(cc->DataLength);
- cc_len = next ? next : remain_len;
-
- if ((next & 0x7) != 0 ||
- next > remain_len ||
- name_off != offsetof(struct create_context, Buffer) ||
- name_len < 4 ||
- name_off + name_len > cc_len ||
- (value_off & 0x7) != 0 ||
- (value_off && (value_off < name_off + name_len)) ||
- ((u64)value_off + value_len > cc_len))
- return ERR_PTR(-EINVAL);
-
- name = (char *)cc + name_off;
- if (name_len == tag_len && !memcmp(name, tag, name_len))
- return cc;
-
- remain_len -= next;
- } while (next != 0);
-
- return NULL;
-}
-
-/**
- * create_durable_rsp_buf() - create durable handle context
- * @cc: buffer to create durable context response
- */
-void create_durable_rsp_buf(char *cc)
-{
- struct create_durable_rsp *buf;
-
- buf = (struct create_durable_rsp *)cc;
- memset(buf, 0, sizeof(struct create_durable_rsp));
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_durable_rsp, Data));
- buf->ccontext.DataLength = cpu_to_le32(8);
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_durable_rsp, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_DURABLE_HANDLE_RESPONSE is "DHnQ" */
- buf->Name[0] = 'D';
- buf->Name[1] = 'H';
- buf->Name[2] = 'n';
- buf->Name[3] = 'Q';
-}
-
-/**
- * create_durable_v2_rsp_buf() - create durable handle v2 context
- * @cc: buffer to create durable context response
- * @fp: ksmbd file pointer
- */
-void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp)
-{
- struct create_durable_v2_rsp *buf;
-
- buf = (struct create_durable_v2_rsp *)cc;
- memset(buf, 0, sizeof(struct create_durable_rsp));
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_durable_rsp, Data));
- buf->ccontext.DataLength = cpu_to_le32(8);
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_durable_rsp, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2 is "DH2Q" */
- buf->Name[0] = 'D';
- buf->Name[1] = 'H';
- buf->Name[2] = '2';
- buf->Name[3] = 'Q';
-
- buf->Timeout = cpu_to_le32(fp->durable_timeout);
-}
-
-/**
- * create_mxac_rsp_buf() - create query maximal access context
- * @cc: buffer to create maximal access context response
- * @maximal_access: maximal access
- */
-void create_mxac_rsp_buf(char *cc, int maximal_access)
-{
- struct create_mxac_rsp *buf;
-
- buf = (struct create_mxac_rsp *)cc;
- memset(buf, 0, sizeof(struct create_mxac_rsp));
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_mxac_rsp, QueryStatus));
- buf->ccontext.DataLength = cpu_to_le32(8);
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_mxac_rsp, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE is "MxAc" */
- buf->Name[0] = 'M';
- buf->Name[1] = 'x';
- buf->Name[2] = 'A';
- buf->Name[3] = 'c';
-
- buf->QueryStatus = STATUS_SUCCESS;
- buf->MaximalAccess = cpu_to_le32(maximal_access);
-}
-
-void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id)
-{
- struct create_disk_id_rsp *buf;
-
- buf = (struct create_disk_id_rsp *)cc;
- memset(buf, 0, sizeof(struct create_disk_id_rsp));
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_disk_id_rsp, DiskFileId));
- buf->ccontext.DataLength = cpu_to_le32(32);
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_mxac_rsp, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- /* SMB2_CREATE_QUERY_ON_DISK_ID_RESPONSE is "QFid" */
- buf->Name[0] = 'Q';
- buf->Name[1] = 'F';
- buf->Name[2] = 'i';
- buf->Name[3] = 'd';
-
- buf->DiskFileId = cpu_to_le64(file_id);
- buf->VolumeId = cpu_to_le64(vol_id);
-}
-
-/**
- * create_posix_rsp_buf() - create posix extension context
- * @cc: buffer to create posix on posix response
- * @fp: ksmbd file pointer
- */
-void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
-{
- struct create_posix_rsp *buf;
- struct inode *inode = file_inode(fp->filp);
- struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
- vfsuid_t vfsuid = i_uid_into_vfsuid(user_ns, inode);
- vfsgid_t vfsgid = i_gid_into_vfsgid(user_ns, inode);
-
- buf = (struct create_posix_rsp *)cc;
- memset(buf, 0, sizeof(struct create_posix_rsp));
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_posix_rsp, nlink));
- /*
- * DataLength = nlink(4) + reparse_tag(4) + mode(4) +
- * domain sid(28) + unix group sid(16).
- */
- buf->ccontext.DataLength = cpu_to_le32(56);
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
- (struct create_posix_rsp, Name));
- buf->ccontext.NameLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
- /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
- buf->Name[0] = 0x93;
- buf->Name[1] = 0xAD;
- buf->Name[2] = 0x25;
- buf->Name[3] = 0x50;
- buf->Name[4] = 0x9C;
- buf->Name[5] = 0xB4;
- buf->Name[6] = 0x11;
- buf->Name[7] = 0xE7;
- buf->Name[8] = 0xB4;
- buf->Name[9] = 0x23;
- buf->Name[10] = 0x83;
- buf->Name[11] = 0xDE;
- buf->Name[12] = 0x96;
- buf->Name[13] = 0x8B;
- buf->Name[14] = 0xCD;
- buf->Name[15] = 0x7C;
-
- buf->nlink = cpu_to_le32(inode->i_nlink);
- buf->reparse_tag = cpu_to_le32(fp->volatile_id);
- buf->mode = cpu_to_le32(inode->i_mode & 0777);
- /*
- * SidBuffer(44) contain two sids(Domain sid(28), UNIX group sid(16)).
- * Domain sid(28) = revision(1) + num_subauth(1) + authority(6) +
- * sub_auth(4 * 4(num_subauth)) + RID(4).
- * UNIX group id(16) = revision(1) + num_subauth(1) + authority(6) +
- * sub_auth(4 * 1(num_subauth)) + RID(4).
- */
- id_to_sid(from_kuid_munged(&init_user_ns, vfsuid_into_kuid(vfsuid)),
- SIDOWNER, (struct smb_sid *)&buf->SidBuffer[0]);
- id_to_sid(from_kgid_munged(&init_user_ns, vfsgid_into_kgid(vfsgid)),
- SIDUNIX_GROUP, (struct smb_sid *)&buf->SidBuffer[28]);
-}
-
-/*
- * Find lease object(opinfo) for given lease key/fid from lease
- * break/file close path.
- */
-/**
- * lookup_lease_in_table() - find a matching lease info object
- * @conn: connection instance
- * @lease_key: lease key to be searched for
- *
- * Return: opinfo if found matching opinfo, otherwise NULL
- */
-struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
- char *lease_key)
-{
- struct oplock_info *opinfo = NULL, *ret_op = NULL;
- struct lease_table *lt;
- int ret;
-
- read_lock(&lease_list_lock);
- list_for_each_entry(lt, &lease_table_list, l_entry) {
- if (!memcmp(lt->client_guid, conn->ClientGUID,
- SMB2_CLIENT_GUID_SIZE))
- goto found;
- }
-
- read_unlock(&lease_list_lock);
- return NULL;
-
-found:
- rcu_read_lock();
- list_for_each_entry_rcu(opinfo, <->lease_list, lease_entry) {
- if (!atomic_inc_not_zero(&opinfo->refcount))
- continue;
- rcu_read_unlock();
- if (!opinfo->op_state || opinfo->op_state == OPLOCK_CLOSING)
- goto op_next;
- if (!(opinfo->o_lease->state &
- (SMB2_LEASE_HANDLE_CACHING_LE |
- SMB2_LEASE_WRITE_CACHING_LE)))
- goto op_next;
- ret = compare_guid_key(opinfo, conn->ClientGUID,
- lease_key);
- if (ret) {
- ksmbd_debug(OPLOCK, "found opinfo\n");
- ret_op = opinfo;
- goto out;
- }
-op_next:
- opinfo_put(opinfo);
- rcu_read_lock();
- }
- rcu_read_unlock();
-
-out:
- read_unlock(&lease_list_lock);
- return ret_op;
-}
diff --git a/fs/ksmbd/oplock.h b/fs/ksmbd/oplock.h
deleted file mode 100644
index 4b0fe6da7694..000000000000
--- a/fs/ksmbd/oplock.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_OPLOCK_H
-#define __KSMBD_OPLOCK_H
-
-#include "smb_common.h"
-
-#define OPLOCK_WAIT_TIME (35 * HZ)
-
-/* SMB2 Oplock levels */
-#define SMB2_OPLOCK_LEVEL_NONE 0x00
-#define SMB2_OPLOCK_LEVEL_II 0x01
-#define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08
-#define SMB2_OPLOCK_LEVEL_BATCH 0x09
-#define SMB2_OPLOCK_LEVEL_LEASE 0xFF
-
-/* Oplock states */
-#define OPLOCK_STATE_NONE 0x00
-#define OPLOCK_ACK_WAIT 0x01
-#define OPLOCK_CLOSING 0x02
-
-#define OPLOCK_WRITE_TO_READ 0x01
-#define OPLOCK_READ_HANDLE_TO_READ 0x02
-#define OPLOCK_WRITE_TO_NONE 0x04
-#define OPLOCK_READ_TO_NONE 0x08
-
-struct lease_ctx_info {
- __u8 lease_key[SMB2_LEASE_KEY_SIZE];
- __le32 req_state;
- __le32 flags;
- __le64 duration;
- __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE];
- int version;
-};
-
-struct lease_table {
- char client_guid[SMB2_CLIENT_GUID_SIZE];
- struct list_head lease_list;
- struct list_head l_entry;
- spinlock_t lb_lock;
-};
-
-struct lease {
- __u8 lease_key[SMB2_LEASE_KEY_SIZE];
- __le32 state;
- __le32 new_state;
- __le32 flags;
- __le64 duration;
- __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE];
- int version;
- unsigned short epoch;
- struct lease_table *l_lb;
-};
-
-struct oplock_info {
- struct ksmbd_conn *conn;
- struct ksmbd_session *sess;
- struct ksmbd_work *work;
- struct ksmbd_file *o_fp;
- int level;
- int op_state;
- unsigned long pending_break;
- u64 fid;
- atomic_t breaking_cnt;
- atomic_t refcount;
- __u16 Tid;
- bool is_lease;
- bool open_trunc; /* truncate on open */
- struct lease *o_lease;
- struct list_head interim_list;
- struct list_head op_entry;
- struct list_head lease_entry;
- wait_queue_head_t oplock_q; /* Other server threads */
- wait_queue_head_t oplock_brk; /* oplock breaking wait */
- struct rcu_head rcu_head;
-};
-
-struct lease_break_info {
- __le32 curr_state;
- __le32 new_state;
- __le16 epoch;
- char lease_key[SMB2_LEASE_KEY_SIZE];
-};
-
-struct oplock_break_info {
- int level;
- int open_trunc;
- int fid;
-};
-
-int smb_grant_oplock(struct ksmbd_work *work, int req_op_level,
- u64 pid, struct ksmbd_file *fp, __u16 tid,
- struct lease_ctx_info *lctx, int share_ret);
-void smb_break_all_levII_oplock(struct ksmbd_work *work,
- struct ksmbd_file *fp, int is_trunc);
-int opinfo_write_to_read(struct oplock_info *opinfo);
-int opinfo_read_handle_to_read(struct oplock_info *opinfo);
-int opinfo_write_to_none(struct oplock_info *opinfo);
-int opinfo_read_to_none(struct oplock_info *opinfo);
-void close_id_del_oplock(struct ksmbd_file *fp);
-void smb_break_all_oplock(struct ksmbd_work *work, struct ksmbd_file *fp);
-struct oplock_info *opinfo_get(struct ksmbd_file *fp);
-void opinfo_put(struct oplock_info *opinfo);
-
-/* Lease related functions */
-void create_lease_buf(u8 *rbuf, struct lease *lease);
-struct lease_ctx_info *parse_lease_state(void *open_req);
-__u8 smb2_map_lease_to_oplock(__le32 lease_state);
-int lease_read_to_write(struct oplock_info *opinfo);
-
-/* Durable related functions */
-void create_durable_rsp_buf(char *cc);
-void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp);
-void create_mxac_rsp_buf(char *cc, int maximal_access);
-void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id);
-void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp);
-struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len);
-struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
- char *lease_key);
-int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
- struct lease_ctx_info *lctx);
-void destroy_lease_table(struct ksmbd_conn *conn);
-#endif /* __KSMBD_OPLOCK_H */
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
deleted file mode 100644
index 8a0ad399f245..000000000000
--- a/fs/ksmbd/server.c
+++ /dev/null
@@ -1,639 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include "glob.h"
-#include "oplock.h"
-#include "misc.h"
-#include <linux/sched/signal.h>
-#include <linux/workqueue.h>
-#include <linux/sysfs.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include "server.h"
-#include "smb_common.h"
-#include "smbstatus.h"
-#include "connection.h"
-#include "transport_ipc.h"
-#include "mgmt/user_session.h"
-#include "crypto_ctx.h"
-#include "auth.h"
-
-int ksmbd_debug_types;
-
-struct ksmbd_server_config server_conf;
-
-enum SERVER_CTRL_TYPE {
- SERVER_CTRL_TYPE_INIT,
- SERVER_CTRL_TYPE_RESET,
-};
-
-struct server_ctrl_struct {
- int type;
- struct work_struct ctrl_work;
-};
-
-static DEFINE_MUTEX(ctrl_lock);
-
-static int ___server_conf_set(int idx, char *val)
-{
- if (idx >= ARRAY_SIZE(server_conf.conf))
- return -EINVAL;
-
- if (!val || val[0] == 0x00)
- return -EINVAL;
-
- kfree(server_conf.conf[idx]);
- server_conf.conf[idx] = kstrdup(val, GFP_KERNEL);
- if (!server_conf.conf[idx])
- return -ENOMEM;
- return 0;
-}
-
-int ksmbd_set_netbios_name(char *v)
-{
- return ___server_conf_set(SERVER_CONF_NETBIOS_NAME, v);
-}
-
-int ksmbd_set_server_string(char *v)
-{
- return ___server_conf_set(SERVER_CONF_SERVER_STRING, v);
-}
-
-int ksmbd_set_work_group(char *v)
-{
- return ___server_conf_set(SERVER_CONF_WORK_GROUP, v);
-}
-
-char *ksmbd_netbios_name(void)
-{
- return server_conf.conf[SERVER_CONF_NETBIOS_NAME];
-}
-
-char *ksmbd_server_string(void)
-{
- return server_conf.conf[SERVER_CONF_SERVER_STRING];
-}
-
-char *ksmbd_work_group(void)
-{
- return server_conf.conf[SERVER_CONF_WORK_GROUP];
-}
-
-/**
- * check_conn_state() - check state of server thread connection
- * @work: smb work containing server thread information
- *
- * Return: 0 on valid connection, otherwise 1 to reconnect
- */
-static inline int check_conn_state(struct ksmbd_work *work)
-{
- struct smb_hdr *rsp_hdr;
-
- if (ksmbd_conn_exiting(work->conn) ||
- ksmbd_conn_need_reconnect(work->conn)) {
- rsp_hdr = work->response_buf;
- rsp_hdr->Status.CifsError = STATUS_CONNECTION_DISCONNECTED;
- return 1;
- }
- return 0;
-}
-
-#define SERVER_HANDLER_CONTINUE 0
-#define SERVER_HANDLER_ABORT 1
-
-static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
- u16 *cmd)
-{
- struct smb_version_cmds *cmds;
- u16 command;
- int ret;
-
- if (check_conn_state(work))
- return SERVER_HANDLER_CONTINUE;
-
- if (ksmbd_verify_smb_message(work))
- return SERVER_HANDLER_ABORT;
-
- command = conn->ops->get_cmd_val(work);
- *cmd = command;
-
-andx_again:
- if (command >= conn->max_cmds) {
- conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
- return SERVER_HANDLER_CONTINUE;
- }
-
- cmds = &conn->cmds[command];
- if (!cmds->proc) {
- ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command);
- conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED);
- return SERVER_HANDLER_CONTINUE;
- }
-
- if (work->sess && conn->ops->is_sign_req(work, command)) {
- ret = conn->ops->check_sign_req(work);
- if (!ret) {
- conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
- return SERVER_HANDLER_CONTINUE;
- }
- }
-
- ret = cmds->proc(work);
-
- if (ret < 0)
- ksmbd_debug(CONN, "Failed to process %u [%d]\n", command, ret);
- /* AndX commands - chained request can return positive values */
- else if (ret > 0) {
- command = ret;
- *cmd = command;
- goto andx_again;
- }
-
- if (work->send_no_response)
- return SERVER_HANDLER_ABORT;
- return SERVER_HANDLER_CONTINUE;
-}
-
-static void __handle_ksmbd_work(struct ksmbd_work *work,
- struct ksmbd_conn *conn)
-{
- u16 command = 0;
- int rc;
-
- if (conn->ops->allocate_rsp_buf(work))
- return;
-
- if (conn->ops->is_transform_hdr &&
- conn->ops->is_transform_hdr(work->request_buf)) {
- rc = conn->ops->decrypt_req(work);
- if (rc < 0) {
- conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
- goto send;
- }
-
- work->encrypted = true;
- }
-
- rc = conn->ops->init_rsp_hdr(work);
- if (rc) {
- /* either uid or tid is not correct */
- conn->ops->set_rsp_status(work, STATUS_INVALID_HANDLE);
- goto send;
- }
-
- if (conn->ops->check_user_session) {
- rc = conn->ops->check_user_session(work);
- if (rc < 0) {
- command = conn->ops->get_cmd_val(work);
- conn->ops->set_rsp_status(work,
- STATUS_USER_SESSION_DELETED);
- goto send;
- } else if (rc > 0) {
- rc = conn->ops->get_ksmbd_tcon(work);
- if (rc < 0) {
- conn->ops->set_rsp_status(work,
- STATUS_NETWORK_NAME_DELETED);
- goto send;
- }
- }
- }
-
- do {
- rc = __process_request(work, conn, &command);
- if (rc == SERVER_HANDLER_ABORT)
- break;
-
- /*
- * Call smb2_set_rsp_credits() function to set number of credits
- * granted in hdr of smb2 response.
- */
- if (conn->ops->set_rsp_credits) {
- spin_lock(&conn->credits_lock);
- rc = conn->ops->set_rsp_credits(work);
- spin_unlock(&conn->credits_lock);
- if (rc < 0) {
- conn->ops->set_rsp_status(work,
- STATUS_INVALID_PARAMETER);
- goto send;
- }
- }
-
- if (work->sess &&
- (work->sess->sign || smb3_11_final_sess_setup_resp(work) ||
- conn->ops->is_sign_req(work, command)))
- conn->ops->set_sign_rsp(work);
- } while (is_chained_smb2_message(work));
-
- if (work->send_no_response)
- return;
-
-send:
- smb3_preauth_hash_rsp(work);
- if (work->sess && work->sess->enc && work->encrypted &&
- conn->ops->encrypt_resp) {
- rc = conn->ops->encrypt_resp(work);
- if (rc < 0)
- conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
- }
-
- ksmbd_conn_write(work);
-}
-
-/**
- * handle_ksmbd_work() - process pending smb work requests
- * @wk: smb work containing request command buffer
- *
- * called by kworker threads to processing remaining smb work requests
- */
-static void handle_ksmbd_work(struct work_struct *wk)
-{
- struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
- struct ksmbd_conn *conn = work->conn;
-
- atomic64_inc(&conn->stats.request_served);
-
- __handle_ksmbd_work(work, conn);
-
- ksmbd_conn_try_dequeue_request(work);
- ksmbd_free_work_struct(work);
- /*
- * Checking waitqueue to dropping pending requests on
- * disconnection. waitqueue_active is safe because it
- * uses atomic operation for condition.
- */
- if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
- wake_up(&conn->r_count_q);
-}
-
-/**
- * queue_ksmbd_work() - queue a smb request to worker thread queue
- * for proccessing smb command and sending response
- * @conn: connection instance
- *
- * read remaining data from socket create and submit work.
- */
-static int queue_ksmbd_work(struct ksmbd_conn *conn)
-{
- struct ksmbd_work *work;
-
- work = ksmbd_alloc_work_struct();
- if (!work) {
- pr_err("allocation for work failed\n");
- return -ENOMEM;
- }
-
- work->conn = conn;
- work->request_buf = conn->request_buf;
- conn->request_buf = NULL;
-
- ksmbd_init_smb_server(work);
-
- ksmbd_conn_enqueue_request(work);
- atomic_inc(&conn->r_count);
- /* update activity on connection */
- conn->last_active = jiffies;
- INIT_WORK(&work->work, handle_ksmbd_work);
- ksmbd_queue_work(work);
- return 0;
-}
-
-static int ksmbd_server_process_request(struct ksmbd_conn *conn)
-{
- return queue_ksmbd_work(conn);
-}
-
-static int ksmbd_server_terminate_conn(struct ksmbd_conn *conn)
-{
- ksmbd_sessions_deregister(conn);
- destroy_lease_table(conn);
- return 0;
-}
-
-static void ksmbd_server_tcp_callbacks_init(void)
-{
- struct ksmbd_conn_ops ops;
-
- ops.process_fn = ksmbd_server_process_request;
- ops.terminate_fn = ksmbd_server_terminate_conn;
-
- ksmbd_conn_init_server_callbacks(&ops);
-}
-
-static void server_conf_free(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(server_conf.conf); i++) {
- kfree(server_conf.conf[i]);
- server_conf.conf[i] = NULL;
- }
-}
-
-static int server_conf_init(void)
-{
- WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP);
- server_conf.enforced_signing = 0;
- server_conf.min_protocol = ksmbd_min_protocol();
- server_conf.max_protocol = ksmbd_max_protocol();
- server_conf.auth_mechs = KSMBD_AUTH_NTLMSSP;
-#ifdef CONFIG_SMB_SERVER_KERBEROS5
- server_conf.auth_mechs |= KSMBD_AUTH_KRB5 |
- KSMBD_AUTH_MSKRB5;
-#endif
- return 0;
-}
-
-static void server_ctrl_handle_init(struct server_ctrl_struct *ctrl)
-{
- int ret;
-
- ret = ksmbd_conn_transport_init();
- if (ret) {
- server_queue_ctrl_reset_work();
- return;
- }
-
- WRITE_ONCE(server_conf.state, SERVER_STATE_RUNNING);
-}
-
-static void server_ctrl_handle_reset(struct server_ctrl_struct *ctrl)
-{
- ksmbd_ipc_soft_reset();
- ksmbd_conn_transport_destroy();
- server_conf_free();
- server_conf_init();
- WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP);
-}
-
-static void server_ctrl_handle_work(struct work_struct *work)
-{
- struct server_ctrl_struct *ctrl;
-
- ctrl = container_of(work, struct server_ctrl_struct, ctrl_work);
-
- mutex_lock(&ctrl_lock);
- switch (ctrl->type) {
- case SERVER_CTRL_TYPE_INIT:
- server_ctrl_handle_init(ctrl);
- break;
- case SERVER_CTRL_TYPE_RESET:
- server_ctrl_handle_reset(ctrl);
- break;
- default:
- pr_err("Unknown server work type: %d\n", ctrl->type);
- }
- mutex_unlock(&ctrl_lock);
- kfree(ctrl);
- module_put(THIS_MODULE);
-}
-
-static int __queue_ctrl_work(int type)
-{
- struct server_ctrl_struct *ctrl;
-
- ctrl = kmalloc(sizeof(struct server_ctrl_struct), GFP_KERNEL);
- if (!ctrl)
- return -ENOMEM;
-
- __module_get(THIS_MODULE);
- ctrl->type = type;
- INIT_WORK(&ctrl->ctrl_work, server_ctrl_handle_work);
- queue_work(system_long_wq, &ctrl->ctrl_work);
- return 0;
-}
-
-int server_queue_ctrl_init_work(void)
-{
- return __queue_ctrl_work(SERVER_CTRL_TYPE_INIT);
-}
-
-int server_queue_ctrl_reset_work(void)
-{
- return __queue_ctrl_work(SERVER_CTRL_TYPE_RESET);
-}
-
-static ssize_t stats_show(struct class *class, struct class_attribute *attr,
- char *buf)
-{
- /*
- * Inc this each time you change stats output format,
- * so user space will know what to do.
- */
- static int stats_version = 2;
- static const char * const state[] = {
- "startup",
- "running",
- "reset",
- "shutdown"
- };
-
- ssize_t sz = scnprintf(buf, PAGE_SIZE, "%d %s %d %lu\n", stats_version,
- state[server_conf.state], server_conf.tcp_port,
- server_conf.ipc_last_active / HZ);
- return sz;
-}
-
-static ssize_t kill_server_store(struct class *class,
- struct class_attribute *attr, const char *buf,
- size_t len)
-{
- if (!sysfs_streq(buf, "hard"))
- return len;
-
- pr_info("kill command received\n");
- mutex_lock(&ctrl_lock);
- WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
- __module_get(THIS_MODULE);
- server_ctrl_handle_reset(NULL);
- module_put(THIS_MODULE);
- mutex_unlock(&ctrl_lock);
- return len;
-}
-
-static const char * const debug_type_strings[] = {"smb", "auth", "vfs",
- "oplock", "ipc", "conn",
- "rdma"};
-
-static ssize_t debug_show(struct class *class, struct class_attribute *attr,
- char *buf)
-{
- ssize_t sz = 0;
- int i, pos = 0;
-
- for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) {
- if ((ksmbd_debug_types >> i) & 1) {
- pos = scnprintf(buf + sz,
- PAGE_SIZE - sz,
- "[%s] ",
- debug_type_strings[i]);
- } else {
- pos = scnprintf(buf + sz,
- PAGE_SIZE - sz,
- "%s ",
- debug_type_strings[i]);
- }
- sz += pos;
- }
- sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
- return sz;
-}
-
-static ssize_t debug_store(struct class *class, struct class_attribute *attr,
- const char *buf, size_t len)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) {
- if (sysfs_streq(buf, "all")) {
- if (ksmbd_debug_types == KSMBD_DEBUG_ALL)
- ksmbd_debug_types = 0;
- else
- ksmbd_debug_types = KSMBD_DEBUG_ALL;
- break;
- }
-
- if (sysfs_streq(buf, debug_type_strings[i])) {
- if (ksmbd_debug_types & (1 << i))
- ksmbd_debug_types &= ~(1 << i);
- else
- ksmbd_debug_types |= (1 << i);
- break;
- }
- }
-
- return len;
-}
-
-static CLASS_ATTR_RO(stats);
-static CLASS_ATTR_WO(kill_server);
-static CLASS_ATTR_RW(debug);
-
-static struct attribute *ksmbd_control_class_attrs[] = {
- &class_attr_stats.attr,
- &class_attr_kill_server.attr,
- &class_attr_debug.attr,
- NULL,
-};
-ATTRIBUTE_GROUPS(ksmbd_control_class);
-
-static struct class ksmbd_control_class = {
- .name = "ksmbd-control",
- .owner = THIS_MODULE,
- .class_groups = ksmbd_control_class_groups,
-};
-
-static int ksmbd_server_shutdown(void)
-{
- WRITE_ONCE(server_conf.state, SERVER_STATE_SHUTTING_DOWN);
-
- class_unregister(&ksmbd_control_class);
- ksmbd_workqueue_destroy();
- ksmbd_ipc_release();
- ksmbd_conn_transport_destroy();
- ksmbd_crypto_destroy();
- ksmbd_free_global_file_table();
- destroy_lease_table(NULL);
- ksmbd_work_pool_destroy();
- ksmbd_exit_file_cache();
- server_conf_free();
- return 0;
-}
-
-static int __init ksmbd_server_init(void)
-{
- int ret;
-
- ret = class_register(&ksmbd_control_class);
- if (ret) {
- pr_err("Unable to register ksmbd-control class\n");
- return ret;
- }
-
- ksmbd_server_tcp_callbacks_init();
-
- ret = server_conf_init();
- if (ret)
- goto err_unregister;
-
- ret = ksmbd_work_pool_init();
- if (ret)
- goto err_unregister;
-
- ret = ksmbd_init_file_cache();
- if (ret)
- goto err_destroy_work_pools;
-
- ret = ksmbd_ipc_init();
- if (ret)
- goto err_exit_file_cache;
-
- ret = ksmbd_init_global_file_table();
- if (ret)
- goto err_ipc_release;
-
- ret = ksmbd_inode_hash_init();
- if (ret)
- goto err_destroy_file_table;
-
- ret = ksmbd_crypto_create();
- if (ret)
- goto err_release_inode_hash;
-
- ret = ksmbd_workqueue_init();
- if (ret)
- goto err_crypto_destroy;
-
- pr_warn_once("The ksmbd server is experimental\n");
-
- return 0;
-
-err_crypto_destroy:
- ksmbd_crypto_destroy();
-err_release_inode_hash:
- ksmbd_release_inode_hash();
-err_destroy_file_table:
- ksmbd_free_global_file_table();
-err_ipc_release:
- ksmbd_ipc_release();
-err_exit_file_cache:
- ksmbd_exit_file_cache();
-err_destroy_work_pools:
- ksmbd_work_pool_destroy();
-err_unregister:
- class_unregister(&ksmbd_control_class);
-
- return ret;
-}
-
-/**
- * ksmbd_server_exit() - shutdown forker thread and free memory at module exit
- */
-static void __exit ksmbd_server_exit(void)
-{
- ksmbd_server_shutdown();
- rcu_barrier();
- ksmbd_release_inode_hash();
-}
-
-MODULE_AUTHOR("Namjae Jeon <linkinjeon@kernel.org>");
-MODULE_VERSION(KSMBD_VERSION);
-MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
-MODULE_LICENSE("GPL");
-MODULE_SOFTDEP("pre: ecb");
-MODULE_SOFTDEP("pre: hmac");
-MODULE_SOFTDEP("pre: md5");
-MODULE_SOFTDEP("pre: nls");
-MODULE_SOFTDEP("pre: aes");
-MODULE_SOFTDEP("pre: cmac");
-MODULE_SOFTDEP("pre: sha256");
-MODULE_SOFTDEP("pre: sha512");
-MODULE_SOFTDEP("pre: aead2");
-MODULE_SOFTDEP("pre: ccm");
-MODULE_SOFTDEP("pre: gcm");
-MODULE_SOFTDEP("pre: crc32");
-module_init(ksmbd_server_init)
-module_exit(ksmbd_server_exit)
diff --git a/fs/ksmbd/server.h b/fs/ksmbd/server.h
deleted file mode 100644
index db7278181760..000000000000
--- a/fs/ksmbd/server.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __SERVER_H__
-#define __SERVER_H__
-
-#include "smbacl.h"
-
-/*
- * Server state type
- */
-enum {
- SERVER_STATE_STARTING_UP,
- SERVER_STATE_RUNNING,
- SERVER_STATE_RESETTING,
- SERVER_STATE_SHUTTING_DOWN,
-};
-
-/*
- * Server global config string index
- */
-enum {
- SERVER_CONF_NETBIOS_NAME,
- SERVER_CONF_SERVER_STRING,
- SERVER_CONF_WORK_GROUP,
-};
-
-struct ksmbd_server_config {
- unsigned int flags;
- unsigned int state;
- short signing;
- short enforced_signing;
- short min_protocol;
- short max_protocol;
- unsigned short tcp_port;
- unsigned short ipc_timeout;
- unsigned long ipc_last_active;
- unsigned long deadtime;
- unsigned int share_fake_fscaps;
- struct smb_sid domain_sid;
- unsigned int auth_mechs;
- unsigned int max_connections;
-
- char *conf[SERVER_CONF_WORK_GROUP + 1];
-};
-
-extern struct ksmbd_server_config server_conf;
-
-int ksmbd_set_netbios_name(char *v);
-int ksmbd_set_server_string(char *v);
-int ksmbd_set_work_group(char *v);
-
-char *ksmbd_netbios_name(void);
-char *ksmbd_server_string(void);
-char *ksmbd_work_group(void);
-
-static inline int ksmbd_server_running(void)
-{
- return READ_ONCE(server_conf.state) == SERVER_STATE_RUNNING;
-}
-
-static inline int ksmbd_server_configurable(void)
-{
- return READ_ONCE(server_conf.state) < SERVER_STATE_RESETTING;
-}
-
-int server_queue_ctrl_init_work(void);
-int server_queue_ctrl_reset_work(void);
-#endif /* __SERVER_H__ */
diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c
deleted file mode 100644
index 0ffe663b7590..000000000000
--- a/fs/ksmbd/smb2misc.c
+++ /dev/null
@@ -1,447 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include "glob.h"
-#include "nterr.h"
-#include "smb_common.h"
-#include "smbstatus.h"
-#include "mgmt/user_session.h"
-#include "connection.h"
-
-static int check_smb2_hdr(struct smb2_hdr *hdr)
-{
- /*
- * Make sure that this really is an SMB, that it is a response.
- */
- if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
- return 1;
- return 0;
-}
-
-/*
- * The following table defines the expected "StructureSize" of SMB2 requests
- * in order by SMB2 command. This is similar to "wct" in SMB/CIFS requests.
- *
- * Note that commands are defined in smb2pdu.h in le16 but the array below is
- * indexed by command in host byte order
- */
-static const __le16 smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
- /* SMB2_NEGOTIATE */ cpu_to_le16(36),
- /* SMB2_SESSION_SETUP */ cpu_to_le16(25),
- /* SMB2_LOGOFF */ cpu_to_le16(4),
- /* SMB2_TREE_CONNECT */ cpu_to_le16(9),
- /* SMB2_TREE_DISCONNECT */ cpu_to_le16(4),
- /* SMB2_CREATE */ cpu_to_le16(57),
- /* SMB2_CLOSE */ cpu_to_le16(24),
- /* SMB2_FLUSH */ cpu_to_le16(24),
- /* SMB2_READ */ cpu_to_le16(49),
- /* SMB2_WRITE */ cpu_to_le16(49),
- /* SMB2_LOCK */ cpu_to_le16(48),
- /* SMB2_IOCTL */ cpu_to_le16(57),
- /* SMB2_CANCEL */ cpu_to_le16(4),
- /* SMB2_ECHO */ cpu_to_le16(4),
- /* SMB2_QUERY_DIRECTORY */ cpu_to_le16(33),
- /* SMB2_CHANGE_NOTIFY */ cpu_to_le16(32),
- /* SMB2_QUERY_INFO */ cpu_to_le16(41),
- /* SMB2_SET_INFO */ cpu_to_le16(33),
- /* use 44 for lease break */
- /* SMB2_OPLOCK_BREAK */ cpu_to_le16(36)
-};
-
-/*
- * The size of the variable area depends on the offset and length fields
- * located in different fields for various SMB2 requests. SMB2 requests
- * with no variable length info, show an offset of zero for the offset field.
- */
-static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
- /* SMB2_NEGOTIATE */ true,
- /* SMB2_SESSION_SETUP */ true,
- /* SMB2_LOGOFF */ false,
- /* SMB2_TREE_CONNECT */ true,
- /* SMB2_TREE_DISCONNECT */ false,
- /* SMB2_CREATE */ true,
- /* SMB2_CLOSE */ false,
- /* SMB2_FLUSH */ false,
- /* SMB2_READ */ true,
- /* SMB2_WRITE */ true,
- /* SMB2_LOCK */ true,
- /* SMB2_IOCTL */ true,
- /* SMB2_CANCEL */ false, /* BB CHECK this not listed in documentation */
- /* SMB2_ECHO */ false,
- /* SMB2_QUERY_DIRECTORY */ true,
- /* SMB2_CHANGE_NOTIFY */ false,
- /* SMB2_QUERY_INFO */ true,
- /* SMB2_SET_INFO */ true,
- /* SMB2_OPLOCK_BREAK */ false
-};
-
-/*
- * Set length of the data area and the offset to arguments.
- * if they are invalid, return error.
- */
-static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
- struct smb2_hdr *hdr)
-{
- int ret = 0;
-
- *off = 0;
- *len = 0;
-
- /*
- * Following commands have data areas so we have to get the location
- * of the data buffer offset and data buffer length for the particular
- * command.
- */
- switch (hdr->Command) {
- case SMB2_SESSION_SETUP:
- *off = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferOffset);
- *len = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferLength);
- break;
- case SMB2_TREE_CONNECT:
- *off = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset);
- *len = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathLength);
- break;
- case SMB2_CREATE:
- {
- if (((struct smb2_create_req *)hdr)->CreateContextsLength) {
- *off = le32_to_cpu(((struct smb2_create_req *)
- hdr)->CreateContextsOffset);
- *len = le32_to_cpu(((struct smb2_create_req *)
- hdr)->CreateContextsLength);
- break;
- }
-
- *off = le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset);
- *len = le16_to_cpu(((struct smb2_create_req *)hdr)->NameLength);
- break;
- }
- case SMB2_QUERY_INFO:
- *off = le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset);
- *len = le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLength);
- break;
- case SMB2_SET_INFO:
- *off = le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset);
- *len = le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength);
- break;
- case SMB2_READ:
- *off = le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoOffset);
- *len = le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoLength);
- break;
- case SMB2_WRITE:
- if (((struct smb2_write_req *)hdr)->DataOffset ||
- ((struct smb2_write_req *)hdr)->Length) {
- *off = max_t(unsigned int,
- le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset),
- offsetof(struct smb2_write_req, Buffer));
- *len = le32_to_cpu(((struct smb2_write_req *)hdr)->Length);
- break;
- }
-
- *off = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoOffset);
- *len = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLength);
- break;
- case SMB2_QUERY_DIRECTORY:
- *off = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset);
- *len = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameLength);
- break;
- case SMB2_LOCK:
- {
- unsigned short lock_count;
-
- lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount);
- if (lock_count > 0) {
- *off = offsetof(struct smb2_lock_req, locks);
- *len = sizeof(struct smb2_lock_element) * lock_count;
- }
- break;
- }
- case SMB2_IOCTL:
- *off = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset);
- *len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount);
- break;
- default:
- ksmbd_debug(SMB, "no length check for command\n");
- break;
- }
-
- if (*off > 4096) {
- ksmbd_debug(SMB, "offset %d too large\n", *off);
- ret = -EINVAL;
- } else if ((u64)*off + *len > MAX_STREAM_PROT_LEN) {
- ksmbd_debug(SMB, "Request is larger than maximum stream protocol length(%u): %llu\n",
- MAX_STREAM_PROT_LEN, (u64)*off + *len);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-/*
- * Calculate the size of the SMB message based on the fixed header
- * portion, the number of word parameters and the data portion of the message.
- */
-static int smb2_calc_size(void *buf, unsigned int *len)
-{
- struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
- struct smb2_hdr *hdr = &pdu->hdr;
- unsigned int offset; /* the offset from the beginning of SMB to data area */
- unsigned int data_length; /* the length of the variable length data area */
- int ret;
-
- /* Structure Size has already been checked to make sure it is 64 */
- *len = le16_to_cpu(hdr->StructureSize);
-
- /*
- * StructureSize2, ie length of fixed parameter area has already
- * been checked to make sure it is the correct length.
- */
- *len += le16_to_cpu(pdu->StructureSize2);
- /*
- * StructureSize2 of smb2_lock pdu is set to 48, indicating
- * the size of smb2 lock request with single smb2_lock_element
- * regardless of number of locks. Subtract single
- * smb2_lock_element for correct buffer size check.
- */
- if (hdr->Command == SMB2_LOCK)
- *len -= sizeof(struct smb2_lock_element);
-
- if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false)
- goto calc_size_exit;
-
- ret = smb2_get_data_area_len(&offset, &data_length, hdr);
- if (ret)
- return ret;
- ksmbd_debug(SMB, "SMB2 data length %u offset %u\n", data_length,
- offset);
-
- if (data_length > 0) {
- /*
- * Check to make sure that data area begins after fixed area,
- * Note that last byte of the fixed area is part of data area
- * for some commands, typically those with odd StructureSize,
- * so we must add one to the calculation.
- */
- if (offset + 1 < *len) {
- ksmbd_debug(SMB,
- "data area offset %d overlaps SMB2 header %u\n",
- offset + 1, *len);
- return -EINVAL;
- }
-
- *len = offset + data_length;
- }
-
-calc_size_exit:
- ksmbd_debug(SMB, "SMB2 len %u\n", *len);
- return 0;
-}
-
-static inline int smb2_query_info_req_len(struct smb2_query_info_req *h)
-{
- return le32_to_cpu(h->InputBufferLength) +
- le32_to_cpu(h->OutputBufferLength);
-}
-
-static inline int smb2_set_info_req_len(struct smb2_set_info_req *h)
-{
- return le32_to_cpu(h->BufferLength);
-}
-
-static inline int smb2_read_req_len(struct smb2_read_req *h)
-{
- return le32_to_cpu(h->Length);
-}
-
-static inline int smb2_write_req_len(struct smb2_write_req *h)
-{
- return le32_to_cpu(h->Length);
-}
-
-static inline int smb2_query_dir_req_len(struct smb2_query_directory_req *h)
-{
- return le32_to_cpu(h->OutputBufferLength);
-}
-
-static inline int smb2_ioctl_req_len(struct smb2_ioctl_req *h)
-{
- return le32_to_cpu(h->InputCount) +
- le32_to_cpu(h->OutputCount);
-}
-
-static inline int smb2_ioctl_resp_len(struct smb2_ioctl_req *h)
-{
- return le32_to_cpu(h->MaxInputResponse) +
- le32_to_cpu(h->MaxOutputResponse);
-}
-
-static int smb2_validate_credit_charge(struct ksmbd_conn *conn,
- struct smb2_hdr *hdr)
-{
- unsigned int req_len = 0, expect_resp_len = 0, calc_credit_num, max_len;
- unsigned short credit_charge = le16_to_cpu(hdr->CreditCharge);
- void *__hdr = hdr;
- int ret = 0;
-
- switch (hdr->Command) {
- case SMB2_QUERY_INFO:
- req_len = smb2_query_info_req_len(__hdr);
- break;
- case SMB2_SET_INFO:
- req_len = smb2_set_info_req_len(__hdr);
- break;
- case SMB2_READ:
- req_len = smb2_read_req_len(__hdr);
- break;
- case SMB2_WRITE:
- req_len = smb2_write_req_len(__hdr);
- break;
- case SMB2_QUERY_DIRECTORY:
- req_len = smb2_query_dir_req_len(__hdr);
- break;
- case SMB2_IOCTL:
- req_len = smb2_ioctl_req_len(__hdr);
- expect_resp_len = smb2_ioctl_resp_len(__hdr);
- break;
- case SMB2_CANCEL:
- return 0;
- default:
- req_len = 1;
- break;
- }
-
- credit_charge = max_t(unsigned short, credit_charge, 1);
- max_len = max_t(unsigned int, req_len, expect_resp_len);
- calc_credit_num = DIV_ROUND_UP(max_len, SMB2_MAX_BUFFER_SIZE);
-
- if (credit_charge < calc_credit_num) {
- ksmbd_debug(SMB, "Insufficient credit charge, given: %d, needed: %d\n",
- credit_charge, calc_credit_num);
- return 1;
- } else if (credit_charge > conn->vals->max_credits) {
- ksmbd_debug(SMB, "Too large credit charge: %d\n", credit_charge);
- return 1;
- }
-
- spin_lock(&conn->credits_lock);
- if (credit_charge > conn->total_credits) {
- ksmbd_debug(SMB, "Insufficient credits granted, given: %u, granted: %u\n",
- credit_charge, conn->total_credits);
- ret = 1;
- }
-
- if ((u64)conn->outstanding_credits + credit_charge > conn->total_credits) {
- ksmbd_debug(SMB, "Limits exceeding the maximum allowable outstanding requests, given : %u, pending : %u\n",
- credit_charge, conn->outstanding_credits);
- ret = 1;
- } else
- conn->outstanding_credits += credit_charge;
-
- spin_unlock(&conn->credits_lock);
-
- return ret;
-}
-
-int ksmbd_smb2_check_message(struct ksmbd_work *work)
-{
- struct smb2_pdu *pdu = ksmbd_req_buf_next(work);
- struct smb2_hdr *hdr = &pdu->hdr;
- int command;
- __u32 clc_len; /* calculated length */
- __u32 len = get_rfc1002_len(work->request_buf);
-
- if (le32_to_cpu(hdr->NextCommand) > 0)
- len = le32_to_cpu(hdr->NextCommand);
- else if (work->next_smb2_rcv_hdr_off)
- len -= work->next_smb2_rcv_hdr_off;
-
- if (check_smb2_hdr(hdr))
- return 1;
-
- if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
- ksmbd_debug(SMB, "Illegal structure size %u\n",
- le16_to_cpu(hdr->StructureSize));
- return 1;
- }
-
- command = le16_to_cpu(hdr->Command);
- if (command >= NUMBER_OF_SMB2_COMMANDS) {
- ksmbd_debug(SMB, "Illegal SMB2 command %d\n", command);
- return 1;
- }
-
- if (smb2_req_struct_sizes[command] != pdu->StructureSize2) {
- if (command != SMB2_OPLOCK_BREAK_HE &&
- (hdr->Status == 0 || pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2_LE)) {
- /* error packets have 9 byte structure size */
- ksmbd_debug(SMB,
- "Illegal request size %u for command %d\n",
- le16_to_cpu(pdu->StructureSize2), command);
- return 1;
- } else if (command == SMB2_OPLOCK_BREAK_HE &&
- hdr->Status == 0 &&
- le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 &&
- le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) {
- /* special case for SMB2.1 lease break message */
- ksmbd_debug(SMB,
- "Illegal request size %d for oplock break\n",
- le16_to_cpu(pdu->StructureSize2));
- return 1;
- }
- }
-
- if (smb2_calc_size(hdr, &clc_len))
- return 1;
-
- if (len != clc_len) {
- /* client can return one byte more due to implied bcc[0] */
- if (clc_len == len + 1)
- goto validate_credit;
-
- /*
- * Some windows servers (win2016) will pad also the final
- * PDU in a compound to 8 bytes.
- */
- if (ALIGN(clc_len, 8) == len)
- goto validate_credit;
-
- /*
- * SMB2 NEGOTIATE request will be validated when message
- * handling proceeds.
- */
- if (command == SMB2_NEGOTIATE_HE)
- goto validate_credit;
-
- /*
- * Allow a message that padded to 8byte boundary.
- * Linux 4.19.217 with smb 3.0.2 are sometimes
- * sending messages where the cls_len is exactly
- * 8 bytes less than len.
- */
- if (clc_len < len && (len - clc_len) <= 8)
- goto validate_credit;
-
- pr_err_ratelimited(
- "cli req too short, len %d not %d. cmd:%d mid:%llu\n",
- len, clc_len, command,
- le64_to_cpu(hdr->MessageId));
-
- return 1;
- }
-
-validate_credit:
- if ((work->conn->vals->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU) &&
- smb2_validate_credit_charge(work->conn, hdr)) {
- work->conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
- return 1;
- }
-
- return 0;
-}
-
-int smb2_negotiate_request(struct ksmbd_work *work)
-{
- return ksmbd_smb_negotiate_common(work, SMB2_NEGOTIATE_HE);
-}
diff --git a/fs/ksmbd/smb2ops.c b/fs/ksmbd/smb2ops.c
deleted file mode 100644
index ab23da2120b9..000000000000
--- a/fs/ksmbd/smb2ops.c
+++ /dev/null
@@ -1,314 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/slab.h>
-#include "glob.h"
-
-#include "auth.h"
-#include "connection.h"
-#include "smb_common.h"
-#include "server.h"
-
-static struct smb_version_values smb21_server_values = {
- .version_string = SMB21_VERSION_STRING,
- .protocol_id = SMB21_PROT_ID,
- .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
- .max_read_size = SMB21_DEFAULT_IOSIZE,
- .max_write_size = SMB21_DEFAULT_IOSIZE,
- .max_trans_size = SMB21_DEFAULT_IOSIZE,
- .max_credits = SMB2_MAX_CREDITS,
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .create_lease_size = sizeof(struct create_lease),
- .create_durable_size = sizeof(struct create_durable_rsp),
- .create_mxac_size = sizeof(struct create_mxac_rsp),
- .create_disk_id_size = sizeof(struct create_disk_id_rsp),
- .create_posix_size = sizeof(struct create_posix_rsp),
-};
-
-static struct smb_version_values smb30_server_values = {
- .version_string = SMB30_VERSION_STRING,
- .protocol_id = SMB30_PROT_ID,
- .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
- .max_read_size = SMB3_DEFAULT_IOSIZE,
- .max_write_size = SMB3_DEFAULT_IOSIZE,
- .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
- .max_credits = SMB2_MAX_CREDITS,
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .create_lease_size = sizeof(struct create_lease_v2),
- .create_durable_size = sizeof(struct create_durable_rsp),
- .create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
- .create_mxac_size = sizeof(struct create_mxac_rsp),
- .create_disk_id_size = sizeof(struct create_disk_id_rsp),
- .create_posix_size = sizeof(struct create_posix_rsp),
-};
-
-static struct smb_version_values smb302_server_values = {
- .version_string = SMB302_VERSION_STRING,
- .protocol_id = SMB302_PROT_ID,
- .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
- .max_read_size = SMB3_DEFAULT_IOSIZE,
- .max_write_size = SMB3_DEFAULT_IOSIZE,
- .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
- .max_credits = SMB2_MAX_CREDITS,
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .create_lease_size = sizeof(struct create_lease_v2),
- .create_durable_size = sizeof(struct create_durable_rsp),
- .create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
- .create_mxac_size = sizeof(struct create_mxac_rsp),
- .create_disk_id_size = sizeof(struct create_disk_id_rsp),
- .create_posix_size = sizeof(struct create_posix_rsp),
-};
-
-static struct smb_version_values smb311_server_values = {
- .version_string = SMB311_VERSION_STRING,
- .protocol_id = SMB311_PROT_ID,
- .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
- .max_read_size = SMB3_DEFAULT_IOSIZE,
- .max_write_size = SMB3_DEFAULT_IOSIZE,
- .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
- .max_credits = SMB2_MAX_CREDITS,
- .large_lock_type = 0,
- .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
- .shared_lock_type = SMB2_LOCKFLAG_SHARED,
- .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
- .header_size = sizeof(struct smb2_hdr),
- .max_header_size = MAX_SMB2_HDR_SIZE,
- .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
- .lock_cmd = SMB2_LOCK,
- .cap_unix = 0,
- .cap_nt_find = SMB2_NT_FIND,
- .cap_large_files = SMB2_LARGE_FILES,
- .create_lease_size = sizeof(struct create_lease_v2),
- .create_durable_size = sizeof(struct create_durable_rsp),
- .create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
- .create_mxac_size = sizeof(struct create_mxac_rsp),
- .create_disk_id_size = sizeof(struct create_disk_id_rsp),
- .create_posix_size = sizeof(struct create_posix_rsp),
-};
-
-static struct smb_version_ops smb2_0_server_ops = {
- .get_cmd_val = get_smb2_cmd_val,
- .init_rsp_hdr = init_smb2_rsp_hdr,
- .set_rsp_status = set_smb2_rsp_status,
- .allocate_rsp_buf = smb2_allocate_rsp_buf,
- .set_rsp_credits = smb2_set_rsp_credits,
- .check_user_session = smb2_check_user_session,
- .get_ksmbd_tcon = smb2_get_ksmbd_tcon,
- .is_sign_req = smb2_is_sign_req,
- .check_sign_req = smb2_check_sign_req,
- .set_sign_rsp = smb2_set_sign_rsp
-};
-
-static struct smb_version_ops smb3_0_server_ops = {
- .get_cmd_val = get_smb2_cmd_val,
- .init_rsp_hdr = init_smb2_rsp_hdr,
- .set_rsp_status = set_smb2_rsp_status,
- .allocate_rsp_buf = smb2_allocate_rsp_buf,
- .set_rsp_credits = smb2_set_rsp_credits,
- .check_user_session = smb2_check_user_session,
- .get_ksmbd_tcon = smb2_get_ksmbd_tcon,
- .is_sign_req = smb2_is_sign_req,
- .check_sign_req = smb3_check_sign_req,
- .set_sign_rsp = smb3_set_sign_rsp,
- .generate_signingkey = ksmbd_gen_smb30_signingkey,
- .generate_encryptionkey = ksmbd_gen_smb30_encryptionkey,
- .is_transform_hdr = smb3_is_transform_hdr,
- .decrypt_req = smb3_decrypt_req,
- .encrypt_resp = smb3_encrypt_resp
-};
-
-static struct smb_version_ops smb3_11_server_ops = {
- .get_cmd_val = get_smb2_cmd_val,
- .init_rsp_hdr = init_smb2_rsp_hdr,
- .set_rsp_status = set_smb2_rsp_status,
- .allocate_rsp_buf = smb2_allocate_rsp_buf,
- .set_rsp_credits = smb2_set_rsp_credits,
- .check_user_session = smb2_check_user_session,
- .get_ksmbd_tcon = smb2_get_ksmbd_tcon,
- .is_sign_req = smb2_is_sign_req,
- .check_sign_req = smb3_check_sign_req,
- .set_sign_rsp = smb3_set_sign_rsp,
- .generate_signingkey = ksmbd_gen_smb311_signingkey,
- .generate_encryptionkey = ksmbd_gen_smb311_encryptionkey,
- .is_transform_hdr = smb3_is_transform_hdr,
- .decrypt_req = smb3_decrypt_req,
- .encrypt_resp = smb3_encrypt_resp
-};
-
-static struct smb_version_cmds smb2_0_server_cmds[NUMBER_OF_SMB2_COMMANDS] = {
- [SMB2_NEGOTIATE_HE] = { .proc = smb2_negotiate_request, },
- [SMB2_SESSION_SETUP_HE] = { .proc = smb2_sess_setup, },
- [SMB2_TREE_CONNECT_HE] = { .proc = smb2_tree_connect,},
- [SMB2_TREE_DISCONNECT_HE] = { .proc = smb2_tree_disconnect,},
- [SMB2_LOGOFF_HE] = { .proc = smb2_session_logoff,},
- [SMB2_CREATE_HE] = { .proc = smb2_open},
- [SMB2_QUERY_INFO_HE] = { .proc = smb2_query_info},
- [SMB2_QUERY_DIRECTORY_HE] = { .proc = smb2_query_dir},
- [SMB2_CLOSE_HE] = { .proc = smb2_close},
- [SMB2_ECHO_HE] = { .proc = smb2_echo},
- [SMB2_SET_INFO_HE] = { .proc = smb2_set_info},
- [SMB2_READ_HE] = { .proc = smb2_read},
- [SMB2_WRITE_HE] = { .proc = smb2_write},
- [SMB2_FLUSH_HE] = { .proc = smb2_flush},
- [SMB2_CANCEL_HE] = { .proc = smb2_cancel},
- [SMB2_LOCK_HE] = { .proc = smb2_lock},
- [SMB2_IOCTL_HE] = { .proc = smb2_ioctl},
- [SMB2_OPLOCK_BREAK_HE] = { .proc = smb2_oplock_break},
- [SMB2_CHANGE_NOTIFY_HE] = { .proc = smb2_notify},
-};
-
-/**
- * init_smb2_1_server() - initialize a smb server connection with smb2.1
- * command dispatcher
- * @conn: connection instance
- */
-void init_smb2_1_server(struct ksmbd_conn *conn)
-{
- conn->vals = &smb21_server_values;
- conn->ops = &smb2_0_server_ops;
- conn->cmds = smb2_0_server_cmds;
- conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
- conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256_LE;
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
- conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
-}
-
-/**
- * init_smb3_0_server() - initialize a smb server connection with smb3.0
- * command dispatcher
- * @conn: connection instance
- */
-void init_smb3_0_server(struct ksmbd_conn *conn)
-{
- conn->vals = &smb30_server_values;
- conn->ops = &smb3_0_server_ops;
- conn->cmds = smb2_0_server_cmds;
- conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
- conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
- conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
- conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
- conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
- conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
-}
-
-/**
- * init_smb3_02_server() - initialize a smb server connection with smb3.02
- * command dispatcher
- * @conn: connection instance
- */
-void init_smb3_02_server(struct ksmbd_conn *conn)
-{
- conn->vals = &smb302_server_values;
- conn->ops = &smb3_0_server_ops;
- conn->cmds = smb2_0_server_cmds;
- conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
- conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
- conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
- conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
- conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
- conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
-}
-
-/**
- * init_smb3_11_server() - initialize a smb server connection with smb3.11
- * command dispatcher
- * @conn: connection instance
- */
-int init_smb3_11_server(struct ksmbd_conn *conn)
-{
- conn->vals = &smb311_server_values;
- conn->ops = &smb3_11_server_ops;
- conn->cmds = smb2_0_server_cmds;
- conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
- conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
- conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
- conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
-
- INIT_LIST_HEAD(&conn->preauth_sess_table);
- return 0;
-}
-
-void init_smb2_max_read_size(unsigned int sz)
-{
- sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE);
- smb21_server_values.max_read_size = sz;
- smb30_server_values.max_read_size = sz;
- smb302_server_values.max_read_size = sz;
- smb311_server_values.max_read_size = sz;
-}
-
-void init_smb2_max_write_size(unsigned int sz)
-{
- sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE);
- smb21_server_values.max_write_size = sz;
- smb30_server_values.max_write_size = sz;
- smb302_server_values.max_write_size = sz;
- smb311_server_values.max_write_size = sz;
-}
-
-void init_smb2_max_trans_size(unsigned int sz)
-{
- sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE);
- smb21_server_values.max_trans_size = sz;
- smb30_server_values.max_trans_size = sz;
- smb302_server_values.max_trans_size = sz;
- smb311_server_values.max_trans_size = sz;
-}
-
-void init_smb2_max_credits(unsigned int sz)
-{
- smb21_server_values.max_credits = sz;
- smb30_server_values.max_credits = sz;
- smb302_server_values.max_credits = sz;
- smb311_server_values.max_credits = sz;
-}
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
deleted file mode 100644
index 56f661e5ef62..000000000000
--- a/fs/ksmbd/smb2pdu.c
+++ /dev/null
@@ -1,8693 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/inetdevice.h>
-#include <net/addrconf.h>
-#include <linux/syscalls.h>
-#include <linux/namei.h>
-#include <linux/statfs.h>
-#include <linux/ethtool.h>
-#include <linux/falloc.h>
-#include <linux/mount.h>
-
-#include "glob.h"
-#include "smbfsctl.h"
-#include "oplock.h"
-#include "smbacl.h"
-
-#include "auth.h"
-#include "asn1.h"
-#include "connection.h"
-#include "transport_ipc.h"
-#include "transport_rdma.h"
-#include "vfs.h"
-#include "vfs_cache.h"
-#include "misc.h"
-
-#include "server.h"
-#include "smb_common.h"
-#include "smbstatus.h"
-#include "ksmbd_work.h"
-#include "mgmt/user_config.h"
-#include "mgmt/share_config.h"
-#include "mgmt/tree_connect.h"
-#include "mgmt/user_session.h"
-#include "mgmt/ksmbd_ida.h"
-#include "ndr.h"
-
-static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
-{
- if (work->next_smb2_rcv_hdr_off) {
- *req = ksmbd_req_buf_next(work);
- *rsp = ksmbd_resp_buf_next(work);
- } else {
- *req = smb2_get_msg(work->request_buf);
- *rsp = smb2_get_msg(work->response_buf);
- }
-}
-
-#define WORK_BUFFERS(w, rq, rs) __wbuf((w), (void **)&(rq), (void **)&(rs))
-
-/**
- * check_session_id() - check for valid session id in smb header
- * @conn: connection instance
- * @id: session id from smb header
- *
- * Return: 1 if valid session id, otherwise 0
- */
-static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
-{
- struct ksmbd_session *sess;
-
- if (id == 0 || id == -1)
- return false;
-
- sess = ksmbd_session_lookup_all(conn, id);
- if (sess)
- return true;
- pr_err("Invalid user session id: %llu\n", id);
- return false;
-}
-
-struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn)
-{
- return xa_load(&sess->ksmbd_chann_list, (long)conn);
-}
-
-/**
- * smb2_get_ksmbd_tcon() - get tree connection information using a tree id.
- * @work: smb work
- *
- * Return: 0 if there is a tree connection matched or these are
- * skipable commands, otherwise error
- */
-int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
-{
- struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
- unsigned int cmd = le16_to_cpu(req_hdr->Command);
- int tree_id;
-
- work->tcon = NULL;
- if (cmd == SMB2_TREE_CONNECT_HE ||
- cmd == SMB2_CANCEL_HE ||
- cmd == SMB2_LOGOFF_HE) {
- ksmbd_debug(SMB, "skip to check tree connect request\n");
- return 0;
- }
-
- if (xa_empty(&work->sess->tree_conns)) {
- ksmbd_debug(SMB, "NO tree connected\n");
- return -ENOENT;
- }
-
- tree_id = le32_to_cpu(req_hdr->Id.SyncId.TreeId);
- work->tcon = ksmbd_tree_conn_lookup(work->sess, tree_id);
- if (!work->tcon) {
- pr_err("Invalid tid %d\n", tree_id);
- return -EINVAL;
- }
-
- return 1;
-}
-
-/**
- * smb2_set_err_rsp() - set error response code on smb response
- * @work: smb work containing response buffer
- */
-void smb2_set_err_rsp(struct ksmbd_work *work)
-{
- struct smb2_err_rsp *err_rsp;
-
- if (work->next_smb2_rcv_hdr_off)
- err_rsp = ksmbd_resp_buf_next(work);
- else
- err_rsp = smb2_get_msg(work->response_buf);
-
- if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) {
- err_rsp->StructureSize = SMB2_ERROR_STRUCTURE_SIZE2_LE;
- err_rsp->ErrorContextCount = 0;
- err_rsp->Reserved = 0;
- err_rsp->ByteCount = 0;
- err_rsp->ErrorData[0] = 0;
- inc_rfc1001_len(work->response_buf, SMB2_ERROR_STRUCTURE_SIZE2);
- }
-}
-
-/**
- * is_smb2_neg_cmd() - is it smb2 negotiation command
- * @work: smb work containing smb header
- *
- * Return: true if smb2 negotiation command, otherwise false
- */
-bool is_smb2_neg_cmd(struct ksmbd_work *work)
-{
- struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
-
- /* is it SMB2 header ? */
- if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
- return false;
-
- /* make sure it is request not response message */
- if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
- return false;
-
- if (hdr->Command != SMB2_NEGOTIATE)
- return false;
-
- return true;
-}
-
-/**
- * is_smb2_rsp() - is it smb2 response
- * @work: smb work containing smb response buffer
- *
- * Return: true if smb2 response, otherwise false
- */
-bool is_smb2_rsp(struct ksmbd_work *work)
-{
- struct smb2_hdr *hdr = smb2_get_msg(work->response_buf);
-
- /* is it SMB2 header ? */
- if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
- return false;
-
- /* make sure it is response not request message */
- if (!(hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR))
- return false;
-
- return true;
-}
-
-/**
- * get_smb2_cmd_val() - get smb command code from smb header
- * @work: smb work containing smb request buffer
- *
- * Return: smb2 request command value
- */
-u16 get_smb2_cmd_val(struct ksmbd_work *work)
-{
- struct smb2_hdr *rcv_hdr;
-
- if (work->next_smb2_rcv_hdr_off)
- rcv_hdr = ksmbd_req_buf_next(work);
- else
- rcv_hdr = smb2_get_msg(work->request_buf);
- return le16_to_cpu(rcv_hdr->Command);
-}
-
-/**
- * set_smb2_rsp_status() - set error response code on smb2 header
- * @work: smb work containing response buffer
- * @err: error response code
- */
-void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
-{
- struct smb2_hdr *rsp_hdr;
-
- if (work->next_smb2_rcv_hdr_off)
- rsp_hdr = ksmbd_resp_buf_next(work);
- else
- rsp_hdr = smb2_get_msg(work->response_buf);
- rsp_hdr->Status = err;
- smb2_set_err_rsp(work);
-}
-
-/**
- * init_smb2_neg_rsp() - initialize smb2 response for negotiate command
- * @work: smb work containing smb request buffer
- *
- * smb2 negotiate response is sent in reply of smb1 negotiate command for
- * dialect auto-negotiation.
- */
-int init_smb2_neg_rsp(struct ksmbd_work *work)
-{
- struct smb2_hdr *rsp_hdr;
- struct smb2_negotiate_rsp *rsp;
- struct ksmbd_conn *conn = work->conn;
-
- *(__be32 *)work->response_buf =
- cpu_to_be32(conn->vals->header_size);
-
- rsp_hdr = smb2_get_msg(work->response_buf);
- memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
- rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
- rsp_hdr->CreditRequest = cpu_to_le16(2);
- rsp_hdr->Command = SMB2_NEGOTIATE;
- rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
- rsp_hdr->NextCommand = 0;
- rsp_hdr->MessageId = 0;
- rsp_hdr->Id.SyncId.ProcessId = 0;
- rsp_hdr->Id.SyncId.TreeId = 0;
- rsp_hdr->SessionId = 0;
- memset(rsp_hdr->Signature, 0, 16);
-
- rsp = smb2_get_msg(work->response_buf);
-
- WARN_ON(ksmbd_conn_good(conn));
-
- rsp->StructureSize = cpu_to_le16(65);
- ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
- rsp->DialectRevision = cpu_to_le16(conn->dialect);
- /* Not setting conn guid rsp->ServerGUID, as it
- * not used by client for identifying connection
- */
- rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
- /* Default Max Message Size till SMB2.0, 64K*/
- rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size);
- rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size);
- rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size);
-
- rsp->SystemTime = cpu_to_le64(ksmbd_systime());
- rsp->ServerStartTime = 0;
-
- rsp->SecurityBufferOffset = cpu_to_le16(128);
- rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
- ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
- le16_to_cpu(rsp->SecurityBufferOffset));
- inc_rfc1001_len(work->response_buf,
- sizeof(struct smb2_negotiate_rsp) -
- sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
- AUTH_GSS_LENGTH);
- rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
- if (server_conf.signing == KSMBD_CONFIG_OPT_MANDATORY)
- rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
- conn->use_spnego = true;
-
- ksmbd_conn_set_need_negotiate(conn);
- return 0;
-}
-
-/**
- * smb2_set_rsp_credits() - set number of credits in response buffer
- * @work: smb work containing smb response buffer
- */
-int smb2_set_rsp_credits(struct ksmbd_work *work)
-{
- struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
- struct smb2_hdr *hdr = ksmbd_resp_buf_next(work);
- struct ksmbd_conn *conn = work->conn;
- unsigned short credits_requested, aux_max;
- unsigned short credit_charge, credits_granted = 0;
-
- if (work->send_no_response)
- return 0;
-
- hdr->CreditCharge = req_hdr->CreditCharge;
-
- if (conn->total_credits > conn->vals->max_credits) {
- hdr->CreditRequest = 0;
- pr_err("Total credits overflow: %d\n", conn->total_credits);
- return -EINVAL;
- }
-
- credit_charge = max_t(unsigned short,
- le16_to_cpu(req_hdr->CreditCharge), 1);
- if (credit_charge > conn->total_credits) {
- ksmbd_debug(SMB, "Insufficient credits granted, given: %u, granted: %u\n",
- credit_charge, conn->total_credits);
- return -EINVAL;
- }
-
- conn->total_credits -= credit_charge;
- conn->outstanding_credits -= credit_charge;
- credits_requested = max_t(unsigned short,
- le16_to_cpu(req_hdr->CreditRequest), 1);
-
- /* according to smb2.credits smbtorture, Windows server
- * 2016 or later grant up to 8192 credits at once.
- *
- * TODO: Need to adjuct CreditRequest value according to
- * current cpu load
- */
- if (hdr->Command == SMB2_NEGOTIATE)
- aux_max = 1;
- else
- aux_max = conn->vals->max_credits - conn->total_credits;
- credits_granted = min_t(unsigned short, credits_requested, aux_max);
-
- conn->total_credits += credits_granted;
- work->credits_granted += credits_granted;
-
- if (!req_hdr->NextCommand) {
- /* Update CreditRequest in last request */
- hdr->CreditRequest = cpu_to_le16(work->credits_granted);
- }
- ksmbd_debug(SMB,
- "credits: requested[%d] granted[%d] total_granted[%d]\n",
- credits_requested, credits_granted,
- conn->total_credits);
- return 0;
-}
-
-/**
- * init_chained_smb2_rsp() - initialize smb2 chained response
- * @work: smb work containing smb response buffer
- */
-static void init_chained_smb2_rsp(struct ksmbd_work *work)
-{
- struct smb2_hdr *req = ksmbd_req_buf_next(work);
- struct smb2_hdr *rsp = ksmbd_resp_buf_next(work);
- struct smb2_hdr *rsp_hdr;
- struct smb2_hdr *rcv_hdr;
- int next_hdr_offset = 0;
- int len, new_len;
-
- /* Len of this response = updated RFC len - offset of previous cmd
- * in the compound rsp
- */
-
- /* Storing the current local FID which may be needed by subsequent
- * command in the compound request
- */
- if (req->Command == SMB2_CREATE && rsp->Status == STATUS_SUCCESS) {
- work->compound_fid = ((struct smb2_create_rsp *)rsp)->VolatileFileId;
- work->compound_pfid = ((struct smb2_create_rsp *)rsp)->PersistentFileId;
- work->compound_sid = le64_to_cpu(rsp->SessionId);
- }
-
- len = get_rfc1002_len(work->response_buf) - work->next_smb2_rsp_hdr_off;
- next_hdr_offset = le32_to_cpu(req->NextCommand);
-
- new_len = ALIGN(len, 8);
- inc_rfc1001_len(work->response_buf,
- sizeof(struct smb2_hdr) + new_len - len);
- rsp->NextCommand = cpu_to_le32(new_len);
-
- work->next_smb2_rcv_hdr_off += next_hdr_offset;
- work->next_smb2_rsp_hdr_off += new_len;
- ksmbd_debug(SMB,
- "Compound req new_len = %d rcv off = %d rsp off = %d\n",
- new_len, work->next_smb2_rcv_hdr_off,
- work->next_smb2_rsp_hdr_off);
-
- rsp_hdr = ksmbd_resp_buf_next(work);
- rcv_hdr = ksmbd_req_buf_next(work);
-
- if (!(rcv_hdr->Flags & SMB2_FLAGS_RELATED_OPERATIONS)) {
- ksmbd_debug(SMB, "related flag should be set\n");
- work->compound_fid = KSMBD_NO_FID;
- work->compound_pfid = KSMBD_NO_FID;
- }
- memset((char *)rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
- rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
- rsp_hdr->Command = rcv_hdr->Command;
-
- /*
- * Message is response. We don't grant oplock yet.
- */
- rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR |
- SMB2_FLAGS_RELATED_OPERATIONS);
- rsp_hdr->NextCommand = 0;
- rsp_hdr->MessageId = rcv_hdr->MessageId;
- rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId;
- rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId;
- rsp_hdr->SessionId = rcv_hdr->SessionId;
- memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
-}
-
-/**
- * is_chained_smb2_message() - check for chained command
- * @work: smb work containing smb request buffer
- *
- * Return: true if chained request, otherwise false
- */
-bool is_chained_smb2_message(struct ksmbd_work *work)
-{
- struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
- unsigned int len, next_cmd;
-
- if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
- return false;
-
- hdr = ksmbd_req_buf_next(work);
- next_cmd = le32_to_cpu(hdr->NextCommand);
- if (next_cmd > 0) {
- if ((u64)work->next_smb2_rcv_hdr_off + next_cmd +
- __SMB2_HEADER_STRUCTURE_SIZE >
- get_rfc1002_len(work->request_buf)) {
- pr_err("next command(%u) offset exceeds smb msg size\n",
- next_cmd);
- return false;
- }
-
- if ((u64)get_rfc1002_len(work->response_buf) + MAX_CIFS_SMALL_BUFFER_SIZE >
- work->response_sz) {
- pr_err("next response offset exceeds response buffer size\n");
- return false;
- }
-
- ksmbd_debug(SMB, "got SMB2 chained command\n");
- init_chained_smb2_rsp(work);
- return true;
- } else if (work->next_smb2_rcv_hdr_off) {
- /*
- * This is last request in chained command,
- * align response to 8 byte
- */
- len = ALIGN(get_rfc1002_len(work->response_buf), 8);
- len = len - get_rfc1002_len(work->response_buf);
- if (len) {
- ksmbd_debug(SMB, "padding len %u\n", len);
- inc_rfc1001_len(work->response_buf, len);
- if (work->aux_payload_sz)
- work->aux_payload_sz += len;
- }
- }
- return false;
-}
-
-/**
- * init_smb2_rsp_hdr() - initialize smb2 response
- * @work: smb work containing smb request buffer
- *
- * Return: 0
- */
-int init_smb2_rsp_hdr(struct ksmbd_work *work)
-{
- struct smb2_hdr *rsp_hdr = smb2_get_msg(work->response_buf);
- struct smb2_hdr *rcv_hdr = smb2_get_msg(work->request_buf);
- struct ksmbd_conn *conn = work->conn;
-
- memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
- *(__be32 *)work->response_buf =
- cpu_to_be32(conn->vals->header_size);
- rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
- rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
- rsp_hdr->Command = rcv_hdr->Command;
-
- /*
- * Message is response. We don't grant oplock yet.
- */
- rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
- rsp_hdr->NextCommand = 0;
- rsp_hdr->MessageId = rcv_hdr->MessageId;
- rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId;
- rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId;
- rsp_hdr->SessionId = rcv_hdr->SessionId;
- memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
-
- work->syncronous = true;
- if (work->async_id) {
- ksmbd_release_id(&conn->async_ida, work->async_id);
- work->async_id = 0;
- }
-
- return 0;
-}
-
-/**
- * smb2_allocate_rsp_buf() - allocate smb2 response buffer
- * @work: smb work containing smb request buffer
- *
- * Return: 0 on success, otherwise -ENOMEM
- */
-int smb2_allocate_rsp_buf(struct ksmbd_work *work)
-{
- struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
- size_t small_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
- size_t large_sz = small_sz + work->conn->vals->max_trans_size;
- size_t sz = small_sz;
- int cmd = le16_to_cpu(hdr->Command);
-
- if (cmd == SMB2_IOCTL_HE || cmd == SMB2_QUERY_DIRECTORY_HE)
- sz = large_sz;
-
- if (cmd == SMB2_QUERY_INFO_HE) {
- struct smb2_query_info_req *req;
-
- req = smb2_get_msg(work->request_buf);
- if ((req->InfoType == SMB2_O_INFO_FILE &&
- (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
- req->FileInfoClass == FILE_ALL_INFORMATION)) ||
- req->InfoType == SMB2_O_INFO_SECURITY)
- sz = large_sz;
- }
-
- /* allocate large response buf for chained commands */
- if (le32_to_cpu(hdr->NextCommand) > 0)
- sz = large_sz;
-
- work->response_buf = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
- if (!work->response_buf)
- return -ENOMEM;
-
- work->response_sz = sz;
- return 0;
-}
-
-/**
- * smb2_check_user_session() - check for valid session for a user
- * @work: smb work containing smb request buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_check_user_session(struct ksmbd_work *work)
-{
- struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
- struct ksmbd_conn *conn = work->conn;
- unsigned int cmd = conn->ops->get_cmd_val(work);
- unsigned long long sess_id;
-
- work->sess = NULL;
- /*
- * SMB2_ECHO, SMB2_NEGOTIATE, SMB2_SESSION_SETUP command do not
- * require a session id, so no need to validate user session's for
- * these commands.
- */
- if (cmd == SMB2_ECHO_HE || cmd == SMB2_NEGOTIATE_HE ||
- cmd == SMB2_SESSION_SETUP_HE)
- return 0;
-
- if (!ksmbd_conn_good(conn))
- return -EINVAL;
-
- sess_id = le64_to_cpu(req_hdr->SessionId);
- /* Check for validity of user session */
- work->sess = ksmbd_session_lookup_all(conn, sess_id);
- if (work->sess)
- return 1;
- ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
- return -EINVAL;
-}
-
-static void destroy_previous_session(struct ksmbd_conn *conn,
- struct ksmbd_user *user, u64 id)
-{
- struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id);
- struct ksmbd_user *prev_user;
- struct channel *chann;
- long index;
-
- if (!prev_sess)
- return;
-
- prev_user = prev_sess->user;
-
- if (!prev_user ||
- strcmp(user->name, prev_user->name) ||
- user->passkey_sz != prev_user->passkey_sz ||
- memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
- return;
-
- prev_sess->state = SMB2_SESSION_EXPIRED;
- xa_for_each(&prev_sess->ksmbd_chann_list, index, chann)
- ksmbd_conn_set_exiting(chann->conn);
-}
-
-/**
- * smb2_get_name() - get filename string from on the wire smb format
- * @src: source buffer
- * @maxlen: maxlen of source string
- * @local_nls: nls_table pointer
- *
- * Return: matching converted filename on success, otherwise error ptr
- */
-static char *
-smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls)
-{
- char *name;
-
- name = smb_strndup_from_utf16(src, maxlen, 1, local_nls);
- if (IS_ERR(name)) {
- pr_err("failed to get name %ld\n", PTR_ERR(name));
- return name;
- }
-
- ksmbd_conv_path_to_unix(name);
- ksmbd_strip_last_slash(name);
- return name;
-}
-
-int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
-{
- struct smb2_hdr *rsp_hdr;
- struct ksmbd_conn *conn = work->conn;
- int id;
-
- rsp_hdr = smb2_get_msg(work->response_buf);
- rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
-
- id = ksmbd_acquire_async_msg_id(&conn->async_ida);
- if (id < 0) {
- pr_err("Failed to alloc async message id\n");
- return id;
- }
- work->syncronous = false;
- work->async_id = id;
- rsp_hdr->Id.AsyncId = cpu_to_le64(id);
-
- ksmbd_debug(SMB,
- "Send interim Response to inform async request id : %d\n",
- work->async_id);
-
- work->cancel_fn = fn;
- work->cancel_argv = arg;
-
- if (list_empty(&work->async_request_entry)) {
- spin_lock(&conn->request_lock);
- list_add_tail(&work->async_request_entry, &conn->async_requests);
- spin_unlock(&conn->request_lock);
- }
-
- return 0;
-}
-
-void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
-{
- struct smb2_hdr *rsp_hdr;
-
- rsp_hdr = smb2_get_msg(work->response_buf);
- smb2_set_err_rsp(work);
- rsp_hdr->Status = status;
-
- work->multiRsp = 1;
- ksmbd_conn_write(work);
- rsp_hdr->Status = 0;
- work->multiRsp = 0;
-}
-
-static __le32 smb2_get_reparse_tag_special_file(umode_t mode)
-{
- if (S_ISDIR(mode) || S_ISREG(mode))
- return 0;
-
- if (S_ISLNK(mode))
- return IO_REPARSE_TAG_LX_SYMLINK_LE;
- else if (S_ISFIFO(mode))
- return IO_REPARSE_TAG_LX_FIFO_LE;
- else if (S_ISSOCK(mode))
- return IO_REPARSE_TAG_AF_UNIX_LE;
- else if (S_ISCHR(mode))
- return IO_REPARSE_TAG_LX_CHR_LE;
- else if (S_ISBLK(mode))
- return IO_REPARSE_TAG_LX_BLK_LE;
-
- return 0;
-}
-
-/**
- * smb2_get_dos_mode() - get file mode in dos format from unix mode
- * @stat: kstat containing file mode
- * @attribute: attribute flags
- *
- * Return: converted dos mode
- */
-static int smb2_get_dos_mode(struct kstat *stat, int attribute)
-{
- int attr = 0;
-
- if (S_ISDIR(stat->mode)) {
- attr = FILE_ATTRIBUTE_DIRECTORY |
- (attribute & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM));
- } else {
- attr = (attribute & 0x00005137) | FILE_ATTRIBUTE_ARCHIVE;
- attr &= ~(FILE_ATTRIBUTE_DIRECTORY);
- if (S_ISREG(stat->mode) && (server_conf.share_fake_fscaps &
- FILE_SUPPORTS_SPARSE_FILES))
- attr |= FILE_ATTRIBUTE_SPARSE_FILE;
-
- if (smb2_get_reparse_tag_special_file(stat->mode))
- attr |= FILE_ATTRIBUTE_REPARSE_POINT;
- }
-
- return attr;
-}
-
-static void build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt,
- __le16 hash_id)
-{
- pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES;
- pneg_ctxt->DataLength = cpu_to_le16(38);
- pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1);
- pneg_ctxt->Reserved = cpu_to_le32(0);
- pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE);
- get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE);
- pneg_ctxt->HashAlgorithms = hash_id;
-}
-
-static void build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt,
- __le16 cipher_type)
-{
- pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
- pneg_ctxt->DataLength = cpu_to_le16(4);
- pneg_ctxt->Reserved = cpu_to_le32(0);
- pneg_ctxt->CipherCount = cpu_to_le16(1);
- pneg_ctxt->Ciphers[0] = cipher_type;
-}
-
-static void build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt,
- __le16 comp_algo)
-{
- pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES;
- pneg_ctxt->DataLength =
- cpu_to_le16(sizeof(struct smb2_compression_capabilities_context)
- - sizeof(struct smb2_neg_context));
- pneg_ctxt->Reserved = cpu_to_le32(0);
- pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(1);
- pneg_ctxt->Flags = cpu_to_le32(0);
- pneg_ctxt->CompressionAlgorithms[0] = comp_algo;
-}
-
-static void build_sign_cap_ctxt(struct smb2_signing_capabilities *pneg_ctxt,
- __le16 sign_algo)
-{
- pneg_ctxt->ContextType = SMB2_SIGNING_CAPABILITIES;
- pneg_ctxt->DataLength =
- cpu_to_le16((sizeof(struct smb2_signing_capabilities) + 2)
- - sizeof(struct smb2_neg_context));
- pneg_ctxt->Reserved = cpu_to_le32(0);
- pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(1);
- pneg_ctxt->SigningAlgorithms[0] = sign_algo;
-}
-
-static void build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
-{
- pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE;
- pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
- /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
- pneg_ctxt->Name[0] = 0x93;
- pneg_ctxt->Name[1] = 0xAD;
- pneg_ctxt->Name[2] = 0x25;
- pneg_ctxt->Name[3] = 0x50;
- pneg_ctxt->Name[4] = 0x9C;
- pneg_ctxt->Name[5] = 0xB4;
- pneg_ctxt->Name[6] = 0x11;
- pneg_ctxt->Name[7] = 0xE7;
- pneg_ctxt->Name[8] = 0xB4;
- pneg_ctxt->Name[9] = 0x23;
- pneg_ctxt->Name[10] = 0x83;
- pneg_ctxt->Name[11] = 0xDE;
- pneg_ctxt->Name[12] = 0x96;
- pneg_ctxt->Name[13] = 0x8B;
- pneg_ctxt->Name[14] = 0xCD;
- pneg_ctxt->Name[15] = 0x7C;
-}
-
-static void assemble_neg_contexts(struct ksmbd_conn *conn,
- struct smb2_negotiate_rsp *rsp,
- void *smb2_buf_len)
-{
- char *pneg_ctxt = (char *)rsp +
- le32_to_cpu(rsp->NegotiateContextOffset);
- int neg_ctxt_cnt = 1;
- int ctxt_size;
-
- ksmbd_debug(SMB,
- "assemble SMB2_PREAUTH_INTEGRITY_CAPABILITIES context\n");
- build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt,
- conn->preauth_info->Preauth_HashId);
- rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt);
- inc_rfc1001_len(smb2_buf_len, AUTH_GSS_PADDING);
- ctxt_size = sizeof(struct smb2_preauth_neg_context);
- /* Round to 8 byte boundary */
- pneg_ctxt += round_up(sizeof(struct smb2_preauth_neg_context), 8);
-
- if (conn->cipher_type) {
- ctxt_size = round_up(ctxt_size, 8);
- ksmbd_debug(SMB,
- "assemble SMB2_ENCRYPTION_CAPABILITIES context\n");
- build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt,
- conn->cipher_type);
- rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
- ctxt_size += sizeof(struct smb2_encryption_neg_context) + 2;
- /* Round to 8 byte boundary */
- pneg_ctxt +=
- round_up(sizeof(struct smb2_encryption_neg_context) + 2,
- 8);
- }
-
- if (conn->compress_algorithm) {
- ctxt_size = round_up(ctxt_size, 8);
- ksmbd_debug(SMB,
- "assemble SMB2_COMPRESSION_CAPABILITIES context\n");
- /* Temporarily set to SMB3_COMPRESS_NONE */
- build_compression_ctxt((struct smb2_compression_capabilities_context *)pneg_ctxt,
- conn->compress_algorithm);
- rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
- ctxt_size += sizeof(struct smb2_compression_capabilities_context) + 2;
- /* Round to 8 byte boundary */
- pneg_ctxt += round_up(sizeof(struct smb2_compression_capabilities_context) + 2,
- 8);
- }
-
- if (conn->posix_ext_supported) {
- ctxt_size = round_up(ctxt_size, 8);
- ksmbd_debug(SMB,
- "assemble SMB2_POSIX_EXTENSIONS_AVAILABLE context\n");
- build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
- rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
- ctxt_size += sizeof(struct smb2_posix_neg_context);
- /* Round to 8 byte boundary */
- pneg_ctxt += round_up(sizeof(struct smb2_posix_neg_context), 8);
- }
-
- if (conn->signing_negotiated) {
- ctxt_size = round_up(ctxt_size, 8);
- ksmbd_debug(SMB,
- "assemble SMB2_SIGNING_CAPABILITIES context\n");
- build_sign_cap_ctxt((struct smb2_signing_capabilities *)pneg_ctxt,
- conn->signing_algorithm);
- rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
- ctxt_size += sizeof(struct smb2_signing_capabilities) + 2;
- }
-
- inc_rfc1001_len(smb2_buf_len, ctxt_size);
-}
-
-static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
- struct smb2_preauth_neg_context *pneg_ctxt,
- int ctxt_len)
-{
- /*
- * sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt,
- * which may not be present. Only check for used HashAlgorithms[1].
- */
- if (ctxt_len <
- sizeof(struct smb2_neg_context) + MIN_PREAUTH_CTXT_DATA_LEN)
- return STATUS_INVALID_PARAMETER;
-
- if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
- return STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP;
-
- conn->preauth_info->Preauth_HashId = SMB2_PREAUTH_INTEGRITY_SHA512;
- return STATUS_SUCCESS;
-}
-
-static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
- struct smb2_encryption_neg_context *pneg_ctxt,
- int ctxt_len)
-{
- int cph_cnt;
- int i, cphs_size;
-
- if (sizeof(struct smb2_encryption_neg_context) > ctxt_len) {
- pr_err("Invalid SMB2_ENCRYPTION_CAPABILITIES context size\n");
- return;
- }
-
- conn->cipher_type = 0;
-
- cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
- cphs_size = cph_cnt * sizeof(__le16);
-
- if (sizeof(struct smb2_encryption_neg_context) + cphs_size >
- ctxt_len) {
- pr_err("Invalid cipher count(%d)\n", cph_cnt);
- return;
- }
-
- if (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION))
- return;
-
- for (i = 0; i < cph_cnt; i++) {
- if (pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_GCM ||
- pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_CCM ||
- pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_CCM ||
- pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_GCM) {
- ksmbd_debug(SMB, "Cipher ID = 0x%x\n",
- pneg_ctxt->Ciphers[i]);
- conn->cipher_type = pneg_ctxt->Ciphers[i];
- break;
- }
- }
-}
-
-/**
- * smb3_encryption_negotiated() - checks if server and client agreed on enabling encryption
- * @conn: smb connection
- *
- * Return: true if connection should be encrypted, else false
- */
-bool smb3_encryption_negotiated(struct ksmbd_conn *conn)
-{
- if (!conn->ops->generate_encryptionkey)
- return false;
-
- /*
- * SMB 3.0 and 3.0.2 dialects use the SMB2_GLOBAL_CAP_ENCRYPTION flag.
- * SMB 3.1.1 uses the cipher_type field.
- */
- return (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) ||
- conn->cipher_type;
-}
-
-static void decode_compress_ctxt(struct ksmbd_conn *conn,
- struct smb2_compression_capabilities_context *pneg_ctxt)
-{
- conn->compress_algorithm = SMB3_COMPRESS_NONE;
-}
-
-static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
- struct smb2_signing_capabilities *pneg_ctxt,
- int ctxt_len)
-{
- int sign_algo_cnt;
- int i, sign_alos_size;
-
- if (sizeof(struct smb2_signing_capabilities) > ctxt_len) {
- pr_err("Invalid SMB2_SIGNING_CAPABILITIES context length\n");
- return;
- }
-
- conn->signing_negotiated = false;
- sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
- sign_alos_size = sign_algo_cnt * sizeof(__le16);
-
- if (sizeof(struct smb2_signing_capabilities) + sign_alos_size >
- ctxt_len) {
- pr_err("Invalid signing algorithm count(%d)\n", sign_algo_cnt);
- return;
- }
-
- for (i = 0; i < sign_algo_cnt; i++) {
- if (pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_HMAC_SHA256_LE ||
- pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_AES_CMAC_LE) {
- ksmbd_debug(SMB, "Signing Algorithm ID = 0x%x\n",
- pneg_ctxt->SigningAlgorithms[i]);
- conn->signing_negotiated = true;
- conn->signing_algorithm =
- pneg_ctxt->SigningAlgorithms[i];
- break;
- }
- }
-}
-
-static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
- struct smb2_negotiate_req *req,
- unsigned int len_of_smb)
-{
- /* +4 is to account for the RFC1001 len field */
- struct smb2_neg_context *pctx = (struct smb2_neg_context *)req;
- int i = 0, len_of_ctxts;
- unsigned int offset = le32_to_cpu(req->NegotiateContextOffset);
- unsigned int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
- __le32 status = STATUS_INVALID_PARAMETER;
-
- ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);
- if (len_of_smb <= offset) {
- ksmbd_debug(SMB, "Invalid response: negotiate context offset\n");
- return status;
- }
-
- len_of_ctxts = len_of_smb - offset;
-
- while (i++ < neg_ctxt_cnt) {
- int clen, ctxt_len;
-
- if (len_of_ctxts < (int)sizeof(struct smb2_neg_context))
- break;
-
- pctx = (struct smb2_neg_context *)((char *)pctx + offset);
- clen = le16_to_cpu(pctx->DataLength);
- ctxt_len = clen + sizeof(struct smb2_neg_context);
-
- if (ctxt_len > len_of_ctxts)
- break;
-
- if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
- ksmbd_debug(SMB,
- "deassemble SMB2_PREAUTH_INTEGRITY_CAPABILITIES context\n");
- if (conn->preauth_info->Preauth_HashId)
- break;
-
- status = decode_preauth_ctxt(conn,
- (struct smb2_preauth_neg_context *)pctx,
- ctxt_len);
- if (status != STATUS_SUCCESS)
- break;
- } else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
- ksmbd_debug(SMB,
- "deassemble SMB2_ENCRYPTION_CAPABILITIES context\n");
- if (conn->cipher_type)
- break;
-
- decode_encrypt_ctxt(conn,
- (struct smb2_encryption_neg_context *)pctx,
- ctxt_len);
- } else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) {
- ksmbd_debug(SMB,
- "deassemble SMB2_COMPRESSION_CAPABILITIES context\n");
- if (conn->compress_algorithm)
- break;
-
- decode_compress_ctxt(conn,
- (struct smb2_compression_capabilities_context *)pctx);
- } else if (pctx->ContextType == SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) {
- ksmbd_debug(SMB,
- "deassemble SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context\n");
- } else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) {
- ksmbd_debug(SMB,
- "deassemble SMB2_POSIX_EXTENSIONS_AVAILABLE context\n");
- conn->posix_ext_supported = true;
- } else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) {
- ksmbd_debug(SMB,
- "deassemble SMB2_SIGNING_CAPABILITIES context\n");
-
- decode_sign_cap_ctxt(conn,
- (struct smb2_signing_capabilities *)pctx,
- ctxt_len);
- }
-
- /* offsets must be 8 byte aligned */
- offset = (ctxt_len + 7) & ~0x7;
- len_of_ctxts -= offset;
- }
- return status;
-}
-
-/**
- * smb2_handle_negotiate() - handler for smb2 negotiate command
- * @work: smb work containing smb request buffer
- *
- * Return: 0
- */
-int smb2_handle_negotiate(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_negotiate_req *req = smb2_get_msg(work->request_buf);
- struct smb2_negotiate_rsp *rsp = smb2_get_msg(work->response_buf);
- int rc = 0;
- unsigned int smb2_buf_len, smb2_neg_size;
- __le32 status;
-
- ksmbd_debug(SMB, "Received negotiate request\n");
- conn->need_neg = false;
- if (ksmbd_conn_good(conn)) {
- pr_err("conn->tcp_status is already in CifsGood State\n");
- work->send_no_response = 1;
- return rc;
- }
-
- smb2_buf_len = get_rfc1002_len(work->request_buf);
- smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects);
- if (smb2_neg_size > smb2_buf_len) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- rc = -EINVAL;
- goto err_out;
- }
-
- if (req->DialectCount == 0) {
- pr_err("malformed packet\n");
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- rc = -EINVAL;
- goto err_out;
- }
-
- if (conn->dialect == SMB311_PROT_ID) {
- unsigned int nego_ctxt_off = le32_to_cpu(req->NegotiateContextOffset);
-
- if (smb2_buf_len < nego_ctxt_off) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- rc = -EINVAL;
- goto err_out;
- }
-
- if (smb2_neg_size > nego_ctxt_off) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- rc = -EINVAL;
- goto err_out;
- }
-
- if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) >
- nego_ctxt_off) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- rc = -EINVAL;
- goto err_out;
- }
- } else {
- if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) >
- smb2_buf_len) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- rc = -EINVAL;
- goto err_out;
- }
- }
-
- conn->cli_cap = le32_to_cpu(req->Capabilities);
- switch (conn->dialect) {
- case SMB311_PROT_ID:
- conn->preauth_info =
- kzalloc(sizeof(struct preauth_integrity_info),
- GFP_KERNEL);
- if (!conn->preauth_info) {
- rc = -ENOMEM;
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- goto err_out;
- }
-
- status = deassemble_neg_contexts(conn, req,
- get_rfc1002_len(work->request_buf));
- if (status != STATUS_SUCCESS) {
- pr_err("deassemble_neg_contexts error(0x%x)\n",
- status);
- rsp->hdr.Status = status;
- rc = -EINVAL;
- kfree(conn->preauth_info);
- conn->preauth_info = NULL;
- goto err_out;
- }
-
- rc = init_smb3_11_server(conn);
- if (rc < 0) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- kfree(conn->preauth_info);
- conn->preauth_info = NULL;
- goto err_out;
- }
-
- ksmbd_gen_preauth_integrity_hash(conn,
- work->request_buf,
- conn->preauth_info->Preauth_HashValue);
- rsp->NegotiateContextOffset =
- cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
- assemble_neg_contexts(conn, rsp, work->response_buf);
- break;
- case SMB302_PROT_ID:
- init_smb3_02_server(conn);
- break;
- case SMB30_PROT_ID:
- init_smb3_0_server(conn);
- break;
- case SMB21_PROT_ID:
- init_smb2_1_server(conn);
- break;
- case SMB2X_PROT_ID:
- case BAD_PROT_ID:
- default:
- ksmbd_debug(SMB, "Server dialect :0x%x not supported\n",
- conn->dialect);
- rsp->hdr.Status = STATUS_NOT_SUPPORTED;
- rc = -EINVAL;
- goto err_out;
- }
- rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
-
- /* For stats */
- conn->connection_type = conn->dialect;
-
- rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size);
- rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size);
- rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size);
-
- memcpy(conn->ClientGUID, req->ClientGUID,
- SMB2_CLIENT_GUID_SIZE);
- conn->cli_sec_mode = le16_to_cpu(req->SecurityMode);
-
- rsp->StructureSize = cpu_to_le16(65);
- rsp->DialectRevision = cpu_to_le16(conn->dialect);
- /* Not setting conn guid rsp->ServerGUID, as it
- * not used by client for identifying server
- */
- memset(rsp->ServerGUID, 0, SMB2_CLIENT_GUID_SIZE);
-
- rsp->SystemTime = cpu_to_le64(ksmbd_systime());
- rsp->ServerStartTime = 0;
- ksmbd_debug(SMB, "negotiate context offset %d, count %d\n",
- le32_to_cpu(rsp->NegotiateContextOffset),
- le16_to_cpu(rsp->NegotiateContextCount));
-
- rsp->SecurityBufferOffset = cpu_to_le16(128);
- rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
- ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
- le16_to_cpu(rsp->SecurityBufferOffset));
- inc_rfc1001_len(work->response_buf, sizeof(struct smb2_negotiate_rsp) -
- sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
- AUTH_GSS_LENGTH);
- rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
- conn->use_spnego = true;
-
- if ((server_conf.signing == KSMBD_CONFIG_OPT_AUTO ||
- server_conf.signing == KSMBD_CONFIG_OPT_DISABLED) &&
- req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED_LE)
- conn->sign = true;
- else if (server_conf.signing == KSMBD_CONFIG_OPT_MANDATORY) {
- server_conf.enforced_signing = true;
- rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
- conn->sign = true;
- }
-
- conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode);
- ksmbd_conn_set_need_negotiate(conn);
-
-err_out:
- if (rc < 0)
- smb2_set_err_rsp(work);
-
- return rc;
-}
-
-static int alloc_preauth_hash(struct ksmbd_session *sess,
- struct ksmbd_conn *conn)
-{
- if (sess->Preauth_HashValue)
- return 0;
-
- sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue,
- PREAUTH_HASHVALUE_SIZE, GFP_KERNEL);
- if (!sess->Preauth_HashValue)
- return -ENOMEM;
-
- return 0;
-}
-
-static int generate_preauth_hash(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct ksmbd_session *sess = work->sess;
- u8 *preauth_hash;
-
- if (conn->dialect != SMB311_PROT_ID)
- return 0;
-
- if (conn->binding) {
- struct preauth_session *preauth_sess;
-
- preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
- if (!preauth_sess) {
- preauth_sess = ksmbd_preauth_session_alloc(conn, sess->id);
- if (!preauth_sess)
- return -ENOMEM;
- }
-
- preauth_hash = preauth_sess->Preauth_HashValue;
- } else {
- if (!sess->Preauth_HashValue)
- if (alloc_preauth_hash(sess, conn))
- return -ENOMEM;
- preauth_hash = sess->Preauth_HashValue;
- }
-
- ksmbd_gen_preauth_integrity_hash(conn, work->request_buf, preauth_hash);
- return 0;
-}
-
-static int decode_negotiation_token(struct ksmbd_conn *conn,
- struct negotiate_message *negblob,
- size_t sz)
-{
- if (!conn->use_spnego)
- return -EINVAL;
-
- if (ksmbd_decode_negTokenInit((char *)negblob, sz, conn)) {
- if (ksmbd_decode_negTokenTarg((char *)negblob, sz, conn)) {
- conn->auth_mechs |= KSMBD_AUTH_NTLMSSP;
- conn->preferred_auth_mech = KSMBD_AUTH_NTLMSSP;
- conn->use_spnego = false;
- }
- }
- return 0;
-}
-
-static int ntlm_negotiate(struct ksmbd_work *work,
- struct negotiate_message *negblob,
- size_t negblob_len)
-{
- struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
- struct challenge_message *chgblob;
- unsigned char *spnego_blob = NULL;
- u16 spnego_blob_len;
- char *neg_blob;
- int sz, rc;
-
- ksmbd_debug(SMB, "negotiate phase\n");
- rc = ksmbd_decode_ntlmssp_neg_blob(negblob, negblob_len, work->conn);
- if (rc)
- return rc;
-
- sz = le16_to_cpu(rsp->SecurityBufferOffset);
- chgblob =
- (struct challenge_message *)((char *)&rsp->hdr.ProtocolId + sz);
- memset(chgblob, 0, sizeof(struct challenge_message));
-
- if (!work->conn->use_spnego) {
- sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn);
- if (sz < 0)
- return -ENOMEM;
-
- rsp->SecurityBufferLength = cpu_to_le16(sz);
- return 0;
- }
-
- sz = sizeof(struct challenge_message);
- sz += (strlen(ksmbd_netbios_name()) * 2 + 1 + 4) * 6;
-
- neg_blob = kzalloc(sz, GFP_KERNEL);
- if (!neg_blob)
- return -ENOMEM;
-
- chgblob = (struct challenge_message *)neg_blob;
- sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn);
- if (sz < 0) {
- rc = -ENOMEM;
- goto out;
- }
-
- rc = build_spnego_ntlmssp_neg_blob(&spnego_blob, &spnego_blob_len,
- neg_blob, sz);
- if (rc) {
- rc = -ENOMEM;
- goto out;
- }
-
- sz = le16_to_cpu(rsp->SecurityBufferOffset);
- memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
- rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
-
-out:
- kfree(spnego_blob);
- kfree(neg_blob);
- return rc;
-}
-
-static struct authenticate_message *user_authblob(struct ksmbd_conn *conn,
- struct smb2_sess_setup_req *req)
-{
- int sz;
-
- if (conn->use_spnego && conn->mechToken)
- return (struct authenticate_message *)conn->mechToken;
-
- sz = le16_to_cpu(req->SecurityBufferOffset);
- return (struct authenticate_message *)((char *)&req->hdr.ProtocolId
- + sz);
-}
-
-static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
- struct smb2_sess_setup_req *req)
-{
- struct authenticate_message *authblob;
- struct ksmbd_user *user;
- char *name;
- unsigned int name_off, name_len, secbuf_len;
-
- secbuf_len = le16_to_cpu(req->SecurityBufferLength);
- if (secbuf_len < sizeof(struct authenticate_message)) {
- ksmbd_debug(SMB, "blob len %d too small\n", secbuf_len);
- return NULL;
- }
- authblob = user_authblob(conn, req);
- name_off = le32_to_cpu(authblob->UserName.BufferOffset);
- name_len = le16_to_cpu(authblob->UserName.Length);
-
- if (secbuf_len < (u64)name_off + name_len)
- return NULL;
-
- name = smb_strndup_from_utf16((const char *)authblob + name_off,
- name_len,
- true,
- conn->local_nls);
- if (IS_ERR(name)) {
- pr_err("cannot allocate memory\n");
- return NULL;
- }
-
- ksmbd_debug(SMB, "session setup request for user %s\n", name);
- user = ksmbd_login_user(name);
- kfree(name);
- return user;
-}
-
-static int ntlm_authenticate(struct ksmbd_work *work)
-{
- struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
- struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
- struct ksmbd_conn *conn = work->conn;
- struct ksmbd_session *sess = work->sess;
- struct channel *chann = NULL;
- struct ksmbd_user *user;
- u64 prev_id;
- int sz, rc;
-
- ksmbd_debug(SMB, "authenticate phase\n");
- if (conn->use_spnego) {
- unsigned char *spnego_blob;
- u16 spnego_blob_len;
-
- rc = build_spnego_ntlmssp_auth_blob(&spnego_blob,
- &spnego_blob_len,
- 0);
- if (rc)
- return -ENOMEM;
-
- sz = le16_to_cpu(rsp->SecurityBufferOffset);
- memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
- rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
- kfree(spnego_blob);
- inc_rfc1001_len(work->response_buf, spnego_blob_len - 1);
- }
-
- user = session_user(conn, req);
- if (!user) {
- ksmbd_debug(SMB, "Unknown user name or an error\n");
- return -EPERM;
- }
-
- /* Check for previous session */
- prev_id = le64_to_cpu(req->PreviousSessionId);
- if (prev_id && prev_id != sess->id)
- destroy_previous_session(conn, user, prev_id);
-
- if (sess->state == SMB2_SESSION_VALID) {
- /*
- * Reuse session if anonymous try to connect
- * on reauthetication.
- */
- if (conn->binding == false && ksmbd_anonymous_user(user)) {
- ksmbd_free_user(user);
- return 0;
- }
-
- if (!ksmbd_compare_user(sess->user, user)) {
- ksmbd_free_user(user);
- return -EPERM;
- }
- ksmbd_free_user(user);
- } else {
- sess->user = user;
- }
-
- if (conn->binding == false && user_guest(sess->user)) {
- rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE;
- } else {
- struct authenticate_message *authblob;
-
- authblob = user_authblob(conn, req);
- sz = le16_to_cpu(req->SecurityBufferLength);
- rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, conn, sess);
- if (rc) {
- set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD);
- ksmbd_debug(SMB, "authentication failed\n");
- return -EPERM;
- }
- }
-
- /*
- * If session state is SMB2_SESSION_VALID, We can assume
- * that it is reauthentication. And the user/password
- * has been verified, so return it here.
- */
- if (sess->state == SMB2_SESSION_VALID) {
- if (conn->binding)
- goto binding_session;
- return 0;
- }
-
- if ((rsp->SessionFlags != SMB2_SESSION_FLAG_IS_GUEST_LE &&
- (conn->sign || server_conf.enforced_signing)) ||
- (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
- sess->sign = true;
-
- if (smb3_encryption_negotiated(conn) &&
- !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
- rc = conn->ops->generate_encryptionkey(conn, sess);
- if (rc) {
- ksmbd_debug(SMB,
- "SMB3 encryption key generation failed\n");
- return -EINVAL;
- }
- sess->enc = true;
- rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
- /*
- * signing is disable if encryption is enable
- * on this session
- */
- sess->sign = false;
- }
-
-binding_session:
- if (conn->dialect >= SMB30_PROT_ID) {
- chann = lookup_chann_list(sess, conn);
- if (!chann) {
- chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
- if (!chann)
- return -ENOMEM;
-
- chann->conn = conn;
- xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
- }
- }
-
- if (conn->ops->generate_signingkey) {
- rc = conn->ops->generate_signingkey(sess, conn);
- if (rc) {
- ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
- return -EINVAL;
- }
- }
-
- if (!ksmbd_conn_lookup_dialect(conn)) {
- pr_err("fail to verify the dialect\n");
- return -ENOENT;
- }
- return 0;
-}
-
-#ifdef CONFIG_SMB_SERVER_KERBEROS5
-static int krb5_authenticate(struct ksmbd_work *work)
-{
- struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
- struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
- struct ksmbd_conn *conn = work->conn;
- struct ksmbd_session *sess = work->sess;
- char *in_blob, *out_blob;
- struct channel *chann = NULL;
- u64 prev_sess_id;
- int in_len, out_len;
- int retval;
-
- in_blob = (char *)&req->hdr.ProtocolId +
- le16_to_cpu(req->SecurityBufferOffset);
- in_len = le16_to_cpu(req->SecurityBufferLength);
- out_blob = (char *)&rsp->hdr.ProtocolId +
- le16_to_cpu(rsp->SecurityBufferOffset);
- out_len = work->response_sz -
- (le16_to_cpu(rsp->SecurityBufferOffset) + 4);
-
- /* Check previous session */
- prev_sess_id = le64_to_cpu(req->PreviousSessionId);
- if (prev_sess_id && prev_sess_id != sess->id)
- destroy_previous_session(conn, sess->user, prev_sess_id);
-
- if (sess->state == SMB2_SESSION_VALID)
- ksmbd_free_user(sess->user);
-
- retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
- out_blob, &out_len);
- if (retval) {
- ksmbd_debug(SMB, "krb5 authentication failed\n");
- return -EINVAL;
- }
- rsp->SecurityBufferLength = cpu_to_le16(out_len);
- inc_rfc1001_len(work->response_buf, out_len - 1);
-
- if ((conn->sign || server_conf.enforced_signing) ||
- (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
- sess->sign = true;
-
- if (smb3_encryption_negotiated(conn)) {
- retval = conn->ops->generate_encryptionkey(conn, sess);
- if (retval) {
- ksmbd_debug(SMB,
- "SMB3 encryption key generation failed\n");
- return -EINVAL;
- }
- sess->enc = true;
- rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
- sess->sign = false;
- }
-
- if (conn->dialect >= SMB30_PROT_ID) {
- chann = lookup_chann_list(sess, conn);
- if (!chann) {
- chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
- if (!chann)
- return -ENOMEM;
-
- chann->conn = conn;
- xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
- }
- }
-
- if (conn->ops->generate_signingkey) {
- retval = conn->ops->generate_signingkey(sess, conn);
- if (retval) {
- ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
- return -EINVAL;
- }
- }
-
- if (!ksmbd_conn_lookup_dialect(conn)) {
- pr_err("fail to verify the dialect\n");
- return -ENOENT;
- }
- return 0;
-}
-#else
-static int krb5_authenticate(struct ksmbd_work *work)
-{
- return -EOPNOTSUPP;
-}
-#endif
-
-int smb2_sess_setup(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
- struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
- struct ksmbd_session *sess;
- struct negotiate_message *negblob;
- unsigned int negblob_len, negblob_off;
- int rc = 0;
-
- ksmbd_debug(SMB, "Received request for session setup\n");
-
- rsp->StructureSize = cpu_to_le16(9);
- rsp->SessionFlags = 0;
- rsp->SecurityBufferOffset = cpu_to_le16(72);
- rsp->SecurityBufferLength = 0;
- inc_rfc1001_len(work->response_buf, 9);
-
- ksmbd_conn_lock(conn);
- if (!req->hdr.SessionId) {
- sess = ksmbd_smb2_session_create();
- if (!sess) {
- rc = -ENOMEM;
- goto out_err;
- }
- rsp->hdr.SessionId = cpu_to_le64(sess->id);
- rc = ksmbd_session_register(conn, sess);
- if (rc)
- goto out_err;
- } else if (conn->dialect >= SMB30_PROT_ID &&
- (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
- req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) {
- u64 sess_id = le64_to_cpu(req->hdr.SessionId);
-
- sess = ksmbd_session_lookup_slowpath(sess_id);
- if (!sess) {
- rc = -ENOENT;
- goto out_err;
- }
-
- if (conn->dialect != sess->dialect) {
- rc = -EINVAL;
- goto out_err;
- }
-
- if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
- rc = -EINVAL;
- goto out_err;
- }
-
- if (strncmp(conn->ClientGUID, sess->ClientGUID,
- SMB2_CLIENT_GUID_SIZE)) {
- rc = -ENOENT;
- goto out_err;
- }
-
- if (sess->state == SMB2_SESSION_IN_PROGRESS) {
- rc = -EACCES;
- goto out_err;
- }
-
- if (sess->state == SMB2_SESSION_EXPIRED) {
- rc = -EFAULT;
- goto out_err;
- }
-
- if (ksmbd_conn_need_reconnect(conn)) {
- rc = -EFAULT;
- sess = NULL;
- goto out_err;
- }
-
- if (ksmbd_session_lookup(conn, sess_id)) {
- rc = -EACCES;
- goto out_err;
- }
-
- if (user_guest(sess->user)) {
- rc = -EOPNOTSUPP;
- goto out_err;
- }
-
- conn->binding = true;
- } else if ((conn->dialect < SMB30_PROT_ID ||
- server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
- (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
- sess = NULL;
- rc = -EACCES;
- goto out_err;
- } else {
- sess = ksmbd_session_lookup(conn,
- le64_to_cpu(req->hdr.SessionId));
- if (!sess) {
- rc = -ENOENT;
- goto out_err;
- }
-
- if (sess->state == SMB2_SESSION_EXPIRED) {
- rc = -EFAULT;
- goto out_err;
- }
-
- if (ksmbd_conn_need_reconnect(conn)) {
- rc = -EFAULT;
- sess = NULL;
- goto out_err;
- }
- }
- work->sess = sess;
-
- negblob_off = le16_to_cpu(req->SecurityBufferOffset);
- negblob_len = le16_to_cpu(req->SecurityBufferLength);
- if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer) ||
- negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) {
- rc = -EINVAL;
- goto out_err;
- }
-
- negblob = (struct negotiate_message *)((char *)&req->hdr.ProtocolId +
- negblob_off);
-
- if (decode_negotiation_token(conn, negblob, negblob_len) == 0) {
- if (conn->mechToken)
- negblob = (struct negotiate_message *)conn->mechToken;
- }
-
- if (server_conf.auth_mechs & conn->auth_mechs) {
- rc = generate_preauth_hash(work);
- if (rc)
- goto out_err;
-
- if (conn->preferred_auth_mech &
- (KSMBD_AUTH_KRB5 | KSMBD_AUTH_MSKRB5)) {
- rc = krb5_authenticate(work);
- if (rc) {
- rc = -EINVAL;
- goto out_err;
- }
-
- if (!ksmbd_conn_need_reconnect(conn)) {
- ksmbd_conn_set_good(conn);
- sess->state = SMB2_SESSION_VALID;
- }
- kfree(sess->Preauth_HashValue);
- sess->Preauth_HashValue = NULL;
- } else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
- if (negblob->MessageType == NtLmNegotiate) {
- rc = ntlm_negotiate(work, negblob, negblob_len);
- if (rc)
- goto out_err;
- rsp->hdr.Status =
- STATUS_MORE_PROCESSING_REQUIRED;
- /*
- * Note: here total size -1 is done as an
- * adjustment for 0 size blob
- */
- inc_rfc1001_len(work->response_buf,
- le16_to_cpu(rsp->SecurityBufferLength) - 1);
-
- } else if (negblob->MessageType == NtLmAuthenticate) {
- rc = ntlm_authenticate(work);
- if (rc)
- goto out_err;
-
- if (!ksmbd_conn_need_reconnect(conn)) {
- ksmbd_conn_set_good(conn);
- sess->state = SMB2_SESSION_VALID;
- }
- if (conn->binding) {
- struct preauth_session *preauth_sess;
-
- preauth_sess =
- ksmbd_preauth_session_lookup(conn, sess->id);
- if (preauth_sess) {
- list_del(&preauth_sess->preauth_entry);
- kfree(preauth_sess);
- }
- }
- kfree(sess->Preauth_HashValue);
- sess->Preauth_HashValue = NULL;
- } else {
- pr_info_ratelimited("Unknown NTLMSSP message type : 0x%x\n",
- le32_to_cpu(negblob->MessageType));
- rc = -EINVAL;
- }
- } else {
- /* TODO: need one more negotiation */
- pr_err("Not support the preferred authentication\n");
- rc = -EINVAL;
- }
- } else {
- pr_err("Not support authentication\n");
- rc = -EINVAL;
- }
-
-out_err:
- if (rc == -EINVAL)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- else if (rc == -ENOENT)
- rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
- else if (rc == -EACCES)
- rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED;
- else if (rc == -EFAULT)
- rsp->hdr.Status = STATUS_NETWORK_SESSION_EXPIRED;
- else if (rc == -ENOMEM)
- rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
- else if (rc == -EOPNOTSUPP)
- rsp->hdr.Status = STATUS_NOT_SUPPORTED;
- else if (rc)
- rsp->hdr.Status = STATUS_LOGON_FAILURE;
-
- if (conn->use_spnego && conn->mechToken) {
- kfree(conn->mechToken);
- conn->mechToken = NULL;
- }
-
- if (rc < 0) {
- /*
- * SecurityBufferOffset should be set to zero
- * in session setup error response.
- */
- rsp->SecurityBufferOffset = 0;
-
- if (sess) {
- bool try_delay = false;
-
- /*
- * To avoid dictionary attacks (repeated session setups rapidly sent) to
- * connect to server, ksmbd make a delay of a 5 seconds on session setup
- * failure to make it harder to send enough random connection requests
- * to break into a server.
- */
- if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION)
- try_delay = true;
-
- sess->last_active = jiffies;
- sess->state = SMB2_SESSION_EXPIRED;
- if (try_delay) {
- ksmbd_conn_set_need_reconnect(conn);
- ssleep(5);
- ksmbd_conn_set_need_negotiate(conn);
- }
- }
- }
-
- ksmbd_conn_unlock(conn);
- return rc;
-}
-
-/**
- * smb2_tree_connect() - handler for smb2 tree connect command
- * @work: smb work containing smb request buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_tree_connect(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_tree_connect_req *req = smb2_get_msg(work->request_buf);
- struct smb2_tree_connect_rsp *rsp = smb2_get_msg(work->response_buf);
- struct ksmbd_session *sess = work->sess;
- char *treename = NULL, *name = NULL;
- struct ksmbd_tree_conn_status status;
- struct ksmbd_share_config *share;
- int rc = -EINVAL;
-
- treename = smb_strndup_from_utf16(req->Buffer,
- le16_to_cpu(req->PathLength), true,
- conn->local_nls);
- if (IS_ERR(treename)) {
- pr_err("treename is NULL\n");
- status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
- goto out_err1;
- }
-
- name = ksmbd_extract_sharename(conn->um, treename);
- if (IS_ERR(name)) {
- status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
- goto out_err1;
- }
-
- ksmbd_debug(SMB, "tree connect request for tree %s treename %s\n",
- name, treename);
-
- status = ksmbd_tree_conn_connect(conn, sess, name);
- if (status.ret == KSMBD_TREE_CONN_STATUS_OK)
- rsp->hdr.Id.SyncId.TreeId = cpu_to_le32(status.tree_conn->id);
- else
- goto out_err1;
-
- share = status.tree_conn->share_conf;
- if (test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
- ksmbd_debug(SMB, "IPC share path request\n");
- rsp->ShareType = SMB2_SHARE_TYPE_PIPE;
- rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE |
- FILE_EXECUTE_LE | FILE_READ_ATTRIBUTES_LE |
- FILE_DELETE_LE | FILE_READ_CONTROL_LE |
- FILE_WRITE_DAC_LE | FILE_WRITE_OWNER_LE |
- FILE_SYNCHRONIZE_LE;
- } else {
- rsp->ShareType = SMB2_SHARE_TYPE_DISK;
- rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE |
- FILE_EXECUTE_LE | FILE_READ_ATTRIBUTES_LE;
- if (test_tree_conn_flag(status.tree_conn,
- KSMBD_TREE_CONN_FLAG_WRITABLE)) {
- rsp->MaximalAccess |= FILE_WRITE_DATA_LE |
- FILE_APPEND_DATA_LE | FILE_WRITE_EA_LE |
- FILE_DELETE_LE | FILE_WRITE_ATTRIBUTES_LE |
- FILE_DELETE_CHILD_LE | FILE_READ_CONTROL_LE |
- FILE_WRITE_DAC_LE | FILE_WRITE_OWNER_LE |
- FILE_SYNCHRONIZE_LE;
- }
- }
-
- status.tree_conn->maximal_access = le32_to_cpu(rsp->MaximalAccess);
- if (conn->posix_ext_supported)
- status.tree_conn->posix_extensions = true;
-
- rsp->StructureSize = cpu_to_le16(16);
- inc_rfc1001_len(work->response_buf, 16);
-out_err1:
- rsp->Capabilities = 0;
- rsp->Reserved = 0;
- /* default manual caching */
- rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
-
- if (!IS_ERR(treename))
- kfree(treename);
- if (!IS_ERR(name))
- kfree(name);
-
- switch (status.ret) {
- case KSMBD_TREE_CONN_STATUS_OK:
- rsp->hdr.Status = STATUS_SUCCESS;
- rc = 0;
- break;
- case -ESTALE:
- case -ENOENT:
- case KSMBD_TREE_CONN_STATUS_NO_SHARE:
- rsp->hdr.Status = STATUS_BAD_NETWORK_NAME;
- break;
- case -ENOMEM:
- case KSMBD_TREE_CONN_STATUS_NOMEM:
- rsp->hdr.Status = STATUS_NO_MEMORY;
- break;
- case KSMBD_TREE_CONN_STATUS_ERROR:
- case KSMBD_TREE_CONN_STATUS_TOO_MANY_CONNS:
- case KSMBD_TREE_CONN_STATUS_TOO_MANY_SESSIONS:
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- break;
- case -EINVAL:
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- break;
- default:
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- }
-
- if (status.ret != KSMBD_TREE_CONN_STATUS_OK)
- smb2_set_err_rsp(work);
-
- return rc;
-}
-
-/**
- * smb2_create_open_flags() - convert smb open flags to unix open flags
- * @file_present: is file already present
- * @access: file access flags
- * @disposition: file disposition flags
- * @may_flags: set with MAY_ flags
- *
- * Return: file open flags
- */
-static int smb2_create_open_flags(bool file_present, __le32 access,
- __le32 disposition,
- int *may_flags)
-{
- int oflags = O_NONBLOCK | O_LARGEFILE;
-
- if (access & FILE_READ_DESIRED_ACCESS_LE &&
- access & FILE_WRITE_DESIRE_ACCESS_LE) {
- oflags |= O_RDWR;
- *may_flags = MAY_OPEN | MAY_READ | MAY_WRITE;
- } else if (access & FILE_WRITE_DESIRE_ACCESS_LE) {
- oflags |= O_WRONLY;
- *may_flags = MAY_OPEN | MAY_WRITE;
- } else {
- oflags |= O_RDONLY;
- *may_flags = MAY_OPEN | MAY_READ;
- }
-
- if (access == FILE_READ_ATTRIBUTES_LE)
- oflags |= O_PATH;
-
- if (file_present) {
- switch (disposition & FILE_CREATE_MASK_LE) {
- case FILE_OPEN_LE:
- case FILE_CREATE_LE:
- break;
- case FILE_SUPERSEDE_LE:
- case FILE_OVERWRITE_LE:
- case FILE_OVERWRITE_IF_LE:
- oflags |= O_TRUNC;
- break;
- default:
- break;
- }
- } else {
- switch (disposition & FILE_CREATE_MASK_LE) {
- case FILE_SUPERSEDE_LE:
- case FILE_CREATE_LE:
- case FILE_OPEN_IF_LE:
- case FILE_OVERWRITE_IF_LE:
- oflags |= O_CREAT;
- break;
- case FILE_OPEN_LE:
- case FILE_OVERWRITE_LE:
- oflags &= ~O_CREAT;
- break;
- default:
- break;
- }
- }
-
- return oflags;
-}
-
-/**
- * smb2_tree_disconnect() - handler for smb tree connect request
- * @work: smb work containing request buffer
- *
- * Return: 0
- */
-int smb2_tree_disconnect(struct ksmbd_work *work)
-{
- struct smb2_tree_disconnect_rsp *rsp = smb2_get_msg(work->response_buf);
- struct ksmbd_session *sess = work->sess;
- struct ksmbd_tree_connect *tcon = work->tcon;
-
- rsp->StructureSize = cpu_to_le16(4);
- inc_rfc1001_len(work->response_buf, 4);
-
- ksmbd_debug(SMB, "request\n");
-
- if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) {
- struct smb2_tree_disconnect_req *req =
- smb2_get_msg(work->request_buf);
-
- ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
-
- rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
- smb2_set_err_rsp(work);
- return 0;
- }
-
- ksmbd_close_tree_conn_fds(work);
- ksmbd_tree_conn_disconnect(sess, tcon);
- work->tcon = NULL;
- return 0;
-}
-
-/**
- * smb2_session_logoff() - handler for session log off request
- * @work: smb work containing request buffer
- *
- * Return: 0
- */
-int smb2_session_logoff(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_logoff_rsp *rsp = smb2_get_msg(work->response_buf);
- struct ksmbd_session *sess;
- struct smb2_logoff_req *req = smb2_get_msg(work->request_buf);
- u64 sess_id = le64_to_cpu(req->hdr.SessionId);
-
- rsp->StructureSize = cpu_to_le16(4);
- inc_rfc1001_len(work->response_buf, 4);
-
- ksmbd_debug(SMB, "request\n");
-
- ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_RECONNECT);
- ksmbd_close_session_fds(work);
- ksmbd_conn_wait_idle(conn, sess_id);
-
- /*
- * Re-lookup session to validate if session is deleted
- * while waiting request complete
- */
- sess = ksmbd_session_lookup_all(conn, sess_id);
- if (ksmbd_tree_conn_session_logoff(sess)) {
- ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
- rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
- smb2_set_err_rsp(work);
- return 0;
- }
-
- ksmbd_destroy_file_table(&sess->file_table);
- sess->state = SMB2_SESSION_EXPIRED;
-
- ksmbd_free_user(sess->user);
- sess->user = NULL;
- ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE);
- return 0;
-}
-
-/**
- * create_smb2_pipe() - create IPC pipe
- * @work: smb work containing request buffer
- *
- * Return: 0 on success, otherwise error
- */
-static noinline int create_smb2_pipe(struct ksmbd_work *work)
-{
- struct smb2_create_rsp *rsp = smb2_get_msg(work->response_buf);
- struct smb2_create_req *req = smb2_get_msg(work->request_buf);
- int id;
- int err;
- char *name;
-
- name = smb_strndup_from_utf16(req->Buffer, le16_to_cpu(req->NameLength),
- 1, work->conn->local_nls);
- if (IS_ERR(name)) {
- rsp->hdr.Status = STATUS_NO_MEMORY;
- err = PTR_ERR(name);
- goto out;
- }
-
- id = ksmbd_session_rpc_open(work->sess, name);
- if (id < 0) {
- pr_err("Unable to open RPC pipe: %d\n", id);
- err = id;
- goto out;
- }
-
- rsp->hdr.Status = STATUS_SUCCESS;
- rsp->StructureSize = cpu_to_le16(89);
- rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE;
- rsp->Flags = 0;
- rsp->CreateAction = cpu_to_le32(FILE_OPENED);
-
- rsp->CreationTime = cpu_to_le64(0);
- rsp->LastAccessTime = cpu_to_le64(0);
- rsp->ChangeTime = cpu_to_le64(0);
- rsp->AllocationSize = cpu_to_le64(0);
- rsp->EndofFile = cpu_to_le64(0);
- rsp->FileAttributes = FILE_ATTRIBUTE_NORMAL_LE;
- rsp->Reserved2 = 0;
- rsp->VolatileFileId = id;
- rsp->PersistentFileId = 0;
- rsp->CreateContextsOffset = 0;
- rsp->CreateContextsLength = 0;
-
- inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
- kfree(name);
- return 0;
-
-out:
- switch (err) {
- case -EINVAL:
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- break;
- case -ENOSPC:
- case -ENOMEM:
- rsp->hdr.Status = STATUS_NO_MEMORY;
- break;
- }
-
- if (!IS_ERR(name))
- kfree(name);
-
- smb2_set_err_rsp(work);
- return err;
-}
-
-/**
- * smb2_set_ea() - handler for setting extended attributes using set
- * info command
- * @eabuf: set info command buffer
- * @buf_len: set info command buffer length
- * @path: dentry path for get ea
- *
- * Return: 0 on success, otherwise error
- */
-static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
- const struct path *path)
-{
- struct user_namespace *user_ns = mnt_user_ns(path->mnt);
- char *attr_name = NULL, *value;
- int rc = 0;
- unsigned int next = 0;
-
- if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength +
- le16_to_cpu(eabuf->EaValueLength))
- return -EINVAL;
-
- attr_name = kmalloc(XATTR_NAME_MAX + 1, GFP_KERNEL);
- if (!attr_name)
- return -ENOMEM;
-
- do {
- if (!eabuf->EaNameLength)
- goto next;
-
- ksmbd_debug(SMB,
- "name : <%s>, name_len : %u, value_len : %u, next : %u\n",
- eabuf->name, eabuf->EaNameLength,
- le16_to_cpu(eabuf->EaValueLength),
- le32_to_cpu(eabuf->NextEntryOffset));
-
- if (eabuf->EaNameLength >
- (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
- rc = -EINVAL;
- break;
- }
-
- memcpy(attr_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
- memcpy(&attr_name[XATTR_USER_PREFIX_LEN], eabuf->name,
- eabuf->EaNameLength);
- attr_name[XATTR_USER_PREFIX_LEN + eabuf->EaNameLength] = '\0';
- value = (char *)&eabuf->name + eabuf->EaNameLength + 1;
-
- if (!eabuf->EaValueLength) {
- rc = ksmbd_vfs_casexattr_len(user_ns,
- path->dentry,
- attr_name,
- XATTR_USER_PREFIX_LEN +
- eabuf->EaNameLength);
-
- /* delete the EA only when it exits */
- if (rc > 0) {
- rc = ksmbd_vfs_remove_xattr(user_ns,
- path->dentry,
- attr_name);
-
- if (rc < 0) {
- ksmbd_debug(SMB,
- "remove xattr failed(%d)\n",
- rc);
- break;
- }
- }
-
- /* if the EA doesn't exist, just do nothing. */
- rc = 0;
- } else {
- rc = ksmbd_vfs_setxattr(user_ns,
- path->dentry, attr_name, value,
- le16_to_cpu(eabuf->EaValueLength), 0);
- if (rc < 0) {
- ksmbd_debug(SMB,
- "ksmbd_vfs_setxattr is failed(%d)\n",
- rc);
- break;
- }
- }
-
-next:
- next = le32_to_cpu(eabuf->NextEntryOffset);
- if (next == 0 || buf_len < next)
- break;
- buf_len -= next;
- eabuf = (struct smb2_ea_info *)((char *)eabuf + next);
- if (next < (u32)eabuf->EaNameLength + le16_to_cpu(eabuf->EaValueLength))
- break;
-
- } while (next != 0);
-
- kfree(attr_name);
- return rc;
-}
-
-static noinline int smb2_set_stream_name_xattr(const struct path *path,
- struct ksmbd_file *fp,
- char *stream_name, int s_type)
-{
- struct user_namespace *user_ns = mnt_user_ns(path->mnt);
- size_t xattr_stream_size;
- char *xattr_stream_name;
- int rc;
-
- rc = ksmbd_vfs_xattr_stream_name(stream_name,
- &xattr_stream_name,
- &xattr_stream_size,
- s_type);
- if (rc)
- return rc;
-
- fp->stream.name = xattr_stream_name;
- fp->stream.size = xattr_stream_size;
-
- /* Check if there is stream prefix in xattr space */
- rc = ksmbd_vfs_casexattr_len(user_ns,
- path->dentry,
- xattr_stream_name,
- xattr_stream_size);
- if (rc >= 0)
- return 0;
-
- if (fp->cdoption == FILE_OPEN_LE) {
- ksmbd_debug(SMB, "XATTR stream name lookup failed: %d\n", rc);
- return -EBADF;
- }
-
- rc = ksmbd_vfs_setxattr(user_ns, path->dentry,
- xattr_stream_name, NULL, 0, 0);
- if (rc < 0)
- pr_err("Failed to store XATTR stream name :%d\n", rc);
- return 0;
-}
-
-static int smb2_remove_smb_xattrs(const struct path *path)
-{
- struct user_namespace *user_ns = mnt_user_ns(path->mnt);
- char *name, *xattr_list = NULL;
- ssize_t xattr_list_len;
- int err = 0;
-
- xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
- if (xattr_list_len < 0) {
- goto out;
- } else if (!xattr_list_len) {
- ksmbd_debug(SMB, "empty xattr in the file\n");
- goto out;
- }
-
- for (name = xattr_list; name - xattr_list < xattr_list_len;
- name += strlen(name) + 1) {
- ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
-
- if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
- !strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
- STREAM_PREFIX_LEN)) {
- err = ksmbd_vfs_remove_xattr(user_ns, path->dentry,
- name);
- if (err)
- ksmbd_debug(SMB, "remove xattr failed : %s\n",
- name);
- }
- }
-out:
- kvfree(xattr_list);
- return err;
-}
-
-static int smb2_create_truncate(const struct path *path)
-{
- int rc = vfs_truncate(path, 0);
-
- if (rc) {
- pr_err("vfs_truncate failed, rc %d\n", rc);
- return rc;
- }
-
- rc = smb2_remove_smb_xattrs(path);
- if (rc == -EOPNOTSUPP)
- rc = 0;
- if (rc)
- ksmbd_debug(SMB,
- "ksmbd_truncate_stream_name_xattr failed, rc %d\n",
- rc);
- return rc;
-}
-
-static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *path,
- struct ksmbd_file *fp)
-{
- struct xattr_dos_attrib da = {0};
- int rc;
-
- if (!test_share_config_flag(tcon->share_conf,
- KSMBD_SHARE_FLAG_STORE_DOS_ATTRS))
- return;
-
- da.version = 4;
- da.attr = le32_to_cpu(fp->f_ci->m_fattr);
- da.itime = da.create_time = fp->create_time;
- da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
- XATTR_DOSINFO_ITIME;
-
- rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt),
- path->dentry, &da);
- if (rc)
- ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
-}
-
-static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
- const struct path *path, struct ksmbd_file *fp)
-{
- struct xattr_dos_attrib da;
- int rc;
-
- fp->f_ci->m_fattr &= ~(FILE_ATTRIBUTE_HIDDEN_LE | FILE_ATTRIBUTE_SYSTEM_LE);
-
- /* get FileAttributes from XATTR_NAME_DOS_ATTRIBUTE */
- if (!test_share_config_flag(tcon->share_conf,
- KSMBD_SHARE_FLAG_STORE_DOS_ATTRS))
- return;
-
- rc = ksmbd_vfs_get_dos_attrib_xattr(mnt_user_ns(path->mnt),
- path->dentry, &da);
- if (rc > 0) {
- fp->f_ci->m_fattr = cpu_to_le32(da.attr);
- fp->create_time = da.create_time;
- fp->itime = da.itime;
- }
-}
-
-static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
- int open_flags, umode_t posix_mode, bool is_dir)
-{
- struct ksmbd_tree_connect *tcon = work->tcon;
- struct ksmbd_share_config *share = tcon->share_conf;
- umode_t mode;
- int rc;
-
- if (!(open_flags & O_CREAT))
- return -EBADF;
-
- ksmbd_debug(SMB, "file does not exist, so creating\n");
- if (is_dir == true) {
- ksmbd_debug(SMB, "creating directory\n");
-
- mode = share_config_directory_mode(share, posix_mode);
- rc = ksmbd_vfs_mkdir(work, name, mode);
- if (rc)
- return rc;
- } else {
- ksmbd_debug(SMB, "creating regular file\n");
-
- mode = share_config_create_mode(share, posix_mode);
- rc = ksmbd_vfs_create(work, name, mode);
- if (rc)
- return rc;
- }
-
- rc = ksmbd_vfs_kern_path(work, name, 0, path, 0);
- if (rc) {
- pr_err("cannot get linux path (%s), err = %d\n",
- name, rc);
- return rc;
- }
- return 0;
-}
-
-static int smb2_create_sd_buffer(struct ksmbd_work *work,
- struct smb2_create_req *req,
- const struct path *path)
-{
- struct create_context *context;
- struct create_sd_buf_req *sd_buf;
-
- if (!req->CreateContextsOffset)
- return -ENOENT;
-
- /* Parse SD BUFFER create contexts */
- context = smb2_find_context_vals(req, SMB2_CREATE_SD_BUFFER, 4);
- if (!context)
- return -ENOENT;
- else if (IS_ERR(context))
- return PTR_ERR(context);
-
- ksmbd_debug(SMB,
- "Set ACLs using SMB2_CREATE_SD_BUFFER context\n");
- sd_buf = (struct create_sd_buf_req *)context;
- if (le16_to_cpu(context->DataOffset) +
- le32_to_cpu(context->DataLength) <
- sizeof(struct create_sd_buf_req))
- return -EINVAL;
- return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd,
- le32_to_cpu(sd_buf->ccontext.DataLength), true);
-}
-
-static void ksmbd_acls_fattr(struct smb_fattr *fattr,
- struct user_namespace *mnt_userns,
- struct inode *inode)
-{
- vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
- vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
-
- fattr->cf_uid = vfsuid_into_kuid(vfsuid);
- fattr->cf_gid = vfsgid_into_kgid(vfsgid);
- fattr->cf_mode = inode->i_mode;
- fattr->cf_acls = NULL;
- fattr->cf_dacls = NULL;
-
- if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
- fattr->cf_acls = get_acl(inode, ACL_TYPE_ACCESS);
- if (S_ISDIR(inode->i_mode))
- fattr->cf_dacls = get_acl(inode, ACL_TYPE_DEFAULT);
- }
-}
-
-/**
- * smb2_open() - handler for smb file open request
- * @work: smb work containing request buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_open(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct ksmbd_session *sess = work->sess;
- struct ksmbd_tree_connect *tcon = work->tcon;
- struct smb2_create_req *req;
- struct smb2_create_rsp *rsp;
- struct path path;
- struct ksmbd_share_config *share = tcon->share_conf;
- struct ksmbd_file *fp = NULL;
- struct file *filp = NULL;
- struct user_namespace *user_ns = NULL;
- struct kstat stat;
- struct create_context *context;
- struct lease_ctx_info *lc = NULL;
- struct create_ea_buf_req *ea_buf = NULL;
- struct oplock_info *opinfo;
- __le32 *next_ptr = NULL;
- int req_op_level = 0, open_flags = 0, may_flags = 0, file_info = 0;
- int rc = 0;
- int contxt_cnt = 0, query_disk_id = 0;
- int maximal_access_ctxt = 0, posix_ctxt = 0;
- int s_type = 0;
- int next_off = 0;
- char *name = NULL;
- char *stream_name = NULL;
- bool file_present = false, created = false, already_permitted = false;
- int share_ret, need_truncate = 0;
- u64 time;
- umode_t posix_mode = 0;
- __le32 daccess, maximal_access = 0;
-
- WORK_BUFFERS(work, req, rsp);
-
- if (req->hdr.NextCommand && !work->next_smb2_rcv_hdr_off &&
- (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)) {
- ksmbd_debug(SMB, "invalid flag in chained command\n");
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- smb2_set_err_rsp(work);
- return -EINVAL;
- }
-
- if (test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
- ksmbd_debug(SMB, "IPC pipe create request\n");
- return create_smb2_pipe(work);
- }
-
- if (req->NameLength) {
- if ((req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
- *(char *)req->Buffer == '\\') {
- pr_err("not allow directory name included leading slash\n");
- rc = -EINVAL;
- goto err_out1;
- }
-
- name = smb2_get_name(req->Buffer,
- le16_to_cpu(req->NameLength),
- work->conn->local_nls);
- if (IS_ERR(name)) {
- rc = PTR_ERR(name);
- if (rc != -ENOMEM)
- rc = -ENOENT;
- name = NULL;
- goto err_out1;
- }
-
- ksmbd_debug(SMB, "converted name = %s\n", name);
- if (strchr(name, ':')) {
- if (!test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_STREAMS)) {
- rc = -EBADF;
- goto err_out1;
- }
- rc = parse_stream_name(name, &stream_name, &s_type);
- if (rc < 0)
- goto err_out1;
- }
-
- rc = ksmbd_validate_filename(name);
- if (rc < 0)
- goto err_out1;
-
- if (ksmbd_share_veto_filename(share, name)) {
- rc = -ENOENT;
- ksmbd_debug(SMB, "Reject open(), vetoed file: %s\n",
- name);
- goto err_out1;
- }
- } else {
- name = kstrdup("", GFP_KERNEL);
- if (!name) {
- rc = -ENOMEM;
- goto err_out1;
- }
- }
-
- req_op_level = req->RequestedOplockLevel;
- if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
- lc = parse_lease_state(req);
-
- if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE)) {
- pr_err("Invalid impersonationlevel : 0x%x\n",
- le32_to_cpu(req->ImpersonationLevel));
- rc = -EIO;
- rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL;
- goto err_out1;
- }
-
- if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK_LE)) {
- pr_err("Invalid create options : 0x%x\n",
- le32_to_cpu(req->CreateOptions));
- rc = -EINVAL;
- goto err_out1;
- } else {
- if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE &&
- req->CreateOptions & FILE_RANDOM_ACCESS_LE)
- req->CreateOptions = ~(FILE_SEQUENTIAL_ONLY_LE);
-
- if (req->CreateOptions &
- (FILE_OPEN_BY_FILE_ID_LE | CREATE_TREE_CONNECTION |
- FILE_RESERVE_OPFILTER_LE)) {
- rc = -EOPNOTSUPP;
- goto err_out1;
- }
-
- if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
- if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) {
- rc = -EINVAL;
- goto err_out1;
- } else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) {
- req->CreateOptions = ~(FILE_NO_COMPRESSION_LE);
- }
- }
- }
-
- if (le32_to_cpu(req->CreateDisposition) >
- le32_to_cpu(FILE_OVERWRITE_IF_LE)) {
- pr_err("Invalid create disposition : 0x%x\n",
- le32_to_cpu(req->CreateDisposition));
- rc = -EINVAL;
- goto err_out1;
- }
-
- if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) {
- pr_err("Invalid desired access : 0x%x\n",
- le32_to_cpu(req->DesiredAccess));
- rc = -EACCES;
- goto err_out1;
- }
-
- if (req->FileAttributes && !(req->FileAttributes & FILE_ATTRIBUTE_MASK_LE)) {
- pr_err("Invalid file attribute : 0x%x\n",
- le32_to_cpu(req->FileAttributes));
- rc = -EINVAL;
- goto err_out1;
- }
-
- if (req->CreateContextsOffset) {
- /* Parse non-durable handle create contexts */
- context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER, 4);
- if (IS_ERR(context)) {
- rc = PTR_ERR(context);
- goto err_out1;
- } else if (context) {
- ea_buf = (struct create_ea_buf_req *)context;
- if (le16_to_cpu(context->DataOffset) +
- le32_to_cpu(context->DataLength) <
- sizeof(struct create_ea_buf_req)) {
- rc = -EINVAL;
- goto err_out1;
- }
- if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) {
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- rc = -EACCES;
- goto err_out1;
- }
- }
-
- context = smb2_find_context_vals(req,
- SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4);
- if (IS_ERR(context)) {
- rc = PTR_ERR(context);
- goto err_out1;
- } else if (context) {
- ksmbd_debug(SMB,
- "get query maximal access context\n");
- maximal_access_ctxt = 1;
- }
-
- context = smb2_find_context_vals(req,
- SMB2_CREATE_TIMEWARP_REQUEST, 4);
- if (IS_ERR(context)) {
- rc = PTR_ERR(context);
- goto err_out1;
- } else if (context) {
- ksmbd_debug(SMB, "get timewarp context\n");
- rc = -EBADF;
- goto err_out1;
- }
-
- if (tcon->posix_extensions) {
- context = smb2_find_context_vals(req,
- SMB2_CREATE_TAG_POSIX, 16);
- if (IS_ERR(context)) {
- rc = PTR_ERR(context);
- goto err_out1;
- } else if (context) {
- struct create_posix *posix =
- (struct create_posix *)context;
- if (le16_to_cpu(context->DataOffset) +
- le32_to_cpu(context->DataLength) <
- sizeof(struct create_posix) - 4) {
- rc = -EINVAL;
- goto err_out1;
- }
- ksmbd_debug(SMB, "get posix context\n");
-
- posix_mode = le32_to_cpu(posix->Mode);
- posix_ctxt = 1;
- }
- }
- }
-
- if (ksmbd_override_fsids(work)) {
- rc = -ENOMEM;
- goto err_out1;
- }
-
- rc = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS, &path, 1);
- if (!rc) {
- if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) {
- /*
- * If file exists with under flags, return access
- * denied error.
- */
- if (req->CreateDisposition == FILE_OVERWRITE_IF_LE ||
- req->CreateDisposition == FILE_OPEN_IF_LE) {
- rc = -EACCES;
- path_put(&path);
- goto err_out;
- }
-
- if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
- ksmbd_debug(SMB,
- "User does not have write permission\n");
- rc = -EACCES;
- path_put(&path);
- goto err_out;
- }
- } else if (d_is_symlink(path.dentry)) {
- rc = -EACCES;
- path_put(&path);
- goto err_out;
- }
- }
-
- if (rc) {
- if (rc != -ENOENT)
- goto err_out;
- ksmbd_debug(SMB, "can not get linux path for %s, rc = %d\n",
- name, rc);
- rc = 0;
- } else {
- file_present = true;
- user_ns = mnt_user_ns(path.mnt);
- }
- if (stream_name) {
- if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
- if (s_type == DATA_STREAM) {
- rc = -EIO;
- rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
- }
- } else {
- if (file_present && S_ISDIR(d_inode(path.dentry)->i_mode) &&
- s_type == DATA_STREAM) {
- rc = -EIO;
- rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
- }
- }
-
- if (req->CreateOptions & FILE_DIRECTORY_FILE_LE &&
- req->FileAttributes & FILE_ATTRIBUTE_NORMAL_LE) {
- rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
- rc = -EIO;
- }
-
- if (rc < 0)
- goto err_out;
- }
-
- if (file_present && req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE &&
- S_ISDIR(d_inode(path.dentry)->i_mode) &&
- !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
- ksmbd_debug(SMB, "open() argument is a directory: %s, %x\n",
- name, req->CreateOptions);
- rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
- rc = -EIO;
- goto err_out;
- }
-
- if (file_present && (req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
- !(req->CreateDisposition == FILE_CREATE_LE) &&
- !S_ISDIR(d_inode(path.dentry)->i_mode)) {
- rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
- rc = -EIO;
- goto err_out;
- }
-
- if (!stream_name && file_present &&
- req->CreateDisposition == FILE_CREATE_LE) {
- rc = -EEXIST;
- goto err_out;
- }
-
- daccess = smb_map_generic_desired_access(req->DesiredAccess);
-
- if (file_present && !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
- rc = smb_check_perm_dacl(conn, &path, &daccess,
- sess->user->uid);
- if (rc)
- goto err_out;
- }
-
- if (daccess & FILE_MAXIMAL_ACCESS_LE) {
- if (!file_present) {
- daccess = cpu_to_le32(GENERIC_ALL_FLAGS);
- } else {
- rc = ksmbd_vfs_query_maximal_access(user_ns,
- path.dentry,
- &daccess);
- if (rc)
- goto err_out;
- already_permitted = true;
- }
- maximal_access = daccess;
- }
-
- open_flags = smb2_create_open_flags(file_present, daccess,
- req->CreateDisposition,
- &may_flags);
-
- if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
- if (open_flags & O_CREAT) {
- ksmbd_debug(SMB,
- "User does not have write permission\n");
- rc = -EACCES;
- goto err_out;
- }
- }
-
- /*create file if not present */
- if (!file_present) {
- rc = smb2_creat(work, &path, name, open_flags, posix_mode,
- req->CreateOptions & FILE_DIRECTORY_FILE_LE);
- if (rc) {
- if (rc == -ENOENT) {
- rc = -EIO;
- rsp->hdr.Status = STATUS_OBJECT_PATH_NOT_FOUND;
- }
- goto err_out;
- }
-
- created = true;
- user_ns = mnt_user_ns(path.mnt);
- if (ea_buf) {
- if (le32_to_cpu(ea_buf->ccontext.DataLength) <
- sizeof(struct smb2_ea_info)) {
- rc = -EINVAL;
- goto err_out;
- }
-
- rc = smb2_set_ea(&ea_buf->ea,
- le32_to_cpu(ea_buf->ccontext.DataLength),
- &path);
- if (rc == -EOPNOTSUPP)
- rc = 0;
- else if (rc)
- goto err_out;
- }
- } else if (!already_permitted) {
- /* FILE_READ_ATTRIBUTE is allowed without inode_permission,
- * because execute(search) permission on a parent directory,
- * is already granted.
- */
- if (daccess & ~(FILE_READ_ATTRIBUTES_LE | FILE_READ_CONTROL_LE)) {
- rc = inode_permission(user_ns,
- d_inode(path.dentry),
- may_flags);
- if (rc)
- goto err_out;
-
- if ((daccess & FILE_DELETE_LE) ||
- (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
- rc = ksmbd_vfs_may_delete(user_ns,
- path.dentry);
- if (rc)
- goto err_out;
- }
- }
- }
-
- rc = ksmbd_query_inode_status(d_inode(path.dentry->d_parent));
- if (rc == KSMBD_INODE_STATUS_PENDING_DELETE) {
- rc = -EBUSY;
- goto err_out;
- }
-
- rc = 0;
- filp = dentry_open(&path, open_flags, current_cred());
- if (IS_ERR(filp)) {
- rc = PTR_ERR(filp);
- pr_err("dentry open for dir failed, rc %d\n", rc);
- goto err_out;
- }
-
- if (file_present) {
- if (!(open_flags & O_TRUNC))
- file_info = FILE_OPENED;
- else
- file_info = FILE_OVERWRITTEN;
-
- if ((req->CreateDisposition & FILE_CREATE_MASK_LE) ==
- FILE_SUPERSEDE_LE)
- file_info = FILE_SUPERSEDED;
- } else if (open_flags & O_CREAT) {
- file_info = FILE_CREATED;
- }
-
- ksmbd_vfs_set_fadvise(filp, req->CreateOptions);
-
- /* Obtain Volatile-ID */
- fp = ksmbd_open_fd(work, filp);
- if (IS_ERR(fp)) {
- fput(filp);
- rc = PTR_ERR(fp);
- fp = NULL;
- goto err_out;
- }
-
- /* Get Persistent-ID */
- ksmbd_open_durable_fd(fp);
- if (!has_file_id(fp->persistent_id)) {
- rc = -ENOMEM;
- goto err_out;
- }
-
- fp->cdoption = req->CreateDisposition;
- fp->daccess = daccess;
- fp->saccess = req->ShareAccess;
- fp->coption = req->CreateOptions;
-
- /* Set default windows and posix acls if creating new file */
- if (created) {
- int posix_acl_rc;
- struct inode *inode = d_inode(path.dentry);
-
- posix_acl_rc = ksmbd_vfs_inherit_posix_acl(user_ns,
- inode,
- d_inode(path.dentry->d_parent));
- if (posix_acl_rc)
- ksmbd_debug(SMB, "inherit posix acl failed : %d\n", posix_acl_rc);
-
- if (test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_ACL_XATTR)) {
- rc = smb_inherit_dacl(conn, &path, sess->user->uid,
- sess->user->gid);
- }
-
- if (rc) {
- rc = smb2_create_sd_buffer(work, req, &path);
- if (rc) {
- if (posix_acl_rc)
- ksmbd_vfs_set_init_posix_acl(user_ns,
- inode);
-
- if (test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_ACL_XATTR)) {
- struct smb_fattr fattr;
- struct smb_ntsd *pntsd;
- int pntsd_size, ace_num = 0;
-
- ksmbd_acls_fattr(&fattr, user_ns, inode);
- if (fattr.cf_acls)
- ace_num = fattr.cf_acls->a_count;
- if (fattr.cf_dacls)
- ace_num += fattr.cf_dacls->a_count;
-
- pntsd = kmalloc(sizeof(struct smb_ntsd) +
- sizeof(struct smb_sid) * 3 +
- sizeof(struct smb_acl) +
- sizeof(struct smb_ace) * ace_num * 2,
- GFP_KERNEL);
- if (!pntsd) {
- posix_acl_release(fattr.cf_acls);
- posix_acl_release(fattr.cf_dacls);
- goto err_out;
- }
-
- rc = build_sec_desc(user_ns,
- pntsd, NULL, 0,
- OWNER_SECINFO |
- GROUP_SECINFO |
- DACL_SECINFO,
- &pntsd_size, &fattr);
- posix_acl_release(fattr.cf_acls);
- posix_acl_release(fattr.cf_dacls);
- if (rc) {
- kfree(pntsd);
- goto err_out;
- }
-
- rc = ksmbd_vfs_set_sd_xattr(conn,
- user_ns,
- path.dentry,
- pntsd,
- pntsd_size);
- kfree(pntsd);
- if (rc)
- pr_err("failed to store ntacl in xattr : %d\n",
- rc);
- }
- }
- }
- rc = 0;
- }
-
- if (stream_name) {
- rc = smb2_set_stream_name_xattr(&path,
- fp,
- stream_name,
- s_type);
- if (rc)
- goto err_out;
- file_info = FILE_CREATED;
- }
-
- fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE |
- FILE_WRITE_ATTRIBUTES_LE | FILE_SYNCHRONIZE_LE));
- if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC &&
- !fp->attrib_only && !stream_name) {
- smb_break_all_oplock(work, fp);
- need_truncate = 1;
- }
-
- /* fp should be searchable through ksmbd_inode.m_fp_list
- * after daccess, saccess, attrib_only, and stream are
- * initialized.
- */
- write_lock(&fp->f_ci->m_lock);
- list_add(&fp->node, &fp->f_ci->m_fp_list);
- write_unlock(&fp->f_ci->m_lock);
-
- /* Check delete pending among previous fp before oplock break */
- if (ksmbd_inode_pending_delete(fp)) {
- rc = -EBUSY;
- goto err_out;
- }
-
- share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
- if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
- (req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
- !(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) {
- if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) {
- rc = share_ret;
- goto err_out;
- }
- } else {
- if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
- req_op_level = smb2_map_lease_to_oplock(lc->req_state);
- ksmbd_debug(SMB,
- "lease req for(%s) req oplock state 0x%x, lease state 0x%x\n",
- name, req_op_level, lc->req_state);
- rc = find_same_lease_key(sess, fp->f_ci, lc);
- if (rc)
- goto err_out;
- } else if (open_flags == O_RDONLY &&
- (req_op_level == SMB2_OPLOCK_LEVEL_BATCH ||
- req_op_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE))
- req_op_level = SMB2_OPLOCK_LEVEL_II;
-
- rc = smb_grant_oplock(work, req_op_level,
- fp->persistent_id, fp,
- le32_to_cpu(req->hdr.Id.SyncId.TreeId),
- lc, share_ret);
- if (rc < 0)
- goto err_out;
- }
-
- if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)
- ksmbd_fd_set_delete_on_close(fp, file_info);
-
- if (need_truncate) {
- rc = smb2_create_truncate(&path);
- if (rc)
- goto err_out;
- }
-
- if (req->CreateContextsOffset) {
- struct create_alloc_size_req *az_req;
-
- az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req,
- SMB2_CREATE_ALLOCATION_SIZE, 4);
- if (IS_ERR(az_req)) {
- rc = PTR_ERR(az_req);
- goto err_out;
- } else if (az_req) {
- loff_t alloc_size;
- int err;
-
- if (le16_to_cpu(az_req->ccontext.DataOffset) +
- le32_to_cpu(az_req->ccontext.DataLength) <
- sizeof(struct create_alloc_size_req)) {
- rc = -EINVAL;
- goto err_out;
- }
- alloc_size = le64_to_cpu(az_req->AllocationSize);
- ksmbd_debug(SMB,
- "request smb2 create allocate size : %llu\n",
- alloc_size);
- smb_break_all_levII_oplock(work, fp, 1);
- err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
- alloc_size);
- if (err < 0)
- ksmbd_debug(SMB,
- "vfs_fallocate is failed : %d\n",
- err);
- }
-
- context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4);
- if (IS_ERR(context)) {
- rc = PTR_ERR(context);
- goto err_out;
- } else if (context) {
- ksmbd_debug(SMB, "get query on disk id context\n");
- query_disk_id = 1;
- }
- }
-
- rc = ksmbd_vfs_getattr(&path, &stat);
- if (rc)
- goto err_out;
-
- if (stat.result_mask & STATX_BTIME)
- fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
- else
- fp->create_time = ksmbd_UnixTimeToNT(stat.ctime);
- if (req->FileAttributes || fp->f_ci->m_fattr == 0)
- fp->f_ci->m_fattr =
- cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes)));
-
- if (!created)
- smb2_update_xattrs(tcon, &path, fp);
- else
- smb2_new_xattrs(tcon, &path, fp);
-
- memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
-
- rsp->StructureSize = cpu_to_le16(89);
- rcu_read_lock();
- opinfo = rcu_dereference(fp->f_opinfo);
- rsp->OplockLevel = opinfo != NULL ? opinfo->level : 0;
- rcu_read_unlock();
- rsp->Flags = 0;
- rsp->CreateAction = cpu_to_le32(file_info);
- rsp->CreationTime = cpu_to_le64(fp->create_time);
- time = ksmbd_UnixTimeToNT(stat.atime);
- rsp->LastAccessTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(stat.mtime);
- rsp->LastWriteTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(stat.ctime);
- rsp->ChangeTime = cpu_to_le64(time);
- rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 :
- cpu_to_le64(stat.blocks << 9);
- rsp->EndofFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
- rsp->FileAttributes = fp->f_ci->m_fattr;
-
- rsp->Reserved2 = 0;
-
- rsp->PersistentFileId = fp->persistent_id;
- rsp->VolatileFileId = fp->volatile_id;
-
- rsp->CreateContextsOffset = 0;
- rsp->CreateContextsLength = 0;
- inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
-
- /* If lease is request send lease context response */
- if (opinfo && opinfo->is_lease) {
- struct create_context *lease_ccontext;
-
- ksmbd_debug(SMB, "lease granted on(%s) lease state 0x%x\n",
- name, opinfo->o_lease->state);
- rsp->OplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
-
- lease_ccontext = (struct create_context *)rsp->Buffer;
- contxt_cnt++;
- create_lease_buf(rsp->Buffer, opinfo->o_lease);
- le32_add_cpu(&rsp->CreateContextsLength,
- conn->vals->create_lease_size);
- inc_rfc1001_len(work->response_buf,
- conn->vals->create_lease_size);
- next_ptr = &lease_ccontext->Next;
- next_off = conn->vals->create_lease_size;
- }
-
- if (maximal_access_ctxt) {
- struct create_context *mxac_ccontext;
-
- if (maximal_access == 0)
- ksmbd_vfs_query_maximal_access(user_ns,
- path.dentry,
- &maximal_access);
- mxac_ccontext = (struct create_context *)(rsp->Buffer +
- le32_to_cpu(rsp->CreateContextsLength));
- contxt_cnt++;
- create_mxac_rsp_buf(rsp->Buffer +
- le32_to_cpu(rsp->CreateContextsLength),
- le32_to_cpu(maximal_access));
- le32_add_cpu(&rsp->CreateContextsLength,
- conn->vals->create_mxac_size);
- inc_rfc1001_len(work->response_buf,
- conn->vals->create_mxac_size);
- if (next_ptr)
- *next_ptr = cpu_to_le32(next_off);
- next_ptr = &mxac_ccontext->Next;
- next_off = conn->vals->create_mxac_size;
- }
-
- if (query_disk_id) {
- struct create_context *disk_id_ccontext;
-
- disk_id_ccontext = (struct create_context *)(rsp->Buffer +
- le32_to_cpu(rsp->CreateContextsLength));
- contxt_cnt++;
- create_disk_id_rsp_buf(rsp->Buffer +
- le32_to_cpu(rsp->CreateContextsLength),
- stat.ino, tcon->id);
- le32_add_cpu(&rsp->CreateContextsLength,
- conn->vals->create_disk_id_size);
- inc_rfc1001_len(work->response_buf,
- conn->vals->create_disk_id_size);
- if (next_ptr)
- *next_ptr = cpu_to_le32(next_off);
- next_ptr = &disk_id_ccontext->Next;
- next_off = conn->vals->create_disk_id_size;
- }
-
- if (posix_ctxt) {
- contxt_cnt++;
- create_posix_rsp_buf(rsp->Buffer +
- le32_to_cpu(rsp->CreateContextsLength),
- fp);
- le32_add_cpu(&rsp->CreateContextsLength,
- conn->vals->create_posix_size);
- inc_rfc1001_len(work->response_buf,
- conn->vals->create_posix_size);
- if (next_ptr)
- *next_ptr = cpu_to_le32(next_off);
- }
-
- if (contxt_cnt > 0) {
- rsp->CreateContextsOffset =
- cpu_to_le32(offsetof(struct smb2_create_rsp, Buffer));
- }
-
-err_out:
- if (file_present || created)
- path_put(&path);
- ksmbd_revert_fsids(work);
-err_out1:
- if (rc) {
- if (rc == -EINVAL)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- else if (rc == -EOPNOTSUPP)
- rsp->hdr.Status = STATUS_NOT_SUPPORTED;
- else if (rc == -EACCES || rc == -ESTALE || rc == -EXDEV)
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- else if (rc == -ENOENT)
- rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID;
- else if (rc == -EPERM)
- rsp->hdr.Status = STATUS_SHARING_VIOLATION;
- else if (rc == -EBUSY)
- rsp->hdr.Status = STATUS_DELETE_PENDING;
- else if (rc == -EBADF)
- rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
- else if (rc == -ENOEXEC)
- rsp->hdr.Status = STATUS_DUPLICATE_OBJECTID;
- else if (rc == -ENXIO)
- rsp->hdr.Status = STATUS_NO_SUCH_DEVICE;
- else if (rc == -EEXIST)
- rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION;
- else if (rc == -EMFILE)
- rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
- if (!rsp->hdr.Status)
- rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
-
- if (fp)
- ksmbd_fd_put(work, fp);
- smb2_set_err_rsp(work);
- ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status);
- }
-
- kfree(name);
- kfree(lc);
-
- return 0;
-}
-
-static int readdir_info_level_struct_sz(int info_level)
-{
- switch (info_level) {
- case FILE_FULL_DIRECTORY_INFORMATION:
- return sizeof(struct file_full_directory_info);
- case FILE_BOTH_DIRECTORY_INFORMATION:
- return sizeof(struct file_both_directory_info);
- case FILE_DIRECTORY_INFORMATION:
- return sizeof(struct file_directory_info);
- case FILE_NAMES_INFORMATION:
- return sizeof(struct file_names_info);
- case FILEID_FULL_DIRECTORY_INFORMATION:
- return sizeof(struct file_id_full_dir_info);
- case FILEID_BOTH_DIRECTORY_INFORMATION:
- return sizeof(struct file_id_both_directory_info);
- case SMB_FIND_FILE_POSIX_INFO:
- return sizeof(struct smb2_posix_info);
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
-{
- switch (info_level) {
- case FILE_FULL_DIRECTORY_INFORMATION:
- {
- struct file_full_directory_info *ffdinfo;
-
- ffdinfo = (struct file_full_directory_info *)d_info->rptr;
- d_info->rptr += le32_to_cpu(ffdinfo->NextEntryOffset);
- d_info->name = ffdinfo->FileName;
- d_info->name_len = le32_to_cpu(ffdinfo->FileNameLength);
- return 0;
- }
- case FILE_BOTH_DIRECTORY_INFORMATION:
- {
- struct file_both_directory_info *fbdinfo;
-
- fbdinfo = (struct file_both_directory_info *)d_info->rptr;
- d_info->rptr += le32_to_cpu(fbdinfo->NextEntryOffset);
- d_info->name = fbdinfo->FileName;
- d_info->name_len = le32_to_cpu(fbdinfo->FileNameLength);
- return 0;
- }
- case FILE_DIRECTORY_INFORMATION:
- {
- struct file_directory_info *fdinfo;
-
- fdinfo = (struct file_directory_info *)d_info->rptr;
- d_info->rptr += le32_to_cpu(fdinfo->NextEntryOffset);
- d_info->name = fdinfo->FileName;
- d_info->name_len = le32_to_cpu(fdinfo->FileNameLength);
- return 0;
- }
- case FILE_NAMES_INFORMATION:
- {
- struct file_names_info *fninfo;
-
- fninfo = (struct file_names_info *)d_info->rptr;
- d_info->rptr += le32_to_cpu(fninfo->NextEntryOffset);
- d_info->name = fninfo->FileName;
- d_info->name_len = le32_to_cpu(fninfo->FileNameLength);
- return 0;
- }
- case FILEID_FULL_DIRECTORY_INFORMATION:
- {
- struct file_id_full_dir_info *dinfo;
-
- dinfo = (struct file_id_full_dir_info *)d_info->rptr;
- d_info->rptr += le32_to_cpu(dinfo->NextEntryOffset);
- d_info->name = dinfo->FileName;
- d_info->name_len = le32_to_cpu(dinfo->FileNameLength);
- return 0;
- }
- case FILEID_BOTH_DIRECTORY_INFORMATION:
- {
- struct file_id_both_directory_info *fibdinfo;
-
- fibdinfo = (struct file_id_both_directory_info *)d_info->rptr;
- d_info->rptr += le32_to_cpu(fibdinfo->NextEntryOffset);
- d_info->name = fibdinfo->FileName;
- d_info->name_len = le32_to_cpu(fibdinfo->FileNameLength);
- return 0;
- }
- case SMB_FIND_FILE_POSIX_INFO:
- {
- struct smb2_posix_info *posix_info;
-
- posix_info = (struct smb2_posix_info *)d_info->rptr;
- d_info->rptr += le32_to_cpu(posix_info->NextEntryOffset);
- d_info->name = posix_info->name;
- d_info->name_len = le32_to_cpu(posix_info->name_len);
- return 0;
- }
- default:
- return -EINVAL;
- }
-}
-
-/**
- * smb2_populate_readdir_entry() - encode directory entry in smb2 response
- * buffer
- * @conn: connection instance
- * @info_level: smb information level
- * @d_info: structure included variables for query dir
- * @ksmbd_kstat: ksmbd wrapper of dirent stat information
- *
- * if directory has many entries, find first can't read it fully.
- * find next might be called multiple times to read remaining dir entries
- *
- * Return: 0 on success, otherwise error
- */
-static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
- struct ksmbd_dir_info *d_info,
- struct ksmbd_kstat *ksmbd_kstat)
-{
- int next_entry_offset = 0;
- char *conv_name;
- int conv_len;
- void *kstat;
- int struct_sz, rc = 0;
-
- conv_name = ksmbd_convert_dir_info_name(d_info,
- conn->local_nls,
- &conv_len);
- if (!conv_name)
- return -ENOMEM;
-
- /* Somehow the name has only terminating NULL bytes */
- if (conv_len < 0) {
- rc = -EINVAL;
- goto free_conv_name;
- }
-
- struct_sz = readdir_info_level_struct_sz(info_level) - 1 + conv_len;
- next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT);
- d_info->last_entry_off_align = next_entry_offset - struct_sz;
-
- if (next_entry_offset > d_info->out_buf_len) {
- d_info->out_buf_len = 0;
- rc = -ENOSPC;
- goto free_conv_name;
- }
-
- kstat = d_info->wptr;
- if (info_level != FILE_NAMES_INFORMATION)
- kstat = ksmbd_vfs_init_kstat(&d_info->wptr, ksmbd_kstat);
-
- switch (info_level) {
- case FILE_FULL_DIRECTORY_INFORMATION:
- {
- struct file_full_directory_info *ffdinfo;
-
- ffdinfo = (struct file_full_directory_info *)kstat;
- ffdinfo->FileNameLength = cpu_to_le32(conv_len);
- ffdinfo->EaSize =
- smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
- if (ffdinfo->EaSize)
- ffdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
- if (d_info->hide_dot_file && d_info->name[0] == '.')
- ffdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
- memcpy(ffdinfo->FileName, conv_name, conv_len);
- ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILE_BOTH_DIRECTORY_INFORMATION:
- {
- struct file_both_directory_info *fbdinfo;
-
- fbdinfo = (struct file_both_directory_info *)kstat;
- fbdinfo->FileNameLength = cpu_to_le32(conv_len);
- fbdinfo->EaSize =
- smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
- if (fbdinfo->EaSize)
- fbdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
- fbdinfo->ShortNameLength = 0;
- fbdinfo->Reserved = 0;
- if (d_info->hide_dot_file && d_info->name[0] == '.')
- fbdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
- memcpy(fbdinfo->FileName, conv_name, conv_len);
- fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILE_DIRECTORY_INFORMATION:
- {
- struct file_directory_info *fdinfo;
-
- fdinfo = (struct file_directory_info *)kstat;
- fdinfo->FileNameLength = cpu_to_le32(conv_len);
- if (d_info->hide_dot_file && d_info->name[0] == '.')
- fdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
- memcpy(fdinfo->FileName, conv_name, conv_len);
- fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILE_NAMES_INFORMATION:
- {
- struct file_names_info *fninfo;
-
- fninfo = (struct file_names_info *)kstat;
- fninfo->FileNameLength = cpu_to_le32(conv_len);
- memcpy(fninfo->FileName, conv_name, conv_len);
- fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILEID_FULL_DIRECTORY_INFORMATION:
- {
- struct file_id_full_dir_info *dinfo;
-
- dinfo = (struct file_id_full_dir_info *)kstat;
- dinfo->FileNameLength = cpu_to_le32(conv_len);
- dinfo->EaSize =
- smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
- if (dinfo->EaSize)
- dinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
- dinfo->Reserved = 0;
- dinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
- if (d_info->hide_dot_file && d_info->name[0] == '.')
- dinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
- memcpy(dinfo->FileName, conv_name, conv_len);
- dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILEID_BOTH_DIRECTORY_INFORMATION:
- {
- struct file_id_both_directory_info *fibdinfo;
-
- fibdinfo = (struct file_id_both_directory_info *)kstat;
- fibdinfo->FileNameLength = cpu_to_le32(conv_len);
- fibdinfo->EaSize =
- smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
- if (fibdinfo->EaSize)
- fibdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
- fibdinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
- fibdinfo->ShortNameLength = 0;
- fibdinfo->Reserved = 0;
- fibdinfo->Reserved2 = cpu_to_le16(0);
- if (d_info->hide_dot_file && d_info->name[0] == '.')
- fibdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
- memcpy(fibdinfo->FileName, conv_name, conv_len);
- fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case SMB_FIND_FILE_POSIX_INFO:
- {
- struct smb2_posix_info *posix_info;
- u64 time;
-
- posix_info = (struct smb2_posix_info *)kstat;
- posix_info->Ignored = 0;
- posix_info->CreationTime = cpu_to_le64(ksmbd_kstat->create_time);
- time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
- posix_info->ChangeTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->atime);
- posix_info->LastAccessTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->mtime);
- posix_info->LastWriteTime = cpu_to_le64(time);
- posix_info->EndOfFile = cpu_to_le64(ksmbd_kstat->kstat->size);
- posix_info->AllocationSize = cpu_to_le64(ksmbd_kstat->kstat->blocks << 9);
- posix_info->DeviceId = cpu_to_le32(ksmbd_kstat->kstat->rdev);
- posix_info->HardLinks = cpu_to_le32(ksmbd_kstat->kstat->nlink);
- posix_info->Mode = cpu_to_le32(ksmbd_kstat->kstat->mode & 0777);
- posix_info->Inode = cpu_to_le64(ksmbd_kstat->kstat->ino);
- posix_info->DosAttributes =
- S_ISDIR(ksmbd_kstat->kstat->mode) ?
- FILE_ATTRIBUTE_DIRECTORY_LE : FILE_ATTRIBUTE_ARCHIVE_LE;
- if (d_info->hide_dot_file && d_info->name[0] == '.')
- posix_info->DosAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
- /*
- * SidBuffer(32) contain two sids(Domain sid(16), UNIX group sid(16)).
- * UNIX sid(16) = revision(1) + num_subauth(1) + authority(6) +
- * sub_auth(4 * 1(num_subauth)) + RID(4).
- */
- id_to_sid(from_kuid_munged(&init_user_ns, ksmbd_kstat->kstat->uid),
- SIDUNIX_USER, (struct smb_sid *)&posix_info->SidBuffer[0]);
- id_to_sid(from_kgid_munged(&init_user_ns, ksmbd_kstat->kstat->gid),
- SIDUNIX_GROUP, (struct smb_sid *)&posix_info->SidBuffer[16]);
- memcpy(posix_info->name, conv_name, conv_len);
- posix_info->name_len = cpu_to_le32(conv_len);
- posix_info->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
-
- } /* switch (info_level) */
-
- d_info->last_entry_offset = d_info->data_count;
- d_info->data_count += next_entry_offset;
- d_info->out_buf_len -= next_entry_offset;
- d_info->wptr += next_entry_offset;
-
- ksmbd_debug(SMB,
- "info_level : %d, buf_len :%d, next_offset : %d, data_count : %d\n",
- info_level, d_info->out_buf_len,
- next_entry_offset, d_info->data_count);
-
-free_conv_name:
- kfree(conv_name);
- return rc;
-}
-
-struct smb2_query_dir_private {
- struct ksmbd_work *work;
- char *search_pattern;
- struct ksmbd_file *dir_fp;
-
- struct ksmbd_dir_info *d_info;
- int info_level;
-};
-
-static void lock_dir(struct ksmbd_file *dir_fp)
-{
- struct dentry *dir = dir_fp->filp->f_path.dentry;
-
- inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
-}
-
-static void unlock_dir(struct ksmbd_file *dir_fp)
-{
- struct dentry *dir = dir_fp->filp->f_path.dentry;
-
- inode_unlock(d_inode(dir));
-}
-
-static int process_query_dir_entries(struct smb2_query_dir_private *priv)
-{
- struct user_namespace *user_ns = file_mnt_user_ns(priv->dir_fp->filp);
- struct kstat kstat;
- struct ksmbd_kstat ksmbd_kstat;
- int rc;
- int i;
-
- for (i = 0; i < priv->d_info->num_entry; i++) {
- struct dentry *dent;
-
- if (dentry_name(priv->d_info, priv->info_level))
- return -EINVAL;
-
- lock_dir(priv->dir_fp);
- dent = lookup_one(user_ns, priv->d_info->name,
- priv->dir_fp->filp->f_path.dentry,
- priv->d_info->name_len);
- unlock_dir(priv->dir_fp);
-
- if (IS_ERR(dent)) {
- ksmbd_debug(SMB, "Cannot lookup `%s' [%ld]\n",
- priv->d_info->name,
- PTR_ERR(dent));
- continue;
- }
- if (unlikely(d_is_negative(dent))) {
- dput(dent);
- ksmbd_debug(SMB, "Negative dentry `%s'\n",
- priv->d_info->name);
- continue;
- }
-
- ksmbd_kstat.kstat = &kstat;
- if (priv->info_level != FILE_NAMES_INFORMATION)
- ksmbd_vfs_fill_dentry_attrs(priv->work,
- user_ns,
- dent,
- &ksmbd_kstat);
-
- rc = smb2_populate_readdir_entry(priv->work->conn,
- priv->info_level,
- priv->d_info,
- &ksmbd_kstat);
- dput(dent);
- if (rc)
- return rc;
- }
- return 0;
-}
-
-static int reserve_populate_dentry(struct ksmbd_dir_info *d_info,
- int info_level)
-{
- int struct_sz;
- int conv_len;
- int next_entry_offset;
-
- struct_sz = readdir_info_level_struct_sz(info_level);
- if (struct_sz == -EOPNOTSUPP)
- return -EOPNOTSUPP;
-
- conv_len = (d_info->name_len + 1) * 2;
- next_entry_offset = ALIGN(struct_sz - 1 + conv_len,
- KSMBD_DIR_INFO_ALIGNMENT);
-
- if (next_entry_offset > d_info->out_buf_len) {
- d_info->out_buf_len = 0;
- return -ENOSPC;
- }
-
- switch (info_level) {
- case FILE_FULL_DIRECTORY_INFORMATION:
- {
- struct file_full_directory_info *ffdinfo;
-
- ffdinfo = (struct file_full_directory_info *)d_info->wptr;
- memcpy(ffdinfo->FileName, d_info->name, d_info->name_len);
- ffdinfo->FileName[d_info->name_len] = 0x00;
- ffdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
- ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILE_BOTH_DIRECTORY_INFORMATION:
- {
- struct file_both_directory_info *fbdinfo;
-
- fbdinfo = (struct file_both_directory_info *)d_info->wptr;
- memcpy(fbdinfo->FileName, d_info->name, d_info->name_len);
- fbdinfo->FileName[d_info->name_len] = 0x00;
- fbdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
- fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILE_DIRECTORY_INFORMATION:
- {
- struct file_directory_info *fdinfo;
-
- fdinfo = (struct file_directory_info *)d_info->wptr;
- memcpy(fdinfo->FileName, d_info->name, d_info->name_len);
- fdinfo->FileName[d_info->name_len] = 0x00;
- fdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
- fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILE_NAMES_INFORMATION:
- {
- struct file_names_info *fninfo;
-
- fninfo = (struct file_names_info *)d_info->wptr;
- memcpy(fninfo->FileName, d_info->name, d_info->name_len);
- fninfo->FileName[d_info->name_len] = 0x00;
- fninfo->FileNameLength = cpu_to_le32(d_info->name_len);
- fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILEID_FULL_DIRECTORY_INFORMATION:
- {
- struct file_id_full_dir_info *dinfo;
-
- dinfo = (struct file_id_full_dir_info *)d_info->wptr;
- memcpy(dinfo->FileName, d_info->name, d_info->name_len);
- dinfo->FileName[d_info->name_len] = 0x00;
- dinfo->FileNameLength = cpu_to_le32(d_info->name_len);
- dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case FILEID_BOTH_DIRECTORY_INFORMATION:
- {
- struct file_id_both_directory_info *fibdinfo;
-
- fibdinfo = (struct file_id_both_directory_info *)d_info->wptr;
- memcpy(fibdinfo->FileName, d_info->name, d_info->name_len);
- fibdinfo->FileName[d_info->name_len] = 0x00;
- fibdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
- fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
- break;
- }
- case SMB_FIND_FILE_POSIX_INFO:
- {
- struct smb2_posix_info *posix_info;
-
- posix_info = (struct smb2_posix_info *)d_info->wptr;
- memcpy(posix_info->name, d_info->name, d_info->name_len);
- posix_info->name[d_info->name_len] = 0x00;
- posix_info->name_len = cpu_to_le32(d_info->name_len);
- posix_info->NextEntryOffset =
- cpu_to_le32(next_entry_offset);
- break;
- }
- } /* switch (info_level) */
-
- d_info->num_entry++;
- d_info->out_buf_len -= next_entry_offset;
- d_info->wptr += next_entry_offset;
- return 0;
-}
-
-static bool __query_dir(struct dir_context *ctx, const char *name, int namlen,
- loff_t offset, u64 ino, unsigned int d_type)
-{
- struct ksmbd_readdir_data *buf;
- struct smb2_query_dir_private *priv;
- struct ksmbd_dir_info *d_info;
- int rc;
-
- buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
- priv = buf->private;
- d_info = priv->d_info;
-
- /* dot and dotdot entries are already reserved */
- if (!strcmp(".", name) || !strcmp("..", name))
- return true;
- if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
- return true;
- if (!match_pattern(name, namlen, priv->search_pattern))
- return true;
-
- d_info->name = name;
- d_info->name_len = namlen;
- rc = reserve_populate_dentry(d_info, priv->info_level);
- if (rc)
- return false;
- if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY)
- d_info->out_buf_len = 0;
- return true;
-}
-
-static int verify_info_level(int info_level)
-{
- switch (info_level) {
- case FILE_FULL_DIRECTORY_INFORMATION:
- case FILE_BOTH_DIRECTORY_INFORMATION:
- case FILE_DIRECTORY_INFORMATION:
- case FILE_NAMES_INFORMATION:
- case FILEID_FULL_DIRECTORY_INFORMATION:
- case FILEID_BOTH_DIRECTORY_INFORMATION:
- case SMB_FIND_FILE_POSIX_INFO:
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static int smb2_resp_buf_len(struct ksmbd_work *work, unsigned short hdr2_len)
-{
- int free_len;
-
- free_len = (int)(work->response_sz -
- (get_rfc1002_len(work->response_buf) + 4)) - hdr2_len;
- return free_len;
-}
-
-static int smb2_calc_max_out_buf_len(struct ksmbd_work *work,
- unsigned short hdr2_len,
- unsigned int out_buf_len)
-{
- int free_len;
-
- if (out_buf_len > work->conn->vals->max_trans_size)
- return -EINVAL;
-
- free_len = smb2_resp_buf_len(work, hdr2_len);
- if (free_len < 0)
- return -EINVAL;
-
- return min_t(int, out_buf_len, free_len);
-}
-
-int smb2_query_dir(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_query_directory_req *req;
- struct smb2_query_directory_rsp *rsp;
- struct ksmbd_share_config *share = work->tcon->share_conf;
- struct ksmbd_file *dir_fp = NULL;
- struct ksmbd_dir_info d_info;
- int rc = 0;
- char *srch_ptr = NULL;
- unsigned char srch_flag;
- int buffer_sz;
- struct smb2_query_dir_private query_dir_private = {NULL, };
-
- WORK_BUFFERS(work, req, rsp);
-
- if (ksmbd_override_fsids(work)) {
- rsp->hdr.Status = STATUS_NO_MEMORY;
- smb2_set_err_rsp(work);
- return -ENOMEM;
- }
-
- rc = verify_info_level(req->FileInformationClass);
- if (rc) {
- rc = -EFAULT;
- goto err_out2;
- }
-
- dir_fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
- if (!dir_fp) {
- rc = -EBADF;
- goto err_out2;
- }
-
- if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) ||
- inode_permission(file_mnt_user_ns(dir_fp->filp),
- file_inode(dir_fp->filp),
- MAY_READ | MAY_EXEC)) {
- pr_err("no right to enumerate directory (%pD)\n", dir_fp->filp);
- rc = -EACCES;
- goto err_out2;
- }
-
- if (!S_ISDIR(file_inode(dir_fp->filp)->i_mode)) {
- pr_err("can't do query dir for a file\n");
- rc = -EINVAL;
- goto err_out2;
- }
-
- srch_flag = req->Flags;
- srch_ptr = smb_strndup_from_utf16(req->Buffer,
- le16_to_cpu(req->FileNameLength), 1,
- conn->local_nls);
- if (IS_ERR(srch_ptr)) {
- ksmbd_debug(SMB, "Search Pattern not found\n");
- rc = -EINVAL;
- goto err_out2;
- } else {
- ksmbd_debug(SMB, "Search pattern is %s\n", srch_ptr);
- }
-
- if (srch_flag & SMB2_REOPEN || srch_flag & SMB2_RESTART_SCANS) {
- ksmbd_debug(SMB, "Restart directory scan\n");
- generic_file_llseek(dir_fp->filp, 0, SEEK_SET);
- }
-
- memset(&d_info, 0, sizeof(struct ksmbd_dir_info));
- d_info.wptr = (char *)rsp->Buffer;
- d_info.rptr = (char *)rsp->Buffer;
- d_info.out_buf_len =
- smb2_calc_max_out_buf_len(work, 8,
- le32_to_cpu(req->OutputBufferLength));
- if (d_info.out_buf_len < 0) {
- rc = -EINVAL;
- goto err_out;
- }
- d_info.flags = srch_flag;
-
- /*
- * reserve dot and dotdot entries in head of buffer
- * in first response
- */
- rc = ksmbd_populate_dot_dotdot_entries(work, req->FileInformationClass,
- dir_fp, &d_info, srch_ptr,
- smb2_populate_readdir_entry);
- if (rc == -ENOSPC)
- rc = 0;
- else if (rc)
- goto err_out;
-
- if (test_share_config_flag(share, KSMBD_SHARE_FLAG_HIDE_DOT_FILES))
- d_info.hide_dot_file = true;
-
- buffer_sz = d_info.out_buf_len;
- d_info.rptr = d_info.wptr;
- query_dir_private.work = work;
- query_dir_private.search_pattern = srch_ptr;
- query_dir_private.dir_fp = dir_fp;
- query_dir_private.d_info = &d_info;
- query_dir_private.info_level = req->FileInformationClass;
- dir_fp->readdir_data.private = &query_dir_private;
- set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
-
- rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
- /*
- * req->OutputBufferLength is too small to contain even one entry.
- * In this case, it immediately returns OutputBufferLength 0 to client.
- */
- if (!d_info.out_buf_len && !d_info.num_entry)
- goto no_buf_len;
- if (rc > 0 || rc == -ENOSPC)
- rc = 0;
- else if (rc)
- goto err_out;
-
- d_info.wptr = d_info.rptr;
- d_info.out_buf_len = buffer_sz;
- rc = process_query_dir_entries(&query_dir_private);
- if (rc)
- goto err_out;
-
- if (!d_info.data_count && d_info.out_buf_len >= 0) {
- if (srch_flag & SMB2_RETURN_SINGLE_ENTRY && !is_asterisk(srch_ptr)) {
- rsp->hdr.Status = STATUS_NO_SUCH_FILE;
- } else {
- dir_fp->dot_dotdot[0] = dir_fp->dot_dotdot[1] = 0;
- rsp->hdr.Status = STATUS_NO_MORE_FILES;
- }
- rsp->StructureSize = cpu_to_le16(9);
- rsp->OutputBufferOffset = cpu_to_le16(0);
- rsp->OutputBufferLength = cpu_to_le32(0);
- rsp->Buffer[0] = 0;
- inc_rfc1001_len(work->response_buf, 9);
- } else {
-no_buf_len:
- ((struct file_directory_info *)
- ((char *)rsp->Buffer + d_info.last_entry_offset))
- ->NextEntryOffset = 0;
- if (d_info.data_count >= d_info.last_entry_off_align)
- d_info.data_count -= d_info.last_entry_off_align;
-
- rsp->StructureSize = cpu_to_le16(9);
- rsp->OutputBufferOffset = cpu_to_le16(72);
- rsp->OutputBufferLength = cpu_to_le32(d_info.data_count);
- inc_rfc1001_len(work->response_buf, 8 + d_info.data_count);
- }
-
- kfree(srch_ptr);
- ksmbd_fd_put(work, dir_fp);
- ksmbd_revert_fsids(work);
- return 0;
-
-err_out:
- pr_err("error while processing smb2 query dir rc = %d\n", rc);
- kfree(srch_ptr);
-
-err_out2:
- if (rc == -EINVAL)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- else if (rc == -EACCES)
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- else if (rc == -ENOENT)
- rsp->hdr.Status = STATUS_NO_SUCH_FILE;
- else if (rc == -EBADF)
- rsp->hdr.Status = STATUS_FILE_CLOSED;
- else if (rc == -ENOMEM)
- rsp->hdr.Status = STATUS_NO_MEMORY;
- else if (rc == -EFAULT)
- rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
- else if (rc == -EIO)
- rsp->hdr.Status = STATUS_FILE_CORRUPT_ERROR;
- if (!rsp->hdr.Status)
- rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
-
- smb2_set_err_rsp(work);
- ksmbd_fd_put(work, dir_fp);
- ksmbd_revert_fsids(work);
- return 0;
-}
-
-/**
- * buffer_check_err() - helper function to check buffer errors
- * @reqOutputBufferLength: max buffer length expected in command response
- * @rsp: query info response buffer contains output buffer length
- * @rsp_org: base response buffer pointer in case of chained response
- * @infoclass_size: query info class response buffer size
- *
- * Return: 0 on success, otherwise error
- */
-static int buffer_check_err(int reqOutputBufferLength,
- struct smb2_query_info_rsp *rsp,
- void *rsp_org, int infoclass_size)
-{
- if (reqOutputBufferLength < le32_to_cpu(rsp->OutputBufferLength)) {
- if (reqOutputBufferLength < infoclass_size) {
- pr_err("Invalid Buffer Size Requested\n");
- rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
- *(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr));
- return -EINVAL;
- }
-
- ksmbd_debug(SMB, "Buffer Overflow\n");
- rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
- *(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr) +
- reqOutputBufferLength);
- rsp->OutputBufferLength = cpu_to_le32(reqOutputBufferLength);
- }
- return 0;
-}
-
-static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp,
- void *rsp_org)
-{
- struct smb2_file_standard_info *sinfo;
-
- sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
-
- sinfo->AllocationSize = cpu_to_le64(4096);
- sinfo->EndOfFile = cpu_to_le64(0);
- sinfo->NumberOfLinks = cpu_to_le32(1);
- sinfo->DeletePending = 1;
- sinfo->Directory = 0;
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_standard_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_standard_info));
-}
-
-static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num,
- void *rsp_org)
-{
- struct smb2_file_internal_info *file_info;
-
- file_info = (struct smb2_file_internal_info *)rsp->Buffer;
-
- /* any unique number */
- file_info->IndexNumber = cpu_to_le64(num | (1ULL << 63));
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_internal_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_internal_info));
-}
-
-static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
- struct smb2_query_info_req *req,
- struct smb2_query_info_rsp *rsp,
- void *rsp_org)
-{
- u64 id;
- int rc;
-
- /*
- * Windows can sometime send query file info request on
- * pipe without opening it, checking error condition here
- */
- id = req->VolatileFileId;
- if (!ksmbd_session_rpc_method(sess, id))
- return -ENOENT;
-
- ksmbd_debug(SMB, "FileInfoClass %u, FileId 0x%llx\n",
- req->FileInfoClass, req->VolatileFileId);
-
- switch (req->FileInfoClass) {
- case FILE_STANDARD_INFORMATION:
- get_standard_info_pipe(rsp, rsp_org);
- rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, rsp_org,
- FILE_STANDARD_INFORMATION_SIZE);
- break;
- case FILE_INTERNAL_INFORMATION:
- get_internal_info_pipe(rsp, id, rsp_org);
- rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, rsp_org,
- FILE_INTERNAL_INFORMATION_SIZE);
- break;
- default:
- ksmbd_debug(SMB, "smb2_info_file_pipe for %u not supported\n",
- req->FileInfoClass);
- rc = -EOPNOTSUPP;
- }
- return rc;
-}
-
-/**
- * smb2_get_ea() - handler for smb2 get extended attribute command
- * @work: smb work containing query info command buffer
- * @fp: ksmbd_file pointer
- * @req: get extended attribute request
- * @rsp: response buffer pointer
- * @rsp_org: base response buffer pointer in case of chained response
- *
- * Return: 0 on success, otherwise error
- */
-static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
- struct smb2_query_info_req *req,
- struct smb2_query_info_rsp *rsp, void *rsp_org)
-{
- struct smb2_ea_info *eainfo, *prev_eainfo;
- char *name, *ptr, *xattr_list = NULL, *buf;
- int rc, name_len, value_len, xattr_list_len, idx;
- ssize_t buf_free_len, alignment_bytes, next_offset, rsp_data_cnt = 0;
- struct smb2_ea_info_req *ea_req = NULL;
- const struct path *path;
- struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
-
- if (!(fp->daccess & FILE_READ_EA_LE)) {
- pr_err("Not permitted to read ext attr : 0x%x\n",
- fp->daccess);
- return -EACCES;
- }
-
- path = &fp->filp->f_path;
- /* single EA entry is requested with given user.* name */
- if (req->InputBufferLength) {
- if (le32_to_cpu(req->InputBufferLength) <
- sizeof(struct smb2_ea_info_req))
- return -EINVAL;
-
- ea_req = (struct smb2_ea_info_req *)req->Buffer;
- } else {
- /* need to send all EAs, if no specific EA is requested*/
- if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY)
- ksmbd_debug(SMB,
- "All EAs are requested but need to send single EA entry in rsp flags 0x%x\n",
- le32_to_cpu(req->Flags));
- }
-
- buf_free_len =
- smb2_calc_max_out_buf_len(work, 8,
- le32_to_cpu(req->OutputBufferLength));
- if (buf_free_len < 0)
- return -EINVAL;
-
- rc = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
- if (rc < 0) {
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
- goto out;
- } else if (!rc) { /* there is no EA in the file */
- ksmbd_debug(SMB, "no ea data in the file\n");
- goto done;
- }
- xattr_list_len = rc;
-
- ptr = (char *)rsp->Buffer;
- eainfo = (struct smb2_ea_info *)ptr;
- prev_eainfo = eainfo;
- idx = 0;
-
- while (idx < xattr_list_len) {
- name = xattr_list + idx;
- name_len = strlen(name);
-
- ksmbd_debug(SMB, "%s, len %d\n", name, name_len);
- idx += name_len + 1;
-
- /*
- * CIFS does not support EA other than user.* namespace,
- * still keep the framework generic, to list other attrs
- * in future.
- */
- if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
- continue;
-
- if (!strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
- STREAM_PREFIX_LEN))
- continue;
-
- if (req->InputBufferLength &&
- strncmp(&name[XATTR_USER_PREFIX_LEN], ea_req->name,
- ea_req->EaNameLength))
- continue;
-
- if (!strncmp(&name[XATTR_USER_PREFIX_LEN],
- DOS_ATTRIBUTE_PREFIX, DOS_ATTRIBUTE_PREFIX_LEN))
- continue;
-
- if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
- name_len -= XATTR_USER_PREFIX_LEN;
-
- ptr = (char *)(&eainfo->name + name_len + 1);
- buf_free_len -= (offsetof(struct smb2_ea_info, name) +
- name_len + 1);
- /* bailout if xattr can't fit in buf_free_len */
- value_len = ksmbd_vfs_getxattr(user_ns, path->dentry,
- name, &buf);
- if (value_len <= 0) {
- rc = -ENOENT;
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
- goto out;
- }
-
- buf_free_len -= value_len;
- if (buf_free_len < 0) {
- kfree(buf);
- break;
- }
-
- memcpy(ptr, buf, value_len);
- kfree(buf);
-
- ptr += value_len;
- eainfo->Flags = 0;
- eainfo->EaNameLength = name_len;
-
- if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
- memcpy(eainfo->name, &name[XATTR_USER_PREFIX_LEN],
- name_len);
- else
- memcpy(eainfo->name, name, name_len);
-
- eainfo->name[name_len] = '\0';
- eainfo->EaValueLength = cpu_to_le16(value_len);
- next_offset = offsetof(struct smb2_ea_info, name) +
- name_len + 1 + value_len;
-
- /* align next xattr entry at 4 byte bundary */
- alignment_bytes = ((next_offset + 3) & ~3) - next_offset;
- if (alignment_bytes) {
- memset(ptr, '\0', alignment_bytes);
- ptr += alignment_bytes;
- next_offset += alignment_bytes;
- buf_free_len -= alignment_bytes;
- }
- eainfo->NextEntryOffset = cpu_to_le32(next_offset);
- prev_eainfo = eainfo;
- eainfo = (struct smb2_ea_info *)ptr;
- rsp_data_cnt += next_offset;
-
- if (req->InputBufferLength) {
- ksmbd_debug(SMB, "single entry requested\n");
- break;
- }
- }
-
- /* no more ea entries */
- prev_eainfo->NextEntryOffset = 0;
-done:
- rc = 0;
- if (rsp_data_cnt == 0)
- rsp->hdr.Status = STATUS_NO_EAS_ON_FILE;
- rsp->OutputBufferLength = cpu_to_le32(rsp_data_cnt);
- inc_rfc1001_len(rsp_org, rsp_data_cnt);
-out:
- kvfree(xattr_list);
- return rc;
-}
-
-static void get_file_access_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb2_file_access_info *file_info;
-
- file_info = (struct smb2_file_access_info *)rsp->Buffer;
- file_info->AccessFlags = fp->daccess;
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_access_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_access_info));
-}
-
-static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb2_file_basic_info *basic_info;
- struct kstat stat;
- u64 time;
-
- if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
- pr_err("no right to read the attributes : 0x%x\n",
- fp->daccess);
- return -EACCES;
- }
-
- basic_info = (struct smb2_file_basic_info *)rsp->Buffer;
- generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
- &stat);
- basic_info->CreationTime = cpu_to_le64(fp->create_time);
- time = ksmbd_UnixTimeToNT(stat.atime);
- basic_info->LastAccessTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(stat.mtime);
- basic_info->LastWriteTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(stat.ctime);
- basic_info->ChangeTime = cpu_to_le64(time);
- basic_info->Attributes = fp->f_ci->m_fattr;
- basic_info->Pad1 = 0;
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_basic_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_basic_info));
- return 0;
-}
-
-static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb2_file_standard_info *sinfo;
- unsigned int delete_pending;
- struct inode *inode;
- struct kstat stat;
-
- inode = file_inode(fp->filp);
- generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
-
- sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
- delete_pending = ksmbd_inode_pending_delete(fp);
-
- sinfo->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
- sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
- sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
- sinfo->DeletePending = delete_pending;
- sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0;
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_standard_info));
- inc_rfc1001_len(rsp_org,
- sizeof(struct smb2_file_standard_info));
-}
-
-static void get_file_alignment_info(struct smb2_query_info_rsp *rsp,
- void *rsp_org)
-{
- struct smb2_file_alignment_info *file_info;
-
- file_info = (struct smb2_file_alignment_info *)rsp->Buffer;
- file_info->AlignmentRequirement = 0;
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_alignment_info));
- inc_rfc1001_len(rsp_org,
- sizeof(struct smb2_file_alignment_info));
-}
-
-static int get_file_all_info(struct ksmbd_work *work,
- struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp,
- void *rsp_org)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_file_all_info *file_info;
- unsigned int delete_pending;
- struct inode *inode;
- struct kstat stat;
- int conv_len;
- char *filename;
- u64 time;
-
- if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
- ksmbd_debug(SMB, "no right to read the attributes : 0x%x\n",
- fp->daccess);
- return -EACCES;
- }
-
- filename = convert_to_nt_pathname(work->tcon->share_conf, &fp->filp->f_path);
- if (IS_ERR(filename))
- return PTR_ERR(filename);
-
- inode = file_inode(fp->filp);
- generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
-
- ksmbd_debug(SMB, "filename = %s\n", filename);
- delete_pending = ksmbd_inode_pending_delete(fp);
- file_info = (struct smb2_file_all_info *)rsp->Buffer;
-
- file_info->CreationTime = cpu_to_le64(fp->create_time);
- time = ksmbd_UnixTimeToNT(stat.atime);
- file_info->LastAccessTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(stat.mtime);
- file_info->LastWriteTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(stat.ctime);
- file_info->ChangeTime = cpu_to_le64(time);
- file_info->Attributes = fp->f_ci->m_fattr;
- file_info->Pad1 = 0;
- file_info->AllocationSize =
- cpu_to_le64(inode->i_blocks << 9);
- file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
- file_info->NumberOfLinks =
- cpu_to_le32(get_nlink(&stat) - delete_pending);
- file_info->DeletePending = delete_pending;
- file_info->Directory = S_ISDIR(stat.mode) ? 1 : 0;
- file_info->Pad2 = 0;
- file_info->IndexNumber = cpu_to_le64(stat.ino);
- file_info->EASize = 0;
- file_info->AccessFlags = fp->daccess;
- file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
- file_info->Mode = fp->coption;
- file_info->AlignmentRequirement = 0;
- conv_len = smbConvertToUTF16((__le16 *)file_info->FileName, filename,
- PATH_MAX, conn->local_nls, 0);
- conv_len *= 2;
- file_info->FileNameLength = cpu_to_le32(conv_len);
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_all_info) + conv_len - 1);
- kfree(filename);
- inc_rfc1001_len(rsp_org, le32_to_cpu(rsp->OutputBufferLength));
- return 0;
-}
-
-static void get_file_alternate_info(struct ksmbd_work *work,
- struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp,
- void *rsp_org)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_file_alt_name_info *file_info;
- struct dentry *dentry = fp->filp->f_path.dentry;
- int conv_len;
-
- spin_lock(&dentry->d_lock);
- file_info = (struct smb2_file_alt_name_info *)rsp->Buffer;
- conv_len = ksmbd_extract_shortname(conn,
- dentry->d_name.name,
- file_info->FileName);
- spin_unlock(&dentry->d_lock);
- file_info->FileNameLength = cpu_to_le32(conv_len);
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len);
- inc_rfc1001_len(rsp_org, le32_to_cpu(rsp->OutputBufferLength));
-}
-
-static void get_file_stream_info(struct ksmbd_work *work,
- struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp,
- void *rsp_org)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_file_stream_info *file_info;
- char *stream_name, *xattr_list = NULL, *stream_buf;
- struct kstat stat;
- const struct path *path = &fp->filp->f_path;
- ssize_t xattr_list_len;
- int nbytes = 0, streamlen, stream_name_len, next, idx = 0;
- int buf_free_len;
- struct smb2_query_info_req *req = ksmbd_req_buf_next(work);
-
- generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
- &stat);
- file_info = (struct smb2_file_stream_info *)rsp->Buffer;
-
- buf_free_len =
- smb2_calc_max_out_buf_len(work, 8,
- le32_to_cpu(req->OutputBufferLength));
- if (buf_free_len < 0)
- goto out;
-
- xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
- if (xattr_list_len < 0) {
- goto out;
- } else if (!xattr_list_len) {
- ksmbd_debug(SMB, "empty xattr in the file\n");
- goto out;
- }
-
- while (idx < xattr_list_len) {
- stream_name = xattr_list + idx;
- streamlen = strlen(stream_name);
- idx += streamlen + 1;
-
- ksmbd_debug(SMB, "%s, len %d\n", stream_name, streamlen);
-
- if (strncmp(&stream_name[XATTR_USER_PREFIX_LEN],
- STREAM_PREFIX, STREAM_PREFIX_LEN))
- continue;
-
- stream_name_len = streamlen - (XATTR_USER_PREFIX_LEN +
- STREAM_PREFIX_LEN);
- streamlen = stream_name_len;
-
- /* plus : size */
- streamlen += 1;
- stream_buf = kmalloc(streamlen + 1, GFP_KERNEL);
- if (!stream_buf)
- break;
-
- streamlen = snprintf(stream_buf, streamlen + 1,
- ":%s", &stream_name[XATTR_NAME_STREAM_LEN]);
-
- next = sizeof(struct smb2_file_stream_info) + streamlen * 2;
- if (next > buf_free_len) {
- kfree(stream_buf);
- break;
- }
-
- file_info = (struct smb2_file_stream_info *)&rsp->Buffer[nbytes];
- streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName,
- stream_buf, streamlen,
- conn->local_nls, 0);
- streamlen *= 2;
- kfree(stream_buf);
- file_info->StreamNameLength = cpu_to_le32(streamlen);
- file_info->StreamSize = cpu_to_le64(stream_name_len);
- file_info->StreamAllocationSize = cpu_to_le64(stream_name_len);
-
- nbytes += next;
- buf_free_len -= next;
- file_info->NextEntryOffset = cpu_to_le32(next);
- }
-
-out:
- if (!S_ISDIR(stat.mode) &&
- buf_free_len >= sizeof(struct smb2_file_stream_info) + 7 * 2) {
- file_info = (struct smb2_file_stream_info *)
- &rsp->Buffer[nbytes];
- streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName,
- "::$DATA", 7, conn->local_nls, 0);
- streamlen *= 2;
- file_info->StreamNameLength = cpu_to_le32(streamlen);
- file_info->StreamSize = cpu_to_le64(stat.size);
- file_info->StreamAllocationSize = cpu_to_le64(stat.blocks << 9);
- nbytes += sizeof(struct smb2_file_stream_info) + streamlen;
- }
-
- /* last entry offset should be 0 */
- file_info->NextEntryOffset = 0;
- kvfree(xattr_list);
-
- rsp->OutputBufferLength = cpu_to_le32(nbytes);
- inc_rfc1001_len(rsp_org, nbytes);
-}
-
-static void get_file_internal_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb2_file_internal_info *file_info;
- struct kstat stat;
-
- generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
- &stat);
- file_info = (struct smb2_file_internal_info *)rsp->Buffer;
- file_info->IndexNumber = cpu_to_le64(stat.ino);
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_internal_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_internal_info));
-}
-
-static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb2_file_ntwrk_info *file_info;
- struct inode *inode;
- struct kstat stat;
- u64 time;
-
- if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
- pr_err("no right to read the attributes : 0x%x\n",
- fp->daccess);
- return -EACCES;
- }
-
- file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer;
-
- inode = file_inode(fp->filp);
- generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
-
- file_info->CreationTime = cpu_to_le64(fp->create_time);
- time = ksmbd_UnixTimeToNT(stat.atime);
- file_info->LastAccessTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(stat.mtime);
- file_info->LastWriteTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(stat.ctime);
- file_info->ChangeTime = cpu_to_le64(time);
- file_info->Attributes = fp->f_ci->m_fattr;
- file_info->AllocationSize =
- cpu_to_le64(inode->i_blocks << 9);
- file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
- file_info->Reserved = cpu_to_le32(0);
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_ntwrk_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_ntwrk_info));
- return 0;
-}
-
-static void get_file_ea_info(struct smb2_query_info_rsp *rsp, void *rsp_org)
-{
- struct smb2_file_ea_info *file_info;
-
- file_info = (struct smb2_file_ea_info *)rsp->Buffer;
- file_info->EASize = 0;
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_ea_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_ea_info));
-}
-
-static void get_file_position_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb2_file_pos_info *file_info;
-
- file_info = (struct smb2_file_pos_info *)rsp->Buffer;
- file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_pos_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_pos_info));
-}
-
-static void get_file_mode_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb2_file_mode_info *file_info;
-
- file_info = (struct smb2_file_mode_info *)rsp->Buffer;
- file_info->Mode = fp->coption & FILE_MODE_INFO_MASK;
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_mode_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_mode_info));
-}
-
-static void get_file_compression_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb2_file_comp_info *file_info;
- struct kstat stat;
-
- generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
- &stat);
-
- file_info = (struct smb2_file_comp_info *)rsp->Buffer;
- file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9);
- file_info->CompressionFormat = COMPRESSION_FORMAT_NONE;
- file_info->CompressionUnitShift = 0;
- file_info->ChunkShift = 0;
- file_info->ClusterShift = 0;
- memset(&file_info->Reserved[0], 0, 3);
-
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_comp_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_comp_info));
-}
-
-static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb2_file_attr_tag_info *file_info;
-
- if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
- pr_err("no right to read the attributes : 0x%x\n",
- fp->daccess);
- return -EACCES;
- }
-
- file_info = (struct smb2_file_attr_tag_info *)rsp->Buffer;
- file_info->FileAttributes = fp->f_ci->m_fattr;
- file_info->ReparseTag = 0;
- rsp->OutputBufferLength =
- cpu_to_le32(sizeof(struct smb2_file_attr_tag_info));
- inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_attr_tag_info));
- return 0;
-}
-
-static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
- struct ksmbd_file *fp, void *rsp_org)
-{
- struct smb311_posix_qinfo *file_info;
- struct inode *inode = file_inode(fp->filp);
- struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
- vfsuid_t vfsuid = i_uid_into_vfsuid(user_ns, inode);
- vfsgid_t vfsgid = i_gid_into_vfsgid(user_ns, inode);
- u64 time;
- int out_buf_len = sizeof(struct smb311_posix_qinfo) + 32;
-
- file_info = (struct smb311_posix_qinfo *)rsp->Buffer;
- file_info->CreationTime = cpu_to_le64(fp->create_time);
- time = ksmbd_UnixTimeToNT(inode->i_atime);
- file_info->LastAccessTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(inode->i_mtime);
- file_info->LastWriteTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(inode->i_ctime);
- file_info->ChangeTime = cpu_to_le64(time);
- file_info->DosAttributes = fp->f_ci->m_fattr;
- file_info->Inode = cpu_to_le64(inode->i_ino);
- file_info->EndOfFile = cpu_to_le64(inode->i_size);
- file_info->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
- file_info->HardLinks = cpu_to_le32(inode->i_nlink);
- file_info->Mode = cpu_to_le32(inode->i_mode & 0777);
- file_info->DeviceId = cpu_to_le32(inode->i_rdev);
-
- /*
- * Sids(32) contain two sids(Domain sid(16), UNIX group sid(16)).
- * UNIX sid(16) = revision(1) + num_subauth(1) + authority(6) +
- * sub_auth(4 * 1(num_subauth)) + RID(4).
- */
- id_to_sid(from_kuid_munged(&init_user_ns, vfsuid_into_kuid(vfsuid)),
- SIDUNIX_USER, (struct smb_sid *)&file_info->Sids[0]);
- id_to_sid(from_kgid_munged(&init_user_ns, vfsgid_into_kgid(vfsgid)),
- SIDUNIX_GROUP, (struct smb_sid *)&file_info->Sids[16]);
-
- rsp->OutputBufferLength = cpu_to_le32(out_buf_len);
- inc_rfc1001_len(rsp_org, out_buf_len);
- return out_buf_len;
-}
-
-static int smb2_get_info_file(struct ksmbd_work *work,
- struct smb2_query_info_req *req,
- struct smb2_query_info_rsp *rsp)
-{
- struct ksmbd_file *fp;
- int fileinfoclass = 0;
- int rc = 0;
- int file_infoclass_size;
- unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
-
- if (test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_PIPE)) {
- /* smb2 info file called for pipe */
- return smb2_get_info_file_pipe(work->sess, req, rsp,
- work->response_buf);
- }
-
- if (work->next_smb2_rcv_hdr_off) {
- if (!has_file_id(req->VolatileFileId)) {
- ksmbd_debug(SMB, "Compound request set FID = %llu\n",
- work->compound_fid);
- id = work->compound_fid;
- pid = work->compound_pfid;
- }
- }
-
- if (!has_file_id(id)) {
- id = req->VolatileFileId;
- pid = req->PersistentFileId;
- }
-
- fp = ksmbd_lookup_fd_slow(work, id, pid);
- if (!fp)
- return -ENOENT;
-
- fileinfoclass = req->FileInfoClass;
-
- switch (fileinfoclass) {
- case FILE_ACCESS_INFORMATION:
- get_file_access_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_ACCESS_INFORMATION_SIZE;
- break;
-
- case FILE_BASIC_INFORMATION:
- rc = get_file_basic_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_BASIC_INFORMATION_SIZE;
- break;
-
- case FILE_STANDARD_INFORMATION:
- get_file_standard_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_STANDARD_INFORMATION_SIZE;
- break;
-
- case FILE_ALIGNMENT_INFORMATION:
- get_file_alignment_info(rsp, work->response_buf);
- file_infoclass_size = FILE_ALIGNMENT_INFORMATION_SIZE;
- break;
-
- case FILE_ALL_INFORMATION:
- rc = get_file_all_info(work, rsp, fp, work->response_buf);
- file_infoclass_size = FILE_ALL_INFORMATION_SIZE;
- break;
-
- case FILE_ALTERNATE_NAME_INFORMATION:
- get_file_alternate_info(work, rsp, fp, work->response_buf);
- file_infoclass_size = FILE_ALTERNATE_NAME_INFORMATION_SIZE;
- break;
-
- case FILE_STREAM_INFORMATION:
- get_file_stream_info(work, rsp, fp, work->response_buf);
- file_infoclass_size = FILE_STREAM_INFORMATION_SIZE;
- break;
-
- case FILE_INTERNAL_INFORMATION:
- get_file_internal_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_INTERNAL_INFORMATION_SIZE;
- break;
-
- case FILE_NETWORK_OPEN_INFORMATION:
- rc = get_file_network_open_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_NETWORK_OPEN_INFORMATION_SIZE;
- break;
-
- case FILE_EA_INFORMATION:
- get_file_ea_info(rsp, work->response_buf);
- file_infoclass_size = FILE_EA_INFORMATION_SIZE;
- break;
-
- case FILE_FULL_EA_INFORMATION:
- rc = smb2_get_ea(work, fp, req, rsp, work->response_buf);
- file_infoclass_size = FILE_FULL_EA_INFORMATION_SIZE;
- break;
-
- case FILE_POSITION_INFORMATION:
- get_file_position_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_POSITION_INFORMATION_SIZE;
- break;
-
- case FILE_MODE_INFORMATION:
- get_file_mode_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_MODE_INFORMATION_SIZE;
- break;
-
- case FILE_COMPRESSION_INFORMATION:
- get_file_compression_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_COMPRESSION_INFORMATION_SIZE;
- break;
-
- case FILE_ATTRIBUTE_TAG_INFORMATION:
- rc = get_file_attribute_tag_info(rsp, fp, work->response_buf);
- file_infoclass_size = FILE_ATTRIBUTE_TAG_INFORMATION_SIZE;
- break;
- case SMB_FIND_FILE_POSIX_INFO:
- if (!work->tcon->posix_extensions) {
- pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
- rc = -EOPNOTSUPP;
- } else {
- file_infoclass_size = find_file_posix_info(rsp, fp,
- work->response_buf);
- }
- break;
- default:
- ksmbd_debug(SMB, "fileinfoclass %d not supported yet\n",
- fileinfoclass);
- rc = -EOPNOTSUPP;
- }
- if (!rc)
- rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, work->response_buf,
- file_infoclass_size);
- ksmbd_fd_put(work, fp);
- return rc;
-}
-
-static int smb2_get_info_filesystem(struct ksmbd_work *work,
- struct smb2_query_info_req *req,
- struct smb2_query_info_rsp *rsp)
-{
- struct ksmbd_session *sess = work->sess;
- struct ksmbd_conn *conn = work->conn;
- struct ksmbd_share_config *share = work->tcon->share_conf;
- int fsinfoclass = 0;
- struct kstatfs stfs;
- struct path path;
- int rc = 0, len;
- int fs_infoclass_size = 0;
-
- if (!share->path)
- return -EIO;
-
- rc = kern_path(share->path, LOOKUP_NO_SYMLINKS, &path);
- if (rc) {
- pr_err("cannot create vfs path\n");
- return -EIO;
- }
-
- rc = vfs_statfs(&path, &stfs);
- if (rc) {
- pr_err("cannot do stat of path %s\n", share->path);
- path_put(&path);
- return -EIO;
- }
-
- fsinfoclass = req->FileInfoClass;
-
- switch (fsinfoclass) {
- case FS_DEVICE_INFORMATION:
- {
- struct filesystem_device_info *info;
-
- info = (struct filesystem_device_info *)rsp->Buffer;
-
- info->DeviceType = cpu_to_le32(stfs.f_type);
- info->DeviceCharacteristics = cpu_to_le32(0x00000020);
- rsp->OutputBufferLength = cpu_to_le32(8);
- inc_rfc1001_len(work->response_buf, 8);
- fs_infoclass_size = FS_DEVICE_INFORMATION_SIZE;
- break;
- }
- case FS_ATTRIBUTE_INFORMATION:
- {
- struct filesystem_attribute_info *info;
- size_t sz;
-
- info = (struct filesystem_attribute_info *)rsp->Buffer;
- info->Attributes = cpu_to_le32(FILE_SUPPORTS_OBJECT_IDS |
- FILE_PERSISTENT_ACLS |
- FILE_UNICODE_ON_DISK |
- FILE_CASE_PRESERVED_NAMES |
- FILE_CASE_SENSITIVE_SEARCH |
- FILE_SUPPORTS_BLOCK_REFCOUNTING);
-
- info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
-
- if (test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_STREAMS))
- info->Attributes |= cpu_to_le32(FILE_NAMED_STREAMS);
-
- info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen);
- len = smbConvertToUTF16((__le16 *)info->FileSystemName,
- "NTFS", PATH_MAX, conn->local_nls, 0);
- len = len * 2;
- info->FileSystemNameLen = cpu_to_le32(len);
- sz = sizeof(struct filesystem_attribute_info) - 2 + len;
- rsp->OutputBufferLength = cpu_to_le32(sz);
- inc_rfc1001_len(work->response_buf, sz);
- fs_infoclass_size = FS_ATTRIBUTE_INFORMATION_SIZE;
- break;
- }
- case FS_VOLUME_INFORMATION:
- {
- struct filesystem_vol_info *info;
- size_t sz;
- unsigned int serial_crc = 0;
-
- info = (struct filesystem_vol_info *)(rsp->Buffer);
- info->VolumeCreationTime = 0;
- serial_crc = crc32_le(serial_crc, share->name,
- strlen(share->name));
- serial_crc = crc32_le(serial_crc, share->path,
- strlen(share->path));
- serial_crc = crc32_le(serial_crc, ksmbd_netbios_name(),
- strlen(ksmbd_netbios_name()));
- /* Taking dummy value of serial number*/
- info->SerialNumber = cpu_to_le32(serial_crc);
- len = smbConvertToUTF16((__le16 *)info->VolumeLabel,
- share->name, PATH_MAX,
- conn->local_nls, 0);
- len = len * 2;
- info->VolumeLabelSize = cpu_to_le32(len);
- info->Reserved = 0;
- sz = sizeof(struct filesystem_vol_info) - 2 + len;
- rsp->OutputBufferLength = cpu_to_le32(sz);
- inc_rfc1001_len(work->response_buf, sz);
- fs_infoclass_size = FS_VOLUME_INFORMATION_SIZE;
- break;
- }
- case FS_SIZE_INFORMATION:
- {
- struct filesystem_info *info;
-
- info = (struct filesystem_info *)(rsp->Buffer);
- info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks);
- info->FreeAllocationUnits = cpu_to_le64(stfs.f_bfree);
- info->SectorsPerAllocationUnit = cpu_to_le32(1);
- info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
- rsp->OutputBufferLength = cpu_to_le32(24);
- inc_rfc1001_len(work->response_buf, 24);
- fs_infoclass_size = FS_SIZE_INFORMATION_SIZE;
- break;
- }
- case FS_FULL_SIZE_INFORMATION:
- {
- struct smb2_fs_full_size_info *info;
-
- info = (struct smb2_fs_full_size_info *)(rsp->Buffer);
- info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks);
- info->CallerAvailableAllocationUnits =
- cpu_to_le64(stfs.f_bavail);
- info->ActualAvailableAllocationUnits =
- cpu_to_le64(stfs.f_bfree);
- info->SectorsPerAllocationUnit = cpu_to_le32(1);
- info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
- rsp->OutputBufferLength = cpu_to_le32(32);
- inc_rfc1001_len(work->response_buf, 32);
- fs_infoclass_size = FS_FULL_SIZE_INFORMATION_SIZE;
- break;
- }
- case FS_OBJECT_ID_INFORMATION:
- {
- struct object_id_info *info;
-
- info = (struct object_id_info *)(rsp->Buffer);
-
- if (!user_guest(sess->user))
- memcpy(info->objid, user_passkey(sess->user), 16);
- else
- memset(info->objid, 0, 16);
-
- info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC);
- info->extended_info.version = cpu_to_le32(1);
- info->extended_info.release = cpu_to_le32(1);
- info->extended_info.rel_date = 0;
- memcpy(info->extended_info.version_string, "1.1.0", strlen("1.1.0"));
- rsp->OutputBufferLength = cpu_to_le32(64);
- inc_rfc1001_len(work->response_buf, 64);
- fs_infoclass_size = FS_OBJECT_ID_INFORMATION_SIZE;
- break;
- }
- case FS_SECTOR_SIZE_INFORMATION:
- {
- struct smb3_fs_ss_info *info;
- unsigned int sector_size =
- min_t(unsigned int, path.mnt->mnt_sb->s_blocksize, 4096);
-
- info = (struct smb3_fs_ss_info *)(rsp->Buffer);
-
- info->LogicalBytesPerSector = cpu_to_le32(sector_size);
- info->PhysicalBytesPerSectorForAtomicity =
- cpu_to_le32(sector_size);
- info->PhysicalBytesPerSectorForPerf = cpu_to_le32(sector_size);
- info->FSEffPhysicalBytesPerSectorForAtomicity =
- cpu_to_le32(sector_size);
- info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE |
- SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
- info->ByteOffsetForSectorAlignment = 0;
- info->ByteOffsetForPartitionAlignment = 0;
- rsp->OutputBufferLength = cpu_to_le32(28);
- inc_rfc1001_len(work->response_buf, 28);
- fs_infoclass_size = FS_SECTOR_SIZE_INFORMATION_SIZE;
- break;
- }
- case FS_CONTROL_INFORMATION:
- {
- /*
- * TODO : The current implementation is based on
- * test result with win7(NTFS) server. It's need to
- * modify this to get valid Quota values
- * from Linux kernel
- */
- struct smb2_fs_control_info *info;
-
- info = (struct smb2_fs_control_info *)(rsp->Buffer);
- info->FreeSpaceStartFiltering = 0;
- info->FreeSpaceThreshold = 0;
- info->FreeSpaceStopFiltering = 0;
- info->DefaultQuotaThreshold = cpu_to_le64(SMB2_NO_FID);
- info->DefaultQuotaLimit = cpu_to_le64(SMB2_NO_FID);
- info->Padding = 0;
- rsp->OutputBufferLength = cpu_to_le32(48);
- inc_rfc1001_len(work->response_buf, 48);
- fs_infoclass_size = FS_CONTROL_INFORMATION_SIZE;
- break;
- }
- case FS_POSIX_INFORMATION:
- {
- struct filesystem_posix_info *info;
-
- if (!work->tcon->posix_extensions) {
- pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
- rc = -EOPNOTSUPP;
- } else {
- info = (struct filesystem_posix_info *)(rsp->Buffer);
- info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize);
- info->BlockSize = cpu_to_le32(stfs.f_bsize);
- info->TotalBlocks = cpu_to_le64(stfs.f_blocks);
- info->BlocksAvail = cpu_to_le64(stfs.f_bfree);
- info->UserBlocksAvail = cpu_to_le64(stfs.f_bavail);
- info->TotalFileNodes = cpu_to_le64(stfs.f_files);
- info->FreeFileNodes = cpu_to_le64(stfs.f_ffree);
- rsp->OutputBufferLength = cpu_to_le32(56);
- inc_rfc1001_len(work->response_buf, 56);
- fs_infoclass_size = FS_POSIX_INFORMATION_SIZE;
- }
- break;
- }
- default:
- path_put(&path);
- return -EOPNOTSUPP;
- }
- rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
- rsp, work->response_buf,
- fs_infoclass_size);
- path_put(&path);
- return rc;
-}
-
-static int smb2_get_info_sec(struct ksmbd_work *work,
- struct smb2_query_info_req *req,
- struct smb2_query_info_rsp *rsp)
-{
- struct ksmbd_file *fp;
- struct user_namespace *user_ns;
- struct smb_ntsd *pntsd = (struct smb_ntsd *)rsp->Buffer, *ppntsd = NULL;
- struct smb_fattr fattr = {{0}};
- struct inode *inode;
- __u32 secdesclen = 0;
- unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
- int addition_info = le32_to_cpu(req->AdditionalInformation);
- int rc = 0, ppntsd_size = 0;
-
- if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
- PROTECTED_DACL_SECINFO |
- UNPROTECTED_DACL_SECINFO)) {
- ksmbd_debug(SMB, "Unsupported addition info: 0x%x)\n",
- addition_info);
-
- pntsd->revision = cpu_to_le16(1);
- pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PROTECTED);
- pntsd->osidoffset = 0;
- pntsd->gsidoffset = 0;
- pntsd->sacloffset = 0;
- pntsd->dacloffset = 0;
-
- secdesclen = sizeof(struct smb_ntsd);
- rsp->OutputBufferLength = cpu_to_le32(secdesclen);
- inc_rfc1001_len(work->response_buf, secdesclen);
-
- return 0;
- }
-
- if (work->next_smb2_rcv_hdr_off) {
- if (!has_file_id(req->VolatileFileId)) {
- ksmbd_debug(SMB, "Compound request set FID = %llu\n",
- work->compound_fid);
- id = work->compound_fid;
- pid = work->compound_pfid;
- }
- }
-
- if (!has_file_id(id)) {
- id = req->VolatileFileId;
- pid = req->PersistentFileId;
- }
-
- fp = ksmbd_lookup_fd_slow(work, id, pid);
- if (!fp)
- return -ENOENT;
-
- user_ns = file_mnt_user_ns(fp->filp);
- inode = file_inode(fp->filp);
- ksmbd_acls_fattr(&fattr, user_ns, inode);
-
- if (test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_ACL_XATTR))
- ppntsd_size = ksmbd_vfs_get_sd_xattr(work->conn, user_ns,
- fp->filp->f_path.dentry,
- &ppntsd);
-
- /* Check if sd buffer size exceeds response buffer size */
- if (smb2_resp_buf_len(work, 8) > ppntsd_size)
- rc = build_sec_desc(user_ns, pntsd, ppntsd, ppntsd_size,
- addition_info, &secdesclen, &fattr);
- posix_acl_release(fattr.cf_acls);
- posix_acl_release(fattr.cf_dacls);
- kfree(ppntsd);
- ksmbd_fd_put(work, fp);
- if (rc)
- return rc;
-
- rsp->OutputBufferLength = cpu_to_le32(secdesclen);
- inc_rfc1001_len(work->response_buf, secdesclen);
- return 0;
-}
-
-/**
- * smb2_query_info() - handler for smb2 query info command
- * @work: smb work containing query info request buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_query_info(struct ksmbd_work *work)
-{
- struct smb2_query_info_req *req;
- struct smb2_query_info_rsp *rsp;
- int rc = 0;
-
- WORK_BUFFERS(work, req, rsp);
-
- ksmbd_debug(SMB, "GOT query info request\n");
-
- switch (req->InfoType) {
- case SMB2_O_INFO_FILE:
- ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n");
- rc = smb2_get_info_file(work, req, rsp);
- break;
- case SMB2_O_INFO_FILESYSTEM:
- ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILESYSTEM\n");
- rc = smb2_get_info_filesystem(work, req, rsp);
- break;
- case SMB2_O_INFO_SECURITY:
- ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n");
- rc = smb2_get_info_sec(work, req, rsp);
- break;
- default:
- ksmbd_debug(SMB, "InfoType %d not supported yet\n",
- req->InfoType);
- rc = -EOPNOTSUPP;
- }
-
- if (rc < 0) {
- if (rc == -EACCES)
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- else if (rc == -ENOENT)
- rsp->hdr.Status = STATUS_FILE_CLOSED;
- else if (rc == -EIO)
- rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
- else if (rc == -EOPNOTSUPP || rsp->hdr.Status == 0)
- rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
- smb2_set_err_rsp(work);
-
- ksmbd_debug(SMB, "error while processing smb2 query rc = %d\n",
- rc);
- return rc;
- }
- rsp->StructureSize = cpu_to_le16(9);
- rsp->OutputBufferOffset = cpu_to_le16(72);
- inc_rfc1001_len(work->response_buf, 8);
- return 0;
-}
-
-/**
- * smb2_close_pipe() - handler for closing IPC pipe
- * @work: smb work containing close request buffer
- *
- * Return: 0
- */
-static noinline int smb2_close_pipe(struct ksmbd_work *work)
-{
- u64 id;
- struct smb2_close_req *req = smb2_get_msg(work->request_buf);
- struct smb2_close_rsp *rsp = smb2_get_msg(work->response_buf);
-
- id = req->VolatileFileId;
- ksmbd_session_rpc_close(work->sess, id);
-
- rsp->StructureSize = cpu_to_le16(60);
- rsp->Flags = 0;
- rsp->Reserved = 0;
- rsp->CreationTime = 0;
- rsp->LastAccessTime = 0;
- rsp->LastWriteTime = 0;
- rsp->ChangeTime = 0;
- rsp->AllocationSize = 0;
- rsp->EndOfFile = 0;
- rsp->Attributes = 0;
- inc_rfc1001_len(work->response_buf, 60);
- return 0;
-}
-
-/**
- * smb2_close() - handler for smb2 close file command
- * @work: smb work containing close request buffer
- *
- * Return: 0
- */
-int smb2_close(struct ksmbd_work *work)
-{
- u64 volatile_id = KSMBD_NO_FID;
- u64 sess_id;
- struct smb2_close_req *req;
- struct smb2_close_rsp *rsp;
- struct ksmbd_conn *conn = work->conn;
- struct ksmbd_file *fp;
- struct inode *inode;
- u64 time;
- int err = 0;
-
- WORK_BUFFERS(work, req, rsp);
-
- if (test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_PIPE)) {
- ksmbd_debug(SMB, "IPC pipe close request\n");
- return smb2_close_pipe(work);
- }
-
- sess_id = le64_to_cpu(req->hdr.SessionId);
- if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)
- sess_id = work->compound_sid;
-
- work->compound_sid = 0;
- if (check_session_id(conn, sess_id)) {
- work->compound_sid = sess_id;
- } else {
- rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
- if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- err = -EBADF;
- goto out;
- }
-
- if (work->next_smb2_rcv_hdr_off &&
- !has_file_id(req->VolatileFileId)) {
- if (!has_file_id(work->compound_fid)) {
- /* file already closed, return FILE_CLOSED */
- ksmbd_debug(SMB, "file already closed\n");
- rsp->hdr.Status = STATUS_FILE_CLOSED;
- err = -EBADF;
- goto out;
- } else {
- ksmbd_debug(SMB,
- "Compound request set FID = %llu:%llu\n",
- work->compound_fid,
- work->compound_pfid);
- volatile_id = work->compound_fid;
-
- /* file closed, stored id is not valid anymore */
- work->compound_fid = KSMBD_NO_FID;
- work->compound_pfid = KSMBD_NO_FID;
- }
- } else {
- volatile_id = req->VolatileFileId;
- }
- ksmbd_debug(SMB, "volatile_id = %llu\n", volatile_id);
-
- rsp->StructureSize = cpu_to_le16(60);
- rsp->Reserved = 0;
-
- if (req->Flags == SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB) {
- fp = ksmbd_lookup_fd_fast(work, volatile_id);
- if (!fp) {
- err = -ENOENT;
- goto out;
- }
-
- inode = file_inode(fp->filp);
- rsp->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB;
- rsp->AllocationSize = S_ISDIR(inode->i_mode) ? 0 :
- cpu_to_le64(inode->i_blocks << 9);
- rsp->EndOfFile = cpu_to_le64(inode->i_size);
- rsp->Attributes = fp->f_ci->m_fattr;
- rsp->CreationTime = cpu_to_le64(fp->create_time);
- time = ksmbd_UnixTimeToNT(inode->i_atime);
- rsp->LastAccessTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(inode->i_mtime);
- rsp->LastWriteTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(inode->i_ctime);
- rsp->ChangeTime = cpu_to_le64(time);
- ksmbd_fd_put(work, fp);
- } else {
- rsp->Flags = 0;
- rsp->AllocationSize = 0;
- rsp->EndOfFile = 0;
- rsp->Attributes = 0;
- rsp->CreationTime = 0;
- rsp->LastAccessTime = 0;
- rsp->LastWriteTime = 0;
- rsp->ChangeTime = 0;
- }
-
- err = ksmbd_close_fd(work, volatile_id);
-out:
- if (err) {
- if (rsp->hdr.Status == 0)
- rsp->hdr.Status = STATUS_FILE_CLOSED;
- smb2_set_err_rsp(work);
- } else {
- inc_rfc1001_len(work->response_buf, 60);
- }
-
- return 0;
-}
-
-/**
- * smb2_echo() - handler for smb2 echo(ping) command
- * @work: smb work containing echo request buffer
- *
- * Return: 0
- */
-int smb2_echo(struct ksmbd_work *work)
-{
- struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf);
-
- rsp->StructureSize = cpu_to_le16(4);
- rsp->Reserved = 0;
- inc_rfc1001_len(work->response_buf, 4);
- return 0;
-}
-
-static int smb2_rename(struct ksmbd_work *work,
- struct ksmbd_file *fp,
- struct user_namespace *user_ns,
- struct smb2_file_rename_info *file_info,
- struct nls_table *local_nls)
-{
- struct ksmbd_share_config *share = fp->tcon->share_conf;
- char *new_name = NULL, *abs_oldname = NULL, *old_name = NULL;
- char *pathname = NULL;
- struct path path;
- bool file_present = true;
- int rc;
-
- ksmbd_debug(SMB, "setting FILE_RENAME_INFO\n");
- pathname = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!pathname)
- return -ENOMEM;
-
- abs_oldname = file_path(fp->filp, pathname, PATH_MAX);
- if (IS_ERR(abs_oldname)) {
- rc = -EINVAL;
- goto out;
- }
- old_name = strrchr(abs_oldname, '/');
- if (old_name && old_name[1] != '\0') {
- old_name++;
- } else {
- ksmbd_debug(SMB, "can't get last component in path %s\n",
- abs_oldname);
- rc = -ENOENT;
- goto out;
- }
-
- new_name = smb2_get_name(file_info->FileName,
- le32_to_cpu(file_info->FileNameLength),
- local_nls);
- if (IS_ERR(new_name)) {
- rc = PTR_ERR(new_name);
- goto out;
- }
-
- if (strchr(new_name, ':')) {
- int s_type;
- char *xattr_stream_name, *stream_name = NULL;
- size_t xattr_stream_size;
- int len;
-
- rc = parse_stream_name(new_name, &stream_name, &s_type);
- if (rc < 0)
- goto out;
-
- len = strlen(new_name);
- if (len > 0 && new_name[len - 1] != '/') {
- pr_err("not allow base filename in rename\n");
- rc = -ESHARE;
- goto out;
- }
-
- rc = ksmbd_vfs_xattr_stream_name(stream_name,
- &xattr_stream_name,
- &xattr_stream_size,
- s_type);
- if (rc)
- goto out;
-
- rc = ksmbd_vfs_setxattr(user_ns,
- fp->filp->f_path.dentry,
- xattr_stream_name,
- NULL, 0, 0);
- if (rc < 0) {
- pr_err("failed to store stream name in xattr: %d\n",
- rc);
- rc = -EINVAL;
- goto out;
- }
-
- goto out;
- }
-
- ksmbd_debug(SMB, "new name %s\n", new_name);
- rc = ksmbd_vfs_kern_path(work, new_name, LOOKUP_NO_SYMLINKS, &path, 1);
- if (rc) {
- if (rc != -ENOENT)
- goto out;
- file_present = false;
- } else {
- path_put(&path);
- }
-
- if (ksmbd_share_veto_filename(share, new_name)) {
- rc = -ENOENT;
- ksmbd_debug(SMB, "Can't rename vetoed file: %s\n", new_name);
- goto out;
- }
-
- if (file_info->ReplaceIfExists) {
- if (file_present) {
- rc = ksmbd_vfs_remove_file(work, new_name);
- if (rc) {
- if (rc != -ENOTEMPTY)
- rc = -EINVAL;
- ksmbd_debug(SMB, "cannot delete %s, rc %d\n",
- new_name, rc);
- goto out;
- }
- }
- } else {
- if (file_present &&
- strncmp(old_name, path.dentry->d_name.name, strlen(old_name))) {
- rc = -EEXIST;
- ksmbd_debug(SMB,
- "cannot rename already existing file\n");
- goto out;
- }
- }
-
- rc = ksmbd_vfs_fp_rename(work, fp, new_name);
-out:
- kfree(pathname);
- if (!IS_ERR(new_name))
- kfree(new_name);
- return rc;
-}
-
-static int smb2_create_link(struct ksmbd_work *work,
- struct ksmbd_share_config *share,
- struct smb2_file_link_info *file_info,
- unsigned int buf_len, struct file *filp,
- struct nls_table *local_nls)
-{
- char *link_name = NULL, *target_name = NULL, *pathname = NULL;
- struct path path;
- bool file_present = true;
- int rc;
-
- if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
- le32_to_cpu(file_info->FileNameLength))
- return -EINVAL;
-
- ksmbd_debug(SMB, "setting FILE_LINK_INFORMATION\n");
- pathname = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!pathname)
- return -ENOMEM;
-
- link_name = smb2_get_name(file_info->FileName,
- le32_to_cpu(file_info->FileNameLength),
- local_nls);
- if (IS_ERR(link_name) || S_ISDIR(file_inode(filp)->i_mode)) {
- rc = -EINVAL;
- goto out;
- }
-
- ksmbd_debug(SMB, "link name is %s\n", link_name);
- target_name = file_path(filp, pathname, PATH_MAX);
- if (IS_ERR(target_name)) {
- rc = -EINVAL;
- goto out;
- }
-
- ksmbd_debug(SMB, "target name is %s\n", target_name);
- rc = ksmbd_vfs_kern_path(work, link_name, LOOKUP_NO_SYMLINKS, &path, 0);
- if (rc) {
- if (rc != -ENOENT)
- goto out;
- file_present = false;
- } else {
- path_put(&path);
- }
-
- if (file_info->ReplaceIfExists) {
- if (file_present) {
- rc = ksmbd_vfs_remove_file(work, link_name);
- if (rc) {
- rc = -EINVAL;
- ksmbd_debug(SMB, "cannot delete %s\n",
- link_name);
- goto out;
- }
- }
- } else {
- if (file_present) {
- rc = -EEXIST;
- ksmbd_debug(SMB, "link already exists\n");
- goto out;
- }
- }
-
- rc = ksmbd_vfs_link(work, target_name, link_name);
- if (rc)
- rc = -EINVAL;
-out:
- if (!IS_ERR(link_name))
- kfree(link_name);
- kfree(pathname);
- return rc;
-}
-
-static int set_file_basic_info(struct ksmbd_file *fp,
- struct smb2_file_basic_info *file_info,
- struct ksmbd_share_config *share)
-{
- struct iattr attrs;
- struct file *filp;
- struct inode *inode;
- struct user_namespace *user_ns;
- int rc = 0;
-
- if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE))
- return -EACCES;
-
- attrs.ia_valid = 0;
- filp = fp->filp;
- inode = file_inode(filp);
- user_ns = file_mnt_user_ns(filp);
-
- if (file_info->CreationTime)
- fp->create_time = le64_to_cpu(file_info->CreationTime);
-
- if (file_info->LastAccessTime) {
- attrs.ia_atime = ksmbd_NTtimeToUnix(file_info->LastAccessTime);
- attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
- }
-
- attrs.ia_valid |= ATTR_CTIME;
- if (file_info->ChangeTime)
- attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
- else
- attrs.ia_ctime = inode->i_ctime;
-
- if (file_info->LastWriteTime) {
- attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime);
- attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
- }
-
- if (file_info->Attributes) {
- if (!S_ISDIR(inode->i_mode) &&
- file_info->Attributes & FILE_ATTRIBUTE_DIRECTORY_LE) {
- pr_err("can't change a file to a directory\n");
- return -EINVAL;
- }
-
- if (!(S_ISDIR(inode->i_mode) && file_info->Attributes == FILE_ATTRIBUTE_NORMAL_LE))
- fp->f_ci->m_fattr = file_info->Attributes |
- (fp->f_ci->m_fattr & FILE_ATTRIBUTE_DIRECTORY_LE);
- }
-
- if (test_share_config_flag(share, KSMBD_SHARE_FLAG_STORE_DOS_ATTRS) &&
- (file_info->CreationTime || file_info->Attributes)) {
- struct xattr_dos_attrib da = {0};
-
- da.version = 4;
- da.itime = fp->itime;
- da.create_time = fp->create_time;
- da.attr = le32_to_cpu(fp->f_ci->m_fattr);
- da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
- XATTR_DOSINFO_ITIME;
-
- rc = ksmbd_vfs_set_dos_attrib_xattr(user_ns,
- filp->f_path.dentry, &da);
- if (rc)
- ksmbd_debug(SMB,
- "failed to restore file attribute in EA\n");
- rc = 0;
- }
-
- if (attrs.ia_valid) {
- struct dentry *dentry = filp->f_path.dentry;
- struct inode *inode = d_inode(dentry);
-
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- return -EACCES;
-
- inode_lock(inode);
- inode->i_ctime = attrs.ia_ctime;
- attrs.ia_valid &= ~ATTR_CTIME;
- rc = notify_change(user_ns, dentry, &attrs, NULL);
- inode_unlock(inode);
- }
- return rc;
-}
-
-static int set_file_allocation_info(struct ksmbd_work *work,
- struct ksmbd_file *fp,
- struct smb2_file_alloc_info *file_alloc_info)
-{
- /*
- * TODO : It's working fine only when store dos attributes
- * is not yes. need to implement a logic which works
- * properly with any smb.conf option
- */
-
- loff_t alloc_blks;
- struct inode *inode;
- int rc;
-
- if (!(fp->daccess & FILE_WRITE_DATA_LE))
- return -EACCES;
-
- alloc_blks = (le64_to_cpu(file_alloc_info->AllocationSize) + 511) >> 9;
- inode = file_inode(fp->filp);
-
- if (alloc_blks > inode->i_blocks) {
- smb_break_all_levII_oplock(work, fp, 1);
- rc = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
- alloc_blks * 512);
- if (rc && rc != -EOPNOTSUPP) {
- pr_err("vfs_fallocate is failed : %d\n", rc);
- return rc;
- }
- } else if (alloc_blks < inode->i_blocks) {
- loff_t size;
-
- /*
- * Allocation size could be smaller than original one
- * which means allocated blocks in file should be
- * deallocated. use truncate to cut out it, but inode
- * size is also updated with truncate offset.
- * inode size is retained by backup inode size.
- */
- size = i_size_read(inode);
- rc = ksmbd_vfs_truncate(work, fp, alloc_blks * 512);
- if (rc) {
- pr_err("truncate failed!, err %d\n", rc);
- return rc;
- }
- if (size < alloc_blks * 512)
- i_size_write(inode, size);
- }
- return 0;
-}
-
-static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp,
- struct smb2_file_eof_info *file_eof_info)
-{
- loff_t newsize;
- struct inode *inode;
- int rc;
-
- if (!(fp->daccess & FILE_WRITE_DATA_LE))
- return -EACCES;
-
- newsize = le64_to_cpu(file_eof_info->EndOfFile);
- inode = file_inode(fp->filp);
-
- /*
- * If FILE_END_OF_FILE_INFORMATION of set_info_file is called
- * on FAT32 shared device, truncate execution time is too long
- * and network error could cause from windows client. because
- * truncate of some filesystem like FAT32 fill zero data in
- * truncated range.
- */
- if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) {
- ksmbd_debug(SMB, "truncated to newsize %lld\n", newsize);
- rc = ksmbd_vfs_truncate(work, fp, newsize);
- if (rc) {
- ksmbd_debug(SMB, "truncate failed!, err %d\n", rc);
- if (rc != -EAGAIN)
- rc = -EBADF;
- return rc;
- }
- }
- return 0;
-}
-
-static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
- struct smb2_file_rename_info *rename_info,
- unsigned int buf_len)
-{
- struct user_namespace *user_ns;
- struct ksmbd_file *parent_fp;
- struct dentry *parent;
- struct dentry *dentry = fp->filp->f_path.dentry;
- int ret;
-
- if (!(fp->daccess & FILE_DELETE_LE)) {
- pr_err("no right to delete : 0x%x\n", fp->daccess);
- return -EACCES;
- }
-
- if (buf_len < (u64)sizeof(struct smb2_file_rename_info) +
- le32_to_cpu(rename_info->FileNameLength))
- return -EINVAL;
-
- user_ns = file_mnt_user_ns(fp->filp);
- if (ksmbd_stream_fd(fp))
- goto next;
-
- parent = dget_parent(dentry);
- ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
- if (ret) {
- dput(parent);
- return ret;
- }
-
- parent_fp = ksmbd_lookup_fd_inode(d_inode(parent));
- inode_unlock(d_inode(parent));
- dput(parent);
-
- if (parent_fp) {
- if (parent_fp->daccess & FILE_DELETE_LE) {
- pr_err("parent dir is opened with delete access\n");
- ksmbd_fd_put(work, parent_fp);
- return -ESHARE;
- }
- ksmbd_fd_put(work, parent_fp);
- }
-next:
- return smb2_rename(work, fp, user_ns, rename_info,
- work->conn->local_nls);
-}
-
-static int set_file_disposition_info(struct ksmbd_file *fp,
- struct smb2_file_disposition_info *file_info)
-{
- struct inode *inode;
-
- if (!(fp->daccess & FILE_DELETE_LE)) {
- pr_err("no right to delete : 0x%x\n", fp->daccess);
- return -EACCES;
- }
-
- inode = file_inode(fp->filp);
- if (file_info->DeletePending) {
- if (S_ISDIR(inode->i_mode) &&
- ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY)
- return -EBUSY;
- ksmbd_set_inode_pending_delete(fp);
- } else {
- ksmbd_clear_inode_pending_delete(fp);
- }
- return 0;
-}
-
-static int set_file_position_info(struct ksmbd_file *fp,
- struct smb2_file_pos_info *file_info)
-{
- loff_t current_byte_offset;
- unsigned long sector_size;
- struct inode *inode;
-
- inode = file_inode(fp->filp);
- current_byte_offset = le64_to_cpu(file_info->CurrentByteOffset);
- sector_size = inode->i_sb->s_blocksize;
-
- if (current_byte_offset < 0 ||
- (fp->coption == FILE_NO_INTERMEDIATE_BUFFERING_LE &&
- current_byte_offset & (sector_size - 1))) {
- pr_err("CurrentByteOffset is not valid : %llu\n",
- current_byte_offset);
- return -EINVAL;
- }
-
- fp->filp->f_pos = current_byte_offset;
- return 0;
-}
-
-static int set_file_mode_info(struct ksmbd_file *fp,
- struct smb2_file_mode_info *file_info)
-{
- __le32 mode;
-
- mode = file_info->Mode;
-
- if ((mode & ~FILE_MODE_INFO_MASK)) {
- pr_err("Mode is not valid : 0x%x\n", le32_to_cpu(mode));
- return -EINVAL;
- }
-
- /*
- * TODO : need to implement consideration for
- * FILE_SYNCHRONOUS_IO_ALERT and FILE_SYNCHRONOUS_IO_NONALERT
- */
- ksmbd_vfs_set_fadvise(fp->filp, mode);
- fp->coption = mode;
- return 0;
-}
-
-/**
- * smb2_set_info_file() - handler for smb2 set info command
- * @work: smb work containing set info command buffer
- * @fp: ksmbd_file pointer
- * @req: request buffer pointer
- * @share: ksmbd_share_config pointer
- *
- * Return: 0 on success, otherwise error
- * TODO: need to implement an error handling for STATUS_INFO_LENGTH_MISMATCH
- */
-static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
- struct smb2_set_info_req *req,
- struct ksmbd_share_config *share)
-{
- unsigned int buf_len = le32_to_cpu(req->BufferLength);
-
- switch (req->FileInfoClass) {
- case FILE_BASIC_INFORMATION:
- {
- if (buf_len < sizeof(struct smb2_file_basic_info))
- return -EINVAL;
-
- return set_file_basic_info(fp, (struct smb2_file_basic_info *)req->Buffer, share);
- }
- case FILE_ALLOCATION_INFORMATION:
- {
- if (buf_len < sizeof(struct smb2_file_alloc_info))
- return -EINVAL;
-
- return set_file_allocation_info(work, fp,
- (struct smb2_file_alloc_info *)req->Buffer);
- }
- case FILE_END_OF_FILE_INFORMATION:
- {
- if (buf_len < sizeof(struct smb2_file_eof_info))
- return -EINVAL;
-
- return set_end_of_file_info(work, fp,
- (struct smb2_file_eof_info *)req->Buffer);
- }
- case FILE_RENAME_INFORMATION:
- {
- if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
- ksmbd_debug(SMB,
- "User does not have write permission\n");
- return -EACCES;
- }
-
- if (buf_len < sizeof(struct smb2_file_rename_info))
- return -EINVAL;
-
- return set_rename_info(work, fp,
- (struct smb2_file_rename_info *)req->Buffer,
- buf_len);
- }
- case FILE_LINK_INFORMATION:
- {
- if (buf_len < sizeof(struct smb2_file_link_info))
- return -EINVAL;
-
- return smb2_create_link(work, work->tcon->share_conf,
- (struct smb2_file_link_info *)req->Buffer,
- buf_len, fp->filp,
- work->conn->local_nls);
- }
- case FILE_DISPOSITION_INFORMATION:
- {
- if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
- ksmbd_debug(SMB,
- "User does not have write permission\n");
- return -EACCES;
- }
-
- if (buf_len < sizeof(struct smb2_file_disposition_info))
- return -EINVAL;
-
- return set_file_disposition_info(fp,
- (struct smb2_file_disposition_info *)req->Buffer);
- }
- case FILE_FULL_EA_INFORMATION:
- {
- if (!(fp->daccess & FILE_WRITE_EA_LE)) {
- pr_err("Not permitted to write ext attr: 0x%x\n",
- fp->daccess);
- return -EACCES;
- }
-
- if (buf_len < sizeof(struct smb2_ea_info))
- return -EINVAL;
-
- return smb2_set_ea((struct smb2_ea_info *)req->Buffer,
- buf_len, &fp->filp->f_path);
- }
- case FILE_POSITION_INFORMATION:
- {
- if (buf_len < sizeof(struct smb2_file_pos_info))
- return -EINVAL;
-
- return set_file_position_info(fp, (struct smb2_file_pos_info *)req->Buffer);
- }
- case FILE_MODE_INFORMATION:
- {
- if (buf_len < sizeof(struct smb2_file_mode_info))
- return -EINVAL;
-
- return set_file_mode_info(fp, (struct smb2_file_mode_info *)req->Buffer);
- }
- }
-
- pr_err("Unimplemented Fileinfoclass :%d\n", req->FileInfoClass);
- return -EOPNOTSUPP;
-}
-
-static int smb2_set_info_sec(struct ksmbd_file *fp, int addition_info,
- char *buffer, int buf_len)
-{
- struct smb_ntsd *pntsd = (struct smb_ntsd *)buffer;
-
- fp->saccess |= FILE_SHARE_DELETE_LE;
-
- return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd,
- buf_len, false);
-}
-
-/**
- * smb2_set_info() - handler for smb2 set info command handler
- * @work: smb work containing set info request buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_set_info(struct ksmbd_work *work)
-{
- struct smb2_set_info_req *req;
- struct smb2_set_info_rsp *rsp;
- struct ksmbd_file *fp;
- int rc = 0;
- unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
-
- ksmbd_debug(SMB, "Received set info request\n");
-
- if (work->next_smb2_rcv_hdr_off) {
- req = ksmbd_req_buf_next(work);
- rsp = ksmbd_resp_buf_next(work);
- if (!has_file_id(req->VolatileFileId)) {
- ksmbd_debug(SMB, "Compound request set FID = %llu\n",
- work->compound_fid);
- id = work->compound_fid;
- pid = work->compound_pfid;
- }
- } else {
- req = smb2_get_msg(work->request_buf);
- rsp = smb2_get_msg(work->response_buf);
- }
-
- if (!has_file_id(id)) {
- id = req->VolatileFileId;
- pid = req->PersistentFileId;
- }
-
- fp = ksmbd_lookup_fd_slow(work, id, pid);
- if (!fp) {
- ksmbd_debug(SMB, "Invalid id for close: %u\n", id);
- rc = -ENOENT;
- goto err_out;
- }
-
- switch (req->InfoType) {
- case SMB2_O_INFO_FILE:
- ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n");
- rc = smb2_set_info_file(work, fp, req, work->tcon->share_conf);
- break;
- case SMB2_O_INFO_SECURITY:
- ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n");
- if (ksmbd_override_fsids(work)) {
- rc = -ENOMEM;
- goto err_out;
- }
- rc = smb2_set_info_sec(fp,
- le32_to_cpu(req->AdditionalInformation),
- req->Buffer,
- le32_to_cpu(req->BufferLength));
- ksmbd_revert_fsids(work);
- break;
- default:
- rc = -EOPNOTSUPP;
- }
-
- if (rc < 0)
- goto err_out;
-
- rsp->StructureSize = cpu_to_le16(2);
- inc_rfc1001_len(work->response_buf, 2);
- ksmbd_fd_put(work, fp);
- return 0;
-
-err_out:
- if (rc == -EACCES || rc == -EPERM || rc == -EXDEV)
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- else if (rc == -EINVAL)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- else if (rc == -ESHARE)
- rsp->hdr.Status = STATUS_SHARING_VIOLATION;
- else if (rc == -ENOENT)
- rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID;
- else if (rc == -EBUSY || rc == -ENOTEMPTY)
- rsp->hdr.Status = STATUS_DIRECTORY_NOT_EMPTY;
- else if (rc == -EAGAIN)
- rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
- else if (rc == -EBADF || rc == -ESTALE)
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
- else if (rc == -EEXIST)
- rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION;
- else if (rsp->hdr.Status == 0 || rc == -EOPNOTSUPP)
- rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
- smb2_set_err_rsp(work);
- ksmbd_fd_put(work, fp);
- ksmbd_debug(SMB, "error while processing smb2 query rc = %d\n", rc);
- return rc;
-}
-
-/**
- * smb2_read_pipe() - handler for smb2 read from IPC pipe
- * @work: smb work containing read IPC pipe command buffer
- *
- * Return: 0 on success, otherwise error
- */
-static noinline int smb2_read_pipe(struct ksmbd_work *work)
-{
- int nbytes = 0, err;
- u64 id;
- struct ksmbd_rpc_command *rpc_resp;
- struct smb2_read_req *req = smb2_get_msg(work->request_buf);
- struct smb2_read_rsp *rsp = smb2_get_msg(work->response_buf);
-
- id = req->VolatileFileId;
-
- inc_rfc1001_len(work->response_buf, 16);
- rpc_resp = ksmbd_rpc_read(work->sess, id);
- if (rpc_resp) {
- if (rpc_resp->flags != KSMBD_RPC_OK) {
- err = -EINVAL;
- goto out;
- }
-
- work->aux_payload_buf =
- kvmalloc(rpc_resp->payload_sz, GFP_KERNEL | __GFP_ZERO);
- if (!work->aux_payload_buf) {
- err = -ENOMEM;
- goto out;
- }
-
- memcpy(work->aux_payload_buf, rpc_resp->payload,
- rpc_resp->payload_sz);
-
- nbytes = rpc_resp->payload_sz;
- work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
- work->aux_payload_sz = nbytes;
- kvfree(rpc_resp);
- }
-
- rsp->StructureSize = cpu_to_le16(17);
- rsp->DataOffset = 80;
- rsp->Reserved = 0;
- rsp->DataLength = cpu_to_le32(nbytes);
- rsp->DataRemaining = 0;
- rsp->Flags = 0;
- inc_rfc1001_len(work->response_buf, nbytes);
- return 0;
-
-out:
- rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
- smb2_set_err_rsp(work);
- kvfree(rpc_resp);
- return err;
-}
-
-static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
- struct smb2_buffer_desc_v1 *desc,
- __le32 Channel,
- __le16 ChannelInfoLength)
-{
- unsigned int i, ch_count;
-
- if (work->conn->dialect == SMB30_PROT_ID &&
- Channel != SMB2_CHANNEL_RDMA_V1)
- return -EINVAL;
-
- ch_count = le16_to_cpu(ChannelInfoLength) / sizeof(*desc);
- if (ksmbd_debug_types & KSMBD_DEBUG_RDMA) {
- for (i = 0; i < ch_count; i++) {
- pr_info("RDMA r/w request %#x: token %#x, length %#x\n",
- i,
- le32_to_cpu(desc[i].token),
- le32_to_cpu(desc[i].length));
- }
- }
- if (!ch_count)
- return -EINVAL;
-
- work->need_invalidate_rkey =
- (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
- if (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE)
- work->remote_key = le32_to_cpu(desc->token);
- return 0;
-}
-
-static ssize_t smb2_read_rdma_channel(struct ksmbd_work *work,
- struct smb2_read_req *req, void *data_buf,
- size_t length)
-{
- int err;
-
- err = ksmbd_conn_rdma_write(work->conn, data_buf, length,
- (struct smb2_buffer_desc_v1 *)
- ((char *)req + le16_to_cpu(req->ReadChannelInfoOffset)),
- le16_to_cpu(req->ReadChannelInfoLength));
- if (err)
- return err;
-
- return length;
-}
-
-/**
- * smb2_read() - handler for smb2 read from file
- * @work: smb work containing read command buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_read(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_read_req *req;
- struct smb2_read_rsp *rsp;
- struct ksmbd_file *fp = NULL;
- loff_t offset;
- size_t length, mincount;
- ssize_t nbytes = 0, remain_bytes = 0;
- int err = 0;
- bool is_rdma_channel = false;
- unsigned int max_read_size = conn->vals->max_read_size;
-
- WORK_BUFFERS(work, req, rsp);
-
- if (test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_PIPE)) {
- ksmbd_debug(SMB, "IPC pipe read request\n");
- return smb2_read_pipe(work);
- }
-
- if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
- req->Channel == SMB2_CHANNEL_RDMA_V1) {
- is_rdma_channel = true;
- max_read_size = get_smbd_max_read_write_size();
- }
-
- if (is_rdma_channel == true) {
- unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
-
- if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
- err = -EINVAL;
- goto out;
- }
- err = smb2_set_remote_key_for_rdma(work,
- (struct smb2_buffer_desc_v1 *)
- ((char *)req + ch_offset),
- req->Channel,
- req->ReadChannelInfoLength);
- if (err)
- goto out;
- }
-
- fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
- if (!fp) {
- err = -ENOENT;
- goto out;
- }
-
- if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_READ_ATTRIBUTES_LE))) {
- pr_err("Not permitted to read : 0x%x\n", fp->daccess);
- err = -EACCES;
- goto out;
- }
-
- offset = le64_to_cpu(req->Offset);
- length = le32_to_cpu(req->Length);
- mincount = le32_to_cpu(req->MinimumCount);
-
- if (length > max_read_size) {
- ksmbd_debug(SMB, "limiting read size to max size(%u)\n",
- max_read_size);
- err = -EINVAL;
- goto out;
- }
-
- ksmbd_debug(SMB, "filename %pD, offset %lld, len %zu\n",
- fp->filp, offset, length);
-
- work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
- if (!work->aux_payload_buf) {
- err = -ENOMEM;
- goto out;
- }
-
- nbytes = ksmbd_vfs_read(work, fp, length, &offset);
- if (nbytes < 0) {
- err = nbytes;
- goto out;
- }
-
- if ((nbytes == 0 && length != 0) || nbytes < mincount) {
- kvfree(work->aux_payload_buf);
- work->aux_payload_buf = NULL;
- rsp->hdr.Status = STATUS_END_OF_FILE;
- smb2_set_err_rsp(work);
- ksmbd_fd_put(work, fp);
- return 0;
- }
-
- ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
- nbytes, offset, mincount);
-
- if (is_rdma_channel == true) {
- /* write data to the client using rdma channel */
- remain_bytes = smb2_read_rdma_channel(work, req,
- work->aux_payload_buf,
- nbytes);
- kvfree(work->aux_payload_buf);
- work->aux_payload_buf = NULL;
-
- nbytes = 0;
- if (remain_bytes < 0) {
- err = (int)remain_bytes;
- goto out;
- }
- }
-
- rsp->StructureSize = cpu_to_le16(17);
- rsp->DataOffset = 80;
- rsp->Reserved = 0;
- rsp->DataLength = cpu_to_le32(nbytes);
- rsp->DataRemaining = cpu_to_le32(remain_bytes);
- rsp->Flags = 0;
- inc_rfc1001_len(work->response_buf, 16);
- work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
- work->aux_payload_sz = nbytes;
- inc_rfc1001_len(work->response_buf, nbytes);
- ksmbd_fd_put(work, fp);
- return 0;
-
-out:
- if (err) {
- if (err == -EISDIR)
- rsp->hdr.Status = STATUS_INVALID_DEVICE_REQUEST;
- else if (err == -EAGAIN)
- rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
- else if (err == -ENOENT)
- rsp->hdr.Status = STATUS_FILE_CLOSED;
- else if (err == -EACCES)
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- else if (err == -ESHARE)
- rsp->hdr.Status = STATUS_SHARING_VIOLATION;
- else if (err == -EINVAL)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- else
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
-
- smb2_set_err_rsp(work);
- }
- ksmbd_fd_put(work, fp);
- return err;
-}
-
-/**
- * smb2_write_pipe() - handler for smb2 write on IPC pipe
- * @work: smb work containing write IPC pipe command buffer
- *
- * Return: 0 on success, otherwise error
- */
-static noinline int smb2_write_pipe(struct ksmbd_work *work)
-{
- struct smb2_write_req *req = smb2_get_msg(work->request_buf);
- struct smb2_write_rsp *rsp = smb2_get_msg(work->response_buf);
- struct ksmbd_rpc_command *rpc_resp;
- u64 id = 0;
- int err = 0, ret = 0;
- char *data_buf;
- size_t length;
-
- length = le32_to_cpu(req->Length);
- id = req->VolatileFileId;
-
- if ((u64)le16_to_cpu(req->DataOffset) + length >
- get_rfc1002_len(work->request_buf)) {
- pr_err("invalid write data offset %u, smb_len %u\n",
- le16_to_cpu(req->DataOffset),
- get_rfc1002_len(work->request_buf));
- err = -EINVAL;
- goto out;
- }
-
- data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
- le16_to_cpu(req->DataOffset));
-
- rpc_resp = ksmbd_rpc_write(work->sess, id, data_buf, length);
- if (rpc_resp) {
- if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) {
- rsp->hdr.Status = STATUS_NOT_SUPPORTED;
- kvfree(rpc_resp);
- smb2_set_err_rsp(work);
- return -EOPNOTSUPP;
- }
- if (rpc_resp->flags != KSMBD_RPC_OK) {
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
- smb2_set_err_rsp(work);
- kvfree(rpc_resp);
- return ret;
- }
- kvfree(rpc_resp);
- }
-
- rsp->StructureSize = cpu_to_le16(17);
- rsp->DataOffset = 0;
- rsp->Reserved = 0;
- rsp->DataLength = cpu_to_le32(length);
- rsp->DataRemaining = 0;
- rsp->Reserved2 = 0;
- inc_rfc1001_len(work->response_buf, 16);
- return 0;
-out:
- if (err) {
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
- smb2_set_err_rsp(work);
- }
-
- return err;
-}
-
-static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
- struct smb2_write_req *req,
- struct ksmbd_file *fp,
- loff_t offset, size_t length, bool sync)
-{
- char *data_buf;
- int ret;
- ssize_t nbytes;
-
- data_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
- if (!data_buf)
- return -ENOMEM;
-
- ret = ksmbd_conn_rdma_read(work->conn, data_buf, length,
- (struct smb2_buffer_desc_v1 *)
- ((char *)req + le16_to_cpu(req->WriteChannelInfoOffset)),
- le16_to_cpu(req->WriteChannelInfoLength));
- if (ret < 0) {
- kvfree(data_buf);
- return ret;
- }
-
- ret = ksmbd_vfs_write(work, fp, data_buf, length, &offset, sync, &nbytes);
- kvfree(data_buf);
- if (ret < 0)
- return ret;
-
- return nbytes;
-}
-
-/**
- * smb2_write() - handler for smb2 write from file
- * @work: smb work containing write command buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_write(struct ksmbd_work *work)
-{
- struct smb2_write_req *req;
- struct smb2_write_rsp *rsp;
- struct ksmbd_file *fp = NULL;
- loff_t offset;
- size_t length;
- ssize_t nbytes;
- char *data_buf;
- bool writethrough = false, is_rdma_channel = false;
- int err = 0;
- unsigned int max_write_size = work->conn->vals->max_write_size;
-
- WORK_BUFFERS(work, req, rsp);
-
- if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_PIPE)) {
- ksmbd_debug(SMB, "IPC pipe write request\n");
- return smb2_write_pipe(work);
- }
-
- offset = le64_to_cpu(req->Offset);
- length = le32_to_cpu(req->Length);
-
- if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
- req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
- is_rdma_channel = true;
- max_write_size = get_smbd_max_read_write_size();
- length = le32_to_cpu(req->RemainingBytes);
- }
-
- if (is_rdma_channel == true) {
- unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
-
- if (req->Length != 0 || req->DataOffset != 0 ||
- ch_offset < offsetof(struct smb2_write_req, Buffer)) {
- err = -EINVAL;
- goto out;
- }
- err = smb2_set_remote_key_for_rdma(work,
- (struct smb2_buffer_desc_v1 *)
- ((char *)req + ch_offset),
- req->Channel,
- req->WriteChannelInfoLength);
- if (err)
- goto out;
- }
-
- if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
- ksmbd_debug(SMB, "User does not have write permission\n");
- err = -EACCES;
- goto out;
- }
-
- fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
- if (!fp) {
- err = -ENOENT;
- goto out;
- }
-
- if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_READ_ATTRIBUTES_LE))) {
- pr_err("Not permitted to write : 0x%x\n", fp->daccess);
- err = -EACCES;
- goto out;
- }
-
- if (length > max_write_size) {
- ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
- max_write_size);
- err = -EINVAL;
- goto out;
- }
-
- ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
- if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
- writethrough = true;
-
- if (is_rdma_channel == false) {
- if (le16_to_cpu(req->DataOffset) <
- offsetof(struct smb2_write_req, Buffer)) {
- err = -EINVAL;
- goto out;
- }
-
- data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
- le16_to_cpu(req->DataOffset));
-
- ksmbd_debug(SMB, "filename %pD, offset %lld, len %zu\n",
- fp->filp, offset, length);
- err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
- writethrough, &nbytes);
- if (err < 0)
- goto out;
- } else {
- /* read data from the client using rdma channel, and
- * write the data.
- */
- nbytes = smb2_write_rdma_channel(work, req, fp, offset, length,
- writethrough);
- if (nbytes < 0) {
- err = (int)nbytes;
- goto out;
- }
- }
-
- rsp->StructureSize = cpu_to_le16(17);
- rsp->DataOffset = 0;
- rsp->Reserved = 0;
- rsp->DataLength = cpu_to_le32(nbytes);
- rsp->DataRemaining = 0;
- rsp->Reserved2 = 0;
- inc_rfc1001_len(work->response_buf, 16);
- ksmbd_fd_put(work, fp);
- return 0;
-
-out:
- if (err == -EAGAIN)
- rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
- else if (err == -ENOSPC || err == -EFBIG)
- rsp->hdr.Status = STATUS_DISK_FULL;
- else if (err == -ENOENT)
- rsp->hdr.Status = STATUS_FILE_CLOSED;
- else if (err == -EACCES)
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- else if (err == -ESHARE)
- rsp->hdr.Status = STATUS_SHARING_VIOLATION;
- else if (err == -EINVAL)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- else
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
-
- smb2_set_err_rsp(work);
- ksmbd_fd_put(work, fp);
- return err;
-}
-
-/**
- * smb2_flush() - handler for smb2 flush file - fsync
- * @work: smb work containing flush command buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_flush(struct ksmbd_work *work)
-{
- struct smb2_flush_req *req;
- struct smb2_flush_rsp *rsp;
- int err;
-
- WORK_BUFFERS(work, req, rsp);
-
- ksmbd_debug(SMB, "SMB2_FLUSH called for fid %llu\n", req->VolatileFileId);
-
- err = ksmbd_vfs_fsync(work, req->VolatileFileId, req->PersistentFileId);
- if (err)
- goto out;
-
- rsp->StructureSize = cpu_to_le16(4);
- rsp->Reserved = 0;
- inc_rfc1001_len(work->response_buf, 4);
- return 0;
-
-out:
- if (err) {
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
- smb2_set_err_rsp(work);
- }
-
- return err;
-}
-
-/**
- * smb2_cancel() - handler for smb2 cancel command
- * @work: smb work containing cancel command buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_cancel(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
- struct smb2_hdr *chdr;
- struct ksmbd_work *iter;
- struct list_head *command_list;
-
- ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
- hdr->MessageId, hdr->Flags);
-
- if (hdr->Flags & SMB2_FLAGS_ASYNC_COMMAND) {
- command_list = &conn->async_requests;
-
- spin_lock(&conn->request_lock);
- list_for_each_entry(iter, command_list,
- async_request_entry) {
- chdr = smb2_get_msg(iter->request_buf);
-
- if (iter->async_id !=
- le64_to_cpu(hdr->Id.AsyncId))
- continue;
-
- ksmbd_debug(SMB,
- "smb2 with AsyncId %llu cancelled command = 0x%x\n",
- le64_to_cpu(hdr->Id.AsyncId),
- le16_to_cpu(chdr->Command));
- iter->state = KSMBD_WORK_CANCELLED;
- if (iter->cancel_fn)
- iter->cancel_fn(iter->cancel_argv);
- break;
- }
- spin_unlock(&conn->request_lock);
- } else {
- command_list = &conn->requests;
-
- spin_lock(&conn->request_lock);
- list_for_each_entry(iter, command_list, request_entry) {
- chdr = smb2_get_msg(iter->request_buf);
-
- if (chdr->MessageId != hdr->MessageId ||
- iter == work)
- continue;
-
- ksmbd_debug(SMB,
- "smb2 with mid %llu cancelled command = 0x%x\n",
- le64_to_cpu(hdr->MessageId),
- le16_to_cpu(chdr->Command));
- iter->state = KSMBD_WORK_CANCELLED;
- break;
- }
- spin_unlock(&conn->request_lock);
- }
-
- /* For SMB2_CANCEL command itself send no response*/
- work->send_no_response = 1;
- return 0;
-}
-
-struct file_lock *smb_flock_init(struct file *f)
-{
- struct file_lock *fl;
-
- fl = locks_alloc_lock();
- if (!fl)
- goto out;
-
- locks_init_lock(fl);
-
- fl->fl_owner = f;
- fl->fl_pid = current->tgid;
- fl->fl_file = f;
- fl->fl_flags = FL_POSIX;
- fl->fl_ops = NULL;
- fl->fl_lmops = NULL;
-
-out:
- return fl;
-}
-
-static int smb2_set_flock_flags(struct file_lock *flock, int flags)
-{
- int cmd = -EINVAL;
-
- /* Checking for wrong flag combination during lock request*/
- switch (flags) {
- case SMB2_LOCKFLAG_SHARED:
- ksmbd_debug(SMB, "received shared request\n");
- cmd = F_SETLKW;
- flock->fl_type = F_RDLCK;
- flock->fl_flags |= FL_SLEEP;
- break;
- case SMB2_LOCKFLAG_EXCLUSIVE:
- ksmbd_debug(SMB, "received exclusive request\n");
- cmd = F_SETLKW;
- flock->fl_type = F_WRLCK;
- flock->fl_flags |= FL_SLEEP;
- break;
- case SMB2_LOCKFLAG_SHARED | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
- ksmbd_debug(SMB,
- "received shared & fail immediately request\n");
- cmd = F_SETLK;
- flock->fl_type = F_RDLCK;
- break;
- case SMB2_LOCKFLAG_EXCLUSIVE | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
- ksmbd_debug(SMB,
- "received exclusive & fail immediately request\n");
- cmd = F_SETLK;
- flock->fl_type = F_WRLCK;
- break;
- case SMB2_LOCKFLAG_UNLOCK:
- ksmbd_debug(SMB, "received unlock request\n");
- flock->fl_type = F_UNLCK;
- cmd = 0;
- break;
- }
-
- return cmd;
-}
-
-static struct ksmbd_lock *smb2_lock_init(struct file_lock *flock,
- unsigned int cmd, int flags,
- struct list_head *lock_list)
-{
- struct ksmbd_lock *lock;
-
- lock = kzalloc(sizeof(struct ksmbd_lock), GFP_KERNEL);
- if (!lock)
- return NULL;
-
- lock->cmd = cmd;
- lock->fl = flock;
- lock->start = flock->fl_start;
- lock->end = flock->fl_end;
- lock->flags = flags;
- if (lock->start == lock->end)
- lock->zero_len = 1;
- INIT_LIST_HEAD(&lock->clist);
- INIT_LIST_HEAD(&lock->flist);
- INIT_LIST_HEAD(&lock->llist);
- list_add_tail(&lock->llist, lock_list);
-
- return lock;
-}
-
-static void smb2_remove_blocked_lock(void **argv)
-{
- struct file_lock *flock = (struct file_lock *)argv[0];
-
- ksmbd_vfs_posix_lock_unblock(flock);
- wake_up(&flock->fl_wait);
-}
-
-static inline bool lock_defer_pending(struct file_lock *fl)
-{
- /* check pending lock waiters */
- return waitqueue_active(&fl->fl_wait);
-}
-
-/**
- * smb2_lock() - handler for smb2 file lock command
- * @work: smb work containing lock command buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_lock(struct ksmbd_work *work)
-{
- struct smb2_lock_req *req = smb2_get_msg(work->request_buf);
- struct smb2_lock_rsp *rsp = smb2_get_msg(work->response_buf);
- struct smb2_lock_element *lock_ele;
- struct ksmbd_file *fp = NULL;
- struct file_lock *flock = NULL;
- struct file *filp = NULL;
- int lock_count;
- int flags = 0;
- int cmd = 0;
- int err = -EIO, i, rc = 0;
- u64 lock_start, lock_length;
- struct ksmbd_lock *smb_lock = NULL, *cmp_lock, *tmp, *tmp2;
- struct ksmbd_conn *conn;
- int nolock = 0;
- LIST_HEAD(lock_list);
- LIST_HEAD(rollback_list);
- int prior_lock = 0;
-
- ksmbd_debug(SMB, "Received lock request\n");
- fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
- if (!fp) {
- ksmbd_debug(SMB, "Invalid file id for lock : %llu\n", req->VolatileFileId);
- err = -ENOENT;
- goto out2;
- }
-
- filp = fp->filp;
- lock_count = le16_to_cpu(req->LockCount);
- lock_ele = req->locks;
-
- ksmbd_debug(SMB, "lock count is %d\n", lock_count);
- if (!lock_count) {
- err = -EINVAL;
- goto out2;
- }
-
- for (i = 0; i < lock_count; i++) {
- flags = le32_to_cpu(lock_ele[i].Flags);
-
- flock = smb_flock_init(filp);
- if (!flock)
- goto out;
-
- cmd = smb2_set_flock_flags(flock, flags);
-
- lock_start = le64_to_cpu(lock_ele[i].Offset);
- lock_length = le64_to_cpu(lock_ele[i].Length);
- if (lock_start > U64_MAX - lock_length) {
- pr_err("Invalid lock range requested\n");
- rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE;
- goto out;
- }
-
- if (lock_start > OFFSET_MAX)
- flock->fl_start = OFFSET_MAX;
- else
- flock->fl_start = lock_start;
-
- lock_length = le64_to_cpu(lock_ele[i].Length);
- if (lock_length > OFFSET_MAX - flock->fl_start)
- lock_length = OFFSET_MAX - flock->fl_start;
-
- flock->fl_end = flock->fl_start + lock_length;
-
- if (flock->fl_end < flock->fl_start) {
- ksmbd_debug(SMB,
- "the end offset(%llx) is smaller than the start offset(%llx)\n",
- flock->fl_end, flock->fl_start);
- rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE;
- goto out;
- }
-
- /* Check conflict locks in one request */
- list_for_each_entry(cmp_lock, &lock_list, llist) {
- if (cmp_lock->fl->fl_start <= flock->fl_start &&
- cmp_lock->fl->fl_end >= flock->fl_end) {
- if (cmp_lock->fl->fl_type != F_UNLCK &&
- flock->fl_type != F_UNLCK) {
- pr_err("conflict two locks in one request\n");
- err = -EINVAL;
- goto out;
- }
- }
- }
-
- smb_lock = smb2_lock_init(flock, cmd, flags, &lock_list);
- if (!smb_lock) {
- err = -EINVAL;
- goto out;
- }
- }
-
- list_for_each_entry_safe(smb_lock, tmp, &lock_list, llist) {
- if (smb_lock->cmd < 0) {
- err = -EINVAL;
- goto out;
- }
-
- if (!(smb_lock->flags & SMB2_LOCKFLAG_MASK)) {
- err = -EINVAL;
- goto out;
- }
-
- if ((prior_lock & (SMB2_LOCKFLAG_EXCLUSIVE | SMB2_LOCKFLAG_SHARED) &&
- smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) ||
- (prior_lock == SMB2_LOCKFLAG_UNLOCK &&
- !(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK))) {
- err = -EINVAL;
- goto out;
- }
-
- prior_lock = smb_lock->flags;
-
- if (!(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) &&
- !(smb_lock->flags & SMB2_LOCKFLAG_FAIL_IMMEDIATELY))
- goto no_check_cl;
-
- nolock = 1;
- /* check locks in connection list */
- down_read(&conn_list_lock);
- list_for_each_entry(conn, &conn_list, conns_list) {
- spin_lock(&conn->llist_lock);
- list_for_each_entry_safe(cmp_lock, tmp2, &conn->lock_list, clist) {
- if (file_inode(cmp_lock->fl->fl_file) !=
- file_inode(smb_lock->fl->fl_file))
- continue;
-
- if (smb_lock->fl->fl_type == F_UNLCK) {
- if (cmp_lock->fl->fl_file == smb_lock->fl->fl_file &&
- cmp_lock->start == smb_lock->start &&
- cmp_lock->end == smb_lock->end &&
- !lock_defer_pending(cmp_lock->fl)) {
- nolock = 0;
- list_del(&cmp_lock->flist);
- list_del(&cmp_lock->clist);
- spin_unlock(&conn->llist_lock);
- up_read(&conn_list_lock);
-
- locks_free_lock(cmp_lock->fl);
- kfree(cmp_lock);
- goto out_check_cl;
- }
- continue;
- }
-
- if (cmp_lock->fl->fl_file == smb_lock->fl->fl_file) {
- if (smb_lock->flags & SMB2_LOCKFLAG_SHARED)
- continue;
- } else {
- if (cmp_lock->flags & SMB2_LOCKFLAG_SHARED)
- continue;
- }
-
- /* check zero byte lock range */
- if (cmp_lock->zero_len && !smb_lock->zero_len &&
- cmp_lock->start > smb_lock->start &&
- cmp_lock->start < smb_lock->end) {
- spin_unlock(&conn->llist_lock);
- up_read(&conn_list_lock);
- pr_err("previous lock conflict with zero byte lock range\n");
- goto out;
- }
-
- if (smb_lock->zero_len && !cmp_lock->zero_len &&
- smb_lock->start > cmp_lock->start &&
- smb_lock->start < cmp_lock->end) {
- spin_unlock(&conn->llist_lock);
- up_read(&conn_list_lock);
- pr_err("current lock conflict with zero byte lock range\n");
- goto out;
- }
-
- if (((cmp_lock->start <= smb_lock->start &&
- cmp_lock->end > smb_lock->start) ||
- (cmp_lock->start < smb_lock->end &&
- cmp_lock->end >= smb_lock->end)) &&
- !cmp_lock->zero_len && !smb_lock->zero_len) {
- spin_unlock(&conn->llist_lock);
- up_read(&conn_list_lock);
- pr_err("Not allow lock operation on exclusive lock range\n");
- goto out;
- }
- }
- spin_unlock(&conn->llist_lock);
- }
- up_read(&conn_list_lock);
-out_check_cl:
- if (smb_lock->fl->fl_type == F_UNLCK && nolock) {
- pr_err("Try to unlock nolocked range\n");
- rsp->hdr.Status = STATUS_RANGE_NOT_LOCKED;
- goto out;
- }
-
-no_check_cl:
- if (smb_lock->zero_len) {
- err = 0;
- goto skip;
- }
-
- flock = smb_lock->fl;
- list_del(&smb_lock->llist);
-retry:
- rc = vfs_lock_file(filp, smb_lock->cmd, flock, NULL);
-skip:
- if (flags & SMB2_LOCKFLAG_UNLOCK) {
- if (!rc) {
- ksmbd_debug(SMB, "File unlocked\n");
- } else if (rc == -ENOENT) {
- rsp->hdr.Status = STATUS_NOT_LOCKED;
- goto out;
- }
- locks_free_lock(flock);
- kfree(smb_lock);
- } else {
- if (rc == FILE_LOCK_DEFERRED) {
- void **argv;
-
- ksmbd_debug(SMB,
- "would have to wait for getting lock\n");
- spin_lock(&work->conn->llist_lock);
- list_add_tail(&smb_lock->clist,
- &work->conn->lock_list);
- spin_unlock(&work->conn->llist_lock);
- list_add(&smb_lock->llist, &rollback_list);
-
- argv = kmalloc(sizeof(void *), GFP_KERNEL);
- if (!argv) {
- err = -ENOMEM;
- goto out;
- }
- argv[0] = flock;
-
- rc = setup_async_work(work,
- smb2_remove_blocked_lock,
- argv);
- if (rc) {
- err = -ENOMEM;
- goto out;
- }
- spin_lock(&fp->f_lock);
- list_add(&work->fp_entry, &fp->blocked_works);
- spin_unlock(&fp->f_lock);
-
- smb2_send_interim_resp(work, STATUS_PENDING);
-
- ksmbd_vfs_posix_lock_wait(flock);
-
- spin_lock(&work->conn->request_lock);
- spin_lock(&fp->f_lock);
- list_del(&work->fp_entry);
- work->cancel_fn = NULL;
- kfree(argv);
- spin_unlock(&fp->f_lock);
- spin_unlock(&work->conn->request_lock);
-
- if (work->state != KSMBD_WORK_ACTIVE) {
- list_del(&smb_lock->llist);
- spin_lock(&work->conn->llist_lock);
- list_del(&smb_lock->clist);
- spin_unlock(&work->conn->llist_lock);
- locks_free_lock(flock);
-
- if (work->state == KSMBD_WORK_CANCELLED) {
- rsp->hdr.Status =
- STATUS_CANCELLED;
- kfree(smb_lock);
- smb2_send_interim_resp(work,
- STATUS_CANCELLED);
- work->send_no_response = 1;
- goto out;
- }
- init_smb2_rsp_hdr(work);
- smb2_set_err_rsp(work);
- rsp->hdr.Status =
- STATUS_RANGE_NOT_LOCKED;
- kfree(smb_lock);
- goto out2;
- }
-
- list_del(&smb_lock->llist);
- spin_lock(&work->conn->llist_lock);
- list_del(&smb_lock->clist);
- spin_unlock(&work->conn->llist_lock);
-
- goto retry;
- } else if (!rc) {
- spin_lock(&work->conn->llist_lock);
- list_add_tail(&smb_lock->clist,
- &work->conn->lock_list);
- list_add_tail(&smb_lock->flist,
- &fp->lock_list);
- spin_unlock(&work->conn->llist_lock);
- list_add(&smb_lock->llist, &rollback_list);
- ksmbd_debug(SMB, "successful in taking lock\n");
- } else {
- goto out;
- }
- }
- }
-
- if (atomic_read(&fp->f_ci->op_count) > 1)
- smb_break_all_oplock(work, fp);
-
- rsp->StructureSize = cpu_to_le16(4);
- ksmbd_debug(SMB, "successful in taking lock\n");
- rsp->hdr.Status = STATUS_SUCCESS;
- rsp->Reserved = 0;
- inc_rfc1001_len(work->response_buf, 4);
- ksmbd_fd_put(work, fp);
- return 0;
-
-out:
- list_for_each_entry_safe(smb_lock, tmp, &lock_list, llist) {
- locks_free_lock(smb_lock->fl);
- list_del(&smb_lock->llist);
- kfree(smb_lock);
- }
-
- list_for_each_entry_safe(smb_lock, tmp, &rollback_list, llist) {
- struct file_lock *rlock = NULL;
-
- rlock = smb_flock_init(filp);
- rlock->fl_type = F_UNLCK;
- rlock->fl_start = smb_lock->start;
- rlock->fl_end = smb_lock->end;
-
- rc = vfs_lock_file(filp, 0, rlock, NULL);
- if (rc)
- pr_err("rollback unlock fail : %d\n", rc);
-
- list_del(&smb_lock->llist);
- spin_lock(&work->conn->llist_lock);
- if (!list_empty(&smb_lock->flist))
- list_del(&smb_lock->flist);
- list_del(&smb_lock->clist);
- spin_unlock(&work->conn->llist_lock);
-
- locks_free_lock(smb_lock->fl);
- locks_free_lock(rlock);
- kfree(smb_lock);
- }
-out2:
- ksmbd_debug(SMB, "failed in taking lock(flags : %x), err : %d\n", flags, err);
-
- if (!rsp->hdr.Status) {
- if (err == -EINVAL)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- else if (err == -ENOMEM)
- rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
- else if (err == -ENOENT)
- rsp->hdr.Status = STATUS_FILE_CLOSED;
- else
- rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
- }
-
- smb2_set_err_rsp(work);
- ksmbd_fd_put(work, fp);
- return err;
-}
-
-static int fsctl_copychunk(struct ksmbd_work *work,
- struct copychunk_ioctl_req *ci_req,
- unsigned int cnt_code,
- unsigned int input_count,
- unsigned long long volatile_id,
- unsigned long long persistent_id,
- struct smb2_ioctl_rsp *rsp)
-{
- struct copychunk_ioctl_rsp *ci_rsp;
- struct ksmbd_file *src_fp = NULL, *dst_fp = NULL;
- struct srv_copychunk *chunks;
- unsigned int i, chunk_count, chunk_count_written = 0;
- unsigned int chunk_size_written = 0;
- loff_t total_size_written = 0;
- int ret = 0;
-
- ci_rsp = (struct copychunk_ioctl_rsp *)&rsp->Buffer[0];
-
- rsp->VolatileFileId = volatile_id;
- rsp->PersistentFileId = persistent_id;
- ci_rsp->ChunksWritten =
- cpu_to_le32(ksmbd_server_side_copy_max_chunk_count());
- ci_rsp->ChunkBytesWritten =
- cpu_to_le32(ksmbd_server_side_copy_max_chunk_size());
- ci_rsp->TotalBytesWritten =
- cpu_to_le32(ksmbd_server_side_copy_max_total_size());
-
- chunks = (struct srv_copychunk *)&ci_req->Chunks[0];
- chunk_count = le32_to_cpu(ci_req->ChunkCount);
- if (chunk_count == 0)
- goto out;
- total_size_written = 0;
-
- /* verify the SRV_COPYCHUNK_COPY packet */
- if (chunk_count > ksmbd_server_side_copy_max_chunk_count() ||
- input_count < offsetof(struct copychunk_ioctl_req, Chunks) +
- chunk_count * sizeof(struct srv_copychunk)) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- return -EINVAL;
- }
-
- for (i = 0; i < chunk_count; i++) {
- if (le32_to_cpu(chunks[i].Length) == 0 ||
- le32_to_cpu(chunks[i].Length) > ksmbd_server_side_copy_max_chunk_size())
- break;
- total_size_written += le32_to_cpu(chunks[i].Length);
- }
-
- if (i < chunk_count ||
- total_size_written > ksmbd_server_side_copy_max_total_size()) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- return -EINVAL;
- }
-
- src_fp = ksmbd_lookup_foreign_fd(work,
- le64_to_cpu(ci_req->ResumeKey[0]));
- dst_fp = ksmbd_lookup_fd_slow(work, volatile_id, persistent_id);
- ret = -EINVAL;
- if (!src_fp ||
- src_fp->persistent_id != le64_to_cpu(ci_req->ResumeKey[1])) {
- rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
- goto out;
- }
-
- if (!dst_fp) {
- rsp->hdr.Status = STATUS_FILE_CLOSED;
- goto out;
- }
-
- /*
- * FILE_READ_DATA should only be included in
- * the FSCTL_COPYCHUNK case
- */
- if (cnt_code == FSCTL_COPYCHUNK &&
- !(dst_fp->daccess & (FILE_READ_DATA_LE | FILE_GENERIC_READ_LE))) {
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- goto out;
- }
-
- ret = ksmbd_vfs_copy_file_ranges(work, src_fp, dst_fp,
- chunks, chunk_count,
- &chunk_count_written,
- &chunk_size_written,
- &total_size_written);
- if (ret < 0) {
- if (ret == -EACCES)
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- if (ret == -EAGAIN)
- rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
- else if (ret == -EBADF)
- rsp->hdr.Status = STATUS_INVALID_HANDLE;
- else if (ret == -EFBIG || ret == -ENOSPC)
- rsp->hdr.Status = STATUS_DISK_FULL;
- else if (ret == -EINVAL)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- else if (ret == -EISDIR)
- rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
- else if (ret == -E2BIG)
- rsp->hdr.Status = STATUS_INVALID_VIEW_SIZE;
- else
- rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
- }
-
- ci_rsp->ChunksWritten = cpu_to_le32(chunk_count_written);
- ci_rsp->ChunkBytesWritten = cpu_to_le32(chunk_size_written);
- ci_rsp->TotalBytesWritten = cpu_to_le32(total_size_written);
-out:
- ksmbd_fd_put(work, src_fp);
- ksmbd_fd_put(work, dst_fp);
- return ret;
-}
-
-static __be32 idev_ipv4_address(struct in_device *idev)
-{
- __be32 addr = 0;
-
- struct in_ifaddr *ifa;
-
- rcu_read_lock();
- in_dev_for_each_ifa_rcu(ifa, idev) {
- if (ifa->ifa_flags & IFA_F_SECONDARY)
- continue;
-
- addr = ifa->ifa_address;
- break;
- }
- rcu_read_unlock();
- return addr;
-}
-
-static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
- struct smb2_ioctl_rsp *rsp,
- unsigned int out_buf_len)
-{
- struct network_interface_info_ioctl_rsp *nii_rsp = NULL;
- int nbytes = 0;
- struct net_device *netdev;
- struct sockaddr_storage_rsp *sockaddr_storage;
- unsigned int flags;
- unsigned long long speed;
-
- rtnl_lock();
- for_each_netdev(&init_net, netdev) {
- bool ipv4_set = false;
-
- if (netdev->type == ARPHRD_LOOPBACK)
- continue;
-
- flags = dev_get_flags(netdev);
- if (!(flags & IFF_RUNNING))
- continue;
-ipv6_retry:
- if (out_buf_len <
- nbytes + sizeof(struct network_interface_info_ioctl_rsp)) {
- rtnl_unlock();
- return -ENOSPC;
- }
-
- nii_rsp = (struct network_interface_info_ioctl_rsp *)
- &rsp->Buffer[nbytes];
- nii_rsp->IfIndex = cpu_to_le32(netdev->ifindex);
-
- nii_rsp->Capability = 0;
- if (netdev->real_num_tx_queues > 1)
- nii_rsp->Capability |= cpu_to_le32(RSS_CAPABLE);
- if (ksmbd_rdma_capable_netdev(netdev))
- nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE);
-
- nii_rsp->Next = cpu_to_le32(152);
- nii_rsp->Reserved = 0;
-
- if (netdev->ethtool_ops->get_link_ksettings) {
- struct ethtool_link_ksettings cmd;
-
- netdev->ethtool_ops->get_link_ksettings(netdev, &cmd);
- speed = cmd.base.speed;
- } else {
- ksmbd_debug(SMB, "%s %s\n", netdev->name,
- "speed is unknown, defaulting to 1Gb/sec");
- speed = SPEED_1000;
- }
-
- speed *= 1000000;
- nii_rsp->LinkSpeed = cpu_to_le64(speed);
-
- sockaddr_storage = (struct sockaddr_storage_rsp *)
- nii_rsp->SockAddr_Storage;
- memset(sockaddr_storage, 0, 128);
-
- if (!ipv4_set) {
- struct in_device *idev;
-
- sockaddr_storage->Family = cpu_to_le16(INTERNETWORK);
- sockaddr_storage->addr4.Port = 0;
-
- idev = __in_dev_get_rtnl(netdev);
- if (!idev)
- continue;
- sockaddr_storage->addr4.IPv4address =
- idev_ipv4_address(idev);
- nbytes += sizeof(struct network_interface_info_ioctl_rsp);
- ipv4_set = true;
- goto ipv6_retry;
- } else {
- struct inet6_dev *idev6;
- struct inet6_ifaddr *ifa;
- __u8 *ipv6_addr = sockaddr_storage->addr6.IPv6address;
-
- sockaddr_storage->Family = cpu_to_le16(INTERNETWORKV6);
- sockaddr_storage->addr6.Port = 0;
- sockaddr_storage->addr6.FlowInfo = 0;
-
- idev6 = __in6_dev_get(netdev);
- if (!idev6)
- continue;
-
- list_for_each_entry(ifa, &idev6->addr_list, if_list) {
- if (ifa->flags & (IFA_F_TENTATIVE |
- IFA_F_DEPRECATED))
- continue;
- memcpy(ipv6_addr, ifa->addr.s6_addr, 16);
- break;
- }
- sockaddr_storage->addr6.ScopeId = 0;
- nbytes += sizeof(struct network_interface_info_ioctl_rsp);
- }
- }
- rtnl_unlock();
-
- /* zero if this is last one */
- if (nii_rsp)
- nii_rsp->Next = 0;
-
- rsp->PersistentFileId = SMB2_NO_FID;
- rsp->VolatileFileId = SMB2_NO_FID;
- return nbytes;
-}
-
-static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn,
- struct validate_negotiate_info_req *neg_req,
- struct validate_negotiate_info_rsp *neg_rsp,
- unsigned int in_buf_len)
-{
- int ret = 0;
- int dialect;
-
- if (in_buf_len < offsetof(struct validate_negotiate_info_req, Dialects) +
- le16_to_cpu(neg_req->DialectCount) * sizeof(__le16))
- return -EINVAL;
-
- dialect = ksmbd_lookup_dialect_by_id(neg_req->Dialects,
- neg_req->DialectCount);
- if (dialect == BAD_PROT_ID || dialect != conn->dialect) {
- ret = -EINVAL;
- goto err_out;
- }
-
- if (strncmp(neg_req->Guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE)) {
- ret = -EINVAL;
- goto err_out;
- }
-
- if (le16_to_cpu(neg_req->SecurityMode) != conn->cli_sec_mode) {
- ret = -EINVAL;
- goto err_out;
- }
-
- if (le32_to_cpu(neg_req->Capabilities) != conn->cli_cap) {
- ret = -EINVAL;
- goto err_out;
- }
-
- neg_rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
- memset(neg_rsp->Guid, 0, SMB2_CLIENT_GUID_SIZE);
- neg_rsp->SecurityMode = cpu_to_le16(conn->srv_sec_mode);
- neg_rsp->Dialect = cpu_to_le16(conn->dialect);
-err_out:
- return ret;
-}
-
-static int fsctl_query_allocated_ranges(struct ksmbd_work *work, u64 id,
- struct file_allocated_range_buffer *qar_req,
- struct file_allocated_range_buffer *qar_rsp,
- unsigned int in_count, unsigned int *out_count)
-{
- struct ksmbd_file *fp;
- loff_t start, length;
- int ret = 0;
-
- *out_count = 0;
- if (in_count == 0)
- return -EINVAL;
-
- start = le64_to_cpu(qar_req->file_offset);
- length = le64_to_cpu(qar_req->length);
-
- if (start < 0 || length < 0)
- return -EINVAL;
-
- fp = ksmbd_lookup_fd_fast(work, id);
- if (!fp)
- return -ENOENT;
-
- ret = ksmbd_vfs_fqar_lseek(fp, start, length,
- qar_rsp, in_count, out_count);
- if (ret && ret != -E2BIG)
- *out_count = 0;
-
- ksmbd_fd_put(work, fp);
- return ret;
-}
-
-static int fsctl_pipe_transceive(struct ksmbd_work *work, u64 id,
- unsigned int out_buf_len,
- struct smb2_ioctl_req *req,
- struct smb2_ioctl_rsp *rsp)
-{
- struct ksmbd_rpc_command *rpc_resp;
- char *data_buf = (char *)&req->Buffer[0];
- int nbytes = 0;
-
- rpc_resp = ksmbd_rpc_ioctl(work->sess, id, data_buf,
- le32_to_cpu(req->InputCount));
- if (rpc_resp) {
- if (rpc_resp->flags == KSMBD_RPC_SOME_NOT_MAPPED) {
- /*
- * set STATUS_SOME_NOT_MAPPED response
- * for unknown domain sid.
- */
- rsp->hdr.Status = STATUS_SOME_NOT_MAPPED;
- } else if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) {
- rsp->hdr.Status = STATUS_NOT_SUPPORTED;
- goto out;
- } else if (rpc_resp->flags != KSMBD_RPC_OK) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- goto out;
- }
-
- nbytes = rpc_resp->payload_sz;
- if (rpc_resp->payload_sz > out_buf_len) {
- rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
- nbytes = out_buf_len;
- }
-
- if (!rpc_resp->payload_sz) {
- rsp->hdr.Status =
- STATUS_UNEXPECTED_IO_ERROR;
- goto out;
- }
-
- memcpy((char *)rsp->Buffer, rpc_resp->payload, nbytes);
- }
-out:
- kvfree(rpc_resp);
- return nbytes;
-}
-
-static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
- struct file_sparse *sparse)
-{
- struct ksmbd_file *fp;
- struct user_namespace *user_ns;
- int ret = 0;
- __le32 old_fattr;
-
- fp = ksmbd_lookup_fd_fast(work, id);
- if (!fp)
- return -ENOENT;
- user_ns = file_mnt_user_ns(fp->filp);
-
- old_fattr = fp->f_ci->m_fattr;
- if (sparse->SetSparse)
- fp->f_ci->m_fattr |= FILE_ATTRIBUTE_SPARSE_FILE_LE;
- else
- fp->f_ci->m_fattr &= ~FILE_ATTRIBUTE_SPARSE_FILE_LE;
-
- if (fp->f_ci->m_fattr != old_fattr &&
- test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
- struct xattr_dos_attrib da;
-
- ret = ksmbd_vfs_get_dos_attrib_xattr(user_ns,
- fp->filp->f_path.dentry, &da);
- if (ret <= 0)
- goto out;
-
- da.attr = le32_to_cpu(fp->f_ci->m_fattr);
- ret = ksmbd_vfs_set_dos_attrib_xattr(user_ns,
- fp->filp->f_path.dentry, &da);
- if (ret)
- fp->f_ci->m_fattr = old_fattr;
- }
-
-out:
- ksmbd_fd_put(work, fp);
- return ret;
-}
-
-static int fsctl_request_resume_key(struct ksmbd_work *work,
- struct smb2_ioctl_req *req,
- struct resume_key_ioctl_rsp *key_rsp)
-{
- struct ksmbd_file *fp;
-
- fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
- if (!fp)
- return -ENOENT;
-
- memset(key_rsp, 0, sizeof(*key_rsp));
- key_rsp->ResumeKey[0] = req->VolatileFileId;
- key_rsp->ResumeKey[1] = req->PersistentFileId;
- ksmbd_fd_put(work, fp);
-
- return 0;
-}
-
-/**
- * smb2_ioctl() - handler for smb2 ioctl command
- * @work: smb work containing ioctl command buffer
- *
- * Return: 0 on success, otherwise error
- */
-int smb2_ioctl(struct ksmbd_work *work)
-{
- struct smb2_ioctl_req *req;
- struct smb2_ioctl_rsp *rsp;
- unsigned int cnt_code, nbytes = 0, out_buf_len, in_buf_len;
- u64 id = KSMBD_NO_FID;
- struct ksmbd_conn *conn = work->conn;
- int ret = 0;
-
- if (work->next_smb2_rcv_hdr_off) {
- req = ksmbd_req_buf_next(work);
- rsp = ksmbd_resp_buf_next(work);
- if (!has_file_id(req->VolatileFileId)) {
- ksmbd_debug(SMB, "Compound request set FID = %llu\n",
- work->compound_fid);
- id = work->compound_fid;
- }
- } else {
- req = smb2_get_msg(work->request_buf);
- rsp = smb2_get_msg(work->response_buf);
- }
-
- if (!has_file_id(id))
- id = req->VolatileFileId;
-
- if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) {
- rsp->hdr.Status = STATUS_NOT_SUPPORTED;
- goto out;
- }
-
- cnt_code = le32_to_cpu(req->CtlCode);
- ret = smb2_calc_max_out_buf_len(work, 48,
- le32_to_cpu(req->MaxOutputResponse));
- if (ret < 0) {
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- goto out;
- }
- out_buf_len = (unsigned int)ret;
- in_buf_len = le32_to_cpu(req->InputCount);
-
- switch (cnt_code) {
- case FSCTL_DFS_GET_REFERRALS:
- case FSCTL_DFS_GET_REFERRALS_EX:
- /* Not support DFS yet */
- rsp->hdr.Status = STATUS_FS_DRIVER_REQUIRED;
- goto out;
- case FSCTL_CREATE_OR_GET_OBJECT_ID:
- {
- struct file_object_buf_type1_ioctl_rsp *obj_buf;
-
- nbytes = sizeof(struct file_object_buf_type1_ioctl_rsp);
- obj_buf = (struct file_object_buf_type1_ioctl_rsp *)
- &rsp->Buffer[0];
-
- /*
- * TODO: This is dummy implementation to pass smbtorture
- * Need to check correct response later
- */
- memset(obj_buf->ObjectId, 0x0, 16);
- memset(obj_buf->BirthVolumeId, 0x0, 16);
- memset(obj_buf->BirthObjectId, 0x0, 16);
- memset(obj_buf->DomainId, 0x0, 16);
-
- break;
- }
- case FSCTL_PIPE_TRANSCEIVE:
- out_buf_len = min_t(u32, KSMBD_IPC_MAX_PAYLOAD, out_buf_len);
- nbytes = fsctl_pipe_transceive(work, id, out_buf_len, req, rsp);
- break;
- case FSCTL_VALIDATE_NEGOTIATE_INFO:
- if (conn->dialect < SMB30_PROT_ID) {
- ret = -EOPNOTSUPP;
- goto out;
- }
-
- if (in_buf_len < offsetof(struct validate_negotiate_info_req,
- Dialects)) {
- ret = -EINVAL;
- goto out;
- }
-
- if (out_buf_len < sizeof(struct validate_negotiate_info_rsp)) {
- ret = -EINVAL;
- goto out;
- }
-
- ret = fsctl_validate_negotiate_info(conn,
- (struct validate_negotiate_info_req *)&req->Buffer[0],
- (struct validate_negotiate_info_rsp *)&rsp->Buffer[0],
- in_buf_len);
- if (ret < 0)
- goto out;
-
- nbytes = sizeof(struct validate_negotiate_info_rsp);
- rsp->PersistentFileId = SMB2_NO_FID;
- rsp->VolatileFileId = SMB2_NO_FID;
- break;
- case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
- ret = fsctl_query_iface_info_ioctl(conn, rsp, out_buf_len);
- if (ret < 0)
- goto out;
- nbytes = ret;
- break;
- case FSCTL_REQUEST_RESUME_KEY:
- if (out_buf_len < sizeof(struct resume_key_ioctl_rsp)) {
- ret = -EINVAL;
- goto out;
- }
-
- ret = fsctl_request_resume_key(work, req,
- (struct resume_key_ioctl_rsp *)&rsp->Buffer[0]);
- if (ret < 0)
- goto out;
- rsp->PersistentFileId = req->PersistentFileId;
- rsp->VolatileFileId = req->VolatileFileId;
- nbytes = sizeof(struct resume_key_ioctl_rsp);
- break;
- case FSCTL_COPYCHUNK:
- case FSCTL_COPYCHUNK_WRITE:
- if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
- ksmbd_debug(SMB,
- "User does not have write permission\n");
- ret = -EACCES;
- goto out;
- }
-
- if (in_buf_len < sizeof(struct copychunk_ioctl_req)) {
- ret = -EINVAL;
- goto out;
- }
-
- if (out_buf_len < sizeof(struct copychunk_ioctl_rsp)) {
- ret = -EINVAL;
- goto out;
- }
-
- nbytes = sizeof(struct copychunk_ioctl_rsp);
- rsp->VolatileFileId = req->VolatileFileId;
- rsp->PersistentFileId = req->PersistentFileId;
- fsctl_copychunk(work,
- (struct copychunk_ioctl_req *)&req->Buffer[0],
- le32_to_cpu(req->CtlCode),
- le32_to_cpu(req->InputCount),
- req->VolatileFileId,
- req->PersistentFileId,
- rsp);
- break;
- case FSCTL_SET_SPARSE:
- if (in_buf_len < sizeof(struct file_sparse)) {
- ret = -EINVAL;
- goto out;
- }
-
- ret = fsctl_set_sparse(work, id,
- (struct file_sparse *)&req->Buffer[0]);
- if (ret < 0)
- goto out;
- break;
- case FSCTL_SET_ZERO_DATA:
- {
- struct file_zero_data_information *zero_data;
- struct ksmbd_file *fp;
- loff_t off, len, bfz;
-
- if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
- ksmbd_debug(SMB,
- "User does not have write permission\n");
- ret = -EACCES;
- goto out;
- }
-
- if (in_buf_len < sizeof(struct file_zero_data_information)) {
- ret = -EINVAL;
- goto out;
- }
-
- zero_data =
- (struct file_zero_data_information *)&req->Buffer[0];
-
- off = le64_to_cpu(zero_data->FileOffset);
- bfz = le64_to_cpu(zero_data->BeyondFinalZero);
- if (off < 0 || bfz < 0 || off > bfz) {
- ret = -EINVAL;
- goto out;
- }
-
- len = bfz - off;
- if (len) {
- fp = ksmbd_lookup_fd_fast(work, id);
- if (!fp) {
- ret = -ENOENT;
- goto out;
- }
-
- ret = ksmbd_vfs_zero_data(work, fp, off, len);
- ksmbd_fd_put(work, fp);
- if (ret < 0)
- goto out;
- }
- break;
- }
- case FSCTL_QUERY_ALLOCATED_RANGES:
- if (in_buf_len < sizeof(struct file_allocated_range_buffer)) {
- ret = -EINVAL;
- goto out;
- }
-
- ret = fsctl_query_allocated_ranges(work, id,
- (struct file_allocated_range_buffer *)&req->Buffer[0],
- (struct file_allocated_range_buffer *)&rsp->Buffer[0],
- out_buf_len /
- sizeof(struct file_allocated_range_buffer), &nbytes);
- if (ret == -E2BIG) {
- rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
- } else if (ret < 0) {
- nbytes = 0;
- goto out;
- }
-
- nbytes *= sizeof(struct file_allocated_range_buffer);
- break;
- case FSCTL_GET_REPARSE_POINT:
- {
- struct reparse_data_buffer *reparse_ptr;
- struct ksmbd_file *fp;
-
- reparse_ptr = (struct reparse_data_buffer *)&rsp->Buffer[0];
- fp = ksmbd_lookup_fd_fast(work, id);
- if (!fp) {
- pr_err("not found fp!!\n");
- ret = -ENOENT;
- goto out;
- }
-
- reparse_ptr->ReparseTag =
- smb2_get_reparse_tag_special_file(file_inode(fp->filp)->i_mode);
- reparse_ptr->ReparseDataLength = 0;
- ksmbd_fd_put(work, fp);
- nbytes = sizeof(struct reparse_data_buffer);
- break;
- }
- case FSCTL_DUPLICATE_EXTENTS_TO_FILE:
- {
- struct ksmbd_file *fp_in, *fp_out = NULL;
- struct duplicate_extents_to_file *dup_ext;
- loff_t src_off, dst_off, length, cloned;
-
- if (in_buf_len < sizeof(struct duplicate_extents_to_file)) {
- ret = -EINVAL;
- goto out;
- }
-
- dup_ext = (struct duplicate_extents_to_file *)&req->Buffer[0];
-
- fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle,
- dup_ext->PersistentFileHandle);
- if (!fp_in) {
- pr_err("not found file handle in duplicate extent to file\n");
- ret = -ENOENT;
- goto out;
- }
-
- fp_out = ksmbd_lookup_fd_fast(work, id);
- if (!fp_out) {
- pr_err("not found fp\n");
- ret = -ENOENT;
- goto dup_ext_out;
- }
-
- src_off = le64_to_cpu(dup_ext->SourceFileOffset);
- dst_off = le64_to_cpu(dup_ext->TargetFileOffset);
- length = le64_to_cpu(dup_ext->ByteCount);
- /*
- * XXX: It is not clear if FSCTL_DUPLICATE_EXTENTS_TO_FILE
- * should fall back to vfs_copy_file_range(). This could be
- * beneficial when re-exporting nfs/smb mount, but note that
- * this can result in partial copy that returns an error status.
- * If/when FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX is implemented,
- * fall back to vfs_copy_file_range(), should be avoided when
- * the flag DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC is set.
- */
- cloned = vfs_clone_file_range(fp_in->filp, src_off,
- fp_out->filp, dst_off, length, 0);
- if (cloned == -EXDEV || cloned == -EOPNOTSUPP) {
- ret = -EOPNOTSUPP;
- goto dup_ext_out;
- } else if (cloned != length) {
- cloned = vfs_copy_file_range(fp_in->filp, src_off,
- fp_out->filp, dst_off,
- length, 0);
- if (cloned != length) {
- if (cloned < 0)
- ret = cloned;
- else
- ret = -EINVAL;
- }
- }
-
-dup_ext_out:
- ksmbd_fd_put(work, fp_in);
- ksmbd_fd_put(work, fp_out);
- if (ret < 0)
- goto out;
- break;
- }
- default:
- ksmbd_debug(SMB, "not implemented yet ioctl command 0x%x\n",
- cnt_code);
- ret = -EOPNOTSUPP;
- goto out;
- }
-
- rsp->CtlCode = cpu_to_le32(cnt_code);
- rsp->InputCount = cpu_to_le32(0);
- rsp->InputOffset = cpu_to_le32(112);
- rsp->OutputOffset = cpu_to_le32(112);
- rsp->OutputCount = cpu_to_le32(nbytes);
- rsp->StructureSize = cpu_to_le16(49);
- rsp->Reserved = cpu_to_le16(0);
- rsp->Flags = cpu_to_le32(0);
- rsp->Reserved2 = cpu_to_le32(0);
- inc_rfc1001_len(work->response_buf, 48 + nbytes);
-
- return 0;
-
-out:
- if (ret == -EACCES)
- rsp->hdr.Status = STATUS_ACCESS_DENIED;
- else if (ret == -ENOENT)
- rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
- else if (ret == -EOPNOTSUPP)
- rsp->hdr.Status = STATUS_NOT_SUPPORTED;
- else if (ret == -ENOSPC)
- rsp->hdr.Status = STATUS_BUFFER_TOO_SMALL;
- else if (ret < 0 || rsp->hdr.Status == 0)
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- smb2_set_err_rsp(work);
- return 0;
-}
-
-/**
- * smb20_oplock_break_ack() - handler for smb2.0 oplock break command
- * @work: smb work containing oplock break command buffer
- *
- * Return: 0
- */
-static void smb20_oplock_break_ack(struct ksmbd_work *work)
-{
- struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
- struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
- struct ksmbd_file *fp;
- struct oplock_info *opinfo = NULL;
- __le32 err = 0;
- int ret = 0;
- u64 volatile_id, persistent_id;
- char req_oplevel = 0, rsp_oplevel = 0;
- unsigned int oplock_change_type;
-
- volatile_id = req->VolatileFid;
- persistent_id = req->PersistentFid;
- req_oplevel = req->OplockLevel;
- ksmbd_debug(OPLOCK, "v_id %llu, p_id %llu request oplock level %d\n",
- volatile_id, persistent_id, req_oplevel);
-
- fp = ksmbd_lookup_fd_slow(work, volatile_id, persistent_id);
- if (!fp) {
- rsp->hdr.Status = STATUS_FILE_CLOSED;
- smb2_set_err_rsp(work);
- return;
- }
-
- opinfo = opinfo_get(fp);
- if (!opinfo) {
- pr_err("unexpected null oplock_info\n");
- rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
- smb2_set_err_rsp(work);
- ksmbd_fd_put(work, fp);
- return;
- }
-
- if (opinfo->level == SMB2_OPLOCK_LEVEL_NONE) {
- rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
- goto err_out;
- }
-
- if (opinfo->op_state == OPLOCK_STATE_NONE) {
- ksmbd_debug(SMB, "unexpected oplock state 0x%x\n", opinfo->op_state);
- rsp->hdr.Status = STATUS_UNSUCCESSFUL;
- goto err_out;
- }
-
- if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
- opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) &&
- (req_oplevel != SMB2_OPLOCK_LEVEL_II &&
- req_oplevel != SMB2_OPLOCK_LEVEL_NONE)) {
- err = STATUS_INVALID_OPLOCK_PROTOCOL;
- oplock_change_type = OPLOCK_WRITE_TO_NONE;
- } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II &&
- req_oplevel != SMB2_OPLOCK_LEVEL_NONE) {
- err = STATUS_INVALID_OPLOCK_PROTOCOL;
- oplock_change_type = OPLOCK_READ_TO_NONE;
- } else if (req_oplevel == SMB2_OPLOCK_LEVEL_II ||
- req_oplevel == SMB2_OPLOCK_LEVEL_NONE) {
- err = STATUS_INVALID_DEVICE_STATE;
- if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
- opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) &&
- req_oplevel == SMB2_OPLOCK_LEVEL_II) {
- oplock_change_type = OPLOCK_WRITE_TO_READ;
- } else if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
- opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) &&
- req_oplevel == SMB2_OPLOCK_LEVEL_NONE) {
- oplock_change_type = OPLOCK_WRITE_TO_NONE;
- } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II &&
- req_oplevel == SMB2_OPLOCK_LEVEL_NONE) {
- oplock_change_type = OPLOCK_READ_TO_NONE;
- } else {
- oplock_change_type = 0;
- }
- } else {
- oplock_change_type = 0;
- }
-
- switch (oplock_change_type) {
- case OPLOCK_WRITE_TO_READ:
- ret = opinfo_write_to_read(opinfo);
- rsp_oplevel = SMB2_OPLOCK_LEVEL_II;
- break;
- case OPLOCK_WRITE_TO_NONE:
- ret = opinfo_write_to_none(opinfo);
- rsp_oplevel = SMB2_OPLOCK_LEVEL_NONE;
- break;
- case OPLOCK_READ_TO_NONE:
- ret = opinfo_read_to_none(opinfo);
- rsp_oplevel = SMB2_OPLOCK_LEVEL_NONE;
- break;
- default:
- pr_err("unknown oplock change 0x%x -> 0x%x\n",
- opinfo->level, rsp_oplevel);
- }
-
- if (ret < 0) {
- rsp->hdr.Status = err;
- goto err_out;
- }
-
- opinfo_put(opinfo);
- ksmbd_fd_put(work, fp);
- opinfo->op_state = OPLOCK_STATE_NONE;
- wake_up_interruptible_all(&opinfo->oplock_q);
-
- rsp->StructureSize = cpu_to_le16(24);
- rsp->OplockLevel = rsp_oplevel;
- rsp->Reserved = 0;
- rsp->Reserved2 = 0;
- rsp->VolatileFid = volatile_id;
- rsp->PersistentFid = persistent_id;
- inc_rfc1001_len(work->response_buf, 24);
- return;
-
-err_out:
- opinfo->op_state = OPLOCK_STATE_NONE;
- wake_up_interruptible_all(&opinfo->oplock_q);
-
- opinfo_put(opinfo);
- ksmbd_fd_put(work, fp);
- smb2_set_err_rsp(work);
-}
-
-static int check_lease_state(struct lease *lease, __le32 req_state)
-{
- if ((lease->new_state ==
- (SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_HANDLE_CACHING_LE)) &&
- !(req_state & SMB2_LEASE_WRITE_CACHING_LE)) {
- lease->new_state = req_state;
- return 0;
- }
-
- if (lease->new_state == req_state)
- return 0;
-
- return 1;
-}
-
-/**
- * smb21_lease_break_ack() - handler for smb2.1 lease break command
- * @work: smb work containing lease break command buffer
- *
- * Return: 0
- */
-static void smb21_lease_break_ack(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_lease_ack *req = smb2_get_msg(work->request_buf);
- struct smb2_lease_ack *rsp = smb2_get_msg(work->response_buf);
- struct oplock_info *opinfo;
- __le32 err = 0;
- int ret = 0;
- unsigned int lease_change_type;
- __le32 lease_state;
- struct lease *lease;
-
- ksmbd_debug(OPLOCK, "smb21 lease break, lease state(0x%x)\n",
- le32_to_cpu(req->LeaseState));
- opinfo = lookup_lease_in_table(conn, req->LeaseKey);
- if (!opinfo) {
- ksmbd_debug(OPLOCK, "file not opened\n");
- smb2_set_err_rsp(work);
- rsp->hdr.Status = STATUS_UNSUCCESSFUL;
- return;
- }
- lease = opinfo->o_lease;
-
- if (opinfo->op_state == OPLOCK_STATE_NONE) {
- pr_err("unexpected lease break state 0x%x\n",
- opinfo->op_state);
- rsp->hdr.Status = STATUS_UNSUCCESSFUL;
- goto err_out;
- }
-
- if (check_lease_state(lease, req->LeaseState)) {
- rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED;
- ksmbd_debug(OPLOCK,
- "req lease state: 0x%x, expected state: 0x%x\n",
- req->LeaseState, lease->new_state);
- goto err_out;
- }
-
- if (!atomic_read(&opinfo->breaking_cnt)) {
- rsp->hdr.Status = STATUS_UNSUCCESSFUL;
- goto err_out;
- }
-
- /* check for bad lease state */
- if (req->LeaseState &
- (~(SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_HANDLE_CACHING_LE))) {
- err = STATUS_INVALID_OPLOCK_PROTOCOL;
- if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
- lease_change_type = OPLOCK_WRITE_TO_NONE;
- else
- lease_change_type = OPLOCK_READ_TO_NONE;
- ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n",
- le32_to_cpu(lease->state),
- le32_to_cpu(req->LeaseState));
- } else if (lease->state == SMB2_LEASE_READ_CACHING_LE &&
- req->LeaseState != SMB2_LEASE_NONE_LE) {
- err = STATUS_INVALID_OPLOCK_PROTOCOL;
- lease_change_type = OPLOCK_READ_TO_NONE;
- ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n",
- le32_to_cpu(lease->state),
- le32_to_cpu(req->LeaseState));
- } else {
- /* valid lease state changes */
- err = STATUS_INVALID_DEVICE_STATE;
- if (req->LeaseState == SMB2_LEASE_NONE_LE) {
- if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
- lease_change_type = OPLOCK_WRITE_TO_NONE;
- else
- lease_change_type = OPLOCK_READ_TO_NONE;
- } else if (req->LeaseState & SMB2_LEASE_READ_CACHING_LE) {
- if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
- lease_change_type = OPLOCK_WRITE_TO_READ;
- else
- lease_change_type = OPLOCK_READ_HANDLE_TO_READ;
- } else {
- lease_change_type = 0;
- }
- }
-
- switch (lease_change_type) {
- case OPLOCK_WRITE_TO_READ:
- ret = opinfo_write_to_read(opinfo);
- break;
- case OPLOCK_READ_HANDLE_TO_READ:
- ret = opinfo_read_handle_to_read(opinfo);
- break;
- case OPLOCK_WRITE_TO_NONE:
- ret = opinfo_write_to_none(opinfo);
- break;
- case OPLOCK_READ_TO_NONE:
- ret = opinfo_read_to_none(opinfo);
- break;
- default:
- ksmbd_debug(OPLOCK, "unknown lease change 0x%x -> 0x%x\n",
- le32_to_cpu(lease->state),
- le32_to_cpu(req->LeaseState));
- }
-
- lease_state = lease->state;
- opinfo->op_state = OPLOCK_STATE_NONE;
- wake_up_interruptible_all(&opinfo->oplock_q);
- atomic_dec(&opinfo->breaking_cnt);
- wake_up_interruptible_all(&opinfo->oplock_brk);
- opinfo_put(opinfo);
-
- if (ret < 0) {
- rsp->hdr.Status = err;
- goto err_out;
- }
-
- rsp->StructureSize = cpu_to_le16(36);
- rsp->Reserved = 0;
- rsp->Flags = 0;
- memcpy(rsp->LeaseKey, req->LeaseKey, 16);
- rsp->LeaseState = lease_state;
- rsp->LeaseDuration = 0;
- inc_rfc1001_len(work->response_buf, 36);
- return;
-
-err_out:
- opinfo->op_state = OPLOCK_STATE_NONE;
- wake_up_interruptible_all(&opinfo->oplock_q);
- atomic_dec(&opinfo->breaking_cnt);
- wake_up_interruptible_all(&opinfo->oplock_brk);
-
- opinfo_put(opinfo);
- smb2_set_err_rsp(work);
-}
-
-/**
- * smb2_oplock_break() - dispatcher for smb2.0 and 2.1 oplock/lease break
- * @work: smb work containing oplock/lease break command buffer
- *
- * Return: 0
- */
-int smb2_oplock_break(struct ksmbd_work *work)
-{
- struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
- struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
-
- switch (le16_to_cpu(req->StructureSize)) {
- case OP_BREAK_STRUCT_SIZE_20:
- smb20_oplock_break_ack(work);
- break;
- case OP_BREAK_STRUCT_SIZE_21:
- smb21_lease_break_ack(work);
- break;
- default:
- ksmbd_debug(OPLOCK, "invalid break cmd %d\n",
- le16_to_cpu(req->StructureSize));
- rsp->hdr.Status = STATUS_INVALID_PARAMETER;
- smb2_set_err_rsp(work);
- }
-
- return 0;
-}
-
-/**
- * smb2_notify() - handler for smb2 notify request
- * @work: smb work containing notify command buffer
- *
- * Return: 0
- */
-int smb2_notify(struct ksmbd_work *work)
-{
- struct smb2_change_notify_req *req;
- struct smb2_change_notify_rsp *rsp;
-
- WORK_BUFFERS(work, req, rsp);
-
- if (work->next_smb2_rcv_hdr_off && req->hdr.NextCommand) {
- rsp->hdr.Status = STATUS_INTERNAL_ERROR;
- smb2_set_err_rsp(work);
- return 0;
- }
-
- smb2_set_err_rsp(work);
- rsp->hdr.Status = STATUS_NOT_IMPLEMENTED;
- return 0;
-}
-
-/**
- * smb2_is_sign_req() - handler for checking packet signing status
- * @work: smb work containing notify command buffer
- * @command: SMB2 command id
- *
- * Return: true if packed is signed, false otherwise
- */
-bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command)
-{
- struct smb2_hdr *rcv_hdr2 = smb2_get_msg(work->request_buf);
-
- if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) &&
- command != SMB2_NEGOTIATE_HE &&
- command != SMB2_SESSION_SETUP_HE &&
- command != SMB2_OPLOCK_BREAK_HE)
- return true;
-
- return false;
-}
-
-/**
- * smb2_check_sign_req() - handler for req packet sign processing
- * @work: smb work containing notify command buffer
- *
- * Return: 1 on success, 0 otherwise
- */
-int smb2_check_sign_req(struct ksmbd_work *work)
-{
- struct smb2_hdr *hdr;
- char signature_req[SMB2_SIGNATURE_SIZE];
- char signature[SMB2_HMACSHA256_SIZE];
- struct kvec iov[1];
- size_t len;
-
- hdr = smb2_get_msg(work->request_buf);
- if (work->next_smb2_rcv_hdr_off)
- hdr = ksmbd_req_buf_next(work);
-
- if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
- len = get_rfc1002_len(work->request_buf);
- else if (hdr->NextCommand)
- len = le32_to_cpu(hdr->NextCommand);
- else
- len = get_rfc1002_len(work->request_buf) -
- work->next_smb2_rcv_hdr_off;
-
- memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE);
- memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
-
- iov[0].iov_base = (char *)&hdr->ProtocolId;
- iov[0].iov_len = len;
-
- if (ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1,
- signature))
- return 0;
-
- if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
- pr_err("bad smb2 signature\n");
- return 0;
- }
-
- return 1;
-}
-
-/**
- * smb2_set_sign_rsp() - handler for rsp packet sign processing
- * @work: smb work containing notify command buffer
- *
- */
-void smb2_set_sign_rsp(struct ksmbd_work *work)
-{
- struct smb2_hdr *hdr;
- struct smb2_hdr *req_hdr;
- char signature[SMB2_HMACSHA256_SIZE];
- struct kvec iov[2];
- size_t len;
- int n_vec = 1;
-
- hdr = smb2_get_msg(work->response_buf);
- if (work->next_smb2_rsp_hdr_off)
- hdr = ksmbd_resp_buf_next(work);
-
- req_hdr = ksmbd_req_buf_next(work);
-
- if (!work->next_smb2_rsp_hdr_off) {
- len = get_rfc1002_len(work->response_buf);
- if (req_hdr->NextCommand)
- len = ALIGN(len, 8);
- } else {
- len = get_rfc1002_len(work->response_buf) -
- work->next_smb2_rsp_hdr_off;
- len = ALIGN(len, 8);
- }
-
- if (req_hdr->NextCommand)
- hdr->NextCommand = cpu_to_le32(len);
-
- hdr->Flags |= SMB2_FLAGS_SIGNED;
- memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
-
- iov[0].iov_base = (char *)&hdr->ProtocolId;
- iov[0].iov_len = len;
-
- if (work->aux_payload_sz) {
- iov[0].iov_len -= work->aux_payload_sz;
-
- iov[1].iov_base = work->aux_payload_buf;
- iov[1].iov_len = work->aux_payload_sz;
- n_vec++;
- }
-
- if (!ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec,
- signature))
- memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
-}
-
-/**
- * smb3_check_sign_req() - handler for req packet sign processing
- * @work: smb work containing notify command buffer
- *
- * Return: 1 on success, 0 otherwise
- */
-int smb3_check_sign_req(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- char *signing_key;
- struct smb2_hdr *hdr;
- struct channel *chann;
- char signature_req[SMB2_SIGNATURE_SIZE];
- char signature[SMB2_CMACAES_SIZE];
- struct kvec iov[1];
- size_t len;
-
- hdr = smb2_get_msg(work->request_buf);
- if (work->next_smb2_rcv_hdr_off)
- hdr = ksmbd_req_buf_next(work);
-
- if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
- len = get_rfc1002_len(work->request_buf);
- else if (hdr->NextCommand)
- len = le32_to_cpu(hdr->NextCommand);
- else
- len = get_rfc1002_len(work->request_buf) -
- work->next_smb2_rcv_hdr_off;
-
- if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
- signing_key = work->sess->smb3signingkey;
- } else {
- chann = lookup_chann_list(work->sess, conn);
- if (!chann) {
- return 0;
- }
- signing_key = chann->smb3signingkey;
- }
-
- if (!signing_key) {
- pr_err("SMB3 signing key is not generated\n");
- return 0;
- }
-
- memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE);
- memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
- iov[0].iov_base = (char *)&hdr->ProtocolId;
- iov[0].iov_len = len;
-
- if (ksmbd_sign_smb3_pdu(conn, signing_key, iov, 1, signature))
- return 0;
-
- if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
- pr_err("bad smb2 signature\n");
- return 0;
- }
-
- return 1;
-}
-
-/**
- * smb3_set_sign_rsp() - handler for rsp packet sign processing
- * @work: smb work containing notify command buffer
- *
- */
-void smb3_set_sign_rsp(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct smb2_hdr *req_hdr, *hdr;
- struct channel *chann;
- char signature[SMB2_CMACAES_SIZE];
- struct kvec iov[2];
- int n_vec = 1;
- size_t len;
- char *signing_key;
-
- hdr = smb2_get_msg(work->response_buf);
- if (work->next_smb2_rsp_hdr_off)
- hdr = ksmbd_resp_buf_next(work);
-
- req_hdr = ksmbd_req_buf_next(work);
-
- if (!work->next_smb2_rsp_hdr_off) {
- len = get_rfc1002_len(work->response_buf);
- if (req_hdr->NextCommand)
- len = ALIGN(len, 8);
- } else {
- len = get_rfc1002_len(work->response_buf) -
- work->next_smb2_rsp_hdr_off;
- len = ALIGN(len, 8);
- }
-
- if (conn->binding == false &&
- le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
- signing_key = work->sess->smb3signingkey;
- } else {
- chann = lookup_chann_list(work->sess, work->conn);
- if (!chann) {
- return;
- }
- signing_key = chann->smb3signingkey;
- }
-
- if (!signing_key)
- return;
-
- if (req_hdr->NextCommand)
- hdr->NextCommand = cpu_to_le32(len);
-
- hdr->Flags |= SMB2_FLAGS_SIGNED;
- memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
- iov[0].iov_base = (char *)&hdr->ProtocolId;
- iov[0].iov_len = len;
- if (work->aux_payload_sz) {
- iov[0].iov_len -= work->aux_payload_sz;
- iov[1].iov_base = work->aux_payload_buf;
- iov[1].iov_len = work->aux_payload_sz;
- n_vec++;
- }
-
- if (!ksmbd_sign_smb3_pdu(conn, signing_key, iov, n_vec, signature))
- memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
-}
-
-/**
- * smb3_preauth_hash_rsp() - handler for computing preauth hash on response
- * @work: smb work containing response buffer
- *
- */
-void smb3_preauth_hash_rsp(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct ksmbd_session *sess = work->sess;
- struct smb2_hdr *req, *rsp;
-
- if (conn->dialect != SMB311_PROT_ID)
- return;
-
- WORK_BUFFERS(work, req, rsp);
-
- if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE &&
- conn->preauth_info)
- ksmbd_gen_preauth_integrity_hash(conn, work->response_buf,
- conn->preauth_info->Preauth_HashValue);
-
- if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && sess) {
- __u8 *hash_value;
-
- if (conn->binding) {
- struct preauth_session *preauth_sess;
-
- preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
- if (!preauth_sess)
- return;
- hash_value = preauth_sess->Preauth_HashValue;
- } else {
- hash_value = sess->Preauth_HashValue;
- if (!hash_value)
- return;
- }
- ksmbd_gen_preauth_integrity_hash(conn, work->response_buf,
- hash_value);
- }
-}
-
-static void fill_transform_hdr(void *tr_buf, char *old_buf, __le16 cipher_type)
-{
- struct smb2_transform_hdr *tr_hdr = tr_buf + 4;
- struct smb2_hdr *hdr = smb2_get_msg(old_buf);
- unsigned int orig_len = get_rfc1002_len(old_buf);
-
- /* tr_buf must be cleared by the caller */
- tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
- tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
- tr_hdr->Flags = cpu_to_le16(TRANSFORM_FLAG_ENCRYPTED);
- if (cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
- cipher_type == SMB2_ENCRYPTION_AES256_GCM)
- get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
- else
- get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
- memcpy(&tr_hdr->SessionId, &hdr->SessionId, 8);
- inc_rfc1001_len(tr_buf, sizeof(struct smb2_transform_hdr));
- inc_rfc1001_len(tr_buf, orig_len);
-}
-
-int smb3_encrypt_resp(struct ksmbd_work *work)
-{
- char *buf = work->response_buf;
- struct kvec iov[3];
- int rc = -ENOMEM;
- int buf_size = 0, rq_nvec = 2 + (work->aux_payload_sz ? 1 : 0);
-
- if (ARRAY_SIZE(iov) < rq_nvec)
- return -ENOMEM;
-
- work->tr_buf = kzalloc(sizeof(struct smb2_transform_hdr) + 4, GFP_KERNEL);
- if (!work->tr_buf)
- return rc;
-
- /* fill transform header */
- fill_transform_hdr(work->tr_buf, buf, work->conn->cipher_type);
-
- iov[0].iov_base = work->tr_buf;
- iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
- buf_size += iov[0].iov_len - 4;
-
- iov[1].iov_base = buf + 4;
- iov[1].iov_len = get_rfc1002_len(buf);
- if (work->aux_payload_sz) {
- iov[1].iov_len = work->resp_hdr_sz - 4;
-
- iov[2].iov_base = work->aux_payload_buf;
- iov[2].iov_len = work->aux_payload_sz;
- buf_size += iov[2].iov_len;
- }
- buf_size += iov[1].iov_len;
- work->resp_hdr_sz = iov[1].iov_len;
-
- rc = ksmbd_crypt_message(work, iov, rq_nvec, 1);
- if (rc)
- return rc;
-
- memmove(buf, iov[1].iov_base, iov[1].iov_len);
- *(__be32 *)work->tr_buf = cpu_to_be32(buf_size);
-
- return rc;
-}
-
-bool smb3_is_transform_hdr(void *buf)
-{
- struct smb2_transform_hdr *trhdr = smb2_get_msg(buf);
-
- return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
-}
-
-int smb3_decrypt_req(struct ksmbd_work *work)
-{
- struct ksmbd_session *sess;
- char *buf = work->request_buf;
- unsigned int pdu_length = get_rfc1002_len(buf);
- struct kvec iov[2];
- int buf_data_size = pdu_length - sizeof(struct smb2_transform_hdr);
- struct smb2_transform_hdr *tr_hdr = smb2_get_msg(buf);
- int rc = 0;
-
- if (buf_data_size < sizeof(struct smb2_hdr)) {
- pr_err("Transform message is too small (%u)\n",
- pdu_length);
- return -ECONNABORTED;
- }
-
- if (buf_data_size < le32_to_cpu(tr_hdr->OriginalMessageSize)) {
- pr_err("Transform message is broken\n");
- return -ECONNABORTED;
- }
-
- sess = ksmbd_session_lookup_all(work->conn, le64_to_cpu(tr_hdr->SessionId));
- if (!sess) {
- pr_err("invalid session id(%llx) in transform header\n",
- le64_to_cpu(tr_hdr->SessionId));
- return -ECONNABORTED;
- }
-
- iov[0].iov_base = buf;
- iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
- iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr) + 4;
- iov[1].iov_len = buf_data_size;
- rc = ksmbd_crypt_message(work, iov, 2, 0);
- if (rc)
- return rc;
-
- memmove(buf + 4, iov[1].iov_base, buf_data_size);
- *(__be32 *)buf = cpu_to_be32(buf_data_size);
-
- return rc;
-}
-
-bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- struct ksmbd_session *sess = work->sess;
- struct smb2_hdr *rsp = smb2_get_msg(work->response_buf);
-
- if (conn->dialect < SMB30_PROT_ID)
- return false;
-
- if (work->next_smb2_rcv_hdr_off)
- rsp = ksmbd_resp_buf_next(work);
-
- if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE &&
- sess->user && !user_guest(sess->user) &&
- rsp->Status == STATUS_SUCCESS)
- return true;
- return false;
-}
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
deleted file mode 100644
index dd10f8031606..000000000000
--- a/fs/ksmbd/smb2pdu.h
+++ /dev/null
@@ -1,536 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef _SMB2PDU_H
-#define _SMB2PDU_H
-
-#include "ntlmssp.h"
-#include "smbacl.h"
-
-/*Create Action Flags*/
-#define FILE_SUPERSEDED 0x00000000
-#define FILE_OPENED 0x00000001
-#define FILE_CREATED 0x00000002
-#define FILE_OVERWRITTEN 0x00000003
-
-/* SMB2 Max Credits */
-#define SMB2_MAX_CREDITS 8192
-
-/* BB FIXME - analyze following length BB */
-#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
-
-#define SMB21_DEFAULT_IOSIZE (1024 * 1024)
-#define SMB3_DEFAULT_TRANS_SIZE (1024 * 1024)
-#define SMB3_MIN_IOSIZE (64 * 1024)
-#define SMB3_MAX_IOSIZE (8 * 1024 * 1024)
-#define SMB3_MAX_MSGSIZE (4 * 4096)
-
-/*
- * Definitions for SMB2 Protocol Data Units (network frames)
- *
- * See MS-SMB2.PDF specification for protocol details.
- * The Naming convention is the lower case version of the SMB2
- * command code name for the struct. Note that structures must be packed.
- *
- */
-
-struct preauth_integrity_info {
- /* PreAuth integrity Hash ID */
- __le16 Preauth_HashId;
- /* PreAuth integrity Hash Value */
- __u8 Preauth_HashValue[SMB2_PREAUTH_HASH_SIZE];
-};
-
-/* offset is sizeof smb2_negotiate_rsp but rounded up to 8 bytes. */
-#ifdef CONFIG_SMB_SERVER_KERBEROS5
-/* sizeof(struct smb2_negotiate_rsp) =
- * header(64) + response(64) + GSS_LENGTH(96) + GSS_PADDING(0)
- */
-#define OFFSET_OF_NEG_CONTEXT 0xe0
-#else
-/* sizeof(struct smb2_negotiate_rsp) =
- * header(64) + response(64) + GSS_LENGTH(74) + GSS_PADDING(6)
- */
-#define OFFSET_OF_NEG_CONTEXT 0xd0
-#endif
-
-#define SMB2_SESSION_EXPIRED (0)
-#define SMB2_SESSION_IN_PROGRESS BIT(0)
-#define SMB2_SESSION_VALID BIT(1)
-
-#define SMB2_SESSION_TIMEOUT (10 * HZ)
-
-struct create_durable_req_v2 {
- struct create_context ccontext;
- __u8 Name[8];
- __le32 Timeout;
- __le32 Flags;
- __u8 Reserved[8];
- __u8 CreateGuid[16];
-} __packed;
-
-struct create_durable_reconn_req {
- struct create_context ccontext;
- __u8 Name[8];
- union {
- __u8 Reserved[16];
- struct {
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- } Fid;
- } Data;
-} __packed;
-
-struct create_durable_reconn_v2_req {
- struct create_context ccontext;
- __u8 Name[8];
- struct {
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- } Fid;
- __u8 CreateGuid[16];
- __le32 Flags;
-} __packed;
-
-struct create_app_inst_id {
- struct create_context ccontext;
- __u8 Name[8];
- __u8 Reserved[8];
- __u8 AppInstanceId[16];
-} __packed;
-
-struct create_app_inst_id_vers {
- struct create_context ccontext;
- __u8 Name[8];
- __u8 Reserved[2];
- __u8 Padding[4];
- __le64 AppInstanceVersionHigh;
- __le64 AppInstanceVersionLow;
-} __packed;
-
-struct create_mxac_req {
- struct create_context ccontext;
- __u8 Name[8];
- __le64 Timestamp;
-} __packed;
-
-struct create_alloc_size_req {
- struct create_context ccontext;
- __u8 Name[8];
- __le64 AllocationSize;
-} __packed;
-
-struct create_durable_rsp {
- struct create_context ccontext;
- __u8 Name[8];
- union {
- __u8 Reserved[8];
- __u64 data;
- } Data;
-} __packed;
-
-struct create_durable_v2_rsp {
- struct create_context ccontext;
- __u8 Name[8];
- __le32 Timeout;
- __le32 Flags;
-} __packed;
-
-struct create_mxac_rsp {
- struct create_context ccontext;
- __u8 Name[8];
- __le32 QueryStatus;
- __le32 MaximalAccess;
-} __packed;
-
-struct create_disk_id_rsp {
- struct create_context ccontext;
- __u8 Name[8];
- __le64 DiskFileId;
- __le64 VolumeId;
- __u8 Reserved[16];
-} __packed;
-
-/* equivalent of the contents of SMB3.1.1 POSIX open context response */
-struct create_posix_rsp {
- struct create_context ccontext;
- __u8 Name[16];
- __le32 nlink;
- __le32 reparse_tag;
- __le32 mode;
- /* SidBuffer contain two sids(Domain sid(28), UNIX group sid(16)) */
- u8 SidBuffer[44];
-} __packed;
-
-struct smb2_buffer_desc_v1 {
- __le64 offset;
- __le32 token;
- __le32 length;
-} __packed;
-
-#define SMB2_0_IOCTL_IS_FSCTL 0x00000001
-
-struct smb_sockaddr_in {
- __be16 Port;
- __be32 IPv4address;
- __u8 Reserved[8];
-} __packed;
-
-struct smb_sockaddr_in6 {
- __be16 Port;
- __be32 FlowInfo;
- __u8 IPv6address[16];
- __be32 ScopeId;
-} __packed;
-
-#define INTERNETWORK 0x0002
-#define INTERNETWORKV6 0x0017
-
-struct sockaddr_storage_rsp {
- __le16 Family;
- union {
- struct smb_sockaddr_in addr4;
- struct smb_sockaddr_in6 addr6;
- };
-} __packed;
-
-#define RSS_CAPABLE 0x00000001
-#define RDMA_CAPABLE 0x00000002
-
-struct network_interface_info_ioctl_rsp {
- __le32 Next; /* next interface. zero if this is last one */
- __le32 IfIndex;
- __le32 Capability; /* RSS or RDMA Capable */
- __le32 Reserved;
- __le64 LinkSpeed;
- char SockAddr_Storage[128];
-} __packed;
-
-struct file_object_buf_type1_ioctl_rsp {
- __u8 ObjectId[16];
- __u8 BirthVolumeId[16];
- __u8 BirthObjectId[16];
- __u8 DomainId[16];
-} __packed;
-
-struct resume_key_ioctl_rsp {
- __u64 ResumeKey[3];
- __le32 ContextLength;
- __u8 Context[4]; /* ignored, Windows sets to 4 bytes of zero */
-} __packed;
-
-struct copychunk_ioctl_req {
- __le64 ResumeKey[3];
- __le32 ChunkCount;
- __le32 Reserved;
- __u8 Chunks[1]; /* array of srv_copychunk */
-} __packed;
-
-struct srv_copychunk {
- __le64 SourceOffset;
- __le64 TargetOffset;
- __le32 Length;
- __le32 Reserved;
-} __packed;
-
-struct copychunk_ioctl_rsp {
- __le32 ChunksWritten;
- __le32 ChunkBytesWritten;
- __le32 TotalBytesWritten;
-} __packed;
-
-struct file_sparse {
- __u8 SetSparse;
-} __packed;
-
-/* FILE Info response size */
-#define FILE_DIRECTORY_INFORMATION_SIZE 1
-#define FILE_FULL_DIRECTORY_INFORMATION_SIZE 2
-#define FILE_BOTH_DIRECTORY_INFORMATION_SIZE 3
-#define FILE_BASIC_INFORMATION_SIZE 40
-#define FILE_STANDARD_INFORMATION_SIZE 24
-#define FILE_INTERNAL_INFORMATION_SIZE 8
-#define FILE_EA_INFORMATION_SIZE 4
-#define FILE_ACCESS_INFORMATION_SIZE 4
-#define FILE_NAME_INFORMATION_SIZE 9
-#define FILE_RENAME_INFORMATION_SIZE 10
-#define FILE_LINK_INFORMATION_SIZE 11
-#define FILE_NAMES_INFORMATION_SIZE 12
-#define FILE_DISPOSITION_INFORMATION_SIZE 13
-#define FILE_POSITION_INFORMATION_SIZE 14
-#define FILE_FULL_EA_INFORMATION_SIZE 15
-#define FILE_MODE_INFORMATION_SIZE 4
-#define FILE_ALIGNMENT_INFORMATION_SIZE 4
-#define FILE_ALL_INFORMATION_SIZE 104
-#define FILE_ALLOCATION_INFORMATION_SIZE 19
-#define FILE_END_OF_FILE_INFORMATION_SIZE 20
-#define FILE_ALTERNATE_NAME_INFORMATION_SIZE 8
-#define FILE_STREAM_INFORMATION_SIZE 32
-#define FILE_PIPE_INFORMATION_SIZE 23
-#define FILE_PIPE_LOCAL_INFORMATION_SIZE 24
-#define FILE_PIPE_REMOTE_INFORMATION_SIZE 25
-#define FILE_MAILSLOT_QUERY_INFORMATION_SIZE 26
-#define FILE_MAILSLOT_SET_INFORMATION_SIZE 27
-#define FILE_COMPRESSION_INFORMATION_SIZE 16
-#define FILE_OBJECT_ID_INFORMATION_SIZE 29
-/* Number 30 not defined in documents */
-#define FILE_MOVE_CLUSTER_INFORMATION_SIZE 31
-#define FILE_QUOTA_INFORMATION_SIZE 32
-#define FILE_REPARSE_POINT_INFORMATION_SIZE 33
-#define FILE_NETWORK_OPEN_INFORMATION_SIZE 56
-#define FILE_ATTRIBUTE_TAG_INFORMATION_SIZE 8
-
-/* FS Info response size */
-#define FS_DEVICE_INFORMATION_SIZE 8
-#define FS_ATTRIBUTE_INFORMATION_SIZE 16
-#define FS_VOLUME_INFORMATION_SIZE 24
-#define FS_SIZE_INFORMATION_SIZE 24
-#define FS_FULL_SIZE_INFORMATION_SIZE 32
-#define FS_SECTOR_SIZE_INFORMATION_SIZE 28
-#define FS_OBJECT_ID_INFORMATION_SIZE 64
-#define FS_CONTROL_INFORMATION_SIZE 48
-#define FS_POSIX_INFORMATION_SIZE 56
-
-/* FS_ATTRIBUTE_File_System_Name */
-#define FS_TYPE_SUPPORT_SIZE 44
-struct fs_type_info {
- char *fs_name;
- long magic_number;
-} __packed;
-
-/*
- * PDU query infolevel structure definitions
- * BB consider moving to a different header
- */
-
-struct smb2_file_access_info {
- __le32 AccessFlags;
-} __packed;
-
-struct smb2_file_alignment_info {
- __le32 AlignmentRequirement;
-} __packed;
-
-struct smb2_file_basic_info { /* data block encoding of response to level 18 */
- __le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le32 Attributes;
- __u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */
-} __packed;
-
-struct smb2_file_alt_name_info {
- __le32 FileNameLength;
- char FileName[];
-} __packed;
-
-struct smb2_file_stream_info {
- __le32 NextEntryOffset;
- __le32 StreamNameLength;
- __le64 StreamSize;
- __le64 StreamAllocationSize;
- char StreamName[];
-} __packed;
-
-struct smb2_file_ntwrk_info {
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 AllocationSize;
- __le64 EndOfFile;
- __le32 Attributes;
- __le32 Reserved;
-} __packed;
-
-struct smb2_file_standard_info {
- __le64 AllocationSize;
- __le64 EndOfFile;
- __le32 NumberOfLinks; /* hard links */
- __u8 DeletePending;
- __u8 Directory;
- __le16 Reserved;
-} __packed; /* level 18 Query */
-
-struct smb2_file_ea_info {
- __le32 EASize;
-} __packed;
-
-struct smb2_file_alloc_info {
- __le64 AllocationSize;
-} __packed;
-
-struct smb2_file_disposition_info {
- __u8 DeletePending;
-} __packed;
-
-struct smb2_file_pos_info {
- __le64 CurrentByteOffset;
-} __packed;
-
-#define FILE_MODE_INFO_MASK cpu_to_le32(0x0000100e)
-
-struct smb2_file_mode_info {
- __le32 Mode;
-} __packed;
-
-#define COMPRESSION_FORMAT_NONE 0x0000
-#define COMPRESSION_FORMAT_LZNT1 0x0002
-
-struct smb2_file_comp_info {
- __le64 CompressedFileSize;
- __le16 CompressionFormat;
- __u8 CompressionUnitShift;
- __u8 ChunkShift;
- __u8 ClusterShift;
- __u8 Reserved[3];
-} __packed;
-
-struct smb2_file_attr_tag_info {
- __le32 FileAttributes;
- __le32 ReparseTag;
-} __packed;
-
-#define SL_RESTART_SCAN 0x00000001
-#define SL_RETURN_SINGLE_ENTRY 0x00000002
-#define SL_INDEX_SPECIFIED 0x00000004
-
-struct smb2_ea_info_req {
- __le32 NextEntryOffset;
- __u8 EaNameLength;
- char name[1];
-} __packed; /* level 15 Query */
-
-struct smb2_ea_info {
- __le32 NextEntryOffset;
- __u8 Flags;
- __u8 EaNameLength;
- __le16 EaValueLength;
- char name[1];
- /* optionally followed by value */
-} __packed; /* level 15 Query */
-
-struct create_ea_buf_req {
- struct create_context ccontext;
- __u8 Name[8];
- struct smb2_ea_info ea;
-} __packed;
-
-struct create_sd_buf_req {
- struct create_context ccontext;
- __u8 Name[8];
- struct smb_ntsd ntsd;
-} __packed;
-
-struct smb2_posix_info {
- __le32 NextEntryOffset;
- __u32 Ignored;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 DosAttributes;
- __le64 Inode;
- __le32 DeviceId;
- __le32 Zero;
- /* beginning of POSIX Create Context Response */
- __le32 HardLinks;
- __le32 ReparseTag;
- __le32 Mode;
- /* SidBuffer contain two sids (UNIX user sid(16), UNIX group sid(16)) */
- u8 SidBuffer[32];
- __le32 name_len;
- u8 name[1];
- /*
- * var sized owner SID
- * var sized group SID
- * le32 filenamelength
- * u8 filename[]
- */
-} __packed;
-
-/* functions */
-void init_smb2_1_server(struct ksmbd_conn *conn);
-void init_smb3_0_server(struct ksmbd_conn *conn);
-void init_smb3_02_server(struct ksmbd_conn *conn);
-int init_smb3_11_server(struct ksmbd_conn *conn);
-
-void init_smb2_max_read_size(unsigned int sz);
-void init_smb2_max_write_size(unsigned int sz);
-void init_smb2_max_trans_size(unsigned int sz);
-void init_smb2_max_credits(unsigned int sz);
-
-bool is_smb2_neg_cmd(struct ksmbd_work *work);
-bool is_smb2_rsp(struct ksmbd_work *work);
-
-u16 get_smb2_cmd_val(struct ksmbd_work *work);
-void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err);
-int init_smb2_rsp_hdr(struct ksmbd_work *work);
-int smb2_allocate_rsp_buf(struct ksmbd_work *work);
-bool is_chained_smb2_message(struct ksmbd_work *work);
-int init_smb2_neg_rsp(struct ksmbd_work *work);
-void smb2_set_err_rsp(struct ksmbd_work *work);
-int smb2_check_user_session(struct ksmbd_work *work);
-int smb2_get_ksmbd_tcon(struct ksmbd_work *work);
-bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command);
-int smb2_check_sign_req(struct ksmbd_work *work);
-void smb2_set_sign_rsp(struct ksmbd_work *work);
-int smb3_check_sign_req(struct ksmbd_work *work);
-void smb3_set_sign_rsp(struct ksmbd_work *work);
-int find_matching_smb2_dialect(int start_index, __le16 *cli_dialects,
- __le16 dialects_count);
-struct file_lock *smb_flock_init(struct file *f);
-int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
- void **arg);
-void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
-struct channel *lookup_chann_list(struct ksmbd_session *sess,
- struct ksmbd_conn *conn);
-void smb3_preauth_hash_rsp(struct ksmbd_work *work);
-bool smb3_is_transform_hdr(void *buf);
-int smb3_decrypt_req(struct ksmbd_work *work);
-int smb3_encrypt_resp(struct ksmbd_work *work);
-bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work);
-int smb2_set_rsp_credits(struct ksmbd_work *work);
-bool smb3_encryption_negotiated(struct ksmbd_conn *conn);
-
-/* smb2 misc functions */
-int ksmbd_smb2_check_message(struct ksmbd_work *work);
-
-/* smb2 command handlers */
-int smb2_handle_negotiate(struct ksmbd_work *work);
-int smb2_negotiate_request(struct ksmbd_work *work);
-int smb2_sess_setup(struct ksmbd_work *work);
-int smb2_tree_connect(struct ksmbd_work *work);
-int smb2_tree_disconnect(struct ksmbd_work *work);
-int smb2_session_logoff(struct ksmbd_work *work);
-int smb2_open(struct ksmbd_work *work);
-int smb2_query_info(struct ksmbd_work *work);
-int smb2_query_dir(struct ksmbd_work *work);
-int smb2_close(struct ksmbd_work *work);
-int smb2_echo(struct ksmbd_work *work);
-int smb2_set_info(struct ksmbd_work *work);
-int smb2_read(struct ksmbd_work *work);
-int smb2_write(struct ksmbd_work *work);
-int smb2_flush(struct ksmbd_work *work);
-int smb2_cancel(struct ksmbd_work *work);
-int smb2_lock(struct ksmbd_work *work);
-int smb2_ioctl(struct ksmbd_work *work);
-int smb2_oplock_break(struct ksmbd_work *work);
-int smb2_notify(struct ksmbd_work *ksmbd_work);
-
-/*
- * Get the body of the smb2 message excluding the 4 byte rfc1002 headers
- * from request/response buffer.
- */
-static inline void *smb2_get_msg(void *buf)
-{
- return buf + 4;
-}
-
-#endif /* _SMB2PDU_H */
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
deleted file mode 100644
index 05d7f3e910bf..000000000000
--- a/fs/ksmbd/smb_common.c
+++ /dev/null
@@ -1,797 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- * Copyright (C) 2018 Namjae Jeon <linkinjeon@kernel.org>
- */
-
-#include <linux/user_namespace.h>
-
-#include "smb_common.h"
-#include "server.h"
-#include "misc.h"
-#include "smbstatus.h"
-#include "connection.h"
-#include "ksmbd_work.h"
-#include "mgmt/user_session.h"
-#include "mgmt/user_config.h"
-#include "mgmt/tree_connect.h"
-#include "mgmt/share_config.h"
-
-/*for shortname implementation */
-static const char basechars[43] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
-#define MANGLE_BASE (sizeof(basechars) / sizeof(char) - 1)
-#define MAGIC_CHAR '~'
-#define PERIOD '.'
-#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
-
-struct smb_protocol {
- int index;
- char *name;
- char *prot;
- __u16 prot_id;
-};
-
-static struct smb_protocol smb1_protos[] = {
- {
- SMB21_PROT,
- "\2SMB 2.1",
- "SMB2_10",
- SMB21_PROT_ID
- },
- {
- SMB2X_PROT,
- "\2SMB 2.???",
- "SMB2_22",
- SMB2X_PROT_ID
- },
-};
-
-static struct smb_protocol smb2_protos[] = {
- {
- SMB21_PROT,
- "\2SMB 2.1",
- "SMB2_10",
- SMB21_PROT_ID
- },
- {
- SMB30_PROT,
- "\2SMB 3.0",
- "SMB3_00",
- SMB30_PROT_ID
- },
- {
- SMB302_PROT,
- "\2SMB 3.02",
- "SMB3_02",
- SMB302_PROT_ID
- },
- {
- SMB311_PROT,
- "\2SMB 3.1.1",
- "SMB3_11",
- SMB311_PROT_ID
- },
-};
-
-unsigned int ksmbd_server_side_copy_max_chunk_count(void)
-{
- return 256;
-}
-
-unsigned int ksmbd_server_side_copy_max_chunk_size(void)
-{
- return (2U << 30) - 1;
-}
-
-unsigned int ksmbd_server_side_copy_max_total_size(void)
-{
- return (2U << 30) - 1;
-}
-
-inline int ksmbd_min_protocol(void)
-{
- return SMB21_PROT;
-}
-
-inline int ksmbd_max_protocol(void)
-{
- return SMB311_PROT;
-}
-
-int ksmbd_lookup_protocol_idx(char *str)
-{
- int offt = ARRAY_SIZE(smb1_protos) - 1;
- int len = strlen(str);
-
- while (offt >= 0) {
- if (!strncmp(str, smb1_protos[offt].prot, len)) {
- ksmbd_debug(SMB, "selected %s dialect idx = %d\n",
- smb1_protos[offt].prot, offt);
- return smb1_protos[offt].index;
- }
- offt--;
- }
-
- offt = ARRAY_SIZE(smb2_protos) - 1;
- while (offt >= 0) {
- if (!strncmp(str, smb2_protos[offt].prot, len)) {
- ksmbd_debug(SMB, "selected %s dialect idx = %d\n",
- smb2_protos[offt].prot, offt);
- return smb2_protos[offt].index;
- }
- offt--;
- }
- return -1;
-}
-
-/**
- * ksmbd_verify_smb_message() - check for valid smb2 request header
- * @work: smb work
- *
- * check for valid smb signature and packet direction(request/response)
- *
- * Return: 0 on success, otherwise -EINVAL
- */
-int ksmbd_verify_smb_message(struct ksmbd_work *work)
-{
- struct smb2_hdr *smb2_hdr = ksmbd_req_buf_next(work);
- struct smb_hdr *hdr;
-
- if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER)
- return ksmbd_smb2_check_message(work);
-
- hdr = work->request_buf;
- if (*(__le32 *)hdr->Protocol == SMB1_PROTO_NUMBER &&
- hdr->Command == SMB_COM_NEGOTIATE) {
- work->conn->outstanding_credits++;
- return 0;
- }
-
- return -EINVAL;
-}
-
-/**
- * ksmbd_smb_request() - check for valid smb request type
- * @conn: connection instance
- *
- * Return: true on success, otherwise false
- */
-bool ksmbd_smb_request(struct ksmbd_conn *conn)
-{
- __le32 *proto = (__le32 *)smb2_get_msg(conn->request_buf);
-
- if (*proto == SMB2_COMPRESSION_TRANSFORM_ID) {
- pr_err_ratelimited("smb2 compression not support yet");
- return false;
- }
-
- if (*proto != SMB1_PROTO_NUMBER &&
- *proto != SMB2_PROTO_NUMBER &&
- *proto != SMB2_TRANSFORM_PROTO_NUM)
- return false;
-
- return true;
-}
-
-static bool supported_protocol(int idx)
-{
- if (idx == SMB2X_PROT &&
- (server_conf.min_protocol >= SMB21_PROT ||
- server_conf.max_protocol <= SMB311_PROT))
- return true;
-
- return (server_conf.min_protocol <= idx &&
- idx <= server_conf.max_protocol);
-}
-
-static char *next_dialect(char *dialect, int *next_off, int bcount)
-{
- dialect = dialect + *next_off;
- *next_off = strnlen(dialect, bcount);
- if (dialect[*next_off] != '\0')
- return NULL;
- return dialect;
-}
-
-static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count)
-{
- int i, seq_num, bcount, next;
- char *dialect;
-
- for (i = ARRAY_SIZE(smb1_protos) - 1; i >= 0; i--) {
- seq_num = 0;
- next = 0;
- dialect = cli_dialects;
- bcount = le16_to_cpu(byte_count);
- do {
- dialect = next_dialect(dialect, &next, bcount);
- if (!dialect)
- break;
- ksmbd_debug(SMB, "client requested dialect %s\n",
- dialect);
- if (!strcmp(dialect, smb1_protos[i].name)) {
- if (supported_protocol(smb1_protos[i].index)) {
- ksmbd_debug(SMB,
- "selected %s dialect\n",
- smb1_protos[i].name);
- if (smb1_protos[i].index == SMB1_PROT)
- return seq_num;
- return smb1_protos[i].prot_id;
- }
- }
- seq_num++;
- bcount -= (++next);
- } while (bcount > 0);
- }
-
- return BAD_PROT_ID;
-}
-
-int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)
-{
- int i;
- int count;
-
- for (i = ARRAY_SIZE(smb2_protos) - 1; i >= 0; i--) {
- count = le16_to_cpu(dialects_count);
- while (--count >= 0) {
- ksmbd_debug(SMB, "client requested dialect 0x%x\n",
- le16_to_cpu(cli_dialects[count]));
- if (le16_to_cpu(cli_dialects[count]) !=
- smb2_protos[i].prot_id)
- continue;
-
- if (supported_protocol(smb2_protos[i].index)) {
- ksmbd_debug(SMB, "selected %s dialect\n",
- smb2_protos[i].name);
- return smb2_protos[i].prot_id;
- }
- }
- }
-
- return BAD_PROT_ID;
-}
-
-static int ksmbd_negotiate_smb_dialect(void *buf)
-{
- int smb_buf_length = get_rfc1002_len(buf);
- __le32 proto = ((struct smb2_hdr *)smb2_get_msg(buf))->ProtocolId;
-
- if (proto == SMB2_PROTO_NUMBER) {
- struct smb2_negotiate_req *req;
- int smb2_neg_size =
- offsetof(struct smb2_negotiate_req, Dialects);
-
- req = (struct smb2_negotiate_req *)smb2_get_msg(buf);
- if (smb2_neg_size > smb_buf_length)
- goto err_out;
-
- if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) >
- smb_buf_length)
- goto err_out;
-
- return ksmbd_lookup_dialect_by_id(req->Dialects,
- req->DialectCount);
- }
-
- proto = *(__le32 *)((struct smb_hdr *)buf)->Protocol;
- if (proto == SMB1_PROTO_NUMBER) {
- struct smb_negotiate_req *req;
-
- req = (struct smb_negotiate_req *)buf;
- if (le16_to_cpu(req->ByteCount) < 2)
- goto err_out;
-
- if (offsetof(struct smb_negotiate_req, DialectsArray) - 4 +
- le16_to_cpu(req->ByteCount) > smb_buf_length) {
- goto err_out;
- }
-
- return ksmbd_lookup_dialect_by_name(req->DialectsArray,
- req->ByteCount);
- }
-
-err_out:
- return BAD_PROT_ID;
-}
-
-#define SMB_COM_NEGOTIATE_EX 0x0
-
-/**
- * get_smb1_cmd_val() - get smb command value from smb header
- * @work: smb work containing smb header
- *
- * Return: smb command value
- */
-static u16 get_smb1_cmd_val(struct ksmbd_work *work)
-{
- return SMB_COM_NEGOTIATE_EX;
-}
-
-/**
- * init_smb1_rsp_hdr() - initialize smb negotiate response header
- * @work: smb work containing smb request
- *
- * Return: 0 on success, otherwise -EINVAL
- */
-static int init_smb1_rsp_hdr(struct ksmbd_work *work)
-{
- struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
- struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
-
- /*
- * Remove 4 byte direct TCP header.
- */
- *(__be32 *)work->response_buf =
- cpu_to_be32(sizeof(struct smb_hdr) - 4);
-
- rsp_hdr->Command = SMB_COM_NEGOTIATE;
- *(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
- rsp_hdr->Flags = SMBFLG_RESPONSE;
- rsp_hdr->Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
- SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
- rsp_hdr->Pid = rcv_hdr->Pid;
- rsp_hdr->Mid = rcv_hdr->Mid;
- return 0;
-}
-
-/**
- * smb1_check_user_session() - check for valid session for a user
- * @work: smb work containing smb request buffer
- *
- * Return: 0 on success, otherwise error
- */
-static int smb1_check_user_session(struct ksmbd_work *work)
-{
- unsigned int cmd = work->conn->ops->get_cmd_val(work);
-
- if (cmd == SMB_COM_NEGOTIATE_EX)
- return 0;
-
- return -EINVAL;
-}
-
-/**
- * smb1_allocate_rsp_buf() - allocate response buffer for a command
- * @work: smb work containing smb request
- *
- * Return: 0 on success, otherwise -ENOMEM
- */
-static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
-{
- work->response_buf = kmalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
- GFP_KERNEL | __GFP_ZERO);
- work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
-
- if (!work->response_buf) {
- pr_err("Failed to allocate %u bytes buffer\n",
- MAX_CIFS_SMALL_BUFFER_SIZE);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static struct smb_version_ops smb1_server_ops = {
- .get_cmd_val = get_smb1_cmd_val,
- .init_rsp_hdr = init_smb1_rsp_hdr,
- .allocate_rsp_buf = smb1_allocate_rsp_buf,
- .check_user_session = smb1_check_user_session,
-};
-
-static int smb1_negotiate(struct ksmbd_work *work)
-{
- return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE);
-}
-
-static struct smb_version_cmds smb1_server_cmds[1] = {
- [SMB_COM_NEGOTIATE_EX] = { .proc = smb1_negotiate, },
-};
-
-static void init_smb1_server(struct ksmbd_conn *conn)
-{
- conn->ops = &smb1_server_ops;
- conn->cmds = smb1_server_cmds;
- conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
-}
-
-void ksmbd_init_smb_server(struct ksmbd_work *work)
-{
- struct ksmbd_conn *conn = work->conn;
- __le32 proto;
-
- if (conn->need_neg == false)
- return;
-
- proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
- if (proto == SMB1_PROTO_NUMBER)
- init_smb1_server(conn);
- else
- init_smb3_11_server(conn);
-}
-
-int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
- struct ksmbd_file *dir,
- struct ksmbd_dir_info *d_info,
- char *search_pattern,
- int (*fn)(struct ksmbd_conn *, int,
- struct ksmbd_dir_info *,
- struct ksmbd_kstat *))
-{
- int i, rc = 0;
- struct ksmbd_conn *conn = work->conn;
- struct user_namespace *user_ns = file_mnt_user_ns(dir->filp);
-
- for (i = 0; i < 2; i++) {
- struct kstat kstat;
- struct ksmbd_kstat ksmbd_kstat;
- struct dentry *dentry;
-
- if (!dir->dot_dotdot[i]) { /* fill dot entry info */
- if (i == 0) {
- d_info->name = ".";
- d_info->name_len = 1;
- dentry = dir->filp->f_path.dentry;
- } else {
- d_info->name = "..";
- d_info->name_len = 2;
- dentry = dir->filp->f_path.dentry->d_parent;
- }
-
- if (!match_pattern(d_info->name, d_info->name_len,
- search_pattern)) {
- dir->dot_dotdot[i] = 1;
- continue;
- }
-
- ksmbd_kstat.kstat = &kstat;
- ksmbd_vfs_fill_dentry_attrs(work,
- user_ns,
- dentry,
- &ksmbd_kstat);
- rc = fn(conn, info_level, d_info, &ksmbd_kstat);
- if (rc)
- break;
- if (d_info->out_buf_len <= 0)
- break;
-
- dir->dot_dotdot[i] = 1;
- if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY) {
- d_info->out_buf_len = 0;
- break;
- }
- }
- }
-
- return rc;
-}
-
-/**
- * ksmbd_extract_shortname() - get shortname from long filename
- * @conn: connection instance
- * @longname: source long filename
- * @shortname: destination short filename
- *
- * Return: shortname length or 0 when source long name is '.' or '..'
- * TODO: Though this function comforms the restriction of 8.3 Filename spec,
- * but the result is different with Windows 7's one. need to check.
- */
-int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname,
- char *shortname)
-{
- const char *p;
- char base[9], extension[4];
- char out[13] = {0};
- int baselen = 0;
- int extlen = 0, len = 0;
- unsigned int csum = 0;
- const unsigned char *ptr;
- bool dot_present = true;
-
- p = longname;
- if ((*p == '.') || (!(strcmp(p, "..")))) {
- /*no mangling required */
- return 0;
- }
-
- p = strrchr(longname, '.');
- if (p == longname) { /*name starts with a dot*/
- strscpy(extension, "___", strlen("___"));
- } else {
- if (p) {
- p++;
- while (*p && extlen < 3) {
- if (*p != '.')
- extension[extlen++] = toupper(*p);
- p++;
- }
- extension[extlen] = '\0';
- } else {
- dot_present = false;
- }
- }
-
- p = longname;
- if (*p == '.') {
- p++;
- longname++;
- }
- while (*p && (baselen < 5)) {
- if (*p != '.')
- base[baselen++] = toupper(*p);
- p++;
- }
-
- base[baselen] = MAGIC_CHAR;
- memcpy(out, base, baselen + 1);
-
- ptr = longname;
- len = strlen(longname);
- for (; len > 0; len--, ptr++)
- csum += *ptr;
-
- csum = csum % (MANGLE_BASE * MANGLE_BASE);
- out[baselen + 1] = mangle(csum / MANGLE_BASE);
- out[baselen + 2] = mangle(csum);
- out[baselen + 3] = PERIOD;
-
- if (dot_present)
- memcpy(&out[baselen + 4], extension, 4);
- else
- out[baselen + 4] = '\0';
- smbConvertToUTF16((__le16 *)shortname, out, PATH_MAX,
- conn->local_nls, 0);
- len = strlen(out) * 2;
- return len;
-}
-
-static int __smb2_negotiate(struct ksmbd_conn *conn)
-{
- return (conn->dialect >= SMB20_PROT_ID &&
- conn->dialect <= SMB311_PROT_ID);
-}
-
-static int smb_handle_negotiate(struct ksmbd_work *work)
-{
- struct smb_negotiate_rsp *neg_rsp = work->response_buf;
-
- ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
-
- /* Add 2 byte bcc and 2 byte DialectIndex. */
- inc_rfc1001_len(work->response_buf, 4);
- neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
-
- neg_rsp->hdr.WordCount = 1;
- neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
- neg_rsp->ByteCount = 0;
- return 0;
-}
-
-int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
-{
- struct ksmbd_conn *conn = work->conn;
- int ret;
-
- conn->dialect =
- ksmbd_negotiate_smb_dialect(work->request_buf);
- ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
-
- if (command == SMB2_NEGOTIATE_HE) {
- ret = smb2_handle_negotiate(work);
- return ret;
- }
-
- if (command == SMB_COM_NEGOTIATE) {
- if (__smb2_negotiate(conn)) {
- init_smb3_11_server(conn);
- init_smb2_neg_rsp(work);
- ksmbd_debug(SMB, "Upgrade to SMB2 negotiation\n");
- return 0;
- }
- return smb_handle_negotiate(work);
- }
-
- pr_err("Unknown SMB negotiation command: %u\n", command);
- return -EINVAL;
-}
-
-enum SHARED_MODE_ERRORS {
- SHARE_DELETE_ERROR,
- SHARE_READ_ERROR,
- SHARE_WRITE_ERROR,
- FILE_READ_ERROR,
- FILE_WRITE_ERROR,
- FILE_DELETE_ERROR,
-};
-
-static const char * const shared_mode_errors[] = {
- "Current access mode does not permit SHARE_DELETE",
- "Current access mode does not permit SHARE_READ",
- "Current access mode does not permit SHARE_WRITE",
- "Desired access mode does not permit FILE_READ",
- "Desired access mode does not permit FILE_WRITE",
- "Desired access mode does not permit FILE_DELETE",
-};
-
-static void smb_shared_mode_error(int error, struct ksmbd_file *prev_fp,
- struct ksmbd_file *curr_fp)
-{
- ksmbd_debug(SMB, "%s\n", shared_mode_errors[error]);
- ksmbd_debug(SMB, "Current mode: 0x%x Desired mode: 0x%x\n",
- prev_fp->saccess, curr_fp->daccess);
-}
-
-int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
-{
- int rc = 0;
- struct ksmbd_file *prev_fp;
-
- /*
- * Lookup fp in master fp list, and check desired access and
- * shared mode between previous open and current open.
- */
- read_lock(&curr_fp->f_ci->m_lock);
- list_for_each_entry(prev_fp, &curr_fp->f_ci->m_fp_list, node) {
- if (file_inode(filp) != file_inode(prev_fp->filp))
- continue;
-
- if (filp == prev_fp->filp)
- continue;
-
- if (ksmbd_stream_fd(prev_fp) && ksmbd_stream_fd(curr_fp))
- if (strcmp(prev_fp->stream.name, curr_fp->stream.name))
- continue;
-
- if (prev_fp->attrib_only != curr_fp->attrib_only)
- continue;
-
- if (!(prev_fp->saccess & FILE_SHARE_DELETE_LE) &&
- curr_fp->daccess & FILE_DELETE_LE) {
- smb_shared_mode_error(SHARE_DELETE_ERROR,
- prev_fp,
- curr_fp);
- rc = -EPERM;
- break;
- }
-
- /*
- * Only check FILE_SHARE_DELETE if stream opened and
- * normal file opened.
- */
- if (ksmbd_stream_fd(prev_fp) && !ksmbd_stream_fd(curr_fp))
- continue;
-
- if (!(prev_fp->saccess & FILE_SHARE_READ_LE) &&
- curr_fp->daccess & (FILE_EXECUTE_LE | FILE_READ_DATA_LE)) {
- smb_shared_mode_error(SHARE_READ_ERROR,
- prev_fp,
- curr_fp);
- rc = -EPERM;
- break;
- }
-
- if (!(prev_fp->saccess & FILE_SHARE_WRITE_LE) &&
- curr_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE)) {
- smb_shared_mode_error(SHARE_WRITE_ERROR,
- prev_fp,
- curr_fp);
- rc = -EPERM;
- break;
- }
-
- if (prev_fp->daccess & (FILE_EXECUTE_LE | FILE_READ_DATA_LE) &&
- !(curr_fp->saccess & FILE_SHARE_READ_LE)) {
- smb_shared_mode_error(FILE_READ_ERROR,
- prev_fp,
- curr_fp);
- rc = -EPERM;
- break;
- }
-
- if (prev_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE) &&
- !(curr_fp->saccess & FILE_SHARE_WRITE_LE)) {
- smb_shared_mode_error(FILE_WRITE_ERROR,
- prev_fp,
- curr_fp);
- rc = -EPERM;
- break;
- }
-
- if (prev_fp->daccess & FILE_DELETE_LE &&
- !(curr_fp->saccess & FILE_SHARE_DELETE_LE)) {
- smb_shared_mode_error(FILE_DELETE_ERROR,
- prev_fp,
- curr_fp);
- rc = -EPERM;
- break;
- }
- }
- read_unlock(&curr_fp->f_ci->m_lock);
-
- return rc;
-}
-
-bool is_asterisk(char *p)
-{
- return p && p[0] == '*';
-}
-
-int ksmbd_override_fsids(struct ksmbd_work *work)
-{
- struct ksmbd_session *sess = work->sess;
- struct ksmbd_share_config *share = work->tcon->share_conf;
- struct cred *cred;
- struct group_info *gi;
- unsigned int uid;
- unsigned int gid;
-
- uid = user_uid(sess->user);
- gid = user_gid(sess->user);
- if (share->force_uid != KSMBD_SHARE_INVALID_UID)
- uid = share->force_uid;
- if (share->force_gid != KSMBD_SHARE_INVALID_GID)
- gid = share->force_gid;
-
- cred = prepare_kernel_cred(NULL);
- if (!cred)
- return -ENOMEM;
-
- cred->fsuid = make_kuid(&init_user_ns, uid);
- cred->fsgid = make_kgid(&init_user_ns, gid);
-
- gi = groups_alloc(0);
- if (!gi) {
- abort_creds(cred);
- return -ENOMEM;
- }
- set_groups(cred, gi);
- put_group_info(gi);
-
- if (!uid_eq(cred->fsuid, GLOBAL_ROOT_UID))
- cred->cap_effective = cap_drop_fs_set(cred->cap_effective);
-
- WARN_ON(work->saved_cred);
- work->saved_cred = override_creds(cred);
- if (!work->saved_cred) {
- abort_creds(cred);
- return -EINVAL;
- }
- return 0;
-}
-
-void ksmbd_revert_fsids(struct ksmbd_work *work)
-{
- const struct cred *cred;
-
- WARN_ON(!work->saved_cred);
-
- cred = current_cred();
- revert_creds(work->saved_cred);
- put_cred(cred);
- work->saved_cred = NULL;
-}
-
-__le32 smb_map_generic_desired_access(__le32 daccess)
-{
- if (daccess & FILE_GENERIC_READ_LE) {
- daccess |= cpu_to_le32(GENERIC_READ_FLAGS);
- daccess &= ~FILE_GENERIC_READ_LE;
- }
-
- if (daccess & FILE_GENERIC_WRITE_LE) {
- daccess |= cpu_to_le32(GENERIC_WRITE_FLAGS);
- daccess &= ~FILE_GENERIC_WRITE_LE;
- }
-
- if (daccess & FILE_GENERIC_EXECUTE_LE) {
- daccess |= cpu_to_le32(GENERIC_EXECUTE_FLAGS);
- daccess &= ~FILE_GENERIC_EXECUTE_LE;
- }
-
- if (daccess & FILE_GENERIC_ALL_LE) {
- daccess |= cpu_to_le32(GENERIC_ALL_FLAGS);
- daccess &= ~FILE_GENERIC_ALL_LE;
- }
-
- return daccess;
-}
diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h
deleted file mode 100644
index 78c44978a906..000000000000
--- a/fs/ksmbd/smb_common.h
+++ /dev/null
@@ -1,468 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __SMB_COMMON_H__
-#define __SMB_COMMON_H__
-
-#include <linux/kernel.h>
-
-#include "glob.h"
-#include "nterr.h"
-#include "../smbfs_common/smb2pdu.h"
-#include "smb2pdu.h"
-
-/* ksmbd's Specific ERRNO */
-#define ESHARE 50000
-
-#define SMB1_PROT 0
-#define SMB2_PROT 1
-#define SMB21_PROT 2
-/* multi-protocol negotiate request */
-#define SMB2X_PROT 3
-#define SMB30_PROT 4
-#define SMB302_PROT 5
-#define SMB311_PROT 6
-#define BAD_PROT 0xFFFF
-
-#define SMB1_VERSION_STRING "1.0"
-#define SMB20_VERSION_STRING "2.0"
-#define SMB21_VERSION_STRING "2.1"
-#define SMB30_VERSION_STRING "3.0"
-#define SMB302_VERSION_STRING "3.02"
-#define SMB311_VERSION_STRING "3.1.1"
-
-#define SMB_ECHO_INTERVAL (60 * HZ)
-
-#define CIFS_DEFAULT_IOSIZE (64 * 1024)
-#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
-
-#define MAX_STREAM_PROT_LEN 0x00FFFFFF
-
-/* Responses when opening a file. */
-#define F_SUPERSEDED 0
-#define F_OPENED 1
-#define F_CREATED 2
-#define F_OVERWRITTEN 3
-
-/*
- * File Attribute flags
- */
-#define ATTR_POSIX_SEMANTICS 0x01000000
-#define ATTR_BACKUP_SEMANTICS 0x02000000
-#define ATTR_DELETE_ON_CLOSE 0x04000000
-#define ATTR_SEQUENTIAL_SCAN 0x08000000
-#define ATTR_RANDOM_ACCESS 0x10000000
-#define ATTR_NO_BUFFERING 0x20000000
-#define ATTR_WRITE_THROUGH 0x80000000
-
-/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */
-#define FILE_SUPPORTS_SPARSE_VDL 0x10000000 /* faster nonsparse extend */
-#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000 /* allow ioctl dup extents */
-#define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000
-#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
-#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
-#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
-#define FILE_SUPPORTS_HARD_LINKS 0x00400000
-#define FILE_SUPPORTS_TRANSACTIONS 0x00200000
-#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
-#define FILE_READ_ONLY_VOLUME 0x00080000
-#define FILE_NAMED_STREAMS 0x00040000
-#define FILE_SUPPORTS_ENCRYPTION 0x00020000
-#define FILE_SUPPORTS_OBJECT_IDS 0x00010000
-#define FILE_VOLUME_IS_COMPRESSED 0x00008000
-#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100
-#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080
-#define FILE_SUPPORTS_SPARSE_FILES 0x00000040
-#define FILE_VOLUME_QUOTAS 0x00000020
-#define FILE_FILE_COMPRESSION 0x00000010
-#define FILE_PERSISTENT_ACLS 0x00000008
-#define FILE_UNICODE_ON_DISK 0x00000004
-#define FILE_CASE_PRESERVED_NAMES 0x00000002
-#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
-
-#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
-#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
-#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
-#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
-/* with the file can be read */
-#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
-/* with the file can be written */
-#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
-/* the file using system paging I/O */
-#define FILE_DELETE_CHILD 0x00000040
-#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
-/* file can be read */
-#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
-/* file can be written */
-#define DELETE 0x00010000 /* The file can be deleted */
-#define READ_CONTROL 0x00020000 /* The access control list and */
-/* ownership associated with the */
-/* file can be read */
-#define WRITE_DAC 0x00040000 /* The access control list and */
-/* ownership associated with the */
-/* file can be written. */
-#define WRITE_OWNER 0x00080000 /* Ownership information associated */
-/* with the file can be written */
-#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
-/* synchronize with the completion */
-/* of an input/output request */
-#define GENERIC_ALL 0x10000000
-#define GENERIC_EXECUTE 0x20000000
-#define GENERIC_WRITE 0x40000000
-#define GENERIC_READ 0x80000000
-/* In summary - Relevant file */
-/* access flags from CIFS are */
-/* file_read_data, file_write_data */
-/* file_execute, file_read_attributes*/
-/* write_dac, and delete. */
-
-#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \
- | FILE_READ_ATTRIBUTES \
- | DELETE | READ_CONTROL | WRITE_DAC \
- | WRITE_OWNER | SYNCHRONIZE)
-#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
- | FILE_WRITE_EA \
- | FILE_DELETE_CHILD \
- | FILE_WRITE_ATTRIBUTES \
- | DELETE | READ_CONTROL | WRITE_DAC \
- | WRITE_OWNER | SYNCHRONIZE)
-#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
- | FILE_READ_ATTRIBUTES \
- | FILE_WRITE_ATTRIBUTES \
- | DELETE | READ_CONTROL | WRITE_DAC \
- | WRITE_OWNER | SYNCHRONIZE)
-
-#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \
- | READ_CONTROL | SYNCHRONIZE)
-
-/* generic flags for file open */
-#define GENERIC_READ_FLAGS (READ_CONTROL | FILE_READ_DATA | \
- FILE_READ_ATTRIBUTES | \
- FILE_READ_EA | SYNCHRONIZE)
-
-#define GENERIC_WRITE_FLAGS (READ_CONTROL | FILE_WRITE_DATA | \
- FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | \
- FILE_APPEND_DATA | SYNCHRONIZE)
-
-#define GENERIC_EXECUTE_FLAGS (READ_CONTROL | FILE_EXECUTE | \
- FILE_READ_ATTRIBUTES | SYNCHRONIZE)
-
-#define GENERIC_ALL_FLAGS (DELETE | READ_CONTROL | WRITE_DAC | \
- WRITE_OWNER | SYNCHRONIZE | FILE_READ_DATA | \
- FILE_WRITE_DATA | FILE_APPEND_DATA | \
- FILE_READ_EA | FILE_WRITE_EA | \
- FILE_EXECUTE | FILE_DELETE_CHILD | \
- FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)
-
-#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff)
-#define SMB_COM_NEGOTIATE 0x72
-#define SMB1_CLIENT_GUID_SIZE (16)
-
-#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
-
-#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
-#define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
-#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
-#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
-
-struct smb_hdr {
- __be32 smb_buf_length;
- __u8 Protocol[4];
- __u8 Command;
- union {
- struct {
- __u8 ErrorClass;
- __u8 Reserved;
- __le16 Error;
- } __packed DosError;
- __le32 CifsError;
- } __packed Status;
- __u8 Flags;
- __le16 Flags2; /* note: le */
- __le16 PidHigh;
- union {
- struct {
- __le32 SequenceNumber; /* le */
- __u32 Reserved; /* zero */
- } __packed Sequence;
- __u8 SecuritySignature[8]; /* le */
- } __packed Signature;
- __u8 pad[2];
- __le16 Tid;
- __le16 Pid;
- __le16 Uid;
- __le16 Mid;
- __u8 WordCount;
-} __packed;
-
-struct smb_negotiate_req {
- struct smb_hdr hdr; /* wct = 0 */
- __le16 ByteCount;
- unsigned char DialectsArray[1];
-} __packed;
-
-struct smb_negotiate_rsp {
- struct smb_hdr hdr; /* wct = 17 */
- __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
- __le16 ByteCount;
-} __packed;
-
-struct filesystem_attribute_info {
- __le32 Attributes;
- __le32 MaxPathNameComponentLength;
- __le32 FileSystemNameLen;
- __le16 FileSystemName[1]; /* do not have to save this - get subset? */
-} __packed;
-
-struct filesystem_device_info {
- __le32 DeviceType;
- __le32 DeviceCharacteristics;
-} __packed; /* device info level 0x104 */
-
-struct filesystem_vol_info {
- __le64 VolumeCreationTime;
- __le32 SerialNumber;
- __le32 VolumeLabelSize;
- __le16 Reserved;
- __le16 VolumeLabel[1];
-} __packed;
-
-struct filesystem_info {
- __le64 TotalAllocationUnits;
- __le64 FreeAllocationUnits;
- __le32 SectorsPerAllocationUnit;
- __le32 BytesPerSector;
-} __packed; /* size info, level 0x103 */
-
-#define EXTENDED_INFO_MAGIC 0x43667364 /* Cfsd */
-#define STRING_LENGTH 28
-
-struct fs_extended_info {
- __le32 magic;
- __le32 version;
- __le32 release;
- __u64 rel_date;
- char version_string[STRING_LENGTH];
-} __packed;
-
-struct object_id_info {
- char objid[16];
- struct fs_extended_info extended_info;
-} __packed;
-
-struct file_directory_info {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 ExtFileAttributes;
- __le32 FileNameLength;
- char FileName[1];
-} __packed; /* level 0x101 FF resp data */
-
-struct file_names_info {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le32 FileNameLength;
- char FileName[1];
-} __packed; /* level 0xc FF resp data */
-
-struct file_full_directory_info {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 ExtFileAttributes;
- __le32 FileNameLength;
- __le32 EaSize;
- char FileName[1];
-} __packed; /* level 0x102 FF resp */
-
-struct file_both_directory_info {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 ExtFileAttributes;
- __le32 FileNameLength;
- __le32 EaSize; /* length of the xattrs */
- __u8 ShortNameLength;
- __u8 Reserved;
- __u8 ShortName[24];
- char FileName[1];
-} __packed; /* level 0x104 FFrsp data */
-
-struct file_id_both_directory_info {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 ExtFileAttributes;
- __le32 FileNameLength;
- __le32 EaSize; /* length of the xattrs */
- __u8 ShortNameLength;
- __u8 Reserved;
- __u8 ShortName[24];
- __le16 Reserved2;
- __le64 UniqueId;
- char FileName[1];
-} __packed;
-
-struct file_id_full_dir_info {
- __le32 NextEntryOffset;
- __u32 FileIndex;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 ExtFileAttributes;
- __le32 FileNameLength;
- __le32 EaSize; /* EA size */
- __le32 Reserved;
- __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
- char FileName[1];
-} __packed; /* level 0x105 FF rsp data */
-
-struct smb_version_values {
- char *version_string;
- __u16 protocol_id;
- __le16 lock_cmd;
- __u32 capabilities;
- __u32 max_read_size;
- __u32 max_write_size;
- __u32 max_trans_size;
- __u32 max_credits;
- __u32 large_lock_type;
- __u32 exclusive_lock_type;
- __u32 shared_lock_type;
- __u32 unlock_lock_type;
- size_t header_size;
- size_t max_header_size;
- size_t read_rsp_size;
- unsigned int cap_unix;
- unsigned int cap_nt_find;
- unsigned int cap_large_files;
- __u16 signing_enabled;
- __u16 signing_required;
- size_t create_lease_size;
- size_t create_durable_size;
- size_t create_durable_v2_size;
- size_t create_mxac_size;
- size_t create_disk_id_size;
- size_t create_posix_size;
-};
-
-struct filesystem_posix_info {
- /* For undefined recommended transfer size return -1 in that field */
- __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
- __le32 BlockSize;
- /* The next three fields are in terms of the block size.
- * (above). If block size is unknown, 4096 would be a
- * reasonable block size for a server to report.
- * Note that returning the blocks/blocksavail removes need
- * to make a second call (to QFSInfo level 0x103 to get this info.
- * UserBlockAvail is typically less than or equal to BlocksAvail,
- * if no distinction is made return the same value in each
- */
- __le64 TotalBlocks;
- __le64 BlocksAvail; /* bfree */
- __le64 UserBlocksAvail; /* bavail */
- /* For undefined Node fields or FSID return -1 */
- __le64 TotalFileNodes;
- __le64 FreeFileNodes;
- __le64 FileSysIdentifier; /* fsid */
- /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
- /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
-} __packed;
-
-struct smb_version_ops {
- u16 (*get_cmd_val)(struct ksmbd_work *swork);
- int (*init_rsp_hdr)(struct ksmbd_work *swork);
- void (*set_rsp_status)(struct ksmbd_work *swork, __le32 err);
- int (*allocate_rsp_buf)(struct ksmbd_work *work);
- int (*set_rsp_credits)(struct ksmbd_work *work);
- int (*check_user_session)(struct ksmbd_work *work);
- int (*get_ksmbd_tcon)(struct ksmbd_work *work);
- bool (*is_sign_req)(struct ksmbd_work *work, unsigned int command);
- int (*check_sign_req)(struct ksmbd_work *work);
- void (*set_sign_rsp)(struct ksmbd_work *work);
- int (*generate_signingkey)(struct ksmbd_session *sess, struct ksmbd_conn *conn);
- int (*generate_encryptionkey)(struct ksmbd_conn *conn, struct ksmbd_session *sess);
- bool (*is_transform_hdr)(void *buf);
- int (*decrypt_req)(struct ksmbd_work *work);
- int (*encrypt_resp)(struct ksmbd_work *work);
-};
-
-struct smb_version_cmds {
- int (*proc)(struct ksmbd_work *swork);
-};
-
-int ksmbd_min_protocol(void);
-int ksmbd_max_protocol(void);
-
-int ksmbd_lookup_protocol_idx(char *str);
-
-int ksmbd_verify_smb_message(struct ksmbd_work *work);
-bool ksmbd_smb_request(struct ksmbd_conn *conn);
-
-int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
-
-void ksmbd_init_smb_server(struct ksmbd_work *work);
-
-struct ksmbd_kstat;
-int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
- int info_level,
- struct ksmbd_file *dir,
- struct ksmbd_dir_info *d_info,
- char *search_pattern,
- int (*fn)(struct ksmbd_conn *,
- int,
- struct ksmbd_dir_info *,
- struct ksmbd_kstat *));
-
-int ksmbd_extract_shortname(struct ksmbd_conn *conn,
- const char *longname,
- char *shortname);
-
-int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command);
-
-int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp);
-int ksmbd_override_fsids(struct ksmbd_work *work);
-void ksmbd_revert_fsids(struct ksmbd_work *work);
-
-unsigned int ksmbd_server_side_copy_max_chunk_count(void);
-unsigned int ksmbd_server_side_copy_max_chunk_size(void);
-unsigned int ksmbd_server_side_copy_max_total_size(void);
-bool is_asterisk(char *p);
-__le32 smb_map_generic_desired_access(__le32 daccess);
-
-static inline unsigned int get_rfc1002_len(void *buf)
-{
- return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
-}
-
-static inline void inc_rfc1001_len(void *buf, int count)
-{
- be32_add_cpu((__be32 *)buf, count);
-}
-#endif /* __SMB_COMMON_H__ */
diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c
deleted file mode 100644
index b05ff9b146b5..000000000000
--- a/fs/ksmbd/smbacl.c
+++ /dev/null
@@ -1,1436 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1+
-/*
- * Copyright (C) International Business Machines Corp., 2007,2008
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Copyright (C) 2020 Samsung Electronics Co., Ltd.
- * Author(s): Namjae Jeon <linkinjeon@kernel.org>
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/mnt_idmapping.h>
-
-#include "smbacl.h"
-#include "smb_common.h"
-#include "server.h"
-#include "misc.h"
-#include "mgmt/share_config.h"
-
-static const struct smb_sid domain = {1, 4, {0, 0, 0, 0, 0, 5},
- {cpu_to_le32(21), cpu_to_le32(1), cpu_to_le32(2), cpu_to_le32(3),
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/* security id for everyone/world system group */
-static const struct smb_sid creator_owner = {
- 1, 1, {0, 0, 0, 0, 0, 3}, {0} };
-/* security id for everyone/world system group */
-static const struct smb_sid creator_group = {
- 1, 1, {0, 0, 0, 0, 0, 3}, {cpu_to_le32(1)} };
-
-/* security id for everyone/world system group */
-static const struct smb_sid sid_everyone = {
- 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
-/* security id for Authenticated Users system group */
-static const struct smb_sid sid_authusers = {
- 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
-
-/* S-1-22-1 Unmapped Unix users */
-static const struct smb_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
- {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/* S-1-22-2 Unmapped Unix groups */
-static const struct smb_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
- {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/*
- * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
- */
-
-/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
-
-/* S-1-5-88-1 Unix uid */
-static const struct smb_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
- {cpu_to_le32(88),
- cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/* S-1-5-88-2 Unix gid */
-static const struct smb_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
- {cpu_to_le32(88),
- cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/* S-1-5-88-3 Unix mode */
-static const struct smb_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
- {cpu_to_le32(88),
- cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
-
-/*
- * if the two SIDs (roughly equivalent to a UUID for a user or group) are
- * the same returns zero, if they do not match returns non-zero.
- */
-int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid)
-{
- int i;
- int num_subauth, num_sat, num_saw;
-
- if (!ctsid || !cwsid)
- return 1;
-
- /* compare the revision */
- if (ctsid->revision != cwsid->revision) {
- if (ctsid->revision > cwsid->revision)
- return 1;
- else
- return -1;
- }
-
- /* compare all of the six auth values */
- for (i = 0; i < NUM_AUTHS; ++i) {
- if (ctsid->authority[i] != cwsid->authority[i]) {
- if (ctsid->authority[i] > cwsid->authority[i])
- return 1;
- else
- return -1;
- }
- }
-
- /* compare all of the subauth values if any */
- num_sat = ctsid->num_subauth;
- num_saw = cwsid->num_subauth;
- num_subauth = num_sat < num_saw ? num_sat : num_saw;
- if (num_subauth) {
- for (i = 0; i < num_subauth; ++i) {
- if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
- if (le32_to_cpu(ctsid->sub_auth[i]) >
- le32_to_cpu(cwsid->sub_auth[i]))
- return 1;
- else
- return -1;
- }
- }
- }
-
- return 0; /* sids compare/match */
-}
-
-static void smb_copy_sid(struct smb_sid *dst, const struct smb_sid *src)
-{
- int i;
-
- dst->revision = src->revision;
- dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
- for (i = 0; i < NUM_AUTHS; ++i)
- dst->authority[i] = src->authority[i];
- for (i = 0; i < dst->num_subauth; ++i)
- dst->sub_auth[i] = src->sub_auth[i];
-}
-
-/*
- * change posix mode to reflect permissions
- * pmode is the existing mode (we only want to overwrite part of this
- * bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
- */
-static umode_t access_flags_to_mode(struct smb_fattr *fattr, __le32 ace_flags,
- int type)
-{
- __u32 flags = le32_to_cpu(ace_flags);
- umode_t mode = 0;
-
- if (flags & GENERIC_ALL) {
- mode = 0777;
- ksmbd_debug(SMB, "all perms\n");
- return mode;
- }
-
- if ((flags & GENERIC_READ) || (flags & FILE_READ_RIGHTS))
- mode = 0444;
- if ((flags & GENERIC_WRITE) || (flags & FILE_WRITE_RIGHTS)) {
- mode |= 0222;
- if (S_ISDIR(fattr->cf_mode))
- mode |= 0111;
- }
- if ((flags & GENERIC_EXECUTE) || (flags & FILE_EXEC_RIGHTS))
- mode |= 0111;
-
- if (type == ACCESS_DENIED_ACE_TYPE || type == ACCESS_DENIED_OBJECT_ACE_TYPE)
- mode = ~mode;
-
- ksmbd_debug(SMB, "access flags 0x%x mode now %04o\n", flags, mode);
-
- return mode;
-}
-
-/*
- * Generate access flags to reflect permissions mode is the existing mode.
- * This function is called for every ACE in the DACL whose SID matches
- * with either owner or group or everyone.
- */
-static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
- __u32 *pace_flags)
-{
- /* reset access mask */
- *pace_flags = 0x0;
-
- /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
- mode &= bits_to_use;
-
- /*
- * check for R/W/X UGO since we do not know whose flags
- * is this but we have cleared all the bits sans RWX for
- * either user or group or other as per bits_to_use
- */
- if (mode & 0444)
- *pace_flags |= SET_FILE_READ_RIGHTS;
- if (mode & 0222)
- *pace_flags |= FILE_WRITE_RIGHTS;
- if (mode & 0111)
- *pace_flags |= SET_FILE_EXEC_RIGHTS;
-
- ksmbd_debug(SMB, "mode: %o, access flags now 0x%x\n",
- mode, *pace_flags);
-}
-
-static __u16 fill_ace_for_sid(struct smb_ace *pntace,
- const struct smb_sid *psid, int type, int flags,
- umode_t mode, umode_t bits)
-{
- int i;
- __u16 size = 0;
- __u32 access_req = 0;
-
- pntace->type = type;
- pntace->flags = flags;
- mode_to_access_flags(mode, bits, &access_req);
- if (!access_req)
- access_req = SET_MINIMUM_RIGHTS;
- pntace->access_req = cpu_to_le32(access_req);
-
- pntace->sid.revision = psid->revision;
- pntace->sid.num_subauth = psid->num_subauth;
- for (i = 0; i < NUM_AUTHS; i++)
- pntace->sid.authority[i] = psid->authority[i];
- for (i = 0; i < psid->num_subauth; i++)
- pntace->sid.sub_auth[i] = psid->sub_auth[i];
-
- size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
- pntace->size = cpu_to_le16(size);
-
- return size;
-}
-
-void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid)
-{
- switch (sidtype) {
- case SIDOWNER:
- smb_copy_sid(ssid, &server_conf.domain_sid);
- break;
- case SIDUNIX_USER:
- smb_copy_sid(ssid, &sid_unix_users);
- break;
- case SIDUNIX_GROUP:
- smb_copy_sid(ssid, &sid_unix_groups);
- break;
- case SIDCREATOR_OWNER:
- smb_copy_sid(ssid, &creator_owner);
- return;
- case SIDCREATOR_GROUP:
- smb_copy_sid(ssid, &creator_group);
- return;
- case SIDNFS_USER:
- smb_copy_sid(ssid, &sid_unix_NFS_users);
- break;
- case SIDNFS_GROUP:
- smb_copy_sid(ssid, &sid_unix_NFS_groups);
- break;
- case SIDNFS_MODE:
- smb_copy_sid(ssid, &sid_unix_NFS_mode);
- break;
- default:
- return;
- }
-
- /* RID */
- ssid->sub_auth[ssid->num_subauth] = cpu_to_le32(cid);
- ssid->num_subauth++;
-}
-
-static int sid_to_id(struct user_namespace *user_ns,
- struct smb_sid *psid, uint sidtype,
- struct smb_fattr *fattr)
-{
- int rc = -EINVAL;
-
- /*
- * If we have too many subauthorities, then something is really wrong.
- * Just return an error.
- */
- if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
- pr_err("%s: %u subauthorities is too many!\n",
- __func__, psid->num_subauth);
- return -EIO;
- }
-
- if (sidtype == SIDOWNER) {
- kuid_t uid;
- uid_t id;
-
- id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
- uid = KUIDT_INIT(id);
- uid = from_vfsuid(user_ns, &init_user_ns, VFSUIDT_INIT(uid));
- if (uid_valid(uid)) {
- fattr->cf_uid = uid;
- rc = 0;
- }
- } else {
- kgid_t gid;
- gid_t id;
-
- id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
- gid = KGIDT_INIT(id);
- gid = from_vfsgid(user_ns, &init_user_ns, VFSGIDT_INIT(gid));
- if (gid_valid(gid)) {
- fattr->cf_gid = gid;
- rc = 0;
- }
- }
-
- return rc;
-}
-
-void posix_state_to_acl(struct posix_acl_state *state,
- struct posix_acl_entry *pace)
-{
- int i;
-
- pace->e_tag = ACL_USER_OBJ;
- pace->e_perm = state->owner.allow;
- for (i = 0; i < state->users->n; i++) {
- pace++;
- pace->e_tag = ACL_USER;
- pace->e_uid = state->users->aces[i].uid;
- pace->e_perm = state->users->aces[i].perms.allow;
- }
-
- pace++;
- pace->e_tag = ACL_GROUP_OBJ;
- pace->e_perm = state->group.allow;
-
- for (i = 0; i < state->groups->n; i++) {
- pace++;
- pace->e_tag = ACL_GROUP;
- pace->e_gid = state->groups->aces[i].gid;
- pace->e_perm = state->groups->aces[i].perms.allow;
- }
-
- if (state->users->n || state->groups->n) {
- pace++;
- pace->e_tag = ACL_MASK;
- pace->e_perm = state->mask.allow;
- }
-
- pace++;
- pace->e_tag = ACL_OTHER;
- pace->e_perm = state->other.allow;
-}
-
-int init_acl_state(struct posix_acl_state *state, int cnt)
-{
- int alloc;
-
- memset(state, 0, sizeof(struct posix_acl_state));
- /*
- * In the worst case, each individual acl could be for a distinct
- * named user or group, but we don't know which, so we allocate
- * enough space for either:
- */
- alloc = sizeof(struct posix_ace_state_array)
- + cnt * sizeof(struct posix_user_ace_state);
- state->users = kzalloc(alloc, GFP_KERNEL);
- if (!state->users)
- return -ENOMEM;
- state->groups = kzalloc(alloc, GFP_KERNEL);
- if (!state->groups) {
- kfree(state->users);
- return -ENOMEM;
- }
- return 0;
-}
-
-void free_acl_state(struct posix_acl_state *state)
-{
- kfree(state->users);
- kfree(state->groups);
-}
-
-static void parse_dacl(struct user_namespace *user_ns,
- struct smb_acl *pdacl, char *end_of_acl,
- struct smb_sid *pownersid, struct smb_sid *pgrpsid,
- struct smb_fattr *fattr)
-{
- int i, ret;
- int num_aces = 0;
- unsigned int acl_size;
- char *acl_base;
- struct smb_ace **ppace;
- struct posix_acl_entry *cf_pace, *cf_pdace;
- struct posix_acl_state acl_state, default_acl_state;
- umode_t mode = 0, acl_mode;
- bool owner_found = false, group_found = false, others_found = false;
-
- if (!pdacl)
- return;
-
- /* validate that we do not go past end of acl */
- if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) ||
- end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
- pr_err("ACL too small to parse DACL\n");
- return;
- }
-
- ksmbd_debug(SMB, "DACL revision %d size %d num aces %d\n",
- le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
- le32_to_cpu(pdacl->num_aces));
-
- acl_base = (char *)pdacl;
- acl_size = sizeof(struct smb_acl);
-
- num_aces = le32_to_cpu(pdacl->num_aces);
- if (num_aces <= 0)
- return;
-
- if (num_aces > ULONG_MAX / sizeof(struct smb_ace *))
- return;
-
- ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), GFP_KERNEL);
- if (!ppace)
- return;
-
- ret = init_acl_state(&acl_state, num_aces);
- if (ret)
- return;
- ret = init_acl_state(&default_acl_state, num_aces);
- if (ret) {
- free_acl_state(&acl_state);
- return;
- }
-
- /*
- * reset rwx permissions for user/group/other.
- * Also, if num_aces is 0 i.e. DACL has no ACEs,
- * user/group/other have no permissions
- */
- for (i = 0; i < num_aces; ++i) {
- if (end_of_acl - acl_base < acl_size)
- break;
-
- ppace[i] = (struct smb_ace *)(acl_base + acl_size);
- acl_base = (char *)ppace[i];
- acl_size = offsetof(struct smb_ace, sid) +
- offsetof(struct smb_sid, sub_auth);
-
- if (end_of_acl - acl_base < acl_size ||
- ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
- (end_of_acl - acl_base <
- acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||
- (le16_to_cpu(ppace[i]->size) <
- acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth))
- break;
-
- acl_size = le16_to_cpu(ppace[i]->size);
- ppace[i]->access_req =
- smb_map_generic_desired_access(ppace[i]->access_req);
-
- if (!(compare_sids(&ppace[i]->sid, &sid_unix_NFS_mode))) {
- fattr->cf_mode =
- le32_to_cpu(ppace[i]->sid.sub_auth[2]);
- break;
- } else if (!compare_sids(&ppace[i]->sid, pownersid)) {
- acl_mode = access_flags_to_mode(fattr,
- ppace[i]->access_req,
- ppace[i]->type);
- acl_mode &= 0700;
-
- if (!owner_found) {
- mode &= ~(0700);
- mode |= acl_mode;
- }
- owner_found = true;
- } else if (!compare_sids(&ppace[i]->sid, pgrpsid) ||
- ppace[i]->sid.sub_auth[ppace[i]->sid.num_subauth - 1] ==
- DOMAIN_USER_RID_LE) {
- acl_mode = access_flags_to_mode(fattr,
- ppace[i]->access_req,
- ppace[i]->type);
- acl_mode &= 0070;
- if (!group_found) {
- mode &= ~(0070);
- mode |= acl_mode;
- }
- group_found = true;
- } else if (!compare_sids(&ppace[i]->sid, &sid_everyone)) {
- acl_mode = access_flags_to_mode(fattr,
- ppace[i]->access_req,
- ppace[i]->type);
- acl_mode &= 0007;
- if (!others_found) {
- mode &= ~(0007);
- mode |= acl_mode;
- }
- others_found = true;
- } else if (!compare_sids(&ppace[i]->sid, &creator_owner)) {
- continue;
- } else if (!compare_sids(&ppace[i]->sid, &creator_group)) {
- continue;
- } else if (!compare_sids(&ppace[i]->sid, &sid_authusers)) {
- continue;
- } else {
- struct smb_fattr temp_fattr;
-
- acl_mode = access_flags_to_mode(fattr, ppace[i]->access_req,
- ppace[i]->type);
- temp_fattr.cf_uid = INVALID_UID;
- ret = sid_to_id(user_ns, &ppace[i]->sid, SIDOWNER, &temp_fattr);
- if (ret || uid_eq(temp_fattr.cf_uid, INVALID_UID)) {
- pr_err("%s: Error %d mapping Owner SID to uid\n",
- __func__, ret);
- continue;
- }
-
- acl_state.owner.allow = ((acl_mode & 0700) >> 6) | 0004;
- acl_state.users->aces[acl_state.users->n].uid =
- temp_fattr.cf_uid;
- acl_state.users->aces[acl_state.users->n++].perms.allow =
- ((acl_mode & 0700) >> 6) | 0004;
- default_acl_state.owner.allow = ((acl_mode & 0700) >> 6) | 0004;
- default_acl_state.users->aces[default_acl_state.users->n].uid =
- temp_fattr.cf_uid;
- default_acl_state.users->aces[default_acl_state.users->n++].perms.allow =
- ((acl_mode & 0700) >> 6) | 0004;
- }
- }
- kfree(ppace);
-
- if (owner_found) {
- /* The owner must be set to at least read-only. */
- acl_state.owner.allow = ((mode & 0700) >> 6) | 0004;
- acl_state.users->aces[acl_state.users->n].uid = fattr->cf_uid;
- acl_state.users->aces[acl_state.users->n++].perms.allow =
- ((mode & 0700) >> 6) | 0004;
- default_acl_state.owner.allow = ((mode & 0700) >> 6) | 0004;
- default_acl_state.users->aces[default_acl_state.users->n].uid =
- fattr->cf_uid;
- default_acl_state.users->aces[default_acl_state.users->n++].perms.allow =
- ((mode & 0700) >> 6) | 0004;
- }
-
- if (group_found) {
- acl_state.group.allow = (mode & 0070) >> 3;
- acl_state.groups->aces[acl_state.groups->n].gid =
- fattr->cf_gid;
- acl_state.groups->aces[acl_state.groups->n++].perms.allow =
- (mode & 0070) >> 3;
- default_acl_state.group.allow = (mode & 0070) >> 3;
- default_acl_state.groups->aces[default_acl_state.groups->n].gid =
- fattr->cf_gid;
- default_acl_state.groups->aces[default_acl_state.groups->n++].perms.allow =
- (mode & 0070) >> 3;
- }
-
- if (others_found) {
- fattr->cf_mode &= ~(0007);
- fattr->cf_mode |= mode & 0007;
-
- acl_state.other.allow = mode & 0007;
- default_acl_state.other.allow = mode & 0007;
- }
-
- if (acl_state.users->n || acl_state.groups->n) {
- acl_state.mask.allow = 0x07;
-
- if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
- fattr->cf_acls =
- posix_acl_alloc(acl_state.users->n +
- acl_state.groups->n + 4, GFP_KERNEL);
- if (fattr->cf_acls) {
- cf_pace = fattr->cf_acls->a_entries;
- posix_state_to_acl(&acl_state, cf_pace);
- }
- }
- }
-
- if (default_acl_state.users->n || default_acl_state.groups->n) {
- default_acl_state.mask.allow = 0x07;
-
- if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
- fattr->cf_dacls =
- posix_acl_alloc(default_acl_state.users->n +
- default_acl_state.groups->n + 4, GFP_KERNEL);
- if (fattr->cf_dacls) {
- cf_pdace = fattr->cf_dacls->a_entries;
- posix_state_to_acl(&default_acl_state, cf_pdace);
- }
- }
- }
- free_acl_state(&acl_state);
- free_acl_state(&default_acl_state);
-}
-
-static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
- struct smb_ace *pndace,
- struct smb_fattr *fattr, u32 *num_aces,
- u16 *size, u32 nt_aces_num)
-{
- struct posix_acl_entry *pace;
- struct smb_sid *sid;
- struct smb_ace *ntace;
- int i, j;
-
- if (!fattr->cf_acls)
- goto posix_default_acl;
-
- pace = fattr->cf_acls->a_entries;
- for (i = 0; i < fattr->cf_acls->a_count; i++, pace++) {
- int flags = 0;
-
- sid = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
- if (!sid)
- break;
-
- if (pace->e_tag == ACL_USER) {
- uid_t uid;
- unsigned int sid_type = SIDOWNER;
-
- uid = posix_acl_uid_translate(user_ns, pace);
- if (!uid)
- sid_type = SIDUNIX_USER;
- id_to_sid(uid, sid_type, sid);
- } else if (pace->e_tag == ACL_GROUP) {
- gid_t gid;
-
- gid = posix_acl_gid_translate(user_ns, pace);
- id_to_sid(gid, SIDUNIX_GROUP, sid);
- } else if (pace->e_tag == ACL_OTHER && !nt_aces_num) {
- smb_copy_sid(sid, &sid_everyone);
- } else {
- kfree(sid);
- continue;
- }
- ntace = pndace;
- for (j = 0; j < nt_aces_num; j++) {
- if (ntace->sid.sub_auth[ntace->sid.num_subauth - 1] ==
- sid->sub_auth[sid->num_subauth - 1])
- goto pass_same_sid;
- ntace = (struct smb_ace *)((char *)ntace +
- le16_to_cpu(ntace->size));
- }
-
- if (S_ISDIR(fattr->cf_mode) && pace->e_tag == ACL_OTHER)
- flags = 0x03;
-
- ntace = (struct smb_ace *)((char *)pndace + *size);
- *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
- pace->e_perm, 0777);
- (*num_aces)++;
- if (pace->e_tag == ACL_USER)
- ntace->access_req |=
- FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
-
- if (S_ISDIR(fattr->cf_mode) &&
- (pace->e_tag == ACL_USER || pace->e_tag == ACL_GROUP)) {
- ntace = (struct smb_ace *)((char *)pndace + *size);
- *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
- 0x03, pace->e_perm, 0777);
- (*num_aces)++;
- if (pace->e_tag == ACL_USER)
- ntace->access_req |=
- FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
- }
-
-pass_same_sid:
- kfree(sid);
- }
-
- if (nt_aces_num)
- return;
-
-posix_default_acl:
- if (!fattr->cf_dacls)
- return;
-
- pace = fattr->cf_dacls->a_entries;
- for (i = 0; i < fattr->cf_dacls->a_count; i++, pace++) {
- sid = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
- if (!sid)
- break;
-
- if (pace->e_tag == ACL_USER) {
- uid_t uid;
-
- uid = posix_acl_uid_translate(user_ns, pace);
- id_to_sid(uid, SIDCREATOR_OWNER, sid);
- } else if (pace->e_tag == ACL_GROUP) {
- gid_t gid;
-
- gid = posix_acl_gid_translate(user_ns, pace);
- id_to_sid(gid, SIDCREATOR_GROUP, sid);
- } else {
- kfree(sid);
- continue;
- }
-
- ntace = (struct smb_ace *)((char *)pndace + *size);
- *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
- pace->e_perm, 0777);
- (*num_aces)++;
- if (pace->e_tag == ACL_USER)
- ntace->access_req |=
- FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
- kfree(sid);
- }
-}
-
-static void set_ntacl_dacl(struct user_namespace *user_ns,
- struct smb_acl *pndacl,
- struct smb_acl *nt_dacl,
- unsigned int aces_size,
- const struct smb_sid *pownersid,
- const struct smb_sid *pgrpsid,
- struct smb_fattr *fattr)
-{
- struct smb_ace *ntace, *pndace;
- int nt_num_aces = le32_to_cpu(nt_dacl->num_aces), num_aces = 0;
- unsigned short size = 0;
- int i;
-
- pndace = (struct smb_ace *)((char *)pndacl + sizeof(struct smb_acl));
- if (nt_num_aces) {
- ntace = (struct smb_ace *)((char *)nt_dacl + sizeof(struct smb_acl));
- for (i = 0; i < nt_num_aces; i++) {
- unsigned short nt_ace_size;
-
- if (offsetof(struct smb_ace, access_req) > aces_size)
- break;
-
- nt_ace_size = le16_to_cpu(ntace->size);
- if (nt_ace_size > aces_size)
- break;
-
- memcpy((char *)pndace + size, ntace, nt_ace_size);
- size += nt_ace_size;
- aces_size -= nt_ace_size;
- ntace = (struct smb_ace *)((char *)ntace + nt_ace_size);
- num_aces++;
- }
- }
-
- set_posix_acl_entries_dacl(user_ns, pndace, fattr,
- &num_aces, &size, nt_num_aces);
- pndacl->num_aces = cpu_to_le32(num_aces);
- pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
-}
-
-static void set_mode_dacl(struct user_namespace *user_ns,
- struct smb_acl *pndacl, struct smb_fattr *fattr)
-{
- struct smb_ace *pace, *pndace;
- u32 num_aces = 0;
- u16 size = 0, ace_size = 0;
- uid_t uid;
- const struct smb_sid *sid;
-
- pace = pndace = (struct smb_ace *)((char *)pndacl + sizeof(struct smb_acl));
-
- if (fattr->cf_acls) {
- set_posix_acl_entries_dacl(user_ns, pndace, fattr,
- &num_aces, &size, num_aces);
- goto out;
- }
-
- /* owner RID */
- uid = from_kuid(&init_user_ns, fattr->cf_uid);
- if (uid)
- sid = &server_conf.domain_sid;
- else
- sid = &sid_unix_users;
- ace_size = fill_ace_for_sid(pace, sid, ACCESS_ALLOWED, 0,
- fattr->cf_mode, 0700);
- pace->sid.sub_auth[pace->sid.num_subauth++] = cpu_to_le32(uid);
- pace->size = cpu_to_le16(ace_size + 4);
- size += le16_to_cpu(pace->size);
- pace = (struct smb_ace *)((char *)pndace + size);
-
- /* Group RID */
- ace_size = fill_ace_for_sid(pace, &sid_unix_groups,
- ACCESS_ALLOWED, 0, fattr->cf_mode, 0070);
- pace->sid.sub_auth[pace->sid.num_subauth++] =
- cpu_to_le32(from_kgid(&init_user_ns, fattr->cf_gid));
- pace->size = cpu_to_le16(ace_size + 4);
- size += le16_to_cpu(pace->size);
- pace = (struct smb_ace *)((char *)pndace + size);
- num_aces = 3;
-
- if (S_ISDIR(fattr->cf_mode)) {
- pace = (struct smb_ace *)((char *)pndace + size);
-
- /* creator owner */
- size += fill_ace_for_sid(pace, &creator_owner, ACCESS_ALLOWED,
- 0x0b, fattr->cf_mode, 0700);
- pace = (struct smb_ace *)((char *)pndace + size);
-
- /* creator group */
- size += fill_ace_for_sid(pace, &creator_group, ACCESS_ALLOWED,
- 0x0b, fattr->cf_mode, 0070);
- pace = (struct smb_ace *)((char *)pndace + size);
- num_aces = 5;
- }
-
- /* other */
- size += fill_ace_for_sid(pace, &sid_everyone, ACCESS_ALLOWED, 0,
- fattr->cf_mode, 0007);
-
-out:
- pndacl->num_aces = cpu_to_le32(num_aces);
- pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
-}
-
-static int parse_sid(struct smb_sid *psid, char *end_of_acl)
-{
- /*
- * validate that we do not go past end of ACL - sid must be at least 8
- * bytes long (assuming no sub-auths - e.g. the null SID
- */
- if (end_of_acl < (char *)psid + 8) {
- pr_err("ACL too small to parse SID %p\n", psid);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* Convert CIFS ACL to POSIX form */
-int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
- int acl_len, struct smb_fattr *fattr)
-{
- int rc = 0;
- struct smb_sid *owner_sid_ptr, *group_sid_ptr;
- struct smb_acl *dacl_ptr; /* no need for SACL ptr */
- char *end_of_acl = ((char *)pntsd) + acl_len;
- __u32 dacloffset;
- int pntsd_type;
-
- if (!pntsd)
- return -EIO;
-
- if (acl_len < sizeof(struct smb_ntsd))
- return -EINVAL;
-
- owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->osidoffset));
- group_sid_ptr = (struct smb_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->gsidoffset));
- dacloffset = le32_to_cpu(pntsd->dacloffset);
- dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
- ksmbd_debug(SMB,
- "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
- pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
- le32_to_cpu(pntsd->gsidoffset),
- le32_to_cpu(pntsd->sacloffset), dacloffset);
-
- pntsd_type = le16_to_cpu(pntsd->type);
- if (!(pntsd_type & DACL_PRESENT)) {
- ksmbd_debug(SMB, "DACL_PRESENT in DACL type is not set\n");
- return rc;
- }
-
- pntsd->type = cpu_to_le16(DACL_PRESENT);
-
- if (pntsd->osidoffset) {
- rc = parse_sid(owner_sid_ptr, end_of_acl);
- if (rc) {
- pr_err("%s: Error %d parsing Owner SID\n", __func__, rc);
- return rc;
- }
-
- rc = sid_to_id(user_ns, owner_sid_ptr, SIDOWNER, fattr);
- if (rc) {
- pr_err("%s: Error %d mapping Owner SID to uid\n",
- __func__, rc);
- owner_sid_ptr = NULL;
- }
- }
-
- if (pntsd->gsidoffset) {
- rc = parse_sid(group_sid_ptr, end_of_acl);
- if (rc) {
- pr_err("%s: Error %d mapping Owner SID to gid\n",
- __func__, rc);
- return rc;
- }
- rc = sid_to_id(user_ns, group_sid_ptr, SIDUNIX_GROUP, fattr);
- if (rc) {
- pr_err("%s: Error %d mapping Group SID to gid\n",
- __func__, rc);
- group_sid_ptr = NULL;
- }
- }
-
- if ((pntsd_type & (DACL_AUTO_INHERITED | DACL_AUTO_INHERIT_REQ)) ==
- (DACL_AUTO_INHERITED | DACL_AUTO_INHERIT_REQ))
- pntsd->type |= cpu_to_le16(DACL_AUTO_INHERITED);
- if (pntsd_type & DACL_PROTECTED)
- pntsd->type |= cpu_to_le16(DACL_PROTECTED);
-
- if (dacloffset) {
- parse_dacl(user_ns, dacl_ptr, end_of_acl,
- owner_sid_ptr, group_sid_ptr, fattr);
- }
-
- return 0;
-}
-
-/* Convert permission bits from mode to equivalent CIFS ACL */
-int build_sec_desc(struct user_namespace *user_ns,
- struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
- int ppntsd_size, int addition_info, __u32 *secdesclen,
- struct smb_fattr *fattr)
-{
- int rc = 0;
- __u32 offset;
- struct smb_sid *owner_sid_ptr, *group_sid_ptr;
- struct smb_sid *nowner_sid_ptr, *ngroup_sid_ptr;
- struct smb_acl *dacl_ptr = NULL; /* no need for SACL ptr */
- uid_t uid;
- gid_t gid;
- unsigned int sid_type = SIDOWNER;
-
- nowner_sid_ptr = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
- if (!nowner_sid_ptr)
- return -ENOMEM;
-
- uid = from_kuid(&init_user_ns, fattr->cf_uid);
- if (!uid)
- sid_type = SIDUNIX_USER;
- id_to_sid(uid, sid_type, nowner_sid_ptr);
-
- ngroup_sid_ptr = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
- if (!ngroup_sid_ptr) {
- kfree(nowner_sid_ptr);
- return -ENOMEM;
- }
-
- gid = from_kgid(&init_user_ns, fattr->cf_gid);
- id_to_sid(gid, SIDUNIX_GROUP, ngroup_sid_ptr);
-
- offset = sizeof(struct smb_ntsd);
- pntsd->sacloffset = 0;
- pntsd->revision = cpu_to_le16(1);
- pntsd->type = cpu_to_le16(SELF_RELATIVE);
- if (ppntsd)
- pntsd->type |= ppntsd->type;
-
- if (addition_info & OWNER_SECINFO) {
- pntsd->osidoffset = cpu_to_le32(offset);
- owner_sid_ptr = (struct smb_sid *)((char *)pntsd + offset);
- smb_copy_sid(owner_sid_ptr, nowner_sid_ptr);
- offset += 1 + 1 + 6 + (nowner_sid_ptr->num_subauth * 4);
- }
-
- if (addition_info & GROUP_SECINFO) {
- pntsd->gsidoffset = cpu_to_le32(offset);
- group_sid_ptr = (struct smb_sid *)((char *)pntsd + offset);
- smb_copy_sid(group_sid_ptr, ngroup_sid_ptr);
- offset += 1 + 1 + 6 + (ngroup_sid_ptr->num_subauth * 4);
- }
-
- if (addition_info & DACL_SECINFO) {
- pntsd->type |= cpu_to_le16(DACL_PRESENT);
- dacl_ptr = (struct smb_acl *)((char *)pntsd + offset);
- dacl_ptr->revision = cpu_to_le16(2);
- dacl_ptr->size = cpu_to_le16(sizeof(struct smb_acl));
- dacl_ptr->num_aces = 0;
-
- if (!ppntsd) {
- set_mode_dacl(user_ns, dacl_ptr, fattr);
- } else {
- struct smb_acl *ppdacl_ptr;
- unsigned int dacl_offset = le32_to_cpu(ppntsd->dacloffset);
- int ppdacl_size, ntacl_size = ppntsd_size - dacl_offset;
-
- if (!dacl_offset ||
- (dacl_offset + sizeof(struct smb_acl) > ppntsd_size))
- goto out;
-
- ppdacl_ptr = (struct smb_acl *)((char *)ppntsd + dacl_offset);
- ppdacl_size = le16_to_cpu(ppdacl_ptr->size);
- if (ppdacl_size > ntacl_size ||
- ppdacl_size < sizeof(struct smb_acl))
- goto out;
-
- set_ntacl_dacl(user_ns, dacl_ptr, ppdacl_ptr,
- ntacl_size - sizeof(struct smb_acl),
- nowner_sid_ptr, ngroup_sid_ptr,
- fattr);
- }
- pntsd->dacloffset = cpu_to_le32(offset);
- offset += le16_to_cpu(dacl_ptr->size);
- }
-
-out:
- kfree(nowner_sid_ptr);
- kfree(ngroup_sid_ptr);
- *secdesclen = offset;
- return rc;
-}
-
-static void smb_set_ace(struct smb_ace *ace, const struct smb_sid *sid, u8 type,
- u8 flags, __le32 access_req)
-{
- ace->type = type;
- ace->flags = flags;
- ace->access_req = access_req;
- smb_copy_sid(&ace->sid, sid);
- ace->size = cpu_to_le16(1 + 1 + 2 + 4 + 1 + 1 + 6 + (sid->num_subauth * 4));
-}
-
-int smb_inherit_dacl(struct ksmbd_conn *conn,
- const struct path *path,
- unsigned int uid, unsigned int gid)
-{
- const struct smb_sid *psid, *creator = NULL;
- struct smb_ace *parent_aces, *aces;
- struct smb_acl *parent_pdacl;
- struct smb_ntsd *parent_pntsd = NULL;
- struct smb_sid owner_sid, group_sid;
- struct dentry *parent = path->dentry->d_parent;
- struct user_namespace *user_ns = mnt_user_ns(path->mnt);
- int inherited_flags = 0, flags = 0, i, ace_cnt = 0, nt_size = 0, pdacl_size;
- int rc = 0, num_aces, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size;
- char *aces_base;
- bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
-
- pntsd_size = ksmbd_vfs_get_sd_xattr(conn, user_ns,
- parent, &parent_pntsd);
- if (pntsd_size <= 0)
- return -ENOENT;
- dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
- if (!dacloffset || (dacloffset + sizeof(struct smb_acl) > pntsd_size)) {
- rc = -EINVAL;
- goto free_parent_pntsd;
- }
-
- parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset);
- acl_len = pntsd_size - dacloffset;
- num_aces = le32_to_cpu(parent_pdacl->num_aces);
- pntsd_type = le16_to_cpu(parent_pntsd->type);
- pdacl_size = le16_to_cpu(parent_pdacl->size);
-
- if (pdacl_size > acl_len || pdacl_size < sizeof(struct smb_acl)) {
- rc = -EINVAL;
- goto free_parent_pntsd;
- }
-
- aces_base = kmalloc(sizeof(struct smb_ace) * num_aces * 2, GFP_KERNEL);
- if (!aces_base) {
- rc = -ENOMEM;
- goto free_parent_pntsd;
- }
-
- aces = (struct smb_ace *)aces_base;
- parent_aces = (struct smb_ace *)((char *)parent_pdacl +
- sizeof(struct smb_acl));
- aces_size = acl_len - sizeof(struct smb_acl);
-
- if (pntsd_type & DACL_AUTO_INHERITED)
- inherited_flags = INHERITED_ACE;
-
- for (i = 0; i < num_aces; i++) {
- int pace_size;
-
- if (offsetof(struct smb_ace, access_req) > aces_size)
- break;
-
- pace_size = le16_to_cpu(parent_aces->size);
- if (pace_size > aces_size)
- break;
-
- aces_size -= pace_size;
-
- flags = parent_aces->flags;
- if (!smb_inherit_flags(flags, is_dir))
- goto pass;
- if (is_dir) {
- flags &= ~(INHERIT_ONLY_ACE | INHERITED_ACE);
- if (!(flags & CONTAINER_INHERIT_ACE))
- flags |= INHERIT_ONLY_ACE;
- if (flags & NO_PROPAGATE_INHERIT_ACE)
- flags = 0;
- } else {
- flags = 0;
- }
-
- if (!compare_sids(&creator_owner, &parent_aces->sid)) {
- creator = &creator_owner;
- id_to_sid(uid, SIDOWNER, &owner_sid);
- psid = &owner_sid;
- } else if (!compare_sids(&creator_group, &parent_aces->sid)) {
- creator = &creator_group;
- id_to_sid(gid, SIDUNIX_GROUP, &group_sid);
- psid = &group_sid;
- } else {
- creator = NULL;
- psid = &parent_aces->sid;
- }
-
- if (is_dir && creator && flags & CONTAINER_INHERIT_ACE) {
- smb_set_ace(aces, psid, parent_aces->type, inherited_flags,
- parent_aces->access_req);
- nt_size += le16_to_cpu(aces->size);
- ace_cnt++;
- aces = (struct smb_ace *)((char *)aces + le16_to_cpu(aces->size));
- flags |= INHERIT_ONLY_ACE;
- psid = creator;
- } else if (is_dir && !(parent_aces->flags & NO_PROPAGATE_INHERIT_ACE)) {
- psid = &parent_aces->sid;
- }
-
- smb_set_ace(aces, psid, parent_aces->type, flags | inherited_flags,
- parent_aces->access_req);
- nt_size += le16_to_cpu(aces->size);
- aces = (struct smb_ace *)((char *)aces + le16_to_cpu(aces->size));
- ace_cnt++;
-pass:
- parent_aces = (struct smb_ace *)((char *)parent_aces + pace_size);
- }
-
- if (nt_size > 0) {
- struct smb_ntsd *pntsd;
- struct smb_acl *pdacl;
- struct smb_sid *powner_sid = NULL, *pgroup_sid = NULL;
- int powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
-
- if (parent_pntsd->osidoffset) {
- powner_sid = (struct smb_sid *)((char *)parent_pntsd +
- le32_to_cpu(parent_pntsd->osidoffset));
- powner_sid_size = 1 + 1 + 6 + (powner_sid->num_subauth * 4);
- }
- if (parent_pntsd->gsidoffset) {
- pgroup_sid = (struct smb_sid *)((char *)parent_pntsd +
- le32_to_cpu(parent_pntsd->gsidoffset));
- pgroup_sid_size = 1 + 1 + 6 + (pgroup_sid->num_subauth * 4);
- }
-
- pntsd = kzalloc(sizeof(struct smb_ntsd) + powner_sid_size +
- pgroup_sid_size + sizeof(struct smb_acl) +
- nt_size, GFP_KERNEL);
- if (!pntsd) {
- rc = -ENOMEM;
- goto free_aces_base;
- }
-
- pntsd->revision = cpu_to_le16(1);
- pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PRESENT);
- if (le16_to_cpu(parent_pntsd->type) & DACL_AUTO_INHERITED)
- pntsd->type |= cpu_to_le16(DACL_AUTO_INHERITED);
- pntsd_size = sizeof(struct smb_ntsd);
- pntsd->osidoffset = parent_pntsd->osidoffset;
- pntsd->gsidoffset = parent_pntsd->gsidoffset;
- pntsd->dacloffset = parent_pntsd->dacloffset;
-
- if (pntsd->osidoffset) {
- struct smb_sid *owner_sid = (struct smb_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->osidoffset));
- memcpy(owner_sid, powner_sid, powner_sid_size);
- pntsd_size += powner_sid_size;
- }
-
- if (pntsd->gsidoffset) {
- struct smb_sid *group_sid = (struct smb_sid *)((char *)pntsd +
- le32_to_cpu(pntsd->gsidoffset));
- memcpy(group_sid, pgroup_sid, pgroup_sid_size);
- pntsd_size += pgroup_sid_size;
- }
-
- if (pntsd->dacloffset) {
- struct smb_ace *pace;
-
- pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
- pdacl->revision = cpu_to_le16(2);
- pdacl->size = cpu_to_le16(sizeof(struct smb_acl) + nt_size);
- pdacl->num_aces = cpu_to_le32(ace_cnt);
- pace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
- memcpy(pace, aces_base, nt_size);
- pntsd_size += sizeof(struct smb_acl) + nt_size;
- }
-
- ksmbd_vfs_set_sd_xattr(conn, user_ns,
- path->dentry, pntsd, pntsd_size);
- kfree(pntsd);
- }
-
-free_aces_base:
- kfree(aces_base);
-free_parent_pntsd:
- kfree(parent_pntsd);
- return rc;
-}
-
-bool smb_inherit_flags(int flags, bool is_dir)
-{
- if (!is_dir)
- return (flags & OBJECT_INHERIT_ACE) != 0;
-
- if (flags & OBJECT_INHERIT_ACE && !(flags & NO_PROPAGATE_INHERIT_ACE))
- return true;
-
- if (flags & CONTAINER_INHERIT_ACE)
- return true;
- return false;
-}
-
-int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
- __le32 *pdaccess, int uid)
-{
- struct user_namespace *user_ns = mnt_user_ns(path->mnt);
- struct smb_ntsd *pntsd = NULL;
- struct smb_acl *pdacl;
- struct posix_acl *posix_acls;
- int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size, dacl_offset;
- struct smb_sid sid;
- int granted = le32_to_cpu(*pdaccess & ~FILE_MAXIMAL_ACCESS_LE);
- struct smb_ace *ace;
- int i, found = 0;
- unsigned int access_bits = 0;
- struct smb_ace *others_ace = NULL;
- struct posix_acl_entry *pa_entry;
- unsigned int sid_type = SIDOWNER;
- unsigned short ace_size;
-
- ksmbd_debug(SMB, "check permission using windows acl\n");
- pntsd_size = ksmbd_vfs_get_sd_xattr(conn, user_ns,
- path->dentry, &pntsd);
- if (pntsd_size <= 0 || !pntsd)
- goto err_out;
-
- dacl_offset = le32_to_cpu(pntsd->dacloffset);
- if (!dacl_offset ||
- (dacl_offset + sizeof(struct smb_acl) > pntsd_size))
- goto err_out;
-
- pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
- acl_size = pntsd_size - dacl_offset;
- pdacl_size = le16_to_cpu(pdacl->size);
-
- if (pdacl_size > acl_size || pdacl_size < sizeof(struct smb_acl))
- goto err_out;
-
- if (!pdacl->num_aces) {
- if (!(pdacl_size - sizeof(struct smb_acl)) &&
- *pdaccess & ~(FILE_READ_CONTROL_LE | FILE_WRITE_DAC_LE)) {
- rc = -EACCES;
- goto err_out;
- }
- goto err_out;
- }
-
- if (*pdaccess & FILE_MAXIMAL_ACCESS_LE) {
- granted = READ_CONTROL | WRITE_DAC | FILE_READ_ATTRIBUTES |
- DELETE;
-
- ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
- aces_size = acl_size - sizeof(struct smb_acl);
- for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) {
- if (offsetof(struct smb_ace, access_req) > aces_size)
- break;
- ace_size = le16_to_cpu(ace->size);
- if (ace_size > aces_size)
- break;
- aces_size -= ace_size;
- granted |= le32_to_cpu(ace->access_req);
- ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
- }
-
- if (!pdacl->num_aces)
- granted = GENERIC_ALL_FLAGS;
- }
-
- if (!uid)
- sid_type = SIDUNIX_USER;
- id_to_sid(uid, sid_type, &sid);
-
- ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
- aces_size = acl_size - sizeof(struct smb_acl);
- for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) {
- if (offsetof(struct smb_ace, access_req) > aces_size)
- break;
- ace_size = le16_to_cpu(ace->size);
- if (ace_size > aces_size)
- break;
- aces_size -= ace_size;
-
- if (!compare_sids(&sid, &ace->sid) ||
- !compare_sids(&sid_unix_NFS_mode, &ace->sid)) {
- found = 1;
- break;
- }
- if (!compare_sids(&sid_everyone, &ace->sid))
- others_ace = ace;
-
- ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
- }
-
- if (*pdaccess & FILE_MAXIMAL_ACCESS_LE && found) {
- granted = READ_CONTROL | WRITE_DAC | FILE_READ_ATTRIBUTES |
- DELETE;
-
- granted |= le32_to_cpu(ace->access_req);
-
- if (!pdacl->num_aces)
- granted = GENERIC_ALL_FLAGS;
- }
-
- if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
- posix_acls = get_acl(d_inode(path->dentry), ACL_TYPE_ACCESS);
- if (posix_acls && !found) {
- unsigned int id = -1;
-
- pa_entry = posix_acls->a_entries;
- for (i = 0; i < posix_acls->a_count; i++, pa_entry++) {
- if (pa_entry->e_tag == ACL_USER)
- id = posix_acl_uid_translate(user_ns, pa_entry);
- else if (pa_entry->e_tag == ACL_GROUP)
- id = posix_acl_gid_translate(user_ns, pa_entry);
- else
- continue;
-
- if (id == uid) {
- mode_to_access_flags(pa_entry->e_perm,
- 0777,
- &access_bits);
- if (!access_bits)
- access_bits =
- SET_MINIMUM_RIGHTS;
- posix_acl_release(posix_acls);
- goto check_access_bits;
- }
- }
- }
- if (posix_acls)
- posix_acl_release(posix_acls);
- }
-
- if (!found) {
- if (others_ace) {
- ace = others_ace;
- } else {
- ksmbd_debug(SMB, "Can't find corresponding sid\n");
- rc = -EACCES;
- goto err_out;
- }
- }
-
- switch (ace->type) {
- case ACCESS_ALLOWED_ACE_TYPE:
- access_bits = le32_to_cpu(ace->access_req);
- break;
- case ACCESS_DENIED_ACE_TYPE:
- case ACCESS_DENIED_CALLBACK_ACE_TYPE:
- access_bits = le32_to_cpu(~ace->access_req);
- break;
- }
-
-check_access_bits:
- if (granted &
- ~(access_bits | FILE_READ_ATTRIBUTES | READ_CONTROL | WRITE_DAC | DELETE)) {
- ksmbd_debug(SMB, "Access denied with winACL, granted : %x, access_req : %x\n",
- granted, le32_to_cpu(ace->access_req));
- rc = -EACCES;
- goto err_out;
- }
-
- *pdaccess = cpu_to_le32(granted);
-err_out:
- kfree(pntsd);
- return rc;
-}
-
-int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
- const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
- bool type_check)
-{
- int rc;
- struct smb_fattr fattr = {{0}};
- struct inode *inode = d_inode(path->dentry);
- struct user_namespace *user_ns = mnt_user_ns(path->mnt);
- struct iattr newattrs;
-
- fattr.cf_uid = INVALID_UID;
- fattr.cf_gid = INVALID_GID;
- fattr.cf_mode = inode->i_mode;
-
- rc = parse_sec_desc(user_ns, pntsd, ntsd_len, &fattr);
- if (rc)
- goto out;
-
- newattrs.ia_valid = ATTR_CTIME;
- if (!uid_eq(fattr.cf_uid, INVALID_UID)) {
- newattrs.ia_valid |= ATTR_UID;
- newattrs.ia_uid = fattr.cf_uid;
- }
- if (!gid_eq(fattr.cf_gid, INVALID_GID)) {
- newattrs.ia_valid |= ATTR_GID;
- newattrs.ia_gid = fattr.cf_gid;
- }
- newattrs.ia_valid |= ATTR_MODE;
- newattrs.ia_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777);
-
- ksmbd_vfs_remove_acl_xattrs(user_ns, path->dentry);
- /* Update posix acls */
- if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && fattr.cf_dacls) {
- rc = set_posix_acl(user_ns, inode,
- ACL_TYPE_ACCESS, fattr.cf_acls);
- if (rc < 0)
- ksmbd_debug(SMB,
- "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
- rc);
- if (S_ISDIR(inode->i_mode) && fattr.cf_dacls) {
- rc = set_posix_acl(user_ns, inode,
- ACL_TYPE_DEFAULT, fattr.cf_dacls);
- if (rc)
- ksmbd_debug(SMB,
- "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
- rc);
- }
- }
-
- inode_lock(inode);
- rc = notify_change(user_ns, path->dentry, &newattrs, NULL);
- inode_unlock(inode);
- if (rc)
- goto out;
-
- /* Check it only calling from SD BUFFER context */
- if (type_check && !(le16_to_cpu(pntsd->type) & DACL_PRESENT))
- goto out;
-
- if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) {
- /* Update WinACL in xattr */
- ksmbd_vfs_remove_sd_xattrs(user_ns, path->dentry);
- ksmbd_vfs_set_sd_xattr(conn, user_ns,
- path->dentry, pntsd, ntsd_len);
- }
-
-out:
- posix_acl_release(fattr.cf_acls);
- posix_acl_release(fattr.cf_dacls);
- mark_inode_dirty(inode);
- return rc;
-}
-
-void ksmbd_init_domain(u32 *sub_auth)
-{
- int i;
-
- memcpy(&server_conf.domain_sid, &domain, sizeof(struct smb_sid));
- for (i = 0; i < 3; ++i)
- server_conf.domain_sid.sub_auth[i + 1] = cpu_to_le32(sub_auth[i]);
-}
diff --git a/fs/ksmbd/smbacl.h b/fs/ksmbd/smbacl.h
deleted file mode 100644
index 618f2e0236b3..000000000000
--- a/fs/ksmbd/smbacl.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * Copyright (c) International Business Machines Corp., 2007
- * Author(s): Steve French (sfrench@us.ibm.com)
- * Modified by Namjae Jeon (linkinjeon@kernel.org)
- */
-
-#ifndef _SMBACL_H
-#define _SMBACL_H
-
-#include <linux/fs.h>
-#include <linux/namei.h>
-#include <linux/posix_acl.h>
-#include <linux/mnt_idmapping.h>
-
-#include "mgmt/tree_connect.h"
-
-#define NUM_AUTHS (6) /* number of authority fields */
-#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
-
-/*
- * ACE types - see MS-DTYP 2.4.4.1
- */
-enum {
- ACCESS_ALLOWED,
- ACCESS_DENIED,
-};
-
-/*
- * Security ID types
- */
-enum {
- SIDOWNER = 1,
- SIDGROUP,
- SIDCREATOR_OWNER,
- SIDCREATOR_GROUP,
- SIDUNIX_USER,
- SIDUNIX_GROUP,
- SIDNFS_USER,
- SIDNFS_GROUP,
- SIDNFS_MODE,
-};
-
-/* Revision for ACLs */
-#define SD_REVISION 1
-
-/* Control flags for Security Descriptor */
-#define OWNER_DEFAULTED 0x0001
-#define GROUP_DEFAULTED 0x0002
-#define DACL_PRESENT 0x0004
-#define DACL_DEFAULTED 0x0008
-#define SACL_PRESENT 0x0010
-#define SACL_DEFAULTED 0x0020
-#define DACL_TRUSTED 0x0040
-#define SERVER_SECURITY 0x0080
-#define DACL_AUTO_INHERIT_REQ 0x0100
-#define SACL_AUTO_INHERIT_REQ 0x0200
-#define DACL_AUTO_INHERITED 0x0400
-#define SACL_AUTO_INHERITED 0x0800
-#define DACL_PROTECTED 0x1000
-#define SACL_PROTECTED 0x2000
-#define RM_CONTROL_VALID 0x4000
-#define SELF_RELATIVE 0x8000
-
-/* ACE types - see MS-DTYP 2.4.4.1 */
-#define ACCESS_ALLOWED_ACE_TYPE 0x00
-#define ACCESS_DENIED_ACE_TYPE 0x01
-#define SYSTEM_AUDIT_ACE_TYPE 0x02
-#define SYSTEM_ALARM_ACE_TYPE 0x03
-#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
-#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
-#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
-#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
-#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
-#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
-#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
-#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
-#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C
-#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D
-#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */
-#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
-#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
-#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
-#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
-#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13
-
-/* ACE flags */
-#define OBJECT_INHERIT_ACE 0x01
-#define CONTAINER_INHERIT_ACE 0x02
-#define NO_PROPAGATE_INHERIT_ACE 0x04
-#define INHERIT_ONLY_ACE 0x08
-#define INHERITED_ACE 0x10
-#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
-#define FAILED_ACCESS_ACE_FLAG 0x80
-
-/*
- * Maximum size of a string representation of a SID:
- *
- * The fields are unsigned values in decimal. So:
- *
- * u8: max 3 bytes in decimal
- * u32: max 10 bytes in decimal
- *
- * "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
- *
- * For authority field, max is when all 6 values are non-zero and it must be
- * represented in hex. So "-0x" + 12 hex digits.
- *
- * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
- */
-#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
-#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
-
-#define DOMAIN_USER_RID_LE cpu_to_le32(513)
-
-struct ksmbd_conn;
-
-struct smb_ntsd {
- __le16 revision; /* revision level */
- __le16 type;
- __le32 osidoffset;
- __le32 gsidoffset;
- __le32 sacloffset;
- __le32 dacloffset;
-} __packed;
-
-struct smb_sid {
- __u8 revision; /* revision level */
- __u8 num_subauth;
- __u8 authority[NUM_AUTHS];
- __le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
-} __packed;
-
-/* size of a struct cifs_sid, sans sub_auth array */
-#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
-
-struct smb_acl {
- __le16 revision; /* revision level */
- __le16 size;
- __le32 num_aces;
-} __packed;
-
-struct smb_ace {
- __u8 type;
- __u8 flags;
- __le16 size;
- __le32 access_req;
- struct smb_sid sid; /* ie UUID of user or group who gets these perms */
-} __packed;
-
-struct smb_fattr {
- kuid_t cf_uid;
- kgid_t cf_gid;
- umode_t cf_mode;
- __le32 daccess;
- struct posix_acl *cf_acls;
- struct posix_acl *cf_dacls;
-};
-
-struct posix_ace_state {
- u32 allow;
- u32 deny;
-};
-
-struct posix_user_ace_state {
- union {
- kuid_t uid;
- kgid_t gid;
- };
- struct posix_ace_state perms;
-};
-
-struct posix_ace_state_array {
- int n;
- struct posix_user_ace_state aces[];
-};
-
-/*
- * while processing the nfsv4 ace, this maintains the partial permissions
- * calculated so far:
- */
-
-struct posix_acl_state {
- struct posix_ace_state owner;
- struct posix_ace_state group;
- struct posix_ace_state other;
- struct posix_ace_state everyone;
- struct posix_ace_state mask; /* deny unused in this case */
- struct posix_ace_state_array *users;
- struct posix_ace_state_array *groups;
-};
-
-int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
- int acl_len, struct smb_fattr *fattr);
-int build_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
- struct smb_ntsd *ppntsd, int ppntsd_size, int addition_info,
- __u32 *secdesclen, struct smb_fattr *fattr);
-int init_acl_state(struct posix_acl_state *state, int cnt);
-void free_acl_state(struct posix_acl_state *state);
-void posix_state_to_acl(struct posix_acl_state *state,
- struct posix_acl_entry *pace);
-int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid);
-bool smb_inherit_flags(int flags, bool is_dir);
-int smb_inherit_dacl(struct ksmbd_conn *conn, const struct path *path,
- unsigned int uid, unsigned int gid);
-int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
- __le32 *pdaccess, int uid);
-int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
- const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
- bool type_check);
-void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
-void ksmbd_init_domain(u32 *sub_auth);
-
-static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns,
- struct posix_acl_entry *pace)
-{
- vfsuid_t vfsuid;
-
- /* If this is an idmapped mount, apply the idmapping. */
- vfsuid = make_vfsuid(mnt_userns, &init_user_ns, pace->e_uid);
-
- /* Translate the kuid into a userspace id ksmbd would see. */
- return from_kuid(&init_user_ns, vfsuid_into_kuid(vfsuid));
-}
-
-static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns,
- struct posix_acl_entry *pace)
-{
- vfsgid_t vfsgid;
-
- /* If this is an idmapped mount, apply the idmapping. */
- vfsgid = make_vfsgid(mnt_userns, &init_user_ns, pace->e_gid);
-
- /* Translate the kgid into a userspace id ksmbd would see. */
- return from_kgid(&init_user_ns, vfsgid_into_kgid(vfsgid));
-}
-
-#endif /* _SMBACL_H */
diff --git a/fs/ksmbd/smbfsctl.h b/fs/ksmbd/smbfsctl.h
deleted file mode 100644
index b98418aae20c..000000000000
--- a/fs/ksmbd/smbfsctl.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions
- *
- * Copyright (c) International Business Machines Corp., 2002,2009
- * Author(s): Steve French (sfrench@us.ibm.com)
- */
-
-/* IOCTL information */
-/*
- * List of ioctl/fsctl function codes that are or could be useful in the
- * future to remote clients like cifs or SMB2 client. There is probably
- * a slightly larger set of fsctls that NTFS local filesystem could handle,
- * including the seven below that we do not have struct definitions for.
- * Even with protocol definitions for most of these now available, we still
- * need to do some experimentation to identify which are practical to do
- * remotely. Some of the following, such as the encryption/compression ones
- * could be invoked from tools via a specialized hook into the VFS rather
- * than via the standard vfs entry points
- */
-
-#ifndef __KSMBD_SMBFSCTL_H
-#define __KSMBD_SMBFSCTL_H
-
-#define FSCTL_DFS_GET_REFERRALS 0x00060194
-#define FSCTL_DFS_GET_REFERRALS_EX 0x000601B0
-#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
-#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
-#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
-#define FSCTL_LOCK_VOLUME 0x00090018
-#define FSCTL_UNLOCK_VOLUME 0x0009001C
-#define FSCTL_IS_PATHNAME_VALID 0x0009002C /* BB add struct */
-#define FSCTL_GET_COMPRESSION 0x0009003C /* BB add struct */
-#define FSCTL_SET_COMPRESSION 0x0009C040 /* BB add struct */
-#define FSCTL_QUERY_FAT_BPB 0x00090058 /* BB add struct */
-/* Verify the next FSCTL number, we had it as 0x00090090 before */
-#define FSCTL_FILESYSTEM_GET_STATS 0x00090060 /* BB add struct */
-#define FSCTL_GET_NTFS_VOLUME_DATA 0x00090064 /* BB add struct */
-#define FSCTL_GET_RETRIEVAL_POINTERS 0x00090073 /* BB add struct */
-#define FSCTL_IS_VOLUME_DIRTY 0x00090078 /* BB add struct */
-#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x00090083 /* BB add struct */
-#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
-#define FSCTL_FIND_FILES_BY_SID 0x0009008F /* BB add struct */
-#define FSCTL_SET_OBJECT_ID 0x00090098 /* BB add struct */
-#define FSCTL_GET_OBJECT_ID 0x0009009C /* BB add struct */
-#define FSCTL_DELETE_OBJECT_ID 0x000900A0 /* BB add struct */
-#define FSCTL_SET_REPARSE_POINT 0x000900A4 /* BB add struct */
-#define FSCTL_GET_REPARSE_POINT 0x000900A8 /* BB add struct */
-#define FSCTL_DELETE_REPARSE_POINT 0x000900AC /* BB add struct */
-#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */
-#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */
-#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */
-#define FSCTL_SET_ZERO_DATA 0x000980C8 /* BB add struct */
-#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */
-#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */
-#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */
-#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 /* BB add struct */
-#define FSCTL_READ_FILE_USN_DATA 0x000900EB /* BB add struct */
-#define FSCTL_WRITE_USN_CLOSE_RECORD 0x000900EF /* BB add struct */
-#define FSCTL_SIS_COPYFILE 0x00090100 /* BB add struct */
-#define FSCTL_RECALL_FILE 0x00090117 /* BB add struct */
-#define FSCTL_QUERY_SPARING_INFO 0x00090138 /* BB add struct */
-#define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */
-#define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */
-#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF /* BB add struct */
-#define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */
-#define FSCTL_DUPLICATE_EXTENTS_TO_FILE 0x00098344
-#define FSCTL_SIS_LINK_FILES 0x0009C104
-#define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */
-#define FSCTL_PIPE_TRANSCEIVE 0x0011C017 /* BB add struct */
-/* strange that the number for this op is not sequential with previous op */
-#define FSCTL_PIPE_WAIT 0x00110018 /* BB add struct */
-#define FSCTL_REQUEST_RESUME_KEY 0x00140078
-#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
-#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
-#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
-#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC
-#define FSCTL_COPYCHUNK 0x001440F2
-#define FSCTL_COPYCHUNK_WRITE 0x001480F2
-
-#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
-#define IO_REPARSE_TAG_HSM 0xC0000004
-#define IO_REPARSE_TAG_SIS 0x80000007
-
-/* WSL reparse tags */
-#define IO_REPARSE_TAG_LX_SYMLINK_LE cpu_to_le32(0xA000001D)
-#define IO_REPARSE_TAG_AF_UNIX_LE cpu_to_le32(0x80000023)
-#define IO_REPARSE_TAG_LX_FIFO_LE cpu_to_le32(0x80000024)
-#define IO_REPARSE_TAG_LX_CHR_LE cpu_to_le32(0x80000025)
-#define IO_REPARSE_TAG_LX_BLK_LE cpu_to_le32(0x80000026)
-#endif /* __KSMBD_SMBFSCTL_H */
diff --git a/fs/ksmbd/smbstatus.h b/fs/ksmbd/smbstatus.h
deleted file mode 100644
index 108a8b6ed24a..000000000000
--- a/fs/ksmbd/smbstatus.h
+++ /dev/null
@@ -1,1822 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * fs/cifs/smb2status.h
- *
- * SMB2 Status code (network error) definitions
- * Definitions are from MS-ERREF
- *
- * Copyright (c) International Business Machines Corp., 2009,2011
- * Author(s): Steve French (sfrench@us.ibm.com)
- */
-
-/*
- * 0 1 2 3 4 5 6 7 8 9 0 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
- * SEV C N <-------Facility--------> <------Error Status Code------>
- *
- * C is set if "customer defined" error, N bit is reserved and MBZ
- */
-
-#define STATUS_SEVERITY_SUCCESS cpu_to_le32(0x0000)
-#define STATUS_SEVERITY_INFORMATIONAL cpu_to_le32(0x0001)
-#define STATUS_SEVERITY_WARNING cpu_to_le32(0x0002)
-#define STATUS_SEVERITY_ERROR cpu_to_le32(0x0003)
-
-struct ntstatus {
- /* Facility is the high 12 bits of the following field */
- __le32 Facility; /* low 2 bits Severity, next is Customer, then rsrvd */
- __le32 Code;
-};
-
-#define STATUS_SUCCESS 0x00000000
-#define STATUS_WAIT_0 cpu_to_le32(0x00000000)
-#define STATUS_WAIT_1 cpu_to_le32(0x00000001)
-#define STATUS_WAIT_2 cpu_to_le32(0x00000002)
-#define STATUS_WAIT_3 cpu_to_le32(0x00000003)
-#define STATUS_WAIT_63 cpu_to_le32(0x0000003F)
-#define STATUS_ABANDONED cpu_to_le32(0x00000080)
-#define STATUS_ABANDONED_WAIT_0 cpu_to_le32(0x00000080)
-#define STATUS_ABANDONED_WAIT_63 cpu_to_le32(0x000000BF)
-#define STATUS_USER_APC cpu_to_le32(0x000000C0)
-#define STATUS_KERNEL_APC cpu_to_le32(0x00000100)
-#define STATUS_ALERTED cpu_to_le32(0x00000101)
-#define STATUS_TIMEOUT cpu_to_le32(0x00000102)
-#define STATUS_PENDING cpu_to_le32(0x00000103)
-#define STATUS_REPARSE cpu_to_le32(0x00000104)
-#define STATUS_MORE_ENTRIES cpu_to_le32(0x00000105)
-#define STATUS_NOT_ALL_ASSIGNED cpu_to_le32(0x00000106)
-#define STATUS_SOME_NOT_MAPPED cpu_to_le32(0x00000107)
-#define STATUS_OPLOCK_BREAK_IN_PROGRESS cpu_to_le32(0x00000108)
-#define STATUS_VOLUME_MOUNTED cpu_to_le32(0x00000109)
-#define STATUS_RXACT_COMMITTED cpu_to_le32(0x0000010A)
-#define STATUS_NOTIFY_CLEANUP cpu_to_le32(0x0000010B)
-#define STATUS_NOTIFY_ENUM_DIR cpu_to_le32(0x0000010C)
-#define STATUS_NO_QUOTAS_FOR_ACCOUNT cpu_to_le32(0x0000010D)
-#define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED cpu_to_le32(0x0000010E)
-#define STATUS_PAGE_FAULT_TRANSITION cpu_to_le32(0x00000110)
-#define STATUS_PAGE_FAULT_DEMAND_ZERO cpu_to_le32(0x00000111)
-#define STATUS_PAGE_FAULT_COPY_ON_WRITE cpu_to_le32(0x00000112)
-#define STATUS_PAGE_FAULT_GUARD_PAGE cpu_to_le32(0x00000113)
-#define STATUS_PAGE_FAULT_PAGING_FILE cpu_to_le32(0x00000114)
-#define STATUS_CACHE_PAGE_LOCKED cpu_to_le32(0x00000115)
-#define STATUS_CRASH_DUMP cpu_to_le32(0x00000116)
-#define STATUS_BUFFER_ALL_ZEROS cpu_to_le32(0x00000117)
-#define STATUS_REPARSE_OBJECT cpu_to_le32(0x00000118)
-#define STATUS_RESOURCE_REQUIREMENTS_CHANGED cpu_to_le32(0x00000119)
-#define STATUS_TRANSLATION_COMPLETE cpu_to_le32(0x00000120)
-#define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY cpu_to_le32(0x00000121)
-#define STATUS_NOTHING_TO_TERMINATE cpu_to_le32(0x00000122)
-#define STATUS_PROCESS_NOT_IN_JOB cpu_to_le32(0x00000123)
-#define STATUS_PROCESS_IN_JOB cpu_to_le32(0x00000124)
-#define STATUS_VOLSNAP_HIBERNATE_READY cpu_to_le32(0x00000125)
-#define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY cpu_to_le32(0x00000126)
-#define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED cpu_to_le32(0x00000127)
-#define STATUS_INTERRUPT_STILL_CONNECTED cpu_to_le32(0x00000128)
-#define STATUS_PROCESS_CLONED cpu_to_le32(0x00000129)
-#define STATUS_FILE_LOCKED_WITH_ONLY_READERS cpu_to_le32(0x0000012A)
-#define STATUS_FILE_LOCKED_WITH_WRITERS cpu_to_le32(0x0000012B)
-#define STATUS_RESOURCEMANAGER_READ_ONLY cpu_to_le32(0x00000202)
-#define STATUS_WAIT_FOR_OPLOCK cpu_to_le32(0x00000367)
-#define DBG_EXCEPTION_HANDLED cpu_to_le32(0x00010001)
-#define DBG_CONTINUE cpu_to_le32(0x00010002)
-#define STATUS_FLT_IO_COMPLETE cpu_to_le32(0x001C0001)
-#define STATUS_OBJECT_NAME_EXISTS cpu_to_le32(0x40000000)
-#define STATUS_THREAD_WAS_SUSPENDED cpu_to_le32(0x40000001)
-#define STATUS_WORKING_SET_LIMIT_RANGE cpu_to_le32(0x40000002)
-#define STATUS_IMAGE_NOT_AT_BASE cpu_to_le32(0x40000003)
-#define STATUS_RXACT_STATE_CREATED cpu_to_le32(0x40000004)
-#define STATUS_SEGMENT_NOTIFICATION cpu_to_le32(0x40000005)
-#define STATUS_LOCAL_USER_SESSION_KEY cpu_to_le32(0x40000006)
-#define STATUS_BAD_CURRENT_DIRECTORY cpu_to_le32(0x40000007)
-#define STATUS_SERIAL_MORE_WRITES cpu_to_le32(0x40000008)
-#define STATUS_REGISTRY_RECOVERED cpu_to_le32(0x40000009)
-#define STATUS_FT_READ_RECOVERY_FROM_BACKUP cpu_to_le32(0x4000000A)
-#define STATUS_FT_WRITE_RECOVERY cpu_to_le32(0x4000000B)
-#define STATUS_SERIAL_COUNTER_TIMEOUT cpu_to_le32(0x4000000C)
-#define STATUS_NULL_LM_PASSWORD cpu_to_le32(0x4000000D)
-#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH cpu_to_le32(0x4000000E)
-#define STATUS_RECEIVE_PARTIAL cpu_to_le32(0x4000000F)
-#define STATUS_RECEIVE_EXPEDITED cpu_to_le32(0x40000010)
-#define STATUS_RECEIVE_PARTIAL_EXPEDITED cpu_to_le32(0x40000011)
-#define STATUS_EVENT_DONE cpu_to_le32(0x40000012)
-#define STATUS_EVENT_PENDING cpu_to_le32(0x40000013)
-#define STATUS_CHECKING_FILE_SYSTEM cpu_to_le32(0x40000014)
-#define STATUS_FATAL_APP_EXIT cpu_to_le32(0x40000015)
-#define STATUS_PREDEFINED_HANDLE cpu_to_le32(0x40000016)
-#define STATUS_WAS_UNLOCKED cpu_to_le32(0x40000017)
-#define STATUS_SERVICE_NOTIFICATION cpu_to_le32(0x40000018)
-#define STATUS_WAS_LOCKED cpu_to_le32(0x40000019)
-#define STATUS_LOG_HARD_ERROR cpu_to_le32(0x4000001A)
-#define STATUS_ALREADY_WIN32 cpu_to_le32(0x4000001B)
-#define STATUS_WX86_UNSIMULATE cpu_to_le32(0x4000001C)
-#define STATUS_WX86_CONTINUE cpu_to_le32(0x4000001D)
-#define STATUS_WX86_SINGLE_STEP cpu_to_le32(0x4000001E)
-#define STATUS_WX86_BREAKPOINT cpu_to_le32(0x4000001F)
-#define STATUS_WX86_EXCEPTION_CONTINUE cpu_to_le32(0x40000020)
-#define STATUS_WX86_EXCEPTION_LASTCHANCE cpu_to_le32(0x40000021)
-#define STATUS_WX86_EXCEPTION_CHAIN cpu_to_le32(0x40000022)
-#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE cpu_to_le32(0x40000023)
-#define STATUS_NO_YIELD_PERFORMED cpu_to_le32(0x40000024)
-#define STATUS_TIMER_RESUME_IGNORED cpu_to_le32(0x40000025)
-#define STATUS_ARBITRATION_UNHANDLED cpu_to_le32(0x40000026)
-#define STATUS_CARDBUS_NOT_SUPPORTED cpu_to_le32(0x40000027)
-#define STATUS_WX86_CREATEWX86TIB cpu_to_le32(0x40000028)
-#define STATUS_MP_PROCESSOR_MISMATCH cpu_to_le32(0x40000029)
-#define STATUS_HIBERNATED cpu_to_le32(0x4000002A)
-#define STATUS_RESUME_HIBERNATION cpu_to_le32(0x4000002B)
-#define STATUS_FIRMWARE_UPDATED cpu_to_le32(0x4000002C)
-#define STATUS_DRIVERS_LEAKING_LOCKED_PAGES cpu_to_le32(0x4000002D)
-#define STATUS_MESSAGE_RETRIEVED cpu_to_le32(0x4000002E)
-#define STATUS_SYSTEM_POWERSTATE_TRANSITION cpu_to_le32(0x4000002F)
-#define STATUS_ALPC_CHECK_COMPLETION_LIST cpu_to_le32(0x40000030)
-#define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION cpu_to_le32(0x40000031)
-#define STATUS_ACCESS_AUDIT_BY_POLICY cpu_to_le32(0x40000032)
-#define STATUS_ABANDON_HIBERFILE cpu_to_le32(0x40000033)
-#define STATUS_BIZRULES_NOT_ENABLED cpu_to_le32(0x40000034)
-#define STATUS_WAKE_SYSTEM cpu_to_le32(0x40000294)
-#define STATUS_DS_SHUTTING_DOWN cpu_to_le32(0x40000370)
-#define DBG_REPLY_LATER cpu_to_le32(0x40010001)
-#define DBG_UNABLE_TO_PROVIDE_HANDLE cpu_to_le32(0x40010002)
-#define DBG_TERMINATE_THREAD cpu_to_le32(0x40010003)
-#define DBG_TERMINATE_PROCESS cpu_to_le32(0x40010004)
-#define DBG_CONTROL_C cpu_to_le32(0x40010005)
-#define DBG_PRINTEXCEPTION_C cpu_to_le32(0x40010006)
-#define DBG_RIPEXCEPTION cpu_to_le32(0x40010007)
-#define DBG_CONTROL_BREAK cpu_to_le32(0x40010008)
-#define DBG_COMMAND_EXCEPTION cpu_to_le32(0x40010009)
-#define RPC_NT_UUID_LOCAL_ONLY cpu_to_le32(0x40020056)
-#define RPC_NT_SEND_INCOMPLETE cpu_to_le32(0x400200AF)
-#define STATUS_CTX_CDM_CONNECT cpu_to_le32(0x400A0004)
-#define STATUS_CTX_CDM_DISCONNECT cpu_to_le32(0x400A0005)
-#define STATUS_SXS_RELEASE_ACTIVATION_CONTEXT cpu_to_le32(0x4015000D)
-#define STATUS_RECOVERY_NOT_NEEDED cpu_to_le32(0x40190034)
-#define STATUS_RM_ALREADY_STARTED cpu_to_le32(0x40190035)
-#define STATUS_LOG_NO_RESTART cpu_to_le32(0x401A000C)
-#define STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST cpu_to_le32(0x401B00EC)
-#define STATUS_GRAPHICS_PARTIAL_DATA_POPULATED cpu_to_le32(0x401E000A)
-#define STATUS_GRAPHICS_DRIVER_MISMATCH cpu_to_le32(0x401E0117)
-#define STATUS_GRAPHICS_MODE_NOT_PINNED cpu_to_le32(0x401E0307)
-#define STATUS_GRAPHICS_NO_PREFERRED_MODE cpu_to_le32(0x401E031E)
-#define STATUS_GRAPHICS_DATASET_IS_EMPTY cpu_to_le32(0x401E034B)
-#define STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET cpu_to_le32(0x401E034C)
-#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED \
- cpu_to_le32(0x401E0351)
-#define STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS cpu_to_le32(0x401E042F)
-#define STATUS_GRAPHICS_LEADLINK_START_DEFERRED cpu_to_le32(0x401E0437)
-#define STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY cpu_to_le32(0x401E0439)
-#define STATUS_GRAPHICS_START_DEFERRED cpu_to_le32(0x401E043A)
-#define STATUS_NDIS_INDICATION_REQUIRED cpu_to_le32(0x40230001)
-#define STATUS_GUARD_PAGE_VIOLATION cpu_to_le32(0x80000001)
-#define STATUS_DATATYPE_MISALIGNMENT cpu_to_le32(0x80000002)
-#define STATUS_BREAKPOINT cpu_to_le32(0x80000003)
-#define STATUS_SINGLE_STEP cpu_to_le32(0x80000004)
-#define STATUS_BUFFER_OVERFLOW cpu_to_le32(0x80000005)
-#define STATUS_NO_MORE_FILES cpu_to_le32(0x80000006)
-#define STATUS_WAKE_SYSTEM_DEBUGGER cpu_to_le32(0x80000007)
-#define STATUS_HANDLES_CLOSED cpu_to_le32(0x8000000A)
-#define STATUS_NO_INHERITANCE cpu_to_le32(0x8000000B)
-#define STATUS_GUID_SUBSTITUTION_MADE cpu_to_le32(0x8000000C)
-#define STATUS_PARTIAL_COPY cpu_to_le32(0x8000000D)
-#define STATUS_DEVICE_PAPER_EMPTY cpu_to_le32(0x8000000E)
-#define STATUS_DEVICE_POWERED_OFF cpu_to_le32(0x8000000F)
-#define STATUS_DEVICE_OFF_LINE cpu_to_le32(0x80000010)
-#define STATUS_DEVICE_BUSY cpu_to_le32(0x80000011)
-#define STATUS_NO_MORE_EAS cpu_to_le32(0x80000012)
-#define STATUS_INVALID_EA_NAME cpu_to_le32(0x80000013)
-#define STATUS_EA_LIST_INCONSISTENT cpu_to_le32(0x80000014)
-#define STATUS_INVALID_EA_FLAG cpu_to_le32(0x80000015)
-#define STATUS_VERIFY_REQUIRED cpu_to_le32(0x80000016)
-#define STATUS_EXTRANEOUS_INFORMATION cpu_to_le32(0x80000017)
-#define STATUS_RXACT_COMMIT_NECESSARY cpu_to_le32(0x80000018)
-#define STATUS_NO_MORE_ENTRIES cpu_to_le32(0x8000001A)
-#define STATUS_FILEMARK_DETECTED cpu_to_le32(0x8000001B)
-#define STATUS_MEDIA_CHANGED cpu_to_le32(0x8000001C)
-#define STATUS_BUS_RESET cpu_to_le32(0x8000001D)
-#define STATUS_END_OF_MEDIA cpu_to_le32(0x8000001E)
-#define STATUS_BEGINNING_OF_MEDIA cpu_to_le32(0x8000001F)
-#define STATUS_MEDIA_CHECK cpu_to_le32(0x80000020)
-#define STATUS_SETMARK_DETECTED cpu_to_le32(0x80000021)
-#define STATUS_NO_DATA_DETECTED cpu_to_le32(0x80000022)
-#define STATUS_REDIRECTOR_HAS_OPEN_HANDLES cpu_to_le32(0x80000023)
-#define STATUS_SERVER_HAS_OPEN_HANDLES cpu_to_le32(0x80000024)
-#define STATUS_ALREADY_DISCONNECTED cpu_to_le32(0x80000025)
-#define STATUS_LONGJUMP cpu_to_le32(0x80000026)
-#define STATUS_CLEANER_CARTRIDGE_INSTALLED cpu_to_le32(0x80000027)
-#define STATUS_PLUGPLAY_QUERY_VETOED cpu_to_le32(0x80000028)
-#define STATUS_UNWIND_CONSOLIDATE cpu_to_le32(0x80000029)
-#define STATUS_REGISTRY_HIVE_RECOVERED cpu_to_le32(0x8000002A)
-#define STATUS_DLL_MIGHT_BE_INSECURE cpu_to_le32(0x8000002B)
-#define STATUS_DLL_MIGHT_BE_INCOMPATIBLE cpu_to_le32(0x8000002C)
-#define STATUS_STOPPED_ON_SYMLINK cpu_to_le32(0x8000002D)
-#define STATUS_DEVICE_REQUIRES_CLEANING cpu_to_le32(0x80000288)
-#define STATUS_DEVICE_DOOR_OPEN cpu_to_le32(0x80000289)
-#define STATUS_DATA_LOST_REPAIR cpu_to_le32(0x80000803)
-#define DBG_EXCEPTION_NOT_HANDLED cpu_to_le32(0x80010001)
-#define STATUS_CLUSTER_NODE_ALREADY_UP cpu_to_le32(0x80130001)
-#define STATUS_CLUSTER_NODE_ALREADY_DOWN cpu_to_le32(0x80130002)
-#define STATUS_CLUSTER_NETWORK_ALREADY_ONLINE cpu_to_le32(0x80130003)
-#define STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE cpu_to_le32(0x80130004)
-#define STATUS_CLUSTER_NODE_ALREADY_MEMBER cpu_to_le32(0x80130005)
-#define STATUS_COULD_NOT_RESIZE_LOG cpu_to_le32(0x80190009)
-#define STATUS_NO_TXF_METADATA cpu_to_le32(0x80190029)
-#define STATUS_CANT_RECOVER_WITH_HANDLE_OPEN cpu_to_le32(0x80190031)
-#define STATUS_TXF_METADATA_ALREADY_PRESENT cpu_to_le32(0x80190041)
-#define STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET cpu_to_le32(0x80190042)
-#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED \
- cpu_to_le32(0x801B00EB)
-#define STATUS_FLT_BUFFER_TOO_SMALL cpu_to_le32(0x801C0001)
-#define STATUS_FVE_PARTIAL_METADATA cpu_to_le32(0x80210001)
-#define STATUS_UNSUCCESSFUL cpu_to_le32(0xC0000001)
-#define STATUS_NOT_IMPLEMENTED cpu_to_le32(0xC0000002)
-#define STATUS_INVALID_INFO_CLASS cpu_to_le32(0xC0000003)
-#define STATUS_INFO_LENGTH_MISMATCH cpu_to_le32(0xC0000004)
-#define STATUS_ACCESS_VIOLATION cpu_to_le32(0xC0000005)
-#define STATUS_IN_PAGE_ERROR cpu_to_le32(0xC0000006)
-#define STATUS_PAGEFILE_QUOTA cpu_to_le32(0xC0000007)
-#define STATUS_INVALID_HANDLE cpu_to_le32(0xC0000008)
-#define STATUS_BAD_INITIAL_STACK cpu_to_le32(0xC0000009)
-#define STATUS_BAD_INITIAL_PC cpu_to_le32(0xC000000A)
-#define STATUS_INVALID_CID cpu_to_le32(0xC000000B)
-#define STATUS_TIMER_NOT_CANCELED cpu_to_le32(0xC000000C)
-#define STATUS_INVALID_PARAMETER cpu_to_le32(0xC000000D)
-#define STATUS_NO_SUCH_DEVICE cpu_to_le32(0xC000000E)
-#define STATUS_NO_SUCH_FILE cpu_to_le32(0xC000000F)
-#define STATUS_INVALID_DEVICE_REQUEST cpu_to_le32(0xC0000010)
-#define STATUS_END_OF_FILE cpu_to_le32(0xC0000011)
-#define STATUS_WRONG_VOLUME cpu_to_le32(0xC0000012)
-#define STATUS_NO_MEDIA_IN_DEVICE cpu_to_le32(0xC0000013)
-#define STATUS_UNRECOGNIZED_MEDIA cpu_to_le32(0xC0000014)
-#define STATUS_NONEXISTENT_SECTOR cpu_to_le32(0xC0000015)
-#define STATUS_MORE_PROCESSING_REQUIRED cpu_to_le32(0xC0000016)
-#define STATUS_NO_MEMORY cpu_to_le32(0xC0000017)
-#define STATUS_CONFLICTING_ADDRESSES cpu_to_le32(0xC0000018)
-#define STATUS_NOT_MAPPED_VIEW cpu_to_le32(0xC0000019)
-#define STATUS_UNABLE_TO_FREE_VM cpu_to_le32(0xC000001A)
-#define STATUS_UNABLE_TO_DELETE_SECTION cpu_to_le32(0xC000001B)
-#define STATUS_INVALID_SYSTEM_SERVICE cpu_to_le32(0xC000001C)
-#define STATUS_ILLEGAL_INSTRUCTION cpu_to_le32(0xC000001D)
-#define STATUS_INVALID_LOCK_SEQUENCE cpu_to_le32(0xC000001E)
-#define STATUS_INVALID_VIEW_SIZE cpu_to_le32(0xC000001F)
-#define STATUS_INVALID_FILE_FOR_SECTION cpu_to_le32(0xC0000020)
-#define STATUS_ALREADY_COMMITTED cpu_to_le32(0xC0000021)
-#define STATUS_ACCESS_DENIED cpu_to_le32(0xC0000022)
-#define STATUS_BUFFER_TOO_SMALL cpu_to_le32(0xC0000023)
-#define STATUS_OBJECT_TYPE_MISMATCH cpu_to_le32(0xC0000024)
-#define STATUS_NONCONTINUABLE_EXCEPTION cpu_to_le32(0xC0000025)
-#define STATUS_INVALID_DISPOSITION cpu_to_le32(0xC0000026)
-#define STATUS_UNWIND cpu_to_le32(0xC0000027)
-#define STATUS_BAD_STACK cpu_to_le32(0xC0000028)
-#define STATUS_INVALID_UNWIND_TARGET cpu_to_le32(0xC0000029)
-#define STATUS_NOT_LOCKED cpu_to_le32(0xC000002A)
-#define STATUS_PARITY_ERROR cpu_to_le32(0xC000002B)
-#define STATUS_UNABLE_TO_DECOMMIT_VM cpu_to_le32(0xC000002C)
-#define STATUS_NOT_COMMITTED cpu_to_le32(0xC000002D)
-#define STATUS_INVALID_PORT_ATTRIBUTES cpu_to_le32(0xC000002E)
-#define STATUS_PORT_MESSAGE_TOO_LONG cpu_to_le32(0xC000002F)
-#define STATUS_INVALID_PARAMETER_MIX cpu_to_le32(0xC0000030)
-#define STATUS_INVALID_QUOTA_LOWER cpu_to_le32(0xC0000031)
-#define STATUS_DISK_CORRUPT_ERROR cpu_to_le32(0xC0000032)
-#define STATUS_OBJECT_NAME_INVALID cpu_to_le32(0xC0000033)
-#define STATUS_OBJECT_NAME_NOT_FOUND cpu_to_le32(0xC0000034)
-#define STATUS_OBJECT_NAME_COLLISION cpu_to_le32(0xC0000035)
-#define STATUS_PORT_DISCONNECTED cpu_to_le32(0xC0000037)
-#define STATUS_DEVICE_ALREADY_ATTACHED cpu_to_le32(0xC0000038)
-#define STATUS_OBJECT_PATH_INVALID cpu_to_le32(0xC0000039)
-#define STATUS_OBJECT_PATH_NOT_FOUND cpu_to_le32(0xC000003A)
-#define STATUS_OBJECT_PATH_SYNTAX_BAD cpu_to_le32(0xC000003B)
-#define STATUS_DATA_OVERRUN cpu_to_le32(0xC000003C)
-#define STATUS_DATA_LATE_ERROR cpu_to_le32(0xC000003D)
-#define STATUS_DATA_ERROR cpu_to_le32(0xC000003E)
-#define STATUS_CRC_ERROR cpu_to_le32(0xC000003F)
-#define STATUS_SECTION_TOO_BIG cpu_to_le32(0xC0000040)
-#define STATUS_PORT_CONNECTION_REFUSED cpu_to_le32(0xC0000041)
-#define STATUS_INVALID_PORT_HANDLE cpu_to_le32(0xC0000042)
-#define STATUS_SHARING_VIOLATION cpu_to_le32(0xC0000043)
-#define STATUS_QUOTA_EXCEEDED cpu_to_le32(0xC0000044)
-#define STATUS_INVALID_PAGE_PROTECTION cpu_to_le32(0xC0000045)
-#define STATUS_MUTANT_NOT_OWNED cpu_to_le32(0xC0000046)
-#define STATUS_SEMAPHORE_LIMIT_EXCEEDED cpu_to_le32(0xC0000047)
-#define STATUS_PORT_ALREADY_SET cpu_to_le32(0xC0000048)
-#define STATUS_SECTION_NOT_IMAGE cpu_to_le32(0xC0000049)
-#define STATUS_SUSPEND_COUNT_EXCEEDED cpu_to_le32(0xC000004A)
-#define STATUS_THREAD_IS_TERMINATING cpu_to_le32(0xC000004B)
-#define STATUS_BAD_WORKING_SET_LIMIT cpu_to_le32(0xC000004C)
-#define STATUS_INCOMPATIBLE_FILE_MAP cpu_to_le32(0xC000004D)
-#define STATUS_SECTION_PROTECTION cpu_to_le32(0xC000004E)
-#define STATUS_EAS_NOT_SUPPORTED cpu_to_le32(0xC000004F)
-#define STATUS_EA_TOO_LARGE cpu_to_le32(0xC0000050)
-#define STATUS_NONEXISTENT_EA_ENTRY cpu_to_le32(0xC0000051)
-#define STATUS_NO_EAS_ON_FILE cpu_to_le32(0xC0000052)
-#define STATUS_EA_CORRUPT_ERROR cpu_to_le32(0xC0000053)
-#define STATUS_FILE_LOCK_CONFLICT cpu_to_le32(0xC0000054)
-#define STATUS_LOCK_NOT_GRANTED cpu_to_le32(0xC0000055)
-#define STATUS_DELETE_PENDING cpu_to_le32(0xC0000056)
-#define STATUS_CTL_FILE_NOT_SUPPORTED cpu_to_le32(0xC0000057)
-#define STATUS_UNKNOWN_REVISION cpu_to_le32(0xC0000058)
-#define STATUS_REVISION_MISMATCH cpu_to_le32(0xC0000059)
-#define STATUS_INVALID_OWNER cpu_to_le32(0xC000005A)
-#define STATUS_INVALID_PRIMARY_GROUP cpu_to_le32(0xC000005B)
-#define STATUS_NO_IMPERSONATION_TOKEN cpu_to_le32(0xC000005C)
-#define STATUS_CANT_DISABLE_MANDATORY cpu_to_le32(0xC000005D)
-#define STATUS_NO_LOGON_SERVERS cpu_to_le32(0xC000005E)
-#define STATUS_NO_SUCH_LOGON_SESSION cpu_to_le32(0xC000005F)
-#define STATUS_NO_SUCH_PRIVILEGE cpu_to_le32(0xC0000060)
-#define STATUS_PRIVILEGE_NOT_HELD cpu_to_le32(0xC0000061)
-#define STATUS_INVALID_ACCOUNT_NAME cpu_to_le32(0xC0000062)
-#define STATUS_USER_EXISTS cpu_to_le32(0xC0000063)
-#define STATUS_NO_SUCH_USER cpu_to_le32(0xC0000064)
-#define STATUS_GROUP_EXISTS cpu_to_le32(0xC0000065)
-#define STATUS_NO_SUCH_GROUP cpu_to_le32(0xC0000066)
-#define STATUS_MEMBER_IN_GROUP cpu_to_le32(0xC0000067)
-#define STATUS_MEMBER_NOT_IN_GROUP cpu_to_le32(0xC0000068)
-#define STATUS_LAST_ADMIN cpu_to_le32(0xC0000069)
-#define STATUS_WRONG_PASSWORD cpu_to_le32(0xC000006A)
-#define STATUS_ILL_FORMED_PASSWORD cpu_to_le32(0xC000006B)
-#define STATUS_PASSWORD_RESTRICTION cpu_to_le32(0xC000006C)
-#define STATUS_LOGON_FAILURE cpu_to_le32(0xC000006D)
-#define STATUS_ACCOUNT_RESTRICTION cpu_to_le32(0xC000006E)
-#define STATUS_INVALID_LOGON_HOURS cpu_to_le32(0xC000006F)
-#define STATUS_INVALID_WORKSTATION cpu_to_le32(0xC0000070)
-#define STATUS_PASSWORD_EXPIRED cpu_to_le32(0xC0000071)
-#define STATUS_ACCOUNT_DISABLED cpu_to_le32(0xC0000072)
-#define STATUS_NONE_MAPPED cpu_to_le32(0xC0000073)
-#define STATUS_TOO_MANY_LUIDS_REQUESTED cpu_to_le32(0xC0000074)
-#define STATUS_LUIDS_EXHAUSTED cpu_to_le32(0xC0000075)
-#define STATUS_INVALID_SUB_AUTHORITY cpu_to_le32(0xC0000076)
-#define STATUS_INVALID_ACL cpu_to_le32(0xC0000077)
-#define STATUS_INVALID_SID cpu_to_le32(0xC0000078)
-#define STATUS_INVALID_SECURITY_DESCR cpu_to_le32(0xC0000079)
-#define STATUS_PROCEDURE_NOT_FOUND cpu_to_le32(0xC000007A)
-#define STATUS_INVALID_IMAGE_FORMAT cpu_to_le32(0xC000007B)
-#define STATUS_NO_TOKEN cpu_to_le32(0xC000007C)
-#define STATUS_BAD_INHERITANCE_ACL cpu_to_le32(0xC000007D)
-#define STATUS_RANGE_NOT_LOCKED cpu_to_le32(0xC000007E)
-#define STATUS_DISK_FULL cpu_to_le32(0xC000007F)
-#define STATUS_SERVER_DISABLED cpu_to_le32(0xC0000080)
-#define STATUS_SERVER_NOT_DISABLED cpu_to_le32(0xC0000081)
-#define STATUS_TOO_MANY_GUIDS_REQUESTED cpu_to_le32(0xC0000082)
-#define STATUS_GUIDS_EXHAUSTED cpu_to_le32(0xC0000083)
-#define STATUS_INVALID_ID_AUTHORITY cpu_to_le32(0xC0000084)
-#define STATUS_AGENTS_EXHAUSTED cpu_to_le32(0xC0000085)
-#define STATUS_INVALID_VOLUME_LABEL cpu_to_le32(0xC0000086)
-#define STATUS_SECTION_NOT_EXTENDED cpu_to_le32(0xC0000087)
-#define STATUS_NOT_MAPPED_DATA cpu_to_le32(0xC0000088)
-#define STATUS_RESOURCE_DATA_NOT_FOUND cpu_to_le32(0xC0000089)
-#define STATUS_RESOURCE_TYPE_NOT_FOUND cpu_to_le32(0xC000008A)
-#define STATUS_RESOURCE_NAME_NOT_FOUND cpu_to_le32(0xC000008B)
-#define STATUS_ARRAY_BOUNDS_EXCEEDED cpu_to_le32(0xC000008C)
-#define STATUS_FLOAT_DENORMAL_OPERAND cpu_to_le32(0xC000008D)
-#define STATUS_FLOAT_DIVIDE_BY_ZERO cpu_to_le32(0xC000008E)
-#define STATUS_FLOAT_INEXACT_RESULT cpu_to_le32(0xC000008F)
-#define STATUS_FLOAT_INVALID_OPERATION cpu_to_le32(0xC0000090)
-#define STATUS_FLOAT_OVERFLOW cpu_to_le32(0xC0000091)
-#define STATUS_FLOAT_STACK_CHECK cpu_to_le32(0xC0000092)
-#define STATUS_FLOAT_UNDERFLOW cpu_to_le32(0xC0000093)
-#define STATUS_INTEGER_DIVIDE_BY_ZERO cpu_to_le32(0xC0000094)
-#define STATUS_INTEGER_OVERFLOW cpu_to_le32(0xC0000095)
-#define STATUS_PRIVILEGED_INSTRUCTION cpu_to_le32(0xC0000096)
-#define STATUS_TOO_MANY_PAGING_FILES cpu_to_le32(0xC0000097)
-#define STATUS_FILE_INVALID cpu_to_le32(0xC0000098)
-#define STATUS_ALLOTTED_SPACE_EXCEEDED cpu_to_le32(0xC0000099)
-#define STATUS_INSUFFICIENT_RESOURCES cpu_to_le32(0xC000009A)
-#define STATUS_DFS_EXIT_PATH_FOUND cpu_to_le32(0xC000009B)
-#define STATUS_DEVICE_DATA_ERROR cpu_to_le32(0xC000009C)
-#define STATUS_DEVICE_NOT_CONNECTED cpu_to_le32(0xC000009D)
-#define STATUS_DEVICE_POWER_FAILURE cpu_to_le32(0xC000009E)
-#define STATUS_FREE_VM_NOT_AT_BASE cpu_to_le32(0xC000009F)
-#define STATUS_MEMORY_NOT_ALLOCATED cpu_to_le32(0xC00000A0)
-#define STATUS_WORKING_SET_QUOTA cpu_to_le32(0xC00000A1)
-#define STATUS_MEDIA_WRITE_PROTECTED cpu_to_le32(0xC00000A2)
-#define STATUS_DEVICE_NOT_READY cpu_to_le32(0xC00000A3)
-#define STATUS_INVALID_GROUP_ATTRIBUTES cpu_to_le32(0xC00000A4)
-#define STATUS_BAD_IMPERSONATION_LEVEL cpu_to_le32(0xC00000A5)
-#define STATUS_CANT_OPEN_ANONYMOUS cpu_to_le32(0xC00000A6)
-#define STATUS_BAD_VALIDATION_CLASS cpu_to_le32(0xC00000A7)
-#define STATUS_BAD_TOKEN_TYPE cpu_to_le32(0xC00000A8)
-#define STATUS_BAD_MASTER_BOOT_RECORD cpu_to_le32(0xC00000A9)
-#define STATUS_INSTRUCTION_MISALIGNMENT cpu_to_le32(0xC00000AA)
-#define STATUS_INSTANCE_NOT_AVAILABLE cpu_to_le32(0xC00000AB)
-#define STATUS_PIPE_NOT_AVAILABLE cpu_to_le32(0xC00000AC)
-#define STATUS_INVALID_PIPE_STATE cpu_to_le32(0xC00000AD)
-#define STATUS_PIPE_BUSY cpu_to_le32(0xC00000AE)
-#define STATUS_ILLEGAL_FUNCTION cpu_to_le32(0xC00000AF)
-#define STATUS_PIPE_DISCONNECTED cpu_to_le32(0xC00000B0)
-#define STATUS_PIPE_CLOSING cpu_to_le32(0xC00000B1)
-#define STATUS_PIPE_CONNECTED cpu_to_le32(0xC00000B2)
-#define STATUS_PIPE_LISTENING cpu_to_le32(0xC00000B3)
-#define STATUS_INVALID_READ_MODE cpu_to_le32(0xC00000B4)
-#define STATUS_IO_TIMEOUT cpu_to_le32(0xC00000B5)
-#define STATUS_FILE_FORCED_CLOSED cpu_to_le32(0xC00000B6)
-#define STATUS_PROFILING_NOT_STARTED cpu_to_le32(0xC00000B7)
-#define STATUS_PROFILING_NOT_STOPPED cpu_to_le32(0xC00000B8)
-#define STATUS_COULD_NOT_INTERPRET cpu_to_le32(0xC00000B9)
-#define STATUS_FILE_IS_A_DIRECTORY cpu_to_le32(0xC00000BA)
-#define STATUS_NOT_SUPPORTED cpu_to_le32(0xC00000BB)
-#define STATUS_REMOTE_NOT_LISTENING cpu_to_le32(0xC00000BC)
-#define STATUS_DUPLICATE_NAME cpu_to_le32(0xC00000BD)
-#define STATUS_BAD_NETWORK_PATH cpu_to_le32(0xC00000BE)
-#define STATUS_NETWORK_BUSY cpu_to_le32(0xC00000BF)
-#define STATUS_DEVICE_DOES_NOT_EXIST cpu_to_le32(0xC00000C0)
-#define STATUS_TOO_MANY_COMMANDS cpu_to_le32(0xC00000C1)
-#define STATUS_ADAPTER_HARDWARE_ERROR cpu_to_le32(0xC00000C2)
-#define STATUS_INVALID_NETWORK_RESPONSE cpu_to_le32(0xC00000C3)
-#define STATUS_UNEXPECTED_NETWORK_ERROR cpu_to_le32(0xC00000C4)
-#define STATUS_BAD_REMOTE_ADAPTER cpu_to_le32(0xC00000C5)
-#define STATUS_PRINT_QUEUE_FULL cpu_to_le32(0xC00000C6)
-#define STATUS_NO_SPOOL_SPACE cpu_to_le32(0xC00000C7)
-#define STATUS_PRINT_CANCELLED cpu_to_le32(0xC00000C8)
-#define STATUS_NETWORK_NAME_DELETED cpu_to_le32(0xC00000C9)
-#define STATUS_NETWORK_ACCESS_DENIED cpu_to_le32(0xC00000CA)
-#define STATUS_BAD_DEVICE_TYPE cpu_to_le32(0xC00000CB)
-#define STATUS_BAD_NETWORK_NAME cpu_to_le32(0xC00000CC)
-#define STATUS_TOO_MANY_NAMES cpu_to_le32(0xC00000CD)
-#define STATUS_TOO_MANY_SESSIONS cpu_to_le32(0xC00000CE)
-#define STATUS_SHARING_PAUSED cpu_to_le32(0xC00000CF)
-#define STATUS_REQUEST_NOT_ACCEPTED cpu_to_le32(0xC00000D0)
-#define STATUS_REDIRECTOR_PAUSED cpu_to_le32(0xC00000D1)
-#define STATUS_NET_WRITE_FAULT cpu_to_le32(0xC00000D2)
-#define STATUS_PROFILING_AT_LIMIT cpu_to_le32(0xC00000D3)
-#define STATUS_NOT_SAME_DEVICE cpu_to_le32(0xC00000D4)
-#define STATUS_FILE_RENAMED cpu_to_le32(0xC00000D5)
-#define STATUS_VIRTUAL_CIRCUIT_CLOSED cpu_to_le32(0xC00000D6)
-#define STATUS_NO_SECURITY_ON_OBJECT cpu_to_le32(0xC00000D7)
-#define STATUS_CANT_WAIT cpu_to_le32(0xC00000D8)
-#define STATUS_PIPE_EMPTY cpu_to_le32(0xC00000D9)
-#define STATUS_CANT_ACCESS_DOMAIN_INFO cpu_to_le32(0xC00000DA)
-#define STATUS_CANT_TERMINATE_SELF cpu_to_le32(0xC00000DB)
-#define STATUS_INVALID_SERVER_STATE cpu_to_le32(0xC00000DC)
-#define STATUS_INVALID_DOMAIN_STATE cpu_to_le32(0xC00000DD)
-#define STATUS_INVALID_DOMAIN_ROLE cpu_to_le32(0xC00000DE)
-#define STATUS_NO_SUCH_DOMAIN cpu_to_le32(0xC00000DF)
-#define STATUS_DOMAIN_EXISTS cpu_to_le32(0xC00000E0)
-#define STATUS_DOMAIN_LIMIT_EXCEEDED cpu_to_le32(0xC00000E1)
-#define STATUS_OPLOCK_NOT_GRANTED cpu_to_le32(0xC00000E2)
-#define STATUS_INVALID_OPLOCK_PROTOCOL cpu_to_le32(0xC00000E3)
-#define STATUS_INTERNAL_DB_CORRUPTION cpu_to_le32(0xC00000E4)
-#define STATUS_INTERNAL_ERROR cpu_to_le32(0xC00000E5)
-#define STATUS_GENERIC_NOT_MAPPED cpu_to_le32(0xC00000E6)
-#define STATUS_BAD_DESCRIPTOR_FORMAT cpu_to_le32(0xC00000E7)
-#define STATUS_INVALID_USER_BUFFER cpu_to_le32(0xC00000E8)
-#define STATUS_UNEXPECTED_IO_ERROR cpu_to_le32(0xC00000E9)
-#define STATUS_UNEXPECTED_MM_CREATE_ERR cpu_to_le32(0xC00000EA)
-#define STATUS_UNEXPECTED_MM_MAP_ERROR cpu_to_le32(0xC00000EB)
-#define STATUS_UNEXPECTED_MM_EXTEND_ERR cpu_to_le32(0xC00000EC)
-#define STATUS_NOT_LOGON_PROCESS cpu_to_le32(0xC00000ED)
-#define STATUS_LOGON_SESSION_EXISTS cpu_to_le32(0xC00000EE)
-#define STATUS_INVALID_PARAMETER_1 cpu_to_le32(0xC00000EF)
-#define STATUS_INVALID_PARAMETER_2 cpu_to_le32(0xC00000F0)
-#define STATUS_INVALID_PARAMETER_3 cpu_to_le32(0xC00000F1)
-#define STATUS_INVALID_PARAMETER_4 cpu_to_le32(0xC00000F2)
-#define STATUS_INVALID_PARAMETER_5 cpu_to_le32(0xC00000F3)
-#define STATUS_INVALID_PARAMETER_6 cpu_to_le32(0xC00000F4)
-#define STATUS_INVALID_PARAMETER_7 cpu_to_le32(0xC00000F5)
-#define STATUS_INVALID_PARAMETER_8 cpu_to_le32(0xC00000F6)
-#define STATUS_INVALID_PARAMETER_9 cpu_to_le32(0xC00000F7)
-#define STATUS_INVALID_PARAMETER_10 cpu_to_le32(0xC00000F8)
-#define STATUS_INVALID_PARAMETER_11 cpu_to_le32(0xC00000F9)
-#define STATUS_INVALID_PARAMETER_12 cpu_to_le32(0xC00000FA)
-#define STATUS_REDIRECTOR_NOT_STARTED cpu_to_le32(0xC00000FB)
-#define STATUS_REDIRECTOR_STARTED cpu_to_le32(0xC00000FC)
-#define STATUS_STACK_OVERFLOW cpu_to_le32(0xC00000FD)
-#define STATUS_NO_SUCH_PACKAGE cpu_to_le32(0xC00000FE)
-#define STATUS_BAD_FUNCTION_TABLE cpu_to_le32(0xC00000FF)
-#define STATUS_VARIABLE_NOT_FOUND cpu_to_le32(0xC0000100)
-#define STATUS_DIRECTORY_NOT_EMPTY cpu_to_le32(0xC0000101)
-#define STATUS_FILE_CORRUPT_ERROR cpu_to_le32(0xC0000102)
-#define STATUS_NOT_A_DIRECTORY cpu_to_le32(0xC0000103)
-#define STATUS_BAD_LOGON_SESSION_STATE cpu_to_le32(0xC0000104)
-#define STATUS_LOGON_SESSION_COLLISION cpu_to_le32(0xC0000105)
-#define STATUS_NAME_TOO_LONG cpu_to_le32(0xC0000106)
-#define STATUS_FILES_OPEN cpu_to_le32(0xC0000107)
-#define STATUS_CONNECTION_IN_USE cpu_to_le32(0xC0000108)
-#define STATUS_MESSAGE_NOT_FOUND cpu_to_le32(0xC0000109)
-#define STATUS_PROCESS_IS_TERMINATING cpu_to_le32(0xC000010A)
-#define STATUS_INVALID_LOGON_TYPE cpu_to_le32(0xC000010B)
-#define STATUS_NO_GUID_TRANSLATION cpu_to_le32(0xC000010C)
-#define STATUS_CANNOT_IMPERSONATE cpu_to_le32(0xC000010D)
-#define STATUS_IMAGE_ALREADY_LOADED cpu_to_le32(0xC000010E)
-#define STATUS_ABIOS_NOT_PRESENT cpu_to_le32(0xC000010F)
-#define STATUS_ABIOS_LID_NOT_EXIST cpu_to_le32(0xC0000110)
-#define STATUS_ABIOS_LID_ALREADY_OWNED cpu_to_le32(0xC0000111)
-#define STATUS_ABIOS_NOT_LID_OWNER cpu_to_le32(0xC0000112)
-#define STATUS_ABIOS_INVALID_COMMAND cpu_to_le32(0xC0000113)
-#define STATUS_ABIOS_INVALID_LID cpu_to_le32(0xC0000114)
-#define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE cpu_to_le32(0xC0000115)
-#define STATUS_ABIOS_INVALID_SELECTOR cpu_to_le32(0xC0000116)
-#define STATUS_NO_LDT cpu_to_le32(0xC0000117)
-#define STATUS_INVALID_LDT_SIZE cpu_to_le32(0xC0000118)
-#define STATUS_INVALID_LDT_OFFSET cpu_to_le32(0xC0000119)
-#define STATUS_INVALID_LDT_DESCRIPTOR cpu_to_le32(0xC000011A)
-#define STATUS_INVALID_IMAGE_NE_FORMAT cpu_to_le32(0xC000011B)
-#define STATUS_RXACT_INVALID_STATE cpu_to_le32(0xC000011C)
-#define STATUS_RXACT_COMMIT_FAILURE cpu_to_le32(0xC000011D)
-#define STATUS_MAPPED_FILE_SIZE_ZERO cpu_to_le32(0xC000011E)
-#define STATUS_TOO_MANY_OPENED_FILES cpu_to_le32(0xC000011F)
-#define STATUS_CANCELLED cpu_to_le32(0xC0000120)
-#define STATUS_CANNOT_DELETE cpu_to_le32(0xC0000121)
-#define STATUS_INVALID_COMPUTER_NAME cpu_to_le32(0xC0000122)
-#define STATUS_FILE_DELETED cpu_to_le32(0xC0000123)
-#define STATUS_SPECIAL_ACCOUNT cpu_to_le32(0xC0000124)
-#define STATUS_SPECIAL_GROUP cpu_to_le32(0xC0000125)
-#define STATUS_SPECIAL_USER cpu_to_le32(0xC0000126)
-#define STATUS_MEMBERS_PRIMARY_GROUP cpu_to_le32(0xC0000127)
-#define STATUS_FILE_CLOSED cpu_to_le32(0xC0000128)
-#define STATUS_TOO_MANY_THREADS cpu_to_le32(0xC0000129)
-#define STATUS_THREAD_NOT_IN_PROCESS cpu_to_le32(0xC000012A)
-#define STATUS_TOKEN_ALREADY_IN_USE cpu_to_le32(0xC000012B)
-#define STATUS_PAGEFILE_QUOTA_EXCEEDED cpu_to_le32(0xC000012C)
-#define STATUS_COMMITMENT_LIMIT cpu_to_le32(0xC000012D)
-#define STATUS_INVALID_IMAGE_LE_FORMAT cpu_to_le32(0xC000012E)
-#define STATUS_INVALID_IMAGE_NOT_MZ cpu_to_le32(0xC000012F)
-#define STATUS_INVALID_IMAGE_PROTECT cpu_to_le32(0xC0000130)
-#define STATUS_INVALID_IMAGE_WIN_16 cpu_to_le32(0xC0000131)
-#define STATUS_LOGON_SERVER_CONFLICT cpu_to_le32(0xC0000132)
-#define STATUS_TIME_DIFFERENCE_AT_DC cpu_to_le32(0xC0000133)
-#define STATUS_SYNCHRONIZATION_REQUIRED cpu_to_le32(0xC0000134)
-#define STATUS_DLL_NOT_FOUND cpu_to_le32(0xC0000135)
-#define STATUS_OPEN_FAILED cpu_to_le32(0xC0000136)
-#define STATUS_IO_PRIVILEGE_FAILED cpu_to_le32(0xC0000137)
-#define STATUS_ORDINAL_NOT_FOUND cpu_to_le32(0xC0000138)
-#define STATUS_ENTRYPOINT_NOT_FOUND cpu_to_le32(0xC0000139)
-#define STATUS_CONTROL_C_EXIT cpu_to_le32(0xC000013A)
-#define STATUS_LOCAL_DISCONNECT cpu_to_le32(0xC000013B)
-#define STATUS_REMOTE_DISCONNECT cpu_to_le32(0xC000013C)
-#define STATUS_REMOTE_RESOURCES cpu_to_le32(0xC000013D)
-#define STATUS_LINK_FAILED cpu_to_le32(0xC000013E)
-#define STATUS_LINK_TIMEOUT cpu_to_le32(0xC000013F)
-#define STATUS_INVALID_CONNECTION cpu_to_le32(0xC0000140)
-#define STATUS_INVALID_ADDRESS cpu_to_le32(0xC0000141)
-#define STATUS_DLL_INIT_FAILED cpu_to_le32(0xC0000142)
-#define STATUS_MISSING_SYSTEMFILE cpu_to_le32(0xC0000143)
-#define STATUS_UNHANDLED_EXCEPTION cpu_to_le32(0xC0000144)
-#define STATUS_APP_INIT_FAILURE cpu_to_le32(0xC0000145)
-#define STATUS_PAGEFILE_CREATE_FAILED cpu_to_le32(0xC0000146)
-#define STATUS_NO_PAGEFILE cpu_to_le32(0xC0000147)
-#define STATUS_INVALID_LEVEL cpu_to_le32(0xC0000148)
-#define STATUS_WRONG_PASSWORD_CORE cpu_to_le32(0xC0000149)
-#define STATUS_ILLEGAL_FLOAT_CONTEXT cpu_to_le32(0xC000014A)
-#define STATUS_PIPE_BROKEN cpu_to_le32(0xC000014B)
-#define STATUS_REGISTRY_CORRUPT cpu_to_le32(0xC000014C)
-#define STATUS_REGISTRY_IO_FAILED cpu_to_le32(0xC000014D)
-#define STATUS_NO_EVENT_PAIR cpu_to_le32(0xC000014E)
-#define STATUS_UNRECOGNIZED_VOLUME cpu_to_le32(0xC000014F)
-#define STATUS_SERIAL_NO_DEVICE_INITED cpu_to_le32(0xC0000150)
-#define STATUS_NO_SUCH_ALIAS cpu_to_le32(0xC0000151)
-#define STATUS_MEMBER_NOT_IN_ALIAS cpu_to_le32(0xC0000152)
-#define STATUS_MEMBER_IN_ALIAS cpu_to_le32(0xC0000153)
-#define STATUS_ALIAS_EXISTS cpu_to_le32(0xC0000154)
-#define STATUS_LOGON_NOT_GRANTED cpu_to_le32(0xC0000155)
-#define STATUS_TOO_MANY_SECRETS cpu_to_le32(0xC0000156)
-#define STATUS_SECRET_TOO_LONG cpu_to_le32(0xC0000157)
-#define STATUS_INTERNAL_DB_ERROR cpu_to_le32(0xC0000158)
-#define STATUS_FULLSCREEN_MODE cpu_to_le32(0xC0000159)
-#define STATUS_TOO_MANY_CONTEXT_IDS cpu_to_le32(0xC000015A)
-#define STATUS_LOGON_TYPE_NOT_GRANTED cpu_to_le32(0xC000015B)
-#define STATUS_NOT_REGISTRY_FILE cpu_to_le32(0xC000015C)
-#define STATUS_NT_CROSS_ENCRYPTION_REQUIRED cpu_to_le32(0xC000015D)
-#define STATUS_DOMAIN_CTRLR_CONFIG_ERROR cpu_to_le32(0xC000015E)
-#define STATUS_FT_MISSING_MEMBER cpu_to_le32(0xC000015F)
-#define STATUS_ILL_FORMED_SERVICE_ENTRY cpu_to_le32(0xC0000160)
-#define STATUS_ILLEGAL_CHARACTER cpu_to_le32(0xC0000161)
-#define STATUS_UNMAPPABLE_CHARACTER cpu_to_le32(0xC0000162)
-#define STATUS_UNDEFINED_CHARACTER cpu_to_le32(0xC0000163)
-#define STATUS_FLOPPY_VOLUME cpu_to_le32(0xC0000164)
-#define STATUS_FLOPPY_ID_MARK_NOT_FOUND cpu_to_le32(0xC0000165)
-#define STATUS_FLOPPY_WRONG_CYLINDER cpu_to_le32(0xC0000166)
-#define STATUS_FLOPPY_UNKNOWN_ERROR cpu_to_le32(0xC0000167)
-#define STATUS_FLOPPY_BAD_REGISTERS cpu_to_le32(0xC0000168)
-#define STATUS_DISK_RECALIBRATE_FAILED cpu_to_le32(0xC0000169)
-#define STATUS_DISK_OPERATION_FAILED cpu_to_le32(0xC000016A)
-#define STATUS_DISK_RESET_FAILED cpu_to_le32(0xC000016B)
-#define STATUS_SHARED_IRQ_BUSY cpu_to_le32(0xC000016C)
-#define STATUS_FT_ORPHANING cpu_to_le32(0xC000016D)
-#define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT cpu_to_le32(0xC000016E)
-#define STATUS_PARTITION_FAILURE cpu_to_le32(0xC0000172)
-#define STATUS_INVALID_BLOCK_LENGTH cpu_to_le32(0xC0000173)
-#define STATUS_DEVICE_NOT_PARTITIONED cpu_to_le32(0xC0000174)
-#define STATUS_UNABLE_TO_LOCK_MEDIA cpu_to_le32(0xC0000175)
-#define STATUS_UNABLE_TO_UNLOAD_MEDIA cpu_to_le32(0xC0000176)
-#define STATUS_EOM_OVERFLOW cpu_to_le32(0xC0000177)
-#define STATUS_NO_MEDIA cpu_to_le32(0xC0000178)
-#define STATUS_NO_SUCH_MEMBER cpu_to_le32(0xC000017A)
-#define STATUS_INVALID_MEMBER cpu_to_le32(0xC000017B)
-#define STATUS_KEY_DELETED cpu_to_le32(0xC000017C)
-#define STATUS_NO_LOG_SPACE cpu_to_le32(0xC000017D)
-#define STATUS_TOO_MANY_SIDS cpu_to_le32(0xC000017E)
-#define STATUS_LM_CROSS_ENCRYPTION_REQUIRED cpu_to_le32(0xC000017F)
-#define STATUS_KEY_HAS_CHILDREN cpu_to_le32(0xC0000180)
-#define STATUS_CHILD_MUST_BE_VOLATILE cpu_to_le32(0xC0000181)
-#define STATUS_DEVICE_CONFIGURATION_ERROR cpu_to_le32(0xC0000182)
-#define STATUS_DRIVER_INTERNAL_ERROR cpu_to_le32(0xC0000183)
-#define STATUS_INVALID_DEVICE_STATE cpu_to_le32(0xC0000184)
-#define STATUS_IO_DEVICE_ERROR cpu_to_le32(0xC0000185)
-#define STATUS_DEVICE_PROTOCOL_ERROR cpu_to_le32(0xC0000186)
-#define STATUS_BACKUP_CONTROLLER cpu_to_le32(0xC0000187)
-#define STATUS_LOG_FILE_FULL cpu_to_le32(0xC0000188)
-#define STATUS_TOO_LATE cpu_to_le32(0xC0000189)
-#define STATUS_NO_TRUST_LSA_SECRET cpu_to_le32(0xC000018A)
-#define STATUS_NO_TRUST_SAM_ACCOUNT cpu_to_le32(0xC000018B)
-#define STATUS_TRUSTED_DOMAIN_FAILURE cpu_to_le32(0xC000018C)
-#define STATUS_TRUSTED_RELATIONSHIP_FAILURE cpu_to_le32(0xC000018D)
-#define STATUS_EVENTLOG_FILE_CORRUPT cpu_to_le32(0xC000018E)
-#define STATUS_EVENTLOG_CANT_START cpu_to_le32(0xC000018F)
-#define STATUS_TRUST_FAILURE cpu_to_le32(0xC0000190)
-#define STATUS_MUTANT_LIMIT_EXCEEDED cpu_to_le32(0xC0000191)
-#define STATUS_NETLOGON_NOT_STARTED cpu_to_le32(0xC0000192)
-#define STATUS_ACCOUNT_EXPIRED cpu_to_le32(0xC0000193)
-#define STATUS_POSSIBLE_DEADLOCK cpu_to_le32(0xC0000194)
-#define STATUS_NETWORK_CREDENTIAL_CONFLICT cpu_to_le32(0xC0000195)
-#define STATUS_REMOTE_SESSION_LIMIT cpu_to_le32(0xC0000196)
-#define STATUS_EVENTLOG_FILE_CHANGED cpu_to_le32(0xC0000197)
-#define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT cpu_to_le32(0xC0000198)
-#define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT cpu_to_le32(0xC0000199)
-#define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT cpu_to_le32(0xC000019A)
-#define STATUS_DOMAIN_TRUST_INCONSISTENT cpu_to_le32(0xC000019B)
-#define STATUS_FS_DRIVER_REQUIRED cpu_to_le32(0xC000019C)
-#define STATUS_IMAGE_ALREADY_LOADED_AS_DLL cpu_to_le32(0xC000019D)
-#define STATUS_NETWORK_OPEN_RESTRICTION cpu_to_le32(0xC0000201)
-#define STATUS_NO_USER_SESSION_KEY cpu_to_le32(0xC0000202)
-#define STATUS_USER_SESSION_DELETED cpu_to_le32(0xC0000203)
-#define STATUS_RESOURCE_LANG_NOT_FOUND cpu_to_le32(0xC0000204)
-#define STATUS_INSUFF_SERVER_RESOURCES cpu_to_le32(0xC0000205)
-#define STATUS_INVALID_BUFFER_SIZE cpu_to_le32(0xC0000206)
-#define STATUS_INVALID_ADDRESS_COMPONENT cpu_to_le32(0xC0000207)
-#define STATUS_INVALID_ADDRESS_WILDCARD cpu_to_le32(0xC0000208)
-#define STATUS_TOO_MANY_ADDRESSES cpu_to_le32(0xC0000209)
-#define STATUS_ADDRESS_ALREADY_EXISTS cpu_to_le32(0xC000020A)
-#define STATUS_ADDRESS_CLOSED cpu_to_le32(0xC000020B)
-#define STATUS_CONNECTION_DISCONNECTED cpu_to_le32(0xC000020C)
-#define STATUS_CONNECTION_RESET cpu_to_le32(0xC000020D)
-#define STATUS_TOO_MANY_NODES cpu_to_le32(0xC000020E)
-#define STATUS_TRANSACTION_ABORTED cpu_to_le32(0xC000020F)
-#define STATUS_TRANSACTION_TIMED_OUT cpu_to_le32(0xC0000210)
-#define STATUS_TRANSACTION_NO_RELEASE cpu_to_le32(0xC0000211)
-#define STATUS_TRANSACTION_NO_MATCH cpu_to_le32(0xC0000212)
-#define STATUS_TRANSACTION_RESPONDED cpu_to_le32(0xC0000213)
-#define STATUS_TRANSACTION_INVALID_ID cpu_to_le32(0xC0000214)
-#define STATUS_TRANSACTION_INVALID_TYPE cpu_to_le32(0xC0000215)
-#define STATUS_NOT_SERVER_SESSION cpu_to_le32(0xC0000216)
-#define STATUS_NOT_CLIENT_SESSION cpu_to_le32(0xC0000217)
-#define STATUS_CANNOT_LOAD_REGISTRY_FILE cpu_to_le32(0xC0000218)
-#define STATUS_DEBUG_ATTACH_FAILED cpu_to_le32(0xC0000219)
-#define STATUS_SYSTEM_PROCESS_TERMINATED cpu_to_le32(0xC000021A)
-#define STATUS_DATA_NOT_ACCEPTED cpu_to_le32(0xC000021B)
-#define STATUS_NO_BROWSER_SERVERS_FOUND cpu_to_le32(0xC000021C)
-#define STATUS_VDM_HARD_ERROR cpu_to_le32(0xC000021D)
-#define STATUS_DRIVER_CANCEL_TIMEOUT cpu_to_le32(0xC000021E)
-#define STATUS_REPLY_MESSAGE_MISMATCH cpu_to_le32(0xC000021F)
-#define STATUS_MAPPED_ALIGNMENT cpu_to_le32(0xC0000220)
-#define STATUS_IMAGE_CHECKSUM_MISMATCH cpu_to_le32(0xC0000221)
-#define STATUS_LOST_WRITEBEHIND_DATA cpu_to_le32(0xC0000222)
-#define STATUS_CLIENT_SERVER_PARAMETERS_INVALID cpu_to_le32(0xC0000223)
-#define STATUS_PASSWORD_MUST_CHANGE cpu_to_le32(0xC0000224)
-#define STATUS_NOT_FOUND cpu_to_le32(0xC0000225)
-#define STATUS_NOT_TINY_STREAM cpu_to_le32(0xC0000226)
-#define STATUS_RECOVERY_FAILURE cpu_to_le32(0xC0000227)
-#define STATUS_STACK_OVERFLOW_READ cpu_to_le32(0xC0000228)
-#define STATUS_FAIL_CHECK cpu_to_le32(0xC0000229)
-#define STATUS_DUPLICATE_OBJECTID cpu_to_le32(0xC000022A)
-#define STATUS_OBJECTID_EXISTS cpu_to_le32(0xC000022B)
-#define STATUS_CONVERT_TO_LARGE cpu_to_le32(0xC000022C)
-#define STATUS_RETRY cpu_to_le32(0xC000022D)
-#define STATUS_FOUND_OUT_OF_SCOPE cpu_to_le32(0xC000022E)
-#define STATUS_ALLOCATE_BUCKET cpu_to_le32(0xC000022F)
-#define STATUS_PROPSET_NOT_FOUND cpu_to_le32(0xC0000230)
-#define STATUS_MARSHALL_OVERFLOW cpu_to_le32(0xC0000231)
-#define STATUS_INVALID_VARIANT cpu_to_le32(0xC0000232)
-#define STATUS_DOMAIN_CONTROLLER_NOT_FOUND cpu_to_le32(0xC0000233)
-#define STATUS_ACCOUNT_LOCKED_OUT cpu_to_le32(0xC0000234)
-#define STATUS_HANDLE_NOT_CLOSABLE cpu_to_le32(0xC0000235)
-#define STATUS_CONNECTION_REFUSED cpu_to_le32(0xC0000236)
-#define STATUS_GRACEFUL_DISCONNECT cpu_to_le32(0xC0000237)
-#define STATUS_ADDRESS_ALREADY_ASSOCIATED cpu_to_le32(0xC0000238)
-#define STATUS_ADDRESS_NOT_ASSOCIATED cpu_to_le32(0xC0000239)
-#define STATUS_CONNECTION_INVALID cpu_to_le32(0xC000023A)
-#define STATUS_CONNECTION_ACTIVE cpu_to_le32(0xC000023B)
-#define STATUS_NETWORK_UNREACHABLE cpu_to_le32(0xC000023C)
-#define STATUS_HOST_UNREACHABLE cpu_to_le32(0xC000023D)
-#define STATUS_PROTOCOL_UNREACHABLE cpu_to_le32(0xC000023E)
-#define STATUS_PORT_UNREACHABLE cpu_to_le32(0xC000023F)
-#define STATUS_REQUEST_ABORTED cpu_to_le32(0xC0000240)
-#define STATUS_CONNECTION_ABORTED cpu_to_le32(0xC0000241)
-#define STATUS_BAD_COMPRESSION_BUFFER cpu_to_le32(0xC0000242)
-#define STATUS_USER_MAPPED_FILE cpu_to_le32(0xC0000243)
-#define STATUS_AUDIT_FAILED cpu_to_le32(0xC0000244)
-#define STATUS_TIMER_RESOLUTION_NOT_SET cpu_to_le32(0xC0000245)
-#define STATUS_CONNECTION_COUNT_LIMIT cpu_to_le32(0xC0000246)
-#define STATUS_LOGIN_TIME_RESTRICTION cpu_to_le32(0xC0000247)
-#define STATUS_LOGIN_WKSTA_RESTRICTION cpu_to_le32(0xC0000248)
-#define STATUS_IMAGE_MP_UP_MISMATCH cpu_to_le32(0xC0000249)
-#define STATUS_INSUFFICIENT_LOGON_INFO cpu_to_le32(0xC0000250)
-#define STATUS_BAD_DLL_ENTRYPOINT cpu_to_le32(0xC0000251)
-#define STATUS_BAD_SERVICE_ENTRYPOINT cpu_to_le32(0xC0000252)
-#define STATUS_LPC_REPLY_LOST cpu_to_le32(0xC0000253)
-#define STATUS_IP_ADDRESS_CONFLICT1 cpu_to_le32(0xC0000254)
-#define STATUS_IP_ADDRESS_CONFLICT2 cpu_to_le32(0xC0000255)
-#define STATUS_REGISTRY_QUOTA_LIMIT cpu_to_le32(0xC0000256)
-#define STATUS_PATH_NOT_COVERED cpu_to_le32(0xC0000257)
-#define STATUS_NO_CALLBACK_ACTIVE cpu_to_le32(0xC0000258)
-#define STATUS_LICENSE_QUOTA_EXCEEDED cpu_to_le32(0xC0000259)
-#define STATUS_PWD_TOO_SHORT cpu_to_le32(0xC000025A)
-#define STATUS_PWD_TOO_RECENT cpu_to_le32(0xC000025B)
-#define STATUS_PWD_HISTORY_CONFLICT cpu_to_le32(0xC000025C)
-#define STATUS_PLUGPLAY_NO_DEVICE cpu_to_le32(0xC000025E)
-#define STATUS_UNSUPPORTED_COMPRESSION cpu_to_le32(0xC000025F)
-#define STATUS_INVALID_HW_PROFILE cpu_to_le32(0xC0000260)
-#define STATUS_INVALID_PLUGPLAY_DEVICE_PATH cpu_to_le32(0xC0000261)
-#define STATUS_DRIVER_ORDINAL_NOT_FOUND cpu_to_le32(0xC0000262)
-#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND cpu_to_le32(0xC0000263)
-#define STATUS_RESOURCE_NOT_OWNED cpu_to_le32(0xC0000264)
-#define STATUS_TOO_MANY_LINKS cpu_to_le32(0xC0000265)
-#define STATUS_QUOTA_LIST_INCONSISTENT cpu_to_le32(0xC0000266)
-#define STATUS_FILE_IS_OFFLINE cpu_to_le32(0xC0000267)
-#define STATUS_EVALUATION_EXPIRATION cpu_to_le32(0xC0000268)
-#define STATUS_ILLEGAL_DLL_RELOCATION cpu_to_le32(0xC0000269)
-#define STATUS_LICENSE_VIOLATION cpu_to_le32(0xC000026A)
-#define STATUS_DLL_INIT_FAILED_LOGOFF cpu_to_le32(0xC000026B)
-#define STATUS_DRIVER_UNABLE_TO_LOAD cpu_to_le32(0xC000026C)
-#define STATUS_DFS_UNAVAILABLE cpu_to_le32(0xC000026D)
-#define STATUS_VOLUME_DISMOUNTED cpu_to_le32(0xC000026E)
-#define STATUS_WX86_INTERNAL_ERROR cpu_to_le32(0xC000026F)
-#define STATUS_WX86_FLOAT_STACK_CHECK cpu_to_le32(0xC0000270)
-#define STATUS_VALIDATE_CONTINUE cpu_to_le32(0xC0000271)
-#define STATUS_NO_MATCH cpu_to_le32(0xC0000272)
-#define STATUS_NO_MORE_MATCHES cpu_to_le32(0xC0000273)
-#define STATUS_NOT_A_REPARSE_POINT cpu_to_le32(0xC0000275)
-#define STATUS_IO_REPARSE_TAG_INVALID cpu_to_le32(0xC0000276)
-#define STATUS_IO_REPARSE_TAG_MISMATCH cpu_to_le32(0xC0000277)
-#define STATUS_IO_REPARSE_DATA_INVALID cpu_to_le32(0xC0000278)
-#define STATUS_IO_REPARSE_TAG_NOT_HANDLED cpu_to_le32(0xC0000279)
-#define STATUS_REPARSE_POINT_NOT_RESOLVED cpu_to_le32(0xC0000280)
-#define STATUS_DIRECTORY_IS_A_REPARSE_POINT cpu_to_le32(0xC0000281)
-#define STATUS_RANGE_LIST_CONFLICT cpu_to_le32(0xC0000282)
-#define STATUS_SOURCE_ELEMENT_EMPTY cpu_to_le32(0xC0000283)
-#define STATUS_DESTINATION_ELEMENT_FULL cpu_to_le32(0xC0000284)
-#define STATUS_ILLEGAL_ELEMENT_ADDRESS cpu_to_le32(0xC0000285)
-#define STATUS_MAGAZINE_NOT_PRESENT cpu_to_le32(0xC0000286)
-#define STATUS_REINITIALIZATION_NEEDED cpu_to_le32(0xC0000287)
-#define STATUS_ENCRYPTION_FAILED cpu_to_le32(0xC000028A)
-#define STATUS_DECRYPTION_FAILED cpu_to_le32(0xC000028B)
-#define STATUS_RANGE_NOT_FOUND cpu_to_le32(0xC000028C)
-#define STATUS_NO_RECOVERY_POLICY cpu_to_le32(0xC000028D)
-#define STATUS_NO_EFS cpu_to_le32(0xC000028E)
-#define STATUS_WRONG_EFS cpu_to_le32(0xC000028F)
-#define STATUS_NO_USER_KEYS cpu_to_le32(0xC0000290)
-#define STATUS_FILE_NOT_ENCRYPTED cpu_to_le32(0xC0000291)
-#define STATUS_NOT_EXPORT_FORMAT cpu_to_le32(0xC0000292)
-#define STATUS_FILE_ENCRYPTED cpu_to_le32(0xC0000293)
-#define STATUS_WMI_GUID_NOT_FOUND cpu_to_le32(0xC0000295)
-#define STATUS_WMI_INSTANCE_NOT_FOUND cpu_to_le32(0xC0000296)
-#define STATUS_WMI_ITEMID_NOT_FOUND cpu_to_le32(0xC0000297)
-#define STATUS_WMI_TRY_AGAIN cpu_to_le32(0xC0000298)
-#define STATUS_SHARED_POLICY cpu_to_le32(0xC0000299)
-#define STATUS_POLICY_OBJECT_NOT_FOUND cpu_to_le32(0xC000029A)
-#define STATUS_POLICY_ONLY_IN_DS cpu_to_le32(0xC000029B)
-#define STATUS_VOLUME_NOT_UPGRADED cpu_to_le32(0xC000029C)
-#define STATUS_REMOTE_STORAGE_NOT_ACTIVE cpu_to_le32(0xC000029D)
-#define STATUS_REMOTE_STORAGE_MEDIA_ERROR cpu_to_le32(0xC000029E)
-#define STATUS_NO_TRACKING_SERVICE cpu_to_le32(0xC000029F)
-#define STATUS_SERVER_SID_MISMATCH cpu_to_le32(0xC00002A0)
-#define STATUS_DS_NO_ATTRIBUTE_OR_VALUE cpu_to_le32(0xC00002A1)
-#define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX cpu_to_le32(0xC00002A2)
-#define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED cpu_to_le32(0xC00002A3)
-#define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS cpu_to_le32(0xC00002A4)
-#define STATUS_DS_BUSY cpu_to_le32(0xC00002A5)
-#define STATUS_DS_UNAVAILABLE cpu_to_le32(0xC00002A6)
-#define STATUS_DS_NO_RIDS_ALLOCATED cpu_to_le32(0xC00002A7)
-#define STATUS_DS_NO_MORE_RIDS cpu_to_le32(0xC00002A8)
-#define STATUS_DS_INCORRECT_ROLE_OWNER cpu_to_le32(0xC00002A9)
-#define STATUS_DS_RIDMGR_INIT_ERROR cpu_to_le32(0xC00002AA)
-#define STATUS_DS_OBJ_CLASS_VIOLATION cpu_to_le32(0xC00002AB)
-#define STATUS_DS_CANT_ON_NON_LEAF cpu_to_le32(0xC00002AC)
-#define STATUS_DS_CANT_ON_RDN cpu_to_le32(0xC00002AD)
-#define STATUS_DS_CANT_MOD_OBJ_CLASS cpu_to_le32(0xC00002AE)
-#define STATUS_DS_CROSS_DOM_MOVE_FAILED cpu_to_le32(0xC00002AF)
-#define STATUS_DS_GC_NOT_AVAILABLE cpu_to_le32(0xC00002B0)
-#define STATUS_DIRECTORY_SERVICE_REQUIRED cpu_to_le32(0xC00002B1)
-#define STATUS_REPARSE_ATTRIBUTE_CONFLICT cpu_to_le32(0xC00002B2)
-#define STATUS_CANT_ENABLE_DENY_ONLY cpu_to_le32(0xC00002B3)
-#define STATUS_FLOAT_MULTIPLE_FAULTS cpu_to_le32(0xC00002B4)
-#define STATUS_FLOAT_MULTIPLE_TRAPS cpu_to_le32(0xC00002B5)
-#define STATUS_DEVICE_REMOVED cpu_to_le32(0xC00002B6)
-#define STATUS_JOURNAL_DELETE_IN_PROGRESS cpu_to_le32(0xC00002B7)
-#define STATUS_JOURNAL_NOT_ACTIVE cpu_to_le32(0xC00002B8)
-#define STATUS_NOINTERFACE cpu_to_le32(0xC00002B9)
-#define STATUS_DS_ADMIN_LIMIT_EXCEEDED cpu_to_le32(0xC00002C1)
-#define STATUS_DRIVER_FAILED_SLEEP cpu_to_le32(0xC00002C2)
-#define STATUS_MUTUAL_AUTHENTICATION_FAILED cpu_to_le32(0xC00002C3)
-#define STATUS_CORRUPT_SYSTEM_FILE cpu_to_le32(0xC00002C4)
-#define STATUS_DATATYPE_MISALIGNMENT_ERROR cpu_to_le32(0xC00002C5)
-#define STATUS_WMI_READ_ONLY cpu_to_le32(0xC00002C6)
-#define STATUS_WMI_SET_FAILURE cpu_to_le32(0xC00002C7)
-#define STATUS_COMMITMENT_MINIMUM cpu_to_le32(0xC00002C8)
-#define STATUS_REG_NAT_CONSUMPTION cpu_to_le32(0xC00002C9)
-#define STATUS_TRANSPORT_FULL cpu_to_le32(0xC00002CA)
-#define STATUS_DS_SAM_INIT_FAILURE cpu_to_le32(0xC00002CB)
-#define STATUS_ONLY_IF_CONNECTED cpu_to_le32(0xC00002CC)
-#define STATUS_DS_SENSITIVE_GROUP_VIOLATION cpu_to_le32(0xC00002CD)
-#define STATUS_PNP_RESTART_ENUMERATION cpu_to_le32(0xC00002CE)
-#define STATUS_JOURNAL_ENTRY_DELETED cpu_to_le32(0xC00002CF)
-#define STATUS_DS_CANT_MOD_PRIMARYGROUPID cpu_to_le32(0xC00002D0)
-#define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE cpu_to_le32(0xC00002D1)
-#define STATUS_PNP_REBOOT_REQUIRED cpu_to_le32(0xC00002D2)
-#define STATUS_POWER_STATE_INVALID cpu_to_le32(0xC00002D3)
-#define STATUS_DS_INVALID_GROUP_TYPE cpu_to_le32(0xC00002D4)
-#define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN cpu_to_le32(0xC00002D5)
-#define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN cpu_to_le32(0xC00002D6)
-#define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER cpu_to_le32(0xC00002D7)
-#define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER cpu_to_le32(0xC00002D8)
-#define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER cpu_to_le32(0xC00002D9)
-#define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER cpu_to_le32(0xC00002DA)
-#define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER \
- cpu_to_le32(0xC00002DB)
-#define STATUS_DS_HAVE_PRIMARY_MEMBERS cpu_to_le32(0xC00002DC)
-#define STATUS_WMI_NOT_SUPPORTED cpu_to_le32(0xC00002DD)
-#define STATUS_INSUFFICIENT_POWER cpu_to_le32(0xC00002DE)
-#define STATUS_SAM_NEED_BOOTKEY_PASSWORD cpu_to_le32(0xC00002DF)
-#define STATUS_SAM_NEED_BOOTKEY_FLOPPY cpu_to_le32(0xC00002E0)
-#define STATUS_DS_CANT_START cpu_to_le32(0xC00002E1)
-#define STATUS_DS_INIT_FAILURE cpu_to_le32(0xC00002E2)
-#define STATUS_SAM_INIT_FAILURE cpu_to_le32(0xC00002E3)
-#define STATUS_DS_GC_REQUIRED cpu_to_le32(0xC00002E4)
-#define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY cpu_to_le32(0xC00002E5)
-#define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS cpu_to_le32(0xC00002E6)
-#define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED cpu_to_le32(0xC00002E7)
-#define STATUS_MULTIPLE_FAULT_VIOLATION cpu_to_le32(0xC00002E8)
-#define STATUS_CURRENT_DOMAIN_NOT_ALLOWED cpu_to_le32(0xC00002E9)
-#define STATUS_CANNOT_MAKE cpu_to_le32(0xC00002EA)
-#define STATUS_SYSTEM_SHUTDOWN cpu_to_le32(0xC00002EB)
-#define STATUS_DS_INIT_FAILURE_CONSOLE cpu_to_le32(0xC00002EC)
-#define STATUS_DS_SAM_INIT_FAILURE_CONSOLE cpu_to_le32(0xC00002ED)
-#define STATUS_UNFINISHED_CONTEXT_DELETED cpu_to_le32(0xC00002EE)
-#define STATUS_NO_TGT_REPLY cpu_to_le32(0xC00002EF)
-#define STATUS_OBJECTID_NOT_FOUND cpu_to_le32(0xC00002F0)
-#define STATUS_NO_IP_ADDRESSES cpu_to_le32(0xC00002F1)
-#define STATUS_WRONG_CREDENTIAL_HANDLE cpu_to_le32(0xC00002F2)
-#define STATUS_CRYPTO_SYSTEM_INVALID cpu_to_le32(0xC00002F3)
-#define STATUS_MAX_REFERRALS_EXCEEDED cpu_to_le32(0xC00002F4)
-#define STATUS_MUST_BE_KDC cpu_to_le32(0xC00002F5)
-#define STATUS_STRONG_CRYPTO_NOT_SUPPORTED cpu_to_le32(0xC00002F6)
-#define STATUS_TOO_MANY_PRINCIPALS cpu_to_le32(0xC00002F7)
-#define STATUS_NO_PA_DATA cpu_to_le32(0xC00002F8)
-#define STATUS_PKINIT_NAME_MISMATCH cpu_to_le32(0xC00002F9)
-#define STATUS_SMARTCARD_LOGON_REQUIRED cpu_to_le32(0xC00002FA)
-#define STATUS_KDC_INVALID_REQUEST cpu_to_le32(0xC00002FB)
-#define STATUS_KDC_UNABLE_TO_REFER cpu_to_le32(0xC00002FC)
-#define STATUS_KDC_UNKNOWN_ETYPE cpu_to_le32(0xC00002FD)
-#define STATUS_SHUTDOWN_IN_PROGRESS cpu_to_le32(0xC00002FE)
-#define STATUS_SERVER_SHUTDOWN_IN_PROGRESS cpu_to_le32(0xC00002FF)
-#define STATUS_NOT_SUPPORTED_ON_SBS cpu_to_le32(0xC0000300)
-#define STATUS_WMI_GUID_DISCONNECTED cpu_to_le32(0xC0000301)
-#define STATUS_WMI_ALREADY_DISABLED cpu_to_le32(0xC0000302)
-#define STATUS_WMI_ALREADY_ENABLED cpu_to_le32(0xC0000303)
-#define STATUS_MFT_TOO_FRAGMENTED cpu_to_le32(0xC0000304)
-#define STATUS_COPY_PROTECTION_FAILURE cpu_to_le32(0xC0000305)
-#define STATUS_CSS_AUTHENTICATION_FAILURE cpu_to_le32(0xC0000306)
-#define STATUS_CSS_KEY_NOT_PRESENT cpu_to_le32(0xC0000307)
-#define STATUS_CSS_KEY_NOT_ESTABLISHED cpu_to_le32(0xC0000308)
-#define STATUS_CSS_SCRAMBLED_SECTOR cpu_to_le32(0xC0000309)
-#define STATUS_CSS_REGION_MISMATCH cpu_to_le32(0xC000030A)
-#define STATUS_CSS_RESETS_EXHAUSTED cpu_to_le32(0xC000030B)
-#define STATUS_PKINIT_FAILURE cpu_to_le32(0xC0000320)
-#define STATUS_SMARTCARD_SUBSYSTEM_FAILURE cpu_to_le32(0xC0000321)
-#define STATUS_NO_KERB_KEY cpu_to_le32(0xC0000322)
-#define STATUS_HOST_DOWN cpu_to_le32(0xC0000350)
-#define STATUS_UNSUPPORTED_PREAUTH cpu_to_le32(0xC0000351)
-#define STATUS_EFS_ALG_BLOB_TOO_BIG cpu_to_le32(0xC0000352)
-#define STATUS_PORT_NOT_SET cpu_to_le32(0xC0000353)
-#define STATUS_DEBUGGER_INACTIVE cpu_to_le32(0xC0000354)
-#define STATUS_DS_VERSION_CHECK_FAILURE cpu_to_le32(0xC0000355)
-#define STATUS_AUDITING_DISABLED cpu_to_le32(0xC0000356)
-#define STATUS_PRENT4_MACHINE_ACCOUNT cpu_to_le32(0xC0000357)
-#define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER cpu_to_le32(0xC0000358)
-#define STATUS_INVALID_IMAGE_WIN_32 cpu_to_le32(0xC0000359)
-#define STATUS_INVALID_IMAGE_WIN_64 cpu_to_le32(0xC000035A)
-#define STATUS_BAD_BINDINGS cpu_to_le32(0xC000035B)
-#define STATUS_NETWORK_SESSION_EXPIRED cpu_to_le32(0xC000035C)
-#define STATUS_APPHELP_BLOCK cpu_to_le32(0xC000035D)
-#define STATUS_ALL_SIDS_FILTERED cpu_to_le32(0xC000035E)
-#define STATUS_NOT_SAFE_MODE_DRIVER cpu_to_le32(0xC000035F)
-#define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT cpu_to_le32(0xC0000361)
-#define STATUS_ACCESS_DISABLED_BY_POLICY_PATH cpu_to_le32(0xC0000362)
-#define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER cpu_to_le32(0xC0000363)
-#define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER cpu_to_le32(0xC0000364)
-#define STATUS_FAILED_DRIVER_ENTRY cpu_to_le32(0xC0000365)
-#define STATUS_DEVICE_ENUMERATION_ERROR cpu_to_le32(0xC0000366)
-#define STATUS_MOUNT_POINT_NOT_RESOLVED cpu_to_le32(0xC0000368)
-#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER cpu_to_le32(0xC0000369)
-#define STATUS_MCA_OCCURRED cpu_to_le32(0xC000036A)
-#define STATUS_DRIVER_BLOCKED_CRITICAL cpu_to_le32(0xC000036B)
-#define STATUS_DRIVER_BLOCKED cpu_to_le32(0xC000036C)
-#define STATUS_DRIVER_DATABASE_ERROR cpu_to_le32(0xC000036D)
-#define STATUS_SYSTEM_HIVE_TOO_LARGE cpu_to_le32(0xC000036E)
-#define STATUS_INVALID_IMPORT_OF_NON_DLL cpu_to_le32(0xC000036F)
-#define STATUS_NO_SECRETS cpu_to_le32(0xC0000371)
-#define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY cpu_to_le32(0xC0000372)
-#define STATUS_FAILED_STACK_SWITCH cpu_to_le32(0xC0000373)
-#define STATUS_HEAP_CORRUPTION cpu_to_le32(0xC0000374)
-#define STATUS_SMARTCARD_WRONG_PIN cpu_to_le32(0xC0000380)
-#define STATUS_SMARTCARD_CARD_BLOCKED cpu_to_le32(0xC0000381)
-#define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED cpu_to_le32(0xC0000382)
-#define STATUS_SMARTCARD_NO_CARD cpu_to_le32(0xC0000383)
-#define STATUS_SMARTCARD_NO_KEY_CONTAINER cpu_to_le32(0xC0000384)
-#define STATUS_SMARTCARD_NO_CERTIFICATE cpu_to_le32(0xC0000385)
-#define STATUS_SMARTCARD_NO_KEYSET cpu_to_le32(0xC0000386)
-#define STATUS_SMARTCARD_IO_ERROR cpu_to_le32(0xC0000387)
-#define STATUS_DOWNGRADE_DETECTED cpu_to_le32(0xC0000388)
-#define STATUS_SMARTCARD_CERT_REVOKED cpu_to_le32(0xC0000389)
-#define STATUS_ISSUING_CA_UNTRUSTED cpu_to_le32(0xC000038A)
-#define STATUS_REVOCATION_OFFLINE_C cpu_to_le32(0xC000038B)
-#define STATUS_PKINIT_CLIENT_FAILURE cpu_to_le32(0xC000038C)
-#define STATUS_SMARTCARD_CERT_EXPIRED cpu_to_le32(0xC000038D)
-#define STATUS_DRIVER_FAILED_PRIOR_UNLOAD cpu_to_le32(0xC000038E)
-#define STATUS_SMARTCARD_SILENT_CONTEXT cpu_to_le32(0xC000038F)
-#define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000401)
-#define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000402)
-#define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000403)
-#define STATUS_DS_NAME_NOT_UNIQUE cpu_to_le32(0xC0000404)
-#define STATUS_DS_DUPLICATE_ID_FOUND cpu_to_le32(0xC0000405)
-#define STATUS_DS_GROUP_CONVERSION_ERROR cpu_to_le32(0xC0000406)
-#define STATUS_VOLSNAP_PREPARE_HIBERNATE cpu_to_le32(0xC0000407)
-#define STATUS_USER2USER_REQUIRED cpu_to_le32(0xC0000408)
-#define STATUS_STACK_BUFFER_OVERRUN cpu_to_le32(0xC0000409)
-#define STATUS_NO_S4U_PROT_SUPPORT cpu_to_le32(0xC000040A)
-#define STATUS_CROSSREALM_DELEGATION_FAILURE cpu_to_le32(0xC000040B)
-#define STATUS_REVOCATION_OFFLINE_KDC cpu_to_le32(0xC000040C)
-#define STATUS_ISSUING_CA_UNTRUSTED_KDC cpu_to_le32(0xC000040D)
-#define STATUS_KDC_CERT_EXPIRED cpu_to_le32(0xC000040E)
-#define STATUS_KDC_CERT_REVOKED cpu_to_le32(0xC000040F)
-#define STATUS_PARAMETER_QUOTA_EXCEEDED cpu_to_le32(0xC0000410)
-#define STATUS_HIBERNATION_FAILURE cpu_to_le32(0xC0000411)
-#define STATUS_DELAY_LOAD_FAILED cpu_to_le32(0xC0000412)
-#define STATUS_AUTHENTICATION_FIREWALL_FAILED cpu_to_le32(0xC0000413)
-#define STATUS_VDM_DISALLOWED cpu_to_le32(0xC0000414)
-#define STATUS_HUNG_DISPLAY_DRIVER_THREAD cpu_to_le32(0xC0000415)
-#define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE \
- cpu_to_le32(0xC0000416)
-#define STATUS_INVALID_CRUNTIME_PARAMETER cpu_to_le32(0xC0000417)
-#define STATUS_NTLM_BLOCKED cpu_to_le32(0xC0000418)
-#define STATUS_ASSERTION_FAILURE cpu_to_le32(0xC0000420)
-#define STATUS_VERIFIER_STOP cpu_to_le32(0xC0000421)
-#define STATUS_CALLBACK_POP_STACK cpu_to_le32(0xC0000423)
-#define STATUS_INCOMPATIBLE_DRIVER_BLOCKED cpu_to_le32(0xC0000424)
-#define STATUS_HIVE_UNLOADED cpu_to_le32(0xC0000425)
-#define STATUS_COMPRESSION_DISABLED cpu_to_le32(0xC0000426)
-#define STATUS_FILE_SYSTEM_LIMITATION cpu_to_le32(0xC0000427)
-#define STATUS_INVALID_IMAGE_HASH cpu_to_le32(0xC0000428)
-#define STATUS_NOT_CAPABLE cpu_to_le32(0xC0000429)
-#define STATUS_REQUEST_OUT_OF_SEQUENCE cpu_to_le32(0xC000042A)
-#define STATUS_IMPLEMENTATION_LIMIT cpu_to_le32(0xC000042B)
-#define STATUS_ELEVATION_REQUIRED cpu_to_le32(0xC000042C)
-#define STATUS_BEYOND_VDL cpu_to_le32(0xC0000432)
-#define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS cpu_to_le32(0xC0000433)
-#define STATUS_PTE_CHANGED cpu_to_le32(0xC0000434)
-#define STATUS_PURGE_FAILED cpu_to_le32(0xC0000435)
-#define STATUS_CRED_REQUIRES_CONFIRMATION cpu_to_le32(0xC0000440)
-#define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE cpu_to_le32(0xC0000441)
-#define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER cpu_to_le32(0xC0000442)
-#define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE cpu_to_le32(0xC0000443)
-#define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE cpu_to_le32(0xC0000444)
-#define STATUS_CS_ENCRYPTION_FILE_NOT_CSE cpu_to_le32(0xC0000445)
-#define STATUS_INVALID_LABEL cpu_to_le32(0xC0000446)
-#define STATUS_DRIVER_PROCESS_TERMINATED cpu_to_le32(0xC0000450)
-#define STATUS_AMBIGUOUS_SYSTEM_DEVICE cpu_to_le32(0xC0000451)
-#define STATUS_SYSTEM_DEVICE_NOT_FOUND cpu_to_le32(0xC0000452)
-#define STATUS_RESTART_BOOT_APPLICATION cpu_to_le32(0xC0000453)
-#define STATUS_INVALID_TASK_NAME cpu_to_le32(0xC0000500)
-#define STATUS_INVALID_TASK_INDEX cpu_to_le32(0xC0000501)
-#define STATUS_THREAD_ALREADY_IN_TASK cpu_to_le32(0xC0000502)
-#define STATUS_CALLBACK_BYPASS cpu_to_le32(0xC0000503)
-#define STATUS_PORT_CLOSED cpu_to_le32(0xC0000700)
-#define STATUS_MESSAGE_LOST cpu_to_le32(0xC0000701)
-#define STATUS_INVALID_MESSAGE cpu_to_le32(0xC0000702)
-#define STATUS_REQUEST_CANCELED cpu_to_le32(0xC0000703)
-#define STATUS_RECURSIVE_DISPATCH cpu_to_le32(0xC0000704)
-#define STATUS_LPC_RECEIVE_BUFFER_EXPECTED cpu_to_le32(0xC0000705)
-#define STATUS_LPC_INVALID_CONNECTION_USAGE cpu_to_le32(0xC0000706)
-#define STATUS_LPC_REQUESTS_NOT_ALLOWED cpu_to_le32(0xC0000707)
-#define STATUS_RESOURCE_IN_USE cpu_to_le32(0xC0000708)
-#define STATUS_HARDWARE_MEMORY_ERROR cpu_to_le32(0xC0000709)
-#define STATUS_THREADPOOL_HANDLE_EXCEPTION cpu_to_le32(0xC000070A)
-#define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED cpu_to_le32(0xC000070B)
-#define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED \
- cpu_to_le32(0xC000070C)
-#define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED \
- cpu_to_le32(0xC000070D)
-#define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED \
- cpu_to_le32(0xC000070E)
-#define STATUS_THREADPOOL_RELEASED_DURING_OPERATION cpu_to_le32(0xC000070F)
-#define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING cpu_to_le32(0xC0000710)
-#define STATUS_APC_RETURNED_WHILE_IMPERSONATING cpu_to_le32(0xC0000711)
-#define STATUS_PROCESS_IS_PROTECTED cpu_to_le32(0xC0000712)
-#define STATUS_MCA_EXCEPTION cpu_to_le32(0xC0000713)
-#define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE cpu_to_le32(0xC0000714)
-#define STATUS_SYMLINK_CLASS_DISABLED cpu_to_le32(0xC0000715)
-#define STATUS_INVALID_IDN_NORMALIZATION cpu_to_le32(0xC0000716)
-#define STATUS_NO_UNICODE_TRANSLATION cpu_to_le32(0xC0000717)
-#define STATUS_ALREADY_REGISTERED cpu_to_le32(0xC0000718)
-#define STATUS_CONTEXT_MISMATCH cpu_to_le32(0xC0000719)
-#define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST cpu_to_le32(0xC000071A)
-#define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY cpu_to_le32(0xC000071B)
-#define STATUS_INVALID_THREAD cpu_to_le32(0xC000071C)
-#define STATUS_CALLBACK_RETURNED_TRANSACTION cpu_to_le32(0xC000071D)
-#define STATUS_CALLBACK_RETURNED_LDR_LOCK cpu_to_le32(0xC000071E)
-#define STATUS_CALLBACK_RETURNED_LANG cpu_to_le32(0xC000071F)
-#define STATUS_CALLBACK_RETURNED_PRI_BACK cpu_to_le32(0xC0000720)
-#define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY cpu_to_le32(0xC0000721)
-#define STATUS_DISK_REPAIR_DISABLED cpu_to_le32(0xC0000800)
-#define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS cpu_to_le32(0xC0000801)
-#define STATUS_DISK_QUOTA_EXCEEDED cpu_to_le32(0xC0000802)
-#define STATUS_CONTENT_BLOCKED cpu_to_le32(0xC0000804)
-#define STATUS_BAD_CLUSTERS cpu_to_le32(0xC0000805)
-#define STATUS_VOLUME_DIRTY cpu_to_le32(0xC0000806)
-#define STATUS_FILE_CHECKED_OUT cpu_to_le32(0xC0000901)
-#define STATUS_CHECKOUT_REQUIRED cpu_to_le32(0xC0000902)
-#define STATUS_BAD_FILE_TYPE cpu_to_le32(0xC0000903)
-#define STATUS_FILE_TOO_LARGE cpu_to_le32(0xC0000904)
-#define STATUS_FORMS_AUTH_REQUIRED cpu_to_le32(0xC0000905)
-#define STATUS_VIRUS_INFECTED cpu_to_le32(0xC0000906)
-#define STATUS_VIRUS_DELETED cpu_to_le32(0xC0000907)
-#define STATUS_BAD_MCFG_TABLE cpu_to_le32(0xC0000908)
-#define STATUS_WOW_ASSERTION cpu_to_le32(0xC0009898)
-#define STATUS_INVALID_SIGNATURE cpu_to_le32(0xC000A000)
-#define STATUS_HMAC_NOT_SUPPORTED cpu_to_le32(0xC000A001)
-#define STATUS_IPSEC_QUEUE_OVERFLOW cpu_to_le32(0xC000A010)
-#define STATUS_ND_QUEUE_OVERFLOW cpu_to_le32(0xC000A011)
-#define STATUS_HOPLIMIT_EXCEEDED cpu_to_le32(0xC000A012)
-#define STATUS_PROTOCOL_NOT_SUPPORTED cpu_to_le32(0xC000A013)
-#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED \
- cpu_to_le32(0xC000A080)
-#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR \
- cpu_to_le32(0xC000A081)
-#define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR cpu_to_le32(0xC000A082)
-#define STATUS_XML_PARSE_ERROR cpu_to_le32(0xC000A083)
-#define STATUS_XMLDSIG_ERROR cpu_to_le32(0xC000A084)
-#define STATUS_WRONG_COMPARTMENT cpu_to_le32(0xC000A085)
-#define STATUS_AUTHIP_FAILURE cpu_to_le32(0xC000A086)
-#define DBG_NO_STATE_CHANGE cpu_to_le32(0xC0010001)
-#define DBG_APP_NOT_IDLE cpu_to_le32(0xC0010002)
-#define RPC_NT_INVALID_STRING_BINDING cpu_to_le32(0xC0020001)
-#define RPC_NT_WRONG_KIND_OF_BINDING cpu_to_le32(0xC0020002)
-#define RPC_NT_INVALID_BINDING cpu_to_le32(0xC0020003)
-#define RPC_NT_PROTSEQ_NOT_SUPPORTED cpu_to_le32(0xC0020004)
-#define RPC_NT_INVALID_RPC_PROTSEQ cpu_to_le32(0xC0020005)
-#define RPC_NT_INVALID_STRING_UUID cpu_to_le32(0xC0020006)
-#define RPC_NT_INVALID_ENDPOINT_FORMAT cpu_to_le32(0xC0020007)
-#define RPC_NT_INVALID_NET_ADDR cpu_to_le32(0xC0020008)
-#define RPC_NT_NO_ENDPOINT_FOUND cpu_to_le32(0xC0020009)
-#define RPC_NT_INVALID_TIMEOUT cpu_to_le32(0xC002000A)
-#define RPC_NT_OBJECT_NOT_FOUND cpu_to_le32(0xC002000B)
-#define RPC_NT_ALREADY_REGISTERED cpu_to_le32(0xC002000C)
-#define RPC_NT_TYPE_ALREADY_REGISTERED cpu_to_le32(0xC002000D)
-#define RPC_NT_ALREADY_LISTENING cpu_to_le32(0xC002000E)
-#define RPC_NT_NO_PROTSEQS_REGISTERED cpu_to_le32(0xC002000F)
-#define RPC_NT_NOT_LISTENING cpu_to_le32(0xC0020010)
-#define RPC_NT_UNKNOWN_MGR_TYPE cpu_to_le32(0xC0020011)
-#define RPC_NT_UNKNOWN_IF cpu_to_le32(0xC0020012)
-#define RPC_NT_NO_BINDINGS cpu_to_le32(0xC0020013)
-#define RPC_NT_NO_PROTSEQS cpu_to_le32(0xC0020014)
-#define RPC_NT_CANT_CREATE_ENDPOINT cpu_to_le32(0xC0020015)
-#define RPC_NT_OUT_OF_RESOURCES cpu_to_le32(0xC0020016)
-#define RPC_NT_SERVER_UNAVAILABLE cpu_to_le32(0xC0020017)
-#define RPC_NT_SERVER_TOO_BUSY cpu_to_le32(0xC0020018)
-#define RPC_NT_INVALID_NETWORK_OPTIONS cpu_to_le32(0xC0020019)
-#define RPC_NT_NO_CALL_ACTIVE cpu_to_le32(0xC002001A)
-#define RPC_NT_CALL_FAILED cpu_to_le32(0xC002001B)
-#define RPC_NT_CALL_FAILED_DNE cpu_to_le32(0xC002001C)
-#define RPC_NT_PROTOCOL_ERROR cpu_to_le32(0xC002001D)
-#define RPC_NT_UNSUPPORTED_TRANS_SYN cpu_to_le32(0xC002001F)
-#define RPC_NT_UNSUPPORTED_TYPE cpu_to_le32(0xC0020021)
-#define RPC_NT_INVALID_TAG cpu_to_le32(0xC0020022)
-#define RPC_NT_INVALID_BOUND cpu_to_le32(0xC0020023)
-#define RPC_NT_NO_ENTRY_NAME cpu_to_le32(0xC0020024)
-#define RPC_NT_INVALID_NAME_SYNTAX cpu_to_le32(0xC0020025)
-#define RPC_NT_UNSUPPORTED_NAME_SYNTAX cpu_to_le32(0xC0020026)
-#define RPC_NT_UUID_NO_ADDRESS cpu_to_le32(0xC0020028)
-#define RPC_NT_DUPLICATE_ENDPOINT cpu_to_le32(0xC0020029)
-#define RPC_NT_UNKNOWN_AUTHN_TYPE cpu_to_le32(0xC002002A)
-#define RPC_NT_MAX_CALLS_TOO_SMALL cpu_to_le32(0xC002002B)
-#define RPC_NT_STRING_TOO_LONG cpu_to_le32(0xC002002C)
-#define RPC_NT_PROTSEQ_NOT_FOUND cpu_to_le32(0xC002002D)
-#define RPC_NT_PROCNUM_OUT_OF_RANGE cpu_to_le32(0xC002002E)
-#define RPC_NT_BINDING_HAS_NO_AUTH cpu_to_le32(0xC002002F)
-#define RPC_NT_UNKNOWN_AUTHN_SERVICE cpu_to_le32(0xC0020030)
-#define RPC_NT_UNKNOWN_AUTHN_LEVEL cpu_to_le32(0xC0020031)
-#define RPC_NT_INVALID_AUTH_IDENTITY cpu_to_le32(0xC0020032)
-#define RPC_NT_UNKNOWN_AUTHZ_SERVICE cpu_to_le32(0xC0020033)
-#define EPT_NT_INVALID_ENTRY cpu_to_le32(0xC0020034)
-#define EPT_NT_CANT_PERFORM_OP cpu_to_le32(0xC0020035)
-#define EPT_NT_NOT_REGISTERED cpu_to_le32(0xC0020036)
-#define RPC_NT_NOTHING_TO_EXPORT cpu_to_le32(0xC0020037)
-#define RPC_NT_INCOMPLETE_NAME cpu_to_le32(0xC0020038)
-#define RPC_NT_INVALID_VERS_OPTION cpu_to_le32(0xC0020039)
-#define RPC_NT_NO_MORE_MEMBERS cpu_to_le32(0xC002003A)
-#define RPC_NT_NOT_ALL_OBJS_UNEXPORTED cpu_to_le32(0xC002003B)
-#define RPC_NT_INTERFACE_NOT_FOUND cpu_to_le32(0xC002003C)
-#define RPC_NT_ENTRY_ALREADY_EXISTS cpu_to_le32(0xC002003D)
-#define RPC_NT_ENTRY_NOT_FOUND cpu_to_le32(0xC002003E)
-#define RPC_NT_NAME_SERVICE_UNAVAILABLE cpu_to_le32(0xC002003F)
-#define RPC_NT_INVALID_NAF_ID cpu_to_le32(0xC0020040)
-#define RPC_NT_CANNOT_SUPPORT cpu_to_le32(0xC0020041)
-#define RPC_NT_NO_CONTEXT_AVAILABLE cpu_to_le32(0xC0020042)
-#define RPC_NT_INTERNAL_ERROR cpu_to_le32(0xC0020043)
-#define RPC_NT_ZERO_DIVIDE cpu_to_le32(0xC0020044)
-#define RPC_NT_ADDRESS_ERROR cpu_to_le32(0xC0020045)
-#define RPC_NT_FP_DIV_ZERO cpu_to_le32(0xC0020046)
-#define RPC_NT_FP_UNDERFLOW cpu_to_le32(0xC0020047)
-#define RPC_NT_FP_OVERFLOW cpu_to_le32(0xC0020048)
-#define RPC_NT_CALL_IN_PROGRESS cpu_to_le32(0xC0020049)
-#define RPC_NT_NO_MORE_BINDINGS cpu_to_le32(0xC002004A)
-#define RPC_NT_GROUP_MEMBER_NOT_FOUND cpu_to_le32(0xC002004B)
-#define EPT_NT_CANT_CREATE cpu_to_le32(0xC002004C)
-#define RPC_NT_INVALID_OBJECT cpu_to_le32(0xC002004D)
-#define RPC_NT_NO_INTERFACES cpu_to_le32(0xC002004F)
-#define RPC_NT_CALL_CANCELLED cpu_to_le32(0xC0020050)
-#define RPC_NT_BINDING_INCOMPLETE cpu_to_le32(0xC0020051)
-#define RPC_NT_COMM_FAILURE cpu_to_le32(0xC0020052)
-#define RPC_NT_UNSUPPORTED_AUTHN_LEVEL cpu_to_le32(0xC0020053)
-#define RPC_NT_NO_PRINC_NAME cpu_to_le32(0xC0020054)
-#define RPC_NT_NOT_RPC_ERROR cpu_to_le32(0xC0020055)
-#define RPC_NT_SEC_PKG_ERROR cpu_to_le32(0xC0020057)
-#define RPC_NT_NOT_CANCELLED cpu_to_le32(0xC0020058)
-#define RPC_NT_INVALID_ASYNC_HANDLE cpu_to_le32(0xC0020062)
-#define RPC_NT_INVALID_ASYNC_CALL cpu_to_le32(0xC0020063)
-#define RPC_NT_PROXY_ACCESS_DENIED cpu_to_le32(0xC0020064)
-#define RPC_NT_NO_MORE_ENTRIES cpu_to_le32(0xC0030001)
-#define RPC_NT_SS_CHAR_TRANS_OPEN_FAIL cpu_to_le32(0xC0030002)
-#define RPC_NT_SS_CHAR_TRANS_SHORT_FILE cpu_to_le32(0xC0030003)
-#define RPC_NT_SS_IN_NULL_CONTEXT cpu_to_le32(0xC0030004)
-#define RPC_NT_SS_CONTEXT_MISMATCH cpu_to_le32(0xC0030005)
-#define RPC_NT_SS_CONTEXT_DAMAGED cpu_to_le32(0xC0030006)
-#define RPC_NT_SS_HANDLES_MISMATCH cpu_to_le32(0xC0030007)
-#define RPC_NT_SS_CANNOT_GET_CALL_HANDLE cpu_to_le32(0xC0030008)
-#define RPC_NT_NULL_REF_POINTER cpu_to_le32(0xC0030009)
-#define RPC_NT_ENUM_VALUE_OUT_OF_RANGE cpu_to_le32(0xC003000A)
-#define RPC_NT_BYTE_COUNT_TOO_SMALL cpu_to_le32(0xC003000B)
-#define RPC_NT_BAD_STUB_DATA cpu_to_le32(0xC003000C)
-#define RPC_NT_INVALID_ES_ACTION cpu_to_le32(0xC0030059)
-#define RPC_NT_WRONG_ES_VERSION cpu_to_le32(0xC003005A)
-#define RPC_NT_WRONG_STUB_VERSION cpu_to_le32(0xC003005B)
-#define RPC_NT_INVALID_PIPE_OBJECT cpu_to_le32(0xC003005C)
-#define RPC_NT_INVALID_PIPE_OPERATION cpu_to_le32(0xC003005D)
-#define RPC_NT_WRONG_PIPE_VERSION cpu_to_le32(0xC003005E)
-#define RPC_NT_PIPE_CLOSED cpu_to_le32(0xC003005F)
-#define RPC_NT_PIPE_DISCIPLINE_ERROR cpu_to_le32(0xC0030060)
-#define RPC_NT_PIPE_EMPTY cpu_to_le32(0xC0030061)
-#define STATUS_PNP_BAD_MPS_TABLE cpu_to_le32(0xC0040035)
-#define STATUS_PNP_TRANSLATION_FAILED cpu_to_le32(0xC0040036)
-#define STATUS_PNP_IRQ_TRANSLATION_FAILED cpu_to_le32(0xC0040037)
-#define STATUS_PNP_INVALID_ID cpu_to_le32(0xC0040038)
-#define STATUS_IO_REISSUE_AS_CACHED cpu_to_le32(0xC0040039)
-#define STATUS_CTX_WINSTATION_NAME_INVALID cpu_to_le32(0xC00A0001)
-#define STATUS_CTX_INVALID_PD cpu_to_le32(0xC00A0002)
-#define STATUS_CTX_PD_NOT_FOUND cpu_to_le32(0xC00A0003)
-#define STATUS_CTX_CLOSE_PENDING cpu_to_le32(0xC00A0006)
-#define STATUS_CTX_NO_OUTBUF cpu_to_le32(0xC00A0007)
-#define STATUS_CTX_MODEM_INF_NOT_FOUND cpu_to_le32(0xC00A0008)
-#define STATUS_CTX_INVALID_MODEMNAME cpu_to_le32(0xC00A0009)
-#define STATUS_CTX_RESPONSE_ERROR cpu_to_le32(0xC00A000A)
-#define STATUS_CTX_MODEM_RESPONSE_TIMEOUT cpu_to_le32(0xC00A000B)
-#define STATUS_CTX_MODEM_RESPONSE_NO_CARRIER cpu_to_le32(0xC00A000C)
-#define STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE cpu_to_le32(0xC00A000D)
-#define STATUS_CTX_MODEM_RESPONSE_BUSY cpu_to_le32(0xC00A000E)
-#define STATUS_CTX_MODEM_RESPONSE_VOICE cpu_to_le32(0xC00A000F)
-#define STATUS_CTX_TD_ERROR cpu_to_le32(0xC00A0010)
-#define STATUS_CTX_LICENSE_CLIENT_INVALID cpu_to_le32(0xC00A0012)
-#define STATUS_CTX_LICENSE_NOT_AVAILABLE cpu_to_le32(0xC00A0013)
-#define STATUS_CTX_LICENSE_EXPIRED cpu_to_le32(0xC00A0014)
-#define STATUS_CTX_WINSTATION_NOT_FOUND cpu_to_le32(0xC00A0015)
-#define STATUS_CTX_WINSTATION_NAME_COLLISION cpu_to_le32(0xC00A0016)
-#define STATUS_CTX_WINSTATION_BUSY cpu_to_le32(0xC00A0017)
-#define STATUS_CTX_BAD_VIDEO_MODE cpu_to_le32(0xC00A0018)
-#define STATUS_CTX_GRAPHICS_INVALID cpu_to_le32(0xC00A0022)
-#define STATUS_CTX_NOT_CONSOLE cpu_to_le32(0xC00A0024)
-#define STATUS_CTX_CLIENT_QUERY_TIMEOUT cpu_to_le32(0xC00A0026)
-#define STATUS_CTX_CONSOLE_DISCONNECT cpu_to_le32(0xC00A0027)
-#define STATUS_CTX_CONSOLE_CONNECT cpu_to_le32(0xC00A0028)
-#define STATUS_CTX_SHADOW_DENIED cpu_to_le32(0xC00A002A)
-#define STATUS_CTX_WINSTATION_ACCESS_DENIED cpu_to_le32(0xC00A002B)
-#define STATUS_CTX_INVALID_WD cpu_to_le32(0xC00A002E)
-#define STATUS_CTX_WD_NOT_FOUND cpu_to_le32(0xC00A002F)
-#define STATUS_CTX_SHADOW_INVALID cpu_to_le32(0xC00A0030)
-#define STATUS_CTX_SHADOW_DISABLED cpu_to_le32(0xC00A0031)
-#define STATUS_RDP_PROTOCOL_ERROR cpu_to_le32(0xC00A0032)
-#define STATUS_CTX_CLIENT_LICENSE_NOT_SET cpu_to_le32(0xC00A0033)
-#define STATUS_CTX_CLIENT_LICENSE_IN_USE cpu_to_le32(0xC00A0034)
-#define STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE cpu_to_le32(0xC00A0035)
-#define STATUS_CTX_SHADOW_NOT_RUNNING cpu_to_le32(0xC00A0036)
-#define STATUS_CTX_LOGON_DISABLED cpu_to_le32(0xC00A0037)
-#define STATUS_CTX_SECURITY_LAYER_ERROR cpu_to_le32(0xC00A0038)
-#define STATUS_TS_INCOMPATIBLE_SESSIONS cpu_to_le32(0xC00A0039)
-#define STATUS_MUI_FILE_NOT_FOUND cpu_to_le32(0xC00B0001)
-#define STATUS_MUI_INVALID_FILE cpu_to_le32(0xC00B0002)
-#define STATUS_MUI_INVALID_RC_CONFIG cpu_to_le32(0xC00B0003)
-#define STATUS_MUI_INVALID_LOCALE_NAME cpu_to_le32(0xC00B0004)
-#define STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME cpu_to_le32(0xC00B0005)
-#define STATUS_MUI_FILE_NOT_LOADED cpu_to_le32(0xC00B0006)
-#define STATUS_RESOURCE_ENUM_USER_STOP cpu_to_le32(0xC00B0007)
-#define STATUS_CLUSTER_INVALID_NODE cpu_to_le32(0xC0130001)
-#define STATUS_CLUSTER_NODE_EXISTS cpu_to_le32(0xC0130002)
-#define STATUS_CLUSTER_JOIN_IN_PROGRESS cpu_to_le32(0xC0130003)
-#define STATUS_CLUSTER_NODE_NOT_FOUND cpu_to_le32(0xC0130004)
-#define STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND cpu_to_le32(0xC0130005)
-#define STATUS_CLUSTER_NETWORK_EXISTS cpu_to_le32(0xC0130006)
-#define STATUS_CLUSTER_NETWORK_NOT_FOUND cpu_to_le32(0xC0130007)
-#define STATUS_CLUSTER_NETINTERFACE_EXISTS cpu_to_le32(0xC0130008)
-#define STATUS_CLUSTER_NETINTERFACE_NOT_FOUND cpu_to_le32(0xC0130009)
-#define STATUS_CLUSTER_INVALID_REQUEST cpu_to_le32(0xC013000A)
-#define STATUS_CLUSTER_INVALID_NETWORK_PROVIDER cpu_to_le32(0xC013000B)
-#define STATUS_CLUSTER_NODE_DOWN cpu_to_le32(0xC013000C)
-#define STATUS_CLUSTER_NODE_UNREACHABLE cpu_to_le32(0xC013000D)
-#define STATUS_CLUSTER_NODE_NOT_MEMBER cpu_to_le32(0xC013000E)
-#define STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS cpu_to_le32(0xC013000F)
-#define STATUS_CLUSTER_INVALID_NETWORK cpu_to_le32(0xC0130010)
-#define STATUS_CLUSTER_NO_NET_ADAPTERS cpu_to_le32(0xC0130011)
-#define STATUS_CLUSTER_NODE_UP cpu_to_le32(0xC0130012)
-#define STATUS_CLUSTER_NODE_PAUSED cpu_to_le32(0xC0130013)
-#define STATUS_CLUSTER_NODE_NOT_PAUSED cpu_to_le32(0xC0130014)
-#define STATUS_CLUSTER_NO_SECURITY_CONTEXT cpu_to_le32(0xC0130015)
-#define STATUS_CLUSTER_NETWORK_NOT_INTERNAL cpu_to_le32(0xC0130016)
-#define STATUS_CLUSTER_POISONED cpu_to_le32(0xC0130017)
-#define STATUS_ACPI_INVALID_OPCODE cpu_to_le32(0xC0140001)
-#define STATUS_ACPI_STACK_OVERFLOW cpu_to_le32(0xC0140002)
-#define STATUS_ACPI_ASSERT_FAILED cpu_to_le32(0xC0140003)
-#define STATUS_ACPI_INVALID_INDEX cpu_to_le32(0xC0140004)
-#define STATUS_ACPI_INVALID_ARGUMENT cpu_to_le32(0xC0140005)
-#define STATUS_ACPI_FATAL cpu_to_le32(0xC0140006)
-#define STATUS_ACPI_INVALID_SUPERNAME cpu_to_le32(0xC0140007)
-#define STATUS_ACPI_INVALID_ARGTYPE cpu_to_le32(0xC0140008)
-#define STATUS_ACPI_INVALID_OBJTYPE cpu_to_le32(0xC0140009)
-#define STATUS_ACPI_INVALID_TARGETTYPE cpu_to_le32(0xC014000A)
-#define STATUS_ACPI_INCORRECT_ARGUMENT_COUNT cpu_to_le32(0xC014000B)
-#define STATUS_ACPI_ADDRESS_NOT_MAPPED cpu_to_le32(0xC014000C)
-#define STATUS_ACPI_INVALID_EVENTTYPE cpu_to_le32(0xC014000D)
-#define STATUS_ACPI_HANDLER_COLLISION cpu_to_le32(0xC014000E)
-#define STATUS_ACPI_INVALID_DATA cpu_to_le32(0xC014000F)
-#define STATUS_ACPI_INVALID_REGION cpu_to_le32(0xC0140010)
-#define STATUS_ACPI_INVALID_ACCESS_SIZE cpu_to_le32(0xC0140011)
-#define STATUS_ACPI_ACQUIRE_GLOBAL_LOCK cpu_to_le32(0xC0140012)
-#define STATUS_ACPI_ALREADY_INITIALIZED cpu_to_le32(0xC0140013)
-#define STATUS_ACPI_NOT_INITIALIZED cpu_to_le32(0xC0140014)
-#define STATUS_ACPI_INVALID_MUTEX_LEVEL cpu_to_le32(0xC0140015)
-#define STATUS_ACPI_MUTEX_NOT_OWNED cpu_to_le32(0xC0140016)
-#define STATUS_ACPI_MUTEX_NOT_OWNER cpu_to_le32(0xC0140017)
-#define STATUS_ACPI_RS_ACCESS cpu_to_le32(0xC0140018)
-#define STATUS_ACPI_INVALID_TABLE cpu_to_le32(0xC0140019)
-#define STATUS_ACPI_REG_HANDLER_FAILED cpu_to_le32(0xC0140020)
-#define STATUS_ACPI_POWER_REQUEST_FAILED cpu_to_le32(0xC0140021)
-#define STATUS_SXS_SECTION_NOT_FOUND cpu_to_le32(0xC0150001)
-#define STATUS_SXS_CANT_GEN_ACTCTX cpu_to_le32(0xC0150002)
-#define STATUS_SXS_INVALID_ACTCTXDATA_FORMAT cpu_to_le32(0xC0150003)
-#define STATUS_SXS_ASSEMBLY_NOT_FOUND cpu_to_le32(0xC0150004)
-#define STATUS_SXS_MANIFEST_FORMAT_ERROR cpu_to_le32(0xC0150005)
-#define STATUS_SXS_MANIFEST_PARSE_ERROR cpu_to_le32(0xC0150006)
-#define STATUS_SXS_ACTIVATION_CONTEXT_DISABLED cpu_to_le32(0xC0150007)
-#define STATUS_SXS_KEY_NOT_FOUND cpu_to_le32(0xC0150008)
-#define STATUS_SXS_VERSION_CONFLICT cpu_to_le32(0xC0150009)
-#define STATUS_SXS_WRONG_SECTION_TYPE cpu_to_le32(0xC015000A)
-#define STATUS_SXS_THREAD_QUERIES_DISABLED cpu_to_le32(0xC015000B)
-#define STATUS_SXS_ASSEMBLY_MISSING cpu_to_le32(0xC015000C)
-#define STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET cpu_to_le32(0xC015000E)
-#define STATUS_SXS_EARLY_DEACTIVATION cpu_to_le32(0xC015000F)
-#define STATUS_SXS_INVALID_DEACTIVATION cpu_to_le32(0xC0150010)
-#define STATUS_SXS_MULTIPLE_DEACTIVATION cpu_to_le32(0xC0150011)
-#define STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY \
- cpu_to_le32(0xC0150012)
-#define STATUS_SXS_PROCESS_TERMINATION_REQUESTED cpu_to_le32(0xC0150013)
-#define STATUS_SXS_CORRUPT_ACTIVATION_STACK cpu_to_le32(0xC0150014)
-#define STATUS_SXS_CORRUPTION cpu_to_le32(0xC0150015)
-#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE cpu_to_le32(0xC0150016)
-#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME cpu_to_le32(0xC0150017)
-#define STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE cpu_to_le32(0xC0150018)
-#define STATUS_SXS_IDENTITY_PARSE_ERROR cpu_to_le32(0xC0150019)
-#define STATUS_SXS_COMPONENT_STORE_CORRUPT cpu_to_le32(0xC015001A)
-#define STATUS_SXS_FILE_HASH_MISMATCH cpu_to_le32(0xC015001B)
-#define STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT \
- cpu_to_le32(0xC015001C)
-#define STATUS_SXS_IDENTITIES_DIFFERENT cpu_to_le32(0xC015001D)
-#define STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT cpu_to_le32(0xC015001E)
-#define STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY cpu_to_le32(0xC015001F)
-#define STATUS_ADVANCED_INSTALLER_FAILED cpu_to_le32(0xC0150020)
-#define STATUS_XML_ENCODING_MISMATCH cpu_to_le32(0xC0150021)
-#define STATUS_SXS_MANIFEST_TOO_BIG cpu_to_le32(0xC0150022)
-#define STATUS_SXS_SETTING_NOT_REGISTERED cpu_to_le32(0xC0150023)
-#define STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE cpu_to_le32(0xC0150024)
-#define STATUS_SMI_PRIMITIVE_INSTALLER_FAILED cpu_to_le32(0xC0150025)
-#define STATUS_GENERIC_COMMAND_FAILED cpu_to_le32(0xC0150026)
-#define STATUS_SXS_FILE_HASH_MISSING cpu_to_le32(0xC0150027)
-#define STATUS_TRANSACTIONAL_CONFLICT cpu_to_le32(0xC0190001)
-#define STATUS_INVALID_TRANSACTION cpu_to_le32(0xC0190002)
-#define STATUS_TRANSACTION_NOT_ACTIVE cpu_to_le32(0xC0190003)
-#define STATUS_TM_INITIALIZATION_FAILED cpu_to_le32(0xC0190004)
-#define STATUS_RM_NOT_ACTIVE cpu_to_le32(0xC0190005)
-#define STATUS_RM_METADATA_CORRUPT cpu_to_le32(0xC0190006)
-#define STATUS_TRANSACTION_NOT_JOINED cpu_to_le32(0xC0190007)
-#define STATUS_DIRECTORY_NOT_RM cpu_to_le32(0xC0190008)
-#define STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE cpu_to_le32(0xC019000A)
-#define STATUS_LOG_RESIZE_INVALID_SIZE cpu_to_le32(0xC019000B)
-#define STATUS_REMOTE_FILE_VERSION_MISMATCH cpu_to_le32(0xC019000C)
-#define STATUS_CRM_PROTOCOL_ALREADY_EXISTS cpu_to_le32(0xC019000F)
-#define STATUS_TRANSACTION_PROPAGATION_FAILED cpu_to_le32(0xC0190010)
-#define STATUS_CRM_PROTOCOL_NOT_FOUND cpu_to_le32(0xC0190011)
-#define STATUS_TRANSACTION_SUPERIOR_EXISTS cpu_to_le32(0xC0190012)
-#define STATUS_TRANSACTION_REQUEST_NOT_VALID cpu_to_le32(0xC0190013)
-#define STATUS_TRANSACTION_NOT_REQUESTED cpu_to_le32(0xC0190014)
-#define STATUS_TRANSACTION_ALREADY_ABORTED cpu_to_le32(0xC0190015)
-#define STATUS_TRANSACTION_ALREADY_COMMITTED cpu_to_le32(0xC0190016)
-#define STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER cpu_to_le32(0xC0190017)
-#define STATUS_CURRENT_TRANSACTION_NOT_VALID cpu_to_le32(0xC0190018)
-#define STATUS_LOG_GROWTH_FAILED cpu_to_le32(0xC0190019)
-#define STATUS_OBJECT_NO_LONGER_EXISTS cpu_to_le32(0xC0190021)
-#define STATUS_STREAM_MINIVERSION_NOT_FOUND cpu_to_le32(0xC0190022)
-#define STATUS_STREAM_MINIVERSION_NOT_VALID cpu_to_le32(0xC0190023)
-#define STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION \
- cpu_to_le32(0xC0190024)
-#define STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT cpu_to_le32(0xC0190025)
-#define STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS cpu_to_le32(0xC0190026)
-#define STATUS_HANDLE_NO_LONGER_VALID cpu_to_le32(0xC0190028)
-#define STATUS_LOG_CORRUPTION_DETECTED cpu_to_le32(0xC0190030)
-#define STATUS_RM_DISCONNECTED cpu_to_le32(0xC0190032)
-#define STATUS_ENLISTMENT_NOT_SUPERIOR cpu_to_le32(0xC0190033)
-#define STATUS_FILE_IDENTITY_NOT_PERSISTENT cpu_to_le32(0xC0190036)
-#define STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY cpu_to_le32(0xC0190037)
-#define STATUS_CANT_CROSS_RM_BOUNDARY cpu_to_le32(0xC0190038)
-#define STATUS_TXF_DIR_NOT_EMPTY cpu_to_le32(0xC0190039)
-#define STATUS_INDOUBT_TRANSACTIONS_EXIST cpu_to_le32(0xC019003A)
-#define STATUS_TM_VOLATILE cpu_to_le32(0xC019003B)
-#define STATUS_ROLLBACK_TIMER_EXPIRED cpu_to_le32(0xC019003C)
-#define STATUS_TXF_ATTRIBUTE_CORRUPT cpu_to_le32(0xC019003D)
-#define STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC019003E)
-#define STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED cpu_to_le32(0xC019003F)
-#define STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE cpu_to_le32(0xC0190040)
-#define STATUS_TRANSACTION_REQUIRED_PROMOTION cpu_to_le32(0xC0190043)
-#define STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION cpu_to_le32(0xC0190044)
-#define STATUS_TRANSACTIONS_NOT_FROZEN cpu_to_le32(0xC0190045)
-#define STATUS_TRANSACTION_FREEZE_IN_PROGRESS cpu_to_le32(0xC0190046)
-#define STATUS_NOT_SNAPSHOT_VOLUME cpu_to_le32(0xC0190047)
-#define STATUS_NO_SAVEPOINT_WITH_OPEN_FILES cpu_to_le32(0xC0190048)
-#define STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC0190049)
-#define STATUS_TM_IDENTITY_MISMATCH cpu_to_le32(0xC019004A)
-#define STATUS_FLOATED_SECTION cpu_to_le32(0xC019004B)
-#define STATUS_CANNOT_ACCEPT_TRANSACTED_WORK cpu_to_le32(0xC019004C)
-#define STATUS_CANNOT_ABORT_TRANSACTIONS cpu_to_le32(0xC019004D)
-#define STATUS_TRANSACTION_NOT_FOUND cpu_to_le32(0xC019004E)
-#define STATUS_RESOURCEMANAGER_NOT_FOUND cpu_to_le32(0xC019004F)
-#define STATUS_ENLISTMENT_NOT_FOUND cpu_to_le32(0xC0190050)
-#define STATUS_TRANSACTIONMANAGER_NOT_FOUND cpu_to_le32(0xC0190051)
-#define STATUS_TRANSACTIONMANAGER_NOT_ONLINE cpu_to_le32(0xC0190052)
-#define STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION \
- cpu_to_le32(0xC0190053)
-#define STATUS_TRANSACTION_NOT_ROOT cpu_to_le32(0xC0190054)
-#define STATUS_TRANSACTION_OBJECT_EXPIRED cpu_to_le32(0xC0190055)
-#define STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC0190056)
-#define STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED cpu_to_le32(0xC0190057)
-#define STATUS_TRANSACTION_RECORD_TOO_LONG cpu_to_le32(0xC0190058)
-#define STATUS_NO_LINK_TRACKING_IN_TRANSACTION cpu_to_le32(0xC0190059)
-#define STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION cpu_to_le32(0xC019005A)
-#define STATUS_TRANSACTION_INTEGRITY_VIOLATED cpu_to_le32(0xC019005B)
-#define STATUS_LOG_SECTOR_INVALID cpu_to_le32(0xC01A0001)
-#define STATUS_LOG_SECTOR_PARITY_INVALID cpu_to_le32(0xC01A0002)
-#define STATUS_LOG_SECTOR_REMAPPED cpu_to_le32(0xC01A0003)
-#define STATUS_LOG_BLOCK_INCOMPLETE cpu_to_le32(0xC01A0004)
-#define STATUS_LOG_INVALID_RANGE cpu_to_le32(0xC01A0005)
-#define STATUS_LOG_BLOCKS_EXHAUSTED cpu_to_le32(0xC01A0006)
-#define STATUS_LOG_READ_CONTEXT_INVALID cpu_to_le32(0xC01A0007)
-#define STATUS_LOG_RESTART_INVALID cpu_to_le32(0xC01A0008)
-#define STATUS_LOG_BLOCK_VERSION cpu_to_le32(0xC01A0009)
-#define STATUS_LOG_BLOCK_INVALID cpu_to_le32(0xC01A000A)
-#define STATUS_LOG_READ_MODE_INVALID cpu_to_le32(0xC01A000B)
-#define STATUS_LOG_METADATA_CORRUPT cpu_to_le32(0xC01A000D)
-#define STATUS_LOG_METADATA_INVALID cpu_to_le32(0xC01A000E)
-#define STATUS_LOG_METADATA_INCONSISTENT cpu_to_le32(0xC01A000F)
-#define STATUS_LOG_RESERVATION_INVALID cpu_to_le32(0xC01A0010)
-#define STATUS_LOG_CANT_DELETE cpu_to_le32(0xC01A0011)
-#define STATUS_LOG_CONTAINER_LIMIT_EXCEEDED cpu_to_le32(0xC01A0012)
-#define STATUS_LOG_START_OF_LOG cpu_to_le32(0xC01A0013)
-#define STATUS_LOG_POLICY_ALREADY_INSTALLED cpu_to_le32(0xC01A0014)
-#define STATUS_LOG_POLICY_NOT_INSTALLED cpu_to_le32(0xC01A0015)
-#define STATUS_LOG_POLICY_INVALID cpu_to_le32(0xC01A0016)
-#define STATUS_LOG_POLICY_CONFLICT cpu_to_le32(0xC01A0017)
-#define STATUS_LOG_PINNED_ARCHIVE_TAIL cpu_to_le32(0xC01A0018)
-#define STATUS_LOG_RECORD_NONEXISTENT cpu_to_le32(0xC01A0019)
-#define STATUS_LOG_RECORDS_RESERVED_INVALID cpu_to_le32(0xC01A001A)
-#define STATUS_LOG_SPACE_RESERVED_INVALID cpu_to_le32(0xC01A001B)
-#define STATUS_LOG_TAIL_INVALID cpu_to_le32(0xC01A001C)
-#define STATUS_LOG_FULL cpu_to_le32(0xC01A001D)
-#define STATUS_LOG_MULTIPLEXED cpu_to_le32(0xC01A001E)
-#define STATUS_LOG_DEDICATED cpu_to_le32(0xC01A001F)
-#define STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS cpu_to_le32(0xC01A0020)
-#define STATUS_LOG_ARCHIVE_IN_PROGRESS cpu_to_le32(0xC01A0021)
-#define STATUS_LOG_EPHEMERAL cpu_to_le32(0xC01A0022)
-#define STATUS_LOG_NOT_ENOUGH_CONTAINERS cpu_to_le32(0xC01A0023)
-#define STATUS_LOG_CLIENT_ALREADY_REGISTERED cpu_to_le32(0xC01A0024)
-#define STATUS_LOG_CLIENT_NOT_REGISTERED cpu_to_le32(0xC01A0025)
-#define STATUS_LOG_FULL_HANDLER_IN_PROGRESS cpu_to_le32(0xC01A0026)
-#define STATUS_LOG_CONTAINER_READ_FAILED cpu_to_le32(0xC01A0027)
-#define STATUS_LOG_CONTAINER_WRITE_FAILED cpu_to_le32(0xC01A0028)
-#define STATUS_LOG_CONTAINER_OPEN_FAILED cpu_to_le32(0xC01A0029)
-#define STATUS_LOG_CONTAINER_STATE_INVALID cpu_to_le32(0xC01A002A)
-#define STATUS_LOG_STATE_INVALID cpu_to_le32(0xC01A002B)
-#define STATUS_LOG_PINNED cpu_to_le32(0xC01A002C)
-#define STATUS_LOG_METADATA_FLUSH_FAILED cpu_to_le32(0xC01A002D)
-#define STATUS_LOG_INCONSISTENT_SECURITY cpu_to_le32(0xC01A002E)
-#define STATUS_LOG_APPENDED_FLUSH_FAILED cpu_to_le32(0xC01A002F)
-#define STATUS_LOG_PINNED_RESERVATION cpu_to_le32(0xC01A0030)
-#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD cpu_to_le32(0xC01B00EA)
-#define STATUS_FLT_NO_HANDLER_DEFINED cpu_to_le32(0xC01C0001)
-#define STATUS_FLT_CONTEXT_ALREADY_DEFINED cpu_to_le32(0xC01C0002)
-#define STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST cpu_to_le32(0xC01C0003)
-#define STATUS_FLT_DISALLOW_FAST_IO cpu_to_le32(0xC01C0004)
-#define STATUS_FLT_INVALID_NAME_REQUEST cpu_to_le32(0xC01C0005)
-#define STATUS_FLT_NOT_SAFE_TO_POST_OPERATION cpu_to_le32(0xC01C0006)
-#define STATUS_FLT_NOT_INITIALIZED cpu_to_le32(0xC01C0007)
-#define STATUS_FLT_FILTER_NOT_READY cpu_to_le32(0xC01C0008)
-#define STATUS_FLT_POST_OPERATION_CLEANUP cpu_to_le32(0xC01C0009)
-#define STATUS_FLT_INTERNAL_ERROR cpu_to_le32(0xC01C000A)
-#define STATUS_FLT_DELETING_OBJECT cpu_to_le32(0xC01C000B)
-#define STATUS_FLT_MUST_BE_NONPAGED_POOL cpu_to_le32(0xC01C000C)
-#define STATUS_FLT_DUPLICATE_ENTRY cpu_to_le32(0xC01C000D)
-#define STATUS_FLT_CBDQ_DISABLED cpu_to_le32(0xC01C000E)
-#define STATUS_FLT_DO_NOT_ATTACH cpu_to_le32(0xC01C000F)
-#define STATUS_FLT_DO_NOT_DETACH cpu_to_le32(0xC01C0010)
-#define STATUS_FLT_INSTANCE_ALTITUDE_COLLISION cpu_to_le32(0xC01C0011)
-#define STATUS_FLT_INSTANCE_NAME_COLLISION cpu_to_le32(0xC01C0012)
-#define STATUS_FLT_FILTER_NOT_FOUND cpu_to_le32(0xC01C0013)
-#define STATUS_FLT_VOLUME_NOT_FOUND cpu_to_le32(0xC01C0014)
-#define STATUS_FLT_INSTANCE_NOT_FOUND cpu_to_le32(0xC01C0015)
-#define STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND cpu_to_le32(0xC01C0016)
-#define STATUS_FLT_INVALID_CONTEXT_REGISTRATION cpu_to_le32(0xC01C0017)
-#define STATUS_FLT_NAME_CACHE_MISS cpu_to_le32(0xC01C0018)
-#define STATUS_FLT_NO_DEVICE_OBJECT cpu_to_le32(0xC01C0019)
-#define STATUS_FLT_VOLUME_ALREADY_MOUNTED cpu_to_le32(0xC01C001A)
-#define STATUS_FLT_ALREADY_ENLISTED cpu_to_le32(0xC01C001B)
-#define STATUS_FLT_CONTEXT_ALREADY_LINKED cpu_to_le32(0xC01C001C)
-#define STATUS_FLT_NO_WAITER_FOR_REPLY cpu_to_le32(0xC01C0020)
-#define STATUS_MONITOR_NO_DESCRIPTOR cpu_to_le32(0xC01D0001)
-#define STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT cpu_to_le32(0xC01D0002)
-#define STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM cpu_to_le32(0xC01D0003)
-#define STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK cpu_to_le32(0xC01D0004)
-#define STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED cpu_to_le32(0xC01D0005)
-#define STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK \
- cpu_to_le32(0xC01D0006)
-#define STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK \
- cpu_to_le32(0xC01D0007)
-#define STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA cpu_to_le32(0xC01D0008)
-#define STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK cpu_to_le32(0xC01D0009)
-#define STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER cpu_to_le32(0xC01E0000)
-#define STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER cpu_to_le32(0xC01E0001)
-#define STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER cpu_to_le32(0xC01E0002)
-#define STATUS_GRAPHICS_ADAPTER_WAS_RESET cpu_to_le32(0xC01E0003)
-#define STATUS_GRAPHICS_INVALID_DRIVER_MODEL cpu_to_le32(0xC01E0004)
-#define STATUS_GRAPHICS_PRESENT_MODE_CHANGED cpu_to_le32(0xC01E0005)
-#define STATUS_GRAPHICS_PRESENT_OCCLUDED cpu_to_le32(0xC01E0006)
-#define STATUS_GRAPHICS_PRESENT_DENIED cpu_to_le32(0xC01E0007)
-#define STATUS_GRAPHICS_CANNOTCOLORCONVERT cpu_to_le32(0xC01E0008)
-#define STATUS_GRAPHICS_NO_VIDEO_MEMORY cpu_to_le32(0xC01E0100)
-#define STATUS_GRAPHICS_CANT_LOCK_MEMORY cpu_to_le32(0xC01E0101)
-#define STATUS_GRAPHICS_ALLOCATION_BUSY cpu_to_le32(0xC01E0102)
-#define STATUS_GRAPHICS_TOO_MANY_REFERENCES cpu_to_le32(0xC01E0103)
-#define STATUS_GRAPHICS_TRY_AGAIN_LATER cpu_to_le32(0xC01E0104)
-#define STATUS_GRAPHICS_TRY_AGAIN_NOW cpu_to_le32(0xC01E0105)
-#define STATUS_GRAPHICS_ALLOCATION_INVALID cpu_to_le32(0xC01E0106)
-#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE cpu_to_le32(0xC01E0107)
-#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED cpu_to_le32(0xC01E0108)
-#define STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION cpu_to_le32(0xC01E0109)
-#define STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE cpu_to_le32(0xC01E0110)
-#define STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION cpu_to_le32(0xC01E0111)
-#define STATUS_GRAPHICS_ALLOCATION_CLOSED cpu_to_le32(0xC01E0112)
-#define STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE cpu_to_le32(0xC01E0113)
-#define STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE cpu_to_le32(0xC01E0114)
-#define STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE cpu_to_le32(0xC01E0115)
-#define STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST cpu_to_le32(0xC01E0116)
-#define STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE cpu_to_le32(0xC01E0200)
-#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY cpu_to_le32(0xC01E0300)
-#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED cpu_to_le32(0xC01E0301)
-#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED \
- cpu_to_le32(0xC01E0302)
-#define STATUS_GRAPHICS_INVALID_VIDPN cpu_to_le32(0xC01E0303)
-#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE cpu_to_le32(0xC01E0304)
-#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET cpu_to_le32(0xC01E0305)
-#define STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED cpu_to_le32(0xC01E0306)
-#define STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET cpu_to_le32(0xC01E0308)
-#define STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET cpu_to_le32(0xC01E0309)
-#define STATUS_GRAPHICS_INVALID_FREQUENCY cpu_to_le32(0xC01E030A)
-#define STATUS_GRAPHICS_INVALID_ACTIVE_REGION cpu_to_le32(0xC01E030B)
-#define STATUS_GRAPHICS_INVALID_TOTAL_REGION cpu_to_le32(0xC01E030C)
-#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE \
- cpu_to_le32(0xC01E0310)
-#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE \
- cpu_to_le32(0xC01E0311)
-#define STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET cpu_to_le32(0xC01E0312)
-#define STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY cpu_to_le32(0xC01E0313)
-#define STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET cpu_to_le32(0xC01E0314)
-#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET cpu_to_le32(0xC01E0315)
-#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET cpu_to_le32(0xC01E0316)
-#define STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET cpu_to_le32(0xC01E0317)
-#define STATUS_GRAPHICS_TARGET_ALREADY_IN_SET cpu_to_le32(0xC01E0318)
-#define STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH cpu_to_le32(0xC01E0319)
-#define STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY cpu_to_le32(0xC01E031A)
-#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET \
- cpu_to_le32(0xC01E031B)
-#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE cpu_to_le32(0xC01E031C)
-#define STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET cpu_to_le32(0xC01E031D)
-#define STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET cpu_to_le32(0xC01E031F)
-#define STATUS_GRAPHICS_STALE_MODESET cpu_to_le32(0xC01E0320)
-#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET cpu_to_le32(0xC01E0321)
-#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE cpu_to_le32(0xC01E0322)
-#define STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN cpu_to_le32(0xC01E0323)
-#define STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0324)
-#define STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION \
- cpu_to_le32(0xC01E0325)
-#define STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES \
- cpu_to_le32(0xC01E0326)
-#define STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0327)
-#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE \
- cpu_to_le32(0xC01E0328)
-#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET \
- cpu_to_le32(0xC01E0329)
-#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET cpu_to_le32(0xC01E032A)
-#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR cpu_to_le32(0xC01E032B)
-#define STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET cpu_to_le32(0xC01E032C)
-#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET cpu_to_le32(0xC01E032D)
-#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE \
- cpu_to_le32(0xC01E032E)
-#define STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE cpu_to_le32(0xC01E032F)
-#define STATUS_GRAPHICS_RESOURCES_NOT_RELATED cpu_to_le32(0xC01E0330)
-#define STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0331)
-#define STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0332)
-#define STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET cpu_to_le32(0xC01E0333)
-#define STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER \
- cpu_to_le32(0xC01E0334)
-#define STATUS_GRAPHICS_NO_VIDPNMGR cpu_to_le32(0xC01E0335)
-#define STATUS_GRAPHICS_NO_ACTIVE_VIDPN cpu_to_le32(0xC01E0336)
-#define STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY cpu_to_le32(0xC01E0337)
-#define STATUS_GRAPHICS_MONITOR_NOT_CONNECTED cpu_to_le32(0xC01E0338)
-#define STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0339)
-#define STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE cpu_to_le32(0xC01E033A)
-#define STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE cpu_to_le32(0xC01E033B)
-#define STATUS_GRAPHICS_INVALID_STRIDE cpu_to_le32(0xC01E033C)
-#define STATUS_GRAPHICS_INVALID_PIXELFORMAT cpu_to_le32(0xC01E033D)
-#define STATUS_GRAPHICS_INVALID_COLORBASIS cpu_to_le32(0xC01E033E)
-#define STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE cpu_to_le32(0xC01E033F)
-#define STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0340)
-#define STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT \
- cpu_to_le32(0xC01E0341)
-#define STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE cpu_to_le32(0xC01E0342)
-#define STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN cpu_to_le32(0xC01E0343)
-#define STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL cpu_to_le32(0xC01E0344)
-#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION \
- cpu_to_le32(0xC01E0345)
-#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED \
- cpu_to_le32(0xC01E0346)
-#define STATUS_GRAPHICS_INVALID_GAMMA_RAMP cpu_to_le32(0xC01E0347)
-#define STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED cpu_to_le32(0xC01E0348)
-#define STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED cpu_to_le32(0xC01E0349)
-#define STATUS_GRAPHICS_MODE_NOT_IN_MODESET cpu_to_le32(0xC01E034A)
-#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON \
- cpu_to_le32(0xC01E034D)
-#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE cpu_to_le32(0xC01E034E)
-#define STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE cpu_to_le32(0xC01E034F)
-#define STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS \
- cpu_to_le32(0xC01E0350)
-#define STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING cpu_to_le32(0xC01E0352)
-#define STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED cpu_to_le32(0xC01E0353)
-#define STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS cpu_to_le32(0xC01E0354)
-#define STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT cpu_to_le32(0xC01E0355)
-#define STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM cpu_to_le32(0xC01E0356)
-#define STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN \
- cpu_to_le32(0xC01E0357)
-#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT \
- cpu_to_le32(0xC01E0358)
-#define STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED cpu_to_le32(0xC01E0359)
-#define STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION \
- cpu_to_le32(0xC01E035A)
-#define STATUS_GRAPHICS_INVALID_CLIENT_TYPE cpu_to_le32(0xC01E035B)
-#define STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET cpu_to_le32(0xC01E035C)
-#define STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED \
- cpu_to_le32(0xC01E0400)
-#define STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED cpu_to_le32(0xC01E0401)
-#define STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER cpu_to_le32(0xC01E0430)
-#define STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED cpu_to_le32(0xC01E0431)
-#define STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED cpu_to_le32(0xC01E0432)
-#define STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY cpu_to_le32(0xC01E0433)
-#define STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED cpu_to_le32(0xC01E0434)
-#define STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON cpu_to_le32(0xC01E0435)
-#define STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE cpu_to_le32(0xC01E0436)
-#define STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER cpu_to_le32(0xC01E0438)
-#define STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED cpu_to_le32(0xC01E043B)
-#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS \
- cpu_to_le32(0xC01E051C)
-#define STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST cpu_to_le32(0xC01E051D)
-#define STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR cpu_to_le32(0xC01E051E)
-#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS \
- cpu_to_le32(0xC01E051F)
-#define STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED cpu_to_le32(0xC01E0520)
-#define STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST \
- cpu_to_le32(0xC01E0521)
-#define STATUS_GRAPHICS_OPM_NOT_SUPPORTED cpu_to_le32(0xC01E0500)
-#define STATUS_GRAPHICS_COPP_NOT_SUPPORTED cpu_to_le32(0xC01E0501)
-#define STATUS_GRAPHICS_UAB_NOT_SUPPORTED cpu_to_le32(0xC01E0502)
-#define STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS cpu_to_le32(0xC01E0503)
-#define STATUS_GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL cpu_to_le32(0xC01E0504)
-#define STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST cpu_to_le32(0xC01E0505)
-#define STATUS_GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME \
- cpu_to_le32(0xC01E0506)
-#define STATUS_GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP \
- cpu_to_le32(0xC01E0507)
-#define STATUS_GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED \
- cpu_to_le32(0xC01E0508)
-#define STATUS_GRAPHICS_OPM_INVALID_POINTER cpu_to_le32(0xC01E050A)
-#define STATUS_GRAPHICS_OPM_INTERNAL_ERROR cpu_to_le32(0xC01E050B)
-#define STATUS_GRAPHICS_OPM_INVALID_HANDLE cpu_to_le32(0xC01E050C)
-#define STATUS_GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE \
- cpu_to_le32(0xC01E050D)
-#define STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH cpu_to_le32(0xC01E050E)
-#define STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED cpu_to_le32(0xC01E050F)
-#define STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED cpu_to_le32(0xC01E0510)
-#define STATUS_GRAPHICS_PVP_HFS_FAILED cpu_to_le32(0xC01E0511)
-#define STATUS_GRAPHICS_OPM_INVALID_SRM cpu_to_le32(0xC01E0512)
-#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP cpu_to_le32(0xC01E0513)
-#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP cpu_to_le32(0xC01E0514)
-#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA \
- cpu_to_le32(0xC01E0515)
-#define STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET cpu_to_le32(0xC01E0516)
-#define STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH cpu_to_le32(0xC01E0517)
-#define STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE \
- cpu_to_le32(0xC01E0518)
-#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS \
- cpu_to_le32(0xC01E051A)
-#define STATUS_GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS \
- cpu_to_le32(0xC01E051B)
-#define STATUS_GRAPHICS_I2C_NOT_SUPPORTED cpu_to_le32(0xC01E0580)
-#define STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST cpu_to_le32(0xC01E0581)
-#define STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA cpu_to_le32(0xC01E0582)
-#define STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA cpu_to_le32(0xC01E0583)
-#define STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED cpu_to_le32(0xC01E0584)
-#define STATUS_GRAPHICS_DDCCI_INVALID_DATA cpu_to_le32(0xC01E0585)
-#define STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE \
- cpu_to_le32(0xC01E0586)
-#define STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING \
- cpu_to_le32(0xC01E0587)
-#define STATUS_GRAPHICS_MCA_INTERNAL_ERROR cpu_to_le32(0xC01E0588)
-#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND cpu_to_le32(0xC01E0589)
-#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH cpu_to_le32(0xC01E058A)
-#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM cpu_to_le32(0xC01E058B)
-#define STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE cpu_to_le32(0xC01E058C)
-#define STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS cpu_to_le32(0xC01E058D)
-#define STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED cpu_to_le32(0xC01E05E0)
-#define STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME \
- cpu_to_le32(0xC01E05E1)
-#define STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP \
- cpu_to_le32(0xC01E05E2)
-#define STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED cpu_to_le32(0xC01E05E3)
-#define STATUS_GRAPHICS_INVALID_POINTER cpu_to_le32(0xC01E05E4)
-#define STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE \
- cpu_to_le32(0xC01E05E5)
-#define STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL cpu_to_le32(0xC01E05E6)
-#define STATUS_GRAPHICS_INTERNAL_ERROR cpu_to_le32(0xC01E05E7)
-#define STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS cpu_to_le32(0xC01E05E8)
-#define STATUS_FVE_LOCKED_VOLUME cpu_to_le32(0xC0210000)
-#define STATUS_FVE_NOT_ENCRYPTED cpu_to_le32(0xC0210001)
-#define STATUS_FVE_BAD_INFORMATION cpu_to_le32(0xC0210002)
-#define STATUS_FVE_TOO_SMALL cpu_to_le32(0xC0210003)
-#define STATUS_FVE_FAILED_WRONG_FS cpu_to_le32(0xC0210004)
-#define STATUS_FVE_FAILED_BAD_FS cpu_to_le32(0xC0210005)
-#define STATUS_FVE_FS_NOT_EXTENDED cpu_to_le32(0xC0210006)
-#define STATUS_FVE_FS_MOUNTED cpu_to_le32(0xC0210007)
-#define STATUS_FVE_NO_LICENSE cpu_to_le32(0xC0210008)
-#define STATUS_FVE_ACTION_NOT_ALLOWED cpu_to_le32(0xC0210009)
-#define STATUS_FVE_BAD_DATA cpu_to_le32(0xC021000A)
-#define STATUS_FVE_VOLUME_NOT_BOUND cpu_to_le32(0xC021000B)
-#define STATUS_FVE_NOT_DATA_VOLUME cpu_to_le32(0xC021000C)
-#define STATUS_FVE_CONV_READ_ERROR cpu_to_le32(0xC021000D)
-#define STATUS_FVE_CONV_WRITE_ERROR cpu_to_le32(0xC021000E)
-#define STATUS_FVE_OVERLAPPED_UPDATE cpu_to_le32(0xC021000F)
-#define STATUS_FVE_FAILED_SECTOR_SIZE cpu_to_le32(0xC0210010)
-#define STATUS_FVE_FAILED_AUTHENTICATION cpu_to_le32(0xC0210011)
-#define STATUS_FVE_NOT_OS_VOLUME cpu_to_le32(0xC0210012)
-#define STATUS_FVE_KEYFILE_NOT_FOUND cpu_to_le32(0xC0210013)
-#define STATUS_FVE_KEYFILE_INVALID cpu_to_le32(0xC0210014)
-#define STATUS_FVE_KEYFILE_NO_VMK cpu_to_le32(0xC0210015)
-#define STATUS_FVE_TPM_DISABLED cpu_to_le32(0xC0210016)
-#define STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO cpu_to_le32(0xC0210017)
-#define STATUS_FVE_TPM_INVALID_PCR cpu_to_le32(0xC0210018)
-#define STATUS_FVE_TPM_NO_VMK cpu_to_le32(0xC0210019)
-#define STATUS_FVE_PIN_INVALID cpu_to_le32(0xC021001A)
-#define STATUS_FVE_AUTH_INVALID_APPLICATION cpu_to_le32(0xC021001B)
-#define STATUS_FVE_AUTH_INVALID_CONFIG cpu_to_le32(0xC021001C)
-#define STATUS_FVE_DEBUGGER_ENABLED cpu_to_le32(0xC021001D)
-#define STATUS_FVE_DRY_RUN_FAILED cpu_to_le32(0xC021001E)
-#define STATUS_FVE_BAD_METADATA_POINTER cpu_to_le32(0xC021001F)
-#define STATUS_FVE_OLD_METADATA_COPY cpu_to_le32(0xC0210020)
-#define STATUS_FVE_REBOOT_REQUIRED cpu_to_le32(0xC0210021)
-#define STATUS_FVE_RAW_ACCESS cpu_to_le32(0xC0210022)
-#define STATUS_FVE_RAW_BLOCKED cpu_to_le32(0xC0210023)
-#define STATUS_FWP_CALLOUT_NOT_FOUND cpu_to_le32(0xC0220001)
-#define STATUS_FWP_CONDITION_NOT_FOUND cpu_to_le32(0xC0220002)
-#define STATUS_FWP_FILTER_NOT_FOUND cpu_to_le32(0xC0220003)
-#define STATUS_FWP_LAYER_NOT_FOUND cpu_to_le32(0xC0220004)
-#define STATUS_FWP_PROVIDER_NOT_FOUND cpu_to_le32(0xC0220005)
-#define STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND cpu_to_le32(0xC0220006)
-#define STATUS_FWP_SUBLAYER_NOT_FOUND cpu_to_le32(0xC0220007)
-#define STATUS_FWP_NOT_FOUND cpu_to_le32(0xC0220008)
-#define STATUS_FWP_ALREADY_EXISTS cpu_to_le32(0xC0220009)
-#define STATUS_FWP_IN_USE cpu_to_le32(0xC022000A)
-#define STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS cpu_to_le32(0xC022000B)
-#define STATUS_FWP_WRONG_SESSION cpu_to_le32(0xC022000C)
-#define STATUS_FWP_NO_TXN_IN_PROGRESS cpu_to_le32(0xC022000D)
-#define STATUS_FWP_TXN_IN_PROGRESS cpu_to_le32(0xC022000E)
-#define STATUS_FWP_TXN_ABORTED cpu_to_le32(0xC022000F)
-#define STATUS_FWP_SESSION_ABORTED cpu_to_le32(0xC0220010)
-#define STATUS_FWP_INCOMPATIBLE_TXN cpu_to_le32(0xC0220011)
-#define STATUS_FWP_TIMEOUT cpu_to_le32(0xC0220012)
-#define STATUS_FWP_NET_EVENTS_DISABLED cpu_to_le32(0xC0220013)
-#define STATUS_FWP_INCOMPATIBLE_LAYER cpu_to_le32(0xC0220014)
-#define STATUS_FWP_KM_CLIENTS_ONLY cpu_to_le32(0xC0220015)
-#define STATUS_FWP_LIFETIME_MISMATCH cpu_to_le32(0xC0220016)
-#define STATUS_FWP_BUILTIN_OBJECT cpu_to_le32(0xC0220017)
-#define STATUS_FWP_TOO_MANY_BOOTTIME_FILTERS cpu_to_le32(0xC0220018)
-#define STATUS_FWP_TOO_MANY_CALLOUTS cpu_to_le32(0xC0220018)
-#define STATUS_FWP_NOTIFICATION_DROPPED cpu_to_le32(0xC0220019)
-#define STATUS_FWP_TRAFFIC_MISMATCH cpu_to_le32(0xC022001A)
-#define STATUS_FWP_INCOMPATIBLE_SA_STATE cpu_to_le32(0xC022001B)
-#define STATUS_FWP_NULL_POINTER cpu_to_le32(0xC022001C)
-#define STATUS_FWP_INVALID_ENUMERATOR cpu_to_le32(0xC022001D)
-#define STATUS_FWP_INVALID_FLAGS cpu_to_le32(0xC022001E)
-#define STATUS_FWP_INVALID_NET_MASK cpu_to_le32(0xC022001F)
-#define STATUS_FWP_INVALID_RANGE cpu_to_le32(0xC0220020)
-#define STATUS_FWP_INVALID_INTERVAL cpu_to_le32(0xC0220021)
-#define STATUS_FWP_ZERO_LENGTH_ARRAY cpu_to_le32(0xC0220022)
-#define STATUS_FWP_NULL_DISPLAY_NAME cpu_to_le32(0xC0220023)
-#define STATUS_FWP_INVALID_ACTION_TYPE cpu_to_le32(0xC0220024)
-#define STATUS_FWP_INVALID_WEIGHT cpu_to_le32(0xC0220025)
-#define STATUS_FWP_MATCH_TYPE_MISMATCH cpu_to_le32(0xC0220026)
-#define STATUS_FWP_TYPE_MISMATCH cpu_to_le32(0xC0220027)
-#define STATUS_FWP_OUT_OF_BOUNDS cpu_to_le32(0xC0220028)
-#define STATUS_FWP_RESERVED cpu_to_le32(0xC0220029)
-#define STATUS_FWP_DUPLICATE_CONDITION cpu_to_le32(0xC022002A)
-#define STATUS_FWP_DUPLICATE_KEYMOD cpu_to_le32(0xC022002B)
-#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER cpu_to_le32(0xC022002C)
-#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER cpu_to_le32(0xC022002D)
-#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER cpu_to_le32(0xC022002E)
-#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT cpu_to_le32(0xC022002F)
-#define STATUS_FWP_INCOMPATIBLE_AUTH_METHOD cpu_to_le32(0xC0220030)
-#define STATUS_FWP_INCOMPATIBLE_DH_GROUP cpu_to_le32(0xC0220031)
-#define STATUS_FWP_EM_NOT_SUPPORTED cpu_to_le32(0xC0220032)
-#define STATUS_FWP_NEVER_MATCH cpu_to_le32(0xC0220033)
-#define STATUS_FWP_PROVIDER_CONTEXT_MISMATCH cpu_to_le32(0xC0220034)
-#define STATUS_FWP_INVALID_PARAMETER cpu_to_le32(0xC0220035)
-#define STATUS_FWP_TOO_MANY_SUBLAYERS cpu_to_le32(0xC0220036)
-#define STATUS_FWP_CALLOUT_NOTIFICATION_FAILED cpu_to_le32(0xC0220037)
-#define STATUS_FWP_INCOMPATIBLE_AUTH_CONFIG cpu_to_le32(0xC0220038)
-#define STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG cpu_to_le32(0xC0220039)
-#define STATUS_FWP_TCPIP_NOT_READY cpu_to_le32(0xC0220100)
-#define STATUS_FWP_INJECT_HANDLE_CLOSING cpu_to_le32(0xC0220101)
-#define STATUS_FWP_INJECT_HANDLE_STALE cpu_to_le32(0xC0220102)
-#define STATUS_FWP_CANNOT_PEND cpu_to_le32(0xC0220103)
-#define STATUS_NDIS_CLOSING cpu_to_le32(0xC0230002)
-#define STATUS_NDIS_BAD_VERSION cpu_to_le32(0xC0230004)
-#define STATUS_NDIS_BAD_CHARACTERISTICS cpu_to_le32(0xC0230005)
-#define STATUS_NDIS_ADAPTER_NOT_FOUND cpu_to_le32(0xC0230006)
-#define STATUS_NDIS_OPEN_FAILED cpu_to_le32(0xC0230007)
-#define STATUS_NDIS_DEVICE_FAILED cpu_to_le32(0xC0230008)
-#define STATUS_NDIS_MULTICAST_FULL cpu_to_le32(0xC0230009)
-#define STATUS_NDIS_MULTICAST_EXISTS cpu_to_le32(0xC023000A)
-#define STATUS_NDIS_MULTICAST_NOT_FOUND cpu_to_le32(0xC023000B)
-#define STATUS_NDIS_REQUEST_ABORTED cpu_to_le32(0xC023000C)
-#define STATUS_NDIS_RESET_IN_PROGRESS cpu_to_le32(0xC023000D)
-#define STATUS_NDIS_INVALID_PACKET cpu_to_le32(0xC023000F)
-#define STATUS_NDIS_INVALID_DEVICE_REQUEST cpu_to_le32(0xC0230010)
-#define STATUS_NDIS_ADAPTER_NOT_READY cpu_to_le32(0xC0230011)
-#define STATUS_NDIS_INVALID_LENGTH cpu_to_le32(0xC0230014)
-#define STATUS_NDIS_INVALID_DATA cpu_to_le32(0xC0230015)
-#define STATUS_NDIS_BUFFER_TOO_SHORT cpu_to_le32(0xC0230016)
-#define STATUS_NDIS_INVALID_OID cpu_to_le32(0xC0230017)
-#define STATUS_NDIS_ADAPTER_REMOVED cpu_to_le32(0xC0230018)
-#define STATUS_NDIS_UNSUPPORTED_MEDIA cpu_to_le32(0xC0230019)
-#define STATUS_NDIS_GROUP_ADDRESS_IN_USE cpu_to_le32(0xC023001A)
-#define STATUS_NDIS_FILE_NOT_FOUND cpu_to_le32(0xC023001B)
-#define STATUS_NDIS_ERROR_READING_FILE cpu_to_le32(0xC023001C)
-#define STATUS_NDIS_ALREADY_MAPPED cpu_to_le32(0xC023001D)
-#define STATUS_NDIS_RESOURCE_CONFLICT cpu_to_le32(0xC023001E)
-#define STATUS_NDIS_MEDIA_DISCONNECTED cpu_to_le32(0xC023001F)
-#define STATUS_NDIS_INVALID_ADDRESS cpu_to_le32(0xC0230022)
-#define STATUS_NDIS_PAUSED cpu_to_le32(0xC023002A)
-#define STATUS_NDIS_INTERFACE_NOT_FOUND cpu_to_le32(0xC023002B)
-#define STATUS_NDIS_UNSUPPORTED_REVISION cpu_to_le32(0xC023002C)
-#define STATUS_NDIS_INVALID_PORT cpu_to_le32(0xC023002D)
-#define STATUS_NDIS_INVALID_PORT_STATE cpu_to_le32(0xC023002E)
-#define STATUS_NDIS_LOW_POWER_STATE cpu_to_le32(0xC023002F)
-#define STATUS_NDIS_NOT_SUPPORTED cpu_to_le32(0xC02300BB)
-#define STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED cpu_to_le32(0xC0232000)
-#define STATUS_NDIS_DOT11_MEDIA_IN_USE cpu_to_le32(0xC0232001)
-#define STATUS_NDIS_DOT11_POWER_STATE_INVALID cpu_to_le32(0xC0232002)
-#define STATUS_IPSEC_BAD_SPI cpu_to_le32(0xC0360001)
-#define STATUS_IPSEC_SA_LIFETIME_EXPIRED cpu_to_le32(0xC0360002)
-#define STATUS_IPSEC_WRONG_SA cpu_to_le32(0xC0360003)
-#define STATUS_IPSEC_REPLAY_CHECK_FAILED cpu_to_le32(0xC0360004)
-#define STATUS_IPSEC_INVALID_PACKET cpu_to_le32(0xC0360005)
-#define STATUS_IPSEC_INTEGRITY_CHECK_FAILED cpu_to_le32(0xC0360006)
-#define STATUS_IPSEC_CLEAR_TEXT_DROP cpu_to_le32(0xC0360007)
-
-#define STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP cpu_to_le32(0xC05D0000)
-#define STATUS_INVALID_LOCK_RANGE cpu_to_le32(0xC00001a1)
diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
deleted file mode 100644
index 40c721f9227e..000000000000
--- a/fs/ksmbd/transport_ipc.c
+++ /dev/null
@@ -1,884 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/jhash.h>
-#include <linux/slab.h>
-#include <linux/rwsem.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/hashtable.h>
-#include <net/net_namespace.h>
-#include <net/genetlink.h>
-#include <linux/socket.h>
-#include <linux/workqueue.h>
-
-#include "vfs_cache.h"
-#include "transport_ipc.h"
-#include "server.h"
-#include "smb_common.h"
-
-#include "mgmt/user_config.h"
-#include "mgmt/share_config.h"
-#include "mgmt/user_session.h"
-#include "mgmt/tree_connect.h"
-#include "mgmt/ksmbd_ida.h"
-#include "connection.h"
-#include "transport_tcp.h"
-#include "transport_rdma.h"
-
-#define IPC_WAIT_TIMEOUT (2 * HZ)
-
-#define IPC_MSG_HASH_BITS 3
-static DEFINE_HASHTABLE(ipc_msg_table, IPC_MSG_HASH_BITS);
-static DECLARE_RWSEM(ipc_msg_table_lock);
-static DEFINE_MUTEX(startup_lock);
-
-static DEFINE_IDA(ipc_ida);
-
-static unsigned int ksmbd_tools_pid;
-
-static bool ksmbd_ipc_validate_version(struct genl_info *m)
-{
- if (m->genlhdr->version != KSMBD_GENL_VERSION) {
- pr_err("%s. ksmbd: %d, kernel module: %d. %s.\n",
- "Daemon and kernel module version mismatch",
- m->genlhdr->version,
- KSMBD_GENL_VERSION,
- "User-space ksmbd should terminate");
- return false;
- }
- return true;
-}
-
-struct ksmbd_ipc_msg {
- unsigned int type;
- unsigned int sz;
- unsigned char payload[];
-};
-
-struct ipc_msg_table_entry {
- unsigned int handle;
- unsigned int type;
- wait_queue_head_t wait;
- struct hlist_node ipc_table_hlist;
-
- void *response;
-};
-
-static struct delayed_work ipc_timer_work;
-
-static int handle_startup_event(struct sk_buff *skb, struct genl_info *info);
-static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info);
-static int handle_generic_event(struct sk_buff *skb, struct genl_info *info);
-static int ksmbd_ipc_heartbeat_request(void);
-
-static const struct nla_policy ksmbd_nl_policy[KSMBD_EVENT_MAX] = {
- [KSMBD_EVENT_UNSPEC] = {
- .len = 0,
- },
- [KSMBD_EVENT_HEARTBEAT_REQUEST] = {
- .len = sizeof(struct ksmbd_heartbeat),
- },
- [KSMBD_EVENT_STARTING_UP] = {
- .len = sizeof(struct ksmbd_startup_request),
- },
- [KSMBD_EVENT_SHUTTING_DOWN] = {
- .len = sizeof(struct ksmbd_shutdown_request),
- },
- [KSMBD_EVENT_LOGIN_REQUEST] = {
- .len = sizeof(struct ksmbd_login_request),
- },
- [KSMBD_EVENT_LOGIN_RESPONSE] = {
- .len = sizeof(struct ksmbd_login_response),
- },
- [KSMBD_EVENT_SHARE_CONFIG_REQUEST] = {
- .len = sizeof(struct ksmbd_share_config_request),
- },
- [KSMBD_EVENT_SHARE_CONFIG_RESPONSE] = {
- .len = sizeof(struct ksmbd_share_config_response),
- },
- [KSMBD_EVENT_TREE_CONNECT_REQUEST] = {
- .len = sizeof(struct ksmbd_tree_connect_request),
- },
- [KSMBD_EVENT_TREE_CONNECT_RESPONSE] = {
- .len = sizeof(struct ksmbd_tree_connect_response),
- },
- [KSMBD_EVENT_TREE_DISCONNECT_REQUEST] = {
- .len = sizeof(struct ksmbd_tree_disconnect_request),
- },
- [KSMBD_EVENT_LOGOUT_REQUEST] = {
- .len = sizeof(struct ksmbd_logout_request),
- },
- [KSMBD_EVENT_RPC_REQUEST] = {
- },
- [KSMBD_EVENT_RPC_RESPONSE] = {
- },
- [KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST] = {
- },
- [KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE] = {
- },
-};
-
-static struct genl_ops ksmbd_genl_ops[] = {
- {
- .cmd = KSMBD_EVENT_UNSPEC,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_HEARTBEAT_REQUEST,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_STARTING_UP,
- .doit = handle_startup_event,
- },
- {
- .cmd = KSMBD_EVENT_SHUTTING_DOWN,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_LOGIN_REQUEST,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_LOGIN_RESPONSE,
- .doit = handle_generic_event,
- },
- {
- .cmd = KSMBD_EVENT_SHARE_CONFIG_REQUEST,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_SHARE_CONFIG_RESPONSE,
- .doit = handle_generic_event,
- },
- {
- .cmd = KSMBD_EVENT_TREE_CONNECT_REQUEST,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_TREE_CONNECT_RESPONSE,
- .doit = handle_generic_event,
- },
- {
- .cmd = KSMBD_EVENT_TREE_DISCONNECT_REQUEST,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_LOGOUT_REQUEST,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_RPC_REQUEST,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_RPC_RESPONSE,
- .doit = handle_generic_event,
- },
- {
- .cmd = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST,
- .doit = handle_unsupported_event,
- },
- {
- .cmd = KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE,
- .doit = handle_generic_event,
- },
-};
-
-static struct genl_family ksmbd_genl_family = {
- .name = KSMBD_GENL_NAME,
- .version = KSMBD_GENL_VERSION,
- .hdrsize = 0,
- .maxattr = KSMBD_EVENT_MAX,
- .netnsok = true,
- .module = THIS_MODULE,
- .ops = ksmbd_genl_ops,
- .n_ops = ARRAY_SIZE(ksmbd_genl_ops),
- .resv_start_op = KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE + 1,
-};
-
-static void ksmbd_nl_init_fixup(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ksmbd_genl_ops); i++)
- ksmbd_genl_ops[i].validate = GENL_DONT_VALIDATE_STRICT |
- GENL_DONT_VALIDATE_DUMP;
-
- ksmbd_genl_family.policy = ksmbd_nl_policy;
-}
-
-static int rpc_context_flags(struct ksmbd_session *sess)
-{
- if (user_guest(sess->user))
- return KSMBD_RPC_RESTRICTED_CONTEXT;
- return 0;
-}
-
-static void ipc_update_last_active(void)
-{
- if (server_conf.ipc_timeout)
- server_conf.ipc_last_active = jiffies;
-}
-
-static struct ksmbd_ipc_msg *ipc_msg_alloc(size_t sz)
-{
- struct ksmbd_ipc_msg *msg;
- size_t msg_sz = sz + sizeof(struct ksmbd_ipc_msg);
-
- msg = kvmalloc(msg_sz, GFP_KERNEL | __GFP_ZERO);
- if (msg)
- msg->sz = sz;
- return msg;
-}
-
-static void ipc_msg_free(struct ksmbd_ipc_msg *msg)
-{
- kvfree(msg);
-}
-
-static void ipc_msg_handle_free(int handle)
-{
- if (handle >= 0)
- ksmbd_release_id(&ipc_ida, handle);
-}
-
-static int handle_response(int type, void *payload, size_t sz)
-{
- unsigned int handle = *(unsigned int *)payload;
- struct ipc_msg_table_entry *entry;
- int ret = 0;
-
- ipc_update_last_active();
- down_read(&ipc_msg_table_lock);
- hash_for_each_possible(ipc_msg_table, entry, ipc_table_hlist, handle) {
- if (handle != entry->handle)
- continue;
-
- entry->response = NULL;
- /*
- * Response message type value should be equal to
- * request message type + 1.
- */
- if (entry->type + 1 != type) {
- pr_err("Waiting for IPC type %d, got %d. Ignore.\n",
- entry->type + 1, type);
- }
-
- entry->response = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
- if (!entry->response) {
- ret = -ENOMEM;
- break;
- }
-
- memcpy(entry->response, payload, sz);
- wake_up_interruptible(&entry->wait);
- ret = 0;
- break;
- }
- up_read(&ipc_msg_table_lock);
-
- return ret;
-}
-
-static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
-{
- int ret;
-
- ksmbd_set_fd_limit(req->file_max);
- server_conf.flags = req->flags;
- server_conf.signing = req->signing;
- server_conf.tcp_port = req->tcp_port;
- server_conf.ipc_timeout = req->ipc_timeout * HZ;
- server_conf.deadtime = req->deadtime * SMB_ECHO_INTERVAL;
- server_conf.share_fake_fscaps = req->share_fake_fscaps;
- ksmbd_init_domain(req->sub_auth);
-
- if (req->smb2_max_read)
- init_smb2_max_read_size(req->smb2_max_read);
- if (req->smb2_max_write)
- init_smb2_max_write_size(req->smb2_max_write);
- if (req->smb2_max_trans)
- init_smb2_max_trans_size(req->smb2_max_trans);
- if (req->smb2_max_credits)
- init_smb2_max_credits(req->smb2_max_credits);
- if (req->smbd_max_io_size)
- init_smbd_max_io_size(req->smbd_max_io_size);
-
- if (req->max_connections)
- server_conf.max_connections = req->max_connections;
-
- ret = ksmbd_set_netbios_name(req->netbios_name);
- ret |= ksmbd_set_server_string(req->server_string);
- ret |= ksmbd_set_work_group(req->work_group);
- ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req),
- req->ifc_list_sz);
- if (ret) {
- pr_err("Server configuration error: %s %s %s\n",
- req->netbios_name, req->server_string,
- req->work_group);
- return ret;
- }
-
- if (req->min_prot[0]) {
- ret = ksmbd_lookup_protocol_idx(req->min_prot);
- if (ret >= 0)
- server_conf.min_protocol = ret;
- }
- if (req->max_prot[0]) {
- ret = ksmbd_lookup_protocol_idx(req->max_prot);
- if (ret >= 0)
- server_conf.max_protocol = ret;
- }
-
- if (server_conf.ipc_timeout)
- schedule_delayed_work(&ipc_timer_work, server_conf.ipc_timeout);
- return 0;
-}
-
-static int handle_startup_event(struct sk_buff *skb, struct genl_info *info)
-{
- int ret = 0;
-
-#ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
- if (!netlink_capable(skb, CAP_NET_ADMIN))
- return -EPERM;
-#endif
-
- if (!ksmbd_ipc_validate_version(info))
- return -EINVAL;
-
- if (!info->attrs[KSMBD_EVENT_STARTING_UP])
- return -EINVAL;
-
- mutex_lock(&startup_lock);
- if (!ksmbd_server_configurable()) {
- mutex_unlock(&startup_lock);
- pr_err("Server reset is in progress, can't start daemon\n");
- return -EINVAL;
- }
-
- if (ksmbd_tools_pid) {
- if (ksmbd_ipc_heartbeat_request() == 0) {
- ret = -EINVAL;
- goto out;
- }
-
- pr_err("Reconnect to a new user space daemon\n");
- } else {
- struct ksmbd_startup_request *req;
-
- req = nla_data(info->attrs[info->genlhdr->cmd]);
- ret = ipc_server_config_on_startup(req);
- if (ret)
- goto out;
- server_queue_ctrl_init_work();
- }
-
- ksmbd_tools_pid = info->snd_portid;
- ipc_update_last_active();
-
-out:
- mutex_unlock(&startup_lock);
- return ret;
-}
-
-static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info)
-{
- pr_err("Unknown IPC event: %d, ignore.\n", info->genlhdr->cmd);
- return -EINVAL;
-}
-
-static int handle_generic_event(struct sk_buff *skb, struct genl_info *info)
-{
- void *payload;
- int sz;
- int type = info->genlhdr->cmd;
-
-#ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
- if (!netlink_capable(skb, CAP_NET_ADMIN))
- return -EPERM;
-#endif
-
- if (type >= KSMBD_EVENT_MAX) {
- WARN_ON(1);
- return -EINVAL;
- }
-
- if (!ksmbd_ipc_validate_version(info))
- return -EINVAL;
-
- if (!info->attrs[type])
- return -EINVAL;
-
- payload = nla_data(info->attrs[info->genlhdr->cmd]);
- sz = nla_len(info->attrs[info->genlhdr->cmd]);
- return handle_response(type, payload, sz);
-}
-
-static int ipc_msg_send(struct ksmbd_ipc_msg *msg)
-{
- struct genlmsghdr *nlh;
- struct sk_buff *skb;
- int ret = -EINVAL;
-
- if (!ksmbd_tools_pid)
- return ret;
-
- skb = genlmsg_new(msg->sz, GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
-
- nlh = genlmsg_put(skb, 0, 0, &ksmbd_genl_family, 0, msg->type);
- if (!nlh)
- goto out;
-
- ret = nla_put(skb, msg->type, msg->sz, msg->payload);
- if (ret) {
- genlmsg_cancel(skb, nlh);
- goto out;
- }
-
- genlmsg_end(skb, nlh);
- ret = genlmsg_unicast(&init_net, skb, ksmbd_tools_pid);
- if (!ret)
- ipc_update_last_active();
- return ret;
-
-out:
- nlmsg_free(skb);
- return ret;
-}
-
-static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle)
-{
- struct ipc_msg_table_entry entry;
- int ret;
-
- if ((int)handle < 0)
- return NULL;
-
- entry.type = msg->type;
- entry.response = NULL;
- init_waitqueue_head(&entry.wait);
-
- down_write(&ipc_msg_table_lock);
- entry.handle = handle;
- hash_add(ipc_msg_table, &entry.ipc_table_hlist, entry.handle);
- up_write(&ipc_msg_table_lock);
-
- ret = ipc_msg_send(msg);
- if (ret)
- goto out;
-
- ret = wait_event_interruptible_timeout(entry.wait,
- entry.response != NULL,
- IPC_WAIT_TIMEOUT);
-out:
- down_write(&ipc_msg_table_lock);
- hash_del(&entry.ipc_table_hlist);
- up_write(&ipc_msg_table_lock);
- return entry.response;
-}
-
-static int ksmbd_ipc_heartbeat_request(void)
-{
- struct ksmbd_ipc_msg *msg;
- int ret;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_heartbeat));
- if (!msg)
- return -EINVAL;
-
- msg->type = KSMBD_EVENT_HEARTBEAT_REQUEST;
- ret = ipc_msg_send(msg);
- ipc_msg_free(msg);
- return ret;
-}
-
-struct ksmbd_login_response *ksmbd_ipc_login_request(const char *account)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_login_request *req;
- struct ksmbd_login_response *resp;
-
- if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
- return NULL;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_login_request));
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_LOGIN_REQUEST;
- req = (struct ksmbd_login_request *)msg->payload;
- req->handle = ksmbd_acquire_id(&ipc_ida);
- strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_handle_free(req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-struct ksmbd_spnego_authen_response *
-ksmbd_ipc_spnego_authen_request(const char *spnego_blob, int blob_len)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_spnego_authen_request *req;
- struct ksmbd_spnego_authen_response *resp;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_spnego_authen_request) +
- blob_len + 1);
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST;
- req = (struct ksmbd_spnego_authen_request *)msg->payload;
- req->handle = ksmbd_acquire_id(&ipc_ida);
- req->spnego_blob_len = blob_len;
- memcpy(req->spnego_blob, spnego_blob, blob_len);
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_handle_free(req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-struct ksmbd_tree_connect_response *
-ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess,
- struct ksmbd_share_config *share,
- struct ksmbd_tree_connect *tree_conn,
- struct sockaddr *peer_addr)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_tree_connect_request *req;
- struct ksmbd_tree_connect_response *resp;
-
- if (strlen(user_name(sess->user)) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
- return NULL;
-
- if (strlen(share->name) >= KSMBD_REQ_MAX_SHARE_NAME)
- return NULL;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_connect_request));
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_TREE_CONNECT_REQUEST;
- req = (struct ksmbd_tree_connect_request *)msg->payload;
-
- req->handle = ksmbd_acquire_id(&ipc_ida);
- req->account_flags = sess->user->flags;
- req->session_id = sess->id;
- req->connect_id = tree_conn->id;
- strscpy(req->account, user_name(sess->user), KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
- strscpy(req->share, share->name, KSMBD_REQ_MAX_SHARE_NAME);
- snprintf(req->peer_addr, sizeof(req->peer_addr), "%pIS", peer_addr);
-
- if (peer_addr->sa_family == AF_INET6)
- req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_IPV6;
- if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
- req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_SMB2;
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_handle_free(req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
- unsigned long long connect_id)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_tree_disconnect_request *req;
- int ret;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_disconnect_request));
- if (!msg)
- return -ENOMEM;
-
- msg->type = KSMBD_EVENT_TREE_DISCONNECT_REQUEST;
- req = (struct ksmbd_tree_disconnect_request *)msg->payload;
- req->session_id = session_id;
- req->connect_id = connect_id;
-
- ret = ipc_msg_send(msg);
- ipc_msg_free(msg);
- return ret;
-}
-
-int ksmbd_ipc_logout_request(const char *account, int flags)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_logout_request *req;
- int ret;
-
- if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
- return -EINVAL;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_logout_request));
- if (!msg)
- return -ENOMEM;
-
- msg->type = KSMBD_EVENT_LOGOUT_REQUEST;
- req = (struct ksmbd_logout_request *)msg->payload;
- req->account_flags = flags;
- strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
-
- ret = ipc_msg_send(msg);
- ipc_msg_free(msg);
- return ret;
-}
-
-struct ksmbd_share_config_response *
-ksmbd_ipc_share_config_request(const char *name)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_share_config_request *req;
- struct ksmbd_share_config_response *resp;
-
- if (strlen(name) >= KSMBD_REQ_MAX_SHARE_NAME)
- return NULL;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_share_config_request));
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_SHARE_CONFIG_REQUEST;
- req = (struct ksmbd_share_config_request *)msg->payload;
- req->handle = ksmbd_acquire_id(&ipc_ida);
- strscpy(req->share_name, name, KSMBD_REQ_MAX_SHARE_NAME);
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_handle_free(req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-struct ksmbd_rpc_command *ksmbd_rpc_open(struct ksmbd_session *sess, int handle)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_rpc_command *req;
- struct ksmbd_rpc_command *resp;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = (struct ksmbd_rpc_command *)msg->payload;
- req->handle = handle;
- req->flags = ksmbd_session_rpc_method(sess, handle);
- req->flags |= KSMBD_RPC_OPEN_METHOD;
- req->payload_sz = 0;
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-struct ksmbd_rpc_command *ksmbd_rpc_close(struct ksmbd_session *sess, int handle)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_rpc_command *req;
- struct ksmbd_rpc_command *resp;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = (struct ksmbd_rpc_command *)msg->payload;
- req->handle = handle;
- req->flags = ksmbd_session_rpc_method(sess, handle);
- req->flags |= KSMBD_RPC_CLOSE_METHOD;
- req->payload_sz = 0;
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle,
- void *payload, size_t payload_sz)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_rpc_command *req;
- struct ksmbd_rpc_command *resp;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = (struct ksmbd_rpc_command *)msg->payload;
- req->handle = handle;
- req->flags = ksmbd_session_rpc_method(sess, handle);
- req->flags |= rpc_context_flags(sess);
- req->flags |= KSMBD_RPC_WRITE_METHOD;
- req->payload_sz = payload_sz;
- memcpy(req->payload, payload, payload_sz);
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_rpc_command *req;
- struct ksmbd_rpc_command *resp;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = (struct ksmbd_rpc_command *)msg->payload;
- req->handle = handle;
- req->flags = ksmbd_session_rpc_method(sess, handle);
- req->flags |= rpc_context_flags(sess);
- req->flags |= KSMBD_RPC_READ_METHOD;
- req->payload_sz = 0;
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle,
- void *payload, size_t payload_sz)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_rpc_command *req;
- struct ksmbd_rpc_command *resp;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = (struct ksmbd_rpc_command *)msg->payload;
- req->handle = handle;
- req->flags = ksmbd_session_rpc_method(sess, handle);
- req->flags |= rpc_context_flags(sess);
- req->flags |= KSMBD_RPC_IOCTL_METHOD;
- req->payload_sz = payload_sz;
- memcpy(req->payload, payload, payload_sz);
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-struct ksmbd_rpc_command *ksmbd_rpc_rap(struct ksmbd_session *sess, void *payload,
- size_t payload_sz)
-{
- struct ksmbd_ipc_msg *msg;
- struct ksmbd_rpc_command *req;
- struct ksmbd_rpc_command *resp;
-
- msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
- if (!msg)
- return NULL;
-
- msg->type = KSMBD_EVENT_RPC_REQUEST;
- req = (struct ksmbd_rpc_command *)msg->payload;
- req->handle = ksmbd_acquire_id(&ipc_ida);
- req->flags = rpc_context_flags(sess);
- req->flags |= KSMBD_RPC_RAP_METHOD;
- req->payload_sz = payload_sz;
- memcpy(req->payload, payload, payload_sz);
-
- resp = ipc_msg_send_request(msg, req->handle);
- ipc_msg_handle_free(req->handle);
- ipc_msg_free(msg);
- return resp;
-}
-
-static int __ipc_heartbeat(void)
-{
- unsigned long delta;
-
- if (!ksmbd_server_running())
- return 0;
-
- if (time_after(jiffies, server_conf.ipc_last_active)) {
- delta = (jiffies - server_conf.ipc_last_active);
- } else {
- ipc_update_last_active();
- schedule_delayed_work(&ipc_timer_work,
- server_conf.ipc_timeout);
- return 0;
- }
-
- if (delta < server_conf.ipc_timeout) {
- schedule_delayed_work(&ipc_timer_work,
- server_conf.ipc_timeout - delta);
- return 0;
- }
-
- if (ksmbd_ipc_heartbeat_request() == 0) {
- schedule_delayed_work(&ipc_timer_work,
- server_conf.ipc_timeout);
- return 0;
- }
-
- mutex_lock(&startup_lock);
- WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
- server_conf.ipc_last_active = 0;
- ksmbd_tools_pid = 0;
- pr_err("No IPC daemon response for %lus\n", delta / HZ);
- mutex_unlock(&startup_lock);
- return -EINVAL;
-}
-
-static void ipc_timer_heartbeat(struct work_struct *w)
-{
- if (__ipc_heartbeat())
- server_queue_ctrl_reset_work();
-}
-
-int ksmbd_ipc_id_alloc(void)
-{
- return ksmbd_acquire_id(&ipc_ida);
-}
-
-void ksmbd_rpc_id_free(int handle)
-{
- ksmbd_release_id(&ipc_ida, handle);
-}
-
-void ksmbd_ipc_release(void)
-{
- cancel_delayed_work_sync(&ipc_timer_work);
- genl_unregister_family(&ksmbd_genl_family);
-}
-
-void ksmbd_ipc_soft_reset(void)
-{
- mutex_lock(&startup_lock);
- ksmbd_tools_pid = 0;
- cancel_delayed_work_sync(&ipc_timer_work);
- mutex_unlock(&startup_lock);
-}
-
-int ksmbd_ipc_init(void)
-{
- int ret = 0;
-
- ksmbd_nl_init_fixup();
- INIT_DELAYED_WORK(&ipc_timer_work, ipc_timer_heartbeat);
-
- ret = genl_register_family(&ksmbd_genl_family);
- if (ret) {
- pr_err("Failed to register KSMBD netlink interface %d\n", ret);
- cancel_delayed_work_sync(&ipc_timer_work);
- }
-
- return ret;
-}
diff --git a/fs/ksmbd/transport_ipc.h b/fs/ksmbd/transport_ipc.h
deleted file mode 100644
index 5e5b90a0c187..000000000000
--- a/fs/ksmbd/transport_ipc.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_TRANSPORT_IPC_H__
-#define __KSMBD_TRANSPORT_IPC_H__
-
-#include <linux/wait.h>
-
-#define KSMBD_IPC_MAX_PAYLOAD 4096
-
-struct ksmbd_login_response *
-ksmbd_ipc_login_request(const char *account);
-
-struct ksmbd_session;
-struct ksmbd_share_config;
-struct ksmbd_tree_connect;
-struct sockaddr;
-
-struct ksmbd_tree_connect_response *
-ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess,
- struct ksmbd_share_config *share,
- struct ksmbd_tree_connect *tree_conn,
- struct sockaddr *peer_addr);
-int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
- unsigned long long connect_id);
-int ksmbd_ipc_logout_request(const char *account, int flags);
-struct ksmbd_share_config_response *
-ksmbd_ipc_share_config_request(const char *name);
-struct ksmbd_spnego_authen_response *
-ksmbd_ipc_spnego_authen_request(const char *spnego_blob, int blob_len);
-int ksmbd_ipc_id_alloc(void);
-void ksmbd_rpc_id_free(int handle);
-struct ksmbd_rpc_command *ksmbd_rpc_open(struct ksmbd_session *sess, int handle);
-struct ksmbd_rpc_command *ksmbd_rpc_close(struct ksmbd_session *sess, int handle);
-struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle,
- void *payload, size_t payload_sz);
-struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle);
-struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle,
- void *payload, size_t payload_sz);
-struct ksmbd_rpc_command *ksmbd_rpc_rap(struct ksmbd_session *sess, void *payload,
- size_t payload_sz);
-void ksmbd_ipc_release(void);
-void ksmbd_ipc_soft_reset(void);
-int ksmbd_ipc_init(void);
-#endif /* __KSMBD_TRANSPORT_IPC_H__ */
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
deleted file mode 100644
index c06efc020bd9..000000000000
--- a/fs/ksmbd/transport_rdma.c
+++ /dev/null
@@ -1,2273 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2017, Microsoft Corporation.
- * Copyright (C) 2018, LG Electronics.
- *
- * Author(s): Long Li <longli@microsoft.com>,
- * Hyunchul Lee <hyc.lee@gmail.com>
- */
-
-#define SUBMOD_NAME "smb_direct"
-
-#include <linux/kthread.h>
-#include <linux/list.h>
-#include <linux/mempool.h>
-#include <linux/highmem.h>
-#include <linux/scatterlist.h>
-#include <rdma/ib_verbs.h>
-#include <rdma/rdma_cm.h>
-#include <rdma/rw.h>
-
-#include "glob.h"
-#include "connection.h"
-#include "smb_common.h"
-#include "smbstatus.h"
-#include "transport_rdma.h"
-
-#define SMB_DIRECT_PORT_IWARP 5445
-#define SMB_DIRECT_PORT_INFINIBAND 445
-
-#define SMB_DIRECT_VERSION_LE cpu_to_le16(0x0100)
-
-/* SMB_DIRECT negotiation timeout in seconds */
-#define SMB_DIRECT_NEGOTIATE_TIMEOUT 120
-
-#define SMB_DIRECT_MAX_SEND_SGES 6
-#define SMB_DIRECT_MAX_RECV_SGES 1
-
-/*
- * Default maximum number of RDMA read/write outstanding on this connection
- * This value is possibly decreased during QP creation on hardware limit
- */
-#define SMB_DIRECT_CM_INITIATOR_DEPTH 8
-
-/* Maximum number of retries on data transfer operations */
-#define SMB_DIRECT_CM_RETRY 6
-/* No need to retry on Receiver Not Ready since SMB_DIRECT manages credits */
-#define SMB_DIRECT_CM_RNR_RETRY 0
-
-/*
- * User configurable initial values per SMB_DIRECT transport connection
- * as defined in [MS-SMBD] 3.1.1.1
- * Those may change after a SMB_DIRECT negotiation
- */
-
-/* Set 445 port to SMB Direct port by default */
-static int smb_direct_port = SMB_DIRECT_PORT_INFINIBAND;
-
-/* The local peer's maximum number of credits to grant to the peer */
-static int smb_direct_receive_credit_max = 255;
-
-/* The remote peer's credit request of local peer */
-static int smb_direct_send_credit_target = 255;
-
-/* The maximum single message size can be sent to remote peer */
-static int smb_direct_max_send_size = 1364;
-
-/* The maximum fragmented upper-layer payload receive size supported */
-static int smb_direct_max_fragmented_recv_size = 1024 * 1024;
-
-/* The maximum single-message size which can be received */
-static int smb_direct_max_receive_size = 1364;
-
-static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE;
-
-static LIST_HEAD(smb_direct_device_list);
-static DEFINE_RWLOCK(smb_direct_device_lock);
-
-struct smb_direct_device {
- struct ib_device *ib_dev;
- struct list_head list;
-};
-
-static struct smb_direct_listener {
- struct rdma_cm_id *cm_id;
-} smb_direct_listener;
-
-static struct workqueue_struct *smb_direct_wq;
-
-enum smb_direct_status {
- SMB_DIRECT_CS_NEW = 0,
- SMB_DIRECT_CS_CONNECTED,
- SMB_DIRECT_CS_DISCONNECTING,
- SMB_DIRECT_CS_DISCONNECTED,
-};
-
-struct smb_direct_transport {
- struct ksmbd_transport transport;
-
- enum smb_direct_status status;
- bool full_packet_received;
- wait_queue_head_t wait_status;
-
- struct rdma_cm_id *cm_id;
- struct ib_cq *send_cq;
- struct ib_cq *recv_cq;
- struct ib_pd *pd;
- struct ib_qp *qp;
-
- int max_send_size;
- int max_recv_size;
- int max_fragmented_send_size;
- int max_fragmented_recv_size;
- int max_rdma_rw_size;
-
- spinlock_t reassembly_queue_lock;
- struct list_head reassembly_queue;
- int reassembly_data_length;
- int reassembly_queue_length;
- int first_entry_offset;
- wait_queue_head_t wait_reassembly_queue;
-
- spinlock_t receive_credit_lock;
- int recv_credits;
- int count_avail_recvmsg;
- int recv_credit_max;
- int recv_credit_target;
-
- spinlock_t recvmsg_queue_lock;
- struct list_head recvmsg_queue;
-
- spinlock_t empty_recvmsg_queue_lock;
- struct list_head empty_recvmsg_queue;
-
- int send_credit_target;
- atomic_t send_credits;
- spinlock_t lock_new_recv_credits;
- int new_recv_credits;
- int max_rw_credits;
- int pages_per_rw_credit;
- atomic_t rw_credits;
-
- wait_queue_head_t wait_send_credits;
- wait_queue_head_t wait_rw_credits;
-
- mempool_t *sendmsg_mempool;
- struct kmem_cache *sendmsg_cache;
- mempool_t *recvmsg_mempool;
- struct kmem_cache *recvmsg_cache;
-
- wait_queue_head_t wait_send_pending;
- atomic_t send_pending;
-
- struct delayed_work post_recv_credits_work;
- struct work_struct send_immediate_work;
- struct work_struct disconnect_work;
-
- bool negotiation_requested;
-};
-
-#define KSMBD_TRANS(t) ((struct ksmbd_transport *)&((t)->transport))
-
-enum {
- SMB_DIRECT_MSG_NEGOTIATE_REQ = 0,
- SMB_DIRECT_MSG_DATA_TRANSFER
-};
-
-static struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops;
-
-struct smb_direct_send_ctx {
- struct list_head msg_list;
- int wr_cnt;
- bool need_invalidate_rkey;
- unsigned int remote_key;
-};
-
-struct smb_direct_sendmsg {
- struct smb_direct_transport *transport;
- struct ib_send_wr wr;
- struct list_head list;
- int num_sge;
- struct ib_sge sge[SMB_DIRECT_MAX_SEND_SGES];
- struct ib_cqe cqe;
- u8 packet[];
-};
-
-struct smb_direct_recvmsg {
- struct smb_direct_transport *transport;
- struct list_head list;
- int type;
- struct ib_sge sge;
- struct ib_cqe cqe;
- bool first_segment;
- u8 packet[];
-};
-
-struct smb_direct_rdma_rw_msg {
- struct smb_direct_transport *t;
- struct ib_cqe cqe;
- int status;
- struct completion *completion;
- struct list_head list;
- struct rdma_rw_ctx rw_ctx;
- struct sg_table sgt;
- struct scatterlist sg_list[];
-};
-
-void init_smbd_max_io_size(unsigned int sz)
-{
- sz = clamp_val(sz, SMBD_MIN_IOSIZE, SMBD_MAX_IOSIZE);
- smb_direct_max_read_write_size = sz;
-}
-
-unsigned int get_smbd_max_read_write_size(void)
-{
- return smb_direct_max_read_write_size;
-}
-
-static inline int get_buf_page_count(void *buf, int size)
-{
- return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
- (uintptr_t)buf / PAGE_SIZE;
-}
-
-static void smb_direct_destroy_pools(struct smb_direct_transport *transport);
-static void smb_direct_post_recv_credits(struct work_struct *work);
-static int smb_direct_post_send_data(struct smb_direct_transport *t,
- struct smb_direct_send_ctx *send_ctx,
- struct kvec *iov, int niov,
- int remaining_data_length);
-
-static inline struct smb_direct_transport *
-smb_trans_direct_transfort(struct ksmbd_transport *t)
-{
- return container_of(t, struct smb_direct_transport, transport);
-}
-
-static inline void
-*smb_direct_recvmsg_payload(struct smb_direct_recvmsg *recvmsg)
-{
- return (void *)recvmsg->packet;
-}
-
-static inline bool is_receive_credit_post_required(int receive_credits,
- int avail_recvmsg_count)
-{
- return receive_credits <= (smb_direct_receive_credit_max >> 3) &&
- avail_recvmsg_count >= (receive_credits >> 2);
-}
-
-static struct
-smb_direct_recvmsg *get_free_recvmsg(struct smb_direct_transport *t)
-{
- struct smb_direct_recvmsg *recvmsg = NULL;
-
- spin_lock(&t->recvmsg_queue_lock);
- if (!list_empty(&t->recvmsg_queue)) {
- recvmsg = list_first_entry(&t->recvmsg_queue,
- struct smb_direct_recvmsg,
- list);
- list_del(&recvmsg->list);
- }
- spin_unlock(&t->recvmsg_queue_lock);
- return recvmsg;
-}
-
-static void put_recvmsg(struct smb_direct_transport *t,
- struct smb_direct_recvmsg *recvmsg)
-{
- ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr,
- recvmsg->sge.length, DMA_FROM_DEVICE);
-
- spin_lock(&t->recvmsg_queue_lock);
- list_add(&recvmsg->list, &t->recvmsg_queue);
- spin_unlock(&t->recvmsg_queue_lock);
-}
-
-static struct
-smb_direct_recvmsg *get_empty_recvmsg(struct smb_direct_transport *t)
-{
- struct smb_direct_recvmsg *recvmsg = NULL;
-
- spin_lock(&t->empty_recvmsg_queue_lock);
- if (!list_empty(&t->empty_recvmsg_queue)) {
- recvmsg = list_first_entry(&t->empty_recvmsg_queue,
- struct smb_direct_recvmsg, list);
- list_del(&recvmsg->list);
- }
- spin_unlock(&t->empty_recvmsg_queue_lock);
- return recvmsg;
-}
-
-static void put_empty_recvmsg(struct smb_direct_transport *t,
- struct smb_direct_recvmsg *recvmsg)
-{
- ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr,
- recvmsg->sge.length, DMA_FROM_DEVICE);
-
- spin_lock(&t->empty_recvmsg_queue_lock);
- list_add_tail(&recvmsg->list, &t->empty_recvmsg_queue);
- spin_unlock(&t->empty_recvmsg_queue_lock);
-}
-
-static void enqueue_reassembly(struct smb_direct_transport *t,
- struct smb_direct_recvmsg *recvmsg,
- int data_length)
-{
- spin_lock(&t->reassembly_queue_lock);
- list_add_tail(&recvmsg->list, &t->reassembly_queue);
- t->reassembly_queue_length++;
- /*
- * Make sure reassembly_data_length is updated after list and
- * reassembly_queue_length are updated. On the dequeue side
- * reassembly_data_length is checked without a lock to determine
- * if reassembly_queue_length and list is up to date
- */
- virt_wmb();
- t->reassembly_data_length += data_length;
- spin_unlock(&t->reassembly_queue_lock);
-}
-
-static struct smb_direct_recvmsg *get_first_reassembly(struct smb_direct_transport *t)
-{
- if (!list_empty(&t->reassembly_queue))
- return list_first_entry(&t->reassembly_queue,
- struct smb_direct_recvmsg, list);
- else
- return NULL;
-}
-
-static void smb_direct_disconnect_rdma_work(struct work_struct *work)
-{
- struct smb_direct_transport *t =
- container_of(work, struct smb_direct_transport,
- disconnect_work);
-
- if (t->status == SMB_DIRECT_CS_CONNECTED) {
- t->status = SMB_DIRECT_CS_DISCONNECTING;
- rdma_disconnect(t->cm_id);
- }
-}
-
-static void
-smb_direct_disconnect_rdma_connection(struct smb_direct_transport *t)
-{
- if (t->status == SMB_DIRECT_CS_CONNECTED)
- queue_work(smb_direct_wq, &t->disconnect_work);
-}
-
-static void smb_direct_send_immediate_work(struct work_struct *work)
-{
- struct smb_direct_transport *t = container_of(work,
- struct smb_direct_transport, send_immediate_work);
-
- if (t->status != SMB_DIRECT_CS_CONNECTED)
- return;
-
- smb_direct_post_send_data(t, NULL, NULL, 0, 0);
-}
-
-static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
-{
- struct smb_direct_transport *t;
- struct ksmbd_conn *conn;
-
- t = kzalloc(sizeof(*t), GFP_KERNEL);
- if (!t)
- return NULL;
-
- t->cm_id = cm_id;
- cm_id->context = t;
-
- t->status = SMB_DIRECT_CS_NEW;
- init_waitqueue_head(&t->wait_status);
-
- spin_lock_init(&t->reassembly_queue_lock);
- INIT_LIST_HEAD(&t->reassembly_queue);
- t->reassembly_data_length = 0;
- t->reassembly_queue_length = 0;
- init_waitqueue_head(&t->wait_reassembly_queue);
- init_waitqueue_head(&t->wait_send_credits);
- init_waitqueue_head(&t->wait_rw_credits);
-
- spin_lock_init(&t->receive_credit_lock);
- spin_lock_init(&t->recvmsg_queue_lock);
- INIT_LIST_HEAD(&t->recvmsg_queue);
-
- spin_lock_init(&t->empty_recvmsg_queue_lock);
- INIT_LIST_HEAD(&t->empty_recvmsg_queue);
-
- init_waitqueue_head(&t->wait_send_pending);
- atomic_set(&t->send_pending, 0);
-
- spin_lock_init(&t->lock_new_recv_credits);
-
- INIT_DELAYED_WORK(&t->post_recv_credits_work,
- smb_direct_post_recv_credits);
- INIT_WORK(&t->send_immediate_work, smb_direct_send_immediate_work);
- INIT_WORK(&t->disconnect_work, smb_direct_disconnect_rdma_work);
-
- conn = ksmbd_conn_alloc();
- if (!conn)
- goto err;
- conn->transport = KSMBD_TRANS(t);
- KSMBD_TRANS(t)->conn = conn;
- KSMBD_TRANS(t)->ops = &ksmbd_smb_direct_transport_ops;
- return t;
-err:
- kfree(t);
- return NULL;
-}
-
-static void free_transport(struct smb_direct_transport *t)
-{
- struct smb_direct_recvmsg *recvmsg;
-
- wake_up_interruptible(&t->wait_send_credits);
-
- ksmbd_debug(RDMA, "wait for all send posted to IB to finish\n");
- wait_event(t->wait_send_pending,
- atomic_read(&t->send_pending) == 0);
-
- cancel_work_sync(&t->disconnect_work);
- cancel_delayed_work_sync(&t->post_recv_credits_work);
- cancel_work_sync(&t->send_immediate_work);
-
- if (t->qp) {
- ib_drain_qp(t->qp);
- ib_mr_pool_destroy(t->qp, &t->qp->rdma_mrs);
- ib_destroy_qp(t->qp);
- }
-
- ksmbd_debug(RDMA, "drain the reassembly queue\n");
- do {
- spin_lock(&t->reassembly_queue_lock);
- recvmsg = get_first_reassembly(t);
- if (recvmsg) {
- list_del(&recvmsg->list);
- spin_unlock(&t->reassembly_queue_lock);
- put_recvmsg(t, recvmsg);
- } else {
- spin_unlock(&t->reassembly_queue_lock);
- }
- } while (recvmsg);
- t->reassembly_data_length = 0;
-
- if (t->send_cq)
- ib_free_cq(t->send_cq);
- if (t->recv_cq)
- ib_free_cq(t->recv_cq);
- if (t->pd)
- ib_dealloc_pd(t->pd);
- if (t->cm_id)
- rdma_destroy_id(t->cm_id);
-
- smb_direct_destroy_pools(t);
- ksmbd_conn_free(KSMBD_TRANS(t)->conn);
- kfree(t);
-}
-
-static struct smb_direct_sendmsg
-*smb_direct_alloc_sendmsg(struct smb_direct_transport *t)
-{
- struct smb_direct_sendmsg *msg;
-
- msg = mempool_alloc(t->sendmsg_mempool, GFP_KERNEL);
- if (!msg)
- return ERR_PTR(-ENOMEM);
- msg->transport = t;
- INIT_LIST_HEAD(&msg->list);
- msg->num_sge = 0;
- return msg;
-}
-
-static void smb_direct_free_sendmsg(struct smb_direct_transport *t,
- struct smb_direct_sendmsg *msg)
-{
- int i;
-
- if (msg->num_sge > 0) {
- ib_dma_unmap_single(t->cm_id->device,
- msg->sge[0].addr, msg->sge[0].length,
- DMA_TO_DEVICE);
- for (i = 1; i < msg->num_sge; i++)
- ib_dma_unmap_page(t->cm_id->device,
- msg->sge[i].addr, msg->sge[i].length,
- DMA_TO_DEVICE);
- }
- mempool_free(msg, t->sendmsg_mempool);
-}
-
-static int smb_direct_check_recvmsg(struct smb_direct_recvmsg *recvmsg)
-{
- switch (recvmsg->type) {
- case SMB_DIRECT_MSG_DATA_TRANSFER: {
- struct smb_direct_data_transfer *req =
- (struct smb_direct_data_transfer *)recvmsg->packet;
- struct smb2_hdr *hdr = (struct smb2_hdr *)(recvmsg->packet
- + le32_to_cpu(req->data_offset));
- ksmbd_debug(RDMA,
- "CreditGranted: %u, CreditRequested: %u, DataLength: %u, RemainingDataLength: %u, SMB: %x, Command: %u\n",
- le16_to_cpu(req->credits_granted),
- le16_to_cpu(req->credits_requested),
- req->data_length, req->remaining_data_length,
- hdr->ProtocolId, hdr->Command);
- break;
- }
- case SMB_DIRECT_MSG_NEGOTIATE_REQ: {
- struct smb_direct_negotiate_req *req =
- (struct smb_direct_negotiate_req *)recvmsg->packet;
- ksmbd_debug(RDMA,
- "MinVersion: %u, MaxVersion: %u, CreditRequested: %u, MaxSendSize: %u, MaxRecvSize: %u, MaxFragmentedSize: %u\n",
- le16_to_cpu(req->min_version),
- le16_to_cpu(req->max_version),
- le16_to_cpu(req->credits_requested),
- le32_to_cpu(req->preferred_send_size),
- le32_to_cpu(req->max_receive_size),
- le32_to_cpu(req->max_fragmented_size));
- if (le16_to_cpu(req->min_version) > 0x0100 ||
- le16_to_cpu(req->max_version) < 0x0100)
- return -EOPNOTSUPP;
- if (le16_to_cpu(req->credits_requested) <= 0 ||
- le32_to_cpu(req->max_receive_size) <= 128 ||
- le32_to_cpu(req->max_fragmented_size) <=
- 128 * 1024)
- return -ECONNABORTED;
-
- break;
- }
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smb_direct_recvmsg *recvmsg;
- struct smb_direct_transport *t;
-
- recvmsg = container_of(wc->wr_cqe, struct smb_direct_recvmsg, cqe);
- t = recvmsg->transport;
-
- if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
- if (wc->status != IB_WC_WR_FLUSH_ERR) {
- pr_err("Recv error. status='%s (%d)' opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
- smb_direct_disconnect_rdma_connection(t);
- }
- put_empty_recvmsg(t, recvmsg);
- return;
- }
-
- ksmbd_debug(RDMA, "Recv completed. status='%s (%d)', opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
-
- ib_dma_sync_single_for_cpu(wc->qp->device, recvmsg->sge.addr,
- recvmsg->sge.length, DMA_FROM_DEVICE);
-
- switch (recvmsg->type) {
- case SMB_DIRECT_MSG_NEGOTIATE_REQ:
- if (wc->byte_len < sizeof(struct smb_direct_negotiate_req)) {
- put_empty_recvmsg(t, recvmsg);
- return;
- }
- t->negotiation_requested = true;
- t->full_packet_received = true;
- t->status = SMB_DIRECT_CS_CONNECTED;
- enqueue_reassembly(t, recvmsg, 0);
- wake_up_interruptible(&t->wait_status);
- break;
- case SMB_DIRECT_MSG_DATA_TRANSFER: {
- struct smb_direct_data_transfer *data_transfer =
- (struct smb_direct_data_transfer *)recvmsg->packet;
- unsigned int data_length;
- int avail_recvmsg_count, receive_credits;
-
- if (wc->byte_len <
- offsetof(struct smb_direct_data_transfer, padding)) {
- put_empty_recvmsg(t, recvmsg);
- return;
- }
-
- data_length = le32_to_cpu(data_transfer->data_length);
- if (data_length) {
- if (wc->byte_len < sizeof(struct smb_direct_data_transfer) +
- (u64)data_length) {
- put_empty_recvmsg(t, recvmsg);
- return;
- }
-
- if (t->full_packet_received)
- recvmsg->first_segment = true;
-
- if (le32_to_cpu(data_transfer->remaining_data_length))
- t->full_packet_received = false;
- else
- t->full_packet_received = true;
-
- enqueue_reassembly(t, recvmsg, (int)data_length);
- wake_up_interruptible(&t->wait_reassembly_queue);
-
- spin_lock(&t->receive_credit_lock);
- receive_credits = --(t->recv_credits);
- avail_recvmsg_count = t->count_avail_recvmsg;
- spin_unlock(&t->receive_credit_lock);
- } else {
- put_empty_recvmsg(t, recvmsg);
-
- spin_lock(&t->receive_credit_lock);
- receive_credits = --(t->recv_credits);
- avail_recvmsg_count = ++(t->count_avail_recvmsg);
- spin_unlock(&t->receive_credit_lock);
- }
-
- t->recv_credit_target =
- le16_to_cpu(data_transfer->credits_requested);
- atomic_add(le16_to_cpu(data_transfer->credits_granted),
- &t->send_credits);
-
- if (le16_to_cpu(data_transfer->flags) &
- SMB_DIRECT_RESPONSE_REQUESTED)
- queue_work(smb_direct_wq, &t->send_immediate_work);
-
- if (atomic_read(&t->send_credits) > 0)
- wake_up_interruptible(&t->wait_send_credits);
-
- if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count))
- mod_delayed_work(smb_direct_wq,
- &t->post_recv_credits_work, 0);
- break;
- }
- default:
- break;
- }
-}
-
-static int smb_direct_post_recv(struct smb_direct_transport *t,
- struct smb_direct_recvmsg *recvmsg)
-{
- struct ib_recv_wr wr;
- int ret;
-
- recvmsg->sge.addr = ib_dma_map_single(t->cm_id->device,
- recvmsg->packet, t->max_recv_size,
- DMA_FROM_DEVICE);
- ret = ib_dma_mapping_error(t->cm_id->device, recvmsg->sge.addr);
- if (ret)
- return ret;
- recvmsg->sge.length = t->max_recv_size;
- recvmsg->sge.lkey = t->pd->local_dma_lkey;
- recvmsg->cqe.done = recv_done;
-
- wr.wr_cqe = &recvmsg->cqe;
- wr.next = NULL;
- wr.sg_list = &recvmsg->sge;
- wr.num_sge = 1;
-
- ret = ib_post_recv(t->qp, &wr, NULL);
- if (ret) {
- pr_err("Can't post recv: %d\n", ret);
- ib_dma_unmap_single(t->cm_id->device,
- recvmsg->sge.addr, recvmsg->sge.length,
- DMA_FROM_DEVICE);
- smb_direct_disconnect_rdma_connection(t);
- return ret;
- }
- return ret;
-}
-
-static int smb_direct_read(struct ksmbd_transport *t, char *buf,
- unsigned int size, int unused)
-{
- struct smb_direct_recvmsg *recvmsg;
- struct smb_direct_data_transfer *data_transfer;
- int to_copy, to_read, data_read, offset;
- u32 data_length, remaining_data_length, data_offset;
- int rc;
- struct smb_direct_transport *st = smb_trans_direct_transfort(t);
-
-again:
- if (st->status != SMB_DIRECT_CS_CONNECTED) {
- pr_err("disconnected\n");
- return -ENOTCONN;
- }
-
- /*
- * No need to hold the reassembly queue lock all the time as we are
- * the only one reading from the front of the queue. The transport
- * may add more entries to the back of the queue at the same time
- */
- if (st->reassembly_data_length >= size) {
- int queue_length;
- int queue_removed = 0;
-
- /*
- * Need to make sure reassembly_data_length is read before
- * reading reassembly_queue_length and calling
- * get_first_reassembly. This call is lock free
- * as we never read at the end of the queue which are being
- * updated in SOFTIRQ as more data is received
- */
- virt_rmb();
- queue_length = st->reassembly_queue_length;
- data_read = 0;
- to_read = size;
- offset = st->first_entry_offset;
- while (data_read < size) {
- recvmsg = get_first_reassembly(st);
- data_transfer = smb_direct_recvmsg_payload(recvmsg);
- data_length = le32_to_cpu(data_transfer->data_length);
- remaining_data_length =
- le32_to_cpu(data_transfer->remaining_data_length);
- data_offset = le32_to_cpu(data_transfer->data_offset);
-
- /*
- * The upper layer expects RFC1002 length at the
- * beginning of the payload. Return it to indicate
- * the total length of the packet. This minimize the
- * change to upper layer packet processing logic. This
- * will be eventually remove when an intermediate
- * transport layer is added
- */
- if (recvmsg->first_segment && size == 4) {
- unsigned int rfc1002_len =
- data_length + remaining_data_length;
- *((__be32 *)buf) = cpu_to_be32(rfc1002_len);
- data_read = 4;
- recvmsg->first_segment = false;
- ksmbd_debug(RDMA,
- "returning rfc1002 length %d\n",
- rfc1002_len);
- goto read_rfc1002_done;
- }
-
- to_copy = min_t(int, data_length - offset, to_read);
- memcpy(buf + data_read, (char *)data_transfer + data_offset + offset,
- to_copy);
-
- /* move on to the next buffer? */
- if (to_copy == data_length - offset) {
- queue_length--;
- /*
- * No need to lock if we are not at the
- * end of the queue
- */
- if (queue_length) {
- list_del(&recvmsg->list);
- } else {
- spin_lock_irq(&st->reassembly_queue_lock);
- list_del(&recvmsg->list);
- spin_unlock_irq(&st->reassembly_queue_lock);
- }
- queue_removed++;
- put_recvmsg(st, recvmsg);
- offset = 0;
- } else {
- offset += to_copy;
- }
-
- to_read -= to_copy;
- data_read += to_copy;
- }
-
- spin_lock_irq(&st->reassembly_queue_lock);
- st->reassembly_data_length -= data_read;
- st->reassembly_queue_length -= queue_removed;
- spin_unlock_irq(&st->reassembly_queue_lock);
-
- spin_lock(&st->receive_credit_lock);
- st->count_avail_recvmsg += queue_removed;
- if (is_receive_credit_post_required(st->recv_credits, st->count_avail_recvmsg)) {
- spin_unlock(&st->receive_credit_lock);
- mod_delayed_work(smb_direct_wq,
- &st->post_recv_credits_work, 0);
- } else {
- spin_unlock(&st->receive_credit_lock);
- }
-
- st->first_entry_offset = offset;
- ksmbd_debug(RDMA,
- "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n",
- data_read, st->reassembly_data_length,
- st->first_entry_offset);
-read_rfc1002_done:
- return data_read;
- }
-
- ksmbd_debug(RDMA, "wait_event on more data\n");
- rc = wait_event_interruptible(st->wait_reassembly_queue,
- st->reassembly_data_length >= size ||
- st->status != SMB_DIRECT_CS_CONNECTED);
- if (rc)
- return -EINTR;
-
- goto again;
-}
-
-static void smb_direct_post_recv_credits(struct work_struct *work)
-{
- struct smb_direct_transport *t = container_of(work,
- struct smb_direct_transport, post_recv_credits_work.work);
- struct smb_direct_recvmsg *recvmsg;
- int receive_credits, credits = 0;
- int ret;
- int use_free = 1;
-
- spin_lock(&t->receive_credit_lock);
- receive_credits = t->recv_credits;
- spin_unlock(&t->receive_credit_lock);
-
- if (receive_credits < t->recv_credit_target) {
- while (true) {
- if (use_free)
- recvmsg = get_free_recvmsg(t);
- else
- recvmsg = get_empty_recvmsg(t);
- if (!recvmsg) {
- if (use_free) {
- use_free = 0;
- continue;
- } else {
- break;
- }
- }
-
- recvmsg->type = SMB_DIRECT_MSG_DATA_TRANSFER;
- recvmsg->first_segment = false;
-
- ret = smb_direct_post_recv(t, recvmsg);
- if (ret) {
- pr_err("Can't post recv: %d\n", ret);
- put_recvmsg(t, recvmsg);
- break;
- }
- credits++;
- }
- }
-
- spin_lock(&t->receive_credit_lock);
- t->recv_credits += credits;
- t->count_avail_recvmsg -= credits;
- spin_unlock(&t->receive_credit_lock);
-
- spin_lock(&t->lock_new_recv_credits);
- t->new_recv_credits += credits;
- spin_unlock(&t->lock_new_recv_credits);
-
- if (credits)
- queue_work(smb_direct_wq, &t->send_immediate_work);
-}
-
-static void send_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smb_direct_sendmsg *sendmsg, *sibling;
- struct smb_direct_transport *t;
- struct list_head *pos, *prev, *end;
-
- sendmsg = container_of(wc->wr_cqe, struct smb_direct_sendmsg, cqe);
- t = sendmsg->transport;
-
- ksmbd_debug(RDMA, "Send completed. status='%s (%d)', opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
-
- if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
- pr_err("Send error. status='%s (%d)', opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
- smb_direct_disconnect_rdma_connection(t);
- }
-
- if (atomic_dec_and_test(&t->send_pending))
- wake_up(&t->wait_send_pending);
-
- /* iterate and free the list of messages in reverse. the list's head
- * is invalid.
- */
- for (pos = &sendmsg->list, prev = pos->prev, end = sendmsg->list.next;
- prev != end; pos = prev, prev = prev->prev) {
- sibling = container_of(pos, struct smb_direct_sendmsg, list);
- smb_direct_free_sendmsg(t, sibling);
- }
-
- sibling = container_of(pos, struct smb_direct_sendmsg, list);
- smb_direct_free_sendmsg(t, sibling);
-}
-
-static int manage_credits_prior_sending(struct smb_direct_transport *t)
-{
- int new_credits;
-
- spin_lock(&t->lock_new_recv_credits);
- new_credits = t->new_recv_credits;
- t->new_recv_credits = 0;
- spin_unlock(&t->lock_new_recv_credits);
-
- return new_credits;
-}
-
-static int smb_direct_post_send(struct smb_direct_transport *t,
- struct ib_send_wr *wr)
-{
- int ret;
-
- atomic_inc(&t->send_pending);
- ret = ib_post_send(t->qp, wr, NULL);
- if (ret) {
- pr_err("failed to post send: %d\n", ret);
- if (atomic_dec_and_test(&t->send_pending))
- wake_up(&t->wait_send_pending);
- smb_direct_disconnect_rdma_connection(t);
- }
- return ret;
-}
-
-static void smb_direct_send_ctx_init(struct smb_direct_transport *t,
- struct smb_direct_send_ctx *send_ctx,
- bool need_invalidate_rkey,
- unsigned int remote_key)
-{
- INIT_LIST_HEAD(&send_ctx->msg_list);
- send_ctx->wr_cnt = 0;
- send_ctx->need_invalidate_rkey = need_invalidate_rkey;
- send_ctx->remote_key = remote_key;
-}
-
-static int smb_direct_flush_send_list(struct smb_direct_transport *t,
- struct smb_direct_send_ctx *send_ctx,
- bool is_last)
-{
- struct smb_direct_sendmsg *first, *last;
- int ret;
-
- if (list_empty(&send_ctx->msg_list))
- return 0;
-
- first = list_first_entry(&send_ctx->msg_list,
- struct smb_direct_sendmsg,
- list);
- last = list_last_entry(&send_ctx->msg_list,
- struct smb_direct_sendmsg,
- list);
-
- last->wr.send_flags = IB_SEND_SIGNALED;
- last->wr.wr_cqe = &last->cqe;
- if (is_last && send_ctx->need_invalidate_rkey) {
- last->wr.opcode = IB_WR_SEND_WITH_INV;
- last->wr.ex.invalidate_rkey = send_ctx->remote_key;
- }
-
- ret = smb_direct_post_send(t, &first->wr);
- if (!ret) {
- smb_direct_send_ctx_init(t, send_ctx,
- send_ctx->need_invalidate_rkey,
- send_ctx->remote_key);
- } else {
- atomic_add(send_ctx->wr_cnt, &t->send_credits);
- wake_up(&t->wait_send_credits);
- list_for_each_entry_safe(first, last, &send_ctx->msg_list,
- list) {
- smb_direct_free_sendmsg(t, first);
- }
- }
- return ret;
-}
-
-static int wait_for_credits(struct smb_direct_transport *t,
- wait_queue_head_t *waitq, atomic_t *total_credits,
- int needed)
-{
- int ret;
-
- do {
- if (atomic_sub_return(needed, total_credits) >= 0)
- return 0;
-
- atomic_add(needed, total_credits);
- ret = wait_event_interruptible(*waitq,
- atomic_read(total_credits) >= needed ||
- t->status != SMB_DIRECT_CS_CONNECTED);
-
- if (t->status != SMB_DIRECT_CS_CONNECTED)
- return -ENOTCONN;
- else if (ret < 0)
- return ret;
- } while (true);
-}
-
-static int wait_for_send_credits(struct smb_direct_transport *t,
- struct smb_direct_send_ctx *send_ctx)
-{
- int ret;
-
- if (send_ctx &&
- (send_ctx->wr_cnt >= 16 || atomic_read(&t->send_credits) <= 1)) {
- ret = smb_direct_flush_send_list(t, send_ctx, false);
- if (ret)
- return ret;
- }
-
- return wait_for_credits(t, &t->wait_send_credits, &t->send_credits, 1);
-}
-
-static int wait_for_rw_credits(struct smb_direct_transport *t, int credits)
-{
- return wait_for_credits(t, &t->wait_rw_credits, &t->rw_credits, credits);
-}
-
-static int calc_rw_credits(struct smb_direct_transport *t,
- char *buf, unsigned int len)
-{
- return DIV_ROUND_UP(get_buf_page_count(buf, len),
- t->pages_per_rw_credit);
-}
-
-static int smb_direct_create_header(struct smb_direct_transport *t,
- int size, int remaining_data_length,
- struct smb_direct_sendmsg **sendmsg_out)
-{
- struct smb_direct_sendmsg *sendmsg;
- struct smb_direct_data_transfer *packet;
- int header_length;
- int ret;
-
- sendmsg = smb_direct_alloc_sendmsg(t);
- if (IS_ERR(sendmsg))
- return PTR_ERR(sendmsg);
-
- /* Fill in the packet header */
- packet = (struct smb_direct_data_transfer *)sendmsg->packet;
- packet->credits_requested = cpu_to_le16(t->send_credit_target);
- packet->credits_granted = cpu_to_le16(manage_credits_prior_sending(t));
-
- packet->flags = 0;
- packet->reserved = 0;
- if (!size)
- packet->data_offset = 0;
- else
- packet->data_offset = cpu_to_le32(24);
- packet->data_length = cpu_to_le32(size);
- packet->remaining_data_length = cpu_to_le32(remaining_data_length);
- packet->padding = 0;
-
- ksmbd_debug(RDMA,
- "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n",
- le16_to_cpu(packet->credits_requested),
- le16_to_cpu(packet->credits_granted),
- le32_to_cpu(packet->data_offset),
- le32_to_cpu(packet->data_length),
- le32_to_cpu(packet->remaining_data_length));
-
- /* Map the packet to DMA */
- header_length = sizeof(struct smb_direct_data_transfer);
- /* If this is a packet without payload, don't send padding */
- if (!size)
- header_length =
- offsetof(struct smb_direct_data_transfer, padding);
-
- sendmsg->sge[0].addr = ib_dma_map_single(t->cm_id->device,
- (void *)packet,
- header_length,
- DMA_TO_DEVICE);
- ret = ib_dma_mapping_error(t->cm_id->device, sendmsg->sge[0].addr);
- if (ret) {
- smb_direct_free_sendmsg(t, sendmsg);
- return ret;
- }
-
- sendmsg->num_sge = 1;
- sendmsg->sge[0].length = header_length;
- sendmsg->sge[0].lkey = t->pd->local_dma_lkey;
-
- *sendmsg_out = sendmsg;
- return 0;
-}
-
-static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nentries)
-{
- bool high = is_vmalloc_addr(buf);
- struct page *page;
- int offset, len;
- int i = 0;
-
- if (size <= 0 || nentries < get_buf_page_count(buf, size))
- return -EINVAL;
-
- offset = offset_in_page(buf);
- buf -= offset;
- while (size > 0) {
- len = min_t(int, PAGE_SIZE - offset, size);
- if (high)
- page = vmalloc_to_page(buf);
- else
- page = kmap_to_page(buf);
-
- if (!sg_list)
- return -EINVAL;
- sg_set_page(sg_list, page, len, offset);
- sg_list = sg_next(sg_list);
-
- buf += PAGE_SIZE;
- size -= len;
- offset = 0;
- i++;
- }
- return i;
-}
-
-static int get_mapped_sg_list(struct ib_device *device, void *buf, int size,
- struct scatterlist *sg_list, int nentries,
- enum dma_data_direction dir)
-{
- int npages;
-
- npages = get_sg_list(buf, size, sg_list, nentries);
- if (npages < 0)
- return -EINVAL;
- return ib_dma_map_sg(device, sg_list, npages, dir);
-}
-
-static int post_sendmsg(struct smb_direct_transport *t,
- struct smb_direct_send_ctx *send_ctx,
- struct smb_direct_sendmsg *msg)
-{
- int i;
-
- for (i = 0; i < msg->num_sge; i++)
- ib_dma_sync_single_for_device(t->cm_id->device,
- msg->sge[i].addr, msg->sge[i].length,
- DMA_TO_DEVICE);
-
- msg->cqe.done = send_done;
- msg->wr.opcode = IB_WR_SEND;
- msg->wr.sg_list = &msg->sge[0];
- msg->wr.num_sge = msg->num_sge;
- msg->wr.next = NULL;
-
- if (send_ctx) {
- msg->wr.wr_cqe = NULL;
- msg->wr.send_flags = 0;
- if (!list_empty(&send_ctx->msg_list)) {
- struct smb_direct_sendmsg *last;
-
- last = list_last_entry(&send_ctx->msg_list,
- struct smb_direct_sendmsg,
- list);
- last->wr.next = &msg->wr;
- }
- list_add_tail(&msg->list, &send_ctx->msg_list);
- send_ctx->wr_cnt++;
- return 0;
- }
-
- msg->wr.wr_cqe = &msg->cqe;
- msg->wr.send_flags = IB_SEND_SIGNALED;
- return smb_direct_post_send(t, &msg->wr);
-}
-
-static int smb_direct_post_send_data(struct smb_direct_transport *t,
- struct smb_direct_send_ctx *send_ctx,
- struct kvec *iov, int niov,
- int remaining_data_length)
-{
- int i, j, ret;
- struct smb_direct_sendmsg *msg;
- int data_length;
- struct scatterlist sg[SMB_DIRECT_MAX_SEND_SGES - 1];
-
- ret = wait_for_send_credits(t, send_ctx);
- if (ret)
- return ret;
-
- data_length = 0;
- for (i = 0; i < niov; i++)
- data_length += iov[i].iov_len;
-
- ret = smb_direct_create_header(t, data_length, remaining_data_length,
- &msg);
- if (ret) {
- atomic_inc(&t->send_credits);
- return ret;
- }
-
- for (i = 0; i < niov; i++) {
- struct ib_sge *sge;
- int sg_cnt;
-
- sg_init_table(sg, SMB_DIRECT_MAX_SEND_SGES - 1);
- sg_cnt = get_mapped_sg_list(t->cm_id->device,
- iov[i].iov_base, iov[i].iov_len,
- sg, SMB_DIRECT_MAX_SEND_SGES - 1,
- DMA_TO_DEVICE);
- if (sg_cnt <= 0) {
- pr_err("failed to map buffer\n");
- ret = -ENOMEM;
- goto err;
- } else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES) {
- pr_err("buffer not fitted into sges\n");
- ret = -E2BIG;
- ib_dma_unmap_sg(t->cm_id->device, sg, sg_cnt,
- DMA_TO_DEVICE);
- goto err;
- }
-
- for (j = 0; j < sg_cnt; j++) {
- sge = &msg->sge[msg->num_sge];
- sge->addr = sg_dma_address(&sg[j]);
- sge->length = sg_dma_len(&sg[j]);
- sge->lkey = t->pd->local_dma_lkey;
- msg->num_sge++;
- }
- }
-
- ret = post_sendmsg(t, send_ctx, msg);
- if (ret)
- goto err;
- return 0;
-err:
- smb_direct_free_sendmsg(t, msg);
- atomic_inc(&t->send_credits);
- return ret;
-}
-
-static int smb_direct_writev(struct ksmbd_transport *t,
- struct kvec *iov, int niovs, int buflen,
- bool need_invalidate, unsigned int remote_key)
-{
- struct smb_direct_transport *st = smb_trans_direct_transfort(t);
- int remaining_data_length;
- int start, i, j;
- int max_iov_size = st->max_send_size -
- sizeof(struct smb_direct_data_transfer);
- int ret;
- struct kvec vec;
- struct smb_direct_send_ctx send_ctx;
-
- if (st->status != SMB_DIRECT_CS_CONNECTED)
- return -ENOTCONN;
-
- //FIXME: skip RFC1002 header..
- buflen -= 4;
- iov[0].iov_base += 4;
- iov[0].iov_len -= 4;
-
- remaining_data_length = buflen;
- ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen);
-
- smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key);
- start = i = 0;
- buflen = 0;
- while (true) {
- buflen += iov[i].iov_len;
- if (buflen > max_iov_size) {
- if (i > start) {
- remaining_data_length -=
- (buflen - iov[i].iov_len);
- ret = smb_direct_post_send_data(st, &send_ctx,
- &iov[start], i - start,
- remaining_data_length);
- if (ret)
- goto done;
- } else {
- /* iov[start] is too big, break it */
- int nvec = (buflen + max_iov_size - 1) /
- max_iov_size;
-
- for (j = 0; j < nvec; j++) {
- vec.iov_base =
- (char *)iov[start].iov_base +
- j * max_iov_size;
- vec.iov_len =
- min_t(int, max_iov_size,
- buflen - max_iov_size * j);
- remaining_data_length -= vec.iov_len;
- ret = smb_direct_post_send_data(st, &send_ctx, &vec, 1,
- remaining_data_length);
- if (ret)
- goto done;
- }
- i++;
- if (i == niovs)
- break;
- }
- start = i;
- buflen = 0;
- } else {
- i++;
- if (i == niovs) {
- /* send out all remaining vecs */
- remaining_data_length -= buflen;
- ret = smb_direct_post_send_data(st, &send_ctx,
- &iov[start], i - start,
- remaining_data_length);
- if (ret)
- goto done;
- break;
- }
- }
- }
-
-done:
- ret = smb_direct_flush_send_list(st, &send_ctx, true);
-
- /*
- * As an optimization, we don't wait for individual I/O to finish
- * before sending the next one.
- * Send them all and wait for pending send count to get to 0
- * that means all the I/Os have been out and we are good to return
- */
-
- wait_event(st->wait_send_pending,
- atomic_read(&st->send_pending) == 0);
- return ret;
-}
-
-static void smb_direct_free_rdma_rw_msg(struct smb_direct_transport *t,
- struct smb_direct_rdma_rw_msg *msg,
- enum dma_data_direction dir)
-{
- rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
- msg->sgt.sgl, msg->sgt.nents, dir);
- sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
- kfree(msg);
-}
-
-static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
- enum dma_data_direction dir)
-{
- struct smb_direct_rdma_rw_msg *msg = container_of(wc->wr_cqe,
- struct smb_direct_rdma_rw_msg, cqe);
- struct smb_direct_transport *t = msg->t;
-
- if (wc->status != IB_WC_SUCCESS) {
- msg->status = -EIO;
- pr_err("read/write error. opcode = %d, status = %s(%d)\n",
- wc->opcode, ib_wc_status_msg(wc->status), wc->status);
- if (wc->status != IB_WC_WR_FLUSH_ERR)
- smb_direct_disconnect_rdma_connection(t);
- }
-
- complete(msg->completion);
-}
-
-static void read_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- read_write_done(cq, wc, DMA_FROM_DEVICE);
-}
-
-static void write_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- read_write_done(cq, wc, DMA_TO_DEVICE);
-}
-
-static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
- void *buf, int buf_len,
- struct smb2_buffer_desc_v1 *desc,
- unsigned int desc_len,
- bool is_read)
-{
- struct smb_direct_rdma_rw_msg *msg, *next_msg;
- int i, ret;
- DECLARE_COMPLETION_ONSTACK(completion);
- struct ib_send_wr *first_wr;
- LIST_HEAD(msg_list);
- char *desc_buf;
- int credits_needed;
- unsigned int desc_buf_len;
- size_t total_length = 0;
-
- if (t->status != SMB_DIRECT_CS_CONNECTED)
- return -ENOTCONN;
-
- /* calculate needed credits */
- credits_needed = 0;
- desc_buf = buf;
- for (i = 0; i < desc_len / sizeof(*desc); i++) {
- desc_buf_len = le32_to_cpu(desc[i].length);
-
- credits_needed += calc_rw_credits(t, desc_buf, desc_buf_len);
- desc_buf += desc_buf_len;
- total_length += desc_buf_len;
- if (desc_buf_len == 0 || total_length > buf_len ||
- total_length > t->max_rdma_rw_size)
- return -EINVAL;
- }
-
- ksmbd_debug(RDMA, "RDMA %s, len %#x, needed credits %#x\n",
- is_read ? "read" : "write", buf_len, credits_needed);
-
- ret = wait_for_rw_credits(t, credits_needed);
- if (ret < 0)
- return ret;
-
- /* build rdma_rw_ctx for each descriptor */
- desc_buf = buf;
- for (i = 0; i < desc_len / sizeof(*desc); i++) {
- msg = kzalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
- sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
- if (!msg) {
- ret = -ENOMEM;
- goto out;
- }
-
- desc_buf_len = le32_to_cpu(desc[i].length);
-
- msg->t = t;
- msg->cqe.done = is_read ? read_done : write_done;
- msg->completion = &completion;
-
- msg->sgt.sgl = &msg->sg_list[0];
- ret = sg_alloc_table_chained(&msg->sgt,
- get_buf_page_count(desc_buf, desc_buf_len),
- msg->sg_list, SG_CHUNK_SIZE);
- if (ret) {
- kfree(msg);
- ret = -ENOMEM;
- goto out;
- }
-
- ret = get_sg_list(desc_buf, desc_buf_len,
- msg->sgt.sgl, msg->sgt.orig_nents);
- if (ret < 0) {
- sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
- kfree(msg);
- goto out;
- }
-
- ret = rdma_rw_ctx_init(&msg->rw_ctx, t->qp, t->qp->port,
- msg->sgt.sgl,
- get_buf_page_count(desc_buf, desc_buf_len),
- 0,
- le64_to_cpu(desc[i].offset),
- le32_to_cpu(desc[i].token),
- is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
- if (ret < 0) {
- pr_err("failed to init rdma_rw_ctx: %d\n", ret);
- sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
- kfree(msg);
- goto out;
- }
-
- list_add_tail(&msg->list, &msg_list);
- desc_buf += desc_buf_len;
- }
-
- /* concatenate work requests of rdma_rw_ctxs */
- first_wr = NULL;
- list_for_each_entry_reverse(msg, &msg_list, list) {
- first_wr = rdma_rw_ctx_wrs(&msg->rw_ctx, t->qp, t->qp->port,
- &msg->cqe, first_wr);
- }
-
- ret = ib_post_send(t->qp, first_wr, NULL);
- if (ret) {
- pr_err("failed to post send wr for RDMA R/W: %d\n", ret);
- goto out;
- }
-
- msg = list_last_entry(&msg_list, struct smb_direct_rdma_rw_msg, list);
- wait_for_completion(&completion);
- ret = msg->status;
-out:
- list_for_each_entry_safe(msg, next_msg, &msg_list, list) {
- list_del(&msg->list);
- smb_direct_free_rdma_rw_msg(t, msg,
- is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
- }
- atomic_add(credits_needed, &t->rw_credits);
- wake_up(&t->wait_rw_credits);
- return ret;
-}
-
-static int smb_direct_rdma_write(struct ksmbd_transport *t,
- void *buf, unsigned int buflen,
- struct smb2_buffer_desc_v1 *desc,
- unsigned int desc_len)
-{
- return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen,
- desc, desc_len, false);
-}
-
-static int smb_direct_rdma_read(struct ksmbd_transport *t,
- void *buf, unsigned int buflen,
- struct smb2_buffer_desc_v1 *desc,
- unsigned int desc_len)
-{
- return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen,
- desc, desc_len, true);
-}
-
-static void smb_direct_disconnect(struct ksmbd_transport *t)
-{
- struct smb_direct_transport *st = smb_trans_direct_transfort(t);
-
- ksmbd_debug(RDMA, "Disconnecting cm_id=%p\n", st->cm_id);
-
- smb_direct_disconnect_rdma_work(&st->disconnect_work);
- wait_event_interruptible(st->wait_status,
- st->status == SMB_DIRECT_CS_DISCONNECTED);
- free_transport(st);
-}
-
-static void smb_direct_shutdown(struct ksmbd_transport *t)
-{
- struct smb_direct_transport *st = smb_trans_direct_transfort(t);
-
- ksmbd_debug(RDMA, "smb-direct shutdown cm_id=%p\n", st->cm_id);
-
- smb_direct_disconnect_rdma_work(&st->disconnect_work);
-}
-
-static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
- struct rdma_cm_event *event)
-{
- struct smb_direct_transport *t = cm_id->context;
-
- ksmbd_debug(RDMA, "RDMA CM event. cm_id=%p event=%s (%d)\n",
- cm_id, rdma_event_msg(event->event), event->event);
-
- switch (event->event) {
- case RDMA_CM_EVENT_ESTABLISHED: {
- t->status = SMB_DIRECT_CS_CONNECTED;
- wake_up_interruptible(&t->wait_status);
- break;
- }
- case RDMA_CM_EVENT_DEVICE_REMOVAL:
- case RDMA_CM_EVENT_DISCONNECTED: {
- ib_drain_qp(t->qp);
-
- t->status = SMB_DIRECT_CS_DISCONNECTED;
- wake_up_interruptible(&t->wait_status);
- wake_up_interruptible(&t->wait_reassembly_queue);
- wake_up(&t->wait_send_credits);
- break;
- }
- case RDMA_CM_EVENT_CONNECT_ERROR: {
- t->status = SMB_DIRECT_CS_DISCONNECTED;
- wake_up_interruptible(&t->wait_status);
- break;
- }
- default:
- pr_err("Unexpected RDMA CM event. cm_id=%p, event=%s (%d)\n",
- cm_id, rdma_event_msg(event->event),
- event->event);
- break;
- }
- return 0;
-}
-
-static void smb_direct_qpair_handler(struct ib_event *event, void *context)
-{
- struct smb_direct_transport *t = context;
-
- ksmbd_debug(RDMA, "Received QP event. cm_id=%p, event=%s (%d)\n",
- t->cm_id, ib_event_msg(event->event), event->event);
-
- switch (event->event) {
- case IB_EVENT_CQ_ERR:
- case IB_EVENT_QP_FATAL:
- smb_direct_disconnect_rdma_connection(t);
- break;
- default:
- break;
- }
-}
-
-static int smb_direct_send_negotiate_response(struct smb_direct_transport *t,
- int failed)
-{
- struct smb_direct_sendmsg *sendmsg;
- struct smb_direct_negotiate_resp *resp;
- int ret;
-
- sendmsg = smb_direct_alloc_sendmsg(t);
- if (IS_ERR(sendmsg))
- return -ENOMEM;
-
- resp = (struct smb_direct_negotiate_resp *)sendmsg->packet;
- if (failed) {
- memset(resp, 0, sizeof(*resp));
- resp->min_version = cpu_to_le16(0x0100);
- resp->max_version = cpu_to_le16(0x0100);
- resp->status = STATUS_NOT_SUPPORTED;
- } else {
- resp->status = STATUS_SUCCESS;
- resp->min_version = SMB_DIRECT_VERSION_LE;
- resp->max_version = SMB_DIRECT_VERSION_LE;
- resp->negotiated_version = SMB_DIRECT_VERSION_LE;
- resp->reserved = 0;
- resp->credits_requested =
- cpu_to_le16(t->send_credit_target);
- resp->credits_granted = cpu_to_le16(manage_credits_prior_sending(t));
- resp->max_readwrite_size = cpu_to_le32(t->max_rdma_rw_size);
- resp->preferred_send_size = cpu_to_le32(t->max_send_size);
- resp->max_receive_size = cpu_to_le32(t->max_recv_size);
- resp->max_fragmented_size =
- cpu_to_le32(t->max_fragmented_recv_size);
- }
-
- sendmsg->sge[0].addr = ib_dma_map_single(t->cm_id->device,
- (void *)resp, sizeof(*resp),
- DMA_TO_DEVICE);
- ret = ib_dma_mapping_error(t->cm_id->device, sendmsg->sge[0].addr);
- if (ret) {
- smb_direct_free_sendmsg(t, sendmsg);
- return ret;
- }
-
- sendmsg->num_sge = 1;
- sendmsg->sge[0].length = sizeof(*resp);
- sendmsg->sge[0].lkey = t->pd->local_dma_lkey;
-
- ret = post_sendmsg(t, NULL, sendmsg);
- if (ret) {
- smb_direct_free_sendmsg(t, sendmsg);
- return ret;
- }
-
- wait_event(t->wait_send_pending,
- atomic_read(&t->send_pending) == 0);
- return 0;
-}
-
-static int smb_direct_accept_client(struct smb_direct_transport *t)
-{
- struct rdma_conn_param conn_param;
- struct ib_port_immutable port_immutable;
- u32 ird_ord_hdr[2];
- int ret;
-
- memset(&conn_param, 0, sizeof(conn_param));
- conn_param.initiator_depth = min_t(u8, t->cm_id->device->attrs.max_qp_rd_atom,
- SMB_DIRECT_CM_INITIATOR_DEPTH);
- conn_param.responder_resources = 0;
-
- t->cm_id->device->ops.get_port_immutable(t->cm_id->device,
- t->cm_id->port_num,
- &port_immutable);
- if (port_immutable.core_cap_flags & RDMA_CORE_PORT_IWARP) {
- ird_ord_hdr[0] = conn_param.responder_resources;
- ird_ord_hdr[1] = 1;
- conn_param.private_data = ird_ord_hdr;
- conn_param.private_data_len = sizeof(ird_ord_hdr);
- } else {
- conn_param.private_data = NULL;
- conn_param.private_data_len = 0;
- }
- conn_param.retry_count = SMB_DIRECT_CM_RETRY;
- conn_param.rnr_retry_count = SMB_DIRECT_CM_RNR_RETRY;
- conn_param.flow_control = 0;
-
- ret = rdma_accept(t->cm_id, &conn_param);
- if (ret) {
- pr_err("error at rdma_accept: %d\n", ret);
- return ret;
- }
- return 0;
-}
-
-static int smb_direct_prepare_negotiation(struct smb_direct_transport *t)
-{
- int ret;
- struct smb_direct_recvmsg *recvmsg;
-
- recvmsg = get_free_recvmsg(t);
- if (!recvmsg)
- return -ENOMEM;
- recvmsg->type = SMB_DIRECT_MSG_NEGOTIATE_REQ;
-
- ret = smb_direct_post_recv(t, recvmsg);
- if (ret) {
- pr_err("Can't post recv: %d\n", ret);
- goto out_err;
- }
-
- t->negotiation_requested = false;
- ret = smb_direct_accept_client(t);
- if (ret) {
- pr_err("Can't accept client\n");
- goto out_err;
- }
-
- smb_direct_post_recv_credits(&t->post_recv_credits_work.work);
- return 0;
-out_err:
- put_recvmsg(t, recvmsg);
- return ret;
-}
-
-static unsigned int smb_direct_get_max_fr_pages(struct smb_direct_transport *t)
-{
- return min_t(unsigned int,
- t->cm_id->device->attrs.max_fast_reg_page_list_len,
- 256);
-}
-
-static int smb_direct_init_params(struct smb_direct_transport *t,
- struct ib_qp_cap *cap)
-{
- struct ib_device *device = t->cm_id->device;
- int max_send_sges, max_rw_wrs, max_send_wrs;
- unsigned int max_sge_per_wr, wrs_per_credit;
-
- /* need 3 more sge. because a SMB_DIRECT header, SMB2 header,
- * SMB2 response could be mapped.
- */
- t->max_send_size = smb_direct_max_send_size;
- max_send_sges = DIV_ROUND_UP(t->max_send_size, PAGE_SIZE) + 3;
- if (max_send_sges > SMB_DIRECT_MAX_SEND_SGES) {
- pr_err("max_send_size %d is too large\n", t->max_send_size);
- return -EINVAL;
- }
-
- /* Calculate the number of work requests for RDMA R/W.
- * The maximum number of pages which can be registered
- * with one Memory region can be transferred with one
- * R/W credit. And at least 4 work requests for each credit
- * are needed for MR registration, RDMA R/W, local & remote
- * MR invalidation.
- */
- t->max_rdma_rw_size = smb_direct_max_read_write_size;
- t->pages_per_rw_credit = smb_direct_get_max_fr_pages(t);
- t->max_rw_credits = DIV_ROUND_UP(t->max_rdma_rw_size,
- (t->pages_per_rw_credit - 1) *
- PAGE_SIZE);
-
- max_sge_per_wr = min_t(unsigned int, device->attrs.max_send_sge,
- device->attrs.max_sge_rd);
- max_sge_per_wr = max_t(unsigned int, max_sge_per_wr,
- max_send_sges);
- wrs_per_credit = max_t(unsigned int, 4,
- DIV_ROUND_UP(t->pages_per_rw_credit,
- max_sge_per_wr) + 1);
- max_rw_wrs = t->max_rw_credits * wrs_per_credit;
-
- max_send_wrs = smb_direct_send_credit_target + max_rw_wrs;
- if (max_send_wrs > device->attrs.max_cqe ||
- max_send_wrs > device->attrs.max_qp_wr) {
- pr_err("consider lowering send_credit_target = %d\n",
- smb_direct_send_credit_target);
- pr_err("Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
- device->attrs.max_cqe, device->attrs.max_qp_wr);
- return -EINVAL;
- }
-
- if (smb_direct_receive_credit_max > device->attrs.max_cqe ||
- smb_direct_receive_credit_max > device->attrs.max_qp_wr) {
- pr_err("consider lowering receive_credit_max = %d\n",
- smb_direct_receive_credit_max);
- pr_err("Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n",
- device->attrs.max_cqe, device->attrs.max_qp_wr);
- return -EINVAL;
- }
-
- if (device->attrs.max_recv_sge < SMB_DIRECT_MAX_RECV_SGES) {
- pr_err("warning: device max_recv_sge = %d too small\n",
- device->attrs.max_recv_sge);
- return -EINVAL;
- }
-
- t->recv_credits = 0;
- t->count_avail_recvmsg = 0;
-
- t->recv_credit_max = smb_direct_receive_credit_max;
- t->recv_credit_target = 10;
- t->new_recv_credits = 0;
-
- t->send_credit_target = smb_direct_send_credit_target;
- atomic_set(&t->send_credits, 0);
- atomic_set(&t->rw_credits, t->max_rw_credits);
-
- t->max_send_size = smb_direct_max_send_size;
- t->max_recv_size = smb_direct_max_receive_size;
- t->max_fragmented_recv_size = smb_direct_max_fragmented_recv_size;
-
- cap->max_send_wr = max_send_wrs;
- cap->max_recv_wr = t->recv_credit_max;
- cap->max_send_sge = max_sge_per_wr;
- cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES;
- cap->max_inline_data = 0;
- cap->max_rdma_ctxs = t->max_rw_credits;
- return 0;
-}
-
-static void smb_direct_destroy_pools(struct smb_direct_transport *t)
-{
- struct smb_direct_recvmsg *recvmsg;
-
- while ((recvmsg = get_free_recvmsg(t)))
- mempool_free(recvmsg, t->recvmsg_mempool);
- while ((recvmsg = get_empty_recvmsg(t)))
- mempool_free(recvmsg, t->recvmsg_mempool);
-
- mempool_destroy(t->recvmsg_mempool);
- t->recvmsg_mempool = NULL;
-
- kmem_cache_destroy(t->recvmsg_cache);
- t->recvmsg_cache = NULL;
-
- mempool_destroy(t->sendmsg_mempool);
- t->sendmsg_mempool = NULL;
-
- kmem_cache_destroy(t->sendmsg_cache);
- t->sendmsg_cache = NULL;
-}
-
-static int smb_direct_create_pools(struct smb_direct_transport *t)
-{
- char name[80];
- int i;
- struct smb_direct_recvmsg *recvmsg;
-
- snprintf(name, sizeof(name), "smb_direct_rqst_pool_%p", t);
- t->sendmsg_cache = kmem_cache_create(name,
- sizeof(struct smb_direct_sendmsg) +
- sizeof(struct smb_direct_negotiate_resp),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!t->sendmsg_cache)
- return -ENOMEM;
-
- t->sendmsg_mempool = mempool_create(t->send_credit_target,
- mempool_alloc_slab, mempool_free_slab,
- t->sendmsg_cache);
- if (!t->sendmsg_mempool)
- goto err;
-
- snprintf(name, sizeof(name), "smb_direct_resp_%p", t);
- t->recvmsg_cache = kmem_cache_create(name,
- sizeof(struct smb_direct_recvmsg) +
- t->max_recv_size,
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!t->recvmsg_cache)
- goto err;
-
- t->recvmsg_mempool =
- mempool_create(t->recv_credit_max, mempool_alloc_slab,
- mempool_free_slab, t->recvmsg_cache);
- if (!t->recvmsg_mempool)
- goto err;
-
- INIT_LIST_HEAD(&t->recvmsg_queue);
-
- for (i = 0; i < t->recv_credit_max; i++) {
- recvmsg = mempool_alloc(t->recvmsg_mempool, GFP_KERNEL);
- if (!recvmsg)
- goto err;
- recvmsg->transport = t;
- list_add(&recvmsg->list, &t->recvmsg_queue);
- }
- t->count_avail_recvmsg = t->recv_credit_max;
-
- return 0;
-err:
- smb_direct_destroy_pools(t);
- return -ENOMEM;
-}
-
-static int smb_direct_create_qpair(struct smb_direct_transport *t,
- struct ib_qp_cap *cap)
-{
- int ret;
- struct ib_qp_init_attr qp_attr;
- int pages_per_rw;
-
- t->pd = ib_alloc_pd(t->cm_id->device, 0);
- if (IS_ERR(t->pd)) {
- pr_err("Can't create RDMA PD\n");
- ret = PTR_ERR(t->pd);
- t->pd = NULL;
- return ret;
- }
-
- t->send_cq = ib_alloc_cq(t->cm_id->device, t,
- smb_direct_send_credit_target + cap->max_rdma_ctxs,
- 0, IB_POLL_WORKQUEUE);
- if (IS_ERR(t->send_cq)) {
- pr_err("Can't create RDMA send CQ\n");
- ret = PTR_ERR(t->send_cq);
- t->send_cq = NULL;
- goto err;
- }
-
- t->recv_cq = ib_alloc_cq(t->cm_id->device, t,
- t->recv_credit_max, 0, IB_POLL_WORKQUEUE);
- if (IS_ERR(t->recv_cq)) {
- pr_err("Can't create RDMA recv CQ\n");
- ret = PTR_ERR(t->recv_cq);
- t->recv_cq = NULL;
- goto err;
- }
-
- memset(&qp_attr, 0, sizeof(qp_attr));
- qp_attr.event_handler = smb_direct_qpair_handler;
- qp_attr.qp_context = t;
- qp_attr.cap = *cap;
- qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
- qp_attr.qp_type = IB_QPT_RC;
- qp_attr.send_cq = t->send_cq;
- qp_attr.recv_cq = t->recv_cq;
- qp_attr.port_num = ~0;
-
- ret = rdma_create_qp(t->cm_id, t->pd, &qp_attr);
- if (ret) {
- pr_err("Can't create RDMA QP: %d\n", ret);
- goto err;
- }
-
- t->qp = t->cm_id->qp;
- t->cm_id->event_handler = smb_direct_cm_handler;
-
- pages_per_rw = DIV_ROUND_UP(t->max_rdma_rw_size, PAGE_SIZE) + 1;
- if (pages_per_rw > t->cm_id->device->attrs.max_sgl_rd) {
- ret = ib_mr_pool_init(t->qp, &t->qp->rdma_mrs,
- t->max_rw_credits, IB_MR_TYPE_MEM_REG,
- t->pages_per_rw_credit, 0);
- if (ret) {
- pr_err("failed to init mr pool count %d pages %d\n",
- t->max_rw_credits, t->pages_per_rw_credit);
- goto err;
- }
- }
-
- return 0;
-err:
- if (t->qp) {
- ib_destroy_qp(t->qp);
- t->qp = NULL;
- }
- if (t->recv_cq) {
- ib_destroy_cq(t->recv_cq);
- t->recv_cq = NULL;
- }
- if (t->send_cq) {
- ib_destroy_cq(t->send_cq);
- t->send_cq = NULL;
- }
- if (t->pd) {
- ib_dealloc_pd(t->pd);
- t->pd = NULL;
- }
- return ret;
-}
-
-static int smb_direct_prepare(struct ksmbd_transport *t)
-{
- struct smb_direct_transport *st = smb_trans_direct_transfort(t);
- struct smb_direct_recvmsg *recvmsg;
- struct smb_direct_negotiate_req *req;
- int ret;
-
- ksmbd_debug(RDMA, "Waiting for SMB_DIRECT negotiate request\n");
- ret = wait_event_interruptible_timeout(st->wait_status,
- st->negotiation_requested ||
- st->status == SMB_DIRECT_CS_DISCONNECTED,
- SMB_DIRECT_NEGOTIATE_TIMEOUT * HZ);
- if (ret <= 0 || st->status == SMB_DIRECT_CS_DISCONNECTED)
- return ret < 0 ? ret : -ETIMEDOUT;
-
- recvmsg = get_first_reassembly(st);
- if (!recvmsg)
- return -ECONNABORTED;
-
- ret = smb_direct_check_recvmsg(recvmsg);
- if (ret == -ECONNABORTED)
- goto out;
-
- req = (struct smb_direct_negotiate_req *)recvmsg->packet;
- st->max_recv_size = min_t(int, st->max_recv_size,
- le32_to_cpu(req->preferred_send_size));
- st->max_send_size = min_t(int, st->max_send_size,
- le32_to_cpu(req->max_receive_size));
- st->max_fragmented_send_size =
- le32_to_cpu(req->max_fragmented_size);
- st->max_fragmented_recv_size =
- (st->recv_credit_max * st->max_recv_size) / 2;
-
- ret = smb_direct_send_negotiate_response(st, ret);
-out:
- spin_lock_irq(&st->reassembly_queue_lock);
- st->reassembly_queue_length--;
- list_del(&recvmsg->list);
- spin_unlock_irq(&st->reassembly_queue_lock);
- put_recvmsg(st, recvmsg);
-
- return ret;
-}
-
-static int smb_direct_connect(struct smb_direct_transport *st)
-{
- int ret;
- struct ib_qp_cap qp_cap;
-
- ret = smb_direct_init_params(st, &qp_cap);
- if (ret) {
- pr_err("Can't configure RDMA parameters\n");
- return ret;
- }
-
- ret = smb_direct_create_pools(st);
- if (ret) {
- pr_err("Can't init RDMA pool: %d\n", ret);
- return ret;
- }
-
- ret = smb_direct_create_qpair(st, &qp_cap);
- if (ret) {
- pr_err("Can't accept RDMA client: %d\n", ret);
- return ret;
- }
-
- ret = smb_direct_prepare_negotiation(st);
- if (ret) {
- pr_err("Can't negotiate: %d\n", ret);
- return ret;
- }
- return 0;
-}
-
-static bool rdma_frwr_is_supported(struct ib_device_attr *attrs)
-{
- if (!(attrs->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS))
- return false;
- if (attrs->max_fast_reg_page_list_len == 0)
- return false;
- return true;
-}
-
-static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
-{
- struct smb_direct_transport *t;
- int ret;
-
- if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) {
- ksmbd_debug(RDMA,
- "Fast Registration Work Requests is not supported. device capabilities=%llx\n",
- new_cm_id->device->attrs.device_cap_flags);
- return -EPROTONOSUPPORT;
- }
-
- t = alloc_transport(new_cm_id);
- if (!t)
- return -ENOMEM;
-
- ret = smb_direct_connect(t);
- if (ret)
- goto out_err;
-
- KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop,
- KSMBD_TRANS(t)->conn, "ksmbd:r%u",
- smb_direct_port);
- if (IS_ERR(KSMBD_TRANS(t)->handler)) {
- ret = PTR_ERR(KSMBD_TRANS(t)->handler);
- pr_err("Can't start thread\n");
- goto out_err;
- }
-
- return 0;
-out_err:
- free_transport(t);
- return ret;
-}
-
-static int smb_direct_listen_handler(struct rdma_cm_id *cm_id,
- struct rdma_cm_event *event)
-{
- switch (event->event) {
- case RDMA_CM_EVENT_CONNECT_REQUEST: {
- int ret = smb_direct_handle_connect_request(cm_id);
-
- if (ret) {
- pr_err("Can't create transport: %d\n", ret);
- return ret;
- }
-
- ksmbd_debug(RDMA, "Received connection request. cm_id=%p\n",
- cm_id);
- break;
- }
- default:
- pr_err("Unexpected listen event. cm_id=%p, event=%s (%d)\n",
- cm_id, rdma_event_msg(event->event), event->event);
- break;
- }
- return 0;
-}
-
-static int smb_direct_listen(int port)
-{
- int ret;
- struct rdma_cm_id *cm_id;
- struct sockaddr_in sin = {
- .sin_family = AF_INET,
- .sin_addr.s_addr = htonl(INADDR_ANY),
- .sin_port = htons(port),
- };
-
- cm_id = rdma_create_id(&init_net, smb_direct_listen_handler,
- &smb_direct_listener, RDMA_PS_TCP, IB_QPT_RC);
- if (IS_ERR(cm_id)) {
- pr_err("Can't create cm id: %ld\n", PTR_ERR(cm_id));
- return PTR_ERR(cm_id);
- }
-
- ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
- if (ret) {
- pr_err("Can't bind: %d\n", ret);
- goto err;
- }
-
- smb_direct_listener.cm_id = cm_id;
-
- ret = rdma_listen(cm_id, 10);
- if (ret) {
- pr_err("Can't listen: %d\n", ret);
- goto err;
- }
- return 0;
-err:
- smb_direct_listener.cm_id = NULL;
- rdma_destroy_id(cm_id);
- return ret;
-}
-
-static int smb_direct_ib_client_add(struct ib_device *ib_dev)
-{
- struct smb_direct_device *smb_dev;
-
- /* Set 5445 port if device type is iWARP(No IB) */
- if (ib_dev->node_type != RDMA_NODE_IB_CA)
- smb_direct_port = SMB_DIRECT_PORT_IWARP;
-
- if (!ib_dev->ops.get_netdev ||
- !rdma_frwr_is_supported(&ib_dev->attrs))
- return 0;
-
- smb_dev = kzalloc(sizeof(*smb_dev), GFP_KERNEL);
- if (!smb_dev)
- return -ENOMEM;
- smb_dev->ib_dev = ib_dev;
-
- write_lock(&smb_direct_device_lock);
- list_add(&smb_dev->list, &smb_direct_device_list);
- write_unlock(&smb_direct_device_lock);
-
- ksmbd_debug(RDMA, "ib device added: name %s\n", ib_dev->name);
- return 0;
-}
-
-static void smb_direct_ib_client_remove(struct ib_device *ib_dev,
- void *client_data)
-{
- struct smb_direct_device *smb_dev, *tmp;
-
- write_lock(&smb_direct_device_lock);
- list_for_each_entry_safe(smb_dev, tmp, &smb_direct_device_list, list) {
- if (smb_dev->ib_dev == ib_dev) {
- list_del(&smb_dev->list);
- kfree(smb_dev);
- break;
- }
- }
- write_unlock(&smb_direct_device_lock);
-}
-
-static struct ib_client smb_direct_ib_client = {
- .name = "ksmbd_smb_direct_ib",
- .add = smb_direct_ib_client_add,
- .remove = smb_direct_ib_client_remove,
-};
-
-int ksmbd_rdma_init(void)
-{
- int ret;
-
- smb_direct_listener.cm_id = NULL;
-
- ret = ib_register_client(&smb_direct_ib_client);
- if (ret) {
- pr_err("failed to ib_register_client\n");
- return ret;
- }
-
- /* When a client is running out of send credits, the credits are
- * granted by the server's sending a packet using this queue.
- * This avoids the situation that a clients cannot send packets
- * for lack of credits
- */
- smb_direct_wq = alloc_workqueue("ksmbd-smb_direct-wq",
- WQ_HIGHPRI | WQ_MEM_RECLAIM, 0);
- if (!smb_direct_wq)
- return -ENOMEM;
-
- ret = smb_direct_listen(smb_direct_port);
- if (ret) {
- destroy_workqueue(smb_direct_wq);
- smb_direct_wq = NULL;
- pr_err("Can't listen: %d\n", ret);
- return ret;
- }
-
- ksmbd_debug(RDMA, "init RDMA listener. cm_id=%p\n",
- smb_direct_listener.cm_id);
- return 0;
-}
-
-void ksmbd_rdma_destroy(void)
-{
- if (!smb_direct_listener.cm_id)
- return;
-
- ib_unregister_client(&smb_direct_ib_client);
- rdma_destroy_id(smb_direct_listener.cm_id);
-
- smb_direct_listener.cm_id = NULL;
-
- if (smb_direct_wq) {
- destroy_workqueue(smb_direct_wq);
- smb_direct_wq = NULL;
- }
-}
-
-bool ksmbd_rdma_capable_netdev(struct net_device *netdev)
-{
- struct smb_direct_device *smb_dev;
- int i;
- bool rdma_capable = false;
-
- read_lock(&smb_direct_device_lock);
- list_for_each_entry(smb_dev, &smb_direct_device_list, list) {
- for (i = 0; i < smb_dev->ib_dev->phys_port_cnt; i++) {
- struct net_device *ndev;
-
- ndev = smb_dev->ib_dev->ops.get_netdev(smb_dev->ib_dev,
- i + 1);
- if (!ndev)
- continue;
-
- if (ndev == netdev) {
- dev_put(ndev);
- rdma_capable = true;
- goto out;
- }
- dev_put(ndev);
- }
- }
-out:
- read_unlock(&smb_direct_device_lock);
-
- if (rdma_capable == false) {
- struct ib_device *ibdev;
-
- ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_UNKNOWN);
- if (ibdev) {
- if (rdma_frwr_is_supported(&ibdev->attrs))
- rdma_capable = true;
- ib_device_put(ibdev);
- }
- }
-
- return rdma_capable;
-}
-
-static struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
- .prepare = smb_direct_prepare,
- .disconnect = smb_direct_disconnect,
- .shutdown = smb_direct_shutdown,
- .writev = smb_direct_writev,
- .read = smb_direct_read,
- .rdma_read = smb_direct_rdma_read,
- .rdma_write = smb_direct_rdma_write,
-};
diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
deleted file mode 100644
index 77aee4e5c9dc..000000000000
--- a/fs/ksmbd/transport_rdma.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2017, Microsoft Corporation.
- * Copyright (C) 2018, LG Electronics.
- */
-
-#ifndef __KSMBD_TRANSPORT_RDMA_H__
-#define __KSMBD_TRANSPORT_RDMA_H__
-
-#define SMBD_DEFAULT_IOSIZE (8 * 1024 * 1024)
-#define SMBD_MIN_IOSIZE (512 * 1024)
-#define SMBD_MAX_IOSIZE (16 * 1024 * 1024)
-
-/* SMB DIRECT negotiation request packet [MS-SMBD] 2.2.1 */
-struct smb_direct_negotiate_req {
- __le16 min_version;
- __le16 max_version;
- __le16 reserved;
- __le16 credits_requested;
- __le32 preferred_send_size;
- __le32 max_receive_size;
- __le32 max_fragmented_size;
-} __packed;
-
-/* SMB DIRECT negotiation response packet [MS-SMBD] 2.2.2 */
-struct smb_direct_negotiate_resp {
- __le16 min_version;
- __le16 max_version;
- __le16 negotiated_version;
- __le16 reserved;
- __le16 credits_requested;
- __le16 credits_granted;
- __le32 status;
- __le32 max_readwrite_size;
- __le32 preferred_send_size;
- __le32 max_receive_size;
- __le32 max_fragmented_size;
-} __packed;
-
-#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
-
-/* SMB DIRECT data transfer packet with payload [MS-SMBD] 2.2.3 */
-struct smb_direct_data_transfer {
- __le16 credits_requested;
- __le16 credits_granted;
- __le16 flags;
- __le16 reserved;
- __le32 remaining_data_length;
- __le32 data_offset;
- __le32 data_length;
- __le32 padding;
- __u8 buffer[];
-} __packed;
-
-#ifdef CONFIG_SMB_SERVER_SMBDIRECT
-int ksmbd_rdma_init(void);
-void ksmbd_rdma_destroy(void);
-bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
-void init_smbd_max_io_size(unsigned int sz);
-unsigned int get_smbd_max_read_write_size(void);
-#else
-static inline int ksmbd_rdma_init(void) { return 0; }
-static inline int ksmbd_rdma_destroy(void) { return 0; }
-static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
-static inline void init_smbd_max_io_size(unsigned int sz) { }
-static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }
-#endif
-
-#endif /* __KSMBD_TRANSPORT_RDMA_H__ */
diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c
deleted file mode 100644
index eff7a1d793f0..000000000000
--- a/fs/ksmbd/transport_tcp.c
+++ /dev/null
@@ -1,649 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/freezer.h>
-
-#include "smb_common.h"
-#include "server.h"
-#include "auth.h"
-#include "connection.h"
-#include "transport_tcp.h"
-
-#define IFACE_STATE_DOWN BIT(0)
-#define IFACE_STATE_CONFIGURED BIT(1)
-
-static atomic_t active_num_conn;
-
-struct interface {
- struct task_struct *ksmbd_kthread;
- struct socket *ksmbd_socket;
- struct list_head entry;
- char *name;
- struct mutex sock_release_lock;
- int state;
-};
-
-static LIST_HEAD(iface_list);
-
-static int bind_additional_ifaces;
-
-struct tcp_transport {
- struct ksmbd_transport transport;
- struct socket *sock;
- struct kvec *iov;
- unsigned int nr_iov;
-};
-
-static struct ksmbd_transport_ops ksmbd_tcp_transport_ops;
-
-static void tcp_stop_kthread(struct task_struct *kthread);
-static struct interface *alloc_iface(char *ifname);
-
-#define KSMBD_TRANS(t) (&(t)->transport)
-#define TCP_TRANS(t) ((struct tcp_transport *)container_of(t, \
- struct tcp_transport, transport))
-
-static inline void ksmbd_tcp_nodelay(struct socket *sock)
-{
- tcp_sock_set_nodelay(sock->sk);
-}
-
-static inline void ksmbd_tcp_reuseaddr(struct socket *sock)
-{
- sock_set_reuseaddr(sock->sk);
-}
-
-static inline void ksmbd_tcp_rcv_timeout(struct socket *sock, s64 secs)
-{
- lock_sock(sock->sk);
- if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1)
- sock->sk->sk_rcvtimeo = secs * HZ;
- else
- sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
- release_sock(sock->sk);
-}
-
-static inline void ksmbd_tcp_snd_timeout(struct socket *sock, s64 secs)
-{
- sock_set_sndtimeo(sock->sk, secs);
-}
-
-static struct tcp_transport *alloc_transport(struct socket *client_sk)
-{
- struct tcp_transport *t;
- struct ksmbd_conn *conn;
-
- t = kzalloc(sizeof(*t), GFP_KERNEL);
- if (!t)
- return NULL;
- t->sock = client_sk;
-
- conn = ksmbd_conn_alloc();
- if (!conn) {
- kfree(t);
- return NULL;
- }
-
- conn->transport = KSMBD_TRANS(t);
- KSMBD_TRANS(t)->conn = conn;
- KSMBD_TRANS(t)->ops = &ksmbd_tcp_transport_ops;
- return t;
-}
-
-static void free_transport(struct tcp_transport *t)
-{
- kernel_sock_shutdown(t->sock, SHUT_RDWR);
- sock_release(t->sock);
- t->sock = NULL;
-
- ksmbd_conn_free(KSMBD_TRANS(t)->conn);
- kfree(t->iov);
- kfree(t);
-}
-
-/**
- * kvec_array_init() - initialize a IO vector segment
- * @new: IO vector to be initialized
- * @iov: base IO vector
- * @nr_segs: number of segments in base iov
- * @bytes: total iovec length so far for read
- *
- * Return: Number of IO segments
- */
-static unsigned int kvec_array_init(struct kvec *new, struct kvec *iov,
- unsigned int nr_segs, size_t bytes)
-{
- size_t base = 0;
-
- while (bytes || !iov->iov_len) {
- int copy = min(bytes, iov->iov_len);
-
- bytes -= copy;
- base += copy;
- if (iov->iov_len == base) {
- iov++;
- nr_segs--;
- base = 0;
- }
- }
-
- memcpy(new, iov, sizeof(*iov) * nr_segs);
- new->iov_base += base;
- new->iov_len -= base;
- return nr_segs;
-}
-
-/**
- * get_conn_iovec() - get connection iovec for reading from socket
- * @t: TCP transport instance
- * @nr_segs: number of segments in iov
- *
- * Return: return existing or newly allocate iovec
- */
-static struct kvec *get_conn_iovec(struct tcp_transport *t, unsigned int nr_segs)
-{
- struct kvec *new_iov;
-
- if (t->iov && nr_segs <= t->nr_iov)
- return t->iov;
-
- /* not big enough -- allocate a new one and release the old */
- new_iov = kmalloc_array(nr_segs, sizeof(*new_iov), GFP_KERNEL);
- if (new_iov) {
- kfree(t->iov);
- t->iov = new_iov;
- t->nr_iov = nr_segs;
- }
- return new_iov;
-}
-
-static unsigned short ksmbd_tcp_get_port(const struct sockaddr *sa)
-{
- switch (sa->sa_family) {
- case AF_INET:
- return ntohs(((struct sockaddr_in *)sa)->sin_port);
- case AF_INET6:
- return ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
- }
- return 0;
-}
-
-/**
- * ksmbd_tcp_new_connection() - create a new tcp session on mount
- * @client_sk: socket associated with new connection
- *
- * whenever a new connection is requested, create a conn thread
- * (session thread) to handle new incoming smb requests from the connection
- *
- * Return: 0 on success, otherwise error
- */
-static int ksmbd_tcp_new_connection(struct socket *client_sk)
-{
- struct sockaddr *csin;
- int rc = 0;
- struct tcp_transport *t;
-
- t = alloc_transport(client_sk);
- if (!t) {
- sock_release(client_sk);
- return -ENOMEM;
- }
-
- csin = KSMBD_TCP_PEER_SOCKADDR(KSMBD_TRANS(t)->conn);
- if (kernel_getpeername(client_sk, csin) < 0) {
- pr_err("client ip resolution failed\n");
- rc = -EINVAL;
- goto out_error;
- }
-
- KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop,
- KSMBD_TRANS(t)->conn,
- "ksmbd:%u",
- ksmbd_tcp_get_port(csin));
- if (IS_ERR(KSMBD_TRANS(t)->handler)) {
- pr_err("cannot start conn thread\n");
- rc = PTR_ERR(KSMBD_TRANS(t)->handler);
- free_transport(t);
- }
- return rc;
-
-out_error:
- free_transport(t);
- return rc;
-}
-
-/**
- * ksmbd_kthread_fn() - listen to new SMB connections and callback server
- * @p: arguments to forker thread
- *
- * Return: 0 on success, error number otherwise
- */
-static int ksmbd_kthread_fn(void *p)
-{
- struct socket *client_sk = NULL;
- struct interface *iface = (struct interface *)p;
- int ret;
-
- while (!kthread_should_stop()) {
- mutex_lock(&iface->sock_release_lock);
- if (!iface->ksmbd_socket) {
- mutex_unlock(&iface->sock_release_lock);
- break;
- }
- ret = kernel_accept(iface->ksmbd_socket, &client_sk,
- SOCK_NONBLOCK);
- mutex_unlock(&iface->sock_release_lock);
- if (ret) {
- if (ret == -EAGAIN)
- /* check for new connections every 100 msecs */
- schedule_timeout_interruptible(HZ / 10);
- continue;
- }
-
- if (server_conf.max_connections &&
- atomic_inc_return(&active_num_conn) >= server_conf.max_connections) {
- pr_info_ratelimited("Limit the maximum number of connections(%u)\n",
- atomic_read(&active_num_conn));
- atomic_dec(&active_num_conn);
- sock_release(client_sk);
- continue;
- }
-
- ksmbd_debug(CONN, "connect success: accepted new connection\n");
- client_sk->sk->sk_rcvtimeo = KSMBD_TCP_RECV_TIMEOUT;
- client_sk->sk->sk_sndtimeo = KSMBD_TCP_SEND_TIMEOUT;
-
- ksmbd_tcp_new_connection(client_sk);
- }
-
- ksmbd_debug(CONN, "releasing socket\n");
- return 0;
-}
-
-/**
- * ksmbd_tcp_run_kthread() - start forker thread
- * @iface: pointer to struct interface
- *
- * start forker thread(ksmbd/0) at module init time to listen
- * on port 445 for new SMB connection requests. It creates per connection
- * server threads(ksmbd/x)
- *
- * Return: 0 on success or error number
- */
-static int ksmbd_tcp_run_kthread(struct interface *iface)
-{
- int rc;
- struct task_struct *kthread;
-
- kthread = kthread_run(ksmbd_kthread_fn, (void *)iface, "ksmbd-%s",
- iface->name);
- if (IS_ERR(kthread)) {
- rc = PTR_ERR(kthread);
- return rc;
- }
- iface->ksmbd_kthread = kthread;
-
- return 0;
-}
-
-/**
- * ksmbd_tcp_readv() - read data from socket in given iovec
- * @t: TCP transport instance
- * @iov_orig: base IO vector
- * @nr_segs: number of segments in base iov
- * @to_read: number of bytes to read from socket
- * @max_retries: maximum retry count
- *
- * Return: on success return number of bytes read from socket,
- * otherwise return error number
- */
-static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
- unsigned int nr_segs, unsigned int to_read,
- int max_retries)
-{
- int length = 0;
- int total_read;
- unsigned int segs;
- struct msghdr ksmbd_msg;
- struct kvec *iov;
- struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn;
-
- iov = get_conn_iovec(t, nr_segs);
- if (!iov)
- return -ENOMEM;
-
- ksmbd_msg.msg_control = NULL;
- ksmbd_msg.msg_controllen = 0;
-
- for (total_read = 0; to_read; total_read += length, to_read -= length) {
- try_to_freeze();
-
- if (!ksmbd_conn_alive(conn)) {
- total_read = -ESHUTDOWN;
- break;
- }
- segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
-
- length = kernel_recvmsg(t->sock, &ksmbd_msg,
- iov, segs, to_read, 0);
-
- if (length == -EINTR) {
- total_read = -ESHUTDOWN;
- break;
- } else if (ksmbd_conn_need_reconnect(conn)) {
- total_read = -EAGAIN;
- break;
- } else if (length == -ERESTARTSYS || length == -EAGAIN) {
- /*
- * If max_retries is negative, Allow unlimited
- * retries to keep connection with inactive sessions.
- */
- if (max_retries == 0) {
- total_read = length;
- break;
- } else if (max_retries > 0) {
- max_retries--;
- }
-
- usleep_range(1000, 2000);
- length = 0;
- continue;
- } else if (length <= 0) {
- total_read = length;
- break;
- }
- }
- return total_read;
-}
-
-/**
- * ksmbd_tcp_read() - read data from socket in given buffer
- * @t: TCP transport instance
- * @buf: buffer to store read data from socket
- * @to_read: number of bytes to read from socket
- *
- * Return: on success return number of bytes read from socket,
- * otherwise return error number
- */
-static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf,
- unsigned int to_read, int max_retries)
-{
- struct kvec iov;
-
- iov.iov_base = buf;
- iov.iov_len = to_read;
-
- return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read, max_retries);
-}
-
-static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,
- int nvecs, int size, bool need_invalidate,
- unsigned int remote_key)
-
-{
- struct msghdr smb_msg = {.msg_flags = MSG_NOSIGNAL};
-
- return kernel_sendmsg(TCP_TRANS(t)->sock, &smb_msg, iov, nvecs, size);
-}
-
-static void ksmbd_tcp_disconnect(struct ksmbd_transport *t)
-{
- free_transport(TCP_TRANS(t));
- if (server_conf.max_connections)
- atomic_dec(&active_num_conn);
-}
-
-static void tcp_destroy_socket(struct socket *ksmbd_socket)
-{
- int ret;
-
- if (!ksmbd_socket)
- return;
-
- /* set zero to timeout */
- ksmbd_tcp_rcv_timeout(ksmbd_socket, 0);
- ksmbd_tcp_snd_timeout(ksmbd_socket, 0);
-
- ret = kernel_sock_shutdown(ksmbd_socket, SHUT_RDWR);
- if (ret)
- pr_err("Failed to shutdown socket: %d\n", ret);
- sock_release(ksmbd_socket);
-}
-
-/**
- * create_socket - create socket for ksmbd/0
- *
- * Return: 0 on success, error number otherwise
- */
-static int create_socket(struct interface *iface)
-{
- int ret;
- struct sockaddr_in6 sin6;
- struct sockaddr_in sin;
- struct socket *ksmbd_socket;
- bool ipv4 = false;
-
- ret = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &ksmbd_socket);
- if (ret) {
- if (ret != -EAFNOSUPPORT)
- pr_err("Can't create socket for ipv6, fallback to ipv4: %d\n", ret);
- ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP,
- &ksmbd_socket);
- if (ret) {
- pr_err("Can't create socket for ipv4: %d\n", ret);
- goto out_clear;
- }
-
- sin.sin_family = PF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
- sin.sin_port = htons(server_conf.tcp_port);
- ipv4 = true;
- } else {
- sin6.sin6_family = PF_INET6;
- sin6.sin6_addr = in6addr_any;
- sin6.sin6_port = htons(server_conf.tcp_port);
- }
-
- ksmbd_tcp_nodelay(ksmbd_socket);
- ksmbd_tcp_reuseaddr(ksmbd_socket);
-
- ret = sock_setsockopt(ksmbd_socket,
- SOL_SOCKET,
- SO_BINDTODEVICE,
- KERNEL_SOCKPTR(iface->name),
- strlen(iface->name));
- if (ret != -ENODEV && ret < 0) {
- pr_err("Failed to set SO_BINDTODEVICE: %d\n", ret);
- goto out_error;
- }
-
- if (ipv4)
- ret = kernel_bind(ksmbd_socket, (struct sockaddr *)&sin,
- sizeof(sin));
- else
- ret = kernel_bind(ksmbd_socket, (struct sockaddr *)&sin6,
- sizeof(sin6));
- if (ret) {
- pr_err("Failed to bind socket: %d\n", ret);
- goto out_error;
- }
-
- ksmbd_socket->sk->sk_rcvtimeo = KSMBD_TCP_RECV_TIMEOUT;
- ksmbd_socket->sk->sk_sndtimeo = KSMBD_TCP_SEND_TIMEOUT;
-
- ret = kernel_listen(ksmbd_socket, KSMBD_SOCKET_BACKLOG);
- if (ret) {
- pr_err("Port listen() error: %d\n", ret);
- goto out_error;
- }
-
- iface->ksmbd_socket = ksmbd_socket;
- ret = ksmbd_tcp_run_kthread(iface);
- if (ret) {
- pr_err("Can't start ksmbd main kthread: %d\n", ret);
- goto out_error;
- }
- iface->state = IFACE_STATE_CONFIGURED;
-
- return 0;
-
-out_error:
- tcp_destroy_socket(ksmbd_socket);
-out_clear:
- iface->ksmbd_socket = NULL;
- return ret;
-}
-
-static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
- void *ptr)
-{
- struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
- struct interface *iface;
- int ret, found = 0;
-
- switch (event) {
- case NETDEV_UP:
- if (netif_is_bridge_port(netdev))
- return NOTIFY_OK;
-
- list_for_each_entry(iface, &iface_list, entry) {
- if (!strcmp(iface->name, netdev->name)) {
- found = 1;
- if (iface->state != IFACE_STATE_DOWN)
- break;
- ret = create_socket(iface);
- if (ret)
- return NOTIFY_OK;
- break;
- }
- }
- if (!found && bind_additional_ifaces) {
- iface = alloc_iface(kstrdup(netdev->name, GFP_KERNEL));
- if (!iface)
- return NOTIFY_OK;
- ret = create_socket(iface);
- if (ret)
- break;
- }
- break;
- case NETDEV_DOWN:
- list_for_each_entry(iface, &iface_list, entry) {
- if (!strcmp(iface->name, netdev->name) &&
- iface->state == IFACE_STATE_CONFIGURED) {
- tcp_stop_kthread(iface->ksmbd_kthread);
- iface->ksmbd_kthread = NULL;
- mutex_lock(&iface->sock_release_lock);
- tcp_destroy_socket(iface->ksmbd_socket);
- iface->ksmbd_socket = NULL;
- mutex_unlock(&iface->sock_release_lock);
-
- iface->state = IFACE_STATE_DOWN;
- break;
- }
- }
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block ksmbd_netdev_notifier = {
- .notifier_call = ksmbd_netdev_event,
-};
-
-int ksmbd_tcp_init(void)
-{
- register_netdevice_notifier(&ksmbd_netdev_notifier);
-
- return 0;
-}
-
-static void tcp_stop_kthread(struct task_struct *kthread)
-{
- int ret;
-
- if (!kthread)
- return;
-
- ret = kthread_stop(kthread);
- if (ret)
- pr_err("failed to stop forker thread\n");
-}
-
-void ksmbd_tcp_destroy(void)
-{
- struct interface *iface, *tmp;
-
- unregister_netdevice_notifier(&ksmbd_netdev_notifier);
-
- list_for_each_entry_safe(iface, tmp, &iface_list, entry) {
- list_del(&iface->entry);
- kfree(iface->name);
- kfree(iface);
- }
-}
-
-static struct interface *alloc_iface(char *ifname)
-{
- struct interface *iface;
-
- if (!ifname)
- return NULL;
-
- iface = kzalloc(sizeof(struct interface), GFP_KERNEL);
- if (!iface) {
- kfree(ifname);
- return NULL;
- }
-
- iface->name = ifname;
- iface->state = IFACE_STATE_DOWN;
- list_add(&iface->entry, &iface_list);
- mutex_init(&iface->sock_release_lock);
- return iface;
-}
-
-int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz)
-{
- int sz = 0;
-
- if (!ifc_list_sz) {
- struct net_device *netdev;
-
- rtnl_lock();
- for_each_netdev(&init_net, netdev) {
- if (netif_is_bridge_port(netdev))
- continue;
- if (!alloc_iface(kstrdup(netdev->name, GFP_KERNEL)))
- return -ENOMEM;
- }
- rtnl_unlock();
- bind_additional_ifaces = 1;
- return 0;
- }
-
- while (ifc_list_sz > 0) {
- if (!alloc_iface(kstrdup(ifc_list, GFP_KERNEL)))
- return -ENOMEM;
-
- sz = strlen(ifc_list);
- if (!sz)
- break;
-
- ifc_list += sz + 1;
- ifc_list_sz -= (sz + 1);
- }
-
- bind_additional_ifaces = 0;
-
- return 0;
-}
-
-static struct ksmbd_transport_ops ksmbd_tcp_transport_ops = {
- .read = ksmbd_tcp_read,
- .writev = ksmbd_tcp_writev,
- .disconnect = ksmbd_tcp_disconnect,
-};
diff --git a/fs/ksmbd/transport_tcp.h b/fs/ksmbd/transport_tcp.h
deleted file mode 100644
index e338bebe322f..000000000000
--- a/fs/ksmbd/transport_tcp.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_TRANSPORT_TCP_H__
-#define __KSMBD_TRANSPORT_TCP_H__
-
-int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz);
-int ksmbd_tcp_init(void);
-void ksmbd_tcp_destroy(void);
-
-#endif /* __KSMBD_TRANSPORT_TCP_H__ */
diff --git a/fs/ksmbd/unicode.c b/fs/ksmbd/unicode.c
deleted file mode 100644
index a0db699ddafd..000000000000
--- a/fs/ksmbd/unicode.c
+++ /dev/null
@@ -1,384 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Some of the source code in this file came from fs/cifs/cifs_unicode.c
- *
- * Copyright (c) International Business Machines Corp., 2000,2009
- * Modified by Steve French (sfrench@us.ibm.com)
- * Modified by Namjae Jeon (linkinjeon@kernel.org)
- */
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-#include "glob.h"
-#include "unicode.h"
-#include "uniupr.h"
-#include "smb_common.h"
-
-/*
- * smb_utf16_bytes() - how long will a string be after conversion?
- * @from: pointer to input string
- * @maxbytes: don't go past this many bytes of input string
- * @codepage: destination codepage
- *
- * Walk a utf16le string and return the number of bytes that the string will
- * be after being converted to the given charset, not including any null
- * termination required. Don't walk past maxbytes in the source buffer.
- *
- * Return: string length after conversion
- */
-static int smb_utf16_bytes(const __le16 *from, int maxbytes,
- const struct nls_table *codepage)
-{
- int i;
- int charlen, outlen = 0;
- int maxwords = maxbytes / 2;
- char tmp[NLS_MAX_CHARSET_SIZE];
- __u16 ftmp;
-
- for (i = 0; i < maxwords; i++) {
- ftmp = get_unaligned_le16(&from[i]);
- if (ftmp == 0)
- break;
-
- charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE);
- if (charlen > 0)
- outlen += charlen;
- else
- outlen++;
- }
-
- return outlen;
-}
-
-/*
- * cifs_mapchar() - convert a host-endian char to proper char in codepage
- * @target: where converted character should be copied
- * @src_char: 2 byte host-endian source character
- * @cp: codepage to which character should be converted
- * @mapchar: should character be mapped according to mapchars mount option?
- *
- * This function handles the conversion of a single character. It is the
- * responsibility of the caller to ensure that the target buffer is large
- * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
- *
- * Return: string length after conversion
- */
-static int
-cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
- bool mapchar)
-{
- int len = 1;
-
- if (!mapchar)
- goto cp_convert;
-
- /*
- * BB: Cannot handle remapping UNI_SLASH until all the calls to
- * build_path_from_dentry are modified, as they use slash as
- * separator.
- */
- switch (src_char) {
- case UNI_COLON:
- *target = ':';
- break;
- case UNI_ASTERISK:
- *target = '*';
- break;
- case UNI_QUESTION:
- *target = '?';
- break;
- case UNI_PIPE:
- *target = '|';
- break;
- case UNI_GRTRTHAN:
- *target = '>';
- break;
- case UNI_LESSTHAN:
- *target = '<';
- break;
- default:
- goto cp_convert;
- }
-
-out:
- return len;
-
-cp_convert:
- len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE);
- if (len <= 0) {
- *target = '?';
- len = 1;
- }
-
- goto out;
-}
-
-/*
- * is_char_allowed() - check for valid character
- * @ch: input character to be checked
- *
- * Return: 1 if char is allowed, otherwise 0
- */
-static inline int is_char_allowed(char *ch)
-{
- /* check for control chars, wildcards etc. */
- if (!(*ch & 0x80) &&
- (*ch <= 0x1f ||
- *ch == '?' || *ch == '"' || *ch == '<' ||
- *ch == '>' || *ch == '|'))
- return 0;
-
- return 1;
-}
-
-/*
- * smb_from_utf16() - convert utf16le string to local charset
- * @to: destination buffer
- * @from: source buffer
- * @tolen: destination buffer size (in bytes)
- * @fromlen: source buffer size (in bytes)
- * @codepage: codepage to which characters should be converted
- * @mapchar: should characters be remapped according to the mapchars option?
- *
- * Convert a little-endian utf16le string (as sent by the server) to a string
- * in the provided codepage. The tolen and fromlen parameters are to ensure
- * that the code doesn't walk off of the end of the buffer (which is always
- * a danger if the alignment of the source buffer is off). The destination
- * string is always properly null terminated and fits in the destination
- * buffer. Returns the length of the destination string in bytes (including
- * null terminator).
- *
- * Note that some windows versions actually send multiword UTF-16 characters
- * instead of straight UTF16-2. The linux nls routines however aren't able to
- * deal with those characters properly. In the event that we get some of
- * those characters, they won't be translated properly.
- *
- * Return: string length after conversion
- */
-static int smb_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
- const struct nls_table *codepage, bool mapchar)
-{
- int i, charlen, safelen;
- int outlen = 0;
- int nullsize = nls_nullsize(codepage);
- int fromwords = fromlen / 2;
- char tmp[NLS_MAX_CHARSET_SIZE];
- __u16 ftmp;
-
- /*
- * because the chars can be of varying widths, we need to take care
- * not to overflow the destination buffer when we get close to the
- * end of it. Until we get to this offset, we don't need to check
- * for overflow however.
- */
- safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
-
- for (i = 0; i < fromwords; i++) {
- ftmp = get_unaligned_le16(&from[i]);
- if (ftmp == 0)
- break;
-
- /*
- * check to see if converting this character might make the
- * conversion bleed into the null terminator
- */
- if (outlen >= safelen) {
- charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar);
- if ((outlen + charlen) > (tolen - nullsize))
- break;
- }
-
- /* put converted char into 'to' buffer */
- charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar);
- outlen += charlen;
- }
-
- /* properly null-terminate string */
- for (i = 0; i < nullsize; i++)
- to[outlen++] = 0;
-
- return outlen;
-}
-
-/*
- * smb_strtoUTF16() - Convert character string to unicode string
- * @to: destination buffer
- * @from: source buffer
- * @len: destination buffer size (in bytes)
- * @codepage: codepage to which characters should be converted
- *
- * Return: string length after conversion
- */
-int smb_strtoUTF16(__le16 *to, const char *from, int len,
- const struct nls_table *codepage)
-{
- int charlen;
- int i;
- wchar_t wchar_to; /* needed to quiet sparse */
-
- /* special case for utf8 to handle no plane0 chars */
- if (!strcmp(codepage->charset, "utf8")) {
- /*
- * convert utf8 -> utf16, we assume we have enough space
- * as caller should have assumed conversion does not overflow
- * in destination len is length in wchar_t units (16bits)
- */
- i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN,
- (wchar_t *)to, len);
-
- /* if success terminate and exit */
- if (i >= 0)
- goto success;
- /*
- * if fails fall back to UCS encoding as this
- * function should not return negative values
- * currently can fail only if source contains
- * invalid encoded characters
- */
- }
-
- for (i = 0; len > 0 && *from; i++, from += charlen, len -= charlen) {
- charlen = codepage->char2uni(from, len, &wchar_to);
- if (charlen < 1) {
- /* A question mark */
- wchar_to = 0x003f;
- charlen = 1;
- }
- put_unaligned_le16(wchar_to, &to[i]);
- }
-
-success:
- put_unaligned_le16(0, &to[i]);
- return i;
-}
-
-/*
- * smb_strndup_from_utf16() - copy a string from wire format to the local
- * codepage
- * @src: source string
- * @maxlen: don't walk past this many bytes in the source string
- * @is_unicode: is this a unicode string?
- * @codepage: destination codepage
- *
- * Take a string given by the server, convert it to the local codepage and
- * put it in a new buffer. Returns a pointer to the new string or NULL on
- * error.
- *
- * Return: destination string buffer or error ptr
- */
-char *smb_strndup_from_utf16(const char *src, const int maxlen,
- const bool is_unicode,
- const struct nls_table *codepage)
-{
- int len, ret;
- char *dst;
-
- if (is_unicode) {
- len = smb_utf16_bytes((__le16 *)src, maxlen, codepage);
- len += nls_nullsize(codepage);
- dst = kmalloc(len, GFP_KERNEL);
- if (!dst)
- return ERR_PTR(-ENOMEM);
- ret = smb_from_utf16(dst, (__le16 *)src, len, maxlen, codepage,
- false);
- if (ret < 0) {
- kfree(dst);
- return ERR_PTR(-EINVAL);
- }
- } else {
- len = strnlen(src, maxlen);
- len++;
- dst = kmalloc(len, GFP_KERNEL);
- if (!dst)
- return ERR_PTR(-ENOMEM);
- strscpy(dst, src, len);
- }
-
- return dst;
-}
-
-/*
- * Convert 16 bit Unicode pathname to wire format from string in current code
- * page. Conversion may involve remapping up the six characters that are
- * only legal in POSIX-like OS (if they are present in the string). Path
- * names are little endian 16 bit Unicode on the wire
- */
-/*
- * smbConvertToUTF16() - convert string from local charset to utf16
- * @target: destination buffer
- * @source: source buffer
- * @srclen: source buffer size (in bytes)
- * @cp: codepage to which characters should be converted
- * @mapchar: should characters be remapped according to the mapchars option?
- *
- * Convert 16 bit Unicode pathname to wire format from string in current code
- * page. Conversion may involve remapping up the six characters that are
- * only legal in POSIX-like OS (if they are present in the string). Path
- * names are little endian 16 bit Unicode on the wire
- *
- * Return: char length after conversion
- */
-int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
- const struct nls_table *cp, int mapchars)
-{
- int i, j, charlen;
- char src_char;
- __le16 dst_char;
- wchar_t tmp;
-
- if (!mapchars)
- return smb_strtoUTF16(target, source, srclen, cp);
-
- for (i = 0, j = 0; i < srclen; j++) {
- src_char = source[i];
- charlen = 1;
- switch (src_char) {
- case 0:
- put_unaligned(0, &target[j]);
- return j;
- case ':':
- dst_char = cpu_to_le16(UNI_COLON);
- break;
- case '*':
- dst_char = cpu_to_le16(UNI_ASTERISK);
- break;
- case '?':
- dst_char = cpu_to_le16(UNI_QUESTION);
- break;
- case '<':
- dst_char = cpu_to_le16(UNI_LESSTHAN);
- break;
- case '>':
- dst_char = cpu_to_le16(UNI_GRTRTHAN);
- break;
- case '|':
- dst_char = cpu_to_le16(UNI_PIPE);
- break;
- /*
- * FIXME: We can not handle remapping backslash (UNI_SLASH)
- * until all the calls to build_path_from_dentry are modified,
- * as they use backslash as separator.
- */
- default:
- charlen = cp->char2uni(source + i, srclen - i, &tmp);
- dst_char = cpu_to_le16(tmp);
-
- /*
- * if no match, use question mark, which at least in
- * some cases serves as wild card
- */
- if (charlen < 1) {
- dst_char = cpu_to_le16(0x003f);
- charlen = 1;
- }
- }
- /*
- * character may take more than one byte in the source string,
- * but will take exactly two bytes in the target string
- */
- i += charlen;
- put_unaligned(dst_char, &target[j]);
- }
-
- return j;
-}
diff --git a/fs/ksmbd/unicode.h b/fs/ksmbd/unicode.h
deleted file mode 100644
index 076f6034a789..000000000000
--- a/fs/ksmbd/unicode.h
+++ /dev/null
@@ -1,358 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Some of the source code in this file came from fs/cifs/cifs_unicode.c
- * cifs_unicode: Unicode kernel case support
- *
- * Function:
- * Convert a unicode character to upper or lower case using
- * compressed tables.
- *
- * Copyright (c) International Business Machines Corp., 2000,2009
- *
- *
- * Notes:
- * These APIs are based on the C library functions. The semantics
- * should match the C functions but with expanded size operands.
- *
- * The upper/lower functions are based on a table created by mkupr.
- * This is a compressed table of upper and lower case conversion.
- *
- */
-#ifndef _CIFS_UNICODE_H
-#define _CIFS_UNICODE_H
-
-#include <asm/byteorder.h>
-#include <linux/types.h>
-#include <linux/nls.h>
-#include <linux/unicode.h>
-
-#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
-
-/*
- * Windows maps these to the user defined 16 bit Unicode range since they are
- * reserved symbols (along with \ and /), otherwise illegal to store
- * in filenames in NTFS
- */
-#define UNI_ASTERISK ((__u16)('*' + 0xF000))
-#define UNI_QUESTION ((__u16)('?' + 0xF000))
-#define UNI_COLON ((__u16)(':' + 0xF000))
-#define UNI_GRTRTHAN ((__u16)('>' + 0xF000))
-#define UNI_LESSTHAN ((__u16)('<' + 0xF000))
-#define UNI_PIPE ((__u16)('|' + 0xF000))
-#define UNI_SLASH ((__u16)('\\' + 0xF000))
-
-/* Just define what we want from uniupr.h. We don't want to define the tables
- * in each source file.
- */
-#ifndef UNICASERANGE_DEFINED
-struct UniCaseRange {
- wchar_t start;
- wchar_t end;
- signed char *table;
-};
-#endif /* UNICASERANGE_DEFINED */
-
-#ifndef UNIUPR_NOUPPER
-extern signed char SmbUniUpperTable[512];
-extern const struct UniCaseRange SmbUniUpperRange[];
-#endif /* UNIUPR_NOUPPER */
-
-#ifndef UNIUPR_NOLOWER
-extern signed char CifsUniLowerTable[512];
-extern const struct UniCaseRange CifsUniLowerRange[];
-#endif /* UNIUPR_NOLOWER */
-
-#ifdef __KERNEL__
-int smb_strtoUTF16(__le16 *to, const char *from, int len,
- const struct nls_table *codepage);
-char *smb_strndup_from_utf16(const char *src, const int maxlen,
- const bool is_unicode,
- const struct nls_table *codepage);
-int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
- const struct nls_table *cp, int mapchars);
-char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
-#endif
-
-/*
- * UniStrcat: Concatenate the second string to the first
- *
- * Returns:
- * Address of the first string
- */
-static inline wchar_t *UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)
-{
- wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
-
- while (*ucs1++)
- /*NULL*/; /* To end of first string */
- ucs1--; /* Return to the null */
- while ((*ucs1++ = *ucs2++))
- /*NULL*/; /* copy string 2 over */
- return anchor;
-}
-
-/*
- * UniStrchr: Find a character in a string
- *
- * Returns:
- * Address of first occurrence of character in string
- * or NULL if the character is not in the string
- */
-static inline wchar_t *UniStrchr(const wchar_t *ucs, wchar_t uc)
-{
- while ((*ucs != uc) && *ucs)
- ucs++;
-
- if (*ucs == uc)
- return (wchar_t *)ucs;
- return NULL;
-}
-
-/*
- * UniStrcmp: Compare two strings
- *
- * Returns:
- * < 0: First string is less than second
- * = 0: Strings are equal
- * > 0: First string is greater than second
- */
-static inline int UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
-{
- while ((*ucs1 == *ucs2) && *ucs1) {
- ucs1++;
- ucs2++;
- }
- return (int)*ucs1 - (int)*ucs2;
-}
-
-/*
- * UniStrcpy: Copy a string
- */
-static inline wchar_t *UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
-{
- wchar_t *anchor = ucs1; /* save the start of result string */
-
- while ((*ucs1++ = *ucs2++))
- /*NULL*/;
- return anchor;
-}
-
-/*
- * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
- */
-static inline size_t UniStrlen(const wchar_t *ucs1)
-{
- int i = 0;
-
- while (*ucs1++)
- i++;
- return i;
-}
-
-/*
- * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
- * string (length limited)
- */
-static inline size_t UniStrnlen(const wchar_t *ucs1, int maxlen)
-{
- int i = 0;
-
- while (*ucs1++) {
- i++;
- if (i >= maxlen)
- break;
- }
- return i;
-}
-
-/*
- * UniStrncat: Concatenate length limited string
- */
-static inline wchar_t *UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- wchar_t *anchor = ucs1; /* save pointer to string 1 */
-
- while (*ucs1++)
- /*NULL*/;
- ucs1--; /* point to null terminator of s1 */
- while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
- ucs1++;
- ucs2++;
- }
- *ucs1 = 0; /* Null terminate the result */
- return anchor;
-}
-
-/*
- * UniStrncmp: Compare length limited string
- */
-static inline int UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- if (!n)
- return 0; /* Null strings are equal */
- while ((*ucs1 == *ucs2) && *ucs1 && --n) {
- ucs1++;
- ucs2++;
- }
- return (int)*ucs1 - (int)*ucs2;
-}
-
-/*
- * UniStrncmp_le: Compare length limited string - native to little-endian
- */
-static inline int
-UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- if (!n)
- return 0; /* Null strings are equal */
- while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
- ucs1++;
- ucs2++;
- }
- return (int)*ucs1 - (int)__le16_to_cpu(*ucs2);
-}
-
-/*
- * UniStrncpy: Copy length limited string with pad
- */
-static inline wchar_t *UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- wchar_t *anchor = ucs1;
-
- while (n-- && *ucs2) /* Copy the strings */
- *ucs1++ = *ucs2++;
-
- n++;
- while (n--) /* Pad with nulls */
- *ucs1++ = 0;
- return anchor;
-}
-
-/*
- * UniStrncpy_le: Copy length limited string with pad to little-endian
- */
-static inline wchar_t *UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
-{
- wchar_t *anchor = ucs1;
-
- while (n-- && *ucs2) /* Copy the strings */
- *ucs1++ = __le16_to_cpu(*ucs2++);
-
- n++;
- while (n--) /* Pad with nulls */
- *ucs1++ = 0;
- return anchor;
-}
-
-/*
- * UniStrstr: Find a string in a string
- *
- * Returns:
- * Address of first match found
- * NULL if no matching string is found
- */
-static inline wchar_t *UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
-{
- const wchar_t *anchor1 = ucs1;
- const wchar_t *anchor2 = ucs2;
-
- while (*ucs1) {
- if (*ucs1 == *ucs2) {
- /* Partial match found */
- ucs1++;
- ucs2++;
- } else {
- if (!*ucs2) /* Match found */
- return (wchar_t *)anchor1;
- ucs1 = ++anchor1; /* No match */
- ucs2 = anchor2;
- }
- }
-
- if (!*ucs2) /* Both end together */
- return (wchar_t *)anchor1; /* Match found */
- return NULL; /* No match */
-}
-
-#ifndef UNIUPR_NOUPPER
-/*
- * UniToupper: Convert a unicode character to upper case
- */
-static inline wchar_t UniToupper(register wchar_t uc)
-{
- register const struct UniCaseRange *rp;
-
- if (uc < sizeof(SmbUniUpperTable)) {
- /* Latin characters */
- return uc + SmbUniUpperTable[uc]; /* Use base tables */
- }
-
- rp = SmbUniUpperRange; /* Use range tables */
- while (rp->start) {
- if (uc < rp->start) /* Before start of range */
- return uc; /* Uppercase = input */
- if (uc <= rp->end) /* In range */
- return uc + rp->table[uc - rp->start];
- rp++; /* Try next range */
- }
- return uc; /* Past last range */
-}
-
-/*
- * UniStrupr: Upper case a unicode string
- */
-static inline __le16 *UniStrupr(register __le16 *upin)
-{
- register __le16 *up;
-
- up = upin;
- while (*up) { /* For all characters */
- *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
- up++;
- }
- return upin; /* Return input pointer */
-}
-#endif /* UNIUPR_NOUPPER */
-
-#ifndef UNIUPR_NOLOWER
-/*
- * UniTolower: Convert a unicode character to lower case
- */
-static inline wchar_t UniTolower(register wchar_t uc)
-{
- register const struct UniCaseRange *rp;
-
- if (uc < sizeof(CifsUniLowerTable)) {
- /* Latin characters */
- return uc + CifsUniLowerTable[uc]; /* Use base tables */
- }
-
- rp = CifsUniLowerRange; /* Use range tables */
- while (rp->start) {
- if (uc < rp->start) /* Before start of range */
- return uc; /* Uppercase = input */
- if (uc <= rp->end) /* In range */
- return uc + rp->table[uc - rp->start];
- rp++; /* Try next range */
- }
- return uc; /* Past last range */
-}
-
-/*
- * UniStrlwr: Lower case a unicode string
- */
-static inline wchar_t *UniStrlwr(register wchar_t *upin)
-{
- register wchar_t *up;
-
- up = upin;
- while (*up) { /* For all characters */
- *up = UniTolower(*up);
- up++;
- }
- return upin; /* Return input pointer */
-}
-
-#endif
-
-#endif /* _CIFS_UNICODE_H */
diff --git a/fs/ksmbd/uniupr.h b/fs/ksmbd/uniupr.h
deleted file mode 100644
index 26583b776897..000000000000
--- a/fs/ksmbd/uniupr.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Some of the source code in this file came from fs/cifs/uniupr.h
- * Copyright (c) International Business Machines Corp., 2000,2002
- *
- * uniupr.h - Unicode compressed case ranges
- *
- */
-#ifndef __KSMBD_UNIUPR_H
-#define __KSMBD_UNIUPR_H
-
-#ifndef UNIUPR_NOUPPER
-/*
- * Latin upper case
- */
-signed char SmbUniUpperTable[512] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
- 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, /* 060-06f */
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, 0, 0, 0, 0, 0, /* 070-07f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
- -32, -32, -32, -32, -32, -32, -32, 0, -32, -32,
- -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
- 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
- -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
- 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
- 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
- 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
- -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
- 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
- -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
- 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
-};
-
-/* Upper case range - Greek */
-static signed char UniCaseRangeU03a0[47] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
- 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, /* 3b0-3bf */
- -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
- -63, -63,
-};
-
-/* Upper case range - Cyrillic */
-static signed char UniCaseRangeU0430[48] = {
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, /* 430-43f */
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, /* 440-44f */
- 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
- -80, -80, 0, -80, -80, /* 450-45f */
-};
-
-/* Upper case range - Extended cyrillic */
-static signed char UniCaseRangeU0490[61] = {
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
- 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
-};
-
-/* Upper case range - Extended latin and greek */
-static signed char UniCaseRangeU1e00[509] = {
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
- 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
- 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
- 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
- 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
- 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
- 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112,
- 126, 126, 0, 0, /* 1f70-1f7f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
- 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
- 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
- 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
- 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
- 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
- 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-/* Upper case range - Wide latin */
-static signed char UniCaseRangeUff40[27] = {
- 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, /* ff40-ff4f */
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
-};
-
-/*
- * Upper Case Range
- */
-const struct UniCaseRange SmbUniUpperRange[] = {
- {0x03a0, 0x03ce, UniCaseRangeU03a0},
- {0x0430, 0x045f, UniCaseRangeU0430},
- {0x0490, 0x04cc, UniCaseRangeU0490},
- {0x1e00, 0x1ffc, UniCaseRangeU1e00},
- {0xff40, 0xff5a, UniCaseRangeUff40},
- {0}
-};
-#endif
-
-#ifndef UNIUPR_NOLOWER
-/*
- * Latin lower case
- */
-signed char CifsUniLowerTable[512] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
- 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, /* 040-04f */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0,
- 0, 0, 0, /* 050-05f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, /* 0c0-0cf */
- 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32,
- 32, 32, 32, 0, /* 0d0-0df */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
- 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
- 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
- 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0,
- 0, /* 170-17f */
- 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79,
- 0, /* 180-18f */
- 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
- 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
- 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
- 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
- 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
- 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
-};
-
-/* Lower case range - Greek */
-static signed char UniCaseRangeL0380[44] = {
- 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
- 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, /* 390-39f */
- 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-};
-
-/* Lower case range - Cyrillic */
-static signed char UniCaseRangeL0400[48] = {
- 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 0, 80, 80, /* 400-40f */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, /* 410-41f */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, /* 420-42f */
-};
-
-/* Lower case range - Extended cyrillic */
-static signed char UniCaseRangeL0490[60] = {
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
- 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
-};
-
-/* Lower case range - Extended latin and greek */
-static signed char UniCaseRangeL1e00[504] = {
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
- 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
- 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
- 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0,
- 0, 0, /* 1fc0-1fcf */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0,
- 0, 0, /* 1fe0-1fef */
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-/* Lower case range - Wide latin */
-static signed char UniCaseRangeLff20[27] = {
- 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, /* ff20-ff2f */
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-};
-
-/*
- * Lower Case Range
- */
-const struct UniCaseRange CifsUniLowerRange[] = {
- {0x0380, 0x03ab, UniCaseRangeL0380},
- {0x0400, 0x042f, UniCaseRangeL0400},
- {0x0490, 0x04cb, UniCaseRangeL0490},
- {0x1e00, 0x1ff7, UniCaseRangeL1e00},
- {0xff20, 0xff3a, UniCaseRangeLff20},
- {0}
-};
-#endif
-
-#endif /* __KSMBD_UNIUPR_H */
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
deleted file mode 100644
index 94b8ed4ef870..000000000000
--- a/fs/ksmbd/vfs.c
+++ /dev/null
@@ -1,1911 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-#include <linux/backing-dev.h>
-#include <linux/writeback.h>
-#include <linux/xattr.h>
-#include <linux/falloc.h>
-#include <linux/fsnotify.h>
-#include <linux/dcache.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/sched/xacct.h>
-#include <linux/crc32c.h>
-
-#include "../internal.h" /* for vfs_path_lookup */
-
-#include "glob.h"
-#include "oplock.h"
-#include "connection.h"
-#include "vfs.h"
-#include "vfs_cache.h"
-#include "smbacl.h"
-#include "ndr.h"
-#include "auth.h"
-#include "misc.h"
-
-#include "smb_common.h"
-#include "mgmt/share_config.h"
-#include "mgmt/tree_connect.h"
-#include "mgmt/user_session.h"
-#include "mgmt/user_config.h"
-
-static char *extract_last_component(char *path)
-{
- char *p = strrchr(path, '/');
-
- if (p && p[1] != '\0') {
- *p = '\0';
- p++;
- } else {
- p = NULL;
- }
- return p;
-}
-
-static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
- struct inode *parent_inode,
- struct inode *inode)
-{
- if (!test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_INHERIT_OWNER))
- return;
-
- i_uid_write(inode, i_uid_read(parent_inode));
-}
-
-/**
- * ksmbd_vfs_lock_parent() - lock parent dentry if it is stable
- *
- * the parent dentry got by dget_parent or @parent could be
- * unstable, we try to lock a parent inode and lookup the
- * child dentry again.
- *
- * the reference count of @parent isn't incremented.
- */
-int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
- struct dentry *child)
-{
- struct dentry *dentry;
- int ret = 0;
-
- inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
- dentry = lookup_one(user_ns, child->d_name.name, parent,
- child->d_name.len);
- if (IS_ERR(dentry)) {
- ret = PTR_ERR(dentry);
- goto out_err;
- }
-
- if (dentry != child) {
- ret = -ESTALE;
- dput(dentry);
- goto out_err;
- }
-
- dput(dentry);
- return 0;
-out_err:
- inode_unlock(d_inode(parent));
- return ret;
-}
-
-int ksmbd_vfs_may_delete(struct user_namespace *user_ns,
- struct dentry *dentry)
-{
- struct dentry *parent;
- int ret;
-
- parent = dget_parent(dentry);
- ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
- if (ret) {
- dput(parent);
- return ret;
- }
-
- ret = inode_permission(user_ns, d_inode(parent),
- MAY_EXEC | MAY_WRITE);
-
- inode_unlock(d_inode(parent));
- dput(parent);
- return ret;
-}
-
-int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
- struct dentry *dentry, __le32 *daccess)
-{
- struct dentry *parent;
- int ret = 0;
-
- *daccess = cpu_to_le32(FILE_READ_ATTRIBUTES | READ_CONTROL);
-
- if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_WRITE))
- *daccess |= cpu_to_le32(WRITE_DAC | WRITE_OWNER | SYNCHRONIZE |
- FILE_WRITE_DATA | FILE_APPEND_DATA |
- FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES |
- FILE_DELETE_CHILD);
-
- if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_READ))
- *daccess |= FILE_READ_DATA_LE | FILE_READ_EA_LE;
-
- if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_EXEC))
- *daccess |= FILE_EXECUTE_LE;
-
- parent = dget_parent(dentry);
- ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
- if (ret) {
- dput(parent);
- return ret;
- }
-
- if (!inode_permission(user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE))
- *daccess |= FILE_DELETE_LE;
-
- inode_unlock(d_inode(parent));
- dput(parent);
- return ret;
-}
-
-/**
- * ksmbd_vfs_create() - vfs helper for smb create file
- * @work: work
- * @name: file name that is relative to share
- * @mode: file create mode
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
-{
- struct path path;
- struct dentry *dentry;
- int err;
-
- dentry = ksmbd_vfs_kern_path_create(work, name,
- LOOKUP_NO_SYMLINKS, &path);
- if (IS_ERR(dentry)) {
- err = PTR_ERR(dentry);
- if (err != -ENOENT)
- pr_err("path create failed for %s, err %d\n",
- name, err);
- return err;
- }
-
- mode |= S_IFREG;
- err = vfs_create(mnt_user_ns(path.mnt), d_inode(path.dentry),
- dentry, mode, true);
- if (!err) {
- ksmbd_vfs_inherit_owner(work, d_inode(path.dentry),
- d_inode(dentry));
- } else {
- pr_err("File(%s): creation failed (err:%d)\n", name, err);
- }
- done_path_create(&path, dentry);
- return err;
-}
-
-/**
- * ksmbd_vfs_mkdir() - vfs helper for smb create directory
- * @work: work
- * @name: directory name that is relative to share
- * @mode: directory create mode
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
-{
- struct user_namespace *user_ns;
- struct path path;
- struct dentry *dentry;
- int err;
-
- dentry = ksmbd_vfs_kern_path_create(work, name,
- LOOKUP_NO_SYMLINKS | LOOKUP_DIRECTORY,
- &path);
- if (IS_ERR(dentry)) {
- err = PTR_ERR(dentry);
- if (err != -EEXIST)
- ksmbd_debug(VFS, "path create failed for %s, err %d\n",
- name, err);
- return err;
- }
-
- user_ns = mnt_user_ns(path.mnt);
- mode |= S_IFDIR;
- err = vfs_mkdir(user_ns, d_inode(path.dentry), dentry, mode);
- if (err) {
- goto out;
- } else if (d_unhashed(dentry)) {
- struct dentry *d;
-
- d = lookup_one(user_ns, dentry->d_name.name, dentry->d_parent,
- dentry->d_name.len);
- if (IS_ERR(d)) {
- err = PTR_ERR(d);
- goto out;
- }
- if (unlikely(d_is_negative(d))) {
- dput(d);
- err = -ENOENT;
- goto out;
- }
-
- ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(d));
- dput(d);
- }
-out:
- done_path_create(&path, dentry);
- if (err)
- pr_err("mkdir(%s): creation failed (err:%d)\n", name, err);
- return err;
-}
-
-static ssize_t ksmbd_vfs_getcasexattr(struct user_namespace *user_ns,
- struct dentry *dentry, char *attr_name,
- int attr_name_len, char **attr_value)
-{
- char *name, *xattr_list = NULL;
- ssize_t value_len = -ENOENT, xattr_list_len;
-
- xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
- if (xattr_list_len <= 0)
- goto out;
-
- for (name = xattr_list; name - xattr_list < xattr_list_len;
- name += strlen(name) + 1) {
- ksmbd_debug(VFS, "%s, len %zd\n", name, strlen(name));
- if (strncasecmp(attr_name, name, attr_name_len))
- continue;
-
- value_len = ksmbd_vfs_getxattr(user_ns,
- dentry,
- name,
- attr_value);
- if (value_len < 0)
- pr_err("failed to get xattr in file\n");
- break;
- }
-
-out:
- kvfree(xattr_list);
- return value_len;
-}
-
-static int ksmbd_vfs_stream_read(struct ksmbd_file *fp, char *buf, loff_t *pos,
- size_t count)
-{
- ssize_t v_len;
- char *stream_buf = NULL;
-
- ksmbd_debug(VFS, "read stream data pos : %llu, count : %zd\n",
- *pos, count);
-
- v_len = ksmbd_vfs_getcasexattr(file_mnt_user_ns(fp->filp),
- fp->filp->f_path.dentry,
- fp->stream.name,
- fp->stream.size,
- &stream_buf);
- if ((int)v_len <= 0)
- return (int)v_len;
-
- if (v_len <= *pos) {
- count = -EINVAL;
- goto free_buf;
- }
-
- if (v_len - *pos < count)
- count = v_len - *pos;
-
- memcpy(buf, &stream_buf[*pos], count);
-
-free_buf:
- kvfree(stream_buf);
- return count;
-}
-
-/**
- * check_lock_range() - vfs helper for smb byte range file locking
- * @filp: the file to apply the lock to
- * @start: lock start byte offset
- * @end: lock end byte offset
- * @type: byte range type read/write
- *
- * Return: 0 on success, otherwise error
- */
-static int check_lock_range(struct file *filp, loff_t start, loff_t end,
- unsigned char type)
-{
- struct file_lock *flock;
- struct file_lock_context *ctx = file_inode(filp)->i_flctx;
- int error = 0;
-
- if (!ctx || list_empty_careful(&ctx->flc_posix))
- return 0;
-
- spin_lock(&ctx->flc_lock);
- list_for_each_entry(flock, &ctx->flc_posix, fl_list) {
- /* check conflict locks */
- if (flock->fl_end >= start && end >= flock->fl_start) {
- if (flock->fl_type == F_RDLCK) {
- if (type == WRITE) {
- pr_err("not allow write by shared lock\n");
- error = 1;
- goto out;
- }
- } else if (flock->fl_type == F_WRLCK) {
- /* check owner in lock */
- if (flock->fl_file != filp) {
- error = 1;
- pr_err("not allow rw access by exclusive lock from other opens\n");
- goto out;
- }
- }
- }
- }
-out:
- spin_unlock(&ctx->flc_lock);
- return error;
-}
-
-/**
- * ksmbd_vfs_read() - vfs helper for smb file read
- * @work: smb work
- * @fid: file id of open file
- * @count: read byte count
- * @pos: file pos
- *
- * Return: number of read bytes on success, otherwise error
- */
-int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
- loff_t *pos)
-{
- struct file *filp = fp->filp;
- ssize_t nbytes = 0;
- char *rbuf = work->aux_payload_buf;
- struct inode *inode = file_inode(filp);
-
- if (S_ISDIR(inode->i_mode))
- return -EISDIR;
-
- if (unlikely(count == 0))
- return 0;
-
- if (work->conn->connection_type) {
- if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
- pr_err("no right to read(%pD)\n", fp->filp);
- return -EACCES;
- }
- }
-
- if (ksmbd_stream_fd(fp))
- return ksmbd_vfs_stream_read(fp, rbuf, pos, count);
-
- if (!work->tcon->posix_extensions) {
- int ret;
-
- ret = check_lock_range(filp, *pos, *pos + count - 1, READ);
- if (ret) {
- pr_err("unable to read due to lock\n");
- return -EAGAIN;
- }
- }
-
- nbytes = kernel_read(filp, rbuf, count, pos);
- if (nbytes < 0) {
- pr_err("smb read failed, err = %zd\n", nbytes);
- return nbytes;
- }
-
- filp->f_pos = *pos;
- return nbytes;
-}
-
-static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
- size_t count)
-{
- char *stream_buf = NULL, *wbuf;
- struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
- size_t size, v_len;
- int err = 0;
-
- ksmbd_debug(VFS, "write stream data pos : %llu, count : %zd\n",
- *pos, count);
-
- size = *pos + count;
- if (size > XATTR_SIZE_MAX) {
- size = XATTR_SIZE_MAX;
- count = (*pos + count) - XATTR_SIZE_MAX;
- }
-
- v_len = ksmbd_vfs_getcasexattr(user_ns,
- fp->filp->f_path.dentry,
- fp->stream.name,
- fp->stream.size,
- &stream_buf);
- if ((int)v_len < 0) {
- pr_err("not found stream in xattr : %zd\n", v_len);
- err = (int)v_len;
- goto out;
- }
-
- if (v_len < size) {
- wbuf = kvmalloc(size, GFP_KERNEL | __GFP_ZERO);
- if (!wbuf) {
- err = -ENOMEM;
- goto out;
- }
-
- if (v_len > 0)
- memcpy(wbuf, stream_buf, v_len);
- kvfree(stream_buf);
- stream_buf = wbuf;
- }
-
- memcpy(&stream_buf[*pos], buf, count);
-
- err = ksmbd_vfs_setxattr(user_ns,
- fp->filp->f_path.dentry,
- fp->stream.name,
- (void *)stream_buf,
- size,
- 0);
- if (err < 0)
- goto out;
-
- fp->filp->f_pos = *pos;
- err = 0;
-out:
- kvfree(stream_buf);
- return err;
-}
-
-/**
- * ksmbd_vfs_write() - vfs helper for smb file write
- * @work: work
- * @fid: file id of open file
- * @buf: buf containing data for writing
- * @count: read byte count
- * @pos: file pos
- * @sync: fsync after write
- * @written: number of bytes written
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
- char *buf, size_t count, loff_t *pos, bool sync,
- ssize_t *written)
-{
- struct file *filp;
- loff_t offset = *pos;
- int err = 0;
-
- if (work->conn->connection_type) {
- if (!(fp->daccess & FILE_WRITE_DATA_LE)) {
- pr_err("no right to write(%pD)\n", fp->filp);
- err = -EACCES;
- goto out;
- }
- }
-
- filp = fp->filp;
-
- if (ksmbd_stream_fd(fp)) {
- err = ksmbd_vfs_stream_write(fp, buf, pos, count);
- if (!err)
- *written = count;
- goto out;
- }
-
- if (!work->tcon->posix_extensions) {
- err = check_lock_range(filp, *pos, *pos + count - 1, WRITE);
- if (err) {
- pr_err("unable to write due to lock\n");
- err = -EAGAIN;
- goto out;
- }
- }
-
- /* Do we need to break any of a levelII oplock? */
- smb_break_all_levII_oplock(work, fp, 1);
-
- err = kernel_write(filp, buf, count, pos);
- if (err < 0) {
- ksmbd_debug(VFS, "smb write failed, err = %d\n", err);
- goto out;
- }
-
- filp->f_pos = *pos;
- *written = err;
- err = 0;
- if (sync) {
- err = vfs_fsync_range(filp, offset, offset + *written, 0);
- if (err < 0)
- pr_err("fsync failed for filename = %pD, err = %d\n",
- fp->filp, err);
- }
-
-out:
- return err;
-}
-
-/**
- * ksmbd_vfs_getattr() - vfs helper for smb getattr
- * @work: work
- * @fid: file id of open file
- * @attrs: inode attributes
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat)
-{
- int err;
-
- err = vfs_getattr(path, stat, STATX_BTIME, AT_STATX_SYNC_AS_STAT);
- if (err)
- pr_err("getattr failed, err %d\n", err);
- return err;
-}
-
-/**
- * ksmbd_vfs_fsync() - vfs helper for smb fsync
- * @work: work
- * @fid: file id of open file
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
-{
- struct ksmbd_file *fp;
- int err;
-
- fp = ksmbd_lookup_fd_slow(work, fid, p_id);
- if (!fp) {
- pr_err("failed to get filp for fid %llu\n", fid);
- return -ENOENT;
- }
- err = vfs_fsync(fp->filp, 0);
- if (err < 0)
- pr_err("smb fsync failed, err = %d\n", err);
- ksmbd_fd_put(work, fp);
- return err;
-}
-
-/**
- * ksmbd_vfs_remove_file() - vfs helper for smb rmdir or unlink
- * @name: directory or file name that is relative to share
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
-{
- struct user_namespace *user_ns;
- struct path path;
- struct dentry *parent;
- int err;
-
- if (ksmbd_override_fsids(work))
- return -ENOMEM;
-
- err = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS, &path, false);
- if (err) {
- ksmbd_debug(VFS, "can't get %s, err %d\n", name, err);
- ksmbd_revert_fsids(work);
- return err;
- }
-
- user_ns = mnt_user_ns(path.mnt);
- parent = dget_parent(path.dentry);
- err = ksmbd_vfs_lock_parent(user_ns, parent, path.dentry);
- if (err) {
- dput(parent);
- path_put(&path);
- ksmbd_revert_fsids(work);
- return err;
- }
-
- if (!d_inode(path.dentry)->i_nlink) {
- err = -ENOENT;
- goto out_err;
- }
-
- if (S_ISDIR(d_inode(path.dentry)->i_mode)) {
- err = vfs_rmdir(user_ns, d_inode(parent), path.dentry);
- if (err && err != -ENOTEMPTY)
- ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
- err);
- } else {
- err = vfs_unlink(user_ns, d_inode(parent), path.dentry, NULL);
- if (err)
- ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
- err);
- }
-
-out_err:
- inode_unlock(d_inode(parent));
- dput(parent);
- path_put(&path);
- ksmbd_revert_fsids(work);
- return err;
-}
-
-/**
- * ksmbd_vfs_link() - vfs helper for creating smb hardlink
- * @oldname: source file name
- * @newname: hardlink name that is relative to share
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
- const char *newname)
-{
- struct path oldpath, newpath;
- struct dentry *dentry;
- int err;
-
- if (ksmbd_override_fsids(work))
- return -ENOMEM;
-
- err = kern_path(oldname, LOOKUP_NO_SYMLINKS, &oldpath);
- if (err) {
- pr_err("cannot get linux path for %s, err = %d\n",
- oldname, err);
- goto out1;
- }
-
- dentry = ksmbd_vfs_kern_path_create(work, newname,
- LOOKUP_NO_SYMLINKS | LOOKUP_REVAL,
- &newpath);
- if (IS_ERR(dentry)) {
- err = PTR_ERR(dentry);
- pr_err("path create err for %s, err %d\n", newname, err);
- goto out2;
- }
-
- err = -EXDEV;
- if (oldpath.mnt != newpath.mnt) {
- pr_err("vfs_link failed err %d\n", err);
- goto out3;
- }
-
- err = vfs_link(oldpath.dentry, mnt_user_ns(newpath.mnt),
- d_inode(newpath.dentry),
- dentry, NULL);
- if (err)
- ksmbd_debug(VFS, "vfs_link failed err %d\n", err);
-
-out3:
- done_path_create(&newpath, dentry);
-out2:
- path_put(&oldpath);
-out1:
- ksmbd_revert_fsids(work);
- return err;
-}
-
-static int ksmbd_validate_entry_in_use(struct dentry *src_dent)
-{
- struct dentry *dst_dent;
-
- spin_lock(&src_dent->d_lock);
- list_for_each_entry(dst_dent, &src_dent->d_subdirs, d_child) {
- struct ksmbd_file *child_fp;
-
- if (d_really_is_negative(dst_dent))
- continue;
-
- child_fp = ksmbd_lookup_fd_inode(d_inode(dst_dent));
- if (child_fp) {
- spin_unlock(&src_dent->d_lock);
- ksmbd_debug(VFS, "Forbid rename, sub file/dir is in use\n");
- return -EACCES;
- }
- }
- spin_unlock(&src_dent->d_lock);
-
- return 0;
-}
-
-static int __ksmbd_vfs_rename(struct ksmbd_work *work,
- struct user_namespace *src_user_ns,
- struct dentry *src_dent_parent,
- struct dentry *src_dent,
- struct user_namespace *dst_user_ns,
- struct dentry *dst_dent_parent,
- struct dentry *trap_dent,
- char *dst_name)
-{
- struct dentry *dst_dent;
- int err;
-
- if (!work->tcon->posix_extensions) {
- err = ksmbd_validate_entry_in_use(src_dent);
- if (err)
- return err;
- }
-
- if (d_really_is_negative(src_dent_parent))
- return -ENOENT;
- if (d_really_is_negative(dst_dent_parent))
- return -ENOENT;
- if (d_really_is_negative(src_dent))
- return -ENOENT;
- if (src_dent == trap_dent)
- return -EINVAL;
-
- if (ksmbd_override_fsids(work))
- return -ENOMEM;
-
- dst_dent = lookup_one(dst_user_ns, dst_name, dst_dent_parent,
- strlen(dst_name));
- err = PTR_ERR(dst_dent);
- if (IS_ERR(dst_dent)) {
- pr_err("lookup failed %s [%d]\n", dst_name, err);
- goto out;
- }
-
- err = -ENOTEMPTY;
- if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
- struct renamedata rd = {
- .old_mnt_userns = src_user_ns,
- .old_dir = d_inode(src_dent_parent),
- .old_dentry = src_dent,
- .new_mnt_userns = dst_user_ns,
- .new_dir = d_inode(dst_dent_parent),
- .new_dentry = dst_dent,
- };
- err = vfs_rename(&rd);
- }
- if (err)
- pr_err("vfs_rename failed err %d\n", err);
- if (dst_dent)
- dput(dst_dent);
-out:
- ksmbd_revert_fsids(work);
- return err;
-}
-
-int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
- char *newname)
-{
- struct user_namespace *user_ns;
- struct path dst_path;
- struct dentry *src_dent_parent, *dst_dent_parent;
- struct dentry *src_dent, *trap_dent, *src_child;
- char *dst_name;
- int err;
-
- dst_name = extract_last_component(newname);
- if (!dst_name) {
- dst_name = newname;
- newname = "";
- }
-
- src_dent_parent = dget_parent(fp->filp->f_path.dentry);
- src_dent = fp->filp->f_path.dentry;
-
- err = ksmbd_vfs_kern_path(work, newname,
- LOOKUP_NO_SYMLINKS | LOOKUP_DIRECTORY,
- &dst_path, false);
- if (err) {
- ksmbd_debug(VFS, "Cannot get path for %s [%d]\n", newname, err);
- goto out;
- }
- dst_dent_parent = dst_path.dentry;
-
- trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
- dget(src_dent);
- dget(dst_dent_parent);
- user_ns = file_mnt_user_ns(fp->filp);
- src_child = lookup_one(user_ns, src_dent->d_name.name, src_dent_parent,
- src_dent->d_name.len);
- if (IS_ERR(src_child)) {
- err = PTR_ERR(src_child);
- goto out_lock;
- }
-
- if (src_child != src_dent) {
- err = -ESTALE;
- dput(src_child);
- goto out_lock;
- }
- dput(src_child);
-
- err = __ksmbd_vfs_rename(work,
- user_ns,
- src_dent_parent,
- src_dent,
- mnt_user_ns(dst_path.mnt),
- dst_dent_parent,
- trap_dent,
- dst_name);
-out_lock:
- dput(src_dent);
- dput(dst_dent_parent);
- unlock_rename(src_dent_parent, dst_dent_parent);
- path_put(&dst_path);
-out:
- dput(src_dent_parent);
- return err;
-}
-
-/**
- * ksmbd_vfs_truncate() - vfs helper for smb file truncate
- * @work: work
- * @fid: file id of old file
- * @size: truncate to given size
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_truncate(struct ksmbd_work *work,
- struct ksmbd_file *fp, loff_t size)
-{
- int err = 0;
- struct file *filp;
-
- filp = fp->filp;
-
- /* Do we need to break any of a levelII oplock? */
- smb_break_all_levII_oplock(work, fp, 1);
-
- if (!work->tcon->posix_extensions) {
- struct inode *inode = file_inode(filp);
-
- if (size < inode->i_size) {
- err = check_lock_range(filp, size,
- inode->i_size - 1, WRITE);
- } else {
- err = check_lock_range(filp, inode->i_size,
- size - 1, WRITE);
- }
-
- if (err) {
- pr_err("failed due to lock\n");
- return -EAGAIN;
- }
- }
-
- err = vfs_truncate(&filp->f_path, size);
- if (err)
- pr_err("truncate failed, err %d\n", err);
- return err;
-}
-
-/**
- * ksmbd_vfs_listxattr() - vfs helper for smb list extended attributes
- * @dentry: dentry of file for listing xattrs
- * @list: destination buffer
- * @size: destination buffer length
- *
- * Return: xattr list length on success, otherwise error
- */
-ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list)
-{
- ssize_t size;
- char *vlist = NULL;
-
- size = vfs_listxattr(dentry, NULL, 0);
- if (size <= 0)
- return size;
-
- vlist = kvmalloc(size, GFP_KERNEL | __GFP_ZERO);
- if (!vlist)
- return -ENOMEM;
-
- *list = vlist;
- size = vfs_listxattr(dentry, vlist, size);
- if (size < 0) {
- ksmbd_debug(VFS, "listxattr failed\n");
- kvfree(vlist);
- *list = NULL;
- }
-
- return size;
-}
-
-static ssize_t ksmbd_vfs_xattr_len(struct user_namespace *user_ns,
- struct dentry *dentry, char *xattr_name)
-{
- return vfs_getxattr(user_ns, dentry, xattr_name, NULL, 0);
-}
-
-/**
- * ksmbd_vfs_getxattr() - vfs helper for smb get extended attributes value
- * @user_ns: user namespace
- * @dentry: dentry of file for getting xattrs
- * @xattr_name: name of xattr name to query
- * @xattr_buf: destination buffer xattr value
- *
- * Return: read xattr value length on success, otherwise error
- */
-ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
- struct dentry *dentry,
- char *xattr_name, char **xattr_buf)
-{
- ssize_t xattr_len;
- char *buf;
-
- *xattr_buf = NULL;
- xattr_len = ksmbd_vfs_xattr_len(user_ns, dentry, xattr_name);
- if (xattr_len < 0)
- return xattr_len;
-
- buf = kmalloc(xattr_len + 1, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- xattr_len = vfs_getxattr(user_ns, dentry, xattr_name,
- (void *)buf, xattr_len);
- if (xattr_len > 0)
- *xattr_buf = buf;
- else
- kfree(buf);
- return xattr_len;
-}
-
-/**
- * ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value
- * @user_ns: user namespace
- * @dentry: dentry to set XATTR at
- * @name: xattr name for setxattr
- * @value: xattr value to set
- * @size: size of xattr value
- * @flags: destination buffer length
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
- struct dentry *dentry, const char *attr_name,
- void *attr_value, size_t attr_size, int flags)
-{
- int err;
-
- err = vfs_setxattr(user_ns,
- dentry,
- attr_name,
- attr_value,
- attr_size,
- flags);
- if (err)
- ksmbd_debug(VFS, "setxattr failed, err %d\n", err);
- return err;
-}
-
-/**
- * ksmbd_vfs_set_fadvise() - convert smb IO caching options to linux options
- * @filp: file pointer for IO
- * @options: smb IO options
- */
-void ksmbd_vfs_set_fadvise(struct file *filp, __le32 option)
-{
- struct address_space *mapping;
-
- mapping = filp->f_mapping;
-
- if (!option || !mapping)
- return;
-
- if (option & FILE_WRITE_THROUGH_LE) {
- filp->f_flags |= O_SYNC;
- } else if (option & FILE_SEQUENTIAL_ONLY_LE) {
- filp->f_ra.ra_pages = inode_to_bdi(mapping->host)->ra_pages * 2;
- spin_lock(&filp->f_lock);
- filp->f_mode &= ~FMODE_RANDOM;
- spin_unlock(&filp->f_lock);
- } else if (option & FILE_RANDOM_ACCESS_LE) {
- spin_lock(&filp->f_lock);
- filp->f_mode |= FMODE_RANDOM;
- spin_unlock(&filp->f_lock);
- }
-}
-
-int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
- loff_t off, loff_t len)
-{
- smb_break_all_levII_oplock(work, fp, 1);
- if (fp->f_ci->m_fattr & FILE_ATTRIBUTE_SPARSE_FILE_LE)
- return vfs_fallocate(fp->filp,
- FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
- off, len);
-
- return vfs_fallocate(fp->filp,
- FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
- off, len);
-}
-
-int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
- struct file_allocated_range_buffer *ranges,
- unsigned int in_count, unsigned int *out_count)
-{
- struct file *f = fp->filp;
- struct inode *inode = file_inode(fp->filp);
- loff_t maxbytes = (u64)inode->i_sb->s_maxbytes, end;
- loff_t extent_start, extent_end;
- int ret = 0;
-
- if (start > maxbytes)
- return -EFBIG;
-
- if (!in_count)
- return 0;
-
- /*
- * Shrink request scope to what the fs can actually handle.
- */
- if (length > maxbytes || (maxbytes - length) < start)
- length = maxbytes - start;
-
- if (start + length > inode->i_size)
- length = inode->i_size - start;
-
- *out_count = 0;
- end = start + length;
- while (start < end && *out_count < in_count) {
- extent_start = vfs_llseek(f, start, SEEK_DATA);
- if (extent_start < 0) {
- if (extent_start != -ENXIO)
- ret = (int)extent_start;
- break;
- }
-
- if (extent_start >= end)
- break;
-
- extent_end = vfs_llseek(f, extent_start, SEEK_HOLE);
- if (extent_end < 0) {
- if (extent_end != -ENXIO)
- ret = (int)extent_end;
- break;
- } else if (extent_start >= extent_end) {
- break;
- }
-
- ranges[*out_count].file_offset = cpu_to_le64(extent_start);
- ranges[(*out_count)++].length =
- cpu_to_le64(min(extent_end, end) - extent_start);
-
- start = extent_end;
- }
-
- return ret;
-}
-
-int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
- struct dentry *dentry, char *attr_name)
-{
- return vfs_removexattr(user_ns, dentry, attr_name);
-}
-
-int ksmbd_vfs_unlink(struct user_namespace *user_ns,
- struct dentry *dir, struct dentry *dentry)
-{
- int err = 0;
-
- err = ksmbd_vfs_lock_parent(user_ns, dir, dentry);
- if (err)
- return err;
- dget(dentry);
-
- if (S_ISDIR(d_inode(dentry)->i_mode))
- err = vfs_rmdir(user_ns, d_inode(dir), dentry);
- else
- err = vfs_unlink(user_ns, d_inode(dir), dentry, NULL);
-
- dput(dentry);
- inode_unlock(d_inode(dir));
- if (err)
- ksmbd_debug(VFS, "failed to delete, err %d\n", err);
-
- return err;
-}
-
-static bool __dir_empty(struct dir_context *ctx, const char *name, int namlen,
- loff_t offset, u64 ino, unsigned int d_type)
-{
- struct ksmbd_readdir_data *buf;
-
- buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
- buf->dirent_count++;
-
- return buf->dirent_count <= 2;
-}
-
-/**
- * ksmbd_vfs_empty_dir() - check for empty directory
- * @fp: ksmbd file pointer
- *
- * Return: true if directory empty, otherwise false
- */
-int ksmbd_vfs_empty_dir(struct ksmbd_file *fp)
-{
- int err;
- struct ksmbd_readdir_data readdir_data;
-
- memset(&readdir_data, 0, sizeof(struct ksmbd_readdir_data));
-
- set_ctx_actor(&readdir_data.ctx, __dir_empty);
- readdir_data.dirent_count = 0;
-
- err = iterate_dir(fp->filp, &readdir_data.ctx);
- if (readdir_data.dirent_count > 2)
- err = -ENOTEMPTY;
- else
- err = 0;
- return err;
-}
-
-static bool __caseless_lookup(struct dir_context *ctx, const char *name,
- int namlen, loff_t offset, u64 ino,
- unsigned int d_type)
-{
- struct ksmbd_readdir_data *buf;
- int cmp = -EINVAL;
-
- buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
-
- if (buf->used != namlen)
- return true;
- if (IS_ENABLED(CONFIG_UNICODE) && buf->um) {
- const struct qstr q_buf = {.name = buf->private,
- .len = buf->used};
- const struct qstr q_name = {.name = name,
- .len = namlen};
-
- cmp = utf8_strncasecmp(buf->um, &q_buf, &q_name);
- }
- if (cmp < 0)
- cmp = strncasecmp((char *)buf->private, name, namlen);
- if (!cmp) {
- memcpy((char *)buf->private, name, namlen);
- buf->dirent_count = 1;
- return false;
- }
- return true;
-}
-
-/**
- * ksmbd_vfs_lookup_in_dir() - lookup a file in a directory
- * @dir: path info
- * @name: filename to lookup
- * @namelen: filename length
- *
- * Return: 0 on success, otherwise error
- */
-static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
- size_t namelen, struct unicode_map *um)
-{
- int ret;
- struct file *dfilp;
- int flags = O_RDONLY | O_LARGEFILE;
- struct ksmbd_readdir_data readdir_data = {
- .ctx.actor = __caseless_lookup,
- .private = name,
- .used = namelen,
- .dirent_count = 0,
- .um = um,
- };
-
- dfilp = dentry_open(dir, flags, current_cred());
- if (IS_ERR(dfilp))
- return PTR_ERR(dfilp);
-
- ret = iterate_dir(dfilp, &readdir_data.ctx);
- if (readdir_data.dirent_count > 0)
- ret = 0;
- fput(dfilp);
- return ret;
-}
-
-/**
- * ksmbd_vfs_kern_path() - lookup a file and get path info
- * @name: file path that is relative to share
- * @flags: lookup flags
- * @path: if lookup succeed, return path info
- * @caseless: caseless filename lookup
- *
- * Return: 0 on success, otherwise error
- */
-int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
- unsigned int flags, struct path *path, bool caseless)
-{
- struct ksmbd_share_config *share_conf = work->tcon->share_conf;
- int err;
-
- flags |= LOOKUP_BENEATH;
- err = vfs_path_lookup(share_conf->vfs_path.dentry,
- share_conf->vfs_path.mnt,
- name,
- flags,
- path);
- if (!err)
- return 0;
-
- if (caseless) {
- char *filepath;
- struct path parent;
- size_t path_len, remain_len;
-
- filepath = kstrdup(name, GFP_KERNEL);
- if (!filepath)
- return -ENOMEM;
-
- path_len = strlen(filepath);
- remain_len = path_len;
-
- parent = share_conf->vfs_path;
- path_get(&parent);
-
- while (d_can_lookup(parent.dentry)) {
- char *filename = filepath + path_len - remain_len;
- char *next = strchrnul(filename, '/');
- size_t filename_len = next - filename;
- bool is_last = !next[0];
-
- if (filename_len == 0)
- break;
-
- err = ksmbd_vfs_lookup_in_dir(&parent, filename,
- filename_len,
- work->conn->um);
- path_put(&parent);
- if (err)
- goto out;
-
- next[0] = '\0';
-
- err = vfs_path_lookup(share_conf->vfs_path.dentry,
- share_conf->vfs_path.mnt,
- filepath,
- flags,
- &parent);
- if (err)
- goto out;
- else if (is_last) {
- *path = parent;
- goto out;
- }
-
- next[0] = '/';
- remain_len -= filename_len + 1;
- }
-
- path_put(&parent);
- err = -EINVAL;
-out:
- kfree(filepath);
- }
- return err;
-}
-
-struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
- const char *name,
- unsigned int flags,
- struct path *path)
-{
- char *abs_name;
- struct dentry *dent;
-
- abs_name = convert_to_unix_name(work->tcon->share_conf, name);
- if (!abs_name)
- return ERR_PTR(-ENOMEM);
-
- dent = kern_path_create(AT_FDCWD, abs_name, path, flags);
- kfree(abs_name);
- return dent;
-}
-
-int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
- struct dentry *dentry)
-{
- char *name, *xattr_list = NULL;
- ssize_t xattr_list_len;
- int err = 0;
-
- xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
- if (xattr_list_len < 0) {
- goto out;
- } else if (!xattr_list_len) {
- ksmbd_debug(SMB, "empty xattr in the file\n");
- goto out;
- }
-
- for (name = xattr_list; name - xattr_list < xattr_list_len;
- name += strlen(name) + 1) {
- ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
-
- if (!strncmp(name, XATTR_NAME_POSIX_ACL_ACCESS,
- sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) ||
- !strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
- sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) {
- err = ksmbd_vfs_remove_xattr(user_ns, dentry, name);
- if (err)
- ksmbd_debug(SMB,
- "remove acl xattr failed : %s\n", name);
- }
- }
-out:
- kvfree(xattr_list);
- return err;
-}
-
-int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns,
- struct dentry *dentry)
-{
- char *name, *xattr_list = NULL;
- ssize_t xattr_list_len;
- int err = 0;
-
- xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
- if (xattr_list_len < 0) {
- goto out;
- } else if (!xattr_list_len) {
- ksmbd_debug(SMB, "empty xattr in the file\n");
- goto out;
- }
-
- for (name = xattr_list; name - xattr_list < xattr_list_len;
- name += strlen(name) + 1) {
- ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
-
- if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) {
- err = ksmbd_vfs_remove_xattr(user_ns, dentry, name);
- if (err)
- ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
- }
- }
-out:
- kvfree(xattr_list);
- return err;
-}
-
-static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespace *user_ns,
- struct inode *inode,
- int acl_type)
-{
- struct xattr_smb_acl *smb_acl = NULL;
- struct posix_acl *posix_acls;
- struct posix_acl_entry *pa_entry;
- struct xattr_acl_entry *xa_entry;
- int i;
-
- if (!IS_ENABLED(CONFIG_FS_POSIX_ACL))
- return NULL;
-
- posix_acls = get_acl(inode, acl_type);
- if (!posix_acls)
- return NULL;
-
- smb_acl = kzalloc(sizeof(struct xattr_smb_acl) +
- sizeof(struct xattr_acl_entry) * posix_acls->a_count,
- GFP_KERNEL);
- if (!smb_acl)
- goto out;
-
- smb_acl->count = posix_acls->a_count;
- pa_entry = posix_acls->a_entries;
- xa_entry = smb_acl->entries;
- for (i = 0; i < posix_acls->a_count; i++, pa_entry++, xa_entry++) {
- switch (pa_entry->e_tag) {
- case ACL_USER:
- xa_entry->type = SMB_ACL_USER;
- xa_entry->uid = posix_acl_uid_translate(user_ns, pa_entry);
- break;
- case ACL_USER_OBJ:
- xa_entry->type = SMB_ACL_USER_OBJ;
- break;
- case ACL_GROUP:
- xa_entry->type = SMB_ACL_GROUP;
- xa_entry->gid = posix_acl_gid_translate(user_ns, pa_entry);
- break;
- case ACL_GROUP_OBJ:
- xa_entry->type = SMB_ACL_GROUP_OBJ;
- break;
- case ACL_OTHER:
- xa_entry->type = SMB_ACL_OTHER;
- break;
- case ACL_MASK:
- xa_entry->type = SMB_ACL_MASK;
- break;
- default:
- pr_err("unknown type : 0x%x\n", pa_entry->e_tag);
- goto out;
- }
-
- if (pa_entry->e_perm & ACL_READ)
- xa_entry->perm |= SMB_ACL_READ;
- if (pa_entry->e_perm & ACL_WRITE)
- xa_entry->perm |= SMB_ACL_WRITE;
- if (pa_entry->e_perm & ACL_EXECUTE)
- xa_entry->perm |= SMB_ACL_EXECUTE;
- }
-out:
- posix_acl_release(posix_acls);
- return smb_acl;
-}
-
-int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
- struct user_namespace *user_ns,
- struct dentry *dentry,
- struct smb_ntsd *pntsd, int len)
-{
- int rc;
- struct ndr sd_ndr = {0}, acl_ndr = {0};
- struct xattr_ntacl acl = {0};
- struct xattr_smb_acl *smb_acl, *def_smb_acl = NULL;
- struct inode *inode = d_inode(dentry);
-
- acl.version = 4;
- acl.hash_type = XATTR_SD_HASH_TYPE_SHA256;
- acl.current_time = ksmbd_UnixTimeToNT(current_time(inode));
-
- memcpy(acl.desc, "posix_acl", 9);
- acl.desc_len = 10;
-
- pntsd->osidoffset =
- cpu_to_le32(le32_to_cpu(pntsd->osidoffset) + NDR_NTSD_OFFSETOF);
- pntsd->gsidoffset =
- cpu_to_le32(le32_to_cpu(pntsd->gsidoffset) + NDR_NTSD_OFFSETOF);
- pntsd->dacloffset =
- cpu_to_le32(le32_to_cpu(pntsd->dacloffset) + NDR_NTSD_OFFSETOF);
-
- acl.sd_buf = (char *)pntsd;
- acl.sd_size = len;
-
- rc = ksmbd_gen_sd_hash(conn, acl.sd_buf, acl.sd_size, acl.hash);
- if (rc) {
- pr_err("failed to generate hash for ndr acl\n");
- return rc;
- }
-
- smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
- ACL_TYPE_ACCESS);
- if (S_ISDIR(inode->i_mode))
- def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
- ACL_TYPE_DEFAULT);
-
- rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode,
- smb_acl, def_smb_acl);
- if (rc) {
- pr_err("failed to encode ndr to posix acl\n");
- goto out;
- }
-
- rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset,
- acl.posix_acl_hash);
- if (rc) {
- pr_err("failed to generate hash for ndr acl\n");
- goto out;
- }
-
- rc = ndr_encode_v4_ntacl(&sd_ndr, &acl);
- if (rc) {
- pr_err("failed to encode ndr to posix acl\n");
- goto out;
- }
-
- rc = ksmbd_vfs_setxattr(user_ns, dentry,
- XATTR_NAME_SD, sd_ndr.data,
- sd_ndr.offset, 0);
- if (rc < 0)
- pr_err("Failed to store XATTR ntacl :%d\n", rc);
-
- kfree(sd_ndr.data);
-out:
- kfree(acl_ndr.data);
- kfree(smb_acl);
- kfree(def_smb_acl);
- return rc;
-}
-
-int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
- struct user_namespace *user_ns,
- struct dentry *dentry,
- struct smb_ntsd **pntsd)
-{
- int rc;
- struct ndr n;
- struct inode *inode = d_inode(dentry);
- struct ndr acl_ndr = {0};
- struct xattr_ntacl acl;
- struct xattr_smb_acl *smb_acl = NULL, *def_smb_acl = NULL;
- __u8 cmp_hash[XATTR_SD_HASH_SIZE] = {0};
-
- rc = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_SD, &n.data);
- if (rc <= 0)
- return rc;
-
- n.length = rc;
- rc = ndr_decode_v4_ntacl(&n, &acl);
- if (rc)
- goto free_n_data;
-
- smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
- ACL_TYPE_ACCESS);
- if (S_ISDIR(inode->i_mode))
- def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
- ACL_TYPE_DEFAULT);
-
- rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode, smb_acl,
- def_smb_acl);
- if (rc) {
- pr_err("failed to encode ndr to posix acl\n");
- goto out_free;
- }
-
- rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset, cmp_hash);
- if (rc) {
- pr_err("failed to generate hash for ndr acl\n");
- goto out_free;
- }
-
- if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) {
- pr_err("hash value diff\n");
- rc = -EINVAL;
- goto out_free;
- }
-
- *pntsd = acl.sd_buf;
- if (acl.sd_size < sizeof(struct smb_ntsd)) {
- pr_err("sd size is invalid\n");
- goto out_free;
- }
-
- (*pntsd)->osidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) -
- NDR_NTSD_OFFSETOF);
- (*pntsd)->gsidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) -
- NDR_NTSD_OFFSETOF);
- (*pntsd)->dacloffset = cpu_to_le32(le32_to_cpu((*pntsd)->dacloffset) -
- NDR_NTSD_OFFSETOF);
-
- rc = acl.sd_size;
-out_free:
- kfree(acl_ndr.data);
- kfree(smb_acl);
- kfree(def_smb_acl);
- if (rc < 0) {
- kfree(acl.sd_buf);
- *pntsd = NULL;
- }
-
-free_n_data:
- kfree(n.data);
- return rc;
-}
-
-int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
- struct dentry *dentry,
- struct xattr_dos_attrib *da)
-{
- struct ndr n;
- int err;
-
- err = ndr_encode_dos_attr(&n, da);
- if (err)
- return err;
-
- err = ksmbd_vfs_setxattr(user_ns, dentry, XATTR_NAME_DOS_ATTRIBUTE,
- (void *)n.data, n.offset, 0);
- if (err)
- ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
- kfree(n.data);
-
- return err;
-}
-
-int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns,
- struct dentry *dentry,
- struct xattr_dos_attrib *da)
-{
- struct ndr n;
- int err;
-
- err = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_DOS_ATTRIBUTE,
- (char **)&n.data);
- if (err > 0) {
- n.length = err;
- if (ndr_decode_dos_attr(&n, da))
- err = -EINVAL;
- kfree(n.data);
- } else {
- ksmbd_debug(SMB, "failed to load dos attribute in xattr\n");
- }
-
- return err;
-}
-
-/**
- * ksmbd_vfs_init_kstat() - convert unix stat information to smb stat format
- * @p: destination buffer
- * @ksmbd_kstat: ksmbd kstat wrapper
- */
-void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat)
-{
- struct file_directory_info *info = (struct file_directory_info *)(*p);
- struct kstat *kstat = ksmbd_kstat->kstat;
- u64 time;
-
- info->FileIndex = 0;
- info->CreationTime = cpu_to_le64(ksmbd_kstat->create_time);
- time = ksmbd_UnixTimeToNT(kstat->atime);
- info->LastAccessTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(kstat->mtime);
- info->LastWriteTime = cpu_to_le64(time);
- time = ksmbd_UnixTimeToNT(kstat->ctime);
- info->ChangeTime = cpu_to_le64(time);
-
- if (ksmbd_kstat->file_attributes & FILE_ATTRIBUTE_DIRECTORY_LE) {
- info->EndOfFile = 0;
- info->AllocationSize = 0;
- } else {
- info->EndOfFile = cpu_to_le64(kstat->size);
- info->AllocationSize = cpu_to_le64(kstat->blocks << 9);
- }
- info->ExtFileAttributes = ksmbd_kstat->file_attributes;
-
- return info;
-}
-
-int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
- struct user_namespace *user_ns,
- struct dentry *dentry,
- struct ksmbd_kstat *ksmbd_kstat)
-{
- u64 time;
- int rc;
-
- generic_fillattr(user_ns, d_inode(dentry), ksmbd_kstat->kstat);
-
- time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
- ksmbd_kstat->create_time = time;
-
- /*
- * set default value for the case that store dos attributes is not yes
- * or that acl is disable in server's filesystem and the config is yes.
- */
- if (S_ISDIR(ksmbd_kstat->kstat->mode))
- ksmbd_kstat->file_attributes = FILE_ATTRIBUTE_DIRECTORY_LE;
- else
- ksmbd_kstat->file_attributes = FILE_ATTRIBUTE_ARCHIVE_LE;
-
- if (test_share_config_flag(work->tcon->share_conf,
- KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
- struct xattr_dos_attrib da;
-
- rc = ksmbd_vfs_get_dos_attrib_xattr(user_ns, dentry, &da);
- if (rc > 0) {
- ksmbd_kstat->file_attributes = cpu_to_le32(da.attr);
- ksmbd_kstat->create_time = da.create_time;
- } else {
- ksmbd_debug(VFS, "fail to load dos attribute.\n");
- }
- }
-
- return 0;
-}
-
-ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns,
- struct dentry *dentry, char *attr_name,
- int attr_name_len)
-{
- char *name, *xattr_list = NULL;
- ssize_t value_len = -ENOENT, xattr_list_len;
-
- xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
- if (xattr_list_len <= 0)
- goto out;
-
- for (name = xattr_list; name - xattr_list < xattr_list_len;
- name += strlen(name) + 1) {
- ksmbd_debug(VFS, "%s, len %zd\n", name, strlen(name));
- if (strncasecmp(attr_name, name, attr_name_len))
- continue;
-
- value_len = ksmbd_vfs_xattr_len(user_ns, dentry, name);
- break;
- }
-
-out:
- kvfree(xattr_list);
- return value_len;
-}
-
-int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
- size_t *xattr_stream_name_size, int s_type)
-{
- char *type, *buf;
-
- if (s_type == DIR_STREAM)
- type = ":$INDEX_ALLOCATION";
- else
- type = ":$DATA";
-
- buf = kasprintf(GFP_KERNEL, "%s%s%s",
- XATTR_NAME_STREAM, stream_name, type);
- if (!buf)
- return -ENOMEM;
-
- *xattr_stream_name = buf;
- *xattr_stream_name_size = strlen(buf) + 1;
-
- return 0;
-}
-
-int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
- struct ksmbd_file *src_fp,
- struct ksmbd_file *dst_fp,
- struct srv_copychunk *chunks,
- unsigned int chunk_count,
- unsigned int *chunk_count_written,
- unsigned int *chunk_size_written,
- loff_t *total_size_written)
-{
- unsigned int i;
- loff_t src_off, dst_off, src_file_size;
- size_t len;
- int ret;
-
- *chunk_count_written = 0;
- *chunk_size_written = 0;
- *total_size_written = 0;
-
- if (!(src_fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
- pr_err("no right to read(%pD)\n", src_fp->filp);
- return -EACCES;
- }
- if (!(dst_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) {
- pr_err("no right to write(%pD)\n", dst_fp->filp);
- return -EACCES;
- }
-
- if (ksmbd_stream_fd(src_fp) || ksmbd_stream_fd(dst_fp))
- return -EBADF;
-
- smb_break_all_levII_oplock(work, dst_fp, 1);
-
- if (!work->tcon->posix_extensions) {
- for (i = 0; i < chunk_count; i++) {
- src_off = le64_to_cpu(chunks[i].SourceOffset);
- dst_off = le64_to_cpu(chunks[i].TargetOffset);
- len = le32_to_cpu(chunks[i].Length);
-
- if (check_lock_range(src_fp->filp, src_off,
- src_off + len - 1, READ))
- return -EAGAIN;
- if (check_lock_range(dst_fp->filp, dst_off,
- dst_off + len - 1, WRITE))
- return -EAGAIN;
- }
- }
-
- src_file_size = i_size_read(file_inode(src_fp->filp));
-
- for (i = 0; i < chunk_count; i++) {
- src_off = le64_to_cpu(chunks[i].SourceOffset);
- dst_off = le64_to_cpu(chunks[i].TargetOffset);
- len = le32_to_cpu(chunks[i].Length);
-
- if (src_off + len > src_file_size)
- return -E2BIG;
-
- ret = vfs_copy_file_range(src_fp->filp, src_off,
- dst_fp->filp, dst_off, len, 0);
- if (ret == -EOPNOTSUPP || ret == -EXDEV)
- ret = vfs_copy_file_range(src_fp->filp, src_off,
- dst_fp->filp, dst_off, len,
- COPY_FILE_SPLICE);
- if (ret < 0)
- return ret;
-
- *chunk_count_written += 1;
- *total_size_written += ret;
- }
- return 0;
-}
-
-void ksmbd_vfs_posix_lock_wait(struct file_lock *flock)
-{
- wait_event(flock->fl_wait, !flock->fl_blocker);
-}
-
-int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout)
-{
- return wait_event_interruptible_timeout(flock->fl_wait,
- !flock->fl_blocker,
- timeout);
-}
-
-void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock)
-{
- locks_delete_block(flock);
-}
-
-int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
- struct inode *inode)
-{
- struct posix_acl_state acl_state;
- struct posix_acl *acls;
- int rc;
-
- if (!IS_ENABLED(CONFIG_FS_POSIX_ACL))
- return -EOPNOTSUPP;
-
- ksmbd_debug(SMB, "Set posix acls\n");
- rc = init_acl_state(&acl_state, 1);
- if (rc)
- return rc;
-
- /* Set default owner group */
- acl_state.owner.allow = (inode->i_mode & 0700) >> 6;
- acl_state.group.allow = (inode->i_mode & 0070) >> 3;
- acl_state.other.allow = inode->i_mode & 0007;
- acl_state.users->aces[acl_state.users->n].uid = inode->i_uid;
- acl_state.users->aces[acl_state.users->n++].perms.allow =
- acl_state.owner.allow;
- acl_state.groups->aces[acl_state.groups->n].gid = inode->i_gid;
- acl_state.groups->aces[acl_state.groups->n++].perms.allow =
- acl_state.group.allow;
- acl_state.mask.allow = 0x07;
-
- acls = posix_acl_alloc(6, GFP_KERNEL);
- if (!acls) {
- free_acl_state(&acl_state);
- return -ENOMEM;
- }
- posix_state_to_acl(&acl_state, acls->a_entries);
- rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
- if (rc < 0)
- ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
- rc);
- else if (S_ISDIR(inode->i_mode)) {
- posix_state_to_acl(&acl_state, acls->a_entries);
- rc = set_posix_acl(user_ns, inode, ACL_TYPE_DEFAULT,
- acls);
- if (rc < 0)
- ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
- rc);
- }
- free_acl_state(&acl_state);
- posix_acl_release(acls);
- return rc;
-}
-
-int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
- struct inode *inode, struct inode *parent_inode)
-{
- struct posix_acl *acls;
- struct posix_acl_entry *pace;
- int rc, i;
-
- if (!IS_ENABLED(CONFIG_FS_POSIX_ACL))
- return -EOPNOTSUPP;
-
- acls = get_acl(parent_inode, ACL_TYPE_DEFAULT);
- if (!acls)
- return -ENOENT;
- pace = acls->a_entries;
-
- for (i = 0; i < acls->a_count; i++, pace++) {
- if (pace->e_tag == ACL_MASK) {
- pace->e_perm = 0x07;
- break;
- }
- }
-
- rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
- if (rc < 0)
- ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
- rc);
- if (S_ISDIR(inode->i_mode)) {
- rc = set_posix_acl(user_ns, inode, ACL_TYPE_DEFAULT,
- acls);
- if (rc < 0)
- ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
- rc);
- }
- posix_acl_release(acls);
- return rc;
-}
diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h
deleted file mode 100644
index 593059ca8511..000000000000
--- a/fs/ksmbd/vfs.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_VFS_H__
-#define __KSMBD_VFS_H__
-
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/namei.h>
-#include <uapi/linux/xattr.h>
-#include <linux/posix_acl.h>
-#include <linux/unicode.h>
-
-#include "smbacl.h"
-#include "xattr.h"
-
-/*
- * Enumeration for stream type.
- */
-enum {
- DATA_STREAM = 1, /* type $DATA */
- DIR_STREAM /* type $INDEX_ALLOCATION */
-};
-
-/* CreateOptions */
-#define CREATE_TREE_CONNECTION cpu_to_le32(0x00000080)
-#define FILE_RESERVE_OPFILTER_LE cpu_to_le32(0x00100000)
-
-#define CREATE_OPTION_READONLY 0x10000000
-/* system. NB not sent over wire */
-#define CREATE_OPTION_SPECIAL 0x20000000
-
-struct ksmbd_work;
-struct ksmbd_file;
-struct ksmbd_conn;
-
-struct ksmbd_dir_info {
- const char *name;
- char *wptr;
- char *rptr;
- int name_len;
- int out_buf_len;
- int num_entry;
- int data_count;
- int last_entry_offset;
- bool hide_dot_file;
- int flags;
- int last_entry_off_align;
-};
-
-struct ksmbd_readdir_data {
- struct dir_context ctx;
- union {
- void *private;
- char *dirent;
- };
-
- unsigned int used;
- unsigned int dirent_count;
- unsigned int file_attr;
- struct unicode_map *um;
-};
-
-/* ksmbd kstat wrapper to get valid create time when reading dir entry */
-struct ksmbd_kstat {
- struct kstat *kstat;
- unsigned long long create_time;
- __le32 file_attributes;
-};
-
-int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
- struct dentry *child);
-int ksmbd_vfs_may_delete(struct user_namespace *user_ns, struct dentry *dentry);
-int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
- struct dentry *dentry, __le32 *daccess);
-int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
-int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode);
-int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp,
- size_t count, loff_t *pos);
-int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
- char *buf, size_t count, loff_t *pos, bool sync,
- ssize_t *written);
-int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id);
-int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name);
-int ksmbd_vfs_link(struct ksmbd_work *work,
- const char *oldname, const char *newname);
-int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat);
-int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
- char *newname);
-int ksmbd_vfs_truncate(struct ksmbd_work *work,
- struct ksmbd_file *fp, loff_t size);
-struct srv_copychunk;
-int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
- struct ksmbd_file *src_fp,
- struct ksmbd_file *dst_fp,
- struct srv_copychunk *chunks,
- unsigned int chunk_count,
- unsigned int *chunk_count_written,
- unsigned int *chunk_size_written,
- loff_t *total_size_written);
-ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list);
-ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
- struct dentry *dentry,
- char *xattr_name,
- char **xattr_buf);
-ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns,
- struct dentry *dentry, char *attr_name,
- int attr_name_len);
-int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
- struct dentry *dentry, const char *attr_name,
- void *attr_value, size_t attr_size, int flags);
-int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
- size_t *xattr_stream_name_size, int s_type);
-int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
- struct dentry *dentry, char *attr_name);
-int ksmbd_vfs_kern_path(struct ksmbd_work *work,
- char *name, unsigned int flags, struct path *path,
- bool caseless);
-struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
- const char *name,
- unsigned int flags,
- struct path *path);
-int ksmbd_vfs_empty_dir(struct ksmbd_file *fp);
-void ksmbd_vfs_set_fadvise(struct file *filp, __le32 option);
-int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
- loff_t off, loff_t len);
-struct file_allocated_range_buffer;
-int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
- struct file_allocated_range_buffer *ranges,
- unsigned int in_count, unsigned int *out_count);
-int ksmbd_vfs_unlink(struct user_namespace *user_ns,
- struct dentry *dir, struct dentry *dentry);
-void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat);
-int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
- struct user_namespace *user_ns,
- struct dentry *dentry,
- struct ksmbd_kstat *ksmbd_kstat);
-void ksmbd_vfs_posix_lock_wait(struct file_lock *flock);
-int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout);
-void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock);
-int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
- struct dentry *dentry);
-int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns,
- struct dentry *dentry);
-int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
- struct user_namespace *user_ns,
- struct dentry *dentry,
- struct smb_ntsd *pntsd, int len);
-int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
- struct user_namespace *user_ns,
- struct dentry *dentry,
- struct smb_ntsd **pntsd);
-int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
- struct dentry *dentry,
- struct xattr_dos_attrib *da);
-int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns,
- struct dentry *dentry,
- struct xattr_dos_attrib *da);
-int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
- struct inode *inode);
-int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
- struct inode *inode,
- struct inode *parent_inode);
-#endif /* __KSMBD_VFS_H__ */
diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c
deleted file mode 100644
index 0ae5dd0829e9..000000000000
--- a/fs/ksmbd/vfs_cache.c
+++ /dev/null
@@ -1,708 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
- * Copyright (C) 2019 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include "glob.h"
-#include "vfs_cache.h"
-#include "oplock.h"
-#include "vfs.h"
-#include "connection.h"
-#include "mgmt/tree_connect.h"
-#include "mgmt/user_session.h"
-#include "smb_common.h"
-
-#define S_DEL_PENDING 1
-#define S_DEL_ON_CLS 2
-#define S_DEL_ON_CLS_STREAM 8
-
-static unsigned int inode_hash_mask __read_mostly;
-static unsigned int inode_hash_shift __read_mostly;
-static struct hlist_head *inode_hashtable __read_mostly;
-static DEFINE_RWLOCK(inode_hash_lock);
-
-static struct ksmbd_file_table global_ft;
-static atomic_long_t fd_limit;
-static struct kmem_cache *filp_cache;
-
-void ksmbd_set_fd_limit(unsigned long limit)
-{
- limit = min(limit, get_max_files());
- atomic_long_set(&fd_limit, limit);
-}
-
-static bool fd_limit_depleted(void)
-{
- long v = atomic_long_dec_return(&fd_limit);
-
- if (v >= 0)
- return false;
- atomic_long_inc(&fd_limit);
- return true;
-}
-
-static void fd_limit_close(void)
-{
- atomic_long_inc(&fd_limit);
-}
-
-/*
- * INODE hash
- */
-
-static unsigned long inode_hash(struct super_block *sb, unsigned long hashval)
-{
- unsigned long tmp;
-
- tmp = (hashval * (unsigned long)sb) ^ (GOLDEN_RATIO_PRIME + hashval) /
- L1_CACHE_BYTES;
- tmp = tmp ^ ((tmp ^ GOLDEN_RATIO_PRIME) >> inode_hash_shift);
- return tmp & inode_hash_mask;
-}
-
-static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode)
-{
- struct hlist_head *head = inode_hashtable +
- inode_hash(inode->i_sb, inode->i_ino);
- struct ksmbd_inode *ci = NULL, *ret_ci = NULL;
-
- hlist_for_each_entry(ci, head, m_hash) {
- if (ci->m_inode == inode) {
- if (atomic_inc_not_zero(&ci->m_count))
- ret_ci = ci;
- break;
- }
- }
- return ret_ci;
-}
-
-static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp)
-{
- return __ksmbd_inode_lookup(file_inode(fp->filp));
-}
-
-static struct ksmbd_inode *ksmbd_inode_lookup_by_vfsinode(struct inode *inode)
-{
- struct ksmbd_inode *ci;
-
- read_lock(&inode_hash_lock);
- ci = __ksmbd_inode_lookup(inode);
- read_unlock(&inode_hash_lock);
- return ci;
-}
-
-int ksmbd_query_inode_status(struct inode *inode)
-{
- struct ksmbd_inode *ci;
- int ret = KSMBD_INODE_STATUS_UNKNOWN;
-
- read_lock(&inode_hash_lock);
- ci = __ksmbd_inode_lookup(inode);
- if (ci) {
- ret = KSMBD_INODE_STATUS_OK;
- if (ci->m_flags & S_DEL_PENDING)
- ret = KSMBD_INODE_STATUS_PENDING_DELETE;
- atomic_dec(&ci->m_count);
- }
- read_unlock(&inode_hash_lock);
- return ret;
-}
-
-bool ksmbd_inode_pending_delete(struct ksmbd_file *fp)
-{
- return (fp->f_ci->m_flags & S_DEL_PENDING);
-}
-
-void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp)
-{
- fp->f_ci->m_flags |= S_DEL_PENDING;
-}
-
-void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp)
-{
- fp->f_ci->m_flags &= ~S_DEL_PENDING;
-}
-
-void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
- int file_info)
-{
- if (ksmbd_stream_fd(fp)) {
- fp->f_ci->m_flags |= S_DEL_ON_CLS_STREAM;
- return;
- }
-
- fp->f_ci->m_flags |= S_DEL_ON_CLS;
-}
-
-static void ksmbd_inode_hash(struct ksmbd_inode *ci)
-{
- struct hlist_head *b = inode_hashtable +
- inode_hash(ci->m_inode->i_sb, ci->m_inode->i_ino);
-
- hlist_add_head(&ci->m_hash, b);
-}
-
-static void ksmbd_inode_unhash(struct ksmbd_inode *ci)
-{
- write_lock(&inode_hash_lock);
- hlist_del_init(&ci->m_hash);
- write_unlock(&inode_hash_lock);
-}
-
-static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
-{
- ci->m_inode = file_inode(fp->filp);
- atomic_set(&ci->m_count, 1);
- atomic_set(&ci->op_count, 0);
- atomic_set(&ci->sop_count, 0);
- ci->m_flags = 0;
- ci->m_fattr = 0;
- INIT_LIST_HEAD(&ci->m_fp_list);
- INIT_LIST_HEAD(&ci->m_op_list);
- rwlock_init(&ci->m_lock);
- return 0;
-}
-
-static struct ksmbd_inode *ksmbd_inode_get(struct ksmbd_file *fp)
-{
- struct ksmbd_inode *ci, *tmpci;
- int rc;
-
- read_lock(&inode_hash_lock);
- ci = ksmbd_inode_lookup(fp);
- read_unlock(&inode_hash_lock);
- if (ci)
- return ci;
-
- ci = kmalloc(sizeof(struct ksmbd_inode), GFP_KERNEL);
- if (!ci)
- return NULL;
-
- rc = ksmbd_inode_init(ci, fp);
- if (rc) {
- pr_err("inode initialized failed\n");
- kfree(ci);
- return NULL;
- }
-
- write_lock(&inode_hash_lock);
- tmpci = ksmbd_inode_lookup(fp);
- if (!tmpci) {
- ksmbd_inode_hash(ci);
- } else {
- kfree(ci);
- ci = tmpci;
- }
- write_unlock(&inode_hash_lock);
- return ci;
-}
-
-static void ksmbd_inode_free(struct ksmbd_inode *ci)
-{
- ksmbd_inode_unhash(ci);
- kfree(ci);
-}
-
-static void ksmbd_inode_put(struct ksmbd_inode *ci)
-{
- if (atomic_dec_and_test(&ci->m_count))
- ksmbd_inode_free(ci);
-}
-
-int __init ksmbd_inode_hash_init(void)
-{
- unsigned int loop;
- unsigned long numentries = 16384;
- unsigned long bucketsize = sizeof(struct hlist_head);
- unsigned long size;
-
- inode_hash_shift = ilog2(numentries);
- inode_hash_mask = (1 << inode_hash_shift) - 1;
-
- size = bucketsize << inode_hash_shift;
-
- /* init master fp hash table */
- inode_hashtable = vmalloc(size);
- if (!inode_hashtable)
- return -ENOMEM;
-
- for (loop = 0; loop < (1U << inode_hash_shift); loop++)
- INIT_HLIST_HEAD(&inode_hashtable[loop]);
- return 0;
-}
-
-void ksmbd_release_inode_hash(void)
-{
- vfree(inode_hashtable);
-}
-
-static void __ksmbd_inode_close(struct ksmbd_file *fp)
-{
- struct dentry *dir, *dentry;
- struct ksmbd_inode *ci = fp->f_ci;
- int err;
- struct file *filp;
-
- filp = fp->filp;
- if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) {
- ci->m_flags &= ~S_DEL_ON_CLS_STREAM;
- err = ksmbd_vfs_remove_xattr(file_mnt_user_ns(filp),
- filp->f_path.dentry,
- fp->stream.name);
- if (err)
- pr_err("remove xattr failed : %s\n",
- fp->stream.name);
- }
-
- if (atomic_dec_and_test(&ci->m_count)) {
- write_lock(&ci->m_lock);
- if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
- dentry = filp->f_path.dentry;
- dir = dentry->d_parent;
- ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
- write_unlock(&ci->m_lock);
- ksmbd_vfs_unlink(file_mnt_user_ns(filp), dir, dentry);
- write_lock(&ci->m_lock);
- }
- write_unlock(&ci->m_lock);
-
- ksmbd_inode_free(ci);
- }
-}
-
-static void __ksmbd_remove_durable_fd(struct ksmbd_file *fp)
-{
- if (!has_file_id(fp->persistent_id))
- return;
-
- write_lock(&global_ft.lock);
- idr_remove(global_ft.idr, fp->persistent_id);
- write_unlock(&global_ft.lock);
-}
-
-static void __ksmbd_remove_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
-{
- if (!has_file_id(fp->volatile_id))
- return;
-
- write_lock(&fp->f_ci->m_lock);
- list_del_init(&fp->node);
- write_unlock(&fp->f_ci->m_lock);
-
- write_lock(&ft->lock);
- idr_remove(ft->idr, fp->volatile_id);
- write_unlock(&ft->lock);
-}
-
-static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
-{
- struct file *filp;
- struct ksmbd_lock *smb_lock, *tmp_lock;
-
- fd_limit_close();
- __ksmbd_remove_durable_fd(fp);
- __ksmbd_remove_fd(ft, fp);
-
- close_id_del_oplock(fp);
- filp = fp->filp;
-
- __ksmbd_inode_close(fp);
- if (!IS_ERR_OR_NULL(filp))
- fput(filp);
-
- /* because the reference count of fp is 0, it is guaranteed that
- * there are not accesses to fp->lock_list.
- */
- list_for_each_entry_safe(smb_lock, tmp_lock, &fp->lock_list, flist) {
- spin_lock(&fp->conn->llist_lock);
- list_del(&smb_lock->clist);
- spin_unlock(&fp->conn->llist_lock);
-
- list_del(&smb_lock->flist);
- locks_free_lock(smb_lock->fl);
- kfree(smb_lock);
- }
-
- if (ksmbd_stream_fd(fp))
- kfree(fp->stream.name);
- kmem_cache_free(filp_cache, fp);
-}
-
-static struct ksmbd_file *ksmbd_fp_get(struct ksmbd_file *fp)
-{
- if (!atomic_inc_not_zero(&fp->refcount))
- return NULL;
- return fp;
-}
-
-static struct ksmbd_file *__ksmbd_lookup_fd(struct ksmbd_file_table *ft,
- u64 id)
-{
- struct ksmbd_file *fp;
-
- if (!has_file_id(id))
- return NULL;
-
- read_lock(&ft->lock);
- fp = idr_find(ft->idr, id);
- if (fp)
- fp = ksmbd_fp_get(fp);
- read_unlock(&ft->lock);
- return fp;
-}
-
-static void __put_fd_final(struct ksmbd_work *work, struct ksmbd_file *fp)
-{
- __ksmbd_close_fd(&work->sess->file_table, fp);
- atomic_dec(&work->conn->stats.open_files_count);
-}
-
-static void set_close_state_blocked_works(struct ksmbd_file *fp)
-{
- struct ksmbd_work *cancel_work;
-
- spin_lock(&fp->f_lock);
- list_for_each_entry(cancel_work, &fp->blocked_works,
- fp_entry) {
- cancel_work->state = KSMBD_WORK_CLOSED;
- cancel_work->cancel_fn(cancel_work->cancel_argv);
- }
- spin_unlock(&fp->f_lock);
-}
-
-int ksmbd_close_fd(struct ksmbd_work *work, u64 id)
-{
- struct ksmbd_file *fp;
- struct ksmbd_file_table *ft;
-
- if (!has_file_id(id))
- return 0;
-
- ft = &work->sess->file_table;
- read_lock(&ft->lock);
- fp = idr_find(ft->idr, id);
- if (fp) {
- set_close_state_blocked_works(fp);
-
- if (!atomic_dec_and_test(&fp->refcount))
- fp = NULL;
- }
- read_unlock(&ft->lock);
-
- if (!fp)
- return -EINVAL;
-
- __put_fd_final(work, fp);
- return 0;
-}
-
-void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp)
-{
- if (!fp)
- return;
-
- if (!atomic_dec_and_test(&fp->refcount))
- return;
- __put_fd_final(work, fp);
-}
-
-static bool __sanity_check(struct ksmbd_tree_connect *tcon, struct ksmbd_file *fp)
-{
- if (!fp)
- return false;
- if (fp->tcon != tcon)
- return false;
- return true;
-}
-
-struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id)
-{
- return __ksmbd_lookup_fd(&work->sess->file_table, id);
-}
-
-struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, u64 id)
-{
- struct ksmbd_file *fp = __ksmbd_lookup_fd(&work->sess->file_table, id);
-
- if (__sanity_check(work->tcon, fp))
- return fp;
-
- ksmbd_fd_put(work, fp);
- return NULL;
-}
-
-struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
- u64 pid)
-{
- struct ksmbd_file *fp;
-
- if (!has_file_id(id)) {
- id = work->compound_fid;
- pid = work->compound_pfid;
- }
-
- fp = __ksmbd_lookup_fd(&work->sess->file_table, id);
- if (!__sanity_check(work->tcon, fp)) {
- ksmbd_fd_put(work, fp);
- return NULL;
- }
- if (fp->persistent_id != pid) {
- ksmbd_fd_put(work, fp);
- return NULL;
- }
- return fp;
-}
-
-struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id)
-{
- return __ksmbd_lookup_fd(&global_ft, id);
-}
-
-struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid)
-{
- struct ksmbd_file *fp = NULL;
- unsigned int id;
-
- read_lock(&global_ft.lock);
- idr_for_each_entry(global_ft.idr, fp, id) {
- if (!memcmp(fp->create_guid,
- cguid,
- SMB2_CREATE_GUID_SIZE)) {
- fp = ksmbd_fp_get(fp);
- break;
- }
- }
- read_unlock(&global_ft.lock);
-
- return fp;
-}
-
-struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode)
-{
- struct ksmbd_file *lfp;
- struct ksmbd_inode *ci;
-
- ci = ksmbd_inode_lookup_by_vfsinode(inode);
- if (!ci)
- return NULL;
-
- read_lock(&ci->m_lock);
- list_for_each_entry(lfp, &ci->m_fp_list, node) {
- if (inode == file_inode(lfp->filp)) {
- atomic_dec(&ci->m_count);
- lfp = ksmbd_fp_get(lfp);
- read_unlock(&ci->m_lock);
- return lfp;
- }
- }
- atomic_dec(&ci->m_count);
- read_unlock(&ci->m_lock);
- return NULL;
-}
-
-#define OPEN_ID_TYPE_VOLATILE_ID (0)
-#define OPEN_ID_TYPE_PERSISTENT_ID (1)
-
-static void __open_id_set(struct ksmbd_file *fp, u64 id, int type)
-{
- if (type == OPEN_ID_TYPE_VOLATILE_ID)
- fp->volatile_id = id;
- if (type == OPEN_ID_TYPE_PERSISTENT_ID)
- fp->persistent_id = id;
-}
-
-static int __open_id(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
- int type)
-{
- u64 id = 0;
- int ret;
-
- if (type == OPEN_ID_TYPE_VOLATILE_ID && fd_limit_depleted()) {
- __open_id_set(fp, KSMBD_NO_FID, type);
- return -EMFILE;
- }
-
- idr_preload(GFP_KERNEL);
- write_lock(&ft->lock);
- ret = idr_alloc_cyclic(ft->idr, fp, 0, INT_MAX - 1, GFP_NOWAIT);
- if (ret >= 0) {
- id = ret;
- ret = 0;
- } else {
- id = KSMBD_NO_FID;
- fd_limit_close();
- }
-
- __open_id_set(fp, id, type);
- write_unlock(&ft->lock);
- idr_preload_end();
- return ret;
-}
-
-unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp)
-{
- __open_id(&global_ft, fp, OPEN_ID_TYPE_PERSISTENT_ID);
- return fp->persistent_id;
-}
-
-struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
-{
- struct ksmbd_file *fp;
- int ret;
-
- fp = kmem_cache_zalloc(filp_cache, GFP_KERNEL);
- if (!fp) {
- pr_err("Failed to allocate memory\n");
- return ERR_PTR(-ENOMEM);
- }
-
- INIT_LIST_HEAD(&fp->blocked_works);
- INIT_LIST_HEAD(&fp->node);
- INIT_LIST_HEAD(&fp->lock_list);
- spin_lock_init(&fp->f_lock);
- atomic_set(&fp->refcount, 1);
-
- fp->filp = filp;
- fp->conn = work->conn;
- fp->tcon = work->tcon;
- fp->volatile_id = KSMBD_NO_FID;
- fp->persistent_id = KSMBD_NO_FID;
- fp->f_ci = ksmbd_inode_get(fp);
-
- if (!fp->f_ci) {
- ret = -ENOMEM;
- goto err_out;
- }
-
- ret = __open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
- if (ret) {
- ksmbd_inode_put(fp->f_ci);
- goto err_out;
- }
-
- atomic_inc(&work->conn->stats.open_files_count);
- return fp;
-
-err_out:
- kmem_cache_free(filp_cache, fp);
- return ERR_PTR(ret);
-}
-
-static int
-__close_file_table_ids(struct ksmbd_file_table *ft,
- struct ksmbd_tree_connect *tcon,
- bool (*skip)(struct ksmbd_tree_connect *tcon,
- struct ksmbd_file *fp))
-{
- unsigned int id;
- struct ksmbd_file *fp;
- int num = 0;
-
- idr_for_each_entry(ft->idr, fp, id) {
- if (skip(tcon, fp))
- continue;
-
- set_close_state_blocked_works(fp);
-
- if (!atomic_dec_and_test(&fp->refcount))
- continue;
- __ksmbd_close_fd(ft, fp);
- num++;
- }
- return num;
-}
-
-static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon,
- struct ksmbd_file *fp)
-{
- return fp->tcon != tcon;
-}
-
-static bool session_fd_check(struct ksmbd_tree_connect *tcon,
- struct ksmbd_file *fp)
-{
- return false;
-}
-
-void ksmbd_close_tree_conn_fds(struct ksmbd_work *work)
-{
- int num = __close_file_table_ids(&work->sess->file_table,
- work->tcon,
- tree_conn_fd_check);
-
- atomic_sub(num, &work->conn->stats.open_files_count);
-}
-
-void ksmbd_close_session_fds(struct ksmbd_work *work)
-{
- int num = __close_file_table_ids(&work->sess->file_table,
- work->tcon,
- session_fd_check);
-
- atomic_sub(num, &work->conn->stats.open_files_count);
-}
-
-int ksmbd_init_global_file_table(void)
-{
- return ksmbd_init_file_table(&global_ft);
-}
-
-void ksmbd_free_global_file_table(void)
-{
- struct ksmbd_file *fp = NULL;
- unsigned int id;
-
- idr_for_each_entry(global_ft.idr, fp, id) {
- __ksmbd_remove_durable_fd(fp);
- kmem_cache_free(filp_cache, fp);
- }
-
- ksmbd_destroy_file_table(&global_ft);
-}
-
-int ksmbd_init_file_table(struct ksmbd_file_table *ft)
-{
- ft->idr = kzalloc(sizeof(struct idr), GFP_KERNEL);
- if (!ft->idr)
- return -ENOMEM;
-
- idr_init(ft->idr);
- rwlock_init(&ft->lock);
- return 0;
-}
-
-void ksmbd_destroy_file_table(struct ksmbd_file_table *ft)
-{
- if (!ft->idr)
- return;
-
- __close_file_table_ids(ft, NULL, session_fd_check);
- idr_destroy(ft->idr);
- kfree(ft->idr);
- ft->idr = NULL;
-}
-
-int ksmbd_init_file_cache(void)
-{
- filp_cache = kmem_cache_create("ksmbd_file_cache",
- sizeof(struct ksmbd_file), 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (!filp_cache)
- goto out;
-
- return 0;
-
-out:
- pr_err("failed to allocate file cache\n");
- return -ENOMEM;
-}
-
-void ksmbd_exit_file_cache(void)
-{
- kmem_cache_destroy(filp_cache);
-}
diff --git a/fs/ksmbd/vfs_cache.h b/fs/ksmbd/vfs_cache.h
deleted file mode 100644
index fcb13413fa8d..000000000000
--- a/fs/ksmbd/vfs_cache.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2019 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __VFS_CACHE_H__
-#define __VFS_CACHE_H__
-
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/rwsem.h>
-#include <linux/spinlock.h>
-#include <linux/idr.h>
-#include <linux/workqueue.h>
-
-#include "vfs.h"
-
-/* Windows style file permissions for extended response */
-#define FILE_GENERIC_ALL 0x1F01FF
-#define FILE_GENERIC_READ 0x120089
-#define FILE_GENERIC_WRITE 0x120116
-#define FILE_GENERIC_EXECUTE 0X1200a0
-
-#define KSMBD_START_FID 0
-#define KSMBD_NO_FID (INT_MAX)
-#define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL)
-
-struct ksmbd_conn;
-struct ksmbd_session;
-
-struct ksmbd_lock {
- struct file_lock *fl;
- struct list_head clist;
- struct list_head flist;
- struct list_head llist;
- unsigned int flags;
- int cmd;
- int zero_len;
- unsigned long long start;
- unsigned long long end;
-};
-
-struct stream {
- char *name;
- ssize_t size;
-};
-
-struct ksmbd_inode {
- rwlock_t m_lock;
- atomic_t m_count;
- atomic_t op_count;
- /* opinfo count for streams */
- atomic_t sop_count;
- struct inode *m_inode;
- unsigned int m_flags;
- struct hlist_node m_hash;
- struct list_head m_fp_list;
- struct list_head m_op_list;
- struct oplock_info *m_opinfo;
- __le32 m_fattr;
-};
-
-struct ksmbd_file {
- struct file *filp;
- u64 persistent_id;
- u64 volatile_id;
-
- spinlock_t f_lock;
-
- struct ksmbd_inode *f_ci;
- struct ksmbd_inode *f_parent_ci;
- struct oplock_info __rcu *f_opinfo;
- struct ksmbd_conn *conn;
- struct ksmbd_tree_connect *tcon;
-
- atomic_t refcount;
- __le32 daccess;
- __le32 saccess;
- __le32 coption;
- __le32 cdoption;
- __u64 create_time;
- __u64 itime;
-
- bool is_nt_open;
- bool attrib_only;
-
- char client_guid[16];
- char create_guid[16];
- char app_instance_id[16];
-
- struct stream stream;
- struct list_head node;
- struct list_head blocked_works;
- struct list_head lock_list;
-
- int durable_timeout;
-
- /* if ls is happening on directory, below is valid*/
- struct ksmbd_readdir_data readdir_data;
- int dot_dotdot[2];
-};
-
-static inline void set_ctx_actor(struct dir_context *ctx,
- filldir_t actor)
-{
- ctx->actor = actor;
-}
-
-#define KSMBD_NR_OPEN_DEFAULT BITS_PER_LONG
-
-struct ksmbd_file_table {
- rwlock_t lock;
- struct idr *idr;
-};
-
-static inline bool has_file_id(u64 id)
-{
- return id < KSMBD_NO_FID;
-}
-
-static inline bool ksmbd_stream_fd(struct ksmbd_file *fp)
-{
- return fp->stream.name != NULL;
-}
-
-int ksmbd_init_file_table(struct ksmbd_file_table *ft);
-void ksmbd_destroy_file_table(struct ksmbd_file_table *ft);
-int ksmbd_close_fd(struct ksmbd_work *work, u64 id);
-struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, u64 id);
-struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id);
-struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
- u64 pid);
-void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp);
-struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id);
-struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid);
-struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode);
-unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp);
-struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp);
-void ksmbd_close_tree_conn_fds(struct ksmbd_work *work);
-void ksmbd_close_session_fds(struct ksmbd_work *work);
-int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode);
-int ksmbd_init_global_file_table(void);
-void ksmbd_free_global_file_table(void);
-void ksmbd_set_fd_limit(unsigned long limit);
-
-/*
- * INODE hash
- */
-int __init ksmbd_inode_hash_init(void);
-void ksmbd_release_inode_hash(void);
-
-enum KSMBD_INODE_STATUS {
- KSMBD_INODE_STATUS_OK,
- KSMBD_INODE_STATUS_UNKNOWN,
- KSMBD_INODE_STATUS_PENDING_DELETE,
-};
-
-int ksmbd_query_inode_status(struct inode *inode);
-bool ksmbd_inode_pending_delete(struct ksmbd_file *fp);
-void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp);
-void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp);
-void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
- int file_info);
-int ksmbd_init_file_cache(void);
-void ksmbd_exit_file_cache(void);
-#endif /* __VFS_CACHE_H__ */
diff --git a/fs/ksmbd/xattr.h b/fs/ksmbd/xattr.h
deleted file mode 100644
index 16499ca5c82d..000000000000
--- a/fs/ksmbd/xattr.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2021 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __XATTR_H__
-#define __XATTR_H__
-
-/*
- * These are on-disk structures to store additional metadata into xattr to
- * reproduce windows filesystem semantics. And they are encoded with NDR to
- * compatible with samba's xattr meta format. The compatibility with samba
- * is important because it can lose the information(file attribute,
- * creation time, acls) about the existing files when switching between
- * ksmbd and samba.
- */
-
-/*
- * Dos attribute flags used for what variable is valid.
- */
-enum {
- XATTR_DOSINFO_ATTRIB = 0x00000001,
- XATTR_DOSINFO_EA_SIZE = 0x00000002,
- XATTR_DOSINFO_SIZE = 0x00000004,
- XATTR_DOSINFO_ALLOC_SIZE = 0x00000008,
- XATTR_DOSINFO_CREATE_TIME = 0x00000010,
- XATTR_DOSINFO_CHANGE_TIME = 0x00000020,
- XATTR_DOSINFO_ITIME = 0x00000040
-};
-
-/*
- * Dos attribute structure which is compatible with samba's one.
- * Storing it into the xattr named "DOSATTRIB" separately from inode
- * allows ksmbd to faithfully reproduce windows filesystem semantics
- * on top of a POSIX filesystem.
- */
-struct xattr_dos_attrib {
- __u16 version; /* version 3 or version 4 */
- __u32 flags; /* valid flags */
- __u32 attr; /* Dos attribute */
- __u32 ea_size; /* EA size */
- __u64 size;
- __u64 alloc_size;
- __u64 create_time; /* File creation time */
- __u64 change_time; /* File change time */
- __u64 itime; /* Invented/Initial time */
-};
-
-/*
- * Enumeration is used for computing posix acl hash.
- */
-enum {
- SMB_ACL_TAG_INVALID = 0,
- SMB_ACL_USER,
- SMB_ACL_USER_OBJ,
- SMB_ACL_GROUP,
- SMB_ACL_GROUP_OBJ,
- SMB_ACL_OTHER,
- SMB_ACL_MASK
-};
-
-#define SMB_ACL_READ 4
-#define SMB_ACL_WRITE 2
-#define SMB_ACL_EXECUTE 1
-
-struct xattr_acl_entry {
- int type;
- uid_t uid;
- gid_t gid;
- mode_t perm;
-};
-
-/*
- * xattr_smb_acl structure is used for computing posix acl hash.
- */
-struct xattr_smb_acl {
- int count;
- int next;
- struct xattr_acl_entry entries[];
-};
-
-/* 64bytes hash in xattr_ntacl is computed with sha256 */
-#define XATTR_SD_HASH_TYPE_SHA256 0x1
-#define XATTR_SD_HASH_SIZE 64
-
-/*
- * xattr_ntacl is used for storing ntacl and hashes.
- * Hash is used for checking valid posix acl and ntacl in xattr.
- */
-struct xattr_ntacl {
- __u16 version; /* version 4*/
- void *sd_buf;
- __u32 sd_size;
- __u16 hash_type; /* hash type */
- __u8 desc[10]; /* posix_acl description */
- __u16 desc_len;
- __u64 current_time;
- __u8 hash[XATTR_SD_HASH_SIZE]; /* 64bytes hash for ntacl */
- __u8 posix_acl_hash[XATTR_SD_HASH_SIZE]; /* 64bytes hash for posix acl */
-};
-
-/* DOS ATTRIBUITE XATTR PREFIX */
-#define DOS_ATTRIBUTE_PREFIX "DOSATTRIB"
-#define DOS_ATTRIBUTE_PREFIX_LEN (sizeof(DOS_ATTRIBUTE_PREFIX) - 1)
-#define XATTR_NAME_DOS_ATTRIBUTE (XATTR_USER_PREFIX DOS_ATTRIBUTE_PREFIX)
-#define XATTR_NAME_DOS_ATTRIBUTE_LEN \
- (sizeof(XATTR_USER_PREFIX DOS_ATTRIBUTE_PREFIX) - 1)
-
-/* STREAM XATTR PREFIX */
-#define STREAM_PREFIX "DosStream."
-#define STREAM_PREFIX_LEN (sizeof(STREAM_PREFIX) - 1)
-#define XATTR_NAME_STREAM (XATTR_USER_PREFIX STREAM_PREFIX)
-#define XATTR_NAME_STREAM_LEN (sizeof(XATTR_NAME_STREAM) - 1)
-
-/* SECURITY DESCRIPTOR(NTACL) XATTR PREFIX */
-#define SD_PREFIX "NTACL"
-#define SD_PREFIX_LEN (sizeof(SD_PREFIX) - 1)
-#define XATTR_NAME_SD (XATTR_SECURITY_PREFIX SD_PREFIX)
-#define XATTR_NAME_SD_LEN \
- (sizeof(XATTR_SECURITY_PREFIX SD_PREFIX) - 1)
-
-#endif /* __XATTR_H__ */
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 39b7eea2642a..7d31833e68d1 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -369,7 +369,15 @@ void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
struct page *page = pvec.pages[i];
lock_page(page);
- nilfs_clear_dirty_page(page, silent);
+
+ /*
+ * This page may have been removed from the address
+ * space by truncation or invalidation when the lock
+ * was acquired. Skip processing in that case.
+ */
+ if (likely(page->mapping == mapping))
+ nilfs_clear_dirty_page(page, silent);
+
unlock_page(page);
}
pagevec_release(&pvec);
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c
index 1362ccb64ec7..6e59dc19a732 100644
--- a/fs/nilfs2/segbuf.c
+++ b/fs/nilfs2/segbuf.c
@@ -101,6 +101,12 @@ int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *segbuf)
if (unlikely(!bh))
return -ENOMEM;
+ lock_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ memset(bh->b_data, 0, bh->b_size);
+ set_buffer_uptodate(bh);
+ }
+ unlock_buffer(bh);
nilfs_segbuf_add_segsum_buffer(segbuf, bh);
return 0;
}
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 209e46431a5e..6cf64023be31 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -979,10 +979,13 @@ static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci,
unsigned int isz, srsz;
bh_sr = NILFS_LAST_SEGBUF(&sci->sc_segbufs)->sb_super_root;
+
+ lock_buffer(bh_sr);
raw_sr = (struct nilfs_super_root *)bh_sr->b_data;
isz = nilfs->ns_inode_size;
srsz = NILFS_SR_BYTES(isz);
+ raw_sr->sr_sum = 0; /* Ensure initialization within this update */
raw_sr->sr_bytes = cpu_to_le16(srsz);
raw_sr->sr_nongc_ctime
= cpu_to_le64(nilfs_doing_gc() ?
@@ -996,6 +999,8 @@ static void nilfs_segctor_fill_in_super_root(struct nilfs_sc_info *sci,
nilfs_write_inode_common(nilfs->ns_sufile, (void *)raw_sr +
NILFS_SR_SUFILE_OFFSET(isz), 1);
memset((void *)raw_sr + srsz, 0, nilfs->ns_blocksize - srsz);
+ set_buffer_uptodate(bh_sr);
+ unlock_buffer(bh_sr);
}
static void nilfs_redirty_inodes(struct list_head *head)
@@ -1778,6 +1783,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
list_for_each_entry(segbuf, logs, sb_list) {
list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
b_assoc_buffers) {
+ clear_buffer_uptodate(bh);
if (bh->b_page != bd_page) {
if (bd_page)
end_page_writeback(bd_page);
@@ -1789,6 +1795,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
b_assoc_buffers) {
clear_buffer_async_write(bh);
if (bh == segbuf->sb_super_root) {
+ clear_buffer_uptodate(bh);
if (bh->b_page != bd_page) {
end_page_writeback(bd_page);
bd_page = bh->b_page;
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 77f1e5778d1c..9ba4933087af 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -372,10 +372,31 @@ static int nilfs_move_2nd_super(struct super_block *sb, loff_t sb2off)
goto out;
}
nsbp = (void *)nsbh->b_data + offset;
- memset(nsbp, 0, nilfs->ns_blocksize);
+ lock_buffer(nsbh);
if (sb2i >= 0) {
+ /*
+ * The position of the second superblock only changes by 4KiB,
+ * which is larger than the maximum superblock data size
+ * (= 1KiB), so there is no need to use memmove() to allow
+ * overlap between source and destination.
+ */
memcpy(nsbp, nilfs->ns_sbp[sb2i], nilfs->ns_sbsize);
+
+ /*
+ * Zero fill after copy to avoid overwriting in case of move
+ * within the same block.
+ */
+ memset(nsbh->b_data, 0, offset);
+ memset((void *)nsbp + nilfs->ns_sbsize, 0,
+ nsbh->b_size - offset - nilfs->ns_sbsize);
+ } else {
+ memset(nsbh->b_data, 0, nsbh->b_size);
+ }
+ set_buffer_uptodate(nsbh);
+ unlock_buffer(nsbh);
+
+ if (sb2i >= 0) {
brelse(nilfs->ns_sbh[sb2i]);
nilfs->ns_sbh[sb2i] = nsbh;
nilfs->ns_sbp[sb2i] = nsbp;
diff --git a/fs/smb/Kconfig b/fs/smb/Kconfig
new file mode 100644
index 000000000000..ef425789fa6a
--- /dev/null
+++ b/fs/smb/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# smbfs configuration
+
+source "fs/smb/client/Kconfig"
+source "fs/smb/server/Kconfig"
+
+config SMBFS
+ tristate
+ default y if CIFS=y || SMB_SERVER=y
+ default m if CIFS=m || SMB_SERVER=m
diff --git a/fs/smb/Makefile b/fs/smb/Makefile
new file mode 100644
index 000000000000..9a1bf59a1a65
--- /dev/null
+++ b/fs/smb/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SMBFS) += common/
+obj-$(CONFIG_CIFS) += client/
+obj-$(CONFIG_SMB_SERVER) += server/
diff --git a/fs/smb/client/Kconfig b/fs/smb/client/Kconfig
new file mode 100644
index 000000000000..3b7e3b9e4fd2
--- /dev/null
+++ b/fs/smb/client/Kconfig
@@ -0,0 +1,203 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config CIFS
+ tristate "SMB3 and CIFS support (advanced network filesystem)"
+ depends on INET
+ select NLS
+ select CRYPTO
+ select CRYPTO_MD5
+ select CRYPTO_SHA256
+ select CRYPTO_SHA512
+ select CRYPTO_CMAC
+ select CRYPTO_HMAC
+ select CRYPTO_AEAD2
+ select CRYPTO_CCM
+ select CRYPTO_GCM
+ select CRYPTO_ECB
+ select CRYPTO_AES
+ select KEYS
+ select DNS_RESOLVER
+ select ASN1
+ select OID_REGISTRY
+ help
+ This is the client VFS module for the SMB3 family of NAS protocols,
+ (including support for the most recent, most secure dialect SMB3.1.1)
+ as well as for earlier dialects such as SMB2.1, SMB2 and the older
+ Common Internet File System (CIFS) protocol. CIFS was the successor
+ to the original dialect, the Server Message Block (SMB) protocol, the
+ native file sharing mechanism for most early PC operating systems.
+
+ The SMB3 protocol is supported by most modern operating systems
+ and NAS appliances (e.g. Samba, Windows 10, Windows Server 2016,
+ MacOS) and even in the cloud (e.g. Microsoft Azure).
+ The older CIFS protocol was included in Windows NT4, 2000 and XP (and
+ later) as well by Samba (which provides excellent CIFS and SMB3
+ server support for Linux and many other operating systems). Use of
+ dialects older than SMB2.1 is often discouraged on public networks.
+ This module also provides limited support for OS/2 and Windows ME
+ and similar very old servers.
+
+ This module provides an advanced network file system client
+ for mounting to SMB3 (and CIFS) compliant servers. It includes
+ support for DFS (hierarchical name space), secure per-user
+ session establishment via Kerberos or NTLM or NTLMv2, RDMA
+ (smbdirect), advanced security features, per-share encryption,
+ directory leases, safe distributed caching (oplock), optional packet
+ signing, Unicode and other internationalization improvements.
+
+ In general, the default dialects, SMB3 and later, enable better
+ performance, security and features, than would be possible with CIFS.
+ Note that when mounting to Samba, due to the CIFS POSIX extensions,
+ CIFS mounts can provide slightly better POSIX compatibility
+ than SMB3 mounts. SMB2/SMB3 mount options are also
+ slightly simpler (compared to CIFS) due to protocol improvements.
+
+ If you need to mount to Samba, Azure, Macs or Windows from this machine, say Y.
+
+config CIFS_STATS2
+ bool "Extended statistics"
+ depends on CIFS
+ default y
+ help
+ Enabling this option will allow more detailed statistics on SMB
+ request timing to be displayed in /proc/fs/cifs/DebugData and also
+ allow optional logging of slow responses to dmesg (depending on the
+ value of /proc/fs/cifs/cifsFYI). See Documentation/admin-guide/cifs/usage.rst
+ for more details. These additional statistics may have a minor effect
+ on performance and memory utilization.
+
+ If unsure, say Y.
+
+config CIFS_ALLOW_INSECURE_LEGACY
+ bool "Support legacy servers which use less secure dialects"
+ depends on CIFS
+ default y
+ help
+ Modern dialects, SMB2.1 and later (including SMB3 and 3.1.1), have
+ additional security features, including protection against
+ man-in-the-middle attacks and stronger crypto hashes, so the use
+ of legacy dialects (SMB1/CIFS and SMB2.0) is discouraged.
+
+ Disabling this option prevents users from using vers=1.0 or vers=2.0
+ on mounts with cifs.ko
+
+ If unsure, say Y.
+
+config CIFS_UPCALL
+ bool "Kerberos/SPNEGO advanced session setup"
+ depends on CIFS
+ help
+ Enables an upcall mechanism for CIFS which accesses userspace helper
+ utilities to provide SPNEGO packaged (RFC 4178) Kerberos tickets
+ which are needed to mount to certain secure servers (for which more
+ secure Kerberos authentication is required). If unsure, say Y.
+
+config CIFS_XATTR
+ bool "CIFS extended attributes"
+ depends on CIFS
+ help
+ Extended attributes are name:value pairs associated with inodes by
+ the kernel or by users (see the attr(5) manual page for details).
+ CIFS maps the name of extended attributes beginning with the user
+ namespace prefix to SMB/CIFS EAs. EAs are stored on Windows
+ servers without the user namespace prefix, but their names are
+ seen by Linux cifs clients prefaced by the user namespace prefix.
+ The system namespace (used by some filesystems to store ACLs) is
+ not supported at this time.
+
+ If unsure, say Y.
+
+config CIFS_POSIX
+ bool "CIFS POSIX Extensions"
+ depends on CIFS && CIFS_ALLOW_INSECURE_LEGACY && CIFS_XATTR
+ help
+ Enabling this option will cause the cifs client to attempt to
+ negotiate a newer dialect with servers, such as Samba 3.0.5
+ or later, that optionally can handle more POSIX like (rather
+ than Windows like) file behavior. It also enables
+ support for POSIX ACLs (getfacl and setfacl) to servers
+ (such as Samba 3.10 and later) which can negotiate
+ CIFS POSIX ACL support. If unsure, say N.
+
+config CIFS_DEBUG
+ bool "Enable CIFS debugging routines"
+ default y
+ depends on CIFS
+ help
+ Enabling this option adds helpful debugging messages to
+ the cifs code which increases the size of the cifs module.
+ If unsure, say Y.
+
+config CIFS_DEBUG2
+ bool "Enable additional CIFS debugging routines"
+ depends on CIFS_DEBUG
+ help
+ Enabling this option adds a few more debugging routines
+ to the cifs code which slightly increases the size of
+ the cifs module and can cause additional logging of debug
+ messages in some error paths, slowing performance. This
+ option can be turned off unless you are debugging
+ cifs problems. If unsure, say N.
+
+config CIFS_DEBUG_DUMP_KEYS
+ bool "Dump encryption keys for offline decryption (Unsafe)"
+ depends on CIFS_DEBUG
+ help
+ Enabling this will dump the encryption and decryption keys
+ used to communicate on an encrypted share connection on the
+ console. This allows Wireshark to decrypt and dissect
+ encrypted network captures. Enable this carefully.
+ If unsure, say N.
+
+config CIFS_DFS_UPCALL
+ bool "DFS feature support"
+ depends on CIFS
+ help
+ Distributed File System (DFS) support is used to access shares
+ transparently in an enterprise name space, even if the share
+ moves to a different server. This feature also enables
+ an upcall mechanism for CIFS which contacts userspace helper
+ utilities to provide server name resolution (host names to
+ IP addresses) which is needed in order to reconnect to
+ servers if their addresses change or for implicit mounts of
+ DFS junction points. If unsure, say Y.
+
+config CIFS_SWN_UPCALL
+ bool "SWN feature support"
+ depends on CIFS
+ help
+ The Service Witness Protocol (SWN) is used to get notifications
+ from a highly available server of resource state changes. This
+ feature enables an upcall mechanism for CIFS which contacts a
+ userspace daemon to establish the DCE/RPC connection to retrieve
+ the cluster available interfaces and resource change notifications.
+ If unsure, say Y.
+
+config CIFS_NFSD_EXPORT
+ bool "Allow nfsd to export CIFS file system"
+ depends on CIFS && BROKEN
+ help
+ Allows NFS server to export a CIFS mounted share (nfsd over cifs)
+
+config CIFS_SMB_DIRECT
+ bool "SMB Direct support"
+ depends on CIFS=m && INFINIBAND && INFINIBAND_ADDR_TRANS || CIFS=y && INFINIBAND=y && INFINIBAND_ADDR_TRANS=y
+ help
+ Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1.
+ SMB Direct allows transferring SMB packets over RDMA. If unsure,
+ say Y.
+
+config CIFS_FSCACHE
+ bool "Provide CIFS client caching support"
+ depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
+ help
+ Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
+ to be cached locally on disk through the general filesystem cache
+ manager. If unsure, say N.
+
+config CIFS_ROOT
+ bool "SMB root file system (Experimental)"
+ depends on CIFS=y && IP_PNP
+ help
+ Enables root file system support over SMB protocol.
+
+ Most people say N here.
diff --git a/fs/smb/client/Makefile b/fs/smb/client/Makefile
new file mode 100644
index 000000000000..7c9785973f49
--- /dev/null
+++ b/fs/smb/client/Makefile
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Linux CIFS/SMB2/SMB3 VFS client
+#
+ccflags-y += -I$(src) # needed for trace events
+obj-$(CONFIG_CIFS) += cifs.o
+
+cifs-y := trace.o cifsfs.o cifs_debug.o connect.o dir.o file.o \
+ inode.o link.o misc.o netmisc.o smbencrypt.o transport.o \
+ cached_dir.o cifs_unicode.o nterr.o cifsencrypt.o \
+ readdir.o ioctl.o sess.o export.o unc.o winucase.o \
+ smb2ops.o smb2maperror.o smb2transport.o \
+ smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o \
+ dns_resolve.o cifs_spnego_negtokeninit.asn1.o asn1.o
+
+$(obj)/asn1.o: $(obj)/cifs_spnego_negtokeninit.asn1.h
+
+$(obj)/cifs_spnego_negtokeninit.asn1.o: $(obj)/cifs_spnego_negtokeninit.asn1.c $(obj)/cifs_spnego_negtokeninit.asn1.h
+
+cifs-$(CONFIG_CIFS_XATTR) += xattr.o
+
+cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
+
+cifs-$(CONFIG_CIFS_DFS_UPCALL) += cifs_dfs_ref.o dfs_cache.o
+
+cifs-$(CONFIG_CIFS_SWN_UPCALL) += netlink.o cifs_swn.o
+
+cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o
+
+cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o
+
+cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o
+
+cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o
diff --git a/fs/smb/client/asn1.c b/fs/smb/client/asn1.c
new file mode 100644
index 000000000000..b5724ef9f182
--- /dev/null
+++ b/fs/smb/client/asn1.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/oid_registry.h>
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "cifsproto.h"
+#include "cifs_spnego_negtokeninit.asn1.h"
+
+int
+decode_negTokenInit(unsigned char *security_blob, int length,
+ struct TCP_Server_Info *server)
+{
+ if (asn1_ber_decoder(&cifs_spnego_negtokeninit_decoder, server,
+ security_blob, length) == 0)
+ return 1;
+ else
+ return 0;
+}
+
+int cifs_gssapi_this_mech(void *context, size_t hdrlen,
+ unsigned char tag, const void *value, size_t vlen)
+{
+ enum OID oid;
+
+ oid = look_up_OID(value, vlen);
+ if (oid != OID_spnego) {
+ char buf[50];
+
+ sprint_oid(value, vlen, buf, sizeof(buf));
+ cifs_dbg(FYI, "Error decoding negTokenInit header: unexpected OID %s\n",
+ buf);
+ return -EBADMSG;
+ }
+ return 0;
+}
+
+int cifs_neg_token_init_mech_type(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct TCP_Server_Info *server = context;
+ enum OID oid;
+
+ oid = look_up_OID(value, vlen);
+ if (oid == OID_mskrb5)
+ server->sec_mskerberos = true;
+ else if (oid == OID_krb5u2u)
+ server->sec_kerberosu2u = true;
+ else if (oid == OID_krb5)
+ server->sec_kerberos = true;
+ else if (oid == OID_ntlmssp)
+ server->sec_ntlmssp = true;
+ else {
+ char buf[50];
+
+ sprint_oid(value, vlen, buf, sizeof(buf));
+ cifs_dbg(FYI, "Decoding negTokenInit: unsupported OID %s\n",
+ buf);
+ }
+ return 0;
+}
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
new file mode 100644
index 000000000000..bfc964b36c72
--- /dev/null
+++ b/fs/smb/client/cached_dir.c
@@ -0,0 +1,606 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Functions to handle the cached directory entries
+ *
+ * Copyright (c) 2022, Ronnie Sahlberg <lsahlber@redhat.com>
+ */
+
+#include <linux/namei.h>
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "smb2proto.h"
+#include "cached_dir.h"
+
+static struct cached_fid *init_cached_dir(const char *path);
+static void free_cached_dir(struct cached_fid *cfid);
+static void smb2_close_cached_fid(struct kref *ref);
+
+static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
+ const char *path,
+ bool lookup_only)
+{
+ struct cached_fid *cfid;
+
+ spin_lock(&cfids->cfid_list_lock);
+ list_for_each_entry(cfid, &cfids->entries, entry) {
+ if (!strcmp(cfid->path, path)) {
+ /*
+ * If it doesn't have a lease it is either not yet
+ * fully cached or it may be in the process of
+ * being deleted due to a lease break.
+ */
+ if (!cfid->has_lease) {
+ spin_unlock(&cfids->cfid_list_lock);
+ return NULL;
+ }
+ kref_get(&cfid->refcount);
+ spin_unlock(&cfids->cfid_list_lock);
+ return cfid;
+ }
+ }
+ if (lookup_only) {
+ spin_unlock(&cfids->cfid_list_lock);
+ return NULL;
+ }
+ if (cfids->num_entries >= MAX_CACHED_FIDS) {
+ spin_unlock(&cfids->cfid_list_lock);
+ return NULL;
+ }
+ cfid = init_cached_dir(path);
+ if (cfid == NULL) {
+ spin_unlock(&cfids->cfid_list_lock);
+ return NULL;
+ }
+ cfid->cfids = cfids;
+ cfids->num_entries++;
+ list_add(&cfid->entry, &cfids->entries);
+ cfid->on_list = true;
+ kref_get(&cfid->refcount);
+ spin_unlock(&cfids->cfid_list_lock);
+ return cfid;
+}
+
+static struct dentry *
+path_to_dentry(struct cifs_sb_info *cifs_sb, const char *path)
+{
+ struct dentry *dentry;
+ const char *s, *p;
+ char sep;
+
+ sep = CIFS_DIR_SEP(cifs_sb);
+ dentry = dget(cifs_sb->root);
+ s = path;
+
+ do {
+ struct inode *dir = d_inode(dentry);
+ struct dentry *child;
+
+ if (!S_ISDIR(dir->i_mode)) {
+ dput(dentry);
+ dentry = ERR_PTR(-ENOTDIR);
+ break;
+ }
+
+ /* skip separators */
+ while (*s == sep)
+ s++;
+ if (!*s)
+ break;
+ p = s++;
+ /* next separator */
+ while (*s && *s != sep)
+ s++;
+
+ child = lookup_positive_unlocked(p, dentry, s - p);
+ dput(dentry);
+ dentry = child;
+ } while (!IS_ERR(dentry));
+ return dentry;
+}
+
+static const char *path_no_prefix(struct cifs_sb_info *cifs_sb,
+ const char *path)
+{
+ size_t len = 0;
+
+ if (!*path)
+ return path;
+
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
+ cifs_sb->prepath) {
+ len = strlen(cifs_sb->prepath) + 1;
+ if (unlikely(len > strlen(path)))
+ return ERR_PTR(-EINVAL);
+ }
+ return path + len;
+}
+
+/*
+ * Open the and cache a directory handle.
+ * If error then *cfid is not initialized.
+ */
+int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
+ const char *path,
+ struct cifs_sb_info *cifs_sb,
+ bool lookup_only, struct cached_fid **ret_cfid)
+{
+ struct cifs_ses *ses;
+ struct TCP_Server_Info *server;
+ struct cifs_open_parms oparms;
+ struct smb2_create_rsp *o_rsp = NULL;
+ struct smb2_query_info_rsp *qi_rsp = NULL;
+ int resp_buftype[2];
+ struct smb_rqst rqst[2];
+ struct kvec rsp_iov[2];
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+ struct kvec qi_iov[1];
+ int rc, flags = 0;
+ __le16 *utf16_path = NULL;
+ u8 oplock = SMB2_OPLOCK_LEVEL_II;
+ struct cifs_fid *pfid;
+ struct dentry *dentry = NULL;
+ struct cached_fid *cfid;
+ struct cached_fids *cfids;
+ const char *npath;
+
+ if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache ||
+ is_smb1_server(tcon->ses->server))
+ return -EOPNOTSUPP;
+
+ ses = tcon->ses;
+ server = ses->server;
+ cfids = tcon->cfids;
+
+ if (!server->ops->new_lease_key)
+ return -EIO;
+
+ if (cifs_sb->root == NULL)
+ return -ENOENT;
+
+ utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
+
+ cfid = find_or_create_cached_dir(cfids, path, lookup_only);
+ if (cfid == NULL) {
+ kfree(utf16_path);
+ return -ENOENT;
+ }
+ /*
+ * At this point we either have a lease already and we can just
+ * return it. If not we are guaranteed to be the only thread accessing
+ * this cfid.
+ */
+ if (cfid->has_lease) {
+ *ret_cfid = cfid;
+ kfree(utf16_path);
+ return 0;
+ }
+
+ /*
+ * Skip any prefix paths in @path as lookup_positive_unlocked() ends up
+ * calling ->lookup() which already adds those through
+ * build_path_from_dentry(). Also, do it earlier as we might reconnect
+ * below when trying to send compounded request and then potentially
+ * having a different prefix path (e.g. after DFS failover).
+ */
+ npath = path_no_prefix(cifs_sb, path);
+ if (IS_ERR(npath)) {
+ rc = PTR_ERR(npath);
+ kfree(utf16_path);
+ return rc;
+ }
+
+ /*
+ * We do not hold the lock for the open because in case
+ * SMB2_open needs to reconnect.
+ * This is safe because no other thread will be able to get a ref
+ * to the cfid until we have finished opening the file and (possibly)
+ * acquired a lease.
+ */
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ pfid = &cfid->fid;
+ server->ops->new_lease_key(pfid);
+
+ memset(rqst, 0, sizeof(rqst));
+ resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER;
+ memset(rsp_iov, 0, sizeof(rsp_iov));
+
+ /* Open */
+ memset(&open_iov, 0, sizeof(open_iov));
+ rqst[0].rq_iov = open_iov;
+ rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = path,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE),
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .disposition = FILE_OPEN,
+ .fid = pfid,
+ };
+
+ rc = SMB2_open_init(tcon, server,
+ &rqst[0], &oplock, &oparms, utf16_path);
+ if (rc)
+ goto oshr_free;
+ smb2_set_next_command(tcon, &rqst[0]);
+
+ memset(&qi_iov, 0, sizeof(qi_iov));
+ rqst[1].rq_iov = qi_iov;
+ rqst[1].rq_nvec = 1;
+
+ rc = SMB2_query_info_init(tcon, server,
+ &rqst[1], COMPOUND_FID,
+ COMPOUND_FID, FILE_ALL_INFORMATION,
+ SMB2_O_INFO_FILE, 0,
+ sizeof(struct smb2_file_all_info) +
+ PATH_MAX * 2, 0, NULL);
+ if (rc)
+ goto oshr_free;
+
+ smb2_set_related(&rqst[1]);
+
+ rc = compound_send_recv(xid, ses, server,
+ flags, 2, rqst,
+ resp_buftype, rsp_iov);
+ if (rc) {
+ if (rc == -EREMCHG) {
+ tcon->need_reconnect = true;
+ pr_warn_once("server share %s deleted\n",
+ tcon->tree_name);
+ }
+ goto oshr_free;
+ }
+ cfid->tcon = tcon;
+ cfid->is_open = true;
+
+ o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
+ oparms.fid->persistent_fid = o_rsp->PersistentFileId;
+ oparms.fid->volatile_fid = o_rsp->VolatileFileId;
+#ifdef CONFIG_CIFS_DEBUG2
+ oparms.fid->mid = le64_to_cpu(o_rsp->hdr.MessageId);
+#endif /* CIFS_DEBUG2 */
+
+ if (o_rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
+ goto oshr_free;
+
+ smb2_parse_contexts(server, o_rsp,
+ &oparms.fid->epoch,
+ oparms.fid->lease_key, &oplock,
+ NULL, NULL);
+ if (!(oplock & SMB2_LEASE_READ_CACHING_HE))
+ goto oshr_free;
+ qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
+ if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info))
+ goto oshr_free;
+ if (!smb2_validate_and_copy_iov(
+ le16_to_cpu(qi_rsp->OutputBufferOffset),
+ sizeof(struct smb2_file_all_info),
+ &rsp_iov[1], sizeof(struct smb2_file_all_info),
+ (char *)&cfid->file_all_info))
+ cfid->file_all_info_is_valid = true;
+
+ if (!npath[0])
+ dentry = dget(cifs_sb->root);
+ else {
+ dentry = path_to_dentry(cifs_sb, npath);
+ if (IS_ERR(dentry)) {
+ rc = -ENOENT;
+ goto oshr_free;
+ }
+ }
+ cfid->dentry = dentry;
+ cfid->time = jiffies;
+ cfid->has_lease = true;
+
+oshr_free:
+ kfree(utf16_path);
+ SMB2_open_free(&rqst[0]);
+ SMB2_query_info_free(&rqst[1]);
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ spin_lock(&cfids->cfid_list_lock);
+ if (rc && !cfid->has_lease) {
+ if (cfid->on_list) {
+ list_del(&cfid->entry);
+ cfid->on_list = false;
+ cfids->num_entries--;
+ }
+ rc = -ENOENT;
+ }
+ spin_unlock(&cfids->cfid_list_lock);
+ if (!rc && !cfid->has_lease) {
+ /*
+ * We are guaranteed to have two references at this point.
+ * One for the caller and one for a potential lease.
+ * Release the Lease-ref so that the directory will be closed
+ * when the caller closes the cached handle.
+ */
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
+ }
+ if (rc) {
+ if (cfid->is_open)
+ SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
+ cfid->fid.volatile_fid);
+ free_cached_dir(cfid);
+ cfid = NULL;
+ }
+
+ if (rc == 0) {
+ *ret_cfid = cfid;
+ atomic_inc(&tcon->num_remote_opens);
+ }
+
+ return rc;
+}
+
+int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
+ struct dentry *dentry,
+ struct cached_fid **ret_cfid)
+{
+ struct cached_fid *cfid;
+ struct cached_fids *cfids = tcon->cfids;
+
+ if (cfids == NULL)
+ return -ENOENT;
+
+ spin_lock(&cfids->cfid_list_lock);
+ list_for_each_entry(cfid, &cfids->entries, entry) {
+ if (dentry && cfid->dentry == dentry) {
+ cifs_dbg(FYI, "found a cached root file handle by dentry\n");
+ kref_get(&cfid->refcount);
+ *ret_cfid = cfid;
+ spin_unlock(&cfids->cfid_list_lock);
+ return 0;
+ }
+ }
+ spin_unlock(&cfids->cfid_list_lock);
+ return -ENOENT;
+}
+
+static void
+smb2_close_cached_fid(struct kref *ref)
+{
+ struct cached_fid *cfid = container_of(ref, struct cached_fid,
+ refcount);
+
+ spin_lock(&cfid->cfids->cfid_list_lock);
+ if (cfid->on_list) {
+ list_del(&cfid->entry);
+ cfid->on_list = false;
+ cfid->cfids->num_entries--;
+ }
+ spin_unlock(&cfid->cfids->cfid_list_lock);
+
+ dput(cfid->dentry);
+ cfid->dentry = NULL;
+
+ if (cfid->is_open) {
+ SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
+ cfid->fid.volatile_fid);
+ atomic_dec(&cfid->tcon->num_remote_opens);
+ }
+
+ free_cached_dir(cfid);
+}
+
+void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *name, struct cifs_sb_info *cifs_sb)
+{
+ struct cached_fid *cfid = NULL;
+ int rc;
+
+ rc = open_cached_dir(xid, tcon, name, cifs_sb, true, &cfid);
+ if (rc) {
+ cifs_dbg(FYI, "no cached dir found for rmdir(%s)\n", name);
+ return;
+ }
+ spin_lock(&cfid->cfids->cfid_list_lock);
+ if (cfid->has_lease) {
+ cfid->has_lease = false;
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
+ }
+ spin_unlock(&cfid->cfids->cfid_list_lock);
+ close_cached_dir(cfid);
+}
+
+
+void close_cached_dir(struct cached_fid *cfid)
+{
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
+}
+
+/*
+ * Called from cifs_kill_sb when we unmount a share
+ */
+void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
+{
+ struct rb_root *root = &cifs_sb->tlink_tree;
+ struct rb_node *node;
+ struct cached_fid *cfid;
+ struct cifs_tcon *tcon;
+ struct tcon_link *tlink;
+ struct cached_fids *cfids;
+
+ for (node = rb_first(root); node; node = rb_next(node)) {
+ tlink = rb_entry(node, struct tcon_link, tl_rbnode);
+ tcon = tlink_tcon(tlink);
+ if (IS_ERR(tcon))
+ continue;
+ cfids = tcon->cfids;
+ if (cfids == NULL)
+ continue;
+ list_for_each_entry(cfid, &cfids->entries, entry) {
+ dput(cfid->dentry);
+ cfid->dentry = NULL;
+ }
+ }
+}
+
+/*
+ * Invalidate all cached dirs when a TCON has been reset
+ * due to a session loss.
+ */
+void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
+{
+ struct cached_fids *cfids = tcon->cfids;
+ struct cached_fid *cfid, *q;
+ LIST_HEAD(entry);
+
+ spin_lock(&cfids->cfid_list_lock);
+ list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
+ list_move(&cfid->entry, &entry);
+ cfids->num_entries--;
+ cfid->is_open = false;
+ cfid->on_list = false;
+ /* To prevent race with smb2_cached_lease_break() */
+ kref_get(&cfid->refcount);
+ }
+ spin_unlock(&cfids->cfid_list_lock);
+
+ list_for_each_entry_safe(cfid, q, &entry, entry) {
+ list_del(&cfid->entry);
+ cancel_work_sync(&cfid->lease_break);
+ if (cfid->has_lease) {
+ /*
+ * We lease was never cancelled from the server so we
+ * need to drop the reference.
+ */
+ spin_lock(&cfids->cfid_list_lock);
+ cfid->has_lease = false;
+ spin_unlock(&cfids->cfid_list_lock);
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
+ }
+ /* Drop the extra reference opened above*/
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
+ }
+}
+
+static void
+smb2_cached_lease_break(struct work_struct *work)
+{
+ struct cached_fid *cfid = container_of(work,
+ struct cached_fid, lease_break);
+
+ spin_lock(&cfid->cfids->cfid_list_lock);
+ cfid->has_lease = false;
+ spin_unlock(&cfid->cfids->cfid_list_lock);
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
+}
+
+int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
+{
+ struct cached_fids *cfids = tcon->cfids;
+ struct cached_fid *cfid;
+
+ if (cfids == NULL)
+ return false;
+
+ spin_lock(&cfids->cfid_list_lock);
+ list_for_each_entry(cfid, &cfids->entries, entry) {
+ if (cfid->has_lease &&
+ !memcmp(lease_key,
+ cfid->fid.lease_key,
+ SMB2_LEASE_KEY_SIZE)) {
+ cfid->time = 0;
+ /*
+ * We found a lease remove it from the list
+ * so no threads can access it.
+ */
+ list_del(&cfid->entry);
+ cfid->on_list = false;
+ cfids->num_entries--;
+
+ queue_work(cifsiod_wq,
+ &cfid->lease_break);
+ spin_unlock(&cfids->cfid_list_lock);
+ return true;
+ }
+ }
+ spin_unlock(&cfids->cfid_list_lock);
+ return false;
+}
+
+static struct cached_fid *init_cached_dir(const char *path)
+{
+ struct cached_fid *cfid;
+
+ cfid = kzalloc(sizeof(*cfid), GFP_ATOMIC);
+ if (!cfid)
+ return NULL;
+ cfid->path = kstrdup(path, GFP_ATOMIC);
+ if (!cfid->path) {
+ kfree(cfid);
+ return NULL;
+ }
+
+ INIT_WORK(&cfid->lease_break, smb2_cached_lease_break);
+ INIT_LIST_HEAD(&cfid->entry);
+ INIT_LIST_HEAD(&cfid->dirents.entries);
+ mutex_init(&cfid->dirents.de_mutex);
+ spin_lock_init(&cfid->fid_lock);
+ kref_init(&cfid->refcount);
+ return cfid;
+}
+
+static void free_cached_dir(struct cached_fid *cfid)
+{
+ struct cached_dirent *dirent, *q;
+
+ dput(cfid->dentry);
+ cfid->dentry = NULL;
+
+ /*
+ * Delete all cached dirent names
+ */
+ list_for_each_entry_safe(dirent, q, &cfid->dirents.entries, entry) {
+ list_del(&dirent->entry);
+ kfree(dirent->name);
+ kfree(dirent);
+ }
+
+ kfree(cfid->path);
+ cfid->path = NULL;
+ kfree(cfid);
+}
+
+struct cached_fids *init_cached_dirs(void)
+{
+ struct cached_fids *cfids;
+
+ cfids = kzalloc(sizeof(*cfids), GFP_KERNEL);
+ if (!cfids)
+ return NULL;
+ spin_lock_init(&cfids->cfid_list_lock);
+ INIT_LIST_HEAD(&cfids->entries);
+ return cfids;
+}
+
+/*
+ * Called from tconInfoFree when we are tearing down the tcon.
+ * There are no active users or open files/directories at this point.
+ */
+void free_cached_dirs(struct cached_fids *cfids)
+{
+ struct cached_fid *cfid, *q;
+ LIST_HEAD(entry);
+
+ spin_lock(&cfids->cfid_list_lock);
+ list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
+ cfid->on_list = false;
+ cfid->is_open = false;
+ list_move(&cfid->entry, &entry);
+ }
+ spin_unlock(&cfids->cfid_list_lock);
+
+ list_for_each_entry_safe(cfid, q, &entry, entry) {
+ list_del(&cfid->entry);
+ free_cached_dir(cfid);
+ }
+
+ kfree(cfids);
+}
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
new file mode 100644
index 000000000000..2f4e764c9ca9
--- /dev/null
+++ b/fs/smb/client/cached_dir.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Functions to handle the cached directory entries
+ *
+ * Copyright (c) 2022, Ronnie Sahlberg <lsahlber@redhat.com>
+ */
+
+#ifndef _CACHED_DIR_H
+#define _CACHED_DIR_H
+
+
+struct cached_dirent {
+ struct list_head entry;
+ char *name;
+ int namelen;
+ loff_t pos;
+
+ struct cifs_fattr fattr;
+};
+
+struct cached_dirents {
+ bool is_valid:1;
+ bool is_failed:1;
+ struct dir_context *ctx; /*
+ * Only used to make sure we only take entries
+ * from a single context. Never dereferenced.
+ */
+ struct mutex de_mutex;
+ int pos; /* Expected ctx->pos */
+ struct list_head entries;
+};
+
+struct cached_fid {
+ struct list_head entry;
+ struct cached_fids *cfids;
+ const char *path;
+ bool has_lease:1;
+ bool is_open:1;
+ bool on_list:1;
+ bool file_all_info_is_valid:1;
+ unsigned long time; /* jiffies of when lease was taken */
+ struct kref refcount;
+ struct cifs_fid fid;
+ spinlock_t fid_lock;
+ struct cifs_tcon *tcon;
+ struct dentry *dentry;
+ struct work_struct lease_break;
+ struct smb2_file_all_info file_all_info;
+ struct cached_dirents dirents;
+};
+
+#define MAX_CACHED_FIDS 16
+struct cached_fids {
+ /* Must be held when:
+ * - accessing the cfids->entries list
+ */
+ spinlock_t cfid_list_lock;
+ int num_entries;
+ struct list_head entries;
+};
+
+extern struct cached_fids *init_cached_dirs(void);
+extern void free_cached_dirs(struct cached_fids *cfids);
+extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
+ const char *path,
+ struct cifs_sb_info *cifs_sb,
+ bool lookup_only, struct cached_fid **cfid);
+extern int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
+ struct dentry *dentry,
+ struct cached_fid **cfid);
+extern void close_cached_dir(struct cached_fid *cfid);
+extern void drop_cached_dir_by_name(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const char *name,
+ struct cifs_sb_info *cifs_sb);
+extern void close_all_cached_dirs(struct cifs_sb_info *cifs_sb);
+extern void invalidate_all_cached_dirs(struct cifs_tcon *tcon);
+extern int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]);
+
+#endif /* _CACHED_DIR_H */
diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
new file mode 100644
index 000000000000..e41154ad96af
--- /dev/null
+++ b/fs/smb/client/cifs_debug.c
@@ -0,0 +1,1067 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2000,2005
+ *
+ * Modified by Steve French (sfrench@us.ibm.com)
+ */
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifsfs.h"
+#include "fs_context.h"
+#ifdef CONFIG_CIFS_DFS_UPCALL
+#include "dfs_cache.h"
+#endif
+#ifdef CONFIG_CIFS_SMB_DIRECT
+#include "smbdirect.h"
+#endif
+#include "cifs_swn.h"
+
+void
+cifs_dump_mem(char *label, void *data, int length)
+{
+ pr_debug("%s: dump of %d bytes of data at 0x%p\n", label, length, data);
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
+ data, length, true);
+}
+
+void cifs_dump_detail(void *buf, struct TCP_Server_Info *server)
+{
+#ifdef CONFIG_CIFS_DEBUG2
+ struct smb_hdr *smb = buf;
+
+ cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n",
+ smb->Command, smb->Status.CifsError,
+ smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
+ cifs_dbg(VFS, "smb buf %p len %u\n", smb,
+ server->ops->calc_smb_size(smb));
+#endif /* CONFIG_CIFS_DEBUG2 */
+}
+
+void cifs_dump_mids(struct TCP_Server_Info *server)
+{
+#ifdef CONFIG_CIFS_DEBUG2
+ struct mid_q_entry *mid_entry;
+
+ if (server == NULL)
+ return;
+
+ cifs_dbg(VFS, "Dump pending requests:\n");
+ spin_lock(&server->mid_lock);
+ list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
+ cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n",
+ mid_entry->mid_state,
+ le16_to_cpu(mid_entry->command),
+ mid_entry->pid,
+ mid_entry->callback_data,
+ mid_entry->mid);
+#ifdef CONFIG_CIFS_STATS2
+ cifs_dbg(VFS, "IsLarge: %d buf: %p time rcv: %ld now: %ld\n",
+ mid_entry->large_buf,
+ mid_entry->resp_buf,
+ mid_entry->when_received,
+ jiffies);
+#endif /* STATS2 */
+ cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
+ mid_entry->multiRsp, mid_entry->multiEnd);
+ if (mid_entry->resp_buf) {
+ cifs_dump_detail(mid_entry->resp_buf, server);
+ cifs_dump_mem("existing buf: ",
+ mid_entry->resp_buf, 62);
+ }
+ }
+ spin_unlock(&server->mid_lock);
+#endif /* CONFIG_CIFS_DEBUG2 */
+}
+
+#ifdef CONFIG_PROC_FS
+static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
+{
+ __u32 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
+
+ seq_printf(m, "%s Mounts: %d ", tcon->tree_name, tcon->tc_count);
+ if (tcon->nativeFileSystem)
+ seq_printf(m, "Type: %s ", tcon->nativeFileSystem);
+ seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d Status: %d",
+ le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
+ le32_to_cpu(tcon->fsAttrInfo.Attributes),
+ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
+ tcon->status);
+ if (dev_type == FILE_DEVICE_DISK)
+ seq_puts(m, " type: DISK ");
+ else if (dev_type == FILE_DEVICE_CD_ROM)
+ seq_puts(m, " type: CDROM ");
+ else
+ seq_printf(m, " type: %d ", dev_type);
+
+ seq_printf(m, "Serial Number: 0x%x", tcon->vol_serial_number);
+
+ if ((tcon->seal) ||
+ (tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
+ (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
+ seq_printf(m, " Encrypted");
+ if (tcon->nocase)
+ seq_printf(m, " nocase");
+ if (tcon->unix_ext)
+ seq_printf(m, " POSIX Extensions");
+ if (tcon->ses->server->ops->dump_share_caps)
+ tcon->ses->server->ops->dump_share_caps(m, tcon);
+ if (tcon->use_witness)
+ seq_puts(m, " Witness");
+ if (tcon->broken_sparse_sup)
+ seq_puts(m, " nosparse");
+ if (tcon->need_reconnect)
+ seq_puts(m, "\tDISCONNECTED ");
+ seq_putc(m, '\n');
+}
+
+static void
+cifs_dump_channel(struct seq_file *m, int i, struct cifs_chan *chan)
+{
+ struct TCP_Server_Info *server = chan->server;
+
+ seq_printf(m, "\n\n\t\tChannel: %d ConnectionId: 0x%llx"
+ "\n\t\tNumber of credits: %d Dialect 0x%x"
+ "\n\t\tTCP status: %d Instance: %d"
+ "\n\t\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d"
+ "\n\t\tIn Send: %d In MaxReq Wait: %d",
+ i+1, server->conn_id,
+ server->credits,
+ server->dialect,
+ server->tcpStatus,
+ server->reconnect_instance,
+ server->srv_count,
+ server->sec_mode,
+ in_flight(server),
+ atomic_read(&server->in_send),
+ atomic_read(&server->num_waiters));
+}
+
+static void
+cifs_dump_iface(struct seq_file *m, struct cifs_server_iface *iface)
+{
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
+
+ seq_printf(m, "\tSpeed: %zu bps\n", iface->speed);
+ seq_puts(m, "\t\tCapabilities: ");
+ if (iface->rdma_capable)
+ seq_puts(m, "rdma ");
+ if (iface->rss_capable)
+ seq_puts(m, "rss ");
+ seq_putc(m, '\n');
+ if (iface->sockaddr.ss_family == AF_INET)
+ seq_printf(m, "\t\tIPv4: %pI4\n", &ipv4->sin_addr);
+ else if (iface->sockaddr.ss_family == AF_INET6)
+ seq_printf(m, "\t\tIPv6: %pI6\n", &ipv6->sin6_addr);
+ if (!iface->is_active)
+ seq_puts(m, "\t\t[for-cleanup]\n");
+}
+
+static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
+{
+ struct TCP_Server_Info *server;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+ struct cifsFileInfo *cfile;
+
+ seq_puts(m, "# Version:1\n");
+ seq_puts(m, "# Format:\n");
+ seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>");
+#ifdef CONFIG_CIFS_DEBUG2
+ seq_printf(m, " <filename> <mid>\n");
+#else
+ seq_printf(m, " <filename>\n");
+#endif /* CIFS_DEBUG2 */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(cfile, &tcon->openFileList, tlist) {
+ seq_printf(m,
+ "0x%x 0x%llx 0x%llx 0x%x %d %d %d %pd",
+ tcon->tid,
+ ses->Suid,
+ cfile->fid.persistent_fid,
+ cfile->f_flags,
+ cfile->count,
+ cfile->pid,
+ from_kuid(&init_user_ns, cfile->uid),
+ cfile->dentry);
+#ifdef CONFIG_CIFS_DEBUG2
+ seq_printf(m, " %llu\n", cfile->fid.mid);
+#else
+ seq_printf(m, "\n");
+#endif /* CIFS_DEBUG2 */
+ }
+ spin_unlock(&tcon->open_file_lock);
+ }
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ seq_putc(m, '\n');
+ return 0;
+}
+
+static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
+{
+ struct mid_q_entry *mid_entry;
+ struct TCP_Server_Info *server;
+ struct TCP_Server_Info *chan_server;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+ struct cifs_server_iface *iface;
+ int c, i, j;
+
+ seq_puts(m,
+ "Display Internal CIFS Data Structures for Debugging\n"
+ "---------------------------------------------------\n");
+ seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
+ seq_printf(m, "Features:");
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ seq_printf(m, " DFS");
+#endif
+#ifdef CONFIG_CIFS_FSCACHE
+ seq_printf(m, ",FSCACHE");
+#endif
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ seq_printf(m, ",SMB_DIRECT");
+#endif
+#ifdef CONFIG_CIFS_STATS2
+ seq_printf(m, ",STATS2");
+#else
+ seq_printf(m, ",STATS");
+#endif
+#ifdef CONFIG_CIFS_DEBUG2
+ seq_printf(m, ",DEBUG2");
+#elif defined(CONFIG_CIFS_DEBUG)
+ seq_printf(m, ",DEBUG");
+#endif
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ seq_printf(m, ",ALLOW_INSECURE_LEGACY");
+#endif
+#ifdef CONFIG_CIFS_POSIX
+ seq_printf(m, ",CIFS_POSIX");
+#endif
+#ifdef CONFIG_CIFS_UPCALL
+ seq_printf(m, ",UPCALL(SPNEGO)");
+#endif
+#ifdef CONFIG_CIFS_XATTR
+ seq_printf(m, ",XATTR");
+#endif
+ seq_printf(m, ",ACL");
+#ifdef CONFIG_CIFS_SWN_UPCALL
+ seq_puts(m, ",WITNESS");
+#endif
+ seq_putc(m, '\n');
+ seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
+ seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
+
+ seq_printf(m, "\nServers: ");
+
+ c = 0;
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
+ /* channel info will be printed as a part of sessions below */
+ if (CIFS_SERVER_IS_CHAN(server))
+ continue;
+
+ c++;
+ seq_printf(m, "\n%d) ConnectionId: 0x%llx ",
+ c, server->conn_id);
+
+ spin_lock(&server->srv_lock);
+ if (server->hostname)
+ seq_printf(m, "Hostname: %s ", server->hostname);
+ spin_unlock(&server->srv_lock);
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ if (!server->rdma)
+ goto skip_rdma;
+
+ if (!server->smbd_conn) {
+ seq_printf(m, "\nSMBDirect transport not available");
+ goto skip_rdma;
+ }
+
+ seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
+ "transport status: %x",
+ server->smbd_conn->protocol,
+ server->smbd_conn->transport_status);
+ seq_printf(m, "\nConn receive_credit_max: %x "
+ "send_credit_target: %x max_send_size: %x",
+ server->smbd_conn->receive_credit_max,
+ server->smbd_conn->send_credit_target,
+ server->smbd_conn->max_send_size);
+ seq_printf(m, "\nConn max_fragmented_recv_size: %x "
+ "max_fragmented_send_size: %x max_receive_size:%x",
+ server->smbd_conn->max_fragmented_recv_size,
+ server->smbd_conn->max_fragmented_send_size,
+ server->smbd_conn->max_receive_size);
+ seq_printf(m, "\nConn keep_alive_interval: %x "
+ "max_readwrite_size: %x rdma_readwrite_threshold: %x",
+ server->smbd_conn->keep_alive_interval,
+ server->smbd_conn->max_readwrite_size,
+ server->smbd_conn->rdma_readwrite_threshold);
+ seq_printf(m, "\nDebug count_get_receive_buffer: %x "
+ "count_put_receive_buffer: %x count_send_empty: %x",
+ server->smbd_conn->count_get_receive_buffer,
+ server->smbd_conn->count_put_receive_buffer,
+ server->smbd_conn->count_send_empty);
+ seq_printf(m, "\nRead Queue count_reassembly_queue: %x "
+ "count_enqueue_reassembly_queue: %x "
+ "count_dequeue_reassembly_queue: %x "
+ "fragment_reassembly_remaining: %x "
+ "reassembly_data_length: %x "
+ "reassembly_queue_length: %x",
+ server->smbd_conn->count_reassembly_queue,
+ server->smbd_conn->count_enqueue_reassembly_queue,
+ server->smbd_conn->count_dequeue_reassembly_queue,
+ server->smbd_conn->fragment_reassembly_remaining,
+ server->smbd_conn->reassembly_data_length,
+ server->smbd_conn->reassembly_queue_length);
+ seq_printf(m, "\nCurrent Credits send_credits: %x "
+ "receive_credits: %x receive_credit_target: %x",
+ atomic_read(&server->smbd_conn->send_credits),
+ atomic_read(&server->smbd_conn->receive_credits),
+ server->smbd_conn->receive_credit_target);
+ seq_printf(m, "\nPending send_pending: %x ",
+ atomic_read(&server->smbd_conn->send_pending));
+ seq_printf(m, "\nReceive buffers count_receive_queue: %x "
+ "count_empty_packet_queue: %x",
+ server->smbd_conn->count_receive_queue,
+ server->smbd_conn->count_empty_packet_queue);
+ seq_printf(m, "\nMR responder_resources: %x "
+ "max_frmr_depth: %x mr_type: %x",
+ server->smbd_conn->responder_resources,
+ server->smbd_conn->max_frmr_depth,
+ server->smbd_conn->mr_type);
+ seq_printf(m, "\nMR mr_ready_count: %x mr_used_count: %x",
+ atomic_read(&server->smbd_conn->mr_ready_count),
+ atomic_read(&server->smbd_conn->mr_used_count));
+skip_rdma:
+#endif
+ seq_printf(m, "\nNumber of credits: %d Dialect 0x%x",
+ server->credits, server->dialect);
+ if (server->compress_algorithm == SMB3_COMPRESS_LZNT1)
+ seq_printf(m, " COMPRESS_LZNT1");
+ else if (server->compress_algorithm == SMB3_COMPRESS_LZ77)
+ seq_printf(m, " COMPRESS_LZ77");
+ else if (server->compress_algorithm == SMB3_COMPRESS_LZ77_HUFF)
+ seq_printf(m, " COMPRESS_LZ77_HUFF");
+ if (server->sign)
+ seq_printf(m, " signed");
+ if (server->posix_ext_supported)
+ seq_printf(m, " posix");
+ if (server->nosharesock)
+ seq_printf(m, " nosharesock");
+
+ if (server->rdma)
+ seq_printf(m, "\nRDMA ");
+ seq_printf(m, "\nTCP status: %d Instance: %d"
+ "\nLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
+ server->tcpStatus,
+ server->reconnect_instance,
+ server->srv_count,
+ server->sec_mode, in_flight(server));
+
+ seq_printf(m, "\nIn Send: %d In MaxReq Wait: %d",
+ atomic_read(&server->in_send),
+ atomic_read(&server->num_waiters));
+
+ seq_printf(m, "\n\n\tSessions: ");
+ i = 0;
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+ i++;
+ if ((ses->serverDomain == NULL) ||
+ (ses->serverOS == NULL) ||
+ (ses->serverNOS == NULL)) {
+ seq_printf(m, "\n\t%d) Address: %s Uses: %d Capability: 0x%x\tSession Status: %d ",
+ i, ses->ip_addr, ses->ses_count,
+ ses->capabilities, ses->ses_status);
+ if (ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
+ seq_printf(m, "Guest ");
+ else if (ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
+ seq_printf(m, "Anonymous ");
+ } else {
+ seq_printf(m,
+ "\n\t%d) Name: %s Domain: %s Uses: %d OS: %s "
+ "\n\tNOS: %s\tCapability: 0x%x"
+ "\n\tSMB session status: %d ",
+ i, ses->ip_addr, ses->serverDomain,
+ ses->ses_count, ses->serverOS, ses->serverNOS,
+ ses->capabilities, ses->ses_status);
+ }
+
+ seq_printf(m, "\n\tSecurity type: %s ",
+ get_security_type_str(server->ops->select_sectype(server, ses->sectype)));
+
+ /* dump session id helpful for use with network trace */
+ seq_printf(m, " SessionId: 0x%llx", ses->Suid);
+ if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
+ seq_puts(m, " encrypted");
+ if (ses->sign)
+ seq_puts(m, " signed");
+
+ seq_printf(m, "\n\tUser: %d Cred User: %d",
+ from_kuid(&init_user_ns, ses->linux_uid),
+ from_kuid(&init_user_ns, ses->cred_uid));
+
+ spin_lock(&ses->chan_lock);
+ if (CIFS_CHAN_NEEDS_RECONNECT(ses, 0))
+ seq_puts(m, "\tPrimary channel: DISCONNECTED ");
+ if (CIFS_CHAN_IN_RECONNECT(ses, 0))
+ seq_puts(m, "\t[RECONNECTING] ");
+
+ if (ses->chan_count > 1) {
+ seq_printf(m, "\n\n\tExtra Channels: %zu ",
+ ses->chan_count-1);
+ for (j = 1; j < ses->chan_count; j++) {
+ cifs_dump_channel(m, j, &ses->chans[j]);
+ if (CIFS_CHAN_NEEDS_RECONNECT(ses, j))
+ seq_puts(m, "\tDISCONNECTED ");
+ if (CIFS_CHAN_IN_RECONNECT(ses, j))
+ seq_puts(m, "\t[RECONNECTING] ");
+ }
+ }
+ spin_unlock(&ses->chan_lock);
+
+ seq_puts(m, "\n\n\tShares: ");
+ j = 0;
+
+ seq_printf(m, "\n\t%d) IPC: ", j);
+ if (ses->tcon_ipc)
+ cifs_debug_tcon(m, ses->tcon_ipc);
+ else
+ seq_puts(m, "none\n");
+
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ ++j;
+ seq_printf(m, "\n\t%d) ", j);
+ cifs_debug_tcon(m, tcon);
+ }
+
+ spin_lock(&ses->iface_lock);
+ if (ses->iface_count)
+ seq_printf(m, "\n\n\tServer interfaces: %zu",
+ ses->iface_count);
+ j = 0;
+ list_for_each_entry(iface, &ses->iface_list,
+ iface_head) {
+ seq_printf(m, "\n\t%d)", ++j);
+ cifs_dump_iface(m, iface);
+ if (is_ses_using_iface(ses, iface))
+ seq_puts(m, "\t\t[CONNECTED]\n");
+ }
+ spin_unlock(&ses->iface_lock);
+
+ seq_puts(m, "\n\n\tMIDs: ");
+ spin_lock(&ses->chan_lock);
+ for (j = 0; j < ses->chan_count; j++) {
+ chan_server = ses->chans[j].server;
+ if (!chan_server)
+ continue;
+
+ if (list_empty(&chan_server->pending_mid_q))
+ continue;
+
+ seq_printf(m, "\n\tServer ConnectionId: 0x%llx",
+ chan_server->conn_id);
+ spin_lock(&chan_server->mid_lock);
+ list_for_each_entry(mid_entry, &chan_server->pending_mid_q, qhead) {
+ seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu",
+ mid_entry->mid_state,
+ le16_to_cpu(mid_entry->command),
+ mid_entry->pid,
+ mid_entry->callback_data,
+ mid_entry->mid);
+ }
+ spin_unlock(&chan_server->mid_lock);
+ }
+ spin_unlock(&ses->chan_lock);
+ seq_puts(m, "\n--\n");
+ }
+ if (i == 0)
+ seq_printf(m, "\n\t\t[NONE]");
+ }
+ if (c == 0)
+ seq_printf(m, "\n\t[NONE]");
+
+ spin_unlock(&cifs_tcp_ses_lock);
+ seq_putc(m, '\n');
+ cifs_swn_dump(m);
+
+ /* BB add code to dump additional info such as TCP session info now */
+ return 0;
+}
+
+static ssize_t cifs_stats_proc_write(struct file *file,
+ const char __user *buffer, size_t count, loff_t *ppos)
+{
+ bool bv;
+ int rc;
+ struct TCP_Server_Info *server;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+
+ rc = kstrtobool_from_user(buffer, count, &bv);
+ if (rc == 0) {
+#ifdef CONFIG_CIFS_STATS2
+ int i;
+
+ atomic_set(&total_buf_alloc_count, 0);
+ atomic_set(&total_small_buf_alloc_count, 0);
+#endif /* CONFIG_CIFS_STATS2 */
+ atomic_set(&tcpSesReconnectCount, 0);
+ atomic_set(&tconInfoReconnectCount, 0);
+
+ spin_lock(&GlobalMid_Lock);
+ GlobalMaxActiveXid = 0;
+ GlobalCurrentXid = 0;
+ spin_unlock(&GlobalMid_Lock);
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
+ server->max_in_flight = 0;
+#ifdef CONFIG_CIFS_STATS2
+ for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
+ atomic_set(&server->num_cmds[i], 0);
+ atomic_set(&server->smb2slowcmd[i], 0);
+ server->time_per_cmd[i] = 0;
+ server->slowest_cmd[i] = 0;
+ server->fastest_cmd[0] = 0;
+ }
+#endif /* CONFIG_CIFS_STATS2 */
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ atomic_set(&tcon->num_smbs_sent, 0);
+ spin_lock(&tcon->stat_lock);
+ tcon->bytes_read = 0;
+ tcon->bytes_written = 0;
+ spin_unlock(&tcon->stat_lock);
+ if (server->ops->clear_stats)
+ server->ops->clear_stats(tcon);
+ }
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ } else {
+ return rc;
+ }
+
+ return count;
+}
+
+static int cifs_stats_proc_show(struct seq_file *m, void *v)
+{
+ int i;
+#ifdef CONFIG_CIFS_STATS2
+ int j;
+#endif /* STATS2 */
+ struct TCP_Server_Info *server;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+
+ seq_printf(m, "Resources in use\nCIFS Session: %d\n",
+ sesInfoAllocCount.counter);
+ seq_printf(m, "Share (unique mount targets): %d\n",
+ tconInfoAllocCount.counter);
+ seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n",
+ buf_alloc_count.counter,
+ cifs_min_rcv + tcpSesAllocCount.counter);
+ seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
+ small_buf_alloc_count.counter, cifs_min_small);
+#ifdef CONFIG_CIFS_STATS2
+ seq_printf(m, "Total Large %d Small %d Allocations\n",
+ atomic_read(&total_buf_alloc_count),
+ atomic_read(&total_small_buf_alloc_count));
+#endif /* CONFIG_CIFS_STATS2 */
+
+ seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&mid_count));
+ seq_printf(m,
+ "\n%d session %d share reconnects\n",
+ tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
+
+ seq_printf(m,
+ "Total vfs operations: %d maximum at one time: %d\n",
+ GlobalCurrentXid, GlobalMaxActiveXid);
+
+ i = 0;
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
+ seq_printf(m, "\nMax requests in flight: %d", server->max_in_flight);
+#ifdef CONFIG_CIFS_STATS2
+ seq_puts(m, "\nTotal time spent processing by command. Time ");
+ seq_printf(m, "units are jiffies (%d per second)\n", HZ);
+ seq_puts(m, " SMB3 CMD\tNumber\tTotal Time\tFastest\tSlowest\n");
+ seq_puts(m, " --------\t------\t----------\t-------\t-------\n");
+ for (j = 0; j < NUMBER_OF_SMB2_COMMANDS; j++)
+ seq_printf(m, " %d\t\t%d\t%llu\t\t%u\t%u\n", j,
+ atomic_read(&server->num_cmds[j]),
+ server->time_per_cmd[j],
+ server->fastest_cmd[j],
+ server->slowest_cmd[j]);
+ for (j = 0; j < NUMBER_OF_SMB2_COMMANDS; j++)
+ if (atomic_read(&server->smb2slowcmd[j])) {
+ spin_lock(&server->srv_lock);
+ seq_printf(m, " %d slow responses from %s for command %d\n",
+ atomic_read(&server->smb2slowcmd[j]),
+ server->hostname, j);
+ spin_unlock(&server->srv_lock);
+ }
+#endif /* STATS2 */
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ i++;
+ seq_printf(m, "\n%d) %s", i, tcon->tree_name);
+ if (tcon->need_reconnect)
+ seq_puts(m, "\tDISCONNECTED ");
+ seq_printf(m, "\nSMBs: %d",
+ atomic_read(&tcon->num_smbs_sent));
+ if (server->ops->print_stats)
+ server->ops->print_stats(m, tcon);
+ }
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ seq_putc(m, '\n');
+ return 0;
+}
+
+static int cifs_stats_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cifs_stats_proc_show, NULL);
+}
+
+static const struct proc_ops cifs_stats_proc_ops = {
+ .proc_open = cifs_stats_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+ .proc_write = cifs_stats_proc_write,
+};
+
+#ifdef CONFIG_CIFS_SMB_DIRECT
+#define PROC_FILE_DEFINE(name) \
+static ssize_t name##_write(struct file *file, const char __user *buffer, \
+ size_t count, loff_t *ppos) \
+{ \
+ int rc; \
+ rc = kstrtoint_from_user(buffer, count, 10, & name); \
+ if (rc) \
+ return rc; \
+ return count; \
+} \
+static int name##_proc_show(struct seq_file *m, void *v) \
+{ \
+ seq_printf(m, "%d\n", name ); \
+ return 0; \
+} \
+static int name##_open(struct inode *inode, struct file *file) \
+{ \
+ return single_open(file, name##_proc_show, NULL); \
+} \
+\
+static const struct proc_ops cifs_##name##_proc_fops = { \
+ .proc_open = name##_open, \
+ .proc_read = seq_read, \
+ .proc_lseek = seq_lseek, \
+ .proc_release = single_release, \
+ .proc_write = name##_write, \
+}
+
+PROC_FILE_DEFINE(rdma_readwrite_threshold);
+PROC_FILE_DEFINE(smbd_max_frmr_depth);
+PROC_FILE_DEFINE(smbd_keep_alive_interval);
+PROC_FILE_DEFINE(smbd_max_receive_size);
+PROC_FILE_DEFINE(smbd_max_fragmented_recv_size);
+PROC_FILE_DEFINE(smbd_max_send_size);
+PROC_FILE_DEFINE(smbd_send_credit_target);
+PROC_FILE_DEFINE(smbd_receive_credit_max);
+#endif
+
+static struct proc_dir_entry *proc_fs_cifs;
+static const struct proc_ops cifsFYI_proc_ops;
+static const struct proc_ops cifs_lookup_cache_proc_ops;
+static const struct proc_ops traceSMB_proc_ops;
+static const struct proc_ops cifs_security_flags_proc_ops;
+static const struct proc_ops cifs_linux_ext_proc_ops;
+static const struct proc_ops cifs_mount_params_proc_ops;
+
+void
+cifs_proc_init(void)
+{
+ proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
+ if (proc_fs_cifs == NULL)
+ return;
+
+ proc_create_single("DebugData", 0, proc_fs_cifs,
+ cifs_debug_data_proc_show);
+
+ proc_create_single("open_files", 0400, proc_fs_cifs,
+ cifs_debug_files_proc_show);
+
+ proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_ops);
+ proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_ops);
+ proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_ops);
+ proc_create("LinuxExtensionsEnabled", 0644, proc_fs_cifs,
+ &cifs_linux_ext_proc_ops);
+ proc_create("SecurityFlags", 0644, proc_fs_cifs,
+ &cifs_security_flags_proc_ops);
+ proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
+ &cifs_lookup_cache_proc_ops);
+
+ proc_create("mount_params", 0444, proc_fs_cifs, &cifs_mount_params_proc_ops);
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops);
+#endif
+
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ proc_create("rdma_readwrite_threshold", 0644, proc_fs_cifs,
+ &cifs_rdma_readwrite_threshold_proc_fops);
+ proc_create("smbd_max_frmr_depth", 0644, proc_fs_cifs,
+ &cifs_smbd_max_frmr_depth_proc_fops);
+ proc_create("smbd_keep_alive_interval", 0644, proc_fs_cifs,
+ &cifs_smbd_keep_alive_interval_proc_fops);
+ proc_create("smbd_max_receive_size", 0644, proc_fs_cifs,
+ &cifs_smbd_max_receive_size_proc_fops);
+ proc_create("smbd_max_fragmented_recv_size", 0644, proc_fs_cifs,
+ &cifs_smbd_max_fragmented_recv_size_proc_fops);
+ proc_create("smbd_max_send_size", 0644, proc_fs_cifs,
+ &cifs_smbd_max_send_size_proc_fops);
+ proc_create("smbd_send_credit_target", 0644, proc_fs_cifs,
+ &cifs_smbd_send_credit_target_proc_fops);
+ proc_create("smbd_receive_credit_max", 0644, proc_fs_cifs,
+ &cifs_smbd_receive_credit_max_proc_fops);
+#endif
+}
+
+void
+cifs_proc_clean(void)
+{
+ if (proc_fs_cifs == NULL)
+ return;
+
+ remove_proc_entry("DebugData", proc_fs_cifs);
+ remove_proc_entry("open_files", proc_fs_cifs);
+ remove_proc_entry("cifsFYI", proc_fs_cifs);
+ remove_proc_entry("traceSMB", proc_fs_cifs);
+ remove_proc_entry("Stats", proc_fs_cifs);
+ remove_proc_entry("SecurityFlags", proc_fs_cifs);
+ remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
+ remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
+ remove_proc_entry("mount_params", proc_fs_cifs);
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ remove_proc_entry("dfscache", proc_fs_cifs);
+#endif
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ remove_proc_entry("rdma_readwrite_threshold", proc_fs_cifs);
+ remove_proc_entry("smbd_max_frmr_depth", proc_fs_cifs);
+ remove_proc_entry("smbd_keep_alive_interval", proc_fs_cifs);
+ remove_proc_entry("smbd_max_receive_size", proc_fs_cifs);
+ remove_proc_entry("smbd_max_fragmented_recv_size", proc_fs_cifs);
+ remove_proc_entry("smbd_max_send_size", proc_fs_cifs);
+ remove_proc_entry("smbd_send_credit_target", proc_fs_cifs);
+ remove_proc_entry("smbd_receive_credit_max", proc_fs_cifs);
+#endif
+ remove_proc_entry("fs/cifs", NULL);
+}
+
+static int cifsFYI_proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "%d\n", cifsFYI);
+ return 0;
+}
+
+static int cifsFYI_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cifsFYI_proc_show, NULL);
+}
+
+static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ char c[2] = { '\0' };
+ bool bv;
+ int rc;
+
+ rc = get_user(c[0], buffer);
+ if (rc)
+ return rc;
+ if (strtobool(c, &bv) == 0)
+ cifsFYI = bv;
+ else if ((c[0] > '1') && (c[0] <= '9'))
+ cifsFYI = (int) (c[0] - '0'); /* see cifs_debug.h for meanings */
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static const struct proc_ops cifsFYI_proc_ops = {
+ .proc_open = cifsFYI_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+ .proc_write = cifsFYI_proc_write,
+};
+
+static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "%d\n", linuxExtEnabled);
+ return 0;
+}
+
+static int cifs_linux_ext_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cifs_linux_ext_proc_show, NULL);
+}
+
+static ssize_t cifs_linux_ext_proc_write(struct file *file,
+ const char __user *buffer, size_t count, loff_t *ppos)
+{
+ int rc;
+
+ rc = kstrtobool_from_user(buffer, count, &linuxExtEnabled);
+ if (rc)
+ return rc;
+
+ return count;
+}
+
+static const struct proc_ops cifs_linux_ext_proc_ops = {
+ .proc_open = cifs_linux_ext_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+ .proc_write = cifs_linux_ext_proc_write,
+};
+
+static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "%d\n", lookupCacheEnabled);
+ return 0;
+}
+
+static int cifs_lookup_cache_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cifs_lookup_cache_proc_show, NULL);
+}
+
+static ssize_t cifs_lookup_cache_proc_write(struct file *file,
+ const char __user *buffer, size_t count, loff_t *ppos)
+{
+ int rc;
+
+ rc = kstrtobool_from_user(buffer, count, &lookupCacheEnabled);
+ if (rc)
+ return rc;
+
+ return count;
+}
+
+static const struct proc_ops cifs_lookup_cache_proc_ops = {
+ .proc_open = cifs_lookup_cache_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+ .proc_write = cifs_lookup_cache_proc_write,
+};
+
+static int traceSMB_proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "%d\n", traceSMB);
+ return 0;
+}
+
+static int traceSMB_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, traceSMB_proc_show, NULL);
+}
+
+static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ int rc;
+
+ rc = kstrtobool_from_user(buffer, count, &traceSMB);
+ if (rc)
+ return rc;
+
+ return count;
+}
+
+static const struct proc_ops traceSMB_proc_ops = {
+ .proc_open = traceSMB_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+ .proc_write = traceSMB_proc_write,
+};
+
+static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "0x%x\n", global_secflags);
+ return 0;
+}
+
+static int cifs_security_flags_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cifs_security_flags_proc_show, NULL);
+}
+
+/*
+ * Ensure that if someone sets a MUST flag, that we disable all other MAY
+ * flags except for the ones corresponding to the given MUST flag. If there are
+ * multiple MUST flags, then try to prefer more secure ones.
+ */
+static void
+cifs_security_flags_handle_must_flags(unsigned int *flags)
+{
+ unsigned int signflags = *flags & CIFSSEC_MUST_SIGN;
+
+ if ((*flags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
+ *flags = CIFSSEC_MUST_KRB5;
+ else if ((*flags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
+ *flags = CIFSSEC_MUST_NTLMSSP;
+ else if ((*flags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
+ *flags = CIFSSEC_MUST_NTLMV2;
+
+ *flags |= signflags;
+}
+
+static ssize_t cifs_security_flags_proc_write(struct file *file,
+ const char __user *buffer, size_t count, loff_t *ppos)
+{
+ int rc;
+ unsigned int flags;
+ char flags_string[12];
+ bool bv;
+
+ if ((count < 1) || (count > 11))
+ return -EINVAL;
+
+ memset(flags_string, 0, 12);
+
+ if (copy_from_user(flags_string, buffer, count))
+ return -EFAULT;
+
+ if (count < 3) {
+ /* single char or single char followed by null */
+ if (strtobool(flags_string, &bv) == 0) {
+ global_secflags = bv ? CIFSSEC_MAX : CIFSSEC_DEF;
+ return count;
+ } else if (!isdigit(flags_string[0])) {
+ cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
+ flags_string);
+ return -EINVAL;
+ }
+ }
+
+ /* else we have a number */
+ rc = kstrtouint(flags_string, 0, &flags);
+ if (rc) {
+ cifs_dbg(VFS, "Invalid SecurityFlags: %s\n",
+ flags_string);
+ return rc;
+ }
+
+ cifs_dbg(FYI, "sec flags 0x%x\n", flags);
+
+ if (flags == 0) {
+ cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", flags_string);
+ return -EINVAL;
+ }
+
+ if (flags & ~CIFSSEC_MASK) {
+ cifs_dbg(VFS, "Unsupported security flags: 0x%x\n",
+ flags & ~CIFSSEC_MASK);
+ return -EINVAL;
+ }
+
+ cifs_security_flags_handle_must_flags(&flags);
+
+ /* flags look ok - update the global security flags for cifs module */
+ global_secflags = flags;
+ if (global_secflags & CIFSSEC_MUST_SIGN) {
+ /* requiring signing implies signing is allowed */
+ global_secflags |= CIFSSEC_MAY_SIGN;
+ cifs_dbg(FYI, "packet signing now required\n");
+ } else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) {
+ cifs_dbg(FYI, "packet signing disabled\n");
+ }
+ /* BB should we turn on MAY flags for other MUST options? */
+ return count;
+}
+
+static const struct proc_ops cifs_security_flags_proc_ops = {
+ .proc_open = cifs_security_flags_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+ .proc_write = cifs_security_flags_proc_write,
+};
+
+/* To make it easier to debug, can help to show mount params */
+static int cifs_mount_params_proc_show(struct seq_file *m, void *v)
+{
+ const struct fs_parameter_spec *p;
+ const char *type;
+
+ for (p = smb3_fs_parameters; p->name; p++) {
+ /* cannot use switch with pointers... */
+ if (!p->type) {
+ if (p->flags == fs_param_neg_with_no)
+ type = "noflag";
+ else
+ type = "flag";
+ } else if (p->type == fs_param_is_bool)
+ type = "bool";
+ else if (p->type == fs_param_is_u32)
+ type = "u32";
+ else if (p->type == fs_param_is_u64)
+ type = "u64";
+ else if (p->type == fs_param_is_string)
+ type = "string";
+ else
+ type = "unknown";
+
+ seq_printf(m, "%s:%s\n", p->name, type);
+ }
+
+ return 0;
+}
+
+static int cifs_mount_params_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cifs_mount_params_proc_show, NULL);
+}
+
+static const struct proc_ops cifs_mount_params_proc_ops = {
+ .proc_open = cifs_mount_params_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+ /* No need for write for now */
+ /* .proc_write = cifs_mount_params_proc_write, */
+};
+
+#else
+inline void cifs_proc_init(void)
+{
+}
+
+inline void cifs_proc_clean(void)
+{
+}
+#endif /* PROC_FS */
diff --git a/fs/smb/client/cifs_debug.h b/fs/smb/client/cifs_debug.h
new file mode 100644
index 000000000000..ce5cfd236fdb
--- /dev/null
+++ b/fs/smb/client/cifs_debug.h
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2000,2002
+ * Modified by Steve French (sfrench@us.ibm.com)
+ */
+
+#ifndef _H_CIFS_DEBUG
+#define _H_CIFS_DEBUG
+
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+
+#define pr_fmt(fmt) "CIFS: " fmt
+
+void cifs_dump_mem(char *label, void *data, int length);
+void cifs_dump_detail(void *buf, struct TCP_Server_Info *ptcp_info);
+void cifs_dump_mids(struct TCP_Server_Info *);
+extern bool traceSMB; /* flag which enables the function below */
+void dump_smb(void *, int);
+#define CIFS_INFO 0x01
+#define CIFS_RC 0x02
+#define CIFS_TIMER 0x04
+
+#define VFS 1
+#define FYI 2
+extern int cifsFYI;
+#ifdef CONFIG_CIFS_DEBUG2
+#define NOISY 4
+#else
+#define NOISY 0
+#endif
+#define ONCE 8
+
+/*
+ * debug ON
+ * --------
+ */
+#ifdef CONFIG_CIFS_DEBUG
+
+
+/*
+ * When adding tracepoints and debug messages we have various choices.
+ * Some considerations:
+ *
+ * Use cifs_dbg(VFS, ...) for things we always want logged, and the user to see
+ * cifs_info(...) slightly less important, admin can filter via loglevel > 6
+ * cifs_dbg(FYI, ...) minor debugging messages, off by default
+ * trace_smb3_* ftrace functions are preferred for complex debug messages
+ * intended for developers or experienced admins, off by default
+ */
+
+/* Information level messages, minor events */
+#define cifs_info_func(ratefunc, fmt, ...) \
+ pr_info_ ## ratefunc(fmt, ##__VA_ARGS__)
+
+#define cifs_info(fmt, ...) \
+ cifs_info_func(ratelimited, fmt, ##__VA_ARGS__)
+
+/* information message: e.g., configuration, major event */
+#define cifs_dbg_func(ratefunc, type, fmt, ...) \
+do { \
+ if ((type) & FYI && cifsFYI & CIFS_INFO) { \
+ pr_debug_ ## ratefunc("%s: " fmt, \
+ __FILE__, ##__VA_ARGS__); \
+ } else if ((type) & VFS) { \
+ pr_err_ ## ratefunc("VFS: " fmt, ##__VA_ARGS__); \
+ } else if ((type) & NOISY && (NOISY != 0)) { \
+ pr_debug_ ## ratefunc(fmt, ##__VA_ARGS__); \
+ } \
+} while (0)
+
+#define cifs_dbg(type, fmt, ...) \
+do { \
+ if ((type) & ONCE) \
+ cifs_dbg_func(once, type, fmt, ##__VA_ARGS__); \
+ else \
+ cifs_dbg_func(ratelimited, type, fmt, ##__VA_ARGS__); \
+} while (0)
+
+#define cifs_server_dbg_func(ratefunc, type, fmt, ...) \
+do { \
+ spin_lock(&server->srv_lock); \
+ if ((type) & FYI && cifsFYI & CIFS_INFO) { \
+ pr_debug_ ## ratefunc("%s: \\\\%s " fmt, \
+ __FILE__, server->hostname, \
+ ##__VA_ARGS__); \
+ } else if ((type) & VFS) { \
+ pr_err_ ## ratefunc("VFS: \\\\%s " fmt, \
+ server->hostname, ##__VA_ARGS__); \
+ } else if ((type) & NOISY && (NOISY != 0)) { \
+ pr_debug_ ## ratefunc("\\\\%s " fmt, \
+ server->hostname, ##__VA_ARGS__); \
+ } \
+ spin_unlock(&server->srv_lock); \
+} while (0)
+
+#define cifs_server_dbg(type, fmt, ...) \
+do { \
+ if ((type) & ONCE) \
+ cifs_server_dbg_func(once, type, fmt, ##__VA_ARGS__); \
+ else \
+ cifs_server_dbg_func(ratelimited, type, fmt, \
+ ##__VA_ARGS__); \
+} while (0)
+
+#define cifs_tcon_dbg_func(ratefunc, type, fmt, ...) \
+do { \
+ const char *tn = ""; \
+ if (tcon && tcon->tree_name) \
+ tn = tcon->tree_name; \
+ if ((type) & FYI && cifsFYI & CIFS_INFO) { \
+ pr_debug_ ## ratefunc("%s: %s " fmt, \
+ __FILE__, tn, ##__VA_ARGS__); \
+ } else if ((type) & VFS) { \
+ pr_err_ ## ratefunc("VFS: %s " fmt, tn, ##__VA_ARGS__); \
+ } else if ((type) & NOISY && (NOISY != 0)) { \
+ pr_debug_ ## ratefunc("%s " fmt, tn, ##__VA_ARGS__); \
+ } \
+} while (0)
+
+#define cifs_tcon_dbg(type, fmt, ...) \
+do { \
+ if ((type) & ONCE) \
+ cifs_tcon_dbg_func(once, type, fmt, ##__VA_ARGS__); \
+ else \
+ cifs_tcon_dbg_func(ratelimited, type, fmt, \
+ ##__VA_ARGS__); \
+} while (0)
+
+/*
+ * debug OFF
+ * ---------
+ */
+#else /* _CIFS_DEBUG */
+#define cifs_dbg(type, fmt, ...) \
+do { \
+ if (0) \
+ pr_debug(fmt, ##__VA_ARGS__); \
+} while (0)
+
+#define cifs_server_dbg(type, fmt, ...) \
+do { \
+ if (0) \
+ pr_debug("\\\\%s " fmt, \
+ server->hostname, ##__VA_ARGS__); \
+} while (0)
+
+#define cifs_tcon_dbg(type, fmt, ...) \
+do { \
+ if (0) \
+ pr_debug("%s " fmt, tcon->tree_name, ##__VA_ARGS__); \
+} while (0)
+
+#define cifs_info(fmt, ...) \
+ pr_info(fmt, ##__VA_ARGS__)
+#endif
+
+#endif /* _H_CIFS_DEBUG */
diff --git a/fs/smb/client/cifs_dfs_ref.c b/fs/smb/client/cifs_dfs_ref.c
new file mode 100644
index 000000000000..b0864da9ef43
--- /dev/null
+++ b/fs/smb/client/cifs_dfs_ref.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Contains the CIFS DFS referral mounting routines used for handling
+ * traversal via DFS junction point
+ *
+ * Copyright (c) 2007 Igor Mammedov
+ * Copyright (C) International Business Machines Corp., 2008
+ * Author(s): Igor Mammedov (niallain@gmail.com)
+ * Steve French (sfrench@us.ibm.com)
+ */
+
+#include <linux/dcache.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/slab.h>
+#include <linux/vfs.h>
+#include <linux/fs.h>
+#include <linux/inet.h>
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifsfs.h"
+#include "dns_resolve.h"
+#include "cifs_debug.h"
+#include "cifs_unicode.h"
+#include "dfs_cache.h"
+#include "fs_context.h"
+
+static LIST_HEAD(cifs_dfs_automount_list);
+
+static void cifs_dfs_expire_automounts(struct work_struct *work);
+static DECLARE_DELAYED_WORK(cifs_dfs_automount_task,
+ cifs_dfs_expire_automounts);
+static int cifs_dfs_mountpoint_expiry_timeout = 500 * HZ;
+
+static void cifs_dfs_expire_automounts(struct work_struct *work)
+{
+ struct list_head *list = &cifs_dfs_automount_list;
+
+ mark_mounts_for_expiry(list);
+ if (!list_empty(list))
+ schedule_delayed_work(&cifs_dfs_automount_task,
+ cifs_dfs_mountpoint_expiry_timeout);
+}
+
+void cifs_dfs_release_automount_timer(void)
+{
+ BUG_ON(!list_empty(&cifs_dfs_automount_list));
+ cancel_delayed_work_sync(&cifs_dfs_automount_task);
+}
+
+/**
+ * cifs_build_devname - build a devicename from a UNC and optional prepath
+ * @nodename: pointer to UNC string
+ * @prepath: pointer to prefixpath (or NULL if there isn't one)
+ *
+ * Build a new cifs devicename after chasing a DFS referral. Allocate a buffer
+ * big enough to hold the final thing. Copy the UNC from the nodename, and
+ * concatenate the prepath onto the end of it if there is one.
+ *
+ * Returns pointer to the built string, or a ERR_PTR. Caller is responsible
+ * for freeing the returned string.
+ */
+static char *
+cifs_build_devname(char *nodename, const char *prepath)
+{
+ size_t pplen;
+ size_t unclen;
+ char *dev;
+ char *pos;
+
+ /* skip over any preceding delimiters */
+ nodename += strspn(nodename, "\\");
+ if (!*nodename)
+ return ERR_PTR(-EINVAL);
+
+ /* get length of UNC and set pos to last char */
+ unclen = strlen(nodename);
+ pos = nodename + unclen - 1;
+
+ /* trim off any trailing delimiters */
+ while (*pos == '\\') {
+ --pos;
+ --unclen;
+ }
+
+ /* allocate a buffer:
+ * +2 for preceding "//"
+ * +1 for delimiter between UNC and prepath
+ * +1 for trailing NULL
+ */
+ pplen = prepath ? strlen(prepath) : 0;
+ dev = kmalloc(2 + unclen + 1 + pplen + 1, GFP_KERNEL);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ pos = dev;
+ /* add the initial "//" */
+ *pos = '/';
+ ++pos;
+ *pos = '/';
+ ++pos;
+
+ /* copy in the UNC portion from referral */
+ memcpy(pos, nodename, unclen);
+ pos += unclen;
+
+ /* copy the prefixpath remainder (if there is one) */
+ if (pplen) {
+ *pos = '/';
+ ++pos;
+ memcpy(pos, prepath, pplen);
+ pos += pplen;
+ }
+
+ /* NULL terminator */
+ *pos = '\0';
+
+ convert_delimiter(dev, '/');
+ return dev;
+}
+
+
+/**
+ * cifs_compose_mount_options - creates mount options for referral
+ * @sb_mountdata: parent/root DFS mount options (template)
+ * @fullpath: full path in UNC format
+ * @ref: optional server's referral
+ * @devname: return the built cifs device name if passed pointer not NULL
+ * creates mount options for submount based on template options sb_mountdata
+ * and replacing unc,ip,prefixpath options with ones we've got form ref_unc.
+ *
+ * Returns: pointer to new mount options or ERR_PTR.
+ * Caller is responsible for freeing returned value if it is not error.
+ */
+char *cifs_compose_mount_options(const char *sb_mountdata,
+ const char *fullpath,
+ const struct dfs_info3_param *ref,
+ char **devname)
+{
+ int rc;
+ char *name;
+ char *mountdata = NULL;
+ const char *prepath = NULL;
+ int md_len;
+ char *tkn_e;
+ char *srvIP = NULL;
+ char sep = ',';
+ int off, noff;
+
+ if (sb_mountdata == NULL)
+ return ERR_PTR(-EINVAL);
+
+ if (ref) {
+ if (WARN_ON_ONCE(!ref->node_name || ref->path_consumed < 0))
+ return ERR_PTR(-EINVAL);
+
+ if (strlen(fullpath) - ref->path_consumed) {
+ prepath = fullpath + ref->path_consumed;
+ /* skip initial delimiter */
+ if (*prepath == '/' || *prepath == '\\')
+ prepath++;
+ }
+
+ name = cifs_build_devname(ref->node_name, prepath);
+ if (IS_ERR(name)) {
+ rc = PTR_ERR(name);
+ name = NULL;
+ goto compose_mount_options_err;
+ }
+ } else {
+ name = cifs_build_devname((char *)fullpath, NULL);
+ if (IS_ERR(name)) {
+ rc = PTR_ERR(name);
+ name = NULL;
+ goto compose_mount_options_err;
+ }
+ }
+
+ rc = dns_resolve_server_name_to_ip(name, &srvIP, NULL);
+ if (rc < 0) {
+ cifs_dbg(FYI, "%s: Failed to resolve server part of %s to IP: %d\n",
+ __func__, name, rc);
+ goto compose_mount_options_err;
+ }
+
+ /*
+ * In most cases, we'll be building a shorter string than the original,
+ * but we do have to assume that the address in the ip= option may be
+ * much longer than the original. Add the max length of an address
+ * string to the length of the original string to allow for worst case.
+ */
+ md_len = strlen(sb_mountdata) + INET6_ADDRSTRLEN;
+ mountdata = kzalloc(md_len + sizeof("ip=") + 1, GFP_KERNEL);
+ if (mountdata == NULL) {
+ rc = -ENOMEM;
+ goto compose_mount_options_err;
+ }
+
+ /* copy all options except of unc,ip,prefixpath */
+ off = 0;
+ if (strncmp(sb_mountdata, "sep=", 4) == 0) {
+ sep = sb_mountdata[4];
+ strncpy(mountdata, sb_mountdata, 5);
+ off += 5;
+ }
+
+ do {
+ tkn_e = strchr(sb_mountdata + off, sep);
+ if (tkn_e == NULL)
+ noff = strlen(sb_mountdata + off);
+ else
+ noff = tkn_e - (sb_mountdata + off) + 1;
+
+ if (strncasecmp(sb_mountdata + off, "cruid=", 6) == 0) {
+ off += noff;
+ continue;
+ }
+ if (strncasecmp(sb_mountdata + off, "unc=", 4) == 0) {
+ off += noff;
+ continue;
+ }
+ if (strncasecmp(sb_mountdata + off, "ip=", 3) == 0) {
+ off += noff;
+ continue;
+ }
+ if (strncasecmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
+ off += noff;
+ continue;
+ }
+ strncat(mountdata, sb_mountdata + off, noff);
+ off += noff;
+ } while (tkn_e);
+ strcat(mountdata, sb_mountdata + off);
+ mountdata[md_len] = '\0';
+
+ /* copy new IP and ref share name */
+ if (mountdata[strlen(mountdata) - 1] != sep)
+ strncat(mountdata, &sep, 1);
+ strcat(mountdata, "ip=");
+ strcat(mountdata, srvIP);
+
+ if (devname)
+ *devname = name;
+ else
+ kfree(name);
+
+ /*cifs_dbg(FYI, "%s: parent mountdata: %s\n", __func__, sb_mountdata);*/
+ /*cifs_dbg(FYI, "%s: submount mountdata: %s\n", __func__, mountdata );*/
+
+compose_mount_options_out:
+ kfree(srvIP);
+ return mountdata;
+
+compose_mount_options_err:
+ kfree(mountdata);
+ mountdata = ERR_PTR(rc);
+ kfree(name);
+ goto compose_mount_options_out;
+}
+
+/**
+ * cifs_dfs_do_mount - mounts specified path using DFS full path
+ *
+ * Always pass down @fullpath to smb3_do_mount() so we can use the root server
+ * to perform failover in case we failed to connect to the first target in the
+ * referral.
+ *
+ * @mntpt: directory entry for the path we are trying to automount
+ * @cifs_sb: parent/root superblock
+ * @fullpath: full path in UNC format
+ */
+static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
+ struct cifs_sb_info *cifs_sb,
+ const char *fullpath)
+{
+ struct vfsmount *mnt;
+ char *mountdata;
+ char *devname;
+
+ devname = kstrdup(fullpath, GFP_KERNEL);
+ if (!devname)
+ return ERR_PTR(-ENOMEM);
+
+ convert_delimiter(devname, '/');
+
+ /* TODO: change to call fs_context_for_mount(), fill in context directly, call fc_mount */
+
+ /* See afs_mntpt_do_automount in fs/afs/mntpt.c for an example */
+
+ /* strip first '\' from fullpath */
+ mountdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
+ fullpath + 1, NULL, NULL);
+ if (IS_ERR(mountdata)) {
+ kfree(devname);
+ return (struct vfsmount *)mountdata;
+ }
+
+ mnt = vfs_submount(mntpt, &cifs_fs_type, devname, mountdata);
+ kfree(mountdata);
+ kfree(devname);
+ return mnt;
+}
+
+/*
+ * Create a vfsmount that we can automount
+ */
+static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
+{
+ struct cifs_sb_info *cifs_sb;
+ void *page;
+ char *full_path;
+ struct vfsmount *mnt;
+
+ cifs_dbg(FYI, "in %s\n", __func__);
+ BUG_ON(IS_ROOT(mntpt));
+
+ /*
+ * The MSDFS spec states that paths in DFS referral requests and
+ * responses must be prefixed by a single '\' character instead of
+ * the double backslashes usually used in the UNC. This function
+ * gives us the latter, so we must adjust the result.
+ */
+ cifs_sb = CIFS_SB(mntpt->d_sb);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) {
+ mnt = ERR_PTR(-EREMOTE);
+ goto cdda_exit;
+ }
+
+ page = alloc_dentry_path();
+ /* always use tree name prefix */
+ full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
+ if (IS_ERR(full_path)) {
+ mnt = ERR_CAST(full_path);
+ goto free_full_path;
+ }
+
+ convert_delimiter(full_path, '\\');
+ cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
+
+ mnt = cifs_dfs_do_mount(mntpt, cifs_sb, full_path);
+ cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__, full_path + 1, mnt);
+
+free_full_path:
+ free_dentry_path(page);
+cdda_exit:
+ cifs_dbg(FYI, "leaving %s\n" , __func__);
+ return mnt;
+}
+
+/*
+ * Attempt to automount the referral
+ */
+struct vfsmount *cifs_dfs_d_automount(struct path *path)
+{
+ struct vfsmount *newmnt;
+
+ cifs_dbg(FYI, "in %s\n", __func__);
+
+ newmnt = cifs_dfs_do_automount(path->dentry);
+ if (IS_ERR(newmnt)) {
+ cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__);
+ return newmnt;
+ }
+
+ mntget(newmnt); /* prevent immediate expiration */
+ mnt_set_expiry(newmnt, &cifs_dfs_automount_list);
+ schedule_delayed_work(&cifs_dfs_automount_task,
+ cifs_dfs_mountpoint_expiry_timeout);
+ cifs_dbg(FYI, "leaving %s [ok]\n" , __func__);
+ return newmnt;
+}
+
+const struct inode_operations cifs_dfs_referral_inode_operations = {
+};
diff --git a/fs/smb/client/cifs_fs_sb.h b/fs/smb/client/cifs_fs_sb.h
new file mode 100644
index 000000000000..013a4bd65280
--- /dev/null
+++ b/fs/smb/client/cifs_fs_sb.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002,2004
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+#include <linux/rbtree.h>
+
+#ifndef _CIFS_FS_SB_H
+#define _CIFS_FS_SB_H
+
+#include <linux/backing-dev.h>
+
+#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
+#define CIFS_MOUNT_SET_UID 2 /* set current's euid in create etc. */
+#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
+#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
+#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
+#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
+#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible*/
+#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
+#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */
+#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */
+#define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */
+#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */
+#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */
+#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */
+#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/
+#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */
+#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */
+#define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */
+#define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */
+#define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */
+#define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of SB_POSIXACL in mnt_cifs_flags */
+#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */
+#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */
+#define CIFS_MOUNT_MAP_SFM_CHR 0x800000 /* SFM/MAC mapping for illegal chars */
+#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000 /* make subpath with unaccessible
+ * root mountable
+ */
+#define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */
+#define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */
+#define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */
+#define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */
+#define CIFS_MOUNT_RO_CACHE 0x20000000 /* assumes share will not change */
+#define CIFS_MOUNT_RW_CACHE 0x40000000 /* assumes only client accessing */
+#define CIFS_MOUNT_SHUTDOWN 0x80000000
+
+struct cifs_sb_info {
+ struct rb_root tlink_tree;
+ spinlock_t tlink_tree_lock;
+ struct tcon_link *master_tlink;
+ struct nls_table *local_nls;
+ struct smb3_fs_context *ctx;
+ atomic_t active;
+ unsigned int mnt_cifs_flags;
+ struct delayed_work prune_tlinks;
+ struct rcu_head rcu;
+
+ /* only used when CIFS_MOUNT_USE_PREFIX_PATH is set */
+ char *prepath;
+
+ /* randomly generated 128-bit number for indexing dfs mount groups in referral cache */
+ uuid_t dfs_mount_id;
+ /*
+ * Indicate whether serverino option was turned off later
+ * (cifs_autodisable_serverino) in order to match new mounts.
+ */
+ bool mnt_cifs_serverino_autodisabled;
+ /*
+ * Available once the mount has completed.
+ */
+ struct dentry *root;
+};
+#endif /* _CIFS_FS_SB_H */
diff --git a/fs/smb/client/cifs_ioctl.h b/fs/smb/client/cifs_ioctl.h
new file mode 100644
index 000000000000..d86d78d5bfdc
--- /dev/null
+++ b/fs/smb/client/cifs_ioctl.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Structure definitions for io control for cifs/smb3
+ *
+ * Copyright (c) 2015 Steve French <steve.french@primarydata.com>
+ *
+ */
+
+struct smb_mnt_fs_info {
+ __u32 version; /* 0001 */
+ __u16 protocol_id;
+ __u16 tcon_flags;
+ __u32 vol_serial_number;
+ __u32 vol_create_time;
+ __u32 share_caps;
+ __u32 share_flags;
+ __u32 sector_flags;
+ __u32 optimal_sector_size;
+ __u32 max_bytes_chunk;
+ __u32 fs_attributes;
+ __u32 max_path_component;
+ __u32 device_type;
+ __u32 device_characteristics;
+ __u32 maximal_access;
+ __u64 cifs_posix_caps;
+} __packed;
+
+struct smb_snapshot_array {
+ __u32 number_of_snapshots;
+ __u32 number_of_snapshots_returned;
+ __u32 snapshot_array_size;
+ /* snapshots[]; */
+} __packed;
+
+/* query_info flags */
+#define PASSTHRU_QUERY_INFO 0x00000000
+#define PASSTHRU_FSCTL 0x00000001
+#define PASSTHRU_SET_INFO 0x00000002
+struct smb_query_info {
+ __u32 info_type;
+ __u32 file_info_class;
+ __u32 additional_information;
+ __u32 flags;
+ __u32 input_buffer_length;
+ __u32 output_buffer_length;
+ /* char buffer[]; */
+} __packed;
+
+/*
+ * Dumping the commonly used 16 byte (e.g. CCM and GCM128) keys still supported
+ * for backlevel compatibility, but is not sufficient for dumping the less
+ * frequently used GCM256 (32 byte) keys (see the newer "CIFS_DUMP_FULL_KEY"
+ * ioctl for dumping decryption info for GCM256 mounts)
+ */
+struct smb3_key_debug_info {
+ __u64 Suid;
+ __u16 cipher_type;
+ __u8 auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */
+ __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
+ __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
+} __packed;
+
+/*
+ * Dump variable-sized keys
+ */
+struct smb3_full_key_debug_info {
+ /* INPUT: size of userspace buffer */
+ __u32 in_size;
+
+ /*
+ * INPUT: 0 for current user, otherwise session to dump
+ * OUTPUT: session id that was dumped
+ */
+ __u64 session_id;
+ __u16 cipher_type;
+ __u8 session_key_length;
+ __u8 server_in_key_length;
+ __u8 server_out_key_length;
+ __u8 data[];
+ /*
+ * return this struct with the keys appended at the end:
+ * __u8 session_key[session_key_length];
+ * __u8 server_in_key[server_in_key_length];
+ * __u8 server_out_key[server_out_key_length];
+ */
+} __packed;
+
+struct smb3_notify {
+ __u32 completion_filter;
+ bool watch_tree;
+} __packed;
+
+struct smb3_notify_info {
+ __u32 completion_filter;
+ bool watch_tree;
+ __u32 data_len; /* size of notify data below */
+ __u8 notify_data[];
+} __packed;
+
+#define CIFS_IOCTL_MAGIC 0xCF
+#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)
+#define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4)
+#define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
+#define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
+#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
+#define CIFS_DUMP_KEY _IOWR(CIFS_IOCTL_MAGIC, 8, struct smb3_key_debug_info)
+#define CIFS_IOC_NOTIFY _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify)
+#define CIFS_DUMP_FULL_KEY _IOWR(CIFS_IOCTL_MAGIC, 10, struct smb3_full_key_debug_info)
+#define CIFS_IOC_NOTIFY_INFO _IOWR(CIFS_IOCTL_MAGIC, 11, struct smb3_notify_info)
+#define CIFS_IOC_SHUTDOWN _IOR ('X', 125, __u32)
+
+/*
+ * Flags for going down operation
+ */
+#define CIFS_GOING_FLAGS_DEFAULT 0x0 /* going down */
+#define CIFS_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
+#define CIFS_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
+
+static inline bool cifs_forced_shutdown(struct cifs_sb_info *sbi)
+{
+ if (CIFS_MOUNT_SHUTDOWN & sbi->mnt_cifs_flags)
+ return true;
+ else
+ return false;
+}
diff --git a/fs/smb/client/cifs_spnego.c b/fs/smb/client/cifs_spnego.c
new file mode 100644
index 000000000000..342717bf1dc2
--- /dev/null
+++ b/fs/smb/client/cifs_spnego.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * SPNEGO upcall management for CIFS
+ *
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Author(s): Jeff Layton (jlayton@redhat.com)
+ *
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <keys/user-type.h>
+#include <linux/key-type.h>
+#include <linux/keyctl.h>
+#include <linux/inet.h>
+#include "cifsglob.h"
+#include "cifs_spnego.h"
+#include "cifs_debug.h"
+#include "cifsproto.h"
+static const struct cred *spnego_cred;
+
+/* create a new cifs key */
+static int
+cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
+{
+ char *payload;
+ int ret;
+
+ ret = -ENOMEM;
+ payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
+ if (!payload)
+ goto error;
+
+ /* attach the data */
+ key->payload.data[0] = payload;
+ ret = 0;
+
+error:
+ return ret;
+}
+
+static void
+cifs_spnego_key_destroy(struct key *key)
+{
+ kfree(key->payload.data[0]);
+}
+
+
+/*
+ * keytype for CIFS spnego keys
+ */
+struct key_type cifs_spnego_key_type = {
+ .name = "cifs.spnego",
+ .instantiate = cifs_spnego_key_instantiate,
+ .destroy = cifs_spnego_key_destroy,
+ .describe = user_describe,
+};
+
+/* length of longest version string e.g. strlen("ver=0xFF") */
+#define MAX_VER_STR_LEN 8
+
+/* length of longest security mechanism name, eg in future could have
+ * strlen(";sec=ntlmsspi") */
+#define MAX_MECH_STR_LEN 13
+
+/* strlen of "host=" */
+#define HOST_KEY_LEN 5
+
+/* strlen of ";ip4=" or ";ip6=" */
+#define IP_KEY_LEN 5
+
+/* strlen of ";uid=0x" */
+#define UID_KEY_LEN 7
+
+/* strlen of ";creduid=0x" */
+#define CREDUID_KEY_LEN 11
+
+/* strlen of ";user=" */
+#define USER_KEY_LEN 6
+
+/* strlen of ";pid=0x" */
+#define PID_KEY_LEN 7
+
+/* get a key struct with a SPNEGO security blob, suitable for session setup */
+struct key *
+cifs_get_spnego_key(struct cifs_ses *sesInfo,
+ struct TCP_Server_Info *server)
+{
+ struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
+ struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
+ char *description, *dp;
+ size_t desc_len;
+ struct key *spnego_key;
+ const char *hostname = server->hostname;
+ const struct cred *saved_cred;
+
+ /* length of fields (with semicolons): ver=0xyz ip4=ipaddress
+ host=hostname sec=mechanism uid=0xFF user=username */
+ desc_len = MAX_VER_STR_LEN +
+ HOST_KEY_LEN + strlen(hostname) +
+ IP_KEY_LEN + INET6_ADDRSTRLEN +
+ MAX_MECH_STR_LEN +
+ UID_KEY_LEN + (sizeof(uid_t) * 2) +
+ CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
+ PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
+
+ if (sesInfo->user_name)
+ desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
+
+ spnego_key = ERR_PTR(-ENOMEM);
+ description = kzalloc(desc_len, GFP_KERNEL);
+ if (description == NULL)
+ goto out;
+
+ dp = description;
+ /* start with version and hostname portion of UNC string */
+ spnego_key = ERR_PTR(-EINVAL);
+ sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
+ hostname);
+ dp = description + strlen(description);
+
+ /* add the server address */
+ if (server->dstaddr.ss_family == AF_INET)
+ sprintf(dp, "ip4=%pI4", &sa->sin_addr);
+ else if (server->dstaddr.ss_family == AF_INET6)
+ sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
+ else
+ goto out;
+
+ dp = description + strlen(description);
+
+ /* for now, only sec=krb5 and sec=mskrb5 are valid */
+ if (server->sec_kerberos)
+ sprintf(dp, ";sec=krb5");
+ else if (server->sec_mskerberos)
+ sprintf(dp, ";sec=mskrb5");
+ else {
+ cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n");
+ sprintf(dp, ";sec=krb5");
+ }
+
+ dp = description + strlen(description);
+ sprintf(dp, ";uid=0x%x",
+ from_kuid_munged(&init_user_ns, sesInfo->linux_uid));
+
+ dp = description + strlen(description);
+ sprintf(dp, ";creduid=0x%x",
+ from_kuid_munged(&init_user_ns, sesInfo->cred_uid));
+
+ if (sesInfo->user_name) {
+ dp = description + strlen(description);
+ sprintf(dp, ";user=%s", sesInfo->user_name);
+ }
+
+ dp = description + strlen(description);
+ sprintf(dp, ";pid=0x%x", current->pid);
+
+ cifs_dbg(FYI, "key description = %s\n", description);
+ saved_cred = override_creds(spnego_cred);
+ spnego_key = request_key(&cifs_spnego_key_type, description, "");
+ revert_creds(saved_cred);
+
+#ifdef CONFIG_CIFS_DEBUG2
+ if (cifsFYI && !IS_ERR(spnego_key)) {
+ struct cifs_spnego_msg *msg = spnego_key->payload.data[0];
+ cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U,
+ msg->secblob_len + msg->sesskey_len));
+ }
+#endif /* CONFIG_CIFS_DEBUG2 */
+
+out:
+ kfree(description);
+ return spnego_key;
+}
+
+int
+init_cifs_spnego(void)
+{
+ struct cred *cred;
+ struct key *keyring;
+ int ret;
+
+ cifs_dbg(FYI, "Registering the %s key type\n",
+ cifs_spnego_key_type.name);
+
+ /*
+ * Create an override credential set with special thread keyring for
+ * spnego upcalls.
+ */
+
+ cred = prepare_kernel_cred(NULL);
+ if (!cred)
+ return -ENOMEM;
+
+ keyring = keyring_alloc(".cifs_spnego",
+ GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
+ (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+ KEY_USR_VIEW | KEY_USR_READ,
+ KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
+ if (IS_ERR(keyring)) {
+ ret = PTR_ERR(keyring);
+ goto failed_put_cred;
+ }
+
+ ret = register_key_type(&cifs_spnego_key_type);
+ if (ret < 0)
+ goto failed_put_key;
+
+ /*
+ * instruct request_key() to use this special keyring as a cache for
+ * the results it looks up
+ */
+ set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
+ cred->thread_keyring = keyring;
+ cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+ spnego_cred = cred;
+
+ cifs_dbg(FYI, "cifs spnego keyring: %d\n", key_serial(keyring));
+ return 0;
+
+failed_put_key:
+ key_put(keyring);
+failed_put_cred:
+ put_cred(cred);
+ return ret;
+}
+
+void
+exit_cifs_spnego(void)
+{
+ key_revoke(spnego_cred->thread_keyring);
+ unregister_key_type(&cifs_spnego_key_type);
+ put_cred(spnego_cred);
+ cifs_dbg(FYI, "Unregistered %s key type\n", cifs_spnego_key_type.name);
+}
diff --git a/fs/smb/client/cifs_spnego.h b/fs/smb/client/cifs_spnego.h
new file mode 100644
index 000000000000..7f102ffeb675
--- /dev/null
+++ b/fs/smb/client/cifs_spnego.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ * SPNEGO upcall management for CIFS
+ *
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Author(s): Jeff Layton (jlayton@redhat.com)
+ * Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#ifndef _CIFS_SPNEGO_H
+#define _CIFS_SPNEGO_H
+
+#define CIFS_SPNEGO_UPCALL_VERSION 2
+
+/*
+ * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION.
+ * The flags field is for future use. The request-key callout should set
+ * sesskey_len and secblob_len, and then concatenate the SessKey+SecBlob
+ * and stuff it in the data field.
+ */
+struct cifs_spnego_msg {
+ uint32_t version;
+ uint32_t flags;
+ uint32_t sesskey_len;
+ uint32_t secblob_len;
+ uint8_t data[1];
+};
+
+#ifdef __KERNEL__
+extern struct key_type cifs_spnego_key_type;
+extern struct key *cifs_get_spnego_key(struct cifs_ses *sesInfo,
+ struct TCP_Server_Info *server);
+#endif /* KERNEL */
+
+#endif /* _CIFS_SPNEGO_H */
diff --git a/fs/smb/client/cifs_spnego_negtokeninit.asn1 b/fs/smb/client/cifs_spnego_negtokeninit.asn1
new file mode 100644
index 000000000000..181c083887d5
--- /dev/null
+++ b/fs/smb/client/cifs_spnego_negtokeninit.asn1
@@ -0,0 +1,40 @@
+GSSAPI ::=
+ [APPLICATION 0] IMPLICIT SEQUENCE {
+ thisMech
+ OBJECT IDENTIFIER ({cifs_gssapi_this_mech}),
+ negotiationToken
+ NegotiationToken
+ }
+
+MechType ::= OBJECT IDENTIFIER ({cifs_neg_token_init_mech_type})
+
+MechTypeList ::= SEQUENCE OF MechType
+
+NegHints ::= SEQUENCE {
+ hintName
+ [0] GeneralString OPTIONAL,
+ hintAddress
+ [1] OCTET STRING OPTIONAL
+ }
+
+NegTokenInit2 ::=
+ SEQUENCE {
+ mechTypes
+ [0] MechTypeList OPTIONAL,
+ reqFlags
+ [1] BIT STRING OPTIONAL,
+ mechToken
+ [2] OCTET STRING OPTIONAL,
+ negHints
+ [3] NegHints OPTIONAL,
+ mechListMIC
+ [3] OCTET STRING OPTIONAL
+ }
+
+NegotiationToken ::=
+ CHOICE {
+ negTokenInit
+ [0] NegTokenInit2,
+ negTokenTarg
+ [1] ANY
+ }
diff --git a/fs/smb/client/cifs_swn.c b/fs/smb/client/cifs_swn.c
new file mode 100644
index 000000000000..7233c6a7e6d7
--- /dev/null
+++ b/fs/smb/client/cifs_swn.c
@@ -0,0 +1,674 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Witness Service client for CIFS
+ *
+ * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
+ */
+
+#include <linux/kref.h>
+#include <net/genetlink.h>
+#include <uapi/linux/cifs/cifs_netlink.h>
+
+#include "cifs_swn.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "fscache.h"
+#include "cifs_debug.h"
+#include "netlink.h"
+
+static DEFINE_IDR(cifs_swnreg_idr);
+static DEFINE_MUTEX(cifs_swnreg_idr_mutex);
+
+struct cifs_swn_reg {
+ int id;
+ struct kref ref_count;
+
+ const char *net_name;
+ const char *share_name;
+ bool net_name_notify;
+ bool share_name_notify;
+ bool ip_notify;
+
+ struct cifs_tcon *tcon;
+};
+
+static int cifs_swn_auth_info_krb(struct cifs_tcon *tcon, struct sk_buff *skb)
+{
+ int ret;
+
+ ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_KRB_AUTH);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int cifs_swn_auth_info_ntlm(struct cifs_tcon *tcon, struct sk_buff *skb)
+{
+ int ret;
+
+ if (tcon->ses->user_name != NULL) {
+ ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_USER_NAME, tcon->ses->user_name);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (tcon->ses->password != NULL) {
+ ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_PASSWORD, tcon->ses->password);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (tcon->ses->domainName != NULL) {
+ ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_DOMAIN_NAME, tcon->ses->domainName);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Sends a register message to the userspace daemon based on the registration.
+ * The authentication information to connect to the witness service is bundled
+ * into the message.
+ */
+static int cifs_swn_send_register_message(struct cifs_swn_reg *swnreg)
+{
+ struct sk_buff *skb;
+ struct genlmsghdr *hdr;
+ enum securityEnum authtype;
+ struct sockaddr_storage *addr;
+ int ret;
+
+ skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (skb == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_REGISTER);
+ if (hdr == NULL) {
+ ret = -ENOMEM;
+ goto nlmsg_fail;
+ }
+
+ ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id);
+ if (ret < 0)
+ goto nlmsg_fail;
+
+ ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name);
+ if (ret < 0)
+ goto nlmsg_fail;
+
+ ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name);
+ if (ret < 0)
+ goto nlmsg_fail;
+
+ /*
+ * If there is an address stored use it instead of the server address, because we are
+ * in the process of reconnecting to it after a share has been moved or we have been
+ * told to switch to it (client move message). In these cases we unregister from the
+ * server address and register to the new address when we receive the notification.
+ */
+ if (swnreg->tcon->ses->server->use_swn_dstaddr)
+ addr = &swnreg->tcon->ses->server->swn_dstaddr;
+ else
+ addr = &swnreg->tcon->ses->server->dstaddr;
+
+ ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage), addr);
+ if (ret < 0)
+ goto nlmsg_fail;
+
+ if (swnreg->net_name_notify) {
+ ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY);
+ if (ret < 0)
+ goto nlmsg_fail;
+ }
+
+ if (swnreg->share_name_notify) {
+ ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY);
+ if (ret < 0)
+ goto nlmsg_fail;
+ }
+
+ if (swnreg->ip_notify) {
+ ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY);
+ if (ret < 0)
+ goto nlmsg_fail;
+ }
+
+ authtype = cifs_select_sectype(swnreg->tcon->ses->server, swnreg->tcon->ses->sectype);
+ switch (authtype) {
+ case Kerberos:
+ ret = cifs_swn_auth_info_krb(swnreg->tcon, skb);
+ if (ret < 0) {
+ cifs_dbg(VFS, "%s: Failed to get kerberos auth info: %d\n", __func__, ret);
+ goto nlmsg_fail;
+ }
+ break;
+ case NTLMv2:
+ case RawNTLMSSP:
+ ret = cifs_swn_auth_info_ntlm(swnreg->tcon, skb);
+ if (ret < 0) {
+ cifs_dbg(VFS, "%s: Failed to get NTLM auth info: %d\n", __func__, ret);
+ goto nlmsg_fail;
+ }
+ break;
+ default:
+ cifs_dbg(VFS, "%s: secType %d not supported!\n", __func__, authtype);
+ ret = -EINVAL;
+ goto nlmsg_fail;
+ }
+
+ genlmsg_end(skb, hdr);
+ genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC);
+
+ cifs_dbg(FYI, "%s: Message to register for network name %s with id %d sent\n", __func__,
+ swnreg->net_name, swnreg->id);
+
+ return 0;
+
+nlmsg_fail:
+ genlmsg_cancel(skb, hdr);
+ nlmsg_free(skb);
+fail:
+ return ret;
+}
+
+/*
+ * Sends an uregister message to the userspace daemon based on the registration
+ */
+static int cifs_swn_send_unregister_message(struct cifs_swn_reg *swnreg)
+{
+ struct sk_buff *skb;
+ struct genlmsghdr *hdr;
+ int ret;
+
+ skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_UNREGISTER);
+ if (hdr == NULL) {
+ ret = -ENOMEM;
+ goto nlmsg_fail;
+ }
+
+ ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id);
+ if (ret < 0)
+ goto nlmsg_fail;
+
+ ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name);
+ if (ret < 0)
+ goto nlmsg_fail;
+
+ ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name);
+ if (ret < 0)
+ goto nlmsg_fail;
+
+ ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage),
+ &swnreg->tcon->ses->server->dstaddr);
+ if (ret < 0)
+ goto nlmsg_fail;
+
+ if (swnreg->net_name_notify) {
+ ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY);
+ if (ret < 0)
+ goto nlmsg_fail;
+ }
+
+ if (swnreg->share_name_notify) {
+ ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY);
+ if (ret < 0)
+ goto nlmsg_fail;
+ }
+
+ if (swnreg->ip_notify) {
+ ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY);
+ if (ret < 0)
+ goto nlmsg_fail;
+ }
+
+ genlmsg_end(skb, hdr);
+ genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC);
+
+ cifs_dbg(FYI, "%s: Message to unregister for network name %s with id %d sent\n", __func__,
+ swnreg->net_name, swnreg->id);
+
+ return 0;
+
+nlmsg_fail:
+ genlmsg_cancel(skb, hdr);
+ nlmsg_free(skb);
+ return ret;
+}
+
+/*
+ * Try to find a matching registration for the tcon's server name and share name.
+ * Calls to this function must be protected by cifs_swnreg_idr_mutex.
+ * TODO Try to avoid memory allocations
+ */
+static struct cifs_swn_reg *cifs_find_swn_reg(struct cifs_tcon *tcon)
+{
+ struct cifs_swn_reg *swnreg;
+ int id;
+ const char *share_name;
+ const char *net_name;
+
+ net_name = extract_hostname(tcon->tree_name);
+ if (IS_ERR(net_name)) {
+ int ret;
+
+ ret = PTR_ERR(net_name);
+ cifs_dbg(VFS, "%s: failed to extract host name from target '%s': %d\n",
+ __func__, tcon->tree_name, ret);
+ return ERR_PTR(-EINVAL);
+ }
+
+ share_name = extract_sharename(tcon->tree_name);
+ if (IS_ERR(share_name)) {
+ int ret;
+
+ ret = PTR_ERR(share_name);
+ cifs_dbg(VFS, "%s: failed to extract share name from target '%s': %d\n",
+ __func__, tcon->tree_name, ret);
+ kfree(net_name);
+ return ERR_PTR(-EINVAL);
+ }
+
+ idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
+ if (strcasecmp(swnreg->net_name, net_name) != 0
+ || strcasecmp(swnreg->share_name, share_name) != 0) {
+ continue;
+ }
+
+ cifs_dbg(FYI, "Existing swn registration for %s:%s found\n", swnreg->net_name,
+ swnreg->share_name);
+
+ kfree(net_name);
+ kfree(share_name);
+
+ return swnreg;
+ }
+
+ kfree(net_name);
+ kfree(share_name);
+
+ return ERR_PTR(-EEXIST);
+}
+
+/*
+ * Get a registration for the tcon's server and share name, allocating a new one if it does not
+ * exists
+ */
+static struct cifs_swn_reg *cifs_get_swn_reg(struct cifs_tcon *tcon)
+{
+ struct cifs_swn_reg *reg = NULL;
+ int ret;
+
+ mutex_lock(&cifs_swnreg_idr_mutex);
+
+ /* Check if we are already registered for this network and share names */
+ reg = cifs_find_swn_reg(tcon);
+ if (!IS_ERR(reg)) {
+ kref_get(®->ref_count);
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+ return reg;
+ } else if (PTR_ERR(reg) != -EEXIST) {
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+ return reg;
+ }
+
+ reg = kmalloc(sizeof(struct cifs_swn_reg), GFP_ATOMIC);
+ if (reg == NULL) {
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ kref_init(®->ref_count);
+
+ reg->id = idr_alloc(&cifs_swnreg_idr, reg, 1, 0, GFP_ATOMIC);
+ if (reg->id < 0) {
+ cifs_dbg(FYI, "%s: failed to allocate registration id\n", __func__);
+ ret = reg->id;
+ goto fail;
+ }
+
+ reg->net_name = extract_hostname(tcon->tree_name);
+ if (IS_ERR(reg->net_name)) {
+ ret = PTR_ERR(reg->net_name);
+ cifs_dbg(VFS, "%s: failed to extract host name from target: %d\n", __func__, ret);
+ goto fail_idr;
+ }
+
+ reg->share_name = extract_sharename(tcon->tree_name);
+ if (IS_ERR(reg->share_name)) {
+ ret = PTR_ERR(reg->share_name);
+ cifs_dbg(VFS, "%s: failed to extract share name from target: %d\n", __func__, ret);
+ goto fail_net_name;
+ }
+
+ reg->net_name_notify = true;
+ reg->share_name_notify = true;
+ reg->ip_notify = (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT);
+
+ reg->tcon = tcon;
+
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+
+ return reg;
+
+fail_net_name:
+ kfree(reg->net_name);
+fail_idr:
+ idr_remove(&cifs_swnreg_idr, reg->id);
+fail:
+ kfree(reg);
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+ return ERR_PTR(ret);
+}
+
+static void cifs_swn_reg_release(struct kref *ref)
+{
+ struct cifs_swn_reg *swnreg = container_of(ref, struct cifs_swn_reg, ref_count);
+ int ret;
+
+ ret = cifs_swn_send_unregister_message(swnreg);
+ if (ret < 0)
+ cifs_dbg(VFS, "%s: Failed to send unregister message: %d\n", __func__, ret);
+
+ idr_remove(&cifs_swnreg_idr, swnreg->id);
+ kfree(swnreg->net_name);
+ kfree(swnreg->share_name);
+ kfree(swnreg);
+}
+
+static void cifs_put_swn_reg(struct cifs_swn_reg *swnreg)
+{
+ mutex_lock(&cifs_swnreg_idr_mutex);
+ kref_put(&swnreg->ref_count, cifs_swn_reg_release);
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+}
+
+static int cifs_swn_resource_state_changed(struct cifs_swn_reg *swnreg, const char *name, int state)
+{
+ switch (state) {
+ case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE:
+ cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name);
+ cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
+ break;
+ case CIFS_SWN_RESOURCE_STATE_AVAILABLE:
+ cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name);
+ cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
+ break;
+ case CIFS_SWN_RESOURCE_STATE_UNKNOWN:
+ cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name);
+ break;
+ }
+ return 0;
+}
+
+static bool cifs_sockaddr_equal(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2)
+{
+ if (addr1->ss_family != addr2->ss_family)
+ return false;
+
+ if (addr1->ss_family == AF_INET) {
+ return (memcmp(&((const struct sockaddr_in *)addr1)->sin_addr,
+ &((const struct sockaddr_in *)addr2)->sin_addr,
+ sizeof(struct in_addr)) == 0);
+ }
+
+ if (addr1->ss_family == AF_INET6) {
+ return (memcmp(&((const struct sockaddr_in6 *)addr1)->sin6_addr,
+ &((const struct sockaddr_in6 *)addr2)->sin6_addr,
+ sizeof(struct in6_addr)) == 0);
+ }
+
+ return false;
+}
+
+static int cifs_swn_store_swn_addr(const struct sockaddr_storage *new,
+ const struct sockaddr_storage *old,
+ struct sockaddr_storage *dst)
+{
+ __be16 port = cpu_to_be16(CIFS_PORT);
+
+ if (old->ss_family == AF_INET) {
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)old;
+
+ port = ipv4->sin_port;
+ } else if (old->ss_family == AF_INET6) {
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)old;
+
+ port = ipv6->sin6_port;
+ }
+
+ if (new->ss_family == AF_INET) {
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)new;
+
+ ipv4->sin_port = port;
+ } else if (new->ss_family == AF_INET6) {
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)new;
+
+ ipv6->sin6_port = port;
+ }
+
+ *dst = *new;
+
+ return 0;
+}
+
+static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *addr)
+{
+ int ret = 0;
+
+ /* Store the reconnect address */
+ cifs_server_lock(tcon->ses->server);
+ if (cifs_sockaddr_equal(&tcon->ses->server->dstaddr, addr))
+ goto unlock;
+
+ ret = cifs_swn_store_swn_addr(addr, &tcon->ses->server->dstaddr,
+ &tcon->ses->server->swn_dstaddr);
+ if (ret < 0) {
+ cifs_dbg(VFS, "%s: failed to store address: %d\n", __func__, ret);
+ goto unlock;
+ }
+ tcon->ses->server->use_swn_dstaddr = true;
+
+ /*
+ * Unregister to stop receiving notifications for the old IP address.
+ */
+ ret = cifs_swn_unregister(tcon);
+ if (ret < 0) {
+ cifs_dbg(VFS, "%s: Failed to unregister for witness notifications: %d\n",
+ __func__, ret);
+ goto unlock;
+ }
+
+ /*
+ * And register to receive notifications for the new IP address now that we have
+ * stored the new address.
+ */
+ ret = cifs_swn_register(tcon);
+ if (ret < 0) {
+ cifs_dbg(VFS, "%s: Failed to register for witness notifications: %d\n",
+ __func__, ret);
+ goto unlock;
+ }
+
+ cifs_signal_cifsd_for_reconnect(tcon->ses->server, false);
+
+unlock:
+ cifs_server_unlock(tcon->ses->server);
+
+ return ret;
+}
+
+static int cifs_swn_client_move(struct cifs_swn_reg *swnreg, struct sockaddr_storage *addr)
+{
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr;
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)addr;
+
+ if (addr->ss_family == AF_INET)
+ cifs_dbg(FYI, "%s: move to %pI4\n", __func__, &ipv4->sin_addr);
+ else if (addr->ss_family == AF_INET6)
+ cifs_dbg(FYI, "%s: move to %pI6\n", __func__, &ipv6->sin6_addr);
+
+ return cifs_swn_reconnect(swnreg->tcon, addr);
+}
+
+int cifs_swn_notify(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cifs_swn_reg *swnreg;
+ char name[256];
+ int type;
+
+ if (info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]) {
+ int swnreg_id;
+
+ swnreg_id = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]);
+ mutex_lock(&cifs_swnreg_idr_mutex);
+ swnreg = idr_find(&cifs_swnreg_idr, swnreg_id);
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+ if (swnreg == NULL) {
+ cifs_dbg(FYI, "%s: registration id %d not found\n", __func__, swnreg_id);
+ return -EINVAL;
+ }
+ } else {
+ cifs_dbg(FYI, "%s: missing registration id attribute\n", __func__);
+ return -EINVAL;
+ }
+
+ if (info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]) {
+ type = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]);
+ } else {
+ cifs_dbg(FYI, "%s: missing notification type attribute\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case CIFS_SWN_NOTIFICATION_RESOURCE_CHANGE: {
+ int state;
+
+ if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME]) {
+ nla_strscpy(name, info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME],
+ sizeof(name));
+ } else {
+ cifs_dbg(FYI, "%s: missing resource name attribute\n", __func__);
+ return -EINVAL;
+ }
+ if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]) {
+ state = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]);
+ } else {
+ cifs_dbg(FYI, "%s: missing resource state attribute\n", __func__);
+ return -EINVAL;
+ }
+ return cifs_swn_resource_state_changed(swnreg, name, state);
+ }
+ case CIFS_SWN_NOTIFICATION_CLIENT_MOVE: {
+ struct sockaddr_storage addr;
+
+ if (info->attrs[CIFS_GENL_ATTR_SWN_IP]) {
+ nla_memcpy(&addr, info->attrs[CIFS_GENL_ATTR_SWN_IP], sizeof(addr));
+ } else {
+ cifs_dbg(FYI, "%s: missing IP address attribute\n", __func__);
+ return -EINVAL;
+ }
+ return cifs_swn_client_move(swnreg, &addr);
+ }
+ default:
+ cifs_dbg(FYI, "%s: unknown notification type %d\n", __func__, type);
+ break;
+ }
+
+ return 0;
+}
+
+int cifs_swn_register(struct cifs_tcon *tcon)
+{
+ struct cifs_swn_reg *swnreg;
+ int ret;
+
+ swnreg = cifs_get_swn_reg(tcon);
+ if (IS_ERR(swnreg))
+ return PTR_ERR(swnreg);
+
+ ret = cifs_swn_send_register_message(swnreg);
+ if (ret < 0) {
+ cifs_dbg(VFS, "%s: Failed to send swn register message: %d\n", __func__, ret);
+ /* Do not put the swnreg or return error, the echo task will retry */
+ }
+
+ return 0;
+}
+
+int cifs_swn_unregister(struct cifs_tcon *tcon)
+{
+ struct cifs_swn_reg *swnreg;
+
+ mutex_lock(&cifs_swnreg_idr_mutex);
+
+ swnreg = cifs_find_swn_reg(tcon);
+ if (IS_ERR(swnreg)) {
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+ return PTR_ERR(swnreg);
+ }
+
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+
+ cifs_put_swn_reg(swnreg);
+
+ return 0;
+}
+
+void cifs_swn_dump(struct seq_file *m)
+{
+ struct cifs_swn_reg *swnreg;
+ struct sockaddr_in *sa;
+ struct sockaddr_in6 *sa6;
+ int id;
+
+ seq_puts(m, "Witness registrations:");
+
+ mutex_lock(&cifs_swnreg_idr_mutex);
+ idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
+ seq_printf(m, "\nId: %u Refs: %u Network name: '%s'%s Share name: '%s'%s Ip address: ",
+ id, kref_read(&swnreg->ref_count),
+ swnreg->net_name, swnreg->net_name_notify ? "(y)" : "(n)",
+ swnreg->share_name, swnreg->share_name_notify ? "(y)" : "(n)");
+ switch (swnreg->tcon->ses->server->dstaddr.ss_family) {
+ case AF_INET:
+ sa = (struct sockaddr_in *) &swnreg->tcon->ses->server->dstaddr;
+ seq_printf(m, "%pI4", &sa->sin_addr.s_addr);
+ break;
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *) &swnreg->tcon->ses->server->dstaddr;
+ seq_printf(m, "%pI6", &sa6->sin6_addr.s6_addr);
+ if (sa6->sin6_scope_id)
+ seq_printf(m, "%%%u", sa6->sin6_scope_id);
+ break;
+ default:
+ seq_puts(m, "(unknown)");
+ }
+ seq_printf(m, "%s", swnreg->ip_notify ? "(y)" : "(n)");
+ }
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+ seq_puts(m, "\n");
+}
+
+void cifs_swn_check(void)
+{
+ struct cifs_swn_reg *swnreg;
+ int id;
+ int ret;
+
+ mutex_lock(&cifs_swnreg_idr_mutex);
+ idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
+ ret = cifs_swn_send_register_message(swnreg);
+ if (ret < 0)
+ cifs_dbg(FYI, "%s: Failed to send register message: %d\n", __func__, ret);
+ }
+ mutex_unlock(&cifs_swnreg_idr_mutex);
+}
diff --git a/fs/smb/client/cifs_swn.h b/fs/smb/client/cifs_swn.h
new file mode 100644
index 000000000000..8a9d2a5c9077
--- /dev/null
+++ b/fs/smb/client/cifs_swn.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Witness Service client for CIFS
+ *
+ * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
+ */
+
+#ifndef _CIFS_SWN_H
+#define _CIFS_SWN_H
+#include "cifsglob.h"
+
+struct cifs_tcon;
+struct sk_buff;
+struct genl_info;
+
+#ifdef CONFIG_CIFS_SWN_UPCALL
+extern int cifs_swn_register(struct cifs_tcon *tcon);
+
+extern int cifs_swn_unregister(struct cifs_tcon *tcon);
+
+extern int cifs_swn_notify(struct sk_buff *skb, struct genl_info *info);
+
+extern void cifs_swn_dump(struct seq_file *m);
+
+extern void cifs_swn_check(void);
+
+static inline bool cifs_swn_set_server_dstaddr(struct TCP_Server_Info *server)
+{
+ if (server->use_swn_dstaddr) {
+ server->dstaddr = server->swn_dstaddr;
+ return true;
+ }
+ return false;
+}
+
+static inline void cifs_swn_reset_server_dstaddr(struct TCP_Server_Info *server)
+{
+ server->use_swn_dstaddr = false;
+}
+
+#else
+
+static inline int cifs_swn_register(struct cifs_tcon *tcon) { return 0; }
+static inline int cifs_swn_unregister(struct cifs_tcon *tcon) { return 0; }
+static inline int cifs_swn_notify(struct sk_buff *s, struct genl_info *i) { return 0; }
+static inline void cifs_swn_dump(struct seq_file *m) {}
+static inline void cifs_swn_check(void) {}
+static inline bool cifs_swn_set_server_dstaddr(struct TCP_Server_Info *server) { return false; }
+static inline void cifs_swn_reset_server_dstaddr(struct TCP_Server_Info *server) {}
+
+#endif /* CONFIG_CIFS_SWN_UPCALL */
+#endif /* _CIFS_SWN_H */
diff --git a/fs/smb/client/cifs_unicode.c b/fs/smb/client/cifs_unicode.c
new file mode 100644
index 000000000000..e7582dd79179
--- /dev/null
+++ b/fs/smb/client/cifs_unicode.c
@@ -0,0 +1,632 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2000,2009
+ * Modified by Steve French (sfrench@us.ibm.com)
+ */
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include "cifs_fs_sb.h"
+#include "cifs_unicode.h"
+#include "cifs_uniupr.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+
+int cifs_remap(struct cifs_sb_info *cifs_sb)
+{
+ int map_type;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
+ map_type = SFM_MAP_UNI_RSVD;
+ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
+ map_type = SFU_MAP_UNI_RSVD;
+ else
+ map_type = NO_MAP_UNI_RSVD;
+
+ return map_type;
+}
+
+/* Convert character using the SFU - "Services for Unix" remapping range */
+static bool
+convert_sfu_char(const __u16 src_char, char *target)
+{
+ /*
+ * BB: Cannot handle remapping UNI_SLASH until all the calls to
+ * build_path_from_dentry are modified, as they use slash as
+ * separator.
+ */
+ switch (src_char) {
+ case UNI_COLON:
+ *target = ':';
+ break;
+ case UNI_ASTERISK:
+ *target = '*';
+ break;
+ case UNI_QUESTION:
+ *target = '?';
+ break;
+ case UNI_PIPE:
+ *target = '|';
+ break;
+ case UNI_GRTRTHAN:
+ *target = '>';
+ break;
+ case UNI_LESSTHAN:
+ *target = '<';
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+/* Convert character using the SFM - "Services for Mac" remapping range */
+static bool
+convert_sfm_char(const __u16 src_char, char *target)
+{
+ if (src_char >= 0xF001 && src_char <= 0xF01F) {
+ *target = src_char - 0xF000;
+ return true;
+ }
+ switch (src_char) {
+ case SFM_COLON:
+ *target = ':';
+ break;
+ case SFM_DOUBLEQUOTE:
+ *target = '"';
+ break;
+ case SFM_ASTERISK:
+ *target = '*';
+ break;
+ case SFM_QUESTION:
+ *target = '?';
+ break;
+ case SFM_PIPE:
+ *target = '|';
+ break;
+ case SFM_GRTRTHAN:
+ *target = '>';
+ break;
+ case SFM_LESSTHAN:
+ *target = '<';
+ break;
+ case SFM_SPACE:
+ *target = ' ';
+ break;
+ case SFM_PERIOD:
+ *target = '.';
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+
+/*
+ * cifs_mapchar - convert a host-endian char to proper char in codepage
+ * @target - where converted character should be copied
+ * @src_char - 2 byte host-endian source character
+ * @cp - codepage to which character should be converted
+ * @map_type - How should the 7 NTFS/SMB reserved characters be mapped to UCS2?
+ *
+ * This function handles the conversion of a single character. It is the
+ * responsibility of the caller to ensure that the target buffer is large
+ * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
+ */
+static int
+cifs_mapchar(char *target, const __u16 *from, const struct nls_table *cp,
+ int maptype)
+{
+ int len = 1;
+ __u16 src_char;
+
+ src_char = *from;
+
+ if ((maptype == SFM_MAP_UNI_RSVD) && convert_sfm_char(src_char, target))
+ return len;
+ else if ((maptype == SFU_MAP_UNI_RSVD) &&
+ convert_sfu_char(src_char, target))
+ return len;
+
+ /* if character not one of seven in special remap set */
+ len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE);
+ if (len <= 0)
+ goto surrogate_pair;
+
+ return len;
+
+surrogate_pair:
+ /* convert SURROGATE_PAIR and IVS */
+ if (strcmp(cp->charset, "utf8"))
+ goto unknown;
+ len = utf16s_to_utf8s(from, 3, UTF16_LITTLE_ENDIAN, target, 6);
+ if (len <= 0)
+ goto unknown;
+ return len;
+
+unknown:
+ *target = '?';
+ len = 1;
+ return len;
+}
+
+/*
+ * cifs_from_utf16 - convert utf16le string to local charset
+ * @to - destination buffer
+ * @from - source buffer
+ * @tolen - destination buffer size (in bytes)
+ * @fromlen - source buffer size (in bytes)
+ * @codepage - codepage to which characters should be converted
+ * @mapchar - should characters be remapped according to the mapchars option?
+ *
+ * Convert a little-endian utf16le string (as sent by the server) to a string
+ * in the provided codepage. The tolen and fromlen parameters are to ensure
+ * that the code doesn't walk off of the end of the buffer (which is always
+ * a danger if the alignment of the source buffer is off). The destination
+ * string is always properly null terminated and fits in the destination
+ * buffer. Returns the length of the destination string in bytes (including
+ * null terminator).
+ *
+ * Note that some windows versions actually send multiword UTF-16 characters
+ * instead of straight UTF16-2. The linux nls routines however aren't able to
+ * deal with those characters properly. In the event that we get some of
+ * those characters, they won't be translated properly.
+ */
+int
+cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
+ const struct nls_table *codepage, int map_type)
+{
+ int i, charlen, safelen;
+ int outlen = 0;
+ int nullsize = nls_nullsize(codepage);
+ int fromwords = fromlen / 2;
+ char tmp[NLS_MAX_CHARSET_SIZE];
+ __u16 ftmp[3]; /* ftmp[3] = 3array x 2bytes = 6bytes UTF-16 */
+
+ /*
+ * because the chars can be of varying widths, we need to take care
+ * not to overflow the destination buffer when we get close to the
+ * end of it. Until we get to this offset, we don't need to check
+ * for overflow however.
+ */
+ safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
+
+ for (i = 0; i < fromwords; i++) {
+ ftmp[0] = get_unaligned_le16(&from[i]);
+ if (ftmp[0] == 0)
+ break;
+ if (i + 1 < fromwords)
+ ftmp[1] = get_unaligned_le16(&from[i + 1]);
+ else
+ ftmp[1] = 0;
+ if (i + 2 < fromwords)
+ ftmp[2] = get_unaligned_le16(&from[i + 2]);
+ else
+ ftmp[2] = 0;
+
+ /*
+ * check to see if converting this character might make the
+ * conversion bleed into the null terminator
+ */
+ if (outlen >= safelen) {
+ charlen = cifs_mapchar(tmp, ftmp, codepage, map_type);
+ if ((outlen + charlen) > (tolen - nullsize))
+ break;
+ }
+
+ /* put converted char into 'to' buffer */
+ charlen = cifs_mapchar(&to[outlen], ftmp, codepage, map_type);
+ outlen += charlen;
+
+ /* charlen (=bytes of UTF-8 for 1 character)
+ * 4bytes UTF-8(surrogate pair) is charlen=4
+ * (4bytes UTF-16 code)
+ * 7-8bytes UTF-8(IVS) is charlen=3+4 or 4+4
+ * (2 UTF-8 pairs divided to 2 UTF-16 pairs) */
+ if (charlen == 4)
+ i++;
+ else if (charlen >= 5)
+ /* 5-6bytes UTF-8 */
+ i += 2;
+ }
+
+ /* properly null-terminate string */
+ for (i = 0; i < nullsize; i++)
+ to[outlen++] = 0;
+
+ return outlen;
+}
+
+/*
+ * NAME: cifs_strtoUTF16()
+ *
+ * FUNCTION: Convert character string to unicode string
+ *
+ */
+int
+cifs_strtoUTF16(__le16 *to, const char *from, int len,
+ const struct nls_table *codepage)
+{
+ int charlen;
+ int i;
+ wchar_t wchar_to; /* needed to quiet sparse */
+
+ /* special case for utf8 to handle no plane0 chars */
+ if (!strcmp(codepage->charset, "utf8")) {
+ /*
+ * convert utf8 -> utf16, we assume we have enough space
+ * as caller should have assumed conversion does not overflow
+ * in destination len is length in wchar_t units (16bits)
+ */
+ i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN,
+ (wchar_t *) to, len);
+
+ /* if success terminate and exit */
+ if (i >= 0)
+ goto success;
+ /*
+ * if fails fall back to UCS encoding as this
+ * function should not return negative values
+ * currently can fail only if source contains
+ * invalid encoded characters
+ */
+ }
+
+ for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
+ charlen = codepage->char2uni(from, len, &wchar_to);
+ if (charlen < 1) {
+ cifs_dbg(VFS, "strtoUTF16: char2uni of 0x%x returned %d\n",
+ *from, charlen);
+ /* A question mark */
+ wchar_to = 0x003f;
+ charlen = 1;
+ }
+ put_unaligned_le16(wchar_to, &to[i]);
+ }
+
+success:
+ put_unaligned_le16(0, &to[i]);
+ return i;
+}
+
+/*
+ * cifs_utf16_bytes - how long will a string be after conversion?
+ * @utf16 - pointer to input string
+ * @maxbytes - don't go past this many bytes of input string
+ * @codepage - destination codepage
+ *
+ * Walk a utf16le string and return the number of bytes that the string will
+ * be after being converted to the given charset, not including any null
+ * termination required. Don't walk past maxbytes in the source buffer.
+ */
+int
+cifs_utf16_bytes(const __le16 *from, int maxbytes,
+ const struct nls_table *codepage)
+{
+ int i;
+ int charlen, outlen = 0;
+ int maxwords = maxbytes / 2;
+ char tmp[NLS_MAX_CHARSET_SIZE];
+ __u16 ftmp[3];
+
+ for (i = 0; i < maxwords; i++) {
+ ftmp[0] = get_unaligned_le16(&from[i]);
+ if (ftmp[0] == 0)
+ break;
+ if (i + 1 < maxwords)
+ ftmp[1] = get_unaligned_le16(&from[i + 1]);
+ else
+ ftmp[1] = 0;
+ if (i + 2 < maxwords)
+ ftmp[2] = get_unaligned_le16(&from[i + 2]);
+ else
+ ftmp[2] = 0;
+
+ charlen = cifs_mapchar(tmp, ftmp, codepage, NO_MAP_UNI_RSVD);
+ outlen += charlen;
+ }
+
+ return outlen;
+}
+
+/*
+ * cifs_strndup_from_utf16 - copy a string from wire format to the local
+ * codepage
+ * @src - source string
+ * @maxlen - don't walk past this many bytes in the source string
+ * @is_unicode - is this a unicode string?
+ * @codepage - destination codepage
+ *
+ * Take a string given by the server, convert it to the local codepage and
+ * put it in a new buffer. Returns a pointer to the new string or NULL on
+ * error.
+ */
+char *
+cifs_strndup_from_utf16(const char *src, const int maxlen,
+ const bool is_unicode, const struct nls_table *codepage)
+{
+ int len;
+ char *dst;
+
+ if (is_unicode) {
+ len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage);
+ len += nls_nullsize(codepage);
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst)
+ return NULL;
+ cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
+ NO_MAP_UNI_RSVD);
+ } else {
+ dst = kstrndup(src, maxlen, GFP_KERNEL);
+ }
+
+ return dst;
+}
+
+static __le16 convert_to_sfu_char(char src_char)
+{
+ __le16 dest_char;
+
+ switch (src_char) {
+ case ':':
+ dest_char = cpu_to_le16(UNI_COLON);
+ break;
+ case '*':
+ dest_char = cpu_to_le16(UNI_ASTERISK);
+ break;
+ case '?':
+ dest_char = cpu_to_le16(UNI_QUESTION);
+ break;
+ case '<':
+ dest_char = cpu_to_le16(UNI_LESSTHAN);
+ break;
+ case '>':
+ dest_char = cpu_to_le16(UNI_GRTRTHAN);
+ break;
+ case '|':
+ dest_char = cpu_to_le16(UNI_PIPE);
+ break;
+ default:
+ dest_char = 0;
+ }
+
+ return dest_char;
+}
+
+static __le16 convert_to_sfm_char(char src_char, bool end_of_string)
+{
+ __le16 dest_char;
+
+ if (src_char >= 0x01 && src_char <= 0x1F) {
+ dest_char = cpu_to_le16(src_char + 0xF000);
+ return dest_char;
+ }
+ switch (src_char) {
+ case ':':
+ dest_char = cpu_to_le16(SFM_COLON);
+ break;
+ case '"':
+ dest_char = cpu_to_le16(SFM_DOUBLEQUOTE);
+ break;
+ case '*':
+ dest_char = cpu_to_le16(SFM_ASTERISK);
+ break;
+ case '?':
+ dest_char = cpu_to_le16(SFM_QUESTION);
+ break;
+ case '<':
+ dest_char = cpu_to_le16(SFM_LESSTHAN);
+ break;
+ case '>':
+ dest_char = cpu_to_le16(SFM_GRTRTHAN);
+ break;
+ case '|':
+ dest_char = cpu_to_le16(SFM_PIPE);
+ break;
+ case '.':
+ if (end_of_string)
+ dest_char = cpu_to_le16(SFM_PERIOD);
+ else
+ dest_char = 0;
+ break;
+ case ' ':
+ if (end_of_string)
+ dest_char = cpu_to_le16(SFM_SPACE);
+ else
+ dest_char = 0;
+ break;
+ default:
+ dest_char = 0;
+ }
+
+ return dest_char;
+}
+
+/*
+ * Convert 16 bit Unicode pathname to wire format from string in current code
+ * page. Conversion may involve remapping up the six characters that are
+ * only legal in POSIX-like OS (if they are present in the string). Path
+ * names are little endian 16 bit Unicode on the wire
+ */
+int
+cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
+ const struct nls_table *cp, int map_chars)
+{
+ int i, charlen;
+ int j = 0;
+ char src_char;
+ __le16 dst_char;
+ wchar_t tmp;
+ wchar_t *wchar_to; /* UTF-16 */
+ int ret;
+ unicode_t u;
+
+ if (map_chars == NO_MAP_UNI_RSVD)
+ return cifs_strtoUTF16(target, source, PATH_MAX, cp);
+
+ wchar_to = kzalloc(6, GFP_KERNEL);
+
+ for (i = 0; i < srclen; j++) {
+ src_char = source[i];
+ charlen = 1;
+
+ /* check if end of string */
+ if (src_char == 0)
+ goto ctoUTF16_out;
+
+ /* see if we must remap this char */
+ if (map_chars == SFU_MAP_UNI_RSVD)
+ dst_char = convert_to_sfu_char(src_char);
+ else if (map_chars == SFM_MAP_UNI_RSVD) {
+ bool end_of_string;
+
+ /**
+ * Remap spaces and periods found at the end of every
+ * component of the path. The special cases of '.' and
+ * '..' do not need to be dealt with explicitly because
+ * they are addressed in namei.c:link_path_walk().
+ **/
+ if ((i == srclen - 1) || (source[i+1] == '\\'))
+ end_of_string = true;
+ else
+ end_of_string = false;
+
+ dst_char = convert_to_sfm_char(src_char, end_of_string);
+ } else
+ dst_char = 0;
+ /*
+ * FIXME: We can not handle remapping backslash (UNI_SLASH)
+ * until all the calls to build_path_from_dentry are modified,
+ * as they use backslash as separator.
+ */
+ if (dst_char == 0) {
+ charlen = cp->char2uni(source + i, srclen - i, &tmp);
+ dst_char = cpu_to_le16(tmp);
+
+ /*
+ * if no match, use question mark, which at least in
+ * some cases serves as wild card
+ */
+ if (charlen > 0)
+ goto ctoUTF16;
+
+ /* convert SURROGATE_PAIR */
+ if (strcmp(cp->charset, "utf8") || !wchar_to)
+ goto unknown;
+ if (*(source + i) & 0x80) {
+ charlen = utf8_to_utf32(source + i, 6, &u);
+ if (charlen < 0)
+ goto unknown;
+ } else
+ goto unknown;
+ ret = utf8s_to_utf16s(source + i, charlen,
+ UTF16_LITTLE_ENDIAN,
+ wchar_to, 6);
+ if (ret < 0)
+ goto unknown;
+
+ i += charlen;
+ dst_char = cpu_to_le16(*wchar_to);
+ if (charlen <= 3)
+ /* 1-3bytes UTF-8 to 2bytes UTF-16 */
+ put_unaligned(dst_char, &target[j]);
+ else if (charlen == 4) {
+ /* 4bytes UTF-8(surrogate pair) to 4bytes UTF-16
+ * 7-8bytes UTF-8(IVS) divided to 2 UTF-16
+ * (charlen=3+4 or 4+4) */
+ put_unaligned(dst_char, &target[j]);
+ dst_char = cpu_to_le16(*(wchar_to + 1));
+ j++;
+ put_unaligned(dst_char, &target[j]);
+ } else if (charlen >= 5) {
+ /* 5-6bytes UTF-8 to 6bytes UTF-16 */
+ put_unaligned(dst_char, &target[j]);
+ dst_char = cpu_to_le16(*(wchar_to + 1));
+ j++;
+ put_unaligned(dst_char, &target[j]);
+ dst_char = cpu_to_le16(*(wchar_to + 2));
+ j++;
+ put_unaligned(dst_char, &target[j]);
+ }
+ continue;
+
+unknown:
+ dst_char = cpu_to_le16(0x003f);
+ charlen = 1;
+ }
+
+ctoUTF16:
+ /*
+ * character may take more than one byte in the source string,
+ * but will take exactly two bytes in the target string
+ */
+ i += charlen;
+ put_unaligned(dst_char, &target[j]);
+ }
+
+ctoUTF16_out:
+ put_unaligned(0, &target[j]); /* Null terminate target unicode string */
+ kfree(wchar_to);
+ return j;
+}
+
+/*
+ * cifs_local_to_utf16_bytes - how long will a string be after conversion?
+ * @from - pointer to input string
+ * @maxbytes - don't go past this many bytes of input string
+ * @codepage - source codepage
+ *
+ * Walk a string and return the number of bytes that the string will
+ * be after being converted to the given charset, not including any null
+ * termination required. Don't walk past maxbytes in the source buffer.
+ */
+
+static int
+cifs_local_to_utf16_bytes(const char *from, int len,
+ const struct nls_table *codepage)
+{
+ int charlen;
+ int i;
+ wchar_t wchar_to;
+
+ for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
+ charlen = codepage->char2uni(from, len, &wchar_to);
+ /* Failed conversion defaults to a question mark */
+ if (charlen < 1)
+ charlen = 1;
+ }
+ return 2 * i; /* UTF16 characters are two bytes */
+}
+
+/*
+ * cifs_strndup_to_utf16 - copy a string to wire format from the local codepage
+ * @src - source string
+ * @maxlen - don't walk past this many bytes in the source string
+ * @utf16_len - the length of the allocated string in bytes (including null)
+ * @cp - source codepage
+ * @remap - map special chars
+ *
+ * Take a string convert it from the local codepage to UTF16 and
+ * put it in a new buffer. Returns a pointer to the new string or NULL on
+ * error.
+ */
+__le16 *
+cifs_strndup_to_utf16(const char *src, const int maxlen, int *utf16_len,
+ const struct nls_table *cp, int remap)
+{
+ int len;
+ __le16 *dst;
+
+ len = cifs_local_to_utf16_bytes(src, maxlen, cp);
+ len += 2; /* NULL */
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst) {
+ *utf16_len = 0;
+ return NULL;
+ }
+ cifsConvertToUTF16(dst, src, strlen(src), cp, remap);
+ *utf16_len = len;
+ return dst;
+}
diff --git a/fs/smb/client/cifs_unicode.h b/fs/smb/client/cifs_unicode.h
new file mode 100644
index 000000000000..80b3d845419f
--- /dev/null
+++ b/fs/smb/client/cifs_unicode.h
@@ -0,0 +1,404 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * cifs_unicode: Unicode kernel case support
+ *
+ * Function:
+ * Convert a unicode character to upper or lower case using
+ * compressed tables.
+ *
+ * Copyright (c) International Business Machines Corp., 2000,2009
+ *
+ * Notes:
+ * These APIs are based on the C library functions. The semantics
+ * should match the C functions but with expanded size operands.
+ *
+ * The upper/lower functions are based on a table created by mkupr.
+ * This is a compressed table of upper and lower case conversion.
+ */
+#ifndef _CIFS_UNICODE_H
+#define _CIFS_UNICODE_H
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <linux/nls.h>
+
+#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
+
+/*
+ * Windows maps these to the user defined 16 bit Unicode range since they are
+ * reserved symbols (along with \ and /), otherwise illegal to store
+ * in filenames in NTFS
+ */
+#define UNI_ASTERISK (__u16) ('*' + 0xF000)
+#define UNI_QUESTION (__u16) ('?' + 0xF000)
+#define UNI_COLON (__u16) (':' + 0xF000)
+#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
+#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
+#define UNI_PIPE (__u16) ('|' + 0xF000)
+#define UNI_SLASH (__u16) ('\\' + 0xF000)
+
+/*
+ * Macs use an older "SFM" mapping of the symbols above. Fortunately it does
+ * not conflict (although almost does) with the mapping above.
+ */
+
+#define SFM_DOUBLEQUOTE ((__u16) 0xF020)
+#define SFM_ASTERISK ((__u16) 0xF021)
+#define SFM_QUESTION ((__u16) 0xF025)
+#define SFM_COLON ((__u16) 0xF022)
+#define SFM_GRTRTHAN ((__u16) 0xF024)
+#define SFM_LESSTHAN ((__u16) 0xF023)
+#define SFM_PIPE ((__u16) 0xF027)
+#define SFM_SLASH ((__u16) 0xF026)
+#define SFM_SPACE ((__u16) 0xF028)
+#define SFM_PERIOD ((__u16) 0xF029)
+
+/*
+ * Mapping mechanism to use when one of the seven reserved characters is
+ * encountered. We can only map using one of the mechanisms at a time
+ * since otherwise readdir could return directory entries which we would
+ * not be able to open
+ *
+ * NO_MAP_UNI_RSVD = do not perform any remapping of the character
+ * SFM_MAP_UNI_RSVD = map reserved characters using SFM scheme (MAC compatible)
+ * SFU_MAP_UNI_RSVD = map reserved characters ala SFU ("mapchars" option)
+ *
+ */
+#define NO_MAP_UNI_RSVD 0
+#define SFM_MAP_UNI_RSVD 1
+#define SFU_MAP_UNI_RSVD 2
+
+/* Just define what we want from uniupr.h. We don't want to define the tables
+ * in each source file.
+ */
+#ifndef UNICASERANGE_DEFINED
+struct UniCaseRange {
+ wchar_t start;
+ wchar_t end;
+ signed char *table;
+};
+#endif /* UNICASERANGE_DEFINED */
+
+#ifndef UNIUPR_NOUPPER
+extern signed char CifsUniUpperTable[512];
+extern const struct UniCaseRange CifsUniUpperRange[];
+#endif /* UNIUPR_NOUPPER */
+
+#ifndef UNIUPR_NOLOWER
+extern signed char CifsUniLowerTable[512];
+extern const struct UniCaseRange CifsUniLowerRange[];
+#endif /* UNIUPR_NOLOWER */
+
+#ifdef __KERNEL__
+int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
+ const struct nls_table *cp, int map_type);
+int cifs_utf16_bytes(const __le16 *from, int maxbytes,
+ const struct nls_table *codepage);
+int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *);
+char *cifs_strndup_from_utf16(const char *src, const int maxlen,
+ const bool is_unicode,
+ const struct nls_table *codepage);
+extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
+ const struct nls_table *cp, int mapChars);
+extern int cifs_remap(struct cifs_sb_info *cifs_sb);
+extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen,
+ int *utf16_len, const struct nls_table *cp,
+ int remap);
+#endif
+
+wchar_t cifs_toupper(wchar_t in);
+
+/*
+ * UniStrcat: Concatenate the second string to the first
+ *
+ * Returns:
+ * Address of the first string
+ */
+static inline __le16 *
+UniStrcat(__le16 *ucs1, const __le16 *ucs2)
+{
+ __le16 *anchor = ucs1; /* save a pointer to start of ucs1 */
+
+ while (*ucs1++) ; /* To end of first string */
+ ucs1--; /* Return to the null */
+ while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
+ return anchor;
+}
+
+/*
+ * UniStrchr: Find a character in a string
+ *
+ * Returns:
+ * Address of first occurrence of character in string
+ * or NULL if the character is not in the string
+ */
+static inline wchar_t *
+UniStrchr(const wchar_t *ucs, wchar_t uc)
+{
+ while ((*ucs != uc) && *ucs)
+ ucs++;
+
+ if (*ucs == uc)
+ return (wchar_t *) ucs;
+ return NULL;
+}
+
+/*
+ * UniStrcmp: Compare two strings
+ *
+ * Returns:
+ * < 0: First string is less than second
+ * = 0: Strings are equal
+ * > 0: First string is greater than second
+ */
+static inline int
+UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
+{
+ while ((*ucs1 == *ucs2) && *ucs1) {
+ ucs1++;
+ ucs2++;
+ }
+ return (int) *ucs1 - (int) *ucs2;
+}
+
+/*
+ * UniStrcpy: Copy a string
+ */
+static inline wchar_t *
+UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
+{
+ wchar_t *anchor = ucs1; /* save the start of result string */
+
+ while ((*ucs1++ = *ucs2++)) ;
+ return anchor;
+}
+
+/*
+ * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
+ */
+static inline size_t
+UniStrlen(const wchar_t *ucs1)
+{
+ int i = 0;
+
+ while (*ucs1++)
+ i++;
+ return i;
+}
+
+/*
+ * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
+ * string (length limited)
+ */
+static inline size_t
+UniStrnlen(const wchar_t *ucs1, int maxlen)
+{
+ int i = 0;
+
+ while (*ucs1++) {
+ i++;
+ if (i >= maxlen)
+ break;
+ }
+ return i;
+}
+
+/*
+ * UniStrncat: Concatenate length limited string
+ */
+static inline wchar_t *
+UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ wchar_t *anchor = ucs1; /* save pointer to string 1 */
+
+ while (*ucs1++) ;
+ ucs1--; /* point to null terminator of s1 */
+ while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
+ ucs1++;
+ ucs2++;
+ }
+ *ucs1 = 0; /* Null terminate the result */
+ return (anchor);
+}
+
+/*
+ * UniStrncmp: Compare length limited string
+ */
+static inline int
+UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ if (!n)
+ return 0; /* Null strings are equal */
+ while ((*ucs1 == *ucs2) && *ucs1 && --n) {
+ ucs1++;
+ ucs2++;
+ }
+ return (int) *ucs1 - (int) *ucs2;
+}
+
+/*
+ * UniStrncmp_le: Compare length limited string - native to little-endian
+ */
+static inline int
+UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ if (!n)
+ return 0; /* Null strings are equal */
+ while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
+ ucs1++;
+ ucs2++;
+ }
+ return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
+}
+
+/*
+ * UniStrncpy: Copy length limited string with pad
+ */
+static inline wchar_t *
+UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ wchar_t *anchor = ucs1;
+
+ while (n-- && *ucs2) /* Copy the strings */
+ *ucs1++ = *ucs2++;
+
+ n++;
+ while (n--) /* Pad with nulls */
+ *ucs1++ = 0;
+ return anchor;
+}
+
+/*
+ * UniStrncpy_le: Copy length limited string with pad to little-endian
+ */
+static inline wchar_t *
+UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ wchar_t *anchor = ucs1;
+
+ while (n-- && *ucs2) /* Copy the strings */
+ *ucs1++ = __le16_to_cpu(*ucs2++);
+
+ n++;
+ while (n--) /* Pad with nulls */
+ *ucs1++ = 0;
+ return anchor;
+}
+
+/*
+ * UniStrstr: Find a string in a string
+ *
+ * Returns:
+ * Address of first match found
+ * NULL if no matching string is found
+ */
+static inline wchar_t *
+UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
+{
+ const wchar_t *anchor1 = ucs1;
+ const wchar_t *anchor2 = ucs2;
+
+ while (*ucs1) {
+ if (*ucs1 == *ucs2) {
+ /* Partial match found */
+ ucs1++;
+ ucs2++;
+ } else {
+ if (!*ucs2) /* Match found */
+ return (wchar_t *) anchor1;
+ ucs1 = ++anchor1; /* No match */
+ ucs2 = anchor2;
+ }
+ }
+
+ if (!*ucs2) /* Both end together */
+ return (wchar_t *) anchor1; /* Match found */
+ return NULL; /* No match */
+}
+
+#ifndef UNIUPR_NOUPPER
+/*
+ * UniToupper: Convert a unicode character to upper case
+ */
+static inline wchar_t
+UniToupper(register wchar_t uc)
+{
+ register const struct UniCaseRange *rp;
+
+ if (uc < sizeof(CifsUniUpperTable)) {
+ /* Latin characters */
+ return uc + CifsUniUpperTable[uc]; /* Use base tables */
+ } else {
+ rp = CifsUniUpperRange; /* Use range tables */
+ while (rp->start) {
+ if (uc < rp->start) /* Before start of range */
+ return uc; /* Uppercase = input */
+ if (uc <= rp->end) /* In range */
+ return uc + rp->table[uc - rp->start];
+ rp++; /* Try next range */
+ }
+ }
+ return uc; /* Past last range */
+}
+
+/*
+ * UniStrupr: Upper case a unicode string
+ */
+static inline __le16 *
+UniStrupr(register __le16 *upin)
+{
+ register __le16 *up;
+
+ up = upin;
+ while (*up) { /* For all characters */
+ *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
+ up++;
+ }
+ return upin; /* Return input pointer */
+}
+#endif /* UNIUPR_NOUPPER */
+
+#ifndef UNIUPR_NOLOWER
+/*
+ * UniTolower: Convert a unicode character to lower case
+ */
+static inline wchar_t
+UniTolower(register wchar_t uc)
+{
+ register const struct UniCaseRange *rp;
+
+ if (uc < sizeof(CifsUniLowerTable)) {
+ /* Latin characters */
+ return uc + CifsUniLowerTable[uc]; /* Use base tables */
+ } else {
+ rp = CifsUniLowerRange; /* Use range tables */
+ while (rp->start) {
+ if (uc < rp->start) /* Before start of range */
+ return uc; /* Uppercase = input */
+ if (uc <= rp->end) /* In range */
+ return uc + rp->table[uc - rp->start];
+ rp++; /* Try next range */
+ }
+ }
+ return uc; /* Past last range */
+}
+
+/*
+ * UniStrlwr: Lower case a unicode string
+ */
+static inline wchar_t *
+UniStrlwr(register wchar_t *upin)
+{
+ register wchar_t *up;
+
+ up = upin;
+ while (*up) { /* For all characters */
+ *up = UniTolower(*up);
+ up++;
+ }
+ return upin; /* Return input pointer */
+}
+
+#endif
+
+#endif /* _CIFS_UNICODE_H */
diff --git a/fs/smb/client/cifs_uniupr.h b/fs/smb/client/cifs_uniupr.h
new file mode 100644
index 000000000000..7b272fcdf0d3
--- /dev/null
+++ b/fs/smb/client/cifs_uniupr.h
@@ -0,0 +1,239 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) International Business Machines Corp., 2000,2002
+ *
+ * uniupr.h - Unicode compressed case ranges
+*/
+
+#ifndef UNIUPR_NOUPPER
+/*
+ * Latin upper case
+ */
+signed char CifsUniUpperTable[512] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
+ -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
+ 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
+ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
+ 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
+ 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
+ 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
+ -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
+ 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
+ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
+ 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
+};
+
+/* Upper case range - Greek */
+static signed char UniCaseRangeU03a0[47] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
+ -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
+ -63, -63,
+};
+
+/* Upper case range - Cyrillic */
+static signed char UniCaseRangeU0430[48] = {
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
+ 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
+};
+
+/* Upper case range - Extended cyrillic */
+static signed char UniCaseRangeU0490[61] = {
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
+ 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
+};
+
+/* Upper case range - Extended latin and greek */
+static signed char UniCaseRangeU1e00[509] = {
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
+ 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
+ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
+ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
+ 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
+ 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
+ 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
+ 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
+ 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/* Upper case range - Wide latin */
+static signed char UniCaseRangeUff40[27] = {
+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+};
+
+/*
+ * Upper Case Range
+ */
+const struct UniCaseRange CifsUniUpperRange[] = {
+ {0x03a0, 0x03ce, UniCaseRangeU03a0},
+ {0x0430, 0x045f, UniCaseRangeU0430},
+ {0x0490, 0x04cc, UniCaseRangeU0490},
+ {0x1e00, 0x1ffc, UniCaseRangeU1e00},
+ {0xff40, 0xff5a, UniCaseRangeUff40},
+ {0}
+};
+#endif
+
+#ifndef UNIUPR_NOLOWER
+/*
+ * Latin lower case
+ */
+signed char CifsUniLowerTable[512] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
+ 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
+ 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
+ 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
+ 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
+ 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
+ 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
+ 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
+ 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
+ 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
+};
+
+/* Lower case range - Greek */
+static signed char UniCaseRangeL0380[44] = {
+ 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
+ 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+};
+
+/* Lower case range - Cyrillic */
+static signed char UniCaseRangeL0400[48] = {
+ 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
+};
+
+/* Lower case range - Extended cyrillic */
+static signed char UniCaseRangeL0490[60] = {
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
+ 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
+};
+
+/* Lower case range - Extended latin and greek */
+static signed char UniCaseRangeL1e00[504] = {
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
+ 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/* Lower case range - Wide latin */
+static signed char UniCaseRangeLff20[27] = {
+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+};
+
+/*
+ * Lower Case Range
+ */
+const struct UniCaseRange CifsUniLowerRange[] = {
+ {0x0380, 0x03ab, UniCaseRangeL0380},
+ {0x0400, 0x042f, UniCaseRangeL0400},
+ {0x0490, 0x04cb, UniCaseRangeL0490},
+ {0x1e00, 0x1ff7, UniCaseRangeL1e00},
+ {0xff20, 0xff3a, UniCaseRangeLff20},
+ {0}
+};
+#endif
diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c
new file mode 100644
index 000000000000..a6c7566a0182
--- /dev/null
+++ b/fs/smb/client/cifsacl.c
@@ -0,0 +1,1672 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2007,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Contains the routines for mapping CIFS/NTFS ACLs
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/keyctl.h>
+#include <linux/key-type.h>
+#include <keys/user-type.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsacl.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "fs_context.h"
+
+/* security id for everyone/world system group */
+static const struct cifs_sid sid_everyone = {
+ 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
+/* security id for Authenticated Users system group */
+static const struct cifs_sid sid_authusers = {
+ 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
+
+/* S-1-22-1 Unmapped Unix users */
+static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
+ {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* S-1-22-2 Unmapped Unix groups */
+static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
+ {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/*
+ * See https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
+ */
+
+/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
+
+/* S-1-5-88-1 Unix uid */
+static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(88),
+ cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* S-1-5-88-2 Unix gid */
+static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(88),
+ cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* S-1-5-88-3 Unix mode */
+static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(88),
+ cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+static const struct cred *root_cred;
+
+static int
+cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
+{
+ char *payload;
+
+ /*
+ * If the payload is less than or equal to the size of a pointer, then
+ * an allocation here is wasteful. Just copy the data directly to the
+ * payload.value union member instead.
+ *
+ * With this however, you must check the datalen before trying to
+ * dereference payload.data!
+ */
+ if (prep->datalen <= sizeof(key->payload)) {
+ key->payload.data[0] = NULL;
+ memcpy(&key->payload, prep->data, prep->datalen);
+ } else {
+ payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
+ if (!payload)
+ return -ENOMEM;
+ key->payload.data[0] = payload;
+ }
+
+ key->datalen = prep->datalen;
+ return 0;
+}
+
+static inline void
+cifs_idmap_key_destroy(struct key *key)
+{
+ if (key->datalen > sizeof(key->payload))
+ kfree(key->payload.data[0]);
+}
+
+static struct key_type cifs_idmap_key_type = {
+ .name = "cifs.idmap",
+ .instantiate = cifs_idmap_key_instantiate,
+ .destroy = cifs_idmap_key_destroy,
+ .describe = user_describe,
+};
+
+static char *
+sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
+{
+ int i, len;
+ unsigned int saval;
+ char *sidstr, *strptr;
+ unsigned long long id_auth_val;
+
+ /* 3 bytes for prefix */
+ sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
+ (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
+ GFP_KERNEL);
+ if (!sidstr)
+ return sidstr;
+
+ strptr = sidstr;
+ len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
+ sidptr->revision);
+ strptr += len;
+
+ /* The authority field is a single 48-bit number */
+ id_auth_val = (unsigned long long)sidptr->authority[5];
+ id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
+ id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
+ id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
+ id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
+ id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
+
+ /*
+ * MS-DTYP states that if the authority is >= 2^32, then it should be
+ * expressed as a hex value.
+ */
+ if (id_auth_val <= UINT_MAX)
+ len = sprintf(strptr, "-%llu", id_auth_val);
+ else
+ len = sprintf(strptr, "-0x%llx", id_auth_val);
+
+ strptr += len;
+
+ for (i = 0; i < sidptr->num_subauth; ++i) {
+ saval = le32_to_cpu(sidptr->sub_auth[i]);
+ len = sprintf(strptr, "-%u", saval);
+ strptr += len;
+ }
+
+ return sidstr;
+}
+
+/*
+ * if the two SIDs (roughly equivalent to a UUID for a user or group) are
+ * the same returns zero, if they do not match returns non-zero.
+ */
+static int
+compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
+{
+ int i;
+ int num_subauth, num_sat, num_saw;
+
+ if ((!ctsid) || (!cwsid))
+ return 1;
+
+ /* compare the revision */
+ if (ctsid->revision != cwsid->revision) {
+ if (ctsid->revision > cwsid->revision)
+ return 1;
+ else
+ return -1;
+ }
+
+ /* compare all of the six auth values */
+ for (i = 0; i < NUM_AUTHS; ++i) {
+ if (ctsid->authority[i] != cwsid->authority[i]) {
+ if (ctsid->authority[i] > cwsid->authority[i])
+ return 1;
+ else
+ return -1;
+ }
+ }
+
+ /* compare all of the subauth values if any */
+ num_sat = ctsid->num_subauth;
+ num_saw = cwsid->num_subauth;
+ num_subauth = num_sat < num_saw ? num_sat : num_saw;
+ if (num_subauth) {
+ for (i = 0; i < num_subauth; ++i) {
+ if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
+ if (le32_to_cpu(ctsid->sub_auth[i]) >
+ le32_to_cpu(cwsid->sub_auth[i]))
+ return 1;
+ else
+ return -1;
+ }
+ }
+ }
+
+ return 0; /* sids compare/match */
+}
+
+static bool
+is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
+{
+ int i;
+ int num_subauth;
+ const struct cifs_sid *pwell_known_sid;
+
+ if (!psid || (puid == NULL))
+ return false;
+
+ num_subauth = psid->num_subauth;
+
+ /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
+ if (num_subauth == 2) {
+ if (is_group)
+ pwell_known_sid = &sid_unix_groups;
+ else
+ pwell_known_sid = &sid_unix_users;
+ } else if (num_subauth == 3) {
+ if (is_group)
+ pwell_known_sid = &sid_unix_NFS_groups;
+ else
+ pwell_known_sid = &sid_unix_NFS_users;
+ } else
+ return false;
+
+ /* compare the revision */
+ if (psid->revision != pwell_known_sid->revision)
+ return false;
+
+ /* compare all of the six auth values */
+ for (i = 0; i < NUM_AUTHS; ++i) {
+ if (psid->authority[i] != pwell_known_sid->authority[i]) {
+ cifs_dbg(FYI, "auth %d did not match\n", i);
+ return false;
+ }
+ }
+
+ if (num_subauth == 2) {
+ if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
+ return false;
+
+ *puid = le32_to_cpu(psid->sub_auth[1]);
+ } else /* 3 subauths, ie Windows/Mac style */ {
+ *puid = le32_to_cpu(psid->sub_auth[0]);
+ if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
+ (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
+ return false;
+
+ *puid = le32_to_cpu(psid->sub_auth[2]);
+ }
+
+ cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
+ return true; /* well known sid found, uid returned */
+}
+
+static __u16
+cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
+{
+ int i;
+ __u16 size = 1 + 1 + 6;
+
+ dst->revision = src->revision;
+ dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
+ for (i = 0; i < NUM_AUTHS; ++i)
+ dst->authority[i] = src->authority[i];
+ for (i = 0; i < dst->num_subauth; ++i)
+ dst->sub_auth[i] = src->sub_auth[i];
+ size += (dst->num_subauth * 4);
+
+ return size;
+}
+
+static int
+id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
+{
+ int rc;
+ struct key *sidkey;
+ struct cifs_sid *ksid;
+ unsigned int ksid_size;
+ char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
+ const struct cred *saved_cred;
+
+ rc = snprintf(desc, sizeof(desc), "%ci:%u",
+ sidtype == SIDOWNER ? 'o' : 'g', cid);
+ if (rc >= sizeof(desc))
+ return -EINVAL;
+
+ rc = 0;
+ saved_cred = override_creds(root_cred);
+ sidkey = request_key(&cifs_idmap_key_type, desc, "");
+ if (IS_ERR(sidkey)) {
+ rc = -EINVAL;
+ cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
+ __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
+ goto out_revert_creds;
+ } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
+ rc = -EIO;
+ cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
+ __func__, sidkey->datalen);
+ goto invalidate_key;
+ }
+
+ /*
+ * A sid is usually too large to be embedded in payload.value, but if
+ * there are no subauthorities and the host has 8-byte pointers, then
+ * it could be.
+ */
+ ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
+ (struct cifs_sid *)&sidkey->payload :
+ (struct cifs_sid *)sidkey->payload.data[0];
+
+ ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
+ if (ksid_size > sidkey->datalen) {
+ rc = -EIO;
+ cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
+ __func__, sidkey->datalen, ksid_size);
+ goto invalidate_key;
+ }
+
+ cifs_copy_sid(ssid, ksid);
+out_key_put:
+ key_put(sidkey);
+out_revert_creds:
+ revert_creds(saved_cred);
+ return rc;
+
+invalidate_key:
+ key_invalidate(sidkey);
+ goto out_key_put;
+}
+
+int
+sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
+ struct cifs_fattr *fattr, uint sidtype)
+{
+ int rc = 0;
+ struct key *sidkey;
+ char *sidstr;
+ const struct cred *saved_cred;
+ kuid_t fuid = cifs_sb->ctx->linux_uid;
+ kgid_t fgid = cifs_sb->ctx->linux_gid;
+
+ /*
+ * If we have too many subauthorities, then something is really wrong.
+ * Just return an error.
+ */
+ if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
+ cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
+ __func__, psid->num_subauth);
+ return -EIO;
+ }
+
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) ||
+ (cifs_sb_master_tcon(cifs_sb)->posix_extensions)) {
+ uint32_t unix_id;
+ bool is_group;
+
+ if (sidtype != SIDOWNER)
+ is_group = true;
+ else
+ is_group = false;
+
+ if (is_well_known_sid(psid, &unix_id, is_group) == false)
+ goto try_upcall_to_get_id;
+
+ if (is_group) {
+ kgid_t gid;
+ gid_t id;
+
+ id = (gid_t)unix_id;
+ gid = make_kgid(&init_user_ns, id);
+ if (gid_valid(gid)) {
+ fgid = gid;
+ goto got_valid_id;
+ }
+ } else {
+ kuid_t uid;
+ uid_t id;
+
+ id = (uid_t)unix_id;
+ uid = make_kuid(&init_user_ns, id);
+ if (uid_valid(uid)) {
+ fuid = uid;
+ goto got_valid_id;
+ }
+ }
+ /* If unable to find uid/gid easily from SID try via upcall */
+ }
+
+try_upcall_to_get_id:
+ sidstr = sid_to_key_str(psid, sidtype);
+ if (!sidstr)
+ return -ENOMEM;
+
+ saved_cred = override_creds(root_cred);
+ sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
+ if (IS_ERR(sidkey)) {
+ cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
+ __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
+ goto out_revert_creds;
+ }
+
+ /*
+ * FIXME: Here we assume that uid_t and gid_t are same size. It's
+ * probably a safe assumption but might be better to check based on
+ * sidtype.
+ */
+ BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
+ if (sidkey->datalen != sizeof(uid_t)) {
+ cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
+ __func__, sidkey->datalen);
+ key_invalidate(sidkey);
+ goto out_key_put;
+ }
+
+ if (sidtype == SIDOWNER) {
+ kuid_t uid;
+ uid_t id;
+ memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
+ uid = make_kuid(&init_user_ns, id);
+ if (uid_valid(uid))
+ fuid = uid;
+ } else {
+ kgid_t gid;
+ gid_t id;
+ memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
+ gid = make_kgid(&init_user_ns, id);
+ if (gid_valid(gid))
+ fgid = gid;
+ }
+
+out_key_put:
+ key_put(sidkey);
+out_revert_creds:
+ revert_creds(saved_cred);
+ kfree(sidstr);
+
+ /*
+ * Note that we return 0 here unconditionally. If the mapping
+ * fails then we just fall back to using the ctx->linux_uid/linux_gid.
+ */
+got_valid_id:
+ rc = 0;
+ if (sidtype == SIDOWNER)
+ fattr->cf_uid = fuid;
+ else
+ fattr->cf_gid = fgid;
+ return rc;
+}
+
+int
+init_cifs_idmap(void)
+{
+ struct cred *cred;
+ struct key *keyring;
+ int ret;
+
+ cifs_dbg(FYI, "Registering the %s key type\n",
+ cifs_idmap_key_type.name);
+
+ /* create an override credential set with a special thread keyring in
+ * which requests are cached
+ *
+ * this is used to prevent malicious redirections from being installed
+ * with add_key().
+ */
+ cred = prepare_kernel_cred(NULL);
+ if (!cred)
+ return -ENOMEM;
+
+ keyring = keyring_alloc(".cifs_idmap",
+ GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
+ (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+ KEY_USR_VIEW | KEY_USR_READ,
+ KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
+ if (IS_ERR(keyring)) {
+ ret = PTR_ERR(keyring);
+ goto failed_put_cred;
+ }
+
+ ret = register_key_type(&cifs_idmap_key_type);
+ if (ret < 0)
+ goto failed_put_key;
+
+ /* instruct request_key() to use this special keyring as a cache for
+ * the results it looks up */
+ set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
+ cred->thread_keyring = keyring;
+ cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+ root_cred = cred;
+
+ cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
+ return 0;
+
+failed_put_key:
+ key_put(keyring);
+failed_put_cred:
+ put_cred(cred);
+ return ret;
+}
+
+void
+exit_cifs_idmap(void)
+{
+ key_revoke(root_cred->thread_keyring);
+ unregister_key_type(&cifs_idmap_key_type);
+ put_cred(root_cred);
+ cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
+}
+
+/* copy ntsd, owner sid, and group sid from a security descriptor to another */
+static __u32 copy_sec_desc(const struct cifs_ntsd *pntsd,
+ struct cifs_ntsd *pnntsd,
+ __u32 sidsoffset,
+ struct cifs_sid *pownersid,
+ struct cifs_sid *pgrpsid)
+{
+ struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
+ struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
+
+ /* copy security descriptor control portion */
+ pnntsd->revision = pntsd->revision;
+ pnntsd->type = pntsd->type;
+ pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
+ pnntsd->sacloffset = 0;
+ pnntsd->osidoffset = cpu_to_le32(sidsoffset);
+ pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
+
+ /* copy owner sid */
+ if (pownersid)
+ owner_sid_ptr = pownersid;
+ else
+ owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->osidoffset));
+ nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
+ cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
+
+ /* copy group sid */
+ if (pgrpsid)
+ group_sid_ptr = pgrpsid;
+ else
+ group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->gsidoffset));
+ ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
+ sizeof(struct cifs_sid));
+ cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
+
+ return sidsoffset + (2 * sizeof(struct cifs_sid));
+}
+
+
+/*
+ change posix mode to reflect permissions
+ pmode is the existing mode (we only want to overwrite part of this
+ bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
+*/
+static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
+ umode_t *pdenied, umode_t mask)
+{
+ __u32 flags = le32_to_cpu(ace_flags);
+ /*
+ * Do not assume "preferred" or "canonical" order.
+ * The first DENY or ALLOW ACE which matches perfectly is
+ * the permission to be used. Once allowed or denied, same
+ * permission in later ACEs do not matter.
+ */
+
+ /* If not already allowed, deny these bits */
+ if (type == ACCESS_DENIED) {
+ if (flags & GENERIC_ALL &&
+ !(*pmode & mask & 0777))
+ *pdenied |= mask & 0777;
+
+ if (((flags & GENERIC_WRITE) ||
+ ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) &&
+ !(*pmode & mask & 0222))
+ *pdenied |= mask & 0222;
+
+ if (((flags & GENERIC_READ) ||
+ ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) &&
+ !(*pmode & mask & 0444))
+ *pdenied |= mask & 0444;
+
+ if (((flags & GENERIC_EXECUTE) ||
+ ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) &&
+ !(*pmode & mask & 0111))
+ *pdenied |= mask & 0111;
+
+ return;
+ } else if (type != ACCESS_ALLOWED) {
+ cifs_dbg(VFS, "unknown access control type %d\n", type);
+ return;
+ }
+ /* else ACCESS_ALLOWED type */
+
+ if ((flags & GENERIC_ALL) &&
+ !(*pdenied & mask & 0777)) {
+ *pmode |= mask & 0777;
+ cifs_dbg(NOISY, "all perms\n");
+ return;
+ }
+
+ if (((flags & GENERIC_WRITE) ||
+ ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) &&
+ !(*pdenied & mask & 0222))
+ *pmode |= mask & 0222;
+
+ if (((flags & GENERIC_READ) ||
+ ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) &&
+ !(*pdenied & mask & 0444))
+ *pmode |= mask & 0444;
+
+ if (((flags & GENERIC_EXECUTE) ||
+ ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) &&
+ !(*pdenied & mask & 0111))
+ *pmode |= mask & 0111;
+
+ /* If DELETE_CHILD is set only on an owner ACE, set sticky bit */
+ if (flags & FILE_DELETE_CHILD) {
+ if (mask == ACL_OWNER_MASK) {
+ if (!(*pdenied & 01000))
+ *pmode |= 01000;
+ } else if (!(*pdenied & 01000)) {
+ *pmode &= ~01000;
+ *pdenied |= 01000;
+ }
+ }
+
+ cifs_dbg(NOISY, "access flags 0x%x mode now %04o\n", flags, *pmode);
+ return;
+}
+
+/*
+ Generate access flags to reflect permissions mode is the existing mode.
+ This function is called for every ACE in the DACL whose SID matches
+ with either owner or group or everyone.
+*/
+
+static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
+ __u32 *pace_flags)
+{
+ /* reset access mask */
+ *pace_flags = 0x0;
+
+ /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
+ mode &= bits_to_use;
+
+ /* check for R/W/X UGO since we do not know whose flags
+ is this but we have cleared all the bits sans RWX for
+ either user or group or other as per bits_to_use */
+ if (mode & S_IRUGO)
+ *pace_flags |= SET_FILE_READ_RIGHTS;
+ if (mode & S_IWUGO)
+ *pace_flags |= SET_FILE_WRITE_RIGHTS;
+ if (mode & S_IXUGO)
+ *pace_flags |= SET_FILE_EXEC_RIGHTS;
+
+ cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x\n",
+ mode, *pace_flags);
+ return;
+}
+
+static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct cifs_sid *psid)
+{
+ __u16 size = 1 + 1 + 2 + 4;
+
+ dst->type = src->type;
+ dst->flags = src->flags;
+ dst->access_req = src->access_req;
+
+ /* Check if there's a replacement sid specified */
+ if (psid)
+ size += cifs_copy_sid(&dst->sid, psid);
+ else
+ size += cifs_copy_sid(&dst->sid, &src->sid);
+
+ dst->size = cpu_to_le16(size);
+
+ return size;
+}
+
+static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
+ const struct cifs_sid *psid, __u64 nmode,
+ umode_t bits, __u8 access_type,
+ bool allow_delete_child)
+{
+ int i;
+ __u16 size = 0;
+ __u32 access_req = 0;
+
+ pntace->type = access_type;
+ pntace->flags = 0x0;
+ mode_to_access_flags(nmode, bits, &access_req);
+
+ if (access_type == ACCESS_ALLOWED && allow_delete_child)
+ access_req |= FILE_DELETE_CHILD;
+
+ if (access_type == ACCESS_ALLOWED && !access_req)
+ access_req = SET_MINIMUM_RIGHTS;
+ else if (access_type == ACCESS_DENIED)
+ access_req &= ~SET_MINIMUM_RIGHTS;
+
+ pntace->access_req = cpu_to_le32(access_req);
+
+ pntace->sid.revision = psid->revision;
+ pntace->sid.num_subauth = psid->num_subauth;
+ for (i = 0; i < NUM_AUTHS; i++)
+ pntace->sid.authority[i] = psid->authority[i];
+ for (i = 0; i < psid->num_subauth; i++)
+ pntace->sid.sub_auth[i] = psid->sub_auth[i];
+
+ size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
+ pntace->size = cpu_to_le16(size);
+
+ return size;
+}
+
+
+#ifdef CONFIG_CIFS_DEBUG2
+static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
+{
+ int num_subauth;
+
+ /* validate that we do not go past end of acl */
+
+ if (le16_to_cpu(pace->size) < 16) {
+ cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
+ return;
+ }
+
+ if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
+ cifs_dbg(VFS, "ACL too small to parse ACE\n");
+ return;
+ }
+
+ num_subauth = pace->sid.num_subauth;
+ if (num_subauth) {
+ int i;
+ cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
+ pace->sid.revision, pace->sid.num_subauth, pace->type,
+ pace->flags, le16_to_cpu(pace->size));
+ for (i = 0; i < num_subauth; ++i) {
+ cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
+ i, le32_to_cpu(pace->sid.sub_auth[i]));
+ }
+
+ /* BB add length check to make sure that we do not have huge
+ num auths and therefore go off the end */
+ }
+
+ return;
+}
+#endif
+
+static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
+ struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
+ struct cifs_fattr *fattr, bool mode_from_special_sid)
+{
+ int i;
+ int num_aces = 0;
+ int acl_size;
+ char *acl_base;
+ struct cifs_ace **ppace;
+
+ /* BB need to add parm so we can store the SID BB */
+
+ if (!pdacl) {
+ /* no DACL in the security descriptor, set
+ all the permissions for user/group/other */
+ fattr->cf_mode |= 0777;
+ return;
+ }
+
+ /* validate that we do not go past end of acl */
+ if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
+ cifs_dbg(VFS, "ACL too small to parse DACL\n");
+ return;
+ }
+
+ cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
+ le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
+ le32_to_cpu(pdacl->num_aces));
+
+ /* reset rwx permissions for user/group/other.
+ Also, if num_aces is 0 i.e. DACL has no ACEs,
+ user/group/other have no permissions */
+ fattr->cf_mode &= ~(0777);
+
+ acl_base = (char *)pdacl;
+ acl_size = sizeof(struct cifs_acl);
+
+ num_aces = le32_to_cpu(pdacl->num_aces);
+ if (num_aces > 0) {
+ umode_t denied_mode = 0;
+
+ if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
+ return;
+ ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
+ GFP_KERNEL);
+ if (!ppace)
+ return;
+
+ for (i = 0; i < num_aces; ++i) {
+ ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
+#ifdef CONFIG_CIFS_DEBUG2
+ dump_ace(ppace[i], end_of_acl);
+#endif
+ if (mode_from_special_sid &&
+ (compare_sids(&(ppace[i]->sid),
+ &sid_unix_NFS_mode) == 0)) {
+ /*
+ * Full permissions are:
+ * 07777 = S_ISUID | S_ISGID | S_ISVTX |
+ * S_IRWXU | S_IRWXG | S_IRWXO
+ */
+ fattr->cf_mode &= ~07777;
+ fattr->cf_mode |=
+ le32_to_cpu(ppace[i]->sid.sub_auth[2]);
+ break;
+ } else {
+ if (compare_sids(&(ppace[i]->sid), pownersid) == 0) {
+ access_flags_to_mode(ppace[i]->access_req,
+ ppace[i]->type,
+ &fattr->cf_mode,
+ &denied_mode,
+ ACL_OWNER_MASK);
+ } else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) {
+ access_flags_to_mode(ppace[i]->access_req,
+ ppace[i]->type,
+ &fattr->cf_mode,
+ &denied_mode,
+ ACL_GROUP_MASK);
+ } else if ((compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) ||
+ (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)) {
+ access_flags_to_mode(ppace[i]->access_req,
+ ppace[i]->type,
+ &fattr->cf_mode,
+ &denied_mode,
+ ACL_EVERYONE_MASK);
+ }
+ }
+
+
+/* memcpy((void *)(&(cifscred->aces[i])),
+ (void *)ppace[i],
+ sizeof(struct cifs_ace)); */
+
+ acl_base = (char *)ppace[i];
+ acl_size = le16_to_cpu(ppace[i]->size);
+ }
+
+ kfree(ppace);
+ }
+
+ return;
+}
+
+unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
+{
+ int i;
+ unsigned int ace_size = 20;
+
+ pntace->type = ACCESS_ALLOWED_ACE_TYPE;
+ pntace->flags = 0x0;
+ pntace->access_req = cpu_to_le32(GENERIC_ALL);
+ pntace->sid.num_subauth = 1;
+ pntace->sid.revision = 1;
+ for (i = 0; i < NUM_AUTHS; i++)
+ pntace->sid.authority[i] = sid_authusers.authority[i];
+
+ pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0];
+
+ /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
+ pntace->size = cpu_to_le16(ace_size);
+ return ace_size;
+}
+
+/*
+ * Fill in the special SID based on the mode. See
+ * https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
+ */
+unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
+{
+ int i;
+ unsigned int ace_size = 28;
+
+ pntace->type = ACCESS_DENIED_ACE_TYPE;
+ pntace->flags = 0x0;
+ pntace->access_req = 0;
+ pntace->sid.num_subauth = 3;
+ pntace->sid.revision = 1;
+ for (i = 0; i < NUM_AUTHS; i++)
+ pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i];
+
+ pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
+ pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
+ pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
+
+ /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
+ pntace->size = cpu_to_le16(ace_size);
+ return ace_size;
+}
+
+unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
+{
+ int i;
+ unsigned int ace_size = 28;
+
+ pntace->type = ACCESS_ALLOWED_ACE_TYPE;
+ pntace->flags = 0x0;
+ pntace->access_req = cpu_to_le32(GENERIC_ALL);
+ pntace->sid.num_subauth = 3;
+ pntace->sid.revision = 1;
+ for (i = 0; i < NUM_AUTHS; i++)
+ pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];
+
+ pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
+ pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
+ pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);
+
+ /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
+ pntace->size = cpu_to_le16(ace_size);
+ return ace_size;
+}
+
+static void populate_new_aces(char *nacl_base,
+ struct cifs_sid *pownersid,
+ struct cifs_sid *pgrpsid,
+ __u64 *pnmode, u32 *pnum_aces, u16 *pnsize,
+ bool modefromsid)
+{
+ __u64 nmode;
+ u32 num_aces = 0;
+ u16 nsize = 0;
+ __u64 user_mode;
+ __u64 group_mode;
+ __u64 other_mode;
+ __u64 deny_user_mode = 0;
+ __u64 deny_group_mode = 0;
+ bool sticky_set = false;
+ struct cifs_ace *pnntace = NULL;
+
+ nmode = *pnmode;
+ num_aces = *pnum_aces;
+ nsize = *pnsize;
+
+ if (modefromsid) {
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+ nsize += setup_special_mode_ACE(pnntace, nmode);
+ num_aces++;
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+ nsize += setup_authusers_ACE(pnntace);
+ num_aces++;
+ goto set_size;
+ }
+
+ /*
+ * We'll try to keep the mode as requested by the user.
+ * But in cases where we cannot meaningfully convert that
+ * into ACL, return back the updated mode, so that it is
+ * updated in the inode.
+ */
+
+ if (!memcmp(pownersid, pgrpsid, sizeof(struct cifs_sid))) {
+ /*
+ * Case when owner and group SIDs are the same.
+ * Set the more restrictive of the two modes.
+ */
+ user_mode = nmode & (nmode << 3) & 0700;
+ group_mode = nmode & (nmode >> 3) & 0070;
+ } else {
+ user_mode = nmode & 0700;
+ group_mode = nmode & 0070;
+ }
+
+ other_mode = nmode & 0007;
+
+ /* We need DENY ACE when the perm is more restrictive than the next sets. */
+ deny_user_mode = ~(user_mode) & ((group_mode << 3) | (other_mode << 6)) & 0700;
+ deny_group_mode = ~(group_mode) & (other_mode << 3) & 0070;
+
+ *pnmode = user_mode | group_mode | other_mode | (nmode & ~0777);
+
+ /* This tells if we should allow delete child for group and everyone. */
+ if (nmode & 01000)
+ sticky_set = true;
+
+ if (deny_user_mode) {
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+ nsize += fill_ace_for_sid(pnntace, pownersid, deny_user_mode,
+ 0700, ACCESS_DENIED, false);
+ num_aces++;
+ }
+
+ /* Group DENY ACE does not conflict with owner ALLOW ACE. Keep in preferred order*/
+ if (deny_group_mode && !(deny_group_mode & (user_mode >> 3))) {
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+ nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
+ 0070, ACCESS_DENIED, false);
+ num_aces++;
+ }
+
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+ nsize += fill_ace_for_sid(pnntace, pownersid, user_mode,
+ 0700, ACCESS_ALLOWED, true);
+ num_aces++;
+
+ /* Group DENY ACE conflicts with owner ALLOW ACE. So keep it after. */
+ if (deny_group_mode && (deny_group_mode & (user_mode >> 3))) {
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+ nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
+ 0070, ACCESS_DENIED, false);
+ num_aces++;
+ }
+
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+ nsize += fill_ace_for_sid(pnntace, pgrpsid, group_mode,
+ 0070, ACCESS_ALLOWED, !sticky_set);
+ num_aces++;
+
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+ nsize += fill_ace_for_sid(pnntace, &sid_everyone, other_mode,
+ 0007, ACCESS_ALLOWED, !sticky_set);
+ num_aces++;
+
+set_size:
+ *pnum_aces = num_aces;
+ *pnsize = nsize;
+}
+
+static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
+ struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
+ struct cifs_sid *pnownersid, struct cifs_sid *pngrpsid)
+{
+ int i;
+ u16 size = 0;
+ struct cifs_ace *pntace = NULL;
+ char *acl_base = NULL;
+ u32 src_num_aces = 0;
+ u16 nsize = 0;
+ struct cifs_ace *pnntace = NULL;
+ char *nacl_base = NULL;
+ u16 ace_size = 0;
+
+ acl_base = (char *)pdacl;
+ size = sizeof(struct cifs_acl);
+ src_num_aces = le32_to_cpu(pdacl->num_aces);
+
+ nacl_base = (char *)pndacl;
+ nsize = sizeof(struct cifs_acl);
+
+ /* Go through all the ACEs */
+ for (i = 0; i < src_num_aces; ++i) {
+ pntace = (struct cifs_ace *) (acl_base + size);
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+
+ if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0)
+ ace_size = cifs_copy_ace(pnntace, pntace, pnownersid);
+ else if (pngrpsid && compare_sids(&pntace->sid, pgrpsid) == 0)
+ ace_size = cifs_copy_ace(pnntace, pntace, pngrpsid);
+ else
+ ace_size = cifs_copy_ace(pnntace, pntace, NULL);
+
+ size += le16_to_cpu(pntace->size);
+ nsize += ace_size;
+ }
+
+ return nsize;
+}
+
+static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
+ struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
+ __u64 *pnmode, bool mode_from_sid)
+{
+ int i;
+ u16 size = 0;
+ struct cifs_ace *pntace = NULL;
+ char *acl_base = NULL;
+ u32 src_num_aces = 0;
+ u16 nsize = 0;
+ struct cifs_ace *pnntace = NULL;
+ char *nacl_base = NULL;
+ u32 num_aces = 0;
+ bool new_aces_set = false;
+
+ /* Assuming that pndacl and pnmode are never NULL */
+ nacl_base = (char *)pndacl;
+ nsize = sizeof(struct cifs_acl);
+
+ /* If pdacl is NULL, we don't have a src. Simply populate new ACL. */
+ if (!pdacl) {
+ populate_new_aces(nacl_base,
+ pownersid, pgrpsid,
+ pnmode, &num_aces, &nsize,
+ mode_from_sid);
+ goto finalize_dacl;
+ }
+
+ acl_base = (char *)pdacl;
+ size = sizeof(struct cifs_acl);
+ src_num_aces = le32_to_cpu(pdacl->num_aces);
+
+ /* Retain old ACEs which we can retain */
+ for (i = 0; i < src_num_aces; ++i) {
+ pntace = (struct cifs_ace *) (acl_base + size);
+
+ if (!new_aces_set && (pntace->flags & INHERITED_ACE)) {
+ /* Place the new ACEs in between existing explicit and inherited */
+ populate_new_aces(nacl_base,
+ pownersid, pgrpsid,
+ pnmode, &num_aces, &nsize,
+ mode_from_sid);
+
+ new_aces_set = true;
+ }
+
+ /* If it's any one of the ACE we're replacing, skip! */
+ if (((compare_sids(&pntace->sid, &sid_unix_NFS_mode) == 0) ||
+ (compare_sids(&pntace->sid, pownersid) == 0) ||
+ (compare_sids(&pntace->sid, pgrpsid) == 0) ||
+ (compare_sids(&pntace->sid, &sid_everyone) == 0) ||
+ (compare_sids(&pntace->sid, &sid_authusers) == 0))) {
+ goto next_ace;
+ }
+
+ /* update the pointer to the next ACE to populate*/
+ pnntace = (struct cifs_ace *) (nacl_base + nsize);
+
+ nsize += cifs_copy_ace(pnntace, pntace, NULL);
+ num_aces++;
+
+next_ace:
+ size += le16_to_cpu(pntace->size);
+ }
+
+ /* If inherited ACEs are not present, place the new ones at the tail */
+ if (!new_aces_set) {
+ populate_new_aces(nacl_base,
+ pownersid, pgrpsid,
+ pnmode, &num_aces, &nsize,
+ mode_from_sid);
+
+ new_aces_set = true;
+ }
+
+finalize_dacl:
+ pndacl->num_aces = cpu_to_le32(num_aces);
+ pndacl->size = cpu_to_le16(nsize);
+
+ return 0;
+}
+
+static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
+{
+ /* BB need to add parm so we can store the SID BB */
+
+ /* validate that we do not go past end of ACL - sid must be at least 8
+ bytes long (assuming no sub-auths - e.g. the null SID */
+ if (end_of_acl < (char *)psid + 8) {
+ cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_CIFS_DEBUG2
+ if (psid->num_subauth) {
+ int i;
+ cifs_dbg(FYI, "SID revision %d num_auth %d\n",
+ psid->revision, psid->num_subauth);
+
+ for (i = 0; i < psid->num_subauth; i++) {
+ cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
+ i, le32_to_cpu(psid->sub_auth[i]));
+ }
+
+ /* BB add length check to make sure that we do not have huge
+ num auths and therefore go off the end */
+ cifs_dbg(FYI, "RID 0x%x\n",
+ le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
+ }
+#endif
+
+ return 0;
+}
+
+
+/* Convert CIFS ACL to POSIX form */
+static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
+ struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
+ bool get_mode_from_special_sid)
+{
+ int rc = 0;
+ struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
+ struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
+ char *end_of_acl = ((char *)pntsd) + acl_len;
+ __u32 dacloffset;
+
+ if (pntsd == NULL)
+ return -EIO;
+
+ owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->osidoffset));
+ group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->gsidoffset));
+ dacloffset = le32_to_cpu(pntsd->dacloffset);
+ dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+ cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
+ pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
+ le32_to_cpu(pntsd->gsidoffset),
+ le32_to_cpu(pntsd->sacloffset), dacloffset);
+/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
+ rc = parse_sid(owner_sid_ptr, end_of_acl);
+ if (rc) {
+ cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
+ return rc;
+ }
+ rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
+ if (rc) {
+ cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
+ __func__, rc);
+ return rc;
+ }
+
+ rc = parse_sid(group_sid_ptr, end_of_acl);
+ if (rc) {
+ cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
+ __func__, rc);
+ return rc;
+ }
+ rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
+ if (rc) {
+ cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (dacloffset)
+ parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
+ group_sid_ptr, fattr, get_mode_from_special_sid);
+ else
+ cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
+
+ return rc;
+}
+
+/* Convert permission bits from mode to equivalent CIFS ACL */
+static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
+ __u32 secdesclen, __u32 *pnsecdesclen, __u64 *pnmode, kuid_t uid, kgid_t gid,
+ bool mode_from_sid, bool id_from_sid, int *aclflag)
+{
+ int rc = 0;
+ __u32 dacloffset;
+ __u32 ndacloffset;
+ __u32 sidsoffset;
+ struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
+ struct cifs_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
+ struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
+ struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
+ char *end_of_acl = ((char *)pntsd) + secdesclen;
+ u16 size = 0;
+
+ dacloffset = le32_to_cpu(pntsd->dacloffset);
+ if (dacloffset) {
+ dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+ if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) {
+ cifs_dbg(VFS, "Server returned illegal ACL size\n");
+ return -EINVAL;
+ }
+ }
+
+ owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->osidoffset));
+ group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->gsidoffset));
+
+ if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
+ ndacloffset = sizeof(struct cifs_ntsd);
+ ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
+ ndacl_ptr->revision =
+ dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
+
+ ndacl_ptr->size = cpu_to_le16(0);
+ ndacl_ptr->num_aces = cpu_to_le32(0);
+
+ rc = set_chmod_dacl(dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr,
+ pnmode, mode_from_sid);
+
+ sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
+ /* copy the non-dacl portion of secdesc */
+ *pnsecdesclen = copy_sec_desc(pntsd, pnntsd, sidsoffset,
+ NULL, NULL);
+
+ *aclflag |= CIFS_ACL_DACL;
+ } else {
+ ndacloffset = sizeof(struct cifs_ntsd);
+ ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
+ ndacl_ptr->revision =
+ dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
+ ndacl_ptr->num_aces = dacl_ptr ? dacl_ptr->num_aces : 0;
+
+ if (uid_valid(uid)) { /* chown */
+ uid_t id;
+ nowner_sid_ptr = kzalloc(sizeof(struct cifs_sid),
+ GFP_KERNEL);
+ if (!nowner_sid_ptr) {
+ rc = -ENOMEM;
+ goto chown_chgrp_exit;
+ }
+ id = from_kuid(&init_user_ns, uid);
+ if (id_from_sid) {
+ struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
+ /* Populate the user ownership fields S-1-5-88-1 */
+ osid->Revision = 1;
+ osid->NumAuth = 3;
+ osid->Authority[5] = 5;
+ osid->SubAuthorities[0] = cpu_to_le32(88);
+ osid->SubAuthorities[1] = cpu_to_le32(1);
+ osid->SubAuthorities[2] = cpu_to_le32(id);
+
+ } else { /* lookup sid with upcall */
+ rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
+ if (rc) {
+ cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
+ __func__, rc, id);
+ goto chown_chgrp_exit;
+ }
+ }
+ *aclflag |= CIFS_ACL_OWNER;
+ }
+ if (gid_valid(gid)) { /* chgrp */
+ gid_t id;
+ ngroup_sid_ptr = kzalloc(sizeof(struct cifs_sid),
+ GFP_KERNEL);
+ if (!ngroup_sid_ptr) {
+ rc = -ENOMEM;
+ goto chown_chgrp_exit;
+ }
+ id = from_kgid(&init_user_ns, gid);
+ if (id_from_sid) {
+ struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
+ /* Populate the group ownership fields S-1-5-88-2 */
+ gsid->Revision = 1;
+ gsid->NumAuth = 3;
+ gsid->Authority[5] = 5;
+ gsid->SubAuthorities[0] = cpu_to_le32(88);
+ gsid->SubAuthorities[1] = cpu_to_le32(2);
+ gsid->SubAuthorities[2] = cpu_to_le32(id);
+
+ } else { /* lookup sid with upcall */
+ rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
+ if (rc) {
+ cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
+ __func__, rc, id);
+ goto chown_chgrp_exit;
+ }
+ }
+ *aclflag |= CIFS_ACL_GROUP;
+ }
+
+ if (dacloffset) {
+ /* Replace ACEs for old owner with new one */
+ size = replace_sids_and_copy_aces(dacl_ptr, ndacl_ptr,
+ owner_sid_ptr, group_sid_ptr,
+ nowner_sid_ptr, ngroup_sid_ptr);
+ ndacl_ptr->size = cpu_to_le16(size);
+ }
+
+ sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
+ /* copy the non-dacl portion of secdesc */
+ *pnsecdesclen = copy_sec_desc(pntsd, pnntsd, sidsoffset,
+ nowner_sid_ptr, ngroup_sid_ptr);
+
+chown_chgrp_exit:
+ /* errors could jump here. So make sure we return soon after this */
+ kfree(nowner_sid_ptr);
+ kfree(ngroup_sid_ptr);
+ }
+
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
+ const struct cifs_fid *cifsfid, u32 *pacllen,
+ u32 __maybe_unused unused)
+{
+ struct cifs_ntsd *pntsd = NULL;
+ unsigned int xid;
+ int rc;
+ struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+
+ if (IS_ERR(tlink))
+ return ERR_CAST(tlink);
+
+ xid = get_xid();
+ rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
+ pacllen);
+ free_xid(xid);
+
+ cifs_put_tlink(tlink);
+
+ cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
+ if (rc)
+ return ERR_PTR(rc);
+ return pntsd;
+}
+
+static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
+ const char *path, u32 *pacllen)
+{
+ struct cifs_ntsd *pntsd = NULL;
+ int oplock = 0;
+ unsigned int xid;
+ int rc;
+ struct cifs_tcon *tcon;
+ struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+
+ if (IS_ERR(tlink))
+ return ERR_CAST(tlink);
+
+ tcon = tlink_tcon(tlink);
+ xid = get_xid();
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = READ_CONTROL,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .disposition = FILE_OPEN,
+ .path = path,
+ .fid = &fid,
+ };
+
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (!rc) {
+ rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
+ CIFSSMBClose(xid, tcon, fid.netfid);
+ }
+
+ cifs_put_tlink(tlink);
+ free_xid(xid);
+
+ cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
+ if (rc)
+ return ERR_PTR(rc);
+ return pntsd;
+}
+
+/* Retrieve an ACL from the server */
+struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
+ struct inode *inode, const char *path,
+ u32 *pacllen, u32 info)
+{
+ struct cifs_ntsd *pntsd = NULL;
+ struct cifsFileInfo *open_file = NULL;
+
+ if (inode)
+ open_file = find_readable_file(CIFS_I(inode), true);
+ if (!open_file)
+ return get_cifs_acl_by_path(cifs_sb, path, pacllen);
+
+ pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
+ cifsFileInfo_put(open_file);
+ return pntsd;
+}
+
+ /* Set an ACL on the server */
+int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
+ struct inode *inode, const char *path, int aclflag)
+{
+ int oplock = 0;
+ unsigned int xid;
+ int rc, access_flags;
+ struct cifs_tcon *tcon;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+
+ tcon = tlink_tcon(tlink);
+ xid = get_xid();
+
+ if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
+ access_flags = WRITE_OWNER;
+ else
+ access_flags = WRITE_DAC;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = access_flags,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .disposition = FILE_OPEN,
+ .path = path,
+ .fid = &fid,
+ };
+
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (rc) {
+ cifs_dbg(VFS, "Unable to open file to set ACL\n");
+ goto out;
+ }
+
+ rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
+ cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
+
+ CIFSSMBClose(xid, tcon, fid.netfid);
+out:
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+/* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
+int
+cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
+ struct inode *inode, bool mode_from_special_sid,
+ const char *path, const struct cifs_fid *pfid)
+{
+ struct cifs_ntsd *pntsd = NULL;
+ u32 acllen = 0;
+ int rc = 0;
+ struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+ struct smb_version_operations *ops;
+ const u32 info = 0;
+
+ cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
+
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+
+ ops = tlink_tcon(tlink)->ses->server->ops;
+
+ if (pfid && (ops->get_acl_by_fid))
+ pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen, info);
+ else if (ops->get_acl)
+ pntsd = ops->get_acl(cifs_sb, inode, path, &acllen, info);
+ else {
+ cifs_put_tlink(tlink);
+ return -EOPNOTSUPP;
+ }
+ /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
+ if (IS_ERR(pntsd)) {
+ rc = PTR_ERR(pntsd);
+ cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
+ } else if (mode_from_special_sid) {
+ rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
+ kfree(pntsd);
+ } else {
+ /* get approximated mode from ACL */
+ rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
+ kfree(pntsd);
+ if (rc)
+ cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
+ }
+
+ cifs_put_tlink(tlink);
+
+ return rc;
+}
+
+/* Convert mode bits to an ACL so we can update the ACL on the server */
+int
+id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
+ kuid_t uid, kgid_t gid)
+{
+ int rc = 0;
+ int aclflag = CIFS_ACL_DACL; /* default flag to set */
+ __u32 secdesclen = 0;
+ __u32 nsecdesclen = 0;
+ __u32 dacloffset = 0;
+ struct cifs_acl *dacl_ptr = NULL;
+ struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
+ struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+ struct smb_version_operations *ops;
+ bool mode_from_sid, id_from_sid;
+ const u32 info = 0;
+
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+
+ ops = tlink_tcon(tlink)->ses->server->ops;
+
+ cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
+
+ /* Get the security descriptor */
+
+ if (ops->get_acl == NULL) {
+ cifs_put_tlink(tlink);
+ return -EOPNOTSUPP;
+ }
+
+ pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen, info);
+ if (IS_ERR(pntsd)) {
+ rc = PTR_ERR(pntsd);
+ cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
+ cifs_put_tlink(tlink);
+ return rc;
+ }
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
+ mode_from_sid = true;
+ else
+ mode_from_sid = false;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
+ id_from_sid = true;
+ else
+ id_from_sid = false;
+
+ /* Potentially, five new ACEs can be added to the ACL for U,G,O mapping */
+ nsecdesclen = secdesclen;
+ if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
+ if (mode_from_sid)
+ nsecdesclen += 2 * sizeof(struct cifs_ace);
+ else /* cifsacl */
+ nsecdesclen += 5 * sizeof(struct cifs_ace);
+ } else { /* chown */
+ /* When ownership changes, changes new owner sid length could be different */
+ nsecdesclen = sizeof(struct cifs_ntsd) + (sizeof(struct cifs_sid) * 2);
+ dacloffset = le32_to_cpu(pntsd->dacloffset);
+ if (dacloffset) {
+ dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
+ if (mode_from_sid)
+ nsecdesclen +=
+ le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct cifs_ace);
+ else /* cifsacl */
+ nsecdesclen += le16_to_cpu(dacl_ptr->size);
+ }
+ }
+
+ /*
+ * Add three ACEs for owner, group, everyone getting rid of other ACEs
+ * as chmod disables ACEs and set the security descriptor. Allocate
+ * memory for the smb header, set security descriptor request security
+ * descriptor parameters, and security descriptor itself
+ */
+ nsecdesclen = max_t(u32, nsecdesclen, DEFAULT_SEC_DESC_LEN);
+ pnntsd = kmalloc(nsecdesclen, GFP_KERNEL);
+ if (!pnntsd) {
+ kfree(pntsd);
+ cifs_put_tlink(tlink);
+ return -ENOMEM;
+ }
+
+ rc = build_sec_desc(pntsd, pnntsd, secdesclen, &nsecdesclen, pnmode, uid, gid,
+ mode_from_sid, id_from_sid, &aclflag);
+
+ cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
+
+ if (ops->set_acl == NULL)
+ rc = -EOPNOTSUPP;
+
+ if (!rc) {
+ /* Set the security descriptor */
+ rc = ops->set_acl(pnntsd, nsecdesclen, inode, path, aclflag);
+ cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
+ }
+ cifs_put_tlink(tlink);
+
+ kfree(pnntsd);
+ kfree(pntsd);
+ return rc;
+}
diff --git a/fs/smb/client/cifsacl.h b/fs/smb/client/cifsacl.h
new file mode 100644
index 000000000000..ccbfc754bd3c
--- /dev/null
+++ b/fs/smb/client/cifsacl.h
@@ -0,0 +1,199 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2007
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#ifndef _CIFSACL_H
+#define _CIFSACL_H
+
+#define NUM_AUTHS (6) /* number of authority fields */
+#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
+
+#define READ_BIT 0x4
+#define WRITE_BIT 0x2
+#define EXEC_BIT 0x1
+
+#define ACL_OWNER_MASK 0700
+#define ACL_GROUP_MASK 0070
+#define ACL_EVERYONE_MASK 0007
+
+#define UBITSHIFT 6
+#define GBITSHIFT 3
+
+#define ACCESS_ALLOWED 0
+#define ACCESS_DENIED 1
+
+#define SIDOWNER 1
+#define SIDGROUP 2
+
+/*
+ * Security Descriptor length containing DACL with 3 ACEs (one each for
+ * owner, group and world).
+ */
+#define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \
+ sizeof(struct cifs_acl) + \
+ (sizeof(struct cifs_ace) * 4))
+
+/*
+ * Maximum size of a string representation of a SID:
+ *
+ * The fields are unsigned values in decimal. So:
+ *
+ * u8: max 3 bytes in decimal
+ * u32: max 10 bytes in decimal
+ *
+ * "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
+ *
+ * For authority field, max is when all 6 values are non-zero and it must be
+ * represented in hex. So "-0x" + 12 hex digits.
+ *
+ * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
+ */
+#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
+#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
+
+struct cifs_ntsd {
+ __le16 revision; /* revision level */
+ __le16 type;
+ __le32 osidoffset;
+ __le32 gsidoffset;
+ __le32 sacloffset;
+ __le32 dacloffset;
+} __attribute__((packed));
+
+struct cifs_sid {
+ __u8 revision; /* revision level */
+ __u8 num_subauth;
+ __u8 authority[NUM_AUTHS];
+ __le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
+} __attribute__((packed));
+
+/* size of a struct cifs_sid, sans sub_auth array */
+#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
+
+struct cifs_acl {
+ __le16 revision; /* revision level */
+ __le16 size;
+ __le32 num_aces;
+} __attribute__((packed));
+
+/* ACE types - see MS-DTYP 2.4.4.1 */
+#define ACCESS_ALLOWED_ACE_TYPE 0x00
+#define ACCESS_DENIED_ACE_TYPE 0x01
+#define SYSTEM_AUDIT_ACE_TYPE 0x02
+#define SYSTEM_ALARM_ACE_TYPE 0x03
+#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
+#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
+#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
+#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
+#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
+#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
+#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
+#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
+#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C
+#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D
+#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */
+#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
+#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
+#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
+#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
+#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13
+
+/* ACE flags */
+#define OBJECT_INHERIT_ACE 0x01
+#define CONTAINER_INHERIT_ACE 0x02
+#define NO_PROPAGATE_INHERIT_ACE 0x04
+#define INHERIT_ONLY_ACE 0x08
+#define INHERITED_ACE 0x10
+#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
+#define FAILED_ACCESS_ACE_FLAG 0x80
+
+struct cifs_ace {
+ __u8 type; /* see above and MS-DTYP 2.4.4.1 */
+ __u8 flags;
+ __le16 size;
+ __le32 access_req;
+ struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
+} __attribute__((packed));
+
+/*
+ * The current SMB3 form of security descriptor is similar to what was used for
+ * cifs (see above) but some fields are split, and fields in the struct below
+ * matches names of fields to the spec, MS-DTYP (see sections 2.4.5 and
+ * 2.4.6). Note that "CamelCase" fields are used in this struct in order to
+ * match the MS-DTYP and MS-SMB2 specs which define the wire format.
+ */
+struct smb3_sd {
+ __u8 Revision; /* revision level, MUST be one */
+ __u8 Sbz1; /* only meaningful if 'RM' flag set below */
+ __le16 Control;
+ __le32 OffsetOwner;
+ __le32 OffsetGroup;
+ __le32 OffsetSacl;
+ __le32 OffsetDacl;
+} __packed;
+
+/* Meaning of 'Control' field flags */
+#define ACL_CONTROL_SR 0x8000 /* Self relative */
+#define ACL_CONTROL_RM 0x4000 /* Resource manager control bits */
+#define ACL_CONTROL_PS 0x2000 /* SACL protected from inherits */
+#define ACL_CONTROL_PD 0x1000 /* DACL protected from inherits */
+#define ACL_CONTROL_SI 0x0800 /* SACL Auto-Inherited */
+#define ACL_CONTROL_DI 0x0400 /* DACL Auto-Inherited */
+#define ACL_CONTROL_SC 0x0200 /* SACL computed through inheritance */
+#define ACL_CONTROL_DC 0x0100 /* DACL computed through inheritence */
+#define ACL_CONTROL_SS 0x0080 /* Create server ACL */
+#define ACL_CONTROL_DT 0x0040 /* DACL provided by trusted source */
+#define ACL_CONTROL_SD 0x0020 /* SACL defaulted */
+#define ACL_CONTROL_SP 0x0010 /* SACL is present on object */
+#define ACL_CONTROL_DD 0x0008 /* DACL defaulted */
+#define ACL_CONTROL_DP 0x0004 /* DACL is present on object */
+#define ACL_CONTROL_GD 0x0002 /* Group was defaulted */
+#define ACL_CONTROL_OD 0x0001 /* User was defaulted */
+
+/* Meaning of AclRevision flags */
+#define ACL_REVISION 0x02 /* See section 2.4.4.1 of MS-DTYP */
+#define ACL_REVISION_DS 0x04 /* Additional AceTypes allowed */
+
+struct smb3_acl {
+ u8 AclRevision; /* revision level */
+ u8 Sbz1; /* MBZ */
+ __le16 AclSize;
+ __le16 AceCount;
+ __le16 Sbz2; /* MBZ */
+} __packed;
+
+/*
+ * Used to store the special 'NFS SIDs' used to persist the POSIX uid and gid
+ * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
+ */
+struct owner_sid {
+ u8 Revision;
+ u8 NumAuth;
+ u8 Authority[6];
+ __le32 SubAuthorities[3];
+} __packed;
+
+struct owner_group_sids {
+ struct owner_sid owner;
+ struct owner_sid group;
+} __packed;
+
+/*
+ * Minimum security identifier can be one for system defined Users
+ * and Groups such as NULL SID and World or Built-in accounts such
+ * as Administrator and Guest and consists of
+ * Revision + Num (Sub)Auths + Authority + Domain (one Subauthority)
+ */
+#define MIN_SID_LEN (1 + 1 + 6 + 4) /* in bytes */
+
+/*
+ * Minimum security descriptor can be one without any SACL and DACL and can
+ * consist of revision, type, and two sids of minimum size for owner and group
+ */
+#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN))
+
+#endif /* _CIFSACL_H */
diff --git a/fs/smb/client/cifsencrypt.c b/fs/smb/client/cifsencrypt.c
new file mode 100644
index 000000000000..d0ac2648c0d6
--- /dev/null
+++ b/fs/smb/client/cifsencrypt.c
@@ -0,0 +1,733 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Encryption and hashing operations relating to NTLM, NTLMv2. See MS-NLMP
+ * for more detailed information
+ *
+ * Copyright (C) International Business Machines Corp., 2005,2013
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "cifs_unicode.h"
+#include "cifsproto.h"
+#include "ntlmssp.h"
+#include <linux/ctype.h>
+#include <linux/random.h>
+#include <linux/highmem.h>
+#include <linux/fips.h>
+#include "../common/arc4.h"
+#include <crypto/aead.h>
+
+int __cifs_calc_signature(struct smb_rqst *rqst,
+ struct TCP_Server_Info *server, char *signature,
+ struct shash_desc *shash)
+{
+ int i;
+ int rc;
+ struct kvec *iov = rqst->rq_iov;
+ int n_vec = rqst->rq_nvec;
+
+ /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
+ if (!is_smb1(server)) {
+ if (iov[0].iov_len <= 4)
+ return -EIO;
+ i = 0;
+ } else {
+ if (n_vec < 2 || iov[0].iov_len != 4)
+ return -EIO;
+ i = 1; /* skip rfc1002 length */
+ }
+
+ for (; i < n_vec; i++) {
+ if (iov[i].iov_len == 0)
+ continue;
+ if (iov[i].iov_base == NULL) {
+ cifs_dbg(VFS, "null iovec entry\n");
+ return -EIO;
+ }
+
+ rc = crypto_shash_update(shash,
+ iov[i].iov_base, iov[i].iov_len);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with payload\n",
+ __func__);
+ return rc;
+ }
+ }
+
+ /* now hash over the rq_pages array */
+ for (i = 0; i < rqst->rq_npages; i++) {
+ void *kaddr;
+ unsigned int len, offset;
+
+ rqst_page_get_length(rqst, i, &len, &offset);
+
+ kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
+
+ rc = crypto_shash_update(shash, kaddr, len);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with payload\n",
+ __func__);
+ kunmap(rqst->rq_pages[i]);
+ return rc;
+ }
+
+ kunmap(rqst->rq_pages[i]);
+ }
+
+ rc = crypto_shash_final(shash, signature);
+ if (rc)
+ cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
+
+ return rc;
+}
+
+/*
+ * Calculate and return the CIFS signature based on the mac key and SMB PDU.
+ * The 16 byte signature must be allocated by the caller. Note we only use the
+ * 1st eight bytes and that the smb header signature field on input contains
+ * the sequence number before this function is called. Also, this function
+ * should be called with the server->srv_mutex held.
+ */
+static int cifs_calc_signature(struct smb_rqst *rqst,
+ struct TCP_Server_Info *server, char *signature)
+{
+ int rc;
+
+ if (!rqst->rq_iov || !signature || !server)
+ return -EINVAL;
+
+ rc = cifs_alloc_hash("md5", &server->secmech.md5);
+ if (rc)
+ return -1;
+
+ rc = crypto_shash_init(server->secmech.md5);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
+ return rc;
+ }
+
+ rc = crypto_shash_update(server->secmech.md5,
+ server->session_key.response, server->session_key.len);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
+ return rc;
+ }
+
+ return __cifs_calc_signature(rqst, server, signature, server->secmech.md5);
+}
+
+/* must be called with server->srv_mutex held */
+int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
+ __u32 *pexpected_response_sequence_number)
+{
+ int rc = 0;
+ char smb_signature[20];
+ struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
+
+ if (rqst->rq_iov[0].iov_len != 4 ||
+ rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
+ return -EIO;
+
+ if ((cifs_pdu == NULL) || (server == NULL))
+ return -EINVAL;
+
+ spin_lock(&server->srv_lock);
+ if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
+ server->tcpStatus == CifsNeedNegotiate) {
+ spin_unlock(&server->srv_lock);
+ return rc;
+ }
+ spin_unlock(&server->srv_lock);
+
+ if (!server->session_estab) {
+ memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
+ return rc;
+ }
+
+ cifs_pdu->Signature.Sequence.SequenceNumber =
+ cpu_to_le32(server->sequence_number);
+ cifs_pdu->Signature.Sequence.Reserved = 0;
+
+ *pexpected_response_sequence_number = ++server->sequence_number;
+ ++server->sequence_number;
+
+ rc = cifs_calc_signature(rqst, server, smb_signature);
+ if (rc)
+ memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
+ else
+ memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
+
+ return rc;
+}
+
+int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
+ __u32 *pexpected_response_sequence)
+{
+ struct smb_rqst rqst = { .rq_iov = iov,
+ .rq_nvec = n_vec };
+
+ return cifs_sign_rqst(&rqst, server, pexpected_response_sequence);
+}
+
+/* must be called with server->srv_mutex held */
+int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
+ __u32 *pexpected_response_sequence_number)
+{
+ struct kvec iov[2];
+
+ iov[0].iov_base = cifs_pdu;
+ iov[0].iov_len = 4;
+ iov[1].iov_base = (char *)cifs_pdu + 4;
+ iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
+
+ return cifs_sign_smbv(iov, 2, server,
+ pexpected_response_sequence_number);
+}
+
+int cifs_verify_signature(struct smb_rqst *rqst,
+ struct TCP_Server_Info *server,
+ __u32 expected_sequence_number)
+{
+ unsigned int rc;
+ char server_response_sig[8];
+ char what_we_think_sig_should_be[20];
+ struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
+
+ if (rqst->rq_iov[0].iov_len != 4 ||
+ rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
+ return -EIO;
+
+ if (cifs_pdu == NULL || server == NULL)
+ return -EINVAL;
+
+ if (!server->session_estab)
+ return 0;
+
+ if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
+ struct smb_com_lock_req *pSMB =
+ (struct smb_com_lock_req *)cifs_pdu;
+ if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
+ return 0;
+ }
+
+ /* BB what if signatures are supposed to be on for session but
+ server does not send one? BB */
+
+ /* Do not need to verify session setups with signature "BSRSPYL " */
+ if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
+ cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
+ cifs_pdu->Command);
+
+ /* save off the origiginal signature so we can modify the smb and check
+ its signature against what the server sent */
+ memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
+
+ cifs_pdu->Signature.Sequence.SequenceNumber =
+ cpu_to_le32(expected_sequence_number);
+ cifs_pdu->Signature.Sequence.Reserved = 0;
+
+ cifs_server_lock(server);
+ rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
+ cifs_server_unlock(server);
+
+ if (rc)
+ return rc;
+
+/* cifs_dump_mem("what we think it should be: ",
+ what_we_think_sig_should_be, 16); */
+
+ if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
+ return -EACCES;
+ else
+ return 0;
+
+}
+
+/* Build a proper attribute value/target info pairs blob.
+ * Fill in netbios and dns domain name and workstation name
+ * and client time (total five av pairs and + one end of fields indicator.
+ * Allocate domain name which gets freed when session struct is deallocated.
+ */
+static int
+build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
+{
+ unsigned int dlen;
+ unsigned int size = 2 * sizeof(struct ntlmssp2_name);
+ char *defdmname = "WORKGROUP";
+ unsigned char *blobptr;
+ struct ntlmssp2_name *attrptr;
+
+ if (!ses->domainName) {
+ ses->domainName = kstrdup(defdmname, GFP_KERNEL);
+ if (!ses->domainName)
+ return -ENOMEM;
+ }
+
+ dlen = strlen(ses->domainName);
+
+ /*
+ * The length of this blob is two times the size of a
+ * structure (av pair) which holds name/size
+ * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) +
+ * unicode length of a netbios domain name
+ */
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.len = size + 2 * dlen;
+ ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL);
+ if (!ses->auth_key.response) {
+ ses->auth_key.len = 0;
+ return -ENOMEM;
+ }
+
+ blobptr = ses->auth_key.response;
+ attrptr = (struct ntlmssp2_name *) blobptr;
+
+ /*
+ * As defined in MS-NTLM 3.3.2, just this av pair field
+ * is sufficient as part of the temp
+ */
+ attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
+ attrptr->length = cpu_to_le16(2 * dlen);
+ blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+ cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
+
+ return 0;
+}
+
+/* Server has provided av pairs/target info in the type 2 challenge
+ * packet and we have plucked it and stored within smb session.
+ * We parse that blob here to find netbios domain name to be used
+ * as part of ntlmv2 authentication (in Target String), if not already
+ * specified on the command line.
+ * If this function returns without any error but without fetching
+ * domain name, authentication may fail against some server but
+ * may not fail against other (those who are not very particular
+ * about target string i.e. for some, just user name might suffice.
+ */
+static int
+find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
+{
+ unsigned int attrsize;
+ unsigned int type;
+ unsigned int onesize = sizeof(struct ntlmssp2_name);
+ unsigned char *blobptr;
+ unsigned char *blobend;
+ struct ntlmssp2_name *attrptr;
+
+ if (!ses->auth_key.len || !ses->auth_key.response)
+ return 0;
+
+ blobptr = ses->auth_key.response;
+ blobend = blobptr + ses->auth_key.len;
+
+ while (blobptr + onesize < blobend) {
+ attrptr = (struct ntlmssp2_name *) blobptr;
+ type = le16_to_cpu(attrptr->type);
+ if (type == NTLMSSP_AV_EOL)
+ break;
+ blobptr += 2; /* advance attr type */
+ attrsize = le16_to_cpu(attrptr->length);
+ blobptr += 2; /* advance attr size */
+ if (blobptr + attrsize > blobend)
+ break;
+ if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
+ if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN)
+ break;
+ if (!ses->domainName) {
+ ses->domainName =
+ kmalloc(attrsize + 1, GFP_KERNEL);
+ if (!ses->domainName)
+ return -ENOMEM;
+ cifs_from_utf16(ses->domainName,
+ (__le16 *)blobptr, attrsize, attrsize,
+ nls_cp, NO_MAP_UNI_RSVD);
+ break;
+ }
+ }
+ blobptr += attrsize; /* advance attr value */
+ }
+
+ return 0;
+}
+
+/* Server has provided av pairs/target info in the type 2 challenge
+ * packet and we have plucked it and stored within smb session.
+ * We parse that blob here to find the server given timestamp
+ * as part of ntlmv2 authentication (or local current time as
+ * default in case of failure)
+ */
+static __le64
+find_timestamp(struct cifs_ses *ses)
+{
+ unsigned int attrsize;
+ unsigned int type;
+ unsigned int onesize = sizeof(struct ntlmssp2_name);
+ unsigned char *blobptr;
+ unsigned char *blobend;
+ struct ntlmssp2_name *attrptr;
+ struct timespec64 ts;
+
+ if (!ses->auth_key.len || !ses->auth_key.response)
+ return 0;
+
+ blobptr = ses->auth_key.response;
+ blobend = blobptr + ses->auth_key.len;
+
+ while (blobptr + onesize < blobend) {
+ attrptr = (struct ntlmssp2_name *) blobptr;
+ type = le16_to_cpu(attrptr->type);
+ if (type == NTLMSSP_AV_EOL)
+ break;
+ blobptr += 2; /* advance attr type */
+ attrsize = le16_to_cpu(attrptr->length);
+ blobptr += 2; /* advance attr size */
+ if (blobptr + attrsize > blobend)
+ break;
+ if (type == NTLMSSP_AV_TIMESTAMP) {
+ if (attrsize == sizeof(u64))
+ return *((__le64 *)blobptr);
+ }
+ blobptr += attrsize; /* advance attr value */
+ }
+
+ ktime_get_real_ts64(&ts);
+ return cpu_to_le64(cifs_UnixTimeToNT(ts));
+}
+
+static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
+ const struct nls_table *nls_cp)
+{
+ int rc = 0;
+ int len;
+ char nt_hash[CIFS_NTHASH_SIZE];
+ __le16 *user;
+ wchar_t *domain;
+ wchar_t *server;
+
+ if (!ses->server->secmech.hmacmd5) {
+ cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
+ return -1;
+ }
+
+ /* calculate md4 hash of password */
+ E_md4hash(ses->password, nt_hash, nls_cp);
+
+ rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm, nt_hash,
+ CIFS_NTHASH_SIZE);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
+ return rc;
+ }
+
+ rc = crypto_shash_init(ses->server->secmech.hmacmd5);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
+ return rc;
+ }
+
+ /* convert ses->user_name to unicode */
+ len = ses->user_name ? strlen(ses->user_name) : 0;
+ user = kmalloc(2 + (len * 2), GFP_KERNEL);
+ if (user == NULL) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ if (len) {
+ len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
+ UniStrupr(user);
+ } else {
+ memset(user, '\0', 2);
+ }
+
+ rc = crypto_shash_update(ses->server->secmech.hmacmd5,
+ (char *)user, 2 * len);
+ kfree(user);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
+ return rc;
+ }
+
+ /* convert ses->domainName to unicode and uppercase */
+ if (ses->domainName) {
+ len = strlen(ses->domainName);
+
+ domain = kmalloc(2 + (len * 2), GFP_KERNEL);
+ if (domain == NULL) {
+ rc = -ENOMEM;
+ return rc;
+ }
+ len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
+ nls_cp);
+ rc =
+ crypto_shash_update(ses->server->secmech.hmacmd5,
+ (char *)domain, 2 * len);
+ kfree(domain);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with domain\n",
+ __func__);
+ return rc;
+ }
+ } else {
+ /* We use ses->ip_addr if no domain name available */
+ len = strlen(ses->ip_addr);
+
+ server = kmalloc(2 + (len * 2), GFP_KERNEL);
+ if (server == NULL) {
+ rc = -ENOMEM;
+ return rc;
+ }
+ len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len,
+ nls_cp);
+ rc =
+ crypto_shash_update(ses->server->secmech.hmacmd5,
+ (char *)server, 2 * len);
+ kfree(server);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with server\n",
+ __func__);
+ return rc;
+ }
+ }
+
+ rc = crypto_shash_final(ses->server->secmech.hmacmd5,
+ ntlmv2_hash);
+ if (rc)
+ cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
+
+ return rc;
+}
+
+static int
+CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
+{
+ int rc;
+ struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
+ (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
+ unsigned int hash_len;
+
+ /* The MD5 hash starts at challenge_key.key */
+ hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
+ offsetof(struct ntlmv2_resp, challenge.key[0]));
+
+ if (!ses->server->secmech.hmacmd5) {
+ cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
+ return -1;
+ }
+
+ rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm,
+ ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
+ __func__);
+ return rc;
+ }
+
+ rc = crypto_shash_init(ses->server->secmech.hmacmd5);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
+ return rc;
+ }
+
+ if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
+ memcpy(ntlmv2->challenge.key,
+ ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
+ else
+ memcpy(ntlmv2->challenge.key,
+ ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
+ rc = crypto_shash_update(ses->server->secmech.hmacmd5,
+ ntlmv2->challenge.key, hash_len);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
+ return rc;
+ }
+
+ /* Note that the MD5 digest over writes anon.challenge_key.key */
+ rc = crypto_shash_final(ses->server->secmech.hmacmd5,
+ ntlmv2->ntlmv2_hash);
+ if (rc)
+ cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
+
+ return rc;
+}
+
+int
+setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
+{
+ int rc;
+ int baselen;
+ unsigned int tilen;
+ struct ntlmv2_resp *ntlmv2;
+ char ntlmv2_hash[16];
+ unsigned char *tiblob = NULL; /* target info blob */
+ __le64 rsp_timestamp;
+
+ if (nls_cp == NULL) {
+ cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
+ if (!ses->domainName) {
+ if (ses->domainAuto) {
+ rc = find_domain_name(ses, nls_cp);
+ if (rc) {
+ cifs_dbg(VFS, "error %d finding domain name\n",
+ rc);
+ goto setup_ntlmv2_rsp_ret;
+ }
+ } else {
+ ses->domainName = kstrdup("", GFP_KERNEL);
+ }
+ }
+ } else {
+ rc = build_avpair_blob(ses, nls_cp);
+ if (rc) {
+ cifs_dbg(VFS, "error %d building av pair blob\n", rc);
+ goto setup_ntlmv2_rsp_ret;
+ }
+ }
+
+ /* Must be within 5 minutes of the server (or in range +/-2h
+ * in case of Mac OS X), so simply carry over server timestamp
+ * (as Windows 7 does)
+ */
+ rsp_timestamp = find_timestamp(ses);
+
+ baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
+ tilen = ses->auth_key.len;
+ tiblob = ses->auth_key.response;
+
+ ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
+ if (!ses->auth_key.response) {
+ rc = -ENOMEM;
+ ses->auth_key.len = 0;
+ goto setup_ntlmv2_rsp_ret;
+ }
+ ses->auth_key.len += baselen;
+
+ ntlmv2 = (struct ntlmv2_resp *)
+ (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
+ ntlmv2->blob_signature = cpu_to_le32(0x00000101);
+ ntlmv2->reserved = 0;
+ ntlmv2->time = rsp_timestamp;
+
+ get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
+ ntlmv2->reserved2 = 0;
+
+ memcpy(ses->auth_key.response + baselen, tiblob, tilen);
+
+ cifs_server_lock(ses->server);
+
+ rc = cifs_alloc_hash("hmac(md5)", &ses->server->secmech.hmacmd5);
+ if (rc) {
+ goto unlock;
+ }
+
+ /* calculate ntlmv2_hash */
+ rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
+ if (rc) {
+ cifs_dbg(VFS, "Could not get v2 hash rc %d\n", rc);
+ goto unlock;
+ }
+
+ /* calculate first part of the client response (CR1) */
+ rc = CalcNTLMv2_response(ses, ntlmv2_hash);
+ if (rc) {
+ cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
+ goto unlock;
+ }
+
+ /* now calculate the session key for NTLMv2 */
+ rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm,
+ ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
+ __func__);
+ goto unlock;
+ }
+
+ rc = crypto_shash_init(ses->server->secmech.hmacmd5);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
+ goto unlock;
+ }
+
+ rc = crypto_shash_update(ses->server->secmech.hmacmd5,
+ ntlmv2->ntlmv2_hash,
+ CIFS_HMAC_MD5_HASH_SIZE);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
+ goto unlock;
+ }
+
+ rc = crypto_shash_final(ses->server->secmech.hmacmd5,
+ ses->auth_key.response);
+ if (rc)
+ cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
+
+unlock:
+ cifs_server_unlock(ses->server);
+setup_ntlmv2_rsp_ret:
+ kfree_sensitive(tiblob);
+
+ return rc;
+}
+
+int
+calc_seckey(struct cifs_ses *ses)
+{
+ unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */
+ struct arc4_ctx *ctx_arc4;
+
+ if (fips_enabled)
+ return -ENODEV;
+
+ get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
+
+ ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
+ if (!ctx_arc4) {
+ cifs_dbg(VFS, "Could not allocate arc4 context\n");
+ return -ENOMEM;
+ }
+
+ cifs_arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE);
+ cifs_arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key,
+ CIFS_CPHTXT_SIZE);
+
+ /* make secondary_key/nonce as session key */
+ memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
+ /* and make len as that of session key only */
+ ses->auth_key.len = CIFS_SESS_KEY_SIZE;
+
+ memzero_explicit(sec_key, CIFS_SESS_KEY_SIZE);
+ kfree_sensitive(ctx_arc4);
+ return 0;
+}
+
+void
+cifs_crypto_secmech_release(struct TCP_Server_Info *server)
+{
+ cifs_free_hash(&server->secmech.aes_cmac);
+ cifs_free_hash(&server->secmech.hmacsha256);
+ cifs_free_hash(&server->secmech.md5);
+ cifs_free_hash(&server->secmech.sha512);
+ cifs_free_hash(&server->secmech.hmacmd5);
+
+ if (server->secmech.enc) {
+ crypto_free_aead(server->secmech.enc);
+ server->secmech.enc = NULL;
+ }
+
+ if (server->secmech.dec) {
+ crypto_free_aead(server->secmech.dec);
+ server->secmech.dec = NULL;
+ }
+}
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
new file mode 100644
index 000000000000..078df1e2dd18
--- /dev/null
+++ b/fs/smb/client/cifsfs.c
@@ -0,0 +1,1857 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Common Internet FileSystem (CIFS) client
+ *
+ */
+
+/* Note that BB means BUGBUG (ie something to fix eventually) */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/seq_file.h>
+#include <linux/vfs.h>
+#include <linux/mempool.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/namei.h>
+#include <linux/random.h>
+#include <linux/uuid.h>
+#include <linux/xattr.h>
+#include <uapi/linux/magic.h>
+#include <net/ipv6.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#define DECLARE_GLOBALS_HERE
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include <linux/mm.h>
+#include <linux/key-type.h>
+#include "cifs_spnego.h"
+#include "fscache.h"
+#ifdef CONFIG_CIFS_DFS_UPCALL
+#include "dfs_cache.h"
+#endif
+#ifdef CONFIG_CIFS_SWN_UPCALL
+#include "netlink.h"
+#endif
+#include "fs_context.h"
+#include "cached_dir.h"
+
+/*
+ * DOS dates from 1980/1/1 through 2107/12/31
+ * Protocol specifications indicate the range should be to 119, which
+ * limits maximum year to 2099. But this range has not been checked.
+ */
+#define SMB_DATE_MAX (127<<9 | 12<<5 | 31)
+#define SMB_DATE_MIN (0<<9 | 1<<5 | 1)
+#define SMB_TIME_MAX (23<<11 | 59<<5 | 29)
+
+int cifsFYI = 0;
+bool traceSMB;
+bool enable_oplocks = true;
+bool linuxExtEnabled = true;
+bool lookupCacheEnabled = true;
+bool disable_legacy_dialects; /* false by default */
+bool enable_gcm_256 = true;
+bool require_gcm_256; /* false by default */
+bool enable_negotiate_signing; /* false by default */
+unsigned int global_secflags = CIFSSEC_DEF;
+/* unsigned int ntlmv2_support = 0; */
+unsigned int sign_CIFS_PDUs = 1;
+
+/*
+ * Global transaction id (XID) information
+ */
+unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
+unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
+unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
+spinlock_t GlobalMid_Lock; /* protects above & list operations on midQ entries */
+
+/*
+ * Global counters, updated atomically
+ */
+atomic_t sesInfoAllocCount;
+atomic_t tconInfoAllocCount;
+atomic_t tcpSesNextId;
+atomic_t tcpSesAllocCount;
+atomic_t tcpSesReconnectCount;
+atomic_t tconInfoReconnectCount;
+
+atomic_t mid_count;
+atomic_t buf_alloc_count;
+atomic_t small_buf_alloc_count;
+#ifdef CONFIG_CIFS_STATS2
+atomic_t total_buf_alloc_count;
+atomic_t total_small_buf_alloc_count;
+#endif/* STATS2 */
+struct list_head cifs_tcp_ses_list;
+spinlock_t cifs_tcp_ses_lock;
+static const struct super_operations cifs_super_ops;
+unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
+module_param(CIFSMaxBufSize, uint, 0444);
+MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header) "
+ "for CIFS requests. "
+ "Default: 16384 Range: 8192 to 130048");
+unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
+module_param(cifs_min_rcv, uint, 0444);
+MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
+ "1 to 64");
+unsigned int cifs_min_small = 30;
+module_param(cifs_min_small, uint, 0444);
+MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
+ "Range: 2 to 256");
+unsigned int cifs_max_pending = CIFS_MAX_REQ;
+module_param(cifs_max_pending, uint, 0444);
+MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server for "
+ "CIFS/SMB1 dialect (N/A for SMB3) "
+ "Default: 32767 Range: 2 to 32767.");
+#ifdef CONFIG_CIFS_STATS2
+unsigned int slow_rsp_threshold = 1;
+module_param(slow_rsp_threshold, uint, 0644);
+MODULE_PARM_DESC(slow_rsp_threshold, "Amount of time (in seconds) to wait "
+ "before logging that a response is delayed. "
+ "Default: 1 (if set to 0 disables msg).");
+#endif /* STATS2 */
+
+module_param(enable_oplocks, bool, 0644);
+MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1");
+
+module_param(enable_gcm_256, bool, 0644);
+MODULE_PARM_DESC(enable_gcm_256, "Enable requesting strongest (256 bit) GCM encryption. Default: n/N/0");
+
+module_param(require_gcm_256, bool, 0644);
+MODULE_PARM_DESC(require_gcm_256, "Require strongest (256 bit) GCM encryption. Default: n/N/0");
+
+module_param(enable_negotiate_signing, bool, 0644);
+MODULE_PARM_DESC(enable_negotiate_signing, "Enable negotiating packet signing algorithm with server. Default: n/N/0");
+
+module_param(disable_legacy_dialects, bool, 0644);
+MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be "
+ "helpful to restrict the ability to "
+ "override the default dialects (SMB2.1, "
+ "SMB3 and SMB3.02) on mount with old "
+ "dialects (CIFS/SMB1 and SMB2) since "
+ "vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker"
+ " and less secure. Default: n/N/0");
+
+extern mempool_t *cifs_sm_req_poolp;
+extern mempool_t *cifs_req_poolp;
+extern mempool_t *cifs_mid_poolp;
+
+struct workqueue_struct *cifsiod_wq;
+struct workqueue_struct *decrypt_wq;
+struct workqueue_struct *fileinfo_put_wq;
+struct workqueue_struct *cifsoplockd_wq;
+struct workqueue_struct *deferredclose_wq;
+__u32 cifs_lock_secret;
+
+/*
+ * Bumps refcount for cifs super block.
+ * Note that it should be only called if a referece to VFS super block is
+ * already held, e.g. in open-type syscalls context. Otherwise it can race with
+ * atomic_dec_and_test in deactivate_locked_super.
+ */
+void
+cifs_sb_active(struct super_block *sb)
+{
+ struct cifs_sb_info *server = CIFS_SB(sb);
+
+ if (atomic_inc_return(&server->active) == 1)
+ atomic_inc(&sb->s_active);
+}
+
+void
+cifs_sb_deactive(struct super_block *sb)
+{
+ struct cifs_sb_info *server = CIFS_SB(sb);
+
+ if (atomic_dec_and_test(&server->active))
+ deactivate_super(sb);
+}
+
+static int
+cifs_read_super(struct super_block *sb)
+{
+ struct inode *inode;
+ struct cifs_sb_info *cifs_sb;
+ struct cifs_tcon *tcon;
+ struct timespec64 ts;
+ int rc = 0;
+
+ cifs_sb = CIFS_SB(sb);
+ tcon = cifs_sb_master_tcon(cifs_sb);
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
+ sb->s_flags |= SB_POSIXACL;
+
+ if (tcon->snapshot_time)
+ sb->s_flags |= SB_RDONLY;
+
+ if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files)
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ else
+ sb->s_maxbytes = MAX_NON_LFS;
+
+ /*
+ * Some very old servers like DOS and OS/2 used 2 second granularity
+ * (while all current servers use 100ns granularity - see MS-DTYP)
+ * but 1 second is the maximum allowed granularity for the VFS
+ * so for old servers set time granularity to 1 second while for
+ * everything else (current servers) set it to 100ns.
+ */
+ if ((tcon->ses->server->vals->protocol_id == SMB10_PROT_ID) &&
+ ((tcon->ses->capabilities &
+ tcon->ses->server->vals->cap_nt_find) == 0) &&
+ !tcon->unix_ext) {
+ sb->s_time_gran = 1000000000; /* 1 second is max allowed gran */
+ ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0);
+ sb->s_time_min = ts.tv_sec;
+ ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX),
+ cpu_to_le16(SMB_TIME_MAX), 0);
+ sb->s_time_max = ts.tv_sec;
+ } else {
+ /*
+ * Almost every server, including all SMB2+, uses DCE TIME
+ * ie 100 nanosecond units, since 1601. See MS-DTYP and MS-FSCC
+ */
+ sb->s_time_gran = 100;
+ ts = cifs_NTtimeToUnix(0);
+ sb->s_time_min = ts.tv_sec;
+ ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX));
+ sb->s_time_max = ts.tv_sec;
+ }
+
+ sb->s_magic = CIFS_SUPER_MAGIC;
+ sb->s_op = &cifs_super_ops;
+ sb->s_xattr = cifs_xattr_handlers;
+ rc = super_setup_bdi(sb);
+ if (rc)
+ goto out_no_root;
+ /* tune readahead according to rsize if readahead size not set on mount */
+ if (cifs_sb->ctx->rsize == 0)
+ cifs_sb->ctx->rsize =
+ tcon->ses->server->ops->negotiate_rsize(tcon, cifs_sb->ctx);
+ if (cifs_sb->ctx->rasize)
+ sb->s_bdi->ra_pages = cifs_sb->ctx->rasize / PAGE_SIZE;
+ else
+ sb->s_bdi->ra_pages = cifs_sb->ctx->rsize / PAGE_SIZE;
+
+ sb->s_blocksize = CIFS_MAX_MSGSIZE;
+ sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
+ inode = cifs_root_iget(sb);
+
+ if (IS_ERR(inode)) {
+ rc = PTR_ERR(inode);
+ goto out_no_root;
+ }
+
+ if (tcon->nocase)
+ sb->s_d_op = &cifs_ci_dentry_ops;
+ else
+ sb->s_d_op = &cifs_dentry_ops;
+
+ sb->s_root = d_make_root(inode);
+ if (!sb->s_root) {
+ rc = -ENOMEM;
+ goto out_no_root;
+ }
+
+#ifdef CONFIG_CIFS_NFSD_EXPORT
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+ cifs_dbg(FYI, "export ops supported\n");
+ sb->s_export_op = &cifs_export_ops;
+ }
+#endif /* CONFIG_CIFS_NFSD_EXPORT */
+
+ return 0;
+
+out_no_root:
+ cifs_dbg(VFS, "%s: get root inode failed\n", __func__);
+ return rc;
+}
+
+static void cifs_kill_sb(struct super_block *sb)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+
+ /*
+ * We ned to release all dentries for the cached directories
+ * before we kill the sb.
+ */
+ if (cifs_sb->root) {
+ close_all_cached_dirs(cifs_sb);
+
+ /* finally release root dentry */
+ dput(cifs_sb->root);
+ cifs_sb->root = NULL;
+ }
+
+ kill_anon_super(sb);
+ cifs_umount(cifs_sb);
+}
+
+static int
+cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+ struct super_block *sb = dentry->d_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ unsigned int xid;
+ int rc = 0;
+
+ xid = get_xid();
+
+ if (le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength) > 0)
+ buf->f_namelen =
+ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength);
+ else
+ buf->f_namelen = PATH_MAX;
+
+ buf->f_fsid.val[0] = tcon->vol_serial_number;
+ /* are using part of create time for more randomness, see man statfs */
+ buf->f_fsid.val[1] = (int)le64_to_cpu(tcon->vol_create_time);
+
+ buf->f_files = 0; /* undefined */
+ buf->f_ffree = 0; /* unlimited */
+
+ if (server->ops->queryfs)
+ rc = server->ops->queryfs(xid, tcon, cifs_sb, buf);
+
+ free_xid(xid);
+ return rc;
+}
+
+static long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ struct TCP_Server_Info *server = tcon->ses->server;
+
+ if (server->ops->fallocate)
+ return server->ops->fallocate(file, tcon, mode, off, len);
+
+ return -EOPNOTSUPP;
+}
+
+static int cifs_permission(struct user_namespace *mnt_userns,
+ struct inode *inode, int mask)
+{
+ struct cifs_sb_info *cifs_sb;
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
+ if ((mask & MAY_EXEC) && !execute_ok(inode))
+ return -EACCES;
+ else
+ return 0;
+ } else /* file mode might have been restricted at mount time
+ on the client (above and beyond ACL on servers) for
+ servers which do not support setting and viewing mode bits,
+ so allowing client to check permissions is useful */
+ return generic_permission(&init_user_ns, inode, mask);
+}
+
+static struct kmem_cache *cifs_inode_cachep;
+static struct kmem_cache *cifs_req_cachep;
+static struct kmem_cache *cifs_mid_cachep;
+static struct kmem_cache *cifs_sm_req_cachep;
+mempool_t *cifs_sm_req_poolp;
+mempool_t *cifs_req_poolp;
+mempool_t *cifs_mid_poolp;
+
+static struct inode *
+cifs_alloc_inode(struct super_block *sb)
+{
+ struct cifsInodeInfo *cifs_inode;
+ cifs_inode = alloc_inode_sb(sb, cifs_inode_cachep, GFP_KERNEL);
+ if (!cifs_inode)
+ return NULL;
+ cifs_inode->cifsAttrs = 0x20; /* default */
+ cifs_inode->time = 0;
+ /*
+ * Until the file is open and we have gotten oplock info back from the
+ * server, can not assume caching of file data or metadata.
+ */
+ cifs_set_oplock_level(cifs_inode, 0);
+ cifs_inode->flags = 0;
+ spin_lock_init(&cifs_inode->writers_lock);
+ cifs_inode->writers = 0;
+ cifs_inode->netfs.inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
+ cifs_inode->server_eof = 0;
+ cifs_inode->uniqueid = 0;
+ cifs_inode->createtime = 0;
+ cifs_inode->epoch = 0;
+ spin_lock_init(&cifs_inode->open_file_lock);
+ generate_random_uuid(cifs_inode->lease_key);
+ cifs_inode->symlink_target = NULL;
+
+ /*
+ * Can not set i_flags here - they get immediately overwritten to zero
+ * by the VFS.
+ */
+ /* cifs_inode->netfs.inode.i_flags = S_NOATIME | S_NOCMTIME; */
+ INIT_LIST_HEAD(&cifs_inode->openFileList);
+ INIT_LIST_HEAD(&cifs_inode->llist);
+ INIT_LIST_HEAD(&cifs_inode->deferred_closes);
+ spin_lock_init(&cifs_inode->deferred_lock);
+ return &cifs_inode->netfs.inode;
+}
+
+static void
+cifs_free_inode(struct inode *inode)
+{
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+
+ if (S_ISLNK(inode->i_mode))
+ kfree(cinode->symlink_target);
+ kmem_cache_free(cifs_inode_cachep, cinode);
+}
+
+static void
+cifs_evict_inode(struct inode *inode)
+{
+ truncate_inode_pages_final(&inode->i_data);
+ if (inode->i_state & I_PINNING_FSCACHE_WB)
+ cifs_fscache_unuse_inode_cookie(inode, true);
+ cifs_fscache_release_inode_cookie(inode);
+ clear_inode(inode);
+}
+
+static void
+cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
+{
+ struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
+ struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
+
+ seq_puts(s, ",addr=");
+
+ switch (server->dstaddr.ss_family) {
+ case AF_INET:
+ seq_printf(s, "%pI4", &sa->sin_addr.s_addr);
+ break;
+ case AF_INET6:
+ seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr);
+ if (sa6->sin6_scope_id)
+ seq_printf(s, "%%%u", sa6->sin6_scope_id);
+ break;
+ default:
+ seq_puts(s, "(unknown)");
+ }
+ if (server->rdma)
+ seq_puts(s, ",rdma");
+}
+
+static void
+cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
+{
+ if (ses->sectype == Unspecified) {
+ if (ses->user_name == NULL)
+ seq_puts(s, ",sec=none");
+ return;
+ }
+
+ seq_puts(s, ",sec=");
+
+ switch (ses->sectype) {
+ case NTLMv2:
+ seq_puts(s, "ntlmv2");
+ break;
+ case Kerberos:
+ seq_puts(s, "krb5");
+ break;
+ case RawNTLMSSP:
+ seq_puts(s, "ntlmssp");
+ break;
+ default:
+ /* shouldn't ever happen */
+ seq_puts(s, "unknown");
+ break;
+ }
+
+ if (ses->sign)
+ seq_puts(s, "i");
+
+ if (ses->sectype == Kerberos)
+ seq_printf(s, ",cruid=%u",
+ from_kuid_munged(&init_user_ns, ses->cred_uid));
+}
+
+static void
+cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
+{
+ seq_puts(s, ",cache=");
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
+ seq_puts(s, "strict");
+ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ seq_puts(s, "none");
+ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
+ seq_puts(s, "singleclient"); /* assume only one client access */
+ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)
+ seq_puts(s, "ro"); /* read only caching assumed */
+ else
+ seq_puts(s, "loose");
+}
+
+/*
+ * cifs_show_devname() is used so we show the mount device name with correct
+ * format (e.g. forward slashes vs. back slashes) in /proc/mounts
+ */
+static int cifs_show_devname(struct seq_file *m, struct dentry *root)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
+ char *devname = kstrdup(cifs_sb->ctx->source, GFP_KERNEL);
+
+ if (devname == NULL)
+ seq_puts(m, "none");
+ else {
+ convert_delimiter(devname, '/');
+ /* escape all spaces in share names */
+ seq_escape(m, devname, " \t");
+ kfree(devname);
+ }
+ return 0;
+}
+
+/*
+ * cifs_show_options() is for displaying mount options in /proc/mounts.
+ * Not all settable options are displayed but most of the important
+ * ones are.
+ */
+static int
+cifs_show_options(struct seq_file *s, struct dentry *root)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ struct sockaddr *srcaddr;
+ srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
+
+ seq_show_option(s, "vers", tcon->ses->server->vals->version_string);
+ cifs_show_security(s, tcon->ses);
+ cifs_show_cache_flavor(s, cifs_sb);
+
+ if (tcon->no_lease)
+ seq_puts(s, ",nolease");
+ if (cifs_sb->ctx->multiuser)
+ seq_puts(s, ",multiuser");
+ else if (tcon->ses->user_name)
+ seq_show_option(s, "username", tcon->ses->user_name);
+
+ if (tcon->ses->domainName && tcon->ses->domainName[0] != 0)
+ seq_show_option(s, "domain", tcon->ses->domainName);
+
+ if (srcaddr->sa_family != AF_UNSPEC) {
+ struct sockaddr_in *saddr4;
+ struct sockaddr_in6 *saddr6;
+ saddr4 = (struct sockaddr_in *)srcaddr;
+ saddr6 = (struct sockaddr_in6 *)srcaddr;
+ if (srcaddr->sa_family == AF_INET6)
+ seq_printf(s, ",srcaddr=%pI6c",
+ &saddr6->sin6_addr);
+ else if (srcaddr->sa_family == AF_INET)
+ seq_printf(s, ",srcaddr=%pI4",
+ &saddr4->sin_addr.s_addr);
+ else
+ seq_printf(s, ",srcaddr=BAD-AF:%i",
+ (int)(srcaddr->sa_family));
+ }
+
+ seq_printf(s, ",uid=%u",
+ from_kuid_munged(&init_user_ns, cifs_sb->ctx->linux_uid));
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
+ seq_puts(s, ",forceuid");
+ else
+ seq_puts(s, ",noforceuid");
+
+ seq_printf(s, ",gid=%u",
+ from_kgid_munged(&init_user_ns, cifs_sb->ctx->linux_gid));
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
+ seq_puts(s, ",forcegid");
+ else
+ seq_puts(s, ",noforcegid");
+
+ cifs_show_address(s, tcon->ses->server);
+
+ if (!tcon->unix_ext)
+ seq_printf(s, ",file_mode=0%ho,dir_mode=0%ho",
+ cifs_sb->ctx->file_mode,
+ cifs_sb->ctx->dir_mode);
+ if (cifs_sb->ctx->iocharset)
+ seq_printf(s, ",iocharset=%s", cifs_sb->ctx->iocharset);
+ if (tcon->seal)
+ seq_puts(s, ",seal");
+ else if (tcon->ses->server->ignore_signature)
+ seq_puts(s, ",signloosely");
+ if (tcon->nocase)
+ seq_puts(s, ",nocase");
+ if (tcon->nodelete)
+ seq_puts(s, ",nodelete");
+ if (cifs_sb->ctx->no_sparse)
+ seq_puts(s, ",nosparse");
+ if (tcon->local_lease)
+ seq_puts(s, ",locallease");
+ if (tcon->retry)
+ seq_puts(s, ",hard");
+ else
+ seq_puts(s, ",soft");
+ if (tcon->use_persistent)
+ seq_puts(s, ",persistenthandles");
+ else if (tcon->use_resilient)
+ seq_puts(s, ",resilienthandles");
+ if (tcon->posix_extensions)
+ seq_puts(s, ",posix");
+ else if (tcon->unix_ext)
+ seq_puts(s, ",unix");
+ else
+ seq_puts(s, ",nounix");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
+ seq_puts(s, ",nodfs");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+ seq_puts(s, ",posixpaths");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
+ seq_puts(s, ",setuids");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
+ seq_puts(s, ",idsfromsid");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+ seq_puts(s, ",serverino");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+ seq_puts(s, ",rwpidforward");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL)
+ seq_puts(s, ",forcemand");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ seq_puts(s, ",nouser_xattr");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
+ seq_puts(s, ",mapchars");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
+ seq_puts(s, ",mapposix");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
+ seq_puts(s, ",sfu");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+ seq_puts(s, ",nobrl");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_HANDLE_CACHE)
+ seq_puts(s, ",nohandlecache");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
+ seq_puts(s, ",modefromsid");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
+ seq_puts(s, ",cifsacl");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
+ seq_puts(s, ",dynperm");
+ if (root->d_sb->s_flags & SB_POSIXACL)
+ seq_puts(s, ",acl");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+ seq_puts(s, ",mfsymlinks");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
+ seq_puts(s, ",fsc");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)
+ seq_puts(s, ",nostrictsync");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
+ seq_puts(s, ",noperm");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
+ seq_printf(s, ",backupuid=%u",
+ from_kuid_munged(&init_user_ns,
+ cifs_sb->ctx->backupuid));
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID)
+ seq_printf(s, ",backupgid=%u",
+ from_kgid_munged(&init_user_ns,
+ cifs_sb->ctx->backupgid));
+
+ seq_printf(s, ",rsize=%u", cifs_sb->ctx->rsize);
+ seq_printf(s, ",wsize=%u", cifs_sb->ctx->wsize);
+ seq_printf(s, ",bsize=%u", cifs_sb->ctx->bsize);
+ if (cifs_sb->ctx->rasize)
+ seq_printf(s, ",rasize=%u", cifs_sb->ctx->rasize);
+ if (tcon->ses->server->min_offload)
+ seq_printf(s, ",esize=%u", tcon->ses->server->min_offload);
+ seq_printf(s, ",echo_interval=%lu",
+ tcon->ses->server->echo_interval / HZ);
+
+ /* Only display the following if overridden on mount */
+ if (tcon->ses->server->max_credits != SMB2_MAX_CREDITS_AVAILABLE)
+ seq_printf(s, ",max_credits=%u", tcon->ses->server->max_credits);
+ if (tcon->ses->server->tcp_nodelay)
+ seq_puts(s, ",tcpnodelay");
+ if (tcon->ses->server->noautotune)
+ seq_puts(s, ",noautotune");
+ if (tcon->ses->server->noblocksnd)
+ seq_puts(s, ",noblocksend");
+
+ if (tcon->snapshot_time)
+ seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
+ if (tcon->handle_timeout)
+ seq_printf(s, ",handletimeout=%u", tcon->handle_timeout);
+
+ /*
+ * Display file and directory attribute timeout in seconds.
+ * If file and directory attribute timeout the same then actimeo
+ * was likely specified on mount
+ */
+ if (cifs_sb->ctx->acdirmax == cifs_sb->ctx->acregmax)
+ seq_printf(s, ",actimeo=%lu", cifs_sb->ctx->acregmax / HZ);
+ else {
+ seq_printf(s, ",acdirmax=%lu", cifs_sb->ctx->acdirmax / HZ);
+ seq_printf(s, ",acregmax=%lu", cifs_sb->ctx->acregmax / HZ);
+ }
+ seq_printf(s, ",closetimeo=%lu", cifs_sb->ctx->closetimeo / HZ);
+
+ if (tcon->ses->chan_max > 1)
+ seq_printf(s, ",multichannel,max_channels=%zu",
+ tcon->ses->chan_max);
+
+ if (tcon->use_witness)
+ seq_puts(s, ",witness");
+
+ return 0;
+}
+
+static void cifs_umount_begin(struct super_block *sb)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_tcon *tcon;
+
+ if (cifs_sb == NULL)
+ return;
+
+ tcon = cifs_sb_master_tcon(cifs_sb);
+
+ spin_lock(&cifs_tcp_ses_lock);
+ spin_lock(&tcon->tc_lock);
+ if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
+ /* we have other mounts to same share or we have
+ already tried to umount this and woken up
+ all waiting network requests, nothing to do */
+ spin_unlock(&tcon->tc_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ return;
+ }
+ /*
+ * can not set tcon->status to TID_EXITING yet since we don't know if umount -f will
+ * fail later (e.g. due to open files). TID_EXITING will be set just before tdis req sent
+ */
+ spin_unlock(&tcon->tc_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ cifs_close_all_deferred_files(tcon);
+ /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
+ /* cancel_notify_requests(tcon); */
+ if (tcon->ses && tcon->ses->server) {
+ cifs_dbg(FYI, "wake up tasks now - umount begin not complete\n");
+ wake_up_all(&tcon->ses->server->request_q);
+ wake_up_all(&tcon->ses->server->response_q);
+ msleep(1); /* yield */
+ /* we have to kick the requests once more */
+ wake_up_all(&tcon->ses->server->response_q);
+ msleep(1);
+ }
+
+ return;
+}
+
+static int cifs_freeze(struct super_block *sb)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_tcon *tcon;
+
+ if (cifs_sb == NULL)
+ return 0;
+
+ tcon = cifs_sb_master_tcon(cifs_sb);
+
+ cifs_close_all_deferred_files(tcon);
+ return 0;
+}
+
+#ifdef CONFIG_CIFS_STATS2
+static int cifs_show_stats(struct seq_file *s, struct dentry *root)
+{
+ /* BB FIXME */
+ return 0;
+}
+#endif
+
+static int cifs_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+ fscache_unpin_writeback(wbc, cifs_inode_cookie(inode));
+ return 0;
+}
+
+static int cifs_drop_inode(struct inode *inode)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+ /* no serverino => unconditional eviction */
+ return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ||
+ generic_drop_inode(inode);
+}
+
+static const struct super_operations cifs_super_ops = {
+ .statfs = cifs_statfs,
+ .alloc_inode = cifs_alloc_inode,
+ .write_inode = cifs_write_inode,
+ .free_inode = cifs_free_inode,
+ .drop_inode = cifs_drop_inode,
+ .evict_inode = cifs_evict_inode,
+/* .show_path = cifs_show_path, */ /* Would we ever need show path? */
+ .show_devname = cifs_show_devname,
+/* .delete_inode = cifs_delete_inode, */ /* Do not need above
+ function unless later we add lazy close of inodes or unless the
+ kernel forgets to call us with the same number of releases (closes)
+ as opens */
+ .show_options = cifs_show_options,
+ .umount_begin = cifs_umount_begin,
+ .freeze_fs = cifs_freeze,
+#ifdef CONFIG_CIFS_STATS2
+ .show_stats = cifs_show_stats,
+#endif
+};
+
+/*
+ * Get root dentry from superblock according to prefix path mount option.
+ * Return dentry with refcount + 1 on success and NULL otherwise.
+ */
+static struct dentry *
+cifs_get_root(struct smb3_fs_context *ctx, struct super_block *sb)
+{
+ struct dentry *dentry;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ char *full_path = NULL;
+ char *s, *p;
+ char sep;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
+ return dget(sb->s_root);
+
+ full_path = cifs_build_path_to_root(ctx, cifs_sb,
+ cifs_sb_master_tcon(cifs_sb), 0);
+ if (full_path == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ cifs_dbg(FYI, "Get root dentry for %s\n", full_path);
+
+ sep = CIFS_DIR_SEP(cifs_sb);
+ dentry = dget(sb->s_root);
+ s = full_path;
+
+ do {
+ struct inode *dir = d_inode(dentry);
+ struct dentry *child;
+
+ if (!S_ISDIR(dir->i_mode)) {
+ dput(dentry);
+ dentry = ERR_PTR(-ENOTDIR);
+ break;
+ }
+
+ /* skip separators */
+ while (*s == sep)
+ s++;
+ if (!*s)
+ break;
+ p = s++;
+ /* next separator */
+ while (*s && *s != sep)
+ s++;
+
+ child = lookup_positive_unlocked(p, dentry, s - p);
+ dput(dentry);
+ dentry = child;
+ } while (!IS_ERR(dentry));
+ kfree(full_path);
+ return dentry;
+}
+
+static int cifs_set_super(struct super_block *sb, void *data)
+{
+ struct cifs_mnt_data *mnt_data = data;
+ sb->s_fs_info = mnt_data->cifs_sb;
+ return set_anon_super(sb, NULL);
+}
+
+struct dentry *
+cifs_smb3_do_mount(struct file_system_type *fs_type,
+ int flags, struct smb3_fs_context *old_ctx)
+{
+ int rc;
+ struct super_block *sb = NULL;
+ struct cifs_sb_info *cifs_sb = NULL;
+ struct cifs_mnt_data mnt_data;
+ struct dentry *root;
+
+ /*
+ * Prints in Kernel / CIFS log the attempted mount operation
+ * If CIFS_DEBUG && cifs_FYI
+ */
+ if (cifsFYI)
+ cifs_dbg(FYI, "Devname: %s flags: %d\n", old_ctx->UNC, flags);
+ else
+ cifs_info("Attempting to mount %s\n", old_ctx->UNC);
+
+ cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
+ if (cifs_sb == NULL) {
+ root = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ cifs_sb->ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
+ if (!cifs_sb->ctx) {
+ root = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+ rc = smb3_fs_context_dup(cifs_sb->ctx, old_ctx);
+ if (rc) {
+ root = ERR_PTR(rc);
+ goto out;
+ }
+
+ rc = cifs_setup_volume_info(cifs_sb->ctx, NULL, NULL);
+ if (rc) {
+ root = ERR_PTR(rc);
+ goto out;
+ }
+
+ rc = cifs_setup_cifs_sb(cifs_sb);
+ if (rc) {
+ root = ERR_PTR(rc);
+ goto out;
+ }
+
+ rc = cifs_mount(cifs_sb, cifs_sb->ctx);
+ if (rc) {
+ if (!(flags & SB_SILENT))
+ cifs_dbg(VFS, "cifs_mount failed w/return code = %d\n",
+ rc);
+ root = ERR_PTR(rc);
+ goto out;
+ }
+
+ mnt_data.ctx = cifs_sb->ctx;
+ mnt_data.cifs_sb = cifs_sb;
+ mnt_data.flags = flags;
+
+ /* BB should we make this contingent on mount parm? */
+ flags |= SB_NODIRATIME | SB_NOATIME;
+
+ sb = sget(fs_type, cifs_match_super, cifs_set_super, flags, &mnt_data);
+ if (IS_ERR(sb)) {
+ root = ERR_CAST(sb);
+ cifs_umount(cifs_sb);
+ cifs_sb = NULL;
+ goto out;
+ }
+
+ if (sb->s_root) {
+ cifs_dbg(FYI, "Use existing superblock\n");
+ cifs_umount(cifs_sb);
+ cifs_sb = NULL;
+ } else {
+ rc = cifs_read_super(sb);
+ if (rc) {
+ root = ERR_PTR(rc);
+ goto out_super;
+ }
+
+ sb->s_flags |= SB_ACTIVE;
+ }
+
+ root = cifs_get_root(cifs_sb ? cifs_sb->ctx : old_ctx, sb);
+ if (IS_ERR(root))
+ goto out_super;
+
+ if (cifs_sb)
+ cifs_sb->root = dget(root);
+
+ cifs_dbg(FYI, "dentry root is: %p\n", root);
+ return root;
+
+out_super:
+ deactivate_locked_super(sb);
+ return root;
+out:
+ if (cifs_sb) {
+ if (!sb || IS_ERR(sb)) { /* otherwise kill_sb will handle */
+ kfree(cifs_sb->prepath);
+ smb3_cleanup_fs_context(cifs_sb->ctx);
+ kfree(cifs_sb);
+ }
+ }
+ return root;
+}
+
+
+static ssize_t
+cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+ ssize_t rc;
+ struct inode *inode = file_inode(iocb->ki_filp);
+
+ if (iocb->ki_flags & IOCB_DIRECT)
+ return cifs_user_readv(iocb, iter);
+
+ rc = cifs_revalidate_mapping(inode);
+ if (rc)
+ return rc;
+
+ return generic_file_read_iter(iocb, iter);
+}
+
+static ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+ struct inode *inode = file_inode(iocb->ki_filp);
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ ssize_t written;
+ int rc;
+
+ if (iocb->ki_filp->f_flags & O_DIRECT) {
+ written = cifs_user_writev(iocb, from);
+ if (written > 0 && CIFS_CACHE_READ(cinode)) {
+ cifs_zap_mapping(inode);
+ cifs_dbg(FYI,
+ "Set no oplock for inode=%p after a write operation\n",
+ inode);
+ cinode->oplock = 0;
+ }
+ return written;
+ }
+
+ written = cifs_get_writer(cinode);
+ if (written)
+ return written;
+
+ written = generic_file_write_iter(iocb, from);
+
+ if (CIFS_CACHE_WRITE(CIFS_I(inode)))
+ goto out;
+
+ rc = filemap_fdatawrite(inode->i_mapping);
+ if (rc)
+ cifs_dbg(FYI, "cifs_file_write_iter: %d rc on %p inode\n",
+ rc, inode);
+
+out:
+ cifs_put_writer(cinode);
+ return written;
+}
+
+static loff_t cifs_llseek(struct file *file, loff_t offset, int whence)
+{
+ struct cifsFileInfo *cfile = file->private_data;
+ struct cifs_tcon *tcon;
+
+ /*
+ * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate
+ * the cached file length
+ */
+ if (whence != SEEK_SET && whence != SEEK_CUR) {
+ int rc;
+ struct inode *inode = file_inode(file);
+
+ /*
+ * We need to be sure that all dirty pages are written and the
+ * server has the newest file length.
+ */
+ if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
+ inode->i_mapping->nrpages != 0) {
+ rc = filemap_fdatawait(inode->i_mapping);
+ if (rc) {
+ mapping_set_error(inode->i_mapping, rc);
+ return rc;
+ }
+ }
+ /*
+ * Some applications poll for the file length in this strange
+ * way so we must seek to end on non-oplocked files by
+ * setting the revalidate time to zero.
+ */
+ CIFS_I(inode)->time = 0;
+
+ rc = cifs_revalidate_file_attr(file);
+ if (rc < 0)
+ return (loff_t)rc;
+ }
+ if (cfile && cfile->tlink) {
+ tcon = tlink_tcon(cfile->tlink);
+ if (tcon->ses->server->ops->llseek)
+ return tcon->ses->server->ops->llseek(file, tcon,
+ offset, whence);
+ }
+ return generic_file_llseek(file, offset, whence);
+}
+
+static int
+cifs_setlease(struct file *file, long arg, struct file_lock **lease, void **priv)
+{
+ /*
+ * Note that this is called by vfs setlease with i_lock held to
+ * protect *lease from going away.
+ */
+ struct inode *inode = file_inode(file);
+ struct cifsFileInfo *cfile = file->private_data;
+
+ if (!(S_ISREG(inode->i_mode)))
+ return -EINVAL;
+
+ /* Check if file is oplocked if this is request for new lease */
+ if (arg == F_UNLCK ||
+ ((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
+ ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode))))
+ return generic_setlease(file, arg, lease, priv);
+ else if (tlink_tcon(cfile->tlink)->local_lease &&
+ !CIFS_CACHE_READ(CIFS_I(inode)))
+ /*
+ * If the server claims to support oplock on this file, then we
+ * still need to check oplock even if the local_lease mount
+ * option is set, but there are servers which do not support
+ * oplock for which this mount option may be useful if the user
+ * knows that the file won't be changed on the server by anyone
+ * else.
+ */
+ return generic_setlease(file, arg, lease, priv);
+ else
+ return -EAGAIN;
+}
+
+struct file_system_type cifs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "cifs",
+ .init_fs_context = smb3_init_fs_context,
+ .parameters = smb3_fs_parameters,
+ .kill_sb = cifs_kill_sb,
+ .fs_flags = FS_RENAME_DOES_D_MOVE,
+};
+MODULE_ALIAS_FS("cifs");
+
+struct file_system_type smb3_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "smb3",
+ .init_fs_context = smb3_init_fs_context,
+ .parameters = smb3_fs_parameters,
+ .kill_sb = cifs_kill_sb,
+ .fs_flags = FS_RENAME_DOES_D_MOVE,
+};
+MODULE_ALIAS_FS("smb3");
+MODULE_ALIAS("smb3");
+
+const struct inode_operations cifs_dir_inode_ops = {
+ .create = cifs_create,
+ .atomic_open = cifs_atomic_open,
+ .lookup = cifs_lookup,
+ .getattr = cifs_getattr,
+ .unlink = cifs_unlink,
+ .link = cifs_hardlink,
+ .mkdir = cifs_mkdir,
+ .rmdir = cifs_rmdir,
+ .rename = cifs_rename2,
+ .permission = cifs_permission,
+ .setattr = cifs_setattr,
+ .symlink = cifs_symlink,
+ .mknod = cifs_mknod,
+ .listxattr = cifs_listxattr,
+};
+
+const struct inode_operations cifs_file_inode_ops = {
+ .setattr = cifs_setattr,
+ .getattr = cifs_getattr,
+ .permission = cifs_permission,
+ .listxattr = cifs_listxattr,
+ .fiemap = cifs_fiemap,
+};
+
+const char *cifs_get_link(struct dentry *dentry, struct inode *inode,
+ struct delayed_call *done)
+{
+ char *target_path;
+
+ target_path = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!target_path)
+ return ERR_PTR(-ENOMEM);
+
+ spin_lock(&inode->i_lock);
+ if (likely(CIFS_I(inode)->symlink_target)) {
+ strscpy(target_path, CIFS_I(inode)->symlink_target, PATH_MAX);
+ } else {
+ kfree(target_path);
+ target_path = ERR_PTR(-EOPNOTSUPP);
+ }
+ spin_unlock(&inode->i_lock);
+
+ if (!IS_ERR(target_path))
+ set_delayed_call(done, kfree_link, target_path);
+
+ return target_path;
+}
+
+const struct inode_operations cifs_symlink_inode_ops = {
+ .get_link = cifs_get_link,
+ .permission = cifs_permission,
+ .listxattr = cifs_listxattr,
+};
+
+static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
+ struct file *dst_file, loff_t destoff, loff_t len,
+ unsigned int remap_flags)
+{
+ struct inode *src_inode = file_inode(src_file);
+ struct inode *target_inode = file_inode(dst_file);
+ struct cifsFileInfo *smb_file_src = src_file->private_data;
+ struct cifsFileInfo *smb_file_target;
+ struct cifs_tcon *target_tcon;
+ unsigned int xid;
+ int rc;
+
+ if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
+ return -EINVAL;
+
+ cifs_dbg(FYI, "clone range\n");
+
+ xid = get_xid();
+
+ if (!src_file->private_data || !dst_file->private_data) {
+ rc = -EBADF;
+ cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
+ goto out;
+ }
+
+ smb_file_target = dst_file->private_data;
+ target_tcon = tlink_tcon(smb_file_target->tlink);
+
+ /*
+ * Note: cifs case is easier than btrfs since server responsible for
+ * checks for proper open modes and file type and if it wants
+ * server could even support copy of range where source = target
+ */
+ lock_two_nondirectories(target_inode, src_inode);
+
+ if (len == 0)
+ len = src_inode->i_size - off;
+
+ cifs_dbg(FYI, "about to flush pages\n");
+ /* should we flush first and last page first */
+ truncate_inode_pages_range(&target_inode->i_data, destoff,
+ PAGE_ALIGN(destoff + len)-1);
+
+ if (target_tcon->ses->server->ops->duplicate_extents)
+ rc = target_tcon->ses->server->ops->duplicate_extents(xid,
+ smb_file_src, smb_file_target, off, len, destoff);
+ else
+ rc = -EOPNOTSUPP;
+
+ /* force revalidate of size and timestamps of target file now
+ that target is updated on the server */
+ CIFS_I(target_inode)->time = 0;
+ /* although unlocking in the reverse order from locking is not
+ strictly necessary here it is a little cleaner to be consistent */
+ unlock_two_nondirectories(src_inode, target_inode);
+out:
+ free_xid(xid);
+ return rc < 0 ? rc : len;
+}
+
+ssize_t cifs_file_copychunk_range(unsigned int xid,
+ struct file *src_file, loff_t off,
+ struct file *dst_file, loff_t destoff,
+ size_t len, unsigned int flags)
+{
+ struct inode *src_inode = file_inode(src_file);
+ struct inode *target_inode = file_inode(dst_file);
+ struct cifsFileInfo *smb_file_src;
+ struct cifsFileInfo *smb_file_target;
+ struct cifs_tcon *src_tcon;
+ struct cifs_tcon *target_tcon;
+ ssize_t rc;
+
+ cifs_dbg(FYI, "copychunk range\n");
+
+ if (!src_file->private_data || !dst_file->private_data) {
+ rc = -EBADF;
+ cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
+ goto out;
+ }
+
+ rc = -EXDEV;
+ smb_file_target = dst_file->private_data;
+ smb_file_src = src_file->private_data;
+ src_tcon = tlink_tcon(smb_file_src->tlink);
+ target_tcon = tlink_tcon(smb_file_target->tlink);
+
+ if (src_tcon->ses != target_tcon->ses) {
+ cifs_dbg(VFS, "source and target of copy not on same server\n");
+ goto out;
+ }
+
+ rc = -EOPNOTSUPP;
+ if (!target_tcon->ses->server->ops->copychunk_range)
+ goto out;
+
+ /*
+ * Note: cifs case is easier than btrfs since server responsible for
+ * checks for proper open modes and file type and if it wants
+ * server could even support copy of range where source = target
+ */
+ lock_two_nondirectories(target_inode, src_inode);
+
+ cifs_dbg(FYI, "about to flush pages\n");
+
+ rc = filemap_write_and_wait_range(src_inode->i_mapping, off,
+ off + len - 1);
+ if (rc)
+ goto unlock;
+
+ /* should we flush first and last page first */
+ truncate_inode_pages(&target_inode->i_data, 0);
+
+ rc = file_modified(dst_file);
+ if (!rc)
+ rc = target_tcon->ses->server->ops->copychunk_range(xid,
+ smb_file_src, smb_file_target, off, len, destoff);
+
+ file_accessed(src_file);
+
+ /* force revalidate of size and timestamps of target file now
+ * that target is updated on the server
+ */
+ CIFS_I(target_inode)->time = 0;
+
+unlock:
+ /* although unlocking in the reverse order from locking is not
+ * strictly necessary here it is a little cleaner to be consistent
+ */
+ unlock_two_nondirectories(src_inode, target_inode);
+
+out:
+ return rc;
+}
+
+/*
+ * Directory operations under CIFS/SMB2/SMB3 are synchronous, so fsync()
+ * is a dummy operation.
+ */
+static int cifs_dir_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+ cifs_dbg(FYI, "Sync directory - name: %pD datasync: 0x%x\n",
+ file, datasync);
+
+ return 0;
+}
+
+static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
+ struct file *dst_file, loff_t destoff,
+ size_t len, unsigned int flags)
+{
+ unsigned int xid = get_xid();
+ ssize_t rc;
+ struct cifsFileInfo *cfile = dst_file->private_data;
+
+ if (cfile->swapfile) {
+ rc = -EOPNOTSUPP;
+ free_xid(xid);
+ return rc;
+ }
+
+ rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff,
+ len, flags);
+ free_xid(xid);
+
+ if (rc == -EOPNOTSUPP || rc == -EXDEV)
+ rc = generic_copy_file_range(src_file, off, dst_file,
+ destoff, len, flags);
+ return rc;
+}
+
+const struct file_operations cifs_file_ops = {
+ .read_iter = cifs_loose_read_iter,
+ .write_iter = cifs_file_write_iter,
+ .open = cifs_open,
+ .release = cifs_close,
+ .lock = cifs_lock,
+ .flock = cifs_flock,
+ .fsync = cifs_fsync,
+ .flush = cifs_flush,
+ .mmap = cifs_file_mmap,
+ .splice_read = generic_file_splice_read,
+ .splice_write = iter_file_splice_write,
+ .llseek = cifs_llseek,
+ .unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
+ .remap_file_range = cifs_remap_file_range,
+ .setlease = cifs_setlease,
+ .fallocate = cifs_fallocate,
+};
+
+const struct file_operations cifs_file_strict_ops = {
+ .read_iter = cifs_strict_readv,
+ .write_iter = cifs_strict_writev,
+ .open = cifs_open,
+ .release = cifs_close,
+ .lock = cifs_lock,
+ .flock = cifs_flock,
+ .fsync = cifs_strict_fsync,
+ .flush = cifs_flush,
+ .mmap = cifs_file_strict_mmap,
+ .splice_read = generic_file_splice_read,
+ .splice_write = iter_file_splice_write,
+ .llseek = cifs_llseek,
+ .unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
+ .remap_file_range = cifs_remap_file_range,
+ .setlease = cifs_setlease,
+ .fallocate = cifs_fallocate,
+};
+
+const struct file_operations cifs_file_direct_ops = {
+ .read_iter = cifs_direct_readv,
+ .write_iter = cifs_direct_writev,
+ .open = cifs_open,
+ .release = cifs_close,
+ .lock = cifs_lock,
+ .flock = cifs_flock,
+ .fsync = cifs_fsync,
+ .flush = cifs_flush,
+ .mmap = cifs_file_mmap,
+ .splice_read = generic_file_splice_read,
+ .splice_write = iter_file_splice_write,
+ .unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
+ .remap_file_range = cifs_remap_file_range,
+ .llseek = cifs_llseek,
+ .setlease = cifs_setlease,
+ .fallocate = cifs_fallocate,
+};
+
+const struct file_operations cifs_file_nobrl_ops = {
+ .read_iter = cifs_loose_read_iter,
+ .write_iter = cifs_file_write_iter,
+ .open = cifs_open,
+ .release = cifs_close,
+ .fsync = cifs_fsync,
+ .flush = cifs_flush,
+ .mmap = cifs_file_mmap,
+ .splice_read = generic_file_splice_read,
+ .splice_write = iter_file_splice_write,
+ .llseek = cifs_llseek,
+ .unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
+ .remap_file_range = cifs_remap_file_range,
+ .setlease = cifs_setlease,
+ .fallocate = cifs_fallocate,
+};
+
+const struct file_operations cifs_file_strict_nobrl_ops = {
+ .read_iter = cifs_strict_readv,
+ .write_iter = cifs_strict_writev,
+ .open = cifs_open,
+ .release = cifs_close,
+ .fsync = cifs_strict_fsync,
+ .flush = cifs_flush,
+ .mmap = cifs_file_strict_mmap,
+ .splice_read = generic_file_splice_read,
+ .splice_write = iter_file_splice_write,
+ .llseek = cifs_llseek,
+ .unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
+ .remap_file_range = cifs_remap_file_range,
+ .setlease = cifs_setlease,
+ .fallocate = cifs_fallocate,
+};
+
+const struct file_operations cifs_file_direct_nobrl_ops = {
+ .read_iter = cifs_direct_readv,
+ .write_iter = cifs_direct_writev,
+ .open = cifs_open,
+ .release = cifs_close,
+ .fsync = cifs_fsync,
+ .flush = cifs_flush,
+ .mmap = cifs_file_mmap,
+ .splice_read = generic_file_splice_read,
+ .splice_write = iter_file_splice_write,
+ .unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
+ .remap_file_range = cifs_remap_file_range,
+ .llseek = cifs_llseek,
+ .setlease = cifs_setlease,
+ .fallocate = cifs_fallocate,
+};
+
+const struct file_operations cifs_dir_ops = {
+ .iterate_shared = cifs_readdir,
+ .release = cifs_closedir,
+ .read = generic_read_dir,
+ .unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
+ .remap_file_range = cifs_remap_file_range,
+ .llseek = generic_file_llseek,
+ .fsync = cifs_dir_fsync,
+};
+
+static void
+cifs_init_once(void *inode)
+{
+ struct cifsInodeInfo *cifsi = inode;
+
+ inode_init_once(&cifsi->netfs.inode);
+ init_rwsem(&cifsi->lock_sem);
+}
+
+static int __init
+cifs_init_inodecache(void)
+{
+ cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
+ sizeof(struct cifsInodeInfo),
+ 0, (SLAB_RECLAIM_ACCOUNT|
+ SLAB_MEM_SPREAD|SLAB_ACCOUNT),
+ cifs_init_once);
+ if (cifs_inode_cachep == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void
+cifs_destroy_inodecache(void)
+{
+ /*
+ * Make sure all delayed rcu free inodes are flushed before we
+ * destroy cache.
+ */
+ rcu_barrier();
+ kmem_cache_destroy(cifs_inode_cachep);
+}
+
+static int
+cifs_init_request_bufs(void)
+{
+ /*
+ * SMB2 maximum header size is bigger than CIFS one - no problems to
+ * allocate some more bytes for CIFS.
+ */
+ size_t max_hdr_size = MAX_SMB2_HDR_SIZE;
+
+ if (CIFSMaxBufSize < 8192) {
+ /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
+ Unicode path name has to fit in any SMB/CIFS path based frames */
+ CIFSMaxBufSize = 8192;
+ } else if (CIFSMaxBufSize > 1024*127) {
+ CIFSMaxBufSize = 1024 * 127;
+ } else {
+ CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
+ }
+/*
+ cifs_dbg(VFS, "CIFSMaxBufSize %d 0x%x\n",
+ CIFSMaxBufSize, CIFSMaxBufSize);
+*/
+ cifs_req_cachep = kmem_cache_create_usercopy("cifs_request",
+ CIFSMaxBufSize + max_hdr_size, 0,
+ SLAB_HWCACHE_ALIGN, 0,
+ CIFSMaxBufSize + max_hdr_size,
+ NULL);
+ if (cifs_req_cachep == NULL)
+ return -ENOMEM;
+
+ if (cifs_min_rcv < 1)
+ cifs_min_rcv = 1;
+ else if (cifs_min_rcv > 64) {
+ cifs_min_rcv = 64;
+ cifs_dbg(VFS, "cifs_min_rcv set to maximum (64)\n");
+ }
+
+ cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
+ cifs_req_cachep);
+
+ if (cifs_req_poolp == NULL) {
+ kmem_cache_destroy(cifs_req_cachep);
+ return -ENOMEM;
+ }
+ /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
+ almost all handle based requests (but not write response, nor is it
+ sufficient for path based requests). A smaller size would have
+ been more efficient (compacting multiple slab items on one 4k page)
+ for the case in which debug was on, but this larger size allows
+ more SMBs to use small buffer alloc and is still much more
+ efficient to alloc 1 per page off the slab compared to 17K (5page)
+ alloc of large cifs buffers even when page debugging is on */
+ cifs_sm_req_cachep = kmem_cache_create_usercopy("cifs_small_rq",
+ MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
+ 0, MAX_CIFS_SMALL_BUFFER_SIZE, NULL);
+ if (cifs_sm_req_cachep == NULL) {
+ mempool_destroy(cifs_req_poolp);
+ kmem_cache_destroy(cifs_req_cachep);
+ return -ENOMEM;
+ }
+
+ if (cifs_min_small < 2)
+ cifs_min_small = 2;
+ else if (cifs_min_small > 256) {
+ cifs_min_small = 256;
+ cifs_dbg(FYI, "cifs_min_small set to maximum (256)\n");
+ }
+
+ cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
+ cifs_sm_req_cachep);
+
+ if (cifs_sm_req_poolp == NULL) {
+ mempool_destroy(cifs_req_poolp);
+ kmem_cache_destroy(cifs_req_cachep);
+ kmem_cache_destroy(cifs_sm_req_cachep);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void
+cifs_destroy_request_bufs(void)
+{
+ mempool_destroy(cifs_req_poolp);
+ kmem_cache_destroy(cifs_req_cachep);
+ mempool_destroy(cifs_sm_req_poolp);
+ kmem_cache_destroy(cifs_sm_req_cachep);
+}
+
+static int init_mids(void)
+{
+ cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
+ sizeof(struct mid_q_entry), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (cifs_mid_cachep == NULL)
+ return -ENOMEM;
+
+ /* 3 is a reasonable minimum number of simultaneous operations */
+ cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
+ if (cifs_mid_poolp == NULL) {
+ kmem_cache_destroy(cifs_mid_cachep);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void destroy_mids(void)
+{
+ mempool_destroy(cifs_mid_poolp);
+ kmem_cache_destroy(cifs_mid_cachep);
+}
+
+static int __init
+init_cifs(void)
+{
+ int rc = 0;
+ cifs_proc_init();
+ INIT_LIST_HEAD(&cifs_tcp_ses_list);
+/*
+ * Initialize Global counters
+ */
+ atomic_set(&sesInfoAllocCount, 0);
+ atomic_set(&tconInfoAllocCount, 0);
+ atomic_set(&tcpSesNextId, 0);
+ atomic_set(&tcpSesAllocCount, 0);
+ atomic_set(&tcpSesReconnectCount, 0);
+ atomic_set(&tconInfoReconnectCount, 0);
+
+ atomic_set(&buf_alloc_count, 0);
+ atomic_set(&small_buf_alloc_count, 0);
+#ifdef CONFIG_CIFS_STATS2
+ atomic_set(&total_buf_alloc_count, 0);
+ atomic_set(&total_small_buf_alloc_count, 0);
+ if (slow_rsp_threshold < 1)
+ cifs_dbg(FYI, "slow_response_threshold msgs disabled\n");
+ else if (slow_rsp_threshold > 32767)
+ cifs_dbg(VFS,
+ "slow response threshold set higher than recommended (0 to 32767)\n");
+#endif /* CONFIG_CIFS_STATS2 */
+
+ atomic_set(&mid_count, 0);
+ GlobalCurrentXid = 0;
+ GlobalTotalActiveXid = 0;
+ GlobalMaxActiveXid = 0;
+ spin_lock_init(&cifs_tcp_ses_lock);
+ spin_lock_init(&GlobalMid_Lock);
+
+ cifs_lock_secret = get_random_u32();
+
+ if (cifs_max_pending < 2) {
+ cifs_max_pending = 2;
+ cifs_dbg(FYI, "cifs_max_pending set to min of 2\n");
+ } else if (cifs_max_pending > CIFS_MAX_REQ) {
+ cifs_max_pending = CIFS_MAX_REQ;
+ cifs_dbg(FYI, "cifs_max_pending set to max of %u\n",
+ CIFS_MAX_REQ);
+ }
+
+ cifsiod_wq = alloc_workqueue("cifsiod", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+ if (!cifsiod_wq) {
+ rc = -ENOMEM;
+ goto out_clean_proc;
+ }
+
+ /*
+ * Consider in future setting limit!=0 maybe to min(num_of_cores - 1, 3)
+ * so that we don't launch too many worker threads but
+ * Documentation/core-api/workqueue.rst recommends setting it to 0
+ */
+
+ /* WQ_UNBOUND allows decrypt tasks to run on any CPU */
+ decrypt_wq = alloc_workqueue("smb3decryptd",
+ WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+ if (!decrypt_wq) {
+ rc = -ENOMEM;
+ goto out_destroy_cifsiod_wq;
+ }
+
+ fileinfo_put_wq = alloc_workqueue("cifsfileinfoput",
+ WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+ if (!fileinfo_put_wq) {
+ rc = -ENOMEM;
+ goto out_destroy_decrypt_wq;
+ }
+
+ cifsoplockd_wq = alloc_workqueue("cifsoplockd",
+ WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+ if (!cifsoplockd_wq) {
+ rc = -ENOMEM;
+ goto out_destroy_fileinfo_put_wq;
+ }
+
+ deferredclose_wq = alloc_workqueue("deferredclose",
+ WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+ if (!deferredclose_wq) {
+ rc = -ENOMEM;
+ goto out_destroy_cifsoplockd_wq;
+ }
+
+ rc = cifs_init_inodecache();
+ if (rc)
+ goto out_destroy_deferredclose_wq;
+
+ rc = init_mids();
+ if (rc)
+ goto out_destroy_inodecache;
+
+ rc = cifs_init_request_bufs();
+ if (rc)
+ goto out_destroy_mids;
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ rc = dfs_cache_init();
+ if (rc)
+ goto out_destroy_request_bufs;
+#endif /* CONFIG_CIFS_DFS_UPCALL */
+#ifdef CONFIG_CIFS_UPCALL
+ rc = init_cifs_spnego();
+ if (rc)
+ goto out_destroy_dfs_cache;
+#endif /* CONFIG_CIFS_UPCALL */
+#ifdef CONFIG_CIFS_SWN_UPCALL
+ rc = cifs_genl_init();
+ if (rc)
+ goto out_register_key_type;
+#endif /* CONFIG_CIFS_SWN_UPCALL */
+
+ rc = init_cifs_idmap();
+ if (rc)
+ goto out_cifs_swn_init;
+
+ rc = register_filesystem(&cifs_fs_type);
+ if (rc)
+ goto out_init_cifs_idmap;
+
+ rc = register_filesystem(&smb3_fs_type);
+ if (rc) {
+ unregister_filesystem(&cifs_fs_type);
+ goto out_init_cifs_idmap;
+ }
+
+ return 0;
+
+out_init_cifs_idmap:
+ exit_cifs_idmap();
+out_cifs_swn_init:
+#ifdef CONFIG_CIFS_SWN_UPCALL
+ cifs_genl_exit();
+out_register_key_type:
+#endif
+#ifdef CONFIG_CIFS_UPCALL
+ exit_cifs_spnego();
+out_destroy_dfs_cache:
+#endif
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ dfs_cache_destroy();
+out_destroy_request_bufs:
+#endif
+ cifs_destroy_request_bufs();
+out_destroy_mids:
+ destroy_mids();
+out_destroy_inodecache:
+ cifs_destroy_inodecache();
+out_destroy_deferredclose_wq:
+ destroy_workqueue(deferredclose_wq);
+out_destroy_cifsoplockd_wq:
+ destroy_workqueue(cifsoplockd_wq);
+out_destroy_fileinfo_put_wq:
+ destroy_workqueue(fileinfo_put_wq);
+out_destroy_decrypt_wq:
+ destroy_workqueue(decrypt_wq);
+out_destroy_cifsiod_wq:
+ destroy_workqueue(cifsiod_wq);
+out_clean_proc:
+ cifs_proc_clean();
+ return rc;
+}
+
+static void __exit
+exit_cifs(void)
+{
+ cifs_dbg(NOISY, "exit_smb3\n");
+ unregister_filesystem(&cifs_fs_type);
+ unregister_filesystem(&smb3_fs_type);
+ cifs_dfs_release_automount_timer();
+ exit_cifs_idmap();
+#ifdef CONFIG_CIFS_SWN_UPCALL
+ cifs_genl_exit();
+#endif
+#ifdef CONFIG_CIFS_UPCALL
+ exit_cifs_spnego();
+#endif
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ dfs_cache_destroy();
+#endif
+ cifs_destroy_request_bufs();
+ destroy_mids();
+ cifs_destroy_inodecache();
+ destroy_workqueue(deferredclose_wq);
+ destroy_workqueue(cifsoplockd_wq);
+ destroy_workqueue(decrypt_wq);
+ destroy_workqueue(fileinfo_put_wq);
+ destroy_workqueue(cifsiod_wq);
+ cifs_proc_clean();
+}
+
+MODULE_AUTHOR("Steve French");
+MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
+MODULE_DESCRIPTION
+ ("VFS to access SMB3 servers e.g. Samba, Macs, Azure and Windows (and "
+ "also older servers complying with the SNIA CIFS Specification)");
+MODULE_VERSION(CIFS_VERSION);
+MODULE_SOFTDEP("ecb");
+MODULE_SOFTDEP("hmac");
+MODULE_SOFTDEP("md5");
+MODULE_SOFTDEP("nls");
+MODULE_SOFTDEP("aes");
+MODULE_SOFTDEP("cmac");
+MODULE_SOFTDEP("sha256");
+MODULE_SOFTDEP("sha512");
+MODULE_SOFTDEP("aead2");
+MODULE_SOFTDEP("ccm");
+MODULE_SOFTDEP("gcm");
+module_init(init_cifs)
+module_exit(exit_cifs)
diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h
new file mode 100644
index 000000000000..b6c38896fb2d
--- /dev/null
+++ b/fs/smb/client/cifsfs.h
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002, 2007
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#ifndef _CIFSFS_H
+#define _CIFSFS_H
+
+#include <linux/hash.h>
+
+#define ROOT_I 2
+
+/*
+ * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
+ * so that it will fit. We use hash_64 to convert the value to 31 bits, and
+ * then add 1, to ensure that we don't end up with a 0 as the value.
+ */
+static inline ino_t
+cifs_uniqueid_to_ino_t(u64 fileid)
+{
+ if ((sizeof(ino_t)) < (sizeof(u64)))
+ return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
+
+ return (ino_t)fileid;
+
+}
+
+static inline void cifs_set_time(struct dentry *dentry, unsigned long time)
+{
+ dentry->d_fsdata = (void *) time;
+}
+
+static inline unsigned long cifs_get_time(struct dentry *dentry)
+{
+ return (unsigned long) dentry->d_fsdata;
+}
+
+extern struct file_system_type cifs_fs_type, smb3_fs_type;
+extern const struct address_space_operations cifs_addr_ops;
+extern const struct address_space_operations cifs_addr_ops_smallbuf;
+
+/* Functions related to super block operations */
+extern void cifs_sb_active(struct super_block *sb);
+extern void cifs_sb_deactive(struct super_block *sb);
+
+/* Functions related to inodes */
+extern const struct inode_operations cifs_dir_inode_ops;
+extern struct inode *cifs_root_iget(struct super_block *);
+extern int cifs_create(struct user_namespace *, struct inode *,
+ struct dentry *, umode_t, bool excl);
+extern int cifs_atomic_open(struct inode *, struct dentry *,
+ struct file *, unsigned, umode_t);
+extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
+ unsigned int);
+extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
+extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
+extern int cifs_mknod(struct user_namespace *, struct inode *, struct dentry *,
+ umode_t, dev_t);
+extern int cifs_mkdir(struct user_namespace *, struct inode *, struct dentry *,
+ umode_t);
+extern int cifs_rmdir(struct inode *, struct dentry *);
+extern int cifs_rename2(struct user_namespace *, struct inode *,
+ struct dentry *, struct inode *, struct dentry *,
+ unsigned int);
+extern int cifs_revalidate_file_attr(struct file *filp);
+extern int cifs_revalidate_dentry_attr(struct dentry *);
+extern int cifs_revalidate_file(struct file *filp);
+extern int cifs_revalidate_dentry(struct dentry *);
+extern int cifs_invalidate_mapping(struct inode *inode);
+extern int cifs_revalidate_mapping(struct inode *inode);
+extern int cifs_zap_mapping(struct inode *inode);
+extern int cifs_getattr(struct user_namespace *, const struct path *,
+ struct kstat *, u32, unsigned int);
+extern int cifs_setattr(struct user_namespace *, struct dentry *,
+ struct iattr *);
+extern int cifs_fiemap(struct inode *, struct fiemap_extent_info *, u64 start,
+ u64 len);
+
+extern const struct inode_operations cifs_file_inode_ops;
+extern const struct inode_operations cifs_symlink_inode_ops;
+extern const struct inode_operations cifs_dfs_referral_inode_operations;
+
+
+/* Functions related to files and directories */
+extern const struct file_operations cifs_file_ops;
+extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
+extern const struct file_operations cifs_file_strict_ops; /* if strictio mnt */
+extern const struct file_operations cifs_file_nobrl_ops; /* no brlocks */
+extern const struct file_operations cifs_file_direct_nobrl_ops;
+extern const struct file_operations cifs_file_strict_nobrl_ops;
+extern int cifs_open(struct inode *inode, struct file *file);
+extern int cifs_close(struct inode *inode, struct file *file);
+extern int cifs_closedir(struct inode *inode, struct file *file);
+extern ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to);
+extern ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to);
+extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to);
+extern ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from);
+extern ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from);
+extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from);
+extern int cifs_flock(struct file *pfile, int cmd, struct file_lock *plock);
+extern int cifs_lock(struct file *, int, struct file_lock *);
+extern int cifs_fsync(struct file *, loff_t, loff_t, int);
+extern int cifs_strict_fsync(struct file *, loff_t, loff_t, int);
+extern int cifs_flush(struct file *, fl_owner_t id);
+extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
+extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
+extern const struct file_operations cifs_dir_ops;
+extern int cifs_dir_open(struct inode *inode, struct file *file);
+extern int cifs_readdir(struct file *file, struct dir_context *ctx);
+
+/* Functions related to dir entries */
+extern const struct dentry_operations cifs_dentry_ops;
+extern const struct dentry_operations cifs_ci_dentry_ops;
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
+#else
+static inline struct vfsmount *cifs_dfs_d_automount(struct path *path)
+{
+ return ERR_PTR(-EREMOTE);
+}
+#endif
+
+/* Functions related to symlinks */
+extern const char *cifs_get_link(struct dentry *, struct inode *,
+ struct delayed_call *);
+extern int cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
+ struct dentry *direntry, const char *symname);
+
+#ifdef CONFIG_CIFS_XATTR
+extern const struct xattr_handler *cifs_xattr_handlers[];
+extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
+#else
+# define cifs_xattr_handlers NULL
+# define cifs_listxattr NULL
+#endif
+
+extern ssize_t cifs_file_copychunk_range(unsigned int xid,
+ struct file *src_file, loff_t off,
+ struct file *dst_file, loff_t destoff,
+ size_t len, unsigned int flags);
+
+extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
+extern void cifs_setsize(struct inode *inode, loff_t offset);
+extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
+
+struct smb3_fs_context;
+extern struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type,
+ int flags, struct smb3_fs_context *ctx);
+
+#ifdef CONFIG_CIFS_NFSD_EXPORT
+extern const struct export_operations cifs_export_ops;
+#endif /* CONFIG_CIFS_NFSD_EXPORT */
+
+/* when changing internal version - update following two lines at same time */
+#define SMB3_PRODUCT_BUILD 40
+#define CIFS_VERSION "2.40"
+#endif /* _CIFSFS_H */
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
new file mode 100644
index 000000000000..a37afbb7e399
--- /dev/null
+++ b/fs/smb/client/cifsglob.h
@@ -0,0 +1,2208 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Jeremy Allison (jra@samba.org)
+ *
+ */
+#ifndef _CIFS_GLOB_H
+#define _CIFS_GLOB_H
+
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/inet.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/mm.h>
+#include <linux/mempool.h>
+#include <linux/workqueue.h>
+#include <linux/utsname.h>
+#include <linux/sched/mm.h>
+#include <linux/netfs.h>
+#include "cifs_fs_sb.h"
+#include "cifsacl.h"
+#include <crypto/internal/hash.h>
+#include <linux/scatterlist.h>
+#include <uapi/linux/cifs/cifs_mount.h>
+#include "../common/smb2pdu.h"
+#include "smb2pdu.h"
+
+#define SMB_PATH_MAX 260
+#define CIFS_PORT 445
+#define RFC1001_PORT 139
+
+/*
+ * The sizes of various internal tables and strings
+ */
+#define MAX_UID_INFO 16
+#define MAX_SES_INFO 2
+#define MAX_TCON_INFO 4
+
+#define MAX_TREE_SIZE (2 + CIFS_NI_MAXHOST + 1 + CIFS_MAX_SHARE_LEN + 1)
+
+#define CIFS_MIN_RCV_POOL 4
+
+#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */
+/*
+ * default attribute cache timeout (jiffies)
+ */
+#define CIFS_DEF_ACTIMEO (1 * HZ)
+
+/*
+ * max attribute cache timeout (jiffies) - 2^30
+ */
+#define CIFS_MAX_ACTIMEO (1 << 30)
+
+/*
+ * Max persistent and resilient handle timeout (milliseconds).
+ * Windows durable max was 960000 (16 minutes)
+ */
+#define SMB3_MAX_HANDLE_TIMEOUT 960000
+
+/*
+ * MAX_REQ is the maximum number of requests that WE will send
+ * on one socket concurrently.
+ */
+#define CIFS_MAX_REQ 32767
+
+#define RFC1001_NAME_LEN 15
+#define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1)
+
+/* maximum length of ip addr as a string (including ipv6 and sctp) */
+#define SERVER_NAME_LENGTH 80
+#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
+
+/* echo interval in seconds */
+#define SMB_ECHO_INTERVAL_MIN 1
+#define SMB_ECHO_INTERVAL_MAX 600
+#define SMB_ECHO_INTERVAL_DEFAULT 60
+
+/* dns resolution intervals in seconds */
+#define SMB_DNS_RESOLVE_INTERVAL_MIN 120
+#define SMB_DNS_RESOLVE_INTERVAL_DEFAULT 600
+
+/* smb multichannel query server interfaces interval in seconds */
+#define SMB_INTERFACE_POLL_INTERVAL 600
+
+/* maximum number of PDUs in one compound */
+#define MAX_COMPOUND 5
+
+/*
+ * Default number of credits to keep available for SMB3.
+ * This value is chosen somewhat arbitrarily. The Windows client
+ * defaults to 128 credits, the Windows server allows clients up to
+ * 512 credits (or 8K for later versions), and the NetApp server
+ * does not limit clients at all. Choose a high enough default value
+ * such that the client shouldn't limit performance, but allow mount
+ * to override (until you approach 64K, where we limit credits to 65000
+ * to reduce possibility of seeing more server credit overflow bugs.
+ */
+#define SMB2_MAX_CREDITS_AVAILABLE 32000
+
+#include "cifspdu.h"
+
+#ifndef XATTR_DOS_ATTRIB
+#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
+#endif
+
+#define CIFS_MAX_WORKSTATION_LEN (__NEW_UTS_LEN + 1) /* reasonable max for client */
+
+/*
+ * CIFS vfs client Status information (based on what we know.)
+ */
+
+/* associated with each connection */
+enum statusEnum {
+ CifsNew = 0,
+ CifsGood,
+ CifsExiting,
+ CifsNeedReconnect,
+ CifsNeedNegotiate,
+ CifsInNegotiate,
+};
+
+/* associated with each smb session */
+enum ses_status_enum {
+ SES_NEW = 0,
+ SES_GOOD,
+ SES_EXITING,
+ SES_NEED_RECON,
+ SES_IN_SETUP
+};
+
+/* associated with each tree connection to the server */
+enum tid_status_enum {
+ TID_NEW = 0,
+ TID_GOOD,
+ TID_EXITING,
+ TID_NEED_RECON,
+ TID_NEED_TCON,
+ TID_IN_TCON,
+ TID_NEED_FILES_INVALIDATE, /* currently unused */
+ TID_IN_FILES_INVALIDATE
+};
+
+enum securityEnum {
+ Unspecified = 0, /* not specified */
+ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
+ RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
+ Kerberos, /* Kerberos via SPNEGO */
+};
+
+struct session_key {
+ unsigned int len;
+ char *response;
+};
+
+/* crypto hashing related structure/fields, not specific to a sec mech */
+struct cifs_secmech {
+ struct shash_desc *hmacmd5; /* hmacmd5 hash function, for NTLMv2/CR1 hashes */
+ struct shash_desc *md5; /* md5 hash function, for CIFS/SMB1 signatures */
+ struct shash_desc *hmacsha256; /* hmac-sha256 hash function, for SMB2 signatures */
+ struct shash_desc *sha512; /* sha512 hash function, for SMB3.1.1 preauth hash */
+ struct shash_desc *aes_cmac; /* block-cipher based MAC function, for SMB3 signatures */
+
+ struct crypto_aead *enc; /* smb3 encryption AEAD TFM (AES-CCM and AES-GCM) */
+ struct crypto_aead *dec; /* smb3 decryption AEAD TFM (AES-CCM and AES-GCM) */
+};
+
+/* per smb session structure/fields */
+struct ntlmssp_auth {
+ bool sesskey_per_smbsess; /* whether session key is per smb session */
+ __u32 client_flags; /* sent by client in type 1 ntlmsssp exchange */
+ __u32 server_flags; /* sent by server in type 2 ntlmssp exchange */
+ unsigned char ciphertext[CIFS_CPHTXT_SIZE]; /* sent to server */
+ char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlmssp */
+};
+
+struct cifs_cred {
+ int uid;
+ int gid;
+ int mode;
+ int cecount;
+ struct cifs_sid osid;
+ struct cifs_sid gsid;
+ struct cifs_ntace *ntaces;
+ struct cifs_ace *aces;
+};
+
+struct cifs_open_info_data {
+ char *symlink_target;
+ union {
+ struct smb2_file_all_info fi;
+ struct smb311_posix_qinfo posix_fi;
+ };
+};
+
+static inline void cifs_free_open_info(struct cifs_open_info_data *data)
+{
+ kfree(data->symlink_target);
+}
+
+/*
+ *****************************************************************
+ * Except the CIFS PDUs themselves all the
+ * globally interesting structs should go here
+ *****************************************************************
+ */
+
+/*
+ * A smb_rqst represents a complete request to be issued to a server. It's
+ * formed by a kvec array, followed by an array of pages. Page data is assumed
+ * to start at the beginning of the first page.
+ */
+struct smb_rqst {
+ struct kvec *rq_iov; /* array of kvecs */
+ unsigned int rq_nvec; /* number of kvecs in array */
+ struct page **rq_pages; /* pointer to array of page ptrs */
+ unsigned int rq_offset; /* the offset to the 1st page */
+ unsigned int rq_npages; /* number pages in array */
+ unsigned int rq_pagesz; /* page size to use */
+ unsigned int rq_tailsz; /* length of last page */
+};
+
+struct mid_q_entry;
+struct TCP_Server_Info;
+struct cifsFileInfo;
+struct cifs_ses;
+struct cifs_tcon;
+struct dfs_info3_param;
+struct cifs_fattr;
+struct smb3_fs_context;
+struct cifs_fid;
+struct cifs_readdata;
+struct cifs_writedata;
+struct cifs_io_parms;
+struct cifs_search_info;
+struct cifsInodeInfo;
+struct cifs_open_parms;
+struct cifs_credits;
+
+struct smb_version_operations {
+ int (*send_cancel)(struct TCP_Server_Info *, struct smb_rqst *,
+ struct mid_q_entry *);
+ bool (*compare_fids)(struct cifsFileInfo *, struct cifsFileInfo *);
+ /* setup request: allocate mid, sign message */
+ struct mid_q_entry *(*setup_request)(struct cifs_ses *,
+ struct TCP_Server_Info *,
+ struct smb_rqst *);
+ /* setup async request: allocate mid, sign message */
+ struct mid_q_entry *(*setup_async_request)(struct TCP_Server_Info *,
+ struct smb_rqst *);
+ /* check response: verify signature, map error */
+ int (*check_receive)(struct mid_q_entry *, struct TCP_Server_Info *,
+ bool);
+ void (*add_credits)(struct TCP_Server_Info *server,
+ const struct cifs_credits *credits,
+ const int optype);
+ void (*set_credits)(struct TCP_Server_Info *, const int);
+ int * (*get_credits_field)(struct TCP_Server_Info *, const int);
+ unsigned int (*get_credits)(struct mid_q_entry *);
+ __u64 (*get_next_mid)(struct TCP_Server_Info *);
+ void (*revert_current_mid)(struct TCP_Server_Info *server,
+ const unsigned int val);
+ /* data offset from read response message */
+ unsigned int (*read_data_offset)(char *);
+ /*
+ * Data length from read response message
+ * When in_remaining is true, the returned data length is in
+ * message field DataRemaining for out-of-band data read (e.g through
+ * Memory Registration RDMA write in SMBD).
+ * Otherwise, the returned data length is in message field DataLength.
+ */
+ unsigned int (*read_data_length)(char *, bool in_remaining);
+ /* map smb to linux error */
+ int (*map_error)(char *, bool);
+ /* find mid corresponding to the response message */
+ struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *);
+ void (*dump_detail)(void *buf, struct TCP_Server_Info *ptcp_info);
+ void (*clear_stats)(struct cifs_tcon *);
+ void (*print_stats)(struct seq_file *m, struct cifs_tcon *);
+ void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *);
+ /* verify the message */
+ int (*check_message)(char *, unsigned int, struct TCP_Server_Info *);
+ bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
+ int (*handle_cancelled_mid)(struct mid_q_entry *, struct TCP_Server_Info *);
+ void (*downgrade_oplock)(struct TCP_Server_Info *server,
+ struct cifsInodeInfo *cinode, __u32 oplock,
+ unsigned int epoch, bool *purge_cache);
+ /* process transaction2 response */
+ bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *,
+ char *, int);
+ /* check if we need to negotiate */
+ bool (*need_neg)(struct TCP_Server_Info *);
+ /* negotiate to the server */
+ int (*negotiate)(const unsigned int xid,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+ /* set negotiated write size */
+ unsigned int (*negotiate_wsize)(struct cifs_tcon *tcon, struct smb3_fs_context *ctx);
+ /* set negotiated read size */
+ unsigned int (*negotiate_rsize)(struct cifs_tcon *tcon, struct smb3_fs_context *ctx);
+ /* setup smb sessionn */
+ int (*sess_setup)(const unsigned int, struct cifs_ses *,
+ struct TCP_Server_Info *server,
+ const struct nls_table *);
+ /* close smb session */
+ int (*logoff)(const unsigned int, struct cifs_ses *);
+ /* connect to a server share */
+ int (*tree_connect)(const unsigned int, struct cifs_ses *, const char *,
+ struct cifs_tcon *, const struct nls_table *);
+ /* close tree connecion */
+ int (*tree_disconnect)(const unsigned int, struct cifs_tcon *);
+ /* get DFS referrals */
+ int (*get_dfs_refer)(const unsigned int, struct cifs_ses *,
+ const char *, struct dfs_info3_param **,
+ unsigned int *, const struct nls_table *, int);
+ /* informational QFS call */
+ void (*qfs_tcon)(const unsigned int, struct cifs_tcon *,
+ struct cifs_sb_info *);
+ /* check if a path is accessible or not */
+ int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
+ struct cifs_sb_info *, const char *);
+ /* query path data from the server */
+ int (*query_path_info)(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
+ /* query file data from the server */
+ int (*query_file_info)(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, struct cifs_open_info_data *data);
+ /* query reparse tag from srv to determine which type of special file */
+ int (*query_reparse_tag)(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *path,
+ __u32 *reparse_tag);
+ /* get server index number */
+ int (*get_srv_inum)(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path, u64 *uniqueid,
+ struct cifs_open_info_data *data);
+ /* set size by path */
+ int (*set_path_size)(const unsigned int, struct cifs_tcon *,
+ const char *, __u64, struct cifs_sb_info *, bool);
+ /* set size by file handle */
+ int (*set_file_size)(const unsigned int, struct cifs_tcon *,
+ struct cifsFileInfo *, __u64, bool);
+ /* set attributes */
+ int (*set_file_info)(struct inode *, const char *, FILE_BASIC_INFO *,
+ const unsigned int);
+ int (*set_compression)(const unsigned int, struct cifs_tcon *,
+ struct cifsFileInfo *);
+ /* check if we can send an echo or nor */
+ bool (*can_echo)(struct TCP_Server_Info *);
+ /* send echo request */
+ int (*echo)(struct TCP_Server_Info *);
+ /* create directory */
+ int (*posix_mkdir)(const unsigned int xid, struct inode *inode,
+ umode_t mode, struct cifs_tcon *tcon,
+ const char *full_path,
+ struct cifs_sb_info *cifs_sb);
+ int (*mkdir)(const unsigned int xid, struct inode *inode, umode_t mode,
+ struct cifs_tcon *tcon, const char *name,
+ struct cifs_sb_info *sb);
+ /* set info on created directory */
+ void (*mkdir_setinfo)(struct inode *, const char *,
+ struct cifs_sb_info *, struct cifs_tcon *,
+ const unsigned int);
+ /* remove directory */
+ int (*rmdir)(const unsigned int, struct cifs_tcon *, const char *,
+ struct cifs_sb_info *);
+ /* unlink file */
+ int (*unlink)(const unsigned int, struct cifs_tcon *, const char *,
+ struct cifs_sb_info *);
+ /* open, rename and delete file */
+ int (*rename_pending_delete)(const char *, struct dentry *,
+ const unsigned int);
+ /* send rename request */
+ int (*rename)(const unsigned int, struct cifs_tcon *, const char *,
+ const char *, struct cifs_sb_info *);
+ /* send create hardlink request */
+ int (*create_hardlink)(const unsigned int, struct cifs_tcon *,
+ const char *, const char *,
+ struct cifs_sb_info *);
+ /* query symlink target */
+ int (*query_symlink)(const unsigned int, struct cifs_tcon *,
+ struct cifs_sb_info *, const char *,
+ char **, bool);
+ /* open a file for non-posix mounts */
+ int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
+ void *buf);
+ /* set fid protocol-specific info */
+ void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32);
+ /* close a file */
+ void (*close)(const unsigned int, struct cifs_tcon *,
+ struct cifs_fid *);
+ /* close a file, returning file attributes and timestamps */
+ void (*close_getattr)(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *pfile_info);
+ /* send a flush request to the server */
+ int (*flush)(const unsigned int, struct cifs_tcon *, struct cifs_fid *);
+ /* async read from the server */
+ int (*async_readv)(struct cifs_readdata *);
+ /* async write to the server */
+ int (*async_writev)(struct cifs_writedata *,
+ void (*release)(struct kref *));
+ /* sync read from the server */
+ int (*sync_read)(const unsigned int, struct cifs_fid *,
+ struct cifs_io_parms *, unsigned int *, char **,
+ int *);
+ /* sync write to the server */
+ int (*sync_write)(const unsigned int, struct cifs_fid *,
+ struct cifs_io_parms *, unsigned int *, struct kvec *,
+ unsigned long);
+ /* open dir, start readdir */
+ int (*query_dir_first)(const unsigned int, struct cifs_tcon *,
+ const char *, struct cifs_sb_info *,
+ struct cifs_fid *, __u16,
+ struct cifs_search_info *);
+ /* continue readdir */
+ int (*query_dir_next)(const unsigned int, struct cifs_tcon *,
+ struct cifs_fid *,
+ __u16, struct cifs_search_info *srch_inf);
+ /* close dir */
+ int (*close_dir)(const unsigned int, struct cifs_tcon *,
+ struct cifs_fid *);
+ /* calculate a size of SMB message */
+ unsigned int (*calc_smb_size)(void *buf);
+ /* check for STATUS_PENDING and process the response if yes */
+ bool (*is_status_pending)(char *buf, struct TCP_Server_Info *server);
+ /* check for STATUS_NETWORK_SESSION_EXPIRED */
+ bool (*is_session_expired)(char *);
+ /* send oplock break response */
+ int (*oplock_response)(struct cifs_tcon *tcon, __u64 persistent_fid, __u64 volatile_fid,
+ __u16 net_fid, struct cifsInodeInfo *cifs_inode);
+ /* query remote filesystem */
+ int (*queryfs)(const unsigned int, struct cifs_tcon *,
+ struct cifs_sb_info *, struct kstatfs *);
+ /* send mandatory brlock to the server */
+ int (*mand_lock)(const unsigned int, struct cifsFileInfo *, __u64,
+ __u64, __u32, int, int, bool);
+ /* unlock range of mandatory locks */
+ int (*mand_unlock_range)(struct cifsFileInfo *, struct file_lock *,
+ const unsigned int);
+ /* push brlocks from the cache to the server */
+ int (*push_mand_locks)(struct cifsFileInfo *);
+ /* get lease key of the inode */
+ void (*get_lease_key)(struct inode *, struct cifs_fid *);
+ /* set lease key of the inode */
+ void (*set_lease_key)(struct inode *, struct cifs_fid *);
+ /* generate new lease key */
+ void (*new_lease_key)(struct cifs_fid *);
+ int (*generate_signingkey)(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+ int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *,
+ bool allocate_crypto);
+ int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon,
+ struct cifsFileInfo *src_file);
+ int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *src_file, void __user *);
+ int (*notify)(const unsigned int xid, struct file *pfile,
+ void __user *pbuf, bool return_changes);
+ int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
+ struct cifs_sb_info *, const unsigned char *,
+ char *, unsigned int *);
+ int (*create_mf_symlink)(unsigned int, struct cifs_tcon *,
+ struct cifs_sb_info *, const unsigned char *,
+ char *, unsigned int *);
+ /* if we can do cache read operations */
+ bool (*is_read_op)(__u32);
+ /* set oplock level for the inode */
+ void (*set_oplock_level)(struct cifsInodeInfo *, __u32, unsigned int,
+ bool *);
+ /* create lease context buffer for CREATE request */
+ char * (*create_lease_buf)(u8 *lease_key, u8 oplock);
+ /* parse lease context buffer and return oplock/epoch info */
+ __u8 (*parse_lease_buf)(void *buf, unsigned int *epoch, char *lkey);
+ ssize_t (*copychunk_range)(const unsigned int,
+ struct cifsFileInfo *src_file,
+ struct cifsFileInfo *target_file,
+ u64 src_off, u64 len, u64 dest_off);
+ int (*duplicate_extents)(const unsigned int, struct cifsFileInfo *src,
+ struct cifsFileInfo *target_file, u64 src_off, u64 len,
+ u64 dest_off);
+ int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
+ ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *,
+ const unsigned char *, const unsigned char *, char *,
+ size_t, struct cifs_sb_info *);
+ int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
+ const char *, const void *, const __u16,
+ const struct nls_table *, struct cifs_sb_info *);
+ struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
+ const char *, u32 *, u32);
+ struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
+ const struct cifs_fid *, u32 *, u32);
+ int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
+ int);
+ /* writepages retry size */
+ unsigned int (*wp_retry_size)(struct inode *);
+ /* get mtu credits */
+ int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int,
+ unsigned int *, struct cifs_credits *);
+ /* adjust previously taken mtu credits to request size */
+ int (*adjust_credits)(struct TCP_Server_Info *server,
+ struct cifs_credits *credits,
+ const unsigned int payload_size);
+ /* check if we need to issue closedir */
+ bool (*dir_needs_close)(struct cifsFileInfo *);
+ long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
+ loff_t);
+ /* init transform request - used for encryption for now */
+ int (*init_transform_rq)(struct TCP_Server_Info *, int num_rqst,
+ struct smb_rqst *, struct smb_rqst *);
+ int (*is_transform_hdr)(void *buf);
+ int (*receive_transform)(struct TCP_Server_Info *,
+ struct mid_q_entry **, char **, int *);
+ enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
+ enum securityEnum);
+ int (*next_header)(char *);
+ /* ioctl passthrough for query_info */
+ int (*ioctl_query_info)(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ __le16 *path, int is_dir,
+ unsigned long p);
+ /* make unix special files (block, char, fifo, socket) */
+ int (*make_node)(unsigned int xid,
+ struct inode *inode,
+ struct dentry *dentry,
+ struct cifs_tcon *tcon,
+ const char *full_path,
+ umode_t mode,
+ dev_t device_number);
+ /* version specific fiemap implementation */
+ int (*fiemap)(struct cifs_tcon *tcon, struct cifsFileInfo *,
+ struct fiemap_extent_info *, u64, u64);
+ /* version specific llseek implementation */
+ loff_t (*llseek)(struct file *, struct cifs_tcon *, loff_t, int);
+ /* Check for STATUS_IO_TIMEOUT */
+ bool (*is_status_io_timeout)(char *buf);
+ /* Check for STATUS_NETWORK_NAME_DELETED */
+ void (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
+};
+
+struct smb_version_values {
+ char *version_string;
+ __u16 protocol_id;
+ __u32 req_capabilities;
+ __u32 large_lock_type;
+ __u32 exclusive_lock_type;
+ __u32 shared_lock_type;
+ __u32 unlock_lock_type;
+ size_t header_preamble_size;
+ size_t header_size;
+ size_t max_header_size;
+ size_t read_rsp_size;
+ __le16 lock_cmd;
+ unsigned int cap_unix;
+ unsigned int cap_nt_find;
+ unsigned int cap_large_files;
+ __u16 signing_enabled;
+ __u16 signing_required;
+ size_t create_lease_size;
+};
+
+#define HEADER_SIZE(server) (server->vals->header_size)
+#define MAX_HEADER_SIZE(server) (server->vals->max_header_size)
+#define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size)
+#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1 - HEADER_PREAMBLE_SIZE(server))
+
+/**
+ * CIFS superblock mount flags (mnt_cifs_flags) to consider when
+ * trying to reuse existing superblock for a new mount
+ */
+#define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \
+ CIFS_MOUNT_SERVER_INUM | CIFS_MOUNT_DIRECT_IO | \
+ CIFS_MOUNT_NO_XATTR | CIFS_MOUNT_MAP_SPECIAL_CHR | \
+ CIFS_MOUNT_MAP_SFM_CHR | \
+ CIFS_MOUNT_UNX_EMUL | CIFS_MOUNT_NO_BRL | \
+ CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_OVERR_UID | \
+ CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \
+ CIFS_MOUNT_NOPOSIXBRL | CIFS_MOUNT_NOSSYNC | \
+ CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \
+ CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \
+ CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \
+ CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \
+ CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID | \
+ CIFS_MOUNT_RO_CACHE | CIFS_MOUNT_RW_CACHE)
+
+/**
+ * Generic VFS superblock mount flags (s_flags) to consider when
+ * trying to reuse existing superblock for a new mount
+ */
+#define CIFS_MS_MASK (SB_RDONLY | SB_MANDLOCK | SB_NOEXEC | SB_NOSUID | \
+ SB_NODEV | SB_SYNCHRONOUS)
+
+struct cifs_mnt_data {
+ struct cifs_sb_info *cifs_sb;
+ struct smb3_fs_context *ctx;
+ int flags;
+};
+
+static inline unsigned int
+get_rfc1002_length(void *buf)
+{
+ return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
+}
+
+static inline void
+inc_rfc1001_len(void *buf, int count)
+{
+ be32_add_cpu((__be32 *)buf, count);
+}
+
+struct TCP_Server_Info {
+ struct list_head tcp_ses_list;
+ struct list_head smb_ses_list;
+ spinlock_t srv_lock; /* protect anything here that is not protected */
+ __u64 conn_id; /* connection identifier (useful for debugging) */
+ int srv_count; /* reference counter */
+ /* 15 character server name + 0x20 16th byte indicating type = srv */
+ char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
+ struct smb_version_operations *ops;
+ struct smb_version_values *vals;
+ /* updates to tcpStatus protected by cifs_tcp_ses_lock */
+ enum statusEnum tcpStatus; /* what we think the status is */
+ char *hostname; /* hostname portion of UNC string */
+ struct socket *ssocket;
+ struct sockaddr_storage dstaddr;
+ struct sockaddr_storage srcaddr; /* locally bind to this IP */
+#ifdef CONFIG_NET_NS
+ struct net *net;
+#endif
+ wait_queue_head_t response_q;
+ wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
+ spinlock_t mid_lock; /* protect mid queue and it's entries */
+ struct list_head pending_mid_q;
+ bool noblocksnd; /* use blocking sendmsg */
+ bool noautotune; /* do not autotune send buf sizes */
+ bool nosharesock;
+ bool tcp_nodelay;
+ unsigned int credits; /* send no more requests at once */
+ unsigned int max_credits; /* can override large 32000 default at mnt */
+ unsigned int in_flight; /* number of requests on the wire to server */
+ unsigned int max_in_flight; /* max number of requests that were on wire */
+ spinlock_t req_lock; /* protect the two values above */
+ struct mutex _srv_mutex;
+ unsigned int nofs_flag;
+ struct task_struct *tsk;
+ char server_GUID[16];
+ __u16 sec_mode;
+ bool sign; /* is signing enabled on this connection? */
+ bool ignore_signature:1; /* skip validation of signatures in SMB2/3 rsp */
+ bool session_estab; /* mark when very first sess is established */
+ int echo_credits; /* echo reserved slots */
+ int oplock_credits; /* oplock break reserved slots */
+ bool echoes:1; /* enable echoes */
+ __u8 client_guid[SMB2_CLIENT_GUID_SIZE]; /* Client GUID */
+ u16 dialect; /* dialect index that server chose */
+ bool oplocks:1; /* enable oplocks */
+ unsigned int maxReq; /* Clients should submit no more */
+ /* than maxReq distinct unanswered SMBs to the server when using */
+ /* multiplexed reads or writes (for SMB1/CIFS only, not SMB2/SMB3) */
+ unsigned int maxBuf; /* maxBuf specifies the maximum */
+ /* message size the server can send or receive for non-raw SMBs */
+ /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */
+ /* when socket is setup (and during reconnect) before NegProt sent */
+ unsigned int max_rw; /* maxRw specifies the maximum */
+ /* message size the server can send or receive for */
+ /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
+ unsigned int capabilities; /* selective disabling of caps by smb sess */
+ int timeAdj; /* Adjust for difference in server time zone in sec */
+ __u64 CurrentMid; /* multiplex id - rotating counter, protected by GlobalMid_Lock */
+ char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
+ /* 16th byte of RFC1001 workstation name is always null */
+ char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
+ __u32 sequence_number; /* for signing, protected by srv_mutex */
+ __u32 reconnect_instance; /* incremented on each reconnect */
+ struct session_key session_key;
+ unsigned long lstrp; /* when we got last response from this server */
+ struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */
+#define CIFS_NEGFLAVOR_UNENCAP 1 /* wct == 17, but no ext_sec */
+#define CIFS_NEGFLAVOR_EXTENDED 2 /* wct == 17, ext_sec bit set */
+ char negflavor; /* NEGOTIATE response flavor */
+ /* extended security flavors that server supports */
+ bool sec_ntlmssp; /* supports NTLMSSP */
+ bool sec_kerberosu2u; /* supports U2U Kerberos */
+ bool sec_kerberos; /* supports plain Kerberos */
+ bool sec_mskerberos; /* supports legacy MS Kerberos */
+ bool large_buf; /* is current buffer large? */
+ /* use SMBD connection instead of socket */
+ bool rdma;
+ /* point to the SMBD connection if RDMA is used instead of socket */
+ struct smbd_connection *smbd_conn;
+ struct delayed_work echo; /* echo ping workqueue job */
+ struct delayed_work resolve; /* dns resolution workqueue job */
+ char *smallbuf; /* pointer to current "small" buffer */
+ char *bigbuf; /* pointer to current "big" buffer */
+ /* Total size of this PDU. Only valid from cifs_demultiplex_thread */
+ unsigned int pdu_size;
+ unsigned int total_read; /* total amount of data read in this pass */
+ atomic_t in_send; /* requests trying to send */
+ atomic_t num_waiters; /* blocked waiting to get in sendrecv */
+#ifdef CONFIG_CIFS_STATS2
+ atomic_t num_cmds[NUMBER_OF_SMB2_COMMANDS]; /* total requests by cmd */
+ atomic_t smb2slowcmd[NUMBER_OF_SMB2_COMMANDS]; /* count resps > 1 sec */
+ __u64 time_per_cmd[NUMBER_OF_SMB2_COMMANDS]; /* total time per cmd */
+ __u32 slowest_cmd[NUMBER_OF_SMB2_COMMANDS];
+ __u32 fastest_cmd[NUMBER_OF_SMB2_COMMANDS];
+#endif /* STATS2 */
+ unsigned int max_read;
+ unsigned int max_write;
+ unsigned int min_offload;
+ __le16 compress_algorithm;
+ __u16 signing_algorithm;
+ __le16 cipher_type;
+ /* save initital negprot hash */
+ __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
+ bool signing_negotiated; /* true if valid signing context rcvd from server */
+ bool posix_ext_supported;
+ struct delayed_work reconnect; /* reconnect workqueue job */
+ struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
+ unsigned long echo_interval;
+
+ /*
+ * Number of targets available for reconnect. The more targets
+ * the more tasks have to wait to let the demultiplex thread
+ * reconnect.
+ */
+ int nr_targets;
+ bool noblockcnt; /* use non-blocking connect() */
+
+ /*
+ * If this is a session channel,
+ * primary_server holds the ref-counted
+ * pointer to primary channel connection for the session.
+ */
+#define CIFS_SERVER_IS_CHAN(server) (!!(server)->primary_server)
+ struct TCP_Server_Info *primary_server;
+
+#ifdef CONFIG_CIFS_SWN_UPCALL
+ bool use_swn_dstaddr;
+ struct sockaddr_storage swn_dstaddr;
+#endif
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ bool is_dfs_conn; /* if a dfs connection */
+ struct mutex refpath_lock; /* protects leaf_fullpath */
+ /*
+ * Canonical DFS full paths that were used to chase referrals in mount and reconnect.
+ *
+ * origin_fullpath: first or original referral path
+ * leaf_fullpath: last referral path (might be changed due to nested links in reconnect)
+ *
+ * current_fullpath: pointer to either origin_fullpath or leaf_fullpath
+ * NOTE: cannot be accessed outside cifs_reconnect() and smb2_reconnect()
+ *
+ * format: \\HOST\SHARE\[OPTIONAL PATH]
+ */
+ char *origin_fullpath, *leaf_fullpath, *current_fullpath;
+#endif
+};
+
+static inline bool is_smb1(struct TCP_Server_Info *server)
+{
+ return HEADER_PREAMBLE_SIZE(server) != 0;
+}
+
+static inline void cifs_server_lock(struct TCP_Server_Info *server)
+{
+ unsigned int nofs_flag = memalloc_nofs_save();
+
+ mutex_lock(&server->_srv_mutex);
+ server->nofs_flag = nofs_flag;
+}
+
+static inline void cifs_server_unlock(struct TCP_Server_Info *server)
+{
+ unsigned int nofs_flag = server->nofs_flag;
+
+ mutex_unlock(&server->_srv_mutex);
+ memalloc_nofs_restore(nofs_flag);
+}
+
+struct cifs_credits {
+ unsigned int value;
+ unsigned int instance;
+};
+
+static inline unsigned int
+in_flight(struct TCP_Server_Info *server)
+{
+ unsigned int num;
+ spin_lock(&server->req_lock);
+ num = server->in_flight;
+ spin_unlock(&server->req_lock);
+ return num;
+}
+
+static inline bool
+has_credits(struct TCP_Server_Info *server, int *credits, int num_credits)
+{
+ int num;
+ spin_lock(&server->req_lock);
+ num = *credits;
+ spin_unlock(&server->req_lock);
+ return num >= num_credits;
+}
+
+static inline void
+add_credits(struct TCP_Server_Info *server, const struct cifs_credits *credits,
+ const int optype)
+{
+ server->ops->add_credits(server, credits, optype);
+}
+
+static inline void
+add_credits_and_wake_if(struct TCP_Server_Info *server,
+ const struct cifs_credits *credits, const int optype)
+{
+ if (credits->value) {
+ server->ops->add_credits(server, credits, optype);
+ wake_up(&server->request_q);
+ }
+}
+
+static inline void
+set_credits(struct TCP_Server_Info *server, const int val)
+{
+ server->ops->set_credits(server, val);
+}
+
+static inline int
+adjust_credits(struct TCP_Server_Info *server, struct cifs_credits *credits,
+ const unsigned int payload_size)
+{
+ return server->ops->adjust_credits ?
+ server->ops->adjust_credits(server, credits, payload_size) : 0;
+}
+
+static inline __le64
+get_next_mid64(struct TCP_Server_Info *server)
+{
+ return cpu_to_le64(server->ops->get_next_mid(server));
+}
+
+static inline __le16
+get_next_mid(struct TCP_Server_Info *server)
+{
+ __u16 mid = server->ops->get_next_mid(server);
+ /*
+ * The value in the SMB header should be little endian for easy
+ * on-the-wire decoding.
+ */
+ return cpu_to_le16(mid);
+}
+
+static inline void
+revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
+{
+ if (server->ops->revert_current_mid)
+ server->ops->revert_current_mid(server, val);
+}
+
+static inline void
+revert_current_mid_from_hdr(struct TCP_Server_Info *server,
+ const struct smb2_hdr *shdr)
+{
+ unsigned int num = le16_to_cpu(shdr->CreditCharge);
+
+ return revert_current_mid(server, num > 0 ? num : 1);
+}
+
+static inline __u16
+get_mid(const struct smb_hdr *smb)
+{
+ return le16_to_cpu(smb->Mid);
+}
+
+static inline bool
+compare_mid(__u16 mid, const struct smb_hdr *smb)
+{
+ return mid == le16_to_cpu(smb->Mid);
+}
+
+/*
+ * When the server supports very large reads and writes via POSIX extensions,
+ * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
+ * including the RFC1001 length.
+ *
+ * Note that this might make for "interesting" allocation problems during
+ * writeback however as we have to allocate an array of pointers for the
+ * pages. A 16M write means ~32kb page array with PAGE_SIZE == 4096.
+ *
+ * For reads, there is a similar problem as we need to allocate an array
+ * of kvecs to handle the receive, though that should only need to be done
+ * once.
+ */
+#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
+#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
+
+/*
+ * When the server doesn't allow large posix writes, only allow a rsize/wsize
+ * of 2^17-1 minus the size of the call header. That allows for a read or
+ * write up to the maximum size described by RFC1002.
+ */
+#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
+#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
+
+#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
+
+/*
+ * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
+ * those values when posix extensions aren't in force. In actuality here, we
+ * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
+ * to be ok with the extra byte even though Windows doesn't send writes that
+ * are that large.
+ *
+ * Citation:
+ *
+ * https://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
+ */
+#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
+#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
+
+/*
+ * Macros to allow the TCP_Server_Info->net field and related code to drop out
+ * when CONFIG_NET_NS isn't set.
+ */
+
+#ifdef CONFIG_NET_NS
+
+static inline struct net *cifs_net_ns(struct TCP_Server_Info *srv)
+{
+ return srv->net;
+}
+
+static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net)
+{
+ srv->net = net;
+}
+
+#else
+
+static inline struct net *cifs_net_ns(struct TCP_Server_Info *srv)
+{
+ return &init_net;
+}
+
+static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net)
+{
+}
+
+#endif
+
+struct cifs_server_iface {
+ struct list_head iface_head;
+ struct kref refcount;
+ size_t speed;
+ unsigned int rdma_capable : 1;
+ unsigned int rss_capable : 1;
+ unsigned int is_active : 1; /* unset if non existent */
+ struct sockaddr_storage sockaddr;
+};
+
+/* release iface when last ref is dropped */
+static inline void
+release_iface(struct kref *ref)
+{
+ struct cifs_server_iface *iface = container_of(ref,
+ struct cifs_server_iface,
+ refcount);
+ list_del_init(&iface->iface_head);
+ kfree(iface);
+}
+
+/*
+ * compare two interfaces a and b
+ * return 0 if everything matches.
+ * return 1 if a has higher link speed, or rdma capable, or rss capable
+ * return -1 otherwise.
+ */
+static inline int
+iface_cmp(struct cifs_server_iface *a, struct cifs_server_iface *b)
+{
+ int cmp_ret = 0;
+
+ WARN_ON(!a || !b);
+ if (a->speed == b->speed) {
+ if (a->rdma_capable == b->rdma_capable) {
+ if (a->rss_capable == b->rss_capable) {
+ cmp_ret = memcmp(&a->sockaddr, &b->sockaddr,
+ sizeof(a->sockaddr));
+ if (!cmp_ret)
+ return 0;
+ else if (cmp_ret > 0)
+ return 1;
+ else
+ return -1;
+ } else if (a->rss_capable > b->rss_capable)
+ return 1;
+ else
+ return -1;
+ } else if (a->rdma_capable > b->rdma_capable)
+ return 1;
+ else
+ return -1;
+ } else if (a->speed > b->speed)
+ return 1;
+ else
+ return -1;
+}
+
+struct cifs_chan {
+ unsigned int in_reconnect : 1; /* if session setup in progress for this channel */
+ struct TCP_Server_Info *server;
+ struct cifs_server_iface *iface; /* interface in use */
+ __u8 signkey[SMB3_SIGN_KEY_SIZE];
+};
+
+/*
+ * Session structure. One of these for each uid session with a particular host
+ */
+struct cifs_ses {
+ struct list_head smb_ses_list;
+ struct list_head rlist; /* reconnect list */
+ struct list_head tcon_list;
+ struct cifs_tcon *tcon_ipc;
+ spinlock_t ses_lock; /* protect anything here that is not protected */
+ struct mutex session_mutex;
+ struct TCP_Server_Info *server; /* pointer to server info */
+ int ses_count; /* reference counter */
+ enum ses_status_enum ses_status; /* updates protected by cifs_tcp_ses_lock */
+ unsigned overrideSecFlg; /* if non-zero override global sec flags */
+ char *serverOS; /* name of operating system underlying server */
+ char *serverNOS; /* name of network operating system of server */
+ char *serverDomain; /* security realm of server */
+ __u64 Suid; /* remote smb uid */
+ kuid_t linux_uid; /* overriding owner of files on the mount */
+ kuid_t cred_uid; /* owner of credentials */
+ unsigned int capabilities;
+ char ip_addr[INET6_ADDRSTRLEN + 1]; /* Max ipv6 (or v4) addr string len */
+ char *user_name; /* must not be null except during init of sess
+ and after mount option parsing we fill it */
+ char *domainName;
+ char *password;
+ char workstation_name[CIFS_MAX_WORKSTATION_LEN];
+ struct session_key auth_key;
+ struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
+ enum securityEnum sectype; /* what security flavor was specified? */
+ bool sign; /* is signing required? */
+ bool domainAuto:1;
+ __u16 session_flags;
+ __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
+ __u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
+ __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
+ __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
+
+ /*
+ * Network interfaces available on the server this session is
+ * connected to.
+ *
+ * Other channels can be opened by connecting and binding this
+ * session to interfaces from this list.
+ *
+ * iface_lock should be taken when accessing any of these fields
+ */
+ spinlock_t iface_lock;
+ /* ========= begin: protected by iface_lock ======== */
+ struct list_head iface_list;
+ size_t iface_count;
+ unsigned long iface_last_update; /* jiffies */
+ /* ========= end: protected by iface_lock ======== */
+
+ spinlock_t chan_lock;
+ /* ========= begin: protected by chan_lock ======== */
+#define CIFS_MAX_CHANNELS 16
+#define CIFS_ALL_CHANNELS_SET(ses) \
+ ((1UL << (ses)->chan_count) - 1)
+#define CIFS_ALL_CHANS_GOOD(ses) \
+ (!(ses)->chans_need_reconnect)
+#define CIFS_ALL_CHANS_NEED_RECONNECT(ses) \
+ ((ses)->chans_need_reconnect == CIFS_ALL_CHANNELS_SET(ses))
+#define CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses) \
+ ((ses)->chans_need_reconnect = CIFS_ALL_CHANNELS_SET(ses))
+#define CIFS_CHAN_NEEDS_RECONNECT(ses, index) \
+ test_bit((index), &(ses)->chans_need_reconnect)
+#define CIFS_CHAN_IN_RECONNECT(ses, index) \
+ ((ses)->chans[(index)].in_reconnect)
+
+ struct cifs_chan chans[CIFS_MAX_CHANNELS];
+ size_t chan_count;
+ size_t chan_max;
+ atomic_t chan_seq; /* round robin state */
+
+ /*
+ * chans_need_reconnect is a bitmap indicating which of the channels
+ * under this smb session needs to be reconnected.
+ * If not multichannel session, only one bit will be used.
+ *
+ * We will ask for sess and tcon reconnection only if all the
+ * channels are marked for needing reconnection. This will
+ * enable the sessions on top to continue to live till any
+ * of the channels below are active.
+ */
+ unsigned long chans_need_reconnect;
+ /* ========= end: protected by chan_lock ======== */
+};
+
+static inline bool
+cap_unix(struct cifs_ses *ses)
+{
+ return ses->server->vals->cap_unix & ses->capabilities;
+}
+
+/*
+ * common struct for holding inode info when searching for or updating an
+ * inode with new info
+ */
+
+#define CIFS_FATTR_DFS_REFERRAL 0x1
+#define CIFS_FATTR_DELETE_PENDING 0x2
+#define CIFS_FATTR_NEED_REVAL 0x4
+#define CIFS_FATTR_INO_COLLISION 0x8
+#define CIFS_FATTR_UNKNOWN_NLINK 0x10
+#define CIFS_FATTR_FAKE_ROOT_INO 0x20
+
+struct cifs_fattr {
+ u32 cf_flags;
+ u32 cf_cifsattrs;
+ u64 cf_uniqueid;
+ u64 cf_eof;
+ u64 cf_bytes;
+ u64 cf_createtime;
+ kuid_t cf_uid;
+ kgid_t cf_gid;
+ umode_t cf_mode;
+ dev_t cf_rdev;
+ unsigned int cf_nlink;
+ unsigned int cf_dtype;
+ struct timespec64 cf_atime;
+ struct timespec64 cf_mtime;
+ struct timespec64 cf_ctime;
+ u32 cf_cifstag;
+ char *cf_symlink_target;
+};
+
+/*
+ * there is one of these for each connection to a resource on a particular
+ * session
+ */
+struct cifs_tcon {
+ struct list_head tcon_list;
+ int tc_count;
+ struct list_head rlist; /* reconnect list */
+ spinlock_t tc_lock; /* protect anything here that is not protected */
+ atomic_t num_local_opens; /* num of all opens including disconnected */
+ atomic_t num_remote_opens; /* num of all network opens on server */
+ struct list_head openFileList;
+ spinlock_t open_file_lock; /* protects list above */
+ struct cifs_ses *ses; /* pointer to session associated with */
+ char tree_name[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
+ char *nativeFileSystem;
+ char *password; /* for share-level security */
+ __u32 tid; /* The 4 byte tree id */
+ __u16 Flags; /* optional support bits */
+ enum tid_status_enum status;
+ atomic_t num_smbs_sent;
+ union {
+ struct {
+ atomic_t num_writes;
+ atomic_t num_reads;
+ atomic_t num_flushes;
+ atomic_t num_oplock_brks;
+ atomic_t num_opens;
+ atomic_t num_closes;
+ atomic_t num_deletes;
+ atomic_t num_mkdirs;
+ atomic_t num_posixopens;
+ atomic_t num_posixmkdirs;
+ atomic_t num_rmdirs;
+ atomic_t num_renames;
+ atomic_t num_t2renames;
+ atomic_t num_ffirst;
+ atomic_t num_fnext;
+ atomic_t num_fclose;
+ atomic_t num_hardlinks;
+ atomic_t num_symlinks;
+ atomic_t num_locks;
+ atomic_t num_acl_get;
+ atomic_t num_acl_set;
+ } cifs_stats;
+ struct {
+ atomic_t smb2_com_sent[NUMBER_OF_SMB2_COMMANDS];
+ atomic_t smb2_com_failed[NUMBER_OF_SMB2_COMMANDS];
+ } smb2_stats;
+ } stats;
+ __u64 bytes_read;
+ __u64 bytes_written;
+ spinlock_t stat_lock; /* protects the two fields above */
+ FILE_SYSTEM_DEVICE_INFO fsDevInfo;
+ FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
+ FILE_SYSTEM_UNIX_INFO fsUnixInfo;
+ bool ipc:1; /* set if connection to IPC$ share (always also pipe) */
+ bool pipe:1; /* set if connection to pipe share */
+ bool print:1; /* set if connection to printer share */
+ bool retry:1;
+ bool nocase:1;
+ bool nohandlecache:1; /* if strange server resource prob can turn off */
+ bool nodelete:1;
+ bool seal:1; /* transport encryption for this mounted share */
+ bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
+ for this mount even if server would support */
+ bool posix_extensions; /* if true SMB3.11 posix extensions enabled */
+ bool local_lease:1; /* check leases (only) on local system not remote */
+ bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
+ bool broken_sparse_sup; /* if server or share does not support sparse */
+ bool need_reconnect:1; /* connection reset, tid now invalid */
+ bool need_reopen_files:1; /* need to reopen tcon file handles */
+ bool use_resilient:1; /* use resilient instead of durable handles */
+ bool use_persistent:1; /* use persistent instead of durable handles */
+ bool no_lease:1; /* Do not request leases on files or directories */
+ bool use_witness:1; /* use witness protocol */
+ __le32 capabilities;
+ __u32 share_flags;
+ __u32 maximal_access;
+ __u32 vol_serial_number;
+ __le64 vol_create_time;
+ __u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */
+ __u32 handle_timeout; /* persistent and durable handle timeout in ms */
+ __u32 ss_flags; /* sector size flags */
+ __u32 perf_sector_size; /* best sector size for perf */
+ __u32 max_chunks;
+ __u32 max_bytes_chunk;
+ __u32 max_bytes_copy;
+#ifdef CONFIG_CIFS_FSCACHE
+ u64 resource_id; /* server resource id */
+ struct fscache_volume *fscache; /* cookie for share */
+#endif
+ struct list_head pending_opens; /* list of incomplete opens */
+ struct cached_fids *cfids;
+ /* BB add field for back pointer to sb struct(s)? */
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ struct list_head ulist; /* cache update list */
+#endif
+ struct delayed_work query_interfaces; /* query interfaces workqueue job */
+};
+
+/*
+ * This is a refcounted and timestamped container for a tcon pointer. The
+ * container holds a tcon reference. It is considered safe to free one of
+ * these when the tl_count goes to 0. The tl_time is the time of the last
+ * "get" on the container.
+ */
+struct tcon_link {
+ struct rb_node tl_rbnode;
+ kuid_t tl_uid;
+ unsigned long tl_flags;
+#define TCON_LINK_MASTER 0
+#define TCON_LINK_PENDING 1
+#define TCON_LINK_IN_TREE 2
+ unsigned long tl_time;
+ atomic_t tl_count;
+ struct cifs_tcon *tl_tcon;
+};
+
+extern struct tcon_link *cifs_sb_tlink(struct cifs_sb_info *cifs_sb);
+extern void smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst);
+
+static inline struct cifs_tcon *
+tlink_tcon(struct tcon_link *tlink)
+{
+ return tlink->tl_tcon;
+}
+
+static inline struct tcon_link *
+cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
+{
+ return cifs_sb->master_tlink;
+}
+
+extern void cifs_put_tlink(struct tcon_link *tlink);
+
+static inline struct tcon_link *
+cifs_get_tlink(struct tcon_link *tlink)
+{
+ if (tlink && !IS_ERR(tlink))
+ atomic_inc(&tlink->tl_count);
+ return tlink;
+}
+
+/* This function is always expected to succeed */
+extern struct cifs_tcon *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb);
+
+#define CIFS_OPLOCK_NO_CHANGE 0xfe
+
+struct cifs_pending_open {
+ struct list_head olist;
+ struct tcon_link *tlink;
+ __u8 lease_key[16];
+ __u32 oplock;
+};
+
+struct cifs_deferred_close {
+ struct list_head dlist;
+ struct tcon_link *tlink;
+ __u16 netfid;
+ __u64 persistent_fid;
+ __u64 volatile_fid;
+};
+
+/*
+ * This info hangs off the cifsFileInfo structure, pointed to by llist.
+ * This is used to track byte stream locks on the file
+ */
+struct cifsLockInfo {
+ struct list_head llist; /* pointer to next cifsLockInfo */
+ struct list_head blist; /* pointer to locks blocked on this */
+ wait_queue_head_t block_q;
+ __u64 offset;
+ __u64 length;
+ __u32 pid;
+ __u16 type;
+ __u16 flags;
+};
+
+/*
+ * One of these for each open instance of a file
+ */
+struct cifs_search_info {
+ loff_t index_of_last_entry;
+ __u16 entries_in_buffer;
+ __u16 info_level;
+ __u32 resume_key;
+ char *ntwrk_buf_start;
+ char *srch_entries_start;
+ char *last_entry;
+ const char *presume_name;
+ unsigned int resume_name_len;
+ bool endOfSearch:1;
+ bool emptyDir:1;
+ bool unicode:1;
+ bool smallBuf:1; /* so we know which buf_release function to call */
+};
+
+#define ACL_NO_MODE ((umode_t)(-1))
+struct cifs_open_parms {
+ struct cifs_tcon *tcon;
+ struct cifs_sb_info *cifs_sb;
+ int disposition;
+ int desired_access;
+ int create_options;
+ const char *path;
+ struct cifs_fid *fid;
+ umode_t mode;
+ bool reconnect:1;
+};
+
+struct cifs_fid {
+ __u16 netfid;
+ __u64 persistent_fid; /* persist file id for smb2 */
+ __u64 volatile_fid; /* volatile file id for smb2 */
+ __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */
+ __u8 create_guid[16];
+ __u32 access;
+ struct cifs_pending_open *pending_open;
+ unsigned int epoch;
+#ifdef CONFIG_CIFS_DEBUG2
+ __u64 mid;
+#endif /* CIFS_DEBUG2 */
+ bool purge_cache;
+};
+
+struct cifs_fid_locks {
+ struct list_head llist;
+ struct cifsFileInfo *cfile; /* fid that owns locks */
+ struct list_head locks; /* locks held by fid above */
+};
+
+struct cifsFileInfo {
+ /* following two lists are protected by tcon->open_file_lock */
+ struct list_head tlist; /* pointer to next fid owned by tcon */
+ struct list_head flist; /* next fid (file instance) for this inode */
+ /* lock list below protected by cifsi->lock_sem */
+ struct cifs_fid_locks *llist; /* brlocks held by this fid */
+ kuid_t uid; /* allows finding which FileInfo structure */
+ __u32 pid; /* process id who opened file */
+ struct cifs_fid fid; /* file id from remote */
+ struct list_head rlist; /* reconnect list */
+ /* BB add lock scope info here if needed */ ;
+ /* lock scope id (0 if none) */
+ struct dentry *dentry;
+ struct tcon_link *tlink;
+ unsigned int f_flags;
+ bool invalidHandle:1; /* file closed via session abend */
+ bool swapfile:1;
+ bool oplock_break_cancelled:1;
+ unsigned int oplock_epoch; /* epoch from the lease break */
+ __u32 oplock_level; /* oplock/lease level from the lease break */
+ int count;
+ spinlock_t file_info_lock; /* protects four flag/count fields above */
+ struct mutex fh_mutex; /* prevents reopen race after dead ses*/
+ struct cifs_search_info srch_inf;
+ struct work_struct oplock_break; /* work for oplock breaks */
+ struct work_struct put; /* work for the final part of _put */
+ struct delayed_work deferred;
+ bool deferred_close_scheduled; /* Flag to indicate close is scheduled */
+ char *symlink_target;
+};
+
+struct cifs_io_parms {
+ __u16 netfid;
+ __u64 persistent_fid; /* persist file id for smb2 */
+ __u64 volatile_fid; /* volatile file id for smb2 */
+ __u32 pid;
+ __u64 offset;
+ unsigned int length;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+};
+
+struct cifs_aio_ctx {
+ struct kref refcount;
+ struct list_head list;
+ struct mutex aio_mutex;
+ struct completion done;
+ struct iov_iter iter;
+ struct kiocb *iocb;
+ struct cifsFileInfo *cfile;
+ struct bio_vec *bv;
+ loff_t pos;
+ unsigned int npages;
+ ssize_t rc;
+ unsigned int len;
+ unsigned int total_len;
+ bool should_dirty;
+ /*
+ * Indicates if this aio_ctx is for direct_io,
+ * If yes, iter is a copy of the user passed iov_iter
+ */
+ bool direct_io;
+};
+
+/* asynchronous read support */
+struct cifs_readdata {
+ struct kref refcount;
+ struct list_head list;
+ struct completion done;
+ struct cifsFileInfo *cfile;
+ struct address_space *mapping;
+ struct cifs_aio_ctx *ctx;
+ __u64 offset;
+ unsigned int bytes;
+ unsigned int got_bytes;
+ pid_t pid;
+ int result;
+ struct work_struct work;
+ int (*read_into_pages)(struct TCP_Server_Info *server,
+ struct cifs_readdata *rdata,
+ unsigned int len);
+ int (*copy_into_pages)(struct TCP_Server_Info *server,
+ struct cifs_readdata *rdata,
+ struct iov_iter *iter);
+ struct kvec iov[2];
+ struct TCP_Server_Info *server;
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ struct smbd_mr *mr;
+#endif
+ unsigned int pagesz;
+ unsigned int page_offset;
+ unsigned int tailsz;
+ struct cifs_credits credits;
+ unsigned int nr_pages;
+ struct page **pages;
+};
+
+/* asynchronous write support */
+struct cifs_writedata {
+ struct kref refcount;
+ struct list_head list;
+ struct completion done;
+ enum writeback_sync_modes sync_mode;
+ struct work_struct work;
+ struct cifsFileInfo *cfile;
+ struct cifs_aio_ctx *ctx;
+ __u64 offset;
+ pid_t pid;
+ unsigned int bytes;
+ int result;
+ struct TCP_Server_Info *server;
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ struct smbd_mr *mr;
+#endif
+ unsigned int pagesz;
+ unsigned int page_offset;
+ unsigned int tailsz;
+ struct cifs_credits credits;
+ unsigned int nr_pages;
+ struct page **pages;
+};
+
+/*
+ * Take a reference on the file private data. Must be called with
+ * cfile->file_info_lock held.
+ */
+static inline void
+cifsFileInfo_get_locked(struct cifsFileInfo *cifs_file)
+{
+ ++cifs_file->count;
+}
+
+struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file);
+void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_hdlr,
+ bool offload);
+void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
+
+#define CIFS_CACHE_READ_FLG 1
+#define CIFS_CACHE_HANDLE_FLG 2
+#define CIFS_CACHE_RH_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_HANDLE_FLG)
+#define CIFS_CACHE_WRITE_FLG 4
+#define CIFS_CACHE_RW_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG)
+#define CIFS_CACHE_RHW_FLG (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG)
+
+#define CIFS_CACHE_READ(cinode) ((cinode->oplock & CIFS_CACHE_READ_FLG) || (CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE))
+#define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG)
+#define CIFS_CACHE_WRITE(cinode) ((cinode->oplock & CIFS_CACHE_WRITE_FLG) || (CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE))
+
+/*
+ * One of these for each file inode
+ */
+
+struct cifsInodeInfo {
+ struct netfs_inode netfs; /* Netfslib context and vfs inode */
+ bool can_cache_brlcks;
+ struct list_head llist; /* locks helb by this inode */
+ /*
+ * NOTE: Some code paths call down_read(lock_sem) twice, so
+ * we must always use cifs_down_write() instead of down_write()
+ * for this semaphore to avoid deadlocks.
+ */
+ struct rw_semaphore lock_sem; /* protect the fields above */
+ /* BB add in lists for dirty pages i.e. write caching info for oplock */
+ struct list_head openFileList;
+ spinlock_t open_file_lock; /* protects openFileList */
+ __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
+ unsigned int oplock; /* oplock/lease level we have */
+ unsigned int epoch; /* used to track lease state changes */
+#define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */
+#define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */
+#define CIFS_INODE_FLAG_UNUSED (2) /* Unused flag */
+#define CIFS_INO_DELETE_PENDING (3) /* delete pending on server */
+#define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */
+#define CIFS_INO_LOCK (5) /* lock bit for synchronization */
+#define CIFS_INO_MODIFIED_ATTR (6) /* Indicate change in mtime/ctime */
+#define CIFS_INO_CLOSE_ON_LOCK (7) /* Not to defer the close when lock is set */
+ unsigned long flags;
+ spinlock_t writers_lock;
+ unsigned int writers; /* Number of writers on this inode */
+ unsigned long time; /* jiffies of last update of inode */
+ u64 server_eof; /* current file size on server -- protected by i_lock */
+ u64 uniqueid; /* server inode number */
+ u64 createtime; /* creation time on server */
+ __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for this inode */
+ struct list_head deferred_closes; /* list of deferred closes */
+ spinlock_t deferred_lock; /* protection on deferred list */
+ bool lease_granted; /* Flag to indicate whether lease or oplock is granted. */
+ char *symlink_target;
+};
+
+static inline struct cifsInodeInfo *
+CIFS_I(struct inode *inode)
+{
+ return container_of(inode, struct cifsInodeInfo, netfs.inode);
+}
+
+static inline struct cifs_sb_info *
+CIFS_SB(struct super_block *sb)
+{
+ return sb->s_fs_info;
+}
+
+static inline struct cifs_sb_info *
+CIFS_FILE_SB(struct file *file)
+{
+ return CIFS_SB(file_inode(file)->i_sb);
+}
+
+static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
+{
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+ return '/';
+ else
+ return '\\';
+}
+
+static inline void
+convert_delimiter(char *path, char delim)
+{
+ char old_delim, *pos;
+
+ if (delim == '/')
+ old_delim = '\\';
+ else
+ old_delim = '/';
+
+ pos = path;
+ while ((pos = strchr(pos, old_delim)))
+ *pos = delim;
+}
+
+#define cifs_stats_inc atomic_inc
+
+static inline void cifs_stats_bytes_written(struct cifs_tcon *tcon,
+ unsigned int bytes)
+{
+ if (bytes) {
+ spin_lock(&tcon->stat_lock);
+ tcon->bytes_written += bytes;
+ spin_unlock(&tcon->stat_lock);
+ }
+}
+
+static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon,
+ unsigned int bytes)
+{
+ spin_lock(&tcon->stat_lock);
+ tcon->bytes_read += bytes;
+ spin_unlock(&tcon->stat_lock);
+}
+
+
+/*
+ * This is the prototype for the mid receive function. This function is for
+ * receiving the rest of the SMB frame, starting with the WordCount (which is
+ * just after the MID in struct smb_hdr). Note:
+ *
+ * - This will be called by cifsd, with no locks held.
+ * - The mid will still be on the pending_mid_q.
+ * - mid->resp_buf will point to the current buffer.
+ *
+ * Returns zero on a successful receive, or an error. The receive state in
+ * the TCP_Server_Info will also be updated.
+ */
+typedef int (mid_receive_t)(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid);
+
+/*
+ * This is the prototype for the mid callback function. This is called once the
+ * mid has been received off of the socket. When creating one, take special
+ * care to avoid deadlocks. Things to bear in mind:
+ *
+ * - it will be called by cifsd, with no locks held
+ * - the mid will be removed from any lists
+ */
+typedef void (mid_callback_t)(struct mid_q_entry *mid);
+
+/*
+ * This is the protopyte for mid handle function. This is called once the mid
+ * has been recognized after decryption of the message.
+ */
+typedef int (mid_handle_t)(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid);
+
+/* one of these for every pending CIFS request to the server */
+struct mid_q_entry {
+ struct list_head qhead; /* mids waiting on reply from this server */
+ struct kref refcount;
+ struct TCP_Server_Info *server; /* server corresponding to this mid */
+ __u64 mid; /* multiplex id */
+ __u16 credits; /* number of credits consumed by this mid */
+ __u16 credits_received; /* number of credits from the response */
+ __u32 pid; /* process id */
+ __u32 sequence_number; /* for CIFS signing */
+ unsigned long when_alloc; /* when mid was created */
+#ifdef CONFIG_CIFS_STATS2
+ unsigned long when_sent; /* time when smb send finished */
+ unsigned long when_received; /* when demux complete (taken off wire) */
+#endif
+ mid_receive_t *receive; /* call receive callback */
+ mid_callback_t *callback; /* call completion callback */
+ mid_handle_t *handle; /* call handle mid callback */
+ void *callback_data; /* general purpose pointer for callback */
+ struct task_struct *creator;
+ void *resp_buf; /* pointer to received SMB header */
+ unsigned int resp_buf_size;
+ int mid_state; /* wish this were enum but can not pass to wait_event */
+ unsigned int mid_flags;
+ __le16 command; /* smb command code */
+ unsigned int optype; /* operation type */
+ bool large_buf:1; /* if valid response, is pointer to large buf */
+ bool multiRsp:1; /* multiple trans2 responses for one request */
+ bool multiEnd:1; /* both received */
+ bool decrypted:1; /* decrypted entry */
+};
+
+struct close_cancelled_open {
+ struct cifs_fid fid;
+ struct cifs_tcon *tcon;
+ struct work_struct work;
+ __u64 mid;
+ __u16 cmd;
+};
+
+/* Make code in transport.c a little cleaner by moving
+ update of optional stats into function below */
+static inline void cifs_in_send_inc(struct TCP_Server_Info *server)
+{
+ atomic_inc(&server->in_send);
+}
+
+static inline void cifs_in_send_dec(struct TCP_Server_Info *server)
+{
+ atomic_dec(&server->in_send);
+}
+
+static inline void cifs_num_waiters_inc(struct TCP_Server_Info *server)
+{
+ atomic_inc(&server->num_waiters);
+}
+
+static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server)
+{
+ atomic_dec(&server->num_waiters);
+}
+
+#ifdef CONFIG_CIFS_STATS2
+static inline void cifs_save_when_sent(struct mid_q_entry *mid)
+{
+ mid->when_sent = jiffies;
+}
+#else
+static inline void cifs_save_when_sent(struct mid_q_entry *mid)
+{
+}
+#endif
+
+/* for pending dnotify requests */
+struct dir_notify_req {
+ struct list_head lhead;
+ __le16 Pid;
+ __le16 PidHigh;
+ __u16 Mid;
+ __u16 Tid;
+ __u16 Uid;
+ __u16 netfid;
+ __u32 filter; /* CompletionFilter (for multishot) */
+ int multishot;
+ struct file *pfile;
+};
+
+struct dfs_info3_param {
+ int flags; /* DFSREF_REFERRAL_SERVER, DFSREF_STORAGE_SERVER*/
+ int path_consumed;
+ int server_type;
+ int ref_flag;
+ char *path_name;
+ char *node_name;
+ int ttl;
+};
+
+struct file_list {
+ struct list_head list;
+ struct cifsFileInfo *cfile;
+};
+
+static inline void free_dfs_info_param(struct dfs_info3_param *param)
+{
+ if (param) {
+ kfree(param->path_name);
+ kfree(param->node_name);
+ }
+}
+
+static inline void free_dfs_info_array(struct dfs_info3_param *param,
+ int number_of_items)
+{
+ int i;
+ if ((number_of_items == 0) || (param == NULL))
+ return;
+ for (i = 0; i < number_of_items; i++) {
+ kfree(param[i].path_name);
+ kfree(param[i].node_name);
+ }
+ kfree(param);
+}
+
+static inline bool is_interrupt_error(int error)
+{
+ switch (error) {
+ case -EINTR:
+ case -ERESTARTSYS:
+ case -ERESTARTNOHAND:
+ case -ERESTARTNOINTR:
+ return true;
+ }
+ return false;
+}
+
+static inline bool is_retryable_error(int error)
+{
+ if (is_interrupt_error(error) || error == -EAGAIN)
+ return true;
+ return false;
+}
+
+
+/* cifs_get_writable_file() flags */
+#define FIND_WR_ANY 0
+#define FIND_WR_FSUID_ONLY 1
+#define FIND_WR_WITH_DELETE 2
+
+#define MID_FREE 0
+#define MID_REQUEST_ALLOCATED 1
+#define MID_REQUEST_SUBMITTED 2
+#define MID_RESPONSE_RECEIVED 4
+#define MID_RETRY_NEEDED 8 /* session closed while this request out */
+#define MID_RESPONSE_MALFORMED 0x10
+#define MID_SHUTDOWN 0x20
+
+/* Flags */
+#define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */
+#define MID_DELETED 2 /* Mid has been dequeued/deleted */
+
+/* Types of response buffer returned from SendReceive2 */
+#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
+#define CIFS_SMALL_BUFFER 1
+#define CIFS_LARGE_BUFFER 2
+#define CIFS_IOVEC 4 /* array of response buffers */
+
+/* Type of Request to SendReceive2 */
+#define CIFS_BLOCKING_OP 1 /* operation can block */
+#define CIFS_NON_BLOCKING 2 /* do not block waiting for credits */
+#define CIFS_TIMEOUT_MASK 0x003 /* only one of above set in req */
+#define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */
+#define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */
+#define CIFS_NO_RSP_BUF 0x040 /* no response buffer required */
+
+/* Type of request operation */
+#define CIFS_ECHO_OP 0x080 /* echo request */
+#define CIFS_OBREAK_OP 0x0100 /* oplock break request */
+#define CIFS_NEG_OP 0x0200 /* negotiate request */
+#define CIFS_CP_CREATE_CLOSE_OP 0x0400 /* compound create+close request */
+/* Lower bitmask values are reserved by others below. */
+#define CIFS_SESS_OP 0x2000 /* session setup request */
+#define CIFS_OP_MASK 0x2780 /* mask request type */
+
+#define CIFS_HAS_CREDITS 0x0400 /* already has credits */
+#define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sending */
+#define CIFS_NO_SRV_RSP 0x1000 /* there is no server response */
+
+/* Security Flags: indicate type of session setup needed */
+#define CIFSSEC_MAY_SIGN 0x00001
+#define CIFSSEC_MAY_NTLMV2 0x00004
+#define CIFSSEC_MAY_KRB5 0x00008
+#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
+#define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */
+
+#define CIFSSEC_MUST_SIGN 0x01001
+/* note that only one of the following can be set so the
+result of setting MUST flags more than once will be to
+require use of the stronger protocol */
+#define CIFSSEC_MUST_NTLMV2 0x04004
+#define CIFSSEC_MUST_KRB5 0x08008
+#ifdef CONFIG_CIFS_UPCALL
+#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
+#else
+#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */
+#endif /* UPCALL */
+#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
+#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */
+
+#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_NTLMSSP)
+#define CIFSSEC_MAX (CIFSSEC_MUST_NTLMV2)
+#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)
+/*
+ *****************************************************************
+ * All constants go here
+ *****************************************************************
+ */
+
+#define UID_HASH (16)
+
+/*
+ * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
+ * following to be declared.
+ */
+
+/****************************************************************************
+ * Here are all the locks (spinlock, mutex, semaphore) in cifs.ko, arranged according
+ * to the locking order. i.e. if two locks are to be held together, the lock that
+ * appears higher in this list needs to be taken before the other.
+ *
+ * If you hold a lock that is lower in this list, and you need to take a higher lock
+ * (or if you think that one of the functions that you're calling may need to), first
+ * drop the lock you hold, pick up the higher lock, then the lower one. This will
+ * ensure that locks are picked up only in one direction in the below table
+ * (top to bottom).
+ *
+ * Also, if you expect a function to be called with a lock held, explicitly document
+ * this in the comments on top of your function definition.
+ *
+ * And also, try to keep the critical sections (lock hold time) to be as minimal as
+ * possible. Blocking / calling other functions with a lock held always increase
+ * the risk of a possible deadlock.
+ *
+ * Following this rule will avoid unnecessary deadlocks, which can get really hard to
+ * debug. Also, any new lock that you introduce, please add to this list in the correct
+ * order.
+ *
+ * Please populate this list whenever you introduce new locks in your changes. Or in
+ * case I've missed some existing locks. Please ensure that it's added in the list
+ * based on the locking order expected.
+ *
+ * =====================================================================================
+ * Lock Protects Initialization fn
+ * =====================================================================================
+ * vol_list_lock
+ * vol_info->ctx_lock vol_info->ctx
+ * cifs_sb_info->tlink_tree_lock cifs_sb_info->tlink_tree cifs_setup_cifs_sb
+ * TCP_Server_Info-> TCP_Server_Info cifs_get_tcp_session
+ * reconnect_mutex
+ * TCP_Server_Info->srv_mutex TCP_Server_Info cifs_get_tcp_session
+ * cifs_ses->session_mutex cifs_ses sesInfoAlloc
+ * cifs_tcon
+ * cifs_tcon->open_file_lock cifs_tcon->openFileList tconInfoAlloc
+ * cifs_tcon->pending_opens
+ * cifs_tcon->stat_lock cifs_tcon->bytes_read tconInfoAlloc
+ * cifs_tcon->bytes_written
+ * cifs_tcp_ses_lock cifs_tcp_ses_list sesInfoAlloc
+ * GlobalMid_Lock GlobalMaxActiveXid init_cifs
+ * GlobalCurrentXid
+ * GlobalTotalActiveXid
+ * TCP_Server_Info->srv_lock (anything in struct not protected by another lock and can change)
+ * TCP_Server_Info->mid_lock TCP_Server_Info->pending_mid_q cifs_get_tcp_session
+ * ->CurrentMid
+ * (any changes in mid_q_entry fields)
+ * TCP_Server_Info->req_lock TCP_Server_Info->in_flight cifs_get_tcp_session
+ * ->credits
+ * ->echo_credits
+ * ->oplock_credits
+ * ->reconnect_instance
+ * cifs_ses->ses_lock (anything that is not protected by another lock and can change)
+ * cifs_ses->iface_lock cifs_ses->iface_list sesInfoAlloc
+ * ->iface_count
+ * ->iface_last_update
+ * cifs_ses->chan_lock cifs_ses->chans
+ * ->chans_need_reconnect
+ * ->chans_in_reconnect
+ * cifs_tcon->tc_lock (anything that is not protected by another lock and can change)
+ * cifsInodeInfo->open_file_lock cifsInodeInfo->openFileList cifs_alloc_inode
+ * cifsInodeInfo->writers_lock cifsInodeInfo->writers cifsInodeInfo_alloc
+ * cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once
+ * ->can_cache_brlcks
+ * cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc
+ * cached_fid->fid_mutex cifs_tcon->crfid tconInfoAlloc
+ * cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo
+ * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
+ * ->invalidHandle initiate_cifs_search
+ * ->oplock_break_cancelled
+ * cifs_aio_ctx->aio_mutex cifs_aio_ctx cifs_aio_ctx_alloc
+ ****************************************************************************/
+
+#ifdef DECLARE_GLOBALS_HERE
+#define GLOBAL_EXTERN
+#else
+#define GLOBAL_EXTERN extern
+#endif
+
+/*
+ * the list of TCP_Server_Info structures, ie each of the sockets
+ * connecting our client to a distinct server (ip address), is
+ * chained together by cifs_tcp_ses_list. The list of all our SMB
+ * sessions (and from that the tree connections) can be found
+ * by iterating over cifs_tcp_ses_list
+ */
+extern struct list_head cifs_tcp_ses_list;
+
+/*
+ * This lock protects the cifs_tcp_ses_list, the list of smb sessions per
+ * tcp session, and the list of tcon's per smb session. It also protects
+ * the reference counters for the server, smb session, and tcon.
+ * generally the locks should be taken in order tcp_ses_lock before
+ * tcon->open_file_lock and that before file->file_info_lock since the
+ * structure order is cifs_socket-->cifs_ses-->cifs_tcon-->cifs_file
+ */
+extern spinlock_t cifs_tcp_ses_lock;
+
+/*
+ * Global transaction id (XID) information
+ */
+extern unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
+extern unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
+extern unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
+extern spinlock_t GlobalMid_Lock; /* protects above & list operations on midQ entries */
+
+/*
+ * Global counters, updated atomically
+ */
+extern atomic_t sesInfoAllocCount;
+extern atomic_t tconInfoAllocCount;
+extern atomic_t tcpSesNextId;
+extern atomic_t tcpSesAllocCount;
+extern atomic_t tcpSesReconnectCount;
+extern atomic_t tconInfoReconnectCount;
+
+/* Various Debug counters */
+extern atomic_t buf_alloc_count; /* current number allocated */
+extern atomic_t small_buf_alloc_count;
+#ifdef CONFIG_CIFS_STATS2
+extern atomic_t total_buf_alloc_count; /* total allocated over all time */
+extern atomic_t total_small_buf_alloc_count;
+extern unsigned int slow_rsp_threshold; /* number of secs before logging */
+#endif
+
+/* Misc globals */
+extern bool enable_oplocks; /* enable or disable oplocks */
+extern bool lookupCacheEnabled;
+extern unsigned int global_secflags; /* if on, session setup sent
+ with more secure ntlmssp2 challenge/resp */
+extern unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
+extern bool enable_gcm_256; /* allow optional negotiate of strongest signing (aes-gcm-256) */
+extern bool require_gcm_256; /* require use of strongest signing (aes-gcm-256) */
+extern bool enable_negotiate_signing; /* request use of faster (GMAC) signing if available */
+extern bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
+extern unsigned int CIFSMaxBufSize; /* max size not including hdr */
+extern unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
+extern unsigned int cifs_min_small; /* min size of small buf pool */
+extern unsigned int cifs_max_pending; /* MAX requests at once to server*/
+extern bool disable_legacy_dialects; /* forbid vers=1.0 and vers=2.0 mounts */
+extern atomic_t mid_count;
+
+void cifs_oplock_break(struct work_struct *work);
+void cifs_queue_oplock_break(struct cifsFileInfo *cfile);
+void smb2_deferred_work_close(struct work_struct *work);
+
+extern const struct slow_work_ops cifs_oplock_break_ops;
+extern struct workqueue_struct *cifsiod_wq;
+extern struct workqueue_struct *decrypt_wq;
+extern struct workqueue_struct *fileinfo_put_wq;
+extern struct workqueue_struct *cifsoplockd_wq;
+extern struct workqueue_struct *deferredclose_wq;
+extern __u32 cifs_lock_secret;
+
+extern mempool_t *cifs_mid_poolp;
+
+/* Operations for different SMB versions */
+#define SMB1_VERSION_STRING "1.0"
+#define SMB20_VERSION_STRING "2.0"
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+extern struct smb_version_operations smb1_operations;
+extern struct smb_version_values smb1_values;
+extern struct smb_version_operations smb20_operations;
+extern struct smb_version_values smb20_values;
+#endif /* CIFS_ALLOW_INSECURE_LEGACY */
+#define SMB21_VERSION_STRING "2.1"
+extern struct smb_version_operations smb21_operations;
+extern struct smb_version_values smb21_values;
+#define SMBDEFAULT_VERSION_STRING "default"
+extern struct smb_version_values smbdefault_values;
+#define SMB3ANY_VERSION_STRING "3"
+extern struct smb_version_values smb3any_values;
+#define SMB30_VERSION_STRING "3.0"
+extern struct smb_version_operations smb30_operations;
+extern struct smb_version_values smb30_values;
+#define SMB302_VERSION_STRING "3.02"
+#define ALT_SMB302_VERSION_STRING "3.0.2"
+/*extern struct smb_version_operations smb302_operations;*/ /* not needed yet */
+extern struct smb_version_values smb302_values;
+#define SMB311_VERSION_STRING "3.1.1"
+#define ALT_SMB311_VERSION_STRING "3.11"
+extern struct smb_version_operations smb311_operations;
+extern struct smb_version_values smb311_values;
+
+static inline char *get_security_type_str(enum securityEnum sectype)
+{
+ switch (sectype) {
+ case RawNTLMSSP:
+ return "RawNTLMSSP";
+ case Kerberos:
+ return "Kerberos";
+ case NTLMv2:
+ return "NTLMv2";
+ default:
+ return "Unknown";
+ }
+}
+
+static inline bool is_smb1_server(struct TCP_Server_Info *server)
+{
+ return strcmp(server->vals->version_string, SMB1_VERSION_STRING) == 0;
+}
+
+static inline bool is_tcon_dfs(struct cifs_tcon *tcon)
+{
+ /*
+ * For SMB1, see MS-CIFS 2.4.55 SMB_COM_TREE_CONNECT_ANDX (0x75) and MS-CIFS 3.3.4.4 DFS
+ * Subsystem Notifies That a Share Is a DFS Share.
+ *
+ * For SMB2+, see MS-SMB2 2.2.10 SMB2 TREE_CONNECT Response and MS-SMB2 3.3.4.14 Server
+ * Application Updates a Share.
+ */
+ if (!tcon || !tcon->ses || !tcon->ses->server)
+ return false;
+ return is_smb1_server(tcon->ses->server) ? tcon->Flags & SMB_SHARE_IS_IN_DFS :
+ tcon->share_flags & (SHI1005_FLAGS_DFS | SHI1005_FLAGS_DFS_ROOT);
+}
+
+static inline bool cifs_is_referral_server(struct cifs_tcon *tcon,
+ const struct dfs_info3_param *ref)
+{
+ /*
+ * Check if all targets are capable of handling DFS referrals as per
+ * MS-DFSC 2.2.4 RESP_GET_DFS_REFERRAL.
+ */
+ return is_tcon_dfs(tcon) || (ref && (ref->flags & DFSREF_REFERRAL_SERVER));
+}
+
+static inline u64 cifs_flock_len(const struct file_lock *fl)
+{
+ return (u64)fl->fl_end - fl->fl_start + 1;
+}
+
+static inline size_t ntlmssp_workstation_name_size(const struct cifs_ses *ses)
+{
+ if (WARN_ON_ONCE(!ses || !ses->server))
+ return 0;
+ /*
+ * Make workstation name no more than 15 chars when using insecure dialects as some legacy
+ * servers do require it during NTLMSSP.
+ */
+ if (ses->server->dialect <= SMB20_PROT_ID)
+ return min_t(size_t, sizeof(ses->workstation_name), RFC1001_NAME_LEN_WITH_NULL);
+ return sizeof(ses->workstation_name);
+}
+
+static inline void move_cifs_info_to_smb2(struct smb2_file_all_info *dst, const FILE_ALL_INFO *src)
+{
+ memcpy(dst, src, (size_t)((u8 *)&src->AccessFlags - (u8 *)src));
+ dst->AccessFlags = src->AccessFlags;
+ dst->CurrentByteOffset = src->CurrentByteOffset;
+ dst->Mode = src->Mode;
+ dst->AlignmentRequirement = src->AlignmentRequirement;
+ dst->FileNameLength = src->FileNameLength;
+}
+
+static inline unsigned int cifs_get_num_sgs(const struct smb_rqst *rqst,
+ int num_rqst,
+ const u8 *sig)
+{
+ unsigned int len, skip;
+ unsigned int nents = 0;
+ unsigned long addr;
+ int i, j;
+
+ /* Assumes the first rqst has a transform header as the first iov.
+ * I.e.
+ * rqst[0].rq_iov[0] is transform header
+ * rqst[0].rq_iov[1+] data to be encrypted/decrypted
+ * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
+ */
+ for (i = 0; i < num_rqst; i++) {
+ /*
+ * The first rqst has a transform header where the
+ * first 20 bytes are not part of the encrypted blob.
+ */
+ for (j = 0; j < rqst[i].rq_nvec; j++) {
+ struct kvec *iov = &rqst[i].rq_iov[j];
+
+ skip = (i == 0) && (j == 0) ? 20 : 0;
+ addr = (unsigned long)iov->iov_base + skip;
+ if (unlikely(is_vmalloc_addr((void *)addr))) {
+ len = iov->iov_len - skip;
+ nents += DIV_ROUND_UP(offset_in_page(addr) + len,
+ PAGE_SIZE);
+ } else {
+ nents++;
+ }
+ }
+ nents += rqst[i].rq_npages;
+ }
+ nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE);
+ return nents;
+}
+
+/* We can not use the normal sg_set_buf() as we will sometimes pass a
+ * stack object as buf.
+ */
+static inline struct scatterlist *cifs_sg_set_buf(struct scatterlist *sg,
+ const void *buf,
+ unsigned int buflen)
+{
+ unsigned long addr = (unsigned long)buf;
+ unsigned int off = offset_in_page(addr);
+
+ addr &= PAGE_MASK;
+ if (unlikely(is_vmalloc_addr((void *)addr))) {
+ do {
+ unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off);
+
+ sg_set_page(sg++, vmalloc_to_page((void *)addr), len, off);
+
+ off = 0;
+ addr += PAGE_SIZE;
+ buflen -= len;
+ } while (buflen);
+ } else {
+ sg_set_page(sg++, virt_to_page(addr), buflen, off);
+ }
+ return sg;
+}
+
+#endif /* _CIFS_GLOB_H */
diff --git a/fs/smb/client/cifspdu.h b/fs/smb/client/cifspdu.h
new file mode 100644
index 000000000000..cc458b98441c
--- /dev/null
+++ b/fs/smb/client/cifspdu.h
@@ -0,0 +1,2730 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002,2009
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#ifndef _CIFSPDU_H
+#define _CIFSPDU_H
+
+#include <net/sock.h>
+#include <asm/unaligned.h>
+#include "../common/smbfsctl.h"
+
+#define CIFS_PROT 0
+#define POSIX_PROT (CIFS_PROT+1)
+#define BAD_PROT 0xFFFF
+
+/* SMB command codes:
+ * Note some commands have minimal (wct=0,bcc=0), or uninteresting, responses
+ * (ie which include no useful data other than the SMB error code itself).
+ * This can allow us to avoid response buffer allocations and copy in some cases
+ */
+#define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */
+#define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */
+#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
+#define SMB_COM_FLUSH 0x05 /* triv req/rsp */
+#define SMB_COM_DELETE 0x06 /* trivial response */
+#define SMB_COM_RENAME 0x07 /* trivial response */
+#define SMB_COM_QUERY_INFORMATION 0x08 /* aka getattr */
+#define SMB_COM_SETATTR 0x09 /* trivial response */
+#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
+#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/
+#define SMB_COM_ECHO 0x2B /* echo request */
+#define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */
+#define SMB_COM_READ_ANDX 0x2E
+#define SMB_COM_WRITE_ANDX 0x2F
+#define SMB_COM_TRANSACTION2 0x32
+#define SMB_COM_TRANSACTION2_SECONDARY 0x33
+#define SMB_COM_FIND_CLOSE2 0x34 /* trivial response */
+#define SMB_COM_TREE_DISCONNECT 0x71 /* trivial response */
+#define SMB_COM_NEGOTIATE 0x72
+#define SMB_COM_SESSION_SETUP_ANDX 0x73
+#define SMB_COM_LOGOFF_ANDX 0x74 /* trivial response */
+#define SMB_COM_TREE_CONNECT_ANDX 0x75
+#define SMB_COM_NT_TRANSACT 0xA0
+#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
+#define SMB_COM_NT_CREATE_ANDX 0xA2
+#define SMB_COM_NT_CANCEL 0xA4 /* no response */
+#define SMB_COM_NT_RENAME 0xA5 /* trivial response */
+
+/* Transact2 subcommand codes */
+#define TRANS2_OPEN 0x00
+#define TRANS2_FIND_FIRST 0x01
+#define TRANS2_FIND_NEXT 0x02
+#define TRANS2_QUERY_FS_INFORMATION 0x03
+#define TRANS2_SET_FS_INFORMATION 0x04
+#define TRANS2_QUERY_PATH_INFORMATION 0x05
+#define TRANS2_SET_PATH_INFORMATION 0x06
+#define TRANS2_QUERY_FILE_INFORMATION 0x07
+#define TRANS2_SET_FILE_INFORMATION 0x08
+#define TRANS2_GET_DFS_REFERRAL 0x10
+#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
+
+/* SMB Transact (Named Pipe) subcommand codes */
+#define TRANS_SET_NMPIPE_STATE 0x0001
+#define TRANS_RAW_READ_NMPIPE 0x0011
+#define TRANS_QUERY_NMPIPE_STATE 0x0021
+#define TRANS_QUERY_NMPIPE_INFO 0x0022
+#define TRANS_PEEK_NMPIPE 0x0023
+#define TRANS_TRANSACT_NMPIPE 0x0026
+#define TRANS_RAW_WRITE_NMPIPE 0x0031
+#define TRANS_READ_NMPIPE 0x0036
+#define TRANS_WRITE_NMPIPE 0x0037
+#define TRANS_WAIT_NMPIPE 0x0053
+#define TRANS_CALL_NMPIPE 0x0054
+
+/* NT Transact subcommand codes */
+#define NT_TRANSACT_CREATE 0x01
+#define NT_TRANSACT_IOCTL 0x02
+#define NT_TRANSACT_SET_SECURITY_DESC 0x03
+#define NT_TRANSACT_NOTIFY_CHANGE 0x04
+#define NT_TRANSACT_RENAME 0x05
+#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
+#define NT_TRANSACT_GET_USER_QUOTA 0x07
+#define NT_TRANSACT_SET_USER_QUOTA 0x08
+
+#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
+/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
+/* among the requests (NTCreateX response is bigger with wct of 34) */
+#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
+#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */
+
+/* internal cifs vfs structures */
+/*****************************************************************
+ * All constants go here
+ *****************************************************************
+ */
+
+/*
+ * Starting value for maximum SMB size negotiation
+ */
+#define CIFS_MAX_MSGSIZE (4*4096)
+
+/*
+ * Size of encrypted user password in bytes
+ */
+#define CIFS_ENCPWD_SIZE (16)
+
+/*
+ * Size of the crypto key returned on the negotiate SMB in bytes
+ */
+#define CIFS_CRYPTO_KEY_SIZE (8)
+
+/*
+ * Size of the ntlm client response
+ */
+#define CIFS_AUTH_RESP_SIZE (24)
+
+/*
+ * Size of the session key (crypto key encrypted with the password
+ */
+#define CIFS_SESS_KEY_SIZE (16)
+
+#define CIFS_SERVER_CHALLENGE_SIZE (8)
+#define CIFS_HMAC_MD5_HASH_SIZE (16)
+#define CIFS_CPHTXT_SIZE (16)
+#define CIFS_NTHASH_SIZE (16)
+
+/*
+ * Maximum user name length
+ */
+#define CIFS_UNLEN (20)
+
+/*
+ * Flags on SMB open
+ */
+#define SMBOPEN_WRITE_THROUGH 0x4000
+#define SMBOPEN_DENY_ALL 0x0010
+#define SMBOPEN_DENY_WRITE 0x0020
+#define SMBOPEN_DENY_READ 0x0030
+#define SMBOPEN_DENY_NONE 0x0040
+#define SMBOPEN_READ 0x0000
+#define SMBOPEN_WRITE 0x0001
+#define SMBOPEN_READWRITE 0x0002
+#define SMBOPEN_EXECUTE 0x0003
+
+#define SMBOPEN_OCREATE 0x0010
+#define SMBOPEN_OTRUNC 0x0002
+#define SMBOPEN_OAPPEND 0x0001
+
+/*
+ * SMB flag definitions
+ */
+#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock smb */
+#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
+#define SMBFLG_RSVD 0x04
+#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off
+ implies case sensitive file handling request) */
+#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
+#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
+#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
+#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
+
+/*
+ * SMB flag2 definitions
+ */
+#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3)
+ path names in response */
+#define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
+#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
+#define SMBFLG2_COMPRESSED (8)
+#define SMBFLG2_SECURITY_SIGNATURE_REQUIRED (0x10)
+#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
+#define SMBFLG2_REPARSE_PATH (0x400)
+#define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
+#define SMBFLG2_DFS cpu_to_le16(0x1000)
+#define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
+#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
+#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
+
+/*
+ * These are the file access permission bits defined in CIFS for the
+ * NTCreateAndX as well as the level 0x107
+ * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
+ * responds with the AccessFlags.
+ * The AccessFlags specifies the access permissions a caller has to the
+ * file and can have any suitable combination of the following values:
+ */
+
+#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
+#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
+#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
+#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
+ /* with the file can be read */
+#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
+ /* with the file can be written */
+#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
+ /* the file using system paging I/O */
+#define FILE_DELETE_CHILD 0x00000040
+#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
+ /* file can be read */
+#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
+ /* file can be written */
+#define DELETE 0x00010000 /* The file can be deleted */
+#define READ_CONTROL 0x00020000 /* The access control list and */
+ /* ownership associated with the */
+ /* file can be read */
+#define WRITE_DAC 0x00040000 /* The access control list and */
+ /* ownership associated with the */
+ /* file can be written. */
+#define WRITE_OWNER 0x00080000 /* Ownership information associated */
+ /* with the file can be written */
+#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
+ /* synchronize with the completion */
+ /* of an input/output request */
+#define SYSTEM_SECURITY 0x01000000 /* The system access control list */
+ /* can be read and changed */
+#define GENERIC_ALL 0x10000000
+#define GENERIC_EXECUTE 0x20000000
+#define GENERIC_WRITE 0x40000000
+#define GENERIC_READ 0x80000000
+ /* In summary - Relevant file */
+ /* access flags from CIFS are */
+ /* file_read_data, file_write_data */
+ /* file_execute, file_read_attributes*/
+ /* write_dac, and delete. */
+
+#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
+#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
+ | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
+#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
+
+#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA \
+ | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
+ | FILE_READ_EA | FILE_WRITE_EA \
+ | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
+ | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+
+#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \
+ | READ_CONTROL | SYNCHRONIZE)
+
+
+/*
+ * Invalid readdir handle
+ */
+#define CIFS_NO_HANDLE 0xFFFF
+
+#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL
+
+/* IPC$ in ASCII */
+#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
+
+/* IPC$ in Unicode */
+#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
+
+/* Unicode Null terminate 2 bytes of 0 */
+#define UNICODE_NULL "\x00\x00"
+#define ASCII_NULL 0x00
+
+/*
+ * Server type values (returned on EnumServer API
+ */
+#define CIFS_SV_TYPE_DC 0x00000008
+#define CIFS_SV_TYPE_BACKDC 0x00000010
+
+/*
+ * Alias type flags (From EnumAlias API call
+ */
+#define CIFS_ALIAS_TYPE_FILE 0x0001
+#define CIFS_SHARE_TYPE_FILE 0x0000
+
+/*
+ * File Attribute flags
+ */
+#define ATTR_READONLY 0x0001
+#define ATTR_HIDDEN 0x0002
+#define ATTR_SYSTEM 0x0004
+#define ATTR_VOLUME 0x0008
+#define ATTR_DIRECTORY 0x0010
+#define ATTR_ARCHIVE 0x0020
+#define ATTR_DEVICE 0x0040
+#define ATTR_NORMAL 0x0080
+#define ATTR_TEMPORARY 0x0100
+#define ATTR_SPARSE 0x0200
+#define ATTR_REPARSE 0x0400
+#define ATTR_COMPRESSED 0x0800
+#define ATTR_OFFLINE 0x1000 /* ie file not immediately available -
+ on offline storage */
+#define ATTR_NOT_CONTENT_INDEXED 0x2000
+#define ATTR_ENCRYPTED 0x4000
+#define ATTR_POSIX_SEMANTICS 0x01000000
+#define ATTR_BACKUP_SEMANTICS 0x02000000
+#define ATTR_DELETE_ON_CLOSE 0x04000000
+#define ATTR_SEQUENTIAL_SCAN 0x08000000
+#define ATTR_RANDOM_ACCESS 0x10000000
+#define ATTR_NO_BUFFERING 0x20000000
+#define ATTR_WRITE_THROUGH 0x80000000
+
+/* ShareAccess flags */
+#define FILE_NO_SHARE 0x00000000
+#define FILE_SHARE_READ 0x00000001
+#define FILE_SHARE_WRITE 0x00000002
+#define FILE_SHARE_DELETE 0x00000004
+#define FILE_SHARE_ALL 0x00000007
+
+/* CreateDisposition flags, similar to CreateAction as well */
+#define FILE_SUPERSEDE 0x00000000
+#define FILE_OPEN 0x00000001
+#define FILE_CREATE 0x00000002
+#define FILE_OPEN_IF 0x00000003
+#define FILE_OVERWRITE 0x00000004
+#define FILE_OVERWRITE_IF 0x00000005
+
+/* CreateOptions */
+#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
+#define CREATE_WRITE_THROUGH 0x00000002
+#define CREATE_SEQUENTIAL 0x00000004
+#define CREATE_NO_BUFFER 0x00000008 /* should not buffer on srv */
+#define CREATE_SYNC_ALERT 0x00000010 /* MBZ */
+#define CREATE_ASYNC_ALERT 0x00000020 /* MBZ */
+#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
+#define CREATE_TREE_CONNECTION 0x00000080 /* should be zero */
+#define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */
+#define CREATE_NO_EA_KNOWLEDGE 0x00000200
+#define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete
+ "open for recovery" flag should
+ be zero in any case */
+#define CREATE_OPEN_FOR_RECOVERY 0x00000400
+#define CREATE_RANDOM_ACCESS 0x00000800
+#define CREATE_DELETE_ON_CLOSE 0x00001000
+#define CREATE_OPEN_BY_ID 0x00002000
+#define CREATE_OPEN_BACKUP_INTENT 0x00004000
+#define CREATE_NO_COMPRESSION 0x00008000
+#define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */
+#define OPEN_REPARSE_POINT 0x00200000
+#define OPEN_NO_RECALL 0x00400000
+#define OPEN_FREE_SPACE_QUERY 0x00800000 /* should be zero */
+#define CREATE_OPTIONS_MASK 0x007FFFFF
+#define CREATE_OPTION_READONLY 0x10000000
+#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
+
+/* ImpersonationLevel flags */
+#define SECURITY_ANONYMOUS 0
+#define SECURITY_IDENTIFICATION 1
+#define SECURITY_IMPERSONATION 2
+#define SECURITY_DELEGATION 3
+
+/* SecurityFlags */
+#define SECURITY_CONTEXT_TRACKING 0x01
+#define SECURITY_EFFECTIVE_ONLY 0x02
+
+/*
+ * Default PID value, used in all SMBs where the PID is not important
+ */
+#define CIFS_DFT_PID 0x1234
+
+/*
+ * We use the same routine for Copy and Move SMBs. This flag is used to
+ * distinguish
+ */
+#define CIFS_COPY_OP 1
+#define CIFS_RENAME_OP 2
+
+#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
+#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
+
+struct smb_hdr {
+ __be32 smb_buf_length; /* BB length is only two (rarely three) bytes,
+ with one or two byte "type" preceding it that will be
+ zero - we could mask the type byte off */
+ __u8 Protocol[4];
+ __u8 Command;
+ union {
+ struct {
+ __u8 ErrorClass;
+ __u8 Reserved;
+ __le16 Error;
+ } __attribute__((packed)) DosError;
+ __le32 CifsError;
+ } __attribute__((packed)) Status;
+ __u8 Flags;
+ __le16 Flags2; /* note: le */
+ __le16 PidHigh;
+ union {
+ struct {
+ __le32 SequenceNumber; /* le */
+ __u32 Reserved; /* zero */
+ } __attribute__((packed)) Sequence;
+ __u8 SecuritySignature[8]; /* le */
+ } __attribute__((packed)) Signature;
+ __u8 pad[2];
+ __u16 Tid;
+ __le16 Pid;
+ __u16 Uid;
+ __le16 Mid;
+ __u8 WordCount;
+} __attribute__((packed));
+
+/* given a pointer to an smb_hdr, retrieve a void pointer to the ByteCount */
+static inline void *
+BCC(struct smb_hdr *smb)
+{
+ return (void *)smb + sizeof(*smb) + 2 * smb->WordCount;
+}
+
+/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
+#define pByteArea(smb_var) (BCC(smb_var) + 2)
+
+/* get the unconverted ByteCount for a SMB packet and return it */
+static inline __u16
+get_bcc(struct smb_hdr *hdr)
+{
+ __le16 *bc_ptr = (__le16 *)BCC(hdr);
+
+ return get_unaligned_le16(bc_ptr);
+}
+
+/* set the ByteCount for a SMB packet in little-endian */
+static inline void
+put_bcc(__u16 count, struct smb_hdr *hdr)
+{
+ __le16 *bc_ptr = (__le16 *)BCC(hdr);
+
+ put_unaligned_le16(count, bc_ptr);
+}
+
+/*
+ * Computer Name Length (since Netbios name was length 16 with last byte 0x20)
+ * No longer as important, now that TCP names are more commonly used to
+ * resolve hosts.
+ */
+#define CNLEN 15
+
+/*
+ * Share Name Length (SNLEN)
+ * Note: This length was limited by the SMB used to get
+ * the Share info. NetShareEnum only returned 13
+ * chars, including the null termination.
+ * This was removed because it no longer is limiting.
+ */
+
+/*
+ * Comment Length
+ */
+#define MAXCOMMENTLEN 40
+
+/*
+ * The OS/2 maximum path name
+ */
+#define MAX_PATHCONF 256
+
+/*
+ * SMB frame definitions (following must be packed structs)
+ * See the SNIA CIFS Specification for details.
+ *
+ * The Naming convention is the lower case version of the
+ * smb command code name for the struct and this is typedef to the
+ * uppercase version of the same name with the prefix SMB_ removed
+ * for brevity. Although typedefs are not commonly used for
+ * structure definitions in the Linux kernel, their use in the
+ * CIFS standards document, which this code is based on, may
+ * make this one of the cases where typedefs for structures make
+ * sense to improve readability for readers of the standards doc.
+ * Typedefs can always be removed later if they are too distracting
+ * and they are only used for the CIFSs PDUs themselves, not
+ * internal cifs vfs structures
+ *
+ */
+
+typedef struct negotiate_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __le16 ByteCount;
+ unsigned char DialectsArray[];
+} __attribute__((packed)) NEGOTIATE_REQ;
+
+#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */
+
+#define READ_RAW_ENABLE 1
+#define WRITE_RAW_ENABLE 2
+#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
+#define SMB1_CLIENT_GUID_SIZE (16)
+typedef struct negotiate_rsp {
+ struct smb_hdr hdr; /* wct = 17 */
+ __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
+ __u8 SecurityMode;
+ __le16 MaxMpxCount;
+ __le16 MaxNumberVcs;
+ __le32 MaxBufferSize;
+ __le32 MaxRawSize;
+ __le32 SessionKey;
+ __le32 Capabilities; /* see below */
+ __le32 SystemTimeLow;
+ __le32 SystemTimeHigh;
+ __le16 ServerTimeZone;
+ __u8 EncryptionKeyLength;
+ __u16 ByteCount;
+ union {
+ /* cap extended security off */
+ DECLARE_FLEX_ARRAY(unsigned char, EncryptionKey);
+ /* followed by Domain name - if extended security is off */
+ /* followed by 16 bytes of server GUID */
+ /* then security blob if cap_extended_security negotiated */
+ struct {
+ unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
+ unsigned char SecurityBlob[];
+ } __attribute__((packed)) extended_response;
+ } __attribute__((packed)) u;
+} __attribute__((packed)) NEGOTIATE_RSP;
+
+/* SecurityMode bits */
+#define SECMODE_USER 0x01 /* off indicates share level security */
+#define SECMODE_PW_ENCRYPT 0x02
+#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */
+#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */
+
+/* Negotiate response Capabilities */
+#define CAP_RAW_MODE 0x00000001
+#define CAP_MPX_MODE 0x00000002
+#define CAP_UNICODE 0x00000004
+#define CAP_LARGE_FILES 0x00000008
+#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */
+#define CAP_RPC_REMOTE_APIS 0x00000020
+#define CAP_STATUS32 0x00000040
+#define CAP_LEVEL_II_OPLOCKS 0x00000080
+#define CAP_LOCK_AND_READ 0x00000100
+#define CAP_NT_FIND 0x00000200
+#define CAP_DFS 0x00001000
+#define CAP_INFOLEVEL_PASSTHRU 0x00002000
+#define CAP_LARGE_READ_X 0x00004000
+#define CAP_LARGE_WRITE_X 0x00008000
+#define CAP_LWIO 0x00010000 /* support fctl_srv_req_resume_key */
+#define CAP_UNIX 0x00800000
+#define CAP_COMPRESSED_DATA 0x02000000
+#define CAP_DYNAMIC_REAUTH 0x20000000
+#define CAP_PERSISTENT_HANDLES 0x40000000
+#define CAP_EXTENDED_SECURITY 0x80000000
+
+typedef union smb_com_session_setup_andx {
+ struct { /* request format */
+ struct smb_hdr hdr; /* wct = 12 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 MaxBufferSize;
+ __le16 MaxMpxCount;
+ __le16 VcNumber;
+ __u32 SessionKey;
+ __le16 SecurityBlobLength;
+ __u32 Reserved;
+ __le32 Capabilities; /* see below */
+ __le16 ByteCount;
+ unsigned char SecurityBlob[1]; /* followed by */
+ /* STRING NativeOS */
+ /* STRING NativeLanMan */
+ } __attribute__((packed)) req; /* NTLM request format (with
+ extended security */
+
+ struct { /* request format */
+ struct smb_hdr hdr; /* wct = 13 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 MaxBufferSize;
+ __le16 MaxMpxCount;
+ __le16 VcNumber;
+ __u32 SessionKey;
+ __le16 CaseInsensitivePasswordLength; /* ASCII password len */
+ __le16 CaseSensitivePasswordLength; /* Unicode password length*/
+ __u32 Reserved; /* see below */
+ __le32 Capabilities;
+ __le16 ByteCount;
+ unsigned char CaseInsensitivePassword[1]; /* followed by: */
+ /* unsigned char * CaseSensitivePassword; */
+ /* STRING AccountName */
+ /* STRING PrimaryDomain */
+ /* STRING NativeOS */
+ /* STRING NativeLanMan */
+ } __attribute__((packed)) req_no_secext; /* NTLM request format (without
+ extended security */
+
+ struct { /* default (NTLM) response format */
+ struct smb_hdr hdr; /* wct = 4 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 Action; /* see below */
+ __le16 SecurityBlobLength;
+ __u16 ByteCount;
+ unsigned char SecurityBlob[1]; /* followed by */
+/* unsigned char * NativeOS; */
+/* unsigned char * NativeLanMan; */
+/* unsigned char * PrimaryDomain; */
+ } __attribute__((packed)) resp; /* NTLM response
+ (with or without extended sec) */
+
+ struct { /* request format */
+ struct smb_hdr hdr; /* wct = 10 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 MaxBufferSize;
+ __le16 MaxMpxCount;
+ __le16 VcNumber;
+ __u32 SessionKey;
+ __le16 PasswordLength;
+ __u32 Reserved; /* encrypt key len and offset */
+ __le16 ByteCount;
+ unsigned char AccountPassword[1]; /* followed by */
+ /* STRING AccountName */
+ /* STRING PrimaryDomain */
+ /* STRING NativeOS */
+ /* STRING NativeLanMan */
+ } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) req format */
+
+ struct { /* default (NTLM) response format */
+ struct smb_hdr hdr; /* wct = 3 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 Action; /* see below */
+ __u16 ByteCount;
+ unsigned char NativeOS[1]; /* followed by */
+/* unsigned char * NativeLanMan; */
+/* unsigned char * PrimaryDomain; */
+ } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */
+} __attribute__((packed)) SESSION_SETUP_ANDX;
+
+/* format of NLTMv2 Response ie "case sensitive password" hash when NTLMv2 */
+
+#define NTLMSSP_SERVER_TYPE 1
+#define NTLMSSP_DOMAIN_TYPE 2
+#define NTLMSSP_FQ_DOMAIN_TYPE 3
+#define NTLMSSP_DNS_DOMAIN_TYPE 4
+#define NTLMSSP_DNS_PARENT_TYPE 5
+
+struct ntlmssp2_name {
+ __le16 type;
+ __le16 length;
+/* char name[length]; */
+} __attribute__((packed));
+
+struct ntlmv2_resp {
+ union {
+ char ntlmv2_hash[CIFS_ENCPWD_SIZE];
+ struct {
+ __u8 reserved[8];
+ __u8 key[CIFS_SERVER_CHALLENGE_SIZE];
+ } __attribute__((packed)) challenge;
+ } __attribute__((packed));
+ __le32 blob_signature;
+ __u32 reserved;
+ __le64 time;
+ __u64 client_chal; /* random */
+ __u32 reserved2;
+ /* array of name entries could follow ending in minimum 4 byte struct */
+} __attribute__((packed));
+
+
+#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
+
+/* Capabilities bits (for NTLM SessSetup request) */
+#define CAP_UNICODE 0x00000004
+#define CAP_LARGE_FILES 0x00000008
+#define CAP_NT_SMBS 0x00000010
+#define CAP_STATUS32 0x00000040
+#define CAP_LEVEL_II_OPLOCKS 0x00000080
+#define CAP_NT_FIND 0x00000200 /* reserved should be zero
+ (because NT_SMBs implies the same thing?) */
+#define CAP_BULK_TRANSFER 0x20000000
+#define CAP_EXTENDED_SECURITY 0x80000000
+
+/* Action bits */
+#define GUEST_LOGIN 1
+
+typedef struct smb_com_tconx_req {
+ struct smb_hdr hdr; /* wct = 4 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 Flags; /* see below */
+ __le16 PasswordLength;
+ __le16 ByteCount;
+ unsigned char Password[1]; /* followed by */
+/* STRING Path *//* \\server\share name */
+ /* STRING Service */
+} __attribute__((packed)) TCONX_REQ;
+
+typedef struct smb_com_tconx_rsp {
+ struct smb_hdr hdr; /* wct = 3 , not extended response */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 OptionalSupport; /* see below */
+ __u16 ByteCount;
+ unsigned char Service[1]; /* always ASCII, not Unicode */
+ /* STRING NativeFileSystem */
+} __attribute__((packed)) TCONX_RSP;
+
+typedef struct smb_com_tconx_rsp_ext {
+ struct smb_hdr hdr; /* wct = 7, extended response */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 OptionalSupport; /* see below */
+ __le32 MaximalShareAccessRights;
+ __le32 GuestMaximalShareAccessRights;
+ __u16 ByteCount;
+ unsigned char Service[1]; /* always ASCII, not Unicode */
+ /* STRING NativeFileSystem */
+} __attribute__((packed)) TCONX_RSP_EXT;
+
+
+/* tree connect Flags */
+#define DISCONNECT_TID 0x0001
+#define TCON_EXTENDED_SIGNATURES 0x0004
+#define TCON_EXTENDED_SECINFO 0x0008
+
+/* OptionalSupport bits */
+#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* "must have" directory search bits
+ (exclusive searches supported) */
+#define SMB_SHARE_IS_IN_DFS 0x0002
+#define SMB_CSC_MASK 0x000C
+/* CSC flags defined as follows */
+#define SMB_CSC_CACHE_MANUAL_REINT 0x0000
+#define SMB_CSC_CACHE_AUTO_REINT 0x0004
+#define SMB_CSC_CACHE_VDO 0x0008
+#define SMB_CSC_NO_CACHING 0x000C
+#define SMB_UNIQUE_FILE_NAME 0x0010
+#define SMB_EXTENDED_SIGNATURES 0x0020
+
+/* services
+ *
+ * A: ie disk
+ * LPT1: ie printer
+ * IPC ie named pipe
+ * COMM
+ * ????? ie any type
+ *
+ */
+
+typedef struct smb_com_echo_req {
+ struct smb_hdr hdr;
+ __le16 EchoCount;
+ __le16 ByteCount;
+ char Data[1];
+} __attribute__((packed)) ECHO_REQ;
+
+typedef struct smb_com_echo_rsp {
+ struct smb_hdr hdr;
+ __le16 SequenceNumber;
+ __le16 ByteCount;
+ char Data[1];
+} __attribute__((packed)) ECHO_RSP;
+
+typedef struct smb_com_logoff_andx_req {
+ struct smb_hdr hdr; /* wct = 2 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 ByteCount;
+} __attribute__((packed)) LOGOFF_ANDX_REQ;
+
+typedef struct smb_com_logoff_andx_rsp {
+ struct smb_hdr hdr; /* wct = 2 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __u16 AndXOffset;
+ __u16 ByteCount;
+} __attribute__((packed)) LOGOFF_ANDX_RSP;
+
+typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on
+ tree_connect PDU to effect disconnect */
+ /* tdis is probably simplest SMB PDU */
+ struct {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bcc = 0 */
+ } __attribute__((packed)) req;
+ struct {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bcc = 0 */
+ } __attribute__((packed)) resp;
+} __attribute__((packed)) TREE_DISCONNECT;
+
+typedef struct smb_com_close_req {
+ struct smb_hdr hdr; /* wct = 3 */
+ __u16 FileID;
+ __u32 LastWriteTime; /* should be zero or -1 */
+ __u16 ByteCount; /* 0 */
+} __attribute__((packed)) CLOSE_REQ;
+
+typedef struct smb_com_close_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} __attribute__((packed)) CLOSE_RSP;
+
+typedef struct smb_com_flush_req {
+ struct smb_hdr hdr; /* wct = 1 */
+ __u16 FileID;
+ __u16 ByteCount; /* 0 */
+} __attribute__((packed)) FLUSH_REQ;
+
+typedef struct smb_com_findclose_req {
+ struct smb_hdr hdr; /* wct = 1 */
+ __u16 FileID;
+ __u16 ByteCount; /* 0 */
+} __attribute__((packed)) FINDCLOSE_REQ;
+
+/* OpenFlags */
+#define REQ_MORE_INFO 0x00000001 /* legacy (OPEN_AND_X) only */
+#define REQ_OPLOCK 0x00000002
+#define REQ_BATCHOPLOCK 0x00000004
+#define REQ_OPENDIRONLY 0x00000008
+#define REQ_EXTENDED_INFO 0x00000010
+
+/* File type */
+#define DISK_TYPE 0x0000
+#define BYTE_PIPE_TYPE 0x0001
+#define MESSAGE_PIPE_TYPE 0x0002
+#define PRINTER_TYPE 0x0003
+#define COMM_DEV_TYPE 0x0004
+#define UNKNOWN_TYPE 0xFFFF
+
+/* Device Type or File Status Flags */
+#define NO_EAS 0x0001
+#define NO_SUBSTREAMS 0x0002
+#define NO_REPARSETAG 0x0004
+/* following flags can apply if pipe */
+#define ICOUNT_MASK 0x00FF
+#define PIPE_READ_MODE 0x0100
+#define NAMED_PIPE_TYPE 0x0400
+#define PIPE_END_POINT 0x4000
+#define BLOCKING_NAMED_PIPE 0x8000
+
+typedef struct smb_com_open_req { /* also handles create */
+ struct smb_hdr hdr; /* wct = 24 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u8 Reserved; /* Must Be Zero */
+ __le16 NameLength;
+ __le32 OpenFlags;
+ __u32 RootDirectoryFid;
+ __le32 DesiredAccess;
+ __le64 AllocationSize;
+ __le32 FileAttributes;
+ __le32 ShareAccess;
+ __le32 CreateDisposition;
+ __le32 CreateOptions;
+ __le32 ImpersonationLevel;
+ __u8 SecurityFlags;
+ __le16 ByteCount;
+ char fileName[1];
+} __attribute__((packed)) OPEN_REQ;
+
+/* open response: oplock levels */
+#define OPLOCK_NONE 0
+#define OPLOCK_EXCLUSIVE 1
+#define OPLOCK_BATCH 2
+#define OPLOCK_READ 3 /* level 2 oplock */
+
+/* open response for CreateAction shifted left */
+#define CIFS_CREATE_ACTION 0x20000 /* file created */
+
+typedef struct smb_com_open_rsp {
+ struct smb_hdr hdr; /* wct = 34 BB */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u8 OplockLevel;
+ __u16 Fid;
+ __le32 CreateAction;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le32 FileAttributes;
+ __le64 AllocationSize;
+ __le64 EndOfFile;
+ __le16 FileType;
+ __le16 DeviceState;
+ __u8 DirectoryFlag;
+ __u16 ByteCount; /* bct = 0 */
+} __attribute__((packed)) OPEN_RSP;
+
+typedef struct smb_com_open_rsp_ext {
+ struct smb_hdr hdr; /* wct = 42 but meaningless due to MS bug? */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u8 OplockLevel;
+ __u16 Fid;
+ __le32 CreateAction;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le32 FileAttributes;
+ __le64 AllocationSize;
+ __le64 EndOfFile;
+ __le16 FileType;
+ __le16 DeviceState;
+ __u8 DirectoryFlag;
+ __u8 VolumeGUID[16];
+ __u64 FileId; /* note no endian conversion - is opaque UniqueID */
+ __le32 MaximalAccessRights;
+ __le32 GuestMaximalAccessRights;
+ __u16 ByteCount; /* bct = 0 */
+} __attribute__((packed)) OPEN_RSP_EXT;
+
+
+/* format of legacy open request */
+typedef struct smb_com_openx_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 OpenFlags;
+ __le16 Mode;
+ __le16 Sattr; /* search attributes */
+ __le16 FileAttributes; /* dos attrs */
+ __le32 CreateTime; /* os2 format */
+ __le16 OpenFunction;
+ __le32 EndOfFile;
+ __le32 Timeout;
+ __le32 Reserved;
+ __le16 ByteCount; /* file name follows */
+ char fileName[1];
+} __attribute__((packed)) OPENX_REQ;
+
+typedef struct smb_com_openx_rsp {
+ struct smb_hdr hdr; /* wct = 15 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u16 Fid;
+ __le16 FileAttributes;
+ __le32 LastWriteTime; /* os2 format */
+ __le32 EndOfFile;
+ __le16 Access;
+ __le16 FileType;
+ __le16 IPCState;
+ __le16 Action;
+ __u32 FileId;
+ __u16 Reserved;
+ __u16 ByteCount;
+} __attribute__((packed)) OPENX_RSP;
+
+/* For encoding of POSIX Open Request - see trans2 function 0x209 data struct */
+
+/* Legacy write request for older servers */
+typedef struct smb_com_writex_req {
+ struct smb_hdr hdr; /* wct = 12 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u16 Fid;
+ __le32 OffsetLow;
+ __u32 Reserved; /* Timeout */
+ __le16 WriteMode; /* 1 = write through */
+ __le16 Remaining;
+ __le16 Reserved2;
+ __le16 DataLengthLow;
+ __le16 DataOffset;
+ __le16 ByteCount;
+ __u8 Pad; /* BB check for whether padded to DWORD
+ boundary and optimum performance here */
+ char Data[];
+} __attribute__((packed)) WRITEX_REQ;
+
+typedef struct smb_com_write_req {
+ struct smb_hdr hdr; /* wct = 14 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u16 Fid;
+ __le32 OffsetLow;
+ __u32 Reserved;
+ __le16 WriteMode;
+ __le16 Remaining;
+ __le16 DataLengthHigh;
+ __le16 DataLengthLow;
+ __le16 DataOffset;
+ __le32 OffsetHigh;
+ __le16 ByteCount;
+ __u8 Pad; /* BB check for whether padded to DWORD
+ boundary and optimum performance here */
+ char Data[];
+} __attribute__((packed)) WRITE_REQ;
+
+typedef struct smb_com_write_rsp {
+ struct smb_hdr hdr; /* wct = 6 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 Count;
+ __le16 Remaining;
+ __le16 CountHigh;
+ __u16 Reserved;
+ __u16 ByteCount;
+} __attribute__((packed)) WRITE_RSP;
+
+/* legacy read request for older servers */
+typedef struct smb_com_readx_req {
+ struct smb_hdr hdr; /* wct = 10 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u16 Fid;
+ __le32 OffsetLow;
+ __le16 MaxCount;
+ __le16 MinCount; /* obsolete */
+ __le32 Reserved;
+ __le16 Remaining;
+ __le16 ByteCount;
+} __attribute__((packed)) READX_REQ;
+
+typedef struct smb_com_read_req {
+ struct smb_hdr hdr; /* wct = 12 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u16 Fid;
+ __le32 OffsetLow;
+ __le16 MaxCount;
+ __le16 MinCount; /* obsolete */
+ __le32 MaxCountHigh;
+ __le16 Remaining;
+ __le32 OffsetHigh;
+ __le16 ByteCount;
+} __attribute__((packed)) READ_REQ;
+
+typedef struct smb_com_read_rsp {
+ struct smb_hdr hdr; /* wct = 12 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __le16 Remaining;
+ __le16 DataCompactionMode;
+ __le16 Reserved;
+ __le16 DataLength;
+ __le16 DataOffset;
+ __le16 DataLengthHigh;
+ __u64 Reserved2;
+ __u16 ByteCount;
+ /* read response data immediately follows */
+} __attribute__((packed)) READ_RSP;
+
+typedef struct locking_andx_range {
+ __le16 Pid;
+ __le16 Pad;
+ __le32 OffsetHigh;
+ __le32 OffsetLow;
+ __le32 LengthHigh;
+ __le32 LengthLow;
+} __attribute__((packed)) LOCKING_ANDX_RANGE;
+
+#define LOCKING_ANDX_SHARED_LOCK 0x01
+#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
+#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
+#define LOCKING_ANDX_CANCEL_LOCK 0x08
+#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */
+
+typedef struct smb_com_lock_req {
+ struct smb_hdr hdr; /* wct = 8 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u16 Fid;
+ __u8 LockType;
+ __u8 OplockLevel;
+ __le32 Timeout;
+ __le16 NumberOfUnlocks;
+ __le16 NumberOfLocks;
+ __le16 ByteCount;
+ LOCKING_ANDX_RANGE Locks[1];
+} __attribute__((packed)) LOCK_REQ;
+
+/* lock type */
+#define CIFS_RDLCK 0
+#define CIFS_WRLCK 1
+#define CIFS_UNLCK 2
+typedef struct cifs_posix_lock {
+ __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
+ __le16 lock_flags; /* 1 = Wait (only valid for setlock) */
+ __le32 pid;
+ __le64 start;
+ __le64 length;
+ /* BB what about additional owner info to identify network client */
+} __attribute__((packed)) CIFS_POSIX_LOCK;
+
+typedef struct smb_com_lock_rsp {
+ struct smb_hdr hdr; /* wct = 2 */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+ __u16 ByteCount;
+} __attribute__((packed)) LOCK_RSP;
+
+typedef struct smb_com_rename_req {
+ struct smb_hdr hdr; /* wct = 1 */
+ __le16 SearchAttributes; /* target file attributes */
+ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII or Unicode */
+ unsigned char OldFileName[1];
+ /* followed by __u8 BufferFormat2 */
+ /* followed by NewFileName */
+} __attribute__((packed)) RENAME_REQ;
+
+ /* copy request flags */
+#define COPY_MUST_BE_FILE 0x0001
+#define COPY_MUST_BE_DIR 0x0002
+#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
+#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
+#define COPY_VERIFY_WRITES 0x0010
+#define COPY_TREE 0x0020
+
+typedef struct smb_com_copy_req {
+ struct smb_hdr hdr; /* wct = 3 */
+ __u16 Tid2;
+ __le16 OpenFunction;
+ __le16 Flags;
+ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII or Unicode */
+ unsigned char OldFileName[1];
+ /* followed by __u8 BufferFormat2 */
+ /* followed by NewFileName string */
+} __attribute__((packed)) COPY_REQ;
+
+typedef struct smb_com_copy_rsp {
+ struct smb_hdr hdr; /* wct = 1 */
+ __le16 CopyCount; /* number of files copied */
+ __u16 ByteCount; /* may be zero */
+ __u8 BufferFormat; /* 0x04 - only present if errored file follows */
+ unsigned char ErrorFileName[1]; /* only present if error in copy */
+} __attribute__((packed)) COPY_RSP;
+
+#define CREATE_HARD_LINK 0x103
+#define MOVEFILE_COPY_ALLOWED 0x0002
+#define MOVEFILE_REPLACE_EXISTING 0x0001
+
+typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
+ struct smb_hdr hdr; /* wct = 4 */
+ __le16 SearchAttributes; /* target file attributes */
+ __le16 Flags; /* spec says Information Level */
+ __le32 ClusterCount;
+ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII or Unicode */
+ unsigned char OldFileName[1];
+ /* followed by __u8 BufferFormat2 */
+ /* followed by NewFileName */
+} __attribute__((packed)) NT_RENAME_REQ;
+
+typedef struct smb_com_rename_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} __attribute__((packed)) RENAME_RSP;
+
+typedef struct smb_com_delete_file_req {
+ struct smb_hdr hdr; /* wct = 1 */
+ __le16 SearchAttributes;
+ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char fileName[1];
+} __attribute__((packed)) DELETE_FILE_REQ;
+
+typedef struct smb_com_delete_file_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} __attribute__((packed)) DELETE_FILE_RSP;
+
+typedef struct smb_com_delete_directory_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char DirName[1];
+} __attribute__((packed)) DELETE_DIRECTORY_REQ;
+
+typedef struct smb_com_delete_directory_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} __attribute__((packed)) DELETE_DIRECTORY_RSP;
+
+typedef struct smb_com_create_directory_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __le16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char DirName[1];
+} __attribute__((packed)) CREATE_DIRECTORY_REQ;
+
+typedef struct smb_com_create_directory_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} __attribute__((packed)) CREATE_DIRECTORY_RSP;
+
+typedef struct smb_com_query_information_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __le16 ByteCount; /* 1 + namelen + 1 */
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char FileName[1];
+} __attribute__((packed)) QUERY_INFORMATION_REQ;
+
+typedef struct smb_com_query_information_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ __le16 attr;
+ __le32 last_write_time;
+ __le32 size;
+ __u16 reserved[5];
+ __le16 ByteCount; /* bcc = 0 */
+} __attribute__((packed)) QUERY_INFORMATION_RSP;
+
+typedef struct smb_com_setattr_req {
+ struct smb_hdr hdr; /* wct = 8 */
+ __le16 attr;
+ __le16 time_low;
+ __le16 time_high;
+ __le16 reserved[5]; /* must be zero */
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char fileName[1];
+} __attribute__((packed)) SETATTR_REQ;
+
+typedef struct smb_com_setattr_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} __attribute__((packed)) SETATTR_RSP;
+
+/* empty wct response to setattr */
+
+/*******************************************************/
+/* NT Transact structure definitions follow */
+/* Currently only ioctl, acl (get security descriptor) */
+/* and notify are implemented */
+/*******************************************************/
+typedef struct smb_com_ntransact_req {
+ struct smb_hdr hdr; /* wct >= 19 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* four setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand; /* 2 = IOCTL/FSCTL */
+ /* SetupCount words follow then */
+ __le16 ByteCount;
+ __u8 Pad[3];
+ __u8 Parms[];
+} __attribute__((packed)) NTRANSACT_REQ;
+
+typedef struct smb_com_ntransact_rsp {
+ struct smb_hdr hdr; /* wct = 18 */
+ __u8 Reserved[3];
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 ParameterDisplacement;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __le32 DataDisplacement;
+ __u8 SetupCount; /* 0 */
+ __u16 ByteCount;
+ /* __u8 Pad[3]; */
+ /* parms and data follow */
+} __attribute__((packed)) NTRANSACT_RSP;
+
+/* See MS-SMB 2.2.7.2.1.1 */
+struct srv_copychunk {
+ __le64 SourceOffset;
+ __le64 DestinationOffset;
+ __le32 CopyLength;
+ __u32 Reserved;
+} __packed;
+
+typedef struct smb_com_transaction_ioctl_req {
+ struct smb_hdr hdr; /* wct = 23 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* four setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand; /* 2 = IOCTL/FSCTL */
+ __le32 FunctionCode;
+ __u16 Fid;
+ __u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */
+ __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
+ __le16 ByteCount;
+ __u8 Pad[3];
+ __u8 Data[1];
+} __attribute__((packed)) TRANSACT_IOCTL_REQ;
+
+typedef struct smb_com_transaction_compr_ioctl_req {
+ struct smb_hdr hdr; /* wct = 23 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* four setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand; /* 2 = IOCTL/FSCTL */
+ __le32 FunctionCode;
+ __u16 Fid;
+ __u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */
+ __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
+ __le16 ByteCount;
+ __u8 Pad[3];
+ __le16 compression_state; /* See below for valid flags */
+} __attribute__((packed)) TRANSACT_COMPR_IOCTL_REQ;
+
+/* compression state flags */
+#define COMPRESSION_FORMAT_NONE 0x0000
+#define COMPRESSION_FORMAT_DEFAULT 0x0001
+#define COMPRESSION_FORMAT_LZNT1 0x0002
+
+typedef struct smb_com_transaction_ioctl_rsp {
+ struct smb_hdr hdr; /* wct = 19 */
+ __u8 Reserved[3];
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 ParameterDisplacement;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __le32 DataDisplacement;
+ __u8 SetupCount; /* 1 */
+ __le16 ReturnedDataLen;
+ __u16 ByteCount;
+} __attribute__((packed)) TRANSACT_IOCTL_RSP;
+
+#define CIFS_ACL_OWNER 1
+#define CIFS_ACL_GROUP 2
+#define CIFS_ACL_DACL 4
+#define CIFS_ACL_SACL 8
+
+typedef struct smb_com_transaction_qsec_req {
+ struct smb_hdr hdr; /* wct = 19 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* no setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand; /* 6 = QUERY_SECURITY_DESC */
+ __le16 ByteCount; /* bcc = 3 + 8 */
+ __u8 Pad[3];
+ __u16 Fid;
+ __u16 Reserved2;
+ __le32 AclFlags;
+} __attribute__((packed)) QUERY_SEC_DESC_REQ;
+
+
+typedef struct smb_com_transaction_ssec_req {
+ struct smb_hdr hdr; /* wct = 19 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* no setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand; /* 3 = SET_SECURITY_DESC */
+ __le16 ByteCount; /* bcc = 3 + 8 */
+ __u8 Pad[3];
+ __u16 Fid;
+ __u16 Reserved2;
+ __le32 AclFlags;
+} __attribute__((packed)) SET_SEC_DESC_REQ;
+
+typedef struct smb_com_transaction_change_notify_req {
+ struct smb_hdr hdr; /* wct = 23 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* four setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand;/* 4 = Change Notify */
+ __le32 CompletionFilter; /* operation to monitor */
+ __u16 Fid;
+ __u8 WatchTree; /* 1 = Monitor subdirectories */
+ __u8 Reserved2;
+ __le16 ByteCount;
+/* __u8 Pad[3];*/
+/* __u8 Data[1];*/
+} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
+
+/* BB eventually change to use generic ntransact rsp struct
+ and validation routine */
+typedef struct smb_com_transaction_change_notify_rsp {
+ struct smb_hdr hdr; /* wct = 18 */
+ __u8 Reserved[3];
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 ParameterDisplacement;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __le32 DataDisplacement;
+ __u8 SetupCount; /* 0 */
+ __u16 ByteCount;
+ /* __u8 Pad[3]; */
+} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_RSP;
+/* Completion Filter flags for Notify */
+#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
+#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
+#define FILE_NOTIFY_CHANGE_NAME 0x00000003
+#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
+#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
+#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
+#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
+#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
+#define FILE_NOTIFY_CHANGE_EA 0x00000080
+#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
+#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
+#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
+#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
+
+#define FILE_ACTION_ADDED 0x00000001
+#define FILE_ACTION_REMOVED 0x00000002
+#define FILE_ACTION_MODIFIED 0x00000003
+#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
+#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
+#define FILE_ACTION_ADDED_STREAM 0x00000006
+#define FILE_ACTION_REMOVED_STREAM 0x00000007
+#define FILE_ACTION_MODIFIED_STREAM 0x00000008
+
+/* response contains array of the following structures */
+struct file_notify_information {
+ __le32 NextEntryOffset;
+ __le32 Action;
+ __le32 FileNameLength;
+ __u8 FileName[];
+} __attribute__((packed));
+
+/* For IO_REPARSE_TAG_SYMLINK */
+struct reparse_symlink_data {
+ __le32 ReparseTag;
+ __le16 ReparseDataLength;
+ __u16 Reserved;
+ __le16 SubstituteNameOffset;
+ __le16 SubstituteNameLength;
+ __le16 PrintNameOffset;
+ __le16 PrintNameLength;
+ __le32 Flags;
+ char PathBuffer[];
+} __attribute__((packed));
+
+/* Flag above */
+#define SYMLINK_FLAG_RELATIVE 0x00000001
+
+/* For IO_REPARSE_TAG_NFS */
+#define NFS_SPECFILE_LNK 0x00000000014B4E4C
+#define NFS_SPECFILE_CHR 0x0000000000524843
+#define NFS_SPECFILE_BLK 0x00000000004B4C42
+#define NFS_SPECFILE_FIFO 0x000000004F464946
+#define NFS_SPECFILE_SOCK 0x000000004B434F53
+struct reparse_posix_data {
+ __le32 ReparseTag;
+ __le16 ReparseDataLength;
+ __u16 Reserved;
+ __le64 InodeType; /* LNK, FIFO, CHR etc. */
+ char PathBuffer[];
+} __attribute__((packed));
+
+struct cifs_quota_data {
+ __u32 rsrvd1; /* 0 */
+ __u32 sid_size;
+ __u64 rsrvd2; /* 0 */
+ __u64 space_used;
+ __u64 soft_limit;
+ __u64 hard_limit;
+ char sid[1]; /* variable size? */
+} __attribute__((packed));
+
+/* quota sub commands */
+#define QUOTA_LIST_CONTINUE 0
+#define QUOTA_LIST_START 0x100
+#define QUOTA_FOR_SID 0x101
+
+struct trans2_req {
+ /* struct smb_hdr hdr precedes. Set wct = 14+ */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount;
+ __le16 ParameterOffset;
+ __le16 DataCount;
+ __le16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __le16 SubCommand; /* 1st setup word - SetupCount words follow */
+ __le16 ByteCount;
+} __attribute__((packed));
+
+struct smb_t2_req {
+ struct smb_hdr hdr;
+ struct trans2_req t2_req;
+} __attribute__((packed));
+
+struct trans2_resp {
+ /* struct smb_hdr hdr precedes. Note wct = 10 + setup count */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __u16 Reserved;
+ __le16 ParameterCount;
+ __le16 ParameterOffset;
+ __le16 ParameterDisplacement;
+ __le16 DataCount;
+ __le16 DataOffset;
+ __le16 DataDisplacement;
+ __u8 SetupCount;
+ __u8 Reserved1;
+ /* SetupWords[SetupCount];
+ __u16 ByteCount;
+ __u16 Reserved2;*/
+ /* data area follows */
+} __attribute__((packed));
+
+struct smb_t2_rsp {
+ struct smb_hdr hdr;
+ struct trans2_resp t2_rsp;
+} __attribute__((packed));
+
+/* PathInfo/FileInfo infolevels */
+#define SMB_INFO_STANDARD 1
+#define SMB_SET_FILE_EA 2
+#define SMB_QUERY_FILE_EA_SIZE 2
+#define SMB_INFO_QUERY_EAS_FROM_LIST 3
+#define SMB_INFO_QUERY_ALL_EAS 4
+#define SMB_INFO_IS_NAME_VALID 6
+#define SMB_QUERY_FILE_BASIC_INFO 0x101
+#define SMB_QUERY_FILE_STANDARD_INFO 0x102
+#define SMB_QUERY_FILE_EA_INFO 0x103
+#define SMB_QUERY_FILE_NAME_INFO 0x104
+#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
+#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
+#define SMB_QUERY_FILE_ALL_INFO 0x107
+#define SMB_QUERY_ALT_NAME_INFO 0x108
+#define SMB_QUERY_FILE_STREAM_INFO 0x109
+#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
+#define SMB_QUERY_FILE_UNIX_BASIC 0x200
+#define SMB_QUERY_FILE_UNIX_LINK 0x201
+#define SMB_QUERY_POSIX_ACL 0x204
+#define SMB_QUERY_XATTR 0x205 /* e.g. system EA name space */
+#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
+#define SMB_QUERY_POSIX_PERMISSION 0x207
+#define SMB_QUERY_POSIX_LOCK 0x208
+/* #define SMB_POSIX_OPEN 0x209 */
+/* #define SMB_POSIX_UNLINK 0x20a */
+#define SMB_QUERY_FILE__UNIX_INFO2 0x20b
+#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
+#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
+#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
+#define SMB_QUERY_FILE_POSITION_INFO 0x3f6
+#define SMB_QUERY_FILE_MODE_INFO 0x3f8
+#define SMB_QUERY_FILE_ALGN_INFO 0x3f9
+
+
+#define SMB_SET_FILE_BASIC_INFO 0x101
+#define SMB_SET_FILE_DISPOSITION_INFO 0x102
+#define SMB_SET_FILE_ALLOCATION_INFO 0x103
+#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
+#define SMB_SET_FILE_UNIX_BASIC 0x200
+#define SMB_SET_FILE_UNIX_LINK 0x201
+#define SMB_SET_FILE_UNIX_HLINK 0x203
+#define SMB_SET_POSIX_ACL 0x204
+#define SMB_SET_XATTR 0x205
+#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
+#define SMB_SET_POSIX_LOCK 0x208
+#define SMB_POSIX_OPEN 0x209
+#define SMB_POSIX_UNLINK 0x20a
+#define SMB_SET_FILE_UNIX_INFO2 0x20b
+#define SMB_SET_FILE_BASIC_INFO2 0x3ec
+#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */
+#define SMB_FILE_ALL_INFO2 0x3fa
+#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
+#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
+#define SMB_FILE_MOVE_CLUSTER_INFO 0x407
+#define SMB_FILE_QUOTA_INFO 0x408
+#define SMB_FILE_REPARSEPOINT_INFO 0x409
+#define SMB_FILE_MAXIMUM_INFO 0x40d
+
+/* Find File infolevels */
+#define SMB_FIND_FILE_INFO_STANDARD 0x001
+#define SMB_FIND_FILE_QUERY_EA_SIZE 0x002
+#define SMB_FIND_FILE_QUERY_EAS_FROM_LIST 0x003
+#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
+#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
+#define SMB_FIND_FILE_NAMES_INFO 0x103
+#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
+#define SMB_FIND_FILE_ID_FULL_DIR_INFO 0x105
+#define SMB_FIND_FILE_ID_BOTH_DIR_INFO 0x106
+#define SMB_FIND_FILE_UNIX 0x202
+/* #define SMB_FIND_FILE_POSIX_INFO 0x064 */
+
+typedef struct smb_com_transaction2_qpi_req {
+ struct smb_hdr hdr; /* wct = 14+ */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount;
+ __le16 ParameterOffset;
+ __le16 DataCount;
+ __le16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __le16 SubCommand; /* one setup word */
+ __le16 ByteCount;
+ __u8 Pad;
+ __le16 InformationLevel;
+ __u32 Reserved4;
+ char FileName[1];
+} __attribute__((packed)) TRANSACTION2_QPI_REQ;
+
+typedef struct smb_com_transaction2_qpi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word is present for infolevels > 100 */
+} __attribute__((packed)) TRANSACTION2_QPI_RSP;
+
+typedef struct smb_com_transaction2_spi_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount;
+ __le16 ParameterOffset;
+ __le16 DataCount;
+ __le16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __le16 SubCommand; /* one setup word */
+ __le16 ByteCount;
+ __u8 Pad;
+ __u16 Pad1;
+ __le16 InformationLevel;
+ __u32 Reserved4;
+ char FileName[1];
+} __attribute__((packed)) TRANSACTION2_SPI_REQ;
+
+typedef struct smb_com_transaction2_spi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word is present for infolevels > 100 */
+} __attribute__((packed)) TRANSACTION2_SPI_RSP;
+
+struct set_file_rename {
+ __le32 overwrite; /* 1 = overwrite dest */
+ __u32 root_fid; /* zero */
+ __le32 target_name_len;
+ char target_name[]; /* Must be unicode */
+} __attribute__((packed));
+
+struct smb_com_transaction2_sfi_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount;
+ __le16 ParameterOffset;
+ __le16 DataCount;
+ __le16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __le16 SubCommand; /* one setup word */
+ __le16 ByteCount;
+ __u8 Pad;
+ __u16 Pad1;
+ __u16 Fid;
+ __le16 InformationLevel;
+ __u16 Reserved4;
+ __u8 payload[];
+} __attribute__((packed));
+
+struct smb_com_transaction2_sfi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved -
+ present for infolevels > 100 */
+} __attribute__((packed));
+
+struct smb_t2_qfi_req {
+ struct smb_hdr hdr;
+ struct trans2_req t2;
+ __u8 Pad;
+ __u16 Fid;
+ __le16 InformationLevel;
+} __attribute__((packed));
+
+struct smb_t2_qfi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u16 Reserved2; /* parameter word reserved -
+ present for infolevels > 100 */
+} __attribute__((packed));
+
+/*
+ * Flags on T2 FINDFIRST and FINDNEXT
+ */
+#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
+#define CIFS_SEARCH_CLOSE_AT_END 0x0002
+#define CIFS_SEARCH_RETURN_RESUME 0x0004
+#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
+#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
+
+/*
+ * Size of the resume key on FINDFIRST and FINDNEXT calls
+ */
+#define CIFS_SMB_RESUME_KEY_SIZE 4
+
+typedef struct smb_com_transaction2_ffirst_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount;
+ __le16 ParameterOffset;
+ __le16 DataCount;
+ __le16 DataOffset;
+ __u8 SetupCount; /* one */
+ __u8 Reserved3;
+ __le16 SubCommand; /* TRANS2_FIND_FIRST */
+ __le16 ByteCount;
+ __u8 Pad;
+ __le16 SearchAttributes;
+ __le16 SearchCount;
+ __le16 SearchFlags;
+ __le16 InformationLevel;
+ __le32 SearchStorageType;
+ char FileName[1];
+} __attribute__((packed)) TRANSACTION2_FFIRST_REQ;
+
+typedef struct smb_com_transaction2_ffirst_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+} __attribute__((packed)) TRANSACTION2_FFIRST_RSP;
+
+typedef struct smb_com_transaction2_ffirst_rsp_parms {
+ __u16 SearchHandle;
+ __le16 SearchCount;
+ __le16 EndofSearch;
+ __le16 EAErrorOffset;
+ __le16 LastNameOffset;
+} __attribute__((packed)) T2_FFIRST_RSP_PARMS;
+
+typedef struct smb_com_transaction2_fnext_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount;
+ __le16 ParameterOffset;
+ __le16 DataCount;
+ __le16 DataOffset;
+ __u8 SetupCount; /* one */
+ __u8 Reserved3;
+ __le16 SubCommand; /* TRANS2_FIND_NEXT */
+ __le16 ByteCount;
+ __u8 Pad;
+ __u16 SearchHandle;
+ __le16 SearchCount;
+ __le16 InformationLevel;
+ __u32 ResumeKey;
+ __le16 SearchFlags;
+ char ResumeFileName[];
+} __attribute__((packed)) TRANSACTION2_FNEXT_REQ;
+
+typedef struct smb_com_transaction2_fnext_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+} __attribute__((packed)) TRANSACTION2_FNEXT_RSP;
+
+typedef struct smb_com_transaction2_fnext_rsp_parms {
+ __le16 SearchCount;
+ __le16 EndofSearch;
+ __le16 EAErrorOffset;
+ __le16 LastNameOffset;
+} __attribute__((packed)) T2_FNEXT_RSP_PARMS;
+
+/* QFSInfo Levels */
+#define SMB_INFO_ALLOCATION 1
+#define SMB_INFO_VOLUME 2
+#define SMB_QUERY_FS_VOLUME_INFO 0x102
+#define SMB_QUERY_FS_SIZE_INFO 0x103
+#define SMB_QUERY_FS_DEVICE_INFO 0x104
+#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
+#define SMB_QUERY_CIFS_UNIX_INFO 0x200
+#define SMB_QUERY_POSIX_FS_INFO 0x201
+#define SMB_QUERY_POSIX_WHO_AM_I 0x202
+#define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203
+#define SMB_QUERY_FS_PROXY 0x204 /* WAFS enabled. Returns structure
+ FILE_SYSTEM__UNIX_INFO to tell
+ whether new NTIOCTL available
+ (0xACE) for WAN friendly SMB
+ operations to be carried */
+#define SMB_QUERY_LABEL_INFO 0x3ea
+#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
+#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
+#define SMB_QUERY_OBJECTID_INFO 0x3f0
+
+typedef struct smb_com_transaction2_qfsi_req {
+ struct smb_hdr hdr; /* wct = 14+ */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount;
+ __le16 ParameterOffset;
+ __le16 DataCount;
+ __le16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __le16 SubCommand; /* one setup word */
+ __le16 ByteCount;
+ __u8 Pad;
+ __le16 InformationLevel;
+} __attribute__((packed)) TRANSACTION2_QFSI_REQ;
+
+typedef struct smb_com_transaction_qfsi_rsp {
+ struct smb_hdr hdr; /* wct = 10 + SetupCount */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u8 Pad; /* may be three bytes? *//* followed by data area */
+} __attribute__((packed)) TRANSACTION2_QFSI_RSP;
+
+typedef struct whoami_rsp_data { /* Query level 0x202 */
+ __u32 flags; /* 0 = Authenticated user 1 = GUEST */
+ __u32 mask; /* which flags bits server understands ie 0x0001 */
+ __u64 unix_user_id;
+ __u64 unix_user_gid;
+ __u32 number_of_supplementary_gids; /* may be zero */
+ __u32 number_of_sids; /* may be zero */
+ __u32 length_of_sid_array; /* in bytes - may be zero */
+ __u32 pad; /* reserved - MBZ */
+ /* __u64 gid_array[0]; */ /* may be empty */
+ /* __u8 * psid_list */ /* may be empty */
+} __attribute__((packed)) WHOAMI_RSP_DATA;
+
+/* SETFSInfo Levels */
+#define SMB_SET_CIFS_UNIX_INFO 0x200
+/* level 0x203 is defined above in list of QFS info levels */
+/* #define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203 */
+
+/* Level 0x200 request structure follows */
+typedef struct smb_com_transaction2_setfsi_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount; /* 4 */
+ __le16 ParameterOffset;
+ __le16 DataCount; /* 12 */
+ __le16 DataOffset;
+ __u8 SetupCount; /* one */
+ __u8 Reserved3;
+ __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
+ __le16 ByteCount;
+ __u8 Pad;
+ __u16 FileNum; /* Parameters start. */
+ __le16 InformationLevel;/* Parameters end. */
+ __le16 ClientUnixMajor; /* Data start. */
+ __le16 ClientUnixMinor;
+ __le64 ClientUnixCap; /* Data end */
+} __attribute__((packed)) TRANSACTION2_SETFSI_REQ;
+
+/* level 0x203 request structure follows */
+typedef struct smb_com_transaction2_setfs_enc_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount; /* 4 */
+ __le16 ParameterOffset;
+ __le16 DataCount; /* 12 */
+ __le16 DataOffset;
+ __u8 SetupCount; /* one */
+ __u8 Reserved3;
+ __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
+ __le16 ByteCount;
+ __u8 Pad;
+ __u16 Reserved4; /* Parameters start. */
+ __le16 InformationLevel;/* Parameters end. */
+ /* NTLMSSP Blob, Data start. */
+} __attribute__((packed)) TRANSACTION2_SETFSI_ENC_REQ;
+
+/* response for setfsinfo levels 0x200 and 0x203 */
+typedef struct smb_com_transaction2_setfsi_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+} __attribute__((packed)) TRANSACTION2_SETFSI_RSP;
+
+typedef struct smb_com_transaction2_get_dfs_refer_req {
+ struct smb_hdr hdr; /* wct = 15 */
+ __le16 TotalParameterCount;
+ __le16 TotalDataCount;
+ __le16 MaxParameterCount;
+ __le16 MaxDataCount;
+ __u8 MaxSetupCount;
+ __u8 Reserved;
+ __le16 Flags;
+ __le32 Timeout;
+ __u16 Reserved2;
+ __le16 ParameterCount;
+ __le16 ParameterOffset;
+ __le16 DataCount;
+ __le16 DataOffset;
+ __u8 SetupCount;
+ __u8 Reserved3;
+ __le16 SubCommand; /* one setup word */
+ __le16 ByteCount;
+ __u8 Pad[3]; /* Win2K has sent 0x0F01 (max response length
+ perhaps?) followed by one byte pad - doesn't
+ seem to matter though */
+ __le16 MaxReferralLevel;
+ char RequestFileName[1];
+} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
+
+#define DFS_VERSION cpu_to_le16(0x0003)
+
+/* DFS server target type */
+#define DFS_TYPE_LINK 0x0000 /* also for sysvol targets */
+#define DFS_TYPE_ROOT 0x0001
+
+/* Referral Entry Flags */
+#define DFS_NAME_LIST_REF 0x0200 /* set for domain or DC referral responses */
+#define DFS_TARGET_SET_BOUNDARY 0x0400 /* only valid with version 4 dfs req */
+
+typedef struct dfs_referral_level_3 { /* version 4 is same, + one flag bit */
+ __le16 VersionNumber; /* must be 3 or 4 */
+ __le16 Size;
+ __le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */
+ __le16 ReferralEntryFlags;
+ __le32 TimeToLive;
+ __le16 DfsPathOffset;
+ __le16 DfsAlternatePathOffset;
+ __le16 NetworkAddressOffset; /* offset of the link target */
+ __u8 ServiceSiteGuid[16]; /* MBZ, ignored */
+} __attribute__((packed)) REFERRAL3;
+
+struct get_dfs_referral_rsp {
+ __le16 PathConsumed;
+ __le16 NumberOfReferrals;
+ __le32 DFSFlags;
+ REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
+ /* followed by the strings pointed to by the referral structures */
+} __packed;
+
+typedef struct smb_com_transaction_get_dfs_refer_rsp {
+ struct smb_hdr hdr; /* wct = 10 */
+ struct trans2_resp t2;
+ __u16 ByteCount;
+ __u8 Pad;
+ struct get_dfs_referral_rsp dfs_data;
+} __packed TRANSACTION2_GET_DFS_REFER_RSP;
+
+/* DFS Flags */
+#define DFSREF_REFERRAL_SERVER 0x00000001 /* all targets are DFS roots */
+#define DFSREF_STORAGE_SERVER 0x00000002 /* no further ref requests needed */
+#define DFSREF_TARGET_FAILBACK 0x00000004 /* only for DFS referral version 4 */
+
+/*
+ ************************************************************************
+ * All structs for everything above the SMB PDUs themselves
+ * (such as the T2 level specific data) go here
+ ************************************************************************
+ */
+
+/*
+ * Information on a server
+ */
+
+struct serverInfo {
+ char name[16];
+ unsigned char versionMajor;
+ unsigned char versionMinor;
+ unsigned long type;
+ unsigned int commentOffset;
+} __attribute__((packed));
+
+/*
+ * The following structure is the format of the data returned on a NetShareEnum
+ * with level "90" (x5A)
+ */
+
+struct shareInfo {
+ char shareName[13];
+ char pad;
+ unsigned short type;
+ unsigned int commentOffset;
+} __attribute__((packed));
+
+struct aliasInfo {
+ char aliasName[9];
+ char pad;
+ unsigned int commentOffset;
+ unsigned char type[2];
+} __attribute__((packed));
+
+struct aliasInfo92 {
+ int aliasNameOffset;
+ int serverNameOffset;
+ int shareNameOffset;
+} __attribute__((packed));
+
+typedef struct {
+ __le64 TotalAllocationUnits;
+ __le64 FreeAllocationUnits;
+ __le32 SectorsPerAllocationUnit;
+ __le32 BytesPerSector;
+} __attribute__((packed)) FILE_SYSTEM_INFO; /* size info, level 0x103 */
+
+typedef struct {
+ __le32 fsid;
+ __le32 SectorsPerAllocationUnit;
+ __le32 TotalAllocationUnits;
+ __le32 FreeAllocationUnits;
+ __le16 BytesPerSector;
+} __attribute__((packed)) FILE_SYSTEM_ALLOC_INFO;
+
+typedef struct {
+ __le16 MajorVersionNumber;
+ __le16 MinorVersionNumber;
+ __le64 Capability;
+} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extension level 0x200*/
+
+/* Version numbers for CIFS UNIX major and minor. */
+#define CIFS_UNIX_MAJOR_VERSION 1
+#define CIFS_UNIX_MINOR_VERSION 0
+
+/* Linux/Unix extensions capability flags */
+#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
+#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
+#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
+#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
+#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */
+#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
+ calls including posix open
+ and posix unlink */
+#define CIFS_UNIX_LARGE_READ_CAP 0x00000040 /* support reads >128K (up
+ to 0xFFFF00 */
+#define CIFS_UNIX_LARGE_WRITE_CAP 0x00000080
+#define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x00000100 /* can do SPNEGO crypt */
+#define CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP 0x00000200 /* must do */
+#define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and
+ QFS PROXY call */
+#ifdef CONFIG_CIFS_POSIX
+/* presumably don't need the 0x20 POSIX_PATH_OPS_CAP since we never send
+ LockingX instead of posix locking call on unix sess (and we do not expect
+ LockingX to use different (ie Windows) semantics than posix locking on
+ the same session (if WINE needs to do this later, we can add this cap
+ back in later */
+/* #define CIFS_UNIX_CAP_MASK 0x000000fb */
+#define CIFS_UNIX_CAP_MASK 0x000003db
+#else
+#define CIFS_UNIX_CAP_MASK 0x00000013
+#endif /* CONFIG_CIFS_POSIX */
+
+
+#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
+
+typedef struct {
+ /* For undefined recommended transfer size return -1 in that field */
+ __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
+ __le32 BlockSize;
+ /* The next three fields are in terms of the block size.
+ (above). If block size is unknown, 4096 would be a
+ reasonable block size for a server to report.
+ Note that returning the blocks/blocksavail removes need
+ to make a second call (to QFSInfo level 0x103 to get this info.
+ UserBlockAvail is typically less than or equal to BlocksAvail,
+ if no distinction is made return the same value in each */
+ __le64 TotalBlocks;
+ __le64 BlocksAvail; /* bfree */
+ __le64 UserBlocksAvail; /* bavail */
+ /* For undefined Node fields or FSID return -1 */
+ __le64 TotalFileNodes;
+ __le64 FreeFileNodes;
+ __le64 FileSysIdentifier; /* fsid */
+ /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
+ /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
+} __attribute__((packed)) FILE_SYSTEM_POSIX_INFO;
+
+/* DeviceType Flags */
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+
+/* Device Characteristics */
+#define FILE_REMOVABLE_MEDIA 0x00000001
+#define FILE_READ_ONLY_DEVICE 0x00000002
+#define FILE_FLOPPY_DISKETTE 0x00000004
+#define FILE_WRITE_ONCE_MEDIA 0x00000008
+#define FILE_REMOTE_DEVICE 0x00000010
+#define FILE_DEVICE_IS_MOUNTED 0x00000020
+#define FILE_VIRTUAL_VOLUME 0x00000040
+#define FILE_DEVICE_SECURE_OPEN 0x00000100
+#define FILE_CHARACTERISTIC_TS_DEVICE 0x00001000
+#define FILE_CHARACTERISTIC_WEBDAV_DEVICE 0x00002000
+#define FILE_PORTABLE_DEVICE 0x00004000
+#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000
+
+typedef struct {
+ __le32 DeviceType;
+ __le32 DeviceCharacteristics;
+} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */
+
+/* minimum includes first three fields, and empty FS Name */
+#define MIN_FS_ATTR_INFO_SIZE 12
+
+
+/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */
+#define FILE_SUPPORTS_SPARSE_VDL 0x10000000 /* faster nonsparse extend */
+#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000 /* allow ioctl dup extents */
+#define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000
+#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
+#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
+#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
+#define FILE_SUPPORTS_HARD_LINKS 0x00400000
+#define FILE_SUPPORTS_TRANSACTIONS 0x00200000
+#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
+#define FILE_READ_ONLY_VOLUME 0x00080000
+#define FILE_NAMED_STREAMS 0x00040000
+#define FILE_SUPPORTS_ENCRYPTION 0x00020000
+#define FILE_SUPPORTS_OBJECT_IDS 0x00010000
+#define FILE_VOLUME_IS_COMPRESSED 0x00008000
+#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100
+#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080
+#define FILE_SUPPORTS_SPARSE_FILES 0x00000040
+#define FILE_VOLUME_QUOTAS 0x00000020
+#define FILE_FILE_COMPRESSION 0x00000010
+#define FILE_PERSISTENT_ACLS 0x00000008
+#define FILE_UNICODE_ON_DISK 0x00000004
+#define FILE_CASE_PRESERVED_NAMES 0x00000002
+#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
+typedef struct {
+ __le32 Attributes;
+ __le32 MaxPathNameComponentLength;
+ __le32 FileSystemNameLen;
+ char FileSystemName[52]; /* do not have to save this - get subset? */
+} __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO;
+
+/******************************************************************************/
+/* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */
+/******************************************************************************/
+typedef struct { /* data block encoding of response to level 263 QPathInfo */
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le32 Attributes;
+ __u32 Pad1;
+ __le64 AllocationSize;
+ __le64 EndOfFile; /* size ie offset to first free byte in file */
+ __le32 NumberOfLinks; /* hard links */
+ __u8 DeletePending;
+ __u8 Directory;
+ __u16 Pad2;
+ __le64 IndexNumber;
+ __le32 EASize;
+ __le32 AccessFlags;
+ __u64 IndexNumber1;
+ __le64 CurrentByteOffset;
+ __le32 Mode;
+ __le32 AlignmentRequirement;
+ __le32 FileNameLength;
+ char FileName[1];
+} __attribute__((packed)) FILE_ALL_INFO; /* level 0x107 QPathInfo */
+
+typedef struct {
+ __le64 AllocationSize;
+ __le64 EndOfFile; /* size ie offset to first free byte in file */
+ __le32 NumberOfLinks; /* hard links */
+ __u8 DeletePending;
+ __u8 Directory;
+ __u16 Pad;
+} __attribute__((packed)) FILE_STANDARD_INFO; /* level 0x102 QPathInfo */
+
+
+/* defines for enumerating possible values of the Unix type field below */
+#define UNIX_FILE 0
+#define UNIX_DIR 1
+#define UNIX_SYMLINK 2
+#define UNIX_CHARDEV 3
+#define UNIX_BLOCKDEV 4
+#define UNIX_FIFO 5
+#define UNIX_SOCKET 6
+typedef struct {
+ __le64 EndOfFile;
+ __le64 NumOfBytes;
+ __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */
+ __le64 LastAccessTime;
+ __le64 LastModificationTime;
+ __le64 Uid;
+ __le64 Gid;
+ __le32 Type;
+ __le64 DevMajor;
+ __le64 DevMinor;
+ __le64 UniqueId;
+ __le64 Permissions;
+ __le64 Nlinks;
+} __attribute__((packed)) FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
+
+typedef struct {
+ char LinkDest[1];
+} __attribute__((packed)) FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
+
+/* The following three structures are needed only for
+ setting time to NT4 and some older servers via
+ the primitive DOS time format */
+typedef struct {
+ __u16 Day:5;
+ __u16 Month:4;
+ __u16 Year:7;
+} __attribute__((packed)) SMB_DATE;
+
+typedef struct {
+ __u16 TwoSeconds:5;
+ __u16 Minutes:6;
+ __u16 Hours:5;
+} __attribute__((packed)) SMB_TIME;
+
+typedef struct {
+ __le16 CreationDate; /* SMB Date see above */
+ __le16 CreationTime; /* SMB Time */
+ __le16 LastAccessDate;
+ __le16 LastAccessTime;
+ __le16 LastWriteDate;
+ __le16 LastWriteTime;
+ __le32 DataSize; /* File Size (EOF) */
+ __le32 AllocationSize;
+ __le16 Attributes; /* verify not u32 */
+ __le32 EASize;
+} __attribute__((packed)) FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */
+
+typedef struct {
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le32 Attributes;
+ __u32 Pad;
+} __attribute__((packed)) FILE_BASIC_INFO; /* size info, level 0x101 */
+
+struct file_allocation_info {
+ __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
+} __attribute__((packed)); /* size used on disk, for level 0x103 for set,
+ 0x105 for query */
+
+struct file_end_of_file_info {
+ __le64 FileSize; /* offset to end of file */
+} __attribute__((packed)); /* size info, level 0x104 for set, 0x106 for query */
+
+struct file_alt_name_info {
+ __u8 alt_name[1];
+} __attribute__((packed)); /* level 0x0108 */
+
+struct file_stream_info {
+ __le32 number_of_streams; /* BB check sizes and verify location */
+ /* followed by info on streams themselves
+ u64 size;
+ u64 allocation_size
+ stream info */
+}; /* level 0x109 */
+
+struct file_compression_info {
+ __le64 compressed_size;
+ __le16 format;
+ __u8 unit_shift;
+ __u8 ch_shift;
+ __u8 cl_shift;
+ __u8 pad[3];
+} __attribute__((packed)); /* level 0x10b */
+
+/* POSIX ACL set/query path info structures */
+#define CIFS_ACL_VERSION 1
+struct cifs_posix_ace { /* access control entry (ACE) */
+ __u8 cifs_e_tag;
+ __u8 cifs_e_perm;
+ __le64 cifs_uid; /* or gid */
+} __attribute__((packed));
+
+struct cifs_posix_acl { /* access conrol list (ACL) */
+ __le16 version;
+ __le16 access_entry_count; /* access ACL - count of entries */
+ __le16 default_entry_count; /* default ACL - count of entries */
+ struct cifs_posix_ace ace_array[];
+ /* followed by
+ struct cifs_posix_ace default_ace_arraay[] */
+} __attribute__((packed)); /* level 0x204 */
+
+/* types of access control entries already defined in posix_acl.h */
+/* #define CIFS_POSIX_ACL_USER_OBJ 0x01
+#define CIFS_POSIX_ACL_USER 0x02
+#define CIFS_POSIX_ACL_GROUP_OBJ 0x04
+#define CIFS_POSIX_ACL_GROUP 0x08
+#define CIFS_POSIX_ACL_MASK 0x10
+#define CIFS_POSIX_ACL_OTHER 0x20 */
+
+/* types of perms */
+/* #define CIFS_POSIX_ACL_EXECUTE 0x01
+#define CIFS_POSIX_ACL_WRITE 0x02
+#define CIFS_POSIX_ACL_READ 0x04 */
+
+/* end of POSIX ACL definitions */
+
+/* POSIX Open Flags */
+#define SMB_O_RDONLY 0x1
+#define SMB_O_WRONLY 0x2
+#define SMB_O_RDWR 0x4
+#define SMB_O_CREAT 0x10
+#define SMB_O_EXCL 0x20
+#define SMB_O_TRUNC 0x40
+#define SMB_O_APPEND 0x80
+#define SMB_O_SYNC 0x100
+#define SMB_O_DIRECTORY 0x200
+#define SMB_O_NOFOLLOW 0x400
+#define SMB_O_DIRECT 0x800
+
+typedef struct {
+ __le32 OpenFlags; /* same as NT CreateX */
+ __le32 PosixOpenFlags;
+ __le64 Permissions;
+ __le16 Level; /* reply level requested (see QPathInfo levels) */
+} __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */
+
+typedef struct {
+ __le16 OplockFlags;
+ __u16 Fid;
+ __le32 CreateAction;
+ __le16 ReturnedLevel;
+ __le16 Pad;
+ /* struct following varies based on requested level */
+} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
+
+#define SMB_POSIX_UNLINK_FILE_TARGET 0
+#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1
+
+struct unlink_psx_rq { /* level 0x20a SetPathInfo */
+ __le16 type;
+} __attribute__((packed));
+
+struct file_internal_info {
+ __le64 UniqueId; /* inode number */
+} __attribute__((packed)); /* level 0x3ee */
+
+struct file_mode_info {
+ __le32 Mode;
+} __attribute__((packed)); /* level 0x3f8 */
+
+struct file_attrib_tag {
+ __le32 Attribute;
+ __le32 ReparseTag;
+} __attribute__((packed)); /* level 0x40b */
+
+
+/********************************************************/
+/* FindFirst/FindNext transact2 data buffer formats */
+/********************************************************/
+
+typedef struct {
+ __le32 NextEntryOffset;
+ __u32 ResumeKey; /* as with FileIndex - no need to convert */
+ FILE_UNIX_BASIC_INFO basic;
+ char FileName[1];
+} __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */
+
+typedef struct {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ char FileName[1];
+} __attribute__((packed)) FILE_DIRECTORY_INFO; /* level 0x101 FF resp data */
+
+typedef struct {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ __le32 EaSize; /* length of the xattrs */
+ char FileName[1];
+} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 rsp data */
+
+typedef struct {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ __le32 EaSize; /* EA size */
+ __le32 Reserved;
+ __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
+ char FileName[1];
+} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */
+
+typedef struct {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ __le32 EaSize; /* length of the xattrs */
+ __u8 ShortNameLength;
+ __u8 Reserved;
+ __u8 ShortName[24];
+ char FileName[1];
+} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FFrsp data */
+
+typedef struct {
+ __u32 ResumeKey;
+ __le16 CreationDate; /* SMB Date */
+ __le16 CreationTime; /* SMB Time */
+ __le16 LastAccessDate;
+ __le16 LastAccessTime;
+ __le16 LastWriteDate;
+ __le16 LastWriteTime;
+ __le32 DataSize; /* File Size (EOF) */
+ __le32 AllocationSize;
+ __le16 Attributes; /* verify not u32 */
+ __u8 FileNameLength;
+ char FileName[1];
+} __attribute__((packed)) FIND_FILE_STANDARD_INFO; /* level 0x1 FF resp data */
+
+
+struct win_dev {
+ unsigned char type[8]; /* IntxCHR or IntxBLK */
+ __le64 major;
+ __le64 minor;
+} __attribute__((packed));
+
+struct gea {
+ unsigned char name_len;
+ char name[1];
+} __attribute__((packed));
+
+struct gealist {
+ unsigned long list_len;
+ struct gea list[1];
+} __attribute__((packed));
+
+struct fea {
+ unsigned char EA_flags;
+ __u8 name_len;
+ __le16 value_len;
+ char name[1];
+ /* optionally followed by value */
+} __attribute__((packed));
+/* flags for _FEA.fEA */
+#define FEA_NEEDEA 0x80 /* need EA bit */
+
+struct fealist {
+ __le32 list_len;
+ struct fea list[1];
+} __attribute__((packed));
+
+/* used to hold an arbitrary blob of data */
+struct data_blob {
+ __u8 *data;
+ size_t length;
+ void (*free) (struct data_blob *data_blob);
+} __attribute__((packed));
+
+
+#ifdef CONFIG_CIFS_POSIX
+/*
+ For better POSIX semantics from Linux client, (even better
+ than the existing CIFS Unix Extensions) we need updated PDUs for:
+
+ 1) PosixCreateX - to set and return the mode, inode#, device info and
+ perhaps add a CreateDevice - to create Pipes and other special .inodes
+ Also note POSIX open flags
+ 2) Close - to return the last write time to do cache across close
+ more safely
+ 3) FindFirst return unique inode number - what about resume key, two
+ forms short (matches readdir) and full (enough info to cache inodes)
+ 4) Mkdir - set mode
+
+ And under consideration:
+ 5) FindClose2 (return nanosecond timestamp ??)
+ 6) Use nanosecond timestamps throughout all time fields if
+ corresponding attribute flag is set
+ 7) sendfile - handle based copy
+
+ what about fixing 64 bit alignment
+
+ There are also various legacy SMB/CIFS requests used as is
+
+ From existing Lanman and NTLM dialects:
+ --------------------------------------
+ NEGOTIATE
+ SESSION_SETUP_ANDX (BB which?)
+ TREE_CONNECT_ANDX (BB which wct?)
+ TREE_DISCONNECT (BB add volume timestamp on response)
+ LOGOFF_ANDX
+ DELETE (note delete open file behavior)
+ DELETE_DIRECTORY
+ READ_AND_X
+ WRITE_AND_X
+ LOCKING_AND_X (note posix lock semantics)
+ RENAME (note rename across dirs and open file rename posix behaviors)
+ NT_RENAME (for hardlinks) Is this good enough for all features?
+ FIND_CLOSE2
+ TRANSACTION2 (18 cases)
+ SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
+ (BB verify that never need to set allocation size)
+ SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via
+ Unix ext?)
+
+ COPY (note support for copy across directories) - FUTURE, OPTIONAL
+ setting/getting OS/2 EAs - FUTURE (BB can this handle
+ setting Linux xattrs perfectly) - OPTIONAL
+ dnotify - FUTURE, OPTIONAL
+ quota - FUTURE, OPTIONAL
+
+ Note that various requests implemented for NT interop such as
+ NT_TRANSACT (IOCTL) QueryReparseInfo
+ are unneeded to servers compliant with the CIFS POSIX extensions
+
+ From CIFS Unix Extensions:
+ -------------------------
+ T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
+ T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
+ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
+ T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) BB check for missing
+ inode fields
+ Actually a need QUERY_FILE_UNIX_INFO
+ since has inode num
+ BB what about a) blksize/blkbits/blocks
+ b) i_version
+ c) i_rdev
+ d) notify mask?
+ e) generation
+ f) size_seqcount
+ T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
+ TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
+ T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
+ */
+
+/* xsymlink is a symlink format (used by MacOS) that can be used
+ to save symlink info in a regular file when
+ mounted to operating systems that do not
+ support the cifs Unix extensions or EAs (for xattr
+ based symlinks). For such a file to be recognized
+ as containing symlink data:
+
+ 1) file size must be 1067,
+ 2) signature must begin file data,
+ 3) length field must be set to ASCII representation
+ of a number which is less than or equal to 1024,
+ 4) md5 must match that of the path data */
+
+struct xsymlink {
+ /* 1067 bytes */
+ char signature[4]; /* XSym */ /* not null terminated */
+ char cr0; /* \n */
+/* ASCII representation of length (4 bytes decimal) terminated by \n not null */
+ char length[4];
+ char cr1; /* \n */
+/* md5 of valid subset of path ie path[0] through path[length-1] */
+ __u8 md5[32];
+ char cr2; /* \n */
+/* if room left, then end with \n then 0x20s by convention but not required */
+ char path[1024];
+} __attribute__((packed));
+
+typedef struct file_xattr_info {
+ /* BB do we need another field for flags? BB */
+ __u32 xattr_name_len;
+ __u32 xattr_value_len;
+ char xattr_name[];
+ /* followed by xattr_value[xattr_value_len], no pad */
+} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info
+ level 0x205 */
+
+/* flags for lsattr and chflags commands removed arein uapi/linux/fs.h */
+
+typedef struct file_chattr_info {
+ __le64 mask; /* list of all possible attribute bits */
+ __le64 mode; /* list of actual attribute bits on this inode */
+} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes
+ (chattr, chflags) level 0x206 */
+#endif /* POSIX */
+#endif /* _CIFSPDU_H */
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
new file mode 100644
index 000000000000..98513f5af3f9
--- /dev/null
+++ b/fs/smb/client/cifsproto.h
@@ -0,0 +1,696 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+#ifndef _CIFSPROTO_H
+#define _CIFSPROTO_H
+#include <linux/nls.h>
+#include "trace.h"
+#ifdef CONFIG_CIFS_DFS_UPCALL
+#include "dfs_cache.h"
+#endif
+
+struct statfs;
+struct smb_rqst;
+struct smb3_fs_context;
+
+/*
+ *****************************************************************
+ * All Prototypes
+ *****************************************************************
+ */
+
+extern struct smb_hdr *cifs_buf_get(void);
+extern void cifs_buf_release(void *);
+extern struct smb_hdr *cifs_small_buf_get(void);
+extern void cifs_small_buf_release(void *);
+extern void free_rsp_buf(int, void *);
+extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
+ unsigned int /* length */);
+extern unsigned int _get_xid(void);
+extern void _free_xid(unsigned int);
+#define get_xid() \
+({ \
+ unsigned int __xid = _get_xid(); \
+ cifs_dbg(FYI, "VFS: in %s as Xid: %u with uid: %d\n", \
+ __func__, __xid, \
+ from_kuid(&init_user_ns, current_fsuid())); \
+ trace_smb3_enter(__xid, __func__); \
+ __xid; \
+})
+
+#define free_xid(curr_xid) \
+do { \
+ _free_xid(curr_xid); \
+ cifs_dbg(FYI, "VFS: leaving %s (xid = %u) rc = %d\n", \
+ __func__, curr_xid, (int)rc); \
+ if (rc) \
+ trace_smb3_exit_err(curr_xid, __func__, (int)rc); \
+ else \
+ trace_smb3_exit_done(curr_xid, __func__); \
+} while (0)
+extern int init_cifs_idmap(void);
+extern void exit_cifs_idmap(void);
+extern int init_cifs_spnego(void);
+extern void exit_cifs_spnego(void);
+extern const char *build_path_from_dentry(struct dentry *, void *);
+extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
+ void *page, bool prefix);
+static inline void *alloc_dentry_path(void)
+{
+ return __getname();
+}
+
+static inline void free_dentry_path(void *page)
+{
+ if (page)
+ __putname(page);
+}
+
+extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
+ struct cifs_sb_info *cifs_sb,
+ struct cifs_tcon *tcon,
+ int add_treename);
+extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
+extern char *cifs_compose_mount_options(const char *sb_mountdata,
+ const char *fullpath, const struct dfs_info3_param *ref,
+ char **devname);
+extern void delete_mid(struct mid_q_entry *mid);
+extern void release_mid(struct mid_q_entry *mid);
+extern void cifs_wake_up_task(struct mid_q_entry *mid);
+extern int cifs_handle_standard(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid);
+extern int smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx);
+extern int smb3_parse_opt(const char *options, const char *key, char **val);
+extern bool cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs);
+extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
+extern int cifs_call_async(struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ mid_receive_t *receive, mid_callback_t *callback,
+ mid_handle_t *handle, void *cbdata, const int flags,
+ const struct cifs_credits *exist_credits);
+extern struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses);
+extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ struct smb_rqst *rqst, int *resp_buf_type,
+ const int flags, struct kvec *resp_iov);
+extern int compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const int flags, const int num_rqst,
+ struct smb_rqst *rqst, int *resp_buf_type,
+ struct kvec *resp_iov);
+extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
+ struct smb_hdr * /* input */ ,
+ struct smb_hdr * /* out */ ,
+ int * /* bytes returned */ , const int);
+extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
+ char *in_buf, int flags);
+extern struct mid_q_entry *cifs_setup_request(struct cifs_ses *,
+ struct TCP_Server_Info *,
+ struct smb_rqst *);
+extern struct mid_q_entry *cifs_setup_async_request(struct TCP_Server_Info *,
+ struct smb_rqst *);
+extern int cifs_check_receive(struct mid_q_entry *mid,
+ struct TCP_Server_Info *server, bool log_error);
+extern int cifs_wait_mtu_credits(struct TCP_Server_Info *server,
+ unsigned int size, unsigned int *num,
+ struct cifs_credits *credits);
+extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
+ struct kvec *, int /* nvec to send */,
+ int * /* type of buf returned */, const int flags,
+ struct kvec * /* resp vec */);
+extern int SendReceiveBlockingLock(const unsigned int xid,
+ struct cifs_tcon *ptcon,
+ struct smb_hdr *in_buf ,
+ struct smb_hdr *out_buf,
+ int *bytes_returned);
+void
+cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
+ bool all_channels);
+void
+cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
+ bool mark_smb_session);
+extern int cifs_reconnect(struct TCP_Server_Info *server,
+ bool mark_smb_session);
+extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr);
+extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
+extern bool backup_cred(struct cifs_sb_info *);
+extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
+extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
+ unsigned int bytes_written);
+extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int);
+extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
+ int flags,
+ struct cifsFileInfo **ret_file);
+extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
+ int flags,
+ struct cifsFileInfo **ret_file);
+extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
+extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
+ struct cifsFileInfo **ret_file);
+extern unsigned int smbCalcSize(void *buf);
+extern int decode_negTokenInit(unsigned char *security_blob, int length,
+ struct TCP_Server_Info *server);
+extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
+extern void cifs_set_port(struct sockaddr *addr, const unsigned short int port);
+extern int map_smb_to_linux_error(char *buf, bool logErr);
+extern int map_and_check_smb_error(struct mid_q_entry *mid, bool logErr);
+extern void header_assemble(struct smb_hdr *, char /* command */ ,
+ const struct cifs_tcon *, int /* length of
+ fixed section (word count) in two byte units */);
+extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
+ struct cifs_ses *ses,
+ void **request_buf);
+extern enum securityEnum select_sectype(struct TCP_Server_Info *server,
+ enum securityEnum requested);
+extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp);
+extern struct timespec64 cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
+extern u64 cifs_UnixTimeToNT(struct timespec64);
+extern struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
+ int offset);
+extern void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
+extern int cifs_get_writer(struct cifsInodeInfo *cinode);
+extern void cifs_put_writer(struct cifsInodeInfo *cinode);
+extern void cifs_done_oplock_break(struct cifsInodeInfo *cinode);
+extern int cifs_unlock_range(struct cifsFileInfo *cfile,
+ struct file_lock *flock, const unsigned int xid);
+extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile);
+
+extern void cifs_down_write(struct rw_semaphore *sem);
+struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
+ struct tcon_link *tlink, __u32 oplock,
+ const char *symlink_target);
+extern int cifs_posix_open(const char *full_path, struct inode **inode,
+ struct super_block *sb, int mode,
+ unsigned int f_flags, __u32 *oplock, __u16 *netfid,
+ unsigned int xid);
+void cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr);
+extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
+ FILE_UNIX_BASIC_INFO *info,
+ struct cifs_sb_info *cifs_sb);
+extern void cifs_dir_info_to_fattr(struct cifs_fattr *, FILE_DIRECTORY_INFO *,
+ struct cifs_sb_info *);
+extern int cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
+extern struct inode *cifs_iget(struct super_block *sb,
+ struct cifs_fattr *fattr);
+
+int cifs_get_inode_info(struct inode **inode, const char *full_path,
+ struct cifs_open_info_data *data, struct super_block *sb, int xid,
+ const struct cifs_fid *fid);
+extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
+ struct super_block *sb, unsigned int xid);
+extern int cifs_get_inode_info_unix(struct inode **pinode,
+ const unsigned char *search_path,
+ struct super_block *sb, unsigned int xid);
+extern int cifs_set_file_info(struct inode *inode, struct iattr *attrs,
+ unsigned int xid, const char *full_path, __u32 dosattr);
+extern int cifs_rename_pending_delete(const char *full_path,
+ struct dentry *dentry,
+ const unsigned int xid);
+extern int sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
+ struct cifs_fattr *fattr, uint sidtype);
+extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
+ struct cifs_fattr *fattr, struct inode *inode,
+ bool get_mode_from_special_sid,
+ const char *path, const struct cifs_fid *pfid);
+extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
+ kuid_t uid, kgid_t gid);
+extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
+ const char *, u32 *, u32);
+extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
+ const struct cifs_fid *, u32 *, u32);
+extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
+ const char *, int);
+extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
+extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
+extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace);
+
+extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
+extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
+ unsigned int to_read);
+extern ssize_t cifs_discard_from_socket(struct TCP_Server_Info *server,
+ size_t to_read);
+extern int cifs_read_page_from_socket(struct TCP_Server_Info *server,
+ struct page *page,
+ unsigned int page_offset,
+ unsigned int to_read);
+extern int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb);
+extern int cifs_match_super(struct super_block *, void *);
+extern int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx);
+extern void cifs_umount(struct cifs_sb_info *);
+extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
+extern void cifs_reopen_persistent_handles(struct cifs_tcon *tcon);
+
+extern bool cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset,
+ __u64 length, __u8 type, __u16 flags,
+ struct cifsLockInfo **conf_lock,
+ int rw_check);
+extern void cifs_add_pending_open(struct cifs_fid *fid,
+ struct tcon_link *tlink,
+ struct cifs_pending_open *open);
+extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
+ struct tcon_link *tlink,
+ struct cifs_pending_open *open);
+extern void cifs_del_pending_open(struct cifs_pending_open *open);
+
+extern bool cifs_is_deferred_close(struct cifsFileInfo *cfile,
+ struct cifs_deferred_close **dclose);
+
+extern void cifs_add_deferred_close(struct cifsFileInfo *cfile,
+ struct cifs_deferred_close *dclose);
+
+extern void cifs_del_deferred_close(struct cifsFileInfo *cfile);
+
+extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
+
+extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
+
+extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
+ const char *path);
+extern struct TCP_Server_Info *
+cifs_get_tcp_session(struct smb3_fs_context *ctx,
+ struct TCP_Server_Info *primary_server);
+extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
+ int from_reconnect);
+extern void cifs_put_tcon(struct cifs_tcon *tcon);
+
+#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
+extern void cifs_dfs_release_automount_timer(void);
+#else /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
+#define cifs_dfs_release_automount_timer() do { } while (0)
+#endif /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
+
+void cifs_proc_init(void);
+void cifs_proc_clean(void);
+
+extern void cifs_move_llist(struct list_head *source, struct list_head *dest);
+extern void cifs_free_llist(struct list_head *llist);
+extern void cifs_del_lock_waiters(struct cifsLockInfo *lock);
+
+extern int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon,
+ const struct nls_table *nlsc);
+
+extern int cifs_negotiate_protocol(const unsigned int xid,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+extern int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ struct nls_table *nls_info);
+extern int cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required);
+extern int CIFSSMBNegotiate(const unsigned int xid,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+
+extern int CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
+ const char *tree, struct cifs_tcon *tcon,
+ const struct nls_table *);
+
+extern int CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *searchName, struct cifs_sb_info *cifs_sb,
+ __u16 *searchHandle, __u16 search_flags,
+ struct cifs_search_info *psrch_inf,
+ bool msearch);
+
+extern int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
+ __u16 searchHandle, __u16 search_flags,
+ struct cifs_search_info *psrch_inf);
+
+extern int CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u16 search_handle);
+
+extern int CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ u16 netfid, FILE_ALL_INFO *pFindData);
+extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_Name, FILE_ALL_INFO *data,
+ int legacy /* whether to use old info level */,
+ const struct nls_table *nls_codepage, int remap);
+extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, FILE_ALL_INFO *data,
+ const struct nls_table *nls_codepage, int remap);
+
+extern int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ u16 netfid, FILE_UNIX_BASIC_INFO *pFindData);
+extern int CIFSSMBUnixQPathInfo(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const unsigned char *searchName,
+ FILE_UNIX_BASIC_INFO *pFindData,
+ const struct nls_table *nls_codepage, int remap);
+
+extern int CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
+ const char *search_name,
+ struct dfs_info3_param **target_nodes,
+ unsigned int *num_of_nodes,
+ const struct nls_table *nls_codepage, int remap);
+
+extern int parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
+ unsigned int *num_of_nodes,
+ struct dfs_info3_param **target_nodes,
+ const struct nls_table *nls_codepage, int remap,
+ const char *searchName, bool is_unicode);
+extern void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ struct smb3_fs_context *ctx);
+extern int CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ struct kstatfs *FSData);
+extern int SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ struct kstatfs *FSData);
+extern int CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ __u64 cap);
+
+extern int CIFSSMBQFSAttributeInfo(const unsigned int xid,
+ struct cifs_tcon *tcon);
+extern int CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon);
+extern int CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon);
+extern int CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ struct kstatfs *FSData);
+
+extern int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fileName, const FILE_BASIC_INFO *data,
+ const struct nls_table *nls_codepage,
+ struct cifs_sb_info *cifs_sb);
+extern int CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const FILE_BASIC_INFO *data, __u16 fid,
+ __u32 pid_of_opener);
+extern int CIFSSMBSetFileDisposition(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ bool delete_file, __u16 fid,
+ __u32 pid_of_opener);
+extern int CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *file_name, __u64 size,
+ struct cifs_sb_info *cifs_sb, bool set_allocation);
+extern int CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, __u64 size,
+ bool set_allocation);
+
+struct cifs_unix_set_info_args {
+ __u64 ctime;
+ __u64 atime;
+ __u64 mtime;
+ __u64 mode;
+ kuid_t uid;
+ kgid_t gid;
+ dev_t device;
+};
+
+extern int CIFSSMBUnixSetFileInfo(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const struct cifs_unix_set_info_args *args,
+ u16 fid, u32 pid_of_opener);
+
+extern int CIFSSMBUnixSetPathInfo(const unsigned int xid,
+ struct cifs_tcon *tcon, const char *file_name,
+ const struct cifs_unix_set_info_args *args,
+ const struct nls_table *nls_codepage,
+ int remap);
+
+extern int CIFSSMBMkDir(const unsigned int xid, struct inode *inode,
+ umode_t mode, struct cifs_tcon *tcon,
+ const char *name, struct cifs_sb_info *cifs_sb);
+extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *name, struct cifs_sb_info *cifs_sb);
+extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *name, __u16 type,
+ const struct nls_table *nls_codepage,
+ int remap_special_chars);
+extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *name, struct cifs_sb_info *cifs_sb);
+extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb);
+extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
+ int netfid, const char *target_name,
+ const struct nls_table *nls_codepage,
+ int remap_special_chars);
+extern int CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb);
+extern int CIFSUnixCreateHardLink(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage,
+ int remap_special_chars);
+extern int CIFSUnixCreateSymLink(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage, int remap);
+extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const unsigned char *searchName, char **syminfo,
+ const struct nls_table *nls_codepage, int remap);
+extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
+ __u16 fid, char **symlinkinfo,
+ const struct nls_table *nls_codepage);
+extern int CIFSSMB_set_compression(const unsigned int xid,
+ struct cifs_tcon *tcon, __u16 fid);
+extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
+ int *oplock, FILE_ALL_INFO *buf);
+extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fileName, const int disposition,
+ const int access_flags, const int omode,
+ __u16 *netfid, int *pOplock, FILE_ALL_INFO *,
+ const struct nls_table *nls_codepage, int remap);
+extern int CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
+ u32 posix_flags, __u64 mode, __u16 *netfid,
+ FILE_UNIX_BASIC_INFO *pRetData,
+ __u32 *pOplock, const char *name,
+ const struct nls_table *nls_codepage, int remap);
+extern int CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon,
+ const int smb_file_id);
+
+extern int CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon,
+ const int smb_file_id);
+
+extern int CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, char **buf,
+ int *return_buf_type);
+extern int CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, const char *buf);
+extern int CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, struct kvec *iov, const int nvec);
+extern int CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, __u64 *inode_number,
+ const struct nls_table *nls_codepage,
+ int remap);
+
+extern int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u16 netfid, const __u8 lock_type,
+ const __u32 num_unlock, const __u32 num_lock,
+ LOCKING_ANDX_RANGE *buf);
+extern int CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u16 netfid, const __u32 netpid, const __u64 len,
+ const __u64 offset, const __u32 numUnlock,
+ const __u32 numLock, const __u8 lockType,
+ const bool waitFlag, const __u8 oplock_level);
+extern int CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u16 smb_file_id, const __u32 netpid,
+ const loff_t start_offset, const __u64 len,
+ struct file_lock *, const __u16 lock_type,
+ const bool waitFlag);
+extern int CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon);
+extern int CIFSSMBEcho(struct TCP_Server_Info *server);
+extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses);
+
+extern struct cifs_ses *sesInfoAlloc(void);
+extern void sesInfoFree(struct cifs_ses *);
+extern struct cifs_tcon *tconInfoAlloc(void);
+extern void tconInfoFree(struct cifs_tcon *);
+
+extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
+ __u32 *pexpected_response_sequence_number);
+extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
+ __u32 *);
+extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
+extern int cifs_verify_signature(struct smb_rqst *rqst,
+ struct TCP_Server_Info *server,
+ __u32 expected_sequence_number);
+extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
+extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
+extern int calc_seckey(struct cifs_ses *);
+extern int generate_smb30signingkey(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+extern int generate_smb311signingkey(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+extern int CIFSSMBCopy(unsigned int xid,
+ struct cifs_tcon *source_tcon,
+ const char *fromName,
+ const __u16 target_tid,
+ const char *toName, const int flags,
+ const struct nls_table *nls_codepage,
+ int remap_special_chars);
+extern ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *searchName,
+ const unsigned char *ea_name, char *EAData,
+ size_t bufsize, struct cifs_sb_info *cifs_sb);
+extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fileName, const char *ea_name,
+ const void *ea_value, const __u16 ea_value_len,
+ const struct nls_table *nls_codepage,
+ struct cifs_sb_info *cifs_sb);
+extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
+ __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
+extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,
+ struct cifs_ntsd *, __u32, int);
+extern int CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *searchName,
+ char *acl_inf, const int buflen, const int acl_type,
+ const struct nls_table *nls_codepage, int remap_special_chars);
+extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *fileName,
+ const char *local_acl, const int buflen, const int acl_type,
+ const struct nls_table *nls_codepage, int remap_special_chars);
+extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
+ const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
+#endif /* CIFS_ALLOW_INSECURE_LEGACY */
+extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
+extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr);
+extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ struct cifs_fattr *fattr,
+ const unsigned char *path);
+extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
+ const struct nls_table *codepage);
+
+extern int
+cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname);
+
+extern struct TCP_Server_Info *
+cifs_find_tcp_session(struct smb3_fs_context *ctx);
+
+extern void cifs_put_smb_ses(struct cifs_ses *ses);
+
+extern struct cifs_ses *
+cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx);
+
+void cifs_readdata_release(struct kref *refcount);
+int cifs_async_readv(struct cifs_readdata *rdata);
+int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid);
+
+int cifs_async_writev(struct cifs_writedata *wdata,
+ void (*release)(struct kref *kref));
+void cifs_writev_complete(struct work_struct *work);
+struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
+ work_func_t complete);
+struct cifs_writedata *cifs_writedata_direct_alloc(struct page **pages,
+ work_func_t complete);
+void cifs_writedata_release(struct kref *refcount);
+int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ const unsigned char *path, char *pbuf,
+ unsigned int *pbytes_read);
+int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ const unsigned char *path, char *pbuf,
+ unsigned int *pbytes_written);
+int __cifs_calc_signature(struct smb_rqst *rqst,
+ struct TCP_Server_Info *server, char *signature,
+ struct shash_desc *shash);
+enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
+ enum securityEnum);
+struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
+void cifs_aio_ctx_release(struct kref *refcount);
+int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
+
+int cifs_alloc_hash(const char *name, struct shash_desc **sdesc);
+void cifs_free_hash(struct shash_desc **sdesc);
+
+void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
+ unsigned int *len, unsigned int *offset);
+struct cifs_chan *
+cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server);
+int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses);
+bool is_server_using_iface(struct TCP_Server_Info *server,
+ struct cifs_server_iface *iface);
+bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface);
+void cifs_ses_mark_for_reconnect(struct cifs_ses *ses);
+
+unsigned int
+cifs_ses_get_chan_index(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+void
+cifs_chan_set_in_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+void
+cifs_chan_clear_in_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+bool
+cifs_chan_in_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+void
+cifs_chan_set_need_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+void
+cifs_chan_clear_need_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+bool
+cifs_chan_needs_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+bool
+cifs_chan_is_iface_active(struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+int
+cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server);
+int
+SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount);
+
+void extract_unc_hostname(const char *unc, const char **h, size_t *len);
+int copy_path_name(char *dst, const char *src);
+int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov,
+ int resp_buftype,
+ struct cifs_search_info *srch_inf);
+
+struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server);
+void cifs_put_tcp_super(struct super_block *sb);
+int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix);
+char *extract_hostname(const char *unc);
+char *extract_sharename(const char *unc);
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
+ const char *old_path,
+ const struct nls_table *nls_codepage,
+ struct dfs_info3_param *referral, int remap)
+{
+ return dfs_cache_find(xid, ses, nls_codepage, remap, old_path,
+ referral, NULL);
+}
+
+int match_target_ip(struct TCP_Server_Info *server,
+ const char *share, size_t share_len,
+ bool *result);
+int cifs_inval_name_dfs_link_error(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ const char *full_path,
+ bool *islink);
+#else
+static inline int cifs_inval_name_dfs_link_error(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ const char *full_path,
+ bool *islink)
+{
+ *islink = false;
+ return 0;
+}
+#endif
+
+static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
+{
+ if (cifs_sb && (backup_cred(cifs_sb)))
+ return options | CREATE_OPEN_BACKUP_INTENT;
+ else
+ return options;
+}
+
+struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
+void cifs_put_tcon_super(struct super_block *sb);
+int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
+
+#endif /* _CIFSPROTO_H */
diff --git a/fs/smb/client/cifsroot.c b/fs/smb/client/cifsroot.c
new file mode 100644
index 000000000000..56ec1b233f52
--- /dev/null
+++ b/fs/smb/client/cifsroot.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SMB root file system support
+ *
+ * Copyright (c) 2019 Paulo Alcantara <palcantara@suse.de>
+ */
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/root_dev.h>
+#include <linux/kernel.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <net/ipconfig.h>
+
+#define DEFAULT_MNT_OPTS \
+ "vers=1.0,cifsacl,mfsymlinks,rsize=1048576,wsize=65536,uid=0,gid=0," \
+ "hard,rootfs"
+
+static char root_dev[2048] __initdata = "";
+static char root_opts[1024] __initdata = DEFAULT_MNT_OPTS;
+
+static __be32 __init parse_srvaddr(char *start, char *end)
+{
+ /* TODO: ipv6 support */
+ char addr[sizeof("aaa.bbb.ccc.ddd")];
+ int i = 0;
+
+ while (start < end && i < sizeof(addr) - 1) {
+ if (isdigit(*start) || *start == '.')
+ addr[i++] = *start;
+ start++;
+ }
+ addr[i] = '\0';
+ return in_aton(addr);
+}
+
+/* cifsroot=//<server-ip>/<share>[,options] */
+static int __init cifs_root_setup(char *line)
+{
+ char *s;
+ int len;
+ __be32 srvaddr = htonl(INADDR_NONE);
+
+ ROOT_DEV = Root_CIFS;
+
+ if (strlen(line) > 3 && line[0] == '/' && line[1] == '/') {
+ s = strchr(&line[2], '/');
+ if (!s || s[1] == '\0')
+ return 1;
+
+ /* make s point to ',' or '\0' at end of line */
+ s = strchrnul(s, ',');
+ /* len is strlen(unc) + '\0' */
+ len = s - line + 1;
+ if (len > sizeof(root_dev)) {
+ pr_err("Root-CIFS: UNC path too long\n");
+ return 1;
+ }
+ strscpy(root_dev, line, len);
+ srvaddr = parse_srvaddr(&line[2], s);
+ if (*s) {
+ int n = snprintf(root_opts,
+ sizeof(root_opts), "%s,%s",
+ DEFAULT_MNT_OPTS, s + 1);
+ if (n >= sizeof(root_opts)) {
+ pr_err("Root-CIFS: mount options string too long\n");
+ root_opts[sizeof(root_opts)-1] = '\0';
+ return 1;
+ }
+ }
+ }
+
+ root_server_addr = srvaddr;
+
+ return 1;
+}
+
+__setup("cifsroot=", cifs_root_setup);
+
+int __init cifs_root_data(char **dev, char **opts)
+{
+ if (!root_dev[0] || root_server_addr == htonl(INADDR_NONE)) {
+ pr_err("Root-CIFS: no SMB server address\n");
+ return -1;
+ }
+
+ *dev = root_dev;
+ *opts = root_opts;
+
+ return 0;
+}
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
new file mode 100644
index 000000000000..c90d4ec9292c
--- /dev/null
+++ b/fs/smb/client/cifssmb.c
@@ -0,0 +1,5873 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2010
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Contains the routines for constructing the SMB PDUs themselves
+ *
+ */
+
+ /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
+ /* These are mostly routines that operate on a pathname, or on a tree id */
+ /* (mounted volume), but there are eight handle based routines which must be */
+ /* treated slightly differently for reconnection purposes since we never */
+ /* want to reuse a stale file handle and only the caller knows the file info */
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/vfs.h>
+#include <linux/slab.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/task_io_accounting_ops.h>
+#include <linux/uaccess.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsacl.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "fscache.h"
+#include "smbdirect.h"
+#ifdef CONFIG_CIFS_DFS_UPCALL
+#include "dfs_cache.h"
+#endif
+
+#ifdef CONFIG_CIFS_POSIX
+static struct {
+ int index;
+ char *name;
+} protocols[] = {
+ {CIFS_PROT, "\2NT LM 0.12"},
+ {POSIX_PROT, "\2POSIX 2"},
+ {BAD_PROT, "\2"}
+};
+#else
+static struct {
+ int index;
+ char *name;
+} protocols[] = {
+ {CIFS_PROT, "\2NT LM 0.12"},
+ {BAD_PROT, "\2"}
+};
+#endif
+
+/* define the number of elements in the cifs dialect array */
+#ifdef CONFIG_CIFS_POSIX
+#define CIFS_NUM_PROT 2
+#else /* not posix */
+#define CIFS_NUM_PROT 1
+#endif /* CIFS_POSIX */
+
+
+/* reconnect the socket, tcon, and smb session if needed */
+static int
+cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
+{
+ int rc;
+ struct cifs_ses *ses;
+ struct TCP_Server_Info *server;
+ struct nls_table *nls_codepage;
+
+ /*
+ * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
+ * tcp and smb session status done differently for those three - in the
+ * calling routine
+ */
+ if (!tcon)
+ return 0;
+
+ ses = tcon->ses;
+ server = ses->server;
+
+ /*
+ * only tree disconnect, open, and write, (and ulogoff which does not
+ * have tcon) are allowed as we start umount
+ */
+ spin_lock(&tcon->tc_lock);
+ if (tcon->status == TID_EXITING) {
+ if (smb_command != SMB_COM_TREE_DISCONNECT) {
+ spin_unlock(&tcon->tc_lock);
+ cifs_dbg(FYI, "can not send cmd %d while umounting\n",
+ smb_command);
+ return -ENODEV;
+ }
+ }
+ spin_unlock(&tcon->tc_lock);
+
+ rc = cifs_wait_for_server_reconnect(server, tcon->retry);
+ if (rc)
+ return rc;
+
+ spin_lock(&ses->chan_lock);
+ if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
+ spin_unlock(&ses->chan_lock);
+ return 0;
+ }
+ spin_unlock(&ses->chan_lock);
+
+ nls_codepage = load_nls_default();
+
+ /*
+ * Recheck after acquire mutex. If another thread is negotiating
+ * and the server never sends an answer the socket will be closed
+ * and tcpStatus set to reconnect.
+ */
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsNeedReconnect) {
+ spin_unlock(&server->srv_lock);
+ rc = -EHOSTDOWN;
+ goto out;
+ }
+ spin_unlock(&server->srv_lock);
+
+ /*
+ * need to prevent multiple threads trying to simultaneously
+ * reconnect the same SMB session
+ */
+ spin_lock(&ses->chan_lock);
+ if (!cifs_chan_needs_reconnect(ses, server)) {
+ spin_unlock(&ses->chan_lock);
+
+ /* this means that we only need to tree connect */
+ if (tcon->need_reconnect)
+ goto skip_sess_setup;
+
+ rc = -EHOSTDOWN;
+ goto out;
+ }
+ spin_unlock(&ses->chan_lock);
+
+ mutex_lock(&ses->session_mutex);
+ rc = cifs_negotiate_protocol(0, ses, server);
+ if (!rc)
+ rc = cifs_setup_session(0, ses, server, nls_codepage);
+
+ /* do we need to reconnect tcon? */
+ if (rc || !tcon->need_reconnect) {
+ mutex_unlock(&ses->session_mutex);
+ goto out;
+ }
+
+skip_sess_setup:
+ cifs_mark_open_files_invalid(tcon);
+ rc = cifs_tree_connect(0, tcon, nls_codepage);
+ mutex_unlock(&ses->session_mutex);
+ cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
+
+ if (rc) {
+ pr_warn_once("reconnect tcon failed rc = %d\n", rc);
+ goto out;
+ }
+
+ atomic_inc(&tconInfoReconnectCount);
+
+ /* tell server Unix caps we support */
+ if (cap_unix(ses))
+ reset_cifs_unix_caps(0, tcon, NULL, NULL);
+
+ /*
+ * Removed call to reopen open files here. It is safer (and faster) to
+ * reopen files one at a time as needed in read and write.
+ *
+ * FIXME: what about file locks? don't we need to reclaim them ASAP?
+ */
+
+out:
+ /*
+ * Check if handle based operation so we know whether we can continue
+ * or not without returning to caller to reset file handle
+ */
+ switch (smb_command) {
+ case SMB_COM_READ_ANDX:
+ case SMB_COM_WRITE_ANDX:
+ case SMB_COM_CLOSE:
+ case SMB_COM_FIND_CLOSE2:
+ case SMB_COM_LOCKING_ANDX:
+ rc = -EAGAIN;
+ }
+
+ unload_nls(nls_codepage);
+ return rc;
+}
+
+/* Allocate and return pointer to an SMB request buffer, and set basic
+ SMB information in the SMB header. If the return code is zero, this
+ function must have filled in request_buf pointer */
+static int
+small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
+ void **request_buf)
+{
+ int rc;
+
+ rc = cifs_reconnect_tcon(tcon, smb_command);
+ if (rc)
+ return rc;
+
+ *request_buf = cifs_small_buf_get();
+ if (*request_buf == NULL) {
+ /* BB should we add a retry in here if not a writepage? */
+ return -ENOMEM;
+ }
+
+ header_assemble((struct smb_hdr *) *request_buf, smb_command,
+ tcon, wct);
+
+ if (tcon != NULL)
+ cifs_stats_inc(&tcon->num_smbs_sent);
+
+ return 0;
+}
+
+int
+small_smb_init_no_tc(const int smb_command, const int wct,
+ struct cifs_ses *ses, void **request_buf)
+{
+ int rc;
+ struct smb_hdr *buffer;
+
+ rc = small_smb_init(smb_command, wct, NULL, request_buf);
+ if (rc)
+ return rc;
+
+ buffer = (struct smb_hdr *)*request_buf;
+ buffer->Mid = get_next_mid(ses->server);
+ if (ses->capabilities & CAP_UNICODE)
+ buffer->Flags2 |= SMBFLG2_UNICODE;
+ if (ses->capabilities & CAP_STATUS32)
+ buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+
+ /* uid, tid can stay at zero as set in header assemble */
+
+ /* BB add support for turning on the signing when
+ this function is used after 1st of session setup requests */
+
+ return rc;
+}
+
+/* If the return code is zero, this function must fill in request_buf pointer */
+static int
+__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
+ void **request_buf, void **response_buf)
+{
+ *request_buf = cifs_buf_get();
+ if (*request_buf == NULL) {
+ /* BB should we add a retry in here if not a writepage? */
+ return -ENOMEM;
+ }
+ /* Although the original thought was we needed the response buf for */
+ /* potential retries of smb operations it turns out we can determine */
+ /* from the mid flags when the request buffer can be resent without */
+ /* having to use a second distinct buffer for the response */
+ if (response_buf)
+ *response_buf = *request_buf;
+
+ header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
+ wct);
+
+ if (tcon != NULL)
+ cifs_stats_inc(&tcon->num_smbs_sent);
+
+ return 0;
+}
+
+/* If the return code is zero, this function must fill in request_buf pointer */
+static int
+smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
+ void **request_buf, void **response_buf)
+{
+ int rc;
+
+ rc = cifs_reconnect_tcon(tcon, smb_command);
+ if (rc)
+ return rc;
+
+ return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
+}
+
+static int
+smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
+ void **request_buf, void **response_buf)
+{
+ spin_lock(&tcon->ses->chan_lock);
+ if (cifs_chan_needs_reconnect(tcon->ses, tcon->ses->server) ||
+ tcon->need_reconnect) {
+ spin_unlock(&tcon->ses->chan_lock);
+ return -EHOSTDOWN;
+ }
+ spin_unlock(&tcon->ses->chan_lock);
+
+ return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
+}
+
+static int validate_t2(struct smb_t2_rsp *pSMB)
+{
+ unsigned int total_size;
+
+ /* check for plausible wct */
+ if (pSMB->hdr.WordCount < 10)
+ goto vt2_err;
+
+ /* check for parm and data offset going beyond end of smb */
+ if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
+ get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
+ goto vt2_err;
+
+ total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
+ if (total_size >= 512)
+ goto vt2_err;
+
+ /* check that bcc is at least as big as parms + data, and that it is
+ * less than negotiated smb buffer
+ */
+ total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
+ if (total_size > get_bcc(&pSMB->hdr) ||
+ total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
+ goto vt2_err;
+
+ return 0;
+vt2_err:
+ cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
+ sizeof(struct smb_t2_rsp) + 16);
+ return -EINVAL;
+}
+
+static int
+decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
+{
+ int rc = 0;
+ u16 count;
+ char *guid = pSMBr->u.extended_response.GUID;
+ struct TCP_Server_Info *server = ses->server;
+
+ count = get_bcc(&pSMBr->hdr);
+ if (count < SMB1_CLIENT_GUID_SIZE)
+ return -EIO;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ if (server->srv_count > 1) {
+ spin_unlock(&cifs_tcp_ses_lock);
+ if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
+ cifs_dbg(FYI, "server UID changed\n");
+ memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
+ }
+ } else {
+ spin_unlock(&cifs_tcp_ses_lock);
+ memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
+ }
+
+ if (count == SMB1_CLIENT_GUID_SIZE) {
+ server->sec_ntlmssp = true;
+ } else {
+ count -= SMB1_CLIENT_GUID_SIZE;
+ rc = decode_negTokenInit(
+ pSMBr->u.extended_response.SecurityBlob, count, server);
+ if (rc != 1)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static bool
+should_set_ext_sec_flag(enum securityEnum sectype)
+{
+ switch (sectype) {
+ case RawNTLMSSP:
+ case Kerberos:
+ return true;
+ case Unspecified:
+ if (global_secflags &
+ (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
+ return true;
+ fallthrough;
+ default:
+ return false;
+ }
+}
+
+int
+CIFSSMBNegotiate(const unsigned int xid,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ NEGOTIATE_REQ *pSMB;
+ NEGOTIATE_RSP *pSMBr;
+ int rc = 0;
+ int bytes_returned;
+ int i;
+ u16 count;
+
+ if (!server) {
+ WARN(1, "%s: server is NULL!\n", __func__);
+ return -EIO;
+ }
+
+ rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
+ (void **) &pSMB, (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Mid = get_next_mid(server);
+ pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
+
+ if (should_set_ext_sec_flag(ses->sectype)) {
+ cifs_dbg(FYI, "Requesting extended security\n");
+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ }
+
+ count = 0;
+ /*
+ * We know that all the name entries in the protocols array
+ * are short (< 16 bytes anyway) and are NUL terminated.
+ */
+ for (i = 0; i < CIFS_NUM_PROT; i++) {
+ size_t len = strlen(protocols[i].name) + 1;
+
+ memcpy(&pSMB->DialectsArray[count], protocols[i].name, len);
+ count += len;
+ }
+ inc_rfc1001_len(pSMB, count);
+ pSMB->ByteCount = cpu_to_le16(count);
+
+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc != 0)
+ goto neg_err_exit;
+
+ server->dialect = le16_to_cpu(pSMBr->DialectIndex);
+ cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
+ /* Check wct = 1 error case */
+ if ((pSMBr->hdr.WordCount <= 13) || (server->dialect == BAD_PROT)) {
+ /* core returns wct = 1, but we do not ask for core - otherwise
+ small wct just comes when dialect index is -1 indicating we
+ could not negotiate a common dialect */
+ rc = -EOPNOTSUPP;
+ goto neg_err_exit;
+ } else if (pSMBr->hdr.WordCount != 17) {
+ /* unknown wct */
+ rc = -EOPNOTSUPP;
+ goto neg_err_exit;
+ }
+ /* else wct == 17, NTLM or better */
+
+ server->sec_mode = pSMBr->SecurityMode;
+ if ((server->sec_mode & SECMODE_USER) == 0)
+ cifs_dbg(FYI, "share mode security\n");
+
+ /* one byte, so no need to convert this or EncryptionKeyLen from
+ little endian */
+ server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
+ cifs_max_pending);
+ set_credits(server, server->maxReq);
+ /* probably no need to store and check maxvcs */
+ server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
+ /* set up max_read for readahead check */
+ server->max_read = server->maxBuf;
+ server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
+ cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
+ server->capabilities = le32_to_cpu(pSMBr->Capabilities);
+ server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
+ server->timeAdj *= 60;
+
+ if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
+ server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
+ memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
+ CIFS_CRYPTO_KEY_SIZE);
+ } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
+ server->capabilities & CAP_EXTENDED_SECURITY) {
+ server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
+ rc = decode_ext_sec_blob(ses, pSMBr);
+ } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
+ rc = -EIO; /* no crypt key only if plain text pwd */
+ } else {
+ server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
+ server->capabilities &= ~CAP_EXTENDED_SECURITY;
+ }
+
+ if (!rc)
+ rc = cifs_enable_signing(server, ses->sign);
+neg_err_exit:
+ cifs_buf_release(pSMB);
+
+ cifs_dbg(FYI, "negprot rc %d\n", rc);
+ return rc;
+}
+
+int
+CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
+{
+ struct smb_hdr *smb_buffer;
+ int rc = 0;
+
+ cifs_dbg(FYI, "In tree disconnect\n");
+
+ /* BB: do we need to check this? These should never be NULL. */
+ if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
+ return -EIO;
+
+ /*
+ * No need to return error on this operation if tid invalidated and
+ * closed on server already e.g. due to tcp session crashing. Also,
+ * the tcon is no longer on the list, so no need to take lock before
+ * checking this.
+ */
+ spin_lock(&tcon->ses->chan_lock);
+ if ((tcon->need_reconnect) || CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses)) {
+ spin_unlock(&tcon->ses->chan_lock);
+ return -EIO;
+ }
+ spin_unlock(&tcon->ses->chan_lock);
+
+ rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
+ (void **)&smb_buffer);
+ if (rc)
+ return rc;
+
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
+ cifs_small_buf_release(smb_buffer);
+ if (rc)
+ cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
+
+ /* No need to return error on this operation if tid invalidated and
+ closed on server already e.g. due to tcp session crashing */
+ if (rc == -EAGAIN)
+ rc = 0;
+
+ return rc;
+}
+
+/*
+ * This is a no-op for now. We're not really interested in the reply, but
+ * rather in the fact that the server sent one and that server->lstrp
+ * gets updated.
+ *
+ * FIXME: maybe we should consider checking that the reply matches request?
+ */
+static void
+cifs_echo_callback(struct mid_q_entry *mid)
+{
+ struct TCP_Server_Info *server = mid->callback_data;
+ struct cifs_credits credits = { .value = 1, .instance = 0 };
+
+ release_mid(mid);
+ add_credits(server, &credits, CIFS_ECHO_OP);
+}
+
+int
+CIFSSMBEcho(struct TCP_Server_Info *server)
+{
+ ECHO_REQ *smb;
+ int rc = 0;
+ struct kvec iov[2];
+ struct smb_rqst rqst = { .rq_iov = iov,
+ .rq_nvec = 2 };
+
+ cifs_dbg(FYI, "In echo request\n");
+
+ rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
+ if (rc)
+ return rc;
+
+ if (server->capabilities & CAP_UNICODE)
+ smb->hdr.Flags2 |= SMBFLG2_UNICODE;
+
+ /* set up echo request */
+ smb->hdr.Tid = 0xffff;
+ smb->hdr.WordCount = 1;
+ put_unaligned_le16(1, &smb->EchoCount);
+ put_bcc(1, &smb->hdr);
+ smb->Data[0] = 'a';
+ inc_rfc1001_len(smb, 3);
+
+ iov[0].iov_len = 4;
+ iov[0].iov_base = smb;
+ iov[1].iov_len = get_rfc1002_length(smb);
+ iov[1].iov_base = (char *)smb + 4;
+
+ rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
+ server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL);
+ if (rc)
+ cifs_dbg(FYI, "Echo request failed: %d\n", rc);
+
+ cifs_small_buf_release(smb);
+
+ return rc;
+}
+
+int
+CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
+{
+ LOGOFF_ANDX_REQ *pSMB;
+ int rc = 0;
+
+ cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
+
+ /*
+ * BB: do we need to check validity of ses and server? They should
+ * always be valid since we have an active reference. If not, that
+ * should probably be a BUG()
+ */
+ if (!ses || !ses->server)
+ return -EIO;
+
+ mutex_lock(&ses->session_mutex);
+ spin_lock(&ses->chan_lock);
+ if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
+ spin_unlock(&ses->chan_lock);
+ goto session_already_dead; /* no need to send SMBlogoff if uid
+ already closed due to reconnect */
+ }
+ spin_unlock(&ses->chan_lock);
+
+ rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
+ if (rc) {
+ mutex_unlock(&ses->session_mutex);
+ return rc;
+ }
+
+ pSMB->hdr.Mid = get_next_mid(ses->server);
+
+ if (ses->server->sign)
+ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ pSMB->hdr.Uid = ses->Suid;
+
+ pSMB->AndXCommand = 0xFF;
+ rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
+ cifs_small_buf_release(pSMB);
+session_already_dead:
+ mutex_unlock(&ses->session_mutex);
+
+ /* if session dead then we do not need to do ulogoff,
+ since server closed smb session, no sense reporting
+ error */
+ if (rc == -EAGAIN)
+ rc = 0;
+ return rc;
+}
+
+int
+CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fileName, __u16 type,
+ const struct nls_table *nls_codepage, int remap)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ struct unlink_psx_rq *pRqD;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, param_offset, offset, byte_count;
+
+ cifs_dbg(FYI, "In POSIX delete\n");
+PsxDelete:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fileName);
+ }
+
+ params = 6 + name_len;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = 0; /* BB double check this with jra */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+
+ /* Setup pointer to Request Data (inode type).
+ * Note that SMB offsets are from the beginning of SMB which is 4 bytes
+ * in, after RFC1001 field
+ */
+ pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4);
+ pRqD->type = cpu_to_le16(type);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
+
+ pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
+ pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc)
+ cifs_dbg(FYI, "Posix delete returned %d\n", rc);
+ cifs_buf_release(pSMB);
+
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
+
+ if (rc == -EAGAIN)
+ goto PsxDelete;
+
+ return rc;
+}
+
+int
+CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
+ struct cifs_sb_info *cifs_sb)
+{
+ DELETE_FILE_REQ *pSMB = NULL;
+ DELETE_FILE_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ int remap = cifs_remap(cifs_sb);
+
+DelFileRetry:
+ rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
+ PATH_MAX, cifs_sb->local_nls,
+ remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->fileName, name);
+ }
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
+ pSMB->BufferFormat = 0x04;
+ inc_rfc1001_len(pSMB, name_len + 1);
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
+ if (rc)
+ cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto DelFileRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
+ struct cifs_sb_info *cifs_sb)
+{
+ DELETE_DIRECTORY_REQ *pSMB = NULL;
+ DELETE_DIRECTORY_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ int remap = cifs_remap(cifs_sb);
+
+ cifs_dbg(FYI, "In CIFSSMBRmDir\n");
+RmDirRetry:
+ rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
+ PATH_MAX, cifs_sb->local_nls,
+ remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->DirName, name);
+ }
+
+ pSMB->BufferFormat = 0x04;
+ inc_rfc1001_len(pSMB, name_len + 1);
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
+ if (rc)
+ cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto RmDirRetry;
+ return rc;
+}
+
+int
+CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
+ struct cifs_tcon *tcon, const char *name,
+ struct cifs_sb_info *cifs_sb)
+{
+ int rc = 0;
+ CREATE_DIRECTORY_REQ *pSMB = NULL;
+ CREATE_DIRECTORY_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len;
+ int remap = cifs_remap(cifs_sb);
+
+ cifs_dbg(FYI, "In CIFSSMBMkDir\n");
+MkDirRetry:
+ rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
+ PATH_MAX, cifs_sb->local_nls,
+ remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->DirName, name);
+ }
+
+ pSMB->BufferFormat = 0x04;
+ inc_rfc1001_len(pSMB, name_len + 1);
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
+ if (rc)
+ cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto MkDirRetry;
+ return rc;
+}
+
+int
+CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
+ __u32 posix_flags, __u64 mode, __u16 *netfid,
+ FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
+ const char *name, const struct nls_table *nls_codepage,
+ int remap)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, param_offset, offset, byte_count, count;
+ OPEN_PSX_REQ *pdata;
+ OPEN_PSX_RSP *psx_rsp;
+
+ cifs_dbg(FYI, "In POSIX Create\n");
+PsxCreat:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, name);
+ }
+
+ params = 6 + name_len;
+ count = sizeof(OPEN_PSX_REQ);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+ /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
+ pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4);
+ pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
+ pdata->Permissions = cpu_to_le64(mode);
+ pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
+ pdata->OpenFlags = cpu_to_le32(*pOplock);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Posix create returned %d\n", rc);
+ goto psx_create_err;
+ }
+
+ cifs_dbg(FYI, "copying inode info\n");
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
+ rc = -EIO; /* bad smb */
+ goto psx_create_err;
+ }
+
+ /* copy return information to pRetData */
+ psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
+ + le16_to_cpu(pSMBr->t2.DataOffset));
+
+ *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
+ if (netfid)
+ *netfid = psx_rsp->Fid; /* cifs fid stays in le */
+ /* Let caller know file was created so we can set the mode. */
+ /* Do we care about the CreateAction in any other cases? */
+ if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
+ *pOplock |= CIFS_CREATE_ACTION;
+ /* check to make sure response data is there */
+ if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
+ pRetData->Type = cpu_to_le32(-1); /* unknown */
+ cifs_dbg(NOISY, "unknown type\n");
+ } else {
+ if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
+ + sizeof(FILE_UNIX_BASIC_INFO)) {
+ cifs_dbg(VFS, "Open response data too small\n");
+ pRetData->Type = cpu_to_le32(-1);
+ goto psx_create_err;
+ }
+ memcpy((char *) pRetData,
+ (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
+ sizeof(FILE_UNIX_BASIC_INFO));
+ }
+
+psx_create_err:
+ cifs_buf_release(pSMB);
+
+ if (posix_flags & SMB_O_DIRECTORY)
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
+ else
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
+
+ if (rc == -EAGAIN)
+ goto PsxCreat;
+
+ return rc;
+}
+
+static __u16 convert_disposition(int disposition)
+{
+ __u16 ofun = 0;
+
+ switch (disposition) {
+ case FILE_SUPERSEDE:
+ ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
+ break;
+ case FILE_OPEN:
+ ofun = SMBOPEN_OAPPEND;
+ break;
+ case FILE_CREATE:
+ ofun = SMBOPEN_OCREATE;
+ break;
+ case FILE_OPEN_IF:
+ ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
+ break;
+ case FILE_OVERWRITE:
+ ofun = SMBOPEN_OTRUNC;
+ break;
+ case FILE_OVERWRITE_IF:
+ ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
+ break;
+ default:
+ cifs_dbg(FYI, "unknown disposition %d\n", disposition);
+ ofun = SMBOPEN_OAPPEND; /* regular open */
+ }
+ return ofun;
+}
+
+static int
+access_flags_to_smbopen_mode(const int access_flags)
+{
+ int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
+
+ if (masked_flags == GENERIC_READ)
+ return SMBOPEN_READ;
+ else if (masked_flags == GENERIC_WRITE)
+ return SMBOPEN_WRITE;
+
+ /* just go for read/write */
+ return SMBOPEN_READWRITE;
+}
+
+int
+SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fileName, const int openDisposition,
+ const int access_flags, const int create_options, __u16 *netfid,
+ int *pOplock, FILE_ALL_INFO *pfile_info,
+ const struct nls_table *nls_codepage, int remap)
+{
+ int rc;
+ OPENX_REQ *pSMB = NULL;
+ OPENX_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len;
+ __u16 count;
+
+OldOpenRetry:
+ rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->AndXCommand = 0xFF; /* none */
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ count = 1; /* account for one byte pad to word boundary */
+ name_len =
+ cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
+ fileName, PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ count = 0; /* no pad */
+ name_len = copy_path_name(pSMB->fileName, fileName);
+ }
+ if (*pOplock & REQ_OPLOCK)
+ pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
+ else if (*pOplock & REQ_BATCHOPLOCK)
+ pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
+
+ pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
+ pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
+ pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
+ /* set file as system file if special file such
+ as fifo and server expecting SFU style and
+ no Unix extensions */
+
+ if (create_options & CREATE_OPTION_SPECIAL)
+ pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
+ else /* BB FIXME BB */
+ pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
+
+ if (create_options & CREATE_OPTION_READONLY)
+ pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
+
+ /* BB FIXME BB */
+/* pSMB->CreateOptions = cpu_to_le32(create_options &
+ CREATE_OPTIONS_MASK); */
+ /* BB FIXME END BB */
+
+ pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
+ pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
+ count += name_len;
+ inc_rfc1001_len(pSMB, count);
+
+ pSMB->ByteCount = cpu_to_le16(count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *)pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
+ if (rc) {
+ cifs_dbg(FYI, "Error in Open = %d\n", rc);
+ } else {
+ /* BB verify if wct == 15 */
+
+/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
+
+ *netfid = pSMBr->Fid; /* cifs fid stays in le */
+ /* Let caller know file was created so we can set the mode. */
+ /* Do we care about the CreateAction in any other cases? */
+ /* BB FIXME BB */
+/* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
+ *pOplock |= CIFS_CREATE_ACTION; */
+ /* BB FIXME END */
+
+ if (pfile_info) {
+ pfile_info->CreationTime = 0; /* BB convert CreateTime*/
+ pfile_info->LastAccessTime = 0; /* BB fixme */
+ pfile_info->LastWriteTime = 0; /* BB fixme */
+ pfile_info->ChangeTime = 0; /* BB fixme */
+ pfile_info->Attributes =
+ cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
+ /* the file_info buf is endian converted by caller */
+ pfile_info->AllocationSize =
+ cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
+ pfile_info->EndOfFile = pfile_info->AllocationSize;
+ pfile_info->NumberOfLinks = cpu_to_le32(1);
+ pfile_info->DeletePending = 0;
+ }
+ }
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto OldOpenRetry;
+ return rc;
+}
+
+int
+CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
+ FILE_ALL_INFO *buf)
+{
+ int rc;
+ OPEN_REQ *req = NULL;
+ OPEN_RSP *rsp = NULL;
+ int bytes_returned;
+ int name_len;
+ __u16 count;
+ struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
+ struct cifs_tcon *tcon = oparms->tcon;
+ int remap = cifs_remap(cifs_sb);
+ const struct nls_table *nls = cifs_sb->local_nls;
+ int create_options = oparms->create_options;
+ int desired_access = oparms->desired_access;
+ int disposition = oparms->disposition;
+ const char *path = oparms->path;
+
+openRetry:
+ rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
+ (void **)&rsp);
+ if (rc)
+ return rc;
+
+ /* no commands go after this */
+ req->AndXCommand = 0xFF;
+
+ if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
+ /* account for one byte pad to word boundary */
+ count = 1;
+ name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
+ path, PATH_MAX, nls, remap);
+ /* trailing null */
+ name_len++;
+ name_len *= 2;
+ req->NameLength = cpu_to_le16(name_len);
+ } else {
+ /* BB improve check for buffer overruns BB */
+ /* no pad */
+ count = 0;
+ name_len = copy_path_name(req->fileName, path);
+ req->NameLength = cpu_to_le16(name_len);
+ }
+
+ if (*oplock & REQ_OPLOCK)
+ req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
+ else if (*oplock & REQ_BATCHOPLOCK)
+ req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
+
+ req->DesiredAccess = cpu_to_le32(desired_access);
+ req->AllocationSize = 0;
+
+ /*
+ * Set file as system file if special file such as fifo and server
+ * expecting SFU style and no Unix extensions.
+ */
+ if (create_options & CREATE_OPTION_SPECIAL)
+ req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
+ else
+ req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
+
+ /*
+ * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
+ * sensitive checks for other servers such as Samba.
+ */
+ if (tcon->ses->capabilities & CAP_UNIX)
+ req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
+
+ if (create_options & CREATE_OPTION_READONLY)
+ req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
+
+ req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
+ req->CreateDisposition = cpu_to_le32(disposition);
+ req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
+
+ /* BB Expirement with various impersonation levels and verify */
+ req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
+ req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
+
+ count += name_len;
+ inc_rfc1001_len(req, count);
+
+ req->ByteCount = cpu_to_le16(count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
+ (struct smb_hdr *)rsp, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
+ if (rc) {
+ cifs_dbg(FYI, "Error in Open = %d\n", rc);
+ cifs_buf_release(req);
+ if (rc == -EAGAIN)
+ goto openRetry;
+ return rc;
+ }
+
+ /* 1 byte no need to le_to_cpu */
+ *oplock = rsp->OplockLevel;
+ /* cifs fid stays in le */
+ oparms->fid->netfid = rsp->Fid;
+ oparms->fid->access = desired_access;
+
+ /* Let caller know file was created so we can set the mode. */
+ /* Do we care about the CreateAction in any other cases? */
+ if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
+ *oplock |= CIFS_CREATE_ACTION;
+
+ if (buf) {
+ /* copy from CreationTime to Attributes */
+ memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
+ /* the file_info buf is endian converted by caller */
+ buf->AllocationSize = rsp->AllocationSize;
+ buf->EndOfFile = rsp->EndOfFile;
+ buf->NumberOfLinks = cpu_to_le32(1);
+ buf->DeletePending = 0;
+ }
+
+ cifs_buf_release(req);
+ return rc;
+}
+
+static void
+cifs_readv_callback(struct mid_q_entry *mid)
+{
+ struct cifs_readdata *rdata = mid->callback_data;
+ struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct smb_rqst rqst = { .rq_iov = rdata->iov,
+ .rq_nvec = 2,
+ .rq_pages = rdata->pages,
+ .rq_offset = rdata->page_offset,
+ .rq_npages = rdata->nr_pages,
+ .rq_pagesz = rdata->pagesz,
+ .rq_tailsz = rdata->tailsz };
+ struct cifs_credits credits = { .value = 1, .instance = 0 };
+
+ cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
+ __func__, mid->mid, mid->mid_state, rdata->result,
+ rdata->bytes);
+
+ switch (mid->mid_state) {
+ case MID_RESPONSE_RECEIVED:
+ /* result already set, check signature */
+ if (server->sign) {
+ int rc = 0;
+
+ rc = cifs_verify_signature(&rqst, server,
+ mid->sequence_number);
+ if (rc)
+ cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
+ rc);
+ }
+ /* FIXME: should this be counted toward the initiating task? */
+ task_io_account_read(rdata->got_bytes);
+ cifs_stats_bytes_read(tcon, rdata->got_bytes);
+ break;
+ case MID_REQUEST_SUBMITTED:
+ case MID_RETRY_NEEDED:
+ rdata->result = -EAGAIN;
+ if (server->sign && rdata->got_bytes)
+ /* reset bytes number since we can not check a sign */
+ rdata->got_bytes = 0;
+ /* FIXME: should this be counted toward the initiating task? */
+ task_io_account_read(rdata->got_bytes);
+ cifs_stats_bytes_read(tcon, rdata->got_bytes);
+ break;
+ default:
+ rdata->result = -EIO;
+ }
+
+ queue_work(cifsiod_wq, &rdata->work);
+ release_mid(mid);
+ add_credits(server, &credits, 0);
+}
+
+/* cifs_async_readv - send an async write, and set up mid to handle result */
+int
+cifs_async_readv(struct cifs_readdata *rdata)
+{
+ int rc;
+ READ_REQ *smb = NULL;
+ int wct;
+ struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+ struct smb_rqst rqst = { .rq_iov = rdata->iov,
+ .rq_nvec = 2 };
+
+ cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
+ __func__, rdata->offset, rdata->bytes);
+
+ if (tcon->ses->capabilities & CAP_LARGE_FILES)
+ wct = 12;
+ else {
+ wct = 10; /* old style read */
+ if ((rdata->offset >> 32) > 0) {
+ /* can not handle this big offset for old */
+ return -EIO;
+ }
+ }
+
+ rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
+ if (rc)
+ return rc;
+
+ smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
+ smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
+
+ smb->AndXCommand = 0xFF; /* none */
+ smb->Fid = rdata->cfile->fid.netfid;
+ smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
+ if (wct == 12)
+ smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
+ smb->Remaining = 0;
+ smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
+ smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
+ if (wct == 12)
+ smb->ByteCount = 0;
+ else {
+ /* old style read */
+ struct smb_com_readx_req *smbr =
+ (struct smb_com_readx_req *)smb;
+ smbr->ByteCount = 0;
+ }
+
+ /* 4 for RFC1001 length + 1 for BCC */
+ rdata->iov[0].iov_base = smb;
+ rdata->iov[0].iov_len = 4;
+ rdata->iov[1].iov_base = (char *)smb + 4;
+ rdata->iov[1].iov_len = get_rfc1002_length(smb);
+
+ kref_get(&rdata->refcount);
+ rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
+ cifs_readv_callback, NULL, rdata, 0, NULL);
+
+ if (rc == 0)
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
+ else
+ kref_put(&rdata->refcount, cifs_readdata_release);
+
+ cifs_small_buf_release(smb);
+ return rc;
+}
+
+int
+CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, char **buf, int *pbuf_type)
+{
+ int rc = -EACCES;
+ READ_REQ *pSMB = NULL;
+ READ_RSP *pSMBr = NULL;
+ char *pReadData = NULL;
+ int wct;
+ int resp_buf_type = 0;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ __u32 pid = io_parms->pid;
+ __u16 netfid = io_parms->netfid;
+ __u64 offset = io_parms->offset;
+ struct cifs_tcon *tcon = io_parms->tcon;
+ unsigned int count = io_parms->length;
+
+ cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
+ if (tcon->ses->capabilities & CAP_LARGE_FILES)
+ wct = 12;
+ else {
+ wct = 10; /* old style read */
+ if ((offset >> 32) > 0) {
+ /* can not handle this big offset for old */
+ return -EIO;
+ }
+ }
+
+ *nbytes = 0;
+ rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
+ pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
+
+ /* tcon and ses pointer are checked in smb_init */
+ if (tcon->ses->server == NULL)
+ return -ECONNABORTED;
+
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid;
+ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+ if (wct == 12)
+ pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+
+ pSMB->Remaining = 0;
+ pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
+ pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
+ if (wct == 12)
+ pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
+ else {
+ /* old style read */
+ struct smb_com_readx_req *pSMBW =
+ (struct smb_com_readx_req *)pSMB;
+ pSMBW->ByteCount = 0;
+ }
+
+ iov[0].iov_base = (char *)pSMB;
+ iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
+ rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
+ CIFS_LOG_ERROR, &rsp_iov);
+ cifs_small_buf_release(pSMB);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
+ pSMBr = (READ_RSP *)rsp_iov.iov_base;
+ if (rc) {
+ cifs_dbg(VFS, "Send error in read = %d\n", rc);
+ } else {
+ int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
+ data_length = data_length << 16;
+ data_length += le16_to_cpu(pSMBr->DataLength);
+ *nbytes = data_length;
+
+ /*check that DataLength would not go beyond end of SMB */
+ if ((data_length > CIFSMaxBufSize)
+ || (data_length > count)) {
+ cifs_dbg(FYI, "bad length %d for count %d\n",
+ data_length, count);
+ rc = -EIO;
+ *nbytes = 0;
+ } else {
+ pReadData = (char *) (&pSMBr->hdr.Protocol) +
+ le16_to_cpu(pSMBr->DataOffset);
+/* if (rc = copy_to_user(buf, pReadData, data_length)) {
+ cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
+ rc = -EFAULT;
+ }*/ /* can not use copy_to_user when using page cache*/
+ if (*buf)
+ memcpy(*buf, pReadData, data_length);
+ }
+ }
+
+ if (*buf) {
+ free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
+ } else if (resp_buf_type != CIFS_NO_BUFFER) {
+ /* return buffer to caller to free */
+ *buf = rsp_iov.iov_base;
+ if (resp_buf_type == CIFS_SMALL_BUFFER)
+ *pbuf_type = CIFS_SMALL_BUFFER;
+ else if (resp_buf_type == CIFS_LARGE_BUFFER)
+ *pbuf_type = CIFS_LARGE_BUFFER;
+ } /* else no valid buffer on return - leave as null */
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+ return rc;
+}
+
+
+int
+CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, const char *buf)
+{
+ int rc = -EACCES;
+ WRITE_REQ *pSMB = NULL;
+ WRITE_RSP *pSMBr = NULL;
+ int bytes_returned, wct;
+ __u32 bytes_sent;
+ __u16 byte_count;
+ __u32 pid = io_parms->pid;
+ __u16 netfid = io_parms->netfid;
+ __u64 offset = io_parms->offset;
+ struct cifs_tcon *tcon = io_parms->tcon;
+ unsigned int count = io_parms->length;
+
+ *nbytes = 0;
+
+ /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
+ if (tcon->ses == NULL)
+ return -ECONNABORTED;
+
+ if (tcon->ses->capabilities & CAP_LARGE_FILES)
+ wct = 14;
+ else {
+ wct = 12;
+ if ((offset >> 32) > 0) {
+ /* can not handle big offset for old srv */
+ return -EIO;
+ }
+ }
+
+ rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
+ pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
+
+ /* tcon and ses pointer are checked in smb_init */
+ if (tcon->ses->server == NULL)
+ return -ECONNABORTED;
+
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid;
+ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+ if (wct == 14)
+ pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+
+ pSMB->Reserved = 0xFFFFFFFF;
+ pSMB->WriteMode = 0;
+ pSMB->Remaining = 0;
+
+ /* Can increase buffer size if buffer is big enough in some cases ie we
+ can send more if LARGE_WRITE_X capability returned by the server and if
+ our buffer is big enough or if we convert to iovecs on socket writes
+ and eliminate the copy to the CIFS buffer */
+ if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
+ bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
+ } else {
+ bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
+ & ~0xFF;
+ }
+
+ if (bytes_sent > count)
+ bytes_sent = count;
+ pSMB->DataOffset =
+ cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
+ if (buf)
+ memcpy(pSMB->Data, buf, bytes_sent);
+ else if (count != 0) {
+ /* No buffer */
+ cifs_buf_release(pSMB);
+ return -EINVAL;
+ } /* else setting file size with write of zero bytes */
+ if (wct == 14)
+ byte_count = bytes_sent + 1; /* pad */
+ else /* wct == 12 */
+ byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
+
+ pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
+ pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
+ inc_rfc1001_len(pSMB, byte_count);
+
+ if (wct == 14)
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ else { /* old style write has byte count 4 bytes earlier
+ so 4 bytes pad */
+ struct smb_com_writex_req *pSMBW =
+ (struct smb_com_writex_req *)pSMB;
+ pSMBW->ByteCount = cpu_to_le16(byte_count);
+ }
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in write = %d\n", rc);
+ } else {
+ *nbytes = le16_to_cpu(pSMBr->CountHigh);
+ *nbytes = (*nbytes) << 16;
+ *nbytes += le16_to_cpu(pSMBr->Count);
+
+ /*
+ * Mask off high 16 bits when bytes written as returned by the
+ * server is greater than bytes requested by the client. Some
+ * OS/2 servers are known to set incorrect CountHigh values.
+ */
+ if (*nbytes > count)
+ *nbytes &= 0xFFFF;
+ }
+
+ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+/*
+ * Check the mid_state and signature on received buffer (if any), and queue the
+ * workqueue completion task.
+ */
+static void
+cifs_writev_callback(struct mid_q_entry *mid)
+{
+ struct cifs_writedata *wdata = mid->callback_data;
+ struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
+ unsigned int written;
+ WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
+ struct cifs_credits credits = { .value = 1, .instance = 0 };
+
+ switch (mid->mid_state) {
+ case MID_RESPONSE_RECEIVED:
+ wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
+ if (wdata->result != 0)
+ break;
+
+ written = le16_to_cpu(smb->CountHigh);
+ written <<= 16;
+ written += le16_to_cpu(smb->Count);
+ /*
+ * Mask off high 16 bits when bytes written as returned
+ * by the server is greater than bytes requested by the
+ * client. OS/2 servers are known to set incorrect
+ * CountHigh values.
+ */
+ if (written > wdata->bytes)
+ written &= 0xFFFF;
+
+ if (written < wdata->bytes)
+ wdata->result = -ENOSPC;
+ else
+ wdata->bytes = written;
+ break;
+ case MID_REQUEST_SUBMITTED:
+ case MID_RETRY_NEEDED:
+ wdata->result = -EAGAIN;
+ break;
+ default:
+ wdata->result = -EIO;
+ break;
+ }
+
+ queue_work(cifsiod_wq, &wdata->work);
+ release_mid(mid);
+ add_credits(tcon->ses->server, &credits, 0);
+}
+
+/* cifs_async_writev - send an async write, and set up mid to handle result */
+int
+cifs_async_writev(struct cifs_writedata *wdata,
+ void (*release)(struct kref *kref))
+{
+ int rc = -EACCES;
+ WRITE_REQ *smb = NULL;
+ int wct;
+ struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
+ struct kvec iov[2];
+ struct smb_rqst rqst = { };
+
+ if (tcon->ses->capabilities & CAP_LARGE_FILES) {
+ wct = 14;
+ } else {
+ wct = 12;
+ if (wdata->offset >> 32 > 0) {
+ /* can not handle big offset for old srv */
+ return -EIO;
+ }
+ }
+
+ rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
+ if (rc)
+ goto async_writev_out;
+
+ smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
+ smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
+
+ smb->AndXCommand = 0xFF; /* none */
+ smb->Fid = wdata->cfile->fid.netfid;
+ smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
+ if (wct == 14)
+ smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
+ smb->Reserved = 0xFFFFFFFF;
+ smb->WriteMode = 0;
+ smb->Remaining = 0;
+
+ smb->DataOffset =
+ cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
+
+ /* 4 for RFC1001 length + 1 for BCC */
+ iov[0].iov_len = 4;
+ iov[0].iov_base = smb;
+ iov[1].iov_len = get_rfc1002_length(smb) + 1;
+ iov[1].iov_base = (char *)smb + 4;
+
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 2;
+ rqst.rq_pages = wdata->pages;
+ rqst.rq_offset = wdata->page_offset;
+ rqst.rq_npages = wdata->nr_pages;
+ rqst.rq_pagesz = wdata->pagesz;
+ rqst.rq_tailsz = wdata->tailsz;
+
+ cifs_dbg(FYI, "async write at %llu %u bytes\n",
+ wdata->offset, wdata->bytes);
+
+ smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
+ smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
+
+ if (wct == 14) {
+ inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
+ put_bcc(wdata->bytes + 1, &smb->hdr);
+ } else {
+ /* wct == 12 */
+ struct smb_com_writex_req *smbw =
+ (struct smb_com_writex_req *)smb;
+ inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
+ put_bcc(wdata->bytes + 5, &smbw->hdr);
+ iov[1].iov_len += 4; /* pad bigger by four bytes */
+ }
+
+ kref_get(&wdata->refcount);
+ rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
+ cifs_writev_callback, NULL, wdata, 0, NULL);
+
+ if (rc == 0)
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
+ else
+ kref_put(&wdata->refcount, release);
+
+async_writev_out:
+ cifs_small_buf_release(smb);
+ return rc;
+}
+
+int
+CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, struct kvec *iov, int n_vec)
+{
+ int rc;
+ WRITE_REQ *pSMB = NULL;
+ int wct;
+ int smb_hdr_len;
+ int resp_buf_type = 0;
+ __u32 pid = io_parms->pid;
+ __u16 netfid = io_parms->netfid;
+ __u64 offset = io_parms->offset;
+ struct cifs_tcon *tcon = io_parms->tcon;
+ unsigned int count = io_parms->length;
+ struct kvec rsp_iov;
+
+ *nbytes = 0;
+
+ cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
+
+ if (tcon->ses->capabilities & CAP_LARGE_FILES) {
+ wct = 14;
+ } else {
+ wct = 12;
+ if ((offset >> 32) > 0) {
+ /* can not handle big offset for old srv */
+ return -EIO;
+ }
+ }
+ rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
+ pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
+
+ /* tcon and ses pointer are checked in smb_init */
+ if (tcon->ses->server == NULL)
+ return -ECONNABORTED;
+
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid;
+ pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+ if (wct == 14)
+ pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+ pSMB->Reserved = 0xFFFFFFFF;
+ pSMB->WriteMode = 0;
+ pSMB->Remaining = 0;
+
+ pSMB->DataOffset =
+ cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
+
+ pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
+ pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
+ /* header + 1 byte pad */
+ smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
+ if (wct == 14)
+ inc_rfc1001_len(pSMB, count + 1);
+ else /* wct == 12 */
+ inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
+ if (wct == 14)
+ pSMB->ByteCount = cpu_to_le16(count + 1);
+ else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
+ struct smb_com_writex_req *pSMBW =
+ (struct smb_com_writex_req *)pSMB;
+ pSMBW->ByteCount = cpu_to_le16(count + 5);
+ }
+ iov[0].iov_base = pSMB;
+ if (wct == 14)
+ iov[0].iov_len = smb_hdr_len + 4;
+ else /* wct == 12 pad bigger by four bytes */
+ iov[0].iov_len = smb_hdr_len + 8;
+
+ rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
+ &rsp_iov);
+ cifs_small_buf_release(pSMB);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
+ if (rc) {
+ cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
+ } else if (resp_buf_type == 0) {
+ /* presumably this can not happen, but best to be safe */
+ rc = -EIO;
+ } else {
+ WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
+ *nbytes = le16_to_cpu(pSMBr->CountHigh);
+ *nbytes = (*nbytes) << 16;
+ *nbytes += le16_to_cpu(pSMBr->Count);
+
+ /*
+ * Mask off high 16 bits when bytes written as returned by the
+ * server is greater than bytes requested by the client. OS/2
+ * servers are known to set incorrect CountHigh values.
+ */
+ if (*nbytes > count)
+ *nbytes &= 0xFFFF;
+ }
+
+ free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
+ const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
+{
+ int rc = 0;
+ LOCK_REQ *pSMB = NULL;
+ struct kvec iov[2];
+ struct kvec rsp_iov;
+ int resp_buf_type;
+ __u16 count;
+
+ cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
+ num_lock, num_unlock);
+
+ rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
+ if (rc)
+ return rc;
+
+ pSMB->Timeout = 0;
+ pSMB->NumberOfLocks = cpu_to_le16(num_lock);
+ pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
+ pSMB->LockType = lock_type;
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = netfid; /* netfid stays le */
+
+ count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
+ inc_rfc1001_len(pSMB, count);
+ pSMB->ByteCount = cpu_to_le16(count);
+
+ iov[0].iov_base = (char *)pSMB;
+ iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
+ (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
+ iov[1].iov_base = (char *)buf;
+ iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
+
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
+ rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
+ CIFS_NO_RSP_BUF, &rsp_iov);
+ cifs_small_buf_release(pSMB);
+ if (rc)
+ cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
+
+ return rc;
+}
+
+int
+CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u16 smb_file_id, const __u32 netpid, const __u64 len,
+ const __u64 offset, const __u32 numUnlock,
+ const __u32 numLock, const __u8 lockType,
+ const bool waitFlag, const __u8 oplock_level)
+{
+ int rc = 0;
+ LOCK_REQ *pSMB = NULL;
+/* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
+ int bytes_returned;
+ int flags = 0;
+ __u16 count;
+
+ cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
+ (int)waitFlag, numLock);
+ rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
+
+ if (rc)
+ return rc;
+
+ if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
+ /* no response expected */
+ flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
+ pSMB->Timeout = 0;
+ } else if (waitFlag) {
+ flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
+ pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
+ } else {
+ pSMB->Timeout = 0;
+ }
+
+ pSMB->NumberOfLocks = cpu_to_le16(numLock);
+ pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
+ pSMB->LockType = lockType;
+ pSMB->OplockLevel = oplock_level;
+ pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->Fid = smb_file_id; /* netfid stays le */
+
+ if ((numLock != 0) || (numUnlock != 0)) {
+ pSMB->Locks[0].Pid = cpu_to_le16(netpid);
+ /* BB where to store pid high? */
+ pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
+ pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
+ pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
+ pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
+ count = sizeof(LOCKING_ANDX_RANGE);
+ } else {
+ /* oplock break */
+ count = 0;
+ }
+ inc_rfc1001_len(pSMB, count);
+ pSMB->ByteCount = cpu_to_le16(count);
+
+ if (waitFlag)
+ rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMB, &bytes_returned);
+ else
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
+ cifs_small_buf_release(pSMB);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
+ if (rc)
+ cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+ return rc;
+}
+
+int
+CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u16 smb_file_id, const __u32 netpid,
+ const loff_t start_offset, const __u64 len,
+ struct file_lock *pLockData, const __u16 lock_type,
+ const bool waitFlag)
+{
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+ struct cifs_posix_lock *parm_data;
+ int rc = 0;
+ int timeout = 0;
+ int bytes_returned = 0;
+ int resp_buf_type = 0;
+ __u16 params, param_offset, offset, byte_count, count;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+
+ cifs_dbg(FYI, "Posix Lock\n");
+
+ rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+ if (rc)
+ return rc;
+
+ pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
+
+ params = 6;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+ offset = param_offset + params;
+
+ count = sizeof(struct cifs_posix_lock);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ if (pLockData)
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+ else
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
+ parm_data = (struct cifs_posix_lock *)
+ (((char *)pSMB) + offset + 4);
+
+ parm_data->lock_type = cpu_to_le16(lock_type);
+ if (waitFlag) {
+ timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
+ parm_data->lock_flags = cpu_to_le16(1);
+ pSMB->Timeout = cpu_to_le32(-1);
+ } else
+ pSMB->Timeout = 0;
+
+ parm_data->pid = cpu_to_le32(netpid);
+ parm_data->start = cpu_to_le64(start_offset);
+ parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
+
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->Fid = smb_file_id;
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ if (waitFlag) {
+ rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned);
+ } else {
+ iov[0].iov_base = (char *)pSMB;
+ iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
+ rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
+ &resp_buf_type, timeout, &rsp_iov);
+ pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
+ }
+ cifs_small_buf_release(pSMB);
+
+ if (rc) {
+ cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
+ } else if (pLockData) {
+ /* lock structure can be returned on get */
+ __u16 data_offset;
+ __u16 data_count;
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
+ rc = -EIO; /* bad smb */
+ goto plk_err_exit;
+ }
+ data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ data_count = le16_to_cpu(pSMBr->t2.DataCount);
+ if (data_count < sizeof(struct cifs_posix_lock)) {
+ rc = -EIO;
+ goto plk_err_exit;
+ }
+ parm_data = (struct cifs_posix_lock *)
+ ((char *)&pSMBr->hdr.Protocol + data_offset);
+ if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
+ pLockData->fl_type = F_UNLCK;
+ else {
+ if (parm_data->lock_type ==
+ cpu_to_le16(CIFS_RDLCK))
+ pLockData->fl_type = F_RDLCK;
+ else if (parm_data->lock_type ==
+ cpu_to_le16(CIFS_WRLCK))
+ pLockData->fl_type = F_WRLCK;
+
+ pLockData->fl_start = le64_to_cpu(parm_data->start);
+ pLockData->fl_end = pLockData->fl_start +
+ (le64_to_cpu(parm_data->length) ?
+ le64_to_cpu(parm_data->length) - 1 : 0);
+ pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
+ }
+ }
+
+plk_err_exit:
+ free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+
+int
+CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
+{
+ int rc = 0;
+ CLOSE_REQ *pSMB = NULL;
+ cifs_dbg(FYI, "In CIFSSMBClose\n");
+
+/* do not retry on dead session on close */
+ rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
+ if (rc == -EAGAIN)
+ return 0;
+ if (rc)
+ return rc;
+
+ pSMB->FileID = (__u16) smb_file_id;
+ pSMB->LastWriteTime = 0xFFFFFFFF;
+ pSMB->ByteCount = 0;
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
+ cifs_small_buf_release(pSMB);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
+ if (rc) {
+ if (rc != -EINTR) {
+ /* EINTR is expected when user ctl-c to kill app */
+ cifs_dbg(VFS, "Send error in Close = %d\n", rc);
+ }
+ }
+
+ /* Since session is dead, file will be closed on server already */
+ if (rc == -EAGAIN)
+ rc = 0;
+
+ return rc;
+}
+
+int
+CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
+{
+ int rc = 0;
+ FLUSH_REQ *pSMB = NULL;
+ cifs_dbg(FYI, "In CIFSSMBFlush\n");
+
+ rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
+ if (rc)
+ return rc;
+
+ pSMB->FileID = (__u16) smb_file_id;
+ pSMB->ByteCount = 0;
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
+ cifs_small_buf_release(pSMB);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
+ if (rc)
+ cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
+
+ return rc;
+}
+
+int
+CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb)
+{
+ int rc = 0;
+ RENAME_REQ *pSMB = NULL;
+ RENAME_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len, name_len2;
+ __u16 count;
+ int remap = cifs_remap(cifs_sb);
+
+ cifs_dbg(FYI, "In CIFSSMBRename\n");
+renameRetry:
+ rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->BufferFormat = 0x04;
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+ ATTR_DIRECTORY);
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
+ from_name, PATH_MAX,
+ cifs_sb->local_nls, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ pSMB->OldFileName[name_len] = 0x04; /* pad */
+ /* protocol requires ASCII signature byte on Unicode string */
+ pSMB->OldFileName[name_len + 1] = 0x00;
+ name_len2 =
+ cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+ to_name, PATH_MAX, cifs_sb->local_nls,
+ remap);
+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
+ name_len2 *= 2; /* convert to bytes */
+ } else {
+ name_len = copy_path_name(pSMB->OldFileName, from_name);
+ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
+ name_len2++; /* signature byte */
+ }
+
+ count = 1 /* 1st signature byte */ + name_len + name_len2;
+ inc_rfc1001_len(pSMB, count);
+ pSMB->ByteCount = cpu_to_le16(count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
+ if (rc)
+ cifs_dbg(FYI, "Send error in rename = %d\n", rc);
+
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto renameRetry;
+
+ return rc;
+}
+
+int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
+ int netfid, const char *target_name,
+ const struct nls_table *nls_codepage, int remap)
+{
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+ struct set_file_rename *rename_info;
+ char *data_offset;
+ char dummy_string[30];
+ int rc = 0;
+ int bytes_returned = 0;
+ int len_of_str;
+ __u16 params, param_offset, offset, count, byte_count;
+
+ cifs_dbg(FYI, "Rename to File by handle\n");
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 6;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+ offset = param_offset + params;
+
+ /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
+ data_offset = (char *)(pSMB) + offset + 4;
+ rename_info = (struct set_file_rename *) data_offset;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+ byte_count = 3 /* pad */ + params;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ /* construct random name ".cifs_tmp<inodenum><mid>" */
+ rename_info->overwrite = cpu_to_le32(1);
+ rename_info->root_fid = 0;
+ /* unicode only call */
+ if (target_name == NULL) {
+ sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
+ len_of_str =
+ cifsConvertToUTF16((__le16 *)rename_info->target_name,
+ dummy_string, 24, nls_codepage, remap);
+ } else {
+ len_of_str =
+ cifsConvertToUTF16((__le16 *)rename_info->target_name,
+ target_name, PATH_MAX, nls_codepage,
+ remap);
+ }
+ rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
+ count = sizeof(struct set_file_rename) + (2 * len_of_str);
+ byte_count += count;
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->Fid = netfid;
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
+ if (rc)
+ cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
+ rc);
+
+ cifs_buf_release(pSMB);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+int
+CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fromName, const __u16 target_tid, const char *toName,
+ const int flags, const struct nls_table *nls_codepage, int remap)
+{
+ int rc = 0;
+ COPY_REQ *pSMB = NULL;
+ COPY_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len, name_len2;
+ __u16 count;
+
+ cifs_dbg(FYI, "In CIFSSMBCopy\n");
+copyRetry:
+ rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->BufferFormat = 0x04;
+ pSMB->Tid2 = target_tid;
+
+ pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
+ fromName, PATH_MAX, nls_codepage,
+ remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ pSMB->OldFileName[name_len] = 0x04; /* pad */
+ /* protocol requires ASCII signature byte on Unicode string */
+ pSMB->OldFileName[name_len + 1] = 0x00;
+ name_len2 =
+ cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+ toName, PATH_MAX, nls_codepage, remap);
+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
+ name_len2 *= 2; /* convert to bytes */
+ } else {
+ name_len = copy_path_name(pSMB->OldFileName, fromName);
+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
+ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
+ name_len2++; /* signature byte */
+ }
+
+ count = 1 /* 1st signature byte */ + name_len + name_len2;
+ inc_rfc1001_len(pSMB, count);
+ pSMB->ByteCount = cpu_to_le16(count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
+ rc, le16_to_cpu(pSMBr->CopyCount));
+ }
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto copyRetry;
+
+ return rc;
+}
+
+int
+CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage, int remap)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ char *data_offset;
+ int name_len;
+ int name_len_target;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, param_offset, offset, byte_count;
+
+ cifs_dbg(FYI, "In Symlink Unix style\n");
+createSymLinkRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
+ /* find define for this maxpathcomponent */
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fromName);
+ }
+ params = 6 + name_len;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+
+ /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
+ data_offset = (char *)pSMB + offset + 4;
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len_target =
+ cifsConvertToUTF16((__le16 *) data_offset, toName,
+ /* find define for this maxpathcomponent */
+ PATH_MAX, nls_codepage, remap);
+ name_len_target++; /* trailing null */
+ name_len_target *= 2;
+ } else {
+ name_len_target = copy_path_name(data_offset, toName);
+ }
+
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max on data count below from sess */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + name_len_target;
+ pSMB->DataCount = cpu_to_le16(name_len_target);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
+ if (rc)
+ cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
+ rc);
+
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto createSymLinkRetry;
+
+ return rc;
+}
+
+int
+CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fromName, const char *toName,
+ const struct nls_table *nls_codepage, int remap)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ char *data_offset;
+ int name_len;
+ int name_len_target;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, param_offset, offset, byte_count;
+
+ cifs_dbg(FYI, "In Create Hard link Unix style\n");
+createHardLinkRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+
+ } else {
+ name_len = copy_path_name(pSMB->FileName, toName);
+ }
+ params = 6 + name_len;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+
+ /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
+ data_offset = (char *)pSMB + offset + 4;
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len_target =
+ cifsConvertToUTF16((__le16 *) data_offset, fromName,
+ PATH_MAX, nls_codepage, remap);
+ name_len_target++; /* trailing null */
+ name_len_target *= 2;
+ } else {
+ name_len_target = copy_path_name(data_offset, fromName);
+ }
+
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max on data count below from sess*/
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + name_len_target;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->DataCount = cpu_to_le16(name_len_target);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
+ if (rc)
+ cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
+ rc);
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto createHardLinkRetry;
+
+ return rc;
+}
+
+int
+CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb)
+{
+ int rc = 0;
+ NT_RENAME_REQ *pSMB = NULL;
+ RENAME_RSP *pSMBr = NULL;
+ int bytes_returned;
+ int name_len, name_len2;
+ __u16 count;
+ int remap = cifs_remap(cifs_sb);
+
+ cifs_dbg(FYI, "In CIFSCreateHardLink\n");
+winCreateHardLinkRetry:
+
+ rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+ ATTR_DIRECTORY);
+ pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
+ pSMB->ClusterCount = 0;
+
+ pSMB->BufferFormat = 0x04;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
+ PATH_MAX, cifs_sb->local_nls, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+
+ /* protocol specifies ASCII buffer format (0x04) for unicode */
+ pSMB->OldFileName[name_len] = 0x04;
+ pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
+ name_len2 =
+ cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+ to_name, PATH_MAX, cifs_sb->local_nls,
+ remap);
+ name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
+ name_len2 *= 2; /* convert to bytes */
+ } else {
+ name_len = copy_path_name(pSMB->OldFileName, from_name);
+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
+ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
+ name_len2++; /* signature byte */
+ }
+
+ count = 1 /* string type byte */ + name_len + name_len2;
+ inc_rfc1001_len(pSMB, count);
+ pSMB->ByteCount = cpu_to_le16(count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
+ if (rc)
+ cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto winCreateHardLinkRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *searchName, char **symlinkinfo,
+ const struct nls_table *nls_codepage, int remap)
+{
+/* SMB_QUERY_FILE_UNIX_LINK */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ __u16 params, byte_count;
+ char *data_start;
+
+ cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
+
+querySymLinkRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName,
+ searchName, PATH_MAX, nls_codepage,
+ remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, searchName);
+ }
+
+ params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
+ } else {
+ /* decode response */
+
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ /* BB also check enough total bytes returned */
+ if (rc || get_bcc(&pSMBr->hdr) < 2)
+ rc = -EIO;
+ else {
+ bool is_unicode;
+ u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+
+ data_start = ((char *) &pSMBr->hdr.Protocol) +
+ le16_to_cpu(pSMBr->t2.DataOffset);
+
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ is_unicode = true;
+ else
+ is_unicode = false;
+
+ /* BB FIXME investigate remapping reserved chars here */
+ *symlinkinfo = cifs_strndup_from_utf16(data_start,
+ count, is_unicode, nls_codepage);
+ if (!*symlinkinfo)
+ rc = -ENOMEM;
+ }
+ }
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto querySymLinkRetry;
+ return rc;
+}
+
+/*
+ * Recent Windows versions now create symlinks more frequently
+ * and they use the "reparse point" mechanism below. We can of course
+ * do symlinks nicely to Samba and other servers which support the
+ * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
+ * "MF" symlinks optionally, but for recent Windows we really need to
+ * reenable the code below and fix the cifs_symlink callers to handle this.
+ * In the interim this code has been moved to its own config option so
+ * it is not compiled in by default until callers fixed up and more tested.
+ */
+int
+CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
+ __u16 fid, char **symlinkinfo,
+ const struct nls_table *nls_codepage)
+{
+ int rc = 0;
+ int bytes_returned;
+ struct smb_com_transaction_ioctl_req *pSMB;
+ struct smb_com_transaction_ioctl_rsp *pSMBr;
+ bool is_unicode;
+ unsigned int sub_len;
+ char *sub_start;
+ struct reparse_symlink_data *reparse_buf;
+ struct reparse_posix_data *posix_buf;
+ __u32 data_offset, data_count;
+ char *end_of_smb;
+
+ cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->TotalParameterCount = 0 ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le32(2);
+ /* BB find exact data count max from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
+ pSMB->MaxSetupCount = 4;
+ pSMB->Reserved = 0;
+ pSMB->ParameterOffset = 0;
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 4;
+ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
+ pSMB->IsFsctl = 1; /* FSCTL */
+ pSMB->IsRootFlag = 0;
+ pSMB->Fid = fid; /* file handle always le */
+ pSMB->ByteCount = 0;
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
+ goto qreparse_out;
+ }
+
+ data_offset = le32_to_cpu(pSMBr->DataOffset);
+ data_count = le32_to_cpu(pSMBr->DataCount);
+ if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
+ /* BB also check enough total bytes returned */
+ rc = -EIO; /* bad smb */
+ goto qreparse_out;
+ }
+ if (!data_count || (data_count > 2048)) {
+ rc = -EIO;
+ cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
+ goto qreparse_out;
+ }
+ end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
+ reparse_buf = (struct reparse_symlink_data *)
+ ((char *)&pSMBr->hdr.Protocol + data_offset);
+ if ((char *)reparse_buf >= end_of_smb) {
+ rc = -EIO;
+ goto qreparse_out;
+ }
+ if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
+ cifs_dbg(FYI, "NFS style reparse tag\n");
+ posix_buf = (struct reparse_posix_data *)reparse_buf;
+
+ if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
+ cifs_dbg(FYI, "unsupported file type 0x%llx\n",
+ le64_to_cpu(posix_buf->InodeType));
+ rc = -EOPNOTSUPP;
+ goto qreparse_out;
+ }
+ is_unicode = true;
+ sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
+ if (posix_buf->PathBuffer + sub_len > end_of_smb) {
+ cifs_dbg(FYI, "reparse buf beyond SMB\n");
+ rc = -EIO;
+ goto qreparse_out;
+ }
+ *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
+ sub_len, is_unicode, nls_codepage);
+ goto qreparse_out;
+ } else if (reparse_buf->ReparseTag !=
+ cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
+ rc = -EOPNOTSUPP;
+ goto qreparse_out;
+ }
+
+ /* Reparse tag is NTFS symlink */
+ sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
+ reparse_buf->PathBuffer;
+ sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
+ if (sub_start + sub_len > end_of_smb) {
+ cifs_dbg(FYI, "reparse buf beyond SMB\n");
+ rc = -EIO;
+ goto qreparse_out;
+ }
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ is_unicode = true;
+ else
+ is_unicode = false;
+
+ /* BB FIXME investigate remapping reserved chars here */
+ *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
+ nls_codepage);
+ if (!*symlinkinfo)
+ rc = -ENOMEM;
+qreparse_out:
+ cifs_buf_release(pSMB);
+
+ /*
+ * Note: On -EAGAIN error only caller can retry on handle based calls
+ * since file handle passed in no longer valid.
+ */
+ return rc;
+}
+
+int
+CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+ __u16 fid)
+{
+ int rc = 0;
+ int bytes_returned;
+ struct smb_com_transaction_compr_ioctl_req *pSMB;
+ struct smb_com_transaction_ioctl_rsp *pSMBr;
+
+ cifs_dbg(FYI, "Set compression for %u\n", fid);
+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
+
+ pSMB->TotalParameterCount = 0;
+ pSMB->TotalDataCount = cpu_to_le32(2);
+ pSMB->MaxParameterCount = 0;
+ pSMB->MaxDataCount = 0;
+ pSMB->MaxSetupCount = 4;
+ pSMB->Reserved = 0;
+ pSMB->ParameterOffset = 0;
+ pSMB->DataCount = cpu_to_le32(2);
+ pSMB->DataOffset =
+ cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
+ compression_state) - 4); /* 84 */
+ pSMB->SetupCount = 4;
+ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
+ pSMB->ParameterCount = 0;
+ pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
+ pSMB->IsFsctl = 1; /* FSCTL */
+ pSMB->IsRootFlag = 0;
+ pSMB->Fid = fid; /* file handle always le */
+ /* 3 byte pad, followed by 2 byte compress state */
+ pSMB->ByteCount = cpu_to_le16(5);
+ inc_rfc1001_len(pSMB, 5);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc)
+ cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
+
+ cifs_buf_release(pSMB);
+
+ /*
+ * Note: On -EAGAIN error only caller can retry on handle based calls
+ * since file handle passed in no longer valid.
+ */
+ return rc;
+}
+
+
+#ifdef CONFIG_CIFS_POSIX
+
+/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
+static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
+ struct cifs_posix_ace *cifs_ace)
+{
+ /* u8 cifs fields do not need le conversion */
+ ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
+ ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
+ ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
+/*
+ cifs_dbg(FYI, "perm %d tag %d id %d\n",
+ ace->e_perm, ace->e_tag, ace->e_id);
+*/
+
+ return;
+}
+
+/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
+static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
+ const int acl_type, const int size_of_data_area)
+{
+ int size = 0;
+ int i;
+ __u16 count;
+ struct cifs_posix_ace *pACE;
+ struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
+ struct posix_acl_xattr_header *local_acl = (void *)trgt;
+
+ if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
+ return -EOPNOTSUPP;
+
+ if (acl_type == ACL_TYPE_ACCESS) {
+ count = le16_to_cpu(cifs_acl->access_entry_count);
+ pACE = &cifs_acl->ace_array[0];
+ size = sizeof(struct cifs_posix_acl);
+ size += sizeof(struct cifs_posix_ace) * count;
+ /* check if we would go beyond end of SMB */
+ if (size_of_data_area < size) {
+ cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
+ size_of_data_area, size);
+ return -EINVAL;
+ }
+ } else if (acl_type == ACL_TYPE_DEFAULT) {
+ count = le16_to_cpu(cifs_acl->access_entry_count);
+ size = sizeof(struct cifs_posix_acl);
+ size += sizeof(struct cifs_posix_ace) * count;
+/* skip past access ACEs to get to default ACEs */
+ pACE = &cifs_acl->ace_array[count];
+ count = le16_to_cpu(cifs_acl->default_entry_count);
+ size += sizeof(struct cifs_posix_ace) * count;
+ /* check if we would go beyond end of SMB */
+ if (size_of_data_area < size)
+ return -EINVAL;
+ } else {
+ /* illegal type */
+ return -EINVAL;
+ }
+
+ size = posix_acl_xattr_size(count);
+ if ((buflen == 0) || (local_acl == NULL)) {
+ /* used to query ACL EA size */
+ } else if (size > buflen) {
+ return -ERANGE;
+ } else /* buffer big enough */ {
+ struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
+
+ local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
+ for (i = 0; i < count ; i++) {
+ cifs_convert_ace(&ace[i], pACE);
+ pACE++;
+ }
+ }
+ return size;
+}
+
+static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
+ const struct posix_acl_xattr_entry *local_ace)
+{
+ cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
+ cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
+ /* BB is there a better way to handle the large uid? */
+ if (local_ace->e_id == cpu_to_le32(-1)) {
+ /* Probably no need to le convert -1 on any arch but can not hurt */
+ cifs_ace->cifs_uid = cpu_to_le64(-1);
+ } else
+ cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
+/*
+ cifs_dbg(FYI, "perm %d tag %d id %d\n",
+ ace->e_perm, ace->e_tag, ace->e_id);
+*/
+}
+
+/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
+static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
+ const int buflen, const int acl_type)
+{
+ __u16 rc = 0;
+ struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
+ struct posix_acl_xattr_header *local_acl = (void *)pACL;
+ struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
+ int count;
+ int i;
+
+ if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
+ return 0;
+
+ count = posix_acl_xattr_count((size_t)buflen);
+ cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
+ count, buflen, le32_to_cpu(local_acl->a_version));
+ if (le32_to_cpu(local_acl->a_version) != 2) {
+ cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
+ le32_to_cpu(local_acl->a_version));
+ return 0;
+ }
+ cifs_acl->version = cpu_to_le16(1);
+ if (acl_type == ACL_TYPE_ACCESS) {
+ cifs_acl->access_entry_count = cpu_to_le16(count);
+ cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
+ } else if (acl_type == ACL_TYPE_DEFAULT) {
+ cifs_acl->default_entry_count = cpu_to_le16(count);
+ cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
+ } else {
+ cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
+ return 0;
+ }
+ for (i = 0; i < count; i++)
+ convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
+ if (rc == 0) {
+ rc = (__u16)(count * sizeof(struct cifs_posix_ace));
+ rc += sizeof(struct cifs_posix_acl);
+ /* BB add check to make sure ACL does not overflow SMB */
+ }
+ return rc;
+}
+
+int
+CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *searchName,
+ char *acl_inf, const int buflen, const int acl_type,
+ const struct nls_table *nls_codepage, int remap)
+{
+/* SMB_QUERY_POSIX_ACL */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
+
+queryAclRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName,
+ searchName, PATH_MAX, nls_codepage,
+ remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ pSMB->FileName[name_len] = 0;
+ pSMB->FileName[name_len+1] = 0;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, searchName);
+ }
+
+ params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(
+ offsetof(struct smb_com_transaction2_qpi_req,
+ InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
+ } else {
+ /* decode response */
+
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ /* BB also check enough total bytes returned */
+ if (rc || get_bcc(&pSMBr->hdr) < 2)
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+ rc = cifs_copy_posix_acl(acl_inf,
+ (char *)&pSMBr->hdr.Protocol+data_offset,
+ buflen, acl_type, count);
+ }
+ }
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto queryAclRetry;
+ return rc;
+}
+
+int
+CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *fileName,
+ const char *local_acl, const int buflen,
+ const int acl_type,
+ const struct nls_table *nls_codepage, int remap)
+{
+ struct smb_com_transaction2_spi_req *pSMB = NULL;
+ struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+ char *parm_data;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, byte_count, data_count, param_offset, offset;
+
+ cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
+setAclRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fileName);
+ }
+ params = 6 + name_len;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find max SMB size from sess */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+ parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+
+ /* convert to on the wire format for POSIX ACL */
+ data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
+
+ if (data_count == 0) {
+ rc = -EOPNOTSUPP;
+ goto setACLerrorExit;
+ }
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
+ byte_count = 3 /* pad */ + params + data_count;
+ pSMB->DataCount = cpu_to_le16(data_count);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc)
+ cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
+
+setACLerrorExit:
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto setAclRetry;
+ return rc;
+}
+
+int
+CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
+ const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
+{
+ int rc = 0;
+ struct smb_t2_qfi_req *pSMB = NULL;
+ struct smb_t2_qfi_rsp *pSMBr = NULL;
+ int bytes_returned;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In GetExtAttr\n");
+ if (tcon == NULL)
+ return -ENODEV;
+
+GetExtAttrRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2 /* level */ + 2 /* fid */;
+ pSMB->t2.TotalDataCount = 0;
+ pSMB->t2.MaxParameterCount = cpu_to_le16(4);
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->t2.MaxDataCount = cpu_to_le16(4000);
+ pSMB->t2.MaxSetupCount = 0;
+ pSMB->t2.Reserved = 0;
+ pSMB->t2.Flags = 0;
+ pSMB->t2.Timeout = 0;
+ pSMB->t2.Reserved2 = 0;
+ pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
+ Fid) - 4);
+ pSMB->t2.DataCount = 0;
+ pSMB->t2.DataOffset = 0;
+ pSMB->t2.SetupCount = 1;
+ pSMB->t2.Reserved3 = 0;
+ pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->t2.TotalParameterCount = cpu_to_le16(params);
+ pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
+ pSMB->Pad = 0;
+ pSMB->Fid = netfid;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->t2.ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
+ } else {
+ /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ /* BB also check enough total bytes returned */
+ if (rc || get_bcc(&pSMBr->hdr) < 2)
+ /* If rc should we check for EOPNOSUPP and
+ disable the srvino flag? or in caller? */
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+ struct file_chattr_info *pfinfo;
+
+ if (count != 16) {
+ cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
+ rc = -EIO;
+ goto GetExtAttrOut;
+ }
+ pfinfo = (struct file_chattr_info *)
+ (data_offset + (char *) &pSMBr->hdr.Protocol);
+ *pExtAttrBits = le64_to_cpu(pfinfo->mode);
+ *pMask = le64_to_cpu(pfinfo->mask);
+ }
+ }
+GetExtAttrOut:
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto GetExtAttrRetry;
+ return rc;
+}
+
+#endif /* CONFIG_POSIX */
+
+/*
+ * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
+ * all NT TRANSACTS that we init here have total parm and data under about 400
+ * bytes (to fit in small cifs buffer size), which is the case so far, it
+ * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
+ * returned setup area) and MaxParameterCount (returned parms size) must be set
+ * by caller
+ */
+static int
+smb_init_nttransact(const __u16 sub_command, const int setup_count,
+ const int parm_len, struct cifs_tcon *tcon,
+ void **ret_buf)
+{
+ int rc;
+ __u32 temp_offset;
+ struct smb_com_ntransact_req *pSMB;
+
+ rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
+ (void **)&pSMB);
+ if (rc)
+ return rc;
+ *ret_buf = (void *)pSMB;
+ pSMB->Reserved = 0;
+ pSMB->TotalParameterCount = cpu_to_le32(parm_len);
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->DataCount = pSMB->TotalDataCount;
+ temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
+ (setup_count * 2) - 4 /* for rfc1001 length itself */;
+ pSMB->ParameterOffset = cpu_to_le32(temp_offset);
+ pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
+ pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
+ pSMB->SubCommand = cpu_to_le16(sub_command);
+ return 0;
+}
+
+static int
+validate_ntransact(char *buf, char **ppparm, char **ppdata,
+ __u32 *pparmlen, __u32 *pdatalen)
+{
+ char *end_of_smb;
+ __u32 data_count, data_offset, parm_count, parm_offset;
+ struct smb_com_ntransact_rsp *pSMBr;
+ u16 bcc;
+
+ *pdatalen = 0;
+ *pparmlen = 0;
+
+ if (buf == NULL)
+ return -EINVAL;
+
+ pSMBr = (struct smb_com_ntransact_rsp *)buf;
+
+ bcc = get_bcc(&pSMBr->hdr);
+ end_of_smb = 2 /* sizeof byte count */ + bcc +
+ (char *)&pSMBr->ByteCount;
+
+ data_offset = le32_to_cpu(pSMBr->DataOffset);
+ data_count = le32_to_cpu(pSMBr->DataCount);
+ parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
+ parm_count = le32_to_cpu(pSMBr->ParameterCount);
+
+ *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
+ *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
+
+ /* should we also check that parm and data areas do not overlap? */
+ if (*ppparm > end_of_smb) {
+ cifs_dbg(FYI, "parms start after end of smb\n");
+ return -EINVAL;
+ } else if (parm_count + *ppparm > end_of_smb) {
+ cifs_dbg(FYI, "parm end after end of smb\n");
+ return -EINVAL;
+ } else if (*ppdata > end_of_smb) {
+ cifs_dbg(FYI, "data starts after end of smb\n");
+ return -EINVAL;
+ } else if (data_count + *ppdata > end_of_smb) {
+ cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
+ *ppdata, data_count, (data_count + *ppdata),
+ end_of_smb, pSMBr);
+ return -EINVAL;
+ } else if (parm_count + data_count > bcc) {
+ cifs_dbg(FYI, "parm count and data count larger than SMB\n");
+ return -EINVAL;
+ }
+ *pdatalen = data_count;
+ *pparmlen = parm_count;
+ return 0;
+}
+
+/* Get Security Descriptor (by handle) from remote server for a file or dir */
+int
+CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
+ struct cifs_ntsd **acl_inf, __u32 *pbuflen)
+{
+ int rc = 0;
+ int buf_type = 0;
+ QUERY_SEC_DESC_REQ *pSMB;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+
+ cifs_dbg(FYI, "GetCifsACL\n");
+
+ *pbuflen = 0;
+ *acl_inf = NULL;
+
+ rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
+ 8 /* parm len */, tcon, (void **) &pSMB);
+ if (rc)
+ return rc;
+
+ pSMB->MaxParameterCount = cpu_to_le32(4);
+ /* BB TEST with big acls that might need to be e.g. larger than 16K */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Fid = fid; /* file handle always le */
+ pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
+ CIFS_ACL_DACL);
+ pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
+ inc_rfc1001_len(pSMB, 11);
+ iov[0].iov_base = (char *)pSMB;
+ iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
+
+ rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
+ 0, &rsp_iov);
+ cifs_small_buf_release(pSMB);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
+ } else { /* decode response */
+ __le32 *parm;
+ __u32 parm_len;
+ __u32 acl_len;
+ struct smb_com_ntransact_rsp *pSMBr;
+ char *pdata;
+
+/* validate_nttransact */
+ rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
+ &pdata, &parm_len, pbuflen);
+ if (rc)
+ goto qsec_out;
+ pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
+
+ cifs_dbg(FYI, "smb %p parm %p data %p\n",
+ pSMBr, parm, *acl_inf);
+
+ if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
+ rc = -EIO; /* bad smb */
+ *pbuflen = 0;
+ goto qsec_out;
+ }
+
+/* BB check that data area is minimum length and as big as acl_len */
+
+ acl_len = le32_to_cpu(*parm);
+ if (acl_len != *pbuflen) {
+ cifs_dbg(VFS, "acl length %d does not match %d\n",
+ acl_len, *pbuflen);
+ if (*pbuflen > acl_len)
+ *pbuflen = acl_len;
+ }
+
+ /* check if buffer is big enough for the acl
+ header followed by the smallest SID */
+ if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
+ (*pbuflen >= 64 * 1024)) {
+ cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
+ rc = -EINVAL;
+ *pbuflen = 0;
+ } else {
+ *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
+ if (*acl_inf == NULL) {
+ *pbuflen = 0;
+ rc = -ENOMEM;
+ }
+ }
+ }
+qsec_out:
+ free_rsp_buf(buf_type, rsp_iov.iov_base);
+ return rc;
+}
+
+int
+CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
+ struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
+{
+ __u16 byte_count, param_count, data_count, param_offset, data_offset;
+ int rc = 0;
+ int bytes_returned = 0;
+ SET_SEC_DESC_REQ *pSMB = NULL;
+ void *pSMBr;
+
+setCifsAclRetry:
+ rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
+ if (rc)
+ return rc;
+
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+
+ param_count = 8;
+ param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
+ data_count = acllen;
+ data_offset = param_offset + param_count;
+ byte_count = 3 /* pad */ + param_count;
+
+ pSMB->DataCount = cpu_to_le32(data_count);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->MaxParameterCount = cpu_to_le32(4);
+ pSMB->MaxDataCount = cpu_to_le32(16384);
+ pSMB->ParameterCount = cpu_to_le32(param_count);
+ pSMB->ParameterOffset = cpu_to_le32(param_offset);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->DataOffset = cpu_to_le32(data_offset);
+ pSMB->SetupCount = 0;
+ pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
+ pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
+
+ pSMB->Fid = fid; /* file handle always le */
+ pSMB->Reserved2 = 0;
+ pSMB->AclFlags = cpu_to_le32(aclflag);
+
+ if (pntsd && acllen) {
+ memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
+ data_offset, pntsd, acllen);
+ inc_rfc1001_len(pSMB, byte_count + data_count);
+ } else
+ inc_rfc1001_len(pSMB, byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+
+ cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
+ bytes_returned, rc);
+ if (rc)
+ cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto setCifsAclRetry;
+
+ return (rc);
+}
+
+
+/* Legacy Query Path Information call for lookup to old servers such
+ as Win9x/WinME */
+int
+SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, FILE_ALL_INFO *data,
+ const struct nls_table *nls_codepage, int remap)
+{
+ QUERY_INFORMATION_REQ *pSMB;
+ QUERY_INFORMATION_RSP *pSMBr;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+
+ cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
+QInfRetry:
+ rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName,
+ search_name, PATH_MAX, nls_codepage,
+ remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, search_name);
+ }
+ pSMB->BufferFormat = 0x04;
+ name_len++; /* account for buffer type byte */
+ inc_rfc1001_len(pSMB, (__u16)name_len);
+ pSMB->ByteCount = cpu_to_le16(name_len);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
+ } else if (data) {
+ struct timespec64 ts;
+ __u32 time = le32_to_cpu(pSMBr->last_write_time);
+
+ /* decode response */
+ /* BB FIXME - add time zone adjustment BB */
+ memset(data, 0, sizeof(FILE_ALL_INFO));
+ ts.tv_nsec = 0;
+ ts.tv_sec = time;
+ /* decode time fields */
+ data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
+ data->LastWriteTime = data->ChangeTime;
+ data->LastAccessTime = 0;
+ data->AllocationSize =
+ cpu_to_le64(le32_to_cpu(pSMBr->size));
+ data->EndOfFile = data->AllocationSize;
+ data->Attributes =
+ cpu_to_le32(le16_to_cpu(pSMBr->attr));
+ } else
+ rc = -EIO; /* bad buffer passed in */
+
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QInfRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ u16 netfid, FILE_ALL_INFO *pFindData)
+{
+ struct smb_t2_qfi_req *pSMB = NULL;
+ struct smb_t2_qfi_rsp *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ __u16 params, byte_count;
+
+QFileInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2 /* level */ + 2 /* fid */;
+ pSMB->t2.TotalDataCount = 0;
+ pSMB->t2.MaxParameterCount = cpu_to_le16(4);
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
+ pSMB->t2.MaxSetupCount = 0;
+ pSMB->t2.Reserved = 0;
+ pSMB->t2.Flags = 0;
+ pSMB->t2.Timeout = 0;
+ pSMB->t2.Reserved2 = 0;
+ pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
+ Fid) - 4);
+ pSMB->t2.DataCount = 0;
+ pSMB->t2.DataOffset = 0;
+ pSMB->t2.SetupCount = 1;
+ pSMB->t2.Reserved3 = 0;
+ pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->t2.TotalParameterCount = cpu_to_le16(params);
+ pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
+ pSMB->Pad = 0;
+ pSMB->Fid = netfid;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->t2.ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc) /* BB add auto retry on EOPNOTSUPP? */
+ rc = -EIO;
+ else if (get_bcc(&pSMBr->hdr) < 40)
+ rc = -EIO; /* bad smb */
+ else if (pFindData) {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ data_offset, sizeof(FILE_ALL_INFO));
+ } else
+ rc = -ENOMEM;
+ }
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto QFileInfoRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, FILE_ALL_INFO *data,
+ int legacy /* old style infolevel */,
+ const struct nls_table *nls_codepage, int remap)
+{
+ /* level 263 SMB_QUERY_FILE_ALL_INFO */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ __u16 params, byte_count;
+
+ /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
+QPathInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, search_name);
+ }
+
+ params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ if (legacy)
+ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
+ else
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc) /* BB add auto retry on EOPNOTSUPP? */
+ rc = -EIO;
+ else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
+ rc = -EIO; /* bad smb */
+ else if (legacy && get_bcc(&pSMBr->hdr) < 24)
+ rc = -EIO; /* 24 or 26 expected but we do not read
+ last field */
+ else if (data) {
+ int size;
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+
+ /*
+ * On legacy responses we do not read the last field,
+ * EAsize, fortunately since it varies by subdialect and
+ * also note it differs on Set vs Get, ie two bytes or 4
+ * bytes depending but we don't care here.
+ */
+ if (legacy)
+ size = sizeof(FILE_INFO_STANDARD);
+ else
+ size = sizeof(FILE_ALL_INFO);
+ memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
+ data_offset, size);
+ } else
+ rc = -ENOMEM;
+ }
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto QPathInfoRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
+{
+ struct smb_t2_qfi_req *pSMB = NULL;
+ struct smb_t2_qfi_rsp *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ __u16 params, byte_count;
+
+UnixQFileInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2 /* level */ + 2 /* fid */;
+ pSMB->t2.TotalDataCount = 0;
+ pSMB->t2.MaxParameterCount = cpu_to_le16(4);
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
+ pSMB->t2.MaxSetupCount = 0;
+ pSMB->t2.Reserved = 0;
+ pSMB->t2.Flags = 0;
+ pSMB->t2.Timeout = 0;
+ pSMB->t2.Reserved2 = 0;
+ pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
+ Fid) - 4);
+ pSMB->t2.DataCount = 0;
+ pSMB->t2.DataOffset = 0;
+ pSMB->t2.SetupCount = 1;
+ pSMB->t2.Reserved3 = 0;
+ pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->t2.TotalParameterCount = cpu_to_le16(params);
+ pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
+ pSMB->Pad = 0;
+ pSMB->Fid = netfid;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->t2.ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
+ cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
+ rc = -EIO; /* bad smb */
+ } else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ data_offset,
+ sizeof(FILE_UNIX_BASIC_INFO));
+ }
+ }
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto UnixQFileInfoRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *searchName,
+ FILE_UNIX_BASIC_INFO *pFindData,
+ const struct nls_table *nls_codepage, int remap)
+{
+/* SMB_QUERY_FILE_UNIX_BASIC */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned = 0;
+ int name_len;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
+UnixQPathInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, searchName);
+ }
+
+ params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
+ cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
+ rc = -EIO; /* bad smb */
+ } else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ memcpy((char *) pFindData,
+ (char *) &pSMBr->hdr.Protocol +
+ data_offset,
+ sizeof(FILE_UNIX_BASIC_INFO));
+ }
+ }
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto UnixQPathInfoRetry;
+
+ return rc;
+}
+
+/* xid, tcon, searchName and codepage are input parms, rest are returned */
+int
+CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *searchName, struct cifs_sb_info *cifs_sb,
+ __u16 *pnetfid, __u16 search_flags,
+ struct cifs_search_info *psrch_inf, bool msearch)
+{
+/* level 257 SMB_ */
+ TRANSACTION2_FFIRST_REQ *pSMB = NULL;
+ TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
+ T2_FFIRST_RSP_PARMS *parms;
+ int rc = 0;
+ int bytes_returned = 0;
+ int name_len, remap;
+ __u16 params, byte_count;
+ struct nls_table *nls_codepage;
+
+ cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
+
+findFirstRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ nls_codepage = cifs_sb->local_nls;
+ remap = cifs_remap(cifs_sb);
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+ PATH_MAX, nls_codepage, remap);
+ /* We can not add the asterik earlier in case
+ it got remapped to 0xF03A as if it were part of the
+ directory name instead of a wildcard */
+ name_len *= 2;
+ if (msearch) {
+ pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
+ pSMB->FileName[name_len+1] = 0;
+ pSMB->FileName[name_len+2] = '*';
+ pSMB->FileName[name_len+3] = 0;
+ name_len += 4; /* now the trailing null */
+ /* null terminate just in case */
+ pSMB->FileName[name_len] = 0;
+ pSMB->FileName[name_len+1] = 0;
+ name_len += 2;
+ }
+ } else {
+ name_len = copy_path_name(pSMB->FileName, searchName);
+ if (msearch) {
+ if (WARN_ON_ONCE(name_len > PATH_MAX-2))
+ name_len = PATH_MAX-2;
+ /* overwrite nul byte */
+ pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
+ pSMB->FileName[name_len] = '*';
+ pSMB->FileName[name_len+1] = 0;
+ name_len += 2;
+ }
+ }
+
+ params = 12 + name_len /* includes null */ ;
+ pSMB->TotalDataCount = 0; /* no EAs */
+ pSMB->MaxParameterCount = cpu_to_le16(10);
+ pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(
+ offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
+ - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
+ pSMB->SearchAttributes =
+ cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+ ATTR_DIRECTORY);
+ pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
+ pSMB->SearchFlags = cpu_to_le16(search_flags);
+ pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
+
+ /* BB what should we set StorageType to? Does it matter? BB */
+ pSMB->SearchStorageType = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
+
+ if (rc) {/* BB add logic to retry regular search if Unix search
+ rejected unexpectedly by server */
+ /* BB Add code to handle unsupported level rc */
+ cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
+
+ cifs_buf_release(pSMB);
+
+ /* BB eventually could optimize out free and realloc of buf */
+ /* for this case */
+ if (rc == -EAGAIN)
+ goto findFirstRetry;
+ } else { /* decode response */
+ /* BB remember to free buffer if error BB */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ if (rc == 0) {
+ unsigned int lnoff;
+
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ psrch_inf->unicode = true;
+ else
+ psrch_inf->unicode = false;
+
+ psrch_inf->ntwrk_buf_start = (char *)pSMBr;
+ psrch_inf->smallBuf = false;
+ psrch_inf->srch_entries_start =
+ (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.DataOffset);
+ parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.ParameterOffset));
+
+ if (parms->EndofSearch)
+ psrch_inf->endOfSearch = true;
+ else
+ psrch_inf->endOfSearch = false;
+
+ psrch_inf->entries_in_buffer =
+ le16_to_cpu(parms->SearchCount);
+ psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
+ psrch_inf->entries_in_buffer;
+ lnoff = le16_to_cpu(parms->LastNameOffset);
+ if (CIFSMaxBufSize < lnoff) {
+ cifs_dbg(VFS, "ignoring corrupt resume name\n");
+ psrch_inf->last_entry = NULL;
+ return rc;
+ }
+
+ psrch_inf->last_entry = psrch_inf->srch_entries_start +
+ lnoff;
+
+ if (pnetfid)
+ *pnetfid = parms->SearchHandle;
+ } else {
+ cifs_buf_release(pSMB);
+ }
+ }
+
+ return rc;
+}
+
+int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
+ __u16 searchHandle, __u16 search_flags,
+ struct cifs_search_info *psrch_inf)
+{
+ TRANSACTION2_FNEXT_REQ *pSMB = NULL;
+ TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
+ T2_FNEXT_RSP_PARMS *parms;
+ char *response_data;
+ int rc = 0;
+ int bytes_returned;
+ unsigned int name_len;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In FindNext\n");
+
+ if (psrch_inf->endOfSearch)
+ return -ENOENT;
+
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 14; /* includes 2 bytes of null string, converted to LE below*/
+ byte_count = 0;
+ pSMB->TotalDataCount = 0; /* no EAs */
+ pSMB->MaxParameterCount = cpu_to_le16(8);
+ pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(
+ offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
+ pSMB->SearchHandle = searchHandle; /* always kept as le */
+ pSMB->SearchCount =
+ cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
+ pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
+ pSMB->ResumeKey = psrch_inf->resume_key;
+ pSMB->SearchFlags = cpu_to_le16(search_flags);
+
+ name_len = psrch_inf->resume_name_len;
+ params += name_len;
+ if (name_len < PATH_MAX) {
+ memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
+ byte_count += name_len;
+ /* 14 byte parm len above enough for 2 byte null terminator */
+ pSMB->ResumeFileName[name_len] = 0;
+ pSMB->ResumeFileName[name_len+1] = 0;
+ } else {
+ rc = -EINVAL;
+ goto FNext2_err_exit;
+ }
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
+ if (rc) {
+ if (rc == -EBADF) {
+ psrch_inf->endOfSearch = true;
+ cifs_buf_release(pSMB);
+ rc = 0; /* search probably was closed at end of search*/
+ } else
+ cifs_dbg(FYI, "FindNext returned = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc == 0) {
+ unsigned int lnoff;
+
+ /* BB fixme add lock for file (srch_info) struct here */
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ psrch_inf->unicode = true;
+ else
+ psrch_inf->unicode = false;
+ response_data = (char *) &pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.ParameterOffset);
+ parms = (T2_FNEXT_RSP_PARMS *)response_data;
+ response_data = (char *)&pSMBr->hdr.Protocol +
+ le16_to_cpu(pSMBr->t2.DataOffset);
+ if (psrch_inf->smallBuf)
+ cifs_small_buf_release(
+ psrch_inf->ntwrk_buf_start);
+ else
+ cifs_buf_release(psrch_inf->ntwrk_buf_start);
+ psrch_inf->srch_entries_start = response_data;
+ psrch_inf->ntwrk_buf_start = (char *)pSMB;
+ psrch_inf->smallBuf = false;
+ if (parms->EndofSearch)
+ psrch_inf->endOfSearch = true;
+ else
+ psrch_inf->endOfSearch = false;
+ psrch_inf->entries_in_buffer =
+ le16_to_cpu(parms->SearchCount);
+ psrch_inf->index_of_last_entry +=
+ psrch_inf->entries_in_buffer;
+ lnoff = le16_to_cpu(parms->LastNameOffset);
+ if (CIFSMaxBufSize < lnoff) {
+ cifs_dbg(VFS, "ignoring corrupt resume name\n");
+ psrch_inf->last_entry = NULL;
+ return rc;
+ } else
+ psrch_inf->last_entry =
+ psrch_inf->srch_entries_start + lnoff;
+
+/* cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
+ psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
+
+ /* BB fixme add unlock here */
+ }
+
+ }
+
+ /* BB On error, should we leave previous search buf (and count and
+ last entry fields) intact or free the previous one? */
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+FNext2_err_exit:
+ if (rc != 0)
+ cifs_buf_release(pSMB);
+ return rc;
+}
+
+int
+CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u16 searchHandle)
+{
+ int rc = 0;
+ FINDCLOSE_REQ *pSMB = NULL;
+
+ cifs_dbg(FYI, "In CIFSSMBFindClose\n");
+ rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
+
+ /* no sense returning error if session restarted
+ as file handle has been closed */
+ if (rc == -EAGAIN)
+ return 0;
+ if (rc)
+ return rc;
+
+ pSMB->FileID = searchHandle;
+ pSMB->ByteCount = 0;
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
+ cifs_small_buf_release(pSMB);
+ if (rc)
+ cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
+
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
+
+ /* Since session is dead, search handle closed on server already */
+ if (rc == -EAGAIN)
+ rc = 0;
+
+ return rc;
+}
+
+int
+CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, __u64 *inode_number,
+ const struct nls_table *nls_codepage, int remap)
+{
+ int rc = 0;
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int name_len, bytes_returned;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
+ if (tcon == NULL)
+ return -ENODEV;
+
+GetInodeNumberRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName,
+ search_name, PATH_MAX, nls_codepage,
+ remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, search_name);
+ }
+
+ params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
+ } else {
+ /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ /* BB also check enough total bytes returned */
+ if (rc || get_bcc(&pSMBr->hdr) < 2)
+ /* If rc should we check for EOPNOSUPP and
+ disable the srvino flag? or in caller? */
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+ struct file_internal_info *pfinfo;
+ /* BB Do we need a cast or hash here ? */
+ if (count < 8) {
+ cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
+ rc = -EIO;
+ goto GetInodeNumOut;
+ }
+ pfinfo = (struct file_internal_info *)
+ (data_offset + (char *) &pSMBr->hdr.Protocol);
+ *inode_number = le64_to_cpu(pfinfo->UniqueId);
+ }
+ }
+GetInodeNumOut:
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto GetInodeNumberRetry;
+ return rc;
+}
+
+int
+CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
+ const char *search_name, struct dfs_info3_param **target_nodes,
+ unsigned int *num_of_nodes,
+ const struct nls_table *nls_codepage, int remap)
+{
+/* TRANS2_GET_DFS_REFERRAL */
+ TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
+ TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+ __u16 params, byte_count;
+ *num_of_nodes = 0;
+ *target_nodes = NULL;
+
+ cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
+ if (ses == NULL || ses->tcon_ipc == NULL)
+ return -ENODEV;
+
+getDFSRetry:
+ /*
+ * Use smb_init_no_reconnect() instead of smb_init() as
+ * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
+ * causing an infinite recursion.
+ */
+ rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
+ (void **)&pSMB, (void **)&pSMBr);
+ if (rc)
+ return rc;
+
+ /* server pointer checked in called function,
+ but should never be null here anyway */
+ pSMB->hdr.Mid = get_next_mid(ses->server);
+ pSMB->hdr.Tid = ses->tcon_ipc->tid;
+ pSMB->hdr.Uid = ses->Suid;
+ if (ses->capabilities & CAP_STATUS32)
+ pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
+ if (ses->capabilities & CAP_DFS)
+ pSMB->hdr.Flags2 |= SMBFLG2_DFS;
+
+ if (ses->capabilities & CAP_UNICODE) {
+ pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
+ search_name, PATH_MAX, nls_codepage,
+ remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = copy_path_name(pSMB->RequestFileName, search_name);
+ }
+
+ if (ses->server->sign)
+ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ pSMB->hdr.Uid = ses->Suid;
+
+ params = 2 /* level */ + name_len /*includes null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->MaxParameterCount = 0;
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
+ byte_count = params + 3 /* pad */ ;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->MaxReferralLevel = cpu_to_le16(3);
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
+ goto GetDFSRefExit;
+ }
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ /* BB Also check if enough total bytes returned? */
+ if (rc || get_bcc(&pSMBr->hdr) < 17) {
+ rc = -EIO; /* bad smb */
+ goto GetDFSRefExit;
+ }
+
+ cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
+ get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
+
+ /* parse returned result into more usable form */
+ rc = parse_dfs_referrals(&pSMBr->dfs_data,
+ le16_to_cpu(pSMBr->t2.DataCount),
+ num_of_nodes, target_nodes, nls_codepage,
+ remap, search_name,
+ (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
+
+GetDFSRefExit:
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto getDFSRetry;
+
+ return rc;
+}
+
+/* Query File System Info such as free space to old servers such as Win 9x */
+int
+SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ struct kstatfs *FSData)
+{
+/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_ALLOC_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "OldQFSInfo\n");
+oldQFSInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) < 18)
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
+ get_bcc(&pSMBr->hdr), data_offset);
+
+ response_data = (FILE_SYSTEM_ALLOC_INFO *)
+ (((char *) &pSMBr->hdr.Protocol) + data_offset);
+ FSData->f_bsize =
+ le16_to_cpu(response_data->BytesPerSector) *
+ le32_to_cpu(response_data->
+ SectorsPerAllocationUnit);
+ /*
+ * much prefer larger but if server doesn't report
+ * a valid size than 4K is a reasonable minimum
+ */
+ if (FSData->f_bsize < 512)
+ FSData->f_bsize = 4096;
+
+ FSData->f_blocks =
+ le32_to_cpu(response_data->TotalAllocationUnits);
+ FSData->f_bfree = FSData->f_bavail =
+ le32_to_cpu(response_data->FreeAllocationUnits);
+ cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
+ (unsigned long long)FSData->f_blocks,
+ (unsigned long long)FSData->f_bfree,
+ FSData->f_bsize);
+ }
+ }
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto oldQFSInfoRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ struct kstatfs *FSData)
+{
+/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In QFSInfo\n");
+QFSInfoRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) < 24)
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+
+ response_data =
+ (FILE_SYSTEM_INFO
+ *) (((char *) &pSMBr->hdr.Protocol) +
+ data_offset);
+ FSData->f_bsize =
+ le32_to_cpu(response_data->BytesPerSector) *
+ le32_to_cpu(response_data->
+ SectorsPerAllocationUnit);
+ /*
+ * much prefer larger but if server doesn't report
+ * a valid size than 4K is a reasonable minimum
+ */
+ if (FSData->f_bsize < 512)
+ FSData->f_bsize = 4096;
+
+ FSData->f_blocks =
+ le64_to_cpu(response_data->TotalAllocationUnits);
+ FSData->f_bfree = FSData->f_bavail =
+ le64_to_cpu(response_data->FreeAllocationUnits);
+ cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
+ (unsigned long long)FSData->f_blocks,
+ (unsigned long long)FSData->f_bfree,
+ FSData->f_bsize);
+ }
+ }
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSInfoRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
+{
+/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In QFSAttributeInfo\n");
+QFSAttributeRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) < 13) {
+ /* BB also check if enough bytes returned */
+ rc = -EIO; /* bad smb */
+ } else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ response_data =
+ (FILE_SYSTEM_ATTRIBUTE_INFO
+ *) (((char *) &pSMBr->hdr.Protocol) +
+ data_offset);
+ memcpy(&tcon->fsAttrInfo, response_data,
+ sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
+ }
+ }
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSAttributeRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
+{
+/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_DEVICE_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In QFSDeviceInfo\n");
+QFSDeviceRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) <
+ sizeof(FILE_SYSTEM_DEVICE_INFO))
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ response_data =
+ (FILE_SYSTEM_DEVICE_INFO *)
+ (((char *) &pSMBr->hdr.Protocol) +
+ data_offset);
+ memcpy(&tcon->fsDevInfo, response_data,
+ sizeof(FILE_SYSTEM_DEVICE_INFO));
+ }
+ }
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSDeviceRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
+{
+/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_UNIX_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In QFSUnixInfo\n");
+QFSUnixRetry:
+ rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
+ (void **) &pSMB, (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(100);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ byte_count = params + 1 /* pad */ ;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
+ smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) < 13) {
+ rc = -EIO; /* bad smb */
+ } else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ response_data =
+ (FILE_SYSTEM_UNIX_INFO
+ *) (((char *) &pSMBr->hdr.Protocol) +
+ data_offset);
+ memcpy(&tcon->fsUnixInfo, response_data,
+ sizeof(FILE_SYSTEM_UNIX_INFO));
+ }
+ }
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSUnixRetry;
+
+
+ return rc;
+}
+
+int
+CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
+{
+/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
+ TRANSACTION2_SETFSI_REQ *pSMB = NULL;
+ TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, param_offset, offset, byte_count;
+
+ cifs_dbg(FYI, "In SETFSUnixInfo\n");
+SETFSUnixRetry:
+ /* BB switch to small buf init to save memory */
+ rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
+ (void **) &pSMB, (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 4; /* 2 bytes zero followed by info level. */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
+ - 4;
+ offset = param_offset + params;
+
+ pSMB->MaxParameterCount = cpu_to_le16(4);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(100);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
+ byte_count = 1 /* pad */ + params + 12;
+
+ pSMB->DataCount = cpu_to_le16(12);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+
+ /* Params. */
+ pSMB->FileNum = 0;
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
+
+ /* Data. */
+ pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
+ pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
+ pSMB->ClientUnixCap = cpu_to_le64(cap);
+
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ if (rc)
+ rc = -EIO; /* bad smb */
+ }
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SETFSUnixRetry;
+
+ return rc;
+}
+
+
+
+int
+CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ struct kstatfs *FSData)
+{
+/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_POSIX_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, byte_count;
+
+ cifs_dbg(FYI, "In QFSPosixInfo\n");
+QFSPosixRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(100);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ byte_count = params + 1 /* pad */ ;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
+ smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || get_bcc(&pSMBr->hdr) < 13) {
+ rc = -EIO; /* bad smb */
+ } else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ response_data =
+ (FILE_SYSTEM_POSIX_INFO
+ *) (((char *) &pSMBr->hdr.Protocol) +
+ data_offset);
+ FSData->f_bsize =
+ le32_to_cpu(response_data->BlockSize);
+ /*
+ * much prefer larger but if server doesn't report
+ * a valid size than 4K is a reasonable minimum
+ */
+ if (FSData->f_bsize < 512)
+ FSData->f_bsize = 4096;
+
+ FSData->f_blocks =
+ le64_to_cpu(response_data->TotalBlocks);
+ FSData->f_bfree =
+ le64_to_cpu(response_data->BlocksAvail);
+ if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
+ FSData->f_bavail = FSData->f_bfree;
+ } else {
+ FSData->f_bavail =
+ le64_to_cpu(response_data->UserBlocksAvail);
+ }
+ if (response_data->TotalFileNodes != cpu_to_le64(-1))
+ FSData->f_files =
+ le64_to_cpu(response_data->TotalFileNodes);
+ if (response_data->FreeFileNodes != cpu_to_le64(-1))
+ FSData->f_ffree =
+ le64_to_cpu(response_data->FreeFileNodes);
+ }
+ }
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSPosixRetry;
+
+ return rc;
+}
+
+
+/*
+ * We can not use write of zero bytes trick to set file size due to need for
+ * large file support. Also note that this SetPathInfo is preferred to
+ * SetFileInfo based method in next routine which is only needed to work around
+ * a sharing violation bugin Samba which this routine can run into.
+ */
+int
+CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
+ bool set_allocation)
+{
+ struct smb_com_transaction2_spi_req *pSMB = NULL;
+ struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+ struct file_end_of_file_info *parm_data;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ int remap = cifs_remap(cifs_sb);
+
+ __u16 params, byte_count, data_count, param_offset, offset;
+
+ cifs_dbg(FYI, "In SetEOF\n");
+SetEOFRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
+ PATH_MAX, cifs_sb->local_nls, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, file_name);
+ }
+ params = 6 + name_len;
+ data_count = sizeof(struct file_end_of_file_info);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(4100);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+ if (set_allocation) {
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
+ else
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
+ } else /* Set File Size */ {
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
+ else
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
+ }
+
+ parm_data =
+ (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
+ offset);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + data_count;
+ pSMB->DataCount = cpu_to_le16(data_count);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ parm_data->FileSize = cpu_to_le64(size);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc)
+ cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
+
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetEOFRetry;
+
+ return rc;
+}
+
+int
+CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
+{
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ struct file_end_of_file_info *parm_data;
+ int rc = 0;
+ __u16 params, param_offset, offset, byte_count, count;
+
+ cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
+ (long long)size);
+ rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
+ pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
+
+ params = 6;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+ offset = param_offset + params;
+
+ count = sizeof(struct file_end_of_file_info);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
+ parm_data =
+ (struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ parm_data->FileSize = cpu_to_le64(size);
+ pSMB->Fid = cfile->fid.netfid;
+ if (set_allocation) {
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
+ else
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
+ } else /* Set File Size */ {
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
+ else
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
+ }
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
+ cifs_small_buf_release(pSMB);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
+ rc);
+ }
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+/* Some legacy servers such as NT4 require that the file times be set on
+ an open handle, rather than by pathname - this is awkward due to
+ potential access conflicts on the open, but it is unavoidable for these
+ old servers since the only other choice is to go from 100 nanosecond DCE
+ time and resort to the original setpathinfo level which takes the ancient
+ DOS time format with 2 second granularity */
+int
+CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
+{
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ char *data_offset;
+ int rc = 0;
+ __u16 params, param_offset, offset, byte_count, count;
+
+ cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
+ rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+ pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
+
+ params = 6;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+ offset = param_offset + params;
+
+ data_offset = (char *)pSMB +
+ offsetof(struct smb_hdr, Protocol) + offset;
+
+ count = sizeof(FILE_BASIC_INFO);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find max SMB PDU from sess */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->Fid = fid;
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
+ else
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
+ cifs_small_buf_release(pSMB);
+ if (rc)
+ cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
+ rc);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+int
+CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
+ bool delete_file, __u16 fid, __u32 pid_of_opener)
+{
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ char *data_offset;
+ int rc = 0;
+ __u16 params, param_offset, offset, byte_count, count;
+
+ cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
+ rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+ pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
+
+ params = 6;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+ offset = param_offset + params;
+
+ /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
+ data_offset = (char *)(pSMB) + offset + 4;
+
+ count = 1;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find max SMB PDU from sess */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->Fid = fid;
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ *data_offset = delete_file ? 1 : 0;
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
+ cifs_small_buf_release(pSMB);
+ if (rc)
+ cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
+
+ return rc;
+}
+
+static int
+CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fileName, const FILE_BASIC_INFO *data,
+ const struct nls_table *nls_codepage,
+ struct cifs_sb_info *cifs_sb)
+{
+ int oplock = 0;
+ struct cifs_open_parms oparms;
+ struct cifs_fid fid;
+ int rc;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = GENERIC_WRITE,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .disposition = FILE_OPEN,
+ .path = fileName,
+ .fid = &fid,
+ };
+
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (rc)
+ goto out;
+
+ rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
+ CIFSSMBClose(xid, tcon, fid.netfid);
+out:
+
+ return rc;
+}
+
+int
+CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fileName, const FILE_BASIC_INFO *data,
+ const struct nls_table *nls_codepage,
+ struct cifs_sb_info *cifs_sb)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ char *data_offset;
+ __u16 params, param_offset, offset, byte_count, count;
+ int remap = cifs_remap(cifs_sb);
+
+ cifs_dbg(FYI, "In SetTimes\n");
+
+SetTimesRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fileName);
+ }
+
+ params = 6 + name_len;
+ count = sizeof(FILE_BASIC_INFO);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+ data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
+ else
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc)
+ cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
+
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetTimesRetry;
+
+ if (rc == -EOPNOTSUPP)
+ return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
+ nls_codepage, cifs_sb);
+
+ return rc;
+}
+
+static void
+cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
+ const struct cifs_unix_set_info_args *args)
+{
+ u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
+ u64 mode = args->mode;
+
+ if (uid_valid(args->uid))
+ uid = from_kuid(&init_user_ns, args->uid);
+ if (gid_valid(args->gid))
+ gid = from_kgid(&init_user_ns, args->gid);
+
+ /*
+ * Samba server ignores set of file size to zero due to bugs in some
+ * older clients, but we should be precise - we use SetFileSize to
+ * set file size and do not want to truncate file size to zero
+ * accidentally as happened on one Samba server beta by putting
+ * zero instead of -1 here
+ */
+ data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
+ data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
+ data_offset->LastStatusChange = cpu_to_le64(args->ctime);
+ data_offset->LastAccessTime = cpu_to_le64(args->atime);
+ data_offset->LastModificationTime = cpu_to_le64(args->mtime);
+ data_offset->Uid = cpu_to_le64(uid);
+ data_offset->Gid = cpu_to_le64(gid);
+ /* better to leave device as zero when it is */
+ data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
+ data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
+ data_offset->Permissions = cpu_to_le64(mode);
+
+ if (S_ISREG(mode))
+ data_offset->Type = cpu_to_le32(UNIX_FILE);
+ else if (S_ISDIR(mode))
+ data_offset->Type = cpu_to_le32(UNIX_DIR);
+ else if (S_ISLNK(mode))
+ data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
+ else if (S_ISCHR(mode))
+ data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
+ else if (S_ISBLK(mode))
+ data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
+ else if (S_ISFIFO(mode))
+ data_offset->Type = cpu_to_le32(UNIX_FIFO);
+ else if (S_ISSOCK(mode))
+ data_offset->Type = cpu_to_le32(UNIX_SOCKET);
+}
+
+int
+CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const struct cifs_unix_set_info_args *args,
+ u16 fid, u32 pid_of_opener)
+{
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ char *data_offset;
+ int rc = 0;
+ u16 params, param_offset, offset, byte_count, count;
+
+ cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
+ rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+ if (rc)
+ return rc;
+
+ pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+ pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
+
+ params = 6;
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+ offset = param_offset + params;
+
+ data_offset = (char *)pSMB +
+ offsetof(struct smb_hdr, Protocol) + offset;
+
+ count = sizeof(FILE_UNIX_BASIC_INFO);
+
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find max SMB PDU from sess */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->Fid = fid;
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
+
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
+ cifs_small_buf_release(pSMB);
+ if (rc)
+ cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
+ rc);
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
+
+ return rc;
+}
+
+int
+CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *file_name,
+ const struct cifs_unix_set_info_args *args,
+ const struct nls_table *nls_codepage, int remap)
+{
+ TRANSACTION2_SPI_REQ *pSMB = NULL;
+ TRANSACTION2_SPI_RSP *pSMBr = NULL;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ FILE_UNIX_BASIC_INFO *data_offset;
+ __u16 params, param_offset, offset, count, byte_count;
+
+ cifs_dbg(FYI, "In SetUID/GID/Mode\n");
+setPermsRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, file_name);
+ }
+
+ params = 6 + name_len;
+ count = sizeof(FILE_UNIX_BASIC_INFO);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+ /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
+ data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);
+ memset(data_offset, 0, count);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->DataCount = cpu_to_le16(count);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+
+ cifs_fill_unix_set_info(data_offset, args);
+
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc)
+ cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
+
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto setPermsRetry;
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_XATTR
+/*
+ * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
+ * function used by listxattr and getxattr type calls. When ea_name is set,
+ * it looks for that attribute name and stuffs that value into the EAData
+ * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
+ * buffer. In both cases, the return value is either the length of the
+ * resulting data or a negative error code. If EAData is a NULL pointer then
+ * the data isn't copied to it, but the length is returned.
+ */
+ssize_t
+CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *searchName, const unsigned char *ea_name,
+ char *EAData, size_t buf_size,
+ struct cifs_sb_info *cifs_sb)
+{
+ /* BB assumes one setup word */
+ TRANSACTION2_QPI_REQ *pSMB = NULL;
+ TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int remap = cifs_remap(cifs_sb);
+ struct nls_table *nls_codepage = cifs_sb->local_nls;
+ int rc = 0;
+ int bytes_returned;
+ int list_len;
+ struct fealist *ea_response_data;
+ struct fea *temp_fea;
+ char *temp_ptr;
+ char *end_of_smb;
+ __u16 params, byte_count, data_offset;
+ unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
+
+ cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
+QAllEAsRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ list_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+ PATH_MAX, nls_codepage, remap);
+ list_len++; /* trailing null */
+ list_len *= 2;
+ } else {
+ list_len = copy_path_name(pSMB->FileName, searchName);
+ }
+
+ params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
+ goto QAllEAsOut;
+ }
+
+
+ /* BB also check enough total bytes returned */
+ /* BB we need to improve the validity checking
+ of these trans2 responses */
+
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ if (rc || get_bcc(&pSMBr->hdr) < 4) {
+ rc = -EIO; /* bad smb */
+ goto QAllEAsOut;
+ }
+
+ /* check that length of list is not more than bcc */
+ /* check that each entry does not go beyond length
+ of list */
+ /* check that each element of each entry does not
+ go beyond end of list */
+ /* validate_trans2_offsets() */
+ /* BB check if start of smb + data_offset > &bcc+ bcc */
+
+ data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ ea_response_data = (struct fealist *)
+ (((char *) &pSMBr->hdr.Protocol) + data_offset);
+
+ list_len = le32_to_cpu(ea_response_data->list_len);
+ cifs_dbg(FYI, "ea length %d\n", list_len);
+ if (list_len <= 8) {
+ cifs_dbg(FYI, "empty EA list returned from server\n");
+ /* didn't find the named attribute */
+ if (ea_name)
+ rc = -ENODATA;
+ goto QAllEAsOut;
+ }
+
+ /* make sure list_len doesn't go past end of SMB */
+ end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
+ if ((char *)ea_response_data + list_len > end_of_smb) {
+ cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
+ rc = -EIO;
+ goto QAllEAsOut;
+ }
+
+ /* account for ea list len */
+ list_len -= 4;
+ temp_fea = ea_response_data->list;
+ temp_ptr = (char *)temp_fea;
+ while (list_len > 0) {
+ unsigned int name_len;
+ __u16 value_len;
+
+ list_len -= 4;
+ temp_ptr += 4;
+ /* make sure we can read name_len and value_len */
+ if (list_len < 0) {
+ cifs_dbg(FYI, "EA entry goes beyond length of list\n");
+ rc = -EIO;
+ goto QAllEAsOut;
+ }
+
+ name_len = temp_fea->name_len;
+ value_len = le16_to_cpu(temp_fea->value_len);
+ list_len -= name_len + 1 + value_len;
+ if (list_len < 0) {
+ cifs_dbg(FYI, "EA entry goes beyond length of list\n");
+ rc = -EIO;
+ goto QAllEAsOut;
+ }
+
+ if (ea_name) {
+ if (ea_name_len == name_len &&
+ memcmp(ea_name, temp_ptr, name_len) == 0) {
+ temp_ptr += name_len + 1;
+ rc = value_len;
+ if (buf_size == 0)
+ goto QAllEAsOut;
+ if ((size_t)value_len > buf_size) {
+ rc = -ERANGE;
+ goto QAllEAsOut;
+ }
+ memcpy(EAData, temp_ptr, value_len);
+ goto QAllEAsOut;
+ }
+ } else {
+ /* account for prefix user. and trailing null */
+ rc += (5 + 1 + name_len);
+ if (rc < (int) buf_size) {
+ memcpy(EAData, "user.", 5);
+ EAData += 5;
+ memcpy(EAData, temp_ptr, name_len);
+ EAData += name_len;
+ /* null terminate name */
+ *EAData = 0;
+ ++EAData;
+ } else if (buf_size == 0) {
+ /* skip copy - calc size only */
+ } else {
+ /* stop before overrun buffer */
+ rc = -ERANGE;
+ break;
+ }
+ }
+ temp_ptr += name_len + 1 + value_len;
+ temp_fea = (struct fea *)temp_ptr;
+ }
+
+ /* didn't find the named attribute */
+ if (ea_name)
+ rc = -ENODATA;
+
+QAllEAsOut:
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
+ goto QAllEAsRetry;
+
+ return (ssize_t)rc;
+}
+
+int
+CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *fileName, const char *ea_name, const void *ea_value,
+ const __u16 ea_value_len, const struct nls_table *nls_codepage,
+ struct cifs_sb_info *cifs_sb)
+{
+ struct smb_com_transaction2_spi_req *pSMB = NULL;
+ struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+ struct fealist *parm_data;
+ int name_len;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, param_offset, byte_count, offset, count;
+ int remap = cifs_remap(cifs_sb);
+
+ cifs_dbg(FYI, "In SetEA\n");
+SetEARetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+ PATH_MAX, nls_codepage, remap);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else {
+ name_len = copy_path_name(pSMB->FileName, fileName);
+ }
+
+ params = 6 + name_len;
+
+ /* done calculating parms using name_len of file name,
+ now use name_len to calculate length of ea name
+ we are going to create in the inode xattrs */
+ if (ea_name == NULL)
+ name_len = 0;
+ else
+ name_len = strnlen(ea_name, 255);
+
+ count = sizeof(*parm_data) + ea_value_len + name_len;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find max SMB PDU from sess */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ param_offset = offsetof(struct smb_com_transaction2_spi_req,
+ InformationLevel) - 4;
+ offset = param_offset + params;
+ pSMB->InformationLevel =
+ cpu_to_le16(SMB_SET_FILE_EA);
+
+ parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ byte_count = 3 /* pad */ + params + count;
+ pSMB->DataCount = cpu_to_le16(count);
+ parm_data->list_len = cpu_to_le32(count);
+ parm_data->list[0].EA_flags = 0;
+ /* we checked above that name len is less than 255 */
+ parm_data->list[0].name_len = (__u8)name_len;
+ /* EA names are always ASCII */
+ if (ea_name)
+ strncpy(parm_data->list[0].name, ea_name, name_len);
+ parm_data->list[0].name[name_len] = 0;
+ parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
+ /* caller ensures that ea_value_len is less than 64K but
+ we need to ensure that it fits within the smb */
+
+ /*BB add length check to see if it would fit in
+ negotiated SMB buffer size BB */
+ /* if (ea_value_len > buffer_size - 512 (enough for header)) */
+ if (ea_value_len)
+ memcpy(parm_data->list[0].name+name_len+1,
+ ea_value, ea_value_len);
+
+ pSMB->TotalDataCount = pSMB->DataCount;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->Reserved4 = 0;
+ inc_rfc1001_len(pSMB, byte_count);
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc)
+ cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
+
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetEARetry;
+
+ return rc;
+}
+#endif
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
new file mode 100644
index 000000000000..935fe198a4ba
--- /dev/null
+++ b/fs/smb/client/connect.c
@@ -0,0 +1,4754 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2011
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+#include <linux/fs.h>
+#include <linux/net.h>
+#include <linux/string.h>
+#include <linux/sched/mm.h>
+#include <linux/sched/signal.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/ctype.h>
+#include <linux/utsname.h>
+#include <linux/mempool.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/kthread.h>
+#include <linux/pagevec.h>
+#include <linux/freezer.h>
+#include <linux/namei.h>
+#include <linux/uuid.h>
+#include <linux/uaccess.h>
+#include <asm/processor.h>
+#include <linux/inet.h>
+#include <linux/module.h>
+#include <keys/user-type.h>
+#include <net/ipv6.h>
+#include <linux/parser.h>
+#include <linux/bvec.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "ntlmssp.h"
+#include "nterr.h"
+#include "rfc1002pdu.h"
+#include "fscache.h"
+#include "smb2proto.h"
+#include "smbdirect.h"
+#include "dns_resolve.h"
+#ifdef CONFIG_CIFS_DFS_UPCALL
+#include "dfs_cache.h"
+#endif
+#include "fs_context.h"
+#include "cifs_swn.h"
+
+extern mempool_t *cifs_req_poolp;
+extern bool disable_legacy_dialects;
+
+/* FIXME: should these be tunable? */
+#define TLINK_ERROR_EXPIRE (1 * HZ)
+#define TLINK_IDLE_EXPIRE (600 * HZ)
+
+/* Drop the connection to not overload the server */
+#define NUM_STATUS_IO_TIMEOUT 5
+
+struct mount_ctx {
+ struct cifs_sb_info *cifs_sb;
+ struct smb3_fs_context *fs_ctx;
+ unsigned int xid;
+ struct TCP_Server_Info *server;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ struct cifs_ses *root_ses;
+ uuid_t mount_id;
+ char *origin_fullpath, *leaf_fullpath;
+#endif
+};
+
+static int ip_connect(struct TCP_Server_Info *server);
+static int generic_ip_connect(struct TCP_Server_Info *server);
+static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
+static void cifs_prune_tlinks(struct work_struct *work);
+
+/*
+ * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
+ * get their ip addresses changed at some point.
+ *
+ * This should be called with server->srv_mutex held.
+ */
+static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
+{
+ int rc;
+ int len;
+ char *unc, *ipaddr = NULL;
+ time64_t expiry, now;
+ unsigned long ttl = SMB_DNS_RESOLVE_INTERVAL_DEFAULT;
+
+ if (!server->hostname)
+ return -EINVAL;
+
+ /* if server hostname isn't populated, there's nothing to do here */
+ if (server->hostname[0] == '\0')
+ return 0;
+
+ len = strlen(server->hostname) + 3;
+
+ unc = kmalloc(len, GFP_KERNEL);
+ if (!unc) {
+ cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
+ return -ENOMEM;
+ }
+ scnprintf(unc, len, "\\\\%s", server->hostname);
+
+ rc = dns_resolve_server_name_to_ip(unc, &ipaddr, &expiry);
+ kfree(unc);
+
+ if (rc < 0) {
+ cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
+ __func__, server->hostname, rc);
+ goto requeue_resolve;
+ }
+
+ spin_lock(&server->srv_lock);
+ rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
+ strlen(ipaddr));
+ spin_unlock(&server->srv_lock);
+ kfree(ipaddr);
+
+ /* rc == 1 means success here */
+ if (rc) {
+ now = ktime_get_real_seconds();
+ if (expiry && expiry > now)
+ /*
+ * To make sure we don't use the cached entry, retry 1s
+ * after expiry.
+ */
+ ttl = max_t(unsigned long, expiry - now, SMB_DNS_RESOLVE_INTERVAL_MIN) + 1;
+ }
+ rc = !rc ? -1 : 0;
+
+requeue_resolve:
+ cifs_dbg(FYI, "%s: next dns resolution scheduled for %lu seconds in the future\n",
+ __func__, ttl);
+ mod_delayed_work(cifsiod_wq, &server->resolve, (ttl * HZ));
+
+ return rc;
+}
+
+static void smb2_query_server_interfaces(struct work_struct *work)
+{
+ int rc;
+ struct cifs_tcon *tcon = container_of(work,
+ struct cifs_tcon,
+ query_interfaces.work);
+
+ /*
+ * query server network interfaces, in case they change
+ */
+ rc = SMB3_request_interfaces(0, tcon, false);
+ if (rc) {
+ cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
+ __func__, rc);
+ }
+
+ queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
+ (SMB_INTERFACE_POLL_INTERVAL * HZ));
+}
+
+static void cifs_resolve_server(struct work_struct *work)
+{
+ int rc;
+ struct TCP_Server_Info *server = container_of(work,
+ struct TCP_Server_Info, resolve.work);
+
+ cifs_server_lock(server);
+
+ /*
+ * Resolve the hostname again to make sure that IP address is up-to-date.
+ */
+ rc = reconn_set_ipaddr_from_hostname(server);
+ if (rc) {
+ cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
+ __func__, rc);
+ }
+
+ cifs_server_unlock(server);
+}
+
+/*
+ * Update the tcpStatus for the server.
+ * This is used to signal the cifsd thread to call cifs_reconnect
+ * ONLY cifsd thread should call cifs_reconnect. For any other
+ * thread, use this function
+ *
+ * @server: the tcp ses for which reconnect is needed
+ * @all_channels: if this needs to be done for all channels
+ */
+void
+cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
+ bool all_channels)
+{
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses;
+ int i;
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+ spin_lock(&pserver->srv_lock);
+ if (!all_channels) {
+ pserver->tcpStatus = CifsNeedReconnect;
+ spin_unlock(&pserver->srv_lock);
+ return;
+ }
+ spin_unlock(&pserver->srv_lock);
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+ spin_lock(&ses->chan_lock);
+ for (i = 0; i < ses->chan_count; i++) {
+ spin_lock(&ses->chans[i].server->srv_lock);
+ ses->chans[i].server->tcpStatus = CifsNeedReconnect;
+ spin_unlock(&ses->chans[i].server->srv_lock);
+ }
+ spin_unlock(&ses->chan_lock);
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+}
+
+/*
+ * Mark all sessions and tcons for reconnect.
+ * IMPORTANT: make sure that this gets called only from
+ * cifsd thread. For any other thread, use
+ * cifs_signal_cifsd_for_reconnect
+ *
+ * @server: the tcp ses for which reconnect is needed
+ * @server needs to be previously set to CifsNeedReconnect.
+ * @mark_smb_session: whether even sessions need to be marked
+ */
+void
+cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
+ bool mark_smb_session)
+{
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses, *nses;
+ struct cifs_tcon *tcon;
+
+ /*
+ * before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they
+ * are not used until reconnected.
+ */
+ cifs_dbg(FYI, "%s: marking necessary sessions and tcons for reconnect\n", __func__);
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) {
+ /* check if iface is still active */
+ if (!cifs_chan_is_iface_active(ses, server))
+ cifs_chan_update_iface(ses, server);
+
+ spin_lock(&ses->chan_lock);
+ if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) {
+ spin_unlock(&ses->chan_lock);
+ continue;
+ }
+
+ if (mark_smb_session)
+ CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses);
+ else
+ cifs_chan_set_need_reconnect(ses, server);
+
+ cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
+ __func__, ses->chans_need_reconnect);
+
+ /* If all channels need reconnect, then tcon needs reconnect */
+ if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
+ spin_unlock(&ses->chan_lock);
+ continue;
+ }
+ spin_unlock(&ses->chan_lock);
+
+ spin_lock(&ses->ses_lock);
+ ses->ses_status = SES_NEED_RECON;
+ spin_unlock(&ses->ses_lock);
+
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ tcon->need_reconnect = true;
+ spin_lock(&tcon->tc_lock);
+ tcon->status = TID_NEED_RECON;
+ spin_unlock(&tcon->tc_lock);
+ }
+ if (ses->tcon_ipc) {
+ ses->tcon_ipc->need_reconnect = true;
+ spin_lock(&ses->tcon_ipc->tc_lock);
+ ses->tcon_ipc->status = TID_NEED_RECON;
+ spin_unlock(&ses->tcon_ipc->tc_lock);
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+}
+
+static void
+cifs_abort_connection(struct TCP_Server_Info *server)
+{
+ struct mid_q_entry *mid, *nmid;
+ struct list_head retry_list;
+
+ server->maxBuf = 0;
+ server->max_read = 0;
+
+ /* do not want to be sending data on a socket we are freeing */
+ cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
+ cifs_server_lock(server);
+ if (server->ssocket) {
+ cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", server->ssocket->state,
+ server->ssocket->flags);
+ kernel_sock_shutdown(server->ssocket, SHUT_WR);
+ cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", server->ssocket->state,
+ server->ssocket->flags);
+ sock_release(server->ssocket);
+ server->ssocket = NULL;
+ }
+ server->sequence_number = 0;
+ server->session_estab = false;
+ kfree_sensitive(server->session_key.response);
+ server->session_key.response = NULL;
+ server->session_key.len = 0;
+ server->lstrp = jiffies;
+
+ /* mark submitted MIDs for retry and issue callback */
+ INIT_LIST_HEAD(&retry_list);
+ cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
+ spin_lock(&server->mid_lock);
+ list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) {
+ kref_get(&mid->refcount);
+ if (mid->mid_state == MID_REQUEST_SUBMITTED)
+ mid->mid_state = MID_RETRY_NEEDED;
+ list_move(&mid->qhead, &retry_list);
+ mid->mid_flags |= MID_DELETED;
+ }
+ spin_unlock(&server->mid_lock);
+ cifs_server_unlock(server);
+
+ cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
+ list_for_each_entry_safe(mid, nmid, &retry_list, qhead) {
+ list_del_init(&mid->qhead);
+ mid->callback(mid);
+ release_mid(mid);
+ }
+
+ if (cifs_rdma_enabled(server)) {
+ cifs_server_lock(server);
+ smbd_destroy(server);
+ cifs_server_unlock(server);
+ }
+}
+
+static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num_targets)
+{
+ spin_lock(&server->srv_lock);
+ server->nr_targets = num_targets;
+ if (server->tcpStatus == CifsExiting) {
+ /* the demux thread will exit normally next time through the loop */
+ spin_unlock(&server->srv_lock);
+ wake_up(&server->response_q);
+ return false;
+ }
+
+ cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
+ trace_smb3_reconnect(server->CurrentMid, server->conn_id,
+ server->hostname);
+ server->tcpStatus = CifsNeedReconnect;
+
+ spin_unlock(&server->srv_lock);
+ return true;
+}
+
+/*
+ * cifs tcp session reconnection
+ *
+ * mark tcp session as reconnecting so temporarily locked
+ * mark all smb sessions as reconnecting for tcp session
+ * reconnect tcp session
+ * wake up waiters on reconnection? - (not needed currently)
+ *
+ * if mark_smb_session is passed as true, unconditionally mark
+ * the smb session (and tcon) for reconnect as well. This value
+ * doesn't really matter for non-multichannel scenario.
+ *
+ */
+static int __cifs_reconnect(struct TCP_Server_Info *server,
+ bool mark_smb_session)
+{
+ int rc = 0;
+
+ if (!cifs_tcp_ses_needs_reconnect(server, 1))
+ return 0;
+
+ cifs_mark_tcp_ses_conns_for_reconnect(server, mark_smb_session);
+
+ cifs_abort_connection(server);
+
+ do {
+ try_to_freeze();
+ cifs_server_lock(server);
+
+ if (!cifs_swn_set_server_dstaddr(server)) {
+ /* resolve the hostname again to make sure that IP address is up-to-date */
+ rc = reconn_set_ipaddr_from_hostname(server);
+ cifs_dbg(FYI, "%s: reconn_set_ipaddr_from_hostname: rc=%d\n", __func__, rc);
+ }
+
+ if (cifs_rdma_enabled(server))
+ rc = smbd_reconnect(server);
+ else
+ rc = generic_ip_connect(server);
+ if (rc) {
+ cifs_server_unlock(server);
+ cifs_dbg(FYI, "%s: reconnect error %d\n", __func__, rc);
+ msleep(3000);
+ } else {
+ atomic_inc(&tcpSesReconnectCount);
+ set_credits(server, 1);
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus != CifsExiting)
+ server->tcpStatus = CifsNeedNegotiate;
+ spin_unlock(&server->srv_lock);
+ cifs_swn_reset_server_dstaddr(server);
+ cifs_server_unlock(server);
+ mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
+ }
+ } while (server->tcpStatus == CifsNeedReconnect);
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsNeedNegotiate)
+ mod_delayed_work(cifsiod_wq, &server->echo, 0);
+ spin_unlock(&server->srv_lock);
+
+ wake_up(&server->response_q);
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+static int __reconnect_target_unlocked(struct TCP_Server_Info *server, const char *target)
+{
+ int rc;
+ char *hostname;
+
+ if (!cifs_swn_set_server_dstaddr(server)) {
+ if (server->hostname != target) {
+ hostname = extract_hostname(target);
+ if (!IS_ERR(hostname)) {
+ spin_lock(&server->srv_lock);
+ kfree(server->hostname);
+ server->hostname = hostname;
+ spin_unlock(&server->srv_lock);
+ } else {
+ cifs_dbg(FYI, "%s: couldn't extract hostname or address from dfs target: %ld\n",
+ __func__, PTR_ERR(hostname));
+ cifs_dbg(FYI, "%s: default to last target server: %s\n", __func__,
+ server->hostname);
+ }
+ }
+ /* resolve the hostname again to make sure that IP address is up-to-date. */
+ rc = reconn_set_ipaddr_from_hostname(server);
+ cifs_dbg(FYI, "%s: reconn_set_ipaddr_from_hostname: rc=%d\n", __func__, rc);
+ }
+ /* Reconnect the socket */
+ if (cifs_rdma_enabled(server))
+ rc = smbd_reconnect(server);
+ else
+ rc = generic_ip_connect(server);
+
+ return rc;
+}
+
+static int reconnect_target_unlocked(struct TCP_Server_Info *server, struct dfs_cache_tgt_list *tl,
+ struct dfs_cache_tgt_iterator **target_hint)
+{
+ int rc;
+ struct dfs_cache_tgt_iterator *tit;
+
+ *target_hint = NULL;
+
+ /* If dfs target list is empty, then reconnect to last server */
+ tit = dfs_cache_get_tgt_iterator(tl);
+ if (!tit)
+ return __reconnect_target_unlocked(server, server->hostname);
+
+ /* Otherwise, try every dfs target in @tl */
+ for (; tit; tit = dfs_cache_get_next_tgt(tl, tit)) {
+ rc = __reconnect_target_unlocked(server, dfs_cache_get_tgt_name(tit));
+ if (!rc) {
+ *target_hint = tit;
+ break;
+ }
+ }
+ return rc;
+}
+
+static int reconnect_dfs_server(struct TCP_Server_Info *server)
+{
+ int rc = 0;
+ const char *refpath = server->current_fullpath + 1;
+ struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
+ struct dfs_cache_tgt_iterator *target_hint = NULL;
+ int num_targets = 0;
+
+ /*
+ * Determine the number of dfs targets the referral path in @cifs_sb resolves to.
+ *
+ * smb2_reconnect() needs to know how long it should wait based upon the number of dfs
+ * targets (server->nr_targets). It's also possible that the cached referral was cleared
+ * through /proc/fs/cifs/dfscache or the target list is empty due to server settings after
+ * refreshing the referral, so, in this case, default it to 1.
+ */
+ if (!dfs_cache_noreq_find(refpath, NULL, &tl))
+ num_targets = dfs_cache_get_nr_tgts(&tl);
+ if (!num_targets)
+ num_targets = 1;
+
+ if (!cifs_tcp_ses_needs_reconnect(server, num_targets))
+ return 0;
+
+ /*
+ * Unconditionally mark all sessions & tcons for reconnect as we might be connecting to a
+ * different server or share during failover. It could be improved by adding some logic to
+ * only do that in case it connects to a different server or share, though.
+ */
+ cifs_mark_tcp_ses_conns_for_reconnect(server, true);
+
+ cifs_abort_connection(server);
+
+ do {
+ try_to_freeze();
+ cifs_server_lock(server);
+
+ rc = reconnect_target_unlocked(server, &tl, &target_hint);
+ if (rc) {
+ /* Failed to reconnect socket */
+ cifs_server_unlock(server);
+ cifs_dbg(FYI, "%s: reconnect error %d\n", __func__, rc);
+ msleep(3000);
+ continue;
+ }
+ /*
+ * Socket was created. Update tcp session status to CifsNeedNegotiate so that a
+ * process waiting for reconnect will know it needs to re-establish session and tcon
+ * through the reconnected target server.
+ */
+ atomic_inc(&tcpSesReconnectCount);
+ set_credits(server, 1);
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus != CifsExiting)
+ server->tcpStatus = CifsNeedNegotiate;
+ spin_unlock(&server->srv_lock);
+ cifs_swn_reset_server_dstaddr(server);
+ cifs_server_unlock(server);
+ mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
+ } while (server->tcpStatus == CifsNeedReconnect);
+
+ if (target_hint)
+ dfs_cache_noreq_update_tgthint(refpath, target_hint);
+
+ dfs_cache_free_tgts(&tl);
+
+ /* Need to set up echo worker again once connection has been established */
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsNeedNegotiate)
+ mod_delayed_work(cifsiod_wq, &server->echo, 0);
+ spin_unlock(&server->srv_lock);
+
+ wake_up(&server->response_q);
+ return rc;
+}
+
+int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
+{
+ /* If tcp session is not an dfs connection, then reconnect to last target server */
+ spin_lock(&server->srv_lock);
+ if (!server->is_dfs_conn) {
+ spin_unlock(&server->srv_lock);
+ return __cifs_reconnect(server, mark_smb_session);
+ }
+ spin_unlock(&server->srv_lock);
+
+ mutex_lock(&server->refpath_lock);
+ if (!server->origin_fullpath || !server->leaf_fullpath) {
+ mutex_unlock(&server->refpath_lock);
+ return __cifs_reconnect(server, mark_smb_session);
+ }
+ mutex_unlock(&server->refpath_lock);
+
+ return reconnect_dfs_server(server);
+}
+#else
+int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
+{
+ return __cifs_reconnect(server, mark_smb_session);
+}
+#endif
+
+static void
+cifs_echo_request(struct work_struct *work)
+{
+ int rc;
+ struct TCP_Server_Info *server = container_of(work,
+ struct TCP_Server_Info, echo.work);
+
+ /*
+ * We cannot send an echo if it is disabled.
+ * Also, no need to ping if we got a response recently.
+ */
+
+ if (server->tcpStatus == CifsNeedReconnect ||
+ server->tcpStatus == CifsExiting ||
+ server->tcpStatus == CifsNew ||
+ (server->ops->can_echo && !server->ops->can_echo(server)) ||
+ time_before(jiffies, server->lstrp + server->echo_interval - HZ))
+ goto requeue_echo;
+
+ rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
+ cifs_server_dbg(FYI, "send echo request: rc = %d\n", rc);
+
+ /* Check witness registrations */
+ cifs_swn_check();
+
+requeue_echo:
+ queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
+}
+
+static bool
+allocate_buffers(struct TCP_Server_Info *server)
+{
+ if (!server->bigbuf) {
+ server->bigbuf = (char *)cifs_buf_get();
+ if (!server->bigbuf) {
+ cifs_server_dbg(VFS, "No memory for large SMB response\n");
+ msleep(3000);
+ /* retry will check if exiting */
+ return false;
+ }
+ } else if (server->large_buf) {
+ /* we are reusing a dirty large buf, clear its start */
+ memset(server->bigbuf, 0, HEADER_SIZE(server));
+ }
+
+ if (!server->smallbuf) {
+ server->smallbuf = (char *)cifs_small_buf_get();
+ if (!server->smallbuf) {
+ cifs_server_dbg(VFS, "No memory for SMB response\n");
+ msleep(1000);
+ /* retry will check if exiting */
+ return false;
+ }
+ /* beginning of smb buffer is cleared in our buf_get */
+ } else {
+ /* if existing small buf clear beginning */
+ memset(server->smallbuf, 0, HEADER_SIZE(server));
+ }
+
+ return true;
+}
+
+static bool
+server_unresponsive(struct TCP_Server_Info *server)
+{
+ /*
+ * We need to wait 3 echo intervals to make sure we handle such
+ * situations right:
+ * 1s client sends a normal SMB request
+ * 2s client gets a response
+ * 30s echo workqueue job pops, and decides we got a response recently
+ * and don't need to send another
+ * ...
+ * 65s kernel_recvmsg times out, and we see that we haven't gotten
+ * a response in >60s.
+ */
+ spin_lock(&server->srv_lock);
+ if ((server->tcpStatus == CifsGood ||
+ server->tcpStatus == CifsNeedNegotiate) &&
+ (!server->ops->can_echo || server->ops->can_echo(server)) &&
+ time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
+ spin_unlock(&server->srv_lock);
+ cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
+ (3 * server->echo_interval) / HZ);
+ cifs_reconnect(server, false);
+ return true;
+ }
+ spin_unlock(&server->srv_lock);
+
+ return false;
+}
+
+static inline bool
+zero_credits(struct TCP_Server_Info *server)
+{
+ int val;
+
+ spin_lock(&server->req_lock);
+ val = server->credits + server->echo_credits + server->oplock_credits;
+ if (server->in_flight == 0 && val == 0) {
+ spin_unlock(&server->req_lock);
+ return true;
+ }
+ spin_unlock(&server->req_lock);
+ return false;
+}
+
+static int
+cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
+{
+ int length = 0;
+ int total_read;
+
+ for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
+ try_to_freeze();
+
+ /* reconnect if no credits and no requests in flight */
+ if (zero_credits(server)) {
+ cifs_reconnect(server, false);
+ return -ECONNABORTED;
+ }
+
+ if (server_unresponsive(server))
+ return -ECONNABORTED;
+ if (cifs_rdma_enabled(server) && server->smbd_conn)
+ length = smbd_recv(server->smbd_conn, smb_msg);
+ else
+ length = sock_recvmsg(server->ssocket, smb_msg, 0);
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsExiting) {
+ spin_unlock(&server->srv_lock);
+ return -ESHUTDOWN;
+ }
+
+ if (server->tcpStatus == CifsNeedReconnect) {
+ spin_unlock(&server->srv_lock);
+ cifs_reconnect(server, false);
+ return -ECONNABORTED;
+ }
+ spin_unlock(&server->srv_lock);
+
+ if (length == -ERESTARTSYS ||
+ length == -EAGAIN ||
+ length == -EINTR) {
+ /*
+ * Minimum sleep to prevent looping, allowing socket
+ * to clear and app threads to set tcpStatus
+ * CifsNeedReconnect if server hung.
+ */
+ usleep_range(1000, 2000);
+ length = 0;
+ continue;
+ }
+
+ if (length <= 0) {
+ cifs_dbg(FYI, "Received no data or error: %d\n", length);
+ cifs_reconnect(server, false);
+ return -ECONNABORTED;
+ }
+ }
+ return total_read;
+}
+
+int
+cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
+ unsigned int to_read)
+{
+ struct msghdr smb_msg = {};
+ struct kvec iov = {.iov_base = buf, .iov_len = to_read};
+ iov_iter_kvec(&smb_msg.msg_iter, ITER_DEST, &iov, 1, to_read);
+
+ return cifs_readv_from_socket(server, &smb_msg);
+}
+
+ssize_t
+cifs_discard_from_socket(struct TCP_Server_Info *server, size_t to_read)
+{
+ struct msghdr smb_msg = {};
+
+ /*
+ * iov_iter_discard already sets smb_msg.type and count and iov_offset
+ * and cifs_readv_from_socket sets msg_control and msg_controllen
+ * so little to initialize in struct msghdr
+ */
+ iov_iter_discard(&smb_msg.msg_iter, ITER_DEST, to_read);
+
+ return cifs_readv_from_socket(server, &smb_msg);
+}
+
+int
+cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
+ unsigned int page_offset, unsigned int to_read)
+{
+ struct msghdr smb_msg = {};
+ struct bio_vec bv = {
+ .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
+ iov_iter_bvec(&smb_msg.msg_iter, ITER_DEST, &bv, 1, to_read);
+ return cifs_readv_from_socket(server, &smb_msg);
+}
+
+static bool
+is_smb_response(struct TCP_Server_Info *server, unsigned char type)
+{
+ /*
+ * The first byte big endian of the length field,
+ * is actually not part of the length but the type
+ * with the most common, zero, as regular data.
+ */
+ switch (type) {
+ case RFC1002_SESSION_MESSAGE:
+ /* Regular SMB response */
+ return true;
+ case RFC1002_SESSION_KEEP_ALIVE:
+ cifs_dbg(FYI, "RFC 1002 session keep alive\n");
+ break;
+ case RFC1002_POSITIVE_SESSION_RESPONSE:
+ cifs_dbg(FYI, "RFC 1002 positive session response\n");
+ break;
+ case RFC1002_NEGATIVE_SESSION_RESPONSE:
+ /*
+ * We get this from Windows 98 instead of an error on
+ * SMB negprot response.
+ */
+ cifs_dbg(FYI, "RFC 1002 negative session response\n");
+ /* give server a second to clean up */
+ msleep(1000);
+ /*
+ * Always try 445 first on reconnect since we get NACK
+ * on some if we ever connected to port 139 (the NACK
+ * is since we do not begin with RFC1001 session
+ * initialize frame).
+ */
+ cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
+ cifs_reconnect(server, true);
+ break;
+ default:
+ cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
+ cifs_reconnect(server, true);
+ }
+
+ return false;
+}
+
+void
+dequeue_mid(struct mid_q_entry *mid, bool malformed)
+{
+#ifdef CONFIG_CIFS_STATS2
+ mid->when_received = jiffies;
+#endif
+ spin_lock(&mid->server->mid_lock);
+ if (!malformed)
+ mid->mid_state = MID_RESPONSE_RECEIVED;
+ else
+ mid->mid_state = MID_RESPONSE_MALFORMED;
+ /*
+ * Trying to handle/dequeue a mid after the send_recv()
+ * function has finished processing it is a bug.
+ */
+ if (mid->mid_flags & MID_DELETED) {
+ spin_unlock(&mid->server->mid_lock);
+ pr_warn_once("trying to dequeue a deleted mid\n");
+ } else {
+ list_del_init(&mid->qhead);
+ mid->mid_flags |= MID_DELETED;
+ spin_unlock(&mid->server->mid_lock);
+ }
+}
+
+static unsigned int
+smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
+{
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buffer;
+
+ /*
+ * SMB1 does not use credits.
+ */
+ if (is_smb1(server))
+ return 0;
+
+ return le16_to_cpu(shdr->CreditRequest);
+}
+
+static void
+handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
+ char *buf, int malformed)
+{
+ if (server->ops->check_trans2 &&
+ server->ops->check_trans2(mid, server, buf, malformed))
+ return;
+ mid->credits_received = smb2_get_credits_from_hdr(buf, server);
+ mid->resp_buf = buf;
+ mid->large_buf = server->large_buf;
+ /* Was previous buf put in mpx struct for multi-rsp? */
+ if (!mid->multiRsp) {
+ /* smb buffer will be freed by user thread */
+ if (server->large_buf)
+ server->bigbuf = NULL;
+ else
+ server->smallbuf = NULL;
+ }
+ dequeue_mid(mid, malformed);
+}
+
+int
+cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
+{
+ bool srv_sign_required = server->sec_mode & server->vals->signing_required;
+ bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
+ bool mnt_sign_enabled;
+
+ /*
+ * Is signing required by mnt options? If not then check
+ * global_secflags to see if it is there.
+ */
+ if (!mnt_sign_required)
+ mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
+ CIFSSEC_MUST_SIGN);
+
+ /*
+ * If signing is required then it's automatically enabled too,
+ * otherwise, check to see if the secflags allow it.
+ */
+ mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
+ (global_secflags & CIFSSEC_MAY_SIGN);
+
+ /* If server requires signing, does client allow it? */
+ if (srv_sign_required) {
+ if (!mnt_sign_enabled) {
+ cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!\n");
+ return -EOPNOTSUPP;
+ }
+ server->sign = true;
+ }
+
+ /* If client requires signing, does server allow it? */
+ if (mnt_sign_required) {
+ if (!srv_sign_enabled) {
+ cifs_dbg(VFS, "Server does not support signing!\n");
+ return -EOPNOTSUPP;
+ }
+ server->sign = true;
+ }
+
+ if (cifs_rdma_enabled(server) && server->sign)
+ cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled\n");
+
+ return 0;
+}
+
+
+static void clean_demultiplex_info(struct TCP_Server_Info *server)
+{
+ int length;
+
+ /* take it off the list, if it's not already */
+ spin_lock(&server->srv_lock);
+ list_del_init(&server->tcp_ses_list);
+ spin_unlock(&server->srv_lock);
+
+ cancel_delayed_work_sync(&server->echo);
+ cancel_delayed_work_sync(&server->resolve);
+
+ spin_lock(&server->srv_lock);
+ server->tcpStatus = CifsExiting;
+ spin_unlock(&server->srv_lock);
+ wake_up_all(&server->response_q);
+
+ /* check if we have blocked requests that need to free */
+ spin_lock(&server->req_lock);
+ if (server->credits <= 0)
+ server->credits = 1;
+ spin_unlock(&server->req_lock);
+ /*
+ * Although there should not be any requests blocked on this queue it
+ * can not hurt to be paranoid and try to wake up requests that may
+ * haven been blocked when more than 50 at time were on the wire to the
+ * same server - they now will see the session is in exit state and get
+ * out of SendReceive.
+ */
+ wake_up_all(&server->request_q);
+ /* give those requests time to exit */
+ msleep(125);
+ if (cifs_rdma_enabled(server))
+ smbd_destroy(server);
+ if (server->ssocket) {
+ sock_release(server->ssocket);
+ server->ssocket = NULL;
+ }
+
+ if (!list_empty(&server->pending_mid_q)) {
+ struct list_head dispose_list;
+ struct mid_q_entry *mid_entry;
+ struct list_head *tmp, *tmp2;
+
+ INIT_LIST_HEAD(&dispose_list);
+ spin_lock(&server->mid_lock);
+ list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
+ mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+ cifs_dbg(FYI, "Clearing mid %llu\n", mid_entry->mid);
+ kref_get(&mid_entry->refcount);
+ mid_entry->mid_state = MID_SHUTDOWN;
+ list_move(&mid_entry->qhead, &dispose_list);
+ mid_entry->mid_flags |= MID_DELETED;
+ }
+ spin_unlock(&server->mid_lock);
+
+ /* now walk dispose list and issue callbacks */
+ list_for_each_safe(tmp, tmp2, &dispose_list) {
+ mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+ cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid);
+ list_del_init(&mid_entry->qhead);
+ mid_entry->callback(mid_entry);
+ release_mid(mid_entry);
+ }
+ /* 1/8th of sec is more than enough time for them to exit */
+ msleep(125);
+ }
+
+ if (!list_empty(&server->pending_mid_q)) {
+ /*
+ * mpx threads have not exited yet give them at least the smb
+ * send timeout time for long ops.
+ *
+ * Due to delays on oplock break requests, we need to wait at
+ * least 45 seconds before giving up on a request getting a
+ * response and going ahead and killing cifsd.
+ */
+ cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
+ msleep(46000);
+ /*
+ * If threads still have not exited they are probably never
+ * coming home not much else we can do but free the memory.
+ */
+ }
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ kfree(server->origin_fullpath);
+ kfree(server->leaf_fullpath);
+#endif
+ kfree(server);
+
+ length = atomic_dec_return(&tcpSesAllocCount);
+ if (length > 0)
+ mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
+}
+
+static int
+standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+ int length;
+ char *buf = server->smallbuf;
+ unsigned int pdu_length = server->pdu_size;
+
+ /* make sure this will fit in a large buffer */
+ if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
+ HEADER_PREAMBLE_SIZE(server)) {
+ cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
+ cifs_reconnect(server, true);
+ return -ECONNABORTED;
+ }
+
+ /* switch to large buffer if too big for a small one */
+ if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
+ server->large_buf = true;
+ memcpy(server->bigbuf, buf, server->total_read);
+ buf = server->bigbuf;
+ }
+
+ /* now read the rest */
+ length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
+ pdu_length - MID_HEADER_SIZE(server));
+
+ if (length < 0)
+ return length;
+ server->total_read += length;
+
+ dump_smb(buf, server->total_read);
+
+ return cifs_handle_standard(server, mid);
+}
+
+int
+cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+ char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
+ int rc;
+
+ /*
+ * We know that we received enough to get to the MID as we
+ * checked the pdu_length earlier. Now check to see
+ * if the rest of the header is OK.
+ *
+ * 48 bytes is enough to display the header and a little bit
+ * into the payload for debugging purposes.
+ */
+ rc = server->ops->check_message(buf, server->total_read, server);
+ if (rc)
+ cifs_dump_mem("Bad SMB: ", buf,
+ min_t(unsigned int, server->total_read, 48));
+
+ if (server->ops->is_session_expired &&
+ server->ops->is_session_expired(buf)) {
+ cifs_reconnect(server, true);
+ return -1;
+ }
+
+ if (server->ops->is_status_pending &&
+ server->ops->is_status_pending(buf, server))
+ return -1;
+
+ if (!mid)
+ return rc;
+
+ handle_mid(mid, server, buf, rc);
+ return 0;
+}
+
+static void
+smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
+{
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buffer;
+ int scredits, in_flight;
+
+ /*
+ * SMB1 does not use credits.
+ */
+ if (is_smb1(server))
+ return;
+
+ if (shdr->CreditRequest) {
+ spin_lock(&server->req_lock);
+ server->credits += le16_to_cpu(shdr->CreditRequest);
+ scredits = server->credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+ wake_up(&server->request_q);
+
+ trace_smb3_hdr_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits,
+ le16_to_cpu(shdr->CreditRequest), in_flight);
+ cifs_server_dbg(FYI, "%s: added %u credits total=%d\n",
+ __func__, le16_to_cpu(shdr->CreditRequest),
+ scredits);
+ }
+}
+
+
+static int
+cifs_demultiplex_thread(void *p)
+{
+ int i, num_mids, length;
+ struct TCP_Server_Info *server = p;
+ unsigned int pdu_length;
+ unsigned int next_offset;
+ char *buf = NULL;
+ struct task_struct *task_to_wake = NULL;
+ struct mid_q_entry *mids[MAX_COMPOUND];
+ char *bufs[MAX_COMPOUND];
+ unsigned int noreclaim_flag, num_io_timeout = 0;
+
+ noreclaim_flag = memalloc_noreclaim_save();
+ cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
+
+ length = atomic_inc_return(&tcpSesAllocCount);
+ if (length > 1)
+ mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
+
+ set_freezable();
+ allow_kernel_signal(SIGKILL);
+ while (server->tcpStatus != CifsExiting) {
+ if (try_to_freeze())
+ continue;
+
+ if (!allocate_buffers(server))
+ continue;
+
+ server->large_buf = false;
+ buf = server->smallbuf;
+ pdu_length = 4; /* enough to get RFC1001 header */
+
+ length = cifs_read_from_socket(server, buf, pdu_length);
+ if (length < 0)
+ continue;
+
+ if (is_smb1(server))
+ server->total_read = length;
+ else
+ server->total_read = 0;
+
+ /*
+ * The right amount was read from socket - 4 bytes,
+ * so we can now interpret the length field.
+ */
+ pdu_length = get_rfc1002_length(buf);
+
+ cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
+ if (!is_smb_response(server, buf[0]))
+ continue;
+next_pdu:
+ server->pdu_size = pdu_length;
+
+ /* make sure we have enough to get to the MID */
+ if (server->pdu_size < MID_HEADER_SIZE(server)) {
+ cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
+ server->pdu_size);
+ cifs_reconnect(server, true);
+ continue;
+ }
+
+ /* read down to the MID */
+ length = cifs_read_from_socket(server,
+ buf + HEADER_PREAMBLE_SIZE(server),
+ MID_HEADER_SIZE(server));
+ if (length < 0)
+ continue;
+ server->total_read += length;
+
+ if (server->ops->next_header) {
+ next_offset = server->ops->next_header(buf);
+ if (next_offset)
+ server->pdu_size = next_offset;
+ }
+
+ memset(mids, 0, sizeof(mids));
+ memset(bufs, 0, sizeof(bufs));
+ num_mids = 0;
+
+ if (server->ops->is_transform_hdr &&
+ server->ops->receive_transform &&
+ server->ops->is_transform_hdr(buf)) {
+ length = server->ops->receive_transform(server,
+ mids,
+ bufs,
+ &num_mids);
+ } else {
+ mids[0] = server->ops->find_mid(server, buf);
+ bufs[0] = buf;
+ num_mids = 1;
+
+ if (!mids[0] || !mids[0]->receive)
+ length = standard_receive3(server, mids[0]);
+ else
+ length = mids[0]->receive(server, mids[0]);
+ }
+
+ if (length < 0) {
+ for (i = 0; i < num_mids; i++)
+ if (mids[i])
+ release_mid(mids[i]);
+ continue;
+ }
+
+ if (server->ops->is_status_io_timeout &&
+ server->ops->is_status_io_timeout(buf)) {
+ num_io_timeout++;
+ if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
+ cifs_reconnect(server, false);
+ num_io_timeout = 0;
+ continue;
+ }
+ }
+
+ server->lstrp = jiffies;
+
+ for (i = 0; i < num_mids; i++) {
+ if (mids[i] != NULL) {
+ mids[i]->resp_buf_size = server->pdu_size;
+
+ if (bufs[i] && server->ops->is_network_name_deleted)
+ server->ops->is_network_name_deleted(bufs[i],
+ server);
+
+ if (!mids[i]->multiRsp || mids[i]->multiEnd)
+ mids[i]->callback(mids[i]);
+
+ release_mid(mids[i]);
+ } else if (server->ops->is_oplock_break &&
+ server->ops->is_oplock_break(bufs[i],
+ server)) {
+ smb2_add_credits_from_hdr(bufs[i], server);
+ cifs_dbg(FYI, "Received oplock break\n");
+ } else {
+ cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
+ atomic_read(&mid_count));
+ cifs_dump_mem("Received Data is: ", bufs[i],
+ HEADER_SIZE(server));
+ smb2_add_credits_from_hdr(bufs[i], server);
+#ifdef CONFIG_CIFS_DEBUG2
+ if (server->ops->dump_detail)
+ server->ops->dump_detail(bufs[i],
+ server);
+ cifs_dump_mids(server);
+#endif /* CIFS_DEBUG2 */
+ }
+ }
+
+ if (pdu_length > server->pdu_size) {
+ if (!allocate_buffers(server))
+ continue;
+ pdu_length -= server->pdu_size;
+ server->total_read = 0;
+ server->large_buf = false;
+ buf = server->smallbuf;
+ goto next_pdu;
+ }
+ } /* end while !EXITING */
+
+ /* buffer usually freed in free_mid - need to free it here on exit */
+ cifs_buf_release(server->bigbuf);
+ if (server->smallbuf) /* no sense logging a debug message if NULL */
+ cifs_small_buf_release(server->smallbuf);
+
+ task_to_wake = xchg(&server->tsk, NULL);
+ clean_demultiplex_info(server);
+
+ /* if server->tsk was NULL then wait for a signal before exiting */
+ if (!task_to_wake) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (!signal_pending(current)) {
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+ set_current_state(TASK_RUNNING);
+ }
+
+ memalloc_noreclaim_restore(noreclaim_flag);
+ module_put_and_kthread_exit(0);
+}
+
+/*
+ * Returns true if srcaddr isn't specified and rhs isn't specified, or
+ * if srcaddr is specified and matches the IP address of the rhs argument
+ */
+bool
+cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
+{
+ switch (srcaddr->sa_family) {
+ case AF_UNSPEC:
+ return (rhs->sa_family == AF_UNSPEC);
+ case AF_INET: {
+ struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
+ struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
+ return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
+ struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
+ return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
+ }
+ default:
+ WARN_ON(1);
+ return false; /* don't expect to be here */
+ }
+}
+
+/*
+ * If no port is specified in addr structure, we try to match with 445 port
+ * and if it fails - with 139 ports. It should be called only if address
+ * families of server and addr are equal.
+ */
+static bool
+match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
+{
+ __be16 port, *sport;
+
+ /* SMBDirect manages its own ports, don't match it here */
+ if (server->rdma)
+ return true;
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
+ port = ((struct sockaddr_in *) addr)->sin_port;
+ break;
+ case AF_INET6:
+ sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
+ port = ((struct sockaddr_in6 *) addr)->sin6_port;
+ break;
+ default:
+ WARN_ON(1);
+ return false;
+ }
+
+ if (!port) {
+ port = htons(CIFS_PORT);
+ if (port == *sport)
+ return true;
+
+ port = htons(RFC1001_PORT);
+ }
+
+ return port == *sport;
+}
+
+static bool
+match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
+ struct sockaddr *srcaddr)
+{
+ switch (addr->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
+ struct sockaddr_in *srv_addr4 =
+ (struct sockaddr_in *)&server->dstaddr;
+
+ if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
+ return false;
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
+ struct sockaddr_in6 *srv_addr6 =
+ (struct sockaddr_in6 *)&server->dstaddr;
+
+ if (!ipv6_addr_equal(&addr6->sin6_addr,
+ &srv_addr6->sin6_addr))
+ return false;
+ if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
+ return false;
+ break;
+ }
+ default:
+ WARN_ON(1);
+ return false; /* don't expect to be here */
+ }
+
+ if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr))
+ return false;
+
+ return true;
+}
+
+static bool
+match_security(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+{
+ /*
+ * The select_sectype function should either return the ctx->sectype
+ * that was specified, or "Unspecified" if that sectype was not
+ * compatible with the given NEGOTIATE request.
+ */
+ if (server->ops->select_sectype(server, ctx->sectype)
+ == Unspecified)
+ return false;
+
+ /*
+ * Now check if signing mode is acceptable. No need to check
+ * global_secflags at this point since if MUST_SIGN is set then
+ * the server->sign had better be too.
+ */
+ if (ctx->sign && !server->sign)
+ return false;
+
+ return true;
+}
+
+/* this function must be called with srv_lock held */
+static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+{
+ struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
+
+ lockdep_assert_held(&server->srv_lock);
+
+ if (ctx->nosharesock)
+ return 0;
+
+ /* this server does not share socket */
+ if (server->nosharesock)
+ return 0;
+
+ /* If multidialect negotiation see if existing sessions match one */
+ if (strcmp(ctx->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
+ if (server->vals->protocol_id < SMB30_PROT_ID)
+ return 0;
+ } else if (strcmp(ctx->vals->version_string,
+ SMBDEFAULT_VERSION_STRING) == 0) {
+ if (server->vals->protocol_id < SMB21_PROT_ID)
+ return 0;
+ } else if ((server->vals != ctx->vals) || (server->ops != ctx->ops))
+ return 0;
+
+ if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
+ return 0;
+
+ if (strcasecmp(server->hostname, ctx->server_hostname))
+ return 0;
+
+ if (!match_address(server, addr,
+ (struct sockaddr *)&ctx->srcaddr))
+ return 0;
+
+ if (!match_port(server, addr))
+ return 0;
+
+ if (!match_security(server, ctx))
+ return 0;
+
+ if (server->echo_interval != ctx->echo_interval * HZ)
+ return 0;
+
+ if (server->rdma != ctx->rdma)
+ return 0;
+
+ if (server->ignore_signature != ctx->ignore_signature)
+ return 0;
+
+ if (server->min_offload != ctx->min_offload)
+ return 0;
+
+ return 1;
+}
+
+struct TCP_Server_Info *
+cifs_find_tcp_session(struct smb3_fs_context *ctx)
+{
+ struct TCP_Server_Info *server;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
+ spin_lock(&server->srv_lock);
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ /*
+ * DFS failover implementation in cifs_reconnect() requires unique tcp sessions for
+ * DFS connections to do failover properly, so avoid sharing them with regular
+ * shares or even links that may connect to same server but having completely
+ * different failover targets.
+ */
+ if (server->is_dfs_conn) {
+ spin_unlock(&server->srv_lock);
+ continue;
+ }
+#endif
+ /*
+ * Skip ses channels since they're only handled in lower layers
+ * (e.g. cifs_send_recv).
+ */
+ if (CIFS_SERVER_IS_CHAN(server) || !match_server(server, ctx)) {
+ spin_unlock(&server->srv_lock);
+ continue;
+ }
+ spin_unlock(&server->srv_lock);
+
+ ++server->srv_count;
+ spin_unlock(&cifs_tcp_ses_lock);
+ cifs_dbg(FYI, "Existing tcp session with server found\n");
+ return server;
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+}
+
+void
+cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
+{
+ struct task_struct *task;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ if (--server->srv_count > 0) {
+ spin_unlock(&cifs_tcp_ses_lock);
+ return;
+ }
+
+ /* srv_count can never go negative */
+ WARN_ON(server->srv_count < 0);
+
+ put_net(cifs_net_ns(server));
+
+ list_del_init(&server->tcp_ses_list);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ /* For secondary channels, we pick up ref-count on the primary server */
+ if (CIFS_SERVER_IS_CHAN(server))
+ cifs_put_tcp_session(server->primary_server, from_reconnect);
+
+ cancel_delayed_work_sync(&server->echo);
+ cancel_delayed_work_sync(&server->resolve);
+
+ if (from_reconnect)
+ /*
+ * Avoid deadlock here: reconnect work calls
+ * cifs_put_tcp_session() at its end. Need to be sure
+ * that reconnect work does nothing with server pointer after
+ * that step.
+ */
+ cancel_delayed_work(&server->reconnect);
+ else
+ cancel_delayed_work_sync(&server->reconnect);
+
+ spin_lock(&server->srv_lock);
+ server->tcpStatus = CifsExiting;
+ spin_unlock(&server->srv_lock);
+
+ cifs_crypto_secmech_release(server);
+
+ kfree_sensitive(server->session_key.response);
+ server->session_key.response = NULL;
+ server->session_key.len = 0;
+ kfree(server->hostname);
+ server->hostname = NULL;
+
+ task = xchg(&server->tsk, NULL);
+ if (task)
+ send_sig(SIGKILL, task, 1);
+}
+
+struct TCP_Server_Info *
+cifs_get_tcp_session(struct smb3_fs_context *ctx,
+ struct TCP_Server_Info *primary_server)
+{
+ struct TCP_Server_Info *tcp_ses = NULL;
+ int rc;
+
+ cifs_dbg(FYI, "UNC: %s\n", ctx->UNC);
+
+ /* see if we already have a matching tcp_ses */
+ tcp_ses = cifs_find_tcp_session(ctx);
+ if (tcp_ses)
+ return tcp_ses;
+
+ tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
+ if (!tcp_ses) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+
+ tcp_ses->hostname = kstrdup(ctx->server_hostname, GFP_KERNEL);
+ if (!tcp_ses->hostname) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+
+ if (ctx->nosharesock)
+ tcp_ses->nosharesock = true;
+
+ tcp_ses->ops = ctx->ops;
+ tcp_ses->vals = ctx->vals;
+ cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
+
+ tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId);
+ tcp_ses->noblockcnt = ctx->rootfs;
+ tcp_ses->noblocksnd = ctx->noblocksnd || ctx->rootfs;
+ tcp_ses->noautotune = ctx->noautotune;
+ tcp_ses->tcp_nodelay = ctx->sockopt_tcp_nodelay;
+ tcp_ses->rdma = ctx->rdma;
+ tcp_ses->in_flight = 0;
+ tcp_ses->max_in_flight = 0;
+ tcp_ses->credits = 1;
+ if (primary_server) {
+ spin_lock(&cifs_tcp_ses_lock);
+ ++primary_server->srv_count;
+ spin_unlock(&cifs_tcp_ses_lock);
+ tcp_ses->primary_server = primary_server;
+ }
+ init_waitqueue_head(&tcp_ses->response_q);
+ init_waitqueue_head(&tcp_ses->request_q);
+ INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
+ mutex_init(&tcp_ses->_srv_mutex);
+ memcpy(tcp_ses->workstation_RFC1001_name,
+ ctx->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
+ memcpy(tcp_ses->server_RFC1001_name,
+ ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
+ tcp_ses->session_estab = false;
+ tcp_ses->sequence_number = 0;
+ tcp_ses->reconnect_instance = 1;
+ tcp_ses->lstrp = jiffies;
+ tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression);
+ spin_lock_init(&tcp_ses->req_lock);
+ spin_lock_init(&tcp_ses->srv_lock);
+ spin_lock_init(&tcp_ses->mid_lock);
+ INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
+ INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
+ INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
+ INIT_DELAYED_WORK(&tcp_ses->resolve, cifs_resolve_server);
+ INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
+ mutex_init(&tcp_ses->reconnect_mutex);
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ mutex_init(&tcp_ses->refpath_lock);
+#endif
+ memcpy(&tcp_ses->srcaddr, &ctx->srcaddr,
+ sizeof(tcp_ses->srcaddr));
+ memcpy(&tcp_ses->dstaddr, &ctx->dstaddr,
+ sizeof(tcp_ses->dstaddr));
+ if (ctx->use_client_guid)
+ memcpy(tcp_ses->client_guid, ctx->client_guid,
+ SMB2_CLIENT_GUID_SIZE);
+ else
+ generate_random_uuid(tcp_ses->client_guid);
+ /*
+ * at this point we are the only ones with the pointer
+ * to the struct since the kernel thread not created yet
+ * no need to spinlock this init of tcpStatus or srv_count
+ */
+ tcp_ses->tcpStatus = CifsNew;
+ ++tcp_ses->srv_count;
+
+ if (ctx->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
+ ctx->echo_interval <= SMB_ECHO_INTERVAL_MAX)
+ tcp_ses->echo_interval = ctx->echo_interval * HZ;
+ else
+ tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
+ if (tcp_ses->rdma) {
+#ifndef CONFIG_CIFS_SMB_DIRECT
+ cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
+ rc = -ENOENT;
+ goto out_err_crypto_release;
+#endif
+ tcp_ses->smbd_conn = smbd_get_connection(
+ tcp_ses, (struct sockaddr *)&ctx->dstaddr);
+ if (tcp_ses->smbd_conn) {
+ cifs_dbg(VFS, "RDMA transport established\n");
+ rc = 0;
+ goto smbd_connected;
+ } else {
+ rc = -ENOENT;
+ goto out_err_crypto_release;
+ }
+ }
+ rc = ip_connect(tcp_ses);
+ if (rc < 0) {
+ cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
+ goto out_err_crypto_release;
+ }
+smbd_connected:
+ /*
+ * since we're in a cifs function already, we know that
+ * this will succeed. No need for try_module_get().
+ */
+ __module_get(THIS_MODULE);
+ tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
+ tcp_ses, "cifsd");
+ if (IS_ERR(tcp_ses->tsk)) {
+ rc = PTR_ERR(tcp_ses->tsk);
+ cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
+ module_put(THIS_MODULE);
+ goto out_err_crypto_release;
+ }
+ tcp_ses->min_offload = ctx->min_offload;
+ /*
+ * at this point we are the only ones with the pointer
+ * to the struct since the kernel thread not created yet
+ * no need to spinlock this update of tcpStatus
+ */
+ spin_lock(&tcp_ses->srv_lock);
+ tcp_ses->tcpStatus = CifsNeedNegotiate;
+ spin_unlock(&tcp_ses->srv_lock);
+
+ if ((ctx->max_credits < 20) || (ctx->max_credits > 60000))
+ tcp_ses->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
+ else
+ tcp_ses->max_credits = ctx->max_credits;
+
+ tcp_ses->nr_targets = 1;
+ tcp_ses->ignore_signature = ctx->ignore_signature;
+ /* thread spawned, put it on the list */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ /* queue echo request delayed work */
+ queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
+
+ /* queue dns resolution delayed work */
+ cifs_dbg(FYI, "%s: next dns resolution scheduled for %d seconds in the future\n",
+ __func__, SMB_DNS_RESOLVE_INTERVAL_DEFAULT);
+
+ queue_delayed_work(cifsiod_wq, &tcp_ses->resolve, (SMB_DNS_RESOLVE_INTERVAL_DEFAULT * HZ));
+
+ return tcp_ses;
+
+out_err_crypto_release:
+ cifs_crypto_secmech_release(tcp_ses);
+
+ put_net(cifs_net_ns(tcp_ses));
+
+out_err:
+ if (tcp_ses) {
+ if (CIFS_SERVER_IS_CHAN(tcp_ses))
+ cifs_put_tcp_session(tcp_ses->primary_server, false);
+ kfree(tcp_ses->hostname);
+ if (tcp_ses->ssocket)
+ sock_release(tcp_ses->ssocket);
+ kfree(tcp_ses);
+ }
+ return ERR_PTR(rc);
+}
+
+/* this function must be called with ses_lock and chan_lock held */
+static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
+{
+ if (ctx->sectype != Unspecified &&
+ ctx->sectype != ses->sectype)
+ return 0;
+
+ /*
+ * If an existing session is limited to less channels than
+ * requested, it should not be reused
+ */
+ if (ses->chan_max < ctx->max_channels)
+ return 0;
+
+ switch (ses->sectype) {
+ case Kerberos:
+ if (!uid_eq(ctx->cred_uid, ses->cred_uid))
+ return 0;
+ break;
+ default:
+ /* NULL username means anonymous session */
+ if (ses->user_name == NULL) {
+ if (!ctx->nullauth)
+ return 0;
+ break;
+ }
+
+ /* anything else takes username/password */
+ if (strncmp(ses->user_name,
+ ctx->username ? ctx->username : "",
+ CIFS_MAX_USERNAME_LEN))
+ return 0;
+ if ((ctx->username && strlen(ctx->username) != 0) &&
+ ses->password != NULL &&
+ strncmp(ses->password,
+ ctx->password ? ctx->password : "",
+ CIFS_MAX_PASSWORD_LEN))
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * cifs_setup_ipc - helper to setup the IPC tcon for the session
+ * @ses: smb session to issue the request on
+ * @ctx: the superblock configuration context to use for building the
+ * new tree connection for the IPC (interprocess communication RPC)
+ *
+ * A new IPC connection is made and stored in the session
+ * tcon_ipc. The IPC tcon has the same lifetime as the session.
+ */
+static int
+cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
+{
+ int rc = 0, xid;
+ struct cifs_tcon *tcon;
+ char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
+ bool seal = false;
+ struct TCP_Server_Info *server = ses->server;
+
+ /*
+ * If the mount request that resulted in the creation of the
+ * session requires encryption, force IPC to be encrypted too.
+ */
+ if (ctx->seal) {
+ if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
+ seal = true;
+ else {
+ cifs_server_dbg(VFS,
+ "IPC: server doesn't support encryption\n");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ tcon = tconInfoAlloc();
+ if (tcon == NULL)
+ return -ENOMEM;
+
+ spin_lock(&server->srv_lock);
+ scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
+ spin_unlock(&server->srv_lock);
+
+ xid = get_xid();
+ tcon->ses = ses;
+ tcon->ipc = true;
+ tcon->seal = seal;
+ rc = server->ops->tree_connect(xid, ses, unc, tcon, ctx->local_nls);
+ free_xid(xid);
+
+ if (rc) {
+ cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
+ tconInfoFree(tcon);
+ goto out;
+ }
+
+ cifs_dbg(FYI, "IPC tcon rc=%d ipc tid=0x%x\n", rc, tcon->tid);
+
+ spin_lock(&tcon->tc_lock);
+ tcon->status = TID_GOOD;
+ spin_unlock(&tcon->tc_lock);
+ ses->tcon_ipc = tcon;
+out:
+ return rc;
+}
+
+/**
+ * cifs_free_ipc - helper to release the session IPC tcon
+ * @ses: smb session to unmount the IPC from
+ *
+ * Needs to be called everytime a session is destroyed.
+ *
+ * On session close, the IPC is closed and the server must release all tcons of the session.
+ * No need to send a tree disconnect here.
+ *
+ * Besides, it will make the server to not close durable and resilient files on session close, as
+ * specified in MS-SMB2 3.3.5.6 Receiving an SMB2 LOGOFF Request.
+ */
+static int
+cifs_free_ipc(struct cifs_ses *ses)
+{
+ struct cifs_tcon *tcon = ses->tcon_ipc;
+
+ if (tcon == NULL)
+ return 0;
+
+ tconInfoFree(tcon);
+ ses->tcon_ipc = NULL;
+ return 0;
+}
+
+static struct cifs_ses *
+cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+{
+ struct cifs_ses *ses;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+ spin_lock(&ses->ses_lock);
+ if (ses->ses_status == SES_EXITING) {
+ spin_unlock(&ses->ses_lock);
+ continue;
+ }
+ spin_lock(&ses->chan_lock);
+ if (!match_session(ses, ctx)) {
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+ continue;
+ }
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+
+ ++ses->ses_count;
+ spin_unlock(&cifs_tcp_ses_lock);
+ return ses;
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+}
+
+void cifs_put_smb_ses(struct cifs_ses *ses)
+{
+ unsigned int rc, xid;
+ unsigned int chan_count;
+ struct TCP_Server_Info *server = ses->server;
+
+ spin_lock(&ses->ses_lock);
+ if (ses->ses_status == SES_EXITING) {
+ spin_unlock(&ses->ses_lock);
+ return;
+ }
+ spin_unlock(&ses->ses_lock);
+
+ cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
+ cifs_dbg(FYI,
+ "%s: ses ipc: %s\n", __func__, ses->tcon_ipc ? ses->tcon_ipc->tree_name : "NONE");
+
+ spin_lock(&cifs_tcp_ses_lock);
+ if (--ses->ses_count > 0) {
+ spin_unlock(&cifs_tcp_ses_lock);
+ return;
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ /* ses_count can never go negative */
+ WARN_ON(ses->ses_count < 0);
+
+ if (ses->ses_status == SES_GOOD)
+ ses->ses_status = SES_EXITING;
+
+ cifs_free_ipc(ses);
+
+ if (ses->ses_status == SES_EXITING && server->ops->logoff) {
+ xid = get_xid();
+ rc = server->ops->logoff(xid, ses);
+ if (rc)
+ cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
+ __func__, rc);
+ _free_xid(xid);
+ }
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_del_init(&ses->smb_ses_list);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ chan_count = ses->chan_count;
+
+ /* close any extra channels */
+ if (chan_count > 1) {
+ int i;
+
+ for (i = 1; i < chan_count; i++) {
+ if (ses->chans[i].iface) {
+ kref_put(&ses->chans[i].iface->refcount, release_iface);
+ ses->chans[i].iface = NULL;
+ }
+ cifs_put_tcp_session(ses->chans[i].server, 0);
+ ses->chans[i].server = NULL;
+ }
+ }
+
+ sesInfoFree(ses);
+ cifs_put_tcp_session(server, 0);
+}
+
+#ifdef CONFIG_KEYS
+
+/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
+#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
+
+/* Populate username and pw fields from keyring if possible */
+static int
+cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
+{
+ int rc = 0;
+ int is_domain = 0;
+ const char *delim, *payload;
+ char *desc;
+ ssize_t len;
+ struct key *key;
+ struct TCP_Server_Info *server = ses->server;
+ struct sockaddr_in *sa;
+ struct sockaddr_in6 *sa6;
+ const struct user_key_payload *upayload;
+
+ desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ /* try to find an address key first */
+ switch (server->dstaddr.ss_family) {
+ case AF_INET:
+ sa = (struct sockaddr_in *)&server->dstaddr;
+ sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
+ break;
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *)&server->dstaddr;
+ sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
+ break;
+ default:
+ cifs_dbg(FYI, "Bad ss_family (%hu)\n",
+ server->dstaddr.ss_family);
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
+ key = request_key(&key_type_logon, desc, "");
+ if (IS_ERR(key)) {
+ if (!ses->domainName) {
+ cifs_dbg(FYI, "domainName is NULL\n");
+ rc = PTR_ERR(key);
+ goto out_err;
+ }
+
+ /* didn't work, try to find a domain key */
+ sprintf(desc, "cifs:d:%s", ses->domainName);
+ cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
+ key = request_key(&key_type_logon, desc, "");
+ if (IS_ERR(key)) {
+ rc = PTR_ERR(key);
+ goto out_err;
+ }
+ is_domain = 1;
+ }
+
+ down_read(&key->sem);
+ upayload = user_key_payload_locked(key);
+ if (IS_ERR_OR_NULL(upayload)) {
+ rc = upayload ? PTR_ERR(upayload) : -EINVAL;
+ goto out_key_put;
+ }
+
+ /* find first : in payload */
+ payload = upayload->data;
+ delim = strnchr(payload, upayload->datalen, ':');
+ cifs_dbg(FYI, "payload=%s\n", payload);
+ if (!delim) {
+ cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
+ upayload->datalen);
+ rc = -EINVAL;
+ goto out_key_put;
+ }
+
+ len = delim - payload;
+ if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
+ cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
+ len);
+ rc = -EINVAL;
+ goto out_key_put;
+ }
+
+ ctx->username = kstrndup(payload, len, GFP_KERNEL);
+ if (!ctx->username) {
+ cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
+ len);
+ rc = -ENOMEM;
+ goto out_key_put;
+ }
+ cifs_dbg(FYI, "%s: username=%s\n", __func__, ctx->username);
+
+ len = key->datalen - (len + 1);
+ if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
+ cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
+ rc = -EINVAL;
+ kfree(ctx->username);
+ ctx->username = NULL;
+ goto out_key_put;
+ }
+
+ ++delim;
+ ctx->password = kstrndup(delim, len, GFP_KERNEL);
+ if (!ctx->password) {
+ cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
+ len);
+ rc = -ENOMEM;
+ kfree(ctx->username);
+ ctx->username = NULL;
+ goto out_key_put;
+ }
+
+ /*
+ * If we have a domain key then we must set the domainName in the
+ * for the request.
+ */
+ if (is_domain && ses->domainName) {
+ ctx->domainname = kstrdup(ses->domainName, GFP_KERNEL);
+ if (!ctx->domainname) {
+ cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
+ len);
+ rc = -ENOMEM;
+ kfree(ctx->username);
+ ctx->username = NULL;
+ kfree_sensitive(ctx->password);
+ ctx->password = NULL;
+ goto out_key_put;
+ }
+ }
+
+ strscpy(ctx->workstation_name, ses->workstation_name, sizeof(ctx->workstation_name));
+
+out_key_put:
+ up_read(&key->sem);
+ key_put(key);
+out_err:
+ kfree(desc);
+ cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
+ return rc;
+}
+#else /* ! CONFIG_KEYS */
+static inline int
+cifs_set_cifscreds(struct smb3_fs_context *ctx __attribute__((unused)),
+ struct cifs_ses *ses __attribute__((unused)))
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_KEYS */
+
+/**
+ * cifs_get_smb_ses - get a session matching @ctx data from @server
+ * @server: server to setup the session to
+ * @ctx: superblock configuration context to use to setup the session
+ *
+ * This function assumes it is being called from cifs_mount() where we
+ * already got a server reference (server refcount +1). See
+ * cifs_get_tcon() for refcount explanations.
+ */
+struct cifs_ses *
+cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+{
+ int rc = 0;
+ unsigned int xid;
+ struct cifs_ses *ses;
+ struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
+
+ xid = get_xid();
+
+ ses = cifs_find_smb_ses(server, ctx);
+ if (ses) {
+ cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
+ ses->ses_status);
+
+ spin_lock(&ses->chan_lock);
+ if (cifs_chan_needs_reconnect(ses, server)) {
+ spin_unlock(&ses->chan_lock);
+ cifs_dbg(FYI, "Session needs reconnect\n");
+
+ mutex_lock(&ses->session_mutex);
+ rc = cifs_negotiate_protocol(xid, ses, server);
+ if (rc) {
+ mutex_unlock(&ses->session_mutex);
+ /* problem -- put our ses reference */
+ cifs_put_smb_ses(ses);
+ free_xid(xid);
+ return ERR_PTR(rc);
+ }
+
+ rc = cifs_setup_session(xid, ses, server,
+ ctx->local_nls);
+ if (rc) {
+ mutex_unlock(&ses->session_mutex);
+ /* problem -- put our reference */
+ cifs_put_smb_ses(ses);
+ free_xid(xid);
+ return ERR_PTR(rc);
+ }
+ mutex_unlock(&ses->session_mutex);
+
+ spin_lock(&ses->chan_lock);
+ }
+ spin_unlock(&ses->chan_lock);
+
+ /* existing SMB ses has a server reference already */
+ cifs_put_tcp_session(server, 0);
+ free_xid(xid);
+ return ses;
+ }
+
+ rc = -ENOMEM;
+
+ cifs_dbg(FYI, "Existing smb sess not found\n");
+ ses = sesInfoAlloc();
+ if (ses == NULL)
+ goto get_ses_fail;
+
+ /* new SMB session uses our server ref */
+ ses->server = server;
+ if (server->dstaddr.ss_family == AF_INET6)
+ sprintf(ses->ip_addr, "%pI6", &addr6->sin6_addr);
+ else
+ sprintf(ses->ip_addr, "%pI4", &addr->sin_addr);
+
+ if (ctx->username) {
+ ses->user_name = kstrdup(ctx->username, GFP_KERNEL);
+ if (!ses->user_name)
+ goto get_ses_fail;
+ }
+
+ /* ctx->password freed at unmount */
+ if (ctx->password) {
+ ses->password = kstrdup(ctx->password, GFP_KERNEL);
+ if (!ses->password)
+ goto get_ses_fail;
+ }
+ if (ctx->domainname) {
+ ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL);
+ if (!ses->domainName)
+ goto get_ses_fail;
+ }
+
+ strscpy(ses->workstation_name, ctx->workstation_name, sizeof(ses->workstation_name));
+
+ if (ctx->domainauto)
+ ses->domainAuto = ctx->domainauto;
+ ses->cred_uid = ctx->cred_uid;
+ ses->linux_uid = ctx->linux_uid;
+
+ ses->sectype = ctx->sectype;
+ ses->sign = ctx->sign;
+
+ /* add server as first channel */
+ spin_lock(&ses->chan_lock);
+ ses->chans[0].server = server;
+ ses->chan_count = 1;
+ ses->chan_max = ctx->multichannel ? ctx->max_channels:1;
+ ses->chans_need_reconnect = 1;
+ spin_unlock(&ses->chan_lock);
+
+ mutex_lock(&ses->session_mutex);
+ rc = cifs_negotiate_protocol(xid, ses, server);
+ if (!rc)
+ rc = cifs_setup_session(xid, ses, server, ctx->local_nls);
+ mutex_unlock(&ses->session_mutex);
+
+ /* each channel uses a different signing key */
+ spin_lock(&ses->chan_lock);
+ memcpy(ses->chans[0].signkey, ses->smb3signingkey,
+ sizeof(ses->smb3signingkey));
+ spin_unlock(&ses->chan_lock);
+
+ if (rc)
+ goto get_ses_fail;
+
+ /*
+ * success, put it on the list and add it as first channel
+ * note: the session becomes active soon after this. So you'll
+ * need to lock before changing something in the session.
+ */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_add(&ses->smb_ses_list, &server->smb_ses_list);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ cifs_setup_ipc(ses, ctx);
+
+ free_xid(xid);
+
+ return ses;
+
+get_ses_fail:
+ sesInfoFree(ses);
+ free_xid(xid);
+ return ERR_PTR(rc);
+}
+
+/* this function must be called with tc_lock held */
+static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+{
+ if (tcon->status == TID_EXITING)
+ return 0;
+ if (strncmp(tcon->tree_name, ctx->UNC, MAX_TREE_SIZE))
+ return 0;
+ if (tcon->seal != ctx->seal)
+ return 0;
+ if (tcon->snapshot_time != ctx->snapshot_time)
+ return 0;
+ if (tcon->handle_timeout != ctx->handle_timeout)
+ return 0;
+ if (tcon->no_lease != ctx->no_lease)
+ return 0;
+ if (tcon->nodelete != ctx->nodelete)
+ return 0;
+ return 1;
+}
+
+static struct cifs_tcon *
+cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
+{
+ struct cifs_tcon *tcon;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ spin_lock(&tcon->tc_lock);
+ if (!match_tcon(tcon, ctx)) {
+ spin_unlock(&tcon->tc_lock);
+ continue;
+ }
+ ++tcon->tc_count;
+ spin_unlock(&tcon->tc_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ return tcon;
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+}
+
+void
+cifs_put_tcon(struct cifs_tcon *tcon)
+{
+ unsigned int xid;
+ struct cifs_ses *ses;
+
+ /*
+ * IPC tcon share the lifetime of their session and are
+ * destroyed in the session put function
+ */
+ if (tcon == NULL || tcon->ipc)
+ return;
+
+ ses = tcon->ses;
+ cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
+ spin_lock(&cifs_tcp_ses_lock);
+ spin_lock(&tcon->tc_lock);
+ if (--tcon->tc_count > 0) {
+ spin_unlock(&tcon->tc_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ return;
+ }
+
+ /* tc_count can never go negative */
+ WARN_ON(tcon->tc_count < 0);
+
+ list_del_init(&tcon->tcon_list);
+ tcon->status = TID_EXITING;
+ spin_unlock(&tcon->tc_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ /* cancel polling of interfaces */
+ cancel_delayed_work_sync(&tcon->query_interfaces);
+
+ if (tcon->use_witness) {
+ int rc;
+
+ rc = cifs_swn_unregister(tcon);
+ if (rc < 0) {
+ cifs_dbg(VFS, "%s: Failed to unregister for witness notifications: %d\n",
+ __func__, rc);
+ }
+ }
+
+ xid = get_xid();
+ if (ses->server->ops->tree_disconnect)
+ ses->server->ops->tree_disconnect(xid, tcon);
+ _free_xid(xid);
+
+ cifs_fscache_release_super_cookie(tcon);
+ tconInfoFree(tcon);
+ cifs_put_smb_ses(ses);
+}
+
+/**
+ * cifs_get_tcon - get a tcon matching @ctx data from @ses
+ * @ses: smb session to issue the request on
+ * @ctx: the superblock configuration context to use for building the
+ *
+ * - tcon refcount is the number of mount points using the tcon.
+ * - ses refcount is the number of tcon using the session.
+ *
+ * 1. This function assumes it is being called from cifs_mount() where
+ * we already got a session reference (ses refcount +1).
+ *
+ * 2. Since we're in the context of adding a mount point, the end
+ * result should be either:
+ *
+ * a) a new tcon already allocated with refcount=1 (1 mount point) and
+ * its session refcount incremented (1 new tcon). This +1 was
+ * already done in (1).
+ *
+ * b) an existing tcon with refcount+1 (add a mount point to it) and
+ * identical ses refcount (no new tcon). Because of (1) we need to
+ * decrement the ses refcount.
+ */
+static struct cifs_tcon *
+cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
+{
+ int rc, xid;
+ struct cifs_tcon *tcon;
+
+ tcon = cifs_find_tcon(ses, ctx);
+ if (tcon) {
+ /*
+ * tcon has refcount already incremented but we need to
+ * decrement extra ses reference gotten by caller (case b)
+ */
+ cifs_dbg(FYI, "Found match on UNC path\n");
+ cifs_put_smb_ses(ses);
+ return tcon;
+ }
+
+ if (!ses->server->ops->tree_connect) {
+ rc = -ENOSYS;
+ goto out_fail;
+ }
+
+ tcon = tconInfoAlloc();
+ if (tcon == NULL) {
+ rc = -ENOMEM;
+ goto out_fail;
+ }
+
+ if (ctx->snapshot_time) {
+ if (ses->server->vals->protocol_id == 0) {
+ cifs_dbg(VFS,
+ "Use SMB2 or later for snapshot mount option\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ } else
+ tcon->snapshot_time = ctx->snapshot_time;
+ }
+
+ if (ctx->handle_timeout) {
+ if (ses->server->vals->protocol_id == 0) {
+ cifs_dbg(VFS,
+ "Use SMB2.1 or later for handle timeout option\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ } else
+ tcon->handle_timeout = ctx->handle_timeout;
+ }
+
+ tcon->ses = ses;
+ if (ctx->password) {
+ tcon->password = kstrdup(ctx->password, GFP_KERNEL);
+ if (!tcon->password) {
+ rc = -ENOMEM;
+ goto out_fail;
+ }
+ }
+
+ if (ctx->seal) {
+ if (ses->server->vals->protocol_id == 0) {
+ cifs_dbg(VFS,
+ "SMB3 or later required for encryption\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ } else if (tcon->ses->server->capabilities &
+ SMB2_GLOBAL_CAP_ENCRYPTION)
+ tcon->seal = true;
+ else {
+ cifs_dbg(VFS, "Encryption is not supported on share\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ }
+ }
+
+ if (ctx->linux_ext) {
+ if (ses->server->posix_ext_supported) {
+ tcon->posix_extensions = true;
+ pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
+ } else if ((ses->server->vals->protocol_id == SMB311_PROT_ID) ||
+ (strcmp(ses->server->vals->version_string,
+ SMB3ANY_VERSION_STRING) == 0) ||
+ (strcmp(ses->server->vals->version_string,
+ SMBDEFAULT_VERSION_STRING) == 0)) {
+ cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ } else {
+ cifs_dbg(VFS, "Check vers= mount option. SMB3.11 "
+ "disabled but required for POSIX extensions\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ }
+ }
+
+ xid = get_xid();
+ rc = ses->server->ops->tree_connect(xid, ses, ctx->UNC, tcon,
+ ctx->local_nls);
+ free_xid(xid);
+ cifs_dbg(FYI, "Tcon rc = %d\n", rc);
+ if (rc)
+ goto out_fail;
+
+ tcon->use_persistent = false;
+ /* check if SMB2 or later, CIFS does not support persistent handles */
+ if (ctx->persistent) {
+ if (ses->server->vals->protocol_id == 0) {
+ cifs_dbg(VFS,
+ "SMB3 or later required for persistent handles\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ } else if (ses->server->capabilities &
+ SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
+ tcon->use_persistent = true;
+ else /* persistent handles requested but not supported */ {
+ cifs_dbg(VFS,
+ "Persistent handles not supported on share\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ }
+ } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
+ && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
+ && (ctx->nopersistent == false)) {
+ cifs_dbg(FYI, "enabling persistent handles\n");
+ tcon->use_persistent = true;
+ } else if (ctx->resilient) {
+ if (ses->server->vals->protocol_id == 0) {
+ cifs_dbg(VFS,
+ "SMB2.1 or later required for resilient handles\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ }
+ tcon->use_resilient = true;
+ }
+
+ tcon->use_witness = false;
+ if (IS_ENABLED(CONFIG_CIFS_SWN_UPCALL) && ctx->witness) {
+ if (ses->server->vals->protocol_id >= SMB30_PROT_ID) {
+ if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER) {
+ /*
+ * Set witness in use flag in first place
+ * to retry registration in the echo task
+ */
+ tcon->use_witness = true;
+ /* And try to register immediately */
+ rc = cifs_swn_register(tcon);
+ if (rc < 0) {
+ cifs_dbg(VFS, "Failed to register for witness notifications: %d\n", rc);
+ goto out_fail;
+ }
+ } else {
+ /* TODO: try to extend for non-cluster uses (eg multichannel) */
+ cifs_dbg(VFS, "witness requested on mount but no CLUSTER capability on share\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ }
+ } else {
+ cifs_dbg(VFS, "SMB3 or later required for witness option\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ }
+ }
+
+ /* If the user really knows what they are doing they can override */
+ if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
+ if (ctx->cache_ro)
+ cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
+ else if (ctx->cache_rw)
+ cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
+ }
+
+ if (ctx->no_lease) {
+ if (ses->server->vals->protocol_id == 0) {
+ cifs_dbg(VFS,
+ "SMB2 or later required for nolease option\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ } else
+ tcon->no_lease = ctx->no_lease;
+ }
+
+ /*
+ * We can have only one retry value for a connection to a share so for
+ * resources mounted more than once to the same server share the last
+ * value passed in for the retry flag is used.
+ */
+ tcon->retry = ctx->retry;
+ tcon->nocase = ctx->nocase;
+ tcon->broken_sparse_sup = ctx->no_sparse;
+ if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
+ tcon->nohandlecache = ctx->nohandlecache;
+ else
+ tcon->nohandlecache = true;
+ tcon->nodelete = ctx->nodelete;
+ tcon->local_lease = ctx->local_lease;
+ INIT_LIST_HEAD(&tcon->pending_opens);
+ tcon->status = TID_GOOD;
+
+ INIT_DELAYED_WORK(&tcon->query_interfaces,
+ smb2_query_server_interfaces);
+ if (ses->server->dialect >= SMB30_PROT_ID &&
+ (ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
+ /* schedule query interfaces poll */
+ queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
+ (SMB_INTERFACE_POLL_INTERVAL * HZ));
+ }
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_add(&tcon->tcon_list, &ses->tcon_list);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ return tcon;
+
+out_fail:
+ tconInfoFree(tcon);
+ return ERR_PTR(rc);
+}
+
+void
+cifs_put_tlink(struct tcon_link *tlink)
+{
+ if (!tlink || IS_ERR(tlink))
+ return;
+
+ if (!atomic_dec_and_test(&tlink->tl_count) ||
+ test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
+ tlink->tl_time = jiffies;
+ return;
+ }
+
+ if (!IS_ERR(tlink_tcon(tlink)))
+ cifs_put_tcon(tlink_tcon(tlink));
+ kfree(tlink);
+ return;
+}
+
+static int
+compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
+{
+ struct cifs_sb_info *old = CIFS_SB(sb);
+ struct cifs_sb_info *new = mnt_data->cifs_sb;
+ unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
+ unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
+
+ if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
+ return 0;
+
+ if (old->mnt_cifs_serverino_autodisabled)
+ newflags &= ~CIFS_MOUNT_SERVER_INUM;
+
+ if (oldflags != newflags)
+ return 0;
+
+ /*
+ * We want to share sb only if we don't specify an r/wsize or
+ * specified r/wsize is greater than or equal to existing one.
+ */
+ if (new->ctx->wsize && new->ctx->wsize < old->ctx->wsize)
+ return 0;
+
+ if (new->ctx->rsize && new->ctx->rsize < old->ctx->rsize)
+ return 0;
+
+ if (!uid_eq(old->ctx->linux_uid, new->ctx->linux_uid) ||
+ !gid_eq(old->ctx->linux_gid, new->ctx->linux_gid))
+ return 0;
+
+ if (old->ctx->file_mode != new->ctx->file_mode ||
+ old->ctx->dir_mode != new->ctx->dir_mode)
+ return 0;
+
+ if (strcmp(old->local_nls->charset, new->local_nls->charset))
+ return 0;
+
+ if (old->ctx->acregmax != new->ctx->acregmax)
+ return 0;
+ if (old->ctx->acdirmax != new->ctx->acdirmax)
+ return 0;
+ if (old->ctx->closetimeo != new->ctx->closetimeo)
+ return 0;
+
+ return 1;
+}
+
+static int
+match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
+{
+ struct cifs_sb_info *old = CIFS_SB(sb);
+ struct cifs_sb_info *new = mnt_data->cifs_sb;
+ bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
+ old->prepath;
+ bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
+ new->prepath;
+
+ if (old_set && new_set && !strcmp(new->prepath, old->prepath))
+ return 1;
+ else if (!old_set && !new_set)
+ return 1;
+
+ return 0;
+}
+
+int
+cifs_match_super(struct super_block *sb, void *data)
+{
+ struct cifs_mnt_data *mnt_data = data;
+ struct smb3_fs_context *ctx;
+ struct cifs_sb_info *cifs_sb;
+ struct TCP_Server_Info *tcp_srv;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+ struct tcon_link *tlink;
+ int rc = 0;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ cifs_sb = CIFS_SB(sb);
+
+ /* We do not want to use a superblock that has been shutdown */
+ if (CIFS_MOUNT_SHUTDOWN & cifs_sb->mnt_cifs_flags) {
+ spin_unlock(&cifs_tcp_ses_lock);
+ return 0;
+ }
+
+ tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
+ if (tlink == NULL) {
+ /* can not match superblock if tlink were ever null */
+ spin_unlock(&cifs_tcp_ses_lock);
+ return 0;
+ }
+ tcon = tlink_tcon(tlink);
+ ses = tcon->ses;
+ tcp_srv = ses->server;
+
+ ctx = mnt_data->ctx;
+
+ spin_lock(&tcp_srv->srv_lock);
+ spin_lock(&ses->ses_lock);
+ spin_lock(&ses->chan_lock);
+ spin_lock(&tcon->tc_lock);
+ if (!match_server(tcp_srv, ctx) ||
+ !match_session(ses, ctx) ||
+ !match_tcon(tcon, ctx) ||
+ !match_prepath(sb, mnt_data)) {
+ rc = 0;
+ goto out;
+ }
+
+ rc = compare_mount_options(sb, mnt_data);
+out:
+ spin_unlock(&tcon->tc_lock);
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+ spin_unlock(&tcp_srv->srv_lock);
+
+ spin_unlock(&cifs_tcp_ses_lock);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+static struct lock_class_key cifs_key[2];
+static struct lock_class_key cifs_slock_key[2];
+
+static inline void
+cifs_reclassify_socket4(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ BUG_ON(!sock_allow_reclassification(sk));
+ sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
+ &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
+}
+
+static inline void
+cifs_reclassify_socket6(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ BUG_ON(!sock_allow_reclassification(sk));
+ sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
+ &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
+}
+#else
+static inline void
+cifs_reclassify_socket4(struct socket *sock)
+{
+}
+
+static inline void
+cifs_reclassify_socket6(struct socket *sock)
+{
+}
+#endif
+
+/* See RFC1001 section 14 on representation of Netbios names */
+static void rfc1002mangle(char *target, char *source, unsigned int length)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; i < (length); i++) {
+ /* mask a nibble at a time and encode */
+ target[j] = 'A' + (0x0F & (source[i] >> 4));
+ target[j+1] = 'A' + (0x0F & source[i]);
+ j += 2;
+ }
+
+}
+
+static int
+bind_socket(struct TCP_Server_Info *server)
+{
+ int rc = 0;
+ if (server->srcaddr.ss_family != AF_UNSPEC) {
+ /* Bind to the specified local IP address */
+ struct socket *socket = server->ssocket;
+ rc = socket->ops->bind(socket,
+ (struct sockaddr *) &server->srcaddr,
+ sizeof(server->srcaddr));
+ if (rc < 0) {
+ struct sockaddr_in *saddr4;
+ struct sockaddr_in6 *saddr6;
+ saddr4 = (struct sockaddr_in *)&server->srcaddr;
+ saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
+ if (saddr6->sin6_family == AF_INET6)
+ cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
+ &saddr6->sin6_addr, rc);
+ else
+ cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
+ &saddr4->sin_addr.s_addr, rc);
+ }
+ }
+ return rc;
+}
+
+static int
+ip_rfc1001_connect(struct TCP_Server_Info *server)
+{
+ int rc = 0;
+ /*
+ * some servers require RFC1001 sessinit before sending
+ * negprot - BB check reconnection in case where second
+ * sessinit is sent but no second negprot
+ */
+ struct rfc1002_session_packet req = {};
+ struct smb_hdr *smb_buf = (struct smb_hdr *)&req;
+ unsigned int len;
+
+ req.trailer.session_req.called_len = sizeof(req.trailer.session_req.called_name);
+
+ if (server->server_RFC1001_name[0] != 0)
+ rfc1002mangle(req.trailer.session_req.called_name,
+ server->server_RFC1001_name,
+ RFC1001_NAME_LEN_WITH_NULL);
+ else
+ rfc1002mangle(req.trailer.session_req.called_name,
+ DEFAULT_CIFS_CALLED_NAME,
+ RFC1001_NAME_LEN_WITH_NULL);
+
+ req.trailer.session_req.calling_len = sizeof(req.trailer.session_req.calling_name);
+
+ /* calling name ends in null (byte 16) from old smb convention */
+ if (server->workstation_RFC1001_name[0] != 0)
+ rfc1002mangle(req.trailer.session_req.calling_name,
+ server->workstation_RFC1001_name,
+ RFC1001_NAME_LEN_WITH_NULL);
+ else
+ rfc1002mangle(req.trailer.session_req.calling_name,
+ "LINUX_CIFS_CLNT",
+ RFC1001_NAME_LEN_WITH_NULL);
+
+ /*
+ * As per rfc1002, @len must be the number of bytes that follows the
+ * length field of a rfc1002 session request payload.
+ */
+ len = sizeof(req) - offsetof(struct rfc1002_session_packet, trailer.session_req);
+
+ smb_buf->smb_buf_length = cpu_to_be32((RFC1002_SESSION_REQUEST << 24) | len);
+ rc = smb_send(server, smb_buf, len);
+ /*
+ * RFC1001 layer in at least one server requires very short break before
+ * negprot presumably because not expecting negprot to follow so fast.
+ * This is a simple solution that works without complicating the code
+ * and causes no significant slowing down on mount for everyone else
+ */
+ usleep_range(1000, 2000);
+
+ return rc;
+}
+
+static int
+generic_ip_connect(struct TCP_Server_Info *server)
+{
+ int rc = 0;
+ __be16 sport;
+ int slen, sfamily;
+ struct socket *socket = server->ssocket;
+ struct sockaddr *saddr;
+
+ saddr = (struct sockaddr *) &server->dstaddr;
+
+ if (server->dstaddr.ss_family == AF_INET6) {
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr;
+
+ sport = ipv6->sin6_port;
+ slen = sizeof(struct sockaddr_in6);
+ sfamily = AF_INET6;
+ cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr,
+ ntohs(sport));
+ } else {
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr;
+
+ sport = ipv4->sin_port;
+ slen = sizeof(struct sockaddr_in);
+ sfamily = AF_INET;
+ cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr,
+ ntohs(sport));
+ }
+
+ if (socket == NULL) {
+ rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
+ IPPROTO_TCP, &socket, 1);
+ if (rc < 0) {
+ cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
+ server->ssocket = NULL;
+ return rc;
+ }
+
+ /* BB other socket options to set KEEPALIVE, NODELAY? */
+ cifs_dbg(FYI, "Socket created\n");
+ server->ssocket = socket;
+ socket->sk->sk_allocation = GFP_NOFS;
+ if (sfamily == AF_INET6)
+ cifs_reclassify_socket6(socket);
+ else
+ cifs_reclassify_socket4(socket);
+ }
+
+ rc = bind_socket(server);
+ if (rc < 0)
+ return rc;
+
+ /*
+ * Eventually check for other socket options to change from
+ * the default. sock_setsockopt not used because it expects
+ * user space buffer
+ */
+ socket->sk->sk_rcvtimeo = 7 * HZ;
+ socket->sk->sk_sndtimeo = 5 * HZ;
+
+ /* make the bufsizes depend on wsize/rsize and max requests */
+ if (server->noautotune) {
+ if (socket->sk->sk_sndbuf < (200 * 1024))
+ socket->sk->sk_sndbuf = 200 * 1024;
+ if (socket->sk->sk_rcvbuf < (140 * 1024))
+ socket->sk->sk_rcvbuf = 140 * 1024;
+ }
+
+ if (server->tcp_nodelay)
+ tcp_sock_set_nodelay(socket->sk);
+
+ cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
+ socket->sk->sk_sndbuf,
+ socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
+
+ rc = socket->ops->connect(socket, saddr, slen,
+ server->noblockcnt ? O_NONBLOCK : 0);
+ /*
+ * When mounting SMB root file systems, we do not want to block in
+ * connect. Otherwise bail out and then let cifs_reconnect() perform
+ * reconnect failover - if possible.
+ */
+ if (server->noblockcnt && rc == -EINPROGRESS)
+ rc = 0;
+ if (rc < 0) {
+ cifs_dbg(FYI, "Error %d connecting to server\n", rc);
+ trace_smb3_connect_err(server->hostname, server->conn_id, &server->dstaddr, rc);
+ sock_release(socket);
+ server->ssocket = NULL;
+ return rc;
+ }
+ trace_smb3_connect_done(server->hostname, server->conn_id, &server->dstaddr);
+ if (sport == htons(RFC1001_PORT))
+ rc = ip_rfc1001_connect(server);
+
+ return rc;
+}
+
+static int
+ip_connect(struct TCP_Server_Info *server)
+{
+ __be16 *sport;
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
+ struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
+
+ if (server->dstaddr.ss_family == AF_INET6)
+ sport = &addr6->sin6_port;
+ else
+ sport = &addr->sin_port;
+
+ if (*sport == 0) {
+ int rc;
+
+ /* try with 445 port at first */
+ *sport = htons(CIFS_PORT);
+
+ rc = generic_ip_connect(server);
+ if (rc >= 0)
+ return rc;
+
+ /* if it failed, try with 139 port */
+ *sport = htons(RFC1001_PORT);
+ }
+
+ return generic_ip_connect(server);
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
+{
+ /*
+ * If we are reconnecting then should we check to see if
+ * any requested capabilities changed locally e.g. via
+ * remount but we can not do much about it here
+ * if they have (even if we could detect it by the following)
+ * Perhaps we could add a backpointer to array of sb from tcon
+ * or if we change to make all sb to same share the same
+ * sb as NFS - then we only have one backpointer to sb.
+ * What if we wanted to mount the server share twice once with
+ * and once without posixacls or posix paths?
+ */
+ __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
+
+ if (ctx && ctx->no_linux_ext) {
+ tcon->fsUnixInfo.Capability = 0;
+ tcon->unix_ext = 0; /* Unix Extensions disabled */
+ cifs_dbg(FYI, "Linux protocol extensions disabled\n");
+ return;
+ } else if (ctx)
+ tcon->unix_ext = 1; /* Unix Extensions supported */
+
+ if (!tcon->unix_ext) {
+ cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
+ return;
+ }
+
+ if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
+ __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
+ cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
+ /*
+ * check for reconnect case in which we do not
+ * want to change the mount behavior if we can avoid it
+ */
+ if (ctx == NULL) {
+ /*
+ * turn off POSIX ACL and PATHNAMES if not set
+ * originally at mount time
+ */
+ if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
+ cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+ if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
+ if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
+ cifs_dbg(VFS, "POSIXPATH support change\n");
+ cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
+ } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
+ cifs_dbg(VFS, "possible reconnect error\n");
+ cifs_dbg(VFS, "server disabled POSIX path support\n");
+ }
+ }
+
+ if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
+ cifs_dbg(VFS, "per-share encryption not supported yet\n");
+
+ cap &= CIFS_UNIX_CAP_MASK;
+ if (ctx && ctx->no_psx_acl)
+ cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+ else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
+ cifs_dbg(FYI, "negotiated posix acl support\n");
+ if (cifs_sb)
+ cifs_sb->mnt_cifs_flags |=
+ CIFS_MOUNT_POSIXACL;
+ }
+
+ if (ctx && ctx->posix_paths == 0)
+ cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
+ else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+ cifs_dbg(FYI, "negotiate posix pathnames\n");
+ if (cifs_sb)
+ cifs_sb->mnt_cifs_flags |=
+ CIFS_MOUNT_POSIX_PATHS;
+ }
+
+ cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
+#ifdef CONFIG_CIFS_DEBUG2
+ if (cap & CIFS_UNIX_FCNTL_CAP)
+ cifs_dbg(FYI, "FCNTL cap\n");
+ if (cap & CIFS_UNIX_EXTATTR_CAP)
+ cifs_dbg(FYI, "EXTATTR cap\n");
+ if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
+ cifs_dbg(FYI, "POSIX path cap\n");
+ if (cap & CIFS_UNIX_XATTR_CAP)
+ cifs_dbg(FYI, "XATTR cap\n");
+ if (cap & CIFS_UNIX_POSIX_ACL_CAP)
+ cifs_dbg(FYI, "POSIX ACL cap\n");
+ if (cap & CIFS_UNIX_LARGE_READ_CAP)
+ cifs_dbg(FYI, "very large read cap\n");
+ if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
+ cifs_dbg(FYI, "very large write cap\n");
+ if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
+ cifs_dbg(FYI, "transport encryption cap\n");
+ if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
+ cifs_dbg(FYI, "mandatory transport encryption cap\n");
+#endif /* CIFS_DEBUG2 */
+ if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
+ if (ctx == NULL)
+ cifs_dbg(FYI, "resetting capabilities failed\n");
+ else
+ cifs_dbg(VFS, "Negotiating Unix capabilities with the server failed. Consider mounting with the Unix Extensions disabled if problems are found by specifying the nounix mount option.\n");
+
+ }
+ }
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
+{
+ struct smb3_fs_context *ctx = cifs_sb->ctx;
+
+ INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
+
+ spin_lock_init(&cifs_sb->tlink_tree_lock);
+ cifs_sb->tlink_tree = RB_ROOT;
+
+ cifs_dbg(FYI, "file mode: %04ho dir mode: %04ho\n",
+ ctx->file_mode, ctx->dir_mode);
+
+ /* this is needed for ASCII cp to Unicode converts */
+ if (ctx->iocharset == NULL) {
+ /* load_nls_default cannot return null */
+ cifs_sb->local_nls = load_nls_default();
+ } else {
+ cifs_sb->local_nls = load_nls(ctx->iocharset);
+ if (cifs_sb->local_nls == NULL) {
+ cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
+ ctx->iocharset);
+ return -ELIBACC;
+ }
+ }
+ ctx->local_nls = cifs_sb->local_nls;
+
+ smb3_update_mnt_flags(cifs_sb);
+
+ if (ctx->direct_io)
+ cifs_dbg(FYI, "mounting share using direct i/o\n");
+ if (ctx->cache_ro) {
+ cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
+ } else if (ctx->cache_rw) {
+ cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
+ cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
+ CIFS_MOUNT_RW_CACHE);
+ }
+
+ if ((ctx->cifs_acl) && (ctx->dynperm))
+ cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
+
+ if (ctx->prepath) {
+ cifs_sb->prepath = kstrdup(ctx->prepath, GFP_KERNEL);
+ if (cifs_sb->prepath == NULL)
+ return -ENOMEM;
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
+ }
+
+ return 0;
+}
+
+/* Release all succeed connections */
+static inline void mount_put_conns(struct mount_ctx *mnt_ctx)
+{
+ int rc = 0;
+
+ if (mnt_ctx->tcon)
+ cifs_put_tcon(mnt_ctx->tcon);
+ else if (mnt_ctx->ses)
+ cifs_put_smb_ses(mnt_ctx->ses);
+ else if (mnt_ctx->server)
+ cifs_put_tcp_session(mnt_ctx->server, 0);
+ mnt_ctx->cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
+ free_xid(mnt_ctx->xid);
+}
+
+/* Get connections for tcp, ses and tcon */
+static int mount_get_conns(struct mount_ctx *mnt_ctx)
+{
+ int rc = 0;
+ struct TCP_Server_Info *server = NULL;
+ struct cifs_ses *ses = NULL;
+ struct cifs_tcon *tcon = NULL;
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+ struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
+ unsigned int xid;
+
+ xid = get_xid();
+
+ /* get a reference to a tcp session */
+ server = cifs_get_tcp_session(ctx, NULL);
+ if (IS_ERR(server)) {
+ rc = PTR_ERR(server);
+ server = NULL;
+ goto out;
+ }
+
+ /* get a reference to a SMB session */
+ ses = cifs_get_smb_ses(server, ctx);
+ if (IS_ERR(ses)) {
+ rc = PTR_ERR(ses);
+ ses = NULL;
+ goto out;
+ }
+
+ if ((ctx->persistent == true) && (!(ses->server->capabilities &
+ SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
+ cifs_server_dbg(VFS, "persistent handles not supported by server\n");
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* search for existing tcon to this server share */
+ tcon = cifs_get_tcon(ses, ctx);
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ tcon = NULL;
+ goto out;
+ }
+
+ /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
+ if (tcon->posix_extensions)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ /* tell server which Unix caps we support */
+ if (cap_unix(tcon->ses)) {
+ /*
+ * reset of caps checks mount to see if unix extensions disabled
+ * for just this mount.
+ */
+ reset_cifs_unix_caps(xid, tcon, cifs_sb, ctx);
+ spin_lock(&tcon->ses->server->srv_lock);
+ if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
+ (le64_to_cpu(tcon->fsUnixInfo.Capability) &
+ CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
+ spin_unlock(&tcon->ses->server->srv_lock);
+ rc = -EACCES;
+ goto out;
+ }
+ spin_unlock(&tcon->ses->server->srv_lock);
+ } else
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ tcon->unix_ext = 0; /* server does not support them */
+
+ /* do not care if a following call succeed - informational */
+ if (!tcon->pipe && server->ops->qfs_tcon) {
+ server->ops->qfs_tcon(xid, tcon, cifs_sb);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
+ if (tcon->fsDevInfo.DeviceCharacteristics &
+ cpu_to_le32(FILE_READ_ONLY_DEVICE))
+ cifs_dbg(VFS, "mounted to read only share\n");
+ else if ((cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_RW_CACHE) == 0)
+ cifs_dbg(VFS, "read only mount of RW share\n");
+ /* no need to log a RW mount of a typical RW share */
+ }
+ }
+
+ /*
+ * Clamp the rsize/wsize mount arguments if they are too big for the server
+ * and set the rsize/wsize to the negotiated values if not passed in by
+ * the user on mount
+ */
+ if ((cifs_sb->ctx->wsize == 0) ||
+ (cifs_sb->ctx->wsize > server->ops->negotiate_wsize(tcon, ctx)))
+ cifs_sb->ctx->wsize = server->ops->negotiate_wsize(tcon, ctx);
+ if ((cifs_sb->ctx->rsize == 0) ||
+ (cifs_sb->ctx->rsize > server->ops->negotiate_rsize(tcon, ctx)))
+ cifs_sb->ctx->rsize = server->ops->negotiate_rsize(tcon, ctx);
+
+ /*
+ * The cookie is initialized from volume info returned above.
+ * Inside cifs_fscache_get_super_cookie it checks
+ * that we do not get super cookie twice.
+ */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
+ cifs_fscache_get_super_cookie(tcon);
+
+out:
+ mnt_ctx->server = server;
+ mnt_ctx->ses = ses;
+ mnt_ctx->tcon = tcon;
+ mnt_ctx->xid = xid;
+
+ return rc;
+}
+
+static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
+ struct cifs_tcon *tcon)
+{
+ struct tcon_link *tlink;
+
+ /* hang the tcon off of the superblock */
+ tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
+ if (tlink == NULL)
+ return -ENOMEM;
+
+ tlink->tl_uid = ses->linux_uid;
+ tlink->tl_tcon = tcon;
+ tlink->tl_time = jiffies;
+ set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
+ set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
+
+ cifs_sb->master_tlink = tlink;
+ spin_lock(&cifs_sb->tlink_tree_lock);
+ tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+
+ queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
+ TLINK_IDLE_EXPIRE);
+ return 0;
+}
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+/* Get unique dfs connections */
+static int mount_get_dfs_conns(struct mount_ctx *mnt_ctx)
+{
+ int rc;
+
+ mnt_ctx->fs_ctx->nosharesock = true;
+ rc = mount_get_conns(mnt_ctx);
+ if (mnt_ctx->server) {
+ cifs_dbg(FYI, "%s: marking tcp session as a dfs connection\n", __func__);
+ spin_lock(&mnt_ctx->server->srv_lock);
+ mnt_ctx->server->is_dfs_conn = true;
+ spin_unlock(&mnt_ctx->server->srv_lock);
+ }
+ return rc;
+}
+
+/*
+ * cifs_build_path_to_root returns full path to root when we do not have an
+ * existing connection (tcon)
+ */
+static char *
+build_unc_path_to_root(const struct smb3_fs_context *ctx,
+ const struct cifs_sb_info *cifs_sb, bool useppath)
+{
+ char *full_path, *pos;
+ unsigned int pplen = useppath && ctx->prepath ?
+ strlen(ctx->prepath) + 1 : 0;
+ unsigned int unc_len = strnlen(ctx->UNC, MAX_TREE_SIZE + 1);
+
+ if (unc_len > MAX_TREE_SIZE)
+ return ERR_PTR(-EINVAL);
+
+ full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
+ if (full_path == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(full_path, ctx->UNC, unc_len);
+ pos = full_path + unc_len;
+
+ if (pplen) {
+ *pos = CIFS_DIR_SEP(cifs_sb);
+ memcpy(pos + 1, ctx->prepath, pplen);
+ pos += pplen;
+ }
+
+ *pos = '\0'; /* add trailing null */
+ convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
+ cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
+ return full_path;
+}
+
+/*
+ * expand_dfs_referral - Update cifs_sb from dfs referral path
+ *
+ * cifs_sb->ctx->mount_options will be (re-)allocated to a string containing updated options for the
+ * submount. Otherwise it will be left untouched.
+ */
+static int expand_dfs_referral(struct mount_ctx *mnt_ctx, const char *full_path,
+ struct dfs_info3_param *referral)
+{
+ int rc;
+ struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+ char *fake_devname = NULL, *mdata = NULL;
+
+ mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, full_path + 1, referral,
+ &fake_devname);
+ if (IS_ERR(mdata)) {
+ rc = PTR_ERR(mdata);
+ mdata = NULL;
+ } else {
+ /*
+ * We can not clear out the whole structure since we no longer have an explicit
+ * function to parse a mount-string. Instead we need to clear out the individual
+ * fields that are no longer valid.
+ */
+ kfree(ctx->prepath);
+ ctx->prepath = NULL;
+ rc = cifs_setup_volume_info(ctx, mdata, fake_devname);
+ }
+ kfree(fake_devname);
+ kfree(cifs_sb->ctx->mount_options);
+ cifs_sb->ctx->mount_options = mdata;
+
+ return rc;
+}
+#endif
+
+/* TODO: all callers to this are broken. We are not parsing mount_options here
+ * we should pass a clone of the original context?
+ */
+int
+cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname)
+{
+ int rc;
+
+ if (devname) {
+ cifs_dbg(FYI, "%s: devname=%s\n", __func__, devname);
+ rc = smb3_parse_devname(devname, ctx);
+ if (rc) {
+ cifs_dbg(VFS, "%s: failed to parse %s: %d\n", __func__, devname, rc);
+ return rc;
+ }
+ }
+
+ if (mntopts) {
+ char *ip;
+
+ rc = smb3_parse_opt(mntopts, "ip", &ip);
+ if (rc) {
+ cifs_dbg(VFS, "%s: failed to parse ip options: %d\n", __func__, rc);
+ return rc;
+ }
+
+ rc = cifs_convert_address((struct sockaddr *)&ctx->dstaddr, ip, strlen(ip));
+ kfree(ip);
+ if (!rc) {
+ cifs_dbg(VFS, "%s: failed to convert ip address\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (ctx->nullauth) {
+ cifs_dbg(FYI, "Anonymous login\n");
+ kfree(ctx->username);
+ ctx->username = NULL;
+ } else if (ctx->username) {
+ /* BB fixme parse for domain name here */
+ cifs_dbg(FYI, "Username: %s\n", ctx->username);
+ } else {
+ cifs_dbg(VFS, "No username specified\n");
+ /* In userspace mount helper we can get user name from alternate
+ locations such as env variables and files on disk */
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
+ unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ char *full_path,
+ int added_treename)
+{
+ int rc;
+ char *s;
+ char sep, tmp;
+ int skip = added_treename ? 1 : 0;
+
+ sep = CIFS_DIR_SEP(cifs_sb);
+ s = full_path;
+
+ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
+ while (rc == 0) {
+ /* skip separators */
+ while (*s == sep)
+ s++;
+ if (!*s)
+ break;
+ /* next separator */
+ while (*s && *s != sep)
+ s++;
+ /*
+ * if the treename is added, we then have to skip the first
+ * part within the separators
+ */
+ if (skip) {
+ skip = 0;
+ continue;
+ }
+ /*
+ * temporarily null-terminate the path at the end of
+ * the current component
+ */
+ tmp = *s;
+ *s = 0;
+ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
+ full_path);
+ *s = tmp;
+ }
+ return rc;
+}
+
+/*
+ * Check if path is remote (i.e. a DFS share).
+ *
+ * Return -EREMOTE if it is, otherwise 0 or -errno.
+ */
+static int is_path_remote(struct mount_ctx *mnt_ctx)
+{
+ int rc;
+ struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
+ struct TCP_Server_Info *server = mnt_ctx->server;
+ unsigned int xid = mnt_ctx->xid;
+ struct cifs_tcon *tcon = mnt_ctx->tcon;
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+ char *full_path;
+
+ if (!server->ops->is_path_accessible)
+ return -EOPNOTSUPP;
+
+ /*
+ * cifs_build_path_to_root works only when we have a valid tcon
+ */
+ full_path = cifs_build_path_to_root(ctx, cifs_sb, tcon,
+ tcon->Flags & SMB_SHARE_IS_IN_DFS);
+ if (full_path == NULL)
+ return -ENOMEM;
+
+ cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
+
+ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
+ full_path);
+ if (rc != 0 && rc != -EREMOTE)
+ goto out;
+
+ if (rc != -EREMOTE) {
+ rc = cifs_are_all_path_components_accessible(server, xid, tcon,
+ cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
+ if (rc != 0) {
+ cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
+ rc = 0;
+ }
+ }
+
+out:
+ kfree(full_path);
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+static void set_root_ses(struct mount_ctx *mnt_ctx)
+{
+ if (mnt_ctx->ses) {
+ spin_lock(&cifs_tcp_ses_lock);
+ mnt_ctx->ses->ses_count++;
+ spin_unlock(&cifs_tcp_ses_lock);
+ dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, mnt_ctx->ses);
+ }
+ mnt_ctx->root_ses = mnt_ctx->ses;
+}
+
+static int is_dfs_mount(struct mount_ctx *mnt_ctx, bool *isdfs, struct dfs_cache_tgt_list *root_tl)
+{
+ int rc;
+ struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+
+ *isdfs = true;
+
+ rc = mount_get_conns(mnt_ctx);
+ /*
+ * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally
+ * try to get an DFS referral (even cached) to determine whether it is an DFS mount.
+ *
+ * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem
+ * to respond with PATH_NOT_COVERED to requests that include the prefix.
+ */
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) ||
+ dfs_cache_find(mnt_ctx->xid, mnt_ctx->ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
+ ctx->UNC + 1, NULL, root_tl)) {
+ if (rc)
+ return rc;
+ /* Check if it is fully accessible and then mount it */
+ rc = is_path_remote(mnt_ctx);
+ if (!rc)
+ *isdfs = false;
+ else if (rc != -EREMOTE)
+ return rc;
+ }
+ return 0;
+}
+
+static int connect_dfs_target(struct mount_ctx *mnt_ctx, const char *full_path,
+ const char *ref_path, struct dfs_cache_tgt_iterator *tit)
+{
+ int rc;
+ struct dfs_info3_param ref = {};
+ struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
+ char *oldmnt = cifs_sb->ctx->mount_options;
+
+ cifs_dbg(FYI, "%s: full_path=%s ref_path=%s target=%s\n", __func__, full_path, ref_path,
+ dfs_cache_get_tgt_name(tit));
+
+ rc = dfs_cache_get_tgt_referral(ref_path, tit, &ref);
+ if (rc)
+ goto out;
+
+ rc = expand_dfs_referral(mnt_ctx, full_path, &ref);
+ if (rc)
+ goto out;
+
+ /* Connect to new target only if we were redirected (e.g. mount options changed) */
+ if (oldmnt != cifs_sb->ctx->mount_options) {
+ mount_put_conns(mnt_ctx);
+ rc = mount_get_dfs_conns(mnt_ctx);
+ }
+ if (!rc) {
+ if (cifs_is_referral_server(mnt_ctx->tcon, &ref))
+ set_root_ses(mnt_ctx);
+ rc = dfs_cache_update_tgthint(mnt_ctx->xid, mnt_ctx->root_ses, cifs_sb->local_nls,
+ cifs_remap(cifs_sb), ref_path, tit);
+ }
+
+out:
+ free_dfs_info_param(&ref);
+ return rc;
+}
+
+static int connect_dfs_root(struct mount_ctx *mnt_ctx, struct dfs_cache_tgt_list *root_tl)
+{
+ int rc;
+ char *full_path;
+ struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+ struct dfs_cache_tgt_iterator *tit;
+
+ /* Put initial connections as they might be shared with other mounts. We need unique dfs
+ * connections per mount to properly failover, so mount_get_dfs_conns() must be used from
+ * now on.
+ */
+ mount_put_conns(mnt_ctx);
+ mount_get_dfs_conns(mnt_ctx);
+ set_root_ses(mnt_ctx);
+
+ full_path = build_unc_path_to_root(ctx, cifs_sb, true);
+ if (IS_ERR(full_path))
+ return PTR_ERR(full_path);
+
+ mnt_ctx->origin_fullpath = dfs_cache_canonical_path(ctx->UNC, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ if (IS_ERR(mnt_ctx->origin_fullpath)) {
+ rc = PTR_ERR(mnt_ctx->origin_fullpath);
+ mnt_ctx->origin_fullpath = NULL;
+ goto out;
+ }
+
+ /* Try all dfs root targets */
+ for (rc = -ENOENT, tit = dfs_cache_get_tgt_iterator(root_tl);
+ tit; tit = dfs_cache_get_next_tgt(root_tl, tit)) {
+ rc = connect_dfs_target(mnt_ctx, full_path, mnt_ctx->origin_fullpath + 1, tit);
+ if (!rc) {
+ mnt_ctx->leaf_fullpath = kstrdup(mnt_ctx->origin_fullpath, GFP_KERNEL);
+ if (!mnt_ctx->leaf_fullpath)
+ rc = -ENOMEM;
+ break;
+ }
+ }
+
+out:
+ kfree(full_path);
+ return rc;
+}
+
+static int __follow_dfs_link(struct mount_ctx *mnt_ctx)
+{
+ int rc;
+ struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+ char *full_path;
+ struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
+ struct dfs_cache_tgt_iterator *tit;
+
+ full_path = build_unc_path_to_root(ctx, cifs_sb, true);
+ if (IS_ERR(full_path))
+ return PTR_ERR(full_path);
+
+ kfree(mnt_ctx->leaf_fullpath);
+ mnt_ctx->leaf_fullpath = dfs_cache_canonical_path(full_path, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ if (IS_ERR(mnt_ctx->leaf_fullpath)) {
+ rc = PTR_ERR(mnt_ctx->leaf_fullpath);
+ mnt_ctx->leaf_fullpath = NULL;
+ goto out;
+ }
+
+ /* Get referral from dfs link */
+ rc = dfs_cache_find(mnt_ctx->xid, mnt_ctx->root_ses, cifs_sb->local_nls,
+ cifs_remap(cifs_sb), mnt_ctx->leaf_fullpath + 1, NULL, &tl);
+ if (rc)
+ goto out;
+
+ /* Try all dfs link targets. If an I/O fails from currently connected DFS target with an
+ * error other than STATUS_PATH_NOT_COVERED (-EREMOTE), then retry it from other targets as
+ * specified in MS-DFSC "3.1.5.2 I/O Operation to Target Fails with an Error Other Than
+ * STATUS_PATH_NOT_COVERED."
+ */
+ for (rc = -ENOENT, tit = dfs_cache_get_tgt_iterator(&tl);
+ tit; tit = dfs_cache_get_next_tgt(&tl, tit)) {
+ rc = connect_dfs_target(mnt_ctx, full_path, mnt_ctx->leaf_fullpath + 1, tit);
+ if (!rc) {
+ rc = is_path_remote(mnt_ctx);
+ if (!rc || rc == -EREMOTE)
+ break;
+ }
+ }
+
+out:
+ kfree(full_path);
+ dfs_cache_free_tgts(&tl);
+ return rc;
+}
+
+static int follow_dfs_link(struct mount_ctx *mnt_ctx)
+{
+ int rc;
+ struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+ char *full_path;
+ int num_links = 0;
+
+ full_path = build_unc_path_to_root(ctx, cifs_sb, true);
+ if (IS_ERR(full_path))
+ return PTR_ERR(full_path);
+
+ kfree(mnt_ctx->origin_fullpath);
+ mnt_ctx->origin_fullpath = dfs_cache_canonical_path(full_path, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ kfree(full_path);
+
+ if (IS_ERR(mnt_ctx->origin_fullpath)) {
+ rc = PTR_ERR(mnt_ctx->origin_fullpath);
+ mnt_ctx->origin_fullpath = NULL;
+ return rc;
+ }
+
+ do {
+ rc = __follow_dfs_link(mnt_ctx);
+ if (!rc || rc != -EREMOTE)
+ break;
+ } while (rc = -ELOOP, ++num_links < MAX_NESTED_LINKS);
+
+ return rc;
+}
+
+/* Set up DFS referral paths for failover */
+static void setup_server_referral_paths(struct mount_ctx *mnt_ctx)
+{
+ struct TCP_Server_Info *server = mnt_ctx->server;
+
+ mutex_lock(&server->refpath_lock);
+ server->origin_fullpath = mnt_ctx->origin_fullpath;
+ server->leaf_fullpath = mnt_ctx->leaf_fullpath;
+ server->current_fullpath = mnt_ctx->leaf_fullpath;
+ mutex_unlock(&server->refpath_lock);
+ mnt_ctx->origin_fullpath = mnt_ctx->leaf_fullpath = NULL;
+}
+
+int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
+{
+ int rc;
+ struct mount_ctx mnt_ctx = { .cifs_sb = cifs_sb, .fs_ctx = ctx, };
+ struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
+ bool isdfs;
+
+ rc = is_dfs_mount(&mnt_ctx, &isdfs, &tl);
+ if (rc)
+ goto error;
+ if (!isdfs)
+ goto out;
+
+ /* proceed as DFS mount */
+ uuid_gen(&mnt_ctx.mount_id);
+ rc = connect_dfs_root(&mnt_ctx, &tl);
+ dfs_cache_free_tgts(&tl);
+
+ if (rc)
+ goto error;
+
+ rc = is_path_remote(&mnt_ctx);
+ if (rc)
+ rc = follow_dfs_link(&mnt_ctx);
+ if (rc)
+ goto error;
+
+ setup_server_referral_paths(&mnt_ctx);
+ /*
+ * After reconnecting to a different server, unique ids won't match anymore, so we disable
+ * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE).
+ */
+ cifs_autodisable_serverino(cifs_sb);
+ /*
+ * Force the use of prefix path to support failover on DFS paths that resolve to targets
+ * that have different prefix paths.
+ */
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
+ kfree(cifs_sb->prepath);
+ cifs_sb->prepath = ctx->prepath;
+ ctx->prepath = NULL;
+ uuid_copy(&cifs_sb->dfs_mount_id, &mnt_ctx.mount_id);
+
+out:
+ cifs_try_adding_channels(cifs_sb, mnt_ctx.ses);
+ rc = mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon);
+ if (rc)
+ goto error;
+
+ free_xid(mnt_ctx.xid);
+ return rc;
+
+error:
+ dfs_cache_put_refsrv_sessions(&mnt_ctx.mount_id);
+ kfree(mnt_ctx.origin_fullpath);
+ kfree(mnt_ctx.leaf_fullpath);
+ mount_put_conns(&mnt_ctx);
+ return rc;
+}
+#else
+int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
+{
+ int rc = 0;
+ struct mount_ctx mnt_ctx = { .cifs_sb = cifs_sb, .fs_ctx = ctx, };
+
+ rc = mount_get_conns(&mnt_ctx);
+ if (rc)
+ goto error;
+
+ if (mnt_ctx.tcon) {
+ rc = is_path_remote(&mnt_ctx);
+ if (rc == -EREMOTE)
+ rc = -EOPNOTSUPP;
+ if (rc)
+ goto error;
+ }
+
+ rc = mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon);
+ if (rc)
+ goto error;
+
+ free_xid(mnt_ctx.xid);
+ return rc;
+
+error:
+ mount_put_conns(&mnt_ctx);
+ return rc;
+}
+#endif
+
+/*
+ * Issue a TREE_CONNECT request.
+ */
+int
+CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
+ const char *tree, struct cifs_tcon *tcon,
+ const struct nls_table *nls_codepage)
+{
+ struct smb_hdr *smb_buffer;
+ struct smb_hdr *smb_buffer_response;
+ TCONX_REQ *pSMB;
+ TCONX_RSP *pSMBr;
+ unsigned char *bcc_ptr;
+ int rc = 0;
+ int length;
+ __u16 bytes_left, count;
+
+ if (ses == NULL)
+ return -EIO;
+
+ smb_buffer = cifs_buf_get();
+ if (smb_buffer == NULL)
+ return -ENOMEM;
+
+ smb_buffer_response = smb_buffer;
+
+ header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
+ NULL /*no tid */ , 4 /*wct */ );
+
+ smb_buffer->Mid = get_next_mid(ses->server);
+ smb_buffer->Uid = ses->Suid;
+ pSMB = (TCONX_REQ *) smb_buffer;
+ pSMBr = (TCONX_RSP *) smb_buffer_response;
+
+ pSMB->AndXCommand = 0xFF;
+ pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
+ bcc_ptr = &pSMB->Password[0];
+
+ pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
+ *bcc_ptr = 0; /* password is null byte */
+ bcc_ptr++; /* skip password */
+ /* already aligned so no need to do it below */
+
+ if (ses->server->sign)
+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ if (ses->capabilities & CAP_STATUS32) {
+ smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+ }
+ if (ses->capabilities & CAP_DFS) {
+ smb_buffer->Flags2 |= SMBFLG2_DFS;
+ }
+ if (ses->capabilities & CAP_UNICODE) {
+ smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+ length =
+ cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
+ 6 /* max utf8 char length in bytes */ *
+ (/* server len*/ + 256 /* share len */), nls_codepage);
+ bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
+ bcc_ptr += 2; /* skip trailing null */
+ } else { /* ASCII */
+ strcpy(bcc_ptr, tree);
+ bcc_ptr += strlen(tree) + 1;
+ }
+ strcpy(bcc_ptr, "?????");
+ bcc_ptr += strlen("?????");
+ bcc_ptr += 1;
+ count = bcc_ptr - &pSMB->Password[0];
+ be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
+ pSMB->ByteCount = cpu_to_le16(count);
+
+ rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
+ 0);
+
+ /* above now done in SendReceive */
+ if (rc == 0) {
+ bool is_unicode;
+
+ tcon->tid = smb_buffer_response->Tid;
+ bcc_ptr = pByteArea(smb_buffer_response);
+ bytes_left = get_bcc(smb_buffer_response);
+ length = strnlen(bcc_ptr, bytes_left - 2);
+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
+ is_unicode = true;
+ else
+ is_unicode = false;
+
+
+ /* skip service field (NB: this field is always ASCII) */
+ if (length == 3) {
+ if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
+ (bcc_ptr[2] == 'C')) {
+ cifs_dbg(FYI, "IPC connection\n");
+ tcon->ipc = true;
+ tcon->pipe = true;
+ }
+ } else if (length == 2) {
+ if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
+ /* the most common case */
+ cifs_dbg(FYI, "disk share connection\n");
+ }
+ }
+ bcc_ptr += length + 1;
+ bytes_left -= (length + 1);
+ strscpy(tcon->tree_name, tree, sizeof(tcon->tree_name));
+
+ /* mostly informational -- no need to fail on error here */
+ kfree(tcon->nativeFileSystem);
+ tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
+ bytes_left, is_unicode,
+ nls_codepage);
+
+ cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
+
+ if ((smb_buffer_response->WordCount == 3) ||
+ (smb_buffer_response->WordCount == 7))
+ /* field is in same location */
+ tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
+ else
+ tcon->Flags = 0;
+ cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
+ }
+
+ cifs_buf_release(smb_buffer);
+ return rc;
+}
+
+static void delayed_free(struct rcu_head *p)
+{
+ struct cifs_sb_info *cifs_sb = container_of(p, struct cifs_sb_info, rcu);
+
+ unload_nls(cifs_sb->local_nls);
+ smb3_cleanup_fs_context(cifs_sb->ctx);
+ kfree(cifs_sb);
+}
+
+void
+cifs_umount(struct cifs_sb_info *cifs_sb)
+{
+ struct rb_root *root = &cifs_sb->tlink_tree;
+ struct rb_node *node;
+ struct tcon_link *tlink;
+
+ cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
+
+ spin_lock(&cifs_sb->tlink_tree_lock);
+ while ((node = rb_first(root))) {
+ tlink = rb_entry(node, struct tcon_link, tl_rbnode);
+ cifs_get_tlink(tlink);
+ clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
+ rb_erase(node, root);
+
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+ cifs_put_tlink(tlink);
+ spin_lock(&cifs_sb->tlink_tree_lock);
+ }
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+
+ kfree(cifs_sb->prepath);
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ dfs_cache_put_refsrv_sessions(&cifs_sb->dfs_mount_id);
+#endif
+ call_rcu(&cifs_sb->rcu, delayed_free);
+}
+
+int
+cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ int rc = 0;
+
+ if (!server->ops->need_neg || !server->ops->negotiate)
+ return -ENOSYS;
+
+ /* only send once per connect */
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus != CifsGood &&
+ server->tcpStatus != CifsNew &&
+ server->tcpStatus != CifsNeedNegotiate) {
+ spin_unlock(&server->srv_lock);
+ return -EHOSTDOWN;
+ }
+
+ if (!server->ops->need_neg(server) &&
+ server->tcpStatus == CifsGood) {
+ spin_unlock(&server->srv_lock);
+ return 0;
+ }
+
+ server->tcpStatus = CifsInNegotiate;
+ spin_unlock(&server->srv_lock);
+
+ rc = server->ops->negotiate(xid, ses, server);
+ if (rc == 0) {
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsInNegotiate)
+ server->tcpStatus = CifsGood;
+ else
+ rc = -EHOSTDOWN;
+ spin_unlock(&server->srv_lock);
+ } else {
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsInNegotiate)
+ server->tcpStatus = CifsNeedNegotiate;
+ spin_unlock(&server->srv_lock);
+ }
+
+ return rc;
+}
+
+int
+cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ struct nls_table *nls_info)
+{
+ int rc = -ENOSYS;
+ struct TCP_Server_Info *pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr;
+ struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr;
+ bool is_binding = false;
+
+ spin_lock(&ses->ses_lock);
+ cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
+ __func__, ses->chans_need_reconnect);
+
+ if (ses->ses_status != SES_GOOD &&
+ ses->ses_status != SES_NEW &&
+ ses->ses_status != SES_NEED_RECON) {
+ spin_unlock(&ses->ses_lock);
+ return -EHOSTDOWN;
+ }
+
+ /* only send once per connect */
+ spin_lock(&ses->chan_lock);
+ if (CIFS_ALL_CHANS_GOOD(ses)) {
+ if (ses->ses_status == SES_NEED_RECON)
+ ses->ses_status = SES_GOOD;
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+ return 0;
+ }
+
+ cifs_chan_set_in_reconnect(ses, server);
+ is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
+ spin_unlock(&ses->chan_lock);
+
+ if (!is_binding)
+ ses->ses_status = SES_IN_SETUP;
+ spin_unlock(&ses->ses_lock);
+
+ /* update ses ip_addr only for primary chan */
+ if (server == pserver) {
+ if (server->dstaddr.ss_family == AF_INET6)
+ scnprintf(ses->ip_addr, sizeof(ses->ip_addr), "%pI6", &addr6->sin6_addr);
+ else
+ scnprintf(ses->ip_addr, sizeof(ses->ip_addr), "%pI4", &addr->sin_addr);
+ }
+
+ if (!is_binding) {
+ ses->capabilities = server->capabilities;
+ if (!linuxExtEnabled)
+ ses->capabilities &= (~server->vals->cap_unix);
+
+ if (ses->auth_key.response) {
+ cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
+ ses->auth_key.response);
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.response = NULL;
+ ses->auth_key.len = 0;
+ }
+ }
+
+ cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
+ server->sec_mode, server->capabilities, server->timeAdj);
+
+ if (server->ops->sess_setup)
+ rc = server->ops->sess_setup(xid, ses, server, nls_info);
+
+ if (rc) {
+ cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
+ spin_lock(&ses->ses_lock);
+ if (ses->ses_status == SES_IN_SETUP)
+ ses->ses_status = SES_NEED_RECON;
+ spin_lock(&ses->chan_lock);
+ cifs_chan_clear_in_reconnect(ses, server);
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+ } else {
+ spin_lock(&ses->ses_lock);
+ if (ses->ses_status == SES_IN_SETUP)
+ ses->ses_status = SES_GOOD;
+ spin_lock(&ses->chan_lock);
+ cifs_chan_clear_in_reconnect(ses, server);
+ cifs_chan_clear_need_reconnect(ses, server);
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+ }
+
+ return rc;
+}
+
+static int
+cifs_set_vol_auth(struct smb3_fs_context *ctx, struct cifs_ses *ses)
+{
+ ctx->sectype = ses->sectype;
+
+ /* krb5 is special, since we don't need username or pw */
+ if (ctx->sectype == Kerberos)
+ return 0;
+
+ return cifs_set_cifscreds(ctx, ses);
+}
+
+static struct cifs_tcon *
+cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
+{
+ int rc;
+ struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon = NULL;
+ struct smb3_fs_context *ctx;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (ctx == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ ctx->local_nls = cifs_sb->local_nls;
+ ctx->linux_uid = fsuid;
+ ctx->cred_uid = fsuid;
+ ctx->UNC = master_tcon->tree_name;
+ ctx->retry = master_tcon->retry;
+ ctx->nocase = master_tcon->nocase;
+ ctx->nohandlecache = master_tcon->nohandlecache;
+ ctx->local_lease = master_tcon->local_lease;
+ ctx->no_lease = master_tcon->no_lease;
+ ctx->resilient = master_tcon->use_resilient;
+ ctx->persistent = master_tcon->use_persistent;
+ ctx->handle_timeout = master_tcon->handle_timeout;
+ ctx->no_linux_ext = !master_tcon->unix_ext;
+ ctx->linux_ext = master_tcon->posix_extensions;
+ ctx->sectype = master_tcon->ses->sectype;
+ ctx->sign = master_tcon->ses->sign;
+ ctx->seal = master_tcon->seal;
+ ctx->witness = master_tcon->use_witness;
+
+ rc = cifs_set_vol_auth(ctx, master_tcon->ses);
+ if (rc) {
+ tcon = ERR_PTR(rc);
+ goto out;
+ }
+
+ /* get a reference for the same TCP session */
+ spin_lock(&cifs_tcp_ses_lock);
+ ++master_tcon->ses->server->srv_count;
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ ses = cifs_get_smb_ses(master_tcon->ses->server, ctx);
+ if (IS_ERR(ses)) {
+ tcon = (struct cifs_tcon *)ses;
+ cifs_put_tcp_session(master_tcon->ses->server, 0);
+ goto out;
+ }
+
+ tcon = cifs_get_tcon(ses, ctx);
+ if (IS_ERR(tcon)) {
+ cifs_put_smb_ses(ses);
+ goto out;
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (cap_unix(ses))
+ reset_cifs_unix_caps(0, tcon, NULL, ctx);
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+out:
+ kfree(ctx->username);
+ kfree_sensitive(ctx->password);
+ kfree(ctx);
+
+ return tcon;
+}
+
+struct cifs_tcon *
+cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
+{
+ return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
+}
+
+/* find and return a tlink with given uid */
+static struct tcon_link *
+tlink_rb_search(struct rb_root *root, kuid_t uid)
+{
+ struct rb_node *node = root->rb_node;
+ struct tcon_link *tlink;
+
+ while (node) {
+ tlink = rb_entry(node, struct tcon_link, tl_rbnode);
+
+ if (uid_gt(tlink->tl_uid, uid))
+ node = node->rb_left;
+ else if (uid_lt(tlink->tl_uid, uid))
+ node = node->rb_right;
+ else
+ return tlink;
+ }
+ return NULL;
+}
+
+/* insert a tcon_link into the tree */
+static void
+tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
+{
+ struct rb_node **new = &(root->rb_node), *parent = NULL;
+ struct tcon_link *tlink;
+
+ while (*new) {
+ tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
+ parent = *new;
+
+ if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
+ new = &((*new)->rb_left);
+ else
+ new = &((*new)->rb_right);
+ }
+
+ rb_link_node(&new_tlink->tl_rbnode, parent, new);
+ rb_insert_color(&new_tlink->tl_rbnode, root);
+}
+
+/*
+ * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
+ * current task.
+ *
+ * If the superblock doesn't refer to a multiuser mount, then just return
+ * the master tcon for the mount.
+ *
+ * First, search the rbtree for an existing tcon for this fsuid. If one
+ * exists, then check to see if it's pending construction. If it is then wait
+ * for construction to complete. Once it's no longer pending, check to see if
+ * it failed and either return an error or retry construction, depending on
+ * the timeout.
+ *
+ * If one doesn't exist then insert a new tcon_link struct into the tree and
+ * try to construct a new one.
+ */
+struct tcon_link *
+cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
+{
+ int ret;
+ kuid_t fsuid = current_fsuid();
+ struct tcon_link *tlink, *newtlink;
+
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
+ return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
+
+ spin_lock(&cifs_sb->tlink_tree_lock);
+ tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
+ if (tlink)
+ cifs_get_tlink(tlink);
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+
+ if (tlink == NULL) {
+ newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
+ if (newtlink == NULL)
+ return ERR_PTR(-ENOMEM);
+ newtlink->tl_uid = fsuid;
+ newtlink->tl_tcon = ERR_PTR(-EACCES);
+ set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
+ set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
+ cifs_get_tlink(newtlink);
+
+ spin_lock(&cifs_sb->tlink_tree_lock);
+ /* was one inserted after previous search? */
+ tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
+ if (tlink) {
+ cifs_get_tlink(tlink);
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+ kfree(newtlink);
+ goto wait_for_construction;
+ }
+ tlink = newtlink;
+ tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+ } else {
+wait_for_construction:
+ ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
+ TASK_INTERRUPTIBLE);
+ if (ret) {
+ cifs_put_tlink(tlink);
+ return ERR_PTR(-ERESTARTSYS);
+ }
+
+ /* if it's good, return it */
+ if (!IS_ERR(tlink->tl_tcon))
+ return tlink;
+
+ /* return error if we tried this already recently */
+ if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
+ cifs_put_tlink(tlink);
+ return ERR_PTR(-EACCES);
+ }
+
+ if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
+ goto wait_for_construction;
+ }
+
+ tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
+ clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
+ wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
+
+ if (IS_ERR(tlink->tl_tcon)) {
+ cifs_put_tlink(tlink);
+ return ERR_PTR(-EACCES);
+ }
+
+ return tlink;
+}
+
+/*
+ * periodic workqueue job that scans tcon_tree for a superblock and closes
+ * out tcons.
+ */
+static void
+cifs_prune_tlinks(struct work_struct *work)
+{
+ struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
+ prune_tlinks.work);
+ struct rb_root *root = &cifs_sb->tlink_tree;
+ struct rb_node *node;
+ struct rb_node *tmp;
+ struct tcon_link *tlink;
+
+ /*
+ * Because we drop the spinlock in the loop in order to put the tlink
+ * it's not guarded against removal of links from the tree. The only
+ * places that remove entries from the tree are this function and
+ * umounts. Because this function is non-reentrant and is canceled
+ * before umount can proceed, this is safe.
+ */
+ spin_lock(&cifs_sb->tlink_tree_lock);
+ node = rb_first(root);
+ while (node != NULL) {
+ tmp = node;
+ node = rb_next(tmp);
+ tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
+
+ if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
+ atomic_read(&tlink->tl_count) != 0 ||
+ time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
+ continue;
+
+ cifs_get_tlink(tlink);
+ clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
+ rb_erase(tmp, root);
+
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+ cifs_put_tlink(tlink);
+ spin_lock(&cifs_sb->tlink_tree_lock);
+ }
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+
+ queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
+ TLINK_IDLE_EXPIRE);
+}
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+/* Update dfs referral path of superblock */
+static int update_server_fullpath(struct TCP_Server_Info *server, struct cifs_sb_info *cifs_sb,
+ const char *target)
+{
+ int rc = 0;
+ size_t len = strlen(target);
+ char *refpath, *npath;
+
+ if (unlikely(len < 2 || *target != '\\'))
+ return -EINVAL;
+
+ if (target[1] == '\\') {
+ len += 1;
+ refpath = kmalloc(len, GFP_KERNEL);
+ if (!refpath)
+ return -ENOMEM;
+
+ scnprintf(refpath, len, "%s", target);
+ } else {
+ len += sizeof("\\");
+ refpath = kmalloc(len, GFP_KERNEL);
+ if (!refpath)
+ return -ENOMEM;
+
+ scnprintf(refpath, len, "\\%s", target);
+ }
+
+ npath = dfs_cache_canonical_path(refpath, cifs_sb->local_nls, cifs_remap(cifs_sb));
+ kfree(refpath);
+
+ if (IS_ERR(npath)) {
+ rc = PTR_ERR(npath);
+ } else {
+ mutex_lock(&server->refpath_lock);
+ kfree(server->leaf_fullpath);
+ server->leaf_fullpath = npath;
+ mutex_unlock(&server->refpath_lock);
+ server->current_fullpath = server->leaf_fullpath;
+ }
+ return rc;
+}
+
+static int target_share_matches_server(struct TCP_Server_Info *server, const char *tcp_host,
+ size_t tcp_host_len, char *share, bool *target_match)
+{
+ int rc = 0;
+ const char *dfs_host;
+ size_t dfs_host_len;
+
+ *target_match = true;
+ extract_unc_hostname(share, &dfs_host, &dfs_host_len);
+
+ /* Check if hostnames or addresses match */
+ if (dfs_host_len != tcp_host_len || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
+ cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
+ dfs_host, (int)tcp_host_len, tcp_host);
+ rc = match_target_ip(server, dfs_host, dfs_host_len, target_match);
+ if (rc)
+ cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
+ }
+ return rc;
+}
+
+static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, char *tree, bool islink,
+ struct dfs_cache_tgt_list *tl)
+{
+ int rc;
+ struct TCP_Server_Info *server = tcon->ses->server;
+ const struct smb_version_operations *ops = server->ops;
+ struct cifs_tcon *ipc = tcon->ses->tcon_ipc;
+ char *share = NULL, *prefix = NULL;
+ const char *tcp_host;
+ size_t tcp_host_len;
+ struct dfs_cache_tgt_iterator *tit;
+ bool target_match;
+
+ extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
+
+ tit = dfs_cache_get_tgt_iterator(tl);
+ if (!tit) {
+ rc = -ENOENT;
+ goto out;
+ }
+
+ /* Try to tree connect to all dfs targets */
+ for (; tit; tit = dfs_cache_get_next_tgt(tl, tit)) {
+ const char *target = dfs_cache_get_tgt_name(tit);
+ struct dfs_cache_tgt_list ntl = DFS_CACHE_TGT_LIST_INIT(ntl);
+
+ kfree(share);
+ kfree(prefix);
+ share = prefix = NULL;
+
+ /* Check if share matches with tcp ses */
+ rc = dfs_cache_get_tgt_share(server->current_fullpath + 1, tit, &share, &prefix);
+ if (rc) {
+ cifs_dbg(VFS, "%s: failed to parse target share: %d\n", __func__, rc);
+ break;
+ }
+
+ rc = target_share_matches_server(server, tcp_host, tcp_host_len, share,
+ &target_match);
+ if (rc)
+ break;
+ if (!target_match) {
+ rc = -EHOSTUNREACH;
+ continue;
+ }
+
+ if (ipc->need_reconnect) {
+ scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
+ rc = ops->tree_connect(xid, ipc->ses, tree, ipc, cifs_sb->local_nls);
+ if (rc)
+ break;
+ }
+
+ scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
+ if (!islink) {
+ rc = ops->tree_connect(xid, tcon->ses, tree, tcon, cifs_sb->local_nls);
+ break;
+ }
+ /*
+ * If no dfs referrals were returned from link target, then just do a TREE_CONNECT
+ * to it. Otherwise, cache the dfs referral and then mark current tcp ses for
+ * reconnect so either the demultiplex thread or the echo worker will reconnect to
+ * newly resolved target.
+ */
+ if (dfs_cache_find(xid, tcon->ses, cifs_sb->local_nls, cifs_remap(cifs_sb), target,
+ NULL, &ntl)) {
+ rc = ops->tree_connect(xid, tcon->ses, tree, tcon, cifs_sb->local_nls);
+ if (rc)
+ continue;
+ rc = dfs_cache_noreq_update_tgthint(server->current_fullpath + 1, tit);
+ if (!rc)
+ rc = cifs_update_super_prepath(cifs_sb, prefix);
+ } else {
+ /* Target is another dfs share */
+ rc = update_server_fullpath(server, cifs_sb, target);
+ dfs_cache_free_tgts(tl);
+
+ if (!rc) {
+ rc = -EREMOTE;
+ list_replace_init(&ntl.tl_list, &tl->tl_list);
+ } else
+ dfs_cache_free_tgts(&ntl);
+ }
+ break;
+ }
+
+out:
+ kfree(share);
+ kfree(prefix);
+
+ return rc;
+}
+
+static int tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, char *tree, bool islink,
+ struct dfs_cache_tgt_list *tl)
+{
+ int rc;
+ int num_links = 0;
+ struct TCP_Server_Info *server = tcon->ses->server;
+
+ do {
+ rc = __tree_connect_dfs_target(xid, tcon, cifs_sb, tree, islink, tl);
+ if (!rc || rc != -EREMOTE)
+ break;
+ } while (rc = -ELOOP, ++num_links < MAX_NESTED_LINKS);
+ /*
+ * If we couldn't tree connect to any targets from last referral path, then retry from
+ * original referral path.
+ */
+ if (rc && server->current_fullpath != server->origin_fullpath) {
+ server->current_fullpath = server->origin_fullpath;
+ cifs_signal_cifsd_for_reconnect(server, true);
+ }
+
+ dfs_cache_free_tgts(tl);
+ return rc;
+}
+
+int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
+{
+ int rc;
+ struct TCP_Server_Info *server = tcon->ses->server;
+ const struct smb_version_operations *ops = server->ops;
+ struct super_block *sb = NULL;
+ struct cifs_sb_info *cifs_sb;
+ struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
+ char *tree;
+ struct dfs_info3_param ref = {0};
+
+ /* only send once per connect */
+ spin_lock(&tcon->tc_lock);
+ if (tcon->ses->ses_status != SES_GOOD ||
+ (tcon->status != TID_NEW &&
+ tcon->status != TID_NEED_TCON)) {
+ spin_unlock(&tcon->tc_lock);
+ return 0;
+ }
+ tcon->status = TID_IN_TCON;
+ spin_unlock(&tcon->tc_lock);
+
+ tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
+ if (!tree) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ if (tcon->ipc) {
+ scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
+ rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
+ goto out;
+ }
+
+ sb = cifs_get_tcp_super(server);
+ if (IS_ERR(sb)) {
+ rc = PTR_ERR(sb);
+ cifs_dbg(VFS, "%s: could not find superblock: %d\n", __func__, rc);
+ goto out;
+ }
+
+ cifs_sb = CIFS_SB(sb);
+
+ /* If it is not dfs or there was no cached dfs referral, then reconnect to same share */
+ if (!server->current_fullpath ||
+ dfs_cache_noreq_find(server->current_fullpath + 1, &ref, &tl)) {
+ rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon, cifs_sb->local_nls);
+ goto out;
+ }
+
+ rc = tree_connect_dfs_target(xid, tcon, cifs_sb, tree, ref.server_type == DFS_TYPE_LINK,
+ &tl);
+ free_dfs_info_param(&ref);
+
+out:
+ kfree(tree);
+ cifs_put_tcp_super(sb);
+
+ if (rc) {
+ spin_lock(&tcon->tc_lock);
+ if (tcon->status == TID_IN_TCON)
+ tcon->status = TID_NEED_TCON;
+ spin_unlock(&tcon->tc_lock);
+ } else {
+ spin_lock(&tcon->tc_lock);
+ if (tcon->status == TID_IN_TCON)
+ tcon->status = TID_GOOD;
+ spin_unlock(&tcon->tc_lock);
+ tcon->need_reconnect = false;
+ }
+
+ return rc;
+}
+#else
+int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
+{
+ int rc;
+ const struct smb_version_operations *ops = tcon->ses->server->ops;
+
+ /* only send once per connect */
+ spin_lock(&tcon->tc_lock);
+ if (tcon->ses->ses_status != SES_GOOD ||
+ (tcon->status != TID_NEW &&
+ tcon->status != TID_NEED_TCON)) {
+ spin_unlock(&tcon->tc_lock);
+ return 0;
+ }
+ tcon->status = TID_IN_TCON;
+ spin_unlock(&tcon->tc_lock);
+
+ rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon, nlsc);
+ if (rc) {
+ spin_lock(&tcon->tc_lock);
+ if (tcon->status == TID_IN_TCON)
+ tcon->status = TID_NEED_TCON;
+ spin_unlock(&tcon->tc_lock);
+ } else {
+ spin_lock(&tcon->tc_lock);
+ if (tcon->status == TID_IN_TCON)
+ tcon->status = TID_GOOD;
+ tcon->need_reconnect = false;
+ spin_unlock(&tcon->tc_lock);
+ }
+
+ return rc;
+}
+#endif
diff --git a/fs/smb/client/dfs_cache.c b/fs/smb/client/dfs_cache.c
new file mode 100644
index 000000000000..3bc1d3494be3
--- /dev/null
+++ b/fs/smb/client/dfs_cache.c
@@ -0,0 +1,1690 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DFS referral cache routines
+ *
+ * Copyright (c) 2018-2019 Paulo Alcantara <palcantara@suse.de>
+ */
+
+#include <linux/jhash.h>
+#include <linux/ktime.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/nls.h>
+#include <linux/workqueue.h>
+#include <linux/uuid.h>
+#include "cifsglob.h"
+#include "smb2pdu.h"
+#include "smb2proto.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_unicode.h"
+#include "smb2glob.h"
+#include "dns_resolve.h"
+
+#include "dfs_cache.h"
+
+#define CACHE_HTABLE_SIZE 32
+#define CACHE_MAX_ENTRIES 64
+#define CACHE_MIN_TTL 120 /* 2 minutes */
+
+#define IS_DFS_INTERLINK(v) (((v) & DFSREF_REFERRAL_SERVER) && !((v) & DFSREF_STORAGE_SERVER))
+
+struct cache_dfs_tgt {
+ char *name;
+ int path_consumed;
+ struct list_head list;
+};
+
+struct cache_entry {
+ struct hlist_node hlist;
+ const char *path;
+ int hdr_flags; /* RESP_GET_DFS_REFERRAL.ReferralHeaderFlags */
+ int ttl; /* DFS_REREFERRAL_V3.TimeToLive */
+ int srvtype; /* DFS_REREFERRAL_V3.ServerType */
+ int ref_flags; /* DFS_REREFERRAL_V3.ReferralEntryFlags */
+ struct timespec64 etime;
+ int path_consumed; /* RESP_GET_DFS_REFERRAL.PathConsumed */
+ int numtgts;
+ struct list_head tlist;
+ struct cache_dfs_tgt *tgthint;
+};
+
+/* List of referral server sessions per dfs mount */
+struct mount_group {
+ struct list_head list;
+ uuid_t id;
+ struct cifs_ses *sessions[CACHE_MAX_ENTRIES];
+ int num_sessions;
+ spinlock_t lock;
+ struct list_head refresh_list;
+ struct kref refcount;
+};
+
+static struct kmem_cache *cache_slab __read_mostly;
+static struct workqueue_struct *dfscache_wq __read_mostly;
+
+static int cache_ttl;
+static DEFINE_SPINLOCK(cache_ttl_lock);
+
+static struct nls_table *cache_cp;
+
+/*
+ * Number of entries in the cache
+ */
+static atomic_t cache_count;
+
+static struct hlist_head cache_htable[CACHE_HTABLE_SIZE];
+static DECLARE_RWSEM(htable_rw_lock);
+
+static LIST_HEAD(mount_group_list);
+static DEFINE_MUTEX(mount_group_list_lock);
+
+static void refresh_cache_worker(struct work_struct *work);
+
+static DECLARE_DELAYED_WORK(refresh_task, refresh_cache_worker);
+
+static void get_ipc_unc(const char *ref_path, char *ipc, size_t ipclen)
+{
+ const char *host;
+ size_t len;
+
+ extract_unc_hostname(ref_path, &host, &len);
+ scnprintf(ipc, ipclen, "\\\\%.*s\\IPC$", (int)len, host);
+}
+
+static struct cifs_ses *find_ipc_from_server_path(struct cifs_ses **ses, const char *path)
+{
+ char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
+
+ get_ipc_unc(path, unc, sizeof(unc));
+ for (; *ses; ses++) {
+ if (!strcasecmp(unc, (*ses)->tcon_ipc->tree_name))
+ return *ses;
+ }
+ return ERR_PTR(-ENOENT);
+}
+
+static void __mount_group_release(struct mount_group *mg)
+{
+ int i;
+
+ for (i = 0; i < mg->num_sessions; i++)
+ cifs_put_smb_ses(mg->sessions[i]);
+ kfree(mg);
+}
+
+static void mount_group_release(struct kref *kref)
+{
+ struct mount_group *mg = container_of(kref, struct mount_group, refcount);
+
+ mutex_lock(&mount_group_list_lock);
+ list_del(&mg->list);
+ mutex_unlock(&mount_group_list_lock);
+ __mount_group_release(mg);
+}
+
+static struct mount_group *find_mount_group_locked(const uuid_t *id)
+{
+ struct mount_group *mg;
+
+ list_for_each_entry(mg, &mount_group_list, list) {
+ if (uuid_equal(&mg->id, id))
+ return mg;
+ }
+ return ERR_PTR(-ENOENT);
+}
+
+static struct mount_group *__get_mount_group_locked(const uuid_t *id)
+{
+ struct mount_group *mg;
+
+ mg = find_mount_group_locked(id);
+ if (!IS_ERR(mg))
+ return mg;
+
+ mg = kmalloc(sizeof(*mg), GFP_KERNEL);
+ if (!mg)
+ return ERR_PTR(-ENOMEM);
+ kref_init(&mg->refcount);
+ uuid_copy(&mg->id, id);
+ mg->num_sessions = 0;
+ spin_lock_init(&mg->lock);
+ list_add(&mg->list, &mount_group_list);
+ return mg;
+}
+
+static struct mount_group *get_mount_group(const uuid_t *id)
+{
+ struct mount_group *mg;
+
+ mutex_lock(&mount_group_list_lock);
+ mg = __get_mount_group_locked(id);
+ if (!IS_ERR(mg))
+ kref_get(&mg->refcount);
+ mutex_unlock(&mount_group_list_lock);
+
+ return mg;
+}
+
+static void free_mount_group_list(void)
+{
+ struct mount_group *mg, *tmp_mg;
+
+ list_for_each_entry_safe(mg, tmp_mg, &mount_group_list, list) {
+ list_del_init(&mg->list);
+ __mount_group_release(mg);
+ }
+}
+
+/**
+ * dfs_cache_canonical_path - get a canonical DFS path
+ *
+ * @path: DFS path
+ * @cp: codepage
+ * @remap: mapping type
+ *
+ * Return canonical path if success, otherwise error.
+ */
+char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap)
+{
+ char *tmp;
+ int plen = 0;
+ char *npath;
+
+ if (!path || strlen(path) < 3 || (*path != '\\' && *path != '/'))
+ return ERR_PTR(-EINVAL);
+
+ if (unlikely(strcmp(cp->charset, cache_cp->charset))) {
+ tmp = (char *)cifs_strndup_to_utf16(path, strlen(path), &plen, cp, remap);
+ if (!tmp) {
+ cifs_dbg(VFS, "%s: failed to convert path to utf16\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ npath = cifs_strndup_from_utf16(tmp, plen, true, cache_cp);
+ kfree(tmp);
+
+ if (!npath) {
+ cifs_dbg(VFS, "%s: failed to convert path from utf16\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+ } else {
+ npath = kstrdup(path, GFP_KERNEL);
+ if (!npath)
+ return ERR_PTR(-ENOMEM);
+ }
+ convert_delimiter(npath, '\\');
+ return npath;
+}
+
+static inline bool cache_entry_expired(const struct cache_entry *ce)
+{
+ struct timespec64 ts;
+
+ ktime_get_coarse_real_ts64(&ts);
+ return timespec64_compare(&ts, &ce->etime) >= 0;
+}
+
+static inline void free_tgts(struct cache_entry *ce)
+{
+ struct cache_dfs_tgt *t, *n;
+
+ list_for_each_entry_safe(t, n, &ce->tlist, list) {
+ list_del(&t->list);
+ kfree(t->name);
+ kfree(t);
+ }
+}
+
+static inline void flush_cache_ent(struct cache_entry *ce)
+{
+ hlist_del_init(&ce->hlist);
+ kfree(ce->path);
+ free_tgts(ce);
+ atomic_dec(&cache_count);
+ kmem_cache_free(cache_slab, ce);
+}
+
+static void flush_cache_ents(void)
+{
+ int i;
+
+ for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
+ struct hlist_head *l = &cache_htable[i];
+ struct hlist_node *n;
+ struct cache_entry *ce;
+
+ hlist_for_each_entry_safe(ce, n, l, hlist) {
+ if (!hlist_unhashed(&ce->hlist))
+ flush_cache_ent(ce);
+ }
+ }
+}
+
+/*
+ * dfs cache /proc file
+ */
+static int dfscache_proc_show(struct seq_file *m, void *v)
+{
+ int i;
+ struct cache_entry *ce;
+ struct cache_dfs_tgt *t;
+
+ seq_puts(m, "DFS cache\n---------\n");
+
+ down_read(&htable_rw_lock);
+ for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
+ struct hlist_head *l = &cache_htable[i];
+
+ hlist_for_each_entry(ce, l, hlist) {
+ if (hlist_unhashed(&ce->hlist))
+ continue;
+
+ seq_printf(m,
+ "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n",
+ ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link",
+ ce->ttl, ce->etime.tv_nsec, ce->hdr_flags, ce->ref_flags,
+ IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no",
+ ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no");
+
+ list_for_each_entry(t, &ce->tlist, list) {
+ seq_printf(m, " %s%s\n",
+ t->name,
+ ce->tgthint == t ? " (target hint)" : "");
+ }
+ }
+ }
+ up_read(&htable_rw_lock);
+
+ return 0;
+}
+
+static ssize_t dfscache_proc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+
+ if (c != '0')
+ return -EINVAL;
+
+ cifs_dbg(FYI, "clearing dfs cache\n");
+
+ down_write(&htable_rw_lock);
+ flush_cache_ents();
+ up_write(&htable_rw_lock);
+
+ return count;
+}
+
+static int dfscache_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dfscache_proc_show, NULL);
+}
+
+const struct proc_ops dfscache_proc_ops = {
+ .proc_open = dfscache_proc_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release,
+ .proc_write = dfscache_proc_write,
+};
+
+#ifdef CONFIG_CIFS_DEBUG2
+static inline void dump_tgts(const struct cache_entry *ce)
+{
+ struct cache_dfs_tgt *t;
+
+ cifs_dbg(FYI, "target list:\n");
+ list_for_each_entry(t, &ce->tlist, list) {
+ cifs_dbg(FYI, " %s%s\n", t->name,
+ ce->tgthint == t ? " (target hint)" : "");
+ }
+}
+
+static inline void dump_ce(const struct cache_entry *ce)
+{
+ cifs_dbg(FYI, "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n",
+ ce->path,
+ ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl,
+ ce->etime.tv_nsec,
+ ce->hdr_flags, ce->ref_flags,
+ IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no",
+ ce->path_consumed,
+ cache_entry_expired(ce) ? "yes" : "no");
+ dump_tgts(ce);
+}
+
+static inline void dump_refs(const struct dfs_info3_param *refs, int numrefs)
+{
+ int i;
+
+ cifs_dbg(FYI, "DFS referrals returned by the server:\n");
+ for (i = 0; i < numrefs; i++) {
+ const struct dfs_info3_param *ref = &refs[i];
+
+ cifs_dbg(FYI,
+ "\n"
+ "flags: 0x%x\n"
+ "path_consumed: %d\n"
+ "server_type: 0x%x\n"
+ "ref_flag: 0x%x\n"
+ "path_name: %s\n"
+ "node_name: %s\n"
+ "ttl: %d (%dm)\n",
+ ref->flags, ref->path_consumed, ref->server_type,
+ ref->ref_flag, ref->path_name, ref->node_name,
+ ref->ttl, ref->ttl / 60);
+ }
+}
+#else
+#define dump_tgts(e)
+#define dump_ce(e)
+#define dump_refs(r, n)
+#endif
+
+/**
+ * dfs_cache_init - Initialize DFS referral cache.
+ *
+ * Return zero if initialized successfully, otherwise non-zero.
+ */
+int dfs_cache_init(void)
+{
+ int rc;
+ int i;
+
+ dfscache_wq = alloc_workqueue("cifs-dfscache", WQ_FREEZABLE | WQ_UNBOUND, 1);
+ if (!dfscache_wq)
+ return -ENOMEM;
+
+ cache_slab = kmem_cache_create("cifs_dfs_cache",
+ sizeof(struct cache_entry), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!cache_slab) {
+ rc = -ENOMEM;
+ goto out_destroy_wq;
+ }
+
+ for (i = 0; i < CACHE_HTABLE_SIZE; i++)
+ INIT_HLIST_HEAD(&cache_htable[i]);
+
+ atomic_set(&cache_count, 0);
+ cache_cp = load_nls("utf8");
+ if (!cache_cp)
+ cache_cp = load_nls_default();
+
+ cifs_dbg(FYI, "%s: initialized DFS referral cache\n", __func__);
+ return 0;
+
+out_destroy_wq:
+ destroy_workqueue(dfscache_wq);
+ return rc;
+}
+
+static int cache_entry_hash(const void *data, int size, unsigned int *hash)
+{
+ int i, clen;
+ const unsigned char *s = data;
+ wchar_t c;
+ unsigned int h = 0;
+
+ for (i = 0; i < size; i += clen) {
+ clen = cache_cp->char2uni(&s[i], size - i, &c);
+ if (unlikely(clen < 0)) {
+ cifs_dbg(VFS, "%s: can't convert char\n", __func__);
+ return clen;
+ }
+ c = cifs_toupper(c);
+ h = jhash(&c, sizeof(c), h);
+ }
+ *hash = h % CACHE_HTABLE_SIZE;
+ return 0;
+}
+
+/* Return target hint of a DFS cache entry */
+static inline char *get_tgt_name(const struct cache_entry *ce)
+{
+ struct cache_dfs_tgt *t = ce->tgthint;
+
+ return t ? t->name : ERR_PTR(-ENOENT);
+}
+
+/* Return expire time out of a new entry's TTL */
+static inline struct timespec64 get_expire_time(int ttl)
+{
+ struct timespec64 ts = {
+ .tv_sec = ttl,
+ .tv_nsec = 0,
+ };
+ struct timespec64 now;
+
+ ktime_get_coarse_real_ts64(&now);
+ return timespec64_add(now, ts);
+}
+
+/* Allocate a new DFS target */
+static struct cache_dfs_tgt *alloc_target(const char *name, int path_consumed)
+{
+ struct cache_dfs_tgt *t;
+
+ t = kmalloc(sizeof(*t), GFP_ATOMIC);
+ if (!t)
+ return ERR_PTR(-ENOMEM);
+ t->name = kstrdup(name, GFP_ATOMIC);
+ if (!t->name) {
+ kfree(t);
+ return ERR_PTR(-ENOMEM);
+ }
+ t->path_consumed = path_consumed;
+ INIT_LIST_HEAD(&t->list);
+ return t;
+}
+
+/*
+ * Copy DFS referral information to a cache entry and conditionally update
+ * target hint.
+ */
+static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
+ struct cache_entry *ce, const char *tgthint)
+{
+ int i;
+
+ ce->ttl = max_t(int, refs[0].ttl, CACHE_MIN_TTL);
+ ce->etime = get_expire_time(ce->ttl);
+ ce->srvtype = refs[0].server_type;
+ ce->hdr_flags = refs[0].flags;
+ ce->ref_flags = refs[0].ref_flag;
+ ce->path_consumed = refs[0].path_consumed;
+
+ for (i = 0; i < numrefs; i++) {
+ struct cache_dfs_tgt *t;
+
+ t = alloc_target(refs[i].node_name, refs[i].path_consumed);
+ if (IS_ERR(t)) {
+ free_tgts(ce);
+ return PTR_ERR(t);
+ }
+ if (tgthint && !strcasecmp(t->name, tgthint)) {
+ list_add(&t->list, &ce->tlist);
+ tgthint = NULL;
+ } else {
+ list_add_tail(&t->list, &ce->tlist);
+ }
+ ce->numtgts++;
+ }
+
+ ce->tgthint = list_first_entry_or_null(&ce->tlist,
+ struct cache_dfs_tgt, list);
+
+ return 0;
+}
+
+/* Allocate a new cache entry */
+static struct cache_entry *alloc_cache_entry(struct dfs_info3_param *refs, int numrefs)
+{
+ struct cache_entry *ce;
+ int rc;
+
+ ce = kmem_cache_zalloc(cache_slab, GFP_KERNEL);
+ if (!ce)
+ return ERR_PTR(-ENOMEM);
+
+ ce->path = refs[0].path_name;
+ refs[0].path_name = NULL;
+
+ INIT_HLIST_NODE(&ce->hlist);
+ INIT_LIST_HEAD(&ce->tlist);
+
+ rc = copy_ref_data(refs, numrefs, ce, NULL);
+ if (rc) {
+ kfree(ce->path);
+ kmem_cache_free(cache_slab, ce);
+ ce = ERR_PTR(rc);
+ }
+ return ce;
+}
+
+static void remove_oldest_entry_locked(void)
+{
+ int i;
+ struct cache_entry *ce;
+ struct cache_entry *to_del = NULL;
+
+ WARN_ON(!rwsem_is_locked(&htable_rw_lock));
+
+ for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
+ struct hlist_head *l = &cache_htable[i];
+
+ hlist_for_each_entry(ce, l, hlist) {
+ if (hlist_unhashed(&ce->hlist))
+ continue;
+ if (!to_del || timespec64_compare(&ce->etime,
+ &to_del->etime) < 0)
+ to_del = ce;
+ }
+ }
+
+ if (!to_del) {
+ cifs_dbg(FYI, "%s: no entry to remove\n", __func__);
+ return;
+ }
+
+ cifs_dbg(FYI, "%s: removing entry\n", __func__);
+ dump_ce(to_del);
+ flush_cache_ent(to_del);
+}
+
+/* Add a new DFS cache entry */
+static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
+{
+ int rc;
+ struct cache_entry *ce;
+ unsigned int hash;
+
+ WARN_ON(!rwsem_is_locked(&htable_rw_lock));
+
+ if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES) {
+ cifs_dbg(FYI, "%s: reached max cache size (%d)\n", __func__, CACHE_MAX_ENTRIES);
+ remove_oldest_entry_locked();
+ }
+
+ rc = cache_entry_hash(refs[0].path_name, strlen(refs[0].path_name), &hash);
+ if (rc)
+ return rc;
+
+ ce = alloc_cache_entry(refs, numrefs);
+ if (IS_ERR(ce))
+ return PTR_ERR(ce);
+
+ spin_lock(&cache_ttl_lock);
+ if (!cache_ttl) {
+ cache_ttl = ce->ttl;
+ queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ);
+ } else {
+ cache_ttl = min_t(int, cache_ttl, ce->ttl);
+ mod_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ);
+ }
+ spin_unlock(&cache_ttl_lock);
+
+ hlist_add_head(&ce->hlist, &cache_htable[hash]);
+ dump_ce(ce);
+
+ atomic_inc(&cache_count);
+
+ return 0;
+}
+
+/* Check if two DFS paths are equal. @s1 and @s2 are expected to be in @cache_cp's charset */
+static bool dfs_path_equal(const char *s1, int len1, const char *s2, int len2)
+{
+ int i, l1, l2;
+ wchar_t c1, c2;
+
+ if (len1 != len2)
+ return false;
+
+ for (i = 0; i < len1; i += l1) {
+ l1 = cache_cp->char2uni(&s1[i], len1 - i, &c1);
+ l2 = cache_cp->char2uni(&s2[i], len2 - i, &c2);
+ if (unlikely(l1 < 0 && l2 < 0)) {
+ if (s1[i] != s2[i])
+ return false;
+ l1 = 1;
+ continue;
+ }
+ if (l1 != l2)
+ return false;
+ if (cifs_toupper(c1) != cifs_toupper(c2))
+ return false;
+ }
+ return true;
+}
+
+static struct cache_entry *__lookup_cache_entry(const char *path, unsigned int hash, int len)
+{
+ struct cache_entry *ce;
+
+ hlist_for_each_entry(ce, &cache_htable[hash], hlist) {
+ if (dfs_path_equal(ce->path, strlen(ce->path), path, len)) {
+ dump_ce(ce);
+ return ce;
+ }
+ }
+ return ERR_PTR(-ENOENT);
+}
+
+/*
+ * Find a DFS cache entry in hash table and optionally check prefix path against normalized @path.
+ *
+ * Use whole path components in the match. Must be called with htable_rw_lock held.
+ *
+ * Return ERR_PTR(-ENOENT) if the entry is not found.
+ */
+static struct cache_entry *lookup_cache_entry(const char *path)
+{
+ struct cache_entry *ce;
+ int cnt = 0;
+ const char *s = path, *e;
+ char sep = *s;
+ unsigned int hash;
+ int rc;
+
+ while ((s = strchr(s, sep)) && ++cnt < 3)
+ s++;
+
+ if (cnt < 3) {
+ rc = cache_entry_hash(path, strlen(path), &hash);
+ if (rc)
+ return ERR_PTR(rc);
+ return __lookup_cache_entry(path, hash, strlen(path));
+ }
+ /*
+ * Handle paths that have more than two path components and are a complete prefix of the DFS
+ * referral request path (@path).
+ *
+ * See MS-DFSC 3.2.5.5 "Receiving a Root Referral Request or Link Referral Request".
+ */
+ e = path + strlen(path) - 1;
+ while (e > s) {
+ int len;
+
+ /* skip separators */
+ while (e > s && *e == sep)
+ e--;
+ if (e == s)
+ break;
+
+ len = e + 1 - path;
+ rc = cache_entry_hash(path, len, &hash);
+ if (rc)
+ return ERR_PTR(rc);
+ ce = __lookup_cache_entry(path, hash, len);
+ if (!IS_ERR(ce))
+ return ce;
+
+ /* backward until separator */
+ while (e > s && *e != sep)
+ e--;
+ }
+ return ERR_PTR(-ENOENT);
+}
+
+/**
+ * dfs_cache_destroy - destroy DFS referral cache
+ */
+void dfs_cache_destroy(void)
+{
+ cancel_delayed_work_sync(&refresh_task);
+ unload_nls(cache_cp);
+ free_mount_group_list();
+ flush_cache_ents();
+ kmem_cache_destroy(cache_slab);
+ destroy_workqueue(dfscache_wq);
+
+ cifs_dbg(FYI, "%s: destroyed DFS referral cache\n", __func__);
+}
+
+/* Update a cache entry with the new referral in @refs */
+static int update_cache_entry_locked(struct cache_entry *ce, const struct dfs_info3_param *refs,
+ int numrefs)
+{
+ int rc;
+ char *s, *th = NULL;
+
+ WARN_ON(!rwsem_is_locked(&htable_rw_lock));
+
+ if (ce->tgthint) {
+ s = ce->tgthint->name;
+ th = kstrdup(s, GFP_ATOMIC);
+ if (!th)
+ return -ENOMEM;
+ }
+
+ free_tgts(ce);
+ ce->numtgts = 0;
+
+ rc = copy_ref_data(refs, numrefs, ce, th);
+
+ kfree(th);
+
+ return rc;
+}
+
+static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, const char *path,
+ struct dfs_info3_param **refs, int *numrefs)
+{
+ int rc;
+ int i;
+
+ cifs_dbg(FYI, "%s: get an DFS referral for %s\n", __func__, path);
+
+ *refs = NULL;
+ *numrefs = 0;
+
+ if (!ses || !ses->server || !ses->server->ops->get_dfs_refer)
+ return -EOPNOTSUPP;
+ if (unlikely(!cache_cp))
+ return -EINVAL;
+
+ rc = ses->server->ops->get_dfs_refer(xid, ses, path, refs, numrefs, cache_cp,
+ NO_MAP_UNI_RSVD);
+ if (!rc) {
+ struct dfs_info3_param *ref = *refs;
+
+ for (i = 0; i < *numrefs; i++)
+ convert_delimiter(ref[i].path_name, '\\');
+ }
+ return rc;
+}
+
+/*
+ * Find, create or update a DFS cache entry.
+ *
+ * If the entry wasn't found, it will create a new one. Or if it was found but
+ * expired, then it will update the entry accordingly.
+ *
+ * For interlinks, cifs_mount() and expand_dfs_referral() are supposed to
+ * handle them properly.
+ */
+static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses, const char *path)
+{
+ struct dfs_info3_param *refs = NULL;
+ struct cache_entry *ce;
+ int numrefs = 0;
+ int rc;
+
+ cifs_dbg(FYI, "%s: search path: %s\n", __func__, path);
+
+ down_read(&htable_rw_lock);
+
+ ce = lookup_cache_entry(path);
+ if (!IS_ERR(ce) && !cache_entry_expired(ce)) {
+ up_read(&htable_rw_lock);
+ return 0;
+ }
+ /*
+ * Unlock shared access as we don't want to hold any locks while getting
+ * a new referral. The @ses used for performing the I/O could be
+ * reconnecting and it acquires @htable_rw_lock to look up the dfs cache
+ * in order to failover -- if necessary.
+ */
+ up_read(&htable_rw_lock);
+
+ /*
+ * Either the entry was not found, or it is expired.
+ * Request a new DFS referral in order to create or update a cache entry.
+ */
+ rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
+ if (rc)
+ goto out;
+
+ dump_refs(refs, numrefs);
+
+ down_write(&htable_rw_lock);
+ /* Re-check as another task might have it added or refreshed already */
+ ce = lookup_cache_entry(path);
+ if (!IS_ERR(ce)) {
+ if (cache_entry_expired(ce))
+ rc = update_cache_entry_locked(ce, refs, numrefs);
+ } else {
+ rc = add_cache_entry_locked(refs, numrefs);
+ }
+
+ up_write(&htable_rw_lock);
+out:
+ free_dfs_info_array(refs, numrefs);
+ return rc;
+}
+
+/*
+ * Set up a DFS referral from a given cache entry.
+ *
+ * Must be called with htable_rw_lock held.
+ */
+static int setup_referral(const char *path, struct cache_entry *ce,
+ struct dfs_info3_param *ref, const char *target)
+{
+ int rc;
+
+ cifs_dbg(FYI, "%s: set up new ref\n", __func__);
+
+ memset(ref, 0, sizeof(*ref));
+
+ ref->path_name = kstrdup(path, GFP_ATOMIC);
+ if (!ref->path_name)
+ return -ENOMEM;
+
+ ref->node_name = kstrdup(target, GFP_ATOMIC);
+ if (!ref->node_name) {
+ rc = -ENOMEM;
+ goto err_free_path;
+ }
+
+ ref->path_consumed = ce->path_consumed;
+ ref->ttl = ce->ttl;
+ ref->server_type = ce->srvtype;
+ ref->ref_flag = ce->ref_flags;
+ ref->flags = ce->hdr_flags;
+
+ return 0;
+
+err_free_path:
+ kfree(ref->path_name);
+ ref->path_name = NULL;
+ return rc;
+}
+
+/* Return target list of a DFS cache entry */
+static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
+{
+ int rc;
+ struct list_head *head = &tl->tl_list;
+ struct cache_dfs_tgt *t;
+ struct dfs_cache_tgt_iterator *it, *nit;
+
+ memset(tl, 0, sizeof(*tl));
+ INIT_LIST_HEAD(head);
+
+ list_for_each_entry(t, &ce->tlist, list) {
+ it = kzalloc(sizeof(*it), GFP_ATOMIC);
+ if (!it) {
+ rc = -ENOMEM;
+ goto err_free_it;
+ }
+
+ it->it_name = kstrdup(t->name, GFP_ATOMIC);
+ if (!it->it_name) {
+ kfree(it);
+ rc = -ENOMEM;
+ goto err_free_it;
+ }
+ it->it_path_consumed = t->path_consumed;
+
+ if (ce->tgthint == t)
+ list_add(&it->it_list, head);
+ else
+ list_add_tail(&it->it_list, head);
+ }
+
+ tl->tl_numtgts = ce->numtgts;
+
+ return 0;
+
+err_free_it:
+ list_for_each_entry_safe(it, nit, head, it_list) {
+ list_del(&it->it_list);
+ kfree(it->it_name);
+ kfree(it);
+ }
+ return rc;
+}
+
+/**
+ * dfs_cache_find - find a DFS cache entry
+ *
+ * If it doesn't find the cache entry, then it will get a DFS referral
+ * for @path and create a new entry.
+ *
+ * In case the cache entry exists but expired, it will get a DFS referral
+ * for @path and then update the respective cache entry.
+ *
+ * These parameters are passed down to the get_dfs_refer() call if it
+ * needs to be issued:
+ * @xid: syscall xid
+ * @ses: smb session to issue the request on
+ * @cp: codepage
+ * @remap: path character remapping type
+ * @path: path to lookup in DFS referral cache.
+ *
+ * @ref: when non-NULL, store single DFS referral result in it.
+ * @tgt_list: when non-NULL, store complete DFS target list in it.
+ *
+ * Return zero if the target was found, otherwise non-zero.
+ */
+int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *cp,
+ int remap, const char *path, struct dfs_info3_param *ref,
+ struct dfs_cache_tgt_list *tgt_list)
+{
+ int rc;
+ const char *npath;
+ struct cache_entry *ce;
+
+ npath = dfs_cache_canonical_path(path, cp, remap);
+ if (IS_ERR(npath))
+ return PTR_ERR(npath);
+
+ rc = cache_refresh_path(xid, ses, npath);
+ if (rc)
+ goto out_free_path;
+
+ down_read(&htable_rw_lock);
+
+ ce = lookup_cache_entry(npath);
+ if (IS_ERR(ce)) {
+ up_read(&htable_rw_lock);
+ rc = PTR_ERR(ce);
+ goto out_free_path;
+ }
+
+ if (ref)
+ rc = setup_referral(path, ce, ref, get_tgt_name(ce));
+ else
+ rc = 0;
+ if (!rc && tgt_list)
+ rc = get_targets(ce, tgt_list);
+
+ up_read(&htable_rw_lock);
+
+out_free_path:
+ kfree(npath);
+ return rc;
+}
+
+/**
+ * dfs_cache_noreq_find - find a DFS cache entry without sending any requests to
+ * the currently connected server.
+ *
+ * NOTE: This function will neither update a cache entry in case it was
+ * expired, nor create a new cache entry if @path hasn't been found. It heavily
+ * relies on an existing cache entry.
+ *
+ * @path: canonical DFS path to lookup in the DFS referral cache.
+ * @ref: when non-NULL, store single DFS referral result in it.
+ * @tgt_list: when non-NULL, store complete DFS target list in it.
+ *
+ * Return 0 if successful.
+ * Return -ENOENT if the entry was not found.
+ * Return non-zero for other errors.
+ */
+int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
+ struct dfs_cache_tgt_list *tgt_list)
+{
+ int rc;
+ struct cache_entry *ce;
+
+ cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
+
+ down_read(&htable_rw_lock);
+
+ ce = lookup_cache_entry(path);
+ if (IS_ERR(ce)) {
+ rc = PTR_ERR(ce);
+ goto out_unlock;
+ }
+
+ if (ref)
+ rc = setup_referral(path, ce, ref, get_tgt_name(ce));
+ else
+ rc = 0;
+ if (!rc && tgt_list)
+ rc = get_targets(ce, tgt_list);
+
+out_unlock:
+ up_read(&htable_rw_lock);
+ return rc;
+}
+
+/**
+ * dfs_cache_update_tgthint - update target hint of a DFS cache entry
+ *
+ * If it doesn't find the cache entry, then it will get a DFS referral for @path
+ * and create a new entry.
+ *
+ * In case the cache entry exists but expired, it will get a DFS referral
+ * for @path and then update the respective cache entry.
+ *
+ * @xid: syscall id
+ * @ses: smb session
+ * @cp: codepage
+ * @remap: type of character remapping for paths
+ * @path: path to lookup in DFS referral cache
+ * @it: DFS target iterator
+ *
+ * Return zero if the target hint was updated successfully, otherwise non-zero.
+ */
+int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
+ const struct nls_table *cp, int remap, const char *path,
+ const struct dfs_cache_tgt_iterator *it)
+{
+ struct cache_dfs_tgt *t;
+ struct cache_entry *ce;
+ const char *npath;
+ int rc = 0;
+
+ npath = dfs_cache_canonical_path(path, cp, remap);
+ if (IS_ERR(npath))
+ return PTR_ERR(npath);
+
+ cifs_dbg(FYI, "%s: update target hint - path: %s\n", __func__, npath);
+
+ rc = cache_refresh_path(xid, ses, npath);
+ if (rc)
+ goto out_free_path;
+
+ down_write(&htable_rw_lock);
+
+ ce = lookup_cache_entry(npath);
+ if (IS_ERR(ce)) {
+ rc = PTR_ERR(ce);
+ goto out_unlock;
+ }
+
+ t = ce->tgthint;
+
+ if (likely(!strcasecmp(it->it_name, t->name)))
+ goto out_unlock;
+
+ list_for_each_entry(t, &ce->tlist, list) {
+ if (!strcasecmp(t->name, it->it_name)) {
+ ce->tgthint = t;
+ cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
+ it->it_name);
+ break;
+ }
+ }
+
+out_unlock:
+ up_write(&htable_rw_lock);
+out_free_path:
+ kfree(npath);
+ return rc;
+}
+
+/**
+ * dfs_cache_noreq_update_tgthint - update target hint of a DFS cache entry
+ * without sending any requests to the currently connected server.
+ *
+ * NOTE: This function will neither update a cache entry in case it was
+ * expired, nor create a new cache entry if @path hasn't been found. It heavily
+ * relies on an existing cache entry.
+ *
+ * @path: canonical DFS path to lookup in DFS referral cache.
+ * @it: target iterator which contains the target hint to update the cache
+ * entry with.
+ *
+ * Return zero if the target hint was updated successfully, otherwise non-zero.
+ */
+int dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt_iterator *it)
+{
+ int rc;
+ struct cache_entry *ce;
+ struct cache_dfs_tgt *t;
+
+ if (!it)
+ return -EINVAL;
+
+ cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
+
+ down_write(&htable_rw_lock);
+
+ ce = lookup_cache_entry(path);
+ if (IS_ERR(ce)) {
+ rc = PTR_ERR(ce);
+ goto out_unlock;
+ }
+
+ rc = 0;
+ t = ce->tgthint;
+
+ if (unlikely(!strcasecmp(it->it_name, t->name)))
+ goto out_unlock;
+
+ list_for_each_entry(t, &ce->tlist, list) {
+ if (!strcasecmp(t->name, it->it_name)) {
+ ce->tgthint = t;
+ cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
+ it->it_name);
+ break;
+ }
+ }
+
+out_unlock:
+ up_write(&htable_rw_lock);
+ return rc;
+}
+
+/**
+ * dfs_cache_get_tgt_referral - returns a DFS referral (@ref) from a given
+ * target iterator (@it).
+ *
+ * @path: canonical DFS path to lookup in DFS referral cache.
+ * @it: DFS target iterator.
+ * @ref: DFS referral pointer to set up the gathered information.
+ *
+ * Return zero if the DFS referral was set up correctly, otherwise non-zero.
+ */
+int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iterator *it,
+ struct dfs_info3_param *ref)
+{
+ int rc;
+ struct cache_entry *ce;
+
+ if (!it || !ref)
+ return -EINVAL;
+
+ cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
+
+ down_read(&htable_rw_lock);
+
+ ce = lookup_cache_entry(path);
+ if (IS_ERR(ce)) {
+ rc = PTR_ERR(ce);
+ goto out_unlock;
+ }
+
+ cifs_dbg(FYI, "%s: target name: %s\n", __func__, it->it_name);
+
+ rc = setup_referral(path, ce, ref, it->it_name);
+
+out_unlock:
+ up_read(&htable_rw_lock);
+ return rc;
+}
+
+/**
+ * dfs_cache_add_refsrv_session - add SMB session of referral server
+ *
+ * @mount_id: mount group uuid to lookup.
+ * @ses: reference counted SMB session of referral server.
+ */
+void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses)
+{
+ struct mount_group *mg;
+
+ if (WARN_ON_ONCE(!mount_id || uuid_is_null(mount_id) || !ses))
+ return;
+
+ mg = get_mount_group(mount_id);
+ if (WARN_ON_ONCE(IS_ERR(mg)))
+ return;
+
+ spin_lock(&mg->lock);
+ if (mg->num_sessions < ARRAY_SIZE(mg->sessions))
+ mg->sessions[mg->num_sessions++] = ses;
+ spin_unlock(&mg->lock);
+ kref_put(&mg->refcount, mount_group_release);
+}
+
+/**
+ * dfs_cache_put_refsrv_sessions - put all referral server sessions
+ *
+ * Put all SMB sessions from the given mount group id.
+ *
+ * @mount_id: mount group uuid to lookup.
+ */
+void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id)
+{
+ struct mount_group *mg;
+
+ if (!mount_id || uuid_is_null(mount_id))
+ return;
+
+ mutex_lock(&mount_group_list_lock);
+ mg = find_mount_group_locked(mount_id);
+ if (IS_ERR(mg)) {
+ mutex_unlock(&mount_group_list_lock);
+ return;
+ }
+ mutex_unlock(&mount_group_list_lock);
+ kref_put(&mg->refcount, mount_group_release);
+}
+
+/* Extract share from DFS target and return a pointer to prefix path or NULL */
+static const char *parse_target_share(const char *target, char **share)
+{
+ const char *s, *seps = "/\\";
+ size_t len;
+
+ s = strpbrk(target + 1, seps);
+ if (!s)
+ return ERR_PTR(-EINVAL);
+
+ len = strcspn(s + 1, seps);
+ if (!len)
+ return ERR_PTR(-EINVAL);
+ s += len;
+
+ len = s - target + 1;
+ *share = kstrndup(target, len, GFP_KERNEL);
+ if (!*share)
+ return ERR_PTR(-ENOMEM);
+
+ s = target + len;
+ return s + strspn(s, seps);
+}
+
+/**
+ * dfs_cache_get_tgt_share - parse a DFS target
+ *
+ * @path: DFS full path
+ * @it: DFS target iterator.
+ * @share: tree name.
+ * @prefix: prefix path.
+ *
+ * Return zero if target was parsed correctly, otherwise non-zero.
+ */
+int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, char **share,
+ char **prefix)
+{
+ char sep;
+ char *target_share;
+ char *ppath = NULL;
+ const char *target_ppath, *dfsref_ppath;
+ size_t target_pplen, dfsref_pplen;
+ size_t len, c;
+
+ if (!it || !path || !share || !prefix || strlen(path) < it->it_path_consumed)
+ return -EINVAL;
+
+ sep = it->it_name[0];
+ if (sep != '\\' && sep != '/')
+ return -EINVAL;
+
+ target_ppath = parse_target_share(it->it_name, &target_share);
+ if (IS_ERR(target_ppath))
+ return PTR_ERR(target_ppath);
+
+ /* point to prefix in DFS referral path */
+ dfsref_ppath = path + it->it_path_consumed;
+ dfsref_ppath += strspn(dfsref_ppath, "/\\");
+
+ target_pplen = strlen(target_ppath);
+ dfsref_pplen = strlen(dfsref_ppath);
+
+ /* merge prefix paths from DFS referral path and target node */
+ if (target_pplen || dfsref_pplen) {
+ len = target_pplen + dfsref_pplen + 2;
+ ppath = kzalloc(len, GFP_KERNEL);
+ if (!ppath) {
+ kfree(target_share);
+ return -ENOMEM;
+ }
+ c = strscpy(ppath, target_ppath, len);
+ if (c && dfsref_pplen)
+ ppath[c] = sep;
+ strlcat(ppath, dfsref_ppath, len);
+ }
+ *share = target_share;
+ *prefix = ppath;
+ return 0;
+}
+
+static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, const char *s2)
+{
+ char unc[sizeof("\\\\") + SERVER_NAME_LENGTH] = {0};
+ const char *host;
+ size_t hostlen;
+ char *ip = NULL;
+ struct sockaddr sa;
+ bool match;
+ int rc;
+
+ if (strcasecmp(s1, s2))
+ return false;
+
+ /*
+ * Resolve share's hostname and check if server address matches. Otherwise just ignore it
+ * as we could not have upcall to resolve hostname or failed to convert ip address.
+ */
+ match = true;
+ extract_unc_hostname(s1, &host, &hostlen);
+ scnprintf(unc, sizeof(unc), "\\\\%.*s", (int)hostlen, host);
+
+ rc = dns_resolve_server_name_to_ip(unc, &ip, NULL);
+ if (rc < 0) {
+ cifs_dbg(FYI, "%s: could not resolve %.*s. assuming server address matches.\n",
+ __func__, (int)hostlen, host);
+ return true;
+ }
+
+ if (!cifs_convert_address(&sa, ip, strlen(ip))) {
+ cifs_dbg(VFS, "%s: failed to convert address \'%s\'. skip address matching.\n",
+ __func__, ip);
+ } else {
+ cifs_server_lock(server);
+ match = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, &sa);
+ cifs_server_unlock(server);
+ }
+
+ kfree(ip);
+ return match;
+}
+
+/*
+ * Mark dfs tcon for reconnecting when the currently connected tcon does not match any of the new
+ * target shares in @refs.
+ */
+static void mark_for_reconnect_if_needed(struct cifs_tcon *tcon, struct dfs_cache_tgt_list *tl,
+ const struct dfs_info3_param *refs, int numrefs)
+{
+ struct dfs_cache_tgt_iterator *it;
+ int i;
+
+ for (it = dfs_cache_get_tgt_iterator(tl); it; it = dfs_cache_get_next_tgt(tl, it)) {
+ for (i = 0; i < numrefs; i++) {
+ if (target_share_equal(tcon->ses->server, dfs_cache_get_tgt_name(it),
+ refs[i].node_name))
+ return;
+ }
+ }
+
+ cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__);
+ cifs_signal_cifsd_for_reconnect(tcon->ses->server, true);
+}
+
+/* Refresh dfs referral of tcon and mark it for reconnect if needed */
+static int __refresh_tcon(const char *path, struct cifs_ses **sessions, struct cifs_tcon *tcon,
+ bool force_refresh)
+{
+ struct cifs_ses *ses;
+ struct cache_entry *ce;
+ struct dfs_info3_param *refs = NULL;
+ int numrefs = 0;
+ bool needs_refresh = false;
+ struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
+ int rc = 0;
+ unsigned int xid;
+
+ ses = find_ipc_from_server_path(sessions, path);
+ if (IS_ERR(ses)) {
+ cifs_dbg(FYI, "%s: could not find ipc session\n", __func__);
+ return PTR_ERR(ses);
+ }
+
+ down_read(&htable_rw_lock);
+ ce = lookup_cache_entry(path);
+ needs_refresh = force_refresh || IS_ERR(ce) || cache_entry_expired(ce);
+ if (!IS_ERR(ce)) {
+ rc = get_targets(ce, &tl);
+ if (rc)
+ cifs_dbg(FYI, "%s: could not get dfs targets: %d\n", __func__, rc);
+ }
+ up_read(&htable_rw_lock);
+
+ if (!needs_refresh) {
+ rc = 0;
+ goto out;
+ }
+
+ xid = get_xid();
+ rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
+ free_xid(xid);
+
+ /* Create or update a cache entry with the new referral */
+ if (!rc) {
+ dump_refs(refs, numrefs);
+
+ down_write(&htable_rw_lock);
+ ce = lookup_cache_entry(path);
+ if (IS_ERR(ce))
+ add_cache_entry_locked(refs, numrefs);
+ else if (force_refresh || cache_entry_expired(ce))
+ update_cache_entry_locked(ce, refs, numrefs);
+ up_write(&htable_rw_lock);
+
+ mark_for_reconnect_if_needed(tcon, &tl, refs, numrefs);
+ }
+
+out:
+ dfs_cache_free_tgts(&tl);
+ free_dfs_info_array(refs, numrefs);
+ return rc;
+}
+
+static int refresh_tcon(struct cifs_ses **sessions, struct cifs_tcon *tcon, bool force_refresh)
+{
+ struct TCP_Server_Info *server = tcon->ses->server;
+
+ mutex_lock(&server->refpath_lock);
+ if (server->origin_fullpath) {
+ if (server->leaf_fullpath && strcasecmp(server->leaf_fullpath,
+ server->origin_fullpath))
+ __refresh_tcon(server->leaf_fullpath + 1, sessions, tcon, force_refresh);
+ __refresh_tcon(server->origin_fullpath + 1, sessions, tcon, force_refresh);
+ }
+ mutex_unlock(&server->refpath_lock);
+
+ return 0;
+}
+
+/**
+ * dfs_cache_remount_fs - remount a DFS share
+ *
+ * Reconfigure dfs mount by forcing a new DFS referral and if the currently cached targets do not
+ * match any of the new targets, mark it for reconnect.
+ *
+ * @cifs_sb: cifs superblock.
+ *
+ * Return zero if remounted, otherwise non-zero.
+ */
+int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb)
+{
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct mount_group *mg;
+ struct cifs_ses *sessions[CACHE_MAX_ENTRIES + 1] = {NULL};
+ int rc;
+
+ if (!cifs_sb || !cifs_sb->master_tlink)
+ return -EINVAL;
+
+ tcon = cifs_sb_master_tcon(cifs_sb);
+ server = tcon->ses->server;
+
+ if (!server->origin_fullpath) {
+ cifs_dbg(FYI, "%s: not a dfs mount\n", __func__);
+ return 0;
+ }
+
+ if (uuid_is_null(&cifs_sb->dfs_mount_id)) {
+ cifs_dbg(FYI, "%s: no dfs mount group id\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&mount_group_list_lock);
+ mg = find_mount_group_locked(&cifs_sb->dfs_mount_id);
+ if (IS_ERR(mg)) {
+ mutex_unlock(&mount_group_list_lock);
+ cifs_dbg(FYI, "%s: no ipc session for refreshing referral\n", __func__);
+ return PTR_ERR(mg);
+ }
+ kref_get(&mg->refcount);
+ mutex_unlock(&mount_group_list_lock);
+
+ spin_lock(&mg->lock);
+ memcpy(&sessions, mg->sessions, mg->num_sessions * sizeof(mg->sessions[0]));
+ spin_unlock(&mg->lock);
+
+ /*
+ * After reconnecting to a different server, unique ids won't match anymore, so we disable
+ * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE).
+ */
+ cifs_autodisable_serverino(cifs_sb);
+ /*
+ * Force the use of prefix path to support failover on DFS paths that resolve to targets
+ * that have different prefix paths.
+ */
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
+ rc = refresh_tcon(sessions, tcon, true);
+
+ kref_put(&mg->refcount, mount_group_release);
+ return rc;
+}
+
+/*
+ * Refresh all active dfs mounts regardless of whether they are in cache or not.
+ * (cache can be cleared)
+ */
+static void refresh_mounts(struct cifs_ses **sessions)
+{
+ struct TCP_Server_Info *server;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon, *ntcon;
+ struct list_head tcons;
+
+ INIT_LIST_HEAD(&tcons);
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
+ spin_lock(&server->srv_lock);
+ if (!server->is_dfs_conn) {
+ spin_unlock(&server->srv_lock);
+ continue;
+ }
+ spin_unlock(&server->srv_lock);
+
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ spin_lock(&tcon->tc_lock);
+ if (!tcon->ipc && !tcon->need_reconnect) {
+ tcon->tc_count++;
+ list_add_tail(&tcon->ulist, &tcons);
+ }
+ spin_unlock(&tcon->tc_lock);
+ }
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ list_for_each_entry_safe(tcon, ntcon, &tcons, ulist) {
+ struct TCP_Server_Info *server = tcon->ses->server;
+
+ list_del_init(&tcon->ulist);
+
+ mutex_lock(&server->refpath_lock);
+ if (server->origin_fullpath) {
+ if (server->leaf_fullpath && strcasecmp(server->leaf_fullpath,
+ server->origin_fullpath))
+ __refresh_tcon(server->leaf_fullpath + 1, sessions, tcon, false);
+ __refresh_tcon(server->origin_fullpath + 1, sessions, tcon, false);
+ }
+ mutex_unlock(&server->refpath_lock);
+
+ cifs_put_tcon(tcon);
+ }
+}
+
+static void refresh_cache(struct cifs_ses **sessions)
+{
+ int i;
+ struct cifs_ses *ses;
+ unsigned int xid;
+ char *ref_paths[CACHE_MAX_ENTRIES];
+ int count = 0;
+ struct cache_entry *ce;
+
+ /*
+ * Refresh all cached entries. Get all new referrals outside critical section to avoid
+ * starvation while performing SMB2 IOCTL on broken or slow connections.
+
+ * The cache entries may cover more paths than the active mounts
+ * (e.g. domain-based DFS referrals or multi tier DFS setups).
+ */
+ down_read(&htable_rw_lock);
+ for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
+ struct hlist_head *l = &cache_htable[i];
+
+ hlist_for_each_entry(ce, l, hlist) {
+ if (count == ARRAY_SIZE(ref_paths))
+ goto out_unlock;
+ if (hlist_unhashed(&ce->hlist) || !cache_entry_expired(ce) ||
+ IS_ERR(find_ipc_from_server_path(sessions, ce->path)))
+ continue;
+ ref_paths[count++] = kstrdup(ce->path, GFP_ATOMIC);
+ }
+ }
+
+out_unlock:
+ up_read(&htable_rw_lock);
+
+ for (i = 0; i < count; i++) {
+ char *path = ref_paths[i];
+ struct dfs_info3_param *refs = NULL;
+ int numrefs = 0;
+ int rc = 0;
+
+ if (!path)
+ continue;
+
+ ses = find_ipc_from_server_path(sessions, path);
+ if (IS_ERR(ses))
+ goto next_referral;
+
+ xid = get_xid();
+ rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
+ free_xid(xid);
+
+ if (!rc) {
+ down_write(&htable_rw_lock);
+ ce = lookup_cache_entry(path);
+ /*
+ * We need to re-check it because other tasks might have it deleted or
+ * updated.
+ */
+ if (!IS_ERR(ce) && cache_entry_expired(ce))
+ update_cache_entry_locked(ce, refs, numrefs);
+ up_write(&htable_rw_lock);
+ }
+
+next_referral:
+ kfree(path);
+ free_dfs_info_array(refs, numrefs);
+ }
+}
+
+/*
+ * Worker that will refresh DFS cache and active mounts based on lowest TTL value from a DFS
+ * referral.
+ */
+static void refresh_cache_worker(struct work_struct *work)
+{
+ struct list_head mglist;
+ struct mount_group *mg, *tmp_mg;
+ struct cifs_ses *sessions[CACHE_MAX_ENTRIES + 1] = {NULL};
+ int max_sessions = ARRAY_SIZE(sessions) - 1;
+ int i = 0, count;
+
+ INIT_LIST_HEAD(&mglist);
+
+ /* Get refereces of mount groups */
+ mutex_lock(&mount_group_list_lock);
+ list_for_each_entry(mg, &mount_group_list, list) {
+ kref_get(&mg->refcount);
+ list_add(&mg->refresh_list, &mglist);
+ }
+ mutex_unlock(&mount_group_list_lock);
+
+ /* Fill in local array with an NULL-terminated list of all referral server sessions */
+ list_for_each_entry(mg, &mglist, refresh_list) {
+ if (i >= max_sessions)
+ break;
+
+ spin_lock(&mg->lock);
+ if (i + mg->num_sessions > max_sessions)
+ count = max_sessions - i;
+ else
+ count = mg->num_sessions;
+ memcpy(&sessions[i], mg->sessions, count * sizeof(mg->sessions[0]));
+ spin_unlock(&mg->lock);
+ i += count;
+ }
+
+ if (sessions[0]) {
+ /* Refresh all active mounts and cached entries */
+ refresh_mounts(sessions);
+ refresh_cache(sessions);
+ }
+
+ list_for_each_entry_safe(mg, tmp_mg, &mglist, refresh_list) {
+ list_del_init(&mg->refresh_list);
+ kref_put(&mg->refcount, mount_group_release);
+ }
+
+ spin_lock(&cache_ttl_lock);
+ queue_delayed_work(dfscache_wq, &refresh_task, cache_ttl * HZ);
+ spin_unlock(&cache_ttl_lock);
+}
diff --git a/fs/smb/client/dfs_cache.h b/fs/smb/client/dfs_cache.h
new file mode 100644
index 000000000000..52070d1df189
--- /dev/null
+++ b/fs/smb/client/dfs_cache.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * DFS referral cache routines
+ *
+ * Copyright (c) 2018-2019 Paulo Alcantara <palcantara@suse.de>
+ */
+
+#ifndef _CIFS_DFS_CACHE_H
+#define _CIFS_DFS_CACHE_H
+
+#include <linux/nls.h>
+#include <linux/list.h>
+#include <linux/uuid.h>
+#include "cifsglob.h"
+
+#define DFS_CACHE_TGT_LIST_INIT(var) { .tl_numtgts = 0, .tl_list = LIST_HEAD_INIT((var).tl_list), }
+
+struct dfs_cache_tgt_list {
+ int tl_numtgts;
+ struct list_head tl_list;
+};
+
+struct dfs_cache_tgt_iterator {
+ char *it_name;
+ int it_path_consumed;
+ struct list_head it_list;
+};
+
+int dfs_cache_init(void);
+void dfs_cache_destroy(void);
+extern const struct proc_ops dfscache_proc_ops;
+
+int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *cp,
+ int remap, const char *path, struct dfs_info3_param *ref,
+ struct dfs_cache_tgt_list *tgt_list);
+int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
+ struct dfs_cache_tgt_list *tgt_list);
+int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
+ const struct nls_table *cp, int remap, const char *path,
+ const struct dfs_cache_tgt_iterator *it);
+int dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt_iterator *it);
+int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iterator *it,
+ struct dfs_info3_param *ref);
+int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, char **share,
+ char **prefix);
+void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id);
+void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses);
+char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap);
+int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb);
+
+static inline struct dfs_cache_tgt_iterator *
+dfs_cache_get_next_tgt(struct dfs_cache_tgt_list *tl,
+ struct dfs_cache_tgt_iterator *it)
+{
+ if (!tl || list_empty(&tl->tl_list) || !it ||
+ list_is_last(&it->it_list, &tl->tl_list))
+ return NULL;
+ return list_next_entry(it, it_list);
+}
+
+static inline struct dfs_cache_tgt_iterator *
+dfs_cache_get_tgt_iterator(struct dfs_cache_tgt_list *tl)
+{
+ if (!tl)
+ return NULL;
+ return list_first_entry_or_null(&tl->tl_list,
+ struct dfs_cache_tgt_iterator,
+ it_list);
+}
+
+static inline void dfs_cache_free_tgts(struct dfs_cache_tgt_list *tl)
+{
+ struct dfs_cache_tgt_iterator *it, *nit;
+
+ if (!tl || list_empty(&tl->tl_list))
+ return;
+ list_for_each_entry_safe(it, nit, &tl->tl_list, it_list) {
+ list_del(&it->it_list);
+ kfree(it->it_name);
+ kfree(it);
+ }
+ tl->tl_numtgts = 0;
+}
+
+static inline const char *
+dfs_cache_get_tgt_name(const struct dfs_cache_tgt_iterator *it)
+{
+ return it ? it->it_name : NULL;
+}
+
+static inline int
+dfs_cache_get_nr_tgts(const struct dfs_cache_tgt_list *tl)
+{
+ return tl ? tl->tl_numtgts : 0;
+}
+
+#endif /* _CIFS_DFS_CACHE_H */
diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
new file mode 100644
index 000000000000..e382b794acbe
--- /dev/null
+++ b/fs/smb/client/dir.c
@@ -0,0 +1,867 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * vfs operations that deal with dentries
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2009
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/file.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifs_unicode.h"
+#include "fs_context.h"
+#include "cifs_ioctl.h"
+#include "fscache.h"
+
+static void
+renew_parental_timestamps(struct dentry *direntry)
+{
+ /* BB check if there is a way to get the kernel to do this or if we
+ really need this */
+ do {
+ cifs_set_time(direntry, jiffies);
+ direntry = direntry->d_parent;
+ } while (!IS_ROOT(direntry));
+}
+
+char *
+cifs_build_path_to_root(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb,
+ struct cifs_tcon *tcon, int add_treename)
+{
+ int pplen = ctx->prepath ? strlen(ctx->prepath) + 1 : 0;
+ int dfsplen;
+ char *full_path = NULL;
+
+ /* if no prefix path, simply set path to the root of share to "" */
+ if (pplen == 0) {
+ full_path = kzalloc(1, GFP_KERNEL);
+ return full_path;
+ }
+
+ if (add_treename)
+ dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
+ else
+ dfsplen = 0;
+
+ full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
+ if (full_path == NULL)
+ return full_path;
+
+ if (dfsplen)
+ memcpy(full_path, tcon->tree_name, dfsplen);
+ full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb);
+ memcpy(full_path + dfsplen + 1, ctx->prepath, pplen);
+ convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
+ return full_path;
+}
+
+/* Note: caller must free return buffer */
+const char *
+build_path_from_dentry(struct dentry *direntry, void *page)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ bool prefix = tcon->Flags & SMB_SHARE_IS_IN_DFS;
+
+ return build_path_from_dentry_optional_prefix(direntry, page,
+ prefix);
+}
+
+char *
+build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
+ bool prefix)
+{
+ int dfsplen;
+ int pplen = 0;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ char dirsep = CIFS_DIR_SEP(cifs_sb);
+ char *s;
+
+ if (unlikely(!page))
+ return ERR_PTR(-ENOMEM);
+
+ if (prefix)
+ dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
+ else
+ dfsplen = 0;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
+ pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
+
+ s = dentry_path_raw(direntry, page, PATH_MAX);
+ if (IS_ERR(s))
+ return s;
+ if (!s[1]) // for root we want "", not "/"
+ s++;
+ if (s < (char *)page + pplen + dfsplen)
+ return ERR_PTR(-ENAMETOOLONG);
+ if (pplen) {
+ cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath);
+ s -= pplen;
+ memcpy(s + 1, cifs_sb->prepath, pplen - 1);
+ *s = '/';
+ }
+ if (dirsep != '/') {
+ /* BB test paths to Windows with '/' in the midst of prepath */
+ char *p;
+
+ for (p = s; *p; p++)
+ if (*p == '/')
+ *p = dirsep;
+ }
+ if (dfsplen) {
+ s -= dfsplen;
+ memcpy(s, tcon->tree_name, dfsplen);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
+ int i;
+ for (i = 0; i < dfsplen; i++) {
+ if (s[i] == '\\')
+ s[i] = '/';
+ }
+ }
+ }
+ return s;
+}
+
+/*
+ * Don't allow path components longer than the server max.
+ * Don't allow the separator character in a path component.
+ * The VFS will not allow "/", but "\" is allowed by posix.
+ */
+static int
+check_name(struct dentry *direntry, struct cifs_tcon *tcon)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+ int i;
+
+ if (unlikely(tcon->fsAttrInfo.MaxPathNameComponentLength &&
+ direntry->d_name.len >
+ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength)))
+ return -ENAMETOOLONG;
+
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
+ for (i = 0; i < direntry->d_name.len; i++) {
+ if (direntry->d_name.name[i] == '\\') {
+ cifs_dbg(FYI, "Invalid file name\n");
+ return -EINVAL;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/* Inode operations in similar order to how they appear in Linux file fs.h */
+
+static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
+ struct tcon_link *tlink, unsigned int oflags, umode_t mode, __u32 *oplock,
+ struct cifs_fid *fid, struct cifs_open_info_data *buf)
+{
+ int rc = -ENOENT;
+ int create_options = CREATE_NOT_DIR;
+ int desired_access;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifs_tcon *tcon = tlink_tcon(tlink);
+ const char *full_path;
+ void *page = alloc_dentry_path();
+ struct inode *newinode = NULL;
+ int disposition;
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifs_open_parms oparms;
+
+ *oplock = 0;
+ if (tcon->ses->server->oplocks)
+ *oplock = REQ_OPLOCK;
+
+ full_path = build_path_from_dentry(direntry, page);
+ if (IS_ERR(full_path)) {
+ free_dentry_path(page);
+ return PTR_ERR(full_path);
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
+ (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+ rc = cifs_posix_open(full_path, &newinode, inode->i_sb, mode,
+ oflags, oplock, &fid->netfid, xid);
+ switch (rc) {
+ case 0:
+ if (newinode == NULL) {
+ /* query inode info */
+ goto cifs_create_get_file_info;
+ }
+
+ if (S_ISDIR(newinode->i_mode)) {
+ CIFSSMBClose(xid, tcon, fid->netfid);
+ iput(newinode);
+ rc = -EISDIR;
+ goto out;
+ }
+
+ if (!S_ISREG(newinode->i_mode)) {
+ /*
+ * The server may allow us to open things like
+ * FIFOs, but the client isn't set up to deal
+ * with that. If it's not a regular file, just
+ * close it and proceed as if it were a normal
+ * lookup.
+ */
+ CIFSSMBClose(xid, tcon, fid->netfid);
+ goto cifs_create_get_file_info;
+ }
+ /* success, no need to query */
+ goto cifs_create_set_dentry;
+
+ case -ENOENT:
+ goto cifs_create_get_file_info;
+
+ case -EIO:
+ case -EINVAL:
+ /*
+ * EIO could indicate that (posix open) operation is not
+ * supported, despite what server claimed in capability
+ * negotiation.
+ *
+ * POSIX open in samba versions 3.3.1 and earlier could
+ * incorrectly fail with invalid parameter.
+ */
+ tcon->broken_posix_open = true;
+ break;
+
+ case -EREMOTE:
+ case -EOPNOTSUPP:
+ /*
+ * EREMOTE indicates DFS junction, which is not handled
+ * in posix open. If either that or op not supported
+ * returned, follow the normal lookup.
+ */
+ break;
+
+ default:
+ goto out;
+ }
+ /*
+ * fallthrough to retry, using older open call, this is case
+ * where server does not support this SMB level, and falsely
+ * claims capability (also get here for DFS case which should be
+ * rare for path not covered on files)
+ */
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ desired_access = 0;
+ if (OPEN_FMODE(oflags) & FMODE_READ)
+ desired_access |= GENERIC_READ; /* is this too little? */
+ if (OPEN_FMODE(oflags) & FMODE_WRITE)
+ desired_access |= GENERIC_WRITE;
+
+ disposition = FILE_OVERWRITE_IF;
+ if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ disposition = FILE_CREATE;
+ else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+ disposition = FILE_OVERWRITE_IF;
+ else if ((oflags & O_CREAT) == O_CREAT)
+ disposition = FILE_OPEN_IF;
+ else
+ cifs_dbg(FYI, "Create flag not set in create function\n");
+
+ /*
+ * BB add processing to set equivalent of mode - e.g. via CreateX with
+ * ACLs
+ */
+
+ if (!server->ops->open) {
+ rc = -ENOSYS;
+ goto out;
+ }
+
+ /*
+ * if we're not using unix extensions, see if we need to set
+ * ATTR_READONLY on the create call
+ */
+ if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
+ create_options |= CREATE_OPTION_READONLY;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = desired_access,
+ .create_options = cifs_create_options(cifs_sb, create_options),
+ .disposition = disposition,
+ .path = full_path,
+ .fid = fid,
+ .mode = mode,
+ };
+ rc = server->ops->open(xid, &oparms, oplock, buf);
+ if (rc) {
+ cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
+ goto out;
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ /*
+ * If Open reported that we actually created a file then we now have to
+ * set the mode if possible.
+ */
+ if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
+ struct cifs_unix_set_info_args args = {
+ .mode = mode,
+ .ctime = NO_CHANGE_64,
+ .atime = NO_CHANGE_64,
+ .mtime = NO_CHANGE_64,
+ .device = 0,
+ };
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ args.uid = current_fsuid();
+ if (inode->i_mode & S_ISGID)
+ args.gid = inode->i_gid;
+ else
+ args.gid = current_fsgid();
+ } else {
+ args.uid = INVALID_UID; /* no change */
+ args.gid = INVALID_GID; /* no change */
+ }
+ CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,
+ current->tgid);
+ } else {
+ /*
+ * BB implement mode setting via Windows security
+ * descriptors e.g.
+ */
+ /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
+
+ /* Could set r/o dos attribute if mode & 0222 == 0 */
+ }
+
+cifs_create_get_file_info:
+ /* server might mask mode so we have to query for it */
+ if (tcon->unix_ext)
+ rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
+ xid);
+ else {
+#else
+ {
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ /* TODO: Add support for calling POSIX query info here, but passing in fid */
+ rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, xid, fid);
+ if (newinode) {
+ if (server->ops->set_lease_key)
+ server->ops->set_lease_key(newinode, fid);
+ if ((*oplock & CIFS_CREATE_ACTION) && S_ISREG(newinode->i_mode)) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
+ newinode->i_mode = mode;
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ newinode->i_uid = current_fsuid();
+ if (inode->i_mode & S_ISGID)
+ newinode->i_gid = inode->i_gid;
+ else
+ newinode->i_gid = current_fsgid();
+ }
+ }
+ }
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+cifs_create_set_dentry:
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ if (rc != 0) {
+ cifs_dbg(FYI, "Create worked, get_inode_info failed rc = %d\n",
+ rc);
+ goto out_err;
+ }
+
+ if (newinode)
+ if (S_ISDIR(newinode->i_mode)) {
+ rc = -EISDIR;
+ goto out_err;
+ }
+
+ d_drop(direntry);
+ d_add(direntry, newinode);
+
+out:
+ free_dentry_path(page);
+ return rc;
+
+out_err:
+ if (server->ops->close)
+ server->ops->close(xid, tcon, fid);
+ if (newinode)
+ iput(newinode);
+ goto out;
+}
+
+int
+cifs_atomic_open(struct inode *inode, struct dentry *direntry,
+ struct file *file, unsigned oflags, umode_t mode)
+{
+ int rc;
+ unsigned int xid;
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct cifs_fid fid = {};
+ struct cifs_pending_open open;
+ __u32 oplock;
+ struct cifsFileInfo *file_info;
+ struct cifs_open_info_data buf = {};
+
+ if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
+ return -EIO;
+
+ /*
+ * Posix open is only called (at lookup time) for file create now. For
+ * opens (rather than creates), because we do not know if it is a file
+ * or directory yet, and current Samba no longer allows us to do posix
+ * open on dirs, we could end up wasting an open call on what turns out
+ * to be a dir. For file opens, we wait to call posix open till
+ * cifs_open. It could be added to atomic_open in the future but the
+ * performance tradeoff of the extra network request when EISDIR or
+ * EACCES is returned would have to be weighed against the 50% reduction
+ * in network traffic in the other paths.
+ */
+ if (!(oflags & O_CREAT)) {
+ struct dentry *res;
+
+ /*
+ * Check for hashed negative dentry. We have already revalidated
+ * the dentry and it is fine. No need to perform another lookup.
+ */
+ if (!d_in_lookup(direntry))
+ return -ENOENT;
+
+ res = cifs_lookup(inode, direntry, 0);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
+
+ return finish_no_open(file, res);
+ }
+
+ xid = get_xid();
+
+ cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
+ inode, direntry, direntry);
+
+ tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
+ if (IS_ERR(tlink)) {
+ rc = PTR_ERR(tlink);
+ goto out_free_xid;
+ }
+
+ tcon = tlink_tcon(tlink);
+
+ rc = check_name(direntry, tcon);
+ if (rc)
+ goto out;
+
+ server = tcon->ses->server;
+
+ if (server->ops->new_lease_key)
+ server->ops->new_lease_key(&fid);
+
+ cifs_add_pending_open(&fid, tlink, &open);
+
+ rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
+ &oplock, &fid, &buf);
+ if (rc) {
+ cifs_del_pending_open(&open);
+ goto out;
+ }
+
+ if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ file->f_mode |= FMODE_CREATED;
+
+ rc = finish_open(file, direntry, generic_file_open);
+ if (rc) {
+ if (server->ops->close)
+ server->ops->close(xid, tcon, &fid);
+ cifs_del_pending_open(&open);
+ goto out;
+ }
+
+ if (file->f_flags & O_DIRECT &&
+ CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
+ if (CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+ file->f_op = &cifs_file_direct_nobrl_ops;
+ else
+ file->f_op = &cifs_file_direct_ops;
+ }
+
+ file_info = cifs_new_fileinfo(&fid, file, tlink, oplock, buf.symlink_target);
+ if (file_info == NULL) {
+ if (server->ops->close)
+ server->ops->close(xid, tcon, &fid);
+ cifs_del_pending_open(&open);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ fscache_use_cookie(cifs_inode_cookie(file_inode(file)),
+ file->f_mode & FMODE_WRITE);
+
+out:
+ cifs_put_tlink(tlink);
+out_free_xid:
+ free_xid(xid);
+ cifs_free_open_info(&buf);
+ return rc;
+}
+
+int cifs_create(struct user_namespace *mnt_userns, struct inode *inode,
+ struct dentry *direntry, umode_t mode, bool excl)
+{
+ int rc;
+ unsigned int xid = get_xid();
+ /*
+ * BB below access is probably too much for mknod to request
+ * but we have to do query and setpathinfo so requesting
+ * less could fail (unless we want to request getatr and setatr
+ * permissions (only). At least for POSIX we do not have to
+ * request so much.
+ */
+ unsigned oflags = O_EXCL | O_CREAT | O_RDWR;
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct cifs_fid fid;
+ __u32 oplock;
+ struct cifs_open_info_data buf = {};
+
+ cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
+ inode, direntry, direntry);
+
+ if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb)))) {
+ rc = -EIO;
+ goto out_free_xid;
+ }
+
+ tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
+ rc = PTR_ERR(tlink);
+ if (IS_ERR(tlink))
+ goto out_free_xid;
+
+ tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+
+ if (server->ops->new_lease_key)
+ server->ops->new_lease_key(&fid);
+
+ rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, &oplock, &fid, &buf);
+ if (!rc && server->ops->close)
+ server->ops->close(xid, tcon, &fid);
+
+ cifs_free_open_info(&buf);
+ cifs_put_tlink(tlink);
+out_free_xid:
+ free_xid(xid);
+ return rc;
+}
+
+int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode,
+ struct dentry *direntry, umode_t mode, dev_t device_number)
+{
+ int rc = -EPERM;
+ unsigned int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ const char *full_path;
+ void *page;
+
+ if (!old_valid_dev(device_number))
+ return -EINVAL;
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ if (unlikely(cifs_forced_shutdown(cifs_sb)))
+ return -EIO;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+
+ page = alloc_dentry_path();
+ tcon = tlink_tcon(tlink);
+ xid = get_xid();
+
+ full_path = build_path_from_dentry(direntry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto mknod_out;
+ }
+
+ rc = tcon->ses->server->ops->make_node(xid, inode, direntry, tcon,
+ full_path, mode,
+ device_number);
+
+mknod_out:
+ free_dentry_path(page);
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+struct dentry *
+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
+ unsigned int flags)
+{
+ unsigned int xid;
+ int rc = 0; /* to get around spurious gcc warning, set to zero here */
+ struct cifs_sb_info *cifs_sb;
+ struct tcon_link *tlink;
+ struct cifs_tcon *pTcon;
+ struct inode *newInode = NULL;
+ const char *full_path;
+ void *page;
+ int retry_count = 0;
+
+ xid = get_xid();
+
+ cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
+ parent_dir_inode, direntry, direntry);
+
+ /* check whether path exists */
+
+ cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink)) {
+ free_xid(xid);
+ return ERR_CAST(tlink);
+ }
+ pTcon = tlink_tcon(tlink);
+
+ rc = check_name(direntry, pTcon);
+ if (unlikely(rc)) {
+ cifs_put_tlink(tlink);
+ free_xid(xid);
+ return ERR_PTR(rc);
+ }
+
+ /* can not grab the rename sem here since it would
+ deadlock in the cases (beginning of sys_rename itself)
+ in which we already have the sb rename sem */
+ page = alloc_dentry_path();
+ full_path = build_path_from_dentry(direntry, page);
+ if (IS_ERR(full_path)) {
+ cifs_put_tlink(tlink);
+ free_xid(xid);
+ free_dentry_path(page);
+ return ERR_CAST(full_path);
+ }
+
+ if (d_really_is_positive(direntry)) {
+ cifs_dbg(FYI, "non-NULL inode in lookup\n");
+ } else {
+ cifs_dbg(FYI, "NULL inode in lookup\n");
+ }
+ cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
+ full_path, d_inode(direntry));
+
+again:
+ if (pTcon->posix_extensions)
+ rc = smb311_posix_get_inode_info(&newInode, full_path, parent_dir_inode->i_sb, xid);
+ else if (pTcon->unix_ext) {
+ rc = cifs_get_inode_info_unix(&newInode, full_path,
+ parent_dir_inode->i_sb, xid);
+ } else {
+ rc = cifs_get_inode_info(&newInode, full_path, NULL,
+ parent_dir_inode->i_sb, xid, NULL);
+ }
+
+ if (rc == 0) {
+ /* since paths are not looked up by component - the parent
+ directories are presumed to be good here */
+ renew_parental_timestamps(direntry);
+ } else if (rc == -EAGAIN && retry_count++ < 10) {
+ goto again;
+ } else if (rc == -ENOENT) {
+ cifs_set_time(direntry, jiffies);
+ newInode = NULL;
+ } else {
+ if (rc != -EACCES) {
+ cifs_dbg(FYI, "Unexpected lookup error %d\n", rc);
+ /* We special case check for Access Denied - since that
+ is a common return code */
+ }
+ newInode = ERR_PTR(rc);
+ }
+ free_dentry_path(page);
+ cifs_put_tlink(tlink);
+ free_xid(xid);
+ return d_splice_alias(newInode, direntry);
+}
+
+static int
+cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
+{
+ struct inode *inode;
+ int rc;
+
+ if (flags & LOOKUP_RCU)
+ return -ECHILD;
+
+ if (d_really_is_positive(direntry)) {
+ inode = d_inode(direntry);
+ if ((flags & LOOKUP_REVAL) && !CIFS_CACHE_READ(CIFS_I(inode)))
+ CIFS_I(inode)->time = 0; /* force reval */
+
+ rc = cifs_revalidate_dentry(direntry);
+ if (rc) {
+ cifs_dbg(FYI, "cifs_revalidate_dentry failed with rc=%d", rc);
+ switch (rc) {
+ case -ENOENT:
+ case -ESTALE:
+ /*
+ * Those errors mean the dentry is invalid
+ * (file was deleted or recreated)
+ */
+ return 0;
+ default:
+ /*
+ * Otherwise some unexpected error happened
+ * report it as-is to VFS layer
+ */
+ return rc;
+ }
+ }
+ else {
+ /*
+ * If the inode wasn't known to be a dfs entry when
+ * the dentry was instantiated, such as when created
+ * via ->readdir(), it needs to be set now since the
+ * attributes will have been updated by
+ * cifs_revalidate_dentry().
+ */
+ if (IS_AUTOMOUNT(inode) &&
+ !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) {
+ spin_lock(&direntry->d_lock);
+ direntry->d_flags |= DCACHE_NEED_AUTOMOUNT;
+ spin_unlock(&direntry->d_lock);
+ }
+
+ return 1;
+ }
+ }
+
+ /*
+ * This may be nfsd (or something), anyway, we can't see the
+ * intent of this. So, since this can be for creation, drop it.
+ */
+ if (!flags)
+ return 0;
+
+ /*
+ * Drop the negative dentry, in order to make sure to use the
+ * case sensitive name which is specified by user if this is
+ * for creation.
+ */
+ if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+ return 0;
+
+ if (time_after(jiffies, cifs_get_time(direntry) + HZ) || !lookupCacheEnabled)
+ return 0;
+
+ return 1;
+}
+
+/* static int cifs_d_delete(struct dentry *direntry)
+{
+ int rc = 0;
+
+ cifs_dbg(FYI, "In cifs d_delete, name = %pd\n", direntry);
+
+ return rc;
+} */
+
+const struct dentry_operations cifs_dentry_ops = {
+ .d_revalidate = cifs_d_revalidate,
+ .d_automount = cifs_dfs_d_automount,
+/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
+};
+
+static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q)
+{
+ struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
+ unsigned long hash;
+ wchar_t c;
+ int i, charlen;
+
+ hash = init_name_hash(dentry);
+ for (i = 0; i < q->len; i += charlen) {
+ charlen = codepage->char2uni(&q->name[i], q->len - i, &c);
+ /* error out if we can't convert the character */
+ if (unlikely(charlen < 0))
+ return charlen;
+ hash = partial_name_hash(cifs_toupper(c), hash);
+ }
+ q->hash = end_name_hash(hash);
+
+ return 0;
+}
+
+static int cifs_ci_compare(const struct dentry *dentry,
+ unsigned int len, const char *str, const struct qstr *name)
+{
+ struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
+ wchar_t c1, c2;
+ int i, l1, l2;
+
+ /*
+ * We make the assumption here that uppercase characters in the local
+ * codepage are always the same length as their lowercase counterparts.
+ *
+ * If that's ever not the case, then this will fail to match it.
+ */
+ if (name->len != len)
+ return 1;
+
+ for (i = 0; i < len; i += l1) {
+ /* Convert characters in both strings to UTF-16. */
+ l1 = codepage->char2uni(&str[i], len - i, &c1);
+ l2 = codepage->char2uni(&name->name[i], name->len - i, &c2);
+
+ /*
+ * If we can't convert either character, just declare it to
+ * be 1 byte long and compare the original byte.
+ */
+ if (unlikely(l1 < 0 && l2 < 0)) {
+ if (str[i] != name->name[i])
+ return 1;
+ l1 = 1;
+ continue;
+ }
+
+ /*
+ * Here, we again ass|u|me that upper/lowercase versions of
+ * a character are the same length in the local NLS.
+ */
+ if (l1 != l2)
+ return 1;
+
+ /* Now compare uppercase versions of these characters */
+ if (cifs_toupper(c1) != cifs_toupper(c2))
+ return 1;
+ }
+
+ return 0;
+}
+
+const struct dentry_operations cifs_ci_dentry_ops = {
+ .d_revalidate = cifs_d_revalidate,
+ .d_hash = cifs_ci_hash,
+ .d_compare = cifs_ci_compare,
+ .d_automount = cifs_dfs_d_automount,
+};
diff --git a/fs/smb/client/dns_resolve.c b/fs/smb/client/dns_resolve.c
new file mode 100644
index 000000000000..0458d28d71aa
--- /dev/null
+++ b/fs/smb/client/dns_resolve.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (c) 2007 Igor Mammedov
+ * Author(s): Igor Mammedov (niallain@gmail.com)
+ * Steve French (sfrench@us.ibm.com)
+ * Wang Lei (wang840925@gmail.com)
+ * David Howells (dhowells@redhat.com)
+ *
+ * Contains the CIFS DFS upcall routines used for hostname to
+ * IP address translation.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/dns_resolver.h>
+#include "dns_resolve.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+
+/**
+ * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address.
+ * @unc: UNC path specifying the server (with '/' as delimiter)
+ * @ip_addr: Where to return the IP address.
+ * @expiry: Where to return the expiry time for the dns record.
+ *
+ * The IP address will be returned in string form, and the caller is
+ * responsible for freeing it.
+ *
+ * Returns length of result on success, -ve on error.
+ */
+int
+dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry)
+{
+ struct sockaddr_storage ss;
+ const char *hostname, *sep;
+ char *name;
+ int len, rc;
+
+ if (!ip_addr || !unc)
+ return -EINVAL;
+
+ len = strlen(unc);
+ if (len < 3) {
+ cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc);
+ return -EINVAL;
+ }
+
+ /* Discount leading slashes for cifs */
+ len -= 2;
+ hostname = unc + 2;
+
+ /* Search for server name delimiter */
+ sep = memchr(hostname, '/', len);
+ if (sep)
+ len = sep - hostname;
+ else
+ cifs_dbg(FYI, "%s: probably server name is whole unc: %s\n",
+ __func__, unc);
+
+ /* Try to interpret hostname as an IPv4 or IPv6 address */
+ rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len);
+ if (rc > 0)
+ goto name_is_IP_address;
+
+ /* Perform the upcall */
+ rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len,
+ NULL, ip_addr, expiry, false);
+ if (rc < 0)
+ cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n",
+ __func__, len, len, hostname);
+ else
+ cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n",
+ __func__, len, len, hostname, *ip_addr,
+ expiry ? (*expiry) : 0);
+ return rc;
+
+name_is_IP_address:
+ name = kmalloc(len + 1, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+ memcpy(name, hostname, len);
+ name[len] = 0;
+ cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %s\n",
+ __func__, name);
+ *ip_addr = name;
+ return 0;
+}
diff --git a/fs/smb/client/dns_resolve.h b/fs/smb/client/dns_resolve.h
new file mode 100644
index 000000000000..afc0df381246
--- /dev/null
+++ b/fs/smb/client/dns_resolve.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ * DNS Resolver upcall management for CIFS DFS
+ * Handles host name to IP address resolution
+ *
+ * Copyright (c) International Business Machines Corp., 2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#ifndef _DNS_RESOLVE_H
+#define _DNS_RESOLVE_H
+
+#ifdef __KERNEL__
+extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry);
+#endif /* KERNEL */
+
+#endif /* _DNS_RESOLVE_H */
diff --git a/fs/smb/client/export.c b/fs/smb/client/export.c
new file mode 100644
index 000000000000..37c28415df1e
--- /dev/null
+++ b/fs/smb/client/export.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2007
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Common Internet FileSystem (CIFS) client
+ *
+ * Operations related to support for exporting files via NFSD
+ *
+ */
+
+ /*
+ * See Documentation/filesystems/nfs/exporting.rst
+ * and examples in fs/exportfs
+ *
+ * Since cifs is a network file system, an "fsid" must be included for
+ * any nfs exports file entries which refer to cifs paths. In addition
+ * the cifs mount must be mounted with the "serverino" option (ie use stable
+ * server inode numbers instead of locally generated temporary ones).
+ * Although cifs inodes do not use generation numbers (have generation number
+ * of zero) - the inode number alone should be good enough for simple cases
+ * in which users want to export cifs shares with NFS. The decode and encode
+ * could be improved by using a new routine which expects 64 bit inode numbers
+ * instead of the default 32 bit routines in fs/exportfs
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/exportfs.h>
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "cifsfs.h"
+
+#ifdef CONFIG_CIFS_NFSD_EXPORT
+static struct dentry *cifs_get_parent(struct dentry *dentry)
+{
+ /* BB need to add code here eventually to enable export via NFSD */
+ cifs_dbg(FYI, "get parent for %p\n", dentry);
+ return ERR_PTR(-EACCES);
+}
+
+const struct export_operations cifs_export_ops = {
+ .get_parent = cifs_get_parent,
+/* Following five export operations are unneeded so far and can default:
+ .get_dentry =
+ .get_name =
+ .find_exported_dentry =
+ .decode_fh =
+ .encode_fs = */
+};
+
+#endif /* CONFIG_CIFS_NFSD_EXPORT */
+
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
new file mode 100644
index 000000000000..87dcffece762
--- /dev/null
+++ b/fs/smb/client/file.c
@@ -0,0 +1,5290 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * vfs operations that deal with files
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2010
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Jeremy Allison (jra@samba.org)
+ *
+ */
+#include <linux/fs.h>
+#include <linux/backing-dev.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/pagemap.h>
+#include <linux/pagevec.h>
+#include <linux/writeback.h>
+#include <linux/task_io_accounting_ops.h>
+#include <linux/delay.h>
+#include <linux/mount.h>
+#include <linux/slab.h>
+#include <linux/swap.h>
+#include <linux/mm.h>
+#include <asm/div64.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "fscache.h"
+#include "smbdirect.h"
+#include "fs_context.h"
+#include "cifs_ioctl.h"
+#include "cached_dir.h"
+
+/*
+ * Mark as invalid, all open files on tree connections since they
+ * were closed when session to server was lost.
+ */
+void
+cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
+{
+ struct cifsFileInfo *open_file = NULL;
+ struct list_head *tmp;
+ struct list_head *tmp1;
+
+ /* only send once per connect */
+ spin_lock(&tcon->ses->ses_lock);
+ if ((tcon->ses->ses_status != SES_GOOD) || (tcon->status != TID_NEED_RECON)) {
+ spin_unlock(&tcon->ses->ses_lock);
+ return;
+ }
+ tcon->status = TID_IN_FILES_INVALIDATE;
+ spin_unlock(&tcon->ses->ses_lock);
+
+ /* list all files open on tree connection and mark them invalid */
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
+ open_file = list_entry(tmp, struct cifsFileInfo, tlist);
+ open_file->invalidHandle = true;
+ open_file->oplock_break_cancelled = true;
+ }
+ spin_unlock(&tcon->open_file_lock);
+
+ invalidate_all_cached_dirs(tcon);
+ spin_lock(&tcon->tc_lock);
+ if (tcon->status == TID_IN_FILES_INVALIDATE)
+ tcon->status = TID_NEED_TCON;
+ spin_unlock(&tcon->tc_lock);
+
+ /*
+ * BB Add call to invalidate_inodes(sb) for all superblocks mounted
+ * to this tcon.
+ */
+}
+
+static inline int cifs_convert_flags(unsigned int flags)
+{
+ if ((flags & O_ACCMODE) == O_RDONLY)
+ return GENERIC_READ;
+ else if ((flags & O_ACCMODE) == O_WRONLY)
+ return GENERIC_WRITE;
+ else if ((flags & O_ACCMODE) == O_RDWR) {
+ /* GENERIC_ALL is too much permission to request
+ can cause unnecessary access denied on create */
+ /* return GENERIC_ALL; */
+ return (GENERIC_READ | GENERIC_WRITE);
+ }
+
+ return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
+ FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
+ FILE_READ_DATA);
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+static u32 cifs_posix_convert_flags(unsigned int flags)
+{
+ u32 posix_flags = 0;
+
+ if ((flags & O_ACCMODE) == O_RDONLY)
+ posix_flags = SMB_O_RDONLY;
+ else if ((flags & O_ACCMODE) == O_WRONLY)
+ posix_flags = SMB_O_WRONLY;
+ else if ((flags & O_ACCMODE) == O_RDWR)
+ posix_flags = SMB_O_RDWR;
+
+ if (flags & O_CREAT) {
+ posix_flags |= SMB_O_CREAT;
+ if (flags & O_EXCL)
+ posix_flags |= SMB_O_EXCL;
+ } else if (flags & O_EXCL)
+ cifs_dbg(FYI, "Application %s pid %d has incorrectly set O_EXCL flag but not O_CREAT on file open. Ignoring O_EXCL\n",
+ current->comm, current->tgid);
+
+ if (flags & O_TRUNC)
+ posix_flags |= SMB_O_TRUNC;
+ /* be safe and imply O_SYNC for O_DSYNC */
+ if (flags & O_DSYNC)
+ posix_flags |= SMB_O_SYNC;
+ if (flags & O_DIRECTORY)
+ posix_flags |= SMB_O_DIRECTORY;
+ if (flags & O_NOFOLLOW)
+ posix_flags |= SMB_O_NOFOLLOW;
+ if (flags & O_DIRECT)
+ posix_flags |= SMB_O_DIRECT;
+
+ return posix_flags;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+static inline int cifs_get_disposition(unsigned int flags)
+{
+ if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ return FILE_CREATE;
+ else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+ return FILE_OVERWRITE_IF;
+ else if ((flags & O_CREAT) == O_CREAT)
+ return FILE_OPEN_IF;
+ else if ((flags & O_TRUNC) == O_TRUNC)
+ return FILE_OVERWRITE;
+ else
+ return FILE_OPEN;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+int cifs_posix_open(const char *full_path, struct inode **pinode,
+ struct super_block *sb, int mode, unsigned int f_flags,
+ __u32 *poplock, __u16 *pnetfid, unsigned int xid)
+{
+ int rc;
+ FILE_UNIX_BASIC_INFO *presp_data;
+ __u32 posix_flags = 0;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_fattr fattr;
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+
+ cifs_dbg(FYI, "posix open %s\n", full_path);
+
+ presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+ if (presp_data == NULL)
+ return -ENOMEM;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink)) {
+ rc = PTR_ERR(tlink);
+ goto posix_open_ret;
+ }
+
+ tcon = tlink_tcon(tlink);
+ mode &= ~current_umask();
+
+ posix_flags = cifs_posix_convert_flags(f_flags);
+ rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
+ poplock, full_path, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ cifs_put_tlink(tlink);
+
+ if (rc)
+ goto posix_open_ret;
+
+ if (presp_data->Type == cpu_to_le32(-1))
+ goto posix_open_ret; /* open ok, caller does qpathinfo */
+
+ if (!pinode)
+ goto posix_open_ret; /* caller does not need info */
+
+ cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
+
+ /* get new inode and set it up */
+ if (*pinode == NULL) {
+ cifs_fill_uniqueid(sb, &fattr);
+ *pinode = cifs_iget(sb, &fattr);
+ if (!*pinode) {
+ rc = -ENOMEM;
+ goto posix_open_ret;
+ }
+ } else {
+ cifs_revalidate_mapping(*pinode);
+ rc = cifs_fattr_to_inode(*pinode, &fattr);
+ }
+
+posix_open_ret:
+ kfree(presp_data);
+ return rc;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
+ struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock,
+ struct cifs_fid *fid, unsigned int xid, struct cifs_open_info_data *buf)
+{
+ int rc;
+ int desired_access;
+ int disposition;
+ int create_options = CREATE_NOT_DIR;
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifs_open_parms oparms;
+
+ if (!server->ops->open)
+ return -ENOSYS;
+
+ desired_access = cifs_convert_flags(f_flags);
+
+/*********************************************************************
+ * open flag mapping table:
+ *
+ * POSIX Flag CIFS Disposition
+ * ---------- ----------------
+ * O_CREAT FILE_OPEN_IF
+ * O_CREAT | O_EXCL FILE_CREATE
+ * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
+ * O_TRUNC FILE_OVERWRITE
+ * none of the above FILE_OPEN
+ *
+ * Note that there is not a direct match between disposition
+ * FILE_SUPERSEDE (ie create whether or not file exists although
+ * O_CREAT | O_TRUNC is similar but truncates the existing
+ * file rather than creating a new file as FILE_SUPERSEDE does
+ * (which uses the attributes / metadata passed in on open call)
+ *?
+ *? O_SYNC is a reasonable match to CIFS writethrough flag
+ *? and the read write flags match reasonably. O_LARGEFILE
+ *? is irrelevant because largefile support is always used
+ *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
+ * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
+ *********************************************************************/
+
+ disposition = cifs_get_disposition(f_flags);
+
+ /* BB pass O_SYNC flag through on file attributes .. BB */
+
+ /* O_SYNC also has bit for O_DSYNC so following check picks up either */
+ if (f_flags & O_SYNC)
+ create_options |= CREATE_WRITE_THROUGH;
+
+ if (f_flags & O_DIRECT)
+ create_options |= CREATE_NO_BUFFER;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = desired_access,
+ .create_options = cifs_create_options(cifs_sb, create_options),
+ .disposition = disposition,
+ .path = full_path,
+ .fid = fid,
+ };
+
+ rc = server->ops->open(xid, &oparms, oplock, buf);
+ if (rc)
+ return rc;
+
+ /* TODO: Add support for calling posix query info but with passing in fid */
+ if (tcon->unix_ext)
+ rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
+ xid);
+ else
+ rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
+ xid, fid);
+
+ if (rc) {
+ server->ops->close(xid, tcon, fid);
+ if (rc == -ESTALE)
+ rc = -EOPENSTALE;
+ }
+
+ return rc;
+}
+
+static bool
+cifs_has_mand_locks(struct cifsInodeInfo *cinode)
+{
+ struct cifs_fid_locks *cur;
+ bool has_locks = false;
+
+ down_read(&cinode->lock_sem);
+ list_for_each_entry(cur, &cinode->llist, llist) {
+ if (!list_empty(&cur->locks)) {
+ has_locks = true;
+ break;
+ }
+ }
+ up_read(&cinode->lock_sem);
+ return has_locks;
+}
+
+void
+cifs_down_write(struct rw_semaphore *sem)
+{
+ while (!down_write_trylock(sem))
+ msleep(10);
+}
+
+static void cifsFileInfo_put_work(struct work_struct *work);
+
+struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
+ struct tcon_link *tlink, __u32 oplock,
+ const char *symlink_target)
+{
+ struct dentry *dentry = file_dentry(file);
+ struct inode *inode = d_inode(dentry);
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct cifsFileInfo *cfile;
+ struct cifs_fid_locks *fdlocks;
+ struct cifs_tcon *tcon = tlink_tcon(tlink);
+ struct TCP_Server_Info *server = tcon->ses->server;
+
+ cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+ if (cfile == NULL)
+ return cfile;
+
+ fdlocks = kzalloc(sizeof(struct cifs_fid_locks), GFP_KERNEL);
+ if (!fdlocks) {
+ kfree(cfile);
+ return NULL;
+ }
+
+ if (symlink_target) {
+ cfile->symlink_target = kstrdup(symlink_target, GFP_KERNEL);
+ if (!cfile->symlink_target) {
+ kfree(fdlocks);
+ kfree(cfile);
+ return NULL;
+ }
+ }
+
+ INIT_LIST_HEAD(&fdlocks->locks);
+ fdlocks->cfile = cfile;
+ cfile->llist = fdlocks;
+
+ cfile->count = 1;
+ cfile->pid = current->tgid;
+ cfile->uid = current_fsuid();
+ cfile->dentry = dget(dentry);
+ cfile->f_flags = file->f_flags;
+ cfile->invalidHandle = false;
+ cfile->deferred_close_scheduled = false;
+ cfile->tlink = cifs_get_tlink(tlink);
+ INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
+ INIT_WORK(&cfile->put, cifsFileInfo_put_work);
+ INIT_DELAYED_WORK(&cfile->deferred, smb2_deferred_work_close);
+ mutex_init(&cfile->fh_mutex);
+ spin_lock_init(&cfile->file_info_lock);
+
+ cifs_sb_active(inode->i_sb);
+
+ /*
+ * If the server returned a read oplock and we have mandatory brlocks,
+ * set oplock level to None.
+ */
+ if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) {
+ cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n");
+ oplock = 0;
+ }
+
+ cifs_down_write(&cinode->lock_sem);
+ list_add(&fdlocks->llist, &cinode->llist);
+ up_write(&cinode->lock_sem);
+
+ spin_lock(&tcon->open_file_lock);
+ if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock)
+ oplock = fid->pending_open->oplock;
+ list_del(&fid->pending_open->olist);
+
+ fid->purge_cache = false;
+ server->ops->set_fid(cfile, fid, oplock);
+
+ list_add(&cfile->tlist, &tcon->openFileList);
+ atomic_inc(&tcon->num_local_opens);
+
+ /* if readable file instance put first in list*/
+ spin_lock(&cinode->open_file_lock);
+ if (file->f_mode & FMODE_READ)
+ list_add(&cfile->flist, &cinode->openFileList);
+ else
+ list_add_tail(&cfile->flist, &cinode->openFileList);
+ spin_unlock(&cinode->open_file_lock);
+ spin_unlock(&tcon->open_file_lock);
+
+ if (fid->purge_cache)
+ cifs_zap_mapping(inode);
+
+ file->private_data = cfile;
+ return cfile;
+}
+
+struct cifsFileInfo *
+cifsFileInfo_get(struct cifsFileInfo *cifs_file)
+{
+ spin_lock(&cifs_file->file_info_lock);
+ cifsFileInfo_get_locked(cifs_file);
+ spin_unlock(&cifs_file->file_info_lock);
+ return cifs_file;
+}
+
+static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
+{
+ struct inode *inode = d_inode(cifs_file->dentry);
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct cifsLockInfo *li, *tmp;
+ struct super_block *sb = inode->i_sb;
+
+ /*
+ * Delete any outstanding lock records. We'll lose them when the file
+ * is closed anyway.
+ */
+ cifs_down_write(&cifsi->lock_sem);
+ list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) {
+ list_del(&li->llist);
+ cifs_del_lock_waiters(li);
+ kfree(li);
+ }
+ list_del(&cifs_file->llist->llist);
+ kfree(cifs_file->llist);
+ up_write(&cifsi->lock_sem);
+
+ cifs_put_tlink(cifs_file->tlink);
+ dput(cifs_file->dentry);
+ cifs_sb_deactive(sb);
+ kfree(cifs_file->symlink_target);
+ kfree(cifs_file);
+}
+
+static void cifsFileInfo_put_work(struct work_struct *work)
+{
+ struct cifsFileInfo *cifs_file = container_of(work,
+ struct cifsFileInfo, put);
+
+ cifsFileInfo_put_final(cifs_file);
+}
+
+/**
+ * cifsFileInfo_put - release a reference of file priv data
+ *
+ * Always potentially wait for oplock handler. See _cifsFileInfo_put().
+ *
+ * @cifs_file: cifs/smb3 specific info (eg refcounts) for an open file
+ */
+void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
+{
+ _cifsFileInfo_put(cifs_file, true, true);
+}
+
+/**
+ * _cifsFileInfo_put - release a reference of file priv data
+ *
+ * This may involve closing the filehandle @cifs_file out on the
+ * server. Must be called without holding tcon->open_file_lock,
+ * cinode->open_file_lock and cifs_file->file_info_lock.
+ *
+ * If @wait_for_oplock_handler is true and we are releasing the last
+ * reference, wait for any running oplock break handler of the file
+ * and cancel any pending one.
+ *
+ * @cifs_file: cifs/smb3 specific info (eg refcounts) for an open file
+ * @wait_oplock_handler: must be false if called from oplock_break_handler
+ * @offload: not offloaded on close and oplock breaks
+ *
+ */
+void _cifsFileInfo_put(struct cifsFileInfo *cifs_file,
+ bool wait_oplock_handler, bool offload)
+{
+ struct inode *inode = d_inode(cifs_file->dentry);
+ struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct super_block *sb = inode->i_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_fid fid = {};
+ struct cifs_pending_open open;
+ bool oplock_break_cancelled;
+
+ spin_lock(&tcon->open_file_lock);
+ spin_lock(&cifsi->open_file_lock);
+ spin_lock(&cifs_file->file_info_lock);
+ if (--cifs_file->count > 0) {
+ spin_unlock(&cifs_file->file_info_lock);
+ spin_unlock(&cifsi->open_file_lock);
+ spin_unlock(&tcon->open_file_lock);
+ return;
+ }
+ spin_unlock(&cifs_file->file_info_lock);
+
+ if (server->ops->get_lease_key)
+ server->ops->get_lease_key(inode, &fid);
+
+ /* store open in pending opens to make sure we don't miss lease break */
+ cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open);
+
+ /* remove it from the lists */
+ list_del(&cifs_file->flist);
+ list_del(&cifs_file->tlist);
+ atomic_dec(&tcon->num_local_opens);
+
+ if (list_empty(&cifsi->openFileList)) {
+ cifs_dbg(FYI, "closing last open instance for inode %p\n",
+ d_inode(cifs_file->dentry));
+ /*
+ * In strict cache mode we need invalidate mapping on the last
+ * close because it may cause a error when we open this file
+ * again and get at least level II oplock.
+ */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
+ set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags);
+ cifs_set_oplock_level(cifsi, 0);
+ }
+
+ spin_unlock(&cifsi->open_file_lock);
+ spin_unlock(&tcon->open_file_lock);
+
+ oplock_break_cancelled = wait_oplock_handler ?
+ cancel_work_sync(&cifs_file->oplock_break) : false;
+
+ if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
+ struct TCP_Server_Info *server = tcon->ses->server;
+ unsigned int xid;
+
+ xid = get_xid();
+ if (server->ops->close_getattr)
+ server->ops->close_getattr(xid, tcon, cifs_file);
+ else if (server->ops->close)
+ server->ops->close(xid, tcon, &cifs_file->fid);
+ _free_xid(xid);
+ }
+
+ if (oplock_break_cancelled)
+ cifs_done_oplock_break(cifsi);
+
+ cifs_del_pending_open(&open);
+
+ if (offload)
+ queue_work(fileinfo_put_wq, &cifs_file->put);
+ else
+ cifsFileInfo_put_final(cifs_file);
+}
+
+int cifs_open(struct inode *inode, struct file *file)
+
+{
+ int rc = -EACCES;
+ unsigned int xid;
+ __u32 oplock;
+ struct cifs_sb_info *cifs_sb;
+ struct TCP_Server_Info *server;
+ struct cifs_tcon *tcon;
+ struct tcon_link *tlink;
+ struct cifsFileInfo *cfile = NULL;
+ void *page;
+ const char *full_path;
+ bool posix_open_ok = false;
+ struct cifs_fid fid = {};
+ struct cifs_pending_open open;
+ struct cifs_open_info_data data = {};
+
+ xid = get_xid();
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ if (unlikely(cifs_forced_shutdown(cifs_sb))) {
+ free_xid(xid);
+ return -EIO;
+ }
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink)) {
+ free_xid(xid);
+ return PTR_ERR(tlink);
+ }
+ tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+
+ page = alloc_dentry_path();
+ full_path = build_path_from_dentry(file_dentry(file), page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto out;
+ }
+
+ cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
+ inode, file->f_flags, full_path);
+
+ if (file->f_flags & O_DIRECT &&
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+ file->f_op = &cifs_file_direct_nobrl_ops;
+ else
+ file->f_op = &cifs_file_direct_ops;
+ }
+
+ /* Get the cached handle as SMB2 close is deferred */
+ rc = cifs_get_readable_path(tcon, full_path, &cfile);
+ if (rc == 0) {
+ if (file->f_flags == cfile->f_flags) {
+ file->private_data = cfile;
+ spin_lock(&CIFS_I(inode)->deferred_lock);
+ cifs_del_deferred_close(cfile);
+ spin_unlock(&CIFS_I(inode)->deferred_lock);
+ goto use_cache;
+ } else {
+ _cifsFileInfo_put(cfile, true, false);
+ }
+ }
+
+ if (server->oplocks)
+ oplock = REQ_OPLOCK;
+ else
+ oplock = 0;
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (!tcon->broken_posix_open && tcon->unix_ext &&
+ cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+ /* can not refresh inode info since size could be stale */
+ rc = cifs_posix_open(full_path, &inode, inode->i_sb,
+ cifs_sb->ctx->file_mode /* ignored */,
+ file->f_flags, &oplock, &fid.netfid, xid);
+ if (rc == 0) {
+ cifs_dbg(FYI, "posix open succeeded\n");
+ posix_open_ok = true;
+ } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
+ if (tcon->ses->serverNOS)
+ cifs_dbg(VFS, "server %s of type %s returned unexpected error on SMB posix open, disabling posix open support. Check if server update available.\n",
+ tcon->ses->ip_addr,
+ tcon->ses->serverNOS);
+ tcon->broken_posix_open = true;
+ } else if ((rc != -EIO) && (rc != -EREMOTE) &&
+ (rc != -EOPNOTSUPP)) /* path not found or net err */
+ goto out;
+ /*
+ * Else fallthrough to retry open the old way on network i/o
+ * or DFS errors.
+ */
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ if (server->ops->get_lease_key)
+ server->ops->get_lease_key(inode, &fid);
+
+ cifs_add_pending_open(&fid, tlink, &open);
+
+ if (!posix_open_ok) {
+ if (server->ops->get_lease_key)
+ server->ops->get_lease_key(inode, &fid);
+
+ rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, file->f_flags, &oplock, &fid,
+ xid, &data);
+ if (rc) {
+ cifs_del_pending_open(&open);
+ goto out;
+ }
+ }
+
+ cfile = cifs_new_fileinfo(&fid, file, tlink, oplock, data.symlink_target);
+ if (cfile == NULL) {
+ if (server->ops->close)
+ server->ops->close(xid, tcon, &fid);
+ cifs_del_pending_open(&open);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
+ /*
+ * Time to set mode which we can not set earlier due to
+ * problems creating new read-only files.
+ */
+ struct cifs_unix_set_info_args args = {
+ .mode = inode->i_mode,
+ .uid = INVALID_UID, /* no change */
+ .gid = INVALID_GID, /* no change */
+ .ctime = NO_CHANGE_64,
+ .atime = NO_CHANGE_64,
+ .mtime = NO_CHANGE_64,
+ .device = 0,
+ };
+ CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid,
+ cfile->pid);
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+use_cache:
+ fscache_use_cookie(cifs_inode_cookie(file_inode(file)),
+ file->f_mode & FMODE_WRITE);
+ if (file->f_flags & O_DIRECT &&
+ (!((file->f_flags & O_ACCMODE) != O_RDONLY) ||
+ file->f_flags & O_APPEND))
+ cifs_invalidate_cache(file_inode(file),
+ FSCACHE_INVAL_DIO_WRITE);
+
+out:
+ free_dentry_path(page);
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ cifs_free_open_info(&data);
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+static int cifs_push_posix_locks(struct cifsFileInfo *cfile);
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+/*
+ * Try to reacquire byte range locks that were released when session
+ * to server was lost.
+ */
+static int
+cifs_relock_file(struct cifsFileInfo *cfile)
+{
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ int rc = 0;
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ down_read_nested(&cinode->lock_sem, SINGLE_DEPTH_NESTING);
+ if (cinode->can_cache_brlcks) {
+ /* can cache locks - no need to relock */
+ up_read(&cinode->lock_sem);
+ return rc;
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (cap_unix(tcon->ses) &&
+ (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
+ ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
+ rc = cifs_push_posix_locks(cfile);
+ else
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ rc = tcon->ses->server->ops->push_mand_locks(cfile);
+
+ up_read(&cinode->lock_sem);
+ return rc;
+}
+
+static int
+cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
+{
+ int rc = -EACCES;
+ unsigned int xid;
+ __u32 oplock;
+ struct cifs_sb_info *cifs_sb;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct cifsInodeInfo *cinode;
+ struct inode *inode;
+ void *page;
+ const char *full_path;
+ int desired_access;
+ int disposition = FILE_OPEN;
+ int create_options = CREATE_NOT_DIR;
+ struct cifs_open_parms oparms;
+
+ xid = get_xid();
+ mutex_lock(&cfile->fh_mutex);
+ if (!cfile->invalidHandle) {
+ mutex_unlock(&cfile->fh_mutex);
+ free_xid(xid);
+ return 0;
+ }
+
+ inode = d_inode(cfile->dentry);
+ cifs_sb = CIFS_SB(inode->i_sb);
+ tcon = tlink_tcon(cfile->tlink);
+ server = tcon->ses->server;
+
+ /*
+ * Can not grab rename sem here because various ops, including those
+ * that already have the rename sem can end up causing writepage to get
+ * called and if the server was down that means we end up here, and we
+ * can never tell if the caller already has the rename_sem.
+ */
+ page = alloc_dentry_path();
+ full_path = build_path_from_dentry(cfile->dentry, page);
+ if (IS_ERR(full_path)) {
+ mutex_unlock(&cfile->fh_mutex);
+ free_dentry_path(page);
+ free_xid(xid);
+ return PTR_ERR(full_path);
+ }
+
+ cifs_dbg(FYI, "inode = 0x%p file flags 0x%x for %s\n",
+ inode, cfile->f_flags, full_path);
+
+ if (tcon->ses->server->oplocks)
+ oplock = REQ_OPLOCK;
+ else
+ oplock = 0;
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (tcon->unix_ext && cap_unix(tcon->ses) &&
+ (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+ /*
+ * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
+ * original open. Must mask them off for a reopen.
+ */
+ unsigned int oflags = cfile->f_flags &
+ ~(O_CREAT | O_EXCL | O_TRUNC);
+
+ rc = cifs_posix_open(full_path, NULL, inode->i_sb,
+ cifs_sb->ctx->file_mode /* ignored */,
+ oflags, &oplock, &cfile->fid.netfid, xid);
+ if (rc == 0) {
+ cifs_dbg(FYI, "posix reopen succeeded\n");
+ oparms.reconnect = true;
+ goto reopen_success;
+ }
+ /*
+ * fallthrough to retry open the old way on errors, especially
+ * in the reconnect path it is important to retry hard
+ */
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ desired_access = cifs_convert_flags(cfile->f_flags);
+
+ /* O_SYNC also has bit for O_DSYNC so following check picks up either */
+ if (cfile->f_flags & O_SYNC)
+ create_options |= CREATE_WRITE_THROUGH;
+
+ if (cfile->f_flags & O_DIRECT)
+ create_options |= CREATE_NO_BUFFER;
+
+ if (server->ops->get_lease_key)
+ server->ops->get_lease_key(inode, &cfile->fid);
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = desired_access,
+ .create_options = cifs_create_options(cifs_sb, create_options),
+ .disposition = disposition,
+ .path = full_path,
+ .fid = &cfile->fid,
+ .reconnect = true,
+ };
+
+ /*
+ * Can not refresh inode by passing in file_info buf to be returned by
+ * ops->open and then calling get_inode_info with returned buf since
+ * file might have write behind data that needs to be flushed and server
+ * version of file size can be stale. If we knew for sure that inode was
+ * not dirty locally we could do this.
+ */
+ rc = server->ops->open(xid, &oparms, &oplock, NULL);
+ if (rc == -ENOENT && oparms.reconnect == false) {
+ /* durable handle timeout is expired - open the file again */
+ rc = server->ops->open(xid, &oparms, &oplock, NULL);
+ /* indicate that we need to relock the file */
+ oparms.reconnect = true;
+ }
+
+ if (rc) {
+ mutex_unlock(&cfile->fh_mutex);
+ cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc);
+ cifs_dbg(FYI, "oplock: %d\n", oplock);
+ goto reopen_error_exit;
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+reopen_success:
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ cfile->invalidHandle = false;
+ mutex_unlock(&cfile->fh_mutex);
+ cinode = CIFS_I(inode);
+
+ if (can_flush) {
+ rc = filemap_write_and_wait(inode->i_mapping);
+ if (!is_interrupt_error(rc))
+ mapping_set_error(inode->i_mapping, rc);
+
+ if (tcon->posix_extensions)
+ rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid);
+ else if (tcon->unix_ext)
+ rc = cifs_get_inode_info_unix(&inode, full_path,
+ inode->i_sb, xid);
+ else
+ rc = cifs_get_inode_info(&inode, full_path, NULL,
+ inode->i_sb, xid, NULL);
+ }
+ /*
+ * Else we are writing out data to server already and could deadlock if
+ * we tried to flush data, and since we do not know if we have data that
+ * would invalidate the current end of file on the server we can not go
+ * to the server to get the new inode info.
+ */
+
+ /*
+ * If the server returned a read oplock and we have mandatory brlocks,
+ * set oplock level to None.
+ */
+ if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) {
+ cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n");
+ oplock = 0;
+ }
+
+ server->ops->set_fid(cfile, &cfile->fid, oplock);
+ if (oparms.reconnect)
+ cifs_relock_file(cfile);
+
+reopen_error_exit:
+ free_dentry_path(page);
+ free_xid(xid);
+ return rc;
+}
+
+void smb2_deferred_work_close(struct work_struct *work)
+{
+ struct cifsFileInfo *cfile = container_of(work,
+ struct cifsFileInfo, deferred.work);
+
+ spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+ cifs_del_deferred_close(cfile);
+ cfile->deferred_close_scheduled = false;
+ spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+ _cifsFileInfo_put(cfile, true, false);
+}
+
+int cifs_close(struct inode *inode, struct file *file)
+{
+ struct cifsFileInfo *cfile;
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifs_deferred_close *dclose;
+
+ cifs_fscache_unuse_inode_cookie(inode, file->f_mode & FMODE_WRITE);
+
+ if (file->private_data != NULL) {
+ cfile = file->private_data;
+ file->private_data = NULL;
+ dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
+ if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
+ cinode->lease_granted &&
+ !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) &&
+ dclose) {
+ if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
+ inode->i_ctime = inode->i_mtime = current_time(inode);
+ }
+ spin_lock(&cinode->deferred_lock);
+ cifs_add_deferred_close(cfile, dclose);
+ if (cfile->deferred_close_scheduled &&
+ delayed_work_pending(&cfile->deferred)) {
+ /*
+ * If there is no pending work, mod_delayed_work queues new work.
+ * So, Increase the ref count to avoid use-after-free.
+ */
+ if (!mod_delayed_work(deferredclose_wq,
+ &cfile->deferred, cifs_sb->ctx->closetimeo))
+ cifsFileInfo_get(cfile);
+ } else {
+ /* Deferred close for files */
+ queue_delayed_work(deferredclose_wq,
+ &cfile->deferred, cifs_sb->ctx->closetimeo);
+ cfile->deferred_close_scheduled = true;
+ spin_unlock(&cinode->deferred_lock);
+ return 0;
+ }
+ spin_unlock(&cinode->deferred_lock);
+ _cifsFileInfo_put(cfile, true, false);
+ } else {
+ _cifsFileInfo_put(cfile, true, false);
+ kfree(dclose);
+ }
+ }
+
+ /* return code from the ->release op is always ignored */
+ return 0;
+}
+
+void
+cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
+{
+ struct cifsFileInfo *open_file, *tmp;
+ struct list_head tmp_list;
+
+ if (!tcon->use_persistent || !tcon->need_reopen_files)
+ return;
+
+ tcon->need_reopen_files = false;
+
+ cifs_dbg(FYI, "Reopen persistent handles\n");
+ INIT_LIST_HEAD(&tmp_list);
+
+ /* list all files open on tree connection, reopen resilient handles */
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(open_file, &tcon->openFileList, tlist) {
+ if (!open_file->invalidHandle)
+ continue;
+ cifsFileInfo_get(open_file);
+ list_add_tail(&open_file->rlist, &tmp_list);
+ }
+ spin_unlock(&tcon->open_file_lock);
+
+ list_for_each_entry_safe(open_file, tmp, &tmp_list, rlist) {
+ if (cifs_reopen_file(open_file, false /* do not flush */))
+ tcon->need_reopen_files = true;
+ list_del_init(&open_file->rlist);
+ cifsFileInfo_put(open_file);
+ }
+}
+
+int cifs_closedir(struct inode *inode, struct file *file)
+{
+ int rc = 0;
+ unsigned int xid;
+ struct cifsFileInfo *cfile = file->private_data;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ char *buf;
+
+ cifs_dbg(FYI, "Closedir inode = 0x%p\n", inode);
+
+ if (cfile == NULL)
+ return rc;
+
+ xid = get_xid();
+ tcon = tlink_tcon(cfile->tlink);
+ server = tcon->ses->server;
+
+ cifs_dbg(FYI, "Freeing private data in close dir\n");
+ spin_lock(&cfile->file_info_lock);
+ if (server->ops->dir_needs_close(cfile)) {
+ cfile->invalidHandle = true;
+ spin_unlock(&cfile->file_info_lock);
+ if (server->ops->close_dir)
+ rc = server->ops->close_dir(xid, tcon, &cfile->fid);
+ else
+ rc = -ENOSYS;
+ cifs_dbg(FYI, "Closing uncompleted readdir with rc %d\n", rc);
+ /* not much we can do if it fails anyway, ignore rc */
+ rc = 0;
+ } else
+ spin_unlock(&cfile->file_info_lock);
+
+ buf = cfile->srch_inf.ntwrk_buf_start;
+ if (buf) {
+ cifs_dbg(FYI, "closedir free smb buf in srch struct\n");
+ cfile->srch_inf.ntwrk_buf_start = NULL;
+ if (cfile->srch_inf.smallBuf)
+ cifs_small_buf_release(buf);
+ else
+ cifs_buf_release(buf);
+ }
+
+ cifs_put_tlink(cfile->tlink);
+ kfree(file->private_data);
+ file->private_data = NULL;
+ /* BB can we lock the filestruct while this is going on? */
+ free_xid(xid);
+ return rc;
+}
+
+static struct cifsLockInfo *
+cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 flags)
+{
+ struct cifsLockInfo *lock =
+ kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
+ if (!lock)
+ return lock;
+ lock->offset = offset;
+ lock->length = length;
+ lock->type = type;
+ lock->pid = current->tgid;
+ lock->flags = flags;
+ INIT_LIST_HEAD(&lock->blist);
+ init_waitqueue_head(&lock->block_q);
+ return lock;
+}
+
+void
+cifs_del_lock_waiters(struct cifsLockInfo *lock)
+{
+ struct cifsLockInfo *li, *tmp;
+ list_for_each_entry_safe(li, tmp, &lock->blist, blist) {
+ list_del_init(&li->blist);
+ wake_up(&li->block_q);
+ }
+}
+
+#define CIFS_LOCK_OP 0
+#define CIFS_READ_OP 1
+#define CIFS_WRITE_OP 2
+
+/* @rw_check : 0 - no op, 1 - read, 2 - write */
+static bool
+cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset,
+ __u64 length, __u8 type, __u16 flags,
+ struct cifsFileInfo *cfile,
+ struct cifsLockInfo **conf_lock, int rw_check)
+{
+ struct cifsLockInfo *li;
+ struct cifsFileInfo *cur_cfile = fdlocks->cfile;
+ struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
+
+ list_for_each_entry(li, &fdlocks->locks, llist) {
+ if (offset + length <= li->offset ||
+ offset >= li->offset + li->length)
+ continue;
+ if (rw_check != CIFS_LOCK_OP && current->tgid == li->pid &&
+ server->ops->compare_fids(cfile, cur_cfile)) {
+ /* shared lock prevents write op through the same fid */
+ if (!(li->type & server->vals->shared_lock_type) ||
+ rw_check != CIFS_WRITE_OP)
+ continue;
+ }
+ if ((type & server->vals->shared_lock_type) &&
+ ((server->ops->compare_fids(cfile, cur_cfile) &&
+ current->tgid == li->pid) || type == li->type))
+ continue;
+ if (rw_check == CIFS_LOCK_OP &&
+ (flags & FL_OFDLCK) && (li->flags & FL_OFDLCK) &&
+ server->ops->compare_fids(cfile, cur_cfile))
+ continue;
+ if (conf_lock)
+ *conf_lock = li;
+ return true;
+ }
+ return false;
+}
+
+bool
+cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
+ __u8 type, __u16 flags,
+ struct cifsLockInfo **conf_lock, int rw_check)
+{
+ bool rc = false;
+ struct cifs_fid_locks *cur;
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+
+ list_for_each_entry(cur, &cinode->llist, llist) {
+ rc = cifs_find_fid_lock_conflict(cur, offset, length, type,
+ flags, cfile, conf_lock,
+ rw_check);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * Check if there is another lock that prevents us to set the lock (mandatory
+ * style). If such a lock exists, update the flock structure with its
+ * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
+ * or leave it the same if we can't. Returns 0 if we don't need to request to
+ * the server or 1 otherwise.
+ */
+static int
+cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
+ __u8 type, struct file_lock *flock)
+{
+ int rc = 0;
+ struct cifsLockInfo *conf_lock;
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
+ bool exist;
+
+ down_read(&cinode->lock_sem);
+
+ exist = cifs_find_lock_conflict(cfile, offset, length, type,
+ flock->fl_flags, &conf_lock,
+ CIFS_LOCK_OP);
+ if (exist) {
+ flock->fl_start = conf_lock->offset;
+ flock->fl_end = conf_lock->offset + conf_lock->length - 1;
+ flock->fl_pid = conf_lock->pid;
+ if (conf_lock->type & server->vals->shared_lock_type)
+ flock->fl_type = F_RDLCK;
+ else
+ flock->fl_type = F_WRLCK;
+ } else if (!cinode->can_cache_brlcks)
+ rc = 1;
+ else
+ flock->fl_type = F_UNLCK;
+
+ up_read(&cinode->lock_sem);
+ return rc;
+}
+
+static void
+cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
+{
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ cifs_down_write(&cinode->lock_sem);
+ list_add_tail(&lock->llist, &cfile->llist->locks);
+ up_write(&cinode->lock_sem);
+}
+
+/*
+ * Set the byte-range lock (mandatory style). Returns:
+ * 1) 0, if we set the lock and don't need to request to the server;
+ * 2) 1, if no locks prevent us but we need to request to the server;
+ * 3) -EACCES, if there is a lock that prevents us and wait is false.
+ */
+static int
+cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
+ bool wait)
+{
+ struct cifsLockInfo *conf_lock;
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ bool exist;
+ int rc = 0;
+
+try_again:
+ exist = false;
+ cifs_down_write(&cinode->lock_sem);
+
+ exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
+ lock->type, lock->flags, &conf_lock,
+ CIFS_LOCK_OP);
+ if (!exist && cinode->can_cache_brlcks) {
+ list_add_tail(&lock->llist, &cfile->llist->locks);
+ up_write(&cinode->lock_sem);
+ return rc;
+ }
+
+ if (!exist)
+ rc = 1;
+ else if (!wait)
+ rc = -EACCES;
+ else {
+ list_add_tail(&lock->blist, &conf_lock->blist);
+ up_write(&cinode->lock_sem);
+ rc = wait_event_interruptible(lock->block_q,
+ (lock->blist.prev == &lock->blist) &&
+ (lock->blist.next == &lock->blist));
+ if (!rc)
+ goto try_again;
+ cifs_down_write(&cinode->lock_sem);
+ list_del_init(&lock->blist);
+ }
+
+ up_write(&cinode->lock_sem);
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+/*
+ * Check if there is another lock that prevents us to set the lock (posix
+ * style). If such a lock exists, update the flock structure with its
+ * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks
+ * or leave it the same if we can't. Returns 0 if we don't need to request to
+ * the server or 1 otherwise.
+ */
+static int
+cifs_posix_lock_test(struct file *file, struct file_lock *flock)
+{
+ int rc = 0;
+ struct cifsInodeInfo *cinode = CIFS_I(file_inode(file));
+ unsigned char saved_type = flock->fl_type;
+
+ if ((flock->fl_flags & FL_POSIX) == 0)
+ return 1;
+
+ down_read(&cinode->lock_sem);
+ posix_test_lock(file, flock);
+
+ if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) {
+ flock->fl_type = saved_type;
+ rc = 1;
+ }
+
+ up_read(&cinode->lock_sem);
+ return rc;
+}
+
+/*
+ * Set the byte-range lock (posix style). Returns:
+ * 1) <0, if the error occurs while setting the lock;
+ * 2) 0, if we set the lock and don't need to request to the server;
+ * 3) FILE_LOCK_DEFERRED, if we will wait for some other file_lock;
+ * 4) FILE_LOCK_DEFERRED + 1, if we need to request to the server.
+ */
+static int
+cifs_posix_lock_set(struct file *file, struct file_lock *flock)
+{
+ struct cifsInodeInfo *cinode = CIFS_I(file_inode(file));
+ int rc = FILE_LOCK_DEFERRED + 1;
+
+ if ((flock->fl_flags & FL_POSIX) == 0)
+ return rc;
+
+ cifs_down_write(&cinode->lock_sem);
+ if (!cinode->can_cache_brlcks) {
+ up_write(&cinode->lock_sem);
+ return rc;
+ }
+
+ rc = posix_lock_file(file, flock, NULL);
+ up_write(&cinode->lock_sem);
+ return rc;
+}
+
+int
+cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
+{
+ unsigned int xid;
+ int rc = 0, stored_rc;
+ struct cifsLockInfo *li, *tmp;
+ struct cifs_tcon *tcon;
+ unsigned int num, max_num, max_buf;
+ LOCKING_ANDX_RANGE *buf, *cur;
+ static const int types[] = {
+ LOCKING_ANDX_LARGE_FILES,
+ LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES
+ };
+ int i;
+
+ xid = get_xid();
+ tcon = tlink_tcon(cfile->tlink);
+
+ /*
+ * Accessing maxBuf is racy with cifs_reconnect - need to store value
+ * and check it before using.
+ */
+ max_buf = tcon->ses->server->maxBuf;
+ if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) {
+ free_xid(xid);
+ return -EINVAL;
+ }
+
+ BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
+ PAGE_SIZE);
+ max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
+ PAGE_SIZE);
+ max_num = (max_buf - sizeof(struct smb_hdr)) /
+ sizeof(LOCKING_ANDX_RANGE);
+ buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
+ if (!buf) {
+ free_xid(xid);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < 2; i++) {
+ cur = buf;
+ num = 0;
+ list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
+ if (li->type != types[i])
+ continue;
+ cur->Pid = cpu_to_le16(li->pid);
+ cur->LengthLow = cpu_to_le32((u32)li->length);
+ cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
+ cur->OffsetLow = cpu_to_le32((u32)li->offset);
+ cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
+ if (++num == max_num) {
+ stored_rc = cifs_lockv(xid, tcon,
+ cfile->fid.netfid,
+ (__u8)li->type, 0, num,
+ buf);
+ if (stored_rc)
+ rc = stored_rc;
+ cur = buf;
+ num = 0;
+ } else
+ cur++;
+ }
+
+ if (num) {
+ stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
+ (__u8)types[i], 0, num, buf);
+ if (stored_rc)
+ rc = stored_rc;
+ }
+ }
+
+ kfree(buf);
+ free_xid(xid);
+ return rc;
+}
+
+static __u32
+hash_lockowner(fl_owner_t owner)
+{
+ return cifs_lock_secret ^ hash32_ptr((const void *)owner);
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+struct lock_to_push {
+ struct list_head llist;
+ __u64 offset;
+ __u64 length;
+ __u32 pid;
+ __u16 netfid;
+ __u8 type;
+};
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+static int
+cifs_push_posix_locks(struct cifsFileInfo *cfile)
+{
+ struct inode *inode = d_inode(cfile->dentry);
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ struct file_lock *flock;
+ struct file_lock_context *flctx = inode->i_flctx;
+ unsigned int count = 0, i;
+ int rc = 0, xid, type;
+ struct list_head locks_to_send, *el;
+ struct lock_to_push *lck, *tmp;
+ __u64 length;
+
+ xid = get_xid();
+
+ if (!flctx)
+ goto out;
+
+ spin_lock(&flctx->flc_lock);
+ list_for_each(el, &flctx->flc_posix) {
+ count++;
+ }
+ spin_unlock(&flctx->flc_lock);
+
+ INIT_LIST_HEAD(&locks_to_send);
+
+ /*
+ * Allocating count locks is enough because no FL_POSIX locks can be
+ * added to the list while we are holding cinode->lock_sem that
+ * protects locking operations of this inode.
+ */
+ for (i = 0; i < count; i++) {
+ lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
+ if (!lck) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ list_add_tail(&lck->llist, &locks_to_send);
+ }
+
+ el = locks_to_send.next;
+ spin_lock(&flctx->flc_lock);
+ list_for_each_entry(flock, &flctx->flc_posix, fl_list) {
+ if (el == &locks_to_send) {
+ /*
+ * The list ended. We don't have enough allocated
+ * structures - something is really wrong.
+ */
+ cifs_dbg(VFS, "Can't push all brlocks!\n");
+ break;
+ }
+ length = cifs_flock_len(flock);
+ if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
+ type = CIFS_RDLCK;
+ else
+ type = CIFS_WRLCK;
+ lck = list_entry(el, struct lock_to_push, llist);
+ lck->pid = hash_lockowner(flock->fl_owner);
+ lck->netfid = cfile->fid.netfid;
+ lck->length = length;
+ lck->type = type;
+ lck->offset = flock->fl_start;
+ }
+ spin_unlock(&flctx->flc_lock);
+
+ list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
+ int stored_rc;
+
+ stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid,
+ lck->offset, lck->length, NULL,
+ lck->type, 0);
+ if (stored_rc)
+ rc = stored_rc;
+ list_del(&lck->llist);
+ kfree(lck);
+ }
+
+out:
+ free_xid(xid);
+ return rc;
+err_out:
+ list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) {
+ list_del(&lck->llist);
+ kfree(lck);
+ }
+ goto out;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+static int
+cifs_push_locks(struct cifsFileInfo *cfile)
+{
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ int rc = 0;
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ /* we are going to update can_cache_brlcks here - need a write access */
+ cifs_down_write(&cinode->lock_sem);
+ if (!cinode->can_cache_brlcks) {
+ up_write(&cinode->lock_sem);
+ return rc;
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (cap_unix(tcon->ses) &&
+ (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
+ ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
+ rc = cifs_push_posix_locks(cfile);
+ else
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ rc = tcon->ses->server->ops->push_mand_locks(cfile);
+
+ cinode->can_cache_brlcks = false;
+ up_write(&cinode->lock_sem);
+ return rc;
+}
+
+static void
+cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock,
+ bool *wait_flag, struct TCP_Server_Info *server)
+{
+ if (flock->fl_flags & FL_POSIX)
+ cifs_dbg(FYI, "Posix\n");
+ if (flock->fl_flags & FL_FLOCK)
+ cifs_dbg(FYI, "Flock\n");
+ if (flock->fl_flags & FL_SLEEP) {
+ cifs_dbg(FYI, "Blocking lock\n");
+ *wait_flag = true;
+ }
+ if (flock->fl_flags & FL_ACCESS)
+ cifs_dbg(FYI, "Process suspended by mandatory locking - not implemented yet\n");
+ if (flock->fl_flags & FL_LEASE)
+ cifs_dbg(FYI, "Lease on file - not implemented yet\n");
+ if (flock->fl_flags &
+ (~(FL_POSIX | FL_FLOCK | FL_SLEEP |
+ FL_ACCESS | FL_LEASE | FL_CLOSE | FL_OFDLCK)))
+ cifs_dbg(FYI, "Unknown lock flags 0x%x\n", flock->fl_flags);
+
+ *type = server->vals->large_lock_type;
+ if (flock->fl_type == F_WRLCK) {
+ cifs_dbg(FYI, "F_WRLCK\n");
+ *type |= server->vals->exclusive_lock_type;
+ *lock = 1;
+ } else if (flock->fl_type == F_UNLCK) {
+ cifs_dbg(FYI, "F_UNLCK\n");
+ *type |= server->vals->unlock_lock_type;
+ *unlock = 1;
+ /* Check if unlock includes more than one lock range */
+ } else if (flock->fl_type == F_RDLCK) {
+ cifs_dbg(FYI, "F_RDLCK\n");
+ *type |= server->vals->shared_lock_type;
+ *lock = 1;
+ } else if (flock->fl_type == F_EXLCK) {
+ cifs_dbg(FYI, "F_EXLCK\n");
+ *type |= server->vals->exclusive_lock_type;
+ *lock = 1;
+ } else if (flock->fl_type == F_SHLCK) {
+ cifs_dbg(FYI, "F_SHLCK\n");
+ *type |= server->vals->shared_lock_type;
+ *lock = 1;
+ } else
+ cifs_dbg(FYI, "Unknown type of lock\n");
+}
+
+static int
+cifs_getlk(struct file *file, struct file_lock *flock, __u32 type,
+ bool wait_flag, bool posix_lck, unsigned int xid)
+{
+ int rc = 0;
+ __u64 length = cifs_flock_len(flock);
+ struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ struct TCP_Server_Info *server = tcon->ses->server;
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ __u16 netfid = cfile->fid.netfid;
+
+ if (posix_lck) {
+ int posix_lock_type;
+
+ rc = cifs_posix_lock_test(file, flock);
+ if (!rc)
+ return rc;
+
+ if (type & server->vals->shared_lock_type)
+ posix_lock_type = CIFS_RDLCK;
+ else
+ posix_lock_type = CIFS_WRLCK;
+ rc = CIFSSMBPosixLock(xid, tcon, netfid,
+ hash_lockowner(flock->fl_owner),
+ flock->fl_start, length, flock,
+ posix_lock_type, wait_flag);
+ return rc;
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock);
+ if (!rc)
+ return rc;
+
+ /* BB we could chain these into one lock request BB */
+ rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, type,
+ 1, 0, false);
+ if (rc == 0) {
+ rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
+ type, 0, 1, false);
+ flock->fl_type = F_UNLCK;
+ if (rc != 0)
+ cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n",
+ rc);
+ return 0;
+ }
+
+ if (type & server->vals->shared_lock_type) {
+ flock->fl_type = F_WRLCK;
+ return 0;
+ }
+
+ type &= ~server->vals->exclusive_lock_type;
+
+ rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
+ type | server->vals->shared_lock_type,
+ 1, 0, false);
+ if (rc == 0) {
+ rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
+ type | server->vals->shared_lock_type, 0, 1, false);
+ flock->fl_type = F_RDLCK;
+ if (rc != 0)
+ cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n",
+ rc);
+ } else
+ flock->fl_type = F_WRLCK;
+
+ return 0;
+}
+
+void
+cifs_move_llist(struct list_head *source, struct list_head *dest)
+{
+ struct list_head *li, *tmp;
+ list_for_each_safe(li, tmp, source)
+ list_move(li, dest);
+}
+
+void
+cifs_free_llist(struct list_head *llist)
+{
+ struct cifsLockInfo *li, *tmp;
+ list_for_each_entry_safe(li, tmp, llist, llist) {
+ cifs_del_lock_waiters(li);
+ list_del(&li->llist);
+ kfree(li);
+ }
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+int
+cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
+ unsigned int xid)
+{
+ int rc = 0, stored_rc;
+ static const int types[] = {
+ LOCKING_ANDX_LARGE_FILES,
+ LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES
+ };
+ unsigned int i;
+ unsigned int max_num, num, max_buf;
+ LOCKING_ANDX_RANGE *buf, *cur;
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ struct cifsLockInfo *li, *tmp;
+ __u64 length = cifs_flock_len(flock);
+ struct list_head tmp_llist;
+
+ INIT_LIST_HEAD(&tmp_llist);
+
+ /*
+ * Accessing maxBuf is racy with cifs_reconnect - need to store value
+ * and check it before using.
+ */
+ max_buf = tcon->ses->server->maxBuf;
+ if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE)))
+ return -EINVAL;
+
+ BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
+ PAGE_SIZE);
+ max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
+ PAGE_SIZE);
+ max_num = (max_buf - sizeof(struct smb_hdr)) /
+ sizeof(LOCKING_ANDX_RANGE);
+ buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ cifs_down_write(&cinode->lock_sem);
+ for (i = 0; i < 2; i++) {
+ cur = buf;
+ num = 0;
+ list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
+ if (flock->fl_start > li->offset ||
+ (flock->fl_start + length) <
+ (li->offset + li->length))
+ continue;
+ if (current->tgid != li->pid)
+ continue;
+ if (types[i] != li->type)
+ continue;
+ if (cinode->can_cache_brlcks) {
+ /*
+ * We can cache brlock requests - simply remove
+ * a lock from the file's list.
+ */
+ list_del(&li->llist);
+ cifs_del_lock_waiters(li);
+ kfree(li);
+ continue;
+ }
+ cur->Pid = cpu_to_le16(li->pid);
+ cur->LengthLow = cpu_to_le32((u32)li->length);
+ cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
+ cur->OffsetLow = cpu_to_le32((u32)li->offset);
+ cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
+ /*
+ * We need to save a lock here to let us add it again to
+ * the file's list if the unlock range request fails on
+ * the server.
+ */
+ list_move(&li->llist, &tmp_llist);
+ if (++num == max_num) {
+ stored_rc = cifs_lockv(xid, tcon,
+ cfile->fid.netfid,
+ li->type, num, 0, buf);
+ if (stored_rc) {
+ /*
+ * We failed on the unlock range
+ * request - add all locks from the tmp
+ * list to the head of the file's list.
+ */
+ cifs_move_llist(&tmp_llist,
+ &cfile->llist->locks);
+ rc = stored_rc;
+ } else
+ /*
+ * The unlock range request succeed -
+ * free the tmp list.
+ */
+ cifs_free_llist(&tmp_llist);
+ cur = buf;
+ num = 0;
+ } else
+ cur++;
+ }
+ if (num) {
+ stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
+ types[i], num, 0, buf);
+ if (stored_rc) {
+ cifs_move_llist(&tmp_llist,
+ &cfile->llist->locks);
+ rc = stored_rc;
+ } else
+ cifs_free_llist(&tmp_llist);
+ }
+ }
+
+ up_write(&cinode->lock_sem);
+ kfree(buf);
+ return rc;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+static int
+cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
+ bool wait_flag, bool posix_lck, int lock, int unlock,
+ unsigned int xid)
+{
+ int rc = 0;
+ __u64 length = cifs_flock_len(flock);
+ struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct inode *inode = d_inode(cfile->dentry);
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (posix_lck) {
+ int posix_lock_type;
+
+ rc = cifs_posix_lock_set(file, flock);
+ if (rc <= FILE_LOCK_DEFERRED)
+ return rc;
+
+ if (type & server->vals->shared_lock_type)
+ posix_lock_type = CIFS_RDLCK;
+ else
+ posix_lock_type = CIFS_WRLCK;
+
+ if (unlock == 1)
+ posix_lock_type = CIFS_UNLCK;
+
+ rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid,
+ hash_lockowner(flock->fl_owner),
+ flock->fl_start, length,
+ NULL, posix_lock_type, wait_flag);
+ goto out;
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ if (lock) {
+ struct cifsLockInfo *lock;
+
+ lock = cifs_lock_init(flock->fl_start, length, type,
+ flock->fl_flags);
+ if (!lock)
+ return -ENOMEM;
+
+ rc = cifs_lock_add_if(cfile, lock, wait_flag);
+ if (rc < 0) {
+ kfree(lock);
+ return rc;
+ }
+ if (!rc)
+ goto out;
+
+ /*
+ * Windows 7 server can delay breaking lease from read to None
+ * if we set a byte-range lock on a file - break it explicitly
+ * before sending the lock to the server to be sure the next
+ * read won't conflict with non-overlapted locks due to
+ * pagereading.
+ */
+ if (!CIFS_CACHE_WRITE(CIFS_I(inode)) &&
+ CIFS_CACHE_READ(CIFS_I(inode))) {
+ cifs_zap_mapping(inode);
+ cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n",
+ inode);
+ CIFS_I(inode)->oplock = 0;
+ }
+
+ rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length,
+ type, 1, 0, wait_flag);
+ if (rc) {
+ kfree(lock);
+ return rc;
+ }
+
+ cifs_lock_add(cfile, lock);
+ } else if (unlock)
+ rc = server->ops->mand_unlock_range(cfile, flock, xid);
+
+out:
+ if ((flock->fl_flags & FL_POSIX) || (flock->fl_flags & FL_FLOCK)) {
+ /*
+ * If this is a request to remove all locks because we
+ * are closing the file, it doesn't matter if the
+ * unlocking failed as both cifs.ko and the SMB server
+ * remove the lock on file close
+ */
+ if (rc) {
+ cifs_dbg(VFS, "%s failed rc=%d\n", __func__, rc);
+ if (!(flock->fl_flags & FL_CLOSE))
+ return rc;
+ }
+ rc = locks_lock_file_wait(file, flock);
+ }
+ return rc;
+}
+
+int cifs_flock(struct file *file, int cmd, struct file_lock *fl)
+{
+ int rc, xid;
+ int lock = 0, unlock = 0;
+ bool wait_flag = false;
+ bool posix_lck = false;
+ struct cifs_sb_info *cifs_sb;
+ struct cifs_tcon *tcon;
+ struct cifsFileInfo *cfile;
+ __u32 type;
+
+ xid = get_xid();
+
+ if (!(fl->fl_flags & FL_FLOCK)) {
+ rc = -ENOLCK;
+ free_xid(xid);
+ return rc;
+ }
+
+ cfile = (struct cifsFileInfo *)file->private_data;
+ tcon = tlink_tcon(cfile->tlink);
+
+ cifs_read_flock(fl, &type, &lock, &unlock, &wait_flag,
+ tcon->ses->server);
+ cifs_sb = CIFS_FILE_SB(file);
+
+ if (cap_unix(tcon->ses) &&
+ (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
+ ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
+ posix_lck = true;
+
+ if (!lock && !unlock) {
+ /*
+ * if no lock or unlock then nothing to do since we do not
+ * know what it is
+ */
+ rc = -EOPNOTSUPP;
+ free_xid(xid);
+ return rc;
+ }
+
+ rc = cifs_setlk(file, fl, type, wait_flag, posix_lck, lock, unlock,
+ xid);
+ free_xid(xid);
+ return rc;
+
+
+}
+
+int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
+{
+ int rc, xid;
+ int lock = 0, unlock = 0;
+ bool wait_flag = false;
+ bool posix_lck = false;
+ struct cifs_sb_info *cifs_sb;
+ struct cifs_tcon *tcon;
+ struct cifsFileInfo *cfile;
+ __u32 type;
+
+ rc = -EACCES;
+ xid = get_xid();
+
+ cifs_dbg(FYI, "%s: %pD2 cmd=0x%x type=0x%x flags=0x%x r=%lld:%lld\n", __func__, file, cmd,
+ flock->fl_flags, flock->fl_type, (long long)flock->fl_start,
+ (long long)flock->fl_end);
+
+ cfile = (struct cifsFileInfo *)file->private_data;
+ tcon = tlink_tcon(cfile->tlink);
+
+ cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
+ tcon->ses->server);
+ cifs_sb = CIFS_FILE_SB(file);
+ set_bit(CIFS_INO_CLOSE_ON_LOCK, &CIFS_I(d_inode(cfile->dentry))->flags);
+
+ if (cap_unix(tcon->ses) &&
+ (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
+ ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
+ posix_lck = true;
+ /*
+ * BB add code here to normalize offset and length to account for
+ * negative length which we can not accept over the wire.
+ */
+ if (IS_GETLK(cmd)) {
+ rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid);
+ free_xid(xid);
+ return rc;
+ }
+
+ if (!lock && !unlock) {
+ /*
+ * if no lock or unlock then nothing to do since we do not
+ * know what it is
+ */
+ free_xid(xid);
+ return -EOPNOTSUPP;
+ }
+
+ rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock,
+ xid);
+ free_xid(xid);
+ return rc;
+}
+
+/*
+ * update the file size (if needed) after a write. Should be called with
+ * the inode->i_lock held
+ */
+void
+cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
+ unsigned int bytes_written)
+{
+ loff_t end_of_write = offset + bytes_written;
+
+ if (end_of_write > cifsi->server_eof)
+ cifsi->server_eof = end_of_write;
+}
+
+static ssize_t
+cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
+ size_t write_size, loff_t *offset)
+{
+ int rc = 0;
+ unsigned int bytes_written = 0;
+ unsigned int total_written;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ unsigned int xid;
+ struct dentry *dentry = open_file->dentry;
+ struct cifsInodeInfo *cifsi = CIFS_I(d_inode(dentry));
+ struct cifs_io_parms io_parms = {0};
+
+ cifs_dbg(FYI, "write %zd bytes to offset %lld of %pd\n",
+ write_size, *offset, dentry);
+
+ tcon = tlink_tcon(open_file->tlink);
+ server = tcon->ses->server;
+
+ if (!server->ops->sync_write)
+ return -ENOSYS;
+
+ xid = get_xid();
+
+ for (total_written = 0; write_size > total_written;
+ total_written += bytes_written) {
+ rc = -EAGAIN;
+ while (rc == -EAGAIN) {
+ struct kvec iov[2];
+ unsigned int len;
+
+ if (open_file->invalidHandle) {
+ /* we could deadlock if we called
+ filemap_fdatawait from here so tell
+ reopen_file not to flush data to
+ server now */
+ rc = cifs_reopen_file(open_file, false);
+ if (rc != 0)
+ break;
+ }
+
+ len = min(server->ops->wp_retry_size(d_inode(dentry)),
+ (unsigned int)write_size - total_written);
+ /* iov[0] is reserved for smb header */
+ iov[1].iov_base = (char *)write_data + total_written;
+ iov[1].iov_len = len;
+ io_parms.pid = pid;
+ io_parms.tcon = tcon;
+ io_parms.offset = *offset;
+ io_parms.length = len;
+ rc = server->ops->sync_write(xid, &open_file->fid,
+ &io_parms, &bytes_written, iov, 1);
+ }
+ if (rc || (bytes_written == 0)) {
+ if (total_written)
+ break;
+ else {
+ free_xid(xid);
+ return rc;
+ }
+ } else {
+ spin_lock(&d_inode(dentry)->i_lock);
+ cifs_update_eof(cifsi, *offset, bytes_written);
+ spin_unlock(&d_inode(dentry)->i_lock);
+ *offset += bytes_written;
+ }
+ }
+
+ cifs_stats_bytes_written(tcon, total_written);
+
+ if (total_written > 0) {
+ spin_lock(&d_inode(dentry)->i_lock);
+ if (*offset > d_inode(dentry)->i_size) {
+ i_size_write(d_inode(dentry), *offset);
+ d_inode(dentry)->i_blocks = (512 - 1 + *offset) >> 9;
+ }
+ spin_unlock(&d_inode(dentry)->i_lock);
+ }
+ mark_inode_dirty_sync(d_inode(dentry));
+ free_xid(xid);
+ return total_written;
+}
+
+struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
+ bool fsuid_only)
+{
+ struct cifsFileInfo *open_file = NULL;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb);
+
+ /* only filter by fsuid on multiuser mounts */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
+ fsuid_only = false;
+
+ spin_lock(&cifs_inode->open_file_lock);
+ /* we could simply get the first_list_entry since write-only entries
+ are always at the end of the list but since the first entry might
+ have a close pending, we go through the whole list */
+ list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
+ if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
+ continue;
+ if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
+ if ((!open_file->invalidHandle)) {
+ /* found a good file */
+ /* lock it so it will not be closed on us */
+ cifsFileInfo_get(open_file);
+ spin_unlock(&cifs_inode->open_file_lock);
+ return open_file;
+ } /* else might as well continue, and look for
+ another, or simply have the caller reopen it
+ again rather than trying to fix this handle */
+ } else /* write only file */
+ break; /* write only files are last so must be done */
+ }
+ spin_unlock(&cifs_inode->open_file_lock);
+ return NULL;
+}
+
+/* Return -EBADF if no handle is found and general rc otherwise */
+int
+cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
+ struct cifsFileInfo **ret_file)
+{
+ struct cifsFileInfo *open_file, *inv_file = NULL;
+ struct cifs_sb_info *cifs_sb;
+ bool any_available = false;
+ int rc = -EBADF;
+ unsigned int refind = 0;
+ bool fsuid_only = flags & FIND_WR_FSUID_ONLY;
+ bool with_delete = flags & FIND_WR_WITH_DELETE;
+ *ret_file = NULL;
+
+ /*
+ * Having a null inode here (because mapping->host was set to zero by
+ * the VFS or MM) should not happen but we had reports of on oops (due
+ * to it being zero) during stress testcases so we need to check for it
+ */
+
+ if (cifs_inode == NULL) {
+ cifs_dbg(VFS, "Null inode passed to cifs_writeable_file\n");
+ dump_stack();
+ return rc;
+ }
+
+ cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb);
+
+ /* only filter by fsuid on multiuser mounts */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
+ fsuid_only = false;
+
+ spin_lock(&cifs_inode->open_file_lock);
+refind_writable:
+ if (refind > MAX_REOPEN_ATT) {
+ spin_unlock(&cifs_inode->open_file_lock);
+ return rc;
+ }
+ list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
+ if (!any_available && open_file->pid != current->tgid)
+ continue;
+ if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
+ continue;
+ if (with_delete && !(open_file->fid.access & DELETE))
+ continue;
+ if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
+ if (!open_file->invalidHandle) {
+ /* found a good writable file */
+ cifsFileInfo_get(open_file);
+ spin_unlock(&cifs_inode->open_file_lock);
+ *ret_file = open_file;
+ return 0;
+ } else {
+ if (!inv_file)
+ inv_file = open_file;
+ }
+ }
+ }
+ /* couldn't find useable FH with same pid, try any available */
+ if (!any_available) {
+ any_available = true;
+ goto refind_writable;
+ }
+
+ if (inv_file) {
+ any_available = false;
+ cifsFileInfo_get(inv_file);
+ }
+
+ spin_unlock(&cifs_inode->open_file_lock);
+
+ if (inv_file) {
+ rc = cifs_reopen_file(inv_file, false);
+ if (!rc) {
+ *ret_file = inv_file;
+ return 0;
+ }
+
+ spin_lock(&cifs_inode->open_file_lock);
+ list_move_tail(&inv_file->flist, &cifs_inode->openFileList);
+ spin_unlock(&cifs_inode->open_file_lock);
+ cifsFileInfo_put(inv_file);
+ ++refind;
+ inv_file = NULL;
+ spin_lock(&cifs_inode->open_file_lock);
+ goto refind_writable;
+ }
+
+ return rc;
+}
+
+struct cifsFileInfo *
+find_writable_file(struct cifsInodeInfo *cifs_inode, int flags)
+{
+ struct cifsFileInfo *cfile;
+ int rc;
+
+ rc = cifs_get_writable_file(cifs_inode, flags, &cfile);
+ if (rc)
+ cifs_dbg(FYI, "Couldn't find writable handle rc=%d\n", rc);
+
+ return cfile;
+}
+
+int
+cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
+ int flags,
+ struct cifsFileInfo **ret_file)
+{
+ struct cifsFileInfo *cfile;
+ void *page = alloc_dentry_path();
+
+ *ret_file = NULL;
+
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(cfile, &tcon->openFileList, tlist) {
+ struct cifsInodeInfo *cinode;
+ const char *full_path = build_path_from_dentry(cfile->dentry, page);
+ if (IS_ERR(full_path)) {
+ spin_unlock(&tcon->open_file_lock);
+ free_dentry_path(page);
+ return PTR_ERR(full_path);
+ }
+ if (strcmp(full_path, name))
+ continue;
+
+ cinode = CIFS_I(d_inode(cfile->dentry));
+ spin_unlock(&tcon->open_file_lock);
+ free_dentry_path(page);
+ return cifs_get_writable_file(cinode, flags, ret_file);
+ }
+
+ spin_unlock(&tcon->open_file_lock);
+ free_dentry_path(page);
+ return -ENOENT;
+}
+
+int
+cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
+ struct cifsFileInfo **ret_file)
+{
+ struct cifsFileInfo *cfile;
+ void *page = alloc_dentry_path();
+
+ *ret_file = NULL;
+
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(cfile, &tcon->openFileList, tlist) {
+ struct cifsInodeInfo *cinode;
+ const char *full_path = build_path_from_dentry(cfile->dentry, page);
+ if (IS_ERR(full_path)) {
+ spin_unlock(&tcon->open_file_lock);
+ free_dentry_path(page);
+ return PTR_ERR(full_path);
+ }
+ if (strcmp(full_path, name))
+ continue;
+
+ cinode = CIFS_I(d_inode(cfile->dentry));
+ spin_unlock(&tcon->open_file_lock);
+ free_dentry_path(page);
+ *ret_file = find_readable_file(cinode, 0);
+ return *ret_file ? 0 : -ENOENT;
+ }
+
+ spin_unlock(&tcon->open_file_lock);
+ free_dentry_path(page);
+ return -ENOENT;
+}
+
+void
+cifs_writedata_release(struct kref *refcount)
+{
+ struct cifs_writedata *wdata = container_of(refcount,
+ struct cifs_writedata, refcount);
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ if (wdata->mr) {
+ smbd_deregister_mr(wdata->mr);
+ wdata->mr = NULL;
+ }
+#endif
+
+ if (wdata->cfile)
+ cifsFileInfo_put(wdata->cfile);
+
+ kvfree(wdata->pages);
+ kfree(wdata);
+}
+
+/*
+ * Write failed with a retryable error. Resend the write request. It's also
+ * possible that the page was redirtied so re-clean the page.
+ */
+static void
+cifs_writev_requeue(struct cifs_writedata *wdata)
+{
+ int i, rc = 0;
+ struct inode *inode = d_inode(wdata->cfile->dentry);
+ struct TCP_Server_Info *server;
+ unsigned int rest_len;
+
+ server = tlink_tcon(wdata->cfile->tlink)->ses->server;
+ i = 0;
+ rest_len = wdata->bytes;
+ do {
+ struct cifs_writedata *wdata2;
+ unsigned int j, nr_pages, wsize, tailsz, cur_len;
+
+ wsize = server->ops->wp_retry_size(inode);
+ if (wsize < rest_len) {
+ nr_pages = wsize / PAGE_SIZE;
+ if (!nr_pages) {
+ rc = -EOPNOTSUPP;
+ break;
+ }
+ cur_len = nr_pages * PAGE_SIZE;
+ tailsz = PAGE_SIZE;
+ } else {
+ nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
+ cur_len = rest_len;
+ tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
+ }
+
+ wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
+ if (!wdata2) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ for (j = 0; j < nr_pages; j++) {
+ wdata2->pages[j] = wdata->pages[i + j];
+ lock_page(wdata2->pages[j]);
+ clear_page_dirty_for_io(wdata2->pages[j]);
+ }
+
+ wdata2->sync_mode = wdata->sync_mode;
+ wdata2->nr_pages = nr_pages;
+ wdata2->offset = page_offset(wdata2->pages[0]);
+ wdata2->pagesz = PAGE_SIZE;
+ wdata2->tailsz = tailsz;
+ wdata2->bytes = cur_len;
+
+ rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY,
+ &wdata2->cfile);
+ if (!wdata2->cfile) {
+ cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n",
+ rc);
+ if (!is_retryable_error(rc))
+ rc = -EBADF;
+ } else {
+ wdata2->pid = wdata2->cfile->pid;
+ rc = server->ops->async_writev(wdata2,
+ cifs_writedata_release);
+ }
+
+ for (j = 0; j < nr_pages; j++) {
+ unlock_page(wdata2->pages[j]);
+ if (rc != 0 && !is_retryable_error(rc)) {
+ SetPageError(wdata2->pages[j]);
+ end_page_writeback(wdata2->pages[j]);
+ put_page(wdata2->pages[j]);
+ }
+ }
+
+ kref_put(&wdata2->refcount, cifs_writedata_release);
+ if (rc) {
+ if (is_retryable_error(rc))
+ continue;
+ i += nr_pages;
+ break;
+ }
+
+ rest_len -= cur_len;
+ i += nr_pages;
+ } while (i < wdata->nr_pages);
+
+ /* cleanup remaining pages from the original wdata */
+ for (; i < wdata->nr_pages; i++) {
+ SetPageError(wdata->pages[i]);
+ end_page_writeback(wdata->pages[i]);
+ put_page(wdata->pages[i]);
+ }
+
+ if (rc != 0 && !is_retryable_error(rc))
+ mapping_set_error(inode->i_mapping, rc);
+ kref_put(&wdata->refcount, cifs_writedata_release);
+}
+
+void
+cifs_writev_complete(struct work_struct *work)
+{
+ struct cifs_writedata *wdata = container_of(work,
+ struct cifs_writedata, work);
+ struct inode *inode = d_inode(wdata->cfile->dentry);
+ int i = 0;
+
+ if (wdata->result == 0) {
+ spin_lock(&inode->i_lock);
+ cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
+ spin_unlock(&inode->i_lock);
+ cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
+ wdata->bytes);
+ } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
+ return cifs_writev_requeue(wdata);
+
+ for (i = 0; i < wdata->nr_pages; i++) {
+ struct page *page = wdata->pages[i];
+
+ if (wdata->result == -EAGAIN)
+ __set_page_dirty_nobuffers(page);
+ else if (wdata->result < 0)
+ SetPageError(page);
+ end_page_writeback(page);
+ cifs_readpage_to_fscache(inode, page);
+ put_page(page);
+ }
+ if (wdata->result != -EAGAIN)
+ mapping_set_error(inode->i_mapping, wdata->result);
+ kref_put(&wdata->refcount, cifs_writedata_release);
+}
+
+struct cifs_writedata *
+cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
+{
+ struct cifs_writedata *writedata = NULL;
+ struct page **pages =
+ kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
+ if (pages) {
+ writedata = cifs_writedata_direct_alloc(pages, complete);
+ if (!writedata)
+ kvfree(pages);
+ }
+
+ return writedata;
+}
+
+struct cifs_writedata *
+cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
+{
+ struct cifs_writedata *wdata;
+
+ wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
+ if (wdata != NULL) {
+ wdata->pages = pages;
+ kref_init(&wdata->refcount);
+ INIT_LIST_HEAD(&wdata->list);
+ init_completion(&wdata->done);
+ INIT_WORK(&wdata->work, complete);
+ }
+ return wdata;
+}
+
+
+static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
+{
+ struct address_space *mapping = page->mapping;
+ loff_t offset = (loff_t)page->index << PAGE_SHIFT;
+ char *write_data;
+ int rc = -EFAULT;
+ int bytes_written = 0;
+ struct inode *inode;
+ struct cifsFileInfo *open_file;
+
+ if (!mapping || !mapping->host)
+ return -EFAULT;
+
+ inode = page->mapping->host;
+
+ offset += (loff_t)from;
+ write_data = kmap(page);
+ write_data += from;
+
+ if ((to > PAGE_SIZE) || (from > to)) {
+ kunmap(page);
+ return -EIO;
+ }
+
+ /* racing with truncate? */
+ if (offset > mapping->host->i_size) {
+ kunmap(page);
+ return 0; /* don't care */
+ }
+
+ /* check to make sure that we are not extending the file */
+ if (mapping->host->i_size - offset < (loff_t)to)
+ to = (unsigned)(mapping->host->i_size - offset);
+
+ rc = cifs_get_writable_file(CIFS_I(mapping->host), FIND_WR_ANY,
+ &open_file);
+ if (!rc) {
+ bytes_written = cifs_write(open_file, open_file->pid,
+ write_data, to - from, &offset);
+ cifsFileInfo_put(open_file);
+ /* Does mm or vfs already set times? */
+ inode->i_atime = inode->i_mtime = current_time(inode);
+ if ((bytes_written > 0) && (offset))
+ rc = 0;
+ else if (bytes_written < 0)
+ rc = bytes_written;
+ else
+ rc = -EFAULT;
+ } else {
+ cifs_dbg(FYI, "No writable handle for write page rc=%d\n", rc);
+ if (!is_retryable_error(rc))
+ rc = -EIO;
+ }
+
+ kunmap(page);
+ return rc;
+}
+
+static struct cifs_writedata *
+wdata_alloc_and_fillpages(pgoff_t tofind, struct address_space *mapping,
+ pgoff_t end, pgoff_t *index,
+ unsigned int *found_pages)
+{
+ struct cifs_writedata *wdata;
+
+ wdata = cifs_writedata_alloc((unsigned int)tofind,
+ cifs_writev_complete);
+ if (!wdata)
+ return NULL;
+
+ *found_pages = find_get_pages_range_tag(mapping, index, end,
+ PAGECACHE_TAG_DIRTY, tofind, wdata->pages);
+ return wdata;
+}
+
+static unsigned int
+wdata_prepare_pages(struct cifs_writedata *wdata, unsigned int found_pages,
+ struct address_space *mapping,
+ struct writeback_control *wbc,
+ pgoff_t end, pgoff_t *index, pgoff_t *next, bool *done)
+{
+ unsigned int nr_pages = 0, i;
+ struct page *page;
+
+ for (i = 0; i < found_pages; i++) {
+ page = wdata->pages[i];
+ /*
+ * At this point we hold neither the i_pages lock nor the
+ * page lock: the page may be truncated or invalidated
+ * (changing page->mapping to NULL), or even swizzled
+ * back from swapper_space to tmpfs file mapping
+ */
+
+ if (nr_pages == 0)
+ lock_page(page);
+ else if (!trylock_page(page))
+ break;
+
+ if (unlikely(page->mapping != mapping)) {
+ unlock_page(page);
+ break;
+ }
+
+ if (!wbc->range_cyclic && page->index > end) {
+ *done = true;
+ unlock_page(page);
+ break;
+ }
+
+ if (*next && (page->index != *next)) {
+ /* Not next consecutive page */
+ unlock_page(page);
+ break;
+ }
+
+ if (wbc->sync_mode != WB_SYNC_NONE)
+ wait_on_page_writeback(page);
+
+ if (PageWriteback(page) ||
+ !clear_page_dirty_for_io(page)) {
+ unlock_page(page);
+ break;
+ }
+
+ /*
+ * This actually clears the dirty bit in the radix tree.
+ * See cifs_writepage() for more commentary.
+ */
+ set_page_writeback(page);
+ if (page_offset(page) >= i_size_read(mapping->host)) {
+ *done = true;
+ unlock_page(page);
+ end_page_writeback(page);
+ break;
+ }
+
+ wdata->pages[i] = page;
+ *next = page->index + 1;
+ ++nr_pages;
+ }
+
+ /* reset index to refind any pages skipped */
+ if (nr_pages == 0)
+ *index = wdata->pages[0]->index + 1;
+
+ /* put any pages we aren't going to use */
+ for (i = nr_pages; i < found_pages; i++) {
+ put_page(wdata->pages[i]);
+ wdata->pages[i] = NULL;
+ }
+
+ return nr_pages;
+}
+
+static int
+wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages,
+ struct address_space *mapping, struct writeback_control *wbc)
+{
+ int rc;
+
+ wdata->sync_mode = wbc->sync_mode;
+ wdata->nr_pages = nr_pages;
+ wdata->offset = page_offset(wdata->pages[0]);
+ wdata->pagesz = PAGE_SIZE;
+ wdata->tailsz = min(i_size_read(mapping->host) -
+ page_offset(wdata->pages[nr_pages - 1]),
+ (loff_t)PAGE_SIZE);
+ wdata->bytes = ((nr_pages - 1) * PAGE_SIZE) + wdata->tailsz;
+ wdata->pid = wdata->cfile->pid;
+
+ rc = adjust_credits(wdata->server, &wdata->credits, wdata->bytes);
+ if (rc)
+ return rc;
+
+ if (wdata->cfile->invalidHandle)
+ rc = -EAGAIN;
+ else
+ rc = wdata->server->ops->async_writev(wdata,
+ cifs_writedata_release);
+
+ return rc;
+}
+
+static int cifs_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+{
+ struct inode *inode = mapping->host;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct TCP_Server_Info *server;
+ bool done = false, scanned = false, range_whole = false;
+ pgoff_t end, index;
+ struct cifs_writedata *wdata;
+ struct cifsFileInfo *cfile = NULL;
+ int rc = 0;
+ int saved_rc = 0;
+ unsigned int xid;
+
+ /*
+ * If wsize is smaller than the page cache size, default to writing
+ * one page at a time via cifs_writepage
+ */
+ if (cifs_sb->ctx->wsize < PAGE_SIZE)
+ return generic_writepages(mapping, wbc);
+
+ xid = get_xid();
+ if (wbc->range_cyclic) {
+ index = mapping->writeback_index; /* Start from prev offset */
+ end = -1;
+ } else {
+ index = wbc->range_start >> PAGE_SHIFT;
+ end = wbc->range_end >> PAGE_SHIFT;
+ if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
+ range_whole = true;
+ scanned = true;
+ }
+ server = cifs_pick_channel(cifs_sb_master_tcon(cifs_sb)->ses);
+
+retry:
+ while (!done && index <= end) {
+ unsigned int i, nr_pages, found_pages, wsize;
+ pgoff_t next = 0, tofind, saved_index = index;
+ struct cifs_credits credits_on_stack;
+ struct cifs_credits *credits = &credits_on_stack;
+ int get_file_rc = 0;
+
+ if (cfile)
+ cifsFileInfo_put(cfile);
+
+ rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile);
+
+ /* in case of an error store it to return later */
+ if (rc)
+ get_file_rc = rc;
+
+ rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->wsize,
+ &wsize, credits);
+ if (rc != 0) {
+ done = true;
+ break;
+ }
+
+ tofind = min((wsize / PAGE_SIZE) - 1, end - index) + 1;
+
+ wdata = wdata_alloc_and_fillpages(tofind, mapping, end, &index,
+ &found_pages);
+ if (!wdata) {
+ rc = -ENOMEM;
+ done = true;
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+
+ if (found_pages == 0) {
+ kref_put(&wdata->refcount, cifs_writedata_release);
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+
+ nr_pages = wdata_prepare_pages(wdata, found_pages, mapping, wbc,
+ end, &index, &next, &done);
+
+ /* nothing to write? */
+ if (nr_pages == 0) {
+ kref_put(&wdata->refcount, cifs_writedata_release);
+ add_credits_and_wake_if(server, credits, 0);
+ continue;
+ }
+
+ wdata->credits = credits_on_stack;
+ wdata->cfile = cfile;
+ wdata->server = server;
+ cfile = NULL;
+
+ if (!wdata->cfile) {
+ cifs_dbg(VFS, "No writable handle in writepages rc=%d\n",
+ get_file_rc);
+ if (is_retryable_error(get_file_rc))
+ rc = get_file_rc;
+ else
+ rc = -EBADF;
+ } else
+ rc = wdata_send_pages(wdata, nr_pages, mapping, wbc);
+
+ for (i = 0; i < nr_pages; ++i)
+ unlock_page(wdata->pages[i]);
+
+ /* send failure -- clean up the mess */
+ if (rc != 0) {
+ add_credits_and_wake_if(server, &wdata->credits, 0);
+ for (i = 0; i < nr_pages; ++i) {
+ if (is_retryable_error(rc))
+ redirty_page_for_writepage(wbc,
+ wdata->pages[i]);
+ else
+ SetPageError(wdata->pages[i]);
+ end_page_writeback(wdata->pages[i]);
+ put_page(wdata->pages[i]);
+ }
+ if (!is_retryable_error(rc))
+ mapping_set_error(mapping, rc);
+ }
+ kref_put(&wdata->refcount, cifs_writedata_release);
+
+ if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) {
+ index = saved_index;
+ continue;
+ }
+
+ /* Return immediately if we received a signal during writing */
+ if (is_interrupt_error(rc)) {
+ done = true;
+ break;
+ }
+
+ if (rc != 0 && saved_rc == 0)
+ saved_rc = rc;
+
+ wbc->nr_to_write -= nr_pages;
+ if (wbc->nr_to_write <= 0)
+ done = true;
+
+ index = next;
+ }
+
+ if (!scanned && !done) {
+ /*
+ * We hit the last page and there is more work to be done: wrap
+ * back to the start of the file
+ */
+ scanned = true;
+ index = 0;
+ goto retry;
+ }
+
+ if (saved_rc != 0)
+ rc = saved_rc;
+
+ if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
+ mapping->writeback_index = index;
+
+ if (cfile)
+ cifsFileInfo_put(cfile);
+ free_xid(xid);
+ /* Indication to update ctime and mtime as close is deferred */
+ set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags);
+ return rc;
+}
+
+static int
+cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
+{
+ int rc;
+ unsigned int xid;
+
+ xid = get_xid();
+/* BB add check for wbc flags */
+ get_page(page);
+ if (!PageUptodate(page))
+ cifs_dbg(FYI, "ppw - page not up to date\n");
+
+ /*
+ * Set the "writeback" flag, and clear "dirty" in the radix tree.
+ *
+ * A writepage() implementation always needs to do either this,
+ * or re-dirty the page with "redirty_page_for_writepage()" in
+ * the case of a failure.
+ *
+ * Just unlocking the page will cause the radix tree tag-bits
+ * to fail to update with the state of the page correctly.
+ */
+ set_page_writeback(page);
+retry_write:
+ rc = cifs_partialpagewrite(page, 0, PAGE_SIZE);
+ if (is_retryable_error(rc)) {
+ if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN)
+ goto retry_write;
+ redirty_page_for_writepage(wbc, page);
+ } else if (rc != 0) {
+ SetPageError(page);
+ mapping_set_error(page->mapping, rc);
+ } else {
+ SetPageUptodate(page);
+ }
+ end_page_writeback(page);
+ put_page(page);
+ free_xid(xid);
+ return rc;
+}
+
+static int cifs_writepage(struct page *page, struct writeback_control *wbc)
+{
+ int rc = cifs_writepage_locked(page, wbc);
+ unlock_page(page);
+ return rc;
+}
+
+static int cifs_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ int rc;
+ struct inode *inode = mapping->host;
+ struct cifsFileInfo *cfile = file->private_data;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
+ __u32 pid;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+ pid = cfile->pid;
+ else
+ pid = current->tgid;
+
+ cifs_dbg(FYI, "write_end for page %p from pos %lld with %d bytes\n",
+ page, pos, copied);
+
+ if (PageChecked(page)) {
+ if (copied == len)
+ SetPageUptodate(page);
+ ClearPageChecked(page);
+ } else if (!PageUptodate(page) && copied == PAGE_SIZE)
+ SetPageUptodate(page);
+
+ if (!PageUptodate(page)) {
+ char *page_data;
+ unsigned offset = pos & (PAGE_SIZE - 1);
+ unsigned int xid;
+
+ xid = get_xid();
+ /* this is probably better than directly calling
+ partialpage_write since in this function the file handle is
+ known which we might as well leverage */
+ /* BB check if anything else missing out of ppw
+ such as updating last write time */
+ page_data = kmap(page);
+ rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
+ /* if (rc < 0) should we set writebehind rc? */
+ kunmap(page);
+
+ free_xid(xid);
+ } else {
+ rc = copied;
+ pos += copied;
+ set_page_dirty(page);
+ }
+
+ if (rc > 0) {
+ spin_lock(&inode->i_lock);
+ if (pos > inode->i_size) {
+ i_size_write(inode, pos);
+ inode->i_blocks = (512 - 1 + pos) >> 9;
+ }
+ spin_unlock(&inode->i_lock);
+ }
+
+ unlock_page(page);
+ put_page(page);
+ /* Indication to update ctime and mtime as close is deferred */
+ set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags);
+
+ return rc;
+}
+
+int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
+ int datasync)
+{
+ unsigned int xid;
+ int rc = 0;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct cifsFileInfo *smbfile = file->private_data;
+ struct inode *inode = file_inode(file);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+ rc = file_write_and_wait_range(file, start, end);
+ if (rc) {
+ trace_cifs_fsync_err(inode->i_ino, rc);
+ return rc;
+ }
+
+ xid = get_xid();
+
+ cifs_dbg(FYI, "Sync file - name: %pD datasync: 0x%x\n",
+ file, datasync);
+
+ if (!CIFS_CACHE_READ(CIFS_I(inode))) {
+ rc = cifs_zap_mapping(inode);
+ if (rc) {
+ cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc);
+ rc = 0; /* don't care about it in fsync */
+ }
+ }
+
+ tcon = tlink_tcon(smbfile->tlink);
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
+ server = tcon->ses->server;
+ if (server->ops->flush == NULL) {
+ rc = -ENOSYS;
+ goto strict_fsync_exit;
+ }
+
+ if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) {
+ smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY);
+ if (smbfile) {
+ rc = server->ops->flush(xid, tcon, &smbfile->fid);
+ cifsFileInfo_put(smbfile);
+ } else
+ cifs_dbg(FYI, "ignore fsync for file not open for write\n");
+ } else
+ rc = server->ops->flush(xid, tcon, &smbfile->fid);
+ }
+
+strict_fsync_exit:
+ free_xid(xid);
+ return rc;
+}
+
+int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+ unsigned int xid;
+ int rc = 0;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct cifsFileInfo *smbfile = file->private_data;
+ struct inode *inode = file_inode(file);
+ struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
+
+ rc = file_write_and_wait_range(file, start, end);
+ if (rc) {
+ trace_cifs_fsync_err(file_inode(file)->i_ino, rc);
+ return rc;
+ }
+
+ xid = get_xid();
+
+ cifs_dbg(FYI, "Sync file - name: %pD datasync: 0x%x\n",
+ file, datasync);
+
+ tcon = tlink_tcon(smbfile->tlink);
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
+ server = tcon->ses->server;
+ if (server->ops->flush == NULL) {
+ rc = -ENOSYS;
+ goto fsync_exit;
+ }
+
+ if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) {
+ smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY);
+ if (smbfile) {
+ rc = server->ops->flush(xid, tcon, &smbfile->fid);
+ cifsFileInfo_put(smbfile);
+ } else
+ cifs_dbg(FYI, "ignore fsync for file not open for write\n");
+ } else
+ rc = server->ops->flush(xid, tcon, &smbfile->fid);
+ }
+
+fsync_exit:
+ free_xid(xid);
+ return rc;
+}
+
+/*
+ * As file closes, flush all cached write data for this inode checking
+ * for write behind errors.
+ */
+int cifs_flush(struct file *file, fl_owner_t id)
+{
+ struct inode *inode = file_inode(file);
+ int rc = 0;
+
+ if (file->f_mode & FMODE_WRITE)
+ rc = filemap_write_and_wait(inode->i_mapping);
+
+ cifs_dbg(FYI, "Flush inode %p file %p rc %d\n", inode, file, rc);
+ if (rc) {
+ /* get more nuanced writeback errors */
+ rc = filemap_check_wb_err(file->f_mapping, 0);
+ trace_cifs_flush_err(inode->i_ino, rc);
+ }
+ return rc;
+}
+
+static int
+cifs_write_allocate_pages(struct page **pages, unsigned long num_pages)
+{
+ int rc = 0;
+ unsigned long i;
+
+ for (i = 0; i < num_pages; i++) {
+ pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
+ if (!pages[i]) {
+ /*
+ * save number of pages we have already allocated and
+ * return with ENOMEM error
+ */
+ num_pages = i;
+ rc = -ENOMEM;
+ break;
+ }
+ }
+
+ if (rc) {
+ for (i = 0; i < num_pages; i++)
+ put_page(pages[i]);
+ }
+ return rc;
+}
+
+static inline
+size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
+{
+ size_t num_pages;
+ size_t clen;
+
+ clen = min_t(const size_t, len, wsize);
+ num_pages = DIV_ROUND_UP(clen, PAGE_SIZE);
+
+ if (cur_len)
+ *cur_len = clen;
+
+ return num_pages;
+}
+
+static void
+cifs_uncached_writedata_release(struct kref *refcount)
+{
+ int i;
+ struct cifs_writedata *wdata = container_of(refcount,
+ struct cifs_writedata, refcount);
+
+ kref_put(&wdata->ctx->refcount, cifs_aio_ctx_release);
+ for (i = 0; i < wdata->nr_pages; i++)
+ put_page(wdata->pages[i]);
+ cifs_writedata_release(refcount);
+}
+
+static void collect_uncached_write_data(struct cifs_aio_ctx *ctx);
+
+static void
+cifs_uncached_writev_complete(struct work_struct *work)
+{
+ struct cifs_writedata *wdata = container_of(work,
+ struct cifs_writedata, work);
+ struct inode *inode = d_inode(wdata->cfile->dentry);
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+
+ spin_lock(&inode->i_lock);
+ cifs_update_eof(cifsi, wdata->offset, wdata->bytes);
+ if (cifsi->server_eof > inode->i_size)
+ i_size_write(inode, cifsi->server_eof);
+ spin_unlock(&inode->i_lock);
+
+ complete(&wdata->done);
+ collect_uncached_write_data(wdata->ctx);
+ /* the below call can possibly free the last ref to aio ctx */
+ kref_put(&wdata->refcount, cifs_uncached_writedata_release);
+}
+
+static int
+wdata_fill_from_iovec(struct cifs_writedata *wdata, struct iov_iter *from,
+ size_t *len, unsigned long *num_pages)
+{
+ size_t save_len, copied, bytes, cur_len = *len;
+ unsigned long i, nr_pages = *num_pages;
+
+ save_len = cur_len;
+ for (i = 0; i < nr_pages; i++) {
+ bytes = min_t(const size_t, cur_len, PAGE_SIZE);
+ copied = copy_page_from_iter(wdata->pages[i], 0, bytes, from);
+ cur_len -= copied;
+ /*
+ * If we didn't copy as much as we expected, then that
+ * may mean we trod into an unmapped area. Stop copying
+ * at that point. On the next pass through the big
+ * loop, we'll likely end up getting a zero-length
+ * write and bailing out of it.
+ */
+ if (copied < bytes)
+ break;
+ }
+ cur_len = save_len - cur_len;
+ *len = cur_len;
+
+ /*
+ * If we have no data to send, then that probably means that
+ * the copy above failed altogether. That's most likely because
+ * the address in the iovec was bogus. Return -EFAULT and let
+ * the caller free anything we allocated and bail out.
+ */
+ if (!cur_len)
+ return -EFAULT;
+
+ /*
+ * i + 1 now represents the number of pages we actually used in
+ * the copy phase above.
+ */
+ *num_pages = i + 1;
+ return 0;
+}
+
+static int
+cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list,
+ struct cifs_aio_ctx *ctx)
+{
+ unsigned int wsize;
+ struct cifs_credits credits;
+ int rc;
+ struct TCP_Server_Info *server = wdata->server;
+
+ do {
+ if (wdata->cfile->invalidHandle) {
+ rc = cifs_reopen_file(wdata->cfile, false);
+ if (rc == -EAGAIN)
+ continue;
+ else if (rc)
+ break;
+ }
+
+
+ /*
+ * Wait for credits to resend this wdata.
+ * Note: we are attempting to resend the whole wdata not in
+ * segments
+ */
+ do {
+ rc = server->ops->wait_mtu_credits(server, wdata->bytes,
+ &wsize, &credits);
+ if (rc)
+ goto fail;
+
+ if (wsize < wdata->bytes) {
+ add_credits_and_wake_if(server, &credits, 0);
+ msleep(1000);
+ }
+ } while (wsize < wdata->bytes);
+ wdata->credits = credits;
+
+ rc = adjust_credits(server, &wdata->credits, wdata->bytes);
+
+ if (!rc) {
+ if (wdata->cfile->invalidHandle)
+ rc = -EAGAIN;
+ else {
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ if (wdata->mr) {
+ wdata->mr->need_invalidate = true;
+ smbd_deregister_mr(wdata->mr);
+ wdata->mr = NULL;
+ }
+#endif
+ rc = server->ops->async_writev(wdata,
+ cifs_uncached_writedata_release);
+ }
+ }
+
+ /* If the write was successfully sent, we are done */
+ if (!rc) {
+ list_add_tail(&wdata->list, wdata_list);
+ return 0;
+ }
+
+ /* Roll back credits and retry if needed */
+ add_credits_and_wake_if(server, &wdata->credits, 0);
+ } while (rc == -EAGAIN);
+
+fail:
+ kref_put(&wdata->refcount, cifs_uncached_writedata_release);
+ return rc;
+}
+
+static int
+cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
+ struct cifsFileInfo *open_file,
+ struct cifs_sb_info *cifs_sb, struct list_head *wdata_list,
+ struct cifs_aio_ctx *ctx)
+{
+ int rc = 0;
+ size_t cur_len;
+ unsigned long nr_pages, num_pages, i;
+ struct cifs_writedata *wdata;
+ struct iov_iter saved_from = *from;
+ loff_t saved_offset = offset;
+ pid_t pid;
+ struct TCP_Server_Info *server;
+ struct page **pagevec;
+ size_t start;
+ unsigned int xid;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+ pid = open_file->pid;
+ else
+ pid = current->tgid;
+
+ server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses);
+ xid = get_xid();
+
+ do {
+ unsigned int wsize;
+ struct cifs_credits credits_on_stack;
+ struct cifs_credits *credits = &credits_on_stack;
+
+ if (open_file->invalidHandle) {
+ rc = cifs_reopen_file(open_file, false);
+ if (rc == -EAGAIN)
+ continue;
+ else if (rc)
+ break;
+ }
+
+ rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->wsize,
+ &wsize, credits);
+ if (rc)
+ break;
+
+ cur_len = min_t(const size_t, len, wsize);
+
+ if (ctx->direct_io) {
+ ssize_t result;
+
+ result = iov_iter_get_pages_alloc2(
+ from, &pagevec, cur_len, &start);
+ if (result < 0) {
+ cifs_dbg(VFS,
+ "direct_writev couldn't get user pages (rc=%zd) iter type %d iov_offset %zd count %zd\n",
+ result, iov_iter_type(from),
+ from->iov_offset, from->count);
+ dump_stack();
+
+ rc = result;
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+ cur_len = (size_t)result;
+
+ nr_pages =
+ (cur_len + start + PAGE_SIZE - 1) / PAGE_SIZE;
+
+ wdata = cifs_writedata_direct_alloc(pagevec,
+ cifs_uncached_writev_complete);
+ if (!wdata) {
+ rc = -ENOMEM;
+ for (i = 0; i < nr_pages; i++)
+ put_page(pagevec[i]);
+ kvfree(pagevec);
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+
+
+ wdata->page_offset = start;
+ wdata->tailsz =
+ nr_pages > 1 ?
+ cur_len - (PAGE_SIZE - start) -
+ (nr_pages - 2) * PAGE_SIZE :
+ cur_len;
+ } else {
+ nr_pages = get_numpages(wsize, len, &cur_len);
+ wdata = cifs_writedata_alloc(nr_pages,
+ cifs_uncached_writev_complete);
+ if (!wdata) {
+ rc = -ENOMEM;
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+
+ rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
+ if (rc) {
+ kvfree(wdata->pages);
+ kfree(wdata);
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+
+ num_pages = nr_pages;
+ rc = wdata_fill_from_iovec(
+ wdata, from, &cur_len, &num_pages);
+ if (rc) {
+ for (i = 0; i < nr_pages; i++)
+ put_page(wdata->pages[i]);
+ kvfree(wdata->pages);
+ kfree(wdata);
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+
+ /*
+ * Bring nr_pages down to the number of pages we
+ * actually used, and free any pages that we didn't use.
+ */
+ for ( ; nr_pages > num_pages; nr_pages--)
+ put_page(wdata->pages[nr_pages - 1]);
+
+ wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
+ }
+
+ wdata->sync_mode = WB_SYNC_ALL;
+ wdata->nr_pages = nr_pages;
+ wdata->offset = (__u64)offset;
+ wdata->cfile = cifsFileInfo_get(open_file);
+ wdata->server = server;
+ wdata->pid = pid;
+ wdata->bytes = cur_len;
+ wdata->pagesz = PAGE_SIZE;
+ wdata->credits = credits_on_stack;
+ wdata->ctx = ctx;
+ kref_get(&ctx->refcount);
+
+ rc = adjust_credits(server, &wdata->credits, wdata->bytes);
+
+ if (!rc) {
+ if (wdata->cfile->invalidHandle)
+ rc = -EAGAIN;
+ else
+ rc = server->ops->async_writev(wdata,
+ cifs_uncached_writedata_release);
+ }
+
+ if (rc) {
+ add_credits_and_wake_if(server, &wdata->credits, 0);
+ kref_put(&wdata->refcount,
+ cifs_uncached_writedata_release);
+ if (rc == -EAGAIN) {
+ *from = saved_from;
+ iov_iter_advance(from, offset - saved_offset);
+ continue;
+ }
+ break;
+ }
+
+ list_add_tail(&wdata->list, wdata_list);
+ offset += cur_len;
+ len -= cur_len;
+ } while (len > 0);
+
+ free_xid(xid);
+ return rc;
+}
+
+static void collect_uncached_write_data(struct cifs_aio_ctx *ctx)
+{
+ struct cifs_writedata *wdata, *tmp;
+ struct cifs_tcon *tcon;
+ struct cifs_sb_info *cifs_sb;
+ struct dentry *dentry = ctx->cfile->dentry;
+ ssize_t rc;
+
+ tcon = tlink_tcon(ctx->cfile->tlink);
+ cifs_sb = CIFS_SB(dentry->d_sb);
+
+ mutex_lock(&ctx->aio_mutex);
+
+ if (list_empty(&ctx->list)) {
+ mutex_unlock(&ctx->aio_mutex);
+ return;
+ }
+
+ rc = ctx->rc;
+ /*
+ * Wait for and collect replies for any successful sends in order of
+ * increasing offset. Once an error is hit, then return without waiting
+ * for any more replies.
+ */
+restart_loop:
+ list_for_each_entry_safe(wdata, tmp, &ctx->list, list) {
+ if (!rc) {
+ if (!try_wait_for_completion(&wdata->done)) {
+ mutex_unlock(&ctx->aio_mutex);
+ return;
+ }
+
+ if (wdata->result)
+ rc = wdata->result;
+ else
+ ctx->total_len += wdata->bytes;
+
+ /* resend call if it's a retryable error */
+ if (rc == -EAGAIN) {
+ struct list_head tmp_list;
+ struct iov_iter tmp_from = ctx->iter;
+
+ INIT_LIST_HEAD(&tmp_list);
+ list_del_init(&wdata->list);
+
+ if (ctx->direct_io)
+ rc = cifs_resend_wdata(
+ wdata, &tmp_list, ctx);
+ else {
+ iov_iter_advance(&tmp_from,
+ wdata->offset - ctx->pos);
+
+ rc = cifs_write_from_iter(wdata->offset,
+ wdata->bytes, &tmp_from,
+ ctx->cfile, cifs_sb, &tmp_list,
+ ctx);
+
+ kref_put(&wdata->refcount,
+ cifs_uncached_writedata_release);
+ }
+
+ list_splice(&tmp_list, &ctx->list);
+ goto restart_loop;
+ }
+ }
+ list_del_init(&wdata->list);
+ kref_put(&wdata->refcount, cifs_uncached_writedata_release);
+ }
+
+ cifs_stats_bytes_written(tcon, ctx->total_len);
+ set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(dentry->d_inode)->flags);
+
+ ctx->rc = (rc == 0) ? ctx->total_len : rc;
+
+ mutex_unlock(&ctx->aio_mutex);
+
+ if (ctx->iocb && ctx->iocb->ki_complete)
+ ctx->iocb->ki_complete(ctx->iocb, ctx->rc);
+ else
+ complete(&ctx->done);
+}
+
+static ssize_t __cifs_writev(
+ struct kiocb *iocb, struct iov_iter *from, bool direct)
+{
+ struct file *file = iocb->ki_filp;
+ ssize_t total_written = 0;
+ struct cifsFileInfo *cfile;
+ struct cifs_tcon *tcon;
+ struct cifs_sb_info *cifs_sb;
+ struct cifs_aio_ctx *ctx;
+ struct iov_iter saved_from = *from;
+ size_t len = iov_iter_count(from);
+ int rc;
+
+ /*
+ * iov_iter_get_pages_alloc doesn't work with ITER_KVEC.
+ * In this case, fall back to non-direct write function.
+ * this could be improved by getting pages directly in ITER_KVEC
+ */
+ if (direct && iov_iter_is_kvec(from)) {
+ cifs_dbg(FYI, "use non-direct cifs_writev for kvec I/O\n");
+ direct = false;
+ }
+
+ rc = generic_write_checks(iocb, from);
+ if (rc <= 0)
+ return rc;
+
+ cifs_sb = CIFS_FILE_SB(file);
+ cfile = file->private_data;
+ tcon = tlink_tcon(cfile->tlink);
+
+ if (!tcon->ses->server->ops->async_writev)
+ return -ENOSYS;
+
+ ctx = cifs_aio_ctx_alloc();
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->cfile = cifsFileInfo_get(cfile);
+
+ if (!is_sync_kiocb(iocb))
+ ctx->iocb = iocb;
+
+ ctx->pos = iocb->ki_pos;
+
+ if (direct) {
+ ctx->direct_io = true;
+ ctx->iter = *from;
+ ctx->len = len;
+ } else {
+ rc = setup_aio_ctx_iter(ctx, from, ITER_SOURCE);
+ if (rc) {
+ kref_put(&ctx->refcount, cifs_aio_ctx_release);
+ return rc;
+ }
+ }
+
+ /* grab a lock here due to read response handlers can access ctx */
+ mutex_lock(&ctx->aio_mutex);
+
+ rc = cifs_write_from_iter(iocb->ki_pos, ctx->len, &saved_from,
+ cfile, cifs_sb, &ctx->list, ctx);
+
+ /*
+ * If at least one write was successfully sent, then discard any rc
+ * value from the later writes. If the other write succeeds, then
+ * we'll end up returning whatever was written. If it fails, then
+ * we'll get a new rc value from that.
+ */
+ if (!list_empty(&ctx->list))
+ rc = 0;
+
+ mutex_unlock(&ctx->aio_mutex);
+
+ if (rc) {
+ kref_put(&ctx->refcount, cifs_aio_ctx_release);
+ return rc;
+ }
+
+ if (!is_sync_kiocb(iocb)) {
+ kref_put(&ctx->refcount, cifs_aio_ctx_release);
+ return -EIOCBQUEUED;
+ }
+
+ rc = wait_for_completion_killable(&ctx->done);
+ if (rc) {
+ mutex_lock(&ctx->aio_mutex);
+ ctx->rc = rc = -EINTR;
+ total_written = ctx->total_len;
+ mutex_unlock(&ctx->aio_mutex);
+ } else {
+ rc = ctx->rc;
+ total_written = ctx->total_len;
+ }
+
+ kref_put(&ctx->refcount, cifs_aio_ctx_release);
+
+ if (unlikely(!total_written))
+ return rc;
+
+ iocb->ki_pos += total_written;
+ return total_written;
+}
+
+ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from)
+{
+ struct file *file = iocb->ki_filp;
+
+ cifs_revalidate_mapping(file->f_inode);
+ return __cifs_writev(iocb, from, true);
+}
+
+ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
+{
+ return __cifs_writev(iocb, from, false);
+}
+
+static ssize_t
+cifs_writev(struct kiocb *iocb, struct iov_iter *from)
+{
+ struct file *file = iocb->ki_filp;
+ struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
+ struct inode *inode = file->f_mapping->host;
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
+ ssize_t rc;
+
+ inode_lock(inode);
+ /*
+ * We need to hold the sem to be sure nobody modifies lock list
+ * with a brlock that prevents writing.
+ */
+ down_read(&cinode->lock_sem);
+
+ rc = generic_write_checks(iocb, from);
+ if (rc <= 0)
+ goto out;
+
+ if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from),
+ server->vals->exclusive_lock_type, 0,
+ NULL, CIFS_WRITE_OP))
+ rc = __generic_file_write_iter(iocb, from);
+ else
+ rc = -EACCES;
+out:
+ up_read(&cinode->lock_sem);
+ inode_unlock(inode);
+
+ if (rc > 0)
+ rc = generic_write_sync(iocb, rc);
+ return rc;
+}
+
+ssize_t
+cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
+{
+ struct inode *inode = file_inode(iocb->ki_filp);
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifsFileInfo *cfile = (struct cifsFileInfo *)
+ iocb->ki_filp->private_data;
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ ssize_t written;
+
+ written = cifs_get_writer(cinode);
+ if (written)
+ return written;
+
+ if (CIFS_CACHE_WRITE(cinode)) {
+ if (cap_unix(tcon->ses) &&
+ (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))
+ && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
+ written = generic_file_write_iter(iocb, from);
+ goto out;
+ }
+ written = cifs_writev(iocb, from);
+ goto out;
+ }
+ /*
+ * For non-oplocked files in strict cache mode we need to write the data
+ * to the server exactly from the pos to pos+len-1 rather than flush all
+ * affected pages because it may cause a error with mandatory locks on
+ * these pages but not on the region from pos to ppos+len-1.
+ */
+ written = cifs_user_writev(iocb, from);
+ if (CIFS_CACHE_READ(cinode)) {
+ /*
+ * We have read level caching and we have just sent a write
+ * request to the server thus making data in the cache stale.
+ * Zap the cache and set oplock/lease level to NONE to avoid
+ * reading stale data from the cache. All subsequent read
+ * operations will read new data from the server.
+ */
+ cifs_zap_mapping(inode);
+ cifs_dbg(FYI, "Set Oplock/Lease to NONE for inode=%p after write\n",
+ inode);
+ cinode->oplock = 0;
+ }
+out:
+ cifs_put_writer(cinode);
+ return written;
+}
+
+static struct cifs_readdata *
+cifs_readdata_direct_alloc(struct page **pages, work_func_t complete)
+{
+ struct cifs_readdata *rdata;
+
+ rdata = kzalloc(sizeof(*rdata), GFP_KERNEL);
+ if (rdata != NULL) {
+ rdata->pages = pages;
+ kref_init(&rdata->refcount);
+ INIT_LIST_HEAD(&rdata->list);
+ init_completion(&rdata->done);
+ INIT_WORK(&rdata->work, complete);
+ }
+
+ return rdata;
+}
+
+static struct cifs_readdata *
+cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
+{
+ struct page **pages =
+ kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
+ struct cifs_readdata *ret = NULL;
+
+ if (pages) {
+ ret = cifs_readdata_direct_alloc(pages, complete);
+ if (!ret)
+ kfree(pages);
+ }
+
+ return ret;
+}
+
+void
+cifs_readdata_release(struct kref *refcount)
+{
+ struct cifs_readdata *rdata = container_of(refcount,
+ struct cifs_readdata, refcount);
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ if (rdata->mr) {
+ smbd_deregister_mr(rdata->mr);
+ rdata->mr = NULL;
+ }
+#endif
+ if (rdata->cfile)
+ cifsFileInfo_put(rdata->cfile);
+
+ kvfree(rdata->pages);
+ kfree(rdata);
+}
+
+static int
+cifs_read_allocate_pages(struct cifs_readdata *rdata, unsigned int nr_pages)
+{
+ int rc = 0;
+ struct page *page;
+ unsigned int i;
+
+ for (i = 0; i < nr_pages; i++) {
+ page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
+ if (!page) {
+ rc = -ENOMEM;
+ break;
+ }
+ rdata->pages[i] = page;
+ }
+
+ if (rc) {
+ unsigned int nr_page_failed = i;
+
+ for (i = 0; i < nr_page_failed; i++) {
+ put_page(rdata->pages[i]);
+ rdata->pages[i] = NULL;
+ }
+ }
+ return rc;
+}
+
+static void
+cifs_uncached_readdata_release(struct kref *refcount)
+{
+ struct cifs_readdata *rdata = container_of(refcount,
+ struct cifs_readdata, refcount);
+ unsigned int i;
+
+ kref_put(&rdata->ctx->refcount, cifs_aio_ctx_release);
+ for (i = 0; i < rdata->nr_pages; i++) {
+ put_page(rdata->pages[i]);
+ }
+ cifs_readdata_release(refcount);
+}
+
+/**
+ * cifs_readdata_to_iov - copy data from pages in response to an iovec
+ * @rdata: the readdata response with list of pages holding data
+ * @iter: destination for our data
+ *
+ * This function copies data from a list of pages in a readdata response into
+ * an array of iovecs. It will first calculate where the data should go
+ * based on the info in the readdata and then copy the data into that spot.
+ */
+static int
+cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter)
+{
+ size_t remaining = rdata->got_bytes;
+ unsigned int i;
+
+ for (i = 0; i < rdata->nr_pages; i++) {
+ struct page *page = rdata->pages[i];
+ size_t copy = min_t(size_t, remaining, PAGE_SIZE);
+ size_t written;
+
+ if (unlikely(iov_iter_is_pipe(iter))) {
+ void *addr = kmap_atomic(page);
+
+ written = copy_to_iter(addr, copy, iter);
+ kunmap_atomic(addr);
+ } else
+ written = copy_page_to_iter(page, 0, copy, iter);
+ remaining -= written;
+ if (written < copy && iov_iter_count(iter) > 0)
+ break;
+ }
+ return remaining ? -EFAULT : 0;
+}
+
+static void collect_uncached_read_data(struct cifs_aio_ctx *ctx);
+
+static void
+cifs_uncached_readv_complete(struct work_struct *work)
+{
+ struct cifs_readdata *rdata = container_of(work,
+ struct cifs_readdata, work);
+
+ complete(&rdata->done);
+ collect_uncached_read_data(rdata->ctx);
+ /* the below call can possibly free the last ref to aio ctx */
+ kref_put(&rdata->refcount, cifs_uncached_readdata_release);
+}
+
+static int
+uncached_fill_pages(struct TCP_Server_Info *server,
+ struct cifs_readdata *rdata, struct iov_iter *iter,
+ unsigned int len)
+{
+ int result = 0;
+ unsigned int i;
+ unsigned int nr_pages = rdata->nr_pages;
+ unsigned int page_offset = rdata->page_offset;
+
+ rdata->got_bytes = 0;
+ rdata->tailsz = PAGE_SIZE;
+ for (i = 0; i < nr_pages; i++) {
+ struct page *page = rdata->pages[i];
+ size_t n;
+ unsigned int segment_size = rdata->pagesz;
+
+ if (i == 0)
+ segment_size -= page_offset;
+ else
+ page_offset = 0;
+
+
+ if (len <= 0) {
+ /* no need to hold page hostage */
+ rdata->pages[i] = NULL;
+ rdata->nr_pages--;
+ put_page(page);
+ continue;
+ }
+
+ n = len;
+ if (len >= segment_size)
+ /* enough data to fill the page */
+ n = segment_size;
+ else
+ rdata->tailsz = len;
+ len -= n;
+
+ if (iter)
+ result = copy_page_from_iter(
+ page, page_offset, n, iter);
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ else if (rdata->mr)
+ result = n;
+#endif
+ else
+ result = cifs_read_page_from_socket(
+ server, page, page_offset, n);
+ if (result < 0)
+ break;
+
+ rdata->got_bytes += result;
+ }
+
+ return result != -ECONNABORTED && rdata->got_bytes > 0 ?
+ rdata->got_bytes : result;
+}
+
+static int
+cifs_uncached_read_into_pages(struct TCP_Server_Info *server,
+ struct cifs_readdata *rdata, unsigned int len)
+{
+ return uncached_fill_pages(server, rdata, NULL, len);
+}
+
+static int
+cifs_uncached_copy_into_pages(struct TCP_Server_Info *server,
+ struct cifs_readdata *rdata,
+ struct iov_iter *iter)
+{
+ return uncached_fill_pages(server, rdata, iter, iter->count);
+}
+
+static int cifs_resend_rdata(struct cifs_readdata *rdata,
+ struct list_head *rdata_list,
+ struct cifs_aio_ctx *ctx)
+{
+ unsigned int rsize;
+ struct cifs_credits credits;
+ int rc;
+ struct TCP_Server_Info *server;
+
+ /* XXX: should we pick a new channel here? */
+ server = rdata->server;
+
+ do {
+ if (rdata->cfile->invalidHandle) {
+ rc = cifs_reopen_file(rdata->cfile, true);
+ if (rc == -EAGAIN)
+ continue;
+ else if (rc)
+ break;
+ }
+
+ /*
+ * Wait for credits to resend this rdata.
+ * Note: we are attempting to resend the whole rdata not in
+ * segments
+ */
+ do {
+ rc = server->ops->wait_mtu_credits(server, rdata->bytes,
+ &rsize, &credits);
+
+ if (rc)
+ goto fail;
+
+ if (rsize < rdata->bytes) {
+ add_credits_and_wake_if(server, &credits, 0);
+ msleep(1000);
+ }
+ } while (rsize < rdata->bytes);
+ rdata->credits = credits;
+
+ rc = adjust_credits(server, &rdata->credits, rdata->bytes);
+ if (!rc) {
+ if (rdata->cfile->invalidHandle)
+ rc = -EAGAIN;
+ else {
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ if (rdata->mr) {
+ rdata->mr->need_invalidate = true;
+ smbd_deregister_mr(rdata->mr);
+ rdata->mr = NULL;
+ }
+#endif
+ rc = server->ops->async_readv(rdata);
+ }
+ }
+
+ /* If the read was successfully sent, we are done */
+ if (!rc) {
+ /* Add to aio pending list */
+ list_add_tail(&rdata->list, rdata_list);
+ return 0;
+ }
+
+ /* Roll back credits and retry if needed */
+ add_credits_and_wake_if(server, &rdata->credits, 0);
+ } while (rc == -EAGAIN);
+
+fail:
+ kref_put(&rdata->refcount, cifs_uncached_readdata_release);
+ return rc;
+}
+
+static int
+cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
+ struct cifs_sb_info *cifs_sb, struct list_head *rdata_list,
+ struct cifs_aio_ctx *ctx)
+{
+ struct cifs_readdata *rdata;
+ unsigned int npages, rsize;
+ struct cifs_credits credits_on_stack;
+ struct cifs_credits *credits = &credits_on_stack;
+ size_t cur_len;
+ int rc;
+ pid_t pid;
+ struct TCP_Server_Info *server;
+ struct page **pagevec;
+ size_t start;
+ struct iov_iter direct_iov = ctx->iter;
+
+ server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses);
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+ pid = open_file->pid;
+ else
+ pid = current->tgid;
+
+ if (ctx->direct_io)
+ iov_iter_advance(&direct_iov, offset - ctx->pos);
+
+ do {
+ if (open_file->invalidHandle) {
+ rc = cifs_reopen_file(open_file, true);
+ if (rc == -EAGAIN)
+ continue;
+ else if (rc)
+ break;
+ }
+
+ if (cifs_sb->ctx->rsize == 0)
+ cifs_sb->ctx->rsize =
+ server->ops->negotiate_rsize(tlink_tcon(open_file->tlink),
+ cifs_sb->ctx);
+
+ rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
+ &rsize, credits);
+ if (rc)
+ break;
+
+ cur_len = min_t(const size_t, len, rsize);
+
+ if (ctx->direct_io) {
+ ssize_t result;
+
+ result = iov_iter_get_pages_alloc2(
+ &direct_iov, &pagevec,
+ cur_len, &start);
+ if (result < 0) {
+ cifs_dbg(VFS,
+ "Couldn't get user pages (rc=%zd) iter type %d iov_offset %zd count %zd\n",
+ result, iov_iter_type(&direct_iov),
+ direct_iov.iov_offset,
+ direct_iov.count);
+ dump_stack();
+
+ rc = result;
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+ cur_len = (size_t)result;
+
+ rdata = cifs_readdata_direct_alloc(
+ pagevec, cifs_uncached_readv_complete);
+ if (!rdata) {
+ add_credits_and_wake_if(server, credits, 0);
+ rc = -ENOMEM;
+ break;
+ }
+
+ npages = (cur_len + start + PAGE_SIZE-1) / PAGE_SIZE;
+ rdata->page_offset = start;
+ rdata->tailsz = npages > 1 ?
+ cur_len-(PAGE_SIZE-start)-(npages-2)*PAGE_SIZE :
+ cur_len;
+
+ } else {
+
+ npages = DIV_ROUND_UP(cur_len, PAGE_SIZE);
+ /* allocate a readdata struct */
+ rdata = cifs_readdata_alloc(npages,
+ cifs_uncached_readv_complete);
+ if (!rdata) {
+ add_credits_and_wake_if(server, credits, 0);
+ rc = -ENOMEM;
+ break;
+ }
+
+ rc = cifs_read_allocate_pages(rdata, npages);
+ if (rc) {
+ kvfree(rdata->pages);
+ kfree(rdata);
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+
+ rdata->tailsz = PAGE_SIZE;
+ }
+
+ rdata->server = server;
+ rdata->cfile = cifsFileInfo_get(open_file);
+ rdata->nr_pages = npages;
+ rdata->offset = offset;
+ rdata->bytes = cur_len;
+ rdata->pid = pid;
+ rdata->pagesz = PAGE_SIZE;
+ rdata->read_into_pages = cifs_uncached_read_into_pages;
+ rdata->copy_into_pages = cifs_uncached_copy_into_pages;
+ rdata->credits = credits_on_stack;
+ rdata->ctx = ctx;
+ kref_get(&ctx->refcount);
+
+ rc = adjust_credits(server, &rdata->credits, rdata->bytes);
+
+ if (!rc) {
+ if (rdata->cfile->invalidHandle)
+ rc = -EAGAIN;
+ else
+ rc = server->ops->async_readv(rdata);
+ }
+
+ if (rc) {
+ add_credits_and_wake_if(server, &rdata->credits, 0);
+ kref_put(&rdata->refcount,
+ cifs_uncached_readdata_release);
+ if (rc == -EAGAIN) {
+ iov_iter_revert(&direct_iov, cur_len);
+ continue;
+ }
+ break;
+ }
+
+ list_add_tail(&rdata->list, rdata_list);
+ offset += cur_len;
+ len -= cur_len;
+ } while (len > 0);
+
+ return rc;
+}
+
+static void
+collect_uncached_read_data(struct cifs_aio_ctx *ctx)
+{
+ struct cifs_readdata *rdata, *tmp;
+ struct iov_iter *to = &ctx->iter;
+ struct cifs_sb_info *cifs_sb;
+ int rc;
+
+ cifs_sb = CIFS_SB(ctx->cfile->dentry->d_sb);
+
+ mutex_lock(&ctx->aio_mutex);
+
+ if (list_empty(&ctx->list)) {
+ mutex_unlock(&ctx->aio_mutex);
+ return;
+ }
+
+ rc = ctx->rc;
+ /* the loop below should proceed in the order of increasing offsets */
+again:
+ list_for_each_entry_safe(rdata, tmp, &ctx->list, list) {
+ if (!rc) {
+ if (!try_wait_for_completion(&rdata->done)) {
+ mutex_unlock(&ctx->aio_mutex);
+ return;
+ }
+
+ if (rdata->result == -EAGAIN) {
+ /* resend call if it's a retryable error */
+ struct list_head tmp_list;
+ unsigned int got_bytes = rdata->got_bytes;
+
+ list_del_init(&rdata->list);
+ INIT_LIST_HEAD(&tmp_list);
+
+ /*
+ * Got a part of data and then reconnect has
+ * happened -- fill the buffer and continue
+ * reading.
+ */
+ if (got_bytes && got_bytes < rdata->bytes) {
+ rc = 0;
+ if (!ctx->direct_io)
+ rc = cifs_readdata_to_iov(rdata, to);
+ if (rc) {
+ kref_put(&rdata->refcount,
+ cifs_uncached_readdata_release);
+ continue;
+ }
+ }
+
+ if (ctx->direct_io) {
+ /*
+ * Re-use rdata as this is a
+ * direct I/O
+ */
+ rc = cifs_resend_rdata(
+ rdata,
+ &tmp_list, ctx);
+ } else {
+ rc = cifs_send_async_read(
+ rdata->offset + got_bytes,
+ rdata->bytes - got_bytes,
+ rdata->cfile, cifs_sb,
+ &tmp_list, ctx);
+
+ kref_put(&rdata->refcount,
+ cifs_uncached_readdata_release);
+ }
+
+ list_splice(&tmp_list, &ctx->list);
+
+ goto again;
+ } else if (rdata->result)
+ rc = rdata->result;
+ else if (!ctx->direct_io)
+ rc = cifs_readdata_to_iov(rdata, to);
+
+ /* if there was a short read -- discard anything left */
+ if (rdata->got_bytes && rdata->got_bytes < rdata->bytes)
+ rc = -ENODATA;
+
+ ctx->total_len += rdata->got_bytes;
+ }
+ list_del_init(&rdata->list);
+ kref_put(&rdata->refcount, cifs_uncached_readdata_release);
+ }
+
+ if (!ctx->direct_io)
+ ctx->total_len = ctx->len - iov_iter_count(to);
+
+ /* mask nodata case */
+ if (rc == -ENODATA)
+ rc = 0;
+
+ ctx->rc = (rc == 0) ? (ssize_t)ctx->total_len : rc;
+
+ mutex_unlock(&ctx->aio_mutex);
+
+ if (ctx->iocb && ctx->iocb->ki_complete)
+ ctx->iocb->ki_complete(ctx->iocb, ctx->rc);
+ else
+ complete(&ctx->done);
+}
+
+static ssize_t __cifs_readv(
+ struct kiocb *iocb, struct iov_iter *to, bool direct)
+{
+ size_t len;
+ struct file *file = iocb->ki_filp;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsFileInfo *cfile;
+ struct cifs_tcon *tcon;
+ ssize_t rc, total_read = 0;
+ loff_t offset = iocb->ki_pos;
+ struct cifs_aio_ctx *ctx;
+
+ /*
+ * iov_iter_get_pages_alloc() doesn't work with ITER_KVEC,
+ * fall back to data copy read path
+ * this could be improved by getting pages directly in ITER_KVEC
+ */
+ if (direct && iov_iter_is_kvec(to)) {
+ cifs_dbg(FYI, "use non-direct cifs_user_readv for kvec I/O\n");
+ direct = false;
+ }
+
+ len = iov_iter_count(to);
+ if (!len)
+ return 0;
+
+ cifs_sb = CIFS_FILE_SB(file);
+ cfile = file->private_data;
+ tcon = tlink_tcon(cfile->tlink);
+
+ if (!tcon->ses->server->ops->async_readv)
+ return -ENOSYS;
+
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+ cifs_dbg(FYI, "attempting read on write only file instance\n");
+
+ ctx = cifs_aio_ctx_alloc();
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->cfile = cifsFileInfo_get(cfile);
+
+ if (!is_sync_kiocb(iocb))
+ ctx->iocb = iocb;
+
+ if (user_backed_iter(to))
+ ctx->should_dirty = true;
+
+ if (direct) {
+ ctx->pos = offset;
+ ctx->direct_io = true;
+ ctx->iter = *to;
+ ctx->len = len;
+ } else {
+ rc = setup_aio_ctx_iter(ctx, to, ITER_DEST);
+ if (rc) {
+ kref_put(&ctx->refcount, cifs_aio_ctx_release);
+ return rc;
+ }
+ len = ctx->len;
+ }
+
+ if (direct) {
+ rc = filemap_write_and_wait_range(file->f_inode->i_mapping,
+ offset, offset + len - 1);
+ if (rc) {
+ kref_put(&ctx->refcount, cifs_aio_ctx_release);
+ return -EAGAIN;
+ }
+ }
+
+ /* grab a lock here due to read response handlers can access ctx */
+ mutex_lock(&ctx->aio_mutex);
+
+ rc = cifs_send_async_read(offset, len, cfile, cifs_sb, &ctx->list, ctx);
+
+ /* if at least one read request send succeeded, then reset rc */
+ if (!list_empty(&ctx->list))
+ rc = 0;
+
+ mutex_unlock(&ctx->aio_mutex);
+
+ if (rc) {
+ kref_put(&ctx->refcount, cifs_aio_ctx_release);
+ return rc;
+ }
+
+ if (!is_sync_kiocb(iocb)) {
+ kref_put(&ctx->refcount, cifs_aio_ctx_release);
+ return -EIOCBQUEUED;
+ }
+
+ rc = wait_for_completion_killable(&ctx->done);
+ if (rc) {
+ mutex_lock(&ctx->aio_mutex);
+ ctx->rc = rc = -EINTR;
+ total_read = ctx->total_len;
+ mutex_unlock(&ctx->aio_mutex);
+ } else {
+ rc = ctx->rc;
+ total_read = ctx->total_len;
+ }
+
+ kref_put(&ctx->refcount, cifs_aio_ctx_release);
+
+ if (total_read) {
+ iocb->ki_pos += total_read;
+ return total_read;
+ }
+ return rc;
+}
+
+ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to)
+{
+ return __cifs_readv(iocb, to, true);
+}
+
+ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to)
+{
+ return __cifs_readv(iocb, to, false);
+}
+
+ssize_t
+cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
+{
+ struct inode *inode = file_inode(iocb->ki_filp);
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifsFileInfo *cfile = (struct cifsFileInfo *)
+ iocb->ki_filp->private_data;
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ int rc = -EACCES;
+
+ /*
+ * In strict cache mode we need to read from the server all the time
+ * if we don't have level II oplock because the server can delay mtime
+ * change - so we can't make a decision about inode invalidating.
+ * And we can also fail with pagereading if there are mandatory locks
+ * on pages affected by this read but not on the region from pos to
+ * pos+len-1.
+ */
+ if (!CIFS_CACHE_READ(cinode))
+ return cifs_user_readv(iocb, to);
+
+ if (cap_unix(tcon->ses) &&
+ (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
+ ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
+ return generic_file_read_iter(iocb, to);
+
+ /*
+ * We need to hold the sem to be sure nobody modifies lock list
+ * with a brlock that prevents reading.
+ */
+ down_read(&cinode->lock_sem);
+ if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(to),
+ tcon->ses->server->vals->shared_lock_type,
+ 0, NULL, CIFS_READ_OP))
+ rc = generic_file_read_iter(iocb, to);
+ up_read(&cinode->lock_sem);
+ return rc;
+}
+
+static ssize_t
+cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
+{
+ int rc = -EACCES;
+ unsigned int bytes_read = 0;
+ unsigned int total_read;
+ unsigned int current_read_size;
+ unsigned int rsize;
+ struct cifs_sb_info *cifs_sb;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ unsigned int xid;
+ char *cur_offset;
+ struct cifsFileInfo *open_file;
+ struct cifs_io_parms io_parms = {0};
+ int buf_type = CIFS_NO_BUFFER;
+ __u32 pid;
+
+ xid = get_xid();
+ cifs_sb = CIFS_FILE_SB(file);
+
+ /* FIXME: set up handlers for larger reads and/or convert to async */
+ rsize = min_t(unsigned int, cifs_sb->ctx->rsize, CIFSMaxBufSize);
+
+ if (file->private_data == NULL) {
+ rc = -EBADF;
+ free_xid(xid);
+ return rc;
+ }
+ open_file = file->private_data;
+ tcon = tlink_tcon(open_file->tlink);
+ server = cifs_pick_channel(tcon->ses);
+
+ if (!server->ops->sync_read) {
+ free_xid(xid);
+ return -ENOSYS;
+ }
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+ pid = open_file->pid;
+ else
+ pid = current->tgid;
+
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+ cifs_dbg(FYI, "attempting read on write only file instance\n");
+
+ for (total_read = 0, cur_offset = read_data; read_size > total_read;
+ total_read += bytes_read, cur_offset += bytes_read) {
+ do {
+ current_read_size = min_t(uint, read_size - total_read,
+ rsize);
+ /*
+ * For windows me and 9x we do not want to request more
+ * than it negotiated since it will refuse the read
+ * then.
+ */
+ if (!(tcon->ses->capabilities &
+ tcon->ses->server->vals->cap_large_files)) {
+ current_read_size = min_t(uint,
+ current_read_size, CIFSMaxBufSize);
+ }
+ if (open_file->invalidHandle) {
+ rc = cifs_reopen_file(open_file, true);
+ if (rc != 0)
+ break;
+ }
+ io_parms.pid = pid;
+ io_parms.tcon = tcon;
+ io_parms.offset = *offset;
+ io_parms.length = current_read_size;
+ io_parms.server = server;
+ rc = server->ops->sync_read(xid, &open_file->fid, &io_parms,
+ &bytes_read, &cur_offset,
+ &buf_type);
+ } while (rc == -EAGAIN);
+
+ if (rc || (bytes_read == 0)) {
+ if (total_read) {
+ break;
+ } else {
+ free_xid(xid);
+ return rc;
+ }
+ } else {
+ cifs_stats_bytes_read(tcon, total_read);
+ *offset += bytes_read;
+ }
+ }
+ free_xid(xid);
+ return total_read;
+}
+
+/*
+ * If the page is mmap'ed into a process' page tables, then we need to make
+ * sure that it doesn't change while being written back.
+ */
+static vm_fault_t
+cifs_page_mkwrite(struct vm_fault *vmf)
+{
+ struct page *page = vmf->page;
+
+ /* Wait for the page to be written to the cache before we allow it to
+ * be modified. We then assume the entire page will need writing back.
+ */
+#ifdef CONFIG_CIFS_FSCACHE
+ if (PageFsCache(page) &&
+ wait_on_page_fscache_killable(page) < 0)
+ return VM_FAULT_RETRY;
+#endif
+
+ wait_on_page_writeback(page);
+
+ if (lock_page_killable(page) < 0)
+ return VM_FAULT_RETRY;
+ return VM_FAULT_LOCKED;
+}
+
+static const struct vm_operations_struct cifs_file_vm_ops = {
+ .fault = filemap_fault,
+ .map_pages = filemap_map_pages,
+ .page_mkwrite = cifs_page_mkwrite,
+};
+
+int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ int xid, rc = 0;
+ struct inode *inode = file_inode(file);
+
+ xid = get_xid();
+
+ if (!CIFS_CACHE_READ(CIFS_I(inode)))
+ rc = cifs_zap_mapping(inode);
+ if (!rc)
+ rc = generic_file_mmap(file, vma);
+ if (!rc)
+ vma->vm_ops = &cifs_file_vm_ops;
+
+ free_xid(xid);
+ return rc;
+}
+
+int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ int rc, xid;
+
+ xid = get_xid();
+
+ rc = cifs_revalidate_file(file);
+ if (rc)
+ cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n",
+ rc);
+ if (!rc)
+ rc = generic_file_mmap(file, vma);
+ if (!rc)
+ vma->vm_ops = &cifs_file_vm_ops;
+
+ free_xid(xid);
+ return rc;
+}
+
+static void
+cifs_readv_complete(struct work_struct *work)
+{
+ unsigned int i, got_bytes;
+ struct cifs_readdata *rdata = container_of(work,
+ struct cifs_readdata, work);
+
+ got_bytes = rdata->got_bytes;
+ for (i = 0; i < rdata->nr_pages; i++) {
+ struct page *page = rdata->pages[i];
+
+ if (rdata->result == 0 ||
+ (rdata->result == -EAGAIN && got_bytes)) {
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ } else
+ SetPageError(page);
+
+ if (rdata->result == 0 ||
+ (rdata->result == -EAGAIN && got_bytes))
+ cifs_readpage_to_fscache(rdata->mapping->host, page);
+
+ unlock_page(page);
+
+ got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes);
+
+ put_page(page);
+ rdata->pages[i] = NULL;
+ }
+ kref_put(&rdata->refcount, cifs_readdata_release);
+}
+
+static int
+readpages_fill_pages(struct TCP_Server_Info *server,
+ struct cifs_readdata *rdata, struct iov_iter *iter,
+ unsigned int len)
+{
+ int result = 0;
+ unsigned int i;
+ u64 eof;
+ pgoff_t eof_index;
+ unsigned int nr_pages = rdata->nr_pages;
+ unsigned int page_offset = rdata->page_offset;
+
+ /* determine the eof that the server (probably) has */
+ eof = CIFS_I(rdata->mapping->host)->server_eof;
+ eof_index = eof ? (eof - 1) >> PAGE_SHIFT : 0;
+ cifs_dbg(FYI, "eof=%llu eof_index=%lu\n", eof, eof_index);
+
+ rdata->got_bytes = 0;
+ rdata->tailsz = PAGE_SIZE;
+ for (i = 0; i < nr_pages; i++) {
+ struct page *page = rdata->pages[i];
+ unsigned int to_read = rdata->pagesz;
+ size_t n;
+
+ if (i == 0)
+ to_read -= page_offset;
+ else
+ page_offset = 0;
+
+ n = to_read;
+
+ if (len >= to_read) {
+ len -= to_read;
+ } else if (len > 0) {
+ /* enough for partial page, fill and zero the rest */
+ zero_user(page, len + page_offset, to_read - len);
+ n = rdata->tailsz = len;
+ len = 0;
+ } else if (page->index > eof_index) {
+ /*
+ * The VFS will not try to do readahead past the
+ * i_size, but it's possible that we have outstanding
+ * writes with gaps in the middle and the i_size hasn't
+ * caught up yet. Populate those with zeroed out pages
+ * to prevent the VFS from repeatedly attempting to
+ * fill them until the writes are flushed.
+ */
+ zero_user(page, 0, PAGE_SIZE);
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ unlock_page(page);
+ put_page(page);
+ rdata->pages[i] = NULL;
+ rdata->nr_pages--;
+ continue;
+ } else {
+ /* no need to hold page hostage */
+ unlock_page(page);
+ put_page(page);
+ rdata->pages[i] = NULL;
+ rdata->nr_pages--;
+ continue;
+ }
+
+ if (iter)
+ result = copy_page_from_iter(
+ page, page_offset, n, iter);
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ else if (rdata->mr)
+ result = n;
+#endif
+ else
+ result = cifs_read_page_from_socket(
+ server, page, page_offset, n);
+ if (result < 0)
+ break;
+
+ rdata->got_bytes += result;
+ }
+
+ return result != -ECONNABORTED && rdata->got_bytes > 0 ?
+ rdata->got_bytes : result;
+}
+
+static int
+cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
+ struct cifs_readdata *rdata, unsigned int len)
+{
+ return readpages_fill_pages(server, rdata, NULL, len);
+}
+
+static int
+cifs_readpages_copy_into_pages(struct TCP_Server_Info *server,
+ struct cifs_readdata *rdata,
+ struct iov_iter *iter)
+{
+ return readpages_fill_pages(server, rdata, iter, iter->count);
+}
+
+static void cifs_readahead(struct readahead_control *ractl)
+{
+ int rc;
+ struct cifsFileInfo *open_file = ractl->file->private_data;
+ struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(ractl->file);
+ struct TCP_Server_Info *server;
+ pid_t pid;
+ unsigned int xid, nr_pages, last_batch_size = 0, cache_nr_pages = 0;
+ pgoff_t next_cached = ULONG_MAX;
+ bool caching = fscache_cookie_enabled(cifs_inode_cookie(ractl->mapping->host)) &&
+ cifs_inode_cookie(ractl->mapping->host)->cache_priv;
+ bool check_cache = caching;
+
+ xid = get_xid();
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
+ pid = open_file->pid;
+ else
+ pid = current->tgid;
+
+ rc = 0;
+ server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses);
+
+ cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n",
+ __func__, ractl->file, ractl->mapping, readahead_count(ractl));
+
+ /*
+ * Chop the readahead request up into rsize-sized read requests.
+ */
+ while ((nr_pages = readahead_count(ractl) - last_batch_size)) {
+ unsigned int i, got, rsize;
+ struct page *page;
+ struct cifs_readdata *rdata;
+ struct cifs_credits credits_on_stack;
+ struct cifs_credits *credits = &credits_on_stack;
+ pgoff_t index = readahead_index(ractl) + last_batch_size;
+
+ /*
+ * Find out if we have anything cached in the range of
+ * interest, and if so, where the next chunk of cached data is.
+ */
+ if (caching) {
+ if (check_cache) {
+ rc = cifs_fscache_query_occupancy(
+ ractl->mapping->host, index, nr_pages,
+ &next_cached, &cache_nr_pages);
+ if (rc < 0)
+ caching = false;
+ check_cache = false;
+ }
+
+ if (index == next_cached) {
+ /*
+ * TODO: Send a whole batch of pages to be read
+ * by the cache.
+ */
+ struct folio *folio = readahead_folio(ractl);
+
+ last_batch_size = folio_nr_pages(folio);
+ if (cifs_readpage_from_fscache(ractl->mapping->host,
+ &folio->page) < 0) {
+ /*
+ * TODO: Deal with cache read failure
+ * here, but for the moment, delegate
+ * that to readpage.
+ */
+ caching = false;
+ }
+ folio_unlock(folio);
+ next_cached++;
+ cache_nr_pages--;
+ if (cache_nr_pages == 0)
+ check_cache = true;
+ continue;
+ }
+ }
+
+ if (open_file->invalidHandle) {
+ rc = cifs_reopen_file(open_file, true);
+ if (rc) {
+ if (rc == -EAGAIN)
+ continue;
+ break;
+ }
+ }
+
+ if (cifs_sb->ctx->rsize == 0)
+ cifs_sb->ctx->rsize =
+ server->ops->negotiate_rsize(tlink_tcon(open_file->tlink),
+ cifs_sb->ctx);
+
+ rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize,
+ &rsize, credits);
+ if (rc)
+ break;
+ nr_pages = min_t(size_t, rsize / PAGE_SIZE, readahead_count(ractl));
+ nr_pages = min_t(size_t, nr_pages, next_cached - index);
+
+ /*
+ * Give up immediately if rsize is too small to read an entire
+ * page. The VFS will fall back to readpage. We should never
+ * reach this point however since we set ra_pages to 0 when the
+ * rsize is smaller than a cache page.
+ */
+ if (unlikely(!nr_pages)) {
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+
+ rdata = cifs_readdata_alloc(nr_pages, cifs_readv_complete);
+ if (!rdata) {
+ /* best to give up if we're out of mem */
+ add_credits_and_wake_if(server, credits, 0);
+ break;
+ }
+
+ got = __readahead_batch(ractl, rdata->pages, nr_pages);
+ if (got != nr_pages) {
+ pr_warn("__readahead_batch() returned %u/%u\n",
+ got, nr_pages);
+ nr_pages = got;
+ }
+
+ rdata->nr_pages = nr_pages;
+ rdata->bytes = readahead_batch_length(ractl);
+ rdata->cfile = cifsFileInfo_get(open_file);
+ rdata->server = server;
+ rdata->mapping = ractl->mapping;
+ rdata->offset = readahead_pos(ractl);
+ rdata->pid = pid;
+ rdata->pagesz = PAGE_SIZE;
+ rdata->tailsz = PAGE_SIZE;
+ rdata->read_into_pages = cifs_readpages_read_into_pages;
+ rdata->copy_into_pages = cifs_readpages_copy_into_pages;
+ rdata->credits = credits_on_stack;
+
+ rc = adjust_credits(server, &rdata->credits, rdata->bytes);
+ if (!rc) {
+ if (rdata->cfile->invalidHandle)
+ rc = -EAGAIN;
+ else
+ rc = server->ops->async_readv(rdata);
+ }
+
+ if (rc) {
+ add_credits_and_wake_if(server, &rdata->credits, 0);
+ for (i = 0; i < rdata->nr_pages; i++) {
+ page = rdata->pages[i];
+ unlock_page(page);
+ put_page(page);
+ }
+ /* Fallback to the readpage in error/reconnect cases */
+ kref_put(&rdata->refcount, cifs_readdata_release);
+ break;
+ }
+
+ kref_put(&rdata->refcount, cifs_readdata_release);
+ last_batch_size = nr_pages;
+ }
+
+ free_xid(xid);
+}
+
+/*
+ * cifs_readpage_worker must be called with the page pinned
+ */
+static int cifs_readpage_worker(struct file *file, struct page *page,
+ loff_t *poffset)
+{
+ char *read_data;
+ int rc;
+
+ /* Is the page cached? */
+ rc = cifs_readpage_from_fscache(file_inode(file), page);
+ if (rc == 0)
+ goto read_complete;
+
+ read_data = kmap(page);
+ /* for reads over a certain size could initiate async read ahead */
+
+ rc = cifs_read(file, read_data, PAGE_SIZE, poffset);
+
+ if (rc < 0)
+ goto io_error;
+ else
+ cifs_dbg(FYI, "Bytes read %d\n", rc);
+
+ /* we do not want atime to be less than mtime, it broke some apps */
+ file_inode(file)->i_atime = current_time(file_inode(file));
+ if (timespec64_compare(&(file_inode(file)->i_atime), &(file_inode(file)->i_mtime)))
+ file_inode(file)->i_atime = file_inode(file)->i_mtime;
+ else
+ file_inode(file)->i_atime = current_time(file_inode(file));
+
+ if (PAGE_SIZE > rc)
+ memset(read_data + rc, 0, PAGE_SIZE - rc);
+
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+
+ /* send this page to the cache */
+ cifs_readpage_to_fscache(file_inode(file), page);
+
+ rc = 0;
+
+io_error:
+ kunmap(page);
+ unlock_page(page);
+
+read_complete:
+ return rc;
+}
+
+static int cifs_read_folio(struct file *file, struct folio *folio)
+{
+ struct page *page = &folio->page;
+ loff_t offset = page_file_offset(page);
+ int rc = -EACCES;
+ unsigned int xid;
+
+ xid = get_xid();
+
+ if (file->private_data == NULL) {
+ rc = -EBADF;
+ free_xid(xid);
+ return rc;
+ }
+
+ cifs_dbg(FYI, "read_folio %p at offset %d 0x%x\n",
+ page, (int)offset, (int)offset);
+
+ rc = cifs_readpage_worker(file, page, &offset);
+
+ free_xid(xid);
+ return rc;
+}
+
+static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
+{
+ struct cifsFileInfo *open_file;
+
+ spin_lock(&cifs_inode->open_file_lock);
+ list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
+ if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
+ spin_unlock(&cifs_inode->open_file_lock);
+ return 1;
+ }
+ }
+ spin_unlock(&cifs_inode->open_file_lock);
+ return 0;
+}
+
+/* We do not want to update the file size from server for inodes
+ open for write - to avoid races with writepage extending
+ the file - in the future we could consider allowing
+ refreshing the inode only on increases in the file size
+ but this is tricky to do without racing with writebehind
+ page caching in the current Linux kernel design */
+bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
+{
+ if (!cifsInode)
+ return true;
+
+ if (is_inode_writable(cifsInode)) {
+ /* This inode is open for write at least once */
+ struct cifs_sb_info *cifs_sb;
+
+ cifs_sb = CIFS_SB(cifsInode->netfs.inode.i_sb);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+ /* since no page cache to corrupt on directio
+ we can change size safely */
+ return true;
+ }
+
+ if (i_size_read(&cifsInode->netfs.inode) < end_of_file)
+ return true;
+
+ return false;
+ } else
+ return true;
+}
+
+static int cifs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len,
+ struct page **pagep, void **fsdata)
+{
+ int oncethru = 0;
+ pgoff_t index = pos >> PAGE_SHIFT;
+ loff_t offset = pos & (PAGE_SIZE - 1);
+ loff_t page_start = pos & PAGE_MASK;
+ loff_t i_size;
+ struct page *page;
+ int rc = 0;
+
+ cifs_dbg(FYI, "write_begin from %lld len %d\n", (long long)pos, len);
+
+start:
+ page = grab_cache_page_write_begin(mapping, index);
+ if (!page) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ if (PageUptodate(page))
+ goto out;
+
+ /*
+ * If we write a full page it will be up to date, no need to read from
+ * the server. If the write is short, we'll end up doing a sync write
+ * instead.
+ */
+ if (len == PAGE_SIZE)
+ goto out;
+
+ /*
+ * optimize away the read when we have an oplock, and we're not
+ * expecting to use any of the data we'd be reading in. That
+ * is, when the page lies beyond the EOF, or straddles the EOF
+ * and the write will cover all of the existing data.
+ */
+ if (CIFS_CACHE_READ(CIFS_I(mapping->host))) {
+ i_size = i_size_read(mapping->host);
+ if (page_start >= i_size ||
+ (offset == 0 && (pos + len) >= i_size)) {
+ zero_user_segments(page, 0, offset,
+ offset + len,
+ PAGE_SIZE);
+ /*
+ * PageChecked means that the parts of the page
+ * to which we're not writing are considered up
+ * to date. Once the data is copied to the
+ * page, it can be set uptodate.
+ */
+ SetPageChecked(page);
+ goto out;
+ }
+ }
+
+ if ((file->f_flags & O_ACCMODE) != O_WRONLY && !oncethru) {
+ /*
+ * might as well read a page, it is fast enough. If we get
+ * an error, we don't need to return it. cifs_write_end will
+ * do a sync write instead since PG_uptodate isn't set.
+ */
+ cifs_readpage_worker(file, page, &page_start);
+ put_page(page);
+ oncethru = 1;
+ goto start;
+ } else {
+ /* we could try using another file handle if there is one -
+ but how would we lock it to prevent close of that handle
+ racing with this read? In any case
+ this will be written out by write_end so is fine */
+ }
+out:
+ *pagep = page;
+ return rc;
+}
+
+static bool cifs_release_folio(struct folio *folio, gfp_t gfp)
+{
+ if (folio_test_private(folio))
+ return 0;
+ if (folio_test_fscache(folio)) {
+ if (current_is_kswapd() || !(gfp & __GFP_FS))
+ return false;
+ folio_wait_fscache(folio);
+ }
+ fscache_note_page_release(cifs_inode_cookie(folio->mapping->host));
+ return true;
+}
+
+static void cifs_invalidate_folio(struct folio *folio, size_t offset,
+ size_t length)
+{
+ folio_wait_fscache(folio);
+}
+
+static int cifs_launder_folio(struct folio *folio)
+{
+ int rc = 0;
+ loff_t range_start = folio_pos(folio);
+ loff_t range_end = range_start + folio_size(folio);
+ struct writeback_control wbc = {
+ .sync_mode = WB_SYNC_ALL,
+ .nr_to_write = 0,
+ .range_start = range_start,
+ .range_end = range_end,
+ };
+
+ cifs_dbg(FYI, "Launder page: %lu\n", folio->index);
+
+ if (folio_clear_dirty_for_io(folio))
+ rc = cifs_writepage_locked(&folio->page, &wbc);
+
+ folio_wait_fscache(folio);
+ return rc;
+}
+
+void cifs_oplock_break(struct work_struct *work)
+{
+ struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
+ oplock_break);
+ struct inode *inode = d_inode(cfile->dentry);
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ int rc = 0;
+ bool purge_cache = false, oplock_break_cancelled;
+ __u64 persistent_fid, volatile_fid;
+ __u16 net_fid;
+
+ wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
+ TASK_UNINTERRUPTIBLE);
+
+ server->ops->downgrade_oplock(server, cinode, cfile->oplock_level,
+ cfile->oplock_epoch, &purge_cache);
+
+ if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) &&
+ cifs_has_mand_locks(cinode)) {
+ cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n",
+ inode);
+ cinode->oplock = 0;
+ }
+
+ if (inode && S_ISREG(inode->i_mode)) {
+ if (CIFS_CACHE_READ(cinode))
+ break_lease(inode, O_RDONLY);
+ else
+ break_lease(inode, O_WRONLY);
+ rc = filemap_fdatawrite(inode->i_mapping);
+ if (!CIFS_CACHE_READ(cinode) || purge_cache) {
+ rc = filemap_fdatawait(inode->i_mapping);
+ mapping_set_error(inode->i_mapping, rc);
+ cifs_zap_mapping(inode);
+ }
+ cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc);
+ if (CIFS_CACHE_WRITE(cinode))
+ goto oplock_break_ack;
+ }
+
+ rc = cifs_push_locks(cfile);
+ if (rc)
+ cifs_dbg(VFS, "Push locks rc = %d\n", rc);
+
+oplock_break_ack:
+ /*
+ * When oplock break is received and there are no active
+ * file handles but cached, then schedule deferred close immediately.
+ * So, new open will not use cached handle.
+ */
+
+ if (!CIFS_CACHE_HANDLE(cinode) && !list_empty(&cinode->deferred_closes))
+ cifs_close_deferred_file(cinode);
+
+ persistent_fid = cfile->fid.persistent_fid;
+ volatile_fid = cfile->fid.volatile_fid;
+ net_fid = cfile->fid.netfid;
+ oplock_break_cancelled = cfile->oplock_break_cancelled;
+
+ _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
+ /*
+ * releasing stale oplock after recent reconnect of smb session using
+ * a now incorrect file handle is not a data integrity issue but do
+ * not bother sending an oplock release if session to server still is
+ * disconnected since oplock already released by the server
+ */
+ if (!oplock_break_cancelled) {
+ /* check for server null since can race with kill_sb calling tree disconnect */
+ if (tcon->ses && tcon->ses->server) {
+ rc = tcon->ses->server->ops->oplock_response(tcon, persistent_fid,
+ volatile_fid, net_fid, cinode);
+ cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
+ } else
+ pr_warn_once("lease break not sent for unmounted share\n");
+ }
+
+ cifs_done_oplock_break(cinode);
+}
+
+/*
+ * The presence of cifs_direct_io() in the address space ops vector
+ * allowes open() O_DIRECT flags which would have failed otherwise.
+ *
+ * In the non-cached mode (mount with cache=none), we shunt off direct read and write requests
+ * so this method should never be called.
+ *
+ * Direct IO is not yet supported in the cached mode.
+ */
+static ssize_t
+cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter)
+{
+ /*
+ * FIXME
+ * Eventually need to support direct IO for non forcedirectio mounts
+ */
+ return -EINVAL;
+}
+
+static int cifs_swap_activate(struct swap_info_struct *sis,
+ struct file *swap_file, sector_t *span)
+{
+ struct cifsFileInfo *cfile = swap_file->private_data;
+ struct inode *inode = swap_file->f_mapping->host;
+ unsigned long blocks;
+ long long isize;
+
+ cifs_dbg(FYI, "swap activate\n");
+
+ if (!swap_file->f_mapping->a_ops->swap_rw)
+ /* Cannot support swap */
+ return -EINVAL;
+
+ spin_lock(&inode->i_lock);
+ blocks = inode->i_blocks;
+ isize = inode->i_size;
+ spin_unlock(&inode->i_lock);
+ if (blocks*512 < isize) {
+ pr_warn("swap activate: swapfile has holes\n");
+ return -EINVAL;
+ }
+ *span = sis->pages;
+
+ pr_warn_once("Swap support over SMB3 is experimental\n");
+
+ /*
+ * TODO: consider adding ACL (or documenting how) to prevent other
+ * users (on this or other systems) from reading it
+ */
+
+
+ /* TODO: add sk_set_memalloc(inet) or similar */
+
+ if (cfile)
+ cfile->swapfile = true;
+ /*
+ * TODO: Since file already open, we can't open with DENY_ALL here
+ * but we could add call to grab a byte range lock to prevent others
+ * from reading or writing the file
+ */
+
+ sis->flags |= SWP_FS_OPS;
+ return add_swap_extent(sis, 0, sis->max, 0);
+}
+
+static void cifs_swap_deactivate(struct file *file)
+{
+ struct cifsFileInfo *cfile = file->private_data;
+
+ cifs_dbg(FYI, "swap deactivate\n");
+
+ /* TODO: undo sk_set_memalloc(inet) will eventually be needed */
+
+ if (cfile)
+ cfile->swapfile = false;
+
+ /* do we need to unpin (or unlock) the file */
+}
+
+/*
+ * Mark a page as having been made dirty and thus needing writeback. We also
+ * need to pin the cache object to write back to.
+ */
+#ifdef CONFIG_CIFS_FSCACHE
+static bool cifs_dirty_folio(struct address_space *mapping, struct folio *folio)
+{
+ return fscache_dirty_folio(mapping, folio,
+ cifs_inode_cookie(mapping->host));
+}
+#else
+#define cifs_dirty_folio filemap_dirty_folio
+#endif
+
+const struct address_space_operations cifs_addr_ops = {
+ .read_folio = cifs_read_folio,
+ .readahead = cifs_readahead,
+ .writepage = cifs_writepage,
+ .writepages = cifs_writepages,
+ .write_begin = cifs_write_begin,
+ .write_end = cifs_write_end,
+ .dirty_folio = cifs_dirty_folio,
+ .release_folio = cifs_release_folio,
+ .direct_IO = cifs_direct_io,
+ .invalidate_folio = cifs_invalidate_folio,
+ .launder_folio = cifs_launder_folio,
+ /*
+ * TODO: investigate and if useful we could add an cifs_migratePage
+ * helper (under an CONFIG_MIGRATION) in the future, and also
+ * investigate and add an is_dirty_writeback helper if needed
+ */
+ .swap_activate = cifs_swap_activate,
+ .swap_deactivate = cifs_swap_deactivate,
+};
+
+/*
+ * cifs_readahead requires the server to support a buffer large enough to
+ * contain the header plus one complete page of data. Otherwise, we need
+ * to leave cifs_readahead out of the address space operations.
+ */
+const struct address_space_operations cifs_addr_ops_smallbuf = {
+ .read_folio = cifs_read_folio,
+ .writepage = cifs_writepage,
+ .writepages = cifs_writepages,
+ .write_begin = cifs_write_begin,
+ .write_end = cifs_write_end,
+ .dirty_folio = cifs_dirty_folio,
+ .release_folio = cifs_release_folio,
+ .invalidate_folio = cifs_invalidate_folio,
+ .launder_folio = cifs_launder_folio,
+};
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
new file mode 100644
index 000000000000..e2e2ef0fa9a0
--- /dev/null
+++ b/fs/smb/client/fs_context.c
@@ -0,0 +1,1773 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020, Microsoft Corporation.
+ *
+ * Author(s): Steve French <stfrench@microsoft.com>
+ * David Howells <dhowells@redhat.com>
+ */
+
+/*
+#include <linux/module.h>
+#include <linux/nsproxy.h>
+#include <linux/slab.h>
+#include <linux/magic.h>
+#include <linux/security.h>
+#include <net/net_namespace.h>
+#ifdef CONFIG_CIFS_DFS_UPCALL
+#include "dfs_cache.h"
+#endif
+*/
+
+#include <linux/ctype.h>
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/parser.h>
+#include <linux/utsname.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "ntlmssp.h"
+#include "nterr.h"
+#include "rfc1002pdu.h"
+#include "fs_context.h"
+
+static DEFINE_MUTEX(cifs_mount_mutex);
+
+static const match_table_t cifs_smb_version_tokens = {
+ { Smb_1, SMB1_VERSION_STRING },
+ { Smb_20, SMB20_VERSION_STRING},
+ { Smb_21, SMB21_VERSION_STRING },
+ { Smb_30, SMB30_VERSION_STRING },
+ { Smb_302, SMB302_VERSION_STRING },
+ { Smb_302, ALT_SMB302_VERSION_STRING },
+ { Smb_311, SMB311_VERSION_STRING },
+ { Smb_311, ALT_SMB311_VERSION_STRING },
+ { Smb_3any, SMB3ANY_VERSION_STRING },
+ { Smb_default, SMBDEFAULT_VERSION_STRING },
+ { Smb_version_err, NULL }
+};
+
+static const match_table_t cifs_secflavor_tokens = {
+ { Opt_sec_krb5, "krb5" },
+ { Opt_sec_krb5i, "krb5i" },
+ { Opt_sec_krb5p, "krb5p" },
+ { Opt_sec_ntlmsspi, "ntlmsspi" },
+ { Opt_sec_ntlmssp, "ntlmssp" },
+ { Opt_sec_ntlmv2, "nontlm" },
+ { Opt_sec_ntlmv2, "ntlmv2" },
+ { Opt_sec_ntlmv2i, "ntlmv2i" },
+ { Opt_sec_none, "none" },
+
+ { Opt_sec_err, NULL }
+};
+
+const struct fs_parameter_spec smb3_fs_parameters[] = {
+ /* Mount options that take no arguments */
+ fsparam_flag_no("user_xattr", Opt_user_xattr),
+ fsparam_flag_no("forceuid", Opt_forceuid),
+ fsparam_flag_no("multichannel", Opt_multichannel),
+ fsparam_flag_no("forcegid", Opt_forcegid),
+ fsparam_flag("noblocksend", Opt_noblocksend),
+ fsparam_flag("noautotune", Opt_noautotune),
+ fsparam_flag("nolease", Opt_nolease),
+ fsparam_flag_no("hard", Opt_hard),
+ fsparam_flag_no("soft", Opt_soft),
+ fsparam_flag_no("perm", Opt_perm),
+ fsparam_flag("nodelete", Opt_nodelete),
+ fsparam_flag_no("mapposix", Opt_mapposix),
+ fsparam_flag("mapchars", Opt_mapchars),
+ fsparam_flag("nomapchars", Opt_nomapchars),
+ fsparam_flag_no("sfu", Opt_sfu),
+ fsparam_flag("nodfs", Opt_nodfs),
+ fsparam_flag_no("posixpaths", Opt_posixpaths),
+ fsparam_flag_no("unix", Opt_unix),
+ fsparam_flag_no("linux", Opt_unix),
+ fsparam_flag_no("posix", Opt_unix),
+ fsparam_flag("nocase", Opt_nocase),
+ fsparam_flag("ignorecase", Opt_nocase),
+ fsparam_flag_no("brl", Opt_brl),
+ fsparam_flag_no("handlecache", Opt_handlecache),
+ fsparam_flag("forcemandatorylock", Opt_forcemandatorylock),
+ fsparam_flag("forcemand", Opt_forcemandatorylock),
+ fsparam_flag("setuidfromacl", Opt_setuidfromacl),
+ fsparam_flag("idsfromsid", Opt_setuidfromacl),
+ fsparam_flag_no("setuids", Opt_setuids),
+ fsparam_flag_no("dynperm", Opt_dynperm),
+ fsparam_flag_no("intr", Opt_intr),
+ fsparam_flag_no("strictsync", Opt_strictsync),
+ fsparam_flag_no("serverino", Opt_serverino),
+ fsparam_flag("rwpidforward", Opt_rwpidforward),
+ fsparam_flag("cifsacl", Opt_cifsacl),
+ fsparam_flag_no("acl", Opt_acl),
+ fsparam_flag("locallease", Opt_locallease),
+ fsparam_flag("sign", Opt_sign),
+ fsparam_flag("ignore_signature", Opt_ignore_signature),
+ fsparam_flag("signloosely", Opt_ignore_signature),
+ fsparam_flag("seal", Opt_seal),
+ fsparam_flag("noac", Opt_noac),
+ fsparam_flag("fsc", Opt_fsc),
+ fsparam_flag("mfsymlinks", Opt_mfsymlinks),
+ fsparam_flag("multiuser", Opt_multiuser),
+ fsparam_flag("sloppy", Opt_sloppy),
+ fsparam_flag("nosharesock", Opt_nosharesock),
+ fsparam_flag_no("persistenthandles", Opt_persistent),
+ fsparam_flag_no("resilienthandles", Opt_resilient),
+ fsparam_flag_no("tcpnodelay", Opt_tcp_nodelay),
+ fsparam_flag("nosparse", Opt_nosparse),
+ fsparam_flag("domainauto", Opt_domainauto),
+ fsparam_flag("rdma", Opt_rdma),
+ fsparam_flag("modesid", Opt_modesid),
+ fsparam_flag("modefromsid", Opt_modesid),
+ fsparam_flag("rootfs", Opt_rootfs),
+ fsparam_flag("compress", Opt_compress),
+ fsparam_flag("witness", Opt_witness),
+
+ /* Mount options which take numeric value */
+ fsparam_u32("backupuid", Opt_backupuid),
+ fsparam_u32("backupgid", Opt_backupgid),
+ fsparam_u32("uid", Opt_uid),
+ fsparam_u32("cruid", Opt_cruid),
+ fsparam_u32("gid", Opt_gid),
+ fsparam_u32("file_mode", Opt_file_mode),
+ fsparam_u32("dirmode", Opt_dirmode),
+ fsparam_u32("dir_mode", Opt_dirmode),
+ fsparam_u32("port", Opt_port),
+ fsparam_u32("min_enc_offload", Opt_min_enc_offload),
+ fsparam_u32("esize", Opt_min_enc_offload),
+ fsparam_u32("bsize", Opt_blocksize),
+ fsparam_u32("rasize", Opt_rasize),
+ fsparam_u32("rsize", Opt_rsize),
+ fsparam_u32("wsize", Opt_wsize),
+ fsparam_u32("actimeo", Opt_actimeo),
+ fsparam_u32("acdirmax", Opt_acdirmax),
+ fsparam_u32("acregmax", Opt_acregmax),
+ fsparam_u32("closetimeo", Opt_closetimeo),
+ fsparam_u32("echo_interval", Opt_echo_interval),
+ fsparam_u32("max_credits", Opt_max_credits),
+ fsparam_u32("handletimeout", Opt_handletimeout),
+ fsparam_u64("snapshot", Opt_snapshot),
+ fsparam_u32("max_channels", Opt_max_channels),
+
+ /* Mount options which take string value */
+ fsparam_string("source", Opt_source),
+ fsparam_string("user", Opt_user),
+ fsparam_string("username", Opt_user),
+ fsparam_string("pass", Opt_pass),
+ fsparam_string("password", Opt_pass),
+ fsparam_string("ip", Opt_ip),
+ fsparam_string("addr", Opt_ip),
+ fsparam_string("domain", Opt_domain),
+ fsparam_string("dom", Opt_domain),
+ fsparam_string("srcaddr", Opt_srcaddr),
+ fsparam_string("iocharset", Opt_iocharset),
+ fsparam_string("netbiosname", Opt_netbiosname),
+ fsparam_string("servern", Opt_servern),
+ fsparam_string("ver", Opt_ver),
+ fsparam_string("vers", Opt_vers),
+ fsparam_string("sec", Opt_sec),
+ fsparam_string("cache", Opt_cache),
+
+ /* Arguments that should be ignored */
+ fsparam_flag("guest", Opt_ignore),
+ fsparam_flag("noatime", Opt_ignore),
+ fsparam_flag("relatime", Opt_ignore),
+ fsparam_flag("_netdev", Opt_ignore),
+ fsparam_flag_no("suid", Opt_ignore),
+ fsparam_flag_no("exec", Opt_ignore),
+ fsparam_flag_no("dev", Opt_ignore),
+ fsparam_flag_no("mand", Opt_ignore),
+ fsparam_flag_no("auto", Opt_ignore),
+ fsparam_string("cred", Opt_ignore),
+ fsparam_string("credentials", Opt_ignore),
+ /*
+ * UNC and prefixpath is now extracted from Opt_source
+ * in the new mount API so we can just ignore them going forward.
+ */
+ fsparam_string("unc", Opt_ignore),
+ fsparam_string("prefixpath", Opt_ignore),
+ {}
+};
+
+static int
+cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
+{
+
+ substring_t args[MAX_OPT_ARGS];
+
+ /*
+ * With mount options, the last one should win. Reset any existing
+ * settings back to default.
+ */
+ ctx->sectype = Unspecified;
+ ctx->sign = false;
+
+ switch (match_token(value, cifs_secflavor_tokens, args)) {
+ case Opt_sec_krb5p:
+ cifs_errorf(fc, "sec=krb5p is not supported!\n");
+ return 1;
+ case Opt_sec_krb5i:
+ ctx->sign = true;
+ fallthrough;
+ case Opt_sec_krb5:
+ ctx->sectype = Kerberos;
+ break;
+ case Opt_sec_ntlmsspi:
+ ctx->sign = true;
+ fallthrough;
+ case Opt_sec_ntlmssp:
+ ctx->sectype = RawNTLMSSP;
+ break;
+ case Opt_sec_ntlmv2i:
+ ctx->sign = true;
+ fallthrough;
+ case Opt_sec_ntlmv2:
+ ctx->sectype = NTLMv2;
+ break;
+ case Opt_sec_none:
+ ctx->nullauth = 1;
+ break;
+ default:
+ cifs_errorf(fc, "bad security option: %s\n", value);
+ return 1;
+ }
+
+ return 0;
+}
+
+static const match_table_t cifs_cacheflavor_tokens = {
+ { Opt_cache_loose, "loose" },
+ { Opt_cache_strict, "strict" },
+ { Opt_cache_none, "none" },
+ { Opt_cache_ro, "ro" },
+ { Opt_cache_rw, "singleclient" },
+ { Opt_cache_err, NULL }
+};
+
+static int
+cifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
+{
+ substring_t args[MAX_OPT_ARGS];
+
+ switch (match_token(value, cifs_cacheflavor_tokens, args)) {
+ case Opt_cache_loose:
+ ctx->direct_io = false;
+ ctx->strict_io = false;
+ ctx->cache_ro = false;
+ ctx->cache_rw = false;
+ break;
+ case Opt_cache_strict:
+ ctx->direct_io = false;
+ ctx->strict_io = true;
+ ctx->cache_ro = false;
+ ctx->cache_rw = false;
+ break;
+ case Opt_cache_none:
+ ctx->direct_io = true;
+ ctx->strict_io = false;
+ ctx->cache_ro = false;
+ ctx->cache_rw = false;
+ break;
+ case Opt_cache_ro:
+ ctx->direct_io = false;
+ ctx->strict_io = false;
+ ctx->cache_ro = true;
+ ctx->cache_rw = false;
+ break;
+ case Opt_cache_rw:
+ ctx->direct_io = false;
+ ctx->strict_io = false;
+ ctx->cache_ro = false;
+ ctx->cache_rw = true;
+ break;
+ default:
+ cifs_errorf(fc, "bad cache= option: %s\n", value);
+ return 1;
+ }
+ return 0;
+}
+
+#define DUP_CTX_STR(field) \
+do { \
+ if (ctx->field) { \
+ new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC); \
+ if (new_ctx->field == NULL) { \
+ smb3_cleanup_fs_context_contents(new_ctx); \
+ return -ENOMEM; \
+ } \
+ } \
+} while (0)
+
+int
+smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx)
+{
+ memcpy(new_ctx, ctx, sizeof(*ctx));
+ new_ctx->prepath = NULL;
+ new_ctx->mount_options = NULL;
+ new_ctx->nodename = NULL;
+ new_ctx->username = NULL;
+ new_ctx->password = NULL;
+ new_ctx->server_hostname = NULL;
+ new_ctx->domainname = NULL;
+ new_ctx->UNC = NULL;
+ new_ctx->source = NULL;
+ new_ctx->iocharset = NULL;
+ /*
+ * Make sure to stay in sync with smb3_cleanup_fs_context_contents()
+ */
+ DUP_CTX_STR(prepath);
+ DUP_CTX_STR(mount_options);
+ DUP_CTX_STR(username);
+ DUP_CTX_STR(password);
+ DUP_CTX_STR(server_hostname);
+ DUP_CTX_STR(UNC);
+ DUP_CTX_STR(source);
+ DUP_CTX_STR(domainname);
+ DUP_CTX_STR(nodename);
+ DUP_CTX_STR(iocharset);
+
+ return 0;
+}
+
+static int
+cifs_parse_smb_version(struct fs_context *fc, char *value, struct smb3_fs_context *ctx, bool is_smb3)
+{
+ substring_t args[MAX_OPT_ARGS];
+
+ switch (match_token(value, cifs_smb_version_tokens, args)) {
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ case Smb_1:
+ if (disable_legacy_dialects) {
+ cifs_errorf(fc, "mount with legacy dialect disabled\n");
+ return 1;
+ }
+ if (is_smb3) {
+ cifs_errorf(fc, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
+ return 1;
+ }
+ cifs_errorf(fc, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
+ ctx->ops = &smb1_operations;
+ ctx->vals = &smb1_values;
+ break;
+ case Smb_20:
+ if (disable_legacy_dialects) {
+ cifs_errorf(fc, "mount with legacy dialect disabled\n");
+ return 1;
+ }
+ if (is_smb3) {
+ cifs_errorf(fc, "vers=2.0 not permitted when mounting with smb3\n");
+ return 1;
+ }
+ ctx->ops = &smb20_operations;
+ ctx->vals = &smb20_values;
+ break;
+#else
+ case Smb_1:
+ cifs_errorf(fc, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
+ return 1;
+ case Smb_20:
+ cifs_errorf(fc, "vers=2.0 mount not permitted when legacy dialects disabled\n");
+ return 1;
+#endif /* CIFS_ALLOW_INSECURE_LEGACY */
+ case Smb_21:
+ ctx->ops = &smb21_operations;
+ ctx->vals = &smb21_values;
+ break;
+ case Smb_30:
+ ctx->ops = &smb30_operations;
+ ctx->vals = &smb30_values;
+ break;
+ case Smb_302:
+ ctx->ops = &smb30_operations; /* currently identical with 3.0 */
+ ctx->vals = &smb302_values;
+ break;
+ case Smb_311:
+ ctx->ops = &smb311_operations;
+ ctx->vals = &smb311_values;
+ break;
+ case Smb_3any:
+ ctx->ops = &smb30_operations; /* currently identical with 3.0 */
+ ctx->vals = &smb3any_values;
+ break;
+ case Smb_default:
+ ctx->ops = &smb30_operations;
+ ctx->vals = &smbdefault_values;
+ break;
+ default:
+ cifs_errorf(fc, "Unknown vers= option specified: %s\n", value);
+ return 1;
+ }
+ return 0;
+}
+
+int smb3_parse_opt(const char *options, const char *key, char **val)
+{
+ int rc = -ENOENT;
+ char *opts, *orig, *p;
+
+ orig = opts = kstrdup(options, GFP_KERNEL);
+ if (!opts)
+ return -ENOMEM;
+
+ while ((p = strsep(&opts, ","))) {
+ char *nval;
+
+ if (!*p)
+ continue;
+ if (strncasecmp(p, key, strlen(key)))
+ continue;
+ nval = strchr(p, '=');
+ if (nval) {
+ if (nval == p)
+ continue;
+ *nval++ = 0;
+ *val = kstrdup(nval, GFP_KERNEL);
+ rc = !*val ? -ENOMEM : 0;
+ goto out;
+ }
+ }
+out:
+ kfree(orig);
+ return rc;
+}
+
+/*
+ * Remove duplicate path delimiters. Windows is supposed to do that
+ * but there are some bugs that prevent rename from working if there are
+ * multiple delimiters.
+ *
+ * Returns a sanitized duplicate of @path. @gfp indicates the GFP_* flags
+ * for kstrdup.
+ * The caller is responsible for freeing the original.
+ */
+#define IS_DELIM(c) ((c) == '/' || (c) == '\\')
+char *cifs_sanitize_prepath(char *prepath, gfp_t gfp)
+{
+ char *cursor1 = prepath, *cursor2 = prepath;
+
+ /* skip all prepended delimiters */
+ while (IS_DELIM(*cursor1))
+ cursor1++;
+
+ /* copy the first letter */
+ *cursor2 = *cursor1;
+
+ /* copy the remainder... */
+ while (*(cursor1++)) {
+ /* ... skipping all duplicated delimiters */
+ if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2))
+ continue;
+ *(++cursor2) = *cursor1;
+ }
+
+ /* if the last character is a delimiter, skip it */
+ if (IS_DELIM(*(cursor2 - 1)))
+ cursor2--;
+
+ *(cursor2) = '\0';
+ return kstrdup(prepath, gfp);
+}
+
+/*
+ * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath
+ * fields with the result. Returns 0 on success and an error otherwise
+ * (e.g. ENOMEM or EINVAL)
+ */
+int
+smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
+{
+ char *pos;
+ const char *delims = "/\\";
+ size_t len;
+
+ if (unlikely(!devname || !*devname)) {
+ cifs_dbg(VFS, "Device name not specified\n");
+ return -EINVAL;
+ }
+
+ /* make sure we have a valid UNC double delimiter prefix */
+ len = strspn(devname, delims);
+ if (len != 2)
+ return -EINVAL;
+
+ /* find delimiter between host and sharename */
+ pos = strpbrk(devname + 2, delims);
+ if (!pos)
+ return -EINVAL;
+
+ /* record the server hostname */
+ kfree(ctx->server_hostname);
+ ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL);
+ if (!ctx->server_hostname)
+ return -ENOMEM;
+
+ /* skip past delimiter */
+ ++pos;
+
+ /* now go until next delimiter or end of string */
+ len = strcspn(pos, delims);
+
+ /* move "pos" up to delimiter or NULL */
+ pos += len;
+ kfree(ctx->UNC);
+ ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
+ if (!ctx->UNC)
+ return -ENOMEM;
+
+ convert_delimiter(ctx->UNC, '\\');
+
+ /* skip any delimiter */
+ if (*pos == '/' || *pos == '\\')
+ pos++;
+
+ kfree(ctx->prepath);
+ ctx->prepath = NULL;
+
+ /* If pos is NULL then no prepath */
+ if (!*pos)
+ return 0;
+
+ ctx->prepath = cifs_sanitize_prepath(pos, GFP_KERNEL);
+ if (!ctx->prepath)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void smb3_fs_context_free(struct fs_context *fc);
+static int smb3_fs_context_parse_param(struct fs_context *fc,
+ struct fs_parameter *param);
+static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
+ void *data);
+static int smb3_get_tree(struct fs_context *fc);
+static int smb3_reconfigure(struct fs_context *fc);
+
+static const struct fs_context_operations smb3_fs_context_ops = {
+ .free = smb3_fs_context_free,
+ .parse_param = smb3_fs_context_parse_param,
+ .parse_monolithic = smb3_fs_context_parse_monolithic,
+ .get_tree = smb3_get_tree,
+ .reconfigure = smb3_reconfigure,
+};
+
+/*
+ * Parse a monolithic block of data from sys_mount().
+ * smb3_fs_context_parse_monolithic - Parse key[=val][,key[=val]]* mount data
+ * @ctx: The superblock configuration to fill in.
+ * @data: The data to parse
+ *
+ * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be
+ * called from the ->monolithic_mount_data() fs_context operation.
+ *
+ * Returns 0 on success or the error returned by the ->parse_option() fs_context
+ * operation on failure.
+ */
+static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
+ void *data)
+{
+ struct smb3_fs_context *ctx = smb3_fc2context(fc);
+ char *options = data, *key;
+ int ret = 0;
+
+ if (!options)
+ return 0;
+
+ ctx->mount_options = kstrdup(data, GFP_KERNEL);
+ if (ctx->mount_options == NULL)
+ return -ENOMEM;
+
+ ret = security_sb_eat_lsm_opts(options, &fc->security);
+ if (ret)
+ return ret;
+
+ /* BB Need to add support for sep= here TBD */
+ while ((key = strsep(&options, ",")) != NULL) {
+ size_t len;
+ char *value;
+
+ if (*key == 0)
+ break;
+
+ /* Check if following character is the deliminator If yes,
+ * we have encountered a double deliminator reset the NULL
+ * character to the deliminator
+ */
+ while (options && options[0] == ',') {
+ len = strlen(key);
+ strcpy(key + len, options);
+ options = strchr(options, ',');
+ if (options)
+ *options++ = 0;
+ }
+
+
+ len = 0;
+ value = strchr(key, '=');
+ if (value) {
+ if (value == key)
+ continue;
+ *value++ = 0;
+ len = strlen(value);
+ }
+
+ ret = vfs_parse_fs_string(fc, key, value, len);
+ if (ret < 0)
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Validate the preparsed information in the config.
+ */
+static int smb3_fs_context_validate(struct fs_context *fc)
+{
+ struct smb3_fs_context *ctx = smb3_fc2context(fc);
+
+ if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
+ cifs_errorf(fc, "SMB Direct requires Version >=3.0\n");
+ return -EOPNOTSUPP;
+ }
+
+#ifndef CONFIG_KEYS
+ /* Muliuser mounts require CONFIG_KEYS support */
+ if (ctx->multiuser) {
+ cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
+ return -1;
+ }
+#endif
+
+ if (ctx->got_version == false)
+ pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n");
+
+
+ if (!ctx->UNC) {
+ cifs_errorf(fc, "CIFS mount error: No usable UNC path provided in device string!\n");
+ return -1;
+ }
+
+ /* make sure UNC has a share name */
+ if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
+ cifs_errorf(fc, "Malformed UNC. Unable to find share name.\n");
+ return -ENOENT;
+ }
+
+ if (!ctx->got_ip) {
+ int len;
+ const char *slash;
+
+ /* No ip= option specified? Try to get it from UNC */
+ /* Use the address part of the UNC. */
+ slash = strchr(&ctx->UNC[2], '\\');
+ len = slash - &ctx->UNC[2];
+ if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
+ &ctx->UNC[2], len)) {
+ pr_err("Unable to determine destination address\n");
+ return -EHOSTUNREACH;
+ }
+ }
+
+ /* set the port that we got earlier */
+ cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
+
+ if (ctx->override_uid && !ctx->uid_specified) {
+ ctx->override_uid = 0;
+ pr_notice("ignoring forceuid mount option specified with no uid= option\n");
+ }
+
+ if (ctx->override_gid && !ctx->gid_specified) {
+ ctx->override_gid = 0;
+ pr_notice("ignoring forcegid mount option specified with no gid= option\n");
+ }
+
+ return 0;
+}
+
+static int smb3_get_tree_common(struct fs_context *fc)
+{
+ struct smb3_fs_context *ctx = smb3_fc2context(fc);
+ struct dentry *root;
+ int rc = 0;
+
+ root = cifs_smb3_do_mount(fc->fs_type, 0, ctx);
+ if (IS_ERR(root))
+ return PTR_ERR(root);
+
+ fc->root = root;
+
+ return rc;
+}
+
+/*
+ * Create an SMB3 superblock from the parameters passed.
+ */
+static int smb3_get_tree(struct fs_context *fc)
+{
+ int err = smb3_fs_context_validate(fc);
+ int ret;
+
+ if (err)
+ return err;
+ mutex_lock(&cifs_mount_mutex);
+ ret = smb3_get_tree_common(fc);
+ mutex_unlock(&cifs_mount_mutex);
+ return ret;
+}
+
+static void smb3_fs_context_free(struct fs_context *fc)
+{
+ struct smb3_fs_context *ctx = smb3_fc2context(fc);
+
+ smb3_cleanup_fs_context(ctx);
+}
+
+/*
+ * Compare the old and new proposed context during reconfigure
+ * and check if the changes are compatible.
+ */
+static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
+ struct smb3_fs_context *new_ctx,
+ struct smb3_fs_context *old_ctx)
+{
+ if (new_ctx->posix_paths != old_ctx->posix_paths) {
+ cifs_errorf(fc, "can not change posixpaths during remount\n");
+ return -EINVAL;
+ }
+ if (new_ctx->sectype != old_ctx->sectype) {
+ cifs_errorf(fc, "can not change sec during remount\n");
+ return -EINVAL;
+ }
+ if (new_ctx->multiuser != old_ctx->multiuser) {
+ cifs_errorf(fc, "can not change multiuser during remount\n");
+ return -EINVAL;
+ }
+ if (new_ctx->UNC &&
+ (!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {
+ cifs_errorf(fc, "can not change UNC during remount\n");
+ return -EINVAL;
+ }
+ if (new_ctx->username &&
+ (!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {
+ cifs_errorf(fc, "can not change username during remount\n");
+ return -EINVAL;
+ }
+ if (new_ctx->password &&
+ (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
+ cifs_errorf(fc, "can not change password during remount\n");
+ return -EINVAL;
+ }
+ if (new_ctx->domainname &&
+ (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
+ cifs_errorf(fc, "can not change domainname during remount\n");
+ return -EINVAL;
+ }
+ if (strcmp(new_ctx->workstation_name, old_ctx->workstation_name)) {
+ cifs_errorf(fc, "can not change workstation_name during remount\n");
+ return -EINVAL;
+ }
+ if (new_ctx->nodename &&
+ (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
+ cifs_errorf(fc, "can not change nodename during remount\n");
+ return -EINVAL;
+ }
+ if (new_ctx->iocharset &&
+ (!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {
+ cifs_errorf(fc, "can not change iocharset during remount\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define STEAL_STRING(cifs_sb, ctx, field) \
+do { \
+ kfree(ctx->field); \
+ ctx->field = cifs_sb->ctx->field; \
+ cifs_sb->ctx->field = NULL; \
+} while (0)
+
+#define STEAL_STRING_SENSITIVE(cifs_sb, ctx, field) \
+do { \
+ kfree_sensitive(ctx->field); \
+ ctx->field = cifs_sb->ctx->field; \
+ cifs_sb->ctx->field = NULL; \
+} while (0)
+
+static int smb3_reconfigure(struct fs_context *fc)
+{
+ struct smb3_fs_context *ctx = smb3_fc2context(fc);
+ struct dentry *root = fc->root;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
+ int rc;
+
+ rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx);
+ if (rc)
+ return rc;
+
+ /*
+ * We can not change UNC/username/password/domainname/
+ * workstation_name/nodename/iocharset
+ * during reconnect so ignore what we have in the new context and
+ * just use what we already have in cifs_sb->ctx.
+ */
+ STEAL_STRING(cifs_sb, ctx, UNC);
+ STEAL_STRING(cifs_sb, ctx, source);
+ STEAL_STRING(cifs_sb, ctx, username);
+ STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
+ STEAL_STRING(cifs_sb, ctx, domainname);
+ STEAL_STRING(cifs_sb, ctx, nodename);
+ STEAL_STRING(cifs_sb, ctx, iocharset);
+
+ /* if rsize or wsize not passed in on remount, use previous values */
+ if (ctx->rsize == 0)
+ ctx->rsize = cifs_sb->ctx->rsize;
+ if (ctx->wsize == 0)
+ ctx->wsize = cifs_sb->ctx->wsize;
+
+
+ smb3_cleanup_fs_context_contents(cifs_sb->ctx);
+ rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
+ smb3_update_mnt_flags(cifs_sb);
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ if (!rc)
+ rc = dfs_cache_remount_fs(cifs_sb);
+#endif
+
+ return rc;
+}
+
+static int smb3_fs_context_parse_param(struct fs_context *fc,
+ struct fs_parameter *param)
+{
+ struct fs_parse_result result;
+ struct smb3_fs_context *ctx = smb3_fc2context(fc);
+ int i, opt;
+ bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
+ bool skip_parsing = false;
+ kuid_t uid;
+ kgid_t gid;
+
+ cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
+
+ /*
+ * fs_parse can not handle string options with an empty value so
+ * we will need special handling of them.
+ */
+ if (param->type == fs_value_is_string && param->string[0] == 0) {
+ if (!strcmp("pass", param->key) || !strcmp("password", param->key)) {
+ skip_parsing = true;
+ opt = Opt_pass;
+ } else if (!strcmp("user", param->key) || !strcmp("username", param->key)) {
+ skip_parsing = true;
+ opt = Opt_user;
+ }
+ }
+
+ if (!skip_parsing) {
+ opt = fs_parse(fc, smb3_fs_parameters, param, &result);
+ if (opt < 0)
+ return ctx->sloppy ? 1 : opt;
+ }
+
+ switch (opt) {
+ case Opt_compress:
+ ctx->compression = UNKNOWN_TYPE;
+ cifs_dbg(VFS,
+ "SMB3 compression support is experimental\n");
+ break;
+ case Opt_nodfs:
+ ctx->nodfs = 1;
+ break;
+ case Opt_hard:
+ if (result.negated)
+ ctx->retry = 0;
+ else
+ ctx->retry = 1;
+ break;
+ case Opt_soft:
+ if (result.negated)
+ ctx->retry = 1;
+ else
+ ctx->retry = 0;
+ break;
+ case Opt_mapposix:
+ if (result.negated)
+ ctx->remap = false;
+ else {
+ ctx->remap = true;
+ ctx->sfu_remap = false; /* disable SFU mapping */
+ }
+ break;
+ case Opt_mapchars:
+ if (result.negated)
+ ctx->sfu_remap = false;
+ else {
+ ctx->sfu_remap = true;
+ ctx->remap = false; /* disable SFM (mapposix) mapping */
+ }
+ break;
+ case Opt_user_xattr:
+ if (result.negated)
+ ctx->no_xattr = 1;
+ else
+ ctx->no_xattr = 0;
+ break;
+ case Opt_forceuid:
+ if (result.negated)
+ ctx->override_uid = 0;
+ else
+ ctx->override_uid = 1;
+ break;
+ case Opt_forcegid:
+ if (result.negated)
+ ctx->override_gid = 0;
+ else
+ ctx->override_gid = 1;
+ break;
+ case Opt_perm:
+ if (result.negated)
+ ctx->noperm = 1;
+ else
+ ctx->noperm = 0;
+ break;
+ case Opt_dynperm:
+ if (result.negated)
+ ctx->dynperm = 0;
+ else
+ ctx->dynperm = 1;
+ break;
+ case Opt_sfu:
+ if (result.negated)
+ ctx->sfu_emul = 0;
+ else
+ ctx->sfu_emul = 1;
+ break;
+ case Opt_noblocksend:
+ ctx->noblocksnd = 1;
+ break;
+ case Opt_noautotune:
+ ctx->noautotune = 1;
+ break;
+ case Opt_nolease:
+ ctx->no_lease = 1;
+ break;
+ case Opt_nosparse:
+ ctx->no_sparse = 1;
+ break;
+ case Opt_nodelete:
+ ctx->nodelete = 1;
+ break;
+ case Opt_multichannel:
+ if (result.negated) {
+ ctx->multichannel = false;
+ ctx->max_channels = 1;
+ } else {
+ ctx->multichannel = true;
+ /* if number of channels not specified, default to 2 */
+ if (ctx->max_channels < 2)
+ ctx->max_channels = 2;
+ }
+ break;
+ case Opt_uid:
+ uid = make_kuid(current_user_ns(), result.uint_32);
+ if (!uid_valid(uid))
+ goto cifs_parse_mount_err;
+ ctx->linux_uid = uid;
+ ctx->uid_specified = true;
+ break;
+ case Opt_cruid:
+ uid = make_kuid(current_user_ns(), result.uint_32);
+ if (!uid_valid(uid))
+ goto cifs_parse_mount_err;
+ ctx->cred_uid = uid;
+ ctx->cruid_specified = true;
+ break;
+ case Opt_backupuid:
+ uid = make_kuid(current_user_ns(), result.uint_32);
+ if (!uid_valid(uid))
+ goto cifs_parse_mount_err;
+ ctx->backupuid = uid;
+ ctx->backupuid_specified = true;
+ break;
+ case Opt_backupgid:
+ gid = make_kgid(current_user_ns(), result.uint_32);
+ if (!gid_valid(gid))
+ goto cifs_parse_mount_err;
+ ctx->backupgid = gid;
+ ctx->backupgid_specified = true;
+ break;
+ case Opt_gid:
+ gid = make_kgid(current_user_ns(), result.uint_32);
+ if (!gid_valid(gid))
+ goto cifs_parse_mount_err;
+ ctx->linux_gid = gid;
+ ctx->gid_specified = true;
+ break;
+ case Opt_port:
+ ctx->port = result.uint_32;
+ break;
+ case Opt_file_mode:
+ ctx->file_mode = result.uint_32;
+ break;
+ case Opt_dirmode:
+ ctx->dir_mode = result.uint_32;
+ break;
+ case Opt_min_enc_offload:
+ ctx->min_offload = result.uint_32;
+ break;
+ case Opt_blocksize:
+ /*
+ * inode blocksize realistically should never need to be
+ * less than 16K or greater than 16M and default is 1MB.
+ * Note that small inode block sizes (e.g. 64K) can lead
+ * to very poor performance of common tools like cp and scp
+ */
+ if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||
+ (result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {
+ cifs_errorf(fc, "%s: Invalid blocksize\n",
+ __func__);
+ goto cifs_parse_mount_err;
+ }
+ ctx->bsize = result.uint_32;
+ ctx->got_bsize = true;
+ break;
+ case Opt_rasize:
+ /*
+ * readahead size realistically should never need to be
+ * less than 1M (CIFS_DEFAULT_IOSIZE) or greater than 32M
+ * (perhaps an exception should be considered in the
+ * for the case of a large number of channels
+ * when multichannel is negotiated) since that would lead
+ * to plenty of parallel I/O in flight to the server.
+ * Note that smaller read ahead sizes would
+ * hurt performance of common tools like cp and scp
+ * which often trigger sequential i/o with read ahead
+ */
+ if ((result.uint_32 > (8 * SMB3_DEFAULT_IOSIZE)) ||
+ (result.uint_32 < CIFS_DEFAULT_IOSIZE)) {
+ cifs_errorf(fc, "%s: Invalid rasize %d vs. %d\n",
+ __func__, result.uint_32, SMB3_DEFAULT_IOSIZE);
+ goto cifs_parse_mount_err;
+ }
+ ctx->rasize = result.uint_32;
+ break;
+ case Opt_rsize:
+ ctx->rsize = result.uint_32;
+ ctx->got_rsize = true;
+ break;
+ case Opt_wsize:
+ ctx->wsize = result.uint_32;
+ ctx->got_wsize = true;
+ break;
+ case Opt_acregmax:
+ ctx->acregmax = HZ * result.uint_32;
+ if (ctx->acregmax > CIFS_MAX_ACTIMEO) {
+ cifs_errorf(fc, "acregmax too large\n");
+ goto cifs_parse_mount_err;
+ }
+ break;
+ case Opt_acdirmax:
+ ctx->acdirmax = HZ * result.uint_32;
+ if (ctx->acdirmax > CIFS_MAX_ACTIMEO) {
+ cifs_errorf(fc, "acdirmax too large\n");
+ goto cifs_parse_mount_err;
+ }
+ break;
+ case Opt_actimeo:
+ if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) {
+ cifs_errorf(fc, "timeout too large\n");
+ goto cifs_parse_mount_err;
+ }
+ if ((ctx->acdirmax != CIFS_DEF_ACTIMEO) ||
+ (ctx->acregmax != CIFS_DEF_ACTIMEO)) {
+ cifs_errorf(fc, "actimeo ignored since acregmax or acdirmax specified\n");
+ break;
+ }
+ ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
+ break;
+ case Opt_closetimeo:
+ ctx->closetimeo = HZ * result.uint_32;
+ if (ctx->closetimeo > SMB3_MAX_DCLOSETIMEO) {
+ cifs_errorf(fc, "closetimeo too large\n");
+ goto cifs_parse_mount_err;
+ }
+ break;
+ case Opt_echo_interval:
+ ctx->echo_interval = result.uint_32;
+ break;
+ case Opt_snapshot:
+ ctx->snapshot_time = result.uint_64;
+ break;
+ case Opt_max_credits:
+ if (result.uint_32 < 20 || result.uint_32 > 60000) {
+ cifs_errorf(fc, "%s: Invalid max_credits value\n",
+ __func__);
+ goto cifs_parse_mount_err;
+ }
+ ctx->max_credits = result.uint_32;
+ break;
+ case Opt_max_channels:
+ if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {
+ cifs_errorf(fc, "%s: Invalid max_channels value, needs to be 1-%d\n",
+ __func__, CIFS_MAX_CHANNELS);
+ goto cifs_parse_mount_err;
+ }
+ ctx->max_channels = result.uint_32;
+ /* If more than one channel requested ... they want multichan */
+ if (result.uint_32 > 1)
+ ctx->multichannel = true;
+ break;
+ case Opt_handletimeout:
+ ctx->handle_timeout = result.uint_32;
+ if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
+ cifs_errorf(fc, "Invalid handle cache timeout, longer than 16 minutes\n");
+ goto cifs_parse_mount_err;
+ }
+ break;
+ case Opt_source:
+ kfree(ctx->UNC);
+ ctx->UNC = NULL;
+ switch (smb3_parse_devname(param->string, ctx)) {
+ case 0:
+ break;
+ case -ENOMEM:
+ cifs_errorf(fc, "Unable to allocate memory for devname\n");
+ goto cifs_parse_mount_err;
+ case -EINVAL:
+ cifs_errorf(fc, "Malformed UNC in devname\n");
+ goto cifs_parse_mount_err;
+ default:
+ cifs_errorf(fc, "Unknown error parsing devname\n");
+ goto cifs_parse_mount_err;
+ }
+ ctx->source = kstrdup(param->string, GFP_KERNEL);
+ if (ctx->source == NULL) {
+ cifs_errorf(fc, "OOM when copying UNC string\n");
+ goto cifs_parse_mount_err;
+ }
+ fc->source = kstrdup(param->string, GFP_KERNEL);
+ if (fc->source == NULL) {
+ cifs_errorf(fc, "OOM when copying UNC string\n");
+ goto cifs_parse_mount_err;
+ }
+ break;
+ case Opt_user:
+ kfree(ctx->username);
+ ctx->username = NULL;
+ if (strlen(param->string) == 0) {
+ /* null user, ie. anonymous authentication */
+ ctx->nullauth = 1;
+ break;
+ }
+
+ if (strnlen(param->string, CIFS_MAX_USERNAME_LEN) >
+ CIFS_MAX_USERNAME_LEN) {
+ pr_warn("username too long\n");
+ goto cifs_parse_mount_err;
+ }
+ ctx->username = kstrdup(param->string, GFP_KERNEL);
+ if (ctx->username == NULL) {
+ cifs_errorf(fc, "OOM when copying username string\n");
+ goto cifs_parse_mount_err;
+ }
+ break;
+ case Opt_pass:
+ kfree_sensitive(ctx->password);
+ ctx->password = NULL;
+ if (strlen(param->string) == 0)
+ break;
+
+ ctx->password = kstrdup(param->string, GFP_KERNEL);
+ if (ctx->password == NULL) {
+ cifs_errorf(fc, "OOM when copying password string\n");
+ goto cifs_parse_mount_err;
+ }
+ break;
+ case Opt_ip:
+ if (strlen(param->string) == 0) {
+ ctx->got_ip = false;
+ break;
+ }
+ if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr,
+ param->string,
+ strlen(param->string))) {
+ pr_err("bad ip= option (%s)\n", param->string);
+ goto cifs_parse_mount_err;
+ }
+ ctx->got_ip = true;
+ break;
+ case Opt_domain:
+ if (strnlen(param->string, CIFS_MAX_DOMAINNAME_LEN)
+ == CIFS_MAX_DOMAINNAME_LEN) {
+ pr_warn("domain name too long\n");
+ goto cifs_parse_mount_err;
+ }
+
+ kfree(ctx->domainname);
+ ctx->domainname = kstrdup(param->string, GFP_KERNEL);
+ if (ctx->domainname == NULL) {
+ cifs_errorf(fc, "OOM when copying domainname string\n");
+ goto cifs_parse_mount_err;
+ }
+ cifs_dbg(FYI, "Domain name set\n");
+ break;
+ case Opt_srcaddr:
+ if (!cifs_convert_address(
+ (struct sockaddr *)&ctx->srcaddr,
+ param->string, strlen(param->string))) {
+ pr_warn("Could not parse srcaddr: %s\n",
+ param->string);
+ goto cifs_parse_mount_err;
+ }
+ break;
+ case Opt_iocharset:
+ if (strnlen(param->string, 1024) >= 65) {
+ pr_warn("iocharset name too long\n");
+ goto cifs_parse_mount_err;
+ }
+
+ if (strncasecmp(param->string, "default", 7) != 0) {
+ kfree(ctx->iocharset);
+ ctx->iocharset = kstrdup(param->string, GFP_KERNEL);
+ if (ctx->iocharset == NULL) {
+ cifs_errorf(fc, "OOM when copying iocharset string\n");
+ goto cifs_parse_mount_err;
+ }
+ }
+ /* if iocharset not set then load_nls_default
+ * is used by caller
+ */
+ cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
+ break;
+ case Opt_netbiosname:
+ memset(ctx->source_rfc1001_name, 0x20,
+ RFC1001_NAME_LEN);
+ /*
+ * FIXME: are there cases in which a comma can
+ * be valid in workstation netbios name (and
+ * need special handling)?
+ */
+ for (i = 0; i < RFC1001_NAME_LEN; i++) {
+ /* don't ucase netbiosname for user */
+ if (param->string[i] == 0)
+ break;
+ ctx->source_rfc1001_name[i] = param->string[i];
+ }
+ /* The string has 16th byte zero still from
+ * set at top of the function
+ */
+ if (i == RFC1001_NAME_LEN && param->string[i] != 0)
+ pr_warn("netbiosname longer than 15 truncated\n");
+ break;
+ case Opt_servern:
+ /* last byte, type, is 0x20 for servr type */
+ memset(ctx->target_rfc1001_name, 0x20,
+ RFC1001_NAME_LEN_WITH_NULL);
+ /*
+ * BB are there cases in which a comma can be valid in this
+ * workstation netbios name (and need special handling)?
+ */
+
+ /* user or mount helper must uppercase the netbios name */
+ for (i = 0; i < 15; i++) {
+ if (param->string[i] == 0)
+ break;
+ ctx->target_rfc1001_name[i] = param->string[i];
+ }
+
+ /* The string has 16th byte zero still from set at top of function */
+ if (i == RFC1001_NAME_LEN && param->string[i] != 0)
+ pr_warn("server netbiosname longer than 15 truncated\n");
+ break;
+ case Opt_ver:
+ /* version of mount userspace tools, not dialect */
+ /* If interface changes in mount.cifs bump to new ver */
+ if (strncasecmp(param->string, "1", 1) == 0) {
+ if (strlen(param->string) > 1) {
+ pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
+ param->string);
+ goto cifs_parse_mount_err;
+ }
+ /* This is the default */
+ break;
+ }
+ /* For all other value, error */
+ pr_warn("Invalid mount helper version specified\n");
+ goto cifs_parse_mount_err;
+ case Opt_vers:
+ /* protocol version (dialect) */
+ if (cifs_parse_smb_version(fc, param->string, ctx, is_smb3) != 0)
+ goto cifs_parse_mount_err;
+ ctx->got_version = true;
+ break;
+ case Opt_sec:
+ if (cifs_parse_security_flavors(fc, param->string, ctx) != 0)
+ goto cifs_parse_mount_err;
+ break;
+ case Opt_cache:
+ if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0)
+ goto cifs_parse_mount_err;
+ break;
+ case Opt_witness:
+#ifndef CONFIG_CIFS_SWN_UPCALL
+ cifs_errorf(fc, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
+ goto cifs_parse_mount_err;
+#endif
+ ctx->witness = true;
+ pr_warn_once("Witness protocol support is experimental\n");
+ break;
+ case Opt_rootfs:
+#ifndef CONFIG_CIFS_ROOT
+ cifs_dbg(VFS, "rootfs support requires CONFIG_CIFS_ROOT config option\n");
+ goto cifs_parse_mount_err;
+#endif
+ ctx->rootfs = true;
+ break;
+ case Opt_posixpaths:
+ if (result.negated)
+ ctx->posix_paths = 0;
+ else
+ ctx->posix_paths = 1;
+ break;
+ case Opt_unix:
+ if (result.negated) {
+ if (ctx->linux_ext == 1)
+ pr_warn_once("conflicting posix mount options specified\n");
+ ctx->linux_ext = 0;
+ ctx->no_linux_ext = 1;
+ } else {
+ if (ctx->no_linux_ext == 1)
+ pr_warn_once("conflicting posix mount options specified\n");
+ ctx->linux_ext = 1;
+ ctx->no_linux_ext = 0;
+ }
+ break;
+ case Opt_nocase:
+ ctx->nocase = 1;
+ break;
+ case Opt_brl:
+ if (result.negated) {
+ /*
+ * turn off mandatory locking in mode
+ * if remote locking is turned off since the
+ * local vfs will do advisory
+ */
+ if (ctx->file_mode ==
+ (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
+ ctx->file_mode = S_IALLUGO;
+ ctx->nobrl = 1;
+ } else
+ ctx->nobrl = 0;
+ break;
+ case Opt_handlecache:
+ if (result.negated)
+ ctx->nohandlecache = 1;
+ else
+ ctx->nohandlecache = 0;
+ break;
+ case Opt_forcemandatorylock:
+ ctx->mand_lock = 1;
+ break;
+ case Opt_setuids:
+ ctx->setuids = result.negated;
+ break;
+ case Opt_intr:
+ ctx->intr = !result.negated;
+ break;
+ case Opt_setuidfromacl:
+ ctx->setuidfromacl = 1;
+ break;
+ case Opt_strictsync:
+ ctx->nostrictsync = result.negated;
+ break;
+ case Opt_serverino:
+ ctx->server_ino = !result.negated;
+ break;
+ case Opt_rwpidforward:
+ ctx->rwpidforward = 1;
+ break;
+ case Opt_modesid:
+ ctx->mode_ace = 1;
+ break;
+ case Opt_cifsacl:
+ ctx->cifs_acl = !result.negated;
+ break;
+ case Opt_acl:
+ ctx->no_psx_acl = result.negated;
+ break;
+ case Opt_locallease:
+ ctx->local_lease = 1;
+ break;
+ case Opt_sign:
+ ctx->sign = true;
+ break;
+ case Opt_ignore_signature:
+ ctx->sign = true;
+ ctx->ignore_signature = true;
+ break;
+ case Opt_seal:
+ /* we do not do the following in secFlags because seal
+ * is a per tree connection (mount) not a per socket
+ * or per-smb connection option in the protocol
+ * vol->secFlg |= CIFSSEC_MUST_SEAL;
+ */
+ ctx->seal = 1;
+ break;
+ case Opt_noac:
+ pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
+ break;
+ case Opt_fsc:
+#ifndef CONFIG_CIFS_FSCACHE
+ cifs_errorf(fc, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
+ goto cifs_parse_mount_err;
+#endif
+ ctx->fsc = true;
+ break;
+ case Opt_mfsymlinks:
+ ctx->mfsymlinks = true;
+ break;
+ case Opt_multiuser:
+ ctx->multiuser = true;
+ break;
+ case Opt_sloppy:
+ ctx->sloppy = true;
+ break;
+ case Opt_nosharesock:
+ ctx->nosharesock = true;
+ break;
+ case Opt_persistent:
+ if (result.negated) {
+ ctx->nopersistent = true;
+ if (ctx->persistent) {
+ cifs_errorf(fc, "persistenthandles mount options conflict\n");
+ goto cifs_parse_mount_err;
+ }
+ } else {
+ ctx->persistent = true;
+ if ((ctx->nopersistent) || (ctx->resilient)) {
+ cifs_errorf(fc, "persistenthandles mount options conflict\n");
+ goto cifs_parse_mount_err;
+ }
+ }
+ break;
+ case Opt_resilient:
+ if (result.negated) {
+ ctx->resilient = false; /* already the default */
+ } else {
+ ctx->resilient = true;
+ if (ctx->persistent) {
+ cifs_errorf(fc, "persistenthandles mount options conflict\n");
+ goto cifs_parse_mount_err;
+ }
+ }
+ break;
+ case Opt_tcp_nodelay:
+ /* tcp nodelay should not usually be needed since we CORK/UNCORK the socket */
+ if (result.negated)
+ ctx->sockopt_tcp_nodelay = false;
+ else
+ ctx->sockopt_tcp_nodelay = true;
+ break;
+ case Opt_domainauto:
+ ctx->domainauto = true;
+ break;
+ case Opt_rdma:
+ ctx->rdma = true;
+ break;
+ }
+ /* case Opt_ignore: - is ignored as expected ... */
+
+ return 0;
+
+ cifs_parse_mount_err:
+ kfree_sensitive(ctx->password);
+ return -EINVAL;
+}
+
+int smb3_init_fs_context(struct fs_context *fc)
+{
+ struct smb3_fs_context *ctx;
+ char *nodename = utsname()->nodename;
+ int i;
+
+ ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
+ if (unlikely(!ctx))
+ return -ENOMEM;
+
+ strscpy(ctx->workstation_name, nodename, sizeof(ctx->workstation_name));
+
+ /*
+ * does not have to be perfect mapping since field is
+ * informational, only used for servers that do not support
+ * port 445 and it can be overridden at mount time
+ */
+ memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
+ for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
+ ctx->source_rfc1001_name[i] = toupper(nodename[i]);
+
+ ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
+ /*
+ * null target name indicates to use *SMBSERVR default called name
+ * if we end up sending RFC1001 session initialize
+ */
+ ctx->target_rfc1001_name[0] = 0;
+ ctx->cred_uid = current_uid();
+ ctx->linux_uid = current_uid();
+ ctx->linux_gid = current_gid();
+ /* By default 4MB read ahead size, 1MB block size */
+ ctx->bsize = CIFS_DEFAULT_IOSIZE; /* can improve cp performance significantly */
+ ctx->rasize = 0; /* 0 = use default (ie negotiated rsize) for read ahead pages */
+
+ /*
+ * default to SFM style remapping of seven reserved characters
+ * unless user overrides it or we negotiate CIFS POSIX where
+ * it is unnecessary. Can not simultaneously use more than one mapping
+ * since then readdir could list files that open could not open
+ */
+ ctx->remap = true;
+
+ /* default to only allowing write access to owner of the mount */
+ ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
+
+ /* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
+ /* default is always to request posix paths. */
+ ctx->posix_paths = 1;
+ /* default to using server inode numbers where available */
+ ctx->server_ino = 1;
+
+ /* default is to use strict cifs caching semantics */
+ ctx->strict_io = true;
+
+ ctx->acregmax = CIFS_DEF_ACTIMEO;
+ ctx->acdirmax = CIFS_DEF_ACTIMEO;
+ ctx->closetimeo = SMB3_DEF_DCLOSETIMEO;
+
+ /* Most clients set timeout to 0, allows server to use its default */
+ ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
+
+ /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
+ ctx->ops = &smb30_operations;
+ ctx->vals = &smbdefault_values;
+
+ ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
+
+ /* default to no multichannel (single server connection) */
+ ctx->multichannel = false;
+ ctx->max_channels = 1;
+
+ ctx->backupuid_specified = false; /* no backup intent for a user */
+ ctx->backupgid_specified = false; /* no backup intent for a group */
+
+/*
+ * short int override_uid = -1;
+ * short int override_gid = -1;
+ * char *nodename = strdup(utsname()->nodename);
+ * struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
+ */
+
+ fc->fs_private = ctx;
+ fc->ops = &smb3_fs_context_ops;
+ return 0;
+}
+
+void
+smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ /*
+ * Make sure this stays in sync with smb3_fs_context_dup()
+ */
+ kfree(ctx->mount_options);
+ ctx->mount_options = NULL;
+ kfree(ctx->username);
+ ctx->username = NULL;
+ kfree_sensitive(ctx->password);
+ ctx->password = NULL;
+ kfree(ctx->server_hostname);
+ ctx->server_hostname = NULL;
+ kfree(ctx->UNC);
+ ctx->UNC = NULL;
+ kfree(ctx->source);
+ ctx->source = NULL;
+ kfree(ctx->domainname);
+ ctx->domainname = NULL;
+ kfree(ctx->nodename);
+ ctx->nodename = NULL;
+ kfree(ctx->iocharset);
+ ctx->iocharset = NULL;
+ kfree(ctx->prepath);
+ ctx->prepath = NULL;
+}
+
+void
+smb3_cleanup_fs_context(struct smb3_fs_context *ctx)
+{
+ if (!ctx)
+ return;
+ smb3_cleanup_fs_context_contents(ctx);
+ kfree(ctx);
+}
+
+void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
+{
+ struct smb3_fs_context *ctx = cifs_sb->ctx;
+
+ if (ctx->nodfs)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS;
+
+ if (ctx->noperm)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM;
+
+ if (ctx->setuids)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID;
+
+ if (ctx->setuidfromacl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL;
+
+ if (ctx->server_ino)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
+
+ if (ctx->remap)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR;
+
+ if (ctx->sfu_remap)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
+
+ if (ctx->no_xattr)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR;
+
+ if (ctx->sfu_emul)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL;
+
+ if (ctx->nobrl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL;
+
+ if (ctx->nohandlecache)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
+
+ if (ctx->nostrictsync)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC;
+
+ if (ctx->mand_lock)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL;
+
+ if (ctx->rwpidforward)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD;
+
+ if (ctx->mode_ace)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID;
+
+ if (ctx->cifs_acl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL;
+
+ if (ctx->backupuid_specified)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
+
+ if (ctx->backupgid_specified)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
+
+ if (ctx->override_uid)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID;
+
+ if (ctx->override_gid)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID;
+
+ if (ctx->dynperm)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM;
+
+ if (ctx->fsc)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE;
+
+ if (ctx->multiuser)
+ cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
+ CIFS_MOUNT_NO_PERM);
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MULTIUSER;
+
+
+ if (ctx->strict_io)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO;
+
+ if (ctx->direct_io)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO;
+
+ if (ctx->mfsymlinks)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
+ else
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS;
+ if (ctx->mfsymlinks) {
+ if (ctx->sfu_emul) {
+ /*
+ * Our SFU ("Services for Unix" emulation does not allow
+ * creating symlinks but does allow reading existing SFU
+ * symlinks (it does allow both creating and reading SFU
+ * style mknod and FIFOs though). When "mfsymlinks" and
+ * "sfu" are both enabled at the same time, it allows
+ * reading both types of symlinks, but will only create
+ * them with mfsymlinks format. This allows better
+ * Apple compatibility (probably better for Samba too)
+ * while still recognizing old Windows style symlinks.
+ */
+ cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
+ }
+ }
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SHUTDOWN;
+
+ return;
+}
diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
new file mode 100644
index 000000000000..26093f54d3e6
--- /dev/null
+++ b/fs/smb/client/fs_context.h
@@ -0,0 +1,293 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020, Microsoft Corporation.
+ *
+ * Author(s): Steve French <stfrench@microsoft.com>
+ * David Howells <dhowells@redhat.com>
+ */
+
+#ifndef _FS_CONTEXT_H
+#define _FS_CONTEXT_H
+
+#include "cifsglob.h"
+#include <linux/parser.h>
+#include <linux/fs_parser.h>
+
+/* Log errors in fs_context (new mount api) but also in dmesg (old style) */
+#define cifs_errorf(fc, fmt, ...) \
+ do { \
+ errorf(fc, fmt, ## __VA_ARGS__); \
+ cifs_dbg(VFS, fmt, ## __VA_ARGS__); \
+ } while (0)
+
+enum smb_version {
+ Smb_1 = 1,
+ Smb_20,
+ Smb_21,
+ Smb_30,
+ Smb_302,
+ Smb_311,
+ Smb_3any,
+ Smb_default,
+ Smb_version_err
+};
+
+enum {
+ Opt_cache_loose,
+ Opt_cache_strict,
+ Opt_cache_none,
+ Opt_cache_ro,
+ Opt_cache_rw,
+ Opt_cache_err
+};
+
+enum cifs_sec_param {
+ Opt_sec_krb5,
+ Opt_sec_krb5i,
+ Opt_sec_krb5p,
+ Opt_sec_ntlmsspi,
+ Opt_sec_ntlmssp,
+ Opt_sec_ntlmv2,
+ Opt_sec_ntlmv2i,
+ Opt_sec_none,
+
+ Opt_sec_err
+};
+
+enum cifs_param {
+ /* Mount options that take no arguments */
+ Opt_user_xattr,
+ Opt_forceuid,
+ Opt_forcegid,
+ Opt_noblocksend,
+ Opt_noautotune,
+ Opt_nolease,
+ Opt_nosparse,
+ Opt_hard,
+ Opt_soft,
+ Opt_perm,
+ Opt_nodelete,
+ Opt_mapposix,
+ Opt_mapchars,
+ Opt_nomapchars,
+ Opt_sfu,
+ Opt_nodfs,
+ Opt_posixpaths,
+ Opt_unix,
+ Opt_nocase,
+ Opt_brl,
+ Opt_handlecache,
+ Opt_forcemandatorylock,
+ Opt_setuidfromacl,
+ Opt_setuids,
+ Opt_dynperm,
+ Opt_intr,
+ Opt_strictsync,
+ Opt_serverino,
+ Opt_rwpidforward,
+ Opt_cifsacl,
+ Opt_acl,
+ Opt_locallease,
+ Opt_sign,
+ Opt_ignore_signature,
+ Opt_seal,
+ Opt_noac,
+ Opt_fsc,
+ Opt_mfsymlinks,
+ Opt_multiuser,
+ Opt_sloppy,
+ Opt_nosharesock,
+ Opt_persistent,
+ Opt_resilient,
+ Opt_tcp_nodelay,
+ Opt_domainauto,
+ Opt_rdma,
+ Opt_modesid,
+ Opt_rootfs,
+ Opt_multichannel,
+ Opt_compress,
+ Opt_witness,
+
+ /* Mount options which take numeric value */
+ Opt_backupuid,
+ Opt_backupgid,
+ Opt_uid,
+ Opt_cruid,
+ Opt_gid,
+ Opt_port,
+ Opt_file_mode,
+ Opt_dirmode,
+ Opt_min_enc_offload,
+ Opt_blocksize,
+ Opt_rasize,
+ Opt_rsize,
+ Opt_wsize,
+ Opt_actimeo,
+ Opt_acdirmax,
+ Opt_acregmax,
+ Opt_closetimeo,
+ Opt_echo_interval,
+ Opt_max_credits,
+ Opt_snapshot,
+ Opt_max_channels,
+ Opt_handletimeout,
+
+ /* Mount options which take string value */
+ Opt_source,
+ Opt_user,
+ Opt_pass,
+ Opt_ip,
+ Opt_domain,
+ Opt_srcaddr,
+ Opt_iocharset,
+ Opt_netbiosname,
+ Opt_servern,
+ Opt_ver,
+ Opt_vers,
+ Opt_sec,
+ Opt_cache,
+
+ /* Mount options to be ignored */
+ Opt_ignore,
+
+ Opt_err
+};
+
+struct smb3_fs_context {
+ bool uid_specified;
+ bool cruid_specified;
+ bool gid_specified;
+ bool sloppy;
+ bool got_ip;
+ bool got_version;
+ bool got_rsize;
+ bool got_wsize;
+ bool got_bsize;
+ unsigned short port;
+
+ char *username;
+ char *password;
+ char *domainname;
+ char *source;
+ char *server_hostname;
+ char *UNC;
+ char *nodename;
+ char workstation_name[CIFS_MAX_WORKSTATION_LEN];
+ char *iocharset; /* local code page for mapping to and from Unicode */
+ char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
+ char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
+ kuid_t cred_uid;
+ kuid_t linux_uid;
+ kgid_t linux_gid;
+ kuid_t backupuid;
+ kgid_t backupgid;
+ umode_t file_mode;
+ umode_t dir_mode;
+ enum securityEnum sectype; /* sectype requested via mnt opts */
+ bool sign; /* was signing requested via mnt opts? */
+ bool ignore_signature:1;
+ bool retry:1;
+ bool intr:1;
+ bool setuids:1;
+ bool setuidfromacl:1;
+ bool override_uid:1;
+ bool override_gid:1;
+ bool dynperm:1;
+ bool noperm:1;
+ bool nodelete:1;
+ bool mode_ace:1;
+ bool no_psx_acl:1; /* set if posix acl support should be disabled */
+ bool cifs_acl:1;
+ bool backupuid_specified; /* mount option backupuid is specified */
+ bool backupgid_specified; /* mount option backupgid is specified */
+ bool no_xattr:1; /* set if xattr (EA) support should be disabled*/
+ bool server_ino:1; /* use inode numbers from server ie UniqueId */
+ bool direct_io:1;
+ bool strict_io:1; /* strict cache behavior */
+ bool cache_ro:1;
+ bool cache_rw:1;
+ bool remap:1; /* set to remap seven reserved chars in filenames */
+ bool sfu_remap:1; /* remap seven reserved chars ala SFU */
+ bool posix_paths:1; /* unset to not ask for posix pathnames. */
+ bool no_linux_ext:1;
+ bool linux_ext:1;
+ bool sfu_emul:1;
+ bool nullauth:1; /* attempt to authenticate with null user */
+ bool nocase:1; /* request case insensitive filenames */
+ bool nobrl:1; /* disable sending byte range locks to srv */
+ bool nohandlecache:1; /* disable caching dir handles if srvr probs */
+ bool mand_lock:1; /* send mandatory not posix byte range lock reqs */
+ bool seal:1; /* request transport encryption on share */
+ bool nodfs:1; /* Do not request DFS, even if available */
+ bool local_lease:1; /* check leases only on local system, not remote */
+ bool noblocksnd:1;
+ bool noautotune:1;
+ bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
+ bool no_lease:1; /* disable requesting leases */
+ bool no_sparse:1; /* do not attempt to set files sparse */
+ bool fsc:1; /* enable fscache */
+ bool mfsymlinks:1; /* use Minshall+French Symlinks */
+ bool multiuser:1;
+ bool rwpidforward:1; /* pid forward for read/write operations */
+ bool nosharesock:1;
+ bool persistent:1;
+ bool nopersistent:1;
+ bool resilient:1; /* noresilient not required since not fored for CA */
+ bool domainauto:1;
+ bool rdma:1;
+ bool multichannel:1;
+ bool use_client_guid:1;
+ /* reuse existing guid for multichannel */
+ u8 client_guid[SMB2_CLIENT_GUID_SIZE];
+ unsigned int bsize;
+ unsigned int rasize;
+ unsigned int rsize;
+ unsigned int wsize;
+ unsigned int min_offload;
+ bool sockopt_tcp_nodelay:1;
+ /* attribute cache timemout for files and directories in jiffies */
+ unsigned long acregmax;
+ unsigned long acdirmax;
+ /* timeout for deferred close of files in jiffies */
+ unsigned long closetimeo;
+ struct smb_version_operations *ops;
+ struct smb_version_values *vals;
+ char *prepath;
+ struct sockaddr_storage dstaddr; /* destination address */
+ struct sockaddr_storage srcaddr; /* allow binding to a local IP */
+ struct nls_table *local_nls; /* This is a copy of the pointer in cifs_sb */
+ unsigned int echo_interval; /* echo interval in secs */
+ __u64 snapshot_time; /* needed for timewarp tokens */
+ __u32 handle_timeout; /* persistent and durable handle timeout in ms */
+ unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
+ unsigned int max_channels;
+ __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
+ bool rootfs:1; /* if it's a SMB root file system */
+ bool witness:1; /* use witness protocol */
+
+ char *mount_options;
+};
+
+extern const struct fs_parameter_spec smb3_fs_parameters[];
+
+extern int smb3_init_fs_context(struct fs_context *fc);
+extern void smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx);
+extern void smb3_cleanup_fs_context(struct smb3_fs_context *ctx);
+
+static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *fc)
+{
+ return fc->fs_private;
+}
+
+extern int smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx);
+extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
+
+/*
+ * max deferred close timeout (jiffies) - 2^30
+ */
+#define SMB3_MAX_DCLOSETIMEO (1 << 30)
+#define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */
+
+extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp);
+
+#endif
diff --git a/fs/smb/client/fscache.c b/fs/smb/client/fscache.c
new file mode 100644
index 000000000000..f6f3a6b75601
--- /dev/null
+++ b/fs/smb/client/fscache.c
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * CIFS filesystem cache interface
+ *
+ * Copyright (c) 2010 Novell, Inc.
+ * Author(s): Suresh Jayaraman <sjayaraman@suse.de>
+ *
+ */
+#include "fscache.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifsproto.h"
+
+static void cifs_fscache_fill_volume_coherency(
+ struct cifs_tcon *tcon,
+ struct cifs_fscache_volume_coherency_data *cd)
+{
+ memset(cd, 0, sizeof(*cd));
+ cd->resource_id = cpu_to_le64(tcon->resource_id);
+ cd->vol_create_time = tcon->vol_create_time;
+ cd->vol_serial_number = cpu_to_le32(tcon->vol_serial_number);
+}
+
+int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
+{
+ struct cifs_fscache_volume_coherency_data cd;
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct fscache_volume *vcookie;
+ const struct sockaddr *sa = (struct sockaddr *)&server->dstaddr;
+ size_t slen, i;
+ char *sharename;
+ char *key;
+ int ret = -ENOMEM;
+
+ tcon->fscache = NULL;
+ switch (sa->sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ break;
+ default:
+ cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
+ return -EINVAL;
+ }
+
+ memset(&key, 0, sizeof(key));
+
+ sharename = extract_sharename(tcon->tree_name);
+ if (IS_ERR(sharename)) {
+ cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
+ return -EINVAL;
+ }
+
+ slen = strlen(sharename);
+ for (i = 0; i < slen; i++)
+ if (sharename[i] == '/')
+ sharename[i] = ';';
+
+ key = kasprintf(GFP_KERNEL, "cifs,%pISpc,%s", sa, sharename);
+ if (!key)
+ goto out;
+
+ cifs_fscache_fill_volume_coherency(tcon, &cd);
+ vcookie = fscache_acquire_volume(key,
+ NULL, /* preferred_cache */
+ &cd, sizeof(cd));
+ cifs_dbg(FYI, "%s: (%s/0x%p)\n", __func__, key, vcookie);
+ if (IS_ERR(vcookie)) {
+ if (vcookie != ERR_PTR(-EBUSY)) {
+ ret = PTR_ERR(vcookie);
+ goto out_2;
+ }
+ pr_err("Cache volume key already in use (%s)\n", key);
+ vcookie = NULL;
+ }
+
+ tcon->fscache = vcookie;
+ ret = 0;
+out_2:
+ kfree(key);
+out:
+ kfree(sharename);
+ return ret;
+}
+
+void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
+{
+ struct cifs_fscache_volume_coherency_data cd;
+
+ cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
+
+ cifs_fscache_fill_volume_coherency(tcon, &cd);
+ fscache_relinquish_volume(tcon->fscache, &cd, false);
+ tcon->fscache = NULL;
+}
+
+void cifs_fscache_get_inode_cookie(struct inode *inode)
+{
+ struct cifs_fscache_inode_coherency_data cd;
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+
+ cifs_fscache_fill_coherency(&cifsi->netfs.inode, &cd);
+
+ cifsi->netfs.cache =
+ fscache_acquire_cookie(tcon->fscache, 0,
+ &cifsi->uniqueid, sizeof(cifsi->uniqueid),
+ &cd, sizeof(cd),
+ i_size_read(&cifsi->netfs.inode));
+}
+
+void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update)
+{
+ if (update) {
+ struct cifs_fscache_inode_coherency_data cd;
+ loff_t i_size = i_size_read(inode);
+
+ cifs_fscache_fill_coherency(inode, &cd);
+ fscache_unuse_cookie(cifs_inode_cookie(inode), &cd, &i_size);
+ } else {
+ fscache_unuse_cookie(cifs_inode_cookie(inode), NULL, NULL);
+ }
+}
+
+void cifs_fscache_release_inode_cookie(struct inode *inode)
+{
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct fscache_cookie *cookie = cifs_inode_cookie(inode);
+
+ if (cookie) {
+ cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cookie);
+ fscache_relinquish_cookie(cookie, false);
+ cifsi->netfs.cache = NULL;
+ }
+}
+
+/*
+ * Fallback page reading interface.
+ */
+static int fscache_fallback_read_page(struct inode *inode, struct page *page)
+{
+ struct netfs_cache_resources cres;
+ struct fscache_cookie *cookie = cifs_inode_cookie(inode);
+ struct iov_iter iter;
+ struct bio_vec bvec[1];
+ int ret;
+
+ memset(&cres, 0, sizeof(cres));
+ bvec[0].bv_page = page;
+ bvec[0].bv_offset = 0;
+ bvec[0].bv_len = PAGE_SIZE;
+ iov_iter_bvec(&iter, ITER_DEST, bvec, ARRAY_SIZE(bvec), PAGE_SIZE);
+
+ ret = fscache_begin_read_operation(&cres, cookie);
+ if (ret < 0)
+ return ret;
+
+ ret = fscache_read(&cres, page_offset(page), &iter, NETFS_READ_HOLE_FAIL,
+ NULL, NULL);
+ fscache_end_operation(&cres);
+ return ret;
+}
+
+/*
+ * Fallback page writing interface.
+ */
+static int fscache_fallback_write_page(struct inode *inode, struct page *page,
+ bool no_space_allocated_yet)
+{
+ struct netfs_cache_resources cres;
+ struct fscache_cookie *cookie = cifs_inode_cookie(inode);
+ struct iov_iter iter;
+ struct bio_vec bvec[1];
+ loff_t start = page_offset(page);
+ size_t len = PAGE_SIZE;
+ int ret;
+
+ memset(&cres, 0, sizeof(cres));
+ bvec[0].bv_page = page;
+ bvec[0].bv_offset = 0;
+ bvec[0].bv_len = PAGE_SIZE;
+ iov_iter_bvec(&iter, ITER_SOURCE, bvec, ARRAY_SIZE(bvec), PAGE_SIZE);
+
+ ret = fscache_begin_write_operation(&cres, cookie);
+ if (ret < 0)
+ return ret;
+
+ ret = cres.ops->prepare_write(&cres, &start, &len, i_size_read(inode),
+ no_space_allocated_yet);
+ if (ret == 0)
+ ret = fscache_write(&cres, page_offset(page), &iter, NULL, NULL);
+ fscache_end_operation(&cres);
+ return ret;
+}
+
+/*
+ * Retrieve a page from FS-Cache
+ */
+int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
+{
+ int ret;
+
+ cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n",
+ __func__, cifs_inode_cookie(inode), page, inode);
+
+ ret = fscache_fallback_read_page(inode, page);
+ if (ret < 0)
+ return ret;
+
+ /* Read completed synchronously */
+ SetPageUptodate(page);
+ return 0;
+}
+
+void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
+{
+ cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
+ __func__, cifs_inode_cookie(inode), page, inode);
+
+ fscache_fallback_write_page(inode, page, true);
+}
+
+/*
+ * Query the cache occupancy.
+ */
+int __cifs_fscache_query_occupancy(struct inode *inode,
+ pgoff_t first, unsigned int nr_pages,
+ pgoff_t *_data_first,
+ unsigned int *_data_nr_pages)
+{
+ struct netfs_cache_resources cres;
+ struct fscache_cookie *cookie = cifs_inode_cookie(inode);
+ loff_t start, data_start;
+ size_t len, data_len;
+ int ret;
+
+ ret = fscache_begin_read_operation(&cres, cookie);
+ if (ret < 0)
+ return ret;
+
+ start = first * PAGE_SIZE;
+ len = nr_pages * PAGE_SIZE;
+ ret = cres.ops->query_occupancy(&cres, start, len, PAGE_SIZE,
+ &data_start, &data_len);
+ if (ret == 0) {
+ *_data_first = data_start / PAGE_SIZE;
+ *_data_nr_pages = len / PAGE_SIZE;
+ }
+
+ fscache_end_operation(&cres);
+ return ret;
+}
diff --git a/fs/smb/client/fscache.h b/fs/smb/client/fscache.h
new file mode 100644
index 000000000000..67b601041f0a
--- /dev/null
+++ b/fs/smb/client/fscache.h
@@ -0,0 +1,148 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ * CIFS filesystem cache interface definitions
+ *
+ * Copyright (c) 2010 Novell, Inc.
+ * Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
+ *
+ */
+#ifndef _CIFS_FSCACHE_H
+#define _CIFS_FSCACHE_H
+
+#include <linux/swap.h>
+#include <linux/fscache.h>
+
+#include "cifsglob.h"
+
+/*
+ * Coherency data attached to CIFS volume within the cache
+ */
+struct cifs_fscache_volume_coherency_data {
+ __le64 resource_id; /* unique server resource id */
+ __le64 vol_create_time;
+ __le32 vol_serial_number;
+} __packed;
+
+/*
+ * Coherency data attached to CIFS inode within the cache.
+ */
+struct cifs_fscache_inode_coherency_data {
+ __le64 last_write_time_sec;
+ __le64 last_change_time_sec;
+ __le32 last_write_time_nsec;
+ __le32 last_change_time_nsec;
+};
+
+#ifdef CONFIG_CIFS_FSCACHE
+
+/*
+ * fscache.c
+ */
+extern int cifs_fscache_get_super_cookie(struct cifs_tcon *);
+extern void cifs_fscache_release_super_cookie(struct cifs_tcon *);
+
+extern void cifs_fscache_get_inode_cookie(struct inode *inode);
+extern void cifs_fscache_release_inode_cookie(struct inode *);
+extern void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update);
+
+static inline
+void cifs_fscache_fill_coherency(struct inode *inode,
+ struct cifs_fscache_inode_coherency_data *cd)
+{
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+
+ memset(cd, 0, sizeof(*cd));
+ cd->last_write_time_sec = cpu_to_le64(cifsi->netfs.inode.i_mtime.tv_sec);
+ cd->last_write_time_nsec = cpu_to_le32(cifsi->netfs.inode.i_mtime.tv_nsec);
+ cd->last_change_time_sec = cpu_to_le64(cifsi->netfs.inode.i_ctime.tv_sec);
+ cd->last_change_time_nsec = cpu_to_le32(cifsi->netfs.inode.i_ctime.tv_nsec);
+}
+
+
+static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode)
+{
+ return netfs_i_cookie(&CIFS_I(inode)->netfs);
+}
+
+static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags)
+{
+ struct cifs_fscache_inode_coherency_data cd;
+
+ cifs_fscache_fill_coherency(inode, &cd);
+ fscache_invalidate(cifs_inode_cookie(inode), &cd,
+ i_size_read(inode), flags);
+}
+
+extern int __cifs_fscache_query_occupancy(struct inode *inode,
+ pgoff_t first, unsigned int nr_pages,
+ pgoff_t *_data_first,
+ unsigned int *_data_nr_pages);
+
+static inline int cifs_fscache_query_occupancy(struct inode *inode,
+ pgoff_t first, unsigned int nr_pages,
+ pgoff_t *_data_first,
+ unsigned int *_data_nr_pages)
+{
+ if (!cifs_inode_cookie(inode))
+ return -ENOBUFS;
+ return __cifs_fscache_query_occupancy(inode, first, nr_pages,
+ _data_first, _data_nr_pages);
+}
+
+extern int __cifs_readpage_from_fscache(struct inode *pinode, struct page *ppage);
+extern void __cifs_readpage_to_fscache(struct inode *pinode, struct page *ppage);
+
+
+static inline int cifs_readpage_from_fscache(struct inode *inode,
+ struct page *page)
+{
+ if (cifs_inode_cookie(inode))
+ return __cifs_readpage_from_fscache(inode, page);
+ return -ENOBUFS;
+}
+
+static inline void cifs_readpage_to_fscache(struct inode *inode,
+ struct page *page)
+{
+ if (cifs_inode_cookie(inode))
+ __cifs_readpage_to_fscache(inode, page);
+}
+
+#else /* CONFIG_CIFS_FSCACHE */
+static inline
+void cifs_fscache_fill_coherency(struct inode *inode,
+ struct cifs_fscache_inode_coherency_data *cd)
+{
+}
+
+static inline int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) { return 0; }
+static inline void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {}
+
+static inline void cifs_fscache_get_inode_cookie(struct inode *inode) {}
+static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
+static inline void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update) {}
+static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { return NULL; }
+static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {}
+
+static inline int cifs_fscache_query_occupancy(struct inode *inode,
+ pgoff_t first, unsigned int nr_pages,
+ pgoff_t *_data_first,
+ unsigned int *_data_nr_pages)
+{
+ *_data_first = ULONG_MAX;
+ *_data_nr_pages = 0;
+ return -ENOBUFS;
+}
+
+static inline int
+cifs_readpage_from_fscache(struct inode *inode, struct page *page)
+{
+ return -ENOBUFS;
+}
+
+static inline
+void cifs_readpage_to_fscache(struct inode *inode, struct page *page) {}
+
+#endif /* CONFIG_CIFS_FSCACHE */
+
+#endif /* _CIFS_FSCACHE_H */
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
new file mode 100644
index 000000000000..92c1ed9304be
--- /dev/null
+++ b/fs/smb/client/inode.c
@@ -0,0 +1,3093 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2010
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/freezer.h>
+#include <linux/sched/signal.h>
+#include <linux/wait_bit.h>
+#include <linux/fiemap.h>
+#include <asm/div64.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifs_unicode.h"
+#include "fscache.h"
+#include "fs_context.h"
+#include "cifs_ioctl.h"
+#include "cached_dir.h"
+
+static void cifs_set_ops(struct inode *inode)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
+ inode->i_op = &cifs_file_inode_ops;
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+ inode->i_fop = &cifs_file_direct_nobrl_ops;
+ else
+ inode->i_fop = &cifs_file_direct_ops;
+ } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+ inode->i_fop = &cifs_file_strict_nobrl_ops;
+ else
+ inode->i_fop = &cifs_file_strict_ops;
+ } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+ inode->i_fop = &cifs_file_nobrl_ops;
+ else { /* not direct, send byte range locks */
+ inode->i_fop = &cifs_file_ops;
+ }
+
+ /* check if server can support readahead */
+ if (cifs_sb_master_tcon(cifs_sb)->ses->server->max_read <
+ PAGE_SIZE + MAX_CIFS_HDR_SIZE)
+ inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
+ else
+ inode->i_data.a_ops = &cifs_addr_ops;
+ break;
+ case S_IFDIR:
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ if (IS_AUTOMOUNT(inode)) {
+ inode->i_op = &cifs_dfs_referral_inode_operations;
+ } else {
+#else /* NO DFS support, treat as a directory */
+ {
+#endif
+ inode->i_op = &cifs_dir_inode_ops;
+ inode->i_fop = &cifs_dir_ops;
+ }
+ break;
+ case S_IFLNK:
+ inode->i_op = &cifs_symlink_inode_ops;
+ break;
+ default:
+ init_special_inode(inode, inode->i_mode, inode->i_rdev);
+ break;
+ }
+}
+
+/* check inode attributes against fattr. If they don't match, tag the
+ * inode for cache invalidation
+ */
+static void
+cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
+{
+ struct cifs_fscache_inode_coherency_data cd;
+ struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+
+ cifs_dbg(FYI, "%s: revalidating inode %llu\n",
+ __func__, cifs_i->uniqueid);
+
+ if (inode->i_state & I_NEW) {
+ cifs_dbg(FYI, "%s: inode %llu is new\n",
+ __func__, cifs_i->uniqueid);
+ return;
+ }
+
+ /* don't bother with revalidation if we have an oplock */
+ if (CIFS_CACHE_READ(cifs_i)) {
+ cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
+ __func__, cifs_i->uniqueid);
+ return;
+ }
+
+ /* revalidate if mtime or size have changed */
+ fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
+ if (timespec64_equal(&inode->i_mtime, &fattr->cf_mtime) &&
+ cifs_i->server_eof == fattr->cf_eof) {
+ cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
+ __func__, cifs_i->uniqueid);
+ return;
+ }
+
+ cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
+ __func__, cifs_i->uniqueid);
+ set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
+ /* Invalidate fscache cookie */
+ cifs_fscache_fill_coherency(&cifs_i->netfs.inode, &cd);
+ fscache_invalidate(cifs_inode_cookie(inode), &cd, i_size_read(inode), 0);
+}
+
+/*
+ * copy nlink to the inode, unless it wasn't provided. Provide
+ * sane values if we don't have an existing one and none was provided
+ */
+static void
+cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
+{
+ /*
+ * if we're in a situation where we can't trust what we
+ * got from the server (readdir, some non-unix cases)
+ * fake reasonable values
+ */
+ if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
+ /* only provide fake values on a new inode */
+ if (inode->i_state & I_NEW) {
+ if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
+ set_nlink(inode, 2);
+ else
+ set_nlink(inode, 1);
+ }
+ return;
+ }
+
+ /* we trust the server, so update it */
+ set_nlink(inode, fattr->cf_nlink);
+}
+
+/* populate an inode with info from a cifs_fattr struct */
+int
+cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
+{
+ struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+ if (!(inode->i_state & I_NEW) &&
+ unlikely(inode_wrong_type(inode, fattr->cf_mode))) {
+ CIFS_I(inode)->time = 0; /* force reval */
+ return -ESTALE;
+ }
+
+ cifs_revalidate_cache(inode, fattr);
+
+ spin_lock(&inode->i_lock);
+ fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
+ fattr->cf_atime = timestamp_truncate(fattr->cf_atime, inode);
+ fattr->cf_ctime = timestamp_truncate(fattr->cf_ctime, inode);
+ /* we do not want atime to be less than mtime, it broke some apps */
+ if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime) < 0)
+ inode->i_atime = fattr->cf_mtime;
+ else
+ inode->i_atime = fattr->cf_atime;
+ inode->i_mtime = fattr->cf_mtime;
+ inode->i_ctime = fattr->cf_ctime;
+ inode->i_rdev = fattr->cf_rdev;
+ cifs_nlink_fattr_to_inode(inode, fattr);
+ inode->i_uid = fattr->cf_uid;
+ inode->i_gid = fattr->cf_gid;
+
+ /* if dynperm is set, don't clobber existing mode */
+ if (inode->i_state & I_NEW ||
+ !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
+ inode->i_mode = fattr->cf_mode;
+
+ cifs_i->cifsAttrs = fattr->cf_cifsattrs;
+
+ if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
+ cifs_i->time = 0;
+ else
+ cifs_i->time = jiffies;
+
+ if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
+ set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
+ else
+ clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
+
+ cifs_i->server_eof = fattr->cf_eof;
+ /*
+ * Can't safely change the file size here if the client is writing to
+ * it due to potential races.
+ */
+ if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
+ i_size_write(inode, fattr->cf_eof);
+
+ /*
+ * i_blocks is not related to (i_size / i_blksize),
+ * but instead 512 byte (2**9) size is required for
+ * calculating num blocks.
+ */
+ inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
+ }
+
+ if (S_ISLNK(fattr->cf_mode)) {
+ kfree(cifs_i->symlink_target);
+ cifs_i->symlink_target = fattr->cf_symlink_target;
+ fattr->cf_symlink_target = NULL;
+ }
+ spin_unlock(&inode->i_lock);
+
+ if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
+ inode->i_flags |= S_AUTOMOUNT;
+ if (inode->i_state & I_NEW)
+ cifs_set_ops(inode);
+ return 0;
+}
+
+void
+cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+ return;
+
+ fattr->cf_uniqueid = iunique(sb, ROOT_I);
+}
+
+/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
+void
+cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
+ struct cifs_sb_info *cifs_sb)
+{
+ memset(fattr, 0, sizeof(*fattr));
+ fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
+ fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
+ fattr->cf_eof = le64_to_cpu(info->EndOfFile);
+
+ fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+ fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
+ fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
+ /* old POSIX extensions don't get create time */
+
+ fattr->cf_mode = le64_to_cpu(info->Permissions);
+
+ /*
+ * Since we set the inode type below we need to mask off
+ * to avoid strange results if bits set above.
+ */
+ fattr->cf_mode &= ~S_IFMT;
+ switch (le32_to_cpu(info->Type)) {
+ case UNIX_FILE:
+ fattr->cf_mode |= S_IFREG;
+ fattr->cf_dtype = DT_REG;
+ break;
+ case UNIX_SYMLINK:
+ fattr->cf_mode |= S_IFLNK;
+ fattr->cf_dtype = DT_LNK;
+ break;
+ case UNIX_DIR:
+ fattr->cf_mode |= S_IFDIR;
+ fattr->cf_dtype = DT_DIR;
+ break;
+ case UNIX_CHARDEV:
+ fattr->cf_mode |= S_IFCHR;
+ fattr->cf_dtype = DT_CHR;
+ fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+ le64_to_cpu(info->DevMinor) & MINORMASK);
+ break;
+ case UNIX_BLOCKDEV:
+ fattr->cf_mode |= S_IFBLK;
+ fattr->cf_dtype = DT_BLK;
+ fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+ le64_to_cpu(info->DevMinor) & MINORMASK);
+ break;
+ case UNIX_FIFO:
+ fattr->cf_mode |= S_IFIFO;
+ fattr->cf_dtype = DT_FIFO;
+ break;
+ case UNIX_SOCKET:
+ fattr->cf_mode |= S_IFSOCK;
+ fattr->cf_dtype = DT_SOCK;
+ break;
+ default:
+ /* safest to call it a file if we do not know */
+ fattr->cf_mode |= S_IFREG;
+ fattr->cf_dtype = DT_REG;
+ cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
+ break;
+ }
+
+ fattr->cf_uid = cifs_sb->ctx->linux_uid;
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
+ u64 id = le64_to_cpu(info->Uid);
+ if (id < ((uid_t)-1)) {
+ kuid_t uid = make_kuid(&init_user_ns, id);
+ if (uid_valid(uid))
+ fattr->cf_uid = uid;
+ }
+ }
+
+ fattr->cf_gid = cifs_sb->ctx->linux_gid;
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
+ u64 id = le64_to_cpu(info->Gid);
+ if (id < ((gid_t)-1)) {
+ kgid_t gid = make_kgid(&init_user_ns, id);
+ if (gid_valid(gid))
+ fattr->cf_gid = gid;
+ }
+ }
+
+ fattr->cf_nlink = le64_to_cpu(info->Nlinks);
+}
+
+/*
+ * Fill a cifs_fattr struct with fake inode info.
+ *
+ * Needed to setup cifs_fattr data for the directory which is the
+ * junction to the new submount (ie to setup the fake directory
+ * which represents a DFS referral).
+ */
+static void
+cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+
+ cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
+
+ memset(fattr, 0, sizeof(*fattr));
+ fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
+ fattr->cf_uid = cifs_sb->ctx->linux_uid;
+ fattr->cf_gid = cifs_sb->ctx->linux_gid;
+ ktime_get_coarse_real_ts64(&fattr->cf_mtime);
+ fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
+ fattr->cf_nlink = 2;
+ fattr->cf_flags = CIFS_FATTR_DFS_REFERRAL;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+static int
+cifs_get_file_info_unix(struct file *filp)
+{
+ int rc;
+ unsigned int xid;
+ FILE_UNIX_BASIC_INFO find_data;
+ struct cifs_fattr fattr = {};
+ struct inode *inode = file_inode(filp);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifsFileInfo *cfile = filp->private_data;
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+
+ xid = get_xid();
+
+ if (cfile->symlink_target) {
+ fattr.cf_symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
+ if (!fattr.cf_symlink_target) {
+ rc = -ENOMEM;
+ goto cifs_gfiunix_out;
+ }
+ }
+
+ rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
+ if (!rc) {
+ cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
+ } else if (rc == -EREMOTE) {
+ cifs_create_dfs_fattr(&fattr, inode->i_sb);
+ rc = 0;
+ } else
+ goto cifs_gfiunix_out;
+
+ rc = cifs_fattr_to_inode(inode, &fattr);
+
+cifs_gfiunix_out:
+ free_xid(xid);
+ return rc;
+}
+
+int cifs_get_inode_info_unix(struct inode **pinode,
+ const unsigned char *full_path,
+ struct super_block *sb, unsigned int xid)
+{
+ int rc;
+ FILE_UNIX_BASIC_INFO find_data;
+ struct cifs_fattr fattr;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct tcon_link *tlink;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+
+ cifs_dbg(FYI, "Getting info on %s\n", full_path);
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+
+ /* could have done a find first instead but this returns more info */
+ rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
+ cifs_sb->local_nls, cifs_remap(cifs_sb));
+ cifs_dbg(FYI, "%s: query path info: rc = %d\n", __func__, rc);
+ cifs_put_tlink(tlink);
+
+ if (!rc) {
+ cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
+ } else if (rc == -EREMOTE) {
+ cifs_create_dfs_fattr(&fattr, sb);
+ rc = 0;
+ } else {
+ return rc;
+ }
+
+ /* check for Minshall+French symlinks */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
+ int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
+ full_path);
+ if (tmprc)
+ cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
+ }
+
+ if (S_ISLNK(fattr.cf_mode) && !fattr.cf_symlink_target) {
+ if (!server->ops->query_symlink)
+ return -EOPNOTSUPP;
+ rc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path,
+ &fattr.cf_symlink_target, false);
+ if (rc) {
+ cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc);
+ goto cgiiu_exit;
+ }
+ }
+
+ if (*pinode == NULL) {
+ /* get new inode */
+ cifs_fill_uniqueid(sb, &fattr);
+ *pinode = cifs_iget(sb, &fattr);
+ if (!*pinode)
+ rc = -ENOMEM;
+ } else {
+ /* we already have inode, update it */
+
+ /* if uniqueid is different, return error */
+ if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+ CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
+ CIFS_I(*pinode)->time = 0; /* force reval */
+ rc = -ESTALE;
+ goto cgiiu_exit;
+ }
+
+ /* if filetype is different, return error */
+ rc = cifs_fattr_to_inode(*pinode, &fattr);
+ }
+
+cgiiu_exit:
+ kfree(fattr.cf_symlink_target);
+ return rc;
+}
+#else
+int cifs_get_inode_info_unix(struct inode **pinode,
+ const unsigned char *full_path,
+ struct super_block *sb, unsigned int xid)
+{
+ return -EOPNOTSUPP;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+static int
+cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
+ struct cifs_sb_info *cifs_sb, unsigned int xid)
+{
+ int rc;
+ __u32 oplock;
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ struct cifs_io_parms io_parms = {0};
+ char buf[24];
+ unsigned int bytes_read;
+ char *pbuf;
+ int buf_type = CIFS_NO_BUFFER;
+
+ pbuf = buf;
+
+ fattr->cf_mode &= ~S_IFMT;
+
+ if (fattr->cf_eof == 0) {
+ fattr->cf_mode |= S_IFIFO;
+ fattr->cf_dtype = DT_FIFO;
+ return 0;
+ } else if (fattr->cf_eof < 8) {
+ fattr->cf_mode |= S_IFREG;
+ fattr->cf_dtype = DT_REG;
+ return -EINVAL; /* EOPNOTSUPP? */
+ }
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = GENERIC_READ,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
+ .disposition = FILE_OPEN,
+ .path = path,
+ .fid = &fid,
+ };
+
+ if (tcon->ses->server->oplocks)
+ oplock = REQ_OPLOCK;
+ else
+ oplock = 0;
+ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
+ if (rc) {
+ cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
+ cifs_put_tlink(tlink);
+ return rc;
+ }
+
+ /* Read header */
+ io_parms.netfid = fid.netfid;
+ io_parms.pid = current->tgid;
+ io_parms.tcon = tcon;
+ io_parms.offset = 0;
+ io_parms.length = 24;
+
+ rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
+ &bytes_read, &pbuf, &buf_type);
+ if ((rc == 0) && (bytes_read >= 8)) {
+ if (memcmp("IntxBLK", pbuf, 8) == 0) {
+ cifs_dbg(FYI, "Block device\n");
+ fattr->cf_mode |= S_IFBLK;
+ fattr->cf_dtype = DT_BLK;
+ if (bytes_read == 24) {
+ /* we have enough to decode dev num */
+ __u64 mjr; /* major */
+ __u64 mnr; /* minor */
+ mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
+ mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
+ fattr->cf_rdev = MKDEV(mjr, mnr);
+ }
+ } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
+ cifs_dbg(FYI, "Char device\n");
+ fattr->cf_mode |= S_IFCHR;
+ fattr->cf_dtype = DT_CHR;
+ if (bytes_read == 24) {
+ /* we have enough to decode dev num */
+ __u64 mjr; /* major */
+ __u64 mnr; /* minor */
+ mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
+ mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
+ fattr->cf_rdev = MKDEV(mjr, mnr);
+ }
+ } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
+ cifs_dbg(FYI, "Symlink\n");
+ fattr->cf_mode |= S_IFLNK;
+ fattr->cf_dtype = DT_LNK;
+ } else {
+ fattr->cf_mode |= S_IFREG; /* file? */
+ fattr->cf_dtype = DT_REG;
+ rc = -EOPNOTSUPP;
+ }
+ } else {
+ fattr->cf_mode |= S_IFREG; /* then it is a file */
+ fattr->cf_dtype = DT_REG;
+ rc = -EOPNOTSUPP; /* or some unknown SFU type */
+ }
+
+ tcon->ses->server->ops->close(xid, tcon, &fid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
+
+/*
+ * Fetch mode bits as provided by SFU.
+ *
+ * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
+ */
+static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
+ struct cifs_sb_info *cifs_sb, unsigned int xid)
+{
+#ifdef CONFIG_CIFS_XATTR
+ ssize_t rc;
+ char ea_value[4];
+ __u32 mode;
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+
+ if (tcon->ses->server->ops->query_all_EAs == NULL) {
+ cifs_put_tlink(tlink);
+ return -EOPNOTSUPP;
+ }
+
+ rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
+ "SETFILEBITS", ea_value, 4 /* size of buf */,
+ cifs_sb);
+ cifs_put_tlink(tlink);
+ if (rc < 0)
+ return (int)rc;
+ else if (rc > 3) {
+ mode = le32_to_cpu(*((__le32 *)ea_value));
+ fattr->cf_mode &= ~SFBITS_MASK;
+ cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
+ mode, fattr->cf_mode);
+ fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
+ cifs_dbg(FYI, "special mode bits 0%o\n", mode);
+ }
+
+ return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
+}
+
+/* Fill a cifs_fattr struct with info from POSIX info struct */
+static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,
+ struct super_block *sb, bool adjust_tz, bool symlink)
+{
+ struct smb311_posix_qinfo *info = &data->posix_fi;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+
+ memset(fattr, 0, sizeof(*fattr));
+
+ /* no fattr->flags to set */
+ fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
+ fattr->cf_uniqueid = le64_to_cpu(info->Inode);
+
+ if (info->LastAccessTime)
+ fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+ else
+ ktime_get_coarse_real_ts64(&fattr->cf_atime);
+
+ fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
+ fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
+
+ if (adjust_tz) {
+ fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
+ fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
+ }
+
+ fattr->cf_eof = le64_to_cpu(info->EndOfFile);
+ fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
+ fattr->cf_createtime = le64_to_cpu(info->CreationTime);
+
+ fattr->cf_nlink = le32_to_cpu(info->HardLinks);
+ fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode);
+ /* The srv fs device id is overridden on network mount so setting rdev isn't needed here */
+ /* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */
+
+ if (symlink) {
+ fattr->cf_mode |= S_IFLNK;
+ fattr->cf_dtype = DT_LNK;
+ fattr->cf_symlink_target = data->symlink_target;
+ data->symlink_target = NULL;
+ } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
+ fattr->cf_mode |= S_IFDIR;
+ fattr->cf_dtype = DT_DIR;
+ } else { /* file */
+ fattr->cf_mode |= S_IFREG;
+ fattr->cf_dtype = DT_REG;
+ }
+ /* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
+
+ fattr->cf_uid = cifs_sb->ctx->linux_uid; /* TODO: map uid and gid from SID */
+ fattr->cf_gid = cifs_sb->ctx->linux_gid;
+
+ cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
+ fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
+}
+
+static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,
+ struct super_block *sb, bool adjust_tz, bool symlink,
+ u32 reparse_tag)
+{
+ struct smb2_file_all_info *info = &data->fi;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+
+ memset(fattr, 0, sizeof(*fattr));
+ fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
+ if (info->DeletePending)
+ fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
+
+ if (info->LastAccessTime)
+ fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+ else
+ ktime_get_coarse_real_ts64(&fattr->cf_atime);
+
+ fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
+ fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
+
+ if (adjust_tz) {
+ fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
+ fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
+ }
+
+ fattr->cf_eof = le64_to_cpu(info->EndOfFile);
+ fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
+ fattr->cf_createtime = le64_to_cpu(info->CreationTime);
+
+ fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
+ if (reparse_tag == IO_REPARSE_TAG_LX_SYMLINK) {
+ fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_LNK;
+ } else if (reparse_tag == IO_REPARSE_TAG_LX_FIFO) {
+ fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_FIFO;
+ } else if (reparse_tag == IO_REPARSE_TAG_AF_UNIX) {
+ fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_SOCK;
+ } else if (reparse_tag == IO_REPARSE_TAG_LX_CHR) {
+ fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_CHR;
+ } else if (reparse_tag == IO_REPARSE_TAG_LX_BLK) {
+ fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_BLK;
+ } else if (symlink || reparse_tag == IO_REPARSE_TAG_SYMLINK ||
+ reparse_tag == IO_REPARSE_TAG_NFS) {
+ fattr->cf_mode = S_IFLNK;
+ fattr->cf_dtype = DT_LNK;
+ } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
+ fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;
+ fattr->cf_dtype = DT_DIR;
+ /*
+ * Server can return wrong NumberOfLinks value for directories
+ * when Unix extensions are disabled - fake it.
+ */
+ if (!tcon->unix_ext)
+ fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
+ } else {
+ fattr->cf_mode = S_IFREG | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_REG;
+
+ /* clear write bits if ATTR_READONLY is set */
+ if (fattr->cf_cifsattrs & ATTR_READONLY)
+ fattr->cf_mode &= ~(S_IWUGO);
+
+ /*
+ * Don't accept zero nlink from non-unix servers unless
+ * delete is pending. Instead mark it as unknown.
+ */
+ if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
+ !info->DeletePending) {
+ cifs_dbg(VFS, "bogus file nlink value %u\n",
+ fattr->cf_nlink);
+ fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
+ }
+ }
+
+ if (S_ISLNK(fattr->cf_mode)) {
+ fattr->cf_symlink_target = data->symlink_target;
+ data->symlink_target = NULL;
+ }
+
+ fattr->cf_uid = cifs_sb->ctx->linux_uid;
+ fattr->cf_gid = cifs_sb->ctx->linux_gid;
+}
+
+static int
+cifs_get_file_info(struct file *filp)
+{
+ int rc;
+ unsigned int xid;
+ struct cifs_open_info_data data = {};
+ struct cifs_fattr fattr;
+ struct inode *inode = file_inode(filp);
+ struct cifsFileInfo *cfile = filp->private_data;
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ bool symlink = false;
+ u32 tag = 0;
+
+ if (!server->ops->query_file_info)
+ return -ENOSYS;
+
+ xid = get_xid();
+ rc = server->ops->query_file_info(xid, tcon, cfile, &data);
+ switch (rc) {
+ case 0:
+ /* TODO: add support to query reparse tag */
+ if (data.symlink_target) {
+ symlink = true;
+ tag = IO_REPARSE_TAG_SYMLINK;
+ }
+ cifs_open_info_to_fattr(&fattr, &data, inode->i_sb, false, symlink, tag);
+ break;
+ case -EREMOTE:
+ cifs_create_dfs_fattr(&fattr, inode->i_sb);
+ rc = 0;
+ break;
+ case -EOPNOTSUPP:
+ case -EINVAL:
+ /*
+ * FIXME: legacy server -- fall back to path-based call?
+ * for now, just skip revalidating and mark inode for
+ * immediate reval.
+ */
+ rc = 0;
+ CIFS_I(inode)->time = 0;
+ goto cgfi_exit;
+ default:
+ goto cgfi_exit;
+ }
+
+ /*
+ * don't bother with SFU junk here -- just mark inode as needing
+ * revalidation.
+ */
+ fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
+ fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
+ /* if filetype is different, return error */
+ rc = cifs_fattr_to_inode(inode, &fattr);
+cgfi_exit:
+ cifs_free_open_info(&data);
+ free_xid(xid);
+ return rc;
+}
+
+/* Simple function to return a 64 bit hash of string. Rarely called */
+static __u64 simple_hashstr(const char *str)
+{
+ const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
+ __u64 hash = 0;
+
+ while (*str)
+ hash = (hash + (__u64) *str++) * hash_mult;
+
+ return hash;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+/**
+ * cifs_backup_query_path_info - SMB1 fallback code to get ino
+ *
+ * Fallback code to get file metadata when we don't have access to
+ * full_path (EACCES) and have backup creds.
+ *
+ * @xid: transaction id used to identify original request in logs
+ * @tcon: information about the server share we have mounted
+ * @sb: the superblock stores info such as disk space available
+ * @full_path: name of the file we are getting the metadata for
+ * @resp_buf: will be set to cifs resp buf and needs to be freed with
+ * cifs_buf_release() when done with @data
+ * @data: will be set to search info result buffer
+ */
+static int
+cifs_backup_query_path_info(int xid,
+ struct cifs_tcon *tcon,
+ struct super_block *sb,
+ const char *full_path,
+ void **resp_buf,
+ FILE_ALL_INFO **data)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_search_info info = {0};
+ u16 flags;
+ int rc;
+
+ *resp_buf = NULL;
+ info.endOfSearch = false;
+ if (tcon->unix_ext)
+ info.info_level = SMB_FIND_FILE_UNIX;
+ else if ((tcon->ses->capabilities &
+ tcon->ses->server->vals->cap_nt_find) == 0)
+ info.info_level = SMB_FIND_FILE_INFO_STANDARD;
+ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+ info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
+ else /* no srvino useful for fallback to some netapp */
+ info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
+
+ flags = CIFS_SEARCH_CLOSE_ALWAYS |
+ CIFS_SEARCH_CLOSE_AT_END |
+ CIFS_SEARCH_BACKUP_SEARCH;
+
+ rc = CIFSFindFirst(xid, tcon, full_path,
+ cifs_sb, NULL, flags, &info, false);
+ if (rc)
+ return rc;
+
+ *resp_buf = (void *)info.ntwrk_buf_start;
+ *data = (FILE_ALL_INFO *)info.srch_entries_start;
+ return 0;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+static void cifs_set_fattr_ino(int xid, struct cifs_tcon *tcon, struct super_block *sb,
+ struct inode **inode, const char *full_path,
+ struct cifs_open_info_data *data, struct cifs_fattr *fattr)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ int rc;
+
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
+ if (*inode)
+ fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
+ else
+ fattr->cf_uniqueid = iunique(sb, ROOT_I);
+ return;
+ }
+
+ /*
+ * If we have an inode pass a NULL tcon to ensure we don't
+ * make a round trip to the server. This only works for SMB2+.
+ */
+ rc = server->ops->get_srv_inum(xid, *inode ? NULL : tcon, cifs_sb, full_path,
+ &fattr->cf_uniqueid, data);
+ if (rc) {
+ /*
+ * If that fails reuse existing ino or generate one
+ * and disable server ones
+ */
+ if (*inode)
+ fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
+ else {
+ fattr->cf_uniqueid = iunique(sb, ROOT_I);
+ cifs_autodisable_serverino(cifs_sb);
+ }
+ return;
+ }
+
+ /* If no errors, check for zero root inode (invalid) */
+ if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) {
+ cifs_dbg(FYI, "Invalid (0) inodenum\n");
+ if (*inode) {
+ /* reuse */
+ fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
+ } else {
+ /* make an ino by hashing the UNC */
+ fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
+ fattr->cf_uniqueid = simple_hashstr(tcon->tree_name);
+ }
+ }
+}
+
+static inline bool is_inode_cache_good(struct inode *ino)
+{
+ return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
+}
+
+int cifs_get_inode_info(struct inode **inode, const char *full_path,
+ struct cifs_open_info_data *data, struct super_block *sb, int xid,
+ const struct cifs_fid *fid)
+{
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct tcon_link *tlink;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ bool adjust_tz = false;
+ struct cifs_fattr fattr = {0};
+ bool is_reparse_point = false;
+ struct cifs_open_info_data tmp_data = {};
+ void *smb1_backup_rsp_buf = NULL;
+ int rc = 0;
+ int tmprc = 0;
+ __u32 reparse_tag = 0;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+
+ /*
+ * 1. Fetch file metadata if not provided (data)
+ */
+
+ if (!data) {
+ if (is_inode_cache_good(*inode)) {
+ cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
+ goto out;
+ }
+ rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, &tmp_data,
+ &adjust_tz, &is_reparse_point);
+ data = &tmp_data;
+ }
+
+ /*
+ * 2. Convert it to internal cifs metadata (fattr)
+ */
+
+ switch (rc) {
+ case 0:
+ /*
+ * If the file is a reparse point, it is more complicated
+ * since we have to check if its reparse tag matches a known
+ * special file type e.g. symlink or fifo or char etc.
+ */
+ if (is_reparse_point && data->symlink_target) {
+ reparse_tag = IO_REPARSE_TAG_SYMLINK;
+ } else if ((le32_to_cpu(data->fi.Attributes) & ATTR_REPARSE) &&
+ server->ops->query_reparse_tag) {
+ tmprc = server->ops->query_reparse_tag(xid, tcon, cifs_sb, full_path,
+ &reparse_tag);
+ if (tmprc)
+ cifs_dbg(FYI, "%s: query_reparse_tag: rc = %d\n", __func__, tmprc);
+ if (server->ops->query_symlink) {
+ tmprc = server->ops->query_symlink(xid, tcon, cifs_sb, full_path,
+ &data->symlink_target,
+ is_reparse_point);
+ if (tmprc)
+ cifs_dbg(FYI, "%s: query_symlink: rc = %d\n", __func__,
+ tmprc);
+ }
+ }
+ cifs_open_info_to_fattr(&fattr, data, sb, adjust_tz, is_reparse_point, reparse_tag);
+ break;
+ case -EREMOTE:
+ /* DFS link, no metadata available on this server */
+ cifs_create_dfs_fattr(&fattr, sb);
+ rc = 0;
+ break;
+ case -EACCES:
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ /*
+ * perm errors, try again with backup flags if possible
+ *
+ * For SMB2 and later the backup intent flag
+ * is already sent if needed on open and there
+ * is no path based FindFirst operation to use
+ * to retry with
+ */
+ if (backup_cred(cifs_sb) && is_smb1_server(server)) {
+ /* for easier reading */
+ FILE_ALL_INFO *fi;
+ FILE_DIRECTORY_INFO *fdi;
+ SEARCH_ID_FULL_DIR_INFO *si;
+
+ rc = cifs_backup_query_path_info(xid, tcon, sb,
+ full_path,
+ &smb1_backup_rsp_buf,
+ &fi);
+ if (rc)
+ goto out;
+
+ move_cifs_info_to_smb2(&data->fi, fi);
+ fdi = (FILE_DIRECTORY_INFO *)fi;
+ si = (SEARCH_ID_FULL_DIR_INFO *)fi;
+
+ cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);
+ fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);
+ /* uniqueid set, skip get inum step */
+ goto handle_mnt_opt;
+ } else {
+ /* nothing we can do, bail out */
+ goto out;
+ }
+#else
+ goto out;
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ break;
+ default:
+ cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
+ goto out;
+ }
+
+ /*
+ * 3. Get or update inode number (fattr.cf_uniqueid)
+ */
+
+ cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
+
+ /*
+ * 4. Tweak fattr based on mount options
+ */
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+handle_mnt_opt:
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ /* query for SFU type info if supported and needed */
+ if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+ tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
+ if (tmprc)
+ cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
+ }
+
+ /* fill in 0777 bits from ACL */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
+ rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
+ full_path, fid);
+ if (rc == -EREMOTE)
+ rc = 0;
+ if (rc) {
+ cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
+ __func__, rc);
+ goto out;
+ }
+ } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+ rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
+ full_path, fid);
+ if (rc == -EREMOTE)
+ rc = 0;
+ if (rc) {
+ cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
+ __func__, rc);
+ goto out;
+ }
+ }
+
+ /* fill in remaining high mode bits e.g. SUID, VTX */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
+ cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
+
+ /* check for Minshall+French symlinks */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
+ tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
+ full_path);
+ if (tmprc)
+ cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
+ }
+
+ /*
+ * 5. Update inode with final fattr data
+ */
+
+ if (!*inode) {
+ *inode = cifs_iget(sb, &fattr);
+ if (!*inode)
+ rc = -ENOMEM;
+ } else {
+ /* we already have inode, update it */
+
+ /* if uniqueid is different, return error */
+ if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+ CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
+ CIFS_I(*inode)->time = 0; /* force reval */
+ rc = -ESTALE;
+ goto out;
+ }
+ /* if filetype is different, return error */
+ rc = cifs_fattr_to_inode(*inode, &fattr);
+ }
+out:
+ cifs_buf_release(smb1_backup_rsp_buf);
+ cifs_put_tlink(tlink);
+ cifs_free_open_info(&tmp_data);
+ kfree(fattr.cf_symlink_target);
+ return rc;
+}
+
+int
+smb311_posix_get_inode_info(struct inode **inode,
+ const char *full_path,
+ struct super_block *sb, unsigned int xid)
+{
+ struct cifs_tcon *tcon;
+ struct tcon_link *tlink;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ bool adjust_tz = false;
+ struct cifs_fattr fattr = {0};
+ bool symlink = false;
+ struct cifs_open_info_data data = {};
+ int rc = 0;
+ int tmprc = 0;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+
+ /*
+ * 1. Fetch file metadata
+ */
+
+ if (is_inode_cache_good(*inode)) {
+ cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
+ goto out;
+ }
+
+ rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data, &adjust_tz,
+ &symlink);
+
+ /*
+ * 2. Convert it to internal cifs metadata (fattr)
+ */
+
+ switch (rc) {
+ case 0:
+ smb311_posix_info_to_fattr(&fattr, &data, sb, adjust_tz, symlink);
+ break;
+ case -EREMOTE:
+ /* DFS link, no metadata available on this server */
+ cifs_create_dfs_fattr(&fattr, sb);
+ rc = 0;
+ break;
+ case -EACCES:
+ /*
+ * For SMB2 and later the backup intent flag
+ * is already sent if needed on open and there
+ * is no path based FindFirst operation to use
+ * to retry with so nothing we can do, bail out
+ */
+ goto out;
+ default:
+ cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
+ goto out;
+ }
+
+
+ /*
+ * 3. Tweak fattr based on mount options
+ */
+
+ /* check for Minshall+French symlinks */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
+ tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
+ full_path);
+ if (tmprc)
+ cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
+ }
+
+ /*
+ * 4. Update inode with final fattr data
+ */
+
+ if (!*inode) {
+ *inode = cifs_iget(sb, &fattr);
+ if (!*inode)
+ rc = -ENOMEM;
+ } else {
+ /* we already have inode, update it */
+
+ /* if uniqueid is different, return error */
+ if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
+ CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
+ CIFS_I(*inode)->time = 0; /* force reval */
+ rc = -ESTALE;
+ goto out;
+ }
+
+ /* if filetype is different, return error */
+ rc = cifs_fattr_to_inode(*inode, &fattr);
+ }
+out:
+ cifs_put_tlink(tlink);
+ cifs_free_open_info(&data);
+ kfree(fattr.cf_symlink_target);
+ return rc;
+}
+
+
+static const struct inode_operations cifs_ipc_inode_ops = {
+ .lookup = cifs_lookup,
+};
+
+static int
+cifs_find_inode(struct inode *inode, void *opaque)
+{
+ struct cifs_fattr *fattr = opaque;
+
+ /* don't match inode with different uniqueid */
+ if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
+ return 0;
+
+ /* use createtime like an i_generation field */
+ if (CIFS_I(inode)->createtime != fattr->cf_createtime)
+ return 0;
+
+ /* don't match inode of different type */
+ if (inode_wrong_type(inode, fattr->cf_mode))
+ return 0;
+
+ /* if it's not a directory or has no dentries, then flag it */
+ if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
+ fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
+
+ return 1;
+}
+
+static int
+cifs_init_inode(struct inode *inode, void *opaque)
+{
+ struct cifs_fattr *fattr = opaque;
+
+ CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
+ CIFS_I(inode)->createtime = fattr->cf_createtime;
+ return 0;
+}
+
+/*
+ * walk dentry list for an inode and report whether it has aliases that
+ * are hashed. We use this to determine if a directory inode can actually
+ * be used.
+ */
+static bool
+inode_has_hashed_dentries(struct inode *inode)
+{
+ struct dentry *dentry;
+
+ spin_lock(&inode->i_lock);
+ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
+ if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
+ spin_unlock(&inode->i_lock);
+ return true;
+ }
+ }
+ spin_unlock(&inode->i_lock);
+ return false;
+}
+
+/* Given fattrs, get a corresponding inode */
+struct inode *
+cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
+{
+ unsigned long hash;
+ struct inode *inode;
+
+retry_iget5_locked:
+ cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
+
+ /* hash down to 32-bits on 32-bit arch */
+ hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
+
+ inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
+ if (inode) {
+ /* was there a potentially problematic inode collision? */
+ if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
+ fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
+
+ if (inode_has_hashed_dentries(inode)) {
+ cifs_autodisable_serverino(CIFS_SB(sb));
+ iput(inode);
+ fattr->cf_uniqueid = iunique(sb, ROOT_I);
+ goto retry_iget5_locked;
+ }
+ }
+
+ /* can't fail - see cifs_find_inode() */
+ cifs_fattr_to_inode(inode, fattr);
+ if (sb->s_flags & SB_NOATIME)
+ inode->i_flags |= S_NOATIME | S_NOCMTIME;
+ if (inode->i_state & I_NEW) {
+ inode->i_ino = hash;
+ cifs_fscache_get_inode_cookie(inode);
+ unlock_new_inode(inode);
+ }
+ }
+
+ return inode;
+}
+
+/* gets root inode */
+struct inode *cifs_root_iget(struct super_block *sb)
+{
+ unsigned int xid;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct inode *inode = NULL;
+ long rc;
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ char *path = NULL;
+ int len;
+
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
+ && cifs_sb->prepath) {
+ len = strlen(cifs_sb->prepath);
+ path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
+ if (path == NULL)
+ return ERR_PTR(-ENOMEM);
+ path[0] = '/';
+ memcpy(path+1, cifs_sb->prepath, len);
+ } else {
+ path = kstrdup("", GFP_KERNEL);
+ if (path == NULL)
+ return ERR_PTR(-ENOMEM);
+ }
+
+ xid = get_xid();
+ if (tcon->unix_ext) {
+ rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
+ /* some servers mistakenly claim POSIX support */
+ if (rc != -EOPNOTSUPP)
+ goto iget_no_retry;
+ cifs_dbg(VFS, "server does not support POSIX extensions\n");
+ tcon->unix_ext = false;
+ }
+
+ convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
+ if (tcon->posix_extensions)
+ rc = smb311_posix_get_inode_info(&inode, path, sb, xid);
+ else
+ rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
+
+iget_no_retry:
+ if (!inode) {
+ inode = ERR_PTR(rc);
+ goto out;
+ }
+
+ if (rc && tcon->pipe) {
+ cifs_dbg(FYI, "ipc connection - fake read inode\n");
+ spin_lock(&inode->i_lock);
+ inode->i_mode |= S_IFDIR;
+ set_nlink(inode, 2);
+ inode->i_op = &cifs_ipc_inode_ops;
+ inode->i_fop = &simple_dir_operations;
+ inode->i_uid = cifs_sb->ctx->linux_uid;
+ inode->i_gid = cifs_sb->ctx->linux_gid;
+ spin_unlock(&inode->i_lock);
+ } else if (rc) {
+ iget_failed(inode);
+ inode = ERR_PTR(rc);
+ }
+
+out:
+ kfree(path);
+ free_xid(xid);
+ return inode;
+}
+
+int
+cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
+ const char *full_path, __u32 dosattr)
+{
+ bool set_time = false;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct TCP_Server_Info *server;
+ FILE_BASIC_INFO info_buf;
+
+ if (attrs == NULL)
+ return -EINVAL;
+
+ server = cifs_sb_master_tcon(cifs_sb)->ses->server;
+ if (!server->ops->set_file_info)
+ return -ENOSYS;
+
+ info_buf.Pad = 0;
+
+ if (attrs->ia_valid & ATTR_ATIME) {
+ set_time = true;
+ info_buf.LastAccessTime =
+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
+ } else
+ info_buf.LastAccessTime = 0;
+
+ if (attrs->ia_valid & ATTR_MTIME) {
+ set_time = true;
+ info_buf.LastWriteTime =
+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
+ } else
+ info_buf.LastWriteTime = 0;
+
+ /*
+ * Samba throws this field away, but windows may actually use it.
+ * Do not set ctime unless other time stamps are changed explicitly
+ * (i.e. by utimes()) since we would then have a mix of client and
+ * server times.
+ */
+ if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
+ cifs_dbg(FYI, "CIFS - CTIME changed\n");
+ info_buf.ChangeTime =
+ cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
+ } else
+ info_buf.ChangeTime = 0;
+
+ info_buf.CreationTime = 0; /* don't change */
+ info_buf.Attributes = cpu_to_le32(dosattr);
+
+ return server->ops->set_file_info(inode, full_path, &info_buf, xid);
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+/*
+ * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
+ * and rename it to a random name that hopefully won't conflict with
+ * anything else.
+ */
+int
+cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
+ const unsigned int xid)
+{
+ int oplock = 0;
+ int rc;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ struct inode *inode = d_inode(dentry);
+ struct cifsInodeInfo *cifsInode = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ __u32 dosattr, origattr;
+ FILE_BASIC_INFO *info_buf = NULL;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+
+ /*
+ * We cannot rename the file if the server doesn't support
+ * CAP_INFOLEVEL_PASSTHRU
+ */
+ if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
+ rc = -EBUSY;
+ goto out;
+ }
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = DELETE | FILE_WRITE_ATTRIBUTES,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
+ .disposition = FILE_OPEN,
+ .path = full_path,
+ .fid = &fid,
+ };
+
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (rc != 0)
+ goto out;
+
+ origattr = cifsInode->cifsAttrs;
+ if (origattr == 0)
+ origattr |= ATTR_NORMAL;
+
+ dosattr = origattr & ~ATTR_READONLY;
+ if (dosattr == 0)
+ dosattr |= ATTR_NORMAL;
+ dosattr |= ATTR_HIDDEN;
+
+ /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
+ if (dosattr != origattr) {
+ info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
+ if (info_buf == NULL) {
+ rc = -ENOMEM;
+ goto out_close;
+ }
+ info_buf->Attributes = cpu_to_le32(dosattr);
+ rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
+ current->tgid);
+ /* although we would like to mark the file hidden
+ if that fails we will still try to rename it */
+ if (!rc)
+ cifsInode->cifsAttrs = dosattr;
+ else
+ dosattr = origattr; /* since not able to change them */
+ }
+
+ /* rename the file */
+ rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ if (rc != 0) {
+ rc = -EBUSY;
+ goto undo_setattr;
+ }
+
+ /* try to set DELETE_ON_CLOSE */
+ if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
+ rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
+ current->tgid);
+ /*
+ * some samba versions return -ENOENT when we try to set the
+ * file disposition here. Likely a samba bug, but work around
+ * it for now. This means that some cifsXXX files may hang
+ * around after they shouldn't.
+ *
+ * BB: remove this hack after more servers have the fix
+ */
+ if (rc == -ENOENT)
+ rc = 0;
+ else if (rc != 0) {
+ rc = -EBUSY;
+ goto undo_rename;
+ }
+ set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
+ }
+
+out_close:
+ CIFSSMBClose(xid, tcon, fid.netfid);
+out:
+ kfree(info_buf);
+ cifs_put_tlink(tlink);
+ return rc;
+
+ /*
+ * reset everything back to the original state. Don't bother
+ * dealing with errors here since we can't do anything about
+ * them anyway.
+ */
+undo_rename:
+ CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
+ cifs_sb->local_nls, cifs_remap(cifs_sb));
+undo_setattr:
+ if (dosattr != origattr) {
+ info_buf->Attributes = cpu_to_le32(origattr);
+ if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
+ current->tgid))
+ cifsInode->cifsAttrs = origattr;
+ }
+
+ goto out_close;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+/* copied from fs/nfs/dir.c with small changes */
+static void
+cifs_drop_nlink(struct inode *inode)
+{
+ spin_lock(&inode->i_lock);
+ if (inode->i_nlink > 0)
+ drop_nlink(inode);
+ spin_unlock(&inode->i_lock);
+}
+
+/*
+ * If d_inode(dentry) is null (usually meaning the cached dentry
+ * is a negative dentry) then we would attempt a standard SMB delete, but
+ * if that fails we can not attempt the fall back mechanisms on EACCES
+ * but will return the EACCES to the caller. Note that the VFS does not call
+ * unlink on negative dentries currently.
+ */
+int cifs_unlink(struct inode *dir, struct dentry *dentry)
+{
+ int rc = 0;
+ unsigned int xid;
+ const char *full_path;
+ void *page;
+ struct inode *inode = d_inode(dentry);
+ struct cifsInodeInfo *cifs_inode;
+ struct super_block *sb = dir->i_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct iattr *attrs = NULL;
+ __u32 dosattr = 0, origattr = 0;
+
+ cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
+
+ if (unlikely(cifs_forced_shutdown(cifs_sb)))
+ return -EIO;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+
+ xid = get_xid();
+ page = alloc_dentry_path();
+
+ if (tcon->nodelete) {
+ rc = -EACCES;
+ goto unlink_out;
+ }
+
+ /* Unlink can be called from rename so we can not take the
+ * sb->s_vfs_rename_mutex here */
+ full_path = build_path_from_dentry(dentry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto unlink_out;
+ }
+
+ cifs_close_deferred_file_under_dentry(tcon, full_path);
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+ rc = CIFSPOSIXDelFile(xid, tcon, full_path,
+ SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ cifs_dbg(FYI, "posix del rc %d\n", rc);
+ if ((rc == 0) || (rc == -ENOENT))
+ goto psx_del_no_retry;
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+retry_std_delete:
+ if (!server->ops->unlink) {
+ rc = -ENOSYS;
+ goto psx_del_no_retry;
+ }
+
+ rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
+
+psx_del_no_retry:
+ if (!rc) {
+ if (inode)
+ cifs_drop_nlink(inode);
+ } else if (rc == -ENOENT) {
+ d_drop(dentry);
+ } else if (rc == -EBUSY) {
+ if (server->ops->rename_pending_delete) {
+ rc = server->ops->rename_pending_delete(full_path,
+ dentry, xid);
+ if (rc == 0)
+ cifs_drop_nlink(inode);
+ }
+ } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
+ attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
+ if (attrs == NULL) {
+ rc = -ENOMEM;
+ goto out_reval;
+ }
+
+ /* try to reset dos attributes */
+ cifs_inode = CIFS_I(inode);
+ origattr = cifs_inode->cifsAttrs;
+ if (origattr == 0)
+ origattr |= ATTR_NORMAL;
+ dosattr = origattr & ~ATTR_READONLY;
+ if (dosattr == 0)
+ dosattr |= ATTR_NORMAL;
+ dosattr |= ATTR_HIDDEN;
+
+ rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
+ if (rc != 0)
+ goto out_reval;
+
+ goto retry_std_delete;
+ }
+
+ /* undo the setattr if we errored out and it's needed */
+ if (rc != 0 && dosattr != 0)
+ cifs_set_file_info(inode, attrs, xid, full_path, origattr);
+
+out_reval:
+ if (inode) {
+ cifs_inode = CIFS_I(inode);
+ cifs_inode->time = 0; /* will force revalidate to get info
+ when needed */
+ inode->i_ctime = current_time(inode);
+ }
+ dir->i_ctime = dir->i_mtime = current_time(dir);
+ cifs_inode = CIFS_I(dir);
+ CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
+unlink_out:
+ free_dentry_path(page);
+ kfree(attrs);
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+static int
+cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
+ const char *full_path, struct cifs_sb_info *cifs_sb,
+ struct cifs_tcon *tcon, const unsigned int xid)
+{
+ int rc = 0;
+ struct inode *inode = NULL;
+
+ if (tcon->posix_extensions)
+ rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ else if (tcon->unix_ext)
+ rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
+ xid);
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ else
+ rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
+ xid, NULL);
+
+ if (rc)
+ return rc;
+
+ if (!S_ISDIR(inode->i_mode)) {
+ /*
+ * mkdir succeeded, but another client has managed to remove the
+ * sucker and replace it with non-directory. Return success,
+ * but don't leave the child in dcache.
+ */
+ iput(inode);
+ d_drop(dentry);
+ return 0;
+ }
+ /*
+ * setting nlink not necessary except in cases where we failed to get it
+ * from the server or was set bogus. Also, since this is a brand new
+ * inode, no need to grab the i_lock before setting the i_nlink.
+ */
+ if (inode->i_nlink < 2)
+ set_nlink(inode, 2);
+ mode &= ~current_umask();
+ /* must turn on setgid bit if parent dir has it */
+ if (parent->i_mode & S_ISGID)
+ mode |= S_ISGID;
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (tcon->unix_ext) {
+ struct cifs_unix_set_info_args args = {
+ .mode = mode,
+ .ctime = NO_CHANGE_64,
+ .atime = NO_CHANGE_64,
+ .mtime = NO_CHANGE_64,
+ .device = 0,
+ };
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ args.uid = current_fsuid();
+ if (parent->i_mode & S_ISGID)
+ args.gid = parent->i_gid;
+ else
+ args.gid = current_fsgid();
+ } else {
+ args.uid = INVALID_UID; /* no change */
+ args.gid = INVALID_GID; /* no change */
+ }
+ CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ } else {
+#else
+ {
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ struct TCP_Server_Info *server = tcon->ses->server;
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
+ (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
+ server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
+ tcon, xid);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
+ inode->i_mode = (mode | S_IFDIR);
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ inode->i_uid = current_fsuid();
+ if (inode->i_mode & S_ISGID)
+ inode->i_gid = parent->i_gid;
+ else
+ inode->i_gid = current_fsgid();
+ }
+ }
+ d_instantiate(dentry, inode);
+ return 0;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+static int
+cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
+ const char *full_path, struct cifs_sb_info *cifs_sb,
+ struct cifs_tcon *tcon, const unsigned int xid)
+{
+ int rc = 0;
+ u32 oplock = 0;
+ FILE_UNIX_BASIC_INFO *info = NULL;
+ struct inode *newinode = NULL;
+ struct cifs_fattr fattr;
+
+ info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+ if (info == NULL) {
+ rc = -ENOMEM;
+ goto posix_mkdir_out;
+ }
+
+ mode &= ~current_umask();
+ rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
+ NULL /* netfid */, info, &oplock, full_path,
+ cifs_sb->local_nls, cifs_remap(cifs_sb));
+ if (rc == -EOPNOTSUPP)
+ goto posix_mkdir_out;
+ else if (rc) {
+ cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
+ d_drop(dentry);
+ goto posix_mkdir_out;
+ }
+
+ if (info->Type == cpu_to_le32(-1))
+ /* no return info, go query for it */
+ goto posix_mkdir_get_info;
+ /*
+ * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
+ * need to set uid/gid.
+ */
+
+ cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
+ cifs_fill_uniqueid(inode->i_sb, &fattr);
+ newinode = cifs_iget(inode->i_sb, &fattr);
+ if (!newinode)
+ goto posix_mkdir_get_info;
+
+ d_instantiate(dentry, newinode);
+
+#ifdef CONFIG_CIFS_DEBUG2
+ cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
+ dentry, dentry, newinode);
+
+ if (newinode->i_nlink != 2)
+ cifs_dbg(FYI, "unexpected number of links %d\n",
+ newinode->i_nlink);
+#endif
+
+posix_mkdir_out:
+ kfree(info);
+ return rc;
+posix_mkdir_get_info:
+ rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
+ xid);
+ goto posix_mkdir_out;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode,
+ struct dentry *direntry, umode_t mode)
+{
+ int rc = 0;
+ unsigned int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ const char *full_path;
+ void *page;
+
+ cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
+ mode, inode);
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ if (unlikely(cifs_forced_shutdown(cifs_sb)))
+ return -EIO;
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+
+ xid = get_xid();
+
+ page = alloc_dentry_path();
+ full_path = build_path_from_dentry(direntry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto mkdir_out;
+ }
+
+ server = tcon->ses->server;
+
+ if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
+ rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
+ cifs_sb);
+ d_drop(direntry); /* for time being always refresh inode info */
+ goto mkdir_out;
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+ rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
+ tcon, xid);
+ if (rc != -EOPNOTSUPP)
+ goto mkdir_out;
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ if (!server->ops->mkdir) {
+ rc = -ENOSYS;
+ goto mkdir_out;
+ }
+
+ /* BB add setting the equivalent of mode via CreateX w/ACLs */
+ rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
+ if (rc) {
+ cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
+ d_drop(direntry);
+ goto mkdir_out;
+ }
+
+ /* TODO: skip this for smb2/smb3 */
+ rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
+ xid);
+mkdir_out:
+ /*
+ * Force revalidate to get parent dir info when needed since cached
+ * attributes are invalid now.
+ */
+ CIFS_I(inode)->time = 0;
+ free_dentry_path(page);
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+int cifs_rmdir(struct inode *inode, struct dentry *direntry)
+{
+ int rc = 0;
+ unsigned int xid;
+ struct cifs_sb_info *cifs_sb;
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ const char *full_path;
+ void *page = alloc_dentry_path();
+ struct cifsInodeInfo *cifsInode;
+
+ cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
+
+ xid = get_xid();
+
+ full_path = build_path_from_dentry(direntry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto rmdir_exit;
+ }
+
+ cifs_sb = CIFS_SB(inode->i_sb);
+ if (unlikely(cifs_forced_shutdown(cifs_sb))) {
+ rc = -EIO;
+ goto rmdir_exit;
+ }
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink)) {
+ rc = PTR_ERR(tlink);
+ goto rmdir_exit;
+ }
+ tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+
+ if (!server->ops->rmdir) {
+ rc = -ENOSYS;
+ cifs_put_tlink(tlink);
+ goto rmdir_exit;
+ }
+
+ if (tcon->nodelete) {
+ rc = -EACCES;
+ cifs_put_tlink(tlink);
+ goto rmdir_exit;
+ }
+
+ rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
+ cifs_put_tlink(tlink);
+
+ if (!rc) {
+ spin_lock(&d_inode(direntry)->i_lock);
+ i_size_write(d_inode(direntry), 0);
+ clear_nlink(d_inode(direntry));
+ spin_unlock(&d_inode(direntry)->i_lock);
+ }
+
+ cifsInode = CIFS_I(d_inode(direntry));
+ /* force revalidate to go get info when needed */
+ cifsInode->time = 0;
+
+ cifsInode = CIFS_I(inode);
+ /*
+ * Force revalidate to get parent dir info when needed since cached
+ * attributes are invalid now.
+ */
+ cifsInode->time = 0;
+
+ d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
+ current_time(inode);
+
+rmdir_exit:
+ free_dentry_path(page);
+ free_xid(xid);
+ return rc;
+}
+
+static int
+cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
+ const char *from_path, struct dentry *to_dentry,
+ const char *to_path)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ int oplock;
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ int rc;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+
+ if (!server->ops->rename)
+ return -ENOSYS;
+
+ /* try path-based rename first */
+ rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
+
+ /*
+ * Don't bother with rename by filehandle unless file is busy and
+ * source. Note that cross directory moves do not work with
+ * rename by filehandle to various Windows servers.
+ */
+ if (rc == 0 || rc != -EBUSY)
+ goto do_rename_exit;
+
+ /* Don't fall back to using SMB on SMB 2+ mount */
+ if (server->vals->protocol_id != 0)
+ goto do_rename_exit;
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ /* open-file renames don't work across directories */
+ if (to_dentry->d_parent != from_dentry->d_parent)
+ goto do_rename_exit;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ /* open the file to be renamed -- we need DELETE perms */
+ .desired_access = DELETE,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
+ .disposition = FILE_OPEN,
+ .path = from_path,
+ .fid = &fid,
+ };
+
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (rc == 0) {
+ rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
+ (const char *) to_dentry->d_name.name,
+ cifs_sb->local_nls, cifs_remap(cifs_sb));
+ CIFSSMBClose(xid, tcon, fid.netfid);
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+do_rename_exit:
+ if (rc == 0)
+ d_move(from_dentry, to_dentry);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+int
+cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
+ struct dentry *source_dentry, struct inode *target_dir,
+ struct dentry *target_dentry, unsigned int flags)
+{
+ const char *from_name, *to_name;
+ void *page1, *page2;
+ struct cifs_sb_info *cifs_sb;
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ unsigned int xid;
+ int rc, tmprc;
+ int retry_count = 0;
+ FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ FILE_UNIX_BASIC_INFO *info_buf_target;
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+
+ cifs_sb = CIFS_SB(source_dir->i_sb);
+ if (unlikely(cifs_forced_shutdown(cifs_sb)))
+ return -EIO;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+
+ page1 = alloc_dentry_path();
+ page2 = alloc_dentry_path();
+ xid = get_xid();
+
+ from_name = build_path_from_dentry(source_dentry, page1);
+ if (IS_ERR(from_name)) {
+ rc = PTR_ERR(from_name);
+ goto cifs_rename_exit;
+ }
+
+ to_name = build_path_from_dentry(target_dentry, page2);
+ if (IS_ERR(to_name)) {
+ rc = PTR_ERR(to_name);
+ goto cifs_rename_exit;
+ }
+
+ cifs_close_deferred_file_under_dentry(tcon, from_name);
+ if (d_inode(target_dentry) != NULL)
+ cifs_close_deferred_file_under_dentry(tcon, to_name);
+
+ rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
+ to_name);
+
+ if (rc == -EACCES) {
+ while (retry_count < 3) {
+ cifs_close_all_deferred_files(tcon);
+ rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
+ to_name);
+ if (rc != -EACCES)
+ break;
+ retry_count++;
+ }
+ }
+
+ /*
+ * No-replace is the natural behavior for CIFS, so skip unlink hacks.
+ */
+ if (flags & RENAME_NOREPLACE)
+ goto cifs_rename_exit;
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (rc == -EEXIST && tcon->unix_ext) {
+ /*
+ * Are src and dst hardlinks of same inode? We can only tell
+ * with unix extensions enabled.
+ */
+ info_buf_source =
+ kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
+ GFP_KERNEL);
+ if (info_buf_source == NULL) {
+ rc = -ENOMEM;
+ goto cifs_rename_exit;
+ }
+
+ info_buf_target = info_buf_source + 1;
+ tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
+ info_buf_source,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ if (tmprc != 0)
+ goto unlink_target;
+
+ tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
+ info_buf_target,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+
+ if (tmprc == 0 && (info_buf_source->UniqueId ==
+ info_buf_target->UniqueId)) {
+ /* same file, POSIX says that this is a noop */
+ rc = 0;
+ goto cifs_rename_exit;
+ }
+ }
+ /*
+ * else ... BB we could add the same check for Windows by
+ * checking the UniqueId via FILE_INTERNAL_INFO
+ */
+
+unlink_target:
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ /* Try unlinking the target dentry if it's not negative */
+ if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
+ if (d_is_dir(target_dentry))
+ tmprc = cifs_rmdir(target_dir, target_dentry);
+ else
+ tmprc = cifs_unlink(target_dir, target_dentry);
+ if (tmprc)
+ goto cifs_rename_exit;
+ rc = cifs_do_rename(xid, source_dentry, from_name,
+ target_dentry, to_name);
+ }
+
+ /* force revalidate to go get info when needed */
+ CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
+
+ source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
+ target_dir->i_mtime = current_time(source_dir);
+
+cifs_rename_exit:
+ kfree(info_buf_source);
+ free_dentry_path(page2);
+ free_dentry_path(page1);
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+static bool
+cifs_dentry_needs_reval(struct dentry *dentry)
+{
+ struct inode *inode = d_inode(dentry);
+ struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ struct cached_fid *cfid = NULL;
+
+ if (cifs_i->time == 0)
+ return true;
+
+ if (CIFS_CACHE_READ(cifs_i))
+ return false;
+
+ if (!lookupCacheEnabled)
+ return true;
+
+ if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {
+ spin_lock(&cfid->fid_lock);
+ if (cfid->time && cifs_i->time > cfid->time) {
+ spin_unlock(&cfid->fid_lock);
+ close_cached_dir(cfid);
+ return false;
+ }
+ spin_unlock(&cfid->fid_lock);
+ close_cached_dir(cfid);
+ }
+ /*
+ * depending on inode type, check if attribute caching disabled for
+ * files or directories
+ */
+ if (S_ISDIR(inode->i_mode)) {
+ if (!cifs_sb->ctx->acdirmax)
+ return true;
+ if (!time_in_range(jiffies, cifs_i->time,
+ cifs_i->time + cifs_sb->ctx->acdirmax))
+ return true;
+ } else { /* file */
+ if (!cifs_sb->ctx->acregmax)
+ return true;
+ if (!time_in_range(jiffies, cifs_i->time,
+ cifs_i->time + cifs_sb->ctx->acregmax))
+ return true;
+ }
+
+ /* hardlinked files w/ noserverino get "special" treatment */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
+ S_ISREG(inode->i_mode) && inode->i_nlink != 1)
+ return true;
+
+ return false;
+}
+
+/*
+ * Zap the cache. Called when invalid_mapping flag is set.
+ */
+int
+cifs_invalidate_mapping(struct inode *inode)
+{
+ int rc = 0;
+
+ if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
+ rc = invalidate_inode_pages2(inode->i_mapping);
+ if (rc)
+ cifs_dbg(VFS, "%s: Could not invalidate inode %p\n",
+ __func__, inode);
+ }
+
+ return rc;
+}
+
+/**
+ * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
+ *
+ * @key: currently unused
+ * @mode: the task state to sleep in
+ */
+static int
+cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
+{
+ schedule();
+ if (signal_pending_state(mode, current))
+ return -ERESTARTSYS;
+ return 0;
+}
+
+int
+cifs_revalidate_mapping(struct inode *inode)
+{
+ int rc;
+ unsigned long *flags = &CIFS_I(inode)->flags;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+ /* swapfiles are not supposed to be shared */
+ if (IS_SWAPFILE(inode))
+ return 0;
+
+ rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
+ TASK_KILLABLE|TASK_FREEZABLE_UNSAFE);
+ if (rc)
+ return rc;
+
+ if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
+ /* for cache=singleclient, do not invalidate */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
+ goto skip_invalidate;
+
+ rc = cifs_invalidate_mapping(inode);
+ if (rc)
+ set_bit(CIFS_INO_INVALID_MAPPING, flags);
+ }
+
+skip_invalidate:
+ clear_bit_unlock(CIFS_INO_LOCK, flags);
+ smp_mb__after_atomic();
+ wake_up_bit(flags, CIFS_INO_LOCK);
+
+ return rc;
+}
+
+int
+cifs_zap_mapping(struct inode *inode)
+{
+ set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
+ return cifs_revalidate_mapping(inode);
+}
+
+int cifs_revalidate_file_attr(struct file *filp)
+{
+ int rc = 0;
+ struct dentry *dentry = file_dentry(filp);
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ if (!cifs_dentry_needs_reval(dentry))
+ return rc;
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (tlink_tcon(cfile->tlink)->unix_ext)
+ rc = cifs_get_file_info_unix(filp);
+ else
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ rc = cifs_get_file_info(filp);
+
+ return rc;
+}
+
+int cifs_revalidate_dentry_attr(struct dentry *dentry)
+{
+ unsigned int xid;
+ int rc = 0;
+ struct inode *inode = d_inode(dentry);
+ struct super_block *sb = dentry->d_sb;
+ const char *full_path;
+ void *page;
+ int count = 0;
+
+ if (inode == NULL)
+ return -ENOENT;
+
+ if (!cifs_dentry_needs_reval(dentry))
+ return rc;
+
+ xid = get_xid();
+
+ page = alloc_dentry_path();
+ full_path = build_path_from_dentry(dentry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto out;
+ }
+
+ cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
+ full_path, inode, inode->i_count.counter,
+ dentry, cifs_get_time(dentry), jiffies);
+
+again:
+ if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
+ rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
+ else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
+ rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
+ else
+ rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
+ xid, NULL);
+ if (rc == -EAGAIN && count++ < 10)
+ goto again;
+out:
+ free_dentry_path(page);
+ free_xid(xid);
+
+ return rc;
+}
+
+int cifs_revalidate_file(struct file *filp)
+{
+ int rc;
+ struct inode *inode = file_inode(filp);
+
+ rc = cifs_revalidate_file_attr(filp);
+ if (rc)
+ return rc;
+
+ return cifs_revalidate_mapping(inode);
+}
+
+/* revalidate a dentry's inode attributes */
+int cifs_revalidate_dentry(struct dentry *dentry)
+{
+ int rc;
+ struct inode *inode = d_inode(dentry);
+
+ rc = cifs_revalidate_dentry_attr(dentry);
+ if (rc)
+ return rc;
+
+ return cifs_revalidate_mapping(inode);
+}
+
+int cifs_getattr(struct user_namespace *mnt_userns, const struct path *path,
+ struct kstat *stat, u32 request_mask, unsigned int flags)
+{
+ struct dentry *dentry = path->dentry;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ struct inode *inode = d_inode(dentry);
+ int rc;
+
+ if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
+ return -EIO;
+
+ /*
+ * We need to be sure that all dirty pages are written and the server
+ * has actual ctime, mtime and file length.
+ */
+ if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE | STATX_BLOCKS)) &&
+ !CIFS_CACHE_READ(CIFS_I(inode)) &&
+ inode->i_mapping && inode->i_mapping->nrpages != 0) {
+ rc = filemap_fdatawait(inode->i_mapping);
+ if (rc) {
+ mapping_set_error(inode->i_mapping, rc);
+ return rc;
+ }
+ }
+
+ if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC)
+ CIFS_I(inode)->time = 0; /* force revalidate */
+
+ /*
+ * If the caller doesn't require syncing, only sync if
+ * necessary (e.g. due to earlier truncate or setattr
+ * invalidating the cached metadata)
+ */
+ if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) ||
+ (CIFS_I(inode)->time == 0)) {
+ rc = cifs_revalidate_dentry_attr(dentry);
+ if (rc)
+ return rc;
+ }
+
+ generic_fillattr(&init_user_ns, inode, stat);
+ stat->blksize = cifs_sb->ctx->bsize;
+ stat->ino = CIFS_I(inode)->uniqueid;
+
+ /* old CIFS Unix Extensions doesn't return create time */
+ if (CIFS_I(inode)->createtime) {
+ stat->result_mask |= STATX_BTIME;
+ stat->btime =
+ cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
+ }
+
+ stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
+ if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
+ stat->attributes |= STATX_ATTR_COMPRESSED;
+ if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
+ stat->attributes |= STATX_ATTR_ENCRYPTED;
+
+ /*
+ * If on a multiuser mount without unix extensions or cifsacl being
+ * enabled, and the admin hasn't overridden them, set the ownership
+ * to the fsuid/fsgid of the current process.
+ */
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
+ !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
+ !tcon->unix_ext) {
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
+ stat->uid = current_fsuid();
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
+ stat->gid = current_fsgid();
+ }
+ return 0;
+}
+
+int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
+ u64 len)
+{
+ struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->netfs.inode.i_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifsFileInfo *cfile;
+ int rc;
+
+ if (unlikely(cifs_forced_shutdown(cifs_sb)))
+ return -EIO;
+
+ /*
+ * We need to be sure that all dirty pages are written as they
+ * might fill holes on the server.
+ */
+ if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
+ inode->i_mapping->nrpages != 0) {
+ rc = filemap_fdatawait(inode->i_mapping);
+ if (rc) {
+ mapping_set_error(inode->i_mapping, rc);
+ return rc;
+ }
+ }
+
+ cfile = find_readable_file(cifs_i, false);
+ if (cfile == NULL)
+ return -EINVAL;
+
+ if (server->ops->fiemap) {
+ rc = server->ops->fiemap(tcon, cfile, fei, start, len);
+ cifsFileInfo_put(cfile);
+ return rc;
+ }
+
+ cifsFileInfo_put(cfile);
+ return -ENOTSUPP;
+}
+
+int cifs_truncate_page(struct address_space *mapping, loff_t from)
+{
+ pgoff_t index = from >> PAGE_SHIFT;
+ unsigned offset = from & (PAGE_SIZE - 1);
+ struct page *page;
+ int rc = 0;
+
+ page = grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+
+ zero_user_segment(page, offset, PAGE_SIZE);
+ unlock_page(page);
+ put_page(page);
+ return rc;
+}
+
+void cifs_setsize(struct inode *inode, loff_t offset)
+{
+ struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+
+ spin_lock(&inode->i_lock);
+ i_size_write(inode, offset);
+ spin_unlock(&inode->i_lock);
+
+ /* Cached inode must be refreshed on truncate */
+ cifs_i->time = 0;
+ truncate_pagecache(inode, offset);
+}
+
+static int
+cifs_set_file_size(struct inode *inode, struct iattr *attrs,
+ unsigned int xid, const char *full_path)
+{
+ int rc;
+ struct cifsFileInfo *open_file;
+ struct cifsInodeInfo *cifsInode = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink = NULL;
+ struct cifs_tcon *tcon = NULL;
+ struct TCP_Server_Info *server;
+
+ /*
+ * To avoid spurious oplock breaks from server, in the case of
+ * inodes that we already have open, avoid doing path based
+ * setting of file size if we can do it by handle.
+ * This keeps our caching token (oplock) and avoids timeouts
+ * when the local oplock break takes longer to flush
+ * writebehind data than the SMB timeout for the SetPathInfo
+ * request would allow
+ */
+ open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
+ if (open_file) {
+ tcon = tlink_tcon(open_file->tlink);
+ server = tcon->ses->server;
+ if (server->ops->set_file_size)
+ rc = server->ops->set_file_size(xid, tcon, open_file,
+ attrs->ia_size, false);
+ else
+ rc = -ENOSYS;
+ cifsFileInfo_put(open_file);
+ cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
+ } else
+ rc = -EINVAL;
+
+ if (!rc)
+ goto set_size_out;
+
+ if (tcon == NULL) {
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+ }
+
+ /*
+ * Set file size by pathname rather than by handle either because no
+ * valid, writeable file handle for it was found or because there was
+ * an error setting it by handle.
+ */
+ if (server->ops->set_path_size)
+ rc = server->ops->set_path_size(xid, tcon, full_path,
+ attrs->ia_size, cifs_sb, false);
+ else
+ rc = -ENOSYS;
+ cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
+
+ if (tlink)
+ cifs_put_tlink(tlink);
+
+set_size_out:
+ if (rc == 0) {
+ cifsInode->server_eof = attrs->ia_size;
+ cifs_setsize(inode, attrs->ia_size);
+ /*
+ * i_blocks is not related to (i_size / i_blksize), but instead
+ * 512 byte (2**9) size is required for calculating num blocks.
+ * Until we can query the server for actual allocation size,
+ * this is best estimate we have for blocks allocated for a file
+ * Number of blocks must be rounded up so size 1 is not 0 blocks
+ */
+ inode->i_blocks = (512 - 1 + attrs->ia_size) >> 9;
+
+ /*
+ * The man page of truncate says if the size changed,
+ * then the st_ctime and st_mtime fields for the file
+ * are updated.
+ */
+ attrs->ia_ctime = attrs->ia_mtime = current_time(inode);
+ attrs->ia_valid |= ATTR_CTIME | ATTR_MTIME;
+
+ cifs_truncate_page(inode->i_mapping, inode->i_size);
+ }
+
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+static int
+cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
+{
+ int rc;
+ unsigned int xid;
+ const char *full_path;
+ void *page = alloc_dentry_path();
+ struct inode *inode = d_inode(direntry);
+ struct cifsInodeInfo *cifsInode = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *pTcon;
+ struct cifs_unix_set_info_args *args = NULL;
+ struct cifsFileInfo *open_file;
+
+ cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
+ direntry, attrs->ia_valid);
+
+ xid = get_xid();
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
+ attrs->ia_valid |= ATTR_FORCE;
+
+ rc = setattr_prepare(&init_user_ns, direntry, attrs);
+ if (rc < 0)
+ goto out;
+
+ full_path = build_path_from_dentry(direntry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto out;
+ }
+
+ /*
+ * Attempt to flush data before changing attributes. We need to do
+ * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
+ * ownership or mode then we may also need to do this. Here, we take
+ * the safe way out and just do the flush on all setattr requests. If
+ * the flush returns error, store it to report later and continue.
+ *
+ * BB: This should be smarter. Why bother flushing pages that
+ * will be truncated anyway? Also, should we error out here if
+ * the flush returns error?
+ */
+ rc = filemap_write_and_wait(inode->i_mapping);
+ if (is_interrupt_error(rc)) {
+ rc = -ERESTARTSYS;
+ goto out;
+ }
+
+ mapping_set_error(inode->i_mapping, rc);
+ rc = 0;
+
+ if (attrs->ia_valid & ATTR_SIZE) {
+ rc = cifs_set_file_size(inode, attrs, xid, full_path);
+ if (rc != 0)
+ goto out;
+ }
+
+ /* skip mode change if it's just for clearing setuid/setgid */
+ if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+ attrs->ia_valid &= ~ATTR_MODE;
+
+ args = kmalloc(sizeof(*args), GFP_KERNEL);
+ if (args == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* set up the struct */
+ if (attrs->ia_valid & ATTR_MODE)
+ args->mode = attrs->ia_mode;
+ else
+ args->mode = NO_CHANGE_64;
+
+ if (attrs->ia_valid & ATTR_UID)
+ args->uid = attrs->ia_uid;
+ else
+ args->uid = INVALID_UID; /* no change */
+
+ if (attrs->ia_valid & ATTR_GID)
+ args->gid = attrs->ia_gid;
+ else
+ args->gid = INVALID_GID; /* no change */
+
+ if (attrs->ia_valid & ATTR_ATIME)
+ args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
+ else
+ args->atime = NO_CHANGE_64;
+
+ if (attrs->ia_valid & ATTR_MTIME)
+ args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
+ else
+ args->mtime = NO_CHANGE_64;
+
+ if (attrs->ia_valid & ATTR_CTIME)
+ args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
+ else
+ args->ctime = NO_CHANGE_64;
+
+ args->device = 0;
+ open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
+ if (open_file) {
+ u16 nfid = open_file->fid.netfid;
+ u32 npid = open_file->pid;
+ pTcon = tlink_tcon(open_file->tlink);
+ rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
+ cifsFileInfo_put(open_file);
+ } else {
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink)) {
+ rc = PTR_ERR(tlink);
+ goto out;
+ }
+ pTcon = tlink_tcon(tlink);
+ rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ cifs_put_tlink(tlink);
+ }
+
+ if (rc)
+ goto out;
+
+ if ((attrs->ia_valid & ATTR_SIZE) &&
+ attrs->ia_size != i_size_read(inode)) {
+ truncate_setsize(inode, attrs->ia_size);
+ fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size);
+ }
+
+ setattr_copy(&init_user_ns, inode, attrs);
+ mark_inode_dirty(inode);
+
+ /* force revalidate when any of these times are set since some
+ of the fs types (eg ext3, fat) do not have fine enough
+ time granularity to match protocol, and we do not have a
+ a way (yet) to query the server fs's time granularity (and
+ whether it rounds times down).
+ */
+ if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
+ cifsInode->time = 0;
+out:
+ kfree(args);
+ free_dentry_path(page);
+ free_xid(xid);
+ return rc;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+static int
+cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
+{
+ unsigned int xid;
+ kuid_t uid = INVALID_UID;
+ kgid_t gid = INVALID_GID;
+ struct inode *inode = d_inode(direntry);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifsInodeInfo *cifsInode = CIFS_I(inode);
+ struct cifsFileInfo *wfile;
+ struct cifs_tcon *tcon;
+ const char *full_path;
+ void *page = alloc_dentry_path();
+ int rc = -EACCES;
+ __u32 dosattr = 0;
+ __u64 mode = NO_CHANGE_64;
+
+ xid = get_xid();
+
+ cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
+ direntry, attrs->ia_valid);
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
+ attrs->ia_valid |= ATTR_FORCE;
+
+ rc = setattr_prepare(&init_user_ns, direntry, attrs);
+ if (rc < 0)
+ goto cifs_setattr_exit;
+
+ full_path = build_path_from_dentry(direntry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto cifs_setattr_exit;
+ }
+
+ /*
+ * Attempt to flush data before changing attributes. We need to do
+ * this for ATTR_SIZE and ATTR_MTIME. If the flush of the data
+ * returns error, store it to report later and continue.
+ *
+ * BB: This should be smarter. Why bother flushing pages that
+ * will be truncated anyway? Also, should we error out here if
+ * the flush returns error? Do we need to check for ATTR_MTIME_SET flag?
+ */
+ if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) {
+ rc = filemap_write_and_wait(inode->i_mapping);
+ if (is_interrupt_error(rc)) {
+ rc = -ERESTARTSYS;
+ goto cifs_setattr_exit;
+ }
+ mapping_set_error(inode->i_mapping, rc);
+ }
+
+ rc = 0;
+
+ if ((attrs->ia_valid & ATTR_MTIME) &&
+ !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
+ rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
+ if (!rc) {
+ tcon = tlink_tcon(wfile->tlink);
+ rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
+ cifsFileInfo_put(wfile);
+ if (rc)
+ goto cifs_setattr_exit;
+ } else if (rc != -EBADF)
+ goto cifs_setattr_exit;
+ else
+ rc = 0;
+ }
+
+ if (attrs->ia_valid & ATTR_SIZE) {
+ rc = cifs_set_file_size(inode, attrs, xid, full_path);
+ if (rc != 0)
+ goto cifs_setattr_exit;
+ }
+
+ if (attrs->ia_valid & ATTR_UID)
+ uid = attrs->ia_uid;
+
+ if (attrs->ia_valid & ATTR_GID)
+ gid = attrs->ia_gid;
+
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
+ if (uid_valid(uid) || gid_valid(gid)) {
+ mode = NO_CHANGE_64;
+ rc = id_mode_to_cifs_acl(inode, full_path, &mode,
+ uid, gid);
+ if (rc) {
+ cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
+ __func__, rc);
+ goto cifs_setattr_exit;
+ }
+ }
+ } else
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
+ attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
+
+ /* skip mode change if it's just for clearing setuid/setgid */
+ if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+ attrs->ia_valid &= ~ATTR_MODE;
+
+ if (attrs->ia_valid & ATTR_MODE) {
+ mode = attrs->ia_mode;
+ rc = 0;
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
+ rc = id_mode_to_cifs_acl(inode, full_path, &mode,
+ INVALID_UID, INVALID_GID);
+ if (rc) {
+ cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
+ __func__, rc);
+ goto cifs_setattr_exit;
+ }
+
+ /*
+ * In case of CIFS_MOUNT_CIFS_ACL, we cannot support all modes.
+ * Pick up the actual mode bits that were set.
+ */
+ if (mode != attrs->ia_mode)
+ attrs->ia_mode = mode;
+ } else
+ if (((mode & S_IWUGO) == 0) &&
+ (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
+
+ dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
+
+ /* fix up mode if we're not using dynperm */
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
+ attrs->ia_mode = inode->i_mode & ~S_IWUGO;
+ } else if ((mode & S_IWUGO) &&
+ (cifsInode->cifsAttrs & ATTR_READONLY)) {
+
+ dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
+ /* Attributes of 0 are ignored */
+ if (dosattr == 0)
+ dosattr |= ATTR_NORMAL;
+
+ /* reset local inode permissions to normal */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
+ attrs->ia_mode &= ~(S_IALLUGO);
+ if (S_ISDIR(inode->i_mode))
+ attrs->ia_mode |=
+ cifs_sb->ctx->dir_mode;
+ else
+ attrs->ia_mode |=
+ cifs_sb->ctx->file_mode;
+ }
+ } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
+ /* ignore mode change - ATTR_READONLY hasn't changed */
+ attrs->ia_valid &= ~ATTR_MODE;
+ }
+ }
+
+ if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
+ ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
+ rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
+ /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
+
+ /* Even if error on time set, no sense failing the call if
+ the server would set the time to a reasonable value anyway,
+ and this check ensures that we are not being called from
+ sys_utimes in which case we ought to fail the call back to
+ the user when the server rejects the call */
+ if ((rc) && (attrs->ia_valid &
+ (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
+ rc = 0;
+ }
+
+ /* do not need local check to inode_check_ok since the server does
+ that */
+ if (rc)
+ goto cifs_setattr_exit;
+
+ if ((attrs->ia_valid & ATTR_SIZE) &&
+ attrs->ia_size != i_size_read(inode)) {
+ truncate_setsize(inode, attrs->ia_size);
+ fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size);
+ }
+
+ setattr_copy(&init_user_ns, inode, attrs);
+ mark_inode_dirty(inode);
+
+cifs_setattr_exit:
+ free_xid(xid);
+ free_dentry_path(page);
+ return rc;
+}
+
+int
+cifs_setattr(struct user_namespace *mnt_userns, struct dentry *direntry,
+ struct iattr *attrs)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+ int rc, retries = 0;
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+ if (unlikely(cifs_forced_shutdown(cifs_sb)))
+ return -EIO;
+
+ do {
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (pTcon->unix_ext)
+ rc = cifs_setattr_unix(direntry, attrs);
+ else
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ rc = cifs_setattr_nounix(direntry, attrs);
+ retries++;
+ } while (is_retryable_error(rc) && retries < 2);
+
+ /* BB: add cifs_setattr_legacy for really old servers */
+ return rc;
+}
diff --git a/fs/smb/client/ioctl.c b/fs/smb/client/ioctl.c
new file mode 100644
index 000000000000..6419ec47c2a8
--- /dev/null
+++ b/fs/smb/client/ioctl.c
@@ -0,0 +1,526 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * vfs operations that deal with io control
+ *
+ * Copyright (C) International Business Machines Corp., 2005,2013
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifsfs.h"
+#include "cifs_ioctl.h"
+#include "smb2proto.h"
+#include "smb2glob.h"
+#include <linux/btrfs.h>
+
+static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
+ unsigned long p)
+{
+ struct inode *inode = file_inode(filep);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ struct dentry *dentry = filep->f_path.dentry;
+ const unsigned char *path;
+ void *page = alloc_dentry_path();
+ __le16 *utf16_path = NULL, root_path;
+ int rc = 0;
+
+ path = build_path_from_dentry(dentry, page);
+ if (IS_ERR(path)) {
+ free_dentry_path(page);
+ return PTR_ERR(path);
+ }
+
+ cifs_dbg(FYI, "%s %s\n", __func__, path);
+
+ if (!path[0]) {
+ root_path = 0;
+ utf16_path = &root_path;
+ } else {
+ utf16_path = cifs_convert_path_to_utf16(path + 1, cifs_sb);
+ if (!utf16_path) {
+ rc = -ENOMEM;
+ goto ici_exit;
+ }
+ }
+
+ if (tcon->ses->server->ops->ioctl_query_info)
+ rc = tcon->ses->server->ops->ioctl_query_info(
+ xid, tcon, cifs_sb, utf16_path,
+ filep->private_data ? 0 : 1, p);
+ else
+ rc = -EOPNOTSUPP;
+
+ ici_exit:
+ if (utf16_path != &root_path)
+ kfree(utf16_path);
+ free_dentry_path(page);
+ return rc;
+}
+
+static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
+ unsigned long srcfd)
+{
+ int rc;
+ struct fd src_file;
+ struct inode *src_inode;
+
+ cifs_dbg(FYI, "ioctl copychunk range\n");
+ /* the destination must be opened for writing */
+ if (!(dst_file->f_mode & FMODE_WRITE)) {
+ cifs_dbg(FYI, "file target not open for write\n");
+ return -EINVAL;
+ }
+
+ /* check if target volume is readonly and take reference */
+ rc = mnt_want_write_file(dst_file);
+ if (rc) {
+ cifs_dbg(FYI, "mnt_want_write failed with rc %d\n", rc);
+ return rc;
+ }
+
+ src_file = fdget(srcfd);
+ if (!src_file.file) {
+ rc = -EBADF;
+ goto out_drop_write;
+ }
+
+ if (src_file.file->f_op->unlocked_ioctl != cifs_ioctl) {
+ rc = -EBADF;
+ cifs_dbg(VFS, "src file seems to be from a different filesystem type\n");
+ goto out_fput;
+ }
+
+ src_inode = file_inode(src_file.file);
+ rc = -EINVAL;
+ if (S_ISDIR(src_inode->i_mode))
+ goto out_fput;
+
+ rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
+ src_inode->i_size, 0);
+ if (rc > 0)
+ rc = 0;
+out_fput:
+ fdput(src_file);
+out_drop_write:
+ mnt_drop_write_file(dst_file);
+ return rc;
+}
+
+static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
+ void __user *arg)
+{
+ int rc = 0;
+ struct smb_mnt_fs_info *fsinf;
+
+ fsinf = kzalloc(sizeof(struct smb_mnt_fs_info), GFP_KERNEL);
+ if (fsinf == NULL)
+ return -ENOMEM;
+
+ fsinf->version = 1;
+ fsinf->protocol_id = tcon->ses->server->vals->protocol_id;
+ fsinf->device_characteristics =
+ le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics);
+ fsinf->device_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
+ fsinf->fs_attributes = le32_to_cpu(tcon->fsAttrInfo.Attributes);
+ fsinf->max_path_component =
+ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength);
+ fsinf->vol_serial_number = tcon->vol_serial_number;
+ fsinf->vol_create_time = le64_to_cpu(tcon->vol_create_time);
+ fsinf->share_flags = tcon->share_flags;
+ fsinf->share_caps = le32_to_cpu(tcon->capabilities);
+ fsinf->sector_flags = tcon->ss_flags;
+ fsinf->optimal_sector_size = tcon->perf_sector_size;
+ fsinf->max_bytes_chunk = tcon->max_bytes_chunk;
+ fsinf->maximal_access = tcon->maximal_access;
+ fsinf->cifs_posix_caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
+
+ if (copy_to_user(arg, fsinf, sizeof(struct smb_mnt_fs_info)))
+ rc = -EFAULT;
+
+ kfree(fsinf);
+ return rc;
+}
+
+static int cifs_shutdown(struct super_block *sb, unsigned long arg)
+{
+ struct cifs_sb_info *sbi = CIFS_SB(sb);
+ __u32 flags;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (get_user(flags, (__u32 __user *)arg))
+ return -EFAULT;
+
+ if (flags > CIFS_GOING_FLAGS_NOLOGFLUSH)
+ return -EINVAL;
+
+ if (cifs_forced_shutdown(sbi))
+ return 0;
+
+ cifs_dbg(VFS, "shut down requested (%d)", flags);
+/* trace_cifs_shutdown(sb, flags);*/
+
+ /*
+ * see:
+ * https://man7.org/linux/man-pages/man2/ioctl_xfs_goingdown.2.html
+ * for more information and description of original intent of the flags
+ */
+ switch (flags) {
+ /*
+ * We could add support later for default flag which requires:
+ * "Flush all dirty data and metadata to disk"
+ * would need to call syncfs or equivalent to flush page cache for
+ * the mount and then issue fsync to server (if nostrictsync not set)
+ */
+ case CIFS_GOING_FLAGS_DEFAULT:
+ cifs_dbg(FYI, "shutdown with default flag not supported\n");
+ return -EINVAL;
+ /*
+ * FLAGS_LOGFLUSH is easy since it asks to write out metadata (not
+ * data) but metadata writes are not cached on the client, so can treat
+ * it similarly to NOLOGFLUSH
+ */
+ case CIFS_GOING_FLAGS_LOGFLUSH:
+ case CIFS_GOING_FLAGS_NOLOGFLUSH:
+ sbi->mnt_cifs_flags |= CIFS_MOUNT_SHUTDOWN;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug_info __user *in)
+{
+ struct smb3_full_key_debug_info out;
+ struct cifs_ses *ses;
+ int rc = 0;
+ bool found = false;
+ u8 __user *end;
+
+ if (!smb3_encryption_required(tcon)) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* copy user input into our output buffer */
+ if (copy_from_user(&out, in, sizeof(out))) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (!out.session_id) {
+ /* if ses id is 0, use current user session */
+ ses = tcon->ses;
+ } else {
+ /* otherwise if a session id is given, look for it in all our sessions */
+ struct cifs_ses *ses_it = NULL;
+ struct TCP_Server_Info *server_it = NULL;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(server_it, &cifs_tcp_ses_list, tcp_ses_list) {
+ list_for_each_entry(ses_it, &server_it->smb_ses_list, smb_ses_list) {
+ if (ses_it->Suid == out.session_id) {
+ ses = ses_it;
+ /*
+ * since we are using the session outside the crit
+ * section, we need to make sure it won't be released
+ * so increment its refcount
+ */
+ ses->ses_count++;
+ found = true;
+ goto search_end;
+ }
+ }
+ }
+search_end:
+ spin_unlock(&cifs_tcp_ses_lock);
+ if (!found) {
+ rc = -ENOENT;
+ goto out;
+ }
+ }
+
+ switch (ses->server->cipher_type) {
+ case SMB2_ENCRYPTION_AES128_CCM:
+ case SMB2_ENCRYPTION_AES128_GCM:
+ out.session_key_length = CIFS_SESS_KEY_SIZE;
+ out.server_in_key_length = out.server_out_key_length = SMB3_GCM128_CRYPTKEY_SIZE;
+ break;
+ case SMB2_ENCRYPTION_AES256_CCM:
+ case SMB2_ENCRYPTION_AES256_GCM:
+ out.session_key_length = CIFS_SESS_KEY_SIZE;
+ out.server_in_key_length = out.server_out_key_length = SMB3_GCM256_CRYPTKEY_SIZE;
+ break;
+ default:
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* check if user buffer is big enough to store all the keys */
+ if (out.in_size < sizeof(out) + out.session_key_length + out.server_in_key_length
+ + out.server_out_key_length) {
+ rc = -ENOBUFS;
+ goto out;
+ }
+
+ out.session_id = ses->Suid;
+ out.cipher_type = le16_to_cpu(ses->server->cipher_type);
+
+ /* overwrite user input with our output */
+ if (copy_to_user(in, &out, sizeof(out))) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* append all the keys at the end of the user buffer */
+ end = in->data;
+ if (copy_to_user(end, ses->auth_key.response, out.session_key_length)) {
+ rc = -EINVAL;
+ goto out;
+ }
+ end += out.session_key_length;
+
+ if (copy_to_user(end, ses->smb3encryptionkey, out.server_in_key_length)) {
+ rc = -EINVAL;
+ goto out;
+ }
+ end += out.server_in_key_length;
+
+ if (copy_to_user(end, ses->smb3decryptionkey, out.server_out_key_length)) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+out:
+ if (found)
+ cifs_put_smb_ses(ses);
+ return rc;
+}
+
+long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
+{
+ struct inode *inode = file_inode(filep);
+ struct smb3_key_debug_info pkey_inf;
+ int rc = -ENOTTY; /* strange error - but the precedent */
+ unsigned int xid;
+ struct cifsFileInfo *pSMBFile = filep->private_data;
+ struct cifs_tcon *tcon;
+ struct tcon_link *tlink;
+ struct cifs_sb_info *cifs_sb;
+ __u64 ExtAttrBits = 0;
+ __u64 caps;
+
+ xid = get_xid();
+
+ cifs_dbg(FYI, "cifs ioctl 0x%x\n", command);
+ switch (command) {
+ case FS_IOC_GETFLAGS:
+ if (pSMBFile == NULL)
+ break;
+ tcon = tlink_tcon(pSMBFile->tlink);
+ caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
+#ifdef CONFIG_CIFS_POSIX
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (CIFS_UNIX_EXTATTR_CAP & caps) {
+ __u64 ExtAttrMask = 0;
+ rc = CIFSGetExtAttr(xid, tcon,
+ pSMBFile->fid.netfid,
+ &ExtAttrBits, &ExtAttrMask);
+ if (rc == 0)
+ rc = put_user(ExtAttrBits &
+ FS_FL_USER_VISIBLE,
+ (int __user *)arg);
+ if (rc != -EOPNOTSUPP)
+ break;
+ }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+#endif /* CONFIG_CIFS_POSIX */
+ rc = 0;
+ if (CIFS_I(inode)->cifsAttrs & ATTR_COMPRESSED) {
+ /* add in the compressed bit */
+ ExtAttrBits = FS_COMPR_FL;
+ rc = put_user(ExtAttrBits & FS_FL_USER_VISIBLE,
+ (int __user *)arg);
+ }
+ break;
+ case FS_IOC_SETFLAGS:
+ if (pSMBFile == NULL)
+ break;
+ tcon = tlink_tcon(pSMBFile->tlink);
+ /* caps = le64_to_cpu(tcon->fsUnixInfo.Capability); */
+
+ if (get_user(ExtAttrBits, (int __user *)arg)) {
+ rc = -EFAULT;
+ break;
+ }
+
+ /*
+ * if (CIFS_UNIX_EXTATTR_CAP & caps)
+ * rc = CIFSSetExtAttr(xid, tcon,
+ * pSMBFile->fid.netfid,
+ * extAttrBits,
+ * &ExtAttrMask);
+ * if (rc != -EOPNOTSUPP)
+ * break;
+ */
+
+ /* Currently only flag we can set is compressed flag */
+ if ((ExtAttrBits & FS_COMPR_FL) == 0)
+ break;
+
+ /* Try to set compress flag */
+ if (tcon->ses->server->ops->set_compression) {
+ rc = tcon->ses->server->ops->set_compression(
+ xid, tcon, pSMBFile);
+ cifs_dbg(FYI, "set compress flag rc %d\n", rc);
+ }
+ break;
+ case CIFS_IOC_COPYCHUNK_FILE:
+ rc = cifs_ioctl_copychunk(xid, filep, arg);
+ break;
+ case CIFS_QUERY_INFO:
+ rc = cifs_ioctl_query_info(xid, filep, arg);
+ break;
+ case CIFS_IOC_SET_INTEGRITY:
+ if (pSMBFile == NULL)
+ break;
+ tcon = tlink_tcon(pSMBFile->tlink);
+ if (tcon->ses->server->ops->set_integrity)
+ rc = tcon->ses->server->ops->set_integrity(xid,
+ tcon, pSMBFile);
+ else
+ rc = -EOPNOTSUPP;
+ break;
+ case CIFS_IOC_GET_MNT_INFO:
+ if (pSMBFile == NULL)
+ break;
+ tcon = tlink_tcon(pSMBFile->tlink);
+ rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg);
+ break;
+ case CIFS_ENUMERATE_SNAPSHOTS:
+ if (pSMBFile == NULL)
+ break;
+ if (arg == 0) {
+ rc = -EINVAL;
+ goto cifs_ioc_exit;
+ }
+ tcon = tlink_tcon(pSMBFile->tlink);
+ if (tcon->ses->server->ops->enum_snapshots)
+ rc = tcon->ses->server->ops->enum_snapshots(xid, tcon,
+ pSMBFile, (void __user *)arg);
+ else
+ rc = -EOPNOTSUPP;
+ break;
+ case CIFS_DUMP_KEY:
+ /*
+ * Dump encryption keys. This is an old ioctl that only
+ * handles AES-128-{CCM,GCM}.
+ */
+ if (pSMBFile == NULL)
+ break;
+ if (!capable(CAP_SYS_ADMIN)) {
+ rc = -EACCES;
+ break;
+ }
+
+ tcon = tlink_tcon(pSMBFile->tlink);
+ if (!smb3_encryption_required(tcon)) {
+ rc = -EOPNOTSUPP;
+ break;
+ }
+ pkey_inf.cipher_type =
+ le16_to_cpu(tcon->ses->server->cipher_type);
+ pkey_inf.Suid = tcon->ses->Suid;
+ memcpy(pkey_inf.auth_key, tcon->ses->auth_key.response,
+ 16 /* SMB2_NTLMV2_SESSKEY_SIZE */);
+ memcpy(pkey_inf.smb3decryptionkey,
+ tcon->ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE);
+ memcpy(pkey_inf.smb3encryptionkey,
+ tcon->ses->smb3encryptionkey, SMB3_SIGN_KEY_SIZE);
+ if (copy_to_user((void __user *)arg, &pkey_inf,
+ sizeof(struct smb3_key_debug_info)))
+ rc = -EFAULT;
+ else
+ rc = 0;
+ break;
+ case CIFS_DUMP_FULL_KEY:
+ /*
+ * Dump encryption keys (handles any key sizes)
+ */
+ if (pSMBFile == NULL)
+ break;
+ if (!capable(CAP_SYS_ADMIN)) {
+ rc = -EACCES;
+ break;
+ }
+ tcon = tlink_tcon(pSMBFile->tlink);
+ rc = cifs_dump_full_key(tcon, (void __user *)arg);
+ break;
+ case CIFS_IOC_NOTIFY:
+ if (!S_ISDIR(inode->i_mode)) {
+ /* Notify can only be done on directories */
+ rc = -EOPNOTSUPP;
+ break;
+ }
+ cifs_sb = CIFS_SB(inode->i_sb);
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink)) {
+ rc = PTR_ERR(tlink);
+ break;
+ }
+ tcon = tlink_tcon(tlink);
+ if (tcon && tcon->ses->server->ops->notify) {
+ rc = tcon->ses->server->ops->notify(xid,
+ filep, (void __user *)arg,
+ false /* no ret data */);
+ cifs_dbg(FYI, "ioctl notify rc %d\n", rc);
+ } else
+ rc = -EOPNOTSUPP;
+ cifs_put_tlink(tlink);
+ break;
+ case CIFS_IOC_NOTIFY_INFO:
+ if (!S_ISDIR(inode->i_mode)) {
+ /* Notify can only be done on directories */
+ rc = -EOPNOTSUPP;
+ break;
+ }
+ cifs_sb = CIFS_SB(inode->i_sb);
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink)) {
+ rc = PTR_ERR(tlink);
+ break;
+ }
+ tcon = tlink_tcon(tlink);
+ if (tcon && tcon->ses->server->ops->notify) {
+ rc = tcon->ses->server->ops->notify(xid,
+ filep, (void __user *)arg,
+ true /* return details */);
+ cifs_dbg(FYI, "ioctl notify info rc %d\n", rc);
+ } else
+ rc = -EOPNOTSUPP;
+ cifs_put_tlink(tlink);
+ break;
+ case CIFS_IOC_SHUTDOWN:
+ rc = cifs_shutdown(inode->i_sb, arg);
+ break;
+ default:
+ cifs_dbg(FYI, "unsupported ioctl\n");
+ break;
+ }
+cifs_ioc_exit:
+ free_xid(xid);
+ return rc;
+}
diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c
new file mode 100644
index 000000000000..c0f101fc1e5d
--- /dev/null
+++ b/fs/smb/client/link.c
@@ -0,0 +1,650 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/namei.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifs_unicode.h"
+#include "smb2proto.h"
+#include "cifs_ioctl.h"
+
+/*
+ * M-F Symlink Functions - Begin
+ */
+
+#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
+#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
+#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
+#define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
+#define CIFS_MF_SYMLINK_FILE_SIZE \
+ (CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
+
+#define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
+#define CIFS_MF_SYMLINK_MD5_FORMAT "%16phN\n"
+#define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) md5_hash
+
+static int
+symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
+{
+ int rc;
+ struct shash_desc *md5 = NULL;
+
+ rc = cifs_alloc_hash("md5", &md5);
+ if (rc)
+ goto symlink_hash_err;
+
+ rc = crypto_shash_init(md5);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__);
+ goto symlink_hash_err;
+ }
+ rc = crypto_shash_update(md5, link_str, link_len);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
+ goto symlink_hash_err;
+ }
+ rc = crypto_shash_final(md5, md5_hash);
+ if (rc)
+ cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
+
+symlink_hash_err:
+ cifs_free_hash(&md5);
+ return rc;
+}
+
+static int
+parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
+ char **_link_str)
+{
+ int rc;
+ unsigned int link_len;
+ const char *md5_str1;
+ const char *link_str;
+ u8 md5_hash[16];
+ char md5_str2[34];
+
+ if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+ return -EINVAL;
+
+ md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
+ link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
+
+ rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
+ if (rc != 1)
+ return -EINVAL;
+
+ if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
+ return -EINVAL;
+
+ rc = symlink_hash(link_len, link_str, md5_hash);
+ if (rc) {
+ cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
+ return rc;
+ }
+
+ scnprintf(md5_str2, sizeof(md5_str2),
+ CIFS_MF_SYMLINK_MD5_FORMAT,
+ CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+ if (strncmp(md5_str1, md5_str2, 17) != 0)
+ return -EINVAL;
+
+ if (_link_str) {
+ *_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
+ if (!*_link_str)
+ return -ENOMEM;
+ }
+
+ *_link_len = link_len;
+ return 0;
+}
+
+static int
+format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
+{
+ int rc;
+ unsigned int link_len;
+ unsigned int ofs;
+ u8 md5_hash[16];
+
+ if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+ return -EINVAL;
+
+ link_len = strlen(link_str);
+
+ if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
+ return -ENAMETOOLONG;
+
+ rc = symlink_hash(link_len, link_str, md5_hash);
+ if (rc) {
+ cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
+ return rc;
+ }
+
+ scnprintf(buf, buf_len,
+ CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
+ link_len,
+ CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+ ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
+ memcpy(buf + ofs, link_str, link_len);
+
+ ofs += link_len;
+ if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+ buf[ofs] = '\n';
+ ofs++;
+ }
+
+ while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+ buf[ofs] = ' ';
+ ofs++;
+ }
+
+ return 0;
+}
+
+bool
+couldbe_mf_symlink(const struct cifs_fattr *fattr)
+{
+ if (!S_ISREG(fattr->cf_mode))
+ /* it's not a symlink */
+ return false;
+
+ if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
+ /* it's not a symlink */
+ return false;
+
+ return true;
+}
+
+static int
+create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *fromName,
+ const char *toName)
+{
+ int rc;
+ u8 *buf;
+ unsigned int bytes_written = 0;
+
+ buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
+ if (rc)
+ goto out;
+
+ if (tcon->ses->server->ops->create_mf_symlink)
+ rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon,
+ cifs_sb, fromName, buf, &bytes_written);
+ else
+ rc = -EOPNOTSUPP;
+
+ if (rc)
+ goto out;
+
+ if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
+ rc = -EIO;
+out:
+ kfree(buf);
+ return rc;
+}
+
+int
+check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
+ const unsigned char *path)
+{
+ int rc;
+ u8 *buf = NULL;
+ unsigned int link_len = 0;
+ unsigned int bytes_read = 0;
+ char *symlink = NULL;
+
+ if (!couldbe_mf_symlink(fattr))
+ /* it's not a symlink */
+ return 0;
+
+ buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (tcon->ses->server->ops->query_mf_symlink)
+ rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
+ cifs_sb, path, buf, &bytes_read);
+ else
+ rc = -ENOSYS;
+
+ if (rc)
+ goto out;
+
+ if (bytes_read == 0) /* not a symlink */
+ goto out;
+
+ rc = parse_mf_symlink(buf, bytes_read, &link_len, &symlink);
+ if (rc == -EINVAL) {
+ /* it's not a symlink */
+ rc = 0;
+ goto out;
+ }
+
+ if (rc != 0)
+ goto out;
+
+ /* it is a symlink */
+ fattr->cf_eof = link_len;
+ fattr->cf_mode &= ~S_IFMT;
+ fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
+ fattr->cf_dtype = DT_LNK;
+ fattr->cf_symlink_target = symlink;
+out:
+ kfree(buf);
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+/*
+ * SMB 1.0 Protocol specific functions
+ */
+
+int
+cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const unsigned char *path,
+ char *pbuf, unsigned int *pbytes_read)
+{
+ int rc;
+ int oplock = 0;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ struct cifs_io_parms io_parms = {0};
+ int buf_type = CIFS_NO_BUFFER;
+ FILE_ALL_INFO file_info;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = GENERIC_READ,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
+ .disposition = FILE_OPEN,
+ .path = path,
+ .fid = &fid,
+ };
+
+ rc = CIFS_open(xid, &oparms, &oplock, &file_info);
+ if (rc)
+ return rc;
+
+ if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
+ rc = -ENOENT;
+ /* it's not a symlink */
+ goto out;
+ }
+
+ io_parms.netfid = fid.netfid;
+ io_parms.pid = current->tgid;
+ io_parms.tcon = tcon;
+ io_parms.offset = 0;
+ io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
+
+ rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
+out:
+ CIFSSMBClose(xid, tcon, fid.netfid);
+ return rc;
+}
+
+int
+cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const unsigned char *path,
+ char *pbuf, unsigned int *pbytes_written)
+{
+ int rc;
+ int oplock = 0;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ struct cifs_io_parms io_parms = {0};
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = GENERIC_WRITE,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
+ .disposition = FILE_CREATE,
+ .path = path,
+ .fid = &fid,
+ };
+
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (rc)
+ return rc;
+
+ io_parms.netfid = fid.netfid;
+ io_parms.pid = current->tgid;
+ io_parms.tcon = tcon;
+ io_parms.offset = 0;
+ io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
+
+ rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf);
+ CIFSSMBClose(xid, tcon, fid.netfid);
+ return rc;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+/*
+ * SMB 2.1/SMB3 Protocol specific functions
+ */
+int
+smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const unsigned char *path,
+ char *pbuf, unsigned int *pbytes_read)
+{
+ int rc;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ struct cifs_io_parms io_parms = {0};
+ int buf_type = CIFS_NO_BUFFER;
+ __le16 *utf16_path;
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct smb2_file_all_info *pfile_info = NULL;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .path = path,
+ .desired_access = GENERIC_READ,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
+ .disposition = FILE_OPEN,
+ .fid = &fid,
+ };
+
+ utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+ if (utf16_path == NULL)
+ return -ENOMEM;
+
+ pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+ GFP_KERNEL);
+
+ if (pfile_info == NULL) {
+ kfree(utf16_path);
+ return -ENOMEM;
+ }
+
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
+ NULL, NULL);
+ if (rc)
+ goto qmf_out_open_fail;
+
+ if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
+ /* it's not a symlink */
+ rc = -ENOENT; /* Is there a better rc to return? */
+ goto qmf_out;
+ }
+
+ io_parms.netfid = fid.netfid;
+ io_parms.pid = current->tgid;
+ io_parms.tcon = tcon;
+ io_parms.offset = 0;
+ io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
+ io_parms.persistent_fid = fid.persistent_fid;
+ io_parms.volatile_fid = fid.volatile_fid;
+ rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
+qmf_out:
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+qmf_out_open_fail:
+ kfree(utf16_path);
+ kfree(pfile_info);
+ return rc;
+}
+
+int
+smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const unsigned char *path,
+ char *pbuf, unsigned int *pbytes_written)
+{
+ int rc;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ struct cifs_io_parms io_parms = {0};
+ __le16 *utf16_path;
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct kvec iov[2];
+
+ cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
+
+ utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .path = path,
+ .desired_access = GENERIC_WRITE,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
+ .disposition = FILE_CREATE,
+ .fid = &fid,
+ .mode = 0644,
+ };
+
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
+ NULL, NULL);
+ if (rc) {
+ kfree(utf16_path);
+ return rc;
+ }
+
+ io_parms.netfid = fid.netfid;
+ io_parms.pid = current->tgid;
+ io_parms.tcon = tcon;
+ io_parms.offset = 0;
+ io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
+ io_parms.persistent_fid = fid.persistent_fid;
+ io_parms.volatile_fid = fid.volatile_fid;
+
+ /* iov[0] is reserved for smb header */
+ iov[1].iov_base = pbuf;
+ iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE;
+
+ rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1);
+
+ /* Make sure we wrote all of the symlink data */
+ if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE))
+ rc = -EIO;
+
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+
+ kfree(utf16_path);
+ return rc;
+}
+
+/*
+ * M-F Symlink Functions - End
+ */
+
+int
+cifs_hardlink(struct dentry *old_file, struct inode *inode,
+ struct dentry *direntry)
+{
+ int rc = -EACCES;
+ unsigned int xid;
+ const char *from_name, *to_name;
+ void *page1, *page2;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct cifsInodeInfo *cifsInode;
+
+ if (unlikely(cifs_forced_shutdown(cifs_sb)))
+ return -EIO;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+
+ xid = get_xid();
+ page1 = alloc_dentry_path();
+ page2 = alloc_dentry_path();
+
+ from_name = build_path_from_dentry(old_file, page1);
+ if (IS_ERR(from_name)) {
+ rc = PTR_ERR(from_name);
+ goto cifs_hl_exit;
+ }
+ to_name = build_path_from_dentry(direntry, page2);
+ if (IS_ERR(to_name)) {
+ rc = PTR_ERR(to_name);
+ goto cifs_hl_exit;
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (tcon->unix_ext)
+ rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ else {
+#else
+ {
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ server = tcon->ses->server;
+ if (!server->ops->create_hardlink) {
+ rc = -ENOSYS;
+ goto cifs_hl_exit;
+ }
+ rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
+ cifs_sb);
+ if ((rc == -EIO) || (rc == -EINVAL))
+ rc = -EOPNOTSUPP;
+ }
+
+ d_drop(direntry); /* force new lookup from server of target */
+
+ /*
+ * if source file is cached (oplocked) revalidate will not go to server
+ * until the file is closed or oplock broken so update nlinks locally
+ */
+ if (d_really_is_positive(old_file)) {
+ cifsInode = CIFS_I(d_inode(old_file));
+ if (rc == 0) {
+ spin_lock(&d_inode(old_file)->i_lock);
+ inc_nlink(d_inode(old_file));
+ spin_unlock(&d_inode(old_file)->i_lock);
+
+ /*
+ * parent dir timestamps will update from srv within a
+ * second, would it really be worth it to set the parent
+ * dir cifs inode time to zero to force revalidate
+ * (faster) for it too?
+ */
+ }
+ /*
+ * if not oplocked will force revalidate to get info on source
+ * file from srv. Note Samba server prior to 4.2 has bug -
+ * not updating src file ctime on hardlinks but Windows servers
+ * handle it properly
+ */
+ cifsInode->time = 0;
+
+ /*
+ * Will update parent dir timestamps from srv within a second.
+ * Would it really be worth it to set the parent dir (cifs
+ * inode) time field to zero to force revalidate on parent
+ * directory faster ie
+ *
+ * CIFS_I(inode)->time = 0;
+ */
+ }
+
+cifs_hl_exit:
+ free_dentry_path(page1);
+ free_dentry_path(page2);
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+int
+cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
+ struct dentry *direntry, const char *symname)
+{
+ int rc = -EOPNOTSUPP;
+ unsigned int xid;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *pTcon;
+ const char *full_path;
+ void *page;
+ struct inode *newinode = NULL;
+
+ if (unlikely(cifs_forced_shutdown(cifs_sb)))
+ return -EIO;
+
+ page = alloc_dentry_path();
+ if (!page)
+ return -ENOMEM;
+
+ xid = get_xid();
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink)) {
+ rc = PTR_ERR(tlink);
+ goto symlink_exit;
+ }
+ pTcon = tlink_tcon(tlink);
+
+ full_path = build_path_from_dentry(direntry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto symlink_exit;
+ }
+
+ cifs_dbg(FYI, "Full path: %s\n", full_path);
+ cifs_dbg(FYI, "symname is %s\n", symname);
+
+ /* BB what if DFS and this volume is on different share? BB */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+ rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ else if (pTcon->unix_ext)
+ rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ /* else
+ rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
+ cifs_sb_target->local_nls); */
+
+ if (rc == 0) {
+ if (pTcon->posix_extensions)
+ rc = smb311_posix_get_inode_info(&newinode, full_path, inode->i_sb, xid);
+ else if (pTcon->unix_ext)
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
+ inode->i_sb, xid);
+ else
+ rc = cifs_get_inode_info(&newinode, full_path, NULL,
+ inode->i_sb, xid, NULL);
+
+ if (rc != 0) {
+ cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n",
+ rc);
+ } else {
+ d_instantiate(direntry, newinode);
+ }
+ }
+symlink_exit:
+ free_dentry_path(page);
+ cifs_put_tlink(tlink);
+ free_xid(xid);
+ return rc;
+}
diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
new file mode 100644
index 000000000000..31e06133acc3
--- /dev/null
+++ b/fs/smb/client/misc.c
@@ -0,0 +1,1434 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/mempool.h>
+#include <linux/vmalloc.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "smberr.h"
+#include "nterr.h"
+#include "cifs_unicode.h"
+#include "smb2pdu.h"
+#include "cifsfs.h"
+#ifdef CONFIG_CIFS_DFS_UPCALL
+#include "dns_resolve.h"
+#include "dfs_cache.h"
+#endif
+#include "fs_context.h"
+#include "cached_dir.h"
+
+extern mempool_t *cifs_sm_req_poolp;
+extern mempool_t *cifs_req_poolp;
+
+/* The xid serves as a useful identifier for each incoming vfs request,
+ in a similar way to the mid which is useful to track each sent smb,
+ and CurrentXid can also provide a running counter (although it
+ will eventually wrap past zero) of the total vfs operations handled
+ since the cifs fs was mounted */
+
+unsigned int
+_get_xid(void)
+{
+ unsigned int xid;
+
+ spin_lock(&GlobalMid_Lock);
+ GlobalTotalActiveXid++;
+
+ /* keep high water mark for number of simultaneous ops in filesystem */
+ if (GlobalTotalActiveXid > GlobalMaxActiveXid)
+ GlobalMaxActiveXid = GlobalTotalActiveXid;
+ if (GlobalTotalActiveXid > 65000)
+ cifs_dbg(FYI, "warning: more than 65000 requests active\n");
+ xid = GlobalCurrentXid++;
+ spin_unlock(&GlobalMid_Lock);
+ return xid;
+}
+
+void
+_free_xid(unsigned int xid)
+{
+ spin_lock(&GlobalMid_Lock);
+ /* if (GlobalTotalActiveXid == 0)
+ BUG(); */
+ GlobalTotalActiveXid--;
+ spin_unlock(&GlobalMid_Lock);
+}
+
+struct cifs_ses *
+sesInfoAlloc(void)
+{
+ struct cifs_ses *ret_buf;
+
+ ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL);
+ if (ret_buf) {
+ atomic_inc(&sesInfoAllocCount);
+ spin_lock_init(&ret_buf->ses_lock);
+ ret_buf->ses_status = SES_NEW;
+ ++ret_buf->ses_count;
+ INIT_LIST_HEAD(&ret_buf->smb_ses_list);
+ INIT_LIST_HEAD(&ret_buf->tcon_list);
+ mutex_init(&ret_buf->session_mutex);
+ spin_lock_init(&ret_buf->iface_lock);
+ INIT_LIST_HEAD(&ret_buf->iface_list);
+ spin_lock_init(&ret_buf->chan_lock);
+ }
+ return ret_buf;
+}
+
+void
+sesInfoFree(struct cifs_ses *buf_to_free)
+{
+ struct cifs_server_iface *iface = NULL, *niface = NULL;
+
+ if (buf_to_free == NULL) {
+ cifs_dbg(FYI, "Null buffer passed to sesInfoFree\n");
+ return;
+ }
+
+ atomic_dec(&sesInfoAllocCount);
+ kfree(buf_to_free->serverOS);
+ kfree(buf_to_free->serverDomain);
+ kfree(buf_to_free->serverNOS);
+ kfree_sensitive(buf_to_free->password);
+ kfree(buf_to_free->user_name);
+ kfree(buf_to_free->domainName);
+ kfree_sensitive(buf_to_free->auth_key.response);
+ spin_lock(&buf_to_free->iface_lock);
+ list_for_each_entry_safe(iface, niface, &buf_to_free->iface_list,
+ iface_head)
+ kref_put(&iface->refcount, release_iface);
+ spin_unlock(&buf_to_free->iface_lock);
+ kfree_sensitive(buf_to_free);
+}
+
+struct cifs_tcon *
+tconInfoAlloc(void)
+{
+ struct cifs_tcon *ret_buf;
+
+ ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
+ if (!ret_buf)
+ return NULL;
+ ret_buf->cfids = init_cached_dirs();
+ if (!ret_buf->cfids) {
+ kfree(ret_buf);
+ return NULL;
+ }
+
+ atomic_inc(&tconInfoAllocCount);
+ ret_buf->status = TID_NEW;
+ ++ret_buf->tc_count;
+ spin_lock_init(&ret_buf->tc_lock);
+ INIT_LIST_HEAD(&ret_buf->openFileList);
+ INIT_LIST_HEAD(&ret_buf->tcon_list);
+ spin_lock_init(&ret_buf->open_file_lock);
+ spin_lock_init(&ret_buf->stat_lock);
+ atomic_set(&ret_buf->num_local_opens, 0);
+ atomic_set(&ret_buf->num_remote_opens, 0);
+
+ return ret_buf;
+}
+
+void
+tconInfoFree(struct cifs_tcon *tcon)
+{
+ if (tcon == NULL) {
+ cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
+ return;
+ }
+ free_cached_dirs(tcon->cfids);
+ atomic_dec(&tconInfoAllocCount);
+ kfree(tcon->nativeFileSystem);
+ kfree_sensitive(tcon->password);
+ kfree(tcon);
+}
+
+struct smb_hdr *
+cifs_buf_get(void)
+{
+ struct smb_hdr *ret_buf = NULL;
+ /*
+ * SMB2 header is bigger than CIFS one - no problems to clean some
+ * more bytes for CIFS.
+ */
+ size_t buf_size = sizeof(struct smb2_hdr);
+
+ /*
+ * We could use negotiated size instead of max_msgsize -
+ * but it may be more efficient to always alloc same size
+ * albeit slightly larger than necessary and maxbuffersize
+ * defaults to this and can not be bigger.
+ */
+ ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS);
+
+ /* clear the first few header bytes */
+ /* for most paths, more is cleared in header_assemble */
+ memset(ret_buf, 0, buf_size + 3);
+ atomic_inc(&buf_alloc_count);
+#ifdef CONFIG_CIFS_STATS2
+ atomic_inc(&total_buf_alloc_count);
+#endif /* CONFIG_CIFS_STATS2 */
+
+ return ret_buf;
+}
+
+void
+cifs_buf_release(void *buf_to_free)
+{
+ if (buf_to_free == NULL) {
+ /* cifs_dbg(FYI, "Null buffer passed to cifs_buf_release\n");*/
+ return;
+ }
+ mempool_free(buf_to_free, cifs_req_poolp);
+
+ atomic_dec(&buf_alloc_count);
+ return;
+}
+
+struct smb_hdr *
+cifs_small_buf_get(void)
+{
+ struct smb_hdr *ret_buf = NULL;
+
+/* We could use negotiated size instead of max_msgsize -
+ but it may be more efficient to always alloc same size
+ albeit slightly larger than necessary and maxbuffersize
+ defaults to this and can not be bigger */
+ ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS);
+ /* No need to clear memory here, cleared in header assemble */
+ /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
+ atomic_inc(&small_buf_alloc_count);
+#ifdef CONFIG_CIFS_STATS2
+ atomic_inc(&total_small_buf_alloc_count);
+#endif /* CONFIG_CIFS_STATS2 */
+
+ return ret_buf;
+}
+
+void
+cifs_small_buf_release(void *buf_to_free)
+{
+
+ if (buf_to_free == NULL) {
+ cifs_dbg(FYI, "Null buffer passed to cifs_small_buf_release\n");
+ return;
+ }
+ mempool_free(buf_to_free, cifs_sm_req_poolp);
+
+ atomic_dec(&small_buf_alloc_count);
+ return;
+}
+
+void
+free_rsp_buf(int resp_buftype, void *rsp)
+{
+ if (resp_buftype == CIFS_SMALL_BUFFER)
+ cifs_small_buf_release(rsp);
+ else if (resp_buftype == CIFS_LARGE_BUFFER)
+ cifs_buf_release(rsp);
+}
+
+/* NB: MID can not be set if treeCon not passed in, in that
+ case it is responsbility of caller to set the mid */
+void
+header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
+ const struct cifs_tcon *treeCon, int word_count
+ /* length of fixed section (word count) in two byte units */)
+{
+ char *temp = (char *) buffer;
+
+ memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
+
+ buffer->smb_buf_length = cpu_to_be32(
+ (2 * word_count) + sizeof(struct smb_hdr) -
+ 4 /* RFC 1001 length field does not count */ +
+ 2 /* for bcc field itself */) ;
+
+ buffer->Protocol[0] = 0xFF;
+ buffer->Protocol[1] = 'S';
+ buffer->Protocol[2] = 'M';
+ buffer->Protocol[3] = 'B';
+ buffer->Command = smb_command;
+ buffer->Flags = 0x00; /* case sensitive */
+ buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
+ buffer->Pid = cpu_to_le16((__u16)current->tgid);
+ buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
+ if (treeCon) {
+ buffer->Tid = treeCon->tid;
+ if (treeCon->ses) {
+ if (treeCon->ses->capabilities & CAP_UNICODE)
+ buffer->Flags2 |= SMBFLG2_UNICODE;
+ if (treeCon->ses->capabilities & CAP_STATUS32)
+ buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+
+ /* Uid is not converted */
+ buffer->Uid = treeCon->ses->Suid;
+ if (treeCon->ses->server)
+ buffer->Mid = get_next_mid(treeCon->ses->server);
+ }
+ if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
+ buffer->Flags2 |= SMBFLG2_DFS;
+ if (treeCon->nocase)
+ buffer->Flags |= SMBFLG_CASELESS;
+ if ((treeCon->ses) && (treeCon->ses->server))
+ if (treeCon->ses->server->sign)
+ buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+ }
+
+/* endian conversion of flags is now done just before sending */
+ buffer->WordCount = (char) word_count;
+ return;
+}
+
+static int
+check_smb_hdr(struct smb_hdr *smb)
+{
+ /* does it have the right SMB "signature" ? */
+ if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) {
+ cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n",
+ *(unsigned int *)smb->Protocol);
+ return 1;
+ }
+
+ /* if it's a response then accept */
+ if (smb->Flags & SMBFLG_RESPONSE)
+ return 0;
+
+ /* only one valid case where server sends us request */
+ if (smb->Command == SMB_COM_LOCKING_ANDX)
+ return 0;
+
+ cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
+ get_mid(smb));
+ return 1;
+}
+
+int
+checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
+{
+ struct smb_hdr *smb = (struct smb_hdr *)buf;
+ __u32 rfclen = be32_to_cpu(smb->smb_buf_length);
+ __u32 clc_len; /* calculated length */
+ cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
+ total_read, rfclen);
+
+ /* is this frame too small to even get to a BCC? */
+ if (total_read < 2 + sizeof(struct smb_hdr)) {
+ if ((total_read >= sizeof(struct smb_hdr) - 1)
+ && (smb->Status.CifsError != 0)) {
+ /* it's an error return */
+ smb->WordCount = 0;
+ /* some error cases do not return wct and bcc */
+ return 0;
+ } else if ((total_read == sizeof(struct smb_hdr) + 1) &&
+ (smb->WordCount == 0)) {
+ char *tmp = (char *)smb;
+ /* Need to work around a bug in two servers here */
+ /* First, check if the part of bcc they sent was zero */
+ if (tmp[sizeof(struct smb_hdr)] == 0) {
+ /* some servers return only half of bcc
+ * on simple responses (wct, bcc both zero)
+ * in particular have seen this on
+ * ulogoffX and FindClose. This leaves
+ * one byte of bcc potentially unitialized
+ */
+ /* zero rest of bcc */
+ tmp[sizeof(struct smb_hdr)+1] = 0;
+ return 0;
+ }
+ cifs_dbg(VFS, "rcvd invalid byte count (bcc)\n");
+ } else {
+ cifs_dbg(VFS, "Length less than smb header size\n");
+ }
+ return -EIO;
+ }
+
+ /* otherwise, there is enough to get to the BCC */
+ if (check_smb_hdr(smb))
+ return -EIO;
+ clc_len = smbCalcSize(smb);
+
+ if (4 + rfclen != total_read) {
+ cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n",
+ rfclen);
+ return -EIO;
+ }
+
+ if (4 + rfclen != clc_len) {
+ __u16 mid = get_mid(smb);
+ /* check if bcc wrapped around for large read responses */
+ if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
+ /* check if lengths match mod 64K */
+ if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
+ return 0; /* bcc wrapped */
+ }
+ cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
+ clc_len, 4 + rfclen, mid);
+
+ if (4 + rfclen < clc_len) {
+ cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
+ rfclen, mid);
+ return -EIO;
+ } else if (rfclen > clc_len + 512) {
+ /*
+ * Some servers (Windows XP in particular) send more
+ * data than the lengths in the SMB packet would
+ * indicate on certain calls (byte range locks and
+ * trans2 find first calls in particular). While the
+ * client can handle such a frame by ignoring the
+ * trailing data, we choose limit the amount of extra
+ * data to 512 bytes.
+ */
+ cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
+ rfclen, mid);
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+bool
+is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
+{
+ struct smb_hdr *buf = (struct smb_hdr *)buffer;
+ struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+ struct cifsInodeInfo *pCifsInode;
+ struct cifsFileInfo *netfile;
+
+ cifs_dbg(FYI, "Checking for oplock break or dnotify response\n");
+ if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
+ (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
+ struct smb_com_transaction_change_notify_rsp *pSMBr =
+ (struct smb_com_transaction_change_notify_rsp *)buf;
+ struct file_notify_information *pnotify;
+ __u32 data_offset = 0;
+ size_t len = srv->total_read - sizeof(pSMBr->hdr.smb_buf_length);
+
+ if (get_bcc(buf) > sizeof(struct file_notify_information)) {
+ data_offset = le32_to_cpu(pSMBr->DataOffset);
+
+ if (data_offset >
+ len - sizeof(struct file_notify_information)) {
+ cifs_dbg(FYI, "Invalid data_offset %u\n",
+ data_offset);
+ return true;
+ }
+ pnotify = (struct file_notify_information *)
+ ((char *)&pSMBr->hdr.Protocol + data_offset);
+ cifs_dbg(FYI, "dnotify on %s Action: 0x%x\n",
+ pnotify->FileName, pnotify->Action);
+ /* cifs_dump_mem("Rcvd notify Data: ",buf,
+ sizeof(struct smb_hdr)+60); */
+ return true;
+ }
+ if (pSMBr->hdr.Status.CifsError) {
+ cifs_dbg(FYI, "notify err 0x%x\n",
+ pSMBr->hdr.Status.CifsError);
+ return true;
+ }
+ return false;
+ }
+ if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
+ return false;
+ if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {
+ /* no sense logging error on invalid handle on oplock
+ break - harmless race between close request and oplock
+ break response is expected from time to time writing out
+ large dirty files cached on the client */
+ if ((NT_STATUS_INVALID_HANDLE) ==
+ le32_to_cpu(pSMB->hdr.Status.CifsError)) {
+ cifs_dbg(FYI, "Invalid handle on oplock break\n");
+ return true;
+ } else if (ERRbadfid ==
+ le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
+ return true;
+ } else {
+ return false; /* on valid oplock brk we get "request" */
+ }
+ }
+ if (pSMB->hdr.WordCount != 8)
+ return false;
+
+ cifs_dbg(FYI, "oplock type 0x%x level 0x%x\n",
+ pSMB->LockType, pSMB->OplockLevel);
+ if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
+ return false;
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(srv) ? srv->primary_server : srv;
+
+ /* look up tcon based on tid & uid */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ if (tcon->tid != buf->Tid)
+ continue;
+
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks);
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(netfile, &tcon->openFileList, tlist) {
+ if (pSMB->Fid != netfile->fid.netfid)
+ continue;
+
+ cifs_dbg(FYI, "file id match, oplock break\n");
+ pCifsInode = CIFS_I(d_inode(netfile->dentry));
+
+ set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
+ &pCifsInode->flags);
+
+ netfile->oplock_epoch = 0;
+ netfile->oplock_level = pSMB->OplockLevel;
+ netfile->oplock_break_cancelled = false;
+ cifs_queue_oplock_break(netfile);
+
+ spin_unlock(&tcon->open_file_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ return true;
+ }
+ spin_unlock(&tcon->open_file_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ cifs_dbg(FYI, "No matching file for oplock break\n");
+ return true;
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
+ return true;
+}
+
+void
+dump_smb(void *buf, int smb_buf_length)
+{
+ if (traceSMB == 0)
+ return;
+
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 8, 2, buf,
+ smb_buf_length, true);
+}
+
+void
+cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
+{
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+ struct cifs_tcon *tcon = NULL;
+
+ if (cifs_sb->master_tlink)
+ tcon = cifs_sb_master_tcon(cifs_sb);
+
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
+ cifs_sb->mnt_cifs_serverino_autodisabled = true;
+ cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s\n",
+ tcon ? tcon->tree_name : "new server");
+ cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS)\n");
+ cifs_dbg(VFS, "Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n");
+
+ }
+}
+
+void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
+{
+ oplock &= 0xF;
+
+ if (oplock == OPLOCK_EXCLUSIVE) {
+ cinode->oplock = CIFS_CACHE_WRITE_FLG | CIFS_CACHE_READ_FLG;
+ cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
+ &cinode->netfs.inode);
+ } else if (oplock == OPLOCK_READ) {
+ cinode->oplock = CIFS_CACHE_READ_FLG;
+ cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
+ &cinode->netfs.inode);
+ } else
+ cinode->oplock = 0;
+}
+
+/*
+ * We wait for oplock breaks to be processed before we attempt to perform
+ * writes.
+ */
+int cifs_get_writer(struct cifsInodeInfo *cinode)
+{
+ int rc;
+
+start:
+ rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK,
+ TASK_KILLABLE);
+ if (rc)
+ return rc;
+
+ spin_lock(&cinode->writers_lock);
+ if (!cinode->writers)
+ set_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
+ cinode->writers++;
+ /* Check to see if we have started servicing an oplock break */
+ if (test_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags)) {
+ cinode->writers--;
+ if (cinode->writers == 0) {
+ clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
+ wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
+ }
+ spin_unlock(&cinode->writers_lock);
+ goto start;
+ }
+ spin_unlock(&cinode->writers_lock);
+ return 0;
+}
+
+void cifs_put_writer(struct cifsInodeInfo *cinode)
+{
+ spin_lock(&cinode->writers_lock);
+ cinode->writers--;
+ if (cinode->writers == 0) {
+ clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags);
+ wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS);
+ }
+ spin_unlock(&cinode->writers_lock);
+}
+
+/**
+ * cifs_queue_oplock_break - queue the oplock break handler for cfile
+ * @cfile: The file to break the oplock on
+ *
+ * This function is called from the demultiplex thread when it
+ * receives an oplock break for @cfile.
+ *
+ * Assumes the tcon->open_file_lock is held.
+ * Assumes cfile->file_info_lock is NOT held.
+ */
+void cifs_queue_oplock_break(struct cifsFileInfo *cfile)
+{
+ /*
+ * Bump the handle refcount now while we hold the
+ * open_file_lock to enforce the validity of it for the oplock
+ * break handler. The matching put is done at the end of the
+ * handler.
+ */
+ cifsFileInfo_get(cfile);
+
+ queue_work(cifsoplockd_wq, &cfile->oplock_break);
+}
+
+void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
+{
+ clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
+ wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK);
+}
+
+bool
+backup_cred(struct cifs_sb_info *cifs_sb)
+{
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) {
+ if (uid_eq(cifs_sb->ctx->backupuid, current_fsuid()))
+ return true;
+ }
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) {
+ if (in_group_p(cifs_sb->ctx->backupgid))
+ return true;
+ }
+
+ return false;
+}
+
+void
+cifs_del_pending_open(struct cifs_pending_open *open)
+{
+ spin_lock(&tlink_tcon(open->tlink)->open_file_lock);
+ list_del(&open->olist);
+ spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
+}
+
+void
+cifs_add_pending_open_locked(struct cifs_fid *fid, struct tcon_link *tlink,
+ struct cifs_pending_open *open)
+{
+ memcpy(open->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
+ open->oplock = CIFS_OPLOCK_NO_CHANGE;
+ open->tlink = tlink;
+ fid->pending_open = open;
+ list_add_tail(&open->olist, &tlink_tcon(tlink)->pending_opens);
+}
+
+void
+cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
+ struct cifs_pending_open *open)
+{
+ spin_lock(&tlink_tcon(tlink)->open_file_lock);
+ cifs_add_pending_open_locked(fid, tlink, open);
+ spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
+}
+
+/*
+ * Critical section which runs after acquiring deferred_lock.
+ * As there is no reference count on cifs_deferred_close, pdclose
+ * should not be used outside deferred_lock.
+ */
+bool
+cifs_is_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close **pdclose)
+{
+ struct cifs_deferred_close *dclose;
+
+ list_for_each_entry(dclose, &CIFS_I(d_inode(cfile->dentry))->deferred_closes, dlist) {
+ if ((dclose->netfid == cfile->fid.netfid) &&
+ (dclose->persistent_fid == cfile->fid.persistent_fid) &&
+ (dclose->volatile_fid == cfile->fid.volatile_fid)) {
+ *pdclose = dclose;
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * Critical section which runs after acquiring deferred_lock.
+ */
+void
+cifs_add_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close *dclose)
+{
+ bool is_deferred = false;
+ struct cifs_deferred_close *pdclose;
+
+ is_deferred = cifs_is_deferred_close(cfile, &pdclose);
+ if (is_deferred) {
+ kfree(dclose);
+ return;
+ }
+
+ dclose->tlink = cfile->tlink;
+ dclose->netfid = cfile->fid.netfid;
+ dclose->persistent_fid = cfile->fid.persistent_fid;
+ dclose->volatile_fid = cfile->fid.volatile_fid;
+ list_add_tail(&dclose->dlist, &CIFS_I(d_inode(cfile->dentry))->deferred_closes);
+}
+
+/*
+ * Critical section which runs after acquiring deferred_lock.
+ */
+void
+cifs_del_deferred_close(struct cifsFileInfo *cfile)
+{
+ bool is_deferred = false;
+ struct cifs_deferred_close *dclose;
+
+ is_deferred = cifs_is_deferred_close(cfile, &dclose);
+ if (!is_deferred)
+ return;
+ list_del(&dclose->dlist);
+ kfree(dclose);
+}
+
+void
+cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
+{
+ struct cifsFileInfo *cfile = NULL;
+ struct file_list *tmp_list, *tmp_next_list;
+ struct list_head file_head;
+
+ if (cifs_inode == NULL)
+ return;
+
+ INIT_LIST_HEAD(&file_head);
+ spin_lock(&cifs_inode->open_file_lock);
+ list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
+ if (delayed_work_pending(&cfile->deferred)) {
+ if (cancel_delayed_work(&cfile->deferred)) {
+ spin_lock(&cifs_inode->deferred_lock);
+ cifs_del_deferred_close(cfile);
+ spin_unlock(&cifs_inode->deferred_lock);
+
+ tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
+ if (tmp_list == NULL)
+ break;
+ tmp_list->cfile = cfile;
+ list_add_tail(&tmp_list->list, &file_head);
+ }
+ }
+ }
+ spin_unlock(&cifs_inode->open_file_lock);
+
+ list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
+ _cifsFileInfo_put(tmp_list->cfile, false, false);
+ list_del(&tmp_list->list);
+ kfree(tmp_list);
+ }
+}
+
+void
+cifs_close_all_deferred_files(struct cifs_tcon *tcon)
+{
+ struct cifsFileInfo *cfile;
+ struct file_list *tmp_list, *tmp_next_list;
+ struct list_head file_head;
+
+ INIT_LIST_HEAD(&file_head);
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(cfile, &tcon->openFileList, tlist) {
+ if (delayed_work_pending(&cfile->deferred)) {
+ if (cancel_delayed_work(&cfile->deferred)) {
+ spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+ cifs_del_deferred_close(cfile);
+ spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+
+ tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
+ if (tmp_list == NULL)
+ break;
+ tmp_list->cfile = cfile;
+ list_add_tail(&tmp_list->list, &file_head);
+ }
+ }
+ }
+ spin_unlock(&tcon->open_file_lock);
+
+ list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
+ _cifsFileInfo_put(tmp_list->cfile, true, false);
+ list_del(&tmp_list->list);
+ kfree(tmp_list);
+ }
+}
+void
+cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
+{
+ struct cifsFileInfo *cfile;
+ struct file_list *tmp_list, *tmp_next_list;
+ struct list_head file_head;
+ void *page;
+ const char *full_path;
+
+ INIT_LIST_HEAD(&file_head);
+ page = alloc_dentry_path();
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(cfile, &tcon->openFileList, tlist) {
+ full_path = build_path_from_dentry(cfile->dentry, page);
+ if (strstr(full_path, path)) {
+ if (delayed_work_pending(&cfile->deferred)) {
+ if (cancel_delayed_work(&cfile->deferred)) {
+ spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+ cifs_del_deferred_close(cfile);
+ spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+
+ tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
+ if (tmp_list == NULL)
+ break;
+ tmp_list->cfile = cfile;
+ list_add_tail(&tmp_list->list, &file_head);
+ }
+ }
+ }
+ }
+ spin_unlock(&tcon->open_file_lock);
+
+ list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
+ _cifsFileInfo_put(tmp_list->cfile, true, false);
+ list_del(&tmp_list->list);
+ kfree(tmp_list);
+ }
+ free_dentry_path(page);
+}
+
+/* parses DFS referral V3 structure
+ * caller is responsible for freeing target_nodes
+ * returns:
+ * - on success - 0
+ * - on failure - errno
+ */
+int
+parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
+ unsigned int *num_of_nodes,
+ struct dfs_info3_param **target_nodes,
+ const struct nls_table *nls_codepage, int remap,
+ const char *searchName, bool is_unicode)
+{
+ int i, rc = 0;
+ char *data_end;
+ struct dfs_referral_level_3 *ref;
+
+ *num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals);
+
+ if (*num_of_nodes < 1) {
+ cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
+ *num_of_nodes);
+ rc = -EINVAL;
+ goto parse_DFS_referrals_exit;
+ }
+
+ ref = (struct dfs_referral_level_3 *) &(rsp->referrals);
+ if (ref->VersionNumber != cpu_to_le16(3)) {
+ cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
+ le16_to_cpu(ref->VersionNumber));
+ rc = -EINVAL;
+ goto parse_DFS_referrals_exit;
+ }
+
+ /* get the upper boundary of the resp buffer */
+ data_end = (char *)rsp + rsp_size;
+
+ cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
+ *num_of_nodes, le32_to_cpu(rsp->DFSFlags));
+
+ *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
+ GFP_KERNEL);
+ if (*target_nodes == NULL) {
+ rc = -ENOMEM;
+ goto parse_DFS_referrals_exit;
+ }
+
+ /* collect necessary data from referrals */
+ for (i = 0; i < *num_of_nodes; i++) {
+ char *temp;
+ int max_len;
+ struct dfs_info3_param *node = (*target_nodes)+i;
+
+ node->flags = le32_to_cpu(rsp->DFSFlags);
+ if (is_unicode) {
+ __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
+ GFP_KERNEL);
+ if (tmp == NULL) {
+ rc = -ENOMEM;
+ goto parse_DFS_referrals_exit;
+ }
+ cifsConvertToUTF16((__le16 *) tmp, searchName,
+ PATH_MAX, nls_codepage, remap);
+ node->path_consumed = cifs_utf16_bytes(tmp,
+ le16_to_cpu(rsp->PathConsumed),
+ nls_codepage);
+ kfree(tmp);
+ } else
+ node->path_consumed = le16_to_cpu(rsp->PathConsumed);
+
+ node->server_type = le16_to_cpu(ref->ServerType);
+ node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
+
+ /* copy DfsPath */
+ temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
+ max_len = data_end - temp;
+ node->path_name = cifs_strndup_from_utf16(temp, max_len,
+ is_unicode, nls_codepage);
+ if (!node->path_name) {
+ rc = -ENOMEM;
+ goto parse_DFS_referrals_exit;
+ }
+
+ /* copy link target UNC */
+ temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
+ max_len = data_end - temp;
+ node->node_name = cifs_strndup_from_utf16(temp, max_len,
+ is_unicode, nls_codepage);
+ if (!node->node_name) {
+ rc = -ENOMEM;
+ goto parse_DFS_referrals_exit;
+ }
+
+ node->ttl = le32_to_cpu(ref->TimeToLive);
+
+ ref++;
+ }
+
+parse_DFS_referrals_exit:
+ if (rc) {
+ free_dfs_info_array(*target_nodes, *num_of_nodes);
+ *target_nodes = NULL;
+ *num_of_nodes = 0;
+ }
+ return rc;
+}
+
+struct cifs_aio_ctx *
+cifs_aio_ctx_alloc(void)
+{
+ struct cifs_aio_ctx *ctx;
+
+ /*
+ * Must use kzalloc to initialize ctx->bv to NULL and ctx->direct_io
+ * to false so that we know when we have to unreference pages within
+ * cifs_aio_ctx_release()
+ */
+ ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL);
+ if (!ctx)
+ return NULL;
+
+ INIT_LIST_HEAD(&ctx->list);
+ mutex_init(&ctx->aio_mutex);
+ init_completion(&ctx->done);
+ kref_init(&ctx->refcount);
+ return ctx;
+}
+
+void
+cifs_aio_ctx_release(struct kref *refcount)
+{
+ struct cifs_aio_ctx *ctx = container_of(refcount,
+ struct cifs_aio_ctx, refcount);
+
+ cifsFileInfo_put(ctx->cfile);
+
+ /*
+ * ctx->bv is only set if setup_aio_ctx_iter() was call successfuly
+ * which means that iov_iter_get_pages() was a success and thus that
+ * we have taken reference on pages.
+ */
+ if (ctx->bv) {
+ unsigned i;
+
+ for (i = 0; i < ctx->npages; i++) {
+ if (ctx->should_dirty)
+ set_page_dirty(ctx->bv[i].bv_page);
+ put_page(ctx->bv[i].bv_page);
+ }
+ kvfree(ctx->bv);
+ }
+
+ kfree(ctx);
+}
+
+#define CIFS_AIO_KMALLOC_LIMIT (1024 * 1024)
+
+int
+setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
+{
+ ssize_t rc;
+ unsigned int cur_npages;
+ unsigned int npages = 0;
+ unsigned int i;
+ size_t len;
+ size_t count = iov_iter_count(iter);
+ unsigned int saved_len;
+ size_t start;
+ unsigned int max_pages = iov_iter_npages(iter, INT_MAX);
+ struct page **pages = NULL;
+ struct bio_vec *bv = NULL;
+
+ if (iov_iter_is_kvec(iter)) {
+ memcpy(&ctx->iter, iter, sizeof(*iter));
+ ctx->len = count;
+ iov_iter_advance(iter, count);
+ return 0;
+ }
+
+ if (array_size(max_pages, sizeof(*bv)) <= CIFS_AIO_KMALLOC_LIMIT)
+ bv = kmalloc_array(max_pages, sizeof(*bv), GFP_KERNEL);
+
+ if (!bv) {
+ bv = vmalloc(array_size(max_pages, sizeof(*bv)));
+ if (!bv)
+ return -ENOMEM;
+ }
+
+ if (array_size(max_pages, sizeof(*pages)) <= CIFS_AIO_KMALLOC_LIMIT)
+ pages = kmalloc_array(max_pages, sizeof(*pages), GFP_KERNEL);
+
+ if (!pages) {
+ pages = vmalloc(array_size(max_pages, sizeof(*pages)));
+ if (!pages) {
+ kvfree(bv);
+ return -ENOMEM;
+ }
+ }
+
+ saved_len = count;
+
+ while (count && npages < max_pages) {
+ rc = iov_iter_get_pages2(iter, pages, count, max_pages, &start);
+ if (rc < 0) {
+ cifs_dbg(VFS, "Couldn't get user pages (rc=%zd)\n", rc);
+ break;
+ }
+
+ if (rc > count) {
+ cifs_dbg(VFS, "get pages rc=%zd more than %zu\n", rc,
+ count);
+ break;
+ }
+
+ count -= rc;
+ rc += start;
+ cur_npages = DIV_ROUND_UP(rc, PAGE_SIZE);
+
+ if (npages + cur_npages > max_pages) {
+ cifs_dbg(VFS, "out of vec array capacity (%u vs %u)\n",
+ npages + cur_npages, max_pages);
+ break;
+ }
+
+ for (i = 0; i < cur_npages; i++) {
+ len = rc > PAGE_SIZE ? PAGE_SIZE : rc;
+ bv[npages + i].bv_page = pages[i];
+ bv[npages + i].bv_offset = start;
+ bv[npages + i].bv_len = len - start;
+ rc -= len;
+ start = 0;
+ }
+
+ npages += cur_npages;
+ }
+
+ kvfree(pages);
+ ctx->bv = bv;
+ ctx->len = saved_len - count;
+ ctx->npages = npages;
+ iov_iter_bvec(&ctx->iter, rw, ctx->bv, npages, ctx->len);
+ return 0;
+}
+
+/**
+ * cifs_alloc_hash - allocate hash and hash context together
+ * @name: The name of the crypto hash algo
+ * @sdesc: SHASH descriptor where to put the pointer to the hash TFM
+ *
+ * The caller has to make sure @sdesc is initialized to either NULL or
+ * a valid context. It can be freed via cifs_free_hash().
+ */
+int
+cifs_alloc_hash(const char *name, struct shash_desc **sdesc)
+{
+ int rc = 0;
+ struct crypto_shash *alg = NULL;
+
+ if (*sdesc)
+ return 0;
+
+ alg = crypto_alloc_shash(name, 0, 0);
+ if (IS_ERR(alg)) {
+ cifs_dbg(VFS, "Could not allocate shash TFM '%s'\n", name);
+ rc = PTR_ERR(alg);
+ *sdesc = NULL;
+ return rc;
+ }
+
+ *sdesc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(alg), GFP_KERNEL);
+ if (*sdesc == NULL) {
+ cifs_dbg(VFS, "no memory left to allocate shash TFM '%s'\n", name);
+ crypto_free_shash(alg);
+ return -ENOMEM;
+ }
+
+ (*sdesc)->tfm = alg;
+ return 0;
+}
+
+/**
+ * cifs_free_hash - free hash and hash context together
+ * @sdesc: Where to find the pointer to the hash TFM
+ *
+ * Freeing a NULL descriptor is safe.
+ */
+void
+cifs_free_hash(struct shash_desc **sdesc)
+{
+ if (unlikely(!sdesc) || !*sdesc)
+ return;
+
+ if ((*sdesc)->tfm) {
+ crypto_free_shash((*sdesc)->tfm);
+ (*sdesc)->tfm = NULL;
+ }
+
+ kfree_sensitive(*sdesc);
+ *sdesc = NULL;
+}
+
+/**
+ * rqst_page_get_length - obtain the length and offset for a page in smb_rqst
+ * @rqst: The request descriptor
+ * @page: The index of the page to query
+ * @len: Where to store the length for this page:
+ * @offset: Where to store the offset for this page
+ */
+void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
+ unsigned int *len, unsigned int *offset)
+{
+ *len = rqst->rq_pagesz;
+ *offset = (page == 0) ? rqst->rq_offset : 0;
+
+ if (rqst->rq_npages == 1 || page == rqst->rq_npages-1)
+ *len = rqst->rq_tailsz;
+ else if (page == 0)
+ *len = rqst->rq_pagesz - rqst->rq_offset;
+}
+
+void extract_unc_hostname(const char *unc, const char **h, size_t *len)
+{
+ const char *end;
+
+ /* skip initial slashes */
+ while (*unc && (*unc == '\\' || *unc == '/'))
+ unc++;
+
+ end = unc;
+
+ while (*end && !(*end == '\\' || *end == '/'))
+ end++;
+
+ *h = unc;
+ *len = end - unc;
+}
+
+/**
+ * copy_path_name - copy src path to dst, possibly truncating
+ * @dst: The destination buffer
+ * @src: The source name
+ *
+ * returns number of bytes written (including trailing nul)
+ */
+int copy_path_name(char *dst, const char *src)
+{
+ int name_len;
+
+ /*
+ * PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it
+ * will truncate and strlen(dst) will be PATH_MAX-1
+ */
+ name_len = strscpy(dst, src, PATH_MAX);
+ if (WARN_ON_ONCE(name_len < 0))
+ name_len = PATH_MAX-1;
+
+ /* we count the trailing nul */
+ name_len++;
+ return name_len;
+}
+
+struct super_cb_data {
+ void *data;
+ struct super_block *sb;
+};
+
+static void tcp_super_cb(struct super_block *sb, void *arg)
+{
+ struct super_cb_data *sd = arg;
+ struct TCP_Server_Info *server = sd->data;
+ struct cifs_sb_info *cifs_sb;
+ struct cifs_tcon *tcon;
+
+ if (sd->sb)
+ return;
+
+ cifs_sb = CIFS_SB(sb);
+ tcon = cifs_sb_master_tcon(cifs_sb);
+ if (tcon->ses->server == server)
+ sd->sb = sb;
+}
+
+static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *),
+ void *data)
+{
+ struct super_cb_data sd = {
+ .data = data,
+ .sb = NULL,
+ };
+ struct file_system_type **fs_type = (struct file_system_type *[]) {
+ &cifs_fs_type, &smb3_fs_type, NULL,
+ };
+
+ for (; *fs_type; fs_type++) {
+ iterate_supers_type(*fs_type, f, &sd);
+ if (sd.sb) {
+ /*
+ * Grab an active reference in order to prevent automounts (DFS links)
+ * of expiring and then freeing up our cifs superblock pointer while
+ * we're doing failover.
+ */
+ cifs_sb_active(sd.sb);
+ return sd.sb;
+ }
+ }
+ return ERR_PTR(-EINVAL);
+}
+
+static void __cifs_put_super(struct super_block *sb)
+{
+ if (!IS_ERR_OR_NULL(sb))
+ cifs_sb_deactive(sb);
+}
+
+struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server)
+{
+ return __cifs_get_super(tcp_super_cb, server);
+}
+
+void cifs_put_tcp_super(struct super_block *sb)
+{
+ __cifs_put_super(sb);
+}
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+int match_target_ip(struct TCP_Server_Info *server,
+ const char *share, size_t share_len,
+ bool *result)
+{
+ int rc;
+ char *target, *tip = NULL;
+ struct sockaddr tipaddr;
+
+ *result = false;
+
+ target = kzalloc(share_len + 3, GFP_KERNEL);
+ if (!target) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ scnprintf(target, share_len + 3, "\\\\%.*s", (int)share_len, share);
+
+ cifs_dbg(FYI, "%s: target name: %s\n", __func__, target + 2);
+
+ rc = dns_resolve_server_name_to_ip(target, &tip, NULL);
+ if (rc < 0)
+ goto out;
+
+ cifs_dbg(FYI, "%s: target ip: %s\n", __func__, tip);
+
+ if (!cifs_convert_address(&tipaddr, tip, strlen(tip))) {
+ cifs_dbg(VFS, "%s: failed to convert target ip address\n",
+ __func__);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr,
+ &tipaddr);
+ cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result);
+ rc = 0;
+
+out:
+ kfree(target);
+ kfree(tip);
+
+ return rc;
+}
+
+int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
+{
+ kfree(cifs_sb->prepath);
+
+ if (prefix && *prefix) {
+ cifs_sb->prepath = cifs_sanitize_prepath(prefix, GFP_ATOMIC);
+ if (!cifs_sb->prepath)
+ return -ENOMEM;
+
+ convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
+ } else
+ cifs_sb->prepath = NULL;
+
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
+ return 0;
+}
+
+/*
+ * Handle weird Windows SMB server behaviour. It responds with
+ * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request for
+ * "\<server>\<dfsname>\<linkpath>" DFS reference, where <dfsname> contains
+ * non-ASCII unicode symbols.
+ */
+int cifs_inval_name_dfs_link_error(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ const char *full_path,
+ bool *islink)
+{
+ struct cifs_ses *ses = tcon->ses;
+ size_t len;
+ char *path;
+ char *ref_path;
+
+ *islink = false;
+
+ /*
+ * Fast path - skip check when @full_path doesn't have a prefix path to
+ * look up or tcon is not DFS.
+ */
+ if (strlen(full_path) < 2 || !cifs_sb ||
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) ||
+ !is_tcon_dfs(tcon) || !ses->server->origin_fullpath)
+ return 0;
+
+ /*
+ * Slow path - tcon is DFS and @full_path has prefix path, so attempt
+ * to get a referral to figure out whether it is an DFS link.
+ */
+ len = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1) + strlen(full_path) + 1;
+ path = kmalloc(len, GFP_KERNEL);
+ if (!path)
+ return -ENOMEM;
+
+ scnprintf(path, len, "%s%s", tcon->tree_name, full_path);
+ ref_path = dfs_cache_canonical_path(path + 1, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ kfree(path);
+
+ if (IS_ERR(ref_path)) {
+ if (PTR_ERR(ref_path) != -EINVAL)
+ return PTR_ERR(ref_path);
+ } else {
+ struct dfs_info3_param *refs = NULL;
+ int num_refs = 0;
+
+ /*
+ * XXX: we are not using dfs_cache_find() here because we might
+ * end filling all the DFS cache and thus potentially
+ * removing cached DFS targets that the client would eventually
+ * need during failover.
+ */
+ if (ses->server->ops->get_dfs_refer &&
+ !ses->server->ops->get_dfs_refer(xid, ses, ref_path, &refs,
+ &num_refs, cifs_sb->local_nls,
+ cifs_remap(cifs_sb)))
+ *islink = refs[0].server_type == DFS_TYPE_LINK;
+ free_dfs_info_array(refs, num_refs);
+ kfree(ref_path);
+ }
+ return 0;
+}
+#endif
+
+int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry)
+{
+ int timeout = 10;
+ int rc;
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus != CifsNeedReconnect) {
+ spin_unlock(&server->srv_lock);
+ return 0;
+ }
+ timeout *= server->nr_targets;
+ spin_unlock(&server->srv_lock);
+
+ /*
+ * Give demultiplex thread up to 10 seconds to each target available for
+ * reconnect -- should be greater than cifs socket timeout which is 7
+ * seconds.
+ *
+ * On "soft" mounts we wait once. Hard mounts keep retrying until
+ * process is killed or server comes back on-line.
+ */
+ do {
+ rc = wait_event_interruptible_timeout(server->response_q,
+ (server->tcpStatus != CifsNeedReconnect),
+ timeout * HZ);
+ if (rc < 0) {
+ cifs_dbg(FYI, "%s: aborting reconnect due to received signal\n",
+ __func__);
+ return -ERESTARTSYS;
+ }
+
+ /* are we still trying to reconnect? */
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus != CifsNeedReconnect) {
+ spin_unlock(&server->srv_lock);
+ return 0;
+ }
+ spin_unlock(&server->srv_lock);
+ } while (retry);
+
+ cifs_dbg(FYI, "%s: gave up waiting on reconnect\n", __func__);
+ return -EHOSTDOWN;
+}
diff --git a/fs/smb/client/netlink.c b/fs/smb/client/netlink.c
new file mode 100644
index 000000000000..147d9409252c
--- /dev/null
+++ b/fs/smb/client/netlink.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Netlink routines for CIFS
+ *
+ * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
+ */
+
+#include <net/genetlink.h>
+#include <uapi/linux/cifs/cifs_netlink.h>
+
+#include "netlink.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "cifs_swn.h"
+
+static const struct nla_policy cifs_genl_policy[CIFS_GENL_ATTR_MAX + 1] = {
+ [CIFS_GENL_ATTR_SWN_REGISTRATION_ID] = { .type = NLA_U32 },
+ [CIFS_GENL_ATTR_SWN_NET_NAME] = { .type = NLA_STRING },
+ [CIFS_GENL_ATTR_SWN_SHARE_NAME] = { .type = NLA_STRING },
+ [CIFS_GENL_ATTR_SWN_IP] = { .len = sizeof(struct sockaddr_storage) },
+ [CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY] = { .type = NLA_FLAG },
+ [CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY] = { .type = NLA_FLAG },
+ [CIFS_GENL_ATTR_SWN_IP_NOTIFY] = { .type = NLA_FLAG },
+ [CIFS_GENL_ATTR_SWN_KRB_AUTH] = { .type = NLA_FLAG },
+ [CIFS_GENL_ATTR_SWN_USER_NAME] = { .type = NLA_STRING },
+ [CIFS_GENL_ATTR_SWN_PASSWORD] = { .type = NLA_STRING },
+ [CIFS_GENL_ATTR_SWN_DOMAIN_NAME] = { .type = NLA_STRING },
+ [CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE] = { .type = NLA_U32 },
+ [CIFS_GENL_ATTR_SWN_RESOURCE_STATE] = { .type = NLA_U32 },
+ [CIFS_GENL_ATTR_SWN_RESOURCE_NAME] = { .type = NLA_STRING},
+};
+
+static const struct genl_ops cifs_genl_ops[] = {
+ {
+ .cmd = CIFS_GENL_CMD_SWN_NOTIFY,
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ .doit = cifs_swn_notify,
+ },
+};
+
+static const struct genl_multicast_group cifs_genl_mcgrps[] = {
+ [CIFS_GENL_MCGRP_SWN] = { .name = CIFS_GENL_MCGRP_SWN_NAME },
+};
+
+struct genl_family cifs_genl_family = {
+ .name = CIFS_GENL_NAME,
+ .version = CIFS_GENL_VERSION,
+ .hdrsize = 0,
+ .maxattr = CIFS_GENL_ATTR_MAX,
+ .module = THIS_MODULE,
+ .policy = cifs_genl_policy,
+ .ops = cifs_genl_ops,
+ .n_ops = ARRAY_SIZE(cifs_genl_ops),
+ .resv_start_op = CIFS_GENL_CMD_SWN_NOTIFY + 1,
+ .mcgrps = cifs_genl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(cifs_genl_mcgrps),
+};
+
+/**
+ * cifs_genl_init - Register generic netlink family
+ *
+ * Return zero if initialized successfully, otherwise non-zero.
+ */
+int cifs_genl_init(void)
+{
+ int ret;
+
+ ret = genl_register_family(&cifs_genl_family);
+ if (ret < 0) {
+ cifs_dbg(VFS, "%s: failed to register netlink family\n",
+ __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * cifs_genl_exit - Unregister generic netlink family
+ */
+void cifs_genl_exit(void)
+{
+ int ret;
+
+ ret = genl_unregister_family(&cifs_genl_family);
+ if (ret < 0) {
+ cifs_dbg(VFS, "%s: failed to unregister netlink family\n",
+ __func__);
+ }
+}
diff --git a/fs/smb/client/netlink.h b/fs/smb/client/netlink.h
new file mode 100644
index 000000000000..e2fa8ed24c54
--- /dev/null
+++ b/fs/smb/client/netlink.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Netlink routines for CIFS
+ *
+ * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
+ */
+
+#ifndef _CIFS_NETLINK_H
+#define _CIFS_NETLINK_H
+
+extern struct genl_family cifs_genl_family;
+
+extern int cifs_genl_init(void);
+extern void cifs_genl_exit(void);
+
+#endif /* _CIFS_NETLINK_H */
diff --git a/fs/smb/client/netmisc.c b/fs/smb/client/netmisc.c
new file mode 100644
index 000000000000..1b52e6ac431c
--- /dev/null
+++ b/fs/smb/client/netmisc.c
@@ -0,0 +1,1021 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Error mapping routines from Samba libsmb/errormap.c
+ * Copyright (C) Andrew Tridgell 2001
+ */
+
+#include <linux/net.h>
+#include <linux/string.h>
+#include <linux/in.h>
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <asm/div64.h>
+#include <asm/byteorder.h>
+#include <linux/inet.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smberr.h"
+#include "cifs_debug.h"
+#include "nterr.h"
+
+struct smb_to_posix_error {
+ __u16 smb_err;
+ int posix_code;
+};
+
+static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
+ {ERRbadfunc, -EINVAL},
+ {ERRbadfile, -ENOENT},
+ {ERRbadpath, -ENOTDIR},
+ {ERRnofids, -EMFILE},
+ {ERRnoaccess, -EACCES},
+ {ERRbadfid, -EBADF},
+ {ERRbadmcb, -EIO},
+ {ERRnomem, -EREMOTEIO},
+ {ERRbadmem, -EFAULT},
+ {ERRbadenv, -EFAULT},
+ {ERRbadformat, -EINVAL},
+ {ERRbadaccess, -EACCES},
+ {ERRbaddata, -EIO},
+ {ERRbaddrive, -ENXIO},
+ {ERRremcd, -EACCES},
+ {ERRdiffdevice, -EXDEV},
+ {ERRnofiles, -ENOENT},
+ {ERRwriteprot, -EROFS},
+ {ERRbadshare, -EBUSY},
+ {ERRlock, -EACCES},
+ {ERRunsup, -EINVAL},
+ {ERRnosuchshare, -ENXIO},
+ {ERRfilexists, -EEXIST},
+ {ERRinvparm, -EINVAL},
+ {ERRdiskfull, -ENOSPC},
+ {ERRinvname, -ENOENT},
+ {ERRinvlevel, -EOPNOTSUPP},
+ {ERRdirnotempty, -ENOTEMPTY},
+ {ERRnotlocked, -ENOLCK},
+ {ERRcancelviolation, -ENOLCK},
+ {ERRalreadyexists, -EEXIST},
+ {ERRmoredata, -EOVERFLOW},
+ {ERReasnotsupported, -EOPNOTSUPP},
+ {ErrQuota, -EDQUOT},
+ {ErrNotALink, -ENOLINK},
+ {ERRnetlogonNotStarted, -ENOPROTOOPT},
+ {ERRsymlink, -EOPNOTSUPP},
+ {ErrTooManyLinks, -EMLINK},
+ {0, 0}
+};
+
+static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
+ {ERRerror, -EIO},
+ {ERRbadpw, -EACCES}, /* was EPERM */
+ {ERRbadtype, -EREMOTE},
+ {ERRaccess, -EACCES},
+ {ERRinvtid, -ENXIO},
+ {ERRinvnetname, -ENXIO},
+ {ERRinvdevice, -ENXIO},
+ {ERRqfull, -ENOSPC},
+ {ERRqtoobig, -ENOSPC},
+ {ERRqeof, -EIO},
+ {ERRinvpfid, -EBADF},
+ {ERRsmbcmd, -EBADRQC},
+ {ERRsrverror, -EIO},
+ {ERRbadBID, -EIO},
+ {ERRfilespecs, -EINVAL},
+ {ERRbadLink, -EIO},
+ {ERRbadpermits, -EINVAL},
+ {ERRbadPID, -ESRCH},
+ {ERRsetattrmode, -EINVAL},
+ {ERRpaused, -EHOSTDOWN},
+ {ERRmsgoff, -EHOSTDOWN},
+ {ERRnoroom, -ENOSPC},
+ {ERRrmuns, -EUSERS},
+ {ERRtimeout, -ETIME},
+ {ERRnoresource, -EREMOTEIO},
+ {ERRtoomanyuids, -EUSERS},
+ {ERRbaduid, -EACCES},
+ {ERRusempx, -EIO},
+ {ERRusestd, -EIO},
+ {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
+ {ERRnoSuchUser, -EACCES},
+/* {ERRaccountexpired, -EACCES},
+ {ERRbadclient, -EACCES},
+ {ERRbadLogonTime, -EACCES},
+ {ERRpasswordExpired, -EACCES},*/
+ {ERRaccountexpired, -EKEYEXPIRED},
+ {ERRbadclient, -EACCES},
+ {ERRbadLogonTime, -EACCES},
+ {ERRpasswordExpired, -EKEYEXPIRED},
+
+ {ERRnosupport, -EINVAL},
+ {0, 0}
+};
+
+/*
+ * Convert a string containing text IPv4 or IPv6 address to binary form.
+ *
+ * Returns 0 on failure.
+ */
+static int
+cifs_inet_pton(const int address_family, const char *cp, int len, void *dst)
+{
+ int ret = 0;
+
+ /* calculate length by finding first slash or NULL */
+ if (address_family == AF_INET)
+ ret = in4_pton(cp, len, dst, '\\', NULL);
+ else if (address_family == AF_INET6)
+ ret = in6_pton(cp, len, dst , '\\', NULL);
+
+ cifs_dbg(NOISY, "address conversion returned %d for %*.*s\n",
+ ret, len, len, cp);
+ if (ret > 0)
+ ret = 1;
+ return ret;
+}
+
+/*
+ * Try to convert a string to an IPv4 address and then attempt to convert
+ * it to an IPv6 address if that fails. Set the family field if either
+ * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to
+ * treat the part following it as a numeric sin6_scope_id.
+ *
+ * Returns 0 on failure.
+ */
+int
+cifs_convert_address(struct sockaddr *dst, const char *src, int len)
+{
+ int rc, alen, slen;
+ const char *pct;
+ char scope_id[13];
+ struct sockaddr_in *s4 = (struct sockaddr_in *) dst;
+ struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst;
+
+ /* IPv4 address */
+ if (cifs_inet_pton(AF_INET, src, len, &s4->sin_addr.s_addr)) {
+ s4->sin_family = AF_INET;
+ return 1;
+ }
+
+ /* attempt to exclude the scope ID from the address part */
+ pct = memchr(src, '%', len);
+ alen = pct ? pct - src : len;
+
+ rc = cifs_inet_pton(AF_INET6, src, alen, &s6->sin6_addr.s6_addr);
+ if (!rc)
+ return rc;
+
+ s6->sin6_family = AF_INET6;
+ if (pct) {
+ /* grab the scope ID */
+ slen = len - (alen + 1);
+ if (slen <= 0 || slen > 12)
+ return 0;
+ memcpy(scope_id, pct + 1, slen);
+ scope_id[slen] = '\0';
+
+ rc = kstrtouint(scope_id, 0, &s6->sin6_scope_id);
+ rc = (rc == 0) ? 1 : 0;
+ }
+
+ return rc;
+}
+
+void
+cifs_set_port(struct sockaddr *addr, const unsigned short int port)
+{
+ switch (addr->sa_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)addr)->sin_port = htons(port);
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)addr)->sin6_port = htons(port);
+ break;
+ }
+}
+
+/*****************************************************************************
+convert a NT status code to a dos class/code
+ *****************************************************************************/
+/* NT status -> dos error map */
+static const struct {
+ __u8 dos_class;
+ __u16 dos_code;
+ __u32 ntstatus;
+} ntstatus_to_dos_map[] = {
+ {
+ ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
+ ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
+ ERRDOS, ERRinvlevel, NT_STATUS_INVALID_INFO_CLASS}, {
+ ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
+ ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
+ ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
+ ERRDOS, 87, NT_STATUS_INVALID_CID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
+ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
+ ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
+ ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
+ ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
+ ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
+ ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
+ ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
+ during the session setup } */
+ {
+ ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
+ ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
+ ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
+ ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
+ ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
+ ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
+ ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
+ during the session setup } */
+ {
+ ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
+ ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
+ ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
+ ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
+ ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
+ ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
+ /* mapping changed since shell does lookup on * expects FileNotFound */
+ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, {
+ ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
+ ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
+ ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
+ ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
+ ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
+ ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
+ ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
+ ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
+ ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
+ ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
+ ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
+ ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
+ ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
+ ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
+ ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
+ ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
+ ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
+ ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
+ ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
+ ERRDOS, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED}, {
+ ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
+ ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
+ ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
+ ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
+ ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
+ ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
+ ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
+ during the session setup } */
+ {
+ ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */
+ ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
+ during the session setup } */
+ {
+ ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
+ ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, {
+ ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, {
+ ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
+ ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
+ ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
+ ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
+ ERRDOS, 112, NT_STATUS_DISK_FULL}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
+ ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
+ ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
+ ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
+ ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
+ ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
+ ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
+ ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
+ ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_INSUFFICIENT_RESOURCES to
+ NT_STATUS_INSUFF_SERVER_RESOURCES during the session setup } */
+ {
+ ERRDOS, ERRnoresource, NT_STATUS_INSUFFICIENT_RESOURCES}, {
+ ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
+ ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
+ ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
+ ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
+ ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
+ ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
+ ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
+ ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
+ ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
+ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
+ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
+ ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
+ ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
+ ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
+ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
+ ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
+ ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
+ ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
+ ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
+ ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
+ ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
+ ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
+ ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
+ ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
+ ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
+ ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
+ ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
+ ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
+ ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
+ ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
+ ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
+ ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
+ ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
+ ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
+ ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
+ ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
+ ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
+ ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
+ ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
+ ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
+ ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
+ ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
+ ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
+ ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
+ ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
+ ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
+ ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
+ ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
+ ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
+ ERRDOS, 203, 0xc0000100}, {
+ ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
+ ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
+ ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
+ ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
+ ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
+ ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
+ ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
+ ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
+ ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
+ ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
+ ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
+ ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
+ ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
+ ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
+ ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
+ ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
+ ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
+ ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
+ ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
+ ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
+ ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
+ ERRHRD, ERRgeneral, 0xc000016e}, {
+ ERRHRD, ERRgeneral, 0xc000016f}, {
+ ERRHRD, ERRgeneral, 0xc0000170}, {
+ ERRHRD, ERRgeneral, 0xc0000171}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
+ ERRHRD, ERRgeneral, 0xc0000179}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
+ ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
+ ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
+ ERRDOS, 19, NT_STATUS_TOO_LATE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_NO_TRUST_SAM_ACCOUNT to
+ NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE during the session setup } */
+ {
+ ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
+ ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
+ ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
+/* { This NT error code was 'sqashed'
+ from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
+ during the session setup } */
+ {
+ ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
+ ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
+ ERRDOS, ERRnoresource, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
+ ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
+ ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
+ ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
+ ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
+ ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
+ ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
+ ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
+ ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
+ ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
+ ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
+ ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_MUST_CHANGE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
+ ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
+ ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
+ ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
+ ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
+ ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
+ ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
+ ERRHRD, ERRgeneral, 0xc000024a}, {
+ ERRHRD, ERRgeneral, 0xc000024b}, {
+ ERRHRD, ERRgeneral, 0xc000024c}, {
+ ERRHRD, ERRgeneral, 0xc000024d}, {
+ ERRHRD, ERRgeneral, 0xc000024e}, {
+ ERRHRD, ERRgeneral, 0xc000024f}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
+ ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
+ ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
+ ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
+ ERRHRD, ERRgeneral, 0xc000025d}, {
+ ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
+ ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
+ ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
+ ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
+ ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
+ ERRDOS, ErrTooManyLinks, NT_STATUS_TOO_MANY_LINKS}, {
+ ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
+ ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
+ ERRDOS, 21, 0xc000026e}, {
+ ERRDOS, 161, 0xc0000281}, {
+ ERRDOS, ERRnoaccess, 0xc000028a}, {
+ ERRDOS, ERRnoaccess, 0xc000028b}, {
+ ERRHRD, ERRgeneral, 0xc000028c}, {
+ ERRDOS, ERRnoaccess, 0xc000028d}, {
+ ERRDOS, ERRnoaccess, 0xc000028e}, {
+ ERRDOS, ERRnoaccess, 0xc000028f}, {
+ ERRDOS, ERRnoaccess, 0xc0000290}, {
+ ERRDOS, ERRbadfunc, 0xc000029c}, {
+ ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
+ ERRDOS, ERRinvlevel, 0x007c0001}, {
+ 0, 0, 0 }
+};
+
+/*****************************************************************************
+ Print an error message from the status code
+ *****************************************************************************/
+static void
+cifs_print_status(__u32 status_code)
+{
+ int idx = 0;
+
+ while (nt_errs[idx].nt_errstr != NULL) {
+ if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
+ (status_code & 0xFFFFFF)) {
+ pr_notice("Status code returned 0x%08x %s\n",
+ status_code, nt_errs[idx].nt_errstr);
+ }
+ idx++;
+ }
+ return;
+}
+
+
+static void
+ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode)
+{
+ int i;
+ if (ntstatus == 0) {
+ *eclass = 0;
+ *ecode = 0;
+ return;
+ }
+ for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
+ if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
+ *eclass = ntstatus_to_dos_map[i].dos_class;
+ *ecode = ntstatus_to_dos_map[i].dos_code;
+ return;
+ }
+ }
+ *eclass = ERRHRD;
+ *ecode = ERRgeneral;
+}
+
+int
+map_smb_to_linux_error(char *buf, bool logErr)
+{
+ struct smb_hdr *smb = (struct smb_hdr *)buf;
+ unsigned int i;
+ int rc = -EIO; /* if transport error smb error may not be set */
+ __u8 smberrclass;
+ __u16 smberrcode;
+
+ /* BB if NT Status codes - map NT BB */
+
+ /* old style smb error codes */
+ if (smb->Status.CifsError == 0)
+ return 0;
+
+ if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
+ /* translate the newer STATUS codes to old style SMB errors
+ * and then to POSIX errors */
+ __u32 err = le32_to_cpu(smb->Status.CifsError);
+ if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED)))
+ cifs_print_status(err);
+ else if (cifsFYI & CIFS_RC)
+ cifs_print_status(err);
+ ntstatus_to_dos(err, &smberrclass, &smberrcode);
+ } else {
+ smberrclass = smb->Status.DosError.ErrorClass;
+ smberrcode = le16_to_cpu(smb->Status.DosError.Error);
+ }
+
+ /* old style errors */
+
+ /* DOS class smb error codes - map DOS */
+ if (smberrclass == ERRDOS) {
+ /* 1 byte field no need to byte reverse */
+ for (i = 0;
+ i <
+ sizeof(mapping_table_ERRDOS) /
+ sizeof(struct smb_to_posix_error); i++) {
+ if (mapping_table_ERRDOS[i].smb_err == 0)
+ break;
+ else if (mapping_table_ERRDOS[i].smb_err ==
+ smberrcode) {
+ rc = mapping_table_ERRDOS[i].posix_code;
+ break;
+ }
+ /* else try next error mapping one to see if match */
+ }
+ } else if (smberrclass == ERRSRV) {
+ /* server class of error codes */
+ for (i = 0;
+ i <
+ sizeof(mapping_table_ERRSRV) /
+ sizeof(struct smb_to_posix_error); i++) {
+ if (mapping_table_ERRSRV[i].smb_err == 0)
+ break;
+ else if (mapping_table_ERRSRV[i].smb_err ==
+ smberrcode) {
+ rc = mapping_table_ERRSRV[i].posix_code;
+ break;
+ }
+ /* else try next error mapping to see if match */
+ }
+ }
+ /* else ERRHRD class errors or junk - return EIO */
+
+ cifs_dbg(FYI, "Mapping smb error code 0x%x to POSIX err %d\n",
+ le32_to_cpu(smb->Status.CifsError), rc);
+
+ /* generic corrective action e.g. reconnect SMB session on
+ * ERRbaduid could be added */
+
+ return rc;
+}
+
+int
+map_and_check_smb_error(struct mid_q_entry *mid, bool logErr)
+{
+ int rc;
+ struct smb_hdr *smb = (struct smb_hdr *)mid->resp_buf;
+
+ rc = map_smb_to_linux_error((char *)smb, logErr);
+ if (rc == -EACCES && !(smb->Flags2 & SMBFLG2_ERR_STATUS)) {
+ /* possible ERRBaduid */
+ __u8 class = smb->Status.DosError.ErrorClass;
+ __u16 code = le16_to_cpu(smb->Status.DosError.Error);
+
+ /* switch can be used to handle different errors */
+ if (class == ERRSRV && code == ERRbaduid) {
+ cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n",
+ code);
+ cifs_signal_cifsd_for_reconnect(mid->server, false);
+ }
+ }
+
+ return rc;
+}
+
+
+/*
+ * calculate the size of the SMB message based on the fixed header
+ * portion, the number of word parameters and the data portion of the message
+ */
+unsigned int
+smbCalcSize(void *buf)
+{
+ struct smb_hdr *ptr = buf;
+ return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
+ 2 /* size of the bcc field */ + get_bcc(ptr));
+}
+
+/* The following are taken from fs/ntfs/util.c */
+
+#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
+
+/*
+ * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
+ * into Unix UTC (based 1970-01-01, in seconds).
+ */
+struct timespec64
+cifs_NTtimeToUnix(__le64 ntutc)
+{
+ struct timespec64 ts;
+ /* BB what about the timezone? BB */
+
+ /* Subtract the NTFS time offset, then convert to 1s intervals. */
+ s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
+ u64 abs_t;
+
+ /*
+ * Unfortunately can not use normal 64 bit division on 32 bit arch, but
+ * the alternative, do_div, does not work with negative numbers so have
+ * to special case them
+ */
+ if (t < 0) {
+ abs_t = -t;
+ ts.tv_nsec = (time64_t)(do_div(abs_t, 10000000) * 100);
+ ts.tv_nsec = -ts.tv_nsec;
+ ts.tv_sec = -abs_t;
+ } else {
+ abs_t = t;
+ ts.tv_nsec = (time64_t)do_div(abs_t, 10000000) * 100;
+ ts.tv_sec = abs_t;
+ }
+
+ return ts;
+}
+
+/* Convert the Unix UTC into NT UTC. */
+u64
+cifs_UnixTimeToNT(struct timespec64 t)
+{
+ /* Convert to 100ns intervals and then add the NTFS time offset. */
+ return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET;
+}
+
+static const int total_days_of_prev_months[] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
+{
+ struct timespec64 ts;
+ time64_t sec, days;
+ int min, day, month, year;
+ u16 date = le16_to_cpu(le_date);
+ u16 time = le16_to_cpu(le_time);
+ SMB_TIME *st = (SMB_TIME *)&time;
+ SMB_DATE *sd = (SMB_DATE *)&date;
+
+ cifs_dbg(FYI, "date %d time %d\n", date, time);
+
+ sec = 2 * st->TwoSeconds;
+ min = st->Minutes;
+ if ((sec > 59) || (min > 59))
+ cifs_dbg(VFS, "Invalid time min %d sec %lld\n", min, sec);
+ sec += (min * 60);
+ sec += 60 * 60 * st->Hours;
+ if (st->Hours > 24)
+ cifs_dbg(VFS, "Invalid hours %d\n", st->Hours);
+ day = sd->Day;
+ month = sd->Month;
+ if (day < 1 || day > 31 || month < 1 || month > 12) {
+ cifs_dbg(VFS, "Invalid date, month %d day: %d\n", month, day);
+ day = clamp(day, 1, 31);
+ month = clamp(month, 1, 12);
+ }
+ month -= 1;
+ days = day + total_days_of_prev_months[month];
+ days += 3652; /* account for difference in days between 1980 and 1970 */
+ year = sd->Year;
+ days += year * 365;
+ days += (year/4); /* leap year */
+ /* generalized leap year calculation is more complex, ie no leap year
+ for years/100 except for years/400, but since the maximum number for DOS
+ year is 2**7, the last year is 1980+127, which means we need only
+ consider 2 special case years, ie the years 2000 and 2100, and only
+ adjust for the lack of leap year for the year 2100, as 2000 was a
+ leap year (divisable by 400) */
+ if (year >= 120) /* the year 2100 */
+ days = days - 1; /* do not count leap year for the year 2100 */
+
+ /* adjust for leap year where we are still before leap day */
+ if (year != 120)
+ days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
+ sec += 24 * 60 * 60 * days;
+
+ ts.tv_sec = sec + offset;
+
+ /* cifs_dbg(FYI, "sec after cnvrt dos to unix time %d\n",sec); */
+
+ ts.tv_nsec = 0;
+ return ts;
+}
diff --git a/fs/smb/client/nterr.c b/fs/smb/client/nterr.c
new file mode 100644
index 000000000000..358a766375b4
--- /dev/null
+++ b/fs/smb/client/nterr.c
@@ -0,0 +1,674 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * RPC Pipe client / server routines
+ * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
+ */
+
+/* NT error codes - see nterr.h */
+#include <linux/types.h>
+#include <linux/fs.h>
+#include "nterr.h"
+
+const struct nt_err_code_struct nt_errs[] = {
+ {"NT_STATUS_OK", NT_STATUS_OK},
+ {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
+ {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
+ {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
+ {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
+ {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
+ {"NT_STATUS_BUFFER_OVERFLOW", NT_STATUS_BUFFER_OVERFLOW},
+ {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
+ {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
+ {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
+ {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
+ {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
+ {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
+ {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
+ {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
+ {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
+ {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
+ {"NT_STATUS_INVALID_DEVICE_REQUEST",
+ NT_STATUS_INVALID_DEVICE_REQUEST},
+ {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
+ {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
+ {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
+ {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
+ {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
+ {"NT_STATUS_MORE_PROCESSING_REQUIRED",
+ NT_STATUS_MORE_PROCESSING_REQUIRED},
+ {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
+ {"NT_STATUS_CONFLICTING_ADDRESSES",
+ NT_STATUS_CONFLICTING_ADDRESSES},
+ {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
+ {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
+ {"NT_STATUS_UNABLE_TO_DELETE_SECTION",
+ NT_STATUS_UNABLE_TO_DELETE_SECTION},
+ {"NT_STATUS_INVALID_SYSTEM_SERVICE",
+ NT_STATUS_INVALID_SYSTEM_SERVICE},
+ {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
+ {"NT_STATUS_INVALID_LOCK_SEQUENCE",
+ NT_STATUS_INVALID_LOCK_SEQUENCE},
+ {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
+ {"NT_STATUS_INVALID_FILE_FOR_SECTION",
+ NT_STATUS_INVALID_FILE_FOR_SECTION},
+ {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
+ {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
+ {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
+ {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
+ {"NT_STATUS_NONCONTINUABLE_EXCEPTION",
+ NT_STATUS_NONCONTINUABLE_EXCEPTION},
+ {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
+ {"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
+ {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
+ {"NT_STATUS_INVALID_UNWIND_TARGET",
+ NT_STATUS_INVALID_UNWIND_TARGET},
+ {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
+ {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
+ {"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
+ NT_STATUS_UNABLE_TO_DECOMMIT_VM},
+ {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
+ {"NT_STATUS_INVALID_PORT_ATTRIBUTES",
+ NT_STATUS_INVALID_PORT_ATTRIBUTES},
+ {"NT_STATUS_PORT_MESSAGE_TOO_LONG",
+ NT_STATUS_PORT_MESSAGE_TOO_LONG},
+ {"NT_STATUS_INVALID_PARAMETER_MIX",
+ NT_STATUS_INVALID_PARAMETER_MIX},
+ {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
+ {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
+ {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
+ {"NT_STATUS_OBJECT_NAME_NOT_FOUND",
+ NT_STATUS_OBJECT_NAME_NOT_FOUND},
+ {"NT_STATUS_OBJECT_NAME_COLLISION",
+ NT_STATUS_OBJECT_NAME_COLLISION},
+ {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
+ {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
+ {"NT_STATUS_DEVICE_ALREADY_ATTACHED",
+ NT_STATUS_DEVICE_ALREADY_ATTACHED},
+ {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
+ {"NT_STATUS_OBJECT_PATH_NOT_FOUND",
+ NT_STATUS_OBJECT_PATH_NOT_FOUND},
+ {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
+ NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
+ {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
+ {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
+ {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
+ {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
+ {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
+ {"NT_STATUS_PORT_CONNECTION_REFUSED",
+ NT_STATUS_PORT_CONNECTION_REFUSED},
+ {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
+ {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
+ {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
+ {"NT_STATUS_INVALID_PAGE_PROTECTION",
+ NT_STATUS_INVALID_PAGE_PROTECTION},
+ {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
+ {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
+ NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
+ {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
+ {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
+ {"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
+ NT_STATUS_SUSPEND_COUNT_EXCEEDED},
+ {"NT_STATUS_THREAD_IS_TERMINATING",
+ NT_STATUS_THREAD_IS_TERMINATING},
+ {"NT_STATUS_BAD_WORKING_SET_LIMIT",
+ NT_STATUS_BAD_WORKING_SET_LIMIT},
+ {"NT_STATUS_INCOMPATIBLE_FILE_MAP",
+ NT_STATUS_INCOMPATIBLE_FILE_MAP},
+ {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
+ {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
+ {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
+ {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
+ {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
+ {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
+ {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
+ {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
+ {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
+ {"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
+ NT_STATUS_CTL_FILE_NOT_SUPPORTED},
+ {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
+ {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
+ {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
+ {"NT_STATUS_INVALID_PRIMARY_GROUP",
+ NT_STATUS_INVALID_PRIMARY_GROUP},
+ {"NT_STATUS_NO_IMPERSONATION_TOKEN",
+ NT_STATUS_NO_IMPERSONATION_TOKEN},
+ {"NT_STATUS_CANT_DISABLE_MANDATORY",
+ NT_STATUS_CANT_DISABLE_MANDATORY},
+ {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
+ {"NT_STATUS_NO_SUCH_LOGON_SESSION",
+ NT_STATUS_NO_SUCH_LOGON_SESSION},
+ {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
+ {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
+ {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
+ {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
+ {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
+ {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
+ {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
+ {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
+ {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
+ {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
+ {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
+ {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
+ {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
+ {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
+ {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
+ {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
+ {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
+ {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
+ {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
+ {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
+ {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
+ NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
+ {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
+ {"NT_STATUS_INVALID_SUB_AUTHORITY",
+ NT_STATUS_INVALID_SUB_AUTHORITY},
+ {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
+ {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
+ {"NT_STATUS_INVALID_SECURITY_DESCR",
+ NT_STATUS_INVALID_SECURITY_DESCR},
+ {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
+ {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
+ {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
+ {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
+ {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
+ {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
+ {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
+ {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
+ {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
+ NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
+ {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
+ {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
+ {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
+ {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
+ {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
+ {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
+ {"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
+ NT_STATUS_RESOURCE_DATA_NOT_FOUND},
+ {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
+ NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
+ {"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
+ NT_STATUS_RESOURCE_NAME_NOT_FOUND},
+ {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
+ NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
+ {"NT_STATUS_FLOAT_DENORMAL_OPERAND",
+ NT_STATUS_FLOAT_DENORMAL_OPERAND},
+ {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
+ {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
+ {"NT_STATUS_FLOAT_INVALID_OPERATION",
+ NT_STATUS_FLOAT_INVALID_OPERATION},
+ {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
+ {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
+ {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
+ {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
+ NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
+ {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
+ {"NT_STATUS_PRIVILEGED_INSTRUCTION",
+ NT_STATUS_PRIVILEGED_INSTRUCTION},
+ {"NT_STATUS_TOO_MANY_PAGING_FILES",
+ NT_STATUS_TOO_MANY_PAGING_FILES},
+ {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
+ {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
+ NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
+ {"NT_STATUS_INSUFFICIENT_RESOURCES",
+ NT_STATUS_INSUFFICIENT_RESOURCES},
+ {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
+ {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
+ {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
+ {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
+ {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
+ {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
+ {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
+ {"NT_STATUS_MEDIA_WRITE_PROTECTED",
+ NT_STATUS_MEDIA_WRITE_PROTECTED},
+ {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
+ {"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
+ NT_STATUS_INVALID_GROUP_ATTRIBUTES},
+ {"NT_STATUS_BAD_IMPERSONATION_LEVEL",
+ NT_STATUS_BAD_IMPERSONATION_LEVEL},
+ {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
+ {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
+ {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
+ {"NT_STATUS_BAD_MASTER_BOOT_RECORD",
+ NT_STATUS_BAD_MASTER_BOOT_RECORD},
+ {"NT_STATUS_INSTRUCTION_MISALIGNMENT",
+ NT_STATUS_INSTRUCTION_MISALIGNMENT},
+ {"NT_STATUS_INSTANCE_NOT_AVAILABLE",
+ NT_STATUS_INSTANCE_NOT_AVAILABLE},
+ {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
+ {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
+ {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
+ {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
+ {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
+ {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
+ {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
+ {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
+ {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
+ {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
+ {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
+ {"NT_STATUS_PROFILING_NOT_STARTED",
+ NT_STATUS_PROFILING_NOT_STARTED},
+ {"NT_STATUS_PROFILING_NOT_STOPPED",
+ NT_STATUS_PROFILING_NOT_STOPPED},
+ {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
+ {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
+ {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
+ {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
+ {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
+ {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
+ {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
+ {"NT_STATUS_DEVICE_DOES_NOT_EXIST",
+ NT_STATUS_DEVICE_DOES_NOT_EXIST},
+ {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
+ {"NT_STATUS_ADAPTER_HARDWARE_ERROR",
+ NT_STATUS_ADAPTER_HARDWARE_ERROR},
+ {"NT_STATUS_INVALID_NETWORK_RESPONSE",
+ NT_STATUS_INVALID_NETWORK_RESPONSE},
+ {"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
+ NT_STATUS_UNEXPECTED_NETWORK_ERROR},
+ {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
+ {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
+ {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
+ {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
+ {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
+ {"NT_STATUS_NETWORK_ACCESS_DENIED",
+ NT_STATUS_NETWORK_ACCESS_DENIED},
+ {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
+ {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
+ {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
+ {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
+ {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
+ {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
+ {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
+ {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
+ {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
+ {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
+ {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
+ {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
+ NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
+ {"NT_STATUS_NO_SECURITY_ON_OBJECT",
+ NT_STATUS_NO_SECURITY_ON_OBJECT},
+ {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
+ {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
+ {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
+ NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
+ {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
+ {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
+ {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
+ {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
+ {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
+ {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
+ {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
+ NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
+ {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
+ {"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
+ NT_STATUS_INVALID_OPLOCK_PROTOCOL},
+ {"NT_STATUS_INTERNAL_DB_CORRUPTION",
+ NT_STATUS_INTERNAL_DB_CORRUPTION},
+ {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
+ {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
+ {"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
+ NT_STATUS_BAD_DESCRIPTOR_FORMAT},
+ {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
+ {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
+ {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
+ NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
+ {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
+ NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
+ {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
+ NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
+ {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
+ {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
+ {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
+ {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
+ {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
+ {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
+ {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
+ {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
+ {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
+ {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
+ {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
+ {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
+ {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
+ {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
+ {"NT_STATUS_REDIRECTOR_NOT_STARTED",
+ NT_STATUS_REDIRECTOR_NOT_STARTED},
+ {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
+ {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
+ {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
+ {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
+ {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
+ {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
+ {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
+ {"NT_STATUS_BAD_LOGON_SESSION_STATE",
+ NT_STATUS_BAD_LOGON_SESSION_STATE},
+ {"NT_STATUS_LOGON_SESSION_COLLISION",
+ NT_STATUS_LOGON_SESSION_COLLISION},
+ {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
+ {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
+ {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
+ {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
+ {"NT_STATUS_PROCESS_IS_TERMINATING",
+ NT_STATUS_PROCESS_IS_TERMINATING},
+ {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
+ {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
+ {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
+ {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
+ {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
+ {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
+ {"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
+ NT_STATUS_ABIOS_LID_ALREADY_OWNED},
+ {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
+ {"NT_STATUS_ABIOS_INVALID_COMMAND",
+ NT_STATUS_ABIOS_INVALID_COMMAND},
+ {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
+ {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
+ NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
+ {"NT_STATUS_ABIOS_INVALID_SELECTOR",
+ NT_STATUS_ABIOS_INVALID_SELECTOR},
+ {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
+ {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
+ {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
+ {"NT_STATUS_INVALID_LDT_DESCRIPTOR",
+ NT_STATUS_INVALID_LDT_DESCRIPTOR},
+ {"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
+ NT_STATUS_INVALID_IMAGE_NE_FORMAT},
+ {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
+ {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
+ {"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
+ NT_STATUS_MAPPED_FILE_SIZE_ZERO},
+ {"NT_STATUS_TOO_MANY_OPENED_FILES",
+ NT_STATUS_TOO_MANY_OPENED_FILES},
+ {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
+ {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
+ {"NT_STATUS_INVALID_COMPUTER_NAME",
+ NT_STATUS_INVALID_COMPUTER_NAME},
+ {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
+ {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
+ {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
+ {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
+ {"NT_STATUS_MEMBERS_PRIMARY_GROUP",
+ NT_STATUS_MEMBERS_PRIMARY_GROUP},
+ {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
+ {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
+ {"NT_STATUS_THREAD_NOT_IN_PROCESS",
+ NT_STATUS_THREAD_NOT_IN_PROCESS},
+ {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
+ {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
+ NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
+ {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
+ {"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
+ NT_STATUS_INVALID_IMAGE_LE_FORMAT},
+ {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
+ {"NT_STATUS_INVALID_IMAGE_PROTECT",
+ NT_STATUS_INVALID_IMAGE_PROTECT},
+ {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
+ {"NT_STATUS_LOGON_SERVER_CONFLICT",
+ NT_STATUS_LOGON_SERVER_CONFLICT},
+ {"NT_STATUS_TIME_DIFFERENCE_AT_DC",
+ NT_STATUS_TIME_DIFFERENCE_AT_DC},
+ {"NT_STATUS_SYNCHRONIZATION_REQUIRED",
+ NT_STATUS_SYNCHRONIZATION_REQUIRED},
+ {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
+ {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
+ {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
+ {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
+ {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
+ {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
+ {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
+ {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
+ {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
+ {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
+ {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
+ {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
+ {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
+ {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
+ {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
+ {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
+ {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
+ {"NT_STATUS_PAGEFILE_CREATE_FAILED",
+ NT_STATUS_PAGEFILE_CREATE_FAILED},
+ {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
+ {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
+ {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
+ {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
+ NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
+ {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
+ {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
+ {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
+ {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
+ {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
+ {"NT_STATUS_SERIAL_NO_DEVICE_INITED",
+ NT_STATUS_SERIAL_NO_DEVICE_INITED},
+ {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
+ {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
+ {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
+ {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
+ {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
+ {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
+ {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
+ {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
+ {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
+ {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
+ {"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
+ NT_STATUS_LOGON_TYPE_NOT_GRANTED},
+ {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
+ {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
+ NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
+ {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
+ NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
+ {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
+ {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
+ NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
+ {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
+ {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
+ {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
+ {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
+ {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
+ NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
+ {"NT_STATUS_FLOPPY_WRONG_CYLINDER",
+ NT_STATUS_FLOPPY_WRONG_CYLINDER},
+ {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
+ {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
+ {"NT_STATUS_DISK_RECALIBRATE_FAILED",
+ NT_STATUS_DISK_RECALIBRATE_FAILED},
+ {"NT_STATUS_DISK_OPERATION_FAILED",
+ NT_STATUS_DISK_OPERATION_FAILED},
+ {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
+ {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
+ {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
+ {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
+ {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
+ {"NT_STATUS_DEVICE_NOT_PARTITIONED",
+ NT_STATUS_DEVICE_NOT_PARTITIONED},
+ {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
+ {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
+ NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
+ {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
+ {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
+ {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
+ {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
+ {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
+ {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
+ {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
+ {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
+ NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
+ {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
+ {"NT_STATUS_CHILD_MUST_BE_VOLATILE",
+ NT_STATUS_CHILD_MUST_BE_VOLATILE},
+ {"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
+ NT_STATUS_DEVICE_CONFIGURATION_ERROR},
+ {"NT_STATUS_DRIVER_INTERNAL_ERROR",
+ NT_STATUS_DRIVER_INTERNAL_ERROR},
+ {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
+ {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
+ {"NT_STATUS_DEVICE_PROTOCOL_ERROR",
+ NT_STATUS_DEVICE_PROTOCOL_ERROR},
+ {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
+ {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
+ {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
+ {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
+ {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
+ {"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
+ NT_STATUS_TRUSTED_DOMAIN_FAILURE},
+ {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
+ NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
+ {"NT_STATUS_EVENTLOG_FILE_CORRUPT",
+ NT_STATUS_EVENTLOG_FILE_CORRUPT},
+ {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
+ {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
+ {"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
+ NT_STATUS_MUTANT_LIMIT_EXCEEDED},
+ {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
+ {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
+ {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
+ {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
+ NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
+ {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
+ {"NT_STATUS_EVENTLOG_FILE_CHANGED",
+ NT_STATUS_EVENTLOG_FILE_CHANGED},
+ {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
+ NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
+ {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
+ NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
+ {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
+ NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
+ {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
+ NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
+ {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
+ {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
+ {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
+ {"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
+ NT_STATUS_RESOURCE_LANG_NOT_FOUND},
+ {"NT_STATUS_INSUFF_SERVER_RESOURCES",
+ NT_STATUS_INSUFF_SERVER_RESOURCES},
+ {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
+ {"NT_STATUS_INVALID_ADDRESS_COMPONENT",
+ NT_STATUS_INVALID_ADDRESS_COMPONENT},
+ {"NT_STATUS_INVALID_ADDRESS_WILDCARD",
+ NT_STATUS_INVALID_ADDRESS_WILDCARD},
+ {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
+ {"NT_STATUS_ADDRESS_ALREADY_EXISTS",
+ NT_STATUS_ADDRESS_ALREADY_EXISTS},
+ {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
+ {"NT_STATUS_CONNECTION_DISCONNECTED",
+ NT_STATUS_CONNECTION_DISCONNECTED},
+ {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
+ {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
+ {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
+ {"NT_STATUS_TRANSACTION_TIMED_OUT",
+ NT_STATUS_TRANSACTION_TIMED_OUT},
+ {"NT_STATUS_TRANSACTION_NO_RELEASE",
+ NT_STATUS_TRANSACTION_NO_RELEASE},
+ {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
+ {"NT_STATUS_TRANSACTION_RESPONDED",
+ NT_STATUS_TRANSACTION_RESPONDED},
+ {"NT_STATUS_TRANSACTION_INVALID_ID",
+ NT_STATUS_TRANSACTION_INVALID_ID},
+ {"NT_STATUS_TRANSACTION_INVALID_TYPE",
+ NT_STATUS_TRANSACTION_INVALID_TYPE},
+ {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
+ {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
+ {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
+ NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
+ {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
+ {"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
+ NT_STATUS_SYSTEM_PROCESS_TERMINATED},
+ {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
+ {"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
+ NT_STATUS_NO_BROWSER_SERVERS_FOUND},
+ {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
+ {"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
+ NT_STATUS_DRIVER_CANCEL_TIMEOUT},
+ {"NT_STATUS_REPLY_MESSAGE_MISMATCH",
+ NT_STATUS_REPLY_MESSAGE_MISMATCH},
+ {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
+ {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
+ NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
+ {"NT_STATUS_LOST_WRITEBEHIND_DATA",
+ NT_STATUS_LOST_WRITEBEHIND_DATA},
+ {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
+ NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
+ {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
+ {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
+ {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
+ {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
+ {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
+ {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
+ {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
+ {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
+ {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
+ {"NT_STATUS_RETRY", NT_STATUS_RETRY},
+ {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
+ {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
+ {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
+ {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
+ {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
+ {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
+ NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
+ {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
+ {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
+ {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
+ {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
+ {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
+ NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
+ {"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
+ NT_STATUS_ADDRESS_NOT_ASSOCIATED},
+ {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
+ {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
+ {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
+ {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
+ {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
+ {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
+ {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
+ {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
+ {"NT_STATUS_BAD_COMPRESSION_BUFFER",
+ NT_STATUS_BAD_COMPRESSION_BUFFER},
+ {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
+ {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
+ {"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
+ NT_STATUS_TIMER_RESOLUTION_NOT_SET},
+ {"NT_STATUS_CONNECTION_COUNT_LIMIT",
+ NT_STATUS_CONNECTION_COUNT_LIMIT},
+ {"NT_STATUS_LOGIN_TIME_RESTRICTION",
+ NT_STATUS_LOGIN_TIME_RESTRICTION},
+ {"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
+ NT_STATUS_LOGIN_WKSTA_RESTRICTION},
+ {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
+ {"NT_STATUS_INSUFFICIENT_LOGON_INFO",
+ NT_STATUS_INSUFFICIENT_LOGON_INFO},
+ {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
+ {"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
+ NT_STATUS_BAD_SERVICE_ENTRYPOINT},
+ {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
+ {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
+ {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
+ {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
+ {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
+ {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
+ {"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
+ NT_STATUS_LICENSE_QUOTA_EXCEEDED},
+ {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
+ {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
+ {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
+ {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
+ {"NT_STATUS_UNSUPPORTED_COMPRESSION",
+ NT_STATUS_UNSUPPORTED_COMPRESSION},
+ {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
+ {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
+ NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
+ {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
+ NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
+ {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
+ NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
+ {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
+ {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
+ {"NT_STATUS_QUOTA_LIST_INCONSISTENT",
+ NT_STATUS_QUOTA_LIST_INCONSISTENT},
+ {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
+ {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
+ {"NT_STATUS_MORE_ENTRIES", NT_STATUS_MORE_ENTRIES},
+ {"NT_STATUS_SOME_UNMAPPED", NT_STATUS_SOME_UNMAPPED},
+ {NULL, 0}
+};
diff --git a/fs/smb/client/nterr.h b/fs/smb/client/nterr.h
new file mode 100644
index 000000000000..edd4741cab0a
--- /dev/null
+++ b/fs/smb/client/nterr.h
@@ -0,0 +1,551 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NT error code constants
+ Copyright (C) Andrew Tridgell 1992-2000
+ Copyright (C) John H Terpstra 1996-2000
+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000
+ Copyright (C) Paul Ashton 1998-2000
+
+*/
+
+
+
+#ifndef _NTERR_H
+#define _NTERR_H
+
+struct nt_err_code_struct {
+ char *nt_errstr;
+ __u32 nt_errcode;
+};
+
+extern const struct nt_err_code_struct nt_errs[];
+
+/* Win32 Status codes. */
+#define NT_STATUS_MORE_ENTRIES 0x0105
+#define NT_ERROR_INVALID_PARAMETER 0x0057
+#define NT_ERROR_INSUFFICIENT_BUFFER 0x007a
+#define NT_STATUS_1804 0x070c
+#define NT_STATUS_NOTIFY_ENUM_DIR 0x010c
+
+/*
+ * Win32 Error codes extracted using a loop in smbclient then printing a netmon
+ * sniff to a file.
+ */
+
+#define NT_STATUS_OK 0x0000
+#define NT_STATUS_SOME_UNMAPPED 0x0107
+#define NT_STATUS_BUFFER_OVERFLOW 0x80000005
+#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
+#define NT_STATUS_MEDIA_CHANGED 0x8000001c
+#define NT_STATUS_END_OF_MEDIA 0x8000001e
+#define NT_STATUS_MEDIA_CHECK 0x80000020
+#define NT_STATUS_NO_DATA_DETECTED 0x8000001c
+#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d
+#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288
+#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288
+#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
+#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
+#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
+#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
+#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
+#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
+#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
+#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
+#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
+#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
+#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
+#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
+#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
+#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
+#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
+#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
+#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
+#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
+#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
+#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
+#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
+#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
+#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
+#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
+#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
+#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
+#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
+#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
+#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
+#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
+#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
+#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
+#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
+#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
+#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
+#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
+#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
+#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
+#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
+#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
+#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
+#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
+#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
+#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
+#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
+#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
+#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
+#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
+#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
+#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
+#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
+#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
+#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
+#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
+#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
+#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
+#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
+#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
+#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
+#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
+#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
+#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
+#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
+#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
+#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
+#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
+#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
+#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
+#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
+#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
+#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
+#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
+#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
+#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
+#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
+#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
+#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
+#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
+#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
+#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
+#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
+#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
+#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
+#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
+#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
+#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
+#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
+#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
+#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
+#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
+#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
+#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
+#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
+#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
+#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
+#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
+#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
+#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
+#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
+#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
+#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
+#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
+#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
+#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
+#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
+#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
+#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
+#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
+#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
+#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
+#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
+#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
+#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
+#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
+#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
+#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
+#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
+#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
+#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
+#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
+#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
+#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
+#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
+#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
+#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
+#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
+#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
+#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
+#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
+#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
+#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
+#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
+#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
+#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
+#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
+#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
+#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
+#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
+#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
+#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
+#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
+#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
+#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
+#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
+#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
+#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
+#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
+#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
+#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
+#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
+#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
+#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
+#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
+#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
+#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
+#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
+#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
+#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
+#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
+#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
+#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
+#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
+#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
+#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
+#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
+#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
+#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
+#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
+#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
+#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
+#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
+#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
+#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
+#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
+#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
+#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
+#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
+#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
+#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
+#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
+#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
+#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
+#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
+#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
+#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
+#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
+#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
+#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
+#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
+#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
+#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
+#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
+#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
+#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
+#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
+#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
+#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
+#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
+#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
+#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
+#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
+#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
+#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
+#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
+#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
+#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
+#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
+#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
+#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
+#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
+#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
+#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
+#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
+#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
+#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
+#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
+#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
+#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
+#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
+#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
+#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
+#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
+#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
+#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
+#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
+#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
+#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
+#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
+#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
+#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
+#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
+#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
+#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
+#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
+#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
+#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
+#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
+#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
+#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
+#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
+#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
+#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
+#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
+#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
+#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
+#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
+#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
+#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
+#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
+#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
+#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
+#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
+#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
+#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
+#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
+#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
+#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
+#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
+#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
+#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
+#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
+#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
+#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
+#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
+#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
+#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
+#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
+#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
+#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
+#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
+#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
+#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
+#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
+#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
+#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
+#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
+#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
+#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
+#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
+#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
+#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
+#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
+#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
+#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
+#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
+#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
+#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
+#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
+#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
+#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
+#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
+#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
+#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
+#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
+#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
+#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
+#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
+#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
+#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
+#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
+#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
+#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
+#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
+#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
+#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
+#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
+#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
+#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
+#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
+#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
+#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
+#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
+#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
+#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
+#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
+#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
+#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
+#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
+#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
+#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
+#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
+#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
+#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
+#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
+#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
+#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
+#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
+#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
+#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
+#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
+#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
+#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
+#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
+#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
+#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
+#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
+#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
+#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
+#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
+#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
+#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
+#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
+#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
+#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
+#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
+#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
+#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
+#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
+#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
+#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
+#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
+#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
+#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
+#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
+#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
+#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
+#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
+#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
+#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
+#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
+#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
+#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
+#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
+#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
+#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
+#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
+#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
+#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
+#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
+#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
+#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
+#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
+#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
+#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
+#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
+#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
+#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
+#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
+#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
+#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
+#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
+#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
+#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
+#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
+#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
+#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
+#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
+#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
+#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
+#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
+#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
+#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
+#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
+#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
+#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
+#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
+#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
+#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
+#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
+#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
+#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
+#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
+#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
+#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
+#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
+#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
+#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
+#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
+#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
+#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
+#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
+#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
+#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
+#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
+#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
+#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
+#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
+#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
+#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
+#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
+#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
+#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
+#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
+#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
+#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
+#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
+#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
+#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
+#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
+#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
+#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
+#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
+#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
+#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
+#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
+#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
+#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
+#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
+#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
+#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
+#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
+#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
+#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
+#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
+#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
+#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
+#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
+#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
+#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
+#define NT_STATUS_RETRY 0xC0000000 | 0x022d
+#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
+#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
+#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
+#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
+#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
+#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
+#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
+#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
+#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
+#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
+#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
+#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
+#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
+#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
+#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
+#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
+#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
+#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
+#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
+#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
+#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
+#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
+#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
+#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
+#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
+#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
+#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
+#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
+#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
+#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
+#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
+#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
+#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
+#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
+#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
+#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
+#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
+#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
+#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
+#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
+#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
+#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
+#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
+#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
+#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
+#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
+#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
+#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
+#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
+#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
+#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
+#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
+
+#endif /* _NTERR_H */
diff --git a/fs/smb/client/ntlmssp.h b/fs/smb/client/ntlmssp.h
new file mode 100644
index 000000000000..55758b9ec877
--- /dev/null
+++ b/fs/smb/client/ntlmssp.h
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002,2007
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#define NTLMSSP_SIGNATURE "NTLMSSP"
+/* Message Types */
+#define NtLmNegotiate cpu_to_le32(1)
+#define NtLmChallenge cpu_to_le32(2)
+#define NtLmAuthenticate cpu_to_le32(3)
+#define UnknownMessage cpu_to_le32(8)
+
+/* Negotiate Flags */
+#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */
+#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
+#define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */
+/* define reserved9 0x08 */
+#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */
+#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
+#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
+#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */
+/* defined reserved 8 0x0100 */
+#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
+#define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */
+#define NTLMSSP_ANONYMOUS 0x0800
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */
+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
+#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */
+#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
+#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
+#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
+#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/
+/* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */
+#define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000
+#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */
+#define NTLMSSP_REQUEST_NON_NT_KEY 0x400000
+#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
+/* #define reserved4 0x1000000 */
+#define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we only set for SMB2+ */
+/* #define reserved3 0x4000000 */
+/* #define reserved2 0x8000000 */
+/* #define reserved1 0x10000000 */
+#define NTLMSSP_NEGOTIATE_128 0x20000000
+#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
+#define NTLMSSP_NEGOTIATE_56 0x80000000
+
+/* Define AV Pair Field IDs */
+enum av_field_type {
+ NTLMSSP_AV_EOL = 0,
+ NTLMSSP_AV_NB_COMPUTER_NAME,
+ NTLMSSP_AV_NB_DOMAIN_NAME,
+ NTLMSSP_AV_DNS_COMPUTER_NAME,
+ NTLMSSP_AV_DNS_DOMAIN_NAME,
+ NTLMSSP_AV_DNS_TREE_NAME,
+ NTLMSSP_AV_FLAGS,
+ NTLMSSP_AV_TIMESTAMP,
+ NTLMSSP_AV_RESTRICTION,
+ NTLMSSP_AV_TARGET_NAME,
+ NTLMSSP_AV_CHANNEL_BINDINGS
+};
+
+/* Although typedefs are not commonly used for structure definitions */
+/* in the Linux kernel, in this particular case they are useful */
+/* to more closely match the standards document for NTLMSSP from */
+/* OpenGroup and to make the code more closely match the standard in */
+/* appearance */
+
+typedef struct _SECURITY_BUFFER {
+ __le16 Length;
+ __le16 MaximumLength;
+ __le32 BufferOffset; /* offset to buffer */
+} __attribute__((packed)) SECURITY_BUFFER;
+
+typedef struct _NEGOTIATE_MESSAGE {
+ __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+ __le32 MessageType; /* NtLmNegotiate = 1 */
+ __le32 NegotiateFlags;
+ SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
+ SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
+ /* SECURITY_BUFFER for version info not present since we
+ do not set the version is present flag */
+ char DomainString[0];
+ /* followed by WorkstationString */
+} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
+
+#define NTLMSSP_REVISION_W2K3 0x0F
+
+/* See MS-NLMP section 2.2.2.10 */
+struct ntlmssp_version {
+ __u8 ProductMajorVersion;
+ __u8 ProductMinorVersion;
+ __le16 ProductBuild; /* we send the cifs.ko module version here */
+ __u8 Reserved[3];
+ __u8 NTLMRevisionCurrent; /* currently 0x0F */
+} __packed;
+
+/* see MS-NLMP section 2.2.1.1 */
+struct negotiate_message {
+ __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+ __le32 MessageType; /* NtLmNegotiate = 1 */
+ __le32 NegotiateFlags;
+ SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
+ SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
+ struct ntlmssp_version Version;
+ /* SECURITY_BUFFER */
+ char DomainString[];
+ /* followed by WorkstationString */
+} __packed;
+
+typedef struct _CHALLENGE_MESSAGE {
+ __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+ __le32 MessageType; /* NtLmChallenge = 2 */
+ SECURITY_BUFFER TargetName;
+ __le32 NegotiateFlags;
+ __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
+ __u8 Reserved[8];
+ SECURITY_BUFFER TargetInfoArray;
+ /* SECURITY_BUFFER for version info not present since we
+ do not set the version is present flag */
+} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
+
+typedef struct _AUTHENTICATE_MESSAGE {
+ __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+ __le32 MessageType; /* NtLmsAuthenticate = 3 */
+ SECURITY_BUFFER LmChallengeResponse;
+ SECURITY_BUFFER NtChallengeResponse;
+ SECURITY_BUFFER DomainName;
+ SECURITY_BUFFER UserName;
+ SECURITY_BUFFER WorkstationName;
+ SECURITY_BUFFER SessionKey;
+ __le32 NegotiateFlags;
+ /* SECURITY_BUFFER for version info not present since we
+ do not set the version is present flag */
+ char UserString[0];
+} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
+
+/*
+ * Size of the session key (crypto key encrypted with the password
+ */
+
+int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses);
+int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, u16 *buflen,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp);
+int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer, u16 *buflen,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp);
+int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp);
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
new file mode 100644
index 000000000000..2d75ba5aaa8a
--- /dev/null
+++ b/fs/smb/client/readdir.c
@@ -0,0 +1,1237 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Directory search handling
+ *
+ * Copyright (C) International Business Machines Corp., 2004, 2008
+ * Copyright (C) Red Hat, Inc., 2011
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifsfs.h"
+#include "smb2proto.h"
+#include "fs_context.h"
+#include "cached_dir.h"
+
+/*
+ * To be safe - for UCS to UTF-8 with strings loaded with the rare long
+ * characters alloc more to account for such multibyte target UTF-8
+ * characters.
+ */
+#define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
+
+#ifdef CONFIG_CIFS_DEBUG2
+static void dump_cifs_file_struct(struct file *file, char *label)
+{
+ struct cifsFileInfo *cf;
+
+ if (file) {
+ cf = file->private_data;
+ if (cf == NULL) {
+ cifs_dbg(FYI, "empty cifs private file data\n");
+ return;
+ }
+ if (cf->invalidHandle)
+ cifs_dbg(FYI, "Invalid handle\n");
+ if (cf->srch_inf.endOfSearch)
+ cifs_dbg(FYI, "end of search\n");
+ if (cf->srch_inf.emptyDir)
+ cifs_dbg(FYI, "empty dir\n");
+ }
+}
+#else
+static inline void dump_cifs_file_struct(struct file *file, char *label)
+{
+}
+#endif /* DEBUG2 */
+
+/*
+ * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT
+ *
+ * Find the dentry that matches "name". If there isn't one, create one. If it's
+ * a negative dentry or the uniqueid or filetype(mode) changed,
+ * then drop it and recreate it.
+ */
+static void
+cifs_prime_dcache(struct dentry *parent, struct qstr *name,
+ struct cifs_fattr *fattr)
+{
+ struct dentry *dentry, *alias;
+ struct inode *inode;
+ struct super_block *sb = parent->d_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+
+ cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
+
+ dentry = d_hash_and_lookup(parent, name);
+ if (!dentry) {
+ /*
+ * If we know that the inode will need to be revalidated
+ * immediately, then don't create a new dentry for it.
+ * We'll end up doing an on the wire call either way and
+ * this spares us an invalidation.
+ */
+ if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
+ return;
+retry:
+ dentry = d_alloc_parallel(parent, name, &wq);
+ }
+ if (IS_ERR(dentry))
+ return;
+ if (!d_in_lookup(dentry)) {
+ inode = d_inode(dentry);
+ if (inode) {
+ if (d_mountpoint(dentry)) {
+ dput(dentry);
+ return;
+ }
+ /*
+ * If we're generating inode numbers, then we don't
+ * want to clobber the existing one with the one that
+ * the readdir code created.
+ */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
+ fattr->cf_uniqueid = CIFS_I(inode)->uniqueid;
+
+ /* update inode in place
+ * if both i_ino and i_mode didn't change */
+ if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid &&
+ cifs_fattr_to_inode(inode, fattr) == 0) {
+ dput(dentry);
+ return;
+ }
+ }
+ d_invalidate(dentry);
+ dput(dentry);
+ goto retry;
+ } else {
+ inode = cifs_iget(sb, fattr);
+ if (!inode)
+ inode = ERR_PTR(-ENOMEM);
+ alias = d_splice_alias(inode, dentry);
+ d_lookup_done(dentry);
+ if (alias && !IS_ERR(alias))
+ dput(alias);
+ }
+ dput(dentry);
+}
+
+static bool reparse_file_needs_reval(const struct cifs_fattr *fattr)
+{
+ if (!(fattr->cf_cifsattrs & ATTR_REPARSE))
+ return false;
+ /*
+ * The DFS tags should be only intepreted by server side as per
+ * MS-FSCC 2.1.2.1, but let's include them anyway.
+ *
+ * Besides, if cf_cifstag is unset (0), then we still need it to be
+ * revalidated to know exactly what reparse point it is.
+ */
+ switch (fattr->cf_cifstag) {
+ case IO_REPARSE_TAG_DFS:
+ case IO_REPARSE_TAG_DFSR:
+ case IO_REPARSE_TAG_SYMLINK:
+ case IO_REPARSE_TAG_NFS:
+ case 0:
+ return true;
+ }
+ return false;
+}
+
+static void
+cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
+{
+ fattr->cf_uid = cifs_sb->ctx->linux_uid;
+ fattr->cf_gid = cifs_sb->ctx->linux_gid;
+
+ /*
+ * The IO_REPARSE_TAG_LX_ tags originally were used by WSL but they
+ * are preferred by the Linux client in some cases since, unlike
+ * the NFS reparse tag (or EAs), they don't require an extra query
+ * to determine which type of special file they represent.
+ * TODO: go through all documented reparse tags to see if we can
+ * reasonably map some of them to directories vs. files vs. symlinks
+ */
+ if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
+ fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;
+ fattr->cf_dtype = DT_DIR;
+ } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_SYMLINK) {
+ fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_LNK;
+ } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_FIFO) {
+ fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_FIFO;
+ } else if (fattr->cf_cifstag == IO_REPARSE_TAG_AF_UNIX) {
+ fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_SOCK;
+ } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_CHR) {
+ fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_CHR;
+ } else if (fattr->cf_cifstag == IO_REPARSE_TAG_LX_BLK) {
+ fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_BLK;
+ } else { /* TODO: should we mark some other reparse points (like DFSR) as directories? */
+ fattr->cf_mode = S_IFREG | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_REG;
+ }
+
+ /*
+ * We need to revalidate it further to make a decision about whether it
+ * is a symbolic link, DFS referral or a reparse point with a direct
+ * access like junctions, deduplicated files, NFS symlinks.
+ */
+ if (reparse_file_needs_reval(fattr))
+ fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
+
+ /* non-unix readdir doesn't provide nlink */
+ fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
+
+ if (fattr->cf_cifsattrs & ATTR_READONLY)
+ fattr->cf_mode &= ~S_IWUGO;
+
+ /*
+ * We of course don't get ACL info in FIND_FIRST/NEXT results, so
+ * mark it for revalidation so that "ls -l" will look right. It might
+ * be super-slow, but if we don't do this then the ownership of files
+ * may look wrong since the inodes may not have timed out by the time
+ * "ls" does a stat() call on them.
+ */
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID))
+ fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
+ fattr->cf_cifsattrs & ATTR_SYSTEM) {
+ if (fattr->cf_eof == 0) {
+ fattr->cf_mode &= ~S_IFMT;
+ fattr->cf_mode |= S_IFIFO;
+ fattr->cf_dtype = DT_FIFO;
+ } else {
+ /*
+ * trying to get the type and mode via SFU can be slow,
+ * so just call those regular files for now, and mark
+ * for reval
+ */
+ fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
+ }
+ }
+}
+
+/* Fill a cifs_fattr struct with info from SMB_FIND_FILE_POSIX_INFO. */
+static void
+cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
+ struct cifs_sb_info *cifs_sb)
+{
+ struct smb2_posix_info_parsed parsed;
+
+ posix_info_parse(info, NULL, &parsed);
+
+ memset(fattr, 0, sizeof(*fattr));
+ fattr->cf_uniqueid = le64_to_cpu(info->Inode);
+ fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
+ fattr->cf_eof = le64_to_cpu(info->EndOfFile);
+
+ fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+ fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
+ fattr->cf_ctime = cifs_NTtimeToUnix(info->CreationTime);
+
+ fattr->cf_nlink = le32_to_cpu(info->HardLinks);
+ fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
+
+ /*
+ * Since we set the inode type below we need to mask off
+ * to avoid strange results if bits set above.
+ * XXX: why not make server&client use the type bits?
+ */
+ fattr->cf_mode = le32_to_cpu(info->Mode) & ~S_IFMT;
+
+ cifs_dbg(FYI, "posix fattr: dev %d, reparse %d, mode %o\n",
+ le32_to_cpu(info->DeviceId),
+ le32_to_cpu(info->ReparseTag),
+ le32_to_cpu(info->Mode));
+
+ if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
+ fattr->cf_mode |= S_IFDIR;
+ fattr->cf_dtype = DT_DIR;
+ } else {
+ /*
+ * mark anything that is not a dir as regular
+ * file. special files should have the REPARSE
+ * attribute and will be marked as needing revaluation
+ */
+ fattr->cf_mode |= S_IFREG;
+ fattr->cf_dtype = DT_REG;
+ }
+
+ if (reparse_file_needs_reval(fattr))
+ fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
+
+ sid_to_id(cifs_sb, &parsed.owner, fattr, SIDOWNER);
+ sid_to_id(cifs_sb, &parsed.group, fattr, SIDGROUP);
+}
+
+static void __dir_info_to_fattr(struct cifs_fattr *fattr, const void *info)
+{
+ const FILE_DIRECTORY_INFO *fi = info;
+
+ memset(fattr, 0, sizeof(*fattr));
+ fattr->cf_cifsattrs = le32_to_cpu(fi->ExtFileAttributes);
+ fattr->cf_eof = le64_to_cpu(fi->EndOfFile);
+ fattr->cf_bytes = le64_to_cpu(fi->AllocationSize);
+ fattr->cf_createtime = le64_to_cpu(fi->CreationTime);
+ fattr->cf_atime = cifs_NTtimeToUnix(fi->LastAccessTime);
+ fattr->cf_ctime = cifs_NTtimeToUnix(fi->ChangeTime);
+ fattr->cf_mtime = cifs_NTtimeToUnix(fi->LastWriteTime);
+}
+
+void
+cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
+ struct cifs_sb_info *cifs_sb)
+{
+ __dir_info_to_fattr(fattr, info);
+ cifs_fill_common_info(fattr, cifs_sb);
+}
+
+static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr,
+ SEARCH_ID_FULL_DIR_INFO *info,
+ struct cifs_sb_info *cifs_sb)
+{
+ __dir_info_to_fattr(fattr, info);
+
+ /* See MS-FSCC 2.4.19 FileIdFullDirectoryInformation */
+ if (fattr->cf_cifsattrs & ATTR_REPARSE)
+ fattr->cf_cifstag = le32_to_cpu(info->EaSize);
+ cifs_fill_common_info(fattr, cifs_sb);
+}
+
+static void
+cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
+ struct cifs_sb_info *cifs_sb)
+{
+ int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj;
+
+ memset(fattr, 0, sizeof(*fattr));
+ fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
+ info->LastAccessTime, offset);
+ fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
+ info->LastWriteTime, offset);
+ fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
+ info->LastWriteTime, offset);
+
+ fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
+ fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
+ fattr->cf_eof = le32_to_cpu(info->DataSize);
+
+ cifs_fill_common_info(fattr, cifs_sb);
+}
+
+/* BB eventually need to add the following helper function to
+ resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
+ we try to do FindFirst on (NTFS) directory symlinks */
+/*
+int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
+ unsigned int xid)
+{
+ __u16 fid;
+ int len;
+ int oplock = 0;
+ int rc;
+ struct cifs_tcon *ptcon = cifs_sb_tcon(cifs_sb);
+ char *tmpbuffer;
+
+ rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
+ OPEN_REPARSE_POINT, &fid, &oplock, NULL,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb);
+ if (!rc) {
+ tmpbuffer = kmalloc(maxpath);
+ rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
+ tmpbuffer,
+ maxpath -1,
+ fid,
+ cifs_sb->local_nls);
+ if (CIFSSMBClose(xid, ptcon, fid)) {
+ cifs_dbg(FYI, "Error closing temporary reparsepoint open\n");
+ }
+ }
+}
+ */
+
+static int
+_initiate_cifs_search(const unsigned int xid, struct file *file,
+ const char *full_path)
+{
+ __u16 search_flags;
+ int rc = 0;
+ struct cifsFileInfo *cifsFile;
+ struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
+ struct tcon_link *tlink = NULL;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+
+ if (file->private_data == NULL) {
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+
+ cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+ if (cifsFile == NULL) {
+ rc = -ENOMEM;
+ goto error_exit;
+ }
+ spin_lock_init(&cifsFile->file_info_lock);
+ file->private_data = cifsFile;
+ cifsFile->tlink = cifs_get_tlink(tlink);
+ tcon = tlink_tcon(tlink);
+ } else {
+ cifsFile = file->private_data;
+ tcon = tlink_tcon(cifsFile->tlink);
+ }
+
+ server = tcon->ses->server;
+
+ if (!server->ops->query_dir_first) {
+ rc = -ENOSYS;
+ goto error_exit;
+ }
+
+ cifsFile->invalidHandle = true;
+ cifsFile->srch_inf.endOfSearch = false;
+
+ cifs_dbg(FYI, "Full path: %s start at: %lld\n", full_path, file->f_pos);
+
+ffirst_retry:
+ /* test for Unix extensions */
+ /* but now check for them on the share/mount not on the SMB session */
+ /* if (cap_unix(tcon->ses) { */
+ if (tcon->unix_ext)
+ cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
+ else if (tcon->posix_extensions)
+ cifsFile->srch_inf.info_level = SMB_FIND_FILE_POSIX_INFO;
+ else if ((tcon->ses->capabilities &
+ tcon->ses->server->vals->cap_nt_find) == 0) {
+ cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
+ } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+ cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
+ } else /* not srvinos - BB fixme add check for backlevel? */ {
+ cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
+ }
+
+ search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
+ if (backup_cred(cifs_sb))
+ search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
+
+ rc = server->ops->query_dir_first(xid, tcon, full_path, cifs_sb,
+ &cifsFile->fid, search_flags,
+ &cifsFile->srch_inf);
+
+ if (rc == 0)
+ cifsFile->invalidHandle = false;
+ /* BB add following call to handle readdir on new NTFS symlink errors
+ else if STATUS_STOPPED_ON_SYMLINK
+ call get_symlink_reparse_path and retry with new path */
+ else if ((rc == -EOPNOTSUPP) &&
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
+ goto ffirst_retry;
+ }
+error_exit:
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+static int
+initiate_cifs_search(const unsigned int xid, struct file *file,
+ const char *full_path)
+{
+ int rc, retry_count = 0;
+
+ do {
+ rc = _initiate_cifs_search(xid, file, full_path);
+ /*
+ * If we don't have enough credits to start reading the
+ * directory just try again after short wait.
+ */
+ if (rc != -EDEADLK)
+ break;
+
+ usleep_range(512, 2048);
+ } while (retry_count++ < 5);
+
+ return rc;
+}
+
+/* return length of unicode string in bytes */
+static int cifs_unicode_bytelen(const char *str)
+{
+ int len;
+ const __le16 *ustr = (const __le16 *)str;
+
+ for (len = 0; len <= PATH_MAX; len++) {
+ if (ustr[len] == 0)
+ return len << 1;
+ }
+ cifs_dbg(FYI, "Unicode string longer than PATH_MAX found\n");
+ return len << 1;
+}
+
+static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
+{
+ char *new_entry;
+ FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
+
+ if (level == SMB_FIND_FILE_INFO_STANDARD) {
+ FIND_FILE_STANDARD_INFO *pfData;
+ pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
+
+ new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
+ pfData->FileNameLength;
+ } else {
+ u32 next_offset = le32_to_cpu(pDirInfo->NextEntryOffset);
+
+ if (old_entry + next_offset < old_entry) {
+ cifs_dbg(VFS, "Invalid offset %u\n", next_offset);
+ return NULL;
+ }
+ new_entry = old_entry + next_offset;
+ }
+ cifs_dbg(FYI, "new entry %p old entry %p\n", new_entry, old_entry);
+ /* validate that new_entry is not past end of SMB */
+ if (new_entry >= end_of_smb) {
+ cifs_dbg(VFS, "search entry %p began after end of SMB %p old entry %p\n",
+ new_entry, end_of_smb, old_entry);
+ return NULL;
+ } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
+ (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
+ || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
+ (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
+ cifs_dbg(VFS, "search entry %p extends after end of SMB %p\n",
+ new_entry, end_of_smb);
+ return NULL;
+ } else
+ return new_entry;
+
+}
+
+struct cifs_dirent {
+ const char *name;
+ size_t namelen;
+ u32 resume_key;
+ u64 ino;
+};
+
+static void cifs_fill_dirent_posix(struct cifs_dirent *de,
+ const struct smb2_posix_info *info)
+{
+ struct smb2_posix_info_parsed parsed;
+
+ /* payload should have already been checked at this point */
+ if (posix_info_parse(info, NULL, &parsed) < 0) {
+ cifs_dbg(VFS, "Invalid POSIX info payload\n");
+ return;
+ }
+
+ de->name = parsed.name;
+ de->namelen = parsed.name_len;
+ de->resume_key = info->Ignored;
+ de->ino = le64_to_cpu(info->Inode);
+}
+
+static void cifs_fill_dirent_unix(struct cifs_dirent *de,
+ const FILE_UNIX_INFO *info, bool is_unicode)
+{
+ de->name = &info->FileName[0];
+ if (is_unicode)
+ de->namelen = cifs_unicode_bytelen(de->name);
+ else
+ de->namelen = strnlen(de->name, PATH_MAX);
+ de->resume_key = info->ResumeKey;
+ de->ino = le64_to_cpu(info->basic.UniqueId);
+}
+
+static void cifs_fill_dirent_dir(struct cifs_dirent *de,
+ const FILE_DIRECTORY_INFO *info)
+{
+ de->name = &info->FileName[0];
+ de->namelen = le32_to_cpu(info->FileNameLength);
+ de->resume_key = info->FileIndex;
+}
+
+static void cifs_fill_dirent_full(struct cifs_dirent *de,
+ const FILE_FULL_DIRECTORY_INFO *info)
+{
+ de->name = &info->FileName[0];
+ de->namelen = le32_to_cpu(info->FileNameLength);
+ de->resume_key = info->FileIndex;
+}
+
+static void cifs_fill_dirent_search(struct cifs_dirent *de,
+ const SEARCH_ID_FULL_DIR_INFO *info)
+{
+ de->name = &info->FileName[0];
+ de->namelen = le32_to_cpu(info->FileNameLength);
+ de->resume_key = info->FileIndex;
+ de->ino = le64_to_cpu(info->UniqueId);
+}
+
+static void cifs_fill_dirent_both(struct cifs_dirent *de,
+ const FILE_BOTH_DIRECTORY_INFO *info)
+{
+ de->name = &info->FileName[0];
+ de->namelen = le32_to_cpu(info->FileNameLength);
+ de->resume_key = info->FileIndex;
+}
+
+static void cifs_fill_dirent_std(struct cifs_dirent *de,
+ const FIND_FILE_STANDARD_INFO *info)
+{
+ de->name = &info->FileName[0];
+ /* one byte length, no endianess conversion */
+ de->namelen = info->FileNameLength;
+ de->resume_key = info->ResumeKey;
+}
+
+static int cifs_fill_dirent(struct cifs_dirent *de, const void *info,
+ u16 level, bool is_unicode)
+{
+ memset(de, 0, sizeof(*de));
+
+ switch (level) {
+ case SMB_FIND_FILE_POSIX_INFO:
+ cifs_fill_dirent_posix(de, info);
+ break;
+ case SMB_FIND_FILE_UNIX:
+ cifs_fill_dirent_unix(de, info, is_unicode);
+ break;
+ case SMB_FIND_FILE_DIRECTORY_INFO:
+ cifs_fill_dirent_dir(de, info);
+ break;
+ case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+ cifs_fill_dirent_full(de, info);
+ break;
+ case SMB_FIND_FILE_ID_FULL_DIR_INFO:
+ cifs_fill_dirent_search(de, info);
+ break;
+ case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+ cifs_fill_dirent_both(de, info);
+ break;
+ case SMB_FIND_FILE_INFO_STANDARD:
+ cifs_fill_dirent_std(de, info);
+ break;
+ default:
+ cifs_dbg(FYI, "Unknown findfirst level %d\n", level);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define UNICODE_DOT cpu_to_le16(0x2e)
+
+/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
+static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode)
+{
+ int rc = 0;
+
+ if (!de->name)
+ return 0;
+
+ if (is_unicode) {
+ __le16 *ufilename = (__le16 *)de->name;
+ if (de->namelen == 2) {
+ /* check for . */
+ if (ufilename[0] == UNICODE_DOT)
+ rc = 1;
+ } else if (de->namelen == 4) {
+ /* check for .. */
+ if (ufilename[0] == UNICODE_DOT &&
+ ufilename[1] == UNICODE_DOT)
+ rc = 2;
+ }
+ } else /* ASCII */ {
+ if (de->namelen == 1) {
+ if (de->name[0] == '.')
+ rc = 1;
+ } else if (de->namelen == 2) {
+ if (de->name[0] == '.' && de->name[1] == '.')
+ rc = 2;
+ }
+ }
+
+ return rc;
+}
+
+/* Check if directory that we are searching has changed so we can decide
+ whether we can use the cached search results from the previous search */
+static int is_dir_changed(struct file *file)
+{
+ struct inode *inode = file_inode(file);
+ struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
+
+ if (cifsInfo->time == 0)
+ return 1; /* directory was changed, perhaps due to unlink */
+ else
+ return 0;
+
+}
+
+static int cifs_save_resume_key(const char *current_entry,
+ struct cifsFileInfo *file_info)
+{
+ struct cifs_dirent de;
+ int rc;
+
+ rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level,
+ file_info->srch_inf.unicode);
+ if (!rc) {
+ file_info->srch_inf.presume_name = de.name;
+ file_info->srch_inf.resume_name_len = de.namelen;
+ file_info->srch_inf.resume_key = de.resume_key;
+ }
+ return rc;
+}
+
+/*
+ * Find the corresponding entry in the search. Note that the SMB server returns
+ * search entries for . and .. which complicates logic here if we choose to
+ * parse for them and we do not assume that they are located in the findfirst
+ * return buffer. We start counting in the buffer with entry 2 and increment for
+ * every entry (do not increment for . or .. entry).
+ */
+static int
+find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
+ struct file *file, const char *full_path,
+ char **current_entry, int *num_to_ret)
+{
+ __u16 search_flags;
+ int rc = 0;
+ int pos_in_buf = 0;
+ loff_t first_entry_in_buffer;
+ loff_t index_to_find = pos;
+ struct cifsFileInfo *cfile = file->private_data;
+ struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ /* check if index in the buffer */
+
+ if (!server->ops->query_dir_first || !server->ops->query_dir_next)
+ return -ENOSYS;
+
+ if ((cfile == NULL) || (current_entry == NULL) || (num_to_ret == NULL))
+ return -ENOENT;
+
+ *current_entry = NULL;
+ first_entry_in_buffer = cfile->srch_inf.index_of_last_entry -
+ cfile->srch_inf.entries_in_buffer;
+
+ /*
+ * If first entry in buf is zero then is first buffer
+ * in search response data which means it is likely . and ..
+ * will be in this buffer, although some servers do not return
+ * . and .. for the root of a drive and for those we need
+ * to start two entries earlier.
+ */
+
+ dump_cifs_file_struct(file, "In fce ");
+ if (((index_to_find < cfile->srch_inf.index_of_last_entry) &&
+ is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
+ /* close and restart search */
+ cifs_dbg(FYI, "search backing up - close and restart search\n");
+ spin_lock(&cfile->file_info_lock);
+ if (server->ops->dir_needs_close(cfile)) {
+ cfile->invalidHandle = true;
+ spin_unlock(&cfile->file_info_lock);
+ if (server->ops->close_dir)
+ server->ops->close_dir(xid, tcon, &cfile->fid);
+ } else
+ spin_unlock(&cfile->file_info_lock);
+ if (cfile->srch_inf.ntwrk_buf_start) {
+ cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n");
+ if (cfile->srch_inf.smallBuf)
+ cifs_small_buf_release(cfile->srch_inf.
+ ntwrk_buf_start);
+ else
+ cifs_buf_release(cfile->srch_inf.
+ ntwrk_buf_start);
+ cfile->srch_inf.ntwrk_buf_start = NULL;
+ }
+ rc = initiate_cifs_search(xid, file, full_path);
+ if (rc) {
+ cifs_dbg(FYI, "error %d reinitiating a search on rewind\n",
+ rc);
+ return rc;
+ }
+ /* FindFirst/Next set last_entry to NULL on malformed reply */
+ if (cfile->srch_inf.last_entry)
+ cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
+ }
+
+ search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
+ if (backup_cred(cifs_sb))
+ search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
+
+ while ((index_to_find >= cfile->srch_inf.index_of_last_entry) &&
+ (rc == 0) && !cfile->srch_inf.endOfSearch) {
+ cifs_dbg(FYI, "calling findnext2\n");
+ rc = server->ops->query_dir_next(xid, tcon, &cfile->fid,
+ search_flags,
+ &cfile->srch_inf);
+ /* FindFirst/Next set last_entry to NULL on malformed reply */
+ if (cfile->srch_inf.last_entry)
+ cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
+ if (rc)
+ return -ENOENT;
+ }
+ if (index_to_find < cfile->srch_inf.index_of_last_entry) {
+ /* we found the buffer that contains the entry */
+ /* scan and find it */
+ int i;
+ char *cur_ent;
+ char *end_of_smb;
+
+ if (cfile->srch_inf.ntwrk_buf_start == NULL) {
+ cifs_dbg(VFS, "ntwrk_buf_start is NULL during readdir\n");
+ return -EIO;
+ }
+
+ end_of_smb = cfile->srch_inf.ntwrk_buf_start +
+ server->ops->calc_smb_size(
+ cfile->srch_inf.ntwrk_buf_start);
+
+ cur_ent = cfile->srch_inf.srch_entries_start;
+ first_entry_in_buffer = cfile->srch_inf.index_of_last_entry
+ - cfile->srch_inf.entries_in_buffer;
+ pos_in_buf = index_to_find - first_entry_in_buffer;
+ cifs_dbg(FYI, "found entry - pos_in_buf %d\n", pos_in_buf);
+
+ for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) {
+ /* go entry by entry figuring out which is first */
+ cur_ent = nxt_dir_entry(cur_ent, end_of_smb,
+ cfile->srch_inf.info_level);
+ }
+ if ((cur_ent == NULL) && (i < pos_in_buf)) {
+ /* BB fixme - check if we should flag this error */
+ cifs_dbg(VFS, "reached end of buf searching for pos in buf %d index to find %lld rc %d\n",
+ pos_in_buf, index_to_find, rc);
+ }
+ rc = 0;
+ *current_entry = cur_ent;
+ } else {
+ cifs_dbg(FYI, "index not in buffer - could not findnext into it\n");
+ return 0;
+ }
+
+ if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) {
+ cifs_dbg(FYI, "can not return entries pos_in_buf beyond last\n");
+ *num_to_ret = 0;
+ } else
+ *num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf;
+
+ return rc;
+}
+
+static bool emit_cached_dirents(struct cached_dirents *cde,
+ struct dir_context *ctx)
+{
+ struct cached_dirent *dirent;
+ bool rc;
+
+ list_for_each_entry(dirent, &cde->entries, entry) {
+ /*
+ * Skip all early entries prior to the current lseek()
+ * position.
+ */
+ if (ctx->pos > dirent->pos)
+ continue;
+ /*
+ * We recorded the current ->pos value for the dirent
+ * when we stored it in the cache.
+ * However, this sequence of ->pos values may have holes
+ * in it, for example dot-dirs returned from the server
+ * are suppressed.
+ * Handle this bu forcing ctx->pos to be the same as the
+ * ->pos of the current dirent we emit from the cache.
+ * This means that when we emit these entries from the cache
+ * we now emit them with the same ->pos value as in the
+ * initial scan.
+ */
+ ctx->pos = dirent->pos;
+ rc = dir_emit(ctx, dirent->name, dirent->namelen,
+ dirent->fattr.cf_uniqueid,
+ dirent->fattr.cf_dtype);
+ if (!rc)
+ return rc;
+ ctx->pos++;
+ }
+ return true;
+}
+
+static void update_cached_dirents_count(struct cached_dirents *cde,
+ struct dir_context *ctx)
+{
+ if (cde->ctx != ctx)
+ return;
+ if (cde->is_valid || cde->is_failed)
+ return;
+
+ cde->pos++;
+}
+
+static void finished_cached_dirents_count(struct cached_dirents *cde,
+ struct dir_context *ctx)
+{
+ if (cde->ctx != ctx)
+ return;
+ if (cde->is_valid || cde->is_failed)
+ return;
+ if (ctx->pos != cde->pos)
+ return;
+
+ cde->is_valid = 1;
+}
+
+static void add_cached_dirent(struct cached_dirents *cde,
+ struct dir_context *ctx,
+ const char *name, int namelen,
+ struct cifs_fattr *fattr)
+{
+ struct cached_dirent *de;
+
+ if (cde->ctx != ctx)
+ return;
+ if (cde->is_valid || cde->is_failed)
+ return;
+ if (ctx->pos != cde->pos) {
+ cde->is_failed = 1;
+ return;
+ }
+ de = kzalloc(sizeof(*de), GFP_ATOMIC);
+ if (de == NULL) {
+ cde->is_failed = 1;
+ return;
+ }
+ de->namelen = namelen;
+ de->name = kstrndup(name, namelen, GFP_ATOMIC);
+ if (de->name == NULL) {
+ kfree(de);
+ cde->is_failed = 1;
+ return;
+ }
+ de->pos = ctx->pos;
+
+ memcpy(&de->fattr, fattr, sizeof(struct cifs_fattr));
+
+ list_add_tail(&de->entry, &cde->entries);
+}
+
+static bool cifs_dir_emit(struct dir_context *ctx,
+ const char *name, int namelen,
+ struct cifs_fattr *fattr,
+ struct cached_fid *cfid)
+{
+ bool rc;
+ ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
+
+ rc = dir_emit(ctx, name, namelen, ino, fattr->cf_dtype);
+ if (!rc)
+ return rc;
+
+ if (cfid) {
+ mutex_lock(&cfid->dirents.de_mutex);
+ add_cached_dirent(&cfid->dirents, ctx, name, namelen,
+ fattr);
+ mutex_unlock(&cfid->dirents.de_mutex);
+ }
+
+ return rc;
+}
+
+static int cifs_filldir(char *find_entry, struct file *file,
+ struct dir_context *ctx,
+ char *scratch_buf, unsigned int max_len,
+ struct cached_fid *cfid)
+{
+ struct cifsFileInfo *file_info = file->private_data;
+ struct super_block *sb = file_inode(file)->i_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_dirent de = { NULL, };
+ struct cifs_fattr fattr;
+ struct qstr name;
+ int rc = 0;
+
+ rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
+ file_info->srch_inf.unicode);
+ if (rc)
+ return rc;
+
+ if (de.namelen > max_len) {
+ cifs_dbg(VFS, "bad search response length %zd past smb end\n",
+ de.namelen);
+ return -EINVAL;
+ }
+
+ /* skip . and .. since we added them first */
+ if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
+ return 0;
+
+ if (file_info->srch_inf.unicode) {
+ struct nls_table *nlt = cifs_sb->local_nls;
+ int map_type;
+
+ map_type = cifs_remap(cifs_sb);
+ name.name = scratch_buf;
+ name.len =
+ cifs_from_utf16((char *)name.name, (__le16 *)de.name,
+ UNICODE_NAME_MAX,
+ min_t(size_t, de.namelen,
+ (size_t)max_len), nlt, map_type);
+ name.len -= nls_nullsize(nlt);
+ } else {
+ name.name = de.name;
+ name.len = de.namelen;
+ }
+
+ switch (file_info->srch_inf.info_level) {
+ case SMB_FIND_FILE_POSIX_INFO:
+ cifs_posix_to_fattr(&fattr,
+ (struct smb2_posix_info *)find_entry,
+ cifs_sb);
+ break;
+ case SMB_FIND_FILE_UNIX:
+ cifs_unix_basic_to_fattr(&fattr,
+ &((FILE_UNIX_INFO *)find_entry)->basic,
+ cifs_sb);
+ if (S_ISLNK(fattr.cf_mode))
+ fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
+ break;
+ case SMB_FIND_FILE_INFO_STANDARD:
+ cifs_std_info_to_fattr(&fattr,
+ (FIND_FILE_STANDARD_INFO *)find_entry,
+ cifs_sb);
+ break;
+ case SMB_FIND_FILE_ID_FULL_DIR_INFO:
+ cifs_fulldir_info_to_fattr(&fattr,
+ (SEARCH_ID_FULL_DIR_INFO *)find_entry,
+ cifs_sb);
+ break;
+ default:
+ cifs_dir_info_to_fattr(&fattr,
+ (FILE_DIRECTORY_INFO *)find_entry,
+ cifs_sb);
+ break;
+ }
+
+ if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
+ fattr.cf_uniqueid = de.ino;
+ } else {
+ fattr.cf_uniqueid = iunique(sb, ROOT_I);
+ cifs_autodisable_serverino(cifs_sb);
+ }
+
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
+ couldbe_mf_symlink(&fattr))
+ /*
+ * trying to get the type and mode can be slow,
+ * so just call those regular files for now, and mark
+ * for reval
+ */
+ fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
+
+ cifs_prime_dcache(file_dentry(file), &name, &fattr);
+
+ return !cifs_dir_emit(ctx, name.name, name.len,
+ &fattr, cfid);
+}
+
+
+int cifs_readdir(struct file *file, struct dir_context *ctx)
+{
+ int rc = 0;
+ unsigned int xid;
+ int i;
+ struct tcon_link *tlink = NULL;
+ struct cifs_tcon *tcon;
+ struct cifsFileInfo *cifsFile;
+ char *current_entry;
+ int num_to_fill = 0;
+ char *tmp_buf = NULL;
+ char *end_of_smb;
+ unsigned int max_len;
+ const char *full_path;
+ void *page = alloc_dentry_path();
+ struct cached_fid *cfid = NULL;
+ struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
+
+ xid = get_xid();
+
+ full_path = build_path_from_dentry(file_dentry(file), page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto rddir2_exit;
+ }
+
+ if (file->private_data == NULL) {
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ goto cache_not_found;
+ tcon = tlink_tcon(tlink);
+ } else {
+ cifsFile = file->private_data;
+ tcon = tlink_tcon(cifsFile->tlink);
+ }
+
+ rc = open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid);
+ cifs_put_tlink(tlink);
+ if (rc)
+ goto cache_not_found;
+
+ mutex_lock(&cfid->dirents.de_mutex);
+ /*
+ * If this was reading from the start of the directory
+ * we need to initialize scanning and storing the
+ * directory content.
+ */
+ if (ctx->pos == 0 && cfid->dirents.ctx == NULL) {
+ cfid->dirents.ctx = ctx;
+ cfid->dirents.pos = 2;
+ }
+ /*
+ * If we already have the entire directory cached then
+ * we can just serve the cache.
+ */
+ if (cfid->dirents.is_valid) {
+ if (!dir_emit_dots(file, ctx)) {
+ mutex_unlock(&cfid->dirents.de_mutex);
+ goto rddir2_exit;
+ }
+ emit_cached_dirents(&cfid->dirents, ctx);
+ mutex_unlock(&cfid->dirents.de_mutex);
+ goto rddir2_exit;
+ }
+ mutex_unlock(&cfid->dirents.de_mutex);
+
+ /* Drop the cache while calling initiate_cifs_search and
+ * find_cifs_entry in case there will be reconnects during
+ * query_directory.
+ */
+ close_cached_dir(cfid);
+ cfid = NULL;
+
+ cache_not_found:
+ /*
+ * Ensure FindFirst doesn't fail before doing filldir() for '.' and
+ * '..'. Otherwise we won't be able to notify VFS in case of failure.
+ */
+ if (file->private_data == NULL) {
+ rc = initiate_cifs_search(xid, file, full_path);
+ cifs_dbg(FYI, "initiate cifs search rc %d\n", rc);
+ if (rc)
+ goto rddir2_exit;
+ }
+
+ if (!dir_emit_dots(file, ctx))
+ goto rddir2_exit;
+
+ /* 1) If search is active,
+ is in current search buffer?
+ if it before then restart search
+ if after then keep searching till find it */
+ cifsFile = file->private_data;
+ if (cifsFile->srch_inf.endOfSearch) {
+ if (cifsFile->srch_inf.emptyDir) {
+ cifs_dbg(FYI, "End of search, empty dir\n");
+ rc = 0;
+ goto rddir2_exit;
+ }
+ } /* else {
+ cifsFile->invalidHandle = true;
+ tcon->ses->server->close(xid, tcon, &cifsFile->fid);
+ } */
+
+ tcon = tlink_tcon(cifsFile->tlink);
+ rc = find_cifs_entry(xid, tcon, ctx->pos, file, full_path,
+ ¤t_entry, &num_to_fill);
+ open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid);
+ if (rc) {
+ cifs_dbg(FYI, "fce error %d\n", rc);
+ goto rddir2_exit;
+ } else if (current_entry != NULL) {
+ cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
+ } else {
+ if (cfid) {
+ mutex_lock(&cfid->dirents.de_mutex);
+ finished_cached_dirents_count(&cfid->dirents, ctx);
+ mutex_unlock(&cfid->dirents.de_mutex);
+ }
+ cifs_dbg(FYI, "Could not find entry\n");
+ goto rddir2_exit;
+ }
+ cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
+ num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
+ max_len = tcon->ses->server->ops->calc_smb_size(
+ cifsFile->srch_inf.ntwrk_buf_start);
+ end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
+
+ tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
+ if (tmp_buf == NULL) {
+ rc = -ENOMEM;
+ goto rddir2_exit;
+ }
+
+ for (i = 0; i < num_to_fill; i++) {
+ if (current_entry == NULL) {
+ /* evaluate whether this case is an error */
+ cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
+ num_to_fill, i);
+ break;
+ }
+ /*
+ * if buggy server returns . and .. late do we want to
+ * check for that here?
+ */
+ *tmp_buf = 0;
+ rc = cifs_filldir(current_entry, file, ctx,
+ tmp_buf, max_len, cfid);
+ if (rc) {
+ if (rc > 0)
+ rc = 0;
+ break;
+ }
+
+ ctx->pos++;
+ if (cfid) {
+ mutex_lock(&cfid->dirents.de_mutex);
+ update_cached_dirents_count(&cfid->dirents, ctx);
+ mutex_unlock(&cfid->dirents.de_mutex);
+ }
+
+ if (ctx->pos ==
+ cifsFile->srch_inf.index_of_last_entry) {
+ cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
+ ctx->pos, tmp_buf);
+ cifs_save_resume_key(current_entry, cifsFile);
+ break;
+ }
+ current_entry =
+ nxt_dir_entry(current_entry, end_of_smb,
+ cifsFile->srch_inf.info_level);
+ }
+ kfree(tmp_buf);
+
+rddir2_exit:
+ if (cfid)
+ close_cached_dir(cfid);
+ free_dentry_path(page);
+ free_xid(xid);
+ return rc;
+}
diff --git a/fs/smb/client/rfc1002pdu.h b/fs/smb/client/rfc1002pdu.h
new file mode 100644
index 000000000000..ae1d025da294
--- /dev/null
+++ b/fs/smb/client/rfc1002pdu.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Protocol Data Unit definitions for RFC 1001/1002 support
+ *
+ * Copyright (c) International Business Machines Corp., 2004
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
+
+ /* RFC 1002 session packet types */
+#define RFC1002_SESSION_MESSAGE 0x00
+#define RFC1002_SESSION_REQUEST 0x81
+#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
+#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
+#define RFC1002_RETARGET_SESSION_RESPONSE 0x84
+#define RFC1002_SESSION_KEEP_ALIVE 0x85
+
+ /* RFC 1002 flags (only one defined */
+#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
+
+struct rfc1002_session_packet {
+ __u8 type;
+ __u8 flags;
+ __u16 length;
+ union {
+ struct {
+ __u8 called_len;
+ __u8 called_name[32];
+ __u8 scope1; /* null */
+ __u8 calling_len;
+ __u8 calling_name[32];
+ __u8 scope2; /* null */
+ } __attribute__((packed)) session_req;
+ struct {
+ __u32 retarget_ip_addr;
+ __u16 port;
+ } __attribute__((packed)) retarget_resp;
+ __u8 neg_ses_resp_error_code;
+ /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
+ SESSION_KEEP_ALIVE packet also does not include a trailer.
+ Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
+ } __attribute__((packed)) trailer;
+} __attribute__((packed));
+
+/* Negative Session Response error codes */
+#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
+#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
+#define RFC1002_NOT_PRESENT 0x82 /* called name not present */
+#define RFC1002_INSUFFICIENT_RESOURCE 0x83
+#define RFC1002_UNSPECIFIED_ERROR 0x8F
+
+/* RFC 1002 Datagram service packets are not defined here as they
+are not needed for the network filesystem client unless we plan on
+implementing broadcast resolution of the server ip address (from
+server netbios name). Currently server names are resolved only via DNS
+(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
+
+#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c
new file mode 100644
index 000000000000..81be17845072
--- /dev/null
+++ b/fs/smb/client/sess.c
@@ -0,0 +1,1858 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * SMB/CIFS session setup handling routines
+ *
+ * Copyright (c) International Business Machines Corp., 2006, 2009
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "ntlmssp.h"
+#include "nterr.h"
+#include <linux/utsname.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include "cifsfs.h"
+#include "cifs_spnego.h"
+#include "smb2proto.h"
+#include "fs_context.h"
+
+static int
+cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
+ struct cifs_server_iface *iface);
+
+bool
+is_server_using_iface(struct TCP_Server_Info *server,
+ struct cifs_server_iface *iface)
+{
+ struct sockaddr_in *i4 = (struct sockaddr_in *)&iface->sockaddr;
+ struct sockaddr_in6 *i6 = (struct sockaddr_in6 *)&iface->sockaddr;
+ struct sockaddr_in *s4 = (struct sockaddr_in *)&server->dstaddr;
+ struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&server->dstaddr;
+
+ if (server->dstaddr.ss_family != iface->sockaddr.ss_family)
+ return false;
+ if (server->dstaddr.ss_family == AF_INET) {
+ if (s4->sin_addr.s_addr != i4->sin_addr.s_addr)
+ return false;
+ } else if (server->dstaddr.ss_family == AF_INET6) {
+ if (memcmp(&s6->sin6_addr, &i6->sin6_addr,
+ sizeof(i6->sin6_addr)) != 0)
+ return false;
+ } else {
+ /* unknown family.. */
+ return false;
+ }
+ return true;
+}
+
+bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
+{
+ int i;
+
+ spin_lock(&ses->chan_lock);
+ for (i = 0; i < ses->chan_count; i++) {
+ if (ses->chans[i].iface == iface) {
+ spin_unlock(&ses->chan_lock);
+ return true;
+ }
+ }
+ spin_unlock(&ses->chan_lock);
+ return false;
+}
+
+/* channel helper functions. assumed that chan_lock is held by caller. */
+
+unsigned int
+cifs_ses_get_chan_index(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ unsigned int i;
+
+ for (i = 0; i < ses->chan_count; i++) {
+ if (ses->chans[i].server == server)
+ return i;
+ }
+
+ /* If we didn't find the channel, it is likely a bug */
+ if (server)
+ cifs_dbg(VFS, "unable to get chan index for server: 0x%llx",
+ server->conn_id);
+ WARN_ON(1);
+ return 0;
+}
+
+void
+cifs_chan_set_in_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
+
+ ses->chans[chan_index].in_reconnect = true;
+}
+
+void
+cifs_chan_clear_in_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
+
+ ses->chans[chan_index].in_reconnect = false;
+}
+
+bool
+cifs_chan_in_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
+
+ return CIFS_CHAN_IN_RECONNECT(ses, chan_index);
+}
+
+void
+cifs_chan_set_need_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
+
+ set_bit(chan_index, &ses->chans_need_reconnect);
+ cifs_dbg(FYI, "Set reconnect bitmask for chan %u; now 0x%lx\n",
+ chan_index, ses->chans_need_reconnect);
+}
+
+void
+cifs_chan_clear_need_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
+
+ clear_bit(chan_index, &ses->chans_need_reconnect);
+ cifs_dbg(FYI, "Cleared reconnect bitmask for chan %u; now 0x%lx\n",
+ chan_index, ses->chans_need_reconnect);
+}
+
+bool
+cifs_chan_needs_reconnect(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
+
+ return CIFS_CHAN_NEEDS_RECONNECT(ses, chan_index);
+}
+
+bool
+cifs_chan_is_iface_active(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
+
+ return ses->chans[chan_index].iface &&
+ ses->chans[chan_index].iface->is_active;
+}
+
+/* returns number of channels added */
+int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
+{
+ struct TCP_Server_Info *server = ses->server;
+ int old_chan_count, new_chan_count;
+ int left;
+ int rc = 0;
+ int tries = 0;
+ struct cifs_server_iface *iface = NULL, *niface = NULL;
+
+ spin_lock(&ses->chan_lock);
+
+ new_chan_count = old_chan_count = ses->chan_count;
+ left = ses->chan_max - ses->chan_count;
+
+ if (left <= 0) {
+ spin_unlock(&ses->chan_lock);
+ cifs_dbg(FYI,
+ "ses already at max_channels (%zu), nothing to open\n",
+ ses->chan_max);
+ return 0;
+ }
+
+ if (server->dialect < SMB30_PROT_ID) {
+ spin_unlock(&ses->chan_lock);
+ cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
+ return 0;
+ }
+
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
+ ses->chan_max = 1;
+ spin_unlock(&ses->chan_lock);
+ cifs_server_dbg(VFS, "no multichannel support\n");
+ return 0;
+ }
+ spin_unlock(&ses->chan_lock);
+
+ /*
+ * Keep connecting to same, fastest, iface for all channels as
+ * long as its RSS. Try next fastest one if not RSS or channel
+ * creation fails.
+ */
+ spin_lock(&ses->iface_lock);
+ iface = list_first_entry(&ses->iface_list, struct cifs_server_iface,
+ iface_head);
+ spin_unlock(&ses->iface_lock);
+
+ while (left > 0) {
+
+ tries++;
+ if (tries > 3*ses->chan_max) {
+ cifs_dbg(FYI, "too many channel open attempts (%d channels left to open)\n",
+ left);
+ break;
+ }
+
+ spin_lock(&ses->iface_lock);
+ if (!ses->iface_count) {
+ spin_unlock(&ses->iface_lock);
+ break;
+ }
+
+ list_for_each_entry_safe_from(iface, niface, &ses->iface_list,
+ iface_head) {
+ /* skip ifaces that are unusable */
+ if (!iface->is_active ||
+ (is_ses_using_iface(ses, iface) &&
+ !iface->rss_capable)) {
+ continue;
+ }
+
+ /* take ref before unlock */
+ kref_get(&iface->refcount);
+
+ spin_unlock(&ses->iface_lock);
+ rc = cifs_ses_add_channel(cifs_sb, ses, iface);
+ spin_lock(&ses->iface_lock);
+
+ if (rc) {
+ cifs_dbg(VFS, "failed to open extra channel on iface:%pIS rc=%d\n",
+ &iface->sockaddr,
+ rc);
+ kref_put(&iface->refcount, release_iface);
+ continue;
+ }
+
+ cifs_dbg(FYI, "successfully opened new channel on iface:%pIS\n",
+ &iface->sockaddr);
+ break;
+ }
+ spin_unlock(&ses->iface_lock);
+
+ left--;
+ new_chan_count++;
+ }
+
+ return new_chan_count - old_chan_count;
+}
+
+/*
+ * update the iface for the channel if necessary.
+ * will return 0 when iface is updated, 1 if removed, 2 otherwise
+ * Must be called with chan_lock held.
+ */
+int
+cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
+{
+ unsigned int chan_index;
+ struct cifs_server_iface *iface = NULL;
+ struct cifs_server_iface *old_iface = NULL;
+ int rc = 0;
+
+ spin_lock(&ses->chan_lock);
+ chan_index = cifs_ses_get_chan_index(ses, server);
+ if (!chan_index) {
+ spin_unlock(&ses->chan_lock);
+ return 0;
+ }
+
+ if (ses->chans[chan_index].iface) {
+ old_iface = ses->chans[chan_index].iface;
+ if (old_iface->is_active) {
+ spin_unlock(&ses->chan_lock);
+ return 1;
+ }
+ }
+ spin_unlock(&ses->chan_lock);
+
+ spin_lock(&ses->iface_lock);
+ /* then look for a new one */
+ list_for_each_entry(iface, &ses->iface_list, iface_head) {
+ if (!iface->is_active ||
+ (is_ses_using_iface(ses, iface) &&
+ !iface->rss_capable)) {
+ continue;
+ }
+ kref_get(&iface->refcount);
+ break;
+ }
+
+ if (list_entry_is_head(iface, &ses->iface_list, iface_head)) {
+ rc = 1;
+ iface = NULL;
+ cifs_dbg(FYI, "unable to find a suitable iface\n");
+ }
+
+ /* now drop the ref to the current iface */
+ if (old_iface && iface) {
+ cifs_dbg(FYI, "replacing iface: %pIS with %pIS\n",
+ &old_iface->sockaddr,
+ &iface->sockaddr);
+ kref_put(&old_iface->refcount, release_iface);
+ } else if (old_iface) {
+ cifs_dbg(FYI, "releasing ref to iface: %pIS\n",
+ &old_iface->sockaddr);
+ kref_put(&old_iface->refcount, release_iface);
+ } else {
+ WARN_ON(!iface);
+ cifs_dbg(FYI, "adding new iface: %pIS\n", &iface->sockaddr);
+ }
+ spin_unlock(&ses->iface_lock);
+
+ spin_lock(&ses->chan_lock);
+ chan_index = cifs_ses_get_chan_index(ses, server);
+ ses->chans[chan_index].iface = iface;
+
+ /* No iface is found. if secondary chan, drop connection */
+ if (!iface && CIFS_SERVER_IS_CHAN(server))
+ ses->chans[chan_index].server = NULL;
+
+ spin_unlock(&ses->chan_lock);
+
+ if (!iface && CIFS_SERVER_IS_CHAN(server))
+ cifs_put_tcp_session(server, false);
+
+ return rc;
+}
+
+/*
+ * If server is a channel of ses, return the corresponding enclosing
+ * cifs_chan otherwise return NULL.
+ */
+struct cifs_chan *
+cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server)
+{
+ int i;
+
+ spin_lock(&ses->chan_lock);
+ for (i = 0; i < ses->chan_count; i++) {
+ if (ses->chans[i].server == server) {
+ spin_unlock(&ses->chan_lock);
+ return &ses->chans[i];
+ }
+ }
+ spin_unlock(&ses->chan_lock);
+ return NULL;
+}
+
+static int
+cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
+ struct cifs_server_iface *iface)
+{
+ struct TCP_Server_Info *chan_server;
+ struct cifs_chan *chan;
+ struct smb3_fs_context ctx = {NULL};
+ static const char unc_fmt[] = "\\%s\\foo";
+ char unc[sizeof(unc_fmt)+SERVER_NAME_LEN_WITH_NULL] = {0};
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
+ int rc;
+ unsigned int xid = get_xid();
+
+ if (iface->sockaddr.ss_family == AF_INET)
+ cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI4)\n",
+ ses, iface->speed, iface->rdma_capable ? "yes" : "no",
+ &ipv4->sin_addr);
+ else
+ cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI6)\n",
+ ses, iface->speed, iface->rdma_capable ? "yes" : "no",
+ &ipv6->sin6_addr);
+
+ /*
+ * Setup a ctx with mostly the same info as the existing
+ * session and overwrite it with the requested iface data.
+ *
+ * We need to setup at least the fields used for negprot and
+ * sesssetup.
+ *
+ * We only need the ctx here, so we can reuse memory from
+ * the session and server without caring about memory
+ * management.
+ */
+
+ /* Always make new connection for now (TODO?) */
+ ctx.nosharesock = true;
+
+ /* Auth */
+ ctx.domainauto = ses->domainAuto;
+ ctx.domainname = ses->domainName;
+
+ /* no hostname for extra channels */
+ ctx.server_hostname = "";
+
+ ctx.username = ses->user_name;
+ ctx.password = ses->password;
+ ctx.sectype = ses->sectype;
+ ctx.sign = ses->sign;
+
+ /* UNC and paths */
+ /* XXX: Use ses->server->hostname? */
+ sprintf(unc, unc_fmt, ses->ip_addr);
+ ctx.UNC = unc;
+ ctx.prepath = "";
+
+ /* Reuse same version as master connection */
+ ctx.vals = ses->server->vals;
+ ctx.ops = ses->server->ops;
+
+ ctx.noblocksnd = ses->server->noblocksnd;
+ ctx.noautotune = ses->server->noautotune;
+ ctx.sockopt_tcp_nodelay = ses->server->tcp_nodelay;
+ ctx.echo_interval = ses->server->echo_interval / HZ;
+ ctx.max_credits = ses->server->max_credits;
+
+ /*
+ * This will be used for encoding/decoding user/domain/pw
+ * during sess setup auth.
+ */
+ ctx.local_nls = cifs_sb->local_nls;
+
+ /* Use RDMA if possible */
+ ctx.rdma = iface->rdma_capable;
+ memcpy(&ctx.dstaddr, &iface->sockaddr, sizeof(struct sockaddr_storage));
+
+ /* reuse master con client guid */
+ memcpy(&ctx.client_guid, ses->server->client_guid,
+ SMB2_CLIENT_GUID_SIZE);
+ ctx.use_client_guid = true;
+
+ chan_server = cifs_get_tcp_session(&ctx, ses->server);
+
+ spin_lock(&ses->chan_lock);
+ chan = &ses->chans[ses->chan_count];
+ chan->server = chan_server;
+ if (IS_ERR(chan->server)) {
+ rc = PTR_ERR(chan->server);
+ chan->server = NULL;
+ spin_unlock(&ses->chan_lock);
+ goto out;
+ }
+ chan->iface = iface;
+ ses->chan_count++;
+ atomic_set(&ses->chan_seq, 0);
+
+ /* Mark this channel as needing connect/setup */
+ cifs_chan_set_need_reconnect(ses, chan->server);
+
+ spin_unlock(&ses->chan_lock);
+
+ mutex_lock(&ses->session_mutex);
+ /*
+ * We need to allocate the server crypto now as we will need
+ * to sign packets before we generate the channel signing key
+ * (we sign with the session key)
+ */
+ rc = smb311_crypto_shash_allocate(chan->server);
+ if (rc) {
+ cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
+ mutex_unlock(&ses->session_mutex);
+ goto out;
+ }
+
+ rc = cifs_negotiate_protocol(xid, ses, chan->server);
+ if (!rc)
+ rc = cifs_setup_session(xid, ses, chan->server, cifs_sb->local_nls);
+
+ mutex_unlock(&ses->session_mutex);
+
+out:
+ if (rc && chan->server) {
+ /*
+ * we should avoid race with these delayed works before we
+ * remove this channel
+ */
+ cancel_delayed_work_sync(&chan->server->echo);
+ cancel_delayed_work_sync(&chan->server->resolve);
+ cancel_delayed_work_sync(&chan->server->reconnect);
+
+ spin_lock(&ses->chan_lock);
+ /* we rely on all bits beyond chan_count to be clear */
+ cifs_chan_clear_need_reconnect(ses, chan->server);
+ ses->chan_count--;
+ /*
+ * chan_count should never reach 0 as at least the primary
+ * channel is always allocated
+ */
+ WARN_ON(ses->chan_count < 1);
+ spin_unlock(&ses->chan_lock);
+
+ cifs_put_tcp_session(chan->server, 0);
+ }
+
+ free_xid(xid);
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+static __u32 cifs_ssetup_hdr(struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ SESSION_SETUP_ANDX *pSMB)
+{
+ __u32 capabilities = 0;
+
+ /* init fields common to all four types of SessSetup */
+ /* Note that offsets for first seven fields in req struct are same */
+ /* in CIFS Specs so does not matter which of 3 forms of struct */
+ /* that we use in next few lines */
+ /* Note that header is initialized to zero in header_assemble */
+ pSMB->req.AndXCommand = 0xFF;
+ pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32,
+ CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
+ USHRT_MAX));
+ pSMB->req.MaxMpxCount = cpu_to_le16(server->maxReq);
+ pSMB->req.VcNumber = cpu_to_le16(1);
+
+ /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
+
+ /* BB verify whether signing required on neg or just on auth frame
+ (and NTLM case) */
+
+ capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+ CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
+
+ if (server->sign)
+ pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ if (ses->capabilities & CAP_UNICODE) {
+ pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
+ capabilities |= CAP_UNICODE;
+ }
+ if (ses->capabilities & CAP_STATUS32) {
+ pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
+ capabilities |= CAP_STATUS32;
+ }
+ if (ses->capabilities & CAP_DFS) {
+ pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
+ capabilities |= CAP_DFS;
+ }
+ if (ses->capabilities & CAP_UNIX)
+ capabilities |= CAP_UNIX;
+
+ return capabilities;
+}
+
+static void
+unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
+{
+ char *bcc_ptr = *pbcc_area;
+ int bytes_ret = 0;
+
+ /* Copy OS version */
+ bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
+ nls_cp);
+ bcc_ptr += 2 * bytes_ret;
+ bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
+ 32, nls_cp);
+ bcc_ptr += 2 * bytes_ret;
+ bcc_ptr += 2; /* trailing null */
+
+ bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
+ 32, nls_cp);
+ bcc_ptr += 2 * bytes_ret;
+ bcc_ptr += 2; /* trailing null */
+
+ *pbcc_area = bcc_ptr;
+}
+
+static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
+ const struct nls_table *nls_cp)
+{
+ char *bcc_ptr = *pbcc_area;
+ int bytes_ret = 0;
+
+ /* copy domain */
+ if (ses->domainName == NULL) {
+ /* Sending null domain better than using a bogus domain name (as
+ we did briefly in 2.6.18) since server will use its default */
+ *bcc_ptr = 0;
+ *(bcc_ptr+1) = 0;
+ bytes_ret = 0;
+ } else
+ bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
+ CIFS_MAX_DOMAINNAME_LEN, nls_cp);
+ bcc_ptr += 2 * bytes_ret;
+ bcc_ptr += 2; /* account for null terminator */
+
+ *pbcc_area = bcc_ptr;
+}
+
+static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
+ const struct nls_table *nls_cp)
+{
+ char *bcc_ptr = *pbcc_area;
+ int bytes_ret = 0;
+
+ /* BB FIXME add check that strings total less
+ than 335 or will need to send them as arrays */
+
+ /* copy user */
+ if (ses->user_name == NULL) {
+ /* null user mount */
+ *bcc_ptr = 0;
+ *(bcc_ptr+1) = 0;
+ } else {
+ bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
+ CIFS_MAX_USERNAME_LEN, nls_cp);
+ }
+ bcc_ptr += 2 * bytes_ret;
+ bcc_ptr += 2; /* account for null termination */
+
+ unicode_domain_string(&bcc_ptr, ses, nls_cp);
+ unicode_oslm_strings(&bcc_ptr, nls_cp);
+
+ *pbcc_area = bcc_ptr;
+}
+
+static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
+ const struct nls_table *nls_cp)
+{
+ char *bcc_ptr = *pbcc_area;
+ int len;
+
+ /* copy user */
+ /* BB what about null user mounts - check that we do this BB */
+ /* copy user */
+ if (ses->user_name != NULL) {
+ len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
+ if (WARN_ON_ONCE(len < 0))
+ len = CIFS_MAX_USERNAME_LEN - 1;
+ bcc_ptr += len;
+ }
+ /* else null user mount */
+ *bcc_ptr = 0;
+ bcc_ptr++; /* account for null termination */
+
+ /* copy domain */
+ if (ses->domainName != NULL) {
+ len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+ if (WARN_ON_ONCE(len < 0))
+ len = CIFS_MAX_DOMAINNAME_LEN - 1;
+ bcc_ptr += len;
+ } /* else we will send a null domain name
+ so the server will default to its own domain */
+ *bcc_ptr = 0;
+ bcc_ptr++;
+
+ /* BB check for overflow here */
+
+ strcpy(bcc_ptr, "Linux version ");
+ bcc_ptr += strlen("Linux version ");
+ strcpy(bcc_ptr, init_utsname()->release);
+ bcc_ptr += strlen(init_utsname()->release) + 1;
+
+ strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+ bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+
+ *pbcc_area = bcc_ptr;
+}
+
+static void
+decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
+ const struct nls_table *nls_cp)
+{
+ int len;
+ char *data = *pbcc_area;
+
+ cifs_dbg(FYI, "bleft %d\n", bleft);
+
+ kfree(ses->serverOS);
+ ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
+ cifs_dbg(FYI, "serverOS=%s\n", ses->serverOS);
+ len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
+ data += len;
+ bleft -= len;
+ if (bleft <= 0)
+ return;
+
+ kfree(ses->serverNOS);
+ ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
+ cifs_dbg(FYI, "serverNOS=%s\n", ses->serverNOS);
+ len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
+ data += len;
+ bleft -= len;
+ if (bleft <= 0)
+ return;
+
+ kfree(ses->serverDomain);
+ ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
+ cifs_dbg(FYI, "serverDomain=%s\n", ses->serverDomain);
+
+ return;
+}
+
+static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
+ struct cifs_ses *ses,
+ const struct nls_table *nls_cp)
+{
+ int len;
+ char *bcc_ptr = *pbcc_area;
+
+ cifs_dbg(FYI, "decode sessetup ascii. bleft %d\n", bleft);
+
+ len = strnlen(bcc_ptr, bleft);
+ if (len >= bleft)
+ return;
+
+ kfree(ses->serverOS);
+
+ ses->serverOS = kmalloc(len + 1, GFP_KERNEL);
+ if (ses->serverOS) {
+ memcpy(ses->serverOS, bcc_ptr, len);
+ ses->serverOS[len] = 0;
+ if (strncmp(ses->serverOS, "OS/2", 4) == 0)
+ cifs_dbg(FYI, "OS/2 server\n");
+ }
+
+ bcc_ptr += len + 1;
+ bleft -= len + 1;
+
+ len = strnlen(bcc_ptr, bleft);
+ if (len >= bleft)
+ return;
+
+ kfree(ses->serverNOS);
+
+ ses->serverNOS = kmalloc(len + 1, GFP_KERNEL);
+ if (ses->serverNOS) {
+ memcpy(ses->serverNOS, bcc_ptr, len);
+ ses->serverNOS[len] = 0;
+ }
+
+ bcc_ptr += len + 1;
+ bleft -= len + 1;
+
+ len = strnlen(bcc_ptr, bleft);
+ if (len > bleft)
+ return;
+
+ /* No domain field in LANMAN case. Domain is
+ returned by old servers in the SMB negprot response */
+ /* BB For newer servers which do not support Unicode,
+ but thus do return domain here we could add parsing
+ for it later, but it is not very important */
+ cifs_dbg(FYI, "ascii: bytes left %d\n", bleft);
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
+ struct cifs_ses *ses)
+{
+ unsigned int tioffset; /* challenge message target info area */
+ unsigned int tilen; /* challenge message target info area length */
+ CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
+ __u32 server_flags;
+
+ if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
+ cifs_dbg(VFS, "challenge blob len %d too small\n", blob_len);
+ return -EINVAL;
+ }
+
+ if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
+ cifs_dbg(VFS, "blob signature incorrect %s\n",
+ pblob->Signature);
+ return -EINVAL;
+ }
+ if (pblob->MessageType != NtLmChallenge) {
+ cifs_dbg(VFS, "Incorrect message type %d\n",
+ pblob->MessageType);
+ return -EINVAL;
+ }
+
+ server_flags = le32_to_cpu(pblob->NegotiateFlags);
+ cifs_dbg(FYI, "%s: negotiate=0x%08x challenge=0x%08x\n", __func__,
+ ses->ntlmssp->client_flags, server_flags);
+
+ if ((ses->ntlmssp->client_flags & (NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN)) &&
+ (!(server_flags & NTLMSSP_NEGOTIATE_56) && !(server_flags & NTLMSSP_NEGOTIATE_128))) {
+ cifs_dbg(VFS, "%s: requested signing/encryption but server did not return either 56-bit or 128-bit session key size\n",
+ __func__);
+ return -EINVAL;
+ }
+ if (!(server_flags & NTLMSSP_NEGOTIATE_NTLM) && !(server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) {
+ cifs_dbg(VFS, "%s: server does not seem to support either NTLMv1 or NTLMv2\n", __func__);
+ return -EINVAL;
+ }
+ if (ses->server->sign && !(server_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+ cifs_dbg(VFS, "%s: forced packet signing but server does not seem to support it\n",
+ __func__);
+ return -EOPNOTSUPP;
+ }
+ if ((ses->ntlmssp->client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
+ !(server_flags & NTLMSSP_NEGOTIATE_KEY_XCH))
+ pr_warn_once("%s: authentication has been weakened as server does not support key exchange\n",
+ __func__);
+
+ ses->ntlmssp->server_flags = server_flags;
+
+ memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
+ /* In particular we can examine sign flags */
+ /* BB spec says that if AvId field of MsvAvTimestamp is populated then
+ we must set the MIC field of the AUTHENTICATE_MESSAGE */
+
+ tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
+ tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
+ if (tioffset > blob_len || tioffset + tilen > blob_len) {
+ cifs_dbg(VFS, "tioffset + tilen too high %u + %u\n",
+ tioffset, tilen);
+ return -EINVAL;
+ }
+ if (tilen) {
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.response = kmemdup(bcc_ptr + tioffset, tilen,
+ GFP_KERNEL);
+ if (!ses->auth_key.response) {
+ cifs_dbg(VFS, "Challenge target info alloc failure\n");
+ return -ENOMEM;
+ }
+ ses->auth_key.len = tilen;
+ }
+
+ return 0;
+}
+
+static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size)
+{
+ int sz = base_size + ses->auth_key.len
+ - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
+
+ if (ses->domainName)
+ sz += sizeof(__le16) * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+ else
+ sz += sizeof(__le16);
+
+ if (ses->user_name)
+ sz += sizeof(__le16) * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
+ else
+ sz += sizeof(__le16);
+
+ if (ses->workstation_name[0])
+ sz += sizeof(__le16) * strnlen(ses->workstation_name,
+ ntlmssp_workstation_name_size(ses));
+ else
+ sz += sizeof(__le16);
+
+ return sz;
+}
+
+static inline void cifs_security_buffer_from_str(SECURITY_BUFFER *pbuf,
+ char *str_value,
+ int str_length,
+ unsigned char *pstart,
+ unsigned char **pcur,
+ const struct nls_table *nls_cp)
+{
+ unsigned char *tmp = pstart;
+ int len;
+
+ if (!pbuf)
+ return;
+
+ if (!pcur)
+ pcur = &tmp;
+
+ if (!str_value) {
+ pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
+ pbuf->Length = 0;
+ pbuf->MaximumLength = 0;
+ *pcur += sizeof(__le16);
+ } else {
+ len = cifs_strtoUTF16((__le16 *)*pcur,
+ str_value,
+ str_length,
+ nls_cp);
+ len *= sizeof(__le16);
+ pbuf->BufferOffset = cpu_to_le32(*pcur - pstart);
+ pbuf->Length = cpu_to_le16(len);
+ pbuf->MaximumLength = cpu_to_le16(len);
+ *pcur += len;
+ }
+}
+
+/* BB Move to ntlmssp.c eventually */
+
+int build_ntlmssp_negotiate_blob(unsigned char **pbuffer,
+ u16 *buflen,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp)
+{
+ int rc = 0;
+ NEGOTIATE_MESSAGE *sec_blob;
+ __u32 flags;
+ unsigned char *tmp;
+ int len;
+
+ len = size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE));
+ *pbuffer = kmalloc(len, GFP_KERNEL);
+ if (!*pbuffer) {
+ rc = -ENOMEM;
+ cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
+ *buflen = 0;
+ goto setup_ntlm_neg_ret;
+ }
+ sec_blob = (NEGOTIATE_MESSAGE *)*pbuffer;
+
+ memset(*pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
+ memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
+ sec_blob->MessageType = NtLmNegotiate;
+
+ /* BB is NTLMV2 session security format easier to use here? */
+ flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
+ NTLMSSP_NEGOTIATE_SIGN;
+ if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
+ flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
+
+ tmp = *pbuffer + sizeof(NEGOTIATE_MESSAGE);
+ ses->ntlmssp->client_flags = flags;
+ sec_blob->NegotiateFlags = cpu_to_le32(flags);
+
+ /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
+ cifs_security_buffer_from_str(&sec_blob->DomainName,
+ NULL,
+ CIFS_MAX_DOMAINNAME_LEN,
+ *pbuffer, &tmp,
+ nls_cp);
+
+ cifs_security_buffer_from_str(&sec_blob->WorkstationName,
+ NULL,
+ CIFS_MAX_WORKSTATION_LEN,
+ *pbuffer, &tmp,
+ nls_cp);
+
+ *buflen = tmp - *pbuffer;
+setup_ntlm_neg_ret:
+ return rc;
+}
+
+/*
+ * Build ntlmssp blob with additional fields, such as version,
+ * supported by modern servers. For safety limit to SMB3 or later
+ * See notes in MS-NLMP Section 2.2.2.1 e.g.
+ */
+int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer,
+ u16 *buflen,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp)
+{
+ int rc = 0;
+ struct negotiate_message *sec_blob;
+ __u32 flags;
+ unsigned char *tmp;
+ int len;
+
+ len = size_of_ntlmssp_blob(ses, sizeof(struct negotiate_message));
+ *pbuffer = kmalloc(len, GFP_KERNEL);
+ if (!*pbuffer) {
+ rc = -ENOMEM;
+ cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
+ *buflen = 0;
+ goto setup_ntlm_smb3_neg_ret;
+ }
+ sec_blob = (struct negotiate_message *)*pbuffer;
+
+ memset(*pbuffer, 0, sizeof(struct negotiate_message));
+ memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
+ sec_blob->MessageType = NtLmNegotiate;
+
+ /* BB is NTLMV2 session security format easier to use here? */
+ flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC |
+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL |
+ NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION;
+ if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess)
+ flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
+
+ sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR;
+ sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL;
+ sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD);
+ sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
+
+ tmp = *pbuffer + sizeof(struct negotiate_message);
+ ses->ntlmssp->client_flags = flags;
+ sec_blob->NegotiateFlags = cpu_to_le32(flags);
+
+ /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */
+ cifs_security_buffer_from_str(&sec_blob->DomainName,
+ NULL,
+ CIFS_MAX_DOMAINNAME_LEN,
+ *pbuffer, &tmp,
+ nls_cp);
+
+ cifs_security_buffer_from_str(&sec_blob->WorkstationName,
+ NULL,
+ CIFS_MAX_WORKSTATION_LEN,
+ *pbuffer, &tmp,
+ nls_cp);
+
+ *buflen = tmp - *pbuffer;
+setup_ntlm_smb3_neg_ret:
+ return rc;
+}
+
+
+int build_ntlmssp_auth_blob(unsigned char **pbuffer,
+ u16 *buflen,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp)
+{
+ int rc;
+ AUTHENTICATE_MESSAGE *sec_blob;
+ __u32 flags;
+ unsigned char *tmp;
+ int len;
+
+ rc = setup_ntlmv2_rsp(ses, nls_cp);
+ if (rc) {
+ cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
+ *buflen = 0;
+ goto setup_ntlmv2_ret;
+ }
+
+ len = size_of_ntlmssp_blob(ses, sizeof(AUTHENTICATE_MESSAGE));
+ *pbuffer = kmalloc(len, GFP_KERNEL);
+ if (!*pbuffer) {
+ rc = -ENOMEM;
+ cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
+ *buflen = 0;
+ goto setup_ntlmv2_ret;
+ }
+ sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
+
+ memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
+ sec_blob->MessageType = NtLmAuthenticate;
+
+ flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
+
+ tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
+ sec_blob->NegotiateFlags = cpu_to_le32(flags);
+
+ sec_blob->LmChallengeResponse.BufferOffset =
+ cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
+ sec_blob->LmChallengeResponse.Length = 0;
+ sec_blob->LmChallengeResponse.MaximumLength = 0;
+
+ sec_blob->NtChallengeResponse.BufferOffset =
+ cpu_to_le32(tmp - *pbuffer);
+ if (ses->user_name != NULL) {
+ memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+ ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
+
+ sec_blob->NtChallengeResponse.Length =
+ cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ sec_blob->NtChallengeResponse.MaximumLength =
+ cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ } else {
+ /*
+ * don't send an NT Response for anonymous access
+ */
+ sec_blob->NtChallengeResponse.Length = 0;
+ sec_blob->NtChallengeResponse.MaximumLength = 0;
+ }
+
+ cifs_security_buffer_from_str(&sec_blob->DomainName,
+ ses->domainName,
+ CIFS_MAX_DOMAINNAME_LEN,
+ *pbuffer, &tmp,
+ nls_cp);
+
+ cifs_security_buffer_from_str(&sec_blob->UserName,
+ ses->user_name,
+ CIFS_MAX_USERNAME_LEN,
+ *pbuffer, &tmp,
+ nls_cp);
+
+ cifs_security_buffer_from_str(&sec_blob->WorkstationName,
+ ses->workstation_name,
+ ntlmssp_workstation_name_size(ses),
+ *pbuffer, &tmp,
+ nls_cp);
+
+ if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
+ (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) &&
+ !calc_seckey(ses)) {
+ memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
+ sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
+ sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
+ sec_blob->SessionKey.MaximumLength =
+ cpu_to_le16(CIFS_CPHTXT_SIZE);
+ tmp += CIFS_CPHTXT_SIZE;
+ } else {
+ sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
+ sec_blob->SessionKey.Length = 0;
+ sec_blob->SessionKey.MaximumLength = 0;
+ }
+
+ *buflen = tmp - *pbuffer;
+setup_ntlmv2_ret:
+ return rc;
+}
+
+enum securityEnum
+cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
+{
+ switch (server->negflavor) {
+ case CIFS_NEGFLAVOR_EXTENDED:
+ switch (requested) {
+ case Kerberos:
+ case RawNTLMSSP:
+ return requested;
+ case Unspecified:
+ if (server->sec_ntlmssp &&
+ (global_secflags & CIFSSEC_MAY_NTLMSSP))
+ return RawNTLMSSP;
+ if ((server->sec_kerberos || server->sec_mskerberos) &&
+ (global_secflags & CIFSSEC_MAY_KRB5))
+ return Kerberos;
+ fallthrough;
+ default:
+ return Unspecified;
+ }
+ case CIFS_NEGFLAVOR_UNENCAP:
+ switch (requested) {
+ case NTLMv2:
+ return requested;
+ case Unspecified:
+ if (global_secflags & CIFSSEC_MAY_NTLMV2)
+ return NTLMv2;
+ break;
+ default:
+ break;
+ }
+ fallthrough;
+ default:
+ return Unspecified;
+ }
+}
+
+struct sess_data {
+ unsigned int xid;
+ struct cifs_ses *ses;
+ struct TCP_Server_Info *server;
+ struct nls_table *nls_cp;
+ void (*func)(struct sess_data *);
+ int result;
+
+ /* we will send the SMB in three pieces:
+ * a fixed length beginning part, an optional
+ * SPNEGO blob (which can be zero length), and a
+ * last part which will include the strings
+ * and rest of bcc area. This allows us to avoid
+ * a large buffer 17K allocation
+ */
+ int buf0_type;
+ struct kvec iov[3];
+};
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+static int
+sess_alloc_buffer(struct sess_data *sess_data, int wct)
+{
+ int rc;
+ struct cifs_ses *ses = sess_data->ses;
+ struct smb_hdr *smb_buf;
+
+ rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
+ (void **)&smb_buf);
+
+ if (rc)
+ return rc;
+
+ sess_data->iov[0].iov_base = (char *)smb_buf;
+ sess_data->iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
+ /*
+ * This variable will be used to clear the buffer
+ * allocated above in case of any error in the calling function.
+ */
+ sess_data->buf0_type = CIFS_SMALL_BUFFER;
+
+ /* 2000 big enough to fit max user, domain, NOS name etc. */
+ sess_data->iov[2].iov_base = kmalloc(2000, GFP_KERNEL);
+ if (!sess_data->iov[2].iov_base) {
+ rc = -ENOMEM;
+ goto out_free_smb_buf;
+ }
+
+ return 0;
+
+out_free_smb_buf:
+ cifs_small_buf_release(smb_buf);
+ sess_data->iov[0].iov_base = NULL;
+ sess_data->iov[0].iov_len = 0;
+ sess_data->buf0_type = CIFS_NO_BUFFER;
+ return rc;
+}
+
+static void
+sess_free_buffer(struct sess_data *sess_data)
+{
+ struct kvec *iov = sess_data->iov;
+
+ /*
+ * Zero the session data before freeing, as it might contain sensitive info (keys, etc).
+ * Note that iov[1] is already freed by caller.
+ */
+ if (sess_data->buf0_type != CIFS_NO_BUFFER && iov[0].iov_base)
+ memzero_explicit(iov[0].iov_base, iov[0].iov_len);
+
+ free_rsp_buf(sess_data->buf0_type, iov[0].iov_base);
+ sess_data->buf0_type = CIFS_NO_BUFFER;
+ kfree_sensitive(iov[2].iov_base);
+}
+
+static int
+sess_establish_session(struct sess_data *sess_data)
+{
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+
+ cifs_server_lock(server);
+ if (!server->session_estab) {
+ if (server->sign) {
+ server->session_key.response =
+ kmemdup(ses->auth_key.response,
+ ses->auth_key.len, GFP_KERNEL);
+ if (!server->session_key.response) {
+ cifs_server_unlock(server);
+ return -ENOMEM;
+ }
+ server->session_key.len =
+ ses->auth_key.len;
+ }
+ server->sequence_number = 0x2;
+ server->session_estab = true;
+ }
+ cifs_server_unlock(server);
+
+ cifs_dbg(FYI, "CIFS session established successfully\n");
+ return 0;
+}
+
+static int
+sess_sendreceive(struct sess_data *sess_data)
+{
+ int rc;
+ struct smb_hdr *smb_buf = (struct smb_hdr *) sess_data->iov[0].iov_base;
+ __u16 count;
+ struct kvec rsp_iov = { NULL, 0 };
+
+ count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len;
+ be32_add_cpu(&smb_buf->smb_buf_length, count);
+ put_bcc(count, smb_buf);
+
+ rc = SendReceive2(sess_data->xid, sess_data->ses,
+ sess_data->iov, 3 /* num_iovecs */,
+ &sess_data->buf0_type,
+ CIFS_LOG_ERROR, &rsp_iov);
+ cifs_small_buf_release(sess_data->iov[0].iov_base);
+ memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
+
+ return rc;
+}
+
+static void
+sess_auth_ntlmv2(struct sess_data *sess_data)
+{
+ int rc = 0;
+ struct smb_hdr *smb_buf;
+ SESSION_SETUP_ANDX *pSMB;
+ char *bcc_ptr;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+ __u32 capabilities;
+ __u16 bytes_remaining;
+
+ /* old style NTLM sessionsetup */
+ /* wct = 13 */
+ rc = sess_alloc_buffer(sess_data, 13);
+ if (rc)
+ goto out;
+
+ pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
+ bcc_ptr = sess_data->iov[2].iov_base;
+ capabilities = cifs_ssetup_hdr(ses, server, pSMB);
+
+ pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+
+ /* LM2 password would be here if we supported it */
+ pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
+
+ if (ses->user_name != NULL) {
+ /* calculate nlmv2 response and session key */
+ rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
+ if (rc) {
+ cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
+ goto out;
+ }
+
+ memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+ ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
+
+ /* set case sensitive password length after tilen may get
+ * assigned, tilen is 0 otherwise.
+ */
+ pSMB->req_no_secext.CaseSensitivePasswordLength =
+ cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ } else {
+ pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
+ }
+
+ if (ses->capabilities & CAP_UNICODE) {
+ if (!IS_ALIGNED(sess_data->iov[0].iov_len, 2)) {
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ unicode_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
+ } else {
+ ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
+ }
+
+
+ sess_data->iov[2].iov_len = (long) bcc_ptr -
+ (long) sess_data->iov[2].iov_base;
+
+ rc = sess_sendreceive(sess_data);
+ if (rc)
+ goto out;
+
+ pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
+ smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
+
+ if (smb_buf->WordCount != 3) {
+ rc = -EIO;
+ cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
+ goto out;
+ }
+
+ if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
+ cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
+
+ ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
+ cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
+
+ bytes_remaining = get_bcc(smb_buf);
+ bcc_ptr = pByteArea(smb_buf);
+
+ /* BB check if Unicode and decode strings */
+ if (bytes_remaining == 0) {
+ /* no string area to decode, do nothing */
+ } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
+ /* unicode string area must be word-aligned */
+ if (!IS_ALIGNED((unsigned long)bcc_ptr - (unsigned long)smb_buf, 2)) {
+ ++bcc_ptr;
+ --bytes_remaining;
+ }
+ decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
+ sess_data->nls_cp);
+ } else {
+ decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
+ sess_data->nls_cp);
+ }
+
+ rc = sess_establish_session(sess_data);
+out:
+ sess_data->result = rc;
+ sess_data->func = NULL;
+ sess_free_buffer(sess_data);
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.response = NULL;
+}
+
+#ifdef CONFIG_CIFS_UPCALL
+static void
+sess_auth_kerberos(struct sess_data *sess_data)
+{
+ int rc = 0;
+ struct smb_hdr *smb_buf;
+ SESSION_SETUP_ANDX *pSMB;
+ char *bcc_ptr;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+ __u32 capabilities;
+ __u16 bytes_remaining;
+ struct key *spnego_key = NULL;
+ struct cifs_spnego_msg *msg;
+ u16 blob_len;
+
+ /* extended security */
+ /* wct = 12 */
+ rc = sess_alloc_buffer(sess_data, 12);
+ if (rc)
+ goto out;
+
+ pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
+ bcc_ptr = sess_data->iov[2].iov_base;
+ capabilities = cifs_ssetup_hdr(ses, server, pSMB);
+
+ spnego_key = cifs_get_spnego_key(ses, server);
+ if (IS_ERR(spnego_key)) {
+ rc = PTR_ERR(spnego_key);
+ spnego_key = NULL;
+ goto out;
+ }
+
+ msg = spnego_key->payload.data[0];
+ /*
+ * check version field to make sure that cifs.upcall is
+ * sending us a response in an expected form
+ */
+ if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
+ cifs_dbg(VFS, "incorrect version of cifs.upcall (expected %d but got %d)\n",
+ CIFS_SPNEGO_UPCALL_VERSION, msg->version);
+ rc = -EKEYREJECTED;
+ goto out_put_spnego_key;
+ }
+
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
+ GFP_KERNEL);
+ if (!ses->auth_key.response) {
+ cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n",
+ msg->sesskey_len);
+ rc = -ENOMEM;
+ goto out_put_spnego_key;
+ }
+ ses->auth_key.len = msg->sesskey_len;
+
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ capabilities |= CAP_EXTENDED_SECURITY;
+ pSMB->req.Capabilities = cpu_to_le32(capabilities);
+ sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
+ sess_data->iov[1].iov_len = msg->secblob_len;
+ pSMB->req.SecurityBlobLength = cpu_to_le16(sess_data->iov[1].iov_len);
+
+ if (ses->capabilities & CAP_UNICODE) {
+ /* unicode strings must be word aligned */
+ if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) {
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
+ unicode_domain_string(&bcc_ptr, ses, sess_data->nls_cp);
+ } else {
+ /* BB: is this right? */
+ ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp);
+ }
+
+ sess_data->iov[2].iov_len = (long) bcc_ptr -
+ (long) sess_data->iov[2].iov_base;
+
+ rc = sess_sendreceive(sess_data);
+ if (rc)
+ goto out_put_spnego_key;
+
+ pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
+ smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
+
+ if (smb_buf->WordCount != 4) {
+ rc = -EIO;
+ cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
+ goto out_put_spnego_key;
+ }
+
+ if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
+ cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
+
+ ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
+ cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
+
+ bytes_remaining = get_bcc(smb_buf);
+ bcc_ptr = pByteArea(smb_buf);
+
+ blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
+ if (blob_len > bytes_remaining) {
+ cifs_dbg(VFS, "bad security blob length %d\n",
+ blob_len);
+ rc = -EINVAL;
+ goto out_put_spnego_key;
+ }
+ bcc_ptr += blob_len;
+ bytes_remaining -= blob_len;
+
+ /* BB check if Unicode and decode strings */
+ if (bytes_remaining == 0) {
+ /* no string area to decode, do nothing */
+ } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
+ /* unicode string area must be word-aligned */
+ if (!IS_ALIGNED((unsigned long)bcc_ptr - (unsigned long)smb_buf, 2)) {
+ ++bcc_ptr;
+ --bytes_remaining;
+ }
+ decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
+ sess_data->nls_cp);
+ } else {
+ decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
+ sess_data->nls_cp);
+ }
+
+ rc = sess_establish_session(sess_data);
+out_put_spnego_key:
+ key_invalidate(spnego_key);
+ key_put(spnego_key);
+out:
+ sess_data->result = rc;
+ sess_data->func = NULL;
+ sess_free_buffer(sess_data);
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.response = NULL;
+}
+
+#endif /* ! CONFIG_CIFS_UPCALL */
+
+/*
+ * The required kvec buffers have to be allocated before calling this
+ * function.
+ */
+static int
+_sess_auth_rawntlmssp_assemble_req(struct sess_data *sess_data)
+{
+ SESSION_SETUP_ANDX *pSMB;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+ __u32 capabilities;
+ char *bcc_ptr;
+
+ pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
+
+ capabilities = cifs_ssetup_hdr(ses, server, pSMB);
+ if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
+ cifs_dbg(VFS, "NTLMSSP requires Unicode support\n");
+ return -ENOSYS;
+ }
+
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ capabilities |= CAP_EXTENDED_SECURITY;
+ pSMB->req.Capabilities |= cpu_to_le32(capabilities);
+
+ bcc_ptr = sess_data->iov[2].iov_base;
+ /* unicode strings must be word aligned */
+ if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) {
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp);
+
+ sess_data->iov[2].iov_len = (long) bcc_ptr -
+ (long) sess_data->iov[2].iov_base;
+
+ return 0;
+}
+
+static void
+sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data);
+
+static void
+sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
+{
+ int rc;
+ struct smb_hdr *smb_buf;
+ SESSION_SETUP_ANDX *pSMB;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+ __u16 bytes_remaining;
+ char *bcc_ptr;
+ unsigned char *ntlmsspblob = NULL;
+ u16 blob_len;
+
+ cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n");
+
+ /*
+ * if memory allocation is successful, caller of this function
+ * frees it.
+ */
+ ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
+ if (!ses->ntlmssp) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ ses->ntlmssp->sesskey_per_smbsess = false;
+
+ /* wct = 12 */
+ rc = sess_alloc_buffer(sess_data, 12);
+ if (rc)
+ goto out;
+
+ pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
+
+ /* Build security blob before we assemble the request */
+ rc = build_ntlmssp_negotiate_blob(&ntlmsspblob,
+ &blob_len, ses, server,
+ sess_data->nls_cp);
+ if (rc)
+ goto out_free_ntlmsspblob;
+
+ sess_data->iov[1].iov_len = blob_len;
+ sess_data->iov[1].iov_base = ntlmsspblob;
+ pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
+
+ rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
+ if (rc)
+ goto out_free_ntlmsspblob;
+
+ rc = sess_sendreceive(sess_data);
+
+ pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
+ smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
+
+ /* If true, rc here is expected and not an error */
+ if (sess_data->buf0_type != CIFS_NO_BUFFER &&
+ smb_buf->Status.CifsError ==
+ cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
+ rc = 0;
+
+ if (rc)
+ goto out_free_ntlmsspblob;
+
+ cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
+
+ if (smb_buf->WordCount != 4) {
+ rc = -EIO;
+ cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
+ goto out_free_ntlmsspblob;
+ }
+
+ ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
+ cifs_dbg(FYI, "UID = %llu\n", ses->Suid);
+
+ bytes_remaining = get_bcc(smb_buf);
+ bcc_ptr = pByteArea(smb_buf);
+
+ blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
+ if (blob_len > bytes_remaining) {
+ cifs_dbg(VFS, "bad security blob length %d\n",
+ blob_len);
+ rc = -EINVAL;
+ goto out_free_ntlmsspblob;
+ }
+
+ rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
+
+out_free_ntlmsspblob:
+ kfree_sensitive(ntlmsspblob);
+out:
+ sess_free_buffer(sess_data);
+
+ if (!rc) {
+ sess_data->func = sess_auth_rawntlmssp_authenticate;
+ return;
+ }
+
+ /* Else error. Cleanup */
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.response = NULL;
+ kfree_sensitive(ses->ntlmssp);
+ ses->ntlmssp = NULL;
+
+ sess_data->func = NULL;
+ sess_data->result = rc;
+}
+
+static void
+sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
+{
+ int rc;
+ struct smb_hdr *smb_buf;
+ SESSION_SETUP_ANDX *pSMB;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+ __u16 bytes_remaining;
+ char *bcc_ptr;
+ unsigned char *ntlmsspblob = NULL;
+ u16 blob_len;
+
+ cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
+
+ /* wct = 12 */
+ rc = sess_alloc_buffer(sess_data, 12);
+ if (rc)
+ goto out;
+
+ /* Build security blob before we assemble the request */
+ pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
+ smb_buf = (struct smb_hdr *)pSMB;
+ rc = build_ntlmssp_auth_blob(&ntlmsspblob,
+ &blob_len, ses, server,
+ sess_data->nls_cp);
+ if (rc)
+ goto out_free_ntlmsspblob;
+ sess_data->iov[1].iov_len = blob_len;
+ sess_data->iov[1].iov_base = ntlmsspblob;
+ pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
+ /*
+ * Make sure that we tell the server that we are using
+ * the uid that it just gave us back on the response
+ * (challenge)
+ */
+ smb_buf->Uid = ses->Suid;
+
+ rc = _sess_auth_rawntlmssp_assemble_req(sess_data);
+ if (rc)
+ goto out_free_ntlmsspblob;
+
+ rc = sess_sendreceive(sess_data);
+ if (rc)
+ goto out_free_ntlmsspblob;
+
+ pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
+ smb_buf = (struct smb_hdr *)sess_data->iov[0].iov_base;
+ if (smb_buf->WordCount != 4) {
+ rc = -EIO;
+ cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount);
+ goto out_free_ntlmsspblob;
+ }
+
+ if (le16_to_cpu(pSMB->resp.Action) & GUEST_LOGIN)
+ cifs_dbg(FYI, "Guest login\n"); /* BB mark SesInfo struct? */
+
+ if (ses->Suid != smb_buf->Uid) {
+ ses->Suid = smb_buf->Uid;
+ cifs_dbg(FYI, "UID changed! new UID = %llu\n", ses->Suid);
+ }
+
+ bytes_remaining = get_bcc(smb_buf);
+ bcc_ptr = pByteArea(smb_buf);
+ blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
+ if (blob_len > bytes_remaining) {
+ cifs_dbg(VFS, "bad security blob length %d\n",
+ blob_len);
+ rc = -EINVAL;
+ goto out_free_ntlmsspblob;
+ }
+ bcc_ptr += blob_len;
+ bytes_remaining -= blob_len;
+
+
+ /* BB check if Unicode and decode strings */
+ if (bytes_remaining == 0) {
+ /* no string area to decode, do nothing */
+ } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
+ /* unicode string area must be word-aligned */
+ if (!IS_ALIGNED((unsigned long)bcc_ptr - (unsigned long)smb_buf, 2)) {
+ ++bcc_ptr;
+ --bytes_remaining;
+ }
+ decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses,
+ sess_data->nls_cp);
+ } else {
+ decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,
+ sess_data->nls_cp);
+ }
+
+out_free_ntlmsspblob:
+ kfree_sensitive(ntlmsspblob);
+out:
+ sess_free_buffer(sess_data);
+
+ if (!rc)
+ rc = sess_establish_session(sess_data);
+
+ /* Cleanup */
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.response = NULL;
+ kfree_sensitive(ses->ntlmssp);
+ ses->ntlmssp = NULL;
+
+ sess_data->func = NULL;
+ sess_data->result = rc;
+}
+
+static int select_sec(struct sess_data *sess_data)
+{
+ int type;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+
+ type = cifs_select_sectype(server, ses->sectype);
+ cifs_dbg(FYI, "sess setup type %d\n", type);
+ if (type == Unspecified) {
+ cifs_dbg(VFS, "Unable to select appropriate authentication method!\n");
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case NTLMv2:
+ sess_data->func = sess_auth_ntlmv2;
+ break;
+ case Kerberos:
+#ifdef CONFIG_CIFS_UPCALL
+ sess_data->func = sess_auth_kerberos;
+ break;
+#else
+ cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
+ return -ENOSYS;
+#endif /* CONFIG_CIFS_UPCALL */
+ case RawNTLMSSP:
+ sess_data->func = sess_auth_rawntlmssp_negotiate;
+ break;
+ default:
+ cifs_dbg(VFS, "secType %d not supported!\n", type);
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp)
+{
+ int rc = 0;
+ struct sess_data *sess_data;
+
+ if (ses == NULL) {
+ WARN(1, "%s: ses == NULL!", __func__);
+ return -EINVAL;
+ }
+
+ sess_data = kzalloc(sizeof(struct sess_data), GFP_KERNEL);
+ if (!sess_data)
+ return -ENOMEM;
+
+ sess_data->xid = xid;
+ sess_data->ses = ses;
+ sess_data->server = server;
+ sess_data->buf0_type = CIFS_NO_BUFFER;
+ sess_data->nls_cp = (struct nls_table *) nls_cp;
+
+ rc = select_sec(sess_data);
+ if (rc)
+ goto out;
+
+ while (sess_data->func)
+ sess_data->func(sess_data);
+
+ /* Store result before we free sess_data */
+ rc = sess_data->result;
+
+out:
+ kfree_sensitive(sess_data);
+ return rc;
+}
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
new file mode 100644
index 000000000000..7d1b3fc014d9
--- /dev/null
+++ b/fs/smb/client/smb1ops.c
@@ -0,0 +1,1276 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SMB1 (CIFS) version specific operations
+ *
+ * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
+ */
+
+#include <linux/pagemap.h>
+#include <linux/vfs.h>
+#include <uapi/linux/magic.h>
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifspdu.h"
+#include "cifs_unicode.h"
+#include "fs_context.h"
+
+/*
+ * An NT cancel request header looks just like the original request except:
+ *
+ * The Command is SMB_COM_NT_CANCEL
+ * The WordCount is zeroed out
+ * The ByteCount is zeroed out
+ *
+ * This function mangles an existing request buffer into a
+ * SMB_COM_NT_CANCEL request and then sends it.
+ */
+static int
+send_nt_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
+ struct mid_q_entry *mid)
+{
+ int rc = 0;
+ struct smb_hdr *in_buf = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
+
+ /* -4 for RFC1001 length and +2 for BCC field */
+ in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2);
+ in_buf->Command = SMB_COM_NT_CANCEL;
+ in_buf->WordCount = 0;
+ put_bcc(0, in_buf);
+
+ cifs_server_lock(server);
+ rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
+ if (rc) {
+ cifs_server_unlock(server);
+ return rc;
+ }
+
+ /*
+ * The response to this call was already factored into the sequence
+ * number when the call went out, so we must adjust it back downward
+ * after signing here.
+ */
+ --server->sequence_number;
+ rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
+ if (rc < 0)
+ server->sequence_number--;
+
+ cifs_server_unlock(server);
+
+ cifs_dbg(FYI, "issued NT_CANCEL for mid %u, rc = %d\n",
+ get_mid(in_buf), rc);
+
+ return rc;
+}
+
+static bool
+cifs_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
+{
+ return ob1->fid.netfid == ob2->fid.netfid;
+}
+
+static unsigned int
+cifs_read_data_offset(char *buf)
+{
+ READ_RSP *rsp = (READ_RSP *)buf;
+ return le16_to_cpu(rsp->DataOffset);
+}
+
+static unsigned int
+cifs_read_data_length(char *buf, bool in_remaining)
+{
+ READ_RSP *rsp = (READ_RSP *)buf;
+ /* It's a bug reading remaining data for SMB1 packets */
+ WARN_ON(in_remaining);
+ return (le16_to_cpu(rsp->DataLengthHigh) << 16) +
+ le16_to_cpu(rsp->DataLength);
+}
+
+static struct mid_q_entry *
+cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
+{
+ struct smb_hdr *buf = (struct smb_hdr *)buffer;
+ struct mid_q_entry *mid;
+
+ spin_lock(&server->mid_lock);
+ list_for_each_entry(mid, &server->pending_mid_q, qhead) {
+ if (compare_mid(mid->mid, buf) &&
+ mid->mid_state == MID_REQUEST_SUBMITTED &&
+ le16_to_cpu(mid->command) == buf->Command) {
+ kref_get(&mid->refcount);
+ spin_unlock(&server->mid_lock);
+ return mid;
+ }
+ }
+ spin_unlock(&server->mid_lock);
+ return NULL;
+}
+
+static void
+cifs_add_credits(struct TCP_Server_Info *server,
+ const struct cifs_credits *credits, const int optype)
+{
+ spin_lock(&server->req_lock);
+ server->credits += credits->value;
+ server->in_flight--;
+ spin_unlock(&server->req_lock);
+ wake_up(&server->request_q);
+}
+
+static void
+cifs_set_credits(struct TCP_Server_Info *server, const int val)
+{
+ spin_lock(&server->req_lock);
+ server->credits = val;
+ server->oplocks = val > 1 ? enable_oplocks : false;
+ spin_unlock(&server->req_lock);
+}
+
+static int *
+cifs_get_credits_field(struct TCP_Server_Info *server, const int optype)
+{
+ return &server->credits;
+}
+
+static unsigned int
+cifs_get_credits(struct mid_q_entry *mid)
+{
+ return 1;
+}
+
+/*
+ * Find a free multiplex id (SMB mid). Otherwise there could be
+ * mid collisions which might cause problems, demultiplexing the
+ * wrong response to this request. Multiplex ids could collide if
+ * one of a series requests takes much longer than the others, or
+ * if a very large number of long lived requests (byte range
+ * locks or FindNotify requests) are pending. No more than
+ * 64K-1 requests can be outstanding at one time. If no
+ * mids are available, return zero. A future optimization
+ * could make the combination of mids and uid the key we use
+ * to demultiplex on (rather than mid alone).
+ * In addition to the above check, the cifs demultiplex
+ * code already used the command code as a secondary
+ * check of the frame and if signing is negotiated the
+ * response would be discarded if the mid were the same
+ * but the signature was wrong. Since the mid is not put in the
+ * pending queue until later (when it is about to be dispatched)
+ * we do have to limit the number of outstanding requests
+ * to somewhat less than 64K-1 although it is hard to imagine
+ * so many threads being in the vfs at one time.
+ */
+static __u64
+cifs_get_next_mid(struct TCP_Server_Info *server)
+{
+ __u64 mid = 0;
+ __u16 last_mid, cur_mid;
+ bool collision, reconnect = false;
+
+ spin_lock(&server->mid_lock);
+
+ /* mid is 16 bit only for CIFS/SMB */
+ cur_mid = (__u16)((server->CurrentMid) & 0xffff);
+ /* we do not want to loop forever */
+ last_mid = cur_mid;
+ cur_mid++;
+ /* avoid 0xFFFF MID */
+ if (cur_mid == 0xffff)
+ cur_mid++;
+
+ /*
+ * This nested loop looks more expensive than it is.
+ * In practice the list of pending requests is short,
+ * fewer than 50, and the mids are likely to be unique
+ * on the first pass through the loop unless some request
+ * takes longer than the 64 thousand requests before it
+ * (and it would also have to have been a request that
+ * did not time out).
+ */
+ while (cur_mid != last_mid) {
+ struct mid_q_entry *mid_entry;
+ unsigned int num_mids;
+
+ collision = false;
+ if (cur_mid == 0)
+ cur_mid++;
+
+ num_mids = 0;
+ list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
+ ++num_mids;
+ if (mid_entry->mid == cur_mid &&
+ mid_entry->mid_state == MID_REQUEST_SUBMITTED) {
+ /* This mid is in use, try a different one */
+ collision = true;
+ break;
+ }
+ }
+
+ /*
+ * if we have more than 32k mids in the list, then something
+ * is very wrong. Possibly a local user is trying to DoS the
+ * box by issuing long-running calls and SIGKILL'ing them. If
+ * we get to 2^16 mids then we're in big trouble as this
+ * function could loop forever.
+ *
+ * Go ahead and assign out the mid in this situation, but force
+ * an eventual reconnect to clean out the pending_mid_q.
+ */
+ if (num_mids > 32768)
+ reconnect = true;
+
+ if (!collision) {
+ mid = (__u64)cur_mid;
+ server->CurrentMid = mid;
+ break;
+ }
+ cur_mid++;
+ }
+ spin_unlock(&server->mid_lock);
+
+ if (reconnect) {
+ cifs_signal_cifsd_for_reconnect(server, false);
+ }
+
+ return mid;
+}
+
+/*
+ return codes:
+ 0 not a transact2, or all data present
+ >0 transact2 with that much data missing
+ -EINVAL invalid transact2
+ */
+static int
+check2ndT2(char *buf)
+{
+ struct smb_hdr *pSMB = (struct smb_hdr *)buf;
+ struct smb_t2_rsp *pSMBt;
+ int remaining;
+ __u16 total_data_size, data_in_this_rsp;
+
+ if (pSMB->Command != SMB_COM_TRANSACTION2)
+ return 0;
+
+ /* check for plausible wct, bcc and t2 data and parm sizes */
+ /* check for parm and data offset going beyond end of smb */
+ if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
+ cifs_dbg(FYI, "Invalid transact2 word count\n");
+ return -EINVAL;
+ }
+
+ pSMBt = (struct smb_t2_rsp *)pSMB;
+
+ total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
+ data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
+
+ if (total_data_size == data_in_this_rsp)
+ return 0;
+ else if (total_data_size < data_in_this_rsp) {
+ cifs_dbg(FYI, "total data %d smaller than data in frame %d\n",
+ total_data_size, data_in_this_rsp);
+ return -EINVAL;
+ }
+
+ remaining = total_data_size - data_in_this_rsp;
+
+ cifs_dbg(FYI, "missing %d bytes from transact2, check next response\n",
+ remaining);
+ if (total_data_size > CIFSMaxBufSize) {
+ cifs_dbg(VFS, "TotalDataSize %d is over maximum buffer %d\n",
+ total_data_size, CIFSMaxBufSize);
+ return -EINVAL;
+ }
+ return remaining;
+}
+
+static int
+coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
+{
+ struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
+ struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
+ char *data_area_of_tgt;
+ char *data_area_of_src;
+ int remaining;
+ unsigned int byte_count, total_in_tgt;
+ __u16 tgt_total_cnt, src_total_cnt, total_in_src;
+
+ src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
+ tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
+
+ if (tgt_total_cnt != src_total_cnt)
+ cifs_dbg(FYI, "total data count of primary and secondary t2 differ source=%hu target=%hu\n",
+ src_total_cnt, tgt_total_cnt);
+
+ total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
+
+ remaining = tgt_total_cnt - total_in_tgt;
+
+ if (remaining < 0) {
+ cifs_dbg(FYI, "Server sent too much data. tgt_total_cnt=%hu total_in_tgt=%u\n",
+ tgt_total_cnt, total_in_tgt);
+ return -EPROTO;
+ }
+
+ if (remaining == 0) {
+ /* nothing to do, ignore */
+ cifs_dbg(FYI, "no more data remains\n");
+ return 0;
+ }
+
+ total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
+ if (remaining < total_in_src)
+ cifs_dbg(FYI, "transact2 2nd response contains too much data\n");
+
+ /* find end of first SMB data area */
+ data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
+ get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
+
+ /* validate target area */
+ data_area_of_src = (char *)&pSMBs->hdr.Protocol +
+ get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
+
+ data_area_of_tgt += total_in_tgt;
+
+ total_in_tgt += total_in_src;
+ /* is the result too big for the field? */
+ if (total_in_tgt > USHRT_MAX) {
+ cifs_dbg(FYI, "coalesced DataCount too large (%u)\n",
+ total_in_tgt);
+ return -EPROTO;
+ }
+ put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
+
+ /* fix up the BCC */
+ byte_count = get_bcc(target_hdr);
+ byte_count += total_in_src;
+ /* is the result too big for the field? */
+ if (byte_count > USHRT_MAX) {
+ cifs_dbg(FYI, "coalesced BCC too large (%u)\n", byte_count);
+ return -EPROTO;
+ }
+ put_bcc(byte_count, target_hdr);
+
+ byte_count = be32_to_cpu(target_hdr->smb_buf_length);
+ byte_count += total_in_src;
+ /* don't allow buffer to overflow */
+ if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+ cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n",
+ byte_count);
+ return -ENOBUFS;
+ }
+ target_hdr->smb_buf_length = cpu_to_be32(byte_count);
+
+ /* copy second buffer into end of first buffer */
+ memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
+
+ if (remaining != total_in_src) {
+ /* more responses to go */
+ cifs_dbg(FYI, "waiting for more secondary responses\n");
+ return 1;
+ }
+
+ /* we are done */
+ cifs_dbg(FYI, "found the last secondary response\n");
+ return 0;
+}
+
+static void
+cifs_downgrade_oplock(struct TCP_Server_Info *server,
+ struct cifsInodeInfo *cinode, __u32 oplock,
+ unsigned int epoch, bool *purge_cache)
+{
+ cifs_set_oplock_level(cinode, oplock);
+}
+
+static bool
+cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
+ char *buf, int malformed)
+{
+ if (malformed)
+ return false;
+ if (check2ndT2(buf) <= 0)
+ return false;
+ mid->multiRsp = true;
+ if (mid->resp_buf) {
+ /* merge response - fix up 1st*/
+ malformed = coalesce_t2(buf, mid->resp_buf);
+ if (malformed > 0)
+ return true;
+ /* All parts received or packet is malformed. */
+ mid->multiEnd = true;
+ dequeue_mid(mid, malformed);
+ return true;
+ }
+ if (!server->large_buf) {
+ /*FIXME: switch to already allocated largebuf?*/
+ cifs_dbg(VFS, "1st trans2 resp needs bigbuf\n");
+ } else {
+ /* Have first buffer */
+ mid->resp_buf = buf;
+ mid->large_buf = true;
+ server->bigbuf = NULL;
+ }
+ return true;
+}
+
+static bool
+cifs_need_neg(struct TCP_Server_Info *server)
+{
+ return server->maxBuf == 0;
+}
+
+static int
+cifs_negotiate(const unsigned int xid,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ int rc;
+ rc = CIFSSMBNegotiate(xid, ses, server);
+ if (rc == -EAGAIN) {
+ /* retry only once on 1st time connection */
+ set_credits(server, 1);
+ rc = CIFSSMBNegotiate(xid, ses, server);
+ if (rc == -EAGAIN)
+ rc = -EHOSTDOWN;
+ }
+ return rc;
+}
+
+static unsigned int
+cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+{
+ __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ unsigned int wsize;
+
+ /* start with specified wsize, or default */
+ if (ctx->wsize)
+ wsize = ctx->wsize;
+ else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
+ wsize = CIFS_DEFAULT_IOSIZE;
+ else
+ wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
+
+ /* can server support 24-bit write sizes? (via UNIX extensions) */
+ if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
+ wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
+
+ /*
+ * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
+ * Limit it to max buffer offered by the server, minus the size of the
+ * WRITEX header, not including the 4 byte RFC1001 length.
+ */
+ if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
+ (!(server->capabilities & CAP_UNIX) && server->sign))
+ wsize = min_t(unsigned int, wsize,
+ server->maxBuf - sizeof(WRITE_REQ) + 4);
+
+ /* hard limit of CIFS_MAX_WSIZE */
+ wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
+
+ return wsize;
+}
+
+static unsigned int
+cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+{
+ __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ unsigned int rsize, defsize;
+
+ /*
+ * Set default value...
+ *
+ * HACK alert! Ancient servers have very small buffers. Even though
+ * MS-CIFS indicates that servers are only limited by the client's
+ * bufsize for reads, testing against win98se shows that it throws
+ * INVALID_PARAMETER errors if you try to request too large a read.
+ * OS/2 just sends back short reads.
+ *
+ * If the server doesn't advertise CAP_LARGE_READ_X, then assume that
+ * it can't handle a read request larger than its MaxBufferSize either.
+ */
+ if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
+ defsize = CIFS_DEFAULT_IOSIZE;
+ else if (server->capabilities & CAP_LARGE_READ_X)
+ defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
+ else
+ defsize = server->maxBuf - sizeof(READ_RSP);
+
+ rsize = ctx->rsize ? ctx->rsize : defsize;
+
+ /*
+ * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
+ * the client's MaxBufferSize.
+ */
+ if (!(server->capabilities & CAP_LARGE_READ_X))
+ rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
+
+ /* hard limit of CIFS_MAX_RSIZE */
+ rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
+
+ return rsize;
+}
+
+static void
+cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb)
+{
+ CIFSSMBQFSDeviceInfo(xid, tcon);
+ CIFSSMBQFSAttributeInfo(xid, tcon);
+}
+
+static int
+cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path)
+{
+ int rc;
+ FILE_ALL_INFO *file_info;
+
+ file_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (file_info == NULL)
+ return -ENOMEM;
+
+ rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info,
+ 0 /* not legacy */, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+
+ if (rc == -EOPNOTSUPP || rc == -EINVAL)
+ rc = SMBQueryInformation(xid, tcon, full_path, file_info,
+ cifs_sb->local_nls, cifs_remap(cifs_sb));
+ kfree(file_info);
+ return rc;
+}
+
+static int cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ struct cifs_open_info_data *data, bool *adjustTZ, bool *symlink)
+{
+ int rc;
+ FILE_ALL_INFO fi = {};
+
+ *symlink = false;
+
+ /* could do find first instead but this returns more info */
+ rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ /*
+ * BB optimize code so we do not make the above call when server claims
+ * no NT SMB support and the above call failed at least once - set flag
+ * in tcon or mount.
+ */
+ if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
+ rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ *adjustTZ = true;
+ }
+
+ if (!rc) {
+ int tmprc;
+ int oplock = 0;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+
+ move_cifs_info_to_smb2(&data->fi, &fi);
+
+ if (!(le32_to_cpu(fi.Attributes) & ATTR_REPARSE))
+ return 0;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .disposition = FILE_OPEN,
+ .path = full_path,
+ .fid = &fid,
+ };
+
+ /* Need to check if this is a symbolic link or not */
+ tmprc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (tmprc == -EOPNOTSUPP)
+ *symlink = true;
+ else if (tmprc == 0)
+ CIFSSMBClose(xid, tcon, fid.netfid);
+ }
+
+ return rc;
+}
+
+static int cifs_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ u64 *uniqueid, struct cifs_open_info_data *unused)
+{
+ /*
+ * We can not use the IndexNumber field by default from Windows or
+ * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
+ * CIFS spec claims that this value is unique within the scope of a
+ * share, and the windows docs hint that it's actually unique
+ * per-machine.
+ *
+ * There may be higher info levels that work but are there Windows
+ * server or network appliances for which IndexNumber field is not
+ * guaranteed unique?
+ */
+ return CIFSGetSrvInodeNumber(xid, tcon, full_path, uniqueid,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+}
+
+static int cifs_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, struct cifs_open_info_data *data)
+{
+ int rc;
+ FILE_ALL_INFO fi = {};
+
+ if (cfile->symlink_target) {
+ data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
+ if (!data->symlink_target)
+ return -ENOMEM;
+ }
+
+ rc = CIFSSMBQFileInfo(xid, tcon, cfile->fid.netfid, &fi);
+ if (!rc)
+ move_cifs_info_to_smb2(&data->fi, &fi);
+ return rc;
+}
+
+static void
+cifs_clear_stats(struct cifs_tcon *tcon)
+{
+ atomic_set(&tcon->stats.cifs_stats.num_writes, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_reads, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_flushes, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_oplock_brks, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_opens, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_posixopens, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_posixmkdirs, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_closes, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_deletes, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_mkdirs, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_rmdirs, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_renames, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_t2renames, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_ffirst, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_fnext, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_fclose, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_hardlinks, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_symlinks, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_locks, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_acl_get, 0);
+ atomic_set(&tcon->stats.cifs_stats.num_acl_set, 0);
+}
+
+static void
+cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
+{
+ seq_printf(m, " Oplocks breaks: %d",
+ atomic_read(&tcon->stats.cifs_stats.num_oplock_brks));
+ seq_printf(m, "\nReads: %d Bytes: %llu",
+ atomic_read(&tcon->stats.cifs_stats.num_reads),
+ (long long)(tcon->bytes_read));
+ seq_printf(m, "\nWrites: %d Bytes: %llu",
+ atomic_read(&tcon->stats.cifs_stats.num_writes),
+ (long long)(tcon->bytes_written));
+ seq_printf(m, "\nFlushes: %d",
+ atomic_read(&tcon->stats.cifs_stats.num_flushes));
+ seq_printf(m, "\nLocks: %d HardLinks: %d Symlinks: %d",
+ atomic_read(&tcon->stats.cifs_stats.num_locks),
+ atomic_read(&tcon->stats.cifs_stats.num_hardlinks),
+ atomic_read(&tcon->stats.cifs_stats.num_symlinks));
+ seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d",
+ atomic_read(&tcon->stats.cifs_stats.num_opens),
+ atomic_read(&tcon->stats.cifs_stats.num_closes),
+ atomic_read(&tcon->stats.cifs_stats.num_deletes));
+ seq_printf(m, "\nPosix Opens: %d Posix Mkdirs: %d",
+ atomic_read(&tcon->stats.cifs_stats.num_posixopens),
+ atomic_read(&tcon->stats.cifs_stats.num_posixmkdirs));
+ seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
+ atomic_read(&tcon->stats.cifs_stats.num_mkdirs),
+ atomic_read(&tcon->stats.cifs_stats.num_rmdirs));
+ seq_printf(m, "\nRenames: %d T2 Renames %d",
+ atomic_read(&tcon->stats.cifs_stats.num_renames),
+ atomic_read(&tcon->stats.cifs_stats.num_t2renames));
+ seq_printf(m, "\nFindFirst: %d FNext %d FClose %d",
+ atomic_read(&tcon->stats.cifs_stats.num_ffirst),
+ atomic_read(&tcon->stats.cifs_stats.num_fnext),
+ atomic_read(&tcon->stats.cifs_stats.num_fclose));
+}
+
+static void
+cifs_mkdir_setinfo(struct inode *inode, const char *full_path,
+ struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
+ const unsigned int xid)
+{
+ FILE_BASIC_INFO info;
+ struct cifsInodeInfo *cifsInode;
+ u32 dosattrs;
+ int rc;
+
+ memset(&info, 0, sizeof(info));
+ cifsInode = CIFS_I(inode);
+ dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
+ info.Attributes = cpu_to_le32(dosattrs);
+ rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls,
+ cifs_sb);
+ if (rc == 0)
+ cifsInode->cifsAttrs = dosattrs;
+}
+
+static int cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
+ void *buf)
+{
+ struct cifs_open_info_data *data = buf;
+ FILE_ALL_INFO fi = {};
+ int rc;
+
+ if (!(oparms->tcon->ses->capabilities & CAP_NT_SMBS))
+ rc = SMBLegacyOpen(xid, oparms->tcon, oparms->path,
+ oparms->disposition,
+ oparms->desired_access,
+ oparms->create_options,
+ &oparms->fid->netfid, oplock, &fi,
+ oparms->cifs_sb->local_nls,
+ cifs_remap(oparms->cifs_sb));
+ else
+ rc = CIFS_open(xid, oparms, oplock, &fi);
+
+ if (!rc && data)
+ move_cifs_info_to_smb2(&data->fi, &fi);
+
+ return rc;
+}
+
+static void
+cifs_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
+{
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ cfile->fid.netfid = fid->netfid;
+ cifs_set_oplock_level(cinode, oplock);
+ cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
+}
+
+static void
+cifs_close_file(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid)
+{
+ CIFSSMBClose(xid, tcon, fid->netfid);
+}
+
+static int
+cifs_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid)
+{
+ return CIFSSMBFlush(xid, tcon, fid->netfid);
+}
+
+static int
+cifs_sync_read(const unsigned int xid, struct cifs_fid *pfid,
+ struct cifs_io_parms *parms, unsigned int *bytes_read,
+ char **buf, int *buf_type)
+{
+ parms->netfid = pfid->netfid;
+ return CIFSSMBRead(xid, parms, bytes_read, buf, buf_type);
+}
+
+static int
+cifs_sync_write(const unsigned int xid, struct cifs_fid *pfid,
+ struct cifs_io_parms *parms, unsigned int *written,
+ struct kvec *iov, unsigned long nr_segs)
+{
+
+ parms->netfid = pfid->netfid;
+ return CIFSSMBWrite2(xid, parms, written, iov, nr_segs);
+}
+
+static int
+smb_set_file_info(struct inode *inode, const char *full_path,
+ FILE_BASIC_INFO *buf, const unsigned int xid)
+{
+ int oplock = 0;
+ int rc;
+ __u32 netpid;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ struct cifsFileInfo *open_file;
+ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink = NULL;
+ struct cifs_tcon *tcon;
+
+ /* if the file is already open for write, just use that fileid */
+ open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
+ if (open_file) {
+ fid.netfid = open_file->fid.netfid;
+ netpid = open_file->pid;
+ tcon = tlink_tcon(open_file->tlink);
+ goto set_via_filehandle;
+ }
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink)) {
+ rc = PTR_ERR(tlink);
+ tlink = NULL;
+ goto out;
+ }
+ tcon = tlink_tcon(tlink);
+
+ rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls,
+ cifs_sb);
+ if (rc == 0) {
+ cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
+ goto out;
+ } else if (rc != -EOPNOTSUPP && rc != -EINVAL) {
+ goto out;
+ }
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
+ .disposition = FILE_OPEN,
+ .path = full_path,
+ .fid = &fid,
+ };
+
+ cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n");
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (rc != 0) {
+ if (rc == -EIO)
+ rc = -EINVAL;
+ goto out;
+ }
+
+ netpid = current->tgid;
+
+set_via_filehandle:
+ rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid);
+ if (!rc)
+ cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
+
+ if (open_file == NULL)
+ CIFSSMBClose(xid, tcon, fid.netfid);
+ else
+ cifsFileInfo_put(open_file);
+out:
+ if (tlink != NULL)
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+static int
+cifs_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile)
+{
+ return CIFSSMB_set_compression(xid, tcon, cfile->fid.netfid);
+}
+
+static int
+cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *path, struct cifs_sb_info *cifs_sb,
+ struct cifs_fid *fid, __u16 search_flags,
+ struct cifs_search_info *srch_inf)
+{
+ int rc;
+
+ rc = CIFSFindFirst(xid, tcon, path, cifs_sb,
+ &fid->netfid, search_flags, srch_inf, true);
+ if (rc)
+ cifs_dbg(FYI, "find first failed=%d\n", rc);
+ return rc;
+}
+
+static int
+cifs_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid, __u16 search_flags,
+ struct cifs_search_info *srch_inf)
+{
+ return CIFSFindNext(xid, tcon, fid->netfid, search_flags, srch_inf);
+}
+
+static int
+cifs_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid)
+{
+ return CIFSFindClose(xid, tcon, fid->netfid);
+}
+
+static int
+cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
+ __u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
+{
+ return CIFSSMBLock(0, tcon, net_fid, current->tgid, 0, 0, 0, 0,
+ LOCKING_ANDX_OPLOCK_RELEASE, false, CIFS_CACHE_READ(cinode) ? 1 : 0);
+}
+
+static int
+cifs_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
+{
+ int rc = -EOPNOTSUPP;
+
+ buf->f_type = CIFS_SUPER_MAGIC;
+
+ /*
+ * We could add a second check for a QFS Unix capability bit
+ */
+ if ((tcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability)))
+ rc = CIFSSMBQFSPosixInfo(xid, tcon, buf);
+
+ /*
+ * Only need to call the old QFSInfo if failed on newer one,
+ * e.g. by OS/2.
+ **/
+ if (rc && (tcon->ses->capabilities & CAP_NT_SMBS))
+ rc = CIFSSMBQFSInfo(xid, tcon, buf);
+
+ /*
+ * Some old Windows servers also do not support level 103, retry with
+ * older level one if old server failed the previous call or we
+ * bypassed it because we detected that this was an older LANMAN sess
+ */
+ if (rc)
+ rc = SMBOldQFSInfo(xid, tcon, buf);
+ return rc;
+}
+
+static int
+cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
+ __u64 length, __u32 type, int lock, int unlock, bool wait)
+{
+ return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->fid.netfid,
+ current->tgid, length, offset, unlock, lock,
+ (__u8)type, wait, 0);
+}
+
+static int
+cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *searchName, char **symlinkinfo,
+ const struct nls_table *nls_codepage)
+{
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ int rc;
+ struct dfs_info3_param referral = {0};
+
+ rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage, &referral,
+ 0);
+
+ if (!rc) {
+ *symlinkinfo = kstrdup(referral.node_name, GFP_KERNEL);
+ free_dfs_info_param(&referral);
+ if (!*symlinkinfo)
+ rc = -ENOMEM;
+ }
+ return rc;
+#else /* No DFS support */
+ return -EREMOTE;
+#endif
+}
+
+static int
+cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ char **target_path, bool is_reparse_point)
+{
+ int rc;
+ int oplock = 0;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+
+ cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
+
+ if (is_reparse_point) {
+ cifs_dbg(VFS, "reparse points not handled for SMB1 symlinks\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* Check for unix extensions */
+ if (cap_unix(tcon->ses)) {
+ rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ if (rc == -EREMOTE)
+ rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
+ target_path,
+ cifs_sb->local_nls);
+
+ goto out;
+ }
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .create_options = cifs_create_options(cifs_sb,
+ OPEN_REPARSE_POINT),
+ .disposition = FILE_OPEN,
+ .path = full_path,
+ .fid = &fid,
+ };
+
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (rc)
+ goto out;
+
+ rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path,
+ cifs_sb->local_nls);
+ if (rc)
+ goto out_close;
+
+ convert_delimiter(*target_path, '/');
+out_close:
+ CIFSSMBClose(xid, tcon, fid.netfid);
+out:
+ if (!rc)
+ cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+ return rc;
+}
+
+static bool
+cifs_is_read_op(__u32 oplock)
+{
+ return oplock == OPLOCK_READ;
+}
+
+static unsigned int
+cifs_wp_retry_size(struct inode *inode)
+{
+ return CIFS_SB(inode->i_sb)->ctx->wsize;
+}
+
+static bool
+cifs_dir_needs_close(struct cifsFileInfo *cfile)
+{
+ return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
+}
+
+static bool
+cifs_can_echo(struct TCP_Server_Info *server)
+{
+ if (server->tcpStatus == CifsGood)
+ return true;
+
+ return false;
+}
+
+static int
+cifs_make_node(unsigned int xid, struct inode *inode,
+ struct dentry *dentry, struct cifs_tcon *tcon,
+ const char *full_path, umode_t mode, dev_t dev)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct inode *newinode = NULL;
+ int rc = -EPERM;
+ struct cifs_open_info_data buf = {};
+ struct cifs_io_parms io_parms;
+ __u32 oplock = 0;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ unsigned int bytes_written;
+ struct win_dev *pdev;
+ struct kvec iov[2];
+
+ if (tcon->unix_ext) {
+ /*
+ * SMB1 Unix Extensions: requires server support but
+ * works with all special files
+ */
+ struct cifs_unix_set_info_args args = {
+ .mode = mode & ~current_umask(),
+ .ctime = NO_CHANGE_64,
+ .atime = NO_CHANGE_64,
+ .mtime = NO_CHANGE_64,
+ .device = dev,
+ };
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ args.uid = current_fsuid();
+ args.gid = current_fsgid();
+ } else {
+ args.uid = INVALID_UID; /* no change */
+ args.gid = INVALID_GID; /* no change */
+ }
+ rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+ if (rc)
+ return rc;
+
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
+ inode->i_sb, xid);
+
+ if (rc == 0)
+ d_instantiate(dentry, newinode);
+ return rc;
+ }
+
+ /*
+ * SMB1 SFU emulation: should work with all servers, but only
+ * support block and char device (no socket & fifo)
+ */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
+ return rc;
+
+ if (!S_ISCHR(mode) && !S_ISBLK(mode))
+ return rc;
+
+ cifs_dbg(FYI, "sfu compat create special file\n");
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = GENERIC_WRITE,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
+ CREATE_OPTION_SPECIAL),
+ .disposition = FILE_CREATE,
+ .path = full_path,
+ .fid = &fid,
+ };
+
+ if (tcon->ses->server->oplocks)
+ oplock = REQ_OPLOCK;
+ else
+ oplock = 0;
+ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
+ if (rc)
+ return rc;
+
+ /*
+ * BB Do not bother to decode buf since no local inode yet to put
+ * timestamps in, but we can reuse it safely.
+ */
+
+ pdev = (struct win_dev *)&buf.fi;
+ io_parms.pid = current->tgid;
+ io_parms.tcon = tcon;
+ io_parms.offset = 0;
+ io_parms.length = sizeof(struct win_dev);
+ iov[1].iov_base = &buf.fi;
+ iov[1].iov_len = sizeof(struct win_dev);
+ if (S_ISCHR(mode)) {
+ memcpy(pdev->type, "IntxCHR", 8);
+ pdev->major = cpu_to_le64(MAJOR(dev));
+ pdev->minor = cpu_to_le64(MINOR(dev));
+ rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
+ &bytes_written, iov, 1);
+ } else if (S_ISBLK(mode)) {
+ memcpy(pdev->type, "IntxBLK", 8);
+ pdev->major = cpu_to_le64(MAJOR(dev));
+ pdev->minor = cpu_to_le64(MINOR(dev));
+ rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
+ &bytes_written, iov, 1);
+ }
+ tcon->ses->server->ops->close(xid, tcon, &fid);
+ d_drop(dentry);
+
+ /* FIXME: add code here to set EAs */
+
+ cifs_free_open_info(&buf);
+ return rc;
+}
+
+
+
+struct smb_version_operations smb1_operations = {
+ .send_cancel = send_nt_cancel,
+ .compare_fids = cifs_compare_fids,
+ .setup_request = cifs_setup_request,
+ .setup_async_request = cifs_setup_async_request,
+ .check_receive = cifs_check_receive,
+ .add_credits = cifs_add_credits,
+ .set_credits = cifs_set_credits,
+ .get_credits_field = cifs_get_credits_field,
+ .get_credits = cifs_get_credits,
+ .wait_mtu_credits = cifs_wait_mtu_credits,
+ .get_next_mid = cifs_get_next_mid,
+ .read_data_offset = cifs_read_data_offset,
+ .read_data_length = cifs_read_data_length,
+ .map_error = map_smb_to_linux_error,
+ .find_mid = cifs_find_mid,
+ .check_message = checkSMB,
+ .dump_detail = cifs_dump_detail,
+ .clear_stats = cifs_clear_stats,
+ .print_stats = cifs_print_stats,
+ .is_oplock_break = is_valid_oplock_break,
+ .downgrade_oplock = cifs_downgrade_oplock,
+ .check_trans2 = cifs_check_trans2,
+ .need_neg = cifs_need_neg,
+ .negotiate = cifs_negotiate,
+ .negotiate_wsize = cifs_negotiate_wsize,
+ .negotiate_rsize = cifs_negotiate_rsize,
+ .sess_setup = CIFS_SessSetup,
+ .logoff = CIFSSMBLogoff,
+ .tree_connect = CIFSTCon,
+ .tree_disconnect = CIFSSMBTDis,
+ .get_dfs_refer = CIFSGetDFSRefer,
+ .qfs_tcon = cifs_qfs_tcon,
+ .is_path_accessible = cifs_is_path_accessible,
+ .can_echo = cifs_can_echo,
+ .query_path_info = cifs_query_path_info,
+ .query_file_info = cifs_query_file_info,
+ .get_srv_inum = cifs_get_srv_inum,
+ .set_path_size = CIFSSMBSetEOF,
+ .set_file_size = CIFSSMBSetFileSize,
+ .set_file_info = smb_set_file_info,
+ .set_compression = cifs_set_compression,
+ .echo = CIFSSMBEcho,
+ .mkdir = CIFSSMBMkDir,
+ .mkdir_setinfo = cifs_mkdir_setinfo,
+ .rmdir = CIFSSMBRmDir,
+ .unlink = CIFSSMBDelFile,
+ .rename_pending_delete = cifs_rename_pending_delete,
+ .rename = CIFSSMBRename,
+ .create_hardlink = CIFSCreateHardLink,
+ .query_symlink = cifs_query_symlink,
+ .open = cifs_open_file,
+ .set_fid = cifs_set_fid,
+ .close = cifs_close_file,
+ .flush = cifs_flush_file,
+ .async_readv = cifs_async_readv,
+ .async_writev = cifs_async_writev,
+ .sync_read = cifs_sync_read,
+ .sync_write = cifs_sync_write,
+ .query_dir_first = cifs_query_dir_first,
+ .query_dir_next = cifs_query_dir_next,
+ .close_dir = cifs_close_dir,
+ .calc_smb_size = smbCalcSize,
+ .oplock_response = cifs_oplock_response,
+ .queryfs = cifs_queryfs,
+ .mand_lock = cifs_mand_lock,
+ .mand_unlock_range = cifs_unlock_range,
+ .push_mand_locks = cifs_push_mandatory_locks,
+ .query_mf_symlink = cifs_query_mf_symlink,
+ .create_mf_symlink = cifs_create_mf_symlink,
+ .is_read_op = cifs_is_read_op,
+ .wp_retry_size = cifs_wp_retry_size,
+ .dir_needs_close = cifs_dir_needs_close,
+ .select_sectype = cifs_select_sectype,
+#ifdef CONFIG_CIFS_XATTR
+ .query_all_EAs = CIFSSMBQAllEAs,
+ .set_EA = CIFSSMBSetEA,
+#endif /* CIFS_XATTR */
+ .get_acl = get_cifs_acl,
+ .get_acl_by_fid = get_cifs_acl_by_fid,
+ .set_acl = set_cifs_acl,
+ .make_node = cifs_make_node,
+};
+
+struct smb_version_values smb1_values = {
+ .version_string = SMB1_VERSION_STRING,
+ .protocol_id = SMB10_PROT_ID,
+ .large_lock_type = LOCKING_ANDX_LARGE_FILES,
+ .exclusive_lock_type = 0,
+ .shared_lock_type = LOCKING_ANDX_SHARED_LOCK,
+ .unlock_lock_type = 0,
+ .header_preamble_size = 4,
+ .header_size = sizeof(struct smb_hdr),
+ .max_header_size = MAX_CIFS_HDR_SIZE,
+ .read_rsp_size = sizeof(READ_RSP),
+ .lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX),
+ .cap_unix = CAP_UNIX,
+ .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND,
+ .cap_large_files = CAP_LARGE_FILES,
+ .signing_enabled = SECMODE_SIGN_ENABLED,
+ .signing_required = SECMODE_SIGN_REQUIRED,
+};
diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c
new file mode 100644
index 000000000000..ba6cc50af390
--- /dev/null
+++ b/fs/smb/client/smb2file.c
@@ -0,0 +1,371 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002, 2011
+ * Author(s): Steve French (sfrench@us.ibm.com),
+ * Pavel Shilovsky ((pshilovsky@samba.org) 2012
+ *
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <asm/div64.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifs_unicode.h"
+#include "fscache.h"
+#include "smb2proto.h"
+#include "smb2status.h"
+
+static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov)
+{
+ struct smb2_err_rsp *err = iov->iov_base;
+ struct smb2_symlink_err_rsp *sym = ERR_PTR(-EINVAL);
+ u32 len;
+
+ if (err->ErrorContextCount) {
+ struct smb2_error_context_rsp *p, *end;
+
+ len = (u32)err->ErrorContextCount * (offsetof(struct smb2_error_context_rsp,
+ ErrorContextData) +
+ sizeof(struct smb2_symlink_err_rsp));
+ if (le32_to_cpu(err->ByteCount) < len || iov->iov_len < len + sizeof(*err))
+ return ERR_PTR(-EINVAL);
+
+ p = (struct smb2_error_context_rsp *)err->ErrorData;
+ end = (struct smb2_error_context_rsp *)((u8 *)err + iov->iov_len);
+ do {
+ if (le32_to_cpu(p->ErrorId) == SMB2_ERROR_ID_DEFAULT) {
+ sym = (struct smb2_symlink_err_rsp *)&p->ErrorContextData;
+ break;
+ }
+ cifs_dbg(FYI, "%s: skipping unhandled error context: 0x%x\n",
+ __func__, le32_to_cpu(p->ErrorId));
+
+ len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8);
+ p = (struct smb2_error_context_rsp *)((u8 *)&p->ErrorContextData + len);
+ } while (p < end);
+ } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) &&
+ iov->iov_len >= SMB2_SYMLINK_STRUCT_SIZE) {
+ sym = (struct smb2_symlink_err_rsp *)err->ErrorData;
+ }
+
+ if (!IS_ERR(sym) && (le32_to_cpu(sym->SymLinkErrorTag) != SYMLINK_ERROR_TAG ||
+ le32_to_cpu(sym->ReparseTag) != IO_REPARSE_TAG_SYMLINK))
+ sym = ERR_PTR(-EINVAL);
+
+ return sym;
+}
+
+int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path)
+{
+ struct smb2_symlink_err_rsp *sym;
+ unsigned int sub_offs, sub_len;
+ unsigned int print_offs, print_len;
+ char *s;
+
+ if (!cifs_sb || !iov || !iov->iov_base || !iov->iov_len || !path)
+ return -EINVAL;
+
+ sym = symlink_data(iov);
+ if (IS_ERR(sym))
+ return PTR_ERR(sym);
+
+ sub_len = le16_to_cpu(sym->SubstituteNameLength);
+ sub_offs = le16_to_cpu(sym->SubstituteNameOffset);
+ print_len = le16_to_cpu(sym->PrintNameLength);
+ print_offs = le16_to_cpu(sym->PrintNameOffset);
+
+ if (iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offs + sub_len ||
+ iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + print_offs + print_len)
+ return -EINVAL;
+
+ s = cifs_strndup_from_utf16((char *)sym->PathBuffer + sub_offs, sub_len, true,
+ cifs_sb->local_nls);
+ if (!s)
+ return -ENOMEM;
+ convert_delimiter(s, '/');
+ cifs_dbg(FYI, "%s: symlink target: %s\n", __func__, s);
+
+ *path = s;
+ return 0;
+}
+
+int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, void *buf)
+{
+ int rc;
+ __le16 *smb2_path;
+ __u8 smb2_oplock;
+ struct cifs_open_info_data *data = buf;
+ struct smb2_file_all_info file_info = {};
+ struct smb2_file_all_info *smb2_data = data ? &file_info : NULL;
+ struct kvec err_iov = {};
+ int err_buftype = CIFS_NO_BUFFER;
+ struct cifs_fid *fid = oparms->fid;
+ struct network_resiliency_req nr_ioctl_req;
+
+ smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb);
+ if (smb2_path == NULL)
+ return -ENOMEM;
+
+ oparms->desired_access |= FILE_READ_ATTRIBUTES;
+ smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH;
+
+ rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL, &err_iov,
+ &err_buftype);
+ if (rc && data) {
+ struct smb2_hdr *hdr = err_iov.iov_base;
+
+ if (unlikely(!err_iov.iov_base || err_buftype == CIFS_NO_BUFFER))
+ goto out;
+ if (hdr->Status == STATUS_STOPPED_ON_SYMLINK) {
+ rc = smb2_parse_symlink_response(oparms->cifs_sb, &err_iov,
+ &data->symlink_target);
+ if (!rc) {
+ memset(smb2_data, 0, sizeof(*smb2_data));
+ oparms->create_options |= OPEN_REPARSE_POINT;
+ rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data,
+ NULL, NULL, NULL);
+ oparms->create_options &= ~OPEN_REPARSE_POINT;
+ }
+ }
+ }
+
+ if (rc)
+ goto out;
+
+ if (oparms->tcon->use_resilient) {
+ /* default timeout is 0, servers pick default (120 seconds) */
+ nr_ioctl_req.Timeout =
+ cpu_to_le32(oparms->tcon->handle_timeout);
+ nr_ioctl_req.Reserved = 0;
+ rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
+ fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
+ (char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
+ CIFSMaxBufSize, NULL, NULL /* no return info */);
+ if (rc == -EOPNOTSUPP) {
+ cifs_dbg(VFS,
+ "resiliency not supported by server, disabling\n");
+ oparms->tcon->use_resilient = false;
+ } else if (rc)
+ cifs_dbg(FYI, "error %d setting resiliency\n", rc);
+
+ rc = 0;
+ }
+
+ if (smb2_data) {
+ /* if open response does not have IndexNumber field - get it */
+ if (smb2_data->IndexNumber == 0) {
+ rc = SMB2_get_srv_num(xid, oparms->tcon,
+ fid->persistent_fid,
+ fid->volatile_fid,
+ &smb2_data->IndexNumber);
+ if (rc) {
+ /*
+ * let get_inode_info disable server inode
+ * numbers
+ */
+ smb2_data->IndexNumber = 0;
+ rc = 0;
+ }
+ }
+ memcpy(&data->fi, smb2_data, sizeof(data->fi));
+ }
+
+ *oplock = smb2_oplock;
+out:
+ free_rsp_buf(err_buftype, err_iov.iov_base);
+ kfree(smb2_path);
+ return rc;
+}
+
+int
+smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
+ const unsigned int xid)
+{
+ int rc = 0, stored_rc;
+ unsigned int max_num, num = 0, max_buf;
+ struct smb2_lock_element *buf, *cur;
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ struct cifsLockInfo *li, *tmp;
+ __u64 length = 1 + flock->fl_end - flock->fl_start;
+ struct list_head tmp_llist;
+
+ INIT_LIST_HEAD(&tmp_llist);
+
+ /*
+ * Accessing maxBuf is racy with cifs_reconnect - need to store value
+ * and check it before using.
+ */
+ max_buf = tcon->ses->server->maxBuf;
+ if (max_buf < sizeof(struct smb2_lock_element))
+ return -EINVAL;
+
+ BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
+ max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
+ max_num = max_buf / sizeof(struct smb2_lock_element);
+ buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ cur = buf;
+
+ cifs_down_write(&cinode->lock_sem);
+ list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
+ if (flock->fl_start > li->offset ||
+ (flock->fl_start + length) <
+ (li->offset + li->length))
+ continue;
+ if (current->tgid != li->pid)
+ /*
+ * flock and OFD lock are associated with an open
+ * file description, not the process.
+ */
+ if (!(flock->fl_flags & (FL_FLOCK | FL_OFDLCK)))
+ continue;
+ if (cinode->can_cache_brlcks) {
+ /*
+ * We can cache brlock requests - simply remove a lock
+ * from the file's list.
+ */
+ list_del(&li->llist);
+ cifs_del_lock_waiters(li);
+ kfree(li);
+ continue;
+ }
+ cur->Length = cpu_to_le64(li->length);
+ cur->Offset = cpu_to_le64(li->offset);
+ cur->Flags = cpu_to_le32(SMB2_LOCKFLAG_UNLOCK);
+ /*
+ * We need to save a lock here to let us add it again to the
+ * file's list if the unlock range request fails on the server.
+ */
+ list_move(&li->llist, &tmp_llist);
+ if (++num == max_num) {
+ stored_rc = smb2_lockv(xid, tcon,
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ current->tgid, num, buf);
+ if (stored_rc) {
+ /*
+ * We failed on the unlock range request - add
+ * all locks from the tmp list to the head of
+ * the file's list.
+ */
+ cifs_move_llist(&tmp_llist,
+ &cfile->llist->locks);
+ rc = stored_rc;
+ } else
+ /*
+ * The unlock range request succeed - free the
+ * tmp list.
+ */
+ cifs_free_llist(&tmp_llist);
+ cur = buf;
+ num = 0;
+ } else
+ cur++;
+ }
+ if (num) {
+ stored_rc = smb2_lockv(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, current->tgid,
+ num, buf);
+ if (stored_rc) {
+ cifs_move_llist(&tmp_llist, &cfile->llist->locks);
+ rc = stored_rc;
+ } else
+ cifs_free_llist(&tmp_llist);
+ }
+ up_write(&cinode->lock_sem);
+
+ kfree(buf);
+ return rc;
+}
+
+static int
+smb2_push_mand_fdlocks(struct cifs_fid_locks *fdlocks, const unsigned int xid,
+ struct smb2_lock_element *buf, unsigned int max_num)
+{
+ int rc = 0, stored_rc;
+ struct cifsFileInfo *cfile = fdlocks->cfile;
+ struct cifsLockInfo *li;
+ unsigned int num = 0;
+ struct smb2_lock_element *cur = buf;
+ struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
+
+ list_for_each_entry(li, &fdlocks->locks, llist) {
+ cur->Length = cpu_to_le64(li->length);
+ cur->Offset = cpu_to_le64(li->offset);
+ cur->Flags = cpu_to_le32(li->type |
+ SMB2_LOCKFLAG_FAIL_IMMEDIATELY);
+ if (++num == max_num) {
+ stored_rc = smb2_lockv(xid, tcon,
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ current->tgid, num, buf);
+ if (stored_rc)
+ rc = stored_rc;
+ cur = buf;
+ num = 0;
+ } else
+ cur++;
+ }
+ if (num) {
+ stored_rc = smb2_lockv(xid, tcon,
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ current->tgid, num, buf);
+ if (stored_rc)
+ rc = stored_rc;
+ }
+
+ return rc;
+}
+
+int
+smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
+{
+ int rc = 0, stored_rc;
+ unsigned int xid;
+ unsigned int max_num, max_buf;
+ struct smb2_lock_element *buf;
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ struct cifs_fid_locks *fdlocks;
+
+ xid = get_xid();
+
+ /*
+ * Accessing maxBuf is racy with cifs_reconnect - need to store value
+ * and check it for zero before using.
+ */
+ max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf;
+ if (max_buf < sizeof(struct smb2_lock_element)) {
+ free_xid(xid);
+ return -EINVAL;
+ }
+
+ BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
+ max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
+ max_num = max_buf / sizeof(struct smb2_lock_element);
+ buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
+ if (!buf) {
+ free_xid(xid);
+ return -ENOMEM;
+ }
+
+ list_for_each_entry(fdlocks, &cinode->llist, llist) {
+ stored_rc = smb2_push_mand_fdlocks(fdlocks, xid, buf, max_num);
+ if (stored_rc)
+ rc = stored_rc;
+ }
+
+ kfree(buf);
+ free_xid(xid);
+ return rc;
+}
diff --git a/fs/smb/client/smb2glob.h b/fs/smb/client/smb2glob.h
new file mode 100644
index 000000000000..82e916ad167c
--- /dev/null
+++ b/fs/smb/client/smb2glob.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Definitions for various global variables and structures
+ *
+ * Copyright (C) International Business Machines Corp., 2002, 2011
+ * Etersoft, 2012
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Jeremy Allison (jra@samba.org)
+ * Pavel Shilovsky (pshilovsky@samba.org) 2012
+ *
+ */
+#ifndef _SMB2_GLOB_H
+#define _SMB2_GLOB_H
+
+/*
+ *****************************************************************
+ * Constants go here
+ *****************************************************************
+ */
+
+/*
+ * Identifiers for functions that use the open, operation, close pattern
+ * in smb2inode.c:smb2_compound_op()
+ */
+#define SMB2_OP_SET_DELETE 1
+#define SMB2_OP_SET_INFO 2
+#define SMB2_OP_QUERY_INFO 3
+#define SMB2_OP_QUERY_DIR 4
+#define SMB2_OP_MKDIR 5
+#define SMB2_OP_RENAME 6
+#define SMB2_OP_DELETE 7
+#define SMB2_OP_HARDLINK 8
+#define SMB2_OP_SET_EOF 9
+#define SMB2_OP_RMDIR 10
+#define SMB2_OP_POSIX_QUERY_INFO 11
+
+/* Used when constructing chained read requests. */
+#define CHAINED_REQUEST 1
+#define START_OF_CHAIN 2
+#define END_OF_CHAIN 4
+#define RELATED_REQUEST 8
+
+#endif /* _SMB2_GLOB_H */
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
new file mode 100644
index 000000000000..c97e049e29dd
--- /dev/null
+++ b/fs/smb/client/smb2inode.c
@@ -0,0 +1,799 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002, 2011
+ * Etersoft, 2012
+ * Author(s): Pavel Shilovsky (pshilovsky@samba.org),
+ * Steve French (sfrench@us.ibm.com)
+ *
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <asm/div64.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifs_unicode.h"
+#include "fscache.h"
+#include "smb2glob.h"
+#include "smb2pdu.h"
+#include "smb2proto.h"
+#include "cached_dir.h"
+#include "smb2status.h"
+
+static void
+free_set_inf_compound(struct smb_rqst *rqst)
+{
+ if (rqst[1].rq_iov)
+ SMB2_set_info_free(&rqst[1]);
+ if (rqst[2].rq_iov)
+ SMB2_close_free(&rqst[2]);
+}
+
+
+struct cop_vars {
+ struct cifs_open_parms oparms;
+ struct kvec rsp_iov[3];
+ struct smb_rqst rqst[3];
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+ struct kvec qi_iov[1];
+ struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
+ struct kvec close_iov[1];
+ struct smb2_file_rename_info rename_info;
+ struct smb2_file_link_info link_info;
+};
+
+/*
+ * note: If cfile is passed, the reference to it is dropped here.
+ * So make sure that you do not reuse cfile after return from this func.
+ *
+ * If passing @err_iov and @err_buftype, ensure to make them both large enough (>= 3) to hold all
+ * error responses. Caller is also responsible for freeing them up.
+ */
+static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ __u32 desired_access, __u32 create_disposition, __u32 create_options,
+ umode_t mode, void *ptr, int command, struct cifsFileInfo *cfile,
+ struct kvec *err_iov, int *err_buftype)
+{
+ struct cop_vars *vars = NULL;
+ struct kvec *rsp_iov;
+ struct smb_rqst *rqst;
+ int rc;
+ __le16 *utf16_path = NULL;
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_fid fid;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server;
+ int num_rqst = 0;
+ int resp_buftype[3];
+ struct smb2_query_info_rsp *qi_rsp = NULL;
+ struct cifs_open_info_data *idata;
+ int flags = 0;
+ __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0};
+ unsigned int size[2];
+ void *data[2];
+ int len;
+
+ vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
+ if (vars == NULL)
+ return -ENOMEM;
+ rqst = &vars->rqst[0];
+ rsp_iov = &vars->rsp_iov[0];
+
+ server = cifs_pick_channel(ses);
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
+
+ /* We already have a handle so we can skip the open */
+ if (cfile)
+ goto after_open;
+
+ /* Open */
+ utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
+ if (!utf16_path) {
+ rc = -ENOMEM;
+ goto finished;
+ }
+
+ vars->oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = full_path,
+ .desired_access = desired_access,
+ .disposition = create_disposition,
+ .create_options = cifs_create_options(cifs_sb, create_options),
+ .fid = &fid,
+ .mode = mode,
+ .cifs_sb = cifs_sb,
+ };
+
+ rqst[num_rqst].rq_iov = &vars->open_iov[0];
+ rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE;
+ rc = SMB2_open_init(tcon, server,
+ &rqst[num_rqst], &oplock, &vars->oparms,
+ utf16_path);
+ kfree(utf16_path);
+ if (rc)
+ goto finished;
+
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ after_open:
+ num_rqst++;
+ rc = 0;
+
+ /* Operation */
+ switch (command) {
+ case SMB2_OP_QUERY_INFO:
+ rqst[num_rqst].rq_iov = &vars->qi_iov[0];
+ rqst[num_rqst].rq_nvec = 1;
+
+ if (cfile)
+ rc = SMB2_query_info_init(tcon, server,
+ &rqst[num_rqst],
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ FILE_ALL_INFORMATION,
+ SMB2_O_INFO_FILE, 0,
+ sizeof(struct smb2_file_all_info) +
+ PATH_MAX * 2, 0, NULL);
+ else {
+ rc = SMB2_query_info_init(tcon, server,
+ &rqst[num_rqst],
+ COMPOUND_FID,
+ COMPOUND_FID,
+ FILE_ALL_INFORMATION,
+ SMB2_O_INFO_FILE, 0,
+ sizeof(struct smb2_file_all_info) +
+ PATH_MAX * 2, 0, NULL);
+ if (!rc) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ }
+ }
+
+ if (rc)
+ goto finished;
+ num_rqst++;
+ trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
+ full_path);
+ break;
+ case SMB2_OP_POSIX_QUERY_INFO:
+ rqst[num_rqst].rq_iov = &vars->qi_iov[0];
+ rqst[num_rqst].rq_nvec = 1;
+
+ if (cfile)
+ rc = SMB2_query_info_init(tcon, server,
+ &rqst[num_rqst],
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ SMB_FIND_FILE_POSIX_INFO,
+ SMB2_O_INFO_FILE, 0,
+ /* TBD: fix following to allow for longer SIDs */
+ sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) +
+ (sizeof(struct cifs_sid) * 2), 0, NULL);
+ else {
+ rc = SMB2_query_info_init(tcon, server,
+ &rqst[num_rqst],
+ COMPOUND_FID,
+ COMPOUND_FID,
+ SMB_FIND_FILE_POSIX_INFO,
+ SMB2_O_INFO_FILE, 0,
+ sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) +
+ (sizeof(struct cifs_sid) * 2), 0, NULL);
+ if (!rc) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ }
+ }
+
+ if (rc)
+ goto finished;
+ num_rqst++;
+ trace_smb3_posix_query_info_compound_enter(xid, ses->Suid, tcon->tid, full_path);
+ break;
+ case SMB2_OP_DELETE:
+ trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);
+ break;
+ case SMB2_OP_MKDIR:
+ /*
+ * Directories are created through parameters in the
+ * SMB2_open() call.
+ */
+ trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path);
+ break;
+ case SMB2_OP_RMDIR:
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
+ rqst[num_rqst].rq_nvec = 1;
+
+ size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */
+ data[0] = &delete_pending[0];
+
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst[num_rqst], COMPOUND_FID,
+ COMPOUND_FID, current->tgid,
+ FILE_DISPOSITION_INFORMATION,
+ SMB2_O_INFO_FILE, 0, data, size);
+ if (rc)
+ goto finished;
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst++]);
+ trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path);
+ break;
+ case SMB2_OP_SET_EOF:
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
+ rqst[num_rqst].rq_nvec = 1;
+
+ size[0] = 8; /* sizeof __le64 */
+ data[0] = ptr;
+
+ if (cfile) {
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst[num_rqst],
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ current->tgid,
+ FILE_END_OF_FILE_INFORMATION,
+ SMB2_O_INFO_FILE, 0,
+ data, size);
+ } else {
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst[num_rqst],
+ COMPOUND_FID,
+ COMPOUND_FID,
+ current->tgid,
+ FILE_END_OF_FILE_INFORMATION,
+ SMB2_O_INFO_FILE, 0,
+ data, size);
+ if (!rc) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ }
+ }
+ if (rc)
+ goto finished;
+ num_rqst++;
+ trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
+ break;
+ case SMB2_OP_SET_INFO:
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
+ rqst[num_rqst].rq_nvec = 1;
+
+
+ size[0] = sizeof(FILE_BASIC_INFO);
+ data[0] = ptr;
+
+ if (cfile)
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst[num_rqst],
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, current->tgid,
+ FILE_BASIC_INFORMATION,
+ SMB2_O_INFO_FILE, 0, data, size);
+ else {
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst[num_rqst],
+ COMPOUND_FID,
+ COMPOUND_FID, current->tgid,
+ FILE_BASIC_INFORMATION,
+ SMB2_O_INFO_FILE, 0, data, size);
+ if (!rc) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ }
+ }
+
+ if (rc)
+ goto finished;
+ num_rqst++;
+ trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid,
+ full_path);
+ break;
+ case SMB2_OP_RENAME:
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
+ rqst[num_rqst].rq_nvec = 2;
+
+ len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
+
+ vars->rename_info.ReplaceIfExists = 1;
+ vars->rename_info.RootDirectory = 0;
+ vars->rename_info.FileNameLength = cpu_to_le32(len);
+
+ size[0] = sizeof(struct smb2_file_rename_info);
+ data[0] = &vars->rename_info;
+
+ size[1] = len + 2 /* null */;
+ data[1] = (__le16 *)ptr;
+
+ if (cfile)
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst[num_rqst],
+ cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ current->tgid, FILE_RENAME_INFORMATION,
+ SMB2_O_INFO_FILE, 0, data, size);
+ else {
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst[num_rqst],
+ COMPOUND_FID, COMPOUND_FID,
+ current->tgid, FILE_RENAME_INFORMATION,
+ SMB2_O_INFO_FILE, 0, data, size);
+ if (!rc) {
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst]);
+ }
+ }
+ if (rc)
+ goto finished;
+ num_rqst++;
+ trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path);
+ break;
+ case SMB2_OP_HARDLINK:
+ rqst[num_rqst].rq_iov = &vars->si_iov[0];
+ rqst[num_rqst].rq_nvec = 2;
+
+ len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX));
+
+ vars->link_info.ReplaceIfExists = 0;
+ vars->link_info.RootDirectory = 0;
+ vars->link_info.FileNameLength = cpu_to_le32(len);
+
+ size[0] = sizeof(struct smb2_file_link_info);
+ data[0] = &vars->link_info;
+
+ size[1] = len + 2 /* null */;
+ data[1] = (__le16 *)ptr;
+
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst[num_rqst], COMPOUND_FID,
+ COMPOUND_FID, current->tgid,
+ FILE_LINK_INFORMATION,
+ SMB2_O_INFO_FILE, 0, data, size);
+ if (rc)
+ goto finished;
+ smb2_set_next_command(tcon, &rqst[num_rqst]);
+ smb2_set_related(&rqst[num_rqst++]);
+ trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path);
+ break;
+ default:
+ cifs_dbg(VFS, "Invalid command\n");
+ rc = -EINVAL;
+ }
+ if (rc)
+ goto finished;
+
+ /* We already have a handle so we can skip the close */
+ if (cfile)
+ goto after_close;
+ /* Close */
+ flags |= CIFS_CP_CREATE_CLOSE_OP;
+ rqst[num_rqst].rq_iov = &vars->close_iov[0];
+ rqst[num_rqst].rq_nvec = 1;
+ rc = SMB2_close_init(tcon, server,
+ &rqst[num_rqst], COMPOUND_FID,
+ COMPOUND_FID, false);
+ smb2_set_related(&rqst[num_rqst]);
+ if (rc)
+ goto finished;
+ after_close:
+ num_rqst++;
+
+ if (cfile) {
+ rc = compound_send_recv(xid, ses, server,
+ flags, num_rqst - 2,
+ &rqst[1], &resp_buftype[1],
+ &rsp_iov[1]);
+ } else
+ rc = compound_send_recv(xid, ses, server,
+ flags, num_rqst,
+ rqst, resp_buftype,
+ rsp_iov);
+
+ finished:
+ if (cfile)
+ cifsFileInfo_put(cfile);
+
+ SMB2_open_free(&rqst[0]);
+ if (rc == -EREMCHG) {
+ pr_warn_once("server share %s deleted\n", tcon->tree_name);
+ tcon->need_reconnect = true;
+ }
+
+ switch (command) {
+ case SMB2_OP_QUERY_INFO:
+ idata = ptr;
+ if (rc == 0 && cfile && cfile->symlink_target) {
+ idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
+ if (!idata->symlink_target)
+ rc = -ENOMEM;
+ }
+ if (rc == 0) {
+ qi_rsp = (struct smb2_query_info_rsp *)
+ rsp_iov[1].iov_base;
+ rc = smb2_validate_and_copy_iov(
+ le16_to_cpu(qi_rsp->OutputBufferOffset),
+ le32_to_cpu(qi_rsp->OutputBufferLength),
+ &rsp_iov[1], sizeof(idata->fi), (char *)&idata->fi);
+ }
+ if (rqst[1].rq_iov)
+ SMB2_query_info_free(&rqst[1]);
+ if (rqst[2].rq_iov)
+ SMB2_close_free(&rqst[2]);
+ if (rc)
+ trace_smb3_query_info_compound_err(xid, ses->Suid,
+ tcon->tid, rc);
+ else
+ trace_smb3_query_info_compound_done(xid, ses->Suid,
+ tcon->tid);
+ break;
+ case SMB2_OP_POSIX_QUERY_INFO:
+ idata = ptr;
+ if (rc == 0 && cfile && cfile->symlink_target) {
+ idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
+ if (!idata->symlink_target)
+ rc = -ENOMEM;
+ }
+ if (rc == 0) {
+ qi_rsp = (struct smb2_query_info_rsp *)
+ rsp_iov[1].iov_base;
+ rc = smb2_validate_and_copy_iov(
+ le16_to_cpu(qi_rsp->OutputBufferOffset),
+ le32_to_cpu(qi_rsp->OutputBufferLength),
+ &rsp_iov[1], sizeof(idata->posix_fi) /* add SIDs */,
+ (char *)&idata->posix_fi);
+ }
+ if (rqst[1].rq_iov)
+ SMB2_query_info_free(&rqst[1]);
+ if (rqst[2].rq_iov)
+ SMB2_close_free(&rqst[2]);
+ if (rc)
+ trace_smb3_posix_query_info_compound_err(xid, ses->Suid, tcon->tid, rc);
+ else
+ trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid);
+ break;
+ case SMB2_OP_DELETE:
+ if (rc)
+ trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc);
+ else
+ trace_smb3_delete_done(xid, ses->Suid, tcon->tid);
+ if (rqst[1].rq_iov)
+ SMB2_close_free(&rqst[1]);
+ break;
+ case SMB2_OP_MKDIR:
+ if (rc)
+ trace_smb3_mkdir_err(xid, ses->Suid, tcon->tid, rc);
+ else
+ trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid);
+ if (rqst[1].rq_iov)
+ SMB2_close_free(&rqst[1]);
+ break;
+ case SMB2_OP_HARDLINK:
+ if (rc)
+ trace_smb3_hardlink_err(xid, ses->Suid, tcon->tid, rc);
+ else
+ trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid);
+ free_set_inf_compound(rqst);
+ break;
+ case SMB2_OP_RENAME:
+ if (rc)
+ trace_smb3_rename_err(xid, ses->Suid, tcon->tid, rc);
+ else
+ trace_smb3_rename_done(xid, ses->Suid, tcon->tid);
+ free_set_inf_compound(rqst);
+ break;
+ case SMB2_OP_RMDIR:
+ if (rc)
+ trace_smb3_rmdir_err(xid, ses->Suid, tcon->tid, rc);
+ else
+ trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid);
+ free_set_inf_compound(rqst);
+ break;
+ case SMB2_OP_SET_EOF:
+ if (rc)
+ trace_smb3_set_eof_err(xid, ses->Suid, tcon->tid, rc);
+ else
+ trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid);
+ free_set_inf_compound(rqst);
+ break;
+ case SMB2_OP_SET_INFO:
+ if (rc)
+ trace_smb3_set_info_compound_err(xid, ses->Suid,
+ tcon->tid, rc);
+ else
+ trace_smb3_set_info_compound_done(xid, ses->Suid,
+ tcon->tid);
+ free_set_inf_compound(rqst);
+ break;
+ }
+
+ if (rc && err_iov && err_buftype) {
+ memcpy(err_iov, rsp_iov, 3 * sizeof(*err_iov));
+ memcpy(err_buftype, resp_buftype, 3 * sizeof(*err_buftype));
+ } else {
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+ }
+ kfree(vars);
+ return rc;
+}
+
+int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse)
+{
+ __u32 create_options = 0;
+ struct cifsFileInfo *cfile;
+ struct cached_fid *cfid = NULL;
+ struct kvec err_iov[3] = {};
+ int err_buftype[3] = {};
+ bool islink;
+ int rc, rc2;
+
+ *adjust_tz = false;
+ *reparse = false;
+
+ if (strcmp(full_path, ""))
+ rc = -ENOENT;
+ else
+ rc = open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid);
+ /* If it is a root and its handle is cached then use it */
+ if (!rc) {
+ if (cfid->file_all_info_is_valid) {
+ memcpy(&data->fi, &cfid->file_all_info, sizeof(data->fi));
+ } else {
+ rc = SMB2_query_info(xid, tcon, cfid->fid.persistent_fid,
+ cfid->fid.volatile_fid, &data->fi);
+ }
+ close_cached_dir(cfid);
+ return rc;
+ }
+
+ cifs_get_readable_path(tcon, full_path, &cfile);
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
+ create_options, ACL_NO_MODE, data, SMB2_OP_QUERY_INFO, cfile,
+ err_iov, err_buftype);
+ if (rc) {
+ struct smb2_hdr *hdr = err_iov[0].iov_base;
+
+ if (unlikely(!hdr || err_buftype[0] == CIFS_NO_BUFFER))
+ goto out;
+ if (rc == -EOPNOTSUPP && hdr->Command == SMB2_CREATE &&
+ hdr->Status == STATUS_STOPPED_ON_SYMLINK) {
+ rc = smb2_parse_symlink_response(cifs_sb, err_iov,
+ &data->symlink_target);
+ if (rc)
+ goto out;
+
+ *reparse = true;
+ create_options |= OPEN_REPARSE_POINT;
+
+ /* Failed on a symbolic link - query a reparse point info */
+ cifs_get_readable_path(tcon, full_path, &cfile);
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
+ FILE_READ_ATTRIBUTES, FILE_OPEN,
+ create_options, ACL_NO_MODE, data,
+ SMB2_OP_QUERY_INFO, cfile, NULL, NULL);
+ goto out;
+ } else if (rc != -EREMOTE && hdr->Status == STATUS_OBJECT_NAME_INVALID) {
+ rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
+ full_path, &islink);
+ if (rc2) {
+ rc = rc2;
+ goto out;
+ }
+ if (islink)
+ rc = -EREMOTE;
+ }
+ if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb &&
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS))
+ rc = -EOPNOTSUPP;
+ }
+
+out:
+ free_rsp_buf(err_buftype[0], err_iov[0].iov_base);
+ free_rsp_buf(err_buftype[1], err_iov[1].iov_base);
+ free_rsp_buf(err_buftype[2], err_iov[2].iov_base);
+ return rc;
+}
+
+
+int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse)
+{
+ int rc;
+ __u32 create_options = 0;
+ struct cifsFileInfo *cfile;
+ struct kvec err_iov[3] = {};
+ int err_buftype[3] = {};
+
+ *adjust_tz = false;
+ *reparse = false;
+
+ /*
+ * BB TODO: Add support for using the cached root handle.
+ * Create SMB2_query_posix_info worker function to do non-compounded query
+ * when we already have an open file handle for this. For now this is fast enough
+ * (always using the compounded version).
+ */
+
+ cifs_get_readable_path(tcon, full_path, &cfile);
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
+ create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile,
+ err_iov, err_buftype);
+ if (rc == -EOPNOTSUPP) {
+ /* BB TODO: When support for special files added to Samba re-verify this path */
+ if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER &&
+ ((struct smb2_hdr *)err_iov[0].iov_base)->Command == SMB2_CREATE &&
+ ((struct smb2_hdr *)err_iov[0].iov_base)->Status == STATUS_STOPPED_ON_SYMLINK) {
+ rc = smb2_parse_symlink_response(cifs_sb, err_iov, &data->symlink_target);
+ if (rc)
+ goto out;
+ }
+ *reparse = true;
+ create_options |= OPEN_REPARSE_POINT;
+
+ /* Failed on a symbolic link - query a reparse point info */
+ cifs_get_readable_path(tcon, full_path, &cfile);
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES,
+ FILE_OPEN, create_options, ACL_NO_MODE, data,
+ SMB2_OP_POSIX_QUERY_INFO, cfile, NULL, NULL);
+ }
+
+out:
+ free_rsp_buf(err_buftype[0], err_iov[0].iov_base);
+ free_rsp_buf(err_buftype[1], err_iov[1].iov_base);
+ free_rsp_buf(err_buftype[2], err_iov[2].iov_base);
+ return rc;
+}
+
+int
+smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
+ struct cifs_tcon *tcon, const char *name,
+ struct cifs_sb_info *cifs_sb)
+{
+ return smb2_compound_op(xid, tcon, cifs_sb, name,
+ FILE_WRITE_ATTRIBUTES, FILE_CREATE,
+ CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR,
+ NULL, NULL, NULL);
+}
+
+void
+smb2_mkdir_setinfo(struct inode *inode, const char *name,
+ struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon,
+ const unsigned int xid)
+{
+ FILE_BASIC_INFO data;
+ struct cifsInodeInfo *cifs_i;
+ struct cifsFileInfo *cfile;
+ u32 dosattrs;
+ int tmprc;
+
+ memset(&data, 0, sizeof(data));
+ cifs_i = CIFS_I(inode);
+ dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
+ data.Attributes = cpu_to_le32(dosattrs);
+ cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
+ tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
+ FILE_WRITE_ATTRIBUTES, FILE_CREATE,
+ CREATE_NOT_FILE, ACL_NO_MODE,
+ &data, SMB2_OP_SET_INFO, cfile, NULL, NULL);
+ if (tmprc == 0)
+ cifs_i->cifsAttrs = dosattrs;
+}
+
+int
+smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
+ struct cifs_sb_info *cifs_sb)
+{
+ drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
+ return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
+ CREATE_NOT_FILE, ACL_NO_MODE,
+ NULL, SMB2_OP_RMDIR, NULL, NULL, NULL);
+}
+
+int
+smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
+ struct cifs_sb_info *cifs_sb)
+{
+ return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
+ CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
+ ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL, NULL, NULL);
+}
+
+static int
+smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb, __u32 access, int command,
+ struct cifsFileInfo *cfile)
+{
+ __le16 *smb2_to_name = NULL;
+ int rc;
+
+ smb2_to_name = cifs_convert_path_to_utf16(to_name, cifs_sb);
+ if (smb2_to_name == NULL) {
+ rc = -ENOMEM;
+ goto smb2_rename_path;
+ }
+ rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
+ FILE_OPEN, 0, ACL_NO_MODE, smb2_to_name,
+ command, cfile, NULL, NULL);
+smb2_rename_path:
+ kfree(smb2_to_name);
+ return rc;
+}
+
+int
+smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb)
+{
+ struct cifsFileInfo *cfile;
+
+ drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
+ cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
+
+ return smb2_set_path_attr(xid, tcon, from_name, to_name,
+ cifs_sb, DELETE, SMB2_OP_RENAME, cfile);
+}
+
+int
+smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb)
+{
+ return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
+ FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK,
+ NULL);
+}
+
+int
+smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *full_path, __u64 size,
+ struct cifs_sb_info *cifs_sb, bool set_alloc)
+{
+ __le64 eof = cpu_to_le64(size);
+ struct cifsFileInfo *cfile;
+
+ cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
+ return smb2_compound_op(xid, tcon, cifs_sb, full_path,
+ FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE,
+ &eof, SMB2_OP_SET_EOF, cfile, NULL, NULL);
+}
+
+int
+smb2_set_file_info(struct inode *inode, const char *full_path,
+ FILE_BASIC_INFO *buf, const unsigned int xid)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *tcon;
+ struct cifsFileInfo *cfile;
+ int rc;
+
+ if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
+ (buf->LastWriteTime == 0) && (buf->ChangeTime == 0) &&
+ (buf->Attributes == 0))
+ return 0; /* would be a no op, no sense sending this */
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ tcon = tlink_tcon(tlink);
+
+ cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
+ FILE_WRITE_ATTRIBUTES, FILE_OPEN,
+ 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, cfile,
+ NULL, NULL);
+ cifs_put_tlink(tlink);
+ return rc;
+}
diff --git a/fs/smb/client/smb2maperror.c b/fs/smb/client/smb2maperror.c
new file mode 100644
index 000000000000..194799ddd382
--- /dev/null
+++ b/fs/smb/client/smb2maperror.c
@@ -0,0 +1,2481 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Functions which do error mapping of SMB2 status codes to POSIX errors
+ *
+ * Copyright (C) International Business Machines Corp., 2009
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+#include <linux/errno.h>
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "smb2pdu.h"
+#include "smb2proto.h"
+#include "smb2status.h"
+#include "smb2glob.h"
+#include "trace.h"
+
+struct status_to_posix_error {
+ __le32 smb2_status;
+ int posix_error;
+ char *status_string;
+};
+
+static const struct status_to_posix_error smb2_error_map_table[] = {
+ {STATUS_SUCCESS, 0, "STATUS_SUCCESS"},
+ {STATUS_WAIT_0, 0, "STATUS_WAIT_0"},
+ {STATUS_WAIT_1, -EIO, "STATUS_WAIT_1"},
+ {STATUS_WAIT_2, -EIO, "STATUS_WAIT_2"},
+ {STATUS_WAIT_3, -EIO, "STATUS_WAIT_3"},
+ {STATUS_WAIT_63, -EIO, "STATUS_WAIT_63"},
+ {STATUS_ABANDONED, -EIO, "STATUS_ABANDONED"},
+ {STATUS_ABANDONED_WAIT_0, -EIO, "STATUS_ABANDONED_WAIT_0"},
+ {STATUS_ABANDONED_WAIT_63, -EIO, "STATUS_ABANDONED_WAIT_63"},
+ {STATUS_USER_APC, -EIO, "STATUS_USER_APC"},
+ {STATUS_KERNEL_APC, -EIO, "STATUS_KERNEL_APC"},
+ {STATUS_ALERTED, -EIO, "STATUS_ALERTED"},
+ {STATUS_TIMEOUT, -ETIMEDOUT, "STATUS_TIMEOUT"},
+ {STATUS_PENDING, -EIO, "STATUS_PENDING"},
+ {STATUS_REPARSE, -EIO, "STATUS_REPARSE"},
+ {STATUS_MORE_ENTRIES, -EIO, "STATUS_MORE_ENTRIES"},
+ {STATUS_NOT_ALL_ASSIGNED, -EIO, "STATUS_NOT_ALL_ASSIGNED"},
+ {STATUS_SOME_NOT_MAPPED, -EIO, "STATUS_SOME_NOT_MAPPED"},
+ {STATUS_OPLOCK_BREAK_IN_PROGRESS, -EIO,
+ "STATUS_OPLOCK_BREAK_IN_PROGRESS"},
+ {STATUS_VOLUME_MOUNTED, -EIO, "STATUS_VOLUME_MOUNTED"},
+ {STATUS_RXACT_COMMITTED, -EIO, "STATUS_RXACT_COMMITTED"},
+ {STATUS_NOTIFY_CLEANUP, -EIO, "STATUS_NOTIFY_CLEANUP"},
+ {STATUS_NOTIFY_ENUM_DIR, -EIO, "STATUS_NOTIFY_ENUM_DIR"},
+ {STATUS_NO_QUOTAS_FOR_ACCOUNT, -EIO, "STATUS_NO_QUOTAS_FOR_ACCOUNT"},
+ {STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED, -EIO,
+ "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED"},
+ {STATUS_PAGE_FAULT_TRANSITION, -EIO, "STATUS_PAGE_FAULT_TRANSITION"},
+ {STATUS_PAGE_FAULT_DEMAND_ZERO, -EIO, "STATUS_PAGE_FAULT_DEMAND_ZERO"},
+ {STATUS_PAGE_FAULT_COPY_ON_WRITE, -EIO,
+ "STATUS_PAGE_FAULT_COPY_ON_WRITE"},
+ {STATUS_PAGE_FAULT_GUARD_PAGE, -EIO, "STATUS_PAGE_FAULT_GUARD_PAGE"},
+ {STATUS_PAGE_FAULT_PAGING_FILE, -EIO, "STATUS_PAGE_FAULT_PAGING_FILE"},
+ {STATUS_CACHE_PAGE_LOCKED, -EIO, "STATUS_CACHE_PAGE_LOCKED"},
+ {STATUS_CRASH_DUMP, -EIO, "STATUS_CRASH_DUMP"},
+ {STATUS_BUFFER_ALL_ZEROS, -EIO, "STATUS_BUFFER_ALL_ZEROS"},
+ {STATUS_REPARSE_OBJECT, -EIO, "STATUS_REPARSE_OBJECT"},
+ {STATUS_RESOURCE_REQUIREMENTS_CHANGED, -EIO,
+ "STATUS_RESOURCE_REQUIREMENTS_CHANGED"},
+ {STATUS_TRANSLATION_COMPLETE, -EIO, "STATUS_TRANSLATION_COMPLETE"},
+ {STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY, -EIO,
+ "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY"},
+ {STATUS_NOTHING_TO_TERMINATE, -EIO, "STATUS_NOTHING_TO_TERMINATE"},
+ {STATUS_PROCESS_NOT_IN_JOB, -EIO, "STATUS_PROCESS_NOT_IN_JOB"},
+ {STATUS_PROCESS_IN_JOB, -EIO, "STATUS_PROCESS_IN_JOB"},
+ {STATUS_VOLSNAP_HIBERNATE_READY, -EIO,
+ "STATUS_VOLSNAP_HIBERNATE_READY"},
+ {STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY, -EIO,
+ "STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY"},
+ {STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED, -EIO,
+ "STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED"},
+ {STATUS_INTERRUPT_STILL_CONNECTED, -EIO,
+ "STATUS_INTERRUPT_STILL_CONNECTED"},
+ {STATUS_PROCESS_CLONED, -EIO, "STATUS_PROCESS_CLONED"},
+ {STATUS_FILE_LOCKED_WITH_ONLY_READERS, -EIO,
+ "STATUS_FILE_LOCKED_WITH_ONLY_READERS"},
+ {STATUS_FILE_LOCKED_WITH_WRITERS, -EIO,
+ "STATUS_FILE_LOCKED_WITH_WRITERS"},
+ {STATUS_RESOURCEMANAGER_READ_ONLY, -EROFS,
+ "STATUS_RESOURCEMANAGER_READ_ONLY"},
+ {STATUS_WAIT_FOR_OPLOCK, -EIO, "STATUS_WAIT_FOR_OPLOCK"},
+ {DBG_EXCEPTION_HANDLED, -EIO, "DBG_EXCEPTION_HANDLED"},
+ {DBG_CONTINUE, -EIO, "DBG_CONTINUE"},
+ {STATUS_FLT_IO_COMPLETE, -EIO, "STATUS_FLT_IO_COMPLETE"},
+ {STATUS_OBJECT_NAME_EXISTS, -EIO, "STATUS_OBJECT_NAME_EXISTS"},
+ {STATUS_THREAD_WAS_SUSPENDED, -EIO, "STATUS_THREAD_WAS_SUSPENDED"},
+ {STATUS_WORKING_SET_LIMIT_RANGE, -EIO,
+ "STATUS_WORKING_SET_LIMIT_RANGE"},
+ {STATUS_IMAGE_NOT_AT_BASE, -EIO, "STATUS_IMAGE_NOT_AT_BASE"},
+ {STATUS_RXACT_STATE_CREATED, -EIO, "STATUS_RXACT_STATE_CREATED"},
+ {STATUS_SEGMENT_NOTIFICATION, -EIO, "STATUS_SEGMENT_NOTIFICATION"},
+ {STATUS_LOCAL_USER_SESSION_KEY, -EIO, "STATUS_LOCAL_USER_SESSION_KEY"},
+ {STATUS_BAD_CURRENT_DIRECTORY, -EIO, "STATUS_BAD_CURRENT_DIRECTORY"},
+ {STATUS_SERIAL_MORE_WRITES, -EIO, "STATUS_SERIAL_MORE_WRITES"},
+ {STATUS_REGISTRY_RECOVERED, -EIO, "STATUS_REGISTRY_RECOVERED"},
+ {STATUS_FT_READ_RECOVERY_FROM_BACKUP, -EIO,
+ "STATUS_FT_READ_RECOVERY_FROM_BACKUP"},
+ {STATUS_FT_WRITE_RECOVERY, -EIO, "STATUS_FT_WRITE_RECOVERY"},
+ {STATUS_SERIAL_COUNTER_TIMEOUT, -ETIMEDOUT,
+ "STATUS_SERIAL_COUNTER_TIMEOUT"},
+ {STATUS_NULL_LM_PASSWORD, -EIO, "STATUS_NULL_LM_PASSWORD"},
+ {STATUS_IMAGE_MACHINE_TYPE_MISMATCH, -EIO,
+ "STATUS_IMAGE_MACHINE_TYPE_MISMATCH"},
+ {STATUS_RECEIVE_PARTIAL, -EIO, "STATUS_RECEIVE_PARTIAL"},
+ {STATUS_RECEIVE_EXPEDITED, -EIO, "STATUS_RECEIVE_EXPEDITED"},
+ {STATUS_RECEIVE_PARTIAL_EXPEDITED, -EIO,
+ "STATUS_RECEIVE_PARTIAL_EXPEDITED"},
+ {STATUS_EVENT_DONE, -EIO, "STATUS_EVENT_DONE"},
+ {STATUS_EVENT_PENDING, -EIO, "STATUS_EVENT_PENDING"},
+ {STATUS_CHECKING_FILE_SYSTEM, -EIO, "STATUS_CHECKING_FILE_SYSTEM"},
+ {STATUS_FATAL_APP_EXIT, -EIO, "STATUS_FATAL_APP_EXIT"},
+ {STATUS_PREDEFINED_HANDLE, -EIO, "STATUS_PREDEFINED_HANDLE"},
+ {STATUS_WAS_UNLOCKED, -EIO, "STATUS_WAS_UNLOCKED"},
+ {STATUS_SERVICE_NOTIFICATION, -EIO, "STATUS_SERVICE_NOTIFICATION"},
+ {STATUS_WAS_LOCKED, -EIO, "STATUS_WAS_LOCKED"},
+ {STATUS_LOG_HARD_ERROR, -EIO, "STATUS_LOG_HARD_ERROR"},
+ {STATUS_ALREADY_WIN32, -EIO, "STATUS_ALREADY_WIN32"},
+ {STATUS_WX86_UNSIMULATE, -EIO, "STATUS_WX86_UNSIMULATE"},
+ {STATUS_WX86_CONTINUE, -EIO, "STATUS_WX86_CONTINUE"},
+ {STATUS_WX86_SINGLE_STEP, -EIO, "STATUS_WX86_SINGLE_STEP"},
+ {STATUS_WX86_BREAKPOINT, -EIO, "STATUS_WX86_BREAKPOINT"},
+ {STATUS_WX86_EXCEPTION_CONTINUE, -EIO,
+ "STATUS_WX86_EXCEPTION_CONTINUE"},
+ {STATUS_WX86_EXCEPTION_LASTCHANCE, -EIO,
+ "STATUS_WX86_EXCEPTION_LASTCHANCE"},
+ {STATUS_WX86_EXCEPTION_CHAIN, -EIO, "STATUS_WX86_EXCEPTION_CHAIN"},
+ {STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE, -EIO,
+ "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE"},
+ {STATUS_NO_YIELD_PERFORMED, -EIO, "STATUS_NO_YIELD_PERFORMED"},
+ {STATUS_TIMER_RESUME_IGNORED, -EIO, "STATUS_TIMER_RESUME_IGNORED"},
+ {STATUS_ARBITRATION_UNHANDLED, -EIO, "STATUS_ARBITRATION_UNHANDLED"},
+ {STATUS_CARDBUS_NOT_SUPPORTED, -ENOSYS, "STATUS_CARDBUS_NOT_SUPPORTED"},
+ {STATUS_WX86_CREATEWX86TIB, -EIO, "STATUS_WX86_CREATEWX86TIB"},
+ {STATUS_MP_PROCESSOR_MISMATCH, -EIO, "STATUS_MP_PROCESSOR_MISMATCH"},
+ {STATUS_HIBERNATED, -EIO, "STATUS_HIBERNATED"},
+ {STATUS_RESUME_HIBERNATION, -EIO, "STATUS_RESUME_HIBERNATION"},
+ {STATUS_FIRMWARE_UPDATED, -EIO, "STATUS_FIRMWARE_UPDATED"},
+ {STATUS_DRIVERS_LEAKING_LOCKED_PAGES, -EIO,
+ "STATUS_DRIVERS_LEAKING_LOCKED_PAGES"},
+ {STATUS_MESSAGE_RETRIEVED, -EIO, "STATUS_MESSAGE_RETRIEVED"},
+ {STATUS_SYSTEM_POWERSTATE_TRANSITION, -EIO,
+ "STATUS_SYSTEM_POWERSTATE_TRANSITION"},
+ {STATUS_ALPC_CHECK_COMPLETION_LIST, -EIO,
+ "STATUS_ALPC_CHECK_COMPLETION_LIST"},
+ {STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION, -EIO,
+ "STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION"},
+ {STATUS_ACCESS_AUDIT_BY_POLICY, -EIO, "STATUS_ACCESS_AUDIT_BY_POLICY"},
+ {STATUS_ABANDON_HIBERFILE, -EIO, "STATUS_ABANDON_HIBERFILE"},
+ {STATUS_BIZRULES_NOT_ENABLED, -EIO, "STATUS_BIZRULES_NOT_ENABLED"},
+ {STATUS_WAKE_SYSTEM, -EIO, "STATUS_WAKE_SYSTEM"},
+ {STATUS_DS_SHUTTING_DOWN, -EIO, "STATUS_DS_SHUTTING_DOWN"},
+ {DBG_REPLY_LATER, -EIO, "DBG_REPLY_LATER"},
+ {DBG_UNABLE_TO_PROVIDE_HANDLE, -EIO, "DBG_UNABLE_TO_PROVIDE_HANDLE"},
+ {DBG_TERMINATE_THREAD, -EIO, "DBG_TERMINATE_THREAD"},
+ {DBG_TERMINATE_PROCESS, -EIO, "DBG_TERMINATE_PROCESS"},
+ {DBG_CONTROL_C, -EIO, "DBG_CONTROL_C"},
+ {DBG_PRINTEXCEPTION_C, -EIO, "DBG_PRINTEXCEPTION_C"},
+ {DBG_RIPEXCEPTION, -EIO, "DBG_RIPEXCEPTION"},
+ {DBG_CONTROL_BREAK, -EIO, "DBG_CONTROL_BREAK"},
+ {DBG_COMMAND_EXCEPTION, -EIO, "DBG_COMMAND_EXCEPTION"},
+ {RPC_NT_UUID_LOCAL_ONLY, -EIO, "RPC_NT_UUID_LOCAL_ONLY"},
+ {RPC_NT_SEND_INCOMPLETE, -EIO, "RPC_NT_SEND_INCOMPLETE"},
+ {STATUS_CTX_CDM_CONNECT, -EIO, "STATUS_CTX_CDM_CONNECT"},
+ {STATUS_CTX_CDM_DISCONNECT, -EIO, "STATUS_CTX_CDM_DISCONNECT"},
+ {STATUS_SXS_RELEASE_ACTIVATION_CONTEXT, -EIO,
+ "STATUS_SXS_RELEASE_ACTIVATION_CONTEXT"},
+ {STATUS_RECOVERY_NOT_NEEDED, -EIO, "STATUS_RECOVERY_NOT_NEEDED"},
+ {STATUS_RM_ALREADY_STARTED, -EIO, "STATUS_RM_ALREADY_STARTED"},
+ {STATUS_LOG_NO_RESTART, -EIO, "STATUS_LOG_NO_RESTART"},
+ {STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST, -EIO,
+ "STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST"},
+ {STATUS_GRAPHICS_PARTIAL_DATA_POPULATED, -EIO,
+ "STATUS_GRAPHICS_PARTIAL_DATA_POPULATED"},
+ {STATUS_GRAPHICS_DRIVER_MISMATCH, -EIO,
+ "STATUS_GRAPHICS_DRIVER_MISMATCH"},
+ {STATUS_GRAPHICS_MODE_NOT_PINNED, -EIO,
+ "STATUS_GRAPHICS_MODE_NOT_PINNED"},
+ {STATUS_GRAPHICS_NO_PREFERRED_MODE, -EIO,
+ "STATUS_GRAPHICS_NO_PREFERRED_MODE"},
+ {STATUS_GRAPHICS_DATASET_IS_EMPTY, -EIO,
+ "STATUS_GRAPHICS_DATASET_IS_EMPTY"},
+ {STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET, -EIO,
+ "STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET"},
+ {STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED, -EIO,
+ "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED"},
+ {STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS, -EIO,
+ "STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS"},
+ {STATUS_GRAPHICS_LEADLINK_START_DEFERRED, -EIO,
+ "STATUS_GRAPHICS_LEADLINK_START_DEFERRED"},
+ {STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY, -EIO,
+ "STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY"},
+ {STATUS_GRAPHICS_START_DEFERRED, -EIO,
+ "STATUS_GRAPHICS_START_DEFERRED"},
+ {STATUS_NDIS_INDICATION_REQUIRED, -EIO,
+ "STATUS_NDIS_INDICATION_REQUIRED"},
+ {STATUS_GUARD_PAGE_VIOLATION, -EIO, "STATUS_GUARD_PAGE_VIOLATION"},
+ {STATUS_DATATYPE_MISALIGNMENT, -EIO, "STATUS_DATATYPE_MISALIGNMENT"},
+ {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
+ {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
+ {STATUS_BUFFER_OVERFLOW, -E2BIG, "STATUS_BUFFER_OVERFLOW"},
+ {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
+ {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
+ {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
+ {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"},
+ {STATUS_GUID_SUBSTITUTION_MADE, -EIO, "STATUS_GUID_SUBSTITUTION_MADE"},
+ {STATUS_PARTIAL_COPY, -EIO, "STATUS_PARTIAL_COPY"},
+ {STATUS_DEVICE_PAPER_EMPTY, -EIO, "STATUS_DEVICE_PAPER_EMPTY"},
+ {STATUS_DEVICE_POWERED_OFF, -EIO, "STATUS_DEVICE_POWERED_OFF"},
+ {STATUS_DEVICE_OFF_LINE, -EIO, "STATUS_DEVICE_OFF_LINE"},
+ {STATUS_DEVICE_BUSY, -EBUSY, "STATUS_DEVICE_BUSY"},
+ {STATUS_NO_MORE_EAS, -EIO, "STATUS_NO_MORE_EAS"},
+ {STATUS_INVALID_EA_NAME, -EINVAL, "STATUS_INVALID_EA_NAME"},
+ {STATUS_EA_LIST_INCONSISTENT, -EIO, "STATUS_EA_LIST_INCONSISTENT"},
+ {STATUS_INVALID_EA_FLAG, -EINVAL, "STATUS_INVALID_EA_FLAG"},
+ {STATUS_VERIFY_REQUIRED, -EIO, "STATUS_VERIFY_REQUIRED"},
+ {STATUS_EXTRANEOUS_INFORMATION, -EIO, "STATUS_EXTRANEOUS_INFORMATION"},
+ {STATUS_RXACT_COMMIT_NECESSARY, -EIO, "STATUS_RXACT_COMMIT_NECESSARY"},
+ {STATUS_NO_MORE_ENTRIES, -EIO, "STATUS_NO_MORE_ENTRIES"},
+ {STATUS_FILEMARK_DETECTED, -EIO, "STATUS_FILEMARK_DETECTED"},
+ {STATUS_MEDIA_CHANGED, -EIO, "STATUS_MEDIA_CHANGED"},
+ {STATUS_BUS_RESET, -EIO, "STATUS_BUS_RESET"},
+ {STATUS_END_OF_MEDIA, -EIO, "STATUS_END_OF_MEDIA"},
+ {STATUS_BEGINNING_OF_MEDIA, -EIO, "STATUS_BEGINNING_OF_MEDIA"},
+ {STATUS_MEDIA_CHECK, -EIO, "STATUS_MEDIA_CHECK"},
+ {STATUS_SETMARK_DETECTED, -EIO, "STATUS_SETMARK_DETECTED"},
+ {STATUS_NO_DATA_DETECTED, -EIO, "STATUS_NO_DATA_DETECTED"},
+ {STATUS_REDIRECTOR_HAS_OPEN_HANDLES, -EIO,
+ "STATUS_REDIRECTOR_HAS_OPEN_HANDLES"},
+ {STATUS_SERVER_HAS_OPEN_HANDLES, -EIO,
+ "STATUS_SERVER_HAS_OPEN_HANDLES"},
+ {STATUS_ALREADY_DISCONNECTED, -EIO, "STATUS_ALREADY_DISCONNECTED"},
+ {STATUS_LONGJUMP, -EIO, "STATUS_LONGJUMP"},
+ {STATUS_CLEANER_CARTRIDGE_INSTALLED, -EIO,
+ "STATUS_CLEANER_CARTRIDGE_INSTALLED"},
+ {STATUS_PLUGPLAY_QUERY_VETOED, -EIO, "STATUS_PLUGPLAY_QUERY_VETOED"},
+ {STATUS_UNWIND_CONSOLIDATE, -EIO, "STATUS_UNWIND_CONSOLIDATE"},
+ {STATUS_REGISTRY_HIVE_RECOVERED, -EIO,
+ "STATUS_REGISTRY_HIVE_RECOVERED"},
+ {STATUS_DLL_MIGHT_BE_INSECURE, -EIO, "STATUS_DLL_MIGHT_BE_INSECURE"},
+ {STATUS_DLL_MIGHT_BE_INCOMPATIBLE, -EIO,
+ "STATUS_DLL_MIGHT_BE_INCOMPATIBLE"},
+ {STATUS_STOPPED_ON_SYMLINK, -EOPNOTSUPP, "STATUS_STOPPED_ON_SYMLINK"},
+ {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EOPNOTSUPP,
+ "STATUS_REPARSE_NOT_HANDLED"},
+ {STATUS_DEVICE_REQUIRES_CLEANING, -EIO,
+ "STATUS_DEVICE_REQUIRES_CLEANING"},
+ {STATUS_DEVICE_DOOR_OPEN, -EIO, "STATUS_DEVICE_DOOR_OPEN"},
+ {STATUS_DATA_LOST_REPAIR, -EIO, "STATUS_DATA_LOST_REPAIR"},
+ {DBG_EXCEPTION_NOT_HANDLED, -EIO, "DBG_EXCEPTION_NOT_HANDLED"},
+ {STATUS_CLUSTER_NODE_ALREADY_UP, -EIO,
+ "STATUS_CLUSTER_NODE_ALREADY_UP"},
+ {STATUS_CLUSTER_NODE_ALREADY_DOWN, -EIO,
+ "STATUS_CLUSTER_NODE_ALREADY_DOWN"},
+ {STATUS_CLUSTER_NETWORK_ALREADY_ONLINE, -EIO,
+ "STATUS_CLUSTER_NETWORK_ALREADY_ONLINE"},
+ {STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE, -EIO,
+ "STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE"},
+ {STATUS_CLUSTER_NODE_ALREADY_MEMBER, -EIO,
+ "STATUS_CLUSTER_NODE_ALREADY_MEMBER"},
+ {STATUS_COULD_NOT_RESIZE_LOG, -EIO, "STATUS_COULD_NOT_RESIZE_LOG"},
+ {STATUS_NO_TXF_METADATA, -EIO, "STATUS_NO_TXF_METADATA"},
+ {STATUS_CANT_RECOVER_WITH_HANDLE_OPEN, -EIO,
+ "STATUS_CANT_RECOVER_WITH_HANDLE_OPEN"},
+ {STATUS_TXF_METADATA_ALREADY_PRESENT, -EIO,
+ "STATUS_TXF_METADATA_ALREADY_PRESENT"},
+ {STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET, -EIO,
+ "STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET"},
+ {STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED, -EIO,
+ "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED"},
+ {STATUS_FLT_BUFFER_TOO_SMALL, -ENOBUFS, "STATUS_FLT_BUFFER_TOO_SMALL"},
+ {STATUS_FVE_PARTIAL_METADATA, -EIO, "STATUS_FVE_PARTIAL_METADATA"},
+ {STATUS_UNSUCCESSFUL, -EIO, "STATUS_UNSUCCESSFUL"},
+ {STATUS_NOT_IMPLEMENTED, -EOPNOTSUPP, "STATUS_NOT_IMPLEMENTED"},
+ {STATUS_INVALID_INFO_CLASS, -EIO, "STATUS_INVALID_INFO_CLASS"},
+ {STATUS_INFO_LENGTH_MISMATCH, -EIO, "STATUS_INFO_LENGTH_MISMATCH"},
+ {STATUS_ACCESS_VIOLATION, -EACCES, "STATUS_ACCESS_VIOLATION"},
+ {STATUS_IN_PAGE_ERROR, -EFAULT, "STATUS_IN_PAGE_ERROR"},
+ {STATUS_PAGEFILE_QUOTA, -EDQUOT, "STATUS_PAGEFILE_QUOTA"},
+ {STATUS_INVALID_HANDLE, -EBADF, "STATUS_INVALID_HANDLE"},
+ {STATUS_BAD_INITIAL_STACK, -EIO, "STATUS_BAD_INITIAL_STACK"},
+ {STATUS_BAD_INITIAL_PC, -EIO, "STATUS_BAD_INITIAL_PC"},
+ {STATUS_INVALID_CID, -EIO, "STATUS_INVALID_CID"},
+ {STATUS_TIMER_NOT_CANCELED, -EIO, "STATUS_TIMER_NOT_CANCELED"},
+ {STATUS_INVALID_PARAMETER, -EINVAL, "STATUS_INVALID_PARAMETER"},
+ {STATUS_NO_SUCH_DEVICE, -ENODEV, "STATUS_NO_SUCH_DEVICE"},
+ {STATUS_NO_SUCH_FILE, -ENOENT, "STATUS_NO_SUCH_FILE"},
+ {STATUS_INVALID_DEVICE_REQUEST, -EOPNOTSUPP, "STATUS_INVALID_DEVICE_REQUEST"},
+ {STATUS_END_OF_FILE, -ENODATA, "STATUS_END_OF_FILE"},
+ {STATUS_WRONG_VOLUME, -EIO, "STATUS_WRONG_VOLUME"},
+ {STATUS_NO_MEDIA_IN_DEVICE, -EIO, "STATUS_NO_MEDIA_IN_DEVICE"},
+ {STATUS_UNRECOGNIZED_MEDIA, -EIO, "STATUS_UNRECOGNIZED_MEDIA"},
+ {STATUS_NONEXISTENT_SECTOR, -EIO, "STATUS_NONEXISTENT_SECTOR"},
+ {STATUS_MORE_PROCESSING_REQUIRED, -EIO,
+ "STATUS_MORE_PROCESSING_REQUIRED"},
+ {STATUS_NO_MEMORY, -EREMOTEIO, "STATUS_NO_MEMORY"},
+ {STATUS_CONFLICTING_ADDRESSES, -EADDRINUSE,
+ "STATUS_CONFLICTING_ADDRESSES"},
+ {STATUS_NOT_MAPPED_VIEW, -EIO, "STATUS_NOT_MAPPED_VIEW"},
+ {STATUS_UNABLE_TO_FREE_VM, -EIO, "STATUS_UNABLE_TO_FREE_VM"},
+ {STATUS_UNABLE_TO_DELETE_SECTION, -EIO,
+ "STATUS_UNABLE_TO_DELETE_SECTION"},
+ {STATUS_INVALID_SYSTEM_SERVICE, -EIO, "STATUS_INVALID_SYSTEM_SERVICE"},
+ {STATUS_ILLEGAL_INSTRUCTION, -EIO, "STATUS_ILLEGAL_INSTRUCTION"},
+ {STATUS_INVALID_LOCK_SEQUENCE, -EIO, "STATUS_INVALID_LOCK_SEQUENCE"},
+ {STATUS_INVALID_VIEW_SIZE, -EIO, "STATUS_INVALID_VIEW_SIZE"},
+ {STATUS_INVALID_FILE_FOR_SECTION, -EIO,
+ "STATUS_INVALID_FILE_FOR_SECTION"},
+ {STATUS_ALREADY_COMMITTED, -EIO, "STATUS_ALREADY_COMMITTED"},
+ {STATUS_ACCESS_DENIED, -EACCES, "STATUS_ACCESS_DENIED"},
+ {STATUS_BUFFER_TOO_SMALL, -EIO, "STATUS_BUFFER_TOO_SMALL"},
+ {STATUS_OBJECT_TYPE_MISMATCH, -EIO, "STATUS_OBJECT_TYPE_MISMATCH"},
+ {STATUS_NONCONTINUABLE_EXCEPTION, -EIO,
+ "STATUS_NONCONTINUABLE_EXCEPTION"},
+ {STATUS_INVALID_DISPOSITION, -EIO, "STATUS_INVALID_DISPOSITION"},
+ {STATUS_UNWIND, -EIO, "STATUS_UNWIND"},
+ {STATUS_BAD_STACK, -EIO, "STATUS_BAD_STACK"},
+ {STATUS_INVALID_UNWIND_TARGET, -EIO, "STATUS_INVALID_UNWIND_TARGET"},
+ {STATUS_NOT_LOCKED, -EIO, "STATUS_NOT_LOCKED"},
+ {STATUS_PARITY_ERROR, -EIO, "STATUS_PARITY_ERROR"},
+ {STATUS_UNABLE_TO_DECOMMIT_VM, -EIO, "STATUS_UNABLE_TO_DECOMMIT_VM"},
+ {STATUS_NOT_COMMITTED, -EIO, "STATUS_NOT_COMMITTED"},
+ {STATUS_INVALID_PORT_ATTRIBUTES, -EIO,
+ "STATUS_INVALID_PORT_ATTRIBUTES"},
+ {STATUS_PORT_MESSAGE_TOO_LONG, -EIO, "STATUS_PORT_MESSAGE_TOO_LONG"},
+ {STATUS_INVALID_PARAMETER_MIX, -EINVAL, "STATUS_INVALID_PARAMETER_MIX"},
+ {STATUS_INVALID_QUOTA_LOWER, -EIO, "STATUS_INVALID_QUOTA_LOWER"},
+ {STATUS_DISK_CORRUPT_ERROR, -EIO, "STATUS_DISK_CORRUPT_ERROR"},
+ {STATUS_OBJECT_NAME_INVALID, -ENOENT, "STATUS_OBJECT_NAME_INVALID"},
+ {STATUS_OBJECT_NAME_NOT_FOUND, -ENOENT, "STATUS_OBJECT_NAME_NOT_FOUND"},
+ {STATUS_OBJECT_NAME_COLLISION, -EEXIST, "STATUS_OBJECT_NAME_COLLISION"},
+ {STATUS_PORT_DISCONNECTED, -EIO, "STATUS_PORT_DISCONNECTED"},
+ {STATUS_DEVICE_ALREADY_ATTACHED, -EIO,
+ "STATUS_DEVICE_ALREADY_ATTACHED"},
+ {STATUS_OBJECT_PATH_INVALID, -ENOTDIR, "STATUS_OBJECT_PATH_INVALID"},
+ {STATUS_OBJECT_PATH_NOT_FOUND, -ENOENT, "STATUS_OBJECT_PATH_NOT_FOUND"},
+ {STATUS_OBJECT_PATH_SYNTAX_BAD, -EIO, "STATUS_OBJECT_PATH_SYNTAX_BAD"},
+ {STATUS_DATA_OVERRUN, -EIO, "STATUS_DATA_OVERRUN"},
+ {STATUS_DATA_LATE_ERROR, -EIO, "STATUS_DATA_LATE_ERROR"},
+ {STATUS_DATA_ERROR, -EIO, "STATUS_DATA_ERROR"},
+ {STATUS_CRC_ERROR, -EIO, "STATUS_CRC_ERROR"},
+ {STATUS_SECTION_TOO_BIG, -EIO, "STATUS_SECTION_TOO_BIG"},
+ {STATUS_PORT_CONNECTION_REFUSED, -ECONNREFUSED,
+ "STATUS_PORT_CONNECTION_REFUSED"},
+ {STATUS_INVALID_PORT_HANDLE, -EIO, "STATUS_INVALID_PORT_HANDLE"},
+ {STATUS_SHARING_VIOLATION, -EBUSY, "STATUS_SHARING_VIOLATION"},
+ {STATUS_QUOTA_EXCEEDED, -EDQUOT, "STATUS_QUOTA_EXCEEDED"},
+ {STATUS_INVALID_PAGE_PROTECTION, -EIO,
+ "STATUS_INVALID_PAGE_PROTECTION"},
+ {STATUS_MUTANT_NOT_OWNED, -EIO, "STATUS_MUTANT_NOT_OWNED"},
+ {STATUS_SEMAPHORE_LIMIT_EXCEEDED, -EIO,
+ "STATUS_SEMAPHORE_LIMIT_EXCEEDED"},
+ {STATUS_PORT_ALREADY_SET, -EIO, "STATUS_PORT_ALREADY_SET"},
+ {STATUS_SECTION_NOT_IMAGE, -EIO, "STATUS_SECTION_NOT_IMAGE"},
+ {STATUS_SUSPEND_COUNT_EXCEEDED, -EIO, "STATUS_SUSPEND_COUNT_EXCEEDED"},
+ {STATUS_THREAD_IS_TERMINATING, -EIO, "STATUS_THREAD_IS_TERMINATING"},
+ {STATUS_BAD_WORKING_SET_LIMIT, -EIO, "STATUS_BAD_WORKING_SET_LIMIT"},
+ {STATUS_INCOMPATIBLE_FILE_MAP, -EIO, "STATUS_INCOMPATIBLE_FILE_MAP"},
+ {STATUS_SECTION_PROTECTION, -EIO, "STATUS_SECTION_PROTECTION"},
+ {STATUS_EAS_NOT_SUPPORTED, -EOPNOTSUPP, "STATUS_EAS_NOT_SUPPORTED"},
+ {STATUS_EA_TOO_LARGE, -EIO, "STATUS_EA_TOO_LARGE"},
+ {STATUS_NONEXISTENT_EA_ENTRY, -EIO, "STATUS_NONEXISTENT_EA_ENTRY"},
+ {STATUS_NO_EAS_ON_FILE, -ENODATA, "STATUS_NO_EAS_ON_FILE"},
+ {STATUS_EA_CORRUPT_ERROR, -EIO, "STATUS_EA_CORRUPT_ERROR"},
+ {STATUS_FILE_LOCK_CONFLICT, -EACCES, "STATUS_FILE_LOCK_CONFLICT"},
+ {STATUS_LOCK_NOT_GRANTED, -EACCES, "STATUS_LOCK_NOT_GRANTED"},
+ {STATUS_DELETE_PENDING, -ENOENT, "STATUS_DELETE_PENDING"},
+ {STATUS_CTL_FILE_NOT_SUPPORTED, -ENOSYS,
+ "STATUS_CTL_FILE_NOT_SUPPORTED"},
+ {STATUS_UNKNOWN_REVISION, -EIO, "STATUS_UNKNOWN_REVISION"},
+ {STATUS_REVISION_MISMATCH, -EIO, "STATUS_REVISION_MISMATCH"},
+ {STATUS_INVALID_OWNER, -EIO, "STATUS_INVALID_OWNER"},
+ {STATUS_INVALID_PRIMARY_GROUP, -EIO, "STATUS_INVALID_PRIMARY_GROUP"},
+ {STATUS_NO_IMPERSONATION_TOKEN, -EIO, "STATUS_NO_IMPERSONATION_TOKEN"},
+ {STATUS_CANT_DISABLE_MANDATORY, -EIO, "STATUS_CANT_DISABLE_MANDATORY"},
+ {STATUS_NO_LOGON_SERVERS, -EIO, "STATUS_NO_LOGON_SERVERS"},
+ {STATUS_NO_SUCH_LOGON_SESSION, -EIO, "STATUS_NO_SUCH_LOGON_SESSION"},
+ {STATUS_NO_SUCH_PRIVILEGE, -EIO, "STATUS_NO_SUCH_PRIVILEGE"},
+ {STATUS_PRIVILEGE_NOT_HELD, -EIO, "STATUS_PRIVILEGE_NOT_HELD"},
+ {STATUS_INVALID_ACCOUNT_NAME, -EIO, "STATUS_INVALID_ACCOUNT_NAME"},
+ {STATUS_USER_EXISTS, -EIO, "STATUS_USER_EXISTS"},
+ {STATUS_NO_SUCH_USER, -EIO, "STATUS_NO_SUCH_USER"},
+ {STATUS_GROUP_EXISTS, -EIO, "STATUS_GROUP_EXISTS"},
+ {STATUS_NO_SUCH_GROUP, -EIO, "STATUS_NO_SUCH_GROUP"},
+ {STATUS_MEMBER_IN_GROUP, -EIO, "STATUS_MEMBER_IN_GROUP"},
+ {STATUS_MEMBER_NOT_IN_GROUP, -EIO, "STATUS_MEMBER_NOT_IN_GROUP"},
+ {STATUS_LAST_ADMIN, -EIO, "STATUS_LAST_ADMIN"},
+ {STATUS_WRONG_PASSWORD, -EACCES, "STATUS_WRONG_PASSWORD"},
+ {STATUS_ILL_FORMED_PASSWORD, -EINVAL, "STATUS_ILL_FORMED_PASSWORD"},
+ {STATUS_PASSWORD_RESTRICTION, -EACCES, "STATUS_PASSWORD_RESTRICTION"},
+ {STATUS_LOGON_FAILURE, -EACCES, "STATUS_LOGON_FAILURE"},
+ {STATUS_ACCOUNT_RESTRICTION, -EACCES, "STATUS_ACCOUNT_RESTRICTION"},
+ {STATUS_INVALID_LOGON_HOURS, -EACCES, "STATUS_INVALID_LOGON_HOURS"},
+ {STATUS_INVALID_WORKSTATION, -EACCES, "STATUS_INVALID_WORKSTATION"},
+ {STATUS_PASSWORD_EXPIRED, -EKEYEXPIRED, "STATUS_PASSWORD_EXPIRED"},
+ {STATUS_ACCOUNT_DISABLED, -EKEYREVOKED, "STATUS_ACCOUNT_DISABLED"},
+ {STATUS_NONE_MAPPED, -EIO, "STATUS_NONE_MAPPED"},
+ {STATUS_TOO_MANY_LUIDS_REQUESTED, -EIO,
+ "STATUS_TOO_MANY_LUIDS_REQUESTED"},
+ {STATUS_LUIDS_EXHAUSTED, -EIO, "STATUS_LUIDS_EXHAUSTED"},
+ {STATUS_INVALID_SUB_AUTHORITY, -EIO, "STATUS_INVALID_SUB_AUTHORITY"},
+ {STATUS_INVALID_ACL, -EIO, "STATUS_INVALID_ACL"},
+ {STATUS_INVALID_SID, -EIO, "STATUS_INVALID_SID"},
+ {STATUS_INVALID_SECURITY_DESCR, -EIO, "STATUS_INVALID_SECURITY_DESCR"},
+ {STATUS_PROCEDURE_NOT_FOUND, -EIO, "STATUS_PROCEDURE_NOT_FOUND"},
+ {STATUS_INVALID_IMAGE_FORMAT, -EIO, "STATUS_INVALID_IMAGE_FORMAT"},
+ {STATUS_NO_TOKEN, -EIO, "STATUS_NO_TOKEN"},
+ {STATUS_BAD_INHERITANCE_ACL, -EIO, "STATUS_BAD_INHERITANCE_ACL"},
+ {STATUS_RANGE_NOT_LOCKED, -EIO, "STATUS_RANGE_NOT_LOCKED"},
+ {STATUS_DISK_FULL, -ENOSPC, "STATUS_DISK_FULL"},
+ {STATUS_SERVER_DISABLED, -EIO, "STATUS_SERVER_DISABLED"},
+ {STATUS_SERVER_NOT_DISABLED, -EIO, "STATUS_SERVER_NOT_DISABLED"},
+ {STATUS_TOO_MANY_GUIDS_REQUESTED, -EIO,
+ "STATUS_TOO_MANY_GUIDS_REQUESTED"},
+ {STATUS_GUIDS_EXHAUSTED, -EIO, "STATUS_GUIDS_EXHAUSTED"},
+ {STATUS_INVALID_ID_AUTHORITY, -EIO, "STATUS_INVALID_ID_AUTHORITY"},
+ {STATUS_AGENTS_EXHAUSTED, -EIO, "STATUS_AGENTS_EXHAUSTED"},
+ {STATUS_INVALID_VOLUME_LABEL, -EIO, "STATUS_INVALID_VOLUME_LABEL"},
+ {STATUS_SECTION_NOT_EXTENDED, -EIO, "STATUS_SECTION_NOT_EXTENDED"},
+ {STATUS_NOT_MAPPED_DATA, -EIO, "STATUS_NOT_MAPPED_DATA"},
+ {STATUS_RESOURCE_DATA_NOT_FOUND, -EIO,
+ "STATUS_RESOURCE_DATA_NOT_FOUND"},
+ {STATUS_RESOURCE_TYPE_NOT_FOUND, -EIO,
+ "STATUS_RESOURCE_TYPE_NOT_FOUND"},
+ {STATUS_RESOURCE_NAME_NOT_FOUND, -EIO,
+ "STATUS_RESOURCE_NAME_NOT_FOUND"},
+ {STATUS_ARRAY_BOUNDS_EXCEEDED, -EIO, "STATUS_ARRAY_BOUNDS_EXCEEDED"},
+ {STATUS_FLOAT_DENORMAL_OPERAND, -EIO, "STATUS_FLOAT_DENORMAL_OPERAND"},
+ {STATUS_FLOAT_DIVIDE_BY_ZERO, -EIO, "STATUS_FLOAT_DIVIDE_BY_ZERO"},
+ {STATUS_FLOAT_INEXACT_RESULT, -EIO, "STATUS_FLOAT_INEXACT_RESULT"},
+ {STATUS_FLOAT_INVALID_OPERATION, -EIO,
+ "STATUS_FLOAT_INVALID_OPERATION"},
+ {STATUS_FLOAT_OVERFLOW, -EIO, "STATUS_FLOAT_OVERFLOW"},
+ {STATUS_FLOAT_STACK_CHECK, -EIO, "STATUS_FLOAT_STACK_CHECK"},
+ {STATUS_FLOAT_UNDERFLOW, -EIO, "STATUS_FLOAT_UNDERFLOW"},
+ {STATUS_INTEGER_DIVIDE_BY_ZERO, -EIO, "STATUS_INTEGER_DIVIDE_BY_ZERO"},
+ {STATUS_INTEGER_OVERFLOW, -EIO, "STATUS_INTEGER_OVERFLOW"},
+ {STATUS_PRIVILEGED_INSTRUCTION, -EIO, "STATUS_PRIVILEGED_INSTRUCTION"},
+ {STATUS_TOO_MANY_PAGING_FILES, -EIO, "STATUS_TOO_MANY_PAGING_FILES"},
+ {STATUS_FILE_INVALID, -EIO, "STATUS_FILE_INVALID"},
+ {STATUS_ALLOTTED_SPACE_EXCEEDED, -EIO,
+ "STATUS_ALLOTTED_SPACE_EXCEEDED"},
+ {STATUS_INSUFFICIENT_RESOURCES, -EAGAIN,
+ "STATUS_INSUFFICIENT_RESOURCES"},
+ {STATUS_DFS_EXIT_PATH_FOUND, -EIO, "STATUS_DFS_EXIT_PATH_FOUND"},
+ {STATUS_DEVICE_DATA_ERROR, -EIO, "STATUS_DEVICE_DATA_ERROR"},
+ {STATUS_DEVICE_NOT_CONNECTED, -EIO, "STATUS_DEVICE_NOT_CONNECTED"},
+ {STATUS_DEVICE_POWER_FAILURE, -EIO, "STATUS_DEVICE_POWER_FAILURE"},
+ {STATUS_FREE_VM_NOT_AT_BASE, -EIO, "STATUS_FREE_VM_NOT_AT_BASE"},
+ {STATUS_MEMORY_NOT_ALLOCATED, -EFAULT, "STATUS_MEMORY_NOT_ALLOCATED"},
+ {STATUS_WORKING_SET_QUOTA, -EIO, "STATUS_WORKING_SET_QUOTA"},
+ {STATUS_MEDIA_WRITE_PROTECTED, -EROFS, "STATUS_MEDIA_WRITE_PROTECTED"},
+ {STATUS_DEVICE_NOT_READY, -EIO, "STATUS_DEVICE_NOT_READY"},
+ {STATUS_INVALID_GROUP_ATTRIBUTES, -EIO,
+ "STATUS_INVALID_GROUP_ATTRIBUTES"},
+ {STATUS_BAD_IMPERSONATION_LEVEL, -EIO,
+ "STATUS_BAD_IMPERSONATION_LEVEL"},
+ {STATUS_CANT_OPEN_ANONYMOUS, -EIO, "STATUS_CANT_OPEN_ANONYMOUS"},
+ {STATUS_BAD_VALIDATION_CLASS, -EIO, "STATUS_BAD_VALIDATION_CLASS"},
+ {STATUS_BAD_TOKEN_TYPE, -EIO, "STATUS_BAD_TOKEN_TYPE"},
+ {STATUS_BAD_MASTER_BOOT_RECORD, -EIO, "STATUS_BAD_MASTER_BOOT_RECORD"},
+ {STATUS_INSTRUCTION_MISALIGNMENT, -EIO,
+ "STATUS_INSTRUCTION_MISALIGNMENT"},
+ {STATUS_INSTANCE_NOT_AVAILABLE, -EIO, "STATUS_INSTANCE_NOT_AVAILABLE"},
+ {STATUS_PIPE_NOT_AVAILABLE, -EIO, "STATUS_PIPE_NOT_AVAILABLE"},
+ {STATUS_INVALID_PIPE_STATE, -EIO, "STATUS_INVALID_PIPE_STATE"},
+ {STATUS_PIPE_BUSY, -EBUSY, "STATUS_PIPE_BUSY"},
+ {STATUS_ILLEGAL_FUNCTION, -EIO, "STATUS_ILLEGAL_FUNCTION"},
+ {STATUS_PIPE_DISCONNECTED, -EPIPE, "STATUS_PIPE_DISCONNECTED"},
+ {STATUS_PIPE_CLOSING, -EIO, "STATUS_PIPE_CLOSING"},
+ {STATUS_PIPE_CONNECTED, -EIO, "STATUS_PIPE_CONNECTED"},
+ {STATUS_PIPE_LISTENING, -EIO, "STATUS_PIPE_LISTENING"},
+ {STATUS_INVALID_READ_MODE, -EIO, "STATUS_INVALID_READ_MODE"},
+ {STATUS_IO_TIMEOUT, -EAGAIN, "STATUS_IO_TIMEOUT"},
+ {STATUS_FILE_FORCED_CLOSED, -EIO, "STATUS_FILE_FORCED_CLOSED"},
+ {STATUS_PROFILING_NOT_STARTED, -EIO, "STATUS_PROFILING_NOT_STARTED"},
+ {STATUS_PROFILING_NOT_STOPPED, -EIO, "STATUS_PROFILING_NOT_STOPPED"},
+ {STATUS_COULD_NOT_INTERPRET, -EIO, "STATUS_COULD_NOT_INTERPRET"},
+ {STATUS_FILE_IS_A_DIRECTORY, -EISDIR, "STATUS_FILE_IS_A_DIRECTORY"},
+ {STATUS_NOT_SUPPORTED, -EOPNOTSUPP, "STATUS_NOT_SUPPORTED"},
+ {STATUS_REMOTE_NOT_LISTENING, -EHOSTDOWN,
+ "STATUS_REMOTE_NOT_LISTENING"},
+ {STATUS_DUPLICATE_NAME, -ENOTUNIQ, "STATUS_DUPLICATE_NAME"},
+ {STATUS_BAD_NETWORK_PATH, -EINVAL, "STATUS_BAD_NETWORK_PATH"},
+ {STATUS_NETWORK_BUSY, -EBUSY, "STATUS_NETWORK_BUSY"},
+ {STATUS_DEVICE_DOES_NOT_EXIST, -ENODEV, "STATUS_DEVICE_DOES_NOT_EXIST"},
+ {STATUS_TOO_MANY_COMMANDS, -EIO, "STATUS_TOO_MANY_COMMANDS"},
+ {STATUS_ADAPTER_HARDWARE_ERROR, -EIO, "STATUS_ADAPTER_HARDWARE_ERROR"},
+ {STATUS_INVALID_NETWORK_RESPONSE, -EIO,
+ "STATUS_INVALID_NETWORK_RESPONSE"},
+ {STATUS_UNEXPECTED_NETWORK_ERROR, -EIO,
+ "STATUS_UNEXPECTED_NETWORK_ERROR"},
+ {STATUS_BAD_REMOTE_ADAPTER, -EIO, "STATUS_BAD_REMOTE_ADAPTER"},
+ {STATUS_PRINT_QUEUE_FULL, -EIO, "STATUS_PRINT_QUEUE_FULL"},
+ {STATUS_NO_SPOOL_SPACE, -EIO, "STATUS_NO_SPOOL_SPACE"},
+ {STATUS_PRINT_CANCELLED, -EIO, "STATUS_PRINT_CANCELLED"},
+ {STATUS_NETWORK_NAME_DELETED, -EREMCHG, "STATUS_NETWORK_NAME_DELETED"},
+ {STATUS_NETWORK_ACCESS_DENIED, -EACCES, "STATUS_NETWORK_ACCESS_DENIED"},
+ {STATUS_BAD_DEVICE_TYPE, -EIO, "STATUS_BAD_DEVICE_TYPE"},
+ {STATUS_BAD_NETWORK_NAME, -ENOENT, "STATUS_BAD_NETWORK_NAME"},
+ {STATUS_TOO_MANY_NAMES, -EIO, "STATUS_TOO_MANY_NAMES"},
+ {STATUS_TOO_MANY_SESSIONS, -EIO, "STATUS_TOO_MANY_SESSIONS"},
+ {STATUS_SHARING_PAUSED, -EIO, "STATUS_SHARING_PAUSED"},
+ {STATUS_REQUEST_NOT_ACCEPTED, -EIO, "STATUS_REQUEST_NOT_ACCEPTED"},
+ {STATUS_REDIRECTOR_PAUSED, -EIO, "STATUS_REDIRECTOR_PAUSED"},
+ {STATUS_NET_WRITE_FAULT, -EIO, "STATUS_NET_WRITE_FAULT"},
+ {STATUS_PROFILING_AT_LIMIT, -EIO, "STATUS_PROFILING_AT_LIMIT"},
+ {STATUS_NOT_SAME_DEVICE, -EXDEV, "STATUS_NOT_SAME_DEVICE"},
+ {STATUS_FILE_RENAMED, -EIO, "STATUS_FILE_RENAMED"},
+ {STATUS_VIRTUAL_CIRCUIT_CLOSED, -EIO, "STATUS_VIRTUAL_CIRCUIT_CLOSED"},
+ {STATUS_NO_SECURITY_ON_OBJECT, -EIO, "STATUS_NO_SECURITY_ON_OBJECT"},
+ {STATUS_CANT_WAIT, -EIO, "STATUS_CANT_WAIT"},
+ {STATUS_PIPE_EMPTY, -EIO, "STATUS_PIPE_EMPTY"},
+ {STATUS_CANT_ACCESS_DOMAIN_INFO, -EIO,
+ "STATUS_CANT_ACCESS_DOMAIN_INFO"},
+ {STATUS_CANT_TERMINATE_SELF, -EIO, "STATUS_CANT_TERMINATE_SELF"},
+ {STATUS_INVALID_SERVER_STATE, -EIO, "STATUS_INVALID_SERVER_STATE"},
+ {STATUS_INVALID_DOMAIN_STATE, -EIO, "STATUS_INVALID_DOMAIN_STATE"},
+ {STATUS_INVALID_DOMAIN_ROLE, -EIO, "STATUS_INVALID_DOMAIN_ROLE"},
+ {STATUS_NO_SUCH_DOMAIN, -EIO, "STATUS_NO_SUCH_DOMAIN"},
+ {STATUS_DOMAIN_EXISTS, -EIO, "STATUS_DOMAIN_EXISTS"},
+ {STATUS_DOMAIN_LIMIT_EXCEEDED, -EIO, "STATUS_DOMAIN_LIMIT_EXCEEDED"},
+ {STATUS_OPLOCK_NOT_GRANTED, -EIO, "STATUS_OPLOCK_NOT_GRANTED"},
+ {STATUS_INVALID_OPLOCK_PROTOCOL, -EIO,
+ "STATUS_INVALID_OPLOCK_PROTOCOL"},
+ {STATUS_INTERNAL_DB_CORRUPTION, -EIO, "STATUS_INTERNAL_DB_CORRUPTION"},
+ {STATUS_INTERNAL_ERROR, -EIO, "STATUS_INTERNAL_ERROR"},
+ {STATUS_GENERIC_NOT_MAPPED, -EIO, "STATUS_GENERIC_NOT_MAPPED"},
+ {STATUS_BAD_DESCRIPTOR_FORMAT, -EIO, "STATUS_BAD_DESCRIPTOR_FORMAT"},
+ {STATUS_INVALID_USER_BUFFER, -EIO, "STATUS_INVALID_USER_BUFFER"},
+ {STATUS_UNEXPECTED_IO_ERROR, -EIO, "STATUS_UNEXPECTED_IO_ERROR"},
+ {STATUS_UNEXPECTED_MM_CREATE_ERR, -EIO,
+ "STATUS_UNEXPECTED_MM_CREATE_ERR"},
+ {STATUS_UNEXPECTED_MM_MAP_ERROR, -EIO,
+ "STATUS_UNEXPECTED_MM_MAP_ERROR"},
+ {STATUS_UNEXPECTED_MM_EXTEND_ERR, -EIO,
+ "STATUS_UNEXPECTED_MM_EXTEND_ERR"},
+ {STATUS_NOT_LOGON_PROCESS, -EIO, "STATUS_NOT_LOGON_PROCESS"},
+ {STATUS_LOGON_SESSION_EXISTS, -EIO, "STATUS_LOGON_SESSION_EXISTS"},
+ {STATUS_INVALID_PARAMETER_1, -EINVAL, "STATUS_INVALID_PARAMETER_1"},
+ {STATUS_INVALID_PARAMETER_2, -EINVAL, "STATUS_INVALID_PARAMETER_2"},
+ {STATUS_INVALID_PARAMETER_3, -EINVAL, "STATUS_INVALID_PARAMETER_3"},
+ {STATUS_INVALID_PARAMETER_4, -EINVAL, "STATUS_INVALID_PARAMETER_4"},
+ {STATUS_INVALID_PARAMETER_5, -EINVAL, "STATUS_INVALID_PARAMETER_5"},
+ {STATUS_INVALID_PARAMETER_6, -EINVAL, "STATUS_INVALID_PARAMETER_6"},
+ {STATUS_INVALID_PARAMETER_7, -EINVAL, "STATUS_INVALID_PARAMETER_7"},
+ {STATUS_INVALID_PARAMETER_8, -EINVAL, "STATUS_INVALID_PARAMETER_8"},
+ {STATUS_INVALID_PARAMETER_9, -EINVAL, "STATUS_INVALID_PARAMETER_9"},
+ {STATUS_INVALID_PARAMETER_10, -EINVAL, "STATUS_INVALID_PARAMETER_10"},
+ {STATUS_INVALID_PARAMETER_11, -EINVAL, "STATUS_INVALID_PARAMETER_11"},
+ {STATUS_INVALID_PARAMETER_12, -EINVAL, "STATUS_INVALID_PARAMETER_12"},
+ {STATUS_REDIRECTOR_NOT_STARTED, -EIO, "STATUS_REDIRECTOR_NOT_STARTED"},
+ {STATUS_REDIRECTOR_STARTED, -EIO, "STATUS_REDIRECTOR_STARTED"},
+ {STATUS_STACK_OVERFLOW, -EIO, "STATUS_STACK_OVERFLOW"},
+ {STATUS_NO_SUCH_PACKAGE, -EIO, "STATUS_NO_SUCH_PACKAGE"},
+ {STATUS_BAD_FUNCTION_TABLE, -EIO, "STATUS_BAD_FUNCTION_TABLE"},
+ {STATUS_VARIABLE_NOT_FOUND, -EIO, "STATUS_VARIABLE_NOT_FOUND"},
+ {STATUS_DIRECTORY_NOT_EMPTY, -ENOTEMPTY, "STATUS_DIRECTORY_NOT_EMPTY"},
+ {STATUS_FILE_CORRUPT_ERROR, -EIO, "STATUS_FILE_CORRUPT_ERROR"},
+ {STATUS_NOT_A_DIRECTORY, -ENOTDIR, "STATUS_NOT_A_DIRECTORY"},
+ {STATUS_BAD_LOGON_SESSION_STATE, -EIO,
+ "STATUS_BAD_LOGON_SESSION_STATE"},
+ {STATUS_LOGON_SESSION_COLLISION, -EIO,
+ "STATUS_LOGON_SESSION_COLLISION"},
+ {STATUS_NAME_TOO_LONG, -ENAMETOOLONG, "STATUS_NAME_TOO_LONG"},
+ {STATUS_FILES_OPEN, -EIO, "STATUS_FILES_OPEN"},
+ {STATUS_CONNECTION_IN_USE, -EIO, "STATUS_CONNECTION_IN_USE"},
+ {STATUS_MESSAGE_NOT_FOUND, -EIO, "STATUS_MESSAGE_NOT_FOUND"},
+ {STATUS_PROCESS_IS_TERMINATING, -EIO, "STATUS_PROCESS_IS_TERMINATING"},
+ {STATUS_INVALID_LOGON_TYPE, -EIO, "STATUS_INVALID_LOGON_TYPE"},
+ {STATUS_NO_GUID_TRANSLATION, -EIO, "STATUS_NO_GUID_TRANSLATION"},
+ {STATUS_CANNOT_IMPERSONATE, -EIO, "STATUS_CANNOT_IMPERSONATE"},
+ {STATUS_IMAGE_ALREADY_LOADED, -EIO, "STATUS_IMAGE_ALREADY_LOADED"},
+ {STATUS_ABIOS_NOT_PRESENT, -EIO, "STATUS_ABIOS_NOT_PRESENT"},
+ {STATUS_ABIOS_LID_NOT_EXIST, -EIO, "STATUS_ABIOS_LID_NOT_EXIST"},
+ {STATUS_ABIOS_LID_ALREADY_OWNED, -EIO,
+ "STATUS_ABIOS_LID_ALREADY_OWNED"},
+ {STATUS_ABIOS_NOT_LID_OWNER, -EIO, "STATUS_ABIOS_NOT_LID_OWNER"},
+ {STATUS_ABIOS_INVALID_COMMAND, -EIO, "STATUS_ABIOS_INVALID_COMMAND"},
+ {STATUS_ABIOS_INVALID_LID, -EIO, "STATUS_ABIOS_INVALID_LID"},
+ {STATUS_ABIOS_SELECTOR_NOT_AVAILABLE, -EIO,
+ "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE"},
+ {STATUS_ABIOS_INVALID_SELECTOR, -EIO, "STATUS_ABIOS_INVALID_SELECTOR"},
+ {STATUS_NO_LDT, -EIO, "STATUS_NO_LDT"},
+ {STATUS_INVALID_LDT_SIZE, -EIO, "STATUS_INVALID_LDT_SIZE"},
+ {STATUS_INVALID_LDT_OFFSET, -EIO, "STATUS_INVALID_LDT_OFFSET"},
+ {STATUS_INVALID_LDT_DESCRIPTOR, -EIO, "STATUS_INVALID_LDT_DESCRIPTOR"},
+ {STATUS_INVALID_IMAGE_NE_FORMAT, -EIO,
+ "STATUS_INVALID_IMAGE_NE_FORMAT"},
+ {STATUS_RXACT_INVALID_STATE, -EIO, "STATUS_RXACT_INVALID_STATE"},
+ {STATUS_RXACT_COMMIT_FAILURE, -EIO, "STATUS_RXACT_COMMIT_FAILURE"},
+ {STATUS_MAPPED_FILE_SIZE_ZERO, -EIO, "STATUS_MAPPED_FILE_SIZE_ZERO"},
+ {STATUS_TOO_MANY_OPENED_FILES, -EMFILE, "STATUS_TOO_MANY_OPENED_FILES"},
+ {STATUS_CANCELLED, -EIO, "STATUS_CANCELLED"},
+ {STATUS_CANNOT_DELETE, -EACCES, "STATUS_CANNOT_DELETE"},
+ {STATUS_INVALID_COMPUTER_NAME, -EIO, "STATUS_INVALID_COMPUTER_NAME"},
+ {STATUS_FILE_DELETED, -EIO, "STATUS_FILE_DELETED"},
+ {STATUS_SPECIAL_ACCOUNT, -EIO, "STATUS_SPECIAL_ACCOUNT"},
+ {STATUS_SPECIAL_GROUP, -EIO, "STATUS_SPECIAL_GROUP"},
+ {STATUS_SPECIAL_USER, -EIO, "STATUS_SPECIAL_USER"},
+ {STATUS_MEMBERS_PRIMARY_GROUP, -EIO, "STATUS_MEMBERS_PRIMARY_GROUP"},
+ {STATUS_FILE_CLOSED, -EBADF, "STATUS_FILE_CLOSED"},
+ {STATUS_TOO_MANY_THREADS, -EIO, "STATUS_TOO_MANY_THREADS"},
+ {STATUS_THREAD_NOT_IN_PROCESS, -EIO, "STATUS_THREAD_NOT_IN_PROCESS"},
+ {STATUS_TOKEN_ALREADY_IN_USE, -EIO, "STATUS_TOKEN_ALREADY_IN_USE"},
+ {STATUS_PAGEFILE_QUOTA_EXCEEDED, -EDQUOT,
+ "STATUS_PAGEFILE_QUOTA_EXCEEDED"},
+ {STATUS_COMMITMENT_LIMIT, -EIO, "STATUS_COMMITMENT_LIMIT"},
+ {STATUS_INVALID_IMAGE_LE_FORMAT, -EIO,
+ "STATUS_INVALID_IMAGE_LE_FORMAT"},
+ {STATUS_INVALID_IMAGE_NOT_MZ, -EIO, "STATUS_INVALID_IMAGE_NOT_MZ"},
+ {STATUS_INVALID_IMAGE_PROTECT, -EIO, "STATUS_INVALID_IMAGE_PROTECT"},
+ {STATUS_INVALID_IMAGE_WIN_16, -EIO, "STATUS_INVALID_IMAGE_WIN_16"},
+ {STATUS_LOGON_SERVER_CONFLICT, -EIO, "STATUS_LOGON_SERVER_CONFLICT"},
+ {STATUS_TIME_DIFFERENCE_AT_DC, -EIO, "STATUS_TIME_DIFFERENCE_AT_DC"},
+ {STATUS_SYNCHRONIZATION_REQUIRED, -EIO,
+ "STATUS_SYNCHRONIZATION_REQUIRED"},
+ {STATUS_DLL_NOT_FOUND, -ENOENT, "STATUS_DLL_NOT_FOUND"},
+ {STATUS_OPEN_FAILED, -EIO, "STATUS_OPEN_FAILED"},
+ {STATUS_IO_PRIVILEGE_FAILED, -EIO, "STATUS_IO_PRIVILEGE_FAILED"},
+ {STATUS_ORDINAL_NOT_FOUND, -EIO, "STATUS_ORDINAL_NOT_FOUND"},
+ {STATUS_ENTRYPOINT_NOT_FOUND, -EIO, "STATUS_ENTRYPOINT_NOT_FOUND"},
+ {STATUS_CONTROL_C_EXIT, -EIO, "STATUS_CONTROL_C_EXIT"},
+ {STATUS_LOCAL_DISCONNECT, -EIO, "STATUS_LOCAL_DISCONNECT"},
+ {STATUS_REMOTE_DISCONNECT, -ESHUTDOWN, "STATUS_REMOTE_DISCONNECT"},
+ {STATUS_REMOTE_RESOURCES, -EIO, "STATUS_REMOTE_RESOURCES"},
+ {STATUS_LINK_FAILED, -EXDEV, "STATUS_LINK_FAILED"},
+ {STATUS_LINK_TIMEOUT, -ETIMEDOUT, "STATUS_LINK_TIMEOUT"},
+ {STATUS_INVALID_CONNECTION, -EIO, "STATUS_INVALID_CONNECTION"},
+ {STATUS_INVALID_ADDRESS, -EIO, "STATUS_INVALID_ADDRESS"},
+ {STATUS_DLL_INIT_FAILED, -EIO, "STATUS_DLL_INIT_FAILED"},
+ {STATUS_MISSING_SYSTEMFILE, -EIO, "STATUS_MISSING_SYSTEMFILE"},
+ {STATUS_UNHANDLED_EXCEPTION, -EIO, "STATUS_UNHANDLED_EXCEPTION"},
+ {STATUS_APP_INIT_FAILURE, -EIO, "STATUS_APP_INIT_FAILURE"},
+ {STATUS_PAGEFILE_CREATE_FAILED, -EIO, "STATUS_PAGEFILE_CREATE_FAILED"},
+ {STATUS_NO_PAGEFILE, -EIO, "STATUS_NO_PAGEFILE"},
+ {STATUS_INVALID_LEVEL, -EIO, "STATUS_INVALID_LEVEL"},
+ {STATUS_WRONG_PASSWORD_CORE, -EIO, "STATUS_WRONG_PASSWORD_CORE"},
+ {STATUS_ILLEGAL_FLOAT_CONTEXT, -EIO, "STATUS_ILLEGAL_FLOAT_CONTEXT"},
+ {STATUS_PIPE_BROKEN, -EPIPE, "STATUS_PIPE_BROKEN"},
+ {STATUS_REGISTRY_CORRUPT, -EIO, "STATUS_REGISTRY_CORRUPT"},
+ {STATUS_REGISTRY_IO_FAILED, -EIO, "STATUS_REGISTRY_IO_FAILED"},
+ {STATUS_NO_EVENT_PAIR, -EIO, "STATUS_NO_EVENT_PAIR"},
+ {STATUS_UNRECOGNIZED_VOLUME, -EIO, "STATUS_UNRECOGNIZED_VOLUME"},
+ {STATUS_SERIAL_NO_DEVICE_INITED, -EIO,
+ "STATUS_SERIAL_NO_DEVICE_INITED"},
+ {STATUS_NO_SUCH_ALIAS, -EIO, "STATUS_NO_SUCH_ALIAS"},
+ {STATUS_MEMBER_NOT_IN_ALIAS, -EIO, "STATUS_MEMBER_NOT_IN_ALIAS"},
+ {STATUS_MEMBER_IN_ALIAS, -EIO, "STATUS_MEMBER_IN_ALIAS"},
+ {STATUS_ALIAS_EXISTS, -EIO, "STATUS_ALIAS_EXISTS"},
+ {STATUS_LOGON_NOT_GRANTED, -EIO, "STATUS_LOGON_NOT_GRANTED"},
+ {STATUS_TOO_MANY_SECRETS, -EIO, "STATUS_TOO_MANY_SECRETS"},
+ {STATUS_SECRET_TOO_LONG, -EIO, "STATUS_SECRET_TOO_LONG"},
+ {STATUS_INTERNAL_DB_ERROR, -EIO, "STATUS_INTERNAL_DB_ERROR"},
+ {STATUS_FULLSCREEN_MODE, -EIO, "STATUS_FULLSCREEN_MODE"},
+ {STATUS_TOO_MANY_CONTEXT_IDS, -EIO, "STATUS_TOO_MANY_CONTEXT_IDS"},
+ {STATUS_LOGON_TYPE_NOT_GRANTED, -EIO, "STATUS_LOGON_TYPE_NOT_GRANTED"},
+ {STATUS_NOT_REGISTRY_FILE, -EIO, "STATUS_NOT_REGISTRY_FILE"},
+ {STATUS_NT_CROSS_ENCRYPTION_REQUIRED, -EIO,
+ "STATUS_NT_CROSS_ENCRYPTION_REQUIRED"},
+ {STATUS_DOMAIN_CTRLR_CONFIG_ERROR, -EIO,
+ "STATUS_DOMAIN_CTRLR_CONFIG_ERROR"},
+ {STATUS_FT_MISSING_MEMBER, -EIO, "STATUS_FT_MISSING_MEMBER"},
+ {STATUS_ILL_FORMED_SERVICE_ENTRY, -EIO,
+ "STATUS_ILL_FORMED_SERVICE_ENTRY"},
+ {STATUS_ILLEGAL_CHARACTER, -EIO, "STATUS_ILLEGAL_CHARACTER"},
+ {STATUS_UNMAPPABLE_CHARACTER, -EIO, "STATUS_UNMAPPABLE_CHARACTER"},
+ {STATUS_UNDEFINED_CHARACTER, -EIO, "STATUS_UNDEFINED_CHARACTER"},
+ {STATUS_FLOPPY_VOLUME, -EIO, "STATUS_FLOPPY_VOLUME"},
+ {STATUS_FLOPPY_ID_MARK_NOT_FOUND, -EIO,
+ "STATUS_FLOPPY_ID_MARK_NOT_FOUND"},
+ {STATUS_FLOPPY_WRONG_CYLINDER, -EIO, "STATUS_FLOPPY_WRONG_CYLINDER"},
+ {STATUS_FLOPPY_UNKNOWN_ERROR, -EIO, "STATUS_FLOPPY_UNKNOWN_ERROR"},
+ {STATUS_FLOPPY_BAD_REGISTERS, -EIO, "STATUS_FLOPPY_BAD_REGISTERS"},
+ {STATUS_DISK_RECALIBRATE_FAILED, -EIO,
+ "STATUS_DISK_RECALIBRATE_FAILED"},
+ {STATUS_DISK_OPERATION_FAILED, -EIO, "STATUS_DISK_OPERATION_FAILED"},
+ {STATUS_DISK_RESET_FAILED, -EIO, "STATUS_DISK_RESET_FAILED"},
+ {STATUS_SHARED_IRQ_BUSY, -EBUSY, "STATUS_SHARED_IRQ_BUSY"},
+ {STATUS_FT_ORPHANING, -EIO, "STATUS_FT_ORPHANING"},
+ {STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT, -EIO,
+ "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT"},
+ {STATUS_PARTITION_FAILURE, -EIO, "STATUS_PARTITION_FAILURE"},
+ {STATUS_INVALID_BLOCK_LENGTH, -EIO, "STATUS_INVALID_BLOCK_LENGTH"},
+ {STATUS_DEVICE_NOT_PARTITIONED, -EIO, "STATUS_DEVICE_NOT_PARTITIONED"},
+ {STATUS_UNABLE_TO_LOCK_MEDIA, -EIO, "STATUS_UNABLE_TO_LOCK_MEDIA"},
+ {STATUS_UNABLE_TO_UNLOAD_MEDIA, -EIO, "STATUS_UNABLE_TO_UNLOAD_MEDIA"},
+ {STATUS_EOM_OVERFLOW, -EIO, "STATUS_EOM_OVERFLOW"},
+ {STATUS_NO_MEDIA, -EIO, "STATUS_NO_MEDIA"},
+ {STATUS_NO_SUCH_MEMBER, -EIO, "STATUS_NO_SUCH_MEMBER"},
+ {STATUS_INVALID_MEMBER, -EIO, "STATUS_INVALID_MEMBER"},
+ {STATUS_KEY_DELETED, -EIO, "STATUS_KEY_DELETED"},
+ {STATUS_NO_LOG_SPACE, -EIO, "STATUS_NO_LOG_SPACE"},
+ {STATUS_TOO_MANY_SIDS, -EIO, "STATUS_TOO_MANY_SIDS"},
+ {STATUS_LM_CROSS_ENCRYPTION_REQUIRED, -EIO,
+ "STATUS_LM_CROSS_ENCRYPTION_REQUIRED"},
+ {STATUS_KEY_HAS_CHILDREN, -EIO, "STATUS_KEY_HAS_CHILDREN"},
+ {STATUS_CHILD_MUST_BE_VOLATILE, -EIO, "STATUS_CHILD_MUST_BE_VOLATILE"},
+ {STATUS_DEVICE_CONFIGURATION_ERROR, -EIO,
+ "STATUS_DEVICE_CONFIGURATION_ERROR"},
+ {STATUS_DRIVER_INTERNAL_ERROR, -EIO, "STATUS_DRIVER_INTERNAL_ERROR"},
+ {STATUS_INVALID_DEVICE_STATE, -EIO, "STATUS_INVALID_DEVICE_STATE"},
+ {STATUS_IO_DEVICE_ERROR, -EIO, "STATUS_IO_DEVICE_ERROR"},
+ {STATUS_DEVICE_PROTOCOL_ERROR, -EIO, "STATUS_DEVICE_PROTOCOL_ERROR"},
+ {STATUS_BACKUP_CONTROLLER, -EIO, "STATUS_BACKUP_CONTROLLER"},
+ {STATUS_LOG_FILE_FULL, -EIO, "STATUS_LOG_FILE_FULL"},
+ {STATUS_TOO_LATE, -EIO, "STATUS_TOO_LATE"},
+ {STATUS_NO_TRUST_LSA_SECRET, -EIO, "STATUS_NO_TRUST_LSA_SECRET"},
+ {STATUS_NO_TRUST_SAM_ACCOUNT, -EIO, "STATUS_NO_TRUST_SAM_ACCOUNT"},
+ {STATUS_TRUSTED_DOMAIN_FAILURE, -EIO, "STATUS_TRUSTED_DOMAIN_FAILURE"},
+ {STATUS_TRUSTED_RELATIONSHIP_FAILURE, -EIO,
+ "STATUS_TRUSTED_RELATIONSHIP_FAILURE"},
+ {STATUS_EVENTLOG_FILE_CORRUPT, -EIO, "STATUS_EVENTLOG_FILE_CORRUPT"},
+ {STATUS_EVENTLOG_CANT_START, -EIO, "STATUS_EVENTLOG_CANT_START"},
+ {STATUS_TRUST_FAILURE, -EIO, "STATUS_TRUST_FAILURE"},
+ {STATUS_MUTANT_LIMIT_EXCEEDED, -EIO, "STATUS_MUTANT_LIMIT_EXCEEDED"},
+ {STATUS_NETLOGON_NOT_STARTED, -EIO, "STATUS_NETLOGON_NOT_STARTED"},
+ {STATUS_ACCOUNT_EXPIRED, -EKEYEXPIRED, "STATUS_ACCOUNT_EXPIRED"},
+ {STATUS_POSSIBLE_DEADLOCK, -EIO, "STATUS_POSSIBLE_DEADLOCK"},
+ {STATUS_NETWORK_CREDENTIAL_CONFLICT, -EIO,
+ "STATUS_NETWORK_CREDENTIAL_CONFLICT"},
+ {STATUS_REMOTE_SESSION_LIMIT, -EIO, "STATUS_REMOTE_SESSION_LIMIT"},
+ {STATUS_EVENTLOG_FILE_CHANGED, -EIO, "STATUS_EVENTLOG_FILE_CHANGED"},
+ {STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT, -EIO,
+ "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"},
+ {STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, -EIO,
+ "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"},
+ {STATUS_NOLOGON_SERVER_TRUST_ACCOUNT, -EIO,
+ "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"},
+ {STATUS_DOMAIN_TRUST_INCONSISTENT, -EIO,
+ "STATUS_DOMAIN_TRUST_INCONSISTENT"},
+ {STATUS_FS_DRIVER_REQUIRED, -EOPNOTSUPP, "STATUS_FS_DRIVER_REQUIRED"},
+ {STATUS_IMAGE_ALREADY_LOADED_AS_DLL, -EIO,
+ "STATUS_IMAGE_ALREADY_LOADED_AS_DLL"},
+ {STATUS_NETWORK_OPEN_RESTRICTION, -EIO,
+ "STATUS_NETWORK_OPEN_RESTRICTION"},
+ {STATUS_NO_USER_SESSION_KEY, -EIO, "STATUS_NO_USER_SESSION_KEY"},
+ {STATUS_USER_SESSION_DELETED, -EIO, "STATUS_USER_SESSION_DELETED"},
+ {STATUS_RESOURCE_LANG_NOT_FOUND, -EIO,
+ "STATUS_RESOURCE_LANG_NOT_FOUND"},
+ {STATUS_INSUFF_SERVER_RESOURCES, -EIO,
+ "STATUS_INSUFF_SERVER_RESOURCES"},
+ {STATUS_INVALID_BUFFER_SIZE, -EIO, "STATUS_INVALID_BUFFER_SIZE"},
+ {STATUS_INVALID_ADDRESS_COMPONENT, -EIO,
+ "STATUS_INVALID_ADDRESS_COMPONENT"},
+ {STATUS_INVALID_ADDRESS_WILDCARD, -EIO,
+ "STATUS_INVALID_ADDRESS_WILDCARD"},
+ {STATUS_TOO_MANY_ADDRESSES, -EIO, "STATUS_TOO_MANY_ADDRESSES"},
+ {STATUS_ADDRESS_ALREADY_EXISTS, -EADDRINUSE,
+ "STATUS_ADDRESS_ALREADY_EXISTS"},
+ {STATUS_ADDRESS_CLOSED, -EIO, "STATUS_ADDRESS_CLOSED"},
+ {STATUS_CONNECTION_DISCONNECTED, -ECONNABORTED,
+ "STATUS_CONNECTION_DISCONNECTED"},
+ {STATUS_CONNECTION_RESET, -ENETRESET, "STATUS_CONNECTION_RESET"},
+ {STATUS_TOO_MANY_NODES, -EIO, "STATUS_TOO_MANY_NODES"},
+ {STATUS_TRANSACTION_ABORTED, -EIO, "STATUS_TRANSACTION_ABORTED"},
+ {STATUS_TRANSACTION_TIMED_OUT, -EIO, "STATUS_TRANSACTION_TIMED_OUT"},
+ {STATUS_TRANSACTION_NO_RELEASE, -EIO, "STATUS_TRANSACTION_NO_RELEASE"},
+ {STATUS_TRANSACTION_NO_MATCH, -EIO, "STATUS_TRANSACTION_NO_MATCH"},
+ {STATUS_TRANSACTION_RESPONDED, -EIO, "STATUS_TRANSACTION_RESPONDED"},
+ {STATUS_TRANSACTION_INVALID_ID, -EIO, "STATUS_TRANSACTION_INVALID_ID"},
+ {STATUS_TRANSACTION_INVALID_TYPE, -EIO,
+ "STATUS_TRANSACTION_INVALID_TYPE"},
+ {STATUS_NOT_SERVER_SESSION, -EIO, "STATUS_NOT_SERVER_SESSION"},
+ {STATUS_NOT_CLIENT_SESSION, -EIO, "STATUS_NOT_CLIENT_SESSION"},
+ {STATUS_CANNOT_LOAD_REGISTRY_FILE, -EIO,
+ "STATUS_CANNOT_LOAD_REGISTRY_FILE"},
+ {STATUS_DEBUG_ATTACH_FAILED, -EIO, "STATUS_DEBUG_ATTACH_FAILED"},
+ {STATUS_SYSTEM_PROCESS_TERMINATED, -EIO,
+ "STATUS_SYSTEM_PROCESS_TERMINATED"},
+ {STATUS_DATA_NOT_ACCEPTED, -EIO, "STATUS_DATA_NOT_ACCEPTED"},
+ {STATUS_NO_BROWSER_SERVERS_FOUND, -EIO,
+ "STATUS_NO_BROWSER_SERVERS_FOUND"},
+ {STATUS_VDM_HARD_ERROR, -EIO, "STATUS_VDM_HARD_ERROR"},
+ {STATUS_DRIVER_CANCEL_TIMEOUT, -EIO, "STATUS_DRIVER_CANCEL_TIMEOUT"},
+ {STATUS_REPLY_MESSAGE_MISMATCH, -EIO, "STATUS_REPLY_MESSAGE_MISMATCH"},
+ {STATUS_MAPPED_ALIGNMENT, -EIO, "STATUS_MAPPED_ALIGNMENT"},
+ {STATUS_IMAGE_CHECKSUM_MISMATCH, -EIO,
+ "STATUS_IMAGE_CHECKSUM_MISMATCH"},
+ {STATUS_LOST_WRITEBEHIND_DATA, -EIO, "STATUS_LOST_WRITEBEHIND_DATA"},
+ {STATUS_CLIENT_SERVER_PARAMETERS_INVALID, -EIO,
+ "STATUS_CLIENT_SERVER_PARAMETERS_INVALID"},
+ {STATUS_PASSWORD_MUST_CHANGE, -EIO, "STATUS_PASSWORD_MUST_CHANGE"},
+ {STATUS_NOT_FOUND, -ENOENT, "STATUS_NOT_FOUND"},
+ {STATUS_NOT_TINY_STREAM, -EIO, "STATUS_NOT_TINY_STREAM"},
+ {STATUS_RECOVERY_FAILURE, -EIO, "STATUS_RECOVERY_FAILURE"},
+ {STATUS_STACK_OVERFLOW_READ, -EIO, "STATUS_STACK_OVERFLOW_READ"},
+ {STATUS_FAIL_CHECK, -EIO, "STATUS_FAIL_CHECK"},
+ {STATUS_DUPLICATE_OBJECTID, -EIO, "STATUS_DUPLICATE_OBJECTID"},
+ {STATUS_OBJECTID_EXISTS, -EIO, "STATUS_OBJECTID_EXISTS"},
+ {STATUS_CONVERT_TO_LARGE, -EIO, "STATUS_CONVERT_TO_LARGE"},
+ {STATUS_RETRY, -EAGAIN, "STATUS_RETRY"},
+ {STATUS_FOUND_OUT_OF_SCOPE, -EIO, "STATUS_FOUND_OUT_OF_SCOPE"},
+ {STATUS_ALLOCATE_BUCKET, -EIO, "STATUS_ALLOCATE_BUCKET"},
+ {STATUS_PROPSET_NOT_FOUND, -EIO, "STATUS_PROPSET_NOT_FOUND"},
+ {STATUS_MARSHALL_OVERFLOW, -EIO, "STATUS_MARSHALL_OVERFLOW"},
+ {STATUS_INVALID_VARIANT, -EIO, "STATUS_INVALID_VARIANT"},
+ {STATUS_DOMAIN_CONTROLLER_NOT_FOUND, -EIO,
+ "STATUS_DOMAIN_CONTROLLER_NOT_FOUND"},
+ {STATUS_ACCOUNT_LOCKED_OUT, -EACCES, "STATUS_ACCOUNT_LOCKED_OUT"},
+ {STATUS_HANDLE_NOT_CLOSABLE, -EIO, "STATUS_HANDLE_NOT_CLOSABLE"},
+ {STATUS_CONNECTION_REFUSED, -EIO, "STATUS_CONNECTION_REFUSED"},
+ {STATUS_GRACEFUL_DISCONNECT, -EIO, "STATUS_GRACEFUL_DISCONNECT"},
+ {STATUS_ADDRESS_ALREADY_ASSOCIATED, -EIO,
+ "STATUS_ADDRESS_ALREADY_ASSOCIATED"},
+ {STATUS_ADDRESS_NOT_ASSOCIATED, -EIO, "STATUS_ADDRESS_NOT_ASSOCIATED"},
+ {STATUS_CONNECTION_INVALID, -EIO, "STATUS_CONNECTION_INVALID"},
+ {STATUS_CONNECTION_ACTIVE, -EIO, "STATUS_CONNECTION_ACTIVE"},
+ {STATUS_NETWORK_UNREACHABLE, -ENETUNREACH,
+ "STATUS_NETWORK_UNREACHABLE"},
+ {STATUS_HOST_UNREACHABLE, -EHOSTDOWN, "STATUS_HOST_UNREACHABLE"},
+ {STATUS_PROTOCOL_UNREACHABLE, -ENETUNREACH,
+ "STATUS_PROTOCOL_UNREACHABLE"},
+ {STATUS_PORT_UNREACHABLE, -ENETUNREACH, "STATUS_PORT_UNREACHABLE"},
+ {STATUS_REQUEST_ABORTED, -EIO, "STATUS_REQUEST_ABORTED"},
+ {STATUS_CONNECTION_ABORTED, -ECONNABORTED, "STATUS_CONNECTION_ABORTED"},
+ {STATUS_BAD_COMPRESSION_BUFFER, -EIO, "STATUS_BAD_COMPRESSION_BUFFER"},
+ {STATUS_USER_MAPPED_FILE, -EIO, "STATUS_USER_MAPPED_FILE"},
+ {STATUS_AUDIT_FAILED, -EIO, "STATUS_AUDIT_FAILED"},
+ {STATUS_TIMER_RESOLUTION_NOT_SET, -EIO,
+ "STATUS_TIMER_RESOLUTION_NOT_SET"},
+ {STATUS_CONNECTION_COUNT_LIMIT, -EIO, "STATUS_CONNECTION_COUNT_LIMIT"},
+ {STATUS_LOGIN_TIME_RESTRICTION, -EACCES,
+ "STATUS_LOGIN_TIME_RESTRICTION"},
+ {STATUS_LOGIN_WKSTA_RESTRICTION, -EACCES,
+ "STATUS_LOGIN_WKSTA_RESTRICTION"},
+ {STATUS_IMAGE_MP_UP_MISMATCH, -EIO, "STATUS_IMAGE_MP_UP_MISMATCH"},
+ {STATUS_INSUFFICIENT_LOGON_INFO, -EIO,
+ "STATUS_INSUFFICIENT_LOGON_INFO"},
+ {STATUS_BAD_DLL_ENTRYPOINT, -EIO, "STATUS_BAD_DLL_ENTRYPOINT"},
+ {STATUS_BAD_SERVICE_ENTRYPOINT, -EIO, "STATUS_BAD_SERVICE_ENTRYPOINT"},
+ {STATUS_LPC_REPLY_LOST, -EIO, "STATUS_LPC_REPLY_LOST"},
+ {STATUS_IP_ADDRESS_CONFLICT1, -EIO, "STATUS_IP_ADDRESS_CONFLICT1"},
+ {STATUS_IP_ADDRESS_CONFLICT2, -EIO, "STATUS_IP_ADDRESS_CONFLICT2"},
+ {STATUS_REGISTRY_QUOTA_LIMIT, -EDQUOT, "STATUS_REGISTRY_QUOTA_LIMIT"},
+ {STATUS_PATH_NOT_COVERED, -EREMOTE, "STATUS_PATH_NOT_COVERED"},
+ {STATUS_NO_CALLBACK_ACTIVE, -EIO, "STATUS_NO_CALLBACK_ACTIVE"},
+ {STATUS_LICENSE_QUOTA_EXCEEDED, -EACCES,
+ "STATUS_LICENSE_QUOTA_EXCEEDED"},
+ {STATUS_PWD_TOO_SHORT, -EIO, "STATUS_PWD_TOO_SHORT"},
+ {STATUS_PWD_TOO_RECENT, -EIO, "STATUS_PWD_TOO_RECENT"},
+ {STATUS_PWD_HISTORY_CONFLICT, -EIO, "STATUS_PWD_HISTORY_CONFLICT"},
+ {STATUS_PLUGPLAY_NO_DEVICE, -EIO, "STATUS_PLUGPLAY_NO_DEVICE"},
+ {STATUS_UNSUPPORTED_COMPRESSION, -EIO,
+ "STATUS_UNSUPPORTED_COMPRESSION"},
+ {STATUS_INVALID_HW_PROFILE, -EIO, "STATUS_INVALID_HW_PROFILE"},
+ {STATUS_INVALID_PLUGPLAY_DEVICE_PATH, -EIO,
+ "STATUS_INVALID_PLUGPLAY_DEVICE_PATH"},
+ {STATUS_DRIVER_ORDINAL_NOT_FOUND, -EIO,
+ "STATUS_DRIVER_ORDINAL_NOT_FOUND"},
+ {STATUS_DRIVER_ENTRYPOINT_NOT_FOUND, -EIO,
+ "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND"},
+ {STATUS_RESOURCE_NOT_OWNED, -EIO, "STATUS_RESOURCE_NOT_OWNED"},
+ {STATUS_TOO_MANY_LINKS, -EMLINK, "STATUS_TOO_MANY_LINKS"},
+ {STATUS_QUOTA_LIST_INCONSISTENT, -EIO,
+ "STATUS_QUOTA_LIST_INCONSISTENT"},
+ {STATUS_FILE_IS_OFFLINE, -EIO, "STATUS_FILE_IS_OFFLINE"},
+ {STATUS_EVALUATION_EXPIRATION, -EIO, "STATUS_EVALUATION_EXPIRATION"},
+ {STATUS_ILLEGAL_DLL_RELOCATION, -EIO, "STATUS_ILLEGAL_DLL_RELOCATION"},
+ {STATUS_LICENSE_VIOLATION, -EIO, "STATUS_LICENSE_VIOLATION"},
+ {STATUS_DLL_INIT_FAILED_LOGOFF, -EIO, "STATUS_DLL_INIT_FAILED_LOGOFF"},
+ {STATUS_DRIVER_UNABLE_TO_LOAD, -EIO, "STATUS_DRIVER_UNABLE_TO_LOAD"},
+ {STATUS_DFS_UNAVAILABLE, -EIO, "STATUS_DFS_UNAVAILABLE"},
+ {STATUS_VOLUME_DISMOUNTED, -EIO, "STATUS_VOLUME_DISMOUNTED"},
+ {STATUS_WX86_INTERNAL_ERROR, -EIO, "STATUS_WX86_INTERNAL_ERROR"},
+ {STATUS_WX86_FLOAT_STACK_CHECK, -EIO, "STATUS_WX86_FLOAT_STACK_CHECK"},
+ {STATUS_VALIDATE_CONTINUE, -EIO, "STATUS_VALIDATE_CONTINUE"},
+ {STATUS_NO_MATCH, -EIO, "STATUS_NO_MATCH"},
+ {STATUS_NO_MORE_MATCHES, -EIO, "STATUS_NO_MORE_MATCHES"},
+ {STATUS_NOT_A_REPARSE_POINT, -EIO, "STATUS_NOT_A_REPARSE_POINT"},
+ {STATUS_IO_REPARSE_TAG_INVALID, -EIO, "STATUS_IO_REPARSE_TAG_INVALID"},
+ {STATUS_IO_REPARSE_TAG_MISMATCH, -EIO,
+ "STATUS_IO_REPARSE_TAG_MISMATCH"},
+ {STATUS_IO_REPARSE_DATA_INVALID, -EIO,
+ "STATUS_IO_REPARSE_DATA_INVALID"},
+ {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EIO,
+ "STATUS_IO_REPARSE_TAG_NOT_HANDLED"},
+ {STATUS_REPARSE_POINT_NOT_RESOLVED, -EIO,
+ "STATUS_REPARSE_POINT_NOT_RESOLVED"},
+ {STATUS_DIRECTORY_IS_A_REPARSE_POINT, -EIO,
+ "STATUS_DIRECTORY_IS_A_REPARSE_POINT"},
+ {STATUS_RANGE_LIST_CONFLICT, -EIO, "STATUS_RANGE_LIST_CONFLICT"},
+ {STATUS_SOURCE_ELEMENT_EMPTY, -EIO, "STATUS_SOURCE_ELEMENT_EMPTY"},
+ {STATUS_DESTINATION_ELEMENT_FULL, -EIO,
+ "STATUS_DESTINATION_ELEMENT_FULL"},
+ {STATUS_ILLEGAL_ELEMENT_ADDRESS, -EIO,
+ "STATUS_ILLEGAL_ELEMENT_ADDRESS"},
+ {STATUS_MAGAZINE_NOT_PRESENT, -EIO, "STATUS_MAGAZINE_NOT_PRESENT"},
+ {STATUS_REINITIALIZATION_NEEDED, -EIO,
+ "STATUS_REINITIALIZATION_NEEDED"},
+ {STATUS_ENCRYPTION_FAILED, -EIO, "STATUS_ENCRYPTION_FAILED"},
+ {STATUS_DECRYPTION_FAILED, -EIO, "STATUS_DECRYPTION_FAILED"},
+ {STATUS_RANGE_NOT_FOUND, -EIO, "STATUS_RANGE_NOT_FOUND"},
+ {STATUS_NO_RECOVERY_POLICY, -EIO, "STATUS_NO_RECOVERY_POLICY"},
+ {STATUS_NO_EFS, -EIO, "STATUS_NO_EFS"},
+ {STATUS_WRONG_EFS, -EIO, "STATUS_WRONG_EFS"},
+ {STATUS_NO_USER_KEYS, -EIO, "STATUS_NO_USER_KEYS"},
+ {STATUS_FILE_NOT_ENCRYPTED, -EIO, "STATUS_FILE_NOT_ENCRYPTED"},
+ {STATUS_NOT_EXPORT_FORMAT, -EIO, "STATUS_NOT_EXPORT_FORMAT"},
+ {STATUS_FILE_ENCRYPTED, -EIO, "STATUS_FILE_ENCRYPTED"},
+ {STATUS_WMI_GUID_NOT_FOUND, -EIO, "STATUS_WMI_GUID_NOT_FOUND"},
+ {STATUS_WMI_INSTANCE_NOT_FOUND, -EIO, "STATUS_WMI_INSTANCE_NOT_FOUND"},
+ {STATUS_WMI_ITEMID_NOT_FOUND, -EIO, "STATUS_WMI_ITEMID_NOT_FOUND"},
+ {STATUS_WMI_TRY_AGAIN, -EIO, "STATUS_WMI_TRY_AGAIN"},
+ {STATUS_SHARED_POLICY, -EIO, "STATUS_SHARED_POLICY"},
+ {STATUS_POLICY_OBJECT_NOT_FOUND, -EIO,
+ "STATUS_POLICY_OBJECT_NOT_FOUND"},
+ {STATUS_POLICY_ONLY_IN_DS, -EIO, "STATUS_POLICY_ONLY_IN_DS"},
+ {STATUS_VOLUME_NOT_UPGRADED, -EIO, "STATUS_VOLUME_NOT_UPGRADED"},
+ {STATUS_REMOTE_STORAGE_NOT_ACTIVE, -EIO,
+ "STATUS_REMOTE_STORAGE_NOT_ACTIVE"},
+ {STATUS_REMOTE_STORAGE_MEDIA_ERROR, -EIO,
+ "STATUS_REMOTE_STORAGE_MEDIA_ERROR"},
+ {STATUS_NO_TRACKING_SERVICE, -EIO, "STATUS_NO_TRACKING_SERVICE"},
+ {STATUS_SERVER_SID_MISMATCH, -EIO, "STATUS_SERVER_SID_MISMATCH"},
+ {STATUS_DS_NO_ATTRIBUTE_OR_VALUE, -EIO,
+ "STATUS_DS_NO_ATTRIBUTE_OR_VALUE"},
+ {STATUS_DS_INVALID_ATTRIBUTE_SYNTAX, -EIO,
+ "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX"},
+ {STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED, -EIO,
+ "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED"},
+ {STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS, -EIO,
+ "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS"},
+ {STATUS_DS_BUSY, -EBUSY, "STATUS_DS_BUSY"},
+ {STATUS_DS_UNAVAILABLE, -EIO, "STATUS_DS_UNAVAILABLE"},
+ {STATUS_DS_NO_RIDS_ALLOCATED, -EIO, "STATUS_DS_NO_RIDS_ALLOCATED"},
+ {STATUS_DS_NO_MORE_RIDS, -EIO, "STATUS_DS_NO_MORE_RIDS"},
+ {STATUS_DS_INCORRECT_ROLE_OWNER, -EIO,
+ "STATUS_DS_INCORRECT_ROLE_OWNER"},
+ {STATUS_DS_RIDMGR_INIT_ERROR, -EIO, "STATUS_DS_RIDMGR_INIT_ERROR"},
+ {STATUS_DS_OBJ_CLASS_VIOLATION, -EIO, "STATUS_DS_OBJ_CLASS_VIOLATION"},
+ {STATUS_DS_CANT_ON_NON_LEAF, -EIO, "STATUS_DS_CANT_ON_NON_LEAF"},
+ {STATUS_DS_CANT_ON_RDN, -EIO, "STATUS_DS_CANT_ON_RDN"},
+ {STATUS_DS_CANT_MOD_OBJ_CLASS, -EIO, "STATUS_DS_CANT_MOD_OBJ_CLASS"},
+ {STATUS_DS_CROSS_DOM_MOVE_FAILED, -EIO,
+ "STATUS_DS_CROSS_DOM_MOVE_FAILED"},
+ {STATUS_DS_GC_NOT_AVAILABLE, -EIO, "STATUS_DS_GC_NOT_AVAILABLE"},
+ {STATUS_DIRECTORY_SERVICE_REQUIRED, -EIO,
+ "STATUS_DIRECTORY_SERVICE_REQUIRED"},
+ {STATUS_REPARSE_ATTRIBUTE_CONFLICT, -EIO,
+ "STATUS_REPARSE_ATTRIBUTE_CONFLICT"},
+ {STATUS_CANT_ENABLE_DENY_ONLY, -EIO, "STATUS_CANT_ENABLE_DENY_ONLY"},
+ {STATUS_FLOAT_MULTIPLE_FAULTS, -EIO, "STATUS_FLOAT_MULTIPLE_FAULTS"},
+ {STATUS_FLOAT_MULTIPLE_TRAPS, -EIO, "STATUS_FLOAT_MULTIPLE_TRAPS"},
+ {STATUS_DEVICE_REMOVED, -EIO, "STATUS_DEVICE_REMOVED"},
+ {STATUS_JOURNAL_DELETE_IN_PROGRESS, -EIO,
+ "STATUS_JOURNAL_DELETE_IN_PROGRESS"},
+ {STATUS_JOURNAL_NOT_ACTIVE, -EIO, "STATUS_JOURNAL_NOT_ACTIVE"},
+ {STATUS_NOINTERFACE, -EIO, "STATUS_NOINTERFACE"},
+ {STATUS_DS_ADMIN_LIMIT_EXCEEDED, -EIO,
+ "STATUS_DS_ADMIN_LIMIT_EXCEEDED"},
+ {STATUS_DRIVER_FAILED_SLEEP, -EIO, "STATUS_DRIVER_FAILED_SLEEP"},
+ {STATUS_MUTUAL_AUTHENTICATION_FAILED, -EIO,
+ "STATUS_MUTUAL_AUTHENTICATION_FAILED"},
+ {STATUS_CORRUPT_SYSTEM_FILE, -EIO, "STATUS_CORRUPT_SYSTEM_FILE"},
+ {STATUS_DATATYPE_MISALIGNMENT_ERROR, -EIO,
+ "STATUS_DATATYPE_MISALIGNMENT_ERROR"},
+ {STATUS_WMI_READ_ONLY, -EROFS, "STATUS_WMI_READ_ONLY"},
+ {STATUS_WMI_SET_FAILURE, -EIO, "STATUS_WMI_SET_FAILURE"},
+ {STATUS_COMMITMENT_MINIMUM, -EIO, "STATUS_COMMITMENT_MINIMUM"},
+ {STATUS_REG_NAT_CONSUMPTION, -EIO, "STATUS_REG_NAT_CONSUMPTION"},
+ {STATUS_TRANSPORT_FULL, -EIO, "STATUS_TRANSPORT_FULL"},
+ {STATUS_DS_SAM_INIT_FAILURE, -EIO, "STATUS_DS_SAM_INIT_FAILURE"},
+ {STATUS_ONLY_IF_CONNECTED, -EIO, "STATUS_ONLY_IF_CONNECTED"},
+ {STATUS_DS_SENSITIVE_GROUP_VIOLATION, -EIO,
+ "STATUS_DS_SENSITIVE_GROUP_VIOLATION"},
+ {STATUS_PNP_RESTART_ENUMERATION, -EIO,
+ "STATUS_PNP_RESTART_ENUMERATION"},
+ {STATUS_JOURNAL_ENTRY_DELETED, -EIO, "STATUS_JOURNAL_ENTRY_DELETED"},
+ {STATUS_DS_CANT_MOD_PRIMARYGROUPID, -EIO,
+ "STATUS_DS_CANT_MOD_PRIMARYGROUPID"},
+ {STATUS_SYSTEM_IMAGE_BAD_SIGNATURE, -EIO,
+ "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE"},
+ {STATUS_PNP_REBOOT_REQUIRED, -EIO, "STATUS_PNP_REBOOT_REQUIRED"},
+ {STATUS_POWER_STATE_INVALID, -EIO, "STATUS_POWER_STATE_INVALID"},
+ {STATUS_DS_INVALID_GROUP_TYPE, -EIO, "STATUS_DS_INVALID_GROUP_TYPE"},
+ {STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN, -EIO,
+ "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN"},
+ {STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN, -EIO,
+ "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN"},
+ {STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER, -EIO,
+ "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER"},
+ {STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER, -EIO,
+ "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER"},
+ {STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER, -EIO,
+ "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER"},
+ {STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER, -EIO,
+ "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER"},
+ {STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER, -EIO,
+ "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER"},
+ {STATUS_DS_HAVE_PRIMARY_MEMBERS, -EIO,
+ "STATUS_DS_HAVE_PRIMARY_MEMBERS"},
+ {STATUS_WMI_NOT_SUPPORTED, -EOPNOTSUPP, "STATUS_WMI_NOT_SUPPORTED"},
+ {STATUS_INSUFFICIENT_POWER, -EIO, "STATUS_INSUFFICIENT_POWER"},
+ {STATUS_SAM_NEED_BOOTKEY_PASSWORD, -EIO,
+ "STATUS_SAM_NEED_BOOTKEY_PASSWORD"},
+ {STATUS_SAM_NEED_BOOTKEY_FLOPPY, -EIO,
+ "STATUS_SAM_NEED_BOOTKEY_FLOPPY"},
+ {STATUS_DS_CANT_START, -EIO, "STATUS_DS_CANT_START"},
+ {STATUS_DS_INIT_FAILURE, -EIO, "STATUS_DS_INIT_FAILURE"},
+ {STATUS_SAM_INIT_FAILURE, -EIO, "STATUS_SAM_INIT_FAILURE"},
+ {STATUS_DS_GC_REQUIRED, -EIO, "STATUS_DS_GC_REQUIRED"},
+ {STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY, -EIO,
+ "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY"},
+ {STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS, -EIO,
+ "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS"},
+ {STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED, -EDQUOT,
+ "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED"},
+ {STATUS_MULTIPLE_FAULT_VIOLATION, -EIO,
+ "STATUS_MULTIPLE_FAULT_VIOLATION"},
+ {STATUS_CURRENT_DOMAIN_NOT_ALLOWED, -EIO,
+ "STATUS_CURRENT_DOMAIN_NOT_ALLOWED"},
+ {STATUS_CANNOT_MAKE, -EIO, "STATUS_CANNOT_MAKE"},
+ {STATUS_SYSTEM_SHUTDOWN, -EIO, "STATUS_SYSTEM_SHUTDOWN"},
+ {STATUS_DS_INIT_FAILURE_CONSOLE, -EIO,
+ "STATUS_DS_INIT_FAILURE_CONSOLE"},
+ {STATUS_DS_SAM_INIT_FAILURE_CONSOLE, -EIO,
+ "STATUS_DS_SAM_INIT_FAILURE_CONSOLE"},
+ {STATUS_UNFINISHED_CONTEXT_DELETED, -EIO,
+ "STATUS_UNFINISHED_CONTEXT_DELETED"},
+ {STATUS_NO_TGT_REPLY, -EIO, "STATUS_NO_TGT_REPLY"},
+ /* Note that ENOATTTR and ENODATA are the same errno */
+ {STATUS_OBJECTID_NOT_FOUND, -ENODATA, "STATUS_OBJECTID_NOT_FOUND"},
+ {STATUS_NO_IP_ADDRESSES, -EIO, "STATUS_NO_IP_ADDRESSES"},
+ {STATUS_WRONG_CREDENTIAL_HANDLE, -EIO,
+ "STATUS_WRONG_CREDENTIAL_HANDLE"},
+ {STATUS_CRYPTO_SYSTEM_INVALID, -EIO, "STATUS_CRYPTO_SYSTEM_INVALID"},
+ {STATUS_MAX_REFERRALS_EXCEEDED, -EIO, "STATUS_MAX_REFERRALS_EXCEEDED"},
+ {STATUS_MUST_BE_KDC, -EIO, "STATUS_MUST_BE_KDC"},
+ {STATUS_STRONG_CRYPTO_NOT_SUPPORTED, -EIO,
+ "STATUS_STRONG_CRYPTO_NOT_SUPPORTED"},
+ {STATUS_TOO_MANY_PRINCIPALS, -EIO, "STATUS_TOO_MANY_PRINCIPALS"},
+ {STATUS_NO_PA_DATA, -EIO, "STATUS_NO_PA_DATA"},
+ {STATUS_PKINIT_NAME_MISMATCH, -EIO, "STATUS_PKINIT_NAME_MISMATCH"},
+ {STATUS_SMARTCARD_LOGON_REQUIRED, -EIO,
+ "STATUS_SMARTCARD_LOGON_REQUIRED"},
+ {STATUS_KDC_INVALID_REQUEST, -EIO, "STATUS_KDC_INVALID_REQUEST"},
+ {STATUS_KDC_UNABLE_TO_REFER, -EIO, "STATUS_KDC_UNABLE_TO_REFER"},
+ {STATUS_KDC_UNKNOWN_ETYPE, -EIO, "STATUS_KDC_UNKNOWN_ETYPE"},
+ {STATUS_SHUTDOWN_IN_PROGRESS, -EIO, "STATUS_SHUTDOWN_IN_PROGRESS"},
+ {STATUS_SERVER_SHUTDOWN_IN_PROGRESS, -EIO,
+ "STATUS_SERVER_SHUTDOWN_IN_PROGRESS"},
+ {STATUS_NOT_SUPPORTED_ON_SBS, -EOPNOTSUPP,
+ "STATUS_NOT_SUPPORTED_ON_SBS"},
+ {STATUS_WMI_GUID_DISCONNECTED, -EIO, "STATUS_WMI_GUID_DISCONNECTED"},
+ {STATUS_WMI_ALREADY_DISABLED, -EIO, "STATUS_WMI_ALREADY_DISABLED"},
+ {STATUS_WMI_ALREADY_ENABLED, -EIO, "STATUS_WMI_ALREADY_ENABLED"},
+ {STATUS_MFT_TOO_FRAGMENTED, -EIO, "STATUS_MFT_TOO_FRAGMENTED"},
+ {STATUS_COPY_PROTECTION_FAILURE, -EIO,
+ "STATUS_COPY_PROTECTION_FAILURE"},
+ {STATUS_CSS_AUTHENTICATION_FAILURE, -EIO,
+ "STATUS_CSS_AUTHENTICATION_FAILURE"},
+ {STATUS_CSS_KEY_NOT_PRESENT, -EIO, "STATUS_CSS_KEY_NOT_PRESENT"},
+ {STATUS_CSS_KEY_NOT_ESTABLISHED, -EIO,
+ "STATUS_CSS_KEY_NOT_ESTABLISHED"},
+ {STATUS_CSS_SCRAMBLED_SECTOR, -EIO, "STATUS_CSS_SCRAMBLED_SECTOR"},
+ {STATUS_CSS_REGION_MISMATCH, -EIO, "STATUS_CSS_REGION_MISMATCH"},
+ {STATUS_CSS_RESETS_EXHAUSTED, -EIO, "STATUS_CSS_RESETS_EXHAUSTED"},
+ {STATUS_PKINIT_FAILURE, -EIO, "STATUS_PKINIT_FAILURE"},
+ {STATUS_SMARTCARD_SUBSYSTEM_FAILURE, -EIO,
+ "STATUS_SMARTCARD_SUBSYSTEM_FAILURE"},
+ {STATUS_NO_KERB_KEY, -EIO, "STATUS_NO_KERB_KEY"},
+ {STATUS_HOST_DOWN, -EIO, "STATUS_HOST_DOWN"},
+ {STATUS_UNSUPPORTED_PREAUTH, -EIO, "STATUS_UNSUPPORTED_PREAUTH"},
+ {STATUS_EFS_ALG_BLOB_TOO_BIG, -EIO, "STATUS_EFS_ALG_BLOB_TOO_BIG"},
+ {STATUS_PORT_NOT_SET, -EIO, "STATUS_PORT_NOT_SET"},
+ {STATUS_DEBUGGER_INACTIVE, -EIO, "STATUS_DEBUGGER_INACTIVE"},
+ {STATUS_DS_VERSION_CHECK_FAILURE, -EIO,
+ "STATUS_DS_VERSION_CHECK_FAILURE"},
+ {STATUS_AUDITING_DISABLED, -EIO, "STATUS_AUDITING_DISABLED"},
+ {STATUS_PRENT4_MACHINE_ACCOUNT, -EIO, "STATUS_PRENT4_MACHINE_ACCOUNT"},
+ {STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER, -EIO,
+ "STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER"},
+ {STATUS_INVALID_IMAGE_WIN_32, -EIO, "STATUS_INVALID_IMAGE_WIN_32"},
+ {STATUS_INVALID_IMAGE_WIN_64, -EIO, "STATUS_INVALID_IMAGE_WIN_64"},
+ {STATUS_BAD_BINDINGS, -EIO, "STATUS_BAD_BINDINGS"},
+ {STATUS_NETWORK_SESSION_EXPIRED, -EIO,
+ "STATUS_NETWORK_SESSION_EXPIRED"},
+ {STATUS_APPHELP_BLOCK, -EIO, "STATUS_APPHELP_BLOCK"},
+ {STATUS_ALL_SIDS_FILTERED, -EIO, "STATUS_ALL_SIDS_FILTERED"},
+ {STATUS_NOT_SAFE_MODE_DRIVER, -EIO, "STATUS_NOT_SAFE_MODE_DRIVER"},
+ {STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT, -EACCES,
+ "STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT"},
+ {STATUS_ACCESS_DISABLED_BY_POLICY_PATH, -EACCES,
+ "STATUS_ACCESS_DISABLED_BY_POLICY_PATH"},
+ {STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER, -EACCES,
+ "STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER"},
+ {STATUS_ACCESS_DISABLED_BY_POLICY_OTHER, -EACCES,
+ "STATUS_ACCESS_DISABLED_BY_POLICY_OTHER"},
+ {STATUS_FAILED_DRIVER_ENTRY, -EIO, "STATUS_FAILED_DRIVER_ENTRY"},
+ {STATUS_DEVICE_ENUMERATION_ERROR, -EIO,
+ "STATUS_DEVICE_ENUMERATION_ERROR"},
+ {STATUS_MOUNT_POINT_NOT_RESOLVED, -EIO,
+ "STATUS_MOUNT_POINT_NOT_RESOLVED"},
+ {STATUS_INVALID_DEVICE_OBJECT_PARAMETER, -EIO,
+ "STATUS_INVALID_DEVICE_OBJECT_PARAMETER"},
+ {STATUS_MCA_OCCURED, -EIO, "STATUS_MCA_OCCURED"},
+ {STATUS_DRIVER_BLOCKED_CRITICAL, -EIO,
+ "STATUS_DRIVER_BLOCKED_CRITICAL"},
+ {STATUS_DRIVER_BLOCKED, -EIO, "STATUS_DRIVER_BLOCKED"},
+ {STATUS_DRIVER_DATABASE_ERROR, -EIO, "STATUS_DRIVER_DATABASE_ERROR"},
+ {STATUS_SYSTEM_HIVE_TOO_LARGE, -EIO, "STATUS_SYSTEM_HIVE_TOO_LARGE"},
+ {STATUS_INVALID_IMPORT_OF_NON_DLL, -EIO,
+ "STATUS_INVALID_IMPORT_OF_NON_DLL"},
+ {STATUS_NO_SECRETS, -EIO, "STATUS_NO_SECRETS"},
+ {STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY, -EACCES,
+ "STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY"},
+ {STATUS_FAILED_STACK_SWITCH, -EIO, "STATUS_FAILED_STACK_SWITCH"},
+ {STATUS_HEAP_CORRUPTION, -EIO, "STATUS_HEAP_CORRUPTION"},
+ {STATUS_SMARTCARD_WRONG_PIN, -EIO, "STATUS_SMARTCARD_WRONG_PIN"},
+ {STATUS_SMARTCARD_CARD_BLOCKED, -EIO, "STATUS_SMARTCARD_CARD_BLOCKED"},
+ {STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED, -EIO,
+ "STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED"},
+ {STATUS_SMARTCARD_NO_CARD, -EIO, "STATUS_SMARTCARD_NO_CARD"},
+ {STATUS_SMARTCARD_NO_KEY_CONTAINER, -EIO,
+ "STATUS_SMARTCARD_NO_KEY_CONTAINER"},
+ {STATUS_SMARTCARD_NO_CERTIFICATE, -EIO,
+ "STATUS_SMARTCARD_NO_CERTIFICATE"},
+ {STATUS_SMARTCARD_NO_KEYSET, -EIO, "STATUS_SMARTCARD_NO_KEYSET"},
+ {STATUS_SMARTCARD_IO_ERROR, -EIO, "STATUS_SMARTCARD_IO_ERROR"},
+ {STATUS_DOWNGRADE_DETECTED, -EIO, "STATUS_DOWNGRADE_DETECTED"},
+ {STATUS_SMARTCARD_CERT_REVOKED, -EIO, "STATUS_SMARTCARD_CERT_REVOKED"},
+ {STATUS_ISSUING_CA_UNTRUSTED, -EIO, "STATUS_ISSUING_CA_UNTRUSTED"},
+ {STATUS_REVOCATION_OFFLINE_C, -EIO, "STATUS_REVOCATION_OFFLINE_C"},
+ {STATUS_PKINIT_CLIENT_FAILURE, -EIO, "STATUS_PKINIT_CLIENT_FAILURE"},
+ {STATUS_SMARTCARD_CERT_EXPIRED, -EIO, "STATUS_SMARTCARD_CERT_EXPIRED"},
+ {STATUS_DRIVER_FAILED_PRIOR_UNLOAD, -EIO,
+ "STATUS_DRIVER_FAILED_PRIOR_UNLOAD"},
+ {STATUS_SMARTCARD_SILENT_CONTEXT, -EIO,
+ "STATUS_SMARTCARD_SILENT_CONTEXT"},
+ {STATUS_PER_USER_TRUST_QUOTA_EXCEEDED, -EDQUOT,
+ "STATUS_PER_USER_TRUST_QUOTA_EXCEEDED"},
+ {STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED, -EDQUOT,
+ "STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED"},
+ {STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED, -EDQUOT,
+ "STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED"},
+ {STATUS_DS_NAME_NOT_UNIQUE, -EIO, "STATUS_DS_NAME_NOT_UNIQUE"},
+ {STATUS_DS_DUPLICATE_ID_FOUND, -EIO, "STATUS_DS_DUPLICATE_ID_FOUND"},
+ {STATUS_DS_GROUP_CONVERSION_ERROR, -EIO,
+ "STATUS_DS_GROUP_CONVERSION_ERROR"},
+ {STATUS_VOLSNAP_PREPARE_HIBERNATE, -EIO,
+ "STATUS_VOLSNAP_PREPARE_HIBERNATE"},
+ {STATUS_USER2USER_REQUIRED, -EIO, "STATUS_USER2USER_REQUIRED"},
+ {STATUS_STACK_BUFFER_OVERRUN, -EIO, "STATUS_STACK_BUFFER_OVERRUN"},
+ {STATUS_NO_S4U_PROT_SUPPORT, -EIO, "STATUS_NO_S4U_PROT_SUPPORT"},
+ {STATUS_CROSSREALM_DELEGATION_FAILURE, -EIO,
+ "STATUS_CROSSREALM_DELEGATION_FAILURE"},
+ {STATUS_REVOCATION_OFFLINE_KDC, -EIO, "STATUS_REVOCATION_OFFLINE_KDC"},
+ {STATUS_ISSUING_CA_UNTRUSTED_KDC, -EIO,
+ "STATUS_ISSUING_CA_UNTRUSTED_KDC"},
+ {STATUS_KDC_CERT_EXPIRED, -EIO, "STATUS_KDC_CERT_EXPIRED"},
+ {STATUS_KDC_CERT_REVOKED, -EIO, "STATUS_KDC_CERT_REVOKED"},
+ {STATUS_PARAMETER_QUOTA_EXCEEDED, -EDQUOT,
+ "STATUS_PARAMETER_QUOTA_EXCEEDED"},
+ {STATUS_HIBERNATION_FAILURE, -EIO, "STATUS_HIBERNATION_FAILURE"},
+ {STATUS_DELAY_LOAD_FAILED, -EIO, "STATUS_DELAY_LOAD_FAILED"},
+ {STATUS_AUTHENTICATION_FIREWALL_FAILED, -EIO,
+ "STATUS_AUTHENTICATION_FIREWALL_FAILED"},
+ {STATUS_VDM_DISALLOWED, -EIO, "STATUS_VDM_DISALLOWED"},
+ {STATUS_HUNG_DISPLAY_DRIVER_THREAD, -EIO,
+ "STATUS_HUNG_DISPLAY_DRIVER_THREAD"},
+ {STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE, -EIO,
+ "STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE"},
+ {STATUS_INVALID_CRUNTIME_PARAMETER, -EIO,
+ "STATUS_INVALID_CRUNTIME_PARAMETER"},
+ {STATUS_NTLM_BLOCKED, -EIO, "STATUS_NTLM_BLOCKED"},
+ {STATUS_ASSERTION_FAILURE, -EIO, "STATUS_ASSERTION_FAILURE"},
+ {STATUS_VERIFIER_STOP, -EIO, "STATUS_VERIFIER_STOP"},
+ {STATUS_CALLBACK_POP_STACK, -EIO, "STATUS_CALLBACK_POP_STACK"},
+ {STATUS_INCOMPATIBLE_DRIVER_BLOCKED, -EIO,
+ "STATUS_INCOMPATIBLE_DRIVER_BLOCKED"},
+ {STATUS_HIVE_UNLOADED, -EIO, "STATUS_HIVE_UNLOADED"},
+ {STATUS_COMPRESSION_DISABLED, -EIO, "STATUS_COMPRESSION_DISABLED"},
+ {STATUS_FILE_SYSTEM_LIMITATION, -EIO, "STATUS_FILE_SYSTEM_LIMITATION"},
+ {STATUS_INVALID_IMAGE_HASH, -EIO, "STATUS_INVALID_IMAGE_HASH"},
+ {STATUS_NOT_CAPABLE, -EIO, "STATUS_NOT_CAPABLE"},
+ {STATUS_REQUEST_OUT_OF_SEQUENCE, -EIO,
+ "STATUS_REQUEST_OUT_OF_SEQUENCE"},
+ {STATUS_IMPLEMENTATION_LIMIT, -EIO, "STATUS_IMPLEMENTATION_LIMIT"},
+ {STATUS_ELEVATION_REQUIRED, -EIO, "STATUS_ELEVATION_REQUIRED"},
+ {STATUS_BEYOND_VDL, -EIO, "STATUS_BEYOND_VDL"},
+ {STATUS_ENCOUNTERED_WRITE_IN_PROGRESS, -EIO,
+ "STATUS_ENCOUNTERED_WRITE_IN_PROGRESS"},
+ {STATUS_PTE_CHANGED, -EIO, "STATUS_PTE_CHANGED"},
+ {STATUS_PURGE_FAILED, -EIO, "STATUS_PURGE_FAILED"},
+ {STATUS_CRED_REQUIRES_CONFIRMATION, -EIO,
+ "STATUS_CRED_REQUIRES_CONFIRMATION"},
+ {STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE, -EIO,
+ "STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE"},
+ {STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER, -EIO,
+ "STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER"},
+ {STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE, -EIO,
+ "STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE"},
+ {STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE, -EIO,
+ "STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE"},
+ {STATUS_CS_ENCRYPTION_FILE_NOT_CSE, -EIO,
+ "STATUS_CS_ENCRYPTION_FILE_NOT_CSE"},
+ {STATUS_INVALID_LABEL, -EIO, "STATUS_INVALID_LABEL"},
+ {STATUS_DRIVER_PROCESS_TERMINATED, -EIO,
+ "STATUS_DRIVER_PROCESS_TERMINATED"},
+ {STATUS_AMBIGUOUS_SYSTEM_DEVICE, -EIO,
+ "STATUS_AMBIGUOUS_SYSTEM_DEVICE"},
+ {STATUS_SYSTEM_DEVICE_NOT_FOUND, -EIO,
+ "STATUS_SYSTEM_DEVICE_NOT_FOUND"},
+ {STATUS_RESTART_BOOT_APPLICATION, -EIO,
+ "STATUS_RESTART_BOOT_APPLICATION"},
+ {STATUS_INVALID_TASK_NAME, -EIO, "STATUS_INVALID_TASK_NAME"},
+ {STATUS_INVALID_TASK_INDEX, -EIO, "STATUS_INVALID_TASK_INDEX"},
+ {STATUS_THREAD_ALREADY_IN_TASK, -EIO, "STATUS_THREAD_ALREADY_IN_TASK"},
+ {STATUS_CALLBACK_BYPASS, -EIO, "STATUS_CALLBACK_BYPASS"},
+ {STATUS_PORT_CLOSED, -EIO, "STATUS_PORT_CLOSED"},
+ {STATUS_MESSAGE_LOST, -EIO, "STATUS_MESSAGE_LOST"},
+ {STATUS_INVALID_MESSAGE, -EIO, "STATUS_INVALID_MESSAGE"},
+ {STATUS_REQUEST_CANCELED, -EIO, "STATUS_REQUEST_CANCELED"},
+ {STATUS_RECURSIVE_DISPATCH, -EIO, "STATUS_RECURSIVE_DISPATCH"},
+ {STATUS_LPC_RECEIVE_BUFFER_EXPECTED, -EIO,
+ "STATUS_LPC_RECEIVE_BUFFER_EXPECTED"},
+ {STATUS_LPC_INVALID_CONNECTION_USAGE, -EIO,
+ "STATUS_LPC_INVALID_CONNECTION_USAGE"},
+ {STATUS_LPC_REQUESTS_NOT_ALLOWED, -EIO,
+ "STATUS_LPC_REQUESTS_NOT_ALLOWED"},
+ {STATUS_RESOURCE_IN_USE, -EIO, "STATUS_RESOURCE_IN_USE"},
+ {STATUS_HARDWARE_MEMORY_ERROR, -EIO, "STATUS_HARDWARE_MEMORY_ERROR"},
+ {STATUS_THREADPOOL_HANDLE_EXCEPTION, -EIO,
+ "STATUS_THREADPOOL_HANDLE_EXCEPTION"},
+ {STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED, -EIO,
+ "STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED"},
+ {STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED, -EIO,
+ "STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED"},
+ {STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED, -EIO,
+ "STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED"},
+ {STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED, -EIO,
+ "STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED"},
+ {STATUS_THREADPOOL_RELEASED_DURING_OPERATION, -EIO,
+ "STATUS_THREADPOOL_RELEASED_DURING_OPERATION"},
+ {STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING, -EIO,
+ "STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING"},
+ {STATUS_APC_RETURNED_WHILE_IMPERSONATING, -EIO,
+ "STATUS_APC_RETURNED_WHILE_IMPERSONATING"},
+ {STATUS_PROCESS_IS_PROTECTED, -EIO, "STATUS_PROCESS_IS_PROTECTED"},
+ {STATUS_MCA_EXCEPTION, -EIO, "STATUS_MCA_EXCEPTION"},
+ {STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE, -EIO,
+ "STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE"},
+ {STATUS_SYMLINK_CLASS_DISABLED, -EIO, "STATUS_SYMLINK_CLASS_DISABLED"},
+ {STATUS_INVALID_IDN_NORMALIZATION, -EIO,
+ "STATUS_INVALID_IDN_NORMALIZATION"},
+ {STATUS_NO_UNICODE_TRANSLATION, -EIO, "STATUS_NO_UNICODE_TRANSLATION"},
+ {STATUS_ALREADY_REGISTERED, -EIO, "STATUS_ALREADY_REGISTERED"},
+ {STATUS_CONTEXT_MISMATCH, -EIO, "STATUS_CONTEXT_MISMATCH"},
+ {STATUS_PORT_ALREADY_HAS_COMPLETION_LIST, -EIO,
+ "STATUS_PORT_ALREADY_HAS_COMPLETION_LIST"},
+ {STATUS_CALLBACK_RETURNED_THREAD_PRIORITY, -EIO,
+ "STATUS_CALLBACK_RETURNED_THREAD_PRIORITY"},
+ {STATUS_INVALID_THREAD, -EIO, "STATUS_INVALID_THREAD"},
+ {STATUS_CALLBACK_RETURNED_TRANSACTION, -EIO,
+ "STATUS_CALLBACK_RETURNED_TRANSACTION"},
+ {STATUS_CALLBACK_RETURNED_LDR_LOCK, -EIO,
+ "STATUS_CALLBACK_RETURNED_LDR_LOCK"},
+ {STATUS_CALLBACK_RETURNED_LANG, -EIO, "STATUS_CALLBACK_RETURNED_LANG"},
+ {STATUS_CALLBACK_RETURNED_PRI_BACK, -EIO,
+ "STATUS_CALLBACK_RETURNED_PRI_BACK"},
+ {STATUS_CALLBACK_RETURNED_THREAD_AFFINITY, -EIO,
+ "STATUS_CALLBACK_RETURNED_THREAD_AFFINITY"},
+ {STATUS_DISK_REPAIR_DISABLED, -EIO, "STATUS_DISK_REPAIR_DISABLED"},
+ {STATUS_DS_DOMAIN_RENAME_IN_PROGRESS, -EIO,
+ "STATUS_DS_DOMAIN_RENAME_IN_PROGRESS"},
+ {STATUS_DISK_QUOTA_EXCEEDED, -EDQUOT, "STATUS_DISK_QUOTA_EXCEEDED"},
+ {STATUS_CONTENT_BLOCKED, -EIO, "STATUS_CONTENT_BLOCKED"},
+ {STATUS_BAD_CLUSTERS, -EIO, "STATUS_BAD_CLUSTERS"},
+ {STATUS_VOLUME_DIRTY, -EIO, "STATUS_VOLUME_DIRTY"},
+ {STATUS_FILE_CHECKED_OUT, -EIO, "STATUS_FILE_CHECKED_OUT"},
+ {STATUS_CHECKOUT_REQUIRED, -EIO, "STATUS_CHECKOUT_REQUIRED"},
+ {STATUS_BAD_FILE_TYPE, -EIO, "STATUS_BAD_FILE_TYPE"},
+ {STATUS_FILE_TOO_LARGE, -EIO, "STATUS_FILE_TOO_LARGE"},
+ {STATUS_FORMS_AUTH_REQUIRED, -EIO, "STATUS_FORMS_AUTH_REQUIRED"},
+ {STATUS_VIRUS_INFECTED, -EIO, "STATUS_VIRUS_INFECTED"},
+ {STATUS_VIRUS_DELETED, -EIO, "STATUS_VIRUS_DELETED"},
+ {STATUS_BAD_MCFG_TABLE, -EIO, "STATUS_BAD_MCFG_TABLE"},
+ {STATUS_WOW_ASSERTION, -EIO, "STATUS_WOW_ASSERTION"},
+ {STATUS_INVALID_SIGNATURE, -EIO, "STATUS_INVALID_SIGNATURE"},
+ {STATUS_HMAC_NOT_SUPPORTED, -EIO, "STATUS_HMAC_NOT_SUPPORTED"},
+ {STATUS_IPSEC_QUEUE_OVERFLOW, -EIO, "STATUS_IPSEC_QUEUE_OVERFLOW"},
+ {STATUS_ND_QUEUE_OVERFLOW, -EIO, "STATUS_ND_QUEUE_OVERFLOW"},
+ {STATUS_HOPLIMIT_EXCEEDED, -EIO, "STATUS_HOPLIMIT_EXCEEDED"},
+ {STATUS_PROTOCOL_NOT_SUPPORTED, -EOPNOTSUPP,
+ "STATUS_PROTOCOL_NOT_SUPPORTED"},
+ {STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED, -EIO,
+ "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED"},
+ {STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR, -EIO,
+ "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR"},
+ {STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR, -EIO,
+ "STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR"},
+ {STATUS_XML_PARSE_ERROR, -EIO, "STATUS_XML_PARSE_ERROR"},
+ {STATUS_XMLDSIG_ERROR, -EIO, "STATUS_XMLDSIG_ERROR"},
+ {STATUS_WRONG_COMPARTMENT, -EIO, "STATUS_WRONG_COMPARTMENT"},
+ {STATUS_AUTHIP_FAILURE, -EIO, "STATUS_AUTHIP_FAILURE"},
+ {DBG_NO_STATE_CHANGE, -EIO, "DBG_NO_STATE_CHANGE"},
+ {DBG_APP_NOT_IDLE, -EIO, "DBG_APP_NOT_IDLE"},
+ {RPC_NT_INVALID_STRING_BINDING, -EIO, "RPC_NT_INVALID_STRING_BINDING"},
+ {RPC_NT_WRONG_KIND_OF_BINDING, -EIO, "RPC_NT_WRONG_KIND_OF_BINDING"},
+ {RPC_NT_INVALID_BINDING, -EIO, "RPC_NT_INVALID_BINDING"},
+ {RPC_NT_PROTSEQ_NOT_SUPPORTED, -EOPNOTSUPP,
+ "RPC_NT_PROTSEQ_NOT_SUPPORTED"},
+ {RPC_NT_INVALID_RPC_PROTSEQ, -EIO, "RPC_NT_INVALID_RPC_PROTSEQ"},
+ {RPC_NT_INVALID_STRING_UUID, -EIO, "RPC_NT_INVALID_STRING_UUID"},
+ {RPC_NT_INVALID_ENDPOINT_FORMAT, -EIO,
+ "RPC_NT_INVALID_ENDPOINT_FORMAT"},
+ {RPC_NT_INVALID_NET_ADDR, -EIO, "RPC_NT_INVALID_NET_ADDR"},
+ {RPC_NT_NO_ENDPOINT_FOUND, -EIO, "RPC_NT_NO_ENDPOINT_FOUND"},
+ {RPC_NT_INVALID_TIMEOUT, -EINVAL, "RPC_NT_INVALID_TIMEOUT"},
+ {RPC_NT_OBJECT_NOT_FOUND, -ENOENT, "RPC_NT_OBJECT_NOT_FOUND"},
+ {RPC_NT_ALREADY_REGISTERED, -EIO, "RPC_NT_ALREADY_REGISTERED"},
+ {RPC_NT_TYPE_ALREADY_REGISTERED, -EIO,
+ "RPC_NT_TYPE_ALREADY_REGISTERED"},
+ {RPC_NT_ALREADY_LISTENING, -EIO, "RPC_NT_ALREADY_LISTENING"},
+ {RPC_NT_NO_PROTSEQS_REGISTERED, -EIO, "RPC_NT_NO_PROTSEQS_REGISTERED"},
+ {RPC_NT_NOT_LISTENING, -EIO, "RPC_NT_NOT_LISTENING"},
+ {RPC_NT_UNKNOWN_MGR_TYPE, -EIO, "RPC_NT_UNKNOWN_MGR_TYPE"},
+ {RPC_NT_UNKNOWN_IF, -EIO, "RPC_NT_UNKNOWN_IF"},
+ {RPC_NT_NO_BINDINGS, -EIO, "RPC_NT_NO_BINDINGS"},
+ {RPC_NT_NO_PROTSEQS, -EIO, "RPC_NT_NO_PROTSEQS"},
+ {RPC_NT_CANT_CREATE_ENDPOINT, -EIO, "RPC_NT_CANT_CREATE_ENDPOINT"},
+ {RPC_NT_OUT_OF_RESOURCES, -EIO, "RPC_NT_OUT_OF_RESOURCES"},
+ {RPC_NT_SERVER_UNAVAILABLE, -EIO, "RPC_NT_SERVER_UNAVAILABLE"},
+ {RPC_NT_SERVER_TOO_BUSY, -EBUSY, "RPC_NT_SERVER_TOO_BUSY"},
+ {RPC_NT_INVALID_NETWORK_OPTIONS, -EIO,
+ "RPC_NT_INVALID_NETWORK_OPTIONS"},
+ {RPC_NT_NO_CALL_ACTIVE, -EIO, "RPC_NT_NO_CALL_ACTIVE"},
+ {RPC_NT_CALL_FAILED, -EIO, "RPC_NT_CALL_FAILED"},
+ {RPC_NT_CALL_FAILED_DNE, -EIO, "RPC_NT_CALL_FAILED_DNE"},
+ {RPC_NT_PROTOCOL_ERROR, -EIO, "RPC_NT_PROTOCOL_ERROR"},
+ {RPC_NT_UNSUPPORTED_TRANS_SYN, -EIO, "RPC_NT_UNSUPPORTED_TRANS_SYN"},
+ {RPC_NT_UNSUPPORTED_TYPE, -EIO, "RPC_NT_UNSUPPORTED_TYPE"},
+ {RPC_NT_INVALID_TAG, -EIO, "RPC_NT_INVALID_TAG"},
+ {RPC_NT_INVALID_BOUND, -EIO, "RPC_NT_INVALID_BOUND"},
+ {RPC_NT_NO_ENTRY_NAME, -EIO, "RPC_NT_NO_ENTRY_NAME"},
+ {RPC_NT_INVALID_NAME_SYNTAX, -EIO, "RPC_NT_INVALID_NAME_SYNTAX"},
+ {RPC_NT_UNSUPPORTED_NAME_SYNTAX, -EIO,
+ "RPC_NT_UNSUPPORTED_NAME_SYNTAX"},
+ {RPC_NT_UUID_NO_ADDRESS, -EIO, "RPC_NT_UUID_NO_ADDRESS"},
+ {RPC_NT_DUPLICATE_ENDPOINT, -ENOTUNIQ, "RPC_NT_DUPLICATE_ENDPOINT"},
+ {RPC_NT_UNKNOWN_AUTHN_TYPE, -EIO, "RPC_NT_UNKNOWN_AUTHN_TYPE"},
+ {RPC_NT_MAX_CALLS_TOO_SMALL, -EIO, "RPC_NT_MAX_CALLS_TOO_SMALL"},
+ {RPC_NT_STRING_TOO_LONG, -EIO, "RPC_NT_STRING_TOO_LONG"},
+ {RPC_NT_PROTSEQ_NOT_FOUND, -EIO, "RPC_NT_PROTSEQ_NOT_FOUND"},
+ {RPC_NT_PROCNUM_OUT_OF_RANGE, -EIO, "RPC_NT_PROCNUM_OUT_OF_RANGE"},
+ {RPC_NT_BINDING_HAS_NO_AUTH, -EIO, "RPC_NT_BINDING_HAS_NO_AUTH"},
+ {RPC_NT_UNKNOWN_AUTHN_SERVICE, -EIO, "RPC_NT_UNKNOWN_AUTHN_SERVICE"},
+ {RPC_NT_UNKNOWN_AUTHN_LEVEL, -EIO, "RPC_NT_UNKNOWN_AUTHN_LEVEL"},
+ {RPC_NT_INVALID_AUTH_IDENTITY, -EIO, "RPC_NT_INVALID_AUTH_IDENTITY"},
+ {RPC_NT_UNKNOWN_AUTHZ_SERVICE, -EIO, "RPC_NT_UNKNOWN_AUTHZ_SERVICE"},
+ {EPT_NT_INVALID_ENTRY, -EIO, "EPT_NT_INVALID_ENTRY"},
+ {EPT_NT_CANT_PERFORM_OP, -EIO, "EPT_NT_CANT_PERFORM_OP"},
+ {EPT_NT_NOT_REGISTERED, -EIO, "EPT_NT_NOT_REGISTERED"},
+ {RPC_NT_NOTHING_TO_EXPORT, -EIO, "RPC_NT_NOTHING_TO_EXPORT"},
+ {RPC_NT_INCOMPLETE_NAME, -EIO, "RPC_NT_INCOMPLETE_NAME"},
+ {RPC_NT_INVALID_VERS_OPTION, -EIO, "RPC_NT_INVALID_VERS_OPTION"},
+ {RPC_NT_NO_MORE_MEMBERS, -EIO, "RPC_NT_NO_MORE_MEMBERS"},
+ {RPC_NT_NOT_ALL_OBJS_UNEXPORTED, -EIO,
+ "RPC_NT_NOT_ALL_OBJS_UNEXPORTED"},
+ {RPC_NT_INTERFACE_NOT_FOUND, -EIO, "RPC_NT_INTERFACE_NOT_FOUND"},
+ {RPC_NT_ENTRY_ALREADY_EXISTS, -EIO, "RPC_NT_ENTRY_ALREADY_EXISTS"},
+ {RPC_NT_ENTRY_NOT_FOUND, -EIO, "RPC_NT_ENTRY_NOT_FOUND"},
+ {RPC_NT_NAME_SERVICE_UNAVAILABLE, -EIO,
+ "RPC_NT_NAME_SERVICE_UNAVAILABLE"},
+ {RPC_NT_INVALID_NAF_ID, -EIO, "RPC_NT_INVALID_NAF_ID"},
+ {RPC_NT_CANNOT_SUPPORT, -EOPNOTSUPP, "RPC_NT_CANNOT_SUPPORT"},
+ {RPC_NT_NO_CONTEXT_AVAILABLE, -EIO, "RPC_NT_NO_CONTEXT_AVAILABLE"},
+ {RPC_NT_INTERNAL_ERROR, -EIO, "RPC_NT_INTERNAL_ERROR"},
+ {RPC_NT_ZERO_DIVIDE, -EIO, "RPC_NT_ZERO_DIVIDE"},
+ {RPC_NT_ADDRESS_ERROR, -EIO, "RPC_NT_ADDRESS_ERROR"},
+ {RPC_NT_FP_DIV_ZERO, -EIO, "RPC_NT_FP_DIV_ZERO"},
+ {RPC_NT_FP_UNDERFLOW, -EIO, "RPC_NT_FP_UNDERFLOW"},
+ {RPC_NT_FP_OVERFLOW, -EIO, "RPC_NT_FP_OVERFLOW"},
+ {RPC_NT_CALL_IN_PROGRESS, -EIO, "RPC_NT_CALL_IN_PROGRESS"},
+ {RPC_NT_NO_MORE_BINDINGS, -EIO, "RPC_NT_NO_MORE_BINDINGS"},
+ {RPC_NT_GROUP_MEMBER_NOT_FOUND, -EIO, "RPC_NT_GROUP_MEMBER_NOT_FOUND"},
+ {EPT_NT_CANT_CREATE, -EIO, "EPT_NT_CANT_CREATE"},
+ {RPC_NT_INVALID_OBJECT, -EIO, "RPC_NT_INVALID_OBJECT"},
+ {RPC_NT_NO_INTERFACES, -EIO, "RPC_NT_NO_INTERFACES"},
+ {RPC_NT_CALL_CANCELLED, -EIO, "RPC_NT_CALL_CANCELLED"},
+ {RPC_NT_BINDING_INCOMPLETE, -EIO, "RPC_NT_BINDING_INCOMPLETE"},
+ {RPC_NT_COMM_FAILURE, -EIO, "RPC_NT_COMM_FAILURE"},
+ {RPC_NT_UNSUPPORTED_AUTHN_LEVEL, -EIO,
+ "RPC_NT_UNSUPPORTED_AUTHN_LEVEL"},
+ {RPC_NT_NO_PRINC_NAME, -EIO, "RPC_NT_NO_PRINC_NAME"},
+ {RPC_NT_NOT_RPC_ERROR, -EIO, "RPC_NT_NOT_RPC_ERROR"},
+ {RPC_NT_SEC_PKG_ERROR, -EIO, "RPC_NT_SEC_PKG_ERROR"},
+ {RPC_NT_NOT_CANCELLED, -EIO, "RPC_NT_NOT_CANCELLED"},
+ {RPC_NT_INVALID_ASYNC_HANDLE, -EIO, "RPC_NT_INVALID_ASYNC_HANDLE"},
+ {RPC_NT_INVALID_ASYNC_CALL, -EIO, "RPC_NT_INVALID_ASYNC_CALL"},
+ {RPC_NT_PROXY_ACCESS_DENIED, -EACCES, "RPC_NT_PROXY_ACCESS_DENIED"},
+ {RPC_NT_NO_MORE_ENTRIES, -EIO, "RPC_NT_NO_MORE_ENTRIES"},
+ {RPC_NT_SS_CHAR_TRANS_OPEN_FAIL, -EIO,
+ "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL"},
+ {RPC_NT_SS_CHAR_TRANS_SHORT_FILE, -EIO,
+ "RPC_NT_SS_CHAR_TRANS_SHORT_FILE"},
+ {RPC_NT_SS_IN_NULL_CONTEXT, -EIO, "RPC_NT_SS_IN_NULL_CONTEXT"},
+ {RPC_NT_SS_CONTEXT_MISMATCH, -EIO, "RPC_NT_SS_CONTEXT_MISMATCH"},
+ {RPC_NT_SS_CONTEXT_DAMAGED, -EIO, "RPC_NT_SS_CONTEXT_DAMAGED"},
+ {RPC_NT_SS_HANDLES_MISMATCH, -EIO, "RPC_NT_SS_HANDLES_MISMATCH"},
+ {RPC_NT_SS_CANNOT_GET_CALL_HANDLE, -EIO,
+ "RPC_NT_SS_CANNOT_GET_CALL_HANDLE"},
+ {RPC_NT_NULL_REF_POINTER, -EIO, "RPC_NT_NULL_REF_POINTER"},
+ {RPC_NT_ENUM_VALUE_OUT_OF_RANGE, -EIO,
+ "RPC_NT_ENUM_VALUE_OUT_OF_RANGE"},
+ {RPC_NT_BYTE_COUNT_TOO_SMALL, -EIO, "RPC_NT_BYTE_COUNT_TOO_SMALL"},
+ {RPC_NT_BAD_STUB_DATA, -EIO, "RPC_NT_BAD_STUB_DATA"},
+ {RPC_NT_INVALID_ES_ACTION, -EIO, "RPC_NT_INVALID_ES_ACTION"},
+ {RPC_NT_WRONG_ES_VERSION, -EIO, "RPC_NT_WRONG_ES_VERSION"},
+ {RPC_NT_WRONG_STUB_VERSION, -EIO, "RPC_NT_WRONG_STUB_VERSION"},
+ {RPC_NT_INVALID_PIPE_OBJECT, -EIO, "RPC_NT_INVALID_PIPE_OBJECT"},
+ {RPC_NT_INVALID_PIPE_OPERATION, -EIO, "RPC_NT_INVALID_PIPE_OPERATION"},
+ {RPC_NT_WRONG_PIPE_VERSION, -EIO, "RPC_NT_WRONG_PIPE_VERSION"},
+ {RPC_NT_PIPE_CLOSED, -EIO, "RPC_NT_PIPE_CLOSED"},
+ {RPC_NT_PIPE_DISCIPLINE_ERROR, -EIO, "RPC_NT_PIPE_DISCIPLINE_ERROR"},
+ {RPC_NT_PIPE_EMPTY, -EIO, "RPC_NT_PIPE_EMPTY"},
+ {STATUS_PNP_BAD_MPS_TABLE, -EIO, "STATUS_PNP_BAD_MPS_TABLE"},
+ {STATUS_PNP_TRANSLATION_FAILED, -EIO, "STATUS_PNP_TRANSLATION_FAILED"},
+ {STATUS_PNP_IRQ_TRANSLATION_FAILED, -EIO,
+ "STATUS_PNP_IRQ_TRANSLATION_FAILED"},
+ {STATUS_PNP_INVALID_ID, -EIO, "STATUS_PNP_INVALID_ID"},
+ {STATUS_IO_REISSUE_AS_CACHED, -EIO, "STATUS_IO_REISSUE_AS_CACHED"},
+ {STATUS_CTX_WINSTATION_NAME_INVALID, -EIO,
+ "STATUS_CTX_WINSTATION_NAME_INVALID"},
+ {STATUS_CTX_INVALID_PD, -EIO, "STATUS_CTX_INVALID_PD"},
+ {STATUS_CTX_PD_NOT_FOUND, -EIO, "STATUS_CTX_PD_NOT_FOUND"},
+ {STATUS_CTX_CLOSE_PENDING, -EIO, "STATUS_CTX_CLOSE_PENDING"},
+ {STATUS_CTX_NO_OUTBUF, -EIO, "STATUS_CTX_NO_OUTBUF"},
+ {STATUS_CTX_MODEM_INF_NOT_FOUND, -EIO,
+ "STATUS_CTX_MODEM_INF_NOT_FOUND"},
+ {STATUS_CTX_INVALID_MODEMNAME, -EIO, "STATUS_CTX_INVALID_MODEMNAME"},
+ {STATUS_CTX_RESPONSE_ERROR, -EIO, "STATUS_CTX_RESPONSE_ERROR"},
+ {STATUS_CTX_MODEM_RESPONSE_TIMEOUT, -ETIMEDOUT,
+ "STATUS_CTX_MODEM_RESPONSE_TIMEOUT"},
+ {STATUS_CTX_MODEM_RESPONSE_NO_CARRIER, -EIO,
+ "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER"},
+ {STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE, -EIO,
+ "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE"},
+ {STATUS_CTX_MODEM_RESPONSE_BUSY, -EBUSY,
+ "STATUS_CTX_MODEM_RESPONSE_BUSY"},
+ {STATUS_CTX_MODEM_RESPONSE_VOICE, -EIO,
+ "STATUS_CTX_MODEM_RESPONSE_VOICE"},
+ {STATUS_CTX_TD_ERROR, -EIO, "STATUS_CTX_TD_ERROR"},
+ {STATUS_CTX_LICENSE_CLIENT_INVALID, -EIO,
+ "STATUS_CTX_LICENSE_CLIENT_INVALID"},
+ {STATUS_CTX_LICENSE_NOT_AVAILABLE, -EIO,
+ "STATUS_CTX_LICENSE_NOT_AVAILABLE"},
+ {STATUS_CTX_LICENSE_EXPIRED, -EIO, "STATUS_CTX_LICENSE_EXPIRED"},
+ {STATUS_CTX_WINSTATION_NOT_FOUND, -EIO,
+ "STATUS_CTX_WINSTATION_NOT_FOUND"},
+ {STATUS_CTX_WINSTATION_NAME_COLLISION, -EIO,
+ "STATUS_CTX_WINSTATION_NAME_COLLISION"},
+ {STATUS_CTX_WINSTATION_BUSY, -EBUSY, "STATUS_CTX_WINSTATION_BUSY"},
+ {STATUS_CTX_BAD_VIDEO_MODE, -EIO, "STATUS_CTX_BAD_VIDEO_MODE"},
+ {STATUS_CTX_GRAPHICS_INVALID, -EIO, "STATUS_CTX_GRAPHICS_INVALID"},
+ {STATUS_CTX_NOT_CONSOLE, -EIO, "STATUS_CTX_NOT_CONSOLE"},
+ {STATUS_CTX_CLIENT_QUERY_TIMEOUT, -EIO,
+ "STATUS_CTX_CLIENT_QUERY_TIMEOUT"},
+ {STATUS_CTX_CONSOLE_DISCONNECT, -EIO, "STATUS_CTX_CONSOLE_DISCONNECT"},
+ {STATUS_CTX_CONSOLE_CONNECT, -EIO, "STATUS_CTX_CONSOLE_CONNECT"},
+ {STATUS_CTX_SHADOW_DENIED, -EIO, "STATUS_CTX_SHADOW_DENIED"},
+ {STATUS_CTX_WINSTATION_ACCESS_DENIED, -EACCES,
+ "STATUS_CTX_WINSTATION_ACCESS_DENIED"},
+ {STATUS_CTX_INVALID_WD, -EIO, "STATUS_CTX_INVALID_WD"},
+ {STATUS_CTX_WD_NOT_FOUND, -EIO, "STATUS_CTX_WD_NOT_FOUND"},
+ {STATUS_CTX_SHADOW_INVALID, -EIO, "STATUS_CTX_SHADOW_INVALID"},
+ {STATUS_CTX_SHADOW_DISABLED, -EIO, "STATUS_CTX_SHADOW_DISABLED"},
+ {STATUS_RDP_PROTOCOL_ERROR, -EIO, "STATUS_RDP_PROTOCOL_ERROR"},
+ {STATUS_CTX_CLIENT_LICENSE_NOT_SET, -EIO,
+ "STATUS_CTX_CLIENT_LICENSE_NOT_SET"},
+ {STATUS_CTX_CLIENT_LICENSE_IN_USE, -EIO,
+ "STATUS_CTX_CLIENT_LICENSE_IN_USE"},
+ {STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE, -EIO,
+ "STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE"},
+ {STATUS_CTX_SHADOW_NOT_RUNNING, -EIO, "STATUS_CTX_SHADOW_NOT_RUNNING"},
+ {STATUS_CTX_LOGON_DISABLED, -EIO, "STATUS_CTX_LOGON_DISABLED"},
+ {STATUS_CTX_SECURITY_LAYER_ERROR, -EIO,
+ "STATUS_CTX_SECURITY_LAYER_ERROR"},
+ {STATUS_TS_INCOMPATIBLE_SESSIONS, -EIO,
+ "STATUS_TS_INCOMPATIBLE_SESSIONS"},
+ {STATUS_MUI_FILE_NOT_FOUND, -EIO, "STATUS_MUI_FILE_NOT_FOUND"},
+ {STATUS_MUI_INVALID_FILE, -EIO, "STATUS_MUI_INVALID_FILE"},
+ {STATUS_MUI_INVALID_RC_CONFIG, -EIO, "STATUS_MUI_INVALID_RC_CONFIG"},
+ {STATUS_MUI_INVALID_LOCALE_NAME, -EIO,
+ "STATUS_MUI_INVALID_LOCALE_NAME"},
+ {STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME, -EIO,
+ "STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME"},
+ {STATUS_MUI_FILE_NOT_LOADED, -EIO, "STATUS_MUI_FILE_NOT_LOADED"},
+ {STATUS_RESOURCE_ENUM_USER_STOP, -EIO,
+ "STATUS_RESOURCE_ENUM_USER_STOP"},
+ {STATUS_CLUSTER_INVALID_NODE, -EIO, "STATUS_CLUSTER_INVALID_NODE"},
+ {STATUS_CLUSTER_NODE_EXISTS, -EIO, "STATUS_CLUSTER_NODE_EXISTS"},
+ {STATUS_CLUSTER_JOIN_IN_PROGRESS, -EIO,
+ "STATUS_CLUSTER_JOIN_IN_PROGRESS"},
+ {STATUS_CLUSTER_NODE_NOT_FOUND, -EIO, "STATUS_CLUSTER_NODE_NOT_FOUND"},
+ {STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND, -EIO,
+ "STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND"},
+ {STATUS_CLUSTER_NETWORK_EXISTS, -EIO, "STATUS_CLUSTER_NETWORK_EXISTS"},
+ {STATUS_CLUSTER_NETWORK_NOT_FOUND, -EIO,
+ "STATUS_CLUSTER_NETWORK_NOT_FOUND"},
+ {STATUS_CLUSTER_NETINTERFACE_EXISTS, -EIO,
+ "STATUS_CLUSTER_NETINTERFACE_EXISTS"},
+ {STATUS_CLUSTER_NETINTERFACE_NOT_FOUND, -EIO,
+ "STATUS_CLUSTER_NETINTERFACE_NOT_FOUND"},
+ {STATUS_CLUSTER_INVALID_REQUEST, -EIO,
+ "STATUS_CLUSTER_INVALID_REQUEST"},
+ {STATUS_CLUSTER_INVALID_NETWORK_PROVIDER, -EIO,
+ "STATUS_CLUSTER_INVALID_NETWORK_PROVIDER"},
+ {STATUS_CLUSTER_NODE_DOWN, -EIO, "STATUS_CLUSTER_NODE_DOWN"},
+ {STATUS_CLUSTER_NODE_UNREACHABLE, -EIO,
+ "STATUS_CLUSTER_NODE_UNREACHABLE"},
+ {STATUS_CLUSTER_NODE_NOT_MEMBER, -EIO,
+ "STATUS_CLUSTER_NODE_NOT_MEMBER"},
+ {STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS, -EIO,
+ "STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS"},
+ {STATUS_CLUSTER_INVALID_NETWORK, -EIO,
+ "STATUS_CLUSTER_INVALID_NETWORK"},
+ {STATUS_CLUSTER_NO_NET_ADAPTERS, -EIO,
+ "STATUS_CLUSTER_NO_NET_ADAPTERS"},
+ {STATUS_CLUSTER_NODE_UP, -EIO, "STATUS_CLUSTER_NODE_UP"},
+ {STATUS_CLUSTER_NODE_PAUSED, -EIO, "STATUS_CLUSTER_NODE_PAUSED"},
+ {STATUS_CLUSTER_NODE_NOT_PAUSED, -EIO,
+ "STATUS_CLUSTER_NODE_NOT_PAUSED"},
+ {STATUS_CLUSTER_NO_SECURITY_CONTEXT, -EIO,
+ "STATUS_CLUSTER_NO_SECURITY_CONTEXT"},
+ {STATUS_CLUSTER_NETWORK_NOT_INTERNAL, -EIO,
+ "STATUS_CLUSTER_NETWORK_NOT_INTERNAL"},
+ {STATUS_CLUSTER_POISONED, -EIO, "STATUS_CLUSTER_POISONED"},
+ {STATUS_ACPI_INVALID_OPCODE, -EIO, "STATUS_ACPI_INVALID_OPCODE"},
+ {STATUS_ACPI_STACK_OVERFLOW, -EIO, "STATUS_ACPI_STACK_OVERFLOW"},
+ {STATUS_ACPI_ASSERT_FAILED, -EIO, "STATUS_ACPI_ASSERT_FAILED"},
+ {STATUS_ACPI_INVALID_INDEX, -EIO, "STATUS_ACPI_INVALID_INDEX"},
+ {STATUS_ACPI_INVALID_ARGUMENT, -EIO, "STATUS_ACPI_INVALID_ARGUMENT"},
+ {STATUS_ACPI_FATAL, -EIO, "STATUS_ACPI_FATAL"},
+ {STATUS_ACPI_INVALID_SUPERNAME, -EIO, "STATUS_ACPI_INVALID_SUPERNAME"},
+ {STATUS_ACPI_INVALID_ARGTYPE, -EIO, "STATUS_ACPI_INVALID_ARGTYPE"},
+ {STATUS_ACPI_INVALID_OBJTYPE, -EIO, "STATUS_ACPI_INVALID_OBJTYPE"},
+ {STATUS_ACPI_INVALID_TARGETTYPE, -EIO,
+ "STATUS_ACPI_INVALID_TARGETTYPE"},
+ {STATUS_ACPI_INCORRECT_ARGUMENT_COUNT, -EIO,
+ "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT"},
+ {STATUS_ACPI_ADDRESS_NOT_MAPPED, -EIO,
+ "STATUS_ACPI_ADDRESS_NOT_MAPPED"},
+ {STATUS_ACPI_INVALID_EVENTTYPE, -EIO, "STATUS_ACPI_INVALID_EVENTTYPE"},
+ {STATUS_ACPI_HANDLER_COLLISION, -EIO, "STATUS_ACPI_HANDLER_COLLISION"},
+ {STATUS_ACPI_INVALID_DATA, -EIO, "STATUS_ACPI_INVALID_DATA"},
+ {STATUS_ACPI_INVALID_REGION, -EIO, "STATUS_ACPI_INVALID_REGION"},
+ {STATUS_ACPI_INVALID_ACCESS_SIZE, -EIO,
+ "STATUS_ACPI_INVALID_ACCESS_SIZE"},
+ {STATUS_ACPI_ACQUIRE_GLOBAL_LOCK, -EIO,
+ "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK"},
+ {STATUS_ACPI_ALREADY_INITIALIZED, -EIO,
+ "STATUS_ACPI_ALREADY_INITIALIZED"},
+ {STATUS_ACPI_NOT_INITIALIZED, -EIO, "STATUS_ACPI_NOT_INITIALIZED"},
+ {STATUS_ACPI_INVALID_MUTEX_LEVEL, -EIO,
+ "STATUS_ACPI_INVALID_MUTEX_LEVEL"},
+ {STATUS_ACPI_MUTEX_NOT_OWNED, -EIO, "STATUS_ACPI_MUTEX_NOT_OWNED"},
+ {STATUS_ACPI_MUTEX_NOT_OWNER, -EIO, "STATUS_ACPI_MUTEX_NOT_OWNER"},
+ {STATUS_ACPI_RS_ACCESS, -EIO, "STATUS_ACPI_RS_ACCESS"},
+ {STATUS_ACPI_INVALID_TABLE, -EIO, "STATUS_ACPI_INVALID_TABLE"},
+ {STATUS_ACPI_REG_HANDLER_FAILED, -EIO,
+ "STATUS_ACPI_REG_HANDLER_FAILED"},
+ {STATUS_ACPI_POWER_REQUEST_FAILED, -EIO,
+ "STATUS_ACPI_POWER_REQUEST_FAILED"},
+ {STATUS_SXS_SECTION_NOT_FOUND, -EIO, "STATUS_SXS_SECTION_NOT_FOUND"},
+ {STATUS_SXS_CANT_GEN_ACTCTX, -EIO, "STATUS_SXS_CANT_GEN_ACTCTX"},
+ {STATUS_SXS_INVALID_ACTCTXDATA_FORMAT, -EIO,
+ "STATUS_SXS_INVALID_ACTCTXDATA_FORMAT"},
+ {STATUS_SXS_ASSEMBLY_NOT_FOUND, -EIO, "STATUS_SXS_ASSEMBLY_NOT_FOUND"},
+ {STATUS_SXS_MANIFEST_FORMAT_ERROR, -EIO,
+ "STATUS_SXS_MANIFEST_FORMAT_ERROR"},
+ {STATUS_SXS_MANIFEST_PARSE_ERROR, -EIO,
+ "STATUS_SXS_MANIFEST_PARSE_ERROR"},
+ {STATUS_SXS_ACTIVATION_CONTEXT_DISABLED, -EIO,
+ "STATUS_SXS_ACTIVATION_CONTEXT_DISABLED"},
+ {STATUS_SXS_KEY_NOT_FOUND, -EIO, "STATUS_SXS_KEY_NOT_FOUND"},
+ {STATUS_SXS_VERSION_CONFLICT, -EIO, "STATUS_SXS_VERSION_CONFLICT"},
+ {STATUS_SXS_WRONG_SECTION_TYPE, -EIO, "STATUS_SXS_WRONG_SECTION_TYPE"},
+ {STATUS_SXS_THREAD_QUERIES_DISABLED, -EIO,
+ "STATUS_SXS_THREAD_QUERIES_DISABLED"},
+ {STATUS_SXS_ASSEMBLY_MISSING, -EIO, "STATUS_SXS_ASSEMBLY_MISSING"},
+ {STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET, -EIO,
+ "STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET"},
+ {STATUS_SXS_EARLY_DEACTIVATION, -EIO, "STATUS_SXS_EARLY_DEACTIVATION"},
+ {STATUS_SXS_INVALID_DEACTIVATION, -EIO,
+ "STATUS_SXS_INVALID_DEACTIVATION"},
+ {STATUS_SXS_MULTIPLE_DEACTIVATION, -EIO,
+ "STATUS_SXS_MULTIPLE_DEACTIVATION"},
+ {STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY, -EIO,
+ "STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY"},
+ {STATUS_SXS_PROCESS_TERMINATION_REQUESTED, -EIO,
+ "STATUS_SXS_PROCESS_TERMINATION_REQUESTED"},
+ {STATUS_SXS_CORRUPT_ACTIVATION_STACK, -EIO,
+ "STATUS_SXS_CORRUPT_ACTIVATION_STACK"},
+ {STATUS_SXS_CORRUPTION, -EIO, "STATUS_SXS_CORRUPTION"},
+ {STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE, -EIO,
+ "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE"},
+ {STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME, -EIO,
+ "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME"},
+ {STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE, -EIO,
+ "STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE"},
+ {STATUS_SXS_IDENTITY_PARSE_ERROR, -EIO,
+ "STATUS_SXS_IDENTITY_PARSE_ERROR"},
+ {STATUS_SXS_COMPONENT_STORE_CORRUPT, -EIO,
+ "STATUS_SXS_COMPONENT_STORE_CORRUPT"},
+ {STATUS_SXS_FILE_HASH_MISMATCH, -EIO, "STATUS_SXS_FILE_HASH_MISMATCH"},
+ {STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT, -EIO,
+ "STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT"},
+ {STATUS_SXS_IDENTITIES_DIFFERENT, -EIO,
+ "STATUS_SXS_IDENTITIES_DIFFERENT"},
+ {STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT, -EIO,
+ "STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT"},
+ {STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY, -EIO,
+ "STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY"},
+ {STATUS_ADVANCED_INSTALLER_FAILED, -EIO,
+ "STATUS_ADVANCED_INSTALLER_FAILED"},
+ {STATUS_XML_ENCODING_MISMATCH, -EIO, "STATUS_XML_ENCODING_MISMATCH"},
+ {STATUS_SXS_MANIFEST_TOO_BIG, -EIO, "STATUS_SXS_MANIFEST_TOO_BIG"},
+ {STATUS_SXS_SETTING_NOT_REGISTERED, -EIO,
+ "STATUS_SXS_SETTING_NOT_REGISTERED"},
+ {STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE, -EIO,
+ "STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE"},
+ {STATUS_SMI_PRIMITIVE_INSTALLER_FAILED, -EIO,
+ "STATUS_SMI_PRIMITIVE_INSTALLER_FAILED"},
+ {STATUS_GENERIC_COMMAND_FAILED, -EIO, "STATUS_GENERIC_COMMAND_FAILED"},
+ {STATUS_SXS_FILE_HASH_MISSING, -EIO, "STATUS_SXS_FILE_HASH_MISSING"},
+ {STATUS_TRANSACTIONAL_CONFLICT, -EIO, "STATUS_TRANSACTIONAL_CONFLICT"},
+ {STATUS_INVALID_TRANSACTION, -EIO, "STATUS_INVALID_TRANSACTION"},
+ {STATUS_TRANSACTION_NOT_ACTIVE, -EIO, "STATUS_TRANSACTION_NOT_ACTIVE"},
+ {STATUS_TM_INITIALIZATION_FAILED, -EIO,
+ "STATUS_TM_INITIALIZATION_FAILED"},
+ {STATUS_RM_NOT_ACTIVE, -EIO, "STATUS_RM_NOT_ACTIVE"},
+ {STATUS_RM_METADATA_CORRUPT, -EIO, "STATUS_RM_METADATA_CORRUPT"},
+ {STATUS_TRANSACTION_NOT_JOINED, -EIO, "STATUS_TRANSACTION_NOT_JOINED"},
+ {STATUS_DIRECTORY_NOT_RM, -EIO, "STATUS_DIRECTORY_NOT_RM"},
+ {STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE, -EIO,
+ "STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE"},
+ {STATUS_LOG_RESIZE_INVALID_SIZE, -EIO,
+ "STATUS_LOG_RESIZE_INVALID_SIZE"},
+ {STATUS_REMOTE_FILE_VERSION_MISMATCH, -EIO,
+ "STATUS_REMOTE_FILE_VERSION_MISMATCH"},
+ {STATUS_CRM_PROTOCOL_ALREADY_EXISTS, -EIO,
+ "STATUS_CRM_PROTOCOL_ALREADY_EXISTS"},
+ {STATUS_TRANSACTION_PROPAGATION_FAILED, -EIO,
+ "STATUS_TRANSACTION_PROPAGATION_FAILED"},
+ {STATUS_CRM_PROTOCOL_NOT_FOUND, -EIO, "STATUS_CRM_PROTOCOL_NOT_FOUND"},
+ {STATUS_TRANSACTION_SUPERIOR_EXISTS, -EIO,
+ "STATUS_TRANSACTION_SUPERIOR_EXISTS"},
+ {STATUS_TRANSACTION_REQUEST_NOT_VALID, -EIO,
+ "STATUS_TRANSACTION_REQUEST_NOT_VALID"},
+ {STATUS_TRANSACTION_NOT_REQUESTED, -EIO,
+ "STATUS_TRANSACTION_NOT_REQUESTED"},
+ {STATUS_TRANSACTION_ALREADY_ABORTED, -EIO,
+ "STATUS_TRANSACTION_ALREADY_ABORTED"},
+ {STATUS_TRANSACTION_ALREADY_COMMITTED, -EIO,
+ "STATUS_TRANSACTION_ALREADY_COMMITTED"},
+ {STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER, -EIO,
+ "STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER"},
+ {STATUS_CURRENT_TRANSACTION_NOT_VALID, -EIO,
+ "STATUS_CURRENT_TRANSACTION_NOT_VALID"},
+ {STATUS_LOG_GROWTH_FAILED, -EIO, "STATUS_LOG_GROWTH_FAILED"},
+ {STATUS_OBJECT_NO_LONGER_EXISTS, -EIO,
+ "STATUS_OBJECT_NO_LONGER_EXISTS"},
+ {STATUS_STREAM_MINIVERSION_NOT_FOUND, -EIO,
+ "STATUS_STREAM_MINIVERSION_NOT_FOUND"},
+ {STATUS_STREAM_MINIVERSION_NOT_VALID, -EIO,
+ "STATUS_STREAM_MINIVERSION_NOT_VALID"},
+ {STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION, -EIO,
+ "STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION"},
+ {STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT, -EIO,
+ "STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT"},
+ {STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS, -EIO,
+ "STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS"},
+ {STATUS_HANDLE_NO_LONGER_VALID, -EIO, "STATUS_HANDLE_NO_LONGER_VALID"},
+ {STATUS_LOG_CORRUPTION_DETECTED, -EIO,
+ "STATUS_LOG_CORRUPTION_DETECTED"},
+ {STATUS_RM_DISCONNECTED, -EIO, "STATUS_RM_DISCONNECTED"},
+ {STATUS_ENLISTMENT_NOT_SUPERIOR, -EIO,
+ "STATUS_ENLISTMENT_NOT_SUPERIOR"},
+ {STATUS_FILE_IDENTITY_NOT_PERSISTENT, -EIO,
+ "STATUS_FILE_IDENTITY_NOT_PERSISTENT"},
+ {STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY, -EIO,
+ "STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY"},
+ {STATUS_CANT_CROSS_RM_BOUNDARY, -EIO, "STATUS_CANT_CROSS_RM_BOUNDARY"},
+ {STATUS_TXF_DIR_NOT_EMPTY, -EIO, "STATUS_TXF_DIR_NOT_EMPTY"},
+ {STATUS_INDOUBT_TRANSACTIONS_EXIST, -EIO,
+ "STATUS_INDOUBT_TRANSACTIONS_EXIST"},
+ {STATUS_TM_VOLATILE, -EIO, "STATUS_TM_VOLATILE"},
+ {STATUS_ROLLBACK_TIMER_EXPIRED, -EIO, "STATUS_ROLLBACK_TIMER_EXPIRED"},
+ {STATUS_TXF_ATTRIBUTE_CORRUPT, -EIO, "STATUS_TXF_ATTRIBUTE_CORRUPT"},
+ {STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION, -EIO,
+ "STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION"},
+ {STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED, -EIO,
+ "STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED"},
+ {STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE, -EIO,
+ "STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE"},
+ {STATUS_TRANSACTION_REQUIRED_PROMOTION, -EIO,
+ "STATUS_TRANSACTION_REQUIRED_PROMOTION"},
+ {STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION, -EIO,
+ "STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION"},
+ {STATUS_TRANSACTIONS_NOT_FROZEN, -EIO,
+ "STATUS_TRANSACTIONS_NOT_FROZEN"},
+ {STATUS_TRANSACTION_FREEZE_IN_PROGRESS, -EIO,
+ "STATUS_TRANSACTION_FREEZE_IN_PROGRESS"},
+ {STATUS_NOT_SNAPSHOT_VOLUME, -EIO, "STATUS_NOT_SNAPSHOT_VOLUME"},
+ {STATUS_NO_SAVEPOINT_WITH_OPEN_FILES, -EIO,
+ "STATUS_NO_SAVEPOINT_WITH_OPEN_FILES"},
+ {STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION, -EIO,
+ "STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION"},
+ {STATUS_TM_IDENTITY_MISMATCH, -EIO, "STATUS_TM_IDENTITY_MISMATCH"},
+ {STATUS_FLOATED_SECTION, -EIO, "STATUS_FLOATED_SECTION"},
+ {STATUS_CANNOT_ACCEPT_TRANSACTED_WORK, -EIO,
+ "STATUS_CANNOT_ACCEPT_TRANSACTED_WORK"},
+ {STATUS_CANNOT_ABORT_TRANSACTIONS, -EIO,
+ "STATUS_CANNOT_ABORT_TRANSACTIONS"},
+ {STATUS_TRANSACTION_NOT_FOUND, -EIO, "STATUS_TRANSACTION_NOT_FOUND"},
+ {STATUS_RESOURCEMANAGER_NOT_FOUND, -EIO,
+ "STATUS_RESOURCEMANAGER_NOT_FOUND"},
+ {STATUS_ENLISTMENT_NOT_FOUND, -EIO, "STATUS_ENLISTMENT_NOT_FOUND"},
+ {STATUS_TRANSACTIONMANAGER_NOT_FOUND, -EIO,
+ "STATUS_TRANSACTIONMANAGER_NOT_FOUND"},
+ {STATUS_TRANSACTIONMANAGER_NOT_ONLINE, -EIO,
+ "STATUS_TRANSACTIONMANAGER_NOT_ONLINE"},
+ {STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION, -EIO,
+ "STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION"},
+ {STATUS_TRANSACTION_NOT_ROOT, -EIO, "STATUS_TRANSACTION_NOT_ROOT"},
+ {STATUS_TRANSACTION_OBJECT_EXPIRED, -EIO,
+ "STATUS_TRANSACTION_OBJECT_EXPIRED"},
+ {STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION, -EIO,
+ "STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION"},
+ {STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED, -EIO,
+ "STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED"},
+ {STATUS_TRANSACTION_RECORD_TOO_LONG, -EIO,
+ "STATUS_TRANSACTION_RECORD_TOO_LONG"},
+ {STATUS_NO_LINK_TRACKING_IN_TRANSACTION, -EIO,
+ "STATUS_NO_LINK_TRACKING_IN_TRANSACTION"},
+ {STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION, -EOPNOTSUPP,
+ "STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION"},
+ {STATUS_TRANSACTION_INTEGRITY_VIOLATED, -EIO,
+ "STATUS_TRANSACTION_INTEGRITY_VIOLATED"},
+ {STATUS_LOG_SECTOR_INVALID, -EIO, "STATUS_LOG_SECTOR_INVALID"},
+ {STATUS_LOG_SECTOR_PARITY_INVALID, -EIO,
+ "STATUS_LOG_SECTOR_PARITY_INVALID"},
+ {STATUS_LOG_SECTOR_REMAPPED, -EIO, "STATUS_LOG_SECTOR_REMAPPED"},
+ {STATUS_LOG_BLOCK_INCOMPLETE, -EIO, "STATUS_LOG_BLOCK_INCOMPLETE"},
+ {STATUS_LOG_INVALID_RANGE, -EIO, "STATUS_LOG_INVALID_RANGE"},
+ {STATUS_LOG_BLOCKS_EXHAUSTED, -EIO, "STATUS_LOG_BLOCKS_EXHAUSTED"},
+ {STATUS_LOG_READ_CONTEXT_INVALID, -EIO,
+ "STATUS_LOG_READ_CONTEXT_INVALID"},
+ {STATUS_LOG_RESTART_INVALID, -EIO, "STATUS_LOG_RESTART_INVALID"},
+ {STATUS_LOG_BLOCK_VERSION, -EIO, "STATUS_LOG_BLOCK_VERSION"},
+ {STATUS_LOG_BLOCK_INVALID, -EIO, "STATUS_LOG_BLOCK_INVALID"},
+ {STATUS_LOG_READ_MODE_INVALID, -EIO, "STATUS_LOG_READ_MODE_INVALID"},
+ {STATUS_LOG_METADATA_CORRUPT, -EIO, "STATUS_LOG_METADATA_CORRUPT"},
+ {STATUS_LOG_METADATA_INVALID, -EIO, "STATUS_LOG_METADATA_INVALID"},
+ {STATUS_LOG_METADATA_INCONSISTENT, -EIO,
+ "STATUS_LOG_METADATA_INCONSISTENT"},
+ {STATUS_LOG_RESERVATION_INVALID, -EIO,
+ "STATUS_LOG_RESERVATION_INVALID"},
+ {STATUS_LOG_CANT_DELETE, -EIO, "STATUS_LOG_CANT_DELETE"},
+ {STATUS_LOG_CONTAINER_LIMIT_EXCEEDED, -EIO,
+ "STATUS_LOG_CONTAINER_LIMIT_EXCEEDED"},
+ {STATUS_LOG_START_OF_LOG, -EIO, "STATUS_LOG_START_OF_LOG"},
+ {STATUS_LOG_POLICY_ALREADY_INSTALLED, -EIO,
+ "STATUS_LOG_POLICY_ALREADY_INSTALLED"},
+ {STATUS_LOG_POLICY_NOT_INSTALLED, -EIO,
+ "STATUS_LOG_POLICY_NOT_INSTALLED"},
+ {STATUS_LOG_POLICY_INVALID, -EIO, "STATUS_LOG_POLICY_INVALID"},
+ {STATUS_LOG_POLICY_CONFLICT, -EIO, "STATUS_LOG_POLICY_CONFLICT"},
+ {STATUS_LOG_PINNED_ARCHIVE_TAIL, -EIO,
+ "STATUS_LOG_PINNED_ARCHIVE_TAIL"},
+ {STATUS_LOG_RECORD_NONEXISTENT, -EIO, "STATUS_LOG_RECORD_NONEXISTENT"},
+ {STATUS_LOG_RECORDS_RESERVED_INVALID, -EIO,
+ "STATUS_LOG_RECORDS_RESERVED_INVALID"},
+ {STATUS_LOG_SPACE_RESERVED_INVALID, -EIO,
+ "STATUS_LOG_SPACE_RESERVED_INVALID"},
+ {STATUS_LOG_TAIL_INVALID, -EIO, "STATUS_LOG_TAIL_INVALID"},
+ {STATUS_LOG_FULL, -EIO, "STATUS_LOG_FULL"},
+ {STATUS_LOG_MULTIPLEXED, -EIO, "STATUS_LOG_MULTIPLEXED"},
+ {STATUS_LOG_DEDICATED, -EIO, "STATUS_LOG_DEDICATED"},
+ {STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS, -EIO,
+ "STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS"},
+ {STATUS_LOG_ARCHIVE_IN_PROGRESS, -EIO,
+ "STATUS_LOG_ARCHIVE_IN_PROGRESS"},
+ {STATUS_LOG_EPHEMERAL, -EIO, "STATUS_LOG_EPHEMERAL"},
+ {STATUS_LOG_NOT_ENOUGH_CONTAINERS, -EIO,
+ "STATUS_LOG_NOT_ENOUGH_CONTAINERS"},
+ {STATUS_LOG_CLIENT_ALREADY_REGISTERED, -EIO,
+ "STATUS_LOG_CLIENT_ALREADY_REGISTERED"},
+ {STATUS_LOG_CLIENT_NOT_REGISTERED, -EIO,
+ "STATUS_LOG_CLIENT_NOT_REGISTERED"},
+ {STATUS_LOG_FULL_HANDLER_IN_PROGRESS, -EIO,
+ "STATUS_LOG_FULL_HANDLER_IN_PROGRESS"},
+ {STATUS_LOG_CONTAINER_READ_FAILED, -EIO,
+ "STATUS_LOG_CONTAINER_READ_FAILED"},
+ {STATUS_LOG_CONTAINER_WRITE_FAILED, -EIO,
+ "STATUS_LOG_CONTAINER_WRITE_FAILED"},
+ {STATUS_LOG_CONTAINER_OPEN_FAILED, -EIO,
+ "STATUS_LOG_CONTAINER_OPEN_FAILED"},
+ {STATUS_LOG_CONTAINER_STATE_INVALID, -EIO,
+ "STATUS_LOG_CONTAINER_STATE_INVALID"},
+ {STATUS_LOG_STATE_INVALID, -EIO, "STATUS_LOG_STATE_INVALID"},
+ {STATUS_LOG_PINNED, -EIO, "STATUS_LOG_PINNED"},
+ {STATUS_LOG_METADATA_FLUSH_FAILED, -EIO,
+ "STATUS_LOG_METADATA_FLUSH_FAILED"},
+ {STATUS_LOG_INCONSISTENT_SECURITY, -EIO,
+ "STATUS_LOG_INCONSISTENT_SECURITY"},
+ {STATUS_LOG_APPENDED_FLUSH_FAILED, -EIO,
+ "STATUS_LOG_APPENDED_FLUSH_FAILED"},
+ {STATUS_LOG_PINNED_RESERVATION, -EIO, "STATUS_LOG_PINNED_RESERVATION"},
+ {STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD, -EIO,
+ "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD"},
+ {STATUS_FLT_NO_HANDLER_DEFINED, -EIO, "STATUS_FLT_NO_HANDLER_DEFINED"},
+ {STATUS_FLT_CONTEXT_ALREADY_DEFINED, -EIO,
+ "STATUS_FLT_CONTEXT_ALREADY_DEFINED"},
+ {STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST, -EIO,
+ "STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST"},
+ {STATUS_FLT_DISALLOW_FAST_IO, -EIO, "STATUS_FLT_DISALLOW_FAST_IO"},
+ {STATUS_FLT_INVALID_NAME_REQUEST, -EIO,
+ "STATUS_FLT_INVALID_NAME_REQUEST"},
+ {STATUS_FLT_NOT_SAFE_TO_POST_OPERATION, -EIO,
+ "STATUS_FLT_NOT_SAFE_TO_POST_OPERATION"},
+ {STATUS_FLT_NOT_INITIALIZED, -EIO, "STATUS_FLT_NOT_INITIALIZED"},
+ {STATUS_FLT_FILTER_NOT_READY, -EIO, "STATUS_FLT_FILTER_NOT_READY"},
+ {STATUS_FLT_POST_OPERATION_CLEANUP, -EIO,
+ "STATUS_FLT_POST_OPERATION_CLEANUP"},
+ {STATUS_FLT_INTERNAL_ERROR, -EIO, "STATUS_FLT_INTERNAL_ERROR"},
+ {STATUS_FLT_DELETING_OBJECT, -EIO, "STATUS_FLT_DELETING_OBJECT"},
+ {STATUS_FLT_MUST_BE_NONPAGED_POOL, -EIO,
+ "STATUS_FLT_MUST_BE_NONPAGED_POOL"},
+ {STATUS_FLT_DUPLICATE_ENTRY, -EIO, "STATUS_FLT_DUPLICATE_ENTRY"},
+ {STATUS_FLT_CBDQ_DISABLED, -EIO, "STATUS_FLT_CBDQ_DISABLED"},
+ {STATUS_FLT_DO_NOT_ATTACH, -EIO, "STATUS_FLT_DO_NOT_ATTACH"},
+ {STATUS_FLT_DO_NOT_DETACH, -EIO, "STATUS_FLT_DO_NOT_DETACH"},
+ {STATUS_FLT_INSTANCE_ALTITUDE_COLLISION, -EIO,
+ "STATUS_FLT_INSTANCE_ALTITUDE_COLLISION"},
+ {STATUS_FLT_INSTANCE_NAME_COLLISION, -EIO,
+ "STATUS_FLT_INSTANCE_NAME_COLLISION"},
+ {STATUS_FLT_FILTER_NOT_FOUND, -EIO, "STATUS_FLT_FILTER_NOT_FOUND"},
+ {STATUS_FLT_VOLUME_NOT_FOUND, -EIO, "STATUS_FLT_VOLUME_NOT_FOUND"},
+ {STATUS_FLT_INSTANCE_NOT_FOUND, -EIO, "STATUS_FLT_INSTANCE_NOT_FOUND"},
+ {STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND, -EIO,
+ "STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND"},
+ {STATUS_FLT_INVALID_CONTEXT_REGISTRATION, -EIO,
+ "STATUS_FLT_INVALID_CONTEXT_REGISTRATION"},
+ {STATUS_FLT_NAME_CACHE_MISS, -EIO, "STATUS_FLT_NAME_CACHE_MISS"},
+ {STATUS_FLT_NO_DEVICE_OBJECT, -EIO, "STATUS_FLT_NO_DEVICE_OBJECT"},
+ {STATUS_FLT_VOLUME_ALREADY_MOUNTED, -EIO,
+ "STATUS_FLT_VOLUME_ALREADY_MOUNTED"},
+ {STATUS_FLT_ALREADY_ENLISTED, -EIO, "STATUS_FLT_ALREADY_ENLISTED"},
+ {STATUS_FLT_CONTEXT_ALREADY_LINKED, -EIO,
+ "STATUS_FLT_CONTEXT_ALREADY_LINKED"},
+ {STATUS_FLT_NO_WAITER_FOR_REPLY, -EIO,
+ "STATUS_FLT_NO_WAITER_FOR_REPLY"},
+ {STATUS_MONITOR_NO_DESCRIPTOR, -EIO, "STATUS_MONITOR_NO_DESCRIPTOR"},
+ {STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT, -EIO,
+ "STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT"},
+ {STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM, -EIO,
+ "STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM"},
+ {STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK, -EIO,
+ "STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK"},
+ {STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED, -EIO,
+ "STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED"},
+ {STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK, -EIO,
+ "STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK"},
+ {STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK, -EIO,
+ "STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK"},
+ {STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA, -EIO,
+ "STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA"},
+ {STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK, -EIO,
+ "STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK"},
+ {STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER, -EIO,
+ "STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER"},
+ {STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER, -EIO,
+ "STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER"},
+ {STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER, -EIO,
+ "STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER"},
+ {STATUS_GRAPHICS_ADAPTER_WAS_RESET, -EIO,
+ "STATUS_GRAPHICS_ADAPTER_WAS_RESET"},
+ {STATUS_GRAPHICS_INVALID_DRIVER_MODEL, -EIO,
+ "STATUS_GRAPHICS_INVALID_DRIVER_MODEL"},
+ {STATUS_GRAPHICS_PRESENT_MODE_CHANGED, -EIO,
+ "STATUS_GRAPHICS_PRESENT_MODE_CHANGED"},
+ {STATUS_GRAPHICS_PRESENT_OCCLUDED, -EIO,
+ "STATUS_GRAPHICS_PRESENT_OCCLUDED"},
+ {STATUS_GRAPHICS_PRESENT_DENIED, -EIO,
+ "STATUS_GRAPHICS_PRESENT_DENIED"},
+ {STATUS_GRAPHICS_CANNOTCOLORCONVERT, -EIO,
+ "STATUS_GRAPHICS_CANNOTCOLORCONVERT"},
+ {STATUS_GRAPHICS_NO_VIDEO_MEMORY, -EIO,
+ "STATUS_GRAPHICS_NO_VIDEO_MEMORY"},
+ {STATUS_GRAPHICS_CANT_LOCK_MEMORY, -EIO,
+ "STATUS_GRAPHICS_CANT_LOCK_MEMORY"},
+ {STATUS_GRAPHICS_ALLOCATION_BUSY, -EBUSY,
+ "STATUS_GRAPHICS_ALLOCATION_BUSY"},
+ {STATUS_GRAPHICS_TOO_MANY_REFERENCES, -EIO,
+ "STATUS_GRAPHICS_TOO_MANY_REFERENCES"},
+ {STATUS_GRAPHICS_TRY_AGAIN_LATER, -EIO,
+ "STATUS_GRAPHICS_TRY_AGAIN_LATER"},
+ {STATUS_GRAPHICS_TRY_AGAIN_NOW, -EIO, "STATUS_GRAPHICS_TRY_AGAIN_NOW"},
+ {STATUS_GRAPHICS_ALLOCATION_INVALID, -EIO,
+ "STATUS_GRAPHICS_ALLOCATION_INVALID"},
+ {STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE, -EIO,
+ "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE"},
+ {STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED, -EIO,
+ "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED"},
+ {STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION, -EIO,
+ "STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION"},
+ {STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE, -EIO,
+ "STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE"},
+ {STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION, -EIO,
+ "STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION"},
+ {STATUS_GRAPHICS_ALLOCATION_CLOSED, -EIO,
+ "STATUS_GRAPHICS_ALLOCATION_CLOSED"},
+ {STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE, -EIO,
+ "STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE"},
+ {STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE, -EIO,
+ "STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE"},
+ {STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE, -EIO,
+ "STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE"},
+ {STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST, -EIO,
+ "STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST"},
+ {STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE, -EIO,
+ "STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE"},
+ {STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY"},
+ {STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_INVALID_VIDPN, -EIO, "STATUS_GRAPHICS_INVALID_VIDPN"},
+ {STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE"},
+ {STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET"},
+ {STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET"},
+ {STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET"},
+ {STATUS_GRAPHICS_INVALID_FREQUENCY, -EIO,
+ "STATUS_GRAPHICS_INVALID_FREQUENCY"},
+ {STATUS_GRAPHICS_INVALID_ACTIVE_REGION, -EIO,
+ "STATUS_GRAPHICS_INVALID_ACTIVE_REGION"},
+ {STATUS_GRAPHICS_INVALID_TOTAL_REGION, -EIO,
+ "STATUS_GRAPHICS_INVALID_TOTAL_REGION"},
+ {STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE"},
+ {STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE"},
+ {STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET, -EIO,
+ "STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET"},
+ {STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY, -EIO,
+ "STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY"},
+ {STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET, -EIO,
+ "STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET"},
+ {STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET"},
+ {STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET"},
+ {STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET, -EIO,
+ "STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET"},
+ {STATUS_GRAPHICS_TARGET_ALREADY_IN_SET, -EIO,
+ "STATUS_GRAPHICS_TARGET_ALREADY_IN_SET"},
+ {STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH"},
+ {STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY, -EIO,
+ "STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY"},
+ {STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET, -EIO,
+ "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET"},
+ {STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE, -EIO,
+ "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE"},
+ {STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET, -EIO,
+ "STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET"},
+ {STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET, -EIO,
+ "STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET"},
+ {STATUS_GRAPHICS_STALE_MODESET, -EIO, "STATUS_GRAPHICS_STALE_MODESET"},
+ {STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET, -EIO,
+ "STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET"},
+ {STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE, -EIO,
+ "STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE"},
+ {STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN, -EIO,
+ "STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN"},
+ {STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE, -EIO,
+ "STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE"},
+ {STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION, -EIO,
+ "STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION"},
+ {STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES, -EIO,
+ "STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES"},
+ {STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY, -EIO,
+ "STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY"},
+ {STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE, -EIO,
+ "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE"},
+ {STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET, -EIO,
+ "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET"},
+ {STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET, -EIO,
+ "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET"},
+ {STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR, -EIO,
+ "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR"},
+ {STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET, -EIO,
+ "STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET"},
+ {STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET, -EIO,
+ "STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET"},
+ {STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE, -EIO,
+ "STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE"},
+ {STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE"},
+ {STATUS_GRAPHICS_RESOURCES_NOT_RELATED, -EIO,
+ "STATUS_GRAPHICS_RESOURCES_NOT_RELATED"},
+ {STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE, -EIO,
+ "STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE"},
+ {STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE, -EIO,
+ "STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE"},
+ {STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET, -EIO,
+ "STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET"},
+ {STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER, -EIO,
+ "STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER"},
+ {STATUS_GRAPHICS_NO_VIDPNMGR, -EIO, "STATUS_GRAPHICS_NO_VIDPNMGR"},
+ {STATUS_GRAPHICS_NO_ACTIVE_VIDPN, -EIO,
+ "STATUS_GRAPHICS_NO_ACTIVE_VIDPN"},
+ {STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY, -EIO,
+ "STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY"},
+ {STATUS_GRAPHICS_MONITOR_NOT_CONNECTED, -EIO,
+ "STATUS_GRAPHICS_MONITOR_NOT_CONNECTED"},
+ {STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY, -EIO,
+ "STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY"},
+ {STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE, -EIO,
+ "STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE"},
+ {STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE, -EIO,
+ "STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE"},
+ {STATUS_GRAPHICS_INVALID_STRIDE, -EIO,
+ "STATUS_GRAPHICS_INVALID_STRIDE"},
+ {STATUS_GRAPHICS_INVALID_PIXELFORMAT, -EIO,
+ "STATUS_GRAPHICS_INVALID_PIXELFORMAT"},
+ {STATUS_GRAPHICS_INVALID_COLORBASIS, -EIO,
+ "STATUS_GRAPHICS_INVALID_COLORBASIS"},
+ {STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE, -EIO,
+ "STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE"},
+ {STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY, -EIO,
+ "STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY"},
+ {STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT, -EIO,
+ "STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT"},
+ {STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, -EIO,
+ "STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE"},
+ {STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN, -EIO,
+ "STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN"},
+ {STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL, -EIO,
+ "STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL"},
+ {STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION, -EIO,
+ "STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION"},
+ {STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED,
+ -EIO,
+ "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_INVALID_GAMMA_RAMP, -EIO,
+ "STATUS_GRAPHICS_INVALID_GAMMA_RAMP"},
+ {STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_MODE_NOT_IN_MODESET, -EIO,
+ "STATUS_GRAPHICS_MODE_NOT_IN_MODESET"},
+ {STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON, -EIO,
+ "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON"},
+ {STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE, -EIO,
+ "STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE"},
+ {STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE, -EIO,
+ "STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE"},
+ {STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS, -EIO,
+ "STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS"},
+ {STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING, -EIO,
+ "STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING"},
+ {STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED, -EIO,
+ "STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED"},
+ {STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS, -EIO,
+ "STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS"},
+ {STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT, -EIO,
+ "STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT"},
+ {STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM, -EIO,
+ "STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM"},
+ {STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN, -EIO,
+ "STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN"},
+ {STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT, -EIO,
+ "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT"},
+ {STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED, -EIO,
+ "STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED"},
+ {STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION, -EIO,
+ "STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION"},
+ {STATUS_GRAPHICS_INVALID_CLIENT_TYPE, -EIO,
+ "STATUS_GRAPHICS_INVALID_CLIENT_TYPE"},
+ {STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET, -EIO,
+ "STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET"},
+ {STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED, -EIO,
+ "STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED"},
+ {STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER, -EIO,
+ "STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER"},
+ {STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED, -EIO,
+ "STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED"},
+ {STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED, -EIO,
+ "STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED"},
+ {STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY, -EIO,
+ "STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY"},
+ {STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED, -EIO,
+ "STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED"},
+ {STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON, -EIO,
+ "STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON"},
+ {STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE, -EIO,
+ "STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE"},
+ {STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER, -EIO,
+ "STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER"},
+ {STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED, -EIO,
+ "STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED"},
+ {STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS,
+ -EIO,
+ "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS"},
+ {STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST, -EIO,
+ "STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST"},
+ {STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR, -EIO,
+ "STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR"},
+ {STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS, -EIO,
+ "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS"},
+ {STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST, -EIO,
+ "STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST"},
+ {STATUS_GRAPHICS_OPM_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_OPM_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_COPP_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_COPP_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_UAB_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_UAB_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS, -EIO,
+ "STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS"},
+ {STATUS_GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL, -EIO,
+ "STATUS_GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL"},
+ {STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST, -EIO,
+ "STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST"},
+ {STATUS_GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME, -EIO,
+ "STATUS_GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME"},
+ {STATUS_GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP, -EIO,
+ "STATUS_GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP"},
+ {STATUS_GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_OPM_INVALID_POINTER, -EIO,
+ "STATUS_GRAPHICS_OPM_INVALID_POINTER"},
+ {STATUS_GRAPHICS_OPM_INTERNAL_ERROR, -EIO,
+ "STATUS_GRAPHICS_OPM_INTERNAL_ERROR"},
+ {STATUS_GRAPHICS_OPM_INVALID_HANDLE, -EIO,
+ "STATUS_GRAPHICS_OPM_INVALID_HANDLE"},
+ {STATUS_GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE, -EIO,
+ "STATUS_GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE"},
+ {STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH, -EIO,
+ "STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH"},
+ {STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED, -EIO,
+ "STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED"},
+ {STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED, -EIO,
+ "STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED"},
+ {STATUS_GRAPHICS_PVP_HFS_FAILED, -EIO,
+ "STATUS_GRAPHICS_PVP_HFS_FAILED"},
+ {STATUS_GRAPHICS_OPM_INVALID_SRM, -EIO,
+ "STATUS_GRAPHICS_OPM_INVALID_SRM"},
+ {STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP, -EIO,
+ "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP"},
+ {STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP, -EIO,
+ "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP"},
+ {STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA, -EIO,
+ "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA"},
+ {STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET, -EIO,
+ "STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET"},
+ {STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH, -EIO,
+ "STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH"},
+ {STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE, -EIO,
+ "STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE"},
+ {STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS, -EIO,
+ "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS"},
+ {STATUS_GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS, -EIO,
+ "STATUS_GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS"},
+ {STATUS_GRAPHICS_I2C_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_I2C_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST, -EIO,
+ "STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST"},
+ {STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA, -EIO,
+ "STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA"},
+ {STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA, -EIO,
+ "STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA"},
+ {STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_DDCCI_INVALID_DATA, -EIO,
+ "STATUS_GRAPHICS_DDCCI_INVALID_DATA"},
+ {STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE,
+ -EIO,
+ "STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE"},
+ {STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING, -EIO,
+ "STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING"},
+ {STATUS_GRAPHICS_MCA_INTERNAL_ERROR, -EIO,
+ "STATUS_GRAPHICS_MCA_INTERNAL_ERROR"},
+ {STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND, -EIO,
+ "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND"},
+ {STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH, -EIO,
+ "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH"},
+ {STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM, -EIO,
+ "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM"},
+ {STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE, -EIO,
+ "STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE"},
+ {STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS, -EIO,
+ "STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS"},
+ {STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED"},
+ {STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME, -EIO,
+ "STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME"},
+ {STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP, -EIO,
+ "STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP"},
+ {STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED, -EIO,
+ "STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED"},
+ {STATUS_GRAPHICS_INVALID_POINTER, -EIO,
+ "STATUS_GRAPHICS_INVALID_POINTER"},
+ {STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE, -EIO,
+ "STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE"},
+ {STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL, -EIO,
+ "STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL"},
+ {STATUS_GRAPHICS_INTERNAL_ERROR, -EIO,
+ "STATUS_GRAPHICS_INTERNAL_ERROR"},
+ {STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS, -EIO,
+ "STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS"},
+ {STATUS_FVE_LOCKED_VOLUME, -EIO, "STATUS_FVE_LOCKED_VOLUME"},
+ {STATUS_FVE_NOT_ENCRYPTED, -EIO, "STATUS_FVE_NOT_ENCRYPTED"},
+ {STATUS_FVE_BAD_INFORMATION, -EIO, "STATUS_FVE_BAD_INFORMATION"},
+ {STATUS_FVE_TOO_SMALL, -EIO, "STATUS_FVE_TOO_SMALL"},
+ {STATUS_FVE_FAILED_WRONG_FS, -EIO, "STATUS_FVE_FAILED_WRONG_FS"},
+ {STATUS_FVE_FAILED_BAD_FS, -EIO, "STATUS_FVE_FAILED_BAD_FS"},
+ {STATUS_FVE_FS_NOT_EXTENDED, -EIO, "STATUS_FVE_FS_NOT_EXTENDED"},
+ {STATUS_FVE_FS_MOUNTED, -EIO, "STATUS_FVE_FS_MOUNTED"},
+ {STATUS_FVE_NO_LICENSE, -EIO, "STATUS_FVE_NO_LICENSE"},
+ {STATUS_FVE_ACTION_NOT_ALLOWED, -EIO, "STATUS_FVE_ACTION_NOT_ALLOWED"},
+ {STATUS_FVE_BAD_DATA, -EIO, "STATUS_FVE_BAD_DATA"},
+ {STATUS_FVE_VOLUME_NOT_BOUND, -EIO, "STATUS_FVE_VOLUME_NOT_BOUND"},
+ {STATUS_FVE_NOT_DATA_VOLUME, -EIO, "STATUS_FVE_NOT_DATA_VOLUME"},
+ {STATUS_FVE_CONV_READ_ERROR, -EIO, "STATUS_FVE_CONV_READ_ERROR"},
+ {STATUS_FVE_CONV_WRITE_ERROR, -EIO, "STATUS_FVE_CONV_WRITE_ERROR"},
+ {STATUS_FVE_OVERLAPPED_UPDATE, -EIO, "STATUS_FVE_OVERLAPPED_UPDATE"},
+ {STATUS_FVE_FAILED_SECTOR_SIZE, -EIO, "STATUS_FVE_FAILED_SECTOR_SIZE"},
+ {STATUS_FVE_FAILED_AUTHENTICATION, -EIO,
+ "STATUS_FVE_FAILED_AUTHENTICATION"},
+ {STATUS_FVE_NOT_OS_VOLUME, -EIO, "STATUS_FVE_NOT_OS_VOLUME"},
+ {STATUS_FVE_KEYFILE_NOT_FOUND, -EIO, "STATUS_FVE_KEYFILE_NOT_FOUND"},
+ {STATUS_FVE_KEYFILE_INVALID, -EIO, "STATUS_FVE_KEYFILE_INVALID"},
+ {STATUS_FVE_KEYFILE_NO_VMK, -EIO, "STATUS_FVE_KEYFILE_NO_VMK"},
+ {STATUS_FVE_TPM_DISABLED, -EIO, "STATUS_FVE_TPM_DISABLED"},
+ {STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO, -EIO,
+ "STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO"},
+ {STATUS_FVE_TPM_INVALID_PCR, -EIO, "STATUS_FVE_TPM_INVALID_PCR"},
+ {STATUS_FVE_TPM_NO_VMK, -EIO, "STATUS_FVE_TPM_NO_VMK"},
+ {STATUS_FVE_PIN_INVALID, -EIO, "STATUS_FVE_PIN_INVALID"},
+ {STATUS_FVE_AUTH_INVALID_APPLICATION, -EIO,
+ "STATUS_FVE_AUTH_INVALID_APPLICATION"},
+ {STATUS_FVE_AUTH_INVALID_CONFIG, -EIO,
+ "STATUS_FVE_AUTH_INVALID_CONFIG"},
+ {STATUS_FVE_DEBUGGER_ENABLED, -EIO, "STATUS_FVE_DEBUGGER_ENABLED"},
+ {STATUS_FVE_DRY_RUN_FAILED, -EIO, "STATUS_FVE_DRY_RUN_FAILED"},
+ {STATUS_FVE_BAD_METADATA_POINTER, -EIO,
+ "STATUS_FVE_BAD_METADATA_POINTER"},
+ {STATUS_FVE_OLD_METADATA_COPY, -EIO, "STATUS_FVE_OLD_METADATA_COPY"},
+ {STATUS_FVE_REBOOT_REQUIRED, -EIO, "STATUS_FVE_REBOOT_REQUIRED"},
+ {STATUS_FVE_RAW_ACCESS, -EIO, "STATUS_FVE_RAW_ACCESS"},
+ {STATUS_FVE_RAW_BLOCKED, -EIO, "STATUS_FVE_RAW_BLOCKED"},
+ {STATUS_FWP_CALLOUT_NOT_FOUND, -EIO, "STATUS_FWP_CALLOUT_NOT_FOUND"},
+ {STATUS_FWP_CONDITION_NOT_FOUND, -EIO,
+ "STATUS_FWP_CONDITION_NOT_FOUND"},
+ {STATUS_FWP_FILTER_NOT_FOUND, -EIO, "STATUS_FWP_FILTER_NOT_FOUND"},
+ {STATUS_FWP_LAYER_NOT_FOUND, -EIO, "STATUS_FWP_LAYER_NOT_FOUND"},
+ {STATUS_FWP_PROVIDER_NOT_FOUND, -EIO, "STATUS_FWP_PROVIDER_NOT_FOUND"},
+ {STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND, -EIO,
+ "STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND"},
+ {STATUS_FWP_SUBLAYER_NOT_FOUND, -EIO, "STATUS_FWP_SUBLAYER_NOT_FOUND"},
+ {STATUS_FWP_NOT_FOUND, -EIO, "STATUS_FWP_NOT_FOUND"},
+ {STATUS_FWP_ALREADY_EXISTS, -EIO, "STATUS_FWP_ALREADY_EXISTS"},
+ {STATUS_FWP_IN_USE, -EIO, "STATUS_FWP_IN_USE"},
+ {STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS, -EIO,
+ "STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS"},
+ {STATUS_FWP_WRONG_SESSION, -EIO, "STATUS_FWP_WRONG_SESSION"},
+ {STATUS_FWP_NO_TXN_IN_PROGRESS, -EIO, "STATUS_FWP_NO_TXN_IN_PROGRESS"},
+ {STATUS_FWP_TXN_IN_PROGRESS, -EIO, "STATUS_FWP_TXN_IN_PROGRESS"},
+ {STATUS_FWP_TXN_ABORTED, -EIO, "STATUS_FWP_TXN_ABORTED"},
+ {STATUS_FWP_SESSION_ABORTED, -EIO, "STATUS_FWP_SESSION_ABORTED"},
+ {STATUS_FWP_INCOMPATIBLE_TXN, -EIO, "STATUS_FWP_INCOMPATIBLE_TXN"},
+ {STATUS_FWP_TIMEOUT, -ETIMEDOUT, "STATUS_FWP_TIMEOUT"},
+ {STATUS_FWP_NET_EVENTS_DISABLED, -EIO,
+ "STATUS_FWP_NET_EVENTS_DISABLED"},
+ {STATUS_FWP_INCOMPATIBLE_LAYER, -EIO, "STATUS_FWP_INCOMPATIBLE_LAYER"},
+ {STATUS_FWP_KM_CLIENTS_ONLY, -EIO, "STATUS_FWP_KM_CLIENTS_ONLY"},
+ {STATUS_FWP_LIFETIME_MISMATCH, -EIO, "STATUS_FWP_LIFETIME_MISMATCH"},
+ {STATUS_FWP_BUILTIN_OBJECT, -EIO, "STATUS_FWP_BUILTIN_OBJECT"},
+ {STATUS_FWP_TOO_MANY_BOOTTIME_FILTERS, -EIO,
+ "STATUS_FWP_TOO_MANY_BOOTTIME_FILTERS"},
+ {STATUS_FWP_TOO_MANY_CALLOUTS, -EIO, "STATUS_FWP_TOO_MANY_CALLOUTS"},
+ {STATUS_FWP_NOTIFICATION_DROPPED, -EIO,
+ "STATUS_FWP_NOTIFICATION_DROPPED"},
+ {STATUS_FWP_TRAFFIC_MISMATCH, -EIO, "STATUS_FWP_TRAFFIC_MISMATCH"},
+ {STATUS_FWP_INCOMPATIBLE_SA_STATE, -EIO,
+ "STATUS_FWP_INCOMPATIBLE_SA_STATE"},
+ {STATUS_FWP_NULL_POINTER, -EIO, "STATUS_FWP_NULL_POINTER"},
+ {STATUS_FWP_INVALID_ENUMERATOR, -EIO, "STATUS_FWP_INVALID_ENUMERATOR"},
+ {STATUS_FWP_INVALID_FLAGS, -EIO, "STATUS_FWP_INVALID_FLAGS"},
+ {STATUS_FWP_INVALID_NET_MASK, -EIO, "STATUS_FWP_INVALID_NET_MASK"},
+ {STATUS_FWP_INVALID_RANGE, -EIO, "STATUS_FWP_INVALID_RANGE"},
+ {STATUS_FWP_INVALID_INTERVAL, -EIO, "STATUS_FWP_INVALID_INTERVAL"},
+ {STATUS_FWP_ZERO_LENGTH_ARRAY, -EIO, "STATUS_FWP_ZERO_LENGTH_ARRAY"},
+ {STATUS_FWP_NULL_DISPLAY_NAME, -EIO, "STATUS_FWP_NULL_DISPLAY_NAME"},
+ {STATUS_FWP_INVALID_ACTION_TYPE, -EIO,
+ "STATUS_FWP_INVALID_ACTION_TYPE"},
+ {STATUS_FWP_INVALID_WEIGHT, -EIO, "STATUS_FWP_INVALID_WEIGHT"},
+ {STATUS_FWP_MATCH_TYPE_MISMATCH, -EIO,
+ "STATUS_FWP_MATCH_TYPE_MISMATCH"},
+ {STATUS_FWP_TYPE_MISMATCH, -EIO, "STATUS_FWP_TYPE_MISMATCH"},
+ {STATUS_FWP_OUT_OF_BOUNDS, -EIO, "STATUS_FWP_OUT_OF_BOUNDS"},
+ {STATUS_FWP_RESERVED, -EIO, "STATUS_FWP_RESERVED"},
+ {STATUS_FWP_DUPLICATE_CONDITION, -EIO,
+ "STATUS_FWP_DUPLICATE_CONDITION"},
+ {STATUS_FWP_DUPLICATE_KEYMOD, -EIO, "STATUS_FWP_DUPLICATE_KEYMOD"},
+ {STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER, -EIO,
+ "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER"},
+ {STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER, -EIO,
+ "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER"},
+ {STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER, -EIO,
+ "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER"},
+ {STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT, -EIO,
+ "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT"},
+ {STATUS_FWP_INCOMPATIBLE_AUTH_METHOD, -EIO,
+ "STATUS_FWP_INCOMPATIBLE_AUTH_METHOD"},
+ {STATUS_FWP_INCOMPATIBLE_DH_GROUP, -EIO,
+ "STATUS_FWP_INCOMPATIBLE_DH_GROUP"},
+ {STATUS_FWP_EM_NOT_SUPPORTED, -EOPNOTSUPP,
+ "STATUS_FWP_EM_NOT_SUPPORTED"},
+ {STATUS_FWP_NEVER_MATCH, -EIO, "STATUS_FWP_NEVER_MATCH"},
+ {STATUS_FWP_PROVIDER_CONTEXT_MISMATCH, -EIO,
+ "STATUS_FWP_PROVIDER_CONTEXT_MISMATCH"},
+ {STATUS_FWP_INVALID_PARAMETER, -EIO, "STATUS_FWP_INVALID_PARAMETER"},
+ {STATUS_FWP_TOO_MANY_SUBLAYERS, -EIO, "STATUS_FWP_TOO_MANY_SUBLAYERS"},
+ {STATUS_FWP_CALLOUT_NOTIFICATION_FAILED, -EIO,
+ "STATUS_FWP_CALLOUT_NOTIFICATION_FAILED"},
+ {STATUS_FWP_INCOMPATIBLE_AUTH_CONFIG, -EIO,
+ "STATUS_FWP_INCOMPATIBLE_AUTH_CONFIG"},
+ {STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG, -EIO,
+ "STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG"},
+ {STATUS_FWP_TCPIP_NOT_READY, -EIO, "STATUS_FWP_TCPIP_NOT_READY"},
+ {STATUS_FWP_INJECT_HANDLE_CLOSING, -EIO,
+ "STATUS_FWP_INJECT_HANDLE_CLOSING"},
+ {STATUS_FWP_INJECT_HANDLE_STALE, -EIO,
+ "STATUS_FWP_INJECT_HANDLE_STALE"},
+ {STATUS_FWP_CANNOT_PEND, -EIO, "STATUS_FWP_CANNOT_PEND"},
+ {STATUS_NDIS_CLOSING, -EIO, "STATUS_NDIS_CLOSING"},
+ {STATUS_NDIS_BAD_VERSION, -EIO, "STATUS_NDIS_BAD_VERSION"},
+ {STATUS_NDIS_BAD_CHARACTERISTICS, -EIO,
+ "STATUS_NDIS_BAD_CHARACTERISTICS"},
+ {STATUS_NDIS_ADAPTER_NOT_FOUND, -EIO, "STATUS_NDIS_ADAPTER_NOT_FOUND"},
+ {STATUS_NDIS_OPEN_FAILED, -EIO, "STATUS_NDIS_OPEN_FAILED"},
+ {STATUS_NDIS_DEVICE_FAILED, -EIO, "STATUS_NDIS_DEVICE_FAILED"},
+ {STATUS_NDIS_MULTICAST_FULL, -EIO, "STATUS_NDIS_MULTICAST_FULL"},
+ {STATUS_NDIS_MULTICAST_EXISTS, -EIO, "STATUS_NDIS_MULTICAST_EXISTS"},
+ {STATUS_NDIS_MULTICAST_NOT_FOUND, -EIO,
+ "STATUS_NDIS_MULTICAST_NOT_FOUND"},
+ {STATUS_NDIS_REQUEST_ABORTED, -EIO, "STATUS_NDIS_REQUEST_ABORTED"},
+ {STATUS_NDIS_RESET_IN_PROGRESS, -EIO, "STATUS_NDIS_RESET_IN_PROGRESS"},
+ {STATUS_NDIS_INVALID_PACKET, -EIO, "STATUS_NDIS_INVALID_PACKET"},
+ {STATUS_NDIS_INVALID_DEVICE_REQUEST, -EIO,
+ "STATUS_NDIS_INVALID_DEVICE_REQUEST"},
+ {STATUS_NDIS_ADAPTER_NOT_READY, -EIO, "STATUS_NDIS_ADAPTER_NOT_READY"},
+ {STATUS_NDIS_INVALID_LENGTH, -EIO, "STATUS_NDIS_INVALID_LENGTH"},
+ {STATUS_NDIS_INVALID_DATA, -EIO, "STATUS_NDIS_INVALID_DATA"},
+ {STATUS_NDIS_BUFFER_TOO_SHORT, -ENOBUFS,
+ "STATUS_NDIS_BUFFER_TOO_SHORT"},
+ {STATUS_NDIS_INVALID_OID, -EIO, "STATUS_NDIS_INVALID_OID"},
+ {STATUS_NDIS_ADAPTER_REMOVED, -EIO, "STATUS_NDIS_ADAPTER_REMOVED"},
+ {STATUS_NDIS_UNSUPPORTED_MEDIA, -EIO, "STATUS_NDIS_UNSUPPORTED_MEDIA"},
+ {STATUS_NDIS_GROUP_ADDRESS_IN_USE, -EIO,
+ "STATUS_NDIS_GROUP_ADDRESS_IN_USE"},
+ {STATUS_NDIS_FILE_NOT_FOUND, -EIO, "STATUS_NDIS_FILE_NOT_FOUND"},
+ {STATUS_NDIS_ERROR_READING_FILE, -EIO,
+ "STATUS_NDIS_ERROR_READING_FILE"},
+ {STATUS_NDIS_ALREADY_MAPPED, -EIO, "STATUS_NDIS_ALREADY_MAPPED"},
+ {STATUS_NDIS_RESOURCE_CONFLICT, -EIO, "STATUS_NDIS_RESOURCE_CONFLICT"},
+ {STATUS_NDIS_MEDIA_DISCONNECTED, -EIO,
+ "STATUS_NDIS_MEDIA_DISCONNECTED"},
+ {STATUS_NDIS_INVALID_ADDRESS, -EIO, "STATUS_NDIS_INVALID_ADDRESS"},
+ {STATUS_NDIS_PAUSED, -EIO, "STATUS_NDIS_PAUSED"},
+ {STATUS_NDIS_INTERFACE_NOT_FOUND, -EIO,
+ "STATUS_NDIS_INTERFACE_NOT_FOUND"},
+ {STATUS_NDIS_UNSUPPORTED_REVISION, -EIO,
+ "STATUS_NDIS_UNSUPPORTED_REVISION"},
+ {STATUS_NDIS_INVALID_PORT, -EIO, "STATUS_NDIS_INVALID_PORT"},
+ {STATUS_NDIS_INVALID_PORT_STATE, -EIO,
+ "STATUS_NDIS_INVALID_PORT_STATE"},
+ {STATUS_NDIS_LOW_POWER_STATE, -EIO, "STATUS_NDIS_LOW_POWER_STATE"},
+ {STATUS_NDIS_NOT_SUPPORTED, -ENOSYS, "STATUS_NDIS_NOT_SUPPORTED"},
+ {STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED, -EIO,
+ "STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED"},
+ {STATUS_NDIS_DOT11_MEDIA_IN_USE, -EIO,
+ "STATUS_NDIS_DOT11_MEDIA_IN_USE"},
+ {STATUS_NDIS_DOT11_POWER_STATE_INVALID, -EIO,
+ "STATUS_NDIS_DOT11_POWER_STATE_INVALID"},
+ {STATUS_IPSEC_BAD_SPI, -EIO, "STATUS_IPSEC_BAD_SPI"},
+ {STATUS_IPSEC_SA_LIFETIME_EXPIRED, -EIO,
+ "STATUS_IPSEC_SA_LIFETIME_EXPIRED"},
+ {STATUS_IPSEC_WRONG_SA, -EIO, "STATUS_IPSEC_WRONG_SA"},
+ {STATUS_IPSEC_REPLAY_CHECK_FAILED, -EIO,
+ "STATUS_IPSEC_REPLAY_CHECK_FAILED"},
+ {STATUS_IPSEC_INVALID_PACKET, -EIO, "STATUS_IPSEC_INVALID_PACKET"},
+ {STATUS_IPSEC_INTEGRITY_CHECK_FAILED, -EIO,
+ "STATUS_IPSEC_INTEGRITY_CHECK_FAILED"},
+ {STATUS_IPSEC_CLEAR_TEXT_DROP, -EIO, "STATUS_IPSEC_CLEAR_TEXT_DROP"},
+ {0, 0, NULL}
+};
+
+/*****************************************************************************
+ Print an error message from the status code
+ *****************************************************************************/
+static void
+smb2_print_status(__le32 status)
+{
+ int idx = 0;
+
+ while (smb2_error_map_table[idx].status_string != NULL) {
+ if ((smb2_error_map_table[idx].smb2_status) == status) {
+ pr_notice("Status code returned 0x%08x %s\n", status,
+ smb2_error_map_table[idx].status_string);
+ }
+ idx++;
+ }
+ return;
+}
+
+int
+map_smb2_to_linux_error(char *buf, bool log_err)
+{
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+ unsigned int i;
+ int rc = -EIO;
+ __le32 smb2err = shdr->Status;
+
+ if (smb2err == 0) {
+ trace_smb3_cmd_done(le32_to_cpu(shdr->Id.SyncId.TreeId),
+ le64_to_cpu(shdr->SessionId),
+ le16_to_cpu(shdr->Command),
+ le64_to_cpu(shdr->MessageId));
+ return 0;
+ }
+
+ /* mask facility */
+ if (log_err && (smb2err != STATUS_MORE_PROCESSING_REQUIRED) &&
+ (smb2err != STATUS_END_OF_FILE))
+ smb2_print_status(smb2err);
+ else if (cifsFYI & CIFS_RC)
+ smb2_print_status(smb2err);
+
+ for (i = 0; i < sizeof(smb2_error_map_table) /
+ sizeof(struct status_to_posix_error); i++) {
+ if (smb2_error_map_table[i].smb2_status == smb2err) {
+ rc = smb2_error_map_table[i].posix_error;
+ break;
+ }
+ }
+
+ /* on error mapping not found - return EIO */
+
+ cifs_dbg(FYI, "Mapping SMB2 status code 0x%08x to POSIX err %d\n",
+ __le32_to_cpu(smb2err), rc);
+
+ trace_smb3_cmd_err(le32_to_cpu(shdr->Id.SyncId.TreeId),
+ le64_to_cpu(shdr->SessionId),
+ le16_to_cpu(shdr->Command),
+ le64_to_cpu(shdr->MessageId),
+ le32_to_cpu(smb2err), rc);
+ return rc;
+}
diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c
new file mode 100644
index 000000000000..572293c18e16
--- /dev/null
+++ b/fs/smb/client/smb2misc.c
@@ -0,0 +1,944 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2011
+ * Etersoft, 2012
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Pavel Shilovsky (pshilovsky@samba.org) 2012
+ *
+ */
+#include <linux/ctype.h>
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
+#include "cifs_debug.h"
+#include "cifs_unicode.h"
+#include "smb2status.h"
+#include "smb2glob.h"
+#include "nterr.h"
+#include "cached_dir.h"
+
+static int
+check_smb2_hdr(struct smb2_hdr *shdr, __u64 mid)
+{
+ __u64 wire_mid = le64_to_cpu(shdr->MessageId);
+
+ /*
+ * Make sure that this really is an SMB, that it is a response,
+ * and that the message ids match.
+ */
+ if ((shdr->ProtocolId == SMB2_PROTO_NUMBER) &&
+ (mid == wire_mid)) {
+ if (shdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
+ return 0;
+ else {
+ /* only one valid case where server sends us request */
+ if (shdr->Command == SMB2_OPLOCK_BREAK)
+ return 0;
+ else
+ cifs_dbg(VFS, "Received Request not response\n");
+ }
+ } else { /* bad signature or mid */
+ if (shdr->ProtocolId != SMB2_PROTO_NUMBER)
+ cifs_dbg(VFS, "Bad protocol string signature header %x\n",
+ le32_to_cpu(shdr->ProtocolId));
+ if (mid != wire_mid)
+ cifs_dbg(VFS, "Mids do not match: %llu and %llu\n",
+ mid, wire_mid);
+ }
+ cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu\n", wire_mid);
+ return 1;
+}
+
+/*
+ * The following table defines the expected "StructureSize" of SMB2 responses
+ * in order by SMB2 command. This is similar to "wct" in SMB/CIFS responses.
+ *
+ * Note that commands are defined in smb2pdu.h in le16 but the array below is
+ * indexed by command in host byte order
+ */
+static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
+ /* SMB2_NEGOTIATE */ cpu_to_le16(65),
+ /* SMB2_SESSION_SETUP */ cpu_to_le16(9),
+ /* SMB2_LOGOFF */ cpu_to_le16(4),
+ /* SMB2_TREE_CONNECT */ cpu_to_le16(16),
+ /* SMB2_TREE_DISCONNECT */ cpu_to_le16(4),
+ /* SMB2_CREATE */ cpu_to_le16(89),
+ /* SMB2_CLOSE */ cpu_to_le16(60),
+ /* SMB2_FLUSH */ cpu_to_le16(4),
+ /* SMB2_READ */ cpu_to_le16(17),
+ /* SMB2_WRITE */ cpu_to_le16(17),
+ /* SMB2_LOCK */ cpu_to_le16(4),
+ /* SMB2_IOCTL */ cpu_to_le16(49),
+ /* BB CHECK this ... not listed in documentation */
+ /* SMB2_CANCEL */ cpu_to_le16(0),
+ /* SMB2_ECHO */ cpu_to_le16(4),
+ /* SMB2_QUERY_DIRECTORY */ cpu_to_le16(9),
+ /* SMB2_CHANGE_NOTIFY */ cpu_to_le16(9),
+ /* SMB2_QUERY_INFO */ cpu_to_le16(9),
+ /* SMB2_SET_INFO */ cpu_to_le16(2),
+ /* BB FIXME can also be 44 for lease break */
+ /* SMB2_OPLOCK_BREAK */ cpu_to_le16(24)
+};
+
+#define SMB311_NEGPROT_BASE_SIZE (sizeof(struct smb2_hdr) + sizeof(struct smb2_negotiate_rsp))
+
+static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len,
+ __u32 non_ctxlen)
+{
+ __u16 neg_count;
+ __u32 nc_offset, size_of_pad_before_neg_ctxts;
+ struct smb2_negotiate_rsp *pneg_rsp = (struct smb2_negotiate_rsp *)hdr;
+
+ /* Negotiate contexts are only valid for latest dialect SMB3.11 */
+ neg_count = le16_to_cpu(pneg_rsp->NegotiateContextCount);
+ if ((neg_count == 0) ||
+ (pneg_rsp->DialectRevision != cpu_to_le16(SMB311_PROT_ID)))
+ return 0;
+
+ /*
+ * if SPNEGO blob present (ie the RFC2478 GSS info which indicates
+ * which security mechanisms the server supports) make sure that
+ * the negotiate contexts start after it
+ */
+ nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset);
+ /*
+ * non_ctxlen is at least shdr->StructureSize + pdu->StructureSize2
+ * and the latter is 1 byte bigger than the fix-sized area of the
+ * NEGOTIATE response
+ */
+ if (nc_offset + 1 < non_ctxlen) {
+ pr_warn_once("Invalid negotiate context offset %d\n", nc_offset);
+ return 0;
+ } else if (nc_offset + 1 == non_ctxlen) {
+ cifs_dbg(FYI, "no SPNEGO security blob in negprot rsp\n");
+ size_of_pad_before_neg_ctxts = 0;
+ } else if (non_ctxlen == SMB311_NEGPROT_BASE_SIZE)
+ /* has padding, but no SPNEGO blob */
+ size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen + 1;
+ else
+ size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen;
+
+ /* Verify that at least minimal negotiate contexts fit within frame */
+ if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) {
+ pr_warn_once("negotiate context goes beyond end\n");
+ return 0;
+ }
+
+ cifs_dbg(FYI, "length of negcontexts %d pad %d\n",
+ len - nc_offset, size_of_pad_before_neg_ctxts);
+
+ /* length of negcontexts including pad from end of sec blob to them */
+ return (len - nc_offset) + size_of_pad_before_neg_ctxts;
+}
+
+int
+smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)
+{
+ struct TCP_Server_Info *pserver;
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+ struct smb2_pdu *pdu = (struct smb2_pdu *)shdr;
+ int hdr_size = sizeof(struct smb2_hdr);
+ int pdu_size = sizeof(struct smb2_pdu);
+ int command;
+ __u32 calc_len; /* calculated length */
+ __u64 mid;
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+ /*
+ * Add function to do table lookup of StructureSize by command
+ * ie Validate the wct via smb2_struct_sizes table above
+ */
+ if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
+ struct smb2_transform_hdr *thdr =
+ (struct smb2_transform_hdr *)buf;
+ struct cifs_ses *ses = NULL;
+ struct cifs_ses *iter;
+
+ /* decrypt frame now that it is completely read in */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(iter, &pserver->smb_ses_list, smb_ses_list) {
+ if (iter->Suid == le64_to_cpu(thdr->SessionId)) {
+ ses = iter;
+ break;
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ if (!ses) {
+ cifs_dbg(VFS, "no decryption - session id not found\n");
+ return 1;
+ }
+ }
+
+ mid = le64_to_cpu(shdr->MessageId);
+ if (len < pdu_size) {
+ if ((len >= hdr_size)
+ && (shdr->Status != 0)) {
+ pdu->StructureSize2 = 0;
+ /*
+ * As with SMB/CIFS, on some error cases servers may
+ * not return wct properly
+ */
+ return 0;
+ } else {
+ cifs_dbg(VFS, "Length less than SMB header size\n");
+ }
+ return 1;
+ }
+ if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) {
+ cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n",
+ mid);
+ return 1;
+ }
+
+ if (check_smb2_hdr(shdr, mid))
+ return 1;
+
+ if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
+ cifs_dbg(VFS, "Invalid structure size %u\n",
+ le16_to_cpu(shdr->StructureSize));
+ return 1;
+ }
+
+ command = le16_to_cpu(shdr->Command);
+ if (command >= NUMBER_OF_SMB2_COMMANDS) {
+ cifs_dbg(VFS, "Invalid SMB2 command %d\n", command);
+ return 1;
+ }
+
+ if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) {
+ if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 ||
+ pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2_LE)) {
+ /* error packets have 9 byte structure size */
+ cifs_dbg(VFS, "Invalid response size %u for command %d\n",
+ le16_to_cpu(pdu->StructureSize2), command);
+ return 1;
+ } else if (command == SMB2_OPLOCK_BREAK_HE
+ && (shdr->Status == 0)
+ && (le16_to_cpu(pdu->StructureSize2) != 44)
+ && (le16_to_cpu(pdu->StructureSize2) != 36)) {
+ /* special case for SMB2.1 lease break message */
+ cifs_dbg(VFS, "Invalid response size %d for oplock break\n",
+ le16_to_cpu(pdu->StructureSize2));
+ return 1;
+ }
+ }
+
+ calc_len = smb2_calc_size(buf);
+
+ /* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might
+ * be 0, and not a real miscalculation */
+ if (command == SMB2_IOCTL_HE && calc_len == 0)
+ return 0;
+
+ if (command == SMB2_NEGOTIATE_HE)
+ calc_len += get_neg_ctxt_len(shdr, len, calc_len);
+
+ if (len != calc_len) {
+ /* create failed on symlink */
+ if (command == SMB2_CREATE_HE &&
+ shdr->Status == STATUS_STOPPED_ON_SYMLINK)
+ return 0;
+ /* Windows 7 server returns 24 bytes more */
+ if (calc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)
+ return 0;
+ /* server can return one byte more due to implied bcc[0] */
+ if (calc_len == len + 1)
+ return 0;
+
+ /*
+ * Some windows servers (win2016) will pad also the final
+ * PDU in a compound to 8 bytes.
+ */
+ if (ALIGN(calc_len, 8) == len)
+ return 0;
+
+ /*
+ * MacOS server pads after SMB2.1 write response with 3 bytes
+ * of junk. Other servers match RFC1001 len to actual
+ * SMB2/SMB3 frame length (header + smb2 response specific data)
+ * Some windows servers also pad up to 8 bytes when compounding.
+ */
+ if (calc_len < len)
+ return 0;
+
+ /* Only log a message if len was really miscalculated */
+ if (unlikely(cifsFYI))
+ cifs_dbg(FYI, "Server response too short: calculated "
+ "length %u doesn't match read length %u (cmd=%d, mid=%llu)\n",
+ calc_len, len, command, mid);
+ else
+ pr_warn("Server response too short: calculated length "
+ "%u doesn't match read length %u (cmd=%d, mid=%llu)\n",
+ calc_len, len, command, mid);
+
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * The size of the variable area depends on the offset and length fields
+ * located in different fields for various SMB2 responses. SMB2 responses
+ * with no variable length info, show an offset of zero for the offset field.
+ */
+static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
+ /* SMB2_NEGOTIATE */ true,
+ /* SMB2_SESSION_SETUP */ true,
+ /* SMB2_LOGOFF */ false,
+ /* SMB2_TREE_CONNECT */ false,
+ /* SMB2_TREE_DISCONNECT */ false,
+ /* SMB2_CREATE */ true,
+ /* SMB2_CLOSE */ false,
+ /* SMB2_FLUSH */ false,
+ /* SMB2_READ */ true,
+ /* SMB2_WRITE */ false,
+ /* SMB2_LOCK */ false,
+ /* SMB2_IOCTL */ true,
+ /* SMB2_CANCEL */ false, /* BB CHECK this not listed in documentation */
+ /* SMB2_ECHO */ false,
+ /* SMB2_QUERY_DIRECTORY */ true,
+ /* SMB2_CHANGE_NOTIFY */ true,
+ /* SMB2_QUERY_INFO */ true,
+ /* SMB2_SET_INFO */ false,
+ /* SMB2_OPLOCK_BREAK */ false
+};
+
+/*
+ * Returns the pointer to the beginning of the data area. Length of the data
+ * area and the offset to it (from the beginning of the smb are also returned.
+ */
+char *
+smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *shdr)
+{
+ *off = 0;
+ *len = 0;
+
+ /* error responses do not have data area */
+ if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
+ (((struct smb2_err_rsp *)shdr)->StructureSize) ==
+ SMB2_ERROR_STRUCTURE_SIZE2_LE)
+ return NULL;
+
+ /*
+ * Following commands have data areas so we have to get the location
+ * of the data buffer offset and data buffer length for the particular
+ * command.
+ */
+ switch (shdr->Command) {
+ case SMB2_NEGOTIATE:
+ *off = le16_to_cpu(
+ ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferOffset);
+ *len = le16_to_cpu(
+ ((struct smb2_negotiate_rsp *)shdr)->SecurityBufferLength);
+ break;
+ case SMB2_SESSION_SETUP:
+ *off = le16_to_cpu(
+ ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
+ *len = le16_to_cpu(
+ ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
+ break;
+ case SMB2_CREATE:
+ *off = le32_to_cpu(
+ ((struct smb2_create_rsp *)shdr)->CreateContextsOffset);
+ *len = le32_to_cpu(
+ ((struct smb2_create_rsp *)shdr)->CreateContextsLength);
+ break;
+ case SMB2_QUERY_INFO:
+ *off = le16_to_cpu(
+ ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset);
+ *len = le32_to_cpu(
+ ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength);
+ break;
+ case SMB2_READ:
+ /* TODO: is this a bug ? */
+ *off = ((struct smb2_read_rsp *)shdr)->DataOffset;
+ *len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength);
+ break;
+ case SMB2_QUERY_DIRECTORY:
+ *off = le16_to_cpu(
+ ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset);
+ *len = le32_to_cpu(
+ ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength);
+ break;
+ case SMB2_IOCTL:
+ *off = le32_to_cpu(
+ ((struct smb2_ioctl_rsp *)shdr)->OutputOffset);
+ *len = le32_to_cpu(
+ ((struct smb2_ioctl_rsp *)shdr)->OutputCount);
+ break;
+ case SMB2_CHANGE_NOTIFY:
+ *off = le16_to_cpu(
+ ((struct smb2_change_notify_rsp *)shdr)->OutputBufferOffset);
+ *len = le32_to_cpu(
+ ((struct smb2_change_notify_rsp *)shdr)->OutputBufferLength);
+ break;
+ default:
+ cifs_dbg(VFS, "no length check for command %d\n", le16_to_cpu(shdr->Command));
+ break;
+ }
+
+ /*
+ * Invalid length or offset probably means data area is invalid, but
+ * we have little choice but to ignore the data area in this case.
+ */
+ if (*off > 4096) {
+ cifs_dbg(VFS, "offset %d too large, data area ignored\n", *off);
+ *len = 0;
+ *off = 0;
+ } else if (*off < 0) {
+ cifs_dbg(VFS, "negative offset %d to data invalid ignore data area\n",
+ *off);
+ *off = 0;
+ *len = 0;
+ } else if (*len < 0) {
+ cifs_dbg(VFS, "negative data length %d invalid, data area ignored\n",
+ *len);
+ *len = 0;
+ } else if (*len > 128 * 1024) {
+ cifs_dbg(VFS, "data area larger than 128K: %d\n", *len);
+ *len = 0;
+ }
+
+ /* return pointer to beginning of data area, ie offset from SMB start */
+ if ((*off != 0) && (*len != 0))
+ return (char *)shdr + *off;
+ else
+ return NULL;
+}
+
+/*
+ * Calculate the size of the SMB message based on the fixed header
+ * portion, the number of word parameters and the data portion of the message.
+ */
+unsigned int
+smb2_calc_size(void *buf)
+{
+ struct smb2_pdu *pdu = buf;
+ struct smb2_hdr *shdr = &pdu->hdr;
+ int offset; /* the offset from the beginning of SMB to data area */
+ int data_length; /* the length of the variable length data area */
+ /* Structure Size has already been checked to make sure it is 64 */
+ int len = le16_to_cpu(shdr->StructureSize);
+
+ /*
+ * StructureSize2, ie length of fixed parameter area has already
+ * been checked to make sure it is the correct length.
+ */
+ len += le16_to_cpu(pdu->StructureSize2);
+
+ if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
+ goto calc_size_exit;
+
+ smb2_get_data_area_len(&offset, &data_length, shdr);
+ cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset);
+
+ if (data_length > 0) {
+ /*
+ * Check to make sure that data area begins after fixed area,
+ * Note that last byte of the fixed area is part of data area
+ * for some commands, typically those with odd StructureSize,
+ * so we must add one to the calculation.
+ */
+ if (offset + 1 < len) {
+ cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n",
+ offset + 1, len);
+ data_length = 0;
+ } else {
+ len = offset + data_length;
+ }
+ }
+calc_size_exit:
+ cifs_dbg(FYI, "SMB2 len %d\n", len);
+ return len;
+}
+
+/* Note: caller must free return buffer */
+__le16 *
+cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
+{
+ int len;
+ const char *start_of_path;
+ __le16 *to;
+ int map_type;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
+ map_type = SFM_MAP_UNI_RSVD;
+ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
+ map_type = SFU_MAP_UNI_RSVD;
+ else
+ map_type = NO_MAP_UNI_RSVD;
+
+ /* Windows doesn't allow paths beginning with \ */
+ if (from[0] == '\\')
+ start_of_path = from + 1;
+
+ /* SMB311 POSIX extensions paths do not include leading slash */
+ else if (cifs_sb_master_tlink(cifs_sb) &&
+ cifs_sb_master_tcon(cifs_sb)->posix_extensions &&
+ (from[0] == '/')) {
+ start_of_path = from + 1;
+ } else
+ start_of_path = from;
+
+ to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
+ cifs_sb->local_nls, map_type);
+ return to;
+}
+
+__le32
+smb2_get_lease_state(struct cifsInodeInfo *cinode)
+{
+ __le32 lease = 0;
+
+ if (CIFS_CACHE_WRITE(cinode))
+ lease |= SMB2_LEASE_WRITE_CACHING_LE;
+ if (CIFS_CACHE_HANDLE(cinode))
+ lease |= SMB2_LEASE_HANDLE_CACHING_LE;
+ if (CIFS_CACHE_READ(cinode))
+ lease |= SMB2_LEASE_READ_CACHING_LE;
+ return lease;
+}
+
+struct smb2_lease_break_work {
+ struct work_struct lease_break;
+ struct tcon_link *tlink;
+ __u8 lease_key[16];
+ __le32 lease_state;
+};
+
+static void
+cifs_ses_oplock_break(struct work_struct *work)
+{
+ struct smb2_lease_break_work *lw = container_of(work,
+ struct smb2_lease_break_work, lease_break);
+ int rc = 0;
+
+ rc = SMB2_lease_break(0, tlink_tcon(lw->tlink), lw->lease_key,
+ lw->lease_state);
+
+ cifs_dbg(FYI, "Lease release rc %d\n", rc);
+ cifs_put_tlink(lw->tlink);
+ kfree(lw);
+}
+
+static void
+smb2_queue_pending_open_break(struct tcon_link *tlink, __u8 *lease_key,
+ __le32 new_lease_state)
+{
+ struct smb2_lease_break_work *lw;
+
+ lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL);
+ if (!lw) {
+ cifs_put_tlink(tlink);
+ return;
+ }
+
+ INIT_WORK(&lw->lease_break, cifs_ses_oplock_break);
+ lw->tlink = tlink;
+ lw->lease_state = new_lease_state;
+ memcpy(lw->lease_key, lease_key, SMB2_LEASE_KEY_SIZE);
+ queue_work(cifsiod_wq, &lw->lease_break);
+}
+
+static bool
+smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp)
+{
+ __u8 lease_state;
+ struct cifsFileInfo *cfile;
+ struct cifsInodeInfo *cinode;
+ int ack_req = le32_to_cpu(rsp->Flags &
+ SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
+
+ lease_state = le32_to_cpu(rsp->NewLeaseState);
+
+ list_for_each_entry(cfile, &tcon->openFileList, tlist) {
+ cinode = CIFS_I(d_inode(cfile->dentry));
+
+ if (memcmp(cinode->lease_key, rsp->LeaseKey,
+ SMB2_LEASE_KEY_SIZE))
+ continue;
+
+ cifs_dbg(FYI, "found in the open list\n");
+ cifs_dbg(FYI, "lease key match, lease break 0x%x\n",
+ lease_state);
+
+ if (ack_req)
+ cfile->oplock_break_cancelled = false;
+ else
+ cfile->oplock_break_cancelled = true;
+
+ set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags);
+
+ cfile->oplock_epoch = le16_to_cpu(rsp->Epoch);
+ cfile->oplock_level = lease_state;
+
+ cifs_queue_oplock_break(cfile);
+ return true;
+ }
+
+ return false;
+}
+
+static struct cifs_pending_open *
+smb2_tcon_find_pending_open_lease(struct cifs_tcon *tcon,
+ struct smb2_lease_break *rsp)
+{
+ __u8 lease_state = le32_to_cpu(rsp->NewLeaseState);
+ int ack_req = le32_to_cpu(rsp->Flags &
+ SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED);
+ struct cifs_pending_open *open;
+ struct cifs_pending_open *found = NULL;
+
+ list_for_each_entry(open, &tcon->pending_opens, olist) {
+ if (memcmp(open->lease_key, rsp->LeaseKey,
+ SMB2_LEASE_KEY_SIZE))
+ continue;
+
+ if (!found && ack_req) {
+ found = open;
+ }
+
+ cifs_dbg(FYI, "found in the pending open list\n");
+ cifs_dbg(FYI, "lease key match, lease break 0x%x\n",
+ lease_state);
+
+ open->oplock = lease_state;
+ }
+
+ return found;
+}
+
+static bool
+smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
+{
+ struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer;
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+ struct cifs_pending_open *open;
+
+ cifs_dbg(FYI, "Checking for lease break\n");
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+ /* look up tcon based on tid & uid */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ spin_lock(&tcon->open_file_lock);
+ cifs_stats_inc(
+ &tcon->stats.cifs_stats.num_oplock_brks);
+ if (smb2_tcon_has_lease(tcon, rsp)) {
+ spin_unlock(&tcon->open_file_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ return true;
+ }
+ open = smb2_tcon_find_pending_open_lease(tcon,
+ rsp);
+ if (open) {
+ __u8 lease_key[SMB2_LEASE_KEY_SIZE];
+ struct tcon_link *tlink;
+
+ tlink = cifs_get_tlink(open->tlink);
+ memcpy(lease_key, open->lease_key,
+ SMB2_LEASE_KEY_SIZE);
+ spin_unlock(&tcon->open_file_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ smb2_queue_pending_open_break(tlink,
+ lease_key,
+ rsp->NewLeaseState);
+ return true;
+ }
+ spin_unlock(&tcon->open_file_lock);
+
+ if (cached_dir_lease_break(tcon, rsp->LeaseKey)) {
+ spin_unlock(&cifs_tcp_ses_lock);
+ return true;
+ }
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ cifs_dbg(FYI, "Can not process lease break - no lease matched\n");
+ trace_smb3_lease_not_found(le32_to_cpu(rsp->CurrentLeaseState),
+ le32_to_cpu(rsp->hdr.Id.SyncId.TreeId),
+ le64_to_cpu(rsp->hdr.SessionId),
+ *((u64 *)rsp->LeaseKey),
+ *((u64 *)&rsp->LeaseKey[8]));
+
+ return false;
+}
+
+bool
+smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
+{
+ struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+ struct cifsInodeInfo *cinode;
+ struct cifsFileInfo *cfile;
+
+ cifs_dbg(FYI, "Checking for oplock break\n");
+
+ if (rsp->hdr.Command != SMB2_OPLOCK_BREAK)
+ return false;
+
+ if (rsp->StructureSize !=
+ smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
+ if (le16_to_cpu(rsp->StructureSize) == 44)
+ return smb2_is_valid_lease_break(buffer, server);
+ else
+ return false;
+ }
+
+ cifs_dbg(FYI, "oplock level 0x%x\n", rsp->OplockLevel);
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+ /* look up tcon based on tid & uid */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(cfile, &tcon->openFileList, tlist) {
+ if (rsp->PersistentFid !=
+ cfile->fid.persistent_fid ||
+ rsp->VolatileFid !=
+ cfile->fid.volatile_fid)
+ continue;
+
+ cifs_dbg(FYI, "file id match, oplock break\n");
+ cifs_stats_inc(
+ &tcon->stats.cifs_stats.num_oplock_brks);
+ cinode = CIFS_I(d_inode(cfile->dentry));
+ spin_lock(&cfile->file_info_lock);
+ if (!CIFS_CACHE_WRITE(cinode) &&
+ rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE)
+ cfile->oplock_break_cancelled = true;
+ else
+ cfile->oplock_break_cancelled = false;
+
+ set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
+ &cinode->flags);
+
+ cfile->oplock_epoch = 0;
+ cfile->oplock_level = rsp->OplockLevel;
+
+ spin_unlock(&cfile->file_info_lock);
+
+ cifs_queue_oplock_break(cfile);
+
+ spin_unlock(&tcon->open_file_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ return true;
+ }
+ spin_unlock(&tcon->open_file_lock);
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ cifs_dbg(FYI, "No file id matched, oplock break ignored\n");
+ trace_smb3_oplock_not_found(0 /* no xid */, rsp->PersistentFid,
+ le32_to_cpu(rsp->hdr.Id.SyncId.TreeId),
+ le64_to_cpu(rsp->hdr.SessionId));
+
+ return true;
+}
+
+void
+smb2_cancelled_close_fid(struct work_struct *work)
+{
+ struct close_cancelled_open *cancelled = container_of(work,
+ struct close_cancelled_open, work);
+ struct cifs_tcon *tcon = cancelled->tcon;
+ int rc;
+
+ if (cancelled->mid)
+ cifs_tcon_dbg(VFS, "Close unmatched open for MID:%llu\n",
+ cancelled->mid);
+ else
+ cifs_tcon_dbg(VFS, "Close interrupted close\n");
+
+ rc = SMB2_close(0, tcon, cancelled->fid.persistent_fid,
+ cancelled->fid.volatile_fid);
+ if (rc)
+ cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc);
+
+ cifs_put_tcon(tcon);
+ kfree(cancelled);
+}
+
+/*
+ * Caller should already has an extra reference to @tcon
+ * This function is used to queue work to close a handle to prevent leaks
+ * on the server.
+ * We handle two cases. If an open was interrupted after we sent the
+ * SMB2_CREATE to the server but before we processed the reply, and second
+ * if a close was interrupted before we sent the SMB2_CLOSE to the server.
+ */
+static int
+__smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid,
+ __u64 persistent_fid, __u64 volatile_fid)
+{
+ struct close_cancelled_open *cancelled;
+
+ cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC);
+ if (!cancelled)
+ return -ENOMEM;
+
+ cancelled->fid.persistent_fid = persistent_fid;
+ cancelled->fid.volatile_fid = volatile_fid;
+ cancelled->tcon = tcon;
+ cancelled->cmd = cmd;
+ cancelled->mid = mid;
+ INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
+ WARN_ON(queue_work(cifsiod_wq, &cancelled->work) == false);
+
+ return 0;
+}
+
+int
+smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
+ __u64 volatile_fid)
+{
+ int rc;
+
+ cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
+ spin_lock(&cifs_tcp_ses_lock);
+ if (tcon->tc_count <= 0) {
+ struct TCP_Server_Info *server = NULL;
+
+ WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ if (tcon->ses)
+ server = tcon->ses->server;
+
+ cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n",
+ tcon->tid, persistent_fid, volatile_fid);
+
+ return 0;
+ }
+ tcon->tc_count++;
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
+ persistent_fid, volatile_fid);
+ if (rc)
+ cifs_put_tcon(tcon);
+
+ return rc;
+}
+
+int
+smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server)
+{
+ struct smb2_hdr *hdr = mid->resp_buf;
+ struct smb2_create_rsp *rsp = mid->resp_buf;
+ struct cifs_tcon *tcon;
+ int rc;
+
+ if ((mid->optype & CIFS_CP_CREATE_CLOSE_OP) || hdr->Command != SMB2_CREATE ||
+ hdr->Status != STATUS_SUCCESS)
+ return 0;
+
+ tcon = smb2_find_smb_tcon(server, le64_to_cpu(hdr->SessionId),
+ le32_to_cpu(hdr->Id.SyncId.TreeId));
+ if (!tcon)
+ return -ENOENT;
+
+ rc = __smb2_handle_cancelled_cmd(tcon,
+ le16_to_cpu(hdr->Command),
+ le64_to_cpu(hdr->MessageId),
+ rsp->PersistentFileId,
+ rsp->VolatileFileId);
+ if (rc)
+ cifs_put_tcon(tcon);
+
+ return rc;
+}
+
+/**
+ * smb311_update_preauth_hash - update @ses hash with the packet data in @iov
+ *
+ * Assumes @iov does not contain the rfc1002 length and iov[0] has the
+ * SMB2 header.
+ *
+ * @ses: server session structure
+ * @server: pointer to server info
+ * @iov: array containing the SMB request we will send to the server
+ * @nvec: number of array entries for the iov
+ */
+int
+smb311_update_preauth_hash(struct cifs_ses *ses, struct TCP_Server_Info *server,
+ struct kvec *iov, int nvec)
+{
+ int i, rc;
+ struct smb2_hdr *hdr;
+ struct shash_desc *sha512 = NULL;
+
+ hdr = (struct smb2_hdr *)iov[0].iov_base;
+ /* neg prot are always taken */
+ if (hdr->Command == SMB2_NEGOTIATE)
+ goto ok;
+
+ /*
+ * If we process a command which wasn't a negprot it means the
+ * neg prot was already done, so the server dialect was set
+ * and we can test it. Preauth requires 3.1.1 for now.
+ */
+ if (server->dialect != SMB311_PROT_ID)
+ return 0;
+
+ if (hdr->Command != SMB2_SESSION_SETUP)
+ return 0;
+
+ /* skip last sess setup response */
+ if ((hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
+ && (hdr->Status == NT_STATUS_OK
+ || (hdr->Status !=
+ cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))))
+ return 0;
+
+ok:
+ rc = smb311_crypto_shash_allocate(server);
+ if (rc)
+ return rc;
+
+ sha512 = server->secmech.sha512;
+ rc = crypto_shash_init(sha512);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not init sha512 shash\n", __func__);
+ return rc;
+ }
+
+ rc = crypto_shash_update(sha512, ses->preauth_sha_hash,
+ SMB2_PREAUTH_HASH_SIZE);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update sha512 shash\n", __func__);
+ return rc;
+ }
+
+ for (i = 0; i < nvec; i++) {
+ rc = crypto_shash_update(sha512, iov[i].iov_base, iov[i].iov_len);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update sha512 shash\n",
+ __func__);
+ return rc;
+ }
+ }
+
+ rc = crypto_shash_final(sha512, ses->preauth_sha_hash);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not finalize sha512 shash\n",
+ __func__);
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
new file mode 100644
index 000000000000..d512440d35b6
--- /dev/null
+++ b/fs/smb/client/smb2ops.c
@@ -0,0 +1,5805 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SMB2 version specific operations
+ *
+ * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
+ */
+
+#include <linux/pagemap.h>
+#include <linux/vfs.h>
+#include <linux/falloc.h>
+#include <linux/scatterlist.h>
+#include <linux/uuid.h>
+#include <linux/sort.h>
+#include <crypto/aead.h>
+#include <linux/fiemap.h>
+#include <uapi/linux/magic.h>
+#include "cifsfs.h"
+#include "cifsglob.h"
+#include "smb2pdu.h"
+#include "smb2proto.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_unicode.h"
+#include "smb2status.h"
+#include "smb2glob.h"
+#include "cifs_ioctl.h"
+#include "smbdirect.h"
+#include "fscache.h"
+#include "fs_context.h"
+#include "cached_dir.h"
+
+/* Change credits for different ops and return the total number of credits */
+static int
+change_conf(struct TCP_Server_Info *server)
+{
+ server->credits += server->echo_credits + server->oplock_credits;
+ server->oplock_credits = server->echo_credits = 0;
+ switch (server->credits) {
+ case 0:
+ return 0;
+ case 1:
+ server->echoes = false;
+ server->oplocks = false;
+ break;
+ case 2:
+ server->echoes = true;
+ server->oplocks = false;
+ server->echo_credits = 1;
+ break;
+ default:
+ server->echoes = true;
+ if (enable_oplocks) {
+ server->oplocks = true;
+ server->oplock_credits = 1;
+ } else
+ server->oplocks = false;
+
+ server->echo_credits = 1;
+ }
+ server->credits -= server->echo_credits + server->oplock_credits;
+ return server->credits + server->echo_credits + server->oplock_credits;
+}
+
+static void
+smb2_add_credits(struct TCP_Server_Info *server,
+ const struct cifs_credits *credits, const int optype)
+{
+ int *val, rc = -1;
+ int scredits, in_flight;
+ unsigned int add = credits->value;
+ unsigned int instance = credits->instance;
+ bool reconnect_detected = false;
+ bool reconnect_with_invalid_credits = false;
+
+ spin_lock(&server->req_lock);
+ val = server->ops->get_credits_field(server, optype);
+
+ /* eg found case where write overlapping reconnect messed up credits */
+ if (((optype & CIFS_OP_MASK) == CIFS_NEG_OP) && (*val != 0))
+ reconnect_with_invalid_credits = true;
+
+ if ((instance == 0) || (instance == server->reconnect_instance))
+ *val += add;
+ else
+ reconnect_detected = true;
+
+ if (*val > 65000) {
+ *val = 65000; /* Don't get near 64K credits, avoid srv bugs */
+ pr_warn_once("server overflowed SMB3 credits\n");
+ trace_smb3_overflow_credits(server->CurrentMid,
+ server->conn_id, server->hostname, *val,
+ add, server->in_flight);
+ }
+ server->in_flight--;
+ if (server->in_flight == 0 &&
+ ((optype & CIFS_OP_MASK) != CIFS_NEG_OP) &&
+ ((optype & CIFS_OP_MASK) != CIFS_SESS_OP))
+ rc = change_conf(server);
+ /*
+ * Sometimes server returns 0 credits on oplock break ack - we need to
+ * rebalance credits in this case.
+ */
+ else if (server->in_flight > 0 && server->oplock_credits == 0 &&
+ server->oplocks) {
+ if (server->credits > 1) {
+ server->credits--;
+ server->oplock_credits++;
+ }
+ }
+ scredits = *val;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+ wake_up(&server->request_q);
+
+ if (reconnect_detected) {
+ trace_smb3_reconnect_detected(server->CurrentMid,
+ server->conn_id, server->hostname, scredits, add, in_flight);
+
+ cifs_dbg(FYI, "trying to put %d credits from the old server instance %d\n",
+ add, instance);
+ }
+
+ if (reconnect_with_invalid_credits) {
+ trace_smb3_reconnect_with_invalid_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits, add, in_flight);
+ cifs_dbg(FYI, "Negotiate operation when server credits is non-zero. Optype: %d, server credits: %d, credits added: %d\n",
+ optype, scredits, add);
+ }
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsNeedReconnect
+ || server->tcpStatus == CifsExiting) {
+ spin_unlock(&server->srv_lock);
+ return;
+ }
+ spin_unlock(&server->srv_lock);
+
+ switch (rc) {
+ case -1:
+ /* change_conf hasn't been executed */
+ break;
+ case 0:
+ cifs_server_dbg(VFS, "Possible client or server bug - zero credits\n");
+ break;
+ case 1:
+ cifs_server_dbg(VFS, "disabling echoes and oplocks\n");
+ break;
+ case 2:
+ cifs_dbg(FYI, "disabling oplocks\n");
+ break;
+ default:
+ /* change_conf rebalanced credits for different types */
+ break;
+ }
+
+ trace_smb3_add_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits, add, in_flight);
+ cifs_dbg(FYI, "%s: added %u credits total=%d\n", __func__, add, scredits);
+}
+
+static void
+smb2_set_credits(struct TCP_Server_Info *server, const int val)
+{
+ int scredits, in_flight;
+
+ spin_lock(&server->req_lock);
+ server->credits = val;
+ if (val == 1)
+ server->reconnect_instance++;
+ scredits = server->credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+
+ trace_smb3_set_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits, val, in_flight);
+ cifs_dbg(FYI, "%s: set %u credits\n", __func__, val);
+
+ /* don't log while holding the lock */
+ if (val == 1)
+ cifs_dbg(FYI, "set credits to 1 due to smb2 reconnect\n");
+}
+
+static int *
+smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
+{
+ switch (optype) {
+ case CIFS_ECHO_OP:
+ return &server->echo_credits;
+ case CIFS_OBREAK_OP:
+ return &server->oplock_credits;
+ default:
+ return &server->credits;
+ }
+}
+
+static unsigned int
+smb2_get_credits(struct mid_q_entry *mid)
+{
+ return mid->credits_received;
+}
+
+static int
+smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
+ unsigned int *num, struct cifs_credits *credits)
+{
+ int rc = 0;
+ unsigned int scredits, in_flight;
+
+ spin_lock(&server->req_lock);
+ while (1) {
+ if (server->credits <= 0) {
+ spin_unlock(&server->req_lock);
+ cifs_num_waiters_inc(server);
+ rc = wait_event_killable(server->request_q,
+ has_credits(server, &server->credits, 1));
+ cifs_num_waiters_dec(server);
+ if (rc)
+ return rc;
+ spin_lock(&server->req_lock);
+ } else {
+ spin_unlock(&server->req_lock);
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsExiting) {
+ spin_unlock(&server->srv_lock);
+ return -ENOENT;
+ }
+ spin_unlock(&server->srv_lock);
+
+ spin_lock(&server->req_lock);
+ scredits = server->credits;
+ /* can deadlock with reopen */
+ if (scredits <= 8) {
+ *num = SMB2_MAX_BUFFER_SIZE;
+ credits->value = 0;
+ credits->instance = 0;
+ break;
+ }
+
+ /* leave some credits for reopen and other ops */
+ scredits -= 8;
+ *num = min_t(unsigned int, size,
+ scredits * SMB2_MAX_BUFFER_SIZE);
+
+ credits->value =
+ DIV_ROUND_UP(*num, SMB2_MAX_BUFFER_SIZE);
+ credits->instance = server->reconnect_instance;
+ server->credits -= credits->value;
+ server->in_flight++;
+ if (server->in_flight > server->max_in_flight)
+ server->max_in_flight = server->in_flight;
+ break;
+ }
+ }
+ scredits = server->credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+
+ trace_smb3_wait_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits, -(credits->value), in_flight);
+ cifs_dbg(FYI, "%s: removed %u credits total=%d\n",
+ __func__, credits->value, scredits);
+
+ return rc;
+}
+
+static int
+smb2_adjust_credits(struct TCP_Server_Info *server,
+ struct cifs_credits *credits,
+ const unsigned int payload_size)
+{
+ int new_val = DIV_ROUND_UP(payload_size, SMB2_MAX_BUFFER_SIZE);
+ int scredits, in_flight;
+
+ if (!credits->value || credits->value == new_val)
+ return 0;
+
+ if (credits->value < new_val) {
+ trace_smb3_too_many_credits(server->CurrentMid,
+ server->conn_id, server->hostname, 0, credits->value - new_val, 0);
+ cifs_server_dbg(VFS, "request has less credits (%d) than required (%d)",
+ credits->value, new_val);
+
+ return -ENOTSUPP;
+ }
+
+ spin_lock(&server->req_lock);
+
+ if (server->reconnect_instance != credits->instance) {
+ scredits = server->credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+
+ trace_smb3_reconnect_detected(server->CurrentMid,
+ server->conn_id, server->hostname, scredits,
+ credits->value - new_val, in_flight);
+ cifs_server_dbg(VFS, "trying to return %d credits to old session\n",
+ credits->value - new_val);
+ return -EAGAIN;
+ }
+
+ server->credits += credits->value - new_val;
+ scredits = server->credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+ wake_up(&server->request_q);
+
+ trace_smb3_adj_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits,
+ credits->value - new_val, in_flight);
+ cifs_dbg(FYI, "%s: adjust added %u credits total=%d\n",
+ __func__, credits->value - new_val, scredits);
+
+ credits->value = new_val;
+
+ return 0;
+}
+
+static __u64
+smb2_get_next_mid(struct TCP_Server_Info *server)
+{
+ __u64 mid;
+ /* for SMB2 we need the current value */
+ spin_lock(&server->mid_lock);
+ mid = server->CurrentMid++;
+ spin_unlock(&server->mid_lock);
+ return mid;
+}
+
+static void
+smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
+{
+ spin_lock(&server->mid_lock);
+ if (server->CurrentMid >= val)
+ server->CurrentMid -= val;
+ spin_unlock(&server->mid_lock);
+}
+
+static struct mid_q_entry *
+__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
+{
+ struct mid_q_entry *mid;
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+ __u64 wire_mid = le64_to_cpu(shdr->MessageId);
+
+ if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
+ cifs_server_dbg(VFS, "Encrypted frame parsing not supported yet\n");
+ return NULL;
+ }
+
+ spin_lock(&server->mid_lock);
+ list_for_each_entry(mid, &server->pending_mid_q, qhead) {
+ if ((mid->mid == wire_mid) &&
+ (mid->mid_state == MID_REQUEST_SUBMITTED) &&
+ (mid->command == shdr->Command)) {
+ kref_get(&mid->refcount);
+ if (dequeue) {
+ list_del_init(&mid->qhead);
+ mid->mid_flags |= MID_DELETED;
+ }
+ spin_unlock(&server->mid_lock);
+ return mid;
+ }
+ }
+ spin_unlock(&server->mid_lock);
+ return NULL;
+}
+
+static struct mid_q_entry *
+smb2_find_mid(struct TCP_Server_Info *server, char *buf)
+{
+ return __smb2_find_mid(server, buf, false);
+}
+
+static struct mid_q_entry *
+smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf)
+{
+ return __smb2_find_mid(server, buf, true);
+}
+
+static void
+smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
+{
+#ifdef CONFIG_CIFS_DEBUG2
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+
+ cifs_server_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
+ shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
+ shdr->Id.SyncId.ProcessId);
+ cifs_server_dbg(VFS, "smb buf %p len %u\n", buf,
+ server->ops->calc_smb_size(buf));
+#endif
+}
+
+static bool
+smb2_need_neg(struct TCP_Server_Info *server)
+{
+ return server->max_read == 0;
+}
+
+static int
+smb2_negotiate(const unsigned int xid,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ int rc;
+
+ spin_lock(&server->mid_lock);
+ server->CurrentMid = 0;
+ spin_unlock(&server->mid_lock);
+ rc = SMB2_negotiate(xid, ses, server);
+ /* BB we probably don't need to retry with modern servers */
+ if (rc == -EAGAIN)
+ rc = -EHOSTDOWN;
+ return rc;
+}
+
+static unsigned int
+smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+{
+ struct TCP_Server_Info *server = tcon->ses->server;
+ unsigned int wsize;
+
+ /* start with specified wsize, or default */
+ wsize = ctx->wsize ? ctx->wsize : CIFS_DEFAULT_IOSIZE;
+ wsize = min_t(unsigned int, wsize, server->max_write);
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
+ wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
+
+ return wsize;
+}
+
+static unsigned int
+smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+{
+ struct TCP_Server_Info *server = tcon->ses->server;
+ unsigned int wsize;
+
+ /* start with specified wsize, or default */
+ wsize = ctx->wsize ? ctx->wsize : SMB3_DEFAULT_IOSIZE;
+ wsize = min_t(unsigned int, wsize, server->max_write);
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ if (server->rdma) {
+ if (server->sign)
+ /*
+ * Account for SMB2 data transfer packet header and
+ * possible encryption header
+ */
+ wsize = min_t(unsigned int,
+ wsize,
+ server->smbd_conn->max_fragmented_send_size -
+ SMB2_READWRITE_PDU_HEADER_SIZE -
+ sizeof(struct smb2_transform_hdr));
+ else
+ wsize = min_t(unsigned int,
+ wsize, server->smbd_conn->max_readwrite_size);
+ }
+#endif
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
+ wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
+
+ return wsize;
+}
+
+static unsigned int
+smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+{
+ struct TCP_Server_Info *server = tcon->ses->server;
+ unsigned int rsize;
+
+ /* start with specified rsize, or default */
+ rsize = ctx->rsize ? ctx->rsize : CIFS_DEFAULT_IOSIZE;
+ rsize = min_t(unsigned int, rsize, server->max_read);
+
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
+ rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
+
+ return rsize;
+}
+
+static unsigned int
+smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
+{
+ struct TCP_Server_Info *server = tcon->ses->server;
+ unsigned int rsize;
+
+ /* start with specified rsize, or default */
+ rsize = ctx->rsize ? ctx->rsize : SMB3_DEFAULT_IOSIZE;
+ rsize = min_t(unsigned int, rsize, server->max_read);
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ if (server->rdma) {
+ if (server->sign)
+ /*
+ * Account for SMB2 data transfer packet header and
+ * possible encryption header
+ */
+ rsize = min_t(unsigned int,
+ rsize,
+ server->smbd_conn->max_fragmented_recv_size -
+ SMB2_READWRITE_PDU_HEADER_SIZE -
+ sizeof(struct smb2_transform_hdr));
+ else
+ rsize = min_t(unsigned int,
+ rsize, server->smbd_conn->max_readwrite_size);
+ }
+#endif
+
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
+ rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
+
+ return rsize;
+}
+
+static int
+parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
+ size_t buf_len, struct cifs_ses *ses, bool in_mount)
+{
+ struct network_interface_info_ioctl_rsp *p;
+ struct sockaddr_in *addr4;
+ struct sockaddr_in6 *addr6;
+ struct iface_info_ipv4 *p4;
+ struct iface_info_ipv6 *p6;
+ struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL;
+ struct cifs_server_iface tmp_iface;
+ ssize_t bytes_left;
+ size_t next = 0;
+ int nb_iface = 0;
+ int rc = 0, ret = 0;
+
+ bytes_left = buf_len;
+ p = buf;
+
+ spin_lock(&ses->iface_lock);
+ /* do not query too frequently, this time with lock held */
+ if (ses->iface_last_update &&
+ time_before(jiffies, ses->iface_last_update +
+ (SMB_INTERFACE_POLL_INTERVAL * HZ))) {
+ spin_unlock(&ses->iface_lock);
+ return 0;
+ }
+
+ /*
+ * Go through iface_list and do kref_put to remove
+ * any unused ifaces. ifaces in use will be removed
+ * when the last user calls a kref_put on it
+ */
+ list_for_each_entry_safe(iface, niface, &ses->iface_list,
+ iface_head) {
+ iface->is_active = 0;
+ kref_put(&iface->refcount, release_iface);
+ ses->iface_count--;
+ }
+ spin_unlock(&ses->iface_lock);
+
+ /*
+ * Samba server e.g. can return an empty interface list in some cases,
+ * which would only be a problem if we were requesting multichannel
+ */
+ if (bytes_left == 0) {
+ /* avoid spamming logs every 10 minutes, so log only in mount */
+ if ((ses->chan_max > 1) && in_mount)
+ cifs_dbg(VFS,
+ "multichannel not available\n"
+ "Empty network interface list returned by server %s\n",
+ ses->server->hostname);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ while (bytes_left >= sizeof(*p)) {
+ memset(&tmp_iface, 0, sizeof(tmp_iface));
+ tmp_iface.speed = le64_to_cpu(p->LinkSpeed);
+ tmp_iface.rdma_capable = le32_to_cpu(p->Capability & RDMA_CAPABLE) ? 1 : 0;
+ tmp_iface.rss_capable = le32_to_cpu(p->Capability & RSS_CAPABLE) ? 1 : 0;
+
+ switch (p->Family) {
+ /*
+ * The kernel and wire socket structures have the same
+ * layout and use network byte order but make the
+ * conversion explicit in case either one changes.
+ */
+ case INTERNETWORK:
+ addr4 = (struct sockaddr_in *)&tmp_iface.sockaddr;
+ p4 = (struct iface_info_ipv4 *)p->Buffer;
+ addr4->sin_family = AF_INET;
+ memcpy(&addr4->sin_addr, &p4->IPv4Address, 4);
+
+ /* [MS-SMB2] 2.2.32.5.1.1 Clients MUST ignore these */
+ addr4->sin_port = cpu_to_be16(CIFS_PORT);
+
+ cifs_dbg(FYI, "%s: ipv4 %pI4\n", __func__,
+ &addr4->sin_addr);
+ break;
+ case INTERNETWORKV6:
+ addr6 = (struct sockaddr_in6 *)&tmp_iface.sockaddr;
+ p6 = (struct iface_info_ipv6 *)p->Buffer;
+ addr6->sin6_family = AF_INET6;
+ memcpy(&addr6->sin6_addr, &p6->IPv6Address, 16);
+
+ /* [MS-SMB2] 2.2.32.5.1.2 Clients MUST ignore these */
+ addr6->sin6_flowinfo = 0;
+ addr6->sin6_scope_id = 0;
+ addr6->sin6_port = cpu_to_be16(CIFS_PORT);
+
+ cifs_dbg(FYI, "%s: ipv6 %pI6\n", __func__,
+ &addr6->sin6_addr);
+ break;
+ default:
+ cifs_dbg(VFS,
+ "%s: skipping unsupported socket family\n",
+ __func__);
+ goto next_iface;
+ }
+
+ /*
+ * The iface_list is assumed to be sorted by speed.
+ * Check if the new interface exists in that list.
+ * NEVER change iface. it could be in use.
+ * Add a new one instead
+ */
+ spin_lock(&ses->iface_lock);
+ iface = niface = NULL;
+ list_for_each_entry_safe(iface, niface, &ses->iface_list,
+ iface_head) {
+ ret = iface_cmp(iface, &tmp_iface);
+ if (!ret) {
+ /* just get a ref so that it doesn't get picked/freed */
+ iface->is_active = 1;
+ kref_get(&iface->refcount);
+ ses->iface_count++;
+ spin_unlock(&ses->iface_lock);
+ goto next_iface;
+ } else if (ret < 0) {
+ /* all remaining ifaces are slower */
+ kref_get(&iface->refcount);
+ break;
+ }
+ }
+ spin_unlock(&ses->iface_lock);
+
+ /* no match. insert the entry in the list */
+ info = kmalloc(sizeof(struct cifs_server_iface),
+ GFP_KERNEL);
+ if (!info) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ memcpy(info, &tmp_iface, sizeof(tmp_iface));
+
+ /* add this new entry to the list */
+ kref_init(&info->refcount);
+ info->is_active = 1;
+
+ cifs_dbg(FYI, "%s: adding iface %zu\n", __func__, ses->iface_count);
+ cifs_dbg(FYI, "%s: speed %zu bps\n", __func__, info->speed);
+ cifs_dbg(FYI, "%s: capabilities 0x%08x\n", __func__,
+ le32_to_cpu(p->Capability));
+
+ spin_lock(&ses->iface_lock);
+ if (!list_entry_is_head(iface, &ses->iface_list, iface_head)) {
+ list_add_tail(&info->iface_head, &iface->iface_head);
+ kref_put(&iface->refcount, release_iface);
+ } else
+ list_add_tail(&info->iface_head, &ses->iface_list);
+
+ ses->iface_count++;
+ spin_unlock(&ses->iface_lock);
+ ses->iface_last_update = jiffies;
+next_iface:
+ nb_iface++;
+ next = le32_to_cpu(p->Next);
+ if (!next) {
+ bytes_left -= sizeof(*p);
+ break;
+ }
+ p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next);
+ bytes_left -= next;
+ }
+
+ if (!nb_iface) {
+ cifs_dbg(VFS, "%s: malformed interface info\n", __func__);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Azure rounds the buffer size up 8, to a 16 byte boundary */
+ if ((bytes_left > 8) || p->Next)
+ cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);
+
+
+ if (!ses->iface_count) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+out:
+ return rc;
+}
+
+int
+SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount)
+{
+ int rc;
+ unsigned int ret_data_len = 0;
+ struct network_interface_info_ioctl_rsp *out_buf = NULL;
+ struct cifs_ses *ses = tcon->ses;
+
+ /* do not query too frequently */
+ if (ses->iface_last_update &&
+ time_before(jiffies, ses->iface_last_update +
+ (SMB_INTERFACE_POLL_INTERVAL * HZ)))
+ return 0;
+
+ rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
+ FSCTL_QUERY_NETWORK_INTERFACE_INFO,
+ NULL /* no data input */, 0 /* no data input */,
+ CIFSMaxBufSize, (char **)&out_buf, &ret_data_len);
+ if (rc == -EOPNOTSUPP) {
+ cifs_dbg(FYI,
+ "server does not support query network interfaces\n");
+ ret_data_len = 0;
+ } else if (rc != 0) {
+ cifs_tcon_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
+ goto out;
+ }
+
+ rc = parse_server_interfaces(out_buf, ret_data_len, ses, in_mount);
+ if (rc)
+ goto out;
+
+out:
+ kfree(out_buf);
+ return rc;
+}
+
+static void
+smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb)
+{
+ int rc;
+ __le16 srch_path = 0; /* Null - open root of share */
+ u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_open_parms oparms;
+ struct cifs_fid fid;
+ struct cached_fid *cfid = NULL;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = "",
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .fid = &fid,
+ };
+
+ rc = open_cached_dir(xid, tcon, "", cifs_sb, false, &cfid);
+ if (rc == 0)
+ memcpy(&fid, &cfid->fid, sizeof(struct cifs_fid));
+ else
+ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
+ NULL, NULL);
+ if (rc)
+ return;
+
+ SMB3_request_interfaces(xid, tcon, true /* called during mount */);
+
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_ATTRIBUTE_INFORMATION);
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_DEVICE_INFORMATION);
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_VOLUME_INFORMATION);
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
+ if (cfid == NULL)
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ else
+ close_cached_dir(cfid);
+}
+
+static void
+smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb)
+{
+ int rc;
+ __le16 srch_path = 0; /* Null - open root of share */
+ u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_open_parms oparms;
+ struct cifs_fid fid;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = "",
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .fid = &fid,
+ };
+
+ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
+ NULL, NULL);
+ if (rc)
+ return;
+
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_ATTRIBUTE_INFORMATION);
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_DEVICE_INFORMATION);
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+}
+
+static int
+smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path)
+{
+ __le16 *utf16_path;
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ int err_buftype = CIFS_NO_BUFFER;
+ struct cifs_open_parms oparms;
+ struct kvec err_iov = {};
+ struct cifs_fid fid;
+ struct cached_fid *cfid;
+ bool islink;
+ int rc, rc2;
+
+ rc = open_cached_dir(xid, tcon, full_path, cifs_sb, true, &cfid);
+ if (!rc) {
+ if (cfid->has_lease) {
+ close_cached_dir(cfid);
+ return 0;
+ }
+ close_cached_dir(cfid);
+ }
+
+ utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = full_path,
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .fid = &fid,
+ };
+
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
+ &err_iov, &err_buftype);
+ if (rc) {
+ struct smb2_hdr *hdr = err_iov.iov_base;
+
+ if (unlikely(!hdr || err_buftype == CIFS_NO_BUFFER))
+ goto out;
+
+ if (rc != -EREMOTE && hdr->Status == STATUS_OBJECT_NAME_INVALID) {
+ rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
+ full_path, &islink);
+ if (rc2) {
+ rc = rc2;
+ goto out;
+ }
+ if (islink)
+ rc = -EREMOTE;
+ }
+ if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb &&
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS))
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
+ rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+
+out:
+ free_rsp_buf(err_buftype, err_iov.iov_base);
+ kfree(utf16_path);
+ return rc;
+}
+
+static int smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ u64 *uniqueid, struct cifs_open_info_data *data)
+{
+ *uniqueid = le64_to_cpu(data->fi.IndexNumber);
+ return 0;
+}
+
+static int smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, struct cifs_open_info_data *data)
+{
+ struct cifs_fid *fid = &cfile->fid;
+
+ if (cfile->symlink_target) {
+ data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
+ if (!data->symlink_target)
+ return -ENOMEM;
+ }
+ return SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid, &data->fi);
+}
+
+#ifdef CONFIG_CIFS_XATTR
+static ssize_t
+move_smb2_ea_to_cifs(char *dst, size_t dst_size,
+ struct smb2_file_full_ea_info *src, size_t src_size,
+ const unsigned char *ea_name)
+{
+ int rc = 0;
+ unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
+ char *name, *value;
+ size_t buf_size = dst_size;
+ size_t name_len, value_len, user_name_len;
+
+ while (src_size > 0) {
+ name_len = (size_t)src->ea_name_length;
+ value_len = (size_t)le16_to_cpu(src->ea_value_length);
+
+ if (name_len == 0)
+ break;
+
+ if (src_size < 8 + name_len + 1 + value_len) {
+ cifs_dbg(FYI, "EA entry goes beyond length of list\n");
+ rc = -EIO;
+ goto out;
+ }
+
+ name = &src->ea_data[0];
+ value = &src->ea_data[src->ea_name_length + 1];
+
+ if (ea_name) {
+ if (ea_name_len == name_len &&
+ memcmp(ea_name, name, name_len) == 0) {
+ rc = value_len;
+ if (dst_size == 0)
+ goto out;
+ if (dst_size < value_len) {
+ rc = -ERANGE;
+ goto out;
+ }
+ memcpy(dst, value, value_len);
+ goto out;
+ }
+ } else {
+ /* 'user.' plus a terminating null */
+ user_name_len = 5 + 1 + name_len;
+
+ if (buf_size == 0) {
+ /* skip copy - calc size only */
+ rc += user_name_len;
+ } else if (dst_size >= user_name_len) {
+ dst_size -= user_name_len;
+ memcpy(dst, "user.", 5);
+ dst += 5;
+ memcpy(dst, src->ea_data, name_len);
+ dst += name_len;
+ *dst = 0;
+ ++dst;
+ rc += user_name_len;
+ } else {
+ /* stop before overrun buffer */
+ rc = -ERANGE;
+ break;
+ }
+ }
+
+ if (!src->next_entry_offset)
+ break;
+
+ if (src_size < le32_to_cpu(src->next_entry_offset)) {
+ /* stop before overrun buffer */
+ rc = -ERANGE;
+ break;
+ }
+ src_size -= le32_to_cpu(src->next_entry_offset);
+ src = (void *)((char *)src +
+ le32_to_cpu(src->next_entry_offset));
+ }
+
+ /* didn't find the named attribute */
+ if (ea_name)
+ rc = -ENODATA;
+
+out:
+ return (ssize_t)rc;
+}
+
+static ssize_t
+smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
+ const unsigned char *path, const unsigned char *ea_name,
+ char *ea_data, size_t buf_size,
+ struct cifs_sb_info *cifs_sb)
+{
+ int rc;
+ struct kvec rsp_iov = {NULL, 0};
+ int buftype = CIFS_NO_BUFFER;
+ struct smb2_query_info_rsp *rsp;
+ struct smb2_file_full_ea_info *info = NULL;
+
+ rc = smb2_query_info_compound(xid, tcon, path,
+ FILE_READ_EA,
+ FILE_FULL_EA_INFORMATION,
+ SMB2_O_INFO_FILE,
+ CIFSMaxBufSize -
+ MAX_SMB2_CREATE_RESPONSE_SIZE -
+ MAX_SMB2_CLOSE_RESPONSE_SIZE,
+ &rsp_iov, &buftype, cifs_sb);
+ if (rc) {
+ /*
+ * If ea_name is NULL (listxattr) and there are no EAs,
+ * return 0 as it's not an error. Otherwise, the specified
+ * ea_name was not found.
+ */
+ if (!ea_name && rc == -ENODATA)
+ rc = 0;
+ goto qeas_exit;
+ }
+
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
+ rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
+ le32_to_cpu(rsp->OutputBufferLength),
+ &rsp_iov,
+ sizeof(struct smb2_file_full_ea_info));
+ if (rc)
+ goto qeas_exit;
+
+ info = (struct smb2_file_full_ea_info *)(
+ le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
+ rc = move_smb2_ea_to_cifs(ea_data, buf_size, info,
+ le32_to_cpu(rsp->OutputBufferLength), ea_name);
+
+ qeas_exit:
+ free_rsp_buf(buftype, rsp_iov.iov_base);
+ return rc;
+}
+
+
+static int
+smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *path, const char *ea_name, const void *ea_value,
+ const __u16 ea_value_len, const struct nls_table *nls_codepage,
+ struct cifs_sb_info *cifs_sb)
+{
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ __le16 *utf16_path = NULL;
+ int ea_name_len = strlen(ea_name);
+ int flags = CIFS_CP_CREATE_CLOSE_OP;
+ int len;
+ struct smb_rqst rqst[3];
+ int resp_buftype[3];
+ struct kvec rsp_iov[3];
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+ struct cifs_open_parms oparms;
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_fid fid;
+ struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
+ unsigned int size[1];
+ void *data[1];
+ struct smb2_file_full_ea_info *ea = NULL;
+ struct kvec close_iov[1];
+ struct smb2_query_info_rsp *rsp;
+ int rc, used_len = 0;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ if (ea_name_len > 255)
+ return -EINVAL;
+
+ utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
+
+ memset(rqst, 0, sizeof(rqst));
+ resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
+ memset(rsp_iov, 0, sizeof(rsp_iov));
+
+ if (ses->server->ops->query_all_EAs) {
+ if (!ea_value) {
+ rc = ses->server->ops->query_all_EAs(xid, tcon, path,
+ ea_name, NULL, 0,
+ cifs_sb);
+ if (rc == -ENODATA)
+ goto sea_exit;
+ } else {
+ /* If we are adding a attribute we should first check
+ * if there will be enough space available to store
+ * the new EA. If not we should not add it since we
+ * would not be able to even read the EAs back.
+ */
+ rc = smb2_query_info_compound(xid, tcon, path,
+ FILE_READ_EA,
+ FILE_FULL_EA_INFORMATION,
+ SMB2_O_INFO_FILE,
+ CIFSMaxBufSize -
+ MAX_SMB2_CREATE_RESPONSE_SIZE -
+ MAX_SMB2_CLOSE_RESPONSE_SIZE,
+ &rsp_iov[1], &resp_buftype[1], cifs_sb);
+ if (rc == 0) {
+ rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
+ used_len = le32_to_cpu(rsp->OutputBufferLength);
+ }
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ resp_buftype[1] = CIFS_NO_BUFFER;
+ memset(&rsp_iov[1], 0, sizeof(rsp_iov[1]));
+ rc = 0;
+
+ /* Use a fudge factor of 256 bytes in case we collide
+ * with a different set_EAs command.
+ */
+ if(CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE -
+ MAX_SMB2_CLOSE_RESPONSE_SIZE - 256 <
+ used_len + ea_name_len + ea_value_len + 1) {
+ rc = -ENOSPC;
+ goto sea_exit;
+ }
+ }
+ }
+
+ /* Open */
+ memset(&open_iov, 0, sizeof(open_iov));
+ rqst[0].rq_iov = open_iov;
+ rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = path,
+ .desired_access = FILE_WRITE_EA,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .fid = &fid,
+ };
+
+ rc = SMB2_open_init(tcon, server,
+ &rqst[0], &oplock, &oparms, utf16_path);
+ if (rc)
+ goto sea_exit;
+ smb2_set_next_command(tcon, &rqst[0]);
+
+
+ /* Set Info */
+ memset(&si_iov, 0, sizeof(si_iov));
+ rqst[1].rq_iov = si_iov;
+ rqst[1].rq_nvec = 1;
+
+ len = sizeof(*ea) + ea_name_len + ea_value_len + 1;
+ ea = kzalloc(len, GFP_KERNEL);
+ if (ea == NULL) {
+ rc = -ENOMEM;
+ goto sea_exit;
+ }
+
+ ea->ea_name_length = ea_name_len;
+ ea->ea_value_length = cpu_to_le16(ea_value_len);
+ memcpy(ea->ea_data, ea_name, ea_name_len + 1);
+ memcpy(ea->ea_data + ea_name_len + 1, ea_value, ea_value_len);
+
+ size[0] = len;
+ data[0] = ea;
+
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst[1], COMPOUND_FID,
+ COMPOUND_FID, current->tgid,
+ FILE_FULL_EA_INFORMATION,
+ SMB2_O_INFO_FILE, 0, data, size);
+ if (rc)
+ goto sea_exit;
+ smb2_set_next_command(tcon, &rqst[1]);
+ smb2_set_related(&rqst[1]);
+
+
+ /* Close */
+ memset(&close_iov, 0, sizeof(close_iov));
+ rqst[2].rq_iov = close_iov;
+ rqst[2].rq_nvec = 1;
+ rc = SMB2_close_init(tcon, server,
+ &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
+ if (rc)
+ goto sea_exit;
+ smb2_set_related(&rqst[2]);
+
+ rc = compound_send_recv(xid, ses, server,
+ flags, 3, rqst,
+ resp_buftype, rsp_iov);
+ /* no need to bump num_remote_opens because handle immediately closed */
+
+ sea_exit:
+ kfree(ea);
+ kfree(utf16_path);
+ SMB2_open_free(&rqst[0]);
+ SMB2_set_info_free(&rqst[1]);
+ SMB2_close_free(&rqst[2]);
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+ return rc;
+}
+#endif
+
+static bool
+smb2_can_echo(struct TCP_Server_Info *server)
+{
+ return server->echoes;
+}
+
+static void
+smb2_clear_stats(struct cifs_tcon *tcon)
+{
+ int i;
+
+ for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
+ atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0);
+ atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0);
+ }
+}
+
+static void
+smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon)
+{
+ seq_puts(m, "\n\tShare Capabilities:");
+ if (tcon->capabilities & SMB2_SHARE_CAP_DFS)
+ seq_puts(m, " DFS,");
+ if (tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
+ seq_puts(m, " CONTINUOUS AVAILABILITY,");
+ if (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT)
+ seq_puts(m, " SCALEOUT,");
+ if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER)
+ seq_puts(m, " CLUSTER,");
+ if (tcon->capabilities & SMB2_SHARE_CAP_ASYMMETRIC)
+ seq_puts(m, " ASYMMETRIC,");
+ if (tcon->capabilities == 0)
+ seq_puts(m, " None");
+ if (tcon->ss_flags & SSINFO_FLAGS_ALIGNED_DEVICE)
+ seq_puts(m, " Aligned,");
+ if (tcon->ss_flags & SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE)
+ seq_puts(m, " Partition Aligned,");
+ if (tcon->ss_flags & SSINFO_FLAGS_NO_SEEK_PENALTY)
+ seq_puts(m, " SSD,");
+ if (tcon->ss_flags & SSINFO_FLAGS_TRIM_ENABLED)
+ seq_puts(m, " TRIM-support,");
+
+ seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags);
+ seq_printf(m, "\n\ttid: 0x%x", tcon->tid);
+ if (tcon->perf_sector_size)
+ seq_printf(m, "\tOptimal sector size: 0x%x",
+ tcon->perf_sector_size);
+ seq_printf(m, "\tMaximal Access: 0x%x", tcon->maximal_access);
+}
+
+static void
+smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
+{
+ atomic_t *sent = tcon->stats.smb2_stats.smb2_com_sent;
+ atomic_t *failed = tcon->stats.smb2_stats.smb2_com_failed;
+
+ /*
+ * Can't display SMB2_NEGOTIATE, SESSION_SETUP, LOGOFF, CANCEL and ECHO
+ * totals (requests sent) since those SMBs are per-session not per tcon
+ */
+ seq_printf(m, "\nBytes read: %llu Bytes written: %llu",
+ (long long)(tcon->bytes_read),
+ (long long)(tcon->bytes_written));
+ seq_printf(m, "\nOpen files: %d total (local), %d open on server",
+ atomic_read(&tcon->num_local_opens),
+ atomic_read(&tcon->num_remote_opens));
+ seq_printf(m, "\nTreeConnects: %d total %d failed",
+ atomic_read(&sent[SMB2_TREE_CONNECT_HE]),
+ atomic_read(&failed[SMB2_TREE_CONNECT_HE]));
+ seq_printf(m, "\nTreeDisconnects: %d total %d failed",
+ atomic_read(&sent[SMB2_TREE_DISCONNECT_HE]),
+ atomic_read(&failed[SMB2_TREE_DISCONNECT_HE]));
+ seq_printf(m, "\nCreates: %d total %d failed",
+ atomic_read(&sent[SMB2_CREATE_HE]),
+ atomic_read(&failed[SMB2_CREATE_HE]));
+ seq_printf(m, "\nCloses: %d total %d failed",
+ atomic_read(&sent[SMB2_CLOSE_HE]),
+ atomic_read(&failed[SMB2_CLOSE_HE]));
+ seq_printf(m, "\nFlushes: %d total %d failed",
+ atomic_read(&sent[SMB2_FLUSH_HE]),
+ atomic_read(&failed[SMB2_FLUSH_HE]));
+ seq_printf(m, "\nReads: %d total %d failed",
+ atomic_read(&sent[SMB2_READ_HE]),
+ atomic_read(&failed[SMB2_READ_HE]));
+ seq_printf(m, "\nWrites: %d total %d failed",
+ atomic_read(&sent[SMB2_WRITE_HE]),
+ atomic_read(&failed[SMB2_WRITE_HE]));
+ seq_printf(m, "\nLocks: %d total %d failed",
+ atomic_read(&sent[SMB2_LOCK_HE]),
+ atomic_read(&failed[SMB2_LOCK_HE]));
+ seq_printf(m, "\nIOCTLs: %d total %d failed",
+ atomic_read(&sent[SMB2_IOCTL_HE]),
+ atomic_read(&failed[SMB2_IOCTL_HE]));
+ seq_printf(m, "\nQueryDirectories: %d total %d failed",
+ atomic_read(&sent[SMB2_QUERY_DIRECTORY_HE]),
+ atomic_read(&failed[SMB2_QUERY_DIRECTORY_HE]));
+ seq_printf(m, "\nChangeNotifies: %d total %d failed",
+ atomic_read(&sent[SMB2_CHANGE_NOTIFY_HE]),
+ atomic_read(&failed[SMB2_CHANGE_NOTIFY_HE]));
+ seq_printf(m, "\nQueryInfos: %d total %d failed",
+ atomic_read(&sent[SMB2_QUERY_INFO_HE]),
+ atomic_read(&failed[SMB2_QUERY_INFO_HE]));
+ seq_printf(m, "\nSetInfos: %d total %d failed",
+ atomic_read(&sent[SMB2_SET_INFO_HE]),
+ atomic_read(&failed[SMB2_SET_INFO_HE]));
+ seq_printf(m, "\nOplockBreaks: %d sent %d failed",
+ atomic_read(&sent[SMB2_OPLOCK_BREAK_HE]),
+ atomic_read(&failed[SMB2_OPLOCK_BREAK_HE]));
+}
+
+static void
+smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
+{
+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
+ struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
+
+ cfile->fid.persistent_fid = fid->persistent_fid;
+ cfile->fid.volatile_fid = fid->volatile_fid;
+ cfile->fid.access = fid->access;
+#ifdef CONFIG_CIFS_DEBUG2
+ cfile->fid.mid = fid->mid;
+#endif /* CIFS_DEBUG2 */
+ server->ops->set_oplock_level(cinode, oplock, fid->epoch,
+ &fid->purge_cache);
+ cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
+ memcpy(cfile->fid.create_guid, fid->create_guid, 16);
+}
+
+static void
+smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid)
+{
+ SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
+}
+
+static void
+smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile)
+{
+ struct smb2_file_network_open_info file_inf;
+ struct inode *inode;
+ int rc;
+
+ rc = __SMB2_close(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, &file_inf);
+ if (rc)
+ return;
+
+ inode = d_inode(cfile->dentry);
+
+ spin_lock(&inode->i_lock);
+ CIFS_I(inode)->time = jiffies;
+
+ /* Creation time should not need to be updated on close */
+ if (file_inf.LastWriteTime)
+ inode->i_mtime = cifs_NTtimeToUnix(file_inf.LastWriteTime);
+ if (file_inf.ChangeTime)
+ inode->i_ctime = cifs_NTtimeToUnix(file_inf.ChangeTime);
+ if (file_inf.LastAccessTime)
+ inode->i_atime = cifs_NTtimeToUnix(file_inf.LastAccessTime);
+
+ /*
+ * i_blocks is not related to (i_size / i_blksize),
+ * but instead 512 byte (2**9) size is required for
+ * calculating num blocks.
+ */
+ if (le64_to_cpu(file_inf.AllocationSize) > 4096)
+ inode->i_blocks =
+ (512 - 1 + le64_to_cpu(file_inf.AllocationSize)) >> 9;
+
+ /* End of file and Attributes should not have to be updated on close */
+ spin_unlock(&inode->i_lock);
+}
+
+static int
+SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ struct copychunk_ioctl *pcchunk)
+{
+ int rc;
+ unsigned int ret_data_len;
+ struct resume_key_req *res_key;
+
+ rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
+ FSCTL_SRV_REQUEST_RESUME_KEY, NULL, 0 /* no input */,
+ CIFSMaxBufSize, (char **)&res_key, &ret_data_len);
+
+ if (rc == -EOPNOTSUPP) {
+ pr_warn_once("Server share %s does not support copy range\n", tcon->tree_name);
+ goto req_res_key_exit;
+ } else if (rc) {
+ cifs_tcon_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc);
+ goto req_res_key_exit;
+ }
+ if (ret_data_len < sizeof(struct resume_key_req)) {
+ cifs_tcon_dbg(VFS, "Invalid refcopy resume key length\n");
+ rc = -EINVAL;
+ goto req_res_key_exit;
+ }
+ memcpy(pcchunk->SourceKey, res_key->ResumeKey, COPY_CHUNK_RES_KEY_SIZE);
+
+req_res_key_exit:
+ kfree(res_key);
+ return rc;
+}
+
+struct iqi_vars {
+ struct smb_rqst rqst[3];
+ struct kvec rsp_iov[3];
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+ struct kvec qi_iov[1];
+ struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
+ struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
+ struct kvec close_iov[1];
+};
+
+static int
+smb2_ioctl_query_info(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ __le16 *path, int is_dir,
+ unsigned long p)
+{
+ struct iqi_vars *vars;
+ struct smb_rqst *rqst;
+ struct kvec *rsp_iov;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ char __user *arg = (char __user *)p;
+ struct smb_query_info qi;
+ struct smb_query_info __user *pqi;
+ int rc = 0;
+ int flags = CIFS_CP_CREATE_CLOSE_OP;
+ struct smb2_query_info_rsp *qi_rsp = NULL;
+ struct smb2_ioctl_rsp *io_rsp = NULL;
+ void *buffer = NULL;
+ int resp_buftype[3];
+ struct cifs_open_parms oparms;
+ u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_fid fid;
+ unsigned int size[2];
+ void *data[2];
+ int create_options = is_dir ? CREATE_NOT_FILE : CREATE_NOT_DIR;
+ void (*free_req1_func)(struct smb_rqst *r);
+
+ vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
+ if (vars == NULL)
+ return -ENOMEM;
+ rqst = &vars->rqst[0];
+ rsp_iov = &vars->rsp_iov[0];
+
+ resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
+
+ if (copy_from_user(&qi, arg, sizeof(struct smb_query_info))) {
+ rc = -EFAULT;
+ goto free_vars;
+ }
+ if (qi.output_buffer_length > 1024) {
+ rc = -EINVAL;
+ goto free_vars;
+ }
+
+ if (!ses || !server) {
+ rc = -EIO;
+ goto free_vars;
+ }
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ if (qi.output_buffer_length) {
+ buffer = memdup_user(arg + sizeof(struct smb_query_info), qi.output_buffer_length);
+ if (IS_ERR(buffer)) {
+ rc = PTR_ERR(buffer);
+ goto free_vars;
+ }
+ }
+
+ /* Open */
+ rqst[0].rq_iov = &vars->open_iov[0];
+ rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, create_options),
+ .fid = &fid,
+ };
+
+ if (qi.flags & PASSTHRU_FSCTL) {
+ switch (qi.info_type & FSCTL_DEVICE_ACCESS_MASK) {
+ case FSCTL_DEVICE_ACCESS_FILE_READ_WRITE_ACCESS:
+ oparms.desired_access = FILE_READ_DATA | FILE_WRITE_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE;
+ break;
+ case FSCTL_DEVICE_ACCESS_FILE_ANY_ACCESS:
+ oparms.desired_access = GENERIC_ALL;
+ break;
+ case FSCTL_DEVICE_ACCESS_FILE_READ_ACCESS:
+ oparms.desired_access = GENERIC_READ;
+ break;
+ case FSCTL_DEVICE_ACCESS_FILE_WRITE_ACCESS:
+ oparms.desired_access = GENERIC_WRITE;
+ break;
+ }
+ } else if (qi.flags & PASSTHRU_SET_INFO) {
+ oparms.desired_access = GENERIC_WRITE;
+ } else {
+ oparms.desired_access = FILE_READ_ATTRIBUTES | READ_CONTROL;
+ }
+
+ rc = SMB2_open_init(tcon, server,
+ &rqst[0], &oplock, &oparms, path);
+ if (rc)
+ goto free_output_buffer;
+ smb2_set_next_command(tcon, &rqst[0]);
+
+ /* Query */
+ if (qi.flags & PASSTHRU_FSCTL) {
+ /* Can eventually relax perm check since server enforces too */
+ if (!capable(CAP_SYS_ADMIN)) {
+ rc = -EPERM;
+ goto free_open_req;
+ }
+ rqst[1].rq_iov = &vars->io_iov[0];
+ rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
+
+ rc = SMB2_ioctl_init(tcon, server, &rqst[1], COMPOUND_FID, COMPOUND_FID,
+ qi.info_type, buffer, qi.output_buffer_length,
+ CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE -
+ MAX_SMB2_CLOSE_RESPONSE_SIZE);
+ free_req1_func = SMB2_ioctl_free;
+ } else if (qi.flags == PASSTHRU_SET_INFO) {
+ /* Can eventually relax perm check since server enforces too */
+ if (!capable(CAP_SYS_ADMIN)) {
+ rc = -EPERM;
+ goto free_open_req;
+ }
+ if (qi.output_buffer_length < 8) {
+ rc = -EINVAL;
+ goto free_open_req;
+ }
+ rqst[1].rq_iov = &vars->si_iov[0];
+ rqst[1].rq_nvec = 1;
+
+ /* MS-FSCC 2.4.13 FileEndOfFileInformation */
+ size[0] = 8;
+ data[0] = buffer;
+
+ rc = SMB2_set_info_init(tcon, server, &rqst[1], COMPOUND_FID, COMPOUND_FID,
+ current->tgid, FILE_END_OF_FILE_INFORMATION,
+ SMB2_O_INFO_FILE, 0, data, size);
+ free_req1_func = SMB2_set_info_free;
+ } else if (qi.flags == PASSTHRU_QUERY_INFO) {
+ rqst[1].rq_iov = &vars->qi_iov[0];
+ rqst[1].rq_nvec = 1;
+
+ rc = SMB2_query_info_init(tcon, server,
+ &rqst[1], COMPOUND_FID,
+ COMPOUND_FID, qi.file_info_class,
+ qi.info_type, qi.additional_information,
+ qi.input_buffer_length,
+ qi.output_buffer_length, buffer);
+ free_req1_func = SMB2_query_info_free;
+ } else { /* unknown flags */
+ cifs_tcon_dbg(VFS, "Invalid passthru query flags: 0x%x\n",
+ qi.flags);
+ rc = -EINVAL;
+ }
+
+ if (rc)
+ goto free_open_req;
+ smb2_set_next_command(tcon, &rqst[1]);
+ smb2_set_related(&rqst[1]);
+
+ /* Close */
+ rqst[2].rq_iov = &vars->close_iov[0];
+ rqst[2].rq_nvec = 1;
+
+ rc = SMB2_close_init(tcon, server,
+ &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
+ if (rc)
+ goto free_req_1;
+ smb2_set_related(&rqst[2]);
+
+ rc = compound_send_recv(xid, ses, server,
+ flags, 3, rqst,
+ resp_buftype, rsp_iov);
+ if (rc)
+ goto out;
+
+ /* No need to bump num_remote_opens since handle immediately closed */
+ if (qi.flags & PASSTHRU_FSCTL) {
+ pqi = (struct smb_query_info __user *)arg;
+ io_rsp = (struct smb2_ioctl_rsp *)rsp_iov[1].iov_base;
+ if (le32_to_cpu(io_rsp->OutputCount) < qi.input_buffer_length)
+ qi.input_buffer_length = le32_to_cpu(io_rsp->OutputCount);
+ if (qi.input_buffer_length > 0 &&
+ le32_to_cpu(io_rsp->OutputOffset) + qi.input_buffer_length
+ > rsp_iov[1].iov_len) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ if (copy_to_user(&pqi->input_buffer_length,
+ &qi.input_buffer_length,
+ sizeof(qi.input_buffer_length))) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ if (copy_to_user((void __user *)pqi + sizeof(struct smb_query_info),
+ (const void *)io_rsp + le32_to_cpu(io_rsp->OutputOffset),
+ qi.input_buffer_length))
+ rc = -EFAULT;
+ } else {
+ pqi = (struct smb_query_info __user *)arg;
+ qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
+ if (le32_to_cpu(qi_rsp->OutputBufferLength) < qi.input_buffer_length)
+ qi.input_buffer_length = le32_to_cpu(qi_rsp->OutputBufferLength);
+ if (copy_to_user(&pqi->input_buffer_length,
+ &qi.input_buffer_length,
+ sizeof(qi.input_buffer_length))) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ if (copy_to_user(pqi + 1, qi_rsp->Buffer,
+ qi.input_buffer_length))
+ rc = -EFAULT;
+ }
+
+out:
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+ SMB2_close_free(&rqst[2]);
+free_req_1:
+ free_req1_func(&rqst[1]);
+free_open_req:
+ SMB2_open_free(&rqst[0]);
+free_output_buffer:
+ kfree(buffer);
+free_vars:
+ kfree(vars);
+ return rc;
+}
+
+static ssize_t
+smb2_copychunk_range(const unsigned int xid,
+ struct cifsFileInfo *srcfile,
+ struct cifsFileInfo *trgtfile, u64 src_off,
+ u64 len, u64 dest_off)
+{
+ int rc;
+ unsigned int ret_data_len;
+ struct copychunk_ioctl *pcchunk;
+ struct copychunk_ioctl_rsp *retbuf = NULL;
+ struct cifs_tcon *tcon;
+ int chunks_copied = 0;
+ bool chunk_sizes_updated = false;
+ ssize_t bytes_written, total_bytes_written = 0;
+
+ pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);
+ if (pcchunk == NULL)
+ return -ENOMEM;
+
+ cifs_dbg(FYI, "%s: about to call request res key\n", __func__);
+ /* Request a key from the server to identify the source of the copy */
+ rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink),
+ srcfile->fid.persistent_fid,
+ srcfile->fid.volatile_fid, pcchunk);
+
+ /* Note: request_res_key sets res_key null only if rc !=0 */
+ if (rc)
+ goto cchunk_out;
+
+ /* For now array only one chunk long, will make more flexible later */
+ pcchunk->ChunkCount = cpu_to_le32(1);
+ pcchunk->Reserved = 0;
+ pcchunk->Reserved2 = 0;
+
+ tcon = tlink_tcon(trgtfile->tlink);
+
+ while (len > 0) {
+ pcchunk->SourceOffset = cpu_to_le64(src_off);
+ pcchunk->TargetOffset = cpu_to_le64(dest_off);
+ pcchunk->Length =
+ cpu_to_le32(min_t(u64, len, tcon->max_bytes_chunk));
+
+ /* Request server copy to target from src identified by key */
+ kfree(retbuf);
+ retbuf = NULL;
+ rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
+ trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
+ (char *)pcchunk, sizeof(struct copychunk_ioctl),
+ CIFSMaxBufSize, (char **)&retbuf, &ret_data_len);
+ if (rc == 0) {
+ if (ret_data_len !=
+ sizeof(struct copychunk_ioctl_rsp)) {
+ cifs_tcon_dbg(VFS, "Invalid cchunk response size\n");
+ rc = -EIO;
+ goto cchunk_out;
+ }
+ if (retbuf->TotalBytesWritten == 0) {
+ cifs_dbg(FYI, "no bytes copied\n");
+ rc = -EIO;
+ goto cchunk_out;
+ }
+ /*
+ * Check if server claimed to write more than we asked
+ */
+ if (le32_to_cpu(retbuf->TotalBytesWritten) >
+ le32_to_cpu(pcchunk->Length)) {
+ cifs_tcon_dbg(VFS, "Invalid copy chunk response\n");
+ rc = -EIO;
+ goto cchunk_out;
+ }
+ if (le32_to_cpu(retbuf->ChunksWritten) != 1) {
+ cifs_tcon_dbg(VFS, "Invalid num chunks written\n");
+ rc = -EIO;
+ goto cchunk_out;
+ }
+ chunks_copied++;
+
+ bytes_written = le32_to_cpu(retbuf->TotalBytesWritten);
+ src_off += bytes_written;
+ dest_off += bytes_written;
+ len -= bytes_written;
+ total_bytes_written += bytes_written;
+
+ cifs_dbg(FYI, "Chunks %d PartialChunk %d Total %zu\n",
+ le32_to_cpu(retbuf->ChunksWritten),
+ le32_to_cpu(retbuf->ChunkBytesWritten),
+ bytes_written);
+ } else if (rc == -EINVAL) {
+ if (ret_data_len != sizeof(struct copychunk_ioctl_rsp))
+ goto cchunk_out;
+
+ cifs_dbg(FYI, "MaxChunks %d BytesChunk %d MaxCopy %d\n",
+ le32_to_cpu(retbuf->ChunksWritten),
+ le32_to_cpu(retbuf->ChunkBytesWritten),
+ le32_to_cpu(retbuf->TotalBytesWritten));
+
+ /*
+ * Check if this is the first request using these sizes,
+ * (ie check if copy succeed once with original sizes
+ * and check if the server gave us different sizes after
+ * we already updated max sizes on previous request).
+ * if not then why is the server returning an error now
+ */
+ if ((chunks_copied != 0) || chunk_sizes_updated)
+ goto cchunk_out;
+
+ /* Check that server is not asking us to grow size */
+ if (le32_to_cpu(retbuf->ChunkBytesWritten) <
+ tcon->max_bytes_chunk)
+ tcon->max_bytes_chunk =
+ le32_to_cpu(retbuf->ChunkBytesWritten);
+ else
+ goto cchunk_out; /* server gave us bogus size */
+
+ /* No need to change MaxChunks since already set to 1 */
+ chunk_sizes_updated = true;
+ } else
+ goto cchunk_out;
+ }
+
+cchunk_out:
+ kfree(pcchunk);
+ kfree(retbuf);
+ if (rc)
+ return rc;
+ else
+ return total_bytes_written;
+}
+
+static int
+smb2_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid)
+{
+ return SMB2_flush(xid, tcon, fid->persistent_fid, fid->volatile_fid);
+}
+
+static unsigned int
+smb2_read_data_offset(char *buf)
+{
+ struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
+
+ return rsp->DataOffset;
+}
+
+static unsigned int
+smb2_read_data_length(char *buf, bool in_remaining)
+{
+ struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
+
+ if (in_remaining)
+ return le32_to_cpu(rsp->DataRemaining);
+
+ return le32_to_cpu(rsp->DataLength);
+}
+
+
+static int
+smb2_sync_read(const unsigned int xid, struct cifs_fid *pfid,
+ struct cifs_io_parms *parms, unsigned int *bytes_read,
+ char **buf, int *buf_type)
+{
+ parms->persistent_fid = pfid->persistent_fid;
+ parms->volatile_fid = pfid->volatile_fid;
+ return SMB2_read(xid, parms, bytes_read, buf, buf_type);
+}
+
+static int
+smb2_sync_write(const unsigned int xid, struct cifs_fid *pfid,
+ struct cifs_io_parms *parms, unsigned int *written,
+ struct kvec *iov, unsigned long nr_segs)
+{
+
+ parms->persistent_fid = pfid->persistent_fid;
+ parms->volatile_fid = pfid->volatile_fid;
+ return SMB2_write(xid, parms, written, iov, nr_segs);
+}
+
+/* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */
+static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse)
+{
+ struct cifsInodeInfo *cifsi;
+ int rc;
+
+ cifsi = CIFS_I(inode);
+
+ /* if file already sparse don't bother setting sparse again */
+ if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && setsparse)
+ return true; /* already sparse */
+
+ if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && !setsparse)
+ return true; /* already not sparse */
+
+ /*
+ * Can't check for sparse support on share the usual way via the
+ * FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share
+ * since Samba server doesn't set the flag on the share, yet
+ * supports the set sparse FSCTL and returns sparse correctly
+ * in the file attributes. If we fail setting sparse though we
+ * mark that server does not support sparse files for this share
+ * to avoid repeatedly sending the unsupported fsctl to server
+ * if the file is repeatedly extended.
+ */
+ if (tcon->broken_sparse_sup)
+ return false;
+
+ rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
+ &setsparse, 1, CIFSMaxBufSize, NULL, NULL);
+ if (rc) {
+ tcon->broken_sparse_sup = true;
+ cifs_dbg(FYI, "set sparse rc = %d\n", rc);
+ return false;
+ }
+
+ if (setsparse)
+ cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE;
+ else
+ cifsi->cifsAttrs &= (~FILE_ATTRIBUTE_SPARSE_FILE);
+
+ return true;
+}
+
+static int
+smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, __u64 size, bool set_alloc)
+{
+ __le64 eof = cpu_to_le64(size);
+ struct inode *inode;
+
+ /*
+ * If extending file more than one page make sparse. Many Linux fs
+ * make files sparse by default when extending via ftruncate
+ */
+ inode = d_inode(cfile->dentry);
+
+ if (!set_alloc && (size > inode->i_size + 8192)) {
+ __u8 set_sparse = 1;
+
+ /* whether set sparse succeeds or not, extend the file */
+ smb2_set_sparse(xid, tcon, cfile, inode, set_sparse);
+ }
+
+ return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, cfile->pid, &eof);
+}
+
+static int
+smb2_duplicate_extents(const unsigned int xid,
+ struct cifsFileInfo *srcfile,
+ struct cifsFileInfo *trgtfile, u64 src_off,
+ u64 len, u64 dest_off)
+{
+ int rc;
+ unsigned int ret_data_len;
+ struct inode *inode;
+ struct duplicate_extents_to_file dup_ext_buf;
+ struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
+
+ /* server fileays advertise duplicate extent support with this flag */
+ if ((le32_to_cpu(tcon->fsAttrInfo.Attributes) &
+ FILE_SUPPORTS_BLOCK_REFCOUNTING) == 0)
+ return -EOPNOTSUPP;
+
+ dup_ext_buf.VolatileFileHandle = srcfile->fid.volatile_fid;
+ dup_ext_buf.PersistentFileHandle = srcfile->fid.persistent_fid;
+ dup_ext_buf.SourceFileOffset = cpu_to_le64(src_off);
+ dup_ext_buf.TargetFileOffset = cpu_to_le64(dest_off);
+ dup_ext_buf.ByteCount = cpu_to_le64(len);
+ cifs_dbg(FYI, "Duplicate extents: src off %lld dst off %lld len %lld\n",
+ src_off, dest_off, len);
+
+ inode = d_inode(trgtfile->dentry);
+ if (inode->i_size < dest_off + len) {
+ rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
+ if (rc)
+ goto duplicate_extents_out;
+
+ /*
+ * Although also could set plausible allocation size (i_blocks)
+ * here in addition to setting the file size, in reflink
+ * it is likely that the target file is sparse. Its allocation
+ * size will be queried on next revalidate, but it is important
+ * to make sure that file's cached size is updated immediately
+ */
+ cifs_setsize(inode, dest_off + len);
+ }
+ rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
+ trgtfile->fid.volatile_fid,
+ FSCTL_DUPLICATE_EXTENTS_TO_FILE,
+ (char *)&dup_ext_buf,
+ sizeof(struct duplicate_extents_to_file),
+ CIFSMaxBufSize, NULL,
+ &ret_data_len);
+
+ if (ret_data_len > 0)
+ cifs_dbg(FYI, "Non-zero response length in duplicate extents\n");
+
+duplicate_extents_out:
+ return rc;
+}
+
+static int
+smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile)
+{
+ return SMB2_set_compression(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid);
+}
+
+static int
+smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile)
+{
+ struct fsctl_set_integrity_information_req integr_info;
+ unsigned int ret_data_len;
+
+ integr_info.ChecksumAlgorithm = cpu_to_le16(CHECKSUM_TYPE_UNCHANGED);
+ integr_info.Flags = 0;
+ integr_info.Reserved = 0;
+
+ return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ FSCTL_SET_INTEGRITY_INFORMATION,
+ (char *)&integr_info,
+ sizeof(struct fsctl_set_integrity_information_req),
+ CIFSMaxBufSize, NULL,
+ &ret_data_len);
+
+}
+
+/* GMT Token is @GMT-YYYY.MM.DD-HH.MM.SS Unicode which is 48 bytes + null */
+#define GMT_TOKEN_SIZE 50
+
+#define MIN_SNAPSHOT_ARRAY_SIZE 16 /* See MS-SMB2 section 3.3.5.15.1 */
+
+/*
+ * Input buffer contains (empty) struct smb_snapshot array with size filled in
+ * For output see struct SRV_SNAPSHOT_ARRAY in MS-SMB2 section 2.2.32.2
+ */
+static int
+smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, void __user *ioc_buf)
+{
+ char *retbuf = NULL;
+ unsigned int ret_data_len = 0;
+ int rc;
+ u32 max_response_size;
+ struct smb_snapshot_array snapshot_in;
+
+ /*
+ * On the first query to enumerate the list of snapshots available
+ * for this volume the buffer begins with 0 (number of snapshots
+ * which can be returned is zero since at that point we do not know
+ * how big the buffer needs to be). On the second query,
+ * it (ret_data_len) is set to number of snapshots so we can
+ * know to set the maximum response size larger (see below).
+ */
+ if (get_user(ret_data_len, (unsigned int __user *)ioc_buf))
+ return -EFAULT;
+
+ /*
+ * Note that for snapshot queries that servers like Azure expect that
+ * the first query be minimal size (and just used to get the number/size
+ * of previous versions) so response size must be specified as EXACTLY
+ * sizeof(struct snapshot_array) which is 16 when rounded up to multiple
+ * of eight bytes.
+ */
+ if (ret_data_len == 0)
+ max_response_size = MIN_SNAPSHOT_ARRAY_SIZE;
+ else
+ max_response_size = CIFSMaxBufSize;
+
+ rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ FSCTL_SRV_ENUMERATE_SNAPSHOTS,
+ NULL, 0 /* no input data */, max_response_size,
+ (char **)&retbuf,
+ &ret_data_len);
+ cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
+ rc, ret_data_len);
+ if (rc)
+ return rc;
+
+ if (ret_data_len && (ioc_buf != NULL) && (retbuf != NULL)) {
+ /* Fixup buffer */
+ if (copy_from_user(&snapshot_in, ioc_buf,
+ sizeof(struct smb_snapshot_array))) {
+ rc = -EFAULT;
+ kfree(retbuf);
+ return rc;
+ }
+
+ /*
+ * Check for min size, ie not large enough to fit even one GMT
+ * token (snapshot). On the first ioctl some users may pass in
+ * smaller size (or zero) to simply get the size of the array
+ * so the user space caller can allocate sufficient memory
+ * and retry the ioctl again with larger array size sufficient
+ * to hold all of the snapshot GMT tokens on the second try.
+ */
+ if (snapshot_in.snapshot_array_size < GMT_TOKEN_SIZE)
+ ret_data_len = sizeof(struct smb_snapshot_array);
+
+ /*
+ * We return struct SRV_SNAPSHOT_ARRAY, followed by
+ * the snapshot array (of 50 byte GMT tokens) each
+ * representing an available previous version of the data
+ */
+ if (ret_data_len > (snapshot_in.snapshot_array_size +
+ sizeof(struct smb_snapshot_array)))
+ ret_data_len = snapshot_in.snapshot_array_size +
+ sizeof(struct smb_snapshot_array);
+
+ if (copy_to_user(ioc_buf, retbuf, ret_data_len))
+ rc = -EFAULT;
+ }
+
+ kfree(retbuf);
+ return rc;
+}
+
+
+
+static int
+smb3_notify(const unsigned int xid, struct file *pfile,
+ void __user *ioc_buf, bool return_changes)
+{
+ struct smb3_notify_info notify;
+ struct smb3_notify_info __user *pnotify_buf;
+ struct dentry *dentry = pfile->f_path.dentry;
+ struct inode *inode = file_inode(pfile);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifs_open_parms oparms;
+ struct cifs_fid fid;
+ struct cifs_tcon *tcon;
+ const unsigned char *path;
+ char *returned_ioctl_info = NULL;
+ void *page = alloc_dentry_path();
+ __le16 *utf16_path = NULL;
+ u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ int rc = 0;
+ __u32 ret_len = 0;
+
+ path = build_path_from_dentry(dentry, page);
+ if (IS_ERR(path)) {
+ rc = PTR_ERR(path);
+ goto notify_exit;
+ }
+
+ utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+ if (utf16_path == NULL) {
+ rc = -ENOMEM;
+ goto notify_exit;
+ }
+
+ if (return_changes) {
+ if (copy_from_user(¬ify, ioc_buf, sizeof(struct smb3_notify_info))) {
+ rc = -EFAULT;
+ goto notify_exit;
+ }
+ } else {
+ if (copy_from_user(¬ify, ioc_buf, sizeof(struct smb3_notify))) {
+ rc = -EFAULT;
+ goto notify_exit;
+ }
+ notify.data_len = 0;
+ }
+
+ tcon = cifs_sb_master_tcon(cifs_sb);
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = path,
+ .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .fid = &fid,
+ };
+
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL,
+ NULL);
+ if (rc)
+ goto notify_exit;
+
+ rc = SMB2_change_notify(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ notify.watch_tree, notify.completion_filter,
+ notify.data_len, &returned_ioctl_info, &ret_len);
+
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+
+ cifs_dbg(FYI, "change notify for path %s rc %d\n", path, rc);
+ if (return_changes && (ret_len > 0) && (notify.data_len > 0)) {
+ if (ret_len > notify.data_len)
+ ret_len = notify.data_len;
+ pnotify_buf = (struct smb3_notify_info __user *)ioc_buf;
+ if (copy_to_user(pnotify_buf->notify_data, returned_ioctl_info, ret_len))
+ rc = -EFAULT;
+ else if (copy_to_user(&pnotify_buf->data_len, &ret_len, sizeof(ret_len)))
+ rc = -EFAULT;
+ }
+ kfree(returned_ioctl_info);
+notify_exit:
+ free_dentry_path(page);
+ kfree(utf16_path);
+ return rc;
+}
+
+static int
+smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *path, struct cifs_sb_info *cifs_sb,
+ struct cifs_fid *fid, __u16 search_flags,
+ struct cifs_search_info *srch_inf)
+{
+ __le16 *utf16_path;
+ struct smb_rqst rqst[2];
+ struct kvec rsp_iov[2];
+ int resp_buftype[2];
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+ struct kvec qd_iov[SMB2_QUERY_DIRECTORY_IOV_SIZE];
+ int rc, flags = 0;
+ u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_open_parms oparms;
+ struct smb2_query_directory_rsp *qd_rsp = NULL;
+ struct smb2_create_rsp *op_rsp = NULL;
+ struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
+ int retry_count = 0;
+
+ utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(rqst, 0, sizeof(rqst));
+ resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER;
+ memset(rsp_iov, 0, sizeof(rsp_iov));
+
+ /* Open */
+ memset(&open_iov, 0, sizeof(open_iov));
+ rqst[0].rq_iov = open_iov;
+ rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = path,
+ .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .fid = fid,
+ };
+
+ rc = SMB2_open_init(tcon, server,
+ &rqst[0], &oplock, &oparms, utf16_path);
+ if (rc)
+ goto qdf_free;
+ smb2_set_next_command(tcon, &rqst[0]);
+
+ /* Query directory */
+ srch_inf->entries_in_buffer = 0;
+ srch_inf->index_of_last_entry = 2;
+
+ memset(&qd_iov, 0, sizeof(qd_iov));
+ rqst[1].rq_iov = qd_iov;
+ rqst[1].rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE;
+
+ rc = SMB2_query_directory_init(xid, tcon, server,
+ &rqst[1],
+ COMPOUND_FID, COMPOUND_FID,
+ 0, srch_inf->info_level);
+ if (rc)
+ goto qdf_free;
+
+ smb2_set_related(&rqst[1]);
+
+again:
+ rc = compound_send_recv(xid, tcon->ses, server,
+ flags, 2, rqst,
+ resp_buftype, rsp_iov);
+
+ if (rc == -EAGAIN && retry_count++ < 10)
+ goto again;
+
+ /* If the open failed there is nothing to do */
+ op_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
+ if (op_rsp == NULL || op_rsp->hdr.Status != STATUS_SUCCESS) {
+ cifs_dbg(FYI, "query_dir_first: open failed rc=%d\n", rc);
+ goto qdf_free;
+ }
+ fid->persistent_fid = op_rsp->PersistentFileId;
+ fid->volatile_fid = op_rsp->VolatileFileId;
+
+ /* Anything else than ENODATA means a genuine error */
+ if (rc && rc != -ENODATA) {
+ SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
+ cifs_dbg(FYI, "query_dir_first: query directory failed rc=%d\n", rc);
+ trace_smb3_query_dir_err(xid, fid->persistent_fid,
+ tcon->tid, tcon->ses->Suid, 0, 0, rc);
+ goto qdf_free;
+ }
+
+ atomic_inc(&tcon->num_remote_opens);
+
+ qd_rsp = (struct smb2_query_directory_rsp *)rsp_iov[1].iov_base;
+ if (qd_rsp->hdr.Status == STATUS_NO_MORE_FILES) {
+ trace_smb3_query_dir_done(xid, fid->persistent_fid,
+ tcon->tid, tcon->ses->Suid, 0, 0);
+ srch_inf->endOfSearch = true;
+ rc = 0;
+ goto qdf_free;
+ }
+
+ rc = smb2_parse_query_directory(tcon, &rsp_iov[1], resp_buftype[1],
+ srch_inf);
+ if (rc) {
+ trace_smb3_query_dir_err(xid, fid->persistent_fid, tcon->tid,
+ tcon->ses->Suid, 0, 0, rc);
+ goto qdf_free;
+ }
+ resp_buftype[1] = CIFS_NO_BUFFER;
+
+ trace_smb3_query_dir_done(xid, fid->persistent_fid, tcon->tid,
+ tcon->ses->Suid, 0, srch_inf->entries_in_buffer);
+
+ qdf_free:
+ kfree(utf16_path);
+ SMB2_open_free(&rqst[0]);
+ SMB2_query_directory_free(&rqst[1]);
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ return rc;
+}
+
+static int
+smb2_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid, __u16 search_flags,
+ struct cifs_search_info *srch_inf)
+{
+ return SMB2_query_directory(xid, tcon, fid->persistent_fid,
+ fid->volatile_fid, 0, srch_inf);
+}
+
+static int
+smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid)
+{
+ return SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
+}
+
+/*
+ * If we negotiate SMB2 protocol and get STATUS_PENDING - update
+ * the number of credits and return true. Otherwise - return false.
+ */
+static bool
+smb2_is_status_pending(char *buf, struct TCP_Server_Info *server)
+{
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+ int scredits, in_flight;
+
+ if (shdr->Status != STATUS_PENDING)
+ return false;
+
+ if (shdr->CreditRequest) {
+ spin_lock(&server->req_lock);
+ server->credits += le16_to_cpu(shdr->CreditRequest);
+ scredits = server->credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+ wake_up(&server->request_q);
+
+ trace_smb3_pend_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits,
+ le16_to_cpu(shdr->CreditRequest), in_flight);
+ cifs_dbg(FYI, "%s: status pending add %u credits total=%d\n",
+ __func__, le16_to_cpu(shdr->CreditRequest), scredits);
+ }
+
+ return true;
+}
+
+static bool
+smb2_is_session_expired(char *buf)
+{
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+
+ if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED &&
+ shdr->Status != STATUS_USER_SESSION_DELETED)
+ return false;
+
+ trace_smb3_ses_expired(le32_to_cpu(shdr->Id.SyncId.TreeId),
+ le64_to_cpu(shdr->SessionId),
+ le16_to_cpu(shdr->Command),
+ le64_to_cpu(shdr->MessageId));
+ cifs_dbg(FYI, "Session expired or deleted\n");
+
+ return true;
+}
+
+static bool
+smb2_is_status_io_timeout(char *buf)
+{
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+
+ if (shdr->Status == STATUS_IO_TIMEOUT)
+ return true;
+ else
+ return false;
+}
+
+static void
+smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
+{
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+
+ if (shdr->Status != STATUS_NETWORK_NAME_DELETED)
+ return;
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ if (tcon->tid == le32_to_cpu(shdr->Id.SyncId.TreeId)) {
+ spin_lock(&tcon->tc_lock);
+ tcon->need_reconnect = true;
+ spin_unlock(&tcon->tc_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ pr_warn_once("Server share %s deleted.\n",
+ tcon->tree_name);
+ return;
+ }
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+}
+
+static int
+smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
+ __u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode)
+{
+ if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
+ return SMB2_lease_break(0, tcon, cinode->lease_key,
+ smb2_get_lease_state(cinode));
+
+ return SMB2_oplock_break(0, tcon, persistent_fid, volatile_fid,
+ CIFS_CACHE_READ(cinode) ? 1 : 0);
+}
+
+void
+smb2_set_related(struct smb_rqst *rqst)
+{
+ struct smb2_hdr *shdr;
+
+ shdr = (struct smb2_hdr *)(rqst->rq_iov[0].iov_base);
+ if (shdr == NULL) {
+ cifs_dbg(FYI, "shdr NULL in smb2_set_related\n");
+ return;
+ }
+ shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
+}
+
+char smb2_padding[7] = {0, 0, 0, 0, 0, 0, 0};
+
+void
+smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst)
+{
+ struct smb2_hdr *shdr;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = ses->server;
+ unsigned long len = smb_rqst_len(server, rqst);
+ int i, num_padding;
+
+ shdr = (struct smb2_hdr *)(rqst->rq_iov[0].iov_base);
+ if (shdr == NULL) {
+ cifs_dbg(FYI, "shdr NULL in smb2_set_next_command\n");
+ return;
+ }
+
+ /* SMB headers in a compound are 8 byte aligned. */
+
+ /* No padding needed */
+ if (!(len & 7))
+ goto finished;
+
+ num_padding = 8 - (len & 7);
+ if (!smb3_encryption_required(tcon)) {
+ /*
+ * If we do not have encryption then we can just add an extra
+ * iov for the padding.
+ */
+ rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding;
+ rqst->rq_iov[rqst->rq_nvec].iov_len = num_padding;
+ rqst->rq_nvec++;
+ len += num_padding;
+ } else {
+ /*
+ * We can not add a small padding iov for the encryption case
+ * because the encryption framework can not handle the padding
+ * iovs.
+ * We have to flatten this into a single buffer and add
+ * the padding to it.
+ */
+ for (i = 1; i < rqst->rq_nvec; i++) {
+ memcpy(rqst->rq_iov[0].iov_base +
+ rqst->rq_iov[0].iov_len,
+ rqst->rq_iov[i].iov_base,
+ rqst->rq_iov[i].iov_len);
+ rqst->rq_iov[0].iov_len += rqst->rq_iov[i].iov_len;
+ }
+ memset(rqst->rq_iov[0].iov_base + rqst->rq_iov[0].iov_len,
+ 0, num_padding);
+ rqst->rq_iov[0].iov_len += num_padding;
+ len += num_padding;
+ rqst->rq_nvec = 1;
+ }
+
+ finished:
+ shdr->NextCommand = cpu_to_le32(len);
+}
+
+/*
+ * Passes the query info response back to the caller on success.
+ * Caller need to free this with free_rsp_buf().
+ */
+int
+smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *path, u32 desired_access,
+ u32 class, u32 type, u32 output_len,
+ struct kvec *rsp, int *buftype,
+ struct cifs_sb_info *cifs_sb)
+{
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ int flags = CIFS_CP_CREATE_CLOSE_OP;
+ struct smb_rqst rqst[3];
+ int resp_buftype[3];
+ struct kvec rsp_iov[3];
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+ struct kvec qi_iov[1];
+ struct kvec close_iov[1];
+ u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_open_parms oparms;
+ struct cifs_fid fid;
+ int rc;
+ __le16 *utf16_path;
+ struct cached_fid *cfid = NULL;
+
+ if (!path)
+ path = "";
+ utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(rqst, 0, sizeof(rqst));
+ resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
+ memset(rsp_iov, 0, sizeof(rsp_iov));
+
+ /*
+ * We can only call this for things we know are directories.
+ */
+ if (!strcmp(path, ""))
+ open_cached_dir(xid, tcon, path, cifs_sb, false,
+ &cfid); /* cfid null if open dir failed */
+
+ memset(&open_iov, 0, sizeof(open_iov));
+ rqst[0].rq_iov = open_iov;
+ rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = path,
+ .desired_access = desired_access,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .fid = &fid,
+ };
+
+ rc = SMB2_open_init(tcon, server,
+ &rqst[0], &oplock, &oparms, utf16_path);
+ if (rc)
+ goto qic_exit;
+ smb2_set_next_command(tcon, &rqst[0]);
+
+ memset(&qi_iov, 0, sizeof(qi_iov));
+ rqst[1].rq_iov = qi_iov;
+ rqst[1].rq_nvec = 1;
+
+ if (cfid) {
+ rc = SMB2_query_info_init(tcon, server,
+ &rqst[1],
+ cfid->fid.persistent_fid,
+ cfid->fid.volatile_fid,
+ class, type, 0,
+ output_len, 0,
+ NULL);
+ } else {
+ rc = SMB2_query_info_init(tcon, server,
+ &rqst[1],
+ COMPOUND_FID,
+ COMPOUND_FID,
+ class, type, 0,
+ output_len, 0,
+ NULL);
+ }
+ if (rc)
+ goto qic_exit;
+ if (!cfid) {
+ smb2_set_next_command(tcon, &rqst[1]);
+ smb2_set_related(&rqst[1]);
+ }
+
+ memset(&close_iov, 0, sizeof(close_iov));
+ rqst[2].rq_iov = close_iov;
+ rqst[2].rq_nvec = 1;
+
+ rc = SMB2_close_init(tcon, server,
+ &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
+ if (rc)
+ goto qic_exit;
+ smb2_set_related(&rqst[2]);
+
+ if (cfid) {
+ rc = compound_send_recv(xid, ses, server,
+ flags, 1, &rqst[1],
+ &resp_buftype[1], &rsp_iov[1]);
+ } else {
+ rc = compound_send_recv(xid, ses, server,
+ flags, 3, rqst,
+ resp_buftype, rsp_iov);
+ }
+ if (rc) {
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ if (rc == -EREMCHG) {
+ tcon->need_reconnect = true;
+ pr_warn_once("server share %s deleted\n",
+ tcon->tree_name);
+ }
+ goto qic_exit;
+ }
+ *rsp = rsp_iov[1];
+ *buftype = resp_buftype[1];
+
+ qic_exit:
+ kfree(utf16_path);
+ SMB2_open_free(&rqst[0]);
+ SMB2_query_info_free(&rqst[1]);
+ SMB2_close_free(&rqst[2]);
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+ if (cfid)
+ close_cached_dir(cfid);
+ return rc;
+}
+
+static int
+smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
+{
+ struct smb2_query_info_rsp *rsp;
+ struct smb2_fs_full_size_info *info = NULL;
+ struct kvec rsp_iov = {NULL, 0};
+ int buftype = CIFS_NO_BUFFER;
+ int rc;
+
+
+ rc = smb2_query_info_compound(xid, tcon, "",
+ FILE_READ_ATTRIBUTES,
+ FS_FULL_SIZE_INFORMATION,
+ SMB2_O_INFO_FILESYSTEM,
+ sizeof(struct smb2_fs_full_size_info),
+ &rsp_iov, &buftype, cifs_sb);
+ if (rc)
+ goto qfs_exit;
+
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
+ buf->f_type = SMB2_SUPER_MAGIC;
+ info = (struct smb2_fs_full_size_info *)(
+ le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
+ rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
+ le32_to_cpu(rsp->OutputBufferLength),
+ &rsp_iov,
+ sizeof(struct smb2_fs_full_size_info));
+ if (!rc)
+ smb2_copy_fs_info_to_kstatfs(info, buf);
+
+qfs_exit:
+ free_rsp_buf(buftype, rsp_iov.iov_base);
+ return rc;
+}
+
+static int
+smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
+{
+ int rc;
+ __le16 srch_path = 0; /* Null - open root of share */
+ u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_open_parms oparms;
+ struct cifs_fid fid;
+
+ if (!tcon->posix_extensions)
+ return smb2_queryfs(xid, tcon, cifs_sb, buf);
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = "",
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .fid = &fid,
+ };
+
+ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
+ NULL, NULL);
+ if (rc)
+ return rc;
+
+ rc = SMB311_posix_qfs_info(xid, tcon, fid.persistent_fid,
+ fid.volatile_fid, buf);
+ buf->f_type = SMB2_SUPER_MAGIC;
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ return rc;
+}
+
+static bool
+smb2_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
+{
+ return ob1->fid.persistent_fid == ob2->fid.persistent_fid &&
+ ob1->fid.volatile_fid == ob2->fid.volatile_fid;
+}
+
+static int
+smb2_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
+ __u64 length, __u32 type, int lock, int unlock, bool wait)
+{
+ if (unlock && !lock)
+ type = SMB2_LOCKFLAG_UNLOCK;
+ return SMB2_lock(xid, tlink_tcon(cfile->tlink),
+ cfile->fid.persistent_fid, cfile->fid.volatile_fid,
+ current->tgid, length, offset, type, wait);
+}
+
+static void
+smb2_get_lease_key(struct inode *inode, struct cifs_fid *fid)
+{
+ memcpy(fid->lease_key, CIFS_I(inode)->lease_key, SMB2_LEASE_KEY_SIZE);
+}
+
+static void
+smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
+{
+ memcpy(CIFS_I(inode)->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
+}
+
+static void
+smb2_new_lease_key(struct cifs_fid *fid)
+{
+ generate_random_uuid(fid->lease_key);
+}
+
+static int
+smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
+ const char *search_name,
+ struct dfs_info3_param **target_nodes,
+ unsigned int *num_of_nodes,
+ const struct nls_table *nls_codepage, int remap)
+{
+ int rc;
+ __le16 *utf16_path = NULL;
+ int utf16_path_len = 0;
+ struct cifs_tcon *tcon;
+ struct fsctl_get_dfs_referral_req *dfs_req = NULL;
+ struct get_dfs_referral_rsp *dfs_rsp = NULL;
+ u32 dfs_req_size = 0, dfs_rsp_size = 0;
+ int retry_count = 0;
+
+ cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name);
+
+ /*
+ * Try to use the IPC tcon, otherwise just use any
+ */
+ tcon = ses->tcon_ipc;
+ if (tcon == NULL) {
+ spin_lock(&cifs_tcp_ses_lock);
+ tcon = list_first_entry_or_null(&ses->tcon_list,
+ struct cifs_tcon,
+ tcon_list);
+ if (tcon)
+ tcon->tc_count++;
+ spin_unlock(&cifs_tcp_ses_lock);
+ }
+
+ if (tcon == NULL) {
+ cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
+ ses);
+ rc = -ENOTCONN;
+ goto out;
+ }
+
+ utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
+ &utf16_path_len,
+ nls_codepage, remap);
+ if (!utf16_path) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
+ dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
+ if (!dfs_req) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Highest DFS referral version understood */
+ dfs_req->MaxReferralLevel = DFS_VERSION;
+
+ /* Path to resolve in an UTF-16 null-terminated string */
+ memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
+
+ do {
+ rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
+ FSCTL_DFS_GET_REFERRALS,
+ (char *)dfs_req, dfs_req_size, CIFSMaxBufSize,
+ (char **)&dfs_rsp, &dfs_rsp_size);
+ if (!is_retryable_error(rc))
+ break;
+ usleep_range(512, 2048);
+ } while (++retry_count < 5);
+
+ if (rc) {
+ if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP)
+ cifs_tcon_dbg(VFS, "%s: ioctl error: rc=%d\n", __func__, rc);
+ goto out;
+ }
+
+ rc = parse_dfs_referrals(dfs_rsp, dfs_rsp_size,
+ num_of_nodes, target_nodes,
+ nls_codepage, remap, search_name,
+ true /* is_unicode */);
+ if (rc) {
+ cifs_tcon_dbg(VFS, "parse error in %s rc=%d\n", __func__, rc);
+ goto out;
+ }
+
+ out:
+ if (tcon && !tcon->ipc) {
+ /* ipc tcons are not refcounted */
+ spin_lock(&cifs_tcp_ses_lock);
+ tcon->tc_count--;
+ /* tc_count can never go negative */
+ WARN_ON(tcon->tc_count < 0);
+ spin_unlock(&cifs_tcp_ses_lock);
+ }
+ kfree(utf16_path);
+ kfree(dfs_req);
+ kfree(dfs_rsp);
+ return rc;
+}
+
+static int
+parse_reparse_posix(struct reparse_posix_data *symlink_buf,
+ u32 plen, char **target_path,
+ struct cifs_sb_info *cifs_sb)
+{
+ unsigned int len;
+
+ /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */
+ len = le16_to_cpu(symlink_buf->ReparseDataLength);
+
+ if (le64_to_cpu(symlink_buf->InodeType) != NFS_SPECFILE_LNK) {
+ cifs_dbg(VFS, "%lld not a supported symlink type\n",
+ le64_to_cpu(symlink_buf->InodeType));
+ return -EOPNOTSUPP;
+ }
+
+ *target_path = cifs_strndup_from_utf16(
+ symlink_buf->PathBuffer,
+ len, true, cifs_sb->local_nls);
+ if (!(*target_path))
+ return -ENOMEM;
+
+ convert_delimiter(*target_path, '/');
+ cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+
+ return 0;
+}
+
+static int
+parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
+ u32 plen, char **target_path,
+ struct cifs_sb_info *cifs_sb)
+{
+ unsigned int sub_len;
+ unsigned int sub_offset;
+
+ /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */
+
+ sub_offset = le16_to_cpu(symlink_buf->SubstituteNameOffset);
+ sub_len = le16_to_cpu(symlink_buf->SubstituteNameLength);
+ if (sub_offset + 20 > plen ||
+ sub_offset + sub_len + 20 > plen) {
+ cifs_dbg(VFS, "srv returned malformed symlink buffer\n");
+ return -EIO;
+ }
+
+ *target_path = cifs_strndup_from_utf16(
+ symlink_buf->PathBuffer + sub_offset,
+ sub_len, true, cifs_sb->local_nls);
+ if (!(*target_path))
+ return -ENOMEM;
+
+ convert_delimiter(*target_path, '/');
+ cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+
+ return 0;
+}
+
+static int
+parse_reparse_point(struct reparse_data_buffer *buf,
+ u32 plen, char **target_path,
+ struct cifs_sb_info *cifs_sb)
+{
+ if (plen < sizeof(struct reparse_data_buffer)) {
+ cifs_dbg(VFS, "reparse buffer is too small. Must be at least 8 bytes but was %d\n",
+ plen);
+ return -EIO;
+ }
+
+ if (plen < le16_to_cpu(buf->ReparseDataLength) +
+ sizeof(struct reparse_data_buffer)) {
+ cifs_dbg(VFS, "srv returned invalid reparse buf length: %d\n",
+ plen);
+ return -EIO;
+ }
+
+ /* See MS-FSCC 2.1.2 */
+ switch (le32_to_cpu(buf->ReparseTag)) {
+ case IO_REPARSE_TAG_NFS:
+ return parse_reparse_posix(
+ (struct reparse_posix_data *)buf,
+ plen, target_path, cifs_sb);
+ case IO_REPARSE_TAG_SYMLINK:
+ return parse_reparse_symlink(
+ (struct reparse_symlink_data_buffer *)buf,
+ plen, target_path, cifs_sb);
+ default:
+ cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n",
+ le32_to_cpu(buf->ReparseTag));
+ return -EOPNOTSUPP;
+ }
+}
+
+static int
+smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ char **target_path, bool is_reparse_point)
+{
+ int rc;
+ __le16 *utf16_path = NULL;
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_open_parms oparms;
+ struct cifs_fid fid;
+ struct kvec err_iov = {NULL, 0};
+ struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
+ int flags = CIFS_CP_CREATE_CLOSE_OP;
+ struct smb_rqst rqst[3];
+ int resp_buftype[3];
+ struct kvec rsp_iov[3];
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+ struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
+ struct kvec close_iov[1];
+ struct smb2_create_rsp *create_rsp;
+ struct smb2_ioctl_rsp *ioctl_rsp;
+ struct reparse_data_buffer *reparse_buf;
+ int create_options = is_reparse_point ? OPEN_REPARSE_POINT : 0;
+ u32 plen;
+
+ cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
+
+ *target_path = NULL;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(rqst, 0, sizeof(rqst));
+ resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
+ memset(rsp_iov, 0, sizeof(rsp_iov));
+
+ utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
+
+ /* Open */
+ memset(&open_iov, 0, sizeof(open_iov));
+ rqst[0].rq_iov = open_iov;
+ rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = full_path,
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, create_options),
+ .fid = &fid,
+ };
+
+ rc = SMB2_open_init(tcon, server,
+ &rqst[0], &oplock, &oparms, utf16_path);
+ if (rc)
+ goto querty_exit;
+ smb2_set_next_command(tcon, &rqst[0]);
+
+
+ /* IOCTL */
+ memset(&io_iov, 0, sizeof(io_iov));
+ rqst[1].rq_iov = io_iov;
+ rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
+
+ rc = SMB2_ioctl_init(tcon, server,
+ &rqst[1], fid.persistent_fid,
+ fid.volatile_fid, FSCTL_GET_REPARSE_POINT, NULL, 0,
+ CIFSMaxBufSize -
+ MAX_SMB2_CREATE_RESPONSE_SIZE -
+ MAX_SMB2_CLOSE_RESPONSE_SIZE);
+ if (rc)
+ goto querty_exit;
+
+ smb2_set_next_command(tcon, &rqst[1]);
+ smb2_set_related(&rqst[1]);
+
+
+ /* Close */
+ memset(&close_iov, 0, sizeof(close_iov));
+ rqst[2].rq_iov = close_iov;
+ rqst[2].rq_nvec = 1;
+
+ rc = SMB2_close_init(tcon, server,
+ &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
+ if (rc)
+ goto querty_exit;
+
+ smb2_set_related(&rqst[2]);
+
+ rc = compound_send_recv(xid, tcon->ses, server,
+ flags, 3, rqst,
+ resp_buftype, rsp_iov);
+
+ create_rsp = rsp_iov[0].iov_base;
+ if (create_rsp && create_rsp->hdr.Status)
+ err_iov = rsp_iov[0];
+ ioctl_rsp = rsp_iov[1].iov_base;
+
+ /*
+ * Open was successful and we got an ioctl response.
+ */
+ if ((rc == 0) && (is_reparse_point)) {
+ /* See MS-FSCC 2.3.23 */
+
+ reparse_buf = (struct reparse_data_buffer *)
+ ((char *)ioctl_rsp +
+ le32_to_cpu(ioctl_rsp->OutputOffset));
+ plen = le32_to_cpu(ioctl_rsp->OutputCount);
+
+ if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
+ rsp_iov[1].iov_len) {
+ cifs_tcon_dbg(VFS, "srv returned invalid ioctl len: %d\n",
+ plen);
+ rc = -EIO;
+ goto querty_exit;
+ }
+
+ rc = parse_reparse_point(reparse_buf, plen, target_path,
+ cifs_sb);
+ goto querty_exit;
+ }
+
+ if (!rc || !err_iov.iov_base) {
+ rc = -ENOENT;
+ goto querty_exit;
+ }
+
+ rc = smb2_parse_symlink_response(cifs_sb, &err_iov, target_path);
+
+ querty_exit:
+ cifs_dbg(FYI, "query symlink rc %d\n", rc);
+ kfree(utf16_path);
+ SMB2_open_free(&rqst[0]);
+ SMB2_ioctl_free(&rqst[1]);
+ SMB2_close_free(&rqst[2]);
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+ return rc;
+}
+
+int
+smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ __u32 *tag)
+{
+ int rc;
+ __le16 *utf16_path = NULL;
+ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct cifs_open_parms oparms;
+ struct cifs_fid fid;
+ struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
+ int flags = CIFS_CP_CREATE_CLOSE_OP;
+ struct smb_rqst rqst[3];
+ int resp_buftype[3];
+ struct kvec rsp_iov[3];
+ struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+ struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
+ struct kvec close_iov[1];
+ struct smb2_ioctl_rsp *ioctl_rsp;
+ struct reparse_data_buffer *reparse_buf;
+ u32 plen;
+
+ cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(rqst, 0, sizeof(rqst));
+ resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
+ memset(rsp_iov, 0, sizeof(rsp_iov));
+
+ utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
+
+ /*
+ * setup smb2open - TODO add optimization to call cifs_get_readable_path
+ * to see if there is a handle already open that we can use
+ */
+ memset(&open_iov, 0, sizeof(open_iov));
+ rqst[0].rq_iov = open_iov;
+ rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = full_path,
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .disposition = FILE_OPEN,
+ .create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT),
+ .fid = &fid,
+ };
+
+ rc = SMB2_open_init(tcon, server,
+ &rqst[0], &oplock, &oparms, utf16_path);
+ if (rc)
+ goto query_rp_exit;
+ smb2_set_next_command(tcon, &rqst[0]);
+
+
+ /* IOCTL */
+ memset(&io_iov, 0, sizeof(io_iov));
+ rqst[1].rq_iov = io_iov;
+ rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
+
+ rc = SMB2_ioctl_init(tcon, server,
+ &rqst[1], COMPOUND_FID,
+ COMPOUND_FID, FSCTL_GET_REPARSE_POINT, NULL, 0,
+ CIFSMaxBufSize -
+ MAX_SMB2_CREATE_RESPONSE_SIZE -
+ MAX_SMB2_CLOSE_RESPONSE_SIZE);
+ if (rc)
+ goto query_rp_exit;
+
+ smb2_set_next_command(tcon, &rqst[1]);
+ smb2_set_related(&rqst[1]);
+
+
+ /* Close */
+ memset(&close_iov, 0, sizeof(close_iov));
+ rqst[2].rq_iov = close_iov;
+ rqst[2].rq_nvec = 1;
+
+ rc = SMB2_close_init(tcon, server,
+ &rqst[2], COMPOUND_FID, COMPOUND_FID, false);
+ if (rc)
+ goto query_rp_exit;
+
+ smb2_set_related(&rqst[2]);
+
+ rc = compound_send_recv(xid, tcon->ses, server,
+ flags, 3, rqst,
+ resp_buftype, rsp_iov);
+
+ ioctl_rsp = rsp_iov[1].iov_base;
+
+ /*
+ * Open was successful and we got an ioctl response.
+ */
+ if (rc == 0) {
+ /* See MS-FSCC 2.3.23 */
+
+ reparse_buf = (struct reparse_data_buffer *)
+ ((char *)ioctl_rsp +
+ le32_to_cpu(ioctl_rsp->OutputOffset));
+ plen = le32_to_cpu(ioctl_rsp->OutputCount);
+
+ if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
+ rsp_iov[1].iov_len) {
+ cifs_tcon_dbg(FYI, "srv returned invalid ioctl len: %d\n",
+ plen);
+ rc = -EIO;
+ goto query_rp_exit;
+ }
+ *tag = le32_to_cpu(reparse_buf->ReparseTag);
+ }
+
+ query_rp_exit:
+ kfree(utf16_path);
+ SMB2_open_free(&rqst[0]);
+ SMB2_ioctl_free(&rqst[1]);
+ SMB2_close_free(&rqst[2]);
+ free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+ free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+ free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
+ return rc;
+}
+
+static struct cifs_ntsd *
+get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
+ const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
+{
+ struct cifs_ntsd *pntsd = NULL;
+ unsigned int xid;
+ int rc = -EOPNOTSUPP;
+ struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+
+ if (IS_ERR(tlink))
+ return ERR_CAST(tlink);
+
+ xid = get_xid();
+ cifs_dbg(FYI, "trying to get acl\n");
+
+ rc = SMB2_query_acl(xid, tlink_tcon(tlink), cifsfid->persistent_fid,
+ cifsfid->volatile_fid, (void **)&pntsd, pacllen,
+ info);
+ free_xid(xid);
+
+ cifs_put_tlink(tlink);
+
+ cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
+ if (rc)
+ return ERR_PTR(rc);
+ return pntsd;
+
+}
+
+static struct cifs_ntsd *
+get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
+ const char *path, u32 *pacllen, u32 info)
+{
+ struct cifs_ntsd *pntsd = NULL;
+ u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ unsigned int xid;
+ int rc;
+ struct cifs_tcon *tcon;
+ struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ __le16 *utf16_path;
+
+ cifs_dbg(FYI, "get smb3 acl for path %s\n", path);
+ if (IS_ERR(tlink))
+ return ERR_CAST(tlink);
+
+ tcon = tlink_tcon(tlink);
+ xid = get_xid();
+
+ utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+ if (!utf16_path) {
+ rc = -ENOMEM;
+ free_xid(xid);
+ return ERR_PTR(rc);
+ }
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .path = path,
+ .desired_access = READ_CONTROL,
+ .disposition = FILE_OPEN,
+ /*
+ * When querying an ACL, even if the file is a symlink
+ * we want to open the source not the target, and so
+ * the protocol requires that the client specify this
+ * flag when opening a reparse point
+ */
+ .create_options = cifs_create_options(cifs_sb, 0) |
+ OPEN_REPARSE_POINT,
+ .fid = &fid,
+ };
+
+ if (info & SACL_SECINFO)
+ oparms.desired_access |= SYSTEM_SECURITY;
+
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL,
+ NULL);
+ kfree(utf16_path);
+ if (!rc) {
+ rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
+ fid.volatile_fid, (void **)&pntsd, pacllen,
+ info);
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ }
+
+ cifs_put_tlink(tlink);
+ free_xid(xid);
+
+ cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
+ if (rc)
+ return ERR_PTR(rc);
+ return pntsd;
+}
+
+static int
+set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
+ struct inode *inode, const char *path, int aclflag)
+{
+ u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ unsigned int xid;
+ int rc, access_flags = 0;
+ struct cifs_tcon *tcon;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ __le16 *utf16_path;
+
+ cifs_dbg(FYI, "set smb3 acl for path %s\n", path);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+
+ tcon = tlink_tcon(tlink);
+ xid = get_xid();
+
+ if (aclflag & CIFS_ACL_OWNER || aclflag & CIFS_ACL_GROUP)
+ access_flags |= WRITE_OWNER;
+ if (aclflag & CIFS_ACL_SACL)
+ access_flags |= SYSTEM_SECURITY;
+ if (aclflag & CIFS_ACL_DACL)
+ access_flags |= WRITE_DAC;
+
+ utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
+ if (!utf16_path) {
+ rc = -ENOMEM;
+ free_xid(xid);
+ return rc;
+ }
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .desired_access = access_flags,
+ .create_options = cifs_create_options(cifs_sb, 0),
+ .disposition = FILE_OPEN,
+ .path = path,
+ .fid = &fid,
+ };
+
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
+ NULL, NULL);
+ kfree(utf16_path);
+ if (!rc) {
+ rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
+ fid.volatile_fid, pnntsd, acllen, aclflag);
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ }
+
+ cifs_put_tlink(tlink);
+ free_xid(xid);
+ return rc;
+}
+
+/* Retrieve an ACL from the server */
+static struct cifs_ntsd *
+get_smb2_acl(struct cifs_sb_info *cifs_sb,
+ struct inode *inode, const char *path,
+ u32 *pacllen, u32 info)
+{
+ struct cifs_ntsd *pntsd = NULL;
+ struct cifsFileInfo *open_file = NULL;
+
+ if (inode && !(info & SACL_SECINFO))
+ open_file = find_readable_file(CIFS_I(inode), true);
+ if (!open_file || (info & SACL_SECINFO))
+ return get_smb2_acl_by_path(cifs_sb, path, pacllen, info);
+
+ pntsd = get_smb2_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
+ cifsFileInfo_put(open_file);
+ return pntsd;
+}
+
+static long smb3_zero_data(struct file *file, struct cifs_tcon *tcon,
+ loff_t offset, loff_t len, unsigned int xid)
+{
+ struct cifsFileInfo *cfile = file->private_data;
+ struct file_zero_data_information fsctl_buf;
+
+ cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
+
+ fsctl_buf.FileOffset = cpu_to_le64(offset);
+ fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
+
+ return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
+ (char *)&fsctl_buf,
+ sizeof(struct file_zero_data_information),
+ 0, NULL, NULL);
+}
+
+static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
+ loff_t offset, loff_t len, bool keep_size)
+{
+ struct cifs_ses *ses = tcon->ses;
+ struct inode *inode = file_inode(file);
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct cifsFileInfo *cfile = file->private_data;
+ long rc;
+ unsigned int xid;
+ __le64 eof;
+
+ xid = get_xid();
+
+ trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid,
+ ses->Suid, offset, len);
+
+ inode_lock(inode);
+ filemap_invalidate_lock(inode->i_mapping);
+
+ /*
+ * We zero the range through ioctl, so we need remove the page caches
+ * first, otherwise the data may be inconsistent with the server.
+ */
+ truncate_pagecache_range(inode, offset, offset + len - 1);
+
+ /* if file not oplocked can't be sure whether asking to extend size */
+ rc = -EOPNOTSUPP;
+ if (keep_size == false && !CIFS_CACHE_READ(cifsi))
+ goto zero_range_exit;
+
+ rc = smb3_zero_data(file, tcon, offset, len, xid);
+ if (rc < 0)
+ goto zero_range_exit;
+
+ /*
+ * do we also need to change the size of the file?
+ */
+ if (keep_size == false && i_size_read(inode) < offset + len) {
+ eof = cpu_to_le64(offset + len);
+ rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, cfile->pid, &eof);
+ }
+
+ zero_range_exit:
+ filemap_invalidate_unlock(inode->i_mapping);
+ inode_unlock(inode);
+ free_xid(xid);
+ if (rc)
+ trace_smb3_zero_err(xid, cfile->fid.persistent_fid, tcon->tid,
+ ses->Suid, offset, len, rc);
+ else
+ trace_smb3_zero_done(xid, cfile->fid.persistent_fid, tcon->tid,
+ ses->Suid, offset, len);
+ return rc;
+}
+
+static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
+ loff_t offset, loff_t len)
+{
+ struct inode *inode = file_inode(file);
+ struct cifsFileInfo *cfile = file->private_data;
+ struct file_zero_data_information fsctl_buf;
+ long rc;
+ unsigned int xid;
+ __u8 set_sparse = 1;
+
+ xid = get_xid();
+
+ inode_lock(inode);
+ /* Need to make file sparse, if not already, before freeing range. */
+ /* Consider adding equivalent for compressed since it could also work */
+ if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
+ filemap_invalidate_lock(inode->i_mapping);
+ /*
+ * We implement the punch hole through ioctl, so we need remove the page
+ * caches first, otherwise the data may be inconsistent with the server.
+ */
+ truncate_pagecache_range(inode, offset, offset + len - 1);
+
+ cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
+
+ fsctl_buf.FileOffset = cpu_to_le64(offset);
+ fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
+
+ rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
+ (char *)&fsctl_buf,
+ sizeof(struct file_zero_data_information),
+ CIFSMaxBufSize, NULL, NULL);
+ filemap_invalidate_unlock(inode->i_mapping);
+out:
+ inode_unlock(inode);
+ free_xid(xid);
+ return rc;
+}
+
+static int smb3_simple_fallocate_write_range(unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile,
+ loff_t off, loff_t len,
+ char *buf)
+{
+ struct cifs_io_parms io_parms = {0};
+ int nbytes;
+ int rc = 0;
+ struct kvec iov[2];
+
+ io_parms.netfid = cfile->fid.netfid;
+ io_parms.pid = current->tgid;
+ io_parms.tcon = tcon;
+ io_parms.persistent_fid = cfile->fid.persistent_fid;
+ io_parms.volatile_fid = cfile->fid.volatile_fid;
+
+ while (len) {
+ io_parms.offset = off;
+ io_parms.length = len;
+ if (io_parms.length > SMB2_MAX_BUFFER_SIZE)
+ io_parms.length = SMB2_MAX_BUFFER_SIZE;
+ /* iov[0] is reserved for smb header */
+ iov[1].iov_base = buf;
+ iov[1].iov_len = io_parms.length;
+ rc = SMB2_write(xid, &io_parms, &nbytes, iov, 1);
+ if (rc)
+ break;
+ if (nbytes > len)
+ return -EINVAL;
+ buf += nbytes;
+ off += nbytes;
+ len -= nbytes;
+ }
+ return rc;
+}
+
+static int smb3_simple_fallocate_range(unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile,
+ loff_t off, loff_t len)
+{
+ struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data;
+ u32 out_data_len;
+ char *buf = NULL;
+ loff_t l;
+ int rc;
+
+ in_data.file_offset = cpu_to_le64(off);
+ in_data.length = cpu_to_le64(len);
+ rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ FSCTL_QUERY_ALLOCATED_RANGES,
+ (char *)&in_data, sizeof(in_data),
+ 1024 * sizeof(struct file_allocated_range_buffer),
+ (char **)&out_data, &out_data_len);
+ if (rc)
+ goto out;
+
+ buf = kzalloc(1024 * 1024, GFP_KERNEL);
+ if (buf == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ tmp_data = out_data;
+ while (len) {
+ /*
+ * The rest of the region is unmapped so write it all.
+ */
+ if (out_data_len == 0) {
+ rc = smb3_simple_fallocate_write_range(xid, tcon,
+ cfile, off, len, buf);
+ goto out;
+ }
+
+ if (out_data_len < sizeof(struct file_allocated_range_buffer)) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (off < le64_to_cpu(tmp_data->file_offset)) {
+ /*
+ * We are at a hole. Write until the end of the region
+ * or until the next allocated data,
+ * whichever comes next.
+ */
+ l = le64_to_cpu(tmp_data->file_offset) - off;
+ if (len < l)
+ l = len;
+ rc = smb3_simple_fallocate_write_range(xid, tcon,
+ cfile, off, l, buf);
+ if (rc)
+ goto out;
+ off = off + l;
+ len = len - l;
+ if (len == 0)
+ goto out;
+ }
+ /*
+ * We are at a section of allocated data, just skip forward
+ * until the end of the data or the end of the region
+ * we are supposed to fallocate, whichever comes first.
+ */
+ l = le64_to_cpu(tmp_data->length);
+ if (len < l)
+ l = len;
+ off += l;
+ len -= l;
+
+ tmp_data = &tmp_data[1];
+ out_data_len -= sizeof(struct file_allocated_range_buffer);
+ }
+
+ out:
+ kfree(out_data);
+ kfree(buf);
+ return rc;
+}
+
+
+static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
+ loff_t off, loff_t len, bool keep_size)
+{
+ struct inode *inode;
+ struct cifsInodeInfo *cifsi;
+ struct cifsFileInfo *cfile = file->private_data;
+ long rc = -EOPNOTSUPP;
+ unsigned int xid;
+ __le64 eof;
+
+ xid = get_xid();
+
+ inode = d_inode(cfile->dentry);
+ cifsi = CIFS_I(inode);
+
+ trace_smb3_falloc_enter(xid, cfile->fid.persistent_fid, tcon->tid,
+ tcon->ses->Suid, off, len);
+ /* if file not oplocked can't be sure whether asking to extend size */
+ if (!CIFS_CACHE_READ(cifsi))
+ if (keep_size == false) {
+ trace_smb3_falloc_err(xid, cfile->fid.persistent_fid,
+ tcon->tid, tcon->ses->Suid, off, len, rc);
+ free_xid(xid);
+ return rc;
+ }
+
+ /*
+ * Extending the file
+ */
+ if ((keep_size == false) && i_size_read(inode) < off + len) {
+ rc = inode_newsize_ok(inode, off + len);
+ if (rc)
+ goto out;
+
+ if (cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)
+ smb2_set_sparse(xid, tcon, cfile, inode, false);
+
+ eof = cpu_to_le64(off + len);
+ rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, cfile->pid, &eof);
+ if (rc == 0) {
+ cifsi->server_eof = off + len;
+ cifs_setsize(inode, off + len);
+ cifs_truncate_page(inode->i_mapping, inode->i_size);
+ truncate_setsize(inode, off + len);
+ }
+ goto out;
+ }
+
+ /*
+ * Files are non-sparse by default so falloc may be a no-op
+ * Must check if file sparse. If not sparse, and since we are not
+ * extending then no need to do anything since file already allocated
+ */
+ if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
+ rc = 0;
+ goto out;
+ }
+
+ if (keep_size == true) {
+ /*
+ * We can not preallocate pages beyond the end of the file
+ * in SMB2
+ */
+ if (off >= i_size_read(inode)) {
+ rc = 0;
+ goto out;
+ }
+ /*
+ * For fallocates that are partially beyond the end of file,
+ * clamp len so we only fallocate up to the end of file.
+ */
+ if (off + len > i_size_read(inode)) {
+ len = i_size_read(inode) - off;
+ }
+ }
+
+ if ((keep_size == true) || (i_size_read(inode) >= off + len)) {
+ /*
+ * At this point, we are trying to fallocate an internal
+ * regions of a sparse file. Since smb2 does not have a
+ * fallocate command we have two otions on how to emulate this.
+ * We can either turn the entire file to become non-sparse
+ * which we only do if the fallocate is for virtually
+ * the whole file, or we can overwrite the region with zeroes
+ * using SMB2_write, which could be prohibitevly expensive
+ * if len is large.
+ */
+ /*
+ * We are only trying to fallocate a small region so
+ * just write it with zero.
+ */
+ if (len <= 1024 * 1024) {
+ rc = smb3_simple_fallocate_range(xid, tcon, cfile,
+ off, len);
+ goto out;
+ }
+
+ /*
+ * Check if falloc starts within first few pages of file
+ * and ends within a few pages of the end of file to
+ * ensure that most of file is being forced to be
+ * fallocated now. If so then setting whole file sparse
+ * ie potentially making a few extra pages at the beginning
+ * or end of the file non-sparse via set_sparse is harmless.
+ */
+ if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ }
+
+ smb2_set_sparse(xid, tcon, cfile, inode, false);
+ rc = 0;
+
+out:
+ if (rc)
+ trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, tcon->tid,
+ tcon->ses->Suid, off, len, rc);
+ else
+ trace_smb3_falloc_done(xid, cfile->fid.persistent_fid, tcon->tid,
+ tcon->ses->Suid, off, len);
+
+ free_xid(xid);
+ return rc;
+}
+
+static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
+ loff_t off, loff_t len)
+{
+ int rc;
+ unsigned int xid;
+ struct inode *inode = file_inode(file);
+ struct cifsFileInfo *cfile = file->private_data;
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ __le64 eof;
+ loff_t old_eof;
+
+ xid = get_xid();
+
+ inode_lock(inode);
+
+ old_eof = i_size_read(inode);
+ if ((off >= old_eof) ||
+ off + len >= old_eof) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ filemap_invalidate_lock(inode->i_mapping);
+ rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof - 1);
+ if (rc < 0)
+ goto out_2;
+
+ truncate_pagecache_range(inode, off, old_eof);
+
+ rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
+ old_eof - off - len, off);
+ if (rc < 0)
+ goto out_2;
+
+ eof = cpu_to_le64(old_eof - len);
+ rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, cfile->pid, &eof);
+ if (rc < 0)
+ goto out_2;
+
+ rc = 0;
+
+ cifsi->server_eof = i_size_read(inode) - len;
+ truncate_setsize(inode, cifsi->server_eof);
+ fscache_resize_cookie(cifs_inode_cookie(inode), cifsi->server_eof);
+out_2:
+ filemap_invalidate_unlock(inode->i_mapping);
+ out:
+ inode_unlock(inode);
+ free_xid(xid);
+ return rc;
+}
+
+static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
+ loff_t off, loff_t len)
+{
+ int rc;
+ unsigned int xid;
+ struct cifsFileInfo *cfile = file->private_data;
+ struct inode *inode = file_inode(file);
+ __le64 eof;
+ __u64 count, old_eof;
+
+ xid = get_xid();
+
+ inode_lock(inode);
+
+ old_eof = i_size_read(inode);
+ if (off >= old_eof) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ count = old_eof - off;
+ eof = cpu_to_le64(old_eof + len);
+
+ filemap_invalidate_lock(inode->i_mapping);
+ rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof + len - 1);
+ if (rc < 0)
+ goto out_2;
+ truncate_pagecache_range(inode, off, old_eof);
+
+ rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, cfile->pid, &eof);
+ if (rc < 0)
+ goto out_2;
+
+ rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
+ if (rc < 0)
+ goto out_2;
+
+ rc = smb3_zero_data(file, tcon, off, len, xid);
+ if (rc < 0)
+ goto out_2;
+
+ rc = 0;
+out_2:
+ filemap_invalidate_unlock(inode->i_mapping);
+ out:
+ inode_unlock(inode);
+ free_xid(xid);
+ return rc;
+}
+
+static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offset, int whence)
+{
+ struct cifsFileInfo *wrcfile, *cfile = file->private_data;
+ struct cifsInodeInfo *cifsi;
+ struct inode *inode;
+ int rc = 0;
+ struct file_allocated_range_buffer in_data, *out_data = NULL;
+ u32 out_data_len;
+ unsigned int xid;
+
+ if (whence != SEEK_HOLE && whence != SEEK_DATA)
+ return generic_file_llseek(file, offset, whence);
+
+ inode = d_inode(cfile->dentry);
+ cifsi = CIFS_I(inode);
+
+ if (offset < 0 || offset >= i_size_read(inode))
+ return -ENXIO;
+
+ xid = get_xid();
+ /*
+ * We need to be sure that all dirty pages are written as they
+ * might fill holes on the server.
+ * Note that we also MUST flush any written pages since at least
+ * some servers (Windows2016) will not reflect recent writes in
+ * QUERY_ALLOCATED_RANGES until SMB2_flush is called.
+ */
+ wrcfile = find_writable_file(cifsi, FIND_WR_ANY);
+ if (wrcfile) {
+ filemap_write_and_wait(inode->i_mapping);
+ smb2_flush_file(xid, tcon, &wrcfile->fid);
+ cifsFileInfo_put(wrcfile);
+ }
+
+ if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) {
+ if (whence == SEEK_HOLE)
+ offset = i_size_read(inode);
+ goto lseek_exit;
+ }
+
+ in_data.file_offset = cpu_to_le64(offset);
+ in_data.length = cpu_to_le64(i_size_read(inode));
+
+ rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ FSCTL_QUERY_ALLOCATED_RANGES,
+ (char *)&in_data, sizeof(in_data),
+ sizeof(struct file_allocated_range_buffer),
+ (char **)&out_data, &out_data_len);
+ if (rc == -E2BIG)
+ rc = 0;
+ if (rc)
+ goto lseek_exit;
+
+ if (whence == SEEK_HOLE && out_data_len == 0)
+ goto lseek_exit;
+
+ if (whence == SEEK_DATA && out_data_len == 0) {
+ rc = -ENXIO;
+ goto lseek_exit;
+ }
+
+ if (out_data_len < sizeof(struct file_allocated_range_buffer)) {
+ rc = -EINVAL;
+ goto lseek_exit;
+ }
+ if (whence == SEEK_DATA) {
+ offset = le64_to_cpu(out_data->file_offset);
+ goto lseek_exit;
+ }
+ if (offset < le64_to_cpu(out_data->file_offset))
+ goto lseek_exit;
+
+ offset = le64_to_cpu(out_data->file_offset) + le64_to_cpu(out_data->length);
+
+ lseek_exit:
+ free_xid(xid);
+ kfree(out_data);
+ if (!rc)
+ return vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
+ else
+ return rc;
+}
+
+static int smb3_fiemap(struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile,
+ struct fiemap_extent_info *fei, u64 start, u64 len)
+{
+ unsigned int xid;
+ struct file_allocated_range_buffer in_data, *out_data;
+ u32 out_data_len;
+ int i, num, rc, flags, last_blob;
+ u64 next;
+
+ rc = fiemap_prep(d_inode(cfile->dentry), fei, start, &len, 0);
+ if (rc)
+ return rc;
+
+ xid = get_xid();
+ again:
+ in_data.file_offset = cpu_to_le64(start);
+ in_data.length = cpu_to_le64(len);
+
+ rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid,
+ FSCTL_QUERY_ALLOCATED_RANGES,
+ (char *)&in_data, sizeof(in_data),
+ 1024 * sizeof(struct file_allocated_range_buffer),
+ (char **)&out_data, &out_data_len);
+ if (rc == -E2BIG) {
+ last_blob = 0;
+ rc = 0;
+ } else
+ last_blob = 1;
+ if (rc)
+ goto out;
+
+ if (out_data_len && out_data_len < sizeof(struct file_allocated_range_buffer)) {
+ rc = -EINVAL;
+ goto out;
+ }
+ if (out_data_len % sizeof(struct file_allocated_range_buffer)) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ num = out_data_len / sizeof(struct file_allocated_range_buffer);
+ for (i = 0; i < num; i++) {
+ flags = 0;
+ if (i == num - 1 && last_blob)
+ flags |= FIEMAP_EXTENT_LAST;
+
+ rc = fiemap_fill_next_extent(fei,
+ le64_to_cpu(out_data[i].file_offset),
+ le64_to_cpu(out_data[i].file_offset),
+ le64_to_cpu(out_data[i].length),
+ flags);
+ if (rc < 0)
+ goto out;
+ if (rc == 1) {
+ rc = 0;
+ goto out;
+ }
+ }
+
+ if (!last_blob) {
+ next = le64_to_cpu(out_data[num - 1].file_offset) +
+ le64_to_cpu(out_data[num - 1].length);
+ len = len - (next - start);
+ start = next;
+ goto again;
+ }
+
+ out:
+ free_xid(xid);
+ kfree(out_data);
+ return rc;
+}
+
+static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
+ loff_t off, loff_t len)
+{
+ /* KEEP_SIZE already checked for by do_fallocate */
+ if (mode & FALLOC_FL_PUNCH_HOLE)
+ return smb3_punch_hole(file, tcon, off, len);
+ else if (mode & FALLOC_FL_ZERO_RANGE) {
+ if (mode & FALLOC_FL_KEEP_SIZE)
+ return smb3_zero_range(file, tcon, off, len, true);
+ return smb3_zero_range(file, tcon, off, len, false);
+ } else if (mode == FALLOC_FL_KEEP_SIZE)
+ return smb3_simple_falloc(file, tcon, off, len, true);
+ else if (mode == FALLOC_FL_COLLAPSE_RANGE)
+ return smb3_collapse_range(file, tcon, off, len);
+ else if (mode == FALLOC_FL_INSERT_RANGE)
+ return smb3_insert_range(file, tcon, off, len);
+ else if (mode == 0)
+ return smb3_simple_falloc(file, tcon, off, len, false);
+
+ return -EOPNOTSUPP;
+}
+
+static void
+smb2_downgrade_oplock(struct TCP_Server_Info *server,
+ struct cifsInodeInfo *cinode, __u32 oplock,
+ unsigned int epoch, bool *purge_cache)
+{
+ server->ops->set_oplock_level(cinode, oplock, 0, NULL);
+}
+
+static void
+smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
+ unsigned int epoch, bool *purge_cache);
+
+static void
+smb3_downgrade_oplock(struct TCP_Server_Info *server,
+ struct cifsInodeInfo *cinode, __u32 oplock,
+ unsigned int epoch, bool *purge_cache)
+{
+ unsigned int old_state = cinode->oplock;
+ unsigned int old_epoch = cinode->epoch;
+ unsigned int new_state;
+
+ if (epoch > old_epoch) {
+ smb21_set_oplock_level(cinode, oplock, 0, NULL);
+ cinode->epoch = epoch;
+ }
+
+ new_state = cinode->oplock;
+ *purge_cache = false;
+
+ if ((old_state & CIFS_CACHE_READ_FLG) != 0 &&
+ (new_state & CIFS_CACHE_READ_FLG) == 0)
+ *purge_cache = true;
+ else if (old_state == new_state && (epoch - old_epoch > 1))
+ *purge_cache = true;
+}
+
+static void
+smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
+ unsigned int epoch, bool *purge_cache)
+{
+ oplock &= 0xFF;
+ cinode->lease_granted = false;
+ if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
+ return;
+ if (oplock == SMB2_OPLOCK_LEVEL_BATCH) {
+ cinode->oplock = CIFS_CACHE_RHW_FLG;
+ cifs_dbg(FYI, "Batch Oplock granted on inode %p\n",
+ &cinode->netfs.inode);
+ } else if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
+ cinode->oplock = CIFS_CACHE_RW_FLG;
+ cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
+ &cinode->netfs.inode);
+ } else if (oplock == SMB2_OPLOCK_LEVEL_II) {
+ cinode->oplock = CIFS_CACHE_READ_FLG;
+ cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
+ &cinode->netfs.inode);
+ } else
+ cinode->oplock = 0;
+}
+
+static void
+smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
+ unsigned int epoch, bool *purge_cache)
+{
+ char message[5] = {0};
+ unsigned int new_oplock = 0;
+
+ oplock &= 0xFF;
+ cinode->lease_granted = true;
+ if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
+ return;
+
+ /* Check if the server granted an oplock rather than a lease */
+ if (oplock & SMB2_OPLOCK_LEVEL_EXCLUSIVE)
+ return smb2_set_oplock_level(cinode, oplock, epoch,
+ purge_cache);
+
+ if (oplock & SMB2_LEASE_READ_CACHING_HE) {
+ new_oplock |= CIFS_CACHE_READ_FLG;
+ strcat(message, "R");
+ }
+ if (oplock & SMB2_LEASE_HANDLE_CACHING_HE) {
+ new_oplock |= CIFS_CACHE_HANDLE_FLG;
+ strcat(message, "H");
+ }
+ if (oplock & SMB2_LEASE_WRITE_CACHING_HE) {
+ new_oplock |= CIFS_CACHE_WRITE_FLG;
+ strcat(message, "W");
+ }
+ if (!new_oplock)
+ strncpy(message, "None", sizeof(message));
+
+ cinode->oplock = new_oplock;
+ cifs_dbg(FYI, "%s Lease granted on inode %p\n", message,
+ &cinode->netfs.inode);
+}
+
+static void
+smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
+ unsigned int epoch, bool *purge_cache)
+{
+ unsigned int old_oplock = cinode->oplock;
+
+ smb21_set_oplock_level(cinode, oplock, epoch, purge_cache);
+
+ if (purge_cache) {
+ *purge_cache = false;
+ if (old_oplock == CIFS_CACHE_READ_FLG) {
+ if (cinode->oplock == CIFS_CACHE_READ_FLG &&
+ (epoch - cinode->epoch > 0))
+ *purge_cache = true;
+ else if (cinode->oplock == CIFS_CACHE_RH_FLG &&
+ (epoch - cinode->epoch > 1))
+ *purge_cache = true;
+ else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
+ (epoch - cinode->epoch > 1))
+ *purge_cache = true;
+ else if (cinode->oplock == 0 &&
+ (epoch - cinode->epoch > 0))
+ *purge_cache = true;
+ } else if (old_oplock == CIFS_CACHE_RH_FLG) {
+ if (cinode->oplock == CIFS_CACHE_RH_FLG &&
+ (epoch - cinode->epoch > 0))
+ *purge_cache = true;
+ else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
+ (epoch - cinode->epoch > 1))
+ *purge_cache = true;
+ }
+ cinode->epoch = epoch;
+ }
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+static bool
+smb2_is_read_op(__u32 oplock)
+{
+ return oplock == SMB2_OPLOCK_LEVEL_II;
+}
+#endif /* CIFS_ALLOW_INSECURE_LEGACY */
+
+static bool
+smb21_is_read_op(__u32 oplock)
+{
+ return (oplock & SMB2_LEASE_READ_CACHING_HE) &&
+ !(oplock & SMB2_LEASE_WRITE_CACHING_HE);
+}
+
+static __le32
+map_oplock_to_lease(u8 oplock)
+{
+ if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
+ return SMB2_LEASE_WRITE_CACHING_LE | SMB2_LEASE_READ_CACHING_LE;
+ else if (oplock == SMB2_OPLOCK_LEVEL_II)
+ return SMB2_LEASE_READ_CACHING_LE;
+ else if (oplock == SMB2_OPLOCK_LEVEL_BATCH)
+ return SMB2_LEASE_HANDLE_CACHING_LE | SMB2_LEASE_READ_CACHING_LE |
+ SMB2_LEASE_WRITE_CACHING_LE;
+ return 0;
+}
+
+static char *
+smb2_create_lease_buf(u8 *lease_key, u8 oplock)
+{
+ struct create_lease *buf;
+
+ buf = kzalloc(sizeof(struct create_lease), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
+ buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
+
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_lease, lcontext));
+ buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_lease, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
+ buf->Name[0] = 'R';
+ buf->Name[1] = 'q';
+ buf->Name[2] = 'L';
+ buf->Name[3] = 's';
+ return (char *)buf;
+}
+
+static char *
+smb3_create_lease_buf(u8 *lease_key, u8 oplock)
+{
+ struct create_lease_v2 *buf;
+
+ buf = kzalloc(sizeof(struct create_lease_v2), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
+ buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
+
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_lease_v2, lcontext));
+ buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_lease_v2, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
+ buf->Name[0] = 'R';
+ buf->Name[1] = 'q';
+ buf->Name[2] = 'L';
+ buf->Name[3] = 's';
+ return (char *)buf;
+}
+
+static __u8
+smb2_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key)
+{
+ struct create_lease *lc = (struct create_lease *)buf;
+
+ *epoch = 0; /* not used */
+ if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE)
+ return SMB2_OPLOCK_LEVEL_NOCHANGE;
+ return le32_to_cpu(lc->lcontext.LeaseState);
+}
+
+static __u8
+smb3_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key)
+{
+ struct create_lease_v2 *lc = (struct create_lease_v2 *)buf;
+
+ *epoch = le16_to_cpu(lc->lcontext.Epoch);
+ if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE)
+ return SMB2_OPLOCK_LEVEL_NOCHANGE;
+ if (lease_key)
+ memcpy(lease_key, &lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
+ return le32_to_cpu(lc->lcontext.LeaseState);
+}
+
+static unsigned int
+smb2_wp_retry_size(struct inode *inode)
+{
+ return min_t(unsigned int, CIFS_SB(inode->i_sb)->ctx->wsize,
+ SMB2_MAX_BUFFER_SIZE);
+}
+
+static bool
+smb2_dir_needs_close(struct cifsFileInfo *cfile)
+{
+ return !cfile->invalidHandle;
+}
+
+static void
+fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
+ struct smb_rqst *old_rq, __le16 cipher_type)
+{
+ struct smb2_hdr *shdr =
+ (struct smb2_hdr *)old_rq->rq_iov[0].iov_base;
+
+ memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
+ tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
+ tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
+ tr_hdr->Flags = cpu_to_le16(0x01);
+ if ((cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
+ (cipher_type == SMB2_ENCRYPTION_AES256_GCM))
+ get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
+ else
+ get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
+ memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
+}
+
+static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct smb_rqst *rqst,
+ int num_rqst, const u8 *sig, u8 **iv,
+ struct aead_request **req, struct scatterlist **sgl,
+ unsigned int *num_sgs)
+{
+ unsigned int req_size = sizeof(**req) + crypto_aead_reqsize(tfm);
+ unsigned int iv_size = crypto_aead_ivsize(tfm);
+ unsigned int len;
+ u8 *p;
+
+ *num_sgs = cifs_get_num_sgs(rqst, num_rqst, sig);
+
+ len = iv_size;
+ len += crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1);
+ len = ALIGN(len, crypto_tfm_ctx_alignment());
+ len += req_size;
+ len = ALIGN(len, __alignof__(struct scatterlist));
+ len += *num_sgs * sizeof(**sgl);
+
+ p = kmalloc(len, GFP_ATOMIC);
+ if (!p)
+ return NULL;
+
+ *iv = (u8 *)PTR_ALIGN(p, crypto_aead_alignmask(tfm) + 1);
+ *req = (struct aead_request *)PTR_ALIGN(*iv + iv_size,
+ crypto_tfm_ctx_alignment());
+ *sgl = (struct scatterlist *)PTR_ALIGN((u8 *)*req + req_size,
+ __alignof__(struct scatterlist));
+ return p;
+}
+
+static void *smb2_get_aead_req(struct crypto_aead *tfm, const struct smb_rqst *rqst,
+ int num_rqst, const u8 *sig, u8 **iv,
+ struct aead_request **req, struct scatterlist **sgl)
+{
+ unsigned int off, len, skip;
+ struct scatterlist *sg;
+ unsigned int num_sgs;
+ unsigned long addr;
+ int i, j;
+ void *p;
+
+ p = smb2_aead_req_alloc(tfm, rqst, num_rqst, sig, iv, req, sgl, &num_sgs);
+ if (!p)
+ return NULL;
+
+ sg_init_table(*sgl, num_sgs);
+ sg = *sgl;
+
+ /* Assumes the first rqst has a transform header as the first iov.
+ * I.e.
+ * rqst[0].rq_iov[0] is transform header
+ * rqst[0].rq_iov[1+] data to be encrypted/decrypted
+ * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
+ */
+ for (i = 0; i < num_rqst; i++) {
+ /*
+ * The first rqst has a transform header where the
+ * first 20 bytes are not part of the encrypted blob.
+ */
+ for (j = 0; j < rqst[i].rq_nvec; j++) {
+ struct kvec *iov = &rqst[i].rq_iov[j];
+
+ skip = (i == 0) && (j == 0) ? 20 : 0;
+ addr = (unsigned long)iov->iov_base + skip;
+ len = iov->iov_len - skip;
+ sg = cifs_sg_set_buf(sg, (void *)addr, len);
+ }
+ for (j = 0; j < rqst[i].rq_npages; j++) {
+ rqst_page_get_length(&rqst[i], j, &len, &off);
+ sg_set_page(sg++, rqst[i].rq_pages[j], len, off);
+ }
+ }
+ cifs_sg_set_buf(sg, sig, SMB2_SIGNATURE_SIZE);
+
+ return p;
+}
+
+static int
+smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
+{
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses;
+ u8 *ses_enc_key;
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+ if (ses->Suid == ses_id) {
+ spin_lock(&ses->ses_lock);
+ ses_enc_key = enc ? ses->smb3encryptionkey :
+ ses->smb3decryptionkey;
+ memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
+ spin_unlock(&ses->ses_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+ return 0;
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ return -EAGAIN;
+}
+/*
+ * Encrypt or decrypt @rqst message. @rqst[0] has the following format:
+ * iov[0] - transform header (associate data),
+ * iov[1-N] - SMB2 header and pages - data to encrypt.
+ * On success return encrypted data in iov[1-N] and pages, leave iov[0]
+ * untouched.
+ */
+static int
+crypt_message(struct TCP_Server_Info *server, int num_rqst,
+ struct smb_rqst *rqst, int enc)
+{
+ struct smb2_transform_hdr *tr_hdr =
+ (struct smb2_transform_hdr *)rqst[0].rq_iov[0].iov_base;
+ unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
+ int rc = 0;
+ struct scatterlist *sg;
+ u8 sign[SMB2_SIGNATURE_SIZE] = {};
+ u8 key[SMB3_ENC_DEC_KEY_SIZE];
+ struct aead_request *req;
+ u8 *iv;
+ DECLARE_CRYPTO_WAIT(wait);
+ struct crypto_aead *tfm;
+ unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
+ void *creq;
+
+ rc = smb2_get_enc_key(server, le64_to_cpu(tr_hdr->SessionId), enc, key);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not get %scryption key\n", __func__,
+ enc ? "en" : "de");
+ return rc;
+ }
+
+ rc = smb3_crypto_aead_allocate(server);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
+ return rc;
+ }
+
+ tfm = enc ? server->secmech.enc : server->secmech.dec;
+
+ if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
+ (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
+ rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
+ else
+ rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
+
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
+ return rc;
+ }
+
+ rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc);
+ return rc;
+ }
+
+ creq = smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg);
+ if (unlikely(!creq))
+ return -ENOMEM;
+
+ if (!enc) {
+ memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
+ crypt_len += SMB2_SIGNATURE_SIZE;
+ }
+
+ if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
+ (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
+ memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
+ else {
+ iv[0] = 3;
+ memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
+ }
+
+ aead_request_set_tfm(req, tfm);
+ aead_request_set_crypt(req, sg, sg, crypt_len, iv);
+ aead_request_set_ad(req, assoc_data_len);
+
+ aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ crypto_req_done, &wait);
+
+ rc = crypto_wait_req(enc ? crypto_aead_encrypt(req)
+ : crypto_aead_decrypt(req), &wait);
+
+ if (!rc && enc)
+ memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
+
+ kfree_sensitive(creq);
+ return rc;
+}
+
+void
+smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst)
+{
+ int i, j;
+
+ for (i = 0; i < num_rqst; i++) {
+ if (rqst[i].rq_pages) {
+ for (j = rqst[i].rq_npages - 1; j >= 0; j--)
+ put_page(rqst[i].rq_pages[j]);
+ kfree(rqst[i].rq_pages);
+ }
+ }
+}
+
+/*
+ * This function will initialize new_rq and encrypt the content.
+ * The first entry, new_rq[0], only contains a single iov which contains
+ * a smb2_transform_hdr and is pre-allocated by the caller.
+ * This function then populates new_rq[1+] with the content from olq_rq[0+].
+ *
+ * The end result is an array of smb_rqst structures where the first structure
+ * only contains a single iov for the transform header which we then can pass
+ * to crypt_message().
+ *
+ * new_rq[0].rq_iov[0] : smb2_transform_hdr pre-allocated by the caller
+ * new_rq[1+].rq_iov[*] == old_rq[0+].rq_iov[*] : SMB2/3 requests
+ */
+static int
+smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
+ struct smb_rqst *new_rq, struct smb_rqst *old_rq)
+{
+ struct page **pages;
+ struct smb2_transform_hdr *tr_hdr = new_rq[0].rq_iov[0].iov_base;
+ unsigned int npages;
+ unsigned int orig_len = 0;
+ int i, j;
+ int rc = -ENOMEM;
+
+ for (i = 1; i < num_rqst; i++) {
+ npages = old_rq[i - 1].rq_npages;
+ pages = kmalloc_array(npages, sizeof(struct page *),
+ GFP_KERNEL);
+ if (!pages)
+ goto err_free;
+
+ new_rq[i].rq_pages = pages;
+ new_rq[i].rq_npages = npages;
+ new_rq[i].rq_offset = old_rq[i - 1].rq_offset;
+ new_rq[i].rq_pagesz = old_rq[i - 1].rq_pagesz;
+ new_rq[i].rq_tailsz = old_rq[i - 1].rq_tailsz;
+ new_rq[i].rq_iov = old_rq[i - 1].rq_iov;
+ new_rq[i].rq_nvec = old_rq[i - 1].rq_nvec;
+
+ orig_len += smb_rqst_len(server, &old_rq[i - 1]);
+
+ for (j = 0; j < npages; j++) {
+ pages[j] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
+ if (!pages[j])
+ goto err_free;
+ }
+
+ /* copy pages form the old */
+ for (j = 0; j < npages; j++) {
+ char *dst, *src;
+ unsigned int offset, len;
+
+ rqst_page_get_length(&new_rq[i], j, &len, &offset);
+
+ dst = (char *) kmap(new_rq[i].rq_pages[j]) + offset;
+ src = (char *) kmap(old_rq[i - 1].rq_pages[j]) + offset;
+
+ memcpy(dst, src, len);
+ kunmap(new_rq[i].rq_pages[j]);
+ kunmap(old_rq[i - 1].rq_pages[j]);
+ }
+ }
+
+ /* fill the 1st iov with a transform header */
+ fill_transform_hdr(tr_hdr, orig_len, old_rq, server->cipher_type);
+
+ rc = crypt_message(server, num_rqst, new_rq, 1);
+ cifs_dbg(FYI, "Encrypt message returned %d\n", rc);
+ if (rc)
+ goto err_free;
+
+ return rc;
+
+err_free:
+ smb3_free_compound_rqst(num_rqst - 1, &new_rq[1]);
+ return rc;
+}
+
+static int
+smb3_is_transform_hdr(void *buf)
+{
+ struct smb2_transform_hdr *trhdr = buf;
+
+ return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
+}
+
+static int
+decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
+ unsigned int buf_data_size, struct page **pages,
+ unsigned int npages, unsigned int page_data_size,
+ bool is_offloaded)
+{
+ struct kvec iov[2];
+ struct smb_rqst rqst = {NULL};
+ int rc;
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sizeof(struct smb2_transform_hdr);
+ iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
+ iov[1].iov_len = buf_data_size;
+
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 2;
+ rqst.rq_pages = pages;
+ rqst.rq_npages = npages;
+ rqst.rq_pagesz = PAGE_SIZE;
+ rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE;
+
+ rc = crypt_message(server, 1, &rqst, 0);
+ cifs_dbg(FYI, "Decrypt message returned %d\n", rc);
+
+ if (rc)
+ return rc;
+
+ memmove(buf, iov[1].iov_base, buf_data_size);
+
+ if (!is_offloaded)
+ server->total_read = buf_data_size + page_data_size;
+
+ return rc;
+}
+
+static int
+read_data_into_pages(struct TCP_Server_Info *server, struct page **pages,
+ unsigned int npages, unsigned int len)
+{
+ int i;
+ int length;
+
+ for (i = 0; i < npages; i++) {
+ struct page *page = pages[i];
+ size_t n;
+
+ n = len;
+ if (len >= PAGE_SIZE) {
+ /* enough data to fill the page */
+ n = PAGE_SIZE;
+ len -= n;
+ } else {
+ zero_user(page, len, PAGE_SIZE - len);
+ len = 0;
+ }
+ length = cifs_read_page_from_socket(server, page, 0, n);
+ if (length < 0)
+ return length;
+ server->total_read += length;
+ }
+
+ return 0;
+}
+
+static int
+init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size,
+ unsigned int cur_off, struct bio_vec **page_vec)
+{
+ struct bio_vec *bvec;
+ int i;
+
+ bvec = kcalloc(npages, sizeof(struct bio_vec), GFP_KERNEL);
+ if (!bvec)
+ return -ENOMEM;
+
+ for (i = 0; i < npages; i++) {
+ bvec[i].bv_page = pages[i];
+ bvec[i].bv_offset = (i == 0) ? cur_off : 0;
+ bvec[i].bv_len = min_t(unsigned int, PAGE_SIZE, data_size);
+ data_size -= bvec[i].bv_len;
+ }
+
+ if (data_size != 0) {
+ cifs_dbg(VFS, "%s: something went wrong\n", __func__);
+ kfree(bvec);
+ return -EIO;
+ }
+
+ *page_vec = bvec;
+ return 0;
+}
+
+static int
+handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
+ char *buf, unsigned int buf_len, struct page **pages,
+ unsigned int npages, unsigned int page_data_size,
+ bool is_offloaded)
+{
+ unsigned int data_offset;
+ unsigned int data_len;
+ unsigned int cur_off;
+ unsigned int cur_page_idx;
+ unsigned int pad_len;
+ struct cifs_readdata *rdata = mid->callback_data;
+ struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+ struct bio_vec *bvec = NULL;
+ struct iov_iter iter;
+ struct kvec iov;
+ int length;
+ bool use_rdma_mr = false;
+
+ if (shdr->Command != SMB2_READ) {
+ cifs_server_dbg(VFS, "only big read responses are supported\n");
+ return -ENOTSUPP;
+ }
+
+ if (server->ops->is_session_expired &&
+ server->ops->is_session_expired(buf)) {
+ if (!is_offloaded)
+ cifs_reconnect(server, true);
+ return -1;
+ }
+
+ if (server->ops->is_status_pending &&
+ server->ops->is_status_pending(buf, server))
+ return -1;
+
+ /* set up first two iov to get credits */
+ rdata->iov[0].iov_base = buf;
+ rdata->iov[0].iov_len = 0;
+ rdata->iov[1].iov_base = buf;
+ rdata->iov[1].iov_len =
+ min_t(unsigned int, buf_len, server->vals->read_rsp_size);
+ cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+ rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+ cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+ rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
+ rdata->result = server->ops->map_error(buf, true);
+ if (rdata->result != 0) {
+ cifs_dbg(FYI, "%s: server returned error %d\n",
+ __func__, rdata->result);
+ /* normal error on read response */
+ if (is_offloaded)
+ mid->mid_state = MID_RESPONSE_RECEIVED;
+ else
+ dequeue_mid(mid, false);
+ return 0;
+ }
+
+ data_offset = server->ops->read_data_offset(buf);
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ use_rdma_mr = rdata->mr;
+#endif
+ data_len = server->ops->read_data_length(buf, use_rdma_mr);
+
+ if (data_offset < server->vals->read_rsp_size) {
+ /*
+ * win2k8 sometimes sends an offset of 0 when the read
+ * is beyond the EOF. Treat it as if the data starts just after
+ * the header.
+ */
+ cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
+ __func__, data_offset);
+ data_offset = server->vals->read_rsp_size;
+ } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
+ /* data_offset is beyond the end of smallbuf */
+ cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
+ __func__, data_offset);
+ rdata->result = -EIO;
+ if (is_offloaded)
+ mid->mid_state = MID_RESPONSE_MALFORMED;
+ else
+ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+ pad_len = data_offset - server->vals->read_rsp_size;
+
+ if (buf_len <= data_offset) {
+ /* read response payload is in pages */
+ cur_page_idx = pad_len / PAGE_SIZE;
+ cur_off = pad_len % PAGE_SIZE;
+
+ if (cur_page_idx != 0) {
+ /* data offset is beyond the 1st page of response */
+ cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
+ __func__, data_offset);
+ rdata->result = -EIO;
+ if (is_offloaded)
+ mid->mid_state = MID_RESPONSE_MALFORMED;
+ else
+ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+ if (data_len > page_data_size - pad_len) {
+ /* data_len is corrupt -- discard frame */
+ rdata->result = -EIO;
+ if (is_offloaded)
+ mid->mid_state = MID_RESPONSE_MALFORMED;
+ else
+ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+ rdata->result = init_read_bvec(pages, npages, page_data_size,
+ cur_off, &bvec);
+ if (rdata->result != 0) {
+ if (is_offloaded)
+ mid->mid_state = MID_RESPONSE_MALFORMED;
+ else
+ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+ iov_iter_bvec(&iter, ITER_SOURCE, bvec, npages, data_len);
+ } else if (buf_len >= data_offset + data_len) {
+ /* read response payload is in buf */
+ WARN_ONCE(npages > 0, "read data can be either in buf or in pages");
+ iov.iov_base = buf + data_offset;
+ iov.iov_len = data_len;
+ iov_iter_kvec(&iter, ITER_SOURCE, &iov, 1, data_len);
+ } else {
+ /* read response payload cannot be in both buf and pages */
+ WARN_ONCE(1, "buf can not contain only a part of read data");
+ rdata->result = -EIO;
+ if (is_offloaded)
+ mid->mid_state = MID_RESPONSE_MALFORMED;
+ else
+ dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
+ length = rdata->copy_into_pages(server, rdata, &iter);
+
+ kfree(bvec);
+
+ if (length < 0)
+ return length;
+
+ if (is_offloaded)
+ mid->mid_state = MID_RESPONSE_RECEIVED;
+ else
+ dequeue_mid(mid, false);
+ return length;
+}
+
+struct smb2_decrypt_work {
+ struct work_struct decrypt;
+ struct TCP_Server_Info *server;
+ struct page **ppages;
+ char *buf;
+ unsigned int npages;
+ unsigned int len;
+};
+
+
+static void smb2_decrypt_offload(struct work_struct *work)
+{
+ struct smb2_decrypt_work *dw = container_of(work,
+ struct smb2_decrypt_work, decrypt);
+ int i, rc;
+ struct mid_q_entry *mid;
+
+ rc = decrypt_raw_data(dw->server, dw->buf, dw->server->vals->read_rsp_size,
+ dw->ppages, dw->npages, dw->len, true);
+ if (rc) {
+ cifs_dbg(VFS, "error decrypting rc=%d\n", rc);
+ goto free_pages;
+ }
+
+ dw->server->lstrp = jiffies;
+ mid = smb2_find_dequeue_mid(dw->server, dw->buf);
+ if (mid == NULL)
+ cifs_dbg(FYI, "mid not found\n");
+ else {
+ mid->decrypted = true;
+ rc = handle_read_data(dw->server, mid, dw->buf,
+ dw->server->vals->read_rsp_size,
+ dw->ppages, dw->npages, dw->len,
+ true);
+ if (rc >= 0) {
+#ifdef CONFIG_CIFS_STATS2
+ mid->when_received = jiffies;
+#endif
+ if (dw->server->ops->is_network_name_deleted)
+ dw->server->ops->is_network_name_deleted(dw->buf,
+ dw->server);
+
+ mid->callback(mid);
+ } else {
+ spin_lock(&dw->server->srv_lock);
+ if (dw->server->tcpStatus == CifsNeedReconnect) {
+ spin_lock(&dw->server->mid_lock);
+ mid->mid_state = MID_RETRY_NEEDED;
+ spin_unlock(&dw->server->mid_lock);
+ spin_unlock(&dw->server->srv_lock);
+ mid->callback(mid);
+ } else {
+ spin_lock(&dw->server->mid_lock);
+ mid->mid_state = MID_REQUEST_SUBMITTED;
+ mid->mid_flags &= ~(MID_DELETED);
+ list_add_tail(&mid->qhead,
+ &dw->server->pending_mid_q);
+ spin_unlock(&dw->server->mid_lock);
+ spin_unlock(&dw->server->srv_lock);
+ }
+ }
+ release_mid(mid);
+ }
+
+free_pages:
+ for (i = dw->npages-1; i >= 0; i--)
+ put_page(dw->ppages[i]);
+
+ kfree(dw->ppages);
+ cifs_small_buf_release(dw->buf);
+ kfree(dw);
+}
+
+
+static int
+receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
+ int *num_mids)
+{
+ char *buf = server->smallbuf;
+ struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
+ unsigned int npages;
+ struct page **pages;
+ unsigned int len;
+ unsigned int buflen = server->pdu_size;
+ int rc;
+ int i = 0;
+ struct smb2_decrypt_work *dw;
+
+ *num_mids = 1;
+ len = min_t(unsigned int, buflen, server->vals->read_rsp_size +
+ sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1;
+
+ rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len);
+ if (rc < 0)
+ return rc;
+ server->total_read += rc;
+
+ len = le32_to_cpu(tr_hdr->OriginalMessageSize) -
+ server->vals->read_rsp_size;
+ npages = DIV_ROUND_UP(len, PAGE_SIZE);
+
+ pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
+ if (!pages) {
+ rc = -ENOMEM;
+ goto discard_data;
+ }
+
+ for (; i < npages; i++) {
+ pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
+ if (!pages[i]) {
+ rc = -ENOMEM;
+ goto discard_data;
+ }
+ }
+
+ /* read read data into pages */
+ rc = read_data_into_pages(server, pages, npages, len);
+ if (rc)
+ goto free_pages;
+
+ rc = cifs_discard_remaining_data(server);
+ if (rc)
+ goto free_pages;
+
+ /*
+ * For large reads, offload to different thread for better performance,
+ * use more cores decrypting which can be expensive
+ */
+
+ if ((server->min_offload) && (server->in_flight > 1) &&
+ (server->pdu_size >= server->min_offload)) {
+ dw = kmalloc(sizeof(struct smb2_decrypt_work), GFP_KERNEL);
+ if (dw == NULL)
+ goto non_offloaded_decrypt;
+
+ dw->buf = server->smallbuf;
+ server->smallbuf = (char *)cifs_small_buf_get();
+
+ INIT_WORK(&dw->decrypt, smb2_decrypt_offload);
+
+ dw->npages = npages;
+ dw->server = server;
+ dw->ppages = pages;
+ dw->len = len;
+ queue_work(decrypt_wq, &dw->decrypt);
+ *num_mids = 0; /* worker thread takes care of finding mid */
+ return -1;
+ }
+
+non_offloaded_decrypt:
+ rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size,
+ pages, npages, len, false);
+ if (rc)
+ goto free_pages;
+
+ *mid = smb2_find_mid(server, buf);
+ if (*mid == NULL)
+ cifs_dbg(FYI, "mid not found\n");
+ else {
+ cifs_dbg(FYI, "mid found\n");
+ (*mid)->decrypted = true;
+ rc = handle_read_data(server, *mid, buf,
+ server->vals->read_rsp_size,
+ pages, npages, len, false);
+ if (rc >= 0) {
+ if (server->ops->is_network_name_deleted) {
+ server->ops->is_network_name_deleted(buf,
+ server);
+ }
+ }
+ }
+
+free_pages:
+ for (i = i - 1; i >= 0; i--)
+ put_page(pages[i]);
+ kfree(pages);
+ return rc;
+discard_data:
+ cifs_discard_remaining_data(server);
+ goto free_pages;
+}
+
+static int
+receive_encrypted_standard(struct TCP_Server_Info *server,
+ struct mid_q_entry **mids, char **bufs,
+ int *num_mids)
+{
+ int ret, length;
+ char *buf = server->smallbuf;
+ struct smb2_hdr *shdr;
+ unsigned int pdu_length = server->pdu_size;
+ unsigned int buf_size;
+ struct mid_q_entry *mid_entry;
+ int next_is_large;
+ char *next_buffer = NULL;
+
+ *num_mids = 0;
+
+ /* switch to large buffer if too big for a small one */
+ if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE) {
+ server->large_buf = true;
+ memcpy(server->bigbuf, buf, server->total_read);
+ buf = server->bigbuf;
+ }
+
+ /* now read the rest */
+ length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
+ pdu_length - HEADER_SIZE(server) + 1);
+ if (length < 0)
+ return length;
+ server->total_read += length;
+
+ buf_size = pdu_length - sizeof(struct smb2_transform_hdr);
+ length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0, false);
+ if (length)
+ return length;
+
+ next_is_large = server->large_buf;
+one_more:
+ shdr = (struct smb2_hdr *)buf;
+ if (shdr->NextCommand) {
+ if (next_is_large)
+ next_buffer = (char *)cifs_buf_get();
+ else
+ next_buffer = (char *)cifs_small_buf_get();
+ memcpy(next_buffer,
+ buf + le32_to_cpu(shdr->NextCommand),
+ pdu_length - le32_to_cpu(shdr->NextCommand));
+ }
+
+ mid_entry = smb2_find_mid(server, buf);
+ if (mid_entry == NULL)
+ cifs_dbg(FYI, "mid not found\n");
+ else {
+ cifs_dbg(FYI, "mid found\n");
+ mid_entry->decrypted = true;
+ mid_entry->resp_buf_size = server->pdu_size;
+ }
+
+ if (*num_mids >= MAX_COMPOUND) {
+ cifs_server_dbg(VFS, "too many PDUs in compound\n");
+ return -1;
+ }
+ bufs[*num_mids] = buf;
+ mids[(*num_mids)++] = mid_entry;
+
+ if (mid_entry && mid_entry->handle)
+ ret = mid_entry->handle(server, mid_entry);
+ else
+ ret = cifs_handle_standard(server, mid_entry);
+
+ if (ret == 0 && shdr->NextCommand) {
+ pdu_length -= le32_to_cpu(shdr->NextCommand);
+ server->large_buf = next_is_large;
+ if (next_is_large)
+ server->bigbuf = buf = next_buffer;
+ else
+ server->smallbuf = buf = next_buffer;
+ goto one_more;
+ } else if (ret != 0) {
+ /*
+ * ret != 0 here means that we didn't get to handle_mid() thus
+ * server->smallbuf and server->bigbuf are still valid. We need
+ * to free next_buffer because it is not going to be used
+ * anywhere.
+ */
+ if (next_is_large)
+ free_rsp_buf(CIFS_LARGE_BUFFER, next_buffer);
+ else
+ free_rsp_buf(CIFS_SMALL_BUFFER, next_buffer);
+ }
+
+ return ret;
+}
+
+static int
+smb3_receive_transform(struct TCP_Server_Info *server,
+ struct mid_q_entry **mids, char **bufs, int *num_mids)
+{
+ char *buf = server->smallbuf;
+ unsigned int pdu_length = server->pdu_size;
+ struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
+ unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
+
+ if (pdu_length < sizeof(struct smb2_transform_hdr) +
+ sizeof(struct smb2_hdr)) {
+ cifs_server_dbg(VFS, "Transform message is too small (%u)\n",
+ pdu_length);
+ cifs_reconnect(server, true);
+ return -ECONNABORTED;
+ }
+
+ if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) {
+ cifs_server_dbg(VFS, "Transform message is broken\n");
+ cifs_reconnect(server, true);
+ return -ECONNABORTED;
+ }
+
+ /* TODO: add support for compounds containing READ. */
+ if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) {
+ return receive_encrypted_read(server, &mids[0], num_mids);
+ }
+
+ return receive_encrypted_standard(server, mids, bufs, num_mids);
+}
+
+int
+smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+ char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
+
+ return handle_read_data(server, mid, buf, server->pdu_size,
+ NULL, 0, 0, false);
+}
+
+static int
+smb2_next_header(char *buf)
+{
+ struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
+ struct smb2_transform_hdr *t_hdr = (struct smb2_transform_hdr *)buf;
+
+ if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM)
+ return sizeof(struct smb2_transform_hdr) +
+ le32_to_cpu(t_hdr->OriginalMessageSize);
+
+ return le32_to_cpu(hdr->NextCommand);
+}
+
+static int
+smb2_make_node(unsigned int xid, struct inode *inode,
+ struct dentry *dentry, struct cifs_tcon *tcon,
+ const char *full_path, umode_t mode, dev_t dev)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ int rc = -EPERM;
+ struct cifs_open_info_data buf = {};
+ struct cifs_io_parms io_parms = {0};
+ __u32 oplock = 0;
+ struct cifs_fid fid;
+ struct cifs_open_parms oparms;
+ unsigned int bytes_written;
+ struct win_dev *pdev;
+ struct kvec iov[2];
+
+ /*
+ * Check if mounted with mount parm 'sfu' mount parm.
+ * SFU emulation should work with all servers, but only
+ * supports block and char device (no socket & fifo),
+ * and was used by default in earlier versions of Windows
+ */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
+ return rc;
+
+ /*
+ * TODO: Add ability to create instead via reparse point. Windows (e.g.
+ * their current NFS server) uses this approach to expose special files
+ * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
+ */
+
+ if (!S_ISCHR(mode) && !S_ISBLK(mode))
+ return rc;
+
+ cifs_dbg(FYI, "sfu compat create special file\n");
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = GENERIC_WRITE,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
+ CREATE_OPTION_SPECIAL),
+ .disposition = FILE_CREATE,
+ .path = full_path,
+ .fid = &fid,
+ };
+
+ if (tcon->ses->server->oplocks)
+ oplock = REQ_OPLOCK;
+ else
+ oplock = 0;
+ rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
+ if (rc)
+ return rc;
+
+ /*
+ * BB Do not bother to decode buf since no local inode yet to put
+ * timestamps in, but we can reuse it safely.
+ */
+
+ pdev = (struct win_dev *)&buf.fi;
+ io_parms.pid = current->tgid;
+ io_parms.tcon = tcon;
+ io_parms.offset = 0;
+ io_parms.length = sizeof(struct win_dev);
+ iov[1].iov_base = &buf.fi;
+ iov[1].iov_len = sizeof(struct win_dev);
+ if (S_ISCHR(mode)) {
+ memcpy(pdev->type, "IntxCHR", 8);
+ pdev->major = cpu_to_le64(MAJOR(dev));
+ pdev->minor = cpu_to_le64(MINOR(dev));
+ rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
+ &bytes_written, iov, 1);
+ } else if (S_ISBLK(mode)) {
+ memcpy(pdev->type, "IntxBLK", 8);
+ pdev->major = cpu_to_le64(MAJOR(dev));
+ pdev->minor = cpu_to_le64(MINOR(dev));
+ rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
+ &bytes_written, iov, 1);
+ }
+ tcon->ses->server->ops->close(xid, tcon, &fid);
+ d_drop(dentry);
+
+ /* FIXME: add code here to set EAs */
+
+ cifs_free_open_info(&buf);
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+struct smb_version_operations smb20_operations = {
+ .compare_fids = smb2_compare_fids,
+ .setup_request = smb2_setup_request,
+ .setup_async_request = smb2_setup_async_request,
+ .check_receive = smb2_check_receive,
+ .add_credits = smb2_add_credits,
+ .set_credits = smb2_set_credits,
+ .get_credits_field = smb2_get_credits_field,
+ .get_credits = smb2_get_credits,
+ .wait_mtu_credits = cifs_wait_mtu_credits,
+ .get_next_mid = smb2_get_next_mid,
+ .revert_current_mid = smb2_revert_current_mid,
+ .read_data_offset = smb2_read_data_offset,
+ .read_data_length = smb2_read_data_length,
+ .map_error = map_smb2_to_linux_error,
+ .find_mid = smb2_find_mid,
+ .check_message = smb2_check_message,
+ .dump_detail = smb2_dump_detail,
+ .clear_stats = smb2_clear_stats,
+ .print_stats = smb2_print_stats,
+ .is_oplock_break = smb2_is_valid_oplock_break,
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
+ .downgrade_oplock = smb2_downgrade_oplock,
+ .need_neg = smb2_need_neg,
+ .negotiate = smb2_negotiate,
+ .negotiate_wsize = smb2_negotiate_wsize,
+ .negotiate_rsize = smb2_negotiate_rsize,
+ .sess_setup = SMB2_sess_setup,
+ .logoff = SMB2_logoff,
+ .tree_connect = SMB2_tcon,
+ .tree_disconnect = SMB2_tdis,
+ .qfs_tcon = smb2_qfs_tcon,
+ .is_path_accessible = smb2_is_path_accessible,
+ .can_echo = smb2_can_echo,
+ .echo = SMB2_echo,
+ .query_path_info = smb2_query_path_info,
+ .get_srv_inum = smb2_get_srv_inum,
+ .query_file_info = smb2_query_file_info,
+ .set_path_size = smb2_set_path_size,
+ .set_file_size = smb2_set_file_size,
+ .set_file_info = smb2_set_file_info,
+ .set_compression = smb2_set_compression,
+ .mkdir = smb2_mkdir,
+ .mkdir_setinfo = smb2_mkdir_setinfo,
+ .rmdir = smb2_rmdir,
+ .unlink = smb2_unlink,
+ .rename = smb2_rename_path,
+ .create_hardlink = smb2_create_hardlink,
+ .query_symlink = smb2_query_symlink,
+ .query_mf_symlink = smb3_query_mf_symlink,
+ .create_mf_symlink = smb3_create_mf_symlink,
+ .open = smb2_open_file,
+ .set_fid = smb2_set_fid,
+ .close = smb2_close_file,
+ .flush = smb2_flush_file,
+ .async_readv = smb2_async_readv,
+ .async_writev = smb2_async_writev,
+ .sync_read = smb2_sync_read,
+ .sync_write = smb2_sync_write,
+ .query_dir_first = smb2_query_dir_first,
+ .query_dir_next = smb2_query_dir_next,
+ .close_dir = smb2_close_dir,
+ .calc_smb_size = smb2_calc_size,
+ .is_status_pending = smb2_is_status_pending,
+ .is_session_expired = smb2_is_session_expired,
+ .oplock_response = smb2_oplock_response,
+ .queryfs = smb2_queryfs,
+ .mand_lock = smb2_mand_lock,
+ .mand_unlock_range = smb2_unlock_range,
+ .push_mand_locks = smb2_push_mandatory_locks,
+ .get_lease_key = smb2_get_lease_key,
+ .set_lease_key = smb2_set_lease_key,
+ .new_lease_key = smb2_new_lease_key,
+ .calc_signature = smb2_calc_signature,
+ .is_read_op = smb2_is_read_op,
+ .set_oplock_level = smb2_set_oplock_level,
+ .create_lease_buf = smb2_create_lease_buf,
+ .parse_lease_buf = smb2_parse_lease_buf,
+ .copychunk_range = smb2_copychunk_range,
+ .wp_retry_size = smb2_wp_retry_size,
+ .dir_needs_close = smb2_dir_needs_close,
+ .get_dfs_refer = smb2_get_dfs_refer,
+ .select_sectype = smb2_select_sectype,
+#ifdef CONFIG_CIFS_XATTR
+ .query_all_EAs = smb2_query_eas,
+ .set_EA = smb2_set_ea,
+#endif /* CIFS_XATTR */
+ .get_acl = get_smb2_acl,
+ .get_acl_by_fid = get_smb2_acl_by_fid,
+ .set_acl = set_smb2_acl,
+ .next_header = smb2_next_header,
+ .ioctl_query_info = smb2_ioctl_query_info,
+ .make_node = smb2_make_node,
+ .fiemap = smb3_fiemap,
+ .llseek = smb3_llseek,
+ .is_status_io_timeout = smb2_is_status_io_timeout,
+ .is_network_name_deleted = smb2_is_network_name_deleted,
+};
+#endif /* CIFS_ALLOW_INSECURE_LEGACY */
+
+struct smb_version_operations smb21_operations = {
+ .compare_fids = smb2_compare_fids,
+ .setup_request = smb2_setup_request,
+ .setup_async_request = smb2_setup_async_request,
+ .check_receive = smb2_check_receive,
+ .add_credits = smb2_add_credits,
+ .set_credits = smb2_set_credits,
+ .get_credits_field = smb2_get_credits_field,
+ .get_credits = smb2_get_credits,
+ .wait_mtu_credits = smb2_wait_mtu_credits,
+ .adjust_credits = smb2_adjust_credits,
+ .get_next_mid = smb2_get_next_mid,
+ .revert_current_mid = smb2_revert_current_mid,
+ .read_data_offset = smb2_read_data_offset,
+ .read_data_length = smb2_read_data_length,
+ .map_error = map_smb2_to_linux_error,
+ .find_mid = smb2_find_mid,
+ .check_message = smb2_check_message,
+ .dump_detail = smb2_dump_detail,
+ .clear_stats = smb2_clear_stats,
+ .print_stats = smb2_print_stats,
+ .is_oplock_break = smb2_is_valid_oplock_break,
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
+ .downgrade_oplock = smb2_downgrade_oplock,
+ .need_neg = smb2_need_neg,
+ .negotiate = smb2_negotiate,
+ .negotiate_wsize = smb2_negotiate_wsize,
+ .negotiate_rsize = smb2_negotiate_rsize,
+ .sess_setup = SMB2_sess_setup,
+ .logoff = SMB2_logoff,
+ .tree_connect = SMB2_tcon,
+ .tree_disconnect = SMB2_tdis,
+ .qfs_tcon = smb2_qfs_tcon,
+ .is_path_accessible = smb2_is_path_accessible,
+ .can_echo = smb2_can_echo,
+ .echo = SMB2_echo,
+ .query_path_info = smb2_query_path_info,
+ .get_srv_inum = smb2_get_srv_inum,
+ .query_file_info = smb2_query_file_info,
+ .set_path_size = smb2_set_path_size,
+ .set_file_size = smb2_set_file_size,
+ .set_file_info = smb2_set_file_info,
+ .set_compression = smb2_set_compression,
+ .mkdir = smb2_mkdir,
+ .mkdir_setinfo = smb2_mkdir_setinfo,
+ .rmdir = smb2_rmdir,
+ .unlink = smb2_unlink,
+ .rename = smb2_rename_path,
+ .create_hardlink = smb2_create_hardlink,
+ .query_symlink = smb2_query_symlink,
+ .query_mf_symlink = smb3_query_mf_symlink,
+ .create_mf_symlink = smb3_create_mf_symlink,
+ .open = smb2_open_file,
+ .set_fid = smb2_set_fid,
+ .close = smb2_close_file,
+ .flush = smb2_flush_file,
+ .async_readv = smb2_async_readv,
+ .async_writev = smb2_async_writev,
+ .sync_read = smb2_sync_read,
+ .sync_write = smb2_sync_write,
+ .query_dir_first = smb2_query_dir_first,
+ .query_dir_next = smb2_query_dir_next,
+ .close_dir = smb2_close_dir,
+ .calc_smb_size = smb2_calc_size,
+ .is_status_pending = smb2_is_status_pending,
+ .is_session_expired = smb2_is_session_expired,
+ .oplock_response = smb2_oplock_response,
+ .queryfs = smb2_queryfs,
+ .mand_lock = smb2_mand_lock,
+ .mand_unlock_range = smb2_unlock_range,
+ .push_mand_locks = smb2_push_mandatory_locks,
+ .get_lease_key = smb2_get_lease_key,
+ .set_lease_key = smb2_set_lease_key,
+ .new_lease_key = smb2_new_lease_key,
+ .calc_signature = smb2_calc_signature,
+ .is_read_op = smb21_is_read_op,
+ .set_oplock_level = smb21_set_oplock_level,
+ .create_lease_buf = smb2_create_lease_buf,
+ .parse_lease_buf = smb2_parse_lease_buf,
+ .copychunk_range = smb2_copychunk_range,
+ .wp_retry_size = smb2_wp_retry_size,
+ .dir_needs_close = smb2_dir_needs_close,
+ .enum_snapshots = smb3_enum_snapshots,
+ .notify = smb3_notify,
+ .get_dfs_refer = smb2_get_dfs_refer,
+ .select_sectype = smb2_select_sectype,
+#ifdef CONFIG_CIFS_XATTR
+ .query_all_EAs = smb2_query_eas,
+ .set_EA = smb2_set_ea,
+#endif /* CIFS_XATTR */
+ .get_acl = get_smb2_acl,
+ .get_acl_by_fid = get_smb2_acl_by_fid,
+ .set_acl = set_smb2_acl,
+ .next_header = smb2_next_header,
+ .ioctl_query_info = smb2_ioctl_query_info,
+ .make_node = smb2_make_node,
+ .fiemap = smb3_fiemap,
+ .llseek = smb3_llseek,
+ .is_status_io_timeout = smb2_is_status_io_timeout,
+ .is_network_name_deleted = smb2_is_network_name_deleted,
+};
+
+struct smb_version_operations smb30_operations = {
+ .compare_fids = smb2_compare_fids,
+ .setup_request = smb2_setup_request,
+ .setup_async_request = smb2_setup_async_request,
+ .check_receive = smb2_check_receive,
+ .add_credits = smb2_add_credits,
+ .set_credits = smb2_set_credits,
+ .get_credits_field = smb2_get_credits_field,
+ .get_credits = smb2_get_credits,
+ .wait_mtu_credits = smb2_wait_mtu_credits,
+ .adjust_credits = smb2_adjust_credits,
+ .get_next_mid = smb2_get_next_mid,
+ .revert_current_mid = smb2_revert_current_mid,
+ .read_data_offset = smb2_read_data_offset,
+ .read_data_length = smb2_read_data_length,
+ .map_error = map_smb2_to_linux_error,
+ .find_mid = smb2_find_mid,
+ .check_message = smb2_check_message,
+ .dump_detail = smb2_dump_detail,
+ .clear_stats = smb2_clear_stats,
+ .print_stats = smb2_print_stats,
+ .dump_share_caps = smb2_dump_share_caps,
+ .is_oplock_break = smb2_is_valid_oplock_break,
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
+ .downgrade_oplock = smb3_downgrade_oplock,
+ .need_neg = smb2_need_neg,
+ .negotiate = smb2_negotiate,
+ .negotiate_wsize = smb3_negotiate_wsize,
+ .negotiate_rsize = smb3_negotiate_rsize,
+ .sess_setup = SMB2_sess_setup,
+ .logoff = SMB2_logoff,
+ .tree_connect = SMB2_tcon,
+ .tree_disconnect = SMB2_tdis,
+ .qfs_tcon = smb3_qfs_tcon,
+ .is_path_accessible = smb2_is_path_accessible,
+ .can_echo = smb2_can_echo,
+ .echo = SMB2_echo,
+ .query_path_info = smb2_query_path_info,
+ /* WSL tags introduced long after smb2.1, enable for SMB3, 3.11 only */
+ .query_reparse_tag = smb2_query_reparse_tag,
+ .get_srv_inum = smb2_get_srv_inum,
+ .query_file_info = smb2_query_file_info,
+ .set_path_size = smb2_set_path_size,
+ .set_file_size = smb2_set_file_size,
+ .set_file_info = smb2_set_file_info,
+ .set_compression = smb2_set_compression,
+ .mkdir = smb2_mkdir,
+ .mkdir_setinfo = smb2_mkdir_setinfo,
+ .rmdir = smb2_rmdir,
+ .unlink = smb2_unlink,
+ .rename = smb2_rename_path,
+ .create_hardlink = smb2_create_hardlink,
+ .query_symlink = smb2_query_symlink,
+ .query_mf_symlink = smb3_query_mf_symlink,
+ .create_mf_symlink = smb3_create_mf_symlink,
+ .open = smb2_open_file,
+ .set_fid = smb2_set_fid,
+ .close = smb2_close_file,
+ .close_getattr = smb2_close_getattr,
+ .flush = smb2_flush_file,
+ .async_readv = smb2_async_readv,
+ .async_writev = smb2_async_writev,
+ .sync_read = smb2_sync_read,
+ .sync_write = smb2_sync_write,
+ .query_dir_first = smb2_query_dir_first,
+ .query_dir_next = smb2_query_dir_next,
+ .close_dir = smb2_close_dir,
+ .calc_smb_size = smb2_calc_size,
+ .is_status_pending = smb2_is_status_pending,
+ .is_session_expired = smb2_is_session_expired,
+ .oplock_response = smb2_oplock_response,
+ .queryfs = smb2_queryfs,
+ .mand_lock = smb2_mand_lock,
+ .mand_unlock_range = smb2_unlock_range,
+ .push_mand_locks = smb2_push_mandatory_locks,
+ .get_lease_key = smb2_get_lease_key,
+ .set_lease_key = smb2_set_lease_key,
+ .new_lease_key = smb2_new_lease_key,
+ .generate_signingkey = generate_smb30signingkey,
+ .calc_signature = smb3_calc_signature,
+ .set_integrity = smb3_set_integrity,
+ .is_read_op = smb21_is_read_op,
+ .set_oplock_level = smb3_set_oplock_level,
+ .create_lease_buf = smb3_create_lease_buf,
+ .parse_lease_buf = smb3_parse_lease_buf,
+ .copychunk_range = smb2_copychunk_range,
+ .duplicate_extents = smb2_duplicate_extents,
+ .validate_negotiate = smb3_validate_negotiate,
+ .wp_retry_size = smb2_wp_retry_size,
+ .dir_needs_close = smb2_dir_needs_close,
+ .fallocate = smb3_fallocate,
+ .enum_snapshots = smb3_enum_snapshots,
+ .notify = smb3_notify,
+ .init_transform_rq = smb3_init_transform_rq,
+ .is_transform_hdr = smb3_is_transform_hdr,
+ .receive_transform = smb3_receive_transform,
+ .get_dfs_refer = smb2_get_dfs_refer,
+ .select_sectype = smb2_select_sectype,
+#ifdef CONFIG_CIFS_XATTR
+ .query_all_EAs = smb2_query_eas,
+ .set_EA = smb2_set_ea,
+#endif /* CIFS_XATTR */
+ .get_acl = get_smb2_acl,
+ .get_acl_by_fid = get_smb2_acl_by_fid,
+ .set_acl = set_smb2_acl,
+ .next_header = smb2_next_header,
+ .ioctl_query_info = smb2_ioctl_query_info,
+ .make_node = smb2_make_node,
+ .fiemap = smb3_fiemap,
+ .llseek = smb3_llseek,
+ .is_status_io_timeout = smb2_is_status_io_timeout,
+ .is_network_name_deleted = smb2_is_network_name_deleted,
+};
+
+struct smb_version_operations smb311_operations = {
+ .compare_fids = smb2_compare_fids,
+ .setup_request = smb2_setup_request,
+ .setup_async_request = smb2_setup_async_request,
+ .check_receive = smb2_check_receive,
+ .add_credits = smb2_add_credits,
+ .set_credits = smb2_set_credits,
+ .get_credits_field = smb2_get_credits_field,
+ .get_credits = smb2_get_credits,
+ .wait_mtu_credits = smb2_wait_mtu_credits,
+ .adjust_credits = smb2_adjust_credits,
+ .get_next_mid = smb2_get_next_mid,
+ .revert_current_mid = smb2_revert_current_mid,
+ .read_data_offset = smb2_read_data_offset,
+ .read_data_length = smb2_read_data_length,
+ .map_error = map_smb2_to_linux_error,
+ .find_mid = smb2_find_mid,
+ .check_message = smb2_check_message,
+ .dump_detail = smb2_dump_detail,
+ .clear_stats = smb2_clear_stats,
+ .print_stats = smb2_print_stats,
+ .dump_share_caps = smb2_dump_share_caps,
+ .is_oplock_break = smb2_is_valid_oplock_break,
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
+ .downgrade_oplock = smb3_downgrade_oplock,
+ .need_neg = smb2_need_neg,
+ .negotiate = smb2_negotiate,
+ .negotiate_wsize = smb3_negotiate_wsize,
+ .negotiate_rsize = smb3_negotiate_rsize,
+ .sess_setup = SMB2_sess_setup,
+ .logoff = SMB2_logoff,
+ .tree_connect = SMB2_tcon,
+ .tree_disconnect = SMB2_tdis,
+ .qfs_tcon = smb3_qfs_tcon,
+ .is_path_accessible = smb2_is_path_accessible,
+ .can_echo = smb2_can_echo,
+ .echo = SMB2_echo,
+ .query_path_info = smb2_query_path_info,
+ .query_reparse_tag = smb2_query_reparse_tag,
+ .get_srv_inum = smb2_get_srv_inum,
+ .query_file_info = smb2_query_file_info,
+ .set_path_size = smb2_set_path_size,
+ .set_file_size = smb2_set_file_size,
+ .set_file_info = smb2_set_file_info,
+ .set_compression = smb2_set_compression,
+ .mkdir = smb2_mkdir,
+ .mkdir_setinfo = smb2_mkdir_setinfo,
+ .posix_mkdir = smb311_posix_mkdir,
+ .rmdir = smb2_rmdir,
+ .unlink = smb2_unlink,
+ .rename = smb2_rename_path,
+ .create_hardlink = smb2_create_hardlink,
+ .query_symlink = smb2_query_symlink,
+ .query_mf_symlink = smb3_query_mf_symlink,
+ .create_mf_symlink = smb3_create_mf_symlink,
+ .open = smb2_open_file,
+ .set_fid = smb2_set_fid,
+ .close = smb2_close_file,
+ .close_getattr = smb2_close_getattr,
+ .flush = smb2_flush_file,
+ .async_readv = smb2_async_readv,
+ .async_writev = smb2_async_writev,
+ .sync_read = smb2_sync_read,
+ .sync_write = smb2_sync_write,
+ .query_dir_first = smb2_query_dir_first,
+ .query_dir_next = smb2_query_dir_next,
+ .close_dir = smb2_close_dir,
+ .calc_smb_size = smb2_calc_size,
+ .is_status_pending = smb2_is_status_pending,
+ .is_session_expired = smb2_is_session_expired,
+ .oplock_response = smb2_oplock_response,
+ .queryfs = smb311_queryfs,
+ .mand_lock = smb2_mand_lock,
+ .mand_unlock_range = smb2_unlock_range,
+ .push_mand_locks = smb2_push_mandatory_locks,
+ .get_lease_key = smb2_get_lease_key,
+ .set_lease_key = smb2_set_lease_key,
+ .new_lease_key = smb2_new_lease_key,
+ .generate_signingkey = generate_smb311signingkey,
+ .calc_signature = smb3_calc_signature,
+ .set_integrity = smb3_set_integrity,
+ .is_read_op = smb21_is_read_op,
+ .set_oplock_level = smb3_set_oplock_level,
+ .create_lease_buf = smb3_create_lease_buf,
+ .parse_lease_buf = smb3_parse_lease_buf,
+ .copychunk_range = smb2_copychunk_range,
+ .duplicate_extents = smb2_duplicate_extents,
+/* .validate_negotiate = smb3_validate_negotiate, */ /* not used in 3.11 */
+ .wp_retry_size = smb2_wp_retry_size,
+ .dir_needs_close = smb2_dir_needs_close,
+ .fallocate = smb3_fallocate,
+ .enum_snapshots = smb3_enum_snapshots,
+ .notify = smb3_notify,
+ .init_transform_rq = smb3_init_transform_rq,
+ .is_transform_hdr = smb3_is_transform_hdr,
+ .receive_transform = smb3_receive_transform,
+ .get_dfs_refer = smb2_get_dfs_refer,
+ .select_sectype = smb2_select_sectype,
+#ifdef CONFIG_CIFS_XATTR
+ .query_all_EAs = smb2_query_eas,
+ .set_EA = smb2_set_ea,
+#endif /* CIFS_XATTR */
+ .get_acl = get_smb2_acl,
+ .get_acl_by_fid = get_smb2_acl_by_fid,
+ .set_acl = set_smb2_acl,
+ .next_header = smb2_next_header,
+ .ioctl_query_info = smb2_ioctl_query_info,
+ .make_node = smb2_make_node,
+ .fiemap = smb3_fiemap,
+ .llseek = smb3_llseek,
+ .is_status_io_timeout = smb2_is_status_io_timeout,
+ .is_network_name_deleted = smb2_is_network_name_deleted,
+};
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+struct smb_version_values smb20_values = {
+ .version_string = SMB20_VERSION_STRING,
+ .protocol_id = SMB20_PROT_ID,
+ .req_capabilities = 0, /* MBZ */
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .header_preamble_size = 0,
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .create_lease_size = sizeof(struct create_lease),
+};
+#endif /* ALLOW_INSECURE_LEGACY */
+
+struct smb_version_values smb21_values = {
+ .version_string = SMB21_VERSION_STRING,
+ .protocol_id = SMB21_PROT_ID,
+ .req_capabilities = 0, /* MBZ on negotiate req until SMB3 dialect */
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .header_preamble_size = 0,
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .create_lease_size = sizeof(struct create_lease),
+};
+
+struct smb_version_values smb3any_values = {
+ .version_string = SMB3ANY_VERSION_STRING,
+ .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
+ .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .header_preamble_size = 0,
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .create_lease_size = sizeof(struct create_lease_v2),
+};
+
+struct smb_version_values smbdefault_values = {
+ .version_string = SMBDEFAULT_VERSION_STRING,
+ .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
+ .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .header_preamble_size = 0,
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .create_lease_size = sizeof(struct create_lease_v2),
+};
+
+struct smb_version_values smb30_values = {
+ .version_string = SMB30_VERSION_STRING,
+ .protocol_id = SMB30_PROT_ID,
+ .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .header_preamble_size = 0,
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .create_lease_size = sizeof(struct create_lease_v2),
+};
+
+struct smb_version_values smb302_values = {
+ .version_string = SMB302_VERSION_STRING,
+ .protocol_id = SMB302_PROT_ID,
+ .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .header_preamble_size = 0,
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .create_lease_size = sizeof(struct create_lease_v2),
+};
+
+struct smb_version_values smb311_values = {
+ .version_string = SMB311_VERSION_STRING,
+ .protocol_id = SMB311_PROT_ID,
+ .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION | SMB2_GLOBAL_CAP_DIRECTORY_LEASING,
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .header_preamble_size = 0,
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
+ .create_lease_size = sizeof(struct create_lease_v2),
+};
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
new file mode 100644
index 000000000000..3ca593cdda76
--- /dev/null
+++ b/fs/smb/client/smb2pdu.c
@@ -0,0 +1,5722 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2009, 2013
+ * Etersoft, 2012
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Pavel Shilovsky (pshilovsky@samba.org) 2012
+ *
+ * Contains the routines for constructing the SMB2 PDUs themselves
+ *
+ */
+
+ /* SMB2 PDU handling routines here - except for leftovers (eg session setup) */
+ /* Note that there are handle based routines which must be */
+ /* treated slightly differently for reconnection purposes since we never */
+ /* want to reuse a stale file handle and only the caller knows the file info */
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/vfs.h>
+#include <linux/task_io_accounting_ops.h>
+#include <linux/uaccess.h>
+#include <linux/uuid.h>
+#include <linux/pagemap.h>
+#include <linux/xattr.h>
+#include "cifsglob.h"
+#include "cifsacl.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "ntlmssp.h"
+#include "smb2status.h"
+#include "smb2glob.h"
+#include "cifspdu.h"
+#include "cifs_spnego.h"
+#include "smbdirect.h"
+#include "trace.h"
+#ifdef CONFIG_CIFS_DFS_UPCALL
+#include "dfs_cache.h"
+#endif
+#include "cached_dir.h"
+
+/*
+ * The following table defines the expected "StructureSize" of SMB2 requests
+ * in order by SMB2 command. This is similar to "wct" in SMB/CIFS requests.
+ *
+ * Note that commands are defined in smb2pdu.h in le16 but the array below is
+ * indexed by command in host byte order.
+ */
+static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
+ /* SMB2_NEGOTIATE */ 36,
+ /* SMB2_SESSION_SETUP */ 25,
+ /* SMB2_LOGOFF */ 4,
+ /* SMB2_TREE_CONNECT */ 9,
+ /* SMB2_TREE_DISCONNECT */ 4,
+ /* SMB2_CREATE */ 57,
+ /* SMB2_CLOSE */ 24,
+ /* SMB2_FLUSH */ 24,
+ /* SMB2_READ */ 49,
+ /* SMB2_WRITE */ 49,
+ /* SMB2_LOCK */ 48,
+ /* SMB2_IOCTL */ 57,
+ /* SMB2_CANCEL */ 4,
+ /* SMB2_ECHO */ 4,
+ /* SMB2_QUERY_DIRECTORY */ 33,
+ /* SMB2_CHANGE_NOTIFY */ 32,
+ /* SMB2_QUERY_INFO */ 41,
+ /* SMB2_SET_INFO */ 33,
+ /* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */
+};
+
+int smb3_encryption_required(const struct cifs_tcon *tcon)
+{
+ if (!tcon || !tcon->ses)
+ return 0;
+ if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
+ (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
+ return 1;
+ if (tcon->seal &&
+ (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
+ return 1;
+ return 0;
+}
+
+static void
+smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd,
+ const struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server)
+{
+ shdr->ProtocolId = SMB2_PROTO_NUMBER;
+ shdr->StructureSize = cpu_to_le16(64);
+ shdr->Command = smb2_cmd;
+ if (server) {
+ spin_lock(&server->req_lock);
+ /* Request up to 10 credits but don't go over the limit. */
+ if (server->credits >= server->max_credits)
+ shdr->CreditRequest = cpu_to_le16(0);
+ else
+ shdr->CreditRequest = cpu_to_le16(
+ min_t(int, server->max_credits -
+ server->credits, 10));
+ spin_unlock(&server->req_lock);
+ } else {
+ shdr->CreditRequest = cpu_to_le16(2);
+ }
+ shdr->Id.SyncId.ProcessId = cpu_to_le32((__u16)current->tgid);
+
+ if (!tcon)
+ goto out;
+
+ /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */
+ /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */
+ if (server && (server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
+ shdr->CreditCharge = cpu_to_le16(1);
+ /* else CreditCharge MBZ */
+
+ shdr->Id.SyncId.TreeId = cpu_to_le32(tcon->tid);
+ /* Uid is not converted */
+ if (tcon->ses)
+ shdr->SessionId = cpu_to_le64(tcon->ses->Suid);
+
+ /*
+ * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have
+ * to pass the path on the Open SMB prefixed by \\server\share.
+ * Not sure when we would need to do the augmented path (if ever) and
+ * setting this flag breaks the SMB2 open operation since it is
+ * illegal to send an empty path name (without \\server\share prefix)
+ * when the DFS flag is set in the SMB open header. We could
+ * consider setting the flag on all operations other than open
+ * but it is safer to net set it for now.
+ */
+/* if (tcon->share_flags & SHI1005_FLAGS_DFS)
+ shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */
+
+ if (server && server->sign && !smb3_encryption_required(tcon))
+ shdr->Flags |= SMB2_FLAGS_SIGNED;
+out:
+ return;
+}
+
+static int
+smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server)
+{
+ int rc = 0;
+ struct nls_table *nls_codepage = NULL;
+ struct cifs_ses *ses;
+
+ /*
+ * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
+ * check for tcp and smb session status done differently
+ * for those three - in the calling routine.
+ */
+ if (tcon == NULL)
+ return 0;
+
+ /*
+ * Need to also skip SMB2_IOCTL because it is used for checking nested dfs links in
+ * cifs_tree_connect().
+ */
+ if (smb2_command == SMB2_TREE_CONNECT || smb2_command == SMB2_IOCTL)
+ return 0;
+
+ spin_lock(&tcon->tc_lock);
+ if (tcon->status == TID_EXITING) {
+ /*
+ * only tree disconnect allowed when disconnecting ...
+ */
+ if (smb2_command != SMB2_TREE_DISCONNECT) {
+ spin_unlock(&tcon->tc_lock);
+ cifs_dbg(FYI, "can not send cmd %d while umounting\n",
+ smb2_command);
+ return -ENODEV;
+ }
+ }
+ spin_unlock(&tcon->tc_lock);
+
+ ses = tcon->ses;
+ if (!ses)
+ return -EIO;
+ spin_lock(&ses->ses_lock);
+ if (ses->ses_status == SES_EXITING) {
+ spin_unlock(&ses->ses_lock);
+ return -EIO;
+ }
+ spin_unlock(&ses->ses_lock);
+ if (!ses->server || !server)
+ return -EIO;
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsNeedReconnect) {
+ /*
+ * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE
+ * here since they are implicitly done when session drops.
+ */
+ switch (smb2_command) {
+ /*
+ * BB Should we keep oplock break and add flush to exceptions?
+ */
+ case SMB2_TREE_DISCONNECT:
+ case SMB2_CANCEL:
+ case SMB2_CLOSE:
+ case SMB2_OPLOCK_BREAK:
+ spin_unlock(&server->srv_lock);
+ return -EAGAIN;
+ }
+ }
+ spin_unlock(&server->srv_lock);
+
+again:
+ rc = cifs_wait_for_server_reconnect(server, tcon->retry);
+ if (rc)
+ return rc;
+
+ spin_lock(&ses->chan_lock);
+ if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) {
+ spin_unlock(&ses->chan_lock);
+ return 0;
+ }
+ spin_unlock(&ses->chan_lock);
+ cifs_dbg(FYI, "sess reconnect mask: 0x%lx, tcon reconnect: %d",
+ tcon->ses->chans_need_reconnect,
+ tcon->need_reconnect);
+
+ mutex_lock(&ses->session_mutex);
+ /*
+ * Recheck after acquire mutex. If another thread is negotiating
+ * and the server never sends an answer the socket will be closed
+ * and tcpStatus set to reconnect.
+ */
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsNeedReconnect) {
+ spin_unlock(&server->srv_lock);
+ mutex_unlock(&ses->session_mutex);
+
+ if (tcon->retry)
+ goto again;
+
+ rc = -EHOSTDOWN;
+ goto out;
+ }
+ spin_unlock(&server->srv_lock);
+
+ nls_codepage = load_nls_default();
+
+ /*
+ * need to prevent multiple threads trying to simultaneously
+ * reconnect the same SMB session
+ */
+ spin_lock(&ses->ses_lock);
+ spin_lock(&ses->chan_lock);
+ if (!cifs_chan_needs_reconnect(ses, server) &&
+ ses->ses_status == SES_GOOD) {
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+ /* this means that we only need to tree connect */
+ if (tcon->need_reconnect)
+ goto skip_sess_setup;
+
+ mutex_unlock(&ses->session_mutex);
+ goto out;
+ }
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+
+ rc = cifs_negotiate_protocol(0, ses, server);
+ if (!rc) {
+ rc = cifs_setup_session(0, ses, server, nls_codepage);
+ if ((rc == -EACCES) && !tcon->retry) {
+ mutex_unlock(&ses->session_mutex);
+ rc = -EHOSTDOWN;
+ goto failed;
+ } else if (rc) {
+ mutex_unlock(&ses->session_mutex);
+ goto out;
+ }
+ } else {
+ mutex_unlock(&ses->session_mutex);
+ goto out;
+ }
+
+skip_sess_setup:
+ if (!tcon->need_reconnect) {
+ mutex_unlock(&ses->session_mutex);
+ goto out;
+ }
+ cifs_mark_open_files_invalid(tcon);
+ if (tcon->use_persistent)
+ tcon->need_reopen_files = true;
+
+ rc = cifs_tree_connect(0, tcon, nls_codepage);
+ mutex_unlock(&ses->session_mutex);
+
+ cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
+ if (rc) {
+ /* If sess reconnected but tcon didn't, something strange ... */
+ cifs_dbg(VFS, "reconnect tcon failed rc = %d\n", rc);
+ goto out;
+ }
+
+ if (smb2_command != SMB2_INTERNAL_CMD)
+ mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
+
+ atomic_inc(&tconInfoReconnectCount);
+out:
+ /*
+ * Check if handle based operation so we know whether we can continue
+ * or not without returning to caller to reset file handle.
+ */
+ /*
+ * BB Is flush done by server on drop of tcp session? Should we special
+ * case it and skip above?
+ */
+ switch (smb2_command) {
+ case SMB2_FLUSH:
+ case SMB2_READ:
+ case SMB2_WRITE:
+ case SMB2_LOCK:
+ case SMB2_IOCTL:
+ case SMB2_QUERY_DIRECTORY:
+ case SMB2_CHANGE_NOTIFY:
+ case SMB2_QUERY_INFO:
+ case SMB2_SET_INFO:
+ rc = -EAGAIN;
+ }
+failed:
+ unload_nls(nls_codepage);
+ return rc;
+}
+
+static void
+fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ void *buf,
+ unsigned int *total_len)
+{
+ struct smb2_pdu *spdu = buf;
+ /* lookup word count ie StructureSize from table */
+ __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_command)];
+
+ /*
+ * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of
+ * largest operations (Create)
+ */
+ memset(buf, 0, 256);
+
+ smb2_hdr_assemble(&spdu->hdr, smb2_command, tcon, server);
+ spdu->StructureSize2 = cpu_to_le16(parmsize);
+
+ *total_len = parmsize + sizeof(struct smb2_hdr);
+}
+
+/*
+ * Allocate and return pointer to an SMB request hdr, and set basic
+ * SMB information in the SMB header. If the return code is zero, this
+ * function must have filled in request_buf pointer.
+ */
+static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ void **request_buf, unsigned int *total_len)
+{
+ /* BB eventually switch this to SMB2 specific small buf size */
+ if (smb2_command == SMB2_SET_INFO)
+ *request_buf = cifs_buf_get();
+ else
+ *request_buf = cifs_small_buf_get();
+ if (*request_buf == NULL) {
+ /* BB should we add a retry in here if not a writepage? */
+ return -ENOMEM;
+ }
+
+ fill_small_buf(smb2_command, tcon, server,
+ (struct smb2_hdr *)(*request_buf),
+ total_len);
+
+ if (tcon != NULL) {
+ uint16_t com_code = le16_to_cpu(smb2_command);
+ cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
+ cifs_stats_inc(&tcon->num_smbs_sent);
+ }
+
+ return 0;
+}
+
+static int smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ void **request_buf, unsigned int *total_len)
+{
+ int rc;
+
+ rc = smb2_reconnect(smb2_command, tcon, server);
+ if (rc)
+ return rc;
+
+ return __smb2_plain_req_init(smb2_command, tcon, server, request_buf,
+ total_len);
+}
+
+static int smb2_ioctl_req_init(u32 opcode, struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ void **request_buf, unsigned int *total_len)
+{
+ /* Skip reconnect only for FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs */
+ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) {
+ return __smb2_plain_req_init(SMB2_IOCTL, tcon, server,
+ request_buf, total_len);
+ }
+ return smb2_plain_req_init(SMB2_IOCTL, tcon, server,
+ request_buf, total_len);
+}
+
+/* For explanation of negotiate contexts see MS-SMB2 section 2.2.3.1 */
+
+static void
+build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt)
+{
+ pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES;
+ pneg_ctxt->DataLength = cpu_to_le16(38);
+ pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1);
+ pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE);
+ get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE);
+ pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512;
+}
+
+static void
+build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt)
+{
+ pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES;
+ pneg_ctxt->DataLength =
+ cpu_to_le16(sizeof(struct smb2_compression_capabilities_context)
+ - sizeof(struct smb2_neg_context));
+ pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(3);
+ pneg_ctxt->CompressionAlgorithms[0] = SMB3_COMPRESS_LZ77;
+ pneg_ctxt->CompressionAlgorithms[1] = SMB3_COMPRESS_LZ77_HUFF;
+ pneg_ctxt->CompressionAlgorithms[2] = SMB3_COMPRESS_LZNT1;
+}
+
+static unsigned int
+build_signing_ctxt(struct smb2_signing_capabilities *pneg_ctxt)
+{
+ unsigned int ctxt_len = sizeof(struct smb2_signing_capabilities);
+ unsigned short num_algs = 1; /* number of signing algorithms sent */
+
+ pneg_ctxt->ContextType = SMB2_SIGNING_CAPABILITIES;
+ /*
+ * Context Data length must be rounded to multiple of 8 for some servers
+ */
+ pneg_ctxt->DataLength = cpu_to_le16(ALIGN(sizeof(struct smb2_signing_capabilities) -
+ sizeof(struct smb2_neg_context) +
+ (num_algs * sizeof(u16)), 8));
+ pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(num_algs);
+ pneg_ctxt->SigningAlgorithms[0] = cpu_to_le16(SIGNING_ALG_AES_CMAC);
+
+ ctxt_len += sizeof(__le16) * num_algs;
+ ctxt_len = ALIGN(ctxt_len, 8);
+ return ctxt_len;
+ /* TBD add SIGNING_ALG_AES_GMAC and/or SIGNING_ALG_HMAC_SHA256 */
+}
+
+static void
+build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
+{
+ pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
+ if (require_gcm_256) {
+ pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + 1 cipher */
+ pneg_ctxt->CipherCount = cpu_to_le16(1);
+ pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES256_GCM;
+ } else if (enable_gcm_256) {
+ pneg_ctxt->DataLength = cpu_to_le16(8); /* Cipher Count + 3 ciphers */
+ pneg_ctxt->CipherCount = cpu_to_le16(3);
+ pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;
+ pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES256_GCM;
+ pneg_ctxt->Ciphers[2] = SMB2_ENCRYPTION_AES128_CCM;
+ } else {
+ pneg_ctxt->DataLength = cpu_to_le16(6); /* Cipher Count + 2 ciphers */
+ pneg_ctxt->CipherCount = cpu_to_le16(2);
+ pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;
+ pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES128_CCM;
+ }
+}
+
+static unsigned int
+build_netname_ctxt(struct smb2_netname_neg_context *pneg_ctxt, char *hostname)
+{
+ struct nls_table *cp = load_nls_default();
+
+ pneg_ctxt->ContextType = SMB2_NETNAME_NEGOTIATE_CONTEXT_ID;
+
+ /* copy up to max of first 100 bytes of server name to NetName field */
+ pneg_ctxt->DataLength = cpu_to_le16(2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp));
+ /* context size is DataLength + minimal smb2_neg_context */
+ return ALIGN(le16_to_cpu(pneg_ctxt->DataLength) + sizeof(struct smb2_neg_context), 8);
+}
+
+static void
+build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
+{
+ pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE;
+ pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
+ /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
+ pneg_ctxt->Name[0] = 0x93;
+ pneg_ctxt->Name[1] = 0xAD;
+ pneg_ctxt->Name[2] = 0x25;
+ pneg_ctxt->Name[3] = 0x50;
+ pneg_ctxt->Name[4] = 0x9C;
+ pneg_ctxt->Name[5] = 0xB4;
+ pneg_ctxt->Name[6] = 0x11;
+ pneg_ctxt->Name[7] = 0xE7;
+ pneg_ctxt->Name[8] = 0xB4;
+ pneg_ctxt->Name[9] = 0x23;
+ pneg_ctxt->Name[10] = 0x83;
+ pneg_ctxt->Name[11] = 0xDE;
+ pneg_ctxt->Name[12] = 0x96;
+ pneg_ctxt->Name[13] = 0x8B;
+ pneg_ctxt->Name[14] = 0xCD;
+ pneg_ctxt->Name[15] = 0x7C;
+}
+
+static void
+assemble_neg_contexts(struct smb2_negotiate_req *req,
+ struct TCP_Server_Info *server, unsigned int *total_len)
+{
+ unsigned int ctxt_len, neg_context_count;
+ struct TCP_Server_Info *pserver;
+ char *pneg_ctxt;
+ char *hostname;
+
+ if (*total_len > 200) {
+ /* In case length corrupted don't want to overrun smb buffer */
+ cifs_server_dbg(VFS, "Bad frame length assembling neg contexts\n");
+ return;
+ }
+
+ /*
+ * round up total_len of fixed part of SMB3 negotiate request to 8
+ * byte boundary before adding negotiate contexts
+ */
+ *total_len = ALIGN(*total_len, 8);
+
+ pneg_ctxt = (*total_len) + (char *)req;
+ req->NegotiateContextOffset = cpu_to_le32(*total_len);
+
+ build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt);
+ ctxt_len = ALIGN(sizeof(struct smb2_preauth_neg_context), 8);
+ *total_len += ctxt_len;
+ pneg_ctxt += ctxt_len;
+
+ build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt);
+ ctxt_len = ALIGN(sizeof(struct smb2_encryption_neg_context), 8);
+ *total_len += ctxt_len;
+ pneg_ctxt += ctxt_len;
+
+ /*
+ * secondary channels don't have the hostname field populated
+ * use the hostname field in the primary channel instead
+ */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+ cifs_server_lock(pserver);
+ hostname = pserver->hostname;
+ if (hostname && (hostname[0] != 0)) {
+ ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt,
+ hostname);
+ *total_len += ctxt_len;
+ pneg_ctxt += ctxt_len;
+ neg_context_count = 3;
+ } else
+ neg_context_count = 2;
+ cifs_server_unlock(pserver);
+
+ build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
+ *total_len += sizeof(struct smb2_posix_neg_context);
+ pneg_ctxt += sizeof(struct smb2_posix_neg_context);
+ neg_context_count++;
+
+ if (server->compress_algorithm) {
+ build_compression_ctxt((struct smb2_compression_capabilities_context *)
+ pneg_ctxt);
+ ctxt_len = ALIGN(sizeof(struct smb2_compression_capabilities_context), 8);
+ *total_len += ctxt_len;
+ pneg_ctxt += ctxt_len;
+ neg_context_count++;
+ }
+
+ if (enable_negotiate_signing) {
+ ctxt_len = build_signing_ctxt((struct smb2_signing_capabilities *)
+ pneg_ctxt);
+ *total_len += ctxt_len;
+ pneg_ctxt += ctxt_len;
+ neg_context_count++;
+ }
+
+ /* check for and add transport_capabilities and signing capabilities */
+ req->NegotiateContextCount = cpu_to_le16(neg_context_count);
+
+}
+
+/* If invalid preauth context warn but use what we requested, SHA-512 */
+static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
+{
+ unsigned int len = le16_to_cpu(ctxt->DataLength);
+
+ /*
+ * Caller checked that DataLength remains within SMB boundary. We still
+ * need to confirm that one HashAlgorithms member is accounted for.
+ */
+ if (len < MIN_PREAUTH_CTXT_DATA_LEN) {
+ pr_warn_once("server sent bad preauth context\n");
+ return;
+ } else if (len < MIN_PREAUTH_CTXT_DATA_LEN + le16_to_cpu(ctxt->SaltLength)) {
+ pr_warn_once("server sent invalid SaltLength\n");
+ return;
+ }
+ if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1)
+ pr_warn_once("Invalid SMB3 hash algorithm count\n");
+ if (ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
+ pr_warn_once("unknown SMB3 hash algorithm\n");
+}
+
+static void decode_compress_ctx(struct TCP_Server_Info *server,
+ struct smb2_compression_capabilities_context *ctxt)
+{
+ unsigned int len = le16_to_cpu(ctxt->DataLength);
+
+ /*
+ * Caller checked that DataLength remains within SMB boundary. We still
+ * need to confirm that one CompressionAlgorithms member is accounted
+ * for.
+ */
+ if (len < 10) {
+ pr_warn_once("server sent bad compression cntxt\n");
+ return;
+ }
+ if (le16_to_cpu(ctxt->CompressionAlgorithmCount) != 1) {
+ pr_warn_once("Invalid SMB3 compress algorithm count\n");
+ return;
+ }
+ if (le16_to_cpu(ctxt->CompressionAlgorithms[0]) > 3) {
+ pr_warn_once("unknown compression algorithm\n");
+ return;
+ }
+ server->compress_algorithm = ctxt->CompressionAlgorithms[0];
+}
+
+static int decode_encrypt_ctx(struct TCP_Server_Info *server,
+ struct smb2_encryption_neg_context *ctxt)
+{
+ unsigned int len = le16_to_cpu(ctxt->DataLength);
+
+ cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d\n", len);
+ /*
+ * Caller checked that DataLength remains within SMB boundary. We still
+ * need to confirm that one Cipher flexible array member is accounted
+ * for.
+ */
+ if (len < MIN_ENCRYPT_CTXT_DATA_LEN) {
+ pr_warn_once("server sent bad crypto ctxt len\n");
+ return -EINVAL;
+ }
+
+ if (le16_to_cpu(ctxt->CipherCount) != 1) {
+ pr_warn_once("Invalid SMB3.11 cipher count\n");
+ return -EINVAL;
+ }
+ cifs_dbg(FYI, "SMB311 cipher type:%d\n", le16_to_cpu(ctxt->Ciphers[0]));
+ if (require_gcm_256) {
+ if (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES256_GCM) {
+ cifs_dbg(VFS, "Server does not support requested encryption type (AES256 GCM)\n");
+ return -EOPNOTSUPP;
+ }
+ } else if (ctxt->Ciphers[0] == 0) {
+ /*
+ * e.g. if server only supported AES256_CCM (very unlikely)
+ * or server supported no encryption types or had all disabled.
+ * Since GLOBAL_CAP_ENCRYPTION will be not set, in the case
+ * in which mount requested encryption ("seal") checks later
+ * on during tree connection will return proper rc, but if
+ * seal not requested by client, since server is allowed to
+ * return 0 to indicate no supported cipher, we can't fail here
+ */
+ server->cipher_type = 0;
+ server->capabilities &= ~SMB2_GLOBAL_CAP_ENCRYPTION;
+ pr_warn_once("Server does not support requested encryption types\n");
+ return 0;
+ } else if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) &&
+ (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM) &&
+ (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES256_GCM)) {
+ /* server returned a cipher we didn't ask for */
+ pr_warn_once("Invalid SMB3.11 cipher returned\n");
+ return -EINVAL;
+ }
+ server->cipher_type = ctxt->Ciphers[0];
+ server->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
+ return 0;
+}
+
+static void decode_signing_ctx(struct TCP_Server_Info *server,
+ struct smb2_signing_capabilities *pctxt)
+{
+ unsigned int len = le16_to_cpu(pctxt->DataLength);
+
+ /*
+ * Caller checked that DataLength remains within SMB boundary. We still
+ * need to confirm that one SigningAlgorithms flexible array member is
+ * accounted for.
+ */
+ if ((len < 4) || (len > 16)) {
+ pr_warn_once("server sent bad signing negcontext\n");
+ return;
+ }
+ if (le16_to_cpu(pctxt->SigningAlgorithmCount) != 1) {
+ pr_warn_once("Invalid signing algorithm count\n");
+ return;
+ }
+ if (le16_to_cpu(pctxt->SigningAlgorithms[0]) > 2) {
+ pr_warn_once("unknown signing algorithm\n");
+ return;
+ }
+
+ server->signing_negotiated = true;
+ server->signing_algorithm = le16_to_cpu(pctxt->SigningAlgorithms[0]);
+ cifs_dbg(FYI, "signing algorithm %d chosen\n",
+ server->signing_algorithm);
+}
+
+
+static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
+ struct TCP_Server_Info *server,
+ unsigned int len_of_smb)
+{
+ struct smb2_neg_context *pctx;
+ unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset);
+ unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount);
+ unsigned int len_of_ctxts, i;
+ int rc = 0;
+
+ cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt);
+ if (len_of_smb <= offset) {
+ cifs_server_dbg(VFS, "Invalid response: negotiate context offset\n");
+ return -EINVAL;
+ }
+
+ len_of_ctxts = len_of_smb - offset;
+
+ for (i = 0; i < ctxt_cnt; i++) {
+ int clen;
+ /* check that offset is not beyond end of SMB */
+ if (len_of_ctxts < sizeof(struct smb2_neg_context))
+ break;
+
+ pctx = (struct smb2_neg_context *)(offset + (char *)rsp);
+ clen = sizeof(struct smb2_neg_context)
+ + le16_to_cpu(pctx->DataLength);
+ /*
+ * 2.2.4 SMB2 NEGOTIATE Response
+ * Subsequent negotiate contexts MUST appear at the first 8-byte
+ * aligned offset following the previous negotiate context.
+ */
+ if (i + 1 != ctxt_cnt)
+ clen = ALIGN(clen, 8);
+ if (clen > len_of_ctxts)
+ break;
+
+ if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES)
+ decode_preauth_context(
+ (struct smb2_preauth_neg_context *)pctx);
+ else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES)
+ rc = decode_encrypt_ctx(server,
+ (struct smb2_encryption_neg_context *)pctx);
+ else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES)
+ decode_compress_ctx(server,
+ (struct smb2_compression_capabilities_context *)pctx);
+ else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE)
+ server->posix_ext_supported = true;
+ else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES)
+ decode_signing_ctx(server,
+ (struct smb2_signing_capabilities *)pctx);
+ else
+ cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n",
+ le16_to_cpu(pctx->ContextType));
+ if (rc)
+ break;
+
+ offset += clen;
+ len_of_ctxts -= clen;
+ }
+ return rc;
+}
+
+static struct create_posix *
+create_posix_buf(umode_t mode)
+{
+ struct create_posix *buf;
+
+ buf = kzalloc(sizeof(struct create_posix),
+ GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->ccontext.DataOffset =
+ cpu_to_le16(offsetof(struct create_posix, Mode));
+ buf->ccontext.DataLength = cpu_to_le32(4);
+ buf->ccontext.NameOffset =
+ cpu_to_le16(offsetof(struct create_posix, Name));
+ buf->ccontext.NameLength = cpu_to_le16(16);
+
+ /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
+ buf->Name[0] = 0x93;
+ buf->Name[1] = 0xAD;
+ buf->Name[2] = 0x25;
+ buf->Name[3] = 0x50;
+ buf->Name[4] = 0x9C;
+ buf->Name[5] = 0xB4;
+ buf->Name[6] = 0x11;
+ buf->Name[7] = 0xE7;
+ buf->Name[8] = 0xB4;
+ buf->Name[9] = 0x23;
+ buf->Name[10] = 0x83;
+ buf->Name[11] = 0xDE;
+ buf->Name[12] = 0x96;
+ buf->Name[13] = 0x8B;
+ buf->Name[14] = 0xCD;
+ buf->Name[15] = 0x7C;
+ buf->Mode = cpu_to_le32(mode);
+ cifs_dbg(FYI, "mode on posix create 0%o\n", mode);
+ return buf;
+}
+
+static int
+add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+
+ iov[num].iov_base = create_posix_buf(mode);
+ if (mode == ACL_NO_MODE)
+ cifs_dbg(FYI, "Invalid mode\n");
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = sizeof(struct create_posix);
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset = cpu_to_le32(
+ sizeof(struct smb2_create_req) +
+ iov[num - 1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_posix));
+ *num_iovec = num + 1;
+ return 0;
+}
+
+
+/*
+ *
+ * SMB2 Worker functions follow:
+ *
+ * The general structure of the worker functions is:
+ * 1) Call smb2_init (assembles SMB2 header)
+ * 2) Initialize SMB2 command specific fields in fixed length area of SMB
+ * 3) Call smb_sendrcv2 (sends request on socket and waits for response)
+ * 4) Decode SMB2 command specific fields in the fixed length area
+ * 5) Decode variable length data area (if any for this SMB2 command type)
+ * 6) Call free smb buffer
+ * 7) return
+ *
+ */
+
+int
+SMB2_negotiate(const unsigned int xid,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+{
+ struct smb_rqst rqst;
+ struct smb2_negotiate_req *req;
+ struct smb2_negotiate_rsp *rsp;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ int rc;
+ int resp_buftype;
+ int blob_offset, blob_length;
+ char *security_blob;
+ int flags = CIFS_NEG_OP;
+ unsigned int total_len;
+
+ cifs_dbg(FYI, "Negotiate protocol\n");
+
+ if (!server) {
+ WARN(1, "%s: server is NULL!\n", __func__);
+ return -EIO;
+ }
+
+ rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ req->hdr.SessionId = 0;
+
+ memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
+ memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
+
+ if (strcmp(server->vals->version_string,
+ SMB3ANY_VERSION_STRING) == 0) {
+ req->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
+ req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
+ req->Dialects[2] = cpu_to_le16(SMB311_PROT_ID);
+ req->DialectCount = cpu_to_le16(3);
+ total_len += 6;
+ } else if (strcmp(server->vals->version_string,
+ SMBDEFAULT_VERSION_STRING) == 0) {
+ req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
+ req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
+ req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
+ req->Dialects[3] = cpu_to_le16(SMB311_PROT_ID);
+ req->DialectCount = cpu_to_le16(4);
+ total_len += 8;
+ } else {
+ /* otherwise send specific dialect */
+ req->Dialects[0] = cpu_to_le16(server->vals->protocol_id);
+ req->DialectCount = cpu_to_le16(1);
+ total_len += 2;
+ }
+
+ /* only one of SMB2 signing flags may be set in SMB2 request */
+ if (ses->sign)
+ req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
+ else if (global_secflags & CIFSSEC_MAY_SIGN)
+ req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
+ else
+ req->SecurityMode = 0;
+
+ req->Capabilities = cpu_to_le32(server->vals->req_capabilities);
+ if (ses->chan_max > 1)
+ req->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL);
+
+ /* ClientGUID must be zero for SMB2.02 dialect */
+ if (server->vals->protocol_id == SMB20_PROT_ID)
+ memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE);
+ else {
+ memcpy(req->ClientGUID, server->client_guid,
+ SMB2_CLIENT_GUID_SIZE);
+ if ((server->vals->protocol_id == SMB311_PROT_ID) ||
+ (strcmp(server->vals->version_string,
+ SMB3ANY_VERSION_STRING) == 0) ||
+ (strcmp(server->vals->version_string,
+ SMBDEFAULT_VERSION_STRING) == 0))
+ assemble_neg_contexts(req, server, &total_len);
+ }
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ cifs_small_buf_release(req);
+ rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base;
+ /*
+ * No tcon so can't do
+ * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
+ */
+ if (rc == -EOPNOTSUPP) {
+ cifs_server_dbg(VFS, "Dialect not supported by server. Consider specifying vers=1.0 or vers=2.0 on mount for accessing older servers\n");
+ goto neg_exit;
+ } else if (rc != 0)
+ goto neg_exit;
+
+ rc = -EIO;
+ if (strcmp(server->vals->version_string,
+ SMB3ANY_VERSION_STRING) == 0) {
+ if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
+ cifs_server_dbg(VFS,
+ "SMB2 dialect returned but not requested\n");
+ goto neg_exit;
+ } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
+ cifs_server_dbg(VFS,
+ "SMB2.1 dialect returned but not requested\n");
+ goto neg_exit;
+ } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
+ /* ops set to 3.0 by default for default so update */
+ server->ops = &smb311_operations;
+ server->vals = &smb311_values;
+ }
+ } else if (strcmp(server->vals->version_string,
+ SMBDEFAULT_VERSION_STRING) == 0) {
+ if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
+ cifs_server_dbg(VFS,
+ "SMB2 dialect returned but not requested\n");
+ goto neg_exit;
+ } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
+ /* ops set to 3.0 by default for default so update */
+ server->ops = &smb21_operations;
+ server->vals = &smb21_values;
+ } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
+ server->ops = &smb311_operations;
+ server->vals = &smb311_values;
+ }
+ } else if (le16_to_cpu(rsp->DialectRevision) !=
+ server->vals->protocol_id) {
+ /* if requested single dialect ensure returned dialect matched */
+ cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n",
+ le16_to_cpu(rsp->DialectRevision));
+ goto neg_exit;
+ }
+
+ cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
+
+ if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID))
+ cifs_dbg(FYI, "negotiated smb2.0 dialect\n");
+ else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID))
+ cifs_dbg(FYI, "negotiated smb2.1 dialect\n");
+ else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID))
+ cifs_dbg(FYI, "negotiated smb3.0 dialect\n");
+ else if (rsp->DialectRevision == cpu_to_le16(SMB302_PROT_ID))
+ cifs_dbg(FYI, "negotiated smb3.02 dialect\n");
+ else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID))
+ cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n");
+ else {
+ cifs_server_dbg(VFS, "Invalid dialect returned by server 0x%x\n",
+ le16_to_cpu(rsp->DialectRevision));
+ goto neg_exit;
+ }
+
+ rc = 0;
+ server->dialect = le16_to_cpu(rsp->DialectRevision);
+
+ /*
+ * Keep a copy of the hash after negprot. This hash will be
+ * the starting hash value for all sessions made from this
+ * server.
+ */
+ memcpy(server->preauth_sha_hash, ses->preauth_sha_hash,
+ SMB2_PREAUTH_HASH_SIZE);
+
+ /* SMB2 only has an extended negflavor */
+ server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
+ /* set it to the maximum buffer size value we can send with 1 credit */
+ server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize),
+ SMB2_MAX_BUFFER_SIZE);
+ server->max_read = le32_to_cpu(rsp->MaxReadSize);
+ server->max_write = le32_to_cpu(rsp->MaxWriteSize);
+ server->sec_mode = le16_to_cpu(rsp->SecurityMode);
+ if ((server->sec_mode & SMB2_SEC_MODE_FLAGS_ALL) != server->sec_mode)
+ cifs_dbg(FYI, "Server returned unexpected security mode 0x%x\n",
+ server->sec_mode);
+ server->capabilities = le32_to_cpu(rsp->Capabilities);
+ /* Internal types */
+ server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
+
+ /*
+ * SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
+ * Set the cipher type manually.
+ */
+ if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
+ server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
+
+ security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
+ (struct smb2_hdr *)rsp);
+ /*
+ * See MS-SMB2 section 2.2.4: if no blob, client picks default which
+ * for us will be
+ * ses->sectype = RawNTLMSSP;
+ * but for time being this is our only auth choice so doesn't matter.
+ * We just found a server which sets blob length to zero expecting raw.
+ */
+ if (blob_length == 0) {
+ cifs_dbg(FYI, "missing security blob on negprot\n");
+ server->sec_ntlmssp = true;
+ }
+
+ rc = cifs_enable_signing(server, ses->sign);
+ if (rc)
+ goto neg_exit;
+ if (blob_length) {
+ rc = decode_negTokenInit(security_blob, blob_length, server);
+ if (rc == 1)
+ rc = 0;
+ else if (rc == 0)
+ rc = -EIO;
+ }
+
+ if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
+ if (rsp->NegotiateContextCount)
+ rc = smb311_decode_neg_context(rsp, server,
+ rsp_iov.iov_len);
+ else
+ cifs_server_dbg(VFS, "Missing expected negotiate contexts\n");
+ }
+neg_exit:
+ free_rsp_buf(resp_buftype, rsp);
+ return rc;
+}
+
+int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
+{
+ int rc;
+ struct validate_negotiate_info_req *pneg_inbuf;
+ struct validate_negotiate_info_rsp *pneg_rsp = NULL;
+ u32 rsplen;
+ u32 inbuflen; /* max of 4 dialects */
+ struct TCP_Server_Info *server = tcon->ses->server;
+
+ cifs_dbg(FYI, "validate negotiate\n");
+
+ /* In SMB3.11 preauth integrity supersedes validate negotiate */
+ if (server->dialect == SMB311_PROT_ID)
+ return 0;
+
+ /*
+ * validation ioctl must be signed, so no point sending this if we
+ * can not sign it (ie are not known user). Even if signing is not
+ * required (enabled but not negotiated), in those cases we selectively
+ * sign just this, the first and only signed request on a connection.
+ * Having validation of negotiate info helps reduce attack vectors.
+ */
+ if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
+ return 0; /* validation requires signing */
+
+ if (tcon->ses->user_name == NULL) {
+ cifs_dbg(FYI, "Can't validate negotiate: null user mount\n");
+ return 0; /* validation requires signing */
+ }
+
+ if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
+ cifs_tcon_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n");
+
+ pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS);
+ if (!pneg_inbuf)
+ return -ENOMEM;
+
+ pneg_inbuf->Capabilities =
+ cpu_to_le32(server->vals->req_capabilities);
+ if (tcon->ses->chan_max > 1)
+ pneg_inbuf->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL);
+
+ memcpy(pneg_inbuf->Guid, server->client_guid,
+ SMB2_CLIENT_GUID_SIZE);
+
+ if (tcon->ses->sign)
+ pneg_inbuf->SecurityMode =
+ cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
+ else if (global_secflags & CIFSSEC_MAY_SIGN)
+ pneg_inbuf->SecurityMode =
+ cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
+ else
+ pneg_inbuf->SecurityMode = 0;
+
+
+ if (strcmp(server->vals->version_string,
+ SMB3ANY_VERSION_STRING) == 0) {
+ pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
+ pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
+ pneg_inbuf->Dialects[2] = cpu_to_le16(SMB311_PROT_ID);
+ pneg_inbuf->DialectCount = cpu_to_le16(3);
+ /* SMB 2.1 not included so subtract one dialect from len */
+ inbuflen = sizeof(*pneg_inbuf) -
+ (sizeof(pneg_inbuf->Dialects[0]));
+ } else if (strcmp(server->vals->version_string,
+ SMBDEFAULT_VERSION_STRING) == 0) {
+ pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
+ pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
+ pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
+ pneg_inbuf->Dialects[3] = cpu_to_le16(SMB311_PROT_ID);
+ pneg_inbuf->DialectCount = cpu_to_le16(4);
+ /* structure is big enough for 4 dialects */
+ inbuflen = sizeof(*pneg_inbuf);
+ } else {
+ /* otherwise specific dialect was requested */
+ pneg_inbuf->Dialects[0] =
+ cpu_to_le16(server->vals->protocol_id);
+ pneg_inbuf->DialectCount = cpu_to_le16(1);
+ /* structure is big enough for 4 dialects, sending only 1 */
+ inbuflen = sizeof(*pneg_inbuf) -
+ sizeof(pneg_inbuf->Dialects[0]) * 3;
+ }
+
+ rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
+ FSCTL_VALIDATE_NEGOTIATE_INFO,
+ (char *)pneg_inbuf, inbuflen, CIFSMaxBufSize,
+ (char **)&pneg_rsp, &rsplen);
+ if (rc == -EOPNOTSUPP) {
+ /*
+ * Old Windows versions or Netapp SMB server can return
+ * not supported error. Client should accept it.
+ */
+ cifs_tcon_dbg(VFS, "Server does not support validate negotiate\n");
+ rc = 0;
+ goto out_free_inbuf;
+ } else if (rc != 0) {
+ cifs_tcon_dbg(VFS, "validate protocol negotiate failed: %d\n",
+ rc);
+ rc = -EIO;
+ goto out_free_inbuf;
+ }
+
+ rc = -EIO;
+ if (rsplen != sizeof(*pneg_rsp)) {
+ cifs_tcon_dbg(VFS, "Invalid protocol negotiate response size: %d\n",
+ rsplen);
+
+ /* relax check since Mac returns max bufsize allowed on ioctl */
+ if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp))
+ goto out_free_rsp;
+ }
+
+ /* check validate negotiate info response matches what we got earlier */
+ if (pneg_rsp->Dialect != cpu_to_le16(server->dialect))
+ goto vneg_out;
+
+ if (pneg_rsp->SecurityMode != cpu_to_le16(server->sec_mode))
+ goto vneg_out;
+
+ /* do not validate server guid because not saved at negprot time yet */
+
+ if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND |
+ SMB2_LARGE_FILES) != server->capabilities)
+ goto vneg_out;
+
+ /* validate negotiate successful */
+ rc = 0;
+ cifs_dbg(FYI, "validate negotiate info successful\n");
+ goto out_free_rsp;
+
+vneg_out:
+ cifs_tcon_dbg(VFS, "protocol revalidation - security settings mismatch\n");
+out_free_rsp:
+ kfree(pneg_rsp);
+out_free_inbuf:
+ kfree(pneg_inbuf);
+ return rc;
+}
+
+enum securityEnum
+smb2_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
+{
+ switch (requested) {
+ case Kerberos:
+ case RawNTLMSSP:
+ return requested;
+ case NTLMv2:
+ return RawNTLMSSP;
+ case Unspecified:
+ if (server->sec_ntlmssp &&
+ (global_secflags & CIFSSEC_MAY_NTLMSSP))
+ return RawNTLMSSP;
+ if ((server->sec_kerberos || server->sec_mskerberos) &&
+ (global_secflags & CIFSSEC_MAY_KRB5))
+ return Kerberos;
+ fallthrough;
+ default:
+ return Unspecified;
+ }
+}
+
+struct SMB2_sess_data {
+ unsigned int xid;
+ struct cifs_ses *ses;
+ struct TCP_Server_Info *server;
+ struct nls_table *nls_cp;
+ void (*func)(struct SMB2_sess_data *);
+ int result;
+ u64 previous_session;
+
+ /* we will send the SMB in three pieces:
+ * a fixed length beginning part, an optional
+ * SPNEGO blob (which can be zero length), and a
+ * last part which will include the strings
+ * and rest of bcc area. This allows us to avoid
+ * a large buffer 17K allocation
+ */
+ int buf0_type;
+ struct kvec iov[2];
+};
+
+static int
+SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
+{
+ int rc;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+ struct smb2_sess_setup_req *req;
+ unsigned int total_len;
+ bool is_binding = false;
+
+ rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server,
+ (void **) &req,
+ &total_len);
+ if (rc)
+ return rc;
+
+ spin_lock(&ses->ses_lock);
+ is_binding = (ses->ses_status == SES_GOOD);
+ spin_unlock(&ses->ses_lock);
+
+ if (is_binding) {
+ req->hdr.SessionId = cpu_to_le64(ses->Suid);
+ req->hdr.Flags |= SMB2_FLAGS_SIGNED;
+ req->PreviousSessionId = 0;
+ req->Flags = SMB2_SESSION_REQ_FLAG_BINDING;
+ cifs_dbg(FYI, "Binding to sess id: %llx\n", ses->Suid);
+ } else {
+ /* First session, not a reauthenticate */
+ req->hdr.SessionId = 0;
+ /*
+ * if reconnect, we need to send previous sess id
+ * otherwise it is 0
+ */
+ req->PreviousSessionId = cpu_to_le64(sess_data->previous_session);
+ req->Flags = 0; /* MBZ */
+ cifs_dbg(FYI, "Fresh session. Previous: %llx\n",
+ sess_data->previous_session);
+ }
+
+ /* enough to enable echos and oplocks and one max size write */
+ req->hdr.CreditRequest = cpu_to_le16(130);
+
+ /* only one of SMB2 signing flags may be set in SMB2 request */
+ if (server->sign)
+ req->SecurityMode = SMB2_NEGOTIATE_SIGNING_REQUIRED;
+ else if (global_secflags & CIFSSEC_MAY_SIGN) /* one flag unlike MUST_ */
+ req->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED;
+ else
+ req->SecurityMode = 0;
+
+#ifdef CONFIG_CIFS_DFS_UPCALL
+ req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
+#else
+ req->Capabilities = 0;
+#endif /* DFS_UPCALL */
+
+ req->Channel = 0; /* MBZ */
+
+ sess_data->iov[0].iov_base = (char *)req;
+ /* 1 for pad */
+ sess_data->iov[0].iov_len = total_len - 1;
+ /*
+ * This variable will be used to clear the buffer
+ * allocated above in case of any error in the calling function.
+ */
+ sess_data->buf0_type = CIFS_SMALL_BUFFER;
+
+ return 0;
+}
+
+static void
+SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data)
+{
+ struct kvec *iov = sess_data->iov;
+
+ /* iov[1] is already freed by caller */
+ if (sess_data->buf0_type != CIFS_NO_BUFFER && iov[0].iov_base)
+ memzero_explicit(iov[0].iov_base, iov[0].iov_len);
+
+ free_rsp_buf(sess_data->buf0_type, iov[0].iov_base);
+ sess_data->buf0_type = CIFS_NO_BUFFER;
+}
+
+static int
+SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
+{
+ int rc;
+ struct smb_rqst rqst;
+ struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base;
+ struct kvec rsp_iov = { NULL, 0 };
+
+ /* Testing shows that buffer offset must be at location of Buffer[0] */
+ req->SecurityBufferOffset =
+ cpu_to_le16(sizeof(struct smb2_sess_setup_req) - 1 /* pad */);
+ req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len);
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = sess_data->iov;
+ rqst.rq_nvec = 2;
+
+ /* BB add code to build os and lm fields */
+ rc = cifs_send_recv(sess_data->xid, sess_data->ses,
+ sess_data->server,
+ &rqst,
+ &sess_data->buf0_type,
+ CIFS_LOG_ERROR | CIFS_SESS_OP, &rsp_iov);
+ cifs_small_buf_release(sess_data->iov[0].iov_base);
+ memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
+
+ return rc;
+}
+
+static int
+SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
+{
+ int rc = 0;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+
+ cifs_server_lock(server);
+ if (server->ops->generate_signingkey) {
+ rc = server->ops->generate_signingkey(ses, server);
+ if (rc) {
+ cifs_dbg(FYI,
+ "SMB3 session key generation failed\n");
+ cifs_server_unlock(server);
+ return rc;
+ }
+ }
+ if (!server->session_estab) {
+ server->sequence_number = 0x2;
+ server->session_estab = true;
+ }
+ cifs_server_unlock(server);
+
+ cifs_dbg(FYI, "SMB2/3 session established successfully\n");
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_UPCALL
+static void
+SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
+{
+ int rc;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+ struct cifs_spnego_msg *msg;
+ struct key *spnego_key = NULL;
+ struct smb2_sess_setup_rsp *rsp = NULL;
+ bool is_binding = false;
+
+ rc = SMB2_sess_alloc_buffer(sess_data);
+ if (rc)
+ goto out;
+
+ spnego_key = cifs_get_spnego_key(ses, server);
+ if (IS_ERR(spnego_key)) {
+ rc = PTR_ERR(spnego_key);
+ if (rc == -ENOKEY)
+ cifs_dbg(VFS, "Verify user has a krb5 ticket and keyutils is installed\n");
+ spnego_key = NULL;
+ goto out;
+ }
+
+ msg = spnego_key->payload.data[0];
+ /*
+ * check version field to make sure that cifs.upcall is
+ * sending us a response in an expected form
+ */
+ if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
+ cifs_dbg(VFS, "bad cifs.upcall version. Expected %d got %d\n",
+ CIFS_SPNEGO_UPCALL_VERSION, msg->version);
+ rc = -EKEYREJECTED;
+ goto out_put_spnego_key;
+ }
+
+ spin_lock(&ses->ses_lock);
+ is_binding = (ses->ses_status == SES_GOOD);
+ spin_unlock(&ses->ses_lock);
+
+ /* keep session key if binding */
+ if (!is_binding) {
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
+ GFP_KERNEL);
+ if (!ses->auth_key.response) {
+ cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n",
+ msg->sesskey_len);
+ rc = -ENOMEM;
+ goto out_put_spnego_key;
+ }
+ ses->auth_key.len = msg->sesskey_len;
+ }
+
+ sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
+ sess_data->iov[1].iov_len = msg->secblob_len;
+
+ rc = SMB2_sess_sendreceive(sess_data);
+ if (rc)
+ goto out_put_spnego_key;
+
+ rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
+ /* keep session id and flags if binding */
+ if (!is_binding) {
+ ses->Suid = le64_to_cpu(rsp->hdr.SessionId);
+ ses->session_flags = le16_to_cpu(rsp->SessionFlags);
+ }
+
+ rc = SMB2_sess_establish_session(sess_data);
+out_put_spnego_key:
+ key_invalidate(spnego_key);
+ key_put(spnego_key);
+ if (rc) {
+ kfree_sensitive(ses->auth_key.response);
+ ses->auth_key.response = NULL;
+ ses->auth_key.len = 0;
+ }
+out:
+ sess_data->result = rc;
+ sess_data->func = NULL;
+ SMB2_sess_free_buffer(sess_data);
+}
+#else
+static void
+SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
+{
+ cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled!\n");
+ sess_data->result = -EOPNOTSUPP;
+ sess_data->func = NULL;
+}
+#endif
+
+static void
+SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data);
+
+static void
+SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
+{
+ int rc;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+ struct smb2_sess_setup_rsp *rsp = NULL;
+ unsigned char *ntlmssp_blob = NULL;
+ bool use_spnego = false; /* else use raw ntlmssp */
+ u16 blob_length = 0;
+ bool is_binding = false;
+
+ /*
+ * If memory allocation is successful, caller of this function
+ * frees it.
+ */
+ ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
+ if (!ses->ntlmssp) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+ ses->ntlmssp->sesskey_per_smbsess = true;
+
+ rc = SMB2_sess_alloc_buffer(sess_data);
+ if (rc)
+ goto out_err;
+
+ rc = build_ntlmssp_smb3_negotiate_blob(&ntlmssp_blob,
+ &blob_length, ses, server,
+ sess_data->nls_cp);
+ if (rc)
+ goto out;
+
+ if (use_spnego) {
+ /* BB eventually need to add this */
+ cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ sess_data->iov[1].iov_base = ntlmssp_blob;
+ sess_data->iov[1].iov_len = blob_length;
+
+ rc = SMB2_sess_sendreceive(sess_data);
+ rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
+
+ /* If true, rc here is expected and not an error */
+ if (sess_data->buf0_type != CIFS_NO_BUFFER &&
+ rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
+ rc = 0;
+
+ if (rc)
+ goto out;
+
+ if (offsetof(struct smb2_sess_setup_rsp, Buffer) !=
+ le16_to_cpu(rsp->SecurityBufferOffset)) {
+ cifs_dbg(VFS, "Invalid security buffer offset %d\n",
+ le16_to_cpu(rsp->SecurityBufferOffset));
+ rc = -EIO;
+ goto out;
+ }
+ rc = decode_ntlmssp_challenge(rsp->Buffer,
+ le16_to_cpu(rsp->SecurityBufferLength), ses);
+ if (rc)
+ goto out;
+
+ cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
+
+ spin_lock(&ses->ses_lock);
+ is_binding = (ses->ses_status == SES_GOOD);
+ spin_unlock(&ses->ses_lock);
+
+ /* keep existing ses id and flags if binding */
+ if (!is_binding) {
+ ses->Suid = le64_to_cpu(rsp->hdr.SessionId);
+ ses->session_flags = le16_to_cpu(rsp->SessionFlags);
+ }
+
+out:
+ kfree_sensitive(ntlmssp_blob);
+ SMB2_sess_free_buffer(sess_data);
+ if (!rc) {
+ sess_data->result = 0;
+ sess_data->func = SMB2_sess_auth_rawntlmssp_authenticate;
+ return;
+ }
+out_err:
+ kfree_sensitive(ses->ntlmssp);
+ ses->ntlmssp = NULL;
+ sess_data->result = rc;
+ sess_data->func = NULL;
+}
+
+static void
+SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
+{
+ int rc;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+ struct smb2_sess_setup_req *req;
+ struct smb2_sess_setup_rsp *rsp = NULL;
+ unsigned char *ntlmssp_blob = NULL;
+ bool use_spnego = false; /* else use raw ntlmssp */
+ u16 blob_length = 0;
+ bool is_binding = false;
+
+ rc = SMB2_sess_alloc_buffer(sess_data);
+ if (rc)
+ goto out;
+
+ req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base;
+ req->hdr.SessionId = cpu_to_le64(ses->Suid);
+
+ rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length,
+ ses, server,
+ sess_data->nls_cp);
+ if (rc) {
+ cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", rc);
+ goto out;
+ }
+
+ if (use_spnego) {
+ /* BB eventually need to add this */
+ cifs_dbg(VFS, "spnego not supported for SMB2 yet\n");
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ sess_data->iov[1].iov_base = ntlmssp_blob;
+ sess_data->iov[1].iov_len = blob_length;
+
+ rc = SMB2_sess_sendreceive(sess_data);
+ if (rc)
+ goto out;
+
+ rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
+
+ spin_lock(&ses->ses_lock);
+ is_binding = (ses->ses_status == SES_GOOD);
+ spin_unlock(&ses->ses_lock);
+
+ /* keep existing ses id and flags if binding */
+ if (!is_binding) {
+ ses->Suid = le64_to_cpu(rsp->hdr.SessionId);
+ ses->session_flags = le16_to_cpu(rsp->SessionFlags);
+ }
+
+ rc = SMB2_sess_establish_session(sess_data);
+#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
+ if (ses->server->dialect < SMB30_PROT_ID) {
+ cifs_dbg(VFS, "%s: dumping generated SMB2 session keys\n", __func__);
+ /*
+ * The session id is opaque in terms of endianness, so we can't
+ * print it as a long long. we dump it as we got it on the wire
+ */
+ cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid),
+ &ses->Suid);
+ cifs_dbg(VFS, "Session Key %*ph\n",
+ SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
+ cifs_dbg(VFS, "Signing Key %*ph\n",
+ SMB3_SIGN_KEY_SIZE, ses->auth_key.response);
+ }
+#endif
+out:
+ kfree_sensitive(ntlmssp_blob);
+ SMB2_sess_free_buffer(sess_data);
+ kfree_sensitive(ses->ntlmssp);
+ ses->ntlmssp = NULL;
+ sess_data->result = rc;
+ sess_data->func = NULL;
+}
+
+static int
+SMB2_select_sec(struct SMB2_sess_data *sess_data)
+{
+ int type;
+ struct cifs_ses *ses = sess_data->ses;
+ struct TCP_Server_Info *server = sess_data->server;
+
+ type = smb2_select_sectype(server, ses->sectype);
+ cifs_dbg(FYI, "sess setup type %d\n", type);
+ if (type == Unspecified) {
+ cifs_dbg(VFS, "Unable to select appropriate authentication method!\n");
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case Kerberos:
+ sess_data->func = SMB2_auth_kerberos;
+ break;
+ case RawNTLMSSP:
+ sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate;
+ break;
+ default:
+ cifs_dbg(VFS, "secType %d not supported!\n", type);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+int
+SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp)
+{
+ int rc = 0;
+ struct SMB2_sess_data *sess_data;
+
+ cifs_dbg(FYI, "Session Setup\n");
+
+ if (!server) {
+ WARN(1, "%s: server is NULL!\n", __func__);
+ return -EIO;
+ }
+
+ sess_data = kzalloc(sizeof(struct SMB2_sess_data), GFP_KERNEL);
+ if (!sess_data)
+ return -ENOMEM;
+
+ sess_data->xid = xid;
+ sess_data->ses = ses;
+ sess_data->server = server;
+ sess_data->buf0_type = CIFS_NO_BUFFER;
+ sess_data->nls_cp = (struct nls_table *) nls_cp;
+ sess_data->previous_session = ses->Suid;
+
+ rc = SMB2_select_sec(sess_data);
+ if (rc)
+ goto out;
+
+ /*
+ * Initialize the session hash with the server one.
+ */
+ memcpy(ses->preauth_sha_hash, server->preauth_sha_hash,
+ SMB2_PREAUTH_HASH_SIZE);
+
+ while (sess_data->func)
+ sess_data->func(sess_data);
+
+ if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign))
+ cifs_server_dbg(VFS, "signing requested but authenticated as guest\n");
+ rc = sess_data->result;
+out:
+ kfree_sensitive(sess_data);
+ return rc;
+}
+
+int
+SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
+{
+ struct smb_rqst rqst;
+ struct smb2_logoff_req *req; /* response is also trivial struct */
+ int rc = 0;
+ struct TCP_Server_Info *server;
+ int flags = 0;
+ unsigned int total_len;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ int resp_buf_type;
+
+ cifs_dbg(FYI, "disconnect session %p\n", ses);
+
+ if (ses && (ses->server))
+ server = ses->server;
+ else
+ return -EIO;
+
+ /* no need to send SMB logoff if uid already closed due to reconnect */
+ spin_lock(&ses->chan_lock);
+ if (CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
+ spin_unlock(&ses->chan_lock);
+ goto smb2_session_already_dead;
+ }
+ spin_unlock(&ses->chan_lock);
+
+ rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, ses->server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ /* since no tcon, smb2_init can not do this, so do here */
+ req->hdr.SessionId = cpu_to_le64(ses->Suid);
+
+ if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
+ flags |= CIFS_TRANSFORM_REQ;
+ else if (server->sign)
+ req->hdr.Flags |= SMB2_FLAGS_SIGNED;
+
+ flags |= CIFS_NO_RSP_BUF;
+
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, ses->server,
+ &rqst, &resp_buf_type, flags, &rsp_iov);
+ cifs_small_buf_release(req);
+ /*
+ * No tcon so can't do
+ * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
+ */
+
+smb2_session_already_dead:
+ return rc;
+}
+
+static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code)
+{
+ cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_failed[code]);
+}
+
+#define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */)
+
+/* These are similar values to what Windows uses */
+static inline void init_copy_chunk_defaults(struct cifs_tcon *tcon)
+{
+ tcon->max_chunks = 256;
+ tcon->max_bytes_chunk = 1048576;
+ tcon->max_bytes_copy = 16777216;
+}
+
+int
+SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
+ struct cifs_tcon *tcon, const struct nls_table *cp)
+{
+ struct smb_rqst rqst;
+ struct smb2_tree_connect_req *req;
+ struct smb2_tree_connect_rsp *rsp = NULL;
+ struct kvec iov[2];
+ struct kvec rsp_iov = { NULL, 0 };
+ int rc = 0;
+ int resp_buftype;
+ int unc_path_len;
+ __le16 *unc_path = NULL;
+ int flags = 0;
+ unsigned int total_len;
+ struct TCP_Server_Info *server;
+
+ /* always use master channel */
+ server = ses->server;
+
+ cifs_dbg(FYI, "TCON\n");
+
+ if (!server || !tree)
+ return -EIO;
+
+ unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
+ if (unc_path == NULL)
+ return -ENOMEM;
+
+ unc_path_len = cifs_strtoUTF16(unc_path, tree, strlen(tree), cp) + 1;
+ unc_path_len *= 2;
+ if (unc_path_len < 2) {
+ kfree(unc_path);
+ return -EINVAL;
+ }
+
+ /* SMB2 TREE_CONNECT request must be called with TreeId == 0 */
+ tcon->tid = 0;
+ atomic_set(&tcon->num_remote_opens, 0);
+ rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, server,
+ (void **) &req, &total_len);
+ if (rc) {
+ kfree(unc_path);
+ return rc;
+ }
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ iov[0].iov_base = (char *)req;
+ /* 1 for pad */
+ iov[0].iov_len = total_len - 1;
+
+ /* Testing shows that buffer offset must be at location of Buffer[0] */
+ req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req)
+ - 1 /* pad */);
+ req->PathLength = cpu_to_le16(unc_path_len - 2);
+ iov[1].iov_base = unc_path;
+ iov[1].iov_len = unc_path_len;
+
+ /*
+ * 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1
+ * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1
+ * (Samba servers don't always set the flag so also check if null user)
+ */
+ if ((server->dialect == SMB311_PROT_ID) &&
+ !smb3_encryption_required(tcon) &&
+ !(ses->session_flags &
+ (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) &&
+ ((ses->user_name != NULL) || (ses->sectype == Kerberos)))
+ req->hdr.Flags |= SMB2_FLAGS_SIGNED;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 2;
+
+ /* Need 64 for max size write so ask for more in case not there yet */
+ req->hdr.CreditRequest = cpu_to_le16(64);
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ cifs_small_buf_release(req);
+ rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base;
+ trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc);
+ if ((rc != 0) || (rsp == NULL)) {
+ cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE);
+ tcon->need_reconnect = true;
+ goto tcon_error_exit;
+ }
+
+ switch (rsp->ShareType) {
+ case SMB2_SHARE_TYPE_DISK:
+ cifs_dbg(FYI, "connection to disk share\n");
+ break;
+ case SMB2_SHARE_TYPE_PIPE:
+ tcon->pipe = true;
+ cifs_dbg(FYI, "connection to pipe share\n");
+ break;
+ case SMB2_SHARE_TYPE_PRINT:
+ tcon->print = true;
+ cifs_dbg(FYI, "connection to printer\n");
+ break;
+ default:
+ cifs_server_dbg(VFS, "unknown share type %d\n", rsp->ShareType);
+ rc = -EOPNOTSUPP;
+ goto tcon_error_exit;
+ }
+
+ tcon->share_flags = le32_to_cpu(rsp->ShareFlags);
+ tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */
+ tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
+ tcon->tid = le32_to_cpu(rsp->hdr.Id.SyncId.TreeId);
+ strscpy(tcon->tree_name, tree, sizeof(tcon->tree_name));
+
+ if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
+ ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
+ cifs_tcon_dbg(VFS, "DFS capability contradicts DFS flag\n");
+
+ if (tcon->seal &&
+ !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
+ cifs_tcon_dbg(VFS, "Encryption is requested but not supported\n");
+
+ init_copy_chunk_defaults(tcon);
+ if (server->ops->validate_negotiate)
+ rc = server->ops->validate_negotiate(xid, tcon);
+tcon_exit:
+
+ free_rsp_buf(resp_buftype, rsp);
+ kfree(unc_path);
+ return rc;
+
+tcon_error_exit:
+ if (rsp && rsp->hdr.Status == STATUS_BAD_NETWORK_NAME)
+ cifs_tcon_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
+ goto tcon_exit;
+}
+
+int
+SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
+{
+ struct smb_rqst rqst;
+ struct smb2_tree_disconnect_req *req; /* response is trivial */
+ int rc = 0;
+ struct cifs_ses *ses = tcon->ses;
+ int flags = 0;
+ unsigned int total_len;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ int resp_buf_type;
+
+ cifs_dbg(FYI, "Tree Disconnect\n");
+
+ if (!ses || !(ses->server))
+ return -EIO;
+
+ trace_smb3_tdis_enter(xid, tcon->tid, ses->Suid, tcon->tree_name);
+ spin_lock(&ses->chan_lock);
+ if ((tcon->need_reconnect) ||
+ (CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses))) {
+ spin_unlock(&ses->chan_lock);
+ return 0;
+ }
+ spin_unlock(&ses->chan_lock);
+
+ invalidate_all_cached_dirs(tcon);
+
+ rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, ses->server,
+ (void **) &req,
+ &total_len);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ flags |= CIFS_NO_RSP_BUF;
+
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, ses->server,
+ &rqst, &resp_buf_type, flags, &rsp_iov);
+ cifs_small_buf_release(req);
+ if (rc) {
+ cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE);
+ trace_smb3_tdis_err(xid, tcon->tid, ses->Suid, rc);
+ }
+ trace_smb3_tdis_done(xid, tcon->tid, ses->Suid);
+
+ return rc;
+}
+
+
+static struct create_durable *
+create_durable_buf(void)
+{
+ struct create_durable *buf;
+
+ buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_durable, Data));
+ buf->ccontext.DataLength = cpu_to_le32(16);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_durable, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */
+ buf->Name[0] = 'D';
+ buf->Name[1] = 'H';
+ buf->Name[2] = 'n';
+ buf->Name[3] = 'Q';
+ return buf;
+}
+
+static struct create_durable *
+create_reconnect_durable_buf(struct cifs_fid *fid)
+{
+ struct create_durable *buf;
+
+ buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_durable, Data));
+ buf->ccontext.DataLength = cpu_to_le32(16);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_durable, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ buf->Data.Fid.PersistentFileId = fid->persistent_fid;
+ buf->Data.Fid.VolatileFileId = fid->volatile_fid;
+ /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT is "DHnC" */
+ buf->Name[0] = 'D';
+ buf->Name[1] = 'H';
+ buf->Name[2] = 'n';
+ buf->Name[3] = 'C';
+ return buf;
+}
+
+static void
+parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf)
+{
+ struct create_on_disk_id *pdisk_id = (struct create_on_disk_id *)cc;
+
+ cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n",
+ pdisk_id->DiskFileId, pdisk_id->VolumeId);
+ buf->IndexNumber = pdisk_id->DiskFileId;
+}
+
+static void
+parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info,
+ struct create_posix_rsp *posix)
+{
+ int sid_len;
+ u8 *beg = (u8 *)cc + le16_to_cpu(cc->DataOffset);
+ u8 *end = beg + le32_to_cpu(cc->DataLength);
+ u8 *sid;
+
+ memset(posix, 0, sizeof(*posix));
+
+ posix->nlink = le32_to_cpu(*(__le32 *)(beg + 0));
+ posix->reparse_tag = le32_to_cpu(*(__le32 *)(beg + 4));
+ posix->mode = le32_to_cpu(*(__le32 *)(beg + 8));
+
+ sid = beg + 12;
+ sid_len = posix_info_sid_size(sid, end);
+ if (sid_len < 0) {
+ cifs_dbg(VFS, "bad owner sid in posix create response\n");
+ return;
+ }
+ memcpy(&posix->owner, sid, sid_len);
+
+ sid = sid + sid_len;
+ sid_len = posix_info_sid_size(sid, end);
+ if (sid_len < 0) {
+ cifs_dbg(VFS, "bad group sid in posix create response\n");
+ return;
+ }
+ memcpy(&posix->group, sid, sid_len);
+
+ cifs_dbg(FYI, "nlink=%d mode=%o reparse_tag=%x\n",
+ posix->nlink, posix->mode, posix->reparse_tag);
+}
+
+void
+smb2_parse_contexts(struct TCP_Server_Info *server,
+ struct smb2_create_rsp *rsp,
+ unsigned int *epoch, char *lease_key, __u8 *oplock,
+ struct smb2_file_all_info *buf,
+ struct create_posix_rsp *posix)
+{
+ char *data_offset;
+ struct create_context *cc;
+ unsigned int next;
+ unsigned int remaining;
+ char *name;
+ static const char smb3_create_tag_posix[] = {
+ 0x93, 0xAD, 0x25, 0x50, 0x9C,
+ 0xB4, 0x11, 0xE7, 0xB4, 0x23, 0x83,
+ 0xDE, 0x96, 0x8B, 0xCD, 0x7C
+ };
+
+ *oplock = 0;
+ data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
+ remaining = le32_to_cpu(rsp->CreateContextsLength);
+ cc = (struct create_context *)data_offset;
+
+ /* Initialize inode number to 0 in case no valid data in qfid context */
+ if (buf)
+ buf->IndexNumber = 0;
+
+ while (remaining >= sizeof(struct create_context)) {
+ name = le16_to_cpu(cc->NameOffset) + (char *)cc;
+ if (le16_to_cpu(cc->NameLength) == 4 &&
+ strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0)
+ *oplock = server->ops->parse_lease_buf(cc, epoch,
+ lease_key);
+ else if (buf && (le16_to_cpu(cc->NameLength) == 4) &&
+ strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0)
+ parse_query_id_ctxt(cc, buf);
+ else if ((le16_to_cpu(cc->NameLength) == 16)) {
+ if (posix &&
+ memcmp(name, smb3_create_tag_posix, 16) == 0)
+ parse_posix_ctxt(cc, buf, posix);
+ }
+ /* else {
+ cifs_dbg(FYI, "Context not matched with len %d\n",
+ le16_to_cpu(cc->NameLength));
+ cifs_dump_mem("Cctxt name: ", name, 4);
+ } */
+
+ next = le32_to_cpu(cc->Next);
+ if (!next)
+ break;
+ remaining -= next;
+ cc = (struct create_context *)((char *)cc + next);
+ }
+
+ if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
+ *oplock = rsp->OplockLevel;
+
+ return;
+}
+
+static int
+add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
+ unsigned int *num_iovec, u8 *lease_key, __u8 *oplock)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+
+ iov[num].iov_base = server->ops->create_lease_buf(lease_key, *oplock);
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = server->vals->create_lease_size;
+ req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset = cpu_to_le32(
+ sizeof(struct smb2_create_req) +
+ iov[num - 1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength,
+ server->vals->create_lease_size);
+ *num_iovec = num + 1;
+ return 0;
+}
+
+static struct create_durable_v2 *
+create_durable_v2_buf(struct cifs_open_parms *oparms)
+{
+ struct cifs_fid *pfid = oparms->fid;
+ struct create_durable_v2 *buf;
+
+ buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_durable_v2, dcontext));
+ buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2));
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_durable_v2, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+
+ /*
+ * NB: Handle timeout defaults to 0, which allows server to choose
+ * (most servers default to 120 seconds) and most clients default to 0.
+ * This can be overridden at mount ("handletimeout=") if the user wants
+ * a different persistent (or resilient) handle timeout for all opens
+ * opens on a particular SMB3 mount.
+ */
+ buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
+ buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
+ generate_random_uuid(buf->dcontext.CreateGuid);
+ memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
+
+ /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
+ buf->Name[0] = 'D';
+ buf->Name[1] = 'H';
+ buf->Name[2] = '2';
+ buf->Name[3] = 'Q';
+ return buf;
+}
+
+static struct create_durable_handle_reconnect_v2 *
+create_reconnect_durable_v2_buf(struct cifs_fid *fid)
+{
+ struct create_durable_handle_reconnect_v2 *buf;
+
+ buf = kzalloc(sizeof(struct create_durable_handle_reconnect_v2),
+ GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->ccontext.DataOffset =
+ cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
+ dcontext));
+ buf->ccontext.DataLength =
+ cpu_to_le32(sizeof(struct durable_reconnect_context_v2));
+ buf->ccontext.NameOffset =
+ cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
+ Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+
+ buf->dcontext.Fid.PersistentFileId = fid->persistent_fid;
+ buf->dcontext.Fid.VolatileFileId = fid->volatile_fid;
+ buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
+ memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16);
+
+ /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */
+ buf->Name[0] = 'D';
+ buf->Name[1] = 'H';
+ buf->Name[2] = '2';
+ buf->Name[3] = 'C';
+ return buf;
+}
+
+static int
+add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
+ struct cifs_open_parms *oparms)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+
+ iov[num].iov_base = create_durable_v2_buf(oparms);
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = sizeof(struct create_durable_v2);
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset =
+ cpu_to_le32(sizeof(struct smb2_create_req) +
+ iov[1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_v2));
+ *num_iovec = num + 1;
+ return 0;
+}
+
+static int
+add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec,
+ struct cifs_open_parms *oparms)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+
+ /* indicate that we don't need to relock the file */
+ oparms->reconnect = false;
+
+ iov[num].iov_base = create_reconnect_durable_v2_buf(oparms->fid);
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = sizeof(struct create_durable_handle_reconnect_v2);
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset =
+ cpu_to_le32(sizeof(struct smb2_create_req) +
+ iov[1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength,
+ sizeof(struct create_durable_handle_reconnect_v2));
+ *num_iovec = num + 1;
+ return 0;
+}
+
+static int
+add_durable_context(struct kvec *iov, unsigned int *num_iovec,
+ struct cifs_open_parms *oparms, bool use_persistent)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+
+ if (use_persistent) {
+ if (oparms->reconnect)
+ return add_durable_reconnect_v2_context(iov, num_iovec,
+ oparms);
+ else
+ return add_durable_v2_context(iov, num_iovec, oparms);
+ }
+
+ if (oparms->reconnect) {
+ iov[num].iov_base = create_reconnect_durable_buf(oparms->fid);
+ /* indicate that we don't need to relock the file */
+ oparms->reconnect = false;
+ } else
+ iov[num].iov_base = create_durable_buf();
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = sizeof(struct create_durable);
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset =
+ cpu_to_le32(sizeof(struct smb2_create_req) +
+ iov[1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable));
+ *num_iovec = num + 1;
+ return 0;
+}
+
+/* See MS-SMB2 2.2.13.2.7 */
+static struct crt_twarp_ctxt *
+create_twarp_buf(__u64 timewarp)
+{
+ struct crt_twarp_ctxt *buf;
+
+ buf = kzalloc(sizeof(struct crt_twarp_ctxt), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct crt_twarp_ctxt, Timestamp));
+ buf->ccontext.DataLength = cpu_to_le32(8);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct crt_twarp_ctxt, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_TIMEWARP_TOKEN is "TWrp" */
+ buf->Name[0] = 'T';
+ buf->Name[1] = 'W';
+ buf->Name[2] = 'r';
+ buf->Name[3] = 'p';
+ buf->Timestamp = cpu_to_le64(timewarp);
+ return buf;
+}
+
+/* See MS-SMB2 2.2.13.2.7 */
+static int
+add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+
+ iov[num].iov_base = create_twarp_buf(timewarp);
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = sizeof(struct crt_twarp_ctxt);
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset = cpu_to_le32(
+ sizeof(struct smb2_create_req) +
+ iov[num - 1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_twarp_ctxt));
+ *num_iovec = num + 1;
+ return 0;
+}
+
+/* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */
+static void setup_owner_group_sids(char *buf)
+{
+ struct owner_group_sids *sids = (struct owner_group_sids *)buf;
+
+ /* Populate the user ownership fields S-1-5-88-1 */
+ sids->owner.Revision = 1;
+ sids->owner.NumAuth = 3;
+ sids->owner.Authority[5] = 5;
+ sids->owner.SubAuthorities[0] = cpu_to_le32(88);
+ sids->owner.SubAuthorities[1] = cpu_to_le32(1);
+ sids->owner.SubAuthorities[2] = cpu_to_le32(current_fsuid().val);
+
+ /* Populate the group ownership fields S-1-5-88-2 */
+ sids->group.Revision = 1;
+ sids->group.NumAuth = 3;
+ sids->group.Authority[5] = 5;
+ sids->group.SubAuthorities[0] = cpu_to_le32(88);
+ sids->group.SubAuthorities[1] = cpu_to_le32(2);
+ sids->group.SubAuthorities[2] = cpu_to_le32(current_fsgid().val);
+
+ cifs_dbg(FYI, "owner S-1-5-88-1-%d, group S-1-5-88-2-%d\n", current_fsuid().val, current_fsgid().val);
+}
+
+/* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */
+static struct crt_sd_ctxt *
+create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
+{
+ struct crt_sd_ctxt *buf;
+ __u8 *ptr, *aclptr;
+ unsigned int acelen, acl_size, ace_count;
+ unsigned int owner_offset = 0;
+ unsigned int group_offset = 0;
+ struct smb3_acl acl = {};
+
+ *len = round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8);
+
+ if (set_owner) {
+ /* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */
+ *len += sizeof(struct owner_group_sids);
+ }
+
+ buf = kzalloc(*len, GFP_KERNEL);
+ if (buf == NULL)
+ return buf;
+
+ ptr = (__u8 *)&buf[1];
+ if (set_owner) {
+ /* offset fields are from beginning of security descriptor not of create context */
+ owner_offset = ptr - (__u8 *)&buf->sd;
+ buf->sd.OffsetOwner = cpu_to_le32(owner_offset);
+ group_offset = owner_offset + offsetof(struct owner_group_sids, group);
+ buf->sd.OffsetGroup = cpu_to_le32(group_offset);
+
+ setup_owner_group_sids(ptr);
+ ptr += sizeof(struct owner_group_sids);
+ } else {
+ buf->sd.OffsetOwner = 0;
+ buf->sd.OffsetGroup = 0;
+ }
+
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, sd));
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */
+ buf->Name[0] = 'S';
+ buf->Name[1] = 'e';
+ buf->Name[2] = 'c';
+ buf->Name[3] = 'D';
+ buf->sd.Revision = 1; /* Must be one see MS-DTYP 2.4.6 */
+
+ /*
+ * ACL is "self relative" ie ACL is stored in contiguous block of memory
+ * and "DP" ie the DACL is present
+ */
+ buf->sd.Control = cpu_to_le16(ACL_CONTROL_SR | ACL_CONTROL_DP);
+
+ /* offset owner, group and Sbz1 and SACL are all zero */
+ buf->sd.OffsetDacl = cpu_to_le32(ptr - (__u8 *)&buf->sd);
+ /* Ship the ACL for now. we will copy it into buf later. */
+ aclptr = ptr;
+ ptr += sizeof(struct smb3_acl);
+
+ /* create one ACE to hold the mode embedded in reserved special SID */
+ acelen = setup_special_mode_ACE((struct cifs_ace *)ptr, (__u64)mode);
+ ptr += acelen;
+ acl_size = acelen + sizeof(struct smb3_acl);
+ ace_count = 1;
+
+ if (set_owner) {
+ /* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
+ acelen = setup_special_user_owner_ACE((struct cifs_ace *)ptr);
+ ptr += acelen;
+ acl_size += acelen;
+ ace_count += 1;
+ }
+
+ /* and one more ACE to allow access for authenticated users */
+ acelen = setup_authusers_ACE((struct cifs_ace *)ptr);
+ ptr += acelen;
+ acl_size += acelen;
+ ace_count += 1;
+
+ acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */
+ acl.AclSize = cpu_to_le16(acl_size);
+ acl.AceCount = cpu_to_le16(ace_count);
+ /* acl.Sbz1 and Sbz2 MBZ so are not set here, but initialized above */
+ memcpy(aclptr, &acl, sizeof(struct smb3_acl));
+
+ buf->ccontext.DataLength = cpu_to_le32(ptr - (__u8 *)&buf->sd);
+ *len = round_up((unsigned int)(ptr - (__u8 *)buf), 8);
+
+ return buf;
+}
+
+static int
+add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+ unsigned int len = 0;
+
+ iov[num].iov_base = create_sd_buf(mode, set_owner, &len);
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = len;
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset = cpu_to_le32(
+ sizeof(struct smb2_create_req) +
+ iov[num - 1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength, len);
+ *num_iovec = num + 1;
+ return 0;
+}
+
+static struct crt_query_id_ctxt *
+create_query_id_buf(void)
+{
+ struct crt_query_id_ctxt *buf;
+
+ buf = kzalloc(sizeof(struct crt_query_id_ctxt), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->ccontext.DataOffset = cpu_to_le16(0);
+ buf->ccontext.DataLength = cpu_to_le32(0);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct crt_query_id_ctxt, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_QUERY_ON_DISK_ID is "QFid" */
+ buf->Name[0] = 'Q';
+ buf->Name[1] = 'F';
+ buf->Name[2] = 'i';
+ buf->Name[3] = 'd';
+ return buf;
+}
+
+/* See MS-SMB2 2.2.13.2.9 */
+static int
+add_query_id_context(struct kvec *iov, unsigned int *num_iovec)
+{
+ struct smb2_create_req *req = iov[0].iov_base;
+ unsigned int num = *num_iovec;
+
+ iov[num].iov_base = create_query_id_buf();
+ if (iov[num].iov_base == NULL)
+ return -ENOMEM;
+ iov[num].iov_len = sizeof(struct crt_query_id_ctxt);
+ if (!req->CreateContextsOffset)
+ req->CreateContextsOffset = cpu_to_le32(
+ sizeof(struct smb2_create_req) +
+ iov[num - 1].iov_len);
+ le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_query_id_ctxt));
+ *num_iovec = num + 1;
+ return 0;
+}
+
+static int
+alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
+ const char *treename, const __le16 *path)
+{
+ int treename_len, path_len;
+ struct nls_table *cp;
+ const __le16 sep[] = {cpu_to_le16('\\'), cpu_to_le16(0x0000)};
+
+ /*
+ * skip leading "\\"
+ */
+ treename_len = strlen(treename);
+ if (treename_len < 2 || !(treename[0] == '\\' && treename[1] == '\\'))
+ return -EINVAL;
+
+ treename += 2;
+ treename_len -= 2;
+
+ path_len = UniStrnlen((wchar_t *)path, PATH_MAX);
+
+ /* make room for one path separator only if @path isn't empty */
+ *out_len = treename_len + (path[0] ? 1 : 0) + path_len;
+
+ /*
+ * final path needs to be 8-byte aligned as specified in
+ * MS-SMB2 2.2.13 SMB2 CREATE Request.
+ */
+ *out_size = round_up(*out_len * sizeof(__le16), 8);
+ *out_path = kzalloc(*out_size + sizeof(__le16) /* null */, GFP_KERNEL);
+ if (!*out_path)
+ return -ENOMEM;
+
+ cp = load_nls_default();
+ cifs_strtoUTF16(*out_path, treename, treename_len, cp);
+
+ /* Do not append the separator if the path is empty */
+ if (path[0] != cpu_to_le16(0x0000)) {
+ UniStrcat(*out_path, sep);
+ UniStrcat(*out_path, path);
+ }
+
+ unload_nls(cp);
+
+ return 0;
+}
+
+int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
+ umode_t mode, struct cifs_tcon *tcon,
+ const char *full_path,
+ struct cifs_sb_info *cifs_sb)
+{
+ struct smb_rqst rqst;
+ struct smb2_create_req *req;
+ struct smb2_create_rsp *rsp = NULL;
+ struct cifs_ses *ses = tcon->ses;
+ struct kvec iov[3]; /* make sure at least one for each open context */
+ struct kvec rsp_iov = {NULL, 0};
+ int resp_buftype;
+ int uni_path_len;
+ __le16 *copy_path = NULL;
+ int copy_size;
+ int rc = 0;
+ unsigned int n_iov = 2;
+ __u32 file_attributes = 0;
+ char *pc_buf = NULL;
+ int flags = 0;
+ unsigned int total_len;
+ __le16 *utf16_path = NULL;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+
+ cifs_dbg(FYI, "mkdir\n");
+
+ /* resource #1: path allocation */
+ utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
+
+ if (!ses || !server) {
+ rc = -EIO;
+ goto err_free_path;
+ }
+
+ /* resource #2: request */
+ rc = smb2_plain_req_init(SMB2_CREATE, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ goto err_free_path;
+
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ req->ImpersonationLevel = IL_IMPERSONATION;
+ req->DesiredAccess = cpu_to_le32(FILE_WRITE_ATTRIBUTES);
+ /* File attributes ignored on open (used in create though) */
+ req->FileAttributes = cpu_to_le32(file_attributes);
+ req->ShareAccess = FILE_SHARE_ALL_LE;
+ req->CreateDisposition = cpu_to_le32(FILE_CREATE);
+ req->CreateOptions = cpu_to_le32(CREATE_NOT_FILE);
+
+ iov[0].iov_base = (char *)req;
+ /* -1 since last byte is buf[0] which is sent below (path) */
+ iov[0].iov_len = total_len - 1;
+
+ req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
+
+ /* [MS-SMB2] 2.2.13 NameOffset:
+ * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
+ * the SMB2 header, the file name includes a prefix that will
+ * be processed during DFS name normalization as specified in
+ * section 3.3.5.9. Otherwise, the file name is relative to
+ * the share that is identified by the TreeId in the SMB2
+ * header.
+ */
+ if (tcon->share_flags & SHI1005_FLAGS_DFS) {
+ int name_len;
+
+ req->hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
+ rc = alloc_path_with_tree_prefix(©_path, ©_size,
+ &name_len,
+ tcon->tree_name, utf16_path);
+ if (rc)
+ goto err_free_req;
+
+ req->NameLength = cpu_to_le16(name_len * 2);
+ uni_path_len = copy_size;
+ /* free before overwriting resource */
+ kfree(utf16_path);
+ utf16_path = copy_path;
+ } else {
+ uni_path_len = (2 * UniStrnlen((wchar_t *)utf16_path, PATH_MAX)) + 2;
+ /* MUST set path len (NameLength) to 0 opening root of share */
+ req->NameLength = cpu_to_le16(uni_path_len - 2);
+ if (uni_path_len % 8 != 0) {
+ copy_size = roundup(uni_path_len, 8);
+ copy_path = kzalloc(copy_size, GFP_KERNEL);
+ if (!copy_path) {
+ rc = -ENOMEM;
+ goto err_free_req;
+ }
+ memcpy((char *)copy_path, (const char *)utf16_path,
+ uni_path_len);
+ uni_path_len = copy_size;
+ /* free before overwriting resource */
+ kfree(utf16_path);
+ utf16_path = copy_path;
+ }
+ }
+
+ iov[1].iov_len = uni_path_len;
+ iov[1].iov_base = utf16_path;
+ req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE;
+
+ if (tcon->posix_extensions) {
+ /* resource #3: posix buf */
+ rc = add_posix_context(iov, &n_iov, mode);
+ if (rc)
+ goto err_free_req;
+ pc_buf = iov[n_iov-1].iov_base;
+ }
+
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = n_iov;
+
+ /* no need to inc num_remote_opens because we close it just below */
+ trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, full_path, CREATE_NOT_FILE,
+ FILE_WRITE_ATTRIBUTES);
+ /* resource #4: response buffer */
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ if (rc) {
+ cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
+ trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid,
+ CREATE_NOT_FILE,
+ FILE_WRITE_ATTRIBUTES, rc);
+ goto err_free_rsp_buf;
+ }
+
+ /*
+ * Although unlikely to be possible for rsp to be null and rc not set,
+ * adding check below is slightly safer long term (and quiets Coverity
+ * warning)
+ */
+ rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
+ if (rsp == NULL) {
+ rc = -EIO;
+ kfree(pc_buf);
+ goto err_free_req;
+ }
+
+ trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid,
+ CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES);
+
+ SMB2_close(xid, tcon, rsp->PersistentFileId, rsp->VolatileFileId);
+
+ /* Eventually save off posix specific response info and timestaps */
+
+err_free_rsp_buf:
+ free_rsp_buf(resp_buftype, rsp);
+ kfree(pc_buf);
+err_free_req:
+ cifs_small_buf_release(req);
+err_free_path:
+ kfree(utf16_path);
+ return rc;
+}
+
+int
+SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
+ struct smb_rqst *rqst, __u8 *oplock,
+ struct cifs_open_parms *oparms, __le16 *path)
+{
+ struct smb2_create_req *req;
+ unsigned int n_iov = 2;
+ __u32 file_attributes = 0;
+ int copy_size;
+ int uni_path_len;
+ unsigned int total_len;
+ struct kvec *iov = rqst->rq_iov;
+ __le16 *copy_path;
+ int rc;
+
+ rc = smb2_plain_req_init(SMB2_CREATE, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ iov[0].iov_base = (char *)req;
+ /* -1 since last byte is buf[0] which is sent below (path) */
+ iov[0].iov_len = total_len - 1;
+
+ if (oparms->create_options & CREATE_OPTION_READONLY)
+ file_attributes |= ATTR_READONLY;
+ if (oparms->create_options & CREATE_OPTION_SPECIAL)
+ file_attributes |= ATTR_SYSTEM;
+
+ req->ImpersonationLevel = IL_IMPERSONATION;
+ req->DesiredAccess = cpu_to_le32(oparms->desired_access);
+ /* File attributes ignored on open (used in create though) */
+ req->FileAttributes = cpu_to_le32(file_attributes);
+ req->ShareAccess = FILE_SHARE_ALL_LE;
+
+ req->CreateDisposition = cpu_to_le32(oparms->disposition);
+ req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK);
+ req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
+
+ /* [MS-SMB2] 2.2.13 NameOffset:
+ * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
+ * the SMB2 header, the file name includes a prefix that will
+ * be processed during DFS name normalization as specified in
+ * section 3.3.5.9. Otherwise, the file name is relative to
+ * the share that is identified by the TreeId in the SMB2
+ * header.
+ */
+ if (tcon->share_flags & SHI1005_FLAGS_DFS) {
+ int name_len;
+
+ req->hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
+ rc = alloc_path_with_tree_prefix(©_path, ©_size,
+ &name_len,
+ tcon->tree_name, path);
+ if (rc)
+ return rc;
+ req->NameLength = cpu_to_le16(name_len * 2);
+ uni_path_len = copy_size;
+ path = copy_path;
+ } else {
+ uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
+ /* MUST set path len (NameLength) to 0 opening root of share */
+ req->NameLength = cpu_to_le16(uni_path_len - 2);
+ copy_size = round_up(uni_path_len, 8);
+ copy_path = kzalloc(copy_size, GFP_KERNEL);
+ if (!copy_path)
+ return -ENOMEM;
+ memcpy((char *)copy_path, (const char *)path,
+ uni_path_len);
+ uni_path_len = copy_size;
+ path = copy_path;
+ }
+
+ iov[1].iov_len = uni_path_len;
+ iov[1].iov_base = path;
+
+ if ((!server->oplocks) || (tcon->no_lease))
+ *oplock = SMB2_OPLOCK_LEVEL_NONE;
+
+ if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) ||
+ *oplock == SMB2_OPLOCK_LEVEL_NONE)
+ req->RequestedOplockLevel = *oplock;
+ else if (!(server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) &&
+ (oparms->create_options & CREATE_NOT_FILE))
+ req->RequestedOplockLevel = *oplock; /* no srv lease support */
+ else {
+ rc = add_lease_context(server, iov, &n_iov,
+ oparms->fid->lease_key, oplock);
+ if (rc)
+ return rc;
+ }
+
+ if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) {
+ /* need to set Next field of lease context if we request it */
+ if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) {
+ struct create_context *ccontext =
+ (struct create_context *)iov[n_iov-1].iov_base;
+ ccontext->Next =
+ cpu_to_le32(server->vals->create_lease_size);
+ }
+
+ rc = add_durable_context(iov, &n_iov, oparms,
+ tcon->use_persistent);
+ if (rc)
+ return rc;
+ }
+
+ if (tcon->posix_extensions) {
+ if (n_iov > 2) {
+ struct create_context *ccontext =
+ (struct create_context *)iov[n_iov-1].iov_base;
+ ccontext->Next =
+ cpu_to_le32(iov[n_iov-1].iov_len);
+ }
+
+ rc = add_posix_context(iov, &n_iov, oparms->mode);
+ if (rc)
+ return rc;
+ }
+
+ if (tcon->snapshot_time) {
+ cifs_dbg(FYI, "adding snapshot context\n");
+ if (n_iov > 2) {
+ struct create_context *ccontext =
+ (struct create_context *)iov[n_iov-1].iov_base;
+ ccontext->Next =
+ cpu_to_le32(iov[n_iov-1].iov_len);
+ }
+
+ rc = add_twarp_context(iov, &n_iov, tcon->snapshot_time);
+ if (rc)
+ return rc;
+ }
+
+ if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) {
+ bool set_mode;
+ bool set_owner;
+
+ if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
+ (oparms->mode != ACL_NO_MODE))
+ set_mode = true;
+ else {
+ set_mode = false;
+ oparms->mode = ACL_NO_MODE;
+ }
+
+ if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
+ set_owner = true;
+ else
+ set_owner = false;
+
+ if (set_owner | set_mode) {
+ if (n_iov > 2) {
+ struct create_context *ccontext =
+ (struct create_context *)iov[n_iov-1].iov_base;
+ ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
+ }
+
+ cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
+ rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner);
+ if (rc)
+ return rc;
+ }
+ }
+
+ if (n_iov > 2) {
+ struct create_context *ccontext =
+ (struct create_context *)iov[n_iov-1].iov_base;
+ ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
+ }
+ add_query_id_context(iov, &n_iov);
+
+ rqst->rq_nvec = n_iov;
+ return 0;
+}
+
+/* rq_iov[0] is the request and is released by cifs_small_buf_release().
+ * All other vectors are freed by kfree().
+ */
+void
+SMB2_open_free(struct smb_rqst *rqst)
+{
+ int i;
+
+ if (rqst && rqst->rq_iov) {
+ cifs_small_buf_release(rqst->rq_iov[0].iov_base);
+ for (i = 1; i < rqst->rq_nvec; i++)
+ if (rqst->rq_iov[i].iov_base != smb2_padding)
+ kfree(rqst->rq_iov[i].iov_base);
+ }
+}
+
+int
+SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
+ __u8 *oplock, struct smb2_file_all_info *buf,
+ struct create_posix_rsp *posix,
+ struct kvec *err_iov, int *buftype)
+{
+ struct smb_rqst rqst;
+ struct smb2_create_rsp *rsp = NULL;
+ struct cifs_tcon *tcon = oparms->tcon;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ struct kvec iov[SMB2_CREATE_IOV_SIZE];
+ struct kvec rsp_iov = {NULL, 0};
+ int resp_buftype = CIFS_NO_BUFFER;
+ int rc = 0;
+ int flags = 0;
+
+ cifs_dbg(FYI, "create/open\n");
+ if (!ses || !server)
+ return -EIO;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ memset(&iov, 0, sizeof(iov));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+ rc = SMB2_open_init(tcon, server,
+ &rqst, oplock, oparms, path);
+ if (rc)
+ goto creat_exit;
+
+ trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, oparms->path,
+ oparms->create_options, oparms->desired_access);
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags,
+ &rsp_iov);
+ rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
+
+ if (rc != 0) {
+ cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
+ if (err_iov && rsp) {
+ *err_iov = rsp_iov;
+ *buftype = resp_buftype;
+ resp_buftype = CIFS_NO_BUFFER;
+ rsp = NULL;
+ }
+ trace_smb3_open_err(xid, tcon->tid, ses->Suid,
+ oparms->create_options, oparms->desired_access, rc);
+ if (rc == -EREMCHG) {
+ pr_warn_once("server share %s deleted\n",
+ tcon->tree_name);
+ tcon->need_reconnect = true;
+ }
+ goto creat_exit;
+ } else if (rsp == NULL) /* unlikely to happen, but safer to check */
+ goto creat_exit;
+ else
+ trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid,
+ oparms->create_options, oparms->desired_access);
+
+ atomic_inc(&tcon->num_remote_opens);
+ oparms->fid->persistent_fid = rsp->PersistentFileId;
+ oparms->fid->volatile_fid = rsp->VolatileFileId;
+ oparms->fid->access = oparms->desired_access;
+#ifdef CONFIG_CIFS_DEBUG2
+ oparms->fid->mid = le64_to_cpu(rsp->hdr.MessageId);
+#endif /* CIFS_DEBUG2 */
+
+ if (buf) {
+ buf->CreationTime = rsp->CreationTime;
+ buf->LastAccessTime = rsp->LastAccessTime;
+ buf->LastWriteTime = rsp->LastWriteTime;
+ buf->ChangeTime = rsp->ChangeTime;
+ buf->AllocationSize = rsp->AllocationSize;
+ buf->EndOfFile = rsp->EndofFile;
+ buf->Attributes = rsp->FileAttributes;
+ buf->NumberOfLinks = cpu_to_le32(1);
+ buf->DeletePending = 0;
+ }
+
+
+ smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
+ oparms->fid->lease_key, oplock, buf, posix);
+creat_exit:
+ SMB2_open_free(&rqst);
+ free_rsp_buf(resp_buftype, rsp);
+ return rc;
+}
+
+int
+SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid, u32 opcode,
+ char *in_data, u32 indatalen,
+ __u32 max_response_size)
+{
+ struct smb2_ioctl_req *req;
+ struct kvec *iov = rqst->rq_iov;
+ unsigned int total_len;
+ int rc;
+ char *in_data_buf;
+
+ rc = smb2_ioctl_req_init(opcode, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ if (indatalen) {
+ /*
+ * indatalen is usually small at a couple of bytes max, so
+ * just allocate through generic pool
+ */
+ in_data_buf = kmemdup(in_data, indatalen, GFP_NOFS);
+ if (!in_data_buf) {
+ cifs_small_buf_release(req);
+ return -ENOMEM;
+ }
+ }
+
+ req->CtlCode = cpu_to_le32(opcode);
+ req->PersistentFileId = persistent_fid;
+ req->VolatileFileId = volatile_fid;
+
+ iov[0].iov_base = (char *)req;
+ /*
+ * If no input data, the size of ioctl struct in
+ * protocol spec still includes a 1 byte data buffer,
+ * but if input data passed to ioctl, we do not
+ * want to double count this, so we do not send
+ * the dummy one byte of data in iovec[0] if sending
+ * input data (in iovec[1]).
+ */
+ if (indatalen) {
+ req->InputCount = cpu_to_le32(indatalen);
+ /* do not set InputOffset if no input data */
+ req->InputOffset =
+ cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer));
+ rqst->rq_nvec = 2;
+ iov[0].iov_len = total_len - 1;
+ iov[1].iov_base = in_data_buf;
+ iov[1].iov_len = indatalen;
+ } else {
+ rqst->rq_nvec = 1;
+ iov[0].iov_len = total_len;
+ }
+
+ req->OutputOffset = 0;
+ req->OutputCount = 0; /* MBZ */
+
+ /*
+ * In most cases max_response_size is set to 16K (CIFSMaxBufSize)
+ * We Could increase default MaxOutputResponse, but that could require
+ * more credits. Windows typically sets this smaller, but for some
+ * ioctls it may be useful to allow server to send more. No point
+ * limiting what the server can send as long as fits in one credit
+ * We can not handle more than CIFS_MAX_BUF_SIZE yet but may want
+ * to increase this limit up in the future.
+ * Note that for snapshot queries that servers like Azure expect that
+ * the first query be minimal size (and just used to get the number/size
+ * of previous versions) so response size must be specified as EXACTLY
+ * sizeof(struct snapshot_array) which is 16 when rounded up to multiple
+ * of eight bytes. Currently that is the only case where we set max
+ * response size smaller.
+ */
+ req->MaxOutputResponse = cpu_to_le32(max_response_size);
+ req->hdr.CreditCharge =
+ cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size),
+ SMB2_MAX_BUFFER_SIZE));
+ /* always an FSCTL (for now) */
+ req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
+
+ /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
+ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
+ req->hdr.Flags |= SMB2_FLAGS_SIGNED;
+
+ return 0;
+}
+
+void
+SMB2_ioctl_free(struct smb_rqst *rqst)
+{
+ int i;
+ if (rqst && rqst->rq_iov) {
+ cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
+ for (i = 1; i < rqst->rq_nvec; i++)
+ if (rqst->rq_iov[i].iov_base != smb2_padding)
+ kfree(rqst->rq_iov[i].iov_base);
+ }
+}
+
+
+/*
+ * SMB2 IOCTL is used for both IOCTLs and FSCTLs
+ */
+int
+SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
+ u64 volatile_fid, u32 opcode, char *in_data, u32 indatalen,
+ u32 max_out_data_len, char **out_data,
+ u32 *plen /* returned data len */)
+{
+ struct smb_rqst rqst;
+ struct smb2_ioctl_rsp *rsp = NULL;
+ struct cifs_ses *ses;
+ struct TCP_Server_Info *server;
+ struct kvec iov[SMB2_IOCTL_IOV_SIZE];
+ struct kvec rsp_iov = {NULL, 0};
+ int resp_buftype = CIFS_NO_BUFFER;
+ int rc = 0;
+ int flags = 0;
+
+ cifs_dbg(FYI, "SMB2 IOCTL\n");
+
+ if (out_data != NULL)
+ *out_data = NULL;
+
+ /* zero out returned data len, in case of error */
+ if (plen)
+ *plen = 0;
+
+ if (!tcon)
+ return -EIO;
+
+ ses = tcon->ses;
+ if (!ses)
+ return -EIO;
+
+ server = cifs_pick_channel(ses);
+ if (!server)
+ return -EIO;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ memset(&iov, 0, sizeof(iov));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = SMB2_IOCTL_IOV_SIZE;
+
+ rc = SMB2_ioctl_init(tcon, server,
+ &rqst, persistent_fid, volatile_fid, opcode,
+ in_data, indatalen, max_out_data_len);
+ if (rc)
+ goto ioctl_exit;
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags,
+ &rsp_iov);
+ rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base;
+
+ if (rc != 0)
+ trace_smb3_fsctl_err(xid, persistent_fid, tcon->tid,
+ ses->Suid, 0, opcode, rc);
+
+ if ((rc != 0) && (rc != -EINVAL) && (rc != -E2BIG)) {
+ cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
+ goto ioctl_exit;
+ } else if (rc == -EINVAL) {
+ if ((opcode != FSCTL_SRV_COPYCHUNK_WRITE) &&
+ (opcode != FSCTL_SRV_COPYCHUNK)) {
+ cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
+ goto ioctl_exit;
+ }
+ } else if (rc == -E2BIG) {
+ if (opcode != FSCTL_QUERY_ALLOCATED_RANGES) {
+ cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
+ goto ioctl_exit;
+ }
+ }
+
+ /* check if caller wants to look at return data or just return rc */
+ if ((plen == NULL) || (out_data == NULL))
+ goto ioctl_exit;
+
+ /*
+ * Although unlikely to be possible for rsp to be null and rc not set,
+ * adding check below is slightly safer long term (and quiets Coverity
+ * warning)
+ */
+ if (rsp == NULL) {
+ rc = -EIO;
+ goto ioctl_exit;
+ }
+
+ *plen = le32_to_cpu(rsp->OutputCount);
+
+ /* We check for obvious errors in the output buffer length and offset */
+ if (*plen == 0)
+ goto ioctl_exit; /* server returned no data */
+ else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) {
+ cifs_tcon_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen);
+ *plen = 0;
+ rc = -EIO;
+ goto ioctl_exit;
+ }
+
+ if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) {
+ cifs_tcon_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
+ le32_to_cpu(rsp->OutputOffset));
+ *plen = 0;
+ rc = -EIO;
+ goto ioctl_exit;
+ }
+
+ *out_data = kmemdup((char *)rsp + le32_to_cpu(rsp->OutputOffset),
+ *plen, GFP_KERNEL);
+ if (*out_data == NULL) {
+ rc = -ENOMEM;
+ goto ioctl_exit;
+ }
+
+ioctl_exit:
+ SMB2_ioctl_free(&rqst);
+ free_rsp_buf(resp_buftype, rsp);
+ return rc;
+}
+
+/*
+ * Individual callers to ioctl worker function follow
+ */
+
+int
+SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid)
+{
+ int rc;
+ struct compress_ioctl fsctl_input;
+ char *ret_data = NULL;
+
+ fsctl_input.CompressionState =
+ cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
+
+ rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
+ FSCTL_SET_COMPRESSION,
+ (char *)&fsctl_input /* data input */,
+ 2 /* in data len */, CIFSMaxBufSize /* max out data */,
+ &ret_data /* out data */, NULL);
+
+ cifs_dbg(FYI, "set compression rc %d\n", rc);
+
+ return rc;
+}
+
+int
+SMB2_close_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid, bool query_attrs)
+{
+ struct smb2_close_req *req;
+ struct kvec *iov = rqst->rq_iov;
+ unsigned int total_len;
+ int rc;
+
+ rc = smb2_plain_req_init(SMB2_CLOSE, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ req->PersistentFileId = persistent_fid;
+ req->VolatileFileId = volatile_fid;
+ if (query_attrs)
+ req->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB;
+ else
+ req->Flags = 0;
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+
+ return 0;
+}
+
+void
+SMB2_close_free(struct smb_rqst *rqst)
+{
+ if (rqst && rqst->rq_iov)
+ cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
+}
+
+int
+__SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ struct smb2_file_network_open_info *pbuf)
+{
+ struct smb_rqst rqst;
+ struct smb2_close_rsp *rsp = NULL;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ int resp_buftype = CIFS_NO_BUFFER;
+ int rc = 0;
+ int flags = 0;
+ bool query_attrs = false;
+
+ cifs_dbg(FYI, "Close\n");
+
+ if (!ses || !server)
+ return -EIO;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ memset(&iov, 0, sizeof(iov));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ /* check if need to ask server to return timestamps in close response */
+ if (pbuf)
+ query_attrs = true;
+
+ trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid);
+ rc = SMB2_close_init(tcon, server,
+ &rqst, persistent_fid, volatile_fid,
+ query_attrs);
+ if (rc)
+ goto close_exit;
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ rsp = (struct smb2_close_rsp *)rsp_iov.iov_base;
+
+ if (rc != 0) {
+ cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
+ trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid,
+ rc);
+ goto close_exit;
+ } else {
+ trace_smb3_close_done(xid, persistent_fid, tcon->tid,
+ ses->Suid);
+ /*
+ * Note that have to subtract 4 since struct network_open_info
+ * has a final 4 byte pad that close response does not have
+ */
+ if (pbuf)
+ memcpy(pbuf, (char *)&rsp->CreationTime, sizeof(*pbuf) - 4);
+ }
+
+ atomic_dec(&tcon->num_remote_opens);
+close_exit:
+ SMB2_close_free(&rqst);
+ free_rsp_buf(resp_buftype, rsp);
+
+ /* retry close in a worker thread if this one is interrupted */
+ if (is_interrupt_error(rc)) {
+ int tmp_rc;
+
+ tmp_rc = smb2_handle_cancelled_close(tcon, persistent_fid,
+ volatile_fid);
+ if (tmp_rc)
+ cifs_dbg(VFS, "handle cancelled close fid 0x%llx returned error %d\n",
+ persistent_fid, tmp_rc);
+ }
+ return rc;
+}
+
+int
+SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid)
+{
+ return __SMB2_close(xid, tcon, persistent_fid, volatile_fid, NULL);
+}
+
+int
+smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
+ struct kvec *iov, unsigned int min_buf_size)
+{
+ unsigned int smb_len = iov->iov_len;
+ char *end_of_smb = smb_len + (char *)iov->iov_base;
+ char *begin_of_buf = offset + (char *)iov->iov_base;
+ char *end_of_buf = begin_of_buf + buffer_length;
+
+
+ if (buffer_length < min_buf_size) {
+ cifs_dbg(VFS, "buffer length %d smaller than minimum size %d\n",
+ buffer_length, min_buf_size);
+ return -EINVAL;
+ }
+
+ /* check if beyond RFC1001 maximum length */
+ if ((smb_len > 0x7FFFFF) || (buffer_length > 0x7FFFFF)) {
+ cifs_dbg(VFS, "buffer length %d or smb length %d too large\n",
+ buffer_length, smb_len);
+ return -EINVAL;
+ }
+
+ if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) {
+ cifs_dbg(VFS, "Invalid server response, bad offset to data\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * If SMB buffer fields are valid, copy into temporary buffer to hold result.
+ * Caller must free buffer.
+ */
+int
+smb2_validate_and_copy_iov(unsigned int offset, unsigned int buffer_length,
+ struct kvec *iov, unsigned int minbufsize,
+ char *data)
+{
+ char *begin_of_buf = offset + (char *)iov->iov_base;
+ int rc;
+
+ if (!data)
+ return -EINVAL;
+
+ rc = smb2_validate_iov(offset, buffer_length, iov, minbufsize);
+ if (rc)
+ return rc;
+
+ memcpy(data, begin_of_buf, minbufsize);
+
+ return 0;
+}
+
+int
+SMB2_query_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid,
+ u8 info_class, u8 info_type, u32 additional_info,
+ size_t output_len, size_t input_len, void *input)
+{
+ struct smb2_query_info_req *req;
+ struct kvec *iov = rqst->rq_iov;
+ unsigned int total_len;
+ int rc;
+
+ rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ req->InfoType = info_type;
+ req->FileInfoClass = info_class;
+ req->PersistentFileId = persistent_fid;
+ req->VolatileFileId = volatile_fid;
+ req->AdditionalInformation = cpu_to_le32(additional_info);
+
+ req->OutputBufferLength = cpu_to_le32(output_len);
+ if (input_len) {
+ req->InputBufferLength = cpu_to_le32(input_len);
+ /* total_len for smb query request never close to le16 max */
+ req->InputBufferOffset = cpu_to_le16(total_len - 1);
+ memcpy(req->Buffer, input, input_len);
+ }
+
+ iov[0].iov_base = (char *)req;
+ /* 1 for Buffer */
+ iov[0].iov_len = total_len - 1 + input_len;
+ return 0;
+}
+
+void
+SMB2_query_info_free(struct smb_rqst *rqst)
+{
+ if (rqst && rqst->rq_iov)
+ cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
+}
+
+static int
+query_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, u8 info_class, u8 info_type,
+ u32 additional_info, size_t output_len, size_t min_len, void **data,
+ u32 *dlen)
+{
+ struct smb_rqst rqst;
+ struct smb2_query_info_rsp *rsp = NULL;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ int rc = 0;
+ int resp_buftype = CIFS_NO_BUFFER;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server;
+ int flags = 0;
+ bool allocated = false;
+
+ cifs_dbg(FYI, "Query Info\n");
+
+ if (!ses)
+ return -EIO;
+ server = cifs_pick_channel(ses);
+ if (!server)
+ return -EIO;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ memset(&iov, 0, sizeof(iov));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = SMB2_query_info_init(tcon, server,
+ &rqst, persistent_fid, volatile_fid,
+ info_class, info_type, additional_info,
+ output_len, 0, NULL);
+ if (rc)
+ goto qinf_exit;
+
+ trace_smb3_query_info_enter(xid, persistent_fid, tcon->tid,
+ ses->Suid, info_class, (__u32)info_type);
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
+
+ if (rc) {
+ cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
+ trace_smb3_query_info_err(xid, persistent_fid, tcon->tid,
+ ses->Suid, info_class, (__u32)info_type, rc);
+ goto qinf_exit;
+ }
+
+ trace_smb3_query_info_done(xid, persistent_fid, tcon->tid,
+ ses->Suid, info_class, (__u32)info_type);
+
+ if (dlen) {
+ *dlen = le32_to_cpu(rsp->OutputBufferLength);
+ if (!*data) {
+ *data = kmalloc(*dlen, GFP_KERNEL);
+ if (!*data) {
+ cifs_tcon_dbg(VFS,
+ "Error %d allocating memory for acl\n",
+ rc);
+ *dlen = 0;
+ rc = -ENOMEM;
+ goto qinf_exit;
+ }
+ allocated = true;
+ }
+ }
+
+ rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
+ le32_to_cpu(rsp->OutputBufferLength),
+ &rsp_iov, dlen ? *dlen : min_len, *data);
+ if (rc && allocated) {
+ kfree(*data);
+ *data = NULL;
+ *dlen = 0;
+ }
+
+qinf_exit:
+ SMB2_query_info_free(&rqst);
+ free_rsp_buf(resp_buftype, rsp);
+ return rc;
+}
+
+int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, struct smb2_file_all_info *data)
+{
+ return query_info(xid, tcon, persistent_fid, volatile_fid,
+ FILE_ALL_INFORMATION, SMB2_O_INFO_FILE, 0,
+ sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
+ sizeof(struct smb2_file_all_info), (void **)&data,
+ NULL);
+}
+
+#if 0
+/* currently unused, as now we are doing compounding instead (see smb311_posix_query_path_info) */
+int
+SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen)
+{
+ size_t output_len = sizeof(struct smb311_posix_qinfo *) +
+ (sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2);
+ *plen = 0;
+
+ return query_info(xid, tcon, persistent_fid, volatile_fid,
+ SMB_FIND_FILE_POSIX_INFO, SMB2_O_INFO_FILE, 0,
+ output_len, sizeof(struct smb311_posix_qinfo), (void **)&data, plen);
+ /* Note caller must free "data" (passed in above). It may be allocated in query_info call */
+}
+#endif
+
+int
+SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ void **data, u32 *plen, u32 extra_info)
+{
+ __u32 additional_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
+ extra_info;
+ *plen = 0;
+
+ return query_info(xid, tcon, persistent_fid, volatile_fid,
+ 0, SMB2_O_INFO_SECURITY, additional_info,
+ SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen);
+}
+
+int
+SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, __le64 *uniqueid)
+{
+ return query_info(xid, tcon, persistent_fid, volatile_fid,
+ FILE_INTERNAL_INFORMATION, SMB2_O_INFO_FILE, 0,
+ sizeof(struct smb2_file_internal_info),
+ sizeof(struct smb2_file_internal_info),
+ (void **)&uniqueid, NULL);
+}
+
+/*
+ * CHANGE_NOTIFY Request is sent to get notifications on changes to a directory
+ * See MS-SMB2 2.2.35 and 2.2.36
+ */
+
+static int
+SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst,
+ struct cifs_tcon *tcon, struct TCP_Server_Info *server,
+ u64 persistent_fid, u64 volatile_fid,
+ u32 completion_filter, bool watch_tree)
+{
+ struct smb2_change_notify_req *req;
+ struct kvec *iov = rqst->rq_iov;
+ unsigned int total_len;
+ int rc;
+
+ rc = smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ req->PersistentFileId = persistent_fid;
+ req->VolatileFileId = volatile_fid;
+ /* See note 354 of MS-SMB2, 64K max */
+ req->OutputBufferLength =
+ cpu_to_le32(SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE);
+ req->CompletionFilter = cpu_to_le32(completion_filter);
+ if (watch_tree)
+ req->Flags = cpu_to_le16(SMB2_WATCH_TREE);
+ else
+ req->Flags = 0;
+
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+
+ return 0;
+}
+
+int
+SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, bool watch_tree,
+ u32 completion_filter, u32 max_out_data_len, char **out_data,
+ u32 *plen /* returned data len */)
+{
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ struct smb_rqst rqst;
+ struct smb2_change_notify_rsp *smb_rsp;
+ struct kvec iov[1];
+ struct kvec rsp_iov = {NULL, 0};
+ int resp_buftype = CIFS_NO_BUFFER;
+ int flags = 0;
+ int rc = 0;
+
+ cifs_dbg(FYI, "change notify\n");
+ if (!ses || !server)
+ return -EIO;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ memset(&iov, 0, sizeof(iov));
+ if (plen)
+ *plen = 0;
+
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = SMB2_notify_init(xid, &rqst, tcon, server,
+ persistent_fid, volatile_fid,
+ completion_filter, watch_tree);
+ if (rc)
+ goto cnotify_exit;
+
+ trace_smb3_notify_enter(xid, persistent_fid, tcon->tid, ses->Suid,
+ (u8)watch_tree, completion_filter);
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+
+ if (rc != 0) {
+ cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE);
+ trace_smb3_notify_err(xid, persistent_fid, tcon->tid, ses->Suid,
+ (u8)watch_tree, completion_filter, rc);
+ } else {
+ trace_smb3_notify_done(xid, persistent_fid, tcon->tid,
+ ses->Suid, (u8)watch_tree, completion_filter);
+ /* validate that notify information is plausible */
+ if ((rsp_iov.iov_base == NULL) ||
+ (rsp_iov.iov_len < sizeof(struct smb2_change_notify_rsp)))
+ goto cnotify_exit;
+
+ smb_rsp = (struct smb2_change_notify_rsp *)rsp_iov.iov_base;
+
+ smb2_validate_iov(le16_to_cpu(smb_rsp->OutputBufferOffset),
+ le32_to_cpu(smb_rsp->OutputBufferLength), &rsp_iov,
+ sizeof(struct file_notify_information));
+
+ *out_data = kmemdup((char *)smb_rsp + le16_to_cpu(smb_rsp->OutputBufferOffset),
+ le32_to_cpu(smb_rsp->OutputBufferLength), GFP_KERNEL);
+ if (*out_data == NULL) {
+ rc = -ENOMEM;
+ goto cnotify_exit;
+ } else if (plen)
+ *plen = le32_to_cpu(smb_rsp->OutputBufferLength);
+ }
+
+ cnotify_exit:
+ if (rqst.rq_iov)
+ cifs_small_buf_release(rqst.rq_iov[0].iov_base); /* request */
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+ return rc;
+}
+
+
+
+/*
+ * This is a no-op for now. We're not really interested in the reply, but
+ * rather in the fact that the server sent one and that server->lstrp
+ * gets updated.
+ *
+ * FIXME: maybe we should consider checking that the reply matches request?
+ */
+static void
+smb2_echo_callback(struct mid_q_entry *mid)
+{
+ struct TCP_Server_Info *server = mid->callback_data;
+ struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
+ struct cifs_credits credits = { .value = 0, .instance = 0 };
+
+ if (mid->mid_state == MID_RESPONSE_RECEIVED
+ || mid->mid_state == MID_RESPONSE_MALFORMED) {
+ credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
+ credits.instance = server->reconnect_instance;
+ }
+
+ release_mid(mid);
+ add_credits(server, &credits, CIFS_ECHO_OP);
+}
+
+void smb2_reconnect_server(struct work_struct *work)
+{
+ struct TCP_Server_Info *server = container_of(work,
+ struct TCP_Server_Info, reconnect.work);
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses, *ses2;
+ struct cifs_tcon *tcon, *tcon2;
+ struct list_head tmp_list, tmp_ses_list;
+ bool tcon_exist = false, ses_exist = false;
+ bool tcon_selected = false;
+ int rc;
+ bool resched = false;
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+ /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
+ mutex_lock(&pserver->reconnect_mutex);
+
+ INIT_LIST_HEAD(&tmp_list);
+ INIT_LIST_HEAD(&tmp_ses_list);
+ cifs_dbg(FYI, "Reconnecting tcons and channels\n");
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+
+ tcon_selected = false;
+
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ if (tcon->need_reconnect || tcon->need_reopen_files) {
+ tcon->tc_count++;
+ list_add_tail(&tcon->rlist, &tmp_list);
+ tcon_selected = tcon_exist = true;
+ }
+ }
+ /*
+ * IPC has the same lifetime as its session and uses its
+ * refcount.
+ */
+ if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) {
+ list_add_tail(&ses->tcon_ipc->rlist, &tmp_list);
+ tcon_selected = tcon_exist = true;
+ ses->ses_count++;
+ }
+ /*
+ * handle the case where channel needs to reconnect
+ * binding session, but tcon is healthy (some other channel
+ * is active)
+ */
+ spin_lock(&ses->chan_lock);
+ if (!tcon_selected && cifs_chan_needs_reconnect(ses, server)) {
+ list_add_tail(&ses->rlist, &tmp_ses_list);
+ ses_exist = true;
+ ses->ses_count++;
+ }
+ spin_unlock(&ses->chan_lock);
+ }
+ /*
+ * Get the reference to server struct to be sure that the last call of
+ * cifs_put_tcon() in the loop below won't release the server pointer.
+ */
+ if (tcon_exist || ses_exist)
+ server->srv_count++;
+
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
+ rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server);
+ if (!rc)
+ cifs_reopen_persistent_handles(tcon);
+ else
+ resched = true;
+ list_del_init(&tcon->rlist);
+ if (tcon->ipc)
+ cifs_put_smb_ses(tcon->ses);
+ else
+ cifs_put_tcon(tcon);
+ }
+
+ if (!ses_exist)
+ goto done;
+
+ /* allocate a dummy tcon struct used for reconnect */
+ tcon = tconInfoAlloc();
+ if (!tcon) {
+ resched = true;
+ list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
+ list_del_init(&ses->rlist);
+ cifs_put_smb_ses(ses);
+ }
+ goto done;
+ }
+
+ tcon->status = TID_GOOD;
+ tcon->retry = false;
+ tcon->need_reconnect = false;
+
+ /* now reconnect sessions for necessary channels */
+ list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
+ tcon->ses = ses;
+ rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server);
+ if (rc)
+ resched = true;
+ list_del_init(&ses->rlist);
+ cifs_put_smb_ses(ses);
+ }
+ tconInfoFree(tcon);
+
+done:
+ cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");
+ if (resched)
+ queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
+ mutex_unlock(&pserver->reconnect_mutex);
+
+ /* now we can safely release srv struct */
+ if (tcon_exist || ses_exist)
+ cifs_put_tcp_session(server, 1);
+}
+
+int
+SMB2_echo(struct TCP_Server_Info *server)
+{
+ struct smb2_echo_req *req;
+ int rc = 0;
+ struct kvec iov[1];
+ struct smb_rqst rqst = { .rq_iov = iov,
+ .rq_nvec = 1 };
+ unsigned int total_len;
+
+ cifs_dbg(FYI, "In echo request for conn_id %lld\n", server->conn_id);
+
+ spin_lock(&server->srv_lock);
+ if (server->ops->need_neg &&
+ server->ops->need_neg(server)) {
+ spin_unlock(&server->srv_lock);
+ /* No need to send echo on newly established connections */
+ mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
+ return rc;
+ }
+ spin_unlock(&server->srv_lock);
+
+ rc = smb2_plain_req_init(SMB2_ECHO, NULL, server,
+ (void **)&req, &total_len);
+ if (rc)
+ return rc;
+
+ req->hdr.CreditRequest = cpu_to_le16(1);
+
+ iov[0].iov_len = total_len;
+ iov[0].iov_base = (char *)req;
+
+ rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL,
+ server, CIFS_ECHO_OP, NULL);
+ if (rc)
+ cifs_dbg(FYI, "Echo request failed: %d\n", rc);
+
+ cifs_small_buf_release(req);
+ return rc;
+}
+
+void
+SMB2_flush_free(struct smb_rqst *rqst)
+{
+ if (rqst && rqst->rq_iov)
+ cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
+}
+
+int
+SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst,
+ struct cifs_tcon *tcon, struct TCP_Server_Info *server,
+ u64 persistent_fid, u64 volatile_fid)
+{
+ struct smb2_flush_req *req;
+ struct kvec *iov = rqst->rq_iov;
+ unsigned int total_len;
+ int rc;
+
+ rc = smb2_plain_req_init(SMB2_FLUSH, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ req->PersistentFileId = persistent_fid;
+ req->VolatileFileId = volatile_fid;
+
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+
+ return 0;
+}
+
+int
+SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
+ u64 volatile_fid)
+{
+ struct cifs_ses *ses = tcon->ses;
+ struct smb_rqst rqst;
+ struct kvec iov[1];
+ struct kvec rsp_iov = {NULL, 0};
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ int resp_buftype = CIFS_NO_BUFFER;
+ int flags = 0;
+ int rc = 0;
+
+ cifs_dbg(FYI, "flush\n");
+ if (!ses || !(ses->server))
+ return -EIO;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ memset(&iov, 0, sizeof(iov));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = SMB2_flush_init(xid, &rqst, tcon, server,
+ persistent_fid, volatile_fid);
+ if (rc)
+ goto flush_exit;
+
+ trace_smb3_flush_enter(xid, persistent_fid, tcon->tid, ses->Suid);
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+
+ if (rc != 0) {
+ cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE);
+ trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid,
+ rc);
+ } else
+ trace_smb3_flush_done(xid, persistent_fid, tcon->tid,
+ ses->Suid);
+
+ flush_exit:
+ SMB2_flush_free(&rqst);
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+ return rc;
+}
+
+#ifdef CONFIG_CIFS_SMB_DIRECT
+static inline bool smb3_use_rdma_offload(struct cifs_io_parms *io_parms)
+{
+ struct TCP_Server_Info *server = io_parms->server;
+ struct cifs_tcon *tcon = io_parms->tcon;
+
+ /* we can only offload if we're connected */
+ if (!server || !tcon)
+ return false;
+
+ /* we can only offload on an rdma connection */
+ if (!server->rdma || !server->smbd_conn)
+ return false;
+
+ /* we don't support signed offload yet */
+ if (server->sign)
+ return false;
+
+ /* we don't support encrypted offload yet */
+ if (smb3_encryption_required(tcon))
+ return false;
+
+ /* offload also has its overhead, so only do it if desired */
+ if (io_parms->length < server->smbd_conn->rdma_readwrite_threshold)
+ return false;
+
+ return true;
+}
+#endif /* CONFIG_CIFS_SMB_DIRECT */
+
+/*
+ * To form a chain of read requests, any read requests after the first should
+ * have the end_of_chain boolean set to true.
+ */
+static int
+smb2_new_read_req(void **buf, unsigned int *total_len,
+ struct cifs_io_parms *io_parms, struct cifs_readdata *rdata,
+ unsigned int remaining_bytes, int request_type)
+{
+ int rc = -EACCES;
+ struct smb2_read_req *req = NULL;
+ struct smb2_hdr *shdr;
+ struct TCP_Server_Info *server = io_parms->server;
+
+ rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, server,
+ (void **) &req, total_len);
+ if (rc)
+ return rc;
+
+ if (server == NULL)
+ return -ECONNABORTED;
+
+ shdr = &req->hdr;
+ shdr->Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid);
+
+ req->PersistentFileId = io_parms->persistent_fid;
+ req->VolatileFileId = io_parms->volatile_fid;
+ req->ReadChannelInfoOffset = 0; /* reserved */
+ req->ReadChannelInfoLength = 0; /* reserved */
+ req->Channel = 0; /* reserved */
+ req->MinimumCount = 0;
+ req->Length = cpu_to_le32(io_parms->length);
+ req->Offset = cpu_to_le64(io_parms->offset);
+
+ trace_smb3_read_enter(0 /* xid */,
+ io_parms->persistent_fid,
+ io_parms->tcon->tid, io_parms->tcon->ses->Suid,
+ io_parms->offset, io_parms->length);
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ /*
+ * If we want to do a RDMA write, fill in and append
+ * smbd_buffer_descriptor_v1 to the end of read request
+ */
+ if (smb3_use_rdma_offload(io_parms)) {
+ struct smbd_buffer_descriptor_v1 *v1;
+ bool need_invalidate = server->dialect == SMB30_PROT_ID;
+
+ rdata->mr = smbd_register_mr(
+ server->smbd_conn, rdata->pages,
+ rdata->nr_pages, rdata->page_offset,
+ rdata->tailsz, true, need_invalidate);
+ if (!rdata->mr)
+ return -EAGAIN;
+
+ req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
+ if (need_invalidate)
+ req->Channel = SMB2_CHANNEL_RDMA_V1;
+ req->ReadChannelInfoOffset =
+ cpu_to_le16(offsetof(struct smb2_read_req, Buffer));
+ req->ReadChannelInfoLength =
+ cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
+ v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
+ v1->offset = cpu_to_le64(rdata->mr->mr->iova);
+ v1->token = cpu_to_le32(rdata->mr->mr->rkey);
+ v1->length = cpu_to_le32(rdata->mr->mr->length);
+
+ *total_len += sizeof(*v1) - 1;
+ }
+#endif
+ if (request_type & CHAINED_REQUEST) {
+ if (!(request_type & END_OF_CHAIN)) {
+ /* next 8-byte aligned request */
+ *total_len = ALIGN(*total_len, 8);
+ shdr->NextCommand = cpu_to_le32(*total_len);
+ } else /* END_OF_CHAIN */
+ shdr->NextCommand = 0;
+ if (request_type & RELATED_REQUEST) {
+ shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
+ /*
+ * Related requests use info from previous read request
+ * in chain.
+ */
+ shdr->SessionId = cpu_to_le64(0xFFFFFFFFFFFFFFFF);
+ shdr->Id.SyncId.TreeId = cpu_to_le32(0xFFFFFFFF);
+ req->PersistentFileId = (u64)-1;
+ req->VolatileFileId = (u64)-1;
+ }
+ }
+ if (remaining_bytes > io_parms->length)
+ req->RemainingBytes = cpu_to_le32(remaining_bytes);
+ else
+ req->RemainingBytes = 0;
+
+ *buf = req;
+ return rc;
+}
+
+static void
+smb2_readv_callback(struct mid_q_entry *mid)
+{
+ struct cifs_readdata *rdata = mid->callback_data;
+ struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+ struct TCP_Server_Info *server = rdata->server;
+ struct smb2_hdr *shdr =
+ (struct smb2_hdr *)rdata->iov[0].iov_base;
+ struct cifs_credits credits = { .value = 0, .instance = 0 };
+ struct smb_rqst rqst = { .rq_iov = &rdata->iov[1],
+ .rq_nvec = 1, };
+
+ if (rdata->got_bytes) {
+ rqst.rq_pages = rdata->pages;
+ rqst.rq_offset = rdata->page_offset;
+ rqst.rq_npages = rdata->nr_pages;
+ rqst.rq_pagesz = rdata->pagesz;
+ rqst.rq_tailsz = rdata->tailsz;
+ }
+
+ WARN_ONCE(rdata->server != mid->server,
+ "rdata server %p != mid server %p",
+ rdata->server, mid->server);
+
+ cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
+ __func__, mid->mid, mid->mid_state, rdata->result,
+ rdata->bytes);
+
+ switch (mid->mid_state) {
+ case MID_RESPONSE_RECEIVED:
+ credits.value = le16_to_cpu(shdr->CreditRequest);
+ credits.instance = server->reconnect_instance;
+ /* result already set, check signature */
+ if (server->sign && !mid->decrypted) {
+ int rc;
+
+ rc = smb2_verify_signature(&rqst, server);
+ if (rc)
+ cifs_tcon_dbg(VFS, "SMB signature verification returned error = %d\n",
+ rc);
+ }
+ /* FIXME: should this be counted toward the initiating task? */
+ task_io_account_read(rdata->got_bytes);
+ cifs_stats_bytes_read(tcon, rdata->got_bytes);
+ break;
+ case MID_REQUEST_SUBMITTED:
+ case MID_RETRY_NEEDED:
+ rdata->result = -EAGAIN;
+ if (server->sign && rdata->got_bytes)
+ /* reset bytes number since we can not check a sign */
+ rdata->got_bytes = 0;
+ /* FIXME: should this be counted toward the initiating task? */
+ task_io_account_read(rdata->got_bytes);
+ cifs_stats_bytes_read(tcon, rdata->got_bytes);
+ break;
+ case MID_RESPONSE_MALFORMED:
+ credits.value = le16_to_cpu(shdr->CreditRequest);
+ credits.instance = server->reconnect_instance;
+ fallthrough;
+ default:
+ rdata->result = -EIO;
+ }
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ /*
+ * If this rdata has a memmory registered, the MR can be freed
+ * MR needs to be freed as soon as I/O finishes to prevent deadlock
+ * because they have limited number and are used for future I/Os
+ */
+ if (rdata->mr) {
+ smbd_deregister_mr(rdata->mr);
+ rdata->mr = NULL;
+ }
+#endif
+ if (rdata->result && rdata->result != -ENODATA) {
+ cifs_stats_fail_inc(tcon, SMB2_READ_HE);
+ trace_smb3_read_err(0 /* xid */,
+ rdata->cfile->fid.persistent_fid,
+ tcon->tid, tcon->ses->Suid, rdata->offset,
+ rdata->bytes, rdata->result);
+ } else
+ trace_smb3_read_done(0 /* xid */,
+ rdata->cfile->fid.persistent_fid,
+ tcon->tid, tcon->ses->Suid,
+ rdata->offset, rdata->got_bytes);
+
+ queue_work(cifsiod_wq, &rdata->work);
+ release_mid(mid);
+ add_credits(server, &credits, 0);
+}
+
+/* smb2_async_readv - send an async read, and set up mid to handle result */
+int
+smb2_async_readv(struct cifs_readdata *rdata)
+{
+ int rc, flags = 0;
+ char *buf;
+ struct smb2_hdr *shdr;
+ struct cifs_io_parms io_parms;
+ struct smb_rqst rqst = { .rq_iov = rdata->iov,
+ .rq_nvec = 1 };
+ struct TCP_Server_Info *server;
+ struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+ unsigned int total_len;
+
+ cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
+ __func__, rdata->offset, rdata->bytes);
+
+ if (!rdata->server)
+ rdata->server = cifs_pick_channel(tcon->ses);
+
+ io_parms.tcon = tlink_tcon(rdata->cfile->tlink);
+ io_parms.server = server = rdata->server;
+ io_parms.offset = rdata->offset;
+ io_parms.length = rdata->bytes;
+ io_parms.persistent_fid = rdata->cfile->fid.persistent_fid;
+ io_parms.volatile_fid = rdata->cfile->fid.volatile_fid;
+ io_parms.pid = rdata->pid;
+
+ rc = smb2_new_read_req(
+ (void **) &buf, &total_len, &io_parms, rdata, 0, 0);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(io_parms.tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ rdata->iov[0].iov_base = buf;
+ rdata->iov[0].iov_len = total_len;
+
+ shdr = (struct smb2_hdr *)buf;
+
+ if (rdata->credits.value > 0) {
+ shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
+ SMB2_MAX_BUFFER_SIZE));
+ shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8);
+
+ rc = adjust_credits(server, &rdata->credits, rdata->bytes);
+ if (rc)
+ goto async_readv_out;
+
+ flags |= CIFS_HAS_CREDITS;
+ }
+
+ kref_get(&rdata->refcount);
+ rc = cifs_call_async(server, &rqst,
+ cifs_readv_receive, smb2_readv_callback,
+ smb3_handle_read_data, rdata, flags,
+ &rdata->credits);
+ if (rc) {
+ kref_put(&rdata->refcount, cifs_readdata_release);
+ cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
+ trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
+ io_parms.tcon->tid,
+ io_parms.tcon->ses->Suid,
+ io_parms.offset, io_parms.length, rc);
+ }
+
+async_readv_out:
+ cifs_small_buf_release(buf);
+ return rc;
+}
+
+int
+SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, char **buf, int *buf_type)
+{
+ struct smb_rqst rqst;
+ int resp_buftype, rc;
+ struct smb2_read_req *req = NULL;
+ struct smb2_read_rsp *rsp = NULL;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ unsigned int total_len;
+ int flags = CIFS_LOG_ERROR;
+ struct cifs_ses *ses = io_parms->tcon->ses;
+
+ if (!io_parms->server)
+ io_parms->server = cifs_pick_channel(io_parms->tcon->ses);
+
+ *nbytes = 0;
+ rc = smb2_new_read_req((void **)&req, &total_len, io_parms, NULL, 0, 0);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(io_parms->tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, io_parms->server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ rsp = (struct smb2_read_rsp *)rsp_iov.iov_base;
+
+ if (rc) {
+ if (rc != -ENODATA) {
+ cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
+ cifs_dbg(VFS, "Send error in read = %d\n", rc);
+ trace_smb3_read_err(xid,
+ req->PersistentFileId,
+ io_parms->tcon->tid, ses->Suid,
+ io_parms->offset, io_parms->length,
+ rc);
+ } else
+ trace_smb3_read_done(xid, req->PersistentFileId, io_parms->tcon->tid,
+ ses->Suid, io_parms->offset, 0);
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+ cifs_small_buf_release(req);
+ return rc == -ENODATA ? 0 : rc;
+ } else
+ trace_smb3_read_done(xid,
+ req->PersistentFileId,
+ io_parms->tcon->tid, ses->Suid,
+ io_parms->offset, io_parms->length);
+
+ cifs_small_buf_release(req);
+
+ *nbytes = le32_to_cpu(rsp->DataLength);
+ if ((*nbytes > CIFS_MAX_MSGSIZE) ||
+ (*nbytes > io_parms->length)) {
+ cifs_dbg(FYI, "bad length %d for count %d\n",
+ *nbytes, io_parms->length);
+ rc = -EIO;
+ *nbytes = 0;
+ }
+
+ if (*buf) {
+ memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+ } else if (resp_buftype != CIFS_NO_BUFFER) {
+ *buf = rsp_iov.iov_base;
+ if (resp_buftype == CIFS_SMALL_BUFFER)
+ *buf_type = CIFS_SMALL_BUFFER;
+ else if (resp_buftype == CIFS_LARGE_BUFFER)
+ *buf_type = CIFS_LARGE_BUFFER;
+ }
+ return rc;
+}
+
+/*
+ * Check the mid_state and signature on received buffer (if any), and queue the
+ * workqueue completion task.
+ */
+static void
+smb2_writev_callback(struct mid_q_entry *mid)
+{
+ struct cifs_writedata *wdata = mid->callback_data;
+ struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
+ struct TCP_Server_Info *server = wdata->server;
+ unsigned int written;
+ struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
+ struct cifs_credits credits = { .value = 0, .instance = 0 };
+
+ WARN_ONCE(wdata->server != mid->server,
+ "wdata server %p != mid server %p",
+ wdata->server, mid->server);
+
+ switch (mid->mid_state) {
+ case MID_RESPONSE_RECEIVED:
+ credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
+ credits.instance = server->reconnect_instance;
+ wdata->result = smb2_check_receive(mid, server, 0);
+ if (wdata->result != 0)
+ break;
+
+ written = le32_to_cpu(rsp->DataLength);
+ /*
+ * Mask off high 16 bits when bytes written as returned
+ * by the server is greater than bytes requested by the
+ * client. OS/2 servers are known to set incorrect
+ * CountHigh values.
+ */
+ if (written > wdata->bytes)
+ written &= 0xFFFF;
+
+ if (written < wdata->bytes)
+ wdata->result = -ENOSPC;
+ else
+ wdata->bytes = written;
+ break;
+ case MID_REQUEST_SUBMITTED:
+ case MID_RETRY_NEEDED:
+ wdata->result = -EAGAIN;
+ break;
+ case MID_RESPONSE_MALFORMED:
+ credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
+ credits.instance = server->reconnect_instance;
+ fallthrough;
+ default:
+ wdata->result = -EIO;
+ break;
+ }
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ /*
+ * If this wdata has a memory registered, the MR can be freed
+ * The number of MRs available is limited, it's important to recover
+ * used MR as soon as I/O is finished. Hold MR longer in the later
+ * I/O process can possibly result in I/O deadlock due to lack of MR
+ * to send request on I/O retry
+ */
+ if (wdata->mr) {
+ smbd_deregister_mr(wdata->mr);
+ wdata->mr = NULL;
+ }
+#endif
+ if (wdata->result) {
+ cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
+ trace_smb3_write_err(0 /* no xid */,
+ wdata->cfile->fid.persistent_fid,
+ tcon->tid, tcon->ses->Suid, wdata->offset,
+ wdata->bytes, wdata->result);
+ if (wdata->result == -ENOSPC)
+ pr_warn_once("Out of space writing to %s\n",
+ tcon->tree_name);
+ } else
+ trace_smb3_write_done(0 /* no xid */,
+ wdata->cfile->fid.persistent_fid,
+ tcon->tid, tcon->ses->Suid,
+ wdata->offset, wdata->bytes);
+
+ queue_work(cifsiod_wq, &wdata->work);
+ release_mid(mid);
+ add_credits(server, &credits, 0);
+}
+
+/* smb2_async_writev - send an async write, and set up mid to handle result */
+int
+smb2_async_writev(struct cifs_writedata *wdata,
+ void (*release)(struct kref *kref))
+{
+ int rc = -EACCES, flags = 0;
+ struct smb2_write_req *req = NULL;
+ struct smb2_hdr *shdr;
+ struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
+ struct TCP_Server_Info *server = wdata->server;
+ struct kvec iov[1];
+ struct smb_rqst rqst = { };
+ unsigned int total_len;
+ struct cifs_io_parms _io_parms;
+ struct cifs_io_parms *io_parms = NULL;
+
+ if (!wdata->server)
+ server = wdata->server = cifs_pick_channel(tcon->ses);
+
+ /*
+ * in future we may get cifs_io_parms passed in from the caller,
+ * but for now we construct it here...
+ */
+ _io_parms = (struct cifs_io_parms) {
+ .tcon = tcon,
+ .server = server,
+ .offset = wdata->offset,
+ .length = wdata->bytes,
+ .persistent_fid = wdata->cfile->fid.persistent_fid,
+ .volatile_fid = wdata->cfile->fid.volatile_fid,
+ .pid = wdata->pid,
+ };
+ io_parms = &_io_parms;
+
+ rc = smb2_plain_req_init(SMB2_WRITE, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ shdr = (struct smb2_hdr *)req;
+ shdr->Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid);
+
+ req->PersistentFileId = io_parms->persistent_fid;
+ req->VolatileFileId = io_parms->volatile_fid;
+ req->WriteChannelInfoOffset = 0;
+ req->WriteChannelInfoLength = 0;
+ req->Channel = 0;
+ req->Offset = cpu_to_le64(io_parms->offset);
+ req->DataOffset = cpu_to_le16(
+ offsetof(struct smb2_write_req, Buffer));
+ req->RemainingBytes = 0;
+
+ trace_smb3_write_enter(0 /* xid */,
+ io_parms->persistent_fid,
+ io_parms->tcon->tid,
+ io_parms->tcon->ses->Suid,
+ io_parms->offset,
+ io_parms->length);
+
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ /*
+ * If we want to do a server RDMA read, fill in and append
+ * smbd_buffer_descriptor_v1 to the end of write request
+ */
+ if (smb3_use_rdma_offload(io_parms)) {
+ struct smbd_buffer_descriptor_v1 *v1;
+ bool need_invalidate = server->dialect == SMB30_PROT_ID;
+
+ wdata->mr = smbd_register_mr(
+ server->smbd_conn, wdata->pages,
+ wdata->nr_pages, wdata->page_offset,
+ wdata->tailsz, false, need_invalidate);
+ if (!wdata->mr) {
+ rc = -EAGAIN;
+ goto async_writev_out;
+ }
+ req->Length = 0;
+ req->DataOffset = 0;
+ if (wdata->nr_pages > 1)
+ req->RemainingBytes =
+ cpu_to_le32(
+ (wdata->nr_pages - 1) * wdata->pagesz -
+ wdata->page_offset + wdata->tailsz
+ );
+ else
+ req->RemainingBytes = cpu_to_le32(wdata->tailsz);
+ req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
+ if (need_invalidate)
+ req->Channel = SMB2_CHANNEL_RDMA_V1;
+ req->WriteChannelInfoOffset =
+ cpu_to_le16(offsetof(struct smb2_write_req, Buffer));
+ req->WriteChannelInfoLength =
+ cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
+ v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
+ v1->offset = cpu_to_le64(wdata->mr->mr->iova);
+ v1->token = cpu_to_le32(wdata->mr->mr->rkey);
+ v1->length = cpu_to_le32(wdata->mr->mr->length);
+ }
+#endif
+ iov[0].iov_len = total_len - 1;
+ iov[0].iov_base = (char *)req;
+
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+ rqst.rq_pages = wdata->pages;
+ rqst.rq_offset = wdata->page_offset;
+ rqst.rq_npages = wdata->nr_pages;
+ rqst.rq_pagesz = wdata->pagesz;
+ rqst.rq_tailsz = wdata->tailsz;
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ if (wdata->mr) {
+ iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1);
+ rqst.rq_npages = 0;
+ }
+#endif
+ cifs_dbg(FYI, "async write at %llu %u bytes\n",
+ io_parms->offset, io_parms->length);
+
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ /* For RDMA read, I/O size is in RemainingBytes not in Length */
+ if (!wdata->mr)
+ req->Length = cpu_to_le32(io_parms->length);
+#else
+ req->Length = cpu_to_le32(io_parms->length);
+#endif
+
+ if (wdata->credits.value > 0) {
+ shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
+ SMB2_MAX_BUFFER_SIZE));
+ shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8);
+
+ rc = adjust_credits(server, &wdata->credits, io_parms->length);
+ if (rc)
+ goto async_writev_out;
+
+ flags |= CIFS_HAS_CREDITS;
+ }
+
+ kref_get(&wdata->refcount);
+ rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
+ wdata, flags, &wdata->credits);
+
+ if (rc) {
+ trace_smb3_write_err(0 /* no xid */,
+ io_parms->persistent_fid,
+ io_parms->tcon->tid,
+ io_parms->tcon->ses->Suid,
+ io_parms->offset,
+ io_parms->length,
+ rc);
+ kref_put(&wdata->refcount, release);
+ cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
+ }
+
+async_writev_out:
+ cifs_small_buf_release(req);
+ return rc;
+}
+
+/*
+ * SMB2_write function gets iov pointer to kvec array with n_vec as a length.
+ * The length field from io_parms must be at least 1 and indicates a number of
+ * elements with data to write that begins with position 1 in iov array. All
+ * data length is specified by count.
+ */
+int
+SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, struct kvec *iov, int n_vec)
+{
+ struct smb_rqst rqst;
+ int rc = 0;
+ struct smb2_write_req *req = NULL;
+ struct smb2_write_rsp *rsp = NULL;
+ int resp_buftype;
+ struct kvec rsp_iov;
+ int flags = 0;
+ unsigned int total_len;
+ struct TCP_Server_Info *server;
+
+ *nbytes = 0;
+
+ if (n_vec < 1)
+ return rc;
+
+ if (!io_parms->server)
+ io_parms->server = cifs_pick_channel(io_parms->tcon->ses);
+ server = io_parms->server;
+ if (server == NULL)
+ return -ECONNABORTED;
+
+ rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(io_parms->tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ req->hdr.Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid);
+
+ req->PersistentFileId = io_parms->persistent_fid;
+ req->VolatileFileId = io_parms->volatile_fid;
+ req->WriteChannelInfoOffset = 0;
+ req->WriteChannelInfoLength = 0;
+ req->Channel = 0;
+ req->Length = cpu_to_le32(io_parms->length);
+ req->Offset = cpu_to_le64(io_parms->offset);
+ req->DataOffset = cpu_to_le16(
+ offsetof(struct smb2_write_req, Buffer));
+ req->RemainingBytes = 0;
+
+ trace_smb3_write_enter(xid, io_parms->persistent_fid,
+ io_parms->tcon->tid, io_parms->tcon->ses->Suid,
+ io_parms->offset, io_parms->length);
+
+ iov[0].iov_base = (char *)req;
+ /* 1 for Buffer */
+ iov[0].iov_len = total_len - 1;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = n_vec + 1;
+
+ rc = cifs_send_recv(xid, io_parms->tcon->ses, server,
+ &rqst,
+ &resp_buftype, flags, &rsp_iov);
+ rsp = (struct smb2_write_rsp *)rsp_iov.iov_base;
+
+ if (rc) {
+ trace_smb3_write_err(xid,
+ req->PersistentFileId,
+ io_parms->tcon->tid,
+ io_parms->tcon->ses->Suid,
+ io_parms->offset, io_parms->length, rc);
+ cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE);
+ cifs_dbg(VFS, "Send error in write = %d\n", rc);
+ } else {
+ *nbytes = le32_to_cpu(rsp->DataLength);
+ trace_smb3_write_done(xid,
+ req->PersistentFileId,
+ io_parms->tcon->tid,
+ io_parms->tcon->ses->Suid,
+ io_parms->offset, *nbytes);
+ }
+
+ cifs_small_buf_release(req);
+ free_rsp_buf(resp_buftype, rsp);
+ return rc;
+}
+
+int posix_info_sid_size(const void *beg, const void *end)
+{
+ size_t subauth;
+ int total;
+
+ if (beg + 1 > end)
+ return -1;
+
+ subauth = *(u8 *)(beg+1);
+ if (subauth < 1 || subauth > 15)
+ return -1;
+
+ total = 1 + 1 + 6 + 4*subauth;
+ if (beg + total > end)
+ return -1;
+
+ return total;
+}
+
+int posix_info_parse(const void *beg, const void *end,
+ struct smb2_posix_info_parsed *out)
+
+{
+ int total_len = 0;
+ int owner_len, group_len;
+ int name_len;
+ const void *owner_sid;
+ const void *group_sid;
+ const void *name;
+
+ /* if no end bound given, assume payload to be correct */
+ if (!end) {
+ const struct smb2_posix_info *p = beg;
+
+ end = beg + le32_to_cpu(p->NextEntryOffset);
+ /* last element will have a 0 offset, pick a sensible bound */
+ if (end == beg)
+ end += 0xFFFF;
+ }
+
+ /* check base buf */
+ if (beg + sizeof(struct smb2_posix_info) > end)
+ return -1;
+ total_len = sizeof(struct smb2_posix_info);
+
+ /* check owner sid */
+ owner_sid = beg + total_len;
+ owner_len = posix_info_sid_size(owner_sid, end);
+ if (owner_len < 0)
+ return -1;
+ total_len += owner_len;
+
+ /* check group sid */
+ group_sid = beg + total_len;
+ group_len = posix_info_sid_size(group_sid, end);
+ if (group_len < 0)
+ return -1;
+ total_len += group_len;
+
+ /* check name len */
+ if (beg + total_len + 4 > end)
+ return -1;
+ name_len = le32_to_cpu(*(__le32 *)(beg + total_len));
+ if (name_len < 1 || name_len > 0xFFFF)
+ return -1;
+ total_len += 4;
+
+ /* check name */
+ name = beg + total_len;
+ if (name + name_len > end)
+ return -1;
+ total_len += name_len;
+
+ if (out) {
+ out->base = beg;
+ out->size = total_len;
+ out->name_len = name_len;
+ out->name = name;
+ memcpy(&out->owner, owner_sid, owner_len);
+ memcpy(&out->group, group_sid, group_len);
+ }
+ return total_len;
+}
+
+static int posix_info_extra_size(const void *beg, const void *end)
+{
+ int len = posix_info_parse(beg, end, NULL);
+
+ if (len < 0)
+ return -1;
+ return len - sizeof(struct smb2_posix_info);
+}
+
+static unsigned int
+num_entries(int infotype, char *bufstart, char *end_of_buf, char **lastentry,
+ size_t size)
+{
+ int len;
+ unsigned int entrycount = 0;
+ unsigned int next_offset = 0;
+ char *entryptr;
+ FILE_DIRECTORY_INFO *dir_info;
+
+ if (bufstart == NULL)
+ return 0;
+
+ entryptr = bufstart;
+
+ while (1) {
+ if (entryptr + next_offset < entryptr ||
+ entryptr + next_offset > end_of_buf ||
+ entryptr + next_offset + size > end_of_buf) {
+ cifs_dbg(VFS, "malformed search entry would overflow\n");
+ break;
+ }
+
+ entryptr = entryptr + next_offset;
+ dir_info = (FILE_DIRECTORY_INFO *)entryptr;
+
+ if (infotype == SMB_FIND_FILE_POSIX_INFO)
+ len = posix_info_extra_size(entryptr, end_of_buf);
+ else
+ len = le32_to_cpu(dir_info->FileNameLength);
+
+ if (len < 0 ||
+ entryptr + len < entryptr ||
+ entryptr + len > end_of_buf ||
+ entryptr + len + size > end_of_buf) {
+ cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n",
+ end_of_buf);
+ break;
+ }
+
+ *lastentry = entryptr;
+ entrycount++;
+
+ next_offset = le32_to_cpu(dir_info->NextEntryOffset);
+ if (!next_offset)
+ break;
+ }
+
+ return entrycount;
+}
+
+/*
+ * Readdir/FindFirst
+ */
+int SMB2_query_directory_init(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid,
+ int index, int info_level)
+{
+ struct smb2_query_directory_req *req;
+ unsigned char *bufptr;
+ __le16 asteriks = cpu_to_le16('*');
+ unsigned int output_size = CIFSMaxBufSize -
+ MAX_SMB2_CREATE_RESPONSE_SIZE -
+ MAX_SMB2_CLOSE_RESPONSE_SIZE;
+ unsigned int total_len;
+ struct kvec *iov = rqst->rq_iov;
+ int len, rc;
+
+ rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ switch (info_level) {
+ case SMB_FIND_FILE_DIRECTORY_INFO:
+ req->FileInformationClass = FILE_DIRECTORY_INFORMATION;
+ break;
+ case SMB_FIND_FILE_ID_FULL_DIR_INFO:
+ req->FileInformationClass = FILEID_FULL_DIRECTORY_INFORMATION;
+ break;
+ case SMB_FIND_FILE_POSIX_INFO:
+ req->FileInformationClass = SMB_FIND_FILE_POSIX_INFO;
+ break;
+ default:
+ cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
+ info_level);
+ return -EINVAL;
+ }
+
+ req->FileIndex = cpu_to_le32(index);
+ req->PersistentFileId = persistent_fid;
+ req->VolatileFileId = volatile_fid;
+
+ len = 0x2;
+ bufptr = req->Buffer;
+ memcpy(bufptr, &asteriks, len);
+
+ req->FileNameOffset =
+ cpu_to_le16(sizeof(struct smb2_query_directory_req) - 1);
+ req->FileNameLength = cpu_to_le16(len);
+ /*
+ * BB could be 30 bytes or so longer if we used SMB2 specific
+ * buffer lengths, but this is safe and close enough.
+ */
+ output_size = min_t(unsigned int, output_size, server->maxBuf);
+ output_size = min_t(unsigned int, output_size, 2 << 15);
+ req->OutputBufferLength = cpu_to_le32(output_size);
+
+ iov[0].iov_base = (char *)req;
+ /* 1 for Buffer */
+ iov[0].iov_len = total_len - 1;
+
+ iov[1].iov_base = (char *)(req->Buffer);
+ iov[1].iov_len = len;
+
+ trace_smb3_query_dir_enter(xid, persistent_fid, tcon->tid,
+ tcon->ses->Suid, index, output_size);
+
+ return 0;
+}
+
+void SMB2_query_directory_free(struct smb_rqst *rqst)
+{
+ if (rqst && rqst->rq_iov) {
+ cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
+ }
+}
+
+int
+smb2_parse_query_directory(struct cifs_tcon *tcon,
+ struct kvec *rsp_iov,
+ int resp_buftype,
+ struct cifs_search_info *srch_inf)
+{
+ struct smb2_query_directory_rsp *rsp;
+ size_t info_buf_size;
+ char *end_of_smb;
+ int rc;
+
+ rsp = (struct smb2_query_directory_rsp *)rsp_iov->iov_base;
+
+ switch (srch_inf->info_level) {
+ case SMB_FIND_FILE_DIRECTORY_INFO:
+ info_buf_size = sizeof(FILE_DIRECTORY_INFO) - 1;
+ break;
+ case SMB_FIND_FILE_ID_FULL_DIR_INFO:
+ info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1;
+ break;
+ case SMB_FIND_FILE_POSIX_INFO:
+ /* note that posix payload are variable size */
+ info_buf_size = sizeof(struct smb2_posix_info);
+ break;
+ default:
+ cifs_tcon_dbg(VFS, "info level %u isn't supported\n",
+ srch_inf->info_level);
+ return -EINVAL;
+ }
+
+ rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
+ le32_to_cpu(rsp->OutputBufferLength), rsp_iov,
+ info_buf_size);
+ if (rc) {
+ cifs_tcon_dbg(VFS, "bad info payload");
+ return rc;
+ }
+
+ srch_inf->unicode = true;
+
+ if (srch_inf->ntwrk_buf_start) {
+ if (srch_inf->smallBuf)
+ cifs_small_buf_release(srch_inf->ntwrk_buf_start);
+ else
+ cifs_buf_release(srch_inf->ntwrk_buf_start);
+ }
+ srch_inf->ntwrk_buf_start = (char *)rsp;
+ srch_inf->srch_entries_start = srch_inf->last_entry =
+ (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset);
+ end_of_smb = rsp_iov->iov_len + (char *)rsp;
+
+ srch_inf->entries_in_buffer = num_entries(
+ srch_inf->info_level,
+ srch_inf->srch_entries_start,
+ end_of_smb,
+ &srch_inf->last_entry,
+ info_buf_size);
+
+ srch_inf->index_of_last_entry += srch_inf->entries_in_buffer;
+ cifs_dbg(FYI, "num entries %d last_index %lld srch start %p srch end %p\n",
+ srch_inf->entries_in_buffer, srch_inf->index_of_last_entry,
+ srch_inf->srch_entries_start, srch_inf->last_entry);
+ if (resp_buftype == CIFS_LARGE_BUFFER)
+ srch_inf->smallBuf = false;
+ else if (resp_buftype == CIFS_SMALL_BUFFER)
+ srch_inf->smallBuf = true;
+ else
+ cifs_tcon_dbg(VFS, "Invalid search buffer type\n");
+
+ return 0;
+}
+
+int
+SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, int index,
+ struct cifs_search_info *srch_inf)
+{
+ struct smb_rqst rqst;
+ struct kvec iov[SMB2_QUERY_DIRECTORY_IOV_SIZE];
+ struct smb2_query_directory_rsp *rsp = NULL;
+ int resp_buftype = CIFS_NO_BUFFER;
+ struct kvec rsp_iov;
+ int rc = 0;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ int flags = 0;
+
+ if (!ses || !(ses->server))
+ return -EIO;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ memset(&iov, 0, sizeof(iov));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE;
+
+ rc = SMB2_query_directory_init(xid, tcon, server,
+ &rqst, persistent_fid,
+ volatile_fid, index,
+ srch_inf->info_level);
+ if (rc)
+ goto qdir_exit;
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base;
+
+ if (rc) {
+ if (rc == -ENODATA &&
+ rsp->hdr.Status == STATUS_NO_MORE_FILES) {
+ trace_smb3_query_dir_done(xid, persistent_fid,
+ tcon->tid, tcon->ses->Suid, index, 0);
+ srch_inf->endOfSearch = true;
+ rc = 0;
+ } else {
+ trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid,
+ tcon->ses->Suid, index, 0, rc);
+ cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
+ }
+ goto qdir_exit;
+ }
+
+ rc = smb2_parse_query_directory(tcon, &rsp_iov, resp_buftype,
+ srch_inf);
+ if (rc) {
+ trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid,
+ tcon->ses->Suid, index, 0, rc);
+ goto qdir_exit;
+ }
+ resp_buftype = CIFS_NO_BUFFER;
+
+ trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid,
+ tcon->ses->Suid, index, srch_inf->entries_in_buffer);
+
+qdir_exit:
+ SMB2_query_directory_free(&rqst);
+ free_rsp_buf(resp_buftype, rsp);
+ return rc;
+}
+
+int
+SMB2_set_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid, u32 pid,
+ u8 info_class, u8 info_type, u32 additional_info,
+ void **data, unsigned int *size)
+{
+ struct smb2_set_info_req *req;
+ struct kvec *iov = rqst->rq_iov;
+ unsigned int i, total_len;
+ int rc;
+
+ rc = smb2_plain_req_init(SMB2_SET_INFO, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ req->hdr.Id.SyncId.ProcessId = cpu_to_le32(pid);
+ req->InfoType = info_type;
+ req->FileInfoClass = info_class;
+ req->PersistentFileId = persistent_fid;
+ req->VolatileFileId = volatile_fid;
+ req->AdditionalInformation = cpu_to_le32(additional_info);
+
+ req->BufferOffset =
+ cpu_to_le16(sizeof(struct smb2_set_info_req) - 1);
+ req->BufferLength = cpu_to_le32(*size);
+
+ memcpy(req->Buffer, *data, *size);
+ total_len += *size;
+
+ iov[0].iov_base = (char *)req;
+ /* 1 for Buffer */
+ iov[0].iov_len = total_len - 1;
+
+ for (i = 1; i < rqst->rq_nvec; i++) {
+ le32_add_cpu(&req->BufferLength, size[i]);
+ iov[i].iov_base = (char *)data[i];
+ iov[i].iov_len = size[i];
+ }
+
+ return 0;
+}
+
+void
+SMB2_set_info_free(struct smb_rqst *rqst)
+{
+ if (rqst && rqst->rq_iov)
+ cifs_buf_release(rqst->rq_iov[0].iov_base); /* request */
+}
+
+static int
+send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, u32 pid, u8 info_class,
+ u8 info_type, u32 additional_info, unsigned int num,
+ void **data, unsigned int *size)
+{
+ struct smb_rqst rqst;
+ struct smb2_set_info_rsp *rsp = NULL;
+ struct kvec *iov;
+ struct kvec rsp_iov;
+ int rc = 0;
+ int resp_buftype;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ int flags = 0;
+
+ if (!ses || !server)
+ return -EIO;
+
+ if (!num)
+ return -EINVAL;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL);
+ if (!iov)
+ return -ENOMEM;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = num;
+
+ rc = SMB2_set_info_init(tcon, server,
+ &rqst, persistent_fid, volatile_fid, pid,
+ info_class, info_type, additional_info,
+ data, size);
+ if (rc) {
+ kfree(iov);
+ return rc;
+ }
+
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags,
+ &rsp_iov);
+ SMB2_set_info_free(&rqst);
+ rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base;
+
+ if (rc != 0) {
+ cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE);
+ trace_smb3_set_info_err(xid, persistent_fid, tcon->tid,
+ ses->Suid, info_class, (__u32)info_type, rc);
+ }
+
+ free_rsp_buf(resp_buftype, rsp);
+ kfree(iov);
+ return rc;
+}
+
+int
+SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
+ u64 volatile_fid, u32 pid, __le64 *eof)
+{
+ struct smb2_file_eof_info info;
+ void *data;
+ unsigned int size;
+
+ info.EndOfFile = *eof;
+
+ data = &info;
+ size = sizeof(struct smb2_file_eof_info);
+
+ trace_smb3_set_eof(xid, persistent_fid, tcon->tid, tcon->ses->Suid, le64_to_cpu(*eof));
+
+ return send_set_info(xid, tcon, persistent_fid, volatile_fid,
+ pid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE,
+ 0, 1, &data, &size);
+}
+
+int
+SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ struct cifs_ntsd *pnntsd, int pacllen, int aclflag)
+{
+ return send_set_info(xid, tcon, persistent_fid, volatile_fid,
+ current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag,
+ 1, (void **)&pnntsd, &pacllen);
+}
+
+int
+SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ struct smb2_file_full_ea_info *buf, int len)
+{
+ return send_set_info(xid, tcon, persistent_fid, volatile_fid,
+ current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE,
+ 0, 1, (void **)&buf, &len);
+}
+
+int
+SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
+ const u64 persistent_fid, const u64 volatile_fid,
+ __u8 oplock_level)
+{
+ struct smb_rqst rqst;
+ int rc;
+ struct smb2_oplock_break *req = NULL;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ int flags = CIFS_OBREAK_OP;
+ unsigned int total_len;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ int resp_buf_type;
+
+ cifs_dbg(FYI, "SMB2_oplock_break\n");
+ rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ req->VolatileFid = volatile_fid;
+ req->PersistentFid = persistent_fid;
+ req->OplockLevel = oplock_level;
+ req->hdr.CreditRequest = cpu_to_le16(1);
+
+ flags |= CIFS_NO_RSP_BUF;
+
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buf_type, flags, &rsp_iov);
+ cifs_small_buf_release(req);
+
+ if (rc) {
+ cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
+ cifs_dbg(FYI, "Send error in Oplock Break = %d\n", rc);
+ }
+
+ return rc;
+}
+
+void
+smb2_copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf,
+ struct kstatfs *kst)
+{
+ kst->f_bsize = le32_to_cpu(pfs_inf->BytesPerSector) *
+ le32_to_cpu(pfs_inf->SectorsPerAllocationUnit);
+ kst->f_blocks = le64_to_cpu(pfs_inf->TotalAllocationUnits);
+ kst->f_bfree = kst->f_bavail =
+ le64_to_cpu(pfs_inf->CallerAvailableAllocationUnits);
+ return;
+}
+
+static void
+copy_posix_fs_info_to_kstatfs(FILE_SYSTEM_POSIX_INFO *response_data,
+ struct kstatfs *kst)
+{
+ kst->f_bsize = le32_to_cpu(response_data->BlockSize);
+ kst->f_blocks = le64_to_cpu(response_data->TotalBlocks);
+ kst->f_bfree = le64_to_cpu(response_data->BlocksAvail);
+ if (response_data->UserBlocksAvail == cpu_to_le64(-1))
+ kst->f_bavail = kst->f_bfree;
+ else
+ kst->f_bavail = le64_to_cpu(response_data->UserBlocksAvail);
+ if (response_data->TotalFileNodes != cpu_to_le64(-1))
+ kst->f_files = le64_to_cpu(response_data->TotalFileNodes);
+ if (response_data->FreeFileNodes != cpu_to_le64(-1))
+ kst->f_ffree = le64_to_cpu(response_data->FreeFileNodes);
+
+ return;
+}
+
+static int
+build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ int level, int outbuf_len, u64 persistent_fid,
+ u64 volatile_fid)
+{
+ int rc;
+ struct smb2_query_info_req *req;
+ unsigned int total_len;
+
+ cifs_dbg(FYI, "Query FSInfo level %d\n", level);
+
+ if ((tcon->ses == NULL) || server == NULL)
+ return -EIO;
+
+ rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ req->InfoType = SMB2_O_INFO_FILESYSTEM;
+ req->FileInfoClass = level;
+ req->PersistentFileId = persistent_fid;
+ req->VolatileFileId = volatile_fid;
+ /* 1 for pad */
+ req->InputBufferOffset =
+ cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
+ req->OutputBufferLength = cpu_to_le32(
+ outbuf_len + sizeof(struct smb2_query_info_rsp) - 1);
+
+ iov->iov_base = (char *)req;
+ iov->iov_len = total_len;
+ return 0;
+}
+
+int
+SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
+{
+ struct smb_rqst rqst;
+ struct smb2_query_info_rsp *rsp = NULL;
+ struct kvec iov;
+ struct kvec rsp_iov;
+ int rc = 0;
+ int resp_buftype;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ FILE_SYSTEM_POSIX_INFO *info = NULL;
+ int flags = 0;
+
+ rc = build_qfs_info_req(&iov, tcon, server,
+ FS_POSIX_INFORMATION,
+ sizeof(FILE_SYSTEM_POSIX_INFO),
+ persistent_fid, volatile_fid);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = &iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ cifs_small_buf_release(iov.iov_base);
+ if (rc) {
+ cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
+ goto posix_qfsinf_exit;
+ }
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
+
+ info = (FILE_SYSTEM_POSIX_INFO *)(
+ le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
+ rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
+ le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
+ sizeof(FILE_SYSTEM_POSIX_INFO));
+ if (!rc)
+ copy_posix_fs_info_to_kstatfs(info, fsdata);
+
+posix_qfsinf_exit:
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+ return rc;
+}
+
+int
+SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
+{
+ struct smb_rqst rqst;
+ struct smb2_query_info_rsp *rsp = NULL;
+ struct kvec iov;
+ struct kvec rsp_iov;
+ int rc = 0;
+ int resp_buftype;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ struct smb2_fs_full_size_info *info = NULL;
+ int flags = 0;
+
+ rc = build_qfs_info_req(&iov, tcon, server,
+ FS_FULL_SIZE_INFORMATION,
+ sizeof(struct smb2_fs_full_size_info),
+ persistent_fid, volatile_fid);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = &iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ cifs_small_buf_release(iov.iov_base);
+ if (rc) {
+ cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
+ goto qfsinf_exit;
+ }
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
+
+ info = (struct smb2_fs_full_size_info *)(
+ le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
+ rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
+ le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
+ sizeof(struct smb2_fs_full_size_info));
+ if (!rc)
+ smb2_copy_fs_info_to_kstatfs(info, fsdata);
+
+qfsinf_exit:
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+ return rc;
+}
+
+int
+SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, int level)
+{
+ struct smb_rqst rqst;
+ struct smb2_query_info_rsp *rsp = NULL;
+ struct kvec iov;
+ struct kvec rsp_iov;
+ int rc = 0;
+ int resp_buftype, max_len, min_len;
+ struct cifs_ses *ses = tcon->ses;
+ struct TCP_Server_Info *server = cifs_pick_channel(ses);
+ unsigned int rsp_len, offset;
+ int flags = 0;
+
+ if (level == FS_DEVICE_INFORMATION) {
+ max_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
+ min_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
+ } else if (level == FS_ATTRIBUTE_INFORMATION) {
+ max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO);
+ min_len = MIN_FS_ATTR_INFO_SIZE;
+ } else if (level == FS_SECTOR_SIZE_INFORMATION) {
+ max_len = sizeof(struct smb3_fs_ss_info);
+ min_len = sizeof(struct smb3_fs_ss_info);
+ } else if (level == FS_VOLUME_INFORMATION) {
+ max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN;
+ min_len = sizeof(struct smb3_fs_vol_info);
+ } else {
+ cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level);
+ return -EINVAL;
+ }
+
+ rc = build_qfs_info_req(&iov, tcon, server,
+ level, max_len,
+ persistent_fid, volatile_fid);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = &iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buftype, flags, &rsp_iov);
+ cifs_small_buf_release(iov.iov_base);
+ if (rc) {
+ cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
+ goto qfsattr_exit;
+ }
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
+
+ rsp_len = le32_to_cpu(rsp->OutputBufferLength);
+ offset = le16_to_cpu(rsp->OutputBufferOffset);
+ rc = smb2_validate_iov(offset, rsp_len, &rsp_iov, min_len);
+ if (rc)
+ goto qfsattr_exit;
+
+ if (level == FS_ATTRIBUTE_INFORMATION)
+ memcpy(&tcon->fsAttrInfo, offset
+ + (char *)rsp, min_t(unsigned int,
+ rsp_len, max_len));
+ else if (level == FS_DEVICE_INFORMATION)
+ memcpy(&tcon->fsDevInfo, offset
+ + (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO));
+ else if (level == FS_SECTOR_SIZE_INFORMATION) {
+ struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
+ (offset + (char *)rsp);
+ tcon->ss_flags = le32_to_cpu(ss_info->Flags);
+ tcon->perf_sector_size =
+ le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
+ } else if (level == FS_VOLUME_INFORMATION) {
+ struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *)
+ (offset + (char *)rsp);
+ tcon->vol_serial_number = vol_info->VolumeSerialNumber;
+ tcon->vol_create_time = vol_info->VolumeCreationTime;
+ }
+
+qfsattr_exit:
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+ return rc;
+}
+
+int
+smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid,
+ const __u32 num_lock, struct smb2_lock_element *buf)
+{
+ struct smb_rqst rqst;
+ int rc = 0;
+ struct smb2_lock_req *req = NULL;
+ struct kvec iov[2];
+ struct kvec rsp_iov;
+ int resp_buf_type;
+ unsigned int count;
+ int flags = CIFS_NO_RSP_BUF;
+ unsigned int total_len;
+ struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
+
+ cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock);
+
+ rc = smb2_plain_req_init(SMB2_LOCK, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ req->hdr.Id.SyncId.ProcessId = cpu_to_le32(pid);
+ req->LockCount = cpu_to_le16(num_lock);
+
+ req->PersistentFileId = persist_fid;
+ req->VolatileFileId = volatile_fid;
+
+ count = num_lock * sizeof(struct smb2_lock_element);
+
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len - sizeof(struct smb2_lock_element);
+ iov[1].iov_base = (char *)buf;
+ iov[1].iov_len = count;
+
+ cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 2;
+
+ rc = cifs_send_recv(xid, tcon->ses, server,
+ &rqst, &resp_buf_type, flags,
+ &rsp_iov);
+ cifs_small_buf_release(req);
+ if (rc) {
+ cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc);
+ cifs_stats_fail_inc(tcon, SMB2_LOCK_HE);
+ trace_smb3_lock_err(xid, persist_fid, tcon->tid,
+ tcon->ses->Suid, rc);
+ }
+
+ return rc;
+}
+
+int
+SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid,
+ const __u64 length, const __u64 offset, const __u32 lock_flags,
+ const bool wait)
+{
+ struct smb2_lock_element lock;
+
+ lock.Offset = cpu_to_le64(offset);
+ lock.Length = cpu_to_le64(length);
+ lock.Flags = cpu_to_le32(lock_flags);
+ if (!wait && lock_flags != SMB2_LOCKFLAG_UNLOCK)
+ lock.Flags |= cpu_to_le32(SMB2_LOCKFLAG_FAIL_IMMEDIATELY);
+
+ return smb2_lockv(xid, tcon, persist_fid, volatile_fid, pid, 1, &lock);
+}
+
+int
+SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
+ __u8 *lease_key, const __le32 lease_state)
+{
+ struct smb_rqst rqst;
+ int rc;
+ struct smb2_lease_ack *req = NULL;
+ struct cifs_ses *ses = tcon->ses;
+ int flags = CIFS_OBREAK_OP;
+ unsigned int total_len;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ int resp_buf_type;
+ __u64 *please_key_high;
+ __u64 *please_key_low;
+ struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
+
+ cifs_dbg(FYI, "SMB2_lease_break\n");
+ rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server,
+ (void **) &req, &total_len);
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+ req->hdr.CreditRequest = cpu_to_le16(1);
+ req->StructureSize = cpu_to_le16(36);
+ total_len += 12;
+
+ memcpy(req->LeaseKey, lease_key, 16);
+ req->LeaseState = lease_state;
+
+ flags |= CIFS_NO_RSP_BUF;
+
+ iov[0].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, server,
+ &rqst, &resp_buf_type, flags, &rsp_iov);
+ cifs_small_buf_release(req);
+
+ please_key_low = (__u64 *)lease_key;
+ please_key_high = (__u64 *)(lease_key+8);
+ if (rc) {
+ cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
+ trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid,
+ ses->Suid, *please_key_low, *please_key_high, rc);
+ cifs_dbg(FYI, "Send error in Lease Break = %d\n", rc);
+ } else
+ trace_smb3_lease_done(le32_to_cpu(lease_state), tcon->tid,
+ ses->Suid, *please_key_low, *please_key_high);
+
+ return rc;
+}
diff --git a/fs/smb/client/smb2pdu.h b/fs/smb/client/smb2pdu.h
new file mode 100644
index 000000000000..1237bb86e93a
--- /dev/null
+++ b/fs/smb/client/smb2pdu.h
@@ -0,0 +1,434 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2009, 2013
+ * Etersoft, 2012
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Pavel Shilovsky (pshilovsky@samba.org) 2012
+ *
+ */
+
+#ifndef _SMB2PDU_H
+#define _SMB2PDU_H
+
+#include <net/sock.h>
+#include "cifsacl.h"
+
+/* 52 transform hdr + 64 hdr + 88 create rsp */
+#define SMB2_TRANSFORM_HEADER_SIZE 52
+#define MAX_SMB2_HDR_SIZE 204
+
+/* The total header size for SMB2 read and write */
+#define SMB2_READWRITE_PDU_HEADER_SIZE (48 + sizeof(struct smb2_hdr))
+
+/* See MS-SMB2 2.2.43 */
+struct smb2_rdma_transform {
+ __le16 RdmaDescriptorOffset;
+ __le16 RdmaDescriptorLength;
+ __le32 Channel; /* for values see channel description in smb2 read above */
+ __le16 TransformCount;
+ __le16 Reserved1;
+ __le32 Reserved2;
+} __packed;
+
+/* TransformType */
+#define SMB2_RDMA_TRANSFORM_TYPE_ENCRYPTION 0x0001
+#define SMB2_RDMA_TRANSFORM_TYPE_SIGNING 0x0002
+
+struct smb2_rdma_crypto_transform {
+ __le16 TransformType;
+ __le16 SignatureLength;
+ __le16 NonceLength;
+ __u16 Reserved;
+ __u8 Signature[]; /* variable length */
+ /* u8 Nonce[] */
+ /* followed by padding */
+} __packed;
+
+/*
+ * Definitions for SMB2 Protocol Data Units (network frames)
+ *
+ * See MS-SMB2.PDF specification for protocol details.
+ * The Naming convention is the lower case version of the SMB2
+ * command code name for the struct. Note that structures must be packed.
+ *
+ */
+
+#define COMPOUND_FID 0xFFFFFFFFFFFFFFFFULL
+
+#define SMB2_SYMLINK_STRUCT_SIZE \
+ (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
+
+#define SYMLINK_ERROR_TAG 0x4c4d5953
+
+struct smb2_symlink_err_rsp {
+ __le32 SymLinkLength;
+ __le32 SymLinkErrorTag;
+ __le32 ReparseTag;
+ __le16 ReparseDataLength;
+ __le16 UnparsedPathLength;
+ __le16 SubstituteNameOffset;
+ __le16 SubstituteNameLength;
+ __le16 PrintNameOffset;
+ __le16 PrintNameLength;
+ __le32 Flags;
+ __u8 PathBuffer[];
+} __packed;
+
+/* SMB 3.1.1 and later dialects. See MS-SMB2 section 2.2.2.1 */
+struct smb2_error_context_rsp {
+ __le32 ErrorDataLength;
+ __le32 ErrorId;
+ __u8 ErrorContextData; /* ErrorDataLength long array */
+} __packed;
+
+/* ErrorId values */
+#define SMB2_ERROR_ID_DEFAULT 0x00000000
+#define SMB2_ERROR_ID_SHARE_REDIRECT cpu_to_le32(0x72645253) /* "rdRS" */
+
+/* Defines for Type field below (see MS-SMB2 2.2.2.2.2.1) */
+#define MOVE_DST_IPADDR_V4 cpu_to_le32(0x00000001)
+#define MOVE_DST_IPADDR_V6 cpu_to_le32(0x00000002)
+
+struct move_dst_ipaddr {
+ __le32 Type;
+ __u32 Reserved;
+ __u8 address[16]; /* IPv4 followed by 12 bytes rsvd or IPv6 address */
+} __packed;
+
+struct share_redirect_error_context_rsp {
+ __le32 StructureSize;
+ __le32 NotificationType;
+ __le32 ResourceNameOffset;
+ __le32 ResourceNameLength;
+ __le16 Reserved;
+ __le16 TargetType;
+ __le32 IPAddrCount;
+ struct move_dst_ipaddr IpAddrMoveList[];
+ /* __u8 ResourceName[] */ /* Name of share as counted Unicode string */
+} __packed;
+
+/*
+ * Maximum number of iovs we need for an open/create request.
+ * [0] : struct smb2_create_req
+ * [1] : path
+ * [2] : lease context
+ * [3] : durable context
+ * [4] : posix context
+ * [5] : time warp context
+ * [6] : query id context
+ * [7] : compound padding
+ */
+#define SMB2_CREATE_IOV_SIZE 8
+
+/*
+ * Maximum size of a SMB2_CREATE response is 64 (smb2 header) +
+ * 88 (fixed part of create response) + 520 (path) + 208 (contexts) +
+ * 2 bytes of padding.
+ */
+#define MAX_SMB2_CREATE_RESPONSE_SIZE 880
+
+#define SMB2_LEASE_READ_CACHING_HE 0x01
+#define SMB2_LEASE_HANDLE_CACHING_HE 0x02
+#define SMB2_LEASE_WRITE_CACHING_HE 0x04
+
+struct create_durable {
+ struct create_context ccontext;
+ __u8 Name[8];
+ union {
+ __u8 Reserved[16];
+ struct {
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ } Fid;
+ } Data;
+} __packed;
+
+/* See MS-SMB2 2.2.13.2.11 */
+/* Flags */
+#define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002
+struct durable_context_v2 {
+ __le32 Timeout;
+ __le32 Flags;
+ __u64 Reserved;
+ __u8 CreateGuid[16];
+} __packed;
+
+struct create_durable_v2 {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct durable_context_v2 dcontext;
+} __packed;
+
+/* See MS-SMB2 2.2.13.2.12 */
+struct durable_reconnect_context_v2 {
+ struct {
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ } Fid;
+ __u8 CreateGuid[16];
+ __le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
+} __packed;
+
+/* See MS-SMB2 2.2.14.2.9 */
+struct create_on_disk_id {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __le64 DiskFileId;
+ __le64 VolumeId;
+ __u32 Reserved[4];
+} __packed;
+
+/* See MS-SMB2 2.2.14.2.12 */
+struct durable_reconnect_context_v2_rsp {
+ __le32 Timeout;
+ __le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
+} __packed;
+
+struct create_durable_handle_reconnect_v2 {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct durable_reconnect_context_v2 dcontext;
+ __u8 Pad[4];
+} __packed;
+
+/* See MS-SMB2 2.2.13.2.5 */
+struct crt_twarp_ctxt {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __le64 Timestamp;
+
+} __packed;
+
+/* See MS-SMB2 2.2.13.2.9 */
+struct crt_query_id_ctxt {
+ struct create_context ccontext;
+ __u8 Name[8];
+} __packed;
+
+struct crt_sd_ctxt {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct smb3_sd sd;
+} __packed;
+
+
+#define COPY_CHUNK_RES_KEY_SIZE 24
+struct resume_key_req {
+ char ResumeKey[COPY_CHUNK_RES_KEY_SIZE];
+ __le32 ContextLength; /* MBZ */
+ char Context[]; /* ignored, Windows sets to 4 bytes of zero */
+} __packed;
+
+/* this goes in the ioctl buffer when doing a copychunk request */
+struct copychunk_ioctl {
+ char SourceKey[COPY_CHUNK_RES_KEY_SIZE];
+ __le32 ChunkCount; /* we are only sending 1 */
+ __le32 Reserved;
+ /* array will only be one chunk long for us */
+ __le64 SourceOffset;
+ __le64 TargetOffset;
+ __le32 Length; /* how many bytes to copy */
+ __u32 Reserved2;
+} __packed;
+
+struct copychunk_ioctl_rsp {
+ __le32 ChunksWritten;
+ __le32 ChunkBytesWritten;
+ __le32 TotalBytesWritten;
+} __packed;
+
+/* See MS-FSCC 2.3.29 and 2.3.30 */
+struct get_retrieval_pointer_count_req {
+ __le64 StartingVcn; /* virtual cluster number (signed) */
+} __packed;
+
+struct get_retrieval_pointer_count_rsp {
+ __le32 ExtentCount;
+} __packed;
+
+/*
+ * See MS-FSCC 2.3.33 and 2.3.34
+ * request is the same as get_retrieval_point_count_req struct above
+ */
+struct smb3_extents {
+ __le64 NextVcn;
+ __le64 Lcn; /* logical cluster number */
+} __packed;
+
+struct get_retrieval_pointers_refcount_rsp {
+ __le32 ExtentCount;
+ __u32 Reserved;
+ __le64 StartingVcn;
+ struct smb3_extents extents[];
+} __packed;
+
+/* See MS-DFSC 2.2.2 */
+struct fsctl_get_dfs_referral_req {
+ __le16 MaxReferralLevel;
+ __u8 RequestFileName[];
+} __packed;
+
+/* DFS response is struct get_dfs_refer_rsp */
+
+/* See MS-SMB2 2.2.31.3 */
+struct network_resiliency_req {
+ __le32 Timeout;
+ __le32 Reserved;
+} __packed;
+/* There is no buffer for the response ie no struct network_resiliency_rsp */
+
+#define RSS_CAPABLE cpu_to_le32(0x00000001)
+#define RDMA_CAPABLE cpu_to_le32(0x00000002)
+
+#define INTERNETWORK cpu_to_le16(0x0002)
+#define INTERNETWORKV6 cpu_to_le16(0x0017)
+
+struct network_interface_info_ioctl_rsp {
+ __le32 Next; /* next interface. zero if this is last one */
+ __le32 IfIndex;
+ __le32 Capability; /* RSS or RDMA Capable */
+ __le32 Reserved;
+ __le64 LinkSpeed;
+ __le16 Family;
+ __u8 Buffer[126];
+} __packed;
+
+struct iface_info_ipv4 {
+ __be16 Port;
+ __be32 IPv4Address;
+ __be64 Reserved;
+} __packed;
+
+struct iface_info_ipv6 {
+ __be16 Port;
+ __be32 FlowInfo;
+ __u8 IPv6Address[16];
+ __be32 ScopeId;
+} __packed;
+
+#define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL /* general ioctls to srv not to file */
+
+struct compress_ioctl {
+ __le16 CompressionState; /* See cifspdu.h for possible flag values */
+} __packed;
+
+/*
+ * Maximum number of iovs we need for an ioctl request.
+ * [0] : struct smb2_ioctl_req
+ * [1] : in_data
+ */
+#define SMB2_IOCTL_IOV_SIZE 2
+
+/*
+ * PDU query infolevel structure definitions
+ * BB consider moving to a different header
+ */
+
+struct smb2_file_full_ea_info { /* encoding of response for level 15 */
+ __le32 next_entry_offset;
+ __u8 flags;
+ __u8 ea_name_length;
+ __le16 ea_value_length;
+ char ea_data[]; /* \0 terminated name plus value */
+} __packed; /* level 15 Set */
+
+struct smb2_file_reparse_point_info {
+ __le64 IndexNumber;
+ __le32 Tag;
+} __packed;
+
+struct smb2_file_network_open_info {
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 AllocationSize;
+ __le64 EndOfFile;
+ __le32 Attributes;
+ __le32 Reserved;
+} __packed; /* level 34 Query also similar returned in close rsp and open rsp */
+
+/* See MS-FSCC 2.4.21 */
+struct smb2_file_id_information {
+ __le64 VolumeSerialNumber;
+ __u64 PersistentFileId; /* opaque endianness */
+ __u64 VolatileFileId; /* opaque endianness */
+} __packed; /* level 59 */
+
+/* See MS-FSCC 2.4.18 */
+struct smb2_file_id_extd_directory_info {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 FileAttributes;
+ __le32 FileNameLength;
+ __le32 EaSize; /* EA size */
+ __le32 ReparsePointTag; /* valid if FILE_ATTR_REPARSE_POINT set in FileAttributes */
+ __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit */
+ char FileName[1];
+} __packed; /* level 60 */
+
+extern char smb2_padding[7];
+
+/* equivalent of the contents of SMB3.1.1 POSIX open context response */
+struct create_posix_rsp {
+ u32 nlink;
+ u32 reparse_tag;
+ u32 mode;
+ struct cifs_sid owner; /* var-sized on the wire */
+ struct cifs_sid group; /* var-sized on the wire */
+} __packed;
+
+#define SMB2_QUERY_DIRECTORY_IOV_SIZE 2
+
+/*
+ * SMB2-only POSIX info level for query dir
+ *
+ * See posix_info_sid_size(), posix_info_extra_size() and
+ * posix_info_parse() to help with the handling of this struct.
+ */
+struct smb2_posix_info {
+ __le32 NextEntryOffset;
+ __u32 Ignored;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 DosAttributes;
+ __le64 Inode;
+ __le32 DeviceId;
+ __le32 Zero;
+ /* beginning of POSIX Create Context Response */
+ __le32 HardLinks;
+ __le32 ReparseTag;
+ __le32 Mode;
+ /*
+ * var sized owner SID
+ * var sized group SID
+ * le32 filenamelength
+ * u8 filename[]
+ */
+} __packed;
+
+/*
+ * Parsed version of the above struct. Allows direct access to the
+ * variable length fields
+ */
+struct smb2_posix_info_parsed {
+ const struct smb2_posix_info *base;
+ size_t size;
+ struct cifs_sid owner;
+ struct cifs_sid group;
+ int name_len;
+ const u8 *name;
+};
+
+#endif /* _SMB2PDU_H */
diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
new file mode 100644
index 000000000000..be21b5d26f67
--- /dev/null
+++ b/fs/smb/client/smb2proto.h
@@ -0,0 +1,284 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002, 2011
+ * Etersoft, 2012
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Pavel Shilovsky (pshilovsky@samba.org) 2012
+ *
+ */
+#ifndef _SMB2PROTO_H
+#define _SMB2PROTO_H
+#include <linux/nls.h>
+#include <linux/key-type.h>
+
+struct statfs;
+struct smb_rqst;
+
+/*
+ *****************************************************************
+ * All Prototypes
+ *****************************************************************
+ */
+extern int map_smb2_to_linux_error(char *buf, bool log_err);
+extern int smb2_check_message(char *buf, unsigned int length,
+ struct TCP_Server_Info *server);
+extern unsigned int smb2_calc_size(void *buf);
+extern char *smb2_get_data_area_len(int *off, int *len,
+ struct smb2_hdr *shdr);
+extern __le16 *cifs_convert_path_to_utf16(const char *from,
+ struct cifs_sb_info *cifs_sb);
+
+extern int smb2_verify_signature(struct smb_rqst *, struct TCP_Server_Info *);
+extern int smb2_check_receive(struct mid_q_entry *mid,
+ struct TCP_Server_Info *server, bool log_error);
+extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
+ struct TCP_Server_Info *,
+ struct smb_rqst *rqst);
+extern struct mid_q_entry *smb2_setup_async_request(
+ struct TCP_Server_Info *server, struct smb_rqst *rqst);
+extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
+ __u64 ses_id);
+extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
+ __u64 ses_id, __u32 tid);
+extern int smb2_calc_signature(struct smb_rqst *rqst,
+ struct TCP_Server_Info *server,
+ bool allocate_crypto);
+extern int smb3_calc_signature(struct smb_rqst *rqst,
+ struct TCP_Server_Info *server,
+ bool allocate_crypto);
+extern void smb2_echo_request(struct work_struct *work);
+extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode);
+extern bool smb2_is_valid_oplock_break(char *buffer,
+ struct TCP_Server_Info *srv);
+extern int smb3_handle_read_data(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid);
+extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *path,
+ __u32 *reparse_tag);
+int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
+extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *full_path, __u64 size,
+ struct cifs_sb_info *cifs_sb, bool set_alloc);
+extern int smb2_set_file_info(struct inode *inode, const char *full_path,
+ FILE_BASIC_INFO *buf, const unsigned int xid);
+extern int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
+ umode_t mode, struct cifs_tcon *tcon,
+ const char *full_path,
+ struct cifs_sb_info *cifs_sb);
+extern int smb2_mkdir(const unsigned int xid, struct inode *inode,
+ umode_t mode, struct cifs_tcon *tcon,
+ const char *name, struct cifs_sb_info *cifs_sb);
+extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path,
+ struct cifs_sb_info *cifs_sb,
+ struct cifs_tcon *tcon, const unsigned int xid);
+extern int smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *name, struct cifs_sb_info *cifs_sb);
+extern int smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *name, struct cifs_sb_info *cifs_sb);
+extern int smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb);
+extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb);
+extern int smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const unsigned char *path,
+ char *pbuf, unsigned int *pbytes_written);
+extern int smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ const unsigned char *path, char *pbuf,
+ unsigned int *pbytes_read);
+int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path);
+int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
+ void *buf);
+extern int smb2_unlock_range(struct cifsFileInfo *cfile,
+ struct file_lock *flock, const unsigned int xid);
+extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
+extern void smb2_reconnect_server(struct work_struct *work);
+extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server);
+extern unsigned long smb_rqst_len(struct TCP_Server_Info *server,
+ struct smb_rqst *rqst);
+extern void smb2_set_next_command(struct cifs_tcon *tcon,
+ struct smb_rqst *rqst);
+extern void smb2_set_related(struct smb_rqst *rqst);
+
+/*
+ * SMB2 Worker functions - most of protocol specific implementation details
+ * are contained within these calls.
+ */
+extern int SMB2_negotiate(const unsigned int xid,
+ struct cifs_ses *ses,
+ struct TCP_Server_Info *server);
+extern int SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct nls_table *nls_cp);
+extern int SMB2_logoff(const unsigned int xid, struct cifs_ses *ses);
+extern int SMB2_tcon(const unsigned int xid, struct cifs_ses *ses,
+ const char *tree, struct cifs_tcon *tcon,
+ const struct nls_table *);
+extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
+extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
+ __le16 *path, __u8 *oplock,
+ struct smb2_file_all_info *buf,
+ struct create_posix_rsp *posix,
+ struct kvec *err_iov, int *resp_buftype);
+extern int SMB2_open_init(struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ __u8 *oplock, struct cifs_open_parms *oparms,
+ __le16 *path);
+extern void SMB2_open_free(struct smb_rqst *rqst);
+extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, u32 opcode,
+ char *in_data, u32 indatalen, u32 maxoutlen,
+ char **out_data, u32 *plen /* returned data len */);
+extern int SMB2_ioctl_init(struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid, u32 opcode,
+ char *in_data, u32 indatalen,
+ __u32 max_response_size);
+extern void SMB2_ioctl_free(struct smb_rqst *rqst);
+extern int SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, bool watch_tree,
+ u32 completion_filter, u32 max_out_data_len,
+ char **out_data, u32 *plen /* returned data len */);
+
+extern int __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ struct smb2_file_network_open_info *pbuf);
+extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_file_id, u64 volatile_file_id);
+extern int SMB2_close_init(struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid,
+ bool query_attrs);
+extern void SMB2_close_free(struct smb_rqst *rqst);
+extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_file_id, u64 volatile_file_id);
+extern int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst,
+ struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ u64 persistent_file_id, u64 volatile_file_id);
+extern void SMB2_flush_free(struct smb_rqst *rqst);
+extern int SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen);
+extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_file_id, u64 volatile_file_id,
+ struct smb2_file_all_info *data);
+extern int SMB2_query_info_init(struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid,
+ u8 info_class, u8 info_type,
+ u32 additional_info, size_t output_len,
+ size_t input_len, void *input);
+extern void SMB2_query_info_free(struct smb_rqst *rqst);
+extern int SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_file_id, u64 volatile_file_id,
+ void **data, unsigned int *plen, u32 info);
+extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ __le64 *uniqueid);
+extern int smb2_async_readv(struct cifs_readdata *rdata);
+extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, char **buf, int *buf_type);
+extern int smb2_async_writev(struct cifs_writedata *wdata,
+ void (*release)(struct kref *kref));
+extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
+ unsigned int *nbytes, struct kvec *iov, int n_vec);
+extern int SMB2_echo(struct TCP_Server_Info *server);
+extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, int index,
+ struct cifs_search_info *srch_inf);
+extern int SMB2_query_directory_init(unsigned int xid, struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid,
+ int index, int info_level);
+extern void SMB2_query_directory_free(struct smb_rqst *rqst);
+extern int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, u32 pid,
+ __le64 *eof);
+extern int SMB2_set_info_init(struct cifs_tcon *tcon,
+ struct TCP_Server_Info *server,
+ struct smb_rqst *rqst,
+ u64 persistent_fid, u64 volatile_fid, u32 pid,
+ u8 info_class, u8 info_type, u32 additional_info,
+ void **data, unsigned int *size);
+extern void SMB2_set_info_free(struct smb_rqst *rqst);
+extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ struct cifs_ntsd *pnntsd, int pacllen, int aclflag);
+extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ struct smb2_file_full_ea_info *buf, int len);
+extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid);
+extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
+ const u64 persistent_fid, const u64 volatile_fid,
+ const __u8 oplock_level);
+extern int smb2_handle_cancelled_close(struct cifs_tcon *tcon,
+ __u64 persistent_fid,
+ __u64 volatile_fid);
+extern int smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server);
+void smb2_cancelled_close_fid(struct work_struct *work);
+extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_file_id, u64 volatile_file_id,
+ struct kstatfs *FSData);
+extern int SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_file_id, u64 volatile_file_id,
+ struct kstatfs *FSData);
+extern int SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_file_id, u64 volatile_file_id, int lvl);
+extern int SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u64 persist_fid, const __u64 volatile_fid,
+ const __u32 pid, const __u64 length, const __u64 offset,
+ const __u32 lockFlags, const bool wait);
+extern int smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
+ const __u64 persist_fid, const __u64 volatile_fid,
+ const __u32 pid, const __u32 num_lock,
+ struct smb2_lock_element *buf);
+extern int SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
+ __u8 *lease_key, const __le32 lease_state);
+extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *);
+
+extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
+ enum securityEnum);
+extern void smb2_parse_contexts(struct TCP_Server_Info *server,
+ struct smb2_create_rsp *rsp,
+ unsigned int *epoch, char *lease_key,
+ __u8 *oplock, struct smb2_file_all_info *buf,
+ struct create_posix_rsp *posix);
+extern int smb3_encryption_required(const struct cifs_tcon *tcon);
+extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
+ struct kvec *iov, unsigned int min_buf_size);
+extern int smb2_validate_and_copy_iov(unsigned int offset,
+ unsigned int buffer_length,
+ struct kvec *iov,
+ unsigned int minbufsize, char *data);
+extern void smb2_copy_fs_info_to_kstatfs(
+ struct smb2_fs_full_size_info *pfs_inf,
+ struct kstatfs *kst);
+extern int smb311_crypto_shash_allocate(struct TCP_Server_Info *server);
+extern int smb311_update_preauth_hash(struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ struct kvec *iov, int nvec);
+extern int smb2_query_info_compound(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const char *path, u32 desired_access,
+ u32 class, u32 type, u32 output_len,
+ struct kvec *rsp, int *buftype,
+ struct cifs_sb_info *cifs_sb);
+/* query path info from the server using SMB311 POSIX extensions*/
+int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path,
+ struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
+int posix_info_parse(const void *beg, const void *end,
+ struct smb2_posix_info_parsed *out);
+int posix_info_sid_size(const void *beg, const void *end);
+#endif /* _SMB2PROTO_H */
diff --git a/fs/smb/client/smb2status.h b/fs/smb/client/smb2status.h
new file mode 100644
index 000000000000..a9e958166fc5
--- /dev/null
+++ b/fs/smb/client/smb2status.h
@@ -0,0 +1,1769 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * SMB2 Status code (network error) definitions
+ * Definitions are from MS-ERREF
+ *
+ * Copyright (c) International Business Machines Corp., 2009,2011
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+/*
+ * 0 1 2 3 4 5 6 7 8 9 0 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ * SEV C N <-------Facility--------> <------Error Status Code------>
+ *
+ * C is set if "customer defined" error, N bit is reserved and MBZ
+ */
+
+#define STATUS_SEVERITY_SUCCESS __constant_cpu_to_le32(0x0000)
+#define STATUS_SEVERITY_INFORMATIONAL cpu_to_le32(0x0001)
+#define STATUS_SEVERITY_WARNING cpu_to_le32(0x0002)
+#define STATUS_SEVERITY_ERROR cpu_to_le32(0x0003)
+
+struct ntstatus {
+ /* Facility is the high 12 bits of the following field */
+ __le32 Facility; /* low 2 bits Severity, next is Customer, then rsrvd */
+ __le32 Code;
+};
+
+#define STATUS_SUCCESS cpu_to_le32(0x00000000)
+#define STATUS_WAIT_0 cpu_to_le32(0x00000000)
+#define STATUS_WAIT_1 cpu_to_le32(0x00000001)
+#define STATUS_WAIT_2 cpu_to_le32(0x00000002)
+#define STATUS_WAIT_3 cpu_to_le32(0x00000003)
+#define STATUS_WAIT_63 cpu_to_le32(0x0000003F)
+#define STATUS_ABANDONED cpu_to_le32(0x00000080)
+#define STATUS_ABANDONED_WAIT_0 cpu_to_le32(0x00000080)
+#define STATUS_ABANDONED_WAIT_63 cpu_to_le32(0x000000BF)
+#define STATUS_USER_APC cpu_to_le32(0x000000C0)
+#define STATUS_KERNEL_APC cpu_to_le32(0x00000100)
+#define STATUS_ALERTED cpu_to_le32(0x00000101)
+#define STATUS_TIMEOUT cpu_to_le32(0x00000102)
+#define STATUS_PENDING cpu_to_le32(0x00000103)
+#define STATUS_REPARSE cpu_to_le32(0x00000104)
+#define STATUS_MORE_ENTRIES cpu_to_le32(0x00000105)
+#define STATUS_NOT_ALL_ASSIGNED cpu_to_le32(0x00000106)
+#define STATUS_SOME_NOT_MAPPED cpu_to_le32(0x00000107)
+#define STATUS_OPLOCK_BREAK_IN_PROGRESS cpu_to_le32(0x00000108)
+#define STATUS_VOLUME_MOUNTED cpu_to_le32(0x00000109)
+#define STATUS_RXACT_COMMITTED cpu_to_le32(0x0000010A)
+#define STATUS_NOTIFY_CLEANUP cpu_to_le32(0x0000010B)
+#define STATUS_NOTIFY_ENUM_DIR cpu_to_le32(0x0000010C)
+#define STATUS_NO_QUOTAS_FOR_ACCOUNT cpu_to_le32(0x0000010D)
+#define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED cpu_to_le32(0x0000010E)
+#define STATUS_PAGE_FAULT_TRANSITION cpu_to_le32(0x00000110)
+#define STATUS_PAGE_FAULT_DEMAND_ZERO cpu_to_le32(0x00000111)
+#define STATUS_PAGE_FAULT_COPY_ON_WRITE cpu_to_le32(0x00000112)
+#define STATUS_PAGE_FAULT_GUARD_PAGE cpu_to_le32(0x00000113)
+#define STATUS_PAGE_FAULT_PAGING_FILE cpu_to_le32(0x00000114)
+#define STATUS_CACHE_PAGE_LOCKED cpu_to_le32(0x00000115)
+#define STATUS_CRASH_DUMP cpu_to_le32(0x00000116)
+#define STATUS_BUFFER_ALL_ZEROS cpu_to_le32(0x00000117)
+#define STATUS_REPARSE_OBJECT cpu_to_le32(0x00000118)
+#define STATUS_RESOURCE_REQUIREMENTS_CHANGED cpu_to_le32(0x00000119)
+#define STATUS_TRANSLATION_COMPLETE cpu_to_le32(0x00000120)
+#define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY cpu_to_le32(0x00000121)
+#define STATUS_NOTHING_TO_TERMINATE cpu_to_le32(0x00000122)
+#define STATUS_PROCESS_NOT_IN_JOB cpu_to_le32(0x00000123)
+#define STATUS_PROCESS_IN_JOB cpu_to_le32(0x00000124)
+#define STATUS_VOLSNAP_HIBERNATE_READY cpu_to_le32(0x00000125)
+#define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY cpu_to_le32(0x00000126)
+#define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED cpu_to_le32(0x00000127)
+#define STATUS_INTERRUPT_STILL_CONNECTED cpu_to_le32(0x00000128)
+#define STATUS_PROCESS_CLONED cpu_to_le32(0x00000129)
+#define STATUS_FILE_LOCKED_WITH_ONLY_READERS cpu_to_le32(0x0000012A)
+#define STATUS_FILE_LOCKED_WITH_WRITERS cpu_to_le32(0x0000012B)
+#define STATUS_RESOURCEMANAGER_READ_ONLY cpu_to_le32(0x00000202)
+#define STATUS_WAIT_FOR_OPLOCK cpu_to_le32(0x00000367)
+#define DBG_EXCEPTION_HANDLED cpu_to_le32(0x00010001)
+#define DBG_CONTINUE cpu_to_le32(0x00010002)
+#define STATUS_FLT_IO_COMPLETE cpu_to_le32(0x001C0001)
+#define STATUS_OBJECT_NAME_EXISTS cpu_to_le32(0x40000000)
+#define STATUS_THREAD_WAS_SUSPENDED cpu_to_le32(0x40000001)
+#define STATUS_WORKING_SET_LIMIT_RANGE cpu_to_le32(0x40000002)
+#define STATUS_IMAGE_NOT_AT_BASE cpu_to_le32(0x40000003)
+#define STATUS_RXACT_STATE_CREATED cpu_to_le32(0x40000004)
+#define STATUS_SEGMENT_NOTIFICATION cpu_to_le32(0x40000005)
+#define STATUS_LOCAL_USER_SESSION_KEY cpu_to_le32(0x40000006)
+#define STATUS_BAD_CURRENT_DIRECTORY cpu_to_le32(0x40000007)
+#define STATUS_SERIAL_MORE_WRITES cpu_to_le32(0x40000008)
+#define STATUS_REGISTRY_RECOVERED cpu_to_le32(0x40000009)
+#define STATUS_FT_READ_RECOVERY_FROM_BACKUP cpu_to_le32(0x4000000A)
+#define STATUS_FT_WRITE_RECOVERY cpu_to_le32(0x4000000B)
+#define STATUS_SERIAL_COUNTER_TIMEOUT cpu_to_le32(0x4000000C)
+#define STATUS_NULL_LM_PASSWORD cpu_to_le32(0x4000000D)
+#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH cpu_to_le32(0x4000000E)
+#define STATUS_RECEIVE_PARTIAL cpu_to_le32(0x4000000F)
+#define STATUS_RECEIVE_EXPEDITED cpu_to_le32(0x40000010)
+#define STATUS_RECEIVE_PARTIAL_EXPEDITED cpu_to_le32(0x40000011)
+#define STATUS_EVENT_DONE cpu_to_le32(0x40000012)
+#define STATUS_EVENT_PENDING cpu_to_le32(0x40000013)
+#define STATUS_CHECKING_FILE_SYSTEM cpu_to_le32(0x40000014)
+#define STATUS_FATAL_APP_EXIT cpu_to_le32(0x40000015)
+#define STATUS_PREDEFINED_HANDLE cpu_to_le32(0x40000016)
+#define STATUS_WAS_UNLOCKED cpu_to_le32(0x40000017)
+#define STATUS_SERVICE_NOTIFICATION cpu_to_le32(0x40000018)
+#define STATUS_WAS_LOCKED cpu_to_le32(0x40000019)
+#define STATUS_LOG_HARD_ERROR cpu_to_le32(0x4000001A)
+#define STATUS_ALREADY_WIN32 cpu_to_le32(0x4000001B)
+#define STATUS_WX86_UNSIMULATE cpu_to_le32(0x4000001C)
+#define STATUS_WX86_CONTINUE cpu_to_le32(0x4000001D)
+#define STATUS_WX86_SINGLE_STEP cpu_to_le32(0x4000001E)
+#define STATUS_WX86_BREAKPOINT cpu_to_le32(0x4000001F)
+#define STATUS_WX86_EXCEPTION_CONTINUE cpu_to_le32(0x40000020)
+#define STATUS_WX86_EXCEPTION_LASTCHANCE cpu_to_le32(0x40000021)
+#define STATUS_WX86_EXCEPTION_CHAIN cpu_to_le32(0x40000022)
+#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE cpu_to_le32(0x40000023)
+#define STATUS_NO_YIELD_PERFORMED cpu_to_le32(0x40000024)
+#define STATUS_TIMER_RESUME_IGNORED cpu_to_le32(0x40000025)
+#define STATUS_ARBITRATION_UNHANDLED cpu_to_le32(0x40000026)
+#define STATUS_CARDBUS_NOT_SUPPORTED cpu_to_le32(0x40000027)
+#define STATUS_WX86_CREATEWX86TIB cpu_to_le32(0x40000028)
+#define STATUS_MP_PROCESSOR_MISMATCH cpu_to_le32(0x40000029)
+#define STATUS_HIBERNATED cpu_to_le32(0x4000002A)
+#define STATUS_RESUME_HIBERNATION cpu_to_le32(0x4000002B)
+#define STATUS_FIRMWARE_UPDATED cpu_to_le32(0x4000002C)
+#define STATUS_DRIVERS_LEAKING_LOCKED_PAGES cpu_to_le32(0x4000002D)
+#define STATUS_MESSAGE_RETRIEVED cpu_to_le32(0x4000002E)
+#define STATUS_SYSTEM_POWERSTATE_TRANSITION cpu_to_le32(0x4000002F)
+#define STATUS_ALPC_CHECK_COMPLETION_LIST cpu_to_le32(0x40000030)
+#define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION cpu_to_le32(0x40000031)
+#define STATUS_ACCESS_AUDIT_BY_POLICY cpu_to_le32(0x40000032)
+#define STATUS_ABANDON_HIBERFILE cpu_to_le32(0x40000033)
+#define STATUS_BIZRULES_NOT_ENABLED cpu_to_le32(0x40000034)
+#define STATUS_WAKE_SYSTEM cpu_to_le32(0x40000294)
+#define STATUS_DS_SHUTTING_DOWN cpu_to_le32(0x40000370)
+#define DBG_REPLY_LATER cpu_to_le32(0x40010001)
+#define DBG_UNABLE_TO_PROVIDE_HANDLE cpu_to_le32(0x40010002)
+#define DBG_TERMINATE_THREAD cpu_to_le32(0x40010003)
+#define DBG_TERMINATE_PROCESS cpu_to_le32(0x40010004)
+#define DBG_CONTROL_C cpu_to_le32(0x40010005)
+#define DBG_PRINTEXCEPTION_C cpu_to_le32(0x40010006)
+#define DBG_RIPEXCEPTION cpu_to_le32(0x40010007)
+#define DBG_CONTROL_BREAK cpu_to_le32(0x40010008)
+#define DBG_COMMAND_EXCEPTION cpu_to_le32(0x40010009)
+#define RPC_NT_UUID_LOCAL_ONLY cpu_to_le32(0x40020056)
+#define RPC_NT_SEND_INCOMPLETE cpu_to_le32(0x400200AF)
+#define STATUS_CTX_CDM_CONNECT cpu_to_le32(0x400A0004)
+#define STATUS_CTX_CDM_DISCONNECT cpu_to_le32(0x400A0005)
+#define STATUS_SXS_RELEASE_ACTIVATION_CONTEXT cpu_to_le32(0x4015000D)
+#define STATUS_RECOVERY_NOT_NEEDED cpu_to_le32(0x40190034)
+#define STATUS_RM_ALREADY_STARTED cpu_to_le32(0x40190035)
+#define STATUS_LOG_NO_RESTART cpu_to_le32(0x401A000C)
+#define STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST cpu_to_le32(0x401B00EC)
+#define STATUS_GRAPHICS_PARTIAL_DATA_POPULATED cpu_to_le32(0x401E000A)
+#define STATUS_GRAPHICS_DRIVER_MISMATCH cpu_to_le32(0x401E0117)
+#define STATUS_GRAPHICS_MODE_NOT_PINNED cpu_to_le32(0x401E0307)
+#define STATUS_GRAPHICS_NO_PREFERRED_MODE cpu_to_le32(0x401E031E)
+#define STATUS_GRAPHICS_DATASET_IS_EMPTY cpu_to_le32(0x401E034B)
+#define STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET cpu_to_le32(0x401E034C)
+#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED cpu_to_le32(0x401E0351)
+#define STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS cpu_to_le32(0x401E042F)
+#define STATUS_GRAPHICS_LEADLINK_START_DEFERRED cpu_to_le32(0x401E0437)
+#define STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY cpu_to_le32(0x401E0439)
+#define STATUS_GRAPHICS_START_DEFERRED cpu_to_le32(0x401E043A)
+#define STATUS_NDIS_INDICATION_REQUIRED cpu_to_le32(0x40230001)
+#define STATUS_GUARD_PAGE_VIOLATION cpu_to_le32(0x80000001)
+#define STATUS_DATATYPE_MISALIGNMENT cpu_to_le32(0x80000002)
+#define STATUS_BREAKPOINT cpu_to_le32(0x80000003)
+#define STATUS_SINGLE_STEP cpu_to_le32(0x80000004)
+#define STATUS_BUFFER_OVERFLOW cpu_to_le32(0x80000005)
+#define STATUS_NO_MORE_FILES cpu_to_le32(0x80000006)
+#define STATUS_WAKE_SYSTEM_DEBUGGER cpu_to_le32(0x80000007)
+#define STATUS_HANDLES_CLOSED cpu_to_le32(0x8000000A)
+#define STATUS_NO_INHERITANCE cpu_to_le32(0x8000000B)
+#define STATUS_GUID_SUBSTITUTION_MADE cpu_to_le32(0x8000000C)
+#define STATUS_PARTIAL_COPY cpu_to_le32(0x8000000D)
+#define STATUS_DEVICE_PAPER_EMPTY cpu_to_le32(0x8000000E)
+#define STATUS_DEVICE_POWERED_OFF cpu_to_le32(0x8000000F)
+#define STATUS_DEVICE_OFF_LINE cpu_to_le32(0x80000010)
+#define STATUS_DEVICE_BUSY cpu_to_le32(0x80000011)
+#define STATUS_NO_MORE_EAS cpu_to_le32(0x80000012)
+#define STATUS_INVALID_EA_NAME cpu_to_le32(0x80000013)
+#define STATUS_EA_LIST_INCONSISTENT cpu_to_le32(0x80000014)
+#define STATUS_INVALID_EA_FLAG cpu_to_le32(0x80000015)
+#define STATUS_VERIFY_REQUIRED cpu_to_le32(0x80000016)
+#define STATUS_EXTRANEOUS_INFORMATION cpu_to_le32(0x80000017)
+#define STATUS_RXACT_COMMIT_NECESSARY cpu_to_le32(0x80000018)
+#define STATUS_NO_MORE_ENTRIES cpu_to_le32(0x8000001A)
+#define STATUS_FILEMARK_DETECTED cpu_to_le32(0x8000001B)
+#define STATUS_MEDIA_CHANGED cpu_to_le32(0x8000001C)
+#define STATUS_BUS_RESET cpu_to_le32(0x8000001D)
+#define STATUS_END_OF_MEDIA cpu_to_le32(0x8000001E)
+#define STATUS_BEGINNING_OF_MEDIA cpu_to_le32(0x8000001F)
+#define STATUS_MEDIA_CHECK cpu_to_le32(0x80000020)
+#define STATUS_SETMARK_DETECTED cpu_to_le32(0x80000021)
+#define STATUS_NO_DATA_DETECTED cpu_to_le32(0x80000022)
+#define STATUS_REDIRECTOR_HAS_OPEN_HANDLES cpu_to_le32(0x80000023)
+#define STATUS_SERVER_HAS_OPEN_HANDLES cpu_to_le32(0x80000024)
+#define STATUS_ALREADY_DISCONNECTED cpu_to_le32(0x80000025)
+#define STATUS_LONGJUMP cpu_to_le32(0x80000026)
+#define STATUS_CLEANER_CARTRIDGE_INSTALLED cpu_to_le32(0x80000027)
+#define STATUS_PLUGPLAY_QUERY_VETOED cpu_to_le32(0x80000028)
+#define STATUS_UNWIND_CONSOLIDATE cpu_to_le32(0x80000029)
+#define STATUS_REGISTRY_HIVE_RECOVERED cpu_to_le32(0x8000002A)
+#define STATUS_DLL_MIGHT_BE_INSECURE cpu_to_le32(0x8000002B)
+#define STATUS_DLL_MIGHT_BE_INCOMPATIBLE cpu_to_le32(0x8000002C)
+#define STATUS_STOPPED_ON_SYMLINK cpu_to_le32(0x8000002D)
+#define STATUS_DEVICE_REQUIRES_CLEANING cpu_to_le32(0x80000288)
+#define STATUS_DEVICE_DOOR_OPEN cpu_to_le32(0x80000289)
+#define STATUS_DATA_LOST_REPAIR cpu_to_le32(0x80000803)
+#define DBG_EXCEPTION_NOT_HANDLED cpu_to_le32(0x80010001)
+#define STATUS_CLUSTER_NODE_ALREADY_UP cpu_to_le32(0x80130001)
+#define STATUS_CLUSTER_NODE_ALREADY_DOWN cpu_to_le32(0x80130002)
+#define STATUS_CLUSTER_NETWORK_ALREADY_ONLINE cpu_to_le32(0x80130003)
+#define STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE cpu_to_le32(0x80130004)
+#define STATUS_CLUSTER_NODE_ALREADY_MEMBER cpu_to_le32(0x80130005)
+#define STATUS_COULD_NOT_RESIZE_LOG cpu_to_le32(0x80190009)
+#define STATUS_NO_TXF_METADATA cpu_to_le32(0x80190029)
+#define STATUS_CANT_RECOVER_WITH_HANDLE_OPEN cpu_to_le32(0x80190031)
+#define STATUS_TXF_METADATA_ALREADY_PRESENT cpu_to_le32(0x80190041)
+#define STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET cpu_to_le32(0x80190042)
+#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED cpu_to_le32(0x801B00EB)
+#define STATUS_FLT_BUFFER_TOO_SMALL cpu_to_le32(0x801C0001)
+#define STATUS_FVE_PARTIAL_METADATA cpu_to_le32(0x80210001)
+#define STATUS_UNSUCCESSFUL cpu_to_le32(0xC0000001)
+#define STATUS_NOT_IMPLEMENTED cpu_to_le32(0xC0000002)
+#define STATUS_INVALID_INFO_CLASS cpu_to_le32(0xC0000003)
+#define STATUS_INFO_LENGTH_MISMATCH cpu_to_le32(0xC0000004)
+#define STATUS_ACCESS_VIOLATION cpu_to_le32(0xC0000005)
+#define STATUS_IN_PAGE_ERROR cpu_to_le32(0xC0000006)
+#define STATUS_PAGEFILE_QUOTA cpu_to_le32(0xC0000007)
+#define STATUS_INVALID_HANDLE cpu_to_le32(0xC0000008)
+#define STATUS_BAD_INITIAL_STACK cpu_to_le32(0xC0000009)
+#define STATUS_BAD_INITIAL_PC cpu_to_le32(0xC000000A)
+#define STATUS_INVALID_CID cpu_to_le32(0xC000000B)
+#define STATUS_TIMER_NOT_CANCELED cpu_to_le32(0xC000000C)
+#define STATUS_INVALID_PARAMETER cpu_to_le32(0xC000000D)
+#define STATUS_NO_SUCH_DEVICE cpu_to_le32(0xC000000E)
+#define STATUS_NO_SUCH_FILE cpu_to_le32(0xC000000F)
+#define STATUS_INVALID_DEVICE_REQUEST cpu_to_le32(0xC0000010)
+#define STATUS_END_OF_FILE cpu_to_le32(0xC0000011)
+#define STATUS_WRONG_VOLUME cpu_to_le32(0xC0000012)
+#define STATUS_NO_MEDIA_IN_DEVICE cpu_to_le32(0xC0000013)
+#define STATUS_UNRECOGNIZED_MEDIA cpu_to_le32(0xC0000014)
+#define STATUS_NONEXISTENT_SECTOR cpu_to_le32(0xC0000015)
+#define STATUS_MORE_PROCESSING_REQUIRED cpu_to_le32(0xC0000016)
+#define STATUS_NO_MEMORY cpu_to_le32(0xC0000017)
+#define STATUS_CONFLICTING_ADDRESSES cpu_to_le32(0xC0000018)
+#define STATUS_NOT_MAPPED_VIEW cpu_to_le32(0xC0000019)
+#define STATUS_UNABLE_TO_FREE_VM cpu_to_le32(0xC000001A)
+#define STATUS_UNABLE_TO_DELETE_SECTION cpu_to_le32(0xC000001B)
+#define STATUS_INVALID_SYSTEM_SERVICE cpu_to_le32(0xC000001C)
+#define STATUS_ILLEGAL_INSTRUCTION cpu_to_le32(0xC000001D)
+#define STATUS_INVALID_LOCK_SEQUENCE cpu_to_le32(0xC000001E)
+#define STATUS_INVALID_VIEW_SIZE cpu_to_le32(0xC000001F)
+#define STATUS_INVALID_FILE_FOR_SECTION cpu_to_le32(0xC0000020)
+#define STATUS_ALREADY_COMMITTED cpu_to_le32(0xC0000021)
+#define STATUS_ACCESS_DENIED cpu_to_le32(0xC0000022)
+#define STATUS_BUFFER_TOO_SMALL cpu_to_le32(0xC0000023)
+#define STATUS_OBJECT_TYPE_MISMATCH cpu_to_le32(0xC0000024)
+#define STATUS_NONCONTINUABLE_EXCEPTION cpu_to_le32(0xC0000025)
+#define STATUS_INVALID_DISPOSITION cpu_to_le32(0xC0000026)
+#define STATUS_UNWIND cpu_to_le32(0xC0000027)
+#define STATUS_BAD_STACK cpu_to_le32(0xC0000028)
+#define STATUS_INVALID_UNWIND_TARGET cpu_to_le32(0xC0000029)
+#define STATUS_NOT_LOCKED cpu_to_le32(0xC000002A)
+#define STATUS_PARITY_ERROR cpu_to_le32(0xC000002B)
+#define STATUS_UNABLE_TO_DECOMMIT_VM cpu_to_le32(0xC000002C)
+#define STATUS_NOT_COMMITTED cpu_to_le32(0xC000002D)
+#define STATUS_INVALID_PORT_ATTRIBUTES cpu_to_le32(0xC000002E)
+#define STATUS_PORT_MESSAGE_TOO_LONG cpu_to_le32(0xC000002F)
+#define STATUS_INVALID_PARAMETER_MIX cpu_to_le32(0xC0000030)
+#define STATUS_INVALID_QUOTA_LOWER cpu_to_le32(0xC0000031)
+#define STATUS_DISK_CORRUPT_ERROR cpu_to_le32(0xC0000032)
+#define STATUS_OBJECT_NAME_INVALID cpu_to_le32(0xC0000033)
+#define STATUS_OBJECT_NAME_NOT_FOUND cpu_to_le32(0xC0000034)
+#define STATUS_OBJECT_NAME_COLLISION cpu_to_le32(0xC0000035)
+#define STATUS_PORT_DISCONNECTED cpu_to_le32(0xC0000037)
+#define STATUS_DEVICE_ALREADY_ATTACHED cpu_to_le32(0xC0000038)
+#define STATUS_OBJECT_PATH_INVALID cpu_to_le32(0xC0000039)
+#define STATUS_OBJECT_PATH_NOT_FOUND cpu_to_le32(0xC000003A)
+#define STATUS_OBJECT_PATH_SYNTAX_BAD cpu_to_le32(0xC000003B)
+#define STATUS_DATA_OVERRUN cpu_to_le32(0xC000003C)
+#define STATUS_DATA_LATE_ERROR cpu_to_le32(0xC000003D)
+#define STATUS_DATA_ERROR cpu_to_le32(0xC000003E)
+#define STATUS_CRC_ERROR cpu_to_le32(0xC000003F)
+#define STATUS_SECTION_TOO_BIG cpu_to_le32(0xC0000040)
+#define STATUS_PORT_CONNECTION_REFUSED cpu_to_le32(0xC0000041)
+#define STATUS_INVALID_PORT_HANDLE cpu_to_le32(0xC0000042)
+#define STATUS_SHARING_VIOLATION cpu_to_le32(0xC0000043)
+#define STATUS_QUOTA_EXCEEDED cpu_to_le32(0xC0000044)
+#define STATUS_INVALID_PAGE_PROTECTION cpu_to_le32(0xC0000045)
+#define STATUS_MUTANT_NOT_OWNED cpu_to_le32(0xC0000046)
+#define STATUS_SEMAPHORE_LIMIT_EXCEEDED cpu_to_le32(0xC0000047)
+#define STATUS_PORT_ALREADY_SET cpu_to_le32(0xC0000048)
+#define STATUS_SECTION_NOT_IMAGE cpu_to_le32(0xC0000049)
+#define STATUS_SUSPEND_COUNT_EXCEEDED cpu_to_le32(0xC000004A)
+#define STATUS_THREAD_IS_TERMINATING cpu_to_le32(0xC000004B)
+#define STATUS_BAD_WORKING_SET_LIMIT cpu_to_le32(0xC000004C)
+#define STATUS_INCOMPATIBLE_FILE_MAP cpu_to_le32(0xC000004D)
+#define STATUS_SECTION_PROTECTION cpu_to_le32(0xC000004E)
+#define STATUS_EAS_NOT_SUPPORTED cpu_to_le32(0xC000004F)
+#define STATUS_EA_TOO_LARGE cpu_to_le32(0xC0000050)
+#define STATUS_NONEXISTENT_EA_ENTRY cpu_to_le32(0xC0000051)
+#define STATUS_NO_EAS_ON_FILE cpu_to_le32(0xC0000052)
+#define STATUS_EA_CORRUPT_ERROR cpu_to_le32(0xC0000053)
+#define STATUS_FILE_LOCK_CONFLICT cpu_to_le32(0xC0000054)
+#define STATUS_LOCK_NOT_GRANTED cpu_to_le32(0xC0000055)
+#define STATUS_DELETE_PENDING cpu_to_le32(0xC0000056)
+#define STATUS_CTL_FILE_NOT_SUPPORTED cpu_to_le32(0xC0000057)
+#define STATUS_UNKNOWN_REVISION cpu_to_le32(0xC0000058)
+#define STATUS_REVISION_MISMATCH cpu_to_le32(0xC0000059)
+#define STATUS_INVALID_OWNER cpu_to_le32(0xC000005A)
+#define STATUS_INVALID_PRIMARY_GROUP cpu_to_le32(0xC000005B)
+#define STATUS_NO_IMPERSONATION_TOKEN cpu_to_le32(0xC000005C)
+#define STATUS_CANT_DISABLE_MANDATORY cpu_to_le32(0xC000005D)
+#define STATUS_NO_LOGON_SERVERS cpu_to_le32(0xC000005E)
+#define STATUS_NO_SUCH_LOGON_SESSION cpu_to_le32(0xC000005F)
+#define STATUS_NO_SUCH_PRIVILEGE cpu_to_le32(0xC0000060)
+#define STATUS_PRIVILEGE_NOT_HELD cpu_to_le32(0xC0000061)
+#define STATUS_INVALID_ACCOUNT_NAME cpu_to_le32(0xC0000062)
+#define STATUS_USER_EXISTS cpu_to_le32(0xC0000063)
+#define STATUS_NO_SUCH_USER cpu_to_le32(0xC0000064)
+#define STATUS_GROUP_EXISTS cpu_to_le32(0xC0000065)
+#define STATUS_NO_SUCH_GROUP cpu_to_le32(0xC0000066)
+#define STATUS_MEMBER_IN_GROUP cpu_to_le32(0xC0000067)
+#define STATUS_MEMBER_NOT_IN_GROUP cpu_to_le32(0xC0000068)
+#define STATUS_LAST_ADMIN cpu_to_le32(0xC0000069)
+#define STATUS_WRONG_PASSWORD cpu_to_le32(0xC000006A)
+#define STATUS_ILL_FORMED_PASSWORD cpu_to_le32(0xC000006B)
+#define STATUS_PASSWORD_RESTRICTION cpu_to_le32(0xC000006C)
+#define STATUS_LOGON_FAILURE cpu_to_le32(0xC000006D)
+#define STATUS_ACCOUNT_RESTRICTION cpu_to_le32(0xC000006E)
+#define STATUS_INVALID_LOGON_HOURS cpu_to_le32(0xC000006F)
+#define STATUS_INVALID_WORKSTATION cpu_to_le32(0xC0000070)
+#define STATUS_PASSWORD_EXPIRED cpu_to_le32(0xC0000071)
+#define STATUS_ACCOUNT_DISABLED cpu_to_le32(0xC0000072)
+#define STATUS_NONE_MAPPED cpu_to_le32(0xC0000073)
+#define STATUS_TOO_MANY_LUIDS_REQUESTED cpu_to_le32(0xC0000074)
+#define STATUS_LUIDS_EXHAUSTED cpu_to_le32(0xC0000075)
+#define STATUS_INVALID_SUB_AUTHORITY cpu_to_le32(0xC0000076)
+#define STATUS_INVALID_ACL cpu_to_le32(0xC0000077)
+#define STATUS_INVALID_SID cpu_to_le32(0xC0000078)
+#define STATUS_INVALID_SECURITY_DESCR cpu_to_le32(0xC0000079)
+#define STATUS_PROCEDURE_NOT_FOUND cpu_to_le32(0xC000007A)
+#define STATUS_INVALID_IMAGE_FORMAT cpu_to_le32(0xC000007B)
+#define STATUS_NO_TOKEN cpu_to_le32(0xC000007C)
+#define STATUS_BAD_INHERITANCE_ACL cpu_to_le32(0xC000007D)
+#define STATUS_RANGE_NOT_LOCKED cpu_to_le32(0xC000007E)
+#define STATUS_DISK_FULL cpu_to_le32(0xC000007F)
+#define STATUS_SERVER_DISABLED cpu_to_le32(0xC0000080)
+#define STATUS_SERVER_NOT_DISABLED cpu_to_le32(0xC0000081)
+#define STATUS_TOO_MANY_GUIDS_REQUESTED cpu_to_le32(0xC0000082)
+#define STATUS_GUIDS_EXHAUSTED cpu_to_le32(0xC0000083)
+#define STATUS_INVALID_ID_AUTHORITY cpu_to_le32(0xC0000084)
+#define STATUS_AGENTS_EXHAUSTED cpu_to_le32(0xC0000085)
+#define STATUS_INVALID_VOLUME_LABEL cpu_to_le32(0xC0000086)
+#define STATUS_SECTION_NOT_EXTENDED cpu_to_le32(0xC0000087)
+#define STATUS_NOT_MAPPED_DATA cpu_to_le32(0xC0000088)
+#define STATUS_RESOURCE_DATA_NOT_FOUND cpu_to_le32(0xC0000089)
+#define STATUS_RESOURCE_TYPE_NOT_FOUND cpu_to_le32(0xC000008A)
+#define STATUS_RESOURCE_NAME_NOT_FOUND cpu_to_le32(0xC000008B)
+#define STATUS_ARRAY_BOUNDS_EXCEEDED cpu_to_le32(0xC000008C)
+#define STATUS_FLOAT_DENORMAL_OPERAND cpu_to_le32(0xC000008D)
+#define STATUS_FLOAT_DIVIDE_BY_ZERO cpu_to_le32(0xC000008E)
+#define STATUS_FLOAT_INEXACT_RESULT cpu_to_le32(0xC000008F)
+#define STATUS_FLOAT_INVALID_OPERATION cpu_to_le32(0xC0000090)
+#define STATUS_FLOAT_OVERFLOW cpu_to_le32(0xC0000091)
+#define STATUS_FLOAT_STACK_CHECK cpu_to_le32(0xC0000092)
+#define STATUS_FLOAT_UNDERFLOW cpu_to_le32(0xC0000093)
+#define STATUS_INTEGER_DIVIDE_BY_ZERO cpu_to_le32(0xC0000094)
+#define STATUS_INTEGER_OVERFLOW cpu_to_le32(0xC0000095)
+#define STATUS_PRIVILEGED_INSTRUCTION cpu_to_le32(0xC0000096)
+#define STATUS_TOO_MANY_PAGING_FILES cpu_to_le32(0xC0000097)
+#define STATUS_FILE_INVALID cpu_to_le32(0xC0000098)
+#define STATUS_ALLOTTED_SPACE_EXCEEDED cpu_to_le32(0xC0000099)
+#define STATUS_INSUFFICIENT_RESOURCES cpu_to_le32(0xC000009A)
+#define STATUS_DFS_EXIT_PATH_FOUND cpu_to_le32(0xC000009B)
+#define STATUS_DEVICE_DATA_ERROR cpu_to_le32(0xC000009C)
+#define STATUS_DEVICE_NOT_CONNECTED cpu_to_le32(0xC000009D)
+#define STATUS_DEVICE_POWER_FAILURE cpu_to_le32(0xC000009E)
+#define STATUS_FREE_VM_NOT_AT_BASE cpu_to_le32(0xC000009F)
+#define STATUS_MEMORY_NOT_ALLOCATED cpu_to_le32(0xC00000A0)
+#define STATUS_WORKING_SET_QUOTA cpu_to_le32(0xC00000A1)
+#define STATUS_MEDIA_WRITE_PROTECTED cpu_to_le32(0xC00000A2)
+#define STATUS_DEVICE_NOT_READY cpu_to_le32(0xC00000A3)
+#define STATUS_INVALID_GROUP_ATTRIBUTES cpu_to_le32(0xC00000A4)
+#define STATUS_BAD_IMPERSONATION_LEVEL cpu_to_le32(0xC00000A5)
+#define STATUS_CANT_OPEN_ANONYMOUS cpu_to_le32(0xC00000A6)
+#define STATUS_BAD_VALIDATION_CLASS cpu_to_le32(0xC00000A7)
+#define STATUS_BAD_TOKEN_TYPE cpu_to_le32(0xC00000A8)
+#define STATUS_BAD_MASTER_BOOT_RECORD cpu_to_le32(0xC00000A9)
+#define STATUS_INSTRUCTION_MISALIGNMENT cpu_to_le32(0xC00000AA)
+#define STATUS_INSTANCE_NOT_AVAILABLE cpu_to_le32(0xC00000AB)
+#define STATUS_PIPE_NOT_AVAILABLE cpu_to_le32(0xC00000AC)
+#define STATUS_INVALID_PIPE_STATE cpu_to_le32(0xC00000AD)
+#define STATUS_PIPE_BUSY cpu_to_le32(0xC00000AE)
+#define STATUS_ILLEGAL_FUNCTION cpu_to_le32(0xC00000AF)
+#define STATUS_PIPE_DISCONNECTED cpu_to_le32(0xC00000B0)
+#define STATUS_PIPE_CLOSING cpu_to_le32(0xC00000B1)
+#define STATUS_PIPE_CONNECTED cpu_to_le32(0xC00000B2)
+#define STATUS_PIPE_LISTENING cpu_to_le32(0xC00000B3)
+#define STATUS_INVALID_READ_MODE cpu_to_le32(0xC00000B4)
+#define STATUS_IO_TIMEOUT cpu_to_le32(0xC00000B5)
+#define STATUS_FILE_FORCED_CLOSED cpu_to_le32(0xC00000B6)
+#define STATUS_PROFILING_NOT_STARTED cpu_to_le32(0xC00000B7)
+#define STATUS_PROFILING_NOT_STOPPED cpu_to_le32(0xC00000B8)
+#define STATUS_COULD_NOT_INTERPRET cpu_to_le32(0xC00000B9)
+#define STATUS_FILE_IS_A_DIRECTORY cpu_to_le32(0xC00000BA)
+#define STATUS_NOT_SUPPORTED cpu_to_le32(0xC00000BB)
+#define STATUS_REMOTE_NOT_LISTENING cpu_to_le32(0xC00000BC)
+#define STATUS_DUPLICATE_NAME cpu_to_le32(0xC00000BD)
+#define STATUS_BAD_NETWORK_PATH cpu_to_le32(0xC00000BE)
+#define STATUS_NETWORK_BUSY cpu_to_le32(0xC00000BF)
+#define STATUS_DEVICE_DOES_NOT_EXIST cpu_to_le32(0xC00000C0)
+#define STATUS_TOO_MANY_COMMANDS cpu_to_le32(0xC00000C1)
+#define STATUS_ADAPTER_HARDWARE_ERROR cpu_to_le32(0xC00000C2)
+#define STATUS_INVALID_NETWORK_RESPONSE cpu_to_le32(0xC00000C3)
+#define STATUS_UNEXPECTED_NETWORK_ERROR cpu_to_le32(0xC00000C4)
+#define STATUS_BAD_REMOTE_ADAPTER cpu_to_le32(0xC00000C5)
+#define STATUS_PRINT_QUEUE_FULL cpu_to_le32(0xC00000C6)
+#define STATUS_NO_SPOOL_SPACE cpu_to_le32(0xC00000C7)
+#define STATUS_PRINT_CANCELLED cpu_to_le32(0xC00000C8)
+#define STATUS_NETWORK_NAME_DELETED cpu_to_le32(0xC00000C9)
+#define STATUS_NETWORK_ACCESS_DENIED cpu_to_le32(0xC00000CA)
+#define STATUS_BAD_DEVICE_TYPE cpu_to_le32(0xC00000CB)
+#define STATUS_BAD_NETWORK_NAME cpu_to_le32(0xC00000CC)
+#define STATUS_TOO_MANY_NAMES cpu_to_le32(0xC00000CD)
+#define STATUS_TOO_MANY_SESSIONS cpu_to_le32(0xC00000CE)
+#define STATUS_SHARING_PAUSED cpu_to_le32(0xC00000CF)
+#define STATUS_REQUEST_NOT_ACCEPTED cpu_to_le32(0xC00000D0)
+#define STATUS_REDIRECTOR_PAUSED cpu_to_le32(0xC00000D1)
+#define STATUS_NET_WRITE_FAULT cpu_to_le32(0xC00000D2)
+#define STATUS_PROFILING_AT_LIMIT cpu_to_le32(0xC00000D3)
+#define STATUS_NOT_SAME_DEVICE cpu_to_le32(0xC00000D4)
+#define STATUS_FILE_RENAMED cpu_to_le32(0xC00000D5)
+#define STATUS_VIRTUAL_CIRCUIT_CLOSED cpu_to_le32(0xC00000D6)
+#define STATUS_NO_SECURITY_ON_OBJECT cpu_to_le32(0xC00000D7)
+#define STATUS_CANT_WAIT cpu_to_le32(0xC00000D8)
+#define STATUS_PIPE_EMPTY cpu_to_le32(0xC00000D9)
+#define STATUS_CANT_ACCESS_DOMAIN_INFO cpu_to_le32(0xC00000DA)
+#define STATUS_CANT_TERMINATE_SELF cpu_to_le32(0xC00000DB)
+#define STATUS_INVALID_SERVER_STATE cpu_to_le32(0xC00000DC)
+#define STATUS_INVALID_DOMAIN_STATE cpu_to_le32(0xC00000DD)
+#define STATUS_INVALID_DOMAIN_ROLE cpu_to_le32(0xC00000DE)
+#define STATUS_NO_SUCH_DOMAIN cpu_to_le32(0xC00000DF)
+#define STATUS_DOMAIN_EXISTS cpu_to_le32(0xC00000E0)
+#define STATUS_DOMAIN_LIMIT_EXCEEDED cpu_to_le32(0xC00000E1)
+#define STATUS_OPLOCK_NOT_GRANTED cpu_to_le32(0xC00000E2)
+#define STATUS_INVALID_OPLOCK_PROTOCOL cpu_to_le32(0xC00000E3)
+#define STATUS_INTERNAL_DB_CORRUPTION cpu_to_le32(0xC00000E4)
+#define STATUS_INTERNAL_ERROR cpu_to_le32(0xC00000E5)
+#define STATUS_GENERIC_NOT_MAPPED cpu_to_le32(0xC00000E6)
+#define STATUS_BAD_DESCRIPTOR_FORMAT cpu_to_le32(0xC00000E7)
+#define STATUS_INVALID_USER_BUFFER cpu_to_le32(0xC00000E8)
+#define STATUS_UNEXPECTED_IO_ERROR cpu_to_le32(0xC00000E9)
+#define STATUS_UNEXPECTED_MM_CREATE_ERR cpu_to_le32(0xC00000EA)
+#define STATUS_UNEXPECTED_MM_MAP_ERROR cpu_to_le32(0xC00000EB)
+#define STATUS_UNEXPECTED_MM_EXTEND_ERR cpu_to_le32(0xC00000EC)
+#define STATUS_NOT_LOGON_PROCESS cpu_to_le32(0xC00000ED)
+#define STATUS_LOGON_SESSION_EXISTS cpu_to_le32(0xC00000EE)
+#define STATUS_INVALID_PARAMETER_1 cpu_to_le32(0xC00000EF)
+#define STATUS_INVALID_PARAMETER_2 cpu_to_le32(0xC00000F0)
+#define STATUS_INVALID_PARAMETER_3 cpu_to_le32(0xC00000F1)
+#define STATUS_INVALID_PARAMETER_4 cpu_to_le32(0xC00000F2)
+#define STATUS_INVALID_PARAMETER_5 cpu_to_le32(0xC00000F3)
+#define STATUS_INVALID_PARAMETER_6 cpu_to_le32(0xC00000F4)
+#define STATUS_INVALID_PARAMETER_7 cpu_to_le32(0xC00000F5)
+#define STATUS_INVALID_PARAMETER_8 cpu_to_le32(0xC00000F6)
+#define STATUS_INVALID_PARAMETER_9 cpu_to_le32(0xC00000F7)
+#define STATUS_INVALID_PARAMETER_10 cpu_to_le32(0xC00000F8)
+#define STATUS_INVALID_PARAMETER_11 cpu_to_le32(0xC00000F9)
+#define STATUS_INVALID_PARAMETER_12 cpu_to_le32(0xC00000FA)
+#define STATUS_REDIRECTOR_NOT_STARTED cpu_to_le32(0xC00000FB)
+#define STATUS_REDIRECTOR_STARTED cpu_to_le32(0xC00000FC)
+#define STATUS_STACK_OVERFLOW cpu_to_le32(0xC00000FD)
+#define STATUS_NO_SUCH_PACKAGE cpu_to_le32(0xC00000FE)
+#define STATUS_BAD_FUNCTION_TABLE cpu_to_le32(0xC00000FF)
+#define STATUS_VARIABLE_NOT_FOUND cpu_to_le32(0xC0000100)
+#define STATUS_DIRECTORY_NOT_EMPTY cpu_to_le32(0xC0000101)
+#define STATUS_FILE_CORRUPT_ERROR cpu_to_le32(0xC0000102)
+#define STATUS_NOT_A_DIRECTORY cpu_to_le32(0xC0000103)
+#define STATUS_BAD_LOGON_SESSION_STATE cpu_to_le32(0xC0000104)
+#define STATUS_LOGON_SESSION_COLLISION cpu_to_le32(0xC0000105)
+#define STATUS_NAME_TOO_LONG cpu_to_le32(0xC0000106)
+#define STATUS_FILES_OPEN cpu_to_le32(0xC0000107)
+#define STATUS_CONNECTION_IN_USE cpu_to_le32(0xC0000108)
+#define STATUS_MESSAGE_NOT_FOUND cpu_to_le32(0xC0000109)
+#define STATUS_PROCESS_IS_TERMINATING cpu_to_le32(0xC000010A)
+#define STATUS_INVALID_LOGON_TYPE cpu_to_le32(0xC000010B)
+#define STATUS_NO_GUID_TRANSLATION cpu_to_le32(0xC000010C)
+#define STATUS_CANNOT_IMPERSONATE cpu_to_le32(0xC000010D)
+#define STATUS_IMAGE_ALREADY_LOADED cpu_to_le32(0xC000010E)
+#define STATUS_ABIOS_NOT_PRESENT cpu_to_le32(0xC000010F)
+#define STATUS_ABIOS_LID_NOT_EXIST cpu_to_le32(0xC0000110)
+#define STATUS_ABIOS_LID_ALREADY_OWNED cpu_to_le32(0xC0000111)
+#define STATUS_ABIOS_NOT_LID_OWNER cpu_to_le32(0xC0000112)
+#define STATUS_ABIOS_INVALID_COMMAND cpu_to_le32(0xC0000113)
+#define STATUS_ABIOS_INVALID_LID cpu_to_le32(0xC0000114)
+#define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE cpu_to_le32(0xC0000115)
+#define STATUS_ABIOS_INVALID_SELECTOR cpu_to_le32(0xC0000116)
+#define STATUS_NO_LDT cpu_to_le32(0xC0000117)
+#define STATUS_INVALID_LDT_SIZE cpu_to_le32(0xC0000118)
+#define STATUS_INVALID_LDT_OFFSET cpu_to_le32(0xC0000119)
+#define STATUS_INVALID_LDT_DESCRIPTOR cpu_to_le32(0xC000011A)
+#define STATUS_INVALID_IMAGE_NE_FORMAT cpu_to_le32(0xC000011B)
+#define STATUS_RXACT_INVALID_STATE cpu_to_le32(0xC000011C)
+#define STATUS_RXACT_COMMIT_FAILURE cpu_to_le32(0xC000011D)
+#define STATUS_MAPPED_FILE_SIZE_ZERO cpu_to_le32(0xC000011E)
+#define STATUS_TOO_MANY_OPENED_FILES cpu_to_le32(0xC000011F)
+#define STATUS_CANCELLED cpu_to_le32(0xC0000120)
+#define STATUS_CANNOT_DELETE cpu_to_le32(0xC0000121)
+#define STATUS_INVALID_COMPUTER_NAME cpu_to_le32(0xC0000122)
+#define STATUS_FILE_DELETED cpu_to_le32(0xC0000123)
+#define STATUS_SPECIAL_ACCOUNT cpu_to_le32(0xC0000124)
+#define STATUS_SPECIAL_GROUP cpu_to_le32(0xC0000125)
+#define STATUS_SPECIAL_USER cpu_to_le32(0xC0000126)
+#define STATUS_MEMBERS_PRIMARY_GROUP cpu_to_le32(0xC0000127)
+#define STATUS_FILE_CLOSED cpu_to_le32(0xC0000128)
+#define STATUS_TOO_MANY_THREADS cpu_to_le32(0xC0000129)
+#define STATUS_THREAD_NOT_IN_PROCESS cpu_to_le32(0xC000012A)
+#define STATUS_TOKEN_ALREADY_IN_USE cpu_to_le32(0xC000012B)
+#define STATUS_PAGEFILE_QUOTA_EXCEEDED cpu_to_le32(0xC000012C)
+#define STATUS_COMMITMENT_LIMIT cpu_to_le32(0xC000012D)
+#define STATUS_INVALID_IMAGE_LE_FORMAT cpu_to_le32(0xC000012E)
+#define STATUS_INVALID_IMAGE_NOT_MZ cpu_to_le32(0xC000012F)
+#define STATUS_INVALID_IMAGE_PROTECT cpu_to_le32(0xC0000130)
+#define STATUS_INVALID_IMAGE_WIN_16 cpu_to_le32(0xC0000131)
+#define STATUS_LOGON_SERVER_CONFLICT cpu_to_le32(0xC0000132)
+#define STATUS_TIME_DIFFERENCE_AT_DC cpu_to_le32(0xC0000133)
+#define STATUS_SYNCHRONIZATION_REQUIRED cpu_to_le32(0xC0000134)
+#define STATUS_DLL_NOT_FOUND cpu_to_le32(0xC0000135)
+#define STATUS_OPEN_FAILED cpu_to_le32(0xC0000136)
+#define STATUS_IO_PRIVILEGE_FAILED cpu_to_le32(0xC0000137)
+#define STATUS_ORDINAL_NOT_FOUND cpu_to_le32(0xC0000138)
+#define STATUS_ENTRYPOINT_NOT_FOUND cpu_to_le32(0xC0000139)
+#define STATUS_CONTROL_C_EXIT cpu_to_le32(0xC000013A)
+#define STATUS_LOCAL_DISCONNECT cpu_to_le32(0xC000013B)
+#define STATUS_REMOTE_DISCONNECT cpu_to_le32(0xC000013C)
+#define STATUS_REMOTE_RESOURCES cpu_to_le32(0xC000013D)
+#define STATUS_LINK_FAILED cpu_to_le32(0xC000013E)
+#define STATUS_LINK_TIMEOUT cpu_to_le32(0xC000013F)
+#define STATUS_INVALID_CONNECTION cpu_to_le32(0xC0000140)
+#define STATUS_INVALID_ADDRESS cpu_to_le32(0xC0000141)
+#define STATUS_DLL_INIT_FAILED cpu_to_le32(0xC0000142)
+#define STATUS_MISSING_SYSTEMFILE cpu_to_le32(0xC0000143)
+#define STATUS_UNHANDLED_EXCEPTION cpu_to_le32(0xC0000144)
+#define STATUS_APP_INIT_FAILURE cpu_to_le32(0xC0000145)
+#define STATUS_PAGEFILE_CREATE_FAILED cpu_to_le32(0xC0000146)
+#define STATUS_NO_PAGEFILE cpu_to_le32(0xC0000147)
+#define STATUS_INVALID_LEVEL cpu_to_le32(0xC0000148)
+#define STATUS_WRONG_PASSWORD_CORE cpu_to_le32(0xC0000149)
+#define STATUS_ILLEGAL_FLOAT_CONTEXT cpu_to_le32(0xC000014A)
+#define STATUS_PIPE_BROKEN cpu_to_le32(0xC000014B)
+#define STATUS_REGISTRY_CORRUPT cpu_to_le32(0xC000014C)
+#define STATUS_REGISTRY_IO_FAILED cpu_to_le32(0xC000014D)
+#define STATUS_NO_EVENT_PAIR cpu_to_le32(0xC000014E)
+#define STATUS_UNRECOGNIZED_VOLUME cpu_to_le32(0xC000014F)
+#define STATUS_SERIAL_NO_DEVICE_INITED cpu_to_le32(0xC0000150)
+#define STATUS_NO_SUCH_ALIAS cpu_to_le32(0xC0000151)
+#define STATUS_MEMBER_NOT_IN_ALIAS cpu_to_le32(0xC0000152)
+#define STATUS_MEMBER_IN_ALIAS cpu_to_le32(0xC0000153)
+#define STATUS_ALIAS_EXISTS cpu_to_le32(0xC0000154)
+#define STATUS_LOGON_NOT_GRANTED cpu_to_le32(0xC0000155)
+#define STATUS_TOO_MANY_SECRETS cpu_to_le32(0xC0000156)
+#define STATUS_SECRET_TOO_LONG cpu_to_le32(0xC0000157)
+#define STATUS_INTERNAL_DB_ERROR cpu_to_le32(0xC0000158)
+#define STATUS_FULLSCREEN_MODE cpu_to_le32(0xC0000159)
+#define STATUS_TOO_MANY_CONTEXT_IDS cpu_to_le32(0xC000015A)
+#define STATUS_LOGON_TYPE_NOT_GRANTED cpu_to_le32(0xC000015B)
+#define STATUS_NOT_REGISTRY_FILE cpu_to_le32(0xC000015C)
+#define STATUS_NT_CROSS_ENCRYPTION_REQUIRED cpu_to_le32(0xC000015D)
+#define STATUS_DOMAIN_CTRLR_CONFIG_ERROR cpu_to_le32(0xC000015E)
+#define STATUS_FT_MISSING_MEMBER cpu_to_le32(0xC000015F)
+#define STATUS_ILL_FORMED_SERVICE_ENTRY cpu_to_le32(0xC0000160)
+#define STATUS_ILLEGAL_CHARACTER cpu_to_le32(0xC0000161)
+#define STATUS_UNMAPPABLE_CHARACTER cpu_to_le32(0xC0000162)
+#define STATUS_UNDEFINED_CHARACTER cpu_to_le32(0xC0000163)
+#define STATUS_FLOPPY_VOLUME cpu_to_le32(0xC0000164)
+#define STATUS_FLOPPY_ID_MARK_NOT_FOUND cpu_to_le32(0xC0000165)
+#define STATUS_FLOPPY_WRONG_CYLINDER cpu_to_le32(0xC0000166)
+#define STATUS_FLOPPY_UNKNOWN_ERROR cpu_to_le32(0xC0000167)
+#define STATUS_FLOPPY_BAD_REGISTERS cpu_to_le32(0xC0000168)
+#define STATUS_DISK_RECALIBRATE_FAILED cpu_to_le32(0xC0000169)
+#define STATUS_DISK_OPERATION_FAILED cpu_to_le32(0xC000016A)
+#define STATUS_DISK_RESET_FAILED cpu_to_le32(0xC000016B)
+#define STATUS_SHARED_IRQ_BUSY cpu_to_le32(0xC000016C)
+#define STATUS_FT_ORPHANING cpu_to_le32(0xC000016D)
+#define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT cpu_to_le32(0xC000016E)
+#define STATUS_PARTITION_FAILURE cpu_to_le32(0xC0000172)
+#define STATUS_INVALID_BLOCK_LENGTH cpu_to_le32(0xC0000173)
+#define STATUS_DEVICE_NOT_PARTITIONED cpu_to_le32(0xC0000174)
+#define STATUS_UNABLE_TO_LOCK_MEDIA cpu_to_le32(0xC0000175)
+#define STATUS_UNABLE_TO_UNLOAD_MEDIA cpu_to_le32(0xC0000176)
+#define STATUS_EOM_OVERFLOW cpu_to_le32(0xC0000177)
+#define STATUS_NO_MEDIA cpu_to_le32(0xC0000178)
+#define STATUS_NO_SUCH_MEMBER cpu_to_le32(0xC000017A)
+#define STATUS_INVALID_MEMBER cpu_to_le32(0xC000017B)
+#define STATUS_KEY_DELETED cpu_to_le32(0xC000017C)
+#define STATUS_NO_LOG_SPACE cpu_to_le32(0xC000017D)
+#define STATUS_TOO_MANY_SIDS cpu_to_le32(0xC000017E)
+#define STATUS_LM_CROSS_ENCRYPTION_REQUIRED cpu_to_le32(0xC000017F)
+#define STATUS_KEY_HAS_CHILDREN cpu_to_le32(0xC0000180)
+#define STATUS_CHILD_MUST_BE_VOLATILE cpu_to_le32(0xC0000181)
+#define STATUS_DEVICE_CONFIGURATION_ERROR cpu_to_le32(0xC0000182)
+#define STATUS_DRIVER_INTERNAL_ERROR cpu_to_le32(0xC0000183)
+#define STATUS_INVALID_DEVICE_STATE cpu_to_le32(0xC0000184)
+#define STATUS_IO_DEVICE_ERROR cpu_to_le32(0xC0000185)
+#define STATUS_DEVICE_PROTOCOL_ERROR cpu_to_le32(0xC0000186)
+#define STATUS_BACKUP_CONTROLLER cpu_to_le32(0xC0000187)
+#define STATUS_LOG_FILE_FULL cpu_to_le32(0xC0000188)
+#define STATUS_TOO_LATE cpu_to_le32(0xC0000189)
+#define STATUS_NO_TRUST_LSA_SECRET cpu_to_le32(0xC000018A)
+#define STATUS_NO_TRUST_SAM_ACCOUNT cpu_to_le32(0xC000018B)
+#define STATUS_TRUSTED_DOMAIN_FAILURE cpu_to_le32(0xC000018C)
+#define STATUS_TRUSTED_RELATIONSHIP_FAILURE cpu_to_le32(0xC000018D)
+#define STATUS_EVENTLOG_FILE_CORRUPT cpu_to_le32(0xC000018E)
+#define STATUS_EVENTLOG_CANT_START cpu_to_le32(0xC000018F)
+#define STATUS_TRUST_FAILURE cpu_to_le32(0xC0000190)
+#define STATUS_MUTANT_LIMIT_EXCEEDED cpu_to_le32(0xC0000191)
+#define STATUS_NETLOGON_NOT_STARTED cpu_to_le32(0xC0000192)
+#define STATUS_ACCOUNT_EXPIRED cpu_to_le32(0xC0000193)
+#define STATUS_POSSIBLE_DEADLOCK cpu_to_le32(0xC0000194)
+#define STATUS_NETWORK_CREDENTIAL_CONFLICT cpu_to_le32(0xC0000195)
+#define STATUS_REMOTE_SESSION_LIMIT cpu_to_le32(0xC0000196)
+#define STATUS_EVENTLOG_FILE_CHANGED cpu_to_le32(0xC0000197)
+#define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT cpu_to_le32(0xC0000198)
+#define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT cpu_to_le32(0xC0000199)
+#define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT cpu_to_le32(0xC000019A)
+#define STATUS_DOMAIN_TRUST_INCONSISTENT cpu_to_le32(0xC000019B)
+#define STATUS_FS_DRIVER_REQUIRED cpu_to_le32(0xC000019C)
+#define STATUS_IMAGE_ALREADY_LOADED_AS_DLL cpu_to_le32(0xC000019D)
+#define STATUS_NETWORK_OPEN_RESTRICTION cpu_to_le32(0xC0000201)
+#define STATUS_NO_USER_SESSION_KEY cpu_to_le32(0xC0000202)
+#define STATUS_USER_SESSION_DELETED cpu_to_le32(0xC0000203)
+#define STATUS_RESOURCE_LANG_NOT_FOUND cpu_to_le32(0xC0000204)
+#define STATUS_INSUFF_SERVER_RESOURCES cpu_to_le32(0xC0000205)
+#define STATUS_INVALID_BUFFER_SIZE cpu_to_le32(0xC0000206)
+#define STATUS_INVALID_ADDRESS_COMPONENT cpu_to_le32(0xC0000207)
+#define STATUS_INVALID_ADDRESS_WILDCARD cpu_to_le32(0xC0000208)
+#define STATUS_TOO_MANY_ADDRESSES cpu_to_le32(0xC0000209)
+#define STATUS_ADDRESS_ALREADY_EXISTS cpu_to_le32(0xC000020A)
+#define STATUS_ADDRESS_CLOSED cpu_to_le32(0xC000020B)
+#define STATUS_CONNECTION_DISCONNECTED cpu_to_le32(0xC000020C)
+#define STATUS_CONNECTION_RESET cpu_to_le32(0xC000020D)
+#define STATUS_TOO_MANY_NODES cpu_to_le32(0xC000020E)
+#define STATUS_TRANSACTION_ABORTED cpu_to_le32(0xC000020F)
+#define STATUS_TRANSACTION_TIMED_OUT cpu_to_le32(0xC0000210)
+#define STATUS_TRANSACTION_NO_RELEASE cpu_to_le32(0xC0000211)
+#define STATUS_TRANSACTION_NO_MATCH cpu_to_le32(0xC0000212)
+#define STATUS_TRANSACTION_RESPONDED cpu_to_le32(0xC0000213)
+#define STATUS_TRANSACTION_INVALID_ID cpu_to_le32(0xC0000214)
+#define STATUS_TRANSACTION_INVALID_TYPE cpu_to_le32(0xC0000215)
+#define STATUS_NOT_SERVER_SESSION cpu_to_le32(0xC0000216)
+#define STATUS_NOT_CLIENT_SESSION cpu_to_le32(0xC0000217)
+#define STATUS_CANNOT_LOAD_REGISTRY_FILE cpu_to_le32(0xC0000218)
+#define STATUS_DEBUG_ATTACH_FAILED cpu_to_le32(0xC0000219)
+#define STATUS_SYSTEM_PROCESS_TERMINATED cpu_to_le32(0xC000021A)
+#define STATUS_DATA_NOT_ACCEPTED cpu_to_le32(0xC000021B)
+#define STATUS_NO_BROWSER_SERVERS_FOUND cpu_to_le32(0xC000021C)
+#define STATUS_VDM_HARD_ERROR cpu_to_le32(0xC000021D)
+#define STATUS_DRIVER_CANCEL_TIMEOUT cpu_to_le32(0xC000021E)
+#define STATUS_REPLY_MESSAGE_MISMATCH cpu_to_le32(0xC000021F)
+#define STATUS_MAPPED_ALIGNMENT cpu_to_le32(0xC0000220)
+#define STATUS_IMAGE_CHECKSUM_MISMATCH cpu_to_le32(0xC0000221)
+#define STATUS_LOST_WRITEBEHIND_DATA cpu_to_le32(0xC0000222)
+#define STATUS_CLIENT_SERVER_PARAMETERS_INVALID cpu_to_le32(0xC0000223)
+#define STATUS_PASSWORD_MUST_CHANGE cpu_to_le32(0xC0000224)
+#define STATUS_NOT_FOUND cpu_to_le32(0xC0000225)
+#define STATUS_NOT_TINY_STREAM cpu_to_le32(0xC0000226)
+#define STATUS_RECOVERY_FAILURE cpu_to_le32(0xC0000227)
+#define STATUS_STACK_OVERFLOW_READ cpu_to_le32(0xC0000228)
+#define STATUS_FAIL_CHECK cpu_to_le32(0xC0000229)
+#define STATUS_DUPLICATE_OBJECTID cpu_to_le32(0xC000022A)
+#define STATUS_OBJECTID_EXISTS cpu_to_le32(0xC000022B)
+#define STATUS_CONVERT_TO_LARGE cpu_to_le32(0xC000022C)
+#define STATUS_RETRY cpu_to_le32(0xC000022D)
+#define STATUS_FOUND_OUT_OF_SCOPE cpu_to_le32(0xC000022E)
+#define STATUS_ALLOCATE_BUCKET cpu_to_le32(0xC000022F)
+#define STATUS_PROPSET_NOT_FOUND cpu_to_le32(0xC0000230)
+#define STATUS_MARSHALL_OVERFLOW cpu_to_le32(0xC0000231)
+#define STATUS_INVALID_VARIANT cpu_to_le32(0xC0000232)
+#define STATUS_DOMAIN_CONTROLLER_NOT_FOUND cpu_to_le32(0xC0000233)
+#define STATUS_ACCOUNT_LOCKED_OUT cpu_to_le32(0xC0000234)
+#define STATUS_HANDLE_NOT_CLOSABLE cpu_to_le32(0xC0000235)
+#define STATUS_CONNECTION_REFUSED cpu_to_le32(0xC0000236)
+#define STATUS_GRACEFUL_DISCONNECT cpu_to_le32(0xC0000237)
+#define STATUS_ADDRESS_ALREADY_ASSOCIATED cpu_to_le32(0xC0000238)
+#define STATUS_ADDRESS_NOT_ASSOCIATED cpu_to_le32(0xC0000239)
+#define STATUS_CONNECTION_INVALID cpu_to_le32(0xC000023A)
+#define STATUS_CONNECTION_ACTIVE cpu_to_le32(0xC000023B)
+#define STATUS_NETWORK_UNREACHABLE cpu_to_le32(0xC000023C)
+#define STATUS_HOST_UNREACHABLE cpu_to_le32(0xC000023D)
+#define STATUS_PROTOCOL_UNREACHABLE cpu_to_le32(0xC000023E)
+#define STATUS_PORT_UNREACHABLE cpu_to_le32(0xC000023F)
+#define STATUS_REQUEST_ABORTED cpu_to_le32(0xC0000240)
+#define STATUS_CONNECTION_ABORTED cpu_to_le32(0xC0000241)
+#define STATUS_BAD_COMPRESSION_BUFFER cpu_to_le32(0xC0000242)
+#define STATUS_USER_MAPPED_FILE cpu_to_le32(0xC0000243)
+#define STATUS_AUDIT_FAILED cpu_to_le32(0xC0000244)
+#define STATUS_TIMER_RESOLUTION_NOT_SET cpu_to_le32(0xC0000245)
+#define STATUS_CONNECTION_COUNT_LIMIT cpu_to_le32(0xC0000246)
+#define STATUS_LOGIN_TIME_RESTRICTION cpu_to_le32(0xC0000247)
+#define STATUS_LOGIN_WKSTA_RESTRICTION cpu_to_le32(0xC0000248)
+#define STATUS_IMAGE_MP_UP_MISMATCH cpu_to_le32(0xC0000249)
+#define STATUS_INSUFFICIENT_LOGON_INFO cpu_to_le32(0xC0000250)
+#define STATUS_BAD_DLL_ENTRYPOINT cpu_to_le32(0xC0000251)
+#define STATUS_BAD_SERVICE_ENTRYPOINT cpu_to_le32(0xC0000252)
+#define STATUS_LPC_REPLY_LOST cpu_to_le32(0xC0000253)
+#define STATUS_IP_ADDRESS_CONFLICT1 cpu_to_le32(0xC0000254)
+#define STATUS_IP_ADDRESS_CONFLICT2 cpu_to_le32(0xC0000255)
+#define STATUS_REGISTRY_QUOTA_LIMIT cpu_to_le32(0xC0000256)
+#define STATUS_PATH_NOT_COVERED cpu_to_le32(0xC0000257)
+#define STATUS_NO_CALLBACK_ACTIVE cpu_to_le32(0xC0000258)
+#define STATUS_LICENSE_QUOTA_EXCEEDED cpu_to_le32(0xC0000259)
+#define STATUS_PWD_TOO_SHORT cpu_to_le32(0xC000025A)
+#define STATUS_PWD_TOO_RECENT cpu_to_le32(0xC000025B)
+#define STATUS_PWD_HISTORY_CONFLICT cpu_to_le32(0xC000025C)
+#define STATUS_PLUGPLAY_NO_DEVICE cpu_to_le32(0xC000025E)
+#define STATUS_UNSUPPORTED_COMPRESSION cpu_to_le32(0xC000025F)
+#define STATUS_INVALID_HW_PROFILE cpu_to_le32(0xC0000260)
+#define STATUS_INVALID_PLUGPLAY_DEVICE_PATH cpu_to_le32(0xC0000261)
+#define STATUS_DRIVER_ORDINAL_NOT_FOUND cpu_to_le32(0xC0000262)
+#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND cpu_to_le32(0xC0000263)
+#define STATUS_RESOURCE_NOT_OWNED cpu_to_le32(0xC0000264)
+#define STATUS_TOO_MANY_LINKS cpu_to_le32(0xC0000265)
+#define STATUS_QUOTA_LIST_INCONSISTENT cpu_to_le32(0xC0000266)
+#define STATUS_FILE_IS_OFFLINE cpu_to_le32(0xC0000267)
+#define STATUS_EVALUATION_EXPIRATION cpu_to_le32(0xC0000268)
+#define STATUS_ILLEGAL_DLL_RELOCATION cpu_to_le32(0xC0000269)
+#define STATUS_LICENSE_VIOLATION cpu_to_le32(0xC000026A)
+#define STATUS_DLL_INIT_FAILED_LOGOFF cpu_to_le32(0xC000026B)
+#define STATUS_DRIVER_UNABLE_TO_LOAD cpu_to_le32(0xC000026C)
+#define STATUS_DFS_UNAVAILABLE cpu_to_le32(0xC000026D)
+#define STATUS_VOLUME_DISMOUNTED cpu_to_le32(0xC000026E)
+#define STATUS_WX86_INTERNAL_ERROR cpu_to_le32(0xC000026F)
+#define STATUS_WX86_FLOAT_STACK_CHECK cpu_to_le32(0xC0000270)
+#define STATUS_VALIDATE_CONTINUE cpu_to_le32(0xC0000271)
+#define STATUS_NO_MATCH cpu_to_le32(0xC0000272)
+#define STATUS_NO_MORE_MATCHES cpu_to_le32(0xC0000273)
+#define STATUS_NOT_A_REPARSE_POINT cpu_to_le32(0xC0000275)
+#define STATUS_IO_REPARSE_TAG_INVALID cpu_to_le32(0xC0000276)
+#define STATUS_IO_REPARSE_TAG_MISMATCH cpu_to_le32(0xC0000277)
+#define STATUS_IO_REPARSE_DATA_INVALID cpu_to_le32(0xC0000278)
+#define STATUS_IO_REPARSE_TAG_NOT_HANDLED cpu_to_le32(0xC0000279)
+#define STATUS_REPARSE_POINT_NOT_RESOLVED cpu_to_le32(0xC0000280)
+#define STATUS_DIRECTORY_IS_A_REPARSE_POINT cpu_to_le32(0xC0000281)
+#define STATUS_RANGE_LIST_CONFLICT cpu_to_le32(0xC0000282)
+#define STATUS_SOURCE_ELEMENT_EMPTY cpu_to_le32(0xC0000283)
+#define STATUS_DESTINATION_ELEMENT_FULL cpu_to_le32(0xC0000284)
+#define STATUS_ILLEGAL_ELEMENT_ADDRESS cpu_to_le32(0xC0000285)
+#define STATUS_MAGAZINE_NOT_PRESENT cpu_to_le32(0xC0000286)
+#define STATUS_REINITIALIZATION_NEEDED cpu_to_le32(0xC0000287)
+#define STATUS_ENCRYPTION_FAILED cpu_to_le32(0xC000028A)
+#define STATUS_DECRYPTION_FAILED cpu_to_le32(0xC000028B)
+#define STATUS_RANGE_NOT_FOUND cpu_to_le32(0xC000028C)
+#define STATUS_NO_RECOVERY_POLICY cpu_to_le32(0xC000028D)
+#define STATUS_NO_EFS cpu_to_le32(0xC000028E)
+#define STATUS_WRONG_EFS cpu_to_le32(0xC000028F)
+#define STATUS_NO_USER_KEYS cpu_to_le32(0xC0000290)
+#define STATUS_FILE_NOT_ENCRYPTED cpu_to_le32(0xC0000291)
+#define STATUS_NOT_EXPORT_FORMAT cpu_to_le32(0xC0000292)
+#define STATUS_FILE_ENCRYPTED cpu_to_le32(0xC0000293)
+#define STATUS_WMI_GUID_NOT_FOUND cpu_to_le32(0xC0000295)
+#define STATUS_WMI_INSTANCE_NOT_FOUND cpu_to_le32(0xC0000296)
+#define STATUS_WMI_ITEMID_NOT_FOUND cpu_to_le32(0xC0000297)
+#define STATUS_WMI_TRY_AGAIN cpu_to_le32(0xC0000298)
+#define STATUS_SHARED_POLICY cpu_to_le32(0xC0000299)
+#define STATUS_POLICY_OBJECT_NOT_FOUND cpu_to_le32(0xC000029A)
+#define STATUS_POLICY_ONLY_IN_DS cpu_to_le32(0xC000029B)
+#define STATUS_VOLUME_NOT_UPGRADED cpu_to_le32(0xC000029C)
+#define STATUS_REMOTE_STORAGE_NOT_ACTIVE cpu_to_le32(0xC000029D)
+#define STATUS_REMOTE_STORAGE_MEDIA_ERROR cpu_to_le32(0xC000029E)
+#define STATUS_NO_TRACKING_SERVICE cpu_to_le32(0xC000029F)
+#define STATUS_SERVER_SID_MISMATCH cpu_to_le32(0xC00002A0)
+#define STATUS_DS_NO_ATTRIBUTE_OR_VALUE cpu_to_le32(0xC00002A1)
+#define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX cpu_to_le32(0xC00002A2)
+#define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED cpu_to_le32(0xC00002A3)
+#define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS cpu_to_le32(0xC00002A4)
+#define STATUS_DS_BUSY cpu_to_le32(0xC00002A5)
+#define STATUS_DS_UNAVAILABLE cpu_to_le32(0xC00002A6)
+#define STATUS_DS_NO_RIDS_ALLOCATED cpu_to_le32(0xC00002A7)
+#define STATUS_DS_NO_MORE_RIDS cpu_to_le32(0xC00002A8)
+#define STATUS_DS_INCORRECT_ROLE_OWNER cpu_to_le32(0xC00002A9)
+#define STATUS_DS_RIDMGR_INIT_ERROR cpu_to_le32(0xC00002AA)
+#define STATUS_DS_OBJ_CLASS_VIOLATION cpu_to_le32(0xC00002AB)
+#define STATUS_DS_CANT_ON_NON_LEAF cpu_to_le32(0xC00002AC)
+#define STATUS_DS_CANT_ON_RDN cpu_to_le32(0xC00002AD)
+#define STATUS_DS_CANT_MOD_OBJ_CLASS cpu_to_le32(0xC00002AE)
+#define STATUS_DS_CROSS_DOM_MOVE_FAILED cpu_to_le32(0xC00002AF)
+#define STATUS_DS_GC_NOT_AVAILABLE cpu_to_le32(0xC00002B0)
+#define STATUS_DIRECTORY_SERVICE_REQUIRED cpu_to_le32(0xC00002B1)
+#define STATUS_REPARSE_ATTRIBUTE_CONFLICT cpu_to_le32(0xC00002B2)
+#define STATUS_CANT_ENABLE_DENY_ONLY cpu_to_le32(0xC00002B3)
+#define STATUS_FLOAT_MULTIPLE_FAULTS cpu_to_le32(0xC00002B4)
+#define STATUS_FLOAT_MULTIPLE_TRAPS cpu_to_le32(0xC00002B5)
+#define STATUS_DEVICE_REMOVED cpu_to_le32(0xC00002B6)
+#define STATUS_JOURNAL_DELETE_IN_PROGRESS cpu_to_le32(0xC00002B7)
+#define STATUS_JOURNAL_NOT_ACTIVE cpu_to_le32(0xC00002B8)
+#define STATUS_NOINTERFACE cpu_to_le32(0xC00002B9)
+#define STATUS_DS_ADMIN_LIMIT_EXCEEDED cpu_to_le32(0xC00002C1)
+#define STATUS_DRIVER_FAILED_SLEEP cpu_to_le32(0xC00002C2)
+#define STATUS_MUTUAL_AUTHENTICATION_FAILED cpu_to_le32(0xC00002C3)
+#define STATUS_CORRUPT_SYSTEM_FILE cpu_to_le32(0xC00002C4)
+#define STATUS_DATATYPE_MISALIGNMENT_ERROR cpu_to_le32(0xC00002C5)
+#define STATUS_WMI_READ_ONLY cpu_to_le32(0xC00002C6)
+#define STATUS_WMI_SET_FAILURE cpu_to_le32(0xC00002C7)
+#define STATUS_COMMITMENT_MINIMUM cpu_to_le32(0xC00002C8)
+#define STATUS_REG_NAT_CONSUMPTION cpu_to_le32(0xC00002C9)
+#define STATUS_TRANSPORT_FULL cpu_to_le32(0xC00002CA)
+#define STATUS_DS_SAM_INIT_FAILURE cpu_to_le32(0xC00002CB)
+#define STATUS_ONLY_IF_CONNECTED cpu_to_le32(0xC00002CC)
+#define STATUS_DS_SENSITIVE_GROUP_VIOLATION cpu_to_le32(0xC00002CD)
+#define STATUS_PNP_RESTART_ENUMERATION cpu_to_le32(0xC00002CE)
+#define STATUS_JOURNAL_ENTRY_DELETED cpu_to_le32(0xC00002CF)
+#define STATUS_DS_CANT_MOD_PRIMARYGROUPID cpu_to_le32(0xC00002D0)
+#define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE cpu_to_le32(0xC00002D1)
+#define STATUS_PNP_REBOOT_REQUIRED cpu_to_le32(0xC00002D2)
+#define STATUS_POWER_STATE_INVALID cpu_to_le32(0xC00002D3)
+#define STATUS_DS_INVALID_GROUP_TYPE cpu_to_le32(0xC00002D4)
+#define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN cpu_to_le32(0xC00002D5)
+#define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN cpu_to_le32(0xC00002D6)
+#define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER cpu_to_le32(0xC00002D7)
+#define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER cpu_to_le32(0xC00002D8)
+#define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER cpu_to_le32(0xC00002D9)
+#define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER cpu_to_le32(0xC00002DA)
+#define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER cpu_to_le32(0xC00002DB)
+#define STATUS_DS_HAVE_PRIMARY_MEMBERS cpu_to_le32(0xC00002DC)
+#define STATUS_WMI_NOT_SUPPORTED cpu_to_le32(0xC00002DD)
+#define STATUS_INSUFFICIENT_POWER cpu_to_le32(0xC00002DE)
+#define STATUS_SAM_NEED_BOOTKEY_PASSWORD cpu_to_le32(0xC00002DF)
+#define STATUS_SAM_NEED_BOOTKEY_FLOPPY cpu_to_le32(0xC00002E0)
+#define STATUS_DS_CANT_START cpu_to_le32(0xC00002E1)
+#define STATUS_DS_INIT_FAILURE cpu_to_le32(0xC00002E2)
+#define STATUS_SAM_INIT_FAILURE cpu_to_le32(0xC00002E3)
+#define STATUS_DS_GC_REQUIRED cpu_to_le32(0xC00002E4)
+#define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY cpu_to_le32(0xC00002E5)
+#define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS cpu_to_le32(0xC00002E6)
+#define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED cpu_to_le32(0xC00002E7)
+#define STATUS_MULTIPLE_FAULT_VIOLATION cpu_to_le32(0xC00002E8)
+#define STATUS_CURRENT_DOMAIN_NOT_ALLOWED cpu_to_le32(0xC00002E9)
+#define STATUS_CANNOT_MAKE cpu_to_le32(0xC00002EA)
+#define STATUS_SYSTEM_SHUTDOWN cpu_to_le32(0xC00002EB)
+#define STATUS_DS_INIT_FAILURE_CONSOLE cpu_to_le32(0xC00002EC)
+#define STATUS_DS_SAM_INIT_FAILURE_CONSOLE cpu_to_le32(0xC00002ED)
+#define STATUS_UNFINISHED_CONTEXT_DELETED cpu_to_le32(0xC00002EE)
+#define STATUS_NO_TGT_REPLY cpu_to_le32(0xC00002EF)
+#define STATUS_OBJECTID_NOT_FOUND cpu_to_le32(0xC00002F0)
+#define STATUS_NO_IP_ADDRESSES cpu_to_le32(0xC00002F1)
+#define STATUS_WRONG_CREDENTIAL_HANDLE cpu_to_le32(0xC00002F2)
+#define STATUS_CRYPTO_SYSTEM_INVALID cpu_to_le32(0xC00002F3)
+#define STATUS_MAX_REFERRALS_EXCEEDED cpu_to_le32(0xC00002F4)
+#define STATUS_MUST_BE_KDC cpu_to_le32(0xC00002F5)
+#define STATUS_STRONG_CRYPTO_NOT_SUPPORTED cpu_to_le32(0xC00002F6)
+#define STATUS_TOO_MANY_PRINCIPALS cpu_to_le32(0xC00002F7)
+#define STATUS_NO_PA_DATA cpu_to_le32(0xC00002F8)
+#define STATUS_PKINIT_NAME_MISMATCH cpu_to_le32(0xC00002F9)
+#define STATUS_SMARTCARD_LOGON_REQUIRED cpu_to_le32(0xC00002FA)
+#define STATUS_KDC_INVALID_REQUEST cpu_to_le32(0xC00002FB)
+#define STATUS_KDC_UNABLE_TO_REFER cpu_to_le32(0xC00002FC)
+#define STATUS_KDC_UNKNOWN_ETYPE cpu_to_le32(0xC00002FD)
+#define STATUS_SHUTDOWN_IN_PROGRESS cpu_to_le32(0xC00002FE)
+#define STATUS_SERVER_SHUTDOWN_IN_PROGRESS cpu_to_le32(0xC00002FF)
+#define STATUS_NOT_SUPPORTED_ON_SBS cpu_to_le32(0xC0000300)
+#define STATUS_WMI_GUID_DISCONNECTED cpu_to_le32(0xC0000301)
+#define STATUS_WMI_ALREADY_DISABLED cpu_to_le32(0xC0000302)
+#define STATUS_WMI_ALREADY_ENABLED cpu_to_le32(0xC0000303)
+#define STATUS_MFT_TOO_FRAGMENTED cpu_to_le32(0xC0000304)
+#define STATUS_COPY_PROTECTION_FAILURE cpu_to_le32(0xC0000305)
+#define STATUS_CSS_AUTHENTICATION_FAILURE cpu_to_le32(0xC0000306)
+#define STATUS_CSS_KEY_NOT_PRESENT cpu_to_le32(0xC0000307)
+#define STATUS_CSS_KEY_NOT_ESTABLISHED cpu_to_le32(0xC0000308)
+#define STATUS_CSS_SCRAMBLED_SECTOR cpu_to_le32(0xC0000309)
+#define STATUS_CSS_REGION_MISMATCH cpu_to_le32(0xC000030A)
+#define STATUS_CSS_RESETS_EXHAUSTED cpu_to_le32(0xC000030B)
+#define STATUS_PKINIT_FAILURE cpu_to_le32(0xC0000320)
+#define STATUS_SMARTCARD_SUBSYSTEM_FAILURE cpu_to_le32(0xC0000321)
+#define STATUS_NO_KERB_KEY cpu_to_le32(0xC0000322)
+#define STATUS_HOST_DOWN cpu_to_le32(0xC0000350)
+#define STATUS_UNSUPPORTED_PREAUTH cpu_to_le32(0xC0000351)
+#define STATUS_EFS_ALG_BLOB_TOO_BIG cpu_to_le32(0xC0000352)
+#define STATUS_PORT_NOT_SET cpu_to_le32(0xC0000353)
+#define STATUS_DEBUGGER_INACTIVE cpu_to_le32(0xC0000354)
+#define STATUS_DS_VERSION_CHECK_FAILURE cpu_to_le32(0xC0000355)
+#define STATUS_AUDITING_DISABLED cpu_to_le32(0xC0000356)
+#define STATUS_PRENT4_MACHINE_ACCOUNT cpu_to_le32(0xC0000357)
+#define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER cpu_to_le32(0xC0000358)
+#define STATUS_INVALID_IMAGE_WIN_32 cpu_to_le32(0xC0000359)
+#define STATUS_INVALID_IMAGE_WIN_64 cpu_to_le32(0xC000035A)
+#define STATUS_BAD_BINDINGS cpu_to_le32(0xC000035B)
+#define STATUS_NETWORK_SESSION_EXPIRED cpu_to_le32(0xC000035C)
+#define STATUS_APPHELP_BLOCK cpu_to_le32(0xC000035D)
+#define STATUS_ALL_SIDS_FILTERED cpu_to_le32(0xC000035E)
+#define STATUS_NOT_SAFE_MODE_DRIVER cpu_to_le32(0xC000035F)
+#define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT cpu_to_le32(0xC0000361)
+#define STATUS_ACCESS_DISABLED_BY_POLICY_PATH cpu_to_le32(0xC0000362)
+#define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER cpu_to_le32(0xC0000363)
+#define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER cpu_to_le32(0xC0000364)
+#define STATUS_FAILED_DRIVER_ENTRY cpu_to_le32(0xC0000365)
+#define STATUS_DEVICE_ENUMERATION_ERROR cpu_to_le32(0xC0000366)
+#define STATUS_MOUNT_POINT_NOT_RESOLVED cpu_to_le32(0xC0000368)
+#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER cpu_to_le32(0xC0000369)
+#define STATUS_MCA_OCCURED cpu_to_le32(0xC000036A)
+#define STATUS_DRIVER_BLOCKED_CRITICAL cpu_to_le32(0xC000036B)
+#define STATUS_DRIVER_BLOCKED cpu_to_le32(0xC000036C)
+#define STATUS_DRIVER_DATABASE_ERROR cpu_to_le32(0xC000036D)
+#define STATUS_SYSTEM_HIVE_TOO_LARGE cpu_to_le32(0xC000036E)
+#define STATUS_INVALID_IMPORT_OF_NON_DLL cpu_to_le32(0xC000036F)
+#define STATUS_NO_SECRETS cpu_to_le32(0xC0000371)
+#define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY cpu_to_le32(0xC0000372)
+#define STATUS_FAILED_STACK_SWITCH cpu_to_le32(0xC0000373)
+#define STATUS_HEAP_CORRUPTION cpu_to_le32(0xC0000374)
+#define STATUS_SMARTCARD_WRONG_PIN cpu_to_le32(0xC0000380)
+#define STATUS_SMARTCARD_CARD_BLOCKED cpu_to_le32(0xC0000381)
+#define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED cpu_to_le32(0xC0000382)
+#define STATUS_SMARTCARD_NO_CARD cpu_to_le32(0xC0000383)
+#define STATUS_SMARTCARD_NO_KEY_CONTAINER cpu_to_le32(0xC0000384)
+#define STATUS_SMARTCARD_NO_CERTIFICATE cpu_to_le32(0xC0000385)
+#define STATUS_SMARTCARD_NO_KEYSET cpu_to_le32(0xC0000386)
+#define STATUS_SMARTCARD_IO_ERROR cpu_to_le32(0xC0000387)
+#define STATUS_DOWNGRADE_DETECTED cpu_to_le32(0xC0000388)
+#define STATUS_SMARTCARD_CERT_REVOKED cpu_to_le32(0xC0000389)
+#define STATUS_ISSUING_CA_UNTRUSTED cpu_to_le32(0xC000038A)
+#define STATUS_REVOCATION_OFFLINE_C cpu_to_le32(0xC000038B)
+#define STATUS_PKINIT_CLIENT_FAILURE cpu_to_le32(0xC000038C)
+#define STATUS_SMARTCARD_CERT_EXPIRED cpu_to_le32(0xC000038D)
+#define STATUS_DRIVER_FAILED_PRIOR_UNLOAD cpu_to_le32(0xC000038E)
+#define STATUS_SMARTCARD_SILENT_CONTEXT cpu_to_le32(0xC000038F)
+#define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000401)
+#define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000402)
+#define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000403)
+#define STATUS_DS_NAME_NOT_UNIQUE cpu_to_le32(0xC0000404)
+#define STATUS_DS_DUPLICATE_ID_FOUND cpu_to_le32(0xC0000405)
+#define STATUS_DS_GROUP_CONVERSION_ERROR cpu_to_le32(0xC0000406)
+#define STATUS_VOLSNAP_PREPARE_HIBERNATE cpu_to_le32(0xC0000407)
+#define STATUS_USER2USER_REQUIRED cpu_to_le32(0xC0000408)
+#define STATUS_STACK_BUFFER_OVERRUN cpu_to_le32(0xC0000409)
+#define STATUS_NO_S4U_PROT_SUPPORT cpu_to_le32(0xC000040A)
+#define STATUS_CROSSREALM_DELEGATION_FAILURE cpu_to_le32(0xC000040B)
+#define STATUS_REVOCATION_OFFLINE_KDC cpu_to_le32(0xC000040C)
+#define STATUS_ISSUING_CA_UNTRUSTED_KDC cpu_to_le32(0xC000040D)
+#define STATUS_KDC_CERT_EXPIRED cpu_to_le32(0xC000040E)
+#define STATUS_KDC_CERT_REVOKED cpu_to_le32(0xC000040F)
+#define STATUS_PARAMETER_QUOTA_EXCEEDED cpu_to_le32(0xC0000410)
+#define STATUS_HIBERNATION_FAILURE cpu_to_le32(0xC0000411)
+#define STATUS_DELAY_LOAD_FAILED cpu_to_le32(0xC0000412)
+#define STATUS_AUTHENTICATION_FIREWALL_FAILED cpu_to_le32(0xC0000413)
+#define STATUS_VDM_DISALLOWED cpu_to_le32(0xC0000414)
+#define STATUS_HUNG_DISPLAY_DRIVER_THREAD cpu_to_le32(0xC0000415)
+#define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE cpu_to_le32(0xC0000416)
+#define STATUS_INVALID_CRUNTIME_PARAMETER cpu_to_le32(0xC0000417)
+#define STATUS_NTLM_BLOCKED cpu_to_le32(0xC0000418)
+#define STATUS_ASSERTION_FAILURE cpu_to_le32(0xC0000420)
+#define STATUS_VERIFIER_STOP cpu_to_le32(0xC0000421)
+#define STATUS_CALLBACK_POP_STACK cpu_to_le32(0xC0000423)
+#define STATUS_INCOMPATIBLE_DRIVER_BLOCKED cpu_to_le32(0xC0000424)
+#define STATUS_HIVE_UNLOADED cpu_to_le32(0xC0000425)
+#define STATUS_COMPRESSION_DISABLED cpu_to_le32(0xC0000426)
+#define STATUS_FILE_SYSTEM_LIMITATION cpu_to_le32(0xC0000427)
+#define STATUS_INVALID_IMAGE_HASH cpu_to_le32(0xC0000428)
+#define STATUS_NOT_CAPABLE cpu_to_le32(0xC0000429)
+#define STATUS_REQUEST_OUT_OF_SEQUENCE cpu_to_le32(0xC000042A)
+#define STATUS_IMPLEMENTATION_LIMIT cpu_to_le32(0xC000042B)
+#define STATUS_ELEVATION_REQUIRED cpu_to_le32(0xC000042C)
+#define STATUS_BEYOND_VDL cpu_to_le32(0xC0000432)
+#define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS cpu_to_le32(0xC0000433)
+#define STATUS_PTE_CHANGED cpu_to_le32(0xC0000434)
+#define STATUS_PURGE_FAILED cpu_to_le32(0xC0000435)
+#define STATUS_CRED_REQUIRES_CONFIRMATION cpu_to_le32(0xC0000440)
+#define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE cpu_to_le32(0xC0000441)
+#define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER cpu_to_le32(0xC0000442)
+#define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE cpu_to_le32(0xC0000443)
+#define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE cpu_to_le32(0xC0000444)
+#define STATUS_CS_ENCRYPTION_FILE_NOT_CSE cpu_to_le32(0xC0000445)
+#define STATUS_INVALID_LABEL cpu_to_le32(0xC0000446)
+#define STATUS_DRIVER_PROCESS_TERMINATED cpu_to_le32(0xC0000450)
+#define STATUS_AMBIGUOUS_SYSTEM_DEVICE cpu_to_le32(0xC0000451)
+#define STATUS_SYSTEM_DEVICE_NOT_FOUND cpu_to_le32(0xC0000452)
+#define STATUS_RESTART_BOOT_APPLICATION cpu_to_le32(0xC0000453)
+#define STATUS_INVALID_TASK_NAME cpu_to_le32(0xC0000500)
+#define STATUS_INVALID_TASK_INDEX cpu_to_le32(0xC0000501)
+#define STATUS_THREAD_ALREADY_IN_TASK cpu_to_le32(0xC0000502)
+#define STATUS_CALLBACK_BYPASS cpu_to_le32(0xC0000503)
+#define STATUS_PORT_CLOSED cpu_to_le32(0xC0000700)
+#define STATUS_MESSAGE_LOST cpu_to_le32(0xC0000701)
+#define STATUS_INVALID_MESSAGE cpu_to_le32(0xC0000702)
+#define STATUS_REQUEST_CANCELED cpu_to_le32(0xC0000703)
+#define STATUS_RECURSIVE_DISPATCH cpu_to_le32(0xC0000704)
+#define STATUS_LPC_RECEIVE_BUFFER_EXPECTED cpu_to_le32(0xC0000705)
+#define STATUS_LPC_INVALID_CONNECTION_USAGE cpu_to_le32(0xC0000706)
+#define STATUS_LPC_REQUESTS_NOT_ALLOWED cpu_to_le32(0xC0000707)
+#define STATUS_RESOURCE_IN_USE cpu_to_le32(0xC0000708)
+#define STATUS_HARDWARE_MEMORY_ERROR cpu_to_le32(0xC0000709)
+#define STATUS_THREADPOOL_HANDLE_EXCEPTION cpu_to_le32(0xC000070A)
+#define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED cpu_to_le32(0xC000070B)
+#define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED cpu_to_le32(0xC000070C)
+#define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED cpu_to_le32(0xC000070D)
+#define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED cpu_to_le32(0xC000070E)
+#define STATUS_THREADPOOL_RELEASED_DURING_OPERATION cpu_to_le32(0xC000070F)
+#define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING cpu_to_le32(0xC0000710)
+#define STATUS_APC_RETURNED_WHILE_IMPERSONATING cpu_to_le32(0xC0000711)
+#define STATUS_PROCESS_IS_PROTECTED cpu_to_le32(0xC0000712)
+#define STATUS_MCA_EXCEPTION cpu_to_le32(0xC0000713)
+#define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE cpu_to_le32(0xC0000714)
+#define STATUS_SYMLINK_CLASS_DISABLED cpu_to_le32(0xC0000715)
+#define STATUS_INVALID_IDN_NORMALIZATION cpu_to_le32(0xC0000716)
+#define STATUS_NO_UNICODE_TRANSLATION cpu_to_le32(0xC0000717)
+#define STATUS_ALREADY_REGISTERED cpu_to_le32(0xC0000718)
+#define STATUS_CONTEXT_MISMATCH cpu_to_le32(0xC0000719)
+#define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST cpu_to_le32(0xC000071A)
+#define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY cpu_to_le32(0xC000071B)
+#define STATUS_INVALID_THREAD cpu_to_le32(0xC000071C)
+#define STATUS_CALLBACK_RETURNED_TRANSACTION cpu_to_le32(0xC000071D)
+#define STATUS_CALLBACK_RETURNED_LDR_LOCK cpu_to_le32(0xC000071E)
+#define STATUS_CALLBACK_RETURNED_LANG cpu_to_le32(0xC000071F)
+#define STATUS_CALLBACK_RETURNED_PRI_BACK cpu_to_le32(0xC0000720)
+#define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY cpu_to_le32(0xC0000721)
+#define STATUS_DISK_REPAIR_DISABLED cpu_to_le32(0xC0000800)
+#define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS cpu_to_le32(0xC0000801)
+#define STATUS_DISK_QUOTA_EXCEEDED cpu_to_le32(0xC0000802)
+#define STATUS_CONTENT_BLOCKED cpu_to_le32(0xC0000804)
+#define STATUS_BAD_CLUSTERS cpu_to_le32(0xC0000805)
+#define STATUS_VOLUME_DIRTY cpu_to_le32(0xC0000806)
+#define STATUS_FILE_CHECKED_OUT cpu_to_le32(0xC0000901)
+#define STATUS_CHECKOUT_REQUIRED cpu_to_le32(0xC0000902)
+#define STATUS_BAD_FILE_TYPE cpu_to_le32(0xC0000903)
+#define STATUS_FILE_TOO_LARGE cpu_to_le32(0xC0000904)
+#define STATUS_FORMS_AUTH_REQUIRED cpu_to_le32(0xC0000905)
+#define STATUS_VIRUS_INFECTED cpu_to_le32(0xC0000906)
+#define STATUS_VIRUS_DELETED cpu_to_le32(0xC0000907)
+#define STATUS_BAD_MCFG_TABLE cpu_to_le32(0xC0000908)
+#define STATUS_WOW_ASSERTION cpu_to_le32(0xC0009898)
+#define STATUS_INVALID_SIGNATURE cpu_to_le32(0xC000A000)
+#define STATUS_HMAC_NOT_SUPPORTED cpu_to_le32(0xC000A001)
+#define STATUS_IPSEC_QUEUE_OVERFLOW cpu_to_le32(0xC000A010)
+#define STATUS_ND_QUEUE_OVERFLOW cpu_to_le32(0xC000A011)
+#define STATUS_HOPLIMIT_EXCEEDED cpu_to_le32(0xC000A012)
+#define STATUS_PROTOCOL_NOT_SUPPORTED cpu_to_le32(0xC000A013)
+#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED cpu_to_le32(0xC000A080)
+#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR cpu_to_le32(0xC000A081)
+#define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR cpu_to_le32(0xC000A082)
+#define STATUS_XML_PARSE_ERROR cpu_to_le32(0xC000A083)
+#define STATUS_XMLDSIG_ERROR cpu_to_le32(0xC000A084)
+#define STATUS_WRONG_COMPARTMENT cpu_to_le32(0xC000A085)
+#define STATUS_AUTHIP_FAILURE cpu_to_le32(0xC000A086)
+#define DBG_NO_STATE_CHANGE cpu_to_le32(0xC0010001)
+#define DBG_APP_NOT_IDLE cpu_to_le32(0xC0010002)
+#define RPC_NT_INVALID_STRING_BINDING cpu_to_le32(0xC0020001)
+#define RPC_NT_WRONG_KIND_OF_BINDING cpu_to_le32(0xC0020002)
+#define RPC_NT_INVALID_BINDING cpu_to_le32(0xC0020003)
+#define RPC_NT_PROTSEQ_NOT_SUPPORTED cpu_to_le32(0xC0020004)
+#define RPC_NT_INVALID_RPC_PROTSEQ cpu_to_le32(0xC0020005)
+#define RPC_NT_INVALID_STRING_UUID cpu_to_le32(0xC0020006)
+#define RPC_NT_INVALID_ENDPOINT_FORMAT cpu_to_le32(0xC0020007)
+#define RPC_NT_INVALID_NET_ADDR cpu_to_le32(0xC0020008)
+#define RPC_NT_NO_ENDPOINT_FOUND cpu_to_le32(0xC0020009)
+#define RPC_NT_INVALID_TIMEOUT cpu_to_le32(0xC002000A)
+#define RPC_NT_OBJECT_NOT_FOUND cpu_to_le32(0xC002000B)
+#define RPC_NT_ALREADY_REGISTERED cpu_to_le32(0xC002000C)
+#define RPC_NT_TYPE_ALREADY_REGISTERED cpu_to_le32(0xC002000D)
+#define RPC_NT_ALREADY_LISTENING cpu_to_le32(0xC002000E)
+#define RPC_NT_NO_PROTSEQS_REGISTERED cpu_to_le32(0xC002000F)
+#define RPC_NT_NOT_LISTENING cpu_to_le32(0xC0020010)
+#define RPC_NT_UNKNOWN_MGR_TYPE cpu_to_le32(0xC0020011)
+#define RPC_NT_UNKNOWN_IF cpu_to_le32(0xC0020012)
+#define RPC_NT_NO_BINDINGS cpu_to_le32(0xC0020013)
+#define RPC_NT_NO_PROTSEQS cpu_to_le32(0xC0020014)
+#define RPC_NT_CANT_CREATE_ENDPOINT cpu_to_le32(0xC0020015)
+#define RPC_NT_OUT_OF_RESOURCES cpu_to_le32(0xC0020016)
+#define RPC_NT_SERVER_UNAVAILABLE cpu_to_le32(0xC0020017)
+#define RPC_NT_SERVER_TOO_BUSY cpu_to_le32(0xC0020018)
+#define RPC_NT_INVALID_NETWORK_OPTIONS cpu_to_le32(0xC0020019)
+#define RPC_NT_NO_CALL_ACTIVE cpu_to_le32(0xC002001A)
+#define RPC_NT_CALL_FAILED cpu_to_le32(0xC002001B)
+#define RPC_NT_CALL_FAILED_DNE cpu_to_le32(0xC002001C)
+#define RPC_NT_PROTOCOL_ERROR cpu_to_le32(0xC002001D)
+#define RPC_NT_UNSUPPORTED_TRANS_SYN cpu_to_le32(0xC002001F)
+#define RPC_NT_UNSUPPORTED_TYPE cpu_to_le32(0xC0020021)
+#define RPC_NT_INVALID_TAG cpu_to_le32(0xC0020022)
+#define RPC_NT_INVALID_BOUND cpu_to_le32(0xC0020023)
+#define RPC_NT_NO_ENTRY_NAME cpu_to_le32(0xC0020024)
+#define RPC_NT_INVALID_NAME_SYNTAX cpu_to_le32(0xC0020025)
+#define RPC_NT_UNSUPPORTED_NAME_SYNTAX cpu_to_le32(0xC0020026)
+#define RPC_NT_UUID_NO_ADDRESS cpu_to_le32(0xC0020028)
+#define RPC_NT_DUPLICATE_ENDPOINT cpu_to_le32(0xC0020029)
+#define RPC_NT_UNKNOWN_AUTHN_TYPE cpu_to_le32(0xC002002A)
+#define RPC_NT_MAX_CALLS_TOO_SMALL cpu_to_le32(0xC002002B)
+#define RPC_NT_STRING_TOO_LONG cpu_to_le32(0xC002002C)
+#define RPC_NT_PROTSEQ_NOT_FOUND cpu_to_le32(0xC002002D)
+#define RPC_NT_PROCNUM_OUT_OF_RANGE cpu_to_le32(0xC002002E)
+#define RPC_NT_BINDING_HAS_NO_AUTH cpu_to_le32(0xC002002F)
+#define RPC_NT_UNKNOWN_AUTHN_SERVICE cpu_to_le32(0xC0020030)
+#define RPC_NT_UNKNOWN_AUTHN_LEVEL cpu_to_le32(0xC0020031)
+#define RPC_NT_INVALID_AUTH_IDENTITY cpu_to_le32(0xC0020032)
+#define RPC_NT_UNKNOWN_AUTHZ_SERVICE cpu_to_le32(0xC0020033)
+#define EPT_NT_INVALID_ENTRY cpu_to_le32(0xC0020034)
+#define EPT_NT_CANT_PERFORM_OP cpu_to_le32(0xC0020035)
+#define EPT_NT_NOT_REGISTERED cpu_to_le32(0xC0020036)
+#define RPC_NT_NOTHING_TO_EXPORT cpu_to_le32(0xC0020037)
+#define RPC_NT_INCOMPLETE_NAME cpu_to_le32(0xC0020038)
+#define RPC_NT_INVALID_VERS_OPTION cpu_to_le32(0xC0020039)
+#define RPC_NT_NO_MORE_MEMBERS cpu_to_le32(0xC002003A)
+#define RPC_NT_NOT_ALL_OBJS_UNEXPORTED cpu_to_le32(0xC002003B)
+#define RPC_NT_INTERFACE_NOT_FOUND cpu_to_le32(0xC002003C)
+#define RPC_NT_ENTRY_ALREADY_EXISTS cpu_to_le32(0xC002003D)
+#define RPC_NT_ENTRY_NOT_FOUND cpu_to_le32(0xC002003E)
+#define RPC_NT_NAME_SERVICE_UNAVAILABLE cpu_to_le32(0xC002003F)
+#define RPC_NT_INVALID_NAF_ID cpu_to_le32(0xC0020040)
+#define RPC_NT_CANNOT_SUPPORT cpu_to_le32(0xC0020041)
+#define RPC_NT_NO_CONTEXT_AVAILABLE cpu_to_le32(0xC0020042)
+#define RPC_NT_INTERNAL_ERROR cpu_to_le32(0xC0020043)
+#define RPC_NT_ZERO_DIVIDE cpu_to_le32(0xC0020044)
+#define RPC_NT_ADDRESS_ERROR cpu_to_le32(0xC0020045)
+#define RPC_NT_FP_DIV_ZERO cpu_to_le32(0xC0020046)
+#define RPC_NT_FP_UNDERFLOW cpu_to_le32(0xC0020047)
+#define RPC_NT_FP_OVERFLOW cpu_to_le32(0xC0020048)
+#define RPC_NT_CALL_IN_PROGRESS cpu_to_le32(0xC0020049)
+#define RPC_NT_NO_MORE_BINDINGS cpu_to_le32(0xC002004A)
+#define RPC_NT_GROUP_MEMBER_NOT_FOUND cpu_to_le32(0xC002004B)
+#define EPT_NT_CANT_CREATE cpu_to_le32(0xC002004C)
+#define RPC_NT_INVALID_OBJECT cpu_to_le32(0xC002004D)
+#define RPC_NT_NO_INTERFACES cpu_to_le32(0xC002004F)
+#define RPC_NT_CALL_CANCELLED cpu_to_le32(0xC0020050)
+#define RPC_NT_BINDING_INCOMPLETE cpu_to_le32(0xC0020051)
+#define RPC_NT_COMM_FAILURE cpu_to_le32(0xC0020052)
+#define RPC_NT_UNSUPPORTED_AUTHN_LEVEL cpu_to_le32(0xC0020053)
+#define RPC_NT_NO_PRINC_NAME cpu_to_le32(0xC0020054)
+#define RPC_NT_NOT_RPC_ERROR cpu_to_le32(0xC0020055)
+#define RPC_NT_SEC_PKG_ERROR cpu_to_le32(0xC0020057)
+#define RPC_NT_NOT_CANCELLED cpu_to_le32(0xC0020058)
+#define RPC_NT_INVALID_ASYNC_HANDLE cpu_to_le32(0xC0020062)
+#define RPC_NT_INVALID_ASYNC_CALL cpu_to_le32(0xC0020063)
+#define RPC_NT_PROXY_ACCESS_DENIED cpu_to_le32(0xC0020064)
+#define RPC_NT_NO_MORE_ENTRIES cpu_to_le32(0xC0030001)
+#define RPC_NT_SS_CHAR_TRANS_OPEN_FAIL cpu_to_le32(0xC0030002)
+#define RPC_NT_SS_CHAR_TRANS_SHORT_FILE cpu_to_le32(0xC0030003)
+#define RPC_NT_SS_IN_NULL_CONTEXT cpu_to_le32(0xC0030004)
+#define RPC_NT_SS_CONTEXT_MISMATCH cpu_to_le32(0xC0030005)
+#define RPC_NT_SS_CONTEXT_DAMAGED cpu_to_le32(0xC0030006)
+#define RPC_NT_SS_HANDLES_MISMATCH cpu_to_le32(0xC0030007)
+#define RPC_NT_SS_CANNOT_GET_CALL_HANDLE cpu_to_le32(0xC0030008)
+#define RPC_NT_NULL_REF_POINTER cpu_to_le32(0xC0030009)
+#define RPC_NT_ENUM_VALUE_OUT_OF_RANGE cpu_to_le32(0xC003000A)
+#define RPC_NT_BYTE_COUNT_TOO_SMALL cpu_to_le32(0xC003000B)
+#define RPC_NT_BAD_STUB_DATA cpu_to_le32(0xC003000C)
+#define RPC_NT_INVALID_ES_ACTION cpu_to_le32(0xC0030059)
+#define RPC_NT_WRONG_ES_VERSION cpu_to_le32(0xC003005A)
+#define RPC_NT_WRONG_STUB_VERSION cpu_to_le32(0xC003005B)
+#define RPC_NT_INVALID_PIPE_OBJECT cpu_to_le32(0xC003005C)
+#define RPC_NT_INVALID_PIPE_OPERATION cpu_to_le32(0xC003005D)
+#define RPC_NT_WRONG_PIPE_VERSION cpu_to_le32(0xC003005E)
+#define RPC_NT_PIPE_CLOSED cpu_to_le32(0xC003005F)
+#define RPC_NT_PIPE_DISCIPLINE_ERROR cpu_to_le32(0xC0030060)
+#define RPC_NT_PIPE_EMPTY cpu_to_le32(0xC0030061)
+#define STATUS_PNP_BAD_MPS_TABLE cpu_to_le32(0xC0040035)
+#define STATUS_PNP_TRANSLATION_FAILED cpu_to_le32(0xC0040036)
+#define STATUS_PNP_IRQ_TRANSLATION_FAILED cpu_to_le32(0xC0040037)
+#define STATUS_PNP_INVALID_ID cpu_to_le32(0xC0040038)
+#define STATUS_IO_REISSUE_AS_CACHED cpu_to_le32(0xC0040039)
+#define STATUS_CTX_WINSTATION_NAME_INVALID cpu_to_le32(0xC00A0001)
+#define STATUS_CTX_INVALID_PD cpu_to_le32(0xC00A0002)
+#define STATUS_CTX_PD_NOT_FOUND cpu_to_le32(0xC00A0003)
+#define STATUS_CTX_CLOSE_PENDING cpu_to_le32(0xC00A0006)
+#define STATUS_CTX_NO_OUTBUF cpu_to_le32(0xC00A0007)
+#define STATUS_CTX_MODEM_INF_NOT_FOUND cpu_to_le32(0xC00A0008)
+#define STATUS_CTX_INVALID_MODEMNAME cpu_to_le32(0xC00A0009)
+#define STATUS_CTX_RESPONSE_ERROR cpu_to_le32(0xC00A000A)
+#define STATUS_CTX_MODEM_RESPONSE_TIMEOUT cpu_to_le32(0xC00A000B)
+#define STATUS_CTX_MODEM_RESPONSE_NO_CARRIER cpu_to_le32(0xC00A000C)
+#define STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE cpu_to_le32(0xC00A000D)
+#define STATUS_CTX_MODEM_RESPONSE_BUSY cpu_to_le32(0xC00A000E)
+#define STATUS_CTX_MODEM_RESPONSE_VOICE cpu_to_le32(0xC00A000F)
+#define STATUS_CTX_TD_ERROR cpu_to_le32(0xC00A0010)
+#define STATUS_CTX_LICENSE_CLIENT_INVALID cpu_to_le32(0xC00A0012)
+#define STATUS_CTX_LICENSE_NOT_AVAILABLE cpu_to_le32(0xC00A0013)
+#define STATUS_CTX_LICENSE_EXPIRED cpu_to_le32(0xC00A0014)
+#define STATUS_CTX_WINSTATION_NOT_FOUND cpu_to_le32(0xC00A0015)
+#define STATUS_CTX_WINSTATION_NAME_COLLISION cpu_to_le32(0xC00A0016)
+#define STATUS_CTX_WINSTATION_BUSY cpu_to_le32(0xC00A0017)
+#define STATUS_CTX_BAD_VIDEO_MODE cpu_to_le32(0xC00A0018)
+#define STATUS_CTX_GRAPHICS_INVALID cpu_to_le32(0xC00A0022)
+#define STATUS_CTX_NOT_CONSOLE cpu_to_le32(0xC00A0024)
+#define STATUS_CTX_CLIENT_QUERY_TIMEOUT cpu_to_le32(0xC00A0026)
+#define STATUS_CTX_CONSOLE_DISCONNECT cpu_to_le32(0xC00A0027)
+#define STATUS_CTX_CONSOLE_CONNECT cpu_to_le32(0xC00A0028)
+#define STATUS_CTX_SHADOW_DENIED cpu_to_le32(0xC00A002A)
+#define STATUS_CTX_WINSTATION_ACCESS_DENIED cpu_to_le32(0xC00A002B)
+#define STATUS_CTX_INVALID_WD cpu_to_le32(0xC00A002E)
+#define STATUS_CTX_WD_NOT_FOUND cpu_to_le32(0xC00A002F)
+#define STATUS_CTX_SHADOW_INVALID cpu_to_le32(0xC00A0030)
+#define STATUS_CTX_SHADOW_DISABLED cpu_to_le32(0xC00A0031)
+#define STATUS_RDP_PROTOCOL_ERROR cpu_to_le32(0xC00A0032)
+#define STATUS_CTX_CLIENT_LICENSE_NOT_SET cpu_to_le32(0xC00A0033)
+#define STATUS_CTX_CLIENT_LICENSE_IN_USE cpu_to_le32(0xC00A0034)
+#define STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE cpu_to_le32(0xC00A0035)
+#define STATUS_CTX_SHADOW_NOT_RUNNING cpu_to_le32(0xC00A0036)
+#define STATUS_CTX_LOGON_DISABLED cpu_to_le32(0xC00A0037)
+#define STATUS_CTX_SECURITY_LAYER_ERROR cpu_to_le32(0xC00A0038)
+#define STATUS_TS_INCOMPATIBLE_SESSIONS cpu_to_le32(0xC00A0039)
+#define STATUS_MUI_FILE_NOT_FOUND cpu_to_le32(0xC00B0001)
+#define STATUS_MUI_INVALID_FILE cpu_to_le32(0xC00B0002)
+#define STATUS_MUI_INVALID_RC_CONFIG cpu_to_le32(0xC00B0003)
+#define STATUS_MUI_INVALID_LOCALE_NAME cpu_to_le32(0xC00B0004)
+#define STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME cpu_to_le32(0xC00B0005)
+#define STATUS_MUI_FILE_NOT_LOADED cpu_to_le32(0xC00B0006)
+#define STATUS_RESOURCE_ENUM_USER_STOP cpu_to_le32(0xC00B0007)
+#define STATUS_CLUSTER_INVALID_NODE cpu_to_le32(0xC0130001)
+#define STATUS_CLUSTER_NODE_EXISTS cpu_to_le32(0xC0130002)
+#define STATUS_CLUSTER_JOIN_IN_PROGRESS cpu_to_le32(0xC0130003)
+#define STATUS_CLUSTER_NODE_NOT_FOUND cpu_to_le32(0xC0130004)
+#define STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND cpu_to_le32(0xC0130005)
+#define STATUS_CLUSTER_NETWORK_EXISTS cpu_to_le32(0xC0130006)
+#define STATUS_CLUSTER_NETWORK_NOT_FOUND cpu_to_le32(0xC0130007)
+#define STATUS_CLUSTER_NETINTERFACE_EXISTS cpu_to_le32(0xC0130008)
+#define STATUS_CLUSTER_NETINTERFACE_NOT_FOUND cpu_to_le32(0xC0130009)
+#define STATUS_CLUSTER_INVALID_REQUEST cpu_to_le32(0xC013000A)
+#define STATUS_CLUSTER_INVALID_NETWORK_PROVIDER cpu_to_le32(0xC013000B)
+#define STATUS_CLUSTER_NODE_DOWN cpu_to_le32(0xC013000C)
+#define STATUS_CLUSTER_NODE_UNREACHABLE cpu_to_le32(0xC013000D)
+#define STATUS_CLUSTER_NODE_NOT_MEMBER cpu_to_le32(0xC013000E)
+#define STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS cpu_to_le32(0xC013000F)
+#define STATUS_CLUSTER_INVALID_NETWORK cpu_to_le32(0xC0130010)
+#define STATUS_CLUSTER_NO_NET_ADAPTERS cpu_to_le32(0xC0130011)
+#define STATUS_CLUSTER_NODE_UP cpu_to_le32(0xC0130012)
+#define STATUS_CLUSTER_NODE_PAUSED cpu_to_le32(0xC0130013)
+#define STATUS_CLUSTER_NODE_NOT_PAUSED cpu_to_le32(0xC0130014)
+#define STATUS_CLUSTER_NO_SECURITY_CONTEXT cpu_to_le32(0xC0130015)
+#define STATUS_CLUSTER_NETWORK_NOT_INTERNAL cpu_to_le32(0xC0130016)
+#define STATUS_CLUSTER_POISONED cpu_to_le32(0xC0130017)
+#define STATUS_ACPI_INVALID_OPCODE cpu_to_le32(0xC0140001)
+#define STATUS_ACPI_STACK_OVERFLOW cpu_to_le32(0xC0140002)
+#define STATUS_ACPI_ASSERT_FAILED cpu_to_le32(0xC0140003)
+#define STATUS_ACPI_INVALID_INDEX cpu_to_le32(0xC0140004)
+#define STATUS_ACPI_INVALID_ARGUMENT cpu_to_le32(0xC0140005)
+#define STATUS_ACPI_FATAL cpu_to_le32(0xC0140006)
+#define STATUS_ACPI_INVALID_SUPERNAME cpu_to_le32(0xC0140007)
+#define STATUS_ACPI_INVALID_ARGTYPE cpu_to_le32(0xC0140008)
+#define STATUS_ACPI_INVALID_OBJTYPE cpu_to_le32(0xC0140009)
+#define STATUS_ACPI_INVALID_TARGETTYPE cpu_to_le32(0xC014000A)
+#define STATUS_ACPI_INCORRECT_ARGUMENT_COUNT cpu_to_le32(0xC014000B)
+#define STATUS_ACPI_ADDRESS_NOT_MAPPED cpu_to_le32(0xC014000C)
+#define STATUS_ACPI_INVALID_EVENTTYPE cpu_to_le32(0xC014000D)
+#define STATUS_ACPI_HANDLER_COLLISION cpu_to_le32(0xC014000E)
+#define STATUS_ACPI_INVALID_DATA cpu_to_le32(0xC014000F)
+#define STATUS_ACPI_INVALID_REGION cpu_to_le32(0xC0140010)
+#define STATUS_ACPI_INVALID_ACCESS_SIZE cpu_to_le32(0xC0140011)
+#define STATUS_ACPI_ACQUIRE_GLOBAL_LOCK cpu_to_le32(0xC0140012)
+#define STATUS_ACPI_ALREADY_INITIALIZED cpu_to_le32(0xC0140013)
+#define STATUS_ACPI_NOT_INITIALIZED cpu_to_le32(0xC0140014)
+#define STATUS_ACPI_INVALID_MUTEX_LEVEL cpu_to_le32(0xC0140015)
+#define STATUS_ACPI_MUTEX_NOT_OWNED cpu_to_le32(0xC0140016)
+#define STATUS_ACPI_MUTEX_NOT_OWNER cpu_to_le32(0xC0140017)
+#define STATUS_ACPI_RS_ACCESS cpu_to_le32(0xC0140018)
+#define STATUS_ACPI_INVALID_TABLE cpu_to_le32(0xC0140019)
+#define STATUS_ACPI_REG_HANDLER_FAILED cpu_to_le32(0xC0140020)
+#define STATUS_ACPI_POWER_REQUEST_FAILED cpu_to_le32(0xC0140021)
+#define STATUS_SXS_SECTION_NOT_FOUND cpu_to_le32(0xC0150001)
+#define STATUS_SXS_CANT_GEN_ACTCTX cpu_to_le32(0xC0150002)
+#define STATUS_SXS_INVALID_ACTCTXDATA_FORMAT cpu_to_le32(0xC0150003)
+#define STATUS_SXS_ASSEMBLY_NOT_FOUND cpu_to_le32(0xC0150004)
+#define STATUS_SXS_MANIFEST_FORMAT_ERROR cpu_to_le32(0xC0150005)
+#define STATUS_SXS_MANIFEST_PARSE_ERROR cpu_to_le32(0xC0150006)
+#define STATUS_SXS_ACTIVATION_CONTEXT_DISABLED cpu_to_le32(0xC0150007)
+#define STATUS_SXS_KEY_NOT_FOUND cpu_to_le32(0xC0150008)
+#define STATUS_SXS_VERSION_CONFLICT cpu_to_le32(0xC0150009)
+#define STATUS_SXS_WRONG_SECTION_TYPE cpu_to_le32(0xC015000A)
+#define STATUS_SXS_THREAD_QUERIES_DISABLED cpu_to_le32(0xC015000B)
+#define STATUS_SXS_ASSEMBLY_MISSING cpu_to_le32(0xC015000C)
+#define STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET cpu_to_le32(0xC015000E)
+#define STATUS_SXS_EARLY_DEACTIVATION cpu_to_le32(0xC015000F)
+#define STATUS_SXS_INVALID_DEACTIVATION cpu_to_le32(0xC0150010)
+#define STATUS_SXS_MULTIPLE_DEACTIVATION cpu_to_le32(0xC0150011)
+#define STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY cpu_to_le32(0xC0150012)
+#define STATUS_SXS_PROCESS_TERMINATION_REQUESTED cpu_to_le32(0xC0150013)
+#define STATUS_SXS_CORRUPT_ACTIVATION_STACK cpu_to_le32(0xC0150014)
+#define STATUS_SXS_CORRUPTION cpu_to_le32(0xC0150015)
+#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE cpu_to_le32(0xC0150016)
+#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME cpu_to_le32(0xC0150017)
+#define STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE cpu_to_le32(0xC0150018)
+#define STATUS_SXS_IDENTITY_PARSE_ERROR cpu_to_le32(0xC0150019)
+#define STATUS_SXS_COMPONENT_STORE_CORRUPT cpu_to_le32(0xC015001A)
+#define STATUS_SXS_FILE_HASH_MISMATCH cpu_to_le32(0xC015001B)
+#define STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT cpu_to_le32(0xC015001C)
+#define STATUS_SXS_IDENTITIES_DIFFERENT cpu_to_le32(0xC015001D)
+#define STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT cpu_to_le32(0xC015001E)
+#define STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY cpu_to_le32(0xC015001F)
+#define STATUS_ADVANCED_INSTALLER_FAILED cpu_to_le32(0xC0150020)
+#define STATUS_XML_ENCODING_MISMATCH cpu_to_le32(0xC0150021)
+#define STATUS_SXS_MANIFEST_TOO_BIG cpu_to_le32(0xC0150022)
+#define STATUS_SXS_SETTING_NOT_REGISTERED cpu_to_le32(0xC0150023)
+#define STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE cpu_to_le32(0xC0150024)
+#define STATUS_SMI_PRIMITIVE_INSTALLER_FAILED cpu_to_le32(0xC0150025)
+#define STATUS_GENERIC_COMMAND_FAILED cpu_to_le32(0xC0150026)
+#define STATUS_SXS_FILE_HASH_MISSING cpu_to_le32(0xC0150027)
+#define STATUS_TRANSACTIONAL_CONFLICT cpu_to_le32(0xC0190001)
+#define STATUS_INVALID_TRANSACTION cpu_to_le32(0xC0190002)
+#define STATUS_TRANSACTION_NOT_ACTIVE cpu_to_le32(0xC0190003)
+#define STATUS_TM_INITIALIZATION_FAILED cpu_to_le32(0xC0190004)
+#define STATUS_RM_NOT_ACTIVE cpu_to_le32(0xC0190005)
+#define STATUS_RM_METADATA_CORRUPT cpu_to_le32(0xC0190006)
+#define STATUS_TRANSACTION_NOT_JOINED cpu_to_le32(0xC0190007)
+#define STATUS_DIRECTORY_NOT_RM cpu_to_le32(0xC0190008)
+#define STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE cpu_to_le32(0xC019000A)
+#define STATUS_LOG_RESIZE_INVALID_SIZE cpu_to_le32(0xC019000B)
+#define STATUS_REMOTE_FILE_VERSION_MISMATCH cpu_to_le32(0xC019000C)
+#define STATUS_CRM_PROTOCOL_ALREADY_EXISTS cpu_to_le32(0xC019000F)
+#define STATUS_TRANSACTION_PROPAGATION_FAILED cpu_to_le32(0xC0190010)
+#define STATUS_CRM_PROTOCOL_NOT_FOUND cpu_to_le32(0xC0190011)
+#define STATUS_TRANSACTION_SUPERIOR_EXISTS cpu_to_le32(0xC0190012)
+#define STATUS_TRANSACTION_REQUEST_NOT_VALID cpu_to_le32(0xC0190013)
+#define STATUS_TRANSACTION_NOT_REQUESTED cpu_to_le32(0xC0190014)
+#define STATUS_TRANSACTION_ALREADY_ABORTED cpu_to_le32(0xC0190015)
+#define STATUS_TRANSACTION_ALREADY_COMMITTED cpu_to_le32(0xC0190016)
+#define STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER cpu_to_le32(0xC0190017)
+#define STATUS_CURRENT_TRANSACTION_NOT_VALID cpu_to_le32(0xC0190018)
+#define STATUS_LOG_GROWTH_FAILED cpu_to_le32(0xC0190019)
+#define STATUS_OBJECT_NO_LONGER_EXISTS cpu_to_le32(0xC0190021)
+#define STATUS_STREAM_MINIVERSION_NOT_FOUND cpu_to_le32(0xC0190022)
+#define STATUS_STREAM_MINIVERSION_NOT_VALID cpu_to_le32(0xC0190023)
+#define STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION cpu_to_le32(0xC0190024)
+#define STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT cpu_to_le32(0xC0190025)
+#define STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS cpu_to_le32(0xC0190026)
+#define STATUS_HANDLE_NO_LONGER_VALID cpu_to_le32(0xC0190028)
+#define STATUS_LOG_CORRUPTION_DETECTED cpu_to_le32(0xC0190030)
+#define STATUS_RM_DISCONNECTED cpu_to_le32(0xC0190032)
+#define STATUS_ENLISTMENT_NOT_SUPERIOR cpu_to_le32(0xC0190033)
+#define STATUS_FILE_IDENTITY_NOT_PERSISTENT cpu_to_le32(0xC0190036)
+#define STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY cpu_to_le32(0xC0190037)
+#define STATUS_CANT_CROSS_RM_BOUNDARY cpu_to_le32(0xC0190038)
+#define STATUS_TXF_DIR_NOT_EMPTY cpu_to_le32(0xC0190039)
+#define STATUS_INDOUBT_TRANSACTIONS_EXIST cpu_to_le32(0xC019003A)
+#define STATUS_TM_VOLATILE cpu_to_le32(0xC019003B)
+#define STATUS_ROLLBACK_TIMER_EXPIRED cpu_to_le32(0xC019003C)
+#define STATUS_TXF_ATTRIBUTE_CORRUPT cpu_to_le32(0xC019003D)
+#define STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC019003E)
+#define STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED cpu_to_le32(0xC019003F)
+#define STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE cpu_to_le32(0xC0190040)
+#define STATUS_TRANSACTION_REQUIRED_PROMOTION cpu_to_le32(0xC0190043)
+#define STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION cpu_to_le32(0xC0190044)
+#define STATUS_TRANSACTIONS_NOT_FROZEN cpu_to_le32(0xC0190045)
+#define STATUS_TRANSACTION_FREEZE_IN_PROGRESS cpu_to_le32(0xC0190046)
+#define STATUS_NOT_SNAPSHOT_VOLUME cpu_to_le32(0xC0190047)
+#define STATUS_NO_SAVEPOINT_WITH_OPEN_FILES cpu_to_le32(0xC0190048)
+#define STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC0190049)
+#define STATUS_TM_IDENTITY_MISMATCH cpu_to_le32(0xC019004A)
+#define STATUS_FLOATED_SECTION cpu_to_le32(0xC019004B)
+#define STATUS_CANNOT_ACCEPT_TRANSACTED_WORK cpu_to_le32(0xC019004C)
+#define STATUS_CANNOT_ABORT_TRANSACTIONS cpu_to_le32(0xC019004D)
+#define STATUS_TRANSACTION_NOT_FOUND cpu_to_le32(0xC019004E)
+#define STATUS_RESOURCEMANAGER_NOT_FOUND cpu_to_le32(0xC019004F)
+#define STATUS_ENLISTMENT_NOT_FOUND cpu_to_le32(0xC0190050)
+#define STATUS_TRANSACTIONMANAGER_NOT_FOUND cpu_to_le32(0xC0190051)
+#define STATUS_TRANSACTIONMANAGER_NOT_ONLINE cpu_to_le32(0xC0190052)
+#define STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION cpu_to_le32(0xC0190053)
+#define STATUS_TRANSACTION_NOT_ROOT cpu_to_le32(0xC0190054)
+#define STATUS_TRANSACTION_OBJECT_EXPIRED cpu_to_le32(0xC0190055)
+#define STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC0190056)
+#define STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED cpu_to_le32(0xC0190057)
+#define STATUS_TRANSACTION_RECORD_TOO_LONG cpu_to_le32(0xC0190058)
+#define STATUS_NO_LINK_TRACKING_IN_TRANSACTION cpu_to_le32(0xC0190059)
+#define STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION cpu_to_le32(0xC019005A)
+#define STATUS_TRANSACTION_INTEGRITY_VIOLATED cpu_to_le32(0xC019005B)
+#define STATUS_LOG_SECTOR_INVALID cpu_to_le32(0xC01A0001)
+#define STATUS_LOG_SECTOR_PARITY_INVALID cpu_to_le32(0xC01A0002)
+#define STATUS_LOG_SECTOR_REMAPPED cpu_to_le32(0xC01A0003)
+#define STATUS_LOG_BLOCK_INCOMPLETE cpu_to_le32(0xC01A0004)
+#define STATUS_LOG_INVALID_RANGE cpu_to_le32(0xC01A0005)
+#define STATUS_LOG_BLOCKS_EXHAUSTED cpu_to_le32(0xC01A0006)
+#define STATUS_LOG_READ_CONTEXT_INVALID cpu_to_le32(0xC01A0007)
+#define STATUS_LOG_RESTART_INVALID cpu_to_le32(0xC01A0008)
+#define STATUS_LOG_BLOCK_VERSION cpu_to_le32(0xC01A0009)
+#define STATUS_LOG_BLOCK_INVALID cpu_to_le32(0xC01A000A)
+#define STATUS_LOG_READ_MODE_INVALID cpu_to_le32(0xC01A000B)
+#define STATUS_LOG_METADATA_CORRUPT cpu_to_le32(0xC01A000D)
+#define STATUS_LOG_METADATA_INVALID cpu_to_le32(0xC01A000E)
+#define STATUS_LOG_METADATA_INCONSISTENT cpu_to_le32(0xC01A000F)
+#define STATUS_LOG_RESERVATION_INVALID cpu_to_le32(0xC01A0010)
+#define STATUS_LOG_CANT_DELETE cpu_to_le32(0xC01A0011)
+#define STATUS_LOG_CONTAINER_LIMIT_EXCEEDED cpu_to_le32(0xC01A0012)
+#define STATUS_LOG_START_OF_LOG cpu_to_le32(0xC01A0013)
+#define STATUS_LOG_POLICY_ALREADY_INSTALLED cpu_to_le32(0xC01A0014)
+#define STATUS_LOG_POLICY_NOT_INSTALLED cpu_to_le32(0xC01A0015)
+#define STATUS_LOG_POLICY_INVALID cpu_to_le32(0xC01A0016)
+#define STATUS_LOG_POLICY_CONFLICT cpu_to_le32(0xC01A0017)
+#define STATUS_LOG_PINNED_ARCHIVE_TAIL cpu_to_le32(0xC01A0018)
+#define STATUS_LOG_RECORD_NONEXISTENT cpu_to_le32(0xC01A0019)
+#define STATUS_LOG_RECORDS_RESERVED_INVALID cpu_to_le32(0xC01A001A)
+#define STATUS_LOG_SPACE_RESERVED_INVALID cpu_to_le32(0xC01A001B)
+#define STATUS_LOG_TAIL_INVALID cpu_to_le32(0xC01A001C)
+#define STATUS_LOG_FULL cpu_to_le32(0xC01A001D)
+#define STATUS_LOG_MULTIPLEXED cpu_to_le32(0xC01A001E)
+#define STATUS_LOG_DEDICATED cpu_to_le32(0xC01A001F)
+#define STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS cpu_to_le32(0xC01A0020)
+#define STATUS_LOG_ARCHIVE_IN_PROGRESS cpu_to_le32(0xC01A0021)
+#define STATUS_LOG_EPHEMERAL cpu_to_le32(0xC01A0022)
+#define STATUS_LOG_NOT_ENOUGH_CONTAINERS cpu_to_le32(0xC01A0023)
+#define STATUS_LOG_CLIENT_ALREADY_REGISTERED cpu_to_le32(0xC01A0024)
+#define STATUS_LOG_CLIENT_NOT_REGISTERED cpu_to_le32(0xC01A0025)
+#define STATUS_LOG_FULL_HANDLER_IN_PROGRESS cpu_to_le32(0xC01A0026)
+#define STATUS_LOG_CONTAINER_READ_FAILED cpu_to_le32(0xC01A0027)
+#define STATUS_LOG_CONTAINER_WRITE_FAILED cpu_to_le32(0xC01A0028)
+#define STATUS_LOG_CONTAINER_OPEN_FAILED cpu_to_le32(0xC01A0029)
+#define STATUS_LOG_CONTAINER_STATE_INVALID cpu_to_le32(0xC01A002A)
+#define STATUS_LOG_STATE_INVALID cpu_to_le32(0xC01A002B)
+#define STATUS_LOG_PINNED cpu_to_le32(0xC01A002C)
+#define STATUS_LOG_METADATA_FLUSH_FAILED cpu_to_le32(0xC01A002D)
+#define STATUS_LOG_INCONSISTENT_SECURITY cpu_to_le32(0xC01A002E)
+#define STATUS_LOG_APPENDED_FLUSH_FAILED cpu_to_le32(0xC01A002F)
+#define STATUS_LOG_PINNED_RESERVATION cpu_to_le32(0xC01A0030)
+#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD cpu_to_le32(0xC01B00EA)
+#define STATUS_FLT_NO_HANDLER_DEFINED cpu_to_le32(0xC01C0001)
+#define STATUS_FLT_CONTEXT_ALREADY_DEFINED cpu_to_le32(0xC01C0002)
+#define STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST cpu_to_le32(0xC01C0003)
+#define STATUS_FLT_DISALLOW_FAST_IO cpu_to_le32(0xC01C0004)
+#define STATUS_FLT_INVALID_NAME_REQUEST cpu_to_le32(0xC01C0005)
+#define STATUS_FLT_NOT_SAFE_TO_POST_OPERATION cpu_to_le32(0xC01C0006)
+#define STATUS_FLT_NOT_INITIALIZED cpu_to_le32(0xC01C0007)
+#define STATUS_FLT_FILTER_NOT_READY cpu_to_le32(0xC01C0008)
+#define STATUS_FLT_POST_OPERATION_CLEANUP cpu_to_le32(0xC01C0009)
+#define STATUS_FLT_INTERNAL_ERROR cpu_to_le32(0xC01C000A)
+#define STATUS_FLT_DELETING_OBJECT cpu_to_le32(0xC01C000B)
+#define STATUS_FLT_MUST_BE_NONPAGED_POOL cpu_to_le32(0xC01C000C)
+#define STATUS_FLT_DUPLICATE_ENTRY cpu_to_le32(0xC01C000D)
+#define STATUS_FLT_CBDQ_DISABLED cpu_to_le32(0xC01C000E)
+#define STATUS_FLT_DO_NOT_ATTACH cpu_to_le32(0xC01C000F)
+#define STATUS_FLT_DO_NOT_DETACH cpu_to_le32(0xC01C0010)
+#define STATUS_FLT_INSTANCE_ALTITUDE_COLLISION cpu_to_le32(0xC01C0011)
+#define STATUS_FLT_INSTANCE_NAME_COLLISION cpu_to_le32(0xC01C0012)
+#define STATUS_FLT_FILTER_NOT_FOUND cpu_to_le32(0xC01C0013)
+#define STATUS_FLT_VOLUME_NOT_FOUND cpu_to_le32(0xC01C0014)
+#define STATUS_FLT_INSTANCE_NOT_FOUND cpu_to_le32(0xC01C0015)
+#define STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND cpu_to_le32(0xC01C0016)
+#define STATUS_FLT_INVALID_CONTEXT_REGISTRATION cpu_to_le32(0xC01C0017)
+#define STATUS_FLT_NAME_CACHE_MISS cpu_to_le32(0xC01C0018)
+#define STATUS_FLT_NO_DEVICE_OBJECT cpu_to_le32(0xC01C0019)
+#define STATUS_FLT_VOLUME_ALREADY_MOUNTED cpu_to_le32(0xC01C001A)
+#define STATUS_FLT_ALREADY_ENLISTED cpu_to_le32(0xC01C001B)
+#define STATUS_FLT_CONTEXT_ALREADY_LINKED cpu_to_le32(0xC01C001C)
+#define STATUS_FLT_NO_WAITER_FOR_REPLY cpu_to_le32(0xC01C0020)
+#define STATUS_MONITOR_NO_DESCRIPTOR cpu_to_le32(0xC01D0001)
+#define STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT cpu_to_le32(0xC01D0002)
+#define STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM cpu_to_le32(0xC01D0003)
+#define STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK cpu_to_le32(0xC01D0004)
+#define STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED cpu_to_le32(0xC01D0005)
+#define STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK cpu_to_le32(0xC01D0006)
+#define STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK cpu_to_le32(0xC01D0007)
+#define STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA cpu_to_le32(0xC01D0008)
+#define STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK cpu_to_le32(0xC01D0009)
+#define STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER cpu_to_le32(0xC01E0000)
+#define STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER cpu_to_le32(0xC01E0001)
+#define STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER cpu_to_le32(0xC01E0002)
+#define STATUS_GRAPHICS_ADAPTER_WAS_RESET cpu_to_le32(0xC01E0003)
+#define STATUS_GRAPHICS_INVALID_DRIVER_MODEL cpu_to_le32(0xC01E0004)
+#define STATUS_GRAPHICS_PRESENT_MODE_CHANGED cpu_to_le32(0xC01E0005)
+#define STATUS_GRAPHICS_PRESENT_OCCLUDED cpu_to_le32(0xC01E0006)
+#define STATUS_GRAPHICS_PRESENT_DENIED cpu_to_le32(0xC01E0007)
+#define STATUS_GRAPHICS_CANNOTCOLORCONVERT cpu_to_le32(0xC01E0008)
+#define STATUS_GRAPHICS_NO_VIDEO_MEMORY cpu_to_le32(0xC01E0100)
+#define STATUS_GRAPHICS_CANT_LOCK_MEMORY cpu_to_le32(0xC01E0101)
+#define STATUS_GRAPHICS_ALLOCATION_BUSY cpu_to_le32(0xC01E0102)
+#define STATUS_GRAPHICS_TOO_MANY_REFERENCES cpu_to_le32(0xC01E0103)
+#define STATUS_GRAPHICS_TRY_AGAIN_LATER cpu_to_le32(0xC01E0104)
+#define STATUS_GRAPHICS_TRY_AGAIN_NOW cpu_to_le32(0xC01E0105)
+#define STATUS_GRAPHICS_ALLOCATION_INVALID cpu_to_le32(0xC01E0106)
+#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE cpu_to_le32(0xC01E0107)
+#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED cpu_to_le32(0xC01E0108)
+#define STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION cpu_to_le32(0xC01E0109)
+#define STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE cpu_to_le32(0xC01E0110)
+#define STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION cpu_to_le32(0xC01E0111)
+#define STATUS_GRAPHICS_ALLOCATION_CLOSED cpu_to_le32(0xC01E0112)
+#define STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE cpu_to_le32(0xC01E0113)
+#define STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE cpu_to_le32(0xC01E0114)
+#define STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE cpu_to_le32(0xC01E0115)
+#define STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST cpu_to_le32(0xC01E0116)
+#define STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE cpu_to_le32(0xC01E0200)
+#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY cpu_to_le32(0xC01E0300)
+#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED cpu_to_le32(0xC01E0301)
+#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED cpu_to_le32(0xC01E0302)
+#define STATUS_GRAPHICS_INVALID_VIDPN cpu_to_le32(0xC01E0303)
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE cpu_to_le32(0xC01E0304)
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET cpu_to_le32(0xC01E0305)
+#define STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED cpu_to_le32(0xC01E0306)
+#define STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET cpu_to_le32(0xC01E0308)
+#define STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET cpu_to_le32(0xC01E0309)
+#define STATUS_GRAPHICS_INVALID_FREQUENCY cpu_to_le32(0xC01E030A)
+#define STATUS_GRAPHICS_INVALID_ACTIVE_REGION cpu_to_le32(0xC01E030B)
+#define STATUS_GRAPHICS_INVALID_TOTAL_REGION cpu_to_le32(0xC01E030C)
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE cpu_to_le32(0xC01E0310)
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE cpu_to_le32(0xC01E0311)
+#define STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET cpu_to_le32(0xC01E0312)
+#define STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY cpu_to_le32(0xC01E0313)
+#define STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET cpu_to_le32(0xC01E0314)
+#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET cpu_to_le32(0xC01E0315)
+#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET cpu_to_le32(0xC01E0316)
+#define STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET cpu_to_le32(0xC01E0317)
+#define STATUS_GRAPHICS_TARGET_ALREADY_IN_SET cpu_to_le32(0xC01E0318)
+#define STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH cpu_to_le32(0xC01E0319)
+#define STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY cpu_to_le32(0xC01E031A)
+#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET cpu_to_le32(0xC01E031B)
+#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE cpu_to_le32(0xC01E031C)
+#define STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET cpu_to_le32(0xC01E031D)
+#define STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET cpu_to_le32(0xC01E031F)
+#define STATUS_GRAPHICS_STALE_MODESET cpu_to_le32(0xC01E0320)
+#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET cpu_to_le32(0xC01E0321)
+#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE cpu_to_le32(0xC01E0322)
+#define STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN cpu_to_le32(0xC01E0323)
+#define STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0324)
+#define STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION cpu_to_le32(0xC01E0325)
+#define STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES cpu_to_le32(0xC01E0326)
+#define STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0327)
+#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE cpu_to_le32(0xC01E0328)
+#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET cpu_to_le32(0xC01E0329)
+#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET cpu_to_le32(0xC01E032A)
+#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR cpu_to_le32(0xC01E032B)
+#define STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET cpu_to_le32(0xC01E032C)
+#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET cpu_to_le32(0xC01E032D)
+#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E032E)
+#define STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE cpu_to_le32(0xC01E032F)
+#define STATUS_GRAPHICS_RESOURCES_NOT_RELATED cpu_to_le32(0xC01E0330)
+#define STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0331)
+#define STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0332)
+#define STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET cpu_to_le32(0xC01E0333)
+#define STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER cpu_to_le32(0xC01E0334)
+#define STATUS_GRAPHICS_NO_VIDPNMGR cpu_to_le32(0xC01E0335)
+#define STATUS_GRAPHICS_NO_ACTIVE_VIDPN cpu_to_le32(0xC01E0336)
+#define STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY cpu_to_le32(0xC01E0337)
+#define STATUS_GRAPHICS_MONITOR_NOT_CONNECTED cpu_to_le32(0xC01E0338)
+#define STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0339)
+#define STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE cpu_to_le32(0xC01E033A)
+#define STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE cpu_to_le32(0xC01E033B)
+#define STATUS_GRAPHICS_INVALID_STRIDE cpu_to_le32(0xC01E033C)
+#define STATUS_GRAPHICS_INVALID_PIXELFORMAT cpu_to_le32(0xC01E033D)
+#define STATUS_GRAPHICS_INVALID_COLORBASIS cpu_to_le32(0xC01E033E)
+#define STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE cpu_to_le32(0xC01E033F)
+#define STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0340)
+#define STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT cpu_to_le32(0xC01E0341)
+#define STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE cpu_to_le32(0xC01E0342)
+#define STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN cpu_to_le32(0xC01E0343)
+#define STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL cpu_to_le32(0xC01E0344)
+#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION cpu_to_le32(0xC01E0345)
+#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED cpu_to_le32(0xC01E0346)
+#define STATUS_GRAPHICS_INVALID_GAMMA_RAMP cpu_to_le32(0xC01E0347)
+#define STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED cpu_to_le32(0xC01E0348)
+#define STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED cpu_to_le32(0xC01E0349)
+#define STATUS_GRAPHICS_MODE_NOT_IN_MODESET cpu_to_le32(0xC01E034A)
+#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON cpu_to_le32(0xC01E034D)
+#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE cpu_to_le32(0xC01E034E)
+#define STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE cpu_to_le32(0xC01E034F)
+#define STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS cpu_to_le32(0xC01E0350)
+#define STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING cpu_to_le32(0xC01E0352)
+#define STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED cpu_to_le32(0xC01E0353)
+#define STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS cpu_to_le32(0xC01E0354)
+#define STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT cpu_to_le32(0xC01E0355)
+#define STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM cpu_to_le32(0xC01E0356)
+#define STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN cpu_to_le32(0xC01E0357)
+#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT cpu_to_le32(0xC01E0358)
+#define STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED cpu_to_le32(0xC01E0359)
+#define STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION cpu_to_le32(0xC01E035A)
+#define STATUS_GRAPHICS_INVALID_CLIENT_TYPE cpu_to_le32(0xC01E035B)
+#define STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET cpu_to_le32(0xC01E035C)
+#define STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED cpu_to_le32(0xC01E0400)
+#define STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED cpu_to_le32(0xC01E0401)
+#define STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER cpu_to_le32(0xC01E0430)
+#define STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED cpu_to_le32(0xC01E0431)
+#define STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED cpu_to_le32(0xC01E0432)
+#define STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY cpu_to_le32(0xC01E0433)
+#define STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED cpu_to_le32(0xC01E0434)
+#define STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON cpu_to_le32(0xC01E0435)
+#define STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE cpu_to_le32(0xC01E0436)
+#define STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER cpu_to_le32(0xC01E0438)
+#define STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED cpu_to_le32(0xC01E043B)
+#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS cpu_to_le32(0xC01E051C)
+#define STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST cpu_to_le32(0xC01E051D)
+#define STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR cpu_to_le32(0xC01E051E)
+#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS cpu_to_le32(0xC01E051F)
+#define STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED cpu_to_le32(0xC01E0520)
+#define STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST cpu_to_le32(0xC01E0521)
+#define STATUS_GRAPHICS_OPM_NOT_SUPPORTED cpu_to_le32(0xC01E0500)
+#define STATUS_GRAPHICS_COPP_NOT_SUPPORTED cpu_to_le32(0xC01E0501)
+#define STATUS_GRAPHICS_UAB_NOT_SUPPORTED cpu_to_le32(0xC01E0502)
+#define STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS cpu_to_le32(0xC01E0503)
+#define STATUS_GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL cpu_to_le32(0xC01E0504)
+#define STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST cpu_to_le32(0xC01E0505)
+#define STATUS_GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME cpu_to_le32(0xC01E0506)
+#define STATUS_GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP cpu_to_le32(0xC01E0507)
+#define STATUS_GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED cpu_to_le32(0xC01E0508)
+#define STATUS_GRAPHICS_OPM_INVALID_POINTER cpu_to_le32(0xC01E050A)
+#define STATUS_GRAPHICS_OPM_INTERNAL_ERROR cpu_to_le32(0xC01E050B)
+#define STATUS_GRAPHICS_OPM_INVALID_HANDLE cpu_to_le32(0xC01E050C)
+#define STATUS_GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE cpu_to_le32(0xC01E050D)
+#define STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH cpu_to_le32(0xC01E050E)
+#define STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED cpu_to_le32(0xC01E050F)
+#define STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED cpu_to_le32(0xC01E0510)
+#define STATUS_GRAPHICS_PVP_HFS_FAILED cpu_to_le32(0xC01E0511)
+#define STATUS_GRAPHICS_OPM_INVALID_SRM cpu_to_le32(0xC01E0512)
+#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP cpu_to_le32(0xC01E0513)
+#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP cpu_to_le32(0xC01E0514)
+#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA cpu_to_le32(0xC01E0515)
+#define STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET cpu_to_le32(0xC01E0516)
+#define STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH cpu_to_le32(0xC01E0517)
+#define STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE cpu_to_le32(0xC01E0518)
+#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS cpu_to_le32(0xC01E051A)
+#define STATUS_GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS cpu_to_le32(0xC01E051B)
+#define STATUS_GRAPHICS_I2C_NOT_SUPPORTED cpu_to_le32(0xC01E0580)
+#define STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST cpu_to_le32(0xC01E0581)
+#define STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA cpu_to_le32(0xC01E0582)
+#define STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA cpu_to_le32(0xC01E0583)
+#define STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED cpu_to_le32(0xC01E0584)
+#define STATUS_GRAPHICS_DDCCI_INVALID_DATA cpu_to_le32(0xC01E0585)
+#define STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE cpu_to_le32(0xC01E0586)
+#define STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING cpu_to_le32(0xC01E0587)
+#define STATUS_GRAPHICS_MCA_INTERNAL_ERROR cpu_to_le32(0xC01E0588)
+#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND cpu_to_le32(0xC01E0589)
+#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH cpu_to_le32(0xC01E058A)
+#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM cpu_to_le32(0xC01E058B)
+#define STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE cpu_to_le32(0xC01E058C)
+#define STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS cpu_to_le32(0xC01E058D)
+#define STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED cpu_to_le32(0xC01E05E0)
+#define STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME cpu_to_le32(0xC01E05E1)
+#define STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP cpu_to_le32(0xC01E05E2)
+#define STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED cpu_to_le32(0xC01E05E3)
+#define STATUS_GRAPHICS_INVALID_POINTER cpu_to_le32(0xC01E05E4)
+#define STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE cpu_to_le32(0xC01E05E5)
+#define STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL cpu_to_le32(0xC01E05E6)
+#define STATUS_GRAPHICS_INTERNAL_ERROR cpu_to_le32(0xC01E05E7)
+#define STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS cpu_to_le32(0xC01E05E8)
+#define STATUS_FVE_LOCKED_VOLUME cpu_to_le32(0xC0210000)
+#define STATUS_FVE_NOT_ENCRYPTED cpu_to_le32(0xC0210001)
+#define STATUS_FVE_BAD_INFORMATION cpu_to_le32(0xC0210002)
+#define STATUS_FVE_TOO_SMALL cpu_to_le32(0xC0210003)
+#define STATUS_FVE_FAILED_WRONG_FS cpu_to_le32(0xC0210004)
+#define STATUS_FVE_FAILED_BAD_FS cpu_to_le32(0xC0210005)
+#define STATUS_FVE_FS_NOT_EXTENDED cpu_to_le32(0xC0210006)
+#define STATUS_FVE_FS_MOUNTED cpu_to_le32(0xC0210007)
+#define STATUS_FVE_NO_LICENSE cpu_to_le32(0xC0210008)
+#define STATUS_FVE_ACTION_NOT_ALLOWED cpu_to_le32(0xC0210009)
+#define STATUS_FVE_BAD_DATA cpu_to_le32(0xC021000A)
+#define STATUS_FVE_VOLUME_NOT_BOUND cpu_to_le32(0xC021000B)
+#define STATUS_FVE_NOT_DATA_VOLUME cpu_to_le32(0xC021000C)
+#define STATUS_FVE_CONV_READ_ERROR cpu_to_le32(0xC021000D)
+#define STATUS_FVE_CONV_WRITE_ERROR cpu_to_le32(0xC021000E)
+#define STATUS_FVE_OVERLAPPED_UPDATE cpu_to_le32(0xC021000F)
+#define STATUS_FVE_FAILED_SECTOR_SIZE cpu_to_le32(0xC0210010)
+#define STATUS_FVE_FAILED_AUTHENTICATION cpu_to_le32(0xC0210011)
+#define STATUS_FVE_NOT_OS_VOLUME cpu_to_le32(0xC0210012)
+#define STATUS_FVE_KEYFILE_NOT_FOUND cpu_to_le32(0xC0210013)
+#define STATUS_FVE_KEYFILE_INVALID cpu_to_le32(0xC0210014)
+#define STATUS_FVE_KEYFILE_NO_VMK cpu_to_le32(0xC0210015)
+#define STATUS_FVE_TPM_DISABLED cpu_to_le32(0xC0210016)
+#define STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO cpu_to_le32(0xC0210017)
+#define STATUS_FVE_TPM_INVALID_PCR cpu_to_le32(0xC0210018)
+#define STATUS_FVE_TPM_NO_VMK cpu_to_le32(0xC0210019)
+#define STATUS_FVE_PIN_INVALID cpu_to_le32(0xC021001A)
+#define STATUS_FVE_AUTH_INVALID_APPLICATION cpu_to_le32(0xC021001B)
+#define STATUS_FVE_AUTH_INVALID_CONFIG cpu_to_le32(0xC021001C)
+#define STATUS_FVE_DEBUGGER_ENABLED cpu_to_le32(0xC021001D)
+#define STATUS_FVE_DRY_RUN_FAILED cpu_to_le32(0xC021001E)
+#define STATUS_FVE_BAD_METADATA_POINTER cpu_to_le32(0xC021001F)
+#define STATUS_FVE_OLD_METADATA_COPY cpu_to_le32(0xC0210020)
+#define STATUS_FVE_REBOOT_REQUIRED cpu_to_le32(0xC0210021)
+#define STATUS_FVE_RAW_ACCESS cpu_to_le32(0xC0210022)
+#define STATUS_FVE_RAW_BLOCKED cpu_to_le32(0xC0210023)
+#define STATUS_FWP_CALLOUT_NOT_FOUND cpu_to_le32(0xC0220001)
+#define STATUS_FWP_CONDITION_NOT_FOUND cpu_to_le32(0xC0220002)
+#define STATUS_FWP_FILTER_NOT_FOUND cpu_to_le32(0xC0220003)
+#define STATUS_FWP_LAYER_NOT_FOUND cpu_to_le32(0xC0220004)
+#define STATUS_FWP_PROVIDER_NOT_FOUND cpu_to_le32(0xC0220005)
+#define STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND cpu_to_le32(0xC0220006)
+#define STATUS_FWP_SUBLAYER_NOT_FOUND cpu_to_le32(0xC0220007)
+#define STATUS_FWP_NOT_FOUND cpu_to_le32(0xC0220008)
+#define STATUS_FWP_ALREADY_EXISTS cpu_to_le32(0xC0220009)
+#define STATUS_FWP_IN_USE cpu_to_le32(0xC022000A)
+#define STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS cpu_to_le32(0xC022000B)
+#define STATUS_FWP_WRONG_SESSION cpu_to_le32(0xC022000C)
+#define STATUS_FWP_NO_TXN_IN_PROGRESS cpu_to_le32(0xC022000D)
+#define STATUS_FWP_TXN_IN_PROGRESS cpu_to_le32(0xC022000E)
+#define STATUS_FWP_TXN_ABORTED cpu_to_le32(0xC022000F)
+#define STATUS_FWP_SESSION_ABORTED cpu_to_le32(0xC0220010)
+#define STATUS_FWP_INCOMPATIBLE_TXN cpu_to_le32(0xC0220011)
+#define STATUS_FWP_TIMEOUT cpu_to_le32(0xC0220012)
+#define STATUS_FWP_NET_EVENTS_DISABLED cpu_to_le32(0xC0220013)
+#define STATUS_FWP_INCOMPATIBLE_LAYER cpu_to_le32(0xC0220014)
+#define STATUS_FWP_KM_CLIENTS_ONLY cpu_to_le32(0xC0220015)
+#define STATUS_FWP_LIFETIME_MISMATCH cpu_to_le32(0xC0220016)
+#define STATUS_FWP_BUILTIN_OBJECT cpu_to_le32(0xC0220017)
+#define STATUS_FWP_TOO_MANY_BOOTTIME_FILTERS cpu_to_le32(0xC0220018)
+#define STATUS_FWP_TOO_MANY_CALLOUTS cpu_to_le32(0xC0220018)
+#define STATUS_FWP_NOTIFICATION_DROPPED cpu_to_le32(0xC0220019)
+#define STATUS_FWP_TRAFFIC_MISMATCH cpu_to_le32(0xC022001A)
+#define STATUS_FWP_INCOMPATIBLE_SA_STATE cpu_to_le32(0xC022001B)
+#define STATUS_FWP_NULL_POINTER cpu_to_le32(0xC022001C)
+#define STATUS_FWP_INVALID_ENUMERATOR cpu_to_le32(0xC022001D)
+#define STATUS_FWP_INVALID_FLAGS cpu_to_le32(0xC022001E)
+#define STATUS_FWP_INVALID_NET_MASK cpu_to_le32(0xC022001F)
+#define STATUS_FWP_INVALID_RANGE cpu_to_le32(0xC0220020)
+#define STATUS_FWP_INVALID_INTERVAL cpu_to_le32(0xC0220021)
+#define STATUS_FWP_ZERO_LENGTH_ARRAY cpu_to_le32(0xC0220022)
+#define STATUS_FWP_NULL_DISPLAY_NAME cpu_to_le32(0xC0220023)
+#define STATUS_FWP_INVALID_ACTION_TYPE cpu_to_le32(0xC0220024)
+#define STATUS_FWP_INVALID_WEIGHT cpu_to_le32(0xC0220025)
+#define STATUS_FWP_MATCH_TYPE_MISMATCH cpu_to_le32(0xC0220026)
+#define STATUS_FWP_TYPE_MISMATCH cpu_to_le32(0xC0220027)
+#define STATUS_FWP_OUT_OF_BOUNDS cpu_to_le32(0xC0220028)
+#define STATUS_FWP_RESERVED cpu_to_le32(0xC0220029)
+#define STATUS_FWP_DUPLICATE_CONDITION cpu_to_le32(0xC022002A)
+#define STATUS_FWP_DUPLICATE_KEYMOD cpu_to_le32(0xC022002B)
+#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER cpu_to_le32(0xC022002C)
+#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER cpu_to_le32(0xC022002D)
+#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER cpu_to_le32(0xC022002E)
+#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT cpu_to_le32(0xC022002F)
+#define STATUS_FWP_INCOMPATIBLE_AUTH_METHOD cpu_to_le32(0xC0220030)
+#define STATUS_FWP_INCOMPATIBLE_DH_GROUP cpu_to_le32(0xC0220031)
+#define STATUS_FWP_EM_NOT_SUPPORTED cpu_to_le32(0xC0220032)
+#define STATUS_FWP_NEVER_MATCH cpu_to_le32(0xC0220033)
+#define STATUS_FWP_PROVIDER_CONTEXT_MISMATCH cpu_to_le32(0xC0220034)
+#define STATUS_FWP_INVALID_PARAMETER cpu_to_le32(0xC0220035)
+#define STATUS_FWP_TOO_MANY_SUBLAYERS cpu_to_le32(0xC0220036)
+#define STATUS_FWP_CALLOUT_NOTIFICATION_FAILED cpu_to_le32(0xC0220037)
+#define STATUS_FWP_INCOMPATIBLE_AUTH_CONFIG cpu_to_le32(0xC0220038)
+#define STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG cpu_to_le32(0xC0220039)
+#define STATUS_FWP_TCPIP_NOT_READY cpu_to_le32(0xC0220100)
+#define STATUS_FWP_INJECT_HANDLE_CLOSING cpu_to_le32(0xC0220101)
+#define STATUS_FWP_INJECT_HANDLE_STALE cpu_to_le32(0xC0220102)
+#define STATUS_FWP_CANNOT_PEND cpu_to_le32(0xC0220103)
+#define STATUS_NDIS_CLOSING cpu_to_le32(0xC0230002)
+#define STATUS_NDIS_BAD_VERSION cpu_to_le32(0xC0230004)
+#define STATUS_NDIS_BAD_CHARACTERISTICS cpu_to_le32(0xC0230005)
+#define STATUS_NDIS_ADAPTER_NOT_FOUND cpu_to_le32(0xC0230006)
+#define STATUS_NDIS_OPEN_FAILED cpu_to_le32(0xC0230007)
+#define STATUS_NDIS_DEVICE_FAILED cpu_to_le32(0xC0230008)
+#define STATUS_NDIS_MULTICAST_FULL cpu_to_le32(0xC0230009)
+#define STATUS_NDIS_MULTICAST_EXISTS cpu_to_le32(0xC023000A)
+#define STATUS_NDIS_MULTICAST_NOT_FOUND cpu_to_le32(0xC023000B)
+#define STATUS_NDIS_REQUEST_ABORTED cpu_to_le32(0xC023000C)
+#define STATUS_NDIS_RESET_IN_PROGRESS cpu_to_le32(0xC023000D)
+#define STATUS_NDIS_INVALID_PACKET cpu_to_le32(0xC023000F)
+#define STATUS_NDIS_INVALID_DEVICE_REQUEST cpu_to_le32(0xC0230010)
+#define STATUS_NDIS_ADAPTER_NOT_READY cpu_to_le32(0xC0230011)
+#define STATUS_NDIS_INVALID_LENGTH cpu_to_le32(0xC0230014)
+#define STATUS_NDIS_INVALID_DATA cpu_to_le32(0xC0230015)
+#define STATUS_NDIS_BUFFER_TOO_SHORT cpu_to_le32(0xC0230016)
+#define STATUS_NDIS_INVALID_OID cpu_to_le32(0xC0230017)
+#define STATUS_NDIS_ADAPTER_REMOVED cpu_to_le32(0xC0230018)
+#define STATUS_NDIS_UNSUPPORTED_MEDIA cpu_to_le32(0xC0230019)
+#define STATUS_NDIS_GROUP_ADDRESS_IN_USE cpu_to_le32(0xC023001A)
+#define STATUS_NDIS_FILE_NOT_FOUND cpu_to_le32(0xC023001B)
+#define STATUS_NDIS_ERROR_READING_FILE cpu_to_le32(0xC023001C)
+#define STATUS_NDIS_ALREADY_MAPPED cpu_to_le32(0xC023001D)
+#define STATUS_NDIS_RESOURCE_CONFLICT cpu_to_le32(0xC023001E)
+#define STATUS_NDIS_MEDIA_DISCONNECTED cpu_to_le32(0xC023001F)
+#define STATUS_NDIS_INVALID_ADDRESS cpu_to_le32(0xC0230022)
+#define STATUS_NDIS_PAUSED cpu_to_le32(0xC023002A)
+#define STATUS_NDIS_INTERFACE_NOT_FOUND cpu_to_le32(0xC023002B)
+#define STATUS_NDIS_UNSUPPORTED_REVISION cpu_to_le32(0xC023002C)
+#define STATUS_NDIS_INVALID_PORT cpu_to_le32(0xC023002D)
+#define STATUS_NDIS_INVALID_PORT_STATE cpu_to_le32(0xC023002E)
+#define STATUS_NDIS_LOW_POWER_STATE cpu_to_le32(0xC023002F)
+#define STATUS_NDIS_NOT_SUPPORTED cpu_to_le32(0xC02300BB)
+#define STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED cpu_to_le32(0xC0232000)
+#define STATUS_NDIS_DOT11_MEDIA_IN_USE cpu_to_le32(0xC0232001)
+#define STATUS_NDIS_DOT11_POWER_STATE_INVALID cpu_to_le32(0xC0232002)
+#define STATUS_IPSEC_BAD_SPI cpu_to_le32(0xC0360001)
+#define STATUS_IPSEC_SA_LIFETIME_EXPIRED cpu_to_le32(0xC0360002)
+#define STATUS_IPSEC_WRONG_SA cpu_to_le32(0xC0360003)
+#define STATUS_IPSEC_REPLAY_CHECK_FAILED cpu_to_le32(0xC0360004)
+#define STATUS_IPSEC_INVALID_PACKET cpu_to_le32(0xC0360005)
+#define STATUS_IPSEC_INTEGRITY_CHECK_FAILED cpu_to_le32(0xC0360006)
+#define STATUS_IPSEC_CLEAR_TEXT_DROP cpu_to_le32(0xC0360007)
diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c
new file mode 100644
index 000000000000..790acf65a092
--- /dev/null
+++ b/fs/smb/client/smb2transport.c
@@ -0,0 +1,934 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002, 2011
+ * Etersoft, 2012
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Jeremy Allison (jra@samba.org) 2006
+ * Pavel Shilovsky (pshilovsky@samba.org) 2012
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/net.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <asm/processor.h>
+#include <linux/mempool.h>
+#include <linux/highmem.h>
+#include <crypto/aead.h>
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
+#include "cifs_debug.h"
+#include "smb2status.h"
+#include "smb2glob.h"
+
+static int
+smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
+{
+ struct cifs_secmech *p = &server->secmech;
+ int rc;
+
+ rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);
+ if (rc)
+ goto err;
+
+ rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);
+ if (rc)
+ goto err;
+
+ return 0;
+err:
+ cifs_free_hash(&p->hmacsha256);
+ return rc;
+}
+
+int
+smb311_crypto_shash_allocate(struct TCP_Server_Info *server)
+{
+ struct cifs_secmech *p = &server->secmech;
+ int rc = 0;
+
+ rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);
+ if (rc)
+ return rc;
+
+ rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);
+ if (rc)
+ goto err;
+
+ rc = cifs_alloc_hash("sha512", &p->sha512);
+ if (rc)
+ goto err;
+
+ return 0;
+
+err:
+ cifs_free_hash(&p->aes_cmac);
+ cifs_free_hash(&p->hmacsha256);
+ return rc;
+}
+
+
+static
+int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
+{
+ struct cifs_chan *chan;
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses = NULL;
+ int i;
+ int rc = 0;
+ bool is_binding = false;
+
+ spin_lock(&cifs_tcp_ses_lock);
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+ if (ses->Suid == ses_id)
+ goto found;
+ }
+ cifs_server_dbg(VFS, "%s: Could not find session 0x%llx\n",
+ __func__, ses_id);
+ rc = -ENOENT;
+ goto out;
+
+found:
+ spin_lock(&ses->ses_lock);
+ spin_lock(&ses->chan_lock);
+
+ is_binding = (cifs_chan_needs_reconnect(ses, server) &&
+ ses->ses_status == SES_GOOD);
+ if (is_binding) {
+ /*
+ * If we are in the process of binding a new channel
+ * to an existing session, use the master connection
+ * session key
+ */
+ memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+ goto out;
+ }
+
+ /*
+ * Otherwise, use the channel key.
+ */
+
+ for (i = 0; i < ses->chan_count; i++) {
+ chan = ses->chans + i;
+ if (chan->server == server) {
+ memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+ goto out;
+ }
+ }
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+
+ cifs_dbg(VFS,
+ "%s: Could not find channel signing key for session 0x%llx\n",
+ __func__, ses_id);
+ rc = -ENOENT;
+
+out:
+ spin_unlock(&cifs_tcp_ses_lock);
+ return rc;
+}
+
+static struct cifs_ses *
+smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
+{
+ struct TCP_Server_Info *pserver;
+ struct cifs_ses *ses;
+
+ /* If server is a channel, select the primary channel */
+ pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
+
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+ if (ses->Suid != ses_id)
+ continue;
+ ++ses->ses_count;
+ return ses;
+ }
+
+ return NULL;
+}
+
+struct cifs_ses *
+smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
+{
+ struct cifs_ses *ses;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ ses = smb2_find_smb_ses_unlocked(server, ses_id);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ return ses;
+}
+
+static struct cifs_tcon *
+smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
+{
+ struct cifs_tcon *tcon;
+
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ if (tcon->tid != tid)
+ continue;
+ ++tcon->tc_count;
+ return tcon;
+ }
+
+ return NULL;
+}
+
+/*
+ * Obtain tcon corresponding to the tid in the given
+ * cifs_ses
+ */
+
+struct cifs_tcon *
+smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
+{
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ ses = smb2_find_smb_ses_unlocked(server, ses_id);
+ if (!ses) {
+ spin_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+ }
+ tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
+ if (!tcon) {
+ cifs_put_smb_ses(ses);
+ spin_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ /* tcon already has a ref to ses, so we don't need ses anymore */
+ cifs_put_smb_ses(ses);
+
+ return tcon;
+}
+
+int
+smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
+ bool allocate_crypto)
+{
+ int rc;
+ unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
+ unsigned char *sigptr = smb2_signature;
+ struct kvec *iov = rqst->rq_iov;
+ struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
+ struct cifs_ses *ses;
+ struct shash_desc *shash = NULL;
+ struct smb_rqst drqst;
+
+ ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId));
+ if (unlikely(!ses)) {
+ cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
+ return -ENOENT;
+ }
+
+ memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
+ memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
+
+ if (allocate_crypto) {
+ rc = cifs_alloc_hash("hmac(sha256)", &shash);
+ if (rc) {
+ cifs_server_dbg(VFS,
+ "%s: sha256 alloc failed\n", __func__);
+ goto out;
+ }
+ } else {
+ shash = server->secmech.hmacsha256;
+ }
+
+ rc = crypto_shash_setkey(shash->tfm, ses->auth_key.response,
+ SMB2_NTLMV2_SESSKEY_SIZE);
+ if (rc) {
+ cifs_server_dbg(VFS,
+ "%s: Could not update with response\n",
+ __func__);
+ goto out;
+ }
+
+ rc = crypto_shash_init(shash);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);
+ goto out;
+ }
+
+ /*
+ * For SMB2+, __cifs_calc_signature() expects to sign only the actual
+ * data, that is, iov[0] should not contain a rfc1002 length.
+ *
+ * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
+ * __cifs_calc_signature().
+ */
+ drqst = *rqst;
+ if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
+ rc = crypto_shash_update(shash, iov[0].iov_base,
+ iov[0].iov_len);
+ if (rc) {
+ cifs_server_dbg(VFS,
+ "%s: Could not update with payload\n",
+ __func__);
+ goto out;
+ }
+ drqst.rq_iov++;
+ drqst.rq_nvec--;
+ }
+
+ rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
+ if (!rc)
+ memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
+
+out:
+ if (allocate_crypto)
+ cifs_free_hash(&shash);
+ if (ses)
+ cifs_put_smb_ses(ses);
+ return rc;
+}
+
+static int generate_key(struct cifs_ses *ses, struct kvec label,
+ struct kvec context, __u8 *key, unsigned int key_size)
+{
+ unsigned char zero = 0x0;
+ __u8 i[4] = {0, 0, 0, 1};
+ __u8 L128[4] = {0, 0, 0, 128};
+ __u8 L256[4] = {0, 0, 1, 0};
+ int rc = 0;
+ unsigned char prfhash[SMB2_HMACSHA256_SIZE];
+ unsigned char *hashptr = prfhash;
+ struct TCP_Server_Info *server = ses->server;
+
+ memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
+ memset(key, 0x0, key_size);
+
+ rc = smb3_crypto_shash_allocate(server);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__);
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_setkey(server->secmech.hmacsha256->tfm,
+ ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__);
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_init(server->secmech.hmacsha256);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_update(server->secmech.hmacsha256, i, 4);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__);
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_update(server->secmech.hmacsha256, label.iov_base, label.iov_len);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__);
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_update(server->secmech.hmacsha256, &zero, 1);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__);
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_update(server->secmech.hmacsha256, context.iov_base, context.iov_len);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__);
+ goto smb3signkey_ret;
+ }
+
+ if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
+ (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
+ rc = crypto_shash_update(server->secmech.hmacsha256, L256, 4);
+ } else {
+ rc = crypto_shash_update(server->secmech.hmacsha256, L128, 4);
+ }
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_final(server->secmech.hmacsha256, hashptr);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
+ goto smb3signkey_ret;
+ }
+
+ memcpy(key, hashptr, key_size);
+
+smb3signkey_ret:
+ return rc;
+}
+
+struct derivation {
+ struct kvec label;
+ struct kvec context;
+};
+
+struct derivation_triplet {
+ struct derivation signing;
+ struct derivation encryption;
+ struct derivation decryption;
+};
+
+static int
+generate_smb3signingkey(struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const struct derivation_triplet *ptriplet)
+{
+ int rc;
+ bool is_binding = false;
+ int chan_index = 0;
+
+ spin_lock(&ses->ses_lock);
+ spin_lock(&ses->chan_lock);
+ is_binding = (cifs_chan_needs_reconnect(ses, server) &&
+ ses->ses_status == SES_GOOD);
+
+ chan_index = cifs_ses_get_chan_index(ses, server);
+ /* TODO: introduce ref counting for channels when the can be freed */
+ spin_unlock(&ses->chan_lock);
+ spin_unlock(&ses->ses_lock);
+
+ /*
+ * All channels use the same encryption/decryption keys but
+ * they have their own signing key.
+ *
+ * When we generate the keys, check if it is for a new channel
+ * (binding) in which case we only need to generate a signing
+ * key and store it in the channel as to not overwrite the
+ * master connection signing key stored in the session
+ */
+
+ if (is_binding) {
+ rc = generate_key(ses, ptriplet->signing.label,
+ ptriplet->signing.context,
+ ses->chans[chan_index].signkey,
+ SMB3_SIGN_KEY_SIZE);
+ if (rc)
+ return rc;
+ } else {
+ rc = generate_key(ses, ptriplet->signing.label,
+ ptriplet->signing.context,
+ ses->smb3signingkey,
+ SMB3_SIGN_KEY_SIZE);
+ if (rc)
+ return rc;
+
+ /* safe to access primary channel, since it will never go away */
+ spin_lock(&ses->chan_lock);
+ memcpy(ses->chans[chan_index].signkey, ses->smb3signingkey,
+ SMB3_SIGN_KEY_SIZE);
+ spin_unlock(&ses->chan_lock);
+
+ rc = generate_key(ses, ptriplet->encryption.label,
+ ptriplet->encryption.context,
+ ses->smb3encryptionkey,
+ SMB3_ENC_DEC_KEY_SIZE);
+ rc = generate_key(ses, ptriplet->decryption.label,
+ ptriplet->decryption.context,
+ ses->smb3decryptionkey,
+ SMB3_ENC_DEC_KEY_SIZE);
+ if (rc)
+ return rc;
+ }
+
+ if (rc)
+ return rc;
+
+#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
+ cifs_dbg(VFS, "%s: dumping generated AES session keys\n", __func__);
+ /*
+ * The session id is opaque in terms of endianness, so we can't
+ * print it as a long long. we dump it as we got it on the wire
+ */
+ cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid),
+ &ses->Suid);
+ cifs_dbg(VFS, "Cipher type %d\n", server->cipher_type);
+ cifs_dbg(VFS, "Session Key %*ph\n",
+ SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
+ cifs_dbg(VFS, "Signing Key %*ph\n",
+ SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
+ if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
+ (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
+ cifs_dbg(VFS, "ServerIn Key %*ph\n",
+ SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3encryptionkey);
+ cifs_dbg(VFS, "ServerOut Key %*ph\n",
+ SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3decryptionkey);
+ } else {
+ cifs_dbg(VFS, "ServerIn Key %*ph\n",
+ SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);
+ cifs_dbg(VFS, "ServerOut Key %*ph\n",
+ SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey);
+ }
+#endif
+ return rc;
+}
+
+int
+generate_smb30signingkey(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+
+{
+ struct derivation_triplet triplet;
+ struct derivation *d;
+
+ d = &triplet.signing;
+ d->label.iov_base = "SMB2AESCMAC";
+ d->label.iov_len = 12;
+ d->context.iov_base = "SmbSign";
+ d->context.iov_len = 8;
+
+ d = &triplet.encryption;
+ d->label.iov_base = "SMB2AESCCM";
+ d->label.iov_len = 11;
+ d->context.iov_base = "ServerIn ";
+ d->context.iov_len = 10;
+
+ d = &triplet.decryption;
+ d->label.iov_base = "SMB2AESCCM";
+ d->label.iov_len = 11;
+ d->context.iov_base = "ServerOut";
+ d->context.iov_len = 10;
+
+ return generate_smb3signingkey(ses, server, &triplet);
+}
+
+int
+generate_smb311signingkey(struct cifs_ses *ses,
+ struct TCP_Server_Info *server)
+
+{
+ struct derivation_triplet triplet;
+ struct derivation *d;
+
+ d = &triplet.signing;
+ d->label.iov_base = "SMBSigningKey";
+ d->label.iov_len = 14;
+ d->context.iov_base = ses->preauth_sha_hash;
+ d->context.iov_len = 64;
+
+ d = &triplet.encryption;
+ d->label.iov_base = "SMBC2SCipherKey";
+ d->label.iov_len = 16;
+ d->context.iov_base = ses->preauth_sha_hash;
+ d->context.iov_len = 64;
+
+ d = &triplet.decryption;
+ d->label.iov_base = "SMBS2CCipherKey";
+ d->label.iov_len = 16;
+ d->context.iov_base = ses->preauth_sha_hash;
+ d->context.iov_len = 64;
+
+ return generate_smb3signingkey(ses, server, &triplet);
+}
+
+int
+smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
+ bool allocate_crypto)
+{
+ int rc;
+ unsigned char smb3_signature[SMB2_CMACAES_SIZE];
+ unsigned char *sigptr = smb3_signature;
+ struct kvec *iov = rqst->rq_iov;
+ struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
+ struct shash_desc *shash = NULL;
+ struct smb_rqst drqst;
+ u8 key[SMB3_SIGN_KEY_SIZE];
+
+ rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key);
+ if (unlikely(rc)) {
+ cifs_server_dbg(VFS, "%s: Could not get signing key\n", __func__);
+ return rc;
+ }
+
+ if (allocate_crypto) {
+ rc = cifs_alloc_hash("cmac(aes)", &shash);
+ if (rc)
+ return rc;
+ } else {
+ shash = server->secmech.aes_cmac;
+ }
+
+ memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
+ memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
+
+ rc = crypto_shash_setkey(shash->tfm, key, SMB2_CMACAES_SIZE);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
+ goto out;
+ }
+
+ /*
+ * we already allocate aes_cmac when we init smb3 signing key,
+ * so unlike smb2 case we do not have to check here if secmech are
+ * initialized
+ */
+ rc = crypto_shash_init(shash);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
+ goto out;
+ }
+
+ /*
+ * For SMB2+, __cifs_calc_signature() expects to sign only the actual
+ * data, that is, iov[0] should not contain a rfc1002 length.
+ *
+ * Sign the rfc1002 length prior to passing the data (iov[1-N]) down to
+ * __cifs_calc_signature().
+ */
+ drqst = *rqst;
+ if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
+ rc = crypto_shash_update(shash, iov[0].iov_base,
+ iov[0].iov_len);
+ if (rc) {
+ cifs_server_dbg(VFS, "%s: Could not update with payload\n",
+ __func__);
+ goto out;
+ }
+ drqst.rq_iov++;
+ drqst.rq_nvec--;
+ }
+
+ rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
+ if (!rc)
+ memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
+
+out:
+ if (allocate_crypto)
+ cifs_free_hash(&shash);
+ return rc;
+}
+
+/* must be called with server->srv_mutex held */
+static int
+smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
+{
+ int rc = 0;
+ struct smb2_hdr *shdr;
+ struct smb2_sess_setup_req *ssr;
+ bool is_binding;
+ bool is_signed;
+
+ shdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
+ ssr = (struct smb2_sess_setup_req *)shdr;
+
+ is_binding = shdr->Command == SMB2_SESSION_SETUP &&
+ (ssr->Flags & SMB2_SESSION_REQ_FLAG_BINDING);
+ is_signed = shdr->Flags & SMB2_FLAGS_SIGNED;
+
+ if (!is_signed)
+ return 0;
+ spin_lock(&server->srv_lock);
+ if (server->ops->need_neg &&
+ server->ops->need_neg(server)) {
+ spin_unlock(&server->srv_lock);
+ return 0;
+ }
+ spin_unlock(&server->srv_lock);
+ if (!is_binding && !server->session_estab) {
+ strncpy(shdr->Signature, "BSRSPYL", 8);
+ return 0;
+ }
+
+ rc = server->ops->calc_signature(rqst, server, false);
+
+ return rc;
+}
+
+int
+smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
+{
+ unsigned int rc;
+ char server_response_sig[SMB2_SIGNATURE_SIZE];
+ struct smb2_hdr *shdr =
+ (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
+
+ if ((shdr->Command == SMB2_NEGOTIATE) ||
+ (shdr->Command == SMB2_SESSION_SETUP) ||
+ (shdr->Command == SMB2_OPLOCK_BREAK) ||
+ server->ignore_signature ||
+ (!server->session_estab))
+ return 0;
+
+ /*
+ * BB what if signatures are supposed to be on for session but
+ * server does not send one? BB
+ */
+
+ /* Do not need to verify session setups with signature "BSRSPYL " */
+ if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
+ cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
+ shdr->Command);
+
+ /*
+ * Save off the origiginal signature so we can modify the smb and check
+ * our calculated signature against what the server sent.
+ */
+ memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);
+
+ memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
+
+ rc = server->ops->calc_signature(rqst, server, true);
+
+ if (rc)
+ return rc;
+
+ if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE)) {
+ cifs_dbg(VFS, "sign fail cmd 0x%x message id 0x%llx\n",
+ shdr->Command, shdr->MessageId);
+ return -EACCES;
+ } else
+ return 0;
+}
+
+/*
+ * Set message id for the request. Should be called after wait_for_free_request
+ * and when srv_mutex is held.
+ */
+static inline void
+smb2_seq_num_into_buf(struct TCP_Server_Info *server,
+ struct smb2_hdr *shdr)
+{
+ unsigned int i, num = le16_to_cpu(shdr->CreditCharge);
+
+ shdr->MessageId = get_next_mid64(server);
+ /* skip message numbers according to CreditCharge field */
+ for (i = 1; i < num; i++)
+ get_next_mid(server);
+}
+
+static struct mid_q_entry *
+smb2_mid_entry_alloc(const struct smb2_hdr *shdr,
+ struct TCP_Server_Info *server)
+{
+ struct mid_q_entry *temp;
+ unsigned int credits = le16_to_cpu(shdr->CreditCharge);
+
+ if (server == NULL) {
+ cifs_dbg(VFS, "Null TCP session in smb2_mid_entry_alloc\n");
+ return NULL;
+ }
+
+ temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
+ memset(temp, 0, sizeof(struct mid_q_entry));
+ kref_init(&temp->refcount);
+ temp->mid = le64_to_cpu(shdr->MessageId);
+ temp->credits = credits > 0 ? credits : 1;
+ temp->pid = current->pid;
+ temp->command = shdr->Command; /* Always LE */
+ temp->when_alloc = jiffies;
+ temp->server = server;
+
+ /*
+ * The default is for the mid to be synchronous, so the
+ * default callback just wakes up the current task.
+ */
+ get_task_struct(current);
+ temp->creator = current;
+ temp->callback = cifs_wake_up_task;
+ temp->callback_data = current;
+
+ atomic_inc(&mid_count);
+ temp->mid_state = MID_REQUEST_ALLOCATED;
+ trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId),
+ le64_to_cpu(shdr->SessionId),
+ le16_to_cpu(shdr->Command), temp->mid);
+ return temp;
+}
+
+static int
+smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server,
+ struct smb2_hdr *shdr, struct mid_q_entry **mid)
+{
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsExiting) {
+ spin_unlock(&server->srv_lock);
+ return -ENOENT;
+ }
+
+ if (server->tcpStatus == CifsNeedReconnect) {
+ spin_unlock(&server->srv_lock);
+ cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
+ return -EAGAIN;
+ }
+
+ if (server->tcpStatus == CifsNeedNegotiate &&
+ shdr->Command != SMB2_NEGOTIATE) {
+ spin_unlock(&server->srv_lock);
+ return -EAGAIN;
+ }
+ spin_unlock(&server->srv_lock);
+
+ spin_lock(&ses->ses_lock);
+ if (ses->ses_status == SES_NEW) {
+ if ((shdr->Command != SMB2_SESSION_SETUP) &&
+ (shdr->Command != SMB2_NEGOTIATE)) {
+ spin_unlock(&ses->ses_lock);
+ return -EAGAIN;
+ }
+ /* else ok - we are setting up session */
+ }
+
+ if (ses->ses_status == SES_EXITING) {
+ if (shdr->Command != SMB2_LOGOFF) {
+ spin_unlock(&ses->ses_lock);
+ return -EAGAIN;
+ }
+ /* else ok - we are shutting down the session */
+ }
+ spin_unlock(&ses->ses_lock);
+
+ *mid = smb2_mid_entry_alloc(shdr, server);
+ if (*mid == NULL)
+ return -ENOMEM;
+ spin_lock(&server->mid_lock);
+ list_add_tail(&(*mid)->qhead, &server->pending_mid_q);
+ spin_unlock(&server->mid_lock);
+
+ return 0;
+}
+
+int
+smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
+ bool log_error)
+{
+ unsigned int len = mid->resp_buf_size;
+ struct kvec iov[1];
+ struct smb_rqst rqst = { .rq_iov = iov,
+ .rq_nvec = 1 };
+
+ iov[0].iov_base = (char *)mid->resp_buf;
+ iov[0].iov_len = len;
+
+ dump_smb(mid->resp_buf, min_t(u32, 80, len));
+ /* convert the length into a more usable form */
+ if (len > 24 && server->sign && !mid->decrypted) {
+ int rc;
+
+ rc = smb2_verify_signature(&rqst, server);
+ if (rc)
+ cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",
+ rc);
+ }
+
+ return map_smb2_to_linux_error(mid->resp_buf, log_error);
+}
+
+struct mid_q_entry *
+smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server,
+ struct smb_rqst *rqst)
+{
+ int rc;
+ struct smb2_hdr *shdr =
+ (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
+ struct mid_q_entry *mid;
+
+ smb2_seq_num_into_buf(server, shdr);
+
+ rc = smb2_get_mid_entry(ses, server, shdr, &mid);
+ if (rc) {
+ revert_current_mid_from_hdr(server, shdr);
+ return ERR_PTR(rc);
+ }
+
+ rc = smb2_sign_rqst(rqst, server);
+ if (rc) {
+ revert_current_mid_from_hdr(server, shdr);
+ delete_mid(mid);
+ return ERR_PTR(rc);
+ }
+
+ return mid;
+}
+
+struct mid_q_entry *
+smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
+{
+ int rc;
+ struct smb2_hdr *shdr =
+ (struct smb2_hdr *)rqst->rq_iov[0].iov_base;
+ struct mid_q_entry *mid;
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsNeedNegotiate &&
+ shdr->Command != SMB2_NEGOTIATE) {
+ spin_unlock(&server->srv_lock);
+ return ERR_PTR(-EAGAIN);
+ }
+ spin_unlock(&server->srv_lock);
+
+ smb2_seq_num_into_buf(server, shdr);
+
+ mid = smb2_mid_entry_alloc(shdr, server);
+ if (mid == NULL) {
+ revert_current_mid_from_hdr(server, shdr);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ rc = smb2_sign_rqst(rqst, server);
+ if (rc) {
+ revert_current_mid_from_hdr(server, shdr);
+ release_mid(mid);
+ return ERR_PTR(rc);
+ }
+
+ return mid;
+}
+
+int
+smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
+{
+ struct crypto_aead *tfm;
+
+ if (!server->secmech.enc) {
+ if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
+ (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
+ tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
+ else
+ tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
+ if (IS_ERR(tfm)) {
+ cifs_server_dbg(VFS, "%s: Failed alloc encrypt aead\n",
+ __func__);
+ return PTR_ERR(tfm);
+ }
+ server->secmech.enc = tfm;
+ }
+
+ if (!server->secmech.dec) {
+ if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
+ (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
+ tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
+ else
+ tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
+ if (IS_ERR(tfm)) {
+ crypto_free_aead(server->secmech.enc);
+ server->secmech.enc = NULL;
+ cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
+ __func__);
+ return PTR_ERR(tfm);
+ }
+ server->secmech.dec = tfm;
+ }
+
+ return 0;
+}
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
new file mode 100644
index 000000000000..cf923f211c51
--- /dev/null
+++ b/fs/smb/client/smbdirect.c
@@ -0,0 +1,2494 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017, Microsoft Corporation.
+ *
+ * Author(s): Long Li <longli@microsoft.com>
+ */
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include "smbdirect.h"
+#include "cifs_debug.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
+
+static struct smbd_response *get_empty_queue_buffer(
+ struct smbd_connection *info);
+static struct smbd_response *get_receive_buffer(
+ struct smbd_connection *info);
+static void put_receive_buffer(
+ struct smbd_connection *info,
+ struct smbd_response *response);
+static int allocate_receive_buffers(struct smbd_connection *info, int num_buf);
+static void destroy_receive_buffers(struct smbd_connection *info);
+
+static void put_empty_packet(
+ struct smbd_connection *info, struct smbd_response *response);
+static void enqueue_reassembly(
+ struct smbd_connection *info,
+ struct smbd_response *response, int data_length);
+static struct smbd_response *_get_first_reassembly(
+ struct smbd_connection *info);
+
+static int smbd_post_recv(
+ struct smbd_connection *info,
+ struct smbd_response *response);
+
+static int smbd_post_send_empty(struct smbd_connection *info);
+static int smbd_post_send_data(
+ struct smbd_connection *info,
+ struct kvec *iov, int n_vec, int remaining_data_length);
+static int smbd_post_send_page(struct smbd_connection *info,
+ struct page *page, unsigned long offset,
+ size_t size, int remaining_data_length);
+
+static void destroy_mr_list(struct smbd_connection *info);
+static int allocate_mr_list(struct smbd_connection *info);
+
+/* SMBD version number */
+#define SMBD_V1 0x0100
+
+/* Port numbers for SMBD transport */
+#define SMB_PORT 445
+#define SMBD_PORT 5445
+
+/* Address lookup and resolve timeout in ms */
+#define RDMA_RESOLVE_TIMEOUT 5000
+
+/* SMBD negotiation timeout in seconds */
+#define SMBD_NEGOTIATE_TIMEOUT 120
+
+/* SMBD minimum receive size and fragmented sized defined in [MS-SMBD] */
+#define SMBD_MIN_RECEIVE_SIZE 128
+#define SMBD_MIN_FRAGMENTED_SIZE 131072
+
+/*
+ * Default maximum number of RDMA read/write outstanding on this connection
+ * This value is possibly decreased during QP creation on hardware limit
+ */
+#define SMBD_CM_RESPONDER_RESOURCES 32
+
+/* Maximum number of retries on data transfer operations */
+#define SMBD_CM_RETRY 6
+/* No need to retry on Receiver Not Ready since SMBD manages credits */
+#define SMBD_CM_RNR_RETRY 0
+
+/*
+ * User configurable initial values per SMBD transport connection
+ * as defined in [MS-SMBD] 3.1.1.1
+ * Those may change after a SMBD negotiation
+ */
+/* The local peer's maximum number of credits to grant to the peer */
+int smbd_receive_credit_max = 255;
+
+/* The remote peer's credit request of local peer */
+int smbd_send_credit_target = 255;
+
+/* The maximum single message size can be sent to remote peer */
+int smbd_max_send_size = 1364;
+
+/* The maximum fragmented upper-layer payload receive size supported */
+int smbd_max_fragmented_recv_size = 1024 * 1024;
+
+/* The maximum single-message size which can be received */
+int smbd_max_receive_size = 1364;
+
+/* The timeout to initiate send of a keepalive message on idle */
+int smbd_keep_alive_interval = 120;
+
+/*
+ * User configurable initial values for RDMA transport
+ * The actual values used may be lower and are limited to hardware capabilities
+ */
+/* Default maximum number of pages in a single RDMA write/read */
+int smbd_max_frmr_depth = 2048;
+
+/* If payload is less than this byte, use RDMA send/recv not read/write */
+int rdma_readwrite_threshold = 4096;
+
+/* Transport logging functions
+ * Logging are defined as classes. They can be OR'ed to define the actual
+ * logging level via module parameter smbd_logging_class
+ * e.g. cifs.smbd_logging_class=0xa0 will log all log_rdma_recv() and
+ * log_rdma_event()
+ */
+#define LOG_OUTGOING 0x1
+#define LOG_INCOMING 0x2
+#define LOG_READ 0x4
+#define LOG_WRITE 0x8
+#define LOG_RDMA_SEND 0x10
+#define LOG_RDMA_RECV 0x20
+#define LOG_KEEP_ALIVE 0x40
+#define LOG_RDMA_EVENT 0x80
+#define LOG_RDMA_MR 0x100
+static unsigned int smbd_logging_class;
+module_param(smbd_logging_class, uint, 0644);
+MODULE_PARM_DESC(smbd_logging_class,
+ "Logging class for SMBD transport 0x0 to 0x100");
+
+#define ERR 0x0
+#define INFO 0x1
+static unsigned int smbd_logging_level = ERR;
+module_param(smbd_logging_level, uint, 0644);
+MODULE_PARM_DESC(smbd_logging_level,
+ "Logging level for SMBD transport, 0 (default): error, 1: info");
+
+#define log_rdma(level, class, fmt, args...) \
+do { \
+ if (level <= smbd_logging_level || class & smbd_logging_class) \
+ cifs_dbg(VFS, "%s:%d " fmt, __func__, __LINE__, ##args);\
+} while (0)
+
+#define log_outgoing(level, fmt, args...) \
+ log_rdma(level, LOG_OUTGOING, fmt, ##args)
+#define log_incoming(level, fmt, args...) \
+ log_rdma(level, LOG_INCOMING, fmt, ##args)
+#define log_read(level, fmt, args...) log_rdma(level, LOG_READ, fmt, ##args)
+#define log_write(level, fmt, args...) log_rdma(level, LOG_WRITE, fmt, ##args)
+#define log_rdma_send(level, fmt, args...) \
+ log_rdma(level, LOG_RDMA_SEND, fmt, ##args)
+#define log_rdma_recv(level, fmt, args...) \
+ log_rdma(level, LOG_RDMA_RECV, fmt, ##args)
+#define log_keep_alive(level, fmt, args...) \
+ log_rdma(level, LOG_KEEP_ALIVE, fmt, ##args)
+#define log_rdma_event(level, fmt, args...) \
+ log_rdma(level, LOG_RDMA_EVENT, fmt, ##args)
+#define log_rdma_mr(level, fmt, args...) \
+ log_rdma(level, LOG_RDMA_MR, fmt, ##args)
+
+static void smbd_disconnect_rdma_work(struct work_struct *work)
+{
+ struct smbd_connection *info =
+ container_of(work, struct smbd_connection, disconnect_work);
+
+ if (info->transport_status == SMBD_CONNECTED) {
+ info->transport_status = SMBD_DISCONNECTING;
+ rdma_disconnect(info->id);
+ }
+}
+
+static void smbd_disconnect_rdma_connection(struct smbd_connection *info)
+{
+ queue_work(info->workqueue, &info->disconnect_work);
+}
+
+/* Upcall from RDMA CM */
+static int smbd_conn_upcall(
+ struct rdma_cm_id *id, struct rdma_cm_event *event)
+{
+ struct smbd_connection *info = id->context;
+
+ log_rdma_event(INFO, "event=%d status=%d\n",
+ event->event, event->status);
+
+ switch (event->event) {
+ case RDMA_CM_EVENT_ADDR_RESOLVED:
+ case RDMA_CM_EVENT_ROUTE_RESOLVED:
+ info->ri_rc = 0;
+ complete(&info->ri_done);
+ break;
+
+ case RDMA_CM_EVENT_ADDR_ERROR:
+ info->ri_rc = -EHOSTUNREACH;
+ complete(&info->ri_done);
+ break;
+
+ case RDMA_CM_EVENT_ROUTE_ERROR:
+ info->ri_rc = -ENETUNREACH;
+ complete(&info->ri_done);
+ break;
+
+ case RDMA_CM_EVENT_ESTABLISHED:
+ log_rdma_event(INFO, "connected event=%d\n", event->event);
+ info->transport_status = SMBD_CONNECTED;
+ wake_up_interruptible(&info->conn_wait);
+ break;
+
+ case RDMA_CM_EVENT_CONNECT_ERROR:
+ case RDMA_CM_EVENT_UNREACHABLE:
+ case RDMA_CM_EVENT_REJECTED:
+ log_rdma_event(INFO, "connecting failed event=%d\n", event->event);
+ info->transport_status = SMBD_DISCONNECTED;
+ wake_up_interruptible(&info->conn_wait);
+ break;
+
+ case RDMA_CM_EVENT_DEVICE_REMOVAL:
+ case RDMA_CM_EVENT_DISCONNECTED:
+ /* This happenes when we fail the negotiation */
+ if (info->transport_status == SMBD_NEGOTIATE_FAILED) {
+ info->transport_status = SMBD_DISCONNECTED;
+ wake_up(&info->conn_wait);
+ break;
+ }
+
+ info->transport_status = SMBD_DISCONNECTED;
+ wake_up_interruptible(&info->disconn_wait);
+ wake_up_interruptible(&info->wait_reassembly_queue);
+ wake_up_interruptible_all(&info->wait_send_queue);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Upcall from RDMA QP */
+static void
+smbd_qp_async_error_upcall(struct ib_event *event, void *context)
+{
+ struct smbd_connection *info = context;
+
+ log_rdma_event(ERR, "%s on device %s info %p\n",
+ ib_event_msg(event->event), event->device->name, info);
+
+ switch (event->event) {
+ case IB_EVENT_CQ_ERR:
+ case IB_EVENT_QP_FATAL:
+ smbd_disconnect_rdma_connection(info);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static inline void *smbd_request_payload(struct smbd_request *request)
+{
+ return (void *)request->packet;
+}
+
+static inline void *smbd_response_payload(struct smbd_response *response)
+{
+ return (void *)response->packet;
+}
+
+/* Called when a RDMA send is done */
+static void send_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ int i;
+ struct smbd_request *request =
+ container_of(wc->wr_cqe, struct smbd_request, cqe);
+
+ log_rdma_send(INFO, "smbd_request 0x%p completed wc->status=%d\n",
+ request, wc->status);
+
+ if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
+ log_rdma_send(ERR, "wc->status=%d wc->opcode=%d\n",
+ wc->status, wc->opcode);
+ smbd_disconnect_rdma_connection(request->info);
+ }
+
+ for (i = 0; i < request->num_sge; i++)
+ ib_dma_unmap_single(request->info->id->device,
+ request->sge[i].addr,
+ request->sge[i].length,
+ DMA_TO_DEVICE);
+
+ if (atomic_dec_and_test(&request->info->send_pending))
+ wake_up(&request->info->wait_send_pending);
+
+ wake_up(&request->info->wait_post_send);
+
+ mempool_free(request, request->info->request_mempool);
+}
+
+static void dump_smbd_negotiate_resp(struct smbd_negotiate_resp *resp)
+{
+ log_rdma_event(INFO, "resp message min_version %u max_version %u negotiated_version %u credits_requested %u credits_granted %u status %u max_readwrite_size %u preferred_send_size %u max_receive_size %u max_fragmented_size %u\n",
+ resp->min_version, resp->max_version,
+ resp->negotiated_version, resp->credits_requested,
+ resp->credits_granted, resp->status,
+ resp->max_readwrite_size, resp->preferred_send_size,
+ resp->max_receive_size, resp->max_fragmented_size);
+}
+
+/*
+ * Process a negotiation response message, according to [MS-SMBD]3.1.5.7
+ * response, packet_length: the negotiation response message
+ * return value: true if negotiation is a success, false if failed
+ */
+static bool process_negotiation_response(
+ struct smbd_response *response, int packet_length)
+{
+ struct smbd_connection *info = response->info;
+ struct smbd_negotiate_resp *packet = smbd_response_payload(response);
+
+ if (packet_length < sizeof(struct smbd_negotiate_resp)) {
+ log_rdma_event(ERR,
+ "error: packet_length=%d\n", packet_length);
+ return false;
+ }
+
+ if (le16_to_cpu(packet->negotiated_version) != SMBD_V1) {
+ log_rdma_event(ERR, "error: negotiated_version=%x\n",
+ le16_to_cpu(packet->negotiated_version));
+ return false;
+ }
+ info->protocol = le16_to_cpu(packet->negotiated_version);
+
+ if (packet->credits_requested == 0) {
+ log_rdma_event(ERR, "error: credits_requested==0\n");
+ return false;
+ }
+ info->receive_credit_target = le16_to_cpu(packet->credits_requested);
+
+ if (packet->credits_granted == 0) {
+ log_rdma_event(ERR, "error: credits_granted==0\n");
+ return false;
+ }
+ atomic_set(&info->send_credits, le16_to_cpu(packet->credits_granted));
+
+ atomic_set(&info->receive_credits, 0);
+
+ if (le32_to_cpu(packet->preferred_send_size) > info->max_receive_size) {
+ log_rdma_event(ERR, "error: preferred_send_size=%d\n",
+ le32_to_cpu(packet->preferred_send_size));
+ return false;
+ }
+ info->max_receive_size = le32_to_cpu(packet->preferred_send_size);
+
+ if (le32_to_cpu(packet->max_receive_size) < SMBD_MIN_RECEIVE_SIZE) {
+ log_rdma_event(ERR, "error: max_receive_size=%d\n",
+ le32_to_cpu(packet->max_receive_size));
+ return false;
+ }
+ info->max_send_size = min_t(int, info->max_send_size,
+ le32_to_cpu(packet->max_receive_size));
+
+ if (le32_to_cpu(packet->max_fragmented_size) <
+ SMBD_MIN_FRAGMENTED_SIZE) {
+ log_rdma_event(ERR, "error: max_fragmented_size=%d\n",
+ le32_to_cpu(packet->max_fragmented_size));
+ return false;
+ }
+ info->max_fragmented_send_size =
+ le32_to_cpu(packet->max_fragmented_size);
+ info->rdma_readwrite_threshold =
+ rdma_readwrite_threshold > info->max_fragmented_send_size ?
+ info->max_fragmented_send_size :
+ rdma_readwrite_threshold;
+
+
+ info->max_readwrite_size = min_t(u32,
+ le32_to_cpu(packet->max_readwrite_size),
+ info->max_frmr_depth * PAGE_SIZE);
+ info->max_frmr_depth = info->max_readwrite_size / PAGE_SIZE;
+
+ return true;
+}
+
+static void smbd_post_send_credits(struct work_struct *work)
+{
+ int ret = 0;
+ int use_receive_queue = 1;
+ int rc;
+ struct smbd_response *response;
+ struct smbd_connection *info =
+ container_of(work, struct smbd_connection,
+ post_send_credits_work);
+
+ if (info->transport_status != SMBD_CONNECTED) {
+ wake_up(&info->wait_receive_queues);
+ return;
+ }
+
+ if (info->receive_credit_target >
+ atomic_read(&info->receive_credits)) {
+ while (true) {
+ if (use_receive_queue)
+ response = get_receive_buffer(info);
+ else
+ response = get_empty_queue_buffer(info);
+ if (!response) {
+ /* now switch to emtpy packet queue */
+ if (use_receive_queue) {
+ use_receive_queue = 0;
+ continue;
+ } else
+ break;
+ }
+
+ response->type = SMBD_TRANSFER_DATA;
+ response->first_segment = false;
+ rc = smbd_post_recv(info, response);
+ if (rc) {
+ log_rdma_recv(ERR,
+ "post_recv failed rc=%d\n", rc);
+ put_receive_buffer(info, response);
+ break;
+ }
+
+ ret++;
+ }
+ }
+
+ spin_lock(&info->lock_new_credits_offered);
+ info->new_credits_offered += ret;
+ spin_unlock(&info->lock_new_credits_offered);
+
+ /* Promptly send an immediate packet as defined in [MS-SMBD] 3.1.1.1 */
+ info->send_immediate = true;
+ if (atomic_read(&info->receive_credits) <
+ info->receive_credit_target - 1) {
+ if (info->keep_alive_requested == KEEP_ALIVE_PENDING ||
+ info->send_immediate) {
+ log_keep_alive(INFO, "send an empty message\n");
+ smbd_post_send_empty(info);
+ }
+ }
+}
+
+/* Called from softirq, when recv is done */
+static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbd_data_transfer *data_transfer;
+ struct smbd_response *response =
+ container_of(wc->wr_cqe, struct smbd_response, cqe);
+ struct smbd_connection *info = response->info;
+ int data_length = 0;
+
+ log_rdma_recv(INFO, "response=0x%p type=%d wc status=%d wc opcode %d byte_len=%d pkey_index=%u\n",
+ response, response->type, wc->status, wc->opcode,
+ wc->byte_len, wc->pkey_index);
+
+ if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
+ log_rdma_recv(INFO, "wc->status=%d opcode=%d\n",
+ wc->status, wc->opcode);
+ smbd_disconnect_rdma_connection(info);
+ goto error;
+ }
+
+ ib_dma_sync_single_for_cpu(
+ wc->qp->device,
+ response->sge.addr,
+ response->sge.length,
+ DMA_FROM_DEVICE);
+
+ switch (response->type) {
+ /* SMBD negotiation response */
+ case SMBD_NEGOTIATE_RESP:
+ dump_smbd_negotiate_resp(smbd_response_payload(response));
+ info->full_packet_received = true;
+ info->negotiate_done =
+ process_negotiation_response(response, wc->byte_len);
+ complete(&info->negotiate_completion);
+ break;
+
+ /* SMBD data transfer packet */
+ case SMBD_TRANSFER_DATA:
+ data_transfer = smbd_response_payload(response);
+ data_length = le32_to_cpu(data_transfer->data_length);
+
+ /*
+ * If this is a packet with data playload place the data in
+ * reassembly queue and wake up the reading thread
+ */
+ if (data_length) {
+ if (info->full_packet_received)
+ response->first_segment = true;
+
+ if (le32_to_cpu(data_transfer->remaining_data_length))
+ info->full_packet_received = false;
+ else
+ info->full_packet_received = true;
+
+ enqueue_reassembly(
+ info,
+ response,
+ data_length);
+ } else
+ put_empty_packet(info, response);
+
+ if (data_length)
+ wake_up_interruptible(&info->wait_reassembly_queue);
+
+ atomic_dec(&info->receive_credits);
+ info->receive_credit_target =
+ le16_to_cpu(data_transfer->credits_requested);
+ if (le16_to_cpu(data_transfer->credits_granted)) {
+ atomic_add(le16_to_cpu(data_transfer->credits_granted),
+ &info->send_credits);
+ /*
+ * We have new send credits granted from remote peer
+ * If any sender is waiting for credits, unblock it
+ */
+ wake_up_interruptible(&info->wait_send_queue);
+ }
+
+ log_incoming(INFO, "data flags %d data_offset %d data_length %d remaining_data_length %d\n",
+ le16_to_cpu(data_transfer->flags),
+ le32_to_cpu(data_transfer->data_offset),
+ le32_to_cpu(data_transfer->data_length),
+ le32_to_cpu(data_transfer->remaining_data_length));
+
+ /* Send a KEEP_ALIVE response right away if requested */
+ info->keep_alive_requested = KEEP_ALIVE_NONE;
+ if (le16_to_cpu(data_transfer->flags) &
+ SMB_DIRECT_RESPONSE_REQUESTED) {
+ info->keep_alive_requested = KEEP_ALIVE_PENDING;
+ }
+
+ return;
+
+ default:
+ log_rdma_recv(ERR,
+ "unexpected response type=%d\n", response->type);
+ }
+
+error:
+ put_receive_buffer(info, response);
+}
+
+static struct rdma_cm_id *smbd_create_id(
+ struct smbd_connection *info,
+ struct sockaddr *dstaddr, int port)
+{
+ struct rdma_cm_id *id;
+ int rc;
+ __be16 *sport;
+
+ id = rdma_create_id(&init_net, smbd_conn_upcall, info,
+ RDMA_PS_TCP, IB_QPT_RC);
+ if (IS_ERR(id)) {
+ rc = PTR_ERR(id);
+ log_rdma_event(ERR, "rdma_create_id() failed %i\n", rc);
+ return id;
+ }
+
+ if (dstaddr->sa_family == AF_INET6)
+ sport = &((struct sockaddr_in6 *)dstaddr)->sin6_port;
+ else
+ sport = &((struct sockaddr_in *)dstaddr)->sin_port;
+
+ *sport = htons(port);
+
+ init_completion(&info->ri_done);
+ info->ri_rc = -ETIMEDOUT;
+
+ rc = rdma_resolve_addr(id, NULL, (struct sockaddr *)dstaddr,
+ RDMA_RESOLVE_TIMEOUT);
+ if (rc) {
+ log_rdma_event(ERR, "rdma_resolve_addr() failed %i\n", rc);
+ goto out;
+ }
+ rc = wait_for_completion_interruptible_timeout(
+ &info->ri_done, msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT));
+ /* e.g. if interrupted returns -ERESTARTSYS */
+ if (rc < 0) {
+ log_rdma_event(ERR, "rdma_resolve_addr timeout rc: %i\n", rc);
+ goto out;
+ }
+ rc = info->ri_rc;
+ if (rc) {
+ log_rdma_event(ERR, "rdma_resolve_addr() completed %i\n", rc);
+ goto out;
+ }
+
+ info->ri_rc = -ETIMEDOUT;
+ rc = rdma_resolve_route(id, RDMA_RESOLVE_TIMEOUT);
+ if (rc) {
+ log_rdma_event(ERR, "rdma_resolve_route() failed %i\n", rc);
+ goto out;
+ }
+ rc = wait_for_completion_interruptible_timeout(
+ &info->ri_done, msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT));
+ /* e.g. if interrupted returns -ERESTARTSYS */
+ if (rc < 0) {
+ log_rdma_event(ERR, "rdma_resolve_addr timeout rc: %i\n", rc);
+ goto out;
+ }
+ rc = info->ri_rc;
+ if (rc) {
+ log_rdma_event(ERR, "rdma_resolve_route() completed %i\n", rc);
+ goto out;
+ }
+
+ return id;
+
+out:
+ rdma_destroy_id(id);
+ return ERR_PTR(rc);
+}
+
+/*
+ * Test if FRWR (Fast Registration Work Requests) is supported on the device
+ * This implementation requries FRWR on RDMA read/write
+ * return value: true if it is supported
+ */
+static bool frwr_is_supported(struct ib_device_attr *attrs)
+{
+ if (!(attrs->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS))
+ return false;
+ if (attrs->max_fast_reg_page_list_len == 0)
+ return false;
+ return true;
+}
+
+static int smbd_ia_open(
+ struct smbd_connection *info,
+ struct sockaddr *dstaddr, int port)
+{
+ int rc;
+
+ info->id = smbd_create_id(info, dstaddr, port);
+ if (IS_ERR(info->id)) {
+ rc = PTR_ERR(info->id);
+ goto out1;
+ }
+
+ if (!frwr_is_supported(&info->id->device->attrs)) {
+ log_rdma_event(ERR, "Fast Registration Work Requests (FRWR) is not supported\n");
+ log_rdma_event(ERR, "Device capability flags = %llx max_fast_reg_page_list_len = %u\n",
+ info->id->device->attrs.device_cap_flags,
+ info->id->device->attrs.max_fast_reg_page_list_len);
+ rc = -EPROTONOSUPPORT;
+ goto out2;
+ }
+ info->max_frmr_depth = min_t(int,
+ smbd_max_frmr_depth,
+ info->id->device->attrs.max_fast_reg_page_list_len);
+ info->mr_type = IB_MR_TYPE_MEM_REG;
+ if (info->id->device->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
+ info->mr_type = IB_MR_TYPE_SG_GAPS;
+
+ info->pd = ib_alloc_pd(info->id->device, 0);
+ if (IS_ERR(info->pd)) {
+ rc = PTR_ERR(info->pd);
+ log_rdma_event(ERR, "ib_alloc_pd() returned %d\n", rc);
+ goto out2;
+ }
+
+ return 0;
+
+out2:
+ rdma_destroy_id(info->id);
+ info->id = NULL;
+
+out1:
+ return rc;
+}
+
+/*
+ * Send a negotiation request message to the peer
+ * The negotiation procedure is in [MS-SMBD] 3.1.5.2 and 3.1.5.3
+ * After negotiation, the transport is connected and ready for
+ * carrying upper layer SMB payload
+ */
+static int smbd_post_send_negotiate_req(struct smbd_connection *info)
+{
+ struct ib_send_wr send_wr;
+ int rc = -ENOMEM;
+ struct smbd_request *request;
+ struct smbd_negotiate_req *packet;
+
+ request = mempool_alloc(info->request_mempool, GFP_KERNEL);
+ if (!request)
+ return rc;
+
+ request->info = info;
+
+ packet = smbd_request_payload(request);
+ packet->min_version = cpu_to_le16(SMBD_V1);
+ packet->max_version = cpu_to_le16(SMBD_V1);
+ packet->reserved = 0;
+ packet->credits_requested = cpu_to_le16(info->send_credit_target);
+ packet->preferred_send_size = cpu_to_le32(info->max_send_size);
+ packet->max_receive_size = cpu_to_le32(info->max_receive_size);
+ packet->max_fragmented_size =
+ cpu_to_le32(info->max_fragmented_recv_size);
+
+ request->num_sge = 1;
+ request->sge[0].addr = ib_dma_map_single(
+ info->id->device, (void *)packet,
+ sizeof(*packet), DMA_TO_DEVICE);
+ if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) {
+ rc = -EIO;
+ goto dma_mapping_failed;
+ }
+
+ request->sge[0].length = sizeof(*packet);
+ request->sge[0].lkey = info->pd->local_dma_lkey;
+
+ ib_dma_sync_single_for_device(
+ info->id->device, request->sge[0].addr,
+ request->sge[0].length, DMA_TO_DEVICE);
+
+ request->cqe.done = send_done;
+
+ send_wr.next = NULL;
+ send_wr.wr_cqe = &request->cqe;
+ send_wr.sg_list = request->sge;
+ send_wr.num_sge = request->num_sge;
+ send_wr.opcode = IB_WR_SEND;
+ send_wr.send_flags = IB_SEND_SIGNALED;
+
+ log_rdma_send(INFO, "sge addr=0x%llx length=%u lkey=0x%x\n",
+ request->sge[0].addr,
+ request->sge[0].length, request->sge[0].lkey);
+
+ atomic_inc(&info->send_pending);
+ rc = ib_post_send(info->id->qp, &send_wr, NULL);
+ if (!rc)
+ return 0;
+
+ /* if we reach here, post send failed */
+ log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
+ atomic_dec(&info->send_pending);
+ ib_dma_unmap_single(info->id->device, request->sge[0].addr,
+ request->sge[0].length, DMA_TO_DEVICE);
+
+ smbd_disconnect_rdma_connection(info);
+
+dma_mapping_failed:
+ mempool_free(request, info->request_mempool);
+ return rc;
+}
+
+/*
+ * Extend the credits to remote peer
+ * This implements [MS-SMBD] 3.1.5.9
+ * The idea is that we should extend credits to remote peer as quickly as
+ * it's allowed, to maintain data flow. We allocate as much receive
+ * buffer as possible, and extend the receive credits to remote peer
+ * return value: the new credtis being granted.
+ */
+static int manage_credits_prior_sending(struct smbd_connection *info)
+{
+ int new_credits;
+
+ spin_lock(&info->lock_new_credits_offered);
+ new_credits = info->new_credits_offered;
+ info->new_credits_offered = 0;
+ spin_unlock(&info->lock_new_credits_offered);
+
+ return new_credits;
+}
+
+/*
+ * Check if we need to send a KEEP_ALIVE message
+ * The idle connection timer triggers a KEEP_ALIVE message when expires
+ * SMB_DIRECT_RESPONSE_REQUESTED is set in the message flag to have peer send
+ * back a response.
+ * return value:
+ * 1 if SMB_DIRECT_RESPONSE_REQUESTED needs to be set
+ * 0: otherwise
+ */
+static int manage_keep_alive_before_sending(struct smbd_connection *info)
+{
+ if (info->keep_alive_requested == KEEP_ALIVE_PENDING) {
+ info->keep_alive_requested = KEEP_ALIVE_SENT;
+ return 1;
+ }
+ return 0;
+}
+
+/* Post the send request */
+static int smbd_post_send(struct smbd_connection *info,
+ struct smbd_request *request)
+{
+ struct ib_send_wr send_wr;
+ int rc, i;
+
+ for (i = 0; i < request->num_sge; i++) {
+ log_rdma_send(INFO,
+ "rdma_request sge[%d] addr=0x%llx length=%u\n",
+ i, request->sge[i].addr, request->sge[i].length);
+ ib_dma_sync_single_for_device(
+ info->id->device,
+ request->sge[i].addr,
+ request->sge[i].length,
+ DMA_TO_DEVICE);
+ }
+
+ request->cqe.done = send_done;
+
+ send_wr.next = NULL;
+ send_wr.wr_cqe = &request->cqe;
+ send_wr.sg_list = request->sge;
+ send_wr.num_sge = request->num_sge;
+ send_wr.opcode = IB_WR_SEND;
+ send_wr.send_flags = IB_SEND_SIGNALED;
+
+ rc = ib_post_send(info->id->qp, &send_wr, NULL);
+ if (rc) {
+ log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
+ smbd_disconnect_rdma_connection(info);
+ rc = -EAGAIN;
+ } else
+ /* Reset timer for idle connection after packet is sent */
+ mod_delayed_work(info->workqueue, &info->idle_timer_work,
+ info->keep_alive_interval*HZ);
+
+ return rc;
+}
+
+static int smbd_post_send_sgl(struct smbd_connection *info,
+ struct scatterlist *sgl, int data_length, int remaining_data_length)
+{
+ int num_sgs;
+ int i, rc;
+ int header_length;
+ struct smbd_request *request;
+ struct smbd_data_transfer *packet;
+ int new_credits;
+ struct scatterlist *sg;
+
+wait_credit:
+ /* Wait for send credits. A SMBD packet needs one credit */
+ rc = wait_event_interruptible(info->wait_send_queue,
+ atomic_read(&info->send_credits) > 0 ||
+ info->transport_status != SMBD_CONNECTED);
+ if (rc)
+ goto err_wait_credit;
+
+ if (info->transport_status != SMBD_CONNECTED) {
+ log_outgoing(ERR, "disconnected not sending on wait_credit\n");
+ rc = -EAGAIN;
+ goto err_wait_credit;
+ }
+ if (unlikely(atomic_dec_return(&info->send_credits) < 0)) {
+ atomic_inc(&info->send_credits);
+ goto wait_credit;
+ }
+
+wait_send_queue:
+ wait_event(info->wait_post_send,
+ atomic_read(&info->send_pending) < info->send_credit_target ||
+ info->transport_status != SMBD_CONNECTED);
+
+ if (info->transport_status != SMBD_CONNECTED) {
+ log_outgoing(ERR, "disconnected not sending on wait_send_queue\n");
+ rc = -EAGAIN;
+ goto err_wait_send_queue;
+ }
+
+ if (unlikely(atomic_inc_return(&info->send_pending) >
+ info->send_credit_target)) {
+ atomic_dec(&info->send_pending);
+ goto wait_send_queue;
+ }
+
+ request = mempool_alloc(info->request_mempool, GFP_KERNEL);
+ if (!request) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+
+ request->info = info;
+
+ /* Fill in the packet header */
+ packet = smbd_request_payload(request);
+ packet->credits_requested = cpu_to_le16(info->send_credit_target);
+
+ new_credits = manage_credits_prior_sending(info);
+ atomic_add(new_credits, &info->receive_credits);
+ packet->credits_granted = cpu_to_le16(new_credits);
+
+ info->send_immediate = false;
+
+ packet->flags = 0;
+ if (manage_keep_alive_before_sending(info))
+ packet->flags |= cpu_to_le16(SMB_DIRECT_RESPONSE_REQUESTED);
+
+ packet->reserved = 0;
+ if (!data_length)
+ packet->data_offset = 0;
+ else
+ packet->data_offset = cpu_to_le32(24);
+ packet->data_length = cpu_to_le32(data_length);
+ packet->remaining_data_length = cpu_to_le32(remaining_data_length);
+ packet->padding = 0;
+
+ log_outgoing(INFO, "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n",
+ le16_to_cpu(packet->credits_requested),
+ le16_to_cpu(packet->credits_granted),
+ le32_to_cpu(packet->data_offset),
+ le32_to_cpu(packet->data_length),
+ le32_to_cpu(packet->remaining_data_length));
+
+ /* Map the packet to DMA */
+ header_length = sizeof(struct smbd_data_transfer);
+ /* If this is a packet without payload, don't send padding */
+ if (!data_length)
+ header_length = offsetof(struct smbd_data_transfer, padding);
+
+ request->num_sge = 1;
+ request->sge[0].addr = ib_dma_map_single(info->id->device,
+ (void *)packet,
+ header_length,
+ DMA_TO_DEVICE);
+ if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) {
+ rc = -EIO;
+ request->sge[0].addr = 0;
+ goto err_dma;
+ }
+
+ request->sge[0].length = header_length;
+ request->sge[0].lkey = info->pd->local_dma_lkey;
+
+ /* Fill in the packet data payload */
+ num_sgs = sgl ? sg_nents(sgl) : 0;
+ for_each_sg(sgl, sg, num_sgs, i) {
+ request->sge[i+1].addr =
+ ib_dma_map_page(info->id->device, sg_page(sg),
+ sg->offset, sg->length, DMA_TO_DEVICE);
+ if (ib_dma_mapping_error(
+ info->id->device, request->sge[i+1].addr)) {
+ rc = -EIO;
+ request->sge[i+1].addr = 0;
+ goto err_dma;
+ }
+ request->sge[i+1].length = sg->length;
+ request->sge[i+1].lkey = info->pd->local_dma_lkey;
+ request->num_sge++;
+ }
+
+ rc = smbd_post_send(info, request);
+ if (!rc)
+ return 0;
+
+err_dma:
+ for (i = 0; i < request->num_sge; i++)
+ if (request->sge[i].addr)
+ ib_dma_unmap_single(info->id->device,
+ request->sge[i].addr,
+ request->sge[i].length,
+ DMA_TO_DEVICE);
+ mempool_free(request, info->request_mempool);
+
+ /* roll back receive credits and credits to be offered */
+ spin_lock(&info->lock_new_credits_offered);
+ info->new_credits_offered += new_credits;
+ spin_unlock(&info->lock_new_credits_offered);
+ atomic_sub(new_credits, &info->receive_credits);
+
+err_alloc:
+ if (atomic_dec_and_test(&info->send_pending))
+ wake_up(&info->wait_send_pending);
+
+err_wait_send_queue:
+ /* roll back send credits and pending */
+ atomic_inc(&info->send_credits);
+
+err_wait_credit:
+ return rc;
+}
+
+/*
+ * Send a page
+ * page: the page to send
+ * offset: offset in the page to send
+ * size: length in the page to send
+ * remaining_data_length: remaining data to send in this payload
+ */
+static int smbd_post_send_page(struct smbd_connection *info, struct page *page,
+ unsigned long offset, size_t size, int remaining_data_length)
+{
+ struct scatterlist sgl;
+
+ sg_init_table(&sgl, 1);
+ sg_set_page(&sgl, page, size, offset);
+
+ return smbd_post_send_sgl(info, &sgl, size, remaining_data_length);
+}
+
+/*
+ * Send an empty message
+ * Empty message is used to extend credits to peer to for keep live
+ * while there is no upper layer payload to send at the time
+ */
+static int smbd_post_send_empty(struct smbd_connection *info)
+{
+ info->count_send_empty++;
+ return smbd_post_send_sgl(info, NULL, 0, 0);
+}
+
+/*
+ * Send a data buffer
+ * iov: the iov array describing the data buffers
+ * n_vec: number of iov array
+ * remaining_data_length: remaining data to send following this packet
+ * in segmented SMBD packet
+ */
+static int smbd_post_send_data(
+ struct smbd_connection *info, struct kvec *iov, int n_vec,
+ int remaining_data_length)
+{
+ int i;
+ u32 data_length = 0;
+ struct scatterlist sgl[SMBDIRECT_MAX_SEND_SGE - 1];
+
+ if (n_vec > SMBDIRECT_MAX_SEND_SGE - 1) {
+ cifs_dbg(VFS, "Can't fit data to SGL, n_vec=%d\n", n_vec);
+ return -EINVAL;
+ }
+
+ sg_init_table(sgl, n_vec);
+ for (i = 0; i < n_vec; i++) {
+ data_length += iov[i].iov_len;
+ sg_set_buf(&sgl[i], iov[i].iov_base, iov[i].iov_len);
+ }
+
+ return smbd_post_send_sgl(info, sgl, data_length, remaining_data_length);
+}
+
+/*
+ * Post a receive request to the transport
+ * The remote peer can only send data when a receive request is posted
+ * The interaction is controlled by send/receive credit system
+ */
+static int smbd_post_recv(
+ struct smbd_connection *info, struct smbd_response *response)
+{
+ struct ib_recv_wr recv_wr;
+ int rc = -EIO;
+
+ response->sge.addr = ib_dma_map_single(
+ info->id->device, response->packet,
+ info->max_receive_size, DMA_FROM_DEVICE);
+ if (ib_dma_mapping_error(info->id->device, response->sge.addr))
+ return rc;
+
+ response->sge.length = info->max_receive_size;
+ response->sge.lkey = info->pd->local_dma_lkey;
+
+ response->cqe.done = recv_done;
+
+ recv_wr.wr_cqe = &response->cqe;
+ recv_wr.next = NULL;
+ recv_wr.sg_list = &response->sge;
+ recv_wr.num_sge = 1;
+
+ rc = ib_post_recv(info->id->qp, &recv_wr, NULL);
+ if (rc) {
+ ib_dma_unmap_single(info->id->device, response->sge.addr,
+ response->sge.length, DMA_FROM_DEVICE);
+ smbd_disconnect_rdma_connection(info);
+ log_rdma_recv(ERR, "ib_post_recv failed rc=%d\n", rc);
+ }
+
+ return rc;
+}
+
+/* Perform SMBD negotiate according to [MS-SMBD] 3.1.5.2 */
+static int smbd_negotiate(struct smbd_connection *info)
+{
+ int rc;
+ struct smbd_response *response = get_receive_buffer(info);
+
+ response->type = SMBD_NEGOTIATE_RESP;
+ rc = smbd_post_recv(info, response);
+ log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=0x%llx iov.length=%u iov.lkey=0x%x\n",
+ rc, response->sge.addr,
+ response->sge.length, response->sge.lkey);
+ if (rc)
+ return rc;
+
+ init_completion(&info->negotiate_completion);
+ info->negotiate_done = false;
+ rc = smbd_post_send_negotiate_req(info);
+ if (rc)
+ return rc;
+
+ rc = wait_for_completion_interruptible_timeout(
+ &info->negotiate_completion, SMBD_NEGOTIATE_TIMEOUT * HZ);
+ log_rdma_event(INFO, "wait_for_completion_timeout rc=%d\n", rc);
+
+ if (info->negotiate_done)
+ return 0;
+
+ if (rc == 0)
+ rc = -ETIMEDOUT;
+ else if (rc == -ERESTARTSYS)
+ rc = -EINTR;
+ else
+ rc = -ENOTCONN;
+
+ return rc;
+}
+
+static void put_empty_packet(
+ struct smbd_connection *info, struct smbd_response *response)
+{
+ spin_lock(&info->empty_packet_queue_lock);
+ list_add_tail(&response->list, &info->empty_packet_queue);
+ info->count_empty_packet_queue++;
+ spin_unlock(&info->empty_packet_queue_lock);
+
+ queue_work(info->workqueue, &info->post_send_credits_work);
+}
+
+/*
+ * Implement Connection.FragmentReassemblyBuffer defined in [MS-SMBD] 3.1.1.1
+ * This is a queue for reassembling upper layer payload and present to upper
+ * layer. All the inncoming payload go to the reassembly queue, regardless of
+ * if reassembly is required. The uuper layer code reads from the queue for all
+ * incoming payloads.
+ * Put a received packet to the reassembly queue
+ * response: the packet received
+ * data_length: the size of payload in this packet
+ */
+static void enqueue_reassembly(
+ struct smbd_connection *info,
+ struct smbd_response *response,
+ int data_length)
+{
+ spin_lock(&info->reassembly_queue_lock);
+ list_add_tail(&response->list, &info->reassembly_queue);
+ info->reassembly_queue_length++;
+ /*
+ * Make sure reassembly_data_length is updated after list and
+ * reassembly_queue_length are updated. On the dequeue side
+ * reassembly_data_length is checked without a lock to determine
+ * if reassembly_queue_length and list is up to date
+ */
+ virt_wmb();
+ info->reassembly_data_length += data_length;
+ spin_unlock(&info->reassembly_queue_lock);
+ info->count_reassembly_queue++;
+ info->count_enqueue_reassembly_queue++;
+}
+
+/*
+ * Get the first entry at the front of reassembly queue
+ * Caller is responsible for locking
+ * return value: the first entry if any, NULL if queue is empty
+ */
+static struct smbd_response *_get_first_reassembly(struct smbd_connection *info)
+{
+ struct smbd_response *ret = NULL;
+
+ if (!list_empty(&info->reassembly_queue)) {
+ ret = list_first_entry(
+ &info->reassembly_queue,
+ struct smbd_response, list);
+ }
+ return ret;
+}
+
+static struct smbd_response *get_empty_queue_buffer(
+ struct smbd_connection *info)
+{
+ struct smbd_response *ret = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->empty_packet_queue_lock, flags);
+ if (!list_empty(&info->empty_packet_queue)) {
+ ret = list_first_entry(
+ &info->empty_packet_queue,
+ struct smbd_response, list);
+ list_del(&ret->list);
+ info->count_empty_packet_queue--;
+ }
+ spin_unlock_irqrestore(&info->empty_packet_queue_lock, flags);
+
+ return ret;
+}
+
+/*
+ * Get a receive buffer
+ * For each remote send, we need to post a receive. The receive buffers are
+ * pre-allocated in advance.
+ * return value: the receive buffer, NULL if none is available
+ */
+static struct smbd_response *get_receive_buffer(struct smbd_connection *info)
+{
+ struct smbd_response *ret = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->receive_queue_lock, flags);
+ if (!list_empty(&info->receive_queue)) {
+ ret = list_first_entry(
+ &info->receive_queue,
+ struct smbd_response, list);
+ list_del(&ret->list);
+ info->count_receive_queue--;
+ info->count_get_receive_buffer++;
+ }
+ spin_unlock_irqrestore(&info->receive_queue_lock, flags);
+
+ return ret;
+}
+
+/*
+ * Return a receive buffer
+ * Upon returning of a receive buffer, we can post new receive and extend
+ * more receive credits to remote peer. This is done immediately after a
+ * receive buffer is returned.
+ */
+static void put_receive_buffer(
+ struct smbd_connection *info, struct smbd_response *response)
+{
+ unsigned long flags;
+
+ ib_dma_unmap_single(info->id->device, response->sge.addr,
+ response->sge.length, DMA_FROM_DEVICE);
+
+ spin_lock_irqsave(&info->receive_queue_lock, flags);
+ list_add_tail(&response->list, &info->receive_queue);
+ info->count_receive_queue++;
+ info->count_put_receive_buffer++;
+ spin_unlock_irqrestore(&info->receive_queue_lock, flags);
+
+ queue_work(info->workqueue, &info->post_send_credits_work);
+}
+
+/* Preallocate all receive buffer on transport establishment */
+static int allocate_receive_buffers(struct smbd_connection *info, int num_buf)
+{
+ int i;
+ struct smbd_response *response;
+
+ INIT_LIST_HEAD(&info->reassembly_queue);
+ spin_lock_init(&info->reassembly_queue_lock);
+ info->reassembly_data_length = 0;
+ info->reassembly_queue_length = 0;
+
+ INIT_LIST_HEAD(&info->receive_queue);
+ spin_lock_init(&info->receive_queue_lock);
+ info->count_receive_queue = 0;
+
+ INIT_LIST_HEAD(&info->empty_packet_queue);
+ spin_lock_init(&info->empty_packet_queue_lock);
+ info->count_empty_packet_queue = 0;
+
+ init_waitqueue_head(&info->wait_receive_queues);
+
+ for (i = 0; i < num_buf; i++) {
+ response = mempool_alloc(info->response_mempool, GFP_KERNEL);
+ if (!response)
+ goto allocate_failed;
+
+ response->info = info;
+ list_add_tail(&response->list, &info->receive_queue);
+ info->count_receive_queue++;
+ }
+
+ return 0;
+
+allocate_failed:
+ while (!list_empty(&info->receive_queue)) {
+ response = list_first_entry(
+ &info->receive_queue,
+ struct smbd_response, list);
+ list_del(&response->list);
+ info->count_receive_queue--;
+
+ mempool_free(response, info->response_mempool);
+ }
+ return -ENOMEM;
+}
+
+static void destroy_receive_buffers(struct smbd_connection *info)
+{
+ struct smbd_response *response;
+
+ while ((response = get_receive_buffer(info)))
+ mempool_free(response, info->response_mempool);
+
+ while ((response = get_empty_queue_buffer(info)))
+ mempool_free(response, info->response_mempool);
+}
+
+/* Implement idle connection timer [MS-SMBD] 3.1.6.2 */
+static void idle_connection_timer(struct work_struct *work)
+{
+ struct smbd_connection *info = container_of(
+ work, struct smbd_connection,
+ idle_timer_work.work);
+
+ if (info->keep_alive_requested != KEEP_ALIVE_NONE) {
+ log_keep_alive(ERR,
+ "error status info->keep_alive_requested=%d\n",
+ info->keep_alive_requested);
+ smbd_disconnect_rdma_connection(info);
+ return;
+ }
+
+ log_keep_alive(INFO, "about to send an empty idle message\n");
+ smbd_post_send_empty(info);
+
+ /* Setup the next idle timeout work */
+ queue_delayed_work(info->workqueue, &info->idle_timer_work,
+ info->keep_alive_interval*HZ);
+}
+
+/*
+ * Destroy the transport and related RDMA and memory resources
+ * Need to go through all the pending counters and make sure on one is using
+ * the transport while it is destroyed
+ */
+void smbd_destroy(struct TCP_Server_Info *server)
+{
+ struct smbd_connection *info = server->smbd_conn;
+ struct smbd_response *response;
+ unsigned long flags;
+
+ if (!info) {
+ log_rdma_event(INFO, "rdma session already destroyed\n");
+ return;
+ }
+
+ log_rdma_event(INFO, "destroying rdma session\n");
+ if (info->transport_status != SMBD_DISCONNECTED) {
+ rdma_disconnect(server->smbd_conn->id);
+ log_rdma_event(INFO, "wait for transport being disconnected\n");
+ wait_event_interruptible(
+ info->disconn_wait,
+ info->transport_status == SMBD_DISCONNECTED);
+ }
+
+ log_rdma_event(INFO, "destroying qp\n");
+ ib_drain_qp(info->id->qp);
+ rdma_destroy_qp(info->id);
+
+ log_rdma_event(INFO, "cancelling idle timer\n");
+ cancel_delayed_work_sync(&info->idle_timer_work);
+
+ log_rdma_event(INFO, "wait for all send posted to IB to finish\n");
+ wait_event(info->wait_send_pending,
+ atomic_read(&info->send_pending) == 0);
+
+ /* It's not possible for upper layer to get to reassembly */
+ log_rdma_event(INFO, "drain the reassembly queue\n");
+ do {
+ spin_lock_irqsave(&info->reassembly_queue_lock, flags);
+ response = _get_first_reassembly(info);
+ if (response) {
+ list_del(&response->list);
+ spin_unlock_irqrestore(
+ &info->reassembly_queue_lock, flags);
+ put_receive_buffer(info, response);
+ } else
+ spin_unlock_irqrestore(
+ &info->reassembly_queue_lock, flags);
+ } while (response);
+ info->reassembly_data_length = 0;
+
+ log_rdma_event(INFO, "free receive buffers\n");
+ wait_event(info->wait_receive_queues,
+ info->count_receive_queue + info->count_empty_packet_queue
+ == info->receive_credit_max);
+ destroy_receive_buffers(info);
+
+ /*
+ * For performance reasons, memory registration and deregistration
+ * are not locked by srv_mutex. It is possible some processes are
+ * blocked on transport srv_mutex while holding memory registration.
+ * Release the transport srv_mutex to allow them to hit the failure
+ * path when sending data, and then release memory registartions.
+ */
+ log_rdma_event(INFO, "freeing mr list\n");
+ wake_up_interruptible_all(&info->wait_mr);
+ while (atomic_read(&info->mr_used_count)) {
+ cifs_server_unlock(server);
+ msleep(1000);
+ cifs_server_lock(server);
+ }
+ destroy_mr_list(info);
+
+ ib_free_cq(info->send_cq);
+ ib_free_cq(info->recv_cq);
+ ib_dealloc_pd(info->pd);
+ rdma_destroy_id(info->id);
+
+ /* free mempools */
+ mempool_destroy(info->request_mempool);
+ kmem_cache_destroy(info->request_cache);
+
+ mempool_destroy(info->response_mempool);
+ kmem_cache_destroy(info->response_cache);
+
+ info->transport_status = SMBD_DESTROYED;
+
+ destroy_workqueue(info->workqueue);
+ log_rdma_event(INFO, "rdma session destroyed\n");
+ kfree(info);
+ server->smbd_conn = NULL;
+}
+
+/*
+ * Reconnect this SMBD connection, called from upper layer
+ * return value: 0 on success, or actual error code
+ */
+int smbd_reconnect(struct TCP_Server_Info *server)
+{
+ log_rdma_event(INFO, "reconnecting rdma session\n");
+
+ if (!server->smbd_conn) {
+ log_rdma_event(INFO, "rdma session already destroyed\n");
+ goto create_conn;
+ }
+
+ /*
+ * This is possible if transport is disconnected and we haven't received
+ * notification from RDMA, but upper layer has detected timeout
+ */
+ if (server->smbd_conn->transport_status == SMBD_CONNECTED) {
+ log_rdma_event(INFO, "disconnecting transport\n");
+ smbd_destroy(server);
+ }
+
+create_conn:
+ log_rdma_event(INFO, "creating rdma session\n");
+ server->smbd_conn = smbd_get_connection(
+ server, (struct sockaddr *) &server->dstaddr);
+
+ if (server->smbd_conn)
+ cifs_dbg(VFS, "RDMA transport re-established\n");
+
+ return server->smbd_conn ? 0 : -ENOENT;
+}
+
+static void destroy_caches_and_workqueue(struct smbd_connection *info)
+{
+ destroy_receive_buffers(info);
+ destroy_workqueue(info->workqueue);
+ mempool_destroy(info->response_mempool);
+ kmem_cache_destroy(info->response_cache);
+ mempool_destroy(info->request_mempool);
+ kmem_cache_destroy(info->request_cache);
+}
+
+#define MAX_NAME_LEN 80
+static int allocate_caches_and_workqueue(struct smbd_connection *info)
+{
+ char name[MAX_NAME_LEN];
+ int rc;
+
+ scnprintf(name, MAX_NAME_LEN, "smbd_request_%p", info);
+ info->request_cache =
+ kmem_cache_create(
+ name,
+ sizeof(struct smbd_request) +
+ sizeof(struct smbd_data_transfer),
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (!info->request_cache)
+ return -ENOMEM;
+
+ info->request_mempool =
+ mempool_create(info->send_credit_target, mempool_alloc_slab,
+ mempool_free_slab, info->request_cache);
+ if (!info->request_mempool)
+ goto out1;
+
+ scnprintf(name, MAX_NAME_LEN, "smbd_response_%p", info);
+ info->response_cache =
+ kmem_cache_create(
+ name,
+ sizeof(struct smbd_response) +
+ info->max_receive_size,
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (!info->response_cache)
+ goto out2;
+
+ info->response_mempool =
+ mempool_create(info->receive_credit_max, mempool_alloc_slab,
+ mempool_free_slab, info->response_cache);
+ if (!info->response_mempool)
+ goto out3;
+
+ scnprintf(name, MAX_NAME_LEN, "smbd_%p", info);
+ info->workqueue = create_workqueue(name);
+ if (!info->workqueue)
+ goto out4;
+
+ rc = allocate_receive_buffers(info, info->receive_credit_max);
+ if (rc) {
+ log_rdma_event(ERR, "failed to allocate receive buffers\n");
+ goto out5;
+ }
+
+ return 0;
+
+out5:
+ destroy_workqueue(info->workqueue);
+out4:
+ mempool_destroy(info->response_mempool);
+out3:
+ kmem_cache_destroy(info->response_cache);
+out2:
+ mempool_destroy(info->request_mempool);
+out1:
+ kmem_cache_destroy(info->request_cache);
+ return -ENOMEM;
+}
+
+/* Create a SMBD connection, called by upper layer */
+static struct smbd_connection *_smbd_get_connection(
+ struct TCP_Server_Info *server, struct sockaddr *dstaddr, int port)
+{
+ int rc;
+ struct smbd_connection *info;
+ struct rdma_conn_param conn_param;
+ struct ib_qp_init_attr qp_attr;
+ struct sockaddr_in *addr_in = (struct sockaddr_in *) dstaddr;
+ struct ib_port_immutable port_immutable;
+ u32 ird_ord_hdr[2];
+
+ info = kzalloc(sizeof(struct smbd_connection), GFP_KERNEL);
+ if (!info)
+ return NULL;
+
+ info->transport_status = SMBD_CONNECTING;
+ rc = smbd_ia_open(info, dstaddr, port);
+ if (rc) {
+ log_rdma_event(INFO, "smbd_ia_open rc=%d\n", rc);
+ goto create_id_failed;
+ }
+
+ if (smbd_send_credit_target > info->id->device->attrs.max_cqe ||
+ smbd_send_credit_target > info->id->device->attrs.max_qp_wr) {
+ log_rdma_event(ERR, "consider lowering send_credit_target = %d. Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
+ smbd_send_credit_target,
+ info->id->device->attrs.max_cqe,
+ info->id->device->attrs.max_qp_wr);
+ goto config_failed;
+ }
+
+ if (smbd_receive_credit_max > info->id->device->attrs.max_cqe ||
+ smbd_receive_credit_max > info->id->device->attrs.max_qp_wr) {
+ log_rdma_event(ERR, "consider lowering receive_credit_max = %d. Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
+ smbd_receive_credit_max,
+ info->id->device->attrs.max_cqe,
+ info->id->device->attrs.max_qp_wr);
+ goto config_failed;
+ }
+
+ info->receive_credit_max = smbd_receive_credit_max;
+ info->send_credit_target = smbd_send_credit_target;
+ info->max_send_size = smbd_max_send_size;
+ info->max_fragmented_recv_size = smbd_max_fragmented_recv_size;
+ info->max_receive_size = smbd_max_receive_size;
+ info->keep_alive_interval = smbd_keep_alive_interval;
+
+ if (info->id->device->attrs.max_send_sge < SMBDIRECT_MAX_SEND_SGE ||
+ info->id->device->attrs.max_recv_sge < SMBDIRECT_MAX_RECV_SGE) {
+ log_rdma_event(ERR,
+ "device %.*s max_send_sge/max_recv_sge = %d/%d too small\n",
+ IB_DEVICE_NAME_MAX,
+ info->id->device->name,
+ info->id->device->attrs.max_send_sge,
+ info->id->device->attrs.max_recv_sge);
+ goto config_failed;
+ }
+
+ info->send_cq = NULL;
+ info->recv_cq = NULL;
+ info->send_cq =
+ ib_alloc_cq_any(info->id->device, info,
+ info->send_credit_target, IB_POLL_SOFTIRQ);
+ if (IS_ERR(info->send_cq)) {
+ info->send_cq = NULL;
+ goto alloc_cq_failed;
+ }
+
+ info->recv_cq =
+ ib_alloc_cq_any(info->id->device, info,
+ info->receive_credit_max, IB_POLL_SOFTIRQ);
+ if (IS_ERR(info->recv_cq)) {
+ info->recv_cq = NULL;
+ goto alloc_cq_failed;
+ }
+
+ memset(&qp_attr, 0, sizeof(qp_attr));
+ qp_attr.event_handler = smbd_qp_async_error_upcall;
+ qp_attr.qp_context = info;
+ qp_attr.cap.max_send_wr = info->send_credit_target;
+ qp_attr.cap.max_recv_wr = info->receive_credit_max;
+ qp_attr.cap.max_send_sge = SMBDIRECT_MAX_SEND_SGE;
+ qp_attr.cap.max_recv_sge = SMBDIRECT_MAX_RECV_SGE;
+ qp_attr.cap.max_inline_data = 0;
+ qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
+ qp_attr.qp_type = IB_QPT_RC;
+ qp_attr.send_cq = info->send_cq;
+ qp_attr.recv_cq = info->recv_cq;
+ qp_attr.port_num = ~0;
+
+ rc = rdma_create_qp(info->id, info->pd, &qp_attr);
+ if (rc) {
+ log_rdma_event(ERR, "rdma_create_qp failed %i\n", rc);
+ goto create_qp_failed;
+ }
+
+ memset(&conn_param, 0, sizeof(conn_param));
+ conn_param.initiator_depth = 0;
+
+ conn_param.responder_resources =
+ info->id->device->attrs.max_qp_rd_atom
+ < SMBD_CM_RESPONDER_RESOURCES ?
+ info->id->device->attrs.max_qp_rd_atom :
+ SMBD_CM_RESPONDER_RESOURCES;
+ info->responder_resources = conn_param.responder_resources;
+ log_rdma_mr(INFO, "responder_resources=%d\n",
+ info->responder_resources);
+
+ /* Need to send IRD/ORD in private data for iWARP */
+ info->id->device->ops.get_port_immutable(
+ info->id->device, info->id->port_num, &port_immutable);
+ if (port_immutable.core_cap_flags & RDMA_CORE_PORT_IWARP) {
+ ird_ord_hdr[0] = info->responder_resources;
+ ird_ord_hdr[1] = 1;
+ conn_param.private_data = ird_ord_hdr;
+ conn_param.private_data_len = sizeof(ird_ord_hdr);
+ } else {
+ conn_param.private_data = NULL;
+ conn_param.private_data_len = 0;
+ }
+
+ conn_param.retry_count = SMBD_CM_RETRY;
+ conn_param.rnr_retry_count = SMBD_CM_RNR_RETRY;
+ conn_param.flow_control = 0;
+
+ log_rdma_event(INFO, "connecting to IP %pI4 port %d\n",
+ &addr_in->sin_addr, port);
+
+ init_waitqueue_head(&info->conn_wait);
+ init_waitqueue_head(&info->disconn_wait);
+ init_waitqueue_head(&info->wait_reassembly_queue);
+ rc = rdma_connect(info->id, &conn_param);
+ if (rc) {
+ log_rdma_event(ERR, "rdma_connect() failed with %i\n", rc);
+ goto rdma_connect_failed;
+ }
+
+ wait_event_interruptible(
+ info->conn_wait, info->transport_status != SMBD_CONNECTING);
+
+ if (info->transport_status != SMBD_CONNECTED) {
+ log_rdma_event(ERR, "rdma_connect failed port=%d\n", port);
+ goto rdma_connect_failed;
+ }
+
+ log_rdma_event(INFO, "rdma_connect connected\n");
+
+ rc = allocate_caches_and_workqueue(info);
+ if (rc) {
+ log_rdma_event(ERR, "cache allocation failed\n");
+ goto allocate_cache_failed;
+ }
+
+ init_waitqueue_head(&info->wait_send_queue);
+ INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer);
+ queue_delayed_work(info->workqueue, &info->idle_timer_work,
+ info->keep_alive_interval*HZ);
+
+ init_waitqueue_head(&info->wait_send_pending);
+ atomic_set(&info->send_pending, 0);
+
+ init_waitqueue_head(&info->wait_post_send);
+
+ INIT_WORK(&info->disconnect_work, smbd_disconnect_rdma_work);
+ INIT_WORK(&info->post_send_credits_work, smbd_post_send_credits);
+ info->new_credits_offered = 0;
+ spin_lock_init(&info->lock_new_credits_offered);
+
+ rc = smbd_negotiate(info);
+ if (rc) {
+ log_rdma_event(ERR, "smbd_negotiate rc=%d\n", rc);
+ goto negotiation_failed;
+ }
+
+ rc = allocate_mr_list(info);
+ if (rc) {
+ log_rdma_mr(ERR, "memory registration allocation failed\n");
+ goto allocate_mr_failed;
+ }
+
+ return info;
+
+allocate_mr_failed:
+ /* At this point, need to a full transport shutdown */
+ server->smbd_conn = info;
+ smbd_destroy(server);
+ return NULL;
+
+negotiation_failed:
+ cancel_delayed_work_sync(&info->idle_timer_work);
+ destroy_caches_and_workqueue(info);
+ info->transport_status = SMBD_NEGOTIATE_FAILED;
+ init_waitqueue_head(&info->conn_wait);
+ rdma_disconnect(info->id);
+ wait_event(info->conn_wait,
+ info->transport_status == SMBD_DISCONNECTED);
+
+allocate_cache_failed:
+rdma_connect_failed:
+ rdma_destroy_qp(info->id);
+
+create_qp_failed:
+alloc_cq_failed:
+ if (info->send_cq)
+ ib_free_cq(info->send_cq);
+ if (info->recv_cq)
+ ib_free_cq(info->recv_cq);
+
+config_failed:
+ ib_dealloc_pd(info->pd);
+ rdma_destroy_id(info->id);
+
+create_id_failed:
+ kfree(info);
+ return NULL;
+}
+
+struct smbd_connection *smbd_get_connection(
+ struct TCP_Server_Info *server, struct sockaddr *dstaddr)
+{
+ struct smbd_connection *ret;
+ int port = SMBD_PORT;
+
+try_again:
+ ret = _smbd_get_connection(server, dstaddr, port);
+
+ /* Try SMB_PORT if SMBD_PORT doesn't work */
+ if (!ret && port == SMBD_PORT) {
+ port = SMB_PORT;
+ goto try_again;
+ }
+ return ret;
+}
+
+/*
+ * Receive data from receive reassembly queue
+ * All the incoming data packets are placed in reassembly queue
+ * buf: the buffer to read data into
+ * size: the length of data to read
+ * return value: actual data read
+ * Note: this implementation copies the data from reassebmly queue to receive
+ * buffers used by upper layer. This is not the optimal code path. A better way
+ * to do it is to not have upper layer allocate its receive buffers but rather
+ * borrow the buffer from reassembly queue, and return it after data is
+ * consumed. But this will require more changes to upper layer code, and also
+ * need to consider packet boundaries while they still being reassembled.
+ */
+static int smbd_recv_buf(struct smbd_connection *info, char *buf,
+ unsigned int size)
+{
+ struct smbd_response *response;
+ struct smbd_data_transfer *data_transfer;
+ int to_copy, to_read, data_read, offset;
+ u32 data_length, remaining_data_length, data_offset;
+ int rc;
+
+again:
+ /*
+ * No need to hold the reassembly queue lock all the time as we are
+ * the only one reading from the front of the queue. The transport
+ * may add more entries to the back of the queue at the same time
+ */
+ log_read(INFO, "size=%d info->reassembly_data_length=%d\n", size,
+ info->reassembly_data_length);
+ if (info->reassembly_data_length >= size) {
+ int queue_length;
+ int queue_removed = 0;
+
+ /*
+ * Need to make sure reassembly_data_length is read before
+ * reading reassembly_queue_length and calling
+ * _get_first_reassembly. This call is lock free
+ * as we never read at the end of the queue which are being
+ * updated in SOFTIRQ as more data is received
+ */
+ virt_rmb();
+ queue_length = info->reassembly_queue_length;
+ data_read = 0;
+ to_read = size;
+ offset = info->first_entry_offset;
+ while (data_read < size) {
+ response = _get_first_reassembly(info);
+ data_transfer = smbd_response_payload(response);
+ data_length = le32_to_cpu(data_transfer->data_length);
+ remaining_data_length =
+ le32_to_cpu(
+ data_transfer->remaining_data_length);
+ data_offset = le32_to_cpu(data_transfer->data_offset);
+
+ /*
+ * The upper layer expects RFC1002 length at the
+ * beginning of the payload. Return it to indicate
+ * the total length of the packet. This minimize the
+ * change to upper layer packet processing logic. This
+ * will be eventually remove when an intermediate
+ * transport layer is added
+ */
+ if (response->first_segment && size == 4) {
+ unsigned int rfc1002_len =
+ data_length + remaining_data_length;
+ *((__be32 *)buf) = cpu_to_be32(rfc1002_len);
+ data_read = 4;
+ response->first_segment = false;
+ log_read(INFO, "returning rfc1002 length %d\n",
+ rfc1002_len);
+ goto read_rfc1002_done;
+ }
+
+ to_copy = min_t(int, data_length - offset, to_read);
+ memcpy(
+ buf + data_read,
+ (char *)data_transfer + data_offset + offset,
+ to_copy);
+
+ /* move on to the next buffer? */
+ if (to_copy == data_length - offset) {
+ queue_length--;
+ /*
+ * No need to lock if we are not at the
+ * end of the queue
+ */
+ if (queue_length)
+ list_del(&response->list);
+ else {
+ spin_lock_irq(
+ &info->reassembly_queue_lock);
+ list_del(&response->list);
+ spin_unlock_irq(
+ &info->reassembly_queue_lock);
+ }
+ queue_removed++;
+ info->count_reassembly_queue--;
+ info->count_dequeue_reassembly_queue++;
+ put_receive_buffer(info, response);
+ offset = 0;
+ log_read(INFO, "put_receive_buffer offset=0\n");
+ } else
+ offset += to_copy;
+
+ to_read -= to_copy;
+ data_read += to_copy;
+
+ log_read(INFO, "_get_first_reassembly memcpy %d bytes data_transfer_length-offset=%d after that to_read=%d data_read=%d offset=%d\n",
+ to_copy, data_length - offset,
+ to_read, data_read, offset);
+ }
+
+ spin_lock_irq(&info->reassembly_queue_lock);
+ info->reassembly_data_length -= data_read;
+ info->reassembly_queue_length -= queue_removed;
+ spin_unlock_irq(&info->reassembly_queue_lock);
+
+ info->first_entry_offset = offset;
+ log_read(INFO, "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n",
+ data_read, info->reassembly_data_length,
+ info->first_entry_offset);
+read_rfc1002_done:
+ return data_read;
+ }
+
+ log_read(INFO, "wait_event on more data\n");
+ rc = wait_event_interruptible(
+ info->wait_reassembly_queue,
+ info->reassembly_data_length >= size ||
+ info->transport_status != SMBD_CONNECTED);
+ /* Don't return any data if interrupted */
+ if (rc)
+ return rc;
+
+ if (info->transport_status != SMBD_CONNECTED) {
+ log_read(ERR, "disconnected\n");
+ return -ECONNABORTED;
+ }
+
+ goto again;
+}
+
+/*
+ * Receive a page from receive reassembly queue
+ * page: the page to read data into
+ * to_read: the length of data to read
+ * return value: actual data read
+ */
+static int smbd_recv_page(struct smbd_connection *info,
+ struct page *page, unsigned int page_offset,
+ unsigned int to_read)
+{
+ int ret;
+ char *to_address;
+ void *page_address;
+
+ /* make sure we have the page ready for read */
+ ret = wait_event_interruptible(
+ info->wait_reassembly_queue,
+ info->reassembly_data_length >= to_read ||
+ info->transport_status != SMBD_CONNECTED);
+ if (ret)
+ return ret;
+
+ /* now we can read from reassembly queue and not sleep */
+ page_address = kmap_atomic(page);
+ to_address = (char *) page_address + page_offset;
+
+ log_read(INFO, "reading from page=%p address=%p to_read=%d\n",
+ page, to_address, to_read);
+
+ ret = smbd_recv_buf(info, to_address, to_read);
+ kunmap_atomic(page_address);
+
+ return ret;
+}
+
+/*
+ * Receive data from transport
+ * msg: a msghdr point to the buffer, can be ITER_KVEC or ITER_BVEC
+ * return: total bytes read, or 0. SMB Direct will not do partial read.
+ */
+int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
+{
+ char *buf;
+ struct page *page;
+ unsigned int to_read, page_offset;
+ int rc;
+
+ if (iov_iter_rw(&msg->msg_iter) == WRITE) {
+ /* It's a bug in upper layer to get there */
+ cifs_dbg(VFS, "Invalid msg iter dir %u\n",
+ iov_iter_rw(&msg->msg_iter));
+ rc = -EINVAL;
+ goto out;
+ }
+
+ switch (iov_iter_type(&msg->msg_iter)) {
+ case ITER_KVEC:
+ buf = msg->msg_iter.kvec->iov_base;
+ to_read = msg->msg_iter.kvec->iov_len;
+ rc = smbd_recv_buf(info, buf, to_read);
+ break;
+
+ case ITER_BVEC:
+ page = msg->msg_iter.bvec->bv_page;
+ page_offset = msg->msg_iter.bvec->bv_offset;
+ to_read = msg->msg_iter.bvec->bv_len;
+ rc = smbd_recv_page(info, page, page_offset, to_read);
+ break;
+
+ default:
+ /* It's a bug in upper layer to get there */
+ cifs_dbg(VFS, "Invalid msg type %d\n",
+ iov_iter_type(&msg->msg_iter));
+ rc = -EINVAL;
+ }
+
+out:
+ /* SMBDirect will read it all or nothing */
+ if (rc > 0)
+ msg->msg_iter.count = 0;
+ return rc;
+}
+
+/*
+ * Send data to transport
+ * Each rqst is transported as a SMBDirect payload
+ * rqst: the data to write
+ * return value: 0 if successfully write, otherwise error code
+ */
+int smbd_send(struct TCP_Server_Info *server,
+ int num_rqst, struct smb_rqst *rqst_array)
+{
+ struct smbd_connection *info = server->smbd_conn;
+ struct kvec vecs[SMBDIRECT_MAX_SEND_SGE - 1];
+ int nvecs;
+ int size;
+ unsigned int buflen, remaining_data_length;
+ unsigned int offset, remaining_vec_data_length;
+ int start, i, j;
+ int max_iov_size =
+ info->max_send_size - sizeof(struct smbd_data_transfer);
+ struct kvec *iov;
+ int rc;
+ struct smb_rqst *rqst;
+ int rqst_idx;
+
+ if (info->transport_status != SMBD_CONNECTED)
+ return -EAGAIN;
+
+ /*
+ * Add in the page array if there is one. The caller needs to set
+ * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and
+ * ends at page boundary
+ */
+ remaining_data_length = 0;
+ for (i = 0; i < num_rqst; i++)
+ remaining_data_length += smb_rqst_len(server, &rqst_array[i]);
+
+ if (unlikely(remaining_data_length > info->max_fragmented_send_size)) {
+ /* assertion: payload never exceeds negotiated maximum */
+ log_write(ERR, "payload size %d > max size %d\n",
+ remaining_data_length, info->max_fragmented_send_size);
+ return -EINVAL;
+ }
+
+ log_write(INFO, "num_rqst=%d total length=%u\n",
+ num_rqst, remaining_data_length);
+
+ rqst_idx = 0;
+ do {
+ rqst = &rqst_array[rqst_idx];
+ iov = rqst->rq_iov;
+
+ cifs_dbg(FYI, "Sending smb (RDMA): idx=%d smb_len=%lu\n",
+ rqst_idx, smb_rqst_len(server, rqst));
+ remaining_vec_data_length = 0;
+ for (i = 0; i < rqst->rq_nvec; i++) {
+ remaining_vec_data_length += iov[i].iov_len;
+ dump_smb(iov[i].iov_base, iov[i].iov_len);
+ }
+
+ log_write(INFO, "rqst_idx=%d nvec=%d rqst->rq_npages=%d rq_pagesz=%d rq_tailsz=%d buflen=%lu\n",
+ rqst_idx, rqst->rq_nvec,
+ rqst->rq_npages, rqst->rq_pagesz,
+ rqst->rq_tailsz, smb_rqst_len(server, rqst));
+
+ start = 0;
+ offset = 0;
+ do {
+ buflen = 0;
+ i = start;
+ j = 0;
+ while (i < rqst->rq_nvec &&
+ j < SMBDIRECT_MAX_SEND_SGE - 1 &&
+ buflen < max_iov_size) {
+
+ vecs[j].iov_base = iov[i].iov_base + offset;
+ if (buflen + iov[i].iov_len > max_iov_size) {
+ vecs[j].iov_len =
+ max_iov_size - iov[i].iov_len;
+ buflen = max_iov_size;
+ offset = vecs[j].iov_len;
+ } else {
+ vecs[j].iov_len =
+ iov[i].iov_len - offset;
+ buflen += vecs[j].iov_len;
+ offset = 0;
+ ++i;
+ }
+ ++j;
+ }
+
+ remaining_vec_data_length -= buflen;
+ remaining_data_length -= buflen;
+ log_write(INFO, "sending %s iov[%d] from start=%d nvecs=%d remaining_data_length=%d\n",
+ remaining_vec_data_length > 0 ?
+ "partial" : "complete",
+ rqst->rq_nvec, start, j,
+ remaining_data_length);
+
+ start = i;
+ rc = smbd_post_send_data(info, vecs, j, remaining_data_length);
+ if (rc)
+ goto done;
+ } while (remaining_vec_data_length > 0);
+
+ /* now sending pages if there are any */
+ for (i = 0; i < rqst->rq_npages; i++) {
+ rqst_page_get_length(rqst, i, &buflen, &offset);
+ nvecs = (buflen + max_iov_size - 1) / max_iov_size;
+ log_write(INFO, "sending pages buflen=%d nvecs=%d\n",
+ buflen, nvecs);
+ for (j = 0; j < nvecs; j++) {
+ size = min_t(unsigned int, max_iov_size, remaining_data_length);
+ remaining_data_length -= size;
+ log_write(INFO, "sending pages i=%d offset=%d size=%d remaining_data_length=%d\n",
+ i, j * max_iov_size + offset, size,
+ remaining_data_length);
+ rc = smbd_post_send_page(
+ info, rqst->rq_pages[i],
+ j*max_iov_size + offset,
+ size, remaining_data_length);
+ if (rc)
+ goto done;
+ }
+ }
+ } while (++rqst_idx < num_rqst);
+
+done:
+ /*
+ * As an optimization, we don't wait for individual I/O to finish
+ * before sending the next one.
+ * Send them all and wait for pending send count to get to 0
+ * that means all the I/Os have been out and we are good to return
+ */
+
+ wait_event(info->wait_send_pending,
+ atomic_read(&info->send_pending) == 0);
+
+ return rc;
+}
+
+static void register_mr_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbd_mr *mr;
+ struct ib_cqe *cqe;
+
+ if (wc->status) {
+ log_rdma_mr(ERR, "status=%d\n", wc->status);
+ cqe = wc->wr_cqe;
+ mr = container_of(cqe, struct smbd_mr, cqe);
+ smbd_disconnect_rdma_connection(mr->conn);
+ }
+}
+
+/*
+ * The work queue function that recovers MRs
+ * We need to call ib_dereg_mr() and ib_alloc_mr() before this MR can be used
+ * again. Both calls are slow, so finish them in a workqueue. This will not
+ * block I/O path.
+ * There is one workqueue that recovers MRs, there is no need to lock as the
+ * I/O requests calling smbd_register_mr will never update the links in the
+ * mr_list.
+ */
+static void smbd_mr_recovery_work(struct work_struct *work)
+{
+ struct smbd_connection *info =
+ container_of(work, struct smbd_connection, mr_recovery_work);
+ struct smbd_mr *smbdirect_mr;
+ int rc;
+
+ list_for_each_entry(smbdirect_mr, &info->mr_list, list) {
+ if (smbdirect_mr->state == MR_ERROR) {
+
+ /* recover this MR entry */
+ rc = ib_dereg_mr(smbdirect_mr->mr);
+ if (rc) {
+ log_rdma_mr(ERR,
+ "ib_dereg_mr failed rc=%x\n",
+ rc);
+ smbd_disconnect_rdma_connection(info);
+ continue;
+ }
+
+ smbdirect_mr->mr = ib_alloc_mr(
+ info->pd, info->mr_type,
+ info->max_frmr_depth);
+ if (IS_ERR(smbdirect_mr->mr)) {
+ log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x max_frmr_depth=%x\n",
+ info->mr_type,
+ info->max_frmr_depth);
+ smbd_disconnect_rdma_connection(info);
+ continue;
+ }
+ } else
+ /* This MR is being used, don't recover it */
+ continue;
+
+ smbdirect_mr->state = MR_READY;
+
+ /* smbdirect_mr->state is updated by this function
+ * and is read and updated by I/O issuing CPUs trying
+ * to get a MR, the call to atomic_inc_return
+ * implicates a memory barrier and guarantees this
+ * value is updated before waking up any calls to
+ * get_mr() from the I/O issuing CPUs
+ */
+ if (atomic_inc_return(&info->mr_ready_count) == 1)
+ wake_up_interruptible(&info->wait_mr);
+ }
+}
+
+static void destroy_mr_list(struct smbd_connection *info)
+{
+ struct smbd_mr *mr, *tmp;
+
+ cancel_work_sync(&info->mr_recovery_work);
+ list_for_each_entry_safe(mr, tmp, &info->mr_list, list) {
+ if (mr->state == MR_INVALIDATED)
+ ib_dma_unmap_sg(info->id->device, mr->sgl,
+ mr->sgl_count, mr->dir);
+ ib_dereg_mr(mr->mr);
+ kfree(mr->sgl);
+ kfree(mr);
+ }
+}
+
+/*
+ * Allocate MRs used for RDMA read/write
+ * The number of MRs will not exceed hardware capability in responder_resources
+ * All MRs are kept in mr_list. The MR can be recovered after it's used
+ * Recovery is done in smbd_mr_recovery_work. The content of list entry changes
+ * as MRs are used and recovered for I/O, but the list links will not change
+ */
+static int allocate_mr_list(struct smbd_connection *info)
+{
+ int i;
+ struct smbd_mr *smbdirect_mr, *tmp;
+
+ INIT_LIST_HEAD(&info->mr_list);
+ init_waitqueue_head(&info->wait_mr);
+ spin_lock_init(&info->mr_list_lock);
+ atomic_set(&info->mr_ready_count, 0);
+ atomic_set(&info->mr_used_count, 0);
+ init_waitqueue_head(&info->wait_for_mr_cleanup);
+ INIT_WORK(&info->mr_recovery_work, smbd_mr_recovery_work);
+ /* Allocate more MRs (2x) than hardware responder_resources */
+ for (i = 0; i < info->responder_resources * 2; i++) {
+ smbdirect_mr = kzalloc(sizeof(*smbdirect_mr), GFP_KERNEL);
+ if (!smbdirect_mr)
+ goto out;
+ smbdirect_mr->mr = ib_alloc_mr(info->pd, info->mr_type,
+ info->max_frmr_depth);
+ if (IS_ERR(smbdirect_mr->mr)) {
+ log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x max_frmr_depth=%x\n",
+ info->mr_type, info->max_frmr_depth);
+ goto out;
+ }
+ smbdirect_mr->sgl = kcalloc(
+ info->max_frmr_depth,
+ sizeof(struct scatterlist),
+ GFP_KERNEL);
+ if (!smbdirect_mr->sgl) {
+ log_rdma_mr(ERR, "failed to allocate sgl\n");
+ ib_dereg_mr(smbdirect_mr->mr);
+ goto out;
+ }
+ smbdirect_mr->state = MR_READY;
+ smbdirect_mr->conn = info;
+
+ list_add_tail(&smbdirect_mr->list, &info->mr_list);
+ atomic_inc(&info->mr_ready_count);
+ }
+ return 0;
+
+out:
+ kfree(smbdirect_mr);
+
+ list_for_each_entry_safe(smbdirect_mr, tmp, &info->mr_list, list) {
+ list_del(&smbdirect_mr->list);
+ ib_dereg_mr(smbdirect_mr->mr);
+ kfree(smbdirect_mr->sgl);
+ kfree(smbdirect_mr);
+ }
+ return -ENOMEM;
+}
+
+/*
+ * Get a MR from mr_list. This function waits until there is at least one
+ * MR available in the list. It may access the list while the
+ * smbd_mr_recovery_work is recovering the MR list. This doesn't need a lock
+ * as they never modify the same places. However, there may be several CPUs
+ * issueing I/O trying to get MR at the same time, mr_list_lock is used to
+ * protect this situation.
+ */
+static struct smbd_mr *get_mr(struct smbd_connection *info)
+{
+ struct smbd_mr *ret;
+ int rc;
+again:
+ rc = wait_event_interruptible(info->wait_mr,
+ atomic_read(&info->mr_ready_count) ||
+ info->transport_status != SMBD_CONNECTED);
+ if (rc) {
+ log_rdma_mr(ERR, "wait_event_interruptible rc=%x\n", rc);
+ return NULL;
+ }
+
+ if (info->transport_status != SMBD_CONNECTED) {
+ log_rdma_mr(ERR, "info->transport_status=%x\n",
+ info->transport_status);
+ return NULL;
+ }
+
+ spin_lock(&info->mr_list_lock);
+ list_for_each_entry(ret, &info->mr_list, list) {
+ if (ret->state == MR_READY) {
+ ret->state = MR_REGISTERED;
+ spin_unlock(&info->mr_list_lock);
+ atomic_dec(&info->mr_ready_count);
+ atomic_inc(&info->mr_used_count);
+ return ret;
+ }
+ }
+
+ spin_unlock(&info->mr_list_lock);
+ /*
+ * It is possible that we could fail to get MR because other processes may
+ * try to acquire a MR at the same time. If this is the case, retry it.
+ */
+ goto again;
+}
+
+/*
+ * Register memory for RDMA read/write
+ * pages[]: the list of pages to register memory with
+ * num_pages: the number of pages to register
+ * tailsz: if non-zero, the bytes to register in the last page
+ * writing: true if this is a RDMA write (SMB read), false for RDMA read
+ * need_invalidate: true if this MR needs to be locally invalidated after I/O
+ * return value: the MR registered, NULL if failed.
+ */
+struct smbd_mr *smbd_register_mr(
+ struct smbd_connection *info, struct page *pages[], int num_pages,
+ int offset, int tailsz, bool writing, bool need_invalidate)
+{
+ struct smbd_mr *smbdirect_mr;
+ int rc, i;
+ enum dma_data_direction dir;
+ struct ib_reg_wr *reg_wr;
+
+ if (num_pages > info->max_frmr_depth) {
+ log_rdma_mr(ERR, "num_pages=%d max_frmr_depth=%d\n",
+ num_pages, info->max_frmr_depth);
+ return NULL;
+ }
+
+ smbdirect_mr = get_mr(info);
+ if (!smbdirect_mr) {
+ log_rdma_mr(ERR, "get_mr returning NULL\n");
+ return NULL;
+ }
+ smbdirect_mr->need_invalidate = need_invalidate;
+ smbdirect_mr->sgl_count = num_pages;
+ sg_init_table(smbdirect_mr->sgl, num_pages);
+
+ log_rdma_mr(INFO, "num_pages=0x%x offset=0x%x tailsz=0x%x\n",
+ num_pages, offset, tailsz);
+
+ if (num_pages == 1) {
+ sg_set_page(&smbdirect_mr->sgl[0], pages[0], tailsz, offset);
+ goto skip_multiple_pages;
+ }
+
+ /* We have at least two pages to register */
+ sg_set_page(
+ &smbdirect_mr->sgl[0], pages[0], PAGE_SIZE - offset, offset);
+ i = 1;
+ while (i < num_pages - 1) {
+ sg_set_page(&smbdirect_mr->sgl[i], pages[i], PAGE_SIZE, 0);
+ i++;
+ }
+ sg_set_page(&smbdirect_mr->sgl[i], pages[i],
+ tailsz ? tailsz : PAGE_SIZE, 0);
+
+skip_multiple_pages:
+ dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+ smbdirect_mr->dir = dir;
+ rc = ib_dma_map_sg(info->id->device, smbdirect_mr->sgl, num_pages, dir);
+ if (!rc) {
+ log_rdma_mr(ERR, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",
+ num_pages, dir, rc);
+ goto dma_map_error;
+ }
+
+ rc = ib_map_mr_sg(smbdirect_mr->mr, smbdirect_mr->sgl, num_pages,
+ NULL, PAGE_SIZE);
+ if (rc != num_pages) {
+ log_rdma_mr(ERR,
+ "ib_map_mr_sg failed rc = %d num_pages = %x\n",
+ rc, num_pages);
+ goto map_mr_error;
+ }
+
+ ib_update_fast_reg_key(smbdirect_mr->mr,
+ ib_inc_rkey(smbdirect_mr->mr->rkey));
+ reg_wr = &smbdirect_mr->wr;
+ reg_wr->wr.opcode = IB_WR_REG_MR;
+ smbdirect_mr->cqe.done = register_mr_done;
+ reg_wr->wr.wr_cqe = &smbdirect_mr->cqe;
+ reg_wr->wr.num_sge = 0;
+ reg_wr->wr.send_flags = IB_SEND_SIGNALED;
+ reg_wr->mr = smbdirect_mr->mr;
+ reg_wr->key = smbdirect_mr->mr->rkey;
+ reg_wr->access = writing ?
+ IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
+ IB_ACCESS_REMOTE_READ;
+
+ /*
+ * There is no need for waiting for complemtion on ib_post_send
+ * on IB_WR_REG_MR. Hardware enforces a barrier and order of execution
+ * on the next ib_post_send when we actaully send I/O to remote peer
+ */
+ rc = ib_post_send(info->id->qp, ®_wr->wr, NULL);
+ if (!rc)
+ return smbdirect_mr;
+
+ log_rdma_mr(ERR, "ib_post_send failed rc=%x reg_wr->key=%x\n",
+ rc, reg_wr->key);
+
+ /* If all failed, attempt to recover this MR by setting it MR_ERROR*/
+map_mr_error:
+ ib_dma_unmap_sg(info->id->device, smbdirect_mr->sgl,
+ smbdirect_mr->sgl_count, smbdirect_mr->dir);
+
+dma_map_error:
+ smbdirect_mr->state = MR_ERROR;
+ if (atomic_dec_and_test(&info->mr_used_count))
+ wake_up(&info->wait_for_mr_cleanup);
+
+ smbd_disconnect_rdma_connection(info);
+
+ return NULL;
+}
+
+static void local_inv_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbd_mr *smbdirect_mr;
+ struct ib_cqe *cqe;
+
+ cqe = wc->wr_cqe;
+ smbdirect_mr = container_of(cqe, struct smbd_mr, cqe);
+ smbdirect_mr->state = MR_INVALIDATED;
+ if (wc->status != IB_WC_SUCCESS) {
+ log_rdma_mr(ERR, "invalidate failed status=%x\n", wc->status);
+ smbdirect_mr->state = MR_ERROR;
+ }
+ complete(&smbdirect_mr->invalidate_done);
+}
+
+/*
+ * Deregister a MR after I/O is done
+ * This function may wait if remote invalidation is not used
+ * and we have to locally invalidate the buffer to prevent data is being
+ * modified by remote peer after upper layer consumes it
+ */
+int smbd_deregister_mr(struct smbd_mr *smbdirect_mr)
+{
+ struct ib_send_wr *wr;
+ struct smbd_connection *info = smbdirect_mr->conn;
+ int rc = 0;
+
+ if (smbdirect_mr->need_invalidate) {
+ /* Need to finish local invalidation before returning */
+ wr = &smbdirect_mr->inv_wr;
+ wr->opcode = IB_WR_LOCAL_INV;
+ smbdirect_mr->cqe.done = local_inv_done;
+ wr->wr_cqe = &smbdirect_mr->cqe;
+ wr->num_sge = 0;
+ wr->ex.invalidate_rkey = smbdirect_mr->mr->rkey;
+ wr->send_flags = IB_SEND_SIGNALED;
+
+ init_completion(&smbdirect_mr->invalidate_done);
+ rc = ib_post_send(info->id->qp, wr, NULL);
+ if (rc) {
+ log_rdma_mr(ERR, "ib_post_send failed rc=%x\n", rc);
+ smbd_disconnect_rdma_connection(info);
+ goto done;
+ }
+ wait_for_completion(&smbdirect_mr->invalidate_done);
+ smbdirect_mr->need_invalidate = false;
+ } else
+ /*
+ * For remote invalidation, just set it to MR_INVALIDATED
+ * and defer to mr_recovery_work to recover the MR for next use
+ */
+ smbdirect_mr->state = MR_INVALIDATED;
+
+ if (smbdirect_mr->state == MR_INVALIDATED) {
+ ib_dma_unmap_sg(
+ info->id->device, smbdirect_mr->sgl,
+ smbdirect_mr->sgl_count,
+ smbdirect_mr->dir);
+ smbdirect_mr->state = MR_READY;
+ if (atomic_inc_return(&info->mr_ready_count) == 1)
+ wake_up_interruptible(&info->wait_mr);
+ } else
+ /*
+ * Schedule the work to do MR recovery for future I/Os MR
+ * recovery is slow and don't want it to block current I/O
+ */
+ queue_work(info->workqueue, &info->mr_recovery_work);
+
+done:
+ if (atomic_dec_and_test(&info->mr_used_count))
+ wake_up(&info->wait_for_mr_cleanup);
+
+ return rc;
+}
diff --git a/fs/smb/client/smbdirect.h b/fs/smb/client/smbdirect.h
new file mode 100644
index 000000000000..207ef979cd51
--- /dev/null
+++ b/fs/smb/client/smbdirect.h
@@ -0,0 +1,320 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2017, Microsoft Corporation.
+ *
+ * Author(s): Long Li <longli@microsoft.com>
+ */
+#ifndef _SMBDIRECT_H
+#define _SMBDIRECT_H
+
+#ifdef CONFIG_CIFS_SMB_DIRECT
+#define cifs_rdma_enabled(server) ((server)->rdma)
+
+#include "cifsglob.h"
+#include <rdma/ib_verbs.h>
+#include <rdma/rdma_cm.h>
+#include <linux/mempool.h>
+
+extern int rdma_readwrite_threshold;
+extern int smbd_max_frmr_depth;
+extern int smbd_keep_alive_interval;
+extern int smbd_max_receive_size;
+extern int smbd_max_fragmented_recv_size;
+extern int smbd_max_send_size;
+extern int smbd_send_credit_target;
+extern int smbd_receive_credit_max;
+
+enum keep_alive_status {
+ KEEP_ALIVE_NONE,
+ KEEP_ALIVE_PENDING,
+ KEEP_ALIVE_SENT,
+};
+
+enum smbd_connection_status {
+ SMBD_CREATED,
+ SMBD_CONNECTING,
+ SMBD_CONNECTED,
+ SMBD_NEGOTIATE_FAILED,
+ SMBD_DISCONNECTING,
+ SMBD_DISCONNECTED,
+ SMBD_DESTROYED
+};
+
+/*
+ * The context for the SMBDirect transport
+ * Everything related to the transport is here. It has several logical parts
+ * 1. RDMA related structures
+ * 2. SMBDirect connection parameters
+ * 3. Memory registrations
+ * 4. Receive and reassembly queues for data receive path
+ * 5. mempools for allocating packets
+ */
+struct smbd_connection {
+ enum smbd_connection_status transport_status;
+
+ /* RDMA related */
+ struct rdma_cm_id *id;
+ struct ib_qp_init_attr qp_attr;
+ struct ib_pd *pd;
+ struct ib_cq *send_cq, *recv_cq;
+ struct ib_device_attr dev_attr;
+ int ri_rc;
+ struct completion ri_done;
+ wait_queue_head_t conn_wait;
+ wait_queue_head_t disconn_wait;
+
+ struct completion negotiate_completion;
+ bool negotiate_done;
+
+ struct work_struct disconnect_work;
+ struct work_struct post_send_credits_work;
+
+ spinlock_t lock_new_credits_offered;
+ int new_credits_offered;
+
+ /* Connection parameters defined in [MS-SMBD] 3.1.1.1 */
+ int receive_credit_max;
+ int send_credit_target;
+ int max_send_size;
+ int max_fragmented_recv_size;
+ int max_fragmented_send_size;
+ int max_receive_size;
+ int keep_alive_interval;
+ int max_readwrite_size;
+ enum keep_alive_status keep_alive_requested;
+ int protocol;
+ atomic_t send_credits;
+ atomic_t receive_credits;
+ int receive_credit_target;
+ int fragment_reassembly_remaining;
+
+ /* Memory registrations */
+ /* Maximum number of RDMA read/write outstanding on this connection */
+ int responder_resources;
+ /* Maximum number of pages in a single RDMA write/read on this connection */
+ int max_frmr_depth;
+ /*
+ * If payload is less than or equal to the threshold,
+ * use RDMA send/recv to send upper layer I/O.
+ * If payload is more than the threshold,
+ * use RDMA read/write through memory registration for I/O.
+ */
+ int rdma_readwrite_threshold;
+ enum ib_mr_type mr_type;
+ struct list_head mr_list;
+ spinlock_t mr_list_lock;
+ /* The number of available MRs ready for memory registration */
+ atomic_t mr_ready_count;
+ atomic_t mr_used_count;
+ wait_queue_head_t wait_mr;
+ struct work_struct mr_recovery_work;
+ /* Used by transport to wait until all MRs are returned */
+ wait_queue_head_t wait_for_mr_cleanup;
+
+ /* Activity accoutning */
+ atomic_t send_pending;
+ wait_queue_head_t wait_send_pending;
+ wait_queue_head_t wait_post_send;
+
+ /* Receive queue */
+ struct list_head receive_queue;
+ int count_receive_queue;
+ spinlock_t receive_queue_lock;
+
+ struct list_head empty_packet_queue;
+ int count_empty_packet_queue;
+ spinlock_t empty_packet_queue_lock;
+
+ wait_queue_head_t wait_receive_queues;
+
+ /* Reassembly queue */
+ struct list_head reassembly_queue;
+ spinlock_t reassembly_queue_lock;
+ wait_queue_head_t wait_reassembly_queue;
+
+ /* total data length of reassembly queue */
+ int reassembly_data_length;
+ int reassembly_queue_length;
+ /* the offset to first buffer in reassembly queue */
+ int first_entry_offset;
+
+ bool send_immediate;
+
+ wait_queue_head_t wait_send_queue;
+
+ /*
+ * Indicate if we have received a full packet on the connection
+ * This is used to identify the first SMBD packet of a assembled
+ * payload (SMB packet) in reassembly queue so we can return a
+ * RFC1002 length to upper layer to indicate the length of the SMB
+ * packet received
+ */
+ bool full_packet_received;
+
+ struct workqueue_struct *workqueue;
+ struct delayed_work idle_timer_work;
+
+ /* Memory pool for preallocating buffers */
+ /* request pool for RDMA send */
+ struct kmem_cache *request_cache;
+ mempool_t *request_mempool;
+
+ /* response pool for RDMA receive */
+ struct kmem_cache *response_cache;
+ mempool_t *response_mempool;
+
+ /* for debug purposes */
+ unsigned int count_get_receive_buffer;
+ unsigned int count_put_receive_buffer;
+ unsigned int count_reassembly_queue;
+ unsigned int count_enqueue_reassembly_queue;
+ unsigned int count_dequeue_reassembly_queue;
+ unsigned int count_send_empty;
+};
+
+enum smbd_message_type {
+ SMBD_NEGOTIATE_RESP,
+ SMBD_TRANSFER_DATA,
+};
+
+#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
+
+/* SMBD negotiation request packet [MS-SMBD] 2.2.1 */
+struct smbd_negotiate_req {
+ __le16 min_version;
+ __le16 max_version;
+ __le16 reserved;
+ __le16 credits_requested;
+ __le32 preferred_send_size;
+ __le32 max_receive_size;
+ __le32 max_fragmented_size;
+} __packed;
+
+/* SMBD negotiation response packet [MS-SMBD] 2.2.2 */
+struct smbd_negotiate_resp {
+ __le16 min_version;
+ __le16 max_version;
+ __le16 negotiated_version;
+ __le16 reserved;
+ __le16 credits_requested;
+ __le16 credits_granted;
+ __le32 status;
+ __le32 max_readwrite_size;
+ __le32 preferred_send_size;
+ __le32 max_receive_size;
+ __le32 max_fragmented_size;
+} __packed;
+
+/* SMBD data transfer packet with payload [MS-SMBD] 2.2.3 */
+struct smbd_data_transfer {
+ __le16 credits_requested;
+ __le16 credits_granted;
+ __le16 flags;
+ __le16 reserved;
+ __le32 remaining_data_length;
+ __le32 data_offset;
+ __le32 data_length;
+ __le32 padding;
+ __u8 buffer[];
+} __packed;
+
+/* The packet fields for a registered RDMA buffer */
+struct smbd_buffer_descriptor_v1 {
+ __le64 offset;
+ __le32 token;
+ __le32 length;
+} __packed;
+
+/* Maximum number of SGEs used by smbdirect.c in any send work request */
+#define SMBDIRECT_MAX_SEND_SGE 6
+
+/* The context for a SMBD request */
+struct smbd_request {
+ struct smbd_connection *info;
+ struct ib_cqe cqe;
+
+ /* the SGE entries for this work request */
+ struct ib_sge sge[SMBDIRECT_MAX_SEND_SGE];
+ int num_sge;
+
+ /* SMBD packet header follows this structure */
+ u8 packet[];
+};
+
+/* Maximum number of SGEs used by smbdirect.c in any receive work request */
+#define SMBDIRECT_MAX_RECV_SGE 1
+
+/* The context for a SMBD response */
+struct smbd_response {
+ struct smbd_connection *info;
+ struct ib_cqe cqe;
+ struct ib_sge sge;
+
+ enum smbd_message_type type;
+
+ /* Link to receive queue or reassembly queue */
+ struct list_head list;
+
+ /* Indicate if this is the 1st packet of a payload */
+ bool first_segment;
+
+ /* SMBD packet header and payload follows this structure */
+ u8 packet[];
+};
+
+/* Create a SMBDirect session */
+struct smbd_connection *smbd_get_connection(
+ struct TCP_Server_Info *server, struct sockaddr *dstaddr);
+
+/* Reconnect SMBDirect session */
+int smbd_reconnect(struct TCP_Server_Info *server);
+/* Destroy SMBDirect session */
+void smbd_destroy(struct TCP_Server_Info *server);
+
+/* Interface for carrying upper layer I/O through send/recv */
+int smbd_recv(struct smbd_connection *info, struct msghdr *msg);
+int smbd_send(struct TCP_Server_Info *server,
+ int num_rqst, struct smb_rqst *rqst);
+
+enum mr_state {
+ MR_READY,
+ MR_REGISTERED,
+ MR_INVALIDATED,
+ MR_ERROR
+};
+
+struct smbd_mr {
+ struct smbd_connection *conn;
+ struct list_head list;
+ enum mr_state state;
+ struct ib_mr *mr;
+ struct scatterlist *sgl;
+ int sgl_count;
+ enum dma_data_direction dir;
+ union {
+ struct ib_reg_wr wr;
+ struct ib_send_wr inv_wr;
+ };
+ struct ib_cqe cqe;
+ bool need_invalidate;
+ struct completion invalidate_done;
+};
+
+/* Interfaces to register and deregister MR for RDMA read/write */
+struct smbd_mr *smbd_register_mr(
+ struct smbd_connection *info, struct page *pages[], int num_pages,
+ int offset, int tailsz, bool writing, bool need_invalidate);
+int smbd_deregister_mr(struct smbd_mr *mr);
+
+#else
+#define cifs_rdma_enabled(server) 0
+struct smbd_connection {};
+static inline void *smbd_get_connection(
+ struct TCP_Server_Info *server, struct sockaddr *dstaddr) {return NULL;}
+static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1; }
+static inline void smbd_destroy(struct TCP_Server_Info *server) {}
+static inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1; }
+static inline int smbd_send(struct TCP_Server_Info *server, int num_rqst, struct smb_rqst *rqst) {return -1; }
+#endif
+
+#endif
diff --git a/fs/smb/client/smbencrypt.c b/fs/smb/client/smbencrypt.c
new file mode 100644
index 000000000000..f0ce26414f17
--- /dev/null
+++ b/fs/smb/client/smbencrypt.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ SMB parameters and setup
+ Copyright (C) Andrew Tridgell 1992-2000
+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000
+ Modified by Jeremy Allison 1995.
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
+ Modified by Steve French (sfrench@us.ibm.com) 2002-2003
+
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fips.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+#include "cifs_fs_sb.h"
+#include "cifs_unicode.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "cifsproto.h"
+#include "../common/md4.h"
+
+#ifndef false
+#define false 0
+#endif
+#ifndef true
+#define true 1
+#endif
+
+/* following came from the other byteorder.h to avoid include conflicts */
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
+#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
+
+/* produce a md4 message digest from data of length n bytes */
+static int
+mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
+{
+ int rc;
+ struct md4_ctx mctx;
+
+ rc = cifs_md4_init(&mctx);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not init MD4\n", __func__);
+ goto mdfour_err;
+ }
+ rc = cifs_md4_update(&mctx, link_str, link_len);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not update MD4\n", __func__);
+ goto mdfour_err;
+ }
+ rc = cifs_md4_final(&mctx, md4_hash);
+ if (rc)
+ cifs_dbg(VFS, "%s: Could not finalize MD4\n", __func__);
+
+
+mdfour_err:
+ return rc;
+}
+
+/*
+ * Creates the MD4 Hash of the users password in NT UNICODE.
+ */
+
+int
+E_md4hash(const unsigned char *passwd, unsigned char *p16,
+ const struct nls_table *codepage)
+{
+ int rc;
+ int len;
+ __le16 wpwd[129];
+
+ /* Password cannot be longer than 128 characters */
+ if (passwd) /* Password must be converted to NT unicode */
+ len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
+ else {
+ len = 0;
+ *wpwd = 0; /* Ensure string is null terminated */
+ }
+
+ rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__le16));
+ memzero_explicit(wpwd, sizeof(wpwd));
+
+ return rc;
+}
diff --git a/fs/smb/client/smberr.h b/fs/smb/client/smberr.h
new file mode 100644
index 000000000000..aeffdad829e2
--- /dev/null
+++ b/fs/smb/client/smberr.h
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002,2004
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * See Error Codes section of the SNIA CIFS Specification
+ * for more information
+ *
+ */
+
+#define SUCCESS 0x00 /* The request was successful. */
+#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
+#define ERRSRV 0x02 /* Error is generated by the file server daemon */
+#define ERRHRD 0x03 /* Error is a hardware error. */
+#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
+
+/* The following error codes may be generated with the SUCCESS error class.*/
+
+/*#define SUCCESS 0 The request was successful. */
+
+/* The following error codes may be generated with the ERRDOS error class.*/
+
+#define ERRbadfunc 1 /* Invalid function. The server did not
+ recognize or could not perform a
+ system call generated by the server,
+ e.g., set the DIRECTORY attribute on
+ a data file, invalid seek mode. */
+#define ERRbadfile 2 /* File not found. The last component
+ of a file's pathname could not be
+ found. */
+#define ERRbadpath 3 /* Directory invalid. A directory
+ component in a pathname could not be
+ found. */
+#define ERRnofids 4 /* Too many open files. The server has
+ no file handles available. */
+#define ERRnoaccess 5 /* Access denied, the client's context
+ does not permit the requested
+ function. This includes the
+ following conditions: invalid rename
+ command, write to Fid open for read
+ only, read on Fid open for write
+ only, attempt to delete a non-empty
+ directory */
+#define ERRbadfid 6 /* Invalid file handle. The file handle
+ specified was not recognized by the
+ server. */
+#define ERRbadmcb 7 /* Memory control blocks destroyed. */
+#define ERRnomem 8 /* Insufficient server memory to
+ perform the requested function. */
+#define ERRbadmem 9 /* Invalid memory block address. */
+#define ERRbadenv 10 /* Invalid environment. */
+#define ERRbadformat 11 /* Invalid format. */
+#define ERRbadaccess 12 /* Invalid open mode. */
+#define ERRbaddata 13 /* Invalid data (generated only by
+ IOCTL calls within the server). */
+#define ERRbaddrive 15 /* Invalid drive specified. */
+#define ERRremcd 16 /* A Delete Directory request attempted
+ to remove the server's current
+ directory. */
+#define ERRdiffdevice 17 /* Not same device (e.g., a cross
+ volume rename was attempted */
+#define ERRnofiles 18 /* A File Search command can find no
+ more files matching the specified
+ criteria. */
+#define ERRwriteprot 19 /* media is write protected */
+#define ERRgeneral 31
+#define ERRbadshare 32 /* The sharing mode specified for an
+ Open conflicts with existing FIDs on
+ the file. */
+#define ERRlock 33 /* A Lock request conflicted with an
+ existing lock or specified an
+ invalid mode, or an Unlock requested
+ attempted to remove a lock held by
+ another process. */
+#define ERRunsup 50
+#define ERRnosuchshare 67
+#define ERRfilexists 80 /* The file named in the request
+ already exists. */
+#define ERRinvparm 87
+#define ERRdiskfull 112
+#define ERRinvname 123
+#define ERRinvlevel 124
+#define ERRdirnotempty 145
+#define ERRnotlocked 158
+#define ERRcancelviolation 173
+#define ERRalreadyexists 183
+#define ERRbadpipe 230
+#define ERRpipebusy 231
+#define ERRpipeclosing 232
+#define ERRnotconnected 233
+#define ERRmoredata 234
+#define ERReasnotsupported 282
+#define ErrQuota 0x200 /* The operation would cause a quota
+ limit to be exceeded. */
+#define ErrNotALink 0x201 /* A link operation was performed on a
+ pathname that was not a link. */
+
+/* Below errors are used internally (do not come over the wire) for passthrough
+ from STATUS codes to POSIX only */
+#define ERRsymlink 0xFFFD
+#define ErrTooManyLinks 0xFFFE
+
+/* Following error codes may be generated with the ERRSRV error class.*/
+
+#define ERRerror 1 /* Non-specific error code. It is
+ returned under the following
+ conditions: resource other than disk
+ space exhausted (e.g. TIDs), first
+ SMB command was not negotiate,
+ multiple negotiates attempted, and
+ internal server error. */
+#define ERRbadpw 2 /* Bad password - name/password pair in
+ a TreeConnect or Session Setup are
+ invalid. */
+#define ERRbadtype 3 /* used for indicating DFS referral
+ needed */
+#define ERRaccess 4 /* The client does not have the
+ necessary access rights within the
+ specified context for requested
+ function. */
+#define ERRinvtid 5 /* The Tid specified in a command was
+ invalid. */
+#define ERRinvnetname 6 /* Invalid network name in tree
+ connect. */
+#define ERRinvdevice 7 /* Invalid device - printer request
+ made to non-printer connection or
+ non-printer request made to printer
+ connection. */
+#define ERRqfull 49 /* Print queue full (files) -- returned
+ by open print file. */
+#define ERRqtoobig 50 /* Print queue full -- no space. */
+#define ERRqeof 51 /* EOF on print queue dump */
+#define ERRinvpfid 52 /* Invalid print file FID. */
+#define ERRsmbcmd 64 /* The server did not recognize the
+ command received. */
+#define ERRsrverror 65 /* The server encountered an internal
+ error, e.g., system file
+ unavailable. */
+#define ERRbadBID 66 /* (obsolete) */
+#define ERRfilespecs 67 /* The Fid and pathname parameters
+ contained an invalid combination of
+ values. */
+#define ERRbadLink 68 /* (obsolete) */
+#define ERRbadpermits 69 /* The access permissions specified for
+ a file or directory are not a valid
+ combination. */
+#define ERRbadPID 70
+#define ERRsetattrmode 71 /* attribute (mode) is invalid */
+#define ERRpaused 81 /* Server is paused */
+#define ERRmsgoff 82 /* reserved - messaging off */
+#define ERRnoroom 83 /* reserved - no room for message */
+#define ERRrmuns 87 /* reserved - too many remote names */
+#define ERRtimeout 88 /* operation timed out */
+#define ERRnoresource 89 /* No resources available for request
+ */
+#define ERRtoomanyuids 90 /* Too many UIDs active on this session
+ */
+#define ERRbaduid 91 /* The UID is not known as a valid user
+ */
+#define ERRusempx 250 /* temporarily unable to use raw */
+#define ERRusestd 251 /* temporarily unable to use either raw
+ or mpx */
+#define ERR_NOTIFY_ENUM_DIR 1024
+#define ERRnoSuchUser 2238 /* user account does not exist */
+#define ERRaccountexpired 2239
+#define ERRbadclient 2240 /* can not logon from this client */
+#define ERRbadLogonTime 2241 /* logon hours do not allow this */
+#define ERRpasswordExpired 2242
+#define ERRnetlogonNotStarted 2455
+#define ERRnosupport 0xFFFF
diff --git a/fs/smb/client/trace.c b/fs/smb/client/trace.c
new file mode 100644
index 000000000000..465483787193
--- /dev/null
+++ b/fs/smb/client/trace.c
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, Microsoft Corporation.
+ *
+ * Author(s): Steve French <stfrench@microsoft.com>
+ */
+#define CREATE_TRACE_POINTS
+#include "trace.h"
diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h
new file mode 100644
index 000000000000..d3053bd8ae73
--- /dev/null
+++ b/fs/smb/client/trace.h
@@ -0,0 +1,1070 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018, Microsoft Corporation.
+ *
+ * Author(s): Steve French <stfrench@microsoft.com>
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM cifs
+
+#if !defined(_CIFS_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _CIFS_TRACE_H
+
+#include <linux/tracepoint.h>
+#include <linux/net.h>
+#include <linux/inet.h>
+
+/*
+ * Please use this 3-part article as a reference for writing new tracepoints:
+ * https://lwn.net/Articles/379903/
+ */
+
+/* For logging errors in read or write */
+DECLARE_EVENT_CLASS(smb3_rw_err_class,
+ TP_PROTO(unsigned int xid,
+ __u64 fid,
+ __u32 tid,
+ __u64 sesid,
+ __u64 offset,
+ __u32 len,
+ int rc),
+ TP_ARGS(xid, fid, tid, sesid, offset, len, rc),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u64, fid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(__u64, offset)
+ __field(__u32, len)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->fid = fid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->offset = offset;
+ __entry->len = len;
+ __entry->rc = rc;
+ ),
+ TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d",
+ __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+ __entry->offset, __entry->len, __entry->rc)
+)
+
+#define DEFINE_SMB3_RW_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_rw_err_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u64 fid, \
+ __u32 tid, \
+ __u64 sesid, \
+ __u64 offset, \
+ __u32 len, \
+ int rc), \
+ TP_ARGS(xid, fid, tid, sesid, offset, len, rc))
+
+DEFINE_SMB3_RW_ERR_EVENT(write_err);
+DEFINE_SMB3_RW_ERR_EVENT(read_err);
+DEFINE_SMB3_RW_ERR_EVENT(query_dir_err);
+DEFINE_SMB3_RW_ERR_EVENT(zero_err);
+DEFINE_SMB3_RW_ERR_EVENT(falloc_err);
+
+
+/* For logging successful read or write */
+DECLARE_EVENT_CLASS(smb3_rw_done_class,
+ TP_PROTO(unsigned int xid,
+ __u64 fid,
+ __u32 tid,
+ __u64 sesid,
+ __u64 offset,
+ __u32 len),
+ TP_ARGS(xid, fid, tid, sesid, offset, len),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u64, fid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(__u64, offset)
+ __field(__u32, len)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->fid = fid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->offset = offset;
+ __entry->len = len;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x",
+ __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+ __entry->offset, __entry->len)
+)
+
+#define DEFINE_SMB3_RW_DONE_EVENT(name) \
+DEFINE_EVENT(smb3_rw_done_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u64 fid, \
+ __u32 tid, \
+ __u64 sesid, \
+ __u64 offset, \
+ __u32 len), \
+ TP_ARGS(xid, fid, tid, sesid, offset, len))
+
+DEFINE_SMB3_RW_DONE_EVENT(write_enter);
+DEFINE_SMB3_RW_DONE_EVENT(read_enter);
+DEFINE_SMB3_RW_DONE_EVENT(query_dir_enter);
+DEFINE_SMB3_RW_DONE_EVENT(zero_enter);
+DEFINE_SMB3_RW_DONE_EVENT(falloc_enter);
+DEFINE_SMB3_RW_DONE_EVENT(write_done);
+DEFINE_SMB3_RW_DONE_EVENT(read_done);
+DEFINE_SMB3_RW_DONE_EVENT(query_dir_done);
+DEFINE_SMB3_RW_DONE_EVENT(zero_done);
+DEFINE_SMB3_RW_DONE_EVENT(falloc_done);
+
+/* For logging successful set EOF (truncate) */
+DECLARE_EVENT_CLASS(smb3_eof_class,
+ TP_PROTO(unsigned int xid,
+ __u64 fid,
+ __u32 tid,
+ __u64 sesid,
+ __u64 offset),
+ TP_ARGS(xid, fid, tid, sesid, offset),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u64, fid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(__u64, offset)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->fid = fid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->offset = offset;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx",
+ __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+ __entry->offset)
+)
+
+#define DEFINE_SMB3_EOF_EVENT(name) \
+DEFINE_EVENT(smb3_eof_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u64 fid, \
+ __u32 tid, \
+ __u64 sesid, \
+ __u64 offset), \
+ TP_ARGS(xid, fid, tid, sesid, offset))
+
+DEFINE_SMB3_EOF_EVENT(set_eof);
+
+/*
+ * For handle based calls other than read and write, and get/set info
+ */
+DECLARE_EVENT_CLASS(smb3_fd_class,
+ TP_PROTO(unsigned int xid,
+ __u64 fid,
+ __u32 tid,
+ __u64 sesid),
+ TP_ARGS(xid, fid, tid, sesid),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u64, fid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->fid = fid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ ),
+ TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx",
+ __entry->xid, __entry->sesid, __entry->tid, __entry->fid)
+)
+
+#define DEFINE_SMB3_FD_EVENT(name) \
+DEFINE_EVENT(smb3_fd_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u64 fid, \
+ __u32 tid, \
+ __u64 sesid), \
+ TP_ARGS(xid, fid, tid, sesid))
+
+DEFINE_SMB3_FD_EVENT(flush_enter);
+DEFINE_SMB3_FD_EVENT(flush_done);
+DEFINE_SMB3_FD_EVENT(close_enter);
+DEFINE_SMB3_FD_EVENT(close_done);
+DEFINE_SMB3_FD_EVENT(oplock_not_found);
+
+DECLARE_EVENT_CLASS(smb3_fd_err_class,
+ TP_PROTO(unsigned int xid,
+ __u64 fid,
+ __u32 tid,
+ __u64 sesid,
+ int rc),
+ TP_ARGS(xid, fid, tid, sesid, rc),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u64, fid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->fid = fid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->rc = rc;
+ ),
+ TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx rc=%d",
+ __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+ __entry->rc)
+)
+
+#define DEFINE_SMB3_FD_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_fd_err_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u64 fid, \
+ __u32 tid, \
+ __u64 sesid, \
+ int rc), \
+ TP_ARGS(xid, fid, tid, sesid, rc))
+
+DEFINE_SMB3_FD_ERR_EVENT(flush_err);
+DEFINE_SMB3_FD_ERR_EVENT(lock_err);
+DEFINE_SMB3_FD_ERR_EVENT(close_err);
+
+/*
+ * For handle based query/set info calls
+ */
+DECLARE_EVENT_CLASS(smb3_inf_enter_class,
+ TP_PROTO(unsigned int xid,
+ __u64 fid,
+ __u32 tid,
+ __u64 sesid,
+ __u8 infclass,
+ __u32 type),
+ TP_ARGS(xid, fid, tid, sesid, infclass, type),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u64, fid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(__u8, infclass)
+ __field(__u32, type)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->fid = fid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->infclass = infclass;
+ __entry->type = type;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx class=%u type=0x%x",
+ __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+ __entry->infclass, __entry->type)
+)
+
+#define DEFINE_SMB3_INF_ENTER_EVENT(name) \
+DEFINE_EVENT(smb3_inf_enter_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u64 fid, \
+ __u32 tid, \
+ __u64 sesid, \
+ __u8 infclass, \
+ __u32 type), \
+ TP_ARGS(xid, fid, tid, sesid, infclass, type))
+
+DEFINE_SMB3_INF_ENTER_EVENT(query_info_enter);
+DEFINE_SMB3_INF_ENTER_EVENT(query_info_done);
+DEFINE_SMB3_INF_ENTER_EVENT(notify_enter);
+DEFINE_SMB3_INF_ENTER_EVENT(notify_done);
+
+DECLARE_EVENT_CLASS(smb3_inf_err_class,
+ TP_PROTO(unsigned int xid,
+ __u64 fid,
+ __u32 tid,
+ __u64 sesid,
+ __u8 infclass,
+ __u32 type,
+ int rc),
+ TP_ARGS(xid, fid, tid, sesid, infclass, type, rc),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u64, fid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(__u8, infclass)
+ __field(__u32, type)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->fid = fid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->infclass = infclass;
+ __entry->type = type;
+ __entry->rc = rc;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx class=%u type=0x%x rc=%d",
+ __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+ __entry->infclass, __entry->type, __entry->rc)
+)
+
+#define DEFINE_SMB3_INF_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_inf_err_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u64 fid, \
+ __u32 tid, \
+ __u64 sesid, \
+ __u8 infclass, \
+ __u32 type, \
+ int rc), \
+ TP_ARGS(xid, fid, tid, sesid, infclass, type, rc))
+
+DEFINE_SMB3_INF_ERR_EVENT(query_info_err);
+DEFINE_SMB3_INF_ERR_EVENT(set_info_err);
+DEFINE_SMB3_INF_ERR_EVENT(notify_err);
+DEFINE_SMB3_INF_ERR_EVENT(fsctl_err);
+
+DECLARE_EVENT_CLASS(smb3_inf_compound_enter_class,
+ TP_PROTO(unsigned int xid,
+ __u32 tid,
+ __u64 sesid,
+ const char *full_path),
+ TP_ARGS(xid, tid, sesid, full_path),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __string(path, full_path)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __assign_str(path, full_path);
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x path=%s",
+ __entry->xid, __entry->sesid, __entry->tid,
+ __get_str(path))
+)
+
+#define DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(name) \
+DEFINE_EVENT(smb3_inf_compound_enter_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u32 tid, \
+ __u64 sesid, \
+ const char *full_path), \
+ TP_ARGS(xid, tid, sesid, full_path))
+
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_info_compound_enter);
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(posix_query_info_compound_enter);
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter);
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter);
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter);
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_eof_enter);
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_info_compound_enter);
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(delete_enter);
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mkdir_enter);
+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(tdis_enter);
+
+
+DECLARE_EVENT_CLASS(smb3_inf_compound_done_class,
+ TP_PROTO(unsigned int xid,
+ __u32 tid,
+ __u64 sesid),
+ TP_ARGS(xid, tid, sesid),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x",
+ __entry->xid, __entry->sesid, __entry->tid)
+)
+
+#define DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(name) \
+DEFINE_EVENT(smb3_inf_compound_done_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u32 tid, \
+ __u64 sesid), \
+ TP_ARGS(xid, tid, sesid))
+
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_info_compound_done);
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(posix_query_info_compound_done);
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done);
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done);
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done);
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_eof_done);
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_info_compound_done);
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(delete_done);
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mkdir_done);
+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(tdis_done);
+
+
+DECLARE_EVENT_CLASS(smb3_inf_compound_err_class,
+ TP_PROTO(unsigned int xid,
+ __u32 tid,
+ __u64 sesid,
+ int rc),
+ TP_ARGS(xid, tid, sesid, rc),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->rc = rc;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x rc=%d",
+ __entry->xid, __entry->sesid, __entry->tid,
+ __entry->rc)
+)
+
+#define DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_inf_compound_err_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u32 tid, \
+ __u64 sesid, \
+ int rc), \
+ TP_ARGS(xid, tid, sesid, rc))
+
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_info_compound_err);
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(posix_query_info_compound_err);
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err);
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err);
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err);
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_eof_err);
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_info_compound_err);
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mkdir_err);
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(delete_err);
+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(tdis_err);
+
+/*
+ * For logging SMB3 Status code and Command for responses which return errors
+ */
+DECLARE_EVENT_CLASS(smb3_cmd_err_class,
+ TP_PROTO(__u32 tid,
+ __u64 sesid,
+ __u16 cmd,
+ __u64 mid,
+ __u32 status,
+ int rc),
+ TP_ARGS(tid, sesid, cmd, mid, status, rc),
+ TP_STRUCT__entry(
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(__u16, cmd)
+ __field(__u64, mid)
+ __field(__u32, status)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->cmd = cmd;
+ __entry->mid = mid;
+ __entry->status = status;
+ __entry->rc = rc;
+ ),
+ TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu status=0x%x rc=%d",
+ __entry->sesid, __entry->tid, __entry->cmd, __entry->mid,
+ __entry->status, __entry->rc)
+)
+
+#define DEFINE_SMB3_CMD_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_cmd_err_class, smb3_##name, \
+ TP_PROTO(__u32 tid, \
+ __u64 sesid, \
+ __u16 cmd, \
+ __u64 mid, \
+ __u32 status, \
+ int rc), \
+ TP_ARGS(tid, sesid, cmd, mid, status, rc))
+
+DEFINE_SMB3_CMD_ERR_EVENT(cmd_err);
+
+DECLARE_EVENT_CLASS(smb3_cmd_done_class,
+ TP_PROTO(__u32 tid,
+ __u64 sesid,
+ __u16 cmd,
+ __u64 mid),
+ TP_ARGS(tid, sesid, cmd, mid),
+ TP_STRUCT__entry(
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(__u16, cmd)
+ __field(__u64, mid)
+ ),
+ TP_fast_assign(
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->cmd = cmd;
+ __entry->mid = mid;
+ ),
+ TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu",
+ __entry->sesid, __entry->tid,
+ __entry->cmd, __entry->mid)
+)
+
+#define DEFINE_SMB3_CMD_DONE_EVENT(name) \
+DEFINE_EVENT(smb3_cmd_done_class, smb3_##name, \
+ TP_PROTO(__u32 tid, \
+ __u64 sesid, \
+ __u16 cmd, \
+ __u64 mid), \
+ TP_ARGS(tid, sesid, cmd, mid))
+
+DEFINE_SMB3_CMD_DONE_EVENT(cmd_enter);
+DEFINE_SMB3_CMD_DONE_EVENT(cmd_done);
+DEFINE_SMB3_CMD_DONE_EVENT(ses_expired);
+
+DECLARE_EVENT_CLASS(smb3_mid_class,
+ TP_PROTO(__u16 cmd,
+ __u64 mid,
+ __u32 pid,
+ unsigned long when_sent,
+ unsigned long when_received),
+ TP_ARGS(cmd, mid, pid, when_sent, when_received),
+ TP_STRUCT__entry(
+ __field(__u16, cmd)
+ __field(__u64, mid)
+ __field(__u32, pid)
+ __field(unsigned long, when_sent)
+ __field(unsigned long, when_received)
+ ),
+ TP_fast_assign(
+ __entry->cmd = cmd;
+ __entry->mid = mid;
+ __entry->pid = pid;
+ __entry->when_sent = when_sent;
+ __entry->when_received = when_received;
+ ),
+ TP_printk("\tcmd=%u mid=%llu pid=%u, when_sent=%lu when_rcv=%lu",
+ __entry->cmd, __entry->mid, __entry->pid, __entry->when_sent,
+ __entry->when_received)
+)
+
+#define DEFINE_SMB3_MID_EVENT(name) \
+DEFINE_EVENT(smb3_mid_class, smb3_##name, \
+ TP_PROTO(__u16 cmd, \
+ __u64 mid, \
+ __u32 pid, \
+ unsigned long when_sent, \
+ unsigned long when_received), \
+ TP_ARGS(cmd, mid, pid, when_sent, when_received))
+
+DEFINE_SMB3_MID_EVENT(slow_rsp);
+
+DECLARE_EVENT_CLASS(smb3_exit_err_class,
+ TP_PROTO(unsigned int xid,
+ const char *func_name,
+ int rc),
+ TP_ARGS(xid, func_name, rc),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __string(func_name, func_name)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __assign_str(func_name, func_name);
+ __entry->rc = rc;
+ ),
+ TP_printk("\t%s: xid=%u rc=%d",
+ __get_str(func_name), __entry->xid, __entry->rc)
+)
+
+#define DEFINE_SMB3_EXIT_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_exit_err_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ const char *func_name, \
+ int rc), \
+ TP_ARGS(xid, func_name, rc))
+
+DEFINE_SMB3_EXIT_ERR_EVENT(exit_err);
+
+
+DECLARE_EVENT_CLASS(smb3_sync_err_class,
+ TP_PROTO(unsigned long ino,
+ int rc),
+ TP_ARGS(ino, rc),
+ TP_STRUCT__entry(
+ __field(unsigned long, ino)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->ino = ino;
+ __entry->rc = rc;
+ ),
+ TP_printk("\tino=%lu rc=%d",
+ __entry->ino, __entry->rc)
+)
+
+#define DEFINE_SMB3_SYNC_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_sync_err_class, cifs_##name, \
+ TP_PROTO(unsigned long ino, \
+ int rc), \
+ TP_ARGS(ino, rc))
+
+DEFINE_SMB3_SYNC_ERR_EVENT(fsync_err);
+DEFINE_SMB3_SYNC_ERR_EVENT(flush_err);
+
+
+DECLARE_EVENT_CLASS(smb3_enter_exit_class,
+ TP_PROTO(unsigned int xid,
+ const char *func_name),
+ TP_ARGS(xid, func_name),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __string(func_name, func_name)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __assign_str(func_name, func_name);
+ ),
+ TP_printk("\t%s: xid=%u",
+ __get_str(func_name), __entry->xid)
+)
+
+#define DEFINE_SMB3_ENTER_EXIT_EVENT(name) \
+DEFINE_EVENT(smb3_enter_exit_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ const char *func_name), \
+ TP_ARGS(xid, func_name))
+
+DEFINE_SMB3_ENTER_EXIT_EVENT(enter);
+DEFINE_SMB3_ENTER_EXIT_EVENT(exit_done);
+
+/*
+ * For SMB2/SMB3 tree connect
+ */
+
+DECLARE_EVENT_CLASS(smb3_tcon_class,
+ TP_PROTO(unsigned int xid,
+ __u32 tid,
+ __u64 sesid,
+ const char *unc_name,
+ int rc),
+ TP_ARGS(xid, tid, sesid, unc_name, rc),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __string(name, unc_name)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __assign_str(name, unc_name);
+ __entry->rc = rc;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x unc_name=%s rc=%d",
+ __entry->xid, __entry->sesid, __entry->tid,
+ __get_str(name), __entry->rc)
+)
+
+#define DEFINE_SMB3_TCON_EVENT(name) \
+DEFINE_EVENT(smb3_tcon_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u32 tid, \
+ __u64 sesid, \
+ const char *unc_name, \
+ int rc), \
+ TP_ARGS(xid, tid, sesid, unc_name, rc))
+
+DEFINE_SMB3_TCON_EVENT(tcon);
+
+
+/*
+ * For smb2/smb3 open (including create and mkdir) calls
+ */
+
+DECLARE_EVENT_CLASS(smb3_open_enter_class,
+ TP_PROTO(unsigned int xid,
+ __u32 tid,
+ __u64 sesid,
+ const char *full_path,
+ int create_options,
+ int desired_access),
+ TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __string(path, full_path)
+ __field(int, create_options)
+ __field(int, desired_access)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __assign_str(path, full_path);
+ __entry->create_options = create_options;
+ __entry->desired_access = desired_access;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x path=%s cr_opts=0x%x des_access=0x%x",
+ __entry->xid, __entry->sesid, __entry->tid, __get_str(path),
+ __entry->create_options, __entry->desired_access)
+)
+
+#define DEFINE_SMB3_OPEN_ENTER_EVENT(name) \
+DEFINE_EVENT(smb3_open_enter_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u32 tid, \
+ __u64 sesid, \
+ const char *full_path, \
+ int create_options, \
+ int desired_access), \
+ TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access))
+
+DEFINE_SMB3_OPEN_ENTER_EVENT(open_enter);
+DEFINE_SMB3_OPEN_ENTER_EVENT(posix_mkdir_enter);
+
+DECLARE_EVENT_CLASS(smb3_open_err_class,
+ TP_PROTO(unsigned int xid,
+ __u32 tid,
+ __u64 sesid,
+ int create_options,
+ int desired_access,
+ int rc),
+ TP_ARGS(xid, tid, sesid, create_options, desired_access, rc),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(int, create_options)
+ __field(int, desired_access)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->create_options = create_options;
+ __entry->desired_access = desired_access;
+ __entry->rc = rc;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x cr_opts=0x%x des_access=0x%x rc=%d",
+ __entry->xid, __entry->sesid, __entry->tid,
+ __entry->create_options, __entry->desired_access, __entry->rc)
+)
+
+#define DEFINE_SMB3_OPEN_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_open_err_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u32 tid, \
+ __u64 sesid, \
+ int create_options, \
+ int desired_access, \
+ int rc), \
+ TP_ARGS(xid, tid, sesid, create_options, desired_access, rc))
+
+DEFINE_SMB3_OPEN_ERR_EVENT(open_err);
+DEFINE_SMB3_OPEN_ERR_EVENT(posix_mkdir_err);
+
+DECLARE_EVENT_CLASS(smb3_open_done_class,
+ TP_PROTO(unsigned int xid,
+ __u64 fid,
+ __u32 tid,
+ __u64 sesid,
+ int create_options,
+ int desired_access),
+ TP_ARGS(xid, fid, tid, sesid, create_options, desired_access),
+ TP_STRUCT__entry(
+ __field(unsigned int, xid)
+ __field(__u64, fid)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(int, create_options)
+ __field(int, desired_access)
+ ),
+ TP_fast_assign(
+ __entry->xid = xid;
+ __entry->fid = fid;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->create_options = create_options;
+ __entry->desired_access = desired_access;
+ ),
+ TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx cr_opts=0x%x des_access=0x%x",
+ __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+ __entry->create_options, __entry->desired_access)
+)
+
+#define DEFINE_SMB3_OPEN_DONE_EVENT(name) \
+DEFINE_EVENT(smb3_open_done_class, smb3_##name, \
+ TP_PROTO(unsigned int xid, \
+ __u64 fid, \
+ __u32 tid, \
+ __u64 sesid, \
+ int create_options, \
+ int desired_access), \
+ TP_ARGS(xid, fid, tid, sesid, create_options, desired_access))
+
+DEFINE_SMB3_OPEN_DONE_EVENT(open_done);
+DEFINE_SMB3_OPEN_DONE_EVENT(posix_mkdir_done);
+
+
+DECLARE_EVENT_CLASS(smb3_lease_done_class,
+ TP_PROTO(__u32 lease_state,
+ __u32 tid,
+ __u64 sesid,
+ __u64 lease_key_low,
+ __u64 lease_key_high),
+ TP_ARGS(lease_state, tid, sesid, lease_key_low, lease_key_high),
+ TP_STRUCT__entry(
+ __field(__u32, lease_state)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(__u64, lease_key_low)
+ __field(__u64, lease_key_high)
+ ),
+ TP_fast_assign(
+ __entry->lease_state = lease_state;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->lease_key_low = lease_key_low;
+ __entry->lease_key_high = lease_key_high;
+ ),
+ TP_printk("sid=0x%llx tid=0x%x lease_key=0x%llx%llx lease_state=0x%x",
+ __entry->sesid, __entry->tid, __entry->lease_key_high,
+ __entry->lease_key_low, __entry->lease_state)
+)
+
+#define DEFINE_SMB3_LEASE_DONE_EVENT(name) \
+DEFINE_EVENT(smb3_lease_done_class, smb3_##name, \
+ TP_PROTO(__u32 lease_state, \
+ __u32 tid, \
+ __u64 sesid, \
+ __u64 lease_key_low, \
+ __u64 lease_key_high), \
+ TP_ARGS(lease_state, tid, sesid, lease_key_low, lease_key_high))
+
+DEFINE_SMB3_LEASE_DONE_EVENT(lease_done);
+DEFINE_SMB3_LEASE_DONE_EVENT(lease_not_found);
+
+DECLARE_EVENT_CLASS(smb3_lease_err_class,
+ TP_PROTO(__u32 lease_state,
+ __u32 tid,
+ __u64 sesid,
+ __u64 lease_key_low,
+ __u64 lease_key_high,
+ int rc),
+ TP_ARGS(lease_state, tid, sesid, lease_key_low, lease_key_high, rc),
+ TP_STRUCT__entry(
+ __field(__u32, lease_state)
+ __field(__u32, tid)
+ __field(__u64, sesid)
+ __field(__u64, lease_key_low)
+ __field(__u64, lease_key_high)
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ __entry->lease_state = lease_state;
+ __entry->tid = tid;
+ __entry->sesid = sesid;
+ __entry->lease_key_low = lease_key_low;
+ __entry->lease_key_high = lease_key_high;
+ __entry->rc = rc;
+ ),
+ TP_printk("sid=0x%llx tid=0x%x lease_key=0x%llx%llx lease_state=0x%x rc=%d",
+ __entry->sesid, __entry->tid, __entry->lease_key_high,
+ __entry->lease_key_low, __entry->lease_state, __entry->rc)
+)
+
+#define DEFINE_SMB3_LEASE_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_lease_err_class, smb3_##name, \
+ TP_PROTO(__u32 lease_state, \
+ __u32 tid, \
+ __u64 sesid, \
+ __u64 lease_key_low, \
+ __u64 lease_key_high, \
+ int rc), \
+ TP_ARGS(lease_state, tid, sesid, lease_key_low, lease_key_high, rc))
+
+DEFINE_SMB3_LEASE_ERR_EVENT(lease_err);
+
+DECLARE_EVENT_CLASS(smb3_connect_class,
+ TP_PROTO(char *hostname,
+ __u64 conn_id,
+ const struct __kernel_sockaddr_storage *dst_addr),
+ TP_ARGS(hostname, conn_id, dst_addr),
+ TP_STRUCT__entry(
+ __string(hostname, hostname)
+ __field(__u64, conn_id)
+ __array(__u8, dst_addr, sizeof(struct sockaddr_storage))
+ ),
+ TP_fast_assign(
+ struct sockaddr_storage *pss = NULL;
+
+ __entry->conn_id = conn_id;
+ pss = (struct sockaddr_storage *)__entry->dst_addr;
+ *pss = *dst_addr;
+ __assign_str(hostname, hostname);
+ ),
+ TP_printk("conn_id=0x%llx server=%s addr=%pISpsfc",
+ __entry->conn_id,
+ __get_str(hostname),
+ __entry->dst_addr)
+)
+
+#define DEFINE_SMB3_CONNECT_EVENT(name) \
+DEFINE_EVENT(smb3_connect_class, smb3_##name, \
+ TP_PROTO(char *hostname, \
+ __u64 conn_id, \
+ const struct __kernel_sockaddr_storage *addr), \
+ TP_ARGS(hostname, conn_id, addr))
+
+DEFINE_SMB3_CONNECT_EVENT(connect_done);
+
+DECLARE_EVENT_CLASS(smb3_connect_err_class,
+ TP_PROTO(char *hostname, __u64 conn_id,
+ const struct __kernel_sockaddr_storage *dst_addr, int rc),
+ TP_ARGS(hostname, conn_id, dst_addr, rc),
+ TP_STRUCT__entry(
+ __string(hostname, hostname)
+ __field(__u64, conn_id)
+ __array(__u8, dst_addr, sizeof(struct sockaddr_storage))
+ __field(int, rc)
+ ),
+ TP_fast_assign(
+ struct sockaddr_storage *pss = NULL;
+
+ __entry->conn_id = conn_id;
+ __entry->rc = rc;
+ pss = (struct sockaddr_storage *)__entry->dst_addr;
+ *pss = *dst_addr;
+ __assign_str(hostname, hostname);
+ ),
+ TP_printk("rc=%d conn_id=0x%llx server=%s addr=%pISpsfc",
+ __entry->rc,
+ __entry->conn_id,
+ __get_str(hostname),
+ __entry->dst_addr)
+)
+
+#define DEFINE_SMB3_CONNECT_ERR_EVENT(name) \
+DEFINE_EVENT(smb3_connect_err_class, smb3_##name, \
+ TP_PROTO(char *hostname, \
+ __u64 conn_id, \
+ const struct __kernel_sockaddr_storage *addr, \
+ int rc), \
+ TP_ARGS(hostname, conn_id, addr, rc))
+
+DEFINE_SMB3_CONNECT_ERR_EVENT(connect_err);
+
+DECLARE_EVENT_CLASS(smb3_reconnect_class,
+ TP_PROTO(__u64 currmid,
+ __u64 conn_id,
+ char *hostname),
+ TP_ARGS(currmid, conn_id, hostname),
+ TP_STRUCT__entry(
+ __field(__u64, currmid)
+ __field(__u64, conn_id)
+ __string(hostname, hostname)
+ ),
+ TP_fast_assign(
+ __entry->currmid = currmid;
+ __entry->conn_id = conn_id;
+ __assign_str(hostname, hostname);
+ ),
+ TP_printk("conn_id=0x%llx server=%s current_mid=%llu",
+ __entry->conn_id,
+ __get_str(hostname),
+ __entry->currmid)
+)
+
+#define DEFINE_SMB3_RECONNECT_EVENT(name) \
+DEFINE_EVENT(smb3_reconnect_class, smb3_##name, \
+ TP_PROTO(__u64 currmid, \
+ __u64 conn_id, \
+ char *hostname), \
+ TP_ARGS(currmid, conn_id, hostname))
+
+DEFINE_SMB3_RECONNECT_EVENT(reconnect);
+DEFINE_SMB3_RECONNECT_EVENT(partial_send_reconnect);
+
+DECLARE_EVENT_CLASS(smb3_credit_class,
+ TP_PROTO(__u64 currmid,
+ __u64 conn_id,
+ char *hostname,
+ int credits,
+ int credits_to_add,
+ int in_flight),
+ TP_ARGS(currmid, conn_id, hostname, credits, credits_to_add, in_flight),
+ TP_STRUCT__entry(
+ __field(__u64, currmid)
+ __field(__u64, conn_id)
+ __string(hostname, hostname)
+ __field(int, credits)
+ __field(int, credits_to_add)
+ __field(int, in_flight)
+ ),
+ TP_fast_assign(
+ __entry->currmid = currmid;
+ __entry->conn_id = conn_id;
+ __assign_str(hostname, hostname);
+ __entry->credits = credits;
+ __entry->credits_to_add = credits_to_add;
+ __entry->in_flight = in_flight;
+ ),
+ TP_printk("conn_id=0x%llx server=%s current_mid=%llu "
+ "credits=%d credit_change=%d in_flight=%d",
+ __entry->conn_id,
+ __get_str(hostname),
+ __entry->currmid,
+ __entry->credits,
+ __entry->credits_to_add,
+ __entry->in_flight)
+)
+
+#define DEFINE_SMB3_CREDIT_EVENT(name) \
+DEFINE_EVENT(smb3_credit_class, smb3_##name, \
+ TP_PROTO(__u64 currmid, \
+ __u64 conn_id, \
+ char *hostname, \
+ int credits, \
+ int credits_to_add, \
+ int in_flight), \
+ TP_ARGS(currmid, conn_id, hostname, credits, credits_to_add, in_flight))
+
+DEFINE_SMB3_CREDIT_EVENT(reconnect_with_invalid_credits);
+DEFINE_SMB3_CREDIT_EVENT(reconnect_detected);
+DEFINE_SMB3_CREDIT_EVENT(credit_timeout);
+DEFINE_SMB3_CREDIT_EVENT(insufficient_credits);
+DEFINE_SMB3_CREDIT_EVENT(too_many_credits);
+DEFINE_SMB3_CREDIT_EVENT(add_credits);
+DEFINE_SMB3_CREDIT_EVENT(adj_credits);
+DEFINE_SMB3_CREDIT_EVENT(hdr_credits);
+DEFINE_SMB3_CREDIT_EVENT(nblk_credits);
+DEFINE_SMB3_CREDIT_EVENT(pend_credits);
+DEFINE_SMB3_CREDIT_EVENT(wait_credits);
+DEFINE_SMB3_CREDIT_EVENT(waitff_credits);
+DEFINE_SMB3_CREDIT_EVENT(overflow_credits);
+DEFINE_SMB3_CREDIT_EVENT(set_credits);
+
+#endif /* _CIFS_TRACE_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace
+#include <trace/define_trace.h>
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
new file mode 100644
index 000000000000..c961b90f92b9
--- /dev/null
+++ b/fs/smb/client/transport.c
@@ -0,0 +1,1807 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Jeremy Allison (jra@samba.org) 2006.
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/gfp.h>
+#include <linux/wait.h>
+#include <linux/net.h>
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <linux/tcp.h>
+#include <linux/bvec.h>
+#include <linux/highmem.h>
+#include <linux/uaccess.h>
+#include <asm/processor.h>
+#include <linux/mempool.h>
+#include <linux/sched/signal.h>
+#include <linux/task_io_accounting_ops.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "smb2proto.h"
+#include "smbdirect.h"
+
+/* Max number of iovectors we can use off the stack when sending requests. */
+#define CIFS_MAX_IOV_SIZE 8
+
+void
+cifs_wake_up_task(struct mid_q_entry *mid)
+{
+ wake_up_process(mid->callback_data);
+}
+
+static struct mid_q_entry *
+alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
+{
+ struct mid_q_entry *temp;
+
+ if (server == NULL) {
+ cifs_dbg(VFS, "%s: null TCP session\n", __func__);
+ return NULL;
+ }
+
+ temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
+ memset(temp, 0, sizeof(struct mid_q_entry));
+ kref_init(&temp->refcount);
+ temp->mid = get_mid(smb_buffer);
+ temp->pid = current->pid;
+ temp->command = cpu_to_le16(smb_buffer->Command);
+ cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);
+ /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
+ /* when mid allocated can be before when sent */
+ temp->when_alloc = jiffies;
+ temp->server = server;
+
+ /*
+ * The default is for the mid to be synchronous, so the
+ * default callback just wakes up the current task.
+ */
+ get_task_struct(current);
+ temp->creator = current;
+ temp->callback = cifs_wake_up_task;
+ temp->callback_data = current;
+
+ atomic_inc(&mid_count);
+ temp->mid_state = MID_REQUEST_ALLOCATED;
+ return temp;
+}
+
+static void __release_mid(struct kref *refcount)
+{
+ struct mid_q_entry *midEntry =
+ container_of(refcount, struct mid_q_entry, refcount);
+#ifdef CONFIG_CIFS_STATS2
+ __le16 command = midEntry->server->vals->lock_cmd;
+ __u16 smb_cmd = le16_to_cpu(midEntry->command);
+ unsigned long now;
+ unsigned long roundtrip_time;
+#endif
+ struct TCP_Server_Info *server = midEntry->server;
+
+ if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) &&
+ midEntry->mid_state == MID_RESPONSE_RECEIVED &&
+ server->ops->handle_cancelled_mid)
+ server->ops->handle_cancelled_mid(midEntry, server);
+
+ midEntry->mid_state = MID_FREE;
+ atomic_dec(&mid_count);
+ if (midEntry->large_buf)
+ cifs_buf_release(midEntry->resp_buf);
+ else
+ cifs_small_buf_release(midEntry->resp_buf);
+#ifdef CONFIG_CIFS_STATS2
+ now = jiffies;
+ if (now < midEntry->when_alloc)
+ cifs_server_dbg(VFS, "Invalid mid allocation time\n");
+ roundtrip_time = now - midEntry->when_alloc;
+
+ if (smb_cmd < NUMBER_OF_SMB2_COMMANDS) {
+ if (atomic_read(&server->num_cmds[smb_cmd]) == 0) {
+ server->slowest_cmd[smb_cmd] = roundtrip_time;
+ server->fastest_cmd[smb_cmd] = roundtrip_time;
+ } else {
+ if (server->slowest_cmd[smb_cmd] < roundtrip_time)
+ server->slowest_cmd[smb_cmd] = roundtrip_time;
+ else if (server->fastest_cmd[smb_cmd] > roundtrip_time)
+ server->fastest_cmd[smb_cmd] = roundtrip_time;
+ }
+ cifs_stats_inc(&server->num_cmds[smb_cmd]);
+ server->time_per_cmd[smb_cmd] += roundtrip_time;
+ }
+ /*
+ * commands taking longer than one second (default) can be indications
+ * that something is wrong, unless it is quite a slow link or a very
+ * busy server. Note that this calc is unlikely or impossible to wrap
+ * as long as slow_rsp_threshold is not set way above recommended max
+ * value (32767 ie 9 hours) and is generally harmless even if wrong
+ * since only affects debug counters - so leaving the calc as simple
+ * comparison rather than doing multiple conversions and overflow
+ * checks
+ */
+ if ((slow_rsp_threshold != 0) &&
+ time_after(now, midEntry->when_alloc + (slow_rsp_threshold * HZ)) &&
+ (midEntry->command != command)) {
+ /*
+ * smb2slowcmd[NUMBER_OF_SMB2_COMMANDS] counts by command
+ * NB: le16_to_cpu returns unsigned so can not be negative below
+ */
+ if (smb_cmd < NUMBER_OF_SMB2_COMMANDS)
+ cifs_stats_inc(&server->smb2slowcmd[smb_cmd]);
+
+ trace_smb3_slow_rsp(smb_cmd, midEntry->mid, midEntry->pid,
+ midEntry->when_sent, midEntry->when_received);
+ if (cifsFYI & CIFS_TIMER) {
+ pr_debug("slow rsp: cmd %d mid %llu",
+ midEntry->command, midEntry->mid);
+ cifs_info("A: 0x%lx S: 0x%lx R: 0x%lx\n",
+ now - midEntry->when_alloc,
+ now - midEntry->when_sent,
+ now - midEntry->when_received);
+ }
+ }
+#endif
+ put_task_struct(midEntry->creator);
+
+ mempool_free(midEntry, cifs_mid_poolp);
+}
+
+void release_mid(struct mid_q_entry *mid)
+{
+ struct TCP_Server_Info *server = mid->server;
+
+ spin_lock(&server->mid_lock);
+ kref_put(&mid->refcount, __release_mid);
+ spin_unlock(&server->mid_lock);
+}
+
+void
+delete_mid(struct mid_q_entry *mid)
+{
+ spin_lock(&mid->server->mid_lock);
+ if (!(mid->mid_flags & MID_DELETED)) {
+ list_del_init(&mid->qhead);
+ mid->mid_flags |= MID_DELETED;
+ }
+ spin_unlock(&mid->server->mid_lock);
+
+ release_mid(mid);
+}
+
+/*
+ * smb_send_kvec - send an array of kvecs to the server
+ * @server: Server to send the data to
+ * @smb_msg: Message to send
+ * @sent: amount of data sent on socket is stored here
+ *
+ * Our basic "send data to server" function. Should be called with srv_mutex
+ * held. The caller is responsible for handling the results.
+ */
+static int
+smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
+ size_t *sent)
+{
+ int rc = 0;
+ int retries = 0;
+ struct socket *ssocket = server->ssocket;
+
+ *sent = 0;
+
+ if (server->noblocksnd)
+ smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
+ else
+ smb_msg->msg_flags = MSG_NOSIGNAL;
+
+ while (msg_data_left(smb_msg)) {
+ /*
+ * If blocking send, we try 3 times, since each can block
+ * for 5 seconds. For nonblocking we have to try more
+ * but wait increasing amounts of time allowing time for
+ * socket to clear. The overall time we wait in either
+ * case to send on the socket is about 15 seconds.
+ * Similarly we wait for 15 seconds for a response from
+ * the server in SendReceive[2] for the server to send
+ * a response back for most types of requests (except
+ * SMB Write past end of file which can be slow, and
+ * blocking lock operations). NFS waits slightly longer
+ * than CIFS, but this can make it take longer for
+ * nonresponsive servers to be detected and 15 seconds
+ * is more than enough time for modern networks to
+ * send a packet. In most cases if we fail to send
+ * after the retries we will kill the socket and
+ * reconnect which may clear the network problem.
+ */
+ rc = sock_sendmsg(ssocket, smb_msg);
+ if (rc == -EAGAIN) {
+ retries++;
+ if (retries >= 14 ||
+ (!server->noblocksnd && (retries > 2))) {
+ cifs_server_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
+ ssocket);
+ return -EAGAIN;
+ }
+ msleep(1 << retries);
+ continue;
+ }
+
+ if (rc < 0)
+ return rc;
+
+ if (rc == 0) {
+ /* should never happen, letting socket clear before
+ retrying is our only obvious option here */
+ cifs_server_dbg(VFS, "tcp sent no data\n");
+ msleep(500);
+ continue;
+ }
+
+ /* send was at least partially successful */
+ *sent += rc;
+ retries = 0; /* in case we get ENOSPC on the next send */
+ }
+ return 0;
+}
+
+unsigned long
+smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst)
+{
+ unsigned int i;
+ struct kvec *iov;
+ int nvec;
+ unsigned long buflen = 0;
+
+ if (!is_smb1(server) && rqst->rq_nvec >= 2 &&
+ rqst->rq_iov[0].iov_len == 4) {
+ iov = &rqst->rq_iov[1];
+ nvec = rqst->rq_nvec - 1;
+ } else {
+ iov = rqst->rq_iov;
+ nvec = rqst->rq_nvec;
+ }
+
+ /* total up iov array first */
+ for (i = 0; i < nvec; i++)
+ buflen += iov[i].iov_len;
+
+ /*
+ * Add in the page array if there is one. The caller needs to make
+ * sure rq_offset and rq_tailsz are set correctly. If a buffer of
+ * multiple pages ends at page boundary, rq_tailsz needs to be set to
+ * PAGE_SIZE.
+ */
+ if (rqst->rq_npages) {
+ if (rqst->rq_npages == 1)
+ buflen += rqst->rq_tailsz;
+ else {
+ /*
+ * If there is more than one page, calculate the
+ * buffer length based on rq_offset and rq_tailsz
+ */
+ buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
+ rqst->rq_offset;
+ buflen += rqst->rq_tailsz;
+ }
+ }
+
+ return buflen;
+}
+
+static int
+__smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
+ struct smb_rqst *rqst)
+{
+ int rc;
+ struct kvec *iov;
+ int n_vec;
+ unsigned int send_length = 0;
+ unsigned int i, j;
+ sigset_t mask, oldmask;
+ size_t total_len = 0, sent, size;
+ struct socket *ssocket = server->ssocket;
+ struct msghdr smb_msg = {};
+ __be32 rfc1002_marker;
+
+ cifs_in_send_inc(server);
+ if (cifs_rdma_enabled(server)) {
+ /* return -EAGAIN when connecting or reconnecting */
+ rc = -EAGAIN;
+ if (server->smbd_conn)
+ rc = smbd_send(server, num_rqst, rqst);
+ goto smbd_done;
+ }
+
+ rc = -EAGAIN;
+ if (ssocket == NULL)
+ goto out;
+
+ rc = -ERESTARTSYS;
+ if (fatal_signal_pending(current)) {
+ cifs_dbg(FYI, "signal pending before send request\n");
+ goto out;
+ }
+
+ rc = 0;
+ /* cork the socket */
+ tcp_sock_set_cork(ssocket->sk, true);
+
+ for (j = 0; j < num_rqst; j++)
+ send_length += smb_rqst_len(server, &rqst[j]);
+ rfc1002_marker = cpu_to_be32(send_length);
+
+ /*
+ * We should not allow signals to interrupt the network send because
+ * any partial send will cause session reconnects thus increasing
+ * latency of system calls and overload a server with unnecessary
+ * requests.
+ */
+
+ sigfillset(&mask);
+ sigprocmask(SIG_BLOCK, &mask, &oldmask);
+
+ /* Generate a rfc1002 marker for SMB2+ */
+ if (!is_smb1(server)) {
+ struct kvec hiov = {
+ .iov_base = &rfc1002_marker,
+ .iov_len = 4
+ };
+ iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, &hiov, 1, 4);
+ rc = smb_send_kvec(server, &smb_msg, &sent);
+ if (rc < 0)
+ goto unmask;
+
+ total_len += sent;
+ send_length += 4;
+ }
+
+ cifs_dbg(FYI, "Sending smb: smb_len=%u\n", send_length);
+
+ for (j = 0; j < num_rqst; j++) {
+ iov = rqst[j].rq_iov;
+ n_vec = rqst[j].rq_nvec;
+
+ size = 0;
+ for (i = 0; i < n_vec; i++) {
+ dump_smb(iov[i].iov_base, iov[i].iov_len);
+ size += iov[i].iov_len;
+ }
+
+ iov_iter_kvec(&smb_msg.msg_iter, ITER_SOURCE, iov, n_vec, size);
+
+ rc = smb_send_kvec(server, &smb_msg, &sent);
+ if (rc < 0)
+ goto unmask;
+
+ total_len += sent;
+
+ /* now walk the page array and send each page in it */
+ for (i = 0; i < rqst[j].rq_npages; i++) {
+ struct bio_vec bvec;
+
+ bvec.bv_page = rqst[j].rq_pages[i];
+ rqst_page_get_length(&rqst[j], i, &bvec.bv_len,
+ &bvec.bv_offset);
+
+ iov_iter_bvec(&smb_msg.msg_iter, ITER_SOURCE,
+ &bvec, 1, bvec.bv_len);
+ rc = smb_send_kvec(server, &smb_msg, &sent);
+ if (rc < 0)
+ break;
+
+ total_len += sent;
+ }
+ }
+
+unmask:
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
+
+ /*
+ * If signal is pending but we have already sent the whole packet to
+ * the server we need to return success status to allow a corresponding
+ * mid entry to be kept in the pending requests queue thus allowing
+ * to handle responses from the server by the client.
+ *
+ * If only part of the packet has been sent there is no need to hide
+ * interrupt because the session will be reconnected anyway, so there
+ * won't be any response from the server to handle.
+ */
+
+ if (signal_pending(current) && (total_len != send_length)) {
+ cifs_dbg(FYI, "signal is pending after attempt to send\n");
+ rc = -ERESTARTSYS;
+ }
+
+ /* uncork it */
+ tcp_sock_set_cork(ssocket->sk, false);
+
+ if ((total_len > 0) && (total_len != send_length)) {
+ cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
+ send_length, total_len);
+ /*
+ * If we have only sent part of an SMB then the next SMB could
+ * be taken as the remainder of this one. We need to kill the
+ * socket so the server throws away the partial SMB
+ */
+ cifs_signal_cifsd_for_reconnect(server, false);
+ trace_smb3_partial_send_reconnect(server->CurrentMid,
+ server->conn_id, server->hostname);
+ }
+smbd_done:
+ if (rc < 0 && rc != -EINTR)
+ cifs_server_dbg(VFS, "Error %d sending data on socket to server\n",
+ rc);
+ else if (rc > 0)
+ rc = 0;
+out:
+ cifs_in_send_dec(server);
+ return rc;
+}
+
+static int
+smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
+ struct smb_rqst *rqst, int flags)
+{
+ struct kvec iov;
+ struct smb2_transform_hdr *tr_hdr;
+ struct smb_rqst cur_rqst[MAX_COMPOUND];
+ int rc;
+
+ if (!(flags & CIFS_TRANSFORM_REQ))
+ return __smb_send_rqst(server, num_rqst, rqst);
+
+ if (num_rqst > MAX_COMPOUND - 1)
+ return -ENOMEM;
+
+ if (!server->ops->init_transform_rq) {
+ cifs_server_dbg(VFS, "Encryption requested but transform callback is missing\n");
+ return -EIO;
+ }
+
+ tr_hdr = kzalloc(sizeof(*tr_hdr), GFP_NOFS);
+ if (!tr_hdr)
+ return -ENOMEM;
+
+ memset(&cur_rqst[0], 0, sizeof(cur_rqst));
+ memset(&iov, 0, sizeof(iov));
+
+ iov.iov_base = tr_hdr;
+ iov.iov_len = sizeof(*tr_hdr);
+ cur_rqst[0].rq_iov = &iov;
+ cur_rqst[0].rq_nvec = 1;
+
+ rc = server->ops->init_transform_rq(server, num_rqst + 1,
+ &cur_rqst[0], rqst);
+ if (rc)
+ goto out;
+
+ rc = __smb_send_rqst(server, num_rqst + 1, &cur_rqst[0]);
+ smb3_free_compound_rqst(num_rqst, &cur_rqst[1]);
+out:
+ kfree(tr_hdr);
+ return rc;
+}
+
+int
+smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
+ unsigned int smb_buf_length)
+{
+ struct kvec iov[2];
+ struct smb_rqst rqst = { .rq_iov = iov,
+ .rq_nvec = 2 };
+
+ iov[0].iov_base = smb_buffer;
+ iov[0].iov_len = 4;
+ iov[1].iov_base = (char *)smb_buffer + 4;
+ iov[1].iov_len = smb_buf_length;
+
+ return __smb_send_rqst(server, 1, &rqst);
+}
+
+static int
+wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits,
+ const int timeout, const int flags,
+ unsigned int *instance)
+{
+ long rc;
+ int *credits;
+ int optype;
+ long int t;
+ int scredits, in_flight;
+
+ if (timeout < 0)
+ t = MAX_JIFFY_OFFSET;
+ else
+ t = msecs_to_jiffies(timeout);
+
+ optype = flags & CIFS_OP_MASK;
+
+ *instance = 0;
+
+ credits = server->ops->get_credits_field(server, optype);
+ /* Since an echo is already inflight, no need to wait to send another */
+ if (*credits <= 0 && optype == CIFS_ECHO_OP)
+ return -EAGAIN;
+
+ spin_lock(&server->req_lock);
+ if ((flags & CIFS_TIMEOUT_MASK) == CIFS_NON_BLOCKING) {
+ /* oplock breaks must not be held up */
+ server->in_flight++;
+ if (server->in_flight > server->max_in_flight)
+ server->max_in_flight = server->in_flight;
+ *credits -= 1;
+ *instance = server->reconnect_instance;
+ scredits = *credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+
+ trace_smb3_nblk_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits, -1, in_flight);
+ cifs_dbg(FYI, "%s: remove %u credits total=%d\n",
+ __func__, 1, scredits);
+
+ return 0;
+ }
+
+ while (1) {
+ if (*credits < num_credits) {
+ scredits = *credits;
+ spin_unlock(&server->req_lock);
+
+ cifs_num_waiters_inc(server);
+ rc = wait_event_killable_timeout(server->request_q,
+ has_credits(server, credits, num_credits), t);
+ cifs_num_waiters_dec(server);
+ if (!rc) {
+ spin_lock(&server->req_lock);
+ scredits = *credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+
+ trace_smb3_credit_timeout(server->CurrentMid,
+ server->conn_id, server->hostname, scredits,
+ num_credits, in_flight);
+ cifs_server_dbg(VFS, "wait timed out after %d ms\n",
+ timeout);
+ return -EBUSY;
+ }
+ if (rc == -ERESTARTSYS)
+ return -ERESTARTSYS;
+ spin_lock(&server->req_lock);
+ } else {
+ spin_unlock(&server->req_lock);
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsExiting) {
+ spin_unlock(&server->srv_lock);
+ return -ENOENT;
+ }
+ spin_unlock(&server->srv_lock);
+
+ /*
+ * For normal commands, reserve the last MAX_COMPOUND
+ * credits to compound requests.
+ * Otherwise these compounds could be permanently
+ * starved for credits by single-credit requests.
+ *
+ * To prevent spinning CPU, block this thread until
+ * there are >MAX_COMPOUND credits available.
+ * But only do this is we already have a lot of
+ * credits in flight to avoid triggering this check
+ * for servers that are slow to hand out credits on
+ * new sessions.
+ */
+ spin_lock(&server->req_lock);
+ if (!optype && num_credits == 1 &&
+ server->in_flight > 2 * MAX_COMPOUND &&
+ *credits <= MAX_COMPOUND) {
+ spin_unlock(&server->req_lock);
+
+ cifs_num_waiters_inc(server);
+ rc = wait_event_killable_timeout(
+ server->request_q,
+ has_credits(server, credits,
+ MAX_COMPOUND + 1),
+ t);
+ cifs_num_waiters_dec(server);
+ if (!rc) {
+ spin_lock(&server->req_lock);
+ scredits = *credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+
+ trace_smb3_credit_timeout(
+ server->CurrentMid,
+ server->conn_id, server->hostname,
+ scredits, num_credits, in_flight);
+ cifs_server_dbg(VFS, "wait timed out after %d ms\n",
+ timeout);
+ return -EBUSY;
+ }
+ if (rc == -ERESTARTSYS)
+ return -ERESTARTSYS;
+ spin_lock(&server->req_lock);
+ continue;
+ }
+
+ /*
+ * Can not count locking commands against total
+ * as they are allowed to block on server.
+ */
+
+ /* update # of requests on the wire to server */
+ if ((flags & CIFS_TIMEOUT_MASK) != CIFS_BLOCKING_OP) {
+ *credits -= num_credits;
+ server->in_flight += num_credits;
+ if (server->in_flight > server->max_in_flight)
+ server->max_in_flight = server->in_flight;
+ *instance = server->reconnect_instance;
+ }
+ scredits = *credits;
+ in_flight = server->in_flight;
+ spin_unlock(&server->req_lock);
+
+ trace_smb3_waitff_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits,
+ -(num_credits), in_flight);
+ cifs_dbg(FYI, "%s: remove %u credits total=%d\n",
+ __func__, num_credits, scredits);
+ break;
+ }
+ }
+ return 0;
+}
+
+static int
+wait_for_free_request(struct TCP_Server_Info *server, const int flags,
+ unsigned int *instance)
+{
+ return wait_for_free_credits(server, 1, -1, flags,
+ instance);
+}
+
+static int
+wait_for_compound_request(struct TCP_Server_Info *server, int num,
+ const int flags, unsigned int *instance)
+{
+ int *credits;
+ int scredits, in_flight;
+
+ credits = server->ops->get_credits_field(server, flags & CIFS_OP_MASK);
+
+ spin_lock(&server->req_lock);
+ scredits = *credits;
+ in_flight = server->in_flight;
+
+ if (*credits < num) {
+ /*
+ * If the server is tight on resources or just gives us less
+ * credits for other reasons (e.g. requests are coming out of
+ * order and the server delays granting more credits until it
+ * processes a missing mid) and we exhausted most available
+ * credits there may be situations when we try to send
+ * a compound request but we don't have enough credits. At this
+ * point the client needs to decide if it should wait for
+ * additional credits or fail the request. If at least one
+ * request is in flight there is a high probability that the
+ * server will return enough credits to satisfy this compound
+ * request.
+ *
+ * Return immediately if no requests in flight since we will be
+ * stuck on waiting for credits.
+ */
+ if (server->in_flight == 0) {
+ spin_unlock(&server->req_lock);
+ trace_smb3_insufficient_credits(server->CurrentMid,
+ server->conn_id, server->hostname, scredits,
+ num, in_flight);
+ cifs_dbg(FYI, "%s: %d requests in flight, needed %d total=%d\n",
+ __func__, in_flight, num, scredits);
+ return -EDEADLK;
+ }
+ }
+ spin_unlock(&server->req_lock);
+
+ return wait_for_free_credits(server, num, 60000, flags,
+ instance);
+}
+
+int
+cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
+ unsigned int *num, struct cifs_credits *credits)
+{
+ *num = size;
+ credits->value = 0;
+ credits->instance = server->reconnect_instance;
+ return 0;
+}
+
+static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
+ struct mid_q_entry **ppmidQ)
+{
+ spin_lock(&ses->ses_lock);
+ if (ses->ses_status == SES_NEW) {
+ if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
+ (in_buf->Command != SMB_COM_NEGOTIATE)) {
+ spin_unlock(&ses->ses_lock);
+ return -EAGAIN;
+ }
+ /* else ok - we are setting up session */
+ }
+
+ if (ses->ses_status == SES_EXITING) {
+ /* check if SMB session is bad because we are setting it up */
+ if (in_buf->Command != SMB_COM_LOGOFF_ANDX) {
+ spin_unlock(&ses->ses_lock);
+ return -EAGAIN;
+ }
+ /* else ok - we are shutting down session */
+ }
+ spin_unlock(&ses->ses_lock);
+
+ *ppmidQ = alloc_mid(in_buf, ses->server);
+ if (*ppmidQ == NULL)
+ return -ENOMEM;
+ spin_lock(&ses->server->mid_lock);
+ list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
+ spin_unlock(&ses->server->mid_lock);
+ return 0;
+}
+
+static int
+wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
+{
+ int error;
+
+ error = wait_event_state(server->response_q,
+ midQ->mid_state != MID_REQUEST_SUBMITTED,
+ (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE));
+ if (error < 0)
+ return -ERESTARTSYS;
+
+ return 0;
+}
+
+struct mid_q_entry *
+cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
+{
+ int rc;
+ struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
+ struct mid_q_entry *mid;
+
+ if (rqst->rq_iov[0].iov_len != 4 ||
+ rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
+ return ERR_PTR(-EIO);
+
+ /* enable signing if server requires it */
+ if (server->sign)
+ hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+ mid = alloc_mid(hdr, server);
+ if (mid == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
+ if (rc) {
+ release_mid(mid);
+ return ERR_PTR(rc);
+ }
+
+ return mid;
+}
+
+/*
+ * Send a SMB request and set the callback function in the mid to handle
+ * the result. Caller is responsible for dealing with timeouts.
+ */
+int
+cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
+ mid_receive_t *receive, mid_callback_t *callback,
+ mid_handle_t *handle, void *cbdata, const int flags,
+ const struct cifs_credits *exist_credits)
+{
+ int rc;
+ struct mid_q_entry *mid;
+ struct cifs_credits credits = { .value = 0, .instance = 0 };
+ unsigned int instance;
+ int optype;
+
+ optype = flags & CIFS_OP_MASK;
+
+ if ((flags & CIFS_HAS_CREDITS) == 0) {
+ rc = wait_for_free_request(server, flags, &instance);
+ if (rc)
+ return rc;
+ credits.value = 1;
+ credits.instance = instance;
+ } else
+ instance = exist_credits->instance;
+
+ cifs_server_lock(server);
+
+ /*
+ * We can't use credits obtained from the previous session to send this
+ * request. Check if there were reconnects after we obtained credits and
+ * return -EAGAIN in such cases to let callers handle it.
+ */
+ if (instance != server->reconnect_instance) {
+ cifs_server_unlock(server);
+ add_credits_and_wake_if(server, &credits, optype);
+ return -EAGAIN;
+ }
+
+ mid = server->ops->setup_async_request(server, rqst);
+ if (IS_ERR(mid)) {
+ cifs_server_unlock(server);
+ add_credits_and_wake_if(server, &credits, optype);
+ return PTR_ERR(mid);
+ }
+
+ mid->receive = receive;
+ mid->callback = callback;
+ mid->callback_data = cbdata;
+ mid->handle = handle;
+ mid->mid_state = MID_REQUEST_SUBMITTED;
+
+ /* put it on the pending_mid_q */
+ spin_lock(&server->mid_lock);
+ list_add_tail(&mid->qhead, &server->pending_mid_q);
+ spin_unlock(&server->mid_lock);
+
+ /*
+ * Need to store the time in mid before calling I/O. For call_async,
+ * I/O response may come back and free the mid entry on another thread.
+ */
+ cifs_save_when_sent(mid);
+ rc = smb_send_rqst(server, 1, rqst, flags);
+
+ if (rc < 0) {
+ revert_current_mid(server, mid->credits);
+ server->sequence_number -= 2;
+ delete_mid(mid);
+ }
+
+ cifs_server_unlock(server);
+
+ if (rc == 0)
+ return 0;
+
+ add_credits_and_wake_if(server, &credits, optype);
+ return rc;
+}
+
+/*
+ *
+ * Send an SMB Request. No response info (other than return code)
+ * needs to be parsed.
+ *
+ * flags indicate the type of request buffer and how long to wait
+ * and whether to log NT STATUS code (error) before mapping it to POSIX error
+ *
+ */
+int
+SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
+ char *in_buf, int flags)
+{
+ int rc;
+ struct kvec iov[1];
+ struct kvec rsp_iov;
+ int resp_buf_type;
+
+ iov[0].iov_base = in_buf;
+ iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
+ flags |= CIFS_NO_RSP_BUF;
+ rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
+ cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
+
+ return rc;
+}
+
+static int
+cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
+{
+ int rc = 0;
+
+ cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n",
+ __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state);
+
+ spin_lock(&server->mid_lock);
+ switch (mid->mid_state) {
+ case MID_RESPONSE_RECEIVED:
+ spin_unlock(&server->mid_lock);
+ return rc;
+ case MID_RETRY_NEEDED:
+ rc = -EAGAIN;
+ break;
+ case MID_RESPONSE_MALFORMED:
+ rc = -EIO;
+ break;
+ case MID_SHUTDOWN:
+ rc = -EHOSTDOWN;
+ break;
+ default:
+ if (!(mid->mid_flags & MID_DELETED)) {
+ list_del_init(&mid->qhead);
+ mid->mid_flags |= MID_DELETED;
+ }
+ cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
+ __func__, mid->mid, mid->mid_state);
+ rc = -EIO;
+ }
+ spin_unlock(&server->mid_lock);
+
+ release_mid(mid);
+ return rc;
+}
+
+static inline int
+send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
+ struct mid_q_entry *mid)
+{
+ return server->ops->send_cancel ?
+ server->ops->send_cancel(server, rqst, mid) : 0;
+}
+
+int
+cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
+ bool log_error)
+{
+ unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
+
+ dump_smb(mid->resp_buf, min_t(u32, 92, len));
+
+ /* convert the length into a more usable form */
+ if (server->sign) {
+ struct kvec iov[2];
+ int rc = 0;
+ struct smb_rqst rqst = { .rq_iov = iov,
+ .rq_nvec = 2 };
+
+ iov[0].iov_base = mid->resp_buf;
+ iov[0].iov_len = 4;
+ iov[1].iov_base = (char *)mid->resp_buf + 4;
+ iov[1].iov_len = len - 4;
+ /* FIXME: add code to kill session */
+ rc = cifs_verify_signature(&rqst, server,
+ mid->sequence_number);
+ if (rc)
+ cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n",
+ rc);
+ }
+
+ /* BB special case reconnect tid and uid here? */
+ return map_and_check_smb_error(mid, log_error);
+}
+
+struct mid_q_entry *
+cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored,
+ struct smb_rqst *rqst)
+{
+ int rc;
+ struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
+ struct mid_q_entry *mid;
+
+ if (rqst->rq_iov[0].iov_len != 4 ||
+ rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
+ return ERR_PTR(-EIO);
+
+ rc = allocate_mid(ses, hdr, &mid);
+ if (rc)
+ return ERR_PTR(rc);
+ rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
+ if (rc) {
+ delete_mid(mid);
+ return ERR_PTR(rc);
+ }
+ return mid;
+}
+
+static void
+cifs_compound_callback(struct mid_q_entry *mid)
+{
+ struct TCP_Server_Info *server = mid->server;
+ struct cifs_credits credits;
+
+ credits.value = server->ops->get_credits(mid);
+ credits.instance = server->reconnect_instance;
+
+ add_credits(server, &credits, mid->optype);
+}
+
+static void
+cifs_compound_last_callback(struct mid_q_entry *mid)
+{
+ cifs_compound_callback(mid);
+ cifs_wake_up_task(mid);
+}
+
+static void
+cifs_cancelled_callback(struct mid_q_entry *mid)
+{
+ cifs_compound_callback(mid);
+ release_mid(mid);
+}
+
+/*
+ * Return a channel (master if none) of @ses that can be used to send
+ * regular requests.
+ *
+ * If we are currently binding a new channel (negprot/sess.setup),
+ * return the new incomplete channel.
+ */
+struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
+{
+ uint index = 0;
+
+ if (!ses)
+ return NULL;
+
+ /* round robin */
+ index = (uint)atomic_inc_return(&ses->chan_seq);
+
+ spin_lock(&ses->chan_lock);
+ index %= ses->chan_count;
+ spin_unlock(&ses->chan_lock);
+
+ return ses->chans[index].server;
+}
+
+int
+compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ const int flags, const int num_rqst, struct smb_rqst *rqst,
+ int *resp_buf_type, struct kvec *resp_iov)
+{
+ int i, j, optype, rc = 0;
+ struct mid_q_entry *midQ[MAX_COMPOUND];
+ bool cancelled_mid[MAX_COMPOUND] = {false};
+ struct cifs_credits credits[MAX_COMPOUND] = {
+ { .value = 0, .instance = 0 }
+ };
+ unsigned int instance;
+ char *buf;
+
+ optype = flags & CIFS_OP_MASK;
+
+ for (i = 0; i < num_rqst; i++)
+ resp_buf_type[i] = CIFS_NO_BUFFER; /* no response buf yet */
+
+ if (!ses || !ses->server || !server) {
+ cifs_dbg(VFS, "Null session\n");
+ return -EIO;
+ }
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsExiting) {
+ spin_unlock(&server->srv_lock);
+ return -ENOENT;
+ }
+ spin_unlock(&server->srv_lock);
+
+ /*
+ * Wait for all the requests to become available.
+ * This approach still leaves the possibility to be stuck waiting for
+ * credits if the server doesn't grant credits to the outstanding
+ * requests and if the client is completely idle, not generating any
+ * other requests.
+ * This can be handled by the eventual session reconnect.
+ */
+ rc = wait_for_compound_request(server, num_rqst, flags,
+ &instance);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < num_rqst; i++) {
+ credits[i].value = 1;
+ credits[i].instance = instance;
+ }
+
+ /*
+ * Make sure that we sign in the same order that we send on this socket
+ * and avoid races inside tcp sendmsg code that could cause corruption
+ * of smb data.
+ */
+
+ cifs_server_lock(server);
+
+ /*
+ * All the parts of the compound chain belong obtained credits from the
+ * same session. We can not use credits obtained from the previous
+ * session to send this request. Check if there were reconnects after
+ * we obtained credits and return -EAGAIN in such cases to let callers
+ * handle it.
+ */
+ if (instance != server->reconnect_instance) {
+ cifs_server_unlock(server);
+ for (j = 0; j < num_rqst; j++)
+ add_credits(server, &credits[j], optype);
+ return -EAGAIN;
+ }
+
+ for (i = 0; i < num_rqst; i++) {
+ midQ[i] = server->ops->setup_request(ses, server, &rqst[i]);
+ if (IS_ERR(midQ[i])) {
+ revert_current_mid(server, i);
+ for (j = 0; j < i; j++)
+ delete_mid(midQ[j]);
+ cifs_server_unlock(server);
+
+ /* Update # of requests on wire to server */
+ for (j = 0; j < num_rqst; j++)
+ add_credits(server, &credits[j], optype);
+ return PTR_ERR(midQ[i]);
+ }
+
+ midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
+ midQ[i]->optype = optype;
+ /*
+ * Invoke callback for every part of the compound chain
+ * to calculate credits properly. Wake up this thread only when
+ * the last element is received.
+ */
+ if (i < num_rqst - 1)
+ midQ[i]->callback = cifs_compound_callback;
+ else
+ midQ[i]->callback = cifs_compound_last_callback;
+ }
+ rc = smb_send_rqst(server, num_rqst, rqst, flags);
+
+ for (i = 0; i < num_rqst; i++)
+ cifs_save_when_sent(midQ[i]);
+
+ if (rc < 0) {
+ revert_current_mid(server, num_rqst);
+ server->sequence_number -= 2;
+ }
+
+ cifs_server_unlock(server);
+
+ /*
+ * If sending failed for some reason or it is an oplock break that we
+ * will not receive a response to - return credits back
+ */
+ if (rc < 0 || (flags & CIFS_NO_SRV_RSP)) {
+ for (i = 0; i < num_rqst; i++)
+ add_credits(server, &credits[i], optype);
+ goto out;
+ }
+
+ /*
+ * At this point the request is passed to the network stack - we assume
+ * that any credits taken from the server structure on the client have
+ * been spent and we can't return them back. Once we receive responses
+ * we will collect credits granted by the server in the mid callbacks
+ * and add those credits to the server structure.
+ */
+
+ /*
+ * Compounding is never used during session establish.
+ */
+ spin_lock(&ses->ses_lock);
+ if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) {
+ spin_unlock(&ses->ses_lock);
+
+ cifs_server_lock(server);
+ smb311_update_preauth_hash(ses, server, rqst[0].rq_iov, rqst[0].rq_nvec);
+ cifs_server_unlock(server);
+
+ spin_lock(&ses->ses_lock);
+ }
+ spin_unlock(&ses->ses_lock);
+
+ for (i = 0; i < num_rqst; i++) {
+ rc = wait_for_response(server, midQ[i]);
+ if (rc != 0)
+ break;
+ }
+ if (rc != 0) {
+ for (; i < num_rqst; i++) {
+ cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n",
+ midQ[i]->mid, le16_to_cpu(midQ[i]->command));
+ send_cancel(server, &rqst[i], midQ[i]);
+ spin_lock(&server->mid_lock);
+ midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
+ if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
+ midQ[i]->callback = cifs_cancelled_callback;
+ cancelled_mid[i] = true;
+ credits[i].value = 0;
+ }
+ spin_unlock(&server->mid_lock);
+ }
+ }
+
+ for (i = 0; i < num_rqst; i++) {
+ if (rc < 0)
+ goto out;
+
+ rc = cifs_sync_mid_result(midQ[i], server);
+ if (rc != 0) {
+ /* mark this mid as cancelled to not free it below */
+ cancelled_mid[i] = true;
+ goto out;
+ }
+
+ if (!midQ[i]->resp_buf ||
+ midQ[i]->mid_state != MID_RESPONSE_RECEIVED) {
+ rc = -EIO;
+ cifs_dbg(FYI, "Bad MID state?\n");
+ goto out;
+ }
+
+ buf = (char *)midQ[i]->resp_buf;
+ resp_iov[i].iov_base = buf;
+ resp_iov[i].iov_len = midQ[i]->resp_buf_size +
+ HEADER_PREAMBLE_SIZE(server);
+
+ if (midQ[i]->large_buf)
+ resp_buf_type[i] = CIFS_LARGE_BUFFER;
+ else
+ resp_buf_type[i] = CIFS_SMALL_BUFFER;
+
+ rc = server->ops->check_receive(midQ[i], server,
+ flags & CIFS_LOG_ERROR);
+
+ /* mark it so buf will not be freed by delete_mid */
+ if ((flags & CIFS_NO_RSP_BUF) == 0)
+ midQ[i]->resp_buf = NULL;
+
+ }
+
+ /*
+ * Compounding is never used during session establish.
+ */
+ spin_lock(&ses->ses_lock);
+ if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) {
+ struct kvec iov = {
+ .iov_base = resp_iov[0].iov_base,
+ .iov_len = resp_iov[0].iov_len
+ };
+ spin_unlock(&ses->ses_lock);
+ cifs_server_lock(server);
+ smb311_update_preauth_hash(ses, server, &iov, 1);
+ cifs_server_unlock(server);
+ spin_lock(&ses->ses_lock);
+ }
+ spin_unlock(&ses->ses_lock);
+
+out:
+ /*
+ * This will dequeue all mids. After this it is important that the
+ * demultiplex_thread will not process any of these mids any futher.
+ * This is prevented above by using a noop callback that will not
+ * wake this thread except for the very last PDU.
+ */
+ for (i = 0; i < num_rqst; i++) {
+ if (!cancelled_mid[i])
+ delete_mid(midQ[i]);
+ }
+
+ return rc;
+}
+
+int
+cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
+ struct TCP_Server_Info *server,
+ struct smb_rqst *rqst, int *resp_buf_type, const int flags,
+ struct kvec *resp_iov)
+{
+ return compound_send_recv(xid, ses, server, flags, 1,
+ rqst, resp_buf_type, resp_iov);
+}
+
+int
+SendReceive2(const unsigned int xid, struct cifs_ses *ses,
+ struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
+ const int flags, struct kvec *resp_iov)
+{
+ struct smb_rqst rqst;
+ struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
+ int rc;
+
+ if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
+ new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec),
+ GFP_KERNEL);
+ if (!new_iov) {
+ /* otherwise cifs_send_recv below sets resp_buf_type */
+ *resp_buf_type = CIFS_NO_BUFFER;
+ return -ENOMEM;
+ }
+ } else
+ new_iov = s_iov;
+
+ /* 1st iov is a RFC1001 length followed by the rest of the packet */
+ memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
+
+ new_iov[0].iov_base = new_iov[1].iov_base;
+ new_iov[0].iov_len = 4;
+ new_iov[1].iov_base += 4;
+ new_iov[1].iov_len -= 4;
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = new_iov;
+ rqst.rq_nvec = n_vec + 1;
+
+ rc = cifs_send_recv(xid, ses, ses->server,
+ &rqst, resp_buf_type, flags, resp_iov);
+ if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
+ kfree(new_iov);
+ return rc;
+}
+
+int
+SendReceive(const unsigned int xid, struct cifs_ses *ses,
+ struct smb_hdr *in_buf, struct smb_hdr *out_buf,
+ int *pbytes_returned, const int flags)
+{
+ int rc = 0;
+ struct mid_q_entry *midQ;
+ unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
+ struct kvec iov = { .iov_base = in_buf, .iov_len = len };
+ struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
+ struct cifs_credits credits = { .value = 1, .instance = 0 };
+ struct TCP_Server_Info *server;
+
+ if (ses == NULL) {
+ cifs_dbg(VFS, "Null smb session\n");
+ return -EIO;
+ }
+ server = ses->server;
+ if (server == NULL) {
+ cifs_dbg(VFS, "Null tcp session\n");
+ return -EIO;
+ }
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsExiting) {
+ spin_unlock(&server->srv_lock);
+ return -ENOENT;
+ }
+ spin_unlock(&server->srv_lock);
+
+ /* Ensure that we do not send more than 50 overlapping requests
+ to the same server. We may make this configurable later or
+ use ses->maxReq */
+
+ if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+ cifs_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
+ len);
+ return -EIO;
+ }
+
+ rc = wait_for_free_request(server, flags, &credits.instance);
+ if (rc)
+ return rc;
+
+ /* make sure that we sign in the same order that we send on this socket
+ and avoid races inside tcp sendmsg code that could cause corruption
+ of smb data */
+
+ cifs_server_lock(server);
+
+ rc = allocate_mid(ses, in_buf, &midQ);
+ if (rc) {
+ cifs_server_unlock(server);
+ /* Update # of requests on wire to server */
+ add_credits(server, &credits, 0);
+ return rc;
+ }
+
+ rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
+ if (rc) {
+ cifs_server_unlock(server);
+ goto out;
+ }
+
+ midQ->mid_state = MID_REQUEST_SUBMITTED;
+
+ rc = smb_send(server, in_buf, len);
+ cifs_save_when_sent(midQ);
+
+ if (rc < 0)
+ server->sequence_number -= 2;
+
+ cifs_server_unlock(server);
+
+ if (rc < 0)
+ goto out;
+
+ rc = wait_for_response(server, midQ);
+ if (rc != 0) {
+ send_cancel(server, &rqst, midQ);
+ spin_lock(&server->mid_lock);
+ if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
+ /* no longer considered to be "in-flight" */
+ midQ->callback = release_mid;
+ spin_unlock(&server->mid_lock);
+ add_credits(server, &credits, 0);
+ return rc;
+ }
+ spin_unlock(&server->mid_lock);
+ }
+
+ rc = cifs_sync_mid_result(midQ, server);
+ if (rc != 0) {
+ add_credits(server, &credits, 0);
+ return rc;
+ }
+
+ if (!midQ->resp_buf || !out_buf ||
+ midQ->mid_state != MID_RESPONSE_RECEIVED) {
+ rc = -EIO;
+ cifs_server_dbg(VFS, "Bad MID state?\n");
+ goto out;
+ }
+
+ *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
+ memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
+ rc = cifs_check_receive(midQ, server, 0);
+out:
+ delete_mid(midQ);
+ add_credits(server, &credits, 0);
+
+ return rc;
+}
+
+/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
+ blocking lock to return. */
+
+static int
+send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
+ struct smb_hdr *in_buf,
+ struct smb_hdr *out_buf)
+{
+ int bytes_returned;
+ struct cifs_ses *ses = tcon->ses;
+ LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
+
+ /* We just modify the current in_buf to change
+ the type of lock from LOCKING_ANDX_SHARED_LOCK
+ or LOCKING_ANDX_EXCLUSIVE_LOCK to
+ LOCKING_ANDX_CANCEL_LOCK. */
+
+ pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
+ pSMB->Timeout = 0;
+ pSMB->hdr.Mid = get_next_mid(ses->server);
+
+ return SendReceive(xid, ses, in_buf, out_buf,
+ &bytes_returned, 0);
+}
+
+int
+SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
+ struct smb_hdr *in_buf, struct smb_hdr *out_buf,
+ int *pbytes_returned)
+{
+ int rc = 0;
+ int rstart = 0;
+ struct mid_q_entry *midQ;
+ struct cifs_ses *ses;
+ unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
+ struct kvec iov = { .iov_base = in_buf, .iov_len = len };
+ struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
+ unsigned int instance;
+ struct TCP_Server_Info *server;
+
+ if (tcon == NULL || tcon->ses == NULL) {
+ cifs_dbg(VFS, "Null smb session\n");
+ return -EIO;
+ }
+ ses = tcon->ses;
+ server = ses->server;
+
+ if (server == NULL) {
+ cifs_dbg(VFS, "Null tcp session\n");
+ return -EIO;
+ }
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus == CifsExiting) {
+ spin_unlock(&server->srv_lock);
+ return -ENOENT;
+ }
+ spin_unlock(&server->srv_lock);
+
+ /* Ensure that we do not send more than 50 overlapping requests
+ to the same server. We may make this configurable later or
+ use ses->maxReq */
+
+ if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+ cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
+ len);
+ return -EIO;
+ }
+
+ rc = wait_for_free_request(server, CIFS_BLOCKING_OP, &instance);
+ if (rc)
+ return rc;
+
+ /* make sure that we sign in the same order that we send on this socket
+ and avoid races inside tcp sendmsg code that could cause corruption
+ of smb data */
+
+ cifs_server_lock(server);
+
+ rc = allocate_mid(ses, in_buf, &midQ);
+ if (rc) {
+ cifs_server_unlock(server);
+ return rc;
+ }
+
+ rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
+ if (rc) {
+ delete_mid(midQ);
+ cifs_server_unlock(server);
+ return rc;
+ }
+
+ midQ->mid_state = MID_REQUEST_SUBMITTED;
+ rc = smb_send(server, in_buf, len);
+ cifs_save_when_sent(midQ);
+
+ if (rc < 0)
+ server->sequence_number -= 2;
+
+ cifs_server_unlock(server);
+
+ if (rc < 0) {
+ delete_mid(midQ);
+ return rc;
+ }
+
+ /* Wait for a reply - allow signals to interrupt. */
+ rc = wait_event_interruptible(server->response_q,
+ (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
+ ((server->tcpStatus != CifsGood) &&
+ (server->tcpStatus != CifsNew)));
+
+ /* Were we interrupted by a signal ? */
+ spin_lock(&server->srv_lock);
+ if ((rc == -ERESTARTSYS) &&
+ (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
+ ((server->tcpStatus == CifsGood) ||
+ (server->tcpStatus == CifsNew))) {
+ spin_unlock(&server->srv_lock);
+
+ if (in_buf->Command == SMB_COM_TRANSACTION2) {
+ /* POSIX lock. We send a NT_CANCEL SMB to cause the
+ blocking lock to return. */
+ rc = send_cancel(server, &rqst, midQ);
+ if (rc) {
+ delete_mid(midQ);
+ return rc;
+ }
+ } else {
+ /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
+ to cause the blocking lock to return. */
+
+ rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
+
+ /* If we get -ENOLCK back the lock may have
+ already been removed. Don't exit in this case. */
+ if (rc && rc != -ENOLCK) {
+ delete_mid(midQ);
+ return rc;
+ }
+ }
+
+ rc = wait_for_response(server, midQ);
+ if (rc) {
+ send_cancel(server, &rqst, midQ);
+ spin_lock(&server->mid_lock);
+ if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
+ /* no longer considered to be "in-flight" */
+ midQ->callback = release_mid;
+ spin_unlock(&server->mid_lock);
+ return rc;
+ }
+ spin_unlock(&server->mid_lock);
+ }
+
+ /* We got the response - restart system call. */
+ rstart = 1;
+ spin_lock(&server->srv_lock);
+ }
+ spin_unlock(&server->srv_lock);
+
+ rc = cifs_sync_mid_result(midQ, server);
+ if (rc != 0)
+ return rc;
+
+ /* rcvd frame is ok */
+ if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
+ rc = -EIO;
+ cifs_tcon_dbg(VFS, "Bad MID state?\n");
+ goto out;
+ }
+
+ *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
+ memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
+ rc = cifs_check_receive(midQ, server, 0);
+out:
+ delete_mid(midQ);
+ if (rstart && rc == -EACCES)
+ return -ERESTARTSYS;
+ return rc;
+}
+
+/*
+ * Discard any remaining data in the current SMB. To do this, we borrow the
+ * current bigbuf.
+ */
+int
+cifs_discard_remaining_data(struct TCP_Server_Info *server)
+{
+ unsigned int rfclen = server->pdu_size;
+ int remaining = rfclen + HEADER_PREAMBLE_SIZE(server) -
+ server->total_read;
+
+ while (remaining > 0) {
+ int length;
+
+ length = cifs_discard_from_socket(server,
+ min_t(size_t, remaining,
+ CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
+ if (length < 0)
+ return length;
+ server->total_read += length;
+ remaining -= length;
+ }
+
+ return 0;
+}
+
+static int
+__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
+ bool malformed)
+{
+ int length;
+
+ length = cifs_discard_remaining_data(server);
+ dequeue_mid(mid, malformed);
+ mid->resp_buf = server->smallbuf;
+ server->smallbuf = NULL;
+ return length;
+}
+
+static int
+cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+ struct cifs_readdata *rdata = mid->callback_data;
+
+ return __cifs_readv_discard(server, mid, rdata->result);
+}
+
+int
+cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+ int length, len;
+ unsigned int data_offset, data_len;
+ struct cifs_readdata *rdata = mid->callback_data;
+ char *buf = server->smallbuf;
+ unsigned int buflen = server->pdu_size + HEADER_PREAMBLE_SIZE(server);
+ bool use_rdma_mr = false;
+
+ cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
+ __func__, mid->mid, rdata->offset, rdata->bytes);
+
+ /*
+ * read the rest of READ_RSP header (sans Data array), or whatever we
+ * can if there's not enough data. At this point, we've read down to
+ * the Mid.
+ */
+ len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
+ HEADER_SIZE(server) + 1;
+
+ length = cifs_read_from_socket(server,
+ buf + HEADER_SIZE(server) - 1, len);
+ if (length < 0)
+ return length;
+ server->total_read += length;
+
+ if (server->ops->is_session_expired &&
+ server->ops->is_session_expired(buf)) {
+ cifs_reconnect(server, true);
+ return -1;
+ }
+
+ if (server->ops->is_status_pending &&
+ server->ops->is_status_pending(buf, server)) {
+ cifs_discard_remaining_data(server);
+ return -1;
+ }
+
+ /* set up first two iov for signature check and to get credits */
+ rdata->iov[0].iov_base = buf;
+ rdata->iov[0].iov_len = HEADER_PREAMBLE_SIZE(server);
+ rdata->iov[1].iov_base = buf + HEADER_PREAMBLE_SIZE(server);
+ rdata->iov[1].iov_len =
+ server->total_read - HEADER_PREAMBLE_SIZE(server);
+ cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+ rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+ cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+ rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
+ /* Was the SMB read successful? */
+ rdata->result = server->ops->map_error(buf, false);
+ if (rdata->result != 0) {
+ cifs_dbg(FYI, "%s: server returned error %d\n",
+ __func__, rdata->result);
+ /* normal error on read response */
+ return __cifs_readv_discard(server, mid, false);
+ }
+
+ /* Is there enough to get to the rest of the READ_RSP header? */
+ if (server->total_read < server->vals->read_rsp_size) {
+ cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
+ __func__, server->total_read,
+ server->vals->read_rsp_size);
+ rdata->result = -EIO;
+ return cifs_readv_discard(server, mid);
+ }
+
+ data_offset = server->ops->read_data_offset(buf) +
+ HEADER_PREAMBLE_SIZE(server);
+ if (data_offset < server->total_read) {
+ /*
+ * win2k8 sometimes sends an offset of 0 when the read
+ * is beyond the EOF. Treat it as if the data starts just after
+ * the header.
+ */
+ cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
+ __func__, data_offset);
+ data_offset = server->total_read;
+ } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
+ /* data_offset is beyond the end of smallbuf */
+ cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
+ __func__, data_offset);
+ rdata->result = -EIO;
+ return cifs_readv_discard(server, mid);
+ }
+
+ cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
+ __func__, server->total_read, data_offset);
+
+ len = data_offset - server->total_read;
+ if (len > 0) {
+ /* read any junk before data into the rest of smallbuf */
+ length = cifs_read_from_socket(server,
+ buf + server->total_read, len);
+ if (length < 0)
+ return length;
+ server->total_read += length;
+ }
+
+ /* how much data is in the response? */
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ use_rdma_mr = rdata->mr;
+#endif
+ data_len = server->ops->read_data_length(buf, use_rdma_mr);
+ if (!use_rdma_mr && (data_offset + data_len > buflen)) {
+ /* data_len is corrupt -- discard frame */
+ rdata->result = -EIO;
+ return cifs_readv_discard(server, mid);
+ }
+
+ length = rdata->read_into_pages(server, rdata, data_len);
+ if (length < 0)
+ return length;
+
+ server->total_read += length;
+
+ cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
+ server->total_read, buflen, data_len);
+
+ /* discard anything left over */
+ if (server->total_read < buflen)
+ return cifs_readv_discard(server, mid);
+
+ dequeue_mid(mid, false);
+ mid->resp_buf = server->smallbuf;
+ server->smallbuf = NULL;
+ return length;
+}
diff --git a/fs/smb/client/unc.c b/fs/smb/client/unc.c
new file mode 100644
index 000000000000..f6fc5e343ea4
--- /dev/null
+++ b/fs/smb/client/unc.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020, Microsoft Corporation.
+ *
+ * Author(s): Steve French <stfrench@microsoft.com>
+ * Suresh Jayaraman <sjayaraman@suse.de>
+ * Jeff Layton <jlayton@kernel.org>
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/inet.h>
+#include <linux/ctype.h>
+#include "cifsglob.h"
+#include "cifsproto.h"
+
+/* extract the host portion of the UNC string */
+char *extract_hostname(const char *unc)
+{
+ const char *src;
+ char *dst, *delim;
+ unsigned int len;
+
+ /* skip double chars at beginning of string */
+ /* BB: check validity of these bytes? */
+ if (strlen(unc) < 3)
+ return ERR_PTR(-EINVAL);
+ for (src = unc; *src && *src == '\\'; src++)
+ ;
+ if (!*src)
+ return ERR_PTR(-EINVAL);
+
+ /* delimiter between hostname and sharename is always '\\' now */
+ delim = strchr(src, '\\');
+ if (!delim)
+ return ERR_PTR(-EINVAL);
+
+ len = delim - src;
+ dst = kmalloc((len + 1), GFP_KERNEL);
+ if (dst == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(dst, src, len);
+ dst[len] = '\0';
+
+ return dst;
+}
+
+char *extract_sharename(const char *unc)
+{
+ const char *src;
+ char *delim, *dst;
+
+ /* skip double chars at the beginning */
+ src = unc + 2;
+
+ /* share name is always preceded by '\\' now */
+ delim = strchr(src, '\\');
+ if (!delim)
+ return ERR_PTR(-EINVAL);
+ delim++;
+
+ /* caller has to free the memory */
+ dst = kstrdup(delim, GFP_KERNEL);
+ if (!dst)
+ return ERR_PTR(-ENOMEM);
+
+ return dst;
+}
diff --git a/fs/smb/client/winucase.c b/fs/smb/client/winucase.c
new file mode 100644
index 000000000000..2f075b5b50df
--- /dev/null
+++ b/fs/smb/client/winucase.c
@@ -0,0 +1,649 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ * Copyright (c) Jeffrey Layton <jlayton@redhat.com>, 2013
+ *
+ * The const tables in this file were converted from the following info
+ * provided by Microsoft:
+ *
+ * 3.1.5.3 Mapping UTF-16 Strings to Upper Case:
+ *
+ * https://msdn.microsoft.com/en-us/library/hh877830.aspx
+ * http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=10921
+ *
+ * In particular, the table in "Windows 8 Upper Case Mapping Table.txt" was
+ * post-processed using the winucase_convert.pl script.
+ */
+
+#include <linux/nls.h>
+
+wchar_t cifs_toupper(wchar_t in); /* quiet sparse */
+
+static const wchar_t t2_00[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0000,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178,
+};
+
+static const wchar_t t2_01[256] = {
+ 0x0000, 0x0100, 0x0000, 0x0102, 0x0000, 0x0104, 0x0000, 0x0106,
+ 0x0000, 0x0108, 0x0000, 0x010a, 0x0000, 0x010c, 0x0000, 0x010e,
+ 0x0000, 0x0110, 0x0000, 0x0112, 0x0000, 0x0114, 0x0000, 0x0116,
+ 0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x011c, 0x0000, 0x011e,
+ 0x0000, 0x0120, 0x0000, 0x0122, 0x0000, 0x0124, 0x0000, 0x0126,
+ 0x0000, 0x0128, 0x0000, 0x012a, 0x0000, 0x012c, 0x0000, 0x012e,
+ 0x0000, 0x0000, 0x0000, 0x0132, 0x0000, 0x0134, 0x0000, 0x0136,
+ 0x0000, 0x0000, 0x0139, 0x0000, 0x013b, 0x0000, 0x013d, 0x0000,
+ 0x013f, 0x0000, 0x0141, 0x0000, 0x0143, 0x0000, 0x0145, 0x0000,
+ 0x0147, 0x0000, 0x0000, 0x014a, 0x0000, 0x014c, 0x0000, 0x014e,
+ 0x0000, 0x0150, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156,
+ 0x0000, 0x0158, 0x0000, 0x015a, 0x0000, 0x015c, 0x0000, 0x015e,
+ 0x0000, 0x0160, 0x0000, 0x0162, 0x0000, 0x0164, 0x0000, 0x0166,
+ 0x0000, 0x0168, 0x0000, 0x016a, 0x0000, 0x016c, 0x0000, 0x016e,
+ 0x0000, 0x0170, 0x0000, 0x0172, 0x0000, 0x0174, 0x0000, 0x0176,
+ 0x0000, 0x0000, 0x0179, 0x0000, 0x017b, 0x0000, 0x017d, 0x0000,
+ 0x0243, 0x0000, 0x0000, 0x0182, 0x0000, 0x0184, 0x0000, 0x0000,
+ 0x0187, 0x0000, 0x0000, 0x0000, 0x018b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0191, 0x0000, 0x0000, 0x01f6, 0x0000, 0x0000,
+ 0x0000, 0x0198, 0x023d, 0x0000, 0x0000, 0x0000, 0x0220, 0x0000,
+ 0x0000, 0x01a0, 0x0000, 0x01a2, 0x0000, 0x01a4, 0x0000, 0x0000,
+ 0x01a7, 0x0000, 0x0000, 0x0000, 0x0000, 0x01ac, 0x0000, 0x0000,
+ 0x01af, 0x0000, 0x0000, 0x0000, 0x01b3, 0x0000, 0x01b5, 0x0000,
+ 0x0000, 0x01b8, 0x0000, 0x0000, 0x0000, 0x01bc, 0x0000, 0x01f7,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01c4, 0x0000,
+ 0x0000, 0x01c7, 0x0000, 0x0000, 0x01ca, 0x0000, 0x01cd, 0x0000,
+ 0x01cf, 0x0000, 0x01d1, 0x0000, 0x01d3, 0x0000, 0x01d5, 0x0000,
+ 0x01d7, 0x0000, 0x01d9, 0x0000, 0x01db, 0x018e, 0x0000, 0x01de,
+ 0x0000, 0x01e0, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6,
+ 0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x0000, 0x01ee,
+ 0x0000, 0x0000, 0x0000, 0x01f1, 0x0000, 0x01f4, 0x0000, 0x0000,
+ 0x0000, 0x01f8, 0x0000, 0x01fa, 0x0000, 0x01fc, 0x0000, 0x01fe,
+};
+
+static const wchar_t t2_02[256] = {
+ 0x0000, 0x0200, 0x0000, 0x0202, 0x0000, 0x0204, 0x0000, 0x0206,
+ 0x0000, 0x0208, 0x0000, 0x020a, 0x0000, 0x020c, 0x0000, 0x020e,
+ 0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0214, 0x0000, 0x0216,
+ 0x0000, 0x0218, 0x0000, 0x021a, 0x0000, 0x021c, 0x0000, 0x021e,
+ 0x0000, 0x0000, 0x0000, 0x0222, 0x0000, 0x0224, 0x0000, 0x0226,
+ 0x0000, 0x0228, 0x0000, 0x022a, 0x0000, 0x022c, 0x0000, 0x022e,
+ 0x0000, 0x0230, 0x0000, 0x0232, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x023b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0241, 0x0000, 0x0000, 0x0000, 0x0000, 0x0246,
+ 0x0000, 0x0248, 0x0000, 0x024a, 0x0000, 0x024c, 0x0000, 0x024e,
+ 0x2c6f, 0x2c6d, 0x0000, 0x0181, 0x0186, 0x0000, 0x0189, 0x018a,
+ 0x0000, 0x018f, 0x0000, 0x0190, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0193, 0x0000, 0x0000, 0x0194, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0197, 0x0196, 0x0000, 0x2c62, 0x0000, 0x0000, 0x0000, 0x019c,
+ 0x0000, 0x2c6e, 0x019d, 0x0000, 0x0000, 0x019f, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2c64, 0x0000, 0x0000,
+ 0x01a6, 0x0000, 0x0000, 0x01a9, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x01ae, 0x0244, 0x01b1, 0x01b2, 0x0245, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x01b7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_03[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0370, 0x0000, 0x0372, 0x0000, 0x0000, 0x0000, 0x0376,
+ 0x0000, 0x0000, 0x0000, 0x03fd, 0x03fe, 0x03ff, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0386, 0x0388, 0x0389, 0x038a,
+ 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
+ 0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
+ 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x038c, 0x038e, 0x038f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03cf,
+ 0x0000, 0x03d8, 0x0000, 0x03da, 0x0000, 0x03dc, 0x0000, 0x03de,
+ 0x0000, 0x03e0, 0x0000, 0x03e2, 0x0000, 0x03e4, 0x0000, 0x03e6,
+ 0x0000, 0x03e8, 0x0000, 0x03ea, 0x0000, 0x03ec, 0x0000, 0x03ee,
+ 0x0000, 0x0000, 0x03f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x03f7, 0x0000, 0x0000, 0x03fa, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_04[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
+ 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
+ 0x0000, 0x0460, 0x0000, 0x0462, 0x0000, 0x0464, 0x0000, 0x0466,
+ 0x0000, 0x0468, 0x0000, 0x046a, 0x0000, 0x046c, 0x0000, 0x046e,
+ 0x0000, 0x0470, 0x0000, 0x0472, 0x0000, 0x0474, 0x0000, 0x0476,
+ 0x0000, 0x0478, 0x0000, 0x047a, 0x0000, 0x047c, 0x0000, 0x047e,
+ 0x0000, 0x0480, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x048a, 0x0000, 0x048c, 0x0000, 0x048e,
+ 0x0000, 0x0490, 0x0000, 0x0492, 0x0000, 0x0494, 0x0000, 0x0496,
+ 0x0000, 0x0498, 0x0000, 0x049a, 0x0000, 0x049c, 0x0000, 0x049e,
+ 0x0000, 0x04a0, 0x0000, 0x04a2, 0x0000, 0x04a4, 0x0000, 0x04a6,
+ 0x0000, 0x04a8, 0x0000, 0x04aa, 0x0000, 0x04ac, 0x0000, 0x04ae,
+ 0x0000, 0x04b0, 0x0000, 0x04b2, 0x0000, 0x04b4, 0x0000, 0x04b6,
+ 0x0000, 0x04b8, 0x0000, 0x04ba, 0x0000, 0x04bc, 0x0000, 0x04be,
+ 0x0000, 0x0000, 0x04c1, 0x0000, 0x04c3, 0x0000, 0x04c5, 0x0000,
+ 0x04c7, 0x0000, 0x04c9, 0x0000, 0x04cb, 0x0000, 0x04cd, 0x04c0,
+ 0x0000, 0x04d0, 0x0000, 0x04d2, 0x0000, 0x04d4, 0x0000, 0x04d6,
+ 0x0000, 0x04d8, 0x0000, 0x04da, 0x0000, 0x04dc, 0x0000, 0x04de,
+ 0x0000, 0x04e0, 0x0000, 0x04e2, 0x0000, 0x04e4, 0x0000, 0x04e6,
+ 0x0000, 0x04e8, 0x0000, 0x04ea, 0x0000, 0x04ec, 0x0000, 0x04ee,
+ 0x0000, 0x04f0, 0x0000, 0x04f2, 0x0000, 0x04f4, 0x0000, 0x04f6,
+ 0x0000, 0x04f8, 0x0000, 0x04fa, 0x0000, 0x04fc, 0x0000, 0x04fe,
+};
+
+static const wchar_t t2_05[256] = {
+ 0x0000, 0x0500, 0x0000, 0x0502, 0x0000, 0x0504, 0x0000, 0x0506,
+ 0x0000, 0x0508, 0x0000, 0x050a, 0x0000, 0x050c, 0x0000, 0x050e,
+ 0x0000, 0x0510, 0x0000, 0x0512, 0x0000, 0x0514, 0x0000, 0x0516,
+ 0x0000, 0x0518, 0x0000, 0x051a, 0x0000, 0x051c, 0x0000, 0x051e,
+ 0x0000, 0x0520, 0x0000, 0x0522, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,
+ 0x0538, 0x0539, 0x053a, 0x053b, 0x053c, 0x053d, 0x053e, 0x053f,
+ 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,
+ 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, 0x054e, 0x054f,
+ 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_1d[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa77d, 0x0000, 0x0000, 0x0000, 0x2c63, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_1e[256] = {
+ 0x0000, 0x1e00, 0x0000, 0x1e02, 0x0000, 0x1e04, 0x0000, 0x1e06,
+ 0x0000, 0x1e08, 0x0000, 0x1e0a, 0x0000, 0x1e0c, 0x0000, 0x1e0e,
+ 0x0000, 0x1e10, 0x0000, 0x1e12, 0x0000, 0x1e14, 0x0000, 0x1e16,
+ 0x0000, 0x1e18, 0x0000, 0x1e1a, 0x0000, 0x1e1c, 0x0000, 0x1e1e,
+ 0x0000, 0x1e20, 0x0000, 0x1e22, 0x0000, 0x1e24, 0x0000, 0x1e26,
+ 0x0000, 0x1e28, 0x0000, 0x1e2a, 0x0000, 0x1e2c, 0x0000, 0x1e2e,
+ 0x0000, 0x1e30, 0x0000, 0x1e32, 0x0000, 0x1e34, 0x0000, 0x1e36,
+ 0x0000, 0x1e38, 0x0000, 0x1e3a, 0x0000, 0x1e3c, 0x0000, 0x1e3e,
+ 0x0000, 0x1e40, 0x0000, 0x1e42, 0x0000, 0x1e44, 0x0000, 0x1e46,
+ 0x0000, 0x1e48, 0x0000, 0x1e4a, 0x0000, 0x1e4c, 0x0000, 0x1e4e,
+ 0x0000, 0x1e50, 0x0000, 0x1e52, 0x0000, 0x1e54, 0x0000, 0x1e56,
+ 0x0000, 0x1e58, 0x0000, 0x1e5a, 0x0000, 0x1e5c, 0x0000, 0x1e5e,
+ 0x0000, 0x1e60, 0x0000, 0x1e62, 0x0000, 0x1e64, 0x0000, 0x1e66,
+ 0x0000, 0x1e68, 0x0000, 0x1e6a, 0x0000, 0x1e6c, 0x0000, 0x1e6e,
+ 0x0000, 0x1e70, 0x0000, 0x1e72, 0x0000, 0x1e74, 0x0000, 0x1e76,
+ 0x0000, 0x1e78, 0x0000, 0x1e7a, 0x0000, 0x1e7c, 0x0000, 0x1e7e,
+ 0x0000, 0x1e80, 0x0000, 0x1e82, 0x0000, 0x1e84, 0x0000, 0x1e86,
+ 0x0000, 0x1e88, 0x0000, 0x1e8a, 0x0000, 0x1e8c, 0x0000, 0x1e8e,
+ 0x0000, 0x1e90, 0x0000, 0x1e92, 0x0000, 0x1e94, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1ea0, 0x0000, 0x1ea2, 0x0000, 0x1ea4, 0x0000, 0x1ea6,
+ 0x0000, 0x1ea8, 0x0000, 0x1eaa, 0x0000, 0x1eac, 0x0000, 0x1eae,
+ 0x0000, 0x1eb0, 0x0000, 0x1eb2, 0x0000, 0x1eb4, 0x0000, 0x1eb6,
+ 0x0000, 0x1eb8, 0x0000, 0x1eba, 0x0000, 0x1ebc, 0x0000, 0x1ebe,
+ 0x0000, 0x1ec0, 0x0000, 0x1ec2, 0x0000, 0x1ec4, 0x0000, 0x1ec6,
+ 0x0000, 0x1ec8, 0x0000, 0x1eca, 0x0000, 0x1ecc, 0x0000, 0x1ece,
+ 0x0000, 0x1ed0, 0x0000, 0x1ed2, 0x0000, 0x1ed4, 0x0000, 0x1ed6,
+ 0x0000, 0x1ed8, 0x0000, 0x1eda, 0x0000, 0x1edc, 0x0000, 0x1ede,
+ 0x0000, 0x1ee0, 0x0000, 0x1ee2, 0x0000, 0x1ee4, 0x0000, 0x1ee6,
+ 0x0000, 0x1ee8, 0x0000, 0x1eea, 0x0000, 0x1eec, 0x0000, 0x1eee,
+ 0x0000, 0x1ef0, 0x0000, 0x1ef2, 0x0000, 0x1ef4, 0x0000, 0x1ef6,
+ 0x0000, 0x1ef8, 0x0000, 0x1efa, 0x0000, 0x1efc, 0x0000, 0x1efe,
+};
+
+static const wchar_t t2_1f[256] = {
+ 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, 0x1f1c, 0x1f1d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, 0x1f4c, 0x1f4d, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1f59, 0x0000, 0x1f5b, 0x0000, 0x1f5d, 0x0000, 0x1f5f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1fba, 0x1fbb, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, 0x1fda, 0x1fdb,
+ 0x1ff8, 0x1ff9, 0x1fea, 0x1feb, 0x1ffa, 0x1ffb, 0x0000, 0x0000,
+ 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1fb8, 0x1fb9, 0x0000, 0x1fbc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x1fcc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1fd8, 0x1fd9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1fe8, 0x1fe9, 0x0000, 0x0000, 0x0000, 0x1fec, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x1ffc, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_21[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2132, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,
+ 0x2168, 0x2169, 0x216a, 0x216b, 0x216c, 0x216d, 0x216e, 0x216f,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2183, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_24[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba, 0x24bb, 0x24bc, 0x24bd,
+ 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2, 0x24c3, 0x24c4, 0x24c5,
+ 0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca, 0x24cb, 0x24cc, 0x24cd,
+ 0x24ce, 0x24cf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_2c[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2c00, 0x2c01, 0x2c02, 0x2c03, 0x2c04, 0x2c05, 0x2c06, 0x2c07,
+ 0x2c08, 0x2c09, 0x2c0a, 0x2c0b, 0x2c0c, 0x2c0d, 0x2c0e, 0x2c0f,
+ 0x2c10, 0x2c11, 0x2c12, 0x2c13, 0x2c14, 0x2c15, 0x2c16, 0x2c17,
+ 0x2c18, 0x2c19, 0x2c1a, 0x2c1b, 0x2c1c, 0x2c1d, 0x2c1e, 0x2c1f,
+ 0x2c20, 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c27,
+ 0x2c28, 0x2c29, 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x0000,
+ 0x0000, 0x2c60, 0x0000, 0x0000, 0x0000, 0x023a, 0x023e, 0x0000,
+ 0x2c67, 0x0000, 0x2c69, 0x0000, 0x2c6b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2c72, 0x0000, 0x0000, 0x2c75, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2c80, 0x0000, 0x2c82, 0x0000, 0x2c84, 0x0000, 0x2c86,
+ 0x0000, 0x2c88, 0x0000, 0x2c8a, 0x0000, 0x2c8c, 0x0000, 0x2c8e,
+ 0x0000, 0x2c90, 0x0000, 0x2c92, 0x0000, 0x2c94, 0x0000, 0x2c96,
+ 0x0000, 0x2c98, 0x0000, 0x2c9a, 0x0000, 0x2c9c, 0x0000, 0x2c9e,
+ 0x0000, 0x2ca0, 0x0000, 0x2ca2, 0x0000, 0x2ca4, 0x0000, 0x2ca6,
+ 0x0000, 0x2ca8, 0x0000, 0x2caa, 0x0000, 0x2cac, 0x0000, 0x2cae,
+ 0x0000, 0x2cb0, 0x0000, 0x2cb2, 0x0000, 0x2cb4, 0x0000, 0x2cb6,
+ 0x0000, 0x2cb8, 0x0000, 0x2cba, 0x0000, 0x2cbc, 0x0000, 0x2cbe,
+ 0x0000, 0x2cc0, 0x0000, 0x2cc2, 0x0000, 0x2cc4, 0x0000, 0x2cc6,
+ 0x0000, 0x2cc8, 0x0000, 0x2cca, 0x0000, 0x2ccc, 0x0000, 0x2cce,
+ 0x0000, 0x2cd0, 0x0000, 0x2cd2, 0x0000, 0x2cd4, 0x0000, 0x2cd6,
+ 0x0000, 0x2cd8, 0x0000, 0x2cda, 0x0000, 0x2cdc, 0x0000, 0x2cde,
+ 0x0000, 0x2ce0, 0x0000, 0x2ce2, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_2d[256] = {
+ 0x10a0, 0x10a1, 0x10a2, 0x10a3, 0x10a4, 0x10a5, 0x10a6, 0x10a7,
+ 0x10a8, 0x10a9, 0x10aa, 0x10ab, 0x10ac, 0x10ad, 0x10ae, 0x10af,
+ 0x10b0, 0x10b1, 0x10b2, 0x10b3, 0x10b4, 0x10b5, 0x10b6, 0x10b7,
+ 0x10b8, 0x10b9, 0x10ba, 0x10bb, 0x10bc, 0x10bd, 0x10be, 0x10bf,
+ 0x10c0, 0x10c1, 0x10c2, 0x10c3, 0x10c4, 0x10c5, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_a6[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa640, 0x0000, 0xa642, 0x0000, 0xa644, 0x0000, 0xa646,
+ 0x0000, 0xa648, 0x0000, 0xa64a, 0x0000, 0xa64c, 0x0000, 0xa64e,
+ 0x0000, 0xa650, 0x0000, 0xa652, 0x0000, 0xa654, 0x0000, 0xa656,
+ 0x0000, 0xa658, 0x0000, 0xa65a, 0x0000, 0xa65c, 0x0000, 0xa65e,
+ 0x0000, 0x0000, 0x0000, 0xa662, 0x0000, 0xa664, 0x0000, 0xa666,
+ 0x0000, 0xa668, 0x0000, 0xa66a, 0x0000, 0xa66c, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xa680, 0x0000, 0xa682, 0x0000, 0xa684, 0x0000, 0xa686,
+ 0x0000, 0xa688, 0x0000, 0xa68a, 0x0000, 0xa68c, 0x0000, 0xa68e,
+ 0x0000, 0xa690, 0x0000, 0xa692, 0x0000, 0xa694, 0x0000, 0xa696,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_a7[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xa722, 0x0000, 0xa724, 0x0000, 0xa726,
+ 0x0000, 0xa728, 0x0000, 0xa72a, 0x0000, 0xa72c, 0x0000, 0xa72e,
+ 0x0000, 0x0000, 0x0000, 0xa732, 0x0000, 0xa734, 0x0000, 0xa736,
+ 0x0000, 0xa738, 0x0000, 0xa73a, 0x0000, 0xa73c, 0x0000, 0xa73e,
+ 0x0000, 0xa740, 0x0000, 0xa742, 0x0000, 0xa744, 0x0000, 0xa746,
+ 0x0000, 0xa748, 0x0000, 0xa74a, 0x0000, 0xa74c, 0x0000, 0xa74e,
+ 0x0000, 0xa750, 0x0000, 0xa752, 0x0000, 0xa754, 0x0000, 0xa756,
+ 0x0000, 0xa758, 0x0000, 0xa75a, 0x0000, 0xa75c, 0x0000, 0xa75e,
+ 0x0000, 0xa760, 0x0000, 0xa762, 0x0000, 0xa764, 0x0000, 0xa766,
+ 0x0000, 0xa768, 0x0000, 0xa76a, 0x0000, 0xa76c, 0x0000, 0xa76e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xa779, 0x0000, 0xa77b, 0x0000, 0x0000, 0xa77e,
+ 0x0000, 0xa780, 0x0000, 0xa782, 0x0000, 0xa784, 0x0000, 0xa786,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xa78b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t t2_ff[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27,
+ 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f,
+ 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37,
+ 0xff38, 0xff39, 0xff3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const wchar_t *const toplevel[256] = {
+ t2_00, t2_01, t2_02, t2_03, t2_04, t2_05, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, t2_1d, t2_1e, t2_1f,
+ NULL, t2_21, NULL, NULL, t2_24, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, t2_2c, t2_2d, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, t2_a6, t2_a7,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, t2_ff,
+};
+
+/**
+ * cifs_toupper - convert a wchar_t from lower to uppercase
+ * @in: character to convert from lower to uppercase
+ *
+ * This function consults the static tables above to convert a wchar_t from
+ * lower to uppercase. In the event that there is no mapping, the original
+ * "in" character is returned.
+ */
+wchar_t
+cifs_toupper(wchar_t in)
+{
+ unsigned char idx;
+ const wchar_t *tbl;
+ wchar_t out;
+
+ /* grab upper byte */
+ idx = (in & 0xff00) >> 8;
+
+ /* find pointer to 2nd layer table */
+ tbl = toplevel[idx];
+ if (!tbl)
+ return in;
+
+ /* grab lower byte */
+ idx = in & 0xff;
+
+ /* look up character in table */
+ out = tbl[idx];
+ if (out)
+ return out;
+
+ return in;
+}
diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c
new file mode 100644
index 000000000000..998fa51f9b68
--- /dev/null
+++ b/fs/smb/client/xattr.c
@@ -0,0 +1,555 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2003, 2007
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/slab.h>
+#include <linux/xattr.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifs_unicode.h"
+#include "cifs_ioctl.h"
+
+#define MAX_EA_VALUE_SIZE CIFSMaxBufSize
+#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" /* DACL only */
+#define CIFS_XATTR_CIFS_NTSD "system.cifs_ntsd" /* owner plus DACL */
+#define CIFS_XATTR_CIFS_NTSD_FULL "system.cifs_ntsd_full" /* owner/DACL/SACL */
+#define CIFS_XATTR_ATTRIB "cifs.dosattrib" /* full name: user.cifs.dosattrib */
+#define CIFS_XATTR_CREATETIME "cifs.creationtime" /* user.cifs.creationtime */
+/*
+ * Although these three are just aliases for the above, need to move away from
+ * confusing users and using the 20+ year old term 'cifs' when it is no longer
+ * secure, replaced by SMB2 (then even more highly secure SMB3) many years ago
+ */
+#define SMB3_XATTR_CIFS_ACL "system.smb3_acl" /* DACL only */
+#define SMB3_XATTR_CIFS_NTSD "system.smb3_ntsd" /* owner plus DACL */
+#define SMB3_XATTR_CIFS_NTSD_FULL "system.smb3_ntsd_full" /* owner/DACL/SACL */
+#define SMB3_XATTR_ATTRIB "smb3.dosattrib" /* full name: user.smb3.dosattrib */
+#define SMB3_XATTR_CREATETIME "smb3.creationtime" /* user.smb3.creationtime */
+/* BB need to add server (Samba e.g) support for security and trusted prefix */
+
+enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
+ XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
+
+static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon,
+ struct inode *inode, const char *full_path,
+ const void *value, size_t size)
+{
+ ssize_t rc = -EOPNOTSUPP;
+ __u32 *pattrib = (__u32 *)value;
+ __u32 attrib;
+ FILE_BASIC_INFO info_buf;
+
+ if ((value == NULL) || (size != sizeof(__u32)))
+ return -ERANGE;
+
+ memset(&info_buf, 0, sizeof(info_buf));
+ attrib = *pattrib;
+ info_buf.Attributes = cpu_to_le32(attrib);
+ if (pTcon->ses->server->ops->set_file_info)
+ rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
+ &info_buf, xid);
+ if (rc == 0)
+ CIFS_I(inode)->cifsAttrs = attrib;
+
+ return rc;
+}
+
+static int cifs_creation_time_set(unsigned int xid, struct cifs_tcon *pTcon,
+ struct inode *inode, const char *full_path,
+ const void *value, size_t size)
+{
+ ssize_t rc = -EOPNOTSUPP;
+ __u64 *pcreation_time = (__u64 *)value;
+ __u64 creation_time;
+ FILE_BASIC_INFO info_buf;
+
+ if ((value == NULL) || (size != sizeof(__u64)))
+ return -ERANGE;
+
+ memset(&info_buf, 0, sizeof(info_buf));
+ creation_time = *pcreation_time;
+ info_buf.CreationTime = cpu_to_le64(creation_time);
+ if (pTcon->ses->server->ops->set_file_info)
+ rc = pTcon->ses->server->ops->set_file_info(inode, full_path,
+ &info_buf, xid);
+ if (rc == 0)
+ CIFS_I(inode)->createtime = creation_time;
+
+ return rc;
+}
+
+static int cifs_xattr_set(const struct xattr_handler *handler,
+ struct user_namespace *mnt_userns,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, const void *value,
+ size_t size, int flags)
+{
+ int rc = -EOPNOTSUPP;
+ unsigned int xid;
+ struct super_block *sb = dentry->d_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *pTcon;
+ const char *full_path;
+ void *page;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ pTcon = tlink_tcon(tlink);
+
+ xid = get_xid();
+ page = alloc_dentry_path();
+
+ full_path = build_path_from_dentry(dentry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto out;
+ }
+ /* return dos attributes as pseudo xattr */
+ /* return alt name if available as pseudo attr */
+
+ /* if proc/fs/cifs/streamstoxattr is set then
+ search server for EAs or streams to
+ returns as xattrs */
+ if (size > MAX_EA_VALUE_SIZE) {
+ cifs_dbg(FYI, "size of EA value too large\n");
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
+ switch (handler->flags) {
+ case XATTR_USER:
+ cifs_dbg(FYI, "%s:setting user xattr %s\n", __func__, name);
+ if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
+ (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
+ rc = cifs_attrib_set(xid, pTcon, inode, full_path,
+ value, size);
+ if (rc == 0) /* force revalidate of the inode */
+ CIFS_I(inode)->time = 0;
+ break;
+ } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
+ (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
+ rc = cifs_creation_time_set(xid, pTcon, inode,
+ full_path, value, size);
+ if (rc == 0) /* force revalidate of the inode */
+ CIFS_I(inode)->time = 0;
+ break;
+ }
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ goto out;
+
+ if (pTcon->ses->server->ops->set_EA)
+ rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
+ full_path, name, value, (__u16)size,
+ cifs_sb->local_nls, cifs_sb);
+ break;
+
+ case XATTR_CIFS_ACL:
+ case XATTR_CIFS_NTSD:
+ case XATTR_CIFS_NTSD_FULL: {
+ struct cifs_ntsd *pacl;
+
+ if (!value)
+ goto out;
+ pacl = kmalloc(size, GFP_KERNEL);
+ if (!pacl) {
+ rc = -ENOMEM;
+ } else {
+ memcpy(pacl, value, size);
+ if (pTcon->ses->server->ops->set_acl) {
+ int aclflags = 0;
+ rc = 0;
+
+ switch (handler->flags) {
+ case XATTR_CIFS_NTSD_FULL:
+ aclflags = (CIFS_ACL_OWNER |
+ CIFS_ACL_GROUP |
+ CIFS_ACL_DACL |
+ CIFS_ACL_SACL);
+ break;
+ case XATTR_CIFS_NTSD:
+ aclflags = (CIFS_ACL_OWNER |
+ CIFS_ACL_GROUP |
+ CIFS_ACL_DACL);
+ break;
+ case XATTR_CIFS_ACL:
+ default:
+ aclflags = CIFS_ACL_DACL;
+ }
+
+ rc = pTcon->ses->server->ops->set_acl(pacl,
+ size, inode, full_path, aclflags);
+ } else {
+ rc = -EOPNOTSUPP;
+ }
+ if (rc == 0) /* force revalidate of the inode */
+ CIFS_I(inode)->time = 0;
+ kfree(pacl);
+ }
+ break;
+ }
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ case XATTR_ACL_ACCESS:
+#ifdef CONFIG_CIFS_POSIX
+ if (!value)
+ goto out;
+ if (sb->s_flags & SB_POSIXACL)
+ rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
+ value, (const int)size,
+ ACL_TYPE_ACCESS, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+#endif /* CONFIG_CIFS_POSIX */
+ break;
+
+ case XATTR_ACL_DEFAULT:
+#ifdef CONFIG_CIFS_POSIX
+ if (!value)
+ goto out;
+ if (sb->s_flags & SB_POSIXACL)
+ rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
+ value, (const int)size,
+ ACL_TYPE_DEFAULT, cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+#endif /* CONFIG_CIFS_POSIX */
+ break;
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ }
+
+out:
+ free_dentry_path(page);
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+static int cifs_attrib_get(struct dentry *dentry,
+ struct inode *inode, void *value,
+ size_t size)
+{
+ ssize_t rc;
+ __u32 *pattribute;
+
+ rc = cifs_revalidate_dentry_attr(dentry);
+
+ if (rc)
+ return rc;
+
+ if ((value == NULL) || (size == 0))
+ return sizeof(__u32);
+ else if (size < sizeof(__u32))
+ return -ERANGE;
+
+ /* return dos attributes as pseudo xattr */
+ pattribute = (__u32 *)value;
+ *pattribute = CIFS_I(inode)->cifsAttrs;
+
+ return sizeof(__u32);
+}
+
+static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
+ void *value, size_t size)
+{
+ ssize_t rc;
+ __u64 *pcreatetime;
+
+ rc = cifs_revalidate_dentry_attr(dentry);
+ if (rc)
+ return rc;
+
+ if ((value == NULL) || (size == 0))
+ return sizeof(__u64);
+ else if (size < sizeof(__u64))
+ return -ERANGE;
+
+ /* return dos attributes as pseudo xattr */
+ pcreatetime = (__u64 *)value;
+ *pcreatetime = CIFS_I(inode)->createtime;
+ return sizeof(__u64);
+}
+
+
+static int cifs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, void *value, size_t size)
+{
+ ssize_t rc = -EOPNOTSUPP;
+ unsigned int xid;
+ struct super_block *sb = dentry->d_sb;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *pTcon;
+ const char *full_path;
+ void *page;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ pTcon = tlink_tcon(tlink);
+
+ xid = get_xid();
+ page = alloc_dentry_path();
+
+ full_path = build_path_from_dentry(dentry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto out;
+ }
+
+ /* return alt name if available as pseudo attr */
+ switch (handler->flags) {
+ case XATTR_USER:
+ cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
+ if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
+ (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
+ rc = cifs_attrib_get(dentry, inode, value, size);
+ break;
+ } else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
+ (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
+ rc = cifs_creation_time_get(dentry, inode, value, size);
+ break;
+ }
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ goto out;
+
+ if (pTcon->ses->server->ops->query_all_EAs)
+ rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
+ full_path, name, value, size, cifs_sb);
+ break;
+
+ case XATTR_CIFS_ACL:
+ case XATTR_CIFS_NTSD:
+ case XATTR_CIFS_NTSD_FULL: {
+ /*
+ * fetch owner, DACL, and SACL if asked for full descriptor,
+ * fetch owner and DACL otherwise
+ */
+ u32 acllen, extra_info;
+ struct cifs_ntsd *pacl;
+
+ if (pTcon->ses->server->ops->get_acl == NULL)
+ goto out; /* rc already EOPNOTSUPP */
+
+ if (handler->flags == XATTR_CIFS_NTSD_FULL) {
+ extra_info = SACL_SECINFO;
+ } else {
+ extra_info = 0;
+ }
+ pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
+ inode, full_path, &acllen, extra_info);
+ if (IS_ERR(pacl)) {
+ rc = PTR_ERR(pacl);
+ cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
+ __func__, rc);
+ } else {
+ if (value) {
+ if (acllen > size)
+ acllen = -ERANGE;
+ else
+ memcpy(value, pacl, acllen);
+ }
+ rc = acllen;
+ kfree(pacl);
+ }
+ break;
+ }
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ case XATTR_ACL_ACCESS:
+#ifdef CONFIG_CIFS_POSIX
+ if (sb->s_flags & SB_POSIXACL)
+ rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
+ value, size, ACL_TYPE_ACCESS,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+#endif /* CONFIG_CIFS_POSIX */
+ break;
+
+ case XATTR_ACL_DEFAULT:
+#ifdef CONFIG_CIFS_POSIX
+ if (sb->s_flags & SB_POSIXACL)
+ rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
+ value, size, ACL_TYPE_DEFAULT,
+ cifs_sb->local_nls,
+ cifs_remap(cifs_sb));
+#endif /* CONFIG_CIFS_POSIX */
+ break;
+#endif /* ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+ }
+
+ /* We could add an additional check for streams ie
+ if proc/fs/cifs/streamstoxattr is set then
+ search server for EAs or streams to
+ returns as xattrs */
+
+ if (rc == -EINVAL)
+ rc = -EOPNOTSUPP;
+
+out:
+ free_dentry_path(page);
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
+{
+ ssize_t rc = -EOPNOTSUPP;
+ unsigned int xid;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+ struct tcon_link *tlink;
+ struct cifs_tcon *pTcon;
+ const char *full_path;
+ void *page;
+
+ if (unlikely(cifs_forced_shutdown(cifs_sb)))
+ return -EIO;
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ return -EOPNOTSUPP;
+
+ tlink = cifs_sb_tlink(cifs_sb);
+ if (IS_ERR(tlink))
+ return PTR_ERR(tlink);
+ pTcon = tlink_tcon(tlink);
+
+ xid = get_xid();
+ page = alloc_dentry_path();
+
+ full_path = build_path_from_dentry(direntry, page);
+ if (IS_ERR(full_path)) {
+ rc = PTR_ERR(full_path);
+ goto list_ea_exit;
+ }
+ /* return dos attributes as pseudo xattr */
+ /* return alt name if available as pseudo attr */
+
+ /* if proc/fs/cifs/streamstoxattr is set then
+ search server for EAs or streams to
+ returns as xattrs */
+
+ if (pTcon->ses->server->ops->query_all_EAs)
+ rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
+ full_path, NULL, data, buf_size, cifs_sb);
+list_ea_exit:
+ free_dentry_path(page);
+ free_xid(xid);
+ cifs_put_tlink(tlink);
+ return rc;
+}
+
+static const struct xattr_handler cifs_user_xattr_handler = {
+ .prefix = XATTR_USER_PREFIX,
+ .flags = XATTR_USER,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+/* os2.* attributes are treated like user.* attributes */
+static const struct xattr_handler cifs_os2_xattr_handler = {
+ .prefix = XATTR_OS2_PREFIX,
+ .flags = XATTR_USER,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+static const struct xattr_handler cifs_cifs_acl_xattr_handler = {
+ .name = CIFS_XATTR_CIFS_ACL,
+ .flags = XATTR_CIFS_ACL,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+/*
+ * Although this is just an alias for the above, need to move away from
+ * confusing users and using the 20 year old term 'cifs' when it is no
+ * longer secure and was replaced by SMB2/SMB3 a long time ago, and
+ * SMB3 and later are highly secure.
+ */
+static const struct xattr_handler smb3_acl_xattr_handler = {
+ .name = SMB3_XATTR_CIFS_ACL,
+ .flags = XATTR_CIFS_ACL,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+static const struct xattr_handler cifs_cifs_ntsd_xattr_handler = {
+ .name = CIFS_XATTR_CIFS_NTSD,
+ .flags = XATTR_CIFS_NTSD,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+/*
+ * Although this is just an alias for the above, need to move away from
+ * confusing users and using the 20 year old term 'cifs' when it is no
+ * longer secure and was replaced by SMB2/SMB3 a long time ago, and
+ * SMB3 and later are highly secure.
+ */
+static const struct xattr_handler smb3_ntsd_xattr_handler = {
+ .name = SMB3_XATTR_CIFS_NTSD,
+ .flags = XATTR_CIFS_NTSD,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+static const struct xattr_handler cifs_cifs_ntsd_full_xattr_handler = {
+ .name = CIFS_XATTR_CIFS_NTSD_FULL,
+ .flags = XATTR_CIFS_NTSD_FULL,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+/*
+ * Although this is just an alias for the above, need to move away from
+ * confusing users and using the 20 year old term 'cifs' when it is no
+ * longer secure and was replaced by SMB2/SMB3 a long time ago, and
+ * SMB3 and later are highly secure.
+ */
+static const struct xattr_handler smb3_ntsd_full_xattr_handler = {
+ .name = SMB3_XATTR_CIFS_NTSD_FULL,
+ .flags = XATTR_CIFS_NTSD_FULL,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+
+static const struct xattr_handler cifs_posix_acl_access_xattr_handler = {
+ .name = XATTR_NAME_POSIX_ACL_ACCESS,
+ .flags = XATTR_ACL_ACCESS,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+static const struct xattr_handler cifs_posix_acl_default_xattr_handler = {
+ .name = XATTR_NAME_POSIX_ACL_DEFAULT,
+ .flags = XATTR_ACL_DEFAULT,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
+const struct xattr_handler *cifs_xattr_handlers[] = {
+ &cifs_user_xattr_handler,
+ &cifs_os2_xattr_handler,
+ &cifs_cifs_acl_xattr_handler,
+ &smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */
+ &cifs_cifs_ntsd_xattr_handler,
+ &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */
+ &cifs_cifs_ntsd_full_xattr_handler,
+ &smb3_ntsd_full_xattr_handler, /* alias for above since avoiding "cifs" */
+ &cifs_posix_acl_access_xattr_handler,
+ &cifs_posix_acl_default_xattr_handler,
+ NULL
+};
diff --git a/fs/smb/common/Makefile b/fs/smb/common/Makefile
new file mode 100644
index 000000000000..c66dbbc1469c
--- /dev/null
+++ b/fs/smb/common/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for Linux filesystem routines that are shared by client and server.
+#
+
+obj-$(CONFIG_SMBFS) += cifs_arc4.o
+obj-$(CONFIG_SMBFS) += cifs_md4.o
diff --git a/fs/smb/common/arc4.h b/fs/smb/common/arc4.h
new file mode 100644
index 000000000000..12e71ec033a1
--- /dev/null
+++ b/fs/smb/common/arc4.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Common values for ARC4 Cipher Algorithm
+ */
+
+#ifndef _CRYPTO_ARC4_H
+#define _CRYPTO_ARC4_H
+
+#include <linux/types.h>
+
+#define ARC4_MIN_KEY_SIZE 1
+#define ARC4_MAX_KEY_SIZE 256
+#define ARC4_BLOCK_SIZE 1
+
+struct arc4_ctx {
+ u32 S[256];
+ u32 x, y;
+};
+
+int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len);
+void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len);
+
+#endif /* _CRYPTO_ARC4_H */
diff --git a/fs/smb/common/cifs_arc4.c b/fs/smb/common/cifs_arc4.c
new file mode 100644
index 000000000000..043e4cb839fa
--- /dev/null
+++ b/fs/smb/common/cifs_arc4.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Cryptographic API
+ *
+ * ARC4 Cipher Algorithm
+ *
+ * Jon Oberheide <jon@oberheide.org>
+ */
+
+#include <linux/module.h>
+#include "arc4.h"
+
+MODULE_LICENSE("GPL");
+
+int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len)
+{
+ int i, j = 0, k = 0;
+
+ ctx->x = 1;
+ ctx->y = 0;
+
+ for (i = 0; i < 256; i++)
+ ctx->S[i] = i;
+
+ for (i = 0; i < 256; i++) {
+ u32 a = ctx->S[i];
+
+ j = (j + in_key[k] + a) & 0xff;
+ ctx->S[i] = ctx->S[j];
+ ctx->S[j] = a;
+ if (++k >= key_len)
+ k = 0;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_arc4_setkey);
+
+void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len)
+{
+ u32 *const S = ctx->S;
+ u32 x, y, a, b;
+ u32 ty, ta, tb;
+
+ if (len == 0)
+ return;
+
+ x = ctx->x;
+ y = ctx->y;
+
+ a = S[x];
+ y = (y + a) & 0xff;
+ b = S[y];
+
+ do {
+ S[y] = a;
+ a = (a + b) & 0xff;
+ S[x] = b;
+ x = (x + 1) & 0xff;
+ ta = S[x];
+ ty = (y + ta) & 0xff;
+ tb = S[ty];
+ *out++ = *in++ ^ S[a];
+ if (--len == 0)
+ break;
+ y = ty;
+ a = ta;
+ b = tb;
+ } while (true);
+
+ ctx->x = x;
+ ctx->y = y;
+}
+EXPORT_SYMBOL_GPL(cifs_arc4_crypt);
diff --git a/fs/smb/common/cifs_md4.c b/fs/smb/common/cifs_md4.c
new file mode 100644
index 000000000000..50f78cfc6ce9
--- /dev/null
+++ b/fs/smb/common/cifs_md4.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cryptographic API.
+ *
+ * MD4 Message Digest Algorithm (RFC1320).
+ *
+ * Implementation derived from Andrew Tridgell and Steve French's
+ * CIFS MD4 implementation, and the cryptoapi implementation
+ * originally based on the public domain implementation written
+ * by Colin Plumb in 1993.
+ *
+ * Copyright (c) Andrew Tridgell 1997-1998.
+ * Modified by Steve French (sfrench@us.ibm.com) 2002
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include "md4.h"
+
+MODULE_LICENSE("GPL");
+
+static inline u32 lshift(u32 x, unsigned int s)
+{
+ x &= 0xFFFFFFFF;
+ return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
+}
+
+static inline u32 F(u32 x, u32 y, u32 z)
+{
+ return (x & y) | ((~x) & z);
+}
+
+static inline u32 G(u32 x, u32 y, u32 z)
+{
+ return (x & y) | (x & z) | (y & z);
+}
+
+static inline u32 H(u32 x, u32 y, u32 z)
+{
+ return x ^ y ^ z;
+}
+
+#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
+#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s))
+#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s))
+
+static void md4_transform(u32 *hash, u32 const *in)
+{
+ u32 a, b, c, d;
+
+ a = hash[0];
+ b = hash[1];
+ c = hash[2];
+ d = hash[3];
+
+ ROUND1(a, b, c, d, in[0], 3);
+ ROUND1(d, a, b, c, in[1], 7);
+ ROUND1(c, d, a, b, in[2], 11);
+ ROUND1(b, c, d, a, in[3], 19);
+ ROUND1(a, b, c, d, in[4], 3);
+ ROUND1(d, a, b, c, in[5], 7);
+ ROUND1(c, d, a, b, in[6], 11);
+ ROUND1(b, c, d, a, in[7], 19);
+ ROUND1(a, b, c, d, in[8], 3);
+ ROUND1(d, a, b, c, in[9], 7);
+ ROUND1(c, d, a, b, in[10], 11);
+ ROUND1(b, c, d, a, in[11], 19);
+ ROUND1(a, b, c, d, in[12], 3);
+ ROUND1(d, a, b, c, in[13], 7);
+ ROUND1(c, d, a, b, in[14], 11);
+ ROUND1(b, c, d, a, in[15], 19);
+
+ ROUND2(a, b, c, d, in[0], 3);
+ ROUND2(d, a, b, c, in[4], 5);
+ ROUND2(c, d, a, b, in[8], 9);
+ ROUND2(b, c, d, a, in[12], 13);
+ ROUND2(a, b, c, d, in[1], 3);
+ ROUND2(d, a, b, c, in[5], 5);
+ ROUND2(c, d, a, b, in[9], 9);
+ ROUND2(b, c, d, a, in[13], 13);
+ ROUND2(a, b, c, d, in[2], 3);
+ ROUND2(d, a, b, c, in[6], 5);
+ ROUND2(c, d, a, b, in[10], 9);
+ ROUND2(b, c, d, a, in[14], 13);
+ ROUND2(a, b, c, d, in[3], 3);
+ ROUND2(d, a, b, c, in[7], 5);
+ ROUND2(c, d, a, b, in[11], 9);
+ ROUND2(b, c, d, a, in[15], 13);
+
+ ROUND3(a, b, c, d, in[0], 3);
+ ROUND3(d, a, b, c, in[8], 9);
+ ROUND3(c, d, a, b, in[4], 11);
+ ROUND3(b, c, d, a, in[12], 15);
+ ROUND3(a, b, c, d, in[2], 3);
+ ROUND3(d, a, b, c, in[10], 9);
+ ROUND3(c, d, a, b, in[6], 11);
+ ROUND3(b, c, d, a, in[14], 15);
+ ROUND3(a, b, c, d, in[1], 3);
+ ROUND3(d, a, b, c, in[9], 9);
+ ROUND3(c, d, a, b, in[5], 11);
+ ROUND3(b, c, d, a, in[13], 15);
+ ROUND3(a, b, c, d, in[3], 3);
+ ROUND3(d, a, b, c, in[11], 9);
+ ROUND3(c, d, a, b, in[7], 11);
+ ROUND3(b, c, d, a, in[15], 15);
+
+ hash[0] += a;
+ hash[1] += b;
+ hash[2] += c;
+ hash[3] += d;
+}
+
+static inline void md4_transform_helper(struct md4_ctx *ctx)
+{
+ le32_to_cpu_array(ctx->block, ARRAY_SIZE(ctx->block));
+ md4_transform(ctx->hash, ctx->block);
+}
+
+int cifs_md4_init(struct md4_ctx *mctx)
+{
+ memset(mctx, 0, sizeof(struct md4_ctx));
+ mctx->hash[0] = 0x67452301;
+ mctx->hash[1] = 0xefcdab89;
+ mctx->hash[2] = 0x98badcfe;
+ mctx->hash[3] = 0x10325476;
+ mctx->byte_count = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_md4_init);
+
+int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len)
+{
+ const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
+
+ mctx->byte_count += len;
+
+ if (avail > len) {
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, len);
+ return 0;
+ }
+
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, avail);
+
+ md4_transform_helper(mctx);
+ data += avail;
+ len -= avail;
+
+ while (len >= sizeof(mctx->block)) {
+ memcpy(mctx->block, data, sizeof(mctx->block));
+ md4_transform_helper(mctx);
+ data += sizeof(mctx->block);
+ len -= sizeof(mctx->block);
+ }
+
+ memcpy(mctx->block, data, len);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_md4_update);
+
+int cifs_md4_final(struct md4_ctx *mctx, u8 *out)
+{
+ const unsigned int offset = mctx->byte_count & 0x3f;
+ char *p = (char *)mctx->block + offset;
+ int padding = 56 - (offset + 1);
+
+ *p++ = 0x80;
+ if (padding < 0) {
+ memset(p, 0x00, padding + sizeof(u64));
+ md4_transform_helper(mctx);
+ p = (char *)mctx->block;
+ padding = 56;
+ }
+
+ memset(p, 0, padding);
+ mctx->block[14] = mctx->byte_count << 3;
+ mctx->block[15] = mctx->byte_count >> 29;
+ le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
+ sizeof(u64)) / sizeof(u32));
+ md4_transform(mctx->hash, mctx->block);
+ cpu_to_le32_array(mctx->hash, ARRAY_SIZE(mctx->hash));
+ memcpy(out, mctx->hash, sizeof(mctx->hash));
+ memset(mctx, 0, sizeof(*mctx));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cifs_md4_final);
diff --git a/fs/smb/common/md4.h b/fs/smb/common/md4.h
new file mode 100644
index 000000000000..5337becc699a
--- /dev/null
+++ b/fs/smb/common/md4.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Common values for ARC4 Cipher Algorithm
+ */
+
+#ifndef _CIFS_MD4_H
+#define _CIFS_MD4_H
+
+#include <linux/types.h>
+
+#define MD4_DIGEST_SIZE 16
+#define MD4_HMAC_BLOCK_SIZE 64
+#define MD4_BLOCK_WORDS 16
+#define MD4_HASH_WORDS 4
+
+struct md4_ctx {
+ u32 hash[MD4_HASH_WORDS];
+ u32 block[MD4_BLOCK_WORDS];
+ u64 byte_count;
+};
+
+
+int cifs_md4_init(struct md4_ctx *mctx);
+int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len);
+int cifs_md4_final(struct md4_ctx *mctx, u8 *out);
+
+#endif /* _CIFS_MD4_H */
diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h
new file mode 100644
index 000000000000..7d605db3bb3b
--- /dev/null
+++ b/fs/smb/common/smb2pdu.h
@@ -0,0 +1,1702 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+#ifndef _COMMON_SMB2PDU_H
+#define _COMMON_SMB2PDU_H
+
+/*
+ * Note that, due to trying to use names similar to the protocol specifications,
+ * there are many mixed case field names in the structures below. Although
+ * this does not match typical Linux kernel style, it is necessary to be
+ * able to match against the protocol specfication.
+ *
+ * SMB2 commands
+ * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
+ * (ie no useful data other than the SMB error code itself) and are marked such.
+ * Knowing this helps avoid response buffer allocations and copy in some cases.
+ */
+
+/* List of commands in host endian */
+#define SMB2_NEGOTIATE_HE 0x0000
+#define SMB2_SESSION_SETUP_HE 0x0001
+#define SMB2_LOGOFF_HE 0x0002 /* trivial request/resp */
+#define SMB2_TREE_CONNECT_HE 0x0003
+#define SMB2_TREE_DISCONNECT_HE 0x0004 /* trivial req/resp */
+#define SMB2_CREATE_HE 0x0005
+#define SMB2_CLOSE_HE 0x0006
+#define SMB2_FLUSH_HE 0x0007 /* trivial resp */
+#define SMB2_READ_HE 0x0008
+#define SMB2_WRITE_HE 0x0009
+#define SMB2_LOCK_HE 0x000A
+#define SMB2_IOCTL_HE 0x000B
+#define SMB2_CANCEL_HE 0x000C
+#define SMB2_ECHO_HE 0x000D
+#define SMB2_QUERY_DIRECTORY_HE 0x000E
+#define SMB2_CHANGE_NOTIFY_HE 0x000F
+#define SMB2_QUERY_INFO_HE 0x0010
+#define SMB2_SET_INFO_HE 0x0011
+#define SMB2_OPLOCK_BREAK_HE 0x0012
+
+/* The same list in little endian */
+#define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE)
+#define SMB2_SESSION_SETUP cpu_to_le16(SMB2_SESSION_SETUP_HE)
+#define SMB2_LOGOFF cpu_to_le16(SMB2_LOGOFF_HE)
+#define SMB2_TREE_CONNECT cpu_to_le16(SMB2_TREE_CONNECT_HE)
+#define SMB2_TREE_DISCONNECT cpu_to_le16(SMB2_TREE_DISCONNECT_HE)
+#define SMB2_CREATE cpu_to_le16(SMB2_CREATE_HE)
+#define SMB2_CLOSE cpu_to_le16(SMB2_CLOSE_HE)
+#define SMB2_FLUSH cpu_to_le16(SMB2_FLUSH_HE)
+#define SMB2_READ cpu_to_le16(SMB2_READ_HE)
+#define SMB2_WRITE cpu_to_le16(SMB2_WRITE_HE)
+#define SMB2_LOCK cpu_to_le16(SMB2_LOCK_HE)
+#define SMB2_IOCTL cpu_to_le16(SMB2_IOCTL_HE)
+#define SMB2_CANCEL cpu_to_le16(SMB2_CANCEL_HE)
+#define SMB2_ECHO cpu_to_le16(SMB2_ECHO_HE)
+#define SMB2_QUERY_DIRECTORY cpu_to_le16(SMB2_QUERY_DIRECTORY_HE)
+#define SMB2_CHANGE_NOTIFY cpu_to_le16(SMB2_CHANGE_NOTIFY_HE)
+#define SMB2_QUERY_INFO cpu_to_le16(SMB2_QUERY_INFO_HE)
+#define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE)
+#define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE)
+
+#define SMB2_INTERNAL_CMD cpu_to_le16(0xFFFF)
+
+#define NUMBER_OF_SMB2_COMMANDS 0x0013
+
+/*
+ * Size of the session key (crypto key encrypted with the password
+ */
+#define SMB2_NTLMV2_SESSKEY_SIZE 16
+#define SMB2_SIGNATURE_SIZE 16
+#define SMB2_HMACSHA256_SIZE 32
+#define SMB2_CMACAES_SIZE 16
+#define SMB3_GCM128_CRYPTKEY_SIZE 16
+#define SMB3_GCM256_CRYPTKEY_SIZE 32
+
+/*
+ * Size of the smb3 encryption/decryption keys
+ * This size is big enough to store any cipher key types.
+ */
+#define SMB3_ENC_DEC_KEY_SIZE 32
+
+/*
+ * Size of the smb3 signing key
+ */
+#define SMB3_SIGN_KEY_SIZE 16
+
+#define CIFS_CLIENT_CHALLENGE_SIZE 8
+
+/* Maximum buffer size value we can send with 1 credit */
+#define SMB2_MAX_BUFFER_SIZE 65536
+
+/*
+ * The default wsize is 1M for SMB2 (and for some CIFS cases).
+ * find_get_pages seems to return a maximum of 256
+ * pages in a single call. With PAGE_SIZE == 4k, this means we can
+ * fill a single wsize request with a single call.
+ */
+#define SMB3_DEFAULT_IOSIZE (4 * 1024 * 1024)
+
+/*
+ * SMB2 Header Definition
+ *
+ * "MBZ" : Must be Zero
+ * "BB" : BugBug, Something to check/review/analyze later
+ * "PDU" : "Protocol Data Unit" (ie a network "frame")
+ *
+ */
+
+#define __SMB2_HEADER_STRUCTURE_SIZE 64
+#define SMB2_HEADER_STRUCTURE_SIZE \
+ cpu_to_le16(__SMB2_HEADER_STRUCTURE_SIZE)
+
+#define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe)
+#define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
+#define SMB2_COMPRESSION_TRANSFORM_ID cpu_to_le32(0x424d53fc)
+
+/*
+ * SMB2 flag definitions
+ */
+#define SMB2_FLAGS_SERVER_TO_REDIR cpu_to_le32(0x00000001)
+#define SMB2_FLAGS_ASYNC_COMMAND cpu_to_le32(0x00000002)
+#define SMB2_FLAGS_RELATED_OPERATIONS cpu_to_le32(0x00000004)
+#define SMB2_FLAGS_SIGNED cpu_to_le32(0x00000008)
+#define SMB2_FLAGS_PRIORITY_MASK cpu_to_le32(0x00000070) /* SMB3.1.1 */
+#define SMB2_FLAGS_DFS_OPERATIONS cpu_to_le32(0x10000000)
+#define SMB2_FLAGS_REPLAY_OPERATION cpu_to_le32(0x20000000) /* SMB3 & up */
+
+/*
+ * Definitions for SMB2 Protocol Data Units (network frames)
+ *
+ * See MS-SMB2.PDF specification for protocol details.
+ * The Naming convention is the lower case version of the SMB2
+ * command code name for the struct. Note that structures must be packed.
+ *
+ */
+
+/* See MS-SMB2 section 2.2.1 */
+struct smb2_hdr {
+ __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */
+ __le16 StructureSize; /* 64 */
+ __le16 CreditCharge; /* MBZ */
+ __le32 Status; /* Error from server */
+ __le16 Command;
+ __le16 CreditRequest; /* CreditResponse */
+ __le32 Flags;
+ __le32 NextCommand;
+ __le64 MessageId;
+ union {
+ struct {
+ __le32 ProcessId;
+ __le32 TreeId;
+ } __packed SyncId;
+ __le64 AsyncId;
+ } __packed Id;
+ __le64 SessionId;
+ __u8 Signature[16];
+} __packed;
+
+struct smb2_pdu {
+ struct smb2_hdr hdr;
+ __le16 StructureSize2; /* size of wct area (varies, request specific) */
+} __packed;
+
+#define SMB2_ERROR_STRUCTURE_SIZE2 9
+#define SMB2_ERROR_STRUCTURE_SIZE2_LE cpu_to_le16(SMB2_ERROR_STRUCTURE_SIZE2)
+
+struct smb2_err_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize;
+ __u8 ErrorContextCount;
+ __u8 Reserved;
+ __le32 ByteCount; /* even if zero, at least one byte follows */
+ __u8 ErrorData[1]; /* variable length */
+} __packed;
+
+#define SMB3_AES_CCM_NONCE 11
+#define SMB3_AES_GCM_NONCE 12
+
+/* Transform flags (for 3.0 dialect this flag indicates CCM */
+#define TRANSFORM_FLAG_ENCRYPTED 0x0001
+struct smb2_transform_hdr {
+ __le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */
+ __u8 Signature[16];
+ __u8 Nonce[16];
+ __le32 OriginalMessageSize;
+ __u16 Reserved1;
+ __le16 Flags; /* EncryptionAlgorithm for 3.0, enc enabled for 3.1.1 */
+ __le64 SessionId;
+} __packed;
+
+
+/* See MS-SMB2 2.2.42 */
+struct smb2_compression_transform_hdr_unchained {
+ __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */
+ __le32 OriginalCompressedSegmentSize;
+ __le16 CompressionAlgorithm;
+ __le16 Flags;
+ __le16 Length; /* if chained it is length, else offset */
+} __packed;
+
+/* See MS-SMB2 2.2.42.1 */
+#define SMB2_COMPRESSION_FLAG_NONE 0x0000
+#define SMB2_COMPRESSION_FLAG_CHAINED 0x0001
+
+struct compression_payload_header {
+ __le16 CompressionAlgorithm;
+ __le16 Flags;
+ __le32 Length; /* length of compressed playload including field below if present */
+ /* __le32 OriginalPayloadSize; */ /* optional, present when LZNT1, LZ77, LZ77+Huffman */
+} __packed;
+
+/* See MS-SMB2 2.2.42.2 */
+struct smb2_compression_transform_hdr_chained {
+ __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */
+ __le32 OriginalCompressedSegmentSize;
+ /* struct compression_payload_header[] */
+} __packed;
+
+/* See MS-SMB2 2.2.42.2.2 */
+struct compression_pattern_payload_v1 {
+ __le16 Pattern;
+ __le16 Reserved1;
+ __le16 Reserved2;
+ __le32 Repetitions;
+} __packed;
+
+/* See MS-SMB2 section 2.2.9.2 */
+/* Context Types */
+#define SMB2_RESERVED_TREE_CONNECT_CONTEXT_ID 0x0000
+#define SMB2_REMOTED_IDENTITY_TREE_CONNECT_CONTEXT_ID cpu_to_le16(0x0001)
+
+struct tree_connect_contexts {
+ __le16 ContextType;
+ __le16 DataLength;
+ __le32 Reserved;
+ __u8 Data[];
+} __packed;
+
+/* Remoted identity tree connect context structures - see MS-SMB2 2.2.9.2.1 */
+struct smb3_blob_data {
+ __le16 BlobSize;
+ __u8 BlobData[];
+} __packed;
+
+/* Valid values for Attr */
+#define SE_GROUP_MANDATORY 0x00000001
+#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002
+#define SE_GROUP_ENABLED 0x00000004
+#define SE_GROUP_OWNER 0x00000008
+#define SE_GROUP_USE_FOR_DENY_ONLY 0x00000010
+#define SE_GROUP_INTEGRITY 0x00000020
+#define SE_GROUP_INTEGRITY_ENABLED 0x00000040
+#define SE_GROUP_RESOURCE 0x20000000
+#define SE_GROUP_LOGON_ID 0xC0000000
+
+/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */
+
+struct sid_array_data {
+ __le16 SidAttrCount;
+ /* SidAttrList - array of sid_attr_data structs */
+} __packed;
+
+struct luid_attr_data {
+
+} __packed;
+
+/*
+ * struct privilege_data is the same as BLOB_DATA - see MS-SMB2 2.2.9.2.1.5
+ * but with size of LUID_ATTR_DATA struct and BlobData set to LUID_ATTR DATA
+ */
+
+struct privilege_array_data {
+ __le16 PrivilegeCount;
+ /* array of privilege_data structs */
+} __packed;
+
+struct remoted_identity_tcon_context {
+ __le16 TicketType; /* must be 0x0001 */
+ __le16 TicketSize; /* total size of this struct */
+ __le16 User; /* offset to SID_ATTR_DATA struct with user info */
+ __le16 UserName; /* offset to null terminated Unicode username string */
+ __le16 Domain; /* offset to null terminated Unicode domain name */
+ __le16 Groups; /* offset to SID_ARRAY_DATA struct with group info */
+ __le16 RestrictedGroups; /* similar to above */
+ __le16 Privileges; /* offset to PRIVILEGE_ARRAY_DATA struct */
+ __le16 PrimaryGroup; /* offset to SID_ARRAY_DATA struct */
+ __le16 Owner; /* offset to BLOB_DATA struct */
+ __le16 DefaultDacl; /* offset to BLOB_DATA struct */
+ __le16 DeviceGroups; /* offset to SID_ARRAY_DATA struct */
+ __le16 UserClaims; /* offset to BLOB_DATA struct */
+ __le16 DeviceClaims; /* offset to BLOB_DATA struct */
+ __u8 TicketInfo[]; /* variable length buf - remoted identity data */
+} __packed;
+
+struct smb2_tree_connect_req_extension {
+ __le32 TreeConnectContextOffset;
+ __le16 TreeConnectContextCount;
+ __u8 Reserved[10];
+ __u8 PathName[]; /* variable sized array */
+ /* followed by array of TreeConnectContexts */
+} __packed;
+
+/* Flags/Reserved for SMB3.1.1 */
+#define SMB2_TREE_CONNECT_FLAG_CLUSTER_RECONNECT cpu_to_le16(0x0001)
+#define SMB2_TREE_CONNECT_FLAG_REDIRECT_TO_OWNER cpu_to_le16(0x0002)
+#define SMB2_TREE_CONNECT_FLAG_EXTENSION_PRESENT cpu_to_le16(0x0004)
+
+struct smb2_tree_connect_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 9 */
+ __le16 Flags; /* Flags in SMB3.1.1 */
+ __le16 PathOffset;
+ __le16 PathLength;
+ __u8 Buffer[1]; /* variable length */
+} __packed;
+
+/* Possible ShareType values */
+#define SMB2_SHARE_TYPE_DISK 0x01
+#define SMB2_SHARE_TYPE_PIPE 0x02
+#define SMB2_SHARE_TYPE_PRINT 0x03
+
+/*
+ * Possible ShareFlags - exactly one and only one of the first 4 caching flags
+ * must be set (any of the remaining, SHI1005, flags may be set individually
+ * or in combination.
+ */
+#define SMB2_SHAREFLAG_MANUAL_CACHING 0x00000000
+#define SMB2_SHAREFLAG_AUTO_CACHING 0x00000010
+#define SMB2_SHAREFLAG_VDO_CACHING 0x00000020
+#define SMB2_SHAREFLAG_NO_CACHING 0x00000030
+#define SHI1005_FLAGS_DFS 0x00000001
+#define SHI1005_FLAGS_DFS_ROOT 0x00000002
+#define SHI1005_FLAGS_RESTRICT_EXCLUSIVE_OPENS 0x00000100
+#define SHI1005_FLAGS_FORCE_SHARED_DELETE 0x00000200
+#define SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING 0x00000400
+#define SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM 0x00000800
+#define SHI1005_FLAGS_FORCE_LEVELII_OPLOCK 0x00001000
+#define SHI1005_FLAGS_ENABLE_HASH_V1 0x00002000
+#define SHI1005_FLAGS_ENABLE_HASH_V2 0x00004000
+#define SHI1005_FLAGS_ENCRYPT_DATA 0x00008000
+#define SMB2_SHAREFLAG_IDENTITY_REMOTING 0x00040000 /* 3.1.1 */
+#define SMB2_SHAREFLAG_COMPRESS_DATA 0x00100000 /* 3.1.1 */
+#define SHI1005_FLAGS_ALL 0x0014FF33
+
+/* Possible share capabilities */
+#define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008) /* all dialects */
+#define SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY cpu_to_le32(0x00000010) /* 3.0 */
+#define SMB2_SHARE_CAP_SCALEOUT cpu_to_le32(0x00000020) /* 3.0 */
+#define SMB2_SHARE_CAP_CLUSTER cpu_to_le32(0x00000040) /* 3.0 */
+#define SMB2_SHARE_CAP_ASYMMETRIC cpu_to_le32(0x00000080) /* 3.02 */
+#define SMB2_SHARE_CAP_REDIRECT_TO_OWNER cpu_to_le32(0x00000100) /* 3.1.1 */
+
+struct smb2_tree_connect_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 16 */
+ __u8 ShareType; /* see below */
+ __u8 Reserved;
+ __le32 ShareFlags; /* see below */
+ __le32 Capabilities; /* see below */
+ __le32 MaximalAccess;
+} __packed;
+
+struct smb2_tree_disconnect_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 4 */
+ __le16 Reserved;
+} __packed;
+
+struct smb2_tree_disconnect_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 4 */
+ __le16 Reserved;
+} __packed;
+
+
+/*
+ * SMB2_NEGOTIATE_PROTOCOL See MS-SMB2 section 2.2.3
+ */
+/* SecurityMode flags */
+#define SMB2_NEGOTIATE_SIGNING_ENABLED 0x0001
+#define SMB2_NEGOTIATE_SIGNING_ENABLED_LE cpu_to_le16(0x0001)
+#define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x0002
+#define SMB2_NEGOTIATE_SIGNING_REQUIRED_LE cpu_to_le16(0x0002)
+#define SMB2_SEC_MODE_FLAGS_ALL 0x0003
+
+/* Capabilities flags */
+#define SMB2_GLOBAL_CAP_DFS 0x00000001
+#define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */
+#define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */
+#define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x00000008 /* New to SMB3 */
+#define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */
+#define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */
+#define SMB2_GLOBAL_CAP_ENCRYPTION 0x00000040 /* New to SMB3 */
+/* Internal types */
+#define SMB2_NT_FIND 0x00100000
+#define SMB2_LARGE_FILES 0x00200000
+
+#define SMB2_CLIENT_GUID_SIZE 16
+#define SMB2_CREATE_GUID_SIZE 16
+
+/* Dialects */
+#define SMB10_PROT_ID 0x0000 /* local only, not sent on wire w/CIFS negprot */
+#define SMB20_PROT_ID 0x0202
+#define SMB21_PROT_ID 0x0210
+#define SMB2X_PROT_ID 0x02FF
+#define SMB30_PROT_ID 0x0300
+#define SMB302_PROT_ID 0x0302
+#define SMB311_PROT_ID 0x0311
+#define BAD_PROT_ID 0xFFFF
+
+#define SMB311_SALT_SIZE 32
+/* Hash Algorithm Types */
+#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001)
+#define SMB2_PREAUTH_HASH_SIZE 64
+
+/* Negotiate Contexts - ContextTypes. See MS-SMB2 section 2.2.3.1 for details */
+#define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1)
+#define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2)
+#define SMB2_COMPRESSION_CAPABILITIES cpu_to_le16(3)
+#define SMB2_NETNAME_NEGOTIATE_CONTEXT_ID cpu_to_le16(5)
+#define SMB2_TRANSPORT_CAPABILITIES cpu_to_le16(6)
+#define SMB2_RDMA_TRANSFORM_CAPABILITIES cpu_to_le16(7)
+#define SMB2_SIGNING_CAPABILITIES cpu_to_le16(8)
+#define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100)
+
+struct smb2_neg_context {
+ __le16 ContextType;
+ __le16 DataLength;
+ __le32 Reserved;
+ /* Followed by array of data. NOTE: some servers require padding to 8 byte boundary */
+} __packed;
+
+/*
+ * SaltLength that the server send can be zero, so the only three required
+ * fields (all __le16) end up six bytes total, so the minimum context data len
+ * in the response is six bytes which accounts for
+ *
+ * HashAlgorithmCount, SaltLength, and 1 HashAlgorithm.
+ */
+#define MIN_PREAUTH_CTXT_DATA_LEN 6
+
+struct smb2_preauth_neg_context {
+ __le16 ContextType; /* 1 */
+ __le16 DataLength;
+ __le32 Reserved;
+ __le16 HashAlgorithmCount; /* 1 */
+ __le16 SaltLength;
+ __le16 HashAlgorithms; /* HashAlgorithms[0] since only one defined */
+ __u8 Salt[SMB311_SALT_SIZE];
+} __packed;
+
+/* Encryption Algorithms Ciphers */
+#define SMB2_ENCRYPTION_AES128_CCM cpu_to_le16(0x0001)
+#define SMB2_ENCRYPTION_AES128_GCM cpu_to_le16(0x0002)
+#define SMB2_ENCRYPTION_AES256_CCM cpu_to_le16(0x0003)
+#define SMB2_ENCRYPTION_AES256_GCM cpu_to_le16(0x0004)
+
+/* Min encrypt context data is one cipher so 2 bytes + 2 byte count field */
+#define MIN_ENCRYPT_CTXT_DATA_LEN 4
+struct smb2_encryption_neg_context {
+ __le16 ContextType; /* 2 */
+ __le16 DataLength;
+ __le32 Reserved;
+ /* CipherCount usally 2, but can be 3 when AES256-GCM enabled */
+ __le16 CipherCount; /* AES128-GCM and AES128-CCM by default */
+ __le16 Ciphers[];
+} __packed;
+
+/* See MS-SMB2 2.2.3.1.3 */
+#define SMB3_COMPRESS_NONE cpu_to_le16(0x0000)
+#define SMB3_COMPRESS_LZNT1 cpu_to_le16(0x0001)
+#define SMB3_COMPRESS_LZ77 cpu_to_le16(0x0002)
+#define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003)
+/* Pattern scanning algorithm See MS-SMB2 3.1.4.4.1 */
+#define SMB3_COMPRESS_PATTERN cpu_to_le16(0x0004) /* Pattern_V1 */
+
+/* Compression Flags */
+#define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE cpu_to_le32(0x00000000)
+#define SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED cpu_to_le32(0x00000001)
+
+struct smb2_compression_capabilities_context {
+ __le16 ContextType; /* 3 */
+ __le16 DataLength;
+ __le32 Reserved;
+ __le16 CompressionAlgorithmCount;
+ __le16 Padding;
+ __le32 Flags;
+ __le16 CompressionAlgorithms[3];
+ __u16 Pad; /* Some servers require pad to DataLen multiple of 8 */
+ /* Check if pad needed */
+} __packed;
+
+/*
+ * For smb2_netname_negotiate_context_id See MS-SMB2 2.2.3.1.4.
+ * Its struct simply contains NetName, an array of Unicode characters
+ */
+struct smb2_netname_neg_context {
+ __le16 ContextType; /* 5 */
+ __le16 DataLength;
+ __le32 Reserved;
+ __le16 NetName[]; /* hostname of target converted to UCS-2 */
+} __packed;
+
+/*
+ * For smb2_transport_capabilities context see MS-SMB2 2.2.3.1.5
+ * and 2.2.4.1.5
+ */
+
+/* Flags */
+#define SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY 0x00000001
+
+struct smb2_transport_capabilities_context {
+ __le16 ContextType; /* 6 */
+ __le16 DataLength;
+ __u32 Reserved;
+ __le32 Flags;
+ __u32 Pad;
+} __packed;
+
+/*
+ * For rdma transform capabilities context see MS-SMB2 2.2.3.1.6
+ * and 2.2.4.1.6
+ */
+
+/* RDMA Transform IDs */
+#define SMB2_RDMA_TRANSFORM_NONE 0x0000
+#define SMB2_RDMA_TRANSFORM_ENCRYPTION 0x0001
+#define SMB2_RDMA_TRANSFORM_SIGNING 0x0002
+
+struct smb2_rdma_transform_capabilities_context {
+ __le16 ContextType; /* 7 */
+ __le16 DataLength;
+ __u32 Reserved;
+ __le16 TransformCount;
+ __u16 Reserved1;
+ __u32 Reserved2;
+ __le16 RDMATransformIds[];
+} __packed;
+
+/*
+ * For signing capabilities context see MS-SMB2 2.2.3.1.7
+ * and 2.2.4.1.7
+ */
+
+/* Signing algorithms */
+#define SIGNING_ALG_HMAC_SHA256 0
+#define SIGNING_ALG_HMAC_SHA256_LE cpu_to_le16(0)
+#define SIGNING_ALG_AES_CMAC 1
+#define SIGNING_ALG_AES_CMAC_LE cpu_to_le16(1)
+#define SIGNING_ALG_AES_GMAC 2
+#define SIGNING_ALG_AES_GMAC_LE cpu_to_le16(2)
+
+struct smb2_signing_capabilities {
+ __le16 ContextType; /* 8 */
+ __le16 DataLength;
+ __le32 Reserved;
+ __le16 SigningAlgorithmCount;
+ __le16 SigningAlgorithms[];
+ /* Followed by padding to 8 byte boundary (required by some servers) */
+} __packed;
+
+#define POSIX_CTXT_DATA_LEN 16
+struct smb2_posix_neg_context {
+ __le16 ContextType; /* 0x100 */
+ __le16 DataLength;
+ __le32 Reserved;
+ __u8 Name[16]; /* POSIX ctxt GUID 93AD25509CB411E7B42383DE968BCD7C */
+} __packed;
+
+struct smb2_negotiate_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 36 */
+ __le16 DialectCount;
+ __le16 SecurityMode;
+ __le16 Reserved; /* MBZ */
+ __le32 Capabilities;
+ __u8 ClientGUID[SMB2_CLIENT_GUID_SIZE];
+ /* In SMB3.02 and earlier next three were MBZ le64 ClientStartTime */
+ __le32 NegotiateContextOffset; /* SMB3.1.1 only. MBZ earlier */
+ __le16 NegotiateContextCount; /* SMB3.1.1 only. MBZ earlier */
+ __le16 Reserved2;
+ __le16 Dialects[];
+} __packed;
+
+struct smb2_negotiate_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 65 */
+ __le16 SecurityMode;
+ __le16 DialectRevision;
+ __le16 NegotiateContextCount; /* Prior to SMB3.1.1 was Reserved & MBZ */
+ __u8 ServerGUID[16];
+ __le32 Capabilities;
+ __le32 MaxTransactSize;
+ __le32 MaxReadSize;
+ __le32 MaxWriteSize;
+ __le64 SystemTime; /* MBZ */
+ __le64 ServerStartTime;
+ __le16 SecurityBufferOffset;
+ __le16 SecurityBufferLength;
+ __le32 NegotiateContextOffset; /* Pre:SMB3.1.1 was reserved/ignored */
+ __u8 Buffer[1]; /* variable length GSS security buffer */
+} __packed;
+
+
+/*
+ * SMB2_SESSION_SETUP See MS-SMB2 section 2.2.5
+ */
+/* Flags */
+#define SMB2_SESSION_REQ_FLAG_BINDING 0x01
+#define SMB2_SESSION_REQ_FLAG_ENCRYPT_DATA 0x04
+
+struct smb2_sess_setup_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 25 */
+ __u8 Flags;
+ __u8 SecurityMode;
+ __le32 Capabilities;
+ __le32 Channel;
+ __le16 SecurityBufferOffset;
+ __le16 SecurityBufferLength;
+ __le64 PreviousSessionId;
+ __u8 Buffer[1]; /* variable length GSS security buffer */
+} __packed;
+
+/* Currently defined SessionFlags */
+#define SMB2_SESSION_FLAG_IS_GUEST 0x0001
+#define SMB2_SESSION_FLAG_IS_GUEST_LE cpu_to_le16(0x0001)
+#define SMB2_SESSION_FLAG_IS_NULL 0x0002
+#define SMB2_SESSION_FLAG_IS_NULL_LE cpu_to_le16(0x0002)
+#define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004
+#define SMB2_SESSION_FLAG_ENCRYPT_DATA_LE cpu_to_le16(0x0004)
+
+struct smb2_sess_setup_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 9 */
+ __le16 SessionFlags;
+ __le16 SecurityBufferOffset;
+ __le16 SecurityBufferLength;
+ __u8 Buffer[1]; /* variable length GSS security buffer */
+} __packed;
+
+
+/*
+ * SMB2_LOGOFF See MS-SMB2 section 2.2.7
+ */
+struct smb2_logoff_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 4 */
+ __le16 Reserved;
+} __packed;
+
+struct smb2_logoff_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 4 */
+ __le16 Reserved;
+} __packed;
+
+
+/*
+ * SMB2_CLOSE See MS-SMB2 section 2.2.15
+ */
+/* Currently defined values for close flags */
+#define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001)
+struct smb2_close_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 24 */
+ __le16 Flags;
+ __le32 Reserved;
+ __u64 PersistentFileId; /* opaque endianness */
+ __u64 VolatileFileId; /* opaque endianness */
+} __packed;
+
+/*
+ * Maximum size of a SMB2_CLOSE response is 64 (smb2 header) + 60 (data)
+ */
+#define MAX_SMB2_CLOSE_RESPONSE_SIZE 124
+
+struct smb2_close_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* 60 */
+ __le16 Flags;
+ __le32 Reserved;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */
+ __le64 EndOfFile;
+ __le32 Attributes;
+} __packed;
+
+
+/*
+ * SMB2_READ See MS-SMB2 section 2.2.19
+ */
+/* For read request Flags field below, following flag is defined for SMB3.02 */
+#define SMB2_READFLAG_READ_UNBUFFERED 0x01
+#define SMB2_READFLAG_REQUEST_COMPRESSED 0x02 /* See MS-SMB2 2.2.19 */
+
+/* Channel field for read and write: exactly one of following flags can be set*/
+#define SMB2_CHANNEL_NONE cpu_to_le32(0x00000000)
+#define SMB2_CHANNEL_RDMA_V1 cpu_to_le32(0x00000001)
+#define SMB2_CHANNEL_RDMA_V1_INVALIDATE cpu_to_le32(0x00000002)
+#define SMB2_CHANNEL_RDMA_TRANSFORM cpu_to_le32(0x00000003)
+
+/* SMB2 read request without RFC1001 length at the beginning */
+struct smb2_read_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 49 */
+ __u8 Padding; /* offset from start of SMB2 header to place read */
+ __u8 Flags; /* MBZ unless SMB3.02 or later */
+ __le32 Length;
+ __le64 Offset;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ __le32 MinimumCount;
+ __le32 Channel; /* MBZ except for SMB3 or later */
+ __le32 RemainingBytes;
+ __le16 ReadChannelInfoOffset;
+ __le16 ReadChannelInfoLength;
+ __u8 Buffer[1];
+} __packed;
+
+/* Read flags */
+#define SMB2_READFLAG_RESPONSE_NONE cpu_to_le32(0x00000000)
+#define SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM cpu_to_le32(0x00000001)
+
+struct smb2_read_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 17 */
+ __u8 DataOffset;
+ __u8 Reserved;
+ __le32 DataLength;
+ __le32 DataRemaining;
+ __le32 Flags;
+ __u8 Buffer[1];
+} __packed;
+
+
+/*
+ * SMB2_WRITE See MS-SMB2 section 2.2.21
+ */
+/* For write request Flags field below the following flags are defined: */
+#define SMB2_WRITEFLAG_WRITE_THROUGH 0x00000001 /* SMB2.1 or later */
+#define SMB2_WRITEFLAG_WRITE_UNBUFFERED 0x00000002 /* SMB3.02 or later */
+
+struct smb2_write_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 49 */
+ __le16 DataOffset; /* offset from start of SMB2 header to write data */
+ __le32 Length;
+ __le64 Offset;
+ __u64 PersistentFileId; /* opaque endianness */
+ __u64 VolatileFileId; /* opaque endianness */
+ __le32 Channel; /* MBZ unless SMB3.02 or later */
+ __le32 RemainingBytes;
+ __le16 WriteChannelInfoOffset;
+ __le16 WriteChannelInfoLength;
+ __le32 Flags;
+ __u8 Buffer[1];
+} __packed;
+
+struct smb2_write_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 17 */
+ __u8 DataOffset;
+ __u8 Reserved;
+ __le32 DataLength;
+ __le32 DataRemaining;
+ __u32 Reserved2;
+ __u8 Buffer[1];
+} __packed;
+
+
+/*
+ * SMB2_FLUSH See MS-SMB2 section 2.2.17
+ */
+struct smb2_flush_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 24 */
+ __le16 Reserved1;
+ __le32 Reserved2;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+} __packed;
+
+struct smb2_flush_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize;
+ __le16 Reserved;
+} __packed;
+
+#define SMB2_LOCKFLAG_SHARED 0x0001
+#define SMB2_LOCKFLAG_EXCLUSIVE 0x0002
+#define SMB2_LOCKFLAG_UNLOCK 0x0004
+#define SMB2_LOCKFLAG_FAIL_IMMEDIATELY 0x0010
+#define SMB2_LOCKFLAG_MASK 0x0007
+
+struct smb2_lock_element {
+ __le64 Offset;
+ __le64 Length;
+ __le32 Flags;
+ __le32 Reserved;
+} __packed;
+
+struct smb2_lock_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 48 */
+ __le16 LockCount;
+ /*
+ * The least significant four bits are the index, the other 28 bits are
+ * the lock sequence number (0 to 64). See MS-SMB2 2.2.26
+ */
+ __le32 LockSequenceNumber;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ /* Followed by at least one */
+ struct smb2_lock_element locks[1];
+} __packed;
+
+struct smb2_lock_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 4 */
+ __le16 Reserved;
+} __packed;
+
+struct smb2_echo_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 4 */
+ __u16 Reserved;
+} __packed;
+
+struct smb2_echo_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 4 */
+ __u16 Reserved;
+} __packed;
+
+/*
+ * Valid FileInformation classes for query directory
+ *
+ * Note that these are a subset of the (file) QUERY_INFO levels defined
+ * later in this file (but since QUERY_DIRECTORY uses equivalent numbers
+ * we do not redefine them here)
+ *
+ * FileDirectoryInfomation 0x01
+ * FileFullDirectoryInformation 0x02
+ * FileIdFullDirectoryInformation 0x26
+ * FileBothDirectoryInformation 0x03
+ * FileIdBothDirectoryInformation 0x25
+ * FileNamesInformation 0x0C
+ * FileIdExtdDirectoryInformation 0x3C
+ */
+
+/* search (query_directory) Flags field */
+#define SMB2_RESTART_SCANS 0x01
+#define SMB2_RETURN_SINGLE_ENTRY 0x02
+#define SMB2_INDEX_SPECIFIED 0x04
+#define SMB2_REOPEN 0x10
+
+struct smb2_query_directory_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 33 */
+ __u8 FileInformationClass;
+ __u8 Flags;
+ __le32 FileIndex;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ __le16 FileNameOffset;
+ __le16 FileNameLength;
+ __le32 OutputBufferLength;
+ __u8 Buffer[1];
+} __packed;
+
+struct smb2_query_directory_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 9 */
+ __le16 OutputBufferOffset;
+ __le32 OutputBufferLength;
+ __u8 Buffer[1];
+} __packed;
+
+/*
+ * Maximum number of iovs we need for a set-info request.
+ * The largest one is rename/hardlink
+ * [0] : struct smb2_set_info_req + smb2_file_[rename|link]_info
+ * [1] : path
+ * [2] : compound padding
+ */
+#define SMB2_SET_INFO_IOV_SIZE 3
+
+struct smb2_set_info_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 33 */
+ __u8 InfoType;
+ __u8 FileInfoClass;
+ __le32 BufferLength;
+ __le16 BufferOffset;
+ __u16 Reserved;
+ __le32 AdditionalInformation;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ __u8 Buffer[1];
+} __packed;
+
+struct smb2_set_info_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 2 */
+} __packed;
+
+/*
+ * SMB2_NOTIFY See MS-SMB2 section 2.2.35
+ */
+/* notify flags */
+#define SMB2_WATCH_TREE 0x0001
+
+/* notify completion filter flags. See MS-FSCC 2.6 and MS-SMB2 2.2.35 */
+#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
+#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
+#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
+#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
+#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
+#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
+#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
+#define FILE_NOTIFY_CHANGE_EA 0x00000080
+#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
+#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
+#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
+#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
+
+/* SMB2 Notify Action Flags */
+#define FILE_ACTION_ADDED 0x00000001
+#define FILE_ACTION_REMOVED 0x00000002
+#define FILE_ACTION_MODIFIED 0x00000003
+#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
+#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
+#define FILE_ACTION_ADDED_STREAM 0x00000006
+#define FILE_ACTION_REMOVED_STREAM 0x00000007
+#define FILE_ACTION_MODIFIED_STREAM 0x00000008
+#define FILE_ACTION_REMOVED_BY_DELETE 0x00000009
+
+struct smb2_change_notify_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize;
+ __le16 Flags;
+ __le32 OutputBufferLength;
+ __u64 PersistentFileId; /* opaque endianness */
+ __u64 VolatileFileId; /* opaque endianness */
+ __le32 CompletionFilter;
+ __u32 Reserved;
+} __packed;
+
+struct smb2_change_notify_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 9 */
+ __le16 OutputBufferOffset;
+ __le32 OutputBufferLength;
+ __u8 Buffer[1]; /* array of file notify structs */
+} __packed;
+
+
+/*
+ * SMB2_CREATE See MS-SMB2 section 2.2.13
+ */
+/* Oplock levels */
+#define SMB2_OPLOCK_LEVEL_NONE 0x00
+#define SMB2_OPLOCK_LEVEL_II 0x01
+#define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08
+#define SMB2_OPLOCK_LEVEL_BATCH 0x09
+#define SMB2_OPLOCK_LEVEL_LEASE 0xFF
+/* Non-spec internal type */
+#define SMB2_OPLOCK_LEVEL_NOCHANGE 0x99
+
+/* Impersonation Levels. See MS-WPO section 9.7 and MSDN-IMPERS */
+#define IL_ANONYMOUS cpu_to_le32(0x00000000)
+#define IL_IDENTIFICATION cpu_to_le32(0x00000001)
+#define IL_IMPERSONATION cpu_to_le32(0x00000002)
+#define IL_DELEGATE cpu_to_le32(0x00000003)
+
+/* File Attrubutes */
+#define FILE_ATTRIBUTE_READONLY 0x00000001
+#define FILE_ATTRIBUTE_HIDDEN 0x00000002
+#define FILE_ATTRIBUTE_SYSTEM 0x00000004
+#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
+#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
+#define FILE_ATTRIBUTE_NORMAL 0x00000080
+#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
+#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
+#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
+#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
+#define FILE_ATTRIBUTE_OFFLINE 0x00001000
+#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
+#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
+#define FILE_ATTRIBUTE_INTEGRITY_STREAM 0x00008000
+#define FILE_ATTRIBUTE_NO_SCRUB_DATA 0x00020000
+#define FILE_ATTRIBUTE__MASK 0x00007FB7
+
+#define FILE_ATTRIBUTE_READONLY_LE cpu_to_le32(0x00000001)
+#define FILE_ATTRIBUTE_HIDDEN_LE cpu_to_le32(0x00000002)
+#define FILE_ATTRIBUTE_SYSTEM_LE cpu_to_le32(0x00000004)
+#define FILE_ATTRIBUTE_DIRECTORY_LE cpu_to_le32(0x00000010)
+#define FILE_ATTRIBUTE_ARCHIVE_LE cpu_to_le32(0x00000020)
+#define FILE_ATTRIBUTE_NORMAL_LE cpu_to_le32(0x00000080)
+#define FILE_ATTRIBUTE_TEMPORARY_LE cpu_to_le32(0x00000100)
+#define FILE_ATTRIBUTE_SPARSE_FILE_LE cpu_to_le32(0x00000200)
+#define FILE_ATTRIBUTE_REPARSE_POINT_LE cpu_to_le32(0x00000400)
+#define FILE_ATTRIBUTE_COMPRESSED_LE cpu_to_le32(0x00000800)
+#define FILE_ATTRIBUTE_OFFLINE_LE cpu_to_le32(0x00001000)
+#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED_LE cpu_to_le32(0x00002000)
+#define FILE_ATTRIBUTE_ENCRYPTED_LE cpu_to_le32(0x00004000)
+#define FILE_ATTRIBUTE_INTEGRITY_STREAM_LE cpu_to_le32(0x00008000)
+#define FILE_ATTRIBUTE_NO_SCRUB_DATA_LE cpu_to_le32(0x00020000)
+#define FILE_ATTRIBUTE_MASK_LE cpu_to_le32(0x00007FB7)
+
+/* Desired Access Flags */
+#define FILE_READ_DATA_LE cpu_to_le32(0x00000001)
+#define FILE_LIST_DIRECTORY_LE cpu_to_le32(0x00000001)
+#define FILE_WRITE_DATA_LE cpu_to_le32(0x00000002)
+#define FILE_APPEND_DATA_LE cpu_to_le32(0x00000004)
+#define FILE_ADD_SUBDIRECTORY_LE cpu_to_le32(0x00000004)
+#define FILE_READ_EA_LE cpu_to_le32(0x00000008)
+#define FILE_WRITE_EA_LE cpu_to_le32(0x00000010)
+#define FILE_EXECUTE_LE cpu_to_le32(0x00000020)
+#define FILE_DELETE_CHILD_LE cpu_to_le32(0x00000040)
+#define FILE_READ_ATTRIBUTES_LE cpu_to_le32(0x00000080)
+#define FILE_WRITE_ATTRIBUTES_LE cpu_to_le32(0x00000100)
+#define FILE_DELETE_LE cpu_to_le32(0x00010000)
+#define FILE_READ_CONTROL_LE cpu_to_le32(0x00020000)
+#define FILE_WRITE_DAC_LE cpu_to_le32(0x00040000)
+#define FILE_WRITE_OWNER_LE cpu_to_le32(0x00080000)
+#define FILE_SYNCHRONIZE_LE cpu_to_le32(0x00100000)
+#define FILE_ACCESS_SYSTEM_SECURITY_LE cpu_to_le32(0x01000000)
+#define FILE_MAXIMAL_ACCESS_LE cpu_to_le32(0x02000000)
+#define FILE_GENERIC_ALL_LE cpu_to_le32(0x10000000)
+#define FILE_GENERIC_EXECUTE_LE cpu_to_le32(0x20000000)
+#define FILE_GENERIC_WRITE_LE cpu_to_le32(0x40000000)
+#define FILE_GENERIC_READ_LE cpu_to_le32(0x80000000)
+#define DESIRED_ACCESS_MASK cpu_to_le32(0xF21F01FF)
+
+
+#define FILE_READ_DESIRED_ACCESS_LE (FILE_READ_DATA_LE | \
+ FILE_READ_EA_LE | \
+ FILE_GENERIC_READ_LE)
+#define FILE_WRITE_DESIRE_ACCESS_LE (FILE_WRITE_DATA_LE | \
+ FILE_APPEND_DATA_LE | \
+ FILE_WRITE_EA_LE | \
+ FILE_WRITE_ATTRIBUTES_LE | \
+ FILE_GENERIC_WRITE_LE)
+
+/* ShareAccess Flags */
+#define FILE_SHARE_READ_LE cpu_to_le32(0x00000001)
+#define FILE_SHARE_WRITE_LE cpu_to_le32(0x00000002)
+#define FILE_SHARE_DELETE_LE cpu_to_le32(0x00000004)
+#define FILE_SHARE_ALL_LE cpu_to_le32(0x00000007)
+
+/* CreateDisposition Flags */
+#define FILE_SUPERSEDE_LE cpu_to_le32(0x00000000)
+#define FILE_OPEN_LE cpu_to_le32(0x00000001)
+#define FILE_CREATE_LE cpu_to_le32(0x00000002)
+#define FILE_OPEN_IF_LE cpu_to_le32(0x00000003)
+#define FILE_OVERWRITE_LE cpu_to_le32(0x00000004)
+#define FILE_OVERWRITE_IF_LE cpu_to_le32(0x00000005)
+#define FILE_CREATE_MASK_LE cpu_to_le32(0x00000007)
+
+#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \
+ | FILE_READ_ATTRIBUTES)
+#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
+ | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
+#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
+
+/* CreateOptions Flags */
+#define FILE_DIRECTORY_FILE_LE cpu_to_le32(0x00000001)
+/* same as #define CREATE_NOT_FILE_LE cpu_to_le32(0x00000001) */
+#define FILE_WRITE_THROUGH_LE cpu_to_le32(0x00000002)
+#define FILE_SEQUENTIAL_ONLY_LE cpu_to_le32(0x00000004)
+#define FILE_NO_INTERMEDIATE_BUFFERING_LE cpu_to_le32(0x00000008)
+#define FILE_NON_DIRECTORY_FILE_LE cpu_to_le32(0x00000040)
+#define FILE_COMPLETE_IF_OPLOCKED_LE cpu_to_le32(0x00000100)
+#define FILE_NO_EA_KNOWLEDGE_LE cpu_to_le32(0x00000200)
+#define FILE_RANDOM_ACCESS_LE cpu_to_le32(0x00000800)
+#define FILE_DELETE_ON_CLOSE_LE cpu_to_le32(0x00001000)
+#define FILE_OPEN_BY_FILE_ID_LE cpu_to_le32(0x00002000)
+#define FILE_OPEN_FOR_BACKUP_INTENT_LE cpu_to_le32(0x00004000)
+#define FILE_NO_COMPRESSION_LE cpu_to_le32(0x00008000)
+#define FILE_OPEN_REPARSE_POINT_LE cpu_to_le32(0x00200000)
+#define FILE_OPEN_NO_RECALL_LE cpu_to_le32(0x00400000)
+#define CREATE_OPTIONS_MASK_LE cpu_to_le32(0x00FFFFFF)
+
+#define FILE_READ_RIGHTS_LE (FILE_READ_DATA_LE | FILE_READ_EA_LE \
+ | FILE_READ_ATTRIBUTES_LE)
+#define FILE_WRITE_RIGHTS_LE (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE \
+ | FILE_WRITE_EA_LE | FILE_WRITE_ATTRIBUTES_LE)
+#define FILE_EXEC_RIGHTS_LE (FILE_EXECUTE_LE)
+
+/* Create Context Values */
+#define SMB2_CREATE_EA_BUFFER "ExtA" /* extended attributes */
+#define SMB2_CREATE_SD_BUFFER "SecD" /* security descriptor */
+#define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ"
+#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC"
+#define SMB2_CREATE_ALLOCATION_SIZE "AISi"
+#define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
+#define SMB2_CREATE_TIMEWARP_REQUEST "TWrp"
+#define SMB2_CREATE_QUERY_ON_DISK_ID "QFid"
+#define SMB2_CREATE_REQUEST_LEASE "RqLs"
+#define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q"
+#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C"
+#define SMB2_CREATE_TAG_POSIX "\x93\xAD\x25\x50\x9C\xB4\x11\xE7\xB4\x23\x83\xDE\x96\x8B\xCD\x7C"
+#define SMB2_CREATE_APP_INSTANCE_ID "\x45\xBC\xA6\x6A\xEF\xA7\xF7\x4A\x90\x08\xFA\x46\x2E\x14\x4D\x74"
+#define SMB2_CREATE_APP_INSTANCE_VERSION "\xB9\x82\xD0\xB7\x3B\x56\x07\x4F\xA0\x7B\x52\x4A\x81\x16\xA0\x10"
+#define SVHDX_OPEN_DEVICE_CONTEXT "\x9C\xCB\xCF\x9E\x04\xC1\xE6\x43\x98\x0E\x15\x8D\xA1\xF6\xEC\x83"
+#define SMB2_CREATE_TAG_AAPL "AAPL"
+
+/* Flag (SMB3 open response) values */
+#define SMB2_CREATE_FLAG_REPARSEPOINT 0x01
+
+struct create_context {
+ __le32 Next;
+ __le16 NameOffset;
+ __le16 NameLength;
+ __le16 Reserved;
+ __le16 DataOffset;
+ __le32 DataLength;
+ __u8 Buffer[];
+} __packed;
+
+struct smb2_create_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 57 */
+ __u8 SecurityFlags;
+ __u8 RequestedOplockLevel;
+ __le32 ImpersonationLevel;
+ __le64 SmbCreateFlags;
+ __le64 Reserved;
+ __le32 DesiredAccess;
+ __le32 FileAttributes;
+ __le32 ShareAccess;
+ __le32 CreateDisposition;
+ __le32 CreateOptions;
+ __le16 NameOffset;
+ __le16 NameLength;
+ __le32 CreateContextsOffset;
+ __le32 CreateContextsLength;
+ __u8 Buffer[];
+} __packed;
+
+struct smb2_create_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 89 */
+ __u8 OplockLevel;
+ __u8 Flags; /* 0x01 if reparse point */
+ __le32 CreateAction;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 AllocationSize;
+ __le64 EndofFile;
+ __le32 FileAttributes;
+ __le32 Reserved2;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ __le32 CreateContextsOffset;
+ __le32 CreateContextsLength;
+ __u8 Buffer[1];
+} __packed;
+
+struct create_posix {
+ struct create_context ccontext;
+ __u8 Name[16];
+ __le32 Mode;
+ __u32 Reserved;
+} __packed;
+
+#define SMB2_LEASE_NONE_LE cpu_to_le32(0x00)
+#define SMB2_LEASE_READ_CACHING_LE cpu_to_le32(0x01)
+#define SMB2_LEASE_HANDLE_CACHING_LE cpu_to_le32(0x02)
+#define SMB2_LEASE_WRITE_CACHING_LE cpu_to_le32(0x04)
+
+#define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE cpu_to_le32(0x02)
+
+#define SMB2_LEASE_KEY_SIZE 16
+
+struct lease_context {
+ __u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
+ __le32 LeaseState;
+ __le32 LeaseFlags;
+ __le64 LeaseDuration;
+} __packed;
+
+struct lease_context_v2 {
+ __u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
+ __le32 LeaseState;
+ __le32 LeaseFlags;
+ __le64 LeaseDuration;
+ __u8 ParentLeaseKey[SMB2_LEASE_KEY_SIZE];
+ __le16 Epoch;
+ __le16 Reserved;
+} __packed;
+
+struct create_lease {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct lease_context lcontext;
+} __packed;
+
+struct create_lease_v2 {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct lease_context_v2 lcontext;
+ __u8 Pad[4];
+} __packed;
+
+/* See MS-SMB2 2.2.31 and 2.2.32 */
+struct smb2_ioctl_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 57 */
+ __le16 Reserved; /* offset from start of SMB2 header to write data */
+ __le32 CtlCode;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ __le32 InputOffset; /* Reserved MBZ */
+ __le32 InputCount;
+ __le32 MaxInputResponse;
+ __le32 OutputOffset;
+ __le32 OutputCount;
+ __le32 MaxOutputResponse;
+ __le32 Flags;
+ __le32 Reserved2;
+ __u8 Buffer[];
+} __packed;
+
+struct smb2_ioctl_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 49 */
+ __le16 Reserved;
+ __le32 CtlCode;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ __le32 InputOffset; /* Reserved MBZ */
+ __le32 InputCount;
+ __le32 OutputOffset;
+ __le32 OutputCount;
+ __le32 Flags;
+ __le32 Reserved2;
+ __u8 Buffer[];
+} __packed;
+
+/* this goes in the ioctl buffer when doing FSCTL_SET_ZERO_DATA */
+struct file_zero_data_information {
+ __le64 FileOffset;
+ __le64 BeyondFinalZero;
+} __packed;
+
+/* See MS-FSCC 2.3.7 */
+struct duplicate_extents_to_file {
+ __u64 PersistentFileHandle; /* source file handle, opaque endianness */
+ __u64 VolatileFileHandle;
+ __le64 SourceFileOffset;
+ __le64 TargetFileOffset;
+ __le64 ByteCount; /* Bytes to be copied */
+} __packed;
+
+/* See MS-FSCC 2.3.8 */
+#define DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC 0x00000001
+struct duplicate_extents_to_file_ex {
+ __u64 PersistentFileHandle; /* source file handle, opaque endianness */
+ __u64 VolatileFileHandle;
+ __le64 SourceFileOffset;
+ __le64 TargetFileOffset;
+ __le64 ByteCount; /* Bytes to be copied */
+ __le32 Flags;
+ __le32 Reserved;
+} __packed;
+
+
+/* See MS-FSCC 2.3.20 */
+struct fsctl_get_integrity_information_rsp {
+ __le16 ChecksumAlgorithm;
+ __le16 Reserved;
+ __le32 Flags;
+ __le32 ChecksumChunkSizeInBytes;
+ __le32 ClusterSizeInBytes;
+} __packed;
+
+/* See MS-FSCC 2.3.55 */
+struct fsctl_query_file_regions_req {
+ __le64 FileOffset;
+ __le64 Length;
+ __le32 DesiredUsage;
+ __le32 Reserved;
+} __packed;
+
+/* DesiredUsage flags see MS-FSCC 2.3.56.1 */
+#define FILE_USAGE_INVALID_RANGE 0x00000000
+#define FILE_USAGE_VALID_CACHED_DATA 0x00000001
+#define FILE_USAGE_NONCACHED_DATA 0x00000002
+
+struct file_region_info {
+ __le64 FileOffset;
+ __le64 Length;
+ __le32 DesiredUsage;
+ __le32 Reserved;
+} __packed;
+
+/* See MS-FSCC 2.3.56 */
+struct fsctl_query_file_region_rsp {
+ __le32 Flags;
+ __le32 TotalRegionEntryCount;
+ __le32 RegionEntryCount;
+ __u32 Reserved;
+ struct file_region_info Regions[];
+} __packed;
+
+/* See MS-FSCC 2.3.58 */
+struct fsctl_query_on_disk_vol_info_rsp {
+ __le64 DirectoryCount;
+ __le64 FileCount;
+ __le16 FsFormatMajVersion;
+ __le16 FsFormatMinVersion;
+ __u8 FsFormatName[24];
+ __le64 FormatTime;
+ __le64 LastUpdateTime;
+ __u8 CopyrightInfo[68];
+ __u8 AbstractInfo[68];
+ __u8 FormatImplInfo[68];
+ __u8 LastModifyImplInfo[68];
+} __packed;
+
+/* See MS-FSCC 2.3.73 */
+struct fsctl_set_integrity_information_req {
+ __le16 ChecksumAlgorithm;
+ __le16 Reserved;
+ __le32 Flags;
+} __packed;
+
+/* See MS-FSCC 2.3.75 */
+struct fsctl_set_integrity_info_ex_req {
+ __u8 EnableIntegrity;
+ __u8 KeepState;
+ __u16 Reserved;
+ __le32 Flags;
+ __u8 Version;
+ __u8 Reserved2[7];
+} __packed;
+
+/* Integrity ChecksumAlgorithm choices for above */
+#define CHECKSUM_TYPE_NONE 0x0000
+#define CHECKSUM_TYPE_CRC64 0x0002
+#define CHECKSUM_TYPE_UNCHANGED 0xFFFF /* set only */
+
+/* Integrity flags for above */
+#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001
+
+/* Reparse structures - see MS-FSCC 2.1.2 */
+
+/* struct fsctl_reparse_info_req is empty, only response structs (see below) */
+struct reparse_data_buffer {
+ __le32 ReparseTag;
+ __le16 ReparseDataLength;
+ __u16 Reserved;
+ __u8 DataBuffer[]; /* Variable Length */
+} __packed;
+
+struct reparse_guid_data_buffer {
+ __le32 ReparseTag;
+ __le16 ReparseDataLength;
+ __u16 Reserved;
+ __u8 ReparseGuid[16];
+ __u8 DataBuffer[]; /* Variable Length */
+} __packed;
+
+struct reparse_mount_point_data_buffer {
+ __le32 ReparseTag;
+ __le16 ReparseDataLength;
+ __u16 Reserved;
+ __le16 SubstituteNameOffset;
+ __le16 SubstituteNameLength;
+ __le16 PrintNameOffset;
+ __le16 PrintNameLength;
+ __u8 PathBuffer[]; /* Variable Length */
+} __packed;
+
+#define SYMLINK_FLAG_RELATIVE 0x00000001
+
+struct reparse_symlink_data_buffer {
+ __le32 ReparseTag;
+ __le16 ReparseDataLength;
+ __u16 Reserved;
+ __le16 SubstituteNameOffset;
+ __le16 SubstituteNameLength;
+ __le16 PrintNameOffset;
+ __le16 PrintNameLength;
+ __le32 Flags;
+ __u8 PathBuffer[]; /* Variable Length */
+} __packed;
+
+/* See MS-FSCC 2.1.2.6 and cifspdu.h for struct reparse_posix_data */
+
+struct validate_negotiate_info_req {
+ __le32 Capabilities;
+ __u8 Guid[SMB2_CLIENT_GUID_SIZE];
+ __le16 SecurityMode;
+ __le16 DialectCount;
+ __le16 Dialects[4]; /* BB expand this if autonegotiate > 4 dialects */
+} __packed;
+
+struct validate_negotiate_info_rsp {
+ __le32 Capabilities;
+ __u8 Guid[SMB2_CLIENT_GUID_SIZE];
+ __le16 SecurityMode;
+ __le16 Dialect; /* Dialect in use for the connection */
+} __packed;
+
+
+/* Possible InfoType values */
+#define SMB2_O_INFO_FILE 0x01
+#define SMB2_O_INFO_FILESYSTEM 0x02
+#define SMB2_O_INFO_SECURITY 0x03
+#define SMB2_O_INFO_QUOTA 0x04
+
+/* SMB2 Query Info see MS-SMB2 (2.2.37) or MS-DTYP */
+
+/* List of QUERY INFO levels (those also valid for QUERY_DIR are noted below */
+#define FILE_DIRECTORY_INFORMATION 1 /* also for QUERY_DIR */
+#define FILE_FULL_DIRECTORY_INFORMATION 2 /* also for QUERY_DIR */
+#define FILE_BOTH_DIRECTORY_INFORMATION 3 /* also for QUERY_DIR */
+#define FILE_BASIC_INFORMATION 4
+#define FILE_STANDARD_INFORMATION 5
+#define FILE_INTERNAL_INFORMATION 6
+#define FILE_EA_INFORMATION 7
+#define FILE_ACCESS_INFORMATION 8
+#define FILE_NAME_INFORMATION 9
+#define FILE_RENAME_INFORMATION 10
+#define FILE_LINK_INFORMATION 11
+#define FILE_NAMES_INFORMATION 12 /* also for QUERY_DIR */
+#define FILE_DISPOSITION_INFORMATION 13
+#define FILE_POSITION_INFORMATION 14
+#define FILE_FULL_EA_INFORMATION 15
+#define FILE_MODE_INFORMATION 16
+#define FILE_ALIGNMENT_INFORMATION 17
+#define FILE_ALL_INFORMATION 18
+#define FILE_ALLOCATION_INFORMATION 19
+#define FILE_END_OF_FILE_INFORMATION 20
+#define FILE_ALTERNATE_NAME_INFORMATION 21
+#define FILE_STREAM_INFORMATION 22
+#define FILE_PIPE_INFORMATION 23
+#define FILE_PIPE_LOCAL_INFORMATION 24
+#define FILE_PIPE_REMOTE_INFORMATION 25
+#define FILE_MAILSLOT_QUERY_INFORMATION 26
+#define FILE_MAILSLOT_SET_INFORMATION 27
+#define FILE_COMPRESSION_INFORMATION 28
+#define FILE_OBJECT_ID_INFORMATION 29
+/* Number 30 not defined in documents */
+#define FILE_MOVE_CLUSTER_INFORMATION 31
+#define FILE_QUOTA_INFORMATION 32
+#define FILE_REPARSE_POINT_INFORMATION 33
+#define FILE_NETWORK_OPEN_INFORMATION 34
+#define FILE_ATTRIBUTE_TAG_INFORMATION 35
+#define FILE_TRACKING_INFORMATION 36
+#define FILEID_BOTH_DIRECTORY_INFORMATION 37 /* also for QUERY_DIR */
+#define FILEID_FULL_DIRECTORY_INFORMATION 38 /* also for QUERY_DIR */
+#define FILE_VALID_DATA_LENGTH_INFORMATION 39
+#define FILE_SHORT_NAME_INFORMATION 40
+#define FILE_SFIO_RESERVE_INFORMATION 44
+#define FILE_SFIO_VOLUME_INFORMATION 45
+#define FILE_HARD_LINK_INFORMATION 46
+#define FILE_NORMALIZED_NAME_INFORMATION 48
+#define FILEID_GLOBAL_TX_DIRECTORY_INFORMATION 50
+#define FILE_STANDARD_LINK_INFORMATION 54
+#define FILE_ID_INFORMATION 59
+#define FILE_ID_EXTD_DIRECTORY_INFORMATION 60 /* also for QUERY_DIR */
+/* Used for Query Info and Find File POSIX Info for SMB3.1.1 and SMB1 */
+#define SMB_FIND_FILE_POSIX_INFO 0x064
+
+/* Security info type additionalinfo flags. */
+#define OWNER_SECINFO 0x00000001
+#define GROUP_SECINFO 0x00000002
+#define DACL_SECINFO 0x00000004
+#define SACL_SECINFO 0x00000008
+#define LABEL_SECINFO 0x00000010
+#define ATTRIBUTE_SECINFO 0x00000020
+#define SCOPE_SECINFO 0x00000040
+#define BACKUP_SECINFO 0x00010000
+#define UNPROTECTED_SACL_SECINFO 0x10000000
+#define UNPROTECTED_DACL_SECINFO 0x20000000
+#define PROTECTED_SACL_SECINFO 0x40000000
+#define PROTECTED_DACL_SECINFO 0x80000000
+
+/* Flags used for FileFullEAinfo */
+#define SL_RESTART_SCAN 0x00000001
+#define SL_RETURN_SINGLE_ENTRY 0x00000002
+#define SL_INDEX_SPECIFIED 0x00000004
+
+struct smb2_query_info_req {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 41 */
+ __u8 InfoType;
+ __u8 FileInfoClass;
+ __le32 OutputBufferLength;
+ __le16 InputBufferOffset;
+ __u16 Reserved;
+ __le32 InputBufferLength;
+ __le32 AdditionalInformation;
+ __le32 Flags;
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ __u8 Buffer[1];
+} __packed;
+
+struct smb2_query_info_rsp {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 9 */
+ __le16 OutputBufferOffset;
+ __le32 OutputBufferLength;
+ __u8 Buffer[1];
+} __packed;
+
+/*
+ * PDU query infolevel structure definitions
+ */
+
+/* See MS-FSCC 2.3.52 */
+struct file_allocated_range_buffer {
+ __le64 file_offset;
+ __le64 length;
+} __packed;
+
+struct smb2_file_internal_info {
+ __le64 IndexNumber;
+} __packed; /* level 6 Query */
+
+struct smb2_file_rename_info { /* encoding of request for level 10 */
+ __u8 ReplaceIfExists; /* 1 = replace existing target with new */
+ /* 0 = fail if target already exists */
+ __u8 Reserved[7];
+ __u64 RootDirectory; /* MBZ for network operations (why says spec?) */
+ __le32 FileNameLength;
+ char FileName[]; /* New name to be assigned */
+ /* padding - overall struct size must be >= 24 so filename + pad >= 6 */
+} __packed; /* level 10 Set */
+
+struct smb2_file_link_info { /* encoding of request for level 11 */
+ __u8 ReplaceIfExists; /* 1 = replace existing link with new */
+ /* 0 = fail if link already exists */
+ __u8 Reserved[7];
+ __u64 RootDirectory; /* MBZ for network operations (why says spec?) */
+ __le32 FileNameLength;
+ char FileName[]; /* Name to be assigned to new link */
+} __packed; /* level 11 Set */
+
+/*
+ * This level 18, although with struct with same name is different from cifs
+ * level 0x107. Level 0x107 has an extra u64 between AccessFlags and
+ * CurrentByteOffset.
+ */
+struct smb2_file_all_info { /* data block encoding of response to level 18 */
+ __le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le32 Attributes;
+ __u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */
+ __le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */
+ __le64 EndOfFile; /* size ie offset to first free byte in file */
+ __le32 NumberOfLinks; /* hard links */
+ __u8 DeletePending;
+ __u8 Directory;
+ __u16 Pad2; /* End of FILE_STANDARD_INFO equivalent */
+ __le64 IndexNumber;
+ __le32 EASize;
+ __le32 AccessFlags;
+ __le64 CurrentByteOffset;
+ __le32 Mode;
+ __le32 AlignmentRequirement;
+ __le32 FileNameLength;
+ char FileName[1];
+} __packed; /* level 18 Query */
+
+struct smb2_file_eof_info { /* encoding of request for level 10 */
+ __le64 EndOfFile; /* new end of file value */
+} __packed; /* level 20 Set */
+
+/* Level 100 query info */
+struct smb311_posix_qinfo {
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 DosAttributes;
+ __le64 Inode;
+ __le32 DeviceId;
+ __le32 Zero;
+ /* beginning of POSIX Create Context Response */
+ __le32 HardLinks;
+ __le32 ReparseTag;
+ __le32 Mode;
+ u8 Sids[];
+ /*
+ * var sized owner SID
+ * var sized group SID
+ * le32 filenamelength
+ * u8 filename[]
+ */
+} __packed;
+
+/* File System Information Classes */
+#define FS_VOLUME_INFORMATION 1 /* Query */
+#define FS_LABEL_INFORMATION 2 /* Set */
+#define FS_SIZE_INFORMATION 3 /* Query */
+#define FS_DEVICE_INFORMATION 4 /* Query */
+#define FS_ATTRIBUTE_INFORMATION 5 /* Query */
+#define FS_CONTROL_INFORMATION 6 /* Query, Set */
+#define FS_FULL_SIZE_INFORMATION 7 /* Query */
+#define FS_OBJECT_ID_INFORMATION 8 /* Query, Set */
+#define FS_DRIVER_PATH_INFORMATION 9 /* Query */
+#define FS_SECTOR_SIZE_INFORMATION 11 /* SMB3 or later. Query */
+#define FS_POSIX_INFORMATION 100 /* SMB3.1.1 POSIX. Query */
+
+struct smb2_fs_full_size_info {
+ __le64 TotalAllocationUnits;
+ __le64 CallerAvailableAllocationUnits;
+ __le64 ActualAvailableAllocationUnits;
+ __le32 SectorsPerAllocationUnit;
+ __le32 BytesPerSector;
+} __packed;
+
+#define SSINFO_FLAGS_ALIGNED_DEVICE 0x00000001
+#define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE 0x00000002
+#define SSINFO_FLAGS_NO_SEEK_PENALTY 0x00000004
+#define SSINFO_FLAGS_TRIM_ENABLED 0x00000008
+
+/* sector size info struct */
+struct smb3_fs_ss_info {
+ __le32 LogicalBytesPerSector;
+ __le32 PhysicalBytesPerSectorForAtomicity;
+ __le32 PhysicalBytesPerSectorForPerf;
+ __le32 FSEffPhysicalBytesPerSectorForAtomicity;
+ __le32 Flags;
+ __le32 ByteOffsetForSectorAlignment;
+ __le32 ByteOffsetForPartitionAlignment;
+} __packed;
+
+/* File System Control Information */
+struct smb2_fs_control_info {
+ __le64 FreeSpaceStartFiltering;
+ __le64 FreeSpaceThreshold;
+ __le64 FreeSpaceStopFiltering;
+ __le64 DefaultQuotaThreshold;
+ __le64 DefaultQuotaLimit;
+ __le32 FileSystemControlFlags;
+ __le32 Padding;
+} __packed;
+
+/* volume info struct - see MS-FSCC 2.5.9 */
+#define MAX_VOL_LABEL_LEN 32
+struct smb3_fs_vol_info {
+ __le64 VolumeCreationTime;
+ __u32 VolumeSerialNumber;
+ __le32 VolumeLabelLength; /* includes trailing null */
+ __u8 SupportsObjects; /* True if eg like NTFS, supports objects */
+ __u8 Reserved;
+ __u8 VolumeLabel[]; /* variable len */
+} __packed;
+
+/* See MS-SMB2 2.2.23 through 2.2.25 */
+struct smb2_oplock_break {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 24 */
+ __u8 OplockLevel;
+ __u8 Reserved;
+ __le32 Reserved2;
+ __u64 PersistentFid;
+ __u64 VolatileFid;
+} __packed;
+
+#define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01)
+
+struct smb2_lease_break {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 44 */
+ __le16 Epoch;
+ __le32 Flags;
+ __u8 LeaseKey[16];
+ __le32 CurrentLeaseState;
+ __le32 NewLeaseState;
+ __le32 BreakReason;
+ __le32 AccessMaskHint;
+ __le32 ShareMaskHint;
+} __packed;
+
+struct smb2_lease_ack {
+ struct smb2_hdr hdr;
+ __le16 StructureSize; /* Must be 36 */
+ __le16 Reserved;
+ __le32 Flags;
+ __u8 LeaseKey[16];
+ __le32 LeaseState;
+ __le64 LeaseDuration;
+} __packed;
+
+#define OP_BREAK_STRUCT_SIZE_20 24
+#define OP_BREAK_STRUCT_SIZE_21 36
+#endif /* _COMMON_SMB2PDU_H */
diff --git a/fs/smb/common/smbfsctl.h b/fs/smb/common/smbfsctl.h
new file mode 100644
index 000000000000..edd7fc2a7921
--- /dev/null
+++ b/fs/smb/common/smbfsctl.h
@@ -0,0 +1,170 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/*
+ * SMB, CIFS, SMB2 FSCTL definitions
+ *
+ * Copyright (c) International Business Machines Corp., 2002,2013
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+
+/* IOCTL information */
+/*
+ * List of ioctl/fsctl function codes that are or could be useful in the
+ * future to remote clients like cifs or SMB2/SMB3 client. This is probably
+ * a slightly larger set of fsctls that NTFS local filesystem could handle,
+ * including the seven below that we do not have struct definitions for.
+ * Even with protocol definitions for most of these now available, we still
+ * need to do some experimentation to identify which are practical to do
+ * remotely. Some of the following, such as the encryption/compression ones
+ * could be invoked from tools via a specialized hook into the VFS rather
+ * than via the standard vfs entry points
+ *
+ * See MS-SMB2 Section 2.2.31 (last checked September 2021, all of that list are
+ * below). Additional detail on less common ones can be found in MS-FSCC
+ * section 2.3.
+ */
+
+#ifndef __SMBFSCTL_H
+#define __SMBFSCTL_H
+
+/*
+ * FSCTL values are 32 bits and are constructed as
+ * <device 16bits> <access 2bits> <function 12bits> <method 2bits>
+ */
+/* Device */
+#define FSCTL_DEVICE_DFS (0x0006 << 16)
+#define FSCTL_DEVICE_FILE_SYSTEM (0x0009 << 16)
+#define FSCTL_DEVICE_NAMED_PIPE (0x0011 << 16)
+#define FSCTL_DEVICE_NETWORK_FILE_SYSTEM (0x0014 << 16)
+#define FSCTL_DEVICE_MASK 0xffff0000
+/* Access */
+#define FSCTL_DEVICE_ACCESS_FILE_ANY_ACCESS (0x00 << 14)
+#define FSCTL_DEVICE_ACCESS_FILE_READ_ACCESS (0x01 << 14)
+#define FSCTL_DEVICE_ACCESS_FILE_WRITE_ACCESS (0x02 << 14)
+#define FSCTL_DEVICE_ACCESS_FILE_READ_WRITE_ACCESS (0x03 << 14)
+#define FSCTL_DEVICE_ACCESS_MASK 0x0000c000
+/* Function */
+#define FSCTL_DEVICE_FUNCTION_MASK 0x00003ffc
+/* Method */
+#define FSCTL_DEVICE_METHOD_BUFFERED 0x00
+#define FSCTL_DEVICE_METHOD_IN_DIRECT 0x01
+#define FSCTL_DEVICE_METHOD_OUT_DIRECT 0x02
+#define FSCTL_DEVICE_METHOD_NEITHER 0x03
+#define FSCTL_DEVICE_METHOD_MASK 0x00000003
+
+
+#define FSCTL_DFS_GET_REFERRALS 0x00060194
+#define FSCTL_DFS_GET_REFERRALS_EX 0x000601B0
+#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
+#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
+#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
+#define FSCTL_LOCK_VOLUME 0x00090018
+#define FSCTL_UNLOCK_VOLUME 0x0009001C
+#define FSCTL_IS_PATHNAME_VALID 0x0009002C /* BB add struct */
+#define FSCTL_GET_COMPRESSION 0x0009003C /* BB add struct */
+#define FSCTL_SET_COMPRESSION 0x0009C040 /* BB add struct */
+#define FSCTL_QUERY_FAT_BPB 0x00090058 /* BB add struct */
+/* Verify the next FSCTL number, we had it as 0x00090090 before */
+#define FSCTL_FILESYSTEM_GET_STATS 0x00090060 /* BB add struct */
+#define FSCTL_GET_NTFS_VOLUME_DATA 0x00090064 /* BB add struct */
+#define FSCTL_GET_RETRIEVAL_POINTERS 0x00090073 /* BB add struct */
+#define FSCTL_IS_VOLUME_DIRTY 0x00090078 /* BB add struct */
+#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x00090083 /* BB add struct */
+#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
+#define FSCTL_FIND_FILES_BY_SID 0x0009008F /* BB add struct */
+#define FSCTL_SET_OBJECT_ID 0x00090098 /* BB add struct */
+#define FSCTL_GET_OBJECT_ID 0x0009009C /* BB add struct */
+#define FSCTL_DELETE_OBJECT_ID 0x000900A0 /* BB add struct */
+#define FSCTL_SET_REPARSE_POINT 0x000900A4 /* BB add struct */
+#define FSCTL_GET_REPARSE_POINT 0x000900A8 /* BB add struct */
+#define FSCTL_DELETE_REPARSE_POINT 0x000900AC /* BB add struct */
+#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */
+#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */
+#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */
+#define FSCTL_SET_ZERO_DATA 0x000980C8
+#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */
+#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */
+#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */
+#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 /* BB add struct */
+#define FSCTL_READ_FILE_USN_DATA 0x000900EB /* BB add struct */
+#define FSCTL_WRITE_USN_CLOSE_RECORD 0x000900EF /* BB add struct */
+#define FSCTL_MARK_HANDLE 0x000900FC /* BB add struct */
+#define FSCTL_SIS_COPYFILE 0x00090100 /* BB add struct */
+#define FSCTL_RECALL_FILE 0x00090117 /* BB add struct */
+#define FSCTL_QUERY_SPARING_INFO 0x00090138 /* BB add struct */
+#define FSCTL_QUERY_ON_DISK_VOLUME_INFO 0x0009013C
+#define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */
+#define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */
+#define FSCTL_GET_INTEGRITY_INFORMATION 0x0009027C
+#define FSCTL_QUERY_FILE_REGIONS 0x00090284
+#define FSCTL_GET_REFS_VOLUME_DATA 0x000902D8 /* See MS-FSCC 2.3.24 */
+#define FSCTL_SET_INTEGRITY_INFORMATION_EXT 0x00090380
+#define FSCTL_GET_RETRIEVAL_POINTERS_AND_REFCOUNT 0x000903d3
+#define FSCTL_GET_RETRIEVAL_POINTER_COUNT 0x0009042b
+#define FSCTL_REFS_STREAM_SNAPSHOT_MANAGEMENT 0x00090440
+#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF
+#define FSCTL_OFFLOAD_READ 0x00094264 /* BB add struct */
+#define FSCTL_OFFLOAD_WRITE 0x00098268 /* BB add struct */
+#define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */
+#define FSCTL_FILE_LEVEL_TRIM 0x00098208 /* BB add struct */
+#define FSCTL_DUPLICATE_EXTENTS_TO_FILE 0x00098344
+#define FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX 0x000983E8
+#define FSCTL_SIS_LINK_FILES 0x0009C104
+#define FSCTL_SET_INTEGRITY_INFORMATION 0x0009C280
+#define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */
+#define FSCTL_PIPE_TRANSCEIVE 0x0011C017 /* BB add struct */
+/* strange that the number for this op is not sequential with previous op */
+#define FSCTL_PIPE_WAIT 0x00110018 /* BB add struct */
+/* Enumerate previous versions of a file */
+#define FSCTL_SRV_ENUMERATE_SNAPSHOTS 0x00144064
+/* Retrieve an opaque file reference for server-side data movement ie copy */
+#define FSCTL_SRV_REQUEST_RESUME_KEY 0x00140078
+#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4
+#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
+#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
+#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
+/* Perform server-side data movement */
+#define FSCTL_SRV_COPYCHUNK 0x001440F2
+#define FSCTL_SRV_COPYCHUNK_WRITE 0x001480F2
+#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */
+#define FSCTL_SRV_READ_HASH 0x001441BB /* BB add struct */
+
+/* See FSCC 2.1.2.5 */
+#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
+#define IO_REPARSE_TAG_HSM 0xC0000004
+#define IO_REPARSE_TAG_SIS 0x80000007
+#define IO_REPARSE_TAG_HSM2 0x80000006
+#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
+/* Used by the DFS filter. See MS-DFSC */
+#define IO_REPARSE_TAG_DFS 0x8000000A
+/* Used by the DFS filter See MS-DFSC */
+#define IO_REPARSE_TAG_DFSR 0x80000012
+#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
+/* See section MS-FSCC 2.1.2.4 */
+#define IO_REPARSE_TAG_SYMLINK 0xA000000C
+#define IO_REPARSE_TAG_DEDUP 0x80000013
+#define IO_REPARSE_APPXSTREAM 0xC0000014
+/* NFS symlinks, Win 8/SMB3 and later */
+#define IO_REPARSE_TAG_NFS 0x80000014
+/*
+ * AzureFileSync - see
+ * https://docs.microsoft.com/en-us/azure/storage/files/storage-sync-cloud-tiering
+ */
+#define IO_REPARSE_TAG_AZ_FILE_SYNC 0x8000001e
+/* WSL reparse tags */
+#define IO_REPARSE_TAG_LX_SYMLINK 0xA000001D
+#define IO_REPARSE_TAG_AF_UNIX 0x80000023
+#define IO_REPARSE_TAG_LX_FIFO 0x80000024
+#define IO_REPARSE_TAG_LX_CHR 0x80000025
+#define IO_REPARSE_TAG_LX_BLK 0x80000026
+
+#define IO_REPARSE_TAG_LX_SYMLINK_LE cpu_to_le32(0xA000001D)
+#define IO_REPARSE_TAG_AF_UNIX_LE cpu_to_le32(0x80000023)
+#define IO_REPARSE_TAG_LX_FIFO_LE cpu_to_le32(0x80000024)
+#define IO_REPARSE_TAG_LX_CHR_LE cpu_to_le32(0x80000025)
+#define IO_REPARSE_TAG_LX_BLK_LE cpu_to_le32(0x80000026)
+
+/* fsctl flags */
+/* If Flags is set to this value, the request is an FSCTL not ioctl request */
+#define SMB2_0_IOCTL_IS_FSCTL 0x00000001
+#endif /* __SMBFSCTL_H */
diff --git a/fs/smb/server/Kconfig b/fs/smb/server/Kconfig
new file mode 100644
index 000000000000..e1fe17747ed6
--- /dev/null
+++ b/fs/smb/server/Kconfig
@@ -0,0 +1,68 @@
+config SMB_SERVER
+ tristate "SMB3 server support (EXPERIMENTAL)"
+ depends on INET
+ depends on MULTIUSER
+ depends on FILE_LOCKING
+ select NLS
+ select NLS_UTF8
+ select CRYPTO
+ select CRYPTO_MD5
+ select CRYPTO_HMAC
+ select CRYPTO_ECB
+ select CRYPTO_LIB_DES
+ select CRYPTO_SHA256
+ select CRYPTO_CMAC
+ select CRYPTO_SHA512
+ select CRYPTO_AEAD2
+ select CRYPTO_CCM
+ select CRYPTO_GCM
+ select ASN1
+ select OID_REGISTRY
+ select CRC32
+ default n
+ help
+ Choose Y here if you want to allow SMB3 compliant clients
+ to access files residing on this system using SMB3 protocol.
+ To compile the SMB3 server support as a module,
+ choose M here: the module will be called ksmbd.
+
+ You may choose to use a samba server instead, in which
+ case you can choose N here.
+
+ You also need to install user space programs which can be found
+ in ksmbd-tools, available from
+ https://github.com/cifsd-team/ksmbd-tools.
+ More detail about how to run the ksmbd kernel server is
+ available via README file
+ (https://github.com/cifsd-team/ksmbd-tools/blob/master/README).
+
+ ksmbd kernel server includes support for auto-negotiation,
+ Secure negotiate, Pre-authentication integrity, oplock/lease,
+ compound requests, multi-credit, packet signing, RDMA(smbdirect),
+ smb3 encryption, copy-offload, secure per-user session
+ establishment via NTLM or NTLMv2.
+
+config SMB_SERVER_SMBDIRECT
+ bool "Support for SMB Direct protocol"
+ depends on SMB_SERVER=m && INFINIBAND && INFINIBAND_ADDR_TRANS || SMB_SERVER=y && INFINIBAND=y && INFINIBAND_ADDR_TRANS=y
+ select SG_POOL
+ default n
+
+ help
+ Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1.
+
+ SMB Direct allows transferring SMB packets over RDMA. If unsure,
+ say N.
+
+config SMB_SERVER_CHECK_CAP_NET_ADMIN
+ bool "Enable check network administration capability"
+ depends on SMB_SERVER
+ default y
+
+ help
+ Prevent unprivileged processes to start the ksmbd kernel server.
+
+config SMB_SERVER_KERBEROS5
+ bool "Support for Kerberos 5"
+ depends on SMB_SERVER
+ default n
diff --git a/fs/smb/server/Makefile b/fs/smb/server/Makefile
new file mode 100644
index 000000000000..7d6337a7dee4
--- /dev/null
+++ b/fs/smb/server/Makefile
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Makefile for Linux SMB3 kernel server
+#
+obj-$(CONFIG_SMB_SERVER) += ksmbd.o
+
+ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o ndr.o \
+ misc.o oplock.o connection.o ksmbd_work.o crypto_ctx.o \
+ mgmt/ksmbd_ida.o mgmt/user_config.o mgmt/share_config.o \
+ mgmt/tree_connect.o mgmt/user_session.o smb_common.o \
+ transport_tcp.o transport_ipc.o smbacl.o smb2pdu.o \
+ smb2ops.o smb2misc.o ksmbd_spnego_negtokeninit.asn1.o \
+ ksmbd_spnego_negtokentarg.asn1.o asn1.o
+
+$(obj)/asn1.o: $(obj)/ksmbd_spnego_negtokeninit.asn1.h $(obj)/ksmbd_spnego_negtokentarg.asn1.h
+
+$(obj)/ksmbd_spnego_negtokeninit.asn1.o: $(obj)/ksmbd_spnego_negtokeninit.asn1.c $(obj)/ksmbd_spnego_negtokeninit.asn1.h
+$(obj)/ksmbd_spnego_negtokentarg.asn1.o: $(obj)/ksmbd_spnego_negtokentarg.asn1.c $(obj)/ksmbd_spnego_negtokentarg.asn1.h
+
+ksmbd-$(CONFIG_SMB_SERVER_SMBDIRECT) += transport_rdma.o
diff --git a/fs/smb/server/asn1.c b/fs/smb/server/asn1.c
new file mode 100644
index 000000000000..c03eba090368
--- /dev/null
+++ b/fs/smb/server/asn1.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
+ * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
+ *
+ * Copyright (c) 2000 RP Internet (www.rpi.net.au).
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/oid_registry.h>
+
+#include "glob.h"
+
+#include "asn1.h"
+#include "connection.h"
+#include "auth.h"
+#include "ksmbd_spnego_negtokeninit.asn1.h"
+#include "ksmbd_spnego_negtokentarg.asn1.h"
+
+#define NTLMSSP_OID_LEN 10
+
+static char NTLMSSP_OID_STR[NTLMSSP_OID_LEN] = { 0x2b, 0x06, 0x01, 0x04, 0x01,
+ 0x82, 0x37, 0x02, 0x02, 0x0a };
+
+int
+ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
+ struct ksmbd_conn *conn)
+{
+ return asn1_ber_decoder(&ksmbd_spnego_negtokeninit_decoder, conn,
+ security_blob, length);
+}
+
+int
+ksmbd_decode_negTokenTarg(unsigned char *security_blob, int length,
+ struct ksmbd_conn *conn)
+{
+ return asn1_ber_decoder(&ksmbd_spnego_negtokentarg_decoder, conn,
+ security_blob, length);
+}
+
+static int compute_asn_hdr_len_bytes(int len)
+{
+ if (len > 0xFFFFFF)
+ return 4;
+ else if (len > 0xFFFF)
+ return 3;
+ else if (len > 0xFF)
+ return 2;
+ else if (len > 0x7F)
+ return 1;
+ else
+ return 0;
+}
+
+static void encode_asn_tag(char *buf, unsigned int *ofs, char tag, char seq,
+ int length)
+{
+ int i;
+ int index = *ofs;
+ char hdr_len = compute_asn_hdr_len_bytes(length);
+ int len = length + 2 + hdr_len;
+
+ /* insert tag */
+ buf[index++] = tag;
+
+ if (!hdr_len) {
+ buf[index++] = len;
+ } else {
+ buf[index++] = 0x80 | hdr_len;
+ for (i = hdr_len - 1; i >= 0; i--)
+ buf[index++] = (len >> (i * 8)) & 0xFF;
+ }
+
+ /* insert seq */
+ len = len - (index - *ofs);
+ buf[index++] = seq;
+
+ if (!hdr_len) {
+ buf[index++] = len;
+ } else {
+ buf[index++] = 0x80 | hdr_len;
+ for (i = hdr_len - 1; i >= 0; i--)
+ buf[index++] = (len >> (i * 8)) & 0xFF;
+ }
+
+ *ofs += (index - *ofs);
+}
+
+int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
+ char *ntlm_blob, int ntlm_blob_len)
+{
+ char *buf;
+ unsigned int ofs = 0;
+ int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
+ int oid_len = 4 + compute_asn_hdr_len_bytes(NTLMSSP_OID_LEN) * 2 +
+ NTLMSSP_OID_LEN;
+ int ntlmssp_len = 4 + compute_asn_hdr_len_bytes(ntlm_blob_len) * 2 +
+ ntlm_blob_len;
+ int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len +
+ oid_len + ntlmssp_len) * 2 +
+ neg_result_len + oid_len + ntlmssp_len;
+
+ buf = kmalloc(total_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* insert main gss header */
+ encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len + oid_len +
+ ntlmssp_len);
+
+ /* insert neg result */
+ encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
+ buf[ofs++] = 1;
+
+ /* insert oid */
+ encode_asn_tag(buf, &ofs, 0xa1, 0x06, NTLMSSP_OID_LEN);
+ memcpy(buf + ofs, NTLMSSP_OID_STR, NTLMSSP_OID_LEN);
+ ofs += NTLMSSP_OID_LEN;
+
+ /* insert response token - ntlmssp blob */
+ encode_asn_tag(buf, &ofs, 0xa2, 0x04, ntlm_blob_len);
+ memcpy(buf + ofs, ntlm_blob, ntlm_blob_len);
+ ofs += ntlm_blob_len;
+
+ *pbuffer = buf;
+ *buflen = total_len;
+ return 0;
+}
+
+int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
+ int neg_result)
+{
+ char *buf;
+ unsigned int ofs = 0;
+ int neg_result_len = 4 + compute_asn_hdr_len_bytes(1) * 2 + 1;
+ int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len) * 2 +
+ neg_result_len;
+
+ buf = kmalloc(total_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* insert main gss header */
+ encode_asn_tag(buf, &ofs, 0xa1, 0x30, neg_result_len);
+
+ /* insert neg result */
+ encode_asn_tag(buf, &ofs, 0xa0, 0x0a, 1);
+ if (neg_result)
+ buf[ofs++] = 2;
+ else
+ buf[ofs++] = 0;
+
+ *pbuffer = buf;
+ *buflen = total_len;
+ return 0;
+}
+
+int ksmbd_gssapi_this_mech(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ enum OID oid;
+
+ oid = look_up_OID(value, vlen);
+ if (oid != OID_spnego) {
+ char buf[50];
+
+ sprint_oid(value, vlen, buf, sizeof(buf));
+ ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
+ return -EBADMSG;
+ }
+
+ return 0;
+}
+
+int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
+ unsigned char tag, const void *value,
+ size_t vlen)
+{
+ struct ksmbd_conn *conn = context;
+ enum OID oid;
+ int mech_type;
+
+ oid = look_up_OID(value, vlen);
+ if (oid == OID_ntlmssp) {
+ mech_type = KSMBD_AUTH_NTLMSSP;
+ } else if (oid == OID_mskrb5) {
+ mech_type = KSMBD_AUTH_MSKRB5;
+ } else if (oid == OID_krb5) {
+ mech_type = KSMBD_AUTH_KRB5;
+ } else if (oid == OID_krb5u2u) {
+ mech_type = KSMBD_AUTH_KRB5U2U;
+ } else {
+ char buf[50];
+
+ sprint_oid(value, vlen, buf, sizeof(buf));
+ ksmbd_debug(AUTH, "Unexpected OID: %s\n", buf);
+ return -EBADMSG;
+ }
+
+ conn->auth_mechs |= mech_type;
+ if (conn->preferred_auth_mech == 0)
+ conn->preferred_auth_mech = mech_type;
+
+ return 0;
+}
+
+int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
+ unsigned char tag, const void *value,
+ size_t vlen)
+{
+ struct ksmbd_conn *conn = context;
+
+ conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
+ if (!conn->mechToken)
+ return -ENOMEM;
+
+ memcpy(conn->mechToken, value, vlen);
+ conn->mechToken[vlen] = '\0';
+ return 0;
+}
+
+int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
+ unsigned char tag, const void *value,
+ size_t vlen)
+{
+ struct ksmbd_conn *conn = context;
+
+ conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
+ if (!conn->mechToken)
+ return -ENOMEM;
+
+ memcpy(conn->mechToken, value, vlen);
+ conn->mechToken[vlen] = '\0';
+ return 0;
+}
diff --git a/fs/smb/server/asn1.h b/fs/smb/server/asn1.h
new file mode 100644
index 000000000000..ce105f4ce305
--- /dev/null
+++ b/fs/smb/server/asn1.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
+ * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
+ *
+ * Copyright (c) 2000 RP Internet (www.rpi.net.au).
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __ASN1_H__
+#define __ASN1_H__
+
+int ksmbd_decode_negTokenInit(unsigned char *security_blob, int length,
+ struct ksmbd_conn *conn);
+int ksmbd_decode_negTokenTarg(unsigned char *security_blob, int length,
+ struct ksmbd_conn *conn);
+int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
+ char *ntlm_blob, int ntlm_blob_len);
+int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
+ int neg_result);
+#endif /* __ASN1_H__ */
diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c
new file mode 100644
index 000000000000..5e5e120edcc2
--- /dev/null
+++ b/fs/smb/server/auth.c
@@ -0,0 +1,1206 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/backing-dev.h>
+#include <linux/writeback.h>
+#include <linux/uio.h>
+#include <linux/xattr.h>
+#include <crypto/hash.h>
+#include <crypto/aead.h>
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+
+#include "auth.h"
+#include "glob.h"
+
+#include <linux/fips.h>
+#include <crypto/des.h>
+
+#include "server.h"
+#include "smb_common.h"
+#include "connection.h"
+#include "mgmt/user_session.h"
+#include "mgmt/user_config.h"
+#include "crypto_ctx.h"
+#include "transport_ipc.h"
+#include "../common/arc4.h"
+
+/*
+ * Fixed format data defining GSS header and fixed string
+ * "not_defined_in_RFC4178@please_ignore".
+ * So sec blob data in neg phase could be generated statically.
+ */
+static char NEGOTIATE_GSS_HEADER[AUTH_GSS_LENGTH] = {
+#ifdef CONFIG_SMB_SERVER_KERBEROS5
+ 0x60, 0x5e, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x02, 0xa0, 0x54, 0x30, 0x52, 0xa0, 0x24,
+ 0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02,
+ 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
+ 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a, 0x30, 0x28,
+ 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f, 0x74, 0x5f,
+ 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f,
+ 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43, 0x34, 0x31,
+ 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65, 0x61, 0x73,
+ 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65
+#else
+ 0x60, 0x48, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x02, 0xa0, 0x3e, 0x30, 0x3c, 0xa0, 0x0e,
+ 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
+ 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa3, 0x2a,
+ 0x30, 0x28, 0xa0, 0x26, 0x1b, 0x24, 0x6e, 0x6f,
+ 0x74, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
+ 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x52, 0x46, 0x43,
+ 0x34, 0x31, 0x37, 0x38, 0x40, 0x70, 0x6c, 0x65,
+ 0x61, 0x73, 0x65, 0x5f, 0x69, 0x67, 0x6e, 0x6f,
+ 0x72, 0x65
+#endif
+};
+
+void ksmbd_copy_gss_neg_header(void *buf)
+{
+ memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH);
+}
+
+/**
+ * ksmbd_gen_sess_key() - function to generate session key
+ * @sess: session of connection
+ * @hash: source hash value to be used for find session key
+ * @hmac: source hmac value to be used for finding session key
+ *
+ */
+static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash,
+ char *hmac)
+{
+ struct ksmbd_crypto_ctx *ctx;
+ int rc;
+
+ ctx = ksmbd_crypto_ctx_find_hmacmd5();
+ if (!ctx) {
+ ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
+ return -ENOMEM;
+ }
+
+ rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
+ hash,
+ CIFS_HMAC_MD5_HASH_SIZE);
+ if (rc) {
+ ksmbd_debug(AUTH, "hmacmd5 set key fail error %d\n", rc);
+ goto out;
+ }
+
+ rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
+ if (rc) {
+ ksmbd_debug(AUTH, "could not init hmacmd5 error %d\n", rc);
+ goto out;
+ }
+
+ rc = crypto_shash_update(CRYPTO_HMACMD5(ctx),
+ hmac,
+ SMB2_NTLMV2_SESSKEY_SIZE);
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not update with response error %d\n", rc);
+ goto out;
+ }
+
+ rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), sess->sess_key);
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n", rc);
+ goto out;
+ }
+
+out:
+ ksmbd_release_crypto_ctx(ctx);
+ return rc;
+}
+
+static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
+ char *ntlmv2_hash, char *dname)
+{
+ int ret, len, conv_len;
+ wchar_t *domain = NULL;
+ __le16 *uniname = NULL;
+ struct ksmbd_crypto_ctx *ctx;
+
+ ctx = ksmbd_crypto_ctx_find_hmacmd5();
+ if (!ctx) {
+ ksmbd_debug(AUTH, "can't generate ntlmv2 hash\n");
+ return -ENOMEM;
+ }
+
+ ret = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
+ user_passkey(sess->user),
+ CIFS_ENCPWD_SIZE);
+ if (ret) {
+ ksmbd_debug(AUTH, "Could not set NT Hash as a key\n");
+ goto out;
+ }
+
+ ret = crypto_shash_init(CRYPTO_HMACMD5(ctx));
+ if (ret) {
+ ksmbd_debug(AUTH, "could not init hmacmd5\n");
+ goto out;
+ }
+
+ /* convert user_name to unicode */
+ len = strlen(user_name(sess->user));
+ uniname = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
+ if (!uniname) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len,
+ conn->local_nls);
+ if (conv_len < 0 || conv_len > len) {
+ ret = -EINVAL;
+ goto out;
+ }
+ UniStrupr(uniname);
+
+ ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
+ (char *)uniname,
+ UNICODE_LEN(conv_len));
+ if (ret) {
+ ksmbd_debug(AUTH, "Could not update with user\n");
+ goto out;
+ }
+
+ /* Convert domain name or conn name to unicode and uppercase */
+ len = strlen(dname);
+ domain = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ conv_len = smb_strtoUTF16((__le16 *)domain, dname, len,
+ conn->local_nls);
+ if (conv_len < 0 || conv_len > len) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
+ (char *)domain,
+ UNICODE_LEN(conv_len));
+ if (ret) {
+ ksmbd_debug(AUTH, "Could not update with domain\n");
+ goto out;
+ }
+
+ ret = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_hash);
+ if (ret)
+ ksmbd_debug(AUTH, "Could not generate md5 hash\n");
+out:
+ kfree(uniname);
+ kfree(domain);
+ ksmbd_release_crypto_ctx(ctx);
+ return ret;
+}
+
+/**
+ * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
+ * @sess: session of connection
+ * @ntlmv2: NTLMv2 challenge response
+ * @blen: NTLMv2 blob length
+ * @domain_name: domain name
+ *
+ * Return: 0 on success, error number on error
+ */
+int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
+ struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
+ char *cryptkey)
+{
+ char ntlmv2_hash[CIFS_ENCPWD_SIZE];
+ char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
+ struct ksmbd_crypto_ctx *ctx = NULL;
+ char *construct = NULL;
+ int rc, len;
+
+ rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name);
+ if (rc) {
+ ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
+ goto out;
+ }
+
+ ctx = ksmbd_crypto_ctx_find_hmacmd5();
+ if (!ctx) {
+ ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
+ return -ENOMEM;
+ }
+
+ rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
+ ntlmv2_hash,
+ CIFS_HMAC_MD5_HASH_SIZE);
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not set NTLMV2 Hash as a key\n");
+ goto out;
+ }
+
+ rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not init hmacmd5\n");
+ goto out;
+ }
+
+ len = CIFS_CRYPTO_KEY_SIZE + blen;
+ construct = kzalloc(len, GFP_KERNEL);
+ if (!construct) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(construct, cryptkey, CIFS_CRYPTO_KEY_SIZE);
+ memcpy(construct + CIFS_CRYPTO_KEY_SIZE, &ntlmv2->blob_signature, blen);
+
+ rc = crypto_shash_update(CRYPTO_HMACMD5(ctx), construct, len);
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not update with response\n");
+ goto out;
+ }
+
+ rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_rsp);
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not generate md5 hash\n");
+ goto out;
+ }
+ ksmbd_release_crypto_ctx(ctx);
+ ctx = NULL;
+
+ rc = ksmbd_gen_sess_key(sess, ntlmv2_hash, ntlmv2_rsp);
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not generate sess key\n");
+ goto out;
+ }
+
+ if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0)
+ rc = -EINVAL;
+out:
+ if (ctx)
+ ksmbd_release_crypto_ctx(ctx);
+ kfree(construct);
+ return rc;
+}
+
+/**
+ * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
+ * authenticate blob
+ * @authblob: authenticate blob source pointer
+ * @usr: user details
+ * @sess: session of connection
+ *
+ * Return: 0 on success, error number on error
+ */
+int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
+ int blob_len, struct ksmbd_conn *conn,
+ struct ksmbd_session *sess)
+{
+ char *domain_name;
+ unsigned int nt_off, dn_off;
+ unsigned short nt_len, dn_len;
+ int ret;
+
+ if (blob_len < sizeof(struct authenticate_message)) {
+ ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
+ blob_len);
+ return -EINVAL;
+ }
+
+ if (memcmp(authblob->Signature, "NTLMSSP", 8)) {
+ ksmbd_debug(AUTH, "blob signature incorrect %s\n",
+ authblob->Signature);
+ return -EINVAL;
+ }
+
+ nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset);
+ nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length);
+ dn_off = le32_to_cpu(authblob->DomainName.BufferOffset);
+ dn_len = le16_to_cpu(authblob->DomainName.Length);
+
+ if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len ||
+ nt_len < CIFS_ENCPWD_SIZE)
+ return -EINVAL;
+
+ /* TODO : use domain name that imported from configuration file */
+ domain_name = smb_strndup_from_utf16((const char *)authblob + dn_off,
+ dn_len, true, conn->local_nls);
+ if (IS_ERR(domain_name))
+ return PTR_ERR(domain_name);
+
+ /* process NTLMv2 authentication */
+ ksmbd_debug(AUTH, "decode_ntlmssp_authenticate_blob dname%s\n",
+ domain_name);
+ ret = ksmbd_auth_ntlmv2(conn, sess,
+ (struct ntlmv2_resp *)((char *)authblob + nt_off),
+ nt_len - CIFS_ENCPWD_SIZE,
+ domain_name, conn->ntlmssp.cryptkey);
+ kfree(domain_name);
+
+ /* The recovered secondary session key */
+ if (conn->ntlmssp.client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) {
+ struct arc4_ctx *ctx_arc4;
+ unsigned int sess_key_off, sess_key_len;
+
+ sess_key_off = le32_to_cpu(authblob->SessionKey.BufferOffset);
+ sess_key_len = le16_to_cpu(authblob->SessionKey.Length);
+
+ if (blob_len < (u64)sess_key_off + sess_key_len)
+ return -EINVAL;
+
+ ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
+ if (!ctx_arc4)
+ return -ENOMEM;
+
+ cifs_arc4_setkey(ctx_arc4, sess->sess_key,
+ SMB2_NTLMV2_SESSKEY_SIZE);
+ cifs_arc4_crypt(ctx_arc4, sess->sess_key,
+ (char *)authblob + sess_key_off, sess_key_len);
+ kfree_sensitive(ctx_arc4);
+ }
+
+ return ret;
+}
+
+/**
+ * ksmbd_decode_ntlmssp_neg_blob() - helper function to construct
+ * negotiate blob
+ * @negblob: negotiate blob source pointer
+ * @rsp: response header pointer to be updated
+ * @sess: session of connection
+ *
+ */
+int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
+ int blob_len, struct ksmbd_conn *conn)
+{
+ if (blob_len < sizeof(struct negotiate_message)) {
+ ksmbd_debug(AUTH, "negotiate blob len %d too small\n",
+ blob_len);
+ return -EINVAL;
+ }
+
+ if (memcmp(negblob->Signature, "NTLMSSP", 8)) {
+ ksmbd_debug(AUTH, "blob signature incorrect %s\n",
+ negblob->Signature);
+ return -EINVAL;
+ }
+
+ conn->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags);
+ return 0;
+}
+
+/**
+ * ksmbd_build_ntlmssp_challenge_blob() - helper function to construct
+ * challenge blob
+ * @chgblob: challenge blob source pointer to initialize
+ * @rsp: response header pointer to be updated
+ * @sess: session of connection
+ *
+ */
+unsigned int
+ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
+ struct ksmbd_conn *conn)
+{
+ struct target_info *tinfo;
+ wchar_t *name;
+ __u8 *target_name;
+ unsigned int flags, blob_off, blob_len, type, target_info_len = 0;
+ int len, uni_len, conv_len;
+ int cflags = conn->ntlmssp.client_flags;
+
+ memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8);
+ chgblob->MessageType = NtLmChallenge;
+
+ flags = NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_TARGET_TYPE_SERVER |
+ NTLMSSP_NEGOTIATE_TARGET_INFO;
+
+ if (cflags & NTLMSSP_NEGOTIATE_SIGN) {
+ flags |= NTLMSSP_NEGOTIATE_SIGN;
+ flags |= cflags & (NTLMSSP_NEGOTIATE_128 |
+ NTLMSSP_NEGOTIATE_56);
+ }
+
+ if (cflags & NTLMSSP_NEGOTIATE_SEAL && smb3_encryption_negotiated(conn))
+ flags |= NTLMSSP_NEGOTIATE_SEAL;
+
+ if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
+ flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
+
+ if (cflags & NTLMSSP_REQUEST_TARGET)
+ flags |= NTLMSSP_REQUEST_TARGET;
+
+ if (conn->use_spnego &&
+ (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
+ flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
+
+ if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH)
+ flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
+
+ chgblob->NegotiateFlags = cpu_to_le32(flags);
+ len = strlen(ksmbd_netbios_name());
+ name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ conv_len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len,
+ conn->local_nls);
+ if (conv_len < 0 || conv_len > len) {
+ kfree(name);
+ return -EINVAL;
+ }
+
+ uni_len = UNICODE_LEN(conv_len);
+
+ blob_off = sizeof(struct challenge_message);
+ blob_len = blob_off + uni_len;
+
+ chgblob->TargetName.Length = cpu_to_le16(uni_len);
+ chgblob->TargetName.MaximumLength = cpu_to_le16(uni_len);
+ chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off);
+
+ /* Initialize random conn challenge */
+ get_random_bytes(conn->ntlmssp.cryptkey, sizeof(__u64));
+ memcpy(chgblob->Challenge, conn->ntlmssp.cryptkey,
+ CIFS_CRYPTO_KEY_SIZE);
+
+ /* Add Target Information to security buffer */
+ chgblob->TargetInfoArray.BufferOffset = cpu_to_le32(blob_len);
+
+ target_name = (__u8 *)chgblob + blob_off;
+ memcpy(target_name, name, uni_len);
+ tinfo = (struct target_info *)(target_name + uni_len);
+
+ chgblob->TargetInfoArray.Length = 0;
+ /* Add target info list for NetBIOS/DNS settings */
+ for (type = NTLMSSP_AV_NB_COMPUTER_NAME;
+ type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) {
+ tinfo->Type = cpu_to_le16(type);
+ tinfo->Length = cpu_to_le16(uni_len);
+ memcpy(tinfo->Content, name, uni_len);
+ tinfo = (struct target_info *)((char *)tinfo + 4 + uni_len);
+ target_info_len += 4 + uni_len;
+ }
+
+ /* Add terminator subblock */
+ tinfo->Type = 0;
+ tinfo->Length = 0;
+ target_info_len += 4;
+
+ chgblob->TargetInfoArray.Length = cpu_to_le16(target_info_len);
+ chgblob->TargetInfoArray.MaximumLength = cpu_to_le16(target_info_len);
+ blob_len += target_info_len;
+ kfree(name);
+ ksmbd_debug(AUTH, "NTLMSSP SecurityBufferLength %d\n", blob_len);
+ return blob_len;
+}
+
+#ifdef CONFIG_SMB_SERVER_KERBEROS5
+int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
+ int in_len, char *out_blob, int *out_len)
+{
+ struct ksmbd_spnego_authen_response *resp;
+ struct ksmbd_user *user = NULL;
+ int retval;
+
+ resp = ksmbd_ipc_spnego_authen_request(in_blob, in_len);
+ if (!resp) {
+ ksmbd_debug(AUTH, "SPNEGO_AUTHEN_REQUEST failure\n");
+ return -EINVAL;
+ }
+
+ if (!(resp->login_response.status & KSMBD_USER_FLAG_OK)) {
+ ksmbd_debug(AUTH, "krb5 authentication failure\n");
+ retval = -EPERM;
+ goto out;
+ }
+
+ if (*out_len <= resp->spnego_blob_len) {
+ ksmbd_debug(AUTH, "buf len %d, but blob len %d\n",
+ *out_len, resp->spnego_blob_len);
+ retval = -EINVAL;
+ goto out;
+ }
+
+ if (resp->session_key_len > sizeof(sess->sess_key)) {
+ ksmbd_debug(AUTH, "session key is too long\n");
+ retval = -EINVAL;
+ goto out;
+ }
+
+ user = ksmbd_alloc_user(&resp->login_response);
+ if (!user) {
+ ksmbd_debug(AUTH, "login failure\n");
+ retval = -ENOMEM;
+ goto out;
+ }
+ sess->user = user;
+
+ memcpy(sess->sess_key, resp->payload, resp->session_key_len);
+ memcpy(out_blob, resp->payload + resp->session_key_len,
+ resp->spnego_blob_len);
+ *out_len = resp->spnego_blob_len;
+ retval = 0;
+out:
+ kvfree(resp);
+ return retval;
+}
+#else
+int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
+ int in_len, char *out_blob, int *out_len)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
+/**
+ * ksmbd_sign_smb2_pdu() - function to generate packet signing
+ * @conn: connection
+ * @key: signing key
+ * @iov: buffer iov array
+ * @n_vec: number of iovecs
+ * @sig: signature value generated for client request packet
+ *
+ */
+int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
+ int n_vec, char *sig)
+{
+ struct ksmbd_crypto_ctx *ctx;
+ int rc, i;
+
+ ctx = ksmbd_crypto_ctx_find_hmacsha256();
+ if (!ctx) {
+ ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
+ return -ENOMEM;
+ }
+
+ rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
+ key,
+ SMB2_NTLMV2_SESSKEY_SIZE);
+ if (rc)
+ goto out;
+
+ rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
+ if (rc) {
+ ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
+ goto out;
+ }
+
+ for (i = 0; i < n_vec; i++) {
+ rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
+ iov[i].iov_base,
+ iov[i].iov_len);
+ if (rc) {
+ ksmbd_debug(AUTH, "hmacsha256 update error %d\n", rc);
+ goto out;
+ }
+ }
+
+ rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), sig);
+ if (rc)
+ ksmbd_debug(AUTH, "hmacsha256 generation error %d\n", rc);
+out:
+ ksmbd_release_crypto_ctx(ctx);
+ return rc;
+}
+
+/**
+ * ksmbd_sign_smb3_pdu() - function to generate packet signing
+ * @conn: connection
+ * @key: signing key
+ * @iov: buffer iov array
+ * @n_vec: number of iovecs
+ * @sig: signature value generated for client request packet
+ *
+ */
+int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
+ int n_vec, char *sig)
+{
+ struct ksmbd_crypto_ctx *ctx;
+ int rc, i;
+
+ ctx = ksmbd_crypto_ctx_find_cmacaes();
+ if (!ctx) {
+ ksmbd_debug(AUTH, "could not crypto alloc cmac\n");
+ return -ENOMEM;
+ }
+
+ rc = crypto_shash_setkey(CRYPTO_CMACAES_TFM(ctx),
+ key,
+ SMB2_CMACAES_SIZE);
+ if (rc)
+ goto out;
+
+ rc = crypto_shash_init(CRYPTO_CMACAES(ctx));
+ if (rc) {
+ ksmbd_debug(AUTH, "cmaces init error %d\n", rc);
+ goto out;
+ }
+
+ for (i = 0; i < n_vec; i++) {
+ rc = crypto_shash_update(CRYPTO_CMACAES(ctx),
+ iov[i].iov_base,
+ iov[i].iov_len);
+ if (rc) {
+ ksmbd_debug(AUTH, "cmaces update error %d\n", rc);
+ goto out;
+ }
+ }
+
+ rc = crypto_shash_final(CRYPTO_CMACAES(ctx), sig);
+ if (rc)
+ ksmbd_debug(AUTH, "cmaces generation error %d\n", rc);
+out:
+ ksmbd_release_crypto_ctx(ctx);
+ return rc;
+}
+
+struct derivation {
+ struct kvec label;
+ struct kvec context;
+ bool binding;
+};
+
+static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
+ struct kvec label, struct kvec context, __u8 *key,
+ unsigned int key_size)
+{
+ unsigned char zero = 0x0;
+ __u8 i[4] = {0, 0, 0, 1};
+ __u8 L128[4] = {0, 0, 0, 128};
+ __u8 L256[4] = {0, 0, 1, 0};
+ int rc;
+ unsigned char prfhash[SMB2_HMACSHA256_SIZE];
+ unsigned char *hashptr = prfhash;
+ struct ksmbd_crypto_ctx *ctx;
+
+ memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
+ memset(key, 0x0, key_size);
+
+ ctx = ksmbd_crypto_ctx_find_hmacsha256();
+ if (!ctx) {
+ ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
+ return -ENOMEM;
+ }
+
+ rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
+ sess->sess_key,
+ SMB2_NTLMV2_SESSKEY_SIZE);
+ if (rc)
+ goto smb3signkey_ret;
+
+ rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
+ if (rc) {
+ ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), i, 4);
+ if (rc) {
+ ksmbd_debug(AUTH, "could not update with n\n");
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
+ label.iov_base,
+ label.iov_len);
+ if (rc) {
+ ksmbd_debug(AUTH, "could not update with label\n");
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), &zero, 1);
+ if (rc) {
+ ksmbd_debug(AUTH, "could not update with zero\n");
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
+ context.iov_base,
+ context.iov_len);
+ if (rc) {
+ ksmbd_debug(AUTH, "could not update with context\n");
+ goto smb3signkey_ret;
+ }
+
+ if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
+ (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
+ conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
+ rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
+ else
+ rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
+ if (rc) {
+ ksmbd_debug(AUTH, "could not update with L\n");
+ goto smb3signkey_ret;
+ }
+
+ rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), hashptr);
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n",
+ rc);
+ goto smb3signkey_ret;
+ }
+
+ memcpy(key, hashptr, key_size);
+
+smb3signkey_ret:
+ ksmbd_release_crypto_ctx(ctx);
+ return rc;
+}
+
+static int generate_smb3signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn,
+ const struct derivation *signing)
+{
+ int rc;
+ struct channel *chann;
+ char *key;
+
+ chann = lookup_chann_list(sess, conn);
+ if (!chann)
+ return 0;
+
+ if (conn->dialect >= SMB30_PROT_ID && signing->binding)
+ key = chann->smb3signingkey;
+ else
+ key = sess->smb3signingkey;
+
+ rc = generate_key(conn, sess, signing->label, signing->context, key,
+ SMB3_SIGN_KEY_SIZE);
+ if (rc)
+ return rc;
+
+ if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
+ memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
+
+ ksmbd_debug(AUTH, "dumping generated AES signing keys\n");
+ ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
+ ksmbd_debug(AUTH, "Session Key %*ph\n",
+ SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
+ ksmbd_debug(AUTH, "Signing Key %*ph\n",
+ SMB3_SIGN_KEY_SIZE, key);
+ return 0;
+}
+
+int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn)
+{
+ struct derivation d;
+
+ d.label.iov_base = "SMB2AESCMAC";
+ d.label.iov_len = 12;
+ d.context.iov_base = "SmbSign";
+ d.context.iov_len = 8;
+ d.binding = conn->binding;
+
+ return generate_smb3signingkey(sess, conn, &d);
+}
+
+int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn)
+{
+ struct derivation d;
+
+ d.label.iov_base = "SMBSigningKey";
+ d.label.iov_len = 14;
+ if (conn->binding) {
+ struct preauth_session *preauth_sess;
+
+ preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
+ if (!preauth_sess)
+ return -ENOENT;
+ d.context.iov_base = preauth_sess->Preauth_HashValue;
+ } else {
+ d.context.iov_base = sess->Preauth_HashValue;
+ }
+ d.context.iov_len = 64;
+ d.binding = conn->binding;
+
+ return generate_smb3signingkey(sess, conn, &d);
+}
+
+struct derivation_twin {
+ struct derivation encryption;
+ struct derivation decryption;
+};
+
+static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
+ struct ksmbd_session *sess,
+ const struct derivation_twin *ptwin)
+{
+ int rc;
+
+ rc = generate_key(conn, sess, ptwin->encryption.label,
+ ptwin->encryption.context, sess->smb3encryptionkey,
+ SMB3_ENC_DEC_KEY_SIZE);
+ if (rc)
+ return rc;
+
+ rc = generate_key(conn, sess, ptwin->decryption.label,
+ ptwin->decryption.context,
+ sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
+ if (rc)
+ return rc;
+
+ ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
+ ksmbd_debug(AUTH, "Cipher type %d\n", conn->cipher_type);
+ ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
+ ksmbd_debug(AUTH, "Session Key %*ph\n",
+ SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
+ if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
+ conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
+ ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
+ SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey);
+ ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
+ SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3decryptionkey);
+ } else {
+ ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
+ SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3encryptionkey);
+ ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
+ SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
+ }
+ return 0;
+}
+
+int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
+ struct ksmbd_session *sess)
+{
+ struct derivation_twin twin;
+ struct derivation *d;
+
+ d = &twin.encryption;
+ d->label.iov_base = "SMB2AESCCM";
+ d->label.iov_len = 11;
+ d->context.iov_base = "ServerOut";
+ d->context.iov_len = 10;
+
+ d = &twin.decryption;
+ d->label.iov_base = "SMB2AESCCM";
+ d->label.iov_len = 11;
+ d->context.iov_base = "ServerIn ";
+ d->context.iov_len = 10;
+
+ return generate_smb3encryptionkey(conn, sess, &twin);
+}
+
+int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
+ struct ksmbd_session *sess)
+{
+ struct derivation_twin twin;
+ struct derivation *d;
+
+ d = &twin.encryption;
+ d->label.iov_base = "SMBS2CCipherKey";
+ d->label.iov_len = 16;
+ d->context.iov_base = sess->Preauth_HashValue;
+ d->context.iov_len = 64;
+
+ d = &twin.decryption;
+ d->label.iov_base = "SMBC2SCipherKey";
+ d->label.iov_len = 16;
+ d->context.iov_base = sess->Preauth_HashValue;
+ d->context.iov_len = 64;
+
+ return generate_smb3encryptionkey(conn, sess, &twin);
+}
+
+int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
+ __u8 *pi_hash)
+{
+ int rc;
+ struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
+ char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
+ int msg_size = get_rfc1002_len(buf);
+ struct ksmbd_crypto_ctx *ctx = NULL;
+
+ if (conn->preauth_info->Preauth_HashId !=
+ SMB2_PREAUTH_INTEGRITY_SHA512)
+ return -EINVAL;
+
+ ctx = ksmbd_crypto_ctx_find_sha512();
+ if (!ctx) {
+ ksmbd_debug(AUTH, "could not alloc sha512\n");
+ return -ENOMEM;
+ }
+
+ rc = crypto_shash_init(CRYPTO_SHA512(ctx));
+ if (rc) {
+ ksmbd_debug(AUTH, "could not init shashn");
+ goto out;
+ }
+
+ rc = crypto_shash_update(CRYPTO_SHA512(ctx), pi_hash, 64);
+ if (rc) {
+ ksmbd_debug(AUTH, "could not update with n\n");
+ goto out;
+ }
+
+ rc = crypto_shash_update(CRYPTO_SHA512(ctx), all_bytes_msg, msg_size);
+ if (rc) {
+ ksmbd_debug(AUTH, "could not update with n\n");
+ goto out;
+ }
+
+ rc = crypto_shash_final(CRYPTO_SHA512(ctx), pi_hash);
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
+ goto out;
+ }
+out:
+ ksmbd_release_crypto_ctx(ctx);
+ return rc;
+}
+
+int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
+ __u8 *pi_hash)
+{
+ int rc;
+ struct ksmbd_crypto_ctx *ctx = NULL;
+
+ ctx = ksmbd_crypto_ctx_find_sha256();
+ if (!ctx) {
+ ksmbd_debug(AUTH, "could not alloc sha256\n");
+ return -ENOMEM;
+ }
+
+ rc = crypto_shash_init(CRYPTO_SHA256(ctx));
+ if (rc) {
+ ksmbd_debug(AUTH, "could not init shashn");
+ goto out;
+ }
+
+ rc = crypto_shash_update(CRYPTO_SHA256(ctx), sd_buf, len);
+ if (rc) {
+ ksmbd_debug(AUTH, "could not update with n\n");
+ goto out;
+ }
+
+ rc = crypto_shash_final(CRYPTO_SHA256(ctx), pi_hash);
+ if (rc) {
+ ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
+ goto out;
+ }
+out:
+ ksmbd_release_crypto_ctx(ctx);
+ return rc;
+}
+
+static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
+ int enc, u8 *key)
+{
+ struct ksmbd_session *sess;
+ u8 *ses_enc_key;
+
+ if (enc)
+ sess = work->sess;
+ else
+ sess = ksmbd_session_lookup_all(work->conn, ses_id);
+ if (!sess)
+ return -EINVAL;
+
+ ses_enc_key = enc ? sess->smb3encryptionkey :
+ sess->smb3decryptionkey;
+ memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
+
+ return 0;
+}
+
+static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
+ unsigned int buflen)
+{
+ void *addr;
+
+ if (is_vmalloc_addr(buf))
+ addr = vmalloc_to_page(buf);
+ else
+ addr = virt_to_page(buf);
+ sg_set_page(sg, addr, buflen, offset_in_page(buf));
+}
+
+static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
+ u8 *sign)
+{
+ struct scatterlist *sg;
+ unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
+ int i, nr_entries[3] = {0}, total_entries = 0, sg_idx = 0;
+
+ if (!nvec)
+ return NULL;
+
+ for (i = 0; i < nvec - 1; i++) {
+ unsigned long kaddr = (unsigned long)iov[i + 1].iov_base;
+
+ if (is_vmalloc_addr(iov[i + 1].iov_base)) {
+ nr_entries[i] = ((kaddr + iov[i + 1].iov_len +
+ PAGE_SIZE - 1) >> PAGE_SHIFT) -
+ (kaddr >> PAGE_SHIFT);
+ } else {
+ nr_entries[i]++;
+ }
+ total_entries += nr_entries[i];
+ }
+
+ /* Add two entries for transform header and signature */
+ total_entries += 2;
+
+ sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL);
+ if (!sg)
+ return NULL;
+
+ sg_init_table(sg, total_entries);
+ smb2_sg_set_buf(&sg[sg_idx++], iov[0].iov_base + 24, assoc_data_len);
+ for (i = 0; i < nvec - 1; i++) {
+ void *data = iov[i + 1].iov_base;
+ int len = iov[i + 1].iov_len;
+
+ if (is_vmalloc_addr(data)) {
+ int j, offset = offset_in_page(data);
+
+ for (j = 0; j < nr_entries[i]; j++) {
+ unsigned int bytes = PAGE_SIZE - offset;
+
+ if (!len)
+ break;
+
+ if (bytes > len)
+ bytes = len;
+
+ sg_set_page(&sg[sg_idx++],
+ vmalloc_to_page(data), bytes,
+ offset_in_page(data));
+
+ data += bytes;
+ len -= bytes;
+ offset = 0;
+ }
+ } else {
+ sg_set_page(&sg[sg_idx++], virt_to_page(data), len,
+ offset_in_page(data));
+ }
+ }
+ smb2_sg_set_buf(&sg[sg_idx], sign, SMB2_SIGNATURE_SIZE);
+ return sg;
+}
+
+int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
+ unsigned int nvec, int enc)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
+ unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
+ int rc;
+ struct scatterlist *sg;
+ u8 sign[SMB2_SIGNATURE_SIZE] = {};
+ u8 key[SMB3_ENC_DEC_KEY_SIZE];
+ struct aead_request *req;
+ char *iv;
+ unsigned int iv_len;
+ struct crypto_aead *tfm;
+ unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
+ struct ksmbd_crypto_ctx *ctx;
+
+ rc = ksmbd_get_encryption_key(work,
+ le64_to_cpu(tr_hdr->SessionId),
+ enc,
+ key);
+ if (rc) {
+ pr_err("Could not get %scryption key\n", enc ? "en" : "de");
+ return rc;
+ }
+
+ if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
+ conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+ ctx = ksmbd_crypto_ctx_find_gcm();
+ else
+ ctx = ksmbd_crypto_ctx_find_ccm();
+ if (!ctx) {
+ pr_err("crypto alloc failed\n");
+ return -ENOMEM;
+ }
+
+ if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
+ conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+ tfm = CRYPTO_GCM(ctx);
+ else
+ tfm = CRYPTO_CCM(ctx);
+
+ if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
+ conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+ rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
+ else
+ rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
+ if (rc) {
+ pr_err("Failed to set aead key %d\n", rc);
+ goto free_ctx;
+ }
+
+ rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
+ if (rc) {
+ pr_err("Failed to set authsize %d\n", rc);
+ goto free_ctx;
+ }
+
+ req = aead_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ rc = -ENOMEM;
+ goto free_ctx;
+ }
+
+ if (!enc) {
+ memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
+ crypt_len += SMB2_SIGNATURE_SIZE;
+ }
+
+ sg = ksmbd_init_sg(iov, nvec, sign);
+ if (!sg) {
+ pr_err("Failed to init sg\n");
+ rc = -ENOMEM;
+ goto free_req;
+ }
+
+ iv_len = crypto_aead_ivsize(tfm);
+ iv = kzalloc(iv_len, GFP_KERNEL);
+ if (!iv) {
+ rc = -ENOMEM;
+ goto free_sg;
+ }
+
+ if (conn->cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
+ conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
+ memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
+ } else {
+ iv[0] = 3;
+ memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
+ }
+
+ aead_request_set_crypt(req, sg, sg, crypt_len, iv);
+ aead_request_set_ad(req, assoc_data_len);
+ aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
+
+ if (enc)
+ rc = crypto_aead_encrypt(req);
+ else
+ rc = crypto_aead_decrypt(req);
+ if (rc)
+ goto free_iv;
+
+ if (enc)
+ memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
+
+free_iv:
+ kfree(iv);
+free_sg:
+ kfree(sg);
+free_req:
+ kfree(req);
+free_ctx:
+ ksmbd_release_crypto_ctx(ctx);
+ return rc;
+}
diff --git a/fs/smb/server/auth.h b/fs/smb/server/auth.h
new file mode 100644
index 000000000000..362b6159a6cf
--- /dev/null
+++ b/fs/smb/server/auth.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __AUTH_H__
+#define __AUTH_H__
+
+#include "ntlmssp.h"
+
+#ifdef CONFIG_SMB_SERVER_KERBEROS5
+#define AUTH_GSS_LENGTH 96
+#define AUTH_GSS_PADDING 0
+#else
+#define AUTH_GSS_LENGTH 74
+#define AUTH_GSS_PADDING 6
+#endif
+
+#define CIFS_HMAC_MD5_HASH_SIZE (16)
+#define CIFS_NTHASH_SIZE (16)
+
+/*
+ * Size of the ntlm client response
+ */
+#define CIFS_AUTH_RESP_SIZE 24
+#define CIFS_SMB1_SIGNATURE_SIZE 8
+#define CIFS_SMB1_SESSKEY_SIZE 16
+
+#define KSMBD_AUTH_NTLMSSP 0x0001
+#define KSMBD_AUTH_KRB5 0x0002
+#define KSMBD_AUTH_MSKRB5 0x0004
+#define KSMBD_AUTH_KRB5U2U 0x0008
+
+struct ksmbd_session;
+struct ksmbd_conn;
+struct ksmbd_work;
+struct kvec;
+
+int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
+ unsigned int nvec, int enc);
+void ksmbd_copy_gss_neg_header(void *buf);
+int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
+ struct ntlmv2_resp *ntlmv2, int blen, char *domain_name,
+ char *cryptkey);
+int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
+ int blob_len, struct ksmbd_conn *conn,
+ struct ksmbd_session *sess);
+int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob,
+ int blob_len, struct ksmbd_conn *conn);
+unsigned int
+ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
+ struct ksmbd_conn *conn);
+int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
+ int in_len, char *out_blob, int *out_len);
+int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
+ int n_vec, char *sig);
+int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
+ int n_vec, char *sig);
+int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn);
+int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn);
+int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
+ struct ksmbd_session *sess);
+int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
+ struct ksmbd_session *sess);
+int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
+ __u8 *pi_hash);
+int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
+ __u8 *pi_hash);
+#endif
diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
new file mode 100644
index 000000000000..e1d2be19cddf
--- /dev/null
+++ b/fs/smb/server/connection.c
@@ -0,0 +1,485 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <namjae.jeon@protocolfreedom.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/mutex.h>
+#include <linux/freezer.h>
+#include <linux/module.h>
+
+#include "server.h"
+#include "smb_common.h"
+#include "mgmt/ksmbd_ida.h"
+#include "connection.h"
+#include "transport_tcp.h"
+#include "transport_rdma.h"
+
+static DEFINE_MUTEX(init_lock);
+
+static struct ksmbd_conn_ops default_conn_ops;
+
+LIST_HEAD(conn_list);
+DECLARE_RWSEM(conn_list_lock);
+
+/**
+ * ksmbd_conn_free() - free resources of the connection instance
+ *
+ * @conn: connection instance to be cleand up
+ *
+ * During the thread termination, the corresponding conn instance
+ * resources(sock/memory) are released and finally the conn object is freed.
+ */
+void ksmbd_conn_free(struct ksmbd_conn *conn)
+{
+ down_write(&conn_list_lock);
+ list_del(&conn->conns_list);
+ up_write(&conn_list_lock);
+
+ xa_destroy(&conn->sessions);
+ kvfree(conn->request_buf);
+ kfree(conn->preauth_info);
+ kfree(conn);
+}
+
+/**
+ * ksmbd_conn_alloc() - initialize a new connection instance
+ *
+ * Return: ksmbd_conn struct on success, otherwise NULL
+ */
+struct ksmbd_conn *ksmbd_conn_alloc(void)
+{
+ struct ksmbd_conn *conn;
+
+ conn = kzalloc(sizeof(struct ksmbd_conn), GFP_KERNEL);
+ if (!conn)
+ return NULL;
+
+ conn->need_neg = true;
+ ksmbd_conn_set_new(conn);
+ conn->local_nls = load_nls("utf8");
+ if (!conn->local_nls)
+ conn->local_nls = load_nls_default();
+ if (IS_ENABLED(CONFIG_UNICODE))
+ conn->um = utf8_load(UNICODE_AGE(12, 1, 0));
+ else
+ conn->um = ERR_PTR(-EOPNOTSUPP);
+ if (IS_ERR(conn->um))
+ conn->um = NULL;
+ atomic_set(&conn->req_running, 0);
+ atomic_set(&conn->r_count, 0);
+ conn->total_credits = 1;
+ conn->outstanding_credits = 0;
+
+ init_waitqueue_head(&conn->req_running_q);
+ init_waitqueue_head(&conn->r_count_q);
+ INIT_LIST_HEAD(&conn->conns_list);
+ INIT_LIST_HEAD(&conn->requests);
+ INIT_LIST_HEAD(&conn->async_requests);
+ spin_lock_init(&conn->request_lock);
+ spin_lock_init(&conn->credits_lock);
+ ida_init(&conn->async_ida);
+ xa_init(&conn->sessions);
+
+ spin_lock_init(&conn->llist_lock);
+ INIT_LIST_HEAD(&conn->lock_list);
+
+ down_write(&conn_list_lock);
+ list_add(&conn->conns_list, &conn_list);
+ up_write(&conn_list_lock);
+ return conn;
+}
+
+bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)
+{
+ struct ksmbd_conn *t;
+ bool ret = false;
+
+ down_read(&conn_list_lock);
+ list_for_each_entry(t, &conn_list, conns_list) {
+ if (memcmp(t->ClientGUID, c->ClientGUID, SMB2_CLIENT_GUID_SIZE))
+ continue;
+
+ ret = true;
+ break;
+ }
+ up_read(&conn_list_lock);
+ return ret;
+}
+
+void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct list_head *requests_queue = NULL;
+
+ if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
+ requests_queue = &conn->requests;
+ work->syncronous = true;
+ }
+
+ if (requests_queue) {
+ atomic_inc(&conn->req_running);
+ spin_lock(&conn->request_lock);
+ list_add_tail(&work->request_entry, requests_queue);
+ spin_unlock(&conn->request_lock);
+ }
+}
+
+int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ int ret = 1;
+
+ if (list_empty(&work->request_entry) &&
+ list_empty(&work->async_request_entry))
+ return 0;
+
+ if (!work->multiRsp)
+ atomic_dec(&conn->req_running);
+ spin_lock(&conn->request_lock);
+ if (!work->multiRsp) {
+ list_del_init(&work->request_entry);
+ if (work->syncronous == false)
+ list_del_init(&work->async_request_entry);
+ ret = 0;
+ }
+ spin_unlock(&conn->request_lock);
+
+ wake_up_all(&conn->req_running_q);
+ return ret;
+}
+
+void ksmbd_conn_lock(struct ksmbd_conn *conn)
+{
+ mutex_lock(&conn->srv_mutex);
+}
+
+void ksmbd_conn_unlock(struct ksmbd_conn *conn)
+{
+ mutex_unlock(&conn->srv_mutex);
+}
+
+void ksmbd_all_conn_set_status(u64 sess_id, u32 status)
+{
+ struct ksmbd_conn *conn;
+
+ down_read(&conn_list_lock);
+ list_for_each_entry(conn, &conn_list, conns_list) {
+ if (conn->binding || xa_load(&conn->sessions, sess_id))
+ WRITE_ONCE(conn->status, status);
+ }
+ up_read(&conn_list_lock);
+}
+
+void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id)
+{
+ struct ksmbd_conn *bind_conn;
+
+ wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
+
+ down_read(&conn_list_lock);
+ list_for_each_entry(bind_conn, &conn_list, conns_list) {
+ if (bind_conn == conn)
+ continue;
+
+ if ((bind_conn->binding || xa_load(&bind_conn->sessions, sess_id)) &&
+ !ksmbd_conn_releasing(bind_conn) &&
+ atomic_read(&bind_conn->req_running)) {
+ wait_event(bind_conn->req_running_q,
+ atomic_read(&bind_conn->req_running) == 0);
+ }
+ }
+ up_read(&conn_list_lock);
+}
+
+int ksmbd_conn_write(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ size_t len = 0;
+ int sent;
+ struct kvec iov[3];
+ int iov_idx = 0;
+
+ if (!work->response_buf) {
+ pr_err("NULL response header\n");
+ return -EINVAL;
+ }
+
+ if (work->tr_buf) {
+ iov[iov_idx] = (struct kvec) { work->tr_buf,
+ sizeof(struct smb2_transform_hdr) + 4 };
+ len += iov[iov_idx++].iov_len;
+ }
+
+ if (work->aux_payload_sz) {
+ iov[iov_idx] = (struct kvec) { work->response_buf, work->resp_hdr_sz };
+ len += iov[iov_idx++].iov_len;
+ iov[iov_idx] = (struct kvec) { work->aux_payload_buf, work->aux_payload_sz };
+ len += iov[iov_idx++].iov_len;
+ } else {
+ if (work->tr_buf)
+ iov[iov_idx].iov_len = work->resp_hdr_sz;
+ else
+ iov[iov_idx].iov_len = get_rfc1002_len(work->response_buf) + 4;
+ iov[iov_idx].iov_base = work->response_buf;
+ len += iov[iov_idx++].iov_len;
+ }
+
+ ksmbd_conn_lock(conn);
+ sent = conn->transport->ops->writev(conn->transport, &iov[0],
+ iov_idx, len,
+ work->need_invalidate_rkey,
+ work->remote_key);
+ ksmbd_conn_unlock(conn);
+
+ if (sent < 0) {
+ pr_err("Failed to send message: %d\n", sent);
+ return sent;
+ }
+
+ return 0;
+}
+
+int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len)
+{
+ int ret = -EINVAL;
+
+ if (conn->transport->ops->rdma_read)
+ ret = conn->transport->ops->rdma_read(conn->transport,
+ buf, buflen,
+ desc, desc_len);
+ return ret;
+}
+
+int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len)
+{
+ int ret = -EINVAL;
+
+ if (conn->transport->ops->rdma_write)
+ ret = conn->transport->ops->rdma_write(conn->transport,
+ buf, buflen,
+ desc, desc_len);
+ return ret;
+}
+
+bool ksmbd_conn_alive(struct ksmbd_conn *conn)
+{
+ if (!ksmbd_server_running())
+ return false;
+
+ if (ksmbd_conn_exiting(conn))
+ return false;
+
+ if (kthread_should_stop())
+ return false;
+
+ if (atomic_read(&conn->stats.open_files_count) > 0)
+ return true;
+
+ /*
+ * Stop current session if the time that get last request from client
+ * is bigger than deadtime user configured and opening file count is
+ * zero.
+ */
+ if (server_conf.deadtime > 0 &&
+ time_after(jiffies, conn->last_active + server_conf.deadtime)) {
+ ksmbd_debug(CONN, "No response from client in %lu minutes\n",
+ server_conf.deadtime / SMB_ECHO_INTERVAL);
+ return false;
+ }
+ return true;
+}
+
+#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr))
+#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)
+
+/**
+ * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
+ * @p: connection instance
+ *
+ * One thread each per connection
+ *
+ * Return: 0 on success
+ */
+int ksmbd_conn_handler_loop(void *p)
+{
+ struct ksmbd_conn *conn = (struct ksmbd_conn *)p;
+ struct ksmbd_transport *t = conn->transport;
+ unsigned int pdu_size, max_allowed_pdu_size;
+ char hdr_buf[4] = {0,};
+ int size;
+
+ mutex_init(&conn->srv_mutex);
+ __module_get(THIS_MODULE);
+
+ if (t->ops->prepare && t->ops->prepare(t))
+ goto out;
+
+ conn->last_active = jiffies;
+ while (ksmbd_conn_alive(conn)) {
+ if (try_to_freeze())
+ continue;
+
+ kvfree(conn->request_buf);
+ conn->request_buf = NULL;
+
+ size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
+ if (size != sizeof(hdr_buf))
+ break;
+
+ pdu_size = get_rfc1002_len(hdr_buf);
+ ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);
+
+ if (ksmbd_conn_good(conn))
+ max_allowed_pdu_size =
+ SMB3_MAX_MSGSIZE + conn->vals->max_write_size;
+ else
+ max_allowed_pdu_size = SMB3_MAX_MSGSIZE;
+
+ if (pdu_size > max_allowed_pdu_size) {
+ pr_err_ratelimited("PDU length(%u) excceed maximum allowed pdu size(%u) on connection(%d)\n",
+ pdu_size, max_allowed_pdu_size,
+ READ_ONCE(conn->status));
+ break;
+ }
+
+ /*
+ * Check maximum pdu size(0x00FFFFFF).
+ */
+ if (pdu_size > MAX_STREAM_PROT_LEN)
+ break;
+
+ if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE)
+ break;
+
+ /* 4 for rfc1002 length field */
+ /* 1 for implied bcc[0] */
+ size = pdu_size + 4 + 1;
+ conn->request_buf = kvmalloc(size, GFP_KERNEL);
+ if (!conn->request_buf)
+ break;
+
+ memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));
+
+ /*
+ * We already read 4 bytes to find out PDU size, now
+ * read in PDU
+ */
+ size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);
+ if (size < 0) {
+ pr_err("sock_read failed: %d\n", size);
+ break;
+ }
+
+ if (size != pdu_size) {
+ pr_err("PDU error. Read: %d, Expected: %d\n",
+ size, pdu_size);
+ continue;
+ }
+
+ if (!ksmbd_smb_request(conn))
+ break;
+
+ if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
+ SMB2_PROTO_NUMBER) {
+ if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
+ break;
+ }
+
+ if (!default_conn_ops.process_fn) {
+ pr_err("No connection request callback\n");
+ break;
+ }
+
+ if (default_conn_ops.process_fn(conn)) {
+ pr_err("Cannot handle request\n");
+ break;
+ }
+ }
+
+out:
+ ksmbd_conn_set_releasing(conn);
+ /* Wait till all reference dropped to the Server object*/
+ wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
+
+ if (IS_ENABLED(CONFIG_UNICODE))
+ utf8_unload(conn->um);
+ unload_nls(conn->local_nls);
+ if (default_conn_ops.terminate_fn)
+ default_conn_ops.terminate_fn(conn);
+ t->ops->disconnect(t);
+ module_put(THIS_MODULE);
+ return 0;
+}
+
+void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops)
+{
+ default_conn_ops.process_fn = ops->process_fn;
+ default_conn_ops.terminate_fn = ops->terminate_fn;
+}
+
+int ksmbd_conn_transport_init(void)
+{
+ int ret;
+
+ mutex_lock(&init_lock);
+ ret = ksmbd_tcp_init();
+ if (ret) {
+ pr_err("Failed to init TCP subsystem: %d\n", ret);
+ goto out;
+ }
+
+ ret = ksmbd_rdma_init();
+ if (ret) {
+ pr_err("Failed to init RDMA subsystem: %d\n", ret);
+ goto out;
+ }
+out:
+ mutex_unlock(&init_lock);
+ return ret;
+}
+
+static void stop_sessions(void)
+{
+ struct ksmbd_conn *conn;
+ struct ksmbd_transport *t;
+
+again:
+ down_read(&conn_list_lock);
+ list_for_each_entry(conn, &conn_list, conns_list) {
+ struct task_struct *task;
+
+ t = conn->transport;
+ task = t->handler;
+ if (task)
+ ksmbd_debug(CONN, "Stop session handler %s/%d\n",
+ task->comm, task_pid_nr(task));
+ ksmbd_conn_set_exiting(conn);
+ if (t->ops->shutdown) {
+ up_read(&conn_list_lock);
+ t->ops->shutdown(t);
+ down_read(&conn_list_lock);
+ }
+ }
+ up_read(&conn_list_lock);
+
+ if (!list_empty(&conn_list)) {
+ schedule_timeout_interruptible(HZ / 10); /* 100ms */
+ goto again;
+ }
+}
+
+void ksmbd_conn_transport_destroy(void)
+{
+ mutex_lock(&init_lock);
+ ksmbd_tcp_destroy();
+ ksmbd_rdma_destroy();
+ stop_sessions();
+ mutex_unlock(&init_lock);
+}
diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h
new file mode 100644
index 000000000000..ad8dfaa48ffb
--- /dev/null
+++ b/fs/smb/server/connection.h
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __KSMBD_CONNECTION_H__
+#define __KSMBD_CONNECTION_H__
+
+#include <linux/list.h>
+#include <linux/ip.h>
+#include <net/sock.h>
+#include <net/tcp.h>
+#include <net/inet_connection_sock.h>
+#include <net/request_sock.h>
+#include <linux/kthread.h>
+#include <linux/nls.h>
+#include <linux/unicode.h>
+
+#include "smb_common.h"
+#include "ksmbd_work.h"
+
+#define KSMBD_SOCKET_BACKLOG 16
+
+enum {
+ KSMBD_SESS_NEW = 0,
+ KSMBD_SESS_GOOD,
+ KSMBD_SESS_EXITING,
+ KSMBD_SESS_NEED_RECONNECT,
+ KSMBD_SESS_NEED_NEGOTIATE,
+ KSMBD_SESS_RELEASING
+};
+
+struct ksmbd_stats {
+ atomic_t open_files_count;
+ atomic64_t request_served;
+};
+
+struct ksmbd_transport;
+
+struct ksmbd_conn {
+ struct smb_version_values *vals;
+ struct smb_version_ops *ops;
+ struct smb_version_cmds *cmds;
+ unsigned int max_cmds;
+ struct mutex srv_mutex;
+ int status;
+ unsigned int cli_cap;
+ char *request_buf;
+ struct ksmbd_transport *transport;
+ struct nls_table *local_nls;
+ struct unicode_map *um;
+ struct list_head conns_list;
+ /* smb session 1 per user */
+ struct xarray sessions;
+ unsigned long last_active;
+ /* How many request are running currently */
+ atomic_t req_running;
+ /* References which are made for this Server object*/
+ atomic_t r_count;
+ unsigned int total_credits;
+ unsigned int outstanding_credits;
+ spinlock_t credits_lock;
+ wait_queue_head_t req_running_q;
+ wait_queue_head_t r_count_q;
+ /* Lock to protect requests list*/
+ spinlock_t request_lock;
+ struct list_head requests;
+ struct list_head async_requests;
+ int connection_type;
+ struct ksmbd_stats stats;
+ char ClientGUID[SMB2_CLIENT_GUID_SIZE];
+ struct ntlmssp_auth ntlmssp;
+
+ spinlock_t llist_lock;
+ struct list_head lock_list;
+
+ struct preauth_integrity_info *preauth_info;
+
+ bool need_neg;
+ unsigned int auth_mechs;
+ unsigned int preferred_auth_mech;
+ bool sign;
+ bool use_spnego:1;
+ __u16 cli_sec_mode;
+ __u16 srv_sec_mode;
+ /* dialect index that server chose */
+ __u16 dialect;
+
+ char *mechToken;
+
+ struct ksmbd_conn_ops *conn_ops;
+
+ /* Preauth Session Table */
+ struct list_head preauth_sess_table;
+
+ struct sockaddr_storage peer_addr;
+
+ /* Identifier for async message */
+ struct ida async_ida;
+
+ __le16 cipher_type;
+ __le16 compress_algorithm;
+ bool posix_ext_supported;
+ bool signing_negotiated;
+ __le16 signing_algorithm;
+ bool binding;
+};
+
+struct ksmbd_conn_ops {
+ int (*process_fn)(struct ksmbd_conn *conn);
+ int (*terminate_fn)(struct ksmbd_conn *conn);
+};
+
+struct ksmbd_transport_ops {
+ int (*prepare)(struct ksmbd_transport *t);
+ void (*disconnect)(struct ksmbd_transport *t);
+ void (*shutdown)(struct ksmbd_transport *t);
+ int (*read)(struct ksmbd_transport *t, char *buf,
+ unsigned int size, int max_retries);
+ int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
+ int size, bool need_invalidate_rkey,
+ unsigned int remote_key);
+ int (*rdma_read)(struct ksmbd_transport *t,
+ void *buf, unsigned int len,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len);
+ int (*rdma_write)(struct ksmbd_transport *t,
+ void *buf, unsigned int len,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len);
+};
+
+struct ksmbd_transport {
+ struct ksmbd_conn *conn;
+ struct ksmbd_transport_ops *ops;
+ struct task_struct *handler;
+};
+
+#define KSMBD_TCP_RECV_TIMEOUT (7 * HZ)
+#define KSMBD_TCP_SEND_TIMEOUT (5 * HZ)
+#define KSMBD_TCP_PEER_SOCKADDR(c) ((struct sockaddr *)&((c)->peer_addr))
+
+extern struct list_head conn_list;
+extern struct rw_semaphore conn_list_lock;
+
+bool ksmbd_conn_alive(struct ksmbd_conn *conn);
+void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id);
+struct ksmbd_conn *ksmbd_conn_alloc(void);
+void ksmbd_conn_free(struct ksmbd_conn *conn);
+bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
+int ksmbd_conn_write(struct ksmbd_work *work);
+int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len);
+int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len);
+void ksmbd_conn_enqueue_request(struct ksmbd_work *work);
+int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
+void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);
+int ksmbd_conn_handler_loop(void *p);
+int ksmbd_conn_transport_init(void);
+void ksmbd_conn_transport_destroy(void);
+void ksmbd_conn_lock(struct ksmbd_conn *conn);
+void ksmbd_conn_unlock(struct ksmbd_conn *conn);
+
+/*
+ * WARNING
+ *
+ * This is a hack. We will move status to a proper place once we land
+ * a multi-sessions support.
+ */
+static inline bool ksmbd_conn_good(struct ksmbd_conn *conn)
+{
+ return READ_ONCE(conn->status) == KSMBD_SESS_GOOD;
+}
+
+static inline bool ksmbd_conn_need_negotiate(struct ksmbd_conn *conn)
+{
+ return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE;
+}
+
+static inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn)
+{
+ return READ_ONCE(conn->status) == KSMBD_SESS_NEED_RECONNECT;
+}
+
+static inline bool ksmbd_conn_exiting(struct ksmbd_conn *conn)
+{
+ return READ_ONCE(conn->status) == KSMBD_SESS_EXITING;
+}
+
+static inline bool ksmbd_conn_releasing(struct ksmbd_conn *conn)
+{
+ return READ_ONCE(conn->status) == KSMBD_SESS_RELEASING;
+}
+
+static inline void ksmbd_conn_set_new(struct ksmbd_conn *conn)
+{
+ WRITE_ONCE(conn->status, KSMBD_SESS_NEW);
+}
+
+static inline void ksmbd_conn_set_good(struct ksmbd_conn *conn)
+{
+ WRITE_ONCE(conn->status, KSMBD_SESS_GOOD);
+}
+
+static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_conn *conn)
+{
+ WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE);
+}
+
+static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn)
+{
+ WRITE_ONCE(conn->status, KSMBD_SESS_NEED_RECONNECT);
+}
+
+static inline void ksmbd_conn_set_exiting(struct ksmbd_conn *conn)
+{
+ WRITE_ONCE(conn->status, KSMBD_SESS_EXITING);
+}
+
+static inline void ksmbd_conn_set_releasing(struct ksmbd_conn *conn)
+{
+ WRITE_ONCE(conn->status, KSMBD_SESS_RELEASING);
+}
+
+void ksmbd_all_conn_set_status(u64 sess_id, u32 status);
+#endif /* __CONNECTION_H__ */
diff --git a/fs/smb/server/crypto_ctx.c b/fs/smb/server/crypto_ctx.c
new file mode 100644
index 000000000000..81488d04199d
--- /dev/null
+++ b/fs/smb/server/crypto_ctx.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include "glob.h"
+#include "crypto_ctx.h"
+
+struct crypto_ctx_list {
+ spinlock_t ctx_lock;
+ int avail_ctx;
+ struct list_head idle_ctx;
+ wait_queue_head_t ctx_wait;
+};
+
+static struct crypto_ctx_list ctx_list;
+
+static inline void free_aead(struct crypto_aead *aead)
+{
+ if (aead)
+ crypto_free_aead(aead);
+}
+
+static void free_shash(struct shash_desc *shash)
+{
+ if (shash) {
+ crypto_free_shash(shash->tfm);
+ kfree(shash);
+ }
+}
+
+static struct crypto_aead *alloc_aead(int id)
+{
+ struct crypto_aead *tfm = NULL;
+
+ switch (id) {
+ case CRYPTO_AEAD_AES_GCM:
+ tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
+ break;
+ case CRYPTO_AEAD_AES_CCM:
+ tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
+ break;
+ default:
+ pr_err("Does not support encrypt ahead(id : %d)\n", id);
+ return NULL;
+ }
+
+ if (IS_ERR(tfm)) {
+ pr_err("Failed to alloc encrypt aead : %ld\n", PTR_ERR(tfm));
+ return NULL;
+ }
+
+ return tfm;
+}
+
+static struct shash_desc *alloc_shash_desc(int id)
+{
+ struct crypto_shash *tfm = NULL;
+ struct shash_desc *shash;
+
+ switch (id) {
+ case CRYPTO_SHASH_HMACMD5:
+ tfm = crypto_alloc_shash("hmac(md5)", 0, 0);
+ break;
+ case CRYPTO_SHASH_HMACSHA256:
+ tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+ break;
+ case CRYPTO_SHASH_CMACAES:
+ tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
+ break;
+ case CRYPTO_SHASH_SHA256:
+ tfm = crypto_alloc_shash("sha256", 0, 0);
+ break;
+ case CRYPTO_SHASH_SHA512:
+ tfm = crypto_alloc_shash("sha512", 0, 0);
+ break;
+ default:
+ return NULL;
+ }
+
+ if (IS_ERR(tfm))
+ return NULL;
+
+ shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
+ GFP_KERNEL);
+ if (!shash)
+ crypto_free_shash(tfm);
+ else
+ shash->tfm = tfm;
+ return shash;
+}
+
+static void ctx_free(struct ksmbd_crypto_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < CRYPTO_SHASH_MAX; i++)
+ free_shash(ctx->desc[i]);
+ for (i = 0; i < CRYPTO_AEAD_MAX; i++)
+ free_aead(ctx->ccmaes[i]);
+ kfree(ctx);
+}
+
+static struct ksmbd_crypto_ctx *ksmbd_find_crypto_ctx(void)
+{
+ struct ksmbd_crypto_ctx *ctx;
+
+ while (1) {
+ spin_lock(&ctx_list.ctx_lock);
+ if (!list_empty(&ctx_list.idle_ctx)) {
+ ctx = list_entry(ctx_list.idle_ctx.next,
+ struct ksmbd_crypto_ctx,
+ list);
+ list_del(&ctx->list);
+ spin_unlock(&ctx_list.ctx_lock);
+ return ctx;
+ }
+
+ if (ctx_list.avail_ctx > num_online_cpus()) {
+ spin_unlock(&ctx_list.ctx_lock);
+ wait_event(ctx_list.ctx_wait,
+ !list_empty(&ctx_list.idle_ctx));
+ continue;
+ }
+
+ ctx_list.avail_ctx++;
+ spin_unlock(&ctx_list.ctx_lock);
+
+ ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
+ if (!ctx) {
+ spin_lock(&ctx_list.ctx_lock);
+ ctx_list.avail_ctx--;
+ spin_unlock(&ctx_list.ctx_lock);
+ wait_event(ctx_list.ctx_wait,
+ !list_empty(&ctx_list.idle_ctx));
+ continue;
+ }
+ break;
+ }
+ return ctx;
+}
+
+void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx)
+{
+ if (!ctx)
+ return;
+
+ spin_lock(&ctx_list.ctx_lock);
+ if (ctx_list.avail_ctx <= num_online_cpus()) {
+ list_add(&ctx->list, &ctx_list.idle_ctx);
+ spin_unlock(&ctx_list.ctx_lock);
+ wake_up(&ctx_list.ctx_wait);
+ return;
+ }
+
+ ctx_list.avail_ctx--;
+ spin_unlock(&ctx_list.ctx_lock);
+ ctx_free(ctx);
+}
+
+static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id)
+{
+ struct ksmbd_crypto_ctx *ctx;
+
+ if (id >= CRYPTO_SHASH_MAX)
+ return NULL;
+
+ ctx = ksmbd_find_crypto_ctx();
+ if (ctx->desc[id])
+ return ctx;
+
+ ctx->desc[id] = alloc_shash_desc(id);
+ if (ctx->desc[id])
+ return ctx;
+ ksmbd_release_crypto_ctx(ctx);
+ return NULL;
+}
+
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void)
+{
+ return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACMD5);
+}
+
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void)
+{
+ return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACSHA256);
+}
+
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void)
+{
+ return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES);
+}
+
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void)
+{
+ return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA256);
+}
+
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void)
+{
+ return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512);
+}
+
+static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
+{
+ struct ksmbd_crypto_ctx *ctx;
+
+ if (id >= CRYPTO_AEAD_MAX)
+ return NULL;
+
+ ctx = ksmbd_find_crypto_ctx();
+ if (ctx->ccmaes[id])
+ return ctx;
+
+ ctx->ccmaes[id] = alloc_aead(id);
+ if (ctx->ccmaes[id])
+ return ctx;
+ ksmbd_release_crypto_ctx(ctx);
+ return NULL;
+}
+
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void)
+{
+ return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_GCM);
+}
+
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void)
+{
+ return ____crypto_aead_ctx_find(CRYPTO_AEAD_AES_CCM);
+}
+
+void ksmbd_crypto_destroy(void)
+{
+ struct ksmbd_crypto_ctx *ctx;
+
+ while (!list_empty(&ctx_list.idle_ctx)) {
+ ctx = list_entry(ctx_list.idle_ctx.next,
+ struct ksmbd_crypto_ctx,
+ list);
+ list_del(&ctx->list);
+ ctx_free(ctx);
+ }
+}
+
+int ksmbd_crypto_create(void)
+{
+ struct ksmbd_crypto_ctx *ctx;
+
+ spin_lock_init(&ctx_list.ctx_lock);
+ INIT_LIST_HEAD(&ctx_list.idle_ctx);
+ init_waitqueue_head(&ctx_list.ctx_wait);
+ ctx_list.avail_ctx = 1;
+
+ ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ list_add(&ctx->list, &ctx_list.idle_ctx);
+ return 0;
+}
diff --git a/fs/smb/server/crypto_ctx.h b/fs/smb/server/crypto_ctx.h
new file mode 100644
index 000000000000..4a367c62f653
--- /dev/null
+++ b/fs/smb/server/crypto_ctx.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __CRYPTO_CTX_H__
+#define __CRYPTO_CTX_H__
+
+#include <crypto/hash.h>
+#include <crypto/aead.h>
+
+enum {
+ CRYPTO_SHASH_HMACMD5 = 0,
+ CRYPTO_SHASH_HMACSHA256,
+ CRYPTO_SHASH_CMACAES,
+ CRYPTO_SHASH_SHA256,
+ CRYPTO_SHASH_SHA512,
+ CRYPTO_SHASH_MAX,
+};
+
+enum {
+ CRYPTO_AEAD_AES_GCM = 16,
+ CRYPTO_AEAD_AES_CCM,
+ CRYPTO_AEAD_MAX,
+};
+
+enum {
+ CRYPTO_BLK_ECBDES = 32,
+ CRYPTO_BLK_MAX,
+};
+
+struct ksmbd_crypto_ctx {
+ struct list_head list;
+
+ struct shash_desc *desc[CRYPTO_SHASH_MAX];
+ struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX];
+};
+
+#define CRYPTO_HMACMD5(c) ((c)->desc[CRYPTO_SHASH_HMACMD5])
+#define CRYPTO_HMACSHA256(c) ((c)->desc[CRYPTO_SHASH_HMACSHA256])
+#define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES])
+#define CRYPTO_SHA256(c) ((c)->desc[CRYPTO_SHASH_SHA256])
+#define CRYPTO_SHA512(c) ((c)->desc[CRYPTO_SHASH_SHA512])
+
+#define CRYPTO_HMACMD5_TFM(c) ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm)
+#define CRYPTO_HMACSHA256_TFM(c)\
+ ((c)->desc[CRYPTO_SHASH_HMACSHA256]->tfm)
+#define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm)
+#define CRYPTO_SHA256_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA256]->tfm)
+#define CRYPTO_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm)
+
+#define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM])
+#define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM])
+
+void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx);
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void);
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void);
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void);
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void);
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void);
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void);
+struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
+void ksmbd_crypto_destroy(void);
+int ksmbd_crypto_create(void);
+
+#endif /* __CRYPTO_CTX_H__ */
diff --git a/fs/smb/server/glob.h b/fs/smb/server/glob.h
new file mode 100644
index 000000000000..5b8f3e0ebdb3
--- /dev/null
+++ b/fs/smb/server/glob.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __KSMBD_GLOB_H
+#define __KSMBD_GLOB_H
+
+#include <linux/ctype.h>
+
+#include "unicode.h"
+#include "vfs_cache.h"
+
+#define KSMBD_VERSION "3.4.2"
+
+extern int ksmbd_debug_types;
+
+#define KSMBD_DEBUG_SMB BIT(0)
+#define KSMBD_DEBUG_AUTH BIT(1)
+#define KSMBD_DEBUG_VFS BIT(2)
+#define KSMBD_DEBUG_OPLOCK BIT(3)
+#define KSMBD_DEBUG_IPC BIT(4)
+#define KSMBD_DEBUG_CONN BIT(5)
+#define KSMBD_DEBUG_RDMA BIT(6)
+#define KSMBD_DEBUG_ALL (KSMBD_DEBUG_SMB | KSMBD_DEBUG_AUTH | \
+ KSMBD_DEBUG_VFS | KSMBD_DEBUG_OPLOCK | \
+ KSMBD_DEBUG_IPC | KSMBD_DEBUG_CONN | \
+ KSMBD_DEBUG_RDMA)
+
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+
+#ifdef SUBMOD_NAME
+#define pr_fmt(fmt) "ksmbd: " SUBMOD_NAME ": " fmt
+#else
+#define pr_fmt(fmt) "ksmbd: " fmt
+#endif
+
+#define ksmbd_debug(type, fmt, ...) \
+ do { \
+ if (ksmbd_debug_types & KSMBD_DEBUG_##type) \
+ pr_info(fmt, ##__VA_ARGS__); \
+ } while (0)
+
+#define UNICODE_LEN(x) ((x) * 2)
+
+#endif /* __KSMBD_GLOB_H */
diff --git a/fs/smb/server/ksmbd_netlink.h b/fs/smb/server/ksmbd_netlink.h
new file mode 100644
index 000000000000..ce866ff159bf
--- /dev/null
+++ b/fs/smb/server/ksmbd_netlink.h
@@ -0,0 +1,412 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ *
+ * linux-ksmbd-devel@lists.sourceforge.net
+ */
+
+#ifndef _LINUX_KSMBD_SERVER_H
+#define _LINUX_KSMBD_SERVER_H
+
+#include <linux/types.h>
+
+/*
+ * This is a userspace ABI to communicate data between ksmbd and user IPC
+ * daemon using netlink. This is added to track and cache user account DB
+ * and share configuration info from userspace.
+ *
+ * - KSMBD_EVENT_HEARTBEAT_REQUEST(ksmbd_heartbeat)
+ * This event is to check whether user IPC daemon is alive. If user IPC
+ * daemon is dead, ksmbd keep existing connection till disconnecting and
+ * new connection will be denied.
+ *
+ * - KSMBD_EVENT_STARTING_UP(ksmbd_startup_request)
+ * This event is to receive the information that initializes the ksmbd
+ * server from the user IPC daemon and to start the server. The global
+ * section parameters are given from smb.conf as initialization
+ * information.
+ *
+ * - KSMBD_EVENT_SHUTTING_DOWN(ksmbd_shutdown_request)
+ * This event is to shutdown ksmbd server.
+ *
+ * - KSMBD_EVENT_LOGIN_REQUEST/RESPONSE(ksmbd_login_request/response)
+ * This event is to get user account info to user IPC daemon.
+ *
+ * - KSMBD_EVENT_SHARE_CONFIG_REQUEST/RESPONSE(ksmbd_share_config_request/response)
+ * This event is to get net share configuration info.
+ *
+ * - KSMBD_EVENT_TREE_CONNECT_REQUEST/RESPONSE(ksmbd_tree_connect_request/response)
+ * This event is to get session and tree connect info.
+ *
+ * - KSMBD_EVENT_TREE_DISCONNECT_REQUEST(ksmbd_tree_disconnect_request)
+ * This event is to send tree disconnect info to user IPC daemon.
+ *
+ * - KSMBD_EVENT_LOGOUT_REQUEST(ksmbd_logout_request)
+ * This event is to send logout request to user IPC daemon.
+ *
+ * - KSMBD_EVENT_RPC_REQUEST/RESPONSE(ksmbd_rpc_command)
+ * This event is to make DCE/RPC request like srvsvc, wkssvc, lsarpc,
+ * samr to be processed in userspace.
+ *
+ * - KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST/RESPONSE(ksmbd_spnego_authen_request/response)
+ * This event is to make kerberos authentication to be processed in
+ * userspace.
+ */
+
+#define KSMBD_GENL_NAME "SMBD_GENL"
+#define KSMBD_GENL_VERSION 0x01
+
+#define KSMBD_REQ_MAX_ACCOUNT_NAME_SZ 48
+#define KSMBD_REQ_MAX_HASH_SZ 18
+#define KSMBD_REQ_MAX_SHARE_NAME 64
+
+/*
+ * IPC heartbeat frame to check whether user IPC daemon is alive.
+ */
+struct ksmbd_heartbeat {
+ __u32 handle;
+};
+
+/*
+ * Global config flags.
+ */
+#define KSMBD_GLOBAL_FLAG_INVALID (0)
+#define KSMBD_GLOBAL_FLAG_SMB2_LEASES BIT(0)
+#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION BIT(1)
+#define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL BIT(2)
+
+/*
+ * IPC request for ksmbd server startup
+ */
+struct ksmbd_startup_request {
+ __u32 flags; /* Flags for global config */
+ __s32 signing; /* Signing enabled */
+ __s8 min_prot[16]; /* The minimum SMB protocol version */
+ __s8 max_prot[16]; /* The maximum SMB protocol version */
+ __s8 netbios_name[16];
+ __s8 work_group[64]; /* Workgroup */
+ __s8 server_string[64]; /* Server string */
+ __u16 tcp_port; /* tcp port */
+ __u16 ipc_timeout; /*
+ * specifies the number of seconds
+ * server will wait for the userspace to
+ * reply to heartbeat frames.
+ */
+ __u32 deadtime; /* Number of minutes of inactivity */
+ __u32 file_max; /* Limits the maximum number of open files */
+ __u32 smb2_max_write; /* MAX write size */
+ __u32 smb2_max_read; /* MAX read size */
+ __u32 smb2_max_trans; /* MAX trans size */
+ __u32 share_fake_fscaps; /*
+ * Support some special application that
+ * makes QFSINFO calls to check whether
+ * we set the SPARSE_FILES bit (0x40).
+ */
+ __u32 sub_auth[3]; /* Subauth value for Security ID */
+ __u32 smb2_max_credits; /* MAX credits */
+ __u32 smbd_max_io_size; /* smbd read write size */
+ __u32 max_connections; /* Number of maximum simultaneous connections */
+ __u32 reserved[126]; /* Reserved room */
+ __u32 ifc_list_sz; /* interfaces list size */
+ __s8 ____payload[];
+};
+
+#define KSMBD_STARTUP_CONFIG_INTERFACES(s) ((s)->____payload)
+
+/*
+ * IPC request to shutdown ksmbd server.
+ */
+struct ksmbd_shutdown_request {
+ __s32 reserved[16];
+};
+
+/*
+ * IPC user login request.
+ */
+struct ksmbd_login_request {
+ __u32 handle;
+ __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
+ __u32 reserved[16]; /* Reserved room */
+};
+
+/*
+ * IPC user login response.
+ */
+struct ksmbd_login_response {
+ __u32 handle;
+ __u32 gid; /* group id */
+ __u32 uid; /* user id */
+ __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
+ __u16 status;
+ __u16 hash_sz; /* hash size */
+ __s8 hash[KSMBD_REQ_MAX_HASH_SZ]; /* password hash */
+ __u32 reserved[16]; /* Reserved room */
+};
+
+/*
+ * IPC request to fetch net share config.
+ */
+struct ksmbd_share_config_request {
+ __u32 handle;
+ __s8 share_name[KSMBD_REQ_MAX_SHARE_NAME]; /* share name */
+ __u32 reserved[16]; /* Reserved room */
+};
+
+/*
+ * IPC response to the net share config request.
+ */
+struct ksmbd_share_config_response {
+ __u32 handle;
+ __u32 flags;
+ __u16 create_mask;
+ __u16 directory_mask;
+ __u16 force_create_mode;
+ __u16 force_directory_mode;
+ __u16 force_uid;
+ __u16 force_gid;
+ __s8 share_name[KSMBD_REQ_MAX_SHARE_NAME];
+ __u32 reserved[112]; /* Reserved room */
+ __u32 veto_list_sz;
+ __s8 ____payload[];
+};
+
+#define KSMBD_SHARE_CONFIG_VETO_LIST(s) ((s)->____payload)
+
+static inline char *
+ksmbd_share_config_path(struct ksmbd_share_config_response *sc)
+{
+ char *p = sc->____payload;
+
+ if (sc->veto_list_sz)
+ p += sc->veto_list_sz + 1;
+
+ return p;
+}
+
+/*
+ * IPC request for tree connection. This request include session and tree
+ * connect info from client.
+ */
+struct ksmbd_tree_connect_request {
+ __u32 handle;
+ __u16 account_flags;
+ __u16 flags;
+ __u64 session_id;
+ __u64 connect_id;
+ __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ];
+ __s8 share[KSMBD_REQ_MAX_SHARE_NAME];
+ __s8 peer_addr[64];
+ __u32 reserved[16]; /* Reserved room */
+};
+
+/*
+ * IPC Response structure for tree connection.
+ */
+struct ksmbd_tree_connect_response {
+ __u32 handle;
+ __u16 status;
+ __u16 connection_flags;
+ __u32 reserved[16]; /* Reserved room */
+};
+
+/*
+ * IPC Request struture to disconnect tree connection.
+ */
+struct ksmbd_tree_disconnect_request {
+ __u64 session_id; /* session id */
+ __u64 connect_id; /* tree connection id */
+ __u32 reserved[16]; /* Reserved room */
+};
+
+/*
+ * IPC Response structure to logout user account.
+ */
+struct ksmbd_logout_request {
+ __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */
+ __u32 account_flags;
+ __u32 reserved[16]; /* Reserved room */
+};
+
+/*
+ * RPC command structure to send rpc request like srvsvc or wkssvc to
+ * IPC user daemon.
+ */
+struct ksmbd_rpc_command {
+ __u32 handle;
+ __u32 flags;
+ __u32 payload_sz;
+ __u8 payload[];
+};
+
+/*
+ * IPC Request Kerberos authentication
+ */
+struct ksmbd_spnego_authen_request {
+ __u32 handle;
+ __u16 spnego_blob_len; /* the length of spnego_blob */
+ __u8 spnego_blob[]; /*
+ * the GSS token from SecurityBuffer of
+ * SMB2 SESSION SETUP request
+ */
+};
+
+/*
+ * Response data which includes the GSS token and the session key generated by
+ * user daemon.
+ */
+struct ksmbd_spnego_authen_response {
+ __u32 handle;
+ struct ksmbd_login_response login_response; /*
+ * the login response with
+ * a user identified by the
+ * GSS token from a client
+ */
+ __u16 session_key_len; /* the length of the session key */
+ __u16 spnego_blob_len; /*
+ * the length of the GSS token which will be
+ * stored in SecurityBuffer of SMB2 SESSION
+ * SETUP response
+ */
+ __u8 payload[]; /* session key + AP_REP */
+};
+
+/*
+ * This also used as NETLINK attribute type value.
+ *
+ * NOTE:
+ * Response message type value should be equal to
+ * request message type value + 1.
+ */
+enum ksmbd_event {
+ KSMBD_EVENT_UNSPEC = 0,
+ KSMBD_EVENT_HEARTBEAT_REQUEST,
+
+ KSMBD_EVENT_STARTING_UP,
+ KSMBD_EVENT_SHUTTING_DOWN,
+
+ KSMBD_EVENT_LOGIN_REQUEST,
+ KSMBD_EVENT_LOGIN_RESPONSE = 5,
+
+ KSMBD_EVENT_SHARE_CONFIG_REQUEST,
+ KSMBD_EVENT_SHARE_CONFIG_RESPONSE,
+
+ KSMBD_EVENT_TREE_CONNECT_REQUEST,
+ KSMBD_EVENT_TREE_CONNECT_RESPONSE,
+
+ KSMBD_EVENT_TREE_DISCONNECT_REQUEST = 10,
+
+ KSMBD_EVENT_LOGOUT_REQUEST,
+
+ KSMBD_EVENT_RPC_REQUEST,
+ KSMBD_EVENT_RPC_RESPONSE,
+
+ KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST,
+ KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE = 15,
+
+ KSMBD_EVENT_MAX
+};
+
+/*
+ * Enumeration for IPC tree connect status.
+ */
+enum KSMBD_TREE_CONN_STATUS {
+ KSMBD_TREE_CONN_STATUS_OK = 0,
+ KSMBD_TREE_CONN_STATUS_NOMEM,
+ KSMBD_TREE_CONN_STATUS_NO_SHARE,
+ KSMBD_TREE_CONN_STATUS_NO_USER,
+ KSMBD_TREE_CONN_STATUS_INVALID_USER,
+ KSMBD_TREE_CONN_STATUS_HOST_DENIED = 5,
+ KSMBD_TREE_CONN_STATUS_CONN_EXIST,
+ KSMBD_TREE_CONN_STATUS_TOO_MANY_CONNS,
+ KSMBD_TREE_CONN_STATUS_TOO_MANY_SESSIONS,
+ KSMBD_TREE_CONN_STATUS_ERROR,
+};
+
+/*
+ * User config flags.
+ */
+#define KSMBD_USER_FLAG_INVALID (0)
+#define KSMBD_USER_FLAG_OK BIT(0)
+#define KSMBD_USER_FLAG_BAD_PASSWORD BIT(1)
+#define KSMBD_USER_FLAG_BAD_UID BIT(2)
+#define KSMBD_USER_FLAG_BAD_USER BIT(3)
+#define KSMBD_USER_FLAG_GUEST_ACCOUNT BIT(4)
+#define KSMBD_USER_FLAG_DELAY_SESSION BIT(5)
+
+/*
+ * Share config flags.
+ */
+#define KSMBD_SHARE_FLAG_INVALID (0)
+#define KSMBD_SHARE_FLAG_AVAILABLE BIT(0)
+#define KSMBD_SHARE_FLAG_BROWSEABLE BIT(1)
+#define KSMBD_SHARE_FLAG_WRITEABLE BIT(2)
+#define KSMBD_SHARE_FLAG_READONLY BIT(3)
+#define KSMBD_SHARE_FLAG_GUEST_OK BIT(4)
+#define KSMBD_SHARE_FLAG_GUEST_ONLY BIT(5)
+#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS BIT(6)
+#define KSMBD_SHARE_FLAG_OPLOCKS BIT(7)
+#define KSMBD_SHARE_FLAG_PIPE BIT(8)
+#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES BIT(9)
+#define KSMBD_SHARE_FLAG_INHERIT_OWNER BIT(10)
+#define KSMBD_SHARE_FLAG_STREAMS BIT(11)
+#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12)
+#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13)
+#define KSMBD_SHARE_FLAG_UPDATE BIT(14)
+
+/*
+ * Tree connect request flags.
+ */
+#define KSMBD_TREE_CONN_FLAG_REQUEST_SMB1 (0)
+#define KSMBD_TREE_CONN_FLAG_REQUEST_IPV6 BIT(0)
+#define KSMBD_TREE_CONN_FLAG_REQUEST_SMB2 BIT(1)
+
+/*
+ * Tree connect flags.
+ */
+#define KSMBD_TREE_CONN_FLAG_GUEST_ACCOUNT BIT(0)
+#define KSMBD_TREE_CONN_FLAG_READ_ONLY BIT(1)
+#define KSMBD_TREE_CONN_FLAG_WRITABLE BIT(2)
+#define KSMBD_TREE_CONN_FLAG_ADMIN_ACCOUNT BIT(3)
+#define KSMBD_TREE_CONN_FLAG_UPDATE BIT(4)
+
+/*
+ * RPC over IPC.
+ */
+#define KSMBD_RPC_METHOD_RETURN BIT(0)
+#define KSMBD_RPC_SRVSVC_METHOD_INVOKE BIT(1)
+#define KSMBD_RPC_SRVSVC_METHOD_RETURN (KSMBD_RPC_SRVSVC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
+#define KSMBD_RPC_WKSSVC_METHOD_INVOKE BIT(2)
+#define KSMBD_RPC_WKSSVC_METHOD_RETURN (KSMBD_RPC_WKSSVC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
+#define KSMBD_RPC_IOCTL_METHOD (BIT(3) | KSMBD_RPC_METHOD_RETURN)
+#define KSMBD_RPC_OPEN_METHOD BIT(4)
+#define KSMBD_RPC_WRITE_METHOD BIT(5)
+#define KSMBD_RPC_READ_METHOD (BIT(6) | KSMBD_RPC_METHOD_RETURN)
+#define KSMBD_RPC_CLOSE_METHOD BIT(7)
+#define KSMBD_RPC_RAP_METHOD (BIT(8) | KSMBD_RPC_METHOD_RETURN)
+#define KSMBD_RPC_RESTRICTED_CONTEXT BIT(9)
+#define KSMBD_RPC_SAMR_METHOD_INVOKE BIT(10)
+#define KSMBD_RPC_SAMR_METHOD_RETURN (KSMBD_RPC_SAMR_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
+#define KSMBD_RPC_LSARPC_METHOD_INVOKE BIT(11)
+#define KSMBD_RPC_LSARPC_METHOD_RETURN (KSMBD_RPC_LSARPC_METHOD_INVOKE | KSMBD_RPC_METHOD_RETURN)
+
+/*
+ * RPC status definitions.
+ */
+#define KSMBD_RPC_OK 0
+#define KSMBD_RPC_EBAD_FUNC 0x00000001
+#define KSMBD_RPC_EACCESS_DENIED 0x00000005
+#define KSMBD_RPC_EBAD_FID 0x00000006
+#define KSMBD_RPC_ENOMEM 0x00000008
+#define KSMBD_RPC_EBAD_DATA 0x0000000D
+#define KSMBD_RPC_ENOTIMPLEMENTED 0x00000040
+#define KSMBD_RPC_EINVALID_PARAMETER 0x00000057
+#define KSMBD_RPC_EMORE_DATA 0x000000EA
+#define KSMBD_RPC_EINVALID_LEVEL 0x0000007C
+#define KSMBD_RPC_SOME_NOT_MAPPED 0x00000107
+
+#define KSMBD_CONFIG_OPT_DISABLED 0
+#define KSMBD_CONFIG_OPT_ENABLED 1
+#define KSMBD_CONFIG_OPT_AUTO 2
+#define KSMBD_CONFIG_OPT_MANDATORY 3
+
+#endif /* _LINUX_KSMBD_SERVER_H */
diff --git a/fs/smb/server/ksmbd_spnego_negtokeninit.asn1 b/fs/smb/server/ksmbd_spnego_negtokeninit.asn1
new file mode 100644
index 000000000000..0065f191b54b
--- /dev/null
+++ b/fs/smb/server/ksmbd_spnego_negtokeninit.asn1
@@ -0,0 +1,31 @@
+GSSAPI ::=
+ [APPLICATION 0] IMPLICIT SEQUENCE {
+ thisMech
+ OBJECT IDENTIFIER ({ksmbd_gssapi_this_mech}),
+ negotiationToken
+ NegotiationToken
+ }
+
+MechType ::= OBJECT IDENTIFIER ({ksmbd_neg_token_init_mech_type})
+
+MechTypeList ::= SEQUENCE OF MechType
+
+NegTokenInit ::=
+ SEQUENCE {
+ mechTypes
+ [0] MechTypeList,
+ reqFlags
+ [1] BIT STRING OPTIONAL,
+ mechToken
+ [2] OCTET STRING OPTIONAL ({ksmbd_neg_token_init_mech_token}),
+ mechListMIC
+ [3] OCTET STRING OPTIONAL
+ }
+
+NegotiationToken ::=
+ CHOICE {
+ negTokenInit
+ [0] NegTokenInit,
+ negTokenTarg
+ [1] ANY
+ }
diff --git a/fs/smb/server/ksmbd_spnego_negtokentarg.asn1 b/fs/smb/server/ksmbd_spnego_negtokentarg.asn1
new file mode 100644
index 000000000000..1151933e7b9c
--- /dev/null
+++ b/fs/smb/server/ksmbd_spnego_negtokentarg.asn1
@@ -0,0 +1,19 @@
+GSSAPI ::=
+ CHOICE {
+ negTokenInit
+ [0] ANY,
+ negTokenTarg
+ [1] NegTokenTarg
+ }
+
+NegTokenTarg ::=
+ SEQUENCE {
+ negResult
+ [0] ENUMERATED OPTIONAL,
+ supportedMech
+ [1] OBJECT IDENTIFIER OPTIONAL,
+ responseToken
+ [2] OCTET STRING OPTIONAL ({ksmbd_neg_token_targ_resp_token}),
+ mechListMIC
+ [3] OCTET STRING OPTIONAL
+ }
diff --git a/fs/smb/server/ksmbd_work.c b/fs/smb/server/ksmbd_work.c
new file mode 100644
index 000000000000..14b9caebf7a4
--- /dev/null
+++ b/fs/smb/server/ksmbd_work.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include "server.h"
+#include "connection.h"
+#include "ksmbd_work.h"
+#include "mgmt/ksmbd_ida.h"
+
+static struct kmem_cache *work_cache;
+static struct workqueue_struct *ksmbd_wq;
+
+struct ksmbd_work *ksmbd_alloc_work_struct(void)
+{
+ struct ksmbd_work *work = kmem_cache_zalloc(work_cache, GFP_KERNEL);
+
+ if (work) {
+ work->compound_fid = KSMBD_NO_FID;
+ work->compound_pfid = KSMBD_NO_FID;
+ INIT_LIST_HEAD(&work->request_entry);
+ INIT_LIST_HEAD(&work->async_request_entry);
+ INIT_LIST_HEAD(&work->fp_entry);
+ INIT_LIST_HEAD(&work->interim_entry);
+ }
+ return work;
+}
+
+void ksmbd_free_work_struct(struct ksmbd_work *work)
+{
+ WARN_ON(work->saved_cred != NULL);
+
+ kvfree(work->response_buf);
+ kvfree(work->aux_payload_buf);
+ kfree(work->tr_buf);
+ kvfree(work->request_buf);
+ if (work->async_id)
+ ksmbd_release_id(&work->conn->async_ida, work->async_id);
+ kmem_cache_free(work_cache, work);
+}
+
+void ksmbd_work_pool_destroy(void)
+{
+ kmem_cache_destroy(work_cache);
+}
+
+int ksmbd_work_pool_init(void)
+{
+ work_cache = kmem_cache_create("ksmbd_work_cache",
+ sizeof(struct ksmbd_work), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!work_cache)
+ return -ENOMEM;
+ return 0;
+}
+
+int ksmbd_workqueue_init(void)
+{
+ ksmbd_wq = alloc_workqueue("ksmbd-io", 0, 0);
+ if (!ksmbd_wq)
+ return -ENOMEM;
+ return 0;
+}
+
+void ksmbd_workqueue_destroy(void)
+{
+ destroy_workqueue(ksmbd_wq);
+ ksmbd_wq = NULL;
+}
+
+bool ksmbd_queue_work(struct ksmbd_work *work)
+{
+ return queue_work(ksmbd_wq, &work->work);
+}
diff --git a/fs/smb/server/ksmbd_work.h b/fs/smb/server/ksmbd_work.h
new file mode 100644
index 000000000000..5ece58e40c97
--- /dev/null
+++ b/fs/smb/server/ksmbd_work.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __KSMBD_WORK_H__
+#define __KSMBD_WORK_H__
+
+#include <linux/ctype.h>
+#include <linux/workqueue.h>
+
+struct ksmbd_conn;
+struct ksmbd_session;
+struct ksmbd_tree_connect;
+
+enum {
+ KSMBD_WORK_ACTIVE = 0,
+ KSMBD_WORK_CANCELLED,
+ KSMBD_WORK_CLOSED,
+};
+
+/* one of these for every pending CIFS request at the connection */
+struct ksmbd_work {
+ /* Server corresponding to this mid */
+ struct ksmbd_conn *conn;
+ struct ksmbd_session *sess;
+ struct ksmbd_tree_connect *tcon;
+
+ /* Pointer to received SMB header */
+ void *request_buf;
+ /* Response buffer */
+ void *response_buf;
+
+ /* Read data buffer */
+ void *aux_payload_buf;
+
+ /* Next cmd hdr in compound req buf*/
+ int next_smb2_rcv_hdr_off;
+ /* Next cmd hdr in compound rsp buf*/
+ int next_smb2_rsp_hdr_off;
+
+ /*
+ * Current Local FID assigned compound response if SMB2 CREATE
+ * command is present in compound request
+ */
+ u64 compound_fid;
+ u64 compound_pfid;
+ u64 compound_sid;
+
+ const struct cred *saved_cred;
+
+ /* Number of granted credits */
+ unsigned int credits_granted;
+
+ /* response smb header size */
+ unsigned int resp_hdr_sz;
+ unsigned int response_sz;
+ /* Read data count */
+ unsigned int aux_payload_sz;
+
+ void *tr_buf;
+
+ unsigned char state;
+ /* Multiple responses for one request e.g. SMB ECHO */
+ bool multiRsp:1;
+ /* No response for cancelled request */
+ bool send_no_response:1;
+ /* Request is encrypted */
+ bool encrypted:1;
+ /* Is this SYNC or ASYNC ksmbd_work */
+ bool syncronous:1;
+ bool need_invalidate_rkey:1;
+
+ unsigned int remote_key;
+ /* cancel works */
+ int async_id;
+ void **cancel_argv;
+ void (*cancel_fn)(void **argv);
+
+ struct work_struct work;
+ /* List head at conn->requests */
+ struct list_head request_entry;
+ /* List head at conn->async_requests */
+ struct list_head async_request_entry;
+ struct list_head fp_entry;
+ struct list_head interim_entry;
+};
+
+/**
+ * ksmbd_resp_buf_next - Get next buffer on compound response.
+ * @work: smb work containing response buffer
+ */
+static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work)
+{
+ return work->response_buf + work->next_smb2_rsp_hdr_off + 4;
+}
+
+/**
+ * ksmbd_req_buf_next - Get next buffer on compound request.
+ * @work: smb work containing response buffer
+ */
+static inline void *ksmbd_req_buf_next(struct ksmbd_work *work)
+{
+ return work->request_buf + work->next_smb2_rcv_hdr_off + 4;
+}
+
+struct ksmbd_work *ksmbd_alloc_work_struct(void);
+void ksmbd_free_work_struct(struct ksmbd_work *work);
+
+void ksmbd_work_pool_destroy(void);
+int ksmbd_work_pool_init(void);
+
+int ksmbd_workqueue_init(void);
+void ksmbd_workqueue_destroy(void);
+bool ksmbd_queue_work(struct ksmbd_work *work);
+
+#endif /* __KSMBD_WORK_H__ */
diff --git a/fs/smb/server/mgmt/ksmbd_ida.c b/fs/smb/server/mgmt/ksmbd_ida.c
new file mode 100644
index 000000000000..54194d959a5e
--- /dev/null
+++ b/fs/smb/server/mgmt/ksmbd_ida.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include "ksmbd_ida.h"
+
+static inline int __acquire_id(struct ida *ida, int from, int to)
+{
+ return ida_simple_get(ida, from, to, GFP_KERNEL);
+}
+
+int ksmbd_acquire_smb2_tid(struct ida *ida)
+{
+ int id;
+
+ id = __acquire_id(ida, 1, 0xFFFFFFFF);
+
+ return id;
+}
+
+int ksmbd_acquire_smb2_uid(struct ida *ida)
+{
+ int id;
+
+ id = __acquire_id(ida, 1, 0);
+ if (id == 0xFFFE)
+ id = __acquire_id(ida, 1, 0);
+
+ return id;
+}
+
+int ksmbd_acquire_async_msg_id(struct ida *ida)
+{
+ return __acquire_id(ida, 1, 0);
+}
+
+int ksmbd_acquire_id(struct ida *ida)
+{
+ return __acquire_id(ida, 0, 0);
+}
+
+void ksmbd_release_id(struct ida *ida, int id)
+{
+ ida_simple_remove(ida, id);
+}
diff --git a/fs/smb/server/mgmt/ksmbd_ida.h b/fs/smb/server/mgmt/ksmbd_ida.h
new file mode 100644
index 000000000000..2bc07b16cfde
--- /dev/null
+++ b/fs/smb/server/mgmt/ksmbd_ida.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __KSMBD_IDA_MANAGEMENT_H__
+#define __KSMBD_IDA_MANAGEMENT_H__
+
+#include <linux/slab.h>
+#include <linux/idr.h>
+
+/*
+ * 2.2.1.6.7 TID Generation
+ * The value 0xFFFF MUST NOT be used as a valid TID. All other
+ * possible values for TID, including zero (0x0000), are valid.
+ * The value 0xFFFF is used to specify all TIDs or no TID,
+ * depending upon the context in which it is used.
+ */
+int ksmbd_acquire_smb2_tid(struct ida *ida);
+
+/*
+ * 2.2.1.6.8 UID Generation
+ * The value 0xFFFE was declared reserved in the LAN Manager 1.0
+ * documentation, so a value of 0xFFFE SHOULD NOT be used as a
+ * valid UID.<21> All other possible values for a UID, excluding
+ * zero (0x0000), are valid.
+ */
+int ksmbd_acquire_smb2_uid(struct ida *ida);
+int ksmbd_acquire_async_msg_id(struct ida *ida);
+
+int ksmbd_acquire_id(struct ida *ida);
+
+void ksmbd_release_id(struct ida *ida, int id);
+#endif /* __KSMBD_IDA_MANAGEMENT_H__ */
diff --git a/fs/smb/server/mgmt/share_config.c b/fs/smb/server/mgmt/share_config.c
new file mode 100644
index 000000000000..328a412259dc
--- /dev/null
+++ b/fs/smb/server/mgmt/share_config.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/slab.h>
+#include <linux/rwsem.h>
+#include <linux/parser.h>
+#include <linux/namei.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include "share_config.h"
+#include "user_config.h"
+#include "user_session.h"
+#include "../transport_ipc.h"
+#include "../misc.h"
+
+#define SHARE_HASH_BITS 3
+static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
+static DECLARE_RWSEM(shares_table_lock);
+
+struct ksmbd_veto_pattern {
+ char *pattern;
+ struct list_head list;
+};
+
+static unsigned int share_name_hash(const char *name)
+{
+ return jhash(name, strlen(name), 0);
+}
+
+static void kill_share(struct ksmbd_share_config *share)
+{
+ while (!list_empty(&share->veto_list)) {
+ struct ksmbd_veto_pattern *p;
+
+ p = list_entry(share->veto_list.next,
+ struct ksmbd_veto_pattern,
+ list);
+ list_del(&p->list);
+ kfree(p->pattern);
+ kfree(p);
+ }
+
+ if (share->path)
+ path_put(&share->vfs_path);
+ kfree(share->name);
+ kfree(share->path);
+ kfree(share);
+}
+
+void ksmbd_share_config_del(struct ksmbd_share_config *share)
+{
+ down_write(&shares_table_lock);
+ hash_del(&share->hlist);
+ up_write(&shares_table_lock);
+}
+
+void __ksmbd_share_config_put(struct ksmbd_share_config *share)
+{
+ ksmbd_share_config_del(share);
+ kill_share(share);
+}
+
+static struct ksmbd_share_config *
+__get_share_config(struct ksmbd_share_config *share)
+{
+ if (!atomic_inc_not_zero(&share->refcount))
+ return NULL;
+ return share;
+}
+
+static struct ksmbd_share_config *__share_lookup(const char *name)
+{
+ struct ksmbd_share_config *share;
+ unsigned int key = share_name_hash(name);
+
+ hash_for_each_possible(shares_table, share, hlist, key) {
+ if (!strcmp(name, share->name))
+ return share;
+ }
+ return NULL;
+}
+
+static int parse_veto_list(struct ksmbd_share_config *share,
+ char *veto_list,
+ int veto_list_sz)
+{
+ int sz = 0;
+
+ if (!veto_list_sz)
+ return 0;
+
+ while (veto_list_sz > 0) {
+ struct ksmbd_veto_pattern *p;
+
+ sz = strlen(veto_list);
+ if (!sz)
+ break;
+
+ p = kzalloc(sizeof(struct ksmbd_veto_pattern), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->pattern = kstrdup(veto_list, GFP_KERNEL);
+ if (!p->pattern) {
+ kfree(p);
+ return -ENOMEM;
+ }
+
+ list_add(&p->list, &share->veto_list);
+
+ veto_list += sz + 1;
+ veto_list_sz -= (sz + 1);
+ }
+
+ return 0;
+}
+
+static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
+ const char *name)
+{
+ struct ksmbd_share_config_response *resp;
+ struct ksmbd_share_config *share = NULL;
+ struct ksmbd_share_config *lookup;
+ int ret;
+
+ resp = ksmbd_ipc_share_config_request(name);
+ if (!resp)
+ return NULL;
+
+ if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
+ goto out;
+
+ if (*resp->share_name) {
+ char *cf_resp_name;
+ bool equal;
+
+ cf_resp_name = ksmbd_casefold_sharename(um, resp->share_name);
+ if (IS_ERR(cf_resp_name))
+ goto out;
+ equal = !strcmp(cf_resp_name, name);
+ kfree(cf_resp_name);
+ if (!equal)
+ goto out;
+ }
+
+ share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
+ if (!share)
+ goto out;
+
+ share->flags = resp->flags;
+ atomic_set(&share->refcount, 1);
+ INIT_LIST_HEAD(&share->veto_list);
+ share->name = kstrdup(name, GFP_KERNEL);
+
+ if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
+ share->path = kstrdup(ksmbd_share_config_path(resp),
+ GFP_KERNEL);
+ if (share->path)
+ share->path_sz = strlen(share->path);
+ share->create_mask = resp->create_mask;
+ share->directory_mask = resp->directory_mask;
+ share->force_create_mode = resp->force_create_mode;
+ share->force_directory_mode = resp->force_directory_mode;
+ share->force_uid = resp->force_uid;
+ share->force_gid = resp->force_gid;
+ ret = parse_veto_list(share,
+ KSMBD_SHARE_CONFIG_VETO_LIST(resp),
+ resp->veto_list_sz);
+ if (!ret && share->path) {
+ ret = kern_path(share->path, 0, &share->vfs_path);
+ if (ret) {
+ ksmbd_debug(SMB, "failed to access '%s'\n",
+ share->path);
+ /* Avoid put_path() */
+ kfree(share->path);
+ share->path = NULL;
+ }
+ }
+ if (ret || !share->name) {
+ kill_share(share);
+ share = NULL;
+ goto out;
+ }
+ }
+
+ down_write(&shares_table_lock);
+ lookup = __share_lookup(name);
+ if (lookup)
+ lookup = __get_share_config(lookup);
+ if (!lookup) {
+ hash_add(shares_table, &share->hlist, share_name_hash(name));
+ } else {
+ kill_share(share);
+ share = lookup;
+ }
+ up_write(&shares_table_lock);
+
+out:
+ kvfree(resp);
+ return share;
+}
+
+struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
+ const char *name)
+{
+ struct ksmbd_share_config *share;
+
+ down_read(&shares_table_lock);
+ share = __share_lookup(name);
+ if (share)
+ share = __get_share_config(share);
+ up_read(&shares_table_lock);
+
+ if (share)
+ return share;
+ return share_config_request(um, name);
+}
+
+bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
+ const char *filename)
+{
+ struct ksmbd_veto_pattern *p;
+
+ list_for_each_entry(p, &share->veto_list, list) {
+ if (match_wildcard(p->pattern, filename))
+ return true;
+ }
+ return false;
+}
diff --git a/fs/smb/server/mgmt/share_config.h b/fs/smb/server/mgmt/share_config.h
new file mode 100644
index 000000000000..3fd338293942
--- /dev/null
+++ b/fs/smb/server/mgmt/share_config.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __SHARE_CONFIG_MANAGEMENT_H__
+#define __SHARE_CONFIG_MANAGEMENT_H__
+
+#include <linux/workqueue.h>
+#include <linux/hashtable.h>
+#include <linux/path.h>
+#include <linux/unicode.h>
+
+struct ksmbd_share_config {
+ char *name;
+ char *path;
+
+ unsigned int path_sz;
+ unsigned int flags;
+ struct list_head veto_list;
+
+ struct path vfs_path;
+
+ atomic_t refcount;
+ struct hlist_node hlist;
+ unsigned short create_mask;
+ unsigned short directory_mask;
+ unsigned short force_create_mode;
+ unsigned short force_directory_mode;
+ unsigned short force_uid;
+ unsigned short force_gid;
+};
+
+#define KSMBD_SHARE_INVALID_UID ((__u16)-1)
+#define KSMBD_SHARE_INVALID_GID ((__u16)-1)
+
+static inline int share_config_create_mode(struct ksmbd_share_config *share,
+ umode_t posix_mode)
+{
+ if (!share->force_create_mode) {
+ if (!posix_mode)
+ return share->create_mask;
+ else
+ return posix_mode & share->create_mask;
+ }
+ return share->force_create_mode & share->create_mask;
+}
+
+static inline int share_config_directory_mode(struct ksmbd_share_config *share,
+ umode_t posix_mode)
+{
+ if (!share->force_directory_mode) {
+ if (!posix_mode)
+ return share->directory_mask;
+ else
+ return posix_mode & share->directory_mask;
+ }
+
+ return share->force_directory_mode & share->directory_mask;
+}
+
+static inline int test_share_config_flag(struct ksmbd_share_config *share,
+ int flag)
+{
+ return share->flags & flag;
+}
+
+void ksmbd_share_config_del(struct ksmbd_share_config *share);
+void __ksmbd_share_config_put(struct ksmbd_share_config *share);
+
+static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
+{
+ if (!atomic_dec_and_test(&share->refcount))
+ return;
+ __ksmbd_share_config_put(share);
+}
+
+struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
+ const char *name);
+bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
+ const char *filename);
+#endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
diff --git a/fs/smb/server/mgmt/tree_connect.c b/fs/smb/server/mgmt/tree_connect.c
new file mode 100644
index 000000000000..f07a05f37651
--- /dev/null
+++ b/fs/smb/server/mgmt/tree_connect.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/xarray.h>
+
+#include "../transport_ipc.h"
+#include "../connection.h"
+
+#include "tree_connect.h"
+#include "user_config.h"
+#include "share_config.h"
+#include "user_session.h"
+
+struct ksmbd_tree_conn_status
+ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
+ const char *share_name)
+{
+ struct ksmbd_tree_conn_status status = {-ENOENT, NULL};
+ struct ksmbd_tree_connect_response *resp = NULL;
+ struct ksmbd_share_config *sc;
+ struct ksmbd_tree_connect *tree_conn = NULL;
+ struct sockaddr *peer_addr;
+ int ret;
+
+ sc = ksmbd_share_config_get(conn->um, share_name);
+ if (!sc)
+ return status;
+
+ tree_conn = kzalloc(sizeof(struct ksmbd_tree_connect), GFP_KERNEL);
+ if (!tree_conn) {
+ status.ret = -ENOMEM;
+ goto out_error;
+ }
+
+ tree_conn->id = ksmbd_acquire_tree_conn_id(sess);
+ if (tree_conn->id < 0) {
+ status.ret = -EINVAL;
+ goto out_error;
+ }
+
+ peer_addr = KSMBD_TCP_PEER_SOCKADDR(conn);
+ resp = ksmbd_ipc_tree_connect_request(sess,
+ sc,
+ tree_conn,
+ peer_addr);
+ if (!resp) {
+ status.ret = -EINVAL;
+ goto out_error;
+ }
+
+ status.ret = resp->status;
+ if (status.ret != KSMBD_TREE_CONN_STATUS_OK)
+ goto out_error;
+
+ tree_conn->flags = resp->connection_flags;
+ if (test_tree_conn_flag(tree_conn, KSMBD_TREE_CONN_FLAG_UPDATE)) {
+ struct ksmbd_share_config *new_sc;
+
+ ksmbd_share_config_del(sc);
+ new_sc = ksmbd_share_config_get(conn->um, share_name);
+ if (!new_sc) {
+ pr_err("Failed to update stale share config\n");
+ status.ret = -ESTALE;
+ goto out_error;
+ }
+ ksmbd_share_config_put(sc);
+ sc = new_sc;
+ }
+
+ tree_conn->user = sess->user;
+ tree_conn->share_conf = sc;
+ status.tree_conn = tree_conn;
+
+ ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn,
+ GFP_KERNEL));
+ if (ret) {
+ status.ret = -ENOMEM;
+ goto out_error;
+ }
+ kvfree(resp);
+ return status;
+
+out_error:
+ if (tree_conn)
+ ksmbd_release_tree_conn_id(sess, tree_conn->id);
+ ksmbd_share_config_put(sc);
+ kfree(tree_conn);
+ kvfree(resp);
+ return status;
+}
+
+int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
+ struct ksmbd_tree_connect *tree_conn)
+{
+ int ret;
+
+ ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
+ ksmbd_release_tree_conn_id(sess, tree_conn->id);
+ xa_erase(&sess->tree_conns, tree_conn->id);
+ ksmbd_share_config_put(tree_conn->share_conf);
+ kfree(tree_conn);
+ return ret;
+}
+
+struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
+ unsigned int id)
+{
+ struct ksmbd_tree_connect *tcon;
+
+ tcon = xa_load(&sess->tree_conns, id);
+ if (tcon) {
+ if (test_bit(TREE_CONN_EXPIRE, &tcon->status))
+ tcon = NULL;
+ }
+
+ return tcon;
+}
+
+struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
+ unsigned int id)
+{
+ struct ksmbd_tree_connect *tc;
+
+ tc = ksmbd_tree_conn_lookup(sess, id);
+ if (tc)
+ return tc->share_conf;
+ return NULL;
+}
+
+int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess)
+{
+ int ret = 0;
+ struct ksmbd_tree_connect *tc;
+ unsigned long id;
+
+ if (!sess)
+ return -EINVAL;
+
+ xa_for_each(&sess->tree_conns, id, tc)
+ ret |= ksmbd_tree_conn_disconnect(sess, tc);
+ xa_destroy(&sess->tree_conns);
+ return ret;
+}
diff --git a/fs/smb/server/mgmt/tree_connect.h b/fs/smb/server/mgmt/tree_connect.h
new file mode 100644
index 000000000000..700df36cf3e3
--- /dev/null
+++ b/fs/smb/server/mgmt/tree_connect.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __TREE_CONNECT_MANAGEMENT_H__
+#define __TREE_CONNECT_MANAGEMENT_H__
+
+#include <linux/hashtable.h>
+
+#include "../ksmbd_netlink.h"
+
+struct ksmbd_share_config;
+struct ksmbd_user;
+struct ksmbd_conn;
+
+#define TREE_CONN_EXPIRE 1
+
+struct ksmbd_tree_connect {
+ int id;
+
+ unsigned int flags;
+ struct ksmbd_share_config *share_conf;
+ struct ksmbd_user *user;
+
+ struct list_head list;
+
+ int maximal_access;
+ bool posix_extensions;
+ unsigned long status;
+};
+
+struct ksmbd_tree_conn_status {
+ unsigned int ret;
+ struct ksmbd_tree_connect *tree_conn;
+};
+
+static inline int test_tree_conn_flag(struct ksmbd_tree_connect *tree_conn,
+ int flag)
+{
+ return tree_conn->flags & flag;
+}
+
+struct ksmbd_session;
+
+struct ksmbd_tree_conn_status
+ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
+ const char *share_name);
+
+int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
+ struct ksmbd_tree_connect *tree_conn);
+
+struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess,
+ unsigned int id);
+
+struct ksmbd_share_config *ksmbd_tree_conn_share(struct ksmbd_session *sess,
+ unsigned int id);
+
+int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess);
+
+#endif /* __TREE_CONNECT_MANAGEMENT_H__ */
diff --git a/fs/smb/server/mgmt/user_config.c b/fs/smb/server/mgmt/user_config.c
new file mode 100644
index 000000000000..279d00feff21
--- /dev/null
+++ b/fs/smb/server/mgmt/user_config.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/slab.h>
+#include <linux/mm.h>
+
+#include "user_config.h"
+#include "../transport_ipc.h"
+
+struct ksmbd_user *ksmbd_login_user(const char *account)
+{
+ struct ksmbd_login_response *resp;
+ struct ksmbd_user *user = NULL;
+
+ resp = ksmbd_ipc_login_request(account);
+ if (!resp)
+ return NULL;
+
+ if (!(resp->status & KSMBD_USER_FLAG_OK))
+ goto out;
+
+ user = ksmbd_alloc_user(resp);
+out:
+ kvfree(resp);
+ return user;
+}
+
+struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp)
+{
+ struct ksmbd_user *user = NULL;
+
+ user = kmalloc(sizeof(struct ksmbd_user), GFP_KERNEL);
+ if (!user)
+ return NULL;
+
+ user->name = kstrdup(resp->account, GFP_KERNEL);
+ user->flags = resp->status;
+ user->gid = resp->gid;
+ user->uid = resp->uid;
+ user->passkey_sz = resp->hash_sz;
+ user->passkey = kmalloc(resp->hash_sz, GFP_KERNEL);
+ if (user->passkey)
+ memcpy(user->passkey, resp->hash, resp->hash_sz);
+
+ if (!user->name || !user->passkey) {
+ kfree(user->name);
+ kfree(user->passkey);
+ kfree(user);
+ user = NULL;
+ }
+ return user;
+}
+
+void ksmbd_free_user(struct ksmbd_user *user)
+{
+ ksmbd_ipc_logout_request(user->name, user->flags);
+ kfree(user->name);
+ kfree(user->passkey);
+ kfree(user);
+}
+
+int ksmbd_anonymous_user(struct ksmbd_user *user)
+{
+ if (user->name[0] == '\0')
+ return 1;
+ return 0;
+}
+
+bool ksmbd_compare_user(struct ksmbd_user *u1, struct ksmbd_user *u2)
+{
+ if (strcmp(u1->name, u2->name))
+ return false;
+ if (memcmp(u1->passkey, u2->passkey, u1->passkey_sz))
+ return false;
+
+ return true;
+}
diff --git a/fs/smb/server/mgmt/user_config.h b/fs/smb/server/mgmt/user_config.h
new file mode 100644
index 000000000000..6a44109617f1
--- /dev/null
+++ b/fs/smb/server/mgmt/user_config.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __USER_CONFIG_MANAGEMENT_H__
+#define __USER_CONFIG_MANAGEMENT_H__
+
+#include "../glob.h"
+
+struct ksmbd_user {
+ unsigned short flags;
+
+ unsigned int uid;
+ unsigned int gid;
+
+ char *name;
+
+ size_t passkey_sz;
+ char *passkey;
+ unsigned int failed_login_count;
+};
+
+static inline bool user_guest(struct ksmbd_user *user)
+{
+ return user->flags & KSMBD_USER_FLAG_GUEST_ACCOUNT;
+}
+
+static inline void set_user_flag(struct ksmbd_user *user, int flag)
+{
+ user->flags |= flag;
+}
+
+static inline int test_user_flag(struct ksmbd_user *user, int flag)
+{
+ return user->flags & flag;
+}
+
+static inline void set_user_guest(struct ksmbd_user *user)
+{
+}
+
+static inline char *user_passkey(struct ksmbd_user *user)
+{
+ return user->passkey;
+}
+
+static inline char *user_name(struct ksmbd_user *user)
+{
+ return user->name;
+}
+
+static inline unsigned int user_uid(struct ksmbd_user *user)
+{
+ return user->uid;
+}
+
+static inline unsigned int user_gid(struct ksmbd_user *user)
+{
+ return user->gid;
+}
+
+struct ksmbd_user *ksmbd_login_user(const char *account);
+struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp);
+void ksmbd_free_user(struct ksmbd_user *user);
+int ksmbd_anonymous_user(struct ksmbd_user *user);
+bool ksmbd_compare_user(struct ksmbd_user *u1, struct ksmbd_user *u2);
+#endif /* __USER_CONFIG_MANAGEMENT_H__ */
diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
new file mode 100644
index 000000000000..ea4b56d570fb
--- /dev/null
+++ b/fs/smb/server/mgmt/user_session.c
@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/rwsem.h>
+#include <linux/xarray.h>
+
+#include "ksmbd_ida.h"
+#include "user_session.h"
+#include "user_config.h"
+#include "tree_connect.h"
+#include "../transport_ipc.h"
+#include "../connection.h"
+#include "../vfs_cache.h"
+
+static DEFINE_IDA(session_ida);
+
+#define SESSION_HASH_BITS 3
+static DEFINE_HASHTABLE(sessions_table, SESSION_HASH_BITS);
+static DECLARE_RWSEM(sessions_table_lock);
+
+struct ksmbd_session_rpc {
+ int id;
+ unsigned int method;
+ struct list_head list;
+};
+
+static void free_channel_list(struct ksmbd_session *sess)
+{
+ struct channel *chann;
+ unsigned long index;
+
+ xa_for_each(&sess->ksmbd_chann_list, index, chann) {
+ xa_erase(&sess->ksmbd_chann_list, index);
+ kfree(chann);
+ }
+
+ xa_destroy(&sess->ksmbd_chann_list);
+}
+
+static void __session_rpc_close(struct ksmbd_session *sess,
+ struct ksmbd_session_rpc *entry)
+{
+ struct ksmbd_rpc_command *resp;
+
+ resp = ksmbd_rpc_close(sess, entry->id);
+ if (!resp)
+ pr_err("Unable to close RPC pipe %d\n", entry->id);
+
+ kvfree(resp);
+ ksmbd_rpc_id_free(entry->id);
+ kfree(entry);
+}
+
+static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
+{
+ struct ksmbd_session_rpc *entry;
+
+ while (!list_empty(&sess->rpc_handle_list)) {
+ entry = list_entry(sess->rpc_handle_list.next,
+ struct ksmbd_session_rpc,
+ list);
+
+ list_del(&entry->list);
+ __session_rpc_close(sess, entry);
+ }
+}
+
+static int __rpc_method(char *rpc_name)
+{
+ if (!strcmp(rpc_name, "\\srvsvc") || !strcmp(rpc_name, "srvsvc"))
+ return KSMBD_RPC_SRVSVC_METHOD_INVOKE;
+
+ if (!strcmp(rpc_name, "\\wkssvc") || !strcmp(rpc_name, "wkssvc"))
+ return KSMBD_RPC_WKSSVC_METHOD_INVOKE;
+
+ if (!strcmp(rpc_name, "LANMAN") || !strcmp(rpc_name, "lanman"))
+ return KSMBD_RPC_RAP_METHOD;
+
+ if (!strcmp(rpc_name, "\\samr") || !strcmp(rpc_name, "samr"))
+ return KSMBD_RPC_SAMR_METHOD_INVOKE;
+
+ if (!strcmp(rpc_name, "\\lsarpc") || !strcmp(rpc_name, "lsarpc"))
+ return KSMBD_RPC_LSARPC_METHOD_INVOKE;
+
+ pr_err("Unsupported RPC: %s\n", rpc_name);
+ return 0;
+}
+
+int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
+{
+ struct ksmbd_session_rpc *entry;
+ struct ksmbd_rpc_command *resp;
+ int method;
+
+ method = __rpc_method(rpc_name);
+ if (!method)
+ return -EINVAL;
+
+ entry = kzalloc(sizeof(struct ksmbd_session_rpc), GFP_KERNEL);
+ if (!entry)
+ return -EINVAL;
+
+ list_add(&entry->list, &sess->rpc_handle_list);
+ entry->method = method;
+ entry->id = ksmbd_ipc_id_alloc();
+ if (entry->id < 0)
+ goto free_entry;
+
+ resp = ksmbd_rpc_open(sess, entry->id);
+ if (!resp)
+ goto free_id;
+
+ kvfree(resp);
+ return entry->id;
+free_id:
+ ksmbd_rpc_id_free(entry->id);
+free_entry:
+ list_del(&entry->list);
+ kfree(entry);
+ return -EINVAL;
+}
+
+void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
+{
+ struct ksmbd_session_rpc *entry;
+
+ list_for_each_entry(entry, &sess->rpc_handle_list, list) {
+ if (entry->id == id) {
+ list_del(&entry->list);
+ __session_rpc_close(sess, entry);
+ break;
+ }
+ }
+}
+
+int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
+{
+ struct ksmbd_session_rpc *entry;
+
+ list_for_each_entry(entry, &sess->rpc_handle_list, list) {
+ if (entry->id == id)
+ return entry->method;
+ }
+ return 0;
+}
+
+void ksmbd_session_destroy(struct ksmbd_session *sess)
+{
+ if (!sess)
+ return;
+
+ if (sess->user)
+ ksmbd_free_user(sess->user);
+
+ ksmbd_tree_conn_session_logoff(sess);
+ ksmbd_destroy_file_table(&sess->file_table);
+ ksmbd_session_rpc_clear_list(sess);
+ free_channel_list(sess);
+ kfree(sess->Preauth_HashValue);
+ ksmbd_release_id(&session_ida, sess->id);
+ kfree(sess);
+}
+
+static struct ksmbd_session *__session_lookup(unsigned long long id)
+{
+ struct ksmbd_session *sess;
+
+ hash_for_each_possible(sessions_table, sess, hlist, id) {
+ if (id == sess->id) {
+ sess->last_active = jiffies;
+ return sess;
+ }
+ }
+ return NULL;
+}
+
+static void ksmbd_expire_session(struct ksmbd_conn *conn)
+{
+ unsigned long id;
+ struct ksmbd_session *sess;
+
+ down_write(&sessions_table_lock);
+ xa_for_each(&conn->sessions, id, sess) {
+ if (sess->state != SMB2_SESSION_VALID ||
+ time_after(jiffies,
+ sess->last_active + SMB2_SESSION_TIMEOUT)) {
+ xa_erase(&conn->sessions, sess->id);
+ hash_del(&sess->hlist);
+ ksmbd_session_destroy(sess);
+ continue;
+ }
+ }
+ up_write(&sessions_table_lock);
+}
+
+int ksmbd_session_register(struct ksmbd_conn *conn,
+ struct ksmbd_session *sess)
+{
+ sess->dialect = conn->dialect;
+ memcpy(sess->ClientGUID, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
+ ksmbd_expire_session(conn);
+ return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL));
+}
+
+static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
+{
+ struct channel *chann;
+
+ chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
+ if (!chann)
+ return -ENOENT;
+
+ kfree(chann);
+ return 0;
+}
+
+void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
+{
+ struct ksmbd_session *sess;
+ unsigned long id;
+
+ down_write(&sessions_table_lock);
+ if (conn->binding) {
+ int bkt;
+ struct hlist_node *tmp;
+
+ hash_for_each_safe(sessions_table, bkt, tmp, sess, hlist) {
+ if (!ksmbd_chann_del(conn, sess) &&
+ xa_empty(&sess->ksmbd_chann_list)) {
+ hash_del(&sess->hlist);
+ ksmbd_session_destroy(sess);
+ }
+ }
+ }
+
+ xa_for_each(&conn->sessions, id, sess) {
+ unsigned long chann_id;
+ struct channel *chann;
+
+ xa_for_each(&sess->ksmbd_chann_list, chann_id, chann) {
+ if (chann->conn != conn)
+ ksmbd_conn_set_exiting(chann->conn);
+ }
+
+ ksmbd_chann_del(conn, sess);
+ if (xa_empty(&sess->ksmbd_chann_list)) {
+ xa_erase(&conn->sessions, sess->id);
+ hash_del(&sess->hlist);
+ ksmbd_session_destroy(sess);
+ }
+ }
+ up_write(&sessions_table_lock);
+}
+
+struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
+ unsigned long long id)
+{
+ struct ksmbd_session *sess;
+
+ sess = xa_load(&conn->sessions, id);
+ if (sess)
+ sess->last_active = jiffies;
+ return sess;
+}
+
+struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
+{
+ struct ksmbd_session *sess;
+
+ down_read(&sessions_table_lock);
+ sess = __session_lookup(id);
+ if (sess)
+ sess->last_active = jiffies;
+ up_read(&sessions_table_lock);
+
+ return sess;
+}
+
+struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
+ unsigned long long id)
+{
+ struct ksmbd_session *sess;
+
+ sess = ksmbd_session_lookup(conn, id);
+ if (!sess && conn->binding)
+ sess = ksmbd_session_lookup_slowpath(id);
+ if (sess && sess->state != SMB2_SESSION_VALID)
+ sess = NULL;
+ return sess;
+}
+
+struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
+ u64 sess_id)
+{
+ struct preauth_session *sess;
+
+ sess = kmalloc(sizeof(struct preauth_session), GFP_KERNEL);
+ if (!sess)
+ return NULL;
+
+ sess->id = sess_id;
+ memcpy(sess->Preauth_HashValue, conn->preauth_info->Preauth_HashValue,
+ PREAUTH_HASHVALUE_SIZE);
+ list_add(&sess->preauth_entry, &conn->preauth_sess_table);
+
+ return sess;
+}
+
+static bool ksmbd_preauth_session_id_match(struct preauth_session *sess,
+ unsigned long long id)
+{
+ return sess->id == id;
+}
+
+struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
+ unsigned long long id)
+{
+ struct preauth_session *sess = NULL;
+
+ list_for_each_entry(sess, &conn->preauth_sess_table, preauth_entry) {
+ if (ksmbd_preauth_session_id_match(sess, id))
+ return sess;
+ }
+ return NULL;
+}
+
+static int __init_smb2_session(struct ksmbd_session *sess)
+{
+ int id = ksmbd_acquire_smb2_uid(&session_ida);
+
+ if (id < 0)
+ return -EINVAL;
+ sess->id = id;
+ return 0;
+}
+
+static struct ksmbd_session *__session_create(int protocol)
+{
+ struct ksmbd_session *sess;
+ int ret;
+
+ if (protocol != CIFDS_SESSION_FLAG_SMB2)
+ return NULL;
+
+ sess = kzalloc(sizeof(struct ksmbd_session), GFP_KERNEL);
+ if (!sess)
+ return NULL;
+
+ if (ksmbd_init_file_table(&sess->file_table))
+ goto error;
+
+ sess->last_active = jiffies;
+ sess->state = SMB2_SESSION_IN_PROGRESS;
+ set_session_flag(sess, protocol);
+ xa_init(&sess->tree_conns);
+ xa_init(&sess->ksmbd_chann_list);
+ INIT_LIST_HEAD(&sess->rpc_handle_list);
+ sess->sequence_number = 1;
+
+ ret = __init_smb2_session(sess);
+ if (ret)
+ goto error;
+
+ ida_init(&sess->tree_conn_ida);
+
+ down_write(&sessions_table_lock);
+ hash_add(sessions_table, &sess->hlist, sess->id);
+ up_write(&sessions_table_lock);
+
+ return sess;
+
+error:
+ ksmbd_session_destroy(sess);
+ return NULL;
+}
+
+struct ksmbd_session *ksmbd_smb2_session_create(void)
+{
+ return __session_create(CIFDS_SESSION_FLAG_SMB2);
+}
+
+int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess)
+{
+ int id = -EINVAL;
+
+ if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
+ id = ksmbd_acquire_smb2_tid(&sess->tree_conn_ida);
+
+ return id;
+}
+
+void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id)
+{
+ if (id >= 0)
+ ksmbd_release_id(&sess->tree_conn_ida, id);
+}
diff --git a/fs/smb/server/mgmt/user_session.h b/fs/smb/server/mgmt/user_session.h
new file mode 100644
index 000000000000..51f38e5b61ab
--- /dev/null
+++ b/fs/smb/server/mgmt/user_session.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __USER_SESSION_MANAGEMENT_H__
+#define __USER_SESSION_MANAGEMENT_H__
+
+#include <linux/hashtable.h>
+#include <linux/xarray.h>
+
+#include "../smb_common.h"
+#include "../ntlmssp.h"
+
+#define CIFDS_SESSION_FLAG_SMB2 BIT(1)
+
+#define PREAUTH_HASHVALUE_SIZE 64
+
+struct ksmbd_file_table;
+
+struct channel {
+ __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
+ struct ksmbd_conn *conn;
+};
+
+struct preauth_session {
+ __u8 Preauth_HashValue[PREAUTH_HASHVALUE_SIZE];
+ u64 id;
+ struct list_head preauth_entry;
+};
+
+struct ksmbd_session {
+ u64 id;
+
+ __u16 dialect;
+ char ClientGUID[SMB2_CLIENT_GUID_SIZE];
+
+ struct ksmbd_user *user;
+ unsigned int sequence_number;
+ unsigned int flags;
+
+ bool sign;
+ bool enc;
+ bool is_anonymous;
+
+ int state;
+ __u8 *Preauth_HashValue;
+
+ char sess_key[CIFS_KEY_SIZE];
+
+ struct hlist_node hlist;
+ struct xarray ksmbd_chann_list;
+ struct xarray tree_conns;
+ struct ida tree_conn_ida;
+ struct list_head rpc_handle_list;
+
+ __u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
+ __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
+ __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
+
+ struct ksmbd_file_table file_table;
+ unsigned long last_active;
+};
+
+static inline int test_session_flag(struct ksmbd_session *sess, int bit)
+{
+ return sess->flags & bit;
+}
+
+static inline void set_session_flag(struct ksmbd_session *sess, int bit)
+{
+ sess->flags |= bit;
+}
+
+static inline void clear_session_flag(struct ksmbd_session *sess, int bit)
+{
+ sess->flags &= ~bit;
+}
+
+struct ksmbd_session *ksmbd_smb2_session_create(void);
+
+void ksmbd_session_destroy(struct ksmbd_session *sess);
+
+struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id);
+struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
+ unsigned long long id);
+int ksmbd_session_register(struct ksmbd_conn *conn,
+ struct ksmbd_session *sess);
+void ksmbd_sessions_deregister(struct ksmbd_conn *conn);
+struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
+ unsigned long long id);
+struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
+ u64 sess_id);
+struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
+ unsigned long long id);
+
+int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess);
+void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id);
+
+int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name);
+void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id);
+int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id);
+#endif /* __USER_SESSION_MANAGEMENT_H__ */
diff --git a/fs/smb/server/misc.c b/fs/smb/server/misc.c
new file mode 100644
index 000000000000..9e8afaa686e3
--- /dev/null
+++ b/fs/smb/server/misc.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/kernel.h>
+#include <linux/xattr.h>
+#include <linux/fs.h>
+#include <linux/unicode.h>
+
+#include "misc.h"
+#include "smb_common.h"
+#include "connection.h"
+#include "vfs.h"
+
+#include "mgmt/share_config.h"
+
+/**
+ * match_pattern() - compare a string with a pattern which might include
+ * wildcard '*' and '?'
+ * TODO : implement consideration about DOS_DOT, DOS_QM and DOS_STAR
+ *
+ * @str: string to compare with a pattern
+ * @len: string length
+ * @pattern: pattern string which might include wildcard '*' and '?'
+ *
+ * Return: 0 if pattern matched with the string, otherwise non zero value
+ */
+int match_pattern(const char *str, size_t len, const char *pattern)
+{
+ const char *s = str;
+ const char *p = pattern;
+ bool star = false;
+
+ while (*s && len) {
+ switch (*p) {
+ case '?':
+ s++;
+ len--;
+ p++;
+ break;
+ case '*':
+ star = true;
+ str = s;
+ if (!*++p)
+ return true;
+ pattern = p;
+ break;
+ default:
+ if (tolower(*s) == tolower(*p)) {
+ s++;
+ len--;
+ p++;
+ } else {
+ if (!star)
+ return false;
+ str++;
+ s = str;
+ p = pattern;
+ }
+ break;
+ }
+ }
+
+ if (*p == '*')
+ ++p;
+ return !*p;
+}
+
+/*
+ * is_char_allowed() - check for valid character
+ * @ch: input character to be checked
+ *
+ * Return: 1 if char is allowed, otherwise 0
+ */
+static inline int is_char_allowed(char ch)
+{
+ /* check for control chars, wildcards etc. */
+ if (!(ch & 0x80) &&
+ (ch <= 0x1f ||
+ ch == '?' || ch == '"' || ch == '<' ||
+ ch == '>' || ch == '|' || ch == '*'))
+ return 0;
+
+ return 1;
+}
+
+int ksmbd_validate_filename(char *filename)
+{
+ while (*filename) {
+ char c = *filename;
+
+ filename++;
+ if (!is_char_allowed(c)) {
+ ksmbd_debug(VFS, "File name validation failed: 0x%x\n", c);
+ return -ENOENT;
+ }
+ }
+
+ return 0;
+}
+
+static int ksmbd_validate_stream_name(char *stream_name)
+{
+ while (*stream_name) {
+ char c = *stream_name;
+
+ stream_name++;
+ if (c == '/' || c == ':' || c == '\\') {
+ pr_err("Stream name validation failed: %c\n", c);
+ return -ENOENT;
+ }
+ }
+
+ return 0;
+}
+
+int parse_stream_name(char *filename, char **stream_name, int *s_type)
+{
+ char *stream_type;
+ char *s_name;
+ int rc = 0;
+
+ s_name = filename;
+ filename = strsep(&s_name, ":");
+ ksmbd_debug(SMB, "filename : %s, streams : %s\n", filename, s_name);
+ if (strchr(s_name, ':')) {
+ stream_type = s_name;
+ s_name = strsep(&stream_type, ":");
+
+ rc = ksmbd_validate_stream_name(s_name);
+ if (rc < 0) {
+ rc = -ENOENT;
+ goto out;
+ }
+
+ ksmbd_debug(SMB, "stream name : %s, stream type : %s\n", s_name,
+ stream_type);
+ if (!strncasecmp("$data", stream_type, 5))
+ *s_type = DATA_STREAM;
+ else if (!strncasecmp("$index_allocation", stream_type, 17))
+ *s_type = DIR_STREAM;
+ else
+ rc = -ENOENT;
+ }
+
+ *stream_name = s_name;
+out:
+ return rc;
+}
+
+/**
+ * convert_to_nt_pathname() - extract and return windows path string
+ * whose share directory prefix was removed from file path
+ * @share: ksmbd_share_config pointer
+ * @path: path to report
+ *
+ * Return : windows path string or error
+ */
+
+char *convert_to_nt_pathname(struct ksmbd_share_config *share,
+ const struct path *path)
+{
+ char *pathname, *ab_pathname, *nt_pathname;
+ int share_path_len = share->path_sz;
+
+ pathname = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!pathname)
+ return ERR_PTR(-EACCES);
+
+ ab_pathname = d_path(path, pathname, PATH_MAX);
+ if (IS_ERR(ab_pathname)) {
+ nt_pathname = ERR_PTR(-EACCES);
+ goto free_pathname;
+ }
+
+ if (strncmp(ab_pathname, share->path, share_path_len)) {
+ nt_pathname = ERR_PTR(-EACCES);
+ goto free_pathname;
+ }
+
+ nt_pathname = kzalloc(strlen(&ab_pathname[share_path_len]) + 2, GFP_KERNEL);
+ if (!nt_pathname) {
+ nt_pathname = ERR_PTR(-ENOMEM);
+ goto free_pathname;
+ }
+ if (ab_pathname[share_path_len] == '\0')
+ strcpy(nt_pathname, "/");
+ strcat(nt_pathname, &ab_pathname[share_path_len]);
+
+ ksmbd_conv_path_to_windows(nt_pathname);
+
+free_pathname:
+ kfree(pathname);
+ return nt_pathname;
+}
+
+int get_nlink(struct kstat *st)
+{
+ int nlink;
+
+ nlink = st->nlink;
+ if (S_ISDIR(st->mode))
+ nlink--;
+
+ return nlink;
+}
+
+void ksmbd_conv_path_to_unix(char *path)
+{
+ strreplace(path, '\\', '/');
+}
+
+void ksmbd_strip_last_slash(char *path)
+{
+ int len = strlen(path);
+
+ while (len && path[len - 1] == '/') {
+ path[len - 1] = '\0';
+ len--;
+ }
+}
+
+void ksmbd_conv_path_to_windows(char *path)
+{
+ strreplace(path, '/', '\\');
+}
+
+char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name)
+{
+ char *cf_name;
+ int cf_len;
+
+ cf_name = kzalloc(KSMBD_REQ_MAX_SHARE_NAME, GFP_KERNEL);
+ if (!cf_name)
+ return ERR_PTR(-ENOMEM);
+
+ if (IS_ENABLED(CONFIG_UNICODE) && um) {
+ const struct qstr q_name = {.name = name, .len = strlen(name)};
+
+ cf_len = utf8_casefold(um, &q_name, cf_name,
+ KSMBD_REQ_MAX_SHARE_NAME);
+ if (cf_len < 0)
+ goto out_ascii;
+
+ return cf_name;
+ }
+
+out_ascii:
+ cf_len = strscpy(cf_name, name, KSMBD_REQ_MAX_SHARE_NAME);
+ if (cf_len < 0) {
+ kfree(cf_name);
+ return ERR_PTR(-E2BIG);
+ }
+
+ for (; *cf_name; ++cf_name)
+ *cf_name = isascii(*cf_name) ? tolower(*cf_name) : *cf_name;
+ return cf_name - cf_len;
+}
+
+/**
+ * ksmbd_extract_sharename() - get share name from tree connect request
+ * @treename: buffer containing tree name and share name
+ *
+ * Return: share name on success, otherwise error
+ */
+char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename)
+{
+ const char *name = treename, *pos = strrchr(name, '\\');
+
+ if (pos)
+ name = (pos + 1);
+
+ /* caller has to free the memory */
+ return ksmbd_casefold_sharename(um, name);
+}
+
+/**
+ * convert_to_unix_name() - convert windows name to unix format
+ * @share: ksmbd_share_config pointer
+ * @name: file name that is relative to share
+ *
+ * Return: converted name on success, otherwise NULL
+ */
+char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name)
+{
+ int no_slash = 0, name_len, path_len;
+ char *new_name;
+
+ if (name[0] == '/')
+ name++;
+
+ path_len = share->path_sz;
+ name_len = strlen(name);
+ new_name = kmalloc(path_len + name_len + 2, GFP_KERNEL);
+ if (!new_name)
+ return new_name;
+
+ memcpy(new_name, share->path, path_len);
+ if (new_name[path_len - 1] != '/') {
+ new_name[path_len] = '/';
+ no_slash = 1;
+ }
+
+ memcpy(new_name + path_len + no_slash, name, name_len);
+ path_len += name_len + no_slash;
+ new_name[path_len] = 0x00;
+ return new_name;
+}
+
+char *ksmbd_convert_dir_info_name(struct ksmbd_dir_info *d_info,
+ const struct nls_table *local_nls,
+ int *conv_len)
+{
+ char *conv;
+ int sz = min(4 * d_info->name_len, PATH_MAX);
+
+ if (!sz)
+ return NULL;
+
+ conv = kmalloc(sz, GFP_KERNEL);
+ if (!conv)
+ return NULL;
+
+ /* XXX */
+ *conv_len = smbConvertToUTF16((__le16 *)conv, d_info->name,
+ d_info->name_len, local_nls, 0);
+ *conv_len *= 2;
+
+ /* We allocate buffer twice bigger than needed. */
+ conv[*conv_len] = 0x00;
+ conv[*conv_len + 1] = 0x00;
+ return conv;
+}
+
+/*
+ * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
+ * into Unix UTC (based 1970-01-01, in seconds).
+ */
+struct timespec64 ksmbd_NTtimeToUnix(__le64 ntutc)
+{
+ struct timespec64 ts;
+
+ /* Subtract the NTFS time offset, then convert to 1s intervals. */
+ s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
+ u64 abs_t;
+
+ /*
+ * Unfortunately can not use normal 64 bit division on 32 bit arch, but
+ * the alternative, do_div, does not work with negative numbers so have
+ * to special case them
+ */
+ if (t < 0) {
+ abs_t = -t;
+ ts.tv_nsec = do_div(abs_t, 10000000) * 100;
+ ts.tv_nsec = -ts.tv_nsec;
+ ts.tv_sec = -abs_t;
+ } else {
+ abs_t = t;
+ ts.tv_nsec = do_div(abs_t, 10000000) * 100;
+ ts.tv_sec = abs_t;
+ }
+
+ return ts;
+}
+
+/* Convert the Unix UTC into NT UTC. */
+inline u64 ksmbd_UnixTimeToNT(struct timespec64 t)
+{
+ /* Convert to 100ns intervals and then add the NTFS time offset. */
+ return (u64)t.tv_sec * 10000000 + t.tv_nsec / 100 + NTFS_TIME_OFFSET;
+}
+
+inline long long ksmbd_systime(void)
+{
+ struct timespec64 ts;
+
+ ktime_get_real_ts64(&ts);
+ return ksmbd_UnixTimeToNT(ts);
+}
diff --git a/fs/smb/server/misc.h b/fs/smb/server/misc.h
new file mode 100644
index 000000000000..1facfcd21200
--- /dev/null
+++ b/fs/smb/server/misc.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __KSMBD_MISC_H__
+#define __KSMBD_MISC_H__
+
+struct ksmbd_share_config;
+struct nls_table;
+struct kstat;
+struct ksmbd_file;
+
+int match_pattern(const char *str, size_t len, const char *pattern);
+int ksmbd_validate_filename(char *filename);
+int parse_stream_name(char *filename, char **stream_name, int *s_type);
+char *convert_to_nt_pathname(struct ksmbd_share_config *share,
+ const struct path *path);
+int get_nlink(struct kstat *st);
+void ksmbd_conv_path_to_unix(char *path);
+void ksmbd_strip_last_slash(char *path);
+void ksmbd_conv_path_to_windows(char *path);
+char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name);
+char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
+char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);
+
+#define KSMBD_DIR_INFO_ALIGNMENT 8
+struct ksmbd_dir_info;
+char *ksmbd_convert_dir_info_name(struct ksmbd_dir_info *d_info,
+ const struct nls_table *local_nls,
+ int *conv_len);
+
+#define NTFS_TIME_OFFSET ((u64)(369 * 365 + 89) * 24 * 3600 * 10000000)
+struct timespec64 ksmbd_NTtimeToUnix(__le64 ntutc);
+u64 ksmbd_UnixTimeToNT(struct timespec64 t);
+long long ksmbd_systime(void);
+#endif /* __KSMBD_MISC_H__ */
diff --git a/fs/smb/server/ndr.c b/fs/smb/server/ndr.c
new file mode 100644
index 000000000000..4d9e0b54e3db
--- /dev/null
+++ b/fs/smb/server/ndr.c
@@ -0,0 +1,514 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021 Samsung Electronics Co., Ltd.
+ * Author(s): Namjae Jeon <linkinjeon@kernel.org>
+ */
+
+#include <linux/fs.h>
+
+#include "glob.h"
+#include "ndr.h"
+
+static inline char *ndr_get_field(struct ndr *n)
+{
+ return n->data + n->offset;
+}
+
+static int try_to_realloc_ndr_blob(struct ndr *n, size_t sz)
+{
+ char *data;
+
+ data = krealloc(n->data, n->offset + sz + 1024, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ n->data = data;
+ n->length += 1024;
+ memset(n->data + n->offset, 0, 1024);
+ return 0;
+}
+
+static int ndr_write_int16(struct ndr *n, __u16 value)
+{
+ if (n->length <= n->offset + sizeof(value)) {
+ int ret;
+
+ ret = try_to_realloc_ndr_blob(n, sizeof(value));
+ if (ret)
+ return ret;
+ }
+
+ *(__le16 *)ndr_get_field(n) = cpu_to_le16(value);
+ n->offset += sizeof(value);
+ return 0;
+}
+
+static int ndr_write_int32(struct ndr *n, __u32 value)
+{
+ if (n->length <= n->offset + sizeof(value)) {
+ int ret;
+
+ ret = try_to_realloc_ndr_blob(n, sizeof(value));
+ if (ret)
+ return ret;
+ }
+
+ *(__le32 *)ndr_get_field(n) = cpu_to_le32(value);
+ n->offset += sizeof(value);
+ return 0;
+}
+
+static int ndr_write_int64(struct ndr *n, __u64 value)
+{
+ if (n->length <= n->offset + sizeof(value)) {
+ int ret;
+
+ ret = try_to_realloc_ndr_blob(n, sizeof(value));
+ if (ret)
+ return ret;
+ }
+
+ *(__le64 *)ndr_get_field(n) = cpu_to_le64(value);
+ n->offset += sizeof(value);
+ return 0;
+}
+
+static int ndr_write_bytes(struct ndr *n, void *value, size_t sz)
+{
+ if (n->length <= n->offset + sz) {
+ int ret;
+
+ ret = try_to_realloc_ndr_blob(n, sz);
+ if (ret)
+ return ret;
+ }
+
+ memcpy(ndr_get_field(n), value, sz);
+ n->offset += sz;
+ return 0;
+}
+
+static int ndr_write_string(struct ndr *n, char *value)
+{
+ size_t sz;
+
+ sz = strlen(value) + 1;
+ if (n->length <= n->offset + sz) {
+ int ret;
+
+ ret = try_to_realloc_ndr_blob(n, sz);
+ if (ret)
+ return ret;
+ }
+
+ memcpy(ndr_get_field(n), value, sz);
+ n->offset += sz;
+ n->offset = ALIGN(n->offset, 2);
+ return 0;
+}
+
+static int ndr_read_string(struct ndr *n, void *value, size_t sz)
+{
+ int len;
+
+ if (n->offset + sz > n->length)
+ return -EINVAL;
+
+ len = strnlen(ndr_get_field(n), sz);
+ if (value)
+ memcpy(value, ndr_get_field(n), len);
+ len++;
+ n->offset += len;
+ n->offset = ALIGN(n->offset, 2);
+ return 0;
+}
+
+static int ndr_read_bytes(struct ndr *n, void *value, size_t sz)
+{
+ if (n->offset + sz > n->length)
+ return -EINVAL;
+
+ if (value)
+ memcpy(value, ndr_get_field(n), sz);
+ n->offset += sz;
+ return 0;
+}
+
+static int ndr_read_int16(struct ndr *n, __u16 *value)
+{
+ if (n->offset + sizeof(__u16) > n->length)
+ return -EINVAL;
+
+ if (value)
+ *value = le16_to_cpu(*(__le16 *)ndr_get_field(n));
+ n->offset += sizeof(__u16);
+ return 0;
+}
+
+static int ndr_read_int32(struct ndr *n, __u32 *value)
+{
+ if (n->offset + sizeof(__u32) > n->length)
+ return -EINVAL;
+
+ if (value)
+ *value = le32_to_cpu(*(__le32 *)ndr_get_field(n));
+ n->offset += sizeof(__u32);
+ return 0;
+}
+
+static int ndr_read_int64(struct ndr *n, __u64 *value)
+{
+ if (n->offset + sizeof(__u64) > n->length)
+ return -EINVAL;
+
+ if (value)
+ *value = le64_to_cpu(*(__le64 *)ndr_get_field(n));
+ n->offset += sizeof(__u64);
+ return 0;
+}
+
+int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
+{
+ char hex_attr[12] = {0};
+ int ret;
+
+ n->offset = 0;
+ n->length = 1024;
+ n->data = kzalloc(n->length, GFP_KERNEL);
+ if (!n->data)
+ return -ENOMEM;
+
+ if (da->version == 3) {
+ snprintf(hex_attr, 10, "0x%x", da->attr);
+ ret = ndr_write_string(n, hex_attr);
+ } else {
+ ret = ndr_write_string(n, "");
+ }
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int16(n, da->version);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int32(n, da->version);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int32(n, da->flags);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int32(n, da->attr);
+ if (ret)
+ return ret;
+
+ if (da->version == 3) {
+ ret = ndr_write_int32(n, da->ea_size);
+ if (ret)
+ return ret;
+ ret = ndr_write_int64(n, da->size);
+ if (ret)
+ return ret;
+ ret = ndr_write_int64(n, da->alloc_size);
+ } else {
+ ret = ndr_write_int64(n, da->itime);
+ }
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int64(n, da->create_time);
+ if (ret)
+ return ret;
+
+ if (da->version == 3)
+ ret = ndr_write_int64(n, da->change_time);
+ return ret;
+}
+
+int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
+{
+ char hex_attr[12];
+ unsigned int version2;
+ int ret;
+
+ n->offset = 0;
+ ret = ndr_read_string(n, hex_attr, sizeof(hex_attr));
+ if (ret)
+ return ret;
+
+ ret = ndr_read_int16(n, &da->version);
+ if (ret)
+ return ret;
+
+ if (da->version != 3 && da->version != 4) {
+ ksmbd_debug(VFS, "v%d version is not supported\n", da->version);
+ return -EINVAL;
+ }
+
+ ret = ndr_read_int32(n, &version2);
+ if (ret)
+ return ret;
+
+ if (da->version != version2) {
+ ksmbd_debug(VFS, "ndr version mismatched(version: %d, version2: %d)\n",
+ da->version, version2);
+ return -EINVAL;
+ }
+
+ ret = ndr_read_int32(n, NULL);
+ if (ret)
+ return ret;
+
+ ret = ndr_read_int32(n, &da->attr);
+ if (ret)
+ return ret;
+
+ if (da->version == 4) {
+ ret = ndr_read_int64(n, &da->itime);
+ if (ret)
+ return ret;
+
+ ret = ndr_read_int64(n, &da->create_time);
+ } else {
+ ret = ndr_read_int32(n, NULL);
+ if (ret)
+ return ret;
+
+ ret = ndr_read_int64(n, NULL);
+ if (ret)
+ return ret;
+
+ ret = ndr_read_int64(n, NULL);
+ if (ret)
+ return ret;
+
+ ret = ndr_read_int64(n, &da->create_time);
+ if (ret)
+ return ret;
+
+ ret = ndr_read_int64(n, NULL);
+ }
+
+ return ret;
+}
+
+static int ndr_encode_posix_acl_entry(struct ndr *n, struct xattr_smb_acl *acl)
+{
+ int i, ret;
+
+ ret = ndr_write_int32(n, acl->count);
+ if (ret)
+ return ret;
+
+ n->offset = ALIGN(n->offset, 8);
+ ret = ndr_write_int32(n, acl->count);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int32(n, 0);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < acl->count; i++) {
+ n->offset = ALIGN(n->offset, 8);
+ ret = ndr_write_int16(n, acl->entries[i].type);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int16(n, acl->entries[i].type);
+ if (ret)
+ return ret;
+
+ if (acl->entries[i].type == SMB_ACL_USER) {
+ n->offset = ALIGN(n->offset, 8);
+ ret = ndr_write_int64(n, acl->entries[i].uid);
+ } else if (acl->entries[i].type == SMB_ACL_GROUP) {
+ n->offset = ALIGN(n->offset, 8);
+ ret = ndr_write_int64(n, acl->entries[i].gid);
+ }
+ if (ret)
+ return ret;
+
+ /* push permission */
+ ret = ndr_write_int32(n, acl->entries[i].perm);
+ }
+
+ return ret;
+}
+
+int ndr_encode_posix_acl(struct ndr *n,
+ struct user_namespace *user_ns,
+ struct inode *inode,
+ struct xattr_smb_acl *acl,
+ struct xattr_smb_acl *def_acl)
+{
+ unsigned int ref_id = 0x00020000;
+ int ret;
+ vfsuid_t vfsuid;
+ vfsgid_t vfsgid;
+
+ n->offset = 0;
+ n->length = 1024;
+ n->data = kzalloc(n->length, GFP_KERNEL);
+ if (!n->data)
+ return -ENOMEM;
+
+ if (acl) {
+ /* ACL ACCESS */
+ ret = ndr_write_int32(n, ref_id);
+ ref_id += 4;
+ } else {
+ ret = ndr_write_int32(n, 0);
+ }
+ if (ret)
+ return ret;
+
+ if (def_acl) {
+ /* DEFAULT ACL ACCESS */
+ ret = ndr_write_int32(n, ref_id);
+ ref_id += 4;
+ } else {
+ ret = ndr_write_int32(n, 0);
+ }
+ if (ret)
+ return ret;
+
+ vfsuid = i_uid_into_vfsuid(user_ns, inode);
+ ret = ndr_write_int64(n, from_kuid(&init_user_ns, vfsuid_into_kuid(vfsuid)));
+ if (ret)
+ return ret;
+ vfsgid = i_gid_into_vfsgid(user_ns, inode);
+ ret = ndr_write_int64(n, from_kgid(&init_user_ns, vfsgid_into_kgid(vfsgid)));
+ if (ret)
+ return ret;
+ ret = ndr_write_int32(n, inode->i_mode);
+ if (ret)
+ return ret;
+
+ if (acl) {
+ ret = ndr_encode_posix_acl_entry(n, acl);
+ if (def_acl && !ret)
+ ret = ndr_encode_posix_acl_entry(n, def_acl);
+ }
+ return ret;
+}
+
+int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
+{
+ unsigned int ref_id = 0x00020004;
+ int ret;
+
+ n->offset = 0;
+ n->length = 2048;
+ n->data = kzalloc(n->length, GFP_KERNEL);
+ if (!n->data)
+ return -ENOMEM;
+
+ ret = ndr_write_int16(n, acl->version);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int32(n, acl->version);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int16(n, 2);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int32(n, ref_id);
+ if (ret)
+ return ret;
+
+ /* push hash type and hash 64bytes */
+ ret = ndr_write_int16(n, acl->hash_type);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_bytes(n, acl->desc, acl->desc_len);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_int64(n, acl->current_time);
+ if (ret)
+ return ret;
+
+ ret = ndr_write_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
+ if (ret)
+ return ret;
+
+ /* push ndr for security descriptor */
+ ret = ndr_write_bytes(n, acl->sd_buf, acl->sd_size);
+ return ret;
+}
+
+int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
+{
+ unsigned int version2;
+ int ret;
+
+ n->offset = 0;
+ ret = ndr_read_int16(n, &acl->version);
+ if (ret)
+ return ret;
+ if (acl->version != 4) {
+ ksmbd_debug(VFS, "v%d version is not supported\n", acl->version);
+ return -EINVAL;
+ }
+
+ ret = ndr_read_int32(n, &version2);
+ if (ret)
+ return ret;
+ if (acl->version != version2) {
+ ksmbd_debug(VFS, "ndr version mismatched(version: %d, version2: %d)\n",
+ acl->version, version2);
+ return -EINVAL;
+ }
+
+ /* Read Level */
+ ret = ndr_read_int16(n, NULL);
+ if (ret)
+ return ret;
+
+ /* Read Ref Id */
+ ret = ndr_read_int32(n, NULL);
+ if (ret)
+ return ret;
+
+ ret = ndr_read_int16(n, &acl->hash_type);
+ if (ret)
+ return ret;
+
+ ret = ndr_read_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
+ if (ret)
+ return ret;
+
+ ndr_read_bytes(n, acl->desc, 10);
+ if (strncmp(acl->desc, "posix_acl", 9)) {
+ pr_err("Invalid acl description : %s\n", acl->desc);
+ return -EINVAL;
+ }
+
+ /* Read Time */
+ ret = ndr_read_int64(n, NULL);
+ if (ret)
+ return ret;
+
+ /* Read Posix ACL hash */
+ ret = ndr_read_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
+ if (ret)
+ return ret;
+
+ acl->sd_size = n->length - n->offset;
+ acl->sd_buf = kzalloc(acl->sd_size, GFP_KERNEL);
+ if (!acl->sd_buf)
+ return -ENOMEM;
+
+ ret = ndr_read_bytes(n, acl->sd_buf, acl->sd_size);
+ return ret;
+}
diff --git a/fs/smb/server/ndr.h b/fs/smb/server/ndr.h
new file mode 100644
index 000000000000..60ca265d1bb0
--- /dev/null
+++ b/fs/smb/server/ndr.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Samsung Electronics Co., Ltd.
+ * Author(s): Namjae Jeon <linkinjeon@kernel.org>
+ */
+
+struct ndr {
+ char *data;
+ int offset;
+ int length;
+};
+
+#define NDR_NTSD_OFFSETOF 0xA0
+
+int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
+int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
+int ndr_encode_posix_acl(struct ndr *n, struct user_namespace *user_ns,
+ struct inode *inode, struct xattr_smb_acl *acl,
+ struct xattr_smb_acl *def_acl);
+int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl);
+int ndr_encode_v3_ntacl(struct ndr *n, struct xattr_ntacl *acl);
+int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl);
diff --git a/fs/smb/server/nterr.h b/fs/smb/server/nterr.h
new file mode 100644
index 000000000000..2f358f88a018
--- /dev/null
+++ b/fs/smb/server/nterr.h
@@ -0,0 +1,543 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * NT error code constants
+ * Copyright (C) Andrew Tridgell 1992-2000
+ * Copyright (C) John H Terpstra 1996-2000
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-2000
+ * Copyright (C) Paul Ashton 1998-2000
+ */
+
+#ifndef _NTERR_H
+#define _NTERR_H
+
+/* Win32 Status codes. */
+#define NT_STATUS_MORE_ENTRIES 0x0105
+#define NT_ERROR_INVALID_PARAMETER 0x0057
+#define NT_ERROR_INSUFFICIENT_BUFFER 0x007a
+#define NT_STATUS_1804 0x070c
+#define NT_STATUS_NOTIFY_ENUM_DIR 0x010c
+#define NT_STATUS_INVALID_LOCK_RANGE (0xC0000000 | 0x01a1)
+/*
+ * Win32 Error codes extracted using a loop in smbclient then printing a netmon
+ * sniff to a file.
+ */
+
+#define NT_STATUS_OK 0x0000
+#define NT_STATUS_SOME_UNMAPPED 0x0107
+#define NT_STATUS_BUFFER_OVERFLOW 0x80000005
+#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
+#define NT_STATUS_MEDIA_CHANGED 0x8000001c
+#define NT_STATUS_END_OF_MEDIA 0x8000001e
+#define NT_STATUS_MEDIA_CHECK 0x80000020
+#define NT_STATUS_NO_DATA_DETECTED 0x8000001c
+#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d
+#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288
+#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288
+#define NT_STATUS_UNSUCCESSFUL (0xC0000000 | 0x0001)
+#define NT_STATUS_NOT_IMPLEMENTED (0xC0000000 | 0x0002)
+#define NT_STATUS_INVALID_INFO_CLASS (0xC0000000 | 0x0003)
+#define NT_STATUS_INFO_LENGTH_MISMATCH (0xC0000000 | 0x0004)
+#define NT_STATUS_ACCESS_VIOLATION (0xC0000000 | 0x0005)
+#define NT_STATUS_IN_PAGE_ERROR (0xC0000000 | 0x0006)
+#define NT_STATUS_PAGEFILE_QUOTA (0xC0000000 | 0x0007)
+#define NT_STATUS_INVALID_HANDLE (0xC0000000 | 0x0008)
+#define NT_STATUS_BAD_INITIAL_STACK (0xC0000000 | 0x0009)
+#define NT_STATUS_BAD_INITIAL_PC (0xC0000000 | 0x000a)
+#define NT_STATUS_INVALID_CID (0xC0000000 | 0x000b)
+#define NT_STATUS_TIMER_NOT_CANCELED (0xC0000000 | 0x000c)
+#define NT_STATUS_INVALID_PARAMETER (0xC0000000 | 0x000d)
+#define NT_STATUS_NO_SUCH_DEVICE (0xC0000000 | 0x000e)
+#define NT_STATUS_NO_SUCH_FILE (0xC0000000 | 0x000f)
+#define NT_STATUS_INVALID_DEVICE_REQUEST (0xC0000000 | 0x0010)
+#define NT_STATUS_END_OF_FILE (0xC0000000 | 0x0011)
+#define NT_STATUS_WRONG_VOLUME (0xC0000000 | 0x0012)
+#define NT_STATUS_NO_MEDIA_IN_DEVICE (0xC0000000 | 0x0013)
+#define NT_STATUS_UNRECOGNIZED_MEDIA (0xC0000000 | 0x0014)
+#define NT_STATUS_NONEXISTENT_SECTOR (0xC0000000 | 0x0015)
+#define NT_STATUS_MORE_PROCESSING_REQUIRED (0xC0000000 | 0x0016)
+#define NT_STATUS_NO_MEMORY (0xC0000000 | 0x0017)
+#define NT_STATUS_CONFLICTING_ADDRESSES (0xC0000000 | 0x0018)
+#define NT_STATUS_NOT_MAPPED_VIEW (0xC0000000 | 0x0019)
+#define NT_STATUS_UNABLE_TO_FREE_VM (0x80000000 | 0x001a)
+#define NT_STATUS_UNABLE_TO_DELETE_SECTION (0xC0000000 | 0x001b)
+#define NT_STATUS_INVALID_SYSTEM_SERVICE (0xC0000000 | 0x001c)
+#define NT_STATUS_ILLEGAL_INSTRUCTION (0xC0000000 | 0x001d)
+#define NT_STATUS_INVALID_LOCK_SEQUENCE (0xC0000000 | 0x001e)
+#define NT_STATUS_INVALID_VIEW_SIZE (0xC0000000 | 0x001f)
+#define NT_STATUS_INVALID_FILE_FOR_SECTION (0xC0000000 | 0x0020)
+#define NT_STATUS_ALREADY_COMMITTED (0xC0000000 | 0x0021)
+#define NT_STATUS_ACCESS_DENIED (0xC0000000 | 0x0022)
+#define NT_STATUS_BUFFER_TOO_SMALL (0xC0000000 | 0x0023)
+#define NT_STATUS_OBJECT_TYPE_MISMATCH (0xC0000000 | 0x0024)
+#define NT_STATUS_NONCONTINUABLE_EXCEPTION (0xC0000000 | 0x0025)
+#define NT_STATUS_INVALID_DISPOSITION (0xC0000000 | 0x0026)
+#define NT_STATUS_UNWIND (0xC0000000 | 0x0027)
+#define NT_STATUS_BAD_STACK (0xC0000000 | 0x0028)
+#define NT_STATUS_INVALID_UNWIND_TARGET (0xC0000000 | 0x0029)
+#define NT_STATUS_NOT_LOCKED (0xC0000000 | 0x002a)
+#define NT_STATUS_PARITY_ERROR (0xC0000000 | 0x002b)
+#define NT_STATUS_UNABLE_TO_DECOMMIT_VM (0xC0000000 | 0x002c)
+#define NT_STATUS_NOT_COMMITTED (0xC0000000 | 0x002d)
+#define NT_STATUS_INVALID_PORT_ATTRIBUTES (0xC0000000 | 0x002e)
+#define NT_STATUS_PORT_MESSAGE_TOO_LONG (0xC0000000 | 0x002f)
+#define NT_STATUS_INVALID_PARAMETER_MIX (0xC0000000 | 0x0030)
+#define NT_STATUS_INVALID_QUOTA_LOWER (0xC0000000 | 0x0031)
+#define NT_STATUS_DISK_CORRUPT_ERROR (0xC0000000 | 0x0032)
+#define NT_STATUS_OBJECT_NAME_INVALID (0xC0000000 | 0x0033)
+#define NT_STATUS_OBJECT_NAME_NOT_FOUND (0xC0000000 | 0x0034)
+#define NT_STATUS_OBJECT_NAME_COLLISION (0xC0000000 | 0x0035)
+#define NT_STATUS_HANDLE_NOT_WAITABLE (0xC0000000 | 0x0036)
+#define NT_STATUS_PORT_DISCONNECTED (0xC0000000 | 0x0037)
+#define NT_STATUS_DEVICE_ALREADY_ATTACHED (0xC0000000 | 0x0038)
+#define NT_STATUS_OBJECT_PATH_INVALID (0xC0000000 | 0x0039)
+#define NT_STATUS_OBJECT_PATH_NOT_FOUND (0xC0000000 | 0x003a)
+#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD (0xC0000000 | 0x003b)
+#define NT_STATUS_DATA_OVERRUN (0xC0000000 | 0x003c)
+#define NT_STATUS_DATA_LATE_ERROR (0xC0000000 | 0x003d)
+#define NT_STATUS_DATA_ERROR (0xC0000000 | 0x003e)
+#define NT_STATUS_CRC_ERROR (0xC0000000 | 0x003f)
+#define NT_STATUS_SECTION_TOO_BIG (0xC0000000 | 0x0040)
+#define NT_STATUS_PORT_CONNECTION_REFUSED (0xC0000000 | 0x0041)
+#define NT_STATUS_INVALID_PORT_HANDLE (0xC0000000 | 0x0042)
+#define NT_STATUS_SHARING_VIOLATION (0xC0000000 | 0x0043)
+#define NT_STATUS_QUOTA_EXCEEDED (0xC0000000 | 0x0044)
+#define NT_STATUS_INVALID_PAGE_PROTECTION (0xC0000000 | 0x0045)
+#define NT_STATUS_MUTANT_NOT_OWNED (0xC0000000 | 0x0046)
+#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED (0xC0000000 | 0x0047)
+#define NT_STATUS_PORT_ALREADY_SET (0xC0000000 | 0x0048)
+#define NT_STATUS_SECTION_NOT_IMAGE (0xC0000000 | 0x0049)
+#define NT_STATUS_SUSPEND_COUNT_EXCEEDED (0xC0000000 | 0x004a)
+#define NT_STATUS_THREAD_IS_TERMINATING (0xC0000000 | 0x004b)
+#define NT_STATUS_BAD_WORKING_SET_LIMIT (0xC0000000 | 0x004c)
+#define NT_STATUS_INCOMPATIBLE_FILE_MAP (0xC0000000 | 0x004d)
+#define NT_STATUS_SECTION_PROTECTION (0xC0000000 | 0x004e)
+#define NT_STATUS_EAS_NOT_SUPPORTED (0xC0000000 | 0x004f)
+#define NT_STATUS_EA_TOO_LARGE (0xC0000000 | 0x0050)
+#define NT_STATUS_NONEXISTENT_EA_ENTRY (0xC0000000 | 0x0051)
+#define NT_STATUS_NO_EAS_ON_FILE (0xC0000000 | 0x0052)
+#define NT_STATUS_EA_CORRUPT_ERROR (0xC0000000 | 0x0053)
+#define NT_STATUS_FILE_LOCK_CONFLICT (0xC0000000 | 0x0054)
+#define NT_STATUS_LOCK_NOT_GRANTED (0xC0000000 | 0x0055)
+#define NT_STATUS_DELETE_PENDING (0xC0000000 | 0x0056)
+#define NT_STATUS_CTL_FILE_NOT_SUPPORTED (0xC0000000 | 0x0057)
+#define NT_STATUS_UNKNOWN_REVISION (0xC0000000 | 0x0058)
+#define NT_STATUS_REVISION_MISMATCH (0xC0000000 | 0x0059)
+#define NT_STATUS_INVALID_OWNER (0xC0000000 | 0x005a)
+#define NT_STATUS_INVALID_PRIMARY_GROUP (0xC0000000 | 0x005b)
+#define NT_STATUS_NO_IMPERSONATION_TOKEN (0xC0000000 | 0x005c)
+#define NT_STATUS_CANT_DISABLE_MANDATORY (0xC0000000 | 0x005d)
+#define NT_STATUS_NO_LOGON_SERVERS (0xC0000000 | 0x005e)
+#define NT_STATUS_NO_SUCH_LOGON_SESSION (0xC0000000 | 0x005f)
+#define NT_STATUS_NO_SUCH_PRIVILEGE (0xC0000000 | 0x0060)
+#define NT_STATUS_PRIVILEGE_NOT_HELD (0xC0000000 | 0x0061)
+#define NT_STATUS_INVALID_ACCOUNT_NAME (0xC0000000 | 0x0062)
+#define NT_STATUS_USER_EXISTS (0xC0000000 | 0x0063)
+#define NT_STATUS_NO_SUCH_USER (0xC0000000 | 0x0064)
+#define NT_STATUS_GROUP_EXISTS (0xC0000000 | 0x0065)
+#define NT_STATUS_NO_SUCH_GROUP (0xC0000000 | 0x0066)
+#define NT_STATUS_MEMBER_IN_GROUP (0xC0000000 | 0x0067)
+#define NT_STATUS_MEMBER_NOT_IN_GROUP (0xC0000000 | 0x0068)
+#define NT_STATUS_LAST_ADMIN (0xC0000000 | 0x0069)
+#define NT_STATUS_WRONG_PASSWORD (0xC0000000 | 0x006a)
+#define NT_STATUS_ILL_FORMED_PASSWORD (0xC0000000 | 0x006b)
+#define NT_STATUS_PASSWORD_RESTRICTION (0xC0000000 | 0x006c)
+#define NT_STATUS_LOGON_FAILURE (0xC0000000 | 0x006d)
+#define NT_STATUS_ACCOUNT_RESTRICTION (0xC0000000 | 0x006e)
+#define NT_STATUS_INVALID_LOGON_HOURS (0xC0000000 | 0x006f)
+#define NT_STATUS_INVALID_WORKSTATION (0xC0000000 | 0x0070)
+#define NT_STATUS_PASSWORD_EXPIRED (0xC0000000 | 0x0071)
+#define NT_STATUS_ACCOUNT_DISABLED (0xC0000000 | 0x0072)
+#define NT_STATUS_NONE_MAPPED (0xC0000000 | 0x0073)
+#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED (0xC0000000 | 0x0074)
+#define NT_STATUS_LUIDS_EXHAUSTED (0xC0000000 | 0x0075)
+#define NT_STATUS_INVALID_SUB_AUTHORITY (0xC0000000 | 0x0076)
+#define NT_STATUS_INVALID_ACL (0xC0000000 | 0x0077)
+#define NT_STATUS_INVALID_SID (0xC0000000 | 0x0078)
+#define NT_STATUS_INVALID_SECURITY_DESCR (0xC0000000 | 0x0079)
+#define NT_STATUS_PROCEDURE_NOT_FOUND (0xC0000000 | 0x007a)
+#define NT_STATUS_INVALID_IMAGE_FORMAT (0xC0000000 | 0x007b)
+#define NT_STATUS_NO_TOKEN (0xC0000000 | 0x007c)
+#define NT_STATUS_BAD_INHERITANCE_ACL (0xC0000000 | 0x007d)
+#define NT_STATUS_RANGE_NOT_LOCKED (0xC0000000 | 0x007e)
+#define NT_STATUS_DISK_FULL (0xC0000000 | 0x007f)
+#define NT_STATUS_SERVER_DISABLED (0xC0000000 | 0x0080)
+#define NT_STATUS_SERVER_NOT_DISABLED (0xC0000000 | 0x0081)
+#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED (0xC0000000 | 0x0082)
+#define NT_STATUS_GUIDS_EXHAUSTED (0xC0000000 | 0x0083)
+#define NT_STATUS_INVALID_ID_AUTHORITY (0xC0000000 | 0x0084)
+#define NT_STATUS_AGENTS_EXHAUSTED (0xC0000000 | 0x0085)
+#define NT_STATUS_INVALID_VOLUME_LABEL (0xC0000000 | 0x0086)
+#define NT_STATUS_SECTION_NOT_EXTENDED (0xC0000000 | 0x0087)
+#define NT_STATUS_NOT_MAPPED_DATA (0xC0000000 | 0x0088)
+#define NT_STATUS_RESOURCE_DATA_NOT_FOUND (0xC0000000 | 0x0089)
+#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND (0xC0000000 | 0x008a)
+#define NT_STATUS_RESOURCE_NAME_NOT_FOUND (0xC0000000 | 0x008b)
+#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED (0xC0000000 | 0x008c)
+#define NT_STATUS_FLOAT_DENORMAL_OPERAND (0xC0000000 | 0x008d)
+#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO (0xC0000000 | 0x008e)
+#define NT_STATUS_FLOAT_INEXACT_RESULT (0xC0000000 | 0x008f)
+#define NT_STATUS_FLOAT_INVALID_OPERATION (0xC0000000 | 0x0090)
+#define NT_STATUS_FLOAT_OVERFLOW (0xC0000000 | 0x0091)
+#define NT_STATUS_FLOAT_STACK_CHECK (0xC0000000 | 0x0092)
+#define NT_STATUS_FLOAT_UNDERFLOW (0xC0000000 | 0x0093)
+#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO (0xC0000000 | 0x0094)
+#define NT_STATUS_INTEGER_OVERFLOW (0xC0000000 | 0x0095)
+#define NT_STATUS_PRIVILEGED_INSTRUCTION (0xC0000000 | 0x0096)
+#define NT_STATUS_TOO_MANY_PAGING_FILES (0xC0000000 | 0x0097)
+#define NT_STATUS_FILE_INVALID (0xC0000000 | 0x0098)
+#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED (0xC0000000 | 0x0099)
+#define NT_STATUS_INSUFFICIENT_RESOURCES (0xC0000000 | 0x009a)
+#define NT_STATUS_DFS_EXIT_PATH_FOUND (0xC0000000 | 0x009b)
+#define NT_STATUS_DEVICE_DATA_ERROR (0xC0000000 | 0x009c)
+#define NT_STATUS_DEVICE_NOT_CONNECTED (0xC0000000 | 0x009d)
+#define NT_STATUS_DEVICE_POWER_FAILURE (0xC0000000 | 0x009e)
+#define NT_STATUS_FREE_VM_NOT_AT_BASE (0xC0000000 | 0x009f)
+#define NT_STATUS_MEMORY_NOT_ALLOCATED (0xC0000000 | 0x00a0)
+#define NT_STATUS_WORKING_SET_QUOTA (0xC0000000 | 0x00a1)
+#define NT_STATUS_MEDIA_WRITE_PROTECTED (0xC0000000 | 0x00a2)
+#define NT_STATUS_DEVICE_NOT_READY (0xC0000000 | 0x00a3)
+#define NT_STATUS_INVALID_GROUP_ATTRIBUTES (0xC0000000 | 0x00a4)
+#define NT_STATUS_BAD_IMPERSONATION_LEVEL (0xC0000000 | 0x00a5)
+#define NT_STATUS_CANT_OPEN_ANONYMOUS (0xC0000000 | 0x00a6)
+#define NT_STATUS_BAD_VALIDATION_CLASS (0xC0000000 | 0x00a7)
+#define NT_STATUS_BAD_TOKEN_TYPE (0xC0000000 | 0x00a8)
+#define NT_STATUS_BAD_MASTER_BOOT_RECORD (0xC0000000 | 0x00a9)
+#define NT_STATUS_INSTRUCTION_MISALIGNMENT (0xC0000000 | 0x00aa)
+#define NT_STATUS_INSTANCE_NOT_AVAILABLE (0xC0000000 | 0x00ab)
+#define NT_STATUS_PIPE_NOT_AVAILABLE (0xC0000000 | 0x00ac)
+#define NT_STATUS_INVALID_PIPE_STATE (0xC0000000 | 0x00ad)
+#define NT_STATUS_PIPE_BUSY (0xC0000000 | 0x00ae)
+#define NT_STATUS_ILLEGAL_FUNCTION (0xC0000000 | 0x00af)
+#define NT_STATUS_PIPE_DISCONNECTED (0xC0000000 | 0x00b0)
+#define NT_STATUS_PIPE_CLOSING (0xC0000000 | 0x00b1)
+#define NT_STATUS_PIPE_CONNECTED (0xC0000000 | 0x00b2)
+#define NT_STATUS_PIPE_LISTENING (0xC0000000 | 0x00b3)
+#define NT_STATUS_INVALID_READ_MODE (0xC0000000 | 0x00b4)
+#define NT_STATUS_IO_TIMEOUT (0xC0000000 | 0x00b5)
+#define NT_STATUS_FILE_FORCED_CLOSED (0xC0000000 | 0x00b6)
+#define NT_STATUS_PROFILING_NOT_STARTED (0xC0000000 | 0x00b7)
+#define NT_STATUS_PROFILING_NOT_STOPPED (0xC0000000 | 0x00b8)
+#define NT_STATUS_COULD_NOT_INTERPRET (0xC0000000 | 0x00b9)
+#define NT_STATUS_FILE_IS_A_DIRECTORY (0xC0000000 | 0x00ba)
+#define NT_STATUS_NOT_SUPPORTED (0xC0000000 | 0x00bb)
+#define NT_STATUS_REMOTE_NOT_LISTENING (0xC0000000 | 0x00bc)
+#define NT_STATUS_DUPLICATE_NAME (0xC0000000 | 0x00bd)
+#define NT_STATUS_BAD_NETWORK_PATH (0xC0000000 | 0x00be)
+#define NT_STATUS_NETWORK_BUSY (0xC0000000 | 0x00bf)
+#define NT_STATUS_DEVICE_DOES_NOT_EXIST (0xC0000000 | 0x00c0)
+#define NT_STATUS_TOO_MANY_COMMANDS (0xC0000000 | 0x00c1)
+#define NT_STATUS_ADAPTER_HARDWARE_ERROR (0xC0000000 | 0x00c2)
+#define NT_STATUS_INVALID_NETWORK_RESPONSE (0xC0000000 | 0x00c3)
+#define NT_STATUS_UNEXPECTED_NETWORK_ERROR (0xC0000000 | 0x00c4)
+#define NT_STATUS_BAD_REMOTE_ADAPTER (0xC0000000 | 0x00c5)
+#define NT_STATUS_PRINT_QUEUE_FULL (0xC0000000 | 0x00c6)
+#define NT_STATUS_NO_SPOOL_SPACE (0xC0000000 | 0x00c7)
+#define NT_STATUS_PRINT_CANCELLED (0xC0000000 | 0x00c8)
+#define NT_STATUS_NETWORK_NAME_DELETED (0xC0000000 | 0x00c9)
+#define NT_STATUS_NETWORK_ACCESS_DENIED (0xC0000000 | 0x00ca)
+#define NT_STATUS_BAD_DEVICE_TYPE (0xC0000000 | 0x00cb)
+#define NT_STATUS_BAD_NETWORK_NAME (0xC0000000 | 0x00cc)
+#define NT_STATUS_TOO_MANY_NAMES (0xC0000000 | 0x00cd)
+#define NT_STATUS_TOO_MANY_SESSIONS (0xC0000000 | 0x00ce)
+#define NT_STATUS_SHARING_PAUSED (0xC0000000 | 0x00cf)
+#define NT_STATUS_REQUEST_NOT_ACCEPTED (0xC0000000 | 0x00d0)
+#define NT_STATUS_REDIRECTOR_PAUSED (0xC0000000 | 0x00d1)
+#define NT_STATUS_NET_WRITE_FAULT (0xC0000000 | 0x00d2)
+#define NT_STATUS_PROFILING_AT_LIMIT (0xC0000000 | 0x00d3)
+#define NT_STATUS_NOT_SAME_DEVICE (0xC0000000 | 0x00d4)
+#define NT_STATUS_FILE_RENAMED (0xC0000000 | 0x00d5)
+#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED (0xC0000000 | 0x00d6)
+#define NT_STATUS_NO_SECURITY_ON_OBJECT (0xC0000000 | 0x00d7)
+#define NT_STATUS_CANT_WAIT (0xC0000000 | 0x00d8)
+#define NT_STATUS_PIPE_EMPTY (0xC0000000 | 0x00d9)
+#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO (0xC0000000 | 0x00da)
+#define NT_STATUS_CANT_TERMINATE_SELF (0xC0000000 | 0x00db)
+#define NT_STATUS_INVALID_SERVER_STATE (0xC0000000 | 0x00dc)
+#define NT_STATUS_INVALID_DOMAIN_STATE (0xC0000000 | 0x00dd)
+#define NT_STATUS_INVALID_DOMAIN_ROLE (0xC0000000 | 0x00de)
+#define NT_STATUS_NO_SUCH_DOMAIN (0xC0000000 | 0x00df)
+#define NT_STATUS_DOMAIN_EXISTS (0xC0000000 | 0x00e0)
+#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED (0xC0000000 | 0x00e1)
+#define NT_STATUS_OPLOCK_NOT_GRANTED (0xC0000000 | 0x00e2)
+#define NT_STATUS_INVALID_OPLOCK_PROTOCOL (0xC0000000 | 0x00e3)
+#define NT_STATUS_INTERNAL_DB_CORRUPTION (0xC0000000 | 0x00e4)
+#define NT_STATUS_INTERNAL_ERROR (0xC0000000 | 0x00e5)
+#define NT_STATUS_GENERIC_NOT_MAPPED (0xC0000000 | 0x00e6)
+#define NT_STATUS_BAD_DESCRIPTOR_FORMAT (0xC0000000 | 0x00e7)
+#define NT_STATUS_INVALID_USER_BUFFER (0xC0000000 | 0x00e8)
+#define NT_STATUS_UNEXPECTED_IO_ERROR (0xC0000000 | 0x00e9)
+#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR (0xC0000000 | 0x00ea)
+#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR (0xC0000000 | 0x00eb)
+#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR (0xC0000000 | 0x00ec)
+#define NT_STATUS_NOT_LOGON_PROCESS (0xC0000000 | 0x00ed)
+#define NT_STATUS_LOGON_SESSION_EXISTS (0xC0000000 | 0x00ee)
+#define NT_STATUS_INVALID_PARAMETER_1 (0xC0000000 | 0x00ef)
+#define NT_STATUS_INVALID_PARAMETER_2 (0xC0000000 | 0x00f0)
+#define NT_STATUS_INVALID_PARAMETER_3 (0xC0000000 | 0x00f1)
+#define NT_STATUS_INVALID_PARAMETER_4 (0xC0000000 | 0x00f2)
+#define NT_STATUS_INVALID_PARAMETER_5 (0xC0000000 | 0x00f3)
+#define NT_STATUS_INVALID_PARAMETER_6 (0xC0000000 | 0x00f4)
+#define NT_STATUS_INVALID_PARAMETER_7 (0xC0000000 | 0x00f5)
+#define NT_STATUS_INVALID_PARAMETER_8 (0xC0000000 | 0x00f6)
+#define NT_STATUS_INVALID_PARAMETER_9 (0xC0000000 | 0x00f7)
+#define NT_STATUS_INVALID_PARAMETER_10 (0xC0000000 | 0x00f8)
+#define NT_STATUS_INVALID_PARAMETER_11 (0xC0000000 | 0x00f9)
+#define NT_STATUS_INVALID_PARAMETER_12 (0xC0000000 | 0x00fa)
+#define NT_STATUS_REDIRECTOR_NOT_STARTED (0xC0000000 | 0x00fb)
+#define NT_STATUS_REDIRECTOR_STARTED (0xC0000000 | 0x00fc)
+#define NT_STATUS_STACK_OVERFLOW (0xC0000000 | 0x00fd)
+#define NT_STATUS_NO_SUCH_PACKAGE (0xC0000000 | 0x00fe)
+#define NT_STATUS_BAD_FUNCTION_TABLE (0xC0000000 | 0x00ff)
+#define NT_STATUS_DIRECTORY_NOT_EMPTY (0xC0000000 | 0x0101)
+#define NT_STATUS_FILE_CORRUPT_ERROR (0xC0000000 | 0x0102)
+#define NT_STATUS_NOT_A_DIRECTORY (0xC0000000 | 0x0103)
+#define NT_STATUS_BAD_LOGON_SESSION_STATE (0xC0000000 | 0x0104)
+#define NT_STATUS_LOGON_SESSION_COLLISION (0xC0000000 | 0x0105)
+#define NT_STATUS_NAME_TOO_LONG (0xC0000000 | 0x0106)
+#define NT_STATUS_FILES_OPEN (0xC0000000 | 0x0107)
+#define NT_STATUS_CONNECTION_IN_USE (0xC0000000 | 0x0108)
+#define NT_STATUS_MESSAGE_NOT_FOUND (0xC0000000 | 0x0109)
+#define NT_STATUS_PROCESS_IS_TERMINATING (0xC0000000 | 0x010a)
+#define NT_STATUS_INVALID_LOGON_TYPE (0xC0000000 | 0x010b)
+#define NT_STATUS_NO_GUID_TRANSLATION (0xC0000000 | 0x010c)
+#define NT_STATUS_CANNOT_IMPERSONATE (0xC0000000 | 0x010d)
+#define NT_STATUS_IMAGE_ALREADY_LOADED (0xC0000000 | 0x010e)
+#define NT_STATUS_ABIOS_NOT_PRESENT (0xC0000000 | 0x010f)
+#define NT_STATUS_ABIOS_LID_NOT_EXIST (0xC0000000 | 0x0110)
+#define NT_STATUS_ABIOS_LID_ALREADY_OWNED (0xC0000000 | 0x0111)
+#define NT_STATUS_ABIOS_NOT_LID_OWNER (0xC0000000 | 0x0112)
+#define NT_STATUS_ABIOS_INVALID_COMMAND (0xC0000000 | 0x0113)
+#define NT_STATUS_ABIOS_INVALID_LID (0xC0000000 | 0x0114)
+#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE (0xC0000000 | 0x0115)
+#define NT_STATUS_ABIOS_INVALID_SELECTOR (0xC0000000 | 0x0116)
+#define NT_STATUS_NO_LDT (0xC0000000 | 0x0117)
+#define NT_STATUS_INVALID_LDT_SIZE (0xC0000000 | 0x0118)
+#define NT_STATUS_INVALID_LDT_OFFSET (0xC0000000 | 0x0119)
+#define NT_STATUS_INVALID_LDT_DESCRIPTOR (0xC0000000 | 0x011a)
+#define NT_STATUS_INVALID_IMAGE_NE_FORMAT (0xC0000000 | 0x011b)
+#define NT_STATUS_RXACT_INVALID_STATE (0xC0000000 | 0x011c)
+#define NT_STATUS_RXACT_COMMIT_FAILURE (0xC0000000 | 0x011d)
+#define NT_STATUS_MAPPED_FILE_SIZE_ZERO (0xC0000000 | 0x011e)
+#define NT_STATUS_TOO_MANY_OPENED_FILES (0xC0000000 | 0x011f)
+#define NT_STATUS_CANCELLED (0xC0000000 | 0x0120)
+#define NT_STATUS_CANNOT_DELETE (0xC0000000 | 0x0121)
+#define NT_STATUS_INVALID_COMPUTER_NAME (0xC0000000 | 0x0122)
+#define NT_STATUS_FILE_DELETED (0xC0000000 | 0x0123)
+#define NT_STATUS_SPECIAL_ACCOUNT (0xC0000000 | 0x0124)
+#define NT_STATUS_SPECIAL_GROUP (0xC0000000 | 0x0125)
+#define NT_STATUS_SPECIAL_USER (0xC0000000 | 0x0126)
+#define NT_STATUS_MEMBERS_PRIMARY_GROUP (0xC0000000 | 0x0127)
+#define NT_STATUS_FILE_CLOSED (0xC0000000 | 0x0128)
+#define NT_STATUS_TOO_MANY_THREADS (0xC0000000 | 0x0129)
+#define NT_STATUS_THREAD_NOT_IN_PROCESS (0xC0000000 | 0x012a)
+#define NT_STATUS_TOKEN_ALREADY_IN_USE (0xC0000000 | 0x012b)
+#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED (0xC0000000 | 0x012c)
+#define NT_STATUS_COMMITMENT_LIMIT (0xC0000000 | 0x012d)
+#define NT_STATUS_INVALID_IMAGE_LE_FORMAT (0xC0000000 | 0x012e)
+#define NT_STATUS_INVALID_IMAGE_NOT_MZ (0xC0000000 | 0x012f)
+#define NT_STATUS_INVALID_IMAGE_PROTECT (0xC0000000 | 0x0130)
+#define NT_STATUS_INVALID_IMAGE_WIN_16 (0xC0000000 | 0x0131)
+#define NT_STATUS_LOGON_SERVER_CONFLICT (0xC0000000 | 0x0132)
+#define NT_STATUS_TIME_DIFFERENCE_AT_DC (0xC0000000 | 0x0133)
+#define NT_STATUS_SYNCHRONIZATION_REQUIRED (0xC0000000 | 0x0134)
+#define NT_STATUS_DLL_NOT_FOUND (0xC0000000 | 0x0135)
+#define NT_STATUS_OPEN_FAILED (0xC0000000 | 0x0136)
+#define NT_STATUS_IO_PRIVILEGE_FAILED (0xC0000000 | 0x0137)
+#define NT_STATUS_ORDINAL_NOT_FOUND (0xC0000000 | 0x0138)
+#define NT_STATUS_ENTRYPOINT_NOT_FOUND (0xC0000000 | 0x0139)
+#define NT_STATUS_CONTROL_C_EXIT (0xC0000000 | 0x013a)
+#define NT_STATUS_LOCAL_DISCONNECT (0xC0000000 | 0x013b)
+#define NT_STATUS_REMOTE_DISCONNECT (0xC0000000 | 0x013c)
+#define NT_STATUS_REMOTE_RESOURCES (0xC0000000 | 0x013d)
+#define NT_STATUS_LINK_FAILED (0xC0000000 | 0x013e)
+#define NT_STATUS_LINK_TIMEOUT (0xC0000000 | 0x013f)
+#define NT_STATUS_INVALID_CONNECTION (0xC0000000 | 0x0140)
+#define NT_STATUS_INVALID_ADDRESS (0xC0000000 | 0x0141)
+#define NT_STATUS_DLL_INIT_FAILED (0xC0000000 | 0x0142)
+#define NT_STATUS_MISSING_SYSTEMFILE (0xC0000000 | 0x0143)
+#define NT_STATUS_UNHANDLED_EXCEPTION (0xC0000000 | 0x0144)
+#define NT_STATUS_APP_INIT_FAILURE (0xC0000000 | 0x0145)
+#define NT_STATUS_PAGEFILE_CREATE_FAILED (0xC0000000 | 0x0146)
+#define NT_STATUS_NO_PAGEFILE (0xC0000000 | 0x0147)
+#define NT_STATUS_INVALID_LEVEL (0xC0000000 | 0x0148)
+#define NT_STATUS_WRONG_PASSWORD_CORE (0xC0000000 | 0x0149)
+#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT (0xC0000000 | 0x014a)
+#define NT_STATUS_PIPE_BROKEN (0xC0000000 | 0x014b)
+#define NT_STATUS_REGISTRY_CORRUPT (0xC0000000 | 0x014c)
+#define NT_STATUS_REGISTRY_IO_FAILED (0xC0000000 | 0x014d)
+#define NT_STATUS_NO_EVENT_PAIR (0xC0000000 | 0x014e)
+#define NT_STATUS_UNRECOGNIZED_VOLUME (0xC0000000 | 0x014f)
+#define NT_STATUS_SERIAL_NO_DEVICE_INITED (0xC0000000 | 0x0150)
+#define NT_STATUS_NO_SUCH_ALIAS (0xC0000000 | 0x0151)
+#define NT_STATUS_MEMBER_NOT_IN_ALIAS (0xC0000000 | 0x0152)
+#define NT_STATUS_MEMBER_IN_ALIAS (0xC0000000 | 0x0153)
+#define NT_STATUS_ALIAS_EXISTS (0xC0000000 | 0x0154)
+#define NT_STATUS_LOGON_NOT_GRANTED (0xC0000000 | 0x0155)
+#define NT_STATUS_TOO_MANY_SECRETS (0xC0000000 | 0x0156)
+#define NT_STATUS_SECRET_TOO_LONG (0xC0000000 | 0x0157)
+#define NT_STATUS_INTERNAL_DB_ERROR (0xC0000000 | 0x0158)
+#define NT_STATUS_FULLSCREEN_MODE (0xC0000000 | 0x0159)
+#define NT_STATUS_TOO_MANY_CONTEXT_IDS (0xC0000000 | 0x015a)
+#define NT_STATUS_LOGON_TYPE_NOT_GRANTED (0xC0000000 | 0x015b)
+#define NT_STATUS_NOT_REGISTRY_FILE (0xC0000000 | 0x015c)
+#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED (0xC0000000 | 0x015d)
+#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR (0xC0000000 | 0x015e)
+#define NT_STATUS_FT_MISSING_MEMBER (0xC0000000 | 0x015f)
+#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY (0xC0000000 | 0x0160)
+#define NT_STATUS_ILLEGAL_CHARACTER (0xC0000000 | 0x0161)
+#define NT_STATUS_UNMAPPABLE_CHARACTER (0xC0000000 | 0x0162)
+#define NT_STATUS_UNDEFINED_CHARACTER (0xC0000000 | 0x0163)
+#define NT_STATUS_FLOPPY_VOLUME (0xC0000000 | 0x0164)
+#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND (0xC0000000 | 0x0165)
+#define NT_STATUS_FLOPPY_WRONG_CYLINDER (0xC0000000 | 0x0166)
+#define NT_STATUS_FLOPPY_UNKNOWN_ERROR (0xC0000000 | 0x0167)
+#define NT_STATUS_FLOPPY_BAD_REGISTERS (0xC0000000 | 0x0168)
+#define NT_STATUS_DISK_RECALIBRATE_FAILED (0xC0000000 | 0x0169)
+#define NT_STATUS_DISK_OPERATION_FAILED (0xC0000000 | 0x016a)
+#define NT_STATUS_DISK_RESET_FAILED (0xC0000000 | 0x016b)
+#define NT_STATUS_SHARED_IRQ_BUSY (0xC0000000 | 0x016c)
+#define NT_STATUS_FT_ORPHANING (0xC0000000 | 0x016d)
+#define NT_STATUS_PARTITION_FAILURE (0xC0000000 | 0x0172)
+#define NT_STATUS_INVALID_BLOCK_LENGTH (0xC0000000 | 0x0173)
+#define NT_STATUS_DEVICE_NOT_PARTITIONED (0xC0000000 | 0x0174)
+#define NT_STATUS_UNABLE_TO_LOCK_MEDIA (0xC0000000 | 0x0175)
+#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA (0xC0000000 | 0x0176)
+#define NT_STATUS_EOM_OVERFLOW (0xC0000000 | 0x0177)
+#define NT_STATUS_NO_MEDIA (0xC0000000 | 0x0178)
+#define NT_STATUS_NO_SUCH_MEMBER (0xC0000000 | 0x017a)
+#define NT_STATUS_INVALID_MEMBER (0xC0000000 | 0x017b)
+#define NT_STATUS_KEY_DELETED (0xC0000000 | 0x017c)
+#define NT_STATUS_NO_LOG_SPACE (0xC0000000 | 0x017d)
+#define NT_STATUS_TOO_MANY_SIDS (0xC0000000 | 0x017e)
+#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED (0xC0000000 | 0x017f)
+#define NT_STATUS_KEY_HAS_CHILDREN (0xC0000000 | 0x0180)
+#define NT_STATUS_CHILD_MUST_BE_VOLATILE (0xC0000000 | 0x0181)
+#define NT_STATUS_DEVICE_CONFIGURATION_ERROR (0xC0000000 | 0x0182)
+#define NT_STATUS_DRIVER_INTERNAL_ERROR (0xC0000000 | 0x0183)
+#define NT_STATUS_INVALID_DEVICE_STATE (0xC0000000 | 0x0184)
+#define NT_STATUS_IO_DEVICE_ERROR (0xC0000000 | 0x0185)
+#define NT_STATUS_DEVICE_PROTOCOL_ERROR (0xC0000000 | 0x0186)
+#define NT_STATUS_BACKUP_CONTROLLER (0xC0000000 | 0x0187)
+#define NT_STATUS_LOG_FILE_FULL (0xC0000000 | 0x0188)
+#define NT_STATUS_TOO_LATE (0xC0000000 | 0x0189)
+#define NT_STATUS_NO_TRUST_LSA_SECRET (0xC0000000 | 0x018a)
+#define NT_STATUS_NO_TRUST_SAM_ACCOUNT (0xC0000000 | 0x018b)
+#define NT_STATUS_TRUSTED_DOMAIN_FAILURE (0xC0000000 | 0x018c)
+#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE (0xC0000000 | 0x018d)
+#define NT_STATUS_EVENTLOG_FILE_CORRUPT (0xC0000000 | 0x018e)
+#define NT_STATUS_EVENTLOG_CANT_START (0xC0000000 | 0x018f)
+#define NT_STATUS_TRUST_FAILURE (0xC0000000 | 0x0190)
+#define NT_STATUS_MUTANT_LIMIT_EXCEEDED (0xC0000000 | 0x0191)
+#define NT_STATUS_NETLOGON_NOT_STARTED (0xC0000000 | 0x0192)
+#define NT_STATUS_ACCOUNT_EXPIRED (0xC0000000 | 0x0193)
+#define NT_STATUS_POSSIBLE_DEADLOCK (0xC0000000 | 0x0194)
+#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT (0xC0000000 | 0x0195)
+#define NT_STATUS_REMOTE_SESSION_LIMIT (0xC0000000 | 0x0196)
+#define NT_STATUS_EVENTLOG_FILE_CHANGED (0xC0000000 | 0x0197)
+#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT (0xC0000000 | 0x0198)
+#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT (0xC0000000 | 0x0199)
+#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT (0xC0000000 | 0x019a)
+#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT (0xC0000000 | 0x019b)
+#define NT_STATUS_FS_DRIVER_REQUIRED (0xC0000000 | 0x019c)
+#define NT_STATUS_NO_USER_SESSION_KEY (0xC0000000 | 0x0202)
+#define NT_STATUS_USER_SESSION_DELETED (0xC0000000 | 0x0203)
+#define NT_STATUS_RESOURCE_LANG_NOT_FOUND (0xC0000000 | 0x0204)
+#define NT_STATUS_INSUFF_SERVER_RESOURCES (0xC0000000 | 0x0205)
+#define NT_STATUS_INVALID_BUFFER_SIZE (0xC0000000 | 0x0206)
+#define NT_STATUS_INVALID_ADDRESS_COMPONENT (0xC0000000 | 0x0207)
+#define NT_STATUS_INVALID_ADDRESS_WILDCARD (0xC0000000 | 0x0208)
+#define NT_STATUS_TOO_MANY_ADDRESSES (0xC0000000 | 0x0209)
+#define NT_STATUS_ADDRESS_ALREADY_EXISTS (0xC0000000 | 0x020a)
+#define NT_STATUS_ADDRESS_CLOSED (0xC0000000 | 0x020b)
+#define NT_STATUS_CONNECTION_DISCONNECTED (0xC0000000 | 0x020c)
+#define NT_STATUS_CONNECTION_RESET (0xC0000000 | 0x020d)
+#define NT_STATUS_TOO_MANY_NODES (0xC0000000 | 0x020e)
+#define NT_STATUS_TRANSACTION_ABORTED (0xC0000000 | 0x020f)
+#define NT_STATUS_TRANSACTION_TIMED_OUT (0xC0000000 | 0x0210)
+#define NT_STATUS_TRANSACTION_NO_RELEASE (0xC0000000 | 0x0211)
+#define NT_STATUS_TRANSACTION_NO_MATCH (0xC0000000 | 0x0212)
+#define NT_STATUS_TRANSACTION_RESPONDED (0xC0000000 | 0x0213)
+#define NT_STATUS_TRANSACTION_INVALID_ID (0xC0000000 | 0x0214)
+#define NT_STATUS_TRANSACTION_INVALID_TYPE (0xC0000000 | 0x0215)
+#define NT_STATUS_NOT_SERVER_SESSION (0xC0000000 | 0x0216)
+#define NT_STATUS_NOT_CLIENT_SESSION (0xC0000000 | 0x0217)
+#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE (0xC0000000 | 0x0218)
+#define NT_STATUS_DEBUG_ATTACH_FAILED (0xC0000000 | 0x0219)
+#define NT_STATUS_SYSTEM_PROCESS_TERMINATED (0xC0000000 | 0x021a)
+#define NT_STATUS_DATA_NOT_ACCEPTED (0xC0000000 | 0x021b)
+#define NT_STATUS_NO_BROWSER_SERVERS_FOUND (0xC0000000 | 0x021c)
+#define NT_STATUS_VDM_HARD_ERROR (0xC0000000 | 0x021d)
+#define NT_STATUS_DRIVER_CANCEL_TIMEOUT (0xC0000000 | 0x021e)
+#define NT_STATUS_REPLY_MESSAGE_MISMATCH (0xC0000000 | 0x021f)
+#define NT_STATUS_MAPPED_ALIGNMENT (0xC0000000 | 0x0220)
+#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH (0xC0000000 | 0x0221)
+#define NT_STATUS_LOST_WRITEBEHIND_DATA (0xC0000000 | 0x0222)
+#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID (0xC0000000 | 0x0223)
+#define NT_STATUS_PASSWORD_MUST_CHANGE (0xC0000000 | 0x0224)
+#define NT_STATUS_NOT_FOUND (0xC0000000 | 0x0225)
+#define NT_STATUS_NOT_TINY_STREAM (0xC0000000 | 0x0226)
+#define NT_STATUS_RECOVERY_FAILURE (0xC0000000 | 0x0227)
+#define NT_STATUS_STACK_OVERFLOW_READ (0xC0000000 | 0x0228)
+#define NT_STATUS_FAIL_CHECK (0xC0000000 | 0x0229)
+#define NT_STATUS_DUPLICATE_OBJECTID (0xC0000000 | 0x022a)
+#define NT_STATUS_OBJECTID_EXISTS (0xC0000000 | 0x022b)
+#define NT_STATUS_CONVERT_TO_LARGE (0xC0000000 | 0x022c)
+#define NT_STATUS_RETRY (0xC0000000 | 0x022d)
+#define NT_STATUS_FOUND_OUT_OF_SCOPE (0xC0000000 | 0x022e)
+#define NT_STATUS_ALLOCATE_BUCKET (0xC0000000 | 0x022f)
+#define NT_STATUS_PROPSET_NOT_FOUND (0xC0000000 | 0x0230)
+#define NT_STATUS_MARSHALL_OVERFLOW (0xC0000000 | 0x0231)
+#define NT_STATUS_INVALID_VARIANT (0xC0000000 | 0x0232)
+#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND (0xC0000000 | 0x0233)
+#define NT_STATUS_ACCOUNT_LOCKED_OUT (0xC0000000 | 0x0234)
+#define NT_STATUS_HANDLE_NOT_CLOSABLE (0xC0000000 | 0x0235)
+#define NT_STATUS_CONNECTION_REFUSED (0xC0000000 | 0x0236)
+#define NT_STATUS_GRACEFUL_DISCONNECT (0xC0000000 | 0x0237)
+#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED (0xC0000000 | 0x0238)
+#define NT_STATUS_ADDRESS_NOT_ASSOCIATED (0xC0000000 | 0x0239)
+#define NT_STATUS_CONNECTION_INVALID (0xC0000000 | 0x023a)
+#define NT_STATUS_CONNECTION_ACTIVE (0xC0000000 | 0x023b)
+#define NT_STATUS_NETWORK_UNREACHABLE (0xC0000000 | 0x023c)
+#define NT_STATUS_HOST_UNREACHABLE (0xC0000000 | 0x023d)
+#define NT_STATUS_PROTOCOL_UNREACHABLE (0xC0000000 | 0x023e)
+#define NT_STATUS_PORT_UNREACHABLE (0xC0000000 | 0x023f)
+#define NT_STATUS_REQUEST_ABORTED (0xC0000000 | 0x0240)
+#define NT_STATUS_CONNECTION_ABORTED (0xC0000000 | 0x0241)
+#define NT_STATUS_BAD_COMPRESSION_BUFFER (0xC0000000 | 0x0242)
+#define NT_STATUS_USER_MAPPED_FILE (0xC0000000 | 0x0243)
+#define NT_STATUS_AUDIT_FAILED (0xC0000000 | 0x0244)
+#define NT_STATUS_TIMER_RESOLUTION_NOT_SET (0xC0000000 | 0x0245)
+#define NT_STATUS_CONNECTION_COUNT_LIMIT (0xC0000000 | 0x0246)
+#define NT_STATUS_LOGIN_TIME_RESTRICTION (0xC0000000 | 0x0247)
+#define NT_STATUS_LOGIN_WKSTA_RESTRICTION (0xC0000000 | 0x0248)
+#define NT_STATUS_IMAGE_MP_UP_MISMATCH (0xC0000000 | 0x0249)
+#define NT_STATUS_INSUFFICIENT_LOGON_INFO (0xC0000000 | 0x0250)
+#define NT_STATUS_BAD_DLL_ENTRYPOINT (0xC0000000 | 0x0251)
+#define NT_STATUS_BAD_SERVICE_ENTRYPOINT (0xC0000000 | 0x0252)
+#define NT_STATUS_LPC_REPLY_LOST (0xC0000000 | 0x0253)
+#define NT_STATUS_IP_ADDRESS_CONFLICT1 (0xC0000000 | 0x0254)
+#define NT_STATUS_IP_ADDRESS_CONFLICT2 (0xC0000000 | 0x0255)
+#define NT_STATUS_REGISTRY_QUOTA_LIMIT (0xC0000000 | 0x0256)
+#define NT_STATUS_PATH_NOT_COVERED (0xC0000000 | 0x0257)
+#define NT_STATUS_NO_CALLBACK_ACTIVE (0xC0000000 | 0x0258)
+#define NT_STATUS_LICENSE_QUOTA_EXCEEDED (0xC0000000 | 0x0259)
+#define NT_STATUS_PWD_TOO_SHORT (0xC0000000 | 0x025a)
+#define NT_STATUS_PWD_TOO_RECENT (0xC0000000 | 0x025b)
+#define NT_STATUS_PWD_HISTORY_CONFLICT (0xC0000000 | 0x025c)
+#define NT_STATUS_PLUGPLAY_NO_DEVICE (0xC0000000 | 0x025e)
+#define NT_STATUS_UNSUPPORTED_COMPRESSION (0xC0000000 | 0x025f)
+#define NT_STATUS_INVALID_HW_PROFILE (0xC0000000 | 0x0260)
+#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH (0xC0000000 | 0x0261)
+#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND (0xC0000000 | 0x0262)
+#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND (0xC0000000 | 0x0263)
+#define NT_STATUS_RESOURCE_NOT_OWNED (0xC0000000 | 0x0264)
+#define NT_STATUS_TOO_MANY_LINKS (0xC0000000 | 0x0265)
+#define NT_STATUS_QUOTA_LIST_INCONSISTENT (0xC0000000 | 0x0266)
+#define NT_STATUS_FILE_IS_OFFLINE (0xC0000000 | 0x0267)
+#define NT_STATUS_NETWORK_SESSION_EXPIRED (0xC0000000 | 0x035c)
+#define NT_STATUS_NO_SUCH_JOB (0xC0000000 | 0xEDE) /* scheduler */
+#define NT_STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP (0xC0000000 | 0x5D0000)
+#define NT_STATUS_PENDING 0x00000103
+#endif /* _NTERR_H */
diff --git a/fs/smb/server/ntlmssp.h b/fs/smb/server/ntlmssp.h
new file mode 100644
index 000000000000..f13153c18b4e
--- /dev/null
+++ b/fs/smb/server/ntlmssp.h
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/*
+ * Copyright (c) International Business Machines Corp., 2002,2007
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ */
+
+#ifndef __KSMBD_NTLMSSP_H
+#define __KSMBD_NTLMSSP_H
+
+#define NTLMSSP_SIGNATURE "NTLMSSP"
+
+/* Security blob target info data */
+#define TGT_Name "KSMBD"
+
+/*
+ * Size of the crypto key returned on the negotiate SMB in bytes
+ */
+#define CIFS_CRYPTO_KEY_SIZE (8)
+#define CIFS_KEY_SIZE (40)
+
+/*
+ * Size of encrypted user password in bytes
+ */
+#define CIFS_ENCPWD_SIZE (16)
+#define CIFS_CPHTXT_SIZE (16)
+
+/* Message Types */
+#define NtLmNegotiate cpu_to_le32(1)
+#define NtLmChallenge cpu_to_le32(2)
+#define NtLmAuthenticate cpu_to_le32(3)
+#define UnknownMessage cpu_to_le32(8)
+
+/* Negotiate Flags */
+#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */
+#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
+#define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */
+/* define reserved9 0x08 */
+#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */
+#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
+#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
+#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */
+/* defined reserved 8 0x0100 */
+#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
+#define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */
+#define NTLMSSP_ANONYMOUS 0x0800
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */
+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
+#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */
+#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
+#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
+#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
+#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/
+/* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */
+#define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000
+#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */
+#define NTLMSSP_REQUEST_NON_NT_KEY 0x400000
+#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
+/* #define reserved4 0x1000000 */
+#define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we do not set */
+/* #define reserved3 0x4000000 */
+/* #define reserved2 0x8000000 */
+/* #define reserved1 0x10000000 */
+#define NTLMSSP_NEGOTIATE_128 0x20000000
+#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
+#define NTLMSSP_NEGOTIATE_56 0x80000000
+
+/* Define AV Pair Field IDs */
+enum av_field_type {
+ NTLMSSP_AV_EOL = 0,
+ NTLMSSP_AV_NB_COMPUTER_NAME,
+ NTLMSSP_AV_NB_DOMAIN_NAME,
+ NTLMSSP_AV_DNS_COMPUTER_NAME,
+ NTLMSSP_AV_DNS_DOMAIN_NAME,
+ NTLMSSP_AV_DNS_TREE_NAME,
+ NTLMSSP_AV_FLAGS,
+ NTLMSSP_AV_TIMESTAMP,
+ NTLMSSP_AV_RESTRICTION,
+ NTLMSSP_AV_TARGET_NAME,
+ NTLMSSP_AV_CHANNEL_BINDINGS
+};
+
+/* Although typedefs are not commonly used for structure definitions */
+/* in the Linux kernel, in this particular case they are useful */
+/* to more closely match the standards document for NTLMSSP from */
+/* OpenGroup and to make the code more closely match the standard in */
+/* appearance */
+
+struct security_buffer {
+ __le16 Length;
+ __le16 MaximumLength;
+ __le32 BufferOffset; /* offset to buffer */
+} __packed;
+
+struct target_info {
+ __le16 Type;
+ __le16 Length;
+ __u8 Content[];
+} __packed;
+
+struct negotiate_message {
+ __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+ __le32 MessageType; /* NtLmNegotiate = 1 */
+ __le32 NegotiateFlags;
+ struct security_buffer DomainName; /* RFC 1001 style and ASCII */
+ struct security_buffer WorkstationName; /* RFC 1001 and ASCII */
+ /*
+ * struct security_buffer for version info not present since we
+ * do not set the version is present flag
+ */
+ char DomainString[];
+ /* followed by WorkstationString */
+} __packed;
+
+struct challenge_message {
+ __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+ __le32 MessageType; /* NtLmChallenge = 2 */
+ struct security_buffer TargetName;
+ __le32 NegotiateFlags;
+ __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
+ __u8 Reserved[8];
+ struct security_buffer TargetInfoArray;
+ /*
+ * struct security_buffer for version info not present since we
+ * do not set the version is present flag
+ */
+} __packed;
+
+struct authenticate_message {
+ __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+ __le32 MessageType; /* NtLmsAuthenticate = 3 */
+ struct security_buffer LmChallengeResponse;
+ struct security_buffer NtChallengeResponse;
+ struct security_buffer DomainName;
+ struct security_buffer UserName;
+ struct security_buffer WorkstationName;
+ struct security_buffer SessionKey;
+ __le32 NegotiateFlags;
+ /*
+ * struct security_buffer for version info not present since we
+ * do not set the version is present flag
+ */
+ char UserString[];
+} __packed;
+
+struct ntlmv2_resp {
+ char ntlmv2_hash[CIFS_ENCPWD_SIZE];
+ __le32 blob_signature;
+ __u32 reserved;
+ __le64 time;
+ __u64 client_chal; /* random */
+ __u32 reserved2;
+ /* array of name entries could follow ending in minimum 4 byte struct */
+} __packed;
+
+/* per smb session structure/fields */
+struct ntlmssp_auth {
+ /* whether session key is per smb session */
+ bool sesskey_per_smbsess;
+ /* sent by client in type 1 ntlmsssp exchange */
+ __u32 client_flags;
+ /* sent by server in type 2 ntlmssp exchange */
+ __u32 conn_flags;
+ /* sent to server */
+ unsigned char ciphertext[CIFS_CPHTXT_SIZE];
+ /* used by ntlmssp */
+ char cryptkey[CIFS_CRYPTO_KEY_SIZE];
+};
+#endif /* __KSMBD_NTLMSSP_H */
diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
new file mode 100644
index 000000000000..4b210cdd7556
--- /dev/null
+++ b/fs/smb/server/oplock.c
@@ -0,0 +1,1722 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/moduleparam.h>
+
+#include "glob.h"
+#include "oplock.h"
+
+#include "smb_common.h"
+#include "smbstatus.h"
+#include "connection.h"
+#include "mgmt/user_session.h"
+#include "mgmt/share_config.h"
+#include "mgmt/tree_connect.h"
+
+static LIST_HEAD(lease_table_list);
+static DEFINE_RWLOCK(lease_list_lock);
+
+/**
+ * alloc_opinfo() - allocate a new opinfo object for oplock info
+ * @work: smb work
+ * @id: fid of open file
+ * @Tid: tree id of connection
+ *
+ * Return: allocated opinfo object on success, otherwise NULL
+ */
+static struct oplock_info *alloc_opinfo(struct ksmbd_work *work,
+ u64 id, __u16 Tid)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_session *sess = work->sess;
+ struct oplock_info *opinfo;
+
+ opinfo = kzalloc(sizeof(struct oplock_info), GFP_KERNEL);
+ if (!opinfo)
+ return NULL;
+
+ opinfo->sess = sess;
+ opinfo->conn = conn;
+ opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
+ opinfo->op_state = OPLOCK_STATE_NONE;
+ opinfo->pending_break = 0;
+ opinfo->fid = id;
+ opinfo->Tid = Tid;
+ INIT_LIST_HEAD(&opinfo->op_entry);
+ INIT_LIST_HEAD(&opinfo->interim_list);
+ init_waitqueue_head(&opinfo->oplock_q);
+ init_waitqueue_head(&opinfo->oplock_brk);
+ atomic_set(&opinfo->refcount, 1);
+ atomic_set(&opinfo->breaking_cnt, 0);
+
+ return opinfo;
+}
+
+static void lease_add_list(struct oplock_info *opinfo)
+{
+ struct lease_table *lb = opinfo->o_lease->l_lb;
+
+ spin_lock(&lb->lb_lock);
+ list_add_rcu(&opinfo->lease_entry, &lb->lease_list);
+ spin_unlock(&lb->lb_lock);
+}
+
+static void lease_del_list(struct oplock_info *opinfo)
+{
+ struct lease_table *lb = opinfo->o_lease->l_lb;
+
+ if (!lb)
+ return;
+
+ spin_lock(&lb->lb_lock);
+ if (list_empty(&opinfo->lease_entry)) {
+ spin_unlock(&lb->lb_lock);
+ return;
+ }
+
+ list_del_init(&opinfo->lease_entry);
+ opinfo->o_lease->l_lb = NULL;
+ spin_unlock(&lb->lb_lock);
+}
+
+static void lb_add(struct lease_table *lb)
+{
+ write_lock(&lease_list_lock);
+ list_add(&lb->l_entry, &lease_table_list);
+ write_unlock(&lease_list_lock);
+}
+
+static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx)
+{
+ struct lease *lease;
+
+ lease = kmalloc(sizeof(struct lease), GFP_KERNEL);
+ if (!lease)
+ return -ENOMEM;
+
+ memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);
+ lease->state = lctx->req_state;
+ lease->new_state = 0;
+ lease->flags = lctx->flags;
+ lease->duration = lctx->duration;
+ memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE);
+ lease->version = lctx->version;
+ lease->epoch = 0;
+ INIT_LIST_HEAD(&opinfo->lease_entry);
+ opinfo->o_lease = lease;
+
+ return 0;
+}
+
+static void free_lease(struct oplock_info *opinfo)
+{
+ struct lease *lease;
+
+ lease = opinfo->o_lease;
+ kfree(lease);
+}
+
+static void free_opinfo(struct oplock_info *opinfo)
+{
+ if (opinfo->is_lease)
+ free_lease(opinfo);
+ kfree(opinfo);
+}
+
+static inline void opinfo_free_rcu(struct rcu_head *rcu_head)
+{
+ struct oplock_info *opinfo;
+
+ opinfo = container_of(rcu_head, struct oplock_info, rcu_head);
+ free_opinfo(opinfo);
+}
+
+struct oplock_info *opinfo_get(struct ksmbd_file *fp)
+{
+ struct oplock_info *opinfo;
+
+ rcu_read_lock();
+ opinfo = rcu_dereference(fp->f_opinfo);
+ if (opinfo && !atomic_inc_not_zero(&opinfo->refcount))
+ opinfo = NULL;
+ rcu_read_unlock();
+
+ return opinfo;
+}
+
+static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
+{
+ struct oplock_info *opinfo;
+
+ if (list_empty(&ci->m_op_list))
+ return NULL;
+
+ rcu_read_lock();
+ opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info,
+ op_entry);
+ if (opinfo) {
+ if (!atomic_inc_not_zero(&opinfo->refcount))
+ opinfo = NULL;
+ else {
+ atomic_inc(&opinfo->conn->r_count);
+ if (ksmbd_conn_releasing(opinfo->conn)) {
+ atomic_dec(&opinfo->conn->r_count);
+ atomic_dec(&opinfo->refcount);
+ opinfo = NULL;
+ }
+ }
+ }
+
+ rcu_read_unlock();
+
+ return opinfo;
+}
+
+static void opinfo_conn_put(struct oplock_info *opinfo)
+{
+ struct ksmbd_conn *conn;
+
+ if (!opinfo)
+ return;
+
+ conn = opinfo->conn;
+ /*
+ * Checking waitqueue to dropping pending requests on
+ * disconnection. waitqueue_active is safe because it
+ * uses atomic operation for condition.
+ */
+ if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
+ wake_up(&conn->r_count_q);
+ opinfo_put(opinfo);
+}
+
+void opinfo_put(struct oplock_info *opinfo)
+{
+ if (!atomic_dec_and_test(&opinfo->refcount))
+ return;
+
+ call_rcu(&opinfo->rcu_head, opinfo_free_rcu);
+}
+
+static void opinfo_add(struct oplock_info *opinfo)
+{
+ struct ksmbd_inode *ci = opinfo->o_fp->f_ci;
+
+ write_lock(&ci->m_lock);
+ list_add_rcu(&opinfo->op_entry, &ci->m_op_list);
+ write_unlock(&ci->m_lock);
+}
+
+static void opinfo_del(struct oplock_info *opinfo)
+{
+ struct ksmbd_inode *ci = opinfo->o_fp->f_ci;
+
+ if (opinfo->is_lease) {
+ write_lock(&lease_list_lock);
+ lease_del_list(opinfo);
+ write_unlock(&lease_list_lock);
+ }
+ write_lock(&ci->m_lock);
+ list_del_rcu(&opinfo->op_entry);
+ write_unlock(&ci->m_lock);
+}
+
+static unsigned long opinfo_count(struct ksmbd_file *fp)
+{
+ if (ksmbd_stream_fd(fp))
+ return atomic_read(&fp->f_ci->sop_count);
+ else
+ return atomic_read(&fp->f_ci->op_count);
+}
+
+static void opinfo_count_inc(struct ksmbd_file *fp)
+{
+ if (ksmbd_stream_fd(fp))
+ return atomic_inc(&fp->f_ci->sop_count);
+ else
+ return atomic_inc(&fp->f_ci->op_count);
+}
+
+static void opinfo_count_dec(struct ksmbd_file *fp)
+{
+ if (ksmbd_stream_fd(fp))
+ return atomic_dec(&fp->f_ci->sop_count);
+ else
+ return atomic_dec(&fp->f_ci->op_count);
+}
+
+/**
+ * opinfo_write_to_read() - convert a write oplock to read oplock
+ * @opinfo: current oplock info
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+int opinfo_write_to_read(struct oplock_info *opinfo)
+{
+ struct lease *lease = opinfo->o_lease;
+
+ if (!(opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||
+ opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) {
+ pr_err("bad oplock(0x%x)\n", opinfo->level);
+ if (opinfo->is_lease)
+ pr_err("lease state(0x%x)\n", lease->state);
+ return -EINVAL;
+ }
+ opinfo->level = SMB2_OPLOCK_LEVEL_II;
+
+ if (opinfo->is_lease)
+ lease->state = lease->new_state;
+ return 0;
+}
+
+/**
+ * opinfo_read_handle_to_read() - convert a read/handle oplock to read oplock
+ * @opinfo: current oplock info
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+int opinfo_read_handle_to_read(struct oplock_info *opinfo)
+{
+ struct lease *lease = opinfo->o_lease;
+
+ lease->state = lease->new_state;
+ opinfo->level = SMB2_OPLOCK_LEVEL_II;
+ return 0;
+}
+
+/**
+ * opinfo_write_to_none() - convert a write oplock to none
+ * @opinfo: current oplock info
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+int opinfo_write_to_none(struct oplock_info *opinfo)
+{
+ struct lease *lease = opinfo->o_lease;
+
+ if (!(opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||
+ opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) {
+ pr_err("bad oplock(0x%x)\n", opinfo->level);
+ if (opinfo->is_lease)
+ pr_err("lease state(0x%x)\n", lease->state);
+ return -EINVAL;
+ }
+ opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
+ if (opinfo->is_lease)
+ lease->state = lease->new_state;
+ return 0;
+}
+
+/**
+ * opinfo_read_to_none() - convert a write read to none
+ * @opinfo: current oplock info
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+int opinfo_read_to_none(struct oplock_info *opinfo)
+{
+ struct lease *lease = opinfo->o_lease;
+
+ if (opinfo->level != SMB2_OPLOCK_LEVEL_II) {
+ pr_err("bad oplock(0x%x)\n", opinfo->level);
+ if (opinfo->is_lease)
+ pr_err("lease state(0x%x)\n", lease->state);
+ return -EINVAL;
+ }
+ opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
+ if (opinfo->is_lease)
+ lease->state = lease->new_state;
+ return 0;
+}
+
+/**
+ * lease_read_to_write() - upgrade lease state from read to write
+ * @opinfo: current lease info
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+int lease_read_to_write(struct oplock_info *opinfo)
+{
+ struct lease *lease = opinfo->o_lease;
+
+ if (!(lease->state & SMB2_LEASE_READ_CACHING_LE)) {
+ ksmbd_debug(OPLOCK, "bad lease state(0x%x)\n", lease->state);
+ return -EINVAL;
+ }
+
+ lease->new_state = SMB2_LEASE_NONE_LE;
+ lease->state |= SMB2_LEASE_WRITE_CACHING_LE;
+ if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
+ opinfo->level = SMB2_OPLOCK_LEVEL_BATCH;
+ else
+ opinfo->level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
+ return 0;
+}
+
+/**
+ * lease_none_upgrade() - upgrade lease state from none
+ * @opinfo: current lease info
+ * @new_state: new lease state
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+static int lease_none_upgrade(struct oplock_info *opinfo, __le32 new_state)
+{
+ struct lease *lease = opinfo->o_lease;
+
+ if (!(lease->state == SMB2_LEASE_NONE_LE)) {
+ ksmbd_debug(OPLOCK, "bad lease state(0x%x)\n", lease->state);
+ return -EINVAL;
+ }
+
+ lease->new_state = SMB2_LEASE_NONE_LE;
+ lease->state = new_state;
+ if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
+ if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
+ opinfo->level = SMB2_OPLOCK_LEVEL_BATCH;
+ else
+ opinfo->level = SMB2_OPLOCK_LEVEL_II;
+ else if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
+ opinfo->level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
+ else if (lease->state & SMB2_LEASE_READ_CACHING_LE)
+ opinfo->level = SMB2_OPLOCK_LEVEL_II;
+
+ return 0;
+}
+
+/**
+ * close_id_del_oplock() - release oplock object at file close time
+ * @fp: ksmbd file pointer
+ */
+void close_id_del_oplock(struct ksmbd_file *fp)
+{
+ struct oplock_info *opinfo;
+
+ if (S_ISDIR(file_inode(fp->filp)->i_mode))
+ return;
+
+ opinfo = opinfo_get(fp);
+ if (!opinfo)
+ return;
+
+ opinfo_del(opinfo);
+
+ rcu_assign_pointer(fp->f_opinfo, NULL);
+ if (opinfo->op_state == OPLOCK_ACK_WAIT) {
+ opinfo->op_state = OPLOCK_CLOSING;
+ wake_up_interruptible_all(&opinfo->oplock_q);
+ if (opinfo->is_lease) {
+ atomic_set(&opinfo->breaking_cnt, 0);
+ wake_up_interruptible_all(&opinfo->oplock_brk);
+ }
+ }
+
+ opinfo_count_dec(fp);
+ atomic_dec(&opinfo->refcount);
+ opinfo_put(opinfo);
+}
+
+/**
+ * grant_write_oplock() - grant exclusive/batch oplock or write lease
+ * @opinfo_new: new oplock info object
+ * @req_oplock: request oplock
+ * @lctx: lease context information
+ *
+ * Return: 0
+ */
+static void grant_write_oplock(struct oplock_info *opinfo_new, int req_oplock,
+ struct lease_ctx_info *lctx)
+{
+ struct lease *lease = opinfo_new->o_lease;
+
+ if (req_oplock == SMB2_OPLOCK_LEVEL_BATCH)
+ opinfo_new->level = SMB2_OPLOCK_LEVEL_BATCH;
+ else
+ opinfo_new->level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
+
+ if (lctx) {
+ lease->state = lctx->req_state;
+ memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);
+ }
+}
+
+/**
+ * grant_read_oplock() - grant level2 oplock or read lease
+ * @opinfo_new: new oplock info object
+ * @lctx: lease context information
+ *
+ * Return: 0
+ */
+static void grant_read_oplock(struct oplock_info *opinfo_new,
+ struct lease_ctx_info *lctx)
+{
+ struct lease *lease = opinfo_new->o_lease;
+
+ opinfo_new->level = SMB2_OPLOCK_LEVEL_II;
+
+ if (lctx) {
+ lease->state = SMB2_LEASE_READ_CACHING_LE;
+ if (lctx->req_state & SMB2_LEASE_HANDLE_CACHING_LE)
+ lease->state |= SMB2_LEASE_HANDLE_CACHING_LE;
+ memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);
+ }
+}
+
+/**
+ * grant_none_oplock() - grant none oplock or none lease
+ * @opinfo_new: new oplock info object
+ * @lctx: lease context information
+ *
+ * Return: 0
+ */
+static void grant_none_oplock(struct oplock_info *opinfo_new,
+ struct lease_ctx_info *lctx)
+{
+ struct lease *lease = opinfo_new->o_lease;
+
+ opinfo_new->level = SMB2_OPLOCK_LEVEL_NONE;
+
+ if (lctx) {
+ lease->state = 0;
+ memcpy(lease->lease_key, lctx->lease_key, SMB2_LEASE_KEY_SIZE);
+ }
+}
+
+static inline int compare_guid_key(struct oplock_info *opinfo,
+ const char *guid1, const char *key1)
+{
+ const char *guid2, *key2;
+
+ guid2 = opinfo->conn->ClientGUID;
+ key2 = opinfo->o_lease->lease_key;
+ if (!memcmp(guid1, guid2, SMB2_CLIENT_GUID_SIZE) &&
+ !memcmp(key1, key2, SMB2_LEASE_KEY_SIZE))
+ return 1;
+
+ return 0;
+}
+
+/**
+ * same_client_has_lease() - check whether current lease request is
+ * from lease owner of file
+ * @ci: master file pointer
+ * @client_guid: Client GUID
+ * @lctx: lease context information
+ *
+ * Return: oplock(lease) object on success, otherwise NULL
+ */
+static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
+ char *client_guid,
+ struct lease_ctx_info *lctx)
+{
+ int ret;
+ struct lease *lease;
+ struct oplock_info *opinfo;
+ struct oplock_info *m_opinfo = NULL;
+
+ if (!lctx)
+ return NULL;
+
+ /*
+ * Compare lease key and client_guid to know request from same owner
+ * of same client
+ */
+ read_lock(&ci->m_lock);
+ list_for_each_entry(opinfo, &ci->m_op_list, op_entry) {
+ if (!opinfo->is_lease)
+ continue;
+ read_unlock(&ci->m_lock);
+ lease = opinfo->o_lease;
+
+ ret = compare_guid_key(opinfo, client_guid, lctx->lease_key);
+ if (ret) {
+ m_opinfo = opinfo;
+ /* skip upgrading lease about breaking lease */
+ if (atomic_read(&opinfo->breaking_cnt)) {
+ read_lock(&ci->m_lock);
+ continue;
+ }
+
+ /* upgrading lease */
+ if ((atomic_read(&ci->op_count) +
+ atomic_read(&ci->sop_count)) == 1) {
+ if (lease->state ==
+ (lctx->req_state & lease->state)) {
+ lease->state |= lctx->req_state;
+ if (lctx->req_state &
+ SMB2_LEASE_WRITE_CACHING_LE)
+ lease_read_to_write(opinfo);
+ }
+ } else if ((atomic_read(&ci->op_count) +
+ atomic_read(&ci->sop_count)) > 1) {
+ if (lctx->req_state ==
+ (SMB2_LEASE_READ_CACHING_LE |
+ SMB2_LEASE_HANDLE_CACHING_LE))
+ lease->state = lctx->req_state;
+ }
+
+ if (lctx->req_state && lease->state ==
+ SMB2_LEASE_NONE_LE)
+ lease_none_upgrade(opinfo, lctx->req_state);
+ }
+ read_lock(&ci->m_lock);
+ }
+ read_unlock(&ci->m_lock);
+
+ return m_opinfo;
+}
+
+static void wait_for_break_ack(struct oplock_info *opinfo)
+{
+ int rc = 0;
+
+ rc = wait_event_interruptible_timeout(opinfo->oplock_q,
+ opinfo->op_state == OPLOCK_STATE_NONE ||
+ opinfo->op_state == OPLOCK_CLOSING,
+ OPLOCK_WAIT_TIME);
+
+ /* is this a timeout ? */
+ if (!rc) {
+ if (opinfo->is_lease)
+ opinfo->o_lease->state = SMB2_LEASE_NONE_LE;
+ opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
+ opinfo->op_state = OPLOCK_STATE_NONE;
+ }
+}
+
+static void wake_up_oplock_break(struct oplock_info *opinfo)
+{
+ clear_bit_unlock(0, &opinfo->pending_break);
+ /* memory barrier is needed for wake_up_bit() */
+ smp_mb__after_atomic();
+ wake_up_bit(&opinfo->pending_break, 0);
+}
+
+static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)
+{
+ while (test_and_set_bit(0, &opinfo->pending_break)) {
+ wait_on_bit(&opinfo->pending_break, 0, TASK_UNINTERRUPTIBLE);
+
+ /* Not immediately break to none. */
+ opinfo->open_trunc = 0;
+
+ if (opinfo->op_state == OPLOCK_CLOSING)
+ return -ENOENT;
+ else if (!opinfo->is_lease && opinfo->level <= req_op_level)
+ return 1;
+ }
+
+ if (!opinfo->is_lease && opinfo->level <= req_op_level) {
+ wake_up_oplock_break(opinfo);
+ return 1;
+ }
+ return 0;
+}
+
+static inline int allocate_oplock_break_buf(struct ksmbd_work *work)
+{
+ work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, GFP_KERNEL);
+ if (!work->response_buf)
+ return -ENOMEM;
+ work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
+ return 0;
+}
+
+/**
+ * __smb2_oplock_break_noti() - send smb2 oplock break cmd from conn
+ * to client
+ * @wk: smb work object
+ *
+ * There are two ways this function can be called. 1- while file open we break
+ * from exclusive/batch lock to levelII oplock and 2- while file write/truncate
+ * we break from levelII oplock no oplock.
+ * work->request_buf contains oplock_info.
+ */
+static void __smb2_oplock_break_noti(struct work_struct *wk)
+{
+ struct smb2_oplock_break *rsp = NULL;
+ struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
+ struct ksmbd_conn *conn = work->conn;
+ struct oplock_break_info *br_info = work->request_buf;
+ struct smb2_hdr *rsp_hdr;
+ struct ksmbd_file *fp;
+
+ fp = ksmbd_lookup_durable_fd(br_info->fid);
+ if (!fp)
+ goto out;
+
+ if (allocate_oplock_break_buf(work)) {
+ pr_err("smb2_allocate_rsp_buf failed! ");
+ ksmbd_fd_put(work, fp);
+ goto out;
+ }
+
+ rsp_hdr = smb2_get_msg(work->response_buf);
+ memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(conn->vals->header_size);
+ rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
+ rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
+ rsp_hdr->CreditRequest = cpu_to_le16(0);
+ rsp_hdr->Command = SMB2_OPLOCK_BREAK;
+ rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
+ rsp_hdr->NextCommand = 0;
+ rsp_hdr->MessageId = cpu_to_le64(-1);
+ rsp_hdr->Id.SyncId.ProcessId = 0;
+ rsp_hdr->Id.SyncId.TreeId = 0;
+ rsp_hdr->SessionId = 0;
+ memset(rsp_hdr->Signature, 0, 16);
+
+ rsp = smb2_get_msg(work->response_buf);
+
+ rsp->StructureSize = cpu_to_le16(24);
+ if (!br_info->open_trunc &&
+ (br_info->level == SMB2_OPLOCK_LEVEL_BATCH ||
+ br_info->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE))
+ rsp->OplockLevel = SMB2_OPLOCK_LEVEL_II;
+ else
+ rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE;
+ rsp->Reserved = 0;
+ rsp->Reserved2 = 0;
+ rsp->PersistentFid = fp->persistent_id;
+ rsp->VolatileFid = fp->volatile_id;
+
+ inc_rfc1001_len(work->response_buf, 24);
+
+ ksmbd_debug(OPLOCK,
+ "sending oplock break v_id %llu p_id = %llu lock level = %d\n",
+ rsp->VolatileFid, rsp->PersistentFid, rsp->OplockLevel);
+
+ ksmbd_fd_put(work, fp);
+ ksmbd_conn_write(work);
+
+out:
+ ksmbd_free_work_struct(work);
+}
+
+/**
+ * smb2_oplock_break_noti() - send smb2 exclusive/batch to level2 oplock
+ * break command from server to client
+ * @opinfo: oplock info object
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int smb2_oplock_break_noti(struct oplock_info *opinfo)
+{
+ struct ksmbd_conn *conn = opinfo->conn;
+ struct oplock_break_info *br_info;
+ int ret = 0;
+ struct ksmbd_work *work = ksmbd_alloc_work_struct();
+
+ if (!work)
+ return -ENOMEM;
+
+ br_info = kmalloc(sizeof(struct oplock_break_info), GFP_KERNEL);
+ if (!br_info) {
+ ksmbd_free_work_struct(work);
+ return -ENOMEM;
+ }
+
+ br_info->level = opinfo->level;
+ br_info->fid = opinfo->fid;
+ br_info->open_trunc = opinfo->open_trunc;
+
+ work->request_buf = (char *)br_info;
+ work->conn = conn;
+ work->sess = opinfo->sess;
+
+ if (opinfo->op_state == OPLOCK_ACK_WAIT) {
+ INIT_WORK(&work->work, __smb2_oplock_break_noti);
+ ksmbd_queue_work(work);
+
+ wait_for_break_ack(opinfo);
+ } else {
+ __smb2_oplock_break_noti(&work->work);
+ if (opinfo->level == SMB2_OPLOCK_LEVEL_II)
+ opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
+ }
+ return ret;
+}
+
+/**
+ * __smb2_lease_break_noti() - send lease break command from server
+ * to client
+ * @wk: smb work object
+ */
+static void __smb2_lease_break_noti(struct work_struct *wk)
+{
+ struct smb2_lease_break *rsp = NULL;
+ struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
+ struct lease_break_info *br_info = work->request_buf;
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_hdr *rsp_hdr;
+
+ if (allocate_oplock_break_buf(work)) {
+ ksmbd_debug(OPLOCK, "smb2_allocate_rsp_buf failed! ");
+ goto out;
+ }
+
+ rsp_hdr = smb2_get_msg(work->response_buf);
+ memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(conn->vals->header_size);
+ rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
+ rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
+ rsp_hdr->CreditRequest = cpu_to_le16(0);
+ rsp_hdr->Command = SMB2_OPLOCK_BREAK;
+ rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
+ rsp_hdr->NextCommand = 0;
+ rsp_hdr->MessageId = cpu_to_le64(-1);
+ rsp_hdr->Id.SyncId.ProcessId = 0;
+ rsp_hdr->Id.SyncId.TreeId = 0;
+ rsp_hdr->SessionId = 0;
+ memset(rsp_hdr->Signature, 0, 16);
+
+ rsp = smb2_get_msg(work->response_buf);
+ rsp->StructureSize = cpu_to_le16(44);
+ rsp->Epoch = br_info->epoch;
+ rsp->Flags = 0;
+
+ if (br_info->curr_state & (SMB2_LEASE_WRITE_CACHING_LE |
+ SMB2_LEASE_HANDLE_CACHING_LE))
+ rsp->Flags = SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;
+
+ memcpy(rsp->LeaseKey, br_info->lease_key, SMB2_LEASE_KEY_SIZE);
+ rsp->CurrentLeaseState = br_info->curr_state;
+ rsp->NewLeaseState = br_info->new_state;
+ rsp->BreakReason = 0;
+ rsp->AccessMaskHint = 0;
+ rsp->ShareMaskHint = 0;
+
+ inc_rfc1001_len(work->response_buf, 44);
+
+ ksmbd_conn_write(work);
+
+out:
+ ksmbd_free_work_struct(work);
+}
+
+/**
+ * smb2_lease_break_noti() - break lease when a new client request
+ * write lease
+ * @opinfo: conains lease state information
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int smb2_lease_break_noti(struct oplock_info *opinfo)
+{
+ struct ksmbd_conn *conn = opinfo->conn;
+ struct list_head *tmp, *t;
+ struct ksmbd_work *work;
+ struct lease_break_info *br_info;
+ struct lease *lease = opinfo->o_lease;
+
+ work = ksmbd_alloc_work_struct();
+ if (!work)
+ return -ENOMEM;
+
+ br_info = kmalloc(sizeof(struct lease_break_info), GFP_KERNEL);
+ if (!br_info) {
+ ksmbd_free_work_struct(work);
+ return -ENOMEM;
+ }
+
+ br_info->curr_state = lease->state;
+ br_info->new_state = lease->new_state;
+ if (lease->version == 2)
+ br_info->epoch = cpu_to_le16(++lease->epoch);
+ else
+ br_info->epoch = 0;
+ memcpy(br_info->lease_key, lease->lease_key, SMB2_LEASE_KEY_SIZE);
+
+ work->request_buf = (char *)br_info;
+ work->conn = conn;
+ work->sess = opinfo->sess;
+
+ if (opinfo->op_state == OPLOCK_ACK_WAIT) {
+ list_for_each_safe(tmp, t, &opinfo->interim_list) {
+ struct ksmbd_work *in_work;
+
+ in_work = list_entry(tmp, struct ksmbd_work,
+ interim_entry);
+ setup_async_work(in_work, NULL, NULL);
+ smb2_send_interim_resp(in_work, STATUS_PENDING);
+ list_del(&in_work->interim_entry);
+ }
+ INIT_WORK(&work->work, __smb2_lease_break_noti);
+ ksmbd_queue_work(work);
+ wait_for_break_ack(opinfo);
+ } else {
+ __smb2_lease_break_noti(&work->work);
+ if (opinfo->o_lease->new_state == SMB2_LEASE_NONE_LE) {
+ opinfo->level = SMB2_OPLOCK_LEVEL_NONE;
+ opinfo->o_lease->state = SMB2_LEASE_NONE_LE;
+ }
+ }
+ return 0;
+}
+
+static void wait_lease_breaking(struct oplock_info *opinfo)
+{
+ if (!opinfo->is_lease)
+ return;
+
+ wake_up_interruptible_all(&opinfo->oplock_brk);
+ if (atomic_read(&opinfo->breaking_cnt)) {
+ int ret = 0;
+
+ ret = wait_event_interruptible_timeout(opinfo->oplock_brk,
+ atomic_read(&opinfo->breaking_cnt) == 0,
+ HZ);
+ if (!ret)
+ atomic_set(&opinfo->breaking_cnt, 0);
+ }
+}
+
+static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level)
+{
+ int err = 0;
+
+ /* Need to break exclusive/batch oplock, write lease or overwrite_if */
+ ksmbd_debug(OPLOCK,
+ "request to send oplock(level : 0x%x) break notification\n",
+ brk_opinfo->level);
+
+ if (brk_opinfo->is_lease) {
+ struct lease *lease = brk_opinfo->o_lease;
+
+ atomic_inc(&brk_opinfo->breaking_cnt);
+
+ err = oplock_break_pending(brk_opinfo, req_op_level);
+ if (err)
+ return err < 0 ? err : 0;
+
+ if (brk_opinfo->open_trunc) {
+ /*
+ * Create overwrite break trigger the lease break to
+ * none.
+ */
+ lease->new_state = SMB2_LEASE_NONE_LE;
+ } else {
+ if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) {
+ if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
+ lease->new_state =
+ SMB2_LEASE_READ_CACHING_LE |
+ SMB2_LEASE_HANDLE_CACHING_LE;
+ else
+ lease->new_state =
+ SMB2_LEASE_READ_CACHING_LE;
+ } else {
+ if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
+ lease->new_state =
+ SMB2_LEASE_READ_CACHING_LE;
+ else
+ lease->new_state = SMB2_LEASE_NONE_LE;
+ }
+ }
+
+ if (lease->state & (SMB2_LEASE_WRITE_CACHING_LE |
+ SMB2_LEASE_HANDLE_CACHING_LE))
+ brk_opinfo->op_state = OPLOCK_ACK_WAIT;
+ else
+ atomic_dec(&brk_opinfo->breaking_cnt);
+ } else {
+ err = oplock_break_pending(brk_opinfo, req_op_level);
+ if (err)
+ return err < 0 ? err : 0;
+
+ if (brk_opinfo->level == SMB2_OPLOCK_LEVEL_BATCH ||
+ brk_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
+ brk_opinfo->op_state = OPLOCK_ACK_WAIT;
+ }
+
+ if (brk_opinfo->is_lease)
+ err = smb2_lease_break_noti(brk_opinfo);
+ else
+ err = smb2_oplock_break_noti(brk_opinfo);
+
+ ksmbd_debug(OPLOCK, "oplock granted = %d\n", brk_opinfo->level);
+ if (brk_opinfo->op_state == OPLOCK_CLOSING)
+ err = -ENOENT;
+ wake_up_oplock_break(brk_opinfo);
+
+ wait_lease_breaking(brk_opinfo);
+
+ return err;
+}
+
+void destroy_lease_table(struct ksmbd_conn *conn)
+{
+ struct lease_table *lb, *lbtmp;
+ struct oplock_info *opinfo;
+
+ write_lock(&lease_list_lock);
+ if (list_empty(&lease_table_list)) {
+ write_unlock(&lease_list_lock);
+ return;
+ }
+
+ list_for_each_entry_safe(lb, lbtmp, &lease_table_list, l_entry) {
+ if (conn && memcmp(lb->client_guid, conn->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE))
+ continue;
+again:
+ rcu_read_lock();
+ list_for_each_entry_rcu(opinfo, &lb->lease_list,
+ lease_entry) {
+ rcu_read_unlock();
+ lease_del_list(opinfo);
+ goto again;
+ }
+ rcu_read_unlock();
+ list_del(&lb->l_entry);
+ kfree(lb);
+ }
+ write_unlock(&lease_list_lock);
+}
+
+int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
+ struct lease_ctx_info *lctx)
+{
+ struct oplock_info *opinfo;
+ int err = 0;
+ struct lease_table *lb;
+
+ if (!lctx)
+ return err;
+
+ read_lock(&lease_list_lock);
+ if (list_empty(&lease_table_list)) {
+ read_unlock(&lease_list_lock);
+ return 0;
+ }
+
+ list_for_each_entry(lb, &lease_table_list, l_entry) {
+ if (!memcmp(lb->client_guid, sess->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE))
+ goto found;
+ }
+ read_unlock(&lease_list_lock);
+
+ return 0;
+
+found:
+ rcu_read_lock();
+ list_for_each_entry_rcu(opinfo, &lb->lease_list, lease_entry) {
+ if (!atomic_inc_not_zero(&opinfo->refcount))
+ continue;
+ rcu_read_unlock();
+ if (opinfo->o_fp->f_ci == ci)
+ goto op_next;
+ err = compare_guid_key(opinfo, sess->ClientGUID,
+ lctx->lease_key);
+ if (err) {
+ err = -EINVAL;
+ ksmbd_debug(OPLOCK,
+ "found same lease key is already used in other files\n");
+ opinfo_put(opinfo);
+ goto out;
+ }
+op_next:
+ opinfo_put(opinfo);
+ rcu_read_lock();
+ }
+ rcu_read_unlock();
+
+out:
+ read_unlock(&lease_list_lock);
+ return err;
+}
+
+static void copy_lease(struct oplock_info *op1, struct oplock_info *op2)
+{
+ struct lease *lease1 = op1->o_lease;
+ struct lease *lease2 = op2->o_lease;
+
+ op2->level = op1->level;
+ lease2->state = lease1->state;
+ memcpy(lease2->lease_key, lease1->lease_key,
+ SMB2_LEASE_KEY_SIZE);
+ lease2->duration = lease1->duration;
+ lease2->flags = lease1->flags;
+}
+
+static int add_lease_global_list(struct oplock_info *opinfo)
+{
+ struct lease_table *lb;
+
+ read_lock(&lease_list_lock);
+ list_for_each_entry(lb, &lease_table_list, l_entry) {
+ if (!memcmp(lb->client_guid, opinfo->conn->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE)) {
+ opinfo->o_lease->l_lb = lb;
+ lease_add_list(opinfo);
+ read_unlock(&lease_list_lock);
+ return 0;
+ }
+ }
+ read_unlock(&lease_list_lock);
+
+ lb = kmalloc(sizeof(struct lease_table), GFP_KERNEL);
+ if (!lb)
+ return -ENOMEM;
+
+ memcpy(lb->client_guid, opinfo->conn->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE);
+ INIT_LIST_HEAD(&lb->lease_list);
+ spin_lock_init(&lb->lb_lock);
+ opinfo->o_lease->l_lb = lb;
+ lease_add_list(opinfo);
+ lb_add(lb);
+ return 0;
+}
+
+static void set_oplock_level(struct oplock_info *opinfo, int level,
+ struct lease_ctx_info *lctx)
+{
+ switch (level) {
+ case SMB2_OPLOCK_LEVEL_BATCH:
+ case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
+ grant_write_oplock(opinfo, level, lctx);
+ break;
+ case SMB2_OPLOCK_LEVEL_II:
+ grant_read_oplock(opinfo, lctx);
+ break;
+ default:
+ grant_none_oplock(opinfo, lctx);
+ break;
+ }
+}
+
+/**
+ * smb_grant_oplock() - handle oplock/lease request on file open
+ * @work: smb work
+ * @req_op_level: oplock level
+ * @pid: id of open file
+ * @fp: ksmbd file pointer
+ * @tid: Tree id of connection
+ * @lctx: lease context information on file open
+ * @share_ret: share mode
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
+ struct ksmbd_file *fp, __u16 tid,
+ struct lease_ctx_info *lctx, int share_ret)
+{
+ struct ksmbd_session *sess = work->sess;
+ int err = 0;
+ struct oplock_info *opinfo = NULL, *prev_opinfo = NULL;
+ struct ksmbd_inode *ci = fp->f_ci;
+ bool prev_op_has_lease;
+ __le32 prev_op_state = 0;
+
+ /* not support directory lease */
+ if (S_ISDIR(file_inode(fp->filp)->i_mode))
+ return 0;
+
+ opinfo = alloc_opinfo(work, pid, tid);
+ if (!opinfo)
+ return -ENOMEM;
+
+ if (lctx) {
+ err = alloc_lease(opinfo, lctx);
+ if (err)
+ goto err_out;
+ opinfo->is_lease = 1;
+ }
+
+ /* ci does not have any oplock */
+ if (!opinfo_count(fp))
+ goto set_lev;
+
+ /* grant none-oplock if second open is trunc */
+ if (fp->attrib_only && fp->cdoption != FILE_OVERWRITE_IF_LE &&
+ fp->cdoption != FILE_OVERWRITE_LE &&
+ fp->cdoption != FILE_SUPERSEDE_LE) {
+ req_op_level = SMB2_OPLOCK_LEVEL_NONE;
+ goto set_lev;
+ }
+
+ if (lctx) {
+ struct oplock_info *m_opinfo;
+
+ /* is lease already granted ? */
+ m_opinfo = same_client_has_lease(ci, sess->ClientGUID,
+ lctx);
+ if (m_opinfo) {
+ copy_lease(m_opinfo, opinfo);
+ if (atomic_read(&m_opinfo->breaking_cnt))
+ opinfo->o_lease->flags =
+ SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE;
+ goto out;
+ }
+ }
+ prev_opinfo = opinfo_get_list(ci);
+ if (!prev_opinfo ||
+ (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx)) {
+ opinfo_conn_put(prev_opinfo);
+ goto set_lev;
+ }
+ prev_op_has_lease = prev_opinfo->is_lease;
+ if (prev_op_has_lease)
+ prev_op_state = prev_opinfo->o_lease->state;
+
+ if (share_ret < 0 &&
+ prev_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
+ err = share_ret;
+ opinfo_conn_put(prev_opinfo);
+ goto err_out;
+ }
+
+ if (prev_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
+ prev_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
+ opinfo_conn_put(prev_opinfo);
+ goto op_break_not_needed;
+ }
+
+ list_add(&work->interim_entry, &prev_opinfo->interim_list);
+ err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II);
+ opinfo_conn_put(prev_opinfo);
+ if (err == -ENOENT)
+ goto set_lev;
+ /* Check all oplock was freed by close */
+ else if (err < 0)
+ goto err_out;
+
+op_break_not_needed:
+ if (share_ret < 0) {
+ err = share_ret;
+ goto err_out;
+ }
+
+ if (req_op_level != SMB2_OPLOCK_LEVEL_NONE)
+ req_op_level = SMB2_OPLOCK_LEVEL_II;
+
+ /* grant fixed oplock on stacked locking between lease and oplock */
+ if (prev_op_has_lease && !lctx)
+ if (prev_op_state & SMB2_LEASE_HANDLE_CACHING_LE)
+ req_op_level = SMB2_OPLOCK_LEVEL_NONE;
+
+ if (!prev_op_has_lease && lctx) {
+ req_op_level = SMB2_OPLOCK_LEVEL_II;
+ lctx->req_state = SMB2_LEASE_READ_CACHING_LE;
+ }
+
+set_lev:
+ set_oplock_level(opinfo, req_op_level, lctx);
+
+out:
+ rcu_assign_pointer(fp->f_opinfo, opinfo);
+ opinfo->o_fp = fp;
+
+ opinfo_count_inc(fp);
+ opinfo_add(opinfo);
+ if (opinfo->is_lease) {
+ err = add_lease_global_list(opinfo);
+ if (err)
+ goto err_out;
+ }
+
+ return 0;
+err_out:
+ free_opinfo(opinfo);
+ return err;
+}
+
+/**
+ * smb_break_all_write_oplock() - break batch/exclusive oplock to level2
+ * @work: smb work
+ * @fp: ksmbd file pointer
+ * @is_trunc: truncate on open
+ */
+static void smb_break_all_write_oplock(struct ksmbd_work *work,
+ struct ksmbd_file *fp, int is_trunc)
+{
+ struct oplock_info *brk_opinfo;
+
+ brk_opinfo = opinfo_get_list(fp->f_ci);
+ if (!brk_opinfo)
+ return;
+ if (brk_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
+ brk_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
+ opinfo_conn_put(brk_opinfo);
+ return;
+ }
+
+ brk_opinfo->open_trunc = is_trunc;
+ list_add(&work->interim_entry, &brk_opinfo->interim_list);
+ oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II);
+ opinfo_conn_put(brk_opinfo);
+}
+
+/**
+ * smb_break_all_levII_oplock() - send level2 oplock or read lease break command
+ * from server to client
+ * @work: smb work
+ * @fp: ksmbd file pointer
+ * @is_trunc: truncate on open
+ */
+void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
+ int is_trunc)
+{
+ struct oplock_info *op, *brk_op;
+ struct ksmbd_inode *ci;
+ struct ksmbd_conn *conn = work->conn;
+
+ if (!test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_OPLOCKS))
+ return;
+
+ ci = fp->f_ci;
+ op = opinfo_get(fp);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) {
+ if (!atomic_inc_not_zero(&brk_op->refcount))
+ continue;
+
+ atomic_inc(&brk_op->conn->r_count);
+ if (ksmbd_conn_releasing(brk_op->conn)) {
+ atomic_dec(&brk_op->conn->r_count);
+ continue;
+ }
+
+ rcu_read_unlock();
+ if (brk_op->is_lease && (brk_op->o_lease->state &
+ (~(SMB2_LEASE_READ_CACHING_LE |
+ SMB2_LEASE_HANDLE_CACHING_LE)))) {
+ ksmbd_debug(OPLOCK, "unexpected lease state(0x%x)\n",
+ brk_op->o_lease->state);
+ goto next;
+ } else if (brk_op->level !=
+ SMB2_OPLOCK_LEVEL_II) {
+ ksmbd_debug(OPLOCK, "unexpected oplock(0x%x)\n",
+ brk_op->level);
+ goto next;
+ }
+
+ /* Skip oplock being break to none */
+ if (brk_op->is_lease &&
+ brk_op->o_lease->new_state == SMB2_LEASE_NONE_LE &&
+ atomic_read(&brk_op->breaking_cnt))
+ goto next;
+
+ if (op && op->is_lease && brk_op->is_lease &&
+ !memcmp(conn->ClientGUID, brk_op->conn->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE) &&
+ !memcmp(op->o_lease->lease_key, brk_op->o_lease->lease_key,
+ SMB2_LEASE_KEY_SIZE))
+ goto next;
+ brk_op->open_trunc = is_trunc;
+ oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE);
+next:
+ opinfo_conn_put(brk_op);
+ rcu_read_lock();
+ }
+ rcu_read_unlock();
+
+ if (op)
+ opinfo_put(op);
+}
+
+/**
+ * smb_break_all_oplock() - break both batch/exclusive and level2 oplock
+ * @work: smb work
+ * @fp: ksmbd file pointer
+ */
+void smb_break_all_oplock(struct ksmbd_work *work, struct ksmbd_file *fp)
+{
+ if (!test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_OPLOCKS))
+ return;
+
+ smb_break_all_write_oplock(work, fp, 1);
+ smb_break_all_levII_oplock(work, fp, 1);
+}
+
+/**
+ * smb2_map_lease_to_oplock() - map lease state to corresponding oplock type
+ * @lease_state: lease type
+ *
+ * Return: 0 if no mapping, otherwise corresponding oplock type
+ */
+__u8 smb2_map_lease_to_oplock(__le32 lease_state)
+{
+ if (lease_state == (SMB2_LEASE_HANDLE_CACHING_LE |
+ SMB2_LEASE_READ_CACHING_LE |
+ SMB2_LEASE_WRITE_CACHING_LE)) {
+ return SMB2_OPLOCK_LEVEL_BATCH;
+ } else if (lease_state != SMB2_LEASE_WRITE_CACHING_LE &&
+ lease_state & SMB2_LEASE_WRITE_CACHING_LE) {
+ if (!(lease_state & SMB2_LEASE_HANDLE_CACHING_LE))
+ return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
+ } else if (lease_state & SMB2_LEASE_READ_CACHING_LE) {
+ return SMB2_OPLOCK_LEVEL_II;
+ }
+ return 0;
+}
+
+/**
+ * create_lease_buf() - create lease context for open cmd response
+ * @rbuf: buffer to create lease context response
+ * @lease: buffer to stored parsed lease state information
+ */
+void create_lease_buf(u8 *rbuf, struct lease *lease)
+{
+ if (lease->version == 2) {
+ struct create_lease_v2 *buf = (struct create_lease_v2 *)rbuf;
+
+ memset(buf, 0, sizeof(struct create_lease_v2));
+ memcpy(buf->lcontext.LeaseKey, lease->lease_key,
+ SMB2_LEASE_KEY_SIZE);
+ buf->lcontext.LeaseFlags = lease->flags;
+ buf->lcontext.LeaseState = lease->state;
+ memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
+ SMB2_LEASE_KEY_SIZE);
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_lease_v2, lcontext));
+ buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_lease_v2, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ buf->Name[0] = 'R';
+ buf->Name[1] = 'q';
+ buf->Name[2] = 'L';
+ buf->Name[3] = 's';
+ } else {
+ struct create_lease *buf = (struct create_lease *)rbuf;
+
+ memset(buf, 0, sizeof(struct create_lease));
+ memcpy(buf->lcontext.LeaseKey, lease->lease_key, SMB2_LEASE_KEY_SIZE);
+ buf->lcontext.LeaseFlags = lease->flags;
+ buf->lcontext.LeaseState = lease->state;
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_lease, lcontext));
+ buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_lease, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ buf->Name[0] = 'R';
+ buf->Name[1] = 'q';
+ buf->Name[2] = 'L';
+ buf->Name[3] = 's';
+ }
+}
+
+/**
+ * parse_lease_state() - parse lease context containted in file open request
+ * @open_req: buffer containing smb2 file open(create) request
+ *
+ * Return: oplock state, -ENOENT if create lease context not found
+ */
+struct lease_ctx_info *parse_lease_state(void *open_req)
+{
+ struct create_context *cc;
+ struct smb2_create_req *req = (struct smb2_create_req *)open_req;
+ struct lease_ctx_info *lreq;
+
+ cc = smb2_find_context_vals(req, SMB2_CREATE_REQUEST_LEASE, 4);
+ if (IS_ERR_OR_NULL(cc))
+ return NULL;
+
+ lreq = kzalloc(sizeof(struct lease_ctx_info), GFP_KERNEL);
+ if (!lreq)
+ return NULL;
+
+ if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
+ struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
+
+ memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
+ lreq->req_state = lc->lcontext.LeaseState;
+ lreq->flags = lc->lcontext.LeaseFlags;
+ lreq->duration = lc->lcontext.LeaseDuration;
+ memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
+ SMB2_LEASE_KEY_SIZE);
+ lreq->version = 2;
+ } else {
+ struct create_lease *lc = (struct create_lease *)cc;
+
+ memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
+ lreq->req_state = lc->lcontext.LeaseState;
+ lreq->flags = lc->lcontext.LeaseFlags;
+ lreq->duration = lc->lcontext.LeaseDuration;
+ lreq->version = 1;
+ }
+ return lreq;
+}
+
+/**
+ * smb2_find_context_vals() - find a particular context info in open request
+ * @open_req: buffer containing smb2 file open(create) request
+ * @tag: context name to search for
+ * @tag_len: the length of tag
+ *
+ * Return: pointer to requested context, NULL if @str context not found
+ * or error pointer if name length is invalid.
+ */
+struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len)
+{
+ struct create_context *cc;
+ unsigned int next = 0;
+ char *name;
+ struct smb2_create_req *req = (struct smb2_create_req *)open_req;
+ unsigned int remain_len, name_off, name_len, value_off, value_len,
+ cc_len;
+
+ /*
+ * CreateContextsOffset and CreateContextsLength are guaranteed to
+ * be valid because of ksmbd_smb2_check_message().
+ */
+ cc = (struct create_context *)((char *)req +
+ le32_to_cpu(req->CreateContextsOffset));
+ remain_len = le32_to_cpu(req->CreateContextsLength);
+ do {
+ cc = (struct create_context *)((char *)cc + next);
+ if (remain_len < offsetof(struct create_context, Buffer))
+ return ERR_PTR(-EINVAL);
+
+ next = le32_to_cpu(cc->Next);
+ name_off = le16_to_cpu(cc->NameOffset);
+ name_len = le16_to_cpu(cc->NameLength);
+ value_off = le16_to_cpu(cc->DataOffset);
+ value_len = le32_to_cpu(cc->DataLength);
+ cc_len = next ? next : remain_len;
+
+ if ((next & 0x7) != 0 ||
+ next > remain_len ||
+ name_off != offsetof(struct create_context, Buffer) ||
+ name_len < 4 ||
+ name_off + name_len > cc_len ||
+ (value_off & 0x7) != 0 ||
+ (value_off && (value_off < name_off + name_len)) ||
+ ((u64)value_off + value_len > cc_len))
+ return ERR_PTR(-EINVAL);
+
+ name = (char *)cc + name_off;
+ if (name_len == tag_len && !memcmp(name, tag, name_len))
+ return cc;
+
+ remain_len -= next;
+ } while (next != 0);
+
+ return NULL;
+}
+
+/**
+ * create_durable_rsp_buf() - create durable handle context
+ * @cc: buffer to create durable context response
+ */
+void create_durable_rsp_buf(char *cc)
+{
+ struct create_durable_rsp *buf;
+
+ buf = (struct create_durable_rsp *)cc;
+ memset(buf, 0, sizeof(struct create_durable_rsp));
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_durable_rsp, Data));
+ buf->ccontext.DataLength = cpu_to_le32(8);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_durable_rsp, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_DURABLE_HANDLE_RESPONSE is "DHnQ" */
+ buf->Name[0] = 'D';
+ buf->Name[1] = 'H';
+ buf->Name[2] = 'n';
+ buf->Name[3] = 'Q';
+}
+
+/**
+ * create_durable_v2_rsp_buf() - create durable handle v2 context
+ * @cc: buffer to create durable context response
+ * @fp: ksmbd file pointer
+ */
+void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp)
+{
+ struct create_durable_v2_rsp *buf;
+
+ buf = (struct create_durable_v2_rsp *)cc;
+ memset(buf, 0, sizeof(struct create_durable_rsp));
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_durable_rsp, Data));
+ buf->ccontext.DataLength = cpu_to_le32(8);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_durable_rsp, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2 is "DH2Q" */
+ buf->Name[0] = 'D';
+ buf->Name[1] = 'H';
+ buf->Name[2] = '2';
+ buf->Name[3] = 'Q';
+
+ buf->Timeout = cpu_to_le32(fp->durable_timeout);
+}
+
+/**
+ * create_mxac_rsp_buf() - create query maximal access context
+ * @cc: buffer to create maximal access context response
+ * @maximal_access: maximal access
+ */
+void create_mxac_rsp_buf(char *cc, int maximal_access)
+{
+ struct create_mxac_rsp *buf;
+
+ buf = (struct create_mxac_rsp *)cc;
+ memset(buf, 0, sizeof(struct create_mxac_rsp));
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_mxac_rsp, QueryStatus));
+ buf->ccontext.DataLength = cpu_to_le32(8);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_mxac_rsp, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE is "MxAc" */
+ buf->Name[0] = 'M';
+ buf->Name[1] = 'x';
+ buf->Name[2] = 'A';
+ buf->Name[3] = 'c';
+
+ buf->QueryStatus = STATUS_SUCCESS;
+ buf->MaximalAccess = cpu_to_le32(maximal_access);
+}
+
+void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id)
+{
+ struct create_disk_id_rsp *buf;
+
+ buf = (struct create_disk_id_rsp *)cc;
+ memset(buf, 0, sizeof(struct create_disk_id_rsp));
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_disk_id_rsp, DiskFileId));
+ buf->ccontext.DataLength = cpu_to_le32(32);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_mxac_rsp, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ /* SMB2_CREATE_QUERY_ON_DISK_ID_RESPONSE is "QFid" */
+ buf->Name[0] = 'Q';
+ buf->Name[1] = 'F';
+ buf->Name[2] = 'i';
+ buf->Name[3] = 'd';
+
+ buf->DiskFileId = cpu_to_le64(file_id);
+ buf->VolumeId = cpu_to_le64(vol_id);
+}
+
+/**
+ * create_posix_rsp_buf() - create posix extension context
+ * @cc: buffer to create posix on posix response
+ * @fp: ksmbd file pointer
+ */
+void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
+{
+ struct create_posix_rsp *buf;
+ struct inode *inode = file_inode(fp->filp);
+ struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
+ vfsuid_t vfsuid = i_uid_into_vfsuid(user_ns, inode);
+ vfsgid_t vfsgid = i_gid_into_vfsgid(user_ns, inode);
+
+ buf = (struct create_posix_rsp *)cc;
+ memset(buf, 0, sizeof(struct create_posix_rsp));
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_posix_rsp, nlink));
+ /*
+ * DataLength = nlink(4) + reparse_tag(4) + mode(4) +
+ * domain sid(28) + unix group sid(16).
+ */
+ buf->ccontext.DataLength = cpu_to_le32(56);
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_posix_rsp, Name));
+ buf->ccontext.NameLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
+ /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
+ buf->Name[0] = 0x93;
+ buf->Name[1] = 0xAD;
+ buf->Name[2] = 0x25;
+ buf->Name[3] = 0x50;
+ buf->Name[4] = 0x9C;
+ buf->Name[5] = 0xB4;
+ buf->Name[6] = 0x11;
+ buf->Name[7] = 0xE7;
+ buf->Name[8] = 0xB4;
+ buf->Name[9] = 0x23;
+ buf->Name[10] = 0x83;
+ buf->Name[11] = 0xDE;
+ buf->Name[12] = 0x96;
+ buf->Name[13] = 0x8B;
+ buf->Name[14] = 0xCD;
+ buf->Name[15] = 0x7C;
+
+ buf->nlink = cpu_to_le32(inode->i_nlink);
+ buf->reparse_tag = cpu_to_le32(fp->volatile_id);
+ buf->mode = cpu_to_le32(inode->i_mode & 0777);
+ /*
+ * SidBuffer(44) contain two sids(Domain sid(28), UNIX group sid(16)).
+ * Domain sid(28) = revision(1) + num_subauth(1) + authority(6) +
+ * sub_auth(4 * 4(num_subauth)) + RID(4).
+ * UNIX group id(16) = revision(1) + num_subauth(1) + authority(6) +
+ * sub_auth(4 * 1(num_subauth)) + RID(4).
+ */
+ id_to_sid(from_kuid_munged(&init_user_ns, vfsuid_into_kuid(vfsuid)),
+ SIDOWNER, (struct smb_sid *)&buf->SidBuffer[0]);
+ id_to_sid(from_kgid_munged(&init_user_ns, vfsgid_into_kgid(vfsgid)),
+ SIDUNIX_GROUP, (struct smb_sid *)&buf->SidBuffer[28]);
+}
+
+/*
+ * Find lease object(opinfo) for given lease key/fid from lease
+ * break/file close path.
+ */
+/**
+ * lookup_lease_in_table() - find a matching lease info object
+ * @conn: connection instance
+ * @lease_key: lease key to be searched for
+ *
+ * Return: opinfo if found matching opinfo, otherwise NULL
+ */
+struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
+ char *lease_key)
+{
+ struct oplock_info *opinfo = NULL, *ret_op = NULL;
+ struct lease_table *lt;
+ int ret;
+
+ read_lock(&lease_list_lock);
+ list_for_each_entry(lt, &lease_table_list, l_entry) {
+ if (!memcmp(lt->client_guid, conn->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE))
+ goto found;
+ }
+
+ read_unlock(&lease_list_lock);
+ return NULL;
+
+found:
+ rcu_read_lock();
+ list_for_each_entry_rcu(opinfo, <->lease_list, lease_entry) {
+ if (!atomic_inc_not_zero(&opinfo->refcount))
+ continue;
+ rcu_read_unlock();
+ if (!opinfo->op_state || opinfo->op_state == OPLOCK_CLOSING)
+ goto op_next;
+ if (!(opinfo->o_lease->state &
+ (SMB2_LEASE_HANDLE_CACHING_LE |
+ SMB2_LEASE_WRITE_CACHING_LE)))
+ goto op_next;
+ ret = compare_guid_key(opinfo, conn->ClientGUID,
+ lease_key);
+ if (ret) {
+ ksmbd_debug(OPLOCK, "found opinfo\n");
+ ret_op = opinfo;
+ goto out;
+ }
+op_next:
+ opinfo_put(opinfo);
+ rcu_read_lock();
+ }
+ rcu_read_unlock();
+
+out:
+ read_unlock(&lease_list_lock);
+ return ret_op;
+}
diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h
new file mode 100644
index 000000000000..4b0fe6da7694
--- /dev/null
+++ b/fs/smb/server/oplock.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __KSMBD_OPLOCK_H
+#define __KSMBD_OPLOCK_H
+
+#include "smb_common.h"
+
+#define OPLOCK_WAIT_TIME (35 * HZ)
+
+/* SMB2 Oplock levels */
+#define SMB2_OPLOCK_LEVEL_NONE 0x00
+#define SMB2_OPLOCK_LEVEL_II 0x01
+#define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08
+#define SMB2_OPLOCK_LEVEL_BATCH 0x09
+#define SMB2_OPLOCK_LEVEL_LEASE 0xFF
+
+/* Oplock states */
+#define OPLOCK_STATE_NONE 0x00
+#define OPLOCK_ACK_WAIT 0x01
+#define OPLOCK_CLOSING 0x02
+
+#define OPLOCK_WRITE_TO_READ 0x01
+#define OPLOCK_READ_HANDLE_TO_READ 0x02
+#define OPLOCK_WRITE_TO_NONE 0x04
+#define OPLOCK_READ_TO_NONE 0x08
+
+struct lease_ctx_info {
+ __u8 lease_key[SMB2_LEASE_KEY_SIZE];
+ __le32 req_state;
+ __le32 flags;
+ __le64 duration;
+ __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE];
+ int version;
+};
+
+struct lease_table {
+ char client_guid[SMB2_CLIENT_GUID_SIZE];
+ struct list_head lease_list;
+ struct list_head l_entry;
+ spinlock_t lb_lock;
+};
+
+struct lease {
+ __u8 lease_key[SMB2_LEASE_KEY_SIZE];
+ __le32 state;
+ __le32 new_state;
+ __le32 flags;
+ __le64 duration;
+ __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE];
+ int version;
+ unsigned short epoch;
+ struct lease_table *l_lb;
+};
+
+struct oplock_info {
+ struct ksmbd_conn *conn;
+ struct ksmbd_session *sess;
+ struct ksmbd_work *work;
+ struct ksmbd_file *o_fp;
+ int level;
+ int op_state;
+ unsigned long pending_break;
+ u64 fid;
+ atomic_t breaking_cnt;
+ atomic_t refcount;
+ __u16 Tid;
+ bool is_lease;
+ bool open_trunc; /* truncate on open */
+ struct lease *o_lease;
+ struct list_head interim_list;
+ struct list_head op_entry;
+ struct list_head lease_entry;
+ wait_queue_head_t oplock_q; /* Other server threads */
+ wait_queue_head_t oplock_brk; /* oplock breaking wait */
+ struct rcu_head rcu_head;
+};
+
+struct lease_break_info {
+ __le32 curr_state;
+ __le32 new_state;
+ __le16 epoch;
+ char lease_key[SMB2_LEASE_KEY_SIZE];
+};
+
+struct oplock_break_info {
+ int level;
+ int open_trunc;
+ int fid;
+};
+
+int smb_grant_oplock(struct ksmbd_work *work, int req_op_level,
+ u64 pid, struct ksmbd_file *fp, __u16 tid,
+ struct lease_ctx_info *lctx, int share_ret);
+void smb_break_all_levII_oplock(struct ksmbd_work *work,
+ struct ksmbd_file *fp, int is_trunc);
+int opinfo_write_to_read(struct oplock_info *opinfo);
+int opinfo_read_handle_to_read(struct oplock_info *opinfo);
+int opinfo_write_to_none(struct oplock_info *opinfo);
+int opinfo_read_to_none(struct oplock_info *opinfo);
+void close_id_del_oplock(struct ksmbd_file *fp);
+void smb_break_all_oplock(struct ksmbd_work *work, struct ksmbd_file *fp);
+struct oplock_info *opinfo_get(struct ksmbd_file *fp);
+void opinfo_put(struct oplock_info *opinfo);
+
+/* Lease related functions */
+void create_lease_buf(u8 *rbuf, struct lease *lease);
+struct lease_ctx_info *parse_lease_state(void *open_req);
+__u8 smb2_map_lease_to_oplock(__le32 lease_state);
+int lease_read_to_write(struct oplock_info *opinfo);
+
+/* Durable related functions */
+void create_durable_rsp_buf(char *cc);
+void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp);
+void create_mxac_rsp_buf(char *cc, int maximal_access);
+void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id);
+void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp);
+struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len);
+struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
+ char *lease_key);
+int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
+ struct lease_ctx_info *lctx);
+void destroy_lease_table(struct ksmbd_conn *conn);
+#endif /* __KSMBD_OPLOCK_H */
diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c
new file mode 100644
index 000000000000..847ee62afb8a
--- /dev/null
+++ b/fs/smb/server/server.c
@@ -0,0 +1,646 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include "glob.h"
+#include "oplock.h"
+#include "misc.h"
+#include <linux/sched/signal.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include "server.h"
+#include "smb_common.h"
+#include "smbstatus.h"
+#include "connection.h"
+#include "transport_ipc.h"
+#include "mgmt/user_session.h"
+#include "crypto_ctx.h"
+#include "auth.h"
+
+int ksmbd_debug_types;
+
+struct ksmbd_server_config server_conf;
+
+enum SERVER_CTRL_TYPE {
+ SERVER_CTRL_TYPE_INIT,
+ SERVER_CTRL_TYPE_RESET,
+};
+
+struct server_ctrl_struct {
+ int type;
+ struct work_struct ctrl_work;
+};
+
+static DEFINE_MUTEX(ctrl_lock);
+
+static int ___server_conf_set(int idx, char *val)
+{
+ if (idx >= ARRAY_SIZE(server_conf.conf))
+ return -EINVAL;
+
+ if (!val || val[0] == 0x00)
+ return -EINVAL;
+
+ kfree(server_conf.conf[idx]);
+ server_conf.conf[idx] = kstrdup(val, GFP_KERNEL);
+ if (!server_conf.conf[idx])
+ return -ENOMEM;
+ return 0;
+}
+
+int ksmbd_set_netbios_name(char *v)
+{
+ return ___server_conf_set(SERVER_CONF_NETBIOS_NAME, v);
+}
+
+int ksmbd_set_server_string(char *v)
+{
+ return ___server_conf_set(SERVER_CONF_SERVER_STRING, v);
+}
+
+int ksmbd_set_work_group(char *v)
+{
+ return ___server_conf_set(SERVER_CONF_WORK_GROUP, v);
+}
+
+char *ksmbd_netbios_name(void)
+{
+ return server_conf.conf[SERVER_CONF_NETBIOS_NAME];
+}
+
+char *ksmbd_server_string(void)
+{
+ return server_conf.conf[SERVER_CONF_SERVER_STRING];
+}
+
+char *ksmbd_work_group(void)
+{
+ return server_conf.conf[SERVER_CONF_WORK_GROUP];
+}
+
+/**
+ * check_conn_state() - check state of server thread connection
+ * @work: smb work containing server thread information
+ *
+ * Return: 0 on valid connection, otherwise 1 to reconnect
+ */
+static inline int check_conn_state(struct ksmbd_work *work)
+{
+ struct smb_hdr *rsp_hdr;
+
+ if (ksmbd_conn_exiting(work->conn) ||
+ ksmbd_conn_need_reconnect(work->conn)) {
+ rsp_hdr = work->response_buf;
+ rsp_hdr->Status.CifsError = STATUS_CONNECTION_DISCONNECTED;
+ return 1;
+ }
+ return 0;
+}
+
+#define SERVER_HANDLER_CONTINUE 0
+#define SERVER_HANDLER_ABORT 1
+
+static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
+ u16 *cmd)
+{
+ struct smb_version_cmds *cmds;
+ u16 command;
+ int ret;
+
+ if (check_conn_state(work))
+ return SERVER_HANDLER_CONTINUE;
+
+ if (ksmbd_verify_smb_message(work))
+ return SERVER_HANDLER_ABORT;
+
+ command = conn->ops->get_cmd_val(work);
+ *cmd = command;
+
+andx_again:
+ if (command >= conn->max_cmds) {
+ conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
+ return SERVER_HANDLER_CONTINUE;
+ }
+
+ cmds = &conn->cmds[command];
+ if (!cmds->proc) {
+ ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command);
+ conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED);
+ return SERVER_HANDLER_CONTINUE;
+ }
+
+ if (work->sess && conn->ops->is_sign_req(work, command)) {
+ ret = conn->ops->check_sign_req(work);
+ if (!ret) {
+ conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
+ return SERVER_HANDLER_CONTINUE;
+ }
+ }
+
+ ret = cmds->proc(work);
+
+ if (ret < 0)
+ ksmbd_debug(CONN, "Failed to process %u [%d]\n", command, ret);
+ /* AndX commands - chained request can return positive values */
+ else if (ret > 0) {
+ command = ret;
+ *cmd = command;
+ goto andx_again;
+ }
+
+ if (work->send_no_response)
+ return SERVER_HANDLER_ABORT;
+ return SERVER_HANDLER_CONTINUE;
+}
+
+static void __handle_ksmbd_work(struct ksmbd_work *work,
+ struct ksmbd_conn *conn)
+{
+ u16 command = 0;
+ int rc;
+
+ if (conn->ops->allocate_rsp_buf(work))
+ return;
+
+ if (conn->ops->is_transform_hdr &&
+ conn->ops->is_transform_hdr(work->request_buf)) {
+ rc = conn->ops->decrypt_req(work);
+ if (rc < 0) {
+ conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
+ goto send;
+ }
+
+ work->encrypted = true;
+ }
+
+ rc = conn->ops->init_rsp_hdr(work);
+ if (rc) {
+ /* either uid or tid is not correct */
+ conn->ops->set_rsp_status(work, STATUS_INVALID_HANDLE);
+ goto send;
+ }
+
+ do {
+ if (conn->ops->check_user_session) {
+ rc = conn->ops->check_user_session(work);
+ if (rc < 0) {
+ if (rc == -EINVAL)
+ conn->ops->set_rsp_status(work,
+ STATUS_INVALID_PARAMETER);
+ else
+ conn->ops->set_rsp_status(work,
+ STATUS_USER_SESSION_DELETED);
+ goto send;
+ } else if (rc > 0) {
+ rc = conn->ops->get_ksmbd_tcon(work);
+ if (rc < 0) {
+ if (rc == -EINVAL)
+ conn->ops->set_rsp_status(work,
+ STATUS_INVALID_PARAMETER);
+ else
+ conn->ops->set_rsp_status(work,
+ STATUS_NETWORK_NAME_DELETED);
+ goto send;
+ }
+ }
+ }
+
+ rc = __process_request(work, conn, &command);
+ if (rc == SERVER_HANDLER_ABORT)
+ break;
+
+ /*
+ * Call smb2_set_rsp_credits() function to set number of credits
+ * granted in hdr of smb2 response.
+ */
+ if (conn->ops->set_rsp_credits) {
+ spin_lock(&conn->credits_lock);
+ rc = conn->ops->set_rsp_credits(work);
+ spin_unlock(&conn->credits_lock);
+ if (rc < 0) {
+ conn->ops->set_rsp_status(work,
+ STATUS_INVALID_PARAMETER);
+ goto send;
+ }
+ }
+
+ if (work->sess &&
+ (work->sess->sign || smb3_11_final_sess_setup_resp(work) ||
+ conn->ops->is_sign_req(work, command)))
+ conn->ops->set_sign_rsp(work);
+ } while (is_chained_smb2_message(work));
+
+ if (work->send_no_response)
+ return;
+
+send:
+ smb3_preauth_hash_rsp(work);
+ if (work->sess && work->sess->enc && work->encrypted &&
+ conn->ops->encrypt_resp) {
+ rc = conn->ops->encrypt_resp(work);
+ if (rc < 0)
+ conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
+ }
+
+ ksmbd_conn_write(work);
+}
+
+/**
+ * handle_ksmbd_work() - process pending smb work requests
+ * @wk: smb work containing request command buffer
+ *
+ * called by kworker threads to processing remaining smb work requests
+ */
+static void handle_ksmbd_work(struct work_struct *wk)
+{
+ struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work);
+ struct ksmbd_conn *conn = work->conn;
+
+ atomic64_inc(&conn->stats.request_served);
+
+ __handle_ksmbd_work(work, conn);
+
+ ksmbd_conn_try_dequeue_request(work);
+ ksmbd_free_work_struct(work);
+ /*
+ * Checking waitqueue to dropping pending requests on
+ * disconnection. waitqueue_active is safe because it
+ * uses atomic operation for condition.
+ */
+ if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
+ wake_up(&conn->r_count_q);
+}
+
+/**
+ * queue_ksmbd_work() - queue a smb request to worker thread queue
+ * for proccessing smb command and sending response
+ * @conn: connection instance
+ *
+ * read remaining data from socket create and submit work.
+ */
+static int queue_ksmbd_work(struct ksmbd_conn *conn)
+{
+ struct ksmbd_work *work;
+
+ work = ksmbd_alloc_work_struct();
+ if (!work) {
+ pr_err("allocation for work failed\n");
+ return -ENOMEM;
+ }
+
+ work->conn = conn;
+ work->request_buf = conn->request_buf;
+ conn->request_buf = NULL;
+
+ ksmbd_init_smb_server(work);
+
+ ksmbd_conn_enqueue_request(work);
+ atomic_inc(&conn->r_count);
+ /* update activity on connection */
+ conn->last_active = jiffies;
+ INIT_WORK(&work->work, handle_ksmbd_work);
+ ksmbd_queue_work(work);
+ return 0;
+}
+
+static int ksmbd_server_process_request(struct ksmbd_conn *conn)
+{
+ return queue_ksmbd_work(conn);
+}
+
+static int ksmbd_server_terminate_conn(struct ksmbd_conn *conn)
+{
+ ksmbd_sessions_deregister(conn);
+ destroy_lease_table(conn);
+ return 0;
+}
+
+static void ksmbd_server_tcp_callbacks_init(void)
+{
+ struct ksmbd_conn_ops ops;
+
+ ops.process_fn = ksmbd_server_process_request;
+ ops.terminate_fn = ksmbd_server_terminate_conn;
+
+ ksmbd_conn_init_server_callbacks(&ops);
+}
+
+static void server_conf_free(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(server_conf.conf); i++) {
+ kfree(server_conf.conf[i]);
+ server_conf.conf[i] = NULL;
+ }
+}
+
+static int server_conf_init(void)
+{
+ WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP);
+ server_conf.enforced_signing = 0;
+ server_conf.min_protocol = ksmbd_min_protocol();
+ server_conf.max_protocol = ksmbd_max_protocol();
+ server_conf.auth_mechs = KSMBD_AUTH_NTLMSSP;
+#ifdef CONFIG_SMB_SERVER_KERBEROS5
+ server_conf.auth_mechs |= KSMBD_AUTH_KRB5 |
+ KSMBD_AUTH_MSKRB5;
+#endif
+ return 0;
+}
+
+static void server_ctrl_handle_init(struct server_ctrl_struct *ctrl)
+{
+ int ret;
+
+ ret = ksmbd_conn_transport_init();
+ if (ret) {
+ server_queue_ctrl_reset_work();
+ return;
+ }
+
+ WRITE_ONCE(server_conf.state, SERVER_STATE_RUNNING);
+}
+
+static void server_ctrl_handle_reset(struct server_ctrl_struct *ctrl)
+{
+ ksmbd_ipc_soft_reset();
+ ksmbd_conn_transport_destroy();
+ server_conf_free();
+ server_conf_init();
+ WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP);
+}
+
+static void server_ctrl_handle_work(struct work_struct *work)
+{
+ struct server_ctrl_struct *ctrl;
+
+ ctrl = container_of(work, struct server_ctrl_struct, ctrl_work);
+
+ mutex_lock(&ctrl_lock);
+ switch (ctrl->type) {
+ case SERVER_CTRL_TYPE_INIT:
+ server_ctrl_handle_init(ctrl);
+ break;
+ case SERVER_CTRL_TYPE_RESET:
+ server_ctrl_handle_reset(ctrl);
+ break;
+ default:
+ pr_err("Unknown server work type: %d\n", ctrl->type);
+ }
+ mutex_unlock(&ctrl_lock);
+ kfree(ctrl);
+ module_put(THIS_MODULE);
+}
+
+static int __queue_ctrl_work(int type)
+{
+ struct server_ctrl_struct *ctrl;
+
+ ctrl = kmalloc(sizeof(struct server_ctrl_struct), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ __module_get(THIS_MODULE);
+ ctrl->type = type;
+ INIT_WORK(&ctrl->ctrl_work, server_ctrl_handle_work);
+ queue_work(system_long_wq, &ctrl->ctrl_work);
+ return 0;
+}
+
+int server_queue_ctrl_init_work(void)
+{
+ return __queue_ctrl_work(SERVER_CTRL_TYPE_INIT);
+}
+
+int server_queue_ctrl_reset_work(void)
+{
+ return __queue_ctrl_work(SERVER_CTRL_TYPE_RESET);
+}
+
+static ssize_t stats_show(struct class *class, struct class_attribute *attr,
+ char *buf)
+{
+ /*
+ * Inc this each time you change stats output format,
+ * so user space will know what to do.
+ */
+ static int stats_version = 2;
+ static const char * const state[] = {
+ "startup",
+ "running",
+ "reset",
+ "shutdown"
+ };
+
+ ssize_t sz = scnprintf(buf, PAGE_SIZE, "%d %s %d %lu\n", stats_version,
+ state[server_conf.state], server_conf.tcp_port,
+ server_conf.ipc_last_active / HZ);
+ return sz;
+}
+
+static ssize_t kill_server_store(struct class *class,
+ struct class_attribute *attr, const char *buf,
+ size_t len)
+{
+ if (!sysfs_streq(buf, "hard"))
+ return len;
+
+ pr_info("kill command received\n");
+ mutex_lock(&ctrl_lock);
+ WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
+ __module_get(THIS_MODULE);
+ server_ctrl_handle_reset(NULL);
+ module_put(THIS_MODULE);
+ mutex_unlock(&ctrl_lock);
+ return len;
+}
+
+static const char * const debug_type_strings[] = {"smb", "auth", "vfs",
+ "oplock", "ipc", "conn",
+ "rdma"};
+
+static ssize_t debug_show(struct class *class, struct class_attribute *attr,
+ char *buf)
+{
+ ssize_t sz = 0;
+ int i, pos = 0;
+
+ for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) {
+ if ((ksmbd_debug_types >> i) & 1) {
+ pos = scnprintf(buf + sz,
+ PAGE_SIZE - sz,
+ "[%s] ",
+ debug_type_strings[i]);
+ } else {
+ pos = scnprintf(buf + sz,
+ PAGE_SIZE - sz,
+ "%s ",
+ debug_type_strings[i]);
+ }
+ sz += pos;
+ }
+ sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
+ return sz;
+}
+
+static ssize_t debug_store(struct class *class, struct class_attribute *attr,
+ const char *buf, size_t len)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) {
+ if (sysfs_streq(buf, "all")) {
+ if (ksmbd_debug_types == KSMBD_DEBUG_ALL)
+ ksmbd_debug_types = 0;
+ else
+ ksmbd_debug_types = KSMBD_DEBUG_ALL;
+ break;
+ }
+
+ if (sysfs_streq(buf, debug_type_strings[i])) {
+ if (ksmbd_debug_types & (1 << i))
+ ksmbd_debug_types &= ~(1 << i);
+ else
+ ksmbd_debug_types |= (1 << i);
+ break;
+ }
+ }
+
+ return len;
+}
+
+static CLASS_ATTR_RO(stats);
+static CLASS_ATTR_WO(kill_server);
+static CLASS_ATTR_RW(debug);
+
+static struct attribute *ksmbd_control_class_attrs[] = {
+ &class_attr_stats.attr,
+ &class_attr_kill_server.attr,
+ &class_attr_debug.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(ksmbd_control_class);
+
+static struct class ksmbd_control_class = {
+ .name = "ksmbd-control",
+ .owner = THIS_MODULE,
+ .class_groups = ksmbd_control_class_groups,
+};
+
+static int ksmbd_server_shutdown(void)
+{
+ WRITE_ONCE(server_conf.state, SERVER_STATE_SHUTTING_DOWN);
+
+ class_unregister(&ksmbd_control_class);
+ ksmbd_workqueue_destroy();
+ ksmbd_ipc_release();
+ ksmbd_conn_transport_destroy();
+ ksmbd_crypto_destroy();
+ ksmbd_free_global_file_table();
+ destroy_lease_table(NULL);
+ ksmbd_work_pool_destroy();
+ ksmbd_exit_file_cache();
+ server_conf_free();
+ return 0;
+}
+
+static int __init ksmbd_server_init(void)
+{
+ int ret;
+
+ ret = class_register(&ksmbd_control_class);
+ if (ret) {
+ pr_err("Unable to register ksmbd-control class\n");
+ return ret;
+ }
+
+ ksmbd_server_tcp_callbacks_init();
+
+ ret = server_conf_init();
+ if (ret)
+ goto err_unregister;
+
+ ret = ksmbd_work_pool_init();
+ if (ret)
+ goto err_unregister;
+
+ ret = ksmbd_init_file_cache();
+ if (ret)
+ goto err_destroy_work_pools;
+
+ ret = ksmbd_ipc_init();
+ if (ret)
+ goto err_exit_file_cache;
+
+ ret = ksmbd_init_global_file_table();
+ if (ret)
+ goto err_ipc_release;
+
+ ret = ksmbd_inode_hash_init();
+ if (ret)
+ goto err_destroy_file_table;
+
+ ret = ksmbd_crypto_create();
+ if (ret)
+ goto err_release_inode_hash;
+
+ ret = ksmbd_workqueue_init();
+ if (ret)
+ goto err_crypto_destroy;
+
+ pr_warn_once("The ksmbd server is experimental\n");
+
+ return 0;
+
+err_crypto_destroy:
+ ksmbd_crypto_destroy();
+err_release_inode_hash:
+ ksmbd_release_inode_hash();
+err_destroy_file_table:
+ ksmbd_free_global_file_table();
+err_ipc_release:
+ ksmbd_ipc_release();
+err_exit_file_cache:
+ ksmbd_exit_file_cache();
+err_destroy_work_pools:
+ ksmbd_work_pool_destroy();
+err_unregister:
+ class_unregister(&ksmbd_control_class);
+
+ return ret;
+}
+
+/**
+ * ksmbd_server_exit() - shutdown forker thread and free memory at module exit
+ */
+static void __exit ksmbd_server_exit(void)
+{
+ ksmbd_server_shutdown();
+ rcu_barrier();
+ ksmbd_release_inode_hash();
+}
+
+MODULE_AUTHOR("Namjae Jeon <linkinjeon@kernel.org>");
+MODULE_VERSION(KSMBD_VERSION);
+MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
+MODULE_LICENSE("GPL");
+MODULE_SOFTDEP("pre: ecb");
+MODULE_SOFTDEP("pre: hmac");
+MODULE_SOFTDEP("pre: md5");
+MODULE_SOFTDEP("pre: nls");
+MODULE_SOFTDEP("pre: aes");
+MODULE_SOFTDEP("pre: cmac");
+MODULE_SOFTDEP("pre: sha256");
+MODULE_SOFTDEP("pre: sha512");
+MODULE_SOFTDEP("pre: aead2");
+MODULE_SOFTDEP("pre: ccm");
+MODULE_SOFTDEP("pre: gcm");
+MODULE_SOFTDEP("pre: crc32");
+module_init(ksmbd_server_init)
+module_exit(ksmbd_server_exit)
diff --git a/fs/smb/server/server.h b/fs/smb/server/server.h
new file mode 100644
index 000000000000..db7278181760
--- /dev/null
+++ b/fs/smb/server/server.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __SERVER_H__
+#define __SERVER_H__
+
+#include "smbacl.h"
+
+/*
+ * Server state type
+ */
+enum {
+ SERVER_STATE_STARTING_UP,
+ SERVER_STATE_RUNNING,
+ SERVER_STATE_RESETTING,
+ SERVER_STATE_SHUTTING_DOWN,
+};
+
+/*
+ * Server global config string index
+ */
+enum {
+ SERVER_CONF_NETBIOS_NAME,
+ SERVER_CONF_SERVER_STRING,
+ SERVER_CONF_WORK_GROUP,
+};
+
+struct ksmbd_server_config {
+ unsigned int flags;
+ unsigned int state;
+ short signing;
+ short enforced_signing;
+ short min_protocol;
+ short max_protocol;
+ unsigned short tcp_port;
+ unsigned short ipc_timeout;
+ unsigned long ipc_last_active;
+ unsigned long deadtime;
+ unsigned int share_fake_fscaps;
+ struct smb_sid domain_sid;
+ unsigned int auth_mechs;
+ unsigned int max_connections;
+
+ char *conf[SERVER_CONF_WORK_GROUP + 1];
+};
+
+extern struct ksmbd_server_config server_conf;
+
+int ksmbd_set_netbios_name(char *v);
+int ksmbd_set_server_string(char *v);
+int ksmbd_set_work_group(char *v);
+
+char *ksmbd_netbios_name(void);
+char *ksmbd_server_string(void);
+char *ksmbd_work_group(void);
+
+static inline int ksmbd_server_running(void)
+{
+ return READ_ONCE(server_conf.state) == SERVER_STATE_RUNNING;
+}
+
+static inline int ksmbd_server_configurable(void)
+{
+ return READ_ONCE(server_conf.state) < SERVER_STATE_RESETTING;
+}
+
+int server_queue_ctrl_init_work(void);
+int server_queue_ctrl_reset_work(void);
+#endif /* __SERVER_H__ */
diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c
new file mode 100644
index 000000000000..33b7e6c4ceff
--- /dev/null
+++ b/fs/smb/server/smb2misc.c
@@ -0,0 +1,454 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include "glob.h"
+#include "nterr.h"
+#include "smb_common.h"
+#include "smbstatus.h"
+#include "mgmt/user_session.h"
+#include "connection.h"
+
+static int check_smb2_hdr(struct smb2_hdr *hdr)
+{
+ /*
+ * Make sure that this really is an SMB, that it is a response.
+ */
+ if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
+ return 1;
+ return 0;
+}
+
+/*
+ * The following table defines the expected "StructureSize" of SMB2 requests
+ * in order by SMB2 command. This is similar to "wct" in SMB/CIFS requests.
+ *
+ * Note that commands are defined in smb2pdu.h in le16 but the array below is
+ * indexed by command in host byte order
+ */
+static const __le16 smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
+ /* SMB2_NEGOTIATE */ cpu_to_le16(36),
+ /* SMB2_SESSION_SETUP */ cpu_to_le16(25),
+ /* SMB2_LOGOFF */ cpu_to_le16(4),
+ /* SMB2_TREE_CONNECT */ cpu_to_le16(9),
+ /* SMB2_TREE_DISCONNECT */ cpu_to_le16(4),
+ /* SMB2_CREATE */ cpu_to_le16(57),
+ /* SMB2_CLOSE */ cpu_to_le16(24),
+ /* SMB2_FLUSH */ cpu_to_le16(24),
+ /* SMB2_READ */ cpu_to_le16(49),
+ /* SMB2_WRITE */ cpu_to_le16(49),
+ /* SMB2_LOCK */ cpu_to_le16(48),
+ /* SMB2_IOCTL */ cpu_to_le16(57),
+ /* SMB2_CANCEL */ cpu_to_le16(4),
+ /* SMB2_ECHO */ cpu_to_le16(4),
+ /* SMB2_QUERY_DIRECTORY */ cpu_to_le16(33),
+ /* SMB2_CHANGE_NOTIFY */ cpu_to_le16(32),
+ /* SMB2_QUERY_INFO */ cpu_to_le16(41),
+ /* SMB2_SET_INFO */ cpu_to_le16(33),
+ /* use 44 for lease break */
+ /* SMB2_OPLOCK_BREAK */ cpu_to_le16(36)
+};
+
+/*
+ * The size of the variable area depends on the offset and length fields
+ * located in different fields for various SMB2 requests. SMB2 requests
+ * with no variable length info, show an offset of zero for the offset field.
+ */
+static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
+ /* SMB2_NEGOTIATE */ true,
+ /* SMB2_SESSION_SETUP */ true,
+ /* SMB2_LOGOFF */ false,
+ /* SMB2_TREE_CONNECT */ true,
+ /* SMB2_TREE_DISCONNECT */ false,
+ /* SMB2_CREATE */ true,
+ /* SMB2_CLOSE */ false,
+ /* SMB2_FLUSH */ false,
+ /* SMB2_READ */ true,
+ /* SMB2_WRITE */ true,
+ /* SMB2_LOCK */ true,
+ /* SMB2_IOCTL */ true,
+ /* SMB2_CANCEL */ false, /* BB CHECK this not listed in documentation */
+ /* SMB2_ECHO */ false,
+ /* SMB2_QUERY_DIRECTORY */ true,
+ /* SMB2_CHANGE_NOTIFY */ false,
+ /* SMB2_QUERY_INFO */ true,
+ /* SMB2_SET_INFO */ true,
+ /* SMB2_OPLOCK_BREAK */ false
+};
+
+/*
+ * Set length of the data area and the offset to arguments.
+ * if they are invalid, return error.
+ */
+static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
+ struct smb2_hdr *hdr)
+{
+ int ret = 0;
+
+ *off = 0;
+ *len = 0;
+
+ /*
+ * Following commands have data areas so we have to get the location
+ * of the data buffer offset and data buffer length for the particular
+ * command.
+ */
+ switch (hdr->Command) {
+ case SMB2_SESSION_SETUP:
+ *off = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferOffset);
+ *len = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferLength);
+ break;
+ case SMB2_TREE_CONNECT:
+ *off = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset);
+ *len = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathLength);
+ break;
+ case SMB2_CREATE:
+ {
+ if (((struct smb2_create_req *)hdr)->CreateContextsLength) {
+ *off = le32_to_cpu(((struct smb2_create_req *)
+ hdr)->CreateContextsOffset);
+ *len = le32_to_cpu(((struct smb2_create_req *)
+ hdr)->CreateContextsLength);
+ break;
+ }
+
+ *off = le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset);
+ *len = le16_to_cpu(((struct smb2_create_req *)hdr)->NameLength);
+ break;
+ }
+ case SMB2_QUERY_INFO:
+ *off = le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset);
+ *len = le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLength);
+ break;
+ case SMB2_SET_INFO:
+ *off = le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset);
+ *len = le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength);
+ break;
+ case SMB2_READ:
+ *off = le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoOffset);
+ *len = le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoLength);
+ break;
+ case SMB2_WRITE:
+ if (((struct smb2_write_req *)hdr)->DataOffset ||
+ ((struct smb2_write_req *)hdr)->Length) {
+ *off = max_t(unsigned int,
+ le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset),
+ offsetof(struct smb2_write_req, Buffer));
+ *len = le32_to_cpu(((struct smb2_write_req *)hdr)->Length);
+ break;
+ }
+
+ *off = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoOffset);
+ *len = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLength);
+ break;
+ case SMB2_QUERY_DIRECTORY:
+ *off = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset);
+ *len = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameLength);
+ break;
+ case SMB2_LOCK:
+ {
+ unsigned short lock_count;
+
+ lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount);
+ if (lock_count > 0) {
+ *off = offsetof(struct smb2_lock_req, locks);
+ *len = sizeof(struct smb2_lock_element) * lock_count;
+ }
+ break;
+ }
+ case SMB2_IOCTL:
+ *off = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset);
+ *len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount);
+ break;
+ default:
+ ksmbd_debug(SMB, "no length check for command\n");
+ break;
+ }
+
+ if (*off > 4096) {
+ ksmbd_debug(SMB, "offset %d too large\n", *off);
+ ret = -EINVAL;
+ } else if ((u64)*off + *len > MAX_STREAM_PROT_LEN) {
+ ksmbd_debug(SMB, "Request is larger than maximum stream protocol length(%u): %llu\n",
+ MAX_STREAM_PROT_LEN, (u64)*off + *len);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/*
+ * Calculate the size of the SMB message based on the fixed header
+ * portion, the number of word parameters and the data portion of the message.
+ */
+static int smb2_calc_size(void *buf, unsigned int *len)
+{
+ struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
+ struct smb2_hdr *hdr = &pdu->hdr;
+ unsigned int offset; /* the offset from the beginning of SMB to data area */
+ unsigned int data_length; /* the length of the variable length data area */
+ int ret;
+
+ /* Structure Size has already been checked to make sure it is 64 */
+ *len = le16_to_cpu(hdr->StructureSize);
+
+ /*
+ * StructureSize2, ie length of fixed parameter area has already
+ * been checked to make sure it is the correct length.
+ */
+ *len += le16_to_cpu(pdu->StructureSize2);
+ /*
+ * StructureSize2 of smb2_lock pdu is set to 48, indicating
+ * the size of smb2 lock request with single smb2_lock_element
+ * regardless of number of locks. Subtract single
+ * smb2_lock_element for correct buffer size check.
+ */
+ if (hdr->Command == SMB2_LOCK)
+ *len -= sizeof(struct smb2_lock_element);
+
+ if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false)
+ goto calc_size_exit;
+
+ ret = smb2_get_data_area_len(&offset, &data_length, hdr);
+ if (ret)
+ return ret;
+ ksmbd_debug(SMB, "SMB2 data length %u offset %u\n", data_length,
+ offset);
+
+ if (data_length > 0) {
+ /*
+ * Check to make sure that data area begins after fixed area,
+ * Note that last byte of the fixed area is part of data area
+ * for some commands, typically those with odd StructureSize,
+ * so we must add one to the calculation.
+ */
+ if (offset + 1 < *len) {
+ ksmbd_debug(SMB,
+ "data area offset %d overlaps SMB2 header %u\n",
+ offset + 1, *len);
+ return -EINVAL;
+ }
+
+ *len = offset + data_length;
+ }
+
+calc_size_exit:
+ ksmbd_debug(SMB, "SMB2 len %u\n", *len);
+ return 0;
+}
+
+static inline int smb2_query_info_req_len(struct smb2_query_info_req *h)
+{
+ return le32_to_cpu(h->InputBufferLength) +
+ le32_to_cpu(h->OutputBufferLength);
+}
+
+static inline int smb2_set_info_req_len(struct smb2_set_info_req *h)
+{
+ return le32_to_cpu(h->BufferLength);
+}
+
+static inline int smb2_read_req_len(struct smb2_read_req *h)
+{
+ return le32_to_cpu(h->Length);
+}
+
+static inline int smb2_write_req_len(struct smb2_write_req *h)
+{
+ return le32_to_cpu(h->Length);
+}
+
+static inline int smb2_query_dir_req_len(struct smb2_query_directory_req *h)
+{
+ return le32_to_cpu(h->OutputBufferLength);
+}
+
+static inline int smb2_ioctl_req_len(struct smb2_ioctl_req *h)
+{
+ return le32_to_cpu(h->InputCount) +
+ le32_to_cpu(h->OutputCount);
+}
+
+static inline int smb2_ioctl_resp_len(struct smb2_ioctl_req *h)
+{
+ return le32_to_cpu(h->MaxInputResponse) +
+ le32_to_cpu(h->MaxOutputResponse);
+}
+
+static int smb2_validate_credit_charge(struct ksmbd_conn *conn,
+ struct smb2_hdr *hdr)
+{
+ unsigned int req_len = 0, expect_resp_len = 0, calc_credit_num, max_len;
+ unsigned short credit_charge = le16_to_cpu(hdr->CreditCharge);
+ void *__hdr = hdr;
+ int ret = 0;
+
+ switch (hdr->Command) {
+ case SMB2_QUERY_INFO:
+ req_len = smb2_query_info_req_len(__hdr);
+ break;
+ case SMB2_SET_INFO:
+ req_len = smb2_set_info_req_len(__hdr);
+ break;
+ case SMB2_READ:
+ req_len = smb2_read_req_len(__hdr);
+ break;
+ case SMB2_WRITE:
+ req_len = smb2_write_req_len(__hdr);
+ break;
+ case SMB2_QUERY_DIRECTORY:
+ req_len = smb2_query_dir_req_len(__hdr);
+ break;
+ case SMB2_IOCTL:
+ req_len = smb2_ioctl_req_len(__hdr);
+ expect_resp_len = smb2_ioctl_resp_len(__hdr);
+ break;
+ case SMB2_CANCEL:
+ return 0;
+ default:
+ req_len = 1;
+ break;
+ }
+
+ credit_charge = max_t(unsigned short, credit_charge, 1);
+ max_len = max_t(unsigned int, req_len, expect_resp_len);
+ calc_credit_num = DIV_ROUND_UP(max_len, SMB2_MAX_BUFFER_SIZE);
+
+ if (credit_charge < calc_credit_num) {
+ ksmbd_debug(SMB, "Insufficient credit charge, given: %d, needed: %d\n",
+ credit_charge, calc_credit_num);
+ return 1;
+ } else if (credit_charge > conn->vals->max_credits) {
+ ksmbd_debug(SMB, "Too large credit charge: %d\n", credit_charge);
+ return 1;
+ }
+
+ spin_lock(&conn->credits_lock);
+ if (credit_charge > conn->total_credits) {
+ ksmbd_debug(SMB, "Insufficient credits granted, given: %u, granted: %u\n",
+ credit_charge, conn->total_credits);
+ ret = 1;
+ }
+
+ if ((u64)conn->outstanding_credits + credit_charge > conn->total_credits) {
+ ksmbd_debug(SMB, "Limits exceeding the maximum allowable outstanding requests, given : %u, pending : %u\n",
+ credit_charge, conn->outstanding_credits);
+ ret = 1;
+ } else
+ conn->outstanding_credits += credit_charge;
+
+ spin_unlock(&conn->credits_lock);
+
+ return ret;
+}
+
+int ksmbd_smb2_check_message(struct ksmbd_work *work)
+{
+ struct smb2_pdu *pdu = ksmbd_req_buf_next(work);
+ struct smb2_hdr *hdr = &pdu->hdr;
+ int command;
+ __u32 clc_len; /* calculated length */
+ __u32 len = get_rfc1002_len(work->request_buf);
+ __u32 req_struct_size, next_cmd = le32_to_cpu(hdr->NextCommand);
+
+ if ((u64)work->next_smb2_rcv_hdr_off + next_cmd > len) {
+ pr_err("next command(%u) offset exceeds smb msg size\n",
+ next_cmd);
+ return 1;
+ }
+
+ if (next_cmd > 0)
+ len = next_cmd;
+ else if (work->next_smb2_rcv_hdr_off)
+ len -= work->next_smb2_rcv_hdr_off;
+
+ if (check_smb2_hdr(hdr))
+ return 1;
+
+ if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
+ ksmbd_debug(SMB, "Illegal structure size %u\n",
+ le16_to_cpu(hdr->StructureSize));
+ return 1;
+ }
+
+ command = le16_to_cpu(hdr->Command);
+ if (command >= NUMBER_OF_SMB2_COMMANDS) {
+ ksmbd_debug(SMB, "Illegal SMB2 command %d\n", command);
+ return 1;
+ }
+
+ if (smb2_req_struct_sizes[command] != pdu->StructureSize2) {
+ if (command == SMB2_OPLOCK_BREAK_HE &&
+ le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 &&
+ le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) {
+ /* special case for SMB2.1 lease break message */
+ ksmbd_debug(SMB,
+ "Illegal request size %d for oplock break\n",
+ le16_to_cpu(pdu->StructureSize2));
+ return 1;
+ }
+ }
+
+ req_struct_size = le16_to_cpu(pdu->StructureSize2) +
+ __SMB2_HEADER_STRUCTURE_SIZE;
+ if (command == SMB2_LOCK_HE)
+ req_struct_size -= sizeof(struct smb2_lock_element);
+
+ if (req_struct_size > len + 1)
+ return 1;
+
+ if (smb2_calc_size(hdr, &clc_len))
+ return 1;
+
+ if (len != clc_len) {
+ /* client can return one byte more due to implied bcc[0] */
+ if (clc_len == len + 1)
+ goto validate_credit;
+
+ /*
+ * Some windows servers (win2016) will pad also the final
+ * PDU in a compound to 8 bytes.
+ */
+ if (ALIGN(clc_len, 8) == len)
+ goto validate_credit;
+
+ /*
+ * SMB2 NEGOTIATE request will be validated when message
+ * handling proceeds.
+ */
+ if (command == SMB2_NEGOTIATE_HE)
+ goto validate_credit;
+
+ /*
+ * Allow a message that padded to 8byte boundary.
+ * Linux 4.19.217 with smb 3.0.2 are sometimes
+ * sending messages where the cls_len is exactly
+ * 8 bytes less than len.
+ */
+ if (clc_len < len && (len - clc_len) <= 8)
+ goto validate_credit;
+
+ pr_err_ratelimited(
+ "cli req too short, len %d not %d. cmd:%d mid:%llu\n",
+ len, clc_len, command,
+ le64_to_cpu(hdr->MessageId));
+
+ return 1;
+ }
+
+validate_credit:
+ if ((work->conn->vals->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU) &&
+ smb2_validate_credit_charge(work->conn, hdr)) {
+ work->conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
+ return 1;
+ }
+
+ return 0;
+}
+
+int smb2_negotiate_request(struct ksmbd_work *work)
+{
+ return ksmbd_smb_negotiate_common(work, SMB2_NEGOTIATE_HE);
+}
diff --git a/fs/smb/server/smb2ops.c b/fs/smb/server/smb2ops.c
new file mode 100644
index 000000000000..ab23da2120b9
--- /dev/null
+++ b/fs/smb/server/smb2ops.c
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/slab.h>
+#include "glob.h"
+
+#include "auth.h"
+#include "connection.h"
+#include "smb_common.h"
+#include "server.h"
+
+static struct smb_version_values smb21_server_values = {
+ .version_string = SMB21_VERSION_STRING,
+ .protocol_id = SMB21_PROT_ID,
+ .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
+ .max_read_size = SMB21_DEFAULT_IOSIZE,
+ .max_write_size = SMB21_DEFAULT_IOSIZE,
+ .max_trans_size = SMB21_DEFAULT_IOSIZE,
+ .max_credits = SMB2_MAX_CREDITS,
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .create_lease_size = sizeof(struct create_lease),
+ .create_durable_size = sizeof(struct create_durable_rsp),
+ .create_mxac_size = sizeof(struct create_mxac_rsp),
+ .create_disk_id_size = sizeof(struct create_disk_id_rsp),
+ .create_posix_size = sizeof(struct create_posix_rsp),
+};
+
+static struct smb_version_values smb30_server_values = {
+ .version_string = SMB30_VERSION_STRING,
+ .protocol_id = SMB30_PROT_ID,
+ .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
+ .max_read_size = SMB3_DEFAULT_IOSIZE,
+ .max_write_size = SMB3_DEFAULT_IOSIZE,
+ .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
+ .max_credits = SMB2_MAX_CREDITS,
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .create_lease_size = sizeof(struct create_lease_v2),
+ .create_durable_size = sizeof(struct create_durable_rsp),
+ .create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
+ .create_mxac_size = sizeof(struct create_mxac_rsp),
+ .create_disk_id_size = sizeof(struct create_disk_id_rsp),
+ .create_posix_size = sizeof(struct create_posix_rsp),
+};
+
+static struct smb_version_values smb302_server_values = {
+ .version_string = SMB302_VERSION_STRING,
+ .protocol_id = SMB302_PROT_ID,
+ .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
+ .max_read_size = SMB3_DEFAULT_IOSIZE,
+ .max_write_size = SMB3_DEFAULT_IOSIZE,
+ .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
+ .max_credits = SMB2_MAX_CREDITS,
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .create_lease_size = sizeof(struct create_lease_v2),
+ .create_durable_size = sizeof(struct create_durable_rsp),
+ .create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
+ .create_mxac_size = sizeof(struct create_mxac_rsp),
+ .create_disk_id_size = sizeof(struct create_disk_id_rsp),
+ .create_posix_size = sizeof(struct create_posix_rsp),
+};
+
+static struct smb_version_values smb311_server_values = {
+ .version_string = SMB311_VERSION_STRING,
+ .protocol_id = SMB311_PROT_ID,
+ .capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
+ .max_read_size = SMB3_DEFAULT_IOSIZE,
+ .max_write_size = SMB3_DEFAULT_IOSIZE,
+ .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
+ .max_credits = SMB2_MAX_CREDITS,
+ .large_lock_type = 0,
+ .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE,
+ .shared_lock_type = SMB2_LOCKFLAG_SHARED,
+ .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+ .header_size = sizeof(struct smb2_hdr),
+ .max_header_size = MAX_SMB2_HDR_SIZE,
+ .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+ .lock_cmd = SMB2_LOCK,
+ .cap_unix = 0,
+ .cap_nt_find = SMB2_NT_FIND,
+ .cap_large_files = SMB2_LARGE_FILES,
+ .create_lease_size = sizeof(struct create_lease_v2),
+ .create_durable_size = sizeof(struct create_durable_rsp),
+ .create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
+ .create_mxac_size = sizeof(struct create_mxac_rsp),
+ .create_disk_id_size = sizeof(struct create_disk_id_rsp),
+ .create_posix_size = sizeof(struct create_posix_rsp),
+};
+
+static struct smb_version_ops smb2_0_server_ops = {
+ .get_cmd_val = get_smb2_cmd_val,
+ .init_rsp_hdr = init_smb2_rsp_hdr,
+ .set_rsp_status = set_smb2_rsp_status,
+ .allocate_rsp_buf = smb2_allocate_rsp_buf,
+ .set_rsp_credits = smb2_set_rsp_credits,
+ .check_user_session = smb2_check_user_session,
+ .get_ksmbd_tcon = smb2_get_ksmbd_tcon,
+ .is_sign_req = smb2_is_sign_req,
+ .check_sign_req = smb2_check_sign_req,
+ .set_sign_rsp = smb2_set_sign_rsp
+};
+
+static struct smb_version_ops smb3_0_server_ops = {
+ .get_cmd_val = get_smb2_cmd_val,
+ .init_rsp_hdr = init_smb2_rsp_hdr,
+ .set_rsp_status = set_smb2_rsp_status,
+ .allocate_rsp_buf = smb2_allocate_rsp_buf,
+ .set_rsp_credits = smb2_set_rsp_credits,
+ .check_user_session = smb2_check_user_session,
+ .get_ksmbd_tcon = smb2_get_ksmbd_tcon,
+ .is_sign_req = smb2_is_sign_req,
+ .check_sign_req = smb3_check_sign_req,
+ .set_sign_rsp = smb3_set_sign_rsp,
+ .generate_signingkey = ksmbd_gen_smb30_signingkey,
+ .generate_encryptionkey = ksmbd_gen_smb30_encryptionkey,
+ .is_transform_hdr = smb3_is_transform_hdr,
+ .decrypt_req = smb3_decrypt_req,
+ .encrypt_resp = smb3_encrypt_resp
+};
+
+static struct smb_version_ops smb3_11_server_ops = {
+ .get_cmd_val = get_smb2_cmd_val,
+ .init_rsp_hdr = init_smb2_rsp_hdr,
+ .set_rsp_status = set_smb2_rsp_status,
+ .allocate_rsp_buf = smb2_allocate_rsp_buf,
+ .set_rsp_credits = smb2_set_rsp_credits,
+ .check_user_session = smb2_check_user_session,
+ .get_ksmbd_tcon = smb2_get_ksmbd_tcon,
+ .is_sign_req = smb2_is_sign_req,
+ .check_sign_req = smb3_check_sign_req,
+ .set_sign_rsp = smb3_set_sign_rsp,
+ .generate_signingkey = ksmbd_gen_smb311_signingkey,
+ .generate_encryptionkey = ksmbd_gen_smb311_encryptionkey,
+ .is_transform_hdr = smb3_is_transform_hdr,
+ .decrypt_req = smb3_decrypt_req,
+ .encrypt_resp = smb3_encrypt_resp
+};
+
+static struct smb_version_cmds smb2_0_server_cmds[NUMBER_OF_SMB2_COMMANDS] = {
+ [SMB2_NEGOTIATE_HE] = { .proc = smb2_negotiate_request, },
+ [SMB2_SESSION_SETUP_HE] = { .proc = smb2_sess_setup, },
+ [SMB2_TREE_CONNECT_HE] = { .proc = smb2_tree_connect,},
+ [SMB2_TREE_DISCONNECT_HE] = { .proc = smb2_tree_disconnect,},
+ [SMB2_LOGOFF_HE] = { .proc = smb2_session_logoff,},
+ [SMB2_CREATE_HE] = { .proc = smb2_open},
+ [SMB2_QUERY_INFO_HE] = { .proc = smb2_query_info},
+ [SMB2_QUERY_DIRECTORY_HE] = { .proc = smb2_query_dir},
+ [SMB2_CLOSE_HE] = { .proc = smb2_close},
+ [SMB2_ECHO_HE] = { .proc = smb2_echo},
+ [SMB2_SET_INFO_HE] = { .proc = smb2_set_info},
+ [SMB2_READ_HE] = { .proc = smb2_read},
+ [SMB2_WRITE_HE] = { .proc = smb2_write},
+ [SMB2_FLUSH_HE] = { .proc = smb2_flush},
+ [SMB2_CANCEL_HE] = { .proc = smb2_cancel},
+ [SMB2_LOCK_HE] = { .proc = smb2_lock},
+ [SMB2_IOCTL_HE] = { .proc = smb2_ioctl},
+ [SMB2_OPLOCK_BREAK_HE] = { .proc = smb2_oplock_break},
+ [SMB2_CHANGE_NOTIFY_HE] = { .proc = smb2_notify},
+};
+
+/**
+ * init_smb2_1_server() - initialize a smb server connection with smb2.1
+ * command dispatcher
+ * @conn: connection instance
+ */
+void init_smb2_1_server(struct ksmbd_conn *conn)
+{
+ conn->vals = &smb21_server_values;
+ conn->ops = &smb2_0_server_ops;
+ conn->cmds = smb2_0_server_cmds;
+ conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
+ conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256_LE;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
+}
+
+/**
+ * init_smb3_0_server() - initialize a smb server connection with smb3.0
+ * command dispatcher
+ * @conn: connection instance
+ */
+void init_smb3_0_server(struct ksmbd_conn *conn)
+{
+ conn->vals = &smb30_server_values;
+ conn->ops = &smb3_0_server_ops;
+ conn->cmds = smb2_0_server_cmds;
+ conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
+ conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
+ conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
+}
+
+/**
+ * init_smb3_02_server() - initialize a smb server connection with smb3.02
+ * command dispatcher
+ * @conn: connection instance
+ */
+void init_smb3_02_server(struct ksmbd_conn *conn)
+{
+ conn->vals = &smb302_server_values;
+ conn->ops = &smb3_0_server_ops;
+ conn->cmds = smb2_0_server_cmds;
+ conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
+ conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
+ conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
+}
+
+/**
+ * init_smb3_11_server() - initialize a smb server connection with smb3.11
+ * command dispatcher
+ * @conn: connection instance
+ */
+int init_smb3_11_server(struct ksmbd_conn *conn)
+{
+ conn->vals = &smb311_server_values;
+ conn->ops = &smb3_11_server_ops;
+ conn->cmds = smb2_0_server_cmds;
+ conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
+ conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
+
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
+
+ INIT_LIST_HEAD(&conn->preauth_sess_table);
+ return 0;
+}
+
+void init_smb2_max_read_size(unsigned int sz)
+{
+ sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE);
+ smb21_server_values.max_read_size = sz;
+ smb30_server_values.max_read_size = sz;
+ smb302_server_values.max_read_size = sz;
+ smb311_server_values.max_read_size = sz;
+}
+
+void init_smb2_max_write_size(unsigned int sz)
+{
+ sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE);
+ smb21_server_values.max_write_size = sz;
+ smb30_server_values.max_write_size = sz;
+ smb302_server_values.max_write_size = sz;
+ smb311_server_values.max_write_size = sz;
+}
+
+void init_smb2_max_trans_size(unsigned int sz)
+{
+ sz = clamp_val(sz, SMB3_MIN_IOSIZE, SMB3_MAX_IOSIZE);
+ smb21_server_values.max_trans_size = sz;
+ smb30_server_values.max_trans_size = sz;
+ smb302_server_values.max_trans_size = sz;
+ smb311_server_values.max_trans_size = sz;
+}
+
+void init_smb2_max_credits(unsigned int sz)
+{
+ smb21_server_values.max_credits = sz;
+ smb30_server_values.max_credits = sz;
+ smb302_server_values.max_credits = sz;
+ smb311_server_values.max_credits = sz;
+}
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
new file mode 100644
index 000000000000..2b7c0ba6a77d
--- /dev/null
+++ b/fs/smb/server/smb2pdu.c
@@ -0,0 +1,8727 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/inetdevice.h>
+#include <net/addrconf.h>
+#include <linux/syscalls.h>
+#include <linux/namei.h>
+#include <linux/statfs.h>
+#include <linux/ethtool.h>
+#include <linux/falloc.h>
+#include <linux/mount.h>
+
+#include "glob.h"
+#include "smbfsctl.h"
+#include "oplock.h"
+#include "smbacl.h"
+
+#include "auth.h"
+#include "asn1.h"
+#include "connection.h"
+#include "transport_ipc.h"
+#include "transport_rdma.h"
+#include "vfs.h"
+#include "vfs_cache.h"
+#include "misc.h"
+
+#include "server.h"
+#include "smb_common.h"
+#include "smbstatus.h"
+#include "ksmbd_work.h"
+#include "mgmt/user_config.h"
+#include "mgmt/share_config.h"
+#include "mgmt/tree_connect.h"
+#include "mgmt/user_session.h"
+#include "mgmt/ksmbd_ida.h"
+#include "ndr.h"
+
+static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
+{
+ if (work->next_smb2_rcv_hdr_off) {
+ *req = ksmbd_req_buf_next(work);
+ *rsp = ksmbd_resp_buf_next(work);
+ } else {
+ *req = smb2_get_msg(work->request_buf);
+ *rsp = smb2_get_msg(work->response_buf);
+ }
+}
+
+#define WORK_BUFFERS(w, rq, rs) __wbuf((w), (void **)&(rq), (void **)&(rs))
+
+/**
+ * check_session_id() - check for valid session id in smb header
+ * @conn: connection instance
+ * @id: session id from smb header
+ *
+ * Return: 1 if valid session id, otherwise 0
+ */
+static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
+{
+ struct ksmbd_session *sess;
+
+ if (id == 0 || id == -1)
+ return false;
+
+ sess = ksmbd_session_lookup_all(conn, id);
+ if (sess)
+ return true;
+ pr_err("Invalid user session id: %llu\n", id);
+ return false;
+}
+
+struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn *conn)
+{
+ return xa_load(&sess->ksmbd_chann_list, (long)conn);
+}
+
+/**
+ * smb2_get_ksmbd_tcon() - get tree connection information using a tree id.
+ * @work: smb work
+ *
+ * Return: 0 if there is a tree connection matched or these are
+ * skipable commands, otherwise error
+ */
+int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
+{
+ struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+ unsigned int cmd = le16_to_cpu(req_hdr->Command);
+ int tree_id;
+
+ if (cmd == SMB2_TREE_CONNECT_HE ||
+ cmd == SMB2_CANCEL_HE ||
+ cmd == SMB2_LOGOFF_HE) {
+ ksmbd_debug(SMB, "skip to check tree connect request\n");
+ return 0;
+ }
+
+ if (xa_empty(&work->sess->tree_conns)) {
+ ksmbd_debug(SMB, "NO tree connected\n");
+ return -ENOENT;
+ }
+
+ tree_id = le32_to_cpu(req_hdr->Id.SyncId.TreeId);
+
+ /*
+ * If request is not the first in Compound request,
+ * Just validate tree id in header with work->tcon->id.
+ */
+ if (work->next_smb2_rcv_hdr_off) {
+ if (!work->tcon) {
+ pr_err("The first operation in the compound does not have tcon\n");
+ return -EINVAL;
+ }
+ if (work->tcon->id != tree_id) {
+ pr_err("tree id(%u) is different with id(%u) in first operation\n",
+ tree_id, work->tcon->id);
+ return -EINVAL;
+ }
+ return 1;
+ }
+
+ work->tcon = ksmbd_tree_conn_lookup(work->sess, tree_id);
+ if (!work->tcon) {
+ pr_err("Invalid tid %d\n", tree_id);
+ return -ENOENT;
+ }
+
+ return 1;
+}
+
+/**
+ * smb2_set_err_rsp() - set error response code on smb response
+ * @work: smb work containing response buffer
+ */
+void smb2_set_err_rsp(struct ksmbd_work *work)
+{
+ struct smb2_err_rsp *err_rsp;
+
+ if (work->next_smb2_rcv_hdr_off)
+ err_rsp = ksmbd_resp_buf_next(work);
+ else
+ err_rsp = smb2_get_msg(work->response_buf);
+
+ if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) {
+ err_rsp->StructureSize = SMB2_ERROR_STRUCTURE_SIZE2_LE;
+ err_rsp->ErrorContextCount = 0;
+ err_rsp->Reserved = 0;
+ err_rsp->ByteCount = 0;
+ err_rsp->ErrorData[0] = 0;
+ inc_rfc1001_len(work->response_buf, SMB2_ERROR_STRUCTURE_SIZE2);
+ }
+}
+
+/**
+ * is_smb2_neg_cmd() - is it smb2 negotiation command
+ * @work: smb work containing smb header
+ *
+ * Return: true if smb2 negotiation command, otherwise false
+ */
+bool is_smb2_neg_cmd(struct ksmbd_work *work)
+{
+ struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
+
+ /* is it SMB2 header ? */
+ if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
+ return false;
+
+ /* make sure it is request not response message */
+ if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
+ return false;
+
+ if (hdr->Command != SMB2_NEGOTIATE)
+ return false;
+
+ return true;
+}
+
+/**
+ * is_smb2_rsp() - is it smb2 response
+ * @work: smb work containing smb response buffer
+ *
+ * Return: true if smb2 response, otherwise false
+ */
+bool is_smb2_rsp(struct ksmbd_work *work)
+{
+ struct smb2_hdr *hdr = smb2_get_msg(work->response_buf);
+
+ /* is it SMB2 header ? */
+ if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
+ return false;
+
+ /* make sure it is response not request message */
+ if (!(hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR))
+ return false;
+
+ return true;
+}
+
+/**
+ * get_smb2_cmd_val() - get smb command code from smb header
+ * @work: smb work containing smb request buffer
+ *
+ * Return: smb2 request command value
+ */
+u16 get_smb2_cmd_val(struct ksmbd_work *work)
+{
+ struct smb2_hdr *rcv_hdr;
+
+ if (work->next_smb2_rcv_hdr_off)
+ rcv_hdr = ksmbd_req_buf_next(work);
+ else
+ rcv_hdr = smb2_get_msg(work->request_buf);
+ return le16_to_cpu(rcv_hdr->Command);
+}
+
+/**
+ * set_smb2_rsp_status() - set error response code on smb2 header
+ * @work: smb work containing response buffer
+ * @err: error response code
+ */
+void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
+{
+ struct smb2_hdr *rsp_hdr;
+
+ if (work->next_smb2_rcv_hdr_off)
+ rsp_hdr = ksmbd_resp_buf_next(work);
+ else
+ rsp_hdr = smb2_get_msg(work->response_buf);
+ rsp_hdr->Status = err;
+ smb2_set_err_rsp(work);
+}
+
+/**
+ * init_smb2_neg_rsp() - initialize smb2 response for negotiate command
+ * @work: smb work containing smb request buffer
+ *
+ * smb2 negotiate response is sent in reply of smb1 negotiate command for
+ * dialect auto-negotiation.
+ */
+int init_smb2_neg_rsp(struct ksmbd_work *work)
+{
+ struct smb2_hdr *rsp_hdr;
+ struct smb2_negotiate_rsp *rsp;
+ struct ksmbd_conn *conn = work->conn;
+
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(conn->vals->header_size);
+
+ rsp_hdr = smb2_get_msg(work->response_buf);
+ memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
+ rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
+ rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
+ rsp_hdr->CreditRequest = cpu_to_le16(2);
+ rsp_hdr->Command = SMB2_NEGOTIATE;
+ rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
+ rsp_hdr->NextCommand = 0;
+ rsp_hdr->MessageId = 0;
+ rsp_hdr->Id.SyncId.ProcessId = 0;
+ rsp_hdr->Id.SyncId.TreeId = 0;
+ rsp_hdr->SessionId = 0;
+ memset(rsp_hdr->Signature, 0, 16);
+
+ rsp = smb2_get_msg(work->response_buf);
+
+ WARN_ON(ksmbd_conn_good(conn));
+
+ rsp->StructureSize = cpu_to_le16(65);
+ ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
+ rsp->DialectRevision = cpu_to_le16(conn->dialect);
+ /* Not setting conn guid rsp->ServerGUID, as it
+ * not used by client for identifying connection
+ */
+ rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
+ /* Default Max Message Size till SMB2.0, 64K*/
+ rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size);
+ rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size);
+ rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size);
+
+ rsp->SystemTime = cpu_to_le64(ksmbd_systime());
+ rsp->ServerStartTime = 0;
+
+ rsp->SecurityBufferOffset = cpu_to_le16(128);
+ rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
+ ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
+ le16_to_cpu(rsp->SecurityBufferOffset));
+ inc_rfc1001_len(work->response_buf,
+ sizeof(struct smb2_negotiate_rsp) -
+ sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
+ AUTH_GSS_LENGTH);
+ rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
+ if (server_conf.signing == KSMBD_CONFIG_OPT_MANDATORY)
+ rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
+ conn->use_spnego = true;
+
+ ksmbd_conn_set_need_negotiate(conn);
+ return 0;
+}
+
+/**
+ * smb2_set_rsp_credits() - set number of credits in response buffer
+ * @work: smb work containing smb response buffer
+ */
+int smb2_set_rsp_credits(struct ksmbd_work *work)
+{
+ struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
+ struct smb2_hdr *hdr = ksmbd_resp_buf_next(work);
+ struct ksmbd_conn *conn = work->conn;
+ unsigned short credits_requested, aux_max;
+ unsigned short credit_charge, credits_granted = 0;
+
+ if (work->send_no_response)
+ return 0;
+
+ hdr->CreditCharge = req_hdr->CreditCharge;
+
+ if (conn->total_credits > conn->vals->max_credits) {
+ hdr->CreditRequest = 0;
+ pr_err("Total credits overflow: %d\n", conn->total_credits);
+ return -EINVAL;
+ }
+
+ credit_charge = max_t(unsigned short,
+ le16_to_cpu(req_hdr->CreditCharge), 1);
+ if (credit_charge > conn->total_credits) {
+ ksmbd_debug(SMB, "Insufficient credits granted, given: %u, granted: %u\n",
+ credit_charge, conn->total_credits);
+ return -EINVAL;
+ }
+
+ conn->total_credits -= credit_charge;
+ conn->outstanding_credits -= credit_charge;
+ credits_requested = max_t(unsigned short,
+ le16_to_cpu(req_hdr->CreditRequest), 1);
+
+ /* according to smb2.credits smbtorture, Windows server
+ * 2016 or later grant up to 8192 credits at once.
+ *
+ * TODO: Need to adjuct CreditRequest value according to
+ * current cpu load
+ */
+ if (hdr->Command == SMB2_NEGOTIATE)
+ aux_max = 1;
+ else
+ aux_max = conn->vals->max_credits - conn->total_credits;
+ credits_granted = min_t(unsigned short, credits_requested, aux_max);
+
+ conn->total_credits += credits_granted;
+ work->credits_granted += credits_granted;
+
+ if (!req_hdr->NextCommand) {
+ /* Update CreditRequest in last request */
+ hdr->CreditRequest = cpu_to_le16(work->credits_granted);
+ }
+ ksmbd_debug(SMB,
+ "credits: requested[%d] granted[%d] total_granted[%d]\n",
+ credits_requested, credits_granted,
+ conn->total_credits);
+ return 0;
+}
+
+/**
+ * init_chained_smb2_rsp() - initialize smb2 chained response
+ * @work: smb work containing smb response buffer
+ */
+static void init_chained_smb2_rsp(struct ksmbd_work *work)
+{
+ struct smb2_hdr *req = ksmbd_req_buf_next(work);
+ struct smb2_hdr *rsp = ksmbd_resp_buf_next(work);
+ struct smb2_hdr *rsp_hdr;
+ struct smb2_hdr *rcv_hdr;
+ int next_hdr_offset = 0;
+ int len, new_len;
+
+ /* Len of this response = updated RFC len - offset of previous cmd
+ * in the compound rsp
+ */
+
+ /* Storing the current local FID which may be needed by subsequent
+ * command in the compound request
+ */
+ if (req->Command == SMB2_CREATE && rsp->Status == STATUS_SUCCESS) {
+ work->compound_fid = ((struct smb2_create_rsp *)rsp)->VolatileFileId;
+ work->compound_pfid = ((struct smb2_create_rsp *)rsp)->PersistentFileId;
+ work->compound_sid = le64_to_cpu(rsp->SessionId);
+ }
+
+ len = get_rfc1002_len(work->response_buf) - work->next_smb2_rsp_hdr_off;
+ next_hdr_offset = le32_to_cpu(req->NextCommand);
+
+ new_len = ALIGN(len, 8);
+ inc_rfc1001_len(work->response_buf,
+ sizeof(struct smb2_hdr) + new_len - len);
+ rsp->NextCommand = cpu_to_le32(new_len);
+
+ work->next_smb2_rcv_hdr_off += next_hdr_offset;
+ work->next_smb2_rsp_hdr_off += new_len;
+ ksmbd_debug(SMB,
+ "Compound req new_len = %d rcv off = %d rsp off = %d\n",
+ new_len, work->next_smb2_rcv_hdr_off,
+ work->next_smb2_rsp_hdr_off);
+
+ rsp_hdr = ksmbd_resp_buf_next(work);
+ rcv_hdr = ksmbd_req_buf_next(work);
+
+ if (!(rcv_hdr->Flags & SMB2_FLAGS_RELATED_OPERATIONS)) {
+ ksmbd_debug(SMB, "related flag should be set\n");
+ work->compound_fid = KSMBD_NO_FID;
+ work->compound_pfid = KSMBD_NO_FID;
+ }
+ memset((char *)rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
+ rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
+ rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
+ rsp_hdr->Command = rcv_hdr->Command;
+
+ /*
+ * Message is response. We don't grant oplock yet.
+ */
+ rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR |
+ SMB2_FLAGS_RELATED_OPERATIONS);
+ rsp_hdr->NextCommand = 0;
+ rsp_hdr->MessageId = rcv_hdr->MessageId;
+ rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId;
+ rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId;
+ rsp_hdr->SessionId = rcv_hdr->SessionId;
+ memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
+}
+
+/**
+ * is_chained_smb2_message() - check for chained command
+ * @work: smb work containing smb request buffer
+ *
+ * Return: true if chained request, otherwise false
+ */
+bool is_chained_smb2_message(struct ksmbd_work *work)
+{
+ struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
+ unsigned int len, next_cmd;
+
+ if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
+ return false;
+
+ hdr = ksmbd_req_buf_next(work);
+ next_cmd = le32_to_cpu(hdr->NextCommand);
+ if (next_cmd > 0) {
+ if ((u64)work->next_smb2_rcv_hdr_off + next_cmd +
+ __SMB2_HEADER_STRUCTURE_SIZE >
+ get_rfc1002_len(work->request_buf)) {
+ pr_err("next command(%u) offset exceeds smb msg size\n",
+ next_cmd);
+ return false;
+ }
+
+ if ((u64)get_rfc1002_len(work->response_buf) + MAX_CIFS_SMALL_BUFFER_SIZE >
+ work->response_sz) {
+ pr_err("next response offset exceeds response buffer size\n");
+ return false;
+ }
+
+ ksmbd_debug(SMB, "got SMB2 chained command\n");
+ init_chained_smb2_rsp(work);
+ return true;
+ } else if (work->next_smb2_rcv_hdr_off) {
+ /*
+ * This is last request in chained command,
+ * align response to 8 byte
+ */
+ len = ALIGN(get_rfc1002_len(work->response_buf), 8);
+ len = len - get_rfc1002_len(work->response_buf);
+ if (len) {
+ ksmbd_debug(SMB, "padding len %u\n", len);
+ inc_rfc1001_len(work->response_buf, len);
+ if (work->aux_payload_sz)
+ work->aux_payload_sz += len;
+ }
+ }
+ return false;
+}
+
+/**
+ * init_smb2_rsp_hdr() - initialize smb2 response
+ * @work: smb work containing smb request buffer
+ *
+ * Return: 0
+ */
+int init_smb2_rsp_hdr(struct ksmbd_work *work)
+{
+ struct smb2_hdr *rsp_hdr = smb2_get_msg(work->response_buf);
+ struct smb2_hdr *rcv_hdr = smb2_get_msg(work->request_buf);
+ struct ksmbd_conn *conn = work->conn;
+
+ memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(conn->vals->header_size);
+ rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
+ rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
+ rsp_hdr->Command = rcv_hdr->Command;
+
+ /*
+ * Message is response. We don't grant oplock yet.
+ */
+ rsp_hdr->Flags = (SMB2_FLAGS_SERVER_TO_REDIR);
+ rsp_hdr->NextCommand = 0;
+ rsp_hdr->MessageId = rcv_hdr->MessageId;
+ rsp_hdr->Id.SyncId.ProcessId = rcv_hdr->Id.SyncId.ProcessId;
+ rsp_hdr->Id.SyncId.TreeId = rcv_hdr->Id.SyncId.TreeId;
+ rsp_hdr->SessionId = rcv_hdr->SessionId;
+ memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
+
+ work->syncronous = true;
+ if (work->async_id) {
+ ksmbd_release_id(&conn->async_ida, work->async_id);
+ work->async_id = 0;
+ }
+
+ return 0;
+}
+
+/**
+ * smb2_allocate_rsp_buf() - allocate smb2 response buffer
+ * @work: smb work containing smb request buffer
+ *
+ * Return: 0 on success, otherwise -ENOMEM
+ */
+int smb2_allocate_rsp_buf(struct ksmbd_work *work)
+{
+ struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
+ size_t small_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
+ size_t large_sz = small_sz + work->conn->vals->max_trans_size;
+ size_t sz = small_sz;
+ int cmd = le16_to_cpu(hdr->Command);
+
+ if (cmd == SMB2_IOCTL_HE || cmd == SMB2_QUERY_DIRECTORY_HE)
+ sz = large_sz;
+
+ if (cmd == SMB2_QUERY_INFO_HE) {
+ struct smb2_query_info_req *req;
+
+ req = smb2_get_msg(work->request_buf);
+ if ((req->InfoType == SMB2_O_INFO_FILE &&
+ (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
+ req->FileInfoClass == FILE_ALL_INFORMATION)) ||
+ req->InfoType == SMB2_O_INFO_SECURITY)
+ sz = large_sz;
+ }
+
+ /* allocate large response buf for chained commands */
+ if (le32_to_cpu(hdr->NextCommand) > 0)
+ sz = large_sz;
+
+ work->response_buf = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
+ if (!work->response_buf)
+ return -ENOMEM;
+
+ work->response_sz = sz;
+ return 0;
+}
+
+/**
+ * smb2_check_user_session() - check for valid session for a user
+ * @work: smb work containing smb request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_check_user_session(struct ksmbd_work *work)
+{
+ struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+ struct ksmbd_conn *conn = work->conn;
+ unsigned int cmd = conn->ops->get_cmd_val(work);
+ unsigned long long sess_id;
+
+ /*
+ * SMB2_ECHO, SMB2_NEGOTIATE, SMB2_SESSION_SETUP command do not
+ * require a session id, so no need to validate user session's for
+ * these commands.
+ */
+ if (cmd == SMB2_ECHO_HE || cmd == SMB2_NEGOTIATE_HE ||
+ cmd == SMB2_SESSION_SETUP_HE)
+ return 0;
+
+ if (!ksmbd_conn_good(conn))
+ return -EIO;
+
+ sess_id = le64_to_cpu(req_hdr->SessionId);
+
+ /*
+ * If request is not the first in Compound request,
+ * Just validate session id in header with work->sess->id.
+ */
+ if (work->next_smb2_rcv_hdr_off) {
+ if (!work->sess) {
+ pr_err("The first operation in the compound does not have sess\n");
+ return -EINVAL;
+ }
+ if (work->sess->id != sess_id) {
+ pr_err("session id(%llu) is different with the first operation(%lld)\n",
+ sess_id, work->sess->id);
+ return -EINVAL;
+ }
+ return 1;
+ }
+
+ /* Check for validity of user session */
+ work->sess = ksmbd_session_lookup_all(conn, sess_id);
+ if (work->sess)
+ return 1;
+ ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
+ return -ENOENT;
+}
+
+static void destroy_previous_session(struct ksmbd_conn *conn,
+ struct ksmbd_user *user, u64 id)
+{
+ struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id);
+ struct ksmbd_user *prev_user;
+ struct channel *chann;
+ long index;
+
+ if (!prev_sess)
+ return;
+
+ prev_user = prev_sess->user;
+
+ if (!prev_user ||
+ strcmp(user->name, prev_user->name) ||
+ user->passkey_sz != prev_user->passkey_sz ||
+ memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
+ return;
+
+ prev_sess->state = SMB2_SESSION_EXPIRED;
+ xa_for_each(&prev_sess->ksmbd_chann_list, index, chann)
+ ksmbd_conn_set_exiting(chann->conn);
+}
+
+/**
+ * smb2_get_name() - get filename string from on the wire smb format
+ * @src: source buffer
+ * @maxlen: maxlen of source string
+ * @local_nls: nls_table pointer
+ *
+ * Return: matching converted filename on success, otherwise error ptr
+ */
+static char *
+smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls)
+{
+ char *name;
+
+ name = smb_strndup_from_utf16(src, maxlen, 1, local_nls);
+ if (IS_ERR(name)) {
+ pr_err("failed to get name %ld\n", PTR_ERR(name));
+ return name;
+ }
+
+ ksmbd_conv_path_to_unix(name);
+ ksmbd_strip_last_slash(name);
+ return name;
+}
+
+int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
+{
+ struct smb2_hdr *rsp_hdr;
+ struct ksmbd_conn *conn = work->conn;
+ int id;
+
+ rsp_hdr = smb2_get_msg(work->response_buf);
+ rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
+
+ id = ksmbd_acquire_async_msg_id(&conn->async_ida);
+ if (id < 0) {
+ pr_err("Failed to alloc async message id\n");
+ return id;
+ }
+ work->syncronous = false;
+ work->async_id = id;
+ rsp_hdr->Id.AsyncId = cpu_to_le64(id);
+
+ ksmbd_debug(SMB,
+ "Send interim Response to inform async request id : %d\n",
+ work->async_id);
+
+ work->cancel_fn = fn;
+ work->cancel_argv = arg;
+
+ if (list_empty(&work->async_request_entry)) {
+ spin_lock(&conn->request_lock);
+ list_add_tail(&work->async_request_entry, &conn->async_requests);
+ spin_unlock(&conn->request_lock);
+ }
+
+ return 0;
+}
+
+void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
+{
+ struct smb2_hdr *rsp_hdr;
+
+ rsp_hdr = smb2_get_msg(work->response_buf);
+ smb2_set_err_rsp(work);
+ rsp_hdr->Status = status;
+
+ work->multiRsp = 1;
+ ksmbd_conn_write(work);
+ rsp_hdr->Status = 0;
+ work->multiRsp = 0;
+}
+
+static __le32 smb2_get_reparse_tag_special_file(umode_t mode)
+{
+ if (S_ISDIR(mode) || S_ISREG(mode))
+ return 0;
+
+ if (S_ISLNK(mode))
+ return IO_REPARSE_TAG_LX_SYMLINK_LE;
+ else if (S_ISFIFO(mode))
+ return IO_REPARSE_TAG_LX_FIFO_LE;
+ else if (S_ISSOCK(mode))
+ return IO_REPARSE_TAG_AF_UNIX_LE;
+ else if (S_ISCHR(mode))
+ return IO_REPARSE_TAG_LX_CHR_LE;
+ else if (S_ISBLK(mode))
+ return IO_REPARSE_TAG_LX_BLK_LE;
+
+ return 0;
+}
+
+/**
+ * smb2_get_dos_mode() - get file mode in dos format from unix mode
+ * @stat: kstat containing file mode
+ * @attribute: attribute flags
+ *
+ * Return: converted dos mode
+ */
+static int smb2_get_dos_mode(struct kstat *stat, int attribute)
+{
+ int attr = 0;
+
+ if (S_ISDIR(stat->mode)) {
+ attr = FILE_ATTRIBUTE_DIRECTORY |
+ (attribute & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM));
+ } else {
+ attr = (attribute & 0x00005137) | FILE_ATTRIBUTE_ARCHIVE;
+ attr &= ~(FILE_ATTRIBUTE_DIRECTORY);
+ if (S_ISREG(stat->mode) && (server_conf.share_fake_fscaps &
+ FILE_SUPPORTS_SPARSE_FILES))
+ attr |= FILE_ATTRIBUTE_SPARSE_FILE;
+
+ if (smb2_get_reparse_tag_special_file(stat->mode))
+ attr |= FILE_ATTRIBUTE_REPARSE_POINT;
+ }
+
+ return attr;
+}
+
+static void build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt,
+ __le16 hash_id)
+{
+ pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES;
+ pneg_ctxt->DataLength = cpu_to_le16(38);
+ pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1);
+ pneg_ctxt->Reserved = cpu_to_le32(0);
+ pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE);
+ get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE);
+ pneg_ctxt->HashAlgorithms = hash_id;
+}
+
+static void build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt,
+ __le16 cipher_type)
+{
+ pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES;
+ pneg_ctxt->DataLength = cpu_to_le16(4);
+ pneg_ctxt->Reserved = cpu_to_le32(0);
+ pneg_ctxt->CipherCount = cpu_to_le16(1);
+ pneg_ctxt->Ciphers[0] = cipher_type;
+}
+
+static void build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt,
+ __le16 comp_algo)
+{
+ pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES;
+ pneg_ctxt->DataLength =
+ cpu_to_le16(sizeof(struct smb2_compression_capabilities_context)
+ - sizeof(struct smb2_neg_context));
+ pneg_ctxt->Reserved = cpu_to_le32(0);
+ pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(1);
+ pneg_ctxt->Flags = cpu_to_le32(0);
+ pneg_ctxt->CompressionAlgorithms[0] = comp_algo;
+}
+
+static void build_sign_cap_ctxt(struct smb2_signing_capabilities *pneg_ctxt,
+ __le16 sign_algo)
+{
+ pneg_ctxt->ContextType = SMB2_SIGNING_CAPABILITIES;
+ pneg_ctxt->DataLength =
+ cpu_to_le16((sizeof(struct smb2_signing_capabilities) + 2)
+ - sizeof(struct smb2_neg_context));
+ pneg_ctxt->Reserved = cpu_to_le32(0);
+ pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(1);
+ pneg_ctxt->SigningAlgorithms[0] = sign_algo;
+}
+
+static void build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
+{
+ pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE;
+ pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
+ /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */
+ pneg_ctxt->Name[0] = 0x93;
+ pneg_ctxt->Name[1] = 0xAD;
+ pneg_ctxt->Name[2] = 0x25;
+ pneg_ctxt->Name[3] = 0x50;
+ pneg_ctxt->Name[4] = 0x9C;
+ pneg_ctxt->Name[5] = 0xB4;
+ pneg_ctxt->Name[6] = 0x11;
+ pneg_ctxt->Name[7] = 0xE7;
+ pneg_ctxt->Name[8] = 0xB4;
+ pneg_ctxt->Name[9] = 0x23;
+ pneg_ctxt->Name[10] = 0x83;
+ pneg_ctxt->Name[11] = 0xDE;
+ pneg_ctxt->Name[12] = 0x96;
+ pneg_ctxt->Name[13] = 0x8B;
+ pneg_ctxt->Name[14] = 0xCD;
+ pneg_ctxt->Name[15] = 0x7C;
+}
+
+static void assemble_neg_contexts(struct ksmbd_conn *conn,
+ struct smb2_negotiate_rsp *rsp,
+ void *smb2_buf_len)
+{
+ char *pneg_ctxt = (char *)rsp +
+ le32_to_cpu(rsp->NegotiateContextOffset);
+ int neg_ctxt_cnt = 1;
+ int ctxt_size;
+
+ ksmbd_debug(SMB,
+ "assemble SMB2_PREAUTH_INTEGRITY_CAPABILITIES context\n");
+ build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt,
+ conn->preauth_info->Preauth_HashId);
+ rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt);
+ inc_rfc1001_len(smb2_buf_len, AUTH_GSS_PADDING);
+ ctxt_size = sizeof(struct smb2_preauth_neg_context);
+ /* Round to 8 byte boundary */
+ pneg_ctxt += round_up(sizeof(struct smb2_preauth_neg_context), 8);
+
+ if (conn->cipher_type) {
+ ctxt_size = round_up(ctxt_size, 8);
+ ksmbd_debug(SMB,
+ "assemble SMB2_ENCRYPTION_CAPABILITIES context\n");
+ build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt,
+ conn->cipher_type);
+ rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
+ ctxt_size += sizeof(struct smb2_encryption_neg_context) + 2;
+ /* Round to 8 byte boundary */
+ pneg_ctxt +=
+ round_up(sizeof(struct smb2_encryption_neg_context) + 2,
+ 8);
+ }
+
+ if (conn->compress_algorithm) {
+ ctxt_size = round_up(ctxt_size, 8);
+ ksmbd_debug(SMB,
+ "assemble SMB2_COMPRESSION_CAPABILITIES context\n");
+ /* Temporarily set to SMB3_COMPRESS_NONE */
+ build_compression_ctxt((struct smb2_compression_capabilities_context *)pneg_ctxt,
+ conn->compress_algorithm);
+ rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
+ ctxt_size += sizeof(struct smb2_compression_capabilities_context) + 2;
+ /* Round to 8 byte boundary */
+ pneg_ctxt += round_up(sizeof(struct smb2_compression_capabilities_context) + 2,
+ 8);
+ }
+
+ if (conn->posix_ext_supported) {
+ ctxt_size = round_up(ctxt_size, 8);
+ ksmbd_debug(SMB,
+ "assemble SMB2_POSIX_EXTENSIONS_AVAILABLE context\n");
+ build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
+ rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
+ ctxt_size += sizeof(struct smb2_posix_neg_context);
+ /* Round to 8 byte boundary */
+ pneg_ctxt += round_up(sizeof(struct smb2_posix_neg_context), 8);
+ }
+
+ if (conn->signing_negotiated) {
+ ctxt_size = round_up(ctxt_size, 8);
+ ksmbd_debug(SMB,
+ "assemble SMB2_SIGNING_CAPABILITIES context\n");
+ build_sign_cap_ctxt((struct smb2_signing_capabilities *)pneg_ctxt,
+ conn->signing_algorithm);
+ rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
+ ctxt_size += sizeof(struct smb2_signing_capabilities) + 2;
+ }
+
+ inc_rfc1001_len(smb2_buf_len, ctxt_size);
+}
+
+static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
+ struct smb2_preauth_neg_context *pneg_ctxt,
+ int ctxt_len)
+{
+ /*
+ * sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt,
+ * which may not be present. Only check for used HashAlgorithms[1].
+ */
+ if (ctxt_len <
+ sizeof(struct smb2_neg_context) + MIN_PREAUTH_CTXT_DATA_LEN)
+ return STATUS_INVALID_PARAMETER;
+
+ if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
+ return STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP;
+
+ conn->preauth_info->Preauth_HashId = SMB2_PREAUTH_INTEGRITY_SHA512;
+ return STATUS_SUCCESS;
+}
+
+static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
+ struct smb2_encryption_neg_context *pneg_ctxt,
+ int ctxt_len)
+{
+ int cph_cnt;
+ int i, cphs_size;
+
+ if (sizeof(struct smb2_encryption_neg_context) > ctxt_len) {
+ pr_err("Invalid SMB2_ENCRYPTION_CAPABILITIES context size\n");
+ return;
+ }
+
+ conn->cipher_type = 0;
+
+ cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
+ cphs_size = cph_cnt * sizeof(__le16);
+
+ if (sizeof(struct smb2_encryption_neg_context) + cphs_size >
+ ctxt_len) {
+ pr_err("Invalid cipher count(%d)\n", cph_cnt);
+ return;
+ }
+
+ if (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION))
+ return;
+
+ for (i = 0; i < cph_cnt; i++) {
+ if (pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_GCM ||
+ pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_CCM ||
+ pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_CCM ||
+ pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES256_GCM) {
+ ksmbd_debug(SMB, "Cipher ID = 0x%x\n",
+ pneg_ctxt->Ciphers[i]);
+ conn->cipher_type = pneg_ctxt->Ciphers[i];
+ break;
+ }
+ }
+}
+
+/**
+ * smb3_encryption_negotiated() - checks if server and client agreed on enabling encryption
+ * @conn: smb connection
+ *
+ * Return: true if connection should be encrypted, else false
+ */
+bool smb3_encryption_negotiated(struct ksmbd_conn *conn)
+{
+ if (!conn->ops->generate_encryptionkey)
+ return false;
+
+ /*
+ * SMB 3.0 and 3.0.2 dialects use the SMB2_GLOBAL_CAP_ENCRYPTION flag.
+ * SMB 3.1.1 uses the cipher_type field.
+ */
+ return (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) ||
+ conn->cipher_type;
+}
+
+static void decode_compress_ctxt(struct ksmbd_conn *conn,
+ struct smb2_compression_capabilities_context *pneg_ctxt)
+{
+ conn->compress_algorithm = SMB3_COMPRESS_NONE;
+}
+
+static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
+ struct smb2_signing_capabilities *pneg_ctxt,
+ int ctxt_len)
+{
+ int sign_algo_cnt;
+ int i, sign_alos_size;
+
+ if (sizeof(struct smb2_signing_capabilities) > ctxt_len) {
+ pr_err("Invalid SMB2_SIGNING_CAPABILITIES context length\n");
+ return;
+ }
+
+ conn->signing_negotiated = false;
+ sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
+ sign_alos_size = sign_algo_cnt * sizeof(__le16);
+
+ if (sizeof(struct smb2_signing_capabilities) + sign_alos_size >
+ ctxt_len) {
+ pr_err("Invalid signing algorithm count(%d)\n", sign_algo_cnt);
+ return;
+ }
+
+ for (i = 0; i < sign_algo_cnt; i++) {
+ if (pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_HMAC_SHA256_LE ||
+ pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_AES_CMAC_LE) {
+ ksmbd_debug(SMB, "Signing Algorithm ID = 0x%x\n",
+ pneg_ctxt->SigningAlgorithms[i]);
+ conn->signing_negotiated = true;
+ conn->signing_algorithm =
+ pneg_ctxt->SigningAlgorithms[i];
+ break;
+ }
+ }
+}
+
+static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
+ struct smb2_negotiate_req *req,
+ unsigned int len_of_smb)
+{
+ /* +4 is to account for the RFC1001 len field */
+ struct smb2_neg_context *pctx = (struct smb2_neg_context *)req;
+ int i = 0, len_of_ctxts;
+ unsigned int offset = le32_to_cpu(req->NegotiateContextOffset);
+ unsigned int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
+ __le32 status = STATUS_INVALID_PARAMETER;
+
+ ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);
+ if (len_of_smb <= offset) {
+ ksmbd_debug(SMB, "Invalid response: negotiate context offset\n");
+ return status;
+ }
+
+ len_of_ctxts = len_of_smb - offset;
+
+ while (i++ < neg_ctxt_cnt) {
+ int clen, ctxt_len;
+
+ if (len_of_ctxts < (int)sizeof(struct smb2_neg_context))
+ break;
+
+ pctx = (struct smb2_neg_context *)((char *)pctx + offset);
+ clen = le16_to_cpu(pctx->DataLength);
+ ctxt_len = clen + sizeof(struct smb2_neg_context);
+
+ if (ctxt_len > len_of_ctxts)
+ break;
+
+ if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
+ ksmbd_debug(SMB,
+ "deassemble SMB2_PREAUTH_INTEGRITY_CAPABILITIES context\n");
+ if (conn->preauth_info->Preauth_HashId)
+ break;
+
+ status = decode_preauth_ctxt(conn,
+ (struct smb2_preauth_neg_context *)pctx,
+ ctxt_len);
+ if (status != STATUS_SUCCESS)
+ break;
+ } else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
+ ksmbd_debug(SMB,
+ "deassemble SMB2_ENCRYPTION_CAPABILITIES context\n");
+ if (conn->cipher_type)
+ break;
+
+ decode_encrypt_ctxt(conn,
+ (struct smb2_encryption_neg_context *)pctx,
+ ctxt_len);
+ } else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) {
+ ksmbd_debug(SMB,
+ "deassemble SMB2_COMPRESSION_CAPABILITIES context\n");
+ if (conn->compress_algorithm)
+ break;
+
+ decode_compress_ctxt(conn,
+ (struct smb2_compression_capabilities_context *)pctx);
+ } else if (pctx->ContextType == SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) {
+ ksmbd_debug(SMB,
+ "deassemble SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context\n");
+ } else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) {
+ ksmbd_debug(SMB,
+ "deassemble SMB2_POSIX_EXTENSIONS_AVAILABLE context\n");
+ conn->posix_ext_supported = true;
+ } else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) {
+ ksmbd_debug(SMB,
+ "deassemble SMB2_SIGNING_CAPABILITIES context\n");
+
+ decode_sign_cap_ctxt(conn,
+ (struct smb2_signing_capabilities *)pctx,
+ ctxt_len);
+ }
+
+ /* offsets must be 8 byte aligned */
+ offset = (ctxt_len + 7) & ~0x7;
+ len_of_ctxts -= offset;
+ }
+ return status;
+}
+
+/**
+ * smb2_handle_negotiate() - handler for smb2 negotiate command
+ * @work: smb work containing smb request buffer
+ *
+ * Return: 0
+ */
+int smb2_handle_negotiate(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_negotiate_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_negotiate_rsp *rsp = smb2_get_msg(work->response_buf);
+ int rc = 0;
+ unsigned int smb2_buf_len, smb2_neg_size;
+ __le32 status;
+
+ ksmbd_debug(SMB, "Received negotiate request\n");
+ conn->need_neg = false;
+ if (ksmbd_conn_good(conn)) {
+ pr_err("conn->tcp_status is already in CifsGood State\n");
+ work->send_no_response = 1;
+ return rc;
+ }
+
+ smb2_buf_len = get_rfc1002_len(work->request_buf);
+ smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects);
+ if (smb2_neg_size > smb2_buf_len) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ rc = -EINVAL;
+ goto err_out;
+ }
+
+ if (req->DialectCount == 0) {
+ pr_err("malformed packet\n");
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ rc = -EINVAL;
+ goto err_out;
+ }
+
+ if (conn->dialect == SMB311_PROT_ID) {
+ unsigned int nego_ctxt_off = le32_to_cpu(req->NegotiateContextOffset);
+
+ if (smb2_buf_len < nego_ctxt_off) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ rc = -EINVAL;
+ goto err_out;
+ }
+
+ if (smb2_neg_size > nego_ctxt_off) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ rc = -EINVAL;
+ goto err_out;
+ }
+
+ if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) >
+ nego_ctxt_off) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ rc = -EINVAL;
+ goto err_out;
+ }
+ } else {
+ if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) >
+ smb2_buf_len) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ rc = -EINVAL;
+ goto err_out;
+ }
+ }
+
+ conn->cli_cap = le32_to_cpu(req->Capabilities);
+ switch (conn->dialect) {
+ case SMB311_PROT_ID:
+ conn->preauth_info =
+ kzalloc(sizeof(struct preauth_integrity_info),
+ GFP_KERNEL);
+ if (!conn->preauth_info) {
+ rc = -ENOMEM;
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ goto err_out;
+ }
+
+ status = deassemble_neg_contexts(conn, req,
+ get_rfc1002_len(work->request_buf));
+ if (status != STATUS_SUCCESS) {
+ pr_err("deassemble_neg_contexts error(0x%x)\n",
+ status);
+ rsp->hdr.Status = status;
+ rc = -EINVAL;
+ kfree(conn->preauth_info);
+ conn->preauth_info = NULL;
+ goto err_out;
+ }
+
+ rc = init_smb3_11_server(conn);
+ if (rc < 0) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ kfree(conn->preauth_info);
+ conn->preauth_info = NULL;
+ goto err_out;
+ }
+
+ ksmbd_gen_preauth_integrity_hash(conn,
+ work->request_buf,
+ conn->preauth_info->Preauth_HashValue);
+ rsp->NegotiateContextOffset =
+ cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
+ assemble_neg_contexts(conn, rsp, work->response_buf);
+ break;
+ case SMB302_PROT_ID:
+ init_smb3_02_server(conn);
+ break;
+ case SMB30_PROT_ID:
+ init_smb3_0_server(conn);
+ break;
+ case SMB21_PROT_ID:
+ init_smb2_1_server(conn);
+ break;
+ case SMB2X_PROT_ID:
+ case BAD_PROT_ID:
+ default:
+ ksmbd_debug(SMB, "Server dialect :0x%x not supported\n",
+ conn->dialect);
+ rsp->hdr.Status = STATUS_NOT_SUPPORTED;
+ rc = -EINVAL;
+ goto err_out;
+ }
+ rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
+
+ /* For stats */
+ conn->connection_type = conn->dialect;
+
+ rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size);
+ rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size);
+ rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size);
+
+ memcpy(conn->ClientGUID, req->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE);
+ conn->cli_sec_mode = le16_to_cpu(req->SecurityMode);
+
+ rsp->StructureSize = cpu_to_le16(65);
+ rsp->DialectRevision = cpu_to_le16(conn->dialect);
+ /* Not setting conn guid rsp->ServerGUID, as it
+ * not used by client for identifying server
+ */
+ memset(rsp->ServerGUID, 0, SMB2_CLIENT_GUID_SIZE);
+
+ rsp->SystemTime = cpu_to_le64(ksmbd_systime());
+ rsp->ServerStartTime = 0;
+ ksmbd_debug(SMB, "negotiate context offset %d, count %d\n",
+ le32_to_cpu(rsp->NegotiateContextOffset),
+ le16_to_cpu(rsp->NegotiateContextCount));
+
+ rsp->SecurityBufferOffset = cpu_to_le16(128);
+ rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
+ ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
+ le16_to_cpu(rsp->SecurityBufferOffset));
+ inc_rfc1001_len(work->response_buf, sizeof(struct smb2_negotiate_rsp) -
+ sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
+ AUTH_GSS_LENGTH);
+ rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
+ conn->use_spnego = true;
+
+ if ((server_conf.signing == KSMBD_CONFIG_OPT_AUTO ||
+ server_conf.signing == KSMBD_CONFIG_OPT_DISABLED) &&
+ req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED_LE)
+ conn->sign = true;
+ else if (server_conf.signing == KSMBD_CONFIG_OPT_MANDATORY) {
+ server_conf.enforced_signing = true;
+ rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
+ conn->sign = true;
+ }
+
+ conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode);
+ ksmbd_conn_set_need_negotiate(conn);
+
+err_out:
+ if (rc < 0)
+ smb2_set_err_rsp(work);
+
+ return rc;
+}
+
+static int alloc_preauth_hash(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn)
+{
+ if (sess->Preauth_HashValue)
+ return 0;
+
+ sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue,
+ PREAUTH_HASHVALUE_SIZE, GFP_KERNEL);
+ if (!sess->Preauth_HashValue)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int generate_preauth_hash(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_session *sess = work->sess;
+ u8 *preauth_hash;
+
+ if (conn->dialect != SMB311_PROT_ID)
+ return 0;
+
+ if (conn->binding) {
+ struct preauth_session *preauth_sess;
+
+ preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
+ if (!preauth_sess) {
+ preauth_sess = ksmbd_preauth_session_alloc(conn, sess->id);
+ if (!preauth_sess)
+ return -ENOMEM;
+ }
+
+ preauth_hash = preauth_sess->Preauth_HashValue;
+ } else {
+ if (!sess->Preauth_HashValue)
+ if (alloc_preauth_hash(sess, conn))
+ return -ENOMEM;
+ preauth_hash = sess->Preauth_HashValue;
+ }
+
+ ksmbd_gen_preauth_integrity_hash(conn, work->request_buf, preauth_hash);
+ return 0;
+}
+
+static int decode_negotiation_token(struct ksmbd_conn *conn,
+ struct negotiate_message *negblob,
+ size_t sz)
+{
+ if (!conn->use_spnego)
+ return -EINVAL;
+
+ if (ksmbd_decode_negTokenInit((char *)negblob, sz, conn)) {
+ if (ksmbd_decode_negTokenTarg((char *)negblob, sz, conn)) {
+ conn->auth_mechs |= KSMBD_AUTH_NTLMSSP;
+ conn->preferred_auth_mech = KSMBD_AUTH_NTLMSSP;
+ conn->use_spnego = false;
+ }
+ }
+ return 0;
+}
+
+static int ntlm_negotiate(struct ksmbd_work *work,
+ struct negotiate_message *negblob,
+ size_t negblob_len)
+{
+ struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct challenge_message *chgblob;
+ unsigned char *spnego_blob = NULL;
+ u16 spnego_blob_len;
+ char *neg_blob;
+ int sz, rc;
+
+ ksmbd_debug(SMB, "negotiate phase\n");
+ rc = ksmbd_decode_ntlmssp_neg_blob(negblob, negblob_len, work->conn);
+ if (rc)
+ return rc;
+
+ sz = le16_to_cpu(rsp->SecurityBufferOffset);
+ chgblob =
+ (struct challenge_message *)((char *)&rsp->hdr.ProtocolId + sz);
+ memset(chgblob, 0, sizeof(struct challenge_message));
+
+ if (!work->conn->use_spnego) {
+ sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn);
+ if (sz < 0)
+ return -ENOMEM;
+
+ rsp->SecurityBufferLength = cpu_to_le16(sz);
+ return 0;
+ }
+
+ sz = sizeof(struct challenge_message);
+ sz += (strlen(ksmbd_netbios_name()) * 2 + 1 + 4) * 6;
+
+ neg_blob = kzalloc(sz, GFP_KERNEL);
+ if (!neg_blob)
+ return -ENOMEM;
+
+ chgblob = (struct challenge_message *)neg_blob;
+ sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn);
+ if (sz < 0) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ rc = build_spnego_ntlmssp_neg_blob(&spnego_blob, &spnego_blob_len,
+ neg_blob, sz);
+ if (rc) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ sz = le16_to_cpu(rsp->SecurityBufferOffset);
+ memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
+ rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
+
+out:
+ kfree(spnego_blob);
+ kfree(neg_blob);
+ return rc;
+}
+
+static struct authenticate_message *user_authblob(struct ksmbd_conn *conn,
+ struct smb2_sess_setup_req *req)
+{
+ int sz;
+
+ if (conn->use_spnego && conn->mechToken)
+ return (struct authenticate_message *)conn->mechToken;
+
+ sz = le16_to_cpu(req->SecurityBufferOffset);
+ return (struct authenticate_message *)((char *)&req->hdr.ProtocolId
+ + sz);
+}
+
+static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
+ struct smb2_sess_setup_req *req)
+{
+ struct authenticate_message *authblob;
+ struct ksmbd_user *user;
+ char *name;
+ unsigned int name_off, name_len, secbuf_len;
+
+ secbuf_len = le16_to_cpu(req->SecurityBufferLength);
+ if (secbuf_len < sizeof(struct authenticate_message)) {
+ ksmbd_debug(SMB, "blob len %d too small\n", secbuf_len);
+ return NULL;
+ }
+ authblob = user_authblob(conn, req);
+ name_off = le32_to_cpu(authblob->UserName.BufferOffset);
+ name_len = le16_to_cpu(authblob->UserName.Length);
+
+ if (secbuf_len < (u64)name_off + name_len)
+ return NULL;
+
+ name = smb_strndup_from_utf16((const char *)authblob + name_off,
+ name_len,
+ true,
+ conn->local_nls);
+ if (IS_ERR(name)) {
+ pr_err("cannot allocate memory\n");
+ return NULL;
+ }
+
+ ksmbd_debug(SMB, "session setup request for user %s\n", name);
+ user = ksmbd_login_user(name);
+ kfree(name);
+ return user;
+}
+
+static int ntlm_authenticate(struct ksmbd_work *work)
+{
+ struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_session *sess = work->sess;
+ struct channel *chann = NULL;
+ struct ksmbd_user *user;
+ u64 prev_id;
+ int sz, rc;
+
+ ksmbd_debug(SMB, "authenticate phase\n");
+ if (conn->use_spnego) {
+ unsigned char *spnego_blob;
+ u16 spnego_blob_len;
+
+ rc = build_spnego_ntlmssp_auth_blob(&spnego_blob,
+ &spnego_blob_len,
+ 0);
+ if (rc)
+ return -ENOMEM;
+
+ sz = le16_to_cpu(rsp->SecurityBufferOffset);
+ memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
+ rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
+ kfree(spnego_blob);
+ inc_rfc1001_len(work->response_buf, spnego_blob_len - 1);
+ }
+
+ user = session_user(conn, req);
+ if (!user) {
+ ksmbd_debug(SMB, "Unknown user name or an error\n");
+ return -EPERM;
+ }
+
+ /* Check for previous session */
+ prev_id = le64_to_cpu(req->PreviousSessionId);
+ if (prev_id && prev_id != sess->id)
+ destroy_previous_session(conn, user, prev_id);
+
+ if (sess->state == SMB2_SESSION_VALID) {
+ /*
+ * Reuse session if anonymous try to connect
+ * on reauthetication.
+ */
+ if (conn->binding == false && ksmbd_anonymous_user(user)) {
+ ksmbd_free_user(user);
+ return 0;
+ }
+
+ if (!ksmbd_compare_user(sess->user, user)) {
+ ksmbd_free_user(user);
+ return -EPERM;
+ }
+ ksmbd_free_user(user);
+ } else {
+ sess->user = user;
+ }
+
+ if (conn->binding == false && user_guest(sess->user)) {
+ rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE;
+ } else {
+ struct authenticate_message *authblob;
+
+ authblob = user_authblob(conn, req);
+ sz = le16_to_cpu(req->SecurityBufferLength);
+ rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, conn, sess);
+ if (rc) {
+ set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD);
+ ksmbd_debug(SMB, "authentication failed\n");
+ return -EPERM;
+ }
+ }
+
+ /*
+ * If session state is SMB2_SESSION_VALID, We can assume
+ * that it is reauthentication. And the user/password
+ * has been verified, so return it here.
+ */
+ if (sess->state == SMB2_SESSION_VALID) {
+ if (conn->binding)
+ goto binding_session;
+ return 0;
+ }
+
+ if ((rsp->SessionFlags != SMB2_SESSION_FLAG_IS_GUEST_LE &&
+ (conn->sign || server_conf.enforced_signing)) ||
+ (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
+ sess->sign = true;
+
+ if (smb3_encryption_negotiated(conn) &&
+ !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
+ rc = conn->ops->generate_encryptionkey(conn, sess);
+ if (rc) {
+ ksmbd_debug(SMB,
+ "SMB3 encryption key generation failed\n");
+ return -EINVAL;
+ }
+ sess->enc = true;
+ rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
+ /*
+ * signing is disable if encryption is enable
+ * on this session
+ */
+ sess->sign = false;
+ }
+
+binding_session:
+ if (conn->dialect >= SMB30_PROT_ID) {
+ chann = lookup_chann_list(sess, conn);
+ if (!chann) {
+ chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
+ if (!chann)
+ return -ENOMEM;
+
+ chann->conn = conn;
+ xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
+ }
+ }
+
+ if (conn->ops->generate_signingkey) {
+ rc = conn->ops->generate_signingkey(sess, conn);
+ if (rc) {
+ ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (!ksmbd_conn_lookup_dialect(conn)) {
+ pr_err("fail to verify the dialect\n");
+ return -ENOENT;
+ }
+ return 0;
+}
+
+#ifdef CONFIG_SMB_SERVER_KERBEROS5
+static int krb5_authenticate(struct ksmbd_work *work)
+{
+ struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_session *sess = work->sess;
+ char *in_blob, *out_blob;
+ struct channel *chann = NULL;
+ u64 prev_sess_id;
+ int in_len, out_len;
+ int retval;
+
+ in_blob = (char *)&req->hdr.ProtocolId +
+ le16_to_cpu(req->SecurityBufferOffset);
+ in_len = le16_to_cpu(req->SecurityBufferLength);
+ out_blob = (char *)&rsp->hdr.ProtocolId +
+ le16_to_cpu(rsp->SecurityBufferOffset);
+ out_len = work->response_sz -
+ (le16_to_cpu(rsp->SecurityBufferOffset) + 4);
+
+ /* Check previous session */
+ prev_sess_id = le64_to_cpu(req->PreviousSessionId);
+ if (prev_sess_id && prev_sess_id != sess->id)
+ destroy_previous_session(conn, sess->user, prev_sess_id);
+
+ if (sess->state == SMB2_SESSION_VALID)
+ ksmbd_free_user(sess->user);
+
+ retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
+ out_blob, &out_len);
+ if (retval) {
+ ksmbd_debug(SMB, "krb5 authentication failed\n");
+ return -EINVAL;
+ }
+ rsp->SecurityBufferLength = cpu_to_le16(out_len);
+ inc_rfc1001_len(work->response_buf, out_len - 1);
+
+ if ((conn->sign || server_conf.enforced_signing) ||
+ (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
+ sess->sign = true;
+
+ if (smb3_encryption_negotiated(conn)) {
+ retval = conn->ops->generate_encryptionkey(conn, sess);
+ if (retval) {
+ ksmbd_debug(SMB,
+ "SMB3 encryption key generation failed\n");
+ return -EINVAL;
+ }
+ sess->enc = true;
+ rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
+ sess->sign = false;
+ }
+
+ if (conn->dialect >= SMB30_PROT_ID) {
+ chann = lookup_chann_list(sess, conn);
+ if (!chann) {
+ chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
+ if (!chann)
+ return -ENOMEM;
+
+ chann->conn = conn;
+ xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
+ }
+ }
+
+ if (conn->ops->generate_signingkey) {
+ retval = conn->ops->generate_signingkey(sess, conn);
+ if (retval) {
+ ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
+ return -EINVAL;
+ }
+ }
+
+ if (!ksmbd_conn_lookup_dialect(conn)) {
+ pr_err("fail to verify the dialect\n");
+ return -ENOENT;
+ }
+ return 0;
+}
+#else
+static int krb5_authenticate(struct ksmbd_work *work)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
+int smb2_sess_setup(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct ksmbd_session *sess;
+ struct negotiate_message *negblob;
+ unsigned int negblob_len, negblob_off;
+ int rc = 0;
+
+ ksmbd_debug(SMB, "Received request for session setup\n");
+
+ rsp->StructureSize = cpu_to_le16(9);
+ rsp->SessionFlags = 0;
+ rsp->SecurityBufferOffset = cpu_to_le16(72);
+ rsp->SecurityBufferLength = 0;
+ inc_rfc1001_len(work->response_buf, 9);
+
+ ksmbd_conn_lock(conn);
+ if (!req->hdr.SessionId) {
+ sess = ksmbd_smb2_session_create();
+ if (!sess) {
+ rc = -ENOMEM;
+ goto out_err;
+ }
+ rsp->hdr.SessionId = cpu_to_le64(sess->id);
+ rc = ksmbd_session_register(conn, sess);
+ if (rc)
+ goto out_err;
+ } else if (conn->dialect >= SMB30_PROT_ID &&
+ (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
+ req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) {
+ u64 sess_id = le64_to_cpu(req->hdr.SessionId);
+
+ sess = ksmbd_session_lookup_slowpath(sess_id);
+ if (!sess) {
+ rc = -ENOENT;
+ goto out_err;
+ }
+
+ if (conn->dialect != sess->dialect) {
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ if (strncmp(conn->ClientGUID, sess->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE)) {
+ rc = -ENOENT;
+ goto out_err;
+ }
+
+ if (sess->state == SMB2_SESSION_IN_PROGRESS) {
+ rc = -EACCES;
+ goto out_err;
+ }
+
+ if (sess->state == SMB2_SESSION_EXPIRED) {
+ rc = -EFAULT;
+ goto out_err;
+ }
+
+ if (ksmbd_conn_need_reconnect(conn)) {
+ rc = -EFAULT;
+ sess = NULL;
+ goto out_err;
+ }
+
+ if (ksmbd_session_lookup(conn, sess_id)) {
+ rc = -EACCES;
+ goto out_err;
+ }
+
+ if (user_guest(sess->user)) {
+ rc = -EOPNOTSUPP;
+ goto out_err;
+ }
+
+ conn->binding = true;
+ } else if ((conn->dialect < SMB30_PROT_ID ||
+ server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
+ (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
+ sess = NULL;
+ rc = -EACCES;
+ goto out_err;
+ } else {
+ sess = ksmbd_session_lookup(conn,
+ le64_to_cpu(req->hdr.SessionId));
+ if (!sess) {
+ rc = -ENOENT;
+ goto out_err;
+ }
+
+ if (sess->state == SMB2_SESSION_EXPIRED) {
+ rc = -EFAULT;
+ goto out_err;
+ }
+
+ if (ksmbd_conn_need_reconnect(conn)) {
+ rc = -EFAULT;
+ sess = NULL;
+ goto out_err;
+ }
+ }
+ work->sess = sess;
+
+ negblob_off = le16_to_cpu(req->SecurityBufferOffset);
+ negblob_len = le16_to_cpu(req->SecurityBufferLength);
+ if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer) ||
+ negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) {
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ negblob = (struct negotiate_message *)((char *)&req->hdr.ProtocolId +
+ negblob_off);
+
+ if (decode_negotiation_token(conn, negblob, negblob_len) == 0) {
+ if (conn->mechToken)
+ negblob = (struct negotiate_message *)conn->mechToken;
+ }
+
+ if (server_conf.auth_mechs & conn->auth_mechs) {
+ rc = generate_preauth_hash(work);
+ if (rc)
+ goto out_err;
+
+ if (conn->preferred_auth_mech &
+ (KSMBD_AUTH_KRB5 | KSMBD_AUTH_MSKRB5)) {
+ rc = krb5_authenticate(work);
+ if (rc) {
+ rc = -EINVAL;
+ goto out_err;
+ }
+
+ if (!ksmbd_conn_need_reconnect(conn)) {
+ ksmbd_conn_set_good(conn);
+ sess->state = SMB2_SESSION_VALID;
+ }
+ kfree(sess->Preauth_HashValue);
+ sess->Preauth_HashValue = NULL;
+ } else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
+ if (negblob->MessageType == NtLmNegotiate) {
+ rc = ntlm_negotiate(work, negblob, negblob_len);
+ if (rc)
+ goto out_err;
+ rsp->hdr.Status =
+ STATUS_MORE_PROCESSING_REQUIRED;
+ /*
+ * Note: here total size -1 is done as an
+ * adjustment for 0 size blob
+ */
+ inc_rfc1001_len(work->response_buf,
+ le16_to_cpu(rsp->SecurityBufferLength) - 1);
+
+ } else if (negblob->MessageType == NtLmAuthenticate) {
+ rc = ntlm_authenticate(work);
+ if (rc)
+ goto out_err;
+
+ if (!ksmbd_conn_need_reconnect(conn)) {
+ ksmbd_conn_set_good(conn);
+ sess->state = SMB2_SESSION_VALID;
+ }
+ if (conn->binding) {
+ struct preauth_session *preauth_sess;
+
+ preauth_sess =
+ ksmbd_preauth_session_lookup(conn, sess->id);
+ if (preauth_sess) {
+ list_del(&preauth_sess->preauth_entry);
+ kfree(preauth_sess);
+ }
+ }
+ kfree(sess->Preauth_HashValue);
+ sess->Preauth_HashValue = NULL;
+ } else {
+ pr_info_ratelimited("Unknown NTLMSSP message type : 0x%x\n",
+ le32_to_cpu(negblob->MessageType));
+ rc = -EINVAL;
+ }
+ } else {
+ /* TODO: need one more negotiation */
+ pr_err("Not support the preferred authentication\n");
+ rc = -EINVAL;
+ }
+ } else {
+ pr_err("Not support authentication\n");
+ rc = -EINVAL;
+ }
+
+out_err:
+ if (rc == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else if (rc == -ENOENT)
+ rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
+ else if (rc == -EACCES)
+ rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED;
+ else if (rc == -EFAULT)
+ rsp->hdr.Status = STATUS_NETWORK_SESSION_EXPIRED;
+ else if (rc == -ENOMEM)
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
+ else if (rc == -EOPNOTSUPP)
+ rsp->hdr.Status = STATUS_NOT_SUPPORTED;
+ else if (rc)
+ rsp->hdr.Status = STATUS_LOGON_FAILURE;
+
+ if (conn->use_spnego && conn->mechToken) {
+ kfree(conn->mechToken);
+ conn->mechToken = NULL;
+ }
+
+ if (rc < 0) {
+ /*
+ * SecurityBufferOffset should be set to zero
+ * in session setup error response.
+ */
+ rsp->SecurityBufferOffset = 0;
+
+ if (sess) {
+ bool try_delay = false;
+
+ /*
+ * To avoid dictionary attacks (repeated session setups rapidly sent) to
+ * connect to server, ksmbd make a delay of a 5 seconds on session setup
+ * failure to make it harder to send enough random connection requests
+ * to break into a server.
+ */
+ if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION)
+ try_delay = true;
+
+ sess->last_active = jiffies;
+ sess->state = SMB2_SESSION_EXPIRED;
+ if (try_delay) {
+ ksmbd_conn_set_need_reconnect(conn);
+ ssleep(5);
+ ksmbd_conn_set_need_negotiate(conn);
+ }
+ }
+ }
+
+ ksmbd_conn_unlock(conn);
+ return rc;
+}
+
+/**
+ * smb2_tree_connect() - handler for smb2 tree connect command
+ * @work: smb work containing smb request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_tree_connect(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_tree_connect_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_tree_connect_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct ksmbd_session *sess = work->sess;
+ char *treename = NULL, *name = NULL;
+ struct ksmbd_tree_conn_status status;
+ struct ksmbd_share_config *share;
+ int rc = -EINVAL;
+
+ treename = smb_strndup_from_utf16(req->Buffer,
+ le16_to_cpu(req->PathLength), true,
+ conn->local_nls);
+ if (IS_ERR(treename)) {
+ pr_err("treename is NULL\n");
+ status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
+ goto out_err1;
+ }
+
+ name = ksmbd_extract_sharename(conn->um, treename);
+ if (IS_ERR(name)) {
+ status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
+ goto out_err1;
+ }
+
+ ksmbd_debug(SMB, "tree connect request for tree %s treename %s\n",
+ name, treename);
+
+ status = ksmbd_tree_conn_connect(conn, sess, name);
+ if (status.ret == KSMBD_TREE_CONN_STATUS_OK)
+ rsp->hdr.Id.SyncId.TreeId = cpu_to_le32(status.tree_conn->id);
+ else
+ goto out_err1;
+
+ share = status.tree_conn->share_conf;
+ if (test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
+ ksmbd_debug(SMB, "IPC share path request\n");
+ rsp->ShareType = SMB2_SHARE_TYPE_PIPE;
+ rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE |
+ FILE_EXECUTE_LE | FILE_READ_ATTRIBUTES_LE |
+ FILE_DELETE_LE | FILE_READ_CONTROL_LE |
+ FILE_WRITE_DAC_LE | FILE_WRITE_OWNER_LE |
+ FILE_SYNCHRONIZE_LE;
+ } else {
+ rsp->ShareType = SMB2_SHARE_TYPE_DISK;
+ rsp->MaximalAccess = FILE_READ_DATA_LE | FILE_READ_EA_LE |
+ FILE_EXECUTE_LE | FILE_READ_ATTRIBUTES_LE;
+ if (test_tree_conn_flag(status.tree_conn,
+ KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+ rsp->MaximalAccess |= FILE_WRITE_DATA_LE |
+ FILE_APPEND_DATA_LE | FILE_WRITE_EA_LE |
+ FILE_DELETE_LE | FILE_WRITE_ATTRIBUTES_LE |
+ FILE_DELETE_CHILD_LE | FILE_READ_CONTROL_LE |
+ FILE_WRITE_DAC_LE | FILE_WRITE_OWNER_LE |
+ FILE_SYNCHRONIZE_LE;
+ }
+ }
+
+ status.tree_conn->maximal_access = le32_to_cpu(rsp->MaximalAccess);
+ if (conn->posix_ext_supported)
+ status.tree_conn->posix_extensions = true;
+
+ rsp->StructureSize = cpu_to_le16(16);
+ inc_rfc1001_len(work->response_buf, 16);
+out_err1:
+ rsp->Capabilities = 0;
+ rsp->Reserved = 0;
+ /* default manual caching */
+ rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
+
+ if (!IS_ERR(treename))
+ kfree(treename);
+ if (!IS_ERR(name))
+ kfree(name);
+
+ switch (status.ret) {
+ case KSMBD_TREE_CONN_STATUS_OK:
+ rsp->hdr.Status = STATUS_SUCCESS;
+ rc = 0;
+ break;
+ case -ESTALE:
+ case -ENOENT:
+ case KSMBD_TREE_CONN_STATUS_NO_SHARE:
+ rsp->hdr.Status = STATUS_BAD_NETWORK_NAME;
+ break;
+ case -ENOMEM:
+ case KSMBD_TREE_CONN_STATUS_NOMEM:
+ rsp->hdr.Status = STATUS_NO_MEMORY;
+ break;
+ case KSMBD_TREE_CONN_STATUS_ERROR:
+ case KSMBD_TREE_CONN_STATUS_TOO_MANY_CONNS:
+ case KSMBD_TREE_CONN_STATUS_TOO_MANY_SESSIONS:
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ break;
+ case -EINVAL:
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ break;
+ default:
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ }
+
+ if (status.ret != KSMBD_TREE_CONN_STATUS_OK)
+ smb2_set_err_rsp(work);
+
+ return rc;
+}
+
+/**
+ * smb2_create_open_flags() - convert smb open flags to unix open flags
+ * @file_present: is file already present
+ * @access: file access flags
+ * @disposition: file disposition flags
+ * @may_flags: set with MAY_ flags
+ *
+ * Return: file open flags
+ */
+static int smb2_create_open_flags(bool file_present, __le32 access,
+ __le32 disposition,
+ int *may_flags)
+{
+ int oflags = O_NONBLOCK | O_LARGEFILE;
+
+ if (access & FILE_READ_DESIRED_ACCESS_LE &&
+ access & FILE_WRITE_DESIRE_ACCESS_LE) {
+ oflags |= O_RDWR;
+ *may_flags = MAY_OPEN | MAY_READ | MAY_WRITE;
+ } else if (access & FILE_WRITE_DESIRE_ACCESS_LE) {
+ oflags |= O_WRONLY;
+ *may_flags = MAY_OPEN | MAY_WRITE;
+ } else {
+ oflags |= O_RDONLY;
+ *may_flags = MAY_OPEN | MAY_READ;
+ }
+
+ if (access == FILE_READ_ATTRIBUTES_LE)
+ oflags |= O_PATH;
+
+ if (file_present) {
+ switch (disposition & FILE_CREATE_MASK_LE) {
+ case FILE_OPEN_LE:
+ case FILE_CREATE_LE:
+ break;
+ case FILE_SUPERSEDE_LE:
+ case FILE_OVERWRITE_LE:
+ case FILE_OVERWRITE_IF_LE:
+ oflags |= O_TRUNC;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (disposition & FILE_CREATE_MASK_LE) {
+ case FILE_SUPERSEDE_LE:
+ case FILE_CREATE_LE:
+ case FILE_OPEN_IF_LE:
+ case FILE_OVERWRITE_IF_LE:
+ oflags |= O_CREAT;
+ break;
+ case FILE_OPEN_LE:
+ case FILE_OVERWRITE_LE:
+ oflags &= ~O_CREAT;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return oflags;
+}
+
+/**
+ * smb2_tree_disconnect() - handler for smb tree connect request
+ * @work: smb work containing request buffer
+ *
+ * Return: 0
+ */
+int smb2_tree_disconnect(struct ksmbd_work *work)
+{
+ struct smb2_tree_disconnect_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct ksmbd_session *sess = work->sess;
+ struct ksmbd_tree_connect *tcon = work->tcon;
+
+ rsp->StructureSize = cpu_to_le16(4);
+ inc_rfc1001_len(work->response_buf, 4);
+
+ ksmbd_debug(SMB, "request\n");
+
+ if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) {
+ struct smb2_tree_disconnect_req *req =
+ smb2_get_msg(work->request_buf);
+
+ ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
+
+ rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
+ smb2_set_err_rsp(work);
+ return 0;
+ }
+
+ ksmbd_close_tree_conn_fds(work);
+ ksmbd_tree_conn_disconnect(sess, tcon);
+ work->tcon = NULL;
+ return 0;
+}
+
+/**
+ * smb2_session_logoff() - handler for session log off request
+ * @work: smb work containing request buffer
+ *
+ * Return: 0
+ */
+int smb2_session_logoff(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_logoff_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct ksmbd_session *sess;
+ struct smb2_logoff_req *req = smb2_get_msg(work->request_buf);
+ u64 sess_id = le64_to_cpu(req->hdr.SessionId);
+
+ rsp->StructureSize = cpu_to_le16(4);
+ inc_rfc1001_len(work->response_buf, 4);
+
+ ksmbd_debug(SMB, "request\n");
+
+ ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_RECONNECT);
+ ksmbd_close_session_fds(work);
+ ksmbd_conn_wait_idle(conn, sess_id);
+
+ /*
+ * Re-lookup session to validate if session is deleted
+ * while waiting request complete
+ */
+ sess = ksmbd_session_lookup_all(conn, sess_id);
+ if (ksmbd_tree_conn_session_logoff(sess)) {
+ ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
+ rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
+ smb2_set_err_rsp(work);
+ return 0;
+ }
+
+ ksmbd_destroy_file_table(&sess->file_table);
+ sess->state = SMB2_SESSION_EXPIRED;
+
+ ksmbd_free_user(sess->user);
+ sess->user = NULL;
+ ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE);
+ return 0;
+}
+
+/**
+ * create_smb2_pipe() - create IPC pipe
+ * @work: smb work containing request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+static noinline int create_smb2_pipe(struct ksmbd_work *work)
+{
+ struct smb2_create_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_create_req *req = smb2_get_msg(work->request_buf);
+ int id;
+ int err;
+ char *name;
+
+ name = smb_strndup_from_utf16(req->Buffer, le16_to_cpu(req->NameLength),
+ 1, work->conn->local_nls);
+ if (IS_ERR(name)) {
+ rsp->hdr.Status = STATUS_NO_MEMORY;
+ err = PTR_ERR(name);
+ goto out;
+ }
+
+ id = ksmbd_session_rpc_open(work->sess, name);
+ if (id < 0) {
+ pr_err("Unable to open RPC pipe: %d\n", id);
+ err = id;
+ goto out;
+ }
+
+ rsp->hdr.Status = STATUS_SUCCESS;
+ rsp->StructureSize = cpu_to_le16(89);
+ rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE;
+ rsp->Flags = 0;
+ rsp->CreateAction = cpu_to_le32(FILE_OPENED);
+
+ rsp->CreationTime = cpu_to_le64(0);
+ rsp->LastAccessTime = cpu_to_le64(0);
+ rsp->ChangeTime = cpu_to_le64(0);
+ rsp->AllocationSize = cpu_to_le64(0);
+ rsp->EndofFile = cpu_to_le64(0);
+ rsp->FileAttributes = FILE_ATTRIBUTE_NORMAL_LE;
+ rsp->Reserved2 = 0;
+ rsp->VolatileFileId = id;
+ rsp->PersistentFileId = 0;
+ rsp->CreateContextsOffset = 0;
+ rsp->CreateContextsLength = 0;
+
+ inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
+ kfree(name);
+ return 0;
+
+out:
+ switch (err) {
+ case -EINVAL:
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ break;
+ case -ENOSPC:
+ case -ENOMEM:
+ rsp->hdr.Status = STATUS_NO_MEMORY;
+ break;
+ }
+
+ if (!IS_ERR(name))
+ kfree(name);
+
+ smb2_set_err_rsp(work);
+ return err;
+}
+
+/**
+ * smb2_set_ea() - handler for setting extended attributes using set
+ * info command
+ * @eabuf: set info command buffer
+ * @buf_len: set info command buffer length
+ * @path: dentry path for get ea
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
+ const struct path *path)
+{
+ struct user_namespace *user_ns = mnt_user_ns(path->mnt);
+ char *attr_name = NULL, *value;
+ int rc = 0;
+ unsigned int next = 0;
+
+ if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength +
+ le16_to_cpu(eabuf->EaValueLength))
+ return -EINVAL;
+
+ attr_name = kmalloc(XATTR_NAME_MAX + 1, GFP_KERNEL);
+ if (!attr_name)
+ return -ENOMEM;
+
+ do {
+ if (!eabuf->EaNameLength)
+ goto next;
+
+ ksmbd_debug(SMB,
+ "name : <%s>, name_len : %u, value_len : %u, next : %u\n",
+ eabuf->name, eabuf->EaNameLength,
+ le16_to_cpu(eabuf->EaValueLength),
+ le32_to_cpu(eabuf->NextEntryOffset));
+
+ if (eabuf->EaNameLength >
+ (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
+ rc = -EINVAL;
+ break;
+ }
+
+ memcpy(attr_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
+ memcpy(&attr_name[XATTR_USER_PREFIX_LEN], eabuf->name,
+ eabuf->EaNameLength);
+ attr_name[XATTR_USER_PREFIX_LEN + eabuf->EaNameLength] = '\0';
+ value = (char *)&eabuf->name + eabuf->EaNameLength + 1;
+
+ if (!eabuf->EaValueLength) {
+ rc = ksmbd_vfs_casexattr_len(user_ns,
+ path->dentry,
+ attr_name,
+ XATTR_USER_PREFIX_LEN +
+ eabuf->EaNameLength);
+
+ /* delete the EA only when it exits */
+ if (rc > 0) {
+ rc = ksmbd_vfs_remove_xattr(user_ns,
+ path->dentry,
+ attr_name);
+
+ if (rc < 0) {
+ ksmbd_debug(SMB,
+ "remove xattr failed(%d)\n",
+ rc);
+ break;
+ }
+ }
+
+ /* if the EA doesn't exist, just do nothing. */
+ rc = 0;
+ } else {
+ rc = ksmbd_vfs_setxattr(user_ns,
+ path->dentry, attr_name, value,
+ le16_to_cpu(eabuf->EaValueLength), 0);
+ if (rc < 0) {
+ ksmbd_debug(SMB,
+ "ksmbd_vfs_setxattr is failed(%d)\n",
+ rc);
+ break;
+ }
+ }
+
+next:
+ next = le32_to_cpu(eabuf->NextEntryOffset);
+ if (next == 0 || buf_len < next)
+ break;
+ buf_len -= next;
+ eabuf = (struct smb2_ea_info *)((char *)eabuf + next);
+ if (next < (u32)eabuf->EaNameLength + le16_to_cpu(eabuf->EaValueLength))
+ break;
+
+ } while (next != 0);
+
+ kfree(attr_name);
+ return rc;
+}
+
+static noinline int smb2_set_stream_name_xattr(const struct path *path,
+ struct ksmbd_file *fp,
+ char *stream_name, int s_type)
+{
+ struct user_namespace *user_ns = mnt_user_ns(path->mnt);
+ size_t xattr_stream_size;
+ char *xattr_stream_name;
+ int rc;
+
+ rc = ksmbd_vfs_xattr_stream_name(stream_name,
+ &xattr_stream_name,
+ &xattr_stream_size,
+ s_type);
+ if (rc)
+ return rc;
+
+ fp->stream.name = xattr_stream_name;
+ fp->stream.size = xattr_stream_size;
+
+ /* Check if there is stream prefix in xattr space */
+ rc = ksmbd_vfs_casexattr_len(user_ns,
+ path->dentry,
+ xattr_stream_name,
+ xattr_stream_size);
+ if (rc >= 0)
+ return 0;
+
+ if (fp->cdoption == FILE_OPEN_LE) {
+ ksmbd_debug(SMB, "XATTR stream name lookup failed: %d\n", rc);
+ return -EBADF;
+ }
+
+ rc = ksmbd_vfs_setxattr(user_ns, path->dentry,
+ xattr_stream_name, NULL, 0, 0);
+ if (rc < 0)
+ pr_err("Failed to store XATTR stream name :%d\n", rc);
+ return 0;
+}
+
+static int smb2_remove_smb_xattrs(const struct path *path)
+{
+ struct user_namespace *user_ns = mnt_user_ns(path->mnt);
+ char *name, *xattr_list = NULL;
+ ssize_t xattr_list_len;
+ int err = 0;
+
+ xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
+ if (xattr_list_len < 0) {
+ goto out;
+ } else if (!xattr_list_len) {
+ ksmbd_debug(SMB, "empty xattr in the file\n");
+ goto out;
+ }
+
+ for (name = xattr_list; name - xattr_list < xattr_list_len;
+ name += strlen(name) + 1) {
+ ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
+
+ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
+ !strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
+ STREAM_PREFIX_LEN)) {
+ err = ksmbd_vfs_remove_xattr(user_ns, path->dentry,
+ name);
+ if (err)
+ ksmbd_debug(SMB, "remove xattr failed : %s\n",
+ name);
+ }
+ }
+out:
+ kvfree(xattr_list);
+ return err;
+}
+
+static int smb2_create_truncate(const struct path *path)
+{
+ int rc = vfs_truncate(path, 0);
+
+ if (rc) {
+ pr_err("vfs_truncate failed, rc %d\n", rc);
+ return rc;
+ }
+
+ rc = smb2_remove_smb_xattrs(path);
+ if (rc == -EOPNOTSUPP)
+ rc = 0;
+ if (rc)
+ ksmbd_debug(SMB,
+ "ksmbd_truncate_stream_name_xattr failed, rc %d\n",
+ rc);
+ return rc;
+}
+
+static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *path,
+ struct ksmbd_file *fp)
+{
+ struct xattr_dos_attrib da = {0};
+ int rc;
+
+ if (!test_share_config_flag(tcon->share_conf,
+ KSMBD_SHARE_FLAG_STORE_DOS_ATTRS))
+ return;
+
+ da.version = 4;
+ da.attr = le32_to_cpu(fp->f_ci->m_fattr);
+ da.itime = da.create_time = fp->create_time;
+ da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
+ XATTR_DOSINFO_ITIME;
+
+ rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt),
+ path->dentry, &da);
+ if (rc)
+ ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
+}
+
+static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
+ const struct path *path, struct ksmbd_file *fp)
+{
+ struct xattr_dos_attrib da;
+ int rc;
+
+ fp->f_ci->m_fattr &= ~(FILE_ATTRIBUTE_HIDDEN_LE | FILE_ATTRIBUTE_SYSTEM_LE);
+
+ /* get FileAttributes from XATTR_NAME_DOS_ATTRIBUTE */
+ if (!test_share_config_flag(tcon->share_conf,
+ KSMBD_SHARE_FLAG_STORE_DOS_ATTRS))
+ return;
+
+ rc = ksmbd_vfs_get_dos_attrib_xattr(mnt_user_ns(path->mnt),
+ path->dentry, &da);
+ if (rc > 0) {
+ fp->f_ci->m_fattr = cpu_to_le32(da.attr);
+ fp->create_time = da.create_time;
+ fp->itime = da.itime;
+ }
+}
+
+static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
+ int open_flags, umode_t posix_mode, bool is_dir)
+{
+ struct ksmbd_tree_connect *tcon = work->tcon;
+ struct ksmbd_share_config *share = tcon->share_conf;
+ umode_t mode;
+ int rc;
+
+ if (!(open_flags & O_CREAT))
+ return -EBADF;
+
+ ksmbd_debug(SMB, "file does not exist, so creating\n");
+ if (is_dir == true) {
+ ksmbd_debug(SMB, "creating directory\n");
+
+ mode = share_config_directory_mode(share, posix_mode);
+ rc = ksmbd_vfs_mkdir(work, name, mode);
+ if (rc)
+ return rc;
+ } else {
+ ksmbd_debug(SMB, "creating regular file\n");
+
+ mode = share_config_create_mode(share, posix_mode);
+ rc = ksmbd_vfs_create(work, name, mode);
+ if (rc)
+ return rc;
+ }
+
+ rc = ksmbd_vfs_kern_path(work, name, 0, path, 0);
+ if (rc) {
+ pr_err("cannot get linux path (%s), err = %d\n",
+ name, rc);
+ return rc;
+ }
+ return 0;
+}
+
+static int smb2_create_sd_buffer(struct ksmbd_work *work,
+ struct smb2_create_req *req,
+ const struct path *path)
+{
+ struct create_context *context;
+ struct create_sd_buf_req *sd_buf;
+
+ if (!req->CreateContextsOffset)
+ return -ENOENT;
+
+ /* Parse SD BUFFER create contexts */
+ context = smb2_find_context_vals(req, SMB2_CREATE_SD_BUFFER, 4);
+ if (!context)
+ return -ENOENT;
+ else if (IS_ERR(context))
+ return PTR_ERR(context);
+
+ ksmbd_debug(SMB,
+ "Set ACLs using SMB2_CREATE_SD_BUFFER context\n");
+ sd_buf = (struct create_sd_buf_req *)context;
+ if (le16_to_cpu(context->DataOffset) +
+ le32_to_cpu(context->DataLength) <
+ sizeof(struct create_sd_buf_req))
+ return -EINVAL;
+ return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd,
+ le32_to_cpu(sd_buf->ccontext.DataLength), true);
+}
+
+static void ksmbd_acls_fattr(struct smb_fattr *fattr,
+ struct user_namespace *mnt_userns,
+ struct inode *inode)
+{
+ vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
+ vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
+
+ fattr->cf_uid = vfsuid_into_kuid(vfsuid);
+ fattr->cf_gid = vfsgid_into_kgid(vfsgid);
+ fattr->cf_mode = inode->i_mode;
+ fattr->cf_acls = NULL;
+ fattr->cf_dacls = NULL;
+
+ if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
+ fattr->cf_acls = get_acl(inode, ACL_TYPE_ACCESS);
+ if (S_ISDIR(inode->i_mode))
+ fattr->cf_dacls = get_acl(inode, ACL_TYPE_DEFAULT);
+ }
+}
+
+/**
+ * smb2_open() - handler for smb file open request
+ * @work: smb work containing request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_open(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_session *sess = work->sess;
+ struct ksmbd_tree_connect *tcon = work->tcon;
+ struct smb2_create_req *req;
+ struct smb2_create_rsp *rsp;
+ struct path path;
+ struct ksmbd_share_config *share = tcon->share_conf;
+ struct ksmbd_file *fp = NULL;
+ struct file *filp = NULL;
+ struct user_namespace *user_ns = NULL;
+ struct kstat stat;
+ struct create_context *context;
+ struct lease_ctx_info *lc = NULL;
+ struct create_ea_buf_req *ea_buf = NULL;
+ struct oplock_info *opinfo;
+ __le32 *next_ptr = NULL;
+ int req_op_level = 0, open_flags = 0, may_flags = 0, file_info = 0;
+ int rc = 0;
+ int contxt_cnt = 0, query_disk_id = 0;
+ int maximal_access_ctxt = 0, posix_ctxt = 0;
+ int s_type = 0;
+ int next_off = 0;
+ char *name = NULL;
+ char *stream_name = NULL;
+ bool file_present = false, created = false, already_permitted = false;
+ int share_ret, need_truncate = 0;
+ u64 time;
+ umode_t posix_mode = 0;
+ __le32 daccess, maximal_access = 0;
+
+ WORK_BUFFERS(work, req, rsp);
+
+ if (req->hdr.NextCommand && !work->next_smb2_rcv_hdr_off &&
+ (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)) {
+ ksmbd_debug(SMB, "invalid flag in chained command\n");
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ smb2_set_err_rsp(work);
+ return -EINVAL;
+ }
+
+ if (test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
+ ksmbd_debug(SMB, "IPC pipe create request\n");
+ return create_smb2_pipe(work);
+ }
+
+ if (req->NameLength) {
+ if ((req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
+ *(char *)req->Buffer == '\\') {
+ pr_err("not allow directory name included leading slash\n");
+ rc = -EINVAL;
+ goto err_out1;
+ }
+
+ name = smb2_get_name(req->Buffer,
+ le16_to_cpu(req->NameLength),
+ work->conn->local_nls);
+ if (IS_ERR(name)) {
+ rc = PTR_ERR(name);
+ if (rc != -ENOMEM)
+ rc = -ENOENT;
+ name = NULL;
+ goto err_out1;
+ }
+
+ ksmbd_debug(SMB, "converted name = %s\n", name);
+ if (strchr(name, ':')) {
+ if (!test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_STREAMS)) {
+ rc = -EBADF;
+ goto err_out1;
+ }
+ rc = parse_stream_name(name, &stream_name, &s_type);
+ if (rc < 0)
+ goto err_out1;
+ }
+
+ rc = ksmbd_validate_filename(name);
+ if (rc < 0)
+ goto err_out1;
+
+ if (ksmbd_share_veto_filename(share, name)) {
+ rc = -ENOENT;
+ ksmbd_debug(SMB, "Reject open(), vetoed file: %s\n",
+ name);
+ goto err_out1;
+ }
+ } else {
+ name = kstrdup("", GFP_KERNEL);
+ if (!name) {
+ rc = -ENOMEM;
+ goto err_out1;
+ }
+ }
+
+ req_op_level = req->RequestedOplockLevel;
+ if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
+ lc = parse_lease_state(req);
+
+ if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE)) {
+ pr_err("Invalid impersonationlevel : 0x%x\n",
+ le32_to_cpu(req->ImpersonationLevel));
+ rc = -EIO;
+ rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL;
+ goto err_out1;
+ }
+
+ if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK_LE)) {
+ pr_err("Invalid create options : 0x%x\n",
+ le32_to_cpu(req->CreateOptions));
+ rc = -EINVAL;
+ goto err_out1;
+ } else {
+ if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE &&
+ req->CreateOptions & FILE_RANDOM_ACCESS_LE)
+ req->CreateOptions = ~(FILE_SEQUENTIAL_ONLY_LE);
+
+ if (req->CreateOptions &
+ (FILE_OPEN_BY_FILE_ID_LE | CREATE_TREE_CONNECTION |
+ FILE_RESERVE_OPFILTER_LE)) {
+ rc = -EOPNOTSUPP;
+ goto err_out1;
+ }
+
+ if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
+ if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) {
+ rc = -EINVAL;
+ goto err_out1;
+ } else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) {
+ req->CreateOptions = ~(FILE_NO_COMPRESSION_LE);
+ }
+ }
+ }
+
+ if (le32_to_cpu(req->CreateDisposition) >
+ le32_to_cpu(FILE_OVERWRITE_IF_LE)) {
+ pr_err("Invalid create disposition : 0x%x\n",
+ le32_to_cpu(req->CreateDisposition));
+ rc = -EINVAL;
+ goto err_out1;
+ }
+
+ if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) {
+ pr_err("Invalid desired access : 0x%x\n",
+ le32_to_cpu(req->DesiredAccess));
+ rc = -EACCES;
+ goto err_out1;
+ }
+
+ if (req->FileAttributes && !(req->FileAttributes & FILE_ATTRIBUTE_MASK_LE)) {
+ pr_err("Invalid file attribute : 0x%x\n",
+ le32_to_cpu(req->FileAttributes));
+ rc = -EINVAL;
+ goto err_out1;
+ }
+
+ if (req->CreateContextsOffset) {
+ /* Parse non-durable handle create contexts */
+ context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER, 4);
+ if (IS_ERR(context)) {
+ rc = PTR_ERR(context);
+ goto err_out1;
+ } else if (context) {
+ ea_buf = (struct create_ea_buf_req *)context;
+ if (le16_to_cpu(context->DataOffset) +
+ le32_to_cpu(context->DataLength) <
+ sizeof(struct create_ea_buf_req)) {
+ rc = -EINVAL;
+ goto err_out1;
+ }
+ if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) {
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ rc = -EACCES;
+ goto err_out1;
+ }
+ }
+
+ context = smb2_find_context_vals(req,
+ SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4);
+ if (IS_ERR(context)) {
+ rc = PTR_ERR(context);
+ goto err_out1;
+ } else if (context) {
+ ksmbd_debug(SMB,
+ "get query maximal access context\n");
+ maximal_access_ctxt = 1;
+ }
+
+ context = smb2_find_context_vals(req,
+ SMB2_CREATE_TIMEWARP_REQUEST, 4);
+ if (IS_ERR(context)) {
+ rc = PTR_ERR(context);
+ goto err_out1;
+ } else if (context) {
+ ksmbd_debug(SMB, "get timewarp context\n");
+ rc = -EBADF;
+ goto err_out1;
+ }
+
+ if (tcon->posix_extensions) {
+ context = smb2_find_context_vals(req,
+ SMB2_CREATE_TAG_POSIX, 16);
+ if (IS_ERR(context)) {
+ rc = PTR_ERR(context);
+ goto err_out1;
+ } else if (context) {
+ struct create_posix *posix =
+ (struct create_posix *)context;
+ if (le16_to_cpu(context->DataOffset) +
+ le32_to_cpu(context->DataLength) <
+ sizeof(struct create_posix) - 4) {
+ rc = -EINVAL;
+ goto err_out1;
+ }
+ ksmbd_debug(SMB, "get posix context\n");
+
+ posix_mode = le32_to_cpu(posix->Mode);
+ posix_ctxt = 1;
+ }
+ }
+ }
+
+ if (ksmbd_override_fsids(work)) {
+ rc = -ENOMEM;
+ goto err_out1;
+ }
+
+ rc = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS, &path, 1);
+ if (!rc) {
+ if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) {
+ /*
+ * If file exists with under flags, return access
+ * denied error.
+ */
+ if (req->CreateDisposition == FILE_OVERWRITE_IF_LE ||
+ req->CreateDisposition == FILE_OPEN_IF_LE) {
+ rc = -EACCES;
+ path_put(&path);
+ goto err_out;
+ }
+
+ if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+ ksmbd_debug(SMB,
+ "User does not have write permission\n");
+ rc = -EACCES;
+ path_put(&path);
+ goto err_out;
+ }
+ } else if (d_is_symlink(path.dentry)) {
+ rc = -EACCES;
+ path_put(&path);
+ goto err_out;
+ }
+ }
+
+ if (rc) {
+ if (rc != -ENOENT)
+ goto err_out;
+ ksmbd_debug(SMB, "can not get linux path for %s, rc = %d\n",
+ name, rc);
+ rc = 0;
+ } else {
+ file_present = true;
+ user_ns = mnt_user_ns(path.mnt);
+ }
+ if (stream_name) {
+ if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
+ if (s_type == DATA_STREAM) {
+ rc = -EIO;
+ rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
+ }
+ } else {
+ if (file_present && S_ISDIR(d_inode(path.dentry)->i_mode) &&
+ s_type == DATA_STREAM) {
+ rc = -EIO;
+ rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
+ }
+ }
+
+ if (req->CreateOptions & FILE_DIRECTORY_FILE_LE &&
+ req->FileAttributes & FILE_ATTRIBUTE_NORMAL_LE) {
+ rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
+ rc = -EIO;
+ }
+
+ if (rc < 0)
+ goto err_out;
+ }
+
+ if (file_present && req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE &&
+ S_ISDIR(d_inode(path.dentry)->i_mode) &&
+ !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
+ ksmbd_debug(SMB, "open() argument is a directory: %s, %x\n",
+ name, req->CreateOptions);
+ rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
+ rc = -EIO;
+ goto err_out;
+ }
+
+ if (file_present && (req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
+ !(req->CreateDisposition == FILE_CREATE_LE) &&
+ !S_ISDIR(d_inode(path.dentry)->i_mode)) {
+ rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
+ rc = -EIO;
+ goto err_out;
+ }
+
+ if (!stream_name && file_present &&
+ req->CreateDisposition == FILE_CREATE_LE) {
+ rc = -EEXIST;
+ goto err_out;
+ }
+
+ daccess = smb_map_generic_desired_access(req->DesiredAccess);
+
+ if (file_present && !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
+ rc = smb_check_perm_dacl(conn, &path, &daccess,
+ sess->user->uid);
+ if (rc)
+ goto err_out;
+ }
+
+ if (daccess & FILE_MAXIMAL_ACCESS_LE) {
+ if (!file_present) {
+ daccess = cpu_to_le32(GENERIC_ALL_FLAGS);
+ } else {
+ rc = ksmbd_vfs_query_maximal_access(user_ns,
+ path.dentry,
+ &daccess);
+ if (rc)
+ goto err_out;
+ already_permitted = true;
+ }
+ maximal_access = daccess;
+ }
+
+ open_flags = smb2_create_open_flags(file_present, daccess,
+ req->CreateDisposition,
+ &may_flags);
+
+ if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+ if (open_flags & O_CREAT) {
+ ksmbd_debug(SMB,
+ "User does not have write permission\n");
+ rc = -EACCES;
+ goto err_out;
+ }
+ }
+
+ /*create file if not present */
+ if (!file_present) {
+ rc = smb2_creat(work, &path, name, open_flags, posix_mode,
+ req->CreateOptions & FILE_DIRECTORY_FILE_LE);
+ if (rc) {
+ if (rc == -ENOENT) {
+ rc = -EIO;
+ rsp->hdr.Status = STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ goto err_out;
+ }
+
+ created = true;
+ user_ns = mnt_user_ns(path.mnt);
+ if (ea_buf) {
+ if (le32_to_cpu(ea_buf->ccontext.DataLength) <
+ sizeof(struct smb2_ea_info)) {
+ rc = -EINVAL;
+ goto err_out;
+ }
+
+ rc = smb2_set_ea(&ea_buf->ea,
+ le32_to_cpu(ea_buf->ccontext.DataLength),
+ &path);
+ if (rc == -EOPNOTSUPP)
+ rc = 0;
+ else if (rc)
+ goto err_out;
+ }
+ } else if (!already_permitted) {
+ /* FILE_READ_ATTRIBUTE is allowed without inode_permission,
+ * because execute(search) permission on a parent directory,
+ * is already granted.
+ */
+ if (daccess & ~(FILE_READ_ATTRIBUTES_LE | FILE_READ_CONTROL_LE)) {
+ rc = inode_permission(user_ns,
+ d_inode(path.dentry),
+ may_flags);
+ if (rc)
+ goto err_out;
+
+ if ((daccess & FILE_DELETE_LE) ||
+ (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
+ rc = ksmbd_vfs_may_delete(user_ns,
+ path.dentry);
+ if (rc)
+ goto err_out;
+ }
+ }
+ }
+
+ rc = ksmbd_query_inode_status(d_inode(path.dentry->d_parent));
+ if (rc == KSMBD_INODE_STATUS_PENDING_DELETE) {
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ rc = 0;
+ filp = dentry_open(&path, open_flags, current_cred());
+ if (IS_ERR(filp)) {
+ rc = PTR_ERR(filp);
+ pr_err("dentry open for dir failed, rc %d\n", rc);
+ goto err_out;
+ }
+
+ if (file_present) {
+ if (!(open_flags & O_TRUNC))
+ file_info = FILE_OPENED;
+ else
+ file_info = FILE_OVERWRITTEN;
+
+ if ((req->CreateDisposition & FILE_CREATE_MASK_LE) ==
+ FILE_SUPERSEDE_LE)
+ file_info = FILE_SUPERSEDED;
+ } else if (open_flags & O_CREAT) {
+ file_info = FILE_CREATED;
+ }
+
+ ksmbd_vfs_set_fadvise(filp, req->CreateOptions);
+
+ /* Obtain Volatile-ID */
+ fp = ksmbd_open_fd(work, filp);
+ if (IS_ERR(fp)) {
+ fput(filp);
+ rc = PTR_ERR(fp);
+ fp = NULL;
+ goto err_out;
+ }
+
+ /* Get Persistent-ID */
+ ksmbd_open_durable_fd(fp);
+ if (!has_file_id(fp->persistent_id)) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ fp->cdoption = req->CreateDisposition;
+ fp->daccess = daccess;
+ fp->saccess = req->ShareAccess;
+ fp->coption = req->CreateOptions;
+
+ /* Set default windows and posix acls if creating new file */
+ if (created) {
+ int posix_acl_rc;
+ struct inode *inode = d_inode(path.dentry);
+
+ posix_acl_rc = ksmbd_vfs_inherit_posix_acl(user_ns,
+ inode,
+ d_inode(path.dentry->d_parent));
+ if (posix_acl_rc)
+ ksmbd_debug(SMB, "inherit posix acl failed : %d\n", posix_acl_rc);
+
+ if (test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_ACL_XATTR)) {
+ rc = smb_inherit_dacl(conn, &path, sess->user->uid,
+ sess->user->gid);
+ }
+
+ if (rc) {
+ rc = smb2_create_sd_buffer(work, req, &path);
+ if (rc) {
+ if (posix_acl_rc)
+ ksmbd_vfs_set_init_posix_acl(user_ns,
+ inode);
+
+ if (test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_ACL_XATTR)) {
+ struct smb_fattr fattr;
+ struct smb_ntsd *pntsd;
+ int pntsd_size, ace_num = 0;
+
+ ksmbd_acls_fattr(&fattr, user_ns, inode);
+ if (fattr.cf_acls)
+ ace_num = fattr.cf_acls->a_count;
+ if (fattr.cf_dacls)
+ ace_num += fattr.cf_dacls->a_count;
+
+ pntsd = kmalloc(sizeof(struct smb_ntsd) +
+ sizeof(struct smb_sid) * 3 +
+ sizeof(struct smb_acl) +
+ sizeof(struct smb_ace) * ace_num * 2,
+ GFP_KERNEL);
+ if (!pntsd) {
+ posix_acl_release(fattr.cf_acls);
+ posix_acl_release(fattr.cf_dacls);
+ goto err_out;
+ }
+
+ rc = build_sec_desc(user_ns,
+ pntsd, NULL, 0,
+ OWNER_SECINFO |
+ GROUP_SECINFO |
+ DACL_SECINFO,
+ &pntsd_size, &fattr);
+ posix_acl_release(fattr.cf_acls);
+ posix_acl_release(fattr.cf_dacls);
+ if (rc) {
+ kfree(pntsd);
+ goto err_out;
+ }
+
+ rc = ksmbd_vfs_set_sd_xattr(conn,
+ user_ns,
+ path.dentry,
+ pntsd,
+ pntsd_size);
+ kfree(pntsd);
+ if (rc)
+ pr_err("failed to store ntacl in xattr : %d\n",
+ rc);
+ }
+ }
+ }
+ rc = 0;
+ }
+
+ if (stream_name) {
+ rc = smb2_set_stream_name_xattr(&path,
+ fp,
+ stream_name,
+ s_type);
+ if (rc)
+ goto err_out;
+ file_info = FILE_CREATED;
+ }
+
+ fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE |
+ FILE_WRITE_ATTRIBUTES_LE | FILE_SYNCHRONIZE_LE));
+ if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC &&
+ !fp->attrib_only && !stream_name) {
+ smb_break_all_oplock(work, fp);
+ need_truncate = 1;
+ }
+
+ /* fp should be searchable through ksmbd_inode.m_fp_list
+ * after daccess, saccess, attrib_only, and stream are
+ * initialized.
+ */
+ write_lock(&fp->f_ci->m_lock);
+ list_add(&fp->node, &fp->f_ci->m_fp_list);
+ write_unlock(&fp->f_ci->m_lock);
+
+ /* Check delete pending among previous fp before oplock break */
+ if (ksmbd_inode_pending_delete(fp)) {
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
+ if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
+ (req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
+ !(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) {
+ if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) {
+ rc = share_ret;
+ goto err_out;
+ }
+ } else {
+ if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
+ req_op_level = smb2_map_lease_to_oplock(lc->req_state);
+ ksmbd_debug(SMB,
+ "lease req for(%s) req oplock state 0x%x, lease state 0x%x\n",
+ name, req_op_level, lc->req_state);
+ rc = find_same_lease_key(sess, fp->f_ci, lc);
+ if (rc)
+ goto err_out;
+ } else if (open_flags == O_RDONLY &&
+ (req_op_level == SMB2_OPLOCK_LEVEL_BATCH ||
+ req_op_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE))
+ req_op_level = SMB2_OPLOCK_LEVEL_II;
+
+ rc = smb_grant_oplock(work, req_op_level,
+ fp->persistent_id, fp,
+ le32_to_cpu(req->hdr.Id.SyncId.TreeId),
+ lc, share_ret);
+ if (rc < 0)
+ goto err_out;
+ }
+
+ if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)
+ ksmbd_fd_set_delete_on_close(fp, file_info);
+
+ if (need_truncate) {
+ rc = smb2_create_truncate(&path);
+ if (rc)
+ goto err_out;
+ }
+
+ if (req->CreateContextsOffset) {
+ struct create_alloc_size_req *az_req;
+
+ az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req,
+ SMB2_CREATE_ALLOCATION_SIZE, 4);
+ if (IS_ERR(az_req)) {
+ rc = PTR_ERR(az_req);
+ goto err_out;
+ } else if (az_req) {
+ loff_t alloc_size;
+ int err;
+
+ if (le16_to_cpu(az_req->ccontext.DataOffset) +
+ le32_to_cpu(az_req->ccontext.DataLength) <
+ sizeof(struct create_alloc_size_req)) {
+ rc = -EINVAL;
+ goto err_out;
+ }
+ alloc_size = le64_to_cpu(az_req->AllocationSize);
+ ksmbd_debug(SMB,
+ "request smb2 create allocate size : %llu\n",
+ alloc_size);
+ smb_break_all_levII_oplock(work, fp, 1);
+ err = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
+ alloc_size);
+ if (err < 0)
+ ksmbd_debug(SMB,
+ "vfs_fallocate is failed : %d\n",
+ err);
+ }
+
+ context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4);
+ if (IS_ERR(context)) {
+ rc = PTR_ERR(context);
+ goto err_out;
+ } else if (context) {
+ ksmbd_debug(SMB, "get query on disk id context\n");
+ query_disk_id = 1;
+ }
+ }
+
+ rc = ksmbd_vfs_getattr(&path, &stat);
+ if (rc)
+ goto err_out;
+
+ if (stat.result_mask & STATX_BTIME)
+ fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
+ else
+ fp->create_time = ksmbd_UnixTimeToNT(stat.ctime);
+ if (req->FileAttributes || fp->f_ci->m_fattr == 0)
+ fp->f_ci->m_fattr =
+ cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes)));
+
+ if (!created)
+ smb2_update_xattrs(tcon, &path, fp);
+ else
+ smb2_new_xattrs(tcon, &path, fp);
+
+ memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
+
+ rsp->StructureSize = cpu_to_le16(89);
+ rcu_read_lock();
+ opinfo = rcu_dereference(fp->f_opinfo);
+ rsp->OplockLevel = opinfo != NULL ? opinfo->level : 0;
+ rcu_read_unlock();
+ rsp->Flags = 0;
+ rsp->CreateAction = cpu_to_le32(file_info);
+ rsp->CreationTime = cpu_to_le64(fp->create_time);
+ time = ksmbd_UnixTimeToNT(stat.atime);
+ rsp->LastAccessTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(stat.mtime);
+ rsp->LastWriteTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(stat.ctime);
+ rsp->ChangeTime = cpu_to_le64(time);
+ rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 :
+ cpu_to_le64(stat.blocks << 9);
+ rsp->EndofFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
+ rsp->FileAttributes = fp->f_ci->m_fattr;
+
+ rsp->Reserved2 = 0;
+
+ rsp->PersistentFileId = fp->persistent_id;
+ rsp->VolatileFileId = fp->volatile_id;
+
+ rsp->CreateContextsOffset = 0;
+ rsp->CreateContextsLength = 0;
+ inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
+
+ /* If lease is request send lease context response */
+ if (opinfo && opinfo->is_lease) {
+ struct create_context *lease_ccontext;
+
+ ksmbd_debug(SMB, "lease granted on(%s) lease state 0x%x\n",
+ name, opinfo->o_lease->state);
+ rsp->OplockLevel = SMB2_OPLOCK_LEVEL_LEASE;
+
+ lease_ccontext = (struct create_context *)rsp->Buffer;
+ contxt_cnt++;
+ create_lease_buf(rsp->Buffer, opinfo->o_lease);
+ le32_add_cpu(&rsp->CreateContextsLength,
+ conn->vals->create_lease_size);
+ inc_rfc1001_len(work->response_buf,
+ conn->vals->create_lease_size);
+ next_ptr = &lease_ccontext->Next;
+ next_off = conn->vals->create_lease_size;
+ }
+
+ if (maximal_access_ctxt) {
+ struct create_context *mxac_ccontext;
+
+ if (maximal_access == 0)
+ ksmbd_vfs_query_maximal_access(user_ns,
+ path.dentry,
+ &maximal_access);
+ mxac_ccontext = (struct create_context *)(rsp->Buffer +
+ le32_to_cpu(rsp->CreateContextsLength));
+ contxt_cnt++;
+ create_mxac_rsp_buf(rsp->Buffer +
+ le32_to_cpu(rsp->CreateContextsLength),
+ le32_to_cpu(maximal_access));
+ le32_add_cpu(&rsp->CreateContextsLength,
+ conn->vals->create_mxac_size);
+ inc_rfc1001_len(work->response_buf,
+ conn->vals->create_mxac_size);
+ if (next_ptr)
+ *next_ptr = cpu_to_le32(next_off);
+ next_ptr = &mxac_ccontext->Next;
+ next_off = conn->vals->create_mxac_size;
+ }
+
+ if (query_disk_id) {
+ struct create_context *disk_id_ccontext;
+
+ disk_id_ccontext = (struct create_context *)(rsp->Buffer +
+ le32_to_cpu(rsp->CreateContextsLength));
+ contxt_cnt++;
+ create_disk_id_rsp_buf(rsp->Buffer +
+ le32_to_cpu(rsp->CreateContextsLength),
+ stat.ino, tcon->id);
+ le32_add_cpu(&rsp->CreateContextsLength,
+ conn->vals->create_disk_id_size);
+ inc_rfc1001_len(work->response_buf,
+ conn->vals->create_disk_id_size);
+ if (next_ptr)
+ *next_ptr = cpu_to_le32(next_off);
+ next_ptr = &disk_id_ccontext->Next;
+ next_off = conn->vals->create_disk_id_size;
+ }
+
+ if (posix_ctxt) {
+ contxt_cnt++;
+ create_posix_rsp_buf(rsp->Buffer +
+ le32_to_cpu(rsp->CreateContextsLength),
+ fp);
+ le32_add_cpu(&rsp->CreateContextsLength,
+ conn->vals->create_posix_size);
+ inc_rfc1001_len(work->response_buf,
+ conn->vals->create_posix_size);
+ if (next_ptr)
+ *next_ptr = cpu_to_le32(next_off);
+ }
+
+ if (contxt_cnt > 0) {
+ rsp->CreateContextsOffset =
+ cpu_to_le32(offsetof(struct smb2_create_rsp, Buffer));
+ }
+
+err_out:
+ if (file_present || created)
+ path_put(&path);
+ ksmbd_revert_fsids(work);
+err_out1:
+ if (rc) {
+ if (rc == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else if (rc == -EOPNOTSUPP)
+ rsp->hdr.Status = STATUS_NOT_SUPPORTED;
+ else if (rc == -EACCES || rc == -ESTALE || rc == -EXDEV)
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ else if (rc == -ENOENT)
+ rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID;
+ else if (rc == -EPERM)
+ rsp->hdr.Status = STATUS_SHARING_VIOLATION;
+ else if (rc == -EBUSY)
+ rsp->hdr.Status = STATUS_DELETE_PENDING;
+ else if (rc == -EBADF)
+ rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ else if (rc == -ENOEXEC)
+ rsp->hdr.Status = STATUS_DUPLICATE_OBJECTID;
+ else if (rc == -ENXIO)
+ rsp->hdr.Status = STATUS_NO_SUCH_DEVICE;
+ else if (rc == -EEXIST)
+ rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION;
+ else if (rc == -EMFILE)
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
+ if (!rsp->hdr.Status)
+ rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
+
+ if (fp)
+ ksmbd_fd_put(work, fp);
+ smb2_set_err_rsp(work);
+ ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status);
+ }
+
+ kfree(name);
+ kfree(lc);
+
+ return 0;
+}
+
+static int readdir_info_level_struct_sz(int info_level)
+{
+ switch (info_level) {
+ case FILE_FULL_DIRECTORY_INFORMATION:
+ return sizeof(struct file_full_directory_info);
+ case FILE_BOTH_DIRECTORY_INFORMATION:
+ return sizeof(struct file_both_directory_info);
+ case FILE_DIRECTORY_INFORMATION:
+ return sizeof(struct file_directory_info);
+ case FILE_NAMES_INFORMATION:
+ return sizeof(struct file_names_info);
+ case FILEID_FULL_DIRECTORY_INFORMATION:
+ return sizeof(struct file_id_full_dir_info);
+ case FILEID_BOTH_DIRECTORY_INFORMATION:
+ return sizeof(struct file_id_both_directory_info);
+ case SMB_FIND_FILE_POSIX_INFO:
+ return sizeof(struct smb2_posix_info);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
+{
+ switch (info_level) {
+ case FILE_FULL_DIRECTORY_INFORMATION:
+ {
+ struct file_full_directory_info *ffdinfo;
+
+ ffdinfo = (struct file_full_directory_info *)d_info->rptr;
+ d_info->rptr += le32_to_cpu(ffdinfo->NextEntryOffset);
+ d_info->name = ffdinfo->FileName;
+ d_info->name_len = le32_to_cpu(ffdinfo->FileNameLength);
+ return 0;
+ }
+ case FILE_BOTH_DIRECTORY_INFORMATION:
+ {
+ struct file_both_directory_info *fbdinfo;
+
+ fbdinfo = (struct file_both_directory_info *)d_info->rptr;
+ d_info->rptr += le32_to_cpu(fbdinfo->NextEntryOffset);
+ d_info->name = fbdinfo->FileName;
+ d_info->name_len = le32_to_cpu(fbdinfo->FileNameLength);
+ return 0;
+ }
+ case FILE_DIRECTORY_INFORMATION:
+ {
+ struct file_directory_info *fdinfo;
+
+ fdinfo = (struct file_directory_info *)d_info->rptr;
+ d_info->rptr += le32_to_cpu(fdinfo->NextEntryOffset);
+ d_info->name = fdinfo->FileName;
+ d_info->name_len = le32_to_cpu(fdinfo->FileNameLength);
+ return 0;
+ }
+ case FILE_NAMES_INFORMATION:
+ {
+ struct file_names_info *fninfo;
+
+ fninfo = (struct file_names_info *)d_info->rptr;
+ d_info->rptr += le32_to_cpu(fninfo->NextEntryOffset);
+ d_info->name = fninfo->FileName;
+ d_info->name_len = le32_to_cpu(fninfo->FileNameLength);
+ return 0;
+ }
+ case FILEID_FULL_DIRECTORY_INFORMATION:
+ {
+ struct file_id_full_dir_info *dinfo;
+
+ dinfo = (struct file_id_full_dir_info *)d_info->rptr;
+ d_info->rptr += le32_to_cpu(dinfo->NextEntryOffset);
+ d_info->name = dinfo->FileName;
+ d_info->name_len = le32_to_cpu(dinfo->FileNameLength);
+ return 0;
+ }
+ case FILEID_BOTH_DIRECTORY_INFORMATION:
+ {
+ struct file_id_both_directory_info *fibdinfo;
+
+ fibdinfo = (struct file_id_both_directory_info *)d_info->rptr;
+ d_info->rptr += le32_to_cpu(fibdinfo->NextEntryOffset);
+ d_info->name = fibdinfo->FileName;
+ d_info->name_len = le32_to_cpu(fibdinfo->FileNameLength);
+ return 0;
+ }
+ case SMB_FIND_FILE_POSIX_INFO:
+ {
+ struct smb2_posix_info *posix_info;
+
+ posix_info = (struct smb2_posix_info *)d_info->rptr;
+ d_info->rptr += le32_to_cpu(posix_info->NextEntryOffset);
+ d_info->name = posix_info->name;
+ d_info->name_len = le32_to_cpu(posix_info->name_len);
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * smb2_populate_readdir_entry() - encode directory entry in smb2 response
+ * buffer
+ * @conn: connection instance
+ * @info_level: smb information level
+ * @d_info: structure included variables for query dir
+ * @ksmbd_kstat: ksmbd wrapper of dirent stat information
+ *
+ * if directory has many entries, find first can't read it fully.
+ * find next might be called multiple times to read remaining dir entries
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
+ struct ksmbd_dir_info *d_info,
+ struct ksmbd_kstat *ksmbd_kstat)
+{
+ int next_entry_offset = 0;
+ char *conv_name;
+ int conv_len;
+ void *kstat;
+ int struct_sz, rc = 0;
+
+ conv_name = ksmbd_convert_dir_info_name(d_info,
+ conn->local_nls,
+ &conv_len);
+ if (!conv_name)
+ return -ENOMEM;
+
+ /* Somehow the name has only terminating NULL bytes */
+ if (conv_len < 0) {
+ rc = -EINVAL;
+ goto free_conv_name;
+ }
+
+ struct_sz = readdir_info_level_struct_sz(info_level) - 1 + conv_len;
+ next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT);
+ d_info->last_entry_off_align = next_entry_offset - struct_sz;
+
+ if (next_entry_offset > d_info->out_buf_len) {
+ d_info->out_buf_len = 0;
+ rc = -ENOSPC;
+ goto free_conv_name;
+ }
+
+ kstat = d_info->wptr;
+ if (info_level != FILE_NAMES_INFORMATION)
+ kstat = ksmbd_vfs_init_kstat(&d_info->wptr, ksmbd_kstat);
+
+ switch (info_level) {
+ case FILE_FULL_DIRECTORY_INFORMATION:
+ {
+ struct file_full_directory_info *ffdinfo;
+
+ ffdinfo = (struct file_full_directory_info *)kstat;
+ ffdinfo->FileNameLength = cpu_to_le32(conv_len);
+ ffdinfo->EaSize =
+ smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
+ if (ffdinfo->EaSize)
+ ffdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
+ if (d_info->hide_dot_file && d_info->name[0] == '.')
+ ffdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
+ memcpy(ffdinfo->FileName, conv_name, conv_len);
+ ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILE_BOTH_DIRECTORY_INFORMATION:
+ {
+ struct file_both_directory_info *fbdinfo;
+
+ fbdinfo = (struct file_both_directory_info *)kstat;
+ fbdinfo->FileNameLength = cpu_to_le32(conv_len);
+ fbdinfo->EaSize =
+ smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
+ if (fbdinfo->EaSize)
+ fbdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
+ fbdinfo->ShortNameLength = 0;
+ fbdinfo->Reserved = 0;
+ if (d_info->hide_dot_file && d_info->name[0] == '.')
+ fbdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
+ memcpy(fbdinfo->FileName, conv_name, conv_len);
+ fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILE_DIRECTORY_INFORMATION:
+ {
+ struct file_directory_info *fdinfo;
+
+ fdinfo = (struct file_directory_info *)kstat;
+ fdinfo->FileNameLength = cpu_to_le32(conv_len);
+ if (d_info->hide_dot_file && d_info->name[0] == '.')
+ fdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
+ memcpy(fdinfo->FileName, conv_name, conv_len);
+ fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILE_NAMES_INFORMATION:
+ {
+ struct file_names_info *fninfo;
+
+ fninfo = (struct file_names_info *)kstat;
+ fninfo->FileNameLength = cpu_to_le32(conv_len);
+ memcpy(fninfo->FileName, conv_name, conv_len);
+ fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILEID_FULL_DIRECTORY_INFORMATION:
+ {
+ struct file_id_full_dir_info *dinfo;
+
+ dinfo = (struct file_id_full_dir_info *)kstat;
+ dinfo->FileNameLength = cpu_to_le32(conv_len);
+ dinfo->EaSize =
+ smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
+ if (dinfo->EaSize)
+ dinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
+ dinfo->Reserved = 0;
+ dinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
+ if (d_info->hide_dot_file && d_info->name[0] == '.')
+ dinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
+ memcpy(dinfo->FileName, conv_name, conv_len);
+ dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILEID_BOTH_DIRECTORY_INFORMATION:
+ {
+ struct file_id_both_directory_info *fibdinfo;
+
+ fibdinfo = (struct file_id_both_directory_info *)kstat;
+ fibdinfo->FileNameLength = cpu_to_le32(conv_len);
+ fibdinfo->EaSize =
+ smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
+ if (fibdinfo->EaSize)
+ fibdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
+ fibdinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
+ fibdinfo->ShortNameLength = 0;
+ fibdinfo->Reserved = 0;
+ fibdinfo->Reserved2 = cpu_to_le16(0);
+ if (d_info->hide_dot_file && d_info->name[0] == '.')
+ fibdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
+ memcpy(fibdinfo->FileName, conv_name, conv_len);
+ fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case SMB_FIND_FILE_POSIX_INFO:
+ {
+ struct smb2_posix_info *posix_info;
+ u64 time;
+
+ posix_info = (struct smb2_posix_info *)kstat;
+ posix_info->Ignored = 0;
+ posix_info->CreationTime = cpu_to_le64(ksmbd_kstat->create_time);
+ time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
+ posix_info->ChangeTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->atime);
+ posix_info->LastAccessTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->mtime);
+ posix_info->LastWriteTime = cpu_to_le64(time);
+ posix_info->EndOfFile = cpu_to_le64(ksmbd_kstat->kstat->size);
+ posix_info->AllocationSize = cpu_to_le64(ksmbd_kstat->kstat->blocks << 9);
+ posix_info->DeviceId = cpu_to_le32(ksmbd_kstat->kstat->rdev);
+ posix_info->HardLinks = cpu_to_le32(ksmbd_kstat->kstat->nlink);
+ posix_info->Mode = cpu_to_le32(ksmbd_kstat->kstat->mode & 0777);
+ posix_info->Inode = cpu_to_le64(ksmbd_kstat->kstat->ino);
+ posix_info->DosAttributes =
+ S_ISDIR(ksmbd_kstat->kstat->mode) ?
+ FILE_ATTRIBUTE_DIRECTORY_LE : FILE_ATTRIBUTE_ARCHIVE_LE;
+ if (d_info->hide_dot_file && d_info->name[0] == '.')
+ posix_info->DosAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
+ /*
+ * SidBuffer(32) contain two sids(Domain sid(16), UNIX group sid(16)).
+ * UNIX sid(16) = revision(1) + num_subauth(1) + authority(6) +
+ * sub_auth(4 * 1(num_subauth)) + RID(4).
+ */
+ id_to_sid(from_kuid_munged(&init_user_ns, ksmbd_kstat->kstat->uid),
+ SIDUNIX_USER, (struct smb_sid *)&posix_info->SidBuffer[0]);
+ id_to_sid(from_kgid_munged(&init_user_ns, ksmbd_kstat->kstat->gid),
+ SIDUNIX_GROUP, (struct smb_sid *)&posix_info->SidBuffer[16]);
+ memcpy(posix_info->name, conv_name, conv_len);
+ posix_info->name_len = cpu_to_le32(conv_len);
+ posix_info->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+
+ } /* switch (info_level) */
+
+ d_info->last_entry_offset = d_info->data_count;
+ d_info->data_count += next_entry_offset;
+ d_info->out_buf_len -= next_entry_offset;
+ d_info->wptr += next_entry_offset;
+
+ ksmbd_debug(SMB,
+ "info_level : %d, buf_len :%d, next_offset : %d, data_count : %d\n",
+ info_level, d_info->out_buf_len,
+ next_entry_offset, d_info->data_count);
+
+free_conv_name:
+ kfree(conv_name);
+ return rc;
+}
+
+struct smb2_query_dir_private {
+ struct ksmbd_work *work;
+ char *search_pattern;
+ struct ksmbd_file *dir_fp;
+
+ struct ksmbd_dir_info *d_info;
+ int info_level;
+};
+
+static void lock_dir(struct ksmbd_file *dir_fp)
+{
+ struct dentry *dir = dir_fp->filp->f_path.dentry;
+
+ inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
+}
+
+static void unlock_dir(struct ksmbd_file *dir_fp)
+{
+ struct dentry *dir = dir_fp->filp->f_path.dentry;
+
+ inode_unlock(d_inode(dir));
+}
+
+static int process_query_dir_entries(struct smb2_query_dir_private *priv)
+{
+ struct user_namespace *user_ns = file_mnt_user_ns(priv->dir_fp->filp);
+ struct kstat kstat;
+ struct ksmbd_kstat ksmbd_kstat;
+ int rc;
+ int i;
+
+ for (i = 0; i < priv->d_info->num_entry; i++) {
+ struct dentry *dent;
+
+ if (dentry_name(priv->d_info, priv->info_level))
+ return -EINVAL;
+
+ lock_dir(priv->dir_fp);
+ dent = lookup_one(user_ns, priv->d_info->name,
+ priv->dir_fp->filp->f_path.dentry,
+ priv->d_info->name_len);
+ unlock_dir(priv->dir_fp);
+
+ if (IS_ERR(dent)) {
+ ksmbd_debug(SMB, "Cannot lookup `%s' [%ld]\n",
+ priv->d_info->name,
+ PTR_ERR(dent));
+ continue;
+ }
+ if (unlikely(d_is_negative(dent))) {
+ dput(dent);
+ ksmbd_debug(SMB, "Negative dentry `%s'\n",
+ priv->d_info->name);
+ continue;
+ }
+
+ ksmbd_kstat.kstat = &kstat;
+ if (priv->info_level != FILE_NAMES_INFORMATION)
+ ksmbd_vfs_fill_dentry_attrs(priv->work,
+ user_ns,
+ dent,
+ &ksmbd_kstat);
+
+ rc = smb2_populate_readdir_entry(priv->work->conn,
+ priv->info_level,
+ priv->d_info,
+ &ksmbd_kstat);
+ dput(dent);
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
+static int reserve_populate_dentry(struct ksmbd_dir_info *d_info,
+ int info_level)
+{
+ int struct_sz;
+ int conv_len;
+ int next_entry_offset;
+
+ struct_sz = readdir_info_level_struct_sz(info_level);
+ if (struct_sz == -EOPNOTSUPP)
+ return -EOPNOTSUPP;
+
+ conv_len = (d_info->name_len + 1) * 2;
+ next_entry_offset = ALIGN(struct_sz - 1 + conv_len,
+ KSMBD_DIR_INFO_ALIGNMENT);
+
+ if (next_entry_offset > d_info->out_buf_len) {
+ d_info->out_buf_len = 0;
+ return -ENOSPC;
+ }
+
+ switch (info_level) {
+ case FILE_FULL_DIRECTORY_INFORMATION:
+ {
+ struct file_full_directory_info *ffdinfo;
+
+ ffdinfo = (struct file_full_directory_info *)d_info->wptr;
+ memcpy(ffdinfo->FileName, d_info->name, d_info->name_len);
+ ffdinfo->FileName[d_info->name_len] = 0x00;
+ ffdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
+ ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILE_BOTH_DIRECTORY_INFORMATION:
+ {
+ struct file_both_directory_info *fbdinfo;
+
+ fbdinfo = (struct file_both_directory_info *)d_info->wptr;
+ memcpy(fbdinfo->FileName, d_info->name, d_info->name_len);
+ fbdinfo->FileName[d_info->name_len] = 0x00;
+ fbdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
+ fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILE_DIRECTORY_INFORMATION:
+ {
+ struct file_directory_info *fdinfo;
+
+ fdinfo = (struct file_directory_info *)d_info->wptr;
+ memcpy(fdinfo->FileName, d_info->name, d_info->name_len);
+ fdinfo->FileName[d_info->name_len] = 0x00;
+ fdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
+ fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILE_NAMES_INFORMATION:
+ {
+ struct file_names_info *fninfo;
+
+ fninfo = (struct file_names_info *)d_info->wptr;
+ memcpy(fninfo->FileName, d_info->name, d_info->name_len);
+ fninfo->FileName[d_info->name_len] = 0x00;
+ fninfo->FileNameLength = cpu_to_le32(d_info->name_len);
+ fninfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILEID_FULL_DIRECTORY_INFORMATION:
+ {
+ struct file_id_full_dir_info *dinfo;
+
+ dinfo = (struct file_id_full_dir_info *)d_info->wptr;
+ memcpy(dinfo->FileName, d_info->name, d_info->name_len);
+ dinfo->FileName[d_info->name_len] = 0x00;
+ dinfo->FileNameLength = cpu_to_le32(d_info->name_len);
+ dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case FILEID_BOTH_DIRECTORY_INFORMATION:
+ {
+ struct file_id_both_directory_info *fibdinfo;
+
+ fibdinfo = (struct file_id_both_directory_info *)d_info->wptr;
+ memcpy(fibdinfo->FileName, d_info->name, d_info->name_len);
+ fibdinfo->FileName[d_info->name_len] = 0x00;
+ fibdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
+ fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
+ break;
+ }
+ case SMB_FIND_FILE_POSIX_INFO:
+ {
+ struct smb2_posix_info *posix_info;
+
+ posix_info = (struct smb2_posix_info *)d_info->wptr;
+ memcpy(posix_info->name, d_info->name, d_info->name_len);
+ posix_info->name[d_info->name_len] = 0x00;
+ posix_info->name_len = cpu_to_le32(d_info->name_len);
+ posix_info->NextEntryOffset =
+ cpu_to_le32(next_entry_offset);
+ break;
+ }
+ } /* switch (info_level) */
+
+ d_info->num_entry++;
+ d_info->out_buf_len -= next_entry_offset;
+ d_info->wptr += next_entry_offset;
+ return 0;
+}
+
+static bool __query_dir(struct dir_context *ctx, const char *name, int namlen,
+ loff_t offset, u64 ino, unsigned int d_type)
+{
+ struct ksmbd_readdir_data *buf;
+ struct smb2_query_dir_private *priv;
+ struct ksmbd_dir_info *d_info;
+ int rc;
+
+ buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
+ priv = buf->private;
+ d_info = priv->d_info;
+
+ /* dot and dotdot entries are already reserved */
+ if (!strcmp(".", name) || !strcmp("..", name))
+ return true;
+ if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
+ return true;
+ if (!match_pattern(name, namlen, priv->search_pattern))
+ return true;
+
+ d_info->name = name;
+ d_info->name_len = namlen;
+ rc = reserve_populate_dentry(d_info, priv->info_level);
+ if (rc)
+ return false;
+ if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY)
+ d_info->out_buf_len = 0;
+ return true;
+}
+
+static int verify_info_level(int info_level)
+{
+ switch (info_level) {
+ case FILE_FULL_DIRECTORY_INFORMATION:
+ case FILE_BOTH_DIRECTORY_INFORMATION:
+ case FILE_DIRECTORY_INFORMATION:
+ case FILE_NAMES_INFORMATION:
+ case FILEID_FULL_DIRECTORY_INFORMATION:
+ case FILEID_BOTH_DIRECTORY_INFORMATION:
+ case SMB_FIND_FILE_POSIX_INFO:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int smb2_resp_buf_len(struct ksmbd_work *work, unsigned short hdr2_len)
+{
+ int free_len;
+
+ free_len = (int)(work->response_sz -
+ (get_rfc1002_len(work->response_buf) + 4)) - hdr2_len;
+ return free_len;
+}
+
+static int smb2_calc_max_out_buf_len(struct ksmbd_work *work,
+ unsigned short hdr2_len,
+ unsigned int out_buf_len)
+{
+ int free_len;
+
+ if (out_buf_len > work->conn->vals->max_trans_size)
+ return -EINVAL;
+
+ free_len = smb2_resp_buf_len(work, hdr2_len);
+ if (free_len < 0)
+ return -EINVAL;
+
+ return min_t(int, out_buf_len, free_len);
+}
+
+int smb2_query_dir(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_query_directory_req *req;
+ struct smb2_query_directory_rsp *rsp;
+ struct ksmbd_share_config *share = work->tcon->share_conf;
+ struct ksmbd_file *dir_fp = NULL;
+ struct ksmbd_dir_info d_info;
+ int rc = 0;
+ char *srch_ptr = NULL;
+ unsigned char srch_flag;
+ int buffer_sz;
+ struct smb2_query_dir_private query_dir_private = {NULL, };
+
+ WORK_BUFFERS(work, req, rsp);
+
+ if (ksmbd_override_fsids(work)) {
+ rsp->hdr.Status = STATUS_NO_MEMORY;
+ smb2_set_err_rsp(work);
+ return -ENOMEM;
+ }
+
+ rc = verify_info_level(req->FileInformationClass);
+ if (rc) {
+ rc = -EFAULT;
+ goto err_out2;
+ }
+
+ dir_fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
+ if (!dir_fp) {
+ rc = -EBADF;
+ goto err_out2;
+ }
+
+ if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) ||
+ inode_permission(file_mnt_user_ns(dir_fp->filp),
+ file_inode(dir_fp->filp),
+ MAY_READ | MAY_EXEC)) {
+ pr_err("no right to enumerate directory (%pD)\n", dir_fp->filp);
+ rc = -EACCES;
+ goto err_out2;
+ }
+
+ if (!S_ISDIR(file_inode(dir_fp->filp)->i_mode)) {
+ pr_err("can't do query dir for a file\n");
+ rc = -EINVAL;
+ goto err_out2;
+ }
+
+ srch_flag = req->Flags;
+ srch_ptr = smb_strndup_from_utf16(req->Buffer,
+ le16_to_cpu(req->FileNameLength), 1,
+ conn->local_nls);
+ if (IS_ERR(srch_ptr)) {
+ ksmbd_debug(SMB, "Search Pattern not found\n");
+ rc = -EINVAL;
+ goto err_out2;
+ } else {
+ ksmbd_debug(SMB, "Search pattern is %s\n", srch_ptr);
+ }
+
+ if (srch_flag & SMB2_REOPEN || srch_flag & SMB2_RESTART_SCANS) {
+ ksmbd_debug(SMB, "Restart directory scan\n");
+ generic_file_llseek(dir_fp->filp, 0, SEEK_SET);
+ }
+
+ memset(&d_info, 0, sizeof(struct ksmbd_dir_info));
+ d_info.wptr = (char *)rsp->Buffer;
+ d_info.rptr = (char *)rsp->Buffer;
+ d_info.out_buf_len =
+ smb2_calc_max_out_buf_len(work, 8,
+ le32_to_cpu(req->OutputBufferLength));
+ if (d_info.out_buf_len < 0) {
+ rc = -EINVAL;
+ goto err_out;
+ }
+ d_info.flags = srch_flag;
+
+ /*
+ * reserve dot and dotdot entries in head of buffer
+ * in first response
+ */
+ rc = ksmbd_populate_dot_dotdot_entries(work, req->FileInformationClass,
+ dir_fp, &d_info, srch_ptr,
+ smb2_populate_readdir_entry);
+ if (rc == -ENOSPC)
+ rc = 0;
+ else if (rc)
+ goto err_out;
+
+ if (test_share_config_flag(share, KSMBD_SHARE_FLAG_HIDE_DOT_FILES))
+ d_info.hide_dot_file = true;
+
+ buffer_sz = d_info.out_buf_len;
+ d_info.rptr = d_info.wptr;
+ query_dir_private.work = work;
+ query_dir_private.search_pattern = srch_ptr;
+ query_dir_private.dir_fp = dir_fp;
+ query_dir_private.d_info = &d_info;
+ query_dir_private.info_level = req->FileInformationClass;
+ dir_fp->readdir_data.private = &query_dir_private;
+ set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
+
+ rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
+ /*
+ * req->OutputBufferLength is too small to contain even one entry.
+ * In this case, it immediately returns OutputBufferLength 0 to client.
+ */
+ if (!d_info.out_buf_len && !d_info.num_entry)
+ goto no_buf_len;
+ if (rc > 0 || rc == -ENOSPC)
+ rc = 0;
+ else if (rc)
+ goto err_out;
+
+ d_info.wptr = d_info.rptr;
+ d_info.out_buf_len = buffer_sz;
+ rc = process_query_dir_entries(&query_dir_private);
+ if (rc)
+ goto err_out;
+
+ if (!d_info.data_count && d_info.out_buf_len >= 0) {
+ if (srch_flag & SMB2_RETURN_SINGLE_ENTRY && !is_asterisk(srch_ptr)) {
+ rsp->hdr.Status = STATUS_NO_SUCH_FILE;
+ } else {
+ dir_fp->dot_dotdot[0] = dir_fp->dot_dotdot[1] = 0;
+ rsp->hdr.Status = STATUS_NO_MORE_FILES;
+ }
+ rsp->StructureSize = cpu_to_le16(9);
+ rsp->OutputBufferOffset = cpu_to_le16(0);
+ rsp->OutputBufferLength = cpu_to_le32(0);
+ rsp->Buffer[0] = 0;
+ inc_rfc1001_len(work->response_buf, 9);
+ } else {
+no_buf_len:
+ ((struct file_directory_info *)
+ ((char *)rsp->Buffer + d_info.last_entry_offset))
+ ->NextEntryOffset = 0;
+ if (d_info.data_count >= d_info.last_entry_off_align)
+ d_info.data_count -= d_info.last_entry_off_align;
+
+ rsp->StructureSize = cpu_to_le16(9);
+ rsp->OutputBufferOffset = cpu_to_le16(72);
+ rsp->OutputBufferLength = cpu_to_le32(d_info.data_count);
+ inc_rfc1001_len(work->response_buf, 8 + d_info.data_count);
+ }
+
+ kfree(srch_ptr);
+ ksmbd_fd_put(work, dir_fp);
+ ksmbd_revert_fsids(work);
+ return 0;
+
+err_out:
+ pr_err("error while processing smb2 query dir rc = %d\n", rc);
+ kfree(srch_ptr);
+
+err_out2:
+ if (rc == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else if (rc == -EACCES)
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ else if (rc == -ENOENT)
+ rsp->hdr.Status = STATUS_NO_SUCH_FILE;
+ else if (rc == -EBADF)
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ else if (rc == -ENOMEM)
+ rsp->hdr.Status = STATUS_NO_MEMORY;
+ else if (rc == -EFAULT)
+ rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
+ else if (rc == -EIO)
+ rsp->hdr.Status = STATUS_FILE_CORRUPT_ERROR;
+ if (!rsp->hdr.Status)
+ rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
+
+ smb2_set_err_rsp(work);
+ ksmbd_fd_put(work, dir_fp);
+ ksmbd_revert_fsids(work);
+ return 0;
+}
+
+/**
+ * buffer_check_err() - helper function to check buffer errors
+ * @reqOutputBufferLength: max buffer length expected in command response
+ * @rsp: query info response buffer contains output buffer length
+ * @rsp_org: base response buffer pointer in case of chained response
+ * @infoclass_size: query info class response buffer size
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int buffer_check_err(int reqOutputBufferLength,
+ struct smb2_query_info_rsp *rsp,
+ void *rsp_org, int infoclass_size)
+{
+ if (reqOutputBufferLength < le32_to_cpu(rsp->OutputBufferLength)) {
+ if (reqOutputBufferLength < infoclass_size) {
+ pr_err("Invalid Buffer Size Requested\n");
+ rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
+ *(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr));
+ return -EINVAL;
+ }
+
+ ksmbd_debug(SMB, "Buffer Overflow\n");
+ rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
+ *(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr) +
+ reqOutputBufferLength);
+ rsp->OutputBufferLength = cpu_to_le32(reqOutputBufferLength);
+ }
+ return 0;
+}
+
+static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp,
+ void *rsp_org)
+{
+ struct smb2_file_standard_info *sinfo;
+
+ sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
+
+ sinfo->AllocationSize = cpu_to_le64(4096);
+ sinfo->EndOfFile = cpu_to_le64(0);
+ sinfo->NumberOfLinks = cpu_to_le32(1);
+ sinfo->DeletePending = 1;
+ sinfo->Directory = 0;
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_standard_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_standard_info));
+}
+
+static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num,
+ void *rsp_org)
+{
+ struct smb2_file_internal_info *file_info;
+
+ file_info = (struct smb2_file_internal_info *)rsp->Buffer;
+
+ /* any unique number */
+ file_info->IndexNumber = cpu_to_le64(num | (1ULL << 63));
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_internal_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_internal_info));
+}
+
+static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
+ struct smb2_query_info_req *req,
+ struct smb2_query_info_rsp *rsp,
+ void *rsp_org)
+{
+ u64 id;
+ int rc;
+
+ /*
+ * Windows can sometime send query file info request on
+ * pipe without opening it, checking error condition here
+ */
+ id = req->VolatileFileId;
+ if (!ksmbd_session_rpc_method(sess, id))
+ return -ENOENT;
+
+ ksmbd_debug(SMB, "FileInfoClass %u, FileId 0x%llx\n",
+ req->FileInfoClass, req->VolatileFileId);
+
+ switch (req->FileInfoClass) {
+ case FILE_STANDARD_INFORMATION:
+ get_standard_info_pipe(rsp, rsp_org);
+ rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
+ rsp, rsp_org,
+ FILE_STANDARD_INFORMATION_SIZE);
+ break;
+ case FILE_INTERNAL_INFORMATION:
+ get_internal_info_pipe(rsp, id, rsp_org);
+ rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
+ rsp, rsp_org,
+ FILE_INTERNAL_INFORMATION_SIZE);
+ break;
+ default:
+ ksmbd_debug(SMB, "smb2_info_file_pipe for %u not supported\n",
+ req->FileInfoClass);
+ rc = -EOPNOTSUPP;
+ }
+ return rc;
+}
+
+/**
+ * smb2_get_ea() - handler for smb2 get extended attribute command
+ * @work: smb work containing query info command buffer
+ * @fp: ksmbd_file pointer
+ * @req: get extended attribute request
+ * @rsp: response buffer pointer
+ * @rsp_org: base response buffer pointer in case of chained response
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
+ struct smb2_query_info_req *req,
+ struct smb2_query_info_rsp *rsp, void *rsp_org)
+{
+ struct smb2_ea_info *eainfo, *prev_eainfo;
+ char *name, *ptr, *xattr_list = NULL, *buf;
+ int rc, name_len, value_len, xattr_list_len, idx;
+ ssize_t buf_free_len, alignment_bytes, next_offset, rsp_data_cnt = 0;
+ struct smb2_ea_info_req *ea_req = NULL;
+ const struct path *path;
+ struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
+
+ if (!(fp->daccess & FILE_READ_EA_LE)) {
+ pr_err("Not permitted to read ext attr : 0x%x\n",
+ fp->daccess);
+ return -EACCES;
+ }
+
+ path = &fp->filp->f_path;
+ /* single EA entry is requested with given user.* name */
+ if (req->InputBufferLength) {
+ if (le32_to_cpu(req->InputBufferLength) <
+ sizeof(struct smb2_ea_info_req))
+ return -EINVAL;
+
+ ea_req = (struct smb2_ea_info_req *)req->Buffer;
+ } else {
+ /* need to send all EAs, if no specific EA is requested*/
+ if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY)
+ ksmbd_debug(SMB,
+ "All EAs are requested but need to send single EA entry in rsp flags 0x%x\n",
+ le32_to_cpu(req->Flags));
+ }
+
+ buf_free_len =
+ smb2_calc_max_out_buf_len(work, 8,
+ le32_to_cpu(req->OutputBufferLength));
+ if (buf_free_len < 0)
+ return -EINVAL;
+
+ rc = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
+ if (rc < 0) {
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+ goto out;
+ } else if (!rc) { /* there is no EA in the file */
+ ksmbd_debug(SMB, "no ea data in the file\n");
+ goto done;
+ }
+ xattr_list_len = rc;
+
+ ptr = (char *)rsp->Buffer;
+ eainfo = (struct smb2_ea_info *)ptr;
+ prev_eainfo = eainfo;
+ idx = 0;
+
+ while (idx < xattr_list_len) {
+ name = xattr_list + idx;
+ name_len = strlen(name);
+
+ ksmbd_debug(SMB, "%s, len %d\n", name, name_len);
+ idx += name_len + 1;
+
+ /*
+ * CIFS does not support EA other than user.* namespace,
+ * still keep the framework generic, to list other attrs
+ * in future.
+ */
+ if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+ continue;
+
+ if (!strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
+ STREAM_PREFIX_LEN))
+ continue;
+
+ if (req->InputBufferLength &&
+ strncmp(&name[XATTR_USER_PREFIX_LEN], ea_req->name,
+ ea_req->EaNameLength))
+ continue;
+
+ if (!strncmp(&name[XATTR_USER_PREFIX_LEN],
+ DOS_ATTRIBUTE_PREFIX, DOS_ATTRIBUTE_PREFIX_LEN))
+ continue;
+
+ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+ name_len -= XATTR_USER_PREFIX_LEN;
+
+ ptr = (char *)(&eainfo->name + name_len + 1);
+ buf_free_len -= (offsetof(struct smb2_ea_info, name) +
+ name_len + 1);
+ /* bailout if xattr can't fit in buf_free_len */
+ value_len = ksmbd_vfs_getxattr(user_ns, path->dentry,
+ name, &buf);
+ if (value_len <= 0) {
+ rc = -ENOENT;
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+ goto out;
+ }
+
+ buf_free_len -= value_len;
+ if (buf_free_len < 0) {
+ kfree(buf);
+ break;
+ }
+
+ memcpy(ptr, buf, value_len);
+ kfree(buf);
+
+ ptr += value_len;
+ eainfo->Flags = 0;
+ eainfo->EaNameLength = name_len;
+
+ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+ memcpy(eainfo->name, &name[XATTR_USER_PREFIX_LEN],
+ name_len);
+ else
+ memcpy(eainfo->name, name, name_len);
+
+ eainfo->name[name_len] = '\0';
+ eainfo->EaValueLength = cpu_to_le16(value_len);
+ next_offset = offsetof(struct smb2_ea_info, name) +
+ name_len + 1 + value_len;
+
+ /* align next xattr entry at 4 byte bundary */
+ alignment_bytes = ((next_offset + 3) & ~3) - next_offset;
+ if (alignment_bytes) {
+ memset(ptr, '\0', alignment_bytes);
+ ptr += alignment_bytes;
+ next_offset += alignment_bytes;
+ buf_free_len -= alignment_bytes;
+ }
+ eainfo->NextEntryOffset = cpu_to_le32(next_offset);
+ prev_eainfo = eainfo;
+ eainfo = (struct smb2_ea_info *)ptr;
+ rsp_data_cnt += next_offset;
+
+ if (req->InputBufferLength) {
+ ksmbd_debug(SMB, "single entry requested\n");
+ break;
+ }
+ }
+
+ /* no more ea entries */
+ prev_eainfo->NextEntryOffset = 0;
+done:
+ rc = 0;
+ if (rsp_data_cnt == 0)
+ rsp->hdr.Status = STATUS_NO_EAS_ON_FILE;
+ rsp->OutputBufferLength = cpu_to_le32(rsp_data_cnt);
+ inc_rfc1001_len(rsp_org, rsp_data_cnt);
+out:
+ kvfree(xattr_list);
+ return rc;
+}
+
+static void get_file_access_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb2_file_access_info *file_info;
+
+ file_info = (struct smb2_file_access_info *)rsp->Buffer;
+ file_info->AccessFlags = fp->daccess;
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_access_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_access_info));
+}
+
+static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb2_file_basic_info *basic_info;
+ struct kstat stat;
+ u64 time;
+
+ if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
+ pr_err("no right to read the attributes : 0x%x\n",
+ fp->daccess);
+ return -EACCES;
+ }
+
+ basic_info = (struct smb2_file_basic_info *)rsp->Buffer;
+ generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
+ &stat);
+ basic_info->CreationTime = cpu_to_le64(fp->create_time);
+ time = ksmbd_UnixTimeToNT(stat.atime);
+ basic_info->LastAccessTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(stat.mtime);
+ basic_info->LastWriteTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(stat.ctime);
+ basic_info->ChangeTime = cpu_to_le64(time);
+ basic_info->Attributes = fp->f_ci->m_fattr;
+ basic_info->Pad1 = 0;
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_basic_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_basic_info));
+ return 0;
+}
+
+static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb2_file_standard_info *sinfo;
+ unsigned int delete_pending;
+ struct inode *inode;
+ struct kstat stat;
+
+ inode = file_inode(fp->filp);
+ generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
+
+ sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
+ delete_pending = ksmbd_inode_pending_delete(fp);
+
+ sinfo->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
+ sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
+ sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
+ sinfo->DeletePending = delete_pending;
+ sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0;
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_standard_info));
+ inc_rfc1001_len(rsp_org,
+ sizeof(struct smb2_file_standard_info));
+}
+
+static void get_file_alignment_info(struct smb2_query_info_rsp *rsp,
+ void *rsp_org)
+{
+ struct smb2_file_alignment_info *file_info;
+
+ file_info = (struct smb2_file_alignment_info *)rsp->Buffer;
+ file_info->AlignmentRequirement = 0;
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_alignment_info));
+ inc_rfc1001_len(rsp_org,
+ sizeof(struct smb2_file_alignment_info));
+}
+
+static int get_file_all_info(struct ksmbd_work *work,
+ struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp,
+ void *rsp_org)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_file_all_info *file_info;
+ unsigned int delete_pending;
+ struct inode *inode;
+ struct kstat stat;
+ int conv_len;
+ char *filename;
+ u64 time;
+
+ if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
+ ksmbd_debug(SMB, "no right to read the attributes : 0x%x\n",
+ fp->daccess);
+ return -EACCES;
+ }
+
+ filename = convert_to_nt_pathname(work->tcon->share_conf, &fp->filp->f_path);
+ if (IS_ERR(filename))
+ return PTR_ERR(filename);
+
+ inode = file_inode(fp->filp);
+ generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
+
+ ksmbd_debug(SMB, "filename = %s\n", filename);
+ delete_pending = ksmbd_inode_pending_delete(fp);
+ file_info = (struct smb2_file_all_info *)rsp->Buffer;
+
+ file_info->CreationTime = cpu_to_le64(fp->create_time);
+ time = ksmbd_UnixTimeToNT(stat.atime);
+ file_info->LastAccessTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(stat.mtime);
+ file_info->LastWriteTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(stat.ctime);
+ file_info->ChangeTime = cpu_to_le64(time);
+ file_info->Attributes = fp->f_ci->m_fattr;
+ file_info->Pad1 = 0;
+ file_info->AllocationSize =
+ cpu_to_le64(inode->i_blocks << 9);
+ file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
+ file_info->NumberOfLinks =
+ cpu_to_le32(get_nlink(&stat) - delete_pending);
+ file_info->DeletePending = delete_pending;
+ file_info->Directory = S_ISDIR(stat.mode) ? 1 : 0;
+ file_info->Pad2 = 0;
+ file_info->IndexNumber = cpu_to_le64(stat.ino);
+ file_info->EASize = 0;
+ file_info->AccessFlags = fp->daccess;
+ file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
+ file_info->Mode = fp->coption;
+ file_info->AlignmentRequirement = 0;
+ conv_len = smbConvertToUTF16((__le16 *)file_info->FileName, filename,
+ PATH_MAX, conn->local_nls, 0);
+ conv_len *= 2;
+ file_info->FileNameLength = cpu_to_le32(conv_len);
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_all_info) + conv_len - 1);
+ kfree(filename);
+ inc_rfc1001_len(rsp_org, le32_to_cpu(rsp->OutputBufferLength));
+ return 0;
+}
+
+static void get_file_alternate_info(struct ksmbd_work *work,
+ struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp,
+ void *rsp_org)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_file_alt_name_info *file_info;
+ struct dentry *dentry = fp->filp->f_path.dentry;
+ int conv_len;
+
+ spin_lock(&dentry->d_lock);
+ file_info = (struct smb2_file_alt_name_info *)rsp->Buffer;
+ conv_len = ksmbd_extract_shortname(conn,
+ dentry->d_name.name,
+ file_info->FileName);
+ spin_unlock(&dentry->d_lock);
+ file_info->FileNameLength = cpu_to_le32(conv_len);
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len);
+ inc_rfc1001_len(rsp_org, le32_to_cpu(rsp->OutputBufferLength));
+}
+
+static void get_file_stream_info(struct ksmbd_work *work,
+ struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp,
+ void *rsp_org)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_file_stream_info *file_info;
+ char *stream_name, *xattr_list = NULL, *stream_buf;
+ struct kstat stat;
+ const struct path *path = &fp->filp->f_path;
+ ssize_t xattr_list_len;
+ int nbytes = 0, streamlen, stream_name_len, next, idx = 0;
+ int buf_free_len;
+ struct smb2_query_info_req *req = ksmbd_req_buf_next(work);
+
+ generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
+ &stat);
+ file_info = (struct smb2_file_stream_info *)rsp->Buffer;
+
+ buf_free_len =
+ smb2_calc_max_out_buf_len(work, 8,
+ le32_to_cpu(req->OutputBufferLength));
+ if (buf_free_len < 0)
+ goto out;
+
+ xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
+ if (xattr_list_len < 0) {
+ goto out;
+ } else if (!xattr_list_len) {
+ ksmbd_debug(SMB, "empty xattr in the file\n");
+ goto out;
+ }
+
+ while (idx < xattr_list_len) {
+ stream_name = xattr_list + idx;
+ streamlen = strlen(stream_name);
+ idx += streamlen + 1;
+
+ ksmbd_debug(SMB, "%s, len %d\n", stream_name, streamlen);
+
+ if (strncmp(&stream_name[XATTR_USER_PREFIX_LEN],
+ STREAM_PREFIX, STREAM_PREFIX_LEN))
+ continue;
+
+ stream_name_len = streamlen - (XATTR_USER_PREFIX_LEN +
+ STREAM_PREFIX_LEN);
+ streamlen = stream_name_len;
+
+ /* plus : size */
+ streamlen += 1;
+ stream_buf = kmalloc(streamlen + 1, GFP_KERNEL);
+ if (!stream_buf)
+ break;
+
+ streamlen = snprintf(stream_buf, streamlen + 1,
+ ":%s", &stream_name[XATTR_NAME_STREAM_LEN]);
+
+ next = sizeof(struct smb2_file_stream_info) + streamlen * 2;
+ if (next > buf_free_len) {
+ kfree(stream_buf);
+ break;
+ }
+
+ file_info = (struct smb2_file_stream_info *)&rsp->Buffer[nbytes];
+ streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName,
+ stream_buf, streamlen,
+ conn->local_nls, 0);
+ streamlen *= 2;
+ kfree(stream_buf);
+ file_info->StreamNameLength = cpu_to_le32(streamlen);
+ file_info->StreamSize = cpu_to_le64(stream_name_len);
+ file_info->StreamAllocationSize = cpu_to_le64(stream_name_len);
+
+ nbytes += next;
+ buf_free_len -= next;
+ file_info->NextEntryOffset = cpu_to_le32(next);
+ }
+
+out:
+ if (!S_ISDIR(stat.mode) &&
+ buf_free_len >= sizeof(struct smb2_file_stream_info) + 7 * 2) {
+ file_info = (struct smb2_file_stream_info *)
+ &rsp->Buffer[nbytes];
+ streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName,
+ "::$DATA", 7, conn->local_nls, 0);
+ streamlen *= 2;
+ file_info->StreamNameLength = cpu_to_le32(streamlen);
+ file_info->StreamSize = cpu_to_le64(stat.size);
+ file_info->StreamAllocationSize = cpu_to_le64(stat.blocks << 9);
+ nbytes += sizeof(struct smb2_file_stream_info) + streamlen;
+ }
+
+ /* last entry offset should be 0 */
+ file_info->NextEntryOffset = 0;
+ kvfree(xattr_list);
+
+ rsp->OutputBufferLength = cpu_to_le32(nbytes);
+ inc_rfc1001_len(rsp_org, nbytes);
+}
+
+static void get_file_internal_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb2_file_internal_info *file_info;
+ struct kstat stat;
+
+ generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
+ &stat);
+ file_info = (struct smb2_file_internal_info *)rsp->Buffer;
+ file_info->IndexNumber = cpu_to_le64(stat.ino);
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_internal_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_internal_info));
+}
+
+static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb2_file_ntwrk_info *file_info;
+ struct inode *inode;
+ struct kstat stat;
+ u64 time;
+
+ if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
+ pr_err("no right to read the attributes : 0x%x\n",
+ fp->daccess);
+ return -EACCES;
+ }
+
+ file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer;
+
+ inode = file_inode(fp->filp);
+ generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat);
+
+ file_info->CreationTime = cpu_to_le64(fp->create_time);
+ time = ksmbd_UnixTimeToNT(stat.atime);
+ file_info->LastAccessTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(stat.mtime);
+ file_info->LastWriteTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(stat.ctime);
+ file_info->ChangeTime = cpu_to_le64(time);
+ file_info->Attributes = fp->f_ci->m_fattr;
+ file_info->AllocationSize =
+ cpu_to_le64(inode->i_blocks << 9);
+ file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
+ file_info->Reserved = cpu_to_le32(0);
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_ntwrk_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_ntwrk_info));
+ return 0;
+}
+
+static void get_file_ea_info(struct smb2_query_info_rsp *rsp, void *rsp_org)
+{
+ struct smb2_file_ea_info *file_info;
+
+ file_info = (struct smb2_file_ea_info *)rsp->Buffer;
+ file_info->EASize = 0;
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_ea_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_ea_info));
+}
+
+static void get_file_position_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb2_file_pos_info *file_info;
+
+ file_info = (struct smb2_file_pos_info *)rsp->Buffer;
+ file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_pos_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_pos_info));
+}
+
+static void get_file_mode_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb2_file_mode_info *file_info;
+
+ file_info = (struct smb2_file_mode_info *)rsp->Buffer;
+ file_info->Mode = fp->coption & FILE_MODE_INFO_MASK;
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_mode_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_mode_info));
+}
+
+static void get_file_compression_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb2_file_comp_info *file_info;
+ struct kstat stat;
+
+ generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp),
+ &stat);
+
+ file_info = (struct smb2_file_comp_info *)rsp->Buffer;
+ file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9);
+ file_info->CompressionFormat = COMPRESSION_FORMAT_NONE;
+ file_info->CompressionUnitShift = 0;
+ file_info->ChunkShift = 0;
+ file_info->ClusterShift = 0;
+ memset(&file_info->Reserved[0], 0, 3);
+
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_comp_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_comp_info));
+}
+
+static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb2_file_attr_tag_info *file_info;
+
+ if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
+ pr_err("no right to read the attributes : 0x%x\n",
+ fp->daccess);
+ return -EACCES;
+ }
+
+ file_info = (struct smb2_file_attr_tag_info *)rsp->Buffer;
+ file_info->FileAttributes = fp->f_ci->m_fattr;
+ file_info->ReparseTag = 0;
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_attr_tag_info));
+ inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_attr_tag_info));
+ return 0;
+}
+
+static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+{
+ struct smb311_posix_qinfo *file_info;
+ struct inode *inode = file_inode(fp->filp);
+ struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
+ vfsuid_t vfsuid = i_uid_into_vfsuid(user_ns, inode);
+ vfsgid_t vfsgid = i_gid_into_vfsgid(user_ns, inode);
+ u64 time;
+ int out_buf_len = sizeof(struct smb311_posix_qinfo) + 32;
+
+ file_info = (struct smb311_posix_qinfo *)rsp->Buffer;
+ file_info->CreationTime = cpu_to_le64(fp->create_time);
+ time = ksmbd_UnixTimeToNT(inode->i_atime);
+ file_info->LastAccessTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(inode->i_mtime);
+ file_info->LastWriteTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(inode->i_ctime);
+ file_info->ChangeTime = cpu_to_le64(time);
+ file_info->DosAttributes = fp->f_ci->m_fattr;
+ file_info->Inode = cpu_to_le64(inode->i_ino);
+ file_info->EndOfFile = cpu_to_le64(inode->i_size);
+ file_info->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
+ file_info->HardLinks = cpu_to_le32(inode->i_nlink);
+ file_info->Mode = cpu_to_le32(inode->i_mode & 0777);
+ file_info->DeviceId = cpu_to_le32(inode->i_rdev);
+
+ /*
+ * Sids(32) contain two sids(Domain sid(16), UNIX group sid(16)).
+ * UNIX sid(16) = revision(1) + num_subauth(1) + authority(6) +
+ * sub_auth(4 * 1(num_subauth)) + RID(4).
+ */
+ id_to_sid(from_kuid_munged(&init_user_ns, vfsuid_into_kuid(vfsuid)),
+ SIDUNIX_USER, (struct smb_sid *)&file_info->Sids[0]);
+ id_to_sid(from_kgid_munged(&init_user_ns, vfsgid_into_kgid(vfsgid)),
+ SIDUNIX_GROUP, (struct smb_sid *)&file_info->Sids[16]);
+
+ rsp->OutputBufferLength = cpu_to_le32(out_buf_len);
+ inc_rfc1001_len(rsp_org, out_buf_len);
+ return out_buf_len;
+}
+
+static int smb2_get_info_file(struct ksmbd_work *work,
+ struct smb2_query_info_req *req,
+ struct smb2_query_info_rsp *rsp)
+{
+ struct ksmbd_file *fp;
+ int fileinfoclass = 0;
+ int rc = 0;
+ int file_infoclass_size;
+ unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
+
+ if (test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_PIPE)) {
+ /* smb2 info file called for pipe */
+ return smb2_get_info_file_pipe(work->sess, req, rsp,
+ work->response_buf);
+ }
+
+ if (work->next_smb2_rcv_hdr_off) {
+ if (!has_file_id(req->VolatileFileId)) {
+ ksmbd_debug(SMB, "Compound request set FID = %llu\n",
+ work->compound_fid);
+ id = work->compound_fid;
+ pid = work->compound_pfid;
+ }
+ }
+
+ if (!has_file_id(id)) {
+ id = req->VolatileFileId;
+ pid = req->PersistentFileId;
+ }
+
+ fp = ksmbd_lookup_fd_slow(work, id, pid);
+ if (!fp)
+ return -ENOENT;
+
+ fileinfoclass = req->FileInfoClass;
+
+ switch (fileinfoclass) {
+ case FILE_ACCESS_INFORMATION:
+ get_file_access_info(rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_ACCESS_INFORMATION_SIZE;
+ break;
+
+ case FILE_BASIC_INFORMATION:
+ rc = get_file_basic_info(rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_BASIC_INFORMATION_SIZE;
+ break;
+
+ case FILE_STANDARD_INFORMATION:
+ get_file_standard_info(rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_STANDARD_INFORMATION_SIZE;
+ break;
+
+ case FILE_ALIGNMENT_INFORMATION:
+ get_file_alignment_info(rsp, work->response_buf);
+ file_infoclass_size = FILE_ALIGNMENT_INFORMATION_SIZE;
+ break;
+
+ case FILE_ALL_INFORMATION:
+ rc = get_file_all_info(work, rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_ALL_INFORMATION_SIZE;
+ break;
+
+ case FILE_ALTERNATE_NAME_INFORMATION:
+ get_file_alternate_info(work, rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_ALTERNATE_NAME_INFORMATION_SIZE;
+ break;
+
+ case FILE_STREAM_INFORMATION:
+ get_file_stream_info(work, rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_STREAM_INFORMATION_SIZE;
+ break;
+
+ case FILE_INTERNAL_INFORMATION:
+ get_file_internal_info(rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_INTERNAL_INFORMATION_SIZE;
+ break;
+
+ case FILE_NETWORK_OPEN_INFORMATION:
+ rc = get_file_network_open_info(rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_NETWORK_OPEN_INFORMATION_SIZE;
+ break;
+
+ case FILE_EA_INFORMATION:
+ get_file_ea_info(rsp, work->response_buf);
+ file_infoclass_size = FILE_EA_INFORMATION_SIZE;
+ break;
+
+ case FILE_FULL_EA_INFORMATION:
+ rc = smb2_get_ea(work, fp, req, rsp, work->response_buf);
+ file_infoclass_size = FILE_FULL_EA_INFORMATION_SIZE;
+ break;
+
+ case FILE_POSITION_INFORMATION:
+ get_file_position_info(rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_POSITION_INFORMATION_SIZE;
+ break;
+
+ case FILE_MODE_INFORMATION:
+ get_file_mode_info(rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_MODE_INFORMATION_SIZE;
+ break;
+
+ case FILE_COMPRESSION_INFORMATION:
+ get_file_compression_info(rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_COMPRESSION_INFORMATION_SIZE;
+ break;
+
+ case FILE_ATTRIBUTE_TAG_INFORMATION:
+ rc = get_file_attribute_tag_info(rsp, fp, work->response_buf);
+ file_infoclass_size = FILE_ATTRIBUTE_TAG_INFORMATION_SIZE;
+ break;
+ case SMB_FIND_FILE_POSIX_INFO:
+ if (!work->tcon->posix_extensions) {
+ pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
+ rc = -EOPNOTSUPP;
+ } else {
+ file_infoclass_size = find_file_posix_info(rsp, fp,
+ work->response_buf);
+ }
+ break;
+ default:
+ ksmbd_debug(SMB, "fileinfoclass %d not supported yet\n",
+ fileinfoclass);
+ rc = -EOPNOTSUPP;
+ }
+ if (!rc)
+ rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
+ rsp, work->response_buf,
+ file_infoclass_size);
+ ksmbd_fd_put(work, fp);
+ return rc;
+}
+
+static int smb2_get_info_filesystem(struct ksmbd_work *work,
+ struct smb2_query_info_req *req,
+ struct smb2_query_info_rsp *rsp)
+{
+ struct ksmbd_session *sess = work->sess;
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_share_config *share = work->tcon->share_conf;
+ int fsinfoclass = 0;
+ struct kstatfs stfs;
+ struct path path;
+ int rc = 0, len;
+ int fs_infoclass_size = 0;
+
+ if (!share->path)
+ return -EIO;
+
+ rc = kern_path(share->path, LOOKUP_NO_SYMLINKS, &path);
+ if (rc) {
+ pr_err("cannot create vfs path\n");
+ return -EIO;
+ }
+
+ rc = vfs_statfs(&path, &stfs);
+ if (rc) {
+ pr_err("cannot do stat of path %s\n", share->path);
+ path_put(&path);
+ return -EIO;
+ }
+
+ fsinfoclass = req->FileInfoClass;
+
+ switch (fsinfoclass) {
+ case FS_DEVICE_INFORMATION:
+ {
+ struct filesystem_device_info *info;
+
+ info = (struct filesystem_device_info *)rsp->Buffer;
+
+ info->DeviceType = cpu_to_le32(stfs.f_type);
+ info->DeviceCharacteristics = cpu_to_le32(0x00000020);
+ rsp->OutputBufferLength = cpu_to_le32(8);
+ inc_rfc1001_len(work->response_buf, 8);
+ fs_infoclass_size = FS_DEVICE_INFORMATION_SIZE;
+ break;
+ }
+ case FS_ATTRIBUTE_INFORMATION:
+ {
+ struct filesystem_attribute_info *info;
+ size_t sz;
+
+ info = (struct filesystem_attribute_info *)rsp->Buffer;
+ info->Attributes = cpu_to_le32(FILE_SUPPORTS_OBJECT_IDS |
+ FILE_PERSISTENT_ACLS |
+ FILE_UNICODE_ON_DISK |
+ FILE_CASE_PRESERVED_NAMES |
+ FILE_CASE_SENSITIVE_SEARCH |
+ FILE_SUPPORTS_BLOCK_REFCOUNTING);
+
+ info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
+
+ if (test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_STREAMS))
+ info->Attributes |= cpu_to_le32(FILE_NAMED_STREAMS);
+
+ info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen);
+ len = smbConvertToUTF16((__le16 *)info->FileSystemName,
+ "NTFS", PATH_MAX, conn->local_nls, 0);
+ len = len * 2;
+ info->FileSystemNameLen = cpu_to_le32(len);
+ sz = sizeof(struct filesystem_attribute_info) - 2 + len;
+ rsp->OutputBufferLength = cpu_to_le32(sz);
+ inc_rfc1001_len(work->response_buf, sz);
+ fs_infoclass_size = FS_ATTRIBUTE_INFORMATION_SIZE;
+ break;
+ }
+ case FS_VOLUME_INFORMATION:
+ {
+ struct filesystem_vol_info *info;
+ size_t sz;
+ unsigned int serial_crc = 0;
+
+ info = (struct filesystem_vol_info *)(rsp->Buffer);
+ info->VolumeCreationTime = 0;
+ serial_crc = crc32_le(serial_crc, share->name,
+ strlen(share->name));
+ serial_crc = crc32_le(serial_crc, share->path,
+ strlen(share->path));
+ serial_crc = crc32_le(serial_crc, ksmbd_netbios_name(),
+ strlen(ksmbd_netbios_name()));
+ /* Taking dummy value of serial number*/
+ info->SerialNumber = cpu_to_le32(serial_crc);
+ len = smbConvertToUTF16((__le16 *)info->VolumeLabel,
+ share->name, PATH_MAX,
+ conn->local_nls, 0);
+ len = len * 2;
+ info->VolumeLabelSize = cpu_to_le32(len);
+ info->Reserved = 0;
+ sz = sizeof(struct filesystem_vol_info) - 2 + len;
+ rsp->OutputBufferLength = cpu_to_le32(sz);
+ inc_rfc1001_len(work->response_buf, sz);
+ fs_infoclass_size = FS_VOLUME_INFORMATION_SIZE;
+ break;
+ }
+ case FS_SIZE_INFORMATION:
+ {
+ struct filesystem_info *info;
+
+ info = (struct filesystem_info *)(rsp->Buffer);
+ info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks);
+ info->FreeAllocationUnits = cpu_to_le64(stfs.f_bfree);
+ info->SectorsPerAllocationUnit = cpu_to_le32(1);
+ info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
+ rsp->OutputBufferLength = cpu_to_le32(24);
+ inc_rfc1001_len(work->response_buf, 24);
+ fs_infoclass_size = FS_SIZE_INFORMATION_SIZE;
+ break;
+ }
+ case FS_FULL_SIZE_INFORMATION:
+ {
+ struct smb2_fs_full_size_info *info;
+
+ info = (struct smb2_fs_full_size_info *)(rsp->Buffer);
+ info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks);
+ info->CallerAvailableAllocationUnits =
+ cpu_to_le64(stfs.f_bavail);
+ info->ActualAvailableAllocationUnits =
+ cpu_to_le64(stfs.f_bfree);
+ info->SectorsPerAllocationUnit = cpu_to_le32(1);
+ info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
+ rsp->OutputBufferLength = cpu_to_le32(32);
+ inc_rfc1001_len(work->response_buf, 32);
+ fs_infoclass_size = FS_FULL_SIZE_INFORMATION_SIZE;
+ break;
+ }
+ case FS_OBJECT_ID_INFORMATION:
+ {
+ struct object_id_info *info;
+
+ info = (struct object_id_info *)(rsp->Buffer);
+
+ if (!user_guest(sess->user))
+ memcpy(info->objid, user_passkey(sess->user), 16);
+ else
+ memset(info->objid, 0, 16);
+
+ info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC);
+ info->extended_info.version = cpu_to_le32(1);
+ info->extended_info.release = cpu_to_le32(1);
+ info->extended_info.rel_date = 0;
+ memcpy(info->extended_info.version_string, "1.1.0", strlen("1.1.0"));
+ rsp->OutputBufferLength = cpu_to_le32(64);
+ inc_rfc1001_len(work->response_buf, 64);
+ fs_infoclass_size = FS_OBJECT_ID_INFORMATION_SIZE;
+ break;
+ }
+ case FS_SECTOR_SIZE_INFORMATION:
+ {
+ struct smb3_fs_ss_info *info;
+ unsigned int sector_size =
+ min_t(unsigned int, path.mnt->mnt_sb->s_blocksize, 4096);
+
+ info = (struct smb3_fs_ss_info *)(rsp->Buffer);
+
+ info->LogicalBytesPerSector = cpu_to_le32(sector_size);
+ info->PhysicalBytesPerSectorForAtomicity =
+ cpu_to_le32(sector_size);
+ info->PhysicalBytesPerSectorForPerf = cpu_to_le32(sector_size);
+ info->FSEffPhysicalBytesPerSectorForAtomicity =
+ cpu_to_le32(sector_size);
+ info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE |
+ SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
+ info->ByteOffsetForSectorAlignment = 0;
+ info->ByteOffsetForPartitionAlignment = 0;
+ rsp->OutputBufferLength = cpu_to_le32(28);
+ inc_rfc1001_len(work->response_buf, 28);
+ fs_infoclass_size = FS_SECTOR_SIZE_INFORMATION_SIZE;
+ break;
+ }
+ case FS_CONTROL_INFORMATION:
+ {
+ /*
+ * TODO : The current implementation is based on
+ * test result with win7(NTFS) server. It's need to
+ * modify this to get valid Quota values
+ * from Linux kernel
+ */
+ struct smb2_fs_control_info *info;
+
+ info = (struct smb2_fs_control_info *)(rsp->Buffer);
+ info->FreeSpaceStartFiltering = 0;
+ info->FreeSpaceThreshold = 0;
+ info->FreeSpaceStopFiltering = 0;
+ info->DefaultQuotaThreshold = cpu_to_le64(SMB2_NO_FID);
+ info->DefaultQuotaLimit = cpu_to_le64(SMB2_NO_FID);
+ info->Padding = 0;
+ rsp->OutputBufferLength = cpu_to_le32(48);
+ inc_rfc1001_len(work->response_buf, 48);
+ fs_infoclass_size = FS_CONTROL_INFORMATION_SIZE;
+ break;
+ }
+ case FS_POSIX_INFORMATION:
+ {
+ struct filesystem_posix_info *info;
+
+ if (!work->tcon->posix_extensions) {
+ pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
+ rc = -EOPNOTSUPP;
+ } else {
+ info = (struct filesystem_posix_info *)(rsp->Buffer);
+ info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize);
+ info->BlockSize = cpu_to_le32(stfs.f_bsize);
+ info->TotalBlocks = cpu_to_le64(stfs.f_blocks);
+ info->BlocksAvail = cpu_to_le64(stfs.f_bfree);
+ info->UserBlocksAvail = cpu_to_le64(stfs.f_bavail);
+ info->TotalFileNodes = cpu_to_le64(stfs.f_files);
+ info->FreeFileNodes = cpu_to_le64(stfs.f_ffree);
+ rsp->OutputBufferLength = cpu_to_le32(56);
+ inc_rfc1001_len(work->response_buf, 56);
+ fs_infoclass_size = FS_POSIX_INFORMATION_SIZE;
+ }
+ break;
+ }
+ default:
+ path_put(&path);
+ return -EOPNOTSUPP;
+ }
+ rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
+ rsp, work->response_buf,
+ fs_infoclass_size);
+ path_put(&path);
+ return rc;
+}
+
+static int smb2_get_info_sec(struct ksmbd_work *work,
+ struct smb2_query_info_req *req,
+ struct smb2_query_info_rsp *rsp)
+{
+ struct ksmbd_file *fp;
+ struct user_namespace *user_ns;
+ struct smb_ntsd *pntsd = (struct smb_ntsd *)rsp->Buffer, *ppntsd = NULL;
+ struct smb_fattr fattr = {{0}};
+ struct inode *inode;
+ __u32 secdesclen = 0;
+ unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
+ int addition_info = le32_to_cpu(req->AdditionalInformation);
+ int rc = 0, ppntsd_size = 0;
+
+ if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
+ PROTECTED_DACL_SECINFO |
+ UNPROTECTED_DACL_SECINFO)) {
+ ksmbd_debug(SMB, "Unsupported addition info: 0x%x)\n",
+ addition_info);
+
+ pntsd->revision = cpu_to_le16(1);
+ pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PROTECTED);
+ pntsd->osidoffset = 0;
+ pntsd->gsidoffset = 0;
+ pntsd->sacloffset = 0;
+ pntsd->dacloffset = 0;
+
+ secdesclen = sizeof(struct smb_ntsd);
+ rsp->OutputBufferLength = cpu_to_le32(secdesclen);
+ inc_rfc1001_len(work->response_buf, secdesclen);
+
+ return 0;
+ }
+
+ if (work->next_smb2_rcv_hdr_off) {
+ if (!has_file_id(req->VolatileFileId)) {
+ ksmbd_debug(SMB, "Compound request set FID = %llu\n",
+ work->compound_fid);
+ id = work->compound_fid;
+ pid = work->compound_pfid;
+ }
+ }
+
+ if (!has_file_id(id)) {
+ id = req->VolatileFileId;
+ pid = req->PersistentFileId;
+ }
+
+ fp = ksmbd_lookup_fd_slow(work, id, pid);
+ if (!fp)
+ return -ENOENT;
+
+ user_ns = file_mnt_user_ns(fp->filp);
+ inode = file_inode(fp->filp);
+ ksmbd_acls_fattr(&fattr, user_ns, inode);
+
+ if (test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_ACL_XATTR))
+ ppntsd_size = ksmbd_vfs_get_sd_xattr(work->conn, user_ns,
+ fp->filp->f_path.dentry,
+ &ppntsd);
+
+ /* Check if sd buffer size exceeds response buffer size */
+ if (smb2_resp_buf_len(work, 8) > ppntsd_size)
+ rc = build_sec_desc(user_ns, pntsd, ppntsd, ppntsd_size,
+ addition_info, &secdesclen, &fattr);
+ posix_acl_release(fattr.cf_acls);
+ posix_acl_release(fattr.cf_dacls);
+ kfree(ppntsd);
+ ksmbd_fd_put(work, fp);
+ if (rc)
+ return rc;
+
+ rsp->OutputBufferLength = cpu_to_le32(secdesclen);
+ inc_rfc1001_len(work->response_buf, secdesclen);
+ return 0;
+}
+
+/**
+ * smb2_query_info() - handler for smb2 query info command
+ * @work: smb work containing query info request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_query_info(struct ksmbd_work *work)
+{
+ struct smb2_query_info_req *req;
+ struct smb2_query_info_rsp *rsp;
+ int rc = 0;
+
+ WORK_BUFFERS(work, req, rsp);
+
+ ksmbd_debug(SMB, "GOT query info request\n");
+
+ switch (req->InfoType) {
+ case SMB2_O_INFO_FILE:
+ ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n");
+ rc = smb2_get_info_file(work, req, rsp);
+ break;
+ case SMB2_O_INFO_FILESYSTEM:
+ ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILESYSTEM\n");
+ rc = smb2_get_info_filesystem(work, req, rsp);
+ break;
+ case SMB2_O_INFO_SECURITY:
+ ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n");
+ rc = smb2_get_info_sec(work, req, rsp);
+ break;
+ default:
+ ksmbd_debug(SMB, "InfoType %d not supported yet\n",
+ req->InfoType);
+ rc = -EOPNOTSUPP;
+ }
+
+ if (rc < 0) {
+ if (rc == -EACCES)
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ else if (rc == -ENOENT)
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ else if (rc == -EIO)
+ rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
+ else if (rc == -EOPNOTSUPP || rsp->hdr.Status == 0)
+ rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
+ smb2_set_err_rsp(work);
+
+ ksmbd_debug(SMB, "error while processing smb2 query rc = %d\n",
+ rc);
+ return rc;
+ }
+ rsp->StructureSize = cpu_to_le16(9);
+ rsp->OutputBufferOffset = cpu_to_le16(72);
+ inc_rfc1001_len(work->response_buf, 8);
+ return 0;
+}
+
+/**
+ * smb2_close_pipe() - handler for closing IPC pipe
+ * @work: smb work containing close request buffer
+ *
+ * Return: 0
+ */
+static noinline int smb2_close_pipe(struct ksmbd_work *work)
+{
+ u64 id;
+ struct smb2_close_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_close_rsp *rsp = smb2_get_msg(work->response_buf);
+
+ id = req->VolatileFileId;
+ ksmbd_session_rpc_close(work->sess, id);
+
+ rsp->StructureSize = cpu_to_le16(60);
+ rsp->Flags = 0;
+ rsp->Reserved = 0;
+ rsp->CreationTime = 0;
+ rsp->LastAccessTime = 0;
+ rsp->LastWriteTime = 0;
+ rsp->ChangeTime = 0;
+ rsp->AllocationSize = 0;
+ rsp->EndOfFile = 0;
+ rsp->Attributes = 0;
+ inc_rfc1001_len(work->response_buf, 60);
+ return 0;
+}
+
+/**
+ * smb2_close() - handler for smb2 close file command
+ * @work: smb work containing close request buffer
+ *
+ * Return: 0
+ */
+int smb2_close(struct ksmbd_work *work)
+{
+ u64 volatile_id = KSMBD_NO_FID;
+ u64 sess_id;
+ struct smb2_close_req *req;
+ struct smb2_close_rsp *rsp;
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_file *fp;
+ struct inode *inode;
+ u64 time;
+ int err = 0;
+
+ WORK_BUFFERS(work, req, rsp);
+
+ if (test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_PIPE)) {
+ ksmbd_debug(SMB, "IPC pipe close request\n");
+ return smb2_close_pipe(work);
+ }
+
+ sess_id = le64_to_cpu(req->hdr.SessionId);
+ if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)
+ sess_id = work->compound_sid;
+
+ work->compound_sid = 0;
+ if (check_session_id(conn, sess_id)) {
+ work->compound_sid = sess_id;
+ } else {
+ rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
+ if (req->hdr.Flags & SMB2_FLAGS_RELATED_OPERATIONS)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ err = -EBADF;
+ goto out;
+ }
+
+ if (work->next_smb2_rcv_hdr_off &&
+ !has_file_id(req->VolatileFileId)) {
+ if (!has_file_id(work->compound_fid)) {
+ /* file already closed, return FILE_CLOSED */
+ ksmbd_debug(SMB, "file already closed\n");
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ err = -EBADF;
+ goto out;
+ } else {
+ ksmbd_debug(SMB,
+ "Compound request set FID = %llu:%llu\n",
+ work->compound_fid,
+ work->compound_pfid);
+ volatile_id = work->compound_fid;
+
+ /* file closed, stored id is not valid anymore */
+ work->compound_fid = KSMBD_NO_FID;
+ work->compound_pfid = KSMBD_NO_FID;
+ }
+ } else {
+ volatile_id = req->VolatileFileId;
+ }
+ ksmbd_debug(SMB, "volatile_id = %llu\n", volatile_id);
+
+ rsp->StructureSize = cpu_to_le16(60);
+ rsp->Reserved = 0;
+
+ if (req->Flags == SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB) {
+ fp = ksmbd_lookup_fd_fast(work, volatile_id);
+ if (!fp) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ inode = file_inode(fp->filp);
+ rsp->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB;
+ rsp->AllocationSize = S_ISDIR(inode->i_mode) ? 0 :
+ cpu_to_le64(inode->i_blocks << 9);
+ rsp->EndOfFile = cpu_to_le64(inode->i_size);
+ rsp->Attributes = fp->f_ci->m_fattr;
+ rsp->CreationTime = cpu_to_le64(fp->create_time);
+ time = ksmbd_UnixTimeToNT(inode->i_atime);
+ rsp->LastAccessTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(inode->i_mtime);
+ rsp->LastWriteTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(inode->i_ctime);
+ rsp->ChangeTime = cpu_to_le64(time);
+ ksmbd_fd_put(work, fp);
+ } else {
+ rsp->Flags = 0;
+ rsp->AllocationSize = 0;
+ rsp->EndOfFile = 0;
+ rsp->Attributes = 0;
+ rsp->CreationTime = 0;
+ rsp->LastAccessTime = 0;
+ rsp->LastWriteTime = 0;
+ rsp->ChangeTime = 0;
+ }
+
+ err = ksmbd_close_fd(work, volatile_id);
+out:
+ if (err) {
+ if (rsp->hdr.Status == 0)
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ smb2_set_err_rsp(work);
+ } else {
+ inc_rfc1001_len(work->response_buf, 60);
+ }
+
+ return 0;
+}
+
+/**
+ * smb2_echo() - handler for smb2 echo(ping) command
+ * @work: smb work containing echo request buffer
+ *
+ * Return: 0
+ */
+int smb2_echo(struct ksmbd_work *work)
+{
+ struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf);
+
+ rsp->StructureSize = cpu_to_le16(4);
+ rsp->Reserved = 0;
+ inc_rfc1001_len(work->response_buf, 4);
+ return 0;
+}
+
+static int smb2_rename(struct ksmbd_work *work,
+ struct ksmbd_file *fp,
+ struct user_namespace *user_ns,
+ struct smb2_file_rename_info *file_info,
+ struct nls_table *local_nls)
+{
+ struct ksmbd_share_config *share = fp->tcon->share_conf;
+ char *new_name = NULL, *abs_oldname = NULL, *old_name = NULL;
+ char *pathname = NULL;
+ struct path path;
+ bool file_present = true;
+ int rc;
+
+ ksmbd_debug(SMB, "setting FILE_RENAME_INFO\n");
+ pathname = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!pathname)
+ return -ENOMEM;
+
+ abs_oldname = file_path(fp->filp, pathname, PATH_MAX);
+ if (IS_ERR(abs_oldname)) {
+ rc = -EINVAL;
+ goto out;
+ }
+ old_name = strrchr(abs_oldname, '/');
+ if (old_name && old_name[1] != '\0') {
+ old_name++;
+ } else {
+ ksmbd_debug(SMB, "can't get last component in path %s\n",
+ abs_oldname);
+ rc = -ENOENT;
+ goto out;
+ }
+
+ new_name = smb2_get_name(file_info->FileName,
+ le32_to_cpu(file_info->FileNameLength),
+ local_nls);
+ if (IS_ERR(new_name)) {
+ rc = PTR_ERR(new_name);
+ goto out;
+ }
+
+ if (strchr(new_name, ':')) {
+ int s_type;
+ char *xattr_stream_name, *stream_name = NULL;
+ size_t xattr_stream_size;
+ int len;
+
+ rc = parse_stream_name(new_name, &stream_name, &s_type);
+ if (rc < 0)
+ goto out;
+
+ len = strlen(new_name);
+ if (len > 0 && new_name[len - 1] != '/') {
+ pr_err("not allow base filename in rename\n");
+ rc = -ESHARE;
+ goto out;
+ }
+
+ rc = ksmbd_vfs_xattr_stream_name(stream_name,
+ &xattr_stream_name,
+ &xattr_stream_size,
+ s_type);
+ if (rc)
+ goto out;
+
+ rc = ksmbd_vfs_setxattr(user_ns,
+ fp->filp->f_path.dentry,
+ xattr_stream_name,
+ NULL, 0, 0);
+ if (rc < 0) {
+ pr_err("failed to store stream name in xattr: %d\n",
+ rc);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ goto out;
+ }
+
+ ksmbd_debug(SMB, "new name %s\n", new_name);
+ rc = ksmbd_vfs_kern_path(work, new_name, LOOKUP_NO_SYMLINKS, &path, 1);
+ if (rc) {
+ if (rc != -ENOENT)
+ goto out;
+ file_present = false;
+ } else {
+ path_put(&path);
+ }
+
+ if (ksmbd_share_veto_filename(share, new_name)) {
+ rc = -ENOENT;
+ ksmbd_debug(SMB, "Can't rename vetoed file: %s\n", new_name);
+ goto out;
+ }
+
+ if (file_info->ReplaceIfExists) {
+ if (file_present) {
+ rc = ksmbd_vfs_remove_file(work, new_name);
+ if (rc) {
+ if (rc != -ENOTEMPTY)
+ rc = -EINVAL;
+ ksmbd_debug(SMB, "cannot delete %s, rc %d\n",
+ new_name, rc);
+ goto out;
+ }
+ }
+ } else {
+ if (file_present &&
+ strncmp(old_name, path.dentry->d_name.name, strlen(old_name))) {
+ rc = -EEXIST;
+ ksmbd_debug(SMB,
+ "cannot rename already existing file\n");
+ goto out;
+ }
+ }
+
+ rc = ksmbd_vfs_fp_rename(work, fp, new_name);
+out:
+ kfree(pathname);
+ if (!IS_ERR(new_name))
+ kfree(new_name);
+ return rc;
+}
+
+static int smb2_create_link(struct ksmbd_work *work,
+ struct ksmbd_share_config *share,
+ struct smb2_file_link_info *file_info,
+ unsigned int buf_len, struct file *filp,
+ struct nls_table *local_nls)
+{
+ char *link_name = NULL, *target_name = NULL, *pathname = NULL;
+ struct path path;
+ bool file_present = true;
+ int rc;
+
+ if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
+ le32_to_cpu(file_info->FileNameLength))
+ return -EINVAL;
+
+ ksmbd_debug(SMB, "setting FILE_LINK_INFORMATION\n");
+ pathname = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!pathname)
+ return -ENOMEM;
+
+ link_name = smb2_get_name(file_info->FileName,
+ le32_to_cpu(file_info->FileNameLength),
+ local_nls);
+ if (IS_ERR(link_name) || S_ISDIR(file_inode(filp)->i_mode)) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ ksmbd_debug(SMB, "link name is %s\n", link_name);
+ target_name = file_path(filp, pathname, PATH_MAX);
+ if (IS_ERR(target_name)) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ ksmbd_debug(SMB, "target name is %s\n", target_name);
+ rc = ksmbd_vfs_kern_path(work, link_name, LOOKUP_NO_SYMLINKS, &path, 0);
+ if (rc) {
+ if (rc != -ENOENT)
+ goto out;
+ file_present = false;
+ } else {
+ path_put(&path);
+ }
+
+ if (file_info->ReplaceIfExists) {
+ if (file_present) {
+ rc = ksmbd_vfs_remove_file(work, link_name);
+ if (rc) {
+ rc = -EINVAL;
+ ksmbd_debug(SMB, "cannot delete %s\n",
+ link_name);
+ goto out;
+ }
+ }
+ } else {
+ if (file_present) {
+ rc = -EEXIST;
+ ksmbd_debug(SMB, "link already exists\n");
+ goto out;
+ }
+ }
+
+ rc = ksmbd_vfs_link(work, target_name, link_name);
+ if (rc)
+ rc = -EINVAL;
+out:
+ if (!IS_ERR(link_name))
+ kfree(link_name);
+ kfree(pathname);
+ return rc;
+}
+
+static int set_file_basic_info(struct ksmbd_file *fp,
+ struct smb2_file_basic_info *file_info,
+ struct ksmbd_share_config *share)
+{
+ struct iattr attrs;
+ struct file *filp;
+ struct inode *inode;
+ struct user_namespace *user_ns;
+ int rc = 0;
+
+ if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE))
+ return -EACCES;
+
+ attrs.ia_valid = 0;
+ filp = fp->filp;
+ inode = file_inode(filp);
+ user_ns = file_mnt_user_ns(filp);
+
+ if (file_info->CreationTime)
+ fp->create_time = le64_to_cpu(file_info->CreationTime);
+
+ if (file_info->LastAccessTime) {
+ attrs.ia_atime = ksmbd_NTtimeToUnix(file_info->LastAccessTime);
+ attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
+ }
+
+ attrs.ia_valid |= ATTR_CTIME;
+ if (file_info->ChangeTime)
+ attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
+ else
+ attrs.ia_ctime = inode->i_ctime;
+
+ if (file_info->LastWriteTime) {
+ attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime);
+ attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
+ }
+
+ if (file_info->Attributes) {
+ if (!S_ISDIR(inode->i_mode) &&
+ file_info->Attributes & FILE_ATTRIBUTE_DIRECTORY_LE) {
+ pr_err("can't change a file to a directory\n");
+ return -EINVAL;
+ }
+
+ if (!(S_ISDIR(inode->i_mode) && file_info->Attributes == FILE_ATTRIBUTE_NORMAL_LE))
+ fp->f_ci->m_fattr = file_info->Attributes |
+ (fp->f_ci->m_fattr & FILE_ATTRIBUTE_DIRECTORY_LE);
+ }
+
+ if (test_share_config_flag(share, KSMBD_SHARE_FLAG_STORE_DOS_ATTRS) &&
+ (file_info->CreationTime || file_info->Attributes)) {
+ struct xattr_dos_attrib da = {0};
+
+ da.version = 4;
+ da.itime = fp->itime;
+ da.create_time = fp->create_time;
+ da.attr = le32_to_cpu(fp->f_ci->m_fattr);
+ da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
+ XATTR_DOSINFO_ITIME;
+
+ rc = ksmbd_vfs_set_dos_attrib_xattr(user_ns,
+ filp->f_path.dentry, &da);
+ if (rc)
+ ksmbd_debug(SMB,
+ "failed to restore file attribute in EA\n");
+ rc = 0;
+ }
+
+ if (attrs.ia_valid) {
+ struct dentry *dentry = filp->f_path.dentry;
+ struct inode *inode = d_inode(dentry);
+
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ return -EACCES;
+
+ inode_lock(inode);
+ inode->i_ctime = attrs.ia_ctime;
+ attrs.ia_valid &= ~ATTR_CTIME;
+ rc = notify_change(user_ns, dentry, &attrs, NULL);
+ inode_unlock(inode);
+ }
+ return rc;
+}
+
+static int set_file_allocation_info(struct ksmbd_work *work,
+ struct ksmbd_file *fp,
+ struct smb2_file_alloc_info *file_alloc_info)
+{
+ /*
+ * TODO : It's working fine only when store dos attributes
+ * is not yes. need to implement a logic which works
+ * properly with any smb.conf option
+ */
+
+ loff_t alloc_blks;
+ struct inode *inode;
+ int rc;
+
+ if (!(fp->daccess & FILE_WRITE_DATA_LE))
+ return -EACCES;
+
+ alloc_blks = (le64_to_cpu(file_alloc_info->AllocationSize) + 511) >> 9;
+ inode = file_inode(fp->filp);
+
+ if (alloc_blks > inode->i_blocks) {
+ smb_break_all_levII_oplock(work, fp, 1);
+ rc = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
+ alloc_blks * 512);
+ if (rc && rc != -EOPNOTSUPP) {
+ pr_err("vfs_fallocate is failed : %d\n", rc);
+ return rc;
+ }
+ } else if (alloc_blks < inode->i_blocks) {
+ loff_t size;
+
+ /*
+ * Allocation size could be smaller than original one
+ * which means allocated blocks in file should be
+ * deallocated. use truncate to cut out it, but inode
+ * size is also updated with truncate offset.
+ * inode size is retained by backup inode size.
+ */
+ size = i_size_read(inode);
+ rc = ksmbd_vfs_truncate(work, fp, alloc_blks * 512);
+ if (rc) {
+ pr_err("truncate failed!, err %d\n", rc);
+ return rc;
+ }
+ if (size < alloc_blks * 512)
+ i_size_write(inode, size);
+ }
+ return 0;
+}
+
+static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp,
+ struct smb2_file_eof_info *file_eof_info)
+{
+ loff_t newsize;
+ struct inode *inode;
+ int rc;
+
+ if (!(fp->daccess & FILE_WRITE_DATA_LE))
+ return -EACCES;
+
+ newsize = le64_to_cpu(file_eof_info->EndOfFile);
+ inode = file_inode(fp->filp);
+
+ /*
+ * If FILE_END_OF_FILE_INFORMATION of set_info_file is called
+ * on FAT32 shared device, truncate execution time is too long
+ * and network error could cause from windows client. because
+ * truncate of some filesystem like FAT32 fill zero data in
+ * truncated range.
+ */
+ if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) {
+ ksmbd_debug(SMB, "truncated to newsize %lld\n", newsize);
+ rc = ksmbd_vfs_truncate(work, fp, newsize);
+ if (rc) {
+ ksmbd_debug(SMB, "truncate failed!, err %d\n", rc);
+ if (rc != -EAGAIN)
+ rc = -EBADF;
+ return rc;
+ }
+ }
+ return 0;
+}
+
+static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
+ struct smb2_file_rename_info *rename_info,
+ unsigned int buf_len)
+{
+ struct user_namespace *user_ns;
+ struct ksmbd_file *parent_fp;
+ struct dentry *parent;
+ struct dentry *dentry = fp->filp->f_path.dentry;
+ int ret;
+
+ if (!(fp->daccess & FILE_DELETE_LE)) {
+ pr_err("no right to delete : 0x%x\n", fp->daccess);
+ return -EACCES;
+ }
+
+ if (buf_len < (u64)sizeof(struct smb2_file_rename_info) +
+ le32_to_cpu(rename_info->FileNameLength))
+ return -EINVAL;
+
+ user_ns = file_mnt_user_ns(fp->filp);
+ if (ksmbd_stream_fd(fp))
+ goto next;
+
+ parent = dget_parent(dentry);
+ ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
+ if (ret) {
+ dput(parent);
+ return ret;
+ }
+
+ parent_fp = ksmbd_lookup_fd_inode(d_inode(parent));
+ inode_unlock(d_inode(parent));
+ dput(parent);
+
+ if (parent_fp) {
+ if (parent_fp->daccess & FILE_DELETE_LE) {
+ pr_err("parent dir is opened with delete access\n");
+ ksmbd_fd_put(work, parent_fp);
+ return -ESHARE;
+ }
+ ksmbd_fd_put(work, parent_fp);
+ }
+next:
+ return smb2_rename(work, fp, user_ns, rename_info,
+ work->conn->local_nls);
+}
+
+static int set_file_disposition_info(struct ksmbd_file *fp,
+ struct smb2_file_disposition_info *file_info)
+{
+ struct inode *inode;
+
+ if (!(fp->daccess & FILE_DELETE_LE)) {
+ pr_err("no right to delete : 0x%x\n", fp->daccess);
+ return -EACCES;
+ }
+
+ inode = file_inode(fp->filp);
+ if (file_info->DeletePending) {
+ if (S_ISDIR(inode->i_mode) &&
+ ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY)
+ return -EBUSY;
+ ksmbd_set_inode_pending_delete(fp);
+ } else {
+ ksmbd_clear_inode_pending_delete(fp);
+ }
+ return 0;
+}
+
+static int set_file_position_info(struct ksmbd_file *fp,
+ struct smb2_file_pos_info *file_info)
+{
+ loff_t current_byte_offset;
+ unsigned long sector_size;
+ struct inode *inode;
+
+ inode = file_inode(fp->filp);
+ current_byte_offset = le64_to_cpu(file_info->CurrentByteOffset);
+ sector_size = inode->i_sb->s_blocksize;
+
+ if (current_byte_offset < 0 ||
+ (fp->coption == FILE_NO_INTERMEDIATE_BUFFERING_LE &&
+ current_byte_offset & (sector_size - 1))) {
+ pr_err("CurrentByteOffset is not valid : %llu\n",
+ current_byte_offset);
+ return -EINVAL;
+ }
+
+ fp->filp->f_pos = current_byte_offset;
+ return 0;
+}
+
+static int set_file_mode_info(struct ksmbd_file *fp,
+ struct smb2_file_mode_info *file_info)
+{
+ __le32 mode;
+
+ mode = file_info->Mode;
+
+ if ((mode & ~FILE_MODE_INFO_MASK)) {
+ pr_err("Mode is not valid : 0x%x\n", le32_to_cpu(mode));
+ return -EINVAL;
+ }
+
+ /*
+ * TODO : need to implement consideration for
+ * FILE_SYNCHRONOUS_IO_ALERT and FILE_SYNCHRONOUS_IO_NONALERT
+ */
+ ksmbd_vfs_set_fadvise(fp->filp, mode);
+ fp->coption = mode;
+ return 0;
+}
+
+/**
+ * smb2_set_info_file() - handler for smb2 set info command
+ * @work: smb work containing set info command buffer
+ * @fp: ksmbd_file pointer
+ * @req: request buffer pointer
+ * @share: ksmbd_share_config pointer
+ *
+ * Return: 0 on success, otherwise error
+ * TODO: need to implement an error handling for STATUS_INFO_LENGTH_MISMATCH
+ */
+static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ struct smb2_set_info_req *req,
+ struct ksmbd_share_config *share)
+{
+ unsigned int buf_len = le32_to_cpu(req->BufferLength);
+
+ switch (req->FileInfoClass) {
+ case FILE_BASIC_INFORMATION:
+ {
+ if (buf_len < sizeof(struct smb2_file_basic_info))
+ return -EINVAL;
+
+ return set_file_basic_info(fp, (struct smb2_file_basic_info *)req->Buffer, share);
+ }
+ case FILE_ALLOCATION_INFORMATION:
+ {
+ if (buf_len < sizeof(struct smb2_file_alloc_info))
+ return -EINVAL;
+
+ return set_file_allocation_info(work, fp,
+ (struct smb2_file_alloc_info *)req->Buffer);
+ }
+ case FILE_END_OF_FILE_INFORMATION:
+ {
+ if (buf_len < sizeof(struct smb2_file_eof_info))
+ return -EINVAL;
+
+ return set_end_of_file_info(work, fp,
+ (struct smb2_file_eof_info *)req->Buffer);
+ }
+ case FILE_RENAME_INFORMATION:
+ {
+ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+ ksmbd_debug(SMB,
+ "User does not have write permission\n");
+ return -EACCES;
+ }
+
+ if (buf_len < sizeof(struct smb2_file_rename_info))
+ return -EINVAL;
+
+ return set_rename_info(work, fp,
+ (struct smb2_file_rename_info *)req->Buffer,
+ buf_len);
+ }
+ case FILE_LINK_INFORMATION:
+ {
+ if (buf_len < sizeof(struct smb2_file_link_info))
+ return -EINVAL;
+
+ return smb2_create_link(work, work->tcon->share_conf,
+ (struct smb2_file_link_info *)req->Buffer,
+ buf_len, fp->filp,
+ work->conn->local_nls);
+ }
+ case FILE_DISPOSITION_INFORMATION:
+ {
+ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+ ksmbd_debug(SMB,
+ "User does not have write permission\n");
+ return -EACCES;
+ }
+
+ if (buf_len < sizeof(struct smb2_file_disposition_info))
+ return -EINVAL;
+
+ return set_file_disposition_info(fp,
+ (struct smb2_file_disposition_info *)req->Buffer);
+ }
+ case FILE_FULL_EA_INFORMATION:
+ {
+ if (!(fp->daccess & FILE_WRITE_EA_LE)) {
+ pr_err("Not permitted to write ext attr: 0x%x\n",
+ fp->daccess);
+ return -EACCES;
+ }
+
+ if (buf_len < sizeof(struct smb2_ea_info))
+ return -EINVAL;
+
+ return smb2_set_ea((struct smb2_ea_info *)req->Buffer,
+ buf_len, &fp->filp->f_path);
+ }
+ case FILE_POSITION_INFORMATION:
+ {
+ if (buf_len < sizeof(struct smb2_file_pos_info))
+ return -EINVAL;
+
+ return set_file_position_info(fp, (struct smb2_file_pos_info *)req->Buffer);
+ }
+ case FILE_MODE_INFORMATION:
+ {
+ if (buf_len < sizeof(struct smb2_file_mode_info))
+ return -EINVAL;
+
+ return set_file_mode_info(fp, (struct smb2_file_mode_info *)req->Buffer);
+ }
+ }
+
+ pr_err("Unimplemented Fileinfoclass :%d\n", req->FileInfoClass);
+ return -EOPNOTSUPP;
+}
+
+static int smb2_set_info_sec(struct ksmbd_file *fp, int addition_info,
+ char *buffer, int buf_len)
+{
+ struct smb_ntsd *pntsd = (struct smb_ntsd *)buffer;
+
+ fp->saccess |= FILE_SHARE_DELETE_LE;
+
+ return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd,
+ buf_len, false);
+}
+
+/**
+ * smb2_set_info() - handler for smb2 set info command handler
+ * @work: smb work containing set info request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_set_info(struct ksmbd_work *work)
+{
+ struct smb2_set_info_req *req;
+ struct smb2_set_info_rsp *rsp;
+ struct ksmbd_file *fp;
+ int rc = 0;
+ unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
+
+ ksmbd_debug(SMB, "Received set info request\n");
+
+ if (work->next_smb2_rcv_hdr_off) {
+ req = ksmbd_req_buf_next(work);
+ rsp = ksmbd_resp_buf_next(work);
+ if (!has_file_id(req->VolatileFileId)) {
+ ksmbd_debug(SMB, "Compound request set FID = %llu\n",
+ work->compound_fid);
+ id = work->compound_fid;
+ pid = work->compound_pfid;
+ }
+ } else {
+ req = smb2_get_msg(work->request_buf);
+ rsp = smb2_get_msg(work->response_buf);
+ }
+
+ if (!has_file_id(id)) {
+ id = req->VolatileFileId;
+ pid = req->PersistentFileId;
+ }
+
+ fp = ksmbd_lookup_fd_slow(work, id, pid);
+ if (!fp) {
+ ksmbd_debug(SMB, "Invalid id for close: %u\n", id);
+ rc = -ENOENT;
+ goto err_out;
+ }
+
+ switch (req->InfoType) {
+ case SMB2_O_INFO_FILE:
+ ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n");
+ rc = smb2_set_info_file(work, fp, req, work->tcon->share_conf);
+ break;
+ case SMB2_O_INFO_SECURITY:
+ ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n");
+ if (ksmbd_override_fsids(work)) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ rc = smb2_set_info_sec(fp,
+ le32_to_cpu(req->AdditionalInformation),
+ req->Buffer,
+ le32_to_cpu(req->BufferLength));
+ ksmbd_revert_fsids(work);
+ break;
+ default:
+ rc = -EOPNOTSUPP;
+ }
+
+ if (rc < 0)
+ goto err_out;
+
+ rsp->StructureSize = cpu_to_le16(2);
+ inc_rfc1001_len(work->response_buf, 2);
+ ksmbd_fd_put(work, fp);
+ return 0;
+
+err_out:
+ if (rc == -EACCES || rc == -EPERM || rc == -EXDEV)
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ else if (rc == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else if (rc == -ESHARE)
+ rsp->hdr.Status = STATUS_SHARING_VIOLATION;
+ else if (rc == -ENOENT)
+ rsp->hdr.Status = STATUS_OBJECT_NAME_INVALID;
+ else if (rc == -EBUSY || rc == -ENOTEMPTY)
+ rsp->hdr.Status = STATUS_DIRECTORY_NOT_EMPTY;
+ else if (rc == -EAGAIN)
+ rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
+ else if (rc == -EBADF || rc == -ESTALE)
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+ else if (rc == -EEXIST)
+ rsp->hdr.Status = STATUS_OBJECT_NAME_COLLISION;
+ else if (rsp->hdr.Status == 0 || rc == -EOPNOTSUPP)
+ rsp->hdr.Status = STATUS_INVALID_INFO_CLASS;
+ smb2_set_err_rsp(work);
+ ksmbd_fd_put(work, fp);
+ ksmbd_debug(SMB, "error while processing smb2 query rc = %d\n", rc);
+ return rc;
+}
+
+/**
+ * smb2_read_pipe() - handler for smb2 read from IPC pipe
+ * @work: smb work containing read IPC pipe command buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+static noinline int smb2_read_pipe(struct ksmbd_work *work)
+{
+ int nbytes = 0, err;
+ u64 id;
+ struct ksmbd_rpc_command *rpc_resp;
+ struct smb2_read_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_read_rsp *rsp = smb2_get_msg(work->response_buf);
+
+ id = req->VolatileFileId;
+
+ inc_rfc1001_len(work->response_buf, 16);
+ rpc_resp = ksmbd_rpc_read(work->sess, id);
+ if (rpc_resp) {
+ if (rpc_resp->flags != KSMBD_RPC_OK) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ work->aux_payload_buf =
+ kvmalloc(rpc_resp->payload_sz, GFP_KERNEL | __GFP_ZERO);
+ if (!work->aux_payload_buf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(work->aux_payload_buf, rpc_resp->payload,
+ rpc_resp->payload_sz);
+
+ nbytes = rpc_resp->payload_sz;
+ work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
+ work->aux_payload_sz = nbytes;
+ kvfree(rpc_resp);
+ }
+
+ rsp->StructureSize = cpu_to_le16(17);
+ rsp->DataOffset = 80;
+ rsp->Reserved = 0;
+ rsp->DataLength = cpu_to_le32(nbytes);
+ rsp->DataRemaining = 0;
+ rsp->Flags = 0;
+ inc_rfc1001_len(work->response_buf, nbytes);
+ return 0;
+
+out:
+ rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
+ smb2_set_err_rsp(work);
+ kvfree(rpc_resp);
+ return err;
+}
+
+static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
+ struct smb2_buffer_desc_v1 *desc,
+ __le32 Channel,
+ __le16 ChannelInfoLength)
+{
+ unsigned int i, ch_count;
+
+ if (work->conn->dialect == SMB30_PROT_ID &&
+ Channel != SMB2_CHANNEL_RDMA_V1)
+ return -EINVAL;
+
+ ch_count = le16_to_cpu(ChannelInfoLength) / sizeof(*desc);
+ if (ksmbd_debug_types & KSMBD_DEBUG_RDMA) {
+ for (i = 0; i < ch_count; i++) {
+ pr_info("RDMA r/w request %#x: token %#x, length %#x\n",
+ i,
+ le32_to_cpu(desc[i].token),
+ le32_to_cpu(desc[i].length));
+ }
+ }
+ if (!ch_count)
+ return -EINVAL;
+
+ work->need_invalidate_rkey =
+ (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
+ if (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE)
+ work->remote_key = le32_to_cpu(desc->token);
+ return 0;
+}
+
+static ssize_t smb2_read_rdma_channel(struct ksmbd_work *work,
+ struct smb2_read_req *req, void *data_buf,
+ size_t length)
+{
+ int err;
+
+ err = ksmbd_conn_rdma_write(work->conn, data_buf, length,
+ (struct smb2_buffer_desc_v1 *)
+ ((char *)req + le16_to_cpu(req->ReadChannelInfoOffset)),
+ le16_to_cpu(req->ReadChannelInfoLength));
+ if (err)
+ return err;
+
+ return length;
+}
+
+/**
+ * smb2_read() - handler for smb2 read from file
+ * @work: smb work containing read command buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_read(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_read_req *req;
+ struct smb2_read_rsp *rsp;
+ struct ksmbd_file *fp = NULL;
+ loff_t offset;
+ size_t length, mincount;
+ ssize_t nbytes = 0, remain_bytes = 0;
+ int err = 0;
+ bool is_rdma_channel = false;
+ unsigned int max_read_size = conn->vals->max_read_size;
+
+ WORK_BUFFERS(work, req, rsp);
+
+ if (test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_PIPE)) {
+ ksmbd_debug(SMB, "IPC pipe read request\n");
+ return smb2_read_pipe(work);
+ }
+
+ if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
+ req->Channel == SMB2_CHANNEL_RDMA_V1) {
+ is_rdma_channel = true;
+ max_read_size = get_smbd_max_read_write_size();
+ }
+
+ if (is_rdma_channel == true) {
+ unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
+
+ if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
+ err = -EINVAL;
+ goto out;
+ }
+ err = smb2_set_remote_key_for_rdma(work,
+ (struct smb2_buffer_desc_v1 *)
+ ((char *)req + ch_offset),
+ req->Channel,
+ req->ReadChannelInfoLength);
+ if (err)
+ goto out;
+ }
+
+ fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
+ if (!fp) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_READ_ATTRIBUTES_LE))) {
+ pr_err("Not permitted to read : 0x%x\n", fp->daccess);
+ err = -EACCES;
+ goto out;
+ }
+
+ offset = le64_to_cpu(req->Offset);
+ length = le32_to_cpu(req->Length);
+ mincount = le32_to_cpu(req->MinimumCount);
+
+ if (length > max_read_size) {
+ ksmbd_debug(SMB, "limiting read size to max size(%u)\n",
+ max_read_size);
+ err = -EINVAL;
+ goto out;
+ }
+
+ ksmbd_debug(SMB, "filename %pD, offset %lld, len %zu\n",
+ fp->filp, offset, length);
+
+ work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
+ if (!work->aux_payload_buf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ nbytes = ksmbd_vfs_read(work, fp, length, &offset);
+ if (nbytes < 0) {
+ err = nbytes;
+ goto out;
+ }
+
+ if ((nbytes == 0 && length != 0) || nbytes < mincount) {
+ kvfree(work->aux_payload_buf);
+ work->aux_payload_buf = NULL;
+ rsp->hdr.Status = STATUS_END_OF_FILE;
+ smb2_set_err_rsp(work);
+ ksmbd_fd_put(work, fp);
+ return 0;
+ }
+
+ ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
+ nbytes, offset, mincount);
+
+ if (is_rdma_channel == true) {
+ /* write data to the client using rdma channel */
+ remain_bytes = smb2_read_rdma_channel(work, req,
+ work->aux_payload_buf,
+ nbytes);
+ kvfree(work->aux_payload_buf);
+ work->aux_payload_buf = NULL;
+
+ nbytes = 0;
+ if (remain_bytes < 0) {
+ err = (int)remain_bytes;
+ goto out;
+ }
+ }
+
+ rsp->StructureSize = cpu_to_le16(17);
+ rsp->DataOffset = 80;
+ rsp->Reserved = 0;
+ rsp->DataLength = cpu_to_le32(nbytes);
+ rsp->DataRemaining = cpu_to_le32(remain_bytes);
+ rsp->Flags = 0;
+ inc_rfc1001_len(work->response_buf, 16);
+ work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
+ work->aux_payload_sz = nbytes;
+ inc_rfc1001_len(work->response_buf, nbytes);
+ ksmbd_fd_put(work, fp);
+ return 0;
+
+out:
+ if (err) {
+ if (err == -EISDIR)
+ rsp->hdr.Status = STATUS_INVALID_DEVICE_REQUEST;
+ else if (err == -EAGAIN)
+ rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
+ else if (err == -ENOENT)
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ else if (err == -EACCES)
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ else if (err == -ESHARE)
+ rsp->hdr.Status = STATUS_SHARING_VIOLATION;
+ else if (err == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+
+ smb2_set_err_rsp(work);
+ }
+ ksmbd_fd_put(work, fp);
+ return err;
+}
+
+/**
+ * smb2_write_pipe() - handler for smb2 write on IPC pipe
+ * @work: smb work containing write IPC pipe command buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+static noinline int smb2_write_pipe(struct ksmbd_work *work)
+{
+ struct smb2_write_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_write_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct ksmbd_rpc_command *rpc_resp;
+ u64 id = 0;
+ int err = 0, ret = 0;
+ char *data_buf;
+ size_t length;
+
+ length = le32_to_cpu(req->Length);
+ id = req->VolatileFileId;
+
+ if ((u64)le16_to_cpu(req->DataOffset) + length >
+ get_rfc1002_len(work->request_buf)) {
+ pr_err("invalid write data offset %u, smb_len %u\n",
+ le16_to_cpu(req->DataOffset),
+ get_rfc1002_len(work->request_buf));
+ err = -EINVAL;
+ goto out;
+ }
+
+ data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
+ le16_to_cpu(req->DataOffset));
+
+ rpc_resp = ksmbd_rpc_write(work->sess, id, data_buf, length);
+ if (rpc_resp) {
+ if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) {
+ rsp->hdr.Status = STATUS_NOT_SUPPORTED;
+ kvfree(rpc_resp);
+ smb2_set_err_rsp(work);
+ return -EOPNOTSUPP;
+ }
+ if (rpc_resp->flags != KSMBD_RPC_OK) {
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+ smb2_set_err_rsp(work);
+ kvfree(rpc_resp);
+ return ret;
+ }
+ kvfree(rpc_resp);
+ }
+
+ rsp->StructureSize = cpu_to_le16(17);
+ rsp->DataOffset = 0;
+ rsp->Reserved = 0;
+ rsp->DataLength = cpu_to_le32(length);
+ rsp->DataRemaining = 0;
+ rsp->Reserved2 = 0;
+ inc_rfc1001_len(work->response_buf, 16);
+ return 0;
+out:
+ if (err) {
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+ smb2_set_err_rsp(work);
+ }
+
+ return err;
+}
+
+static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
+ struct smb2_write_req *req,
+ struct ksmbd_file *fp,
+ loff_t offset, size_t length, bool sync)
+{
+ char *data_buf;
+ int ret;
+ ssize_t nbytes;
+
+ data_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
+ if (!data_buf)
+ return -ENOMEM;
+
+ ret = ksmbd_conn_rdma_read(work->conn, data_buf, length,
+ (struct smb2_buffer_desc_v1 *)
+ ((char *)req + le16_to_cpu(req->WriteChannelInfoOffset)),
+ le16_to_cpu(req->WriteChannelInfoLength));
+ if (ret < 0) {
+ kvfree(data_buf);
+ return ret;
+ }
+
+ ret = ksmbd_vfs_write(work, fp, data_buf, length, &offset, sync, &nbytes);
+ kvfree(data_buf);
+ if (ret < 0)
+ return ret;
+
+ return nbytes;
+}
+
+/**
+ * smb2_write() - handler for smb2 write from file
+ * @work: smb work containing write command buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_write(struct ksmbd_work *work)
+{
+ struct smb2_write_req *req;
+ struct smb2_write_rsp *rsp;
+ struct ksmbd_file *fp = NULL;
+ loff_t offset;
+ size_t length;
+ ssize_t nbytes;
+ char *data_buf;
+ bool writethrough = false, is_rdma_channel = false;
+ int err = 0;
+ unsigned int max_write_size = work->conn->vals->max_write_size;
+
+ WORK_BUFFERS(work, req, rsp);
+
+ if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_PIPE)) {
+ ksmbd_debug(SMB, "IPC pipe write request\n");
+ return smb2_write_pipe(work);
+ }
+
+ offset = le64_to_cpu(req->Offset);
+ length = le32_to_cpu(req->Length);
+
+ if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
+ req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
+ is_rdma_channel = true;
+ max_write_size = get_smbd_max_read_write_size();
+ length = le32_to_cpu(req->RemainingBytes);
+ }
+
+ if (is_rdma_channel == true) {
+ unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
+
+ if (req->Length != 0 || req->DataOffset != 0 ||
+ ch_offset < offsetof(struct smb2_write_req, Buffer)) {
+ err = -EINVAL;
+ goto out;
+ }
+ err = smb2_set_remote_key_for_rdma(work,
+ (struct smb2_buffer_desc_v1 *)
+ ((char *)req + ch_offset),
+ req->Channel,
+ req->WriteChannelInfoLength);
+ if (err)
+ goto out;
+ }
+
+ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+ ksmbd_debug(SMB, "User does not have write permission\n");
+ err = -EACCES;
+ goto out;
+ }
+
+ fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
+ if (!fp) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_READ_ATTRIBUTES_LE))) {
+ pr_err("Not permitted to write : 0x%x\n", fp->daccess);
+ err = -EACCES;
+ goto out;
+ }
+
+ if (length > max_write_size) {
+ ksmbd_debug(SMB, "limiting write size to max size(%u)\n",
+ max_write_size);
+ err = -EINVAL;
+ goto out;
+ }
+
+ ksmbd_debug(SMB, "flags %u\n", le32_to_cpu(req->Flags));
+ if (le32_to_cpu(req->Flags) & SMB2_WRITEFLAG_WRITE_THROUGH)
+ writethrough = true;
+
+ if (is_rdma_channel == false) {
+ if (le16_to_cpu(req->DataOffset) <
+ offsetof(struct smb2_write_req, Buffer)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
+ le16_to_cpu(req->DataOffset));
+
+ ksmbd_debug(SMB, "filename %pD, offset %lld, len %zu\n",
+ fp->filp, offset, length);
+ err = ksmbd_vfs_write(work, fp, data_buf, length, &offset,
+ writethrough, &nbytes);
+ if (err < 0)
+ goto out;
+ } else {
+ /* read data from the client using rdma channel, and
+ * write the data.
+ */
+ nbytes = smb2_write_rdma_channel(work, req, fp, offset, length,
+ writethrough);
+ if (nbytes < 0) {
+ err = (int)nbytes;
+ goto out;
+ }
+ }
+
+ rsp->StructureSize = cpu_to_le16(17);
+ rsp->DataOffset = 0;
+ rsp->Reserved = 0;
+ rsp->DataLength = cpu_to_le32(nbytes);
+ rsp->DataRemaining = 0;
+ rsp->Reserved2 = 0;
+ inc_rfc1001_len(work->response_buf, 16);
+ ksmbd_fd_put(work, fp);
+ return 0;
+
+out:
+ if (err == -EAGAIN)
+ rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
+ else if (err == -ENOSPC || err == -EFBIG)
+ rsp->hdr.Status = STATUS_DISK_FULL;
+ else if (err == -ENOENT)
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ else if (err == -EACCES)
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ else if (err == -ESHARE)
+ rsp->hdr.Status = STATUS_SHARING_VIOLATION;
+ else if (err == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+
+ smb2_set_err_rsp(work);
+ ksmbd_fd_put(work, fp);
+ return err;
+}
+
+/**
+ * smb2_flush() - handler for smb2 flush file - fsync
+ * @work: smb work containing flush command buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_flush(struct ksmbd_work *work)
+{
+ struct smb2_flush_req *req;
+ struct smb2_flush_rsp *rsp;
+ int err;
+
+ WORK_BUFFERS(work, req, rsp);
+
+ ksmbd_debug(SMB, "SMB2_FLUSH called for fid %llu\n", req->VolatileFileId);
+
+ err = ksmbd_vfs_fsync(work, req->VolatileFileId, req->PersistentFileId);
+ if (err)
+ goto out;
+
+ rsp->StructureSize = cpu_to_le16(4);
+ rsp->Reserved = 0;
+ inc_rfc1001_len(work->response_buf, 4);
+ return 0;
+
+out:
+ if (err) {
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+ smb2_set_err_rsp(work);
+ }
+
+ return err;
+}
+
+/**
+ * smb2_cancel() - handler for smb2 cancel command
+ * @work: smb work containing cancel command buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_cancel(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
+ struct smb2_hdr *chdr;
+ struct ksmbd_work *iter;
+ struct list_head *command_list;
+
+ ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
+ hdr->MessageId, hdr->Flags);
+
+ if (hdr->Flags & SMB2_FLAGS_ASYNC_COMMAND) {
+ command_list = &conn->async_requests;
+
+ spin_lock(&conn->request_lock);
+ list_for_each_entry(iter, command_list,
+ async_request_entry) {
+ chdr = smb2_get_msg(iter->request_buf);
+
+ if (iter->async_id !=
+ le64_to_cpu(hdr->Id.AsyncId))
+ continue;
+
+ ksmbd_debug(SMB,
+ "smb2 with AsyncId %llu cancelled command = 0x%x\n",
+ le64_to_cpu(hdr->Id.AsyncId),
+ le16_to_cpu(chdr->Command));
+ iter->state = KSMBD_WORK_CANCELLED;
+ if (iter->cancel_fn)
+ iter->cancel_fn(iter->cancel_argv);
+ break;
+ }
+ spin_unlock(&conn->request_lock);
+ } else {
+ command_list = &conn->requests;
+
+ spin_lock(&conn->request_lock);
+ list_for_each_entry(iter, command_list, request_entry) {
+ chdr = smb2_get_msg(iter->request_buf);
+
+ if (chdr->MessageId != hdr->MessageId ||
+ iter == work)
+ continue;
+
+ ksmbd_debug(SMB,
+ "smb2 with mid %llu cancelled command = 0x%x\n",
+ le64_to_cpu(hdr->MessageId),
+ le16_to_cpu(chdr->Command));
+ iter->state = KSMBD_WORK_CANCELLED;
+ break;
+ }
+ spin_unlock(&conn->request_lock);
+ }
+
+ /* For SMB2_CANCEL command itself send no response*/
+ work->send_no_response = 1;
+ return 0;
+}
+
+struct file_lock *smb_flock_init(struct file *f)
+{
+ struct file_lock *fl;
+
+ fl = locks_alloc_lock();
+ if (!fl)
+ goto out;
+
+ locks_init_lock(fl);
+
+ fl->fl_owner = f;
+ fl->fl_pid = current->tgid;
+ fl->fl_file = f;
+ fl->fl_flags = FL_POSIX;
+ fl->fl_ops = NULL;
+ fl->fl_lmops = NULL;
+
+out:
+ return fl;
+}
+
+static int smb2_set_flock_flags(struct file_lock *flock, int flags)
+{
+ int cmd = -EINVAL;
+
+ /* Checking for wrong flag combination during lock request*/
+ switch (flags) {
+ case SMB2_LOCKFLAG_SHARED:
+ ksmbd_debug(SMB, "received shared request\n");
+ cmd = F_SETLKW;
+ flock->fl_type = F_RDLCK;
+ flock->fl_flags |= FL_SLEEP;
+ break;
+ case SMB2_LOCKFLAG_EXCLUSIVE:
+ ksmbd_debug(SMB, "received exclusive request\n");
+ cmd = F_SETLKW;
+ flock->fl_type = F_WRLCK;
+ flock->fl_flags |= FL_SLEEP;
+ break;
+ case SMB2_LOCKFLAG_SHARED | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
+ ksmbd_debug(SMB,
+ "received shared & fail immediately request\n");
+ cmd = F_SETLK;
+ flock->fl_type = F_RDLCK;
+ break;
+ case SMB2_LOCKFLAG_EXCLUSIVE | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
+ ksmbd_debug(SMB,
+ "received exclusive & fail immediately request\n");
+ cmd = F_SETLK;
+ flock->fl_type = F_WRLCK;
+ break;
+ case SMB2_LOCKFLAG_UNLOCK:
+ ksmbd_debug(SMB, "received unlock request\n");
+ flock->fl_type = F_UNLCK;
+ cmd = 0;
+ break;
+ }
+
+ return cmd;
+}
+
+static struct ksmbd_lock *smb2_lock_init(struct file_lock *flock,
+ unsigned int cmd, int flags,
+ struct list_head *lock_list)
+{
+ struct ksmbd_lock *lock;
+
+ lock = kzalloc(sizeof(struct ksmbd_lock), GFP_KERNEL);
+ if (!lock)
+ return NULL;
+
+ lock->cmd = cmd;
+ lock->fl = flock;
+ lock->start = flock->fl_start;
+ lock->end = flock->fl_end;
+ lock->flags = flags;
+ if (lock->start == lock->end)
+ lock->zero_len = 1;
+ INIT_LIST_HEAD(&lock->clist);
+ INIT_LIST_HEAD(&lock->flist);
+ INIT_LIST_HEAD(&lock->llist);
+ list_add_tail(&lock->llist, lock_list);
+
+ return lock;
+}
+
+static void smb2_remove_blocked_lock(void **argv)
+{
+ struct file_lock *flock = (struct file_lock *)argv[0];
+
+ ksmbd_vfs_posix_lock_unblock(flock);
+ wake_up(&flock->fl_wait);
+}
+
+static inline bool lock_defer_pending(struct file_lock *fl)
+{
+ /* check pending lock waiters */
+ return waitqueue_active(&fl->fl_wait);
+}
+
+/**
+ * smb2_lock() - handler for smb2 file lock command
+ * @work: smb work containing lock command buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_lock(struct ksmbd_work *work)
+{
+ struct smb2_lock_req *req = smb2_get_msg(work->request_buf);
+ struct smb2_lock_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_lock_element *lock_ele;
+ struct ksmbd_file *fp = NULL;
+ struct file_lock *flock = NULL;
+ struct file *filp = NULL;
+ int lock_count;
+ int flags = 0;
+ int cmd = 0;
+ int err = -EIO, i, rc = 0;
+ u64 lock_start, lock_length;
+ struct ksmbd_lock *smb_lock = NULL, *cmp_lock, *tmp, *tmp2;
+ struct ksmbd_conn *conn;
+ int nolock = 0;
+ LIST_HEAD(lock_list);
+ LIST_HEAD(rollback_list);
+ int prior_lock = 0;
+
+ ksmbd_debug(SMB, "Received lock request\n");
+ fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
+ if (!fp) {
+ ksmbd_debug(SMB, "Invalid file id for lock : %llu\n", req->VolatileFileId);
+ err = -ENOENT;
+ goto out2;
+ }
+
+ filp = fp->filp;
+ lock_count = le16_to_cpu(req->LockCount);
+ lock_ele = req->locks;
+
+ ksmbd_debug(SMB, "lock count is %d\n", lock_count);
+ if (!lock_count) {
+ err = -EINVAL;
+ goto out2;
+ }
+
+ for (i = 0; i < lock_count; i++) {
+ flags = le32_to_cpu(lock_ele[i].Flags);
+
+ flock = smb_flock_init(filp);
+ if (!flock)
+ goto out;
+
+ cmd = smb2_set_flock_flags(flock, flags);
+
+ lock_start = le64_to_cpu(lock_ele[i].Offset);
+ lock_length = le64_to_cpu(lock_ele[i].Length);
+ if (lock_start > U64_MAX - lock_length) {
+ pr_err("Invalid lock range requested\n");
+ rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE;
+ goto out;
+ }
+
+ if (lock_start > OFFSET_MAX)
+ flock->fl_start = OFFSET_MAX;
+ else
+ flock->fl_start = lock_start;
+
+ lock_length = le64_to_cpu(lock_ele[i].Length);
+ if (lock_length > OFFSET_MAX - flock->fl_start)
+ lock_length = OFFSET_MAX - flock->fl_start;
+
+ flock->fl_end = flock->fl_start + lock_length;
+
+ if (flock->fl_end < flock->fl_start) {
+ ksmbd_debug(SMB,
+ "the end offset(%llx) is smaller than the start offset(%llx)\n",
+ flock->fl_end, flock->fl_start);
+ rsp->hdr.Status = STATUS_INVALID_LOCK_RANGE;
+ goto out;
+ }
+
+ /* Check conflict locks in one request */
+ list_for_each_entry(cmp_lock, &lock_list, llist) {
+ if (cmp_lock->fl->fl_start <= flock->fl_start &&
+ cmp_lock->fl->fl_end >= flock->fl_end) {
+ if (cmp_lock->fl->fl_type != F_UNLCK &&
+ flock->fl_type != F_UNLCK) {
+ pr_err("conflict two locks in one request\n");
+ err = -EINVAL;
+ goto out;
+ }
+ }
+ }
+
+ smb_lock = smb2_lock_init(flock, cmd, flags, &lock_list);
+ if (!smb_lock) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ list_for_each_entry_safe(smb_lock, tmp, &lock_list, llist) {
+ if (smb_lock->cmd < 0) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (!(smb_lock->flags & SMB2_LOCKFLAG_MASK)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if ((prior_lock & (SMB2_LOCKFLAG_EXCLUSIVE | SMB2_LOCKFLAG_SHARED) &&
+ smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) ||
+ (prior_lock == SMB2_LOCKFLAG_UNLOCK &&
+ !(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK))) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ prior_lock = smb_lock->flags;
+
+ if (!(smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) &&
+ !(smb_lock->flags & SMB2_LOCKFLAG_FAIL_IMMEDIATELY))
+ goto no_check_cl;
+
+ nolock = 1;
+ /* check locks in connection list */
+ down_read(&conn_list_lock);
+ list_for_each_entry(conn, &conn_list, conns_list) {
+ spin_lock(&conn->llist_lock);
+ list_for_each_entry_safe(cmp_lock, tmp2, &conn->lock_list, clist) {
+ if (file_inode(cmp_lock->fl->fl_file) !=
+ file_inode(smb_lock->fl->fl_file))
+ continue;
+
+ if (smb_lock->fl->fl_type == F_UNLCK) {
+ if (cmp_lock->fl->fl_file == smb_lock->fl->fl_file &&
+ cmp_lock->start == smb_lock->start &&
+ cmp_lock->end == smb_lock->end &&
+ !lock_defer_pending(cmp_lock->fl)) {
+ nolock = 0;
+ list_del(&cmp_lock->flist);
+ list_del(&cmp_lock->clist);
+ spin_unlock(&conn->llist_lock);
+ up_read(&conn_list_lock);
+
+ locks_free_lock(cmp_lock->fl);
+ kfree(cmp_lock);
+ goto out_check_cl;
+ }
+ continue;
+ }
+
+ if (cmp_lock->fl->fl_file == smb_lock->fl->fl_file) {
+ if (smb_lock->flags & SMB2_LOCKFLAG_SHARED)
+ continue;
+ } else {
+ if (cmp_lock->flags & SMB2_LOCKFLAG_SHARED)
+ continue;
+ }
+
+ /* check zero byte lock range */
+ if (cmp_lock->zero_len && !smb_lock->zero_len &&
+ cmp_lock->start > smb_lock->start &&
+ cmp_lock->start < smb_lock->end) {
+ spin_unlock(&conn->llist_lock);
+ up_read(&conn_list_lock);
+ pr_err("previous lock conflict with zero byte lock range\n");
+ goto out;
+ }
+
+ if (smb_lock->zero_len && !cmp_lock->zero_len &&
+ smb_lock->start > cmp_lock->start &&
+ smb_lock->start < cmp_lock->end) {
+ spin_unlock(&conn->llist_lock);
+ up_read(&conn_list_lock);
+ pr_err("current lock conflict with zero byte lock range\n");
+ goto out;
+ }
+
+ if (((cmp_lock->start <= smb_lock->start &&
+ cmp_lock->end > smb_lock->start) ||
+ (cmp_lock->start < smb_lock->end &&
+ cmp_lock->end >= smb_lock->end)) &&
+ !cmp_lock->zero_len && !smb_lock->zero_len) {
+ spin_unlock(&conn->llist_lock);
+ up_read(&conn_list_lock);
+ pr_err("Not allow lock operation on exclusive lock range\n");
+ goto out;
+ }
+ }
+ spin_unlock(&conn->llist_lock);
+ }
+ up_read(&conn_list_lock);
+out_check_cl:
+ if (smb_lock->fl->fl_type == F_UNLCK && nolock) {
+ pr_err("Try to unlock nolocked range\n");
+ rsp->hdr.Status = STATUS_RANGE_NOT_LOCKED;
+ goto out;
+ }
+
+no_check_cl:
+ if (smb_lock->zero_len) {
+ err = 0;
+ goto skip;
+ }
+
+ flock = smb_lock->fl;
+ list_del(&smb_lock->llist);
+retry:
+ rc = vfs_lock_file(filp, smb_lock->cmd, flock, NULL);
+skip:
+ if (flags & SMB2_LOCKFLAG_UNLOCK) {
+ if (!rc) {
+ ksmbd_debug(SMB, "File unlocked\n");
+ } else if (rc == -ENOENT) {
+ rsp->hdr.Status = STATUS_NOT_LOCKED;
+ goto out;
+ }
+ locks_free_lock(flock);
+ kfree(smb_lock);
+ } else {
+ if (rc == FILE_LOCK_DEFERRED) {
+ void **argv;
+
+ ksmbd_debug(SMB,
+ "would have to wait for getting lock\n");
+ spin_lock(&work->conn->llist_lock);
+ list_add_tail(&smb_lock->clist,
+ &work->conn->lock_list);
+ spin_unlock(&work->conn->llist_lock);
+ list_add(&smb_lock->llist, &rollback_list);
+
+ argv = kmalloc(sizeof(void *), GFP_KERNEL);
+ if (!argv) {
+ err = -ENOMEM;
+ goto out;
+ }
+ argv[0] = flock;
+
+ rc = setup_async_work(work,
+ smb2_remove_blocked_lock,
+ argv);
+ if (rc) {
+ err = -ENOMEM;
+ goto out;
+ }
+ spin_lock(&fp->f_lock);
+ list_add(&work->fp_entry, &fp->blocked_works);
+ spin_unlock(&fp->f_lock);
+
+ smb2_send_interim_resp(work, STATUS_PENDING);
+
+ ksmbd_vfs_posix_lock_wait(flock);
+
+ spin_lock(&work->conn->request_lock);
+ spin_lock(&fp->f_lock);
+ list_del(&work->fp_entry);
+ work->cancel_fn = NULL;
+ kfree(argv);
+ spin_unlock(&fp->f_lock);
+ spin_unlock(&work->conn->request_lock);
+
+ if (work->state != KSMBD_WORK_ACTIVE) {
+ list_del(&smb_lock->llist);
+ spin_lock(&work->conn->llist_lock);
+ list_del(&smb_lock->clist);
+ spin_unlock(&work->conn->llist_lock);
+ locks_free_lock(flock);
+
+ if (work->state == KSMBD_WORK_CANCELLED) {
+ rsp->hdr.Status =
+ STATUS_CANCELLED;
+ kfree(smb_lock);
+ smb2_send_interim_resp(work,
+ STATUS_CANCELLED);
+ work->send_no_response = 1;
+ goto out;
+ }
+ init_smb2_rsp_hdr(work);
+ smb2_set_err_rsp(work);
+ rsp->hdr.Status =
+ STATUS_RANGE_NOT_LOCKED;
+ kfree(smb_lock);
+ goto out2;
+ }
+
+ list_del(&smb_lock->llist);
+ spin_lock(&work->conn->llist_lock);
+ list_del(&smb_lock->clist);
+ spin_unlock(&work->conn->llist_lock);
+
+ goto retry;
+ } else if (!rc) {
+ spin_lock(&work->conn->llist_lock);
+ list_add_tail(&smb_lock->clist,
+ &work->conn->lock_list);
+ list_add_tail(&smb_lock->flist,
+ &fp->lock_list);
+ spin_unlock(&work->conn->llist_lock);
+ list_add(&smb_lock->llist, &rollback_list);
+ ksmbd_debug(SMB, "successful in taking lock\n");
+ } else {
+ goto out;
+ }
+ }
+ }
+
+ if (atomic_read(&fp->f_ci->op_count) > 1)
+ smb_break_all_oplock(work, fp);
+
+ rsp->StructureSize = cpu_to_le16(4);
+ ksmbd_debug(SMB, "successful in taking lock\n");
+ rsp->hdr.Status = STATUS_SUCCESS;
+ rsp->Reserved = 0;
+ inc_rfc1001_len(work->response_buf, 4);
+ ksmbd_fd_put(work, fp);
+ return 0;
+
+out:
+ list_for_each_entry_safe(smb_lock, tmp, &lock_list, llist) {
+ locks_free_lock(smb_lock->fl);
+ list_del(&smb_lock->llist);
+ kfree(smb_lock);
+ }
+
+ list_for_each_entry_safe(smb_lock, tmp, &rollback_list, llist) {
+ struct file_lock *rlock = NULL;
+
+ rlock = smb_flock_init(filp);
+ rlock->fl_type = F_UNLCK;
+ rlock->fl_start = smb_lock->start;
+ rlock->fl_end = smb_lock->end;
+
+ rc = vfs_lock_file(filp, 0, rlock, NULL);
+ if (rc)
+ pr_err("rollback unlock fail : %d\n", rc);
+
+ list_del(&smb_lock->llist);
+ spin_lock(&work->conn->llist_lock);
+ if (!list_empty(&smb_lock->flist))
+ list_del(&smb_lock->flist);
+ list_del(&smb_lock->clist);
+ spin_unlock(&work->conn->llist_lock);
+
+ locks_free_lock(smb_lock->fl);
+ locks_free_lock(rlock);
+ kfree(smb_lock);
+ }
+out2:
+ ksmbd_debug(SMB, "failed in taking lock(flags : %x), err : %d\n", flags, err);
+
+ if (!rsp->hdr.Status) {
+ if (err == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else if (err == -ENOMEM)
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
+ else if (err == -ENOENT)
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ else
+ rsp->hdr.Status = STATUS_LOCK_NOT_GRANTED;
+ }
+
+ smb2_set_err_rsp(work);
+ ksmbd_fd_put(work, fp);
+ return err;
+}
+
+static int fsctl_copychunk(struct ksmbd_work *work,
+ struct copychunk_ioctl_req *ci_req,
+ unsigned int cnt_code,
+ unsigned int input_count,
+ unsigned long long volatile_id,
+ unsigned long long persistent_id,
+ struct smb2_ioctl_rsp *rsp)
+{
+ struct copychunk_ioctl_rsp *ci_rsp;
+ struct ksmbd_file *src_fp = NULL, *dst_fp = NULL;
+ struct srv_copychunk *chunks;
+ unsigned int i, chunk_count, chunk_count_written = 0;
+ unsigned int chunk_size_written = 0;
+ loff_t total_size_written = 0;
+ int ret = 0;
+
+ ci_rsp = (struct copychunk_ioctl_rsp *)&rsp->Buffer[0];
+
+ rsp->VolatileFileId = volatile_id;
+ rsp->PersistentFileId = persistent_id;
+ ci_rsp->ChunksWritten =
+ cpu_to_le32(ksmbd_server_side_copy_max_chunk_count());
+ ci_rsp->ChunkBytesWritten =
+ cpu_to_le32(ksmbd_server_side_copy_max_chunk_size());
+ ci_rsp->TotalBytesWritten =
+ cpu_to_le32(ksmbd_server_side_copy_max_total_size());
+
+ chunks = (struct srv_copychunk *)&ci_req->Chunks[0];
+ chunk_count = le32_to_cpu(ci_req->ChunkCount);
+ if (chunk_count == 0)
+ goto out;
+ total_size_written = 0;
+
+ /* verify the SRV_COPYCHUNK_COPY packet */
+ if (chunk_count > ksmbd_server_side_copy_max_chunk_count() ||
+ input_count < offsetof(struct copychunk_ioctl_req, Chunks) +
+ chunk_count * sizeof(struct srv_copychunk)) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ return -EINVAL;
+ }
+
+ for (i = 0; i < chunk_count; i++) {
+ if (le32_to_cpu(chunks[i].Length) == 0 ||
+ le32_to_cpu(chunks[i].Length) > ksmbd_server_side_copy_max_chunk_size())
+ break;
+ total_size_written += le32_to_cpu(chunks[i].Length);
+ }
+
+ if (i < chunk_count ||
+ total_size_written > ksmbd_server_side_copy_max_total_size()) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ return -EINVAL;
+ }
+
+ src_fp = ksmbd_lookup_foreign_fd(work,
+ le64_to_cpu(ci_req->ResumeKey[0]));
+ dst_fp = ksmbd_lookup_fd_slow(work, volatile_id, persistent_id);
+ ret = -EINVAL;
+ if (!src_fp ||
+ src_fp->persistent_id != le64_to_cpu(ci_req->ResumeKey[1])) {
+ rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ goto out;
+ }
+
+ if (!dst_fp) {
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ goto out;
+ }
+
+ /*
+ * FILE_READ_DATA should only be included in
+ * the FSCTL_COPYCHUNK case
+ */
+ if (cnt_code == FSCTL_COPYCHUNK &&
+ !(dst_fp->daccess & (FILE_READ_DATA_LE | FILE_GENERIC_READ_LE))) {
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ goto out;
+ }
+
+ ret = ksmbd_vfs_copy_file_ranges(work, src_fp, dst_fp,
+ chunks, chunk_count,
+ &chunk_count_written,
+ &chunk_size_written,
+ &total_size_written);
+ if (ret < 0) {
+ if (ret == -EACCES)
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ if (ret == -EAGAIN)
+ rsp->hdr.Status = STATUS_FILE_LOCK_CONFLICT;
+ else if (ret == -EBADF)
+ rsp->hdr.Status = STATUS_INVALID_HANDLE;
+ else if (ret == -EFBIG || ret == -ENOSPC)
+ rsp->hdr.Status = STATUS_DISK_FULL;
+ else if (ret == -EINVAL)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ else if (ret == -EISDIR)
+ rsp->hdr.Status = STATUS_FILE_IS_A_DIRECTORY;
+ else if (ret == -E2BIG)
+ rsp->hdr.Status = STATUS_INVALID_VIEW_SIZE;
+ else
+ rsp->hdr.Status = STATUS_UNEXPECTED_IO_ERROR;
+ }
+
+ ci_rsp->ChunksWritten = cpu_to_le32(chunk_count_written);
+ ci_rsp->ChunkBytesWritten = cpu_to_le32(chunk_size_written);
+ ci_rsp->TotalBytesWritten = cpu_to_le32(total_size_written);
+out:
+ ksmbd_fd_put(work, src_fp);
+ ksmbd_fd_put(work, dst_fp);
+ return ret;
+}
+
+static __be32 idev_ipv4_address(struct in_device *idev)
+{
+ __be32 addr = 0;
+
+ struct in_ifaddr *ifa;
+
+ rcu_read_lock();
+ in_dev_for_each_ifa_rcu(ifa, idev) {
+ if (ifa->ifa_flags & IFA_F_SECONDARY)
+ continue;
+
+ addr = ifa->ifa_address;
+ break;
+ }
+ rcu_read_unlock();
+ return addr;
+}
+
+static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
+ struct smb2_ioctl_rsp *rsp,
+ unsigned int out_buf_len)
+{
+ struct network_interface_info_ioctl_rsp *nii_rsp = NULL;
+ int nbytes = 0;
+ struct net_device *netdev;
+ struct sockaddr_storage_rsp *sockaddr_storage;
+ unsigned int flags;
+ unsigned long long speed;
+
+ rtnl_lock();
+ for_each_netdev(&init_net, netdev) {
+ bool ipv4_set = false;
+
+ if (netdev->type == ARPHRD_LOOPBACK)
+ continue;
+
+ flags = dev_get_flags(netdev);
+ if (!(flags & IFF_RUNNING))
+ continue;
+ipv6_retry:
+ if (out_buf_len <
+ nbytes + sizeof(struct network_interface_info_ioctl_rsp)) {
+ rtnl_unlock();
+ return -ENOSPC;
+ }
+
+ nii_rsp = (struct network_interface_info_ioctl_rsp *)
+ &rsp->Buffer[nbytes];
+ nii_rsp->IfIndex = cpu_to_le32(netdev->ifindex);
+
+ nii_rsp->Capability = 0;
+ if (netdev->real_num_tx_queues > 1)
+ nii_rsp->Capability |= cpu_to_le32(RSS_CAPABLE);
+ if (ksmbd_rdma_capable_netdev(netdev))
+ nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE);
+
+ nii_rsp->Next = cpu_to_le32(152);
+ nii_rsp->Reserved = 0;
+
+ if (netdev->ethtool_ops->get_link_ksettings) {
+ struct ethtool_link_ksettings cmd;
+
+ netdev->ethtool_ops->get_link_ksettings(netdev, &cmd);
+ speed = cmd.base.speed;
+ } else {
+ ksmbd_debug(SMB, "%s %s\n", netdev->name,
+ "speed is unknown, defaulting to 1Gb/sec");
+ speed = SPEED_1000;
+ }
+
+ speed *= 1000000;
+ nii_rsp->LinkSpeed = cpu_to_le64(speed);
+
+ sockaddr_storage = (struct sockaddr_storage_rsp *)
+ nii_rsp->SockAddr_Storage;
+ memset(sockaddr_storage, 0, 128);
+
+ if (!ipv4_set) {
+ struct in_device *idev;
+
+ sockaddr_storage->Family = cpu_to_le16(INTERNETWORK);
+ sockaddr_storage->addr4.Port = 0;
+
+ idev = __in_dev_get_rtnl(netdev);
+ if (!idev)
+ continue;
+ sockaddr_storage->addr4.IPv4address =
+ idev_ipv4_address(idev);
+ nbytes += sizeof(struct network_interface_info_ioctl_rsp);
+ ipv4_set = true;
+ goto ipv6_retry;
+ } else {
+ struct inet6_dev *idev6;
+ struct inet6_ifaddr *ifa;
+ __u8 *ipv6_addr = sockaddr_storage->addr6.IPv6address;
+
+ sockaddr_storage->Family = cpu_to_le16(INTERNETWORKV6);
+ sockaddr_storage->addr6.Port = 0;
+ sockaddr_storage->addr6.FlowInfo = 0;
+
+ idev6 = __in6_dev_get(netdev);
+ if (!idev6)
+ continue;
+
+ list_for_each_entry(ifa, &idev6->addr_list, if_list) {
+ if (ifa->flags & (IFA_F_TENTATIVE |
+ IFA_F_DEPRECATED))
+ continue;
+ memcpy(ipv6_addr, ifa->addr.s6_addr, 16);
+ break;
+ }
+ sockaddr_storage->addr6.ScopeId = 0;
+ nbytes += sizeof(struct network_interface_info_ioctl_rsp);
+ }
+ }
+ rtnl_unlock();
+
+ /* zero if this is last one */
+ if (nii_rsp)
+ nii_rsp->Next = 0;
+
+ rsp->PersistentFileId = SMB2_NO_FID;
+ rsp->VolatileFileId = SMB2_NO_FID;
+ return nbytes;
+}
+
+static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn,
+ struct validate_negotiate_info_req *neg_req,
+ struct validate_negotiate_info_rsp *neg_rsp,
+ unsigned int in_buf_len)
+{
+ int ret = 0;
+ int dialect;
+
+ if (in_buf_len < offsetof(struct validate_negotiate_info_req, Dialects) +
+ le16_to_cpu(neg_req->DialectCount) * sizeof(__le16))
+ return -EINVAL;
+
+ dialect = ksmbd_lookup_dialect_by_id(neg_req->Dialects,
+ neg_req->DialectCount);
+ if (dialect == BAD_PROT_ID || dialect != conn->dialect) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ if (strncmp(neg_req->Guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE)) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ if (le16_to_cpu(neg_req->SecurityMode) != conn->cli_sec_mode) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ if (le32_to_cpu(neg_req->Capabilities) != conn->cli_cap) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ neg_rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
+ memset(neg_rsp->Guid, 0, SMB2_CLIENT_GUID_SIZE);
+ neg_rsp->SecurityMode = cpu_to_le16(conn->srv_sec_mode);
+ neg_rsp->Dialect = cpu_to_le16(conn->dialect);
+err_out:
+ return ret;
+}
+
+static int fsctl_query_allocated_ranges(struct ksmbd_work *work, u64 id,
+ struct file_allocated_range_buffer *qar_req,
+ struct file_allocated_range_buffer *qar_rsp,
+ unsigned int in_count, unsigned int *out_count)
+{
+ struct ksmbd_file *fp;
+ loff_t start, length;
+ int ret = 0;
+
+ *out_count = 0;
+ if (in_count == 0)
+ return -EINVAL;
+
+ start = le64_to_cpu(qar_req->file_offset);
+ length = le64_to_cpu(qar_req->length);
+
+ if (start < 0 || length < 0)
+ return -EINVAL;
+
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp)
+ return -ENOENT;
+
+ ret = ksmbd_vfs_fqar_lseek(fp, start, length,
+ qar_rsp, in_count, out_count);
+ if (ret && ret != -E2BIG)
+ *out_count = 0;
+
+ ksmbd_fd_put(work, fp);
+ return ret;
+}
+
+static int fsctl_pipe_transceive(struct ksmbd_work *work, u64 id,
+ unsigned int out_buf_len,
+ struct smb2_ioctl_req *req,
+ struct smb2_ioctl_rsp *rsp)
+{
+ struct ksmbd_rpc_command *rpc_resp;
+ char *data_buf = (char *)&req->Buffer[0];
+ int nbytes = 0;
+
+ rpc_resp = ksmbd_rpc_ioctl(work->sess, id, data_buf,
+ le32_to_cpu(req->InputCount));
+ if (rpc_resp) {
+ if (rpc_resp->flags == KSMBD_RPC_SOME_NOT_MAPPED) {
+ /*
+ * set STATUS_SOME_NOT_MAPPED response
+ * for unknown domain sid.
+ */
+ rsp->hdr.Status = STATUS_SOME_NOT_MAPPED;
+ } else if (rpc_resp->flags == KSMBD_RPC_ENOTIMPLEMENTED) {
+ rsp->hdr.Status = STATUS_NOT_SUPPORTED;
+ goto out;
+ } else if (rpc_resp->flags != KSMBD_RPC_OK) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ goto out;
+ }
+
+ nbytes = rpc_resp->payload_sz;
+ if (rpc_resp->payload_sz > out_buf_len) {
+ rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
+ nbytes = out_buf_len;
+ }
+
+ if (!rpc_resp->payload_sz) {
+ rsp->hdr.Status =
+ STATUS_UNEXPECTED_IO_ERROR;
+ goto out;
+ }
+
+ memcpy((char *)rsp->Buffer, rpc_resp->payload, nbytes);
+ }
+out:
+ kvfree(rpc_resp);
+ return nbytes;
+}
+
+static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
+ struct file_sparse *sparse)
+{
+ struct ksmbd_file *fp;
+ struct user_namespace *user_ns;
+ int ret = 0;
+ __le32 old_fattr;
+
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp)
+ return -ENOENT;
+ user_ns = file_mnt_user_ns(fp->filp);
+
+ old_fattr = fp->f_ci->m_fattr;
+ if (sparse->SetSparse)
+ fp->f_ci->m_fattr |= FILE_ATTRIBUTE_SPARSE_FILE_LE;
+ else
+ fp->f_ci->m_fattr &= ~FILE_ATTRIBUTE_SPARSE_FILE_LE;
+
+ if (fp->f_ci->m_fattr != old_fattr &&
+ test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
+ struct xattr_dos_attrib da;
+
+ ret = ksmbd_vfs_get_dos_attrib_xattr(user_ns,
+ fp->filp->f_path.dentry, &da);
+ if (ret <= 0)
+ goto out;
+
+ da.attr = le32_to_cpu(fp->f_ci->m_fattr);
+ ret = ksmbd_vfs_set_dos_attrib_xattr(user_ns,
+ fp->filp->f_path.dentry, &da);
+ if (ret)
+ fp->f_ci->m_fattr = old_fattr;
+ }
+
+out:
+ ksmbd_fd_put(work, fp);
+ return ret;
+}
+
+static int fsctl_request_resume_key(struct ksmbd_work *work,
+ struct smb2_ioctl_req *req,
+ struct resume_key_ioctl_rsp *key_rsp)
+{
+ struct ksmbd_file *fp;
+
+ fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
+ if (!fp)
+ return -ENOENT;
+
+ memset(key_rsp, 0, sizeof(*key_rsp));
+ key_rsp->ResumeKey[0] = req->VolatileFileId;
+ key_rsp->ResumeKey[1] = req->PersistentFileId;
+ ksmbd_fd_put(work, fp);
+
+ return 0;
+}
+
+/**
+ * smb2_ioctl() - handler for smb2 ioctl command
+ * @work: smb work containing ioctl command buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+int smb2_ioctl(struct ksmbd_work *work)
+{
+ struct smb2_ioctl_req *req;
+ struct smb2_ioctl_rsp *rsp;
+ unsigned int cnt_code, nbytes = 0, out_buf_len, in_buf_len;
+ u64 id = KSMBD_NO_FID;
+ struct ksmbd_conn *conn = work->conn;
+ int ret = 0;
+
+ if (work->next_smb2_rcv_hdr_off) {
+ req = ksmbd_req_buf_next(work);
+ rsp = ksmbd_resp_buf_next(work);
+ if (!has_file_id(req->VolatileFileId)) {
+ ksmbd_debug(SMB, "Compound request set FID = %llu\n",
+ work->compound_fid);
+ id = work->compound_fid;
+ }
+ } else {
+ req = smb2_get_msg(work->request_buf);
+ rsp = smb2_get_msg(work->response_buf);
+ }
+
+ if (!has_file_id(id))
+ id = req->VolatileFileId;
+
+ if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) {
+ rsp->hdr.Status = STATUS_NOT_SUPPORTED;
+ goto out;
+ }
+
+ cnt_code = le32_to_cpu(req->CtlCode);
+ ret = smb2_calc_max_out_buf_len(work, 48,
+ le32_to_cpu(req->MaxOutputResponse));
+ if (ret < 0) {
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ goto out;
+ }
+ out_buf_len = (unsigned int)ret;
+ in_buf_len = le32_to_cpu(req->InputCount);
+
+ switch (cnt_code) {
+ case FSCTL_DFS_GET_REFERRALS:
+ case FSCTL_DFS_GET_REFERRALS_EX:
+ /* Not support DFS yet */
+ rsp->hdr.Status = STATUS_FS_DRIVER_REQUIRED;
+ goto out;
+ case FSCTL_CREATE_OR_GET_OBJECT_ID:
+ {
+ struct file_object_buf_type1_ioctl_rsp *obj_buf;
+
+ nbytes = sizeof(struct file_object_buf_type1_ioctl_rsp);
+ obj_buf = (struct file_object_buf_type1_ioctl_rsp *)
+ &rsp->Buffer[0];
+
+ /*
+ * TODO: This is dummy implementation to pass smbtorture
+ * Need to check correct response later
+ */
+ memset(obj_buf->ObjectId, 0x0, 16);
+ memset(obj_buf->BirthVolumeId, 0x0, 16);
+ memset(obj_buf->BirthObjectId, 0x0, 16);
+ memset(obj_buf->DomainId, 0x0, 16);
+
+ break;
+ }
+ case FSCTL_PIPE_TRANSCEIVE:
+ out_buf_len = min_t(u32, KSMBD_IPC_MAX_PAYLOAD, out_buf_len);
+ nbytes = fsctl_pipe_transceive(work, id, out_buf_len, req, rsp);
+ break;
+ case FSCTL_VALIDATE_NEGOTIATE_INFO:
+ if (conn->dialect < SMB30_PROT_ID) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (in_buf_len < offsetof(struct validate_negotiate_info_req,
+ Dialects)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (out_buf_len < sizeof(struct validate_negotiate_info_rsp)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = fsctl_validate_negotiate_info(conn,
+ (struct validate_negotiate_info_req *)&req->Buffer[0],
+ (struct validate_negotiate_info_rsp *)&rsp->Buffer[0],
+ in_buf_len);
+ if (ret < 0)
+ goto out;
+
+ nbytes = sizeof(struct validate_negotiate_info_rsp);
+ rsp->PersistentFileId = SMB2_NO_FID;
+ rsp->VolatileFileId = SMB2_NO_FID;
+ break;
+ case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
+ ret = fsctl_query_iface_info_ioctl(conn, rsp, out_buf_len);
+ if (ret < 0)
+ goto out;
+ nbytes = ret;
+ break;
+ case FSCTL_REQUEST_RESUME_KEY:
+ if (out_buf_len < sizeof(struct resume_key_ioctl_rsp)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = fsctl_request_resume_key(work, req,
+ (struct resume_key_ioctl_rsp *)&rsp->Buffer[0]);
+ if (ret < 0)
+ goto out;
+ rsp->PersistentFileId = req->PersistentFileId;
+ rsp->VolatileFileId = req->VolatileFileId;
+ nbytes = sizeof(struct resume_key_ioctl_rsp);
+ break;
+ case FSCTL_COPYCHUNK:
+ case FSCTL_COPYCHUNK_WRITE:
+ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+ ksmbd_debug(SMB,
+ "User does not have write permission\n");
+ ret = -EACCES;
+ goto out;
+ }
+
+ if (in_buf_len < sizeof(struct copychunk_ioctl_req)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (out_buf_len < sizeof(struct copychunk_ioctl_rsp)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ nbytes = sizeof(struct copychunk_ioctl_rsp);
+ rsp->VolatileFileId = req->VolatileFileId;
+ rsp->PersistentFileId = req->PersistentFileId;
+ fsctl_copychunk(work,
+ (struct copychunk_ioctl_req *)&req->Buffer[0],
+ le32_to_cpu(req->CtlCode),
+ le32_to_cpu(req->InputCount),
+ req->VolatileFileId,
+ req->PersistentFileId,
+ rsp);
+ break;
+ case FSCTL_SET_SPARSE:
+ if (in_buf_len < sizeof(struct file_sparse)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = fsctl_set_sparse(work, id,
+ (struct file_sparse *)&req->Buffer[0]);
+ if (ret < 0)
+ goto out;
+ break;
+ case FSCTL_SET_ZERO_DATA:
+ {
+ struct file_zero_data_information *zero_data;
+ struct ksmbd_file *fp;
+ loff_t off, len, bfz;
+
+ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+ ksmbd_debug(SMB,
+ "User does not have write permission\n");
+ ret = -EACCES;
+ goto out;
+ }
+
+ if (in_buf_len < sizeof(struct file_zero_data_information)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ zero_data =
+ (struct file_zero_data_information *)&req->Buffer[0];
+
+ off = le64_to_cpu(zero_data->FileOffset);
+ bfz = le64_to_cpu(zero_data->BeyondFinalZero);
+ if (off < 0 || bfz < 0 || off > bfz) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ len = bfz - off;
+ if (len) {
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ ret = ksmbd_vfs_zero_data(work, fp, off, len);
+ ksmbd_fd_put(work, fp);
+ if (ret < 0)
+ goto out;
+ }
+ break;
+ }
+ case FSCTL_QUERY_ALLOCATED_RANGES:
+ if (in_buf_len < sizeof(struct file_allocated_range_buffer)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = fsctl_query_allocated_ranges(work, id,
+ (struct file_allocated_range_buffer *)&req->Buffer[0],
+ (struct file_allocated_range_buffer *)&rsp->Buffer[0],
+ out_buf_len /
+ sizeof(struct file_allocated_range_buffer), &nbytes);
+ if (ret == -E2BIG) {
+ rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
+ } else if (ret < 0) {
+ nbytes = 0;
+ goto out;
+ }
+
+ nbytes *= sizeof(struct file_allocated_range_buffer);
+ break;
+ case FSCTL_GET_REPARSE_POINT:
+ {
+ struct reparse_data_buffer *reparse_ptr;
+ struct ksmbd_file *fp;
+
+ reparse_ptr = (struct reparse_data_buffer *)&rsp->Buffer[0];
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp) {
+ pr_err("not found fp!!\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ reparse_ptr->ReparseTag =
+ smb2_get_reparse_tag_special_file(file_inode(fp->filp)->i_mode);
+ reparse_ptr->ReparseDataLength = 0;
+ ksmbd_fd_put(work, fp);
+ nbytes = sizeof(struct reparse_data_buffer);
+ break;
+ }
+ case FSCTL_DUPLICATE_EXTENTS_TO_FILE:
+ {
+ struct ksmbd_file *fp_in, *fp_out = NULL;
+ struct duplicate_extents_to_file *dup_ext;
+ loff_t src_off, dst_off, length, cloned;
+
+ if (in_buf_len < sizeof(struct duplicate_extents_to_file)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dup_ext = (struct duplicate_extents_to_file *)&req->Buffer[0];
+
+ fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle,
+ dup_ext->PersistentFileHandle);
+ if (!fp_in) {
+ pr_err("not found file handle in duplicate extent to file\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ fp_out = ksmbd_lookup_fd_fast(work, id);
+ if (!fp_out) {
+ pr_err("not found fp\n");
+ ret = -ENOENT;
+ goto dup_ext_out;
+ }
+
+ src_off = le64_to_cpu(dup_ext->SourceFileOffset);
+ dst_off = le64_to_cpu(dup_ext->TargetFileOffset);
+ length = le64_to_cpu(dup_ext->ByteCount);
+ /*
+ * XXX: It is not clear if FSCTL_DUPLICATE_EXTENTS_TO_FILE
+ * should fall back to vfs_copy_file_range(). This could be
+ * beneficial when re-exporting nfs/smb mount, but note that
+ * this can result in partial copy that returns an error status.
+ * If/when FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX is implemented,
+ * fall back to vfs_copy_file_range(), should be avoided when
+ * the flag DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC is set.
+ */
+ cloned = vfs_clone_file_range(fp_in->filp, src_off,
+ fp_out->filp, dst_off, length, 0);
+ if (cloned == -EXDEV || cloned == -EOPNOTSUPP) {
+ ret = -EOPNOTSUPP;
+ goto dup_ext_out;
+ } else if (cloned != length) {
+ cloned = vfs_copy_file_range(fp_in->filp, src_off,
+ fp_out->filp, dst_off,
+ length, 0);
+ if (cloned != length) {
+ if (cloned < 0)
+ ret = cloned;
+ else
+ ret = -EINVAL;
+ }
+ }
+
+dup_ext_out:
+ ksmbd_fd_put(work, fp_in);
+ ksmbd_fd_put(work, fp_out);
+ if (ret < 0)
+ goto out;
+ break;
+ }
+ default:
+ ksmbd_debug(SMB, "not implemented yet ioctl command 0x%x\n",
+ cnt_code);
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ rsp->CtlCode = cpu_to_le32(cnt_code);
+ rsp->InputCount = cpu_to_le32(0);
+ rsp->InputOffset = cpu_to_le32(112);
+ rsp->OutputOffset = cpu_to_le32(112);
+ rsp->OutputCount = cpu_to_le32(nbytes);
+ rsp->StructureSize = cpu_to_le16(49);
+ rsp->Reserved = cpu_to_le16(0);
+ rsp->Flags = cpu_to_le32(0);
+ rsp->Reserved2 = cpu_to_le32(0);
+ inc_rfc1001_len(work->response_buf, 48 + nbytes);
+
+ return 0;
+
+out:
+ if (ret == -EACCES)
+ rsp->hdr.Status = STATUS_ACCESS_DENIED;
+ else if (ret == -ENOENT)
+ rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ else if (ret == -EOPNOTSUPP)
+ rsp->hdr.Status = STATUS_NOT_SUPPORTED;
+ else if (ret == -ENOSPC)
+ rsp->hdr.Status = STATUS_BUFFER_TOO_SMALL;
+ else if (ret < 0 || rsp->hdr.Status == 0)
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ smb2_set_err_rsp(work);
+ return 0;
+}
+
+/**
+ * smb20_oplock_break_ack() - handler for smb2.0 oplock break command
+ * @work: smb work containing oplock break command buffer
+ *
+ * Return: 0
+ */
+static void smb20_oplock_break_ack(struct ksmbd_work *work)
+{
+ struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
+ struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
+ struct ksmbd_file *fp;
+ struct oplock_info *opinfo = NULL;
+ __le32 err = 0;
+ int ret = 0;
+ u64 volatile_id, persistent_id;
+ char req_oplevel = 0, rsp_oplevel = 0;
+ unsigned int oplock_change_type;
+
+ volatile_id = req->VolatileFid;
+ persistent_id = req->PersistentFid;
+ req_oplevel = req->OplockLevel;
+ ksmbd_debug(OPLOCK, "v_id %llu, p_id %llu request oplock level %d\n",
+ volatile_id, persistent_id, req_oplevel);
+
+ fp = ksmbd_lookup_fd_slow(work, volatile_id, persistent_id);
+ if (!fp) {
+ rsp->hdr.Status = STATUS_FILE_CLOSED;
+ smb2_set_err_rsp(work);
+ return;
+ }
+
+ opinfo = opinfo_get(fp);
+ if (!opinfo) {
+ pr_err("unexpected null oplock_info\n");
+ rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
+ smb2_set_err_rsp(work);
+ ksmbd_fd_put(work, fp);
+ return;
+ }
+
+ if (opinfo->level == SMB2_OPLOCK_LEVEL_NONE) {
+ rsp->hdr.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
+ goto err_out;
+ }
+
+ if (opinfo->op_state == OPLOCK_STATE_NONE) {
+ ksmbd_debug(SMB, "unexpected oplock state 0x%x\n", opinfo->op_state);
+ rsp->hdr.Status = STATUS_UNSUCCESSFUL;
+ goto err_out;
+ }
+
+ if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
+ opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) &&
+ (req_oplevel != SMB2_OPLOCK_LEVEL_II &&
+ req_oplevel != SMB2_OPLOCK_LEVEL_NONE)) {
+ err = STATUS_INVALID_OPLOCK_PROTOCOL;
+ oplock_change_type = OPLOCK_WRITE_TO_NONE;
+ } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II &&
+ req_oplevel != SMB2_OPLOCK_LEVEL_NONE) {
+ err = STATUS_INVALID_OPLOCK_PROTOCOL;
+ oplock_change_type = OPLOCK_READ_TO_NONE;
+ } else if (req_oplevel == SMB2_OPLOCK_LEVEL_II ||
+ req_oplevel == SMB2_OPLOCK_LEVEL_NONE) {
+ err = STATUS_INVALID_DEVICE_STATE;
+ if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
+ opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) &&
+ req_oplevel == SMB2_OPLOCK_LEVEL_II) {
+ oplock_change_type = OPLOCK_WRITE_TO_READ;
+ } else if ((opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE ||
+ opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) &&
+ req_oplevel == SMB2_OPLOCK_LEVEL_NONE) {
+ oplock_change_type = OPLOCK_WRITE_TO_NONE;
+ } else if (opinfo->level == SMB2_OPLOCK_LEVEL_II &&
+ req_oplevel == SMB2_OPLOCK_LEVEL_NONE) {
+ oplock_change_type = OPLOCK_READ_TO_NONE;
+ } else {
+ oplock_change_type = 0;
+ }
+ } else {
+ oplock_change_type = 0;
+ }
+
+ switch (oplock_change_type) {
+ case OPLOCK_WRITE_TO_READ:
+ ret = opinfo_write_to_read(opinfo);
+ rsp_oplevel = SMB2_OPLOCK_LEVEL_II;
+ break;
+ case OPLOCK_WRITE_TO_NONE:
+ ret = opinfo_write_to_none(opinfo);
+ rsp_oplevel = SMB2_OPLOCK_LEVEL_NONE;
+ break;
+ case OPLOCK_READ_TO_NONE:
+ ret = opinfo_read_to_none(opinfo);
+ rsp_oplevel = SMB2_OPLOCK_LEVEL_NONE;
+ break;
+ default:
+ pr_err("unknown oplock change 0x%x -> 0x%x\n",
+ opinfo->level, rsp_oplevel);
+ }
+
+ if (ret < 0) {
+ rsp->hdr.Status = err;
+ goto err_out;
+ }
+
+ opinfo_put(opinfo);
+ ksmbd_fd_put(work, fp);
+ opinfo->op_state = OPLOCK_STATE_NONE;
+ wake_up_interruptible_all(&opinfo->oplock_q);
+
+ rsp->StructureSize = cpu_to_le16(24);
+ rsp->OplockLevel = rsp_oplevel;
+ rsp->Reserved = 0;
+ rsp->Reserved2 = 0;
+ rsp->VolatileFid = volatile_id;
+ rsp->PersistentFid = persistent_id;
+ inc_rfc1001_len(work->response_buf, 24);
+ return;
+
+err_out:
+ opinfo->op_state = OPLOCK_STATE_NONE;
+ wake_up_interruptible_all(&opinfo->oplock_q);
+
+ opinfo_put(opinfo);
+ ksmbd_fd_put(work, fp);
+ smb2_set_err_rsp(work);
+}
+
+static int check_lease_state(struct lease *lease, __le32 req_state)
+{
+ if ((lease->new_state ==
+ (SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_HANDLE_CACHING_LE)) &&
+ !(req_state & SMB2_LEASE_WRITE_CACHING_LE)) {
+ lease->new_state = req_state;
+ return 0;
+ }
+
+ if (lease->new_state == req_state)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * smb21_lease_break_ack() - handler for smb2.1 lease break command
+ * @work: smb work containing lease break command buffer
+ *
+ * Return: 0
+ */
+static void smb21_lease_break_ack(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_lease_ack *req = smb2_get_msg(work->request_buf);
+ struct smb2_lease_ack *rsp = smb2_get_msg(work->response_buf);
+ struct oplock_info *opinfo;
+ __le32 err = 0;
+ int ret = 0;
+ unsigned int lease_change_type;
+ __le32 lease_state;
+ struct lease *lease;
+
+ ksmbd_debug(OPLOCK, "smb21 lease break, lease state(0x%x)\n",
+ le32_to_cpu(req->LeaseState));
+ opinfo = lookup_lease_in_table(conn, req->LeaseKey);
+ if (!opinfo) {
+ ksmbd_debug(OPLOCK, "file not opened\n");
+ smb2_set_err_rsp(work);
+ rsp->hdr.Status = STATUS_UNSUCCESSFUL;
+ return;
+ }
+ lease = opinfo->o_lease;
+
+ if (opinfo->op_state == OPLOCK_STATE_NONE) {
+ pr_err("unexpected lease break state 0x%x\n",
+ opinfo->op_state);
+ rsp->hdr.Status = STATUS_UNSUCCESSFUL;
+ goto err_out;
+ }
+
+ if (check_lease_state(lease, req->LeaseState)) {
+ rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED;
+ ksmbd_debug(OPLOCK,
+ "req lease state: 0x%x, expected state: 0x%x\n",
+ req->LeaseState, lease->new_state);
+ goto err_out;
+ }
+
+ if (!atomic_read(&opinfo->breaking_cnt)) {
+ rsp->hdr.Status = STATUS_UNSUCCESSFUL;
+ goto err_out;
+ }
+
+ /* check for bad lease state */
+ if (req->LeaseState &
+ (~(SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_HANDLE_CACHING_LE))) {
+ err = STATUS_INVALID_OPLOCK_PROTOCOL;
+ if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
+ lease_change_type = OPLOCK_WRITE_TO_NONE;
+ else
+ lease_change_type = OPLOCK_READ_TO_NONE;
+ ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n",
+ le32_to_cpu(lease->state),
+ le32_to_cpu(req->LeaseState));
+ } else if (lease->state == SMB2_LEASE_READ_CACHING_LE &&
+ req->LeaseState != SMB2_LEASE_NONE_LE) {
+ err = STATUS_INVALID_OPLOCK_PROTOCOL;
+ lease_change_type = OPLOCK_READ_TO_NONE;
+ ksmbd_debug(OPLOCK, "handle bad lease state 0x%x -> 0x%x\n",
+ le32_to_cpu(lease->state),
+ le32_to_cpu(req->LeaseState));
+ } else {
+ /* valid lease state changes */
+ err = STATUS_INVALID_DEVICE_STATE;
+ if (req->LeaseState == SMB2_LEASE_NONE_LE) {
+ if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
+ lease_change_type = OPLOCK_WRITE_TO_NONE;
+ else
+ lease_change_type = OPLOCK_READ_TO_NONE;
+ } else if (req->LeaseState & SMB2_LEASE_READ_CACHING_LE) {
+ if (lease->state & SMB2_LEASE_WRITE_CACHING_LE)
+ lease_change_type = OPLOCK_WRITE_TO_READ;
+ else
+ lease_change_type = OPLOCK_READ_HANDLE_TO_READ;
+ } else {
+ lease_change_type = 0;
+ }
+ }
+
+ switch (lease_change_type) {
+ case OPLOCK_WRITE_TO_READ:
+ ret = opinfo_write_to_read(opinfo);
+ break;
+ case OPLOCK_READ_HANDLE_TO_READ:
+ ret = opinfo_read_handle_to_read(opinfo);
+ break;
+ case OPLOCK_WRITE_TO_NONE:
+ ret = opinfo_write_to_none(opinfo);
+ break;
+ case OPLOCK_READ_TO_NONE:
+ ret = opinfo_read_to_none(opinfo);
+ break;
+ default:
+ ksmbd_debug(OPLOCK, "unknown lease change 0x%x -> 0x%x\n",
+ le32_to_cpu(lease->state),
+ le32_to_cpu(req->LeaseState));
+ }
+
+ lease_state = lease->state;
+ opinfo->op_state = OPLOCK_STATE_NONE;
+ wake_up_interruptible_all(&opinfo->oplock_q);
+ atomic_dec(&opinfo->breaking_cnt);
+ wake_up_interruptible_all(&opinfo->oplock_brk);
+ opinfo_put(opinfo);
+
+ if (ret < 0) {
+ rsp->hdr.Status = err;
+ goto err_out;
+ }
+
+ rsp->StructureSize = cpu_to_le16(36);
+ rsp->Reserved = 0;
+ rsp->Flags = 0;
+ memcpy(rsp->LeaseKey, req->LeaseKey, 16);
+ rsp->LeaseState = lease_state;
+ rsp->LeaseDuration = 0;
+ inc_rfc1001_len(work->response_buf, 36);
+ return;
+
+err_out:
+ opinfo->op_state = OPLOCK_STATE_NONE;
+ wake_up_interruptible_all(&opinfo->oplock_q);
+ atomic_dec(&opinfo->breaking_cnt);
+ wake_up_interruptible_all(&opinfo->oplock_brk);
+
+ opinfo_put(opinfo);
+ smb2_set_err_rsp(work);
+}
+
+/**
+ * smb2_oplock_break() - dispatcher for smb2.0 and 2.1 oplock/lease break
+ * @work: smb work containing oplock/lease break command buffer
+ *
+ * Return: 0
+ */
+int smb2_oplock_break(struct ksmbd_work *work)
+{
+ struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
+ struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
+
+ switch (le16_to_cpu(req->StructureSize)) {
+ case OP_BREAK_STRUCT_SIZE_20:
+ smb20_oplock_break_ack(work);
+ break;
+ case OP_BREAK_STRUCT_SIZE_21:
+ smb21_lease_break_ack(work);
+ break;
+ default:
+ ksmbd_debug(OPLOCK, "invalid break cmd %d\n",
+ le16_to_cpu(req->StructureSize));
+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
+ smb2_set_err_rsp(work);
+ }
+
+ return 0;
+}
+
+/**
+ * smb2_notify() - handler for smb2 notify request
+ * @work: smb work containing notify command buffer
+ *
+ * Return: 0
+ */
+int smb2_notify(struct ksmbd_work *work)
+{
+ struct smb2_change_notify_req *req;
+ struct smb2_change_notify_rsp *rsp;
+
+ WORK_BUFFERS(work, req, rsp);
+
+ if (work->next_smb2_rcv_hdr_off && req->hdr.NextCommand) {
+ rsp->hdr.Status = STATUS_INTERNAL_ERROR;
+ smb2_set_err_rsp(work);
+ return 0;
+ }
+
+ smb2_set_err_rsp(work);
+ rsp->hdr.Status = STATUS_NOT_IMPLEMENTED;
+ return 0;
+}
+
+/**
+ * smb2_is_sign_req() - handler for checking packet signing status
+ * @work: smb work containing notify command buffer
+ * @command: SMB2 command id
+ *
+ * Return: true if packed is signed, false otherwise
+ */
+bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command)
+{
+ struct smb2_hdr *rcv_hdr2 = smb2_get_msg(work->request_buf);
+
+ if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) &&
+ command != SMB2_NEGOTIATE_HE &&
+ command != SMB2_SESSION_SETUP_HE &&
+ command != SMB2_OPLOCK_BREAK_HE)
+ return true;
+
+ return false;
+}
+
+/**
+ * smb2_check_sign_req() - handler for req packet sign processing
+ * @work: smb work containing notify command buffer
+ *
+ * Return: 1 on success, 0 otherwise
+ */
+int smb2_check_sign_req(struct ksmbd_work *work)
+{
+ struct smb2_hdr *hdr;
+ char signature_req[SMB2_SIGNATURE_SIZE];
+ char signature[SMB2_HMACSHA256_SIZE];
+ struct kvec iov[1];
+ size_t len;
+
+ hdr = smb2_get_msg(work->request_buf);
+ if (work->next_smb2_rcv_hdr_off)
+ hdr = ksmbd_req_buf_next(work);
+
+ if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
+ len = get_rfc1002_len(work->request_buf);
+ else if (hdr->NextCommand)
+ len = le32_to_cpu(hdr->NextCommand);
+ else
+ len = get_rfc1002_len(work->request_buf) -
+ work->next_smb2_rcv_hdr_off;
+
+ memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE);
+ memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
+
+ iov[0].iov_base = (char *)&hdr->ProtocolId;
+ iov[0].iov_len = len;
+
+ if (ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1,
+ signature))
+ return 0;
+
+ if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
+ pr_err("bad smb2 signature\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * smb2_set_sign_rsp() - handler for rsp packet sign processing
+ * @work: smb work containing notify command buffer
+ *
+ */
+void smb2_set_sign_rsp(struct ksmbd_work *work)
+{
+ struct smb2_hdr *hdr;
+ struct smb2_hdr *req_hdr;
+ char signature[SMB2_HMACSHA256_SIZE];
+ struct kvec iov[2];
+ size_t len;
+ int n_vec = 1;
+
+ hdr = smb2_get_msg(work->response_buf);
+ if (work->next_smb2_rsp_hdr_off)
+ hdr = ksmbd_resp_buf_next(work);
+
+ req_hdr = ksmbd_req_buf_next(work);
+
+ if (!work->next_smb2_rsp_hdr_off) {
+ len = get_rfc1002_len(work->response_buf);
+ if (req_hdr->NextCommand)
+ len = ALIGN(len, 8);
+ } else {
+ len = get_rfc1002_len(work->response_buf) -
+ work->next_smb2_rsp_hdr_off;
+ len = ALIGN(len, 8);
+ }
+
+ if (req_hdr->NextCommand)
+ hdr->NextCommand = cpu_to_le32(len);
+
+ hdr->Flags |= SMB2_FLAGS_SIGNED;
+ memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
+
+ iov[0].iov_base = (char *)&hdr->ProtocolId;
+ iov[0].iov_len = len;
+
+ if (work->aux_payload_sz) {
+ iov[0].iov_len -= work->aux_payload_sz;
+
+ iov[1].iov_base = work->aux_payload_buf;
+ iov[1].iov_len = work->aux_payload_sz;
+ n_vec++;
+ }
+
+ if (!ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec,
+ signature))
+ memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
+}
+
+/**
+ * smb3_check_sign_req() - handler for req packet sign processing
+ * @work: smb work containing notify command buffer
+ *
+ * Return: 1 on success, 0 otherwise
+ */
+int smb3_check_sign_req(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ char *signing_key;
+ struct smb2_hdr *hdr;
+ struct channel *chann;
+ char signature_req[SMB2_SIGNATURE_SIZE];
+ char signature[SMB2_CMACAES_SIZE];
+ struct kvec iov[1];
+ size_t len;
+
+ hdr = smb2_get_msg(work->request_buf);
+ if (work->next_smb2_rcv_hdr_off)
+ hdr = ksmbd_req_buf_next(work);
+
+ if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
+ len = get_rfc1002_len(work->request_buf);
+ else if (hdr->NextCommand)
+ len = le32_to_cpu(hdr->NextCommand);
+ else
+ len = get_rfc1002_len(work->request_buf) -
+ work->next_smb2_rcv_hdr_off;
+
+ if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
+ signing_key = work->sess->smb3signingkey;
+ } else {
+ chann = lookup_chann_list(work->sess, conn);
+ if (!chann) {
+ return 0;
+ }
+ signing_key = chann->smb3signingkey;
+ }
+
+ if (!signing_key) {
+ pr_err("SMB3 signing key is not generated\n");
+ return 0;
+ }
+
+ memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE);
+ memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
+ iov[0].iov_base = (char *)&hdr->ProtocolId;
+ iov[0].iov_len = len;
+
+ if (ksmbd_sign_smb3_pdu(conn, signing_key, iov, 1, signature))
+ return 0;
+
+ if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
+ pr_err("bad smb2 signature\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * smb3_set_sign_rsp() - handler for rsp packet sign processing
+ * @work: smb work containing notify command buffer
+ *
+ */
+void smb3_set_sign_rsp(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_hdr *req_hdr, *hdr;
+ struct channel *chann;
+ char signature[SMB2_CMACAES_SIZE];
+ struct kvec iov[2];
+ int n_vec = 1;
+ size_t len;
+ char *signing_key;
+
+ hdr = smb2_get_msg(work->response_buf);
+ if (work->next_smb2_rsp_hdr_off)
+ hdr = ksmbd_resp_buf_next(work);
+
+ req_hdr = ksmbd_req_buf_next(work);
+
+ if (!work->next_smb2_rsp_hdr_off) {
+ len = get_rfc1002_len(work->response_buf);
+ if (req_hdr->NextCommand)
+ len = ALIGN(len, 8);
+ } else {
+ len = get_rfc1002_len(work->response_buf) -
+ work->next_smb2_rsp_hdr_off;
+ len = ALIGN(len, 8);
+ }
+
+ if (conn->binding == false &&
+ le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
+ signing_key = work->sess->smb3signingkey;
+ } else {
+ chann = lookup_chann_list(work->sess, work->conn);
+ if (!chann) {
+ return;
+ }
+ signing_key = chann->smb3signingkey;
+ }
+
+ if (!signing_key)
+ return;
+
+ if (req_hdr->NextCommand)
+ hdr->NextCommand = cpu_to_le32(len);
+
+ hdr->Flags |= SMB2_FLAGS_SIGNED;
+ memset(hdr->Signature, 0, SMB2_SIGNATURE_SIZE);
+ iov[0].iov_base = (char *)&hdr->ProtocolId;
+ iov[0].iov_len = len;
+ if (work->aux_payload_sz) {
+ iov[0].iov_len -= work->aux_payload_sz;
+ iov[1].iov_base = work->aux_payload_buf;
+ iov[1].iov_len = work->aux_payload_sz;
+ n_vec++;
+ }
+
+ if (!ksmbd_sign_smb3_pdu(conn, signing_key, iov, n_vec, signature))
+ memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
+}
+
+/**
+ * smb3_preauth_hash_rsp() - handler for computing preauth hash on response
+ * @work: smb work containing response buffer
+ *
+ */
+void smb3_preauth_hash_rsp(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_session *sess = work->sess;
+ struct smb2_hdr *req, *rsp;
+
+ if (conn->dialect != SMB311_PROT_ID)
+ return;
+
+ WORK_BUFFERS(work, req, rsp);
+
+ if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE &&
+ conn->preauth_info)
+ ksmbd_gen_preauth_integrity_hash(conn, work->response_buf,
+ conn->preauth_info->Preauth_HashValue);
+
+ if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && sess) {
+ __u8 *hash_value;
+
+ if (conn->binding) {
+ struct preauth_session *preauth_sess;
+
+ preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
+ if (!preauth_sess)
+ return;
+ hash_value = preauth_sess->Preauth_HashValue;
+ } else {
+ hash_value = sess->Preauth_HashValue;
+ if (!hash_value)
+ return;
+ }
+ ksmbd_gen_preauth_integrity_hash(conn, work->response_buf,
+ hash_value);
+ }
+}
+
+static void fill_transform_hdr(void *tr_buf, char *old_buf, __le16 cipher_type)
+{
+ struct smb2_transform_hdr *tr_hdr = tr_buf + 4;
+ struct smb2_hdr *hdr = smb2_get_msg(old_buf);
+ unsigned int orig_len = get_rfc1002_len(old_buf);
+
+ /* tr_buf must be cleared by the caller */
+ tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
+ tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
+ tr_hdr->Flags = cpu_to_le16(TRANSFORM_FLAG_ENCRYPTED);
+ if (cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
+ cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+ get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
+ else
+ get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
+ memcpy(&tr_hdr->SessionId, &hdr->SessionId, 8);
+ inc_rfc1001_len(tr_buf, sizeof(struct smb2_transform_hdr));
+ inc_rfc1001_len(tr_buf, orig_len);
+}
+
+int smb3_encrypt_resp(struct ksmbd_work *work)
+{
+ char *buf = work->response_buf;
+ struct kvec iov[3];
+ int rc = -ENOMEM;
+ int buf_size = 0, rq_nvec = 2 + (work->aux_payload_sz ? 1 : 0);
+
+ if (ARRAY_SIZE(iov) < rq_nvec)
+ return -ENOMEM;
+
+ work->tr_buf = kzalloc(sizeof(struct smb2_transform_hdr) + 4, GFP_KERNEL);
+ if (!work->tr_buf)
+ return rc;
+
+ /* fill transform header */
+ fill_transform_hdr(work->tr_buf, buf, work->conn->cipher_type);
+
+ iov[0].iov_base = work->tr_buf;
+ iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
+ buf_size += iov[0].iov_len - 4;
+
+ iov[1].iov_base = buf + 4;
+ iov[1].iov_len = get_rfc1002_len(buf);
+ if (work->aux_payload_sz) {
+ iov[1].iov_len = work->resp_hdr_sz - 4;
+
+ iov[2].iov_base = work->aux_payload_buf;
+ iov[2].iov_len = work->aux_payload_sz;
+ buf_size += iov[2].iov_len;
+ }
+ buf_size += iov[1].iov_len;
+ work->resp_hdr_sz = iov[1].iov_len;
+
+ rc = ksmbd_crypt_message(work, iov, rq_nvec, 1);
+ if (rc)
+ return rc;
+
+ memmove(buf, iov[1].iov_base, iov[1].iov_len);
+ *(__be32 *)work->tr_buf = cpu_to_be32(buf_size);
+
+ return rc;
+}
+
+bool smb3_is_transform_hdr(void *buf)
+{
+ struct smb2_transform_hdr *trhdr = smb2_get_msg(buf);
+
+ return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
+}
+
+int smb3_decrypt_req(struct ksmbd_work *work)
+{
+ struct ksmbd_session *sess;
+ char *buf = work->request_buf;
+ unsigned int pdu_length = get_rfc1002_len(buf);
+ struct kvec iov[2];
+ int buf_data_size = pdu_length - sizeof(struct smb2_transform_hdr);
+ struct smb2_transform_hdr *tr_hdr = smb2_get_msg(buf);
+ int rc = 0;
+
+ if (buf_data_size < sizeof(struct smb2_hdr)) {
+ pr_err("Transform message is too small (%u)\n",
+ pdu_length);
+ return -ECONNABORTED;
+ }
+
+ if (buf_data_size < le32_to_cpu(tr_hdr->OriginalMessageSize)) {
+ pr_err("Transform message is broken\n");
+ return -ECONNABORTED;
+ }
+
+ sess = ksmbd_session_lookup_all(work->conn, le64_to_cpu(tr_hdr->SessionId));
+ if (!sess) {
+ pr_err("invalid session id(%llx) in transform header\n",
+ le64_to_cpu(tr_hdr->SessionId));
+ return -ECONNABORTED;
+ }
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
+ iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr) + 4;
+ iov[1].iov_len = buf_data_size;
+ rc = ksmbd_crypt_message(work, iov, 2, 0);
+ if (rc)
+ return rc;
+
+ memmove(buf + 4, iov[1].iov_base, buf_data_size);
+ *(__be32 *)buf = cpu_to_be32(buf_data_size);
+
+ return rc;
+}
+
+bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_session *sess = work->sess;
+ struct smb2_hdr *rsp = smb2_get_msg(work->response_buf);
+
+ if (conn->dialect < SMB30_PROT_ID)
+ return false;
+
+ if (work->next_smb2_rcv_hdr_off)
+ rsp = ksmbd_resp_buf_next(work);
+
+ if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE &&
+ sess->user && !user_guest(sess->user) &&
+ rsp->Status == STATUS_SUCCESS)
+ return true;
+ return false;
+}
diff --git a/fs/smb/server/smb2pdu.h b/fs/smb/server/smb2pdu.h
new file mode 100644
index 000000000000..dd10f8031606
--- /dev/null
+++ b/fs/smb/server/smb2pdu.h
@@ -0,0 +1,536 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef _SMB2PDU_H
+#define _SMB2PDU_H
+
+#include "ntlmssp.h"
+#include "smbacl.h"
+
+/*Create Action Flags*/
+#define FILE_SUPERSEDED 0x00000000
+#define FILE_OPENED 0x00000001
+#define FILE_CREATED 0x00000002
+#define FILE_OVERWRITTEN 0x00000003
+
+/* SMB2 Max Credits */
+#define SMB2_MAX_CREDITS 8192
+
+/* BB FIXME - analyze following length BB */
+#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
+
+#define SMB21_DEFAULT_IOSIZE (1024 * 1024)
+#define SMB3_DEFAULT_TRANS_SIZE (1024 * 1024)
+#define SMB3_MIN_IOSIZE (64 * 1024)
+#define SMB3_MAX_IOSIZE (8 * 1024 * 1024)
+#define SMB3_MAX_MSGSIZE (4 * 4096)
+
+/*
+ * Definitions for SMB2 Protocol Data Units (network frames)
+ *
+ * See MS-SMB2.PDF specification for protocol details.
+ * The Naming convention is the lower case version of the SMB2
+ * command code name for the struct. Note that structures must be packed.
+ *
+ */
+
+struct preauth_integrity_info {
+ /* PreAuth integrity Hash ID */
+ __le16 Preauth_HashId;
+ /* PreAuth integrity Hash Value */
+ __u8 Preauth_HashValue[SMB2_PREAUTH_HASH_SIZE];
+};
+
+/* offset is sizeof smb2_negotiate_rsp but rounded up to 8 bytes. */
+#ifdef CONFIG_SMB_SERVER_KERBEROS5
+/* sizeof(struct smb2_negotiate_rsp) =
+ * header(64) + response(64) + GSS_LENGTH(96) + GSS_PADDING(0)
+ */
+#define OFFSET_OF_NEG_CONTEXT 0xe0
+#else
+/* sizeof(struct smb2_negotiate_rsp) =
+ * header(64) + response(64) + GSS_LENGTH(74) + GSS_PADDING(6)
+ */
+#define OFFSET_OF_NEG_CONTEXT 0xd0
+#endif
+
+#define SMB2_SESSION_EXPIRED (0)
+#define SMB2_SESSION_IN_PROGRESS BIT(0)
+#define SMB2_SESSION_VALID BIT(1)
+
+#define SMB2_SESSION_TIMEOUT (10 * HZ)
+
+struct create_durable_req_v2 {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __le32 Timeout;
+ __le32 Flags;
+ __u8 Reserved[8];
+ __u8 CreateGuid[16];
+} __packed;
+
+struct create_durable_reconn_req {
+ struct create_context ccontext;
+ __u8 Name[8];
+ union {
+ __u8 Reserved[16];
+ struct {
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ } Fid;
+ } Data;
+} __packed;
+
+struct create_durable_reconn_v2_req {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct {
+ __u64 PersistentFileId;
+ __u64 VolatileFileId;
+ } Fid;
+ __u8 CreateGuid[16];
+ __le32 Flags;
+} __packed;
+
+struct create_app_inst_id {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __u8 Reserved[8];
+ __u8 AppInstanceId[16];
+} __packed;
+
+struct create_app_inst_id_vers {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __u8 Reserved[2];
+ __u8 Padding[4];
+ __le64 AppInstanceVersionHigh;
+ __le64 AppInstanceVersionLow;
+} __packed;
+
+struct create_mxac_req {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __le64 Timestamp;
+} __packed;
+
+struct create_alloc_size_req {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __le64 AllocationSize;
+} __packed;
+
+struct create_durable_rsp {
+ struct create_context ccontext;
+ __u8 Name[8];
+ union {
+ __u8 Reserved[8];
+ __u64 data;
+ } Data;
+} __packed;
+
+struct create_durable_v2_rsp {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __le32 Timeout;
+ __le32 Flags;
+} __packed;
+
+struct create_mxac_rsp {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __le32 QueryStatus;
+ __le32 MaximalAccess;
+} __packed;
+
+struct create_disk_id_rsp {
+ struct create_context ccontext;
+ __u8 Name[8];
+ __le64 DiskFileId;
+ __le64 VolumeId;
+ __u8 Reserved[16];
+} __packed;
+
+/* equivalent of the contents of SMB3.1.1 POSIX open context response */
+struct create_posix_rsp {
+ struct create_context ccontext;
+ __u8 Name[16];
+ __le32 nlink;
+ __le32 reparse_tag;
+ __le32 mode;
+ /* SidBuffer contain two sids(Domain sid(28), UNIX group sid(16)) */
+ u8 SidBuffer[44];
+} __packed;
+
+struct smb2_buffer_desc_v1 {
+ __le64 offset;
+ __le32 token;
+ __le32 length;
+} __packed;
+
+#define SMB2_0_IOCTL_IS_FSCTL 0x00000001
+
+struct smb_sockaddr_in {
+ __be16 Port;
+ __be32 IPv4address;
+ __u8 Reserved[8];
+} __packed;
+
+struct smb_sockaddr_in6 {
+ __be16 Port;
+ __be32 FlowInfo;
+ __u8 IPv6address[16];
+ __be32 ScopeId;
+} __packed;
+
+#define INTERNETWORK 0x0002
+#define INTERNETWORKV6 0x0017
+
+struct sockaddr_storage_rsp {
+ __le16 Family;
+ union {
+ struct smb_sockaddr_in addr4;
+ struct smb_sockaddr_in6 addr6;
+ };
+} __packed;
+
+#define RSS_CAPABLE 0x00000001
+#define RDMA_CAPABLE 0x00000002
+
+struct network_interface_info_ioctl_rsp {
+ __le32 Next; /* next interface. zero if this is last one */
+ __le32 IfIndex;
+ __le32 Capability; /* RSS or RDMA Capable */
+ __le32 Reserved;
+ __le64 LinkSpeed;
+ char SockAddr_Storage[128];
+} __packed;
+
+struct file_object_buf_type1_ioctl_rsp {
+ __u8 ObjectId[16];
+ __u8 BirthVolumeId[16];
+ __u8 BirthObjectId[16];
+ __u8 DomainId[16];
+} __packed;
+
+struct resume_key_ioctl_rsp {
+ __u64 ResumeKey[3];
+ __le32 ContextLength;
+ __u8 Context[4]; /* ignored, Windows sets to 4 bytes of zero */
+} __packed;
+
+struct copychunk_ioctl_req {
+ __le64 ResumeKey[3];
+ __le32 ChunkCount;
+ __le32 Reserved;
+ __u8 Chunks[1]; /* array of srv_copychunk */
+} __packed;
+
+struct srv_copychunk {
+ __le64 SourceOffset;
+ __le64 TargetOffset;
+ __le32 Length;
+ __le32 Reserved;
+} __packed;
+
+struct copychunk_ioctl_rsp {
+ __le32 ChunksWritten;
+ __le32 ChunkBytesWritten;
+ __le32 TotalBytesWritten;
+} __packed;
+
+struct file_sparse {
+ __u8 SetSparse;
+} __packed;
+
+/* FILE Info response size */
+#define FILE_DIRECTORY_INFORMATION_SIZE 1
+#define FILE_FULL_DIRECTORY_INFORMATION_SIZE 2
+#define FILE_BOTH_DIRECTORY_INFORMATION_SIZE 3
+#define FILE_BASIC_INFORMATION_SIZE 40
+#define FILE_STANDARD_INFORMATION_SIZE 24
+#define FILE_INTERNAL_INFORMATION_SIZE 8
+#define FILE_EA_INFORMATION_SIZE 4
+#define FILE_ACCESS_INFORMATION_SIZE 4
+#define FILE_NAME_INFORMATION_SIZE 9
+#define FILE_RENAME_INFORMATION_SIZE 10
+#define FILE_LINK_INFORMATION_SIZE 11
+#define FILE_NAMES_INFORMATION_SIZE 12
+#define FILE_DISPOSITION_INFORMATION_SIZE 13
+#define FILE_POSITION_INFORMATION_SIZE 14
+#define FILE_FULL_EA_INFORMATION_SIZE 15
+#define FILE_MODE_INFORMATION_SIZE 4
+#define FILE_ALIGNMENT_INFORMATION_SIZE 4
+#define FILE_ALL_INFORMATION_SIZE 104
+#define FILE_ALLOCATION_INFORMATION_SIZE 19
+#define FILE_END_OF_FILE_INFORMATION_SIZE 20
+#define FILE_ALTERNATE_NAME_INFORMATION_SIZE 8
+#define FILE_STREAM_INFORMATION_SIZE 32
+#define FILE_PIPE_INFORMATION_SIZE 23
+#define FILE_PIPE_LOCAL_INFORMATION_SIZE 24
+#define FILE_PIPE_REMOTE_INFORMATION_SIZE 25
+#define FILE_MAILSLOT_QUERY_INFORMATION_SIZE 26
+#define FILE_MAILSLOT_SET_INFORMATION_SIZE 27
+#define FILE_COMPRESSION_INFORMATION_SIZE 16
+#define FILE_OBJECT_ID_INFORMATION_SIZE 29
+/* Number 30 not defined in documents */
+#define FILE_MOVE_CLUSTER_INFORMATION_SIZE 31
+#define FILE_QUOTA_INFORMATION_SIZE 32
+#define FILE_REPARSE_POINT_INFORMATION_SIZE 33
+#define FILE_NETWORK_OPEN_INFORMATION_SIZE 56
+#define FILE_ATTRIBUTE_TAG_INFORMATION_SIZE 8
+
+/* FS Info response size */
+#define FS_DEVICE_INFORMATION_SIZE 8
+#define FS_ATTRIBUTE_INFORMATION_SIZE 16
+#define FS_VOLUME_INFORMATION_SIZE 24
+#define FS_SIZE_INFORMATION_SIZE 24
+#define FS_FULL_SIZE_INFORMATION_SIZE 32
+#define FS_SECTOR_SIZE_INFORMATION_SIZE 28
+#define FS_OBJECT_ID_INFORMATION_SIZE 64
+#define FS_CONTROL_INFORMATION_SIZE 48
+#define FS_POSIX_INFORMATION_SIZE 56
+
+/* FS_ATTRIBUTE_File_System_Name */
+#define FS_TYPE_SUPPORT_SIZE 44
+struct fs_type_info {
+ char *fs_name;
+ long magic_number;
+} __packed;
+
+/*
+ * PDU query infolevel structure definitions
+ * BB consider moving to a different header
+ */
+
+struct smb2_file_access_info {
+ __le32 AccessFlags;
+} __packed;
+
+struct smb2_file_alignment_info {
+ __le32 AlignmentRequirement;
+} __packed;
+
+struct smb2_file_basic_info { /* data block encoding of response to level 18 */
+ __le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le32 Attributes;
+ __u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */
+} __packed;
+
+struct smb2_file_alt_name_info {
+ __le32 FileNameLength;
+ char FileName[];
+} __packed;
+
+struct smb2_file_stream_info {
+ __le32 NextEntryOffset;
+ __le32 StreamNameLength;
+ __le64 StreamSize;
+ __le64 StreamAllocationSize;
+ char StreamName[];
+} __packed;
+
+struct smb2_file_ntwrk_info {
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 AllocationSize;
+ __le64 EndOfFile;
+ __le32 Attributes;
+ __le32 Reserved;
+} __packed;
+
+struct smb2_file_standard_info {
+ __le64 AllocationSize;
+ __le64 EndOfFile;
+ __le32 NumberOfLinks; /* hard links */
+ __u8 DeletePending;
+ __u8 Directory;
+ __le16 Reserved;
+} __packed; /* level 18 Query */
+
+struct smb2_file_ea_info {
+ __le32 EASize;
+} __packed;
+
+struct smb2_file_alloc_info {
+ __le64 AllocationSize;
+} __packed;
+
+struct smb2_file_disposition_info {
+ __u8 DeletePending;
+} __packed;
+
+struct smb2_file_pos_info {
+ __le64 CurrentByteOffset;
+} __packed;
+
+#define FILE_MODE_INFO_MASK cpu_to_le32(0x0000100e)
+
+struct smb2_file_mode_info {
+ __le32 Mode;
+} __packed;
+
+#define COMPRESSION_FORMAT_NONE 0x0000
+#define COMPRESSION_FORMAT_LZNT1 0x0002
+
+struct smb2_file_comp_info {
+ __le64 CompressedFileSize;
+ __le16 CompressionFormat;
+ __u8 CompressionUnitShift;
+ __u8 ChunkShift;
+ __u8 ClusterShift;
+ __u8 Reserved[3];
+} __packed;
+
+struct smb2_file_attr_tag_info {
+ __le32 FileAttributes;
+ __le32 ReparseTag;
+} __packed;
+
+#define SL_RESTART_SCAN 0x00000001
+#define SL_RETURN_SINGLE_ENTRY 0x00000002
+#define SL_INDEX_SPECIFIED 0x00000004
+
+struct smb2_ea_info_req {
+ __le32 NextEntryOffset;
+ __u8 EaNameLength;
+ char name[1];
+} __packed; /* level 15 Query */
+
+struct smb2_ea_info {
+ __le32 NextEntryOffset;
+ __u8 Flags;
+ __u8 EaNameLength;
+ __le16 EaValueLength;
+ char name[1];
+ /* optionally followed by value */
+} __packed; /* level 15 Query */
+
+struct create_ea_buf_req {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct smb2_ea_info ea;
+} __packed;
+
+struct create_sd_buf_req {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct smb_ntsd ntsd;
+} __packed;
+
+struct smb2_posix_info {
+ __le32 NextEntryOffset;
+ __u32 Ignored;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 DosAttributes;
+ __le64 Inode;
+ __le32 DeviceId;
+ __le32 Zero;
+ /* beginning of POSIX Create Context Response */
+ __le32 HardLinks;
+ __le32 ReparseTag;
+ __le32 Mode;
+ /* SidBuffer contain two sids (UNIX user sid(16), UNIX group sid(16)) */
+ u8 SidBuffer[32];
+ __le32 name_len;
+ u8 name[1];
+ /*
+ * var sized owner SID
+ * var sized group SID
+ * le32 filenamelength
+ * u8 filename[]
+ */
+} __packed;
+
+/* functions */
+void init_smb2_1_server(struct ksmbd_conn *conn);
+void init_smb3_0_server(struct ksmbd_conn *conn);
+void init_smb3_02_server(struct ksmbd_conn *conn);
+int init_smb3_11_server(struct ksmbd_conn *conn);
+
+void init_smb2_max_read_size(unsigned int sz);
+void init_smb2_max_write_size(unsigned int sz);
+void init_smb2_max_trans_size(unsigned int sz);
+void init_smb2_max_credits(unsigned int sz);
+
+bool is_smb2_neg_cmd(struct ksmbd_work *work);
+bool is_smb2_rsp(struct ksmbd_work *work);
+
+u16 get_smb2_cmd_val(struct ksmbd_work *work);
+void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err);
+int init_smb2_rsp_hdr(struct ksmbd_work *work);
+int smb2_allocate_rsp_buf(struct ksmbd_work *work);
+bool is_chained_smb2_message(struct ksmbd_work *work);
+int init_smb2_neg_rsp(struct ksmbd_work *work);
+void smb2_set_err_rsp(struct ksmbd_work *work);
+int smb2_check_user_session(struct ksmbd_work *work);
+int smb2_get_ksmbd_tcon(struct ksmbd_work *work);
+bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command);
+int smb2_check_sign_req(struct ksmbd_work *work);
+void smb2_set_sign_rsp(struct ksmbd_work *work);
+int smb3_check_sign_req(struct ksmbd_work *work);
+void smb3_set_sign_rsp(struct ksmbd_work *work);
+int find_matching_smb2_dialect(int start_index, __le16 *cli_dialects,
+ __le16 dialects_count);
+struct file_lock *smb_flock_init(struct file *f);
+int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
+ void **arg);
+void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
+struct channel *lookup_chann_list(struct ksmbd_session *sess,
+ struct ksmbd_conn *conn);
+void smb3_preauth_hash_rsp(struct ksmbd_work *work);
+bool smb3_is_transform_hdr(void *buf);
+int smb3_decrypt_req(struct ksmbd_work *work);
+int smb3_encrypt_resp(struct ksmbd_work *work);
+bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work);
+int smb2_set_rsp_credits(struct ksmbd_work *work);
+bool smb3_encryption_negotiated(struct ksmbd_conn *conn);
+
+/* smb2 misc functions */
+int ksmbd_smb2_check_message(struct ksmbd_work *work);
+
+/* smb2 command handlers */
+int smb2_handle_negotiate(struct ksmbd_work *work);
+int smb2_negotiate_request(struct ksmbd_work *work);
+int smb2_sess_setup(struct ksmbd_work *work);
+int smb2_tree_connect(struct ksmbd_work *work);
+int smb2_tree_disconnect(struct ksmbd_work *work);
+int smb2_session_logoff(struct ksmbd_work *work);
+int smb2_open(struct ksmbd_work *work);
+int smb2_query_info(struct ksmbd_work *work);
+int smb2_query_dir(struct ksmbd_work *work);
+int smb2_close(struct ksmbd_work *work);
+int smb2_echo(struct ksmbd_work *work);
+int smb2_set_info(struct ksmbd_work *work);
+int smb2_read(struct ksmbd_work *work);
+int smb2_write(struct ksmbd_work *work);
+int smb2_flush(struct ksmbd_work *work);
+int smb2_cancel(struct ksmbd_work *work);
+int smb2_lock(struct ksmbd_work *work);
+int smb2_ioctl(struct ksmbd_work *work);
+int smb2_oplock_break(struct ksmbd_work *work);
+int smb2_notify(struct ksmbd_work *ksmbd_work);
+
+/*
+ * Get the body of the smb2 message excluding the 4 byte rfc1002 headers
+ * from request/response buffer.
+ */
+static inline void *smb2_get_msg(void *buf)
+{
+ return buf + 4;
+}
+
+#endif /* _SMB2PDU_H */
diff --git a/fs/smb/server/smb_common.c b/fs/smb/server/smb_common.c
new file mode 100644
index 000000000000..05d7f3e910bf
--- /dev/null
+++ b/fs/smb/server/smb_common.c
@@ -0,0 +1,797 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2018 Namjae Jeon <linkinjeon@kernel.org>
+ */
+
+#include <linux/user_namespace.h>
+
+#include "smb_common.h"
+#include "server.h"
+#include "misc.h"
+#include "smbstatus.h"
+#include "connection.h"
+#include "ksmbd_work.h"
+#include "mgmt/user_session.h"
+#include "mgmt/user_config.h"
+#include "mgmt/tree_connect.h"
+#include "mgmt/share_config.h"
+
+/*for shortname implementation */
+static const char basechars[43] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
+#define MANGLE_BASE (sizeof(basechars) / sizeof(char) - 1)
+#define MAGIC_CHAR '~'
+#define PERIOD '.'
+#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
+
+struct smb_protocol {
+ int index;
+ char *name;
+ char *prot;
+ __u16 prot_id;
+};
+
+static struct smb_protocol smb1_protos[] = {
+ {
+ SMB21_PROT,
+ "\2SMB 2.1",
+ "SMB2_10",
+ SMB21_PROT_ID
+ },
+ {
+ SMB2X_PROT,
+ "\2SMB 2.???",
+ "SMB2_22",
+ SMB2X_PROT_ID
+ },
+};
+
+static struct smb_protocol smb2_protos[] = {
+ {
+ SMB21_PROT,
+ "\2SMB 2.1",
+ "SMB2_10",
+ SMB21_PROT_ID
+ },
+ {
+ SMB30_PROT,
+ "\2SMB 3.0",
+ "SMB3_00",
+ SMB30_PROT_ID
+ },
+ {
+ SMB302_PROT,
+ "\2SMB 3.02",
+ "SMB3_02",
+ SMB302_PROT_ID
+ },
+ {
+ SMB311_PROT,
+ "\2SMB 3.1.1",
+ "SMB3_11",
+ SMB311_PROT_ID
+ },
+};
+
+unsigned int ksmbd_server_side_copy_max_chunk_count(void)
+{
+ return 256;
+}
+
+unsigned int ksmbd_server_side_copy_max_chunk_size(void)
+{
+ return (2U << 30) - 1;
+}
+
+unsigned int ksmbd_server_side_copy_max_total_size(void)
+{
+ return (2U << 30) - 1;
+}
+
+inline int ksmbd_min_protocol(void)
+{
+ return SMB21_PROT;
+}
+
+inline int ksmbd_max_protocol(void)
+{
+ return SMB311_PROT;
+}
+
+int ksmbd_lookup_protocol_idx(char *str)
+{
+ int offt = ARRAY_SIZE(smb1_protos) - 1;
+ int len = strlen(str);
+
+ while (offt >= 0) {
+ if (!strncmp(str, smb1_protos[offt].prot, len)) {
+ ksmbd_debug(SMB, "selected %s dialect idx = %d\n",
+ smb1_protos[offt].prot, offt);
+ return smb1_protos[offt].index;
+ }
+ offt--;
+ }
+
+ offt = ARRAY_SIZE(smb2_protos) - 1;
+ while (offt >= 0) {
+ if (!strncmp(str, smb2_protos[offt].prot, len)) {
+ ksmbd_debug(SMB, "selected %s dialect idx = %d\n",
+ smb2_protos[offt].prot, offt);
+ return smb2_protos[offt].index;
+ }
+ offt--;
+ }
+ return -1;
+}
+
+/**
+ * ksmbd_verify_smb_message() - check for valid smb2 request header
+ * @work: smb work
+ *
+ * check for valid smb signature and packet direction(request/response)
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+int ksmbd_verify_smb_message(struct ksmbd_work *work)
+{
+ struct smb2_hdr *smb2_hdr = ksmbd_req_buf_next(work);
+ struct smb_hdr *hdr;
+
+ if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER)
+ return ksmbd_smb2_check_message(work);
+
+ hdr = work->request_buf;
+ if (*(__le32 *)hdr->Protocol == SMB1_PROTO_NUMBER &&
+ hdr->Command == SMB_COM_NEGOTIATE) {
+ work->conn->outstanding_credits++;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * ksmbd_smb_request() - check for valid smb request type
+ * @conn: connection instance
+ *
+ * Return: true on success, otherwise false
+ */
+bool ksmbd_smb_request(struct ksmbd_conn *conn)
+{
+ __le32 *proto = (__le32 *)smb2_get_msg(conn->request_buf);
+
+ if (*proto == SMB2_COMPRESSION_TRANSFORM_ID) {
+ pr_err_ratelimited("smb2 compression not support yet");
+ return false;
+ }
+
+ if (*proto != SMB1_PROTO_NUMBER &&
+ *proto != SMB2_PROTO_NUMBER &&
+ *proto != SMB2_TRANSFORM_PROTO_NUM)
+ return false;
+
+ return true;
+}
+
+static bool supported_protocol(int idx)
+{
+ if (idx == SMB2X_PROT &&
+ (server_conf.min_protocol >= SMB21_PROT ||
+ server_conf.max_protocol <= SMB311_PROT))
+ return true;
+
+ return (server_conf.min_protocol <= idx &&
+ idx <= server_conf.max_protocol);
+}
+
+static char *next_dialect(char *dialect, int *next_off, int bcount)
+{
+ dialect = dialect + *next_off;
+ *next_off = strnlen(dialect, bcount);
+ if (dialect[*next_off] != '\0')
+ return NULL;
+ return dialect;
+}
+
+static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count)
+{
+ int i, seq_num, bcount, next;
+ char *dialect;
+
+ for (i = ARRAY_SIZE(smb1_protos) - 1; i >= 0; i--) {
+ seq_num = 0;
+ next = 0;
+ dialect = cli_dialects;
+ bcount = le16_to_cpu(byte_count);
+ do {
+ dialect = next_dialect(dialect, &next, bcount);
+ if (!dialect)
+ break;
+ ksmbd_debug(SMB, "client requested dialect %s\n",
+ dialect);
+ if (!strcmp(dialect, smb1_protos[i].name)) {
+ if (supported_protocol(smb1_protos[i].index)) {
+ ksmbd_debug(SMB,
+ "selected %s dialect\n",
+ smb1_protos[i].name);
+ if (smb1_protos[i].index == SMB1_PROT)
+ return seq_num;
+ return smb1_protos[i].prot_id;
+ }
+ }
+ seq_num++;
+ bcount -= (++next);
+ } while (bcount > 0);
+ }
+
+ return BAD_PROT_ID;
+}
+
+int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)
+{
+ int i;
+ int count;
+
+ for (i = ARRAY_SIZE(smb2_protos) - 1; i >= 0; i--) {
+ count = le16_to_cpu(dialects_count);
+ while (--count >= 0) {
+ ksmbd_debug(SMB, "client requested dialect 0x%x\n",
+ le16_to_cpu(cli_dialects[count]));
+ if (le16_to_cpu(cli_dialects[count]) !=
+ smb2_protos[i].prot_id)
+ continue;
+
+ if (supported_protocol(smb2_protos[i].index)) {
+ ksmbd_debug(SMB, "selected %s dialect\n",
+ smb2_protos[i].name);
+ return smb2_protos[i].prot_id;
+ }
+ }
+ }
+
+ return BAD_PROT_ID;
+}
+
+static int ksmbd_negotiate_smb_dialect(void *buf)
+{
+ int smb_buf_length = get_rfc1002_len(buf);
+ __le32 proto = ((struct smb2_hdr *)smb2_get_msg(buf))->ProtocolId;
+
+ if (proto == SMB2_PROTO_NUMBER) {
+ struct smb2_negotiate_req *req;
+ int smb2_neg_size =
+ offsetof(struct smb2_negotiate_req, Dialects);
+
+ req = (struct smb2_negotiate_req *)smb2_get_msg(buf);
+ if (smb2_neg_size > smb_buf_length)
+ goto err_out;
+
+ if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) >
+ smb_buf_length)
+ goto err_out;
+
+ return ksmbd_lookup_dialect_by_id(req->Dialects,
+ req->DialectCount);
+ }
+
+ proto = *(__le32 *)((struct smb_hdr *)buf)->Protocol;
+ if (proto == SMB1_PROTO_NUMBER) {
+ struct smb_negotiate_req *req;
+
+ req = (struct smb_negotiate_req *)buf;
+ if (le16_to_cpu(req->ByteCount) < 2)
+ goto err_out;
+
+ if (offsetof(struct smb_negotiate_req, DialectsArray) - 4 +
+ le16_to_cpu(req->ByteCount) > smb_buf_length) {
+ goto err_out;
+ }
+
+ return ksmbd_lookup_dialect_by_name(req->DialectsArray,
+ req->ByteCount);
+ }
+
+err_out:
+ return BAD_PROT_ID;
+}
+
+#define SMB_COM_NEGOTIATE_EX 0x0
+
+/**
+ * get_smb1_cmd_val() - get smb command value from smb header
+ * @work: smb work containing smb header
+ *
+ * Return: smb command value
+ */
+static u16 get_smb1_cmd_val(struct ksmbd_work *work)
+{
+ return SMB_COM_NEGOTIATE_EX;
+}
+
+/**
+ * init_smb1_rsp_hdr() - initialize smb negotiate response header
+ * @work: smb work containing smb request
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+static int init_smb1_rsp_hdr(struct ksmbd_work *work)
+{
+ struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
+ struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
+
+ /*
+ * Remove 4 byte direct TCP header.
+ */
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(sizeof(struct smb_hdr) - 4);
+
+ rsp_hdr->Command = SMB_COM_NEGOTIATE;
+ *(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
+ rsp_hdr->Flags = SMBFLG_RESPONSE;
+ rsp_hdr->Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
+ SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
+ rsp_hdr->Pid = rcv_hdr->Pid;
+ rsp_hdr->Mid = rcv_hdr->Mid;
+ return 0;
+}
+
+/**
+ * smb1_check_user_session() - check for valid session for a user
+ * @work: smb work containing smb request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int smb1_check_user_session(struct ksmbd_work *work)
+{
+ unsigned int cmd = work->conn->ops->get_cmd_val(work);
+
+ if (cmd == SMB_COM_NEGOTIATE_EX)
+ return 0;
+
+ return -EINVAL;
+}
+
+/**
+ * smb1_allocate_rsp_buf() - allocate response buffer for a command
+ * @work: smb work containing smb request
+ *
+ * Return: 0 on success, otherwise -ENOMEM
+ */
+static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
+{
+ work->response_buf = kmalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
+ GFP_KERNEL | __GFP_ZERO);
+ work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
+
+ if (!work->response_buf) {
+ pr_err("Failed to allocate %u bytes buffer\n",
+ MAX_CIFS_SMALL_BUFFER_SIZE);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static struct smb_version_ops smb1_server_ops = {
+ .get_cmd_val = get_smb1_cmd_val,
+ .init_rsp_hdr = init_smb1_rsp_hdr,
+ .allocate_rsp_buf = smb1_allocate_rsp_buf,
+ .check_user_session = smb1_check_user_session,
+};
+
+static int smb1_negotiate(struct ksmbd_work *work)
+{
+ return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE);
+}
+
+static struct smb_version_cmds smb1_server_cmds[1] = {
+ [SMB_COM_NEGOTIATE_EX] = { .proc = smb1_negotiate, },
+};
+
+static void init_smb1_server(struct ksmbd_conn *conn)
+{
+ conn->ops = &smb1_server_ops;
+ conn->cmds = smb1_server_cmds;
+ conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
+}
+
+void ksmbd_init_smb_server(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ __le32 proto;
+
+ if (conn->need_neg == false)
+ return;
+
+ proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
+ if (proto == SMB1_PROTO_NUMBER)
+ init_smb1_server(conn);
+ else
+ init_smb3_11_server(conn);
+}
+
+int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
+ struct ksmbd_file *dir,
+ struct ksmbd_dir_info *d_info,
+ char *search_pattern,
+ int (*fn)(struct ksmbd_conn *, int,
+ struct ksmbd_dir_info *,
+ struct ksmbd_kstat *))
+{
+ int i, rc = 0;
+ struct ksmbd_conn *conn = work->conn;
+ struct user_namespace *user_ns = file_mnt_user_ns(dir->filp);
+
+ for (i = 0; i < 2; i++) {
+ struct kstat kstat;
+ struct ksmbd_kstat ksmbd_kstat;
+ struct dentry *dentry;
+
+ if (!dir->dot_dotdot[i]) { /* fill dot entry info */
+ if (i == 0) {
+ d_info->name = ".";
+ d_info->name_len = 1;
+ dentry = dir->filp->f_path.dentry;
+ } else {
+ d_info->name = "..";
+ d_info->name_len = 2;
+ dentry = dir->filp->f_path.dentry->d_parent;
+ }
+
+ if (!match_pattern(d_info->name, d_info->name_len,
+ search_pattern)) {
+ dir->dot_dotdot[i] = 1;
+ continue;
+ }
+
+ ksmbd_kstat.kstat = &kstat;
+ ksmbd_vfs_fill_dentry_attrs(work,
+ user_ns,
+ dentry,
+ &ksmbd_kstat);
+ rc = fn(conn, info_level, d_info, &ksmbd_kstat);
+ if (rc)
+ break;
+ if (d_info->out_buf_len <= 0)
+ break;
+
+ dir->dot_dotdot[i] = 1;
+ if (d_info->flags & SMB2_RETURN_SINGLE_ENTRY) {
+ d_info->out_buf_len = 0;
+ break;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * ksmbd_extract_shortname() - get shortname from long filename
+ * @conn: connection instance
+ * @longname: source long filename
+ * @shortname: destination short filename
+ *
+ * Return: shortname length or 0 when source long name is '.' or '..'
+ * TODO: Though this function comforms the restriction of 8.3 Filename spec,
+ * but the result is different with Windows 7's one. need to check.
+ */
+int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname,
+ char *shortname)
+{
+ const char *p;
+ char base[9], extension[4];
+ char out[13] = {0};
+ int baselen = 0;
+ int extlen = 0, len = 0;
+ unsigned int csum = 0;
+ const unsigned char *ptr;
+ bool dot_present = true;
+
+ p = longname;
+ if ((*p == '.') || (!(strcmp(p, "..")))) {
+ /*no mangling required */
+ return 0;
+ }
+
+ p = strrchr(longname, '.');
+ if (p == longname) { /*name starts with a dot*/
+ strscpy(extension, "___", strlen("___"));
+ } else {
+ if (p) {
+ p++;
+ while (*p && extlen < 3) {
+ if (*p != '.')
+ extension[extlen++] = toupper(*p);
+ p++;
+ }
+ extension[extlen] = '\0';
+ } else {
+ dot_present = false;
+ }
+ }
+
+ p = longname;
+ if (*p == '.') {
+ p++;
+ longname++;
+ }
+ while (*p && (baselen < 5)) {
+ if (*p != '.')
+ base[baselen++] = toupper(*p);
+ p++;
+ }
+
+ base[baselen] = MAGIC_CHAR;
+ memcpy(out, base, baselen + 1);
+
+ ptr = longname;
+ len = strlen(longname);
+ for (; len > 0; len--, ptr++)
+ csum += *ptr;
+
+ csum = csum % (MANGLE_BASE * MANGLE_BASE);
+ out[baselen + 1] = mangle(csum / MANGLE_BASE);
+ out[baselen + 2] = mangle(csum);
+ out[baselen + 3] = PERIOD;
+
+ if (dot_present)
+ memcpy(&out[baselen + 4], extension, 4);
+ else
+ out[baselen + 4] = '\0';
+ smbConvertToUTF16((__le16 *)shortname, out, PATH_MAX,
+ conn->local_nls, 0);
+ len = strlen(out) * 2;
+ return len;
+}
+
+static int __smb2_negotiate(struct ksmbd_conn *conn)
+{
+ return (conn->dialect >= SMB20_PROT_ID &&
+ conn->dialect <= SMB311_PROT_ID);
+}
+
+static int smb_handle_negotiate(struct ksmbd_work *work)
+{
+ struct smb_negotiate_rsp *neg_rsp = work->response_buf;
+
+ ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
+
+ /* Add 2 byte bcc and 2 byte DialectIndex. */
+ inc_rfc1001_len(work->response_buf, 4);
+ neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
+
+ neg_rsp->hdr.WordCount = 1;
+ neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
+ neg_rsp->ByteCount = 0;
+ return 0;
+}
+
+int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
+{
+ struct ksmbd_conn *conn = work->conn;
+ int ret;
+
+ conn->dialect =
+ ksmbd_negotiate_smb_dialect(work->request_buf);
+ ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
+
+ if (command == SMB2_NEGOTIATE_HE) {
+ ret = smb2_handle_negotiate(work);
+ return ret;
+ }
+
+ if (command == SMB_COM_NEGOTIATE) {
+ if (__smb2_negotiate(conn)) {
+ init_smb3_11_server(conn);
+ init_smb2_neg_rsp(work);
+ ksmbd_debug(SMB, "Upgrade to SMB2 negotiation\n");
+ return 0;
+ }
+ return smb_handle_negotiate(work);
+ }
+
+ pr_err("Unknown SMB negotiation command: %u\n", command);
+ return -EINVAL;
+}
+
+enum SHARED_MODE_ERRORS {
+ SHARE_DELETE_ERROR,
+ SHARE_READ_ERROR,
+ SHARE_WRITE_ERROR,
+ FILE_READ_ERROR,
+ FILE_WRITE_ERROR,
+ FILE_DELETE_ERROR,
+};
+
+static const char * const shared_mode_errors[] = {
+ "Current access mode does not permit SHARE_DELETE",
+ "Current access mode does not permit SHARE_READ",
+ "Current access mode does not permit SHARE_WRITE",
+ "Desired access mode does not permit FILE_READ",
+ "Desired access mode does not permit FILE_WRITE",
+ "Desired access mode does not permit FILE_DELETE",
+};
+
+static void smb_shared_mode_error(int error, struct ksmbd_file *prev_fp,
+ struct ksmbd_file *curr_fp)
+{
+ ksmbd_debug(SMB, "%s\n", shared_mode_errors[error]);
+ ksmbd_debug(SMB, "Current mode: 0x%x Desired mode: 0x%x\n",
+ prev_fp->saccess, curr_fp->daccess);
+}
+
+int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
+{
+ int rc = 0;
+ struct ksmbd_file *prev_fp;
+
+ /*
+ * Lookup fp in master fp list, and check desired access and
+ * shared mode between previous open and current open.
+ */
+ read_lock(&curr_fp->f_ci->m_lock);
+ list_for_each_entry(prev_fp, &curr_fp->f_ci->m_fp_list, node) {
+ if (file_inode(filp) != file_inode(prev_fp->filp))
+ continue;
+
+ if (filp == prev_fp->filp)
+ continue;
+
+ if (ksmbd_stream_fd(prev_fp) && ksmbd_stream_fd(curr_fp))
+ if (strcmp(prev_fp->stream.name, curr_fp->stream.name))
+ continue;
+
+ if (prev_fp->attrib_only != curr_fp->attrib_only)
+ continue;
+
+ if (!(prev_fp->saccess & FILE_SHARE_DELETE_LE) &&
+ curr_fp->daccess & FILE_DELETE_LE) {
+ smb_shared_mode_error(SHARE_DELETE_ERROR,
+ prev_fp,
+ curr_fp);
+ rc = -EPERM;
+ break;
+ }
+
+ /*
+ * Only check FILE_SHARE_DELETE if stream opened and
+ * normal file opened.
+ */
+ if (ksmbd_stream_fd(prev_fp) && !ksmbd_stream_fd(curr_fp))
+ continue;
+
+ if (!(prev_fp->saccess & FILE_SHARE_READ_LE) &&
+ curr_fp->daccess & (FILE_EXECUTE_LE | FILE_READ_DATA_LE)) {
+ smb_shared_mode_error(SHARE_READ_ERROR,
+ prev_fp,
+ curr_fp);
+ rc = -EPERM;
+ break;
+ }
+
+ if (!(prev_fp->saccess & FILE_SHARE_WRITE_LE) &&
+ curr_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE)) {
+ smb_shared_mode_error(SHARE_WRITE_ERROR,
+ prev_fp,
+ curr_fp);
+ rc = -EPERM;
+ break;
+ }
+
+ if (prev_fp->daccess & (FILE_EXECUTE_LE | FILE_READ_DATA_LE) &&
+ !(curr_fp->saccess & FILE_SHARE_READ_LE)) {
+ smb_shared_mode_error(FILE_READ_ERROR,
+ prev_fp,
+ curr_fp);
+ rc = -EPERM;
+ break;
+ }
+
+ if (prev_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE) &&
+ !(curr_fp->saccess & FILE_SHARE_WRITE_LE)) {
+ smb_shared_mode_error(FILE_WRITE_ERROR,
+ prev_fp,
+ curr_fp);
+ rc = -EPERM;
+ break;
+ }
+
+ if (prev_fp->daccess & FILE_DELETE_LE &&
+ !(curr_fp->saccess & FILE_SHARE_DELETE_LE)) {
+ smb_shared_mode_error(FILE_DELETE_ERROR,
+ prev_fp,
+ curr_fp);
+ rc = -EPERM;
+ break;
+ }
+ }
+ read_unlock(&curr_fp->f_ci->m_lock);
+
+ return rc;
+}
+
+bool is_asterisk(char *p)
+{
+ return p && p[0] == '*';
+}
+
+int ksmbd_override_fsids(struct ksmbd_work *work)
+{
+ struct ksmbd_session *sess = work->sess;
+ struct ksmbd_share_config *share = work->tcon->share_conf;
+ struct cred *cred;
+ struct group_info *gi;
+ unsigned int uid;
+ unsigned int gid;
+
+ uid = user_uid(sess->user);
+ gid = user_gid(sess->user);
+ if (share->force_uid != KSMBD_SHARE_INVALID_UID)
+ uid = share->force_uid;
+ if (share->force_gid != KSMBD_SHARE_INVALID_GID)
+ gid = share->force_gid;
+
+ cred = prepare_kernel_cred(NULL);
+ if (!cred)
+ return -ENOMEM;
+
+ cred->fsuid = make_kuid(&init_user_ns, uid);
+ cred->fsgid = make_kgid(&init_user_ns, gid);
+
+ gi = groups_alloc(0);
+ if (!gi) {
+ abort_creds(cred);
+ return -ENOMEM;
+ }
+ set_groups(cred, gi);
+ put_group_info(gi);
+
+ if (!uid_eq(cred->fsuid, GLOBAL_ROOT_UID))
+ cred->cap_effective = cap_drop_fs_set(cred->cap_effective);
+
+ WARN_ON(work->saved_cred);
+ work->saved_cred = override_creds(cred);
+ if (!work->saved_cred) {
+ abort_creds(cred);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void ksmbd_revert_fsids(struct ksmbd_work *work)
+{
+ const struct cred *cred;
+
+ WARN_ON(!work->saved_cred);
+
+ cred = current_cred();
+ revert_creds(work->saved_cred);
+ put_cred(cred);
+ work->saved_cred = NULL;
+}
+
+__le32 smb_map_generic_desired_access(__le32 daccess)
+{
+ if (daccess & FILE_GENERIC_READ_LE) {
+ daccess |= cpu_to_le32(GENERIC_READ_FLAGS);
+ daccess &= ~FILE_GENERIC_READ_LE;
+ }
+
+ if (daccess & FILE_GENERIC_WRITE_LE) {
+ daccess |= cpu_to_le32(GENERIC_WRITE_FLAGS);
+ daccess &= ~FILE_GENERIC_WRITE_LE;
+ }
+
+ if (daccess & FILE_GENERIC_EXECUTE_LE) {
+ daccess |= cpu_to_le32(GENERIC_EXECUTE_FLAGS);
+ daccess &= ~FILE_GENERIC_EXECUTE_LE;
+ }
+
+ if (daccess & FILE_GENERIC_ALL_LE) {
+ daccess |= cpu_to_le32(GENERIC_ALL_FLAGS);
+ daccess &= ~FILE_GENERIC_ALL_LE;
+ }
+
+ return daccess;
+}
diff --git a/fs/smb/server/smb_common.h b/fs/smb/server/smb_common.h
new file mode 100644
index 000000000000..e63d2a4f466b
--- /dev/null
+++ b/fs/smb/server/smb_common.h
@@ -0,0 +1,468 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __SMB_COMMON_H__
+#define __SMB_COMMON_H__
+
+#include <linux/kernel.h>
+
+#include "glob.h"
+#include "nterr.h"
+#include "../common/smb2pdu.h"
+#include "smb2pdu.h"
+
+/* ksmbd's Specific ERRNO */
+#define ESHARE 50000
+
+#define SMB1_PROT 0
+#define SMB2_PROT 1
+#define SMB21_PROT 2
+/* multi-protocol negotiate request */
+#define SMB2X_PROT 3
+#define SMB30_PROT 4
+#define SMB302_PROT 5
+#define SMB311_PROT 6
+#define BAD_PROT 0xFFFF
+
+#define SMB1_VERSION_STRING "1.0"
+#define SMB20_VERSION_STRING "2.0"
+#define SMB21_VERSION_STRING "2.1"
+#define SMB30_VERSION_STRING "3.0"
+#define SMB302_VERSION_STRING "3.02"
+#define SMB311_VERSION_STRING "3.1.1"
+
+#define SMB_ECHO_INTERVAL (60 * HZ)
+
+#define CIFS_DEFAULT_IOSIZE (64 * 1024)
+#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
+
+#define MAX_STREAM_PROT_LEN 0x00FFFFFF
+
+/* Responses when opening a file. */
+#define F_SUPERSEDED 0
+#define F_OPENED 1
+#define F_CREATED 2
+#define F_OVERWRITTEN 3
+
+/*
+ * File Attribute flags
+ */
+#define ATTR_POSIX_SEMANTICS 0x01000000
+#define ATTR_BACKUP_SEMANTICS 0x02000000
+#define ATTR_DELETE_ON_CLOSE 0x04000000
+#define ATTR_SEQUENTIAL_SCAN 0x08000000
+#define ATTR_RANDOM_ACCESS 0x10000000
+#define ATTR_NO_BUFFERING 0x20000000
+#define ATTR_WRITE_THROUGH 0x80000000
+
+/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */
+#define FILE_SUPPORTS_SPARSE_VDL 0x10000000 /* faster nonsparse extend */
+#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000 /* allow ioctl dup extents */
+#define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000
+#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
+#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
+#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
+#define FILE_SUPPORTS_HARD_LINKS 0x00400000
+#define FILE_SUPPORTS_TRANSACTIONS 0x00200000
+#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
+#define FILE_READ_ONLY_VOLUME 0x00080000
+#define FILE_NAMED_STREAMS 0x00040000
+#define FILE_SUPPORTS_ENCRYPTION 0x00020000
+#define FILE_SUPPORTS_OBJECT_IDS 0x00010000
+#define FILE_VOLUME_IS_COMPRESSED 0x00008000
+#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100
+#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080
+#define FILE_SUPPORTS_SPARSE_FILES 0x00000040
+#define FILE_VOLUME_QUOTAS 0x00000020
+#define FILE_FILE_COMPRESSION 0x00000010
+#define FILE_PERSISTENT_ACLS 0x00000008
+#define FILE_UNICODE_ON_DISK 0x00000004
+#define FILE_CASE_PRESERVED_NAMES 0x00000002
+#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
+
+#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
+#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
+#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
+#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
+/* with the file can be read */
+#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
+/* with the file can be written */
+#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
+/* the file using system paging I/O */
+#define FILE_DELETE_CHILD 0x00000040
+#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
+/* file can be read */
+#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
+/* file can be written */
+#define DELETE 0x00010000 /* The file can be deleted */
+#define READ_CONTROL 0x00020000 /* The access control list and */
+/* ownership associated with the */
+/* file can be read */
+#define WRITE_DAC 0x00040000 /* The access control list and */
+/* ownership associated with the */
+/* file can be written. */
+#define WRITE_OWNER 0x00080000 /* Ownership information associated */
+/* with the file can be written */
+#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
+/* synchronize with the completion */
+/* of an input/output request */
+#define GENERIC_ALL 0x10000000
+#define GENERIC_EXECUTE 0x20000000
+#define GENERIC_WRITE 0x40000000
+#define GENERIC_READ 0x80000000
+/* In summary - Relevant file */
+/* access flags from CIFS are */
+/* file_read_data, file_write_data */
+/* file_execute, file_read_attributes*/
+/* write_dac, and delete. */
+
+#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \
+ | FILE_READ_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
+ | FILE_WRITE_EA \
+ | FILE_DELETE_CHILD \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
+ | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+
+#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \
+ | READ_CONTROL | SYNCHRONIZE)
+
+/* generic flags for file open */
+#define GENERIC_READ_FLAGS (READ_CONTROL | FILE_READ_DATA | \
+ FILE_READ_ATTRIBUTES | \
+ FILE_READ_EA | SYNCHRONIZE)
+
+#define GENERIC_WRITE_FLAGS (READ_CONTROL | FILE_WRITE_DATA | \
+ FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | \
+ FILE_APPEND_DATA | SYNCHRONIZE)
+
+#define GENERIC_EXECUTE_FLAGS (READ_CONTROL | FILE_EXECUTE | \
+ FILE_READ_ATTRIBUTES | SYNCHRONIZE)
+
+#define GENERIC_ALL_FLAGS (DELETE | READ_CONTROL | WRITE_DAC | \
+ WRITE_OWNER | SYNCHRONIZE | FILE_READ_DATA | \
+ FILE_WRITE_DATA | FILE_APPEND_DATA | \
+ FILE_READ_EA | FILE_WRITE_EA | \
+ FILE_EXECUTE | FILE_DELETE_CHILD | \
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)
+
+#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff)
+#define SMB_COM_NEGOTIATE 0x72
+#define SMB1_CLIENT_GUID_SIZE (16)
+
+#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
+
+#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
+#define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
+#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
+#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
+
+struct smb_hdr {
+ __be32 smb_buf_length;
+ __u8 Protocol[4];
+ __u8 Command;
+ union {
+ struct {
+ __u8 ErrorClass;
+ __u8 Reserved;
+ __le16 Error;
+ } __packed DosError;
+ __le32 CifsError;
+ } __packed Status;
+ __u8 Flags;
+ __le16 Flags2; /* note: le */
+ __le16 PidHigh;
+ union {
+ struct {
+ __le32 SequenceNumber; /* le */
+ __u32 Reserved; /* zero */
+ } __packed Sequence;
+ __u8 SecuritySignature[8]; /* le */
+ } __packed Signature;
+ __u8 pad[2];
+ __le16 Tid;
+ __le16 Pid;
+ __le16 Uid;
+ __le16 Mid;
+ __u8 WordCount;
+} __packed;
+
+struct smb_negotiate_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __le16 ByteCount;
+ unsigned char DialectsArray[1];
+} __packed;
+
+struct smb_negotiate_rsp {
+ struct smb_hdr hdr; /* wct = 17 */
+ __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
+ __le16 ByteCount;
+} __packed;
+
+struct filesystem_attribute_info {
+ __le32 Attributes;
+ __le32 MaxPathNameComponentLength;
+ __le32 FileSystemNameLen;
+ __le16 FileSystemName[1]; /* do not have to save this - get subset? */
+} __packed;
+
+struct filesystem_device_info {
+ __le32 DeviceType;
+ __le32 DeviceCharacteristics;
+} __packed; /* device info level 0x104 */
+
+struct filesystem_vol_info {
+ __le64 VolumeCreationTime;
+ __le32 SerialNumber;
+ __le32 VolumeLabelSize;
+ __le16 Reserved;
+ __le16 VolumeLabel[1];
+} __packed;
+
+struct filesystem_info {
+ __le64 TotalAllocationUnits;
+ __le64 FreeAllocationUnits;
+ __le32 SectorsPerAllocationUnit;
+ __le32 BytesPerSector;
+} __packed; /* size info, level 0x103 */
+
+#define EXTENDED_INFO_MAGIC 0x43667364 /* Cfsd */
+#define STRING_LENGTH 28
+
+struct fs_extended_info {
+ __le32 magic;
+ __le32 version;
+ __le32 release;
+ __u64 rel_date;
+ char version_string[STRING_LENGTH];
+} __packed;
+
+struct object_id_info {
+ char objid[16];
+ struct fs_extended_info extended_info;
+} __packed;
+
+struct file_directory_info {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ char FileName[1];
+} __packed; /* level 0x101 FF resp data */
+
+struct file_names_info {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le32 FileNameLength;
+ char FileName[1];
+} __packed; /* level 0xc FF resp data */
+
+struct file_full_directory_info {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ __le32 EaSize;
+ char FileName[1];
+} __packed; /* level 0x102 FF resp */
+
+struct file_both_directory_info {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ __le32 EaSize; /* length of the xattrs */
+ __u8 ShortNameLength;
+ __u8 Reserved;
+ __u8 ShortName[24];
+ char FileName[1];
+} __packed; /* level 0x104 FFrsp data */
+
+struct file_id_both_directory_info {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ __le32 EaSize; /* length of the xattrs */
+ __u8 ShortNameLength;
+ __u8 Reserved;
+ __u8 ShortName[24];
+ __le16 Reserved2;
+ __le64 UniqueId;
+ char FileName[1];
+} __packed;
+
+struct file_id_full_dir_info {
+ __le32 NextEntryOffset;
+ __u32 FileIndex;
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+ __le64 ChangeTime;
+ __le64 EndOfFile;
+ __le64 AllocationSize;
+ __le32 ExtFileAttributes;
+ __le32 FileNameLength;
+ __le32 EaSize; /* EA size */
+ __le32 Reserved;
+ __le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
+ char FileName[1];
+} __packed; /* level 0x105 FF rsp data */
+
+struct smb_version_values {
+ char *version_string;
+ __u16 protocol_id;
+ __le16 lock_cmd;
+ __u32 capabilities;
+ __u32 max_read_size;
+ __u32 max_write_size;
+ __u32 max_trans_size;
+ __u32 max_credits;
+ __u32 large_lock_type;
+ __u32 exclusive_lock_type;
+ __u32 shared_lock_type;
+ __u32 unlock_lock_type;
+ size_t header_size;
+ size_t max_header_size;
+ size_t read_rsp_size;
+ unsigned int cap_unix;
+ unsigned int cap_nt_find;
+ unsigned int cap_large_files;
+ __u16 signing_enabled;
+ __u16 signing_required;
+ size_t create_lease_size;
+ size_t create_durable_size;
+ size_t create_durable_v2_size;
+ size_t create_mxac_size;
+ size_t create_disk_id_size;
+ size_t create_posix_size;
+};
+
+struct filesystem_posix_info {
+ /* For undefined recommended transfer size return -1 in that field */
+ __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
+ __le32 BlockSize;
+ /* The next three fields are in terms of the block size.
+ * (above). If block size is unknown, 4096 would be a
+ * reasonable block size for a server to report.
+ * Note that returning the blocks/blocksavail removes need
+ * to make a second call (to QFSInfo level 0x103 to get this info.
+ * UserBlockAvail is typically less than or equal to BlocksAvail,
+ * if no distinction is made return the same value in each
+ */
+ __le64 TotalBlocks;
+ __le64 BlocksAvail; /* bfree */
+ __le64 UserBlocksAvail; /* bavail */
+ /* For undefined Node fields or FSID return -1 */
+ __le64 TotalFileNodes;
+ __le64 FreeFileNodes;
+ __le64 FileSysIdentifier; /* fsid */
+ /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
+ /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
+} __packed;
+
+struct smb_version_ops {
+ u16 (*get_cmd_val)(struct ksmbd_work *swork);
+ int (*init_rsp_hdr)(struct ksmbd_work *swork);
+ void (*set_rsp_status)(struct ksmbd_work *swork, __le32 err);
+ int (*allocate_rsp_buf)(struct ksmbd_work *work);
+ int (*set_rsp_credits)(struct ksmbd_work *work);
+ int (*check_user_session)(struct ksmbd_work *work);
+ int (*get_ksmbd_tcon)(struct ksmbd_work *work);
+ bool (*is_sign_req)(struct ksmbd_work *work, unsigned int command);
+ int (*check_sign_req)(struct ksmbd_work *work);
+ void (*set_sign_rsp)(struct ksmbd_work *work);
+ int (*generate_signingkey)(struct ksmbd_session *sess, struct ksmbd_conn *conn);
+ int (*generate_encryptionkey)(struct ksmbd_conn *conn, struct ksmbd_session *sess);
+ bool (*is_transform_hdr)(void *buf);
+ int (*decrypt_req)(struct ksmbd_work *work);
+ int (*encrypt_resp)(struct ksmbd_work *work);
+};
+
+struct smb_version_cmds {
+ int (*proc)(struct ksmbd_work *swork);
+};
+
+int ksmbd_min_protocol(void);
+int ksmbd_max_protocol(void);
+
+int ksmbd_lookup_protocol_idx(char *str);
+
+int ksmbd_verify_smb_message(struct ksmbd_work *work);
+bool ksmbd_smb_request(struct ksmbd_conn *conn);
+
+int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
+
+void ksmbd_init_smb_server(struct ksmbd_work *work);
+
+struct ksmbd_kstat;
+int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
+ int info_level,
+ struct ksmbd_file *dir,
+ struct ksmbd_dir_info *d_info,
+ char *search_pattern,
+ int (*fn)(struct ksmbd_conn *,
+ int,
+ struct ksmbd_dir_info *,
+ struct ksmbd_kstat *));
+
+int ksmbd_extract_shortname(struct ksmbd_conn *conn,
+ const char *longname,
+ char *shortname);
+
+int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command);
+
+int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp);
+int ksmbd_override_fsids(struct ksmbd_work *work);
+void ksmbd_revert_fsids(struct ksmbd_work *work);
+
+unsigned int ksmbd_server_side_copy_max_chunk_count(void);
+unsigned int ksmbd_server_side_copy_max_chunk_size(void);
+unsigned int ksmbd_server_side_copy_max_total_size(void);
+bool is_asterisk(char *p);
+__le32 smb_map_generic_desired_access(__le32 daccess);
+
+static inline unsigned int get_rfc1002_len(void *buf)
+{
+ return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
+}
+
+static inline void inc_rfc1001_len(void *buf, int count)
+{
+ be32_add_cpu((__be32 *)buf, count);
+}
+#endif /* __SMB_COMMON_H__ */
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
new file mode 100644
index 000000000000..b05ff9b146b5
--- /dev/null
+++ b/fs/smb/server/smbacl.c
@@ -0,0 +1,1436 @@
+// SPDX-License-Identifier: LGPL-2.1+
+/*
+ * Copyright (C) International Business Machines Corp., 2007,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Copyright (C) 2020 Samsung Electronics Co., Ltd.
+ * Author(s): Namjae Jeon <linkinjeon@kernel.org>
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/mnt_idmapping.h>
+
+#include "smbacl.h"
+#include "smb_common.h"
+#include "server.h"
+#include "misc.h"
+#include "mgmt/share_config.h"
+
+static const struct smb_sid domain = {1, 4, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(21), cpu_to_le32(1), cpu_to_le32(2), cpu_to_le32(3),
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* security id for everyone/world system group */
+static const struct smb_sid creator_owner = {
+ 1, 1, {0, 0, 0, 0, 0, 3}, {0} };
+/* security id for everyone/world system group */
+static const struct smb_sid creator_group = {
+ 1, 1, {0, 0, 0, 0, 0, 3}, {cpu_to_le32(1)} };
+
+/* security id for everyone/world system group */
+static const struct smb_sid sid_everyone = {
+ 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
+/* security id for Authenticated Users system group */
+static const struct smb_sid sid_authusers = {
+ 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
+
+/* S-1-22-1 Unmapped Unix users */
+static const struct smb_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
+ {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* S-1-22-2 Unmapped Unix groups */
+static const struct smb_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
+ {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/*
+ * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
+ */
+
+/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
+
+/* S-1-5-88-1 Unix uid */
+static const struct smb_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(88),
+ cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* S-1-5-88-2 Unix gid */
+static const struct smb_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(88),
+ cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/* S-1-5-88-3 Unix mode */
+static const struct smb_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
+ {cpu_to_le32(88),
+ cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
+
+/*
+ * if the two SIDs (roughly equivalent to a UUID for a user or group) are
+ * the same returns zero, if they do not match returns non-zero.
+ */
+int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid)
+{
+ int i;
+ int num_subauth, num_sat, num_saw;
+
+ if (!ctsid || !cwsid)
+ return 1;
+
+ /* compare the revision */
+ if (ctsid->revision != cwsid->revision) {
+ if (ctsid->revision > cwsid->revision)
+ return 1;
+ else
+ return -1;
+ }
+
+ /* compare all of the six auth values */
+ for (i = 0; i < NUM_AUTHS; ++i) {
+ if (ctsid->authority[i] != cwsid->authority[i]) {
+ if (ctsid->authority[i] > cwsid->authority[i])
+ return 1;
+ else
+ return -1;
+ }
+ }
+
+ /* compare all of the subauth values if any */
+ num_sat = ctsid->num_subauth;
+ num_saw = cwsid->num_subauth;
+ num_subauth = num_sat < num_saw ? num_sat : num_saw;
+ if (num_subauth) {
+ for (i = 0; i < num_subauth; ++i) {
+ if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
+ if (le32_to_cpu(ctsid->sub_auth[i]) >
+ le32_to_cpu(cwsid->sub_auth[i]))
+ return 1;
+ else
+ return -1;
+ }
+ }
+ }
+
+ return 0; /* sids compare/match */
+}
+
+static void smb_copy_sid(struct smb_sid *dst, const struct smb_sid *src)
+{
+ int i;
+
+ dst->revision = src->revision;
+ dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
+ for (i = 0; i < NUM_AUTHS; ++i)
+ dst->authority[i] = src->authority[i];
+ for (i = 0; i < dst->num_subauth; ++i)
+ dst->sub_auth[i] = src->sub_auth[i];
+}
+
+/*
+ * change posix mode to reflect permissions
+ * pmode is the existing mode (we only want to overwrite part of this
+ * bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
+ */
+static umode_t access_flags_to_mode(struct smb_fattr *fattr, __le32 ace_flags,
+ int type)
+{
+ __u32 flags = le32_to_cpu(ace_flags);
+ umode_t mode = 0;
+
+ if (flags & GENERIC_ALL) {
+ mode = 0777;
+ ksmbd_debug(SMB, "all perms\n");
+ return mode;
+ }
+
+ if ((flags & GENERIC_READ) || (flags & FILE_READ_RIGHTS))
+ mode = 0444;
+ if ((flags & GENERIC_WRITE) || (flags & FILE_WRITE_RIGHTS)) {
+ mode |= 0222;
+ if (S_ISDIR(fattr->cf_mode))
+ mode |= 0111;
+ }
+ if ((flags & GENERIC_EXECUTE) || (flags & FILE_EXEC_RIGHTS))
+ mode |= 0111;
+
+ if (type == ACCESS_DENIED_ACE_TYPE || type == ACCESS_DENIED_OBJECT_ACE_TYPE)
+ mode = ~mode;
+
+ ksmbd_debug(SMB, "access flags 0x%x mode now %04o\n", flags, mode);
+
+ return mode;
+}
+
+/*
+ * Generate access flags to reflect permissions mode is the existing mode.
+ * This function is called for every ACE in the DACL whose SID matches
+ * with either owner or group or everyone.
+ */
+static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
+ __u32 *pace_flags)
+{
+ /* reset access mask */
+ *pace_flags = 0x0;
+
+ /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
+ mode &= bits_to_use;
+
+ /*
+ * check for R/W/X UGO since we do not know whose flags
+ * is this but we have cleared all the bits sans RWX for
+ * either user or group or other as per bits_to_use
+ */
+ if (mode & 0444)
+ *pace_flags |= SET_FILE_READ_RIGHTS;
+ if (mode & 0222)
+ *pace_flags |= FILE_WRITE_RIGHTS;
+ if (mode & 0111)
+ *pace_flags |= SET_FILE_EXEC_RIGHTS;
+
+ ksmbd_debug(SMB, "mode: %o, access flags now 0x%x\n",
+ mode, *pace_flags);
+}
+
+static __u16 fill_ace_for_sid(struct smb_ace *pntace,
+ const struct smb_sid *psid, int type, int flags,
+ umode_t mode, umode_t bits)
+{
+ int i;
+ __u16 size = 0;
+ __u32 access_req = 0;
+
+ pntace->type = type;
+ pntace->flags = flags;
+ mode_to_access_flags(mode, bits, &access_req);
+ if (!access_req)
+ access_req = SET_MINIMUM_RIGHTS;
+ pntace->access_req = cpu_to_le32(access_req);
+
+ pntace->sid.revision = psid->revision;
+ pntace->sid.num_subauth = psid->num_subauth;
+ for (i = 0; i < NUM_AUTHS; i++)
+ pntace->sid.authority[i] = psid->authority[i];
+ for (i = 0; i < psid->num_subauth; i++)
+ pntace->sid.sub_auth[i] = psid->sub_auth[i];
+
+ size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
+ pntace->size = cpu_to_le16(size);
+
+ return size;
+}
+
+void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid)
+{
+ switch (sidtype) {
+ case SIDOWNER:
+ smb_copy_sid(ssid, &server_conf.domain_sid);
+ break;
+ case SIDUNIX_USER:
+ smb_copy_sid(ssid, &sid_unix_users);
+ break;
+ case SIDUNIX_GROUP:
+ smb_copy_sid(ssid, &sid_unix_groups);
+ break;
+ case SIDCREATOR_OWNER:
+ smb_copy_sid(ssid, &creator_owner);
+ return;
+ case SIDCREATOR_GROUP:
+ smb_copy_sid(ssid, &creator_group);
+ return;
+ case SIDNFS_USER:
+ smb_copy_sid(ssid, &sid_unix_NFS_users);
+ break;
+ case SIDNFS_GROUP:
+ smb_copy_sid(ssid, &sid_unix_NFS_groups);
+ break;
+ case SIDNFS_MODE:
+ smb_copy_sid(ssid, &sid_unix_NFS_mode);
+ break;
+ default:
+ return;
+ }
+
+ /* RID */
+ ssid->sub_auth[ssid->num_subauth] = cpu_to_le32(cid);
+ ssid->num_subauth++;
+}
+
+static int sid_to_id(struct user_namespace *user_ns,
+ struct smb_sid *psid, uint sidtype,
+ struct smb_fattr *fattr)
+{
+ int rc = -EINVAL;
+
+ /*
+ * If we have too many subauthorities, then something is really wrong.
+ * Just return an error.
+ */
+ if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
+ pr_err("%s: %u subauthorities is too many!\n",
+ __func__, psid->num_subauth);
+ return -EIO;
+ }
+
+ if (sidtype == SIDOWNER) {
+ kuid_t uid;
+ uid_t id;
+
+ id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
+ uid = KUIDT_INIT(id);
+ uid = from_vfsuid(user_ns, &init_user_ns, VFSUIDT_INIT(uid));
+ if (uid_valid(uid)) {
+ fattr->cf_uid = uid;
+ rc = 0;
+ }
+ } else {
+ kgid_t gid;
+ gid_t id;
+
+ id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
+ gid = KGIDT_INIT(id);
+ gid = from_vfsgid(user_ns, &init_user_ns, VFSGIDT_INIT(gid));
+ if (gid_valid(gid)) {
+ fattr->cf_gid = gid;
+ rc = 0;
+ }
+ }
+
+ return rc;
+}
+
+void posix_state_to_acl(struct posix_acl_state *state,
+ struct posix_acl_entry *pace)
+{
+ int i;
+
+ pace->e_tag = ACL_USER_OBJ;
+ pace->e_perm = state->owner.allow;
+ for (i = 0; i < state->users->n; i++) {
+ pace++;
+ pace->e_tag = ACL_USER;
+ pace->e_uid = state->users->aces[i].uid;
+ pace->e_perm = state->users->aces[i].perms.allow;
+ }
+
+ pace++;
+ pace->e_tag = ACL_GROUP_OBJ;
+ pace->e_perm = state->group.allow;
+
+ for (i = 0; i < state->groups->n; i++) {
+ pace++;
+ pace->e_tag = ACL_GROUP;
+ pace->e_gid = state->groups->aces[i].gid;
+ pace->e_perm = state->groups->aces[i].perms.allow;
+ }
+
+ if (state->users->n || state->groups->n) {
+ pace++;
+ pace->e_tag = ACL_MASK;
+ pace->e_perm = state->mask.allow;
+ }
+
+ pace++;
+ pace->e_tag = ACL_OTHER;
+ pace->e_perm = state->other.allow;
+}
+
+int init_acl_state(struct posix_acl_state *state, int cnt)
+{
+ int alloc;
+
+ memset(state, 0, sizeof(struct posix_acl_state));
+ /*
+ * In the worst case, each individual acl could be for a distinct
+ * named user or group, but we don't know which, so we allocate
+ * enough space for either:
+ */
+ alloc = sizeof(struct posix_ace_state_array)
+ + cnt * sizeof(struct posix_user_ace_state);
+ state->users = kzalloc(alloc, GFP_KERNEL);
+ if (!state->users)
+ return -ENOMEM;
+ state->groups = kzalloc(alloc, GFP_KERNEL);
+ if (!state->groups) {
+ kfree(state->users);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+void free_acl_state(struct posix_acl_state *state)
+{
+ kfree(state->users);
+ kfree(state->groups);
+}
+
+static void parse_dacl(struct user_namespace *user_ns,
+ struct smb_acl *pdacl, char *end_of_acl,
+ struct smb_sid *pownersid, struct smb_sid *pgrpsid,
+ struct smb_fattr *fattr)
+{
+ int i, ret;
+ int num_aces = 0;
+ unsigned int acl_size;
+ char *acl_base;
+ struct smb_ace **ppace;
+ struct posix_acl_entry *cf_pace, *cf_pdace;
+ struct posix_acl_state acl_state, default_acl_state;
+ umode_t mode = 0, acl_mode;
+ bool owner_found = false, group_found = false, others_found = false;
+
+ if (!pdacl)
+ return;
+
+ /* validate that we do not go past end of acl */
+ if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) ||
+ end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
+ pr_err("ACL too small to parse DACL\n");
+ return;
+ }
+
+ ksmbd_debug(SMB, "DACL revision %d size %d num aces %d\n",
+ le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
+ le32_to_cpu(pdacl->num_aces));
+
+ acl_base = (char *)pdacl;
+ acl_size = sizeof(struct smb_acl);
+
+ num_aces = le32_to_cpu(pdacl->num_aces);
+ if (num_aces <= 0)
+ return;
+
+ if (num_aces > ULONG_MAX / sizeof(struct smb_ace *))
+ return;
+
+ ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), GFP_KERNEL);
+ if (!ppace)
+ return;
+
+ ret = init_acl_state(&acl_state, num_aces);
+ if (ret)
+ return;
+ ret = init_acl_state(&default_acl_state, num_aces);
+ if (ret) {
+ free_acl_state(&acl_state);
+ return;
+ }
+
+ /*
+ * reset rwx permissions for user/group/other.
+ * Also, if num_aces is 0 i.e. DACL has no ACEs,
+ * user/group/other have no permissions
+ */
+ for (i = 0; i < num_aces; ++i) {
+ if (end_of_acl - acl_base < acl_size)
+ break;
+
+ ppace[i] = (struct smb_ace *)(acl_base + acl_size);
+ acl_base = (char *)ppace[i];
+ acl_size = offsetof(struct smb_ace, sid) +
+ offsetof(struct smb_sid, sub_auth);
+
+ if (end_of_acl - acl_base < acl_size ||
+ ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
+ (end_of_acl - acl_base <
+ acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||
+ (le16_to_cpu(ppace[i]->size) <
+ acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth))
+ break;
+
+ acl_size = le16_to_cpu(ppace[i]->size);
+ ppace[i]->access_req =
+ smb_map_generic_desired_access(ppace[i]->access_req);
+
+ if (!(compare_sids(&ppace[i]->sid, &sid_unix_NFS_mode))) {
+ fattr->cf_mode =
+ le32_to_cpu(ppace[i]->sid.sub_auth[2]);
+ break;
+ } else if (!compare_sids(&ppace[i]->sid, pownersid)) {
+ acl_mode = access_flags_to_mode(fattr,
+ ppace[i]->access_req,
+ ppace[i]->type);
+ acl_mode &= 0700;
+
+ if (!owner_found) {
+ mode &= ~(0700);
+ mode |= acl_mode;
+ }
+ owner_found = true;
+ } else if (!compare_sids(&ppace[i]->sid, pgrpsid) ||
+ ppace[i]->sid.sub_auth[ppace[i]->sid.num_subauth - 1] ==
+ DOMAIN_USER_RID_LE) {
+ acl_mode = access_flags_to_mode(fattr,
+ ppace[i]->access_req,
+ ppace[i]->type);
+ acl_mode &= 0070;
+ if (!group_found) {
+ mode &= ~(0070);
+ mode |= acl_mode;
+ }
+ group_found = true;
+ } else if (!compare_sids(&ppace[i]->sid, &sid_everyone)) {
+ acl_mode = access_flags_to_mode(fattr,
+ ppace[i]->access_req,
+ ppace[i]->type);
+ acl_mode &= 0007;
+ if (!others_found) {
+ mode &= ~(0007);
+ mode |= acl_mode;
+ }
+ others_found = true;
+ } else if (!compare_sids(&ppace[i]->sid, &creator_owner)) {
+ continue;
+ } else if (!compare_sids(&ppace[i]->sid, &creator_group)) {
+ continue;
+ } else if (!compare_sids(&ppace[i]->sid, &sid_authusers)) {
+ continue;
+ } else {
+ struct smb_fattr temp_fattr;
+
+ acl_mode = access_flags_to_mode(fattr, ppace[i]->access_req,
+ ppace[i]->type);
+ temp_fattr.cf_uid = INVALID_UID;
+ ret = sid_to_id(user_ns, &ppace[i]->sid, SIDOWNER, &temp_fattr);
+ if (ret || uid_eq(temp_fattr.cf_uid, INVALID_UID)) {
+ pr_err("%s: Error %d mapping Owner SID to uid\n",
+ __func__, ret);
+ continue;
+ }
+
+ acl_state.owner.allow = ((acl_mode & 0700) >> 6) | 0004;
+ acl_state.users->aces[acl_state.users->n].uid =
+ temp_fattr.cf_uid;
+ acl_state.users->aces[acl_state.users->n++].perms.allow =
+ ((acl_mode & 0700) >> 6) | 0004;
+ default_acl_state.owner.allow = ((acl_mode & 0700) >> 6) | 0004;
+ default_acl_state.users->aces[default_acl_state.users->n].uid =
+ temp_fattr.cf_uid;
+ default_acl_state.users->aces[default_acl_state.users->n++].perms.allow =
+ ((acl_mode & 0700) >> 6) | 0004;
+ }
+ }
+ kfree(ppace);
+
+ if (owner_found) {
+ /* The owner must be set to at least read-only. */
+ acl_state.owner.allow = ((mode & 0700) >> 6) | 0004;
+ acl_state.users->aces[acl_state.users->n].uid = fattr->cf_uid;
+ acl_state.users->aces[acl_state.users->n++].perms.allow =
+ ((mode & 0700) >> 6) | 0004;
+ default_acl_state.owner.allow = ((mode & 0700) >> 6) | 0004;
+ default_acl_state.users->aces[default_acl_state.users->n].uid =
+ fattr->cf_uid;
+ default_acl_state.users->aces[default_acl_state.users->n++].perms.allow =
+ ((mode & 0700) >> 6) | 0004;
+ }
+
+ if (group_found) {
+ acl_state.group.allow = (mode & 0070) >> 3;
+ acl_state.groups->aces[acl_state.groups->n].gid =
+ fattr->cf_gid;
+ acl_state.groups->aces[acl_state.groups->n++].perms.allow =
+ (mode & 0070) >> 3;
+ default_acl_state.group.allow = (mode & 0070) >> 3;
+ default_acl_state.groups->aces[default_acl_state.groups->n].gid =
+ fattr->cf_gid;
+ default_acl_state.groups->aces[default_acl_state.groups->n++].perms.allow =
+ (mode & 0070) >> 3;
+ }
+
+ if (others_found) {
+ fattr->cf_mode &= ~(0007);
+ fattr->cf_mode |= mode & 0007;
+
+ acl_state.other.allow = mode & 0007;
+ default_acl_state.other.allow = mode & 0007;
+ }
+
+ if (acl_state.users->n || acl_state.groups->n) {
+ acl_state.mask.allow = 0x07;
+
+ if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
+ fattr->cf_acls =
+ posix_acl_alloc(acl_state.users->n +
+ acl_state.groups->n + 4, GFP_KERNEL);
+ if (fattr->cf_acls) {
+ cf_pace = fattr->cf_acls->a_entries;
+ posix_state_to_acl(&acl_state, cf_pace);
+ }
+ }
+ }
+
+ if (default_acl_state.users->n || default_acl_state.groups->n) {
+ default_acl_state.mask.allow = 0x07;
+
+ if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
+ fattr->cf_dacls =
+ posix_acl_alloc(default_acl_state.users->n +
+ default_acl_state.groups->n + 4, GFP_KERNEL);
+ if (fattr->cf_dacls) {
+ cf_pdace = fattr->cf_dacls->a_entries;
+ posix_state_to_acl(&default_acl_state, cf_pdace);
+ }
+ }
+ }
+ free_acl_state(&acl_state);
+ free_acl_state(&default_acl_state);
+}
+
+static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
+ struct smb_ace *pndace,
+ struct smb_fattr *fattr, u32 *num_aces,
+ u16 *size, u32 nt_aces_num)
+{
+ struct posix_acl_entry *pace;
+ struct smb_sid *sid;
+ struct smb_ace *ntace;
+ int i, j;
+
+ if (!fattr->cf_acls)
+ goto posix_default_acl;
+
+ pace = fattr->cf_acls->a_entries;
+ for (i = 0; i < fattr->cf_acls->a_count; i++, pace++) {
+ int flags = 0;
+
+ sid = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
+ if (!sid)
+ break;
+
+ if (pace->e_tag == ACL_USER) {
+ uid_t uid;
+ unsigned int sid_type = SIDOWNER;
+
+ uid = posix_acl_uid_translate(user_ns, pace);
+ if (!uid)
+ sid_type = SIDUNIX_USER;
+ id_to_sid(uid, sid_type, sid);
+ } else if (pace->e_tag == ACL_GROUP) {
+ gid_t gid;
+
+ gid = posix_acl_gid_translate(user_ns, pace);
+ id_to_sid(gid, SIDUNIX_GROUP, sid);
+ } else if (pace->e_tag == ACL_OTHER && !nt_aces_num) {
+ smb_copy_sid(sid, &sid_everyone);
+ } else {
+ kfree(sid);
+ continue;
+ }
+ ntace = pndace;
+ for (j = 0; j < nt_aces_num; j++) {
+ if (ntace->sid.sub_auth[ntace->sid.num_subauth - 1] ==
+ sid->sub_auth[sid->num_subauth - 1])
+ goto pass_same_sid;
+ ntace = (struct smb_ace *)((char *)ntace +
+ le16_to_cpu(ntace->size));
+ }
+
+ if (S_ISDIR(fattr->cf_mode) && pace->e_tag == ACL_OTHER)
+ flags = 0x03;
+
+ ntace = (struct smb_ace *)((char *)pndace + *size);
+ *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
+ pace->e_perm, 0777);
+ (*num_aces)++;
+ if (pace->e_tag == ACL_USER)
+ ntace->access_req |=
+ FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
+
+ if (S_ISDIR(fattr->cf_mode) &&
+ (pace->e_tag == ACL_USER || pace->e_tag == ACL_GROUP)) {
+ ntace = (struct smb_ace *)((char *)pndace + *size);
+ *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
+ 0x03, pace->e_perm, 0777);
+ (*num_aces)++;
+ if (pace->e_tag == ACL_USER)
+ ntace->access_req |=
+ FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
+ }
+
+pass_same_sid:
+ kfree(sid);
+ }
+
+ if (nt_aces_num)
+ return;
+
+posix_default_acl:
+ if (!fattr->cf_dacls)
+ return;
+
+ pace = fattr->cf_dacls->a_entries;
+ for (i = 0; i < fattr->cf_dacls->a_count; i++, pace++) {
+ sid = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
+ if (!sid)
+ break;
+
+ if (pace->e_tag == ACL_USER) {
+ uid_t uid;
+
+ uid = posix_acl_uid_translate(user_ns, pace);
+ id_to_sid(uid, SIDCREATOR_OWNER, sid);
+ } else if (pace->e_tag == ACL_GROUP) {
+ gid_t gid;
+
+ gid = posix_acl_gid_translate(user_ns, pace);
+ id_to_sid(gid, SIDCREATOR_GROUP, sid);
+ } else {
+ kfree(sid);
+ continue;
+ }
+
+ ntace = (struct smb_ace *)((char *)pndace + *size);
+ *size += fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
+ pace->e_perm, 0777);
+ (*num_aces)++;
+ if (pace->e_tag == ACL_USER)
+ ntace->access_req |=
+ FILE_DELETE_LE | FILE_DELETE_CHILD_LE;
+ kfree(sid);
+ }
+}
+
+static void set_ntacl_dacl(struct user_namespace *user_ns,
+ struct smb_acl *pndacl,
+ struct smb_acl *nt_dacl,
+ unsigned int aces_size,
+ const struct smb_sid *pownersid,
+ const struct smb_sid *pgrpsid,
+ struct smb_fattr *fattr)
+{
+ struct smb_ace *ntace, *pndace;
+ int nt_num_aces = le32_to_cpu(nt_dacl->num_aces), num_aces = 0;
+ unsigned short size = 0;
+ int i;
+
+ pndace = (struct smb_ace *)((char *)pndacl + sizeof(struct smb_acl));
+ if (nt_num_aces) {
+ ntace = (struct smb_ace *)((char *)nt_dacl + sizeof(struct smb_acl));
+ for (i = 0; i < nt_num_aces; i++) {
+ unsigned short nt_ace_size;
+
+ if (offsetof(struct smb_ace, access_req) > aces_size)
+ break;
+
+ nt_ace_size = le16_to_cpu(ntace->size);
+ if (nt_ace_size > aces_size)
+ break;
+
+ memcpy((char *)pndace + size, ntace, nt_ace_size);
+ size += nt_ace_size;
+ aces_size -= nt_ace_size;
+ ntace = (struct smb_ace *)((char *)ntace + nt_ace_size);
+ num_aces++;
+ }
+ }
+
+ set_posix_acl_entries_dacl(user_ns, pndace, fattr,
+ &num_aces, &size, nt_num_aces);
+ pndacl->num_aces = cpu_to_le32(num_aces);
+ pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
+}
+
+static void set_mode_dacl(struct user_namespace *user_ns,
+ struct smb_acl *pndacl, struct smb_fattr *fattr)
+{
+ struct smb_ace *pace, *pndace;
+ u32 num_aces = 0;
+ u16 size = 0, ace_size = 0;
+ uid_t uid;
+ const struct smb_sid *sid;
+
+ pace = pndace = (struct smb_ace *)((char *)pndacl + sizeof(struct smb_acl));
+
+ if (fattr->cf_acls) {
+ set_posix_acl_entries_dacl(user_ns, pndace, fattr,
+ &num_aces, &size, num_aces);
+ goto out;
+ }
+
+ /* owner RID */
+ uid = from_kuid(&init_user_ns, fattr->cf_uid);
+ if (uid)
+ sid = &server_conf.domain_sid;
+ else
+ sid = &sid_unix_users;
+ ace_size = fill_ace_for_sid(pace, sid, ACCESS_ALLOWED, 0,
+ fattr->cf_mode, 0700);
+ pace->sid.sub_auth[pace->sid.num_subauth++] = cpu_to_le32(uid);
+ pace->size = cpu_to_le16(ace_size + 4);
+ size += le16_to_cpu(pace->size);
+ pace = (struct smb_ace *)((char *)pndace + size);
+
+ /* Group RID */
+ ace_size = fill_ace_for_sid(pace, &sid_unix_groups,
+ ACCESS_ALLOWED, 0, fattr->cf_mode, 0070);
+ pace->sid.sub_auth[pace->sid.num_subauth++] =
+ cpu_to_le32(from_kgid(&init_user_ns, fattr->cf_gid));
+ pace->size = cpu_to_le16(ace_size + 4);
+ size += le16_to_cpu(pace->size);
+ pace = (struct smb_ace *)((char *)pndace + size);
+ num_aces = 3;
+
+ if (S_ISDIR(fattr->cf_mode)) {
+ pace = (struct smb_ace *)((char *)pndace + size);
+
+ /* creator owner */
+ size += fill_ace_for_sid(pace, &creator_owner, ACCESS_ALLOWED,
+ 0x0b, fattr->cf_mode, 0700);
+ pace = (struct smb_ace *)((char *)pndace + size);
+
+ /* creator group */
+ size += fill_ace_for_sid(pace, &creator_group, ACCESS_ALLOWED,
+ 0x0b, fattr->cf_mode, 0070);
+ pace = (struct smb_ace *)((char *)pndace + size);
+ num_aces = 5;
+ }
+
+ /* other */
+ size += fill_ace_for_sid(pace, &sid_everyone, ACCESS_ALLOWED, 0,
+ fattr->cf_mode, 0007);
+
+out:
+ pndacl->num_aces = cpu_to_le32(num_aces);
+ pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
+}
+
+static int parse_sid(struct smb_sid *psid, char *end_of_acl)
+{
+ /*
+ * validate that we do not go past end of ACL - sid must be at least 8
+ * bytes long (assuming no sub-auths - e.g. the null SID
+ */
+ if (end_of_acl < (char *)psid + 8) {
+ pr_err("ACL too small to parse SID %p\n", psid);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Convert CIFS ACL to POSIX form */
+int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
+ int acl_len, struct smb_fattr *fattr)
+{
+ int rc = 0;
+ struct smb_sid *owner_sid_ptr, *group_sid_ptr;
+ struct smb_acl *dacl_ptr; /* no need for SACL ptr */
+ char *end_of_acl = ((char *)pntsd) + acl_len;
+ __u32 dacloffset;
+ int pntsd_type;
+
+ if (!pntsd)
+ return -EIO;
+
+ if (acl_len < sizeof(struct smb_ntsd))
+ return -EINVAL;
+
+ owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->osidoffset));
+ group_sid_ptr = (struct smb_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->gsidoffset));
+ dacloffset = le32_to_cpu(pntsd->dacloffset);
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
+ ksmbd_debug(SMB,
+ "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
+ pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
+ le32_to_cpu(pntsd->gsidoffset),
+ le32_to_cpu(pntsd->sacloffset), dacloffset);
+
+ pntsd_type = le16_to_cpu(pntsd->type);
+ if (!(pntsd_type & DACL_PRESENT)) {
+ ksmbd_debug(SMB, "DACL_PRESENT in DACL type is not set\n");
+ return rc;
+ }
+
+ pntsd->type = cpu_to_le16(DACL_PRESENT);
+
+ if (pntsd->osidoffset) {
+ rc = parse_sid(owner_sid_ptr, end_of_acl);
+ if (rc) {
+ pr_err("%s: Error %d parsing Owner SID\n", __func__, rc);
+ return rc;
+ }
+
+ rc = sid_to_id(user_ns, owner_sid_ptr, SIDOWNER, fattr);
+ if (rc) {
+ pr_err("%s: Error %d mapping Owner SID to uid\n",
+ __func__, rc);
+ owner_sid_ptr = NULL;
+ }
+ }
+
+ if (pntsd->gsidoffset) {
+ rc = parse_sid(group_sid_ptr, end_of_acl);
+ if (rc) {
+ pr_err("%s: Error %d mapping Owner SID to gid\n",
+ __func__, rc);
+ return rc;
+ }
+ rc = sid_to_id(user_ns, group_sid_ptr, SIDUNIX_GROUP, fattr);
+ if (rc) {
+ pr_err("%s: Error %d mapping Group SID to gid\n",
+ __func__, rc);
+ group_sid_ptr = NULL;
+ }
+ }
+
+ if ((pntsd_type & (DACL_AUTO_INHERITED | DACL_AUTO_INHERIT_REQ)) ==
+ (DACL_AUTO_INHERITED | DACL_AUTO_INHERIT_REQ))
+ pntsd->type |= cpu_to_le16(DACL_AUTO_INHERITED);
+ if (pntsd_type & DACL_PROTECTED)
+ pntsd->type |= cpu_to_le16(DACL_PROTECTED);
+
+ if (dacloffset) {
+ parse_dacl(user_ns, dacl_ptr, end_of_acl,
+ owner_sid_ptr, group_sid_ptr, fattr);
+ }
+
+ return 0;
+}
+
+/* Convert permission bits from mode to equivalent CIFS ACL */
+int build_sec_desc(struct user_namespace *user_ns,
+ struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
+ int ppntsd_size, int addition_info, __u32 *secdesclen,
+ struct smb_fattr *fattr)
+{
+ int rc = 0;
+ __u32 offset;
+ struct smb_sid *owner_sid_ptr, *group_sid_ptr;
+ struct smb_sid *nowner_sid_ptr, *ngroup_sid_ptr;
+ struct smb_acl *dacl_ptr = NULL; /* no need for SACL ptr */
+ uid_t uid;
+ gid_t gid;
+ unsigned int sid_type = SIDOWNER;
+
+ nowner_sid_ptr = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
+ if (!nowner_sid_ptr)
+ return -ENOMEM;
+
+ uid = from_kuid(&init_user_ns, fattr->cf_uid);
+ if (!uid)
+ sid_type = SIDUNIX_USER;
+ id_to_sid(uid, sid_type, nowner_sid_ptr);
+
+ ngroup_sid_ptr = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
+ if (!ngroup_sid_ptr) {
+ kfree(nowner_sid_ptr);
+ return -ENOMEM;
+ }
+
+ gid = from_kgid(&init_user_ns, fattr->cf_gid);
+ id_to_sid(gid, SIDUNIX_GROUP, ngroup_sid_ptr);
+
+ offset = sizeof(struct smb_ntsd);
+ pntsd->sacloffset = 0;
+ pntsd->revision = cpu_to_le16(1);
+ pntsd->type = cpu_to_le16(SELF_RELATIVE);
+ if (ppntsd)
+ pntsd->type |= ppntsd->type;
+
+ if (addition_info & OWNER_SECINFO) {
+ pntsd->osidoffset = cpu_to_le32(offset);
+ owner_sid_ptr = (struct smb_sid *)((char *)pntsd + offset);
+ smb_copy_sid(owner_sid_ptr, nowner_sid_ptr);
+ offset += 1 + 1 + 6 + (nowner_sid_ptr->num_subauth * 4);
+ }
+
+ if (addition_info & GROUP_SECINFO) {
+ pntsd->gsidoffset = cpu_to_le32(offset);
+ group_sid_ptr = (struct smb_sid *)((char *)pntsd + offset);
+ smb_copy_sid(group_sid_ptr, ngroup_sid_ptr);
+ offset += 1 + 1 + 6 + (ngroup_sid_ptr->num_subauth * 4);
+ }
+
+ if (addition_info & DACL_SECINFO) {
+ pntsd->type |= cpu_to_le16(DACL_PRESENT);
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + offset);
+ dacl_ptr->revision = cpu_to_le16(2);
+ dacl_ptr->size = cpu_to_le16(sizeof(struct smb_acl));
+ dacl_ptr->num_aces = 0;
+
+ if (!ppntsd) {
+ set_mode_dacl(user_ns, dacl_ptr, fattr);
+ } else {
+ struct smb_acl *ppdacl_ptr;
+ unsigned int dacl_offset = le32_to_cpu(ppntsd->dacloffset);
+ int ppdacl_size, ntacl_size = ppntsd_size - dacl_offset;
+
+ if (!dacl_offset ||
+ (dacl_offset + sizeof(struct smb_acl) > ppntsd_size))
+ goto out;
+
+ ppdacl_ptr = (struct smb_acl *)((char *)ppntsd + dacl_offset);
+ ppdacl_size = le16_to_cpu(ppdacl_ptr->size);
+ if (ppdacl_size > ntacl_size ||
+ ppdacl_size < sizeof(struct smb_acl))
+ goto out;
+
+ set_ntacl_dacl(user_ns, dacl_ptr, ppdacl_ptr,
+ ntacl_size - sizeof(struct smb_acl),
+ nowner_sid_ptr, ngroup_sid_ptr,
+ fattr);
+ }
+ pntsd->dacloffset = cpu_to_le32(offset);
+ offset += le16_to_cpu(dacl_ptr->size);
+ }
+
+out:
+ kfree(nowner_sid_ptr);
+ kfree(ngroup_sid_ptr);
+ *secdesclen = offset;
+ return rc;
+}
+
+static void smb_set_ace(struct smb_ace *ace, const struct smb_sid *sid, u8 type,
+ u8 flags, __le32 access_req)
+{
+ ace->type = type;
+ ace->flags = flags;
+ ace->access_req = access_req;
+ smb_copy_sid(&ace->sid, sid);
+ ace->size = cpu_to_le16(1 + 1 + 2 + 4 + 1 + 1 + 6 + (sid->num_subauth * 4));
+}
+
+int smb_inherit_dacl(struct ksmbd_conn *conn,
+ const struct path *path,
+ unsigned int uid, unsigned int gid)
+{
+ const struct smb_sid *psid, *creator = NULL;
+ struct smb_ace *parent_aces, *aces;
+ struct smb_acl *parent_pdacl;
+ struct smb_ntsd *parent_pntsd = NULL;
+ struct smb_sid owner_sid, group_sid;
+ struct dentry *parent = path->dentry->d_parent;
+ struct user_namespace *user_ns = mnt_user_ns(path->mnt);
+ int inherited_flags = 0, flags = 0, i, ace_cnt = 0, nt_size = 0, pdacl_size;
+ int rc = 0, num_aces, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size;
+ char *aces_base;
+ bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
+
+ pntsd_size = ksmbd_vfs_get_sd_xattr(conn, user_ns,
+ parent, &parent_pntsd);
+ if (pntsd_size <= 0)
+ return -ENOENT;
+ dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
+ if (!dacloffset || (dacloffset + sizeof(struct smb_acl) > pntsd_size)) {
+ rc = -EINVAL;
+ goto free_parent_pntsd;
+ }
+
+ parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset);
+ acl_len = pntsd_size - dacloffset;
+ num_aces = le32_to_cpu(parent_pdacl->num_aces);
+ pntsd_type = le16_to_cpu(parent_pntsd->type);
+ pdacl_size = le16_to_cpu(parent_pdacl->size);
+
+ if (pdacl_size > acl_len || pdacl_size < sizeof(struct smb_acl)) {
+ rc = -EINVAL;
+ goto free_parent_pntsd;
+ }
+
+ aces_base = kmalloc(sizeof(struct smb_ace) * num_aces * 2, GFP_KERNEL);
+ if (!aces_base) {
+ rc = -ENOMEM;
+ goto free_parent_pntsd;
+ }
+
+ aces = (struct smb_ace *)aces_base;
+ parent_aces = (struct smb_ace *)((char *)parent_pdacl +
+ sizeof(struct smb_acl));
+ aces_size = acl_len - sizeof(struct smb_acl);
+
+ if (pntsd_type & DACL_AUTO_INHERITED)
+ inherited_flags = INHERITED_ACE;
+
+ for (i = 0; i < num_aces; i++) {
+ int pace_size;
+
+ if (offsetof(struct smb_ace, access_req) > aces_size)
+ break;
+
+ pace_size = le16_to_cpu(parent_aces->size);
+ if (pace_size > aces_size)
+ break;
+
+ aces_size -= pace_size;
+
+ flags = parent_aces->flags;
+ if (!smb_inherit_flags(flags, is_dir))
+ goto pass;
+ if (is_dir) {
+ flags &= ~(INHERIT_ONLY_ACE | INHERITED_ACE);
+ if (!(flags & CONTAINER_INHERIT_ACE))
+ flags |= INHERIT_ONLY_ACE;
+ if (flags & NO_PROPAGATE_INHERIT_ACE)
+ flags = 0;
+ } else {
+ flags = 0;
+ }
+
+ if (!compare_sids(&creator_owner, &parent_aces->sid)) {
+ creator = &creator_owner;
+ id_to_sid(uid, SIDOWNER, &owner_sid);
+ psid = &owner_sid;
+ } else if (!compare_sids(&creator_group, &parent_aces->sid)) {
+ creator = &creator_group;
+ id_to_sid(gid, SIDUNIX_GROUP, &group_sid);
+ psid = &group_sid;
+ } else {
+ creator = NULL;
+ psid = &parent_aces->sid;
+ }
+
+ if (is_dir && creator && flags & CONTAINER_INHERIT_ACE) {
+ smb_set_ace(aces, psid, parent_aces->type, inherited_flags,
+ parent_aces->access_req);
+ nt_size += le16_to_cpu(aces->size);
+ ace_cnt++;
+ aces = (struct smb_ace *)((char *)aces + le16_to_cpu(aces->size));
+ flags |= INHERIT_ONLY_ACE;
+ psid = creator;
+ } else if (is_dir && !(parent_aces->flags & NO_PROPAGATE_INHERIT_ACE)) {
+ psid = &parent_aces->sid;
+ }
+
+ smb_set_ace(aces, psid, parent_aces->type, flags | inherited_flags,
+ parent_aces->access_req);
+ nt_size += le16_to_cpu(aces->size);
+ aces = (struct smb_ace *)((char *)aces + le16_to_cpu(aces->size));
+ ace_cnt++;
+pass:
+ parent_aces = (struct smb_ace *)((char *)parent_aces + pace_size);
+ }
+
+ if (nt_size > 0) {
+ struct smb_ntsd *pntsd;
+ struct smb_acl *pdacl;
+ struct smb_sid *powner_sid = NULL, *pgroup_sid = NULL;
+ int powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
+
+ if (parent_pntsd->osidoffset) {
+ powner_sid = (struct smb_sid *)((char *)parent_pntsd +
+ le32_to_cpu(parent_pntsd->osidoffset));
+ powner_sid_size = 1 + 1 + 6 + (powner_sid->num_subauth * 4);
+ }
+ if (parent_pntsd->gsidoffset) {
+ pgroup_sid = (struct smb_sid *)((char *)parent_pntsd +
+ le32_to_cpu(parent_pntsd->gsidoffset));
+ pgroup_sid_size = 1 + 1 + 6 + (pgroup_sid->num_subauth * 4);
+ }
+
+ pntsd = kzalloc(sizeof(struct smb_ntsd) + powner_sid_size +
+ pgroup_sid_size + sizeof(struct smb_acl) +
+ nt_size, GFP_KERNEL);
+ if (!pntsd) {
+ rc = -ENOMEM;
+ goto free_aces_base;
+ }
+
+ pntsd->revision = cpu_to_le16(1);
+ pntsd->type = cpu_to_le16(SELF_RELATIVE | DACL_PRESENT);
+ if (le16_to_cpu(parent_pntsd->type) & DACL_AUTO_INHERITED)
+ pntsd->type |= cpu_to_le16(DACL_AUTO_INHERITED);
+ pntsd_size = sizeof(struct smb_ntsd);
+ pntsd->osidoffset = parent_pntsd->osidoffset;
+ pntsd->gsidoffset = parent_pntsd->gsidoffset;
+ pntsd->dacloffset = parent_pntsd->dacloffset;
+
+ if (pntsd->osidoffset) {
+ struct smb_sid *owner_sid = (struct smb_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->osidoffset));
+ memcpy(owner_sid, powner_sid, powner_sid_size);
+ pntsd_size += powner_sid_size;
+ }
+
+ if (pntsd->gsidoffset) {
+ struct smb_sid *group_sid = (struct smb_sid *)((char *)pntsd +
+ le32_to_cpu(pntsd->gsidoffset));
+ memcpy(group_sid, pgroup_sid, pgroup_sid_size);
+ pntsd_size += pgroup_sid_size;
+ }
+
+ if (pntsd->dacloffset) {
+ struct smb_ace *pace;
+
+ pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
+ pdacl->revision = cpu_to_le16(2);
+ pdacl->size = cpu_to_le16(sizeof(struct smb_acl) + nt_size);
+ pdacl->num_aces = cpu_to_le32(ace_cnt);
+ pace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
+ memcpy(pace, aces_base, nt_size);
+ pntsd_size += sizeof(struct smb_acl) + nt_size;
+ }
+
+ ksmbd_vfs_set_sd_xattr(conn, user_ns,
+ path->dentry, pntsd, pntsd_size);
+ kfree(pntsd);
+ }
+
+free_aces_base:
+ kfree(aces_base);
+free_parent_pntsd:
+ kfree(parent_pntsd);
+ return rc;
+}
+
+bool smb_inherit_flags(int flags, bool is_dir)
+{
+ if (!is_dir)
+ return (flags & OBJECT_INHERIT_ACE) != 0;
+
+ if (flags & OBJECT_INHERIT_ACE && !(flags & NO_PROPAGATE_INHERIT_ACE))
+ return true;
+
+ if (flags & CONTAINER_INHERIT_ACE)
+ return true;
+ return false;
+}
+
+int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
+ __le32 *pdaccess, int uid)
+{
+ struct user_namespace *user_ns = mnt_user_ns(path->mnt);
+ struct smb_ntsd *pntsd = NULL;
+ struct smb_acl *pdacl;
+ struct posix_acl *posix_acls;
+ int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size, dacl_offset;
+ struct smb_sid sid;
+ int granted = le32_to_cpu(*pdaccess & ~FILE_MAXIMAL_ACCESS_LE);
+ struct smb_ace *ace;
+ int i, found = 0;
+ unsigned int access_bits = 0;
+ struct smb_ace *others_ace = NULL;
+ struct posix_acl_entry *pa_entry;
+ unsigned int sid_type = SIDOWNER;
+ unsigned short ace_size;
+
+ ksmbd_debug(SMB, "check permission using windows acl\n");
+ pntsd_size = ksmbd_vfs_get_sd_xattr(conn, user_ns,
+ path->dentry, &pntsd);
+ if (pntsd_size <= 0 || !pntsd)
+ goto err_out;
+
+ dacl_offset = le32_to_cpu(pntsd->dacloffset);
+ if (!dacl_offset ||
+ (dacl_offset + sizeof(struct smb_acl) > pntsd_size))
+ goto err_out;
+
+ pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
+ acl_size = pntsd_size - dacl_offset;
+ pdacl_size = le16_to_cpu(pdacl->size);
+
+ if (pdacl_size > acl_size || pdacl_size < sizeof(struct smb_acl))
+ goto err_out;
+
+ if (!pdacl->num_aces) {
+ if (!(pdacl_size - sizeof(struct smb_acl)) &&
+ *pdaccess & ~(FILE_READ_CONTROL_LE | FILE_WRITE_DAC_LE)) {
+ rc = -EACCES;
+ goto err_out;
+ }
+ goto err_out;
+ }
+
+ if (*pdaccess & FILE_MAXIMAL_ACCESS_LE) {
+ granted = READ_CONTROL | WRITE_DAC | FILE_READ_ATTRIBUTES |
+ DELETE;
+
+ ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
+ aces_size = acl_size - sizeof(struct smb_acl);
+ for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) {
+ if (offsetof(struct smb_ace, access_req) > aces_size)
+ break;
+ ace_size = le16_to_cpu(ace->size);
+ if (ace_size > aces_size)
+ break;
+ aces_size -= ace_size;
+ granted |= le32_to_cpu(ace->access_req);
+ ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
+ }
+
+ if (!pdacl->num_aces)
+ granted = GENERIC_ALL_FLAGS;
+ }
+
+ if (!uid)
+ sid_type = SIDUNIX_USER;
+ id_to_sid(uid, sid_type, &sid);
+
+ ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
+ aces_size = acl_size - sizeof(struct smb_acl);
+ for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) {
+ if (offsetof(struct smb_ace, access_req) > aces_size)
+ break;
+ ace_size = le16_to_cpu(ace->size);
+ if (ace_size > aces_size)
+ break;
+ aces_size -= ace_size;
+
+ if (!compare_sids(&sid, &ace->sid) ||
+ !compare_sids(&sid_unix_NFS_mode, &ace->sid)) {
+ found = 1;
+ break;
+ }
+ if (!compare_sids(&sid_everyone, &ace->sid))
+ others_ace = ace;
+
+ ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
+ }
+
+ if (*pdaccess & FILE_MAXIMAL_ACCESS_LE && found) {
+ granted = READ_CONTROL | WRITE_DAC | FILE_READ_ATTRIBUTES |
+ DELETE;
+
+ granted |= le32_to_cpu(ace->access_req);
+
+ if (!pdacl->num_aces)
+ granted = GENERIC_ALL_FLAGS;
+ }
+
+ if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
+ posix_acls = get_acl(d_inode(path->dentry), ACL_TYPE_ACCESS);
+ if (posix_acls && !found) {
+ unsigned int id = -1;
+
+ pa_entry = posix_acls->a_entries;
+ for (i = 0; i < posix_acls->a_count; i++, pa_entry++) {
+ if (pa_entry->e_tag == ACL_USER)
+ id = posix_acl_uid_translate(user_ns, pa_entry);
+ else if (pa_entry->e_tag == ACL_GROUP)
+ id = posix_acl_gid_translate(user_ns, pa_entry);
+ else
+ continue;
+
+ if (id == uid) {
+ mode_to_access_flags(pa_entry->e_perm,
+ 0777,
+ &access_bits);
+ if (!access_bits)
+ access_bits =
+ SET_MINIMUM_RIGHTS;
+ posix_acl_release(posix_acls);
+ goto check_access_bits;
+ }
+ }
+ }
+ if (posix_acls)
+ posix_acl_release(posix_acls);
+ }
+
+ if (!found) {
+ if (others_ace) {
+ ace = others_ace;
+ } else {
+ ksmbd_debug(SMB, "Can't find corresponding sid\n");
+ rc = -EACCES;
+ goto err_out;
+ }
+ }
+
+ switch (ace->type) {
+ case ACCESS_ALLOWED_ACE_TYPE:
+ access_bits = le32_to_cpu(ace->access_req);
+ break;
+ case ACCESS_DENIED_ACE_TYPE:
+ case ACCESS_DENIED_CALLBACK_ACE_TYPE:
+ access_bits = le32_to_cpu(~ace->access_req);
+ break;
+ }
+
+check_access_bits:
+ if (granted &
+ ~(access_bits | FILE_READ_ATTRIBUTES | READ_CONTROL | WRITE_DAC | DELETE)) {
+ ksmbd_debug(SMB, "Access denied with winACL, granted : %x, access_req : %x\n",
+ granted, le32_to_cpu(ace->access_req));
+ rc = -EACCES;
+ goto err_out;
+ }
+
+ *pdaccess = cpu_to_le32(granted);
+err_out:
+ kfree(pntsd);
+ return rc;
+}
+
+int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
+ const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
+ bool type_check)
+{
+ int rc;
+ struct smb_fattr fattr = {{0}};
+ struct inode *inode = d_inode(path->dentry);
+ struct user_namespace *user_ns = mnt_user_ns(path->mnt);
+ struct iattr newattrs;
+
+ fattr.cf_uid = INVALID_UID;
+ fattr.cf_gid = INVALID_GID;
+ fattr.cf_mode = inode->i_mode;
+
+ rc = parse_sec_desc(user_ns, pntsd, ntsd_len, &fattr);
+ if (rc)
+ goto out;
+
+ newattrs.ia_valid = ATTR_CTIME;
+ if (!uid_eq(fattr.cf_uid, INVALID_UID)) {
+ newattrs.ia_valid |= ATTR_UID;
+ newattrs.ia_uid = fattr.cf_uid;
+ }
+ if (!gid_eq(fattr.cf_gid, INVALID_GID)) {
+ newattrs.ia_valid |= ATTR_GID;
+ newattrs.ia_gid = fattr.cf_gid;
+ }
+ newattrs.ia_valid |= ATTR_MODE;
+ newattrs.ia_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777);
+
+ ksmbd_vfs_remove_acl_xattrs(user_ns, path->dentry);
+ /* Update posix acls */
+ if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && fattr.cf_dacls) {
+ rc = set_posix_acl(user_ns, inode,
+ ACL_TYPE_ACCESS, fattr.cf_acls);
+ if (rc < 0)
+ ksmbd_debug(SMB,
+ "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
+ rc);
+ if (S_ISDIR(inode->i_mode) && fattr.cf_dacls) {
+ rc = set_posix_acl(user_ns, inode,
+ ACL_TYPE_DEFAULT, fattr.cf_dacls);
+ if (rc)
+ ksmbd_debug(SMB,
+ "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
+ rc);
+ }
+ }
+
+ inode_lock(inode);
+ rc = notify_change(user_ns, path->dentry, &newattrs, NULL);
+ inode_unlock(inode);
+ if (rc)
+ goto out;
+
+ /* Check it only calling from SD BUFFER context */
+ if (type_check && !(le16_to_cpu(pntsd->type) & DACL_PRESENT))
+ goto out;
+
+ if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) {
+ /* Update WinACL in xattr */
+ ksmbd_vfs_remove_sd_xattrs(user_ns, path->dentry);
+ ksmbd_vfs_set_sd_xattr(conn, user_ns,
+ path->dentry, pntsd, ntsd_len);
+ }
+
+out:
+ posix_acl_release(fattr.cf_acls);
+ posix_acl_release(fattr.cf_dacls);
+ mark_inode_dirty(inode);
+ return rc;
+}
+
+void ksmbd_init_domain(u32 *sub_auth)
+{
+ int i;
+
+ memcpy(&server_conf.domain_sid, &domain, sizeof(struct smb_sid));
+ for (i = 0; i < 3; ++i)
+ server_conf.domain_sid.sub_auth[i + 1] = cpu_to_le32(sub_auth[i]);
+}
diff --git a/fs/smb/server/smbacl.h b/fs/smb/server/smbacl.h
new file mode 100644
index 000000000000..618f2e0236b3
--- /dev/null
+++ b/fs/smb/server/smbacl.h
@@ -0,0 +1,238 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/*
+ * Copyright (c) International Business Machines Corp., 2007
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Modified by Namjae Jeon (linkinjeon@kernel.org)
+ */
+
+#ifndef _SMBACL_H
+#define _SMBACL_H
+
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/posix_acl.h>
+#include <linux/mnt_idmapping.h>
+
+#include "mgmt/tree_connect.h"
+
+#define NUM_AUTHS (6) /* number of authority fields */
+#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
+
+/*
+ * ACE types - see MS-DTYP 2.4.4.1
+ */
+enum {
+ ACCESS_ALLOWED,
+ ACCESS_DENIED,
+};
+
+/*
+ * Security ID types
+ */
+enum {
+ SIDOWNER = 1,
+ SIDGROUP,
+ SIDCREATOR_OWNER,
+ SIDCREATOR_GROUP,
+ SIDUNIX_USER,
+ SIDUNIX_GROUP,
+ SIDNFS_USER,
+ SIDNFS_GROUP,
+ SIDNFS_MODE,
+};
+
+/* Revision for ACLs */
+#define SD_REVISION 1
+
+/* Control flags for Security Descriptor */
+#define OWNER_DEFAULTED 0x0001
+#define GROUP_DEFAULTED 0x0002
+#define DACL_PRESENT 0x0004
+#define DACL_DEFAULTED 0x0008
+#define SACL_PRESENT 0x0010
+#define SACL_DEFAULTED 0x0020
+#define DACL_TRUSTED 0x0040
+#define SERVER_SECURITY 0x0080
+#define DACL_AUTO_INHERIT_REQ 0x0100
+#define SACL_AUTO_INHERIT_REQ 0x0200
+#define DACL_AUTO_INHERITED 0x0400
+#define SACL_AUTO_INHERITED 0x0800
+#define DACL_PROTECTED 0x1000
+#define SACL_PROTECTED 0x2000
+#define RM_CONTROL_VALID 0x4000
+#define SELF_RELATIVE 0x8000
+
+/* ACE types - see MS-DTYP 2.4.4.1 */
+#define ACCESS_ALLOWED_ACE_TYPE 0x00
+#define ACCESS_DENIED_ACE_TYPE 0x01
+#define SYSTEM_AUDIT_ACE_TYPE 0x02
+#define SYSTEM_ALARM_ACE_TYPE 0x03
+#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
+#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
+#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
+#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
+#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
+#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
+#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
+#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
+#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C
+#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D
+#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */
+#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
+#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
+#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
+#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
+#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13
+
+/* ACE flags */
+#define OBJECT_INHERIT_ACE 0x01
+#define CONTAINER_INHERIT_ACE 0x02
+#define NO_PROPAGATE_INHERIT_ACE 0x04
+#define INHERIT_ONLY_ACE 0x08
+#define INHERITED_ACE 0x10
+#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
+#define FAILED_ACCESS_ACE_FLAG 0x80
+
+/*
+ * Maximum size of a string representation of a SID:
+ *
+ * The fields are unsigned values in decimal. So:
+ *
+ * u8: max 3 bytes in decimal
+ * u32: max 10 bytes in decimal
+ *
+ * "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
+ *
+ * For authority field, max is when all 6 values are non-zero and it must be
+ * represented in hex. So "-0x" + 12 hex digits.
+ *
+ * Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
+ */
+#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
+#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
+
+#define DOMAIN_USER_RID_LE cpu_to_le32(513)
+
+struct ksmbd_conn;
+
+struct smb_ntsd {
+ __le16 revision; /* revision level */
+ __le16 type;
+ __le32 osidoffset;
+ __le32 gsidoffset;
+ __le32 sacloffset;
+ __le32 dacloffset;
+} __packed;
+
+struct smb_sid {
+ __u8 revision; /* revision level */
+ __u8 num_subauth;
+ __u8 authority[NUM_AUTHS];
+ __le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
+} __packed;
+
+/* size of a struct cifs_sid, sans sub_auth array */
+#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
+
+struct smb_acl {
+ __le16 revision; /* revision level */
+ __le16 size;
+ __le32 num_aces;
+} __packed;
+
+struct smb_ace {
+ __u8 type;
+ __u8 flags;
+ __le16 size;
+ __le32 access_req;
+ struct smb_sid sid; /* ie UUID of user or group who gets these perms */
+} __packed;
+
+struct smb_fattr {
+ kuid_t cf_uid;
+ kgid_t cf_gid;
+ umode_t cf_mode;
+ __le32 daccess;
+ struct posix_acl *cf_acls;
+ struct posix_acl *cf_dacls;
+};
+
+struct posix_ace_state {
+ u32 allow;
+ u32 deny;
+};
+
+struct posix_user_ace_state {
+ union {
+ kuid_t uid;
+ kgid_t gid;
+ };
+ struct posix_ace_state perms;
+};
+
+struct posix_ace_state_array {
+ int n;
+ struct posix_user_ace_state aces[];
+};
+
+/*
+ * while processing the nfsv4 ace, this maintains the partial permissions
+ * calculated so far:
+ */
+
+struct posix_acl_state {
+ struct posix_ace_state owner;
+ struct posix_ace_state group;
+ struct posix_ace_state other;
+ struct posix_ace_state everyone;
+ struct posix_ace_state mask; /* deny unused in this case */
+ struct posix_ace_state_array *users;
+ struct posix_ace_state_array *groups;
+};
+
+int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
+ int acl_len, struct smb_fattr *fattr);
+int build_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
+ struct smb_ntsd *ppntsd, int ppntsd_size, int addition_info,
+ __u32 *secdesclen, struct smb_fattr *fattr);
+int init_acl_state(struct posix_acl_state *state, int cnt);
+void free_acl_state(struct posix_acl_state *state);
+void posix_state_to_acl(struct posix_acl_state *state,
+ struct posix_acl_entry *pace);
+int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid);
+bool smb_inherit_flags(int flags, bool is_dir);
+int smb_inherit_dacl(struct ksmbd_conn *conn, const struct path *path,
+ unsigned int uid, unsigned int gid);
+int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
+ __le32 *pdaccess, int uid);
+int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
+ const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
+ bool type_check);
+void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
+void ksmbd_init_domain(u32 *sub_auth);
+
+static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns,
+ struct posix_acl_entry *pace)
+{
+ vfsuid_t vfsuid;
+
+ /* If this is an idmapped mount, apply the idmapping. */
+ vfsuid = make_vfsuid(mnt_userns, &init_user_ns, pace->e_uid);
+
+ /* Translate the kuid into a userspace id ksmbd would see. */
+ return from_kuid(&init_user_ns, vfsuid_into_kuid(vfsuid));
+}
+
+static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns,
+ struct posix_acl_entry *pace)
+{
+ vfsgid_t vfsgid;
+
+ /* If this is an idmapped mount, apply the idmapping. */
+ vfsgid = make_vfsgid(mnt_userns, &init_user_ns, pace->e_gid);
+
+ /* Translate the kgid into a userspace id ksmbd would see. */
+ return from_kgid(&init_user_ns, vfsgid_into_kgid(vfsgid));
+}
+
+#endif /* _SMBACL_H */
diff --git a/fs/smb/server/smbfsctl.h b/fs/smb/server/smbfsctl.h
new file mode 100644
index 000000000000..b98418aae20c
--- /dev/null
+++ b/fs/smb/server/smbfsctl.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/*
+ * fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions
+ *
+ * Copyright (c) International Business Machines Corp., 2002,2009
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ */
+
+/* IOCTL information */
+/*
+ * List of ioctl/fsctl function codes that are or could be useful in the
+ * future to remote clients like cifs or SMB2 client. There is probably
+ * a slightly larger set of fsctls that NTFS local filesystem could handle,
+ * including the seven below that we do not have struct definitions for.
+ * Even with protocol definitions for most of these now available, we still
+ * need to do some experimentation to identify which are practical to do
+ * remotely. Some of the following, such as the encryption/compression ones
+ * could be invoked from tools via a specialized hook into the VFS rather
+ * than via the standard vfs entry points
+ */
+
+#ifndef __KSMBD_SMBFSCTL_H
+#define __KSMBD_SMBFSCTL_H
+
+#define FSCTL_DFS_GET_REFERRALS 0x00060194
+#define FSCTL_DFS_GET_REFERRALS_EX 0x000601B0
+#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
+#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
+#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
+#define FSCTL_LOCK_VOLUME 0x00090018
+#define FSCTL_UNLOCK_VOLUME 0x0009001C
+#define FSCTL_IS_PATHNAME_VALID 0x0009002C /* BB add struct */
+#define FSCTL_GET_COMPRESSION 0x0009003C /* BB add struct */
+#define FSCTL_SET_COMPRESSION 0x0009C040 /* BB add struct */
+#define FSCTL_QUERY_FAT_BPB 0x00090058 /* BB add struct */
+/* Verify the next FSCTL number, we had it as 0x00090090 before */
+#define FSCTL_FILESYSTEM_GET_STATS 0x00090060 /* BB add struct */
+#define FSCTL_GET_NTFS_VOLUME_DATA 0x00090064 /* BB add struct */
+#define FSCTL_GET_RETRIEVAL_POINTERS 0x00090073 /* BB add struct */
+#define FSCTL_IS_VOLUME_DIRTY 0x00090078 /* BB add struct */
+#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x00090083 /* BB add struct */
+#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
+#define FSCTL_FIND_FILES_BY_SID 0x0009008F /* BB add struct */
+#define FSCTL_SET_OBJECT_ID 0x00090098 /* BB add struct */
+#define FSCTL_GET_OBJECT_ID 0x0009009C /* BB add struct */
+#define FSCTL_DELETE_OBJECT_ID 0x000900A0 /* BB add struct */
+#define FSCTL_SET_REPARSE_POINT 0x000900A4 /* BB add struct */
+#define FSCTL_GET_REPARSE_POINT 0x000900A8 /* BB add struct */
+#define FSCTL_DELETE_REPARSE_POINT 0x000900AC /* BB add struct */
+#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */
+#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */
+#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */
+#define FSCTL_SET_ZERO_DATA 0x000980C8 /* BB add struct */
+#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */
+#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */
+#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */
+#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 /* BB add struct */
+#define FSCTL_READ_FILE_USN_DATA 0x000900EB /* BB add struct */
+#define FSCTL_WRITE_USN_CLOSE_RECORD 0x000900EF /* BB add struct */
+#define FSCTL_SIS_COPYFILE 0x00090100 /* BB add struct */
+#define FSCTL_RECALL_FILE 0x00090117 /* BB add struct */
+#define FSCTL_QUERY_SPARING_INFO 0x00090138 /* BB add struct */
+#define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */
+#define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */
+#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF /* BB add struct */
+#define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */
+#define FSCTL_DUPLICATE_EXTENTS_TO_FILE 0x00098344
+#define FSCTL_SIS_LINK_FILES 0x0009C104
+#define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */
+#define FSCTL_PIPE_TRANSCEIVE 0x0011C017 /* BB add struct */
+/* strange that the number for this op is not sequential with previous op */
+#define FSCTL_PIPE_WAIT 0x00110018 /* BB add struct */
+#define FSCTL_REQUEST_RESUME_KEY 0x00140078
+#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
+#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
+#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
+#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC
+#define FSCTL_COPYCHUNK 0x001440F2
+#define FSCTL_COPYCHUNK_WRITE 0x001480F2
+
+#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
+#define IO_REPARSE_TAG_HSM 0xC0000004
+#define IO_REPARSE_TAG_SIS 0x80000007
+
+/* WSL reparse tags */
+#define IO_REPARSE_TAG_LX_SYMLINK_LE cpu_to_le32(0xA000001D)
+#define IO_REPARSE_TAG_AF_UNIX_LE cpu_to_le32(0x80000023)
+#define IO_REPARSE_TAG_LX_FIFO_LE cpu_to_le32(0x80000024)
+#define IO_REPARSE_TAG_LX_CHR_LE cpu_to_le32(0x80000025)
+#define IO_REPARSE_TAG_LX_BLK_LE cpu_to_le32(0x80000026)
+#endif /* __KSMBD_SMBFSCTL_H */
diff --git a/fs/smb/server/smbstatus.h b/fs/smb/server/smbstatus.h
new file mode 100644
index 000000000000..108a8b6ed24a
--- /dev/null
+++ b/fs/smb/server/smbstatus.h
@@ -0,0 +1,1822 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/*
+ * fs/cifs/smb2status.h
+ *
+ * SMB2 Status code (network error) definitions
+ * Definitions are from MS-ERREF
+ *
+ * Copyright (c) International Business Machines Corp., 2009,2011
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ */
+
+/*
+ * 0 1 2 3 4 5 6 7 8 9 0 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ * SEV C N <-------Facility--------> <------Error Status Code------>
+ *
+ * C is set if "customer defined" error, N bit is reserved and MBZ
+ */
+
+#define STATUS_SEVERITY_SUCCESS cpu_to_le32(0x0000)
+#define STATUS_SEVERITY_INFORMATIONAL cpu_to_le32(0x0001)
+#define STATUS_SEVERITY_WARNING cpu_to_le32(0x0002)
+#define STATUS_SEVERITY_ERROR cpu_to_le32(0x0003)
+
+struct ntstatus {
+ /* Facility is the high 12 bits of the following field */
+ __le32 Facility; /* low 2 bits Severity, next is Customer, then rsrvd */
+ __le32 Code;
+};
+
+#define STATUS_SUCCESS 0x00000000
+#define STATUS_WAIT_0 cpu_to_le32(0x00000000)
+#define STATUS_WAIT_1 cpu_to_le32(0x00000001)
+#define STATUS_WAIT_2 cpu_to_le32(0x00000002)
+#define STATUS_WAIT_3 cpu_to_le32(0x00000003)
+#define STATUS_WAIT_63 cpu_to_le32(0x0000003F)
+#define STATUS_ABANDONED cpu_to_le32(0x00000080)
+#define STATUS_ABANDONED_WAIT_0 cpu_to_le32(0x00000080)
+#define STATUS_ABANDONED_WAIT_63 cpu_to_le32(0x000000BF)
+#define STATUS_USER_APC cpu_to_le32(0x000000C0)
+#define STATUS_KERNEL_APC cpu_to_le32(0x00000100)
+#define STATUS_ALERTED cpu_to_le32(0x00000101)
+#define STATUS_TIMEOUT cpu_to_le32(0x00000102)
+#define STATUS_PENDING cpu_to_le32(0x00000103)
+#define STATUS_REPARSE cpu_to_le32(0x00000104)
+#define STATUS_MORE_ENTRIES cpu_to_le32(0x00000105)
+#define STATUS_NOT_ALL_ASSIGNED cpu_to_le32(0x00000106)
+#define STATUS_SOME_NOT_MAPPED cpu_to_le32(0x00000107)
+#define STATUS_OPLOCK_BREAK_IN_PROGRESS cpu_to_le32(0x00000108)
+#define STATUS_VOLUME_MOUNTED cpu_to_le32(0x00000109)
+#define STATUS_RXACT_COMMITTED cpu_to_le32(0x0000010A)
+#define STATUS_NOTIFY_CLEANUP cpu_to_le32(0x0000010B)
+#define STATUS_NOTIFY_ENUM_DIR cpu_to_le32(0x0000010C)
+#define STATUS_NO_QUOTAS_FOR_ACCOUNT cpu_to_le32(0x0000010D)
+#define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED cpu_to_le32(0x0000010E)
+#define STATUS_PAGE_FAULT_TRANSITION cpu_to_le32(0x00000110)
+#define STATUS_PAGE_FAULT_DEMAND_ZERO cpu_to_le32(0x00000111)
+#define STATUS_PAGE_FAULT_COPY_ON_WRITE cpu_to_le32(0x00000112)
+#define STATUS_PAGE_FAULT_GUARD_PAGE cpu_to_le32(0x00000113)
+#define STATUS_PAGE_FAULT_PAGING_FILE cpu_to_le32(0x00000114)
+#define STATUS_CACHE_PAGE_LOCKED cpu_to_le32(0x00000115)
+#define STATUS_CRASH_DUMP cpu_to_le32(0x00000116)
+#define STATUS_BUFFER_ALL_ZEROS cpu_to_le32(0x00000117)
+#define STATUS_REPARSE_OBJECT cpu_to_le32(0x00000118)
+#define STATUS_RESOURCE_REQUIREMENTS_CHANGED cpu_to_le32(0x00000119)
+#define STATUS_TRANSLATION_COMPLETE cpu_to_le32(0x00000120)
+#define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY cpu_to_le32(0x00000121)
+#define STATUS_NOTHING_TO_TERMINATE cpu_to_le32(0x00000122)
+#define STATUS_PROCESS_NOT_IN_JOB cpu_to_le32(0x00000123)
+#define STATUS_PROCESS_IN_JOB cpu_to_le32(0x00000124)
+#define STATUS_VOLSNAP_HIBERNATE_READY cpu_to_le32(0x00000125)
+#define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY cpu_to_le32(0x00000126)
+#define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED cpu_to_le32(0x00000127)
+#define STATUS_INTERRUPT_STILL_CONNECTED cpu_to_le32(0x00000128)
+#define STATUS_PROCESS_CLONED cpu_to_le32(0x00000129)
+#define STATUS_FILE_LOCKED_WITH_ONLY_READERS cpu_to_le32(0x0000012A)
+#define STATUS_FILE_LOCKED_WITH_WRITERS cpu_to_le32(0x0000012B)
+#define STATUS_RESOURCEMANAGER_READ_ONLY cpu_to_le32(0x00000202)
+#define STATUS_WAIT_FOR_OPLOCK cpu_to_le32(0x00000367)
+#define DBG_EXCEPTION_HANDLED cpu_to_le32(0x00010001)
+#define DBG_CONTINUE cpu_to_le32(0x00010002)
+#define STATUS_FLT_IO_COMPLETE cpu_to_le32(0x001C0001)
+#define STATUS_OBJECT_NAME_EXISTS cpu_to_le32(0x40000000)
+#define STATUS_THREAD_WAS_SUSPENDED cpu_to_le32(0x40000001)
+#define STATUS_WORKING_SET_LIMIT_RANGE cpu_to_le32(0x40000002)
+#define STATUS_IMAGE_NOT_AT_BASE cpu_to_le32(0x40000003)
+#define STATUS_RXACT_STATE_CREATED cpu_to_le32(0x40000004)
+#define STATUS_SEGMENT_NOTIFICATION cpu_to_le32(0x40000005)
+#define STATUS_LOCAL_USER_SESSION_KEY cpu_to_le32(0x40000006)
+#define STATUS_BAD_CURRENT_DIRECTORY cpu_to_le32(0x40000007)
+#define STATUS_SERIAL_MORE_WRITES cpu_to_le32(0x40000008)
+#define STATUS_REGISTRY_RECOVERED cpu_to_le32(0x40000009)
+#define STATUS_FT_READ_RECOVERY_FROM_BACKUP cpu_to_le32(0x4000000A)
+#define STATUS_FT_WRITE_RECOVERY cpu_to_le32(0x4000000B)
+#define STATUS_SERIAL_COUNTER_TIMEOUT cpu_to_le32(0x4000000C)
+#define STATUS_NULL_LM_PASSWORD cpu_to_le32(0x4000000D)
+#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH cpu_to_le32(0x4000000E)
+#define STATUS_RECEIVE_PARTIAL cpu_to_le32(0x4000000F)
+#define STATUS_RECEIVE_EXPEDITED cpu_to_le32(0x40000010)
+#define STATUS_RECEIVE_PARTIAL_EXPEDITED cpu_to_le32(0x40000011)
+#define STATUS_EVENT_DONE cpu_to_le32(0x40000012)
+#define STATUS_EVENT_PENDING cpu_to_le32(0x40000013)
+#define STATUS_CHECKING_FILE_SYSTEM cpu_to_le32(0x40000014)
+#define STATUS_FATAL_APP_EXIT cpu_to_le32(0x40000015)
+#define STATUS_PREDEFINED_HANDLE cpu_to_le32(0x40000016)
+#define STATUS_WAS_UNLOCKED cpu_to_le32(0x40000017)
+#define STATUS_SERVICE_NOTIFICATION cpu_to_le32(0x40000018)
+#define STATUS_WAS_LOCKED cpu_to_le32(0x40000019)
+#define STATUS_LOG_HARD_ERROR cpu_to_le32(0x4000001A)
+#define STATUS_ALREADY_WIN32 cpu_to_le32(0x4000001B)
+#define STATUS_WX86_UNSIMULATE cpu_to_le32(0x4000001C)
+#define STATUS_WX86_CONTINUE cpu_to_le32(0x4000001D)
+#define STATUS_WX86_SINGLE_STEP cpu_to_le32(0x4000001E)
+#define STATUS_WX86_BREAKPOINT cpu_to_le32(0x4000001F)
+#define STATUS_WX86_EXCEPTION_CONTINUE cpu_to_le32(0x40000020)
+#define STATUS_WX86_EXCEPTION_LASTCHANCE cpu_to_le32(0x40000021)
+#define STATUS_WX86_EXCEPTION_CHAIN cpu_to_le32(0x40000022)
+#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE cpu_to_le32(0x40000023)
+#define STATUS_NO_YIELD_PERFORMED cpu_to_le32(0x40000024)
+#define STATUS_TIMER_RESUME_IGNORED cpu_to_le32(0x40000025)
+#define STATUS_ARBITRATION_UNHANDLED cpu_to_le32(0x40000026)
+#define STATUS_CARDBUS_NOT_SUPPORTED cpu_to_le32(0x40000027)
+#define STATUS_WX86_CREATEWX86TIB cpu_to_le32(0x40000028)
+#define STATUS_MP_PROCESSOR_MISMATCH cpu_to_le32(0x40000029)
+#define STATUS_HIBERNATED cpu_to_le32(0x4000002A)
+#define STATUS_RESUME_HIBERNATION cpu_to_le32(0x4000002B)
+#define STATUS_FIRMWARE_UPDATED cpu_to_le32(0x4000002C)
+#define STATUS_DRIVERS_LEAKING_LOCKED_PAGES cpu_to_le32(0x4000002D)
+#define STATUS_MESSAGE_RETRIEVED cpu_to_le32(0x4000002E)
+#define STATUS_SYSTEM_POWERSTATE_TRANSITION cpu_to_le32(0x4000002F)
+#define STATUS_ALPC_CHECK_COMPLETION_LIST cpu_to_le32(0x40000030)
+#define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION cpu_to_le32(0x40000031)
+#define STATUS_ACCESS_AUDIT_BY_POLICY cpu_to_le32(0x40000032)
+#define STATUS_ABANDON_HIBERFILE cpu_to_le32(0x40000033)
+#define STATUS_BIZRULES_NOT_ENABLED cpu_to_le32(0x40000034)
+#define STATUS_WAKE_SYSTEM cpu_to_le32(0x40000294)
+#define STATUS_DS_SHUTTING_DOWN cpu_to_le32(0x40000370)
+#define DBG_REPLY_LATER cpu_to_le32(0x40010001)
+#define DBG_UNABLE_TO_PROVIDE_HANDLE cpu_to_le32(0x40010002)
+#define DBG_TERMINATE_THREAD cpu_to_le32(0x40010003)
+#define DBG_TERMINATE_PROCESS cpu_to_le32(0x40010004)
+#define DBG_CONTROL_C cpu_to_le32(0x40010005)
+#define DBG_PRINTEXCEPTION_C cpu_to_le32(0x40010006)
+#define DBG_RIPEXCEPTION cpu_to_le32(0x40010007)
+#define DBG_CONTROL_BREAK cpu_to_le32(0x40010008)
+#define DBG_COMMAND_EXCEPTION cpu_to_le32(0x40010009)
+#define RPC_NT_UUID_LOCAL_ONLY cpu_to_le32(0x40020056)
+#define RPC_NT_SEND_INCOMPLETE cpu_to_le32(0x400200AF)
+#define STATUS_CTX_CDM_CONNECT cpu_to_le32(0x400A0004)
+#define STATUS_CTX_CDM_DISCONNECT cpu_to_le32(0x400A0005)
+#define STATUS_SXS_RELEASE_ACTIVATION_CONTEXT cpu_to_le32(0x4015000D)
+#define STATUS_RECOVERY_NOT_NEEDED cpu_to_le32(0x40190034)
+#define STATUS_RM_ALREADY_STARTED cpu_to_le32(0x40190035)
+#define STATUS_LOG_NO_RESTART cpu_to_le32(0x401A000C)
+#define STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST cpu_to_le32(0x401B00EC)
+#define STATUS_GRAPHICS_PARTIAL_DATA_POPULATED cpu_to_le32(0x401E000A)
+#define STATUS_GRAPHICS_DRIVER_MISMATCH cpu_to_le32(0x401E0117)
+#define STATUS_GRAPHICS_MODE_NOT_PINNED cpu_to_le32(0x401E0307)
+#define STATUS_GRAPHICS_NO_PREFERRED_MODE cpu_to_le32(0x401E031E)
+#define STATUS_GRAPHICS_DATASET_IS_EMPTY cpu_to_le32(0x401E034B)
+#define STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET cpu_to_le32(0x401E034C)
+#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED \
+ cpu_to_le32(0x401E0351)
+#define STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS cpu_to_le32(0x401E042F)
+#define STATUS_GRAPHICS_LEADLINK_START_DEFERRED cpu_to_le32(0x401E0437)
+#define STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY cpu_to_le32(0x401E0439)
+#define STATUS_GRAPHICS_START_DEFERRED cpu_to_le32(0x401E043A)
+#define STATUS_NDIS_INDICATION_REQUIRED cpu_to_le32(0x40230001)
+#define STATUS_GUARD_PAGE_VIOLATION cpu_to_le32(0x80000001)
+#define STATUS_DATATYPE_MISALIGNMENT cpu_to_le32(0x80000002)
+#define STATUS_BREAKPOINT cpu_to_le32(0x80000003)
+#define STATUS_SINGLE_STEP cpu_to_le32(0x80000004)
+#define STATUS_BUFFER_OVERFLOW cpu_to_le32(0x80000005)
+#define STATUS_NO_MORE_FILES cpu_to_le32(0x80000006)
+#define STATUS_WAKE_SYSTEM_DEBUGGER cpu_to_le32(0x80000007)
+#define STATUS_HANDLES_CLOSED cpu_to_le32(0x8000000A)
+#define STATUS_NO_INHERITANCE cpu_to_le32(0x8000000B)
+#define STATUS_GUID_SUBSTITUTION_MADE cpu_to_le32(0x8000000C)
+#define STATUS_PARTIAL_COPY cpu_to_le32(0x8000000D)
+#define STATUS_DEVICE_PAPER_EMPTY cpu_to_le32(0x8000000E)
+#define STATUS_DEVICE_POWERED_OFF cpu_to_le32(0x8000000F)
+#define STATUS_DEVICE_OFF_LINE cpu_to_le32(0x80000010)
+#define STATUS_DEVICE_BUSY cpu_to_le32(0x80000011)
+#define STATUS_NO_MORE_EAS cpu_to_le32(0x80000012)
+#define STATUS_INVALID_EA_NAME cpu_to_le32(0x80000013)
+#define STATUS_EA_LIST_INCONSISTENT cpu_to_le32(0x80000014)
+#define STATUS_INVALID_EA_FLAG cpu_to_le32(0x80000015)
+#define STATUS_VERIFY_REQUIRED cpu_to_le32(0x80000016)
+#define STATUS_EXTRANEOUS_INFORMATION cpu_to_le32(0x80000017)
+#define STATUS_RXACT_COMMIT_NECESSARY cpu_to_le32(0x80000018)
+#define STATUS_NO_MORE_ENTRIES cpu_to_le32(0x8000001A)
+#define STATUS_FILEMARK_DETECTED cpu_to_le32(0x8000001B)
+#define STATUS_MEDIA_CHANGED cpu_to_le32(0x8000001C)
+#define STATUS_BUS_RESET cpu_to_le32(0x8000001D)
+#define STATUS_END_OF_MEDIA cpu_to_le32(0x8000001E)
+#define STATUS_BEGINNING_OF_MEDIA cpu_to_le32(0x8000001F)
+#define STATUS_MEDIA_CHECK cpu_to_le32(0x80000020)
+#define STATUS_SETMARK_DETECTED cpu_to_le32(0x80000021)
+#define STATUS_NO_DATA_DETECTED cpu_to_le32(0x80000022)
+#define STATUS_REDIRECTOR_HAS_OPEN_HANDLES cpu_to_le32(0x80000023)
+#define STATUS_SERVER_HAS_OPEN_HANDLES cpu_to_le32(0x80000024)
+#define STATUS_ALREADY_DISCONNECTED cpu_to_le32(0x80000025)
+#define STATUS_LONGJUMP cpu_to_le32(0x80000026)
+#define STATUS_CLEANER_CARTRIDGE_INSTALLED cpu_to_le32(0x80000027)
+#define STATUS_PLUGPLAY_QUERY_VETOED cpu_to_le32(0x80000028)
+#define STATUS_UNWIND_CONSOLIDATE cpu_to_le32(0x80000029)
+#define STATUS_REGISTRY_HIVE_RECOVERED cpu_to_le32(0x8000002A)
+#define STATUS_DLL_MIGHT_BE_INSECURE cpu_to_le32(0x8000002B)
+#define STATUS_DLL_MIGHT_BE_INCOMPATIBLE cpu_to_le32(0x8000002C)
+#define STATUS_STOPPED_ON_SYMLINK cpu_to_le32(0x8000002D)
+#define STATUS_DEVICE_REQUIRES_CLEANING cpu_to_le32(0x80000288)
+#define STATUS_DEVICE_DOOR_OPEN cpu_to_le32(0x80000289)
+#define STATUS_DATA_LOST_REPAIR cpu_to_le32(0x80000803)
+#define DBG_EXCEPTION_NOT_HANDLED cpu_to_le32(0x80010001)
+#define STATUS_CLUSTER_NODE_ALREADY_UP cpu_to_le32(0x80130001)
+#define STATUS_CLUSTER_NODE_ALREADY_DOWN cpu_to_le32(0x80130002)
+#define STATUS_CLUSTER_NETWORK_ALREADY_ONLINE cpu_to_le32(0x80130003)
+#define STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE cpu_to_le32(0x80130004)
+#define STATUS_CLUSTER_NODE_ALREADY_MEMBER cpu_to_le32(0x80130005)
+#define STATUS_COULD_NOT_RESIZE_LOG cpu_to_le32(0x80190009)
+#define STATUS_NO_TXF_METADATA cpu_to_le32(0x80190029)
+#define STATUS_CANT_RECOVER_WITH_HANDLE_OPEN cpu_to_le32(0x80190031)
+#define STATUS_TXF_METADATA_ALREADY_PRESENT cpu_to_le32(0x80190041)
+#define STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET cpu_to_le32(0x80190042)
+#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED \
+ cpu_to_le32(0x801B00EB)
+#define STATUS_FLT_BUFFER_TOO_SMALL cpu_to_le32(0x801C0001)
+#define STATUS_FVE_PARTIAL_METADATA cpu_to_le32(0x80210001)
+#define STATUS_UNSUCCESSFUL cpu_to_le32(0xC0000001)
+#define STATUS_NOT_IMPLEMENTED cpu_to_le32(0xC0000002)
+#define STATUS_INVALID_INFO_CLASS cpu_to_le32(0xC0000003)
+#define STATUS_INFO_LENGTH_MISMATCH cpu_to_le32(0xC0000004)
+#define STATUS_ACCESS_VIOLATION cpu_to_le32(0xC0000005)
+#define STATUS_IN_PAGE_ERROR cpu_to_le32(0xC0000006)
+#define STATUS_PAGEFILE_QUOTA cpu_to_le32(0xC0000007)
+#define STATUS_INVALID_HANDLE cpu_to_le32(0xC0000008)
+#define STATUS_BAD_INITIAL_STACK cpu_to_le32(0xC0000009)
+#define STATUS_BAD_INITIAL_PC cpu_to_le32(0xC000000A)
+#define STATUS_INVALID_CID cpu_to_le32(0xC000000B)
+#define STATUS_TIMER_NOT_CANCELED cpu_to_le32(0xC000000C)
+#define STATUS_INVALID_PARAMETER cpu_to_le32(0xC000000D)
+#define STATUS_NO_SUCH_DEVICE cpu_to_le32(0xC000000E)
+#define STATUS_NO_SUCH_FILE cpu_to_le32(0xC000000F)
+#define STATUS_INVALID_DEVICE_REQUEST cpu_to_le32(0xC0000010)
+#define STATUS_END_OF_FILE cpu_to_le32(0xC0000011)
+#define STATUS_WRONG_VOLUME cpu_to_le32(0xC0000012)
+#define STATUS_NO_MEDIA_IN_DEVICE cpu_to_le32(0xC0000013)
+#define STATUS_UNRECOGNIZED_MEDIA cpu_to_le32(0xC0000014)
+#define STATUS_NONEXISTENT_SECTOR cpu_to_le32(0xC0000015)
+#define STATUS_MORE_PROCESSING_REQUIRED cpu_to_le32(0xC0000016)
+#define STATUS_NO_MEMORY cpu_to_le32(0xC0000017)
+#define STATUS_CONFLICTING_ADDRESSES cpu_to_le32(0xC0000018)
+#define STATUS_NOT_MAPPED_VIEW cpu_to_le32(0xC0000019)
+#define STATUS_UNABLE_TO_FREE_VM cpu_to_le32(0xC000001A)
+#define STATUS_UNABLE_TO_DELETE_SECTION cpu_to_le32(0xC000001B)
+#define STATUS_INVALID_SYSTEM_SERVICE cpu_to_le32(0xC000001C)
+#define STATUS_ILLEGAL_INSTRUCTION cpu_to_le32(0xC000001D)
+#define STATUS_INVALID_LOCK_SEQUENCE cpu_to_le32(0xC000001E)
+#define STATUS_INVALID_VIEW_SIZE cpu_to_le32(0xC000001F)
+#define STATUS_INVALID_FILE_FOR_SECTION cpu_to_le32(0xC0000020)
+#define STATUS_ALREADY_COMMITTED cpu_to_le32(0xC0000021)
+#define STATUS_ACCESS_DENIED cpu_to_le32(0xC0000022)
+#define STATUS_BUFFER_TOO_SMALL cpu_to_le32(0xC0000023)
+#define STATUS_OBJECT_TYPE_MISMATCH cpu_to_le32(0xC0000024)
+#define STATUS_NONCONTINUABLE_EXCEPTION cpu_to_le32(0xC0000025)
+#define STATUS_INVALID_DISPOSITION cpu_to_le32(0xC0000026)
+#define STATUS_UNWIND cpu_to_le32(0xC0000027)
+#define STATUS_BAD_STACK cpu_to_le32(0xC0000028)
+#define STATUS_INVALID_UNWIND_TARGET cpu_to_le32(0xC0000029)
+#define STATUS_NOT_LOCKED cpu_to_le32(0xC000002A)
+#define STATUS_PARITY_ERROR cpu_to_le32(0xC000002B)
+#define STATUS_UNABLE_TO_DECOMMIT_VM cpu_to_le32(0xC000002C)
+#define STATUS_NOT_COMMITTED cpu_to_le32(0xC000002D)
+#define STATUS_INVALID_PORT_ATTRIBUTES cpu_to_le32(0xC000002E)
+#define STATUS_PORT_MESSAGE_TOO_LONG cpu_to_le32(0xC000002F)
+#define STATUS_INVALID_PARAMETER_MIX cpu_to_le32(0xC0000030)
+#define STATUS_INVALID_QUOTA_LOWER cpu_to_le32(0xC0000031)
+#define STATUS_DISK_CORRUPT_ERROR cpu_to_le32(0xC0000032)
+#define STATUS_OBJECT_NAME_INVALID cpu_to_le32(0xC0000033)
+#define STATUS_OBJECT_NAME_NOT_FOUND cpu_to_le32(0xC0000034)
+#define STATUS_OBJECT_NAME_COLLISION cpu_to_le32(0xC0000035)
+#define STATUS_PORT_DISCONNECTED cpu_to_le32(0xC0000037)
+#define STATUS_DEVICE_ALREADY_ATTACHED cpu_to_le32(0xC0000038)
+#define STATUS_OBJECT_PATH_INVALID cpu_to_le32(0xC0000039)
+#define STATUS_OBJECT_PATH_NOT_FOUND cpu_to_le32(0xC000003A)
+#define STATUS_OBJECT_PATH_SYNTAX_BAD cpu_to_le32(0xC000003B)
+#define STATUS_DATA_OVERRUN cpu_to_le32(0xC000003C)
+#define STATUS_DATA_LATE_ERROR cpu_to_le32(0xC000003D)
+#define STATUS_DATA_ERROR cpu_to_le32(0xC000003E)
+#define STATUS_CRC_ERROR cpu_to_le32(0xC000003F)
+#define STATUS_SECTION_TOO_BIG cpu_to_le32(0xC0000040)
+#define STATUS_PORT_CONNECTION_REFUSED cpu_to_le32(0xC0000041)
+#define STATUS_INVALID_PORT_HANDLE cpu_to_le32(0xC0000042)
+#define STATUS_SHARING_VIOLATION cpu_to_le32(0xC0000043)
+#define STATUS_QUOTA_EXCEEDED cpu_to_le32(0xC0000044)
+#define STATUS_INVALID_PAGE_PROTECTION cpu_to_le32(0xC0000045)
+#define STATUS_MUTANT_NOT_OWNED cpu_to_le32(0xC0000046)
+#define STATUS_SEMAPHORE_LIMIT_EXCEEDED cpu_to_le32(0xC0000047)
+#define STATUS_PORT_ALREADY_SET cpu_to_le32(0xC0000048)
+#define STATUS_SECTION_NOT_IMAGE cpu_to_le32(0xC0000049)
+#define STATUS_SUSPEND_COUNT_EXCEEDED cpu_to_le32(0xC000004A)
+#define STATUS_THREAD_IS_TERMINATING cpu_to_le32(0xC000004B)
+#define STATUS_BAD_WORKING_SET_LIMIT cpu_to_le32(0xC000004C)
+#define STATUS_INCOMPATIBLE_FILE_MAP cpu_to_le32(0xC000004D)
+#define STATUS_SECTION_PROTECTION cpu_to_le32(0xC000004E)
+#define STATUS_EAS_NOT_SUPPORTED cpu_to_le32(0xC000004F)
+#define STATUS_EA_TOO_LARGE cpu_to_le32(0xC0000050)
+#define STATUS_NONEXISTENT_EA_ENTRY cpu_to_le32(0xC0000051)
+#define STATUS_NO_EAS_ON_FILE cpu_to_le32(0xC0000052)
+#define STATUS_EA_CORRUPT_ERROR cpu_to_le32(0xC0000053)
+#define STATUS_FILE_LOCK_CONFLICT cpu_to_le32(0xC0000054)
+#define STATUS_LOCK_NOT_GRANTED cpu_to_le32(0xC0000055)
+#define STATUS_DELETE_PENDING cpu_to_le32(0xC0000056)
+#define STATUS_CTL_FILE_NOT_SUPPORTED cpu_to_le32(0xC0000057)
+#define STATUS_UNKNOWN_REVISION cpu_to_le32(0xC0000058)
+#define STATUS_REVISION_MISMATCH cpu_to_le32(0xC0000059)
+#define STATUS_INVALID_OWNER cpu_to_le32(0xC000005A)
+#define STATUS_INVALID_PRIMARY_GROUP cpu_to_le32(0xC000005B)
+#define STATUS_NO_IMPERSONATION_TOKEN cpu_to_le32(0xC000005C)
+#define STATUS_CANT_DISABLE_MANDATORY cpu_to_le32(0xC000005D)
+#define STATUS_NO_LOGON_SERVERS cpu_to_le32(0xC000005E)
+#define STATUS_NO_SUCH_LOGON_SESSION cpu_to_le32(0xC000005F)
+#define STATUS_NO_SUCH_PRIVILEGE cpu_to_le32(0xC0000060)
+#define STATUS_PRIVILEGE_NOT_HELD cpu_to_le32(0xC0000061)
+#define STATUS_INVALID_ACCOUNT_NAME cpu_to_le32(0xC0000062)
+#define STATUS_USER_EXISTS cpu_to_le32(0xC0000063)
+#define STATUS_NO_SUCH_USER cpu_to_le32(0xC0000064)
+#define STATUS_GROUP_EXISTS cpu_to_le32(0xC0000065)
+#define STATUS_NO_SUCH_GROUP cpu_to_le32(0xC0000066)
+#define STATUS_MEMBER_IN_GROUP cpu_to_le32(0xC0000067)
+#define STATUS_MEMBER_NOT_IN_GROUP cpu_to_le32(0xC0000068)
+#define STATUS_LAST_ADMIN cpu_to_le32(0xC0000069)
+#define STATUS_WRONG_PASSWORD cpu_to_le32(0xC000006A)
+#define STATUS_ILL_FORMED_PASSWORD cpu_to_le32(0xC000006B)
+#define STATUS_PASSWORD_RESTRICTION cpu_to_le32(0xC000006C)
+#define STATUS_LOGON_FAILURE cpu_to_le32(0xC000006D)
+#define STATUS_ACCOUNT_RESTRICTION cpu_to_le32(0xC000006E)
+#define STATUS_INVALID_LOGON_HOURS cpu_to_le32(0xC000006F)
+#define STATUS_INVALID_WORKSTATION cpu_to_le32(0xC0000070)
+#define STATUS_PASSWORD_EXPIRED cpu_to_le32(0xC0000071)
+#define STATUS_ACCOUNT_DISABLED cpu_to_le32(0xC0000072)
+#define STATUS_NONE_MAPPED cpu_to_le32(0xC0000073)
+#define STATUS_TOO_MANY_LUIDS_REQUESTED cpu_to_le32(0xC0000074)
+#define STATUS_LUIDS_EXHAUSTED cpu_to_le32(0xC0000075)
+#define STATUS_INVALID_SUB_AUTHORITY cpu_to_le32(0xC0000076)
+#define STATUS_INVALID_ACL cpu_to_le32(0xC0000077)
+#define STATUS_INVALID_SID cpu_to_le32(0xC0000078)
+#define STATUS_INVALID_SECURITY_DESCR cpu_to_le32(0xC0000079)
+#define STATUS_PROCEDURE_NOT_FOUND cpu_to_le32(0xC000007A)
+#define STATUS_INVALID_IMAGE_FORMAT cpu_to_le32(0xC000007B)
+#define STATUS_NO_TOKEN cpu_to_le32(0xC000007C)
+#define STATUS_BAD_INHERITANCE_ACL cpu_to_le32(0xC000007D)
+#define STATUS_RANGE_NOT_LOCKED cpu_to_le32(0xC000007E)
+#define STATUS_DISK_FULL cpu_to_le32(0xC000007F)
+#define STATUS_SERVER_DISABLED cpu_to_le32(0xC0000080)
+#define STATUS_SERVER_NOT_DISABLED cpu_to_le32(0xC0000081)
+#define STATUS_TOO_MANY_GUIDS_REQUESTED cpu_to_le32(0xC0000082)
+#define STATUS_GUIDS_EXHAUSTED cpu_to_le32(0xC0000083)
+#define STATUS_INVALID_ID_AUTHORITY cpu_to_le32(0xC0000084)
+#define STATUS_AGENTS_EXHAUSTED cpu_to_le32(0xC0000085)
+#define STATUS_INVALID_VOLUME_LABEL cpu_to_le32(0xC0000086)
+#define STATUS_SECTION_NOT_EXTENDED cpu_to_le32(0xC0000087)
+#define STATUS_NOT_MAPPED_DATA cpu_to_le32(0xC0000088)
+#define STATUS_RESOURCE_DATA_NOT_FOUND cpu_to_le32(0xC0000089)
+#define STATUS_RESOURCE_TYPE_NOT_FOUND cpu_to_le32(0xC000008A)
+#define STATUS_RESOURCE_NAME_NOT_FOUND cpu_to_le32(0xC000008B)
+#define STATUS_ARRAY_BOUNDS_EXCEEDED cpu_to_le32(0xC000008C)
+#define STATUS_FLOAT_DENORMAL_OPERAND cpu_to_le32(0xC000008D)
+#define STATUS_FLOAT_DIVIDE_BY_ZERO cpu_to_le32(0xC000008E)
+#define STATUS_FLOAT_INEXACT_RESULT cpu_to_le32(0xC000008F)
+#define STATUS_FLOAT_INVALID_OPERATION cpu_to_le32(0xC0000090)
+#define STATUS_FLOAT_OVERFLOW cpu_to_le32(0xC0000091)
+#define STATUS_FLOAT_STACK_CHECK cpu_to_le32(0xC0000092)
+#define STATUS_FLOAT_UNDERFLOW cpu_to_le32(0xC0000093)
+#define STATUS_INTEGER_DIVIDE_BY_ZERO cpu_to_le32(0xC0000094)
+#define STATUS_INTEGER_OVERFLOW cpu_to_le32(0xC0000095)
+#define STATUS_PRIVILEGED_INSTRUCTION cpu_to_le32(0xC0000096)
+#define STATUS_TOO_MANY_PAGING_FILES cpu_to_le32(0xC0000097)
+#define STATUS_FILE_INVALID cpu_to_le32(0xC0000098)
+#define STATUS_ALLOTTED_SPACE_EXCEEDED cpu_to_le32(0xC0000099)
+#define STATUS_INSUFFICIENT_RESOURCES cpu_to_le32(0xC000009A)
+#define STATUS_DFS_EXIT_PATH_FOUND cpu_to_le32(0xC000009B)
+#define STATUS_DEVICE_DATA_ERROR cpu_to_le32(0xC000009C)
+#define STATUS_DEVICE_NOT_CONNECTED cpu_to_le32(0xC000009D)
+#define STATUS_DEVICE_POWER_FAILURE cpu_to_le32(0xC000009E)
+#define STATUS_FREE_VM_NOT_AT_BASE cpu_to_le32(0xC000009F)
+#define STATUS_MEMORY_NOT_ALLOCATED cpu_to_le32(0xC00000A0)
+#define STATUS_WORKING_SET_QUOTA cpu_to_le32(0xC00000A1)
+#define STATUS_MEDIA_WRITE_PROTECTED cpu_to_le32(0xC00000A2)
+#define STATUS_DEVICE_NOT_READY cpu_to_le32(0xC00000A3)
+#define STATUS_INVALID_GROUP_ATTRIBUTES cpu_to_le32(0xC00000A4)
+#define STATUS_BAD_IMPERSONATION_LEVEL cpu_to_le32(0xC00000A5)
+#define STATUS_CANT_OPEN_ANONYMOUS cpu_to_le32(0xC00000A6)
+#define STATUS_BAD_VALIDATION_CLASS cpu_to_le32(0xC00000A7)
+#define STATUS_BAD_TOKEN_TYPE cpu_to_le32(0xC00000A8)
+#define STATUS_BAD_MASTER_BOOT_RECORD cpu_to_le32(0xC00000A9)
+#define STATUS_INSTRUCTION_MISALIGNMENT cpu_to_le32(0xC00000AA)
+#define STATUS_INSTANCE_NOT_AVAILABLE cpu_to_le32(0xC00000AB)
+#define STATUS_PIPE_NOT_AVAILABLE cpu_to_le32(0xC00000AC)
+#define STATUS_INVALID_PIPE_STATE cpu_to_le32(0xC00000AD)
+#define STATUS_PIPE_BUSY cpu_to_le32(0xC00000AE)
+#define STATUS_ILLEGAL_FUNCTION cpu_to_le32(0xC00000AF)
+#define STATUS_PIPE_DISCONNECTED cpu_to_le32(0xC00000B0)
+#define STATUS_PIPE_CLOSING cpu_to_le32(0xC00000B1)
+#define STATUS_PIPE_CONNECTED cpu_to_le32(0xC00000B2)
+#define STATUS_PIPE_LISTENING cpu_to_le32(0xC00000B3)
+#define STATUS_INVALID_READ_MODE cpu_to_le32(0xC00000B4)
+#define STATUS_IO_TIMEOUT cpu_to_le32(0xC00000B5)
+#define STATUS_FILE_FORCED_CLOSED cpu_to_le32(0xC00000B6)
+#define STATUS_PROFILING_NOT_STARTED cpu_to_le32(0xC00000B7)
+#define STATUS_PROFILING_NOT_STOPPED cpu_to_le32(0xC00000B8)
+#define STATUS_COULD_NOT_INTERPRET cpu_to_le32(0xC00000B9)
+#define STATUS_FILE_IS_A_DIRECTORY cpu_to_le32(0xC00000BA)
+#define STATUS_NOT_SUPPORTED cpu_to_le32(0xC00000BB)
+#define STATUS_REMOTE_NOT_LISTENING cpu_to_le32(0xC00000BC)
+#define STATUS_DUPLICATE_NAME cpu_to_le32(0xC00000BD)
+#define STATUS_BAD_NETWORK_PATH cpu_to_le32(0xC00000BE)
+#define STATUS_NETWORK_BUSY cpu_to_le32(0xC00000BF)
+#define STATUS_DEVICE_DOES_NOT_EXIST cpu_to_le32(0xC00000C0)
+#define STATUS_TOO_MANY_COMMANDS cpu_to_le32(0xC00000C1)
+#define STATUS_ADAPTER_HARDWARE_ERROR cpu_to_le32(0xC00000C2)
+#define STATUS_INVALID_NETWORK_RESPONSE cpu_to_le32(0xC00000C3)
+#define STATUS_UNEXPECTED_NETWORK_ERROR cpu_to_le32(0xC00000C4)
+#define STATUS_BAD_REMOTE_ADAPTER cpu_to_le32(0xC00000C5)
+#define STATUS_PRINT_QUEUE_FULL cpu_to_le32(0xC00000C6)
+#define STATUS_NO_SPOOL_SPACE cpu_to_le32(0xC00000C7)
+#define STATUS_PRINT_CANCELLED cpu_to_le32(0xC00000C8)
+#define STATUS_NETWORK_NAME_DELETED cpu_to_le32(0xC00000C9)
+#define STATUS_NETWORK_ACCESS_DENIED cpu_to_le32(0xC00000CA)
+#define STATUS_BAD_DEVICE_TYPE cpu_to_le32(0xC00000CB)
+#define STATUS_BAD_NETWORK_NAME cpu_to_le32(0xC00000CC)
+#define STATUS_TOO_MANY_NAMES cpu_to_le32(0xC00000CD)
+#define STATUS_TOO_MANY_SESSIONS cpu_to_le32(0xC00000CE)
+#define STATUS_SHARING_PAUSED cpu_to_le32(0xC00000CF)
+#define STATUS_REQUEST_NOT_ACCEPTED cpu_to_le32(0xC00000D0)
+#define STATUS_REDIRECTOR_PAUSED cpu_to_le32(0xC00000D1)
+#define STATUS_NET_WRITE_FAULT cpu_to_le32(0xC00000D2)
+#define STATUS_PROFILING_AT_LIMIT cpu_to_le32(0xC00000D3)
+#define STATUS_NOT_SAME_DEVICE cpu_to_le32(0xC00000D4)
+#define STATUS_FILE_RENAMED cpu_to_le32(0xC00000D5)
+#define STATUS_VIRTUAL_CIRCUIT_CLOSED cpu_to_le32(0xC00000D6)
+#define STATUS_NO_SECURITY_ON_OBJECT cpu_to_le32(0xC00000D7)
+#define STATUS_CANT_WAIT cpu_to_le32(0xC00000D8)
+#define STATUS_PIPE_EMPTY cpu_to_le32(0xC00000D9)
+#define STATUS_CANT_ACCESS_DOMAIN_INFO cpu_to_le32(0xC00000DA)
+#define STATUS_CANT_TERMINATE_SELF cpu_to_le32(0xC00000DB)
+#define STATUS_INVALID_SERVER_STATE cpu_to_le32(0xC00000DC)
+#define STATUS_INVALID_DOMAIN_STATE cpu_to_le32(0xC00000DD)
+#define STATUS_INVALID_DOMAIN_ROLE cpu_to_le32(0xC00000DE)
+#define STATUS_NO_SUCH_DOMAIN cpu_to_le32(0xC00000DF)
+#define STATUS_DOMAIN_EXISTS cpu_to_le32(0xC00000E0)
+#define STATUS_DOMAIN_LIMIT_EXCEEDED cpu_to_le32(0xC00000E1)
+#define STATUS_OPLOCK_NOT_GRANTED cpu_to_le32(0xC00000E2)
+#define STATUS_INVALID_OPLOCK_PROTOCOL cpu_to_le32(0xC00000E3)
+#define STATUS_INTERNAL_DB_CORRUPTION cpu_to_le32(0xC00000E4)
+#define STATUS_INTERNAL_ERROR cpu_to_le32(0xC00000E5)
+#define STATUS_GENERIC_NOT_MAPPED cpu_to_le32(0xC00000E6)
+#define STATUS_BAD_DESCRIPTOR_FORMAT cpu_to_le32(0xC00000E7)
+#define STATUS_INVALID_USER_BUFFER cpu_to_le32(0xC00000E8)
+#define STATUS_UNEXPECTED_IO_ERROR cpu_to_le32(0xC00000E9)
+#define STATUS_UNEXPECTED_MM_CREATE_ERR cpu_to_le32(0xC00000EA)
+#define STATUS_UNEXPECTED_MM_MAP_ERROR cpu_to_le32(0xC00000EB)
+#define STATUS_UNEXPECTED_MM_EXTEND_ERR cpu_to_le32(0xC00000EC)
+#define STATUS_NOT_LOGON_PROCESS cpu_to_le32(0xC00000ED)
+#define STATUS_LOGON_SESSION_EXISTS cpu_to_le32(0xC00000EE)
+#define STATUS_INVALID_PARAMETER_1 cpu_to_le32(0xC00000EF)
+#define STATUS_INVALID_PARAMETER_2 cpu_to_le32(0xC00000F0)
+#define STATUS_INVALID_PARAMETER_3 cpu_to_le32(0xC00000F1)
+#define STATUS_INVALID_PARAMETER_4 cpu_to_le32(0xC00000F2)
+#define STATUS_INVALID_PARAMETER_5 cpu_to_le32(0xC00000F3)
+#define STATUS_INVALID_PARAMETER_6 cpu_to_le32(0xC00000F4)
+#define STATUS_INVALID_PARAMETER_7 cpu_to_le32(0xC00000F5)
+#define STATUS_INVALID_PARAMETER_8 cpu_to_le32(0xC00000F6)
+#define STATUS_INVALID_PARAMETER_9 cpu_to_le32(0xC00000F7)
+#define STATUS_INVALID_PARAMETER_10 cpu_to_le32(0xC00000F8)
+#define STATUS_INVALID_PARAMETER_11 cpu_to_le32(0xC00000F9)
+#define STATUS_INVALID_PARAMETER_12 cpu_to_le32(0xC00000FA)
+#define STATUS_REDIRECTOR_NOT_STARTED cpu_to_le32(0xC00000FB)
+#define STATUS_REDIRECTOR_STARTED cpu_to_le32(0xC00000FC)
+#define STATUS_STACK_OVERFLOW cpu_to_le32(0xC00000FD)
+#define STATUS_NO_SUCH_PACKAGE cpu_to_le32(0xC00000FE)
+#define STATUS_BAD_FUNCTION_TABLE cpu_to_le32(0xC00000FF)
+#define STATUS_VARIABLE_NOT_FOUND cpu_to_le32(0xC0000100)
+#define STATUS_DIRECTORY_NOT_EMPTY cpu_to_le32(0xC0000101)
+#define STATUS_FILE_CORRUPT_ERROR cpu_to_le32(0xC0000102)
+#define STATUS_NOT_A_DIRECTORY cpu_to_le32(0xC0000103)
+#define STATUS_BAD_LOGON_SESSION_STATE cpu_to_le32(0xC0000104)
+#define STATUS_LOGON_SESSION_COLLISION cpu_to_le32(0xC0000105)
+#define STATUS_NAME_TOO_LONG cpu_to_le32(0xC0000106)
+#define STATUS_FILES_OPEN cpu_to_le32(0xC0000107)
+#define STATUS_CONNECTION_IN_USE cpu_to_le32(0xC0000108)
+#define STATUS_MESSAGE_NOT_FOUND cpu_to_le32(0xC0000109)
+#define STATUS_PROCESS_IS_TERMINATING cpu_to_le32(0xC000010A)
+#define STATUS_INVALID_LOGON_TYPE cpu_to_le32(0xC000010B)
+#define STATUS_NO_GUID_TRANSLATION cpu_to_le32(0xC000010C)
+#define STATUS_CANNOT_IMPERSONATE cpu_to_le32(0xC000010D)
+#define STATUS_IMAGE_ALREADY_LOADED cpu_to_le32(0xC000010E)
+#define STATUS_ABIOS_NOT_PRESENT cpu_to_le32(0xC000010F)
+#define STATUS_ABIOS_LID_NOT_EXIST cpu_to_le32(0xC0000110)
+#define STATUS_ABIOS_LID_ALREADY_OWNED cpu_to_le32(0xC0000111)
+#define STATUS_ABIOS_NOT_LID_OWNER cpu_to_le32(0xC0000112)
+#define STATUS_ABIOS_INVALID_COMMAND cpu_to_le32(0xC0000113)
+#define STATUS_ABIOS_INVALID_LID cpu_to_le32(0xC0000114)
+#define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE cpu_to_le32(0xC0000115)
+#define STATUS_ABIOS_INVALID_SELECTOR cpu_to_le32(0xC0000116)
+#define STATUS_NO_LDT cpu_to_le32(0xC0000117)
+#define STATUS_INVALID_LDT_SIZE cpu_to_le32(0xC0000118)
+#define STATUS_INVALID_LDT_OFFSET cpu_to_le32(0xC0000119)
+#define STATUS_INVALID_LDT_DESCRIPTOR cpu_to_le32(0xC000011A)
+#define STATUS_INVALID_IMAGE_NE_FORMAT cpu_to_le32(0xC000011B)
+#define STATUS_RXACT_INVALID_STATE cpu_to_le32(0xC000011C)
+#define STATUS_RXACT_COMMIT_FAILURE cpu_to_le32(0xC000011D)
+#define STATUS_MAPPED_FILE_SIZE_ZERO cpu_to_le32(0xC000011E)
+#define STATUS_TOO_MANY_OPENED_FILES cpu_to_le32(0xC000011F)
+#define STATUS_CANCELLED cpu_to_le32(0xC0000120)
+#define STATUS_CANNOT_DELETE cpu_to_le32(0xC0000121)
+#define STATUS_INVALID_COMPUTER_NAME cpu_to_le32(0xC0000122)
+#define STATUS_FILE_DELETED cpu_to_le32(0xC0000123)
+#define STATUS_SPECIAL_ACCOUNT cpu_to_le32(0xC0000124)
+#define STATUS_SPECIAL_GROUP cpu_to_le32(0xC0000125)
+#define STATUS_SPECIAL_USER cpu_to_le32(0xC0000126)
+#define STATUS_MEMBERS_PRIMARY_GROUP cpu_to_le32(0xC0000127)
+#define STATUS_FILE_CLOSED cpu_to_le32(0xC0000128)
+#define STATUS_TOO_MANY_THREADS cpu_to_le32(0xC0000129)
+#define STATUS_THREAD_NOT_IN_PROCESS cpu_to_le32(0xC000012A)
+#define STATUS_TOKEN_ALREADY_IN_USE cpu_to_le32(0xC000012B)
+#define STATUS_PAGEFILE_QUOTA_EXCEEDED cpu_to_le32(0xC000012C)
+#define STATUS_COMMITMENT_LIMIT cpu_to_le32(0xC000012D)
+#define STATUS_INVALID_IMAGE_LE_FORMAT cpu_to_le32(0xC000012E)
+#define STATUS_INVALID_IMAGE_NOT_MZ cpu_to_le32(0xC000012F)
+#define STATUS_INVALID_IMAGE_PROTECT cpu_to_le32(0xC0000130)
+#define STATUS_INVALID_IMAGE_WIN_16 cpu_to_le32(0xC0000131)
+#define STATUS_LOGON_SERVER_CONFLICT cpu_to_le32(0xC0000132)
+#define STATUS_TIME_DIFFERENCE_AT_DC cpu_to_le32(0xC0000133)
+#define STATUS_SYNCHRONIZATION_REQUIRED cpu_to_le32(0xC0000134)
+#define STATUS_DLL_NOT_FOUND cpu_to_le32(0xC0000135)
+#define STATUS_OPEN_FAILED cpu_to_le32(0xC0000136)
+#define STATUS_IO_PRIVILEGE_FAILED cpu_to_le32(0xC0000137)
+#define STATUS_ORDINAL_NOT_FOUND cpu_to_le32(0xC0000138)
+#define STATUS_ENTRYPOINT_NOT_FOUND cpu_to_le32(0xC0000139)
+#define STATUS_CONTROL_C_EXIT cpu_to_le32(0xC000013A)
+#define STATUS_LOCAL_DISCONNECT cpu_to_le32(0xC000013B)
+#define STATUS_REMOTE_DISCONNECT cpu_to_le32(0xC000013C)
+#define STATUS_REMOTE_RESOURCES cpu_to_le32(0xC000013D)
+#define STATUS_LINK_FAILED cpu_to_le32(0xC000013E)
+#define STATUS_LINK_TIMEOUT cpu_to_le32(0xC000013F)
+#define STATUS_INVALID_CONNECTION cpu_to_le32(0xC0000140)
+#define STATUS_INVALID_ADDRESS cpu_to_le32(0xC0000141)
+#define STATUS_DLL_INIT_FAILED cpu_to_le32(0xC0000142)
+#define STATUS_MISSING_SYSTEMFILE cpu_to_le32(0xC0000143)
+#define STATUS_UNHANDLED_EXCEPTION cpu_to_le32(0xC0000144)
+#define STATUS_APP_INIT_FAILURE cpu_to_le32(0xC0000145)
+#define STATUS_PAGEFILE_CREATE_FAILED cpu_to_le32(0xC0000146)
+#define STATUS_NO_PAGEFILE cpu_to_le32(0xC0000147)
+#define STATUS_INVALID_LEVEL cpu_to_le32(0xC0000148)
+#define STATUS_WRONG_PASSWORD_CORE cpu_to_le32(0xC0000149)
+#define STATUS_ILLEGAL_FLOAT_CONTEXT cpu_to_le32(0xC000014A)
+#define STATUS_PIPE_BROKEN cpu_to_le32(0xC000014B)
+#define STATUS_REGISTRY_CORRUPT cpu_to_le32(0xC000014C)
+#define STATUS_REGISTRY_IO_FAILED cpu_to_le32(0xC000014D)
+#define STATUS_NO_EVENT_PAIR cpu_to_le32(0xC000014E)
+#define STATUS_UNRECOGNIZED_VOLUME cpu_to_le32(0xC000014F)
+#define STATUS_SERIAL_NO_DEVICE_INITED cpu_to_le32(0xC0000150)
+#define STATUS_NO_SUCH_ALIAS cpu_to_le32(0xC0000151)
+#define STATUS_MEMBER_NOT_IN_ALIAS cpu_to_le32(0xC0000152)
+#define STATUS_MEMBER_IN_ALIAS cpu_to_le32(0xC0000153)
+#define STATUS_ALIAS_EXISTS cpu_to_le32(0xC0000154)
+#define STATUS_LOGON_NOT_GRANTED cpu_to_le32(0xC0000155)
+#define STATUS_TOO_MANY_SECRETS cpu_to_le32(0xC0000156)
+#define STATUS_SECRET_TOO_LONG cpu_to_le32(0xC0000157)
+#define STATUS_INTERNAL_DB_ERROR cpu_to_le32(0xC0000158)
+#define STATUS_FULLSCREEN_MODE cpu_to_le32(0xC0000159)
+#define STATUS_TOO_MANY_CONTEXT_IDS cpu_to_le32(0xC000015A)
+#define STATUS_LOGON_TYPE_NOT_GRANTED cpu_to_le32(0xC000015B)
+#define STATUS_NOT_REGISTRY_FILE cpu_to_le32(0xC000015C)
+#define STATUS_NT_CROSS_ENCRYPTION_REQUIRED cpu_to_le32(0xC000015D)
+#define STATUS_DOMAIN_CTRLR_CONFIG_ERROR cpu_to_le32(0xC000015E)
+#define STATUS_FT_MISSING_MEMBER cpu_to_le32(0xC000015F)
+#define STATUS_ILL_FORMED_SERVICE_ENTRY cpu_to_le32(0xC0000160)
+#define STATUS_ILLEGAL_CHARACTER cpu_to_le32(0xC0000161)
+#define STATUS_UNMAPPABLE_CHARACTER cpu_to_le32(0xC0000162)
+#define STATUS_UNDEFINED_CHARACTER cpu_to_le32(0xC0000163)
+#define STATUS_FLOPPY_VOLUME cpu_to_le32(0xC0000164)
+#define STATUS_FLOPPY_ID_MARK_NOT_FOUND cpu_to_le32(0xC0000165)
+#define STATUS_FLOPPY_WRONG_CYLINDER cpu_to_le32(0xC0000166)
+#define STATUS_FLOPPY_UNKNOWN_ERROR cpu_to_le32(0xC0000167)
+#define STATUS_FLOPPY_BAD_REGISTERS cpu_to_le32(0xC0000168)
+#define STATUS_DISK_RECALIBRATE_FAILED cpu_to_le32(0xC0000169)
+#define STATUS_DISK_OPERATION_FAILED cpu_to_le32(0xC000016A)
+#define STATUS_DISK_RESET_FAILED cpu_to_le32(0xC000016B)
+#define STATUS_SHARED_IRQ_BUSY cpu_to_le32(0xC000016C)
+#define STATUS_FT_ORPHANING cpu_to_le32(0xC000016D)
+#define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT cpu_to_le32(0xC000016E)
+#define STATUS_PARTITION_FAILURE cpu_to_le32(0xC0000172)
+#define STATUS_INVALID_BLOCK_LENGTH cpu_to_le32(0xC0000173)
+#define STATUS_DEVICE_NOT_PARTITIONED cpu_to_le32(0xC0000174)
+#define STATUS_UNABLE_TO_LOCK_MEDIA cpu_to_le32(0xC0000175)
+#define STATUS_UNABLE_TO_UNLOAD_MEDIA cpu_to_le32(0xC0000176)
+#define STATUS_EOM_OVERFLOW cpu_to_le32(0xC0000177)
+#define STATUS_NO_MEDIA cpu_to_le32(0xC0000178)
+#define STATUS_NO_SUCH_MEMBER cpu_to_le32(0xC000017A)
+#define STATUS_INVALID_MEMBER cpu_to_le32(0xC000017B)
+#define STATUS_KEY_DELETED cpu_to_le32(0xC000017C)
+#define STATUS_NO_LOG_SPACE cpu_to_le32(0xC000017D)
+#define STATUS_TOO_MANY_SIDS cpu_to_le32(0xC000017E)
+#define STATUS_LM_CROSS_ENCRYPTION_REQUIRED cpu_to_le32(0xC000017F)
+#define STATUS_KEY_HAS_CHILDREN cpu_to_le32(0xC0000180)
+#define STATUS_CHILD_MUST_BE_VOLATILE cpu_to_le32(0xC0000181)
+#define STATUS_DEVICE_CONFIGURATION_ERROR cpu_to_le32(0xC0000182)
+#define STATUS_DRIVER_INTERNAL_ERROR cpu_to_le32(0xC0000183)
+#define STATUS_INVALID_DEVICE_STATE cpu_to_le32(0xC0000184)
+#define STATUS_IO_DEVICE_ERROR cpu_to_le32(0xC0000185)
+#define STATUS_DEVICE_PROTOCOL_ERROR cpu_to_le32(0xC0000186)
+#define STATUS_BACKUP_CONTROLLER cpu_to_le32(0xC0000187)
+#define STATUS_LOG_FILE_FULL cpu_to_le32(0xC0000188)
+#define STATUS_TOO_LATE cpu_to_le32(0xC0000189)
+#define STATUS_NO_TRUST_LSA_SECRET cpu_to_le32(0xC000018A)
+#define STATUS_NO_TRUST_SAM_ACCOUNT cpu_to_le32(0xC000018B)
+#define STATUS_TRUSTED_DOMAIN_FAILURE cpu_to_le32(0xC000018C)
+#define STATUS_TRUSTED_RELATIONSHIP_FAILURE cpu_to_le32(0xC000018D)
+#define STATUS_EVENTLOG_FILE_CORRUPT cpu_to_le32(0xC000018E)
+#define STATUS_EVENTLOG_CANT_START cpu_to_le32(0xC000018F)
+#define STATUS_TRUST_FAILURE cpu_to_le32(0xC0000190)
+#define STATUS_MUTANT_LIMIT_EXCEEDED cpu_to_le32(0xC0000191)
+#define STATUS_NETLOGON_NOT_STARTED cpu_to_le32(0xC0000192)
+#define STATUS_ACCOUNT_EXPIRED cpu_to_le32(0xC0000193)
+#define STATUS_POSSIBLE_DEADLOCK cpu_to_le32(0xC0000194)
+#define STATUS_NETWORK_CREDENTIAL_CONFLICT cpu_to_le32(0xC0000195)
+#define STATUS_REMOTE_SESSION_LIMIT cpu_to_le32(0xC0000196)
+#define STATUS_EVENTLOG_FILE_CHANGED cpu_to_le32(0xC0000197)
+#define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT cpu_to_le32(0xC0000198)
+#define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT cpu_to_le32(0xC0000199)
+#define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT cpu_to_le32(0xC000019A)
+#define STATUS_DOMAIN_TRUST_INCONSISTENT cpu_to_le32(0xC000019B)
+#define STATUS_FS_DRIVER_REQUIRED cpu_to_le32(0xC000019C)
+#define STATUS_IMAGE_ALREADY_LOADED_AS_DLL cpu_to_le32(0xC000019D)
+#define STATUS_NETWORK_OPEN_RESTRICTION cpu_to_le32(0xC0000201)
+#define STATUS_NO_USER_SESSION_KEY cpu_to_le32(0xC0000202)
+#define STATUS_USER_SESSION_DELETED cpu_to_le32(0xC0000203)
+#define STATUS_RESOURCE_LANG_NOT_FOUND cpu_to_le32(0xC0000204)
+#define STATUS_INSUFF_SERVER_RESOURCES cpu_to_le32(0xC0000205)
+#define STATUS_INVALID_BUFFER_SIZE cpu_to_le32(0xC0000206)
+#define STATUS_INVALID_ADDRESS_COMPONENT cpu_to_le32(0xC0000207)
+#define STATUS_INVALID_ADDRESS_WILDCARD cpu_to_le32(0xC0000208)
+#define STATUS_TOO_MANY_ADDRESSES cpu_to_le32(0xC0000209)
+#define STATUS_ADDRESS_ALREADY_EXISTS cpu_to_le32(0xC000020A)
+#define STATUS_ADDRESS_CLOSED cpu_to_le32(0xC000020B)
+#define STATUS_CONNECTION_DISCONNECTED cpu_to_le32(0xC000020C)
+#define STATUS_CONNECTION_RESET cpu_to_le32(0xC000020D)
+#define STATUS_TOO_MANY_NODES cpu_to_le32(0xC000020E)
+#define STATUS_TRANSACTION_ABORTED cpu_to_le32(0xC000020F)
+#define STATUS_TRANSACTION_TIMED_OUT cpu_to_le32(0xC0000210)
+#define STATUS_TRANSACTION_NO_RELEASE cpu_to_le32(0xC0000211)
+#define STATUS_TRANSACTION_NO_MATCH cpu_to_le32(0xC0000212)
+#define STATUS_TRANSACTION_RESPONDED cpu_to_le32(0xC0000213)
+#define STATUS_TRANSACTION_INVALID_ID cpu_to_le32(0xC0000214)
+#define STATUS_TRANSACTION_INVALID_TYPE cpu_to_le32(0xC0000215)
+#define STATUS_NOT_SERVER_SESSION cpu_to_le32(0xC0000216)
+#define STATUS_NOT_CLIENT_SESSION cpu_to_le32(0xC0000217)
+#define STATUS_CANNOT_LOAD_REGISTRY_FILE cpu_to_le32(0xC0000218)
+#define STATUS_DEBUG_ATTACH_FAILED cpu_to_le32(0xC0000219)
+#define STATUS_SYSTEM_PROCESS_TERMINATED cpu_to_le32(0xC000021A)
+#define STATUS_DATA_NOT_ACCEPTED cpu_to_le32(0xC000021B)
+#define STATUS_NO_BROWSER_SERVERS_FOUND cpu_to_le32(0xC000021C)
+#define STATUS_VDM_HARD_ERROR cpu_to_le32(0xC000021D)
+#define STATUS_DRIVER_CANCEL_TIMEOUT cpu_to_le32(0xC000021E)
+#define STATUS_REPLY_MESSAGE_MISMATCH cpu_to_le32(0xC000021F)
+#define STATUS_MAPPED_ALIGNMENT cpu_to_le32(0xC0000220)
+#define STATUS_IMAGE_CHECKSUM_MISMATCH cpu_to_le32(0xC0000221)
+#define STATUS_LOST_WRITEBEHIND_DATA cpu_to_le32(0xC0000222)
+#define STATUS_CLIENT_SERVER_PARAMETERS_INVALID cpu_to_le32(0xC0000223)
+#define STATUS_PASSWORD_MUST_CHANGE cpu_to_le32(0xC0000224)
+#define STATUS_NOT_FOUND cpu_to_le32(0xC0000225)
+#define STATUS_NOT_TINY_STREAM cpu_to_le32(0xC0000226)
+#define STATUS_RECOVERY_FAILURE cpu_to_le32(0xC0000227)
+#define STATUS_STACK_OVERFLOW_READ cpu_to_le32(0xC0000228)
+#define STATUS_FAIL_CHECK cpu_to_le32(0xC0000229)
+#define STATUS_DUPLICATE_OBJECTID cpu_to_le32(0xC000022A)
+#define STATUS_OBJECTID_EXISTS cpu_to_le32(0xC000022B)
+#define STATUS_CONVERT_TO_LARGE cpu_to_le32(0xC000022C)
+#define STATUS_RETRY cpu_to_le32(0xC000022D)
+#define STATUS_FOUND_OUT_OF_SCOPE cpu_to_le32(0xC000022E)
+#define STATUS_ALLOCATE_BUCKET cpu_to_le32(0xC000022F)
+#define STATUS_PROPSET_NOT_FOUND cpu_to_le32(0xC0000230)
+#define STATUS_MARSHALL_OVERFLOW cpu_to_le32(0xC0000231)
+#define STATUS_INVALID_VARIANT cpu_to_le32(0xC0000232)
+#define STATUS_DOMAIN_CONTROLLER_NOT_FOUND cpu_to_le32(0xC0000233)
+#define STATUS_ACCOUNT_LOCKED_OUT cpu_to_le32(0xC0000234)
+#define STATUS_HANDLE_NOT_CLOSABLE cpu_to_le32(0xC0000235)
+#define STATUS_CONNECTION_REFUSED cpu_to_le32(0xC0000236)
+#define STATUS_GRACEFUL_DISCONNECT cpu_to_le32(0xC0000237)
+#define STATUS_ADDRESS_ALREADY_ASSOCIATED cpu_to_le32(0xC0000238)
+#define STATUS_ADDRESS_NOT_ASSOCIATED cpu_to_le32(0xC0000239)
+#define STATUS_CONNECTION_INVALID cpu_to_le32(0xC000023A)
+#define STATUS_CONNECTION_ACTIVE cpu_to_le32(0xC000023B)
+#define STATUS_NETWORK_UNREACHABLE cpu_to_le32(0xC000023C)
+#define STATUS_HOST_UNREACHABLE cpu_to_le32(0xC000023D)
+#define STATUS_PROTOCOL_UNREACHABLE cpu_to_le32(0xC000023E)
+#define STATUS_PORT_UNREACHABLE cpu_to_le32(0xC000023F)
+#define STATUS_REQUEST_ABORTED cpu_to_le32(0xC0000240)
+#define STATUS_CONNECTION_ABORTED cpu_to_le32(0xC0000241)
+#define STATUS_BAD_COMPRESSION_BUFFER cpu_to_le32(0xC0000242)
+#define STATUS_USER_MAPPED_FILE cpu_to_le32(0xC0000243)
+#define STATUS_AUDIT_FAILED cpu_to_le32(0xC0000244)
+#define STATUS_TIMER_RESOLUTION_NOT_SET cpu_to_le32(0xC0000245)
+#define STATUS_CONNECTION_COUNT_LIMIT cpu_to_le32(0xC0000246)
+#define STATUS_LOGIN_TIME_RESTRICTION cpu_to_le32(0xC0000247)
+#define STATUS_LOGIN_WKSTA_RESTRICTION cpu_to_le32(0xC0000248)
+#define STATUS_IMAGE_MP_UP_MISMATCH cpu_to_le32(0xC0000249)
+#define STATUS_INSUFFICIENT_LOGON_INFO cpu_to_le32(0xC0000250)
+#define STATUS_BAD_DLL_ENTRYPOINT cpu_to_le32(0xC0000251)
+#define STATUS_BAD_SERVICE_ENTRYPOINT cpu_to_le32(0xC0000252)
+#define STATUS_LPC_REPLY_LOST cpu_to_le32(0xC0000253)
+#define STATUS_IP_ADDRESS_CONFLICT1 cpu_to_le32(0xC0000254)
+#define STATUS_IP_ADDRESS_CONFLICT2 cpu_to_le32(0xC0000255)
+#define STATUS_REGISTRY_QUOTA_LIMIT cpu_to_le32(0xC0000256)
+#define STATUS_PATH_NOT_COVERED cpu_to_le32(0xC0000257)
+#define STATUS_NO_CALLBACK_ACTIVE cpu_to_le32(0xC0000258)
+#define STATUS_LICENSE_QUOTA_EXCEEDED cpu_to_le32(0xC0000259)
+#define STATUS_PWD_TOO_SHORT cpu_to_le32(0xC000025A)
+#define STATUS_PWD_TOO_RECENT cpu_to_le32(0xC000025B)
+#define STATUS_PWD_HISTORY_CONFLICT cpu_to_le32(0xC000025C)
+#define STATUS_PLUGPLAY_NO_DEVICE cpu_to_le32(0xC000025E)
+#define STATUS_UNSUPPORTED_COMPRESSION cpu_to_le32(0xC000025F)
+#define STATUS_INVALID_HW_PROFILE cpu_to_le32(0xC0000260)
+#define STATUS_INVALID_PLUGPLAY_DEVICE_PATH cpu_to_le32(0xC0000261)
+#define STATUS_DRIVER_ORDINAL_NOT_FOUND cpu_to_le32(0xC0000262)
+#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND cpu_to_le32(0xC0000263)
+#define STATUS_RESOURCE_NOT_OWNED cpu_to_le32(0xC0000264)
+#define STATUS_TOO_MANY_LINKS cpu_to_le32(0xC0000265)
+#define STATUS_QUOTA_LIST_INCONSISTENT cpu_to_le32(0xC0000266)
+#define STATUS_FILE_IS_OFFLINE cpu_to_le32(0xC0000267)
+#define STATUS_EVALUATION_EXPIRATION cpu_to_le32(0xC0000268)
+#define STATUS_ILLEGAL_DLL_RELOCATION cpu_to_le32(0xC0000269)
+#define STATUS_LICENSE_VIOLATION cpu_to_le32(0xC000026A)
+#define STATUS_DLL_INIT_FAILED_LOGOFF cpu_to_le32(0xC000026B)
+#define STATUS_DRIVER_UNABLE_TO_LOAD cpu_to_le32(0xC000026C)
+#define STATUS_DFS_UNAVAILABLE cpu_to_le32(0xC000026D)
+#define STATUS_VOLUME_DISMOUNTED cpu_to_le32(0xC000026E)
+#define STATUS_WX86_INTERNAL_ERROR cpu_to_le32(0xC000026F)
+#define STATUS_WX86_FLOAT_STACK_CHECK cpu_to_le32(0xC0000270)
+#define STATUS_VALIDATE_CONTINUE cpu_to_le32(0xC0000271)
+#define STATUS_NO_MATCH cpu_to_le32(0xC0000272)
+#define STATUS_NO_MORE_MATCHES cpu_to_le32(0xC0000273)
+#define STATUS_NOT_A_REPARSE_POINT cpu_to_le32(0xC0000275)
+#define STATUS_IO_REPARSE_TAG_INVALID cpu_to_le32(0xC0000276)
+#define STATUS_IO_REPARSE_TAG_MISMATCH cpu_to_le32(0xC0000277)
+#define STATUS_IO_REPARSE_DATA_INVALID cpu_to_le32(0xC0000278)
+#define STATUS_IO_REPARSE_TAG_NOT_HANDLED cpu_to_le32(0xC0000279)
+#define STATUS_REPARSE_POINT_NOT_RESOLVED cpu_to_le32(0xC0000280)
+#define STATUS_DIRECTORY_IS_A_REPARSE_POINT cpu_to_le32(0xC0000281)
+#define STATUS_RANGE_LIST_CONFLICT cpu_to_le32(0xC0000282)
+#define STATUS_SOURCE_ELEMENT_EMPTY cpu_to_le32(0xC0000283)
+#define STATUS_DESTINATION_ELEMENT_FULL cpu_to_le32(0xC0000284)
+#define STATUS_ILLEGAL_ELEMENT_ADDRESS cpu_to_le32(0xC0000285)
+#define STATUS_MAGAZINE_NOT_PRESENT cpu_to_le32(0xC0000286)
+#define STATUS_REINITIALIZATION_NEEDED cpu_to_le32(0xC0000287)
+#define STATUS_ENCRYPTION_FAILED cpu_to_le32(0xC000028A)
+#define STATUS_DECRYPTION_FAILED cpu_to_le32(0xC000028B)
+#define STATUS_RANGE_NOT_FOUND cpu_to_le32(0xC000028C)
+#define STATUS_NO_RECOVERY_POLICY cpu_to_le32(0xC000028D)
+#define STATUS_NO_EFS cpu_to_le32(0xC000028E)
+#define STATUS_WRONG_EFS cpu_to_le32(0xC000028F)
+#define STATUS_NO_USER_KEYS cpu_to_le32(0xC0000290)
+#define STATUS_FILE_NOT_ENCRYPTED cpu_to_le32(0xC0000291)
+#define STATUS_NOT_EXPORT_FORMAT cpu_to_le32(0xC0000292)
+#define STATUS_FILE_ENCRYPTED cpu_to_le32(0xC0000293)
+#define STATUS_WMI_GUID_NOT_FOUND cpu_to_le32(0xC0000295)
+#define STATUS_WMI_INSTANCE_NOT_FOUND cpu_to_le32(0xC0000296)
+#define STATUS_WMI_ITEMID_NOT_FOUND cpu_to_le32(0xC0000297)
+#define STATUS_WMI_TRY_AGAIN cpu_to_le32(0xC0000298)
+#define STATUS_SHARED_POLICY cpu_to_le32(0xC0000299)
+#define STATUS_POLICY_OBJECT_NOT_FOUND cpu_to_le32(0xC000029A)
+#define STATUS_POLICY_ONLY_IN_DS cpu_to_le32(0xC000029B)
+#define STATUS_VOLUME_NOT_UPGRADED cpu_to_le32(0xC000029C)
+#define STATUS_REMOTE_STORAGE_NOT_ACTIVE cpu_to_le32(0xC000029D)
+#define STATUS_REMOTE_STORAGE_MEDIA_ERROR cpu_to_le32(0xC000029E)
+#define STATUS_NO_TRACKING_SERVICE cpu_to_le32(0xC000029F)
+#define STATUS_SERVER_SID_MISMATCH cpu_to_le32(0xC00002A0)
+#define STATUS_DS_NO_ATTRIBUTE_OR_VALUE cpu_to_le32(0xC00002A1)
+#define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX cpu_to_le32(0xC00002A2)
+#define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED cpu_to_le32(0xC00002A3)
+#define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS cpu_to_le32(0xC00002A4)
+#define STATUS_DS_BUSY cpu_to_le32(0xC00002A5)
+#define STATUS_DS_UNAVAILABLE cpu_to_le32(0xC00002A6)
+#define STATUS_DS_NO_RIDS_ALLOCATED cpu_to_le32(0xC00002A7)
+#define STATUS_DS_NO_MORE_RIDS cpu_to_le32(0xC00002A8)
+#define STATUS_DS_INCORRECT_ROLE_OWNER cpu_to_le32(0xC00002A9)
+#define STATUS_DS_RIDMGR_INIT_ERROR cpu_to_le32(0xC00002AA)
+#define STATUS_DS_OBJ_CLASS_VIOLATION cpu_to_le32(0xC00002AB)
+#define STATUS_DS_CANT_ON_NON_LEAF cpu_to_le32(0xC00002AC)
+#define STATUS_DS_CANT_ON_RDN cpu_to_le32(0xC00002AD)
+#define STATUS_DS_CANT_MOD_OBJ_CLASS cpu_to_le32(0xC00002AE)
+#define STATUS_DS_CROSS_DOM_MOVE_FAILED cpu_to_le32(0xC00002AF)
+#define STATUS_DS_GC_NOT_AVAILABLE cpu_to_le32(0xC00002B0)
+#define STATUS_DIRECTORY_SERVICE_REQUIRED cpu_to_le32(0xC00002B1)
+#define STATUS_REPARSE_ATTRIBUTE_CONFLICT cpu_to_le32(0xC00002B2)
+#define STATUS_CANT_ENABLE_DENY_ONLY cpu_to_le32(0xC00002B3)
+#define STATUS_FLOAT_MULTIPLE_FAULTS cpu_to_le32(0xC00002B4)
+#define STATUS_FLOAT_MULTIPLE_TRAPS cpu_to_le32(0xC00002B5)
+#define STATUS_DEVICE_REMOVED cpu_to_le32(0xC00002B6)
+#define STATUS_JOURNAL_DELETE_IN_PROGRESS cpu_to_le32(0xC00002B7)
+#define STATUS_JOURNAL_NOT_ACTIVE cpu_to_le32(0xC00002B8)
+#define STATUS_NOINTERFACE cpu_to_le32(0xC00002B9)
+#define STATUS_DS_ADMIN_LIMIT_EXCEEDED cpu_to_le32(0xC00002C1)
+#define STATUS_DRIVER_FAILED_SLEEP cpu_to_le32(0xC00002C2)
+#define STATUS_MUTUAL_AUTHENTICATION_FAILED cpu_to_le32(0xC00002C3)
+#define STATUS_CORRUPT_SYSTEM_FILE cpu_to_le32(0xC00002C4)
+#define STATUS_DATATYPE_MISALIGNMENT_ERROR cpu_to_le32(0xC00002C5)
+#define STATUS_WMI_READ_ONLY cpu_to_le32(0xC00002C6)
+#define STATUS_WMI_SET_FAILURE cpu_to_le32(0xC00002C7)
+#define STATUS_COMMITMENT_MINIMUM cpu_to_le32(0xC00002C8)
+#define STATUS_REG_NAT_CONSUMPTION cpu_to_le32(0xC00002C9)
+#define STATUS_TRANSPORT_FULL cpu_to_le32(0xC00002CA)
+#define STATUS_DS_SAM_INIT_FAILURE cpu_to_le32(0xC00002CB)
+#define STATUS_ONLY_IF_CONNECTED cpu_to_le32(0xC00002CC)
+#define STATUS_DS_SENSITIVE_GROUP_VIOLATION cpu_to_le32(0xC00002CD)
+#define STATUS_PNP_RESTART_ENUMERATION cpu_to_le32(0xC00002CE)
+#define STATUS_JOURNAL_ENTRY_DELETED cpu_to_le32(0xC00002CF)
+#define STATUS_DS_CANT_MOD_PRIMARYGROUPID cpu_to_le32(0xC00002D0)
+#define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE cpu_to_le32(0xC00002D1)
+#define STATUS_PNP_REBOOT_REQUIRED cpu_to_le32(0xC00002D2)
+#define STATUS_POWER_STATE_INVALID cpu_to_le32(0xC00002D3)
+#define STATUS_DS_INVALID_GROUP_TYPE cpu_to_le32(0xC00002D4)
+#define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN cpu_to_le32(0xC00002D5)
+#define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN cpu_to_le32(0xC00002D6)
+#define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER cpu_to_le32(0xC00002D7)
+#define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER cpu_to_le32(0xC00002D8)
+#define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER cpu_to_le32(0xC00002D9)
+#define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER cpu_to_le32(0xC00002DA)
+#define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER \
+ cpu_to_le32(0xC00002DB)
+#define STATUS_DS_HAVE_PRIMARY_MEMBERS cpu_to_le32(0xC00002DC)
+#define STATUS_WMI_NOT_SUPPORTED cpu_to_le32(0xC00002DD)
+#define STATUS_INSUFFICIENT_POWER cpu_to_le32(0xC00002DE)
+#define STATUS_SAM_NEED_BOOTKEY_PASSWORD cpu_to_le32(0xC00002DF)
+#define STATUS_SAM_NEED_BOOTKEY_FLOPPY cpu_to_le32(0xC00002E0)
+#define STATUS_DS_CANT_START cpu_to_le32(0xC00002E1)
+#define STATUS_DS_INIT_FAILURE cpu_to_le32(0xC00002E2)
+#define STATUS_SAM_INIT_FAILURE cpu_to_le32(0xC00002E3)
+#define STATUS_DS_GC_REQUIRED cpu_to_le32(0xC00002E4)
+#define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY cpu_to_le32(0xC00002E5)
+#define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS cpu_to_le32(0xC00002E6)
+#define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED cpu_to_le32(0xC00002E7)
+#define STATUS_MULTIPLE_FAULT_VIOLATION cpu_to_le32(0xC00002E8)
+#define STATUS_CURRENT_DOMAIN_NOT_ALLOWED cpu_to_le32(0xC00002E9)
+#define STATUS_CANNOT_MAKE cpu_to_le32(0xC00002EA)
+#define STATUS_SYSTEM_SHUTDOWN cpu_to_le32(0xC00002EB)
+#define STATUS_DS_INIT_FAILURE_CONSOLE cpu_to_le32(0xC00002EC)
+#define STATUS_DS_SAM_INIT_FAILURE_CONSOLE cpu_to_le32(0xC00002ED)
+#define STATUS_UNFINISHED_CONTEXT_DELETED cpu_to_le32(0xC00002EE)
+#define STATUS_NO_TGT_REPLY cpu_to_le32(0xC00002EF)
+#define STATUS_OBJECTID_NOT_FOUND cpu_to_le32(0xC00002F0)
+#define STATUS_NO_IP_ADDRESSES cpu_to_le32(0xC00002F1)
+#define STATUS_WRONG_CREDENTIAL_HANDLE cpu_to_le32(0xC00002F2)
+#define STATUS_CRYPTO_SYSTEM_INVALID cpu_to_le32(0xC00002F3)
+#define STATUS_MAX_REFERRALS_EXCEEDED cpu_to_le32(0xC00002F4)
+#define STATUS_MUST_BE_KDC cpu_to_le32(0xC00002F5)
+#define STATUS_STRONG_CRYPTO_NOT_SUPPORTED cpu_to_le32(0xC00002F6)
+#define STATUS_TOO_MANY_PRINCIPALS cpu_to_le32(0xC00002F7)
+#define STATUS_NO_PA_DATA cpu_to_le32(0xC00002F8)
+#define STATUS_PKINIT_NAME_MISMATCH cpu_to_le32(0xC00002F9)
+#define STATUS_SMARTCARD_LOGON_REQUIRED cpu_to_le32(0xC00002FA)
+#define STATUS_KDC_INVALID_REQUEST cpu_to_le32(0xC00002FB)
+#define STATUS_KDC_UNABLE_TO_REFER cpu_to_le32(0xC00002FC)
+#define STATUS_KDC_UNKNOWN_ETYPE cpu_to_le32(0xC00002FD)
+#define STATUS_SHUTDOWN_IN_PROGRESS cpu_to_le32(0xC00002FE)
+#define STATUS_SERVER_SHUTDOWN_IN_PROGRESS cpu_to_le32(0xC00002FF)
+#define STATUS_NOT_SUPPORTED_ON_SBS cpu_to_le32(0xC0000300)
+#define STATUS_WMI_GUID_DISCONNECTED cpu_to_le32(0xC0000301)
+#define STATUS_WMI_ALREADY_DISABLED cpu_to_le32(0xC0000302)
+#define STATUS_WMI_ALREADY_ENABLED cpu_to_le32(0xC0000303)
+#define STATUS_MFT_TOO_FRAGMENTED cpu_to_le32(0xC0000304)
+#define STATUS_COPY_PROTECTION_FAILURE cpu_to_le32(0xC0000305)
+#define STATUS_CSS_AUTHENTICATION_FAILURE cpu_to_le32(0xC0000306)
+#define STATUS_CSS_KEY_NOT_PRESENT cpu_to_le32(0xC0000307)
+#define STATUS_CSS_KEY_NOT_ESTABLISHED cpu_to_le32(0xC0000308)
+#define STATUS_CSS_SCRAMBLED_SECTOR cpu_to_le32(0xC0000309)
+#define STATUS_CSS_REGION_MISMATCH cpu_to_le32(0xC000030A)
+#define STATUS_CSS_RESETS_EXHAUSTED cpu_to_le32(0xC000030B)
+#define STATUS_PKINIT_FAILURE cpu_to_le32(0xC0000320)
+#define STATUS_SMARTCARD_SUBSYSTEM_FAILURE cpu_to_le32(0xC0000321)
+#define STATUS_NO_KERB_KEY cpu_to_le32(0xC0000322)
+#define STATUS_HOST_DOWN cpu_to_le32(0xC0000350)
+#define STATUS_UNSUPPORTED_PREAUTH cpu_to_le32(0xC0000351)
+#define STATUS_EFS_ALG_BLOB_TOO_BIG cpu_to_le32(0xC0000352)
+#define STATUS_PORT_NOT_SET cpu_to_le32(0xC0000353)
+#define STATUS_DEBUGGER_INACTIVE cpu_to_le32(0xC0000354)
+#define STATUS_DS_VERSION_CHECK_FAILURE cpu_to_le32(0xC0000355)
+#define STATUS_AUDITING_DISABLED cpu_to_le32(0xC0000356)
+#define STATUS_PRENT4_MACHINE_ACCOUNT cpu_to_le32(0xC0000357)
+#define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER cpu_to_le32(0xC0000358)
+#define STATUS_INVALID_IMAGE_WIN_32 cpu_to_le32(0xC0000359)
+#define STATUS_INVALID_IMAGE_WIN_64 cpu_to_le32(0xC000035A)
+#define STATUS_BAD_BINDINGS cpu_to_le32(0xC000035B)
+#define STATUS_NETWORK_SESSION_EXPIRED cpu_to_le32(0xC000035C)
+#define STATUS_APPHELP_BLOCK cpu_to_le32(0xC000035D)
+#define STATUS_ALL_SIDS_FILTERED cpu_to_le32(0xC000035E)
+#define STATUS_NOT_SAFE_MODE_DRIVER cpu_to_le32(0xC000035F)
+#define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT cpu_to_le32(0xC0000361)
+#define STATUS_ACCESS_DISABLED_BY_POLICY_PATH cpu_to_le32(0xC0000362)
+#define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER cpu_to_le32(0xC0000363)
+#define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER cpu_to_le32(0xC0000364)
+#define STATUS_FAILED_DRIVER_ENTRY cpu_to_le32(0xC0000365)
+#define STATUS_DEVICE_ENUMERATION_ERROR cpu_to_le32(0xC0000366)
+#define STATUS_MOUNT_POINT_NOT_RESOLVED cpu_to_le32(0xC0000368)
+#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER cpu_to_le32(0xC0000369)
+#define STATUS_MCA_OCCURRED cpu_to_le32(0xC000036A)
+#define STATUS_DRIVER_BLOCKED_CRITICAL cpu_to_le32(0xC000036B)
+#define STATUS_DRIVER_BLOCKED cpu_to_le32(0xC000036C)
+#define STATUS_DRIVER_DATABASE_ERROR cpu_to_le32(0xC000036D)
+#define STATUS_SYSTEM_HIVE_TOO_LARGE cpu_to_le32(0xC000036E)
+#define STATUS_INVALID_IMPORT_OF_NON_DLL cpu_to_le32(0xC000036F)
+#define STATUS_NO_SECRETS cpu_to_le32(0xC0000371)
+#define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY cpu_to_le32(0xC0000372)
+#define STATUS_FAILED_STACK_SWITCH cpu_to_le32(0xC0000373)
+#define STATUS_HEAP_CORRUPTION cpu_to_le32(0xC0000374)
+#define STATUS_SMARTCARD_WRONG_PIN cpu_to_le32(0xC0000380)
+#define STATUS_SMARTCARD_CARD_BLOCKED cpu_to_le32(0xC0000381)
+#define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED cpu_to_le32(0xC0000382)
+#define STATUS_SMARTCARD_NO_CARD cpu_to_le32(0xC0000383)
+#define STATUS_SMARTCARD_NO_KEY_CONTAINER cpu_to_le32(0xC0000384)
+#define STATUS_SMARTCARD_NO_CERTIFICATE cpu_to_le32(0xC0000385)
+#define STATUS_SMARTCARD_NO_KEYSET cpu_to_le32(0xC0000386)
+#define STATUS_SMARTCARD_IO_ERROR cpu_to_le32(0xC0000387)
+#define STATUS_DOWNGRADE_DETECTED cpu_to_le32(0xC0000388)
+#define STATUS_SMARTCARD_CERT_REVOKED cpu_to_le32(0xC0000389)
+#define STATUS_ISSUING_CA_UNTRUSTED cpu_to_le32(0xC000038A)
+#define STATUS_REVOCATION_OFFLINE_C cpu_to_le32(0xC000038B)
+#define STATUS_PKINIT_CLIENT_FAILURE cpu_to_le32(0xC000038C)
+#define STATUS_SMARTCARD_CERT_EXPIRED cpu_to_le32(0xC000038D)
+#define STATUS_DRIVER_FAILED_PRIOR_UNLOAD cpu_to_le32(0xC000038E)
+#define STATUS_SMARTCARD_SILENT_CONTEXT cpu_to_le32(0xC000038F)
+#define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000401)
+#define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000402)
+#define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED cpu_to_le32(0xC0000403)
+#define STATUS_DS_NAME_NOT_UNIQUE cpu_to_le32(0xC0000404)
+#define STATUS_DS_DUPLICATE_ID_FOUND cpu_to_le32(0xC0000405)
+#define STATUS_DS_GROUP_CONVERSION_ERROR cpu_to_le32(0xC0000406)
+#define STATUS_VOLSNAP_PREPARE_HIBERNATE cpu_to_le32(0xC0000407)
+#define STATUS_USER2USER_REQUIRED cpu_to_le32(0xC0000408)
+#define STATUS_STACK_BUFFER_OVERRUN cpu_to_le32(0xC0000409)
+#define STATUS_NO_S4U_PROT_SUPPORT cpu_to_le32(0xC000040A)
+#define STATUS_CROSSREALM_DELEGATION_FAILURE cpu_to_le32(0xC000040B)
+#define STATUS_REVOCATION_OFFLINE_KDC cpu_to_le32(0xC000040C)
+#define STATUS_ISSUING_CA_UNTRUSTED_KDC cpu_to_le32(0xC000040D)
+#define STATUS_KDC_CERT_EXPIRED cpu_to_le32(0xC000040E)
+#define STATUS_KDC_CERT_REVOKED cpu_to_le32(0xC000040F)
+#define STATUS_PARAMETER_QUOTA_EXCEEDED cpu_to_le32(0xC0000410)
+#define STATUS_HIBERNATION_FAILURE cpu_to_le32(0xC0000411)
+#define STATUS_DELAY_LOAD_FAILED cpu_to_le32(0xC0000412)
+#define STATUS_AUTHENTICATION_FIREWALL_FAILED cpu_to_le32(0xC0000413)
+#define STATUS_VDM_DISALLOWED cpu_to_le32(0xC0000414)
+#define STATUS_HUNG_DISPLAY_DRIVER_THREAD cpu_to_le32(0xC0000415)
+#define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE \
+ cpu_to_le32(0xC0000416)
+#define STATUS_INVALID_CRUNTIME_PARAMETER cpu_to_le32(0xC0000417)
+#define STATUS_NTLM_BLOCKED cpu_to_le32(0xC0000418)
+#define STATUS_ASSERTION_FAILURE cpu_to_le32(0xC0000420)
+#define STATUS_VERIFIER_STOP cpu_to_le32(0xC0000421)
+#define STATUS_CALLBACK_POP_STACK cpu_to_le32(0xC0000423)
+#define STATUS_INCOMPATIBLE_DRIVER_BLOCKED cpu_to_le32(0xC0000424)
+#define STATUS_HIVE_UNLOADED cpu_to_le32(0xC0000425)
+#define STATUS_COMPRESSION_DISABLED cpu_to_le32(0xC0000426)
+#define STATUS_FILE_SYSTEM_LIMITATION cpu_to_le32(0xC0000427)
+#define STATUS_INVALID_IMAGE_HASH cpu_to_le32(0xC0000428)
+#define STATUS_NOT_CAPABLE cpu_to_le32(0xC0000429)
+#define STATUS_REQUEST_OUT_OF_SEQUENCE cpu_to_le32(0xC000042A)
+#define STATUS_IMPLEMENTATION_LIMIT cpu_to_le32(0xC000042B)
+#define STATUS_ELEVATION_REQUIRED cpu_to_le32(0xC000042C)
+#define STATUS_BEYOND_VDL cpu_to_le32(0xC0000432)
+#define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS cpu_to_le32(0xC0000433)
+#define STATUS_PTE_CHANGED cpu_to_le32(0xC0000434)
+#define STATUS_PURGE_FAILED cpu_to_le32(0xC0000435)
+#define STATUS_CRED_REQUIRES_CONFIRMATION cpu_to_le32(0xC0000440)
+#define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE cpu_to_le32(0xC0000441)
+#define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER cpu_to_le32(0xC0000442)
+#define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE cpu_to_le32(0xC0000443)
+#define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE cpu_to_le32(0xC0000444)
+#define STATUS_CS_ENCRYPTION_FILE_NOT_CSE cpu_to_le32(0xC0000445)
+#define STATUS_INVALID_LABEL cpu_to_le32(0xC0000446)
+#define STATUS_DRIVER_PROCESS_TERMINATED cpu_to_le32(0xC0000450)
+#define STATUS_AMBIGUOUS_SYSTEM_DEVICE cpu_to_le32(0xC0000451)
+#define STATUS_SYSTEM_DEVICE_NOT_FOUND cpu_to_le32(0xC0000452)
+#define STATUS_RESTART_BOOT_APPLICATION cpu_to_le32(0xC0000453)
+#define STATUS_INVALID_TASK_NAME cpu_to_le32(0xC0000500)
+#define STATUS_INVALID_TASK_INDEX cpu_to_le32(0xC0000501)
+#define STATUS_THREAD_ALREADY_IN_TASK cpu_to_le32(0xC0000502)
+#define STATUS_CALLBACK_BYPASS cpu_to_le32(0xC0000503)
+#define STATUS_PORT_CLOSED cpu_to_le32(0xC0000700)
+#define STATUS_MESSAGE_LOST cpu_to_le32(0xC0000701)
+#define STATUS_INVALID_MESSAGE cpu_to_le32(0xC0000702)
+#define STATUS_REQUEST_CANCELED cpu_to_le32(0xC0000703)
+#define STATUS_RECURSIVE_DISPATCH cpu_to_le32(0xC0000704)
+#define STATUS_LPC_RECEIVE_BUFFER_EXPECTED cpu_to_le32(0xC0000705)
+#define STATUS_LPC_INVALID_CONNECTION_USAGE cpu_to_le32(0xC0000706)
+#define STATUS_LPC_REQUESTS_NOT_ALLOWED cpu_to_le32(0xC0000707)
+#define STATUS_RESOURCE_IN_USE cpu_to_le32(0xC0000708)
+#define STATUS_HARDWARE_MEMORY_ERROR cpu_to_le32(0xC0000709)
+#define STATUS_THREADPOOL_HANDLE_EXCEPTION cpu_to_le32(0xC000070A)
+#define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED cpu_to_le32(0xC000070B)
+#define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED \
+ cpu_to_le32(0xC000070C)
+#define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED \
+ cpu_to_le32(0xC000070D)
+#define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED \
+ cpu_to_le32(0xC000070E)
+#define STATUS_THREADPOOL_RELEASED_DURING_OPERATION cpu_to_le32(0xC000070F)
+#define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING cpu_to_le32(0xC0000710)
+#define STATUS_APC_RETURNED_WHILE_IMPERSONATING cpu_to_le32(0xC0000711)
+#define STATUS_PROCESS_IS_PROTECTED cpu_to_le32(0xC0000712)
+#define STATUS_MCA_EXCEPTION cpu_to_le32(0xC0000713)
+#define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE cpu_to_le32(0xC0000714)
+#define STATUS_SYMLINK_CLASS_DISABLED cpu_to_le32(0xC0000715)
+#define STATUS_INVALID_IDN_NORMALIZATION cpu_to_le32(0xC0000716)
+#define STATUS_NO_UNICODE_TRANSLATION cpu_to_le32(0xC0000717)
+#define STATUS_ALREADY_REGISTERED cpu_to_le32(0xC0000718)
+#define STATUS_CONTEXT_MISMATCH cpu_to_le32(0xC0000719)
+#define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST cpu_to_le32(0xC000071A)
+#define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY cpu_to_le32(0xC000071B)
+#define STATUS_INVALID_THREAD cpu_to_le32(0xC000071C)
+#define STATUS_CALLBACK_RETURNED_TRANSACTION cpu_to_le32(0xC000071D)
+#define STATUS_CALLBACK_RETURNED_LDR_LOCK cpu_to_le32(0xC000071E)
+#define STATUS_CALLBACK_RETURNED_LANG cpu_to_le32(0xC000071F)
+#define STATUS_CALLBACK_RETURNED_PRI_BACK cpu_to_le32(0xC0000720)
+#define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY cpu_to_le32(0xC0000721)
+#define STATUS_DISK_REPAIR_DISABLED cpu_to_le32(0xC0000800)
+#define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS cpu_to_le32(0xC0000801)
+#define STATUS_DISK_QUOTA_EXCEEDED cpu_to_le32(0xC0000802)
+#define STATUS_CONTENT_BLOCKED cpu_to_le32(0xC0000804)
+#define STATUS_BAD_CLUSTERS cpu_to_le32(0xC0000805)
+#define STATUS_VOLUME_DIRTY cpu_to_le32(0xC0000806)
+#define STATUS_FILE_CHECKED_OUT cpu_to_le32(0xC0000901)
+#define STATUS_CHECKOUT_REQUIRED cpu_to_le32(0xC0000902)
+#define STATUS_BAD_FILE_TYPE cpu_to_le32(0xC0000903)
+#define STATUS_FILE_TOO_LARGE cpu_to_le32(0xC0000904)
+#define STATUS_FORMS_AUTH_REQUIRED cpu_to_le32(0xC0000905)
+#define STATUS_VIRUS_INFECTED cpu_to_le32(0xC0000906)
+#define STATUS_VIRUS_DELETED cpu_to_le32(0xC0000907)
+#define STATUS_BAD_MCFG_TABLE cpu_to_le32(0xC0000908)
+#define STATUS_WOW_ASSERTION cpu_to_le32(0xC0009898)
+#define STATUS_INVALID_SIGNATURE cpu_to_le32(0xC000A000)
+#define STATUS_HMAC_NOT_SUPPORTED cpu_to_le32(0xC000A001)
+#define STATUS_IPSEC_QUEUE_OVERFLOW cpu_to_le32(0xC000A010)
+#define STATUS_ND_QUEUE_OVERFLOW cpu_to_le32(0xC000A011)
+#define STATUS_HOPLIMIT_EXCEEDED cpu_to_le32(0xC000A012)
+#define STATUS_PROTOCOL_NOT_SUPPORTED cpu_to_le32(0xC000A013)
+#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED \
+ cpu_to_le32(0xC000A080)
+#define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR \
+ cpu_to_le32(0xC000A081)
+#define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR cpu_to_le32(0xC000A082)
+#define STATUS_XML_PARSE_ERROR cpu_to_le32(0xC000A083)
+#define STATUS_XMLDSIG_ERROR cpu_to_le32(0xC000A084)
+#define STATUS_WRONG_COMPARTMENT cpu_to_le32(0xC000A085)
+#define STATUS_AUTHIP_FAILURE cpu_to_le32(0xC000A086)
+#define DBG_NO_STATE_CHANGE cpu_to_le32(0xC0010001)
+#define DBG_APP_NOT_IDLE cpu_to_le32(0xC0010002)
+#define RPC_NT_INVALID_STRING_BINDING cpu_to_le32(0xC0020001)
+#define RPC_NT_WRONG_KIND_OF_BINDING cpu_to_le32(0xC0020002)
+#define RPC_NT_INVALID_BINDING cpu_to_le32(0xC0020003)
+#define RPC_NT_PROTSEQ_NOT_SUPPORTED cpu_to_le32(0xC0020004)
+#define RPC_NT_INVALID_RPC_PROTSEQ cpu_to_le32(0xC0020005)
+#define RPC_NT_INVALID_STRING_UUID cpu_to_le32(0xC0020006)
+#define RPC_NT_INVALID_ENDPOINT_FORMAT cpu_to_le32(0xC0020007)
+#define RPC_NT_INVALID_NET_ADDR cpu_to_le32(0xC0020008)
+#define RPC_NT_NO_ENDPOINT_FOUND cpu_to_le32(0xC0020009)
+#define RPC_NT_INVALID_TIMEOUT cpu_to_le32(0xC002000A)
+#define RPC_NT_OBJECT_NOT_FOUND cpu_to_le32(0xC002000B)
+#define RPC_NT_ALREADY_REGISTERED cpu_to_le32(0xC002000C)
+#define RPC_NT_TYPE_ALREADY_REGISTERED cpu_to_le32(0xC002000D)
+#define RPC_NT_ALREADY_LISTENING cpu_to_le32(0xC002000E)
+#define RPC_NT_NO_PROTSEQS_REGISTERED cpu_to_le32(0xC002000F)
+#define RPC_NT_NOT_LISTENING cpu_to_le32(0xC0020010)
+#define RPC_NT_UNKNOWN_MGR_TYPE cpu_to_le32(0xC0020011)
+#define RPC_NT_UNKNOWN_IF cpu_to_le32(0xC0020012)
+#define RPC_NT_NO_BINDINGS cpu_to_le32(0xC0020013)
+#define RPC_NT_NO_PROTSEQS cpu_to_le32(0xC0020014)
+#define RPC_NT_CANT_CREATE_ENDPOINT cpu_to_le32(0xC0020015)
+#define RPC_NT_OUT_OF_RESOURCES cpu_to_le32(0xC0020016)
+#define RPC_NT_SERVER_UNAVAILABLE cpu_to_le32(0xC0020017)
+#define RPC_NT_SERVER_TOO_BUSY cpu_to_le32(0xC0020018)
+#define RPC_NT_INVALID_NETWORK_OPTIONS cpu_to_le32(0xC0020019)
+#define RPC_NT_NO_CALL_ACTIVE cpu_to_le32(0xC002001A)
+#define RPC_NT_CALL_FAILED cpu_to_le32(0xC002001B)
+#define RPC_NT_CALL_FAILED_DNE cpu_to_le32(0xC002001C)
+#define RPC_NT_PROTOCOL_ERROR cpu_to_le32(0xC002001D)
+#define RPC_NT_UNSUPPORTED_TRANS_SYN cpu_to_le32(0xC002001F)
+#define RPC_NT_UNSUPPORTED_TYPE cpu_to_le32(0xC0020021)
+#define RPC_NT_INVALID_TAG cpu_to_le32(0xC0020022)
+#define RPC_NT_INVALID_BOUND cpu_to_le32(0xC0020023)
+#define RPC_NT_NO_ENTRY_NAME cpu_to_le32(0xC0020024)
+#define RPC_NT_INVALID_NAME_SYNTAX cpu_to_le32(0xC0020025)
+#define RPC_NT_UNSUPPORTED_NAME_SYNTAX cpu_to_le32(0xC0020026)
+#define RPC_NT_UUID_NO_ADDRESS cpu_to_le32(0xC0020028)
+#define RPC_NT_DUPLICATE_ENDPOINT cpu_to_le32(0xC0020029)
+#define RPC_NT_UNKNOWN_AUTHN_TYPE cpu_to_le32(0xC002002A)
+#define RPC_NT_MAX_CALLS_TOO_SMALL cpu_to_le32(0xC002002B)
+#define RPC_NT_STRING_TOO_LONG cpu_to_le32(0xC002002C)
+#define RPC_NT_PROTSEQ_NOT_FOUND cpu_to_le32(0xC002002D)
+#define RPC_NT_PROCNUM_OUT_OF_RANGE cpu_to_le32(0xC002002E)
+#define RPC_NT_BINDING_HAS_NO_AUTH cpu_to_le32(0xC002002F)
+#define RPC_NT_UNKNOWN_AUTHN_SERVICE cpu_to_le32(0xC0020030)
+#define RPC_NT_UNKNOWN_AUTHN_LEVEL cpu_to_le32(0xC0020031)
+#define RPC_NT_INVALID_AUTH_IDENTITY cpu_to_le32(0xC0020032)
+#define RPC_NT_UNKNOWN_AUTHZ_SERVICE cpu_to_le32(0xC0020033)
+#define EPT_NT_INVALID_ENTRY cpu_to_le32(0xC0020034)
+#define EPT_NT_CANT_PERFORM_OP cpu_to_le32(0xC0020035)
+#define EPT_NT_NOT_REGISTERED cpu_to_le32(0xC0020036)
+#define RPC_NT_NOTHING_TO_EXPORT cpu_to_le32(0xC0020037)
+#define RPC_NT_INCOMPLETE_NAME cpu_to_le32(0xC0020038)
+#define RPC_NT_INVALID_VERS_OPTION cpu_to_le32(0xC0020039)
+#define RPC_NT_NO_MORE_MEMBERS cpu_to_le32(0xC002003A)
+#define RPC_NT_NOT_ALL_OBJS_UNEXPORTED cpu_to_le32(0xC002003B)
+#define RPC_NT_INTERFACE_NOT_FOUND cpu_to_le32(0xC002003C)
+#define RPC_NT_ENTRY_ALREADY_EXISTS cpu_to_le32(0xC002003D)
+#define RPC_NT_ENTRY_NOT_FOUND cpu_to_le32(0xC002003E)
+#define RPC_NT_NAME_SERVICE_UNAVAILABLE cpu_to_le32(0xC002003F)
+#define RPC_NT_INVALID_NAF_ID cpu_to_le32(0xC0020040)
+#define RPC_NT_CANNOT_SUPPORT cpu_to_le32(0xC0020041)
+#define RPC_NT_NO_CONTEXT_AVAILABLE cpu_to_le32(0xC0020042)
+#define RPC_NT_INTERNAL_ERROR cpu_to_le32(0xC0020043)
+#define RPC_NT_ZERO_DIVIDE cpu_to_le32(0xC0020044)
+#define RPC_NT_ADDRESS_ERROR cpu_to_le32(0xC0020045)
+#define RPC_NT_FP_DIV_ZERO cpu_to_le32(0xC0020046)
+#define RPC_NT_FP_UNDERFLOW cpu_to_le32(0xC0020047)
+#define RPC_NT_FP_OVERFLOW cpu_to_le32(0xC0020048)
+#define RPC_NT_CALL_IN_PROGRESS cpu_to_le32(0xC0020049)
+#define RPC_NT_NO_MORE_BINDINGS cpu_to_le32(0xC002004A)
+#define RPC_NT_GROUP_MEMBER_NOT_FOUND cpu_to_le32(0xC002004B)
+#define EPT_NT_CANT_CREATE cpu_to_le32(0xC002004C)
+#define RPC_NT_INVALID_OBJECT cpu_to_le32(0xC002004D)
+#define RPC_NT_NO_INTERFACES cpu_to_le32(0xC002004F)
+#define RPC_NT_CALL_CANCELLED cpu_to_le32(0xC0020050)
+#define RPC_NT_BINDING_INCOMPLETE cpu_to_le32(0xC0020051)
+#define RPC_NT_COMM_FAILURE cpu_to_le32(0xC0020052)
+#define RPC_NT_UNSUPPORTED_AUTHN_LEVEL cpu_to_le32(0xC0020053)
+#define RPC_NT_NO_PRINC_NAME cpu_to_le32(0xC0020054)
+#define RPC_NT_NOT_RPC_ERROR cpu_to_le32(0xC0020055)
+#define RPC_NT_SEC_PKG_ERROR cpu_to_le32(0xC0020057)
+#define RPC_NT_NOT_CANCELLED cpu_to_le32(0xC0020058)
+#define RPC_NT_INVALID_ASYNC_HANDLE cpu_to_le32(0xC0020062)
+#define RPC_NT_INVALID_ASYNC_CALL cpu_to_le32(0xC0020063)
+#define RPC_NT_PROXY_ACCESS_DENIED cpu_to_le32(0xC0020064)
+#define RPC_NT_NO_MORE_ENTRIES cpu_to_le32(0xC0030001)
+#define RPC_NT_SS_CHAR_TRANS_OPEN_FAIL cpu_to_le32(0xC0030002)
+#define RPC_NT_SS_CHAR_TRANS_SHORT_FILE cpu_to_le32(0xC0030003)
+#define RPC_NT_SS_IN_NULL_CONTEXT cpu_to_le32(0xC0030004)
+#define RPC_NT_SS_CONTEXT_MISMATCH cpu_to_le32(0xC0030005)
+#define RPC_NT_SS_CONTEXT_DAMAGED cpu_to_le32(0xC0030006)
+#define RPC_NT_SS_HANDLES_MISMATCH cpu_to_le32(0xC0030007)
+#define RPC_NT_SS_CANNOT_GET_CALL_HANDLE cpu_to_le32(0xC0030008)
+#define RPC_NT_NULL_REF_POINTER cpu_to_le32(0xC0030009)
+#define RPC_NT_ENUM_VALUE_OUT_OF_RANGE cpu_to_le32(0xC003000A)
+#define RPC_NT_BYTE_COUNT_TOO_SMALL cpu_to_le32(0xC003000B)
+#define RPC_NT_BAD_STUB_DATA cpu_to_le32(0xC003000C)
+#define RPC_NT_INVALID_ES_ACTION cpu_to_le32(0xC0030059)
+#define RPC_NT_WRONG_ES_VERSION cpu_to_le32(0xC003005A)
+#define RPC_NT_WRONG_STUB_VERSION cpu_to_le32(0xC003005B)
+#define RPC_NT_INVALID_PIPE_OBJECT cpu_to_le32(0xC003005C)
+#define RPC_NT_INVALID_PIPE_OPERATION cpu_to_le32(0xC003005D)
+#define RPC_NT_WRONG_PIPE_VERSION cpu_to_le32(0xC003005E)
+#define RPC_NT_PIPE_CLOSED cpu_to_le32(0xC003005F)
+#define RPC_NT_PIPE_DISCIPLINE_ERROR cpu_to_le32(0xC0030060)
+#define RPC_NT_PIPE_EMPTY cpu_to_le32(0xC0030061)
+#define STATUS_PNP_BAD_MPS_TABLE cpu_to_le32(0xC0040035)
+#define STATUS_PNP_TRANSLATION_FAILED cpu_to_le32(0xC0040036)
+#define STATUS_PNP_IRQ_TRANSLATION_FAILED cpu_to_le32(0xC0040037)
+#define STATUS_PNP_INVALID_ID cpu_to_le32(0xC0040038)
+#define STATUS_IO_REISSUE_AS_CACHED cpu_to_le32(0xC0040039)
+#define STATUS_CTX_WINSTATION_NAME_INVALID cpu_to_le32(0xC00A0001)
+#define STATUS_CTX_INVALID_PD cpu_to_le32(0xC00A0002)
+#define STATUS_CTX_PD_NOT_FOUND cpu_to_le32(0xC00A0003)
+#define STATUS_CTX_CLOSE_PENDING cpu_to_le32(0xC00A0006)
+#define STATUS_CTX_NO_OUTBUF cpu_to_le32(0xC00A0007)
+#define STATUS_CTX_MODEM_INF_NOT_FOUND cpu_to_le32(0xC00A0008)
+#define STATUS_CTX_INVALID_MODEMNAME cpu_to_le32(0xC00A0009)
+#define STATUS_CTX_RESPONSE_ERROR cpu_to_le32(0xC00A000A)
+#define STATUS_CTX_MODEM_RESPONSE_TIMEOUT cpu_to_le32(0xC00A000B)
+#define STATUS_CTX_MODEM_RESPONSE_NO_CARRIER cpu_to_le32(0xC00A000C)
+#define STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE cpu_to_le32(0xC00A000D)
+#define STATUS_CTX_MODEM_RESPONSE_BUSY cpu_to_le32(0xC00A000E)
+#define STATUS_CTX_MODEM_RESPONSE_VOICE cpu_to_le32(0xC00A000F)
+#define STATUS_CTX_TD_ERROR cpu_to_le32(0xC00A0010)
+#define STATUS_CTX_LICENSE_CLIENT_INVALID cpu_to_le32(0xC00A0012)
+#define STATUS_CTX_LICENSE_NOT_AVAILABLE cpu_to_le32(0xC00A0013)
+#define STATUS_CTX_LICENSE_EXPIRED cpu_to_le32(0xC00A0014)
+#define STATUS_CTX_WINSTATION_NOT_FOUND cpu_to_le32(0xC00A0015)
+#define STATUS_CTX_WINSTATION_NAME_COLLISION cpu_to_le32(0xC00A0016)
+#define STATUS_CTX_WINSTATION_BUSY cpu_to_le32(0xC00A0017)
+#define STATUS_CTX_BAD_VIDEO_MODE cpu_to_le32(0xC00A0018)
+#define STATUS_CTX_GRAPHICS_INVALID cpu_to_le32(0xC00A0022)
+#define STATUS_CTX_NOT_CONSOLE cpu_to_le32(0xC00A0024)
+#define STATUS_CTX_CLIENT_QUERY_TIMEOUT cpu_to_le32(0xC00A0026)
+#define STATUS_CTX_CONSOLE_DISCONNECT cpu_to_le32(0xC00A0027)
+#define STATUS_CTX_CONSOLE_CONNECT cpu_to_le32(0xC00A0028)
+#define STATUS_CTX_SHADOW_DENIED cpu_to_le32(0xC00A002A)
+#define STATUS_CTX_WINSTATION_ACCESS_DENIED cpu_to_le32(0xC00A002B)
+#define STATUS_CTX_INVALID_WD cpu_to_le32(0xC00A002E)
+#define STATUS_CTX_WD_NOT_FOUND cpu_to_le32(0xC00A002F)
+#define STATUS_CTX_SHADOW_INVALID cpu_to_le32(0xC00A0030)
+#define STATUS_CTX_SHADOW_DISABLED cpu_to_le32(0xC00A0031)
+#define STATUS_RDP_PROTOCOL_ERROR cpu_to_le32(0xC00A0032)
+#define STATUS_CTX_CLIENT_LICENSE_NOT_SET cpu_to_le32(0xC00A0033)
+#define STATUS_CTX_CLIENT_LICENSE_IN_USE cpu_to_le32(0xC00A0034)
+#define STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE cpu_to_le32(0xC00A0035)
+#define STATUS_CTX_SHADOW_NOT_RUNNING cpu_to_le32(0xC00A0036)
+#define STATUS_CTX_LOGON_DISABLED cpu_to_le32(0xC00A0037)
+#define STATUS_CTX_SECURITY_LAYER_ERROR cpu_to_le32(0xC00A0038)
+#define STATUS_TS_INCOMPATIBLE_SESSIONS cpu_to_le32(0xC00A0039)
+#define STATUS_MUI_FILE_NOT_FOUND cpu_to_le32(0xC00B0001)
+#define STATUS_MUI_INVALID_FILE cpu_to_le32(0xC00B0002)
+#define STATUS_MUI_INVALID_RC_CONFIG cpu_to_le32(0xC00B0003)
+#define STATUS_MUI_INVALID_LOCALE_NAME cpu_to_le32(0xC00B0004)
+#define STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME cpu_to_le32(0xC00B0005)
+#define STATUS_MUI_FILE_NOT_LOADED cpu_to_le32(0xC00B0006)
+#define STATUS_RESOURCE_ENUM_USER_STOP cpu_to_le32(0xC00B0007)
+#define STATUS_CLUSTER_INVALID_NODE cpu_to_le32(0xC0130001)
+#define STATUS_CLUSTER_NODE_EXISTS cpu_to_le32(0xC0130002)
+#define STATUS_CLUSTER_JOIN_IN_PROGRESS cpu_to_le32(0xC0130003)
+#define STATUS_CLUSTER_NODE_NOT_FOUND cpu_to_le32(0xC0130004)
+#define STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND cpu_to_le32(0xC0130005)
+#define STATUS_CLUSTER_NETWORK_EXISTS cpu_to_le32(0xC0130006)
+#define STATUS_CLUSTER_NETWORK_NOT_FOUND cpu_to_le32(0xC0130007)
+#define STATUS_CLUSTER_NETINTERFACE_EXISTS cpu_to_le32(0xC0130008)
+#define STATUS_CLUSTER_NETINTERFACE_NOT_FOUND cpu_to_le32(0xC0130009)
+#define STATUS_CLUSTER_INVALID_REQUEST cpu_to_le32(0xC013000A)
+#define STATUS_CLUSTER_INVALID_NETWORK_PROVIDER cpu_to_le32(0xC013000B)
+#define STATUS_CLUSTER_NODE_DOWN cpu_to_le32(0xC013000C)
+#define STATUS_CLUSTER_NODE_UNREACHABLE cpu_to_le32(0xC013000D)
+#define STATUS_CLUSTER_NODE_NOT_MEMBER cpu_to_le32(0xC013000E)
+#define STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS cpu_to_le32(0xC013000F)
+#define STATUS_CLUSTER_INVALID_NETWORK cpu_to_le32(0xC0130010)
+#define STATUS_CLUSTER_NO_NET_ADAPTERS cpu_to_le32(0xC0130011)
+#define STATUS_CLUSTER_NODE_UP cpu_to_le32(0xC0130012)
+#define STATUS_CLUSTER_NODE_PAUSED cpu_to_le32(0xC0130013)
+#define STATUS_CLUSTER_NODE_NOT_PAUSED cpu_to_le32(0xC0130014)
+#define STATUS_CLUSTER_NO_SECURITY_CONTEXT cpu_to_le32(0xC0130015)
+#define STATUS_CLUSTER_NETWORK_NOT_INTERNAL cpu_to_le32(0xC0130016)
+#define STATUS_CLUSTER_POISONED cpu_to_le32(0xC0130017)
+#define STATUS_ACPI_INVALID_OPCODE cpu_to_le32(0xC0140001)
+#define STATUS_ACPI_STACK_OVERFLOW cpu_to_le32(0xC0140002)
+#define STATUS_ACPI_ASSERT_FAILED cpu_to_le32(0xC0140003)
+#define STATUS_ACPI_INVALID_INDEX cpu_to_le32(0xC0140004)
+#define STATUS_ACPI_INVALID_ARGUMENT cpu_to_le32(0xC0140005)
+#define STATUS_ACPI_FATAL cpu_to_le32(0xC0140006)
+#define STATUS_ACPI_INVALID_SUPERNAME cpu_to_le32(0xC0140007)
+#define STATUS_ACPI_INVALID_ARGTYPE cpu_to_le32(0xC0140008)
+#define STATUS_ACPI_INVALID_OBJTYPE cpu_to_le32(0xC0140009)
+#define STATUS_ACPI_INVALID_TARGETTYPE cpu_to_le32(0xC014000A)
+#define STATUS_ACPI_INCORRECT_ARGUMENT_COUNT cpu_to_le32(0xC014000B)
+#define STATUS_ACPI_ADDRESS_NOT_MAPPED cpu_to_le32(0xC014000C)
+#define STATUS_ACPI_INVALID_EVENTTYPE cpu_to_le32(0xC014000D)
+#define STATUS_ACPI_HANDLER_COLLISION cpu_to_le32(0xC014000E)
+#define STATUS_ACPI_INVALID_DATA cpu_to_le32(0xC014000F)
+#define STATUS_ACPI_INVALID_REGION cpu_to_le32(0xC0140010)
+#define STATUS_ACPI_INVALID_ACCESS_SIZE cpu_to_le32(0xC0140011)
+#define STATUS_ACPI_ACQUIRE_GLOBAL_LOCK cpu_to_le32(0xC0140012)
+#define STATUS_ACPI_ALREADY_INITIALIZED cpu_to_le32(0xC0140013)
+#define STATUS_ACPI_NOT_INITIALIZED cpu_to_le32(0xC0140014)
+#define STATUS_ACPI_INVALID_MUTEX_LEVEL cpu_to_le32(0xC0140015)
+#define STATUS_ACPI_MUTEX_NOT_OWNED cpu_to_le32(0xC0140016)
+#define STATUS_ACPI_MUTEX_NOT_OWNER cpu_to_le32(0xC0140017)
+#define STATUS_ACPI_RS_ACCESS cpu_to_le32(0xC0140018)
+#define STATUS_ACPI_INVALID_TABLE cpu_to_le32(0xC0140019)
+#define STATUS_ACPI_REG_HANDLER_FAILED cpu_to_le32(0xC0140020)
+#define STATUS_ACPI_POWER_REQUEST_FAILED cpu_to_le32(0xC0140021)
+#define STATUS_SXS_SECTION_NOT_FOUND cpu_to_le32(0xC0150001)
+#define STATUS_SXS_CANT_GEN_ACTCTX cpu_to_le32(0xC0150002)
+#define STATUS_SXS_INVALID_ACTCTXDATA_FORMAT cpu_to_le32(0xC0150003)
+#define STATUS_SXS_ASSEMBLY_NOT_FOUND cpu_to_le32(0xC0150004)
+#define STATUS_SXS_MANIFEST_FORMAT_ERROR cpu_to_le32(0xC0150005)
+#define STATUS_SXS_MANIFEST_PARSE_ERROR cpu_to_le32(0xC0150006)
+#define STATUS_SXS_ACTIVATION_CONTEXT_DISABLED cpu_to_le32(0xC0150007)
+#define STATUS_SXS_KEY_NOT_FOUND cpu_to_le32(0xC0150008)
+#define STATUS_SXS_VERSION_CONFLICT cpu_to_le32(0xC0150009)
+#define STATUS_SXS_WRONG_SECTION_TYPE cpu_to_le32(0xC015000A)
+#define STATUS_SXS_THREAD_QUERIES_DISABLED cpu_to_le32(0xC015000B)
+#define STATUS_SXS_ASSEMBLY_MISSING cpu_to_le32(0xC015000C)
+#define STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET cpu_to_le32(0xC015000E)
+#define STATUS_SXS_EARLY_DEACTIVATION cpu_to_le32(0xC015000F)
+#define STATUS_SXS_INVALID_DEACTIVATION cpu_to_le32(0xC0150010)
+#define STATUS_SXS_MULTIPLE_DEACTIVATION cpu_to_le32(0xC0150011)
+#define STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY \
+ cpu_to_le32(0xC0150012)
+#define STATUS_SXS_PROCESS_TERMINATION_REQUESTED cpu_to_le32(0xC0150013)
+#define STATUS_SXS_CORRUPT_ACTIVATION_STACK cpu_to_le32(0xC0150014)
+#define STATUS_SXS_CORRUPTION cpu_to_le32(0xC0150015)
+#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE cpu_to_le32(0xC0150016)
+#define STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME cpu_to_le32(0xC0150017)
+#define STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE cpu_to_le32(0xC0150018)
+#define STATUS_SXS_IDENTITY_PARSE_ERROR cpu_to_le32(0xC0150019)
+#define STATUS_SXS_COMPONENT_STORE_CORRUPT cpu_to_le32(0xC015001A)
+#define STATUS_SXS_FILE_HASH_MISMATCH cpu_to_le32(0xC015001B)
+#define STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT \
+ cpu_to_le32(0xC015001C)
+#define STATUS_SXS_IDENTITIES_DIFFERENT cpu_to_le32(0xC015001D)
+#define STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT cpu_to_le32(0xC015001E)
+#define STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY cpu_to_le32(0xC015001F)
+#define STATUS_ADVANCED_INSTALLER_FAILED cpu_to_le32(0xC0150020)
+#define STATUS_XML_ENCODING_MISMATCH cpu_to_le32(0xC0150021)
+#define STATUS_SXS_MANIFEST_TOO_BIG cpu_to_le32(0xC0150022)
+#define STATUS_SXS_SETTING_NOT_REGISTERED cpu_to_le32(0xC0150023)
+#define STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE cpu_to_le32(0xC0150024)
+#define STATUS_SMI_PRIMITIVE_INSTALLER_FAILED cpu_to_le32(0xC0150025)
+#define STATUS_GENERIC_COMMAND_FAILED cpu_to_le32(0xC0150026)
+#define STATUS_SXS_FILE_HASH_MISSING cpu_to_le32(0xC0150027)
+#define STATUS_TRANSACTIONAL_CONFLICT cpu_to_le32(0xC0190001)
+#define STATUS_INVALID_TRANSACTION cpu_to_le32(0xC0190002)
+#define STATUS_TRANSACTION_NOT_ACTIVE cpu_to_le32(0xC0190003)
+#define STATUS_TM_INITIALIZATION_FAILED cpu_to_le32(0xC0190004)
+#define STATUS_RM_NOT_ACTIVE cpu_to_le32(0xC0190005)
+#define STATUS_RM_METADATA_CORRUPT cpu_to_le32(0xC0190006)
+#define STATUS_TRANSACTION_NOT_JOINED cpu_to_le32(0xC0190007)
+#define STATUS_DIRECTORY_NOT_RM cpu_to_le32(0xC0190008)
+#define STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE cpu_to_le32(0xC019000A)
+#define STATUS_LOG_RESIZE_INVALID_SIZE cpu_to_le32(0xC019000B)
+#define STATUS_REMOTE_FILE_VERSION_MISMATCH cpu_to_le32(0xC019000C)
+#define STATUS_CRM_PROTOCOL_ALREADY_EXISTS cpu_to_le32(0xC019000F)
+#define STATUS_TRANSACTION_PROPAGATION_FAILED cpu_to_le32(0xC0190010)
+#define STATUS_CRM_PROTOCOL_NOT_FOUND cpu_to_le32(0xC0190011)
+#define STATUS_TRANSACTION_SUPERIOR_EXISTS cpu_to_le32(0xC0190012)
+#define STATUS_TRANSACTION_REQUEST_NOT_VALID cpu_to_le32(0xC0190013)
+#define STATUS_TRANSACTION_NOT_REQUESTED cpu_to_le32(0xC0190014)
+#define STATUS_TRANSACTION_ALREADY_ABORTED cpu_to_le32(0xC0190015)
+#define STATUS_TRANSACTION_ALREADY_COMMITTED cpu_to_le32(0xC0190016)
+#define STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER cpu_to_le32(0xC0190017)
+#define STATUS_CURRENT_TRANSACTION_NOT_VALID cpu_to_le32(0xC0190018)
+#define STATUS_LOG_GROWTH_FAILED cpu_to_le32(0xC0190019)
+#define STATUS_OBJECT_NO_LONGER_EXISTS cpu_to_le32(0xC0190021)
+#define STATUS_STREAM_MINIVERSION_NOT_FOUND cpu_to_le32(0xC0190022)
+#define STATUS_STREAM_MINIVERSION_NOT_VALID cpu_to_le32(0xC0190023)
+#define STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION \
+ cpu_to_le32(0xC0190024)
+#define STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT cpu_to_le32(0xC0190025)
+#define STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS cpu_to_le32(0xC0190026)
+#define STATUS_HANDLE_NO_LONGER_VALID cpu_to_le32(0xC0190028)
+#define STATUS_LOG_CORRUPTION_DETECTED cpu_to_le32(0xC0190030)
+#define STATUS_RM_DISCONNECTED cpu_to_le32(0xC0190032)
+#define STATUS_ENLISTMENT_NOT_SUPERIOR cpu_to_le32(0xC0190033)
+#define STATUS_FILE_IDENTITY_NOT_PERSISTENT cpu_to_le32(0xC0190036)
+#define STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY cpu_to_le32(0xC0190037)
+#define STATUS_CANT_CROSS_RM_BOUNDARY cpu_to_le32(0xC0190038)
+#define STATUS_TXF_DIR_NOT_EMPTY cpu_to_le32(0xC0190039)
+#define STATUS_INDOUBT_TRANSACTIONS_EXIST cpu_to_le32(0xC019003A)
+#define STATUS_TM_VOLATILE cpu_to_le32(0xC019003B)
+#define STATUS_ROLLBACK_TIMER_EXPIRED cpu_to_le32(0xC019003C)
+#define STATUS_TXF_ATTRIBUTE_CORRUPT cpu_to_le32(0xC019003D)
+#define STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC019003E)
+#define STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED cpu_to_le32(0xC019003F)
+#define STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE cpu_to_le32(0xC0190040)
+#define STATUS_TRANSACTION_REQUIRED_PROMOTION cpu_to_le32(0xC0190043)
+#define STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION cpu_to_le32(0xC0190044)
+#define STATUS_TRANSACTIONS_NOT_FROZEN cpu_to_le32(0xC0190045)
+#define STATUS_TRANSACTION_FREEZE_IN_PROGRESS cpu_to_le32(0xC0190046)
+#define STATUS_NOT_SNAPSHOT_VOLUME cpu_to_le32(0xC0190047)
+#define STATUS_NO_SAVEPOINT_WITH_OPEN_FILES cpu_to_le32(0xC0190048)
+#define STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC0190049)
+#define STATUS_TM_IDENTITY_MISMATCH cpu_to_le32(0xC019004A)
+#define STATUS_FLOATED_SECTION cpu_to_le32(0xC019004B)
+#define STATUS_CANNOT_ACCEPT_TRANSACTED_WORK cpu_to_le32(0xC019004C)
+#define STATUS_CANNOT_ABORT_TRANSACTIONS cpu_to_le32(0xC019004D)
+#define STATUS_TRANSACTION_NOT_FOUND cpu_to_le32(0xC019004E)
+#define STATUS_RESOURCEMANAGER_NOT_FOUND cpu_to_le32(0xC019004F)
+#define STATUS_ENLISTMENT_NOT_FOUND cpu_to_le32(0xC0190050)
+#define STATUS_TRANSACTIONMANAGER_NOT_FOUND cpu_to_le32(0xC0190051)
+#define STATUS_TRANSACTIONMANAGER_NOT_ONLINE cpu_to_le32(0xC0190052)
+#define STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION \
+ cpu_to_le32(0xC0190053)
+#define STATUS_TRANSACTION_NOT_ROOT cpu_to_le32(0xC0190054)
+#define STATUS_TRANSACTION_OBJECT_EXPIRED cpu_to_le32(0xC0190055)
+#define STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION cpu_to_le32(0xC0190056)
+#define STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED cpu_to_le32(0xC0190057)
+#define STATUS_TRANSACTION_RECORD_TOO_LONG cpu_to_le32(0xC0190058)
+#define STATUS_NO_LINK_TRACKING_IN_TRANSACTION cpu_to_le32(0xC0190059)
+#define STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION cpu_to_le32(0xC019005A)
+#define STATUS_TRANSACTION_INTEGRITY_VIOLATED cpu_to_le32(0xC019005B)
+#define STATUS_LOG_SECTOR_INVALID cpu_to_le32(0xC01A0001)
+#define STATUS_LOG_SECTOR_PARITY_INVALID cpu_to_le32(0xC01A0002)
+#define STATUS_LOG_SECTOR_REMAPPED cpu_to_le32(0xC01A0003)
+#define STATUS_LOG_BLOCK_INCOMPLETE cpu_to_le32(0xC01A0004)
+#define STATUS_LOG_INVALID_RANGE cpu_to_le32(0xC01A0005)
+#define STATUS_LOG_BLOCKS_EXHAUSTED cpu_to_le32(0xC01A0006)
+#define STATUS_LOG_READ_CONTEXT_INVALID cpu_to_le32(0xC01A0007)
+#define STATUS_LOG_RESTART_INVALID cpu_to_le32(0xC01A0008)
+#define STATUS_LOG_BLOCK_VERSION cpu_to_le32(0xC01A0009)
+#define STATUS_LOG_BLOCK_INVALID cpu_to_le32(0xC01A000A)
+#define STATUS_LOG_READ_MODE_INVALID cpu_to_le32(0xC01A000B)
+#define STATUS_LOG_METADATA_CORRUPT cpu_to_le32(0xC01A000D)
+#define STATUS_LOG_METADATA_INVALID cpu_to_le32(0xC01A000E)
+#define STATUS_LOG_METADATA_INCONSISTENT cpu_to_le32(0xC01A000F)
+#define STATUS_LOG_RESERVATION_INVALID cpu_to_le32(0xC01A0010)
+#define STATUS_LOG_CANT_DELETE cpu_to_le32(0xC01A0011)
+#define STATUS_LOG_CONTAINER_LIMIT_EXCEEDED cpu_to_le32(0xC01A0012)
+#define STATUS_LOG_START_OF_LOG cpu_to_le32(0xC01A0013)
+#define STATUS_LOG_POLICY_ALREADY_INSTALLED cpu_to_le32(0xC01A0014)
+#define STATUS_LOG_POLICY_NOT_INSTALLED cpu_to_le32(0xC01A0015)
+#define STATUS_LOG_POLICY_INVALID cpu_to_le32(0xC01A0016)
+#define STATUS_LOG_POLICY_CONFLICT cpu_to_le32(0xC01A0017)
+#define STATUS_LOG_PINNED_ARCHIVE_TAIL cpu_to_le32(0xC01A0018)
+#define STATUS_LOG_RECORD_NONEXISTENT cpu_to_le32(0xC01A0019)
+#define STATUS_LOG_RECORDS_RESERVED_INVALID cpu_to_le32(0xC01A001A)
+#define STATUS_LOG_SPACE_RESERVED_INVALID cpu_to_le32(0xC01A001B)
+#define STATUS_LOG_TAIL_INVALID cpu_to_le32(0xC01A001C)
+#define STATUS_LOG_FULL cpu_to_le32(0xC01A001D)
+#define STATUS_LOG_MULTIPLEXED cpu_to_le32(0xC01A001E)
+#define STATUS_LOG_DEDICATED cpu_to_le32(0xC01A001F)
+#define STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS cpu_to_le32(0xC01A0020)
+#define STATUS_LOG_ARCHIVE_IN_PROGRESS cpu_to_le32(0xC01A0021)
+#define STATUS_LOG_EPHEMERAL cpu_to_le32(0xC01A0022)
+#define STATUS_LOG_NOT_ENOUGH_CONTAINERS cpu_to_le32(0xC01A0023)
+#define STATUS_LOG_CLIENT_ALREADY_REGISTERED cpu_to_le32(0xC01A0024)
+#define STATUS_LOG_CLIENT_NOT_REGISTERED cpu_to_le32(0xC01A0025)
+#define STATUS_LOG_FULL_HANDLER_IN_PROGRESS cpu_to_le32(0xC01A0026)
+#define STATUS_LOG_CONTAINER_READ_FAILED cpu_to_le32(0xC01A0027)
+#define STATUS_LOG_CONTAINER_WRITE_FAILED cpu_to_le32(0xC01A0028)
+#define STATUS_LOG_CONTAINER_OPEN_FAILED cpu_to_le32(0xC01A0029)
+#define STATUS_LOG_CONTAINER_STATE_INVALID cpu_to_le32(0xC01A002A)
+#define STATUS_LOG_STATE_INVALID cpu_to_le32(0xC01A002B)
+#define STATUS_LOG_PINNED cpu_to_le32(0xC01A002C)
+#define STATUS_LOG_METADATA_FLUSH_FAILED cpu_to_le32(0xC01A002D)
+#define STATUS_LOG_INCONSISTENT_SECURITY cpu_to_le32(0xC01A002E)
+#define STATUS_LOG_APPENDED_FLUSH_FAILED cpu_to_le32(0xC01A002F)
+#define STATUS_LOG_PINNED_RESERVATION cpu_to_le32(0xC01A0030)
+#define STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD cpu_to_le32(0xC01B00EA)
+#define STATUS_FLT_NO_HANDLER_DEFINED cpu_to_le32(0xC01C0001)
+#define STATUS_FLT_CONTEXT_ALREADY_DEFINED cpu_to_le32(0xC01C0002)
+#define STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST cpu_to_le32(0xC01C0003)
+#define STATUS_FLT_DISALLOW_FAST_IO cpu_to_le32(0xC01C0004)
+#define STATUS_FLT_INVALID_NAME_REQUEST cpu_to_le32(0xC01C0005)
+#define STATUS_FLT_NOT_SAFE_TO_POST_OPERATION cpu_to_le32(0xC01C0006)
+#define STATUS_FLT_NOT_INITIALIZED cpu_to_le32(0xC01C0007)
+#define STATUS_FLT_FILTER_NOT_READY cpu_to_le32(0xC01C0008)
+#define STATUS_FLT_POST_OPERATION_CLEANUP cpu_to_le32(0xC01C0009)
+#define STATUS_FLT_INTERNAL_ERROR cpu_to_le32(0xC01C000A)
+#define STATUS_FLT_DELETING_OBJECT cpu_to_le32(0xC01C000B)
+#define STATUS_FLT_MUST_BE_NONPAGED_POOL cpu_to_le32(0xC01C000C)
+#define STATUS_FLT_DUPLICATE_ENTRY cpu_to_le32(0xC01C000D)
+#define STATUS_FLT_CBDQ_DISABLED cpu_to_le32(0xC01C000E)
+#define STATUS_FLT_DO_NOT_ATTACH cpu_to_le32(0xC01C000F)
+#define STATUS_FLT_DO_NOT_DETACH cpu_to_le32(0xC01C0010)
+#define STATUS_FLT_INSTANCE_ALTITUDE_COLLISION cpu_to_le32(0xC01C0011)
+#define STATUS_FLT_INSTANCE_NAME_COLLISION cpu_to_le32(0xC01C0012)
+#define STATUS_FLT_FILTER_NOT_FOUND cpu_to_le32(0xC01C0013)
+#define STATUS_FLT_VOLUME_NOT_FOUND cpu_to_le32(0xC01C0014)
+#define STATUS_FLT_INSTANCE_NOT_FOUND cpu_to_le32(0xC01C0015)
+#define STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND cpu_to_le32(0xC01C0016)
+#define STATUS_FLT_INVALID_CONTEXT_REGISTRATION cpu_to_le32(0xC01C0017)
+#define STATUS_FLT_NAME_CACHE_MISS cpu_to_le32(0xC01C0018)
+#define STATUS_FLT_NO_DEVICE_OBJECT cpu_to_le32(0xC01C0019)
+#define STATUS_FLT_VOLUME_ALREADY_MOUNTED cpu_to_le32(0xC01C001A)
+#define STATUS_FLT_ALREADY_ENLISTED cpu_to_le32(0xC01C001B)
+#define STATUS_FLT_CONTEXT_ALREADY_LINKED cpu_to_le32(0xC01C001C)
+#define STATUS_FLT_NO_WAITER_FOR_REPLY cpu_to_le32(0xC01C0020)
+#define STATUS_MONITOR_NO_DESCRIPTOR cpu_to_le32(0xC01D0001)
+#define STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT cpu_to_le32(0xC01D0002)
+#define STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM cpu_to_le32(0xC01D0003)
+#define STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK cpu_to_le32(0xC01D0004)
+#define STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED cpu_to_le32(0xC01D0005)
+#define STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK \
+ cpu_to_le32(0xC01D0006)
+#define STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK \
+ cpu_to_le32(0xC01D0007)
+#define STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA cpu_to_le32(0xC01D0008)
+#define STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK cpu_to_le32(0xC01D0009)
+#define STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER cpu_to_le32(0xC01E0000)
+#define STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER cpu_to_le32(0xC01E0001)
+#define STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER cpu_to_le32(0xC01E0002)
+#define STATUS_GRAPHICS_ADAPTER_WAS_RESET cpu_to_le32(0xC01E0003)
+#define STATUS_GRAPHICS_INVALID_DRIVER_MODEL cpu_to_le32(0xC01E0004)
+#define STATUS_GRAPHICS_PRESENT_MODE_CHANGED cpu_to_le32(0xC01E0005)
+#define STATUS_GRAPHICS_PRESENT_OCCLUDED cpu_to_le32(0xC01E0006)
+#define STATUS_GRAPHICS_PRESENT_DENIED cpu_to_le32(0xC01E0007)
+#define STATUS_GRAPHICS_CANNOTCOLORCONVERT cpu_to_le32(0xC01E0008)
+#define STATUS_GRAPHICS_NO_VIDEO_MEMORY cpu_to_le32(0xC01E0100)
+#define STATUS_GRAPHICS_CANT_LOCK_MEMORY cpu_to_le32(0xC01E0101)
+#define STATUS_GRAPHICS_ALLOCATION_BUSY cpu_to_le32(0xC01E0102)
+#define STATUS_GRAPHICS_TOO_MANY_REFERENCES cpu_to_le32(0xC01E0103)
+#define STATUS_GRAPHICS_TRY_AGAIN_LATER cpu_to_le32(0xC01E0104)
+#define STATUS_GRAPHICS_TRY_AGAIN_NOW cpu_to_le32(0xC01E0105)
+#define STATUS_GRAPHICS_ALLOCATION_INVALID cpu_to_le32(0xC01E0106)
+#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE cpu_to_le32(0xC01E0107)
+#define STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED cpu_to_le32(0xC01E0108)
+#define STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION cpu_to_le32(0xC01E0109)
+#define STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE cpu_to_le32(0xC01E0110)
+#define STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION cpu_to_le32(0xC01E0111)
+#define STATUS_GRAPHICS_ALLOCATION_CLOSED cpu_to_le32(0xC01E0112)
+#define STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE cpu_to_le32(0xC01E0113)
+#define STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE cpu_to_le32(0xC01E0114)
+#define STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE cpu_to_le32(0xC01E0115)
+#define STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST cpu_to_le32(0xC01E0116)
+#define STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE cpu_to_le32(0xC01E0200)
+#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY cpu_to_le32(0xC01E0300)
+#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED cpu_to_le32(0xC01E0301)
+#define STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED \
+ cpu_to_le32(0xC01E0302)
+#define STATUS_GRAPHICS_INVALID_VIDPN cpu_to_le32(0xC01E0303)
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE cpu_to_le32(0xC01E0304)
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET cpu_to_le32(0xC01E0305)
+#define STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED cpu_to_le32(0xC01E0306)
+#define STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET cpu_to_le32(0xC01E0308)
+#define STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET cpu_to_le32(0xC01E0309)
+#define STATUS_GRAPHICS_INVALID_FREQUENCY cpu_to_le32(0xC01E030A)
+#define STATUS_GRAPHICS_INVALID_ACTIVE_REGION cpu_to_le32(0xC01E030B)
+#define STATUS_GRAPHICS_INVALID_TOTAL_REGION cpu_to_le32(0xC01E030C)
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE \
+ cpu_to_le32(0xC01E0310)
+#define STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE \
+ cpu_to_le32(0xC01E0311)
+#define STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET cpu_to_le32(0xC01E0312)
+#define STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY cpu_to_le32(0xC01E0313)
+#define STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET cpu_to_le32(0xC01E0314)
+#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET cpu_to_le32(0xC01E0315)
+#define STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET cpu_to_le32(0xC01E0316)
+#define STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET cpu_to_le32(0xC01E0317)
+#define STATUS_GRAPHICS_TARGET_ALREADY_IN_SET cpu_to_le32(0xC01E0318)
+#define STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH cpu_to_le32(0xC01E0319)
+#define STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY cpu_to_le32(0xC01E031A)
+#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET \
+ cpu_to_le32(0xC01E031B)
+#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE cpu_to_le32(0xC01E031C)
+#define STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET cpu_to_le32(0xC01E031D)
+#define STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET cpu_to_le32(0xC01E031F)
+#define STATUS_GRAPHICS_STALE_MODESET cpu_to_le32(0xC01E0320)
+#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET cpu_to_le32(0xC01E0321)
+#define STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE cpu_to_le32(0xC01E0322)
+#define STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN cpu_to_le32(0xC01E0323)
+#define STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0324)
+#define STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION \
+ cpu_to_le32(0xC01E0325)
+#define STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES \
+ cpu_to_le32(0xC01E0326)
+#define STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0327)
+#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE \
+ cpu_to_le32(0xC01E0328)
+#define STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET \
+ cpu_to_le32(0xC01E0329)
+#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET cpu_to_le32(0xC01E032A)
+#define STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR cpu_to_le32(0xC01E032B)
+#define STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET cpu_to_le32(0xC01E032C)
+#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET cpu_to_le32(0xC01E032D)
+#define STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE \
+ cpu_to_le32(0xC01E032E)
+#define STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE cpu_to_le32(0xC01E032F)
+#define STATUS_GRAPHICS_RESOURCES_NOT_RELATED cpu_to_le32(0xC01E0330)
+#define STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0331)
+#define STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE cpu_to_le32(0xC01E0332)
+#define STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET cpu_to_le32(0xC01E0333)
+#define STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER \
+ cpu_to_le32(0xC01E0334)
+#define STATUS_GRAPHICS_NO_VIDPNMGR cpu_to_le32(0xC01E0335)
+#define STATUS_GRAPHICS_NO_ACTIVE_VIDPN cpu_to_le32(0xC01E0336)
+#define STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY cpu_to_le32(0xC01E0337)
+#define STATUS_GRAPHICS_MONITOR_NOT_CONNECTED cpu_to_le32(0xC01E0338)
+#define STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0339)
+#define STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE cpu_to_le32(0xC01E033A)
+#define STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE cpu_to_le32(0xC01E033B)
+#define STATUS_GRAPHICS_INVALID_STRIDE cpu_to_le32(0xC01E033C)
+#define STATUS_GRAPHICS_INVALID_PIXELFORMAT cpu_to_le32(0xC01E033D)
+#define STATUS_GRAPHICS_INVALID_COLORBASIS cpu_to_le32(0xC01E033E)
+#define STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE cpu_to_le32(0xC01E033F)
+#define STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY cpu_to_le32(0xC01E0340)
+#define STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT \
+ cpu_to_le32(0xC01E0341)
+#define STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE cpu_to_le32(0xC01E0342)
+#define STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN cpu_to_le32(0xC01E0343)
+#define STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL cpu_to_le32(0xC01E0344)
+#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION \
+ cpu_to_le32(0xC01E0345)
+#define STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED \
+ cpu_to_le32(0xC01E0346)
+#define STATUS_GRAPHICS_INVALID_GAMMA_RAMP cpu_to_le32(0xC01E0347)
+#define STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED cpu_to_le32(0xC01E0348)
+#define STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED cpu_to_le32(0xC01E0349)
+#define STATUS_GRAPHICS_MODE_NOT_IN_MODESET cpu_to_le32(0xC01E034A)
+#define STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON \
+ cpu_to_le32(0xC01E034D)
+#define STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE cpu_to_le32(0xC01E034E)
+#define STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE cpu_to_le32(0xC01E034F)
+#define STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS \
+ cpu_to_le32(0xC01E0350)
+#define STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING cpu_to_le32(0xC01E0352)
+#define STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED cpu_to_le32(0xC01E0353)
+#define STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS cpu_to_le32(0xC01E0354)
+#define STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT cpu_to_le32(0xC01E0355)
+#define STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM cpu_to_le32(0xC01E0356)
+#define STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN \
+ cpu_to_le32(0xC01E0357)
+#define STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT \
+ cpu_to_le32(0xC01E0358)
+#define STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED cpu_to_le32(0xC01E0359)
+#define STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION \
+ cpu_to_le32(0xC01E035A)
+#define STATUS_GRAPHICS_INVALID_CLIENT_TYPE cpu_to_le32(0xC01E035B)
+#define STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET cpu_to_le32(0xC01E035C)
+#define STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED \
+ cpu_to_le32(0xC01E0400)
+#define STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED cpu_to_le32(0xC01E0401)
+#define STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER cpu_to_le32(0xC01E0430)
+#define STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED cpu_to_le32(0xC01E0431)
+#define STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED cpu_to_le32(0xC01E0432)
+#define STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY cpu_to_le32(0xC01E0433)
+#define STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED cpu_to_le32(0xC01E0434)
+#define STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON cpu_to_le32(0xC01E0435)
+#define STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE cpu_to_le32(0xC01E0436)
+#define STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER cpu_to_le32(0xC01E0438)
+#define STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED cpu_to_le32(0xC01E043B)
+#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS \
+ cpu_to_le32(0xC01E051C)
+#define STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST cpu_to_le32(0xC01E051D)
+#define STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR cpu_to_le32(0xC01E051E)
+#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS \
+ cpu_to_le32(0xC01E051F)
+#define STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED cpu_to_le32(0xC01E0520)
+#define STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST \
+ cpu_to_le32(0xC01E0521)
+#define STATUS_GRAPHICS_OPM_NOT_SUPPORTED cpu_to_le32(0xC01E0500)
+#define STATUS_GRAPHICS_COPP_NOT_SUPPORTED cpu_to_le32(0xC01E0501)
+#define STATUS_GRAPHICS_UAB_NOT_SUPPORTED cpu_to_le32(0xC01E0502)
+#define STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS cpu_to_le32(0xC01E0503)
+#define STATUS_GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL cpu_to_le32(0xC01E0504)
+#define STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST cpu_to_le32(0xC01E0505)
+#define STATUS_GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME \
+ cpu_to_le32(0xC01E0506)
+#define STATUS_GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP \
+ cpu_to_le32(0xC01E0507)
+#define STATUS_GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED \
+ cpu_to_le32(0xC01E0508)
+#define STATUS_GRAPHICS_OPM_INVALID_POINTER cpu_to_le32(0xC01E050A)
+#define STATUS_GRAPHICS_OPM_INTERNAL_ERROR cpu_to_le32(0xC01E050B)
+#define STATUS_GRAPHICS_OPM_INVALID_HANDLE cpu_to_le32(0xC01E050C)
+#define STATUS_GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE \
+ cpu_to_le32(0xC01E050D)
+#define STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH cpu_to_le32(0xC01E050E)
+#define STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED cpu_to_le32(0xC01E050F)
+#define STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED cpu_to_le32(0xC01E0510)
+#define STATUS_GRAPHICS_PVP_HFS_FAILED cpu_to_le32(0xC01E0511)
+#define STATUS_GRAPHICS_OPM_INVALID_SRM cpu_to_le32(0xC01E0512)
+#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP cpu_to_le32(0xC01E0513)
+#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP cpu_to_le32(0xC01E0514)
+#define STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA \
+ cpu_to_le32(0xC01E0515)
+#define STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET cpu_to_le32(0xC01E0516)
+#define STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH cpu_to_le32(0xC01E0517)
+#define STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE \
+ cpu_to_le32(0xC01E0518)
+#define STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS \
+ cpu_to_le32(0xC01E051A)
+#define STATUS_GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS \
+ cpu_to_le32(0xC01E051B)
+#define STATUS_GRAPHICS_I2C_NOT_SUPPORTED cpu_to_le32(0xC01E0580)
+#define STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST cpu_to_le32(0xC01E0581)
+#define STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA cpu_to_le32(0xC01E0582)
+#define STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA cpu_to_le32(0xC01E0583)
+#define STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED cpu_to_le32(0xC01E0584)
+#define STATUS_GRAPHICS_DDCCI_INVALID_DATA cpu_to_le32(0xC01E0585)
+#define STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE \
+ cpu_to_le32(0xC01E0586)
+#define STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING \
+ cpu_to_le32(0xC01E0587)
+#define STATUS_GRAPHICS_MCA_INTERNAL_ERROR cpu_to_le32(0xC01E0588)
+#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND cpu_to_le32(0xC01E0589)
+#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH cpu_to_le32(0xC01E058A)
+#define STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM cpu_to_le32(0xC01E058B)
+#define STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE cpu_to_le32(0xC01E058C)
+#define STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS cpu_to_le32(0xC01E058D)
+#define STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED cpu_to_le32(0xC01E05E0)
+#define STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME \
+ cpu_to_le32(0xC01E05E1)
+#define STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP \
+ cpu_to_le32(0xC01E05E2)
+#define STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED cpu_to_le32(0xC01E05E3)
+#define STATUS_GRAPHICS_INVALID_POINTER cpu_to_le32(0xC01E05E4)
+#define STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE \
+ cpu_to_le32(0xC01E05E5)
+#define STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL cpu_to_le32(0xC01E05E6)
+#define STATUS_GRAPHICS_INTERNAL_ERROR cpu_to_le32(0xC01E05E7)
+#define STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS cpu_to_le32(0xC01E05E8)
+#define STATUS_FVE_LOCKED_VOLUME cpu_to_le32(0xC0210000)
+#define STATUS_FVE_NOT_ENCRYPTED cpu_to_le32(0xC0210001)
+#define STATUS_FVE_BAD_INFORMATION cpu_to_le32(0xC0210002)
+#define STATUS_FVE_TOO_SMALL cpu_to_le32(0xC0210003)
+#define STATUS_FVE_FAILED_WRONG_FS cpu_to_le32(0xC0210004)
+#define STATUS_FVE_FAILED_BAD_FS cpu_to_le32(0xC0210005)
+#define STATUS_FVE_FS_NOT_EXTENDED cpu_to_le32(0xC0210006)
+#define STATUS_FVE_FS_MOUNTED cpu_to_le32(0xC0210007)
+#define STATUS_FVE_NO_LICENSE cpu_to_le32(0xC0210008)
+#define STATUS_FVE_ACTION_NOT_ALLOWED cpu_to_le32(0xC0210009)
+#define STATUS_FVE_BAD_DATA cpu_to_le32(0xC021000A)
+#define STATUS_FVE_VOLUME_NOT_BOUND cpu_to_le32(0xC021000B)
+#define STATUS_FVE_NOT_DATA_VOLUME cpu_to_le32(0xC021000C)
+#define STATUS_FVE_CONV_READ_ERROR cpu_to_le32(0xC021000D)
+#define STATUS_FVE_CONV_WRITE_ERROR cpu_to_le32(0xC021000E)
+#define STATUS_FVE_OVERLAPPED_UPDATE cpu_to_le32(0xC021000F)
+#define STATUS_FVE_FAILED_SECTOR_SIZE cpu_to_le32(0xC0210010)
+#define STATUS_FVE_FAILED_AUTHENTICATION cpu_to_le32(0xC0210011)
+#define STATUS_FVE_NOT_OS_VOLUME cpu_to_le32(0xC0210012)
+#define STATUS_FVE_KEYFILE_NOT_FOUND cpu_to_le32(0xC0210013)
+#define STATUS_FVE_KEYFILE_INVALID cpu_to_le32(0xC0210014)
+#define STATUS_FVE_KEYFILE_NO_VMK cpu_to_le32(0xC0210015)
+#define STATUS_FVE_TPM_DISABLED cpu_to_le32(0xC0210016)
+#define STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO cpu_to_le32(0xC0210017)
+#define STATUS_FVE_TPM_INVALID_PCR cpu_to_le32(0xC0210018)
+#define STATUS_FVE_TPM_NO_VMK cpu_to_le32(0xC0210019)
+#define STATUS_FVE_PIN_INVALID cpu_to_le32(0xC021001A)
+#define STATUS_FVE_AUTH_INVALID_APPLICATION cpu_to_le32(0xC021001B)
+#define STATUS_FVE_AUTH_INVALID_CONFIG cpu_to_le32(0xC021001C)
+#define STATUS_FVE_DEBUGGER_ENABLED cpu_to_le32(0xC021001D)
+#define STATUS_FVE_DRY_RUN_FAILED cpu_to_le32(0xC021001E)
+#define STATUS_FVE_BAD_METADATA_POINTER cpu_to_le32(0xC021001F)
+#define STATUS_FVE_OLD_METADATA_COPY cpu_to_le32(0xC0210020)
+#define STATUS_FVE_REBOOT_REQUIRED cpu_to_le32(0xC0210021)
+#define STATUS_FVE_RAW_ACCESS cpu_to_le32(0xC0210022)
+#define STATUS_FVE_RAW_BLOCKED cpu_to_le32(0xC0210023)
+#define STATUS_FWP_CALLOUT_NOT_FOUND cpu_to_le32(0xC0220001)
+#define STATUS_FWP_CONDITION_NOT_FOUND cpu_to_le32(0xC0220002)
+#define STATUS_FWP_FILTER_NOT_FOUND cpu_to_le32(0xC0220003)
+#define STATUS_FWP_LAYER_NOT_FOUND cpu_to_le32(0xC0220004)
+#define STATUS_FWP_PROVIDER_NOT_FOUND cpu_to_le32(0xC0220005)
+#define STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND cpu_to_le32(0xC0220006)
+#define STATUS_FWP_SUBLAYER_NOT_FOUND cpu_to_le32(0xC0220007)
+#define STATUS_FWP_NOT_FOUND cpu_to_le32(0xC0220008)
+#define STATUS_FWP_ALREADY_EXISTS cpu_to_le32(0xC0220009)
+#define STATUS_FWP_IN_USE cpu_to_le32(0xC022000A)
+#define STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS cpu_to_le32(0xC022000B)
+#define STATUS_FWP_WRONG_SESSION cpu_to_le32(0xC022000C)
+#define STATUS_FWP_NO_TXN_IN_PROGRESS cpu_to_le32(0xC022000D)
+#define STATUS_FWP_TXN_IN_PROGRESS cpu_to_le32(0xC022000E)
+#define STATUS_FWP_TXN_ABORTED cpu_to_le32(0xC022000F)
+#define STATUS_FWP_SESSION_ABORTED cpu_to_le32(0xC0220010)
+#define STATUS_FWP_INCOMPATIBLE_TXN cpu_to_le32(0xC0220011)
+#define STATUS_FWP_TIMEOUT cpu_to_le32(0xC0220012)
+#define STATUS_FWP_NET_EVENTS_DISABLED cpu_to_le32(0xC0220013)
+#define STATUS_FWP_INCOMPATIBLE_LAYER cpu_to_le32(0xC0220014)
+#define STATUS_FWP_KM_CLIENTS_ONLY cpu_to_le32(0xC0220015)
+#define STATUS_FWP_LIFETIME_MISMATCH cpu_to_le32(0xC0220016)
+#define STATUS_FWP_BUILTIN_OBJECT cpu_to_le32(0xC0220017)
+#define STATUS_FWP_TOO_MANY_BOOTTIME_FILTERS cpu_to_le32(0xC0220018)
+#define STATUS_FWP_TOO_MANY_CALLOUTS cpu_to_le32(0xC0220018)
+#define STATUS_FWP_NOTIFICATION_DROPPED cpu_to_le32(0xC0220019)
+#define STATUS_FWP_TRAFFIC_MISMATCH cpu_to_le32(0xC022001A)
+#define STATUS_FWP_INCOMPATIBLE_SA_STATE cpu_to_le32(0xC022001B)
+#define STATUS_FWP_NULL_POINTER cpu_to_le32(0xC022001C)
+#define STATUS_FWP_INVALID_ENUMERATOR cpu_to_le32(0xC022001D)
+#define STATUS_FWP_INVALID_FLAGS cpu_to_le32(0xC022001E)
+#define STATUS_FWP_INVALID_NET_MASK cpu_to_le32(0xC022001F)
+#define STATUS_FWP_INVALID_RANGE cpu_to_le32(0xC0220020)
+#define STATUS_FWP_INVALID_INTERVAL cpu_to_le32(0xC0220021)
+#define STATUS_FWP_ZERO_LENGTH_ARRAY cpu_to_le32(0xC0220022)
+#define STATUS_FWP_NULL_DISPLAY_NAME cpu_to_le32(0xC0220023)
+#define STATUS_FWP_INVALID_ACTION_TYPE cpu_to_le32(0xC0220024)
+#define STATUS_FWP_INVALID_WEIGHT cpu_to_le32(0xC0220025)
+#define STATUS_FWP_MATCH_TYPE_MISMATCH cpu_to_le32(0xC0220026)
+#define STATUS_FWP_TYPE_MISMATCH cpu_to_le32(0xC0220027)
+#define STATUS_FWP_OUT_OF_BOUNDS cpu_to_le32(0xC0220028)
+#define STATUS_FWP_RESERVED cpu_to_le32(0xC0220029)
+#define STATUS_FWP_DUPLICATE_CONDITION cpu_to_le32(0xC022002A)
+#define STATUS_FWP_DUPLICATE_KEYMOD cpu_to_le32(0xC022002B)
+#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER cpu_to_le32(0xC022002C)
+#define STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER cpu_to_le32(0xC022002D)
+#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER cpu_to_le32(0xC022002E)
+#define STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT cpu_to_le32(0xC022002F)
+#define STATUS_FWP_INCOMPATIBLE_AUTH_METHOD cpu_to_le32(0xC0220030)
+#define STATUS_FWP_INCOMPATIBLE_DH_GROUP cpu_to_le32(0xC0220031)
+#define STATUS_FWP_EM_NOT_SUPPORTED cpu_to_le32(0xC0220032)
+#define STATUS_FWP_NEVER_MATCH cpu_to_le32(0xC0220033)
+#define STATUS_FWP_PROVIDER_CONTEXT_MISMATCH cpu_to_le32(0xC0220034)
+#define STATUS_FWP_INVALID_PARAMETER cpu_to_le32(0xC0220035)
+#define STATUS_FWP_TOO_MANY_SUBLAYERS cpu_to_le32(0xC0220036)
+#define STATUS_FWP_CALLOUT_NOTIFICATION_FAILED cpu_to_le32(0xC0220037)
+#define STATUS_FWP_INCOMPATIBLE_AUTH_CONFIG cpu_to_le32(0xC0220038)
+#define STATUS_FWP_INCOMPATIBLE_CIPHER_CONFIG cpu_to_le32(0xC0220039)
+#define STATUS_FWP_TCPIP_NOT_READY cpu_to_le32(0xC0220100)
+#define STATUS_FWP_INJECT_HANDLE_CLOSING cpu_to_le32(0xC0220101)
+#define STATUS_FWP_INJECT_HANDLE_STALE cpu_to_le32(0xC0220102)
+#define STATUS_FWP_CANNOT_PEND cpu_to_le32(0xC0220103)
+#define STATUS_NDIS_CLOSING cpu_to_le32(0xC0230002)
+#define STATUS_NDIS_BAD_VERSION cpu_to_le32(0xC0230004)
+#define STATUS_NDIS_BAD_CHARACTERISTICS cpu_to_le32(0xC0230005)
+#define STATUS_NDIS_ADAPTER_NOT_FOUND cpu_to_le32(0xC0230006)
+#define STATUS_NDIS_OPEN_FAILED cpu_to_le32(0xC0230007)
+#define STATUS_NDIS_DEVICE_FAILED cpu_to_le32(0xC0230008)
+#define STATUS_NDIS_MULTICAST_FULL cpu_to_le32(0xC0230009)
+#define STATUS_NDIS_MULTICAST_EXISTS cpu_to_le32(0xC023000A)
+#define STATUS_NDIS_MULTICAST_NOT_FOUND cpu_to_le32(0xC023000B)
+#define STATUS_NDIS_REQUEST_ABORTED cpu_to_le32(0xC023000C)
+#define STATUS_NDIS_RESET_IN_PROGRESS cpu_to_le32(0xC023000D)
+#define STATUS_NDIS_INVALID_PACKET cpu_to_le32(0xC023000F)
+#define STATUS_NDIS_INVALID_DEVICE_REQUEST cpu_to_le32(0xC0230010)
+#define STATUS_NDIS_ADAPTER_NOT_READY cpu_to_le32(0xC0230011)
+#define STATUS_NDIS_INVALID_LENGTH cpu_to_le32(0xC0230014)
+#define STATUS_NDIS_INVALID_DATA cpu_to_le32(0xC0230015)
+#define STATUS_NDIS_BUFFER_TOO_SHORT cpu_to_le32(0xC0230016)
+#define STATUS_NDIS_INVALID_OID cpu_to_le32(0xC0230017)
+#define STATUS_NDIS_ADAPTER_REMOVED cpu_to_le32(0xC0230018)
+#define STATUS_NDIS_UNSUPPORTED_MEDIA cpu_to_le32(0xC0230019)
+#define STATUS_NDIS_GROUP_ADDRESS_IN_USE cpu_to_le32(0xC023001A)
+#define STATUS_NDIS_FILE_NOT_FOUND cpu_to_le32(0xC023001B)
+#define STATUS_NDIS_ERROR_READING_FILE cpu_to_le32(0xC023001C)
+#define STATUS_NDIS_ALREADY_MAPPED cpu_to_le32(0xC023001D)
+#define STATUS_NDIS_RESOURCE_CONFLICT cpu_to_le32(0xC023001E)
+#define STATUS_NDIS_MEDIA_DISCONNECTED cpu_to_le32(0xC023001F)
+#define STATUS_NDIS_INVALID_ADDRESS cpu_to_le32(0xC0230022)
+#define STATUS_NDIS_PAUSED cpu_to_le32(0xC023002A)
+#define STATUS_NDIS_INTERFACE_NOT_FOUND cpu_to_le32(0xC023002B)
+#define STATUS_NDIS_UNSUPPORTED_REVISION cpu_to_le32(0xC023002C)
+#define STATUS_NDIS_INVALID_PORT cpu_to_le32(0xC023002D)
+#define STATUS_NDIS_INVALID_PORT_STATE cpu_to_le32(0xC023002E)
+#define STATUS_NDIS_LOW_POWER_STATE cpu_to_le32(0xC023002F)
+#define STATUS_NDIS_NOT_SUPPORTED cpu_to_le32(0xC02300BB)
+#define STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED cpu_to_le32(0xC0232000)
+#define STATUS_NDIS_DOT11_MEDIA_IN_USE cpu_to_le32(0xC0232001)
+#define STATUS_NDIS_DOT11_POWER_STATE_INVALID cpu_to_le32(0xC0232002)
+#define STATUS_IPSEC_BAD_SPI cpu_to_le32(0xC0360001)
+#define STATUS_IPSEC_SA_LIFETIME_EXPIRED cpu_to_le32(0xC0360002)
+#define STATUS_IPSEC_WRONG_SA cpu_to_le32(0xC0360003)
+#define STATUS_IPSEC_REPLAY_CHECK_FAILED cpu_to_le32(0xC0360004)
+#define STATUS_IPSEC_INVALID_PACKET cpu_to_le32(0xC0360005)
+#define STATUS_IPSEC_INTEGRITY_CHECK_FAILED cpu_to_le32(0xC0360006)
+#define STATUS_IPSEC_CLEAR_TEXT_DROP cpu_to_le32(0xC0360007)
+
+#define STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP cpu_to_le32(0xC05D0000)
+#define STATUS_INVALID_LOCK_RANGE cpu_to_le32(0xC00001a1)
diff --git a/fs/smb/server/transport_ipc.c b/fs/smb/server/transport_ipc.c
new file mode 100644
index 000000000000..40c721f9227e
--- /dev/null
+++ b/fs/smb/server/transport_ipc.c
@@ -0,0 +1,884 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/jhash.h>
+#include <linux/slab.h>
+#include <linux/rwsem.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/hashtable.h>
+#include <net/net_namespace.h>
+#include <net/genetlink.h>
+#include <linux/socket.h>
+#include <linux/workqueue.h>
+
+#include "vfs_cache.h"
+#include "transport_ipc.h"
+#include "server.h"
+#include "smb_common.h"
+
+#include "mgmt/user_config.h"
+#include "mgmt/share_config.h"
+#include "mgmt/user_session.h"
+#include "mgmt/tree_connect.h"
+#include "mgmt/ksmbd_ida.h"
+#include "connection.h"
+#include "transport_tcp.h"
+#include "transport_rdma.h"
+
+#define IPC_WAIT_TIMEOUT (2 * HZ)
+
+#define IPC_MSG_HASH_BITS 3
+static DEFINE_HASHTABLE(ipc_msg_table, IPC_MSG_HASH_BITS);
+static DECLARE_RWSEM(ipc_msg_table_lock);
+static DEFINE_MUTEX(startup_lock);
+
+static DEFINE_IDA(ipc_ida);
+
+static unsigned int ksmbd_tools_pid;
+
+static bool ksmbd_ipc_validate_version(struct genl_info *m)
+{
+ if (m->genlhdr->version != KSMBD_GENL_VERSION) {
+ pr_err("%s. ksmbd: %d, kernel module: %d. %s.\n",
+ "Daemon and kernel module version mismatch",
+ m->genlhdr->version,
+ KSMBD_GENL_VERSION,
+ "User-space ksmbd should terminate");
+ return false;
+ }
+ return true;
+}
+
+struct ksmbd_ipc_msg {
+ unsigned int type;
+ unsigned int sz;
+ unsigned char payload[];
+};
+
+struct ipc_msg_table_entry {
+ unsigned int handle;
+ unsigned int type;
+ wait_queue_head_t wait;
+ struct hlist_node ipc_table_hlist;
+
+ void *response;
+};
+
+static struct delayed_work ipc_timer_work;
+
+static int handle_startup_event(struct sk_buff *skb, struct genl_info *info);
+static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info);
+static int handle_generic_event(struct sk_buff *skb, struct genl_info *info);
+static int ksmbd_ipc_heartbeat_request(void);
+
+static const struct nla_policy ksmbd_nl_policy[KSMBD_EVENT_MAX] = {
+ [KSMBD_EVENT_UNSPEC] = {
+ .len = 0,
+ },
+ [KSMBD_EVENT_HEARTBEAT_REQUEST] = {
+ .len = sizeof(struct ksmbd_heartbeat),
+ },
+ [KSMBD_EVENT_STARTING_UP] = {
+ .len = sizeof(struct ksmbd_startup_request),
+ },
+ [KSMBD_EVENT_SHUTTING_DOWN] = {
+ .len = sizeof(struct ksmbd_shutdown_request),
+ },
+ [KSMBD_EVENT_LOGIN_REQUEST] = {
+ .len = sizeof(struct ksmbd_login_request),
+ },
+ [KSMBD_EVENT_LOGIN_RESPONSE] = {
+ .len = sizeof(struct ksmbd_login_response),
+ },
+ [KSMBD_EVENT_SHARE_CONFIG_REQUEST] = {
+ .len = sizeof(struct ksmbd_share_config_request),
+ },
+ [KSMBD_EVENT_SHARE_CONFIG_RESPONSE] = {
+ .len = sizeof(struct ksmbd_share_config_response),
+ },
+ [KSMBD_EVENT_TREE_CONNECT_REQUEST] = {
+ .len = sizeof(struct ksmbd_tree_connect_request),
+ },
+ [KSMBD_EVENT_TREE_CONNECT_RESPONSE] = {
+ .len = sizeof(struct ksmbd_tree_connect_response),
+ },
+ [KSMBD_EVENT_TREE_DISCONNECT_REQUEST] = {
+ .len = sizeof(struct ksmbd_tree_disconnect_request),
+ },
+ [KSMBD_EVENT_LOGOUT_REQUEST] = {
+ .len = sizeof(struct ksmbd_logout_request),
+ },
+ [KSMBD_EVENT_RPC_REQUEST] = {
+ },
+ [KSMBD_EVENT_RPC_RESPONSE] = {
+ },
+ [KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST] = {
+ },
+ [KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE] = {
+ },
+};
+
+static struct genl_ops ksmbd_genl_ops[] = {
+ {
+ .cmd = KSMBD_EVENT_UNSPEC,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_HEARTBEAT_REQUEST,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_STARTING_UP,
+ .doit = handle_startup_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_SHUTTING_DOWN,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_LOGIN_REQUEST,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_LOGIN_RESPONSE,
+ .doit = handle_generic_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_SHARE_CONFIG_REQUEST,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_SHARE_CONFIG_RESPONSE,
+ .doit = handle_generic_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_TREE_CONNECT_REQUEST,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_TREE_CONNECT_RESPONSE,
+ .doit = handle_generic_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_TREE_DISCONNECT_REQUEST,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_LOGOUT_REQUEST,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_RPC_REQUEST,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_RPC_RESPONSE,
+ .doit = handle_generic_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST,
+ .doit = handle_unsupported_event,
+ },
+ {
+ .cmd = KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE,
+ .doit = handle_generic_event,
+ },
+};
+
+static struct genl_family ksmbd_genl_family = {
+ .name = KSMBD_GENL_NAME,
+ .version = KSMBD_GENL_VERSION,
+ .hdrsize = 0,
+ .maxattr = KSMBD_EVENT_MAX,
+ .netnsok = true,
+ .module = THIS_MODULE,
+ .ops = ksmbd_genl_ops,
+ .n_ops = ARRAY_SIZE(ksmbd_genl_ops),
+ .resv_start_op = KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE + 1,
+};
+
+static void ksmbd_nl_init_fixup(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ksmbd_genl_ops); i++)
+ ksmbd_genl_ops[i].validate = GENL_DONT_VALIDATE_STRICT |
+ GENL_DONT_VALIDATE_DUMP;
+
+ ksmbd_genl_family.policy = ksmbd_nl_policy;
+}
+
+static int rpc_context_flags(struct ksmbd_session *sess)
+{
+ if (user_guest(sess->user))
+ return KSMBD_RPC_RESTRICTED_CONTEXT;
+ return 0;
+}
+
+static void ipc_update_last_active(void)
+{
+ if (server_conf.ipc_timeout)
+ server_conf.ipc_last_active = jiffies;
+}
+
+static struct ksmbd_ipc_msg *ipc_msg_alloc(size_t sz)
+{
+ struct ksmbd_ipc_msg *msg;
+ size_t msg_sz = sz + sizeof(struct ksmbd_ipc_msg);
+
+ msg = kvmalloc(msg_sz, GFP_KERNEL | __GFP_ZERO);
+ if (msg)
+ msg->sz = sz;
+ return msg;
+}
+
+static void ipc_msg_free(struct ksmbd_ipc_msg *msg)
+{
+ kvfree(msg);
+}
+
+static void ipc_msg_handle_free(int handle)
+{
+ if (handle >= 0)
+ ksmbd_release_id(&ipc_ida, handle);
+}
+
+static int handle_response(int type, void *payload, size_t sz)
+{
+ unsigned int handle = *(unsigned int *)payload;
+ struct ipc_msg_table_entry *entry;
+ int ret = 0;
+
+ ipc_update_last_active();
+ down_read(&ipc_msg_table_lock);
+ hash_for_each_possible(ipc_msg_table, entry, ipc_table_hlist, handle) {
+ if (handle != entry->handle)
+ continue;
+
+ entry->response = NULL;
+ /*
+ * Response message type value should be equal to
+ * request message type + 1.
+ */
+ if (entry->type + 1 != type) {
+ pr_err("Waiting for IPC type %d, got %d. Ignore.\n",
+ entry->type + 1, type);
+ }
+
+ entry->response = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
+ if (!entry->response) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ memcpy(entry->response, payload, sz);
+ wake_up_interruptible(&entry->wait);
+ ret = 0;
+ break;
+ }
+ up_read(&ipc_msg_table_lock);
+
+ return ret;
+}
+
+static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
+{
+ int ret;
+
+ ksmbd_set_fd_limit(req->file_max);
+ server_conf.flags = req->flags;
+ server_conf.signing = req->signing;
+ server_conf.tcp_port = req->tcp_port;
+ server_conf.ipc_timeout = req->ipc_timeout * HZ;
+ server_conf.deadtime = req->deadtime * SMB_ECHO_INTERVAL;
+ server_conf.share_fake_fscaps = req->share_fake_fscaps;
+ ksmbd_init_domain(req->sub_auth);
+
+ if (req->smb2_max_read)
+ init_smb2_max_read_size(req->smb2_max_read);
+ if (req->smb2_max_write)
+ init_smb2_max_write_size(req->smb2_max_write);
+ if (req->smb2_max_trans)
+ init_smb2_max_trans_size(req->smb2_max_trans);
+ if (req->smb2_max_credits)
+ init_smb2_max_credits(req->smb2_max_credits);
+ if (req->smbd_max_io_size)
+ init_smbd_max_io_size(req->smbd_max_io_size);
+
+ if (req->max_connections)
+ server_conf.max_connections = req->max_connections;
+
+ ret = ksmbd_set_netbios_name(req->netbios_name);
+ ret |= ksmbd_set_server_string(req->server_string);
+ ret |= ksmbd_set_work_group(req->work_group);
+ ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req),
+ req->ifc_list_sz);
+ if (ret) {
+ pr_err("Server configuration error: %s %s %s\n",
+ req->netbios_name, req->server_string,
+ req->work_group);
+ return ret;
+ }
+
+ if (req->min_prot[0]) {
+ ret = ksmbd_lookup_protocol_idx(req->min_prot);
+ if (ret >= 0)
+ server_conf.min_protocol = ret;
+ }
+ if (req->max_prot[0]) {
+ ret = ksmbd_lookup_protocol_idx(req->max_prot);
+ if (ret >= 0)
+ server_conf.max_protocol = ret;
+ }
+
+ if (server_conf.ipc_timeout)
+ schedule_delayed_work(&ipc_timer_work, server_conf.ipc_timeout);
+ return 0;
+}
+
+static int handle_startup_event(struct sk_buff *skb, struct genl_info *info)
+{
+ int ret = 0;
+
+#ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
+ if (!netlink_capable(skb, CAP_NET_ADMIN))
+ return -EPERM;
+#endif
+
+ if (!ksmbd_ipc_validate_version(info))
+ return -EINVAL;
+
+ if (!info->attrs[KSMBD_EVENT_STARTING_UP])
+ return -EINVAL;
+
+ mutex_lock(&startup_lock);
+ if (!ksmbd_server_configurable()) {
+ mutex_unlock(&startup_lock);
+ pr_err("Server reset is in progress, can't start daemon\n");
+ return -EINVAL;
+ }
+
+ if (ksmbd_tools_pid) {
+ if (ksmbd_ipc_heartbeat_request() == 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pr_err("Reconnect to a new user space daemon\n");
+ } else {
+ struct ksmbd_startup_request *req;
+
+ req = nla_data(info->attrs[info->genlhdr->cmd]);
+ ret = ipc_server_config_on_startup(req);
+ if (ret)
+ goto out;
+ server_queue_ctrl_init_work();
+ }
+
+ ksmbd_tools_pid = info->snd_portid;
+ ipc_update_last_active();
+
+out:
+ mutex_unlock(&startup_lock);
+ return ret;
+}
+
+static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info)
+{
+ pr_err("Unknown IPC event: %d, ignore.\n", info->genlhdr->cmd);
+ return -EINVAL;
+}
+
+static int handle_generic_event(struct sk_buff *skb, struct genl_info *info)
+{
+ void *payload;
+ int sz;
+ int type = info->genlhdr->cmd;
+
+#ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
+ if (!netlink_capable(skb, CAP_NET_ADMIN))
+ return -EPERM;
+#endif
+
+ if (type >= KSMBD_EVENT_MAX) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ if (!ksmbd_ipc_validate_version(info))
+ return -EINVAL;
+
+ if (!info->attrs[type])
+ return -EINVAL;
+
+ payload = nla_data(info->attrs[info->genlhdr->cmd]);
+ sz = nla_len(info->attrs[info->genlhdr->cmd]);
+ return handle_response(type, payload, sz);
+}
+
+static int ipc_msg_send(struct ksmbd_ipc_msg *msg)
+{
+ struct genlmsghdr *nlh;
+ struct sk_buff *skb;
+ int ret = -EINVAL;
+
+ if (!ksmbd_tools_pid)
+ return ret;
+
+ skb = genlmsg_new(msg->sz, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ nlh = genlmsg_put(skb, 0, 0, &ksmbd_genl_family, 0, msg->type);
+ if (!nlh)
+ goto out;
+
+ ret = nla_put(skb, msg->type, msg->sz, msg->payload);
+ if (ret) {
+ genlmsg_cancel(skb, nlh);
+ goto out;
+ }
+
+ genlmsg_end(skb, nlh);
+ ret = genlmsg_unicast(&init_net, skb, ksmbd_tools_pid);
+ if (!ret)
+ ipc_update_last_active();
+ return ret;
+
+out:
+ nlmsg_free(skb);
+ return ret;
+}
+
+static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle)
+{
+ struct ipc_msg_table_entry entry;
+ int ret;
+
+ if ((int)handle < 0)
+ return NULL;
+
+ entry.type = msg->type;
+ entry.response = NULL;
+ init_waitqueue_head(&entry.wait);
+
+ down_write(&ipc_msg_table_lock);
+ entry.handle = handle;
+ hash_add(ipc_msg_table, &entry.ipc_table_hlist, entry.handle);
+ up_write(&ipc_msg_table_lock);
+
+ ret = ipc_msg_send(msg);
+ if (ret)
+ goto out;
+
+ ret = wait_event_interruptible_timeout(entry.wait,
+ entry.response != NULL,
+ IPC_WAIT_TIMEOUT);
+out:
+ down_write(&ipc_msg_table_lock);
+ hash_del(&entry.ipc_table_hlist);
+ up_write(&ipc_msg_table_lock);
+ return entry.response;
+}
+
+static int ksmbd_ipc_heartbeat_request(void)
+{
+ struct ksmbd_ipc_msg *msg;
+ int ret;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_heartbeat));
+ if (!msg)
+ return -EINVAL;
+
+ msg->type = KSMBD_EVENT_HEARTBEAT_REQUEST;
+ ret = ipc_msg_send(msg);
+ ipc_msg_free(msg);
+ return ret;
+}
+
+struct ksmbd_login_response *ksmbd_ipc_login_request(const char *account)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_login_request *req;
+ struct ksmbd_login_response *resp;
+
+ if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
+ return NULL;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_login_request));
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_LOGIN_REQUEST;
+ req = (struct ksmbd_login_request *)msg->payload;
+ req->handle = ksmbd_acquire_id(&ipc_ida);
+ strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_handle_free(req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+struct ksmbd_spnego_authen_response *
+ksmbd_ipc_spnego_authen_request(const char *spnego_blob, int blob_len)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_spnego_authen_request *req;
+ struct ksmbd_spnego_authen_response *resp;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_spnego_authen_request) +
+ blob_len + 1);
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST;
+ req = (struct ksmbd_spnego_authen_request *)msg->payload;
+ req->handle = ksmbd_acquire_id(&ipc_ida);
+ req->spnego_blob_len = blob_len;
+ memcpy(req->spnego_blob, spnego_blob, blob_len);
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_handle_free(req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+struct ksmbd_tree_connect_response *
+ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess,
+ struct ksmbd_share_config *share,
+ struct ksmbd_tree_connect *tree_conn,
+ struct sockaddr *peer_addr)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_tree_connect_request *req;
+ struct ksmbd_tree_connect_response *resp;
+
+ if (strlen(user_name(sess->user)) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
+ return NULL;
+
+ if (strlen(share->name) >= KSMBD_REQ_MAX_SHARE_NAME)
+ return NULL;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_connect_request));
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_TREE_CONNECT_REQUEST;
+ req = (struct ksmbd_tree_connect_request *)msg->payload;
+
+ req->handle = ksmbd_acquire_id(&ipc_ida);
+ req->account_flags = sess->user->flags;
+ req->session_id = sess->id;
+ req->connect_id = tree_conn->id;
+ strscpy(req->account, user_name(sess->user), KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
+ strscpy(req->share, share->name, KSMBD_REQ_MAX_SHARE_NAME);
+ snprintf(req->peer_addr, sizeof(req->peer_addr), "%pIS", peer_addr);
+
+ if (peer_addr->sa_family == AF_INET6)
+ req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_IPV6;
+ if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
+ req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_SMB2;
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_handle_free(req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
+ unsigned long long connect_id)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_tree_disconnect_request *req;
+ int ret;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_disconnect_request));
+ if (!msg)
+ return -ENOMEM;
+
+ msg->type = KSMBD_EVENT_TREE_DISCONNECT_REQUEST;
+ req = (struct ksmbd_tree_disconnect_request *)msg->payload;
+ req->session_id = session_id;
+ req->connect_id = connect_id;
+
+ ret = ipc_msg_send(msg);
+ ipc_msg_free(msg);
+ return ret;
+}
+
+int ksmbd_ipc_logout_request(const char *account, int flags)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_logout_request *req;
+ int ret;
+
+ if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
+ return -EINVAL;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_logout_request));
+ if (!msg)
+ return -ENOMEM;
+
+ msg->type = KSMBD_EVENT_LOGOUT_REQUEST;
+ req = (struct ksmbd_logout_request *)msg->payload;
+ req->account_flags = flags;
+ strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
+
+ ret = ipc_msg_send(msg);
+ ipc_msg_free(msg);
+ return ret;
+}
+
+struct ksmbd_share_config_response *
+ksmbd_ipc_share_config_request(const char *name)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_share_config_request *req;
+ struct ksmbd_share_config_response *resp;
+
+ if (strlen(name) >= KSMBD_REQ_MAX_SHARE_NAME)
+ return NULL;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_share_config_request));
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_SHARE_CONFIG_REQUEST;
+ req = (struct ksmbd_share_config_request *)msg->payload;
+ req->handle = ksmbd_acquire_id(&ipc_ida);
+ strscpy(req->share_name, name, KSMBD_REQ_MAX_SHARE_NAME);
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_handle_free(req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+struct ksmbd_rpc_command *ksmbd_rpc_open(struct ksmbd_session *sess, int handle)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_rpc_command *req;
+ struct ksmbd_rpc_command *resp;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_RPC_REQUEST;
+ req = (struct ksmbd_rpc_command *)msg->payload;
+ req->handle = handle;
+ req->flags = ksmbd_session_rpc_method(sess, handle);
+ req->flags |= KSMBD_RPC_OPEN_METHOD;
+ req->payload_sz = 0;
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+struct ksmbd_rpc_command *ksmbd_rpc_close(struct ksmbd_session *sess, int handle)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_rpc_command *req;
+ struct ksmbd_rpc_command *resp;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_RPC_REQUEST;
+ req = (struct ksmbd_rpc_command *)msg->payload;
+ req->handle = handle;
+ req->flags = ksmbd_session_rpc_method(sess, handle);
+ req->flags |= KSMBD_RPC_CLOSE_METHOD;
+ req->payload_sz = 0;
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle,
+ void *payload, size_t payload_sz)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_rpc_command *req;
+ struct ksmbd_rpc_command *resp;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_RPC_REQUEST;
+ req = (struct ksmbd_rpc_command *)msg->payload;
+ req->handle = handle;
+ req->flags = ksmbd_session_rpc_method(sess, handle);
+ req->flags |= rpc_context_flags(sess);
+ req->flags |= KSMBD_RPC_WRITE_METHOD;
+ req->payload_sz = payload_sz;
+ memcpy(req->payload, payload, payload_sz);
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_rpc_command *req;
+ struct ksmbd_rpc_command *resp;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_RPC_REQUEST;
+ req = (struct ksmbd_rpc_command *)msg->payload;
+ req->handle = handle;
+ req->flags = ksmbd_session_rpc_method(sess, handle);
+ req->flags |= rpc_context_flags(sess);
+ req->flags |= KSMBD_RPC_READ_METHOD;
+ req->payload_sz = 0;
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle,
+ void *payload, size_t payload_sz)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_rpc_command *req;
+ struct ksmbd_rpc_command *resp;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_RPC_REQUEST;
+ req = (struct ksmbd_rpc_command *)msg->payload;
+ req->handle = handle;
+ req->flags = ksmbd_session_rpc_method(sess, handle);
+ req->flags |= rpc_context_flags(sess);
+ req->flags |= KSMBD_RPC_IOCTL_METHOD;
+ req->payload_sz = payload_sz;
+ memcpy(req->payload, payload, payload_sz);
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+struct ksmbd_rpc_command *ksmbd_rpc_rap(struct ksmbd_session *sess, void *payload,
+ size_t payload_sz)
+{
+ struct ksmbd_ipc_msg *msg;
+ struct ksmbd_rpc_command *req;
+ struct ksmbd_rpc_command *resp;
+
+ msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
+ if (!msg)
+ return NULL;
+
+ msg->type = KSMBD_EVENT_RPC_REQUEST;
+ req = (struct ksmbd_rpc_command *)msg->payload;
+ req->handle = ksmbd_acquire_id(&ipc_ida);
+ req->flags = rpc_context_flags(sess);
+ req->flags |= KSMBD_RPC_RAP_METHOD;
+ req->payload_sz = payload_sz;
+ memcpy(req->payload, payload, payload_sz);
+
+ resp = ipc_msg_send_request(msg, req->handle);
+ ipc_msg_handle_free(req->handle);
+ ipc_msg_free(msg);
+ return resp;
+}
+
+static int __ipc_heartbeat(void)
+{
+ unsigned long delta;
+
+ if (!ksmbd_server_running())
+ return 0;
+
+ if (time_after(jiffies, server_conf.ipc_last_active)) {
+ delta = (jiffies - server_conf.ipc_last_active);
+ } else {
+ ipc_update_last_active();
+ schedule_delayed_work(&ipc_timer_work,
+ server_conf.ipc_timeout);
+ return 0;
+ }
+
+ if (delta < server_conf.ipc_timeout) {
+ schedule_delayed_work(&ipc_timer_work,
+ server_conf.ipc_timeout - delta);
+ return 0;
+ }
+
+ if (ksmbd_ipc_heartbeat_request() == 0) {
+ schedule_delayed_work(&ipc_timer_work,
+ server_conf.ipc_timeout);
+ return 0;
+ }
+
+ mutex_lock(&startup_lock);
+ WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
+ server_conf.ipc_last_active = 0;
+ ksmbd_tools_pid = 0;
+ pr_err("No IPC daemon response for %lus\n", delta / HZ);
+ mutex_unlock(&startup_lock);
+ return -EINVAL;
+}
+
+static void ipc_timer_heartbeat(struct work_struct *w)
+{
+ if (__ipc_heartbeat())
+ server_queue_ctrl_reset_work();
+}
+
+int ksmbd_ipc_id_alloc(void)
+{
+ return ksmbd_acquire_id(&ipc_ida);
+}
+
+void ksmbd_rpc_id_free(int handle)
+{
+ ksmbd_release_id(&ipc_ida, handle);
+}
+
+void ksmbd_ipc_release(void)
+{
+ cancel_delayed_work_sync(&ipc_timer_work);
+ genl_unregister_family(&ksmbd_genl_family);
+}
+
+void ksmbd_ipc_soft_reset(void)
+{
+ mutex_lock(&startup_lock);
+ ksmbd_tools_pid = 0;
+ cancel_delayed_work_sync(&ipc_timer_work);
+ mutex_unlock(&startup_lock);
+}
+
+int ksmbd_ipc_init(void)
+{
+ int ret = 0;
+
+ ksmbd_nl_init_fixup();
+ INIT_DELAYED_WORK(&ipc_timer_work, ipc_timer_heartbeat);
+
+ ret = genl_register_family(&ksmbd_genl_family);
+ if (ret) {
+ pr_err("Failed to register KSMBD netlink interface %d\n", ret);
+ cancel_delayed_work_sync(&ipc_timer_work);
+ }
+
+ return ret;
+}
diff --git a/fs/smb/server/transport_ipc.h b/fs/smb/server/transport_ipc.h
new file mode 100644
index 000000000000..5e5b90a0c187
--- /dev/null
+++ b/fs/smb/server/transport_ipc.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __KSMBD_TRANSPORT_IPC_H__
+#define __KSMBD_TRANSPORT_IPC_H__
+
+#include <linux/wait.h>
+
+#define KSMBD_IPC_MAX_PAYLOAD 4096
+
+struct ksmbd_login_response *
+ksmbd_ipc_login_request(const char *account);
+
+struct ksmbd_session;
+struct ksmbd_share_config;
+struct ksmbd_tree_connect;
+struct sockaddr;
+
+struct ksmbd_tree_connect_response *
+ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess,
+ struct ksmbd_share_config *share,
+ struct ksmbd_tree_connect *tree_conn,
+ struct sockaddr *peer_addr);
+int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
+ unsigned long long connect_id);
+int ksmbd_ipc_logout_request(const char *account, int flags);
+struct ksmbd_share_config_response *
+ksmbd_ipc_share_config_request(const char *name);
+struct ksmbd_spnego_authen_response *
+ksmbd_ipc_spnego_authen_request(const char *spnego_blob, int blob_len);
+int ksmbd_ipc_id_alloc(void);
+void ksmbd_rpc_id_free(int handle);
+struct ksmbd_rpc_command *ksmbd_rpc_open(struct ksmbd_session *sess, int handle);
+struct ksmbd_rpc_command *ksmbd_rpc_close(struct ksmbd_session *sess, int handle);
+struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle,
+ void *payload, size_t payload_sz);
+struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle);
+struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle,
+ void *payload, size_t payload_sz);
+struct ksmbd_rpc_command *ksmbd_rpc_rap(struct ksmbd_session *sess, void *payload,
+ size_t payload_sz);
+void ksmbd_ipc_release(void);
+void ksmbd_ipc_soft_reset(void);
+int ksmbd_ipc_init(void);
+#endif /* __KSMBD_TRANSPORT_IPC_H__ */
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
new file mode 100644
index 000000000000..c06efc020bd9
--- /dev/null
+++ b/fs/smb/server/transport_rdma.c
@@ -0,0 +1,2273 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017, Microsoft Corporation.
+ * Copyright (C) 2018, LG Electronics.
+ *
+ * Author(s): Long Li <longli@microsoft.com>,
+ * Hyunchul Lee <hyc.lee@gmail.com>
+ */
+
+#define SUBMOD_NAME "smb_direct"
+
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/mempool.h>
+#include <linux/highmem.h>
+#include <linux/scatterlist.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/rdma_cm.h>
+#include <rdma/rw.h>
+
+#include "glob.h"
+#include "connection.h"
+#include "smb_common.h"
+#include "smbstatus.h"
+#include "transport_rdma.h"
+
+#define SMB_DIRECT_PORT_IWARP 5445
+#define SMB_DIRECT_PORT_INFINIBAND 445
+
+#define SMB_DIRECT_VERSION_LE cpu_to_le16(0x0100)
+
+/* SMB_DIRECT negotiation timeout in seconds */
+#define SMB_DIRECT_NEGOTIATE_TIMEOUT 120
+
+#define SMB_DIRECT_MAX_SEND_SGES 6
+#define SMB_DIRECT_MAX_RECV_SGES 1
+
+/*
+ * Default maximum number of RDMA read/write outstanding on this connection
+ * This value is possibly decreased during QP creation on hardware limit
+ */
+#define SMB_DIRECT_CM_INITIATOR_DEPTH 8
+
+/* Maximum number of retries on data transfer operations */
+#define SMB_DIRECT_CM_RETRY 6
+/* No need to retry on Receiver Not Ready since SMB_DIRECT manages credits */
+#define SMB_DIRECT_CM_RNR_RETRY 0
+
+/*
+ * User configurable initial values per SMB_DIRECT transport connection
+ * as defined in [MS-SMBD] 3.1.1.1
+ * Those may change after a SMB_DIRECT negotiation
+ */
+
+/* Set 445 port to SMB Direct port by default */
+static int smb_direct_port = SMB_DIRECT_PORT_INFINIBAND;
+
+/* The local peer's maximum number of credits to grant to the peer */
+static int smb_direct_receive_credit_max = 255;
+
+/* The remote peer's credit request of local peer */
+static int smb_direct_send_credit_target = 255;
+
+/* The maximum single message size can be sent to remote peer */
+static int smb_direct_max_send_size = 1364;
+
+/* The maximum fragmented upper-layer payload receive size supported */
+static int smb_direct_max_fragmented_recv_size = 1024 * 1024;
+
+/* The maximum single-message size which can be received */
+static int smb_direct_max_receive_size = 1364;
+
+static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE;
+
+static LIST_HEAD(smb_direct_device_list);
+static DEFINE_RWLOCK(smb_direct_device_lock);
+
+struct smb_direct_device {
+ struct ib_device *ib_dev;
+ struct list_head list;
+};
+
+static struct smb_direct_listener {
+ struct rdma_cm_id *cm_id;
+} smb_direct_listener;
+
+static struct workqueue_struct *smb_direct_wq;
+
+enum smb_direct_status {
+ SMB_DIRECT_CS_NEW = 0,
+ SMB_DIRECT_CS_CONNECTED,
+ SMB_DIRECT_CS_DISCONNECTING,
+ SMB_DIRECT_CS_DISCONNECTED,
+};
+
+struct smb_direct_transport {
+ struct ksmbd_transport transport;
+
+ enum smb_direct_status status;
+ bool full_packet_received;
+ wait_queue_head_t wait_status;
+
+ struct rdma_cm_id *cm_id;
+ struct ib_cq *send_cq;
+ struct ib_cq *recv_cq;
+ struct ib_pd *pd;
+ struct ib_qp *qp;
+
+ int max_send_size;
+ int max_recv_size;
+ int max_fragmented_send_size;
+ int max_fragmented_recv_size;
+ int max_rdma_rw_size;
+
+ spinlock_t reassembly_queue_lock;
+ struct list_head reassembly_queue;
+ int reassembly_data_length;
+ int reassembly_queue_length;
+ int first_entry_offset;
+ wait_queue_head_t wait_reassembly_queue;
+
+ spinlock_t receive_credit_lock;
+ int recv_credits;
+ int count_avail_recvmsg;
+ int recv_credit_max;
+ int recv_credit_target;
+
+ spinlock_t recvmsg_queue_lock;
+ struct list_head recvmsg_queue;
+
+ spinlock_t empty_recvmsg_queue_lock;
+ struct list_head empty_recvmsg_queue;
+
+ int send_credit_target;
+ atomic_t send_credits;
+ spinlock_t lock_new_recv_credits;
+ int new_recv_credits;
+ int max_rw_credits;
+ int pages_per_rw_credit;
+ atomic_t rw_credits;
+
+ wait_queue_head_t wait_send_credits;
+ wait_queue_head_t wait_rw_credits;
+
+ mempool_t *sendmsg_mempool;
+ struct kmem_cache *sendmsg_cache;
+ mempool_t *recvmsg_mempool;
+ struct kmem_cache *recvmsg_cache;
+
+ wait_queue_head_t wait_send_pending;
+ atomic_t send_pending;
+
+ struct delayed_work post_recv_credits_work;
+ struct work_struct send_immediate_work;
+ struct work_struct disconnect_work;
+
+ bool negotiation_requested;
+};
+
+#define KSMBD_TRANS(t) ((struct ksmbd_transport *)&((t)->transport))
+
+enum {
+ SMB_DIRECT_MSG_NEGOTIATE_REQ = 0,
+ SMB_DIRECT_MSG_DATA_TRANSFER
+};
+
+static struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops;
+
+struct smb_direct_send_ctx {
+ struct list_head msg_list;
+ int wr_cnt;
+ bool need_invalidate_rkey;
+ unsigned int remote_key;
+};
+
+struct smb_direct_sendmsg {
+ struct smb_direct_transport *transport;
+ struct ib_send_wr wr;
+ struct list_head list;
+ int num_sge;
+ struct ib_sge sge[SMB_DIRECT_MAX_SEND_SGES];
+ struct ib_cqe cqe;
+ u8 packet[];
+};
+
+struct smb_direct_recvmsg {
+ struct smb_direct_transport *transport;
+ struct list_head list;
+ int type;
+ struct ib_sge sge;
+ struct ib_cqe cqe;
+ bool first_segment;
+ u8 packet[];
+};
+
+struct smb_direct_rdma_rw_msg {
+ struct smb_direct_transport *t;
+ struct ib_cqe cqe;
+ int status;
+ struct completion *completion;
+ struct list_head list;
+ struct rdma_rw_ctx rw_ctx;
+ struct sg_table sgt;
+ struct scatterlist sg_list[];
+};
+
+void init_smbd_max_io_size(unsigned int sz)
+{
+ sz = clamp_val(sz, SMBD_MIN_IOSIZE, SMBD_MAX_IOSIZE);
+ smb_direct_max_read_write_size = sz;
+}
+
+unsigned int get_smbd_max_read_write_size(void)
+{
+ return smb_direct_max_read_write_size;
+}
+
+static inline int get_buf_page_count(void *buf, int size)
+{
+ return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
+ (uintptr_t)buf / PAGE_SIZE;
+}
+
+static void smb_direct_destroy_pools(struct smb_direct_transport *transport);
+static void smb_direct_post_recv_credits(struct work_struct *work);
+static int smb_direct_post_send_data(struct smb_direct_transport *t,
+ struct smb_direct_send_ctx *send_ctx,
+ struct kvec *iov, int niov,
+ int remaining_data_length);
+
+static inline struct smb_direct_transport *
+smb_trans_direct_transfort(struct ksmbd_transport *t)
+{
+ return container_of(t, struct smb_direct_transport, transport);
+}
+
+static inline void
+*smb_direct_recvmsg_payload(struct smb_direct_recvmsg *recvmsg)
+{
+ return (void *)recvmsg->packet;
+}
+
+static inline bool is_receive_credit_post_required(int receive_credits,
+ int avail_recvmsg_count)
+{
+ return receive_credits <= (smb_direct_receive_credit_max >> 3) &&
+ avail_recvmsg_count >= (receive_credits >> 2);
+}
+
+static struct
+smb_direct_recvmsg *get_free_recvmsg(struct smb_direct_transport *t)
+{
+ struct smb_direct_recvmsg *recvmsg = NULL;
+
+ spin_lock(&t->recvmsg_queue_lock);
+ if (!list_empty(&t->recvmsg_queue)) {
+ recvmsg = list_first_entry(&t->recvmsg_queue,
+ struct smb_direct_recvmsg,
+ list);
+ list_del(&recvmsg->list);
+ }
+ spin_unlock(&t->recvmsg_queue_lock);
+ return recvmsg;
+}
+
+static void put_recvmsg(struct smb_direct_transport *t,
+ struct smb_direct_recvmsg *recvmsg)
+{
+ ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr,
+ recvmsg->sge.length, DMA_FROM_DEVICE);
+
+ spin_lock(&t->recvmsg_queue_lock);
+ list_add(&recvmsg->list, &t->recvmsg_queue);
+ spin_unlock(&t->recvmsg_queue_lock);
+}
+
+static struct
+smb_direct_recvmsg *get_empty_recvmsg(struct smb_direct_transport *t)
+{
+ struct smb_direct_recvmsg *recvmsg = NULL;
+
+ spin_lock(&t->empty_recvmsg_queue_lock);
+ if (!list_empty(&t->empty_recvmsg_queue)) {
+ recvmsg = list_first_entry(&t->empty_recvmsg_queue,
+ struct smb_direct_recvmsg, list);
+ list_del(&recvmsg->list);
+ }
+ spin_unlock(&t->empty_recvmsg_queue_lock);
+ return recvmsg;
+}
+
+static void put_empty_recvmsg(struct smb_direct_transport *t,
+ struct smb_direct_recvmsg *recvmsg)
+{
+ ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr,
+ recvmsg->sge.length, DMA_FROM_DEVICE);
+
+ spin_lock(&t->empty_recvmsg_queue_lock);
+ list_add_tail(&recvmsg->list, &t->empty_recvmsg_queue);
+ spin_unlock(&t->empty_recvmsg_queue_lock);
+}
+
+static void enqueue_reassembly(struct smb_direct_transport *t,
+ struct smb_direct_recvmsg *recvmsg,
+ int data_length)
+{
+ spin_lock(&t->reassembly_queue_lock);
+ list_add_tail(&recvmsg->list, &t->reassembly_queue);
+ t->reassembly_queue_length++;
+ /*
+ * Make sure reassembly_data_length is updated after list and
+ * reassembly_queue_length are updated. On the dequeue side
+ * reassembly_data_length is checked without a lock to determine
+ * if reassembly_queue_length and list is up to date
+ */
+ virt_wmb();
+ t->reassembly_data_length += data_length;
+ spin_unlock(&t->reassembly_queue_lock);
+}
+
+static struct smb_direct_recvmsg *get_first_reassembly(struct smb_direct_transport *t)
+{
+ if (!list_empty(&t->reassembly_queue))
+ return list_first_entry(&t->reassembly_queue,
+ struct smb_direct_recvmsg, list);
+ else
+ return NULL;
+}
+
+static void smb_direct_disconnect_rdma_work(struct work_struct *work)
+{
+ struct smb_direct_transport *t =
+ container_of(work, struct smb_direct_transport,
+ disconnect_work);
+
+ if (t->status == SMB_DIRECT_CS_CONNECTED) {
+ t->status = SMB_DIRECT_CS_DISCONNECTING;
+ rdma_disconnect(t->cm_id);
+ }
+}
+
+static void
+smb_direct_disconnect_rdma_connection(struct smb_direct_transport *t)
+{
+ if (t->status == SMB_DIRECT_CS_CONNECTED)
+ queue_work(smb_direct_wq, &t->disconnect_work);
+}
+
+static void smb_direct_send_immediate_work(struct work_struct *work)
+{
+ struct smb_direct_transport *t = container_of(work,
+ struct smb_direct_transport, send_immediate_work);
+
+ if (t->status != SMB_DIRECT_CS_CONNECTED)
+ return;
+
+ smb_direct_post_send_data(t, NULL, NULL, 0, 0);
+}
+
+static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
+{
+ struct smb_direct_transport *t;
+ struct ksmbd_conn *conn;
+
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
+ if (!t)
+ return NULL;
+
+ t->cm_id = cm_id;
+ cm_id->context = t;
+
+ t->status = SMB_DIRECT_CS_NEW;
+ init_waitqueue_head(&t->wait_status);
+
+ spin_lock_init(&t->reassembly_queue_lock);
+ INIT_LIST_HEAD(&t->reassembly_queue);
+ t->reassembly_data_length = 0;
+ t->reassembly_queue_length = 0;
+ init_waitqueue_head(&t->wait_reassembly_queue);
+ init_waitqueue_head(&t->wait_send_credits);
+ init_waitqueue_head(&t->wait_rw_credits);
+
+ spin_lock_init(&t->receive_credit_lock);
+ spin_lock_init(&t->recvmsg_queue_lock);
+ INIT_LIST_HEAD(&t->recvmsg_queue);
+
+ spin_lock_init(&t->empty_recvmsg_queue_lock);
+ INIT_LIST_HEAD(&t->empty_recvmsg_queue);
+
+ init_waitqueue_head(&t->wait_send_pending);
+ atomic_set(&t->send_pending, 0);
+
+ spin_lock_init(&t->lock_new_recv_credits);
+
+ INIT_DELAYED_WORK(&t->post_recv_credits_work,
+ smb_direct_post_recv_credits);
+ INIT_WORK(&t->send_immediate_work, smb_direct_send_immediate_work);
+ INIT_WORK(&t->disconnect_work, smb_direct_disconnect_rdma_work);
+
+ conn = ksmbd_conn_alloc();
+ if (!conn)
+ goto err;
+ conn->transport = KSMBD_TRANS(t);
+ KSMBD_TRANS(t)->conn = conn;
+ KSMBD_TRANS(t)->ops = &ksmbd_smb_direct_transport_ops;
+ return t;
+err:
+ kfree(t);
+ return NULL;
+}
+
+static void free_transport(struct smb_direct_transport *t)
+{
+ struct smb_direct_recvmsg *recvmsg;
+
+ wake_up_interruptible(&t->wait_send_credits);
+
+ ksmbd_debug(RDMA, "wait for all send posted to IB to finish\n");
+ wait_event(t->wait_send_pending,
+ atomic_read(&t->send_pending) == 0);
+
+ cancel_work_sync(&t->disconnect_work);
+ cancel_delayed_work_sync(&t->post_recv_credits_work);
+ cancel_work_sync(&t->send_immediate_work);
+
+ if (t->qp) {
+ ib_drain_qp(t->qp);
+ ib_mr_pool_destroy(t->qp, &t->qp->rdma_mrs);
+ ib_destroy_qp(t->qp);
+ }
+
+ ksmbd_debug(RDMA, "drain the reassembly queue\n");
+ do {
+ spin_lock(&t->reassembly_queue_lock);
+ recvmsg = get_first_reassembly(t);
+ if (recvmsg) {
+ list_del(&recvmsg->list);
+ spin_unlock(&t->reassembly_queue_lock);
+ put_recvmsg(t, recvmsg);
+ } else {
+ spin_unlock(&t->reassembly_queue_lock);
+ }
+ } while (recvmsg);
+ t->reassembly_data_length = 0;
+
+ if (t->send_cq)
+ ib_free_cq(t->send_cq);
+ if (t->recv_cq)
+ ib_free_cq(t->recv_cq);
+ if (t->pd)
+ ib_dealloc_pd(t->pd);
+ if (t->cm_id)
+ rdma_destroy_id(t->cm_id);
+
+ smb_direct_destroy_pools(t);
+ ksmbd_conn_free(KSMBD_TRANS(t)->conn);
+ kfree(t);
+}
+
+static struct smb_direct_sendmsg
+*smb_direct_alloc_sendmsg(struct smb_direct_transport *t)
+{
+ struct smb_direct_sendmsg *msg;
+
+ msg = mempool_alloc(t->sendmsg_mempool, GFP_KERNEL);
+ if (!msg)
+ return ERR_PTR(-ENOMEM);
+ msg->transport = t;
+ INIT_LIST_HEAD(&msg->list);
+ msg->num_sge = 0;
+ return msg;
+}
+
+static void smb_direct_free_sendmsg(struct smb_direct_transport *t,
+ struct smb_direct_sendmsg *msg)
+{
+ int i;
+
+ if (msg->num_sge > 0) {
+ ib_dma_unmap_single(t->cm_id->device,
+ msg->sge[0].addr, msg->sge[0].length,
+ DMA_TO_DEVICE);
+ for (i = 1; i < msg->num_sge; i++)
+ ib_dma_unmap_page(t->cm_id->device,
+ msg->sge[i].addr, msg->sge[i].length,
+ DMA_TO_DEVICE);
+ }
+ mempool_free(msg, t->sendmsg_mempool);
+}
+
+static int smb_direct_check_recvmsg(struct smb_direct_recvmsg *recvmsg)
+{
+ switch (recvmsg->type) {
+ case SMB_DIRECT_MSG_DATA_TRANSFER: {
+ struct smb_direct_data_transfer *req =
+ (struct smb_direct_data_transfer *)recvmsg->packet;
+ struct smb2_hdr *hdr = (struct smb2_hdr *)(recvmsg->packet
+ + le32_to_cpu(req->data_offset));
+ ksmbd_debug(RDMA,
+ "CreditGranted: %u, CreditRequested: %u, DataLength: %u, RemainingDataLength: %u, SMB: %x, Command: %u\n",
+ le16_to_cpu(req->credits_granted),
+ le16_to_cpu(req->credits_requested),
+ req->data_length, req->remaining_data_length,
+ hdr->ProtocolId, hdr->Command);
+ break;
+ }
+ case SMB_DIRECT_MSG_NEGOTIATE_REQ: {
+ struct smb_direct_negotiate_req *req =
+ (struct smb_direct_negotiate_req *)recvmsg->packet;
+ ksmbd_debug(RDMA,
+ "MinVersion: %u, MaxVersion: %u, CreditRequested: %u, MaxSendSize: %u, MaxRecvSize: %u, MaxFragmentedSize: %u\n",
+ le16_to_cpu(req->min_version),
+ le16_to_cpu(req->max_version),
+ le16_to_cpu(req->credits_requested),
+ le32_to_cpu(req->preferred_send_size),
+ le32_to_cpu(req->max_receive_size),
+ le32_to_cpu(req->max_fragmented_size));
+ if (le16_to_cpu(req->min_version) > 0x0100 ||
+ le16_to_cpu(req->max_version) < 0x0100)
+ return -EOPNOTSUPP;
+ if (le16_to_cpu(req->credits_requested) <= 0 ||
+ le32_to_cpu(req->max_receive_size) <= 128 ||
+ le32_to_cpu(req->max_fragmented_size) <=
+ 128 * 1024)
+ return -ECONNABORTED;
+
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smb_direct_recvmsg *recvmsg;
+ struct smb_direct_transport *t;
+
+ recvmsg = container_of(wc->wr_cqe, struct smb_direct_recvmsg, cqe);
+ t = recvmsg->transport;
+
+ if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
+ if (wc->status != IB_WC_WR_FLUSH_ERR) {
+ pr_err("Recv error. status='%s (%d)' opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status,
+ wc->opcode);
+ smb_direct_disconnect_rdma_connection(t);
+ }
+ put_empty_recvmsg(t, recvmsg);
+ return;
+ }
+
+ ksmbd_debug(RDMA, "Recv completed. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status,
+ wc->opcode);
+
+ ib_dma_sync_single_for_cpu(wc->qp->device, recvmsg->sge.addr,
+ recvmsg->sge.length, DMA_FROM_DEVICE);
+
+ switch (recvmsg->type) {
+ case SMB_DIRECT_MSG_NEGOTIATE_REQ:
+ if (wc->byte_len < sizeof(struct smb_direct_negotiate_req)) {
+ put_empty_recvmsg(t, recvmsg);
+ return;
+ }
+ t->negotiation_requested = true;
+ t->full_packet_received = true;
+ t->status = SMB_DIRECT_CS_CONNECTED;
+ enqueue_reassembly(t, recvmsg, 0);
+ wake_up_interruptible(&t->wait_status);
+ break;
+ case SMB_DIRECT_MSG_DATA_TRANSFER: {
+ struct smb_direct_data_transfer *data_transfer =
+ (struct smb_direct_data_transfer *)recvmsg->packet;
+ unsigned int data_length;
+ int avail_recvmsg_count, receive_credits;
+
+ if (wc->byte_len <
+ offsetof(struct smb_direct_data_transfer, padding)) {
+ put_empty_recvmsg(t, recvmsg);
+ return;
+ }
+
+ data_length = le32_to_cpu(data_transfer->data_length);
+ if (data_length) {
+ if (wc->byte_len < sizeof(struct smb_direct_data_transfer) +
+ (u64)data_length) {
+ put_empty_recvmsg(t, recvmsg);
+ return;
+ }
+
+ if (t->full_packet_received)
+ recvmsg->first_segment = true;
+
+ if (le32_to_cpu(data_transfer->remaining_data_length))
+ t->full_packet_received = false;
+ else
+ t->full_packet_received = true;
+
+ enqueue_reassembly(t, recvmsg, (int)data_length);
+ wake_up_interruptible(&t->wait_reassembly_queue);
+
+ spin_lock(&t->receive_credit_lock);
+ receive_credits = --(t->recv_credits);
+ avail_recvmsg_count = t->count_avail_recvmsg;
+ spin_unlock(&t->receive_credit_lock);
+ } else {
+ put_empty_recvmsg(t, recvmsg);
+
+ spin_lock(&t->receive_credit_lock);
+ receive_credits = --(t->recv_credits);
+ avail_recvmsg_count = ++(t->count_avail_recvmsg);
+ spin_unlock(&t->receive_credit_lock);
+ }
+
+ t->recv_credit_target =
+ le16_to_cpu(data_transfer->credits_requested);
+ atomic_add(le16_to_cpu(data_transfer->credits_granted),
+ &t->send_credits);
+
+ if (le16_to_cpu(data_transfer->flags) &
+ SMB_DIRECT_RESPONSE_REQUESTED)
+ queue_work(smb_direct_wq, &t->send_immediate_work);
+
+ if (atomic_read(&t->send_credits) > 0)
+ wake_up_interruptible(&t->wait_send_credits);
+
+ if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count))
+ mod_delayed_work(smb_direct_wq,
+ &t->post_recv_credits_work, 0);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static int smb_direct_post_recv(struct smb_direct_transport *t,
+ struct smb_direct_recvmsg *recvmsg)
+{
+ struct ib_recv_wr wr;
+ int ret;
+
+ recvmsg->sge.addr = ib_dma_map_single(t->cm_id->device,
+ recvmsg->packet, t->max_recv_size,
+ DMA_FROM_DEVICE);
+ ret = ib_dma_mapping_error(t->cm_id->device, recvmsg->sge.addr);
+ if (ret)
+ return ret;
+ recvmsg->sge.length = t->max_recv_size;
+ recvmsg->sge.lkey = t->pd->local_dma_lkey;
+ recvmsg->cqe.done = recv_done;
+
+ wr.wr_cqe = &recvmsg->cqe;
+ wr.next = NULL;
+ wr.sg_list = &recvmsg->sge;
+ wr.num_sge = 1;
+
+ ret = ib_post_recv(t->qp, &wr, NULL);
+ if (ret) {
+ pr_err("Can't post recv: %d\n", ret);
+ ib_dma_unmap_single(t->cm_id->device,
+ recvmsg->sge.addr, recvmsg->sge.length,
+ DMA_FROM_DEVICE);
+ smb_direct_disconnect_rdma_connection(t);
+ return ret;
+ }
+ return ret;
+}
+
+static int smb_direct_read(struct ksmbd_transport *t, char *buf,
+ unsigned int size, int unused)
+{
+ struct smb_direct_recvmsg *recvmsg;
+ struct smb_direct_data_transfer *data_transfer;
+ int to_copy, to_read, data_read, offset;
+ u32 data_length, remaining_data_length, data_offset;
+ int rc;
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
+
+again:
+ if (st->status != SMB_DIRECT_CS_CONNECTED) {
+ pr_err("disconnected\n");
+ return -ENOTCONN;
+ }
+
+ /*
+ * No need to hold the reassembly queue lock all the time as we are
+ * the only one reading from the front of the queue. The transport
+ * may add more entries to the back of the queue at the same time
+ */
+ if (st->reassembly_data_length >= size) {
+ int queue_length;
+ int queue_removed = 0;
+
+ /*
+ * Need to make sure reassembly_data_length is read before
+ * reading reassembly_queue_length and calling
+ * get_first_reassembly. This call is lock free
+ * as we never read at the end of the queue which are being
+ * updated in SOFTIRQ as more data is received
+ */
+ virt_rmb();
+ queue_length = st->reassembly_queue_length;
+ data_read = 0;
+ to_read = size;
+ offset = st->first_entry_offset;
+ while (data_read < size) {
+ recvmsg = get_first_reassembly(st);
+ data_transfer = smb_direct_recvmsg_payload(recvmsg);
+ data_length = le32_to_cpu(data_transfer->data_length);
+ remaining_data_length =
+ le32_to_cpu(data_transfer->remaining_data_length);
+ data_offset = le32_to_cpu(data_transfer->data_offset);
+
+ /*
+ * The upper layer expects RFC1002 length at the
+ * beginning of the payload. Return it to indicate
+ * the total length of the packet. This minimize the
+ * change to upper layer packet processing logic. This
+ * will be eventually remove when an intermediate
+ * transport layer is added
+ */
+ if (recvmsg->first_segment && size == 4) {
+ unsigned int rfc1002_len =
+ data_length + remaining_data_length;
+ *((__be32 *)buf) = cpu_to_be32(rfc1002_len);
+ data_read = 4;
+ recvmsg->first_segment = false;
+ ksmbd_debug(RDMA,
+ "returning rfc1002 length %d\n",
+ rfc1002_len);
+ goto read_rfc1002_done;
+ }
+
+ to_copy = min_t(int, data_length - offset, to_read);
+ memcpy(buf + data_read, (char *)data_transfer + data_offset + offset,
+ to_copy);
+
+ /* move on to the next buffer? */
+ if (to_copy == data_length - offset) {
+ queue_length--;
+ /*
+ * No need to lock if we are not at the
+ * end of the queue
+ */
+ if (queue_length) {
+ list_del(&recvmsg->list);
+ } else {
+ spin_lock_irq(&st->reassembly_queue_lock);
+ list_del(&recvmsg->list);
+ spin_unlock_irq(&st->reassembly_queue_lock);
+ }
+ queue_removed++;
+ put_recvmsg(st, recvmsg);
+ offset = 0;
+ } else {
+ offset += to_copy;
+ }
+
+ to_read -= to_copy;
+ data_read += to_copy;
+ }
+
+ spin_lock_irq(&st->reassembly_queue_lock);
+ st->reassembly_data_length -= data_read;
+ st->reassembly_queue_length -= queue_removed;
+ spin_unlock_irq(&st->reassembly_queue_lock);
+
+ spin_lock(&st->receive_credit_lock);
+ st->count_avail_recvmsg += queue_removed;
+ if (is_receive_credit_post_required(st->recv_credits, st->count_avail_recvmsg)) {
+ spin_unlock(&st->receive_credit_lock);
+ mod_delayed_work(smb_direct_wq,
+ &st->post_recv_credits_work, 0);
+ } else {
+ spin_unlock(&st->receive_credit_lock);
+ }
+
+ st->first_entry_offset = offset;
+ ksmbd_debug(RDMA,
+ "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n",
+ data_read, st->reassembly_data_length,
+ st->first_entry_offset);
+read_rfc1002_done:
+ return data_read;
+ }
+
+ ksmbd_debug(RDMA, "wait_event on more data\n");
+ rc = wait_event_interruptible(st->wait_reassembly_queue,
+ st->reassembly_data_length >= size ||
+ st->status != SMB_DIRECT_CS_CONNECTED);
+ if (rc)
+ return -EINTR;
+
+ goto again;
+}
+
+static void smb_direct_post_recv_credits(struct work_struct *work)
+{
+ struct smb_direct_transport *t = container_of(work,
+ struct smb_direct_transport, post_recv_credits_work.work);
+ struct smb_direct_recvmsg *recvmsg;
+ int receive_credits, credits = 0;
+ int ret;
+ int use_free = 1;
+
+ spin_lock(&t->receive_credit_lock);
+ receive_credits = t->recv_credits;
+ spin_unlock(&t->receive_credit_lock);
+
+ if (receive_credits < t->recv_credit_target) {
+ while (true) {
+ if (use_free)
+ recvmsg = get_free_recvmsg(t);
+ else
+ recvmsg = get_empty_recvmsg(t);
+ if (!recvmsg) {
+ if (use_free) {
+ use_free = 0;
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ recvmsg->type = SMB_DIRECT_MSG_DATA_TRANSFER;
+ recvmsg->first_segment = false;
+
+ ret = smb_direct_post_recv(t, recvmsg);
+ if (ret) {
+ pr_err("Can't post recv: %d\n", ret);
+ put_recvmsg(t, recvmsg);
+ break;
+ }
+ credits++;
+ }
+ }
+
+ spin_lock(&t->receive_credit_lock);
+ t->recv_credits += credits;
+ t->count_avail_recvmsg -= credits;
+ spin_unlock(&t->receive_credit_lock);
+
+ spin_lock(&t->lock_new_recv_credits);
+ t->new_recv_credits += credits;
+ spin_unlock(&t->lock_new_recv_credits);
+
+ if (credits)
+ queue_work(smb_direct_wq, &t->send_immediate_work);
+}
+
+static void send_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smb_direct_sendmsg *sendmsg, *sibling;
+ struct smb_direct_transport *t;
+ struct list_head *pos, *prev, *end;
+
+ sendmsg = container_of(wc->wr_cqe, struct smb_direct_sendmsg, cqe);
+ t = sendmsg->transport;
+
+ ksmbd_debug(RDMA, "Send completed. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status,
+ wc->opcode);
+
+ if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
+ pr_err("Send error. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status,
+ wc->opcode);
+ smb_direct_disconnect_rdma_connection(t);
+ }
+
+ if (atomic_dec_and_test(&t->send_pending))
+ wake_up(&t->wait_send_pending);
+
+ /* iterate and free the list of messages in reverse. the list's head
+ * is invalid.
+ */
+ for (pos = &sendmsg->list, prev = pos->prev, end = sendmsg->list.next;
+ prev != end; pos = prev, prev = prev->prev) {
+ sibling = container_of(pos, struct smb_direct_sendmsg, list);
+ smb_direct_free_sendmsg(t, sibling);
+ }
+
+ sibling = container_of(pos, struct smb_direct_sendmsg, list);
+ smb_direct_free_sendmsg(t, sibling);
+}
+
+static int manage_credits_prior_sending(struct smb_direct_transport *t)
+{
+ int new_credits;
+
+ spin_lock(&t->lock_new_recv_credits);
+ new_credits = t->new_recv_credits;
+ t->new_recv_credits = 0;
+ spin_unlock(&t->lock_new_recv_credits);
+
+ return new_credits;
+}
+
+static int smb_direct_post_send(struct smb_direct_transport *t,
+ struct ib_send_wr *wr)
+{
+ int ret;
+
+ atomic_inc(&t->send_pending);
+ ret = ib_post_send(t->qp, wr, NULL);
+ if (ret) {
+ pr_err("failed to post send: %d\n", ret);
+ if (atomic_dec_and_test(&t->send_pending))
+ wake_up(&t->wait_send_pending);
+ smb_direct_disconnect_rdma_connection(t);
+ }
+ return ret;
+}
+
+static void smb_direct_send_ctx_init(struct smb_direct_transport *t,
+ struct smb_direct_send_ctx *send_ctx,
+ bool need_invalidate_rkey,
+ unsigned int remote_key)
+{
+ INIT_LIST_HEAD(&send_ctx->msg_list);
+ send_ctx->wr_cnt = 0;
+ send_ctx->need_invalidate_rkey = need_invalidate_rkey;
+ send_ctx->remote_key = remote_key;
+}
+
+static int smb_direct_flush_send_list(struct smb_direct_transport *t,
+ struct smb_direct_send_ctx *send_ctx,
+ bool is_last)
+{
+ struct smb_direct_sendmsg *first, *last;
+ int ret;
+
+ if (list_empty(&send_ctx->msg_list))
+ return 0;
+
+ first = list_first_entry(&send_ctx->msg_list,
+ struct smb_direct_sendmsg,
+ list);
+ last = list_last_entry(&send_ctx->msg_list,
+ struct smb_direct_sendmsg,
+ list);
+
+ last->wr.send_flags = IB_SEND_SIGNALED;
+ last->wr.wr_cqe = &last->cqe;
+ if (is_last && send_ctx->need_invalidate_rkey) {
+ last->wr.opcode = IB_WR_SEND_WITH_INV;
+ last->wr.ex.invalidate_rkey = send_ctx->remote_key;
+ }
+
+ ret = smb_direct_post_send(t, &first->wr);
+ if (!ret) {
+ smb_direct_send_ctx_init(t, send_ctx,
+ send_ctx->need_invalidate_rkey,
+ send_ctx->remote_key);
+ } else {
+ atomic_add(send_ctx->wr_cnt, &t->send_credits);
+ wake_up(&t->wait_send_credits);
+ list_for_each_entry_safe(first, last, &send_ctx->msg_list,
+ list) {
+ smb_direct_free_sendmsg(t, first);
+ }
+ }
+ return ret;
+}
+
+static int wait_for_credits(struct smb_direct_transport *t,
+ wait_queue_head_t *waitq, atomic_t *total_credits,
+ int needed)
+{
+ int ret;
+
+ do {
+ if (atomic_sub_return(needed, total_credits) >= 0)
+ return 0;
+
+ atomic_add(needed, total_credits);
+ ret = wait_event_interruptible(*waitq,
+ atomic_read(total_credits) >= needed ||
+ t->status != SMB_DIRECT_CS_CONNECTED);
+
+ if (t->status != SMB_DIRECT_CS_CONNECTED)
+ return -ENOTCONN;
+ else if (ret < 0)
+ return ret;
+ } while (true);
+}
+
+static int wait_for_send_credits(struct smb_direct_transport *t,
+ struct smb_direct_send_ctx *send_ctx)
+{
+ int ret;
+
+ if (send_ctx &&
+ (send_ctx->wr_cnt >= 16 || atomic_read(&t->send_credits) <= 1)) {
+ ret = smb_direct_flush_send_list(t, send_ctx, false);
+ if (ret)
+ return ret;
+ }
+
+ return wait_for_credits(t, &t->wait_send_credits, &t->send_credits, 1);
+}
+
+static int wait_for_rw_credits(struct smb_direct_transport *t, int credits)
+{
+ return wait_for_credits(t, &t->wait_rw_credits, &t->rw_credits, credits);
+}
+
+static int calc_rw_credits(struct smb_direct_transport *t,
+ char *buf, unsigned int len)
+{
+ return DIV_ROUND_UP(get_buf_page_count(buf, len),
+ t->pages_per_rw_credit);
+}
+
+static int smb_direct_create_header(struct smb_direct_transport *t,
+ int size, int remaining_data_length,
+ struct smb_direct_sendmsg **sendmsg_out)
+{
+ struct smb_direct_sendmsg *sendmsg;
+ struct smb_direct_data_transfer *packet;
+ int header_length;
+ int ret;
+
+ sendmsg = smb_direct_alloc_sendmsg(t);
+ if (IS_ERR(sendmsg))
+ return PTR_ERR(sendmsg);
+
+ /* Fill in the packet header */
+ packet = (struct smb_direct_data_transfer *)sendmsg->packet;
+ packet->credits_requested = cpu_to_le16(t->send_credit_target);
+ packet->credits_granted = cpu_to_le16(manage_credits_prior_sending(t));
+
+ packet->flags = 0;
+ packet->reserved = 0;
+ if (!size)
+ packet->data_offset = 0;
+ else
+ packet->data_offset = cpu_to_le32(24);
+ packet->data_length = cpu_to_le32(size);
+ packet->remaining_data_length = cpu_to_le32(remaining_data_length);
+ packet->padding = 0;
+
+ ksmbd_debug(RDMA,
+ "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n",
+ le16_to_cpu(packet->credits_requested),
+ le16_to_cpu(packet->credits_granted),
+ le32_to_cpu(packet->data_offset),
+ le32_to_cpu(packet->data_length),
+ le32_to_cpu(packet->remaining_data_length));
+
+ /* Map the packet to DMA */
+ header_length = sizeof(struct smb_direct_data_transfer);
+ /* If this is a packet without payload, don't send padding */
+ if (!size)
+ header_length =
+ offsetof(struct smb_direct_data_transfer, padding);
+
+ sendmsg->sge[0].addr = ib_dma_map_single(t->cm_id->device,
+ (void *)packet,
+ header_length,
+ DMA_TO_DEVICE);
+ ret = ib_dma_mapping_error(t->cm_id->device, sendmsg->sge[0].addr);
+ if (ret) {
+ smb_direct_free_sendmsg(t, sendmsg);
+ return ret;
+ }
+
+ sendmsg->num_sge = 1;
+ sendmsg->sge[0].length = header_length;
+ sendmsg->sge[0].lkey = t->pd->local_dma_lkey;
+
+ *sendmsg_out = sendmsg;
+ return 0;
+}
+
+static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nentries)
+{
+ bool high = is_vmalloc_addr(buf);
+ struct page *page;
+ int offset, len;
+ int i = 0;
+
+ if (size <= 0 || nentries < get_buf_page_count(buf, size))
+ return -EINVAL;
+
+ offset = offset_in_page(buf);
+ buf -= offset;
+ while (size > 0) {
+ len = min_t(int, PAGE_SIZE - offset, size);
+ if (high)
+ page = vmalloc_to_page(buf);
+ else
+ page = kmap_to_page(buf);
+
+ if (!sg_list)
+ return -EINVAL;
+ sg_set_page(sg_list, page, len, offset);
+ sg_list = sg_next(sg_list);
+
+ buf += PAGE_SIZE;
+ size -= len;
+ offset = 0;
+ i++;
+ }
+ return i;
+}
+
+static int get_mapped_sg_list(struct ib_device *device, void *buf, int size,
+ struct scatterlist *sg_list, int nentries,
+ enum dma_data_direction dir)
+{
+ int npages;
+
+ npages = get_sg_list(buf, size, sg_list, nentries);
+ if (npages < 0)
+ return -EINVAL;
+ return ib_dma_map_sg(device, sg_list, npages, dir);
+}
+
+static int post_sendmsg(struct smb_direct_transport *t,
+ struct smb_direct_send_ctx *send_ctx,
+ struct smb_direct_sendmsg *msg)
+{
+ int i;
+
+ for (i = 0; i < msg->num_sge; i++)
+ ib_dma_sync_single_for_device(t->cm_id->device,
+ msg->sge[i].addr, msg->sge[i].length,
+ DMA_TO_DEVICE);
+
+ msg->cqe.done = send_done;
+ msg->wr.opcode = IB_WR_SEND;
+ msg->wr.sg_list = &msg->sge[0];
+ msg->wr.num_sge = msg->num_sge;
+ msg->wr.next = NULL;
+
+ if (send_ctx) {
+ msg->wr.wr_cqe = NULL;
+ msg->wr.send_flags = 0;
+ if (!list_empty(&send_ctx->msg_list)) {
+ struct smb_direct_sendmsg *last;
+
+ last = list_last_entry(&send_ctx->msg_list,
+ struct smb_direct_sendmsg,
+ list);
+ last->wr.next = &msg->wr;
+ }
+ list_add_tail(&msg->list, &send_ctx->msg_list);
+ send_ctx->wr_cnt++;
+ return 0;
+ }
+
+ msg->wr.wr_cqe = &msg->cqe;
+ msg->wr.send_flags = IB_SEND_SIGNALED;
+ return smb_direct_post_send(t, &msg->wr);
+}
+
+static int smb_direct_post_send_data(struct smb_direct_transport *t,
+ struct smb_direct_send_ctx *send_ctx,
+ struct kvec *iov, int niov,
+ int remaining_data_length)
+{
+ int i, j, ret;
+ struct smb_direct_sendmsg *msg;
+ int data_length;
+ struct scatterlist sg[SMB_DIRECT_MAX_SEND_SGES - 1];
+
+ ret = wait_for_send_credits(t, send_ctx);
+ if (ret)
+ return ret;
+
+ data_length = 0;
+ for (i = 0; i < niov; i++)
+ data_length += iov[i].iov_len;
+
+ ret = smb_direct_create_header(t, data_length, remaining_data_length,
+ &msg);
+ if (ret) {
+ atomic_inc(&t->send_credits);
+ return ret;
+ }
+
+ for (i = 0; i < niov; i++) {
+ struct ib_sge *sge;
+ int sg_cnt;
+
+ sg_init_table(sg, SMB_DIRECT_MAX_SEND_SGES - 1);
+ sg_cnt = get_mapped_sg_list(t->cm_id->device,
+ iov[i].iov_base, iov[i].iov_len,
+ sg, SMB_DIRECT_MAX_SEND_SGES - 1,
+ DMA_TO_DEVICE);
+ if (sg_cnt <= 0) {
+ pr_err("failed to map buffer\n");
+ ret = -ENOMEM;
+ goto err;
+ } else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES) {
+ pr_err("buffer not fitted into sges\n");
+ ret = -E2BIG;
+ ib_dma_unmap_sg(t->cm_id->device, sg, sg_cnt,
+ DMA_TO_DEVICE);
+ goto err;
+ }
+
+ for (j = 0; j < sg_cnt; j++) {
+ sge = &msg->sge[msg->num_sge];
+ sge->addr = sg_dma_address(&sg[j]);
+ sge->length = sg_dma_len(&sg[j]);
+ sge->lkey = t->pd->local_dma_lkey;
+ msg->num_sge++;
+ }
+ }
+
+ ret = post_sendmsg(t, send_ctx, msg);
+ if (ret)
+ goto err;
+ return 0;
+err:
+ smb_direct_free_sendmsg(t, msg);
+ atomic_inc(&t->send_credits);
+ return ret;
+}
+
+static int smb_direct_writev(struct ksmbd_transport *t,
+ struct kvec *iov, int niovs, int buflen,
+ bool need_invalidate, unsigned int remote_key)
+{
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
+ int remaining_data_length;
+ int start, i, j;
+ int max_iov_size = st->max_send_size -
+ sizeof(struct smb_direct_data_transfer);
+ int ret;
+ struct kvec vec;
+ struct smb_direct_send_ctx send_ctx;
+
+ if (st->status != SMB_DIRECT_CS_CONNECTED)
+ return -ENOTCONN;
+
+ //FIXME: skip RFC1002 header..
+ buflen -= 4;
+ iov[0].iov_base += 4;
+ iov[0].iov_len -= 4;
+
+ remaining_data_length = buflen;
+ ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen);
+
+ smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key);
+ start = i = 0;
+ buflen = 0;
+ while (true) {
+ buflen += iov[i].iov_len;
+ if (buflen > max_iov_size) {
+ if (i > start) {
+ remaining_data_length -=
+ (buflen - iov[i].iov_len);
+ ret = smb_direct_post_send_data(st, &send_ctx,
+ &iov[start], i - start,
+ remaining_data_length);
+ if (ret)
+ goto done;
+ } else {
+ /* iov[start] is too big, break it */
+ int nvec = (buflen + max_iov_size - 1) /
+ max_iov_size;
+
+ for (j = 0; j < nvec; j++) {
+ vec.iov_base =
+ (char *)iov[start].iov_base +
+ j * max_iov_size;
+ vec.iov_len =
+ min_t(int, max_iov_size,
+ buflen - max_iov_size * j);
+ remaining_data_length -= vec.iov_len;
+ ret = smb_direct_post_send_data(st, &send_ctx, &vec, 1,
+ remaining_data_length);
+ if (ret)
+ goto done;
+ }
+ i++;
+ if (i == niovs)
+ break;
+ }
+ start = i;
+ buflen = 0;
+ } else {
+ i++;
+ if (i == niovs) {
+ /* send out all remaining vecs */
+ remaining_data_length -= buflen;
+ ret = smb_direct_post_send_data(st, &send_ctx,
+ &iov[start], i - start,
+ remaining_data_length);
+ if (ret)
+ goto done;
+ break;
+ }
+ }
+ }
+
+done:
+ ret = smb_direct_flush_send_list(st, &send_ctx, true);
+
+ /*
+ * As an optimization, we don't wait for individual I/O to finish
+ * before sending the next one.
+ * Send them all and wait for pending send count to get to 0
+ * that means all the I/Os have been out and we are good to return
+ */
+
+ wait_event(st->wait_send_pending,
+ atomic_read(&st->send_pending) == 0);
+ return ret;
+}
+
+static void smb_direct_free_rdma_rw_msg(struct smb_direct_transport *t,
+ struct smb_direct_rdma_rw_msg *msg,
+ enum dma_data_direction dir)
+{
+ rdma_rw_ctx_destroy(&msg->rw_ctx, t->qp, t->qp->port,
+ msg->sgt.sgl, msg->sgt.nents, dir);
+ sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
+ kfree(msg);
+}
+
+static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
+ enum dma_data_direction dir)
+{
+ struct smb_direct_rdma_rw_msg *msg = container_of(wc->wr_cqe,
+ struct smb_direct_rdma_rw_msg, cqe);
+ struct smb_direct_transport *t = msg->t;
+
+ if (wc->status != IB_WC_SUCCESS) {
+ msg->status = -EIO;
+ pr_err("read/write error. opcode = %d, status = %s(%d)\n",
+ wc->opcode, ib_wc_status_msg(wc->status), wc->status);
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ smb_direct_disconnect_rdma_connection(t);
+ }
+
+ complete(msg->completion);
+}
+
+static void read_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ read_write_done(cq, wc, DMA_FROM_DEVICE);
+}
+
+static void write_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ read_write_done(cq, wc, DMA_TO_DEVICE);
+}
+
+static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
+ void *buf, int buf_len,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len,
+ bool is_read)
+{
+ struct smb_direct_rdma_rw_msg *msg, *next_msg;
+ int i, ret;
+ DECLARE_COMPLETION_ONSTACK(completion);
+ struct ib_send_wr *first_wr;
+ LIST_HEAD(msg_list);
+ char *desc_buf;
+ int credits_needed;
+ unsigned int desc_buf_len;
+ size_t total_length = 0;
+
+ if (t->status != SMB_DIRECT_CS_CONNECTED)
+ return -ENOTCONN;
+
+ /* calculate needed credits */
+ credits_needed = 0;
+ desc_buf = buf;
+ for (i = 0; i < desc_len / sizeof(*desc); i++) {
+ desc_buf_len = le32_to_cpu(desc[i].length);
+
+ credits_needed += calc_rw_credits(t, desc_buf, desc_buf_len);
+ desc_buf += desc_buf_len;
+ total_length += desc_buf_len;
+ if (desc_buf_len == 0 || total_length > buf_len ||
+ total_length > t->max_rdma_rw_size)
+ return -EINVAL;
+ }
+
+ ksmbd_debug(RDMA, "RDMA %s, len %#x, needed credits %#x\n",
+ is_read ? "read" : "write", buf_len, credits_needed);
+
+ ret = wait_for_rw_credits(t, credits_needed);
+ if (ret < 0)
+ return ret;
+
+ /* build rdma_rw_ctx for each descriptor */
+ desc_buf = buf;
+ for (i = 0; i < desc_len / sizeof(*desc); i++) {
+ msg = kzalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
+ sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
+ if (!msg) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ desc_buf_len = le32_to_cpu(desc[i].length);
+
+ msg->t = t;
+ msg->cqe.done = is_read ? read_done : write_done;
+ msg->completion = &completion;
+
+ msg->sgt.sgl = &msg->sg_list[0];
+ ret = sg_alloc_table_chained(&msg->sgt,
+ get_buf_page_count(desc_buf, desc_buf_len),
+ msg->sg_list, SG_CHUNK_SIZE);
+ if (ret) {
+ kfree(msg);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = get_sg_list(desc_buf, desc_buf_len,
+ msg->sgt.sgl, msg->sgt.orig_nents);
+ if (ret < 0) {
+ sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
+ kfree(msg);
+ goto out;
+ }
+
+ ret = rdma_rw_ctx_init(&msg->rw_ctx, t->qp, t->qp->port,
+ msg->sgt.sgl,
+ get_buf_page_count(desc_buf, desc_buf_len),
+ 0,
+ le64_to_cpu(desc[i].offset),
+ le32_to_cpu(desc[i].token),
+ is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ if (ret < 0) {
+ pr_err("failed to init rdma_rw_ctx: %d\n", ret);
+ sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
+ kfree(msg);
+ goto out;
+ }
+
+ list_add_tail(&msg->list, &msg_list);
+ desc_buf += desc_buf_len;
+ }
+
+ /* concatenate work requests of rdma_rw_ctxs */
+ first_wr = NULL;
+ list_for_each_entry_reverse(msg, &msg_list, list) {
+ first_wr = rdma_rw_ctx_wrs(&msg->rw_ctx, t->qp, t->qp->port,
+ &msg->cqe, first_wr);
+ }
+
+ ret = ib_post_send(t->qp, first_wr, NULL);
+ if (ret) {
+ pr_err("failed to post send wr for RDMA R/W: %d\n", ret);
+ goto out;
+ }
+
+ msg = list_last_entry(&msg_list, struct smb_direct_rdma_rw_msg, list);
+ wait_for_completion(&completion);
+ ret = msg->status;
+out:
+ list_for_each_entry_safe(msg, next_msg, &msg_list, list) {
+ list_del(&msg->list);
+ smb_direct_free_rdma_rw_msg(t, msg,
+ is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ }
+ atomic_add(credits_needed, &t->rw_credits);
+ wake_up(&t->wait_rw_credits);
+ return ret;
+}
+
+static int smb_direct_rdma_write(struct ksmbd_transport *t,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len)
+{
+ return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen,
+ desc, desc_len, false);
+}
+
+static int smb_direct_rdma_read(struct ksmbd_transport *t,
+ void *buf, unsigned int buflen,
+ struct smb2_buffer_desc_v1 *desc,
+ unsigned int desc_len)
+{
+ return smb_direct_rdma_xmit(smb_trans_direct_transfort(t), buf, buflen,
+ desc, desc_len, true);
+}
+
+static void smb_direct_disconnect(struct ksmbd_transport *t)
+{
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
+
+ ksmbd_debug(RDMA, "Disconnecting cm_id=%p\n", st->cm_id);
+
+ smb_direct_disconnect_rdma_work(&st->disconnect_work);
+ wait_event_interruptible(st->wait_status,
+ st->status == SMB_DIRECT_CS_DISCONNECTED);
+ free_transport(st);
+}
+
+static void smb_direct_shutdown(struct ksmbd_transport *t)
+{
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
+
+ ksmbd_debug(RDMA, "smb-direct shutdown cm_id=%p\n", st->cm_id);
+
+ smb_direct_disconnect_rdma_work(&st->disconnect_work);
+}
+
+static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
+ struct rdma_cm_event *event)
+{
+ struct smb_direct_transport *t = cm_id->context;
+
+ ksmbd_debug(RDMA, "RDMA CM event. cm_id=%p event=%s (%d)\n",
+ cm_id, rdma_event_msg(event->event), event->event);
+
+ switch (event->event) {
+ case RDMA_CM_EVENT_ESTABLISHED: {
+ t->status = SMB_DIRECT_CS_CONNECTED;
+ wake_up_interruptible(&t->wait_status);
+ break;
+ }
+ case RDMA_CM_EVENT_DEVICE_REMOVAL:
+ case RDMA_CM_EVENT_DISCONNECTED: {
+ ib_drain_qp(t->qp);
+
+ t->status = SMB_DIRECT_CS_DISCONNECTED;
+ wake_up_interruptible(&t->wait_status);
+ wake_up_interruptible(&t->wait_reassembly_queue);
+ wake_up(&t->wait_send_credits);
+ break;
+ }
+ case RDMA_CM_EVENT_CONNECT_ERROR: {
+ t->status = SMB_DIRECT_CS_DISCONNECTED;
+ wake_up_interruptible(&t->wait_status);
+ break;
+ }
+ default:
+ pr_err("Unexpected RDMA CM event. cm_id=%p, event=%s (%d)\n",
+ cm_id, rdma_event_msg(event->event),
+ event->event);
+ break;
+ }
+ return 0;
+}
+
+static void smb_direct_qpair_handler(struct ib_event *event, void *context)
+{
+ struct smb_direct_transport *t = context;
+
+ ksmbd_debug(RDMA, "Received QP event. cm_id=%p, event=%s (%d)\n",
+ t->cm_id, ib_event_msg(event->event), event->event);
+
+ switch (event->event) {
+ case IB_EVENT_CQ_ERR:
+ case IB_EVENT_QP_FATAL:
+ smb_direct_disconnect_rdma_connection(t);
+ break;
+ default:
+ break;
+ }
+}
+
+static int smb_direct_send_negotiate_response(struct smb_direct_transport *t,
+ int failed)
+{
+ struct smb_direct_sendmsg *sendmsg;
+ struct smb_direct_negotiate_resp *resp;
+ int ret;
+
+ sendmsg = smb_direct_alloc_sendmsg(t);
+ if (IS_ERR(sendmsg))
+ return -ENOMEM;
+
+ resp = (struct smb_direct_negotiate_resp *)sendmsg->packet;
+ if (failed) {
+ memset(resp, 0, sizeof(*resp));
+ resp->min_version = cpu_to_le16(0x0100);
+ resp->max_version = cpu_to_le16(0x0100);
+ resp->status = STATUS_NOT_SUPPORTED;
+ } else {
+ resp->status = STATUS_SUCCESS;
+ resp->min_version = SMB_DIRECT_VERSION_LE;
+ resp->max_version = SMB_DIRECT_VERSION_LE;
+ resp->negotiated_version = SMB_DIRECT_VERSION_LE;
+ resp->reserved = 0;
+ resp->credits_requested =
+ cpu_to_le16(t->send_credit_target);
+ resp->credits_granted = cpu_to_le16(manage_credits_prior_sending(t));
+ resp->max_readwrite_size = cpu_to_le32(t->max_rdma_rw_size);
+ resp->preferred_send_size = cpu_to_le32(t->max_send_size);
+ resp->max_receive_size = cpu_to_le32(t->max_recv_size);
+ resp->max_fragmented_size =
+ cpu_to_le32(t->max_fragmented_recv_size);
+ }
+
+ sendmsg->sge[0].addr = ib_dma_map_single(t->cm_id->device,
+ (void *)resp, sizeof(*resp),
+ DMA_TO_DEVICE);
+ ret = ib_dma_mapping_error(t->cm_id->device, sendmsg->sge[0].addr);
+ if (ret) {
+ smb_direct_free_sendmsg(t, sendmsg);
+ return ret;
+ }
+
+ sendmsg->num_sge = 1;
+ sendmsg->sge[0].length = sizeof(*resp);
+ sendmsg->sge[0].lkey = t->pd->local_dma_lkey;
+
+ ret = post_sendmsg(t, NULL, sendmsg);
+ if (ret) {
+ smb_direct_free_sendmsg(t, sendmsg);
+ return ret;
+ }
+
+ wait_event(t->wait_send_pending,
+ atomic_read(&t->send_pending) == 0);
+ return 0;
+}
+
+static int smb_direct_accept_client(struct smb_direct_transport *t)
+{
+ struct rdma_conn_param conn_param;
+ struct ib_port_immutable port_immutable;
+ u32 ird_ord_hdr[2];
+ int ret;
+
+ memset(&conn_param, 0, sizeof(conn_param));
+ conn_param.initiator_depth = min_t(u8, t->cm_id->device->attrs.max_qp_rd_atom,
+ SMB_DIRECT_CM_INITIATOR_DEPTH);
+ conn_param.responder_resources = 0;
+
+ t->cm_id->device->ops.get_port_immutable(t->cm_id->device,
+ t->cm_id->port_num,
+ &port_immutable);
+ if (port_immutable.core_cap_flags & RDMA_CORE_PORT_IWARP) {
+ ird_ord_hdr[0] = conn_param.responder_resources;
+ ird_ord_hdr[1] = 1;
+ conn_param.private_data = ird_ord_hdr;
+ conn_param.private_data_len = sizeof(ird_ord_hdr);
+ } else {
+ conn_param.private_data = NULL;
+ conn_param.private_data_len = 0;
+ }
+ conn_param.retry_count = SMB_DIRECT_CM_RETRY;
+ conn_param.rnr_retry_count = SMB_DIRECT_CM_RNR_RETRY;
+ conn_param.flow_control = 0;
+
+ ret = rdma_accept(t->cm_id, &conn_param);
+ if (ret) {
+ pr_err("error at rdma_accept: %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int smb_direct_prepare_negotiation(struct smb_direct_transport *t)
+{
+ int ret;
+ struct smb_direct_recvmsg *recvmsg;
+
+ recvmsg = get_free_recvmsg(t);
+ if (!recvmsg)
+ return -ENOMEM;
+ recvmsg->type = SMB_DIRECT_MSG_NEGOTIATE_REQ;
+
+ ret = smb_direct_post_recv(t, recvmsg);
+ if (ret) {
+ pr_err("Can't post recv: %d\n", ret);
+ goto out_err;
+ }
+
+ t->negotiation_requested = false;
+ ret = smb_direct_accept_client(t);
+ if (ret) {
+ pr_err("Can't accept client\n");
+ goto out_err;
+ }
+
+ smb_direct_post_recv_credits(&t->post_recv_credits_work.work);
+ return 0;
+out_err:
+ put_recvmsg(t, recvmsg);
+ return ret;
+}
+
+static unsigned int smb_direct_get_max_fr_pages(struct smb_direct_transport *t)
+{
+ return min_t(unsigned int,
+ t->cm_id->device->attrs.max_fast_reg_page_list_len,
+ 256);
+}
+
+static int smb_direct_init_params(struct smb_direct_transport *t,
+ struct ib_qp_cap *cap)
+{
+ struct ib_device *device = t->cm_id->device;
+ int max_send_sges, max_rw_wrs, max_send_wrs;
+ unsigned int max_sge_per_wr, wrs_per_credit;
+
+ /* need 3 more sge. because a SMB_DIRECT header, SMB2 header,
+ * SMB2 response could be mapped.
+ */
+ t->max_send_size = smb_direct_max_send_size;
+ max_send_sges = DIV_ROUND_UP(t->max_send_size, PAGE_SIZE) + 3;
+ if (max_send_sges > SMB_DIRECT_MAX_SEND_SGES) {
+ pr_err("max_send_size %d is too large\n", t->max_send_size);
+ return -EINVAL;
+ }
+
+ /* Calculate the number of work requests for RDMA R/W.
+ * The maximum number of pages which can be registered
+ * with one Memory region can be transferred with one
+ * R/W credit. And at least 4 work requests for each credit
+ * are needed for MR registration, RDMA R/W, local & remote
+ * MR invalidation.
+ */
+ t->max_rdma_rw_size = smb_direct_max_read_write_size;
+ t->pages_per_rw_credit = smb_direct_get_max_fr_pages(t);
+ t->max_rw_credits = DIV_ROUND_UP(t->max_rdma_rw_size,
+ (t->pages_per_rw_credit - 1) *
+ PAGE_SIZE);
+
+ max_sge_per_wr = min_t(unsigned int, device->attrs.max_send_sge,
+ device->attrs.max_sge_rd);
+ max_sge_per_wr = max_t(unsigned int, max_sge_per_wr,
+ max_send_sges);
+ wrs_per_credit = max_t(unsigned int, 4,
+ DIV_ROUND_UP(t->pages_per_rw_credit,
+ max_sge_per_wr) + 1);
+ max_rw_wrs = t->max_rw_credits * wrs_per_credit;
+
+ max_send_wrs = smb_direct_send_credit_target + max_rw_wrs;
+ if (max_send_wrs > device->attrs.max_cqe ||
+ max_send_wrs > device->attrs.max_qp_wr) {
+ pr_err("consider lowering send_credit_target = %d\n",
+ smb_direct_send_credit_target);
+ pr_err("Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
+ device->attrs.max_cqe, device->attrs.max_qp_wr);
+ return -EINVAL;
+ }
+
+ if (smb_direct_receive_credit_max > device->attrs.max_cqe ||
+ smb_direct_receive_credit_max > device->attrs.max_qp_wr) {
+ pr_err("consider lowering receive_credit_max = %d\n",
+ smb_direct_receive_credit_max);
+ pr_err("Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n",
+ device->attrs.max_cqe, device->attrs.max_qp_wr);
+ return -EINVAL;
+ }
+
+ if (device->attrs.max_recv_sge < SMB_DIRECT_MAX_RECV_SGES) {
+ pr_err("warning: device max_recv_sge = %d too small\n",
+ device->attrs.max_recv_sge);
+ return -EINVAL;
+ }
+
+ t->recv_credits = 0;
+ t->count_avail_recvmsg = 0;
+
+ t->recv_credit_max = smb_direct_receive_credit_max;
+ t->recv_credit_target = 10;
+ t->new_recv_credits = 0;
+
+ t->send_credit_target = smb_direct_send_credit_target;
+ atomic_set(&t->send_credits, 0);
+ atomic_set(&t->rw_credits, t->max_rw_credits);
+
+ t->max_send_size = smb_direct_max_send_size;
+ t->max_recv_size = smb_direct_max_receive_size;
+ t->max_fragmented_recv_size = smb_direct_max_fragmented_recv_size;
+
+ cap->max_send_wr = max_send_wrs;
+ cap->max_recv_wr = t->recv_credit_max;
+ cap->max_send_sge = max_sge_per_wr;
+ cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES;
+ cap->max_inline_data = 0;
+ cap->max_rdma_ctxs = t->max_rw_credits;
+ return 0;
+}
+
+static void smb_direct_destroy_pools(struct smb_direct_transport *t)
+{
+ struct smb_direct_recvmsg *recvmsg;
+
+ while ((recvmsg = get_free_recvmsg(t)))
+ mempool_free(recvmsg, t->recvmsg_mempool);
+ while ((recvmsg = get_empty_recvmsg(t)))
+ mempool_free(recvmsg, t->recvmsg_mempool);
+
+ mempool_destroy(t->recvmsg_mempool);
+ t->recvmsg_mempool = NULL;
+
+ kmem_cache_destroy(t->recvmsg_cache);
+ t->recvmsg_cache = NULL;
+
+ mempool_destroy(t->sendmsg_mempool);
+ t->sendmsg_mempool = NULL;
+
+ kmem_cache_destroy(t->sendmsg_cache);
+ t->sendmsg_cache = NULL;
+}
+
+static int smb_direct_create_pools(struct smb_direct_transport *t)
+{
+ char name[80];
+ int i;
+ struct smb_direct_recvmsg *recvmsg;
+
+ snprintf(name, sizeof(name), "smb_direct_rqst_pool_%p", t);
+ t->sendmsg_cache = kmem_cache_create(name,
+ sizeof(struct smb_direct_sendmsg) +
+ sizeof(struct smb_direct_negotiate_resp),
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (!t->sendmsg_cache)
+ return -ENOMEM;
+
+ t->sendmsg_mempool = mempool_create(t->send_credit_target,
+ mempool_alloc_slab, mempool_free_slab,
+ t->sendmsg_cache);
+ if (!t->sendmsg_mempool)
+ goto err;
+
+ snprintf(name, sizeof(name), "smb_direct_resp_%p", t);
+ t->recvmsg_cache = kmem_cache_create(name,
+ sizeof(struct smb_direct_recvmsg) +
+ t->max_recv_size,
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ if (!t->recvmsg_cache)
+ goto err;
+
+ t->recvmsg_mempool =
+ mempool_create(t->recv_credit_max, mempool_alloc_slab,
+ mempool_free_slab, t->recvmsg_cache);
+ if (!t->recvmsg_mempool)
+ goto err;
+
+ INIT_LIST_HEAD(&t->recvmsg_queue);
+
+ for (i = 0; i < t->recv_credit_max; i++) {
+ recvmsg = mempool_alloc(t->recvmsg_mempool, GFP_KERNEL);
+ if (!recvmsg)
+ goto err;
+ recvmsg->transport = t;
+ list_add(&recvmsg->list, &t->recvmsg_queue);
+ }
+ t->count_avail_recvmsg = t->recv_credit_max;
+
+ return 0;
+err:
+ smb_direct_destroy_pools(t);
+ return -ENOMEM;
+}
+
+static int smb_direct_create_qpair(struct smb_direct_transport *t,
+ struct ib_qp_cap *cap)
+{
+ int ret;
+ struct ib_qp_init_attr qp_attr;
+ int pages_per_rw;
+
+ t->pd = ib_alloc_pd(t->cm_id->device, 0);
+ if (IS_ERR(t->pd)) {
+ pr_err("Can't create RDMA PD\n");
+ ret = PTR_ERR(t->pd);
+ t->pd = NULL;
+ return ret;
+ }
+
+ t->send_cq = ib_alloc_cq(t->cm_id->device, t,
+ smb_direct_send_credit_target + cap->max_rdma_ctxs,
+ 0, IB_POLL_WORKQUEUE);
+ if (IS_ERR(t->send_cq)) {
+ pr_err("Can't create RDMA send CQ\n");
+ ret = PTR_ERR(t->send_cq);
+ t->send_cq = NULL;
+ goto err;
+ }
+
+ t->recv_cq = ib_alloc_cq(t->cm_id->device, t,
+ t->recv_credit_max, 0, IB_POLL_WORKQUEUE);
+ if (IS_ERR(t->recv_cq)) {
+ pr_err("Can't create RDMA recv CQ\n");
+ ret = PTR_ERR(t->recv_cq);
+ t->recv_cq = NULL;
+ goto err;
+ }
+
+ memset(&qp_attr, 0, sizeof(qp_attr));
+ qp_attr.event_handler = smb_direct_qpair_handler;
+ qp_attr.qp_context = t;
+ qp_attr.cap = *cap;
+ qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
+ qp_attr.qp_type = IB_QPT_RC;
+ qp_attr.send_cq = t->send_cq;
+ qp_attr.recv_cq = t->recv_cq;
+ qp_attr.port_num = ~0;
+
+ ret = rdma_create_qp(t->cm_id, t->pd, &qp_attr);
+ if (ret) {
+ pr_err("Can't create RDMA QP: %d\n", ret);
+ goto err;
+ }
+
+ t->qp = t->cm_id->qp;
+ t->cm_id->event_handler = smb_direct_cm_handler;
+
+ pages_per_rw = DIV_ROUND_UP(t->max_rdma_rw_size, PAGE_SIZE) + 1;
+ if (pages_per_rw > t->cm_id->device->attrs.max_sgl_rd) {
+ ret = ib_mr_pool_init(t->qp, &t->qp->rdma_mrs,
+ t->max_rw_credits, IB_MR_TYPE_MEM_REG,
+ t->pages_per_rw_credit, 0);
+ if (ret) {
+ pr_err("failed to init mr pool count %d pages %d\n",
+ t->max_rw_credits, t->pages_per_rw_credit);
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ if (t->qp) {
+ ib_destroy_qp(t->qp);
+ t->qp = NULL;
+ }
+ if (t->recv_cq) {
+ ib_destroy_cq(t->recv_cq);
+ t->recv_cq = NULL;
+ }
+ if (t->send_cq) {
+ ib_destroy_cq(t->send_cq);
+ t->send_cq = NULL;
+ }
+ if (t->pd) {
+ ib_dealloc_pd(t->pd);
+ t->pd = NULL;
+ }
+ return ret;
+}
+
+static int smb_direct_prepare(struct ksmbd_transport *t)
+{
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
+ struct smb_direct_recvmsg *recvmsg;
+ struct smb_direct_negotiate_req *req;
+ int ret;
+
+ ksmbd_debug(RDMA, "Waiting for SMB_DIRECT negotiate request\n");
+ ret = wait_event_interruptible_timeout(st->wait_status,
+ st->negotiation_requested ||
+ st->status == SMB_DIRECT_CS_DISCONNECTED,
+ SMB_DIRECT_NEGOTIATE_TIMEOUT * HZ);
+ if (ret <= 0 || st->status == SMB_DIRECT_CS_DISCONNECTED)
+ return ret < 0 ? ret : -ETIMEDOUT;
+
+ recvmsg = get_first_reassembly(st);
+ if (!recvmsg)
+ return -ECONNABORTED;
+
+ ret = smb_direct_check_recvmsg(recvmsg);
+ if (ret == -ECONNABORTED)
+ goto out;
+
+ req = (struct smb_direct_negotiate_req *)recvmsg->packet;
+ st->max_recv_size = min_t(int, st->max_recv_size,
+ le32_to_cpu(req->preferred_send_size));
+ st->max_send_size = min_t(int, st->max_send_size,
+ le32_to_cpu(req->max_receive_size));
+ st->max_fragmented_send_size =
+ le32_to_cpu(req->max_fragmented_size);
+ st->max_fragmented_recv_size =
+ (st->recv_credit_max * st->max_recv_size) / 2;
+
+ ret = smb_direct_send_negotiate_response(st, ret);
+out:
+ spin_lock_irq(&st->reassembly_queue_lock);
+ st->reassembly_queue_length--;
+ list_del(&recvmsg->list);
+ spin_unlock_irq(&st->reassembly_queue_lock);
+ put_recvmsg(st, recvmsg);
+
+ return ret;
+}
+
+static int smb_direct_connect(struct smb_direct_transport *st)
+{
+ int ret;
+ struct ib_qp_cap qp_cap;
+
+ ret = smb_direct_init_params(st, &qp_cap);
+ if (ret) {
+ pr_err("Can't configure RDMA parameters\n");
+ return ret;
+ }
+
+ ret = smb_direct_create_pools(st);
+ if (ret) {
+ pr_err("Can't init RDMA pool: %d\n", ret);
+ return ret;
+ }
+
+ ret = smb_direct_create_qpair(st, &qp_cap);
+ if (ret) {
+ pr_err("Can't accept RDMA client: %d\n", ret);
+ return ret;
+ }
+
+ ret = smb_direct_prepare_negotiation(st);
+ if (ret) {
+ pr_err("Can't negotiate: %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static bool rdma_frwr_is_supported(struct ib_device_attr *attrs)
+{
+ if (!(attrs->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS))
+ return false;
+ if (attrs->max_fast_reg_page_list_len == 0)
+ return false;
+ return true;
+}
+
+static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
+{
+ struct smb_direct_transport *t;
+ int ret;
+
+ if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) {
+ ksmbd_debug(RDMA,
+ "Fast Registration Work Requests is not supported. device capabilities=%llx\n",
+ new_cm_id->device->attrs.device_cap_flags);
+ return -EPROTONOSUPPORT;
+ }
+
+ t = alloc_transport(new_cm_id);
+ if (!t)
+ return -ENOMEM;
+
+ ret = smb_direct_connect(t);
+ if (ret)
+ goto out_err;
+
+ KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop,
+ KSMBD_TRANS(t)->conn, "ksmbd:r%u",
+ smb_direct_port);
+ if (IS_ERR(KSMBD_TRANS(t)->handler)) {
+ ret = PTR_ERR(KSMBD_TRANS(t)->handler);
+ pr_err("Can't start thread\n");
+ goto out_err;
+ }
+
+ return 0;
+out_err:
+ free_transport(t);
+ return ret;
+}
+
+static int smb_direct_listen_handler(struct rdma_cm_id *cm_id,
+ struct rdma_cm_event *event)
+{
+ switch (event->event) {
+ case RDMA_CM_EVENT_CONNECT_REQUEST: {
+ int ret = smb_direct_handle_connect_request(cm_id);
+
+ if (ret) {
+ pr_err("Can't create transport: %d\n", ret);
+ return ret;
+ }
+
+ ksmbd_debug(RDMA, "Received connection request. cm_id=%p\n",
+ cm_id);
+ break;
+ }
+ default:
+ pr_err("Unexpected listen event. cm_id=%p, event=%s (%d)\n",
+ cm_id, rdma_event_msg(event->event), event->event);
+ break;
+ }
+ return 0;
+}
+
+static int smb_direct_listen(int port)
+{
+ int ret;
+ struct rdma_cm_id *cm_id;
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl(INADDR_ANY),
+ .sin_port = htons(port),
+ };
+
+ cm_id = rdma_create_id(&init_net, smb_direct_listen_handler,
+ &smb_direct_listener, RDMA_PS_TCP, IB_QPT_RC);
+ if (IS_ERR(cm_id)) {
+ pr_err("Can't create cm id: %ld\n", PTR_ERR(cm_id));
+ return PTR_ERR(cm_id);
+ }
+
+ ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
+ if (ret) {
+ pr_err("Can't bind: %d\n", ret);
+ goto err;
+ }
+
+ smb_direct_listener.cm_id = cm_id;
+
+ ret = rdma_listen(cm_id, 10);
+ if (ret) {
+ pr_err("Can't listen: %d\n", ret);
+ goto err;
+ }
+ return 0;
+err:
+ smb_direct_listener.cm_id = NULL;
+ rdma_destroy_id(cm_id);
+ return ret;
+}
+
+static int smb_direct_ib_client_add(struct ib_device *ib_dev)
+{
+ struct smb_direct_device *smb_dev;
+
+ /* Set 5445 port if device type is iWARP(No IB) */
+ if (ib_dev->node_type != RDMA_NODE_IB_CA)
+ smb_direct_port = SMB_DIRECT_PORT_IWARP;
+
+ if (!ib_dev->ops.get_netdev ||
+ !rdma_frwr_is_supported(&ib_dev->attrs))
+ return 0;
+
+ smb_dev = kzalloc(sizeof(*smb_dev), GFP_KERNEL);
+ if (!smb_dev)
+ return -ENOMEM;
+ smb_dev->ib_dev = ib_dev;
+
+ write_lock(&smb_direct_device_lock);
+ list_add(&smb_dev->list, &smb_direct_device_list);
+ write_unlock(&smb_direct_device_lock);
+
+ ksmbd_debug(RDMA, "ib device added: name %s\n", ib_dev->name);
+ return 0;
+}
+
+static void smb_direct_ib_client_remove(struct ib_device *ib_dev,
+ void *client_data)
+{
+ struct smb_direct_device *smb_dev, *tmp;
+
+ write_lock(&smb_direct_device_lock);
+ list_for_each_entry_safe(smb_dev, tmp, &smb_direct_device_list, list) {
+ if (smb_dev->ib_dev == ib_dev) {
+ list_del(&smb_dev->list);
+ kfree(smb_dev);
+ break;
+ }
+ }
+ write_unlock(&smb_direct_device_lock);
+}
+
+static struct ib_client smb_direct_ib_client = {
+ .name = "ksmbd_smb_direct_ib",
+ .add = smb_direct_ib_client_add,
+ .remove = smb_direct_ib_client_remove,
+};
+
+int ksmbd_rdma_init(void)
+{
+ int ret;
+
+ smb_direct_listener.cm_id = NULL;
+
+ ret = ib_register_client(&smb_direct_ib_client);
+ if (ret) {
+ pr_err("failed to ib_register_client\n");
+ return ret;
+ }
+
+ /* When a client is running out of send credits, the credits are
+ * granted by the server's sending a packet using this queue.
+ * This avoids the situation that a clients cannot send packets
+ * for lack of credits
+ */
+ smb_direct_wq = alloc_workqueue("ksmbd-smb_direct-wq",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM, 0);
+ if (!smb_direct_wq)
+ return -ENOMEM;
+
+ ret = smb_direct_listen(smb_direct_port);
+ if (ret) {
+ destroy_workqueue(smb_direct_wq);
+ smb_direct_wq = NULL;
+ pr_err("Can't listen: %d\n", ret);
+ return ret;
+ }
+
+ ksmbd_debug(RDMA, "init RDMA listener. cm_id=%p\n",
+ smb_direct_listener.cm_id);
+ return 0;
+}
+
+void ksmbd_rdma_destroy(void)
+{
+ if (!smb_direct_listener.cm_id)
+ return;
+
+ ib_unregister_client(&smb_direct_ib_client);
+ rdma_destroy_id(smb_direct_listener.cm_id);
+
+ smb_direct_listener.cm_id = NULL;
+
+ if (smb_direct_wq) {
+ destroy_workqueue(smb_direct_wq);
+ smb_direct_wq = NULL;
+ }
+}
+
+bool ksmbd_rdma_capable_netdev(struct net_device *netdev)
+{
+ struct smb_direct_device *smb_dev;
+ int i;
+ bool rdma_capable = false;
+
+ read_lock(&smb_direct_device_lock);
+ list_for_each_entry(smb_dev, &smb_direct_device_list, list) {
+ for (i = 0; i < smb_dev->ib_dev->phys_port_cnt; i++) {
+ struct net_device *ndev;
+
+ ndev = smb_dev->ib_dev->ops.get_netdev(smb_dev->ib_dev,
+ i + 1);
+ if (!ndev)
+ continue;
+
+ if (ndev == netdev) {
+ dev_put(ndev);
+ rdma_capable = true;
+ goto out;
+ }
+ dev_put(ndev);
+ }
+ }
+out:
+ read_unlock(&smb_direct_device_lock);
+
+ if (rdma_capable == false) {
+ struct ib_device *ibdev;
+
+ ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_UNKNOWN);
+ if (ibdev) {
+ if (rdma_frwr_is_supported(&ibdev->attrs))
+ rdma_capable = true;
+ ib_device_put(ibdev);
+ }
+ }
+
+ return rdma_capable;
+}
+
+static struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
+ .prepare = smb_direct_prepare,
+ .disconnect = smb_direct_disconnect,
+ .shutdown = smb_direct_shutdown,
+ .writev = smb_direct_writev,
+ .read = smb_direct_read,
+ .rdma_read = smb_direct_rdma_read,
+ .rdma_write = smb_direct_rdma_write,
+};
diff --git a/fs/smb/server/transport_rdma.h b/fs/smb/server/transport_rdma.h
new file mode 100644
index 000000000000..77aee4e5c9dc
--- /dev/null
+++ b/fs/smb/server/transport_rdma.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2017, Microsoft Corporation.
+ * Copyright (C) 2018, LG Electronics.
+ */
+
+#ifndef __KSMBD_TRANSPORT_RDMA_H__
+#define __KSMBD_TRANSPORT_RDMA_H__
+
+#define SMBD_DEFAULT_IOSIZE (8 * 1024 * 1024)
+#define SMBD_MIN_IOSIZE (512 * 1024)
+#define SMBD_MAX_IOSIZE (16 * 1024 * 1024)
+
+/* SMB DIRECT negotiation request packet [MS-SMBD] 2.2.1 */
+struct smb_direct_negotiate_req {
+ __le16 min_version;
+ __le16 max_version;
+ __le16 reserved;
+ __le16 credits_requested;
+ __le32 preferred_send_size;
+ __le32 max_receive_size;
+ __le32 max_fragmented_size;
+} __packed;
+
+/* SMB DIRECT negotiation response packet [MS-SMBD] 2.2.2 */
+struct smb_direct_negotiate_resp {
+ __le16 min_version;
+ __le16 max_version;
+ __le16 negotiated_version;
+ __le16 reserved;
+ __le16 credits_requested;
+ __le16 credits_granted;
+ __le32 status;
+ __le32 max_readwrite_size;
+ __le32 preferred_send_size;
+ __le32 max_receive_size;
+ __le32 max_fragmented_size;
+} __packed;
+
+#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
+
+/* SMB DIRECT data transfer packet with payload [MS-SMBD] 2.2.3 */
+struct smb_direct_data_transfer {
+ __le16 credits_requested;
+ __le16 credits_granted;
+ __le16 flags;
+ __le16 reserved;
+ __le32 remaining_data_length;
+ __le32 data_offset;
+ __le32 data_length;
+ __le32 padding;
+ __u8 buffer[];
+} __packed;
+
+#ifdef CONFIG_SMB_SERVER_SMBDIRECT
+int ksmbd_rdma_init(void);
+void ksmbd_rdma_destroy(void);
+bool ksmbd_rdma_capable_netdev(struct net_device *netdev);
+void init_smbd_max_io_size(unsigned int sz);
+unsigned int get_smbd_max_read_write_size(void);
+#else
+static inline int ksmbd_rdma_init(void) { return 0; }
+static inline int ksmbd_rdma_destroy(void) { return 0; }
+static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; }
+static inline void init_smbd_max_io_size(unsigned int sz) { }
+static inline unsigned int get_smbd_max_read_write_size(void) { return 0; }
+#endif
+
+#endif /* __KSMBD_TRANSPORT_RDMA_H__ */
diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c
new file mode 100644
index 000000000000..eff7a1d793f0
--- /dev/null
+++ b/fs/smb/server/transport_tcp.c
@@ -0,0 +1,649 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/freezer.h>
+
+#include "smb_common.h"
+#include "server.h"
+#include "auth.h"
+#include "connection.h"
+#include "transport_tcp.h"
+
+#define IFACE_STATE_DOWN BIT(0)
+#define IFACE_STATE_CONFIGURED BIT(1)
+
+static atomic_t active_num_conn;
+
+struct interface {
+ struct task_struct *ksmbd_kthread;
+ struct socket *ksmbd_socket;
+ struct list_head entry;
+ char *name;
+ struct mutex sock_release_lock;
+ int state;
+};
+
+static LIST_HEAD(iface_list);
+
+static int bind_additional_ifaces;
+
+struct tcp_transport {
+ struct ksmbd_transport transport;
+ struct socket *sock;
+ struct kvec *iov;
+ unsigned int nr_iov;
+};
+
+static struct ksmbd_transport_ops ksmbd_tcp_transport_ops;
+
+static void tcp_stop_kthread(struct task_struct *kthread);
+static struct interface *alloc_iface(char *ifname);
+
+#define KSMBD_TRANS(t) (&(t)->transport)
+#define TCP_TRANS(t) ((struct tcp_transport *)container_of(t, \
+ struct tcp_transport, transport))
+
+static inline void ksmbd_tcp_nodelay(struct socket *sock)
+{
+ tcp_sock_set_nodelay(sock->sk);
+}
+
+static inline void ksmbd_tcp_reuseaddr(struct socket *sock)
+{
+ sock_set_reuseaddr(sock->sk);
+}
+
+static inline void ksmbd_tcp_rcv_timeout(struct socket *sock, s64 secs)
+{
+ lock_sock(sock->sk);
+ if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1)
+ sock->sk->sk_rcvtimeo = secs * HZ;
+ else
+ sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
+ release_sock(sock->sk);
+}
+
+static inline void ksmbd_tcp_snd_timeout(struct socket *sock, s64 secs)
+{
+ sock_set_sndtimeo(sock->sk, secs);
+}
+
+static struct tcp_transport *alloc_transport(struct socket *client_sk)
+{
+ struct tcp_transport *t;
+ struct ksmbd_conn *conn;
+
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
+ if (!t)
+ return NULL;
+ t->sock = client_sk;
+
+ conn = ksmbd_conn_alloc();
+ if (!conn) {
+ kfree(t);
+ return NULL;
+ }
+
+ conn->transport = KSMBD_TRANS(t);
+ KSMBD_TRANS(t)->conn = conn;
+ KSMBD_TRANS(t)->ops = &ksmbd_tcp_transport_ops;
+ return t;
+}
+
+static void free_transport(struct tcp_transport *t)
+{
+ kernel_sock_shutdown(t->sock, SHUT_RDWR);
+ sock_release(t->sock);
+ t->sock = NULL;
+
+ ksmbd_conn_free(KSMBD_TRANS(t)->conn);
+ kfree(t->iov);
+ kfree(t);
+}
+
+/**
+ * kvec_array_init() - initialize a IO vector segment
+ * @new: IO vector to be initialized
+ * @iov: base IO vector
+ * @nr_segs: number of segments in base iov
+ * @bytes: total iovec length so far for read
+ *
+ * Return: Number of IO segments
+ */
+static unsigned int kvec_array_init(struct kvec *new, struct kvec *iov,
+ unsigned int nr_segs, size_t bytes)
+{
+ size_t base = 0;
+
+ while (bytes || !iov->iov_len) {
+ int copy = min(bytes, iov->iov_len);
+
+ bytes -= copy;
+ base += copy;
+ if (iov->iov_len == base) {
+ iov++;
+ nr_segs--;
+ base = 0;
+ }
+ }
+
+ memcpy(new, iov, sizeof(*iov) * nr_segs);
+ new->iov_base += base;
+ new->iov_len -= base;
+ return nr_segs;
+}
+
+/**
+ * get_conn_iovec() - get connection iovec for reading from socket
+ * @t: TCP transport instance
+ * @nr_segs: number of segments in iov
+ *
+ * Return: return existing or newly allocate iovec
+ */
+static struct kvec *get_conn_iovec(struct tcp_transport *t, unsigned int nr_segs)
+{
+ struct kvec *new_iov;
+
+ if (t->iov && nr_segs <= t->nr_iov)
+ return t->iov;
+
+ /* not big enough -- allocate a new one and release the old */
+ new_iov = kmalloc_array(nr_segs, sizeof(*new_iov), GFP_KERNEL);
+ if (new_iov) {
+ kfree(t->iov);
+ t->iov = new_iov;
+ t->nr_iov = nr_segs;
+ }
+ return new_iov;
+}
+
+static unsigned short ksmbd_tcp_get_port(const struct sockaddr *sa)
+{
+ switch (sa->sa_family) {
+ case AF_INET:
+ return ntohs(((struct sockaddr_in *)sa)->sin_port);
+ case AF_INET6:
+ return ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
+ }
+ return 0;
+}
+
+/**
+ * ksmbd_tcp_new_connection() - create a new tcp session on mount
+ * @client_sk: socket associated with new connection
+ *
+ * whenever a new connection is requested, create a conn thread
+ * (session thread) to handle new incoming smb requests from the connection
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int ksmbd_tcp_new_connection(struct socket *client_sk)
+{
+ struct sockaddr *csin;
+ int rc = 0;
+ struct tcp_transport *t;
+
+ t = alloc_transport(client_sk);
+ if (!t) {
+ sock_release(client_sk);
+ return -ENOMEM;
+ }
+
+ csin = KSMBD_TCP_PEER_SOCKADDR(KSMBD_TRANS(t)->conn);
+ if (kernel_getpeername(client_sk, csin) < 0) {
+ pr_err("client ip resolution failed\n");
+ rc = -EINVAL;
+ goto out_error;
+ }
+
+ KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop,
+ KSMBD_TRANS(t)->conn,
+ "ksmbd:%u",
+ ksmbd_tcp_get_port(csin));
+ if (IS_ERR(KSMBD_TRANS(t)->handler)) {
+ pr_err("cannot start conn thread\n");
+ rc = PTR_ERR(KSMBD_TRANS(t)->handler);
+ free_transport(t);
+ }
+ return rc;
+
+out_error:
+ free_transport(t);
+ return rc;
+}
+
+/**
+ * ksmbd_kthread_fn() - listen to new SMB connections and callback server
+ * @p: arguments to forker thread
+ *
+ * Return: 0 on success, error number otherwise
+ */
+static int ksmbd_kthread_fn(void *p)
+{
+ struct socket *client_sk = NULL;
+ struct interface *iface = (struct interface *)p;
+ int ret;
+
+ while (!kthread_should_stop()) {
+ mutex_lock(&iface->sock_release_lock);
+ if (!iface->ksmbd_socket) {
+ mutex_unlock(&iface->sock_release_lock);
+ break;
+ }
+ ret = kernel_accept(iface->ksmbd_socket, &client_sk,
+ SOCK_NONBLOCK);
+ mutex_unlock(&iface->sock_release_lock);
+ if (ret) {
+ if (ret == -EAGAIN)
+ /* check for new connections every 100 msecs */
+ schedule_timeout_interruptible(HZ / 10);
+ continue;
+ }
+
+ if (server_conf.max_connections &&
+ atomic_inc_return(&active_num_conn) >= server_conf.max_connections) {
+ pr_info_ratelimited("Limit the maximum number of connections(%u)\n",
+ atomic_read(&active_num_conn));
+ atomic_dec(&active_num_conn);
+ sock_release(client_sk);
+ continue;
+ }
+
+ ksmbd_debug(CONN, "connect success: accepted new connection\n");
+ client_sk->sk->sk_rcvtimeo = KSMBD_TCP_RECV_TIMEOUT;
+ client_sk->sk->sk_sndtimeo = KSMBD_TCP_SEND_TIMEOUT;
+
+ ksmbd_tcp_new_connection(client_sk);
+ }
+
+ ksmbd_debug(CONN, "releasing socket\n");
+ return 0;
+}
+
+/**
+ * ksmbd_tcp_run_kthread() - start forker thread
+ * @iface: pointer to struct interface
+ *
+ * start forker thread(ksmbd/0) at module init time to listen
+ * on port 445 for new SMB connection requests. It creates per connection
+ * server threads(ksmbd/x)
+ *
+ * Return: 0 on success or error number
+ */
+static int ksmbd_tcp_run_kthread(struct interface *iface)
+{
+ int rc;
+ struct task_struct *kthread;
+
+ kthread = kthread_run(ksmbd_kthread_fn, (void *)iface, "ksmbd-%s",
+ iface->name);
+ if (IS_ERR(kthread)) {
+ rc = PTR_ERR(kthread);
+ return rc;
+ }
+ iface->ksmbd_kthread = kthread;
+
+ return 0;
+}
+
+/**
+ * ksmbd_tcp_readv() - read data from socket in given iovec
+ * @t: TCP transport instance
+ * @iov_orig: base IO vector
+ * @nr_segs: number of segments in base iov
+ * @to_read: number of bytes to read from socket
+ * @max_retries: maximum retry count
+ *
+ * Return: on success return number of bytes read from socket,
+ * otherwise return error number
+ */
+static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
+ unsigned int nr_segs, unsigned int to_read,
+ int max_retries)
+{
+ int length = 0;
+ int total_read;
+ unsigned int segs;
+ struct msghdr ksmbd_msg;
+ struct kvec *iov;
+ struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn;
+
+ iov = get_conn_iovec(t, nr_segs);
+ if (!iov)
+ return -ENOMEM;
+
+ ksmbd_msg.msg_control = NULL;
+ ksmbd_msg.msg_controllen = 0;
+
+ for (total_read = 0; to_read; total_read += length, to_read -= length) {
+ try_to_freeze();
+
+ if (!ksmbd_conn_alive(conn)) {
+ total_read = -ESHUTDOWN;
+ break;
+ }
+ segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
+
+ length = kernel_recvmsg(t->sock, &ksmbd_msg,
+ iov, segs, to_read, 0);
+
+ if (length == -EINTR) {
+ total_read = -ESHUTDOWN;
+ break;
+ } else if (ksmbd_conn_need_reconnect(conn)) {
+ total_read = -EAGAIN;
+ break;
+ } else if (length == -ERESTARTSYS || length == -EAGAIN) {
+ /*
+ * If max_retries is negative, Allow unlimited
+ * retries to keep connection with inactive sessions.
+ */
+ if (max_retries == 0) {
+ total_read = length;
+ break;
+ } else if (max_retries > 0) {
+ max_retries--;
+ }
+
+ usleep_range(1000, 2000);
+ length = 0;
+ continue;
+ } else if (length <= 0) {
+ total_read = length;
+ break;
+ }
+ }
+ return total_read;
+}
+
+/**
+ * ksmbd_tcp_read() - read data from socket in given buffer
+ * @t: TCP transport instance
+ * @buf: buffer to store read data from socket
+ * @to_read: number of bytes to read from socket
+ *
+ * Return: on success return number of bytes read from socket,
+ * otherwise return error number
+ */
+static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf,
+ unsigned int to_read, int max_retries)
+{
+ struct kvec iov;
+
+ iov.iov_base = buf;
+ iov.iov_len = to_read;
+
+ return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read, max_retries);
+}
+
+static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,
+ int nvecs, int size, bool need_invalidate,
+ unsigned int remote_key)
+
+{
+ struct msghdr smb_msg = {.msg_flags = MSG_NOSIGNAL};
+
+ return kernel_sendmsg(TCP_TRANS(t)->sock, &smb_msg, iov, nvecs, size);
+}
+
+static void ksmbd_tcp_disconnect(struct ksmbd_transport *t)
+{
+ free_transport(TCP_TRANS(t));
+ if (server_conf.max_connections)
+ atomic_dec(&active_num_conn);
+}
+
+static void tcp_destroy_socket(struct socket *ksmbd_socket)
+{
+ int ret;
+
+ if (!ksmbd_socket)
+ return;
+
+ /* set zero to timeout */
+ ksmbd_tcp_rcv_timeout(ksmbd_socket, 0);
+ ksmbd_tcp_snd_timeout(ksmbd_socket, 0);
+
+ ret = kernel_sock_shutdown(ksmbd_socket, SHUT_RDWR);
+ if (ret)
+ pr_err("Failed to shutdown socket: %d\n", ret);
+ sock_release(ksmbd_socket);
+}
+
+/**
+ * create_socket - create socket for ksmbd/0
+ *
+ * Return: 0 on success, error number otherwise
+ */
+static int create_socket(struct interface *iface)
+{
+ int ret;
+ struct sockaddr_in6 sin6;
+ struct sockaddr_in sin;
+ struct socket *ksmbd_socket;
+ bool ipv4 = false;
+
+ ret = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &ksmbd_socket);
+ if (ret) {
+ if (ret != -EAFNOSUPPORT)
+ pr_err("Can't create socket for ipv6, fallback to ipv4: %d\n", ret);
+ ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP,
+ &ksmbd_socket);
+ if (ret) {
+ pr_err("Can't create socket for ipv4: %d\n", ret);
+ goto out_clear;
+ }
+
+ sin.sin_family = PF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = htons(server_conf.tcp_port);
+ ipv4 = true;
+ } else {
+ sin6.sin6_family = PF_INET6;
+ sin6.sin6_addr = in6addr_any;
+ sin6.sin6_port = htons(server_conf.tcp_port);
+ }
+
+ ksmbd_tcp_nodelay(ksmbd_socket);
+ ksmbd_tcp_reuseaddr(ksmbd_socket);
+
+ ret = sock_setsockopt(ksmbd_socket,
+ SOL_SOCKET,
+ SO_BINDTODEVICE,
+ KERNEL_SOCKPTR(iface->name),
+ strlen(iface->name));
+ if (ret != -ENODEV && ret < 0) {
+ pr_err("Failed to set SO_BINDTODEVICE: %d\n", ret);
+ goto out_error;
+ }
+
+ if (ipv4)
+ ret = kernel_bind(ksmbd_socket, (struct sockaddr *)&sin,
+ sizeof(sin));
+ else
+ ret = kernel_bind(ksmbd_socket, (struct sockaddr *)&sin6,
+ sizeof(sin6));
+ if (ret) {
+ pr_err("Failed to bind socket: %d\n", ret);
+ goto out_error;
+ }
+
+ ksmbd_socket->sk->sk_rcvtimeo = KSMBD_TCP_RECV_TIMEOUT;
+ ksmbd_socket->sk->sk_sndtimeo = KSMBD_TCP_SEND_TIMEOUT;
+
+ ret = kernel_listen(ksmbd_socket, KSMBD_SOCKET_BACKLOG);
+ if (ret) {
+ pr_err("Port listen() error: %d\n", ret);
+ goto out_error;
+ }
+
+ iface->ksmbd_socket = ksmbd_socket;
+ ret = ksmbd_tcp_run_kthread(iface);
+ if (ret) {
+ pr_err("Can't start ksmbd main kthread: %d\n", ret);
+ goto out_error;
+ }
+ iface->state = IFACE_STATE_CONFIGURED;
+
+ return 0;
+
+out_error:
+ tcp_destroy_socket(ksmbd_socket);
+out_clear:
+ iface->ksmbd_socket = NULL;
+ return ret;
+}
+
+static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
+ void *ptr)
+{
+ struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
+ struct interface *iface;
+ int ret, found = 0;
+
+ switch (event) {
+ case NETDEV_UP:
+ if (netif_is_bridge_port(netdev))
+ return NOTIFY_OK;
+
+ list_for_each_entry(iface, &iface_list, entry) {
+ if (!strcmp(iface->name, netdev->name)) {
+ found = 1;
+ if (iface->state != IFACE_STATE_DOWN)
+ break;
+ ret = create_socket(iface);
+ if (ret)
+ return NOTIFY_OK;
+ break;
+ }
+ }
+ if (!found && bind_additional_ifaces) {
+ iface = alloc_iface(kstrdup(netdev->name, GFP_KERNEL));
+ if (!iface)
+ return NOTIFY_OK;
+ ret = create_socket(iface);
+ if (ret)
+ break;
+ }
+ break;
+ case NETDEV_DOWN:
+ list_for_each_entry(iface, &iface_list, entry) {
+ if (!strcmp(iface->name, netdev->name) &&
+ iface->state == IFACE_STATE_CONFIGURED) {
+ tcp_stop_kthread(iface->ksmbd_kthread);
+ iface->ksmbd_kthread = NULL;
+ mutex_lock(&iface->sock_release_lock);
+ tcp_destroy_socket(iface->ksmbd_socket);
+ iface->ksmbd_socket = NULL;
+ mutex_unlock(&iface->sock_release_lock);
+
+ iface->state = IFACE_STATE_DOWN;
+ break;
+ }
+ }
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ksmbd_netdev_notifier = {
+ .notifier_call = ksmbd_netdev_event,
+};
+
+int ksmbd_tcp_init(void)
+{
+ register_netdevice_notifier(&ksmbd_netdev_notifier);
+
+ return 0;
+}
+
+static void tcp_stop_kthread(struct task_struct *kthread)
+{
+ int ret;
+
+ if (!kthread)
+ return;
+
+ ret = kthread_stop(kthread);
+ if (ret)
+ pr_err("failed to stop forker thread\n");
+}
+
+void ksmbd_tcp_destroy(void)
+{
+ struct interface *iface, *tmp;
+
+ unregister_netdevice_notifier(&ksmbd_netdev_notifier);
+
+ list_for_each_entry_safe(iface, tmp, &iface_list, entry) {
+ list_del(&iface->entry);
+ kfree(iface->name);
+ kfree(iface);
+ }
+}
+
+static struct interface *alloc_iface(char *ifname)
+{
+ struct interface *iface;
+
+ if (!ifname)
+ return NULL;
+
+ iface = kzalloc(sizeof(struct interface), GFP_KERNEL);
+ if (!iface) {
+ kfree(ifname);
+ return NULL;
+ }
+
+ iface->name = ifname;
+ iface->state = IFACE_STATE_DOWN;
+ list_add(&iface->entry, &iface_list);
+ mutex_init(&iface->sock_release_lock);
+ return iface;
+}
+
+int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz)
+{
+ int sz = 0;
+
+ if (!ifc_list_sz) {
+ struct net_device *netdev;
+
+ rtnl_lock();
+ for_each_netdev(&init_net, netdev) {
+ if (netif_is_bridge_port(netdev))
+ continue;
+ if (!alloc_iface(kstrdup(netdev->name, GFP_KERNEL)))
+ return -ENOMEM;
+ }
+ rtnl_unlock();
+ bind_additional_ifaces = 1;
+ return 0;
+ }
+
+ while (ifc_list_sz > 0) {
+ if (!alloc_iface(kstrdup(ifc_list, GFP_KERNEL)))
+ return -ENOMEM;
+
+ sz = strlen(ifc_list);
+ if (!sz)
+ break;
+
+ ifc_list += sz + 1;
+ ifc_list_sz -= (sz + 1);
+ }
+
+ bind_additional_ifaces = 0;
+
+ return 0;
+}
+
+static struct ksmbd_transport_ops ksmbd_tcp_transport_ops = {
+ .read = ksmbd_tcp_read,
+ .writev = ksmbd_tcp_writev,
+ .disconnect = ksmbd_tcp_disconnect,
+};
diff --git a/fs/smb/server/transport_tcp.h b/fs/smb/server/transport_tcp.h
new file mode 100644
index 000000000000..e338bebe322f
--- /dev/null
+++ b/fs/smb/server/transport_tcp.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __KSMBD_TRANSPORT_TCP_H__
+#define __KSMBD_TRANSPORT_TCP_H__
+
+int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz);
+int ksmbd_tcp_init(void);
+void ksmbd_tcp_destroy(void);
+
+#endif /* __KSMBD_TRANSPORT_TCP_H__ */
diff --git a/fs/smb/server/unicode.c b/fs/smb/server/unicode.c
new file mode 100644
index 000000000000..a0db699ddafd
--- /dev/null
+++ b/fs/smb/server/unicode.c
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Some of the source code in this file came from fs/cifs/cifs_unicode.c
+ *
+ * Copyright (c) International Business Machines Corp., 2000,2009
+ * Modified by Steve French (sfrench@us.ibm.com)
+ * Modified by Namjae Jeon (linkinjeon@kernel.org)
+ */
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+#include "glob.h"
+#include "unicode.h"
+#include "uniupr.h"
+#include "smb_common.h"
+
+/*
+ * smb_utf16_bytes() - how long will a string be after conversion?
+ * @from: pointer to input string
+ * @maxbytes: don't go past this many bytes of input string
+ * @codepage: destination codepage
+ *
+ * Walk a utf16le string and return the number of bytes that the string will
+ * be after being converted to the given charset, not including any null
+ * termination required. Don't walk past maxbytes in the source buffer.
+ *
+ * Return: string length after conversion
+ */
+static int smb_utf16_bytes(const __le16 *from, int maxbytes,
+ const struct nls_table *codepage)
+{
+ int i;
+ int charlen, outlen = 0;
+ int maxwords = maxbytes / 2;
+ char tmp[NLS_MAX_CHARSET_SIZE];
+ __u16 ftmp;
+
+ for (i = 0; i < maxwords; i++) {
+ ftmp = get_unaligned_le16(&from[i]);
+ if (ftmp == 0)
+ break;
+
+ charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE);
+ if (charlen > 0)
+ outlen += charlen;
+ else
+ outlen++;
+ }
+
+ return outlen;
+}
+
+/*
+ * cifs_mapchar() - convert a host-endian char to proper char in codepage
+ * @target: where converted character should be copied
+ * @src_char: 2 byte host-endian source character
+ * @cp: codepage to which character should be converted
+ * @mapchar: should character be mapped according to mapchars mount option?
+ *
+ * This function handles the conversion of a single character. It is the
+ * responsibility of the caller to ensure that the target buffer is large
+ * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
+ *
+ * Return: string length after conversion
+ */
+static int
+cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
+ bool mapchar)
+{
+ int len = 1;
+
+ if (!mapchar)
+ goto cp_convert;
+
+ /*
+ * BB: Cannot handle remapping UNI_SLASH until all the calls to
+ * build_path_from_dentry are modified, as they use slash as
+ * separator.
+ */
+ switch (src_char) {
+ case UNI_COLON:
+ *target = ':';
+ break;
+ case UNI_ASTERISK:
+ *target = '*';
+ break;
+ case UNI_QUESTION:
+ *target = '?';
+ break;
+ case UNI_PIPE:
+ *target = '|';
+ break;
+ case UNI_GRTRTHAN:
+ *target = '>';
+ break;
+ case UNI_LESSTHAN:
+ *target = '<';
+ break;
+ default:
+ goto cp_convert;
+ }
+
+out:
+ return len;
+
+cp_convert:
+ len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE);
+ if (len <= 0) {
+ *target = '?';
+ len = 1;
+ }
+
+ goto out;
+}
+
+/*
+ * is_char_allowed() - check for valid character
+ * @ch: input character to be checked
+ *
+ * Return: 1 if char is allowed, otherwise 0
+ */
+static inline int is_char_allowed(char *ch)
+{
+ /* check for control chars, wildcards etc. */
+ if (!(*ch & 0x80) &&
+ (*ch <= 0x1f ||
+ *ch == '?' || *ch == '"' || *ch == '<' ||
+ *ch == '>' || *ch == '|'))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * smb_from_utf16() - convert utf16le string to local charset
+ * @to: destination buffer
+ * @from: source buffer
+ * @tolen: destination buffer size (in bytes)
+ * @fromlen: source buffer size (in bytes)
+ * @codepage: codepage to which characters should be converted
+ * @mapchar: should characters be remapped according to the mapchars option?
+ *
+ * Convert a little-endian utf16le string (as sent by the server) to a string
+ * in the provided codepage. The tolen and fromlen parameters are to ensure
+ * that the code doesn't walk off of the end of the buffer (which is always
+ * a danger if the alignment of the source buffer is off). The destination
+ * string is always properly null terminated and fits in the destination
+ * buffer. Returns the length of the destination string in bytes (including
+ * null terminator).
+ *
+ * Note that some windows versions actually send multiword UTF-16 characters
+ * instead of straight UTF16-2. The linux nls routines however aren't able to
+ * deal with those characters properly. In the event that we get some of
+ * those characters, they won't be translated properly.
+ *
+ * Return: string length after conversion
+ */
+static int smb_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
+ const struct nls_table *codepage, bool mapchar)
+{
+ int i, charlen, safelen;
+ int outlen = 0;
+ int nullsize = nls_nullsize(codepage);
+ int fromwords = fromlen / 2;
+ char tmp[NLS_MAX_CHARSET_SIZE];
+ __u16 ftmp;
+
+ /*
+ * because the chars can be of varying widths, we need to take care
+ * not to overflow the destination buffer when we get close to the
+ * end of it. Until we get to this offset, we don't need to check
+ * for overflow however.
+ */
+ safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
+
+ for (i = 0; i < fromwords; i++) {
+ ftmp = get_unaligned_le16(&from[i]);
+ if (ftmp == 0)
+ break;
+
+ /*
+ * check to see if converting this character might make the
+ * conversion bleed into the null terminator
+ */
+ if (outlen >= safelen) {
+ charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar);
+ if ((outlen + charlen) > (tolen - nullsize))
+ break;
+ }
+
+ /* put converted char into 'to' buffer */
+ charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar);
+ outlen += charlen;
+ }
+
+ /* properly null-terminate string */
+ for (i = 0; i < nullsize; i++)
+ to[outlen++] = 0;
+
+ return outlen;
+}
+
+/*
+ * smb_strtoUTF16() - Convert character string to unicode string
+ * @to: destination buffer
+ * @from: source buffer
+ * @len: destination buffer size (in bytes)
+ * @codepage: codepage to which characters should be converted
+ *
+ * Return: string length after conversion
+ */
+int smb_strtoUTF16(__le16 *to, const char *from, int len,
+ const struct nls_table *codepage)
+{
+ int charlen;
+ int i;
+ wchar_t wchar_to; /* needed to quiet sparse */
+
+ /* special case for utf8 to handle no plane0 chars */
+ if (!strcmp(codepage->charset, "utf8")) {
+ /*
+ * convert utf8 -> utf16, we assume we have enough space
+ * as caller should have assumed conversion does not overflow
+ * in destination len is length in wchar_t units (16bits)
+ */
+ i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN,
+ (wchar_t *)to, len);
+
+ /* if success terminate and exit */
+ if (i >= 0)
+ goto success;
+ /*
+ * if fails fall back to UCS encoding as this
+ * function should not return negative values
+ * currently can fail only if source contains
+ * invalid encoded characters
+ */
+ }
+
+ for (i = 0; len > 0 && *from; i++, from += charlen, len -= charlen) {
+ charlen = codepage->char2uni(from, len, &wchar_to);
+ if (charlen < 1) {
+ /* A question mark */
+ wchar_to = 0x003f;
+ charlen = 1;
+ }
+ put_unaligned_le16(wchar_to, &to[i]);
+ }
+
+success:
+ put_unaligned_le16(0, &to[i]);
+ return i;
+}
+
+/*
+ * smb_strndup_from_utf16() - copy a string from wire format to the local
+ * codepage
+ * @src: source string
+ * @maxlen: don't walk past this many bytes in the source string
+ * @is_unicode: is this a unicode string?
+ * @codepage: destination codepage
+ *
+ * Take a string given by the server, convert it to the local codepage and
+ * put it in a new buffer. Returns a pointer to the new string or NULL on
+ * error.
+ *
+ * Return: destination string buffer or error ptr
+ */
+char *smb_strndup_from_utf16(const char *src, const int maxlen,
+ const bool is_unicode,
+ const struct nls_table *codepage)
+{
+ int len, ret;
+ char *dst;
+
+ if (is_unicode) {
+ len = smb_utf16_bytes((__le16 *)src, maxlen, codepage);
+ len += nls_nullsize(codepage);
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst)
+ return ERR_PTR(-ENOMEM);
+ ret = smb_from_utf16(dst, (__le16 *)src, len, maxlen, codepage,
+ false);
+ if (ret < 0) {
+ kfree(dst);
+ return ERR_PTR(-EINVAL);
+ }
+ } else {
+ len = strnlen(src, maxlen);
+ len++;
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst)
+ return ERR_PTR(-ENOMEM);
+ strscpy(dst, src, len);
+ }
+
+ return dst;
+}
+
+/*
+ * Convert 16 bit Unicode pathname to wire format from string in current code
+ * page. Conversion may involve remapping up the six characters that are
+ * only legal in POSIX-like OS (if they are present in the string). Path
+ * names are little endian 16 bit Unicode on the wire
+ */
+/*
+ * smbConvertToUTF16() - convert string from local charset to utf16
+ * @target: destination buffer
+ * @source: source buffer
+ * @srclen: source buffer size (in bytes)
+ * @cp: codepage to which characters should be converted
+ * @mapchar: should characters be remapped according to the mapchars option?
+ *
+ * Convert 16 bit Unicode pathname to wire format from string in current code
+ * page. Conversion may involve remapping up the six characters that are
+ * only legal in POSIX-like OS (if they are present in the string). Path
+ * names are little endian 16 bit Unicode on the wire
+ *
+ * Return: char length after conversion
+ */
+int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
+ const struct nls_table *cp, int mapchars)
+{
+ int i, j, charlen;
+ char src_char;
+ __le16 dst_char;
+ wchar_t tmp;
+
+ if (!mapchars)
+ return smb_strtoUTF16(target, source, srclen, cp);
+
+ for (i = 0, j = 0; i < srclen; j++) {
+ src_char = source[i];
+ charlen = 1;
+ switch (src_char) {
+ case 0:
+ put_unaligned(0, &target[j]);
+ return j;
+ case ':':
+ dst_char = cpu_to_le16(UNI_COLON);
+ break;
+ case '*':
+ dst_char = cpu_to_le16(UNI_ASTERISK);
+ break;
+ case '?':
+ dst_char = cpu_to_le16(UNI_QUESTION);
+ break;
+ case '<':
+ dst_char = cpu_to_le16(UNI_LESSTHAN);
+ break;
+ case '>':
+ dst_char = cpu_to_le16(UNI_GRTRTHAN);
+ break;
+ case '|':
+ dst_char = cpu_to_le16(UNI_PIPE);
+ break;
+ /*
+ * FIXME: We can not handle remapping backslash (UNI_SLASH)
+ * until all the calls to build_path_from_dentry are modified,
+ * as they use backslash as separator.
+ */
+ default:
+ charlen = cp->char2uni(source + i, srclen - i, &tmp);
+ dst_char = cpu_to_le16(tmp);
+
+ /*
+ * if no match, use question mark, which at least in
+ * some cases serves as wild card
+ */
+ if (charlen < 1) {
+ dst_char = cpu_to_le16(0x003f);
+ charlen = 1;
+ }
+ }
+ /*
+ * character may take more than one byte in the source string,
+ * but will take exactly two bytes in the target string
+ */
+ i += charlen;
+ put_unaligned(dst_char, &target[j]);
+ }
+
+ return j;
+}
diff --git a/fs/smb/server/unicode.h b/fs/smb/server/unicode.h
new file mode 100644
index 000000000000..076f6034a789
--- /dev/null
+++ b/fs/smb/server/unicode.h
@@ -0,0 +1,358 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Some of the source code in this file came from fs/cifs/cifs_unicode.c
+ * cifs_unicode: Unicode kernel case support
+ *
+ * Function:
+ * Convert a unicode character to upper or lower case using
+ * compressed tables.
+ *
+ * Copyright (c) International Business Machines Corp., 2000,2009
+ *
+ *
+ * Notes:
+ * These APIs are based on the C library functions. The semantics
+ * should match the C functions but with expanded size operands.
+ *
+ * The upper/lower functions are based on a table created by mkupr.
+ * This is a compressed table of upper and lower case conversion.
+ *
+ */
+#ifndef _CIFS_UNICODE_H
+#define _CIFS_UNICODE_H
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <linux/nls.h>
+#include <linux/unicode.h>
+
+#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
+
+/*
+ * Windows maps these to the user defined 16 bit Unicode range since they are
+ * reserved symbols (along with \ and /), otherwise illegal to store
+ * in filenames in NTFS
+ */
+#define UNI_ASTERISK ((__u16)('*' + 0xF000))
+#define UNI_QUESTION ((__u16)('?' + 0xF000))
+#define UNI_COLON ((__u16)(':' + 0xF000))
+#define UNI_GRTRTHAN ((__u16)('>' + 0xF000))
+#define UNI_LESSTHAN ((__u16)('<' + 0xF000))
+#define UNI_PIPE ((__u16)('|' + 0xF000))
+#define UNI_SLASH ((__u16)('\\' + 0xF000))
+
+/* Just define what we want from uniupr.h. We don't want to define the tables
+ * in each source file.
+ */
+#ifndef UNICASERANGE_DEFINED
+struct UniCaseRange {
+ wchar_t start;
+ wchar_t end;
+ signed char *table;
+};
+#endif /* UNICASERANGE_DEFINED */
+
+#ifndef UNIUPR_NOUPPER
+extern signed char SmbUniUpperTable[512];
+extern const struct UniCaseRange SmbUniUpperRange[];
+#endif /* UNIUPR_NOUPPER */
+
+#ifndef UNIUPR_NOLOWER
+extern signed char CifsUniLowerTable[512];
+extern const struct UniCaseRange CifsUniLowerRange[];
+#endif /* UNIUPR_NOLOWER */
+
+#ifdef __KERNEL__
+int smb_strtoUTF16(__le16 *to, const char *from, int len,
+ const struct nls_table *codepage);
+char *smb_strndup_from_utf16(const char *src, const int maxlen,
+ const bool is_unicode,
+ const struct nls_table *codepage);
+int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
+ const struct nls_table *cp, int mapchars);
+char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
+#endif
+
+/*
+ * UniStrcat: Concatenate the second string to the first
+ *
+ * Returns:
+ * Address of the first string
+ */
+static inline wchar_t *UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)
+{
+ wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
+
+ while (*ucs1++)
+ /*NULL*/; /* To end of first string */
+ ucs1--; /* Return to the null */
+ while ((*ucs1++ = *ucs2++))
+ /*NULL*/; /* copy string 2 over */
+ return anchor;
+}
+
+/*
+ * UniStrchr: Find a character in a string
+ *
+ * Returns:
+ * Address of first occurrence of character in string
+ * or NULL if the character is not in the string
+ */
+static inline wchar_t *UniStrchr(const wchar_t *ucs, wchar_t uc)
+{
+ while ((*ucs != uc) && *ucs)
+ ucs++;
+
+ if (*ucs == uc)
+ return (wchar_t *)ucs;
+ return NULL;
+}
+
+/*
+ * UniStrcmp: Compare two strings
+ *
+ * Returns:
+ * < 0: First string is less than second
+ * = 0: Strings are equal
+ * > 0: First string is greater than second
+ */
+static inline int UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
+{
+ while ((*ucs1 == *ucs2) && *ucs1) {
+ ucs1++;
+ ucs2++;
+ }
+ return (int)*ucs1 - (int)*ucs2;
+}
+
+/*
+ * UniStrcpy: Copy a string
+ */
+static inline wchar_t *UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
+{
+ wchar_t *anchor = ucs1; /* save the start of result string */
+
+ while ((*ucs1++ = *ucs2++))
+ /*NULL*/;
+ return anchor;
+}
+
+/*
+ * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
+ */
+static inline size_t UniStrlen(const wchar_t *ucs1)
+{
+ int i = 0;
+
+ while (*ucs1++)
+ i++;
+ return i;
+}
+
+/*
+ * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
+ * string (length limited)
+ */
+static inline size_t UniStrnlen(const wchar_t *ucs1, int maxlen)
+{
+ int i = 0;
+
+ while (*ucs1++) {
+ i++;
+ if (i >= maxlen)
+ break;
+ }
+ return i;
+}
+
+/*
+ * UniStrncat: Concatenate length limited string
+ */
+static inline wchar_t *UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ wchar_t *anchor = ucs1; /* save pointer to string 1 */
+
+ while (*ucs1++)
+ /*NULL*/;
+ ucs1--; /* point to null terminator of s1 */
+ while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
+ ucs1++;
+ ucs2++;
+ }
+ *ucs1 = 0; /* Null terminate the result */
+ return anchor;
+}
+
+/*
+ * UniStrncmp: Compare length limited string
+ */
+static inline int UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ if (!n)
+ return 0; /* Null strings are equal */
+ while ((*ucs1 == *ucs2) && *ucs1 && --n) {
+ ucs1++;
+ ucs2++;
+ }
+ return (int)*ucs1 - (int)*ucs2;
+}
+
+/*
+ * UniStrncmp_le: Compare length limited string - native to little-endian
+ */
+static inline int
+UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ if (!n)
+ return 0; /* Null strings are equal */
+ while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
+ ucs1++;
+ ucs2++;
+ }
+ return (int)*ucs1 - (int)__le16_to_cpu(*ucs2);
+}
+
+/*
+ * UniStrncpy: Copy length limited string with pad
+ */
+static inline wchar_t *UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ wchar_t *anchor = ucs1;
+
+ while (n-- && *ucs2) /* Copy the strings */
+ *ucs1++ = *ucs2++;
+
+ n++;
+ while (n--) /* Pad with nulls */
+ *ucs1++ = 0;
+ return anchor;
+}
+
+/*
+ * UniStrncpy_le: Copy length limited string with pad to little-endian
+ */
+static inline wchar_t *UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
+{
+ wchar_t *anchor = ucs1;
+
+ while (n-- && *ucs2) /* Copy the strings */
+ *ucs1++ = __le16_to_cpu(*ucs2++);
+
+ n++;
+ while (n--) /* Pad with nulls */
+ *ucs1++ = 0;
+ return anchor;
+}
+
+/*
+ * UniStrstr: Find a string in a string
+ *
+ * Returns:
+ * Address of first match found
+ * NULL if no matching string is found
+ */
+static inline wchar_t *UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
+{
+ const wchar_t *anchor1 = ucs1;
+ const wchar_t *anchor2 = ucs2;
+
+ while (*ucs1) {
+ if (*ucs1 == *ucs2) {
+ /* Partial match found */
+ ucs1++;
+ ucs2++;
+ } else {
+ if (!*ucs2) /* Match found */
+ return (wchar_t *)anchor1;
+ ucs1 = ++anchor1; /* No match */
+ ucs2 = anchor2;
+ }
+ }
+
+ if (!*ucs2) /* Both end together */
+ return (wchar_t *)anchor1; /* Match found */
+ return NULL; /* No match */
+}
+
+#ifndef UNIUPR_NOUPPER
+/*
+ * UniToupper: Convert a unicode character to upper case
+ */
+static inline wchar_t UniToupper(register wchar_t uc)
+{
+ register const struct UniCaseRange *rp;
+
+ if (uc < sizeof(SmbUniUpperTable)) {
+ /* Latin characters */
+ return uc + SmbUniUpperTable[uc]; /* Use base tables */
+ }
+
+ rp = SmbUniUpperRange; /* Use range tables */
+ while (rp->start) {
+ if (uc < rp->start) /* Before start of range */
+ return uc; /* Uppercase = input */
+ if (uc <= rp->end) /* In range */
+ return uc + rp->table[uc - rp->start];
+ rp++; /* Try next range */
+ }
+ return uc; /* Past last range */
+}
+
+/*
+ * UniStrupr: Upper case a unicode string
+ */
+static inline __le16 *UniStrupr(register __le16 *upin)
+{
+ register __le16 *up;
+
+ up = upin;
+ while (*up) { /* For all characters */
+ *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
+ up++;
+ }
+ return upin; /* Return input pointer */
+}
+#endif /* UNIUPR_NOUPPER */
+
+#ifndef UNIUPR_NOLOWER
+/*
+ * UniTolower: Convert a unicode character to lower case
+ */
+static inline wchar_t UniTolower(register wchar_t uc)
+{
+ register const struct UniCaseRange *rp;
+
+ if (uc < sizeof(CifsUniLowerTable)) {
+ /* Latin characters */
+ return uc + CifsUniLowerTable[uc]; /* Use base tables */
+ }
+
+ rp = CifsUniLowerRange; /* Use range tables */
+ while (rp->start) {
+ if (uc < rp->start) /* Before start of range */
+ return uc; /* Uppercase = input */
+ if (uc <= rp->end) /* In range */
+ return uc + rp->table[uc - rp->start];
+ rp++; /* Try next range */
+ }
+ return uc; /* Past last range */
+}
+
+/*
+ * UniStrlwr: Lower case a unicode string
+ */
+static inline wchar_t *UniStrlwr(register wchar_t *upin)
+{
+ register wchar_t *up;
+
+ up = upin;
+ while (*up) { /* For all characters */
+ *up = UniTolower(*up);
+ up++;
+ }
+ return upin; /* Return input pointer */
+}
+
+#endif
+
+#endif /* _CIFS_UNICODE_H */
diff --git a/fs/smb/server/uniupr.h b/fs/smb/server/uniupr.h
new file mode 100644
index 000000000000..26583b776897
--- /dev/null
+++ b/fs/smb/server/uniupr.h
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Some of the source code in this file came from fs/cifs/uniupr.h
+ * Copyright (c) International Business Machines Corp., 2000,2002
+ *
+ * uniupr.h - Unicode compressed case ranges
+ *
+ */
+#ifndef __KSMBD_UNIUPR_H
+#define __KSMBD_UNIUPR_H
+
+#ifndef UNIUPR_NOUPPER
+/*
+ * Latin upper case
+ */
+signed char SmbUniUpperTable[512] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, /* 060-06f */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, 0, 0, 0, 0, 0, /* 070-07f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
+ -32, -32, -32, -32, -32, -32, -32, 0, -32, -32,
+ -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
+ 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
+ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
+ 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
+ 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
+ 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
+ -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
+ 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
+ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
+ 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
+};
+
+/* Upper case range - Greek */
+static signed char UniCaseRangeU03a0[47] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, /* 3b0-3bf */
+ -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
+ -63, -63,
+};
+
+/* Upper case range - Cyrillic */
+static signed char UniCaseRangeU0430[48] = {
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, /* 430-43f */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, /* 440-44f */
+ 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
+ -80, -80, 0, -80, -80, /* 450-45f */
+};
+
+/* Upper case range - Extended cyrillic */
+static signed char UniCaseRangeU0490[61] = {
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
+ 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
+};
+
+/* Upper case range - Extended latin and greek */
+static signed char UniCaseRangeU1e00[509] = {
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
+ 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
+ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
+ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
+ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
+ 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
+ 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112,
+ 126, 126, 0, 0, /* 1f70-1f7f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
+ 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
+ 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
+ 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/* Upper case range - Wide latin */
+static signed char UniCaseRangeUff40[27] = {
+ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+ -32, -32, -32, -32, -32, /* ff40-ff4f */
+ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+};
+
+/*
+ * Upper Case Range
+ */
+const struct UniCaseRange SmbUniUpperRange[] = {
+ {0x03a0, 0x03ce, UniCaseRangeU03a0},
+ {0x0430, 0x045f, UniCaseRangeU0430},
+ {0x0490, 0x04cc, UniCaseRangeU0490},
+ {0x1e00, 0x1ffc, UniCaseRangeU1e00},
+ {0xff40, 0xff5a, UniCaseRangeUff40},
+ {0}
+};
+#endif
+
+#ifndef UNIUPR_NOLOWER
+/*
+ * Latin lower case
+ */
+signed char CifsUniLowerTable[512] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, /* 040-04f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0,
+ 0, 0, 0, /* 050-05f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, /* 0c0-0cf */
+ 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32,
+ 32, 32, 32, 0, /* 0d0-0df */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
+ 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
+ 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0,
+ 0, /* 170-17f */
+ 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79,
+ 0, /* 180-18f */
+ 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
+ 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
+ 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
+ 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
+ 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
+};
+
+/* Lower case range - Greek */
+static signed char UniCaseRangeL0380[44] = {
+ 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, /* 390-39f */
+ 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+};
+
+/* Lower case range - Cyrillic */
+static signed char UniCaseRangeL0400[48] = {
+ 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 0, 80, 80, /* 400-40f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, /* 410-41f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, /* 420-42f */
+};
+
+/* Lower case range - Extended cyrillic */
+static signed char UniCaseRangeL0490[60] = {
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
+ 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
+};
+
+/* Lower case range - Extended latin and greek */
+static signed char UniCaseRangeL1e00[504] = {
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
+ 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0,
+ 0, 0, /* 1fc0-1fcf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
+ 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0,
+ 0, 0, /* 1fe0-1fef */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/* Lower case range - Wide latin */
+static signed char UniCaseRangeLff20[27] = {
+ 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, /* ff20-ff2f */
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+};
+
+/*
+ * Lower Case Range
+ */
+const struct UniCaseRange CifsUniLowerRange[] = {
+ {0x0380, 0x03ab, UniCaseRangeL0380},
+ {0x0400, 0x042f, UniCaseRangeL0400},
+ {0x0490, 0x04cb, UniCaseRangeL0490},
+ {0x1e00, 0x1ff7, UniCaseRangeL1e00},
+ {0xff20, 0xff3a, UniCaseRangeLff20},
+ {0}
+};
+#endif
+
+#endif /* __KSMBD_UNIUPR_H */
diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
new file mode 100644
index 000000000000..36914db8b661
--- /dev/null
+++ b/fs/smb/server/vfs.c
@@ -0,0 +1,1911 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/backing-dev.h>
+#include <linux/writeback.h>
+#include <linux/xattr.h>
+#include <linux/falloc.h>
+#include <linux/fsnotify.h>
+#include <linux/dcache.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/sched/xacct.h>
+#include <linux/crc32c.h>
+
+#include "../../internal.h" /* for vfs_path_lookup */
+
+#include "glob.h"
+#include "oplock.h"
+#include "connection.h"
+#include "vfs.h"
+#include "vfs_cache.h"
+#include "smbacl.h"
+#include "ndr.h"
+#include "auth.h"
+#include "misc.h"
+
+#include "smb_common.h"
+#include "mgmt/share_config.h"
+#include "mgmt/tree_connect.h"
+#include "mgmt/user_session.h"
+#include "mgmt/user_config.h"
+
+static char *extract_last_component(char *path)
+{
+ char *p = strrchr(path, '/');
+
+ if (p && p[1] != '\0') {
+ *p = '\0';
+ p++;
+ } else {
+ p = NULL;
+ }
+ return p;
+}
+
+static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
+ struct inode *parent_inode,
+ struct inode *inode)
+{
+ if (!test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_INHERIT_OWNER))
+ return;
+
+ i_uid_write(inode, i_uid_read(parent_inode));
+}
+
+/**
+ * ksmbd_vfs_lock_parent() - lock parent dentry if it is stable
+ *
+ * the parent dentry got by dget_parent or @parent could be
+ * unstable, we try to lock a parent inode and lookup the
+ * child dentry again.
+ *
+ * the reference count of @parent isn't incremented.
+ */
+int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
+ struct dentry *child)
+{
+ struct dentry *dentry;
+ int ret = 0;
+
+ inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
+ dentry = lookup_one(user_ns, child->d_name.name, parent,
+ child->d_name.len);
+ if (IS_ERR(dentry)) {
+ ret = PTR_ERR(dentry);
+ goto out_err;
+ }
+
+ if (dentry != child) {
+ ret = -ESTALE;
+ dput(dentry);
+ goto out_err;
+ }
+
+ dput(dentry);
+ return 0;
+out_err:
+ inode_unlock(d_inode(parent));
+ return ret;
+}
+
+int ksmbd_vfs_may_delete(struct user_namespace *user_ns,
+ struct dentry *dentry)
+{
+ struct dentry *parent;
+ int ret;
+
+ parent = dget_parent(dentry);
+ ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
+ if (ret) {
+ dput(parent);
+ return ret;
+ }
+
+ ret = inode_permission(user_ns, d_inode(parent),
+ MAY_EXEC | MAY_WRITE);
+
+ inode_unlock(d_inode(parent));
+ dput(parent);
+ return ret;
+}
+
+int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
+ struct dentry *dentry, __le32 *daccess)
+{
+ struct dentry *parent;
+ int ret = 0;
+
+ *daccess = cpu_to_le32(FILE_READ_ATTRIBUTES | READ_CONTROL);
+
+ if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_WRITE))
+ *daccess |= cpu_to_le32(WRITE_DAC | WRITE_OWNER | SYNCHRONIZE |
+ FILE_WRITE_DATA | FILE_APPEND_DATA |
+ FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES |
+ FILE_DELETE_CHILD);
+
+ if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_READ))
+ *daccess |= FILE_READ_DATA_LE | FILE_READ_EA_LE;
+
+ if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_EXEC))
+ *daccess |= FILE_EXECUTE_LE;
+
+ parent = dget_parent(dentry);
+ ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
+ if (ret) {
+ dput(parent);
+ return ret;
+ }
+
+ if (!inode_permission(user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE))
+ *daccess |= FILE_DELETE_LE;
+
+ inode_unlock(d_inode(parent));
+ dput(parent);
+ return ret;
+}
+
+/**
+ * ksmbd_vfs_create() - vfs helper for smb create file
+ * @work: work
+ * @name: file name that is relative to share
+ * @mode: file create mode
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
+{
+ struct path path;
+ struct dentry *dentry;
+ int err;
+
+ dentry = ksmbd_vfs_kern_path_create(work, name,
+ LOOKUP_NO_SYMLINKS, &path);
+ if (IS_ERR(dentry)) {
+ err = PTR_ERR(dentry);
+ if (err != -ENOENT)
+ pr_err("path create failed for %s, err %d\n",
+ name, err);
+ return err;
+ }
+
+ mode |= S_IFREG;
+ err = vfs_create(mnt_user_ns(path.mnt), d_inode(path.dentry),
+ dentry, mode, true);
+ if (!err) {
+ ksmbd_vfs_inherit_owner(work, d_inode(path.dentry),
+ d_inode(dentry));
+ } else {
+ pr_err("File(%s): creation failed (err:%d)\n", name, err);
+ }
+ done_path_create(&path, dentry);
+ return err;
+}
+
+/**
+ * ksmbd_vfs_mkdir() - vfs helper for smb create directory
+ * @work: work
+ * @name: directory name that is relative to share
+ * @mode: directory create mode
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
+{
+ struct user_namespace *user_ns;
+ struct path path;
+ struct dentry *dentry;
+ int err;
+
+ dentry = ksmbd_vfs_kern_path_create(work, name,
+ LOOKUP_NO_SYMLINKS | LOOKUP_DIRECTORY,
+ &path);
+ if (IS_ERR(dentry)) {
+ err = PTR_ERR(dentry);
+ if (err != -EEXIST)
+ ksmbd_debug(VFS, "path create failed for %s, err %d\n",
+ name, err);
+ return err;
+ }
+
+ user_ns = mnt_user_ns(path.mnt);
+ mode |= S_IFDIR;
+ err = vfs_mkdir(user_ns, d_inode(path.dentry), dentry, mode);
+ if (err) {
+ goto out;
+ } else if (d_unhashed(dentry)) {
+ struct dentry *d;
+
+ d = lookup_one(user_ns, dentry->d_name.name, dentry->d_parent,
+ dentry->d_name.len);
+ if (IS_ERR(d)) {
+ err = PTR_ERR(d);
+ goto out;
+ }
+ if (unlikely(d_is_negative(d))) {
+ dput(d);
+ err = -ENOENT;
+ goto out;
+ }
+
+ ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(d));
+ dput(d);
+ }
+out:
+ done_path_create(&path, dentry);
+ if (err)
+ pr_err("mkdir(%s): creation failed (err:%d)\n", name, err);
+ return err;
+}
+
+static ssize_t ksmbd_vfs_getcasexattr(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name,
+ int attr_name_len, char **attr_value)
+{
+ char *name, *xattr_list = NULL;
+ ssize_t value_len = -ENOENT, xattr_list_len;
+
+ xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
+ if (xattr_list_len <= 0)
+ goto out;
+
+ for (name = xattr_list; name - xattr_list < xattr_list_len;
+ name += strlen(name) + 1) {
+ ksmbd_debug(VFS, "%s, len %zd\n", name, strlen(name));
+ if (strncasecmp(attr_name, name, attr_name_len))
+ continue;
+
+ value_len = ksmbd_vfs_getxattr(user_ns,
+ dentry,
+ name,
+ attr_value);
+ if (value_len < 0)
+ pr_err("failed to get xattr in file\n");
+ break;
+ }
+
+out:
+ kvfree(xattr_list);
+ return value_len;
+}
+
+static int ksmbd_vfs_stream_read(struct ksmbd_file *fp, char *buf, loff_t *pos,
+ size_t count)
+{
+ ssize_t v_len;
+ char *stream_buf = NULL;
+
+ ksmbd_debug(VFS, "read stream data pos : %llu, count : %zd\n",
+ *pos, count);
+
+ v_len = ksmbd_vfs_getcasexattr(file_mnt_user_ns(fp->filp),
+ fp->filp->f_path.dentry,
+ fp->stream.name,
+ fp->stream.size,
+ &stream_buf);
+ if ((int)v_len <= 0)
+ return (int)v_len;
+
+ if (v_len <= *pos) {
+ count = -EINVAL;
+ goto free_buf;
+ }
+
+ if (v_len - *pos < count)
+ count = v_len - *pos;
+
+ memcpy(buf, &stream_buf[*pos], count);
+
+free_buf:
+ kvfree(stream_buf);
+ return count;
+}
+
+/**
+ * check_lock_range() - vfs helper for smb byte range file locking
+ * @filp: the file to apply the lock to
+ * @start: lock start byte offset
+ * @end: lock end byte offset
+ * @type: byte range type read/write
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int check_lock_range(struct file *filp, loff_t start, loff_t end,
+ unsigned char type)
+{
+ struct file_lock *flock;
+ struct file_lock_context *ctx = file_inode(filp)->i_flctx;
+ int error = 0;
+
+ if (!ctx || list_empty_careful(&ctx->flc_posix))
+ return 0;
+
+ spin_lock(&ctx->flc_lock);
+ list_for_each_entry(flock, &ctx->flc_posix, fl_list) {
+ /* check conflict locks */
+ if (flock->fl_end >= start && end >= flock->fl_start) {
+ if (flock->fl_type == F_RDLCK) {
+ if (type == WRITE) {
+ pr_err("not allow write by shared lock\n");
+ error = 1;
+ goto out;
+ }
+ } else if (flock->fl_type == F_WRLCK) {
+ /* check owner in lock */
+ if (flock->fl_file != filp) {
+ error = 1;
+ pr_err("not allow rw access by exclusive lock from other opens\n");
+ goto out;
+ }
+ }
+ }
+ }
+out:
+ spin_unlock(&ctx->flc_lock);
+ return error;
+}
+
+/**
+ * ksmbd_vfs_read() - vfs helper for smb file read
+ * @work: smb work
+ * @fid: file id of open file
+ * @count: read byte count
+ * @pos: file pos
+ *
+ * Return: number of read bytes on success, otherwise error
+ */
+int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
+ loff_t *pos)
+{
+ struct file *filp = fp->filp;
+ ssize_t nbytes = 0;
+ char *rbuf = work->aux_payload_buf;
+ struct inode *inode = file_inode(filp);
+
+ if (S_ISDIR(inode->i_mode))
+ return -EISDIR;
+
+ if (unlikely(count == 0))
+ return 0;
+
+ if (work->conn->connection_type) {
+ if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
+ pr_err("no right to read(%pD)\n", fp->filp);
+ return -EACCES;
+ }
+ }
+
+ if (ksmbd_stream_fd(fp))
+ return ksmbd_vfs_stream_read(fp, rbuf, pos, count);
+
+ if (!work->tcon->posix_extensions) {
+ int ret;
+
+ ret = check_lock_range(filp, *pos, *pos + count - 1, READ);
+ if (ret) {
+ pr_err("unable to read due to lock\n");
+ return -EAGAIN;
+ }
+ }
+
+ nbytes = kernel_read(filp, rbuf, count, pos);
+ if (nbytes < 0) {
+ pr_err("smb read failed, err = %zd\n", nbytes);
+ return nbytes;
+ }
+
+ filp->f_pos = *pos;
+ return nbytes;
+}
+
+static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
+ size_t count)
+{
+ char *stream_buf = NULL, *wbuf;
+ struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
+ size_t size, v_len;
+ int err = 0;
+
+ ksmbd_debug(VFS, "write stream data pos : %llu, count : %zd\n",
+ *pos, count);
+
+ size = *pos + count;
+ if (size > XATTR_SIZE_MAX) {
+ size = XATTR_SIZE_MAX;
+ count = (*pos + count) - XATTR_SIZE_MAX;
+ }
+
+ v_len = ksmbd_vfs_getcasexattr(user_ns,
+ fp->filp->f_path.dentry,
+ fp->stream.name,
+ fp->stream.size,
+ &stream_buf);
+ if ((int)v_len < 0) {
+ pr_err("not found stream in xattr : %zd\n", v_len);
+ err = (int)v_len;
+ goto out;
+ }
+
+ if (v_len < size) {
+ wbuf = kvmalloc(size, GFP_KERNEL | __GFP_ZERO);
+ if (!wbuf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ if (v_len > 0)
+ memcpy(wbuf, stream_buf, v_len);
+ kvfree(stream_buf);
+ stream_buf = wbuf;
+ }
+
+ memcpy(&stream_buf[*pos], buf, count);
+
+ err = ksmbd_vfs_setxattr(user_ns,
+ fp->filp->f_path.dentry,
+ fp->stream.name,
+ (void *)stream_buf,
+ size,
+ 0);
+ if (err < 0)
+ goto out;
+
+ fp->filp->f_pos = *pos;
+ err = 0;
+out:
+ kvfree(stream_buf);
+ return err;
+}
+
+/**
+ * ksmbd_vfs_write() - vfs helper for smb file write
+ * @work: work
+ * @fid: file id of open file
+ * @buf: buf containing data for writing
+ * @count: read byte count
+ * @pos: file pos
+ * @sync: fsync after write
+ * @written: number of bytes written
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
+ char *buf, size_t count, loff_t *pos, bool sync,
+ ssize_t *written)
+{
+ struct file *filp;
+ loff_t offset = *pos;
+ int err = 0;
+
+ if (work->conn->connection_type) {
+ if (!(fp->daccess & FILE_WRITE_DATA_LE)) {
+ pr_err("no right to write(%pD)\n", fp->filp);
+ err = -EACCES;
+ goto out;
+ }
+ }
+
+ filp = fp->filp;
+
+ if (ksmbd_stream_fd(fp)) {
+ err = ksmbd_vfs_stream_write(fp, buf, pos, count);
+ if (!err)
+ *written = count;
+ goto out;
+ }
+
+ if (!work->tcon->posix_extensions) {
+ err = check_lock_range(filp, *pos, *pos + count - 1, WRITE);
+ if (err) {
+ pr_err("unable to write due to lock\n");
+ err = -EAGAIN;
+ goto out;
+ }
+ }
+
+ /* Do we need to break any of a levelII oplock? */
+ smb_break_all_levII_oplock(work, fp, 1);
+
+ err = kernel_write(filp, buf, count, pos);
+ if (err < 0) {
+ ksmbd_debug(VFS, "smb write failed, err = %d\n", err);
+ goto out;
+ }
+
+ filp->f_pos = *pos;
+ *written = err;
+ err = 0;
+ if (sync) {
+ err = vfs_fsync_range(filp, offset, offset + *written, 0);
+ if (err < 0)
+ pr_err("fsync failed for filename = %pD, err = %d\n",
+ fp->filp, err);
+ }
+
+out:
+ return err;
+}
+
+/**
+ * ksmbd_vfs_getattr() - vfs helper for smb getattr
+ * @work: work
+ * @fid: file id of open file
+ * @attrs: inode attributes
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat)
+{
+ int err;
+
+ err = vfs_getattr(path, stat, STATX_BTIME, AT_STATX_SYNC_AS_STAT);
+ if (err)
+ pr_err("getattr failed, err %d\n", err);
+ return err;
+}
+
+/**
+ * ksmbd_vfs_fsync() - vfs helper for smb fsync
+ * @work: work
+ * @fid: file id of open file
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
+{
+ struct ksmbd_file *fp;
+ int err;
+
+ fp = ksmbd_lookup_fd_slow(work, fid, p_id);
+ if (!fp) {
+ pr_err("failed to get filp for fid %llu\n", fid);
+ return -ENOENT;
+ }
+ err = vfs_fsync(fp->filp, 0);
+ if (err < 0)
+ pr_err("smb fsync failed, err = %d\n", err);
+ ksmbd_fd_put(work, fp);
+ return err;
+}
+
+/**
+ * ksmbd_vfs_remove_file() - vfs helper for smb rmdir or unlink
+ * @name: directory or file name that is relative to share
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
+{
+ struct user_namespace *user_ns;
+ struct path path;
+ struct dentry *parent;
+ int err;
+
+ if (ksmbd_override_fsids(work))
+ return -ENOMEM;
+
+ err = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS, &path, false);
+ if (err) {
+ ksmbd_debug(VFS, "can't get %s, err %d\n", name, err);
+ ksmbd_revert_fsids(work);
+ return err;
+ }
+
+ user_ns = mnt_user_ns(path.mnt);
+ parent = dget_parent(path.dentry);
+ err = ksmbd_vfs_lock_parent(user_ns, parent, path.dentry);
+ if (err) {
+ dput(parent);
+ path_put(&path);
+ ksmbd_revert_fsids(work);
+ return err;
+ }
+
+ if (!d_inode(path.dentry)->i_nlink) {
+ err = -ENOENT;
+ goto out_err;
+ }
+
+ if (S_ISDIR(d_inode(path.dentry)->i_mode)) {
+ err = vfs_rmdir(user_ns, d_inode(parent), path.dentry);
+ if (err && err != -ENOTEMPTY)
+ ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
+ err);
+ } else {
+ err = vfs_unlink(user_ns, d_inode(parent), path.dentry, NULL);
+ if (err)
+ ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
+ err);
+ }
+
+out_err:
+ inode_unlock(d_inode(parent));
+ dput(parent);
+ path_put(&path);
+ ksmbd_revert_fsids(work);
+ return err;
+}
+
+/**
+ * ksmbd_vfs_link() - vfs helper for creating smb hardlink
+ * @oldname: source file name
+ * @newname: hardlink name that is relative to share
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
+ const char *newname)
+{
+ struct path oldpath, newpath;
+ struct dentry *dentry;
+ int err;
+
+ if (ksmbd_override_fsids(work))
+ return -ENOMEM;
+
+ err = kern_path(oldname, LOOKUP_NO_SYMLINKS, &oldpath);
+ if (err) {
+ pr_err("cannot get linux path for %s, err = %d\n",
+ oldname, err);
+ goto out1;
+ }
+
+ dentry = ksmbd_vfs_kern_path_create(work, newname,
+ LOOKUP_NO_SYMLINKS | LOOKUP_REVAL,
+ &newpath);
+ if (IS_ERR(dentry)) {
+ err = PTR_ERR(dentry);
+ pr_err("path create err for %s, err %d\n", newname, err);
+ goto out2;
+ }
+
+ err = -EXDEV;
+ if (oldpath.mnt != newpath.mnt) {
+ pr_err("vfs_link failed err %d\n", err);
+ goto out3;
+ }
+
+ err = vfs_link(oldpath.dentry, mnt_user_ns(newpath.mnt),
+ d_inode(newpath.dentry),
+ dentry, NULL);
+ if (err)
+ ksmbd_debug(VFS, "vfs_link failed err %d\n", err);
+
+out3:
+ done_path_create(&newpath, dentry);
+out2:
+ path_put(&oldpath);
+out1:
+ ksmbd_revert_fsids(work);
+ return err;
+}
+
+static int ksmbd_validate_entry_in_use(struct dentry *src_dent)
+{
+ struct dentry *dst_dent;
+
+ spin_lock(&src_dent->d_lock);
+ list_for_each_entry(dst_dent, &src_dent->d_subdirs, d_child) {
+ struct ksmbd_file *child_fp;
+
+ if (d_really_is_negative(dst_dent))
+ continue;
+
+ child_fp = ksmbd_lookup_fd_inode(d_inode(dst_dent));
+ if (child_fp) {
+ spin_unlock(&src_dent->d_lock);
+ ksmbd_debug(VFS, "Forbid rename, sub file/dir is in use\n");
+ return -EACCES;
+ }
+ }
+ spin_unlock(&src_dent->d_lock);
+
+ return 0;
+}
+
+static int __ksmbd_vfs_rename(struct ksmbd_work *work,
+ struct user_namespace *src_user_ns,
+ struct dentry *src_dent_parent,
+ struct dentry *src_dent,
+ struct user_namespace *dst_user_ns,
+ struct dentry *dst_dent_parent,
+ struct dentry *trap_dent,
+ char *dst_name)
+{
+ struct dentry *dst_dent;
+ int err;
+
+ if (!work->tcon->posix_extensions) {
+ err = ksmbd_validate_entry_in_use(src_dent);
+ if (err)
+ return err;
+ }
+
+ if (d_really_is_negative(src_dent_parent))
+ return -ENOENT;
+ if (d_really_is_negative(dst_dent_parent))
+ return -ENOENT;
+ if (d_really_is_negative(src_dent))
+ return -ENOENT;
+ if (src_dent == trap_dent)
+ return -EINVAL;
+
+ if (ksmbd_override_fsids(work))
+ return -ENOMEM;
+
+ dst_dent = lookup_one(dst_user_ns, dst_name, dst_dent_parent,
+ strlen(dst_name));
+ err = PTR_ERR(dst_dent);
+ if (IS_ERR(dst_dent)) {
+ pr_err("lookup failed %s [%d]\n", dst_name, err);
+ goto out;
+ }
+
+ err = -ENOTEMPTY;
+ if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
+ struct renamedata rd = {
+ .old_mnt_userns = src_user_ns,
+ .old_dir = d_inode(src_dent_parent),
+ .old_dentry = src_dent,
+ .new_mnt_userns = dst_user_ns,
+ .new_dir = d_inode(dst_dent_parent),
+ .new_dentry = dst_dent,
+ };
+ err = vfs_rename(&rd);
+ }
+ if (err)
+ pr_err("vfs_rename failed err %d\n", err);
+ if (dst_dent)
+ dput(dst_dent);
+out:
+ ksmbd_revert_fsids(work);
+ return err;
+}
+
+int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
+ char *newname)
+{
+ struct user_namespace *user_ns;
+ struct path dst_path;
+ struct dentry *src_dent_parent, *dst_dent_parent;
+ struct dentry *src_dent, *trap_dent, *src_child;
+ char *dst_name;
+ int err;
+
+ dst_name = extract_last_component(newname);
+ if (!dst_name) {
+ dst_name = newname;
+ newname = "";
+ }
+
+ src_dent_parent = dget_parent(fp->filp->f_path.dentry);
+ src_dent = fp->filp->f_path.dentry;
+
+ err = ksmbd_vfs_kern_path(work, newname,
+ LOOKUP_NO_SYMLINKS | LOOKUP_DIRECTORY,
+ &dst_path, false);
+ if (err) {
+ ksmbd_debug(VFS, "Cannot get path for %s [%d]\n", newname, err);
+ goto out;
+ }
+ dst_dent_parent = dst_path.dentry;
+
+ trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
+ dget(src_dent);
+ dget(dst_dent_parent);
+ user_ns = file_mnt_user_ns(fp->filp);
+ src_child = lookup_one(user_ns, src_dent->d_name.name, src_dent_parent,
+ src_dent->d_name.len);
+ if (IS_ERR(src_child)) {
+ err = PTR_ERR(src_child);
+ goto out_lock;
+ }
+
+ if (src_child != src_dent) {
+ err = -ESTALE;
+ dput(src_child);
+ goto out_lock;
+ }
+ dput(src_child);
+
+ err = __ksmbd_vfs_rename(work,
+ user_ns,
+ src_dent_parent,
+ src_dent,
+ mnt_user_ns(dst_path.mnt),
+ dst_dent_parent,
+ trap_dent,
+ dst_name);
+out_lock:
+ dput(src_dent);
+ dput(dst_dent_parent);
+ unlock_rename(src_dent_parent, dst_dent_parent);
+ path_put(&dst_path);
+out:
+ dput(src_dent_parent);
+ return err;
+}
+
+/**
+ * ksmbd_vfs_truncate() - vfs helper for smb file truncate
+ * @work: work
+ * @fid: file id of old file
+ * @size: truncate to given size
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_truncate(struct ksmbd_work *work,
+ struct ksmbd_file *fp, loff_t size)
+{
+ int err = 0;
+ struct file *filp;
+
+ filp = fp->filp;
+
+ /* Do we need to break any of a levelII oplock? */
+ smb_break_all_levII_oplock(work, fp, 1);
+
+ if (!work->tcon->posix_extensions) {
+ struct inode *inode = file_inode(filp);
+
+ if (size < inode->i_size) {
+ err = check_lock_range(filp, size,
+ inode->i_size - 1, WRITE);
+ } else {
+ err = check_lock_range(filp, inode->i_size,
+ size - 1, WRITE);
+ }
+
+ if (err) {
+ pr_err("failed due to lock\n");
+ return -EAGAIN;
+ }
+ }
+
+ err = vfs_truncate(&filp->f_path, size);
+ if (err)
+ pr_err("truncate failed, err %d\n", err);
+ return err;
+}
+
+/**
+ * ksmbd_vfs_listxattr() - vfs helper for smb list extended attributes
+ * @dentry: dentry of file for listing xattrs
+ * @list: destination buffer
+ * @size: destination buffer length
+ *
+ * Return: xattr list length on success, otherwise error
+ */
+ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list)
+{
+ ssize_t size;
+ char *vlist = NULL;
+
+ size = vfs_listxattr(dentry, NULL, 0);
+ if (size <= 0)
+ return size;
+
+ vlist = kvmalloc(size, GFP_KERNEL | __GFP_ZERO);
+ if (!vlist)
+ return -ENOMEM;
+
+ *list = vlist;
+ size = vfs_listxattr(dentry, vlist, size);
+ if (size < 0) {
+ ksmbd_debug(VFS, "listxattr failed\n");
+ kvfree(vlist);
+ *list = NULL;
+ }
+
+ return size;
+}
+
+static ssize_t ksmbd_vfs_xattr_len(struct user_namespace *user_ns,
+ struct dentry *dentry, char *xattr_name)
+{
+ return vfs_getxattr(user_ns, dentry, xattr_name, NULL, 0);
+}
+
+/**
+ * ksmbd_vfs_getxattr() - vfs helper for smb get extended attributes value
+ * @user_ns: user namespace
+ * @dentry: dentry of file for getting xattrs
+ * @xattr_name: name of xattr name to query
+ * @xattr_buf: destination buffer xattr value
+ *
+ * Return: read xattr value length on success, otherwise error
+ */
+ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
+ char *xattr_name, char **xattr_buf)
+{
+ ssize_t xattr_len;
+ char *buf;
+
+ *xattr_buf = NULL;
+ xattr_len = ksmbd_vfs_xattr_len(user_ns, dentry, xattr_name);
+ if (xattr_len < 0)
+ return xattr_len;
+
+ buf = kmalloc(xattr_len + 1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ xattr_len = vfs_getxattr(user_ns, dentry, xattr_name,
+ (void *)buf, xattr_len);
+ if (xattr_len > 0)
+ *xattr_buf = buf;
+ else
+ kfree(buf);
+ return xattr_len;
+}
+
+/**
+ * ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value
+ * @user_ns: user namespace
+ * @dentry: dentry to set XATTR at
+ * @name: xattr name for setxattr
+ * @value: xattr value to set
+ * @size: size of xattr value
+ * @flags: destination buffer length
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
+ struct dentry *dentry, const char *attr_name,
+ void *attr_value, size_t attr_size, int flags)
+{
+ int err;
+
+ err = vfs_setxattr(user_ns,
+ dentry,
+ attr_name,
+ attr_value,
+ attr_size,
+ flags);
+ if (err)
+ ksmbd_debug(VFS, "setxattr failed, err %d\n", err);
+ return err;
+}
+
+/**
+ * ksmbd_vfs_set_fadvise() - convert smb IO caching options to linux options
+ * @filp: file pointer for IO
+ * @options: smb IO options
+ */
+void ksmbd_vfs_set_fadvise(struct file *filp, __le32 option)
+{
+ struct address_space *mapping;
+
+ mapping = filp->f_mapping;
+
+ if (!option || !mapping)
+ return;
+
+ if (option & FILE_WRITE_THROUGH_LE) {
+ filp->f_flags |= O_SYNC;
+ } else if (option & FILE_SEQUENTIAL_ONLY_LE) {
+ filp->f_ra.ra_pages = inode_to_bdi(mapping->host)->ra_pages * 2;
+ spin_lock(&filp->f_lock);
+ filp->f_mode &= ~FMODE_RANDOM;
+ spin_unlock(&filp->f_lock);
+ } else if (option & FILE_RANDOM_ACCESS_LE) {
+ spin_lock(&filp->f_lock);
+ filp->f_mode |= FMODE_RANDOM;
+ spin_unlock(&filp->f_lock);
+ }
+}
+
+int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
+ loff_t off, loff_t len)
+{
+ smb_break_all_levII_oplock(work, fp, 1);
+ if (fp->f_ci->m_fattr & FILE_ATTRIBUTE_SPARSE_FILE_LE)
+ return vfs_fallocate(fp->filp,
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
+ off, len);
+
+ return vfs_fallocate(fp->filp,
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
+ off, len);
+}
+
+int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
+ struct file_allocated_range_buffer *ranges,
+ unsigned int in_count, unsigned int *out_count)
+{
+ struct file *f = fp->filp;
+ struct inode *inode = file_inode(fp->filp);
+ loff_t maxbytes = (u64)inode->i_sb->s_maxbytes, end;
+ loff_t extent_start, extent_end;
+ int ret = 0;
+
+ if (start > maxbytes)
+ return -EFBIG;
+
+ if (!in_count)
+ return 0;
+
+ /*
+ * Shrink request scope to what the fs can actually handle.
+ */
+ if (length > maxbytes || (maxbytes - length) < start)
+ length = maxbytes - start;
+
+ if (start + length > inode->i_size)
+ length = inode->i_size - start;
+
+ *out_count = 0;
+ end = start + length;
+ while (start < end && *out_count < in_count) {
+ extent_start = vfs_llseek(f, start, SEEK_DATA);
+ if (extent_start < 0) {
+ if (extent_start != -ENXIO)
+ ret = (int)extent_start;
+ break;
+ }
+
+ if (extent_start >= end)
+ break;
+
+ extent_end = vfs_llseek(f, extent_start, SEEK_HOLE);
+ if (extent_end < 0) {
+ if (extent_end != -ENXIO)
+ ret = (int)extent_end;
+ break;
+ } else if (extent_start >= extent_end) {
+ break;
+ }
+
+ ranges[*out_count].file_offset = cpu_to_le64(extent_start);
+ ranges[(*out_count)++].length =
+ cpu_to_le64(min(extent_end, end) - extent_start);
+
+ start = extent_end;
+ }
+
+ return ret;
+}
+
+int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name)
+{
+ return vfs_removexattr(user_ns, dentry, attr_name);
+}
+
+int ksmbd_vfs_unlink(struct user_namespace *user_ns,
+ struct dentry *dir, struct dentry *dentry)
+{
+ int err = 0;
+
+ err = ksmbd_vfs_lock_parent(user_ns, dir, dentry);
+ if (err)
+ return err;
+ dget(dentry);
+
+ if (S_ISDIR(d_inode(dentry)->i_mode))
+ err = vfs_rmdir(user_ns, d_inode(dir), dentry);
+ else
+ err = vfs_unlink(user_ns, d_inode(dir), dentry, NULL);
+
+ dput(dentry);
+ inode_unlock(d_inode(dir));
+ if (err)
+ ksmbd_debug(VFS, "failed to delete, err %d\n", err);
+
+ return err;
+}
+
+static bool __dir_empty(struct dir_context *ctx, const char *name, int namlen,
+ loff_t offset, u64 ino, unsigned int d_type)
+{
+ struct ksmbd_readdir_data *buf;
+
+ buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
+ buf->dirent_count++;
+
+ return buf->dirent_count <= 2;
+}
+
+/**
+ * ksmbd_vfs_empty_dir() - check for empty directory
+ * @fp: ksmbd file pointer
+ *
+ * Return: true if directory empty, otherwise false
+ */
+int ksmbd_vfs_empty_dir(struct ksmbd_file *fp)
+{
+ int err;
+ struct ksmbd_readdir_data readdir_data;
+
+ memset(&readdir_data, 0, sizeof(struct ksmbd_readdir_data));
+
+ set_ctx_actor(&readdir_data.ctx, __dir_empty);
+ readdir_data.dirent_count = 0;
+
+ err = iterate_dir(fp->filp, &readdir_data.ctx);
+ if (readdir_data.dirent_count > 2)
+ err = -ENOTEMPTY;
+ else
+ err = 0;
+ return err;
+}
+
+static bool __caseless_lookup(struct dir_context *ctx, const char *name,
+ int namlen, loff_t offset, u64 ino,
+ unsigned int d_type)
+{
+ struct ksmbd_readdir_data *buf;
+ int cmp = -EINVAL;
+
+ buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
+
+ if (buf->used != namlen)
+ return true;
+ if (IS_ENABLED(CONFIG_UNICODE) && buf->um) {
+ const struct qstr q_buf = {.name = buf->private,
+ .len = buf->used};
+ const struct qstr q_name = {.name = name,
+ .len = namlen};
+
+ cmp = utf8_strncasecmp(buf->um, &q_buf, &q_name);
+ }
+ if (cmp < 0)
+ cmp = strncasecmp((char *)buf->private, name, namlen);
+ if (!cmp) {
+ memcpy((char *)buf->private, name, namlen);
+ buf->dirent_count = 1;
+ return false;
+ }
+ return true;
+}
+
+/**
+ * ksmbd_vfs_lookup_in_dir() - lookup a file in a directory
+ * @dir: path info
+ * @name: filename to lookup
+ * @namelen: filename length
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
+ size_t namelen, struct unicode_map *um)
+{
+ int ret;
+ struct file *dfilp;
+ int flags = O_RDONLY | O_LARGEFILE;
+ struct ksmbd_readdir_data readdir_data = {
+ .ctx.actor = __caseless_lookup,
+ .private = name,
+ .used = namelen,
+ .dirent_count = 0,
+ .um = um,
+ };
+
+ dfilp = dentry_open(dir, flags, current_cred());
+ if (IS_ERR(dfilp))
+ return PTR_ERR(dfilp);
+
+ ret = iterate_dir(dfilp, &readdir_data.ctx);
+ if (readdir_data.dirent_count > 0)
+ ret = 0;
+ fput(dfilp);
+ return ret;
+}
+
+/**
+ * ksmbd_vfs_kern_path() - lookup a file and get path info
+ * @name: file path that is relative to share
+ * @flags: lookup flags
+ * @path: if lookup succeed, return path info
+ * @caseless: caseless filename lookup
+ *
+ * Return: 0 on success, otherwise error
+ */
+int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
+ unsigned int flags, struct path *path, bool caseless)
+{
+ struct ksmbd_share_config *share_conf = work->tcon->share_conf;
+ int err;
+
+ flags |= LOOKUP_BENEATH;
+ err = vfs_path_lookup(share_conf->vfs_path.dentry,
+ share_conf->vfs_path.mnt,
+ name,
+ flags,
+ path);
+ if (!err)
+ return 0;
+
+ if (caseless) {
+ char *filepath;
+ struct path parent;
+ size_t path_len, remain_len;
+
+ filepath = kstrdup(name, GFP_KERNEL);
+ if (!filepath)
+ return -ENOMEM;
+
+ path_len = strlen(filepath);
+ remain_len = path_len;
+
+ parent = share_conf->vfs_path;
+ path_get(&parent);
+
+ while (d_can_lookup(parent.dentry)) {
+ char *filename = filepath + path_len - remain_len;
+ char *next = strchrnul(filename, '/');
+ size_t filename_len = next - filename;
+ bool is_last = !next[0];
+
+ if (filename_len == 0)
+ break;
+
+ err = ksmbd_vfs_lookup_in_dir(&parent, filename,
+ filename_len,
+ work->conn->um);
+ path_put(&parent);
+ if (err)
+ goto out;
+
+ next[0] = '\0';
+
+ err = vfs_path_lookup(share_conf->vfs_path.dentry,
+ share_conf->vfs_path.mnt,
+ filepath,
+ flags,
+ &parent);
+ if (err)
+ goto out;
+ else if (is_last) {
+ *path = parent;
+ goto out;
+ }
+
+ next[0] = '/';
+ remain_len -= filename_len + 1;
+ }
+
+ path_put(&parent);
+ err = -EINVAL;
+out:
+ kfree(filepath);
+ }
+ return err;
+}
+
+struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
+ const char *name,
+ unsigned int flags,
+ struct path *path)
+{
+ char *abs_name;
+ struct dentry *dent;
+
+ abs_name = convert_to_unix_name(work->tcon->share_conf, name);
+ if (!abs_name)
+ return ERR_PTR(-ENOMEM);
+
+ dent = kern_path_create(AT_FDCWD, abs_name, path, flags);
+ kfree(abs_name);
+ return dent;
+}
+
+int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
+ struct dentry *dentry)
+{
+ char *name, *xattr_list = NULL;
+ ssize_t xattr_list_len;
+ int err = 0;
+
+ xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
+ if (xattr_list_len < 0) {
+ goto out;
+ } else if (!xattr_list_len) {
+ ksmbd_debug(SMB, "empty xattr in the file\n");
+ goto out;
+ }
+
+ for (name = xattr_list; name - xattr_list < xattr_list_len;
+ name += strlen(name) + 1) {
+ ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
+
+ if (!strncmp(name, XATTR_NAME_POSIX_ACL_ACCESS,
+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) ||
+ !strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) {
+ err = ksmbd_vfs_remove_xattr(user_ns, dentry, name);
+ if (err)
+ ksmbd_debug(SMB,
+ "remove acl xattr failed : %s\n", name);
+ }
+ }
+out:
+ kvfree(xattr_list);
+ return err;
+}
+
+int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns,
+ struct dentry *dentry)
+{
+ char *name, *xattr_list = NULL;
+ ssize_t xattr_list_len;
+ int err = 0;
+
+ xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
+ if (xattr_list_len < 0) {
+ goto out;
+ } else if (!xattr_list_len) {
+ ksmbd_debug(SMB, "empty xattr in the file\n");
+ goto out;
+ }
+
+ for (name = xattr_list; name - xattr_list < xattr_list_len;
+ name += strlen(name) + 1) {
+ ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
+
+ if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) {
+ err = ksmbd_vfs_remove_xattr(user_ns, dentry, name);
+ if (err)
+ ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
+ }
+ }
+out:
+ kvfree(xattr_list);
+ return err;
+}
+
+static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode,
+ int acl_type)
+{
+ struct xattr_smb_acl *smb_acl = NULL;
+ struct posix_acl *posix_acls;
+ struct posix_acl_entry *pa_entry;
+ struct xattr_acl_entry *xa_entry;
+ int i;
+
+ if (!IS_ENABLED(CONFIG_FS_POSIX_ACL))
+ return NULL;
+
+ posix_acls = get_acl(inode, acl_type);
+ if (!posix_acls)
+ return NULL;
+
+ smb_acl = kzalloc(sizeof(struct xattr_smb_acl) +
+ sizeof(struct xattr_acl_entry) * posix_acls->a_count,
+ GFP_KERNEL);
+ if (!smb_acl)
+ goto out;
+
+ smb_acl->count = posix_acls->a_count;
+ pa_entry = posix_acls->a_entries;
+ xa_entry = smb_acl->entries;
+ for (i = 0; i < posix_acls->a_count; i++, pa_entry++, xa_entry++) {
+ switch (pa_entry->e_tag) {
+ case ACL_USER:
+ xa_entry->type = SMB_ACL_USER;
+ xa_entry->uid = posix_acl_uid_translate(user_ns, pa_entry);
+ break;
+ case ACL_USER_OBJ:
+ xa_entry->type = SMB_ACL_USER_OBJ;
+ break;
+ case ACL_GROUP:
+ xa_entry->type = SMB_ACL_GROUP;
+ xa_entry->gid = posix_acl_gid_translate(user_ns, pa_entry);
+ break;
+ case ACL_GROUP_OBJ:
+ xa_entry->type = SMB_ACL_GROUP_OBJ;
+ break;
+ case ACL_OTHER:
+ xa_entry->type = SMB_ACL_OTHER;
+ break;
+ case ACL_MASK:
+ xa_entry->type = SMB_ACL_MASK;
+ break;
+ default:
+ pr_err("unknown type : 0x%x\n", pa_entry->e_tag);
+ goto out;
+ }
+
+ if (pa_entry->e_perm & ACL_READ)
+ xa_entry->perm |= SMB_ACL_READ;
+ if (pa_entry->e_perm & ACL_WRITE)
+ xa_entry->perm |= SMB_ACL_WRITE;
+ if (pa_entry->e_perm & ACL_EXECUTE)
+ xa_entry->perm |= SMB_ACL_EXECUTE;
+ }
+out:
+ posix_acl_release(posix_acls);
+ return smb_acl;
+}
+
+int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct smb_ntsd *pntsd, int len)
+{
+ int rc;
+ struct ndr sd_ndr = {0}, acl_ndr = {0};
+ struct xattr_ntacl acl = {0};
+ struct xattr_smb_acl *smb_acl, *def_smb_acl = NULL;
+ struct inode *inode = d_inode(dentry);
+
+ acl.version = 4;
+ acl.hash_type = XATTR_SD_HASH_TYPE_SHA256;
+ acl.current_time = ksmbd_UnixTimeToNT(current_time(inode));
+
+ memcpy(acl.desc, "posix_acl", 9);
+ acl.desc_len = 10;
+
+ pntsd->osidoffset =
+ cpu_to_le32(le32_to_cpu(pntsd->osidoffset) + NDR_NTSD_OFFSETOF);
+ pntsd->gsidoffset =
+ cpu_to_le32(le32_to_cpu(pntsd->gsidoffset) + NDR_NTSD_OFFSETOF);
+ pntsd->dacloffset =
+ cpu_to_le32(le32_to_cpu(pntsd->dacloffset) + NDR_NTSD_OFFSETOF);
+
+ acl.sd_buf = (char *)pntsd;
+ acl.sd_size = len;
+
+ rc = ksmbd_gen_sd_hash(conn, acl.sd_buf, acl.sd_size, acl.hash);
+ if (rc) {
+ pr_err("failed to generate hash for ndr acl\n");
+ return rc;
+ }
+
+ smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
+ ACL_TYPE_ACCESS);
+ if (S_ISDIR(inode->i_mode))
+ def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
+ ACL_TYPE_DEFAULT);
+
+ rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode,
+ smb_acl, def_smb_acl);
+ if (rc) {
+ pr_err("failed to encode ndr to posix acl\n");
+ goto out;
+ }
+
+ rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset,
+ acl.posix_acl_hash);
+ if (rc) {
+ pr_err("failed to generate hash for ndr acl\n");
+ goto out;
+ }
+
+ rc = ndr_encode_v4_ntacl(&sd_ndr, &acl);
+ if (rc) {
+ pr_err("failed to encode ndr to posix acl\n");
+ goto out;
+ }
+
+ rc = ksmbd_vfs_setxattr(user_ns, dentry,
+ XATTR_NAME_SD, sd_ndr.data,
+ sd_ndr.offset, 0);
+ if (rc < 0)
+ pr_err("Failed to store XATTR ntacl :%d\n", rc);
+
+ kfree(sd_ndr.data);
+out:
+ kfree(acl_ndr.data);
+ kfree(smb_acl);
+ kfree(def_smb_acl);
+ return rc;
+}
+
+int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct smb_ntsd **pntsd)
+{
+ int rc;
+ struct ndr n;
+ struct inode *inode = d_inode(dentry);
+ struct ndr acl_ndr = {0};
+ struct xattr_ntacl acl;
+ struct xattr_smb_acl *smb_acl = NULL, *def_smb_acl = NULL;
+ __u8 cmp_hash[XATTR_SD_HASH_SIZE] = {0};
+
+ rc = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_SD, &n.data);
+ if (rc <= 0)
+ return rc;
+
+ n.length = rc;
+ rc = ndr_decode_v4_ntacl(&n, &acl);
+ if (rc)
+ goto free_n_data;
+
+ smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
+ ACL_TYPE_ACCESS);
+ if (S_ISDIR(inode->i_mode))
+ def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
+ ACL_TYPE_DEFAULT);
+
+ rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode, smb_acl,
+ def_smb_acl);
+ if (rc) {
+ pr_err("failed to encode ndr to posix acl\n");
+ goto out_free;
+ }
+
+ rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset, cmp_hash);
+ if (rc) {
+ pr_err("failed to generate hash for ndr acl\n");
+ goto out_free;
+ }
+
+ if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) {
+ pr_err("hash value diff\n");
+ rc = -EINVAL;
+ goto out_free;
+ }
+
+ *pntsd = acl.sd_buf;
+ if (acl.sd_size < sizeof(struct smb_ntsd)) {
+ pr_err("sd size is invalid\n");
+ goto out_free;
+ }
+
+ (*pntsd)->osidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) -
+ NDR_NTSD_OFFSETOF);
+ (*pntsd)->gsidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) -
+ NDR_NTSD_OFFSETOF);
+ (*pntsd)->dacloffset = cpu_to_le32(le32_to_cpu((*pntsd)->dacloffset) -
+ NDR_NTSD_OFFSETOF);
+
+ rc = acl.sd_size;
+out_free:
+ kfree(acl_ndr.data);
+ kfree(smb_acl);
+ kfree(def_smb_acl);
+ if (rc < 0) {
+ kfree(acl.sd_buf);
+ *pntsd = NULL;
+ }
+
+free_n_data:
+ kfree(n.data);
+ return rc;
+}
+
+int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct xattr_dos_attrib *da)
+{
+ struct ndr n;
+ int err;
+
+ err = ndr_encode_dos_attr(&n, da);
+ if (err)
+ return err;
+
+ err = ksmbd_vfs_setxattr(user_ns, dentry, XATTR_NAME_DOS_ATTRIBUTE,
+ (void *)n.data, n.offset, 0);
+ if (err)
+ ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
+ kfree(n.data);
+
+ return err;
+}
+
+int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct xattr_dos_attrib *da)
+{
+ struct ndr n;
+ int err;
+
+ err = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_DOS_ATTRIBUTE,
+ (char **)&n.data);
+ if (err > 0) {
+ n.length = err;
+ if (ndr_decode_dos_attr(&n, da))
+ err = -EINVAL;
+ kfree(n.data);
+ } else {
+ ksmbd_debug(SMB, "failed to load dos attribute in xattr\n");
+ }
+
+ return err;
+}
+
+/**
+ * ksmbd_vfs_init_kstat() - convert unix stat information to smb stat format
+ * @p: destination buffer
+ * @ksmbd_kstat: ksmbd kstat wrapper
+ */
+void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat)
+{
+ struct file_directory_info *info = (struct file_directory_info *)(*p);
+ struct kstat *kstat = ksmbd_kstat->kstat;
+ u64 time;
+
+ info->FileIndex = 0;
+ info->CreationTime = cpu_to_le64(ksmbd_kstat->create_time);
+ time = ksmbd_UnixTimeToNT(kstat->atime);
+ info->LastAccessTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(kstat->mtime);
+ info->LastWriteTime = cpu_to_le64(time);
+ time = ksmbd_UnixTimeToNT(kstat->ctime);
+ info->ChangeTime = cpu_to_le64(time);
+
+ if (ksmbd_kstat->file_attributes & FILE_ATTRIBUTE_DIRECTORY_LE) {
+ info->EndOfFile = 0;
+ info->AllocationSize = 0;
+ } else {
+ info->EndOfFile = cpu_to_le64(kstat->size);
+ info->AllocationSize = cpu_to_le64(kstat->blocks << 9);
+ }
+ info->ExtFileAttributes = ksmbd_kstat->file_attributes;
+
+ return info;
+}
+
+int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct ksmbd_kstat *ksmbd_kstat)
+{
+ u64 time;
+ int rc;
+
+ generic_fillattr(user_ns, d_inode(dentry), ksmbd_kstat->kstat);
+
+ time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
+ ksmbd_kstat->create_time = time;
+
+ /*
+ * set default value for the case that store dos attributes is not yes
+ * or that acl is disable in server's filesystem and the config is yes.
+ */
+ if (S_ISDIR(ksmbd_kstat->kstat->mode))
+ ksmbd_kstat->file_attributes = FILE_ATTRIBUTE_DIRECTORY_LE;
+ else
+ ksmbd_kstat->file_attributes = FILE_ATTRIBUTE_ARCHIVE_LE;
+
+ if (test_share_config_flag(work->tcon->share_conf,
+ KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
+ struct xattr_dos_attrib da;
+
+ rc = ksmbd_vfs_get_dos_attrib_xattr(user_ns, dentry, &da);
+ if (rc > 0) {
+ ksmbd_kstat->file_attributes = cpu_to_le32(da.attr);
+ ksmbd_kstat->create_time = da.create_time;
+ } else {
+ ksmbd_debug(VFS, "fail to load dos attribute.\n");
+ }
+ }
+
+ return 0;
+}
+
+ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name,
+ int attr_name_len)
+{
+ char *name, *xattr_list = NULL;
+ ssize_t value_len = -ENOENT, xattr_list_len;
+
+ xattr_list_len = ksmbd_vfs_listxattr(dentry, &xattr_list);
+ if (xattr_list_len <= 0)
+ goto out;
+
+ for (name = xattr_list; name - xattr_list < xattr_list_len;
+ name += strlen(name) + 1) {
+ ksmbd_debug(VFS, "%s, len %zd\n", name, strlen(name));
+ if (strncasecmp(attr_name, name, attr_name_len))
+ continue;
+
+ value_len = ksmbd_vfs_xattr_len(user_ns, dentry, name);
+ break;
+ }
+
+out:
+ kvfree(xattr_list);
+ return value_len;
+}
+
+int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
+ size_t *xattr_stream_name_size, int s_type)
+{
+ char *type, *buf;
+
+ if (s_type == DIR_STREAM)
+ type = ":$INDEX_ALLOCATION";
+ else
+ type = ":$DATA";
+
+ buf = kasprintf(GFP_KERNEL, "%s%s%s",
+ XATTR_NAME_STREAM, stream_name, type);
+ if (!buf)
+ return -ENOMEM;
+
+ *xattr_stream_name = buf;
+ *xattr_stream_name_size = strlen(buf) + 1;
+
+ return 0;
+}
+
+int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
+ struct ksmbd_file *src_fp,
+ struct ksmbd_file *dst_fp,
+ struct srv_copychunk *chunks,
+ unsigned int chunk_count,
+ unsigned int *chunk_count_written,
+ unsigned int *chunk_size_written,
+ loff_t *total_size_written)
+{
+ unsigned int i;
+ loff_t src_off, dst_off, src_file_size;
+ size_t len;
+ int ret;
+
+ *chunk_count_written = 0;
+ *chunk_size_written = 0;
+ *total_size_written = 0;
+
+ if (!(src_fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
+ pr_err("no right to read(%pD)\n", src_fp->filp);
+ return -EACCES;
+ }
+ if (!(dst_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) {
+ pr_err("no right to write(%pD)\n", dst_fp->filp);
+ return -EACCES;
+ }
+
+ if (ksmbd_stream_fd(src_fp) || ksmbd_stream_fd(dst_fp))
+ return -EBADF;
+
+ smb_break_all_levII_oplock(work, dst_fp, 1);
+
+ if (!work->tcon->posix_extensions) {
+ for (i = 0; i < chunk_count; i++) {
+ src_off = le64_to_cpu(chunks[i].SourceOffset);
+ dst_off = le64_to_cpu(chunks[i].TargetOffset);
+ len = le32_to_cpu(chunks[i].Length);
+
+ if (check_lock_range(src_fp->filp, src_off,
+ src_off + len - 1, READ))
+ return -EAGAIN;
+ if (check_lock_range(dst_fp->filp, dst_off,
+ dst_off + len - 1, WRITE))
+ return -EAGAIN;
+ }
+ }
+
+ src_file_size = i_size_read(file_inode(src_fp->filp));
+
+ for (i = 0; i < chunk_count; i++) {
+ src_off = le64_to_cpu(chunks[i].SourceOffset);
+ dst_off = le64_to_cpu(chunks[i].TargetOffset);
+ len = le32_to_cpu(chunks[i].Length);
+
+ if (src_off + len > src_file_size)
+ return -E2BIG;
+
+ ret = vfs_copy_file_range(src_fp->filp, src_off,
+ dst_fp->filp, dst_off, len, 0);
+ if (ret == -EOPNOTSUPP || ret == -EXDEV)
+ ret = vfs_copy_file_range(src_fp->filp, src_off,
+ dst_fp->filp, dst_off, len,
+ COPY_FILE_SPLICE);
+ if (ret < 0)
+ return ret;
+
+ *chunk_count_written += 1;
+ *total_size_written += ret;
+ }
+ return 0;
+}
+
+void ksmbd_vfs_posix_lock_wait(struct file_lock *flock)
+{
+ wait_event(flock->fl_wait, !flock->fl_blocker);
+}
+
+int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout)
+{
+ return wait_event_interruptible_timeout(flock->fl_wait,
+ !flock->fl_blocker,
+ timeout);
+}
+
+void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock)
+{
+ locks_delete_block(flock);
+}
+
+int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode)
+{
+ struct posix_acl_state acl_state;
+ struct posix_acl *acls;
+ int rc;
+
+ if (!IS_ENABLED(CONFIG_FS_POSIX_ACL))
+ return -EOPNOTSUPP;
+
+ ksmbd_debug(SMB, "Set posix acls\n");
+ rc = init_acl_state(&acl_state, 1);
+ if (rc)
+ return rc;
+
+ /* Set default owner group */
+ acl_state.owner.allow = (inode->i_mode & 0700) >> 6;
+ acl_state.group.allow = (inode->i_mode & 0070) >> 3;
+ acl_state.other.allow = inode->i_mode & 0007;
+ acl_state.users->aces[acl_state.users->n].uid = inode->i_uid;
+ acl_state.users->aces[acl_state.users->n++].perms.allow =
+ acl_state.owner.allow;
+ acl_state.groups->aces[acl_state.groups->n].gid = inode->i_gid;
+ acl_state.groups->aces[acl_state.groups->n++].perms.allow =
+ acl_state.group.allow;
+ acl_state.mask.allow = 0x07;
+
+ acls = posix_acl_alloc(6, GFP_KERNEL);
+ if (!acls) {
+ free_acl_state(&acl_state);
+ return -ENOMEM;
+ }
+ posix_state_to_acl(&acl_state, acls->a_entries);
+ rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
+ if (rc < 0)
+ ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
+ rc);
+ else if (S_ISDIR(inode->i_mode)) {
+ posix_state_to_acl(&acl_state, acls->a_entries);
+ rc = set_posix_acl(user_ns, inode, ACL_TYPE_DEFAULT,
+ acls);
+ if (rc < 0)
+ ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
+ rc);
+ }
+ free_acl_state(&acl_state);
+ posix_acl_release(acls);
+ return rc;
+}
+
+int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode, struct inode *parent_inode)
+{
+ struct posix_acl *acls;
+ struct posix_acl_entry *pace;
+ int rc, i;
+
+ if (!IS_ENABLED(CONFIG_FS_POSIX_ACL))
+ return -EOPNOTSUPP;
+
+ acls = get_acl(parent_inode, ACL_TYPE_DEFAULT);
+ if (!acls)
+ return -ENOENT;
+ pace = acls->a_entries;
+
+ for (i = 0; i < acls->a_count; i++, pace++) {
+ if (pace->e_tag == ACL_MASK) {
+ pace->e_perm = 0x07;
+ break;
+ }
+ }
+
+ rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls);
+ if (rc < 0)
+ ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
+ rc);
+ if (S_ISDIR(inode->i_mode)) {
+ rc = set_posix_acl(user_ns, inode, ACL_TYPE_DEFAULT,
+ acls);
+ if (rc < 0)
+ ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
+ rc);
+ }
+ posix_acl_release(acls);
+ return rc;
+}
diff --git a/fs/smb/server/vfs.h b/fs/smb/server/vfs.h
new file mode 100644
index 000000000000..593059ca8511
--- /dev/null
+++ b/fs/smb/server/vfs.h
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2018 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __KSMBD_VFS_H__
+#define __KSMBD_VFS_H__
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <uapi/linux/xattr.h>
+#include <linux/posix_acl.h>
+#include <linux/unicode.h>
+
+#include "smbacl.h"
+#include "xattr.h"
+
+/*
+ * Enumeration for stream type.
+ */
+enum {
+ DATA_STREAM = 1, /* type $DATA */
+ DIR_STREAM /* type $INDEX_ALLOCATION */
+};
+
+/* CreateOptions */
+#define CREATE_TREE_CONNECTION cpu_to_le32(0x00000080)
+#define FILE_RESERVE_OPFILTER_LE cpu_to_le32(0x00100000)
+
+#define CREATE_OPTION_READONLY 0x10000000
+/* system. NB not sent over wire */
+#define CREATE_OPTION_SPECIAL 0x20000000
+
+struct ksmbd_work;
+struct ksmbd_file;
+struct ksmbd_conn;
+
+struct ksmbd_dir_info {
+ const char *name;
+ char *wptr;
+ char *rptr;
+ int name_len;
+ int out_buf_len;
+ int num_entry;
+ int data_count;
+ int last_entry_offset;
+ bool hide_dot_file;
+ int flags;
+ int last_entry_off_align;
+};
+
+struct ksmbd_readdir_data {
+ struct dir_context ctx;
+ union {
+ void *private;
+ char *dirent;
+ };
+
+ unsigned int used;
+ unsigned int dirent_count;
+ unsigned int file_attr;
+ struct unicode_map *um;
+};
+
+/* ksmbd kstat wrapper to get valid create time when reading dir entry */
+struct ksmbd_kstat {
+ struct kstat *kstat;
+ unsigned long long create_time;
+ __le32 file_attributes;
+};
+
+int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
+ struct dentry *child);
+int ksmbd_vfs_may_delete(struct user_namespace *user_ns, struct dentry *dentry);
+int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
+ struct dentry *dentry, __le32 *daccess);
+int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
+int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode);
+int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp,
+ size_t count, loff_t *pos);
+int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
+ char *buf, size_t count, loff_t *pos, bool sync,
+ ssize_t *written);
+int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id);
+int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name);
+int ksmbd_vfs_link(struct ksmbd_work *work,
+ const char *oldname, const char *newname);
+int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat);
+int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
+ char *newname);
+int ksmbd_vfs_truncate(struct ksmbd_work *work,
+ struct ksmbd_file *fp, loff_t size);
+struct srv_copychunk;
+int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
+ struct ksmbd_file *src_fp,
+ struct ksmbd_file *dst_fp,
+ struct srv_copychunk *chunks,
+ unsigned int chunk_count,
+ unsigned int *chunk_count_written,
+ unsigned int *chunk_size_written,
+ loff_t *total_size_written);
+ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list);
+ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
+ char *xattr_name,
+ char **xattr_buf);
+ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name,
+ int attr_name_len);
+int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
+ struct dentry *dentry, const char *attr_name,
+ void *attr_value, size_t attr_size, int flags);
+int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
+ size_t *xattr_stream_name_size, int s_type);
+int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry, char *attr_name);
+int ksmbd_vfs_kern_path(struct ksmbd_work *work,
+ char *name, unsigned int flags, struct path *path,
+ bool caseless);
+struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
+ const char *name,
+ unsigned int flags,
+ struct path *path);
+int ksmbd_vfs_empty_dir(struct ksmbd_file *fp);
+void ksmbd_vfs_set_fadvise(struct file *filp, __le32 option);
+int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
+ loff_t off, loff_t len);
+struct file_allocated_range_buffer;
+int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
+ struct file_allocated_range_buffer *ranges,
+ unsigned int in_count, unsigned int *out_count);
+int ksmbd_vfs_unlink(struct user_namespace *user_ns,
+ struct dentry *dir, struct dentry *dentry);
+void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat);
+int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct ksmbd_kstat *ksmbd_kstat);
+void ksmbd_vfs_posix_lock_wait(struct file_lock *flock);
+int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout);
+void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock);
+int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
+ struct dentry *dentry);
+int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns,
+ struct dentry *dentry);
+int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct smb_ntsd *pntsd, int len);
+int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
+ struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct smb_ntsd **pntsd);
+int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct xattr_dos_attrib *da);
+int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns,
+ struct dentry *dentry,
+ struct xattr_dos_attrib *da);
+int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode);
+int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
+ struct inode *inode,
+ struct inode *parent_inode);
+#endif /* __KSMBD_VFS_H__ */
diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
new file mode 100644
index 000000000000..0ae5dd0829e9
--- /dev/null
+++ b/fs/smb/server/vfs_cache.c
@@ -0,0 +1,708 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
+ * Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include "glob.h"
+#include "vfs_cache.h"
+#include "oplock.h"
+#include "vfs.h"
+#include "connection.h"
+#include "mgmt/tree_connect.h"
+#include "mgmt/user_session.h"
+#include "smb_common.h"
+
+#define S_DEL_PENDING 1
+#define S_DEL_ON_CLS 2
+#define S_DEL_ON_CLS_STREAM 8
+
+static unsigned int inode_hash_mask __read_mostly;
+static unsigned int inode_hash_shift __read_mostly;
+static struct hlist_head *inode_hashtable __read_mostly;
+static DEFINE_RWLOCK(inode_hash_lock);
+
+static struct ksmbd_file_table global_ft;
+static atomic_long_t fd_limit;
+static struct kmem_cache *filp_cache;
+
+void ksmbd_set_fd_limit(unsigned long limit)
+{
+ limit = min(limit, get_max_files());
+ atomic_long_set(&fd_limit, limit);
+}
+
+static bool fd_limit_depleted(void)
+{
+ long v = atomic_long_dec_return(&fd_limit);
+
+ if (v >= 0)
+ return false;
+ atomic_long_inc(&fd_limit);
+ return true;
+}
+
+static void fd_limit_close(void)
+{
+ atomic_long_inc(&fd_limit);
+}
+
+/*
+ * INODE hash
+ */
+
+static unsigned long inode_hash(struct super_block *sb, unsigned long hashval)
+{
+ unsigned long tmp;
+
+ tmp = (hashval * (unsigned long)sb) ^ (GOLDEN_RATIO_PRIME + hashval) /
+ L1_CACHE_BYTES;
+ tmp = tmp ^ ((tmp ^ GOLDEN_RATIO_PRIME) >> inode_hash_shift);
+ return tmp & inode_hash_mask;
+}
+
+static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode)
+{
+ struct hlist_head *head = inode_hashtable +
+ inode_hash(inode->i_sb, inode->i_ino);
+ struct ksmbd_inode *ci = NULL, *ret_ci = NULL;
+
+ hlist_for_each_entry(ci, head, m_hash) {
+ if (ci->m_inode == inode) {
+ if (atomic_inc_not_zero(&ci->m_count))
+ ret_ci = ci;
+ break;
+ }
+ }
+ return ret_ci;
+}
+
+static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp)
+{
+ return __ksmbd_inode_lookup(file_inode(fp->filp));
+}
+
+static struct ksmbd_inode *ksmbd_inode_lookup_by_vfsinode(struct inode *inode)
+{
+ struct ksmbd_inode *ci;
+
+ read_lock(&inode_hash_lock);
+ ci = __ksmbd_inode_lookup(inode);
+ read_unlock(&inode_hash_lock);
+ return ci;
+}
+
+int ksmbd_query_inode_status(struct inode *inode)
+{
+ struct ksmbd_inode *ci;
+ int ret = KSMBD_INODE_STATUS_UNKNOWN;
+
+ read_lock(&inode_hash_lock);
+ ci = __ksmbd_inode_lookup(inode);
+ if (ci) {
+ ret = KSMBD_INODE_STATUS_OK;
+ if (ci->m_flags & S_DEL_PENDING)
+ ret = KSMBD_INODE_STATUS_PENDING_DELETE;
+ atomic_dec(&ci->m_count);
+ }
+ read_unlock(&inode_hash_lock);
+ return ret;
+}
+
+bool ksmbd_inode_pending_delete(struct ksmbd_file *fp)
+{
+ return (fp->f_ci->m_flags & S_DEL_PENDING);
+}
+
+void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp)
+{
+ fp->f_ci->m_flags |= S_DEL_PENDING;
+}
+
+void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp)
+{
+ fp->f_ci->m_flags &= ~S_DEL_PENDING;
+}
+
+void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
+ int file_info)
+{
+ if (ksmbd_stream_fd(fp)) {
+ fp->f_ci->m_flags |= S_DEL_ON_CLS_STREAM;
+ return;
+ }
+
+ fp->f_ci->m_flags |= S_DEL_ON_CLS;
+}
+
+static void ksmbd_inode_hash(struct ksmbd_inode *ci)
+{
+ struct hlist_head *b = inode_hashtable +
+ inode_hash(ci->m_inode->i_sb, ci->m_inode->i_ino);
+
+ hlist_add_head(&ci->m_hash, b);
+}
+
+static void ksmbd_inode_unhash(struct ksmbd_inode *ci)
+{
+ write_lock(&inode_hash_lock);
+ hlist_del_init(&ci->m_hash);
+ write_unlock(&inode_hash_lock);
+}
+
+static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
+{
+ ci->m_inode = file_inode(fp->filp);
+ atomic_set(&ci->m_count, 1);
+ atomic_set(&ci->op_count, 0);
+ atomic_set(&ci->sop_count, 0);
+ ci->m_flags = 0;
+ ci->m_fattr = 0;
+ INIT_LIST_HEAD(&ci->m_fp_list);
+ INIT_LIST_HEAD(&ci->m_op_list);
+ rwlock_init(&ci->m_lock);
+ return 0;
+}
+
+static struct ksmbd_inode *ksmbd_inode_get(struct ksmbd_file *fp)
+{
+ struct ksmbd_inode *ci, *tmpci;
+ int rc;
+
+ read_lock(&inode_hash_lock);
+ ci = ksmbd_inode_lookup(fp);
+ read_unlock(&inode_hash_lock);
+ if (ci)
+ return ci;
+
+ ci = kmalloc(sizeof(struct ksmbd_inode), GFP_KERNEL);
+ if (!ci)
+ return NULL;
+
+ rc = ksmbd_inode_init(ci, fp);
+ if (rc) {
+ pr_err("inode initialized failed\n");
+ kfree(ci);
+ return NULL;
+ }
+
+ write_lock(&inode_hash_lock);
+ tmpci = ksmbd_inode_lookup(fp);
+ if (!tmpci) {
+ ksmbd_inode_hash(ci);
+ } else {
+ kfree(ci);
+ ci = tmpci;
+ }
+ write_unlock(&inode_hash_lock);
+ return ci;
+}
+
+static void ksmbd_inode_free(struct ksmbd_inode *ci)
+{
+ ksmbd_inode_unhash(ci);
+ kfree(ci);
+}
+
+static void ksmbd_inode_put(struct ksmbd_inode *ci)
+{
+ if (atomic_dec_and_test(&ci->m_count))
+ ksmbd_inode_free(ci);
+}
+
+int __init ksmbd_inode_hash_init(void)
+{
+ unsigned int loop;
+ unsigned long numentries = 16384;
+ unsigned long bucketsize = sizeof(struct hlist_head);
+ unsigned long size;
+
+ inode_hash_shift = ilog2(numentries);
+ inode_hash_mask = (1 << inode_hash_shift) - 1;
+
+ size = bucketsize << inode_hash_shift;
+
+ /* init master fp hash table */
+ inode_hashtable = vmalloc(size);
+ if (!inode_hashtable)
+ return -ENOMEM;
+
+ for (loop = 0; loop < (1U << inode_hash_shift); loop++)
+ INIT_HLIST_HEAD(&inode_hashtable[loop]);
+ return 0;
+}
+
+void ksmbd_release_inode_hash(void)
+{
+ vfree(inode_hashtable);
+}
+
+static void __ksmbd_inode_close(struct ksmbd_file *fp)
+{
+ struct dentry *dir, *dentry;
+ struct ksmbd_inode *ci = fp->f_ci;
+ int err;
+ struct file *filp;
+
+ filp = fp->filp;
+ if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) {
+ ci->m_flags &= ~S_DEL_ON_CLS_STREAM;
+ err = ksmbd_vfs_remove_xattr(file_mnt_user_ns(filp),
+ filp->f_path.dentry,
+ fp->stream.name);
+ if (err)
+ pr_err("remove xattr failed : %s\n",
+ fp->stream.name);
+ }
+
+ if (atomic_dec_and_test(&ci->m_count)) {
+ write_lock(&ci->m_lock);
+ if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
+ dentry = filp->f_path.dentry;
+ dir = dentry->d_parent;
+ ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
+ write_unlock(&ci->m_lock);
+ ksmbd_vfs_unlink(file_mnt_user_ns(filp), dir, dentry);
+ write_lock(&ci->m_lock);
+ }
+ write_unlock(&ci->m_lock);
+
+ ksmbd_inode_free(ci);
+ }
+}
+
+static void __ksmbd_remove_durable_fd(struct ksmbd_file *fp)
+{
+ if (!has_file_id(fp->persistent_id))
+ return;
+
+ write_lock(&global_ft.lock);
+ idr_remove(global_ft.idr, fp->persistent_id);
+ write_unlock(&global_ft.lock);
+}
+
+static void __ksmbd_remove_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
+{
+ if (!has_file_id(fp->volatile_id))
+ return;
+
+ write_lock(&fp->f_ci->m_lock);
+ list_del_init(&fp->node);
+ write_unlock(&fp->f_ci->m_lock);
+
+ write_lock(&ft->lock);
+ idr_remove(ft->idr, fp->volatile_id);
+ write_unlock(&ft->lock);
+}
+
+static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
+{
+ struct file *filp;
+ struct ksmbd_lock *smb_lock, *tmp_lock;
+
+ fd_limit_close();
+ __ksmbd_remove_durable_fd(fp);
+ __ksmbd_remove_fd(ft, fp);
+
+ close_id_del_oplock(fp);
+ filp = fp->filp;
+
+ __ksmbd_inode_close(fp);
+ if (!IS_ERR_OR_NULL(filp))
+ fput(filp);
+
+ /* because the reference count of fp is 0, it is guaranteed that
+ * there are not accesses to fp->lock_list.
+ */
+ list_for_each_entry_safe(smb_lock, tmp_lock, &fp->lock_list, flist) {
+ spin_lock(&fp->conn->llist_lock);
+ list_del(&smb_lock->clist);
+ spin_unlock(&fp->conn->llist_lock);
+
+ list_del(&smb_lock->flist);
+ locks_free_lock(smb_lock->fl);
+ kfree(smb_lock);
+ }
+
+ if (ksmbd_stream_fd(fp))
+ kfree(fp->stream.name);
+ kmem_cache_free(filp_cache, fp);
+}
+
+static struct ksmbd_file *ksmbd_fp_get(struct ksmbd_file *fp)
+{
+ if (!atomic_inc_not_zero(&fp->refcount))
+ return NULL;
+ return fp;
+}
+
+static struct ksmbd_file *__ksmbd_lookup_fd(struct ksmbd_file_table *ft,
+ u64 id)
+{
+ struct ksmbd_file *fp;
+
+ if (!has_file_id(id))
+ return NULL;
+
+ read_lock(&ft->lock);
+ fp = idr_find(ft->idr, id);
+ if (fp)
+ fp = ksmbd_fp_get(fp);
+ read_unlock(&ft->lock);
+ return fp;
+}
+
+static void __put_fd_final(struct ksmbd_work *work, struct ksmbd_file *fp)
+{
+ __ksmbd_close_fd(&work->sess->file_table, fp);
+ atomic_dec(&work->conn->stats.open_files_count);
+}
+
+static void set_close_state_blocked_works(struct ksmbd_file *fp)
+{
+ struct ksmbd_work *cancel_work;
+
+ spin_lock(&fp->f_lock);
+ list_for_each_entry(cancel_work, &fp->blocked_works,
+ fp_entry) {
+ cancel_work->state = KSMBD_WORK_CLOSED;
+ cancel_work->cancel_fn(cancel_work->cancel_argv);
+ }
+ spin_unlock(&fp->f_lock);
+}
+
+int ksmbd_close_fd(struct ksmbd_work *work, u64 id)
+{
+ struct ksmbd_file *fp;
+ struct ksmbd_file_table *ft;
+
+ if (!has_file_id(id))
+ return 0;
+
+ ft = &work->sess->file_table;
+ read_lock(&ft->lock);
+ fp = idr_find(ft->idr, id);
+ if (fp) {
+ set_close_state_blocked_works(fp);
+
+ if (!atomic_dec_and_test(&fp->refcount))
+ fp = NULL;
+ }
+ read_unlock(&ft->lock);
+
+ if (!fp)
+ return -EINVAL;
+
+ __put_fd_final(work, fp);
+ return 0;
+}
+
+void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp)
+{
+ if (!fp)
+ return;
+
+ if (!atomic_dec_and_test(&fp->refcount))
+ return;
+ __put_fd_final(work, fp);
+}
+
+static bool __sanity_check(struct ksmbd_tree_connect *tcon, struct ksmbd_file *fp)
+{
+ if (!fp)
+ return false;
+ if (fp->tcon != tcon)
+ return false;
+ return true;
+}
+
+struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id)
+{
+ return __ksmbd_lookup_fd(&work->sess->file_table, id);
+}
+
+struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, u64 id)
+{
+ struct ksmbd_file *fp = __ksmbd_lookup_fd(&work->sess->file_table, id);
+
+ if (__sanity_check(work->tcon, fp))
+ return fp;
+
+ ksmbd_fd_put(work, fp);
+ return NULL;
+}
+
+struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
+ u64 pid)
+{
+ struct ksmbd_file *fp;
+
+ if (!has_file_id(id)) {
+ id = work->compound_fid;
+ pid = work->compound_pfid;
+ }
+
+ fp = __ksmbd_lookup_fd(&work->sess->file_table, id);
+ if (!__sanity_check(work->tcon, fp)) {
+ ksmbd_fd_put(work, fp);
+ return NULL;
+ }
+ if (fp->persistent_id != pid) {
+ ksmbd_fd_put(work, fp);
+ return NULL;
+ }
+ return fp;
+}
+
+struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id)
+{
+ return __ksmbd_lookup_fd(&global_ft, id);
+}
+
+struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid)
+{
+ struct ksmbd_file *fp = NULL;
+ unsigned int id;
+
+ read_lock(&global_ft.lock);
+ idr_for_each_entry(global_ft.idr, fp, id) {
+ if (!memcmp(fp->create_guid,
+ cguid,
+ SMB2_CREATE_GUID_SIZE)) {
+ fp = ksmbd_fp_get(fp);
+ break;
+ }
+ }
+ read_unlock(&global_ft.lock);
+
+ return fp;
+}
+
+struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode)
+{
+ struct ksmbd_file *lfp;
+ struct ksmbd_inode *ci;
+
+ ci = ksmbd_inode_lookup_by_vfsinode(inode);
+ if (!ci)
+ return NULL;
+
+ read_lock(&ci->m_lock);
+ list_for_each_entry(lfp, &ci->m_fp_list, node) {
+ if (inode == file_inode(lfp->filp)) {
+ atomic_dec(&ci->m_count);
+ lfp = ksmbd_fp_get(lfp);
+ read_unlock(&ci->m_lock);
+ return lfp;
+ }
+ }
+ atomic_dec(&ci->m_count);
+ read_unlock(&ci->m_lock);
+ return NULL;
+}
+
+#define OPEN_ID_TYPE_VOLATILE_ID (0)
+#define OPEN_ID_TYPE_PERSISTENT_ID (1)
+
+static void __open_id_set(struct ksmbd_file *fp, u64 id, int type)
+{
+ if (type == OPEN_ID_TYPE_VOLATILE_ID)
+ fp->volatile_id = id;
+ if (type == OPEN_ID_TYPE_PERSISTENT_ID)
+ fp->persistent_id = id;
+}
+
+static int __open_id(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
+ int type)
+{
+ u64 id = 0;
+ int ret;
+
+ if (type == OPEN_ID_TYPE_VOLATILE_ID && fd_limit_depleted()) {
+ __open_id_set(fp, KSMBD_NO_FID, type);
+ return -EMFILE;
+ }
+
+ idr_preload(GFP_KERNEL);
+ write_lock(&ft->lock);
+ ret = idr_alloc_cyclic(ft->idr, fp, 0, INT_MAX - 1, GFP_NOWAIT);
+ if (ret >= 0) {
+ id = ret;
+ ret = 0;
+ } else {
+ id = KSMBD_NO_FID;
+ fd_limit_close();
+ }
+
+ __open_id_set(fp, id, type);
+ write_unlock(&ft->lock);
+ idr_preload_end();
+ return ret;
+}
+
+unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp)
+{
+ __open_id(&global_ft, fp, OPEN_ID_TYPE_PERSISTENT_ID);
+ return fp->persistent_id;
+}
+
+struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
+{
+ struct ksmbd_file *fp;
+ int ret;
+
+ fp = kmem_cache_zalloc(filp_cache, GFP_KERNEL);
+ if (!fp) {
+ pr_err("Failed to allocate memory\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ INIT_LIST_HEAD(&fp->blocked_works);
+ INIT_LIST_HEAD(&fp->node);
+ INIT_LIST_HEAD(&fp->lock_list);
+ spin_lock_init(&fp->f_lock);
+ atomic_set(&fp->refcount, 1);
+
+ fp->filp = filp;
+ fp->conn = work->conn;
+ fp->tcon = work->tcon;
+ fp->volatile_id = KSMBD_NO_FID;
+ fp->persistent_id = KSMBD_NO_FID;
+ fp->f_ci = ksmbd_inode_get(fp);
+
+ if (!fp->f_ci) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ ret = __open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
+ if (ret) {
+ ksmbd_inode_put(fp->f_ci);
+ goto err_out;
+ }
+
+ atomic_inc(&work->conn->stats.open_files_count);
+ return fp;
+
+err_out:
+ kmem_cache_free(filp_cache, fp);
+ return ERR_PTR(ret);
+}
+
+static int
+__close_file_table_ids(struct ksmbd_file_table *ft,
+ struct ksmbd_tree_connect *tcon,
+ bool (*skip)(struct ksmbd_tree_connect *tcon,
+ struct ksmbd_file *fp))
+{
+ unsigned int id;
+ struct ksmbd_file *fp;
+ int num = 0;
+
+ idr_for_each_entry(ft->idr, fp, id) {
+ if (skip(tcon, fp))
+ continue;
+
+ set_close_state_blocked_works(fp);
+
+ if (!atomic_dec_and_test(&fp->refcount))
+ continue;
+ __ksmbd_close_fd(ft, fp);
+ num++;
+ }
+ return num;
+}
+
+static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon,
+ struct ksmbd_file *fp)
+{
+ return fp->tcon != tcon;
+}
+
+static bool session_fd_check(struct ksmbd_tree_connect *tcon,
+ struct ksmbd_file *fp)
+{
+ return false;
+}
+
+void ksmbd_close_tree_conn_fds(struct ksmbd_work *work)
+{
+ int num = __close_file_table_ids(&work->sess->file_table,
+ work->tcon,
+ tree_conn_fd_check);
+
+ atomic_sub(num, &work->conn->stats.open_files_count);
+}
+
+void ksmbd_close_session_fds(struct ksmbd_work *work)
+{
+ int num = __close_file_table_ids(&work->sess->file_table,
+ work->tcon,
+ session_fd_check);
+
+ atomic_sub(num, &work->conn->stats.open_files_count);
+}
+
+int ksmbd_init_global_file_table(void)
+{
+ return ksmbd_init_file_table(&global_ft);
+}
+
+void ksmbd_free_global_file_table(void)
+{
+ struct ksmbd_file *fp = NULL;
+ unsigned int id;
+
+ idr_for_each_entry(global_ft.idr, fp, id) {
+ __ksmbd_remove_durable_fd(fp);
+ kmem_cache_free(filp_cache, fp);
+ }
+
+ ksmbd_destroy_file_table(&global_ft);
+}
+
+int ksmbd_init_file_table(struct ksmbd_file_table *ft)
+{
+ ft->idr = kzalloc(sizeof(struct idr), GFP_KERNEL);
+ if (!ft->idr)
+ return -ENOMEM;
+
+ idr_init(ft->idr);
+ rwlock_init(&ft->lock);
+ return 0;
+}
+
+void ksmbd_destroy_file_table(struct ksmbd_file_table *ft)
+{
+ if (!ft->idr)
+ return;
+
+ __close_file_table_ids(ft, NULL, session_fd_check);
+ idr_destroy(ft->idr);
+ kfree(ft->idr);
+ ft->idr = NULL;
+}
+
+int ksmbd_init_file_cache(void)
+{
+ filp_cache = kmem_cache_create("ksmbd_file_cache",
+ sizeof(struct ksmbd_file), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!filp_cache)
+ goto out;
+
+ return 0;
+
+out:
+ pr_err("failed to allocate file cache\n");
+ return -ENOMEM;
+}
+
+void ksmbd_exit_file_cache(void)
+{
+ kmem_cache_destroy(filp_cache);
+}
diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h
new file mode 100644
index 000000000000..fcb13413fa8d
--- /dev/null
+++ b/fs/smb/server/vfs_cache.h
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2019 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __VFS_CACHE_H__
+#define __VFS_CACHE_H__
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/rwsem.h>
+#include <linux/spinlock.h>
+#include <linux/idr.h>
+#include <linux/workqueue.h>
+
+#include "vfs.h"
+
+/* Windows style file permissions for extended response */
+#define FILE_GENERIC_ALL 0x1F01FF
+#define FILE_GENERIC_READ 0x120089
+#define FILE_GENERIC_WRITE 0x120116
+#define FILE_GENERIC_EXECUTE 0X1200a0
+
+#define KSMBD_START_FID 0
+#define KSMBD_NO_FID (INT_MAX)
+#define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL)
+
+struct ksmbd_conn;
+struct ksmbd_session;
+
+struct ksmbd_lock {
+ struct file_lock *fl;
+ struct list_head clist;
+ struct list_head flist;
+ struct list_head llist;
+ unsigned int flags;
+ int cmd;
+ int zero_len;
+ unsigned long long start;
+ unsigned long long end;
+};
+
+struct stream {
+ char *name;
+ ssize_t size;
+};
+
+struct ksmbd_inode {
+ rwlock_t m_lock;
+ atomic_t m_count;
+ atomic_t op_count;
+ /* opinfo count for streams */
+ atomic_t sop_count;
+ struct inode *m_inode;
+ unsigned int m_flags;
+ struct hlist_node m_hash;
+ struct list_head m_fp_list;
+ struct list_head m_op_list;
+ struct oplock_info *m_opinfo;
+ __le32 m_fattr;
+};
+
+struct ksmbd_file {
+ struct file *filp;
+ u64 persistent_id;
+ u64 volatile_id;
+
+ spinlock_t f_lock;
+
+ struct ksmbd_inode *f_ci;
+ struct ksmbd_inode *f_parent_ci;
+ struct oplock_info __rcu *f_opinfo;
+ struct ksmbd_conn *conn;
+ struct ksmbd_tree_connect *tcon;
+
+ atomic_t refcount;
+ __le32 daccess;
+ __le32 saccess;
+ __le32 coption;
+ __le32 cdoption;
+ __u64 create_time;
+ __u64 itime;
+
+ bool is_nt_open;
+ bool attrib_only;
+
+ char client_guid[16];
+ char create_guid[16];
+ char app_instance_id[16];
+
+ struct stream stream;
+ struct list_head node;
+ struct list_head blocked_works;
+ struct list_head lock_list;
+
+ int durable_timeout;
+
+ /* if ls is happening on directory, below is valid*/
+ struct ksmbd_readdir_data readdir_data;
+ int dot_dotdot[2];
+};
+
+static inline void set_ctx_actor(struct dir_context *ctx,
+ filldir_t actor)
+{
+ ctx->actor = actor;
+}
+
+#define KSMBD_NR_OPEN_DEFAULT BITS_PER_LONG
+
+struct ksmbd_file_table {
+ rwlock_t lock;
+ struct idr *idr;
+};
+
+static inline bool has_file_id(u64 id)
+{
+ return id < KSMBD_NO_FID;
+}
+
+static inline bool ksmbd_stream_fd(struct ksmbd_file *fp)
+{
+ return fp->stream.name != NULL;
+}
+
+int ksmbd_init_file_table(struct ksmbd_file_table *ft);
+void ksmbd_destroy_file_table(struct ksmbd_file_table *ft);
+int ksmbd_close_fd(struct ksmbd_work *work, u64 id);
+struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, u64 id);
+struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id);
+struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
+ u64 pid);
+void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp);
+struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id);
+struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid);
+struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode);
+unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp);
+struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp);
+void ksmbd_close_tree_conn_fds(struct ksmbd_work *work);
+void ksmbd_close_session_fds(struct ksmbd_work *work);
+int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode);
+int ksmbd_init_global_file_table(void);
+void ksmbd_free_global_file_table(void);
+void ksmbd_set_fd_limit(unsigned long limit);
+
+/*
+ * INODE hash
+ */
+int __init ksmbd_inode_hash_init(void);
+void ksmbd_release_inode_hash(void);
+
+enum KSMBD_INODE_STATUS {
+ KSMBD_INODE_STATUS_OK,
+ KSMBD_INODE_STATUS_UNKNOWN,
+ KSMBD_INODE_STATUS_PENDING_DELETE,
+};
+
+int ksmbd_query_inode_status(struct inode *inode);
+bool ksmbd_inode_pending_delete(struct ksmbd_file *fp);
+void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp);
+void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp);
+void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
+ int file_info);
+int ksmbd_init_file_cache(void);
+void ksmbd_exit_file_cache(void);
+#endif /* __VFS_CACHE_H__ */
diff --git a/fs/smb/server/xattr.h b/fs/smb/server/xattr.h
new file mode 100644
index 000000000000..16499ca5c82d
--- /dev/null
+++ b/fs/smb/server/xattr.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2021 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef __XATTR_H__
+#define __XATTR_H__
+
+/*
+ * These are on-disk structures to store additional metadata into xattr to
+ * reproduce windows filesystem semantics. And they are encoded with NDR to
+ * compatible with samba's xattr meta format. The compatibility with samba
+ * is important because it can lose the information(file attribute,
+ * creation time, acls) about the existing files when switching between
+ * ksmbd and samba.
+ */
+
+/*
+ * Dos attribute flags used for what variable is valid.
+ */
+enum {
+ XATTR_DOSINFO_ATTRIB = 0x00000001,
+ XATTR_DOSINFO_EA_SIZE = 0x00000002,
+ XATTR_DOSINFO_SIZE = 0x00000004,
+ XATTR_DOSINFO_ALLOC_SIZE = 0x00000008,
+ XATTR_DOSINFO_CREATE_TIME = 0x00000010,
+ XATTR_DOSINFO_CHANGE_TIME = 0x00000020,
+ XATTR_DOSINFO_ITIME = 0x00000040
+};
+
+/*
+ * Dos attribute structure which is compatible with samba's one.
+ * Storing it into the xattr named "DOSATTRIB" separately from inode
+ * allows ksmbd to faithfully reproduce windows filesystem semantics
+ * on top of a POSIX filesystem.
+ */
+struct xattr_dos_attrib {
+ __u16 version; /* version 3 or version 4 */
+ __u32 flags; /* valid flags */
+ __u32 attr; /* Dos attribute */
+ __u32 ea_size; /* EA size */
+ __u64 size;
+ __u64 alloc_size;
+ __u64 create_time; /* File creation time */
+ __u64 change_time; /* File change time */
+ __u64 itime; /* Invented/Initial time */
+};
+
+/*
+ * Enumeration is used for computing posix acl hash.
+ */
+enum {
+ SMB_ACL_TAG_INVALID = 0,
+ SMB_ACL_USER,
+ SMB_ACL_USER_OBJ,
+ SMB_ACL_GROUP,
+ SMB_ACL_GROUP_OBJ,
+ SMB_ACL_OTHER,
+ SMB_ACL_MASK
+};
+
+#define SMB_ACL_READ 4
+#define SMB_ACL_WRITE 2
+#define SMB_ACL_EXECUTE 1
+
+struct xattr_acl_entry {
+ int type;
+ uid_t uid;
+ gid_t gid;
+ mode_t perm;
+};
+
+/*
+ * xattr_smb_acl structure is used for computing posix acl hash.
+ */
+struct xattr_smb_acl {
+ int count;
+ int next;
+ struct xattr_acl_entry entries[];
+};
+
+/* 64bytes hash in xattr_ntacl is computed with sha256 */
+#define XATTR_SD_HASH_TYPE_SHA256 0x1
+#define XATTR_SD_HASH_SIZE 64
+
+/*
+ * xattr_ntacl is used for storing ntacl and hashes.
+ * Hash is used for checking valid posix acl and ntacl in xattr.
+ */
+struct xattr_ntacl {
+ __u16 version; /* version 4*/
+ void *sd_buf;
+ __u32 sd_size;
+ __u16 hash_type; /* hash type */
+ __u8 desc[10]; /* posix_acl description */
+ __u16 desc_len;
+ __u64 current_time;
+ __u8 hash[XATTR_SD_HASH_SIZE]; /* 64bytes hash for ntacl */
+ __u8 posix_acl_hash[XATTR_SD_HASH_SIZE]; /* 64bytes hash for posix acl */
+};
+
+/* DOS ATTRIBUITE XATTR PREFIX */
+#define DOS_ATTRIBUTE_PREFIX "DOSATTRIB"
+#define DOS_ATTRIBUTE_PREFIX_LEN (sizeof(DOS_ATTRIBUTE_PREFIX) - 1)
+#define XATTR_NAME_DOS_ATTRIBUTE (XATTR_USER_PREFIX DOS_ATTRIBUTE_PREFIX)
+#define XATTR_NAME_DOS_ATTRIBUTE_LEN \
+ (sizeof(XATTR_USER_PREFIX DOS_ATTRIBUTE_PREFIX) - 1)
+
+/* STREAM XATTR PREFIX */
+#define STREAM_PREFIX "DosStream."
+#define STREAM_PREFIX_LEN (sizeof(STREAM_PREFIX) - 1)
+#define XATTR_NAME_STREAM (XATTR_USER_PREFIX STREAM_PREFIX)
+#define XATTR_NAME_STREAM_LEN (sizeof(XATTR_NAME_STREAM) - 1)
+
+/* SECURITY DESCRIPTOR(NTACL) XATTR PREFIX */
+#define SD_PREFIX "NTACL"
+#define SD_PREFIX_LEN (sizeof(SD_PREFIX) - 1)
+#define XATTR_NAME_SD (XATTR_SECURITY_PREFIX SD_PREFIX)
+#define XATTR_NAME_SD_LEN \
+ (sizeof(XATTR_SECURITY_PREFIX SD_PREFIX) - 1)
+
+#endif /* __XATTR_H__ */
diff --git a/fs/smbfs_common/Makefile b/fs/smbfs_common/Makefile
deleted file mode 100644
index cafc61a3bfc3..000000000000
--- a/fs/smbfs_common/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for Linux filesystem routines that are shared by client and server.
-#
-
-obj-$(CONFIG_SMBFS_COMMON) += cifs_arc4.o
-obj-$(CONFIG_SMBFS_COMMON) += cifs_md4.o
diff --git a/fs/smbfs_common/arc4.h b/fs/smbfs_common/arc4.h
deleted file mode 100644
index 12e71ec033a1..000000000000
--- a/fs/smbfs_common/arc4.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Common values for ARC4 Cipher Algorithm
- */
-
-#ifndef _CRYPTO_ARC4_H
-#define _CRYPTO_ARC4_H
-
-#include <linux/types.h>
-
-#define ARC4_MIN_KEY_SIZE 1
-#define ARC4_MAX_KEY_SIZE 256
-#define ARC4_BLOCK_SIZE 1
-
-struct arc4_ctx {
- u32 S[256];
- u32 x, y;
-};
-
-int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len);
-void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len);
-
-#endif /* _CRYPTO_ARC4_H */
diff --git a/fs/smbfs_common/cifs_arc4.c b/fs/smbfs_common/cifs_arc4.c
deleted file mode 100644
index 043e4cb839fa..000000000000
--- a/fs/smbfs_common/cifs_arc4.c
+++ /dev/null
@@ -1,74 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Cryptographic API
- *
- * ARC4 Cipher Algorithm
- *
- * Jon Oberheide <jon@oberheide.org>
- */
-
-#include <linux/module.h>
-#include "arc4.h"
-
-MODULE_LICENSE("GPL");
-
-int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len)
-{
- int i, j = 0, k = 0;
-
- ctx->x = 1;
- ctx->y = 0;
-
- for (i = 0; i < 256; i++)
- ctx->S[i] = i;
-
- for (i = 0; i < 256; i++) {
- u32 a = ctx->S[i];
-
- j = (j + in_key[k] + a) & 0xff;
- ctx->S[i] = ctx->S[j];
- ctx->S[j] = a;
- if (++k >= key_len)
- k = 0;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(cifs_arc4_setkey);
-
-void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len)
-{
- u32 *const S = ctx->S;
- u32 x, y, a, b;
- u32 ty, ta, tb;
-
- if (len == 0)
- return;
-
- x = ctx->x;
- y = ctx->y;
-
- a = S[x];
- y = (y + a) & 0xff;
- b = S[y];
-
- do {
- S[y] = a;
- a = (a + b) & 0xff;
- S[x] = b;
- x = (x + 1) & 0xff;
- ta = S[x];
- ty = (y + ta) & 0xff;
- tb = S[ty];
- *out++ = *in++ ^ S[a];
- if (--len == 0)
- break;
- y = ty;
- a = ta;
- b = tb;
- } while (true);
-
- ctx->x = x;
- ctx->y = y;
-}
-EXPORT_SYMBOL_GPL(cifs_arc4_crypt);
diff --git a/fs/smbfs_common/cifs_md4.c b/fs/smbfs_common/cifs_md4.c
deleted file mode 100644
index 50f78cfc6ce9..000000000000
--- a/fs/smbfs_common/cifs_md4.c
+++ /dev/null
@@ -1,197 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Cryptographic API.
- *
- * MD4 Message Digest Algorithm (RFC1320).
- *
- * Implementation derived from Andrew Tridgell and Steve French's
- * CIFS MD4 implementation, and the cryptoapi implementation
- * originally based on the public domain implementation written
- * by Colin Plumb in 1993.
- *
- * Copyright (c) Andrew Tridgell 1997-1998.
- * Modified by Steve French (sfrench@us.ibm.com) 2002
- * Copyright (c) Cryptoapi developers.
- * Copyright (c) 2002 David S. Miller (davem@redhat.com)
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-#include "md4.h"
-
-MODULE_LICENSE("GPL");
-
-static inline u32 lshift(u32 x, unsigned int s)
-{
- x &= 0xFFFFFFFF;
- return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
-}
-
-static inline u32 F(u32 x, u32 y, u32 z)
-{
- return (x & y) | ((~x) & z);
-}
-
-static inline u32 G(u32 x, u32 y, u32 z)
-{
- return (x & y) | (x & z) | (y & z);
-}
-
-static inline u32 H(u32 x, u32 y, u32 z)
-{
- return x ^ y ^ z;
-}
-
-#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
-#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s))
-#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s))
-
-static void md4_transform(u32 *hash, u32 const *in)
-{
- u32 a, b, c, d;
-
- a = hash[0];
- b = hash[1];
- c = hash[2];
- d = hash[3];
-
- ROUND1(a, b, c, d, in[0], 3);
- ROUND1(d, a, b, c, in[1], 7);
- ROUND1(c, d, a, b, in[2], 11);
- ROUND1(b, c, d, a, in[3], 19);
- ROUND1(a, b, c, d, in[4], 3);
- ROUND1(d, a, b, c, in[5], 7);
- ROUND1(c, d, a, b, in[6], 11);
- ROUND1(b, c, d, a, in[7], 19);
- ROUND1(a, b, c, d, in[8], 3);
- ROUND1(d, a, b, c, in[9], 7);
- ROUND1(c, d, a, b, in[10], 11);
- ROUND1(b, c, d, a, in[11], 19);
- ROUND1(a, b, c, d, in[12], 3);
- ROUND1(d, a, b, c, in[13], 7);
- ROUND1(c, d, a, b, in[14], 11);
- ROUND1(b, c, d, a, in[15], 19);
-
- ROUND2(a, b, c, d, in[0], 3);
- ROUND2(d, a, b, c, in[4], 5);
- ROUND2(c, d, a, b, in[8], 9);
- ROUND2(b, c, d, a, in[12], 13);
- ROUND2(a, b, c, d, in[1], 3);
- ROUND2(d, a, b, c, in[5], 5);
- ROUND2(c, d, a, b, in[9], 9);
- ROUND2(b, c, d, a, in[13], 13);
- ROUND2(a, b, c, d, in[2], 3);
- ROUND2(d, a, b, c, in[6], 5);
- ROUND2(c, d, a, b, in[10], 9);
- ROUND2(b, c, d, a, in[14], 13);
- ROUND2(a, b, c, d, in[3], 3);
- ROUND2(d, a, b, c, in[7], 5);
- ROUND2(c, d, a, b, in[11], 9);
- ROUND2(b, c, d, a, in[15], 13);
-
- ROUND3(a, b, c, d, in[0], 3);
- ROUND3(d, a, b, c, in[8], 9);
- ROUND3(c, d, a, b, in[4], 11);
- ROUND3(b, c, d, a, in[12], 15);
- ROUND3(a, b, c, d, in[2], 3);
- ROUND3(d, a, b, c, in[10], 9);
- ROUND3(c, d, a, b, in[6], 11);
- ROUND3(b, c, d, a, in[14], 15);
- ROUND3(a, b, c, d, in[1], 3);
- ROUND3(d, a, b, c, in[9], 9);
- ROUND3(c, d, a, b, in[5], 11);
- ROUND3(b, c, d, a, in[13], 15);
- ROUND3(a, b, c, d, in[3], 3);
- ROUND3(d, a, b, c, in[11], 9);
- ROUND3(c, d, a, b, in[7], 11);
- ROUND3(b, c, d, a, in[15], 15);
-
- hash[0] += a;
- hash[1] += b;
- hash[2] += c;
- hash[3] += d;
-}
-
-static inline void md4_transform_helper(struct md4_ctx *ctx)
-{
- le32_to_cpu_array(ctx->block, ARRAY_SIZE(ctx->block));
- md4_transform(ctx->hash, ctx->block);
-}
-
-int cifs_md4_init(struct md4_ctx *mctx)
-{
- memset(mctx, 0, sizeof(struct md4_ctx));
- mctx->hash[0] = 0x67452301;
- mctx->hash[1] = 0xefcdab89;
- mctx->hash[2] = 0x98badcfe;
- mctx->hash[3] = 0x10325476;
- mctx->byte_count = 0;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(cifs_md4_init);
-
-int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len)
-{
- const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
-
- mctx->byte_count += len;
-
- if (avail > len) {
- memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
- data, len);
- return 0;
- }
-
- memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
- data, avail);
-
- md4_transform_helper(mctx);
- data += avail;
- len -= avail;
-
- while (len >= sizeof(mctx->block)) {
- memcpy(mctx->block, data, sizeof(mctx->block));
- md4_transform_helper(mctx);
- data += sizeof(mctx->block);
- len -= sizeof(mctx->block);
- }
-
- memcpy(mctx->block, data, len);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(cifs_md4_update);
-
-int cifs_md4_final(struct md4_ctx *mctx, u8 *out)
-{
- const unsigned int offset = mctx->byte_count & 0x3f;
- char *p = (char *)mctx->block + offset;
- int padding = 56 - (offset + 1);
-
- *p++ = 0x80;
- if (padding < 0) {
- memset(p, 0x00, padding + sizeof(u64));
- md4_transform_helper(mctx);
- p = (char *)mctx->block;
- padding = 56;
- }
-
- memset(p, 0, padding);
- mctx->block[14] = mctx->byte_count << 3;
- mctx->block[15] = mctx->byte_count >> 29;
- le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
- sizeof(u64)) / sizeof(u32));
- md4_transform(mctx->hash, mctx->block);
- cpu_to_le32_array(mctx->hash, ARRAY_SIZE(mctx->hash));
- memcpy(out, mctx->hash, sizeof(mctx->hash));
- memset(mctx, 0, sizeof(*mctx));
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(cifs_md4_final);
diff --git a/fs/smbfs_common/md4.h b/fs/smbfs_common/md4.h
deleted file mode 100644
index 5337becc699a..000000000000
--- a/fs/smbfs_common/md4.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Common values for ARC4 Cipher Algorithm
- */
-
-#ifndef _CIFS_MD4_H
-#define _CIFS_MD4_H
-
-#include <linux/types.h>
-
-#define MD4_DIGEST_SIZE 16
-#define MD4_HMAC_BLOCK_SIZE 64
-#define MD4_BLOCK_WORDS 16
-#define MD4_HASH_WORDS 4
-
-struct md4_ctx {
- u32 hash[MD4_HASH_WORDS];
- u32 block[MD4_BLOCK_WORDS];
- u64 byte_count;
-};
-
-
-int cifs_md4_init(struct md4_ctx *mctx);
-int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len);
-int cifs_md4_final(struct md4_ctx *mctx, u8 *out);
-
-#endif /* _CIFS_MD4_H */
diff --git a/fs/smbfs_common/smb2pdu.h b/fs/smbfs_common/smb2pdu.h
deleted file mode 100644
index 7d605db3bb3b..000000000000
--- a/fs/smbfs_common/smb2pdu.h
+++ /dev/null
@@ -1,1702 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1 */
-#ifndef _COMMON_SMB2PDU_H
-#define _COMMON_SMB2PDU_H
-
-/*
- * Note that, due to trying to use names similar to the protocol specifications,
- * there are many mixed case field names in the structures below. Although
- * this does not match typical Linux kernel style, it is necessary to be
- * able to match against the protocol specfication.
- *
- * SMB2 commands
- * Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
- * (ie no useful data other than the SMB error code itself) and are marked such.
- * Knowing this helps avoid response buffer allocations and copy in some cases.
- */
-
-/* List of commands in host endian */
-#define SMB2_NEGOTIATE_HE 0x0000
-#define SMB2_SESSION_SETUP_HE 0x0001
-#define SMB2_LOGOFF_HE 0x0002 /* trivial request/resp */
-#define SMB2_TREE_CONNECT_HE 0x0003
-#define SMB2_TREE_DISCONNECT_HE 0x0004 /* trivial req/resp */
-#define SMB2_CREATE_HE 0x0005
-#define SMB2_CLOSE_HE 0x0006
-#define SMB2_FLUSH_HE 0x0007 /* trivial resp */
-#define SMB2_READ_HE 0x0008
-#define SMB2_WRITE_HE 0x0009
-#define SMB2_LOCK_HE 0x000A
-#define SMB2_IOCTL_HE 0x000B
-#define SMB2_CANCEL_HE 0x000C
-#define SMB2_ECHO_HE 0x000D
-#define SMB2_QUERY_DIRECTORY_HE 0x000E
-#define SMB2_CHANGE_NOTIFY_HE 0x000F
-#define SMB2_QUERY_INFO_HE 0x0010
-#define SMB2_SET_INFO_HE 0x0011
-#define SMB2_OPLOCK_BREAK_HE 0x0012
-
-/* The same list in little endian */
-#define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE)
-#define SMB2_SESSION_SETUP cpu_to_le16(SMB2_SESSION_SETUP_HE)
-#define SMB2_LOGOFF cpu_to_le16(SMB2_LOGOFF_HE)
-#define SMB2_TREE_CONNECT cpu_to_le16(SMB2_TREE_CONNECT_HE)
-#define SMB2_TREE_DISCONNECT cpu_to_le16(SMB2_TREE_DISCONNECT_HE)
-#define SMB2_CREATE cpu_to_le16(SMB2_CREATE_HE)
-#define SMB2_CLOSE cpu_to_le16(SMB2_CLOSE_HE)
-#define SMB2_FLUSH cpu_to_le16(SMB2_FLUSH_HE)
-#define SMB2_READ cpu_to_le16(SMB2_READ_HE)
-#define SMB2_WRITE cpu_to_le16(SMB2_WRITE_HE)
-#define SMB2_LOCK cpu_to_le16(SMB2_LOCK_HE)
-#define SMB2_IOCTL cpu_to_le16(SMB2_IOCTL_HE)
-#define SMB2_CANCEL cpu_to_le16(SMB2_CANCEL_HE)
-#define SMB2_ECHO cpu_to_le16(SMB2_ECHO_HE)
-#define SMB2_QUERY_DIRECTORY cpu_to_le16(SMB2_QUERY_DIRECTORY_HE)
-#define SMB2_CHANGE_NOTIFY cpu_to_le16(SMB2_CHANGE_NOTIFY_HE)
-#define SMB2_QUERY_INFO cpu_to_le16(SMB2_QUERY_INFO_HE)
-#define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE)
-#define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE)
-
-#define SMB2_INTERNAL_CMD cpu_to_le16(0xFFFF)
-
-#define NUMBER_OF_SMB2_COMMANDS 0x0013
-
-/*
- * Size of the session key (crypto key encrypted with the password
- */
-#define SMB2_NTLMV2_SESSKEY_SIZE 16
-#define SMB2_SIGNATURE_SIZE 16
-#define SMB2_HMACSHA256_SIZE 32
-#define SMB2_CMACAES_SIZE 16
-#define SMB3_GCM128_CRYPTKEY_SIZE 16
-#define SMB3_GCM256_CRYPTKEY_SIZE 32
-
-/*
- * Size of the smb3 encryption/decryption keys
- * This size is big enough to store any cipher key types.
- */
-#define SMB3_ENC_DEC_KEY_SIZE 32
-
-/*
- * Size of the smb3 signing key
- */
-#define SMB3_SIGN_KEY_SIZE 16
-
-#define CIFS_CLIENT_CHALLENGE_SIZE 8
-
-/* Maximum buffer size value we can send with 1 credit */
-#define SMB2_MAX_BUFFER_SIZE 65536
-
-/*
- * The default wsize is 1M for SMB2 (and for some CIFS cases).
- * find_get_pages seems to return a maximum of 256
- * pages in a single call. With PAGE_SIZE == 4k, this means we can
- * fill a single wsize request with a single call.
- */
-#define SMB3_DEFAULT_IOSIZE (4 * 1024 * 1024)
-
-/*
- * SMB2 Header Definition
- *
- * "MBZ" : Must be Zero
- * "BB" : BugBug, Something to check/review/analyze later
- * "PDU" : "Protocol Data Unit" (ie a network "frame")
- *
- */
-
-#define __SMB2_HEADER_STRUCTURE_SIZE 64
-#define SMB2_HEADER_STRUCTURE_SIZE \
- cpu_to_le16(__SMB2_HEADER_STRUCTURE_SIZE)
-
-#define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe)
-#define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
-#define SMB2_COMPRESSION_TRANSFORM_ID cpu_to_le32(0x424d53fc)
-
-/*
- * SMB2 flag definitions
- */
-#define SMB2_FLAGS_SERVER_TO_REDIR cpu_to_le32(0x00000001)
-#define SMB2_FLAGS_ASYNC_COMMAND cpu_to_le32(0x00000002)
-#define SMB2_FLAGS_RELATED_OPERATIONS cpu_to_le32(0x00000004)
-#define SMB2_FLAGS_SIGNED cpu_to_le32(0x00000008)
-#define SMB2_FLAGS_PRIORITY_MASK cpu_to_le32(0x00000070) /* SMB3.1.1 */
-#define SMB2_FLAGS_DFS_OPERATIONS cpu_to_le32(0x10000000)
-#define SMB2_FLAGS_REPLAY_OPERATION cpu_to_le32(0x20000000) /* SMB3 & up */
-
-/*
- * Definitions for SMB2 Protocol Data Units (network frames)
- *
- * See MS-SMB2.PDF specification for protocol details.
- * The Naming convention is the lower case version of the SMB2
- * command code name for the struct. Note that structures must be packed.
- *
- */
-
-/* See MS-SMB2 section 2.2.1 */
-struct smb2_hdr {
- __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */
- __le16 StructureSize; /* 64 */
- __le16 CreditCharge; /* MBZ */
- __le32 Status; /* Error from server */
- __le16 Command;
- __le16 CreditRequest; /* CreditResponse */
- __le32 Flags;
- __le32 NextCommand;
- __le64 MessageId;
- union {
- struct {
- __le32 ProcessId;
- __le32 TreeId;
- } __packed SyncId;
- __le64 AsyncId;
- } __packed Id;
- __le64 SessionId;
- __u8 Signature[16];
-} __packed;
-
-struct smb2_pdu {
- struct smb2_hdr hdr;
- __le16 StructureSize2; /* size of wct area (varies, request specific) */
-} __packed;
-
-#define SMB2_ERROR_STRUCTURE_SIZE2 9
-#define SMB2_ERROR_STRUCTURE_SIZE2_LE cpu_to_le16(SMB2_ERROR_STRUCTURE_SIZE2)
-
-struct smb2_err_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize;
- __u8 ErrorContextCount;
- __u8 Reserved;
- __le32 ByteCount; /* even if zero, at least one byte follows */
- __u8 ErrorData[1]; /* variable length */
-} __packed;
-
-#define SMB3_AES_CCM_NONCE 11
-#define SMB3_AES_GCM_NONCE 12
-
-/* Transform flags (for 3.0 dialect this flag indicates CCM */
-#define TRANSFORM_FLAG_ENCRYPTED 0x0001
-struct smb2_transform_hdr {
- __le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */
- __u8 Signature[16];
- __u8 Nonce[16];
- __le32 OriginalMessageSize;
- __u16 Reserved1;
- __le16 Flags; /* EncryptionAlgorithm for 3.0, enc enabled for 3.1.1 */
- __le64 SessionId;
-} __packed;
-
-
-/* See MS-SMB2 2.2.42 */
-struct smb2_compression_transform_hdr_unchained {
- __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */
- __le32 OriginalCompressedSegmentSize;
- __le16 CompressionAlgorithm;
- __le16 Flags;
- __le16 Length; /* if chained it is length, else offset */
-} __packed;
-
-/* See MS-SMB2 2.2.42.1 */
-#define SMB2_COMPRESSION_FLAG_NONE 0x0000
-#define SMB2_COMPRESSION_FLAG_CHAINED 0x0001
-
-struct compression_payload_header {
- __le16 CompressionAlgorithm;
- __le16 Flags;
- __le32 Length; /* length of compressed playload including field below if present */
- /* __le32 OriginalPayloadSize; */ /* optional, present when LZNT1, LZ77, LZ77+Huffman */
-} __packed;
-
-/* See MS-SMB2 2.2.42.2 */
-struct smb2_compression_transform_hdr_chained {
- __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */
- __le32 OriginalCompressedSegmentSize;
- /* struct compression_payload_header[] */
-} __packed;
-
-/* See MS-SMB2 2.2.42.2.2 */
-struct compression_pattern_payload_v1 {
- __le16 Pattern;
- __le16 Reserved1;
- __le16 Reserved2;
- __le32 Repetitions;
-} __packed;
-
-/* See MS-SMB2 section 2.2.9.2 */
-/* Context Types */
-#define SMB2_RESERVED_TREE_CONNECT_CONTEXT_ID 0x0000
-#define SMB2_REMOTED_IDENTITY_TREE_CONNECT_CONTEXT_ID cpu_to_le16(0x0001)
-
-struct tree_connect_contexts {
- __le16 ContextType;
- __le16 DataLength;
- __le32 Reserved;
- __u8 Data[];
-} __packed;
-
-/* Remoted identity tree connect context structures - see MS-SMB2 2.2.9.2.1 */
-struct smb3_blob_data {
- __le16 BlobSize;
- __u8 BlobData[];
-} __packed;
-
-/* Valid values for Attr */
-#define SE_GROUP_MANDATORY 0x00000001
-#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002
-#define SE_GROUP_ENABLED 0x00000004
-#define SE_GROUP_OWNER 0x00000008
-#define SE_GROUP_USE_FOR_DENY_ONLY 0x00000010
-#define SE_GROUP_INTEGRITY 0x00000020
-#define SE_GROUP_INTEGRITY_ENABLED 0x00000040
-#define SE_GROUP_RESOURCE 0x20000000
-#define SE_GROUP_LOGON_ID 0xC0000000
-
-/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */
-
-struct sid_array_data {
- __le16 SidAttrCount;
- /* SidAttrList - array of sid_attr_data structs */
-} __packed;
-
-struct luid_attr_data {
-
-} __packed;
-
-/*
- * struct privilege_data is the same as BLOB_DATA - see MS-SMB2 2.2.9.2.1.5
- * but with size of LUID_ATTR_DATA struct and BlobData set to LUID_ATTR DATA
- */
-
-struct privilege_array_data {
- __le16 PrivilegeCount;
- /* array of privilege_data structs */
-} __packed;
-
-struct remoted_identity_tcon_context {
- __le16 TicketType; /* must be 0x0001 */
- __le16 TicketSize; /* total size of this struct */
- __le16 User; /* offset to SID_ATTR_DATA struct with user info */
- __le16 UserName; /* offset to null terminated Unicode username string */
- __le16 Domain; /* offset to null terminated Unicode domain name */
- __le16 Groups; /* offset to SID_ARRAY_DATA struct with group info */
- __le16 RestrictedGroups; /* similar to above */
- __le16 Privileges; /* offset to PRIVILEGE_ARRAY_DATA struct */
- __le16 PrimaryGroup; /* offset to SID_ARRAY_DATA struct */
- __le16 Owner; /* offset to BLOB_DATA struct */
- __le16 DefaultDacl; /* offset to BLOB_DATA struct */
- __le16 DeviceGroups; /* offset to SID_ARRAY_DATA struct */
- __le16 UserClaims; /* offset to BLOB_DATA struct */
- __le16 DeviceClaims; /* offset to BLOB_DATA struct */
- __u8 TicketInfo[]; /* variable length buf - remoted identity data */
-} __packed;
-
-struct smb2_tree_connect_req_extension {
- __le32 TreeConnectContextOffset;
- __le16 TreeConnectContextCount;
- __u8 Reserved[10];
- __u8 PathName[]; /* variable sized array */
- /* followed by array of TreeConnectContexts */
-} __packed;
-
-/* Flags/Reserved for SMB3.1.1 */
-#define SMB2_TREE_CONNECT_FLAG_CLUSTER_RECONNECT cpu_to_le16(0x0001)
-#define SMB2_TREE_CONNECT_FLAG_REDIRECT_TO_OWNER cpu_to_le16(0x0002)
-#define SMB2_TREE_CONNECT_FLAG_EXTENSION_PRESENT cpu_to_le16(0x0004)
-
-struct smb2_tree_connect_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 9 */
- __le16 Flags; /* Flags in SMB3.1.1 */
- __le16 PathOffset;
- __le16 PathLength;
- __u8 Buffer[1]; /* variable length */
-} __packed;
-
-/* Possible ShareType values */
-#define SMB2_SHARE_TYPE_DISK 0x01
-#define SMB2_SHARE_TYPE_PIPE 0x02
-#define SMB2_SHARE_TYPE_PRINT 0x03
-
-/*
- * Possible ShareFlags - exactly one and only one of the first 4 caching flags
- * must be set (any of the remaining, SHI1005, flags may be set individually
- * or in combination.
- */
-#define SMB2_SHAREFLAG_MANUAL_CACHING 0x00000000
-#define SMB2_SHAREFLAG_AUTO_CACHING 0x00000010
-#define SMB2_SHAREFLAG_VDO_CACHING 0x00000020
-#define SMB2_SHAREFLAG_NO_CACHING 0x00000030
-#define SHI1005_FLAGS_DFS 0x00000001
-#define SHI1005_FLAGS_DFS_ROOT 0x00000002
-#define SHI1005_FLAGS_RESTRICT_EXCLUSIVE_OPENS 0x00000100
-#define SHI1005_FLAGS_FORCE_SHARED_DELETE 0x00000200
-#define SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING 0x00000400
-#define SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM 0x00000800
-#define SHI1005_FLAGS_FORCE_LEVELII_OPLOCK 0x00001000
-#define SHI1005_FLAGS_ENABLE_HASH_V1 0x00002000
-#define SHI1005_FLAGS_ENABLE_HASH_V2 0x00004000
-#define SHI1005_FLAGS_ENCRYPT_DATA 0x00008000
-#define SMB2_SHAREFLAG_IDENTITY_REMOTING 0x00040000 /* 3.1.1 */
-#define SMB2_SHAREFLAG_COMPRESS_DATA 0x00100000 /* 3.1.1 */
-#define SHI1005_FLAGS_ALL 0x0014FF33
-
-/* Possible share capabilities */
-#define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008) /* all dialects */
-#define SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY cpu_to_le32(0x00000010) /* 3.0 */
-#define SMB2_SHARE_CAP_SCALEOUT cpu_to_le32(0x00000020) /* 3.0 */
-#define SMB2_SHARE_CAP_CLUSTER cpu_to_le32(0x00000040) /* 3.0 */
-#define SMB2_SHARE_CAP_ASYMMETRIC cpu_to_le32(0x00000080) /* 3.02 */
-#define SMB2_SHARE_CAP_REDIRECT_TO_OWNER cpu_to_le32(0x00000100) /* 3.1.1 */
-
-struct smb2_tree_connect_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 16 */
- __u8 ShareType; /* see below */
- __u8 Reserved;
- __le32 ShareFlags; /* see below */
- __le32 Capabilities; /* see below */
- __le32 MaximalAccess;
-} __packed;
-
-struct smb2_tree_disconnect_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 4 */
- __le16 Reserved;
-} __packed;
-
-struct smb2_tree_disconnect_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 4 */
- __le16 Reserved;
-} __packed;
-
-
-/*
- * SMB2_NEGOTIATE_PROTOCOL See MS-SMB2 section 2.2.3
- */
-/* SecurityMode flags */
-#define SMB2_NEGOTIATE_SIGNING_ENABLED 0x0001
-#define SMB2_NEGOTIATE_SIGNING_ENABLED_LE cpu_to_le16(0x0001)
-#define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x0002
-#define SMB2_NEGOTIATE_SIGNING_REQUIRED_LE cpu_to_le16(0x0002)
-#define SMB2_SEC_MODE_FLAGS_ALL 0x0003
-
-/* Capabilities flags */
-#define SMB2_GLOBAL_CAP_DFS 0x00000001
-#define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */
-#define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */
-#define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x00000008 /* New to SMB3 */
-#define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */
-#define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */
-#define SMB2_GLOBAL_CAP_ENCRYPTION 0x00000040 /* New to SMB3 */
-/* Internal types */
-#define SMB2_NT_FIND 0x00100000
-#define SMB2_LARGE_FILES 0x00200000
-
-#define SMB2_CLIENT_GUID_SIZE 16
-#define SMB2_CREATE_GUID_SIZE 16
-
-/* Dialects */
-#define SMB10_PROT_ID 0x0000 /* local only, not sent on wire w/CIFS negprot */
-#define SMB20_PROT_ID 0x0202
-#define SMB21_PROT_ID 0x0210
-#define SMB2X_PROT_ID 0x02FF
-#define SMB30_PROT_ID 0x0300
-#define SMB302_PROT_ID 0x0302
-#define SMB311_PROT_ID 0x0311
-#define BAD_PROT_ID 0xFFFF
-
-#define SMB311_SALT_SIZE 32
-/* Hash Algorithm Types */
-#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001)
-#define SMB2_PREAUTH_HASH_SIZE 64
-
-/* Negotiate Contexts - ContextTypes. See MS-SMB2 section 2.2.3.1 for details */
-#define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1)
-#define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2)
-#define SMB2_COMPRESSION_CAPABILITIES cpu_to_le16(3)
-#define SMB2_NETNAME_NEGOTIATE_CONTEXT_ID cpu_to_le16(5)
-#define SMB2_TRANSPORT_CAPABILITIES cpu_to_le16(6)
-#define SMB2_RDMA_TRANSFORM_CAPABILITIES cpu_to_le16(7)
-#define SMB2_SIGNING_CAPABILITIES cpu_to_le16(8)
-#define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100)
-
-struct smb2_neg_context {
- __le16 ContextType;
- __le16 DataLength;
- __le32 Reserved;
- /* Followed by array of data. NOTE: some servers require padding to 8 byte boundary */
-} __packed;
-
-/*
- * SaltLength that the server send can be zero, so the only three required
- * fields (all __le16) end up six bytes total, so the minimum context data len
- * in the response is six bytes which accounts for
- *
- * HashAlgorithmCount, SaltLength, and 1 HashAlgorithm.
- */
-#define MIN_PREAUTH_CTXT_DATA_LEN 6
-
-struct smb2_preauth_neg_context {
- __le16 ContextType; /* 1 */
- __le16 DataLength;
- __le32 Reserved;
- __le16 HashAlgorithmCount; /* 1 */
- __le16 SaltLength;
- __le16 HashAlgorithms; /* HashAlgorithms[0] since only one defined */
- __u8 Salt[SMB311_SALT_SIZE];
-} __packed;
-
-/* Encryption Algorithms Ciphers */
-#define SMB2_ENCRYPTION_AES128_CCM cpu_to_le16(0x0001)
-#define SMB2_ENCRYPTION_AES128_GCM cpu_to_le16(0x0002)
-#define SMB2_ENCRYPTION_AES256_CCM cpu_to_le16(0x0003)
-#define SMB2_ENCRYPTION_AES256_GCM cpu_to_le16(0x0004)
-
-/* Min encrypt context data is one cipher so 2 bytes + 2 byte count field */
-#define MIN_ENCRYPT_CTXT_DATA_LEN 4
-struct smb2_encryption_neg_context {
- __le16 ContextType; /* 2 */
- __le16 DataLength;
- __le32 Reserved;
- /* CipherCount usally 2, but can be 3 when AES256-GCM enabled */
- __le16 CipherCount; /* AES128-GCM and AES128-CCM by default */
- __le16 Ciphers[];
-} __packed;
-
-/* See MS-SMB2 2.2.3.1.3 */
-#define SMB3_COMPRESS_NONE cpu_to_le16(0x0000)
-#define SMB3_COMPRESS_LZNT1 cpu_to_le16(0x0001)
-#define SMB3_COMPRESS_LZ77 cpu_to_le16(0x0002)
-#define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003)
-/* Pattern scanning algorithm See MS-SMB2 3.1.4.4.1 */
-#define SMB3_COMPRESS_PATTERN cpu_to_le16(0x0004) /* Pattern_V1 */
-
-/* Compression Flags */
-#define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE cpu_to_le32(0x00000000)
-#define SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED cpu_to_le32(0x00000001)
-
-struct smb2_compression_capabilities_context {
- __le16 ContextType; /* 3 */
- __le16 DataLength;
- __le32 Reserved;
- __le16 CompressionAlgorithmCount;
- __le16 Padding;
- __le32 Flags;
- __le16 CompressionAlgorithms[3];
- __u16 Pad; /* Some servers require pad to DataLen multiple of 8 */
- /* Check if pad needed */
-} __packed;
-
-/*
- * For smb2_netname_negotiate_context_id See MS-SMB2 2.2.3.1.4.
- * Its struct simply contains NetName, an array of Unicode characters
- */
-struct smb2_netname_neg_context {
- __le16 ContextType; /* 5 */
- __le16 DataLength;
- __le32 Reserved;
- __le16 NetName[]; /* hostname of target converted to UCS-2 */
-} __packed;
-
-/*
- * For smb2_transport_capabilities context see MS-SMB2 2.2.3.1.5
- * and 2.2.4.1.5
- */
-
-/* Flags */
-#define SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY 0x00000001
-
-struct smb2_transport_capabilities_context {
- __le16 ContextType; /* 6 */
- __le16 DataLength;
- __u32 Reserved;
- __le32 Flags;
- __u32 Pad;
-} __packed;
-
-/*
- * For rdma transform capabilities context see MS-SMB2 2.2.3.1.6
- * and 2.2.4.1.6
- */
-
-/* RDMA Transform IDs */
-#define SMB2_RDMA_TRANSFORM_NONE 0x0000
-#define SMB2_RDMA_TRANSFORM_ENCRYPTION 0x0001
-#define SMB2_RDMA_TRANSFORM_SIGNING 0x0002
-
-struct smb2_rdma_transform_capabilities_context {
- __le16 ContextType; /* 7 */
- __le16 DataLength;
- __u32 Reserved;
- __le16 TransformCount;
- __u16 Reserved1;
- __u32 Reserved2;
- __le16 RDMATransformIds[];
-} __packed;
-
-/*
- * For signing capabilities context see MS-SMB2 2.2.3.1.7
- * and 2.2.4.1.7
- */
-
-/* Signing algorithms */
-#define SIGNING_ALG_HMAC_SHA256 0
-#define SIGNING_ALG_HMAC_SHA256_LE cpu_to_le16(0)
-#define SIGNING_ALG_AES_CMAC 1
-#define SIGNING_ALG_AES_CMAC_LE cpu_to_le16(1)
-#define SIGNING_ALG_AES_GMAC 2
-#define SIGNING_ALG_AES_GMAC_LE cpu_to_le16(2)
-
-struct smb2_signing_capabilities {
- __le16 ContextType; /* 8 */
- __le16 DataLength;
- __le32 Reserved;
- __le16 SigningAlgorithmCount;
- __le16 SigningAlgorithms[];
- /* Followed by padding to 8 byte boundary (required by some servers) */
-} __packed;
-
-#define POSIX_CTXT_DATA_LEN 16
-struct smb2_posix_neg_context {
- __le16 ContextType; /* 0x100 */
- __le16 DataLength;
- __le32 Reserved;
- __u8 Name[16]; /* POSIX ctxt GUID 93AD25509CB411E7B42383DE968BCD7C */
-} __packed;
-
-struct smb2_negotiate_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 36 */
- __le16 DialectCount;
- __le16 SecurityMode;
- __le16 Reserved; /* MBZ */
- __le32 Capabilities;
- __u8 ClientGUID[SMB2_CLIENT_GUID_SIZE];
- /* In SMB3.02 and earlier next three were MBZ le64 ClientStartTime */
- __le32 NegotiateContextOffset; /* SMB3.1.1 only. MBZ earlier */
- __le16 NegotiateContextCount; /* SMB3.1.1 only. MBZ earlier */
- __le16 Reserved2;
- __le16 Dialects[];
-} __packed;
-
-struct smb2_negotiate_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 65 */
- __le16 SecurityMode;
- __le16 DialectRevision;
- __le16 NegotiateContextCount; /* Prior to SMB3.1.1 was Reserved & MBZ */
- __u8 ServerGUID[16];
- __le32 Capabilities;
- __le32 MaxTransactSize;
- __le32 MaxReadSize;
- __le32 MaxWriteSize;
- __le64 SystemTime; /* MBZ */
- __le64 ServerStartTime;
- __le16 SecurityBufferOffset;
- __le16 SecurityBufferLength;
- __le32 NegotiateContextOffset; /* Pre:SMB3.1.1 was reserved/ignored */
- __u8 Buffer[1]; /* variable length GSS security buffer */
-} __packed;
-
-
-/*
- * SMB2_SESSION_SETUP See MS-SMB2 section 2.2.5
- */
-/* Flags */
-#define SMB2_SESSION_REQ_FLAG_BINDING 0x01
-#define SMB2_SESSION_REQ_FLAG_ENCRYPT_DATA 0x04
-
-struct smb2_sess_setup_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 25 */
- __u8 Flags;
- __u8 SecurityMode;
- __le32 Capabilities;
- __le32 Channel;
- __le16 SecurityBufferOffset;
- __le16 SecurityBufferLength;
- __le64 PreviousSessionId;
- __u8 Buffer[1]; /* variable length GSS security buffer */
-} __packed;
-
-/* Currently defined SessionFlags */
-#define SMB2_SESSION_FLAG_IS_GUEST 0x0001
-#define SMB2_SESSION_FLAG_IS_GUEST_LE cpu_to_le16(0x0001)
-#define SMB2_SESSION_FLAG_IS_NULL 0x0002
-#define SMB2_SESSION_FLAG_IS_NULL_LE cpu_to_le16(0x0002)
-#define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004
-#define SMB2_SESSION_FLAG_ENCRYPT_DATA_LE cpu_to_le16(0x0004)
-
-struct smb2_sess_setup_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 9 */
- __le16 SessionFlags;
- __le16 SecurityBufferOffset;
- __le16 SecurityBufferLength;
- __u8 Buffer[1]; /* variable length GSS security buffer */
-} __packed;
-
-
-/*
- * SMB2_LOGOFF See MS-SMB2 section 2.2.7
- */
-struct smb2_logoff_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 4 */
- __le16 Reserved;
-} __packed;
-
-struct smb2_logoff_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 4 */
- __le16 Reserved;
-} __packed;
-
-
-/*
- * SMB2_CLOSE See MS-SMB2 section 2.2.15
- */
-/* Currently defined values for close flags */
-#define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001)
-struct smb2_close_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 24 */
- __le16 Flags;
- __le32 Reserved;
- __u64 PersistentFileId; /* opaque endianness */
- __u64 VolatileFileId; /* opaque endianness */
-} __packed;
-
-/*
- * Maximum size of a SMB2_CLOSE response is 64 (smb2 header) + 60 (data)
- */
-#define MAX_SMB2_CLOSE_RESPONSE_SIZE 124
-
-struct smb2_close_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* 60 */
- __le16 Flags;
- __le32 Reserved;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */
- __le64 EndOfFile;
- __le32 Attributes;
-} __packed;
-
-
-/*
- * SMB2_READ See MS-SMB2 section 2.2.19
- */
-/* For read request Flags field below, following flag is defined for SMB3.02 */
-#define SMB2_READFLAG_READ_UNBUFFERED 0x01
-#define SMB2_READFLAG_REQUEST_COMPRESSED 0x02 /* See MS-SMB2 2.2.19 */
-
-/* Channel field for read and write: exactly one of following flags can be set*/
-#define SMB2_CHANNEL_NONE cpu_to_le32(0x00000000)
-#define SMB2_CHANNEL_RDMA_V1 cpu_to_le32(0x00000001)
-#define SMB2_CHANNEL_RDMA_V1_INVALIDATE cpu_to_le32(0x00000002)
-#define SMB2_CHANNEL_RDMA_TRANSFORM cpu_to_le32(0x00000003)
-
-/* SMB2 read request without RFC1001 length at the beginning */
-struct smb2_read_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 49 */
- __u8 Padding; /* offset from start of SMB2 header to place read */
- __u8 Flags; /* MBZ unless SMB3.02 or later */
- __le32 Length;
- __le64 Offset;
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- __le32 MinimumCount;
- __le32 Channel; /* MBZ except for SMB3 or later */
- __le32 RemainingBytes;
- __le16 ReadChannelInfoOffset;
- __le16 ReadChannelInfoLength;
- __u8 Buffer[1];
-} __packed;
-
-/* Read flags */
-#define SMB2_READFLAG_RESPONSE_NONE cpu_to_le32(0x00000000)
-#define SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM cpu_to_le32(0x00000001)
-
-struct smb2_read_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 17 */
- __u8 DataOffset;
- __u8 Reserved;
- __le32 DataLength;
- __le32 DataRemaining;
- __le32 Flags;
- __u8 Buffer[1];
-} __packed;
-
-
-/*
- * SMB2_WRITE See MS-SMB2 section 2.2.21
- */
-/* For write request Flags field below the following flags are defined: */
-#define SMB2_WRITEFLAG_WRITE_THROUGH 0x00000001 /* SMB2.1 or later */
-#define SMB2_WRITEFLAG_WRITE_UNBUFFERED 0x00000002 /* SMB3.02 or later */
-
-struct smb2_write_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 49 */
- __le16 DataOffset; /* offset from start of SMB2 header to write data */
- __le32 Length;
- __le64 Offset;
- __u64 PersistentFileId; /* opaque endianness */
- __u64 VolatileFileId; /* opaque endianness */
- __le32 Channel; /* MBZ unless SMB3.02 or later */
- __le32 RemainingBytes;
- __le16 WriteChannelInfoOffset;
- __le16 WriteChannelInfoLength;
- __le32 Flags;
- __u8 Buffer[1];
-} __packed;
-
-struct smb2_write_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 17 */
- __u8 DataOffset;
- __u8 Reserved;
- __le32 DataLength;
- __le32 DataRemaining;
- __u32 Reserved2;
- __u8 Buffer[1];
-} __packed;
-
-
-/*
- * SMB2_FLUSH See MS-SMB2 section 2.2.17
- */
-struct smb2_flush_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 24 */
- __le16 Reserved1;
- __le32 Reserved2;
- __u64 PersistentFileId;
- __u64 VolatileFileId;
-} __packed;
-
-struct smb2_flush_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize;
- __le16 Reserved;
-} __packed;
-
-#define SMB2_LOCKFLAG_SHARED 0x0001
-#define SMB2_LOCKFLAG_EXCLUSIVE 0x0002
-#define SMB2_LOCKFLAG_UNLOCK 0x0004
-#define SMB2_LOCKFLAG_FAIL_IMMEDIATELY 0x0010
-#define SMB2_LOCKFLAG_MASK 0x0007
-
-struct smb2_lock_element {
- __le64 Offset;
- __le64 Length;
- __le32 Flags;
- __le32 Reserved;
-} __packed;
-
-struct smb2_lock_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 48 */
- __le16 LockCount;
- /*
- * The least significant four bits are the index, the other 28 bits are
- * the lock sequence number (0 to 64). See MS-SMB2 2.2.26
- */
- __le32 LockSequenceNumber;
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- /* Followed by at least one */
- struct smb2_lock_element locks[1];
-} __packed;
-
-struct smb2_lock_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 4 */
- __le16 Reserved;
-} __packed;
-
-struct smb2_echo_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 4 */
- __u16 Reserved;
-} __packed;
-
-struct smb2_echo_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 4 */
- __u16 Reserved;
-} __packed;
-
-/*
- * Valid FileInformation classes for query directory
- *
- * Note that these are a subset of the (file) QUERY_INFO levels defined
- * later in this file (but since QUERY_DIRECTORY uses equivalent numbers
- * we do not redefine them here)
- *
- * FileDirectoryInfomation 0x01
- * FileFullDirectoryInformation 0x02
- * FileIdFullDirectoryInformation 0x26
- * FileBothDirectoryInformation 0x03
- * FileIdBothDirectoryInformation 0x25
- * FileNamesInformation 0x0C
- * FileIdExtdDirectoryInformation 0x3C
- */
-
-/* search (query_directory) Flags field */
-#define SMB2_RESTART_SCANS 0x01
-#define SMB2_RETURN_SINGLE_ENTRY 0x02
-#define SMB2_INDEX_SPECIFIED 0x04
-#define SMB2_REOPEN 0x10
-
-struct smb2_query_directory_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 33 */
- __u8 FileInformationClass;
- __u8 Flags;
- __le32 FileIndex;
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- __le16 FileNameOffset;
- __le16 FileNameLength;
- __le32 OutputBufferLength;
- __u8 Buffer[1];
-} __packed;
-
-struct smb2_query_directory_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 9 */
- __le16 OutputBufferOffset;
- __le32 OutputBufferLength;
- __u8 Buffer[1];
-} __packed;
-
-/*
- * Maximum number of iovs we need for a set-info request.
- * The largest one is rename/hardlink
- * [0] : struct smb2_set_info_req + smb2_file_[rename|link]_info
- * [1] : path
- * [2] : compound padding
- */
-#define SMB2_SET_INFO_IOV_SIZE 3
-
-struct smb2_set_info_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 33 */
- __u8 InfoType;
- __u8 FileInfoClass;
- __le32 BufferLength;
- __le16 BufferOffset;
- __u16 Reserved;
- __le32 AdditionalInformation;
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- __u8 Buffer[1];
-} __packed;
-
-struct smb2_set_info_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 2 */
-} __packed;
-
-/*
- * SMB2_NOTIFY See MS-SMB2 section 2.2.35
- */
-/* notify flags */
-#define SMB2_WATCH_TREE 0x0001
-
-/* notify completion filter flags. See MS-FSCC 2.6 and MS-SMB2 2.2.35 */
-#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
-#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
-#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
-#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
-#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
-#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
-#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
-#define FILE_NOTIFY_CHANGE_EA 0x00000080
-#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
-#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
-#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
-#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
-
-/* SMB2 Notify Action Flags */
-#define FILE_ACTION_ADDED 0x00000001
-#define FILE_ACTION_REMOVED 0x00000002
-#define FILE_ACTION_MODIFIED 0x00000003
-#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
-#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
-#define FILE_ACTION_ADDED_STREAM 0x00000006
-#define FILE_ACTION_REMOVED_STREAM 0x00000007
-#define FILE_ACTION_MODIFIED_STREAM 0x00000008
-#define FILE_ACTION_REMOVED_BY_DELETE 0x00000009
-
-struct smb2_change_notify_req {
- struct smb2_hdr hdr;
- __le16 StructureSize;
- __le16 Flags;
- __le32 OutputBufferLength;
- __u64 PersistentFileId; /* opaque endianness */
- __u64 VolatileFileId; /* opaque endianness */
- __le32 CompletionFilter;
- __u32 Reserved;
-} __packed;
-
-struct smb2_change_notify_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 9 */
- __le16 OutputBufferOffset;
- __le32 OutputBufferLength;
- __u8 Buffer[1]; /* array of file notify structs */
-} __packed;
-
-
-/*
- * SMB2_CREATE See MS-SMB2 section 2.2.13
- */
-/* Oplock levels */
-#define SMB2_OPLOCK_LEVEL_NONE 0x00
-#define SMB2_OPLOCK_LEVEL_II 0x01
-#define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08
-#define SMB2_OPLOCK_LEVEL_BATCH 0x09
-#define SMB2_OPLOCK_LEVEL_LEASE 0xFF
-/* Non-spec internal type */
-#define SMB2_OPLOCK_LEVEL_NOCHANGE 0x99
-
-/* Impersonation Levels. See MS-WPO section 9.7 and MSDN-IMPERS */
-#define IL_ANONYMOUS cpu_to_le32(0x00000000)
-#define IL_IDENTIFICATION cpu_to_le32(0x00000001)
-#define IL_IMPERSONATION cpu_to_le32(0x00000002)
-#define IL_DELEGATE cpu_to_le32(0x00000003)
-
-/* File Attrubutes */
-#define FILE_ATTRIBUTE_READONLY 0x00000001
-#define FILE_ATTRIBUTE_HIDDEN 0x00000002
-#define FILE_ATTRIBUTE_SYSTEM 0x00000004
-#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
-#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
-#define FILE_ATTRIBUTE_NORMAL 0x00000080
-#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
-#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
-#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
-#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
-#define FILE_ATTRIBUTE_OFFLINE 0x00001000
-#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
-#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
-#define FILE_ATTRIBUTE_INTEGRITY_STREAM 0x00008000
-#define FILE_ATTRIBUTE_NO_SCRUB_DATA 0x00020000
-#define FILE_ATTRIBUTE__MASK 0x00007FB7
-
-#define FILE_ATTRIBUTE_READONLY_LE cpu_to_le32(0x00000001)
-#define FILE_ATTRIBUTE_HIDDEN_LE cpu_to_le32(0x00000002)
-#define FILE_ATTRIBUTE_SYSTEM_LE cpu_to_le32(0x00000004)
-#define FILE_ATTRIBUTE_DIRECTORY_LE cpu_to_le32(0x00000010)
-#define FILE_ATTRIBUTE_ARCHIVE_LE cpu_to_le32(0x00000020)
-#define FILE_ATTRIBUTE_NORMAL_LE cpu_to_le32(0x00000080)
-#define FILE_ATTRIBUTE_TEMPORARY_LE cpu_to_le32(0x00000100)
-#define FILE_ATTRIBUTE_SPARSE_FILE_LE cpu_to_le32(0x00000200)
-#define FILE_ATTRIBUTE_REPARSE_POINT_LE cpu_to_le32(0x00000400)
-#define FILE_ATTRIBUTE_COMPRESSED_LE cpu_to_le32(0x00000800)
-#define FILE_ATTRIBUTE_OFFLINE_LE cpu_to_le32(0x00001000)
-#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED_LE cpu_to_le32(0x00002000)
-#define FILE_ATTRIBUTE_ENCRYPTED_LE cpu_to_le32(0x00004000)
-#define FILE_ATTRIBUTE_INTEGRITY_STREAM_LE cpu_to_le32(0x00008000)
-#define FILE_ATTRIBUTE_NO_SCRUB_DATA_LE cpu_to_le32(0x00020000)
-#define FILE_ATTRIBUTE_MASK_LE cpu_to_le32(0x00007FB7)
-
-/* Desired Access Flags */
-#define FILE_READ_DATA_LE cpu_to_le32(0x00000001)
-#define FILE_LIST_DIRECTORY_LE cpu_to_le32(0x00000001)
-#define FILE_WRITE_DATA_LE cpu_to_le32(0x00000002)
-#define FILE_APPEND_DATA_LE cpu_to_le32(0x00000004)
-#define FILE_ADD_SUBDIRECTORY_LE cpu_to_le32(0x00000004)
-#define FILE_READ_EA_LE cpu_to_le32(0x00000008)
-#define FILE_WRITE_EA_LE cpu_to_le32(0x00000010)
-#define FILE_EXECUTE_LE cpu_to_le32(0x00000020)
-#define FILE_DELETE_CHILD_LE cpu_to_le32(0x00000040)
-#define FILE_READ_ATTRIBUTES_LE cpu_to_le32(0x00000080)
-#define FILE_WRITE_ATTRIBUTES_LE cpu_to_le32(0x00000100)
-#define FILE_DELETE_LE cpu_to_le32(0x00010000)
-#define FILE_READ_CONTROL_LE cpu_to_le32(0x00020000)
-#define FILE_WRITE_DAC_LE cpu_to_le32(0x00040000)
-#define FILE_WRITE_OWNER_LE cpu_to_le32(0x00080000)
-#define FILE_SYNCHRONIZE_LE cpu_to_le32(0x00100000)
-#define FILE_ACCESS_SYSTEM_SECURITY_LE cpu_to_le32(0x01000000)
-#define FILE_MAXIMAL_ACCESS_LE cpu_to_le32(0x02000000)
-#define FILE_GENERIC_ALL_LE cpu_to_le32(0x10000000)
-#define FILE_GENERIC_EXECUTE_LE cpu_to_le32(0x20000000)
-#define FILE_GENERIC_WRITE_LE cpu_to_le32(0x40000000)
-#define FILE_GENERIC_READ_LE cpu_to_le32(0x80000000)
-#define DESIRED_ACCESS_MASK cpu_to_le32(0xF21F01FF)
-
-
-#define FILE_READ_DESIRED_ACCESS_LE (FILE_READ_DATA_LE | \
- FILE_READ_EA_LE | \
- FILE_GENERIC_READ_LE)
-#define FILE_WRITE_DESIRE_ACCESS_LE (FILE_WRITE_DATA_LE | \
- FILE_APPEND_DATA_LE | \
- FILE_WRITE_EA_LE | \
- FILE_WRITE_ATTRIBUTES_LE | \
- FILE_GENERIC_WRITE_LE)
-
-/* ShareAccess Flags */
-#define FILE_SHARE_READ_LE cpu_to_le32(0x00000001)
-#define FILE_SHARE_WRITE_LE cpu_to_le32(0x00000002)
-#define FILE_SHARE_DELETE_LE cpu_to_le32(0x00000004)
-#define FILE_SHARE_ALL_LE cpu_to_le32(0x00000007)
-
-/* CreateDisposition Flags */
-#define FILE_SUPERSEDE_LE cpu_to_le32(0x00000000)
-#define FILE_OPEN_LE cpu_to_le32(0x00000001)
-#define FILE_CREATE_LE cpu_to_le32(0x00000002)
-#define FILE_OPEN_IF_LE cpu_to_le32(0x00000003)
-#define FILE_OVERWRITE_LE cpu_to_le32(0x00000004)
-#define FILE_OVERWRITE_IF_LE cpu_to_le32(0x00000005)
-#define FILE_CREATE_MASK_LE cpu_to_le32(0x00000007)
-
-#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \
- | FILE_READ_ATTRIBUTES)
-#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
- | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
-#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
-
-/* CreateOptions Flags */
-#define FILE_DIRECTORY_FILE_LE cpu_to_le32(0x00000001)
-/* same as #define CREATE_NOT_FILE_LE cpu_to_le32(0x00000001) */
-#define FILE_WRITE_THROUGH_LE cpu_to_le32(0x00000002)
-#define FILE_SEQUENTIAL_ONLY_LE cpu_to_le32(0x00000004)
-#define FILE_NO_INTERMEDIATE_BUFFERING_LE cpu_to_le32(0x00000008)
-#define FILE_NON_DIRECTORY_FILE_LE cpu_to_le32(0x00000040)
-#define FILE_COMPLETE_IF_OPLOCKED_LE cpu_to_le32(0x00000100)
-#define FILE_NO_EA_KNOWLEDGE_LE cpu_to_le32(0x00000200)
-#define FILE_RANDOM_ACCESS_LE cpu_to_le32(0x00000800)
-#define FILE_DELETE_ON_CLOSE_LE cpu_to_le32(0x00001000)
-#define FILE_OPEN_BY_FILE_ID_LE cpu_to_le32(0x00002000)
-#define FILE_OPEN_FOR_BACKUP_INTENT_LE cpu_to_le32(0x00004000)
-#define FILE_NO_COMPRESSION_LE cpu_to_le32(0x00008000)
-#define FILE_OPEN_REPARSE_POINT_LE cpu_to_le32(0x00200000)
-#define FILE_OPEN_NO_RECALL_LE cpu_to_le32(0x00400000)
-#define CREATE_OPTIONS_MASK_LE cpu_to_le32(0x00FFFFFF)
-
-#define FILE_READ_RIGHTS_LE (FILE_READ_DATA_LE | FILE_READ_EA_LE \
- | FILE_READ_ATTRIBUTES_LE)
-#define FILE_WRITE_RIGHTS_LE (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE \
- | FILE_WRITE_EA_LE | FILE_WRITE_ATTRIBUTES_LE)
-#define FILE_EXEC_RIGHTS_LE (FILE_EXECUTE_LE)
-
-/* Create Context Values */
-#define SMB2_CREATE_EA_BUFFER "ExtA" /* extended attributes */
-#define SMB2_CREATE_SD_BUFFER "SecD" /* security descriptor */
-#define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ"
-#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC"
-#define SMB2_CREATE_ALLOCATION_SIZE "AISi"
-#define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
-#define SMB2_CREATE_TIMEWARP_REQUEST "TWrp"
-#define SMB2_CREATE_QUERY_ON_DISK_ID "QFid"
-#define SMB2_CREATE_REQUEST_LEASE "RqLs"
-#define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q"
-#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C"
-#define SMB2_CREATE_TAG_POSIX "\x93\xAD\x25\x50\x9C\xB4\x11\xE7\xB4\x23\x83\xDE\x96\x8B\xCD\x7C"
-#define SMB2_CREATE_APP_INSTANCE_ID "\x45\xBC\xA6\x6A\xEF\xA7\xF7\x4A\x90\x08\xFA\x46\x2E\x14\x4D\x74"
-#define SMB2_CREATE_APP_INSTANCE_VERSION "\xB9\x82\xD0\xB7\x3B\x56\x07\x4F\xA0\x7B\x52\x4A\x81\x16\xA0\x10"
-#define SVHDX_OPEN_DEVICE_CONTEXT "\x9C\xCB\xCF\x9E\x04\xC1\xE6\x43\x98\x0E\x15\x8D\xA1\xF6\xEC\x83"
-#define SMB2_CREATE_TAG_AAPL "AAPL"
-
-/* Flag (SMB3 open response) values */
-#define SMB2_CREATE_FLAG_REPARSEPOINT 0x01
-
-struct create_context {
- __le32 Next;
- __le16 NameOffset;
- __le16 NameLength;
- __le16 Reserved;
- __le16 DataOffset;
- __le32 DataLength;
- __u8 Buffer[];
-} __packed;
-
-struct smb2_create_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 57 */
- __u8 SecurityFlags;
- __u8 RequestedOplockLevel;
- __le32 ImpersonationLevel;
- __le64 SmbCreateFlags;
- __le64 Reserved;
- __le32 DesiredAccess;
- __le32 FileAttributes;
- __le32 ShareAccess;
- __le32 CreateDisposition;
- __le32 CreateOptions;
- __le16 NameOffset;
- __le16 NameLength;
- __le32 CreateContextsOffset;
- __le32 CreateContextsLength;
- __u8 Buffer[];
-} __packed;
-
-struct smb2_create_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 89 */
- __u8 OplockLevel;
- __u8 Flags; /* 0x01 if reparse point */
- __le32 CreateAction;
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 AllocationSize;
- __le64 EndofFile;
- __le32 FileAttributes;
- __le32 Reserved2;
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- __le32 CreateContextsOffset;
- __le32 CreateContextsLength;
- __u8 Buffer[1];
-} __packed;
-
-struct create_posix {
- struct create_context ccontext;
- __u8 Name[16];
- __le32 Mode;
- __u32 Reserved;
-} __packed;
-
-#define SMB2_LEASE_NONE_LE cpu_to_le32(0x00)
-#define SMB2_LEASE_READ_CACHING_LE cpu_to_le32(0x01)
-#define SMB2_LEASE_HANDLE_CACHING_LE cpu_to_le32(0x02)
-#define SMB2_LEASE_WRITE_CACHING_LE cpu_to_le32(0x04)
-
-#define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE cpu_to_le32(0x02)
-
-#define SMB2_LEASE_KEY_SIZE 16
-
-struct lease_context {
- __u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
- __le32 LeaseState;
- __le32 LeaseFlags;
- __le64 LeaseDuration;
-} __packed;
-
-struct lease_context_v2 {
- __u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
- __le32 LeaseState;
- __le32 LeaseFlags;
- __le64 LeaseDuration;
- __u8 ParentLeaseKey[SMB2_LEASE_KEY_SIZE];
- __le16 Epoch;
- __le16 Reserved;
-} __packed;
-
-struct create_lease {
- struct create_context ccontext;
- __u8 Name[8];
- struct lease_context lcontext;
-} __packed;
-
-struct create_lease_v2 {
- struct create_context ccontext;
- __u8 Name[8];
- struct lease_context_v2 lcontext;
- __u8 Pad[4];
-} __packed;
-
-/* See MS-SMB2 2.2.31 and 2.2.32 */
-struct smb2_ioctl_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 57 */
- __le16 Reserved; /* offset from start of SMB2 header to write data */
- __le32 CtlCode;
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- __le32 InputOffset; /* Reserved MBZ */
- __le32 InputCount;
- __le32 MaxInputResponse;
- __le32 OutputOffset;
- __le32 OutputCount;
- __le32 MaxOutputResponse;
- __le32 Flags;
- __le32 Reserved2;
- __u8 Buffer[];
-} __packed;
-
-struct smb2_ioctl_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 49 */
- __le16 Reserved;
- __le32 CtlCode;
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- __le32 InputOffset; /* Reserved MBZ */
- __le32 InputCount;
- __le32 OutputOffset;
- __le32 OutputCount;
- __le32 Flags;
- __le32 Reserved2;
- __u8 Buffer[];
-} __packed;
-
-/* this goes in the ioctl buffer when doing FSCTL_SET_ZERO_DATA */
-struct file_zero_data_information {
- __le64 FileOffset;
- __le64 BeyondFinalZero;
-} __packed;
-
-/* See MS-FSCC 2.3.7 */
-struct duplicate_extents_to_file {
- __u64 PersistentFileHandle; /* source file handle, opaque endianness */
- __u64 VolatileFileHandle;
- __le64 SourceFileOffset;
- __le64 TargetFileOffset;
- __le64 ByteCount; /* Bytes to be copied */
-} __packed;
-
-/* See MS-FSCC 2.3.8 */
-#define DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC 0x00000001
-struct duplicate_extents_to_file_ex {
- __u64 PersistentFileHandle; /* source file handle, opaque endianness */
- __u64 VolatileFileHandle;
- __le64 SourceFileOffset;
- __le64 TargetFileOffset;
- __le64 ByteCount; /* Bytes to be copied */
- __le32 Flags;
- __le32 Reserved;
-} __packed;
-
-
-/* See MS-FSCC 2.3.20 */
-struct fsctl_get_integrity_information_rsp {
- __le16 ChecksumAlgorithm;
- __le16 Reserved;
- __le32 Flags;
- __le32 ChecksumChunkSizeInBytes;
- __le32 ClusterSizeInBytes;
-} __packed;
-
-/* See MS-FSCC 2.3.55 */
-struct fsctl_query_file_regions_req {
- __le64 FileOffset;
- __le64 Length;
- __le32 DesiredUsage;
- __le32 Reserved;
-} __packed;
-
-/* DesiredUsage flags see MS-FSCC 2.3.56.1 */
-#define FILE_USAGE_INVALID_RANGE 0x00000000
-#define FILE_USAGE_VALID_CACHED_DATA 0x00000001
-#define FILE_USAGE_NONCACHED_DATA 0x00000002
-
-struct file_region_info {
- __le64 FileOffset;
- __le64 Length;
- __le32 DesiredUsage;
- __le32 Reserved;
-} __packed;
-
-/* See MS-FSCC 2.3.56 */
-struct fsctl_query_file_region_rsp {
- __le32 Flags;
- __le32 TotalRegionEntryCount;
- __le32 RegionEntryCount;
- __u32 Reserved;
- struct file_region_info Regions[];
-} __packed;
-
-/* See MS-FSCC 2.3.58 */
-struct fsctl_query_on_disk_vol_info_rsp {
- __le64 DirectoryCount;
- __le64 FileCount;
- __le16 FsFormatMajVersion;
- __le16 FsFormatMinVersion;
- __u8 FsFormatName[24];
- __le64 FormatTime;
- __le64 LastUpdateTime;
- __u8 CopyrightInfo[68];
- __u8 AbstractInfo[68];
- __u8 FormatImplInfo[68];
- __u8 LastModifyImplInfo[68];
-} __packed;
-
-/* See MS-FSCC 2.3.73 */
-struct fsctl_set_integrity_information_req {
- __le16 ChecksumAlgorithm;
- __le16 Reserved;
- __le32 Flags;
-} __packed;
-
-/* See MS-FSCC 2.3.75 */
-struct fsctl_set_integrity_info_ex_req {
- __u8 EnableIntegrity;
- __u8 KeepState;
- __u16 Reserved;
- __le32 Flags;
- __u8 Version;
- __u8 Reserved2[7];
-} __packed;
-
-/* Integrity ChecksumAlgorithm choices for above */
-#define CHECKSUM_TYPE_NONE 0x0000
-#define CHECKSUM_TYPE_CRC64 0x0002
-#define CHECKSUM_TYPE_UNCHANGED 0xFFFF /* set only */
-
-/* Integrity flags for above */
-#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001
-
-/* Reparse structures - see MS-FSCC 2.1.2 */
-
-/* struct fsctl_reparse_info_req is empty, only response structs (see below) */
-struct reparse_data_buffer {
- __le32 ReparseTag;
- __le16 ReparseDataLength;
- __u16 Reserved;
- __u8 DataBuffer[]; /* Variable Length */
-} __packed;
-
-struct reparse_guid_data_buffer {
- __le32 ReparseTag;
- __le16 ReparseDataLength;
- __u16 Reserved;
- __u8 ReparseGuid[16];
- __u8 DataBuffer[]; /* Variable Length */
-} __packed;
-
-struct reparse_mount_point_data_buffer {
- __le32 ReparseTag;
- __le16 ReparseDataLength;
- __u16 Reserved;
- __le16 SubstituteNameOffset;
- __le16 SubstituteNameLength;
- __le16 PrintNameOffset;
- __le16 PrintNameLength;
- __u8 PathBuffer[]; /* Variable Length */
-} __packed;
-
-#define SYMLINK_FLAG_RELATIVE 0x00000001
-
-struct reparse_symlink_data_buffer {
- __le32 ReparseTag;
- __le16 ReparseDataLength;
- __u16 Reserved;
- __le16 SubstituteNameOffset;
- __le16 SubstituteNameLength;
- __le16 PrintNameOffset;
- __le16 PrintNameLength;
- __le32 Flags;
- __u8 PathBuffer[]; /* Variable Length */
-} __packed;
-
-/* See MS-FSCC 2.1.2.6 and cifspdu.h for struct reparse_posix_data */
-
-struct validate_negotiate_info_req {
- __le32 Capabilities;
- __u8 Guid[SMB2_CLIENT_GUID_SIZE];
- __le16 SecurityMode;
- __le16 DialectCount;
- __le16 Dialects[4]; /* BB expand this if autonegotiate > 4 dialects */
-} __packed;
-
-struct validate_negotiate_info_rsp {
- __le32 Capabilities;
- __u8 Guid[SMB2_CLIENT_GUID_SIZE];
- __le16 SecurityMode;
- __le16 Dialect; /* Dialect in use for the connection */
-} __packed;
-
-
-/* Possible InfoType values */
-#define SMB2_O_INFO_FILE 0x01
-#define SMB2_O_INFO_FILESYSTEM 0x02
-#define SMB2_O_INFO_SECURITY 0x03
-#define SMB2_O_INFO_QUOTA 0x04
-
-/* SMB2 Query Info see MS-SMB2 (2.2.37) or MS-DTYP */
-
-/* List of QUERY INFO levels (those also valid for QUERY_DIR are noted below */
-#define FILE_DIRECTORY_INFORMATION 1 /* also for QUERY_DIR */
-#define FILE_FULL_DIRECTORY_INFORMATION 2 /* also for QUERY_DIR */
-#define FILE_BOTH_DIRECTORY_INFORMATION 3 /* also for QUERY_DIR */
-#define FILE_BASIC_INFORMATION 4
-#define FILE_STANDARD_INFORMATION 5
-#define FILE_INTERNAL_INFORMATION 6
-#define FILE_EA_INFORMATION 7
-#define FILE_ACCESS_INFORMATION 8
-#define FILE_NAME_INFORMATION 9
-#define FILE_RENAME_INFORMATION 10
-#define FILE_LINK_INFORMATION 11
-#define FILE_NAMES_INFORMATION 12 /* also for QUERY_DIR */
-#define FILE_DISPOSITION_INFORMATION 13
-#define FILE_POSITION_INFORMATION 14
-#define FILE_FULL_EA_INFORMATION 15
-#define FILE_MODE_INFORMATION 16
-#define FILE_ALIGNMENT_INFORMATION 17
-#define FILE_ALL_INFORMATION 18
-#define FILE_ALLOCATION_INFORMATION 19
-#define FILE_END_OF_FILE_INFORMATION 20
-#define FILE_ALTERNATE_NAME_INFORMATION 21
-#define FILE_STREAM_INFORMATION 22
-#define FILE_PIPE_INFORMATION 23
-#define FILE_PIPE_LOCAL_INFORMATION 24
-#define FILE_PIPE_REMOTE_INFORMATION 25
-#define FILE_MAILSLOT_QUERY_INFORMATION 26
-#define FILE_MAILSLOT_SET_INFORMATION 27
-#define FILE_COMPRESSION_INFORMATION 28
-#define FILE_OBJECT_ID_INFORMATION 29
-/* Number 30 not defined in documents */
-#define FILE_MOVE_CLUSTER_INFORMATION 31
-#define FILE_QUOTA_INFORMATION 32
-#define FILE_REPARSE_POINT_INFORMATION 33
-#define FILE_NETWORK_OPEN_INFORMATION 34
-#define FILE_ATTRIBUTE_TAG_INFORMATION 35
-#define FILE_TRACKING_INFORMATION 36
-#define FILEID_BOTH_DIRECTORY_INFORMATION 37 /* also for QUERY_DIR */
-#define FILEID_FULL_DIRECTORY_INFORMATION 38 /* also for QUERY_DIR */
-#define FILE_VALID_DATA_LENGTH_INFORMATION 39
-#define FILE_SHORT_NAME_INFORMATION 40
-#define FILE_SFIO_RESERVE_INFORMATION 44
-#define FILE_SFIO_VOLUME_INFORMATION 45
-#define FILE_HARD_LINK_INFORMATION 46
-#define FILE_NORMALIZED_NAME_INFORMATION 48
-#define FILEID_GLOBAL_TX_DIRECTORY_INFORMATION 50
-#define FILE_STANDARD_LINK_INFORMATION 54
-#define FILE_ID_INFORMATION 59
-#define FILE_ID_EXTD_DIRECTORY_INFORMATION 60 /* also for QUERY_DIR */
-/* Used for Query Info and Find File POSIX Info for SMB3.1.1 and SMB1 */
-#define SMB_FIND_FILE_POSIX_INFO 0x064
-
-/* Security info type additionalinfo flags. */
-#define OWNER_SECINFO 0x00000001
-#define GROUP_SECINFO 0x00000002
-#define DACL_SECINFO 0x00000004
-#define SACL_SECINFO 0x00000008
-#define LABEL_SECINFO 0x00000010
-#define ATTRIBUTE_SECINFO 0x00000020
-#define SCOPE_SECINFO 0x00000040
-#define BACKUP_SECINFO 0x00010000
-#define UNPROTECTED_SACL_SECINFO 0x10000000
-#define UNPROTECTED_DACL_SECINFO 0x20000000
-#define PROTECTED_SACL_SECINFO 0x40000000
-#define PROTECTED_DACL_SECINFO 0x80000000
-
-/* Flags used for FileFullEAinfo */
-#define SL_RESTART_SCAN 0x00000001
-#define SL_RETURN_SINGLE_ENTRY 0x00000002
-#define SL_INDEX_SPECIFIED 0x00000004
-
-struct smb2_query_info_req {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 41 */
- __u8 InfoType;
- __u8 FileInfoClass;
- __le32 OutputBufferLength;
- __le16 InputBufferOffset;
- __u16 Reserved;
- __le32 InputBufferLength;
- __le32 AdditionalInformation;
- __le32 Flags;
- __u64 PersistentFileId;
- __u64 VolatileFileId;
- __u8 Buffer[1];
-} __packed;
-
-struct smb2_query_info_rsp {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 9 */
- __le16 OutputBufferOffset;
- __le32 OutputBufferLength;
- __u8 Buffer[1];
-} __packed;
-
-/*
- * PDU query infolevel structure definitions
- */
-
-/* See MS-FSCC 2.3.52 */
-struct file_allocated_range_buffer {
- __le64 file_offset;
- __le64 length;
-} __packed;
-
-struct smb2_file_internal_info {
- __le64 IndexNumber;
-} __packed; /* level 6 Query */
-
-struct smb2_file_rename_info { /* encoding of request for level 10 */
- __u8 ReplaceIfExists; /* 1 = replace existing target with new */
- /* 0 = fail if target already exists */
- __u8 Reserved[7];
- __u64 RootDirectory; /* MBZ for network operations (why says spec?) */
- __le32 FileNameLength;
- char FileName[]; /* New name to be assigned */
- /* padding - overall struct size must be >= 24 so filename + pad >= 6 */
-} __packed; /* level 10 Set */
-
-struct smb2_file_link_info { /* encoding of request for level 11 */
- __u8 ReplaceIfExists; /* 1 = replace existing link with new */
- /* 0 = fail if link already exists */
- __u8 Reserved[7];
- __u64 RootDirectory; /* MBZ for network operations (why says spec?) */
- __le32 FileNameLength;
- char FileName[]; /* Name to be assigned to new link */
-} __packed; /* level 11 Set */
-
-/*
- * This level 18, although with struct with same name is different from cifs
- * level 0x107. Level 0x107 has an extra u64 between AccessFlags and
- * CurrentByteOffset.
- */
-struct smb2_file_all_info { /* data block encoding of response to level 18 */
- __le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le32 Attributes;
- __u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */
- __le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */
- __le64 EndOfFile; /* size ie offset to first free byte in file */
- __le32 NumberOfLinks; /* hard links */
- __u8 DeletePending;
- __u8 Directory;
- __u16 Pad2; /* End of FILE_STANDARD_INFO equivalent */
- __le64 IndexNumber;
- __le32 EASize;
- __le32 AccessFlags;
- __le64 CurrentByteOffset;
- __le32 Mode;
- __le32 AlignmentRequirement;
- __le32 FileNameLength;
- char FileName[1];
-} __packed; /* level 18 Query */
-
-struct smb2_file_eof_info { /* encoding of request for level 10 */
- __le64 EndOfFile; /* new end of file value */
-} __packed; /* level 20 Set */
-
-/* Level 100 query info */
-struct smb311_posix_qinfo {
- __le64 CreationTime;
- __le64 LastAccessTime;
- __le64 LastWriteTime;
- __le64 ChangeTime;
- __le64 EndOfFile;
- __le64 AllocationSize;
- __le32 DosAttributes;
- __le64 Inode;
- __le32 DeviceId;
- __le32 Zero;
- /* beginning of POSIX Create Context Response */
- __le32 HardLinks;
- __le32 ReparseTag;
- __le32 Mode;
- u8 Sids[];
- /*
- * var sized owner SID
- * var sized group SID
- * le32 filenamelength
- * u8 filename[]
- */
-} __packed;
-
-/* File System Information Classes */
-#define FS_VOLUME_INFORMATION 1 /* Query */
-#define FS_LABEL_INFORMATION 2 /* Set */
-#define FS_SIZE_INFORMATION 3 /* Query */
-#define FS_DEVICE_INFORMATION 4 /* Query */
-#define FS_ATTRIBUTE_INFORMATION 5 /* Query */
-#define FS_CONTROL_INFORMATION 6 /* Query, Set */
-#define FS_FULL_SIZE_INFORMATION 7 /* Query */
-#define FS_OBJECT_ID_INFORMATION 8 /* Query, Set */
-#define FS_DRIVER_PATH_INFORMATION 9 /* Query */
-#define FS_SECTOR_SIZE_INFORMATION 11 /* SMB3 or later. Query */
-#define FS_POSIX_INFORMATION 100 /* SMB3.1.1 POSIX. Query */
-
-struct smb2_fs_full_size_info {
- __le64 TotalAllocationUnits;
- __le64 CallerAvailableAllocationUnits;
- __le64 ActualAvailableAllocationUnits;
- __le32 SectorsPerAllocationUnit;
- __le32 BytesPerSector;
-} __packed;
-
-#define SSINFO_FLAGS_ALIGNED_DEVICE 0x00000001
-#define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE 0x00000002
-#define SSINFO_FLAGS_NO_SEEK_PENALTY 0x00000004
-#define SSINFO_FLAGS_TRIM_ENABLED 0x00000008
-
-/* sector size info struct */
-struct smb3_fs_ss_info {
- __le32 LogicalBytesPerSector;
- __le32 PhysicalBytesPerSectorForAtomicity;
- __le32 PhysicalBytesPerSectorForPerf;
- __le32 FSEffPhysicalBytesPerSectorForAtomicity;
- __le32 Flags;
- __le32 ByteOffsetForSectorAlignment;
- __le32 ByteOffsetForPartitionAlignment;
-} __packed;
-
-/* File System Control Information */
-struct smb2_fs_control_info {
- __le64 FreeSpaceStartFiltering;
- __le64 FreeSpaceThreshold;
- __le64 FreeSpaceStopFiltering;
- __le64 DefaultQuotaThreshold;
- __le64 DefaultQuotaLimit;
- __le32 FileSystemControlFlags;
- __le32 Padding;
-} __packed;
-
-/* volume info struct - see MS-FSCC 2.5.9 */
-#define MAX_VOL_LABEL_LEN 32
-struct smb3_fs_vol_info {
- __le64 VolumeCreationTime;
- __u32 VolumeSerialNumber;
- __le32 VolumeLabelLength; /* includes trailing null */
- __u8 SupportsObjects; /* True if eg like NTFS, supports objects */
- __u8 Reserved;
- __u8 VolumeLabel[]; /* variable len */
-} __packed;
-
-/* See MS-SMB2 2.2.23 through 2.2.25 */
-struct smb2_oplock_break {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 24 */
- __u8 OplockLevel;
- __u8 Reserved;
- __le32 Reserved2;
- __u64 PersistentFid;
- __u64 VolatileFid;
-} __packed;
-
-#define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01)
-
-struct smb2_lease_break {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 44 */
- __le16 Epoch;
- __le32 Flags;
- __u8 LeaseKey[16];
- __le32 CurrentLeaseState;
- __le32 NewLeaseState;
- __le32 BreakReason;
- __le32 AccessMaskHint;
- __le32 ShareMaskHint;
-} __packed;
-
-struct smb2_lease_ack {
- struct smb2_hdr hdr;
- __le16 StructureSize; /* Must be 36 */
- __le16 Reserved;
- __le32 Flags;
- __u8 LeaseKey[16];
- __le32 LeaseState;
- __le64 LeaseDuration;
-} __packed;
-
-#define OP_BREAK_STRUCT_SIZE_20 24
-#define OP_BREAK_STRUCT_SIZE_21 36
-#endif /* _COMMON_SMB2PDU_H */
diff --git a/fs/smbfs_common/smbfsctl.h b/fs/smbfs_common/smbfsctl.h
deleted file mode 100644
index edd7fc2a7921..000000000000
--- a/fs/smbfs_common/smbfsctl.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-/*
- * SMB, CIFS, SMB2 FSCTL definitions
- *
- * Copyright (c) International Business Machines Corp., 2002,2013
- * Author(s): Steve French (sfrench@us.ibm.com)
- *
- */
-
-/* IOCTL information */
-/*
- * List of ioctl/fsctl function codes that are or could be useful in the
- * future to remote clients like cifs or SMB2/SMB3 client. This is probably
- * a slightly larger set of fsctls that NTFS local filesystem could handle,
- * including the seven below that we do not have struct definitions for.
- * Even with protocol definitions for most of these now available, we still
- * need to do some experimentation to identify which are practical to do
- * remotely. Some of the following, such as the encryption/compression ones
- * could be invoked from tools via a specialized hook into the VFS rather
- * than via the standard vfs entry points
- *
- * See MS-SMB2 Section 2.2.31 (last checked September 2021, all of that list are
- * below). Additional detail on less common ones can be found in MS-FSCC
- * section 2.3.
- */
-
-#ifndef __SMBFSCTL_H
-#define __SMBFSCTL_H
-
-/*
- * FSCTL values are 32 bits and are constructed as
- * <device 16bits> <access 2bits> <function 12bits> <method 2bits>
- */
-/* Device */
-#define FSCTL_DEVICE_DFS (0x0006 << 16)
-#define FSCTL_DEVICE_FILE_SYSTEM (0x0009 << 16)
-#define FSCTL_DEVICE_NAMED_PIPE (0x0011 << 16)
-#define FSCTL_DEVICE_NETWORK_FILE_SYSTEM (0x0014 << 16)
-#define FSCTL_DEVICE_MASK 0xffff0000
-/* Access */
-#define FSCTL_DEVICE_ACCESS_FILE_ANY_ACCESS (0x00 << 14)
-#define FSCTL_DEVICE_ACCESS_FILE_READ_ACCESS (0x01 << 14)
-#define FSCTL_DEVICE_ACCESS_FILE_WRITE_ACCESS (0x02 << 14)
-#define FSCTL_DEVICE_ACCESS_FILE_READ_WRITE_ACCESS (0x03 << 14)
-#define FSCTL_DEVICE_ACCESS_MASK 0x0000c000
-/* Function */
-#define FSCTL_DEVICE_FUNCTION_MASK 0x00003ffc
-/* Method */
-#define FSCTL_DEVICE_METHOD_BUFFERED 0x00
-#define FSCTL_DEVICE_METHOD_IN_DIRECT 0x01
-#define FSCTL_DEVICE_METHOD_OUT_DIRECT 0x02
-#define FSCTL_DEVICE_METHOD_NEITHER 0x03
-#define FSCTL_DEVICE_METHOD_MASK 0x00000003
-
-
-#define FSCTL_DFS_GET_REFERRALS 0x00060194
-#define FSCTL_DFS_GET_REFERRALS_EX 0x000601B0
-#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
-#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
-#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
-#define FSCTL_LOCK_VOLUME 0x00090018
-#define FSCTL_UNLOCK_VOLUME 0x0009001C
-#define FSCTL_IS_PATHNAME_VALID 0x0009002C /* BB add struct */
-#define FSCTL_GET_COMPRESSION 0x0009003C /* BB add struct */
-#define FSCTL_SET_COMPRESSION 0x0009C040 /* BB add struct */
-#define FSCTL_QUERY_FAT_BPB 0x00090058 /* BB add struct */
-/* Verify the next FSCTL number, we had it as 0x00090090 before */
-#define FSCTL_FILESYSTEM_GET_STATS 0x00090060 /* BB add struct */
-#define FSCTL_GET_NTFS_VOLUME_DATA 0x00090064 /* BB add struct */
-#define FSCTL_GET_RETRIEVAL_POINTERS 0x00090073 /* BB add struct */
-#define FSCTL_IS_VOLUME_DIRTY 0x00090078 /* BB add struct */
-#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x00090083 /* BB add struct */
-#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
-#define FSCTL_FIND_FILES_BY_SID 0x0009008F /* BB add struct */
-#define FSCTL_SET_OBJECT_ID 0x00090098 /* BB add struct */
-#define FSCTL_GET_OBJECT_ID 0x0009009C /* BB add struct */
-#define FSCTL_DELETE_OBJECT_ID 0x000900A0 /* BB add struct */
-#define FSCTL_SET_REPARSE_POINT 0x000900A4 /* BB add struct */
-#define FSCTL_GET_REPARSE_POINT 0x000900A8 /* BB add struct */
-#define FSCTL_DELETE_REPARSE_POINT 0x000900AC /* BB add struct */
-#define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */
-#define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */
-#define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */
-#define FSCTL_SET_ZERO_DATA 0x000980C8
-#define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */
-#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */
-#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */
-#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 /* BB add struct */
-#define FSCTL_READ_FILE_USN_DATA 0x000900EB /* BB add struct */
-#define FSCTL_WRITE_USN_CLOSE_RECORD 0x000900EF /* BB add struct */
-#define FSCTL_MARK_HANDLE 0x000900FC /* BB add struct */
-#define FSCTL_SIS_COPYFILE 0x00090100 /* BB add struct */
-#define FSCTL_RECALL_FILE 0x00090117 /* BB add struct */
-#define FSCTL_QUERY_SPARING_INFO 0x00090138 /* BB add struct */
-#define FSCTL_QUERY_ON_DISK_VOLUME_INFO 0x0009013C
-#define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */
-#define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */
-#define FSCTL_GET_INTEGRITY_INFORMATION 0x0009027C
-#define FSCTL_QUERY_FILE_REGIONS 0x00090284
-#define FSCTL_GET_REFS_VOLUME_DATA 0x000902D8 /* See MS-FSCC 2.3.24 */
-#define FSCTL_SET_INTEGRITY_INFORMATION_EXT 0x00090380
-#define FSCTL_GET_RETRIEVAL_POINTERS_AND_REFCOUNT 0x000903d3
-#define FSCTL_GET_RETRIEVAL_POINTER_COUNT 0x0009042b
-#define FSCTL_REFS_STREAM_SNAPSHOT_MANAGEMENT 0x00090440
-#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF
-#define FSCTL_OFFLOAD_READ 0x00094264 /* BB add struct */
-#define FSCTL_OFFLOAD_WRITE 0x00098268 /* BB add struct */
-#define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */
-#define FSCTL_FILE_LEVEL_TRIM 0x00098208 /* BB add struct */
-#define FSCTL_DUPLICATE_EXTENTS_TO_FILE 0x00098344
-#define FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX 0x000983E8
-#define FSCTL_SIS_LINK_FILES 0x0009C104
-#define FSCTL_SET_INTEGRITY_INFORMATION 0x0009C280
-#define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */
-#define FSCTL_PIPE_TRANSCEIVE 0x0011C017 /* BB add struct */
-/* strange that the number for this op is not sequential with previous op */
-#define FSCTL_PIPE_WAIT 0x00110018 /* BB add struct */
-/* Enumerate previous versions of a file */
-#define FSCTL_SRV_ENUMERATE_SNAPSHOTS 0x00144064
-/* Retrieve an opaque file reference for server-side data movement ie copy */
-#define FSCTL_SRV_REQUEST_RESUME_KEY 0x00140078
-#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4
-#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
-#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
-#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
-/* Perform server-side data movement */
-#define FSCTL_SRV_COPYCHUNK 0x001440F2
-#define FSCTL_SRV_COPYCHUNK_WRITE 0x001480F2
-#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */
-#define FSCTL_SRV_READ_HASH 0x001441BB /* BB add struct */
-
-/* See FSCC 2.1.2.5 */
-#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
-#define IO_REPARSE_TAG_HSM 0xC0000004
-#define IO_REPARSE_TAG_SIS 0x80000007
-#define IO_REPARSE_TAG_HSM2 0x80000006
-#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
-/* Used by the DFS filter. See MS-DFSC */
-#define IO_REPARSE_TAG_DFS 0x8000000A
-/* Used by the DFS filter See MS-DFSC */
-#define IO_REPARSE_TAG_DFSR 0x80000012
-#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
-/* See section MS-FSCC 2.1.2.4 */
-#define IO_REPARSE_TAG_SYMLINK 0xA000000C
-#define IO_REPARSE_TAG_DEDUP 0x80000013
-#define IO_REPARSE_APPXSTREAM 0xC0000014
-/* NFS symlinks, Win 8/SMB3 and later */
-#define IO_REPARSE_TAG_NFS 0x80000014
-/*
- * AzureFileSync - see
- * https://docs.microsoft.com/en-us/azure/storage/files/storage-sync-cloud-tiering
- */
-#define IO_REPARSE_TAG_AZ_FILE_SYNC 0x8000001e
-/* WSL reparse tags */
-#define IO_REPARSE_TAG_LX_SYMLINK 0xA000001D
-#define IO_REPARSE_TAG_AF_UNIX 0x80000023
-#define IO_REPARSE_TAG_LX_FIFO 0x80000024
-#define IO_REPARSE_TAG_LX_CHR 0x80000025
-#define IO_REPARSE_TAG_LX_BLK 0x80000026
-
-#define IO_REPARSE_TAG_LX_SYMLINK_LE cpu_to_le32(0xA000001D)
-#define IO_REPARSE_TAG_AF_UNIX_LE cpu_to_le32(0x80000023)
-#define IO_REPARSE_TAG_LX_FIFO_LE cpu_to_le32(0x80000024)
-#define IO_REPARSE_TAG_LX_CHR_LE cpu_to_le32(0x80000025)
-#define IO_REPARSE_TAG_LX_BLK_LE cpu_to_le32(0x80000026)
-
-/* fsctl flags */
-/* If Flags is set to this value, the request is an FSCTL not ioctl request */
-#define SMB2_0_IOCTL_IS_FSCTL 0x00000001
-#endif /* __SMBFSCTL_H */
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 67c0b9e734b6..911bab2998e2 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -751,6 +751,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_event_status
*event_status))
ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number))
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_hw_disable_all_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h
index 7b9571e00cc4..832c6464f063 100644
--- a/include/acpi/actbl3.h
+++ b/include/acpi/actbl3.h
@@ -443,6 +443,7 @@ struct acpi_tpm2_phy {
#define ACPI_TPM2_RESERVED10 10
#define ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC 11 /* V1.2 Rev 8 */
#define ACPI_TPM2_RESERVED 12
+#define ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON 13
/* Optional trailer appears after any start_method subtables */
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 6aeea1071b1b..78bcb1639999 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -244,6 +244,14 @@ struct gpio_irq_chip {
*/
bool initialized;
+ /**
+ * @domain_is_allocated_externally:
+ *
+ * True it the irq_domain was allocated outside of gpiolib, in which
+ * case gpiolib won't free the irq_domain itself.
+ */
+ bool domain_is_allocated_externally;
+
/**
* @init_hw: optional routine to initialize hardware before
* an IRQ chip will be added. This is quite useful when
diff --git a/include/linux/libata.h b/include/linux/libata.h
index fe990176e6ee..9713f4d8f15f 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -834,7 +834,7 @@ struct ata_port {
struct mutex scsi_scan_mutex;
struct delayed_work hotplug_task;
- struct work_struct scsi_rescan_task;
+ struct delayed_work scsi_rescan_task;
unsigned int hsm_task_state;
diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h
index 3c01c2bf84f5..505c908dbb81 100644
--- a/include/linux/regulator/pca9450.h
+++ b/include/linux/regulator/pca9450.h
@@ -196,11 +196,11 @@ enum {
/* PCA9450_REG_LDO3_VOLT bits */
#define LDO3_EN_MASK 0xC0
-#define LDO3OUT_MASK 0x0F
+#define LDO3OUT_MASK 0x1F
/* PCA9450_REG_LDO4_VOLT bits */
#define LDO4_EN_MASK 0xC0
-#define LDO4OUT_MASK 0x0F
+#define LDO4OUT_MASK 0x1F
/* PCA9450_REG_LDO5_VOLT bits */
#define LDO5L_EN_MASK 0xC0
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 22e96b7e1b44..f3a37cacb32c 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -467,7 +467,8 @@ struct nft_set_ops {
int (*init)(const struct nft_set *set,
const struct nft_set_desc *desc,
const struct nlattr * const nla[]);
- void (*destroy)(const struct nft_set *set);
+ void (*destroy)(const struct nft_ctx *ctx,
+ const struct nft_set *set);
void (*gc_init)(const struct nft_set *set);
unsigned int elemsize;
@@ -804,6 +805,8 @@ int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_expr *expr_array[]);
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
bool destroy_expr);
+void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set, void *elem);
/**
* struct nft_set_gc_batch_head - nf_tables set garbage collection batch
@@ -895,6 +898,7 @@ struct nft_expr_type {
enum nft_trans_phase {
NFT_TRANS_PREPARE,
+ NFT_TRANS_PREPARE_ERROR,
NFT_TRANS_ABORT,
NFT_TRANS_COMMIT,
NFT_TRANS_RELEASE
@@ -1002,7 +1006,10 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
return (void *)&rule->data[rule->dlen];
}
-void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule);
+void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule);
+void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule,
+ enum nft_trans_phase phase);
+void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule);
static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
struct nft_regs *regs,
@@ -1085,6 +1092,8 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
const struct nft_set_iter *iter,
struct nft_set_elem *elem);
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
+int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
+void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
enum nft_chain_types {
NFT_CHAIN_T_DEFAULT = 0,
@@ -1121,11 +1130,17 @@ int nft_chain_validate_dependency(const struct nft_chain *chain,
int nft_chain_validate_hooks(const struct nft_chain *chain,
unsigned int hook_flags);
+static inline bool nft_chain_binding(const struct nft_chain *chain)
+{
+ return chain->flags & NFT_CHAIN_BINDING;
+}
+
static inline bool nft_chain_is_bound(struct nft_chain *chain)
{
return (chain->flags & NFT_CHAIN_BINDING) && chain->bound;
}
+int nft_chain_add(struct nft_table *table, struct nft_chain *chain);
void nft_chain_del(struct nft_chain *chain);
void nf_tables_chain_destroy(struct nft_ctx *ctx);
@@ -1543,6 +1558,7 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
* struct nft_trans - nf_tables object update in transaction
*
* @list: used internally
+ * @binding_list: list of objects with possible bindings
* @msg_type: message type
* @put_net: ctx->net needs to be put
* @ctx: transaction context
@@ -1550,6 +1566,7 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
*/
struct nft_trans {
struct list_head list;
+ struct list_head binding_list;
int msg_type;
bool put_net;
struct nft_ctx ctx;
@@ -1560,6 +1577,7 @@ struct nft_trans_rule {
struct nft_rule *rule;
struct nft_flow_rule *flow;
u32 rule_id;
+ bool bound;
};
#define nft_trans_rule(trans) \
@@ -1568,6 +1586,8 @@ struct nft_trans_rule {
(((struct nft_trans_rule *)trans->data)->flow)
#define nft_trans_rule_id(trans) \
(((struct nft_trans_rule *)trans->data)->rule_id)
+#define nft_trans_rule_bound(trans) \
+ (((struct nft_trans_rule *)trans->data)->bound)
struct nft_trans_set {
struct nft_set *set;
@@ -1592,13 +1612,17 @@ struct nft_trans_set {
(((struct nft_trans_set *)trans->data)->gc_int)
struct nft_trans_chain {
+ struct nft_chain *chain;
bool update;
char *name;
struct nft_stats __percpu *stats;
u8 policy;
+ bool bound;
u32 chain_id;
};
+#define nft_trans_chain(trans) \
+ (((struct nft_trans_chain *)trans->data)->chain)
#define nft_trans_chain_update(trans) \
(((struct nft_trans_chain *)trans->data)->update)
#define nft_trans_chain_name(trans) \
@@ -1607,6 +1631,8 @@ struct nft_trans_chain {
(((struct nft_trans_chain *)trans->data)->stats)
#define nft_trans_chain_policy(trans) \
(((struct nft_trans_chain *)trans->data)->policy)
+#define nft_trans_chain_bound(trans) \
+ (((struct nft_trans_chain *)trans->data)->bound)
#define nft_trans_chain_id(trans) \
(((struct nft_trans_chain *)trans->data)->chain_id)
@@ -1679,6 +1705,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
struct nftables_pernet {
struct list_head tables;
struct list_head commit_list;
+ struct list_head binding_list;
struct list_head module_list;
struct list_head notify_list;
struct mutex commit_mutex;
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index dbc81f5eb553..9ec6f2e92ad3 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1039,6 +1039,7 @@ struct xfrm_offload {
struct sec_path {
int len;
int olen;
+ int verified_cnt;
struct xfrm_state *xvec[XFRM_MAX_DEPTH];
struct xfrm_offload ovec[XFRM_MAX_OFFLOAD_DEPTH];
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 86b2a82da546..54e353c9f919 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -68,7 +68,7 @@ DECLARE_EVENT_CLASS(writeback_folio_template,
strscpy_pad(__entry->name,
bdi_dev_name(mapping ? inode_to_bdi(mapping->host) :
NULL), 32);
- __entry->ino = mapping ? mapping->host->i_ino : 0;
+ __entry->ino = (mapping && mapping->host) ? mapping->host->i_ino : 0;
__entry->index = folio->index;
),
diff --git a/io_uring/net.c b/io_uring/net.c
index 05792a689994..2b44126a876e 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -190,7 +190,7 @@ static int io_sendmsg_copy_hdr(struct io_kiocb *req,
ret = sendmsg_copy_msghdr(&iomsg->msg, sr->umsg, sr->msg_flags,
&iomsg->free_iov);
/* save msg_control as sys_sendmsg() overwrites it */
- sr->msg_control = iomsg->msg.msg_control;
+ sr->msg_control = iomsg->msg.msg_control_user;
return ret;
}
@@ -289,7 +289,7 @@ int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
if (req_has_async_data(req)) {
kmsg = req->async_data;
- kmsg->msg.msg_control = sr->msg_control;
+ kmsg->msg.msg_control_user = sr->msg_control;
} else {
ret = io_sendmsg_copy_hdr(req, &iomsg);
if (ret)
@@ -313,6 +313,8 @@ int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK))
return io_setup_async_msg(req, kmsg, issue_flags);
if (ret > 0 && io_net_retry(sock, flags)) {
+ kmsg->msg.msg_controllen = 0;
+ kmsg->msg.msg_control = NULL;
sr->done_io += ret;
req->flags |= REQ_F_PARTIAL_IO;
return io_setup_async_msg(req, kmsg, issue_flags);
@@ -779,16 +781,19 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
flags = sr->msg_flags;
if (force_nonblock)
flags |= MSG_DONTWAIT;
- if (flags & MSG_WAITALL)
- min_ret = iov_iter_count(&kmsg->msg.msg_iter);
kmsg->msg.msg_get_inq = 1;
- if (req->flags & REQ_F_APOLL_MULTISHOT)
+ if (req->flags & REQ_F_APOLL_MULTISHOT) {
ret = io_recvmsg_multishot(sock, sr, kmsg, flags,
&mshot_finished);
- else
+ } else {
+ /* disable partial retry for recvmsg with cmsg attached */
+ if (flags & MSG_WAITALL && !kmsg->msg.msg_controllen)
+ min_ret = iov_iter_count(&kmsg->msg.msg_iter);
+
ret = __sys_recvmsg_sock(sock, &kmsg->msg, sr->umsg,
kmsg->uaddr, flags);
+ }
if (ret < min_ret) {
if (ret == -EAGAIN && force_nonblock) {
diff --git a/io_uring/poll.c b/io_uring/poll.c
index 4788073ec45d..869e1d2a4413 100644
--- a/io_uring/poll.c
+++ b/io_uring/poll.c
@@ -993,8 +993,9 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
struct io_hash_bucket *bucket;
struct io_kiocb *preq;
int ret2, ret = 0;
- bool locked;
+ bool locked = true;
+ io_ring_submit_lock(ctx, issue_flags);
preq = io_poll_find(ctx, true, &cd, &ctx->cancel_table, &bucket);
ret2 = io_poll_disarm(preq);
if (bucket)
@@ -1006,12 +1007,10 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
goto out;
}
- io_ring_submit_lock(ctx, issue_flags);
preq = io_poll_find(ctx, true, &cd, &ctx->cancel_table_locked, &bucket);
ret2 = io_poll_disarm(preq);
if (bucket)
spin_unlock(&bucket->lock);
- io_ring_submit_unlock(ctx, issue_flags);
if (ret2) {
ret = ret2;
goto out;
@@ -1035,7 +1034,7 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
if (poll_update->update_user_data)
preq->cqe.user_data = poll_update->new_user_data;
- ret2 = io_poll_add(preq, issue_flags);
+ ret2 = io_poll_add(preq, issue_flags & ~IO_URING_F_UNLOCKED);
/* successfully updated, don't complete poll request */
if (!ret2 || ret2 == -EIOCBQUEUED)
goto out;
@@ -1043,9 +1042,9 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
req_set_fail(preq);
io_req_set_res(preq, -ECANCELED, 0);
- locked = !(issue_flags & IO_URING_F_UNLOCKED);
io_req_task_complete(preq, &locked);
out:
+ io_ring_submit_unlock(ctx, issue_flags);
if (ret < 0) {
req_set_fail(req);
return ret;
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index a8838a32f750..8220caa488c5 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -735,13 +735,12 @@ static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
return offset < btf->hdr.str_len;
}
-static bool __btf_name_char_ok(char c, bool first, bool dot_ok)
+static bool __btf_name_char_ok(char c, bool first)
{
if ((first ? !isalpha(c) :
!isalnum(c)) &&
c != '_' &&
- ((c == '.' && !dot_ok) ||
- c != '.'))
+ c != '.')
return false;
return true;
}
@@ -758,20 +757,20 @@ static const char *btf_str_by_offset(const struct btf *btf, u32 offset)
return NULL;
}
-static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
+static bool __btf_name_valid(const struct btf *btf, u32 offset)
{
/* offset must be valid */
const char *src = btf_str_by_offset(btf, offset);
const char *src_limit;
- if (!__btf_name_char_ok(*src, true, dot_ok))
+ if (!__btf_name_char_ok(*src, true))
return false;
/* set a limit on identifier length */
src_limit = src + KSYM_NAME_LEN;
src++;
while (*src && src < src_limit) {
- if (!__btf_name_char_ok(*src, false, dot_ok))
+ if (!__btf_name_char_ok(*src, false))
return false;
src++;
}
@@ -779,17 +778,14 @@ static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
return !*src;
}
-/* Only C-style identifier is permitted. This can be relaxed if
- * necessary.
- */
static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
{
- return __btf_name_valid(btf, offset, false);
+ return __btf_name_valid(btf, offset);
}
static bool btf_name_valid_section(const struct btf *btf, u32 offset)
{
- return __btf_name_valid(btf, offset, true);
+ return __btf_name_valid(btf, offset);
}
static const char *__btf_name_by_offset(const struct btf *btf, u32 offset)
@@ -4044,7 +4040,7 @@ static s32 btf_var_check_meta(struct btf_verifier_env *env,
}
if (!t->name_off ||
- !__btf_name_valid(env->btf, t->name_off, true)) {
+ !__btf_name_valid(env->btf, t->name_off)) {
btf_verifier_log_type(env, t, "Invalid name");
return -EINVAL;
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 6c61dba26f4d..8633ec4f92df 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -3383,6 +3383,11 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
return prog->enforce_expected_attach_type &&
prog->expected_attach_type != attach_type ?
-EINVAL : 0;
+ case BPF_PROG_TYPE_KPROBE:
+ if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI &&
+ attach_type != BPF_TRACE_KPROBE_MULTI)
+ return -EINVAL;
+ return 0;
default:
return 0;
}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 280e689517e1..49c6b5e0855c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3061,6 +3061,11 @@ static void save_register_state(struct bpf_func_state *state,
scrub_spilled_slot(&state->stack[spi].slot_type[i - 1]);
}
+static bool is_bpf_st_mem(struct bpf_insn *insn)
+{
+ return BPF_CLASS(insn->code) == BPF_ST && BPF_MODE(insn->code) == BPF_MEM;
+}
+
/* check_stack_{read,write}_fixed_off functions track spill/fill of registers,
* stack boundary and alignment are checked in check_mem_access()
*/
@@ -3072,8 +3077,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
{
struct bpf_func_state *cur; /* state of the current function */
int i, slot = -off - 1, spi = slot / BPF_REG_SIZE, err;
- u32 dst_reg = env->prog->insnsi[insn_idx].dst_reg;
+ struct bpf_insn *insn = &env->prog->insnsi[insn_idx];
struct bpf_reg_state *reg = NULL;
+ u32 dst_reg = insn->dst_reg;
err = grow_stack_state(state, round_up(slot + 1, BPF_REG_SIZE));
if (err)
@@ -3122,6 +3128,16 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
return err;
}
save_register_state(state, spi, reg, size);
+ /* Break the relation on a narrowing spill. */
+ if (fls64(reg->umax_value) > BITS_PER_BYTE * size)
+ state->stack[spi].spilled_ptr.id = 0;
+ } else if (!reg && !(off % BPF_REG_SIZE) && is_bpf_st_mem(insn) &&
+ insn->imm != 0 && env->bpf_capable) {
+ struct bpf_reg_state fake_reg = {};
+
+ __mark_reg_known(&fake_reg, (u32)insn->imm);
+ fake_reg.type = SCALAR_VALUE;
+ save_register_state(state, spi, &fake_reg, size);
} else if (reg && is_spillable_regtype(reg->type)) {
/* register containing pointer is being spilled into stack */
if (size != BPF_REG_SIZE) {
@@ -3156,7 +3172,8 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
state->stack[spi].spilled_ptr.live |= REG_LIVE_WRITTEN;
/* when we zero initialize stack slots mark them as such */
- if (reg && register_is_null(reg)) {
+ if ((reg && register_is_null(reg)) ||
+ (!reg && is_bpf_st_mem(insn) && insn->imm == 0)) {
/* backtracking doesn't work for STACK_ZERO yet. */
err = mark_chain_precision(env, value_regno);
if (err)
@@ -13819,9 +13836,10 @@ static int jit_subprogs(struct bpf_verifier_env *env)
}
/* finally lock prog and jit images for all functions and
- * populate kallsysm
+ * populate kallsysm. Begin at the first subprogram, since
+ * bpf_prog_load will add the kallsyms for the main program.
*/
- for (i = 0; i < env->subprog_cnt; i++) {
+ for (i = 1; i < env->subprog_cnt; i++) {
bpf_prog_lock_ro(func[i]);
bpf_prog_kallsyms_add(func[i]);
}
@@ -13847,6 +13865,8 @@ static int jit_subprogs(struct bpf_verifier_env *env)
prog->jited = 1;
prog->bpf_func = func[0]->bpf_func;
prog->jited_len = func[0]->jited_len;
+ prog->aux->extable = func[0]->aux->extable;
+ prog->aux->num_exentries = func[0]->aux->num_exentries;
prog->aux->func = func;
prog->aux->func_cnt = env->subprog_cnt;
bpf_prog_jit_attempt_done(prog);
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 36c95626afec..2380c4daef33 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1782,7 +1782,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
{
struct cgroup *dcgrp = &dst_root->cgrp;
struct cgroup_subsys *ss;
- int ssid, i, ret;
+ int ssid, ret;
u16 dfl_disable_ss_mask = 0;
lockdep_assert_held(&cgroup_mutex);
@@ -1826,7 +1826,8 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
struct cgroup_root *src_root = ss->root;
struct cgroup *scgrp = &src_root->cgrp;
struct cgroup_subsys_state *css = cgroup_css(scgrp, ss);
- struct css_set *cset;
+ struct css_set *cset, *cset_pos;
+ struct css_task_iter *it;
WARN_ON(!css || cgroup_css(dcgrp, ss));
@@ -1844,9 +1845,22 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
css->cgroup = dcgrp;
spin_lock_irq(&css_set_lock);
- hash_for_each(css_set_table, i, cset, hlist)
+ WARN_ON(!list_empty(&dcgrp->e_csets[ss->id]));
+ list_for_each_entry_safe(cset, cset_pos, &scgrp->e_csets[ss->id],
+ e_cset_node[ss->id]) {
list_move_tail(&cset->e_cset_node[ss->id],
&dcgrp->e_csets[ss->id]);
+ /*
+ * all css_sets of scgrp together in same order to dcgrp,
+ * patch in-flight iterators to preserve correct iteration.
+ * since the iterator is always advanced right away and
+ * finished when it->cset_pos meets it->cset_head, so only
+ * update it->cset_head is enough here.
+ */
+ list_for_each_entry(it, &cset->task_iters, iters_node)
+ if (it->cset_head == &scgrp->e_csets[ss->id])
+ it->cset_head = &dcgrp->e_csets[ss->id];
+ }
spin_unlock_irq(&css_set_lock);
if (ss->css_rstat_flush) {
diff --git a/kernel/cgroup/legacy_freezer.c b/kernel/cgroup/legacy_freezer.c
index 936473203a6b..122dacb3a443 100644
--- a/kernel/cgroup/legacy_freezer.c
+++ b/kernel/cgroup/legacy_freezer.c
@@ -108,16 +108,18 @@ static int freezer_css_online(struct cgroup_subsys_state *css)
struct freezer *freezer = css_freezer(css);
struct freezer *parent = parent_freezer(freezer);
+ cpus_read_lock();
mutex_lock(&freezer_mutex);
freezer->state |= CGROUP_FREEZER_ONLINE;
if (parent && (parent->state & CGROUP_FREEZING)) {
freezer->state |= CGROUP_FREEZING_PARENT | CGROUP_FROZEN;
- static_branch_inc(&freezer_active);
+ static_branch_inc_cpuslocked(&freezer_active);
}
mutex_unlock(&freezer_mutex);
+ cpus_read_unlock();
return 0;
}
@@ -132,14 +134,16 @@ static void freezer_css_offline(struct cgroup_subsys_state *css)
{
struct freezer *freezer = css_freezer(css);
+ cpus_read_lock();
mutex_lock(&freezer_mutex);
if (freezer->state & CGROUP_FREEZING)
- static_branch_dec(&freezer_active);
+ static_branch_dec_cpuslocked(&freezer_active);
freezer->state = 0;
mutex_unlock(&freezer_mutex);
+ cpus_read_unlock();
}
static void freezer_css_free(struct cgroup_subsys_state *css)
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 65b8658da829..e9138cd7a0f5 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -218,19 +218,8 @@ static void tick_setup_device(struct tick_device *td,
* this cpu:
*/
if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) {
- ktime_t next_p;
- u32 rem;
-
tick_do_timer_cpu = cpu;
-
- next_p = ktime_get();
- div_u64_rem(next_p, TICK_NSEC, &rem);
- if (rem) {
- next_p -= rem;
- next_p += TICK_NSEC;
- }
-
- tick_next_period = next_p;
+ tick_next_period = ktime_get();
#ifdef CONFIG_NO_HZ_FULL
/*
* The boot CPU may be nohz_full, in which case set
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index a46506f7ec6d..d6fb6a676bbb 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -161,8 +161,19 @@ static ktime_t tick_init_jiffy_update(void)
raw_spin_lock(&jiffies_lock);
write_seqcount_begin(&jiffies_seq);
/* Did we start the jiffies update yet ? */
- if (last_jiffies_update == 0)
+ if (last_jiffies_update == 0) {
+ u32 rem;
+
+ /*
+ * Ensure that the tick is aligned to a multiple of
+ * TICK_NSEC.
+ */
+ div_u64_rem(tick_next_period, TICK_NSEC, &rem);
+ if (rem)
+ tick_next_period += TICK_NSEC - rem;
+
last_jiffies_update = tick_next_period;
+ }
period = last_jiffies_update;
write_seqcount_end(&jiffies_seq);
raw_spin_unlock(&jiffies_lock);
diff --git a/mm/maccess.c b/mm/maccess.c
index 074f6b086671..518a25667323 100644
--- a/mm/maccess.c
+++ b/mm/maccess.c
@@ -5,6 +5,7 @@
#include <linux/export.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
+#include <asm/tlb.h>
bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src,
size_t size)
@@ -113,11 +114,16 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
{
long ret = -EFAULT;
- if (access_ok(src, size)) {
- pagefault_disable();
- ret = __copy_from_user_inatomic(dst, src, size);
- pagefault_enable();
- }
+
+ if (!__access_ok(src, size))
+ return ret;
+
+ if (!nmi_uaccess_okay())
+ return ret;
+
+ pagefault_disable();
+ ret = __copy_from_user_inatomic(dst, src, size);
+ pagefault_enable();
if (ret)
return -EFAULT;
diff --git a/mm/memfd.c b/mm/memfd.c
index 08f5f8304746..b0104b49bf82 100644
--- a/mm/memfd.c
+++ b/mm/memfd.c
@@ -328,7 +328,8 @@ SYSCALL_DEFINE2(memfd_create,
if (flags & MFD_ALLOW_SEALING) {
file_seals = memfd_file_seals_ptr(file);
- *file_seals &= ~F_SEAL_SEAL;
+ if (file_seals)
+ *file_seals &= ~F_SEAL_SEAL;
}
fd_install(fd, file);
diff --git a/mm/usercopy.c b/mm/usercopy.c
index c1ee15a98633..434fce112acb 100644
--- a/mm/usercopy.c
+++ b/mm/usercopy.c
@@ -172,7 +172,7 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
return;
}
- if (is_vmalloc_addr(ptr)) {
+ if (is_vmalloc_addr(ptr) && !pagefault_disabled()) {
struct vmap_area *area = find_vmap_area(addr);
if (!area)
diff --git a/net/core/sock.c b/net/core/sock.c
index 83f590d8d085..b021cb9c95ef 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1355,12 +1355,6 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
__sock_set_mark(sk, val);
break;
case SO_RCVMARK:
- if (!sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
- !sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
- ret = -EPERM;
- break;
- }
-
sock_valbool_flag(sk, SOCK_RCVMARK, valbool);
break;
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 3969fa805679..ee848be59e65 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -340,6 +340,9 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_
secpath_reset(skb);
+ if (skb_needs_linearize(skb, skb->dev->features) &&
+ __skb_linearize(skb))
+ return -ENOMEM;
return 0;
}
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index ad2afeef4f10..eac206a290d0 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -164,6 +164,7 @@ int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb);
return 0;
}
+EXPORT_SYMBOL(xfrm4_udp_encap_rcv);
int xfrm4_rcv(struct sk_buff *skb)
{
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 242f4295940e..fc6a5be73263 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -375,6 +375,9 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features
secpath_reset(skb);
+ if (skb_needs_linearize(skb, skb->dev->features) &&
+ __skb_linearize(skb))
+ return -ENOMEM;
return 0;
}
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 04cbeefd8982..4907ab241d6b 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -86,6 +86,9 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
__be32 *udpdata32;
__u16 encap_type = up->encap_type;
+ if (skb->protocol == htons(ETH_P_IP))
+ return xfrm4_udp_encap_rcv(sk, skb);
+
/* if this is not encapsulated socket, then just return now */
if (!encap_type)
return 1;
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 59186997c3e2..a2c6ce40e426 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -53,7 +53,7 @@ enum {
static struct percpu_counter mptcp_sockets_allocated ____cacheline_aligned_in_smp;
static void __mptcp_destroy_sock(struct sock *sk);
-static void __mptcp_check_send_data_fin(struct sock *sk);
+static void mptcp_check_send_data_fin(struct sock *sk);
DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions);
static struct net_device mptcp_napi_dev;
@@ -420,8 +420,7 @@ static bool mptcp_pending_data_fin_ack(struct sock *sk)
{
struct mptcp_sock *msk = mptcp_sk(sk);
- return !__mptcp_check_fallback(msk) &&
- ((1 << sk->sk_state) &
+ return ((1 << sk->sk_state) &
(TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK)) &&
msk->write_seq == READ_ONCE(msk->snd_una);
}
@@ -579,9 +578,6 @@ static bool mptcp_check_data_fin(struct sock *sk)
u64 rcv_data_fin_seq;
bool ret = false;
- if (__mptcp_check_fallback(msk))
- return ret;
-
/* Need to ack a DATA_FIN received from a peer while this side
* of the connection is in ESTABLISHED, FIN_WAIT1, or FIN_WAIT2.
* msk->rcv_data_fin was set when parsing the incoming options
@@ -619,7 +615,8 @@ static bool mptcp_check_data_fin(struct sock *sk)
}
ret = true;
- mptcp_send_ack(msk);
+ if (!__mptcp_check_fallback(msk))
+ mptcp_send_ack(msk);
mptcp_close_wake_up(sk);
}
return ret;
@@ -846,12 +843,12 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
return true;
}
-static void __mptcp_flush_join_list(struct sock *sk)
+static void __mptcp_flush_join_list(struct sock *sk, struct list_head *join_list)
{
struct mptcp_subflow_context *tmp, *subflow;
struct mptcp_sock *msk = mptcp_sk(sk);
- list_for_each_entry_safe(subflow, tmp, &msk->join_list, node) {
+ list_for_each_entry_safe(subflow, tmp, join_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
bool slow = lock_sock_fast(ssk);
@@ -1606,7 +1603,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
if (!mptcp_timer_pending(sk))
mptcp_reset_timer(sk);
if (do_check_data_fin)
- __mptcp_check_send_data_fin(sk);
+ mptcp_check_send_data_fin(sk);
}
static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
@@ -1708,7 +1705,13 @@ static int mptcp_sendmsg_fastopen(struct sock *sk, struct sock *ssk, struct msgh
if (ret && ret != -EINPROGRESS && ret != -ERESTARTSYS && ret != -EINTR)
*copied_syn = 0;
} else if (ret && ret != -EINPROGRESS) {
- mptcp_disconnect(sk, 0);
+ /* The disconnect() op called by tcp_sendmsg_fastopen()/
+ * __inet_stream_connect() can fail, due to looking check,
+ * see mptcp_disconnect().
+ * Attempt it again outside the problematic scope.
+ */
+ if (!mptcp_disconnect(sk, 0))
+ sk->sk_socket->state = SS_UNCONNECTED;
}
return ret;
@@ -2375,7 +2378,10 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk);
if (!dispose_it) {
- tcp_disconnect(ssk, 0);
+ /* The MPTCP code never wait on the subflow sockets, TCP-level
+ * disconnect should never fail
+ */
+ WARN_ON_ONCE(tcp_disconnect(ssk, 0));
msk->subflow->state = SS_UNCONNECTED;
mptcp_subflow_ctx_reset(subflow);
release_sock(ssk);
@@ -2656,8 +2662,6 @@ static void mptcp_worker(struct work_struct *work)
if (unlikely((1 << state) & (TCPF_CLOSE | TCPF_LISTEN)))
goto unlock;
- mptcp_check_data_fin_ack(sk);
-
mptcp_check_fastclose(msk);
mptcp_pm_nl_work(msk);
@@ -2665,7 +2669,8 @@ static void mptcp_worker(struct work_struct *work)
if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
mptcp_check_for_eof(msk);
- __mptcp_check_send_data_fin(sk);
+ mptcp_check_send_data_fin(sk);
+ mptcp_check_data_fin_ack(sk);
mptcp_check_data_fin(sk);
if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
@@ -2799,13 +2804,19 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
break;
fallthrough;
case TCP_SYN_SENT:
- tcp_disconnect(ssk, O_NONBLOCK);
+ WARN_ON_ONCE(tcp_disconnect(ssk, O_NONBLOCK));
break;
default:
if (__mptcp_check_fallback(mptcp_sk(sk))) {
pr_debug("Fallback");
ssk->sk_shutdown |= how;
tcp_shutdown(ssk, how);
+
+ /* simulate the data_fin ack reception to let the state
+ * machine move forward
+ */
+ WRITE_ONCE(mptcp_sk(sk)->snd_una, mptcp_sk(sk)->snd_nxt);
+ mptcp_schedule_work(sk);
} else {
pr_debug("Sending DATA_FIN on subflow %p", ssk);
tcp_send_ack(ssk);
@@ -2845,7 +2856,7 @@ static int mptcp_close_state(struct sock *sk)
return next & TCP_ACTION_FIN;
}
-static void __mptcp_check_send_data_fin(struct sock *sk)
+static void mptcp_check_send_data_fin(struct sock *sk)
{
struct mptcp_subflow_context *subflow;
struct mptcp_sock *msk = mptcp_sk(sk);
@@ -2863,19 +2874,6 @@ static void __mptcp_check_send_data_fin(struct sock *sk)
WRITE_ONCE(msk->snd_nxt, msk->write_seq);
- /* fallback socket will not get data_fin/ack, can move to the next
- * state now
- */
- if (__mptcp_check_fallback(msk)) {
- WRITE_ONCE(msk->snd_una, msk->write_seq);
- if ((1 << sk->sk_state) & (TCPF_CLOSING | TCPF_LAST_ACK)) {
- inet_sk_state_store(sk, TCP_CLOSE);
- mptcp_close_wake_up(sk);
- } else if (sk->sk_state == TCP_FIN_WAIT1) {
- inet_sk_state_store(sk, TCP_FIN_WAIT2);
- }
- }
-
mptcp_for_each_subflow(msk, subflow) {
struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
@@ -2895,7 +2893,7 @@ static void __mptcp_wr_shutdown(struct sock *sk)
WRITE_ONCE(msk->write_seq, msk->write_seq + 1);
WRITE_ONCE(msk->snd_data_fin_enable, 1);
- __mptcp_check_send_data_fin(sk);
+ mptcp_check_send_data_fin(sk);
}
static void __mptcp_destroy_sock(struct sock *sk)
@@ -3051,13 +3049,18 @@ static int mptcp_disconnect(struct sock *sk, int flags)
{
struct mptcp_sock *msk = mptcp_sk(sk);
+ /* Deny disconnect if other threads are blocked in sk_wait_event()
+ * or inet_wait_for_connect().
+ */
+ if (sk->sk_wait_pending)
+ return -EBUSY;
+
/* We are on the fastopen error path. We can't call straight into the
* subflows cleanup code due to lock nesting (we are already under
- * msk->firstsocket lock). Do nothing and leave the cleanup to the
- * caller.
+ * msk->firstsocket lock).
*/
if (msk->fastopening)
- return 0;
+ return -EBUSY;
inet_sk_state_store(sk, TCP_CLOSE);
@@ -3118,6 +3121,7 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk,
inet_sk(nsk)->pinet6 = mptcp_inet6_sk(nsk);
#endif
+ nsk->sk_wait_pending = 0;
__mptcp_init_sock(nsk);
msk = mptcp_sk(nsk);
@@ -3320,9 +3324,14 @@ static void mptcp_release_cb(struct sock *sk)
for (;;) {
unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED) |
msk->push_pending;
+ struct list_head join_list;
+
if (!flags)
break;
+ INIT_LIST_HEAD(&join_list);
+ list_splice_init(&msk->join_list, &join_list);
+
/* the following actions acquire the subflow socket lock
*
* 1) can't be invoked in atomic scope
@@ -3333,8 +3342,9 @@ static void mptcp_release_cb(struct sock *sk)
msk->push_pending = 0;
msk->cb_flags &= ~flags;
spin_unlock_bh(&sk->sk_lock.slock);
+
if (flags & BIT(MPTCP_FLUSH_JOIN_LIST))
- __mptcp_flush_join_list(sk);
+ __mptcp_flush_join_list(sk, &join_list);
if (flags & BIT(MPTCP_PUSH_PENDING))
__mptcp_push_pending(sk, 0);
if (flags & BIT(MPTCP_RETRANSMIT))
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 336878f8a222..047e46dd028d 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1688,14 +1688,16 @@ static void subflow_state_change(struct sock *sk)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
struct sock *parent = subflow->conn;
+ struct mptcp_sock *msk;
__subflow_state_change(sk);
+ msk = mptcp_sk(parent);
if (subflow_simultaneous_connect(sk)) {
mptcp_propagate_sndbuf(parent, sk);
mptcp_do_fallback(sk);
- mptcp_rcv_space_init(mptcp_sk(parent), sk);
- pr_fallback(mptcp_sk(parent));
+ mptcp_rcv_space_init(msk, sk);
+ pr_fallback(msk);
subflow->conn_finished = 1;
mptcp_set_connected(parent);
}
@@ -1711,11 +1713,12 @@ static void subflow_state_change(struct sock *sk)
subflow_sched_work_if_closed(mptcp_sk(parent), sk);
- if (__mptcp_check_fallback(mptcp_sk(parent)) &&
- !subflow->rx_eof && subflow_is_done(sk)) {
- subflow->rx_eof = 1;
- mptcp_subflow_eof(parent);
- }
+ /* when the fallback subflow closes the rx side, trigger a 'dummy'
+ * ingress data fin, so that the msk state will follow along
+ */
+ if (__mptcp_check_fallback(msk) && subflow_is_done(sk) && msk->first == sk &&
+ mptcp_update_rcv_data_fin(msk, READ_ONCE(msk->ack_seq), true))
+ mptcp_schedule_work(parent);
}
void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk)
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 029171379884..7243079ef354 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -1225,6 +1225,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->transport_header = skb->network_header;
skb_set_inner_ipproto(skb, next_protocol);
+ skb_set_inner_mac_header(skb, skb_inner_network_offset(skb));
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
bool check = false;
@@ -1373,6 +1374,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
skb->transport_header = skb->network_header;
skb_set_inner_ipproto(skb, next_protocol);
+ skb_set_inner_mac_header(skb, skb_inner_network_offset(skb));
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
bool check = false;
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 13d4913266b4..7f71bdbc8267 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -153,6 +153,7 @@ static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
return NULL;
INIT_LIST_HEAD(&trans->list);
+ INIT_LIST_HEAD(&trans->binding_list);
trans->msg_type = msg_type;
trans->ctx = *ctx;
@@ -165,13 +166,20 @@ static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
}
-static void nft_trans_destroy(struct nft_trans *trans)
+static void nft_trans_list_del(struct nft_trans *trans)
{
list_del(&trans->list);
+ list_del(&trans->binding_list);
+}
+
+static void nft_trans_destroy(struct nft_trans *trans)
+{
+ nft_trans_list_del(trans);
kfree(trans);
}
-static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
+static void __nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set,
+ bool bind)
{
struct nftables_pernet *nft_net;
struct net *net = ctx->net;
@@ -185,16 +193,80 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
switch (trans->msg_type) {
case NFT_MSG_NEWSET:
if (nft_trans_set(trans) == set)
- nft_trans_set_bound(trans) = true;
+ nft_trans_set_bound(trans) = bind;
break;
case NFT_MSG_NEWSETELEM:
if (nft_trans_elem_set(trans) == set)
- nft_trans_elem_set_bound(trans) = true;
+ nft_trans_elem_set_bound(trans) = bind;
+ break;
+ }
+ }
+}
+
+static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ return __nft_set_trans_bind(ctx, set, true);
+}
+
+static void nft_set_trans_unbind(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ return __nft_set_trans_bind(ctx, set, false);
+}
+
+static void __nft_chain_trans_bind(const struct nft_ctx *ctx,
+ struct nft_chain *chain, bool bind)
+{
+ struct nftables_pernet *nft_net;
+ struct net *net = ctx->net;
+ struct nft_trans *trans;
+
+ if (!nft_chain_binding(chain))
+ return;
+
+ nft_net = nft_pernet(net);
+ list_for_each_entry_reverse(trans, &nft_net->commit_list, list) {
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWCHAIN:
+ if (nft_trans_chain(trans) == chain)
+ nft_trans_chain_bound(trans) = bind;
+ break;
+ case NFT_MSG_NEWRULE:
+ if (trans->ctx.chain == chain)
+ nft_trans_rule_bound(trans) = bind;
break;
}
}
}
+static void nft_chain_trans_bind(const struct nft_ctx *ctx,
+ struct nft_chain *chain)
+{
+ __nft_chain_trans_bind(ctx, chain, true);
+}
+
+int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
+{
+ if (!nft_chain_binding(chain))
+ return 0;
+
+ if (nft_chain_binding(ctx->chain))
+ return -EOPNOTSUPP;
+
+ if (chain->bound)
+ return -EBUSY;
+
+ chain->bound = true;
+ chain->use++;
+ nft_chain_trans_bind(ctx, chain);
+
+ return 0;
+}
+
+void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
+{
+ __nft_chain_trans_bind(ctx, chain, false);
+}
+
static int nft_netdev_register_hooks(struct net *net,
struct list_head *hook_list)
{
@@ -294,6 +366,19 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
{
struct nftables_pernet *nft_net = nft_pernet(net);
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWSET:
+ if (!nft_trans_set_update(trans) &&
+ nft_set_is_anonymous(nft_trans_set(trans)))
+ list_add_tail(&trans->binding_list, &nft_net->binding_list);
+ break;
+ case NFT_MSG_NEWCHAIN:
+ if (!nft_trans_chain_update(trans) &&
+ nft_chain_binding(nft_trans_chain(trans)))
+ list_add_tail(&trans->binding_list, &nft_net->binding_list);
+ break;
+ }
+
list_add_tail(&trans->list, &nft_net->commit_list);
}
@@ -340,8 +425,9 @@ static struct nft_trans *nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
ntohl(nla_get_be32(ctx->nla[NFTA_CHAIN_ID]));
}
}
-
+ nft_trans_chain(trans) = ctx->chain;
nft_trans_commit_list_add_tail(ctx->net, trans);
+
return trans;
}
@@ -359,8 +445,7 @@ static int nft_delchain(struct nft_ctx *ctx)
return 0;
}
-static void nft_rule_expr_activate(const struct nft_ctx *ctx,
- struct nft_rule *rule)
+void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule)
{
struct nft_expr *expr;
@@ -373,9 +458,8 @@ static void nft_rule_expr_activate(const struct nft_ctx *ctx,
}
}
-static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
- struct nft_rule *rule,
- enum nft_trans_phase phase)
+void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule,
+ enum nft_trans_phase phase)
{
struct nft_expr *expr;
@@ -497,6 +581,58 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
return __nft_trans_set_add(ctx, msg_type, set, NULL);
}
+static void nft_setelem_data_deactivate(const struct net *net,
+ const struct nft_set *set,
+ struct nft_set_elem *elem);
+
+static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
+ struct nft_set *set,
+ const struct nft_set_iter *iter,
+ struct nft_set_elem *elem)
+{
+ nft_setelem_data_deactivate(ctx->net, set, elem);
+
+ return 0;
+}
+
+struct nft_set_elem_catchall {
+ struct list_head list;
+ struct rcu_head rcu;
+ void *elem;
+};
+
+static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
+ struct nft_set *set)
+{
+ u8 genmask = nft_genmask_next(ctx->net);
+ struct nft_set_elem_catchall *catchall;
+ struct nft_set_elem elem;
+ struct nft_set_ext *ext;
+
+ list_for_each_entry(catchall, &set->catchall_list, list) {
+ ext = nft_set_elem_ext(set, catchall->elem);
+ if (!nft_set_elem_active(ext, genmask))
+ continue;
+
+ elem.priv = catchall->elem;
+ nft_setelem_data_deactivate(ctx->net, set, &elem);
+ break;
+ }
+}
+
+static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ struct nft_set_iter iter = {
+ .genmask = nft_genmask_next(ctx->net),
+ .fn = nft_mapelem_deactivate,
+ };
+
+ set->ops->walk(ctx, set, &iter);
+ WARN_ON_ONCE(iter.err);
+
+ nft_map_catchall_deactivate(ctx, set);
+}
+
static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
{
int err;
@@ -505,6 +641,9 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
if (err < 0)
return err;
+ if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_deactivate(ctx, set);
+
nft_deactivate_next(ctx->net, set);
ctx->table->use--;
@@ -2188,7 +2327,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
return 0;
}
-static int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
+int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
{
int err;
@@ -3315,8 +3454,7 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
return err;
}
-static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
- struct nft_rule *rule)
+void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule)
{
struct nft_expr *expr, *next;
@@ -3333,7 +3471,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
kfree(rule);
}
-void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
+static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
{
nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
nf_tables_rule_destroy(ctx, rule);
@@ -3421,12 +3559,6 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
return 0;
}
-struct nft_set_elem_catchall {
- struct list_head list;
- struct rcu_head rcu;
- void *elem;
-};
-
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
{
u8 genmask = nft_genmask_next(ctx->net);
@@ -3669,7 +3801,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
if (flow)
nft_flow_rule_destroy(flow);
err_release_rule:
- nft_rule_expr_deactivate(&ctx, rule, NFT_TRANS_PREPARE);
+ nft_rule_expr_deactivate(&ctx, rule, NFT_TRANS_PREPARE_ERROR);
nf_tables_rule_destroy(&ctx, rule);
err_release_expr:
for (i = 0; i < n; i++) {
@@ -4642,6 +4774,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
return -EOPNOTSUPP;
+ if (nft_set_is_anonymous(set))
+ return -EOPNOTSUPP;
+
err = nft_set_expr_alloc(&ctx, set, nla, exprs, &num_exprs, flags);
if (err < 0)
return err;
@@ -4745,7 +4880,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
for (i = 0; i < set->num_exprs; i++)
nft_expr_destroy(&ctx, set->exprs[i]);
err_set_destroy:
- ops->destroy(set);
+ ops->destroy(&ctx, set);
err_set_init:
kfree(set->name);
err_set_name:
@@ -4760,7 +4895,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
list_del_rcu(&catchall->list);
- nft_set_elem_destroy(set, catchall->elem, true);
+ nf_tables_set_elem_destroy(ctx, set, catchall->elem);
kfree_rcu(catchall, rcu);
}
}
@@ -4775,7 +4910,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
for (i = 0; i < set->num_exprs; i++)
nft_expr_destroy(ctx, set->exprs[i]);
- set->ops->destroy(set);
+ set->ops->destroy(ctx, set);
nft_set_catchall_destroy(ctx, set);
kfree(set->name);
kvfree(set);
@@ -4936,10 +5071,60 @@ static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
}
}
+static void nft_setelem_data_activate(const struct net *net,
+ const struct nft_set *set,
+ struct nft_set_elem *elem);
+
+static int nft_mapelem_activate(const struct nft_ctx *ctx,
+ struct nft_set *set,
+ const struct nft_set_iter *iter,
+ struct nft_set_elem *elem)
+{
+ nft_setelem_data_activate(ctx->net, set, elem);
+
+ return 0;
+}
+
+static void nft_map_catchall_activate(const struct nft_ctx *ctx,
+ struct nft_set *set)
+{
+ u8 genmask = nft_genmask_next(ctx->net);
+ struct nft_set_elem_catchall *catchall;
+ struct nft_set_elem elem;
+ struct nft_set_ext *ext;
+
+ list_for_each_entry(catchall, &set->catchall_list, list) {
+ ext = nft_set_elem_ext(set, catchall->elem);
+ if (!nft_set_elem_active(ext, genmask))
+ continue;
+
+ elem.priv = catchall->elem;
+ nft_setelem_data_activate(ctx->net, set, &elem);
+ break;
+ }
+}
+
+static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set)
+{
+ struct nft_set_iter iter = {
+ .genmask = nft_genmask_next(ctx->net),
+ .fn = nft_mapelem_activate,
+ };
+
+ set->ops->walk(ctx, set, &iter);
+ WARN_ON_ONCE(iter.err);
+
+ nft_map_catchall_activate(ctx, set);
+}
+
void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set)
{
- if (nft_set_is_anonymous(set))
+ if (nft_set_is_anonymous(set)) {
+ if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_activate(ctx, set);
+
nft_clear(ctx->net, set);
+ }
set->use++;
}
@@ -4950,14 +5135,28 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
enum nft_trans_phase phase)
{
switch (phase) {
- case NFT_TRANS_PREPARE:
+ case NFT_TRANS_PREPARE_ERROR:
+ nft_set_trans_unbind(ctx, set);
if (nft_set_is_anonymous(set))
nft_deactivate_next(ctx->net, set);
+ set->use--;
+ break;
+ case NFT_TRANS_PREPARE:
+ if (nft_set_is_anonymous(set)) {
+ if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_deactivate(ctx, set);
+
+ nft_deactivate_next(ctx->net, set);
+ }
set->use--;
return;
case NFT_TRANS_ABORT:
case NFT_TRANS_RELEASE:
+ if (nft_set_is_anonymous(set) &&
+ set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_deactivate(ctx, set);
+
set->use--;
fallthrough;
default:
@@ -5710,6 +5909,7 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
__nft_set_elem_expr_destroy(ctx, expr);
}
+/* Drop references and destroy. Called from gc, dynset and abort path. */
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
bool destroy_expr)
{
@@ -5731,11 +5931,11 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
}
EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
-/* Only called from commit path, nft_setelem_data_deactivate() already deals
- * with the refcounting from the preparation phase.
+/* Destroy element. References have been already dropped in the preparation
+ * path via nft_setelem_data_deactivate().
*/
-static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
- const struct nft_set *set, void *elem)
+void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set, void *elem)
{
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
@@ -6368,7 +6568,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
if (obj)
obj->use--;
err_elem_userdata:
- nf_tables_set_elem_destroy(ctx, set, elem.priv);
+ nft_set_elem_destroy(set, elem.priv, true);
err_parse_data:
if (nla[NFTA_SET_ELEM_DATA] != NULL)
nft_data_release(&elem.data.val, desc.type);
@@ -6413,7 +6613,8 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
if (IS_ERR(set))
return PTR_ERR(set);
- if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
+ if (!list_empty(&set->bindings) &&
+ (set->flags & (NFT_SET_CONSTANT | NFT_SET_ANONYMOUS)))
return -EBUSY;
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
@@ -6446,7 +6647,6 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
{
struct nft_chain *chain;
- struct nft_rule *rule;
if (type == NFT_DATA_VERDICT) {
switch (data->verdict.code) {
@@ -6454,15 +6654,6 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
case NFT_GOTO:
chain = data->verdict.chain;
chain->use++;
-
- if (!nft_chain_is_bound(chain))
- break;
-
- chain->table->use++;
- list_for_each_entry(rule, &chain->rules, list)
- chain->use++;
-
- nft_chain_add(chain->table, chain);
break;
}
}
@@ -6697,7 +6888,9 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
set = nft_set_lookup(table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
if (IS_ERR(set))
return PTR_ERR(set);
- if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
+
+ if (!list_empty(&set->bindings) &&
+ (set->flags & (NFT_SET_CONSTANT | NFT_SET_ANONYMOUS)))
return -EBUSY;
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
@@ -7464,6 +7657,7 @@ void nf_tables_deactivate_flowtable(const struct nft_ctx *ctx,
enum nft_trans_phase phase)
{
switch (phase) {
+ case NFT_TRANS_PREPARE_ERROR:
case NFT_TRANS_PREPARE:
case NFT_TRANS_ABORT:
case NFT_TRANS_RELEASE:
@@ -8658,7 +8852,7 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
synchronize_rcu();
list_for_each_entry_safe(trans, next, &head, list) {
- list_del(&trans->list);
+ nft_trans_list_del(trans);
nft_commit_release(trans);
}
}
@@ -9025,6 +9219,27 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
return 0;
}
+ list_for_each_entry(trans, &nft_net->binding_list, binding_list) {
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWSET:
+ if (!nft_trans_set_update(trans) &&
+ nft_set_is_anonymous(nft_trans_set(trans)) &&
+ !nft_trans_set_bound(trans)) {
+ pr_warn_once("nftables ruleset with unbound set\n");
+ return -EINVAL;
+ }
+ break;
+ case NFT_MSG_NEWCHAIN:
+ if (!nft_trans_chain_update(trans) &&
+ nft_chain_binding(nft_trans_chain(trans)) &&
+ !nft_trans_chain_bound(trans)) {
+ pr_warn_once("nftables ruleset with unbound chain\n");
+ return -EINVAL;
+ }
+ break;
+ }
+ }
+
/* 0. Validate ruleset, otherwise roll back for error reporting. */
if (nf_tables_validate(net) < 0)
return -EAGAIN;
@@ -9368,7 +9583,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
kfree(nft_trans_chain_name(trans));
nft_trans_destroy(trans);
} else {
- if (nft_chain_is_bound(trans->ctx.chain)) {
+ if (nft_trans_chain_bound(trans)) {
nft_trans_destroy(trans);
break;
}
@@ -9385,6 +9600,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
nft_trans_destroy(trans);
break;
case NFT_MSG_NEWRULE:
+ if (nft_trans_rule_bound(trans)) {
+ nft_trans_destroy(trans);
+ break;
+ }
trans->ctx.chain->use--;
list_del_rcu(&nft_trans_rule(trans)->list);
nft_rule_expr_deactivate(&trans->ctx,
@@ -9417,6 +9636,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
case NFT_MSG_DELSET:
trans->ctx.table->use++;
nft_clear(trans->ctx.net, nft_trans_set(trans));
+ if (nft_trans_set(trans)->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_activate(&trans->ctx, nft_trans_set(trans));
+
nft_trans_destroy(trans);
break;
case NFT_MSG_NEWSETELEM:
@@ -9494,7 +9716,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
list_for_each_entry_safe_reverse(trans, next,
&nft_net->commit_list, list) {
- list_del(&trans->list);
+ nft_trans_list_del(trans);
nf_tables_abort_release(trans);
}
@@ -9943,22 +10165,12 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
static void nft_verdict_uninit(const struct nft_data *data)
{
struct nft_chain *chain;
- struct nft_rule *rule;
switch (data->verdict.code) {
case NFT_JUMP:
case NFT_GOTO:
chain = data->verdict.chain;
chain->use--;
-
- if (!nft_chain_is_bound(chain))
- break;
-
- chain->table->use--;
- list_for_each_entry(rule, &chain->rules, list)
- chain->use--;
-
- nft_chain_del(chain);
break;
}
}
@@ -10193,6 +10405,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
list_for_each_entry_safe(set, ns, &table->sets, list) {
list_del(&set->list);
table->use--;
+ if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
+ nft_map_deactivate(&ctx, set);
+
nft_set_destroy(&ctx, set);
}
list_for_each_entry_safe(obj, ne, &table->objects, list) {
@@ -10277,6 +10492,7 @@ static int __net_init nf_tables_init_net(struct net *net)
INIT_LIST_HEAD(&nft_net->tables);
INIT_LIST_HEAD(&nft_net->commit_list);
+ INIT_LIST_HEAD(&nft_net->binding_list);
INIT_LIST_HEAD(&nft_net->module_list);
INIT_LIST_HEAD(&nft_net->notify_list);
mutex_init(&nft_net->commit_mutex);
diff --git a/net/netfilter/nfnetlink_osf.c b/net/netfilter/nfnetlink_osf.c
index ee6840bd5933..8f1bfa6ccc2d 100644
--- a/net/netfilter/nfnetlink_osf.c
+++ b/net/netfilter/nfnetlink_osf.c
@@ -439,3 +439,4 @@ module_init(nfnl_osf_init);
module_exit(nfnl_osf_fini);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF);
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
index 5f28b21abc7d..900e75e8c346 100644
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -76,11 +76,9 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
switch (priv->data.verdict.code) {
case NFT_JUMP:
case NFT_GOTO:
- if (nft_chain_is_bound(chain)) {
- err = -EBUSY;
- goto err1;
- }
- chain->bound = true;
+ err = nf_tables_bind_chain(ctx, chain);
+ if (err < 0)
+ return err;
break;
default:
break;
@@ -98,6 +96,31 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+ const struct nft_data *data = &priv->data;
+ struct nft_ctx chain_ctx;
+ struct nft_chain *chain;
+ struct nft_rule *rule;
+
+ if (priv->dreg == NFT_REG_VERDICT) {
+ switch (data->verdict.code) {
+ case NFT_JUMP:
+ case NFT_GOTO:
+ chain = data->verdict.chain;
+ if (!nft_chain_binding(chain))
+ break;
+
+ chain_ctx = *ctx;
+ chain_ctx.chain = chain;
+
+ list_for_each_entry(rule, &chain->rules, list)
+ nft_rule_expr_activate(&chain_ctx, rule);
+
+ nft_clear(ctx->net, chain);
+ break;
+ default:
+ break;
+ }
+ }
return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
}
@@ -107,6 +130,43 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
enum nft_trans_phase phase)
{
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+ const struct nft_data *data = &priv->data;
+ struct nft_ctx chain_ctx;
+ struct nft_chain *chain;
+ struct nft_rule *rule;
+
+ if (priv->dreg == NFT_REG_VERDICT) {
+ switch (data->verdict.code) {
+ case NFT_JUMP:
+ case NFT_GOTO:
+ chain = data->verdict.chain;
+ if (!nft_chain_binding(chain))
+ break;
+
+ chain_ctx = *ctx;
+ chain_ctx.chain = chain;
+
+ list_for_each_entry(rule, &chain->rules, list)
+ nft_rule_expr_deactivate(&chain_ctx, rule, phase);
+
+ switch (phase) {
+ case NFT_TRANS_PREPARE_ERROR:
+ nf_tables_unbind_chain(ctx, chain);
+ fallthrough;
+ case NFT_TRANS_PREPARE:
+ nft_deactivate_next(ctx->net, chain);
+ break;
+ default:
+ nft_chain_del(chain);
+ chain->bound = false;
+ chain->table->use--;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
if (phase == NFT_TRANS_COMMIT)
return;
@@ -131,15 +191,27 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
case NFT_GOTO:
chain = data->verdict.chain;
- if (!nft_chain_is_bound(chain))
+ if (!nft_chain_binding(chain))
+ break;
+
+ /* Rule construction failed, but chain is already bound:
+ * let the transaction records release this chain and its rules.
+ */
+ if (chain->bound) {
+ chain->use--;
break;
+ }
+ /* Rule has been deleted, release chain and its rules. */
chain_ctx = *ctx;
chain_ctx.chain = chain;
- list_for_each_entry_safe(rule, n, &chain->rules, list)
- nf_tables_rule_release(&chain_ctx, rule);
-
+ chain->use--;
+ list_for_each_entry_safe(rule, n, &chain->rules, list) {
+ chain->use--;
+ list_del(&rule->list);
+ nf_tables_rule_destroy(&chain_ctx, rule);
+ }
nf_tables_chain_destroy(&chain_ctx);
break;
default:
diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c
index 96081ac8d2b4..1e5e7a181e0b 100644
--- a/net/netfilter/nft_set_bitmap.c
+++ b/net/netfilter/nft_set_bitmap.c
@@ -271,13 +271,14 @@ static int nft_bitmap_init(const struct nft_set *set,
return 0;
}
-static void nft_bitmap_destroy(const struct nft_set *set)
+static void nft_bitmap_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_bitmap *priv = nft_set_priv(set);
struct nft_bitmap_elem *be, *n;
list_for_each_entry_safe(be, n, &priv->list, head)
- nft_set_elem_destroy(set, be, true);
+ nf_tables_set_elem_destroy(ctx, set, be);
}
static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features,
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
index 76de6c8d9865..0b73cb0e752f 100644
--- a/net/netfilter/nft_set_hash.c
+++ b/net/netfilter/nft_set_hash.c
@@ -400,19 +400,31 @@ static int nft_rhash_init(const struct nft_set *set,
return 0;
}
+struct nft_rhash_ctx {
+ const struct nft_ctx ctx;
+ const struct nft_set *set;
+};
+
static void nft_rhash_elem_destroy(void *ptr, void *arg)
{
- nft_set_elem_destroy(arg, ptr, true);
+ struct nft_rhash_ctx *rhash_ctx = arg;
+
+ nf_tables_set_elem_destroy(&rhash_ctx->ctx, rhash_ctx->set, ptr);
}
-static void nft_rhash_destroy(const struct nft_set *set)
+static void nft_rhash_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_rhash *priv = nft_set_priv(set);
+ struct nft_rhash_ctx rhash_ctx = {
+ .ctx = *ctx,
+ .set = set,
+ };
cancel_delayed_work_sync(&priv->gc_work);
rcu_barrier();
rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
- (void *)set);
+ (void *)&rhash_ctx);
}
/* Number of buckets is stored in u32, so cap our result to 1U<<31 */
@@ -643,7 +655,8 @@ static int nft_hash_init(const struct nft_set *set,
return 0;
}
-static void nft_hash_destroy(const struct nft_set *set)
+static void nft_hash_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_hash *priv = nft_set_priv(set);
struct nft_hash_elem *he;
@@ -653,7 +666,7 @@ static void nft_hash_destroy(const struct nft_set *set)
for (i = 0; i < priv->buckets; i++) {
hlist_for_each_entry_safe(he, next, &priv->table[i], node) {
hlist_del_rcu(&he->node);
- nft_set_elem_destroy(set, he, true);
+ nf_tables_set_elem_destroy(ctx, set, he);
}
}
}
diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
index 15e451dc3fc4..0452ee586c1c 100644
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -1974,12 +1974,16 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_iter *iter)
{
struct nft_pipapo *priv = nft_set_priv(set);
+ struct net *net = read_pnet(&set->net);
struct nft_pipapo_match *m;
struct nft_pipapo_field *f;
int i, r;
rcu_read_lock();
- m = rcu_dereference(priv->match);
+ if (iter->genmask == nft_genmask_cur(net))
+ m = rcu_dereference(priv->match);
+ else
+ m = priv->clone;
if (unlikely(!m))
goto out;
@@ -2148,10 +2152,12 @@ static int nft_pipapo_init(const struct nft_set *set,
/**
* nft_set_pipapo_match_destroy() - Destroy elements from key mapping array
+ * @ctx: context
* @set: nftables API set representation
* @m: matching data pointing to key mapping array
*/
-static void nft_set_pipapo_match_destroy(const struct nft_set *set,
+static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set,
struct nft_pipapo_match *m)
{
struct nft_pipapo_field *f;
@@ -2168,15 +2174,17 @@ static void nft_set_pipapo_match_destroy(const struct nft_set *set,
e = f->mt[r].e;
- nft_set_elem_destroy(set, e, true);
+ nf_tables_set_elem_destroy(ctx, set, e);
}
}
/**
* nft_pipapo_destroy() - Free private data for set and all committed elements
+ * @ctx: context
* @set: nftables API set representation
*/
-static void nft_pipapo_destroy(const struct nft_set *set)
+static void nft_pipapo_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_pipapo *priv = nft_set_priv(set);
struct nft_pipapo_match *m;
@@ -2186,7 +2194,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
if (m) {
rcu_barrier();
- nft_set_pipapo_match_destroy(set, m);
+ nft_set_pipapo_match_destroy(ctx, set, m);
#ifdef NFT_PIPAPO_ALIGN
free_percpu(m->scratch_aligned);
@@ -2203,7 +2211,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
m = priv->clone;
if (priv->dirty)
- nft_set_pipapo_match_destroy(set, m);
+ nft_set_pipapo_match_destroy(ctx, set, m);
#ifdef NFT_PIPAPO_ALIGN
free_percpu(priv->clone->scratch_aligned);
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
index 2f114aa10f1a..5c05c9b990fb 100644
--- a/net/netfilter/nft_set_rbtree.c
+++ b/net/netfilter/nft_set_rbtree.c
@@ -664,7 +664,8 @@ static int nft_rbtree_init(const struct nft_set *set,
return 0;
}
-static void nft_rbtree_destroy(const struct nft_set *set)
+static void nft_rbtree_destroy(const struct nft_ctx *ctx,
+ const struct nft_set *set)
{
struct nft_rbtree *priv = nft_set_priv(set);
struct nft_rbtree_elem *rbe;
@@ -675,7 +676,7 @@ static void nft_rbtree_destroy(const struct nft_set *set)
while ((node = priv->root.rb_node) != NULL) {
rb_erase(node, &priv->root);
rbe = rb_entry(node, struct nft_rbtree_elem, node);
- nft_set_elem_destroy(set, rbe, true);
+ nf_tables_set_elem_destroy(ctx, set, rbe);
}
}
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index e1990baf3a3b..dc9485854002 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -71,4 +71,3 @@ MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
MODULE_DESCRIPTION("Passive OS fingerprint matching.");
MODULE_ALIAS("ipt_osf");
MODULE_ALIAS("ip6t_osf");
-MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index fb00ac40ecb7..aa9842158df0 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -966,6 +966,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
if (ret < 0)
return ret;
+ sch_tree_lock(sch);
/* backup q->clg and q->loss_model */
old_clg = q->clg;
old_loss_model = q->loss_model;
@@ -974,7 +975,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]);
if (ret) {
q->loss_model = old_loss_model;
- return ret;
+ goto unlock;
}
} else {
q->loss_model = CLG_RANDOM;
@@ -1041,6 +1042,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
/* capping jitter to the range acceptable by tabledist() */
q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
+unlock:
+ sch_tree_unlock(sch);
return ret;
get_table_failure:
@@ -1050,7 +1053,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
*/
q->clg = old_clg;
q->loss_model = old_loss_model;
- return ret;
+
+ goto unlock;
}
static int netem_init(struct Qdisc *sch, struct nlattr *opt,
diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile
index 494aa744bfb9..08a2870fdd36 100644
--- a/net/xfrm/Makefile
+++ b/net/xfrm/Makefile
@@ -3,6 +3,8 @@
# Makefile for the XFRM subsystem.
#
+xfrm_interface-$(CONFIG_XFRM_INTERFACE) += xfrm_interface_core.o
+
obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
xfrm_input.o xfrm_output.o \
xfrm_sysctl.o xfrm_replay.o xfrm_device.o
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 2defd89da700..ac1a645afa8d 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -131,6 +131,7 @@ struct sec_path *secpath_set(struct sk_buff *skb)
memset(sp->ovec, 0, sizeof(sp->ovec));
sp->olen = 0;
sp->len = 0;
+ sp->verified_cnt = 0;
return sp;
}
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
deleted file mode 100644
index 5a67b120c4db..000000000000
--- a/net/xfrm/xfrm_interface.c
+++ /dev/null
@@ -1,1198 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * XFRM virtual interface
- *
- * Copyright (C) 2018 secunet Security Networks AG
- *
- * Author:
- * Steffen Klassert <steffen.klassert@secunet.com>
- */
-
-#include <linux/module.h>
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/sockios.h>
-#include <linux/icmp.h>
-#include <linux/if.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/net.h>
-#include <linux/in6.h>
-#include <linux/netdevice.h>
-#include <linux/if_link.h>
-#include <linux/if_arp.h>
-#include <linux/icmpv6.h>
-#include <linux/init.h>
-#include <linux/route.h>
-#include <linux/rtnetlink.h>
-#include <linux/netfilter_ipv6.h>
-#include <linux/slab.h>
-#include <linux/hash.h>
-
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-
-#include <net/icmp.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/ip6_route.h>
-#include <net/ip_tunnels.h>
-#include <net/addrconf.h>
-#include <net/xfrm.h>
-#include <net/net_namespace.h>
-#include <net/dst_metadata.h>
-#include <net/netns/generic.h>
-#include <linux/etherdevice.h>
-
-static int xfrmi_dev_init(struct net_device *dev);
-static void xfrmi_dev_setup(struct net_device *dev);
-static struct rtnl_link_ops xfrmi_link_ops __read_mostly;
-static unsigned int xfrmi_net_id __read_mostly;
-static const struct net_device_ops xfrmi_netdev_ops;
-
-#define XFRMI_HASH_BITS 8
-#define XFRMI_HASH_SIZE BIT(XFRMI_HASH_BITS)
-
-struct xfrmi_net {
- /* lists for storing interfaces in use */
- struct xfrm_if __rcu *xfrmi[XFRMI_HASH_SIZE];
- struct xfrm_if __rcu *collect_md_xfrmi;
-};
-
-static const struct nla_policy xfrm_lwt_policy[LWT_XFRM_MAX + 1] = {
- [LWT_XFRM_IF_ID] = NLA_POLICY_MIN(NLA_U32, 1),
- [LWT_XFRM_LINK] = NLA_POLICY_MIN(NLA_U32, 1),
-};
-
-static void xfrmi_destroy_state(struct lwtunnel_state *lwt)
-{
-}
-
-static int xfrmi_build_state(struct net *net, struct nlattr *nla,
- unsigned int family, const void *cfg,
- struct lwtunnel_state **ts,
- struct netlink_ext_ack *extack)
-{
- struct nlattr *tb[LWT_XFRM_MAX + 1];
- struct lwtunnel_state *new_state;
- struct xfrm_md_info *info;
- int ret;
-
- ret = nla_parse_nested(tb, LWT_XFRM_MAX, nla, xfrm_lwt_policy, extack);
- if (ret < 0)
- return ret;
-
- if (!tb[LWT_XFRM_IF_ID]) {
- NL_SET_ERR_MSG(extack, "if_id must be set");
- return -EINVAL;
- }
-
- new_state = lwtunnel_state_alloc(sizeof(*info));
- if (!new_state) {
- NL_SET_ERR_MSG(extack, "failed to create encap info");
- return -ENOMEM;
- }
-
- new_state->type = LWTUNNEL_ENCAP_XFRM;
-
- info = lwt_xfrm_info(new_state);
-
- info->if_id = nla_get_u32(tb[LWT_XFRM_IF_ID]);
-
- if (tb[LWT_XFRM_LINK])
- info->link = nla_get_u32(tb[LWT_XFRM_LINK]);
-
- *ts = new_state;
- return 0;
-}
-
-static int xfrmi_fill_encap_info(struct sk_buff *skb,
- struct lwtunnel_state *lwt)
-{
- struct xfrm_md_info *info = lwt_xfrm_info(lwt);
-
- if (nla_put_u32(skb, LWT_XFRM_IF_ID, info->if_id) ||
- (info->link && nla_put_u32(skb, LWT_XFRM_LINK, info->link)))
- return -EMSGSIZE;
-
- return 0;
-}
-
-static int xfrmi_encap_nlsize(struct lwtunnel_state *lwtstate)
-{
- return nla_total_size(sizeof(u32)) + /* LWT_XFRM_IF_ID */
- nla_total_size(sizeof(u32)); /* LWT_XFRM_LINK */
-}
-
-static int xfrmi_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
-{
- struct xfrm_md_info *a_info = lwt_xfrm_info(a);
- struct xfrm_md_info *b_info = lwt_xfrm_info(b);
-
- return memcmp(a_info, b_info, sizeof(*a_info));
-}
-
-static const struct lwtunnel_encap_ops xfrmi_encap_ops = {
- .build_state = xfrmi_build_state,
- .destroy_state = xfrmi_destroy_state,
- .fill_encap = xfrmi_fill_encap_info,
- .get_encap_size = xfrmi_encap_nlsize,
- .cmp_encap = xfrmi_encap_cmp,
- .owner = THIS_MODULE,
-};
-
-#define for_each_xfrmi_rcu(start, xi) \
- for (xi = rcu_dereference(start); xi; xi = rcu_dereference(xi->next))
-
-static u32 xfrmi_hash(u32 if_id)
-{
- return hash_32(if_id, XFRMI_HASH_BITS);
-}
-
-static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x)
-{
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
- struct xfrm_if *xi;
-
- for_each_xfrmi_rcu(xfrmn->xfrmi[xfrmi_hash(x->if_id)], xi) {
- if (x->if_id == xi->p.if_id &&
- (xi->dev->flags & IFF_UP))
- return xi;
- }
-
- xi = rcu_dereference(xfrmn->collect_md_xfrmi);
- if (xi && (xi->dev->flags & IFF_UP))
- return xi;
-
- return NULL;
-}
-
-static bool xfrmi_decode_session(struct sk_buff *skb,
- unsigned short family,
- struct xfrm_if_decode_session_result *res)
-{
- struct net_device *dev;
- struct xfrm_if *xi;
- int ifindex = 0;
-
- if (!secpath_exists(skb) || !skb->dev)
- return false;
-
- switch (family) {
- case AF_INET6:
- ifindex = inet6_sdif(skb);
- break;
- case AF_INET:
- ifindex = inet_sdif(skb);
- break;
- }
-
- if (ifindex) {
- struct net *net = xs_net(xfrm_input_state(skb));
-
- dev = dev_get_by_index_rcu(net, ifindex);
- } else {
- dev = skb->dev;
- }
-
- if (!dev || !(dev->flags & IFF_UP))
- return false;
- if (dev->netdev_ops != &xfrmi_netdev_ops)
- return false;
-
- xi = netdev_priv(dev);
- res->net = xi->net;
-
- if (xi->p.collect_md)
- res->if_id = xfrm_input_state(skb)->if_id;
- else
- res->if_id = xi->p.if_id;
- return true;
-}
-
-static void xfrmi_link(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
-{
- struct xfrm_if __rcu **xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
-
- rcu_assign_pointer(xi->next , rtnl_dereference(*xip));
- rcu_assign_pointer(*xip, xi);
-}
-
-static void xfrmi_unlink(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
-{
- struct xfrm_if __rcu **xip;
- struct xfrm_if *iter;
-
- for (xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
- (iter = rtnl_dereference(*xip)) != NULL;
- xip = &iter->next) {
- if (xi == iter) {
- rcu_assign_pointer(*xip, xi->next);
- break;
- }
- }
-}
-
-static void xfrmi_dev_free(struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
-
- gro_cells_destroy(&xi->gro_cells);
- free_percpu(dev->tstats);
-}
-
-static int xfrmi_create(struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net *net = dev_net(dev);
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
- int err;
-
- dev->rtnl_link_ops = &xfrmi_link_ops;
- err = register_netdevice(dev);
- if (err < 0)
- goto out;
-
- if (xi->p.collect_md)
- rcu_assign_pointer(xfrmn->collect_md_xfrmi, xi);
- else
- xfrmi_link(xfrmn, xi);
-
- return 0;
-
-out:
- return err;
-}
-
-static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p)
-{
- struct xfrm_if __rcu **xip;
- struct xfrm_if *xi;
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
-
- for (xip = &xfrmn->xfrmi[xfrmi_hash(p->if_id)];
- (xi = rtnl_dereference(*xip)) != NULL;
- xip = &xi->next)
- if (xi->p.if_id == p->if_id)
- return xi;
-
- return NULL;
-}
-
-static void xfrmi_dev_uninit(struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
-
- if (xi->p.collect_md)
- RCU_INIT_POINTER(xfrmn->collect_md_xfrmi, NULL);
- else
- xfrmi_unlink(xfrmn, xi);
-}
-
-static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
-{
- skb_clear_tstamp(skb);
- skb->pkt_type = PACKET_HOST;
- skb->skb_iif = 0;
- skb->ignore_df = 0;
- skb_dst_drop(skb);
- nf_reset_ct(skb);
- nf_reset_trace(skb);
-
- if (!xnet)
- return;
-
- ipvs_reset(skb);
- secpath_reset(skb);
- skb_orphan(skb);
- skb->mark = 0;
-}
-
-static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
-{
- const struct xfrm_mode *inner_mode;
- struct net_device *dev;
- struct xfrm_state *x;
- struct xfrm_if *xi;
- bool xnet;
- int link;
-
- if (err && !secpath_exists(skb))
- return 0;
-
- x = xfrm_input_state(skb);
-
- xi = xfrmi_lookup(xs_net(x), x);
- if (!xi)
- return 1;
-
- link = skb->dev->ifindex;
- dev = xi->dev;
- skb->dev = dev;
-
- if (err) {
- dev->stats.rx_errors++;
- dev->stats.rx_dropped++;
-
- return 0;
- }
-
- xnet = !net_eq(xi->net, dev_net(skb->dev));
-
- if (xnet) {
- inner_mode = &x->inner_mode;
-
- if (x->sel.family == AF_UNSPEC) {
- inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
- if (inner_mode == NULL) {
- XFRM_INC_STATS(dev_net(skb->dev),
- LINUX_MIB_XFRMINSTATEMODEERROR);
- return -EINVAL;
- }
- }
-
- if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb,
- inner_mode->family))
- return -EPERM;
- }
-
- xfrmi_scrub_packet(skb, xnet);
- if (xi->p.collect_md) {
- struct metadata_dst *md_dst;
-
- md_dst = metadata_dst_alloc(0, METADATA_XFRM, GFP_ATOMIC);
- if (!md_dst)
- return -ENOMEM;
-
- md_dst->u.xfrm_info.if_id = x->if_id;
- md_dst->u.xfrm_info.link = link;
- skb_dst_set(skb, (struct dst_entry *)md_dst);
- }
- dev_sw_netstats_rx_add(dev, skb->len);
-
- return 0;
-}
-
-static int
-xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net_device_stats *stats = &xi->dev->stats;
- struct dst_entry *dst = skb_dst(skb);
- unsigned int length = skb->len;
- struct net_device *tdev;
- struct xfrm_state *x;
- int err = -1;
- u32 if_id;
- int mtu;
-
- if (xi->p.collect_md) {
- struct xfrm_md_info *md_info = skb_xfrm_md_info(skb);
-
- if (unlikely(!md_info))
- return -EINVAL;
-
- if_id = md_info->if_id;
- fl->flowi_oif = md_info->link;
- } else {
- if_id = xi->p.if_id;
- }
-
- dst_hold(dst);
- dst = xfrm_lookup_with_ifid(xi->net, dst, fl, NULL, 0, if_id);
- if (IS_ERR(dst)) {
- err = PTR_ERR(dst);
- dst = NULL;
- goto tx_err_link_failure;
- }
-
- x = dst->xfrm;
- if (!x)
- goto tx_err_link_failure;
-
- if (x->if_id != if_id)
- goto tx_err_link_failure;
-
- tdev = dst->dev;
-
- if (tdev == dev) {
- stats->collisions++;
- net_warn_ratelimited("%s: Local routing loop detected!\n",
- dev->name);
- goto tx_err_dst_release;
- }
-
- mtu = dst_mtu(dst);
- if ((!skb_is_gso(skb) && skb->len > mtu) ||
- (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu))) {
- skb_dst_update_pmtu_no_confirm(skb, mtu);
-
- if (skb->protocol == htons(ETH_P_IPV6)) {
- if (mtu < IPV6_MIN_MTU)
- mtu = IPV6_MIN_MTU;
-
- if (skb->len > 1280)
- icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
- else
- goto xmit;
- } else {
- if (!(ip_hdr(skb)->frag_off & htons(IP_DF)))
- goto xmit;
- icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
- htonl(mtu));
- }
-
- dst_release(dst);
- return -EMSGSIZE;
- }
-
-xmit:
- xfrmi_scrub_packet(skb, !net_eq(xi->net, dev_net(dev)));
- skb_dst_set(skb, dst);
- skb->dev = tdev;
-
- err = dst_output(xi->net, skb->sk, skb);
- if (net_xmit_eval(err) == 0) {
- dev_sw_netstats_tx_add(dev, 1, length);
- } else {
- stats->tx_errors++;
- stats->tx_aborted_errors++;
- }
-
- return 0;
-tx_err_link_failure:
- stats->tx_carrier_errors++;
- dst_link_failure(skb);
-tx_err_dst_release:
- dst_release(dst);
- return err;
-}
-
-static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net_device_stats *stats = &xi->dev->stats;
- struct dst_entry *dst = skb_dst(skb);
- struct flowi fl;
- int ret;
-
- memset(&fl, 0, sizeof(fl));
-
- switch (skb->protocol) {
- case htons(ETH_P_IPV6):
- xfrm_decode_session(skb, &fl, AF_INET6);
- memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
- if (!dst) {
- fl.u.ip6.flowi6_oif = dev->ifindex;
- fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
- dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6);
- if (dst->error) {
- dst_release(dst);
- stats->tx_carrier_errors++;
- goto tx_err;
- }
- skb_dst_set(skb, dst);
- }
- break;
- case htons(ETH_P_IP):
- xfrm_decode_session(skb, &fl, AF_INET);
- memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
- if (!dst) {
- struct rtable *rt;
-
- fl.u.ip4.flowi4_oif = dev->ifindex;
- fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
- rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4);
- if (IS_ERR(rt)) {
- stats->tx_carrier_errors++;
- goto tx_err;
- }
- skb_dst_set(skb, &rt->dst);
- }
- break;
- default:
- goto tx_err;
- }
-
- fl.flowi_oif = xi->p.link;
-
- ret = xfrmi_xmit2(skb, dev, &fl);
- if (ret < 0)
- goto tx_err;
-
- return NETDEV_TX_OK;
-
-tx_err:
- stats->tx_errors++;
- stats->tx_dropped++;
- kfree_skb(skb);
- return NETDEV_TX_OK;
-}
-
-static int xfrmi4_err(struct sk_buff *skb, u32 info)
-{
- const struct iphdr *iph = (const struct iphdr *)skb->data;
- struct net *net = dev_net(skb->dev);
- int protocol = iph->protocol;
- struct ip_comp_hdr *ipch;
- struct ip_esp_hdr *esph;
- struct ip_auth_hdr *ah ;
- struct xfrm_state *x;
- struct xfrm_if *xi;
- __be32 spi;
-
- switch (protocol) {
- case IPPROTO_ESP:
- esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
- spi = esph->spi;
- break;
- case IPPROTO_AH:
- ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
- spi = ah->spi;
- break;
- case IPPROTO_COMP:
- ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
- spi = htonl(ntohs(ipch->cpi));
- break;
- default:
- return 0;
- }
-
- switch (icmp_hdr(skb)->type) {
- case ICMP_DEST_UNREACH:
- if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
- return 0;
- break;
- case ICMP_REDIRECT:
- break;
- default:
- return 0;
- }
-
- x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
- spi, protocol, AF_INET);
- if (!x)
- return 0;
-
- xi = xfrmi_lookup(net, x);
- if (!xi) {
- xfrm_state_put(x);
- return -1;
- }
-
- if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
- ipv4_update_pmtu(skb, net, info, 0, protocol);
- else
- ipv4_redirect(skb, net, 0, protocol);
- xfrm_state_put(x);
-
- return 0;
-}
-
-static int xfrmi6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- u8 type, u8 code, int offset, __be32 info)
-{
- const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
- struct net *net = dev_net(skb->dev);
- int protocol = iph->nexthdr;
- struct ip_comp_hdr *ipch;
- struct ip_esp_hdr *esph;
- struct ip_auth_hdr *ah;
- struct xfrm_state *x;
- struct xfrm_if *xi;
- __be32 spi;
-
- switch (protocol) {
- case IPPROTO_ESP:
- esph = (struct ip_esp_hdr *)(skb->data + offset);
- spi = esph->spi;
- break;
- case IPPROTO_AH:
- ah = (struct ip_auth_hdr *)(skb->data + offset);
- spi = ah->spi;
- break;
- case IPPROTO_COMP:
- ipch = (struct ip_comp_hdr *)(skb->data + offset);
- spi = htonl(ntohs(ipch->cpi));
- break;
- default:
- return 0;
- }
-
- if (type != ICMPV6_PKT_TOOBIG &&
- type != NDISC_REDIRECT)
- return 0;
-
- x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
- spi, protocol, AF_INET6);
- if (!x)
- return 0;
-
- xi = xfrmi_lookup(net, x);
- if (!xi) {
- xfrm_state_put(x);
- return -1;
- }
-
- if (type == NDISC_REDIRECT)
- ip6_redirect(skb, net, skb->dev->ifindex, 0,
- sock_net_uid(net, NULL));
- else
- ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
- xfrm_state_put(x);
-
- return 0;
-}
-
-static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p)
-{
- if (xi->p.link != p->link)
- return -EINVAL;
-
- xi->p.if_id = p->if_id;
-
- return 0;
-}
-
-static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
-{
- struct net *net = xi->net;
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
- int err;
-
- xfrmi_unlink(xfrmn, xi);
- synchronize_net();
- err = xfrmi_change(xi, p);
- xfrmi_link(xfrmn, xi);
- netdev_state_change(xi->dev);
- return err;
-}
-
-static int xfrmi_get_iflink(const struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
-
- return xi->p.link;
-}
-
-static const struct net_device_ops xfrmi_netdev_ops = {
- .ndo_init = xfrmi_dev_init,
- .ndo_uninit = xfrmi_dev_uninit,
- .ndo_start_xmit = xfrmi_xmit,
- .ndo_get_stats64 = dev_get_tstats64,
- .ndo_get_iflink = xfrmi_get_iflink,
-};
-
-static void xfrmi_dev_setup(struct net_device *dev)
-{
- dev->netdev_ops = &xfrmi_netdev_ops;
- dev->header_ops = &ip_tunnel_header_ops;
- dev->type = ARPHRD_NONE;
- dev->mtu = ETH_DATA_LEN;
- dev->min_mtu = ETH_MIN_MTU;
- dev->max_mtu = IP_MAX_MTU;
- dev->flags = IFF_NOARP;
- dev->needs_free_netdev = true;
- dev->priv_destructor = xfrmi_dev_free;
- netif_keep_dst(dev);
-
- eth_broadcast_addr(dev->broadcast);
-}
-
-#define XFRMI_FEATURES (NETIF_F_SG | \
- NETIF_F_FRAGLIST | \
- NETIF_F_GSO_SOFTWARE | \
- NETIF_F_HW_CSUM)
-
-static int xfrmi_dev_init(struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
- int err;
-
- dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
- if (!dev->tstats)
- return -ENOMEM;
-
- err = gro_cells_init(&xi->gro_cells, dev);
- if (err) {
- free_percpu(dev->tstats);
- return err;
- }
-
- dev->features |= NETIF_F_LLTX;
- dev->features |= XFRMI_FEATURES;
- dev->hw_features |= XFRMI_FEATURES;
-
- if (phydev) {
- dev->needed_headroom = phydev->needed_headroom;
- dev->needed_tailroom = phydev->needed_tailroom;
-
- if (is_zero_ether_addr(dev->dev_addr))
- eth_hw_addr_inherit(dev, phydev);
- if (is_zero_ether_addr(dev->broadcast))
- memcpy(dev->broadcast, phydev->broadcast,
- dev->addr_len);
- } else {
- eth_hw_addr_random(dev);
- eth_broadcast_addr(dev->broadcast);
- }
-
- return 0;
-}
-
-static int xfrmi_validate(struct nlattr *tb[], struct nlattr *data[],
- struct netlink_ext_ack *extack)
-{
- return 0;
-}
-
-static void xfrmi_netlink_parms(struct nlattr *data[],
- struct xfrm_if_parms *parms)
-{
- memset(parms, 0, sizeof(*parms));
-
- if (!data)
- return;
-
- if (data[IFLA_XFRM_LINK])
- parms->link = nla_get_u32(data[IFLA_XFRM_LINK]);
-
- if (data[IFLA_XFRM_IF_ID])
- parms->if_id = nla_get_u32(data[IFLA_XFRM_IF_ID]);
-
- if (data[IFLA_XFRM_COLLECT_METADATA])
- parms->collect_md = true;
-}
-
-static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
- struct nlattr *tb[], struct nlattr *data[],
- struct netlink_ext_ack *extack)
-{
- struct net *net = dev_net(dev);
- struct xfrm_if_parms p = {};
- struct xfrm_if *xi;
- int err;
-
- xfrmi_netlink_parms(data, &p);
- if (p.collect_md) {
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
-
- if (p.link || p.if_id) {
- NL_SET_ERR_MSG(extack, "link and if_id must be zero");
- return -EINVAL;
- }
-
- if (rtnl_dereference(xfrmn->collect_md_xfrmi))
- return -EEXIST;
-
- } else {
- if (!p.if_id) {
- NL_SET_ERR_MSG(extack, "if_id must be non zero");
- return -EINVAL;
- }
-
- xi = xfrmi_locate(net, &p);
- if (xi)
- return -EEXIST;
- }
-
- xi = netdev_priv(dev);
- xi->p = p;
- xi->net = net;
- xi->dev = dev;
-
- err = xfrmi_create(dev);
- return err;
-}
-
-static void xfrmi_dellink(struct net_device *dev, struct list_head *head)
-{
- unregister_netdevice_queue(dev, head);
-}
-
-static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
- struct nlattr *data[],
- struct netlink_ext_ack *extack)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct net *net = xi->net;
- struct xfrm_if_parms p = {};
-
- xfrmi_netlink_parms(data, &p);
- if (!p.if_id) {
- NL_SET_ERR_MSG(extack, "if_id must be non zero");
- return -EINVAL;
- }
-
- if (p.collect_md) {
- NL_SET_ERR_MSG(extack, "collect_md can't be changed");
- return -EINVAL;
- }
-
- xi = xfrmi_locate(net, &p);
- if (!xi) {
- xi = netdev_priv(dev);
- } else {
- if (xi->dev != dev)
- return -EEXIST;
- if (xi->p.collect_md) {
- NL_SET_ERR_MSG(extack,
- "device can't be changed to collect_md");
- return -EINVAL;
- }
- }
-
- return xfrmi_update(xi, &p);
-}
-
-static size_t xfrmi_get_size(const struct net_device *dev)
-{
- return
- /* IFLA_XFRM_LINK */
- nla_total_size(4) +
- /* IFLA_XFRM_IF_ID */
- nla_total_size(4) +
- /* IFLA_XFRM_COLLECT_METADATA */
- nla_total_size(0) +
- 0;
-}
-
-static int xfrmi_fill_info(struct sk_buff *skb, const struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
- struct xfrm_if_parms *parm = &xi->p;
-
- if (nla_put_u32(skb, IFLA_XFRM_LINK, parm->link) ||
- nla_put_u32(skb, IFLA_XFRM_IF_ID, parm->if_id) ||
- (xi->p.collect_md && nla_put_flag(skb, IFLA_XFRM_COLLECT_METADATA)))
- goto nla_put_failure;
- return 0;
-
-nla_put_failure:
- return -EMSGSIZE;
-}
-
-static struct net *xfrmi_get_link_net(const struct net_device *dev)
-{
- struct xfrm_if *xi = netdev_priv(dev);
-
- return xi->net;
-}
-
-static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
- [IFLA_XFRM_UNSPEC] = { .strict_start_type = IFLA_XFRM_COLLECT_METADATA },
- [IFLA_XFRM_LINK] = { .type = NLA_U32 },
- [IFLA_XFRM_IF_ID] = { .type = NLA_U32 },
- [IFLA_XFRM_COLLECT_METADATA] = { .type = NLA_FLAG },
-};
-
-static struct rtnl_link_ops xfrmi_link_ops __read_mostly = {
- .kind = "xfrm",
- .maxtype = IFLA_XFRM_MAX,
- .policy = xfrmi_policy,
- .priv_size = sizeof(struct xfrm_if),
- .setup = xfrmi_dev_setup,
- .validate = xfrmi_validate,
- .newlink = xfrmi_newlink,
- .dellink = xfrmi_dellink,
- .changelink = xfrmi_changelink,
- .get_size = xfrmi_get_size,
- .fill_info = xfrmi_fill_info,
- .get_link_net = xfrmi_get_link_net,
-};
-
-static void __net_exit xfrmi_exit_batch_net(struct list_head *net_exit_list)
-{
- struct net *net;
- LIST_HEAD(list);
-
- rtnl_lock();
- list_for_each_entry(net, net_exit_list, exit_list) {
- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
- struct xfrm_if __rcu **xip;
- struct xfrm_if *xi;
- int i;
-
- for (i = 0; i < XFRMI_HASH_SIZE; i++) {
- for (xip = &xfrmn->xfrmi[i];
- (xi = rtnl_dereference(*xip)) != NULL;
- xip = &xi->next)
- unregister_netdevice_queue(xi->dev, &list);
- }
- xi = rtnl_dereference(xfrmn->collect_md_xfrmi);
- if (xi)
- unregister_netdevice_queue(xi->dev, &list);
- }
- unregister_netdevice_many(&list);
- rtnl_unlock();
-}
-
-static struct pernet_operations xfrmi_net_ops = {
- .exit_batch = xfrmi_exit_batch_net,
- .id = &xfrmi_net_id,
- .size = sizeof(struct xfrmi_net),
-};
-
-static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
- .handler = xfrm6_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 10,
-};
-
-static struct xfrm6_protocol xfrmi_ah6_protocol __read_mostly = {
- .handler = xfrm6_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 10,
-};
-
-static struct xfrm6_protocol xfrmi_ipcomp6_protocol __read_mostly = {
- .handler = xfrm6_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 10,
-};
-
-#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
-static int xfrmi6_rcv_tunnel(struct sk_buff *skb)
-{
- const xfrm_address_t *saddr;
- __be32 spi;
-
- saddr = (const xfrm_address_t *)&ipv6_hdr(skb)->saddr;
- spi = xfrm6_tunnel_spi_lookup(dev_net(skb->dev), saddr);
-
- return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi, NULL);
-}
-
-static struct xfrm6_tunnel xfrmi_ipv6_handler __read_mostly = {
- .handler = xfrmi6_rcv_tunnel,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 2,
-};
-
-static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
- .handler = xfrmi6_rcv_tunnel,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi6_err,
- .priority = 2,
-};
-#endif
-
-static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
- .handler = xfrm4_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 10,
-};
-
-static struct xfrm4_protocol xfrmi_ah4_protocol __read_mostly = {
- .handler = xfrm4_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 10,
-};
-
-static struct xfrm4_protocol xfrmi_ipcomp4_protocol __read_mostly = {
- .handler = xfrm4_rcv,
- .input_handler = xfrm_input,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 10,
-};
-
-#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
-static int xfrmi4_rcv_tunnel(struct sk_buff *skb)
-{
- return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr);
-}
-
-static struct xfrm_tunnel xfrmi_ipip_handler __read_mostly = {
- .handler = xfrmi4_rcv_tunnel,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 3,
-};
-
-static struct xfrm_tunnel xfrmi_ipip6_handler __read_mostly = {
- .handler = xfrmi4_rcv_tunnel,
- .cb_handler = xfrmi_rcv_cb,
- .err_handler = xfrmi4_err,
- .priority = 2,
-};
-#endif
-
-static int __init xfrmi4_init(void)
-{
- int err;
-
- err = xfrm4_protocol_register(&xfrmi_esp4_protocol, IPPROTO_ESP);
- if (err < 0)
- goto xfrm_proto_esp_failed;
- err = xfrm4_protocol_register(&xfrmi_ah4_protocol, IPPROTO_AH);
- if (err < 0)
- goto xfrm_proto_ah_failed;
- err = xfrm4_protocol_register(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
- if (err < 0)
- goto xfrm_proto_comp_failed;
-#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
- err = xfrm4_tunnel_register(&xfrmi_ipip_handler, AF_INET);
- if (err < 0)
- goto xfrm_tunnel_ipip_failed;
- err = xfrm4_tunnel_register(&xfrmi_ipip6_handler, AF_INET6);
- if (err < 0)
- goto xfrm_tunnel_ipip6_failed;
-#endif
-
- return 0;
-
-#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
-xfrm_tunnel_ipip6_failed:
- xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
-xfrm_tunnel_ipip_failed:
- xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
-#endif
-xfrm_proto_comp_failed:
- xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
-xfrm_proto_ah_failed:
- xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
-xfrm_proto_esp_failed:
- return err;
-}
-
-static void xfrmi4_fini(void)
-{
-#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
- xfrm4_tunnel_deregister(&xfrmi_ipip6_handler, AF_INET6);
- xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
-#endif
- xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
- xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
- xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
-}
-
-static int __init xfrmi6_init(void)
-{
- int err;
-
- err = xfrm6_protocol_register(&xfrmi_esp6_protocol, IPPROTO_ESP);
- if (err < 0)
- goto xfrm_proto_esp_failed;
- err = xfrm6_protocol_register(&xfrmi_ah6_protocol, IPPROTO_AH);
- if (err < 0)
- goto xfrm_proto_ah_failed;
- err = xfrm6_protocol_register(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
- if (err < 0)
- goto xfrm_proto_comp_failed;
-#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
- err = xfrm6_tunnel_register(&xfrmi_ipv6_handler, AF_INET6);
- if (err < 0)
- goto xfrm_tunnel_ipv6_failed;
- err = xfrm6_tunnel_register(&xfrmi_ip6ip_handler, AF_INET);
- if (err < 0)
- goto xfrm_tunnel_ip6ip_failed;
-#endif
-
- return 0;
-
-#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
-xfrm_tunnel_ip6ip_failed:
- xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
-xfrm_tunnel_ipv6_failed:
- xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
-#endif
-xfrm_proto_comp_failed:
- xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
-xfrm_proto_ah_failed:
- xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
-xfrm_proto_esp_failed:
- return err;
-}
-
-static void xfrmi6_fini(void)
-{
-#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
- xfrm6_tunnel_deregister(&xfrmi_ip6ip_handler, AF_INET);
- xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
-#endif
- xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
- xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
- xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
-}
-
-static const struct xfrm_if_cb xfrm_if_cb = {
- .decode_session = xfrmi_decode_session,
-};
-
-static int __init xfrmi_init(void)
-{
- const char *msg;
- int err;
-
- pr_info("IPsec XFRM device driver\n");
-
- msg = "tunnel device";
- err = register_pernet_device(&xfrmi_net_ops);
- if (err < 0)
- goto pernet_dev_failed;
-
- msg = "xfrm4 protocols";
- err = xfrmi4_init();
- if (err < 0)
- goto xfrmi4_failed;
-
- msg = "xfrm6 protocols";
- err = xfrmi6_init();
- if (err < 0)
- goto xfrmi6_failed;
-
-
- msg = "netlink interface";
- err = rtnl_link_register(&xfrmi_link_ops);
- if (err < 0)
- goto rtnl_link_failed;
-
- lwtunnel_encap_add_ops(&xfrmi_encap_ops, LWTUNNEL_ENCAP_XFRM);
-
- xfrm_if_register_cb(&xfrm_if_cb);
-
- return err;
-
-rtnl_link_failed:
- xfrmi6_fini();
-xfrmi6_failed:
- xfrmi4_fini();
-xfrmi4_failed:
- unregister_pernet_device(&xfrmi_net_ops);
-pernet_dev_failed:
- pr_err("xfrmi init: failed to register %s\n", msg);
- return err;
-}
-
-static void __exit xfrmi_fini(void)
-{
- xfrm_if_unregister_cb();
- lwtunnel_encap_del_ops(&xfrmi_encap_ops, LWTUNNEL_ENCAP_XFRM);
- rtnl_link_unregister(&xfrmi_link_ops);
- xfrmi4_fini();
- xfrmi6_fini();
- unregister_pernet_device(&xfrmi_net_ops);
-}
-
-module_init(xfrmi_init);
-module_exit(xfrmi_fini);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_RTNL_LINK("xfrm");
-MODULE_ALIAS_NETDEV("xfrm0");
-MODULE_AUTHOR("Steffen Klassert");
-MODULE_DESCRIPTION("XFRM virtual interface");
diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c
new file mode 100644
index 000000000000..94a3609548b1
--- /dev/null
+++ b/net/xfrm/xfrm_interface_core.c
@@ -0,0 +1,1244 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * XFRM virtual interface
+ *
+ * Copyright (C) 2018 secunet Security Networks AG
+ *
+ * Author:
+ * Steffen Klassert <steffen.klassert@secunet.com>
+ */
+
+#include <linux/module.h>
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/sockios.h>
+#include <linux/icmp.h>
+#include <linux/if.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/net.h>
+#include <linux/in6.h>
+#include <linux/netdevice.h>
+#include <linux/if_link.h>
+#include <linux/if_arp.h>
+#include <linux/icmpv6.h>
+#include <linux/init.h>
+#include <linux/route.h>
+#include <linux/rtnetlink.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/slab.h>
+#include <linux/hash.h>
+
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+
+#include <net/icmp.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/ip_tunnels.h>
+#include <net/addrconf.h>
+#include <net/xfrm.h>
+#include <net/net_namespace.h>
+#include <net/dst_metadata.h>
+#include <net/netns/generic.h>
+#include <linux/etherdevice.h>
+
+static int xfrmi_dev_init(struct net_device *dev);
+static void xfrmi_dev_setup(struct net_device *dev);
+static struct rtnl_link_ops xfrmi_link_ops __read_mostly;
+static unsigned int xfrmi_net_id __read_mostly;
+static const struct net_device_ops xfrmi_netdev_ops;
+
+#define XFRMI_HASH_BITS 8
+#define XFRMI_HASH_SIZE BIT(XFRMI_HASH_BITS)
+
+struct xfrmi_net {
+ /* lists for storing interfaces in use */
+ struct xfrm_if __rcu *xfrmi[XFRMI_HASH_SIZE];
+ struct xfrm_if __rcu *collect_md_xfrmi;
+};
+
+static const struct nla_policy xfrm_lwt_policy[LWT_XFRM_MAX + 1] = {
+ [LWT_XFRM_IF_ID] = NLA_POLICY_MIN(NLA_U32, 1),
+ [LWT_XFRM_LINK] = NLA_POLICY_MIN(NLA_U32, 1),
+};
+
+static void xfrmi_destroy_state(struct lwtunnel_state *lwt)
+{
+}
+
+static int xfrmi_build_state(struct net *net, struct nlattr *nla,
+ unsigned int family, const void *cfg,
+ struct lwtunnel_state **ts,
+ struct netlink_ext_ack *extack)
+{
+ struct nlattr *tb[LWT_XFRM_MAX + 1];
+ struct lwtunnel_state *new_state;
+ struct xfrm_md_info *info;
+ int ret;
+
+ ret = nla_parse_nested(tb, LWT_XFRM_MAX, nla, xfrm_lwt_policy, extack);
+ if (ret < 0)
+ return ret;
+
+ if (!tb[LWT_XFRM_IF_ID]) {
+ NL_SET_ERR_MSG(extack, "if_id must be set");
+ return -EINVAL;
+ }
+
+ new_state = lwtunnel_state_alloc(sizeof(*info));
+ if (!new_state) {
+ NL_SET_ERR_MSG(extack, "failed to create encap info");
+ return -ENOMEM;
+ }
+
+ new_state->type = LWTUNNEL_ENCAP_XFRM;
+
+ info = lwt_xfrm_info(new_state);
+
+ info->if_id = nla_get_u32(tb[LWT_XFRM_IF_ID]);
+
+ if (tb[LWT_XFRM_LINK])
+ info->link = nla_get_u32(tb[LWT_XFRM_LINK]);
+
+ *ts = new_state;
+ return 0;
+}
+
+static int xfrmi_fill_encap_info(struct sk_buff *skb,
+ struct lwtunnel_state *lwt)
+{
+ struct xfrm_md_info *info = lwt_xfrm_info(lwt);
+
+ if (nla_put_u32(skb, LWT_XFRM_IF_ID, info->if_id) ||
+ (info->link && nla_put_u32(skb, LWT_XFRM_LINK, info->link)))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
+static int xfrmi_encap_nlsize(struct lwtunnel_state *lwtstate)
+{
+ return nla_total_size(sizeof(u32)) + /* LWT_XFRM_IF_ID */
+ nla_total_size(sizeof(u32)); /* LWT_XFRM_LINK */
+}
+
+static int xfrmi_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
+{
+ struct xfrm_md_info *a_info = lwt_xfrm_info(a);
+ struct xfrm_md_info *b_info = lwt_xfrm_info(b);
+
+ return memcmp(a_info, b_info, sizeof(*a_info));
+}
+
+static const struct lwtunnel_encap_ops xfrmi_encap_ops = {
+ .build_state = xfrmi_build_state,
+ .destroy_state = xfrmi_destroy_state,
+ .fill_encap = xfrmi_fill_encap_info,
+ .get_encap_size = xfrmi_encap_nlsize,
+ .cmp_encap = xfrmi_encap_cmp,
+ .owner = THIS_MODULE,
+};
+
+#define for_each_xfrmi_rcu(start, xi) \
+ for (xi = rcu_dereference(start); xi; xi = rcu_dereference(xi->next))
+
+static u32 xfrmi_hash(u32 if_id)
+{
+ return hash_32(if_id, XFRMI_HASH_BITS);
+}
+
+static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x)
+{
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+ struct xfrm_if *xi;
+
+ for_each_xfrmi_rcu(xfrmn->xfrmi[xfrmi_hash(x->if_id)], xi) {
+ if (x->if_id == xi->p.if_id &&
+ (xi->dev->flags & IFF_UP))
+ return xi;
+ }
+
+ xi = rcu_dereference(xfrmn->collect_md_xfrmi);
+ if (xi && (xi->dev->flags & IFF_UP))
+ return xi;
+
+ return NULL;
+}
+
+static bool xfrmi_decode_session(struct sk_buff *skb,
+ unsigned short family,
+ struct xfrm_if_decode_session_result *res)
+{
+ struct net_device *dev;
+ struct xfrm_if *xi;
+ int ifindex = 0;
+
+ if (!secpath_exists(skb) || !skb->dev)
+ return false;
+
+ switch (family) {
+ case AF_INET6:
+ ifindex = inet6_sdif(skb);
+ break;
+ case AF_INET:
+ ifindex = inet_sdif(skb);
+ break;
+ }
+
+ if (ifindex) {
+ struct net *net = xs_net(xfrm_input_state(skb));
+
+ dev = dev_get_by_index_rcu(net, ifindex);
+ } else {
+ dev = skb->dev;
+ }
+
+ if (!dev || !(dev->flags & IFF_UP))
+ return false;
+ if (dev->netdev_ops != &xfrmi_netdev_ops)
+ return false;
+
+ xi = netdev_priv(dev);
+ res->net = xi->net;
+
+ if (xi->p.collect_md)
+ res->if_id = xfrm_input_state(skb)->if_id;
+ else
+ res->if_id = xi->p.if_id;
+ return true;
+}
+
+static void xfrmi_link(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
+{
+ struct xfrm_if __rcu **xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
+
+ rcu_assign_pointer(xi->next , rtnl_dereference(*xip));
+ rcu_assign_pointer(*xip, xi);
+}
+
+static void xfrmi_unlink(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
+{
+ struct xfrm_if __rcu **xip;
+ struct xfrm_if *iter;
+
+ for (xip = &xfrmn->xfrmi[xfrmi_hash(xi->p.if_id)];
+ (iter = rtnl_dereference(*xip)) != NULL;
+ xip = &iter->next) {
+ if (xi == iter) {
+ rcu_assign_pointer(*xip, xi->next);
+ break;
+ }
+ }
+}
+
+static void xfrmi_dev_free(struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+
+ gro_cells_destroy(&xi->gro_cells);
+ free_percpu(dev->tstats);
+}
+
+static int xfrmi_create(struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net *net = dev_net(dev);
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+ int err;
+
+ dev->rtnl_link_ops = &xfrmi_link_ops;
+ err = register_netdevice(dev);
+ if (err < 0)
+ goto out;
+
+ if (xi->p.collect_md)
+ rcu_assign_pointer(xfrmn->collect_md_xfrmi, xi);
+ else
+ xfrmi_link(xfrmn, xi);
+
+ return 0;
+
+out:
+ return err;
+}
+
+static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p)
+{
+ struct xfrm_if __rcu **xip;
+ struct xfrm_if *xi;
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+
+ for (xip = &xfrmn->xfrmi[xfrmi_hash(p->if_id)];
+ (xi = rtnl_dereference(*xip)) != NULL;
+ xip = &xi->next)
+ if (xi->p.if_id == p->if_id)
+ return xi;
+
+ return NULL;
+}
+
+static void xfrmi_dev_uninit(struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
+
+ if (xi->p.collect_md)
+ RCU_INIT_POINTER(xfrmn->collect_md_xfrmi, NULL);
+ else
+ xfrmi_unlink(xfrmn, xi);
+}
+
+static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
+{
+ skb_clear_tstamp(skb);
+ skb->pkt_type = PACKET_HOST;
+ skb->skb_iif = 0;
+ skb->ignore_df = 0;
+ skb_dst_drop(skb);
+ nf_reset_ct(skb);
+ nf_reset_trace(skb);
+
+ if (!xnet)
+ return;
+
+ ipvs_reset(skb);
+ secpath_reset(skb);
+ skb_orphan(skb);
+ skb->mark = 0;
+}
+
+static int xfrmi_input(struct sk_buff *skb, int nexthdr, __be32 spi,
+ int encap_type, unsigned short family)
+{
+ struct sec_path *sp;
+
+ sp = skb_sec_path(skb);
+ if (sp && (sp->len || sp->olen) &&
+ !xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
+ goto discard;
+
+ XFRM_SPI_SKB_CB(skb)->family = family;
+ if (family == AF_INET) {
+ XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
+ XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
+ } else {
+ XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
+ XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
+ }
+
+ return xfrm_input(skb, nexthdr, spi, encap_type);
+discard:
+ kfree_skb(skb);
+ return 0;
+}
+
+static int xfrmi4_rcv(struct sk_buff *skb)
+{
+ return xfrmi_input(skb, ip_hdr(skb)->protocol, 0, 0, AF_INET);
+}
+
+static int xfrmi6_rcv(struct sk_buff *skb)
+{
+ return xfrmi_input(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
+ 0, 0, AF_INET6);
+}
+
+static int xfrmi4_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
+{
+ return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET);
+}
+
+static int xfrmi6_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
+{
+ return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET6);
+}
+
+static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
+{
+ const struct xfrm_mode *inner_mode;
+ struct net_device *dev;
+ struct xfrm_state *x;
+ struct xfrm_if *xi;
+ bool xnet;
+ int link;
+
+ if (err && !secpath_exists(skb))
+ return 0;
+
+ x = xfrm_input_state(skb);
+
+ xi = xfrmi_lookup(xs_net(x), x);
+ if (!xi)
+ return 1;
+
+ link = skb->dev->ifindex;
+ dev = xi->dev;
+ skb->dev = dev;
+
+ if (err) {
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
+
+ return 0;
+ }
+
+ xnet = !net_eq(xi->net, dev_net(skb->dev));
+
+ if (xnet) {
+ inner_mode = &x->inner_mode;
+
+ if (x->sel.family == AF_UNSPEC) {
+ inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
+ if (inner_mode == NULL) {
+ XFRM_INC_STATS(dev_net(skb->dev),
+ LINUX_MIB_XFRMINSTATEMODEERROR);
+ return -EINVAL;
+ }
+ }
+
+ if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb,
+ inner_mode->family))
+ return -EPERM;
+ }
+
+ xfrmi_scrub_packet(skb, xnet);
+ if (xi->p.collect_md) {
+ struct metadata_dst *md_dst;
+
+ md_dst = metadata_dst_alloc(0, METADATA_XFRM, GFP_ATOMIC);
+ if (!md_dst)
+ return -ENOMEM;
+
+ md_dst->u.xfrm_info.if_id = x->if_id;
+ md_dst->u.xfrm_info.link = link;
+ skb_dst_set(skb, (struct dst_entry *)md_dst);
+ }
+ dev_sw_netstats_rx_add(dev, skb->len);
+
+ return 0;
+}
+
+static int
+xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net_device_stats *stats = &xi->dev->stats;
+ struct dst_entry *dst = skb_dst(skb);
+ unsigned int length = skb->len;
+ struct net_device *tdev;
+ struct xfrm_state *x;
+ int err = -1;
+ u32 if_id;
+ int mtu;
+
+ if (xi->p.collect_md) {
+ struct xfrm_md_info *md_info = skb_xfrm_md_info(skb);
+
+ if (unlikely(!md_info))
+ return -EINVAL;
+
+ if_id = md_info->if_id;
+ fl->flowi_oif = md_info->link;
+ } else {
+ if_id = xi->p.if_id;
+ }
+
+ dst_hold(dst);
+ dst = xfrm_lookup_with_ifid(xi->net, dst, fl, NULL, 0, if_id);
+ if (IS_ERR(dst)) {
+ err = PTR_ERR(dst);
+ dst = NULL;
+ goto tx_err_link_failure;
+ }
+
+ x = dst->xfrm;
+ if (!x)
+ goto tx_err_link_failure;
+
+ if (x->if_id != if_id)
+ goto tx_err_link_failure;
+
+ tdev = dst->dev;
+
+ if (tdev == dev) {
+ stats->collisions++;
+ net_warn_ratelimited("%s: Local routing loop detected!\n",
+ dev->name);
+ goto tx_err_dst_release;
+ }
+
+ mtu = dst_mtu(dst);
+ if ((!skb_is_gso(skb) && skb->len > mtu) ||
+ (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu))) {
+ skb_dst_update_pmtu_no_confirm(skb, mtu);
+
+ if (skb->protocol == htons(ETH_P_IPV6)) {
+ if (mtu < IPV6_MIN_MTU)
+ mtu = IPV6_MIN_MTU;
+
+ if (skb->len > 1280)
+ icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ else
+ goto xmit;
+ } else {
+ if (!(ip_hdr(skb)->frag_off & htons(IP_DF)))
+ goto xmit;
+ icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+ htonl(mtu));
+ }
+
+ dst_release(dst);
+ return -EMSGSIZE;
+ }
+
+xmit:
+ xfrmi_scrub_packet(skb, !net_eq(xi->net, dev_net(dev)));
+ skb_dst_set(skb, dst);
+ skb->dev = tdev;
+
+ err = dst_output(xi->net, skb->sk, skb);
+ if (net_xmit_eval(err) == 0) {
+ dev_sw_netstats_tx_add(dev, 1, length);
+ } else {
+ stats->tx_errors++;
+ stats->tx_aborted_errors++;
+ }
+
+ return 0;
+tx_err_link_failure:
+ stats->tx_carrier_errors++;
+ dst_link_failure(skb);
+tx_err_dst_release:
+ dst_release(dst);
+ return err;
+}
+
+static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net_device_stats *stats = &xi->dev->stats;
+ struct dst_entry *dst = skb_dst(skb);
+ struct flowi fl;
+ int ret;
+
+ memset(&fl, 0, sizeof(fl));
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IPV6):
+ xfrm_decode_session(skb, &fl, AF_INET6);
+ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+ if (!dst) {
+ fl.u.ip6.flowi6_oif = dev->ifindex;
+ fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
+ dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6);
+ if (dst->error) {
+ dst_release(dst);
+ stats->tx_carrier_errors++;
+ goto tx_err;
+ }
+ skb_dst_set(skb, dst);
+ }
+ break;
+ case htons(ETH_P_IP):
+ xfrm_decode_session(skb, &fl, AF_INET);
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+ if (!dst) {
+ struct rtable *rt;
+
+ fl.u.ip4.flowi4_oif = dev->ifindex;
+ fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+ rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4);
+ if (IS_ERR(rt)) {
+ stats->tx_carrier_errors++;
+ goto tx_err;
+ }
+ skb_dst_set(skb, &rt->dst);
+ }
+ break;
+ default:
+ goto tx_err;
+ }
+
+ fl.flowi_oif = xi->p.link;
+
+ ret = xfrmi_xmit2(skb, dev, &fl);
+ if (ret < 0)
+ goto tx_err;
+
+ return NETDEV_TX_OK;
+
+tx_err:
+ stats->tx_errors++;
+ stats->tx_dropped++;
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+static int xfrmi4_err(struct sk_buff *skb, u32 info)
+{
+ const struct iphdr *iph = (const struct iphdr *)skb->data;
+ struct net *net = dev_net(skb->dev);
+ int protocol = iph->protocol;
+ struct ip_comp_hdr *ipch;
+ struct ip_esp_hdr *esph;
+ struct ip_auth_hdr *ah ;
+ struct xfrm_state *x;
+ struct xfrm_if *xi;
+ __be32 spi;
+
+ switch (protocol) {
+ case IPPROTO_ESP:
+ esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
+ spi = esph->spi;
+ break;
+ case IPPROTO_AH:
+ ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
+ spi = ah->spi;
+ break;
+ case IPPROTO_COMP:
+ ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
+ spi = htonl(ntohs(ipch->cpi));
+ break;
+ default:
+ return 0;
+ }
+
+ switch (icmp_hdr(skb)->type) {
+ case ICMP_DEST_UNREACH:
+ if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
+ return 0;
+ break;
+ case ICMP_REDIRECT:
+ break;
+ default:
+ return 0;
+ }
+
+ x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
+ spi, protocol, AF_INET);
+ if (!x)
+ return 0;
+
+ xi = xfrmi_lookup(net, x);
+ if (!xi) {
+ xfrm_state_put(x);
+ return -1;
+ }
+
+ if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+ ipv4_update_pmtu(skb, net, info, 0, protocol);
+ else
+ ipv4_redirect(skb, net, 0, protocol);
+ xfrm_state_put(x);
+
+ return 0;
+}
+
+static int xfrmi6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ u8 type, u8 code, int offset, __be32 info)
+{
+ const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
+ struct net *net = dev_net(skb->dev);
+ int protocol = iph->nexthdr;
+ struct ip_comp_hdr *ipch;
+ struct ip_esp_hdr *esph;
+ struct ip_auth_hdr *ah;
+ struct xfrm_state *x;
+ struct xfrm_if *xi;
+ __be32 spi;
+
+ switch (protocol) {
+ case IPPROTO_ESP:
+ esph = (struct ip_esp_hdr *)(skb->data + offset);
+ spi = esph->spi;
+ break;
+ case IPPROTO_AH:
+ ah = (struct ip_auth_hdr *)(skb->data + offset);
+ spi = ah->spi;
+ break;
+ case IPPROTO_COMP:
+ ipch = (struct ip_comp_hdr *)(skb->data + offset);
+ spi = htonl(ntohs(ipch->cpi));
+ break;
+ default:
+ return 0;
+ }
+
+ if (type != ICMPV6_PKT_TOOBIG &&
+ type != NDISC_REDIRECT)
+ return 0;
+
+ x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
+ spi, protocol, AF_INET6);
+ if (!x)
+ return 0;
+
+ xi = xfrmi_lookup(net, x);
+ if (!xi) {
+ xfrm_state_put(x);
+ return -1;
+ }
+
+ if (type == NDISC_REDIRECT)
+ ip6_redirect(skb, net, skb->dev->ifindex, 0,
+ sock_net_uid(net, NULL));
+ else
+ ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
+ xfrm_state_put(x);
+
+ return 0;
+}
+
+static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p)
+{
+ if (xi->p.link != p->link)
+ return -EINVAL;
+
+ xi->p.if_id = p->if_id;
+
+ return 0;
+}
+
+static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
+{
+ struct net *net = xi->net;
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+ int err;
+
+ xfrmi_unlink(xfrmn, xi);
+ synchronize_net();
+ err = xfrmi_change(xi, p);
+ xfrmi_link(xfrmn, xi);
+ netdev_state_change(xi->dev);
+ return err;
+}
+
+static int xfrmi_get_iflink(const struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+
+ return xi->p.link;
+}
+
+static const struct net_device_ops xfrmi_netdev_ops = {
+ .ndo_init = xfrmi_dev_init,
+ .ndo_uninit = xfrmi_dev_uninit,
+ .ndo_start_xmit = xfrmi_xmit,
+ .ndo_get_stats64 = dev_get_tstats64,
+ .ndo_get_iflink = xfrmi_get_iflink,
+};
+
+static void xfrmi_dev_setup(struct net_device *dev)
+{
+ dev->netdev_ops = &xfrmi_netdev_ops;
+ dev->header_ops = &ip_tunnel_header_ops;
+ dev->type = ARPHRD_NONE;
+ dev->mtu = ETH_DATA_LEN;
+ dev->min_mtu = ETH_MIN_MTU;
+ dev->max_mtu = IP_MAX_MTU;
+ dev->flags = IFF_NOARP;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = xfrmi_dev_free;
+ netif_keep_dst(dev);
+
+ eth_broadcast_addr(dev->broadcast);
+}
+
+#define XFRMI_FEATURES (NETIF_F_SG | \
+ NETIF_F_FRAGLIST | \
+ NETIF_F_GSO_SOFTWARE | \
+ NETIF_F_HW_CSUM)
+
+static int xfrmi_dev_init(struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
+ int err;
+
+ dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+ if (!dev->tstats)
+ return -ENOMEM;
+
+ err = gro_cells_init(&xi->gro_cells, dev);
+ if (err) {
+ free_percpu(dev->tstats);
+ return err;
+ }
+
+ dev->features |= NETIF_F_LLTX;
+ dev->features |= XFRMI_FEATURES;
+ dev->hw_features |= XFRMI_FEATURES;
+
+ if (phydev) {
+ dev->needed_headroom = phydev->needed_headroom;
+ dev->needed_tailroom = phydev->needed_tailroom;
+
+ if (is_zero_ether_addr(dev->dev_addr))
+ eth_hw_addr_inherit(dev, phydev);
+ if (is_zero_ether_addr(dev->broadcast))
+ memcpy(dev->broadcast, phydev->broadcast,
+ dev->addr_len);
+ } else {
+ eth_hw_addr_random(dev);
+ eth_broadcast_addr(dev->broadcast);
+ }
+
+ return 0;
+}
+
+static int xfrmi_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static void xfrmi_netlink_parms(struct nlattr *data[],
+ struct xfrm_if_parms *parms)
+{
+ memset(parms, 0, sizeof(*parms));
+
+ if (!data)
+ return;
+
+ if (data[IFLA_XFRM_LINK])
+ parms->link = nla_get_u32(data[IFLA_XFRM_LINK]);
+
+ if (data[IFLA_XFRM_IF_ID])
+ parms->if_id = nla_get_u32(data[IFLA_XFRM_IF_ID]);
+
+ if (data[IFLA_XFRM_COLLECT_METADATA])
+ parms->collect_md = true;
+}
+
+static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ struct net *net = dev_net(dev);
+ struct xfrm_if_parms p = {};
+ struct xfrm_if *xi;
+ int err;
+
+ xfrmi_netlink_parms(data, &p);
+ if (p.collect_md) {
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+
+ if (p.link || p.if_id) {
+ NL_SET_ERR_MSG(extack, "link and if_id must be zero");
+ return -EINVAL;
+ }
+
+ if (rtnl_dereference(xfrmn->collect_md_xfrmi))
+ return -EEXIST;
+
+ } else {
+ if (!p.if_id) {
+ NL_SET_ERR_MSG(extack, "if_id must be non zero");
+ return -EINVAL;
+ }
+
+ xi = xfrmi_locate(net, &p);
+ if (xi)
+ return -EEXIST;
+ }
+
+ xi = netdev_priv(dev);
+ xi->p = p;
+ xi->net = net;
+ xi->dev = dev;
+
+ err = xfrmi_create(dev);
+ return err;
+}
+
+static void xfrmi_dellink(struct net_device *dev, struct list_head *head)
+{
+ unregister_netdevice_queue(dev, head);
+}
+
+static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
+ struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct net *net = xi->net;
+ struct xfrm_if_parms p = {};
+
+ xfrmi_netlink_parms(data, &p);
+ if (!p.if_id) {
+ NL_SET_ERR_MSG(extack, "if_id must be non zero");
+ return -EINVAL;
+ }
+
+ if (p.collect_md) {
+ NL_SET_ERR_MSG(extack, "collect_md can't be changed");
+ return -EINVAL;
+ }
+
+ xi = xfrmi_locate(net, &p);
+ if (!xi) {
+ xi = netdev_priv(dev);
+ } else {
+ if (xi->dev != dev)
+ return -EEXIST;
+ if (xi->p.collect_md) {
+ NL_SET_ERR_MSG(extack,
+ "device can't be changed to collect_md");
+ return -EINVAL;
+ }
+ }
+
+ return xfrmi_update(xi, &p);
+}
+
+static size_t xfrmi_get_size(const struct net_device *dev)
+{
+ return
+ /* IFLA_XFRM_LINK */
+ nla_total_size(4) +
+ /* IFLA_XFRM_IF_ID */
+ nla_total_size(4) +
+ /* IFLA_XFRM_COLLECT_METADATA */
+ nla_total_size(0) +
+ 0;
+}
+
+static int xfrmi_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+ struct xfrm_if_parms *parm = &xi->p;
+
+ if (nla_put_u32(skb, IFLA_XFRM_LINK, parm->link) ||
+ nla_put_u32(skb, IFLA_XFRM_IF_ID, parm->if_id) ||
+ (xi->p.collect_md && nla_put_flag(skb, IFLA_XFRM_COLLECT_METADATA)))
+ goto nla_put_failure;
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static struct net *xfrmi_get_link_net(const struct net_device *dev)
+{
+ struct xfrm_if *xi = netdev_priv(dev);
+
+ return xi->net;
+}
+
+static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
+ [IFLA_XFRM_UNSPEC] = { .strict_start_type = IFLA_XFRM_COLLECT_METADATA },
+ [IFLA_XFRM_LINK] = { .type = NLA_U32 },
+ [IFLA_XFRM_IF_ID] = { .type = NLA_U32 },
+ [IFLA_XFRM_COLLECT_METADATA] = { .type = NLA_FLAG },
+};
+
+static struct rtnl_link_ops xfrmi_link_ops __read_mostly = {
+ .kind = "xfrm",
+ .maxtype = IFLA_XFRM_MAX,
+ .policy = xfrmi_policy,
+ .priv_size = sizeof(struct xfrm_if),
+ .setup = xfrmi_dev_setup,
+ .validate = xfrmi_validate,
+ .newlink = xfrmi_newlink,
+ .dellink = xfrmi_dellink,
+ .changelink = xfrmi_changelink,
+ .get_size = xfrmi_get_size,
+ .fill_info = xfrmi_fill_info,
+ .get_link_net = xfrmi_get_link_net,
+};
+
+static void __net_exit xfrmi_exit_batch_net(struct list_head *net_exit_list)
+{
+ struct net *net;
+ LIST_HEAD(list);
+
+ rtnl_lock();
+ list_for_each_entry(net, net_exit_list, exit_list) {
+ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+ struct xfrm_if __rcu **xip;
+ struct xfrm_if *xi;
+ int i;
+
+ for (i = 0; i < XFRMI_HASH_SIZE; i++) {
+ for (xip = &xfrmn->xfrmi[i];
+ (xi = rtnl_dereference(*xip)) != NULL;
+ xip = &xi->next)
+ unregister_netdevice_queue(xi->dev, &list);
+ }
+ xi = rtnl_dereference(xfrmn->collect_md_xfrmi);
+ if (xi)
+ unregister_netdevice_queue(xi->dev, &list);
+ }
+ unregister_netdevice_many(&list);
+ rtnl_unlock();
+}
+
+static struct pernet_operations xfrmi_net_ops = {
+ .exit_batch = xfrmi_exit_batch_net,
+ .id = &xfrmi_net_id,
+ .size = sizeof(struct xfrmi_net),
+};
+
+static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
+ .handler = xfrmi6_rcv,
+ .input_handler = xfrmi6_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 10,
+};
+
+static struct xfrm6_protocol xfrmi_ah6_protocol __read_mostly = {
+ .handler = xfrm6_rcv,
+ .input_handler = xfrm_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 10,
+};
+
+static struct xfrm6_protocol xfrmi_ipcomp6_protocol __read_mostly = {
+ .handler = xfrm6_rcv,
+ .input_handler = xfrm_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 10,
+};
+
+#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+static int xfrmi6_rcv_tunnel(struct sk_buff *skb)
+{
+ const xfrm_address_t *saddr;
+ __be32 spi;
+
+ saddr = (const xfrm_address_t *)&ipv6_hdr(skb)->saddr;
+ spi = xfrm6_tunnel_spi_lookup(dev_net(skb->dev), saddr);
+
+ return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi, NULL);
+}
+
+static struct xfrm6_tunnel xfrmi_ipv6_handler __read_mostly = {
+ .handler = xfrmi6_rcv_tunnel,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 2,
+};
+
+static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
+ .handler = xfrmi6_rcv_tunnel,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi6_err,
+ .priority = 2,
+};
+#endif
+
+static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
+ .handler = xfrmi4_rcv,
+ .input_handler = xfrmi4_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 10,
+};
+
+static struct xfrm4_protocol xfrmi_ah4_protocol __read_mostly = {
+ .handler = xfrm4_rcv,
+ .input_handler = xfrm_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 10,
+};
+
+static struct xfrm4_protocol xfrmi_ipcomp4_protocol __read_mostly = {
+ .handler = xfrm4_rcv,
+ .input_handler = xfrm_input,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 10,
+};
+
+#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+static int xfrmi4_rcv_tunnel(struct sk_buff *skb)
+{
+ return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr);
+}
+
+static struct xfrm_tunnel xfrmi_ipip_handler __read_mostly = {
+ .handler = xfrmi4_rcv_tunnel,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 3,
+};
+
+static struct xfrm_tunnel xfrmi_ipip6_handler __read_mostly = {
+ .handler = xfrmi4_rcv_tunnel,
+ .cb_handler = xfrmi_rcv_cb,
+ .err_handler = xfrmi4_err,
+ .priority = 2,
+};
+#endif
+
+static int __init xfrmi4_init(void)
+{
+ int err;
+
+ err = xfrm4_protocol_register(&xfrmi_esp4_protocol, IPPROTO_ESP);
+ if (err < 0)
+ goto xfrm_proto_esp_failed;
+ err = xfrm4_protocol_register(&xfrmi_ah4_protocol, IPPROTO_AH);
+ if (err < 0)
+ goto xfrm_proto_ah_failed;
+ err = xfrm4_protocol_register(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
+ if (err < 0)
+ goto xfrm_proto_comp_failed;
+#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+ err = xfrm4_tunnel_register(&xfrmi_ipip_handler, AF_INET);
+ if (err < 0)
+ goto xfrm_tunnel_ipip_failed;
+ err = xfrm4_tunnel_register(&xfrmi_ipip6_handler, AF_INET6);
+ if (err < 0)
+ goto xfrm_tunnel_ipip6_failed;
+#endif
+
+ return 0;
+
+#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+xfrm_tunnel_ipip6_failed:
+ xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
+xfrm_tunnel_ipip_failed:
+ xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
+#endif
+xfrm_proto_comp_failed:
+ xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
+xfrm_proto_ah_failed:
+ xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
+xfrm_proto_esp_failed:
+ return err;
+}
+
+static void xfrmi4_fini(void)
+{
+#if IS_REACHABLE(CONFIG_INET_XFRM_TUNNEL)
+ xfrm4_tunnel_deregister(&xfrmi_ipip6_handler, AF_INET6);
+ xfrm4_tunnel_deregister(&xfrmi_ipip_handler, AF_INET);
+#endif
+ xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
+ xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
+ xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
+}
+
+static int __init xfrmi6_init(void)
+{
+ int err;
+
+ err = xfrm6_protocol_register(&xfrmi_esp6_protocol, IPPROTO_ESP);
+ if (err < 0)
+ goto xfrm_proto_esp_failed;
+ err = xfrm6_protocol_register(&xfrmi_ah6_protocol, IPPROTO_AH);
+ if (err < 0)
+ goto xfrm_proto_ah_failed;
+ err = xfrm6_protocol_register(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
+ if (err < 0)
+ goto xfrm_proto_comp_failed;
+#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+ err = xfrm6_tunnel_register(&xfrmi_ipv6_handler, AF_INET6);
+ if (err < 0)
+ goto xfrm_tunnel_ipv6_failed;
+ err = xfrm6_tunnel_register(&xfrmi_ip6ip_handler, AF_INET);
+ if (err < 0)
+ goto xfrm_tunnel_ip6ip_failed;
+#endif
+
+ return 0;
+
+#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+xfrm_tunnel_ip6ip_failed:
+ xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
+xfrm_tunnel_ipv6_failed:
+ xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
+#endif
+xfrm_proto_comp_failed:
+ xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
+xfrm_proto_ah_failed:
+ xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
+xfrm_proto_esp_failed:
+ return err;
+}
+
+static void xfrmi6_fini(void)
+{
+#if IS_REACHABLE(CONFIG_INET6_XFRM_TUNNEL)
+ xfrm6_tunnel_deregister(&xfrmi_ip6ip_handler, AF_INET);
+ xfrm6_tunnel_deregister(&xfrmi_ipv6_handler, AF_INET6);
+#endif
+ xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
+ xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
+ xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
+}
+
+static const struct xfrm_if_cb xfrm_if_cb = {
+ .decode_session = xfrmi_decode_session,
+};
+
+static int __init xfrmi_init(void)
+{
+ const char *msg;
+ int err;
+
+ pr_info("IPsec XFRM device driver\n");
+
+ msg = "tunnel device";
+ err = register_pernet_device(&xfrmi_net_ops);
+ if (err < 0)
+ goto pernet_dev_failed;
+
+ msg = "xfrm4 protocols";
+ err = xfrmi4_init();
+ if (err < 0)
+ goto xfrmi4_failed;
+
+ msg = "xfrm6 protocols";
+ err = xfrmi6_init();
+ if (err < 0)
+ goto xfrmi6_failed;
+
+
+ msg = "netlink interface";
+ err = rtnl_link_register(&xfrmi_link_ops);
+ if (err < 0)
+ goto rtnl_link_failed;
+
+ lwtunnel_encap_add_ops(&xfrmi_encap_ops, LWTUNNEL_ENCAP_XFRM);
+
+ xfrm_if_register_cb(&xfrm_if_cb);
+
+ return err;
+
+rtnl_link_failed:
+ xfrmi6_fini();
+xfrmi6_failed:
+ xfrmi4_fini();
+xfrmi4_failed:
+ unregister_pernet_device(&xfrmi_net_ops);
+pernet_dev_failed:
+ pr_err("xfrmi init: failed to register %s\n", msg);
+ return err;
+}
+
+static void __exit xfrmi_fini(void)
+{
+ xfrm_if_unregister_cb();
+ lwtunnel_encap_del_ops(&xfrmi_encap_ops, LWTUNNEL_ENCAP_XFRM);
+ rtnl_link_unregister(&xfrmi_link_ops);
+ xfrmi4_fini();
+ xfrmi6_fini();
+ unregister_pernet_device(&xfrmi_net_ops);
+}
+
+module_init(xfrmi_init);
+module_exit(xfrmi_fini);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_RTNL_LINK("xfrm");
+MODULE_ALIAS_NETDEV("xfrm0");
+MODULE_AUTHOR("Steffen Klassert");
+MODULE_DESCRIPTION("XFRM virtual interface");
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e894c269affb..7b1b93584bdb 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3274,6 +3274,13 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
return ++idx;
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
+ if (idx < sp->verified_cnt) {
+ /* Secpath entry previously verified, consider optional and
+ * continue searching
+ */
+ continue;
+ }
+
if (start == -1)
start = -2-idx;
break;
@@ -3648,6 +3655,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
* Order is _important_. Later we will implement
* some barriers, but at the moment barriers
* are implied between each two transformations.
+ * Upon success, marks secpath entries as having been
+ * verified to allow them to be skipped in future policy
+ * checks (e.g. nested tunnels).
*/
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
@@ -3666,6 +3676,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
}
xfrm_pols_put(pols, npols);
+ sp->verified_cnt = k;
+
return 1;
}
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK);
diff --git a/scripts/gfp-translate b/scripts/gfp-translate
index b2ce416d944b..6c9aed17cf56 100755
--- a/scripts/gfp-translate
+++ b/scripts/gfp-translate
@@ -63,11 +63,11 @@ fi
# Extract GFP flags from the kernel source
TMPFILE=`mktemp -t gfptranslate-XXXXXX` || exit 1
-grep -q ___GFP $SOURCE/include/linux/gfp.h
+grep -q ___GFP $SOURCE/include/linux/gfp_types.h
if [ $? -eq 0 ]; then
- grep "^#define ___GFP" $SOURCE/include/linux/gfp.h | sed -e 's/u$//' | grep -v GFP_BITS > $TMPFILE
+ grep "^#define ___GFP" $SOURCE/include/linux/gfp_types.h | sed -e 's/u$//' | grep -v GFP_BITS > $TMPFILE
else
- grep "^#define __GFP" $SOURCE/include/linux/gfp.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE
+ grep "^#define __GFP" $SOURCE/include/linux/gfp_types.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE
fi
# Parse the flags
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 920e44ba998a..eb049014f87a 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -9594,6 +9594,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
+ SND_PCI_QUIRK(0x10ec, 0x12cc, "Intel Reference board", ALC225_FIXUP_HEADSET_JACK),
SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
@@ -9814,6 +9815,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED),
SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10),
+ SND_PCI_QUIRK(0x8086, 0x3038, "Intel NUC 13", ALC225_FIXUP_HEADSET_JACK),
SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
#if 0
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 84b401b685f7..c1ca3ceac5f2 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -171,6 +171,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "21CL"),
}
},
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21EF"),
+ }
+ },
{
.driver_data = &acp6x_card,
.matches = {
diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c
index 4f19fd9b65d1..5a4db8944d06 100644
--- a/sound/soc/codecs/nau8824.c
+++ b/sound/soc/codecs/nau8824.c
@@ -1903,6 +1903,30 @@ static const struct dmi_system_id nau8824_quirk_table[] = {
},
.driver_data = (void *)(NAU8824_MONO_SPEAKER),
},
+ {
+ /* Positivo CW14Q01P */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+ DMI_MATCH(DMI_BOARD_NAME, "CW14Q01P"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
+ {
+ /* Positivo K1424G */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+ DMI_MATCH(DMI_BOARD_NAME, "K1424G"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
+ {
+ /* Positivo N14ZP74G */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+ DMI_MATCH(DMI_BOARD_NAME, "N14ZP74G"),
+ },
+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH),
+ },
{}
};
diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c
index 402286dfaea4..9c10200ff34b 100644
--- a/sound/soc/codecs/wcd938x-sdw.c
+++ b/sound/soc/codecs/wcd938x-sdw.c
@@ -1190,7 +1190,6 @@ static const struct regmap_config wcd938x_regmap_config = {
.readable_reg = wcd938x_readable_register,
.writeable_reg = wcd938x_writeable_register,
.volatile_reg = wcd938x_volatile_register,
- .can_multi_write = true,
};
static const struct sdw_slave_ops wcd9380_slave_ops = {
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 6d88af5b287f..b33104715c7b 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -491,14 +491,21 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
regmap_update_bits(sai->regmap, reg, FSL_SAI_CR2_MSEL_MASK,
FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
- if (savediv == 1)
+ if (savediv == 1) {
regmap_update_bits(sai->regmap, reg,
FSL_SAI_CR2_DIV_MASK | FSL_SAI_CR2_BYP,
FSL_SAI_CR2_BYP);
- else
+ if (fsl_sai_dir_is_synced(sai, adir))
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
+ FSL_SAI_CR2_BCI, FSL_SAI_CR2_BCI);
+ else
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
+ FSL_SAI_CR2_BCI, 0);
+ } else {
regmap_update_bits(sai->regmap, reg,
FSL_SAI_CR2_DIV_MASK | FSL_SAI_CR2_BYP,
savediv / 2 - 1);
+ }
if (sai->soc_data->max_register >= FSL_SAI_MCTL) {
/* SAI is in master mode at this point, so enable MCLK */
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index 697f6690068c..c5423f81e456 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -116,6 +116,7 @@
/* SAI Transmit and Receive Configuration 2 Register */
#define FSL_SAI_CR2_SYNC BIT(30)
+#define FSL_SAI_CR2_BCI BIT(28)
#define FSL_SAI_CR2_MSEL_MASK (0x3 << 26)
#define FSL_SAI_CR2_MSEL_BUS 0
#define FSL_SAI_CR2_MSEL_MCLK1 BIT(26)
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index feb55b66239b..fbb682747f59 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -416,6 +416,7 @@ static int __simple_for_each_link(struct asoc_simple_priv *priv,
if (ret < 0) {
of_node_put(codec);
+ of_node_put(plat);
of_node_put(np);
goto error;
}
diff --git a/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c b/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c
index c2aa6f26738b..bf82b923c5fe 100644
--- a/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c
+++ b/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c
@@ -1,13 +1,14 @@
{
"bounds checks mixing signed and unsigned, positive bounds",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 2),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 3),
@@ -17,20 +18,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 3),
@@ -40,20 +42,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 2",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 5),
@@ -65,20 +68,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 3",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 4),
@@ -89,20 +93,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 4",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 1),
BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
@@ -112,19 +117,20 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.result = ACCEPT,
},
{
"bounds checks mixing signed and unsigned, variant 5",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 5),
@@ -135,17 +141,20 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 6",
.insns = {
+ BPF_MOV64_REG(BPF_REG_9, BPF_REG_1),
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_9),
BPF_MOV64_IMM(BPF_REG_2, 0),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -512),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_6, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_6, 5),
@@ -163,13 +172,14 @@
{
"bounds checks mixing signed and unsigned, variant 7",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 1024 * 1024 * 1024),
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 3),
@@ -179,19 +189,20 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.result = ACCEPT,
},
{
"bounds checks mixing signed and unsigned, variant 8",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 2),
@@ -203,20 +214,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 9",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_LD_IMM64(BPF_REG_2, -9223372036854775808ULL),
BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 2),
@@ -228,19 +240,20 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.result = ACCEPT,
},
{
"bounds checks mixing signed and unsigned, variant 10",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 0),
BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 2),
@@ -252,20 +265,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 11",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
@@ -278,20 +292,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 12",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -6),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
@@ -303,20 +318,21 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 13",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, 2),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
@@ -331,7 +347,7 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
@@ -340,13 +356,14 @@
.insns = {
BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
offsetof(struct __sk_buff, mark)),
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -1),
BPF_MOV64_IMM(BPF_REG_8, 2),
@@ -360,20 +377,21 @@
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, -3),
BPF_JMP_IMM(BPF_JA, 0, 0, -7),
},
- .fixup_map_hash_8b = { 4 },
+ .fixup_map_hash_8b = { 6 },
.errstr = "unbounded min value",
.result = REJECT,
},
{
"bounds checks mixing signed and unsigned, variant 15",
.insns = {
+ BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
- BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
- BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, -8),
+ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
BPF_MOV64_IMM(BPF_REG_2, -6),
BPF_JMP_REG(BPF_JGE, BPF_REG_2, BPF_REG_1, 2),
@@ -387,7 +405,7 @@
BPF_MOV64_IMM(BPF_REG_0, 0),
BPF_EXIT_INSN(),
},
- .fixup_map_hash_8b = { 3 },
+ .fixup_map_hash_8b = { 5 },
.errstr = "unbounded min value",
.result = REJECT,
},
diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c
index 969647228817..c6a8c732b802 100644
--- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c
+++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c
@@ -104,13 +104,6 @@
#else
#define __NR_mount_setattr 442
#endif
-
-struct mount_attr {
- __u64 attr_set;
- __u64 attr_clr;
- __u64 propagation;
- __u64 userns_fd;
-};
#endif
#ifndef __NR_open_tree
diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index 21ca91473c09..ee6880ac3e5e 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -92,6 +92,13 @@ NSC_CMD="ip netns exec ${NSC}"
which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
+# Check if FIPS mode is enabled
+if [ -f /proc/sys/crypto/fips_enabled ]; then
+ fips_enabled=`cat /proc/sys/crypto/fips_enabled`
+else
+ fips_enabled=0
+fi
+
################################################################################
# utilities
@@ -1216,7 +1223,7 @@ ipv4_tcp_novrf()
run_cmd nettest -d ${NSA_DEV} -r ${a}
log_test_addr ${a} $? 1 "No server, device client, local conn"
- ipv4_tcp_md5_novrf
+ [ "$fips_enabled" = "1" ] || ipv4_tcp_md5_novrf
}
ipv4_tcp_vrf()
@@ -1270,9 +1277,11 @@ ipv4_tcp_vrf()
log_test_addr ${a} $? 1 "Global server, local connection"
# run MD5 tests
- setup_vrf_dup
- ipv4_tcp_md5
- cleanup_vrf_dup
+ if [ "$fips_enabled" = "0" ]; then
+ setup_vrf_dup
+ ipv4_tcp_md5
+ cleanup_vrf_dup
+ fi
#
# enable VRF global server
@@ -2772,7 +2781,7 @@ ipv6_tcp_novrf()
log_test_addr ${a} $? 1 "No server, device client, local conn"
done
- ipv6_tcp_md5_novrf
+ [ "$fips_enabled" = "1" ] || ipv6_tcp_md5_novrf
}
ipv6_tcp_vrf()
@@ -2842,9 +2851,11 @@ ipv6_tcp_vrf()
log_test_addr ${a} $? 1 "Global server, local connection"
# run MD5 tests
- setup_vrf_dup
- ipv6_tcp_md5
- cleanup_vrf_dup
+ if [ "$fips_enabled" = "0" ]; then
+ setup_vrf_dup
+ ipv6_tcp_md5
+ cleanup_vrf_dup
+ fi
#
# enable VRF global server
diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh
index c5095da7f6bf..aec752a22e9e 100755
--- a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh
+++ b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d.sh
@@ -93,12 +93,16 @@ cleanup()
test_gretap()
{
+ ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \
+ nud permanent dev br2
full_test_span_gre_dir gt4 ingress 8 0 "mirror to gretap"
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
}
test_ip6gretap()
{
+ ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \
+ nud permanent dev br2
full_test_span_gre_dir gt6 ingress 8 0 "mirror to ip6gretap"
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
}
diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
index 9ff22f28032d..0cf4c47a46f9 100755
--- a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
+++ b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh
@@ -90,12 +90,16 @@ cleanup()
test_gretap()
{
+ ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \
+ nud permanent dev br1
full_test_span_gre_dir gt4 ingress 8 0 "mirror to gretap"
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
}
test_ip6gretap()
{
+ ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \
+ nud permanent dev br1
full_test_span_gre_dir gt6 ingress 8 0 "mirror to ip6gretap"
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
}
diff --git a/tools/testing/selftests/net/mptcp/config b/tools/testing/selftests/net/mptcp/config
index 38021a0dd527..6032f9b23c4c 100644
--- a/tools/testing/selftests/net/mptcp/config
+++ b/tools/testing/selftests/net/mptcp/config
@@ -1,3 +1,4 @@
+CONFIG_KALLSYMS=y
CONFIG_MPTCP=y
CONFIG_IPV6=y
CONFIG_MPTCP_IPV6=y
diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh
index dd730a35bd12..400cf1ce96e3 100755
--- a/tools/testing/selftests/net/mptcp/diag.sh
+++ b/tools/testing/selftests/net/mptcp/diag.sh
@@ -42,27 +42,39 @@ fi
__chk_nr()
{
- local condition="$1"
+ local command="$1"
local expected=$2
- local msg nr
+ local msg="$3"
+ local skip="${4:-SKIP}"
+ local nr
- shift 2
- msg=$*
- nr=$(ss -inmHMN $ns | $condition)
+ nr=$(eval $command)
printf "%-50s" "$msg"
if [ $nr != $expected ]; then
- echo "[ fail ] expected $expected found $nr"
- ret=$test_cnt
+ if [ $nr = "$skip" ] && ! mptcp_lib_expect_all_features; then
+ echo "[ skip ] Feature probably not supported"
+ else
+ echo "[ fail ] expected $expected found $nr"
+ ret=$test_cnt
+ fi
else
echo "[ ok ]"
fi
test_cnt=$((test_cnt+1))
}
+__chk_msk_nr()
+{
+ local condition=$1
+ shift 1
+
+ __chk_nr "ss -inmHMN $ns | $condition" "$@"
+}
+
chk_msk_nr()
{
- __chk_nr "grep -c token:" $*
+ __chk_msk_nr "grep -c token:" "$@"
}
wait_msk_nr()
@@ -100,37 +112,26 @@ wait_msk_nr()
chk_msk_fallback_nr()
{
- __chk_nr "grep -c fallback" $*
+ __chk_msk_nr "grep -c fallback" "$@"
}
chk_msk_remote_key_nr()
{
- __chk_nr "grep -c remote_key" $*
+ __chk_msk_nr "grep -c remote_key" "$@"
}
__chk_listen()
{
local filter="$1"
local expected=$2
+ local msg="$3"
- shift 2
- msg=$*
-
- nr=$(ss -N $ns -Ml "$filter" | grep -c LISTEN)
- printf "%-50s" "$msg"
-
- if [ $nr != $expected ]; then
- echo "[ fail ] expected $expected found $nr"
- ret=$test_cnt
- else
- echo "[ ok ]"
- fi
+ __chk_nr "ss -N $ns -Ml '$filter' | grep -c LISTEN" "$expected" "$msg" 0
}
chk_msk_listen()
{
lport=$1
- local msg="check for listen socket"
# destination port search should always return empty list
__chk_listen "dport $lport" 0 "listen match for dport $lport"
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index e54653ea2ed4..7df6b9b6f9a8 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -98,8 +98,8 @@ static struct cfg_sockopt_types cfg_sockopt_types;
static void die_usage(void)
{
fprintf(stderr, "Usage: mptcp_connect [-6] [-c cmsg] [-f offset] [-i file] [-I num] [-j] [-l] "
- "[-m mode] [-M mark] [-o option] [-p port] [-P mode] [-j] [-l] [-r num] "
- "[-s MPTCP|TCP] [-S num] [-r num] [-t num] [-T num] [-u] [-w sec] connect_address\n");
+ "[-m mode] [-M mark] [-o option] [-p port] [-P mode] [-r num] [-R num] "
+ "[-s MPTCP|TCP] [-S num] [-t num] [-T num] [-w sec] connect_address\n");
fprintf(stderr, "\t-6 use ipv6\n");
fprintf(stderr, "\t-c cmsg -- test cmsg type <cmsg>\n");
fprintf(stderr, "\t-f offset -- stop the I/O after receiving and sending the specified amount "
@@ -118,13 +118,13 @@ static void die_usage(void)
fprintf(stderr, "\t-p num -- use port num\n");
fprintf(stderr,
"\t-P [saveWithPeek|saveAfterPeek] -- save data with/after MSG_PEEK form tcp socket\n");
- fprintf(stderr, "\t-t num -- set poll timeout to num\n");
- fprintf(stderr, "\t-T num -- set expected runtime to num ms\n");
fprintf(stderr, "\t-r num -- enable slow mode, limiting each write to num bytes "
"-- for remove addr tests\n");
fprintf(stderr, "\t-R num -- set SO_RCVBUF to num\n");
fprintf(stderr, "\t-s [MPTCP|TCP] -- use mptcp(default) or tcp sockets\n");
fprintf(stderr, "\t-S num -- set SO_SNDBUF to num\n");
+ fprintf(stderr, "\t-t num -- set poll timeout to num\n");
+ fprintf(stderr, "\t-T num -- set expected runtime to num ms\n");
fprintf(stderr, "\t-w num -- wait num sec before closing the socket\n");
exit(1);
}
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
index c923ce5ff6eb..36dc2bab7a13 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
@@ -144,6 +144,7 @@ cleanup()
}
mptcp_lib_check_mptcp
+mptcp_lib_check_kallsyms
ip -Version > /dev/null 2>&1
if [ $? -ne 0 ];then
@@ -696,6 +697,15 @@ run_test_transparent()
return 0
fi
+ # IP(V6)_TRANSPARENT has been added after TOS support which came with
+ # the required infrastructure in MPTCP sockopt code. To support TOS, the
+ # following function has been exported (T). Not great but better than
+ # checking for a specific kernel version.
+ if ! mptcp_lib_kallsyms_has "T __ip_sock_set_tos$"; then
+ echo "INFO: ${msg} not supported by the kernel: SKIP"
+ return
+ fi
+
ip netns exec "$listener_ns" nft -f /dev/stdin <<"EOF"
flush ruleset
table inet mangle {
@@ -772,6 +782,11 @@ run_tests_disconnect()
local old_cin=$cin
local old_sin=$sin
+ if ! mptcp_lib_kallsyms_has "mptcp_pm_data_reset$"; then
+ echo "INFO: Full disconnect not supported: SKIP"
+ return
+ fi
+
cat $cin $cin $cin > "$cin".disconnect
# force do_transfer to cope with the multiple tranmissions
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 6be19b103824..7b65003ee8cf 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -8,6 +8,10 @@
. "$(dirname "${0}")/mptcp_lib.sh"
+# ShellCheck incorrectly believes that most of the code here is unreachable
+# because it's invoked by variable name, see how the "tests" array is used
+#shellcheck disable=SC2317
+
ret=0
sin=""
sinfail=""
@@ -21,6 +25,8 @@ capout=""
ns1=""
ns2=""
ksft_skip=4
+iptables="iptables"
+ip6tables="ip6tables"
timeout_poll=30
timeout_test=$((timeout_poll * 2 + 1))
capture=0
@@ -73,7 +79,7 @@ init_partial()
ip netns add $netns || exit $ksft_skip
ip -net $netns link set lo up
ip netns exec $netns sysctl -q net.mptcp.enabled=1
- ip netns exec $netns sysctl -q net.mptcp.pm_type=0
+ ip netns exec $netns sysctl -q net.mptcp.pm_type=0 2>/dev/null || true
ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0
ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0
if [ $checksum -eq 1 ]; then
@@ -131,13 +137,18 @@ cleanup_partial()
check_tools()
{
mptcp_lib_check_mptcp
+ mptcp_lib_check_kallsyms
if ! ip -Version &> /dev/null; then
echo "SKIP: Could not run test without ip tool"
exit $ksft_skip
fi
- if ! iptables -V &> /dev/null; then
+ # Use the legacy version if available to support old kernel versions
+ if iptables-legacy -V &> /dev/null; then
+ iptables="iptables-legacy"
+ ip6tables="ip6tables-legacy"
+ elif ! iptables -V &> /dev/null; then
echo "SKIP: Could not run all tests without iptables tool"
exit $ksft_skip
fi
@@ -173,6 +184,32 @@ cleanup()
cleanup_partial
}
+# $1: msg
+print_title()
+{
+ printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${1}"
+}
+
+# [ $1: fail msg ]
+mark_as_skipped()
+{
+ local msg="${1:-"Feature not supported"}"
+
+ mptcp_lib_fail_if_expected_feature "${msg}"
+
+ print_title "[ skip ] ${msg}"
+ printf "\n"
+}
+
+# $@: condition
+continue_if()
+{
+ if ! "${@}"; then
+ mark_as_skipped
+ return 1
+ fi
+}
+
skip_test()
{
if [ "${#only_tests_ids[@]}" -eq 0 ] && [ "${#only_tests_names[@]}" -eq 0 ]; then
@@ -216,6 +253,19 @@ reset()
return 0
}
+# $1: test name ; $2: counter to check
+reset_check_counter()
+{
+ reset "${1}" || return 1
+
+ local counter="${2}"
+
+ if ! nstat -asz "${counter}" | grep -wq "${counter}"; then
+ mark_as_skipped "counter '${counter}' is not available"
+ return 1
+ fi
+}
+
# $1: test name
reset_with_cookies()
{
@@ -235,17 +285,21 @@ reset_with_add_addr_timeout()
reset "${1}" || return 1
- tables="iptables"
+ tables="${iptables}"
if [ $ip -eq 6 ]; then
- tables="ip6tables"
+ tables="${ip6tables}"
fi
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
- ip netns exec $ns2 $tables -A OUTPUT -p tcp \
- -m tcp --tcp-option 30 \
- -m bpf --bytecode \
- "$CBPF_MPTCP_SUBOPTION_ADD_ADDR" \
- -j DROP
+
+ if ! ip netns exec $ns2 $tables -A OUTPUT -p tcp \
+ -m tcp --tcp-option 30 \
+ -m bpf --bytecode \
+ "$CBPF_MPTCP_SUBOPTION_ADD_ADDR" \
+ -j DROP; then
+ mark_as_skipped "unable to set the 'add addr' rule"
+ return 1
+ fi
}
# $1: test name
@@ -289,22 +343,17 @@ reset_with_allow_join_id0()
# tc action pedit offset 162 out of bounds
#
# Netfilter is used to mark packets with enough data.
-reset_with_fail()
+setup_fail_rules()
{
- reset "${1}" || return 1
-
- ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=1
- ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=1
-
check_invert=1
validate_checksum=1
- local i="$2"
- local ip="${3:-4}"
+ local i="$1"
+ local ip="${2:-4}"
local tables
- tables="iptables"
+ tables="${iptables}"
if [ $ip -eq 6 ]; then
- tables="ip6tables"
+ tables="${ip6tables}"
fi
ip netns exec $ns2 $tables \
@@ -314,15 +363,51 @@ reset_with_fail()
-p tcp \
-m length --length 150:9999 \
-m statistic --mode nth --packet 1 --every 99999 \
- -j MARK --set-mark 42 || exit 1
+ -j MARK --set-mark 42 || return ${ksft_skip}
- tc -n $ns2 qdisc add dev ns2eth$i clsact || exit 1
+ tc -n $ns2 qdisc add dev ns2eth$i clsact || return ${ksft_skip}
tc -n $ns2 filter add dev ns2eth$i egress \
protocol ip prio 1000 \
handle 42 fw \
action pedit munge offset 148 u8 invert \
pipe csum tcp \
- index 100 || exit 1
+ index 100 || return ${ksft_skip}
+}
+
+reset_with_fail()
+{
+ reset_check_counter "${1}" "MPTcpExtInfiniteMapTx" || return 1
+ shift
+
+ ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=1
+ ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=1
+
+ local rc=0
+ setup_fail_rules "${@}" || rc=$?
+
+ if [ ${rc} -eq ${ksft_skip} ]; then
+ mark_as_skipped "unable to set the 'fail' rules"
+ return 1
+ fi
+}
+
+reset_with_tcp_filter()
+{
+ reset "${1}" || return 1
+ shift
+
+ local ns="${!1}"
+ local src="${2}"
+ local target="${3}"
+
+ if ! ip netns exec "${ns}" ${iptables} \
+ -A INPUT \
+ -s "${src}" \
+ -p tcp \
+ -j "${target}"; then
+ mark_as_skipped "unable to set the filter rules"
+ return 1
+ fi
}
fail_test()
@@ -357,8 +442,9 @@ check_transfer()
local line
if [ -n "$bytes" ]; then
+ local out_size
# when truncating we must check the size explicitly
- local out_size=$(wc -c $out | awk '{print $1}')
+ out_size=$(wc -c $out | awk '{print $1}')
if [ $out_size -ne $bytes ]; then
echo "[ FAIL ] $what output file has wrong size ($out_size, $bytes)"
fail_test
@@ -442,11 +528,25 @@ wait_local_port_listen()
done
}
-rm_addr_count()
+# $1: ns ; $2: counter
+get_counter()
{
- local ns=${1}
+ local ns="${1}"
+ local counter="${2}"
+ local count
+
+ count=$(ip netns exec ${ns} nstat -asz "${counter}" | awk 'NR==1 {next} {print $2}')
+ if [ -z "${count}" ]; then
+ mptcp_lib_fail_if_expected_feature "${counter} counter"
+ return 1
+ fi
- ip netns exec ${ns} nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'
+ echo "${count}"
+}
+
+rm_addr_count()
+{
+ get_counter "${1}" "MPTcpExtRmAddr"
}
# $1: ns, $2: old rm_addr counter in $ns
@@ -469,11 +569,11 @@ wait_mpj()
local ns="${1}"
local cnt old_cnt
- old_cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
+ old_cnt=$(get_counter ${ns} "MPTcpExtMPJoinAckRx")
local i
for i in $(seq 10); do
- cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
+ cnt=$(get_counter ${ns} "MPTcpExtMPJoinAckRx")
[ "$cnt" = "${old_cnt}" ] || break
sleep 0.1
done
@@ -487,6 +587,7 @@ kill_wait()
kill_tests_wait()
{
+ #shellcheck disable=SC2046
kill -SIGUSR1 $(ip netns pids $ns2) $(ip netns pids $ns1)
wait
}
@@ -666,15 +767,6 @@ pm_nl_check_endpoint()
fi
}
-filter_tcp_from()
-{
- local ns="${1}"
- local src="${2}"
- local target="${3}"
-
- ip netns exec "${ns}" iptables -A INPUT -s "${src}" -p tcp -j "${target}"
-}
-
do_transfer()
{
local listener_ns="$1"
@@ -854,11 +946,12 @@ do_transfer()
sp=$(grep "type:10" "$evts_ns1" |
sed -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q')
da=$(grep "type:10" "$evts_ns1" |
- sed -n 's/.*\(daddr6:\)\([0-9a-f:.]*\).*$/\2/p;q')
+ sed -n 's/.*\(daddr[46]:\)\([0-9a-f:.]*\).*$/\2/p;q')
+ echo "$da" | grep -q ":" && addr="::ffff:$addr"
dp=$(grep "type:10" "$evts_ns1" |
sed -n 's/.*\(dport:\)\([[:digit:]]*\).*$/\2/p;q')
ip netns exec ${listener_ns} ./pm_nl_ctl rem token $tk id $id
- ip netns exec ${listener_ns} ./pm_nl_ctl dsf lip "::ffff:$addr" \
+ ip netns exec ${listener_ns} ./pm_nl_ctl dsf lip "$addr" \
lport $sp rip $da rport $dp token $tk
fi
@@ -1152,12 +1245,13 @@ chk_csum_nr()
fi
printf "%-${nr_blank}s %s" " " "sum"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}')
- [ -z "$count" ] && count=0
+ count=$(get_counter ${ns1} "MPTcpExtDataCsumErr")
if [ "$count" != "$csum_ns1" ]; then
extra_msg="$extra_msg ns1=$count"
fi
- if { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } ||
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } ||
{ [ "$count" -lt $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 1 ]; }; then
echo "[fail] got $count data checksum error[s] expected $csum_ns1"
fail_test
@@ -1166,12 +1260,13 @@ chk_csum_nr()
echo -n "[ ok ]"
fi
echo -n " - csum "
- count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}')
- [ -z "$count" ] && count=0
+ count=$(get_counter ${ns2} "MPTcpExtDataCsumErr")
if [ "$count" != "$csum_ns2" ]; then
extra_msg="$extra_msg ns2=$count"
fi
- if { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } ||
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } ||
{ [ "$count" -lt $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 1 ]; }; then
echo "[fail] got $count data checksum error[s] expected $csum_ns2"
fail_test
@@ -1213,12 +1308,13 @@ chk_fail_nr()
fi
printf "%-${nr_blank}s %s" " " "ftx"
- count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPFailTx | awk '{print $2}')
- [ -z "$count" ] && count=0
+ count=$(get_counter ${ns_tx} "MPTcpExtMPFailTx")
if [ "$count" != "$fail_tx" ]; then
extra_msg="$extra_msg,tx=$count"
fi
- if { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } ||
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } ||
{ [ "$count" -gt "$fail_tx" ] && [ $allow_tx_lost -eq 1 ]; }; then
echo "[fail] got $count MP_FAIL[s] TX expected $fail_tx"
fail_test
@@ -1228,12 +1324,13 @@ chk_fail_nr()
fi
echo -n " - failrx"
- count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPFailRx | awk '{print $2}')
- [ -z "$count" ] && count=0
+ count=$(get_counter ${ns_rx} "MPTcpExtMPFailRx")
if [ "$count" != "$fail_rx" ]; then
extra_msg="$extra_msg,rx=$count"
fi
- if { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } ||
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } ||
{ [ "$count" -gt "$fail_rx" ] && [ $allow_rx_lost -eq 1 ]; }; then
echo "[fail] got $count MP_FAIL[s] RX expected $fail_rx"
fail_test
@@ -1265,10 +1362,11 @@ chk_fclose_nr()
fi
printf "%-${nr_blank}s %s" " " "ctx"
- count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPFastcloseTx | awk '{print $2}')
- [ -z "$count" ] && count=0
- [ "$count" != "$fclose_tx" ] && extra_msg="$extra_msg,tx=$count"
- if [ "$count" != "$fclose_tx" ]; then
+ count=$(get_counter ${ns_tx} "MPTcpExtMPFastcloseTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$fclose_tx" ]; then
+ extra_msg="$extra_msg,tx=$count"
echo "[fail] got $count MP_FASTCLOSE[s] TX expected $fclose_tx"
fail_test
dump_stats=1
@@ -1277,10 +1375,11 @@ chk_fclose_nr()
fi
echo -n " - fclzrx"
- count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPFastcloseRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- [ "$count" != "$fclose_rx" ] && extra_msg="$extra_msg,rx=$count"
- if [ "$count" != "$fclose_rx" ]; then
+ count=$(get_counter ${ns_rx} "MPTcpExtMPFastcloseRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$fclose_rx" ]; then
+ extra_msg="$extra_msg,rx=$count"
echo "[fail] got $count MP_FASTCLOSE[s] RX expected $fclose_rx"
fail_test
dump_stats=1
@@ -1311,9 +1410,10 @@ chk_rst_nr()
fi
printf "%-${nr_blank}s %s" " " "rtx"
- count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPRstTx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ $count -lt $rst_tx ]; then
+ count=$(get_counter ${ns_tx} "MPTcpExtMPRstTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ $count -lt $rst_tx ]; then
echo "[fail] got $count MP_RST[s] TX expected $rst_tx"
fail_test
dump_stats=1
@@ -1322,9 +1422,10 @@ chk_rst_nr()
fi
echo -n " - rstrx "
- count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPRstRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" -lt "$rst_rx" ]; then
+ count=$(get_counter ${ns_rx} "MPTcpExtMPRstRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" -lt "$rst_rx" ]; then
echo "[fail] got $count MP_RST[s] RX expected $rst_rx"
fail_test
dump_stats=1
@@ -1345,9 +1446,10 @@ chk_infi_nr()
local dump_stats
printf "%-${nr_blank}s %s" " " "itx"
- count=$(ip netns exec $ns2 nstat -as | grep InfiniteMapTx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$infi_tx" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtInfiniteMapTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$infi_tx" ]; then
echo "[fail] got $count infinite map[s] TX expected $infi_tx"
fail_test
dump_stats=1
@@ -1356,9 +1458,10 @@ chk_infi_nr()
fi
echo -n " - infirx"
- count=$(ip netns exec $ns1 nstat -as | grep InfiniteMapRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$infi_rx" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtInfiniteMapRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$infi_rx" ]; then
echo "[fail] got $count infinite map[s] RX expected $infi_rx"
fail_test
dump_stats=1
@@ -1390,9 +1493,10 @@ chk_join_nr()
fi
printf "%03u %-36s %s" "${TEST_COUNT}" "${title}" "syn"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinSynRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinSynRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn expected $syn_nr"
fail_test
dump_stats=1
@@ -1402,9 +1506,10 @@ chk_join_nr()
echo -n " - synack"
with_cookie=$(ip netns exec $ns2 sysctl -n net.ipv4.tcp_syncookies)
- count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinSynAckRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_ack_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtMPJoinSynAckRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_ack_nr" ]; then
# simult connections exceeding the limit with cookie enabled could go up to
# synack validation as the conn limit can be enforced reliably only after
# the subflow creation
@@ -1420,9 +1525,10 @@ chk_join_nr()
fi
echo -n " - ack"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinAckRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$ack_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinAckRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack expected $ack_nr"
fail_test
dump_stats=1
@@ -1454,12 +1560,12 @@ chk_stale_nr()
local recover_nr
printf "%-${nr_blank}s %-18s" " " "stale"
- stale_nr=$(ip netns exec $ns nstat -as | grep MPTcpExtSubflowStale | awk '{print $2}')
- [ -z "$stale_nr" ] && stale_nr=0
- recover_nr=$(ip netns exec $ns nstat -as | grep MPTcpExtSubflowRecover | awk '{print $2}')
- [ -z "$recover_nr" ] && recover_nr=0
- if [ $stale_nr -lt $stale_min ] ||
+ stale_nr=$(get_counter ${ns} "MPTcpExtSubflowStale")
+ recover_nr=$(get_counter ${ns} "MPTcpExtSubflowRecover")
+ if [ -z "$stale_nr" ] || [ -z "$recover_nr" ]; then
+ echo "[skip]"
+ elif [ $stale_nr -lt $stale_min ] ||
{ [ $stale_max -gt 0 ] && [ $stale_nr -gt $stale_max ]; } ||
[ $((stale_nr - recover_nr)) -ne $stale_delta ]; then
echo "[fail] got $stale_nr stale[s] $recover_nr recover[s], " \
@@ -1495,12 +1601,12 @@ chk_add_nr()
timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout)
printf "%-${nr_blank}s %s" " " "add"
- count=$(ip netns exec $ns2 nstat -as MPTcpExtAddAddr | grep MPTcpExtAddAddr | awk '{print $2}')
- [ -z "$count" ] && count=0
-
+ count=$(get_counter ${ns2} "MPTcpExtAddAddr")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
# if the test configured a short timeout tolerate greater then expected
# add addrs options, due to retransmissions
- if [ "$count" != "$add_nr" ] && { [ "$timeout" -gt 1 ] || [ "$count" -lt "$add_nr" ]; }; then
+ elif [ "$count" != "$add_nr" ] && { [ "$timeout" -gt 1 ] || [ "$count" -lt "$add_nr" ]; }; then
echo "[fail] got $count ADD_ADDR[s] expected $add_nr"
fail_test
dump_stats=1
@@ -1509,9 +1615,10 @@ chk_add_nr()
fi
echo -n " - echo "
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtEchoAdd | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$echo_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtEchoAdd")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$echo_nr" ]; then
echo "[fail] got $count ADD_ADDR echo[s] expected $echo_nr"
fail_test
dump_stats=1
@@ -1521,9 +1628,10 @@ chk_add_nr()
if [ $port_nr -gt 0 ]; then
echo -n " - pt "
- count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtPortAdd | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$port_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtPortAdd")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$port_nr" ]; then
echo "[fail] got $count ADD_ADDR[s] with a port-number expected $port_nr"
fail_test
dump_stats=1
@@ -1532,10 +1640,10 @@ chk_add_nr()
fi
printf "%-${nr_blank}s %s" " " "syn"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortSynRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinPortSynRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn with a different \
port-number expected $syn_nr"
fail_test
@@ -1545,10 +1653,10 @@ chk_add_nr()
fi
echo -n " - synack"
- count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinPortSynAckRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$syn_ack_nr" ]; then
+ count=$(get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$syn_ack_nr" ]; then
echo "[fail] got $count JOIN[s] synack with a different \
port-number expected $syn_ack_nr"
fail_test
@@ -1558,10 +1666,10 @@ chk_add_nr()
fi
echo -n " - ack"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortAckRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$ack_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPJoinPortAckRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack with a different \
port-number expected $ack_nr"
fail_test
@@ -1571,10 +1679,10 @@ chk_add_nr()
fi
printf "%-${nr_blank}s %s" " " "syn"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortSynRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$mis_syn_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMismatchPortSynRx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$mis_syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn with a mismatched \
port-number expected $mis_syn_nr"
fail_test
@@ -1584,10 +1692,10 @@ chk_add_nr()
fi
echo -n " - ack "
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortAckRx |
- awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$mis_ack_nr" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMismatchPortAckRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$mis_ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack with a mismatched \
port-number expected $mis_ack_nr"
fail_test
@@ -1631,9 +1739,10 @@ chk_rm_nr()
fi
printf "%-${nr_blank}s %s" " " "rm "
- count=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmAddr | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$rm_addr_nr" ]; then
+ count=$(get_counter ${addr_ns} "MPTcpExtRmAddr")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$rm_addr_nr" ]; then
echo "[fail] got $count RM_ADDR[s] expected $rm_addr_nr"
fail_test
dump_stats=1
@@ -1642,29 +1751,27 @@ chk_rm_nr()
fi
echo -n " - rmsf "
- count=$(ip netns exec $subflow_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ -n "$simult" ]; then
+ count=$(get_counter ${subflow_ns} "MPTcpExtRmSubflow")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ -n "$simult" ]; then
local cnt suffix
- cnt=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}')
+ cnt=$(get_counter ${addr_ns} "MPTcpExtRmSubflow")
# in case of simult flush, the subflow removal count on each side is
# unreliable
- [ -z "$cnt" ] && cnt=0
count=$((count + cnt))
[ "$count" != "$rm_subflow_nr" ] && suffix="$count in [$rm_subflow_nr:$((rm_subflow_nr*2))]"
if [ $count -ge "$rm_subflow_nr" ] && \
[ "$count" -le "$((rm_subflow_nr *2 ))" ]; then
- echo "[ ok ] $suffix"
+ echo -n "[ ok ] $suffix"
else
echo "[fail] got $count RM_SUBFLOW[s] expected in range [$rm_subflow_nr:$((rm_subflow_nr*2))]"
fail_test
dump_stats=1
fi
- return
- fi
- if [ "$count" != "$rm_subflow_nr" ]; then
+ elif [ "$count" != "$rm_subflow_nr" ]; then
echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr"
fail_test
dump_stats=1
@@ -1685,9 +1792,10 @@ chk_prio_nr()
local dump_stats
printf "%-${nr_blank}s %s" " " "ptx"
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$mp_prio_nr_tx" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPPrioTx")
+ if [ -z "$count" ]; then
+ echo -n "[skip]"
+ elif [ "$count" != "$mp_prio_nr_tx" ]; then
echo "[fail] got $count MP_PRIO[s] TX expected $mp_prio_nr_tx"
fail_test
dump_stats=1
@@ -1696,9 +1804,10 @@ chk_prio_nr()
fi
echo -n " - prx "
- count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}')
- [ -z "$count" ] && count=0
- if [ "$count" != "$mp_prio_nr_rx" ]; then
+ count=$(get_counter ${ns1} "MPTcpExtMPPrioRx")
+ if [ -z "$count" ]; then
+ echo "[skip]"
+ elif [ "$count" != "$mp_prio_nr_rx" ]; then
echo "[fail] got $count MP_PRIO[s] RX expected $mp_prio_nr_rx"
fail_test
dump_stats=1
@@ -1726,7 +1835,7 @@ chk_subflow_nr()
cnt1=$(ss -N $ns1 -tOni | grep -c token)
cnt2=$(ss -N $ns2 -tOni | grep -c token)
- if [ "$cnt1" != "$subflow_nr" -o "$cnt2" != "$subflow_nr" ]; then
+ if [ "$cnt1" != "$subflow_nr" ] || [ "$cnt2" != "$subflow_nr" ]; then
echo "[fail] got $cnt1:$cnt2 subflows expected $subflow_nr"
fail_test
dump_stats=1
@@ -1774,7 +1883,7 @@ wait_attempt_fail()
while [ $time -lt $timeout_ms ]; do
local cnt
- cnt=$(ip netns exec $ns nstat -as TcpAttemptFails | grep TcpAttemptFails | awk '{print $2}')
+ cnt=$(get_counter ${ns} "TcpAttemptFails")
[ "$cnt" = 1 ] && return 1
time=$((time + 100))
@@ -1867,23 +1976,23 @@ subflows_error_tests()
fi
# multiple subflows, with subflow creation error
- if reset "multi subflows, with failing subflow"; then
+ if reset_with_tcp_filter "multi subflows, with failing subflow" ns1 10.0.3.2 REJECT &&
+ continue_if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
- filter_tcp_from $ns1 10.0.3.2 REJECT
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
chk_join_nr 1 1 1
fi
# multiple subflows, with subflow timeout on MPJ
- if reset "multi subflows, with subflow timeout"; then
+ if reset_with_tcp_filter "multi subflows, with subflow timeout" ns1 10.0.3.2 DROP &&
+ continue_if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
- filter_tcp_from $ns1 10.0.3.2 DROP
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
chk_join_nr 1 1 1
fi
@@ -1891,11 +2000,11 @@ subflows_error_tests()
# multiple subflows, check that the endpoint corresponding to
# closed subflow (due to reset) is not reused if additional
# subflows are added later
- if reset "multi subflows, fair usage on close"; then
+ if reset_with_tcp_filter "multi subflows, fair usage on close" ns1 10.0.3.2 REJECT &&
+ continue_if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
- filter_tcp_from $ns1 10.0.3.2 REJECT
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow &
# mpj subflow will be in TW after the reset
@@ -1995,11 +2104,18 @@ signal_address_tests()
# the peer could possibly miss some addr notification, allow retransmission
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
- chk_join_nr 3 3 3
- # the server will not signal the address terminating
- # the MPC subflow
- chk_add_nr 3 3
+ # It is not directly linked to the commit introducing this
+ # symbol but for the parent one which is linked anyway.
+ if ! mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
+ chk_join_nr 3 3 2
+ chk_add_nr 4 4
+ else
+ chk_join_nr 3 3 3
+ # the server will not signal the address terminating
+ # the MPC subflow
+ chk_add_nr 3 3
+ fi
fi
}
@@ -2240,7 +2356,12 @@ remove_tests()
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
chk_join_nr 3 3 3
- chk_rm_nr 0 3 simult
+
+ if mptcp_lib_kversion_ge 5.18; then
+ chk_rm_nr 0 3 simult
+ else
+ chk_rm_nr 3 3
+ fi
fi
# addresses flush
@@ -2479,7 +2600,8 @@ v4mapped_tests()
backup_tests()
{
# single subflow, backup
- if reset "single subflow, backup"; then
+ if reset "single subflow, backup" &&
+ continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
@@ -2489,7 +2611,8 @@ backup_tests()
fi
# single address, backup
- if reset "single address, backup"; then
+ if reset "single address, backup" &&
+ continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 0 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_set_limits $ns2 1 1
@@ -2500,7 +2623,8 @@ backup_tests()
fi
# single address with port, backup
- if reset "single address with port, backup"; then
+ if reset "single address with port, backup" &&
+ continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 0 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
pm_nl_set_limits $ns2 1 1
@@ -2510,14 +2634,16 @@ backup_tests()
chk_prio_nr 1 1
fi
- if reset "mpc backup"; then
+ if reset "mpc backup" &&
+ continue_if mptcp_lib_kallsyms_doesnt_have "mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,backup
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
chk_join_nr 0 0 0
chk_prio_nr 0 1
fi
- if reset "mpc backup both sides"; then
+ if reset "mpc backup both sides" &&
+ continue_if mptcp_lib_kallsyms_doesnt_have "mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns1 10.0.1.1 flags subflow,backup
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,backup
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
@@ -2525,14 +2651,16 @@ backup_tests()
chk_prio_nr 1 1
fi
- if reset "mpc switch to backup"; then
+ if reset "mpc switch to backup" &&
+ continue_if mptcp_lib_kallsyms_doesnt_have "mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
chk_join_nr 0 0 0
chk_prio_nr 0 1
fi
- if reset "mpc switch to backup both sides"; then
+ if reset "mpc switch to backup both sides" &&
+ continue_if mptcp_lib_kallsyms_doesnt_have "mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns1 10.0.1.1 flags subflow
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
@@ -2839,7 +2967,8 @@ fullmesh_tests()
fi
# set fullmesh flag
- if reset "set fullmesh flag test"; then
+ if reset "set fullmesh flag test" &&
+ continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow
pm_nl_set_limits $ns2 4 4
@@ -2849,7 +2978,8 @@ fullmesh_tests()
fi
# set nofullmesh flag
- if reset "set nofullmesh flag test"; then
+ if reset "set nofullmesh flag test" &&
+ continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow,fullmesh
pm_nl_set_limits $ns2 4 4
@@ -2859,7 +2989,8 @@ fullmesh_tests()
fi
# set backup,fullmesh flags
- if reset "set backup,fullmesh flags test"; then
+ if reset "set backup,fullmesh flags test" &&
+ continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow
pm_nl_set_limits $ns2 4 4
@@ -2870,7 +3001,8 @@ fullmesh_tests()
fi
# set nobackup,nofullmesh flags
- if reset "set nobackup,nofullmesh flags test"; then
+ if reset "set nobackup,nofullmesh flags test" &&
+ continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_set_limits $ns2 4 4
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow,backup,fullmesh
@@ -2883,14 +3015,14 @@ fullmesh_tests()
fastclose_tests()
{
- if reset "fastclose test"; then
+ if reset_check_counter "fastclose test" "MPTcpExtMPFastcloseTx"; then
run_tests $ns1 $ns2 10.0.1.1 1024 0 fastclose_client
chk_join_nr 0 0 0
chk_fclose_nr 1 1
chk_rst_nr 1 1 invert
fi
- if reset "fastclose server test"; then
+ if reset_check_counter "fastclose server test" "MPTcpExtMPFastcloseRx"; then
run_tests $ns1 $ns2 10.0.1.1 1024 0 fastclose_server
chk_join_nr 0 0 0
chk_fclose_nr 1 1 invert
@@ -2928,7 +3060,8 @@ fail_tests()
userspace_tests()
{
# userspace pm type prevents add_addr
- if reset "userspace pm type prevents add_addr"; then
+ if reset "userspace pm type prevents add_addr" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
@@ -2939,7 +3072,8 @@ userspace_tests()
fi
# userspace pm type does not echo add_addr without daemon
- if reset "userspace pm no echo w/o daemon"; then
+ if reset "userspace pm no echo w/o daemon" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns2
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
@@ -2950,7 +3084,8 @@ userspace_tests()
fi
# userspace pm type rejects join
- if reset "userspace pm type rejects join"; then
+ if reset "userspace pm type rejects join" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
@@ -2960,7 +3095,8 @@ userspace_tests()
fi
# userspace pm type does not send join
- if reset "userspace pm type does not send join"; then
+ if reset "userspace pm type does not send join" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns2
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
@@ -2970,7 +3106,8 @@ userspace_tests()
fi
# userspace pm type prevents mp_prio
- if reset "userspace pm type prevents mp_prio"; then
+ if reset "userspace pm type prevents mp_prio" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
@@ -2981,7 +3118,8 @@ userspace_tests()
fi
# userspace pm type prevents rm_addr
- if reset "userspace pm type prevents rm_addr"; then
+ if reset "userspace pm type prevents rm_addr" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
set_userspace_pm $ns2
pm_nl_set_limits $ns1 0 1
@@ -2993,7 +3131,8 @@ userspace_tests()
fi
# userspace pm add & remove address
- if reset "userspace pm add & remove address"; then
+ if reset "userspace pm add & remove address" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns1
pm_nl_set_limits $ns2 1 1
run_tests $ns1 $ns2 10.0.1.1 0 userspace_1 0 slow
@@ -3003,7 +3142,8 @@ userspace_tests()
fi
# userspace pm create destroy subflow
- if reset "userspace pm create destroy subflow"; then
+ if reset "userspace pm create destroy subflow" &&
+ continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns2
pm_nl_set_limits $ns1 0 1
run_tests $ns1 $ns2 10.0.1.1 0 0 userspace_1 slow
@@ -3014,8 +3154,10 @@ userspace_tests()
endpoint_tests()
{
+ # subflow_rebuild_header is needed to support the implicit flag
# userspace pm type prevents add_addr
- if reset "implicit EP"; then
+ if reset "implicit EP" &&
+ mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 2 2
pm_nl_set_limits $ns2 2 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
@@ -3035,7 +3177,8 @@ endpoint_tests()
kill_tests_wait
fi
- if reset "delete and re-add"; then
+ if reset "delete and re-add" &&
+ mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
diff --git a/tools/testing/selftests/net/mptcp/mptcp_lib.sh b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
index 3286536b79d5..f32045b23b89 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_lib.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
@@ -38,3 +38,67 @@ mptcp_lib_check_mptcp() {
exit ${KSFT_SKIP}
fi
}
+
+mptcp_lib_check_kallsyms() {
+ if ! mptcp_lib_has_file "/proc/kallsyms"; then
+ echo "SKIP: CONFIG_KALLSYMS is missing"
+ exit ${KSFT_SKIP}
+ fi
+}
+
+# Internal: use mptcp_lib_kallsyms_has() instead
+__mptcp_lib_kallsyms_has() {
+ local sym="${1}"
+
+ mptcp_lib_check_kallsyms
+
+ grep -q " ${sym}" /proc/kallsyms
+}
+
+# $1: part of a symbol to look at, add '$' at the end for full name
+mptcp_lib_kallsyms_has() {
+ local sym="${1}"
+
+ if __mptcp_lib_kallsyms_has "${sym}"; then
+ return 0
+ fi
+
+ mptcp_lib_fail_if_expected_feature "${sym} symbol not found"
+}
+
+# $1: part of a symbol to look at, add '$' at the end for full name
+mptcp_lib_kallsyms_doesnt_have() {
+ local sym="${1}"
+
+ if ! __mptcp_lib_kallsyms_has "${sym}"; then
+ return 0
+ fi
+
+ mptcp_lib_fail_if_expected_feature "${sym} symbol has been found"
+}
+
+# !!!AVOID USING THIS!!!
+# Features might not land in the expected version and features can be backported
+#
+# $1: kernel version, e.g. 6.3
+mptcp_lib_kversion_ge() {
+ local exp_maj="${1%.*}"
+ local exp_min="${1#*.}"
+ local v maj min
+
+ # If the kernel has backported features, set this env var to 1:
+ if [ "${SELFTESTS_MPTCP_LIB_NO_KVERSION_CHECK:-}" = "1" ]; then
+ return 0
+ fi
+
+ v=$(uname -r | cut -d'.' -f1,2)
+ maj=${v%.*}
+ min=${v#*.}
+
+ if [ "${maj}" -gt "${exp_maj}" ] ||
+ { [ "${maj}" -eq "${exp_maj}" ] && [ "${min}" -ge "${exp_min}" ]; }; then
+ return 0
+ fi
+
+ mptcp_lib_fail_if_expected_feature "kernel version ${1} lower than ${v}"
+}
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index ae61f39556ca..b35148edbf02 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -87,6 +87,10 @@ struct so_state {
uint64_t tcpi_rcv_delta;
};
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
static void die_perror(const char *msg)
{
perror(msg);
@@ -349,13 +353,14 @@ static void do_getsockopt_tcp_info(struct so_state *s, int fd, size_t r, size_t
xerror("getsockopt MPTCP_TCPINFO (tries %d, %m)");
assert(olen <= sizeof(ti));
- assert(ti.d.size_user == ti.d.size_kernel);
- assert(ti.d.size_user == sizeof(struct tcp_info));
+ assert(ti.d.size_kernel > 0);
+ assert(ti.d.size_user ==
+ MIN(ti.d.size_kernel, sizeof(struct tcp_info)));
assert(ti.d.num_subflows == 1);
assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data));
olen -= sizeof(struct mptcp_subflow_data);
- assert(olen == sizeof(struct tcp_info));
+ assert(olen == ti.d.size_user);
if (ti.ti[0].tcpi_bytes_sent == w &&
ti.ti[0].tcpi_bytes_received == r)
@@ -401,13 +406,14 @@ static void do_getsockopt_subflow_addrs(int fd)
die_perror("getsockopt MPTCP_SUBFLOW_ADDRS");
assert(olen <= sizeof(addrs));
- assert(addrs.d.size_user == addrs.d.size_kernel);
- assert(addrs.d.size_user == sizeof(struct mptcp_subflow_addrs));
+ assert(addrs.d.size_kernel > 0);
+ assert(addrs.d.size_user ==
+ MIN(addrs.d.size_kernel, sizeof(struct mptcp_subflow_addrs)));
assert(addrs.d.num_subflows == 1);
assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data));
olen -= sizeof(struct mptcp_subflow_data);
- assert(olen == sizeof(struct mptcp_subflow_addrs));
+ assert(olen == addrs.d.size_user);
llen = sizeof(local);
ret = getsockname(fd, (struct sockaddr *)&local, &llen);
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
index 08d8533c98c4..a493eaf8633f 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
@@ -84,6 +84,7 @@ cleanup()
}
mptcp_lib_check_mptcp
+mptcp_lib_check_kallsyms
ip -Version > /dev/null 2>&1
if [ $? -ne 0 ];then
@@ -181,9 +182,14 @@ do_transfer()
local_addr="0.0.0.0"
fi
+ cmsg="TIMESTAMPNS"
+ if mptcp_lib_kallsyms_has "mptcp_ioctl$"; then
+ cmsg+=",TCPINQ"
+ fi
+
timeout ${timeout_test} \
ip netns exec ${listener_ns} \
- $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c TIMESTAMPNS,TCPINQ \
+ $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c "${cmsg}" \
${local_addr} < "$sin" > "$sout" &
spid=$!
@@ -191,7 +197,7 @@ do_transfer()
timeout ${timeout_test} \
ip netns exec ${connector_ns} \
- $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c TIMESTAMPNS,TCPINQ \
+ $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c "${cmsg}" \
$connect_addr < "$cin" > "$cout" &
cpid=$!
@@ -248,6 +254,11 @@ do_mptcp_sockopt_tests()
{
local lret=0
+ if ! mptcp_lib_kallsyms_has "mptcp_diag_fill_info$"; then
+ echo "INFO: MPTCP sockopt not supported: SKIP"
+ return
+ fi
+
ip netns exec "$ns_sbox" ./mptcp_sockopt
lret=$?
@@ -305,6 +316,11 @@ do_tcpinq_tests()
ip netns exec "$ns1" iptables -F
ip netns exec "$ns1" ip6tables -F
+ if ! mptcp_lib_kallsyms_has "mptcp_ioctl$"; then
+ echo "INFO: TCP_INQ not supported: SKIP"
+ return
+ fi
+
for args in "-t tcp" "-r tcp"; do
do_tcpinq_test $args
lret=$?
diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh
index 32f7533e0919..d02e0d63a8f9 100755
--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh
+++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh
@@ -73,8 +73,12 @@ check()
}
check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "defaults addr list"
-check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
+
+default_limits="$(ip netns exec $ns1 ./pm_nl_ctl limits)"
+if mptcp_lib_expect_all_features; then
+ check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
subflows 2" "defaults limits"
+fi
ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1
ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.2 flags subflow dev lo
@@ -121,12 +125,10 @@ ip netns exec $ns1 ./pm_nl_ctl flush
check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "flush addrs"
ip netns exec $ns1 ./pm_nl_ctl limits 9 1
-check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
-subflows 2" "rcv addrs above hard limit"
+check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "rcv addrs above hard limit"
ip netns exec $ns1 ./pm_nl_ctl limits 1 9
-check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 0
-subflows 2" "subflows above hard limit"
+check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "subflows above hard limit"
ip netns exec $ns1 ./pm_nl_ctl limits 8 8
check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 8
@@ -176,14 +178,19 @@ subflow,backup 10.0.1.1" "set flags (backup)"
ip netns exec $ns1 ./pm_nl_ctl set 10.0.1.1 flags nobackup
check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
subflow 10.0.1.1" " (nobackup)"
+
+# fullmesh support has been added later
ip netns exec $ns1 ./pm_nl_ctl set id 1 flags fullmesh
-check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+if ip netns exec $ns1 ./pm_nl_ctl dump | grep -q "fullmesh" ||
+ mptcp_lib_expect_all_features; then
+ check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
subflow,fullmesh 10.0.1.1" " (fullmesh)"
-ip netns exec $ns1 ./pm_nl_ctl set id 1 flags nofullmesh
-check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+ ip netns exec $ns1 ./pm_nl_ctl set id 1 flags nofullmesh
+ check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
subflow 10.0.1.1" " (nofullmesh)"
-ip netns exec $ns1 ./pm_nl_ctl set id 1 flags backup,fullmesh
-check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+ ip netns exec $ns1 ./pm_nl_ctl set id 1 flags backup,fullmesh
+ check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
subflow,backup,fullmesh 10.0.1.1" " (backup,fullmesh)"
+fi
exit $ret
diff --git a/tools/testing/selftests/net/mptcp/userspace_pm.sh b/tools/testing/selftests/net/mptcp/userspace_pm.sh
index 084a2b0a197e..eb0f4f6afebd 100755
--- a/tools/testing/selftests/net/mptcp/userspace_pm.sh
+++ b/tools/testing/selftests/net/mptcp/userspace_pm.sh
@@ -5,10 +5,15 @@
mptcp_lib_check_mptcp
+if ! mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
+ echo "userspace pm tests are not supported by the kernel: SKIP"
+ exit ${KSFT_SKIP}
+fi
+
ip -Version > /dev/null 2>&1
if [ $? -ne 0 ];then
echo "SKIP: Cannot not run test without ip tool"
- exit 1
+ exit ${KSFT_SKIP}
fi
ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index 2cbb12736596..c0ad8385441f 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -25,6 +25,8 @@
#define TLS_PAYLOAD_MAX_LEN 16384
#define SOL_TLS 282
+static int fips_enabled;
+
struct tls_crypto_info_keys {
union {
struct tls12_crypto_info_aes_gcm_128 aes128;
@@ -235,7 +237,7 @@ FIXTURE_VARIANT(tls)
{
uint16_t tls_version;
uint16_t cipher_type;
- bool nopad;
+ bool nopad, fips_non_compliant;
};
FIXTURE_VARIANT_ADD(tls, 12_aes_gcm)
@@ -254,24 +256,28 @@ FIXTURE_VARIANT_ADD(tls, 12_chacha)
{
.tls_version = TLS_1_2_VERSION,
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
+ .fips_non_compliant = true,
};
FIXTURE_VARIANT_ADD(tls, 13_chacha)
{
.tls_version = TLS_1_3_VERSION,
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
+ .fips_non_compliant = true,
};
FIXTURE_VARIANT_ADD(tls, 13_sm4_gcm)
{
.tls_version = TLS_1_3_VERSION,
.cipher_type = TLS_CIPHER_SM4_GCM,
+ .fips_non_compliant = true,
};
FIXTURE_VARIANT_ADD(tls, 13_sm4_ccm)
{
.tls_version = TLS_1_3_VERSION,
.cipher_type = TLS_CIPHER_SM4_CCM,
+ .fips_non_compliant = true,
};
FIXTURE_VARIANT_ADD(tls, 12_aes_ccm)
@@ -311,6 +317,9 @@ FIXTURE_SETUP(tls)
int one = 1;
int ret;
+ if (fips_enabled && variant->fips_non_compliant)
+ SKIP(return, "Unsupported cipher in FIPS mode");
+
tls_crypto_info_init(variant->tls_version, variant->cipher_type,
&tls12);
@@ -1820,4 +1829,17 @@ TEST(tls_v6ops) {
close(sfd);
}
+static void __attribute__((constructor)) fips_check(void) {
+ int res;
+ FILE *f;
+
+ f = fopen("/proc/sys/crypto/fips_enabled", "r");
+ if (f) {
+ res = fscanf(f, "%d", &fips_enabled);
+ if (res != 1)
+ ksft_print_msg("ERROR: Couldn't read /proc/sys/crypto/fips_enabled\n");
+ fclose(f);
+ }
+}
+
TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/net/vrf-xfrm-tests.sh b/tools/testing/selftests/net/vrf-xfrm-tests.sh
index 184da81f554f..452638ae8aed 100755
--- a/tools/testing/selftests/net/vrf-xfrm-tests.sh
+++ b/tools/testing/selftests/net/vrf-xfrm-tests.sh
@@ -264,60 +264,60 @@ setup_xfrm()
ip -netns host1 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
proto esp spi ${SPI_1} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
- enc 'cbc(des3_ede)' ${ENC_1} \
+ auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
+ enc 'cbc(aes)' ${ENC_1} \
sel src ${h1_4} dst ${h2_4} ${devarg}
ip -netns host2 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
proto esp spi ${SPI_1} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
- enc 'cbc(des3_ede)' ${ENC_1} \
+ auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
+ enc 'cbc(aes)' ${ENC_1} \
sel src ${h1_4} dst ${h2_4}
ip -netns host1 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
proto esp spi ${SPI_2} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
- enc 'cbc(des3_ede)' ${ENC_2} \
+ auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
+ enc 'cbc(aes)' ${ENC_2} \
sel src ${h2_4} dst ${h1_4} ${devarg}
ip -netns host2 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
proto esp spi ${SPI_2} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
- enc 'cbc(des3_ede)' ${ENC_2} \
+ auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
+ enc 'cbc(aes)' ${ENC_2} \
sel src ${h2_4} dst ${h1_4}
ip -6 -netns host1 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
proto esp spi ${SPI_1} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
- enc 'cbc(des3_ede)' ${ENC_1} \
+ auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
+ enc 'cbc(aes)' ${ENC_1} \
sel src ${h1_6} dst ${h2_6} ${devarg}
ip -6 -netns host2 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
proto esp spi ${SPI_1} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
- enc 'cbc(des3_ede)' ${ENC_1} \
+ auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
+ enc 'cbc(aes)' ${ENC_1} \
sel src ${h1_6} dst ${h2_6}
ip -6 -netns host1 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
proto esp spi ${SPI_2} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
- enc 'cbc(des3_ede)' ${ENC_2} \
+ auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
+ enc 'cbc(aes)' ${ENC_2} \
sel src ${h2_6} dst ${h1_6} ${devarg}
ip -6 -netns host2 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
proto esp spi ${SPI_2} reqid 0 mode tunnel \
replay-window 4 replay-oseq 0x4 \
- auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
- enc 'cbc(des3_ede)' ${ENC_2} \
+ auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
+ enc 'cbc(aes)' ${ENC_2} \
sel src ${h2_6} dst ${h1_6}
}
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index de8e5eb6af10..640113f047ef 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -691,6 +691,24 @@ static __always_inline int kvm_handle_hva_range_no_flush(struct mmu_notifier *mn
return __kvm_handle_hva_range(kvm, &range);
}
+
+static bool kvm_change_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ /*
+ * Skipping invalid memslots is correct if and only change_pte() is
+ * surrounded by invalidate_range_{start,end}(), which is currently
+ * guaranteed by the primary MMU. If that ever changes, KVM needs to
+ * unmap the memslot instead of skipping the memslot to ensure that KVM
+ * doesn't hold references to the old PFN.
+ */
+ WARN_ON_ONCE(!READ_ONCE(kvm->mn_active_invalidate_count));
+
+ if (range->slot->flags & KVM_MEMSLOT_INVALID)
+ return false;
+
+ return kvm_set_spte_gfn(kvm, range);
+}
+
static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long address,
@@ -712,7 +730,7 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
if (!READ_ONCE(kvm->mmu_invalidate_in_progress))
return;
- kvm_handle_hva_range(mn, address, address + 1, pte, kvm_set_spte_gfn);
+ kvm_handle_hva_range(mn, address, address + 1, pte, kvm_change_spte_gfn);
}
void kvm_mmu_invalidate_begin(struct kvm *kvm, unsigned long start,
^ permalink raw reply related [relevance 1%]
* [PATCH 5.15 82/96] nvme: double KA polling frequency to avoid KATO with TBKAS on
@ 2023-06-26 18:12 6% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-06-26 18:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Costa Sapuntzakis, Randy Jennings,
Uday Shankar, Hannes Reinecke, Sagi Grimberg, Christoph Hellwig,
Keith Busch, Sasha Levin
From: Uday Shankar <ushankar@purestorage.com>
[ Upstream commit ea4d453b9ec9ea279c39744cd0ecb47ef48ede35 ]
With TBKAS on, the completion of one command can defer sending a
keep alive for up to twice the delay between successive runs of
nvme_keep_alive_work. The current delay of KATO / 2 thus makes it
possible for one command to defer sending a keep alive for up to
KATO, which can result in the controller detecting a KATO. The following
trace demonstrates the issue, taking KATO = 8 for simplicity:
1. t = 0: run nvme_keep_alive_work, no keep-alive sent
2. t = ε: I/O completion seen, set comp_seen = true
3. t = 4: run nvme_keep_alive_work, see comp_seen == true,
skip sending keep-alive, set comp_seen = false
4. t = 8: run nvme_keep_alive_work, see comp_seen == false,
send a keep-alive command.
Here, there is a delay of 8 - ε between receiving a command completion
and sending the next command. With ε small, the controller is likely to
detect a keep alive timeout.
Fix this by running nvme_keep_alive_work with a delay of KATO / 4
whenever TBKAS is on. Going through the above trace now gives us a
worst-case delay of 4 - ε, which is in line with the recommendation of
sending a command every KATO / 2 in the NVMe specification.
Reported-by: Costa Sapuntzakis <costa@purestorage.com>
Reported-by: Randy Jennings <randyj@purestorage.com>
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/nvme/host/core.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index e5318b38c6624..98a7649a0f061 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1247,9 +1247,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU);
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+ unsigned long delay = ctrl->kato * HZ / 2;
+
+ /*
+ * When using Traffic Based Keep Alive, we need to run
+ * nvme_keep_alive_work at twice the normal frequency, as one
+ * command completion can postpone sending a keep alive command
+ * by up to twice the delay between runs.
+ */
+ if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+ delay /= 2;
+ return delay;
+}
+
static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
{
- queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work,
+ nvme_keep_alive_work_period(ctrl));
}
static void nvme_keep_alive_end_io(struct request *rq, blk_status_t status)
--
2.39.2
^ permalink raw reply related [relevance 6%]
* [PATCH 6.1 141/170] nvme: double KA polling frequency to avoid KATO with TBKAS on
@ 2023-06-26 18:11 6% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-06-26 18:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Costa Sapuntzakis, Randy Jennings,
Uday Shankar, Hannes Reinecke, Sagi Grimberg, Christoph Hellwig,
Keith Busch, Sasha Levin
From: Uday Shankar <ushankar@purestorage.com>
[ Upstream commit ea4d453b9ec9ea279c39744cd0ecb47ef48ede35 ]
With TBKAS on, the completion of one command can defer sending a
keep alive for up to twice the delay between successive runs of
nvme_keep_alive_work. The current delay of KATO / 2 thus makes it
possible for one command to defer sending a keep alive for up to
KATO, which can result in the controller detecting a KATO. The following
trace demonstrates the issue, taking KATO = 8 for simplicity:
1. t = 0: run nvme_keep_alive_work, no keep-alive sent
2. t = ε: I/O completion seen, set comp_seen = true
3. t = 4: run nvme_keep_alive_work, see comp_seen == true,
skip sending keep-alive, set comp_seen = false
4. t = 8: run nvme_keep_alive_work, see comp_seen == false,
send a keep-alive command.
Here, there is a delay of 8 - ε between receiving a command completion
and sending the next command. With ε small, the controller is likely to
detect a keep alive timeout.
Fix this by running nvme_keep_alive_work with a delay of KATO / 4
whenever TBKAS is on. Going through the above trace now gives us a
worst-case delay of 4 - ε, which is in line with the recommendation of
sending a command every KATO / 2 in the NVMe specification.
Reported-by: Costa Sapuntzakis <costa@purestorage.com>
Reported-by: Randy Jennings <randyj@purestorage.com>
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/nvme/host/core.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 2e22c78991ccf..a97f2f21c5321 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1198,9 +1198,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU);
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+ unsigned long delay = ctrl->kato * HZ / 2;
+
+ /*
+ * When using Traffic Based Keep Alive, we need to run
+ * nvme_keep_alive_work at twice the normal frequency, as one
+ * command completion can postpone sending a keep alive command
+ * by up to twice the delay between runs.
+ */
+ if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+ delay /= 2;
+ return delay;
+}
+
static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
{
- queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work,
+ nvme_keep_alive_work_period(ctrl));
}
static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
--
2.39.2
^ permalink raw reply related [relevance 6%]
* [PATCH 6.3 162/199] nvme: double KA polling frequency to avoid KATO with TBKAS on
@ 2023-06-26 18:11 6% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-06-26 18:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Costa Sapuntzakis, Randy Jennings,
Uday Shankar, Hannes Reinecke, Sagi Grimberg, Christoph Hellwig,
Keith Busch, Sasha Levin
From: Uday Shankar <ushankar@purestorage.com>
[ Upstream commit ea4d453b9ec9ea279c39744cd0ecb47ef48ede35 ]
With TBKAS on, the completion of one command can defer sending a
keep alive for up to twice the delay between successive runs of
nvme_keep_alive_work. The current delay of KATO / 2 thus makes it
possible for one command to defer sending a keep alive for up to
KATO, which can result in the controller detecting a KATO. The following
trace demonstrates the issue, taking KATO = 8 for simplicity:
1. t = 0: run nvme_keep_alive_work, no keep-alive sent
2. t = ε: I/O completion seen, set comp_seen = true
3. t = 4: run nvme_keep_alive_work, see comp_seen == true,
skip sending keep-alive, set comp_seen = false
4. t = 8: run nvme_keep_alive_work, see comp_seen == false,
send a keep-alive command.
Here, there is a delay of 8 - ε between receiving a command completion
and sending the next command. With ε small, the controller is likely to
detect a keep alive timeout.
Fix this by running nvme_keep_alive_work with a delay of KATO / 4
whenever TBKAS is on. Going through the above trace now gives us a
worst-case delay of 4 - ε, which is in line with the recommendation of
sending a command every KATO / 2 in the NVMe specification.
Reported-by: Costa Sapuntzakis <costa@purestorage.com>
Reported-by: Randy Jennings <randyj@purestorage.com>
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/nvme/host/core.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index f12109230dc8d..3838a6622c34b 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1163,9 +1163,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_passthru_end, NVME_TARGET_PASSTHRU);
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+ unsigned long delay = ctrl->kato * HZ / 2;
+
+ /*
+ * When using Traffic Based Keep Alive, we need to run
+ * nvme_keep_alive_work at twice the normal frequency, as one
+ * command completion can postpone sending a keep alive command
+ * by up to twice the delay between runs.
+ */
+ if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+ delay /= 2;
+ return delay;
+}
+
static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
{
- queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work,
+ nvme_keep_alive_work_period(ctrl));
}
static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
--
2.39.2
^ permalink raw reply related [relevance 6%]
* [PATCH AUTOSEL 5.15 09/10] nvme: double KA polling frequency to avoid KATO with TBKAS on
@ 2023-06-15 11:38 6% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2023-06-15 11:38 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Uday Shankar, Costa Sapuntzakis, Randy Jennings, Hannes Reinecke,
Sagi Grimberg, Christoph Hellwig, Keith Busch, Sasha Levin,
linux-nvme
From: Uday Shankar <ushankar@purestorage.com>
[ Upstream commit ea4d453b9ec9ea279c39744cd0ecb47ef48ede35 ]
With TBKAS on, the completion of one command can defer sending a
keep alive for up to twice the delay between successive runs of
nvme_keep_alive_work. The current delay of KATO / 2 thus makes it
possible for one command to defer sending a keep alive for up to
KATO, which can result in the controller detecting a KATO. The following
trace demonstrates the issue, taking KATO = 8 for simplicity:
1. t = 0: run nvme_keep_alive_work, no keep-alive sent
2. t = ε: I/O completion seen, set comp_seen = true
3. t = 4: run nvme_keep_alive_work, see comp_seen == true,
skip sending keep-alive, set comp_seen = false
4. t = 8: run nvme_keep_alive_work, see comp_seen == false,
send a keep-alive command.
Here, there is a delay of 8 - ε between receiving a command completion
and sending the next command. With ε small, the controller is likely to
detect a keep alive timeout.
Fix this by running nvme_keep_alive_work with a delay of KATO / 4
whenever TBKAS is on. Going through the above trace now gives us a
worst-case delay of 4 - ε, which is in line with the recommendation of
sending a command every KATO / 2 in the NVMe specification.
Reported-by: Costa Sapuntzakis <costa@purestorage.com>
Reported-by: Randy Jennings <randyj@purestorage.com>
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/nvme/host/core.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index e5318b38c6624..98a7649a0f061 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1247,9 +1247,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU);
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+ unsigned long delay = ctrl->kato * HZ / 2;
+
+ /*
+ * When using Traffic Based Keep Alive, we need to run
+ * nvme_keep_alive_work at twice the normal frequency, as one
+ * command completion can postpone sending a keep alive command
+ * by up to twice the delay between runs.
+ */
+ if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+ delay /= 2;
+ return delay;
+}
+
static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
{
- queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work,
+ nvme_keep_alive_work_period(ctrl));
}
static void nvme_keep_alive_end_io(struct request *rq, blk_status_t status)
--
2.39.2
^ permalink raw reply related [relevance 6%]
* [PATCH AUTOSEL 6.1 13/16] nvme: double KA polling frequency to avoid KATO with TBKAS on
@ 2023-06-15 11:38 6% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2023-06-15 11:38 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Uday Shankar, Costa Sapuntzakis, Randy Jennings, Hannes Reinecke,
Sagi Grimberg, Christoph Hellwig, Keith Busch, Sasha Levin,
linux-nvme
From: Uday Shankar <ushankar@purestorage.com>
[ Upstream commit ea4d453b9ec9ea279c39744cd0ecb47ef48ede35 ]
With TBKAS on, the completion of one command can defer sending a
keep alive for up to twice the delay between successive runs of
nvme_keep_alive_work. The current delay of KATO / 2 thus makes it
possible for one command to defer sending a keep alive for up to
KATO, which can result in the controller detecting a KATO. The following
trace demonstrates the issue, taking KATO = 8 for simplicity:
1. t = 0: run nvme_keep_alive_work, no keep-alive sent
2. t = ε: I/O completion seen, set comp_seen = true
3. t = 4: run nvme_keep_alive_work, see comp_seen == true,
skip sending keep-alive, set comp_seen = false
4. t = 8: run nvme_keep_alive_work, see comp_seen == false,
send a keep-alive command.
Here, there is a delay of 8 - ε between receiving a command completion
and sending the next command. With ε small, the controller is likely to
detect a keep alive timeout.
Fix this by running nvme_keep_alive_work with a delay of KATO / 4
whenever TBKAS is on. Going through the above trace now gives us a
worst-case delay of 4 - ε, which is in line with the recommendation of
sending a command every KATO / 2 in the NVMe specification.
Reported-by: Costa Sapuntzakis <costa@purestorage.com>
Reported-by: Randy Jennings <randyj@purestorage.com>
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/nvme/host/core.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index f502e032e7e46..50a83306bea7b 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1198,9 +1198,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU);
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+ unsigned long delay = ctrl->kato * HZ / 2;
+
+ /*
+ * When using Traffic Based Keep Alive, we need to run
+ * nvme_keep_alive_work at twice the normal frequency, as one
+ * command completion can postpone sending a keep alive command
+ * by up to twice the delay between runs.
+ */
+ if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+ delay /= 2;
+ return delay;
+}
+
static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
{
- queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work,
+ nvme_keep_alive_work_period(ctrl));
}
static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
--
2.39.2
^ permalink raw reply related [relevance 6%]
* [PATCH AUTOSEL 6.3 16/19] nvme: double KA polling frequency to avoid KATO with TBKAS on
@ 2023-06-15 11:37 6% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2023-06-15 11:37 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Uday Shankar, Costa Sapuntzakis, Randy Jennings, Hannes Reinecke,
Sagi Grimberg, Christoph Hellwig, Keith Busch, Sasha Levin,
linux-nvme
From: Uday Shankar <ushankar@purestorage.com>
[ Upstream commit ea4d453b9ec9ea279c39744cd0ecb47ef48ede35 ]
With TBKAS on, the completion of one command can defer sending a
keep alive for up to twice the delay between successive runs of
nvme_keep_alive_work. The current delay of KATO / 2 thus makes it
possible for one command to defer sending a keep alive for up to
KATO, which can result in the controller detecting a KATO. The following
trace demonstrates the issue, taking KATO = 8 for simplicity:
1. t = 0: run nvme_keep_alive_work, no keep-alive sent
2. t = ε: I/O completion seen, set comp_seen = true
3. t = 4: run nvme_keep_alive_work, see comp_seen == true,
skip sending keep-alive, set comp_seen = false
4. t = 8: run nvme_keep_alive_work, see comp_seen == false,
send a keep-alive command.
Here, there is a delay of 8 - ε between receiving a command completion
and sending the next command. With ε small, the controller is likely to
detect a keep alive timeout.
Fix this by running nvme_keep_alive_work with a delay of KATO / 4
whenever TBKAS is on. Going through the above trace now gives us a
worst-case delay of 4 - ε, which is in line with the recommendation of
sending a command every KATO / 2 in the NVMe specification.
Reported-by: Costa Sapuntzakis <costa@purestorage.com>
Reported-by: Randy Jennings <randyj@purestorage.com>
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/nvme/host/core.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index dba10d182c6b6..28b6fd52f88cb 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1163,9 +1163,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_passthru_end, NVME_TARGET_PASSTHRU);
* The host should send Keep Alive commands at half of the Keep Alive Timeout
* accounting for transport roundtrip times [..].
*/
+static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl)
+{
+ unsigned long delay = ctrl->kato * HZ / 2;
+
+ /*
+ * When using Traffic Based Keep Alive, we need to run
+ * nvme_keep_alive_work at twice the normal frequency, as one
+ * command completion can postpone sending a keep alive command
+ * by up to twice the delay between runs.
+ */
+ if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS)
+ delay /= 2;
+ return delay;
+}
+
static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
{
- queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2);
+ queue_delayed_work(nvme_wq, &ctrl->ka_work,
+ nvme_keep_alive_work_period(ctrl));
}
static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
--
2.39.2
^ permalink raw reply related [relevance 6%]
* [PATCH 6.1 056/225] mptcp: simplify subflow_syn_recv_sock()
@ 2023-06-07 20:14 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-06-07 20:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paolo Abeni, Matthieu Baerts,
David S. Miller, Sasha Levin
From: Paolo Abeni <pabeni@redhat.com>
[ Upstream commit a88d0092b24b8cddce57fe0e88e60a9e29e0b515 ]
Postpone the msk cloning to the child process creation
so that we can avoid a bunch of conditionals.
Link: https://github.com/multipath-tcp/mptcp_net-next/issues/61
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 7e8b88ec35ee ("mptcp: consolidate passive msk socket initialization")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/mptcp/subflow.c | 41 +++++++++++++----------------------------
1 file changed, 13 insertions(+), 28 deletions(-)
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 4995a6281ea16..276e62003631e 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -633,14 +633,6 @@ static bool subflow_hmac_valid(const struct request_sock *req,
return !crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN);
}
-static void mptcp_force_close(struct sock *sk)
-{
- /* the msk is not yet exposed to user-space, and refcount is 2 */
- inet_sk_state_store(sk, TCP_CLOSE);
- sk_common_release(sk);
- sock_put(sk);
-}
-
static void subflow_ulp_fallback(struct sock *sk,
struct mptcp_subflow_context *old_ctx)
{
@@ -693,7 +685,6 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
struct mptcp_subflow_request_sock *subflow_req;
struct mptcp_options_received mp_opt;
bool fallback, fallback_is_fatal;
- struct sock *new_msk = NULL;
struct mptcp_sock *owner;
struct sock *child;
@@ -722,14 +713,9 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
* options.
*/
mptcp_get_options(skb, &mp_opt);
- if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC)) {
+ if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC))
fallback = true;
- goto create_child;
- }
- new_msk = mptcp_sk_clone(listener->conn, &mp_opt, req);
- if (!new_msk)
- fallback = true;
} else if (subflow_req->mp_join) {
mptcp_get_options(skb, &mp_opt);
if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ) ||
@@ -758,21 +744,23 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);
goto dispose_child;
}
-
- mptcp_subflow_drop_ctx(child);
- goto out;
+ goto fallback;
}
/* ssk inherits options of listener sk */
ctx->setsockopt_seq = listener->setsockopt_seq;
if (ctx->mp_capable) {
- owner = mptcp_sk(new_msk);
+ ctx->conn = mptcp_sk_clone(listener->conn, &mp_opt, req);
+ if (!ctx->conn)
+ goto fallback;
+
+ owner = mptcp_sk(ctx->conn);
/* this can't race with mptcp_close(), as the msk is
* not yet exposted to user-space
*/
- inet_sk_state_store((void *)new_msk, TCP_ESTABLISHED);
+ inet_sk_state_store(ctx->conn, TCP_ESTABLISHED);
/* record the newly created socket as the first msk
* subflow, but don't link it yet into conn_list
@@ -782,11 +770,9 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
/* new mpc subflow takes ownership of the newly
* created mptcp socket
*/
- mptcp_sk(new_msk)->setsockopt_seq = ctx->setsockopt_seq;
+ owner->setsockopt_seq = ctx->setsockopt_seq;
mptcp_pm_new_connection(owner, child, 1);
mptcp_token_accept(subflow_req, owner);
- ctx->conn = new_msk;
- new_msk = NULL;
/* set msk addresses early to ensure mptcp_pm_get_local_id()
* uses the correct data
@@ -836,11 +822,6 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
}
}
-out:
- /* dispose of the left over mptcp master, if any */
- if (unlikely(new_msk))
- mptcp_force_close(new_msk);
-
/* check for expected invariant - should never trigger, just help
* catching eariler subtle bugs
*/
@@ -858,6 +839,10 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
/* The last child reference will be released by the caller */
return child;
+
+fallback:
+ mptcp_subflow_drop_ctx(child);
+ return child;
}
static struct inet_connection_sock_af_ops subflow_specific __ro_after_init;
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 6.3 081/286] mptcp: simplify subflow_syn_recv_sock()
@ 2023-06-07 20:13 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-06-07 20:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paolo Abeni, Matthieu Baerts,
David S. Miller, Sasha Levin
From: Paolo Abeni <pabeni@redhat.com>
[ Upstream commit a88d0092b24b8cddce57fe0e88e60a9e29e0b515 ]
Postpone the msk cloning to the child process creation
so that we can avoid a bunch of conditionals.
Link: https://github.com/multipath-tcp/mptcp_net-next/issues/61
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 7e8b88ec35ee ("mptcp: consolidate passive msk socket initialization")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/mptcp/subflow.c | 41 +++++++++++++----------------------------
1 file changed, 13 insertions(+), 28 deletions(-)
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 8a6bd2782dc97..3b8abd79bfbd5 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -695,14 +695,6 @@ static bool subflow_hmac_valid(const struct request_sock *req,
return !crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN);
}
-static void mptcp_force_close(struct sock *sk)
-{
- /* the msk is not yet exposed to user-space, and refcount is 2 */
- inet_sk_state_store(sk, TCP_CLOSE);
- sk_common_release(sk);
- sock_put(sk);
-}
-
static void subflow_ulp_fallback(struct sock *sk,
struct mptcp_subflow_context *old_ctx)
{
@@ -757,7 +749,6 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
struct mptcp_subflow_request_sock *subflow_req;
struct mptcp_options_received mp_opt;
bool fallback, fallback_is_fatal;
- struct sock *new_msk = NULL;
struct mptcp_sock *owner;
struct sock *child;
@@ -786,14 +777,9 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
* options.
*/
mptcp_get_options(skb, &mp_opt);
- if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC)) {
+ if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC))
fallback = true;
- goto create_child;
- }
- new_msk = mptcp_sk_clone(listener->conn, &mp_opt, req);
- if (!new_msk)
- fallback = true;
} else if (subflow_req->mp_join) {
mptcp_get_options(skb, &mp_opt);
if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ) ||
@@ -822,21 +808,23 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);
goto dispose_child;
}
-
- mptcp_subflow_drop_ctx(child);
- goto out;
+ goto fallback;
}
/* ssk inherits options of listener sk */
ctx->setsockopt_seq = listener->setsockopt_seq;
if (ctx->mp_capable) {
- owner = mptcp_sk(new_msk);
+ ctx->conn = mptcp_sk_clone(listener->conn, &mp_opt, req);
+ if (!ctx->conn)
+ goto fallback;
+
+ owner = mptcp_sk(ctx->conn);
/* this can't race with mptcp_close(), as the msk is
* not yet exposted to user-space
*/
- inet_sk_state_store((void *)new_msk, TCP_ESTABLISHED);
+ inet_sk_state_store(ctx->conn, TCP_ESTABLISHED);
/* record the newly created socket as the first msk
* subflow, but don't link it yet into conn_list
@@ -846,11 +834,9 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
/* new mpc subflow takes ownership of the newly
* created mptcp socket
*/
- mptcp_sk(new_msk)->setsockopt_seq = ctx->setsockopt_seq;
+ owner->setsockopt_seq = ctx->setsockopt_seq;
mptcp_pm_new_connection(owner, child, 1);
mptcp_token_accept(subflow_req, owner);
- ctx->conn = new_msk;
- new_msk = NULL;
/* set msk addresses early to ensure mptcp_pm_get_local_id()
* uses the correct data
@@ -900,11 +886,6 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
}
}
-out:
- /* dispose of the left over mptcp master, if any */
- if (unlikely(new_msk))
- mptcp_force_close(new_msk);
-
/* check for expected invariant - should never trigger, just help
* catching eariler subtle bugs
*/
@@ -922,6 +903,10 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
/* The last child reference will be released by the caller */
return child;
+
+fallback:
+ mptcp_subflow_drop_ctx(child);
+ return child;
}
static struct inet_connection_sock_af_ops subflow_specific __ro_after_init;
--
2.39.2
^ permalink raw reply related [relevance 5%]
* Re: amd_sfh driver causes kernel oops during boot
@ 2023-06-05 11:24 5% ` Malte Starostik
0 siblings, 0 replies; 200+ results
From: Malte Starostik @ 2023-06-05 11:24 UTC (permalink / raw)
To: bagasdotme; +Cc: basavaraj.natikar, linux-input, linux, regressions, stable
Hello,
chiming in here as I'm experiencing what looks like the exact same issue, also
on a Lenovo Z13 notebook, also on Arch:
Oops during startup in task udev-worker followed by udev-worker blocking all
attempts to suspend or cleanly shutdown/reboot the machine - in fact I first
noticed because the machine surprised with repeatedly running out of battery
after it had supposedly been in standby but couldn't. Only then I noticed the
error on boot.
bisect result:
904e28c6de083fa4834cdbd0026470ddc30676fc is the first bad commit
commit 904e28c6de083fa4834cdbd0026470ddc30676fc
Merge: a738688177dc 2f7f4efb9411
Author: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Wed Feb 22 10:44:31 2023 +0100
Merge branch 'for-6.3/hid-bpf' into for-linus
Initial support of HID-BPF (Benjamin Tissoires)
The history is a little long for this series, as it was intended to be
sent for v6.2. However some last minute issues forced us to postpone it
to v6.3.
Conflicts:
* drivers/hid/i2c-hid/Kconfig:
commit bf7660dab30d ("HID: stop drivers from selecting CONFIG_HID")
conflicts with commit 2afac81dd165 ("HID: fix I2C_HID not selected
when I2C_HID_OF_ELAN is")
the resolution is simple enough: just drop the "default" and "select"
lines as the new commit from Arnd is doing
BR Malte
> On Wed, May 24, 2023 at 02:10:31PM +0800, Haochen Tong wrote:
> > > What last kernel version before this regression occurs? Do you mean
> > > v6.2?
> > >
> >
> > I was using 6.2.12 (Arch Linux distro kernel) before seeing this
regression.
>
> Can you perform bisection to find the culprit that introduces the
> regression? Since you're on Arch Linux, see its wiki article [1] for
> instructions.
>
> Thanks.
>
> [1]: https://wiki.archlinux.org/title/Bisecting_bugs_with_Git
^ permalink raw reply [relevance 5%]
* Linux 6.3.4
@ 2023-05-24 17:20 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-05-24 17:20 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 6.3.4 kernel.
All users of the 6.3 kernel series must upgrade.
The updated 6.3.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-6.3.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/arm64/silicon-errata.rst | 2
Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml | 2
Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml | 12
Makefile | 2
arch/arm/include/asm/assembler.h | 13
arch/arm/mach-sa1100/jornada720_ssp.c | 5
arch/arm/vfp/entry.S | 16
arch/arm/vfp/vfphw.S | 16
arch/arm/vfp/vfpmodule.c | 27
arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 1
arch/arm64/boot/dts/qcom/msm8996.dtsi | 3
arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts | 2
arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts | 11
arch/arm64/include/asm/kvm_pgtable.h | 1
arch/arm64/kernel/mte.c | 7
arch/arm64/kvm/hyp/pgtable.c | 32
arch/arm64/mm/copypage.c | 5
arch/parisc/include/asm/pdc.h | 1
arch/parisc/kernel/firmware.c | 27
arch/powerpc/kernel/dma-iommu.c | 4
arch/powerpc/kernel/iommu.c | 11
arch/powerpc/kernel/legacy_serial.c | 8
arch/powerpc/mm/book3s64/radix_pgtable.c | 4
arch/powerpc/net/bpf_jit_comp.c | 2
arch/powerpc/platforms/44x/iss4xx.c | 2
arch/powerpc/platforms/44x/ppc476.c | 2
arch/powerpc/platforms/cell/spu_manage.c | 2
arch/powerpc/platforms/powermac/pic.c | 3
arch/powerpc/platforms/powernv/opal-lpc.c | 2
arch/powerpc/platforms/pseries/hotplug-cpu.c | 2
arch/powerpc/platforms/pseries/iommu.c | 13
arch/powerpc/platforms/pseries/vio.c | 2
arch/powerpc/sysdev/mpic_msgr.c | 2
arch/riscv/kernel/image-vars.h | 2
arch/riscv/kernel/probes/Makefile | 2
arch/s390/crypto/chacha-glue.c | 2
arch/s390/kernel/Makefile | 1
arch/x86/kernel/Makefile | 1
block/bfq-iosched.c | 2
crypto/jitterentropy-kcapi.c | 51
crypto/jitterentropy.c | 144 --
crypto/jitterentropy.h | 1
drivers/accel/habanalabs/common/device.c | 9
drivers/accel/habanalabs/common/habanalabs.h | 1
drivers/accel/habanalabs/common/habanalabs_drv.c | 1
drivers/accel/habanalabs/common/memory_mgr.c | 13
drivers/accel/ivpu/ivpu_drv.c | 4
drivers/acpi/acpi_apd.c | 2
drivers/acpi/acpica/dbnames.c | 3
drivers/acpi/acpica/dswstate.c | 11
drivers/acpi/ec.c | 1
drivers/acpi/video_detect.c | 35
drivers/base/regmap/regcache.c | 6
drivers/block/nbd.c | 6
drivers/block/null_blk/main.c | 5
drivers/bluetooth/btbcm.c | 47
drivers/bluetooth/btintel.c | 5
drivers/bluetooth/btrtl.c | 138 +-
drivers/bluetooth/btrtl.h | 5
drivers/bluetooth/btusb.c | 6
drivers/bluetooth/hci_h5.c | 4
drivers/char/tpm/tpm_tis.c | 16
drivers/clk/rockchip/clk-rk3588.c | 42
drivers/clk/tegra/clk-tegra20.c | 28
drivers/firmware/arm_sdei.c | 37
drivers/firmware/smccc/smccc.c | 26
drivers/firmware/smccc/soc_id.c | 28
drivers/firmware/sysfb_simplefb.c | 4
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 26
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 8
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 36
drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c | 21
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 51
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 5
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 2
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 2
drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 55
drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 7
drivers/gpu/drm/amd/display/dc/core/dc.c | 47
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 3
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 5
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 3
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c | 2
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 2
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c | 43
drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c | 2
drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c | 300 ++--
drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c | 4
drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c | 300 ++--
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c | 2
drivers/gpu/drm/amd/include/asic_reg/oss/osssys_4_2_0_offset.h | 6
drivers/gpu/drm/amd/include/asic_reg/oss/osssys_4_2_0_sh_mask.h | 11
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 18
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 20
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 1
drivers/gpu/drm/drm_displayid.c | 17
drivers/gpu/drm/drm_fb_helper.c | 16
drivers/gpu/drm/drm_mipi_dsi.c | 2
drivers/gpu/drm/exynos/exynos_drm_g2d.h | 4
drivers/gpu/drm/i915/Kconfig | 12
drivers/gpu/drm/i915/display/intel_atomic_plane.c | 4
drivers/gpu/drm/i915/display/intel_dp.c | 5
drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c | 7
drivers/gpu/drm/i915/i915_pci.c | 6
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h | 202 +++
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 177 ++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 671 ++--------
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 21
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 23
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 5
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 18
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 4
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 1
drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h | 3
drivers/gpu/drm/msm/dp/dp_audio.c | 12
drivers/gpu/drm/msm/dp/dp_audio.h | 2
drivers/gpu/drm/msm/dp/dp_aux.c | 80 -
drivers/gpu/drm/msm/dp/dp_catalog.c | 2
drivers/gpu/drm/msm/dp/dp_catalog.h | 2
drivers/gpu/drm/msm/dp/dp_display.c | 1
drivers/gpu/drm/msm/msm_gem_submit.c | 25
drivers/gpu/drm/nouveau/include/nvif/if0012.h | 4
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 3
drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 2
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1
drivers/gpu/drm/scheduler/sched_main.c | 2
drivers/gpu/drm/tegra/sor.c | 2
drivers/hid/hid-apple.c | 19
drivers/hid/hid-ids.h | 1
drivers/hid/hid-input.c | 2
drivers/hid/hid-logitech-hidpp.c | 53
drivers/hid/wacom_wac.c | 33
drivers/hwmon/nzxt-smart2.c | 3
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 11
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 57
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 18
drivers/infiniband/core/user_mad.c | 23
drivers/infiniband/hw/mlx5/mr.c | 6
drivers/input/joystick/xpad.c | 5
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 19
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 26
drivers/iommu/sprd-iommu.c | 29
drivers/irqchip/Kconfig | 1
drivers/irqchip/irq-gic-v3.c | 115 +
drivers/mcb/mcb-pci.c | 27
drivers/md/md.c | 18
drivers/media/pci/cx23885/cx23885-core.c | 4
drivers/media/pci/cx23885/cx23885-video.c | 13
drivers/media/pci/intel/ipu3/cio2-bridge.c | 15
drivers/media/pci/intel/ipu3/cio2-bridge.h | 3
drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 2
drivers/media/pci/tw68/tw68-video.c | 16
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c | 7
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 5
drivers/media/platform/renesas/vsp1/vsp1_drm.c | 18
drivers/media/platform/renesas/vsp1/vsp1_entity.c | 11
drivers/media/platform/samsung/exynos4-is/fimc-capture.c | 7
drivers/media/platform/ti/am437x/am437x-vpfe.c | 15
drivers/media/platform/ti/cal/cal-video.c | 8
drivers/media/usb/dvb-usb/cxusb-analog.c | 14
drivers/media/usb/pvrusb2/Kconfig | 3
drivers/memstick/host/r592.c | 2
drivers/message/fusion/mptlan.c | 2
drivers/mfd/dln2.c | 1
drivers/mfd/intel-lpss-pci.c | 15
drivers/mfd/intel_soc_pmic_chtwc.c | 14
drivers/misc/lkdtm/stackleak.c | 6
drivers/net/bonding/bond_netlink.c | 7
drivers/net/bonding/bond_options.c | 8
drivers/net/can/dev/skb.c | 3
drivers/net/can/kvaser_pciefd.c | 51
drivers/net/dsa/mv88e6xxx/port.h | 2
drivers/net/dsa/rzn1_a5psw.c | 83 -
drivers/net/dsa/rzn1_a5psw.h | 3
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9
drivers/net/ethernet/freescale/fec_main.c | 16
drivers/net/ethernet/google/gve/gve_main.c | 13
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c | 25
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h | 8
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 2
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h | 1
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 15
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 4
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 5
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 5
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 5
drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 5
drivers/net/ethernet/intel/ice/ice_lib.c | 5
drivers/net/ethernet/intel/ice/ice_sriov.c | 8
drivers/net/ethernet/intel/ice/ice_txrx.c | 8
drivers/net/ethernet/intel/ice/ice_txrx.h | 9
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 19
drivers/net/ethernet/intel/ice/ice_vf_lib.h | 1
drivers/net/ethernet/intel/ice/ice_virtchnl.c | 1
drivers/net/ethernet/intel/igb/e1000_mac.c | 4
drivers/net/ethernet/mellanox/mlx5/core/en/params.c | 3
drivers/net/ethernet/mellanox/mlx5/core/en_common.c | 2
drivers/net/ethernet/mscc/vsc7514_regs.c | 18
drivers/net/ethernet/netronome/nfp/nic/main.h | 2
drivers/net/ethernet/pasemi/pasemi_mac.c | 2
drivers/net/ethernet/sfc/ef100_netdev.c | 4
drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 1
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 5
drivers/net/ethernet/sun/cassini.c | 2
drivers/net/ipvlan/ipvlan_core.c | 6
drivers/net/mdio/mdio-mvusb.c | 11
drivers/net/pcs/pcs-xpcs.c | 2
drivers/net/phy/bcm-phy-lib.h | 5
drivers/net/phy/bcm7xxx.c | 2
drivers/net/phy/dp83867.c | 22
drivers/net/tap.c | 4
drivers/net/tun.c | 15
drivers/net/virtio_net.c | 61
drivers/net/wireless/ath/ath.h | 12
drivers/net/wireless/ath/ath11k/dp.c | 4
drivers/net/wireless/ath/ath11k/dp_rx.c | 17
drivers/net/wireless/ath/ath11k/peer.h | 1
drivers/net/wireless/ath/ath12k/dp_rx.c | 3
drivers/net/wireless/ath/ath12k/pci.c | 47
drivers/net/wireless/ath/ath12k/pci.h | 6
drivers/net/wireless/ath/ath12k/qmi.c | 4
drivers/net/wireless/ath/key.c | 2
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 13
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 2
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 51
drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 11
drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2
drivers/net/wireless/intel/iwlwifi/dvm/sta.c | 5
drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 2
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 19
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 10
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 2
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 37
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2
drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h | 2
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c | 3
drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 3
drivers/net/wireless/realtek/rtw88/mac80211.c | 2
drivers/net/wireless/realtek/rtw88/main.c | 15
drivers/net/wireless/realtek/rtw88/main.h | 3
drivers/net/wireless/realtek/rtw88/usb.c | 3
drivers/net/wireless/realtek/rtw88/usb.h | 2
drivers/net/wwan/iosm/iosm_ipc_imem.c | 27
drivers/net/wwan/iosm/iosm_ipc_imem_ops.c | 12
drivers/net/wwan/iosm/iosm_ipc_imem_ops.h | 6
drivers/parisc/power.c | 16
drivers/phy/st/phy-miphy28lp.c | 42
drivers/pinctrl/pinctrl-at91.c | 23
drivers/platform/x86/amd/pmc.c | 1
drivers/platform/x86/intel/vsec.c | 69 -
drivers/platform/x86/intel/vsec.h | 9
drivers/platform/x86/x86-android-tablets.c | 101 +
drivers/power/supply/axp288_charger.c | 15
drivers/remoteproc/imx_dsp_rproc.c | 187 ++
drivers/remoteproc/stm32_rproc.c | 8
drivers/s390/block/dasd_eckd.c | 33
drivers/s390/cio/device.c | 2
drivers/s390/cio/qdio.h | 2
drivers/scsi/hisi_sas/hisi_sas.h | 3
drivers/scsi/hisi_sas/hisi_sas_main.c | 25
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4
drivers/scsi/lpfc/lpfc_debugfs.c | 7
drivers/scsi/lpfc/lpfc_els.c | 24
drivers/scsi/scsi_lib.c | 3
drivers/scsi/storvsc_drv.c | 8
drivers/soundwire/bus.c | 15
drivers/soundwire/dmi-quirks.c | 25
drivers/soundwire/qcom.c | 3
drivers/spi/spi-imx.c | 24
drivers/spi/spi-intel-pci.c | 1
drivers/staging/axis-fifo/axis-fifo.c | 28
drivers/staging/media/imx/imx-media-capture.c | 12
drivers/staging/media/imx/imx-media-utils.c | 8
drivers/staging/media/omap4iss/iss_video.c | 6
drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 6
drivers/staging/rtl8192e/rtl8192e/rtl_core.h | 5
drivers/target/iscsi/iscsi_target.c | 6
drivers/thunderbolt/nhi.c | 29
drivers/thunderbolt/nhi_regs.h | 2
drivers/tty/serial/8250/8250_bcm7271.c | 7
drivers/tty/serial/8250/8250_core.c | 1
drivers/tty/serial/8250/8250_exar.c | 17
drivers/tty/serial/8250/8250_pci.c | 5
drivers/tty/serial/arc_uart.c | 7
drivers/tty/serial/qcom_geni_serial.c | 9
drivers/tty/vt/vc_screen.c | 11
drivers/ufs/core/ufshcd.c | 10
drivers/ufs/host/ufshcd-pci.c | 1
drivers/usb/class/usbtmc.c | 2
drivers/usb/dwc3/debugfs.c | 109 +
drivers/usb/dwc3/gadget.c | 67
drivers/usb/gadget/function/u_ether.c | 3
drivers/usb/gadget/udc/core.c | 151 --
drivers/usb/host/uhci-pci.c | 10
drivers/usb/host/xhci-mem.c | 9
drivers/usb/host/xhci-pci.c | 12
drivers/usb/host/xhci-ring.c | 29
drivers/usb/host/xhci.h | 2
drivers/usb/storage/scsiglue.c | 28
drivers/usb/typec/altmodes/displayport.c | 4
drivers/usb/typec/tcpm/tcpm.c | 16
drivers/usb/typec/ucsi/ucsi_acpi.c | 44
drivers/video/fbdev/arcfb.c | 15
fs/ceph/snap.c | 13
fs/cifs/cifsglob.h | 4
fs/cifs/connect.c | 8
fs/cifs/file.c | 26
fs/cifs/smb1ops.c | 9
fs/cifs/smb2ops.c | 7
fs/ext2/ext2.h | 1
fs/ext2/super.c | 7
fs/ext4/balloc.c | 18
fs/ext4/ext4.h | 15
fs/ext4/ialloc.c | 12
fs/ext4/mballoc.c | 131 +
fs/ext4/mmp.c | 9
fs/ext4/super.c | 24
fs/f2fs/checkpoint.c | 22
fs/f2fs/data.c | 7
fs/f2fs/extent_cache.c | 22
fs/f2fs/f2fs.h | 5
fs/f2fs/gc.c | 10
fs/f2fs/gc.h | 2
fs/f2fs/segment.h | 39
fs/f2fs/super.c | 2
fs/gfs2/glops.c | 3
fs/hfsplus/inode.c | 28
fs/ksmbd/connection.c | 3
fs/ksmbd/oplock.c | 5
fs/ksmbd/oplock.h | 2
fs/ksmbd/smb2misc.c | 5
fs/ksmbd/smb2pdu.c | 19
fs/nilfs2/inode.c | 18
fs/ntfs3/frecord.c | 5
fs/ntfs3/fsntfs.c | 1
fs/ntfs3/index.c | 11
fs/ntfs3/inode.c | 6
fs/ntfs3/record.c | 9
fs/open.c | 18
fs/statfs.c | 4
include/drm/display/drm_dp.h | 4
include/linux/arm-smccc.h | 18
include/linux/cpuhotplug.h | 1
include/linux/dim.h | 3
include/linux/if_vlan.h | 17
include/linux/netdevice.h | 1
include/linux/sched/task_stack.h | 2
include/linux/sunrpc/svc_rdma.h | 2
include/linux/sunrpc/svc_xprt.h | 2
include/net/bluetooth/hci.h | 15
include/net/bonding.h | 2
include/net/ip_vs.h | 6
include/net/pkt_sched.h | 2
include/net/sock.h | 2
include/uapi/asm-generic/fcntl.h | 1
kernel/bpf/bpf_local_storage.c | 16
kernel/bpf/verifier.c | 4
kernel/events/core.c | 14
kernel/rcu/refscale.c | 2
kernel/rcu/tree_exp.h | 6
kernel/time/tick-broadcast.c | 120 +
kernel/trace/rethook.c | 4
lib/cpu_rmap.c | 5
lib/dim/dim.c | 5
lib/dim/net_dim.c | 3
lib/dim/rdma_dim.c | 3
lib/maple_tree.c | 12
mm/zswap.c | 16
net/8021q/vlan_dev.c | 4
net/bluetooth/hci_event.c | 9
net/bluetooth/hci_sync.c | 6
net/bluetooth/l2cap_core.c | 1
net/bridge/br_forward.c | 2
net/bridge/br_private_tunnel.h | 8
net/can/isotp.c | 2
net/can/j1939/socket.c | 2
net/core/datagram.c | 15
net/core/dev.c | 4
net/core/skbuff.c | 4
net/core/stream.c | 12
net/devlink/core.c | 16
net/devlink/devl_internal.h | 1
net/devlink/leftover.c | 5
net/ipv4/af_inet.c | 2
net/ipv4/tcp.c | 14
net/ipv4/tcp_bpf.c | 2
net/ipv4/tcp_input.c | 4
net/ipv4/tcp_ipv4.c | 5
net/ipv6/ip6_gre.c | 13
net/key/af_key.c | 12
net/llc/af_llc.c | 8
net/mac80211/cfg.c | 7
net/mac80211/trace.h | 2
net/mac80211/tx.c | 5
net/netfilter/core.c | 6
net/netfilter/ipvs/ip_vs_sync.c | 2
net/netfilter/nf_conntrack_standalone.c | 3
net/netfilter/nf_tables_api.c | 4
net/netfilter/nft_chain_filter.c | 9
net/netfilter/nft_set_rbtree.c | 20
net/netlink/af_netlink.c | 8
net/nsh/nsh.c | 8
net/packet/af_packet.c | 6
net/sched/sch_mqprio.c | 5
net/sched/sch_taprio.c | 12
net/smc/smc_close.c | 4
net/smc/smc_rx.c | 4
net/smc/smc_tx.c | 4
net/socket.c | 2
net/sunrpc/svc.c | 19
net/sunrpc/svc_xprt.c | 24
net/sunrpc/svcsock.c | 30
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 11
net/sunrpc/xprtrdma/svc_rdma_transport.c | 2
net/tipc/bearer.c | 17
net/tipc/bearer.h | 3
net/tipc/link.c | 9
net/tipc/socket.c | 4
net/tipc/udp_media.c | 5
net/tls/tls_main.c | 3
net/unix/af_unix.c | 22
net/vmw_vsock/af_vsock.c | 2
net/wireless/scan.c | 6
net/xfrm/xfrm_device.c | 2
net/xfrm/xfrm_interface_core.c | 54
net/xfrm/xfrm_policy.c | 9
net/xfrm/xfrm_user.c | 15
samples/bpf/hbm.c | 1
scripts/recordmcount.c | 6
sound/firewire/digi00x/digi00x-stream.c | 4
sound/pci/hda/hda_generic.c | 7
sound/pci/hda/hda_intel.c | 3
sound/pci/hda/patch_hdmi.c | 5
sound/pci/hda/patch_realtek.c | 14
sound/soc/amd/Kconfig | 2
sound/soc/amd/ps/acp63.h | 2
sound/soc/amd/ps/pci-ps.c | 8
sound/soc/amd/yc/acp6x-mach.c | 21
sound/soc/amd/yc/acp6x.h | 3
sound/soc/amd/yc/pci-acp6x.c | 8
sound/soc/fsl/fsl_micfil.c | 14
sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 6
sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 1
sound/soc/mediatek/mt8186/mt8186-afe-pcm.c | 4
sound/soc/mediatek/mt8186/mt8186-audsys-clk.c | 46
sound/soc/mediatek/mt8186/mt8186-audsys-clk.h | 1
sound/soc/sof/ipc3-topology.c | 7
sound/soc/sof/topology.c | 4
sound/usb/format.c | 1
tools/include/uapi/asm-generic/fcntl.h | 1
tools/perf/builtin-script.c | 7
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c | 31
tools/testing/selftests/cgroup/test_memcontrol.c | 15
tools/testing/selftests/kvm/lib/x86_64/processor.c | 1
tools/testing/selftests/net/fib_nexthops.sh | 2
tools/testing/selftests/net/srv6_end_dt4_l3vpn_test.sh | 17
virt/kvm/kvm_main.c | 16
466 files changed, 5173 insertions(+), 2478 deletions(-)
Abdun Nihaal (1):
fs/ntfs3: Fix NULL dereference in ni_write_inode
Adrian Hunter (1):
scsi: ufs: ufs-pci: Add support for Intel Lunar Lake
Ahmed Zaki (2):
ice: Fix stats after PF reset
iavf: send VLAN offloading caps once after VFR
Ai Chao (1):
ALSA: hda/realtek: Add a quirk for HP EliteDesk 805
Alain Volmat (1):
phy: st: miphy28lp: use _poll_timeout functions for waits
Alan Stern (1):
USB: usbtmc: Fix direction for 0-length ioctl control messages
Aleksandr Loktionov (1):
igb: fix bit_shift to be in [1..8] range
Aleksandr Mezin (1):
hwmon: (nzxt-smart2) add another USB ID
Alex Deucher (2):
drm/amdgpu/gmc11: implement get_vbios_fb_size()
drm/amdgpu/gfx11: update gpu_clock_counter logic
Alex Henrie (2):
HID: apple: Set the tilde quirk flag on the Geyser 4 and later
HID: apple: Set the tilde quirk flag on the Geyser 3
Alexander Stein (1):
regmap: cache: Return error in cache sync operations for REGCACHE_NONE
Alexandre Ghiti (1):
riscv: Fix EFI stub usage of KASAN instrumented strcmp function
Alexis Lothoré (1):
net: dsa: rzn1-a5psw: fix STP states handling
Alon Giladi (2):
wifi: iwlwifi: fix OEM's name in the ppag approved list
wifi: iwlwifi: mvm: fix OEM's name in the tas approved list
Andrea Mayer (2):
selftests: seg6: disable DAD on IPv6 router cfg for srv6_end_dt4_l3vpn_test
selftets: seg6: disable rp_filter by default in srv6_end_dt4_l3vpn_test
Andreas Gruenbacher (1):
gfs2: Fix inode height consistency check
Andrew Davis (1):
serial: 8250_exar: Add support for USR298x PCI Modems
Andy Shevchenko (2):
xhci: mem: Carefully calculate size for memory allocations
pinctrl: at91: use devm_kasprintf() to avoid potential leaks (part 2)
Ard Biesheuvel (2):
ARM: 9294/2: vfp: Fix broken softirq handling with instrumentation enabled
ARM: 9297/1: vfp: avoid unbalanced stack on 'success' return path
Armin Wolf (1):
ACPI: EC: Fix oops when removing custom query handlers
Arnaud Pouliquen (1):
remoteproc: stm32_rproc: Add mutex protection for workqueue
Arnd Bergmann (4):
clk: tegra20: fix gcc-7 constant overflow warning
media: pvrusb2: fix DVB_CORE dependency
drm/exynos: fix g2d_open/close helper function definitions
bridge: always declare tunnel functions
Avihai Horon (1):
RDMA/mlx5: Remove pcie_relaxed_ordering_enabled() check for RO write
Ayush Gupta (2):
drm/amd/display: populate subvp cmd info only for the top pipe
drm/amd/display: fixed dcn30+ underflow issue
Badhri Jagan Sridharan (1):
usb: typec: altmodes/displayport: fix pin_assignment_show
Baishan Jiang (1):
ASoC: amd: yc: Add ThinkBook 14 G5+ ARP to quirks list for acp6x
Bas Nieuwenhuizen (1):
drm/amdgpu/gfx10: Disable gfxoff before disabling powergating.
Bastien Nocera (2):
HID: logitech-hidpp: Don't use the USB serial for USB devices
HID: logitech-hidpp: Reconcile USB and Unifying serials
Benjamin Poirier (1):
net: selftests: Fix optstring
Bharath SM (2):
SMB3: Close all deferred handles of inode in case of handle lease break
SMB3: drop reference to cfile before sending oplock break
Bingbu Cao (1):
media: ipu3-cio2: support multiple sensors and VCMs with same HID
Cem Kaya (1):
ASoC: amd: Add Dell G15 5525 to quirks list
Chaitanya Kulkarni (1):
null_blk: Always check queue mode setting from configfs
Chao Yu (2):
f2fs: fix to drop all dirty pages during umount() if cp_error is set
f2fs: fix to check readonly condition correctly
Chethan T N (1):
Bluetooth: btintel: Add LE States quirk support
Chih-Yen Chang (3):
ksmbd: allocate one more byte for implied bcc[0]
ksmbd: fix wrong UserName check in session_user
ksmbd: fix global-out-of-bounds in smb2_find_context_vals
Christian Brauner (1):
open: return EINVAL for O_DIRECTORY | O_CREAT
Christophe JAILLET (3):
net: mdio: mvusb: Fix an error handling path in mvusb_mdio_probe()
wifi: mac80211: Fix puncturing bitmap handling in __ieee80211_csa_finalize()
cassini: Fix a memory leak in the error handling path of cas_init_one()
Chuck Lever (2):
SUNRPC: Fix encoding of accepted but unsuccessful RPC replies
SUNRPC: Fix trace_svc_register() call site
Chunyan Zhang (1):
iommu/sprd: Release dma buffer to avoid memory leak
Clément Léger (2):
net: dsa: rzn1-a5psw: enable management frames for CPU port
net: dsa: rzn1-a5psw: disable learning for standalone ports
Colin Foster (1):
net: mscc: ocelot: fix stat counter register values
Colin Ian King (1):
block, bfq: Fix division by zero error on zero wsum
Dan Carpenter (1):
ALSA: firewire-digi00x: prevent potential use after free
Daniel Gabay (1):
wifi: iwlwifi: pcie: fix possible NULL pointer dereference
David E. Box (1):
platform/x86/intel: vsec: Explicitly enable capabilities
Dawid Wesierski (1):
ice: Fix ice VF reset during iavf initialization
Dmitry Baryshkov (4):
drm/msm/dpu: populate SmartDMA features in hw catalog
drm/msm/dpu: drop smart_dma_rev from dpu_caps
drm/msm/dpu: move UBWC/memory configuration to separate struct
drm/msm/dpu: split SM8550 catalog entry to the separate file
Dmitry Bogdanov (1):
scsi: target: iscsit: Free cmds before session free
Domenico Cerasuolo (1):
mm: fix zswap writeback race condition
Dong Chenchen (1):
net: nsh: Use correct mac_offset to unwind gso skb in nsh_gso_segment()
Dongliang Mu (1):
wifi: rtw88: fix memory leak in rtw_usb_probe()
Doug Berger (2):
serial: 8250_bcm7271: balance clk_enable calls
serial: 8250_bcm7271: fix leak in `brcmuart_probe`
Douglas Anderson (2):
drm/msm/dp: Clean up handling of DP AUX interrupts
ASoC: mediatek: mt8186: Fix use-after-free in driver remove path
Duoming Zhou (1):
media: netup_unidvb: fix use-after-free at del_timer()
Edward Lo (3):
fs/ntfs3: Enhance the attribute size check
fs/ntfs3: Validate MFT flags before replaying logs
fs/ntfs3: Add length check in indx_get_root
Eli Cohen (1):
lib: cpu_rmap: Avoid use after free on rmap->obj array entries
Eric Dumazet (9):
net: skb_partial_csum_set() fix against transport header magic value
netlink: annotate accesses to nlk->cb_running
net: annotate sk->sk_err write from do_recvmmsg()
net: deal with most data-races in sk_wait_event()
net: add vlan_get_protocol_and_depth() helper
tcp: add annotations around sk->sk_shutdown accesses
net: datagram: fix data-races in datagram_poll()
tcp: fix possible sk_priority leak in tcp_v4_send_reset()
vlan: fix a potential uninit-value in vlan_dev_hard_start_xmit()
Eugene Huang (1):
soundwire: dmi-quirks: add remapping for Intel 'Rooks County' NUC M15
Evan Quan (1):
drm/amd/pm: fix possible power mode mismatch between driver and PMFW
Feng Jiang (1):
platform/x86/amd: pmc: Fix memory leak in amd_pmc_stb_debugfs_open_v2()
Feng Liu (1):
virtio_net: Fix error unwinding of XDP initialization
Florian Fainelli (3):
net: phy: bcm7xx: Correct read from expansion register
net: bcmgenet: Remove phy_stop() from bcmgenet_netif_stop()
net: bcmgenet: Restore phy_stop() depending upon suspend/close
Florian Westphal (4):
netfilter: nf_tables: always release netdev hooks from notifier
netfilter: conntrack: fix possible bug_on with enable_hooks=1
netfilter: nf_tables: fix nft_trans type confusion
netfilter: nft_set_rbtree: fix null deref on element insertion
Francesco Dolcini (2):
Revert "usb: gadget: udc: core: Prevent redundant calls to pullup"
Revert "usb: gadget: udc: core: Invoke usb_gadget_connect only when started"
Frank Wang (1):
usb: typec: tcpm: fix multiple times discover svids error
Fred Oh (1):
ALSA: hda: LNL: add HD Audio PCI ID
Gabe Teeger (1):
drm/amd/display: Enable HostVM based on rIOMMU active
Gaurav Batra (2):
powerpc/iommu: DMA address offset is incorrectly calculated with 2MB TCEs
powerpc/iommu: Incorrect DDW Table is referenced for SR-IOV device
George Kennedy (1):
vc_screen: reload load of struct vc_data pointer in vcs_write() to avoid UAF
Greg Kroah-Hartman (1):
Linux 6.3.4
Grygorii Strashko (1):
net: phy: dp83867: add w/a for packet errors seen with short cables
Guilherme G. Piccoli (2):
parisc: Replace regular spinlock with spin_trylock on panic path
drm/amdgpu/gfx11: Adjust gfxoff before powergating on gfx11 as well
Gustav Johansson (1):
ksmbd: smb2: Allow messages padded to 8byte boundary
Gustavo A. R. Silva (1):
RDMA/core: Fix multiple -Warray-bounds warnings
Hangbin Liu (1):
bonding: fix send_peer_notif overflow
Hans de Goede (7):
platform/x86: x86-android-tablets: Add Acer Iconia One 7 B1-750 data
ACPI: video: Remove desktops without backlight DMI quirks
wifi: iwlwifi: dvm: Fix memcpy: detected field-spanning write backtrace
Bluetooth: hci_bcm: Fall back to getting bdaddr from EFI if not set
power: supply: axp288_charger: Use alt usb-id extcon on some x86 android tablets
mfd: intel_soc_pmic_chtwc: Add Lenovo Yoga Book X90F to intel_cht_wc_models
wifi: brcmfmac: Check for probe() id argument being NULL
Hao Zeng (2):
samples/bpf: Fix fout leak in hbm's run_bpf_prog
recordmcount: Fix memory leaks in the uwrite function
Hari Bathini (1):
powerpc/bpf: populate extable entries only during the last pass
Harshitha Prem (1):
wifi: ath11k: Ignore frags from uninitialized peer in dp.
Hector Martin (3):
wifi: brcmfmac: pcie: Provide a buffer of random bytes to the device
wifi: brcmfmac: cfg80211: Pass the PMK in binary instead of hex
wifi: brcmfmac: pcie: Add IDs/properties for BCM4387
Heiko Carstens (2):
s390/crypto: use vector instructions only if available for ChaCha20
s390/qdio: fix do_sqbs() inline assembly constraint
Huayu Chen (1):
nfp: fix NFP_NET_MAX_DSCP definition error
Hyunwoo Kim (1):
wifi: iwlwifi: pcie: Fix integer overflow in iwl_write_to_user_buf
Ido Schimmel (1):
devlink: Fix crash with CONFIG_NET_NS=n
Ilan Peer (1):
wifi: cfg80211: Drop entries with invalid BSSIDs in RNR
Ilya Leoshkevich (1):
statfs: enforce statfs[64] structure initialization
Iuliana Prodan (1):
remoteproc: imx_dsp_rproc: Add custom memory copy implementation for i.MX DSP Cores
Ivan Orlov (2):
selftests: cgroup: Add 'malloc' failures checks in test_memcontrol
KVM: selftests: Add 'malloc' failure check in vcpu_save_state
Jack Xiao (1):
drm/amd/amdgpu: introduce gc_*_mes_2.bin v2
Jaegeuk Kim (1):
f2fs: relax sanity check if checkpoint is corrupted
Jan Kara (1):
ext2: Check block size validity during mount
Jan Sokolowski (1):
ice: Fix undersized tx_flags variable
Jani Nikula (3):
drm/dsc: fix DP_DSC_MAX_BPP_DELTA_* macro values
drm/i915: taint kernel when force probing unsupported devices
drm/displayid: add displayid_get_header() and check bounds better
Jarkko Nikula (1):
mfd: intel-lpss: Add Intel Meteor Lake PCH-S LPSS PCI IDs
Jason Gerecke (1):
HID: wacom: generic: Set battery quirk only when we see battery data
Jeremy Soller (1):
ALSA: hda/realtek: Add quirk for Clevo L140AU
Jerry Snitselaar (1):
tpm/tpm_tis: Disable interrupts for more Lenovo devices
Jia-Ju Bai (1):
fs/ntfs3: Fix a possible null-pointer dereference in ni_clear()
Jianhua Lu (1):
dt-bindings: display/msm: dsi-controller-main: Document qcom, master-dsi and qcom, sync-dual-dsi
Jie Wang (2):
net: hns3: fix output information incomplete for dumping tx queue info with debugfs
net: hns3: fix reset delay time to avoid configuration timeout
Jijie Shao (2):
net: hns3: fix sending pfc frames after reset issue
net: hns3: fix reset timeout when enable full VF
Jimmy Assarsson (6):
can: kvaser_pciefd: Set CAN_STATE_STOPPED in kvaser_pciefd_stop()
can: kvaser_pciefd: Call request_irq() before enabling interrupts
can: kvaser_pciefd: Empty SRB buffer in probe
can: kvaser_pciefd: Clear listen-only bit if not explicitly requested
can: kvaser_pciefd: Do not send EFLUSH command on TFD interrupt
can: kvaser_pciefd: Disable interrupts in probe error path
Jiri Pirko (1):
devlink: change per-devlink netdev notifier to static one
Johannes Berg (6):
wifi: iwlwifi: mvm: fix ptk_pn memory leak
wifi: iwlwifi: fix iwl_mvm_max_amsdu_size() for MLO
wifi: mac80211: fix min center freq offset tracing
wifi: iwlwifi: mvm: fix cancel_delayed_work_sync() deadlock
wifi: iwlwifi: fw: fix DBGI dump
wifi: iwlwifi: mvm: don't trust firmware n_channels
John Harrison (1):
drm/i915/guc: Don't capture Gen8 regs on Xe devices
Josh Poimboeuf (2):
sched: Fix KCSAN noinstr violation
lkdtm/stackleak: Fix noinstr violation
Justin Tee (2):
scsi: lpfc: Prevent lpfc_debugfs_lockstat_write() buffer overflow
scsi: lpfc: Correct used_rpi count when devloss tmo fires with no recovery
Kai-Heng Feng (1):
ALSA: hda/realtek: Fix mute and micmute LEDs for yet another HP laptop
Kang Chen (1):
ACPI: processor: Check for null return of devm_kzalloc() in fch_misc_setup()
Karol Wachowski (1):
accel/ivpu: Remove D3hot delay for Meteorlake
Ke Zhang (1):
serial: arc_uart: fix of_iomap leak in `arc_serial_probe`
Kees Cook (3):
drm/nouveau/disp: More DP_RECEIVER_CAP_SIZE array fixes
media: imx-jpeg: Bounds check sizeimage access
wifi: ath: Silence memcpy run-time false positive warning
Kemeng Shi (2):
ext4: allow to find by goal if EXT4_MB_HINT_GOAL_ONLY is set
ext4: set goal start correctly in ext4_mb_normalize_request
Keoseong Park (1):
scsi: ufs: core: Fix I/O hang that occurs when BKOPS fails in W-LUN suspend
Kevin Groeneveld (1):
spi: spi-imx: fix MX51_ECSPI_* macros when cs > 3
Khadija Kamran (1):
staging: axis-fifo: initialize timeouts in init only
Konrad Dybcio (5):
arm64: dts: qcom: msm8996: Add missing DWC3 quirks
arm64: dts: qcom: sdm845-polaris: Drop inexistent properties
arm64: dts: qcom: sm6115-j606f: Add ramoops node
drm/msm/dpu: Allow variable SSPP_BLK size
drm/msm/dpu: Allow variable INTF_BLK size
Konrad Gräfe (1):
usb: gadget: u_ether: Fix host MAC address case
Krzysztof Kozlowski (2):
soundwire: qcom: gracefully handle too many ports in DT
serial: qcom-geni: fix enabling deactivated interrupt
Kumar Kartikeya Dwivedi (1):
bpf: Annotate data races in bpf_local_storage
Kuniyuki Iwashima (4):
net: Fix load-tearing on sk->sk_stamp in sock_recv_cmsgs().
af_unix: Fix a data race of sk->sk_receive_queue->qlen.
af_unix: Fix data races around sk->sk_shutdown.
tun: Fix memory leak for detached NAPI queue.
Larry Finger (1):
wifi: rtw88: Fix memory leak in rtw88_usb
Laurent Pinchart (1):
media: Prefer designated initializers over memset for subdev pad ops
Leon Romanovsky (2):
xfrm: release all offloaded policy memory
xfrm: Fix leak of dev tracker
Li Ma (1):
drm/amdgpu: reserve the old gc_11_0_*_mes.bin
Lorenzo Bianconi (1):
iio: imu: st_lsm6dsx: discard samples during filters settling time
Luke D. Jones (1):
ALSA: hda/realtek: Add quirk for 2nd ASUS GU603
M Chetan Kumar (1):
net: wwan: iosm: fix NULL pointer dereference when removing device
Manivannan Sadhasivam (1):
iommu/arm-smmu-qcom: Limit the SMR groups to 128
Marco Migliore (1):
net: dsa: mv88e6xxx: Fix mv88e6393x EPC write command offset
Marek Vasut (1):
net: stmmac: Initialize MAC_ONEUS_TIC_COUNTER register
Marijn Suijten (5):
drm/msm/dpu: Assign missing writeback log_mask
drm/msm/dpu: Move non-MDP_TOP INTF_INTR offsets out of hwio header
drm/msm/dpu: Reindent REV_7xxx interrupt masks with tabs
drm/msm/dpu: Fix PP_BLK_DIPHER -> DITHER typo
drm/msm/dpu: Remove duplicate register defines from INTF
Mario Limonciello (3):
drm/amd: Fix an out of bounds error in BIOS parser
xhci-pci: Only run d3cold avoidance quirk for s2idle
thunderbolt: Clear registers properly when auto clear isn't in use
Martin Willi (1):
Revert "Fix XFRM-I support for nested ESP tunnels"
Mathias Nyman (1):
xhci: Fix incorrect tracking of free space on transfer rings
Mathieu Poirier (1):
remoteproc: imx_dsp_rproc: Fix kernel test robot sparse warning
Max Chou (2):
Bluetooth: btrtl: check for NULL in btrtl_set_quirks()
Bluetooth: btrtl: Add the support for RTL8851B
Maxim Korotkov (1):
bnxt: avoid overflow in bnxt_get_nvram_directory()
Maxime Bizon (1):
usb-storage: fix deadlock when a scsi command timeouts more than once
Meng Tang (1):
Bluetooth: btusb: Add new PID/VID 04ca:3801 for MT7663
Michael Ellerman (1):
powerpc/64s/radix: Fix soft dirty tracking
Michael Kelley (1):
scsi: storvsc: Don't pass unused PFNs to Hyper-V host
Michael Lee (1):
wifi: mac80211: Abort running color change when stopping the AP
Michal Luczaj (1):
KVM: Fix vcpu_array[0] races
Michal Simek (1):
dt-bindings: ata: ahci-ceva: Cover all 4 iommus entries
Mika Westerberg (1):
spi: intel-pci: Add support for Meteor Lake-S SPI serial flash
Min Li (1):
Bluetooth: L2CAP: fix "bad unlock balance" in l2cap_disconnect_rsp
Mirsad Goran Todorovac (1):
wifi: mac80211: fortify the spinlock against deadlock by interrupt
Mukesh Sisodiya (1):
wifi: iwlwifi: add a new PCI device ID for BZ device
Mukul Joshi (1):
drm/amdgpu: Enable IH retry CAM on GFX9
Nagarajan Maran (1):
wifi: ath11k: Fix SKB corruption in REO destination ring
Nathan Chancellor (1):
net: pasemi: Fix return type of pasemi_mac_start_tx()
NeilBrown (2):
SUNRPC: double free xprt_ctxt while still in use
SUNRPC: always free ctxt when freeing deferred request
Nick Child (2):
net: Catch invalid index in XPS mapping
netdev: Enforce index cap in netdev_get_tx_queue
Nikhil Mahale (1):
ALSA: hda: Add NVIDIA codec IDs a3 through a7 to patch table
Nikita Zhandarovich (1):
drm/i915/dp: prevent potential div-by-zero
Nur Hussein (1):
drm/tegra: Avoid potential 32-bit integer overflow
Ojaswin Mujoo (1):
ext4: Fix best extent lstart adjustment logic in ext4_mb_new_inode_pa()
Oliver Hartkopp (3):
can: dev: fix missing CAN XL support in can_put_echo_skb()
can: j1939: recvmsg(): allow MSG_CMSG_COMPAT flag
can: isotp: recvmsg(): allow MSG_CMSG_COMPAT flag
Oliver Upton (1):
KVM: arm64: Infer the PA offset from IPA in stage-2 map walker
Paul E. McKenney (1):
refscale: Move shutdown from wait_event() to wait_event_idle()
Paul Hsieh (2):
drm/amd/display: Correct DML calculation to align HW formula
drm/amd/display: Correct DML calculation to follow HW SPEC
Peng Zhang (1):
maple_tree: make maple state reusable after mas_empty_area()
Peter Collingbourne (2):
arm64: Also reset KASAN tag if page is not PG_mte_tagged
arm64: mte: Do not set PG_mte_tagged if tags were not initialized
Peter Ujfalusi (1):
ASoC: SOF: ipc3-topology: Make sure that only one cmd is sent in dai_config
Philipp Hortmann (1):
staging: rtl8192e: Replace macro RTL_PCI_DEVICE with PCI_DEVICE
Pierre Asselin (1):
firmware/sysfb: Fix VESA format selection
Pierre Gondois (1):
firmware: arm_sdei: Fix sleep from invalid context BUG
Pieter Jansen van Vuuren (1):
sfc: disable RXFCS and RXALL features by default
Ping-Ke Shih (2):
wifi: rtw88: use work to update rate to avoid RCU warning
wifi: rtw88: correct qsel_to_ep[] type as int
Prajna Sariputra (1):
ASoC: amd: yc: Add DMI entries to support HP OMEN 16-n0xxx (8A42)
Qiang Ning (1):
mfd: dln2: Fix memory leak in dln2_probe()
Rajat Soni (1):
wifi: ath12k: fix memory leak in ath12k_qmi_driver_event_work()
Ramya Gnanasekar (2):
wifi: ath12k: Handle lock during peer_id find
wifi: ath12k: PCI ops for wakeup/release MHI
Randy Dunlap (1):
ARM: 9296/1: HP Jornada 7XX: fix kernel-doc warnings
Ranjani Sridharan (1):
ASoC: SOF: topology: Fix logic for copying tuples
Raul Cheleguini (2):
Bluetooth: Improve support for Actions Semi ATS2851 based devices
Bluetooth: Add new quirk for broken set random RPA timeout for ATS2851
Reese Russell (1):
wifi: mt76: mt7921: add Netgear AXE3000 (A8000) support
Richard Fitzgerald (1):
soundwire: bus: Fix unbalanced pm_runtime_put() causing usage count underflow
Rob Clark (2):
drm/msm: Fix submit error-path leaks
iommu/arm-smmu-qcom: Fix missing adreno_smmu's
Rob Herring (1):
powerpc: Use of_property_present() for testing DT property presence
Rodrigo Siqueira (1):
drm/amd/display: Use DC_LOG_DC in the trasform pixel function
Rodríguez Barbarin, José Javier (1):
mcb-pci: Reallocate memory region to avoid memory overlapping
Roger Quadros (1):
usb: dwc3: gadget: Improve dwc3_gadget_suspend() and dwc3_gadget_resume()
Roy Novich (1):
linux/dim: Do nothing if no time delta between samples
Ryan C. Underwood (1):
ALSA: hda/realtek: Apply HP B&O top speaker profile to Pavilion 15
Ryder Lee (1):
wifi: mt76: connac: fix stats->tx_bytes calculation
Ryusuke Konishi (1):
nilfs2: fix use-after-free bug of nilfs_root in nilfs_evict_inode()
Sabrina Dubroca (1):
xfrm: don't check the default policy if the policy allows the packet
Samson Tam (2):
drm/amd/display: enable DPG when disabling plane for phantom pipe
drm/amd/display: reallocate DET for dual displays with high pixel rate ratio
Samuel Čavoj (1):
usb: typec: ucsi: acpi: add quirk for ASUS Zenbook UM325
Sandipan Das (1):
perf script: Skip aggregation for stat events
Saravana Kannan (1):
drm/mipi-dsi: Set the fwnode for mipi_dsi_device
Sebastian Krzyszkowiak (1):
arm64: dts: imx8mq-librem5: Remove dis_u3_susphy_quirk from usb_dwc3_0
Sebastian Reichel (1):
clk: rockchip: rk3588: make gate linked clocks critical
Shanker Donthineni (1):
irqchip/gicv3: Workaround for NVIDIA erratum T241-FABRIC-4
Shengjiu Wang (1):
ASoC: fsl_micfil: Fix error handler with pm_runtime_enable
Shenwei Wang (1):
net: fec: remove the xdp_return_frame when lack of tx BDs
Simon Horman (1):
ipvs: Update width of source for ip_vs_sync_conn_options
Srinivas Kandagatla (1):
drm/msm/dp: unregister audio driver during unbind
Stanislav Lisovskiy (1):
drm/i915: Fix NULL ptr deref by checking new_crtc_state
Stefan Haberland (1):
s390/dasd: fix command reject error on ESE devices
Stephan Müller (1):
crypto: jitter - permanent and intermittent health errors
Steve French (1):
cifs: missing lock when updating session status
Sui Jingfeng (1):
drm/fbdev-generic: prohibit potential out-of-bounds access
Syed Saba Kareem (1):
ASoC: amd: Add check for acp config flags
Takashi Iwai (2):
ALSA: usb-audio: Add a sample rate workaround for Line6 Pod Go
ALSA: hda: Fix Oops by 9.1 surround channel names
Tamir Duberstein (1):
ACPICA: Avoid undefined behavior: applying zero offset to null pointer
Tetsuo Handa (1):
fs: hfsplus: remove WARN_ON() from hfsplus_cat_{read,write}_inode()
Theodore Ts'o (3):
ext4: reflect error codes from ext4_multi_mount_protect() to its callers
ext4: don't clear SB_RDONLY when remounting r/w until quota is re-enabled
ext4: allow ext4_get_group_info() to fail
Thomas Gleixner (1):
tick/broadcast: Make broadcast device replacement work correctly
Tobias Brunner (2):
xfrm: Reject optional tunnel/BEET mode templates in outbound policies
af_key: Reject optional tunnel/BEET mode templates in outbound policies
Toby Chen (1):
drm/rockchip: dw_hdmi: cleanup drm encoder during unbind
Tom Rix (1):
media: pvrusb2: VIDEO_PVRUSB2 depends on DVB_CORE to use dvb_* symbols
Tomas Krcka (1):
iommu/arm-smmu-v3: Acknowledge pri/event queue overflow if any
Tomer Tayar (1):
accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release()
Tong Liu01 (1):
drm/amdgpu: refine get gpu clock counter method
Tony Lindgren (1):
serial: 8250: Reinit port->pm on port specific driver unbind
Udipto Goswami (1):
usb: dwc3: debugfs: Resume dwc3 before accessing registers
Uwe Kleine-König (1):
net: fec: Better handle pm_runtime_get() failing in .remove()
Vasily Khoruzhick (2):
Bluetooth: Add new quirk for broken local ext features page 2
Bluetooth: btrtl: add support for the RTL8723CS
Vicki Pfau (1):
Input: xpad - add constants for GIP interface numbers
Vineeth Vijayan (1):
s390/cio: include subchannels without devices also for evaluation
Vitaliy Tomin (1):
serial: Add support for Advantech PCI-1611U card
Vitaly Prosyak (1):
drm/sched: Check scheduler work queue before calling timeout handling
Vitaly Rodionov (1):
ALSA: hda/realtek: Add quirk for HP EliteBook G10 laptops
Vladimir Oltean (2):
net/sched: pass netlink extack to mqprio and taprio offload
net: pcs: xpcs: fix C73 AN not getting enabled
Wei Chen (1):
media: mediatek: vcodec: Fix potential array out-of-bounds in decoder queue_setup
Weitao Wang (1):
USB: UHCI: adjust zhaoxin UHCI controllers OverCurrent bit value
Wenchao Hao (1):
scsi: Revert "scsi: core: Do not increase scsi_device's iorequest_cnt if dispatch failed"
Wyes Karny (1):
cpupower: Make TSC read per CPU for Mperf monitor
Xin Long (4):
erspan: get the proto with the md version for collect_md
tipc: add tipc_bearer_min_mtu to calculate min mtu
tipc: do not update mtu if msg_max is too small in mtu negotiation
tipc: check the bearer min mtu properly when setting it by netlink
Xingui Yang (1):
scsi: hisi_sas: Grab sas_dev lock when traversing the members of sas_dev.list
Xiubo Li (1):
ceph: force updating the msg pointer in non-split case
Yafang (1):
bpf: Add preempt_count_{sub,add} into btf id deny list
Yang Jihong (1):
perf/core: Fix perf_sample_data not properly initialized for different swevents in perf_tp_event()
Ye Bin (1):
fs/ntfs3: Fix NULL pointer dereference in 'ni_write_inode'
Yonggil Song (1):
f2fs: Fix system crash due to lack of free space in LFS
Yu Kuai (1):
md: fix soft lockup in status_resync
Ze Gao (2):
rethook: use preempt_{disable, enable}_notrace in rethook_trampoline_handler
rethook, fprobe: do not trace rethook related functions
Zheng Wang (2):
memstick: r592: Fix UAF bug in r592_remove due to race condition
scsi: message: mptlan: Fix use after free bug in mptlan_remove() due to race condition
Zhong Jinghua (1):
nbd: fix incomplete validation of ioctl arg
Zhuang Shengen (1):
vsock: avoid to close connected socket after the timeout
Ziwei Xiao (1):
gve: Remove the code of clearing PBA bit
Zongjie Li (1):
fbdev: arcfb: Fix error handling in arcfb_probe()
Zqiang (1):
rcu: Protect rcu_print_task_exp_stall() ->exp_tasks access
harperchen (2):
media: cx23885: Fix a null-ptr-deref bug in buffer_prepare() and buffer_finish()
media: pci: tw68: Fix null-ptr-deref bug in buf prepare and finish
lyndonli (1):
drm/amdgpu: Fix sdma v4 sw fini error
t.feng (1):
ipvlan:Fix out-of-bounds caused by unclear skb->cb
void0red (1):
ACPICA: ACPICA: check null return of ACPI_ALLOCATE_ZEROED in acpi_db_display_objects
weiliang1503 (1):
HID: Ignore battery for ELAN touchscreen on ROG Flow X13 GV301RA
^ permalink raw reply [relevance 1%]
* [PATCH 6.3 000/363] 6.3.4-rc2 review
@ 2023-05-23 17:01 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-05-23 17:01 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, srw, rwarsow
This is the start of the stable review cycle for the 6.3.4 release.
There are 363 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 25 May 2023 16:48:37 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.3.4-rc2.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.3.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 6.3.4-rc2
Wenchao Hao <haowenchao2@huawei.com>
scsi: Revert "scsi: core: Do not increase scsi_device's iorequest_cnt if dispatch failed"
Li Ma <li.ma@amd.com>
drm/amdgpu: reserve the old gc_11_0_*_mes.bin
Jack Xiao <Jack.Xiao@amd.com>
drm/amd/amdgpu: introduce gc_*_mes_2.bin v2
Ard Biesheuvel <ardb@kernel.org>
ARM: 9297/1: vfp: avoid unbalanced stack on 'success' return path
Ard Biesheuvel <ardb@kernel.org>
ARM: 9294/2: vfp: Fix broken softirq handling with instrumentation enabled
Mathieu Poirier <mathieu.poirier@linaro.org>
remoteproc: imx_dsp_rproc: Fix kernel test robot sparse warning
Ze Gao <zegao2021@gmail.com>
rethook, fprobe: do not trace rethook related functions
Ze Gao <zegao2021@gmail.com>
rethook: use preempt_{disable, enable}_notrace in rethook_trampoline_handler
Peter Collingbourne <pcc@google.com>
arm64: mte: Do not set PG_mte_tagged if tags were not initialized
Peter Collingbourne <pcc@google.com>
arm64: Also reset KASAN tag if page is not PG_mte_tagged
Heiko Carstens <hca@linux.ibm.com>
s390/qdio: fix do_sqbs() inline assembly constraint
Heiko Carstens <hca@linux.ibm.com>
s390/crypto: use vector instructions only if available for ChaCha20
Stefan Haberland <sth@linux.ibm.com>
s390/dasd: fix command reject error on ESE devices
Ryusuke Konishi <konishi.ryusuke@gmail.com>
nilfs2: fix use-after-free bug of nilfs_root in nilfs_evict_inode()
Huayu Chen <huayu.chen@corigine.com>
nfp: fix NFP_NET_MAX_DSCP definition error
Hari Bathini <hbathini@linux.ibm.com>
powerpc/bpf: populate extable entries only during the last pass
Michael Ellerman <mpe@ellerman.id.au>
powerpc/64s/radix: Fix soft dirty tracking
Jerry Snitselaar <jsnitsel@redhat.com>
tpm/tpm_tis: Disable interrupts for more Lenovo devices
Gaurav Batra <gbatra@linux.vnet.ibm.com>
powerpc/iommu: Incorrect DDW Table is referenced for SR-IOV device
Gaurav Batra <gbatra@linux.vnet.ibm.com>
powerpc/iommu: DMA address offset is incorrectly calculated with 2MB TCEs
Michal Simek <michal.simek@amd.com>
dt-bindings: ata: ahci-ceva: Cover all 4 iommus entries
Rob Clark <robdclark@chromium.org>
iommu/arm-smmu-qcom: Fix missing adreno_smmu's
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gfx11: update gpu_clock_counter logic
Tong Liu01 <Tong.Liu01@amd.com>
drm/amdgpu: refine get gpu clock counter method
Guilherme G. Piccoli <gpiccoli@igalia.com>
drm/amdgpu/gfx11: Adjust gfxoff before powergating on gfx11 as well
Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
drm/amdgpu/gfx10: Disable gfxoff before disabling powergating.
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gmc11: implement get_vbios_fb_size()
Evan Quan <evan.quan@amd.com>
drm/amd/pm: fix possible power mode mismatch between driver and PMFW
Xiubo Li <xiubli@redhat.com>
ceph: force updating the msg pointer in non-split case
George Kennedy <george.kennedy@oracle.com>
vc_screen: reload load of struct vc_data pointer in vcs_write() to avoid UAF
Mario Limonciello <mario.limonciello@amd.com>
thunderbolt: Clear registers properly when auto clear isn't in use
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
serial: qcom-geni: fix enabling deactivated interrupt
Andrew Davis <afd@ti.com>
serial: 8250_exar: Add support for USR298x PCI Modems
Vitaliy Tomin <tomin@iszf.irk.ru>
serial: Add support for Advantech PCI-1611U card
Sandipan Das <sandipan.das@amd.com>
perf script: Skip aggregation for stat events
Domenico Cerasuolo <cerasuolodomenico@gmail.com>
mm: fix zswap writeback race condition
Peng Zhang <zhangpeng.00@bytedance.com>
maple_tree: make maple state reusable after mas_empty_area()
Ilya Leoshkevich <iii@linux.ibm.com>
statfs: enforce statfs[64] structure initialization
Michal Luczaj <mhal@rbox.co>
KVM: Fix vcpu_array[0] races
Oliver Upton <oliver.upton@linux.dev>
KVM: arm64: Infer the PA offset from IPA in stage-2 map walker
Chih-Yen Chang <cc85nod@gmail.com>
ksmbd: fix global-out-of-bounds in smb2_find_context_vals
Chih-Yen Chang <cc85nod@gmail.com>
ksmbd: fix wrong UserName check in session_user
Chih-Yen Chang <cc85nod@gmail.com>
ksmbd: allocate one more byte for implied bcc[0]
Gustav Johansson <gustajo@axis.com>
ksmbd: smb2: Allow messages padded to 8byte boundary
Bharath SM <bharathsm@microsoft.com>
SMB3: drop reference to cfile before sending oplock break
Bharath SM <bharathsm@microsoft.com>
SMB3: Close all deferred handles of inode in case of handle lease break
Ping-Ke Shih <pkshih@realtek.com>
wifi: rtw88: correct qsel_to_ep[] type as int
Ping-Ke Shih <pkshih@realtek.com>
wifi: rtw88: use work to update rate to avoid RCU warning
Hans de Goede <hdegoede@redhat.com>
wifi: brcmfmac: Check for probe() id argument being NULL
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Disable interrupts in probe error path
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Do not send EFLUSH command on TFD interrupt
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Clear listen-only bit if not explicitly requested
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Empty SRB buffer in probe
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Call request_irq() before enabling interrupts
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Set CAN_STATE_STOPPED in kvaser_pciefd_stop()
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: recvmsg(): allow MSG_CMSG_COMPAT flag
Oliver Hartkopp <socketcan@hartkopp.net>
can: j1939: recvmsg(): allow MSG_CMSG_COMPAT flag
Kai-Heng Feng <kai.heng.feng@canonical.com>
ALSA: hda/realtek: Fix mute and micmute LEDs for yet another HP laptop
Vitaly Rodionov <vitalyr@opensource.cirrus.com>
ALSA: hda/realtek: Add quirk for HP EliteBook G10 laptops
Luke D. Jones <luke@ljones.dev>
ALSA: hda/realtek: Add quirk for 2nd ASUS GU603
Ai Chao <aichao@kylinos.cn>
ALSA: hda/realtek: Add a quirk for HP EliteDesk 805
Jeremy Soller <jeremy@system76.com>
ALSA: hda/realtek: Add quirk for Clevo L140AU
Nikhil Mahale <nmahale@nvidia.com>
ALSA: hda: Add NVIDIA codec IDs a3 through a7 to patch table
Takashi Iwai <tiwai@suse.de>
ALSA: hda: Fix Oops by 9.1 surround channel names
Mathias Nyman <mathias.nyman@linux.intel.com>
xhci: Fix incorrect tracking of free space on transfer rings
Mario Limonciello <mario.limonciello@amd.com>
xhci-pci: Only run d3cold avoidance quirk for s2idle
Francesco Dolcini <francesco.dolcini@toradex.com>
Revert "usb: gadget: udc: core: Invoke usb_gadget_connect only when started"
Francesco Dolcini <francesco.dolcini@toradex.com>
Revert "usb: gadget: udc: core: Prevent redundant calls to pullup"
Badhri Jagan Sridharan <badhri@google.com>
usb: typec: altmodes/displayport: fix pin_assignment_show
Konrad Gräfe <k.graefe@gateware.de>
usb: gadget: u_ether: Fix host MAC address case
Udipto Goswami <quic_ugoswami@quicinc.com>
usb: dwc3: debugfs: Resume dwc3 before accessing registers
Roger Quadros <rogerq@kernel.org>
usb: dwc3: gadget: Improve dwc3_gadget_suspend() and dwc3_gadget_resume()
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
USB: UHCI: adjust zhaoxin UHCI controllers OverCurrent bit value
Maxime Bizon <mbizon@freebox.fr>
usb-storage: fix deadlock when a scsi command timeouts more than once
Alan Stern <stern@rowland.harvard.edu>
USB: usbtmc: Fix direction for 0-length ioctl control messages
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Add a sample rate workaround for Line6 Pod Go
Arnd Bergmann <arnd@arndb.de>
bridge: always declare tunnel functions
Florian Westphal <fw@strlen.de>
netfilter: nft_set_rbtree: fix null deref on element insertion
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: fix nft_trans type confusion
Benjamin Poirier <bpoirier@nvidia.com>
net: selftests: Fix optstring
Vladimir Oltean <vladimir.oltean@nxp.com>
net: pcs: xpcs: fix C73 AN not getting enabled
M Chetan Kumar <m.chetan.kumar@linux.intel.com>
net: wwan: iosm: fix NULL pointer dereference when removing device
Eric Dumazet <edumazet@google.com>
vlan: fix a potential uninit-value in vlan_dev_hard_start_xmit()
Aleksandr Loktionov <aleksandr.loktionov@intel.com>
igb: fix bit_shift to be in [1..8] range
Marco Migliore <m.migliore@tiesse.com>
net: dsa: mv88e6xxx: Fix mv88e6393x EPC write command offset
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cassini: Fix a memory leak in the error handling path of cas_init_one()
Kuniyuki Iwashima <kuniyu@amazon.com>
tun: Fix memory leak for detached NAPI queue.
Ido Schimmel <idosch@nvidia.com>
devlink: Fix crash with CONFIG_NET_NS=n
Michael Kelley <mikelley@microsoft.com>
scsi: storvsc: Don't pass unused PFNs to Hyper-V host
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: mvm: don't trust firmware n_channels
Alon Giladi <alon.giladi@intel.com>
wifi: iwlwifi: mvm: fix OEM's name in the tas approved list
Alon Giladi <alon.giladi@intel.com>
wifi: iwlwifi: fix OEM's name in the ppag approved list
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: fw: fix DBGI dump
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: mvm: fix cancel_delayed_work_sync() deadlock
Michael Lee <michael-cy.lee@mediatek.com>
wifi: mac80211: Abort running color change when stopping the AP
Johannes Berg <johannes.berg@intel.com>
wifi: mac80211: fix min center freq offset tracing
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: mac80211: Fix puncturing bitmap handling in __ieee80211_csa_finalize()
Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
wifi: mac80211: fortify the spinlock against deadlock by interrupt
Ilan Peer <ilan.peer@intel.com>
wifi: cfg80211: Drop entries with invalid BSSIDs in RNR
Ahmed Zaki <ahmed.zaki@intel.com>
iavf: send VLAN offloading caps once after VFR
Dawid Wesierski <dawidx.wesierski@intel.com>
ice: Fix ice VF reset during iavf initialization
Ahmed Zaki <ahmed.zaki@intel.com>
ice: Fix stats after PF reset
Florian Fainelli <f.fainelli@gmail.com>
net: bcmgenet: Restore phy_stop() depending upon suspend/close
Florian Fainelli <f.fainelli@gmail.com>
net: bcmgenet: Remove phy_stop() from bcmgenet_netif_stop()
Oliver Hartkopp <socketcan@hartkopp.net>
can: dev: fix missing CAN XL support in can_put_echo_skb()
Vineeth Vijayan <vneethv@linux.ibm.com>
s390/cio: include subchannels without devices also for evaluation
Xin Long <lucien.xin@gmail.com>
tipc: check the bearer min mtu properly when setting it by netlink
Xin Long <lucien.xin@gmail.com>
tipc: do not update mtu if msg_max is too small in mtu negotiation
Xin Long <lucien.xin@gmail.com>
tipc: add tipc_bearer_min_mtu to calculate min mtu
Feng Liu <feliu@nvidia.com>
virtio_net: Fix error unwinding of XDP initialization
Shenwei Wang <shenwei.wang@nxp.com>
net: fec: remove the xdp_return_frame when lack of tx BDs
Dong Chenchen <dongchenchen2@huawei.com>
net: nsh: Use correct mac_offset to unwind gso skb in nsh_gso_segment()
Arnd Bergmann <arnd@arndb.de>
drm/exynos: fix g2d_open/close helper function definitions
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ASoC: SOF: topology: Fix logic for copying tuples
Douglas Anderson <dianders@chromium.org>
ASoC: mediatek: mt8186: Fix use-after-free in driver remove path
Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
ASoC: SOF: ipc3-topology: Make sure that only one cmd is sent in dai_config
Chuck Lever <chuck.lever@oracle.com>
SUNRPC: Fix trace_svc_register() call site
NeilBrown <neilb@suse.de>
SUNRPC: always free ctxt when freeing deferred request
NeilBrown <neilb@suse.de>
SUNRPC: double free xprt_ctxt while still in use
Duoming Zhou <duoming@zju.edu.cn>
media: netup_unidvb: fix use-after-free at del_timer()
Jijie Shao <shaojijie@huawei.com>
net: hns3: fix reset timeout when enable full VF
Jie Wang <wangjie125@huawei.com>
net: hns3: fix reset delay time to avoid configuration timeout
Jijie Shao <shaojijie@huawei.com>
net: hns3: fix sending pfc frames after reset issue
Jie Wang <wangjie125@huawei.com>
net: hns3: fix output information incomplete for dumping tx queue info with debugfs
Clément Léger <clement.leger@bootlin.com>
net: dsa: rzn1-a5psw: disable learning for standalone ports
Alexis Lothoré <alexis.lothore@bootlin.com>
net: dsa: rzn1-a5psw: fix STP states handling
Clément Léger <clement.leger@bootlin.com>
net: dsa: rzn1-a5psw: enable management frames for CPU port
Xin Long <lucien.xin@gmail.com>
erspan: get the proto with the md version for collect_md
Doug Berger <opendmb@gmail.com>
serial: 8250_bcm7271: fix leak in `brcmuart_probe`
Doug Berger <opendmb@gmail.com>
serial: 8250_bcm7271: balance clk_enable calls
Ke Zhang <m202171830@hust.edu.cn>
serial: arc_uart: fix of_iomap leak in `arc_serial_probe`
Arnd Bergmann <arnd@arndb.de>
media: pvrusb2: fix DVB_CORE dependency
Eric Dumazet <edumazet@google.com>
tcp: fix possible sk_priority leak in tcp_v4_send_reset()
Zhuang Shengen <zhuangshengen@huawei.com>
vsock: avoid to close connected socket after the timeout
Pieter Jansen van Vuuren <pieter.jansen-van-vuuren@amd.com>
sfc: disable RXFCS and RXALL features by default
Jan Sokolowski <jan.sokolowski@intel.com>
ice: Fix undersized tx_flags variable
Ryan C. Underwood <nemesis@icequake.net>
ALSA: hda/realtek: Apply HP B&O top speaker profile to Pavilion 15
Ryder Lee <ryder.lee@mediatek.com>
wifi: mt76: connac: fix stats->tx_bytes calculation
Dan Carpenter <dan.carpenter@linaro.org>
ALSA: firewire-digi00x: prevent potential use after free
Grygorii Strashko <grygorii.strashko@ti.com>
net: phy: dp83867: add w/a for packet errors seen with short cables
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
net: fec: Better handle pm_runtime_get() failing in .remove()
Jiri Pirko <jiri@resnulli.us>
devlink: change per-devlink netdev notifier to static one
Andrea Mayer <andrea.mayer@uniroma2.it>
selftets: seg6: disable rp_filter by default in srv6_end_dt4_l3vpn_test
Andrea Mayer <andrea.mayer@uniroma2.it>
selftests: seg6: disable DAD on IPv6 router cfg for srv6_end_dt4_l3vpn_test
Rob Clark <robdclark@chromium.org>
drm/msm: Fix submit error-path leaks
Tobias Brunner <tobias@strongswan.org>
af_key: Reject optional tunnel/BEET mode templates in outbound policies
Tobias Brunner <tobias@strongswan.org>
xfrm: Reject optional tunnel/BEET mode templates in outbound policies
Wyes Karny <wyes.karny@amd.com>
cpupower: Make TSC read per CPU for Mperf monitor
Shengjiu Wang <shengjiu.wang@nxp.com>
ASoC: fsl_micfil: Fix error handler with pm_runtime_enable
Chuck Lever <chuck.lever@oracle.com>
SUNRPC: Fix encoding of accepted but unsuccessful RPC replies
Jianhua Lu <lujianhua000@gmail.com>
dt-bindings: display/msm: dsi-controller-main: Document qcom, master-dsi and qcom, sync-dual-dsi
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Remove duplicate register defines from INTF
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Fix PP_BLK_DIPHER -> DITHER typo
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: split SM8550 catalog entry to the separate file
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: move UBWC/memory configuration to separate struct
Konrad Dybcio <konrad.dybcio@linaro.org>
drm/msm/dpu: Allow variable INTF_BLK size
Konrad Dybcio <konrad.dybcio@linaro.org>
drm/msm/dpu: Allow variable SSPP_BLK size
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: drop smart_dma_rev from dpu_caps
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: populate SmartDMA features in hw catalog
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Reindent REV_7xxx interrupt masks with tabs
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Move non-MDP_TOP INTF_INTR offsets out of hwio header
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Assign missing writeback log_mask
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
drm/msm/dp: unregister audio driver during unbind
Martin Willi <martin@strongswan.org>
Revert "Fix XFRM-I support for nested ESP tunnels"
Leon Romanovsky <leon@kernel.org>
xfrm: Fix leak of dev tracker
Leon Romanovsky <leon@kernel.org>
xfrm: release all offloaded policy memory
Sabrina Dubroca <sd@queasysnail.net>
xfrm: don't check the default policy if the policy allows the packet
Guilherme G. Piccoli <gpiccoli@igalia.com>
parisc: Replace regular spinlock with spin_trylock on panic path
Jarkko Nikula <jarkko.nikula@linux.intel.com>
mfd: intel-lpss: Add Intel Meteor Lake PCH-S LPSS PCI IDs
Qiang Ning <qning0106@126.com>
mfd: dln2: Fix memory leak in dln2_probe()
Hans de Goede <hdegoede@redhat.com>
mfd: intel_soc_pmic_chtwc: Add Lenovo Yoga Book X90F to intel_cht_wc_models
Richard Fitzgerald <rf@opensource.cirrus.com>
soundwire: bus: Fix unbalanced pm_runtime_put() causing usage count underflow
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
soundwire: qcom: gracefully handle too many ports in DT
Alain Volmat <avolmat@me.com>
phy: st: miphy28lp: use _poll_timeout functions for waits
Eugene Huang <eugene.huang99@gmail.com>
soundwire: dmi-quirks: add remapping for Intel 'Rooks County' NUC M15
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
pinctrl: at91: use devm_kasprintf() to avoid potential leaks (part 2)
Steve French <stfrench@microsoft.com>
cifs: missing lock when updating session status
Sebastian Reichel <sebastian.reichel@collabora.com>
clk: rockchip: rk3588: make gate linked clocks critical
Avihai Horon <avihaih@nvidia.com>
RDMA/mlx5: Remove pcie_relaxed_ordering_enabled() check for RO write
Vicki Pfau <vi@endrift.com>
Input: xpad - add constants for GIP interface numbers
Hans de Goede <hdegoede@redhat.com>
power: supply: axp288_charger: Use alt usb-id extcon on some x86 android tablets
Chunyan Zhang <chunyan.zhang@unisoc.com>
iommu/sprd: Release dma buffer to avoid memory leak
Tomas Krcka <krckatom@amazon.de>
iommu/arm-smmu-v3: Acknowledge pri/event queue overflow if any
Arnd Bergmann <arnd@arndb.de>
clk: tegra20: fix gcc-7 constant overflow warning
Jia-Ju Bai <baijiaju1990@gmail.com>
fs/ntfs3: Fix a possible null-pointer dereference in ni_clear()
Edward Lo <edward.lo@ambergroup.io>
fs/ntfs3: Add length check in indx_get_root
Edward Lo <edward.lo@ambergroup.io>
fs/ntfs3: Validate MFT flags before replaying logs
Abdun Nihaal <abdun.nihaal@gmail.com>
fs/ntfs3: Fix NULL dereference in ni_write_inode
Edward Lo <edward.lo@ambergroup.io>
fs/ntfs3: Enhance the attribute size check
Ye Bin <yebin10@huawei.com>
fs/ntfs3: Fix NULL pointer dereference in 'ni_write_inode'
Manivannan Sadhasivam <mani@kernel.org>
iommu/arm-smmu-qcom: Limit the SMR groups to 128
Ivan Orlov <ivan.orlov0322@gmail.com>
KVM: selftests: Add 'malloc' failure check in vcpu_save_state
Gustavo A. R. Silva <gustavoars@kernel.org>
RDMA/core: Fix multiple -Warray-bounds warnings
Hao Zeng <zenghao@kylinos.cn>
recordmcount: Fix memory leaks in the uwrite function
Alexandre Ghiti <alexghiti@rivosinc.com>
riscv: Fix EFI stub usage of KASAN instrumented strcmp function
Josh Poimboeuf <jpoimboe@kernel.org>
lkdtm/stackleak: Fix noinstr violation
Josh Poimboeuf <jpoimboe@kernel.org>
sched: Fix KCSAN noinstr violation
Rob Herring <robh@kernel.org>
powerpc: Use of_property_present() for testing DT property presence
Rodríguez Barbarin, José Javier <JoseJavier.Rodriguez@duagon.com>
mcb-pci: Reallocate memory region to avoid memory overlapping
Tony Lindgren <tony@atomide.com>
serial: 8250: Reinit port->pm on port specific driver unbind
Frank Wang <frank.wang@rock-chips.com>
usb: typec: tcpm: fix multiple times discover svids error
Jason Gerecke <killertofu@gmail.com>
HID: wacom: generic: Set battery quirk only when we see battery data
weiliang1503 <weiliang1503@gmail.com>
HID: Ignore battery for ELAN touchscreen on ROG Flow X13 GV301RA
Alex Henrie <alexhenrie24@gmail.com>
HID: apple: Set the tilde quirk flag on the Geyser 3
Syed Saba Kareem <Syed.SabaKareem@amd.com>
ASoC: amd: Add check for acp config flags
Baishan Jiang <bjiang400@outlook.com>
ASoC: amd: yc: Add ThinkBook 14 G5+ ARP to quirks list for acp6x
Cem Kaya <cemkaya.boun@gmail.com>
ASoC: amd: Add Dell G15 5525 to quirks list
Fred Oh <fred.oh@linux.intel.com>
ALSA: hda: LNL: add HD Audio PCI ID
Samuel Čavoj <samuel@cavoj.net>
usb: typec: ucsi: acpi: add quirk for ASUS Zenbook UM325
Kevin Groeneveld <kgroeneveld@lenbrook.com>
spi: spi-imx: fix MX51_ECSPI_* macros when cs > 3
Bastien Nocera <hadess@hadess.net>
HID: logitech-hidpp: Reconcile USB and Unifying serials
Bastien Nocera <hadess@hadess.net>
HID: logitech-hidpp: Don't use the USB serial for USB devices
Prajna Sariputra <putr4.s@gmail.com>
ASoC: amd: yc: Add DMI entries to support HP OMEN 16-n0xxx (8A42)
Mika Westerberg <mika.westerberg@linux.intel.com>
spi: intel-pci: Add support for Meteor Lake-S SPI serial flash
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
xhci: mem: Carefully calculate size for memory allocations
Khadija Kamran <kamrankhadijadj@gmail.com>
staging: axis-fifo: initialize timeouts in init only
Lorenzo Bianconi <lorenzo@kernel.org>
iio: imu: st_lsm6dsx: discard samples during filters settling time
Alex Henrie <alexhenrie24@gmail.com>
HID: apple: Set the tilde quirk flag on the Geyser 4 and later
Philipp Hortmann <philipp.g.hortmann@gmail.com>
staging: rtl8192e: Replace macro RTL_PCI_DEVICE with PCI_DEVICE
Max Chou <max.chou@realtek.com>
Bluetooth: btrtl: Add the support for RTL8851B
Min Li <lm0963hack@gmail.com>
Bluetooth: L2CAP: fix "bad unlock balance" in l2cap_disconnect_rsp
Raul Cheleguini <raul.cheleguini@gmail.com>
Bluetooth: Add new quirk for broken set random RPA timeout for ATS2851
Hans de Goede <hdegoede@redhat.com>
Bluetooth: hci_bcm: Fall back to getting bdaddr from EFI if not set
Chethan T N <chethan.tumkur.narayan@intel.com>
Bluetooth: btintel: Add LE States quirk support
Max Chou <max.chou@realtek.com>
Bluetooth: btrtl: check for NULL in btrtl_set_quirks()
Raul Cheleguini <rcheleguini@google.com>
Bluetooth: Improve support for Actions Semi ATS2851 based devices
Vasily Khoruzhick <anarsoul@gmail.com>
Bluetooth: btrtl: add support for the RTL8723CS
Vasily Khoruzhick <anarsoul@gmail.com>
Bluetooth: Add new quirk for broken local ext features page 2
Meng Tang <tangmeng@uniontech.com>
Bluetooth: btusb: Add new PID/VID 04ca:3801 for MT7663
Simon Horman <horms@kernel.org>
ipvs: Update width of source for ip_vs_sync_conn_options
Zhong Jinghua <zhongjinghua@huawei.com>
nbd: fix incomplete validation of ioctl arg
Larry Finger <Larry.Finger@lwfinger.net>
wifi: rtw88: Fix memory leak in rtw88_usb
Nagarajan Maran <quic_nmaran@quicinc.com>
wifi: ath11k: Fix SKB corruption in REO destination ring
Hans de Goede <hdegoede@redhat.com>
wifi: iwlwifi: dvm: Fix memcpy: detected field-spanning write backtrace
Chaitanya Kulkarni <kch@nvidia.com>
null_blk: Always check queue mode setting from configfs
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: relax sanity check if checkpoint is corrupted
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: fix iwl_mvm_max_amsdu_size() for MLO
Reese Russell <git@qrsnap.io>
wifi: mt76: mt7921: add Netgear AXE3000 (A8000) support
Harshitha Prem <quic_hprem@quicinc.com>
wifi: ath11k: Ignore frags from uninitialized peer in dp.
Colin Ian King <colin.i.king@gmail.com>
block, bfq: Fix division by zero error on zero wsum
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: mvm: fix ptk_pn memory leak
Hyunwoo Kim <imv4bel@gmail.com>
wifi: iwlwifi: pcie: Fix integer overflow in iwl_write_to_user_buf
Mukesh Sisodiya <mukesh.sisodiya@intel.com>
wifi: iwlwifi: add a new PCI device ID for BZ device
Daniel Gabay <daniel.gabay@intel.com>
wifi: iwlwifi: pcie: fix possible NULL pointer dereference
Vladimir Oltean <vladimir.oltean@nxp.com>
net/sched: pass netlink extack to mqprio and taprio offload
Yu Kuai <yukuai3@huawei.com>
md: fix soft lockup in status_resync
Yafang <laoar.shao@gmail.com>
bpf: Add preempt_count_{sub,add} into btf id deny list
Hao Zeng <zenghao@kylinos.cn>
samples/bpf: Fix fout leak in hbm's run_bpf_prog
Chao Yu <chao@kernel.org>
f2fs: fix to check readonly condition correctly
Chao Yu <chao@kernel.org>
f2fs: fix to drop all dirty pages during umount() if cp_error is set
Yonggil Song <yonggil.song@samsung.com>
f2fs: Fix system crash due to lack of free space in LFS
Stephan Müller <smueller@chronox.de>
crypto: jitter - permanent and intermittent health errors
Ojaswin Mujoo <ojaswin@linux.ibm.com>
ext4: Fix best extent lstart adjustment logic in ext4_mb_new_inode_pa()
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: set goal start correctly in ext4_mb_normalize_request
Xingui Yang <yangxingui@huawei.com>
scsi: hisi_sas: Grab sas_dev lock when traversing the members of sas_dev.list
Adrian Hunter <adrian.hunter@intel.com>
scsi: ufs: ufs-pci: Add support for Intel Lunar Lake
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Fix inode height consistency check
Zheng Wang <zyytlz.wz@163.com>
scsi: message: mptlan: Fix use after free bug in mptlan_remove() due to race condition
Eli Cohen <elic@nvidia.com>
lib: cpu_rmap: Avoid use after free on rmap->obj array entries
Dmitry Bogdanov <d.bogdanov@yadro.com>
scsi: target: iscsit: Free cmds before session free
Nick Child <nnac123@linux.ibm.com>
netdev: Enforce index cap in netdev_get_tx_queue
Nick Child <nnac123@linux.ibm.com>
net: Catch invalid index in XPS mapping
Rajat Soni <quic_rajson@quicinc.com>
wifi: ath12k: fix memory leak in ath12k_qmi_driver_event_work()
Nathan Chancellor <nathan@kernel.org>
net: pasemi: Fix return type of pasemi_mac_start_tx()
Maxim Korotkov <korotkov.maxim.s@gmail.com>
bnxt: avoid overflow in bnxt_get_nvram_directory()
Dongliang Mu <dzm91@hust.edu.cn>
wifi: rtw88: fix memory leak in rtw_usb_probe()
Justin Tee <justin.tee@broadcom.com>
scsi: lpfc: Correct used_rpi count when devloss tmo fires with no recovery
Justin Tee <justin.tee@broadcom.com>
scsi: lpfc: Prevent lpfc_debugfs_lockstat_write() buffer overflow
Jan Kara <jack@suse.cz>
ext2: Check block size validity during mount
Hector Martin <marcan@marcan.st>
wifi: brcmfmac: pcie: Add IDs/properties for BCM4387
Hector Martin <marcan@marcan.st>
wifi: brcmfmac: cfg80211: Pass the PMK in binary instead of hex
Hector Martin <marcan@marcan.st>
wifi: brcmfmac: pcie: Provide a buffer of random bytes to the device
Kumar Kartikeya Dwivedi <memxor@gmail.com>
bpf: Annotate data races in bpf_local_storage
Ramya Gnanasekar <quic_rgnanase@quicinc.com>
wifi: ath12k: PCI ops for wakeup/release MHI
Ramya Gnanasekar <quic_rgnanase@quicinc.com>
wifi: ath12k: Handle lock during peer_id find
Kees Cook <keescook@chromium.org>
wifi: ath: Silence memcpy run-time false positive warning
Aleksandr Mezin <mezin.alexander@gmail.com>
hwmon: (nzxt-smart2) add another USB ID
Feng Jiang <jiangfeng@kylinos.cn>
platform/x86/amd: pmc: Fix memory leak in amd_pmc_stb_debugfs_open_v2()
Wei Chen <harperchen1110@gmail.com>
media: mediatek: vcodec: Fix potential array out-of-bounds in decoder queue_setup
Mukul Joshi <mukul.joshi@amd.com>
drm/amdgpu: Enable IH retry CAM on GFX9
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: Prefer designated initializers over memset for subdev pad ops
lyndonli <Lyndon.Li@amd.com>
drm/amdgpu: Fix sdma v4 sw fini error
Mario Limonciello <mario.limonciello@amd.com>
drm/amd: Fix an out of bounds error in BIOS parser
Paul Hsieh <Paul.Hsieh@amd.com>
drm/amd/display: Correct DML calculation to follow HW SPEC
Hans de Goede <hdegoede@redhat.com>
ACPI: video: Remove desktops without backlight DMI quirks
Bingbu Cao <bingbu.cao@intel.com>
media: ipu3-cio2: support multiple sensors and VCMs with same HID
Shanker Donthineni <sdonthineni@nvidia.com>
irqchip/gicv3: Workaround for NVIDIA erratum T241-FABRIC-4
Konrad Dybcio <konrad.dybcio@linaro.org>
arm64: dts: qcom: sm6115-j606f: Add ramoops node
Konrad Dybcio <konrad.dybcio@linaro.org>
arm64: dts: qcom: sdm845-polaris: Drop inexistent properties
void0red <30990023+void0red@users.noreply.github.com>
ACPICA: ACPICA: check null return of ACPI_ALLOCATE_ZEROED in acpi_db_display_objects
Tamir Duberstein <tamird@google.com>
ACPICA: Avoid undefined behavior: applying zero offset to null pointer
Douglas Anderson <dianders@chromium.org>
drm/msm/dp: Clean up handling of DP AUX interrupts
Nur Hussein <hussein@unixcat.org>
drm/tegra: Avoid potential 32-bit integer overflow
Karol Wachowski <karol.wachowski@linux.intel.com>
accel/ivpu: Remove D3hot delay for Meteorlake
Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
remoteproc: stm32_rproc: Add mutex protection for workqueue
Ayush Gupta <ayugupta@amd.com>
drm/amd/display: fixed dcn30+ underflow issue
Armin Wolf <W_Armin@gmx.de>
ACPI: EC: Fix oops when removing custom query handlers
Pierre Gondois <pierre.gondois@arm.com>
firmware: arm_sdei: Fix sleep from invalid context BUG
Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
arm64: dts: imx8mq-librem5: Remove dis_u3_susphy_quirk from usb_dwc3_0
Zheng Wang <zyytlz.wz@163.com>
memstick: r592: Fix UAF bug in r592_remove due to race condition
Toby Chen <tobyc@nvidia.com>
drm/rockchip: dw_hdmi: cleanup drm encoder during unbind
Kang Chen <void0red@gmail.com>
ACPI: processor: Check for null return of devm_kzalloc() in fch_misc_setup()
David E. Box <david.e.box@linux.intel.com>
platform/x86/intel: vsec: Explicitly enable capabilities
Tom Rix <trix@redhat.com>
media: pvrusb2: VIDEO_PVRUSB2 depends on DVB_CORE to use dvb_* symbols
harperchen <harperchen1110@gmail.com>
media: pci: tw68: Fix null-ptr-deref bug in buf prepare and finish
harperchen <harperchen1110@gmail.com>
media: cx23885: Fix a null-ptr-deref bug in buffer_prepare() and buffer_finish()
Kees Cook <keescook@chromium.org>
media: imx-jpeg: Bounds check sizeimage access
Samson Tam <Samson.Tam@amd.com>
drm/amd/display: reallocate DET for dual displays with high pixel rate ratio
Tomer Tayar <ttayar@habana.ai>
accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release()
Konrad Dybcio <konrad.dybcio@linaro.org>
arm64: dts: qcom: msm8996: Add missing DWC3 quirks
Iuliana Prodan <iuliana.prodan@nxp.com>
remoteproc: imx_dsp_rproc: Add custom memory copy implementation for i.MX DSP Cores
Alexander Stein <alexander.stein@ew.tq-group.com>
regmap: cache: Return error in cache sync operations for REGCACHE_NONE
Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
drm/amd/display: Use DC_LOG_DC in the trasform pixel function
Gabe Teeger <gabe.teeger@amd.com>
drm/amd/display: Enable HostVM based on rIOMMU active
Hans de Goede <hdegoede@redhat.com>
platform/x86: x86-android-tablets: Add Acer Iconia One 7 B1-750 data
Samson Tam <samson.tam@amd.com>
drm/amd/display: enable DPG when disabling plane for phantom pipe
Paul Hsieh <Paul.Hsieh@amd.com>
drm/amd/display: Correct DML calculation to align HW formula
Ayush Gupta <ayush.gupta@amd.com>
drm/amd/display: populate subvp cmd info only for the top pipe
Jani Nikula <jani.nikula@intel.com>
drm/displayid: add displayid_get_header() and check bounds better
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
fs: hfsplus: remove WARN_ON() from hfsplus_cat_{read,write}_inode()
Christian Brauner <brauner@kernel.org>
open: return EINVAL for O_DIRECTORY | O_CREAT
Zqiang <qiang1.zhang@intel.com>
rcu: Protect rcu_print_task_exp_stall() ->exp_tasks access
Ivan Orlov <ivan.orlov0322@gmail.com>
selftests: cgroup: Add 'malloc' failures checks in test_memcontrol
Paul E. McKenney <paulmck@kernel.org>
refscale: Move shutdown from wait_event() to wait_event_idle()
Theodore Ts'o <tytso@mit.edu>
ext4: allow ext4_get_group_info() to fail
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: allow to find by goal if EXT4_MB_HINT_GOAL_ONLY is set
Theodore Ts'o <tytso@mit.edu>
ext4: don't clear SB_RDONLY when remounting r/w until quota is re-enabled
Theodore Ts'o <tytso@mit.edu>
ext4: reflect error codes from ext4_multi_mount_protect() to its callers
Zongjie Li <u202112089@hust.edu.cn>
fbdev: arcfb: Fix error handling in arcfb_probe()
Jani Nikula <jani.nikula@intel.com>
drm/i915: taint kernel when force probing unsupported devices
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
drm/i915/dp: prevent potential div-by-zero
Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
drm/i915: Fix NULL ptr deref by checking new_crtc_state
John Harrison <John.C.Harrison@Intel.com>
drm/i915/guc: Don't capture Gen8 regs on Xe devices
Kuniyuki Iwashima <kuniyu@amazon.com>
af_unix: Fix data races around sk->sk_shutdown.
Kuniyuki Iwashima <kuniyu@amazon.com>
af_unix: Fix a data race of sk->sk_receive_queue->qlen.
Eric Dumazet <edumazet@google.com>
net: datagram: fix data-races in datagram_poll()
Vitaly Prosyak <vitaly.prosyak@amd.com>
drm/sched: Check scheduler work queue before calling timeout handling
Colin Foster <colin.foster@in-advantage.com>
net: mscc: ocelot: fix stat counter register values
t.feng <fengtao40@huawei.com>
ipvlan:Fix out-of-bounds caused by unclear skb->cb
Ziwei Xiao <ziweixiao@google.com>
gve: Remove the code of clearing PBA bit
Eric Dumazet <edumazet@google.com>
tcp: add annotations around sk->sk_shutdown accesses
Eric Dumazet <edumazet@google.com>
net: add vlan_get_protocol_and_depth() helper
Eric Dumazet <edumazet@google.com>
net: deal with most data-races in sk_wait_event()
Eric Dumazet <edumazet@google.com>
net: annotate sk->sk_err write from do_recvmmsg()
Eric Dumazet <edumazet@google.com>
netlink: annotate accesses to nlk->cb_running
Hangbin Liu <liuhangbin@gmail.com>
bonding: fix send_peer_notif overflow
Florian Westphal <fw@strlen.de>
netfilter: conntrack: fix possible bug_on with enable_hooks=1
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: always release netdev hooks from notifier
Florian Fainelli <f.fainelli@gmail.com>
net: phy: bcm7xx: Correct read from expansion register
Kuniyuki Iwashima <kuniyu@amazon.com>
net: Fix load-tearing on sk->sk_stamp in sock_recv_cmsgs().
Marek Vasut <marex@denx.de>
net: stmmac: Initialize MAC_ONEUS_TIC_COUNTER register
Roy Novich <royno@nvidia.com>
linux/dim: Do nothing if no time delta between samples
Thomas Gleixner <tglx@linutronix.de>
tick/broadcast: Make broadcast device replacement work correctly
Keoseong Park <keosung.park@samsung.com>
scsi: ufs: core: Fix I/O hang that occurs when BKOPS fails in W-LUN suspend
Yang Jihong <yangjihong1@huawei.com>
perf/core: Fix perf_sample_data not properly initialized for different swevents in perf_tp_event()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
net: mdio: mvusb: Fix an error handling path in mvusb_mdio_probe()
Eric Dumazet <edumazet@google.com>
net: skb_partial_csum_set() fix against transport header magic value
Randy Dunlap <rdunlap@infradead.org>
ARM: 9296/1: HP Jornada 7XX: fix kernel-doc warnings
Saravana Kannan <saravanak@google.com>
drm/mipi-dsi: Set the fwnode for mipi_dsi_device
Kees Cook <keescook@chromium.org>
drm/nouveau/disp: More DP_RECEIVER_CAP_SIZE array fixes
Jani Nikula <jani.nikula@intel.com>
drm/dsc: fix DP_DSC_MAX_BPP_DELTA_* macro values
Pierre Asselin <pa@panix.com>
firmware/sysfb: Fix VESA format selection
Sui Jingfeng <suijingfeng@loongson.cn>
drm/fbdev-generic: prohibit potential out-of-bounds access
-------------
Diffstat:
Documentation/arm64/silicon-errata.rst | 2 +
.../devicetree/bindings/ata/ceva,ahci-1v84.yaml | 2 +-
.../bindings/display/msm/dsi-controller-main.yaml | 12 +
Makefile | 4 +-
arch/arm/include/asm/assembler.h | 13 -
arch/arm/mach-sa1100/jornada720_ssp.c | 5 +-
arch/arm/vfp/entry.S | 16 +-
arch/arm/vfp/vfphw.S | 16 +-
arch/arm/vfp/vfpmodule.c | 27 +-
arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 1 -
arch/arm64/boot/dts/qcom/msm8996.dtsi | 3 +
arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts | 2 -
arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts | 11 +
arch/arm64/include/asm/kvm_pgtable.h | 1 +
arch/arm64/kernel/mte.c | 7 +-
arch/arm64/kvm/hyp/pgtable.c | 32 +-
arch/arm64/mm/copypage.c | 5 +-
arch/parisc/include/asm/pdc.h | 1 +
arch/parisc/kernel/firmware.c | 27 +-
arch/powerpc/kernel/dma-iommu.c | 4 +-
arch/powerpc/kernel/iommu.c | 11 +-
arch/powerpc/kernel/legacy_serial.c | 8 +-
arch/powerpc/mm/book3s64/radix_pgtable.c | 4 +-
arch/powerpc/net/bpf_jit_comp.c | 2 +
arch/powerpc/platforms/44x/iss4xx.c | 2 +-
arch/powerpc/platforms/44x/ppc476.c | 2 +-
arch/powerpc/platforms/cell/spu_manage.c | 2 +-
arch/powerpc/platforms/powermac/pic.c | 3 +-
arch/powerpc/platforms/powernv/opal-lpc.c | 2 +-
arch/powerpc/platforms/pseries/hotplug-cpu.c | 2 +-
arch/powerpc/platforms/pseries/iommu.c | 13 +-
arch/powerpc/platforms/pseries/vio.c | 2 +-
arch/powerpc/sysdev/mpic_msgr.c | 2 +-
arch/riscv/kernel/image-vars.h | 2 -
arch/riscv/kernel/probes/Makefile | 2 +
arch/s390/crypto/chacha-glue.c | 2 +-
arch/s390/kernel/Makefile | 1 +
arch/x86/kernel/Makefile | 1 +
block/bfq-iosched.c | 2 +
crypto/jitterentropy-kcapi.c | 51 +-
crypto/jitterentropy.c | 144 ++---
crypto/jitterentropy.h | 1 -
drivers/accel/habanalabs/common/device.c | 9 +
drivers/accel/habanalabs/common/habanalabs.h | 1 +
drivers/accel/habanalabs/common/habanalabs_drv.c | 1 +
drivers/accel/habanalabs/common/memory_mgr.c | 13 +-
drivers/accel/ivpu/ivpu_drv.c | 4 +
drivers/acpi/acpi_apd.c | 2 +
drivers/acpi/acpica/dbnames.c | 3 +
drivers/acpi/acpica/dswstate.c | 11 +-
drivers/acpi/ec.c | 1 +
drivers/acpi/video_detect.c | 35 --
drivers/base/regmap/regcache.c | 6 +
drivers/block/nbd.c | 6 +
drivers/block/null_blk/main.c | 5 +
drivers/bluetooth/btbcm.c | 47 +-
drivers/bluetooth/btintel.c | 5 +-
drivers/bluetooth/btrtl.c | 138 ++++-
drivers/bluetooth/btrtl.h | 5 +
drivers/bluetooth/btusb.c | 6 +
drivers/bluetooth/hci_h5.c | 4 +
drivers/char/tpm/tpm_tis.c | 16 +
drivers/clk/rockchip/clk-rk3588.c | 42 +-
drivers/clk/tegra/clk-tegra20.c | 28 +-
drivers/firmware/arm_sdei.c | 37 +-
drivers/firmware/smccc/smccc.c | 26 +
drivers/firmware/smccc/soc_id.c | 28 +-
drivers/firmware/sysfb_simplefb.c | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 26 +-
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 8 +-
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 36 +-
drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c | 21 +-
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 51 +-
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 5 +
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 2 +-
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 2 +-
drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 55 +-
drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 7 +-
drivers/gpu/drm/amd/display/dc/core/dc.c | 47 +-
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 3 +-
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 5 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 3 +-
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c | 2 +-
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 2 +-
.../amd/display/dc/dcn32/dcn32_resource_helpers.c | 43 +-
.../amd/display/dc/dml/dcn30/display_mode_vba_30.c | 2 +-
.../amd/display/dc/dml/dcn31/display_mode_vba_31.c | 300 +++++----
.../gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c | 4 +
.../display/dc/dml/dcn314/display_mode_vba_314.c | 300 +++++----
.../amd/display/dc/dml/dcn32/display_mode_vba_32.c | 2 +-
.../amd/include/asic_reg/oss/osssys_4_2_0_offset.h | 6 +
.../include/asic_reg/oss/osssys_4_2_0_sh_mask.h | 11 +
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 18 +
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 20 +-
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 1 +
drivers/gpu/drm/drm_displayid.c | 17 +-
drivers/gpu/drm/drm_fb_helper.c | 16 +-
drivers/gpu/drm/drm_mipi_dsi.c | 2 +-
drivers/gpu/drm/exynos/exynos_drm_g2d.h | 4 +-
drivers/gpu/drm/i915/Kconfig | 12 +-
drivers/gpu/drm/i915/display/intel_atomic_plane.c | 4 +-
drivers/gpu/drm/i915/display/intel_dp.c | 5 +
drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c | 7 +-
drivers/gpu/drm/i915/i915_pci.c | 6 +
.../gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h | 202 +++++++
.../gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 177 ++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 671 ++++++---------------
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 21 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 23 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 5 -
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 18 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 4 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h | 3 -
drivers/gpu/drm/msm/dp/dp_audio.c | 12 +
drivers/gpu/drm/msm/dp/dp_audio.h | 2 +
drivers/gpu/drm/msm/dp/dp_aux.c | 80 ++-
drivers/gpu/drm/msm/dp/dp_catalog.c | 2 +-
drivers/gpu/drm/msm/dp/dp_catalog.h | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 1 +
drivers/gpu/drm/msm/msm_gem_submit.c | 25 +-
drivers/gpu/drm/nouveau/include/nvif/if0012.h | 4 +-
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 3 +-
drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 2 +-
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 +
drivers/gpu/drm/scheduler/sched_main.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 2 +-
drivers/hid/hid-apple.c | 19 +-
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-input.c | 2 +
drivers/hid/hid-logitech-hidpp.c | 53 +-
drivers/hid/wacom_wac.c | 33 +-
drivers/hwmon/nzxt-smart2.c | 3 +-
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 11 +
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 57 +-
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 18 +
drivers/infiniband/core/user_mad.c | 23 +-
drivers/infiniband/hw/mlx5/mr.c | 6 +-
drivers/input/joystick/xpad.c | 5 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 19 +-
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 26 +-
drivers/iommu/sprd-iommu.c | 29 +-
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-gic-v3.c | 115 +++-
drivers/mcb/mcb-pci.c | 27 +-
drivers/md/md.c | 18 +-
drivers/media/pci/cx23885/cx23885-core.c | 4 +-
drivers/media/pci/cx23885/cx23885-video.c | 13 +-
drivers/media/pci/intel/ipu3/cio2-bridge.c | 15 +-
drivers/media/pci/intel/ipu3/cio2-bridge.h | 3 +-
drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 2 +-
drivers/media/pci/tw68/tw68-video.c | 16 +-
.../platform/mediatek/vcodec/mtk_vcodec_dec.c | 7 +
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 5 +
drivers/media/platform/renesas/vsp1/vsp1_drm.c | 18 +-
drivers/media/platform/renesas/vsp1/vsp1_entity.c | 11 +-
.../platform/samsung/exynos4-is/fimc-capture.c | 7 +-
drivers/media/platform/ti/am437x/am437x-vpfe.c | 15 +-
drivers/media/platform/ti/cal/cal-video.c | 8 +-
drivers/media/usb/dvb-usb/cxusb-analog.c | 14 +-
drivers/media/usb/pvrusb2/Kconfig | 3 +-
drivers/memstick/host/r592.c | 2 +-
drivers/message/fusion/mptlan.c | 2 +
drivers/mfd/dln2.c | 1 +
drivers/mfd/intel-lpss-pci.c | 15 +
drivers/mfd/intel_soc_pmic_chtwc.c | 14 +-
drivers/misc/lkdtm/stackleak.c | 6 +
drivers/net/bonding/bond_netlink.c | 7 +-
drivers/net/bonding/bond_options.c | 8 +-
drivers/net/can/dev/skb.c | 3 +-
drivers/net/can/kvaser_pciefd.c | 51 +-
drivers/net/dsa/mv88e6xxx/port.h | 2 +-
drivers/net/dsa/rzn1_a5psw.c | 83 ++-
drivers/net/dsa/rzn1_a5psw.h | 3 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2 +-
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 +-
drivers/net/ethernet/freescale/fec_main.c | 16 +-
drivers/net/ethernet/google/gve/gve_main.c | 13 -
.../hisilicon/hns3/hns3_common/hclge_comm_cmd.c | 25 +-
.../hisilicon/hns3/hns3_common/hclge_comm_cmd.h | 8 +-
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 2 +-
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h | 1 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 15 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 4 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 5 +
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 5 +-
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 5 -
drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 5 +-
drivers/net/ethernet/intel/ice/ice_lib.c | 5 +
drivers/net/ethernet/intel/ice/ice_sriov.c | 8 +-
drivers/net/ethernet/intel/ice/ice_txrx.c | 8 +-
drivers/net/ethernet/intel/ice/ice_txrx.h | 9 +-
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 19 +
drivers/net/ethernet/intel/ice/ice_vf_lib.h | 1 +
drivers/net/ethernet/intel/ice/ice_virtchnl.c | 1 +
drivers/net/ethernet/intel/igb/e1000_mac.c | 4 +-
.../net/ethernet/mellanox/mlx5/core/en/params.c | 3 +-
.../net/ethernet/mellanox/mlx5/core/en_common.c | 2 +-
drivers/net/ethernet/mscc/vsc7514_regs.c | 18 +-
drivers/net/ethernet/netronome/nfp/nic/main.h | 2 +-
drivers/net/ethernet/pasemi/pasemi_mac.c | 2 +-
drivers/net/ethernet/sfc/ef100_netdev.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 5 +
drivers/net/ethernet/sun/cassini.c | 2 +
drivers/net/ipvlan/ipvlan_core.c | 6 +
drivers/net/mdio/mdio-mvusb.c | 11 +-
drivers/net/pcs/pcs-xpcs.c | 2 +-
drivers/net/phy/bcm-phy-lib.h | 5 +
drivers/net/phy/bcm7xxx.c | 2 +-
drivers/net/phy/dp83867.c | 22 +-
drivers/net/tap.c | 4 +-
drivers/net/tun.c | 15 +
drivers/net/virtio_net.c | 61 +-
drivers/net/wireless/ath/ath.h | 12 +-
drivers/net/wireless/ath/ath11k/dp.c | 4 +-
drivers/net/wireless/ath/ath11k/dp_rx.c | 17 +-
drivers/net/wireless/ath/ath11k/peer.h | 1 +
drivers/net/wireless/ath/ath12k/dp_rx.c | 3 +
drivers/net/wireless/ath/ath12k/pci.c | 47 +-
drivers/net/wireless/ath/ath12k/pci.h | 6 +
drivers/net/wireless/ath/ath12k/qmi.c | 4 +-
drivers/net/wireless/ath/key.c | 2 +-
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 +
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 13 +-
.../wireless/broadcom/brcm80211/brcmfmac/chip.c | 2 +
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 51 ++
.../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 11 +
.../broadcom/brcm80211/include/brcm_hw_ids.h | 2 +
drivers/net/wireless/intel/iwlwifi/dvm/sta.c | 5 +-
drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 19 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 +-
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 10 +
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 37 +-
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 +
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 +-
.../net/wireless/mediatek/mt76/mt76_connac2_mac.h | 2 +-
.../net/wireless/mediatek/mt76/mt76_connac_mac.c | 3 +-
drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 3 +
drivers/net/wireless/realtek/rtw88/mac80211.c | 2 +-
drivers/net/wireless/realtek/rtw88/main.c | 15 +
drivers/net/wireless/realtek/rtw88/main.h | 3 +
drivers/net/wireless/realtek/rtw88/usb.c | 3 +-
drivers/net/wireless/realtek/rtw88/usb.h | 2 +-
drivers/net/wwan/iosm/iosm_ipc_imem.c | 27 +-
drivers/net/wwan/iosm/iosm_ipc_imem_ops.c | 12 +-
drivers/net/wwan/iosm/iosm_ipc_imem_ops.h | 6 +-
drivers/parisc/power.c | 16 +-
drivers/phy/st/phy-miphy28lp.c | 42 +-
drivers/pinctrl/pinctrl-at91.c | 23 +-
drivers/platform/x86/amd/pmc.c | 1 +
drivers/platform/x86/intel/vsec.c | 69 +--
drivers/platform/x86/intel/vsec.h | 9 +-
drivers/platform/x86/x86-android-tablets.c | 101 +++-
drivers/power/supply/axp288_charger.c | 15 +-
drivers/remoteproc/imx_dsp_rproc.c | 187 +++++-
drivers/remoteproc/stm32_rproc.c | 8 +
drivers/s390/block/dasd_eckd.c | 33 +-
drivers/s390/cio/device.c | 2 +
drivers/s390/cio/qdio.h | 2 +-
drivers/scsi/hisi_sas/hisi_sas.h | 3 +-
drivers/scsi/hisi_sas/hisi_sas_main.c | 25 +-
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2 +-
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +-
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +-
drivers/scsi/lpfc/lpfc_debugfs.c | 7 +-
drivers/scsi/lpfc/lpfc_els.c | 24 +-
drivers/scsi/scsi_lib.c | 3 +-
drivers/scsi/storvsc_drv.c | 8 +-
drivers/soundwire/bus.c | 15 +-
drivers/soundwire/dmi-quirks.c | 25 +
drivers/soundwire/qcom.c | 3 +
drivers/spi/spi-imx.c | 24 +-
drivers/spi/spi-intel-pci.c | 1 +
drivers/staging/axis-fifo/axis-fifo.c | 28 +-
drivers/staging/media/imx/imx-media-capture.c | 12 +-
drivers/staging/media/imx/imx-media-utils.c | 8 +-
drivers/staging/media/omap4iss/iss_video.c | 6 +-
drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 6 +-
drivers/staging/rtl8192e/rtl8192e/rtl_core.h | 5 -
drivers/target/iscsi/iscsi_target.c | 6 +-
drivers/thunderbolt/nhi.c | 29 +-
drivers/thunderbolt/nhi_regs.h | 2 +
drivers/tty/serial/8250/8250_bcm7271.c | 7 +-
drivers/tty/serial/8250/8250_core.c | 1 +
drivers/tty/serial/8250/8250_exar.c | 17 +
drivers/tty/serial/8250/8250_pci.c | 5 +
drivers/tty/serial/arc_uart.c | 7 +-
drivers/tty/serial/qcom_geni_serial.c | 9 +-
drivers/tty/vt/vc_screen.c | 11 +-
drivers/ufs/core/ufshcd.c | 10 +-
drivers/ufs/host/ufshcd-pci.c | 1 +
drivers/usb/class/usbtmc.c | 2 +
drivers/usb/dwc3/debugfs.c | 109 ++++
drivers/usb/dwc3/gadget.c | 67 +-
drivers/usb/gadget/function/u_ether.c | 3 +
drivers/usb/gadget/udc/core.c | 151 ++---
drivers/usb/host/uhci-pci.c | 10 +-
drivers/usb/host/xhci-mem.c | 9 +-
drivers/usb/host/xhci-pci.c | 12 +-
drivers/usb/host/xhci-ring.c | 29 +-
drivers/usb/host/xhci.h | 2 +-
drivers/usb/storage/scsiglue.c | 28 +-
drivers/usb/typec/altmodes/displayport.c | 4 +
drivers/usb/typec/tcpm/tcpm.c | 16 +-
drivers/usb/typec/ucsi/ucsi_acpi.c | 44 +-
drivers/video/fbdev/arcfb.c | 15 +-
fs/ceph/snap.c | 13 +
fs/cifs/cifsglob.h | 4 +-
fs/cifs/connect.c | 8 +-
fs/cifs/file.c | 26 +-
fs/cifs/smb1ops.c | 9 +-
fs/cifs/smb2ops.c | 7 +-
fs/ext2/ext2.h | 1 +
fs/ext2/super.c | 7 +
fs/ext4/balloc.c | 18 +-
fs/ext4/ext4.h | 15 +-
fs/ext4/ialloc.c | 12 +-
fs/ext4/mballoc.c | 131 ++--
fs/ext4/mmp.c | 9 +-
fs/ext4/super.c | 24 +-
fs/f2fs/checkpoint.c | 22 +-
fs/f2fs/data.c | 7 +-
fs/f2fs/extent_cache.c | 22 +-
fs/f2fs/f2fs.h | 5 +
fs/f2fs/gc.c | 10 +-
fs/f2fs/gc.h | 2 +
fs/f2fs/segment.h | 39 +-
fs/f2fs/super.c | 2 +-
fs/gfs2/glops.c | 3 +-
fs/hfsplus/inode.c | 28 +-
fs/ksmbd/connection.c | 3 +-
fs/ksmbd/oplock.c | 5 +-
fs/ksmbd/oplock.h | 2 +-
fs/ksmbd/smb2misc.c | 5 +-
fs/ksmbd/smb2pdu.c | 19 +-
fs/nilfs2/inode.c | 18 +
fs/ntfs3/frecord.c | 5 +-
fs/ntfs3/fsntfs.c | 1 +
fs/ntfs3/index.c | 11 +-
fs/ntfs3/inode.c | 6 +
fs/ntfs3/record.c | 9 +-
fs/open.c | 18 +-
fs/statfs.c | 4 +-
include/drm/display/drm_dp.h | 4 +-
include/linux/arm-smccc.h | 18 +
include/linux/cpuhotplug.h | 1 -
include/linux/dim.h | 3 +-
include/linux/if_vlan.h | 17 +
include/linux/netdevice.h | 1 +
include/linux/sched/task_stack.h | 2 +-
include/linux/sunrpc/svc_rdma.h | 2 +-
include/linux/sunrpc/svc_xprt.h | 2 +-
include/net/bluetooth/hci.h | 15 +
include/net/bonding.h | 2 +-
include/net/ip_vs.h | 6 +-
include/net/pkt_sched.h | 2 +
include/net/sock.h | 2 +-
include/uapi/asm-generic/fcntl.h | 1 -
kernel/bpf/bpf_local_storage.c | 16 +-
kernel/bpf/verifier.c | 4 +
kernel/events/core.c | 14 +-
kernel/rcu/refscale.c | 2 +-
kernel/rcu/tree_exp.h | 6 +-
kernel/time/tick-broadcast.c | 120 +++-
kernel/trace/rethook.c | 4 +-
lib/cpu_rmap.c | 5 +-
lib/dim/dim.c | 5 +-
lib/dim/net_dim.c | 3 +-
lib/dim/rdma_dim.c | 3 +-
lib/maple_tree.c | 12 +-
mm/zswap.c | 16 +
net/8021q/vlan_dev.c | 4 +-
net/bluetooth/hci_event.c | 9 +-
net/bluetooth/hci_sync.c | 6 +-
net/bluetooth/l2cap_core.c | 1 -
net/bridge/br_forward.c | 2 +-
net/bridge/br_private_tunnel.h | 8 +-
net/can/isotp.c | 2 +-
net/can/j1939/socket.c | 2 +-
net/core/datagram.c | 15 +-
net/core/dev.c | 4 +-
net/core/skbuff.c | 4 +-
net/core/stream.c | 12 +-
net/devlink/core.c | 16 +-
net/devlink/devl_internal.h | 1 -
net/devlink/leftover.c | 5 +-
net/ipv4/af_inet.c | 2 +-
net/ipv4/tcp.c | 14 +-
net/ipv4/tcp_bpf.c | 2 +-
net/ipv4/tcp_input.c | 4 +-
net/ipv4/tcp_ipv4.c | 5 +-
net/ipv6/ip6_gre.c | 13 +-
net/key/af_key.c | 12 +-
net/llc/af_llc.c | 8 +-
net/mac80211/cfg.c | 7 +-
net/mac80211/trace.h | 2 +-
net/mac80211/tx.c | 5 +-
net/netfilter/core.c | 6 +-
net/netfilter/ipvs/ip_vs_sync.c | 2 +-
net/netfilter/nf_conntrack_standalone.c | 3 +-
net/netfilter/nf_tables_api.c | 4 +-
net/netfilter/nft_chain_filter.c | 9 +-
net/netfilter/nft_set_rbtree.c | 20 +-
net/netlink/af_netlink.c | 8 +-
net/nsh/nsh.c | 8 +-
net/packet/af_packet.c | 6 +-
net/sched/sch_mqprio.c | 5 +-
net/sched/sch_taprio.c | 12 +-
net/smc/smc_close.c | 4 +-
net/smc/smc_rx.c | 4 +-
net/smc/smc_tx.c | 4 +-
net/socket.c | 2 +-
net/sunrpc/svc.c | 19 +-
net/sunrpc/svc_xprt.c | 24 +-
net/sunrpc/svcsock.c | 30 +-
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 11 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 2 +-
net/tipc/bearer.c | 17 +-
net/tipc/bearer.h | 3 +
net/tipc/link.c | 9 +-
net/tipc/socket.c | 4 +-
net/tipc/udp_media.c | 5 +-
net/tls/tls_main.c | 3 +-
net/unix/af_unix.c | 22 +-
net/vmw_vsock/af_vsock.c | 2 +-
net/wireless/scan.c | 6 +-
net/xfrm/xfrm_device.c | 2 +-
net/xfrm/xfrm_interface_core.c | 54 +-
net/xfrm/xfrm_policy.c | 9 -
net/xfrm/xfrm_user.c | 15 +-
samples/bpf/hbm.c | 1 +
scripts/recordmcount.c | 6 +-
sound/firewire/digi00x/digi00x-stream.c | 4 +-
sound/pci/hda/hda_generic.c | 7 +-
sound/pci/hda/hda_intel.c | 3 +
sound/pci/hda/patch_hdmi.c | 5 +
sound/pci/hda/patch_realtek.c | 14 +-
sound/soc/amd/Kconfig | 2 +
sound/soc/amd/ps/acp63.h | 2 +
sound/soc/amd/ps/pci-ps.c | 8 +-
sound/soc/amd/yc/acp6x-mach.c | 21 +
sound/soc/amd/yc/acp6x.h | 3 +
sound/soc/amd/yc/pci-acp6x.c | 8 +-
sound/soc/fsl/fsl_micfil.c | 14 +-
sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 6 -
sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 1 -
sound/soc/mediatek/mt8186/mt8186-afe-pcm.c | 4 -
sound/soc/mediatek/mt8186/mt8186-audsys-clk.c | 46 +-
sound/soc/mediatek/mt8186/mt8186-audsys-clk.h | 1 -
sound/soc/sof/ipc3-topology.c | 7 +-
sound/soc/sof/topology.c | 4 +
sound/usb/format.c | 1 +
tools/include/uapi/asm-generic/fcntl.h | 1 -
tools/perf/builtin-script.c | 7 +
.../cpupower/utils/idle_monitor/mperf_monitor.c | 31 +-
tools/testing/selftests/cgroup/test_memcontrol.c | 15 +
tools/testing/selftests/kvm/lib/x86_64/processor.c | 1 +
tools/testing/selftests/net/fib_nexthops.sh | 2 +-
.../selftests/net/srv6_end_dt4_l3vpn_test.sh | 17 +-
virt/kvm/kvm_main.c | 16 +-
466 files changed, 5174 insertions(+), 2479 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 6.3 055/364] accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release()
2023-05-22 19:05 1% [PATCH 6.3 000/364] 6.3.4-rc1 review Greg Kroah-Hartman
@ 2023-05-22 19:06 10% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-05-22 19:06 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Tomer Tayar, Oded Gabbay, Sasha Levin
From: Tomer Tayar <ttayar@habana.ai>
[ Upstream commit 2e8e9a895c4589f124a37fc84d123b5114406e94 ]
The memory manager IDR is currently destroyed when user releases the
file descriptor.
However, at this point the user context might be still held, and memory
buffers might be still in use.
Later on, calls to release those buffers will fail due to not finding
their handles in the IDR, leading to a memory leak.
To avoid this leak, split the IDR destruction from the memory manager
fini, and postpone it to hpriv_release() when there is no user context
and no buffers are used.
Signed-off-by: Tomer Tayar <ttayar@habana.ai>
Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/accel/habanalabs/common/device.c | 9 +++++++++
drivers/accel/habanalabs/common/habanalabs.h | 1 +
drivers/accel/habanalabs/common/habanalabs_drv.c | 1 +
drivers/accel/habanalabs/common/memory_mgr.c | 13 ++++++++++++-
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/accel/habanalabs/common/device.c b/drivers/accel/habanalabs/common/device.c
index 9933e5858a363..c91436609f080 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -423,6 +423,9 @@ static void hpriv_release(struct kref *ref)
mutex_destroy(&hpriv->ctx_lock);
mutex_destroy(&hpriv->restore_phase_mutex);
+ /* There should be no memory buffers at this point and handles IDR can be destroyed */
+ hl_mem_mgr_idr_destroy(&hpriv->mem_mgr);
+
/* Device should be reset if reset-upon-device-release is enabled, or if there is a pending
* reset that waits for device release.
*/
@@ -514,6 +517,10 @@ static int hl_device_release(struct inode *inode, struct file *filp)
}
hl_ctx_mgr_fini(hdev, &hpriv->ctx_mgr);
+
+ /* Memory buffers might be still in use at this point and thus the handles IDR destruction
+ * is postponed to hpriv_release().
+ */
hl_mem_mgr_fini(&hpriv->mem_mgr);
hdev->compute_ctx_in_release = 1;
@@ -887,6 +894,7 @@ static int device_early_init(struct hl_device *hdev)
free_cb_mgr:
hl_mem_mgr_fini(&hdev->kernel_mem_mgr);
+ hl_mem_mgr_idr_destroy(&hdev->kernel_mem_mgr);
free_chip_info:
kfree(hdev->hl_chip_info);
free_prefetch_wq:
@@ -930,6 +938,7 @@ static void device_early_fini(struct hl_device *hdev)
mutex_destroy(&hdev->clk_throttling.lock);
hl_mem_mgr_fini(&hdev->kernel_mem_mgr);
+ hl_mem_mgr_idr_destroy(&hdev->kernel_mem_mgr);
kfree(hdev->hl_chip_info);
diff --git a/drivers/accel/habanalabs/common/habanalabs.h b/drivers/accel/habanalabs/common/habanalabs.h
index fa05e76d3d21a..829b30ab1961a 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -3861,6 +3861,7 @@ const char *hl_sync_engine_to_string(enum hl_sync_engine_type engine_type);
void hl_mem_mgr_init(struct device *dev, struct hl_mem_mgr *mmg);
void hl_mem_mgr_fini(struct hl_mem_mgr *mmg);
+void hl_mem_mgr_idr_destroy(struct hl_mem_mgr *mmg);
int hl_mem_mgr_mmap(struct hl_mem_mgr *mmg, struct vm_area_struct *vma,
void *args);
struct hl_mmap_mem_buf *hl_mmap_mem_buf_get(struct hl_mem_mgr *mmg,
diff --git a/drivers/accel/habanalabs/common/habanalabs_drv.c b/drivers/accel/habanalabs/common/habanalabs_drv.c
index 03dae57dc8386..e3781cfe8a7fe 100644
--- a/drivers/accel/habanalabs/common/habanalabs_drv.c
+++ b/drivers/accel/habanalabs/common/habanalabs_drv.c
@@ -237,6 +237,7 @@ int hl_device_open(struct inode *inode, struct file *filp)
out_err:
mutex_unlock(&hdev->fpriv_list_lock);
hl_mem_mgr_fini(&hpriv->mem_mgr);
+ hl_mem_mgr_idr_destroy(&hpriv->mem_mgr);
hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
filp->private_data = NULL;
mutex_destroy(&hpriv->ctx_lock);
diff --git a/drivers/accel/habanalabs/common/memory_mgr.c b/drivers/accel/habanalabs/common/memory_mgr.c
index 0f2759e265477..f8e8261cc83d8 100644
--- a/drivers/accel/habanalabs/common/memory_mgr.c
+++ b/drivers/accel/habanalabs/common/memory_mgr.c
@@ -341,8 +341,19 @@ void hl_mem_mgr_fini(struct hl_mem_mgr *mmg)
"%s: Buff handle %u for CTX is still alive\n",
topic, id);
}
+}
- /* TODO: can it happen that some buffer is still in use at this point? */
+/**
+ * hl_mem_mgr_idr_destroy() - destroy memory manager IDR.
+ * @mmg: parent unified memory manager
+ *
+ * Destroy the memory manager IDR.
+ * Shall be called when IDR is empty and no memory buffers are in use.
+ */
+void hl_mem_mgr_idr_destroy(struct hl_mem_mgr *mmg)
+{
+ if (!idr_is_empty(&mmg->handles))
+ dev_crit(mmg->dev, "memory manager IDR is destroyed while it is not empty!\n");
idr_destroy(&mmg->handles);
}
--
2.39.2
^ permalink raw reply related [relevance 10%]
* [PATCH 6.3 000/364] 6.3.4-rc1 review
@ 2023-05-22 19:05 1% Greg Kroah-Hartman
2023-05-22 19:06 10% ` [PATCH 6.3 055/364] accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release() Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2023-05-22 19:05 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, srw, rwarsow
This is the start of the stable review cycle for the 6.3.4 release.
There are 364 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 24 May 2023 19:03:25 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.3.4-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.3.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 6.3.4-rc1
Wenchao Hao <haowenchao2@huawei.com>
scsi: Revert "scsi: core: Do not increase scsi_device's iorequest_cnt if dispatch failed"
Li Ma <li.ma@amd.com>
drm/amdgpu: reserve the old gc_11_0_*_mes.bin
Jack Xiao <Jack.Xiao@amd.com>
drm/amd/amdgpu: introduce gc_*_mes_2.bin v2
Ard Biesheuvel <ardb@kernel.org>
ARM: 9297/1: vfp: avoid unbalanced stack on 'success' return path
Ard Biesheuvel <ardb@kernel.org>
ARM: 9294/2: vfp: Fix broken softirq handling with instrumentation enabled
Mathieu Poirier <mathieu.poirier@linaro.org>
remoteproc: imx_dsp_rproc: Fix kernel test robot sparse warning
Ze Gao <zegao2021@gmail.com>
rethook, fprobe: do not trace rethook related functions
Ze Gao <zegao2021@gmail.com>
rethook: use preempt_{disable, enable}_notrace in rethook_trampoline_handler
Peter Collingbourne <pcc@google.com>
arm64: mte: Do not set PG_mte_tagged if tags were not initialized
Peter Collingbourne <pcc@google.com>
arm64: Also reset KASAN tag if page is not PG_mte_tagged
Heiko Carstens <hca@linux.ibm.com>
s390/qdio: fix do_sqbs() inline assembly constraint
Heiko Carstens <hca@linux.ibm.com>
s390/crypto: use vector instructions only if available for ChaCha20
Stefan Haberland <sth@linux.ibm.com>
s390/dasd: fix command reject error on ESE devices
Ryusuke Konishi <konishi.ryusuke@gmail.com>
nilfs2: fix use-after-free bug of nilfs_root in nilfs_evict_inode()
Huayu Chen <huayu.chen@corigine.com>
nfp: fix NFP_NET_MAX_DSCP definition error
Hari Bathini <hbathini@linux.ibm.com>
powerpc/bpf: populate extable entries only during the last pass
Michael Ellerman <mpe@ellerman.id.au>
powerpc/64s/radix: Fix soft dirty tracking
Jerry Snitselaar <jsnitsel@redhat.com>
tpm/tpm_tis: Disable interrupts for more Lenovo devices
Gaurav Batra <gbatra@linux.vnet.ibm.com>
powerpc/iommu: Incorrect DDW Table is referenced for SR-IOV device
Gaurav Batra <gbatra@linux.vnet.ibm.com>
powerpc/iommu: DMA address offset is incorrectly calculated with 2MB TCEs
Michal Simek <michal.simek@amd.com>
dt-bindings: ata: ahci-ceva: Cover all 4 iommus entries
Rob Clark <robdclark@chromium.org>
iommu/arm-smmu-qcom: Fix missing adreno_smmu's
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gfx11: update gpu_clock_counter logic
Tong Liu01 <Tong.Liu01@amd.com>
drm/amdgpu: refine get gpu clock counter method
Guilherme G. Piccoli <gpiccoli@igalia.com>
drm/amdgpu/gfx11: Adjust gfxoff before powergating on gfx11 as well
Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
drm/amdgpu/gfx10: Disable gfxoff before disabling powergating.
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gmc11: implement get_vbios_fb_size()
Evan Quan <evan.quan@amd.com>
drm/amd/pm: fix possible power mode mismatch between driver and PMFW
Xiubo Li <xiubli@redhat.com>
ceph: force updating the msg pointer in non-split case
George Kennedy <george.kennedy@oracle.com>
vc_screen: reload load of struct vc_data pointer in vcs_write() to avoid UAF
Mario Limonciello <mario.limonciello@amd.com>
thunderbolt: Clear registers properly when auto clear isn't in use
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
serial: qcom-geni: fix enabling deactivated interrupt
Andrew Davis <afd@ti.com>
serial: 8250_exar: Add support for USR298x PCI Modems
Vitaliy Tomin <tomin@iszf.irk.ru>
serial: Add support for Advantech PCI-1611U card
Sandipan Das <sandipan.das@amd.com>
perf script: Skip aggregation for stat events
Domenico Cerasuolo <cerasuolodomenico@gmail.com>
mm: fix zswap writeback race condition
Peng Zhang <zhangpeng.00@bytedance.com>
maple_tree: make maple state reusable after mas_empty_area()
Ilya Leoshkevich <iii@linux.ibm.com>
statfs: enforce statfs[64] structure initialization
Michal Luczaj <mhal@rbox.co>
KVM: Fix vcpu_array[0] races
Oliver Upton <oliver.upton@linux.dev>
KVM: arm64: Infer the PA offset from IPA in stage-2 map walker
Chih-Yen Chang <cc85nod@gmail.com>
ksmbd: fix global-out-of-bounds in smb2_find_context_vals
Chih-Yen Chang <cc85nod@gmail.com>
ksmbd: fix wrong UserName check in session_user
Chih-Yen Chang <cc85nod@gmail.com>
ksmbd: allocate one more byte for implied bcc[0]
Gustav Johansson <gustajo@axis.com>
ksmbd: smb2: Allow messages padded to 8byte boundary
Bharath SM <bharathsm@microsoft.com>
SMB3: drop reference to cfile before sending oplock break
Bharath SM <bharathsm@microsoft.com>
SMB3: Close all deferred handles of inode in case of handle lease break
Ping-Ke Shih <pkshih@realtek.com>
wifi: rtw88: correct qsel_to_ep[] type as int
Ping-Ke Shih <pkshih@realtek.com>
wifi: rtw88: use work to update rate to avoid RCU warning
Hans de Goede <hdegoede@redhat.com>
wifi: brcmfmac: Check for probe() id argument being NULL
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Disable interrupts in probe error path
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Do not send EFLUSH command on TFD interrupt
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Clear listen-only bit if not explicitly requested
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Empty SRB buffer in probe
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Call request_irq() before enabling interrupts
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Set CAN_STATE_STOPPED in kvaser_pciefd_stop()
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: recvmsg(): allow MSG_CMSG_COMPAT flag
Oliver Hartkopp <socketcan@hartkopp.net>
can: j1939: recvmsg(): allow MSG_CMSG_COMPAT flag
Kai-Heng Feng <kai.heng.feng@canonical.com>
ALSA: hda/realtek: Fix mute and micmute LEDs for yet another HP laptop
Vitaly Rodionov <vitalyr@opensource.cirrus.com>
ALSA: hda/realtek: Add quirk for HP EliteBook G10 laptops
Luke D. Jones <luke@ljones.dev>
ALSA: hda/realtek: Add quirk for 2nd ASUS GU603
Ai Chao <aichao@kylinos.cn>
ALSA: hda/realtek: Add a quirk for HP EliteDesk 805
Jeremy Soller <jeremy@system76.com>
ALSA: hda/realtek: Add quirk for Clevo L140AU
Nikhil Mahale <nmahale@nvidia.com>
ALSA: hda: Add NVIDIA codec IDs a3 through a7 to patch table
Takashi Iwai <tiwai@suse.de>
ALSA: hda: Fix Oops by 9.1 surround channel names
Mathias Nyman <mathias.nyman@linux.intel.com>
xhci: Fix incorrect tracking of free space on transfer rings
Mario Limonciello <mario.limonciello@amd.com>
xhci-pci: Only run d3cold avoidance quirk for s2idle
Francesco Dolcini <francesco.dolcini@toradex.com>
Revert "usb: gadget: udc: core: Invoke usb_gadget_connect only when started"
Francesco Dolcini <francesco.dolcini@toradex.com>
Revert "usb: gadget: udc: core: Prevent redundant calls to pullup"
Badhri Jagan Sridharan <badhri@google.com>
usb: typec: altmodes/displayport: fix pin_assignment_show
Konrad Gräfe <k.graefe@gateware.de>
usb: gadget: u_ether: Fix host MAC address case
Udipto Goswami <quic_ugoswami@quicinc.com>
usb: dwc3: debugfs: Resume dwc3 before accessing registers
Roger Quadros <rogerq@kernel.org>
usb: dwc3: gadget: Improve dwc3_gadget_suspend() and dwc3_gadget_resume()
Weitao Wang <WeitaoWang-oc@zhaoxin.com>
USB: UHCI: adjust zhaoxin UHCI controllers OverCurrent bit value
Maxime Bizon <mbizon@freebox.fr>
usb-storage: fix deadlock when a scsi command timeouts more than once
Alan Stern <stern@rowland.harvard.edu>
USB: usbtmc: Fix direction for 0-length ioctl control messages
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Add a sample rate workaround for Line6 Pod Go
Arnd Bergmann <arnd@arndb.de>
bridge: always declare tunnel functions
Florian Westphal <fw@strlen.de>
netfilter: nft_set_rbtree: fix null deref on element insertion
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: fix nft_trans type confusion
Benjamin Poirier <bpoirier@nvidia.com>
net: selftests: Fix optstring
Vladimir Oltean <vladimir.oltean@nxp.com>
net: pcs: xpcs: fix C73 AN not getting enabled
M Chetan Kumar <m.chetan.kumar@linux.intel.com>
net: wwan: iosm: fix NULL pointer dereference when removing device
Eric Dumazet <edumazet@google.com>
vlan: fix a potential uninit-value in vlan_dev_hard_start_xmit()
Aleksandr Loktionov <aleksandr.loktionov@intel.com>
igb: fix bit_shift to be in [1..8] range
Marco Migliore <m.migliore@tiesse.com>
net: dsa: mv88e6xxx: Fix mv88e6393x EPC write command offset
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cassini: Fix a memory leak in the error handling path of cas_init_one()
Kuniyuki Iwashima <kuniyu@amazon.com>
tun: Fix memory leak for detached NAPI queue.
Ido Schimmel <idosch@nvidia.com>
devlink: Fix crash with CONFIG_NET_NS=n
Michael Kelley <mikelley@microsoft.com>
scsi: storvsc: Don't pass unused PFNs to Hyper-V host
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: mvm: don't trust firmware n_channels
Alon Giladi <alon.giladi@intel.com>
wifi: iwlwifi: mvm: fix OEM's name in the tas approved list
Alon Giladi <alon.giladi@intel.com>
wifi: iwlwifi: fix OEM's name in the ppag approved list
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: fw: fix DBGI dump
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: mvm: fix cancel_delayed_work_sync() deadlock
Michael Lee <michael-cy.lee@mediatek.com>
wifi: mac80211: Abort running color change when stopping the AP
Johannes Berg <johannes.berg@intel.com>
wifi: mac80211: fix min center freq offset tracing
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
wifi: mac80211: Fix puncturing bitmap handling in __ieee80211_csa_finalize()
Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
wifi: mac80211: fortify the spinlock against deadlock by interrupt
Ilan Peer <ilan.peer@intel.com>
wifi: cfg80211: Drop entries with invalid BSSIDs in RNR
Ahmed Zaki <ahmed.zaki@intel.com>
iavf: send VLAN offloading caps once after VFR
Dawid Wesierski <dawidx.wesierski@intel.com>
ice: Fix ice VF reset during iavf initialization
Ahmed Zaki <ahmed.zaki@intel.com>
ice: Fix stats after PF reset
Florian Fainelli <f.fainelli@gmail.com>
net: bcmgenet: Restore phy_stop() depending upon suspend/close
Florian Fainelli <f.fainelli@gmail.com>
net: bcmgenet: Remove phy_stop() from bcmgenet_netif_stop()
Oliver Hartkopp <socketcan@hartkopp.net>
can: dev: fix missing CAN XL support in can_put_echo_skb()
Vineeth Vijayan <vneethv@linux.ibm.com>
s390/cio: include subchannels without devices also for evaluation
Xin Long <lucien.xin@gmail.com>
tipc: check the bearer min mtu properly when setting it by netlink
Xin Long <lucien.xin@gmail.com>
tipc: do not update mtu if msg_max is too small in mtu negotiation
Xin Long <lucien.xin@gmail.com>
tipc: add tipc_bearer_min_mtu to calculate min mtu
Feng Liu <feliu@nvidia.com>
virtio_net: Fix error unwinding of XDP initialization
Shenwei Wang <shenwei.wang@nxp.com>
net: fec: remove the xdp_return_frame when lack of tx BDs
Dong Chenchen <dongchenchen2@huawei.com>
net: nsh: Use correct mac_offset to unwind gso skb in nsh_gso_segment()
Arnd Bergmann <arnd@arndb.de>
drm/exynos: fix g2d_open/close helper function definitions
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ASoC: SOF: topology: Fix logic for copying tuples
Douglas Anderson <dianders@chromium.org>
ASoC: mediatek: mt8186: Fix use-after-free in driver remove path
Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
ASoC: SOF: ipc3-topology: Make sure that only one cmd is sent in dai_config
Chuck Lever <chuck.lever@oracle.com>
SUNRPC: Fix trace_svc_register() call site
NeilBrown <neilb@suse.de>
SUNRPC: always free ctxt when freeing deferred request
NeilBrown <neilb@suse.de>
SUNRPC: double free xprt_ctxt while still in use
Duoming Zhou <duoming@zju.edu.cn>
media: netup_unidvb: fix use-after-free at del_timer()
Jijie Shao <shaojijie@huawei.com>
net: hns3: fix reset timeout when enable full VF
Jie Wang <wangjie125@huawei.com>
net: hns3: fix reset delay time to avoid configuration timeout
Jijie Shao <shaojijie@huawei.com>
net: hns3: fix sending pfc frames after reset issue
Jie Wang <wangjie125@huawei.com>
net: hns3: fix output information incomplete for dumping tx queue info with debugfs
Clément Léger <clement.leger@bootlin.com>
net: dsa: rzn1-a5psw: disable learning for standalone ports
Alexis Lothoré <alexis.lothore@bootlin.com>
net: dsa: rzn1-a5psw: fix STP states handling
Clément Léger <clement.leger@bootlin.com>
net: dsa: rzn1-a5psw: enable management frames for CPU port
Xin Long <lucien.xin@gmail.com>
erspan: get the proto with the md version for collect_md
Doug Berger <opendmb@gmail.com>
serial: 8250_bcm7271: fix leak in `brcmuart_probe`
Doug Berger <opendmb@gmail.com>
serial: 8250_bcm7271: balance clk_enable calls
Ke Zhang <m202171830@hust.edu.cn>
serial: arc_uart: fix of_iomap leak in `arc_serial_probe`
Arnd Bergmann <arnd@arndb.de>
media: pvrusb2: fix DVB_CORE dependency
Eric Dumazet <edumazet@google.com>
tcp: fix possible sk_priority leak in tcp_v4_send_reset()
Zhuang Shengen <zhuangshengen@huawei.com>
vsock: avoid to close connected socket after the timeout
Pieter Jansen van Vuuren <pieter.jansen-van-vuuren@amd.com>
sfc: disable RXFCS and RXALL features by default
Jan Sokolowski <jan.sokolowski@intel.com>
ice: Fix undersized tx_flags variable
Ryan C. Underwood <nemesis@icequake.net>
ALSA: hda/realtek: Apply HP B&O top speaker profile to Pavilion 15
Ryder Lee <ryder.lee@mediatek.com>
wifi: mt76: connac: fix stats->tx_bytes calculation
Dan Carpenter <dan.carpenter@linaro.org>
ALSA: firewire-digi00x: prevent potential use after free
Grygorii Strashko <grygorii.strashko@ti.com>
net: phy: dp83867: add w/a for packet errors seen with short cables
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
net: fec: Better handle pm_runtime_get() failing in .remove()
Jiri Pirko <jiri@resnulli.us>
devlink: change per-devlink netdev notifier to static one
Andrea Mayer <andrea.mayer@uniroma2.it>
selftets: seg6: disable rp_filter by default in srv6_end_dt4_l3vpn_test
Andrea Mayer <andrea.mayer@uniroma2.it>
selftests: seg6: disable DAD on IPv6 router cfg for srv6_end_dt4_l3vpn_test
Rob Clark <robdclark@chromium.org>
drm/msm: Fix submit error-path leaks
Tobias Brunner <tobias@strongswan.org>
af_key: Reject optional tunnel/BEET mode templates in outbound policies
Tobias Brunner <tobias@strongswan.org>
xfrm: Reject optional tunnel/BEET mode templates in outbound policies
Wyes Karny <wyes.karny@amd.com>
cpupower: Make TSC read per CPU for Mperf monitor
Shengjiu Wang <shengjiu.wang@nxp.com>
ASoC: fsl_micfil: Fix error handler with pm_runtime_enable
Chuck Lever <chuck.lever@oracle.com>
SUNRPC: Fix encoding of accepted but unsuccessful RPC replies
Jianhua Lu <lujianhua000@gmail.com>
dt-bindings: display/msm: dsi-controller-main: Document qcom, master-dsi and qcom, sync-dual-dsi
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Remove duplicate register defines from INTF
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Fix PP_BLK_DIPHER -> DITHER typo
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: split SM8550 catalog entry to the separate file
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: move UBWC/memory configuration to separate struct
Konrad Dybcio <konrad.dybcio@linaro.org>
drm/msm/dpu: Allow variable INTF_BLK size
Konrad Dybcio <konrad.dybcio@linaro.org>
drm/msm/dpu: Allow variable SSPP_BLK size
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: drop smart_dma_rev from dpu_caps
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dpu: populate SmartDMA features in hw catalog
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Reindent REV_7xxx interrupt masks with tabs
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Move non-MDP_TOP INTF_INTR offsets out of hwio header
Marijn Suijten <marijn.suijten@somainline.org>
drm/msm/dpu: Assign missing writeback log_mask
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
drm/msm/dp: unregister audio driver during unbind
Martin Willi <martin@strongswan.org>
Revert "Fix XFRM-I support for nested ESP tunnels"
Leon Romanovsky <leon@kernel.org>
xfrm: Fix leak of dev tracker
Leon Romanovsky <leon@kernel.org>
xfrm: release all offloaded policy memory
Sabrina Dubroca <sd@queasysnail.net>
xfrm: don't check the default policy if the policy allows the packet
Guilherme G. Piccoli <gpiccoli@igalia.com>
parisc: Replace regular spinlock with spin_trylock on panic path
Jarkko Nikula <jarkko.nikula@linux.intel.com>
mfd: intel-lpss: Add Intel Meteor Lake PCH-S LPSS PCI IDs
Qiang Ning <qning0106@126.com>
mfd: dln2: Fix memory leak in dln2_probe()
Hans de Goede <hdegoede@redhat.com>
mfd: intel_soc_pmic_chtwc: Add Lenovo Yoga Book X90F to intel_cht_wc_models
Richard Fitzgerald <rf@opensource.cirrus.com>
soundwire: bus: Fix unbalanced pm_runtime_put() causing usage count underflow
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
soundwire: qcom: gracefully handle too many ports in DT
Alain Volmat <avolmat@me.com>
phy: st: miphy28lp: use _poll_timeout functions for waits
Eugene Huang <eugene.huang99@gmail.com>
soundwire: dmi-quirks: add remapping for Intel 'Rooks County' NUC M15
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
pinctrl: at91: use devm_kasprintf() to avoid potential leaks (part 2)
Steve French <stfrench@microsoft.com>
cifs: missing lock when updating session status
Sebastian Reichel <sebastian.reichel@collabora.com>
clk: rockchip: rk3588: make gate linked clocks critical
Avihai Horon <avihaih@nvidia.com>
RDMA/mlx5: Remove pcie_relaxed_ordering_enabled() check for RO write
Vicki Pfau <vi@endrift.com>
Input: xpad - add constants for GIP interface numbers
Hans de Goede <hdegoede@redhat.com>
power: supply: axp288_charger: Use alt usb-id extcon on some x86 android tablets
Chunyan Zhang <chunyan.zhang@unisoc.com>
iommu/sprd: Release dma buffer to avoid memory leak
Tomas Krcka <krckatom@amazon.de>
iommu/arm-smmu-v3: Acknowledge pri/event queue overflow if any
Arnd Bergmann <arnd@arndb.de>
clk: tegra20: fix gcc-7 constant overflow warning
Jia-Ju Bai <baijiaju1990@gmail.com>
fs/ntfs3: Fix a possible null-pointer dereference in ni_clear()
Edward Lo <edward.lo@ambergroup.io>
fs/ntfs3: Add length check in indx_get_root
Edward Lo <edward.lo@ambergroup.io>
fs/ntfs3: Validate MFT flags before replaying logs
Abdun Nihaal <abdun.nihaal@gmail.com>
fs/ntfs3: Fix NULL dereference in ni_write_inode
Edward Lo <edward.lo@ambergroup.io>
fs/ntfs3: Enhance the attribute size check
Ye Bin <yebin10@huawei.com>
fs/ntfs3: Fix NULL pointer dereference in 'ni_write_inode'
Manivannan Sadhasivam <mani@kernel.org>
iommu/arm-smmu-qcom: Limit the SMR groups to 128
Ivan Orlov <ivan.orlov0322@gmail.com>
KVM: selftests: Add 'malloc' failure check in vcpu_save_state
Gustavo A. R. Silva <gustavoars@kernel.org>
RDMA/core: Fix multiple -Warray-bounds warnings
Hao Zeng <zenghao@kylinos.cn>
recordmcount: Fix memory leaks in the uwrite function
Alexandre Ghiti <alexghiti@rivosinc.com>
riscv: Fix EFI stub usage of KASAN instrumented strcmp function
Josh Poimboeuf <jpoimboe@kernel.org>
lkdtm/stackleak: Fix noinstr violation
Josh Poimboeuf <jpoimboe@kernel.org>
sched: Fix KCSAN noinstr violation
Rob Herring <robh@kernel.org>
powerpc: Use of_property_present() for testing DT property presence
Rodríguez Barbarin, José Javier <JoseJavier.Rodriguez@duagon.com>
mcb-pci: Reallocate memory region to avoid memory overlapping
Tony Lindgren <tony@atomide.com>
serial: 8250: Reinit port->pm on port specific driver unbind
Frank Wang <frank.wang@rock-chips.com>
usb: typec: tcpm: fix multiple times discover svids error
Jason Gerecke <killertofu@gmail.com>
HID: wacom: generic: Set battery quirk only when we see battery data
weiliang1503 <weiliang1503@gmail.com>
HID: Ignore battery for ELAN touchscreen on ROG Flow X13 GV301RA
Alex Henrie <alexhenrie24@gmail.com>
HID: apple: Set the tilde quirk flag on the Geyser 3
Syed Saba Kareem <Syed.SabaKareem@amd.com>
ASoC: amd: Add check for acp config flags
Baishan Jiang <bjiang400@outlook.com>
ASoC: amd: yc: Add ThinkBook 14 G5+ ARP to quirks list for acp6x
Cem Kaya <cemkaya.boun@gmail.com>
ASoC: amd: Add Dell G15 5525 to quirks list
Fred Oh <fred.oh@linux.intel.com>
ALSA: hda: LNL: add HD Audio PCI ID
Samuel Čavoj <samuel@cavoj.net>
usb: typec: ucsi: acpi: add quirk for ASUS Zenbook UM325
Kevin Groeneveld <kgroeneveld@lenbrook.com>
spi: spi-imx: fix MX51_ECSPI_* macros when cs > 3
Bastien Nocera <hadess@hadess.net>
HID: logitech-hidpp: Reconcile USB and Unifying serials
Bastien Nocera <hadess@hadess.net>
HID: logitech-hidpp: Don't use the USB serial for USB devices
Prajna Sariputra <putr4.s@gmail.com>
ASoC: amd: yc: Add DMI entries to support HP OMEN 16-n0xxx (8A42)
Mika Westerberg <mika.westerberg@linux.intel.com>
spi: intel-pci: Add support for Meteor Lake-S SPI serial flash
Josue David Hernandez Gutierrez <josue.d.hernandez.gutierrez@intel.com>
xhci: Avoid PCI MSI/MSIX interrupt reinitialization at resume
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
xhci: mem: Carefully calculate size for memory allocations
Khadija Kamran <kamrankhadijadj@gmail.com>
staging: axis-fifo: initialize timeouts in init only
Lorenzo Bianconi <lorenzo@kernel.org>
iio: imu: st_lsm6dsx: discard samples during filters settling time
Alex Henrie <alexhenrie24@gmail.com>
HID: apple: Set the tilde quirk flag on the Geyser 4 and later
Philipp Hortmann <philipp.g.hortmann@gmail.com>
staging: rtl8192e: Replace macro RTL_PCI_DEVICE with PCI_DEVICE
Max Chou <max.chou@realtek.com>
Bluetooth: btrtl: Add the support for RTL8851B
Min Li <lm0963hack@gmail.com>
Bluetooth: L2CAP: fix "bad unlock balance" in l2cap_disconnect_rsp
Raul Cheleguini <raul.cheleguini@gmail.com>
Bluetooth: Add new quirk for broken set random RPA timeout for ATS2851
Hans de Goede <hdegoede@redhat.com>
Bluetooth: hci_bcm: Fall back to getting bdaddr from EFI if not set
Chethan T N <chethan.tumkur.narayan@intel.com>
Bluetooth: btintel: Add LE States quirk support
Max Chou <max.chou@realtek.com>
Bluetooth: btrtl: check for NULL in btrtl_set_quirks()
Raul Cheleguini <rcheleguini@google.com>
Bluetooth: Improve support for Actions Semi ATS2851 based devices
Vasily Khoruzhick <anarsoul@gmail.com>
Bluetooth: btrtl: add support for the RTL8723CS
Vasily Khoruzhick <anarsoul@gmail.com>
Bluetooth: Add new quirk for broken local ext features page 2
Meng Tang <tangmeng@uniontech.com>
Bluetooth: btusb: Add new PID/VID 04ca:3801 for MT7663
Simon Horman <horms@kernel.org>
ipvs: Update width of source for ip_vs_sync_conn_options
Zhong Jinghua <zhongjinghua@huawei.com>
nbd: fix incomplete validation of ioctl arg
Larry Finger <Larry.Finger@lwfinger.net>
wifi: rtw88: Fix memory leak in rtw88_usb
Nagarajan Maran <quic_nmaran@quicinc.com>
wifi: ath11k: Fix SKB corruption in REO destination ring
Hans de Goede <hdegoede@redhat.com>
wifi: iwlwifi: dvm: Fix memcpy: detected field-spanning write backtrace
Chaitanya Kulkarni <kch@nvidia.com>
null_blk: Always check queue mode setting from configfs
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: relax sanity check if checkpoint is corrupted
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: fix iwl_mvm_max_amsdu_size() for MLO
Reese Russell <git@qrsnap.io>
wifi: mt76: mt7921: add Netgear AXE3000 (A8000) support
Harshitha Prem <quic_hprem@quicinc.com>
wifi: ath11k: Ignore frags from uninitialized peer in dp.
Colin Ian King <colin.i.king@gmail.com>
block, bfq: Fix division by zero error on zero wsum
Johannes Berg <johannes.berg@intel.com>
wifi: iwlwifi: mvm: fix ptk_pn memory leak
Hyunwoo Kim <imv4bel@gmail.com>
wifi: iwlwifi: pcie: Fix integer overflow in iwl_write_to_user_buf
Mukesh Sisodiya <mukesh.sisodiya@intel.com>
wifi: iwlwifi: add a new PCI device ID for BZ device
Daniel Gabay <daniel.gabay@intel.com>
wifi: iwlwifi: pcie: fix possible NULL pointer dereference
Vladimir Oltean <vladimir.oltean@nxp.com>
net/sched: pass netlink extack to mqprio and taprio offload
Yu Kuai <yukuai3@huawei.com>
md: fix soft lockup in status_resync
Yafang <laoar.shao@gmail.com>
bpf: Add preempt_count_{sub,add} into btf id deny list
Hao Zeng <zenghao@kylinos.cn>
samples/bpf: Fix fout leak in hbm's run_bpf_prog
Chao Yu <chao@kernel.org>
f2fs: fix to check readonly condition correctly
Chao Yu <chao@kernel.org>
f2fs: fix to drop all dirty pages during umount() if cp_error is set
Yonggil Song <yonggil.song@samsung.com>
f2fs: Fix system crash due to lack of free space in LFS
Stephan Müller <smueller@chronox.de>
crypto: jitter - permanent and intermittent health errors
Ojaswin Mujoo <ojaswin@linux.ibm.com>
ext4: Fix best extent lstart adjustment logic in ext4_mb_new_inode_pa()
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: set goal start correctly in ext4_mb_normalize_request
Xingui Yang <yangxingui@huawei.com>
scsi: hisi_sas: Grab sas_dev lock when traversing the members of sas_dev.list
Adrian Hunter <adrian.hunter@intel.com>
scsi: ufs: ufs-pci: Add support for Intel Lunar Lake
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Fix inode height consistency check
Zheng Wang <zyytlz.wz@163.com>
scsi: message: mptlan: Fix use after free bug in mptlan_remove() due to race condition
Eli Cohen <elic@nvidia.com>
lib: cpu_rmap: Avoid use after free on rmap->obj array entries
Dmitry Bogdanov <d.bogdanov@yadro.com>
scsi: target: iscsit: Free cmds before session free
Nick Child <nnac123@linux.ibm.com>
netdev: Enforce index cap in netdev_get_tx_queue
Nick Child <nnac123@linux.ibm.com>
net: Catch invalid index in XPS mapping
Rajat Soni <quic_rajson@quicinc.com>
wifi: ath12k: fix memory leak in ath12k_qmi_driver_event_work()
Nathan Chancellor <nathan@kernel.org>
net: pasemi: Fix return type of pasemi_mac_start_tx()
Maxim Korotkov <korotkov.maxim.s@gmail.com>
bnxt: avoid overflow in bnxt_get_nvram_directory()
Dongliang Mu <dzm91@hust.edu.cn>
wifi: rtw88: fix memory leak in rtw_usb_probe()
Justin Tee <justin.tee@broadcom.com>
scsi: lpfc: Correct used_rpi count when devloss tmo fires with no recovery
Justin Tee <justin.tee@broadcom.com>
scsi: lpfc: Prevent lpfc_debugfs_lockstat_write() buffer overflow
Jan Kara <jack@suse.cz>
ext2: Check block size validity during mount
Hector Martin <marcan@marcan.st>
wifi: brcmfmac: pcie: Add IDs/properties for BCM4387
Hector Martin <marcan@marcan.st>
wifi: brcmfmac: cfg80211: Pass the PMK in binary instead of hex
Hector Martin <marcan@marcan.st>
wifi: brcmfmac: pcie: Provide a buffer of random bytes to the device
Kumar Kartikeya Dwivedi <memxor@gmail.com>
bpf: Annotate data races in bpf_local_storage
Ramya Gnanasekar <quic_rgnanase@quicinc.com>
wifi: ath12k: PCI ops for wakeup/release MHI
Ramya Gnanasekar <quic_rgnanase@quicinc.com>
wifi: ath12k: Handle lock during peer_id find
Kees Cook <keescook@chromium.org>
wifi: ath: Silence memcpy run-time false positive warning
Aleksandr Mezin <mezin.alexander@gmail.com>
hwmon: (nzxt-smart2) add another USB ID
Feng Jiang <jiangfeng@kylinos.cn>
platform/x86/amd: pmc: Fix memory leak in amd_pmc_stb_debugfs_open_v2()
Wei Chen <harperchen1110@gmail.com>
media: mediatek: vcodec: Fix potential array out-of-bounds in decoder queue_setup
Mukul Joshi <mukul.joshi@amd.com>
drm/amdgpu: Enable IH retry CAM on GFX9
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: Prefer designated initializers over memset for subdev pad ops
lyndonli <Lyndon.Li@amd.com>
drm/amdgpu: Fix sdma v4 sw fini error
Mario Limonciello <mario.limonciello@amd.com>
drm/amd: Fix an out of bounds error in BIOS parser
Paul Hsieh <Paul.Hsieh@amd.com>
drm/amd/display: Correct DML calculation to follow HW SPEC
Hans de Goede <hdegoede@redhat.com>
ACPI: video: Remove desktops without backlight DMI quirks
Bingbu Cao <bingbu.cao@intel.com>
media: ipu3-cio2: support multiple sensors and VCMs with same HID
Shanker Donthineni <sdonthineni@nvidia.com>
irqchip/gicv3: Workaround for NVIDIA erratum T241-FABRIC-4
Konrad Dybcio <konrad.dybcio@linaro.org>
arm64: dts: qcom: sm6115-j606f: Add ramoops node
Konrad Dybcio <konrad.dybcio@linaro.org>
arm64: dts: qcom: sdm845-polaris: Drop inexistent properties
void0red <30990023+void0red@users.noreply.github.com>
ACPICA: ACPICA: check null return of ACPI_ALLOCATE_ZEROED in acpi_db_display_objects
Tamir Duberstein <tamird@google.com>
ACPICA: Avoid undefined behavior: applying zero offset to null pointer
Douglas Anderson <dianders@chromium.org>
drm/msm/dp: Clean up handling of DP AUX interrupts
Nur Hussein <hussein@unixcat.org>
drm/tegra: Avoid potential 32-bit integer overflow
Karol Wachowski <karol.wachowski@linux.intel.com>
accel/ivpu: Remove D3hot delay for Meteorlake
Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
remoteproc: stm32_rproc: Add mutex protection for workqueue
Ayush Gupta <ayugupta@amd.com>
drm/amd/display: fixed dcn30+ underflow issue
Armin Wolf <W_Armin@gmx.de>
ACPI: EC: Fix oops when removing custom query handlers
Pierre Gondois <pierre.gondois@arm.com>
firmware: arm_sdei: Fix sleep from invalid context BUG
Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
arm64: dts: imx8mq-librem5: Remove dis_u3_susphy_quirk from usb_dwc3_0
Zheng Wang <zyytlz.wz@163.com>
memstick: r592: Fix UAF bug in r592_remove due to race condition
Toby Chen <tobyc@nvidia.com>
drm/rockchip: dw_hdmi: cleanup drm encoder during unbind
Kang Chen <void0red@gmail.com>
ACPI: processor: Check for null return of devm_kzalloc() in fch_misc_setup()
David E. Box <david.e.box@linux.intel.com>
platform/x86/intel: vsec: Explicitly enable capabilities
Tom Rix <trix@redhat.com>
media: pvrusb2: VIDEO_PVRUSB2 depends on DVB_CORE to use dvb_* symbols
harperchen <harperchen1110@gmail.com>
media: pci: tw68: Fix null-ptr-deref bug in buf prepare and finish
harperchen <harperchen1110@gmail.com>
media: cx23885: Fix a null-ptr-deref bug in buffer_prepare() and buffer_finish()
Kees Cook <keescook@chromium.org>
media: imx-jpeg: Bounds check sizeimage access
Samson Tam <Samson.Tam@amd.com>
drm/amd/display: reallocate DET for dual displays with high pixel rate ratio
Tomer Tayar <ttayar@habana.ai>
accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release()
Konrad Dybcio <konrad.dybcio@linaro.org>
arm64: dts: qcom: msm8996: Add missing DWC3 quirks
Iuliana Prodan <iuliana.prodan@nxp.com>
remoteproc: imx_dsp_rproc: Add custom memory copy implementation for i.MX DSP Cores
Alexander Stein <alexander.stein@ew.tq-group.com>
regmap: cache: Return error in cache sync operations for REGCACHE_NONE
Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
drm/amd/display: Use DC_LOG_DC in the trasform pixel function
Gabe Teeger <gabe.teeger@amd.com>
drm/amd/display: Enable HostVM based on rIOMMU active
Hans de Goede <hdegoede@redhat.com>
platform/x86: x86-android-tablets: Add Acer Iconia One 7 B1-750 data
Samson Tam <samson.tam@amd.com>
drm/amd/display: enable DPG when disabling plane for phantom pipe
Paul Hsieh <Paul.Hsieh@amd.com>
drm/amd/display: Correct DML calculation to align HW formula
Ayush Gupta <ayush.gupta@amd.com>
drm/amd/display: populate subvp cmd info only for the top pipe
Jani Nikula <jani.nikula@intel.com>
drm/displayid: add displayid_get_header() and check bounds better
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
fs: hfsplus: remove WARN_ON() from hfsplus_cat_{read,write}_inode()
Christian Brauner <brauner@kernel.org>
open: return EINVAL for O_DIRECTORY | O_CREAT
Zqiang <qiang1.zhang@intel.com>
rcu: Protect rcu_print_task_exp_stall() ->exp_tasks access
Ivan Orlov <ivan.orlov0322@gmail.com>
selftests: cgroup: Add 'malloc' failures checks in test_memcontrol
Paul E. McKenney <paulmck@kernel.org>
refscale: Move shutdown from wait_event() to wait_event_idle()
Theodore Ts'o <tytso@mit.edu>
ext4: allow ext4_get_group_info() to fail
Kemeng Shi <shikemeng@huaweicloud.com>
ext4: allow to find by goal if EXT4_MB_HINT_GOAL_ONLY is set
Theodore Ts'o <tytso@mit.edu>
ext4: don't clear SB_RDONLY when remounting r/w until quota is re-enabled
Theodore Ts'o <tytso@mit.edu>
ext4: reflect error codes from ext4_multi_mount_protect() to its callers
Zongjie Li <u202112089@hust.edu.cn>
fbdev: arcfb: Fix error handling in arcfb_probe()
Jani Nikula <jani.nikula@intel.com>
drm/i915: taint kernel when force probing unsupported devices
Nikita Zhandarovich <n.zhandarovich@fintech.ru>
drm/i915/dp: prevent potential div-by-zero
Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
drm/i915: Fix NULL ptr deref by checking new_crtc_state
John Harrison <John.C.Harrison@Intel.com>
drm/i915/guc: Don't capture Gen8 regs on Xe devices
Kuniyuki Iwashima <kuniyu@amazon.com>
af_unix: Fix data races around sk->sk_shutdown.
Kuniyuki Iwashima <kuniyu@amazon.com>
af_unix: Fix a data race of sk->sk_receive_queue->qlen.
Eric Dumazet <edumazet@google.com>
net: datagram: fix data-races in datagram_poll()
Vitaly Prosyak <vitaly.prosyak@amd.com>
drm/sched: Check scheduler work queue before calling timeout handling
Colin Foster <colin.foster@in-advantage.com>
net: mscc: ocelot: fix stat counter register values
t.feng <fengtao40@huawei.com>
ipvlan:Fix out-of-bounds caused by unclear skb->cb
Ziwei Xiao <ziweixiao@google.com>
gve: Remove the code of clearing PBA bit
Eric Dumazet <edumazet@google.com>
tcp: add annotations around sk->sk_shutdown accesses
Eric Dumazet <edumazet@google.com>
net: add vlan_get_protocol_and_depth() helper
Eric Dumazet <edumazet@google.com>
net: deal with most data-races in sk_wait_event()
Eric Dumazet <edumazet@google.com>
net: annotate sk->sk_err write from do_recvmmsg()
Eric Dumazet <edumazet@google.com>
netlink: annotate accesses to nlk->cb_running
Hangbin Liu <liuhangbin@gmail.com>
bonding: fix send_peer_notif overflow
Florian Westphal <fw@strlen.de>
netfilter: conntrack: fix possible bug_on with enable_hooks=1
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: always release netdev hooks from notifier
Florian Fainelli <f.fainelli@gmail.com>
net: phy: bcm7xx: Correct read from expansion register
Kuniyuki Iwashima <kuniyu@amazon.com>
net: Fix load-tearing on sk->sk_stamp in sock_recv_cmsgs().
Marek Vasut <marex@denx.de>
net: stmmac: Initialize MAC_ONEUS_TIC_COUNTER register
Roy Novich <royno@nvidia.com>
linux/dim: Do nothing if no time delta between samples
Thomas Gleixner <tglx@linutronix.de>
tick/broadcast: Make broadcast device replacement work correctly
Keoseong Park <keosung.park@samsung.com>
scsi: ufs: core: Fix I/O hang that occurs when BKOPS fails in W-LUN suspend
Yang Jihong <yangjihong1@huawei.com>
perf/core: Fix perf_sample_data not properly initialized for different swevents in perf_tp_event()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
net: mdio: mvusb: Fix an error handling path in mvusb_mdio_probe()
Eric Dumazet <edumazet@google.com>
net: skb_partial_csum_set() fix against transport header magic value
Randy Dunlap <rdunlap@infradead.org>
ARM: 9296/1: HP Jornada 7XX: fix kernel-doc warnings
Saravana Kannan <saravanak@google.com>
drm/mipi-dsi: Set the fwnode for mipi_dsi_device
Kees Cook <keescook@chromium.org>
drm/nouveau/disp: More DP_RECEIVER_CAP_SIZE array fixes
Jani Nikula <jani.nikula@intel.com>
drm/dsc: fix DP_DSC_MAX_BPP_DELTA_* macro values
Pierre Asselin <pa@panix.com>
firmware/sysfb: Fix VESA format selection
Sui Jingfeng <suijingfeng@loongson.cn>
drm/fbdev-generic: prohibit potential out-of-bounds access
-------------
Diffstat:
Documentation/arm64/silicon-errata.rst | 2 +
.../devicetree/bindings/ata/ceva,ahci-1v84.yaml | 2 +-
.../bindings/display/msm/dsi-controller-main.yaml | 12 +
Makefile | 4 +-
arch/arm/include/asm/assembler.h | 13 -
arch/arm/mach-sa1100/jornada720_ssp.c | 5 +-
arch/arm/vfp/entry.S | 16 +-
arch/arm/vfp/vfphw.S | 16 +-
arch/arm/vfp/vfpmodule.c | 27 +-
arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 1 -
arch/arm64/boot/dts/qcom/msm8996.dtsi | 3 +
arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts | 2 -
arch/arm64/boot/dts/qcom/sm6115p-lenovo-j606f.dts | 11 +
arch/arm64/include/asm/kvm_pgtable.h | 1 +
arch/arm64/kernel/mte.c | 7 +-
arch/arm64/kvm/hyp/pgtable.c | 32 +-
arch/arm64/mm/copypage.c | 5 +-
arch/parisc/include/asm/pdc.h | 1 +
arch/parisc/kernel/firmware.c | 27 +-
arch/powerpc/kernel/dma-iommu.c | 4 +-
arch/powerpc/kernel/iommu.c | 11 +-
arch/powerpc/kernel/legacy_serial.c | 8 +-
arch/powerpc/mm/book3s64/radix_pgtable.c | 4 +-
arch/powerpc/net/bpf_jit_comp.c | 2 +
arch/powerpc/platforms/44x/iss4xx.c | 2 +-
arch/powerpc/platforms/44x/ppc476.c | 2 +-
arch/powerpc/platforms/cell/spu_manage.c | 2 +-
arch/powerpc/platforms/powermac/pic.c | 3 +-
arch/powerpc/platforms/powernv/opal-lpc.c | 2 +-
arch/powerpc/platforms/pseries/hotplug-cpu.c | 2 +-
arch/powerpc/platforms/pseries/iommu.c | 13 +-
arch/powerpc/platforms/pseries/vio.c | 2 +-
arch/powerpc/sysdev/mpic_msgr.c | 2 +-
arch/riscv/kernel/image-vars.h | 2 -
arch/riscv/kernel/probes/Makefile | 2 +
arch/s390/crypto/chacha-glue.c | 2 +-
arch/s390/kernel/Makefile | 1 +
arch/x86/kernel/Makefile | 1 +
block/bfq-iosched.c | 2 +
crypto/jitterentropy-kcapi.c | 51 +-
crypto/jitterentropy.c | 144 ++---
crypto/jitterentropy.h | 1 -
drivers/accel/habanalabs/common/device.c | 9 +
drivers/accel/habanalabs/common/habanalabs.h | 1 +
drivers/accel/habanalabs/common/habanalabs_drv.c | 1 +
drivers/accel/habanalabs/common/memory_mgr.c | 13 +-
drivers/accel/ivpu/ivpu_drv.c | 4 +
drivers/acpi/acpi_apd.c | 2 +
drivers/acpi/acpica/dbnames.c | 3 +
drivers/acpi/acpica/dswstate.c | 11 +-
drivers/acpi/ec.c | 1 +
drivers/acpi/video_detect.c | 35 --
drivers/base/regmap/regcache.c | 6 +
drivers/block/nbd.c | 6 +
drivers/block/null_blk/main.c | 5 +
drivers/bluetooth/btbcm.c | 47 +-
drivers/bluetooth/btintel.c | 5 +-
drivers/bluetooth/btrtl.c | 138 ++++-
drivers/bluetooth/btrtl.h | 5 +
drivers/bluetooth/btusb.c | 6 +
drivers/bluetooth/hci_h5.c | 4 +
drivers/char/tpm/tpm_tis.c | 16 +
drivers/clk/rockchip/clk-rk3588.c | 42 +-
drivers/clk/tegra/clk-tegra20.c | 28 +-
drivers/firmware/arm_sdei.c | 37 +-
drivers/firmware/smccc/smccc.c | 26 +
drivers/firmware/smccc/soc_id.c | 28 +-
drivers/firmware/sysfb_simplefb.c | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 26 +-
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 8 +-
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 36 +-
drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c | 21 +-
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 51 +-
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 5 +
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 2 +-
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 2 +-
drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 55 +-
drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 7 +-
drivers/gpu/drm/amd/display/dc/core/dc.c | 47 +-
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 3 +-
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 5 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 3 +-
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c | 2 +-
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 2 +-
.../amd/display/dc/dcn32/dcn32_resource_helpers.c | 43 +-
.../amd/display/dc/dml/dcn30/display_mode_vba_30.c | 2 +-
.../amd/display/dc/dml/dcn31/display_mode_vba_31.c | 300 +++++----
.../gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c | 4 +
.../display/dc/dml/dcn314/display_mode_vba_314.c | 300 +++++----
.../amd/display/dc/dml/dcn32/display_mode_vba_32.c | 2 +-
.../amd/include/asic_reg/oss/osssys_4_2_0_offset.h | 6 +
.../include/asic_reg/oss/osssys_4_2_0_sh_mask.h | 11 +
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 18 +
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 20 +-
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 1 +
drivers/gpu/drm/drm_displayid.c | 17 +-
drivers/gpu/drm/drm_fb_helper.c | 16 +-
drivers/gpu/drm/drm_mipi_dsi.c | 2 +-
drivers/gpu/drm/exynos/exynos_drm_g2d.h | 4 +-
drivers/gpu/drm/i915/Kconfig | 12 +-
drivers/gpu/drm/i915/display/intel_atomic_plane.c | 4 +-
drivers/gpu/drm/i915/display/intel_dp.c | 5 +
drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c | 7 +-
drivers/gpu/drm/i915/i915_pci.c | 6 +
.../gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h | 202 +++++++
.../gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 177 ++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 671 ++++++---------------
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 21 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 23 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 5 -
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 18 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 4 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h | 3 -
drivers/gpu/drm/msm/dp/dp_audio.c | 12 +
drivers/gpu/drm/msm/dp/dp_audio.h | 2 +
drivers/gpu/drm/msm/dp/dp_aux.c | 80 ++-
drivers/gpu/drm/msm/dp/dp_catalog.c | 2 +-
drivers/gpu/drm/msm/dp/dp_catalog.h | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 1 +
drivers/gpu/drm/msm/msm_gem_submit.c | 25 +-
drivers/gpu/drm/nouveau/include/nvif/if0012.h | 4 +-
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h | 3 +-
drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c | 2 +-
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 +
drivers/gpu/drm/scheduler/sched_main.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 2 +-
drivers/hid/hid-apple.c | 19 +-
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-input.c | 2 +
drivers/hid/hid-logitech-hidpp.c | 53 +-
drivers/hid/wacom_wac.c | 33 +-
drivers/hwmon/nzxt-smart2.c | 3 +-
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 11 +
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 57 +-
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 18 +
drivers/infiniband/core/user_mad.c | 23 +-
drivers/infiniband/hw/mlx5/mr.c | 6 +-
drivers/input/joystick/xpad.c | 5 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 19 +-
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 26 +-
drivers/iommu/sprd-iommu.c | 29 +-
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-gic-v3.c | 115 +++-
drivers/mcb/mcb-pci.c | 27 +-
drivers/md/md.c | 18 +-
drivers/media/pci/cx23885/cx23885-core.c | 4 +-
drivers/media/pci/cx23885/cx23885-video.c | 13 +-
drivers/media/pci/intel/ipu3/cio2-bridge.c | 15 +-
drivers/media/pci/intel/ipu3/cio2-bridge.h | 3 +-
drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 2 +-
drivers/media/pci/tw68/tw68-video.c | 16 +-
.../platform/mediatek/vcodec/mtk_vcodec_dec.c | 7 +
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 5 +
drivers/media/platform/renesas/vsp1/vsp1_drm.c | 18 +-
drivers/media/platform/renesas/vsp1/vsp1_entity.c | 11 +-
.../platform/samsung/exynos4-is/fimc-capture.c | 7 +-
drivers/media/platform/ti/am437x/am437x-vpfe.c | 15 +-
drivers/media/platform/ti/cal/cal-video.c | 8 +-
drivers/media/usb/dvb-usb/cxusb-analog.c | 14 +-
drivers/media/usb/pvrusb2/Kconfig | 3 +-
drivers/memstick/host/r592.c | 2 +-
drivers/message/fusion/mptlan.c | 2 +
drivers/mfd/dln2.c | 1 +
drivers/mfd/intel-lpss-pci.c | 15 +
drivers/mfd/intel_soc_pmic_chtwc.c | 14 +-
drivers/misc/lkdtm/stackleak.c | 6 +
drivers/net/bonding/bond_netlink.c | 7 +-
drivers/net/bonding/bond_options.c | 8 +-
drivers/net/can/dev/skb.c | 3 +-
drivers/net/can/kvaser_pciefd.c | 51 +-
drivers/net/dsa/mv88e6xxx/port.h | 2 +-
drivers/net/dsa/rzn1_a5psw.c | 83 ++-
drivers/net/dsa/rzn1_a5psw.h | 3 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2 +-
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 +-
drivers/net/ethernet/freescale/fec_main.c | 16 +-
drivers/net/ethernet/google/gve/gve_main.c | 13 -
.../hisilicon/hns3/hns3_common/hclge_comm_cmd.c | 25 +-
.../hisilicon/hns3/hns3_common/hclge_comm_cmd.h | 8 +-
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 2 +-
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h | 1 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 15 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 4 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 5 +
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 5 +-
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 5 -
drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 5 +-
drivers/net/ethernet/intel/ice/ice_lib.c | 5 +
drivers/net/ethernet/intel/ice/ice_sriov.c | 8 +-
drivers/net/ethernet/intel/ice/ice_txrx.c | 8 +-
drivers/net/ethernet/intel/ice/ice_txrx.h | 9 +-
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 19 +
drivers/net/ethernet/intel/ice/ice_vf_lib.h | 1 +
drivers/net/ethernet/intel/ice/ice_virtchnl.c | 1 +
drivers/net/ethernet/intel/igb/e1000_mac.c | 4 +-
.../net/ethernet/mellanox/mlx5/core/en/params.c | 3 +-
.../net/ethernet/mellanox/mlx5/core/en_common.c | 2 +-
drivers/net/ethernet/mscc/vsc7514_regs.c | 18 +-
drivers/net/ethernet/netronome/nfp/nic/main.h | 2 +-
drivers/net/ethernet/pasemi/pasemi_mac.c | 2 +-
drivers/net/ethernet/sfc/ef100_netdev.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 5 +
drivers/net/ethernet/sun/cassini.c | 2 +
drivers/net/ipvlan/ipvlan_core.c | 6 +
drivers/net/mdio/mdio-mvusb.c | 11 +-
drivers/net/pcs/pcs-xpcs.c | 2 +-
drivers/net/phy/bcm-phy-lib.h | 5 +
drivers/net/phy/bcm7xxx.c | 2 +-
drivers/net/phy/dp83867.c | 22 +-
drivers/net/tap.c | 4 +-
drivers/net/tun.c | 15 +
drivers/net/virtio_net.c | 61 +-
drivers/net/wireless/ath/ath.h | 12 +-
drivers/net/wireless/ath/ath11k/dp.c | 4 +-
drivers/net/wireless/ath/ath11k/dp_rx.c | 17 +-
drivers/net/wireless/ath/ath11k/peer.h | 1 +
drivers/net/wireless/ath/ath12k/dp_rx.c | 3 +
drivers/net/wireless/ath/ath12k/pci.c | 47 +-
drivers/net/wireless/ath/ath12k/pci.h | 6 +
drivers/net/wireless/ath/ath12k/qmi.c | 4 +-
drivers/net/wireless/ath/key.c | 2 +-
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 +
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 13 +-
.../wireless/broadcom/brcm80211/brcmfmac/chip.c | 2 +
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 51 ++
.../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 11 +
.../broadcom/brcm80211/include/brcm_hw_ids.h | 2 +
drivers/net/wireless/intel/iwlwifi/dvm/sta.c | 5 +-
drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 19 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 +-
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 10 +
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 37 +-
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 +
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 +-
.../net/wireless/mediatek/mt76/mt76_connac2_mac.h | 2 +-
.../net/wireless/mediatek/mt76/mt76_connac_mac.c | 3 +-
drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 3 +
drivers/net/wireless/realtek/rtw88/mac80211.c | 2 +-
drivers/net/wireless/realtek/rtw88/main.c | 15 +
drivers/net/wireless/realtek/rtw88/main.h | 3 +
drivers/net/wireless/realtek/rtw88/usb.c | 3 +-
drivers/net/wireless/realtek/rtw88/usb.h | 2 +-
drivers/net/wwan/iosm/iosm_ipc_imem.c | 27 +-
drivers/net/wwan/iosm/iosm_ipc_imem_ops.c | 12 +-
drivers/net/wwan/iosm/iosm_ipc_imem_ops.h | 6 +-
drivers/parisc/power.c | 16 +-
drivers/phy/st/phy-miphy28lp.c | 42 +-
drivers/pinctrl/pinctrl-at91.c | 23 +-
drivers/platform/x86/amd/pmc.c | 1 +
drivers/platform/x86/intel/vsec.c | 69 +--
drivers/platform/x86/intel/vsec.h | 9 +-
drivers/platform/x86/x86-android-tablets.c | 101 +++-
drivers/power/supply/axp288_charger.c | 15 +-
drivers/remoteproc/imx_dsp_rproc.c | 187 +++++-
drivers/remoteproc/stm32_rproc.c | 8 +
drivers/s390/block/dasd_eckd.c | 33 +-
drivers/s390/cio/device.c | 2 +
drivers/s390/cio/qdio.h | 2 +-
drivers/scsi/hisi_sas/hisi_sas.h | 3 +-
drivers/scsi/hisi_sas/hisi_sas_main.c | 25 +-
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2 +-
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 +-
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 4 +-
drivers/scsi/lpfc/lpfc_debugfs.c | 7 +-
drivers/scsi/lpfc/lpfc_els.c | 24 +-
drivers/scsi/scsi_lib.c | 3 +-
drivers/scsi/storvsc_drv.c | 8 +-
drivers/soundwire/bus.c | 15 +-
drivers/soundwire/dmi-quirks.c | 25 +
drivers/soundwire/qcom.c | 3 +
drivers/spi/spi-imx.c | 24 +-
drivers/spi/spi-intel-pci.c | 1 +
drivers/staging/axis-fifo/axis-fifo.c | 28 +-
drivers/staging/media/imx/imx-media-capture.c | 12 +-
drivers/staging/media/imx/imx-media-utils.c | 8 +-
drivers/staging/media/omap4iss/iss_video.c | 6 +-
drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 6 +-
drivers/staging/rtl8192e/rtl8192e/rtl_core.h | 5 -
drivers/target/iscsi/iscsi_target.c | 6 +-
drivers/thunderbolt/nhi.c | 29 +-
drivers/thunderbolt/nhi_regs.h | 2 +
drivers/tty/serial/8250/8250_bcm7271.c | 7 +-
drivers/tty/serial/8250/8250_core.c | 1 +
drivers/tty/serial/8250/8250_exar.c | 17 +
drivers/tty/serial/8250/8250_pci.c | 5 +
drivers/tty/serial/arc_uart.c | 7 +-
drivers/tty/serial/qcom_geni_serial.c | 9 +-
drivers/tty/vt/vc_screen.c | 11 +-
drivers/ufs/core/ufshcd.c | 10 +-
drivers/ufs/host/ufshcd-pci.c | 1 +
drivers/usb/class/usbtmc.c | 2 +
drivers/usb/dwc3/debugfs.c | 109 ++++
drivers/usb/dwc3/gadget.c | 67 +-
drivers/usb/gadget/function/u_ether.c | 3 +
drivers/usb/gadget/udc/core.c | 151 ++---
drivers/usb/host/uhci-pci.c | 10 +-
drivers/usb/host/xhci-mem.c | 9 +-
drivers/usb/host/xhci-pci.c | 27 +-
drivers/usb/host/xhci-ring.c | 29 +-
drivers/usb/host/xhci.c | 8 +-
drivers/usb/host/xhci.h | 3 +-
drivers/usb/storage/scsiglue.c | 28 +-
drivers/usb/typec/altmodes/displayport.c | 4 +
drivers/usb/typec/tcpm/tcpm.c | 16 +-
drivers/usb/typec/ucsi/ucsi_acpi.c | 44 +-
drivers/video/fbdev/arcfb.c | 15 +-
fs/ceph/snap.c | 13 +
fs/cifs/cifsglob.h | 4 +-
fs/cifs/connect.c | 8 +-
fs/cifs/file.c | 26 +-
fs/cifs/smb1ops.c | 9 +-
fs/cifs/smb2ops.c | 7 +-
fs/ext2/ext2.h | 1 +
fs/ext2/super.c | 7 +
fs/ext4/balloc.c | 18 +-
fs/ext4/ext4.h | 15 +-
fs/ext4/ialloc.c | 12 +-
fs/ext4/mballoc.c | 131 ++--
fs/ext4/mmp.c | 9 +-
fs/ext4/super.c | 24 +-
fs/f2fs/checkpoint.c | 22 +-
fs/f2fs/data.c | 7 +-
fs/f2fs/extent_cache.c | 22 +-
fs/f2fs/f2fs.h | 5 +
fs/f2fs/gc.c | 10 +-
fs/f2fs/gc.h | 2 +
fs/f2fs/segment.h | 39 +-
fs/f2fs/super.c | 2 +-
fs/gfs2/glops.c | 3 +-
fs/hfsplus/inode.c | 28 +-
fs/ksmbd/connection.c | 3 +-
fs/ksmbd/oplock.c | 5 +-
fs/ksmbd/oplock.h | 2 +-
fs/ksmbd/smb2misc.c | 5 +-
fs/ksmbd/smb2pdu.c | 19 +-
fs/nilfs2/inode.c | 18 +
fs/ntfs3/frecord.c | 5 +-
fs/ntfs3/fsntfs.c | 1 +
fs/ntfs3/index.c | 11 +-
fs/ntfs3/inode.c | 6 +
fs/ntfs3/record.c | 9 +-
fs/open.c | 18 +-
fs/statfs.c | 4 +-
include/drm/display/drm_dp.h | 4 +-
include/linux/arm-smccc.h | 18 +
include/linux/cpuhotplug.h | 1 -
include/linux/dim.h | 3 +-
include/linux/if_vlan.h | 17 +
include/linux/netdevice.h | 1 +
include/linux/sched/task_stack.h | 2 +-
include/linux/sunrpc/svc_rdma.h | 2 +-
include/linux/sunrpc/svc_xprt.h | 2 +-
include/net/bluetooth/hci.h | 15 +
include/net/bonding.h | 2 +-
include/net/ip_vs.h | 6 +-
include/net/pkt_sched.h | 2 +
include/net/sock.h | 2 +-
include/uapi/asm-generic/fcntl.h | 1 -
kernel/bpf/bpf_local_storage.c | 16 +-
kernel/bpf/verifier.c | 4 +
kernel/events/core.c | 14 +-
kernel/rcu/refscale.c | 2 +-
kernel/rcu/tree_exp.h | 6 +-
kernel/time/tick-broadcast.c | 120 +++-
kernel/trace/rethook.c | 4 +-
lib/cpu_rmap.c | 5 +-
lib/dim/dim.c | 5 +-
lib/dim/net_dim.c | 3 +-
lib/dim/rdma_dim.c | 3 +-
lib/maple_tree.c | 12 +-
mm/zswap.c | 16 +
net/8021q/vlan_dev.c | 4 +-
net/bluetooth/hci_event.c | 9 +-
net/bluetooth/hci_sync.c | 6 +-
net/bluetooth/l2cap_core.c | 1 -
net/bridge/br_forward.c | 2 +-
net/bridge/br_private_tunnel.h | 8 +-
net/can/isotp.c | 2 +-
net/can/j1939/socket.c | 2 +-
net/core/datagram.c | 15 +-
net/core/dev.c | 4 +-
net/core/skbuff.c | 4 +-
net/core/stream.c | 12 +-
net/devlink/core.c | 16 +-
net/devlink/devl_internal.h | 1 -
net/devlink/leftover.c | 5 +-
net/ipv4/af_inet.c | 2 +-
net/ipv4/tcp.c | 14 +-
net/ipv4/tcp_bpf.c | 2 +-
net/ipv4/tcp_input.c | 4 +-
net/ipv4/tcp_ipv4.c | 5 +-
net/ipv6/ip6_gre.c | 13 +-
net/key/af_key.c | 12 +-
net/llc/af_llc.c | 8 +-
net/mac80211/cfg.c | 7 +-
net/mac80211/trace.h | 2 +-
net/mac80211/tx.c | 5 +-
net/netfilter/core.c | 6 +-
net/netfilter/ipvs/ip_vs_sync.c | 2 +-
net/netfilter/nf_conntrack_standalone.c | 3 +-
net/netfilter/nf_tables_api.c | 4 +-
net/netfilter/nft_chain_filter.c | 9 +-
net/netfilter/nft_set_rbtree.c | 20 +-
net/netlink/af_netlink.c | 8 +-
net/nsh/nsh.c | 8 +-
net/packet/af_packet.c | 6 +-
net/sched/sch_mqprio.c | 5 +-
net/sched/sch_taprio.c | 12 +-
net/smc/smc_close.c | 4 +-
net/smc/smc_rx.c | 4 +-
net/smc/smc_tx.c | 4 +-
net/socket.c | 2 +-
net/sunrpc/svc.c | 19 +-
net/sunrpc/svc_xprt.c | 24 +-
net/sunrpc/svcsock.c | 30 +-
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 11 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 2 +-
net/tipc/bearer.c | 17 +-
net/tipc/bearer.h | 3 +
net/tipc/link.c | 9 +-
net/tipc/socket.c | 4 +-
net/tipc/udp_media.c | 5 +-
net/tls/tls_main.c | 3 +-
net/unix/af_unix.c | 22 +-
net/vmw_vsock/af_vsock.c | 2 +-
net/wireless/scan.c | 6 +-
net/xfrm/xfrm_device.c | 2 +-
net/xfrm/xfrm_interface_core.c | 54 +-
net/xfrm/xfrm_policy.c | 9 -
net/xfrm/xfrm_user.c | 15 +-
samples/bpf/hbm.c | 1 +
scripts/recordmcount.c | 6 +-
sound/firewire/digi00x/digi00x-stream.c | 4 +-
sound/pci/hda/hda_generic.c | 7 +-
sound/pci/hda/hda_intel.c | 3 +
sound/pci/hda/patch_hdmi.c | 5 +
sound/pci/hda/patch_realtek.c | 14 +-
sound/soc/amd/Kconfig | 2 +
sound/soc/amd/ps/acp63.h | 2 +
sound/soc/amd/ps/pci-ps.c | 8 +-
sound/soc/amd/yc/acp6x-mach.c | 21 +
sound/soc/amd/yc/acp6x.h | 3 +
sound/soc/amd/yc/pci-acp6x.c | 8 +-
sound/soc/fsl/fsl_micfil.c | 14 +-
sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 6 -
sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 1 -
sound/soc/mediatek/mt8186/mt8186-afe-pcm.c | 4 -
sound/soc/mediatek/mt8186/mt8186-audsys-clk.c | 46 +-
sound/soc/mediatek/mt8186/mt8186-audsys-clk.h | 1 -
sound/soc/sof/ipc3-topology.c | 7 +-
sound/soc/sof/topology.c | 4 +
sound/usb/format.c | 1 +
tools/include/uapi/asm-generic/fcntl.h | 1 -
tools/perf/builtin-script.c | 7 +
.../cpupower/utils/idle_monitor/mperf_monitor.c | 31 +-
tools/testing/selftests/cgroup/test_memcontrol.c | 15 +
tools/testing/selftests/kvm/lib/x86_64/processor.c | 1 +
tools/testing/selftests/net/fib_nexthops.sh | 2 +-
.../selftests/net/srv6_end_dt4_l3vpn_test.sh | 17 +-
virt/kvm/kvm_main.c | 16 +-
467 files changed, 5192 insertions(+), 2485 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH AUTOSEL 6.2 11/37] accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release()
@ 2023-05-01 2:59 10% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2023-05-01 2:59 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Tomer Tayar, Oded Gabbay, Sasha Levin, gregkh, dliberman,
osharabi, obitton, dhirschfeld, ynudelman, talcohen, bjauhari,
rkatta
From: Tomer Tayar <ttayar@habana.ai>
[ Upstream commit 2e8e9a895c4589f124a37fc84d123b5114406e94 ]
The memory manager IDR is currently destroyed when user releases the
file descriptor.
However, at this point the user context might be still held, and memory
buffers might be still in use.
Later on, calls to release those buffers will fail due to not finding
their handles in the IDR, leading to a memory leak.
To avoid this leak, split the IDR destruction from the memory manager
fini, and postpone it to hpriv_release() when there is no user context
and no buffers are used.
Signed-off-by: Tomer Tayar <ttayar@habana.ai>
Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/misc/habanalabs/common/device.c | 9 +++++++++
drivers/misc/habanalabs/common/habanalabs.h | 1 +
drivers/misc/habanalabs/common/habanalabs_drv.c | 1 +
drivers/misc/habanalabs/common/memory_mgr.c | 13 ++++++++++++-
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c
index f7b9c3871518b..1334d2b664ec6 100644
--- a/drivers/misc/habanalabs/common/device.c
+++ b/drivers/misc/habanalabs/common/device.c
@@ -423,6 +423,9 @@ static void hpriv_release(struct kref *ref)
mutex_destroy(&hpriv->ctx_lock);
mutex_destroy(&hpriv->restore_phase_mutex);
+ /* There should be no memory buffers at this point and handles IDR can be destroyed */
+ hl_mem_mgr_idr_destroy(&hpriv->mem_mgr);
+
/* Device should be reset if reset-upon-device-release is enabled, or if there is a pending
* reset that waits for device release.
*/
@@ -517,6 +520,10 @@ static int hl_device_release(struct inode *inode, struct file *filp)
hl_release_pending_user_interrupts(hpriv->hdev);
hl_ctx_mgr_fini(hdev, &hpriv->ctx_mgr);
+
+ /* Memory buffers might be still in use at this point and thus the handles IDR destruction
+ * is postponed to hpriv_release().
+ */
hl_mem_mgr_fini(&hpriv->mem_mgr);
hdev->compute_ctx_in_release = 1;
@@ -890,6 +897,7 @@ static int device_early_init(struct hl_device *hdev)
free_cb_mgr:
hl_mem_mgr_fini(&hdev->kernel_mem_mgr);
+ hl_mem_mgr_idr_destroy(&hdev->kernel_mem_mgr);
free_chip_info:
kfree(hdev->hl_chip_info);
free_prefetch_wq:
@@ -933,6 +941,7 @@ static void device_early_fini(struct hl_device *hdev)
mutex_destroy(&hdev->clk_throttling.lock);
hl_mem_mgr_fini(&hdev->kernel_mem_mgr);
+ hl_mem_mgr_idr_destroy(&hdev->kernel_mem_mgr);
kfree(hdev->hl_chip_info);
diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h
index e2527d976ee05..c2dcc2f66835a 100644
--- a/drivers/misc/habanalabs/common/habanalabs.h
+++ b/drivers/misc/habanalabs/common/habanalabs.h
@@ -3801,6 +3801,7 @@ const char *hl_sync_engine_to_string(enum hl_sync_engine_type engine_type);
void hl_mem_mgr_init(struct device *dev, struct hl_mem_mgr *mmg);
void hl_mem_mgr_fini(struct hl_mem_mgr *mmg);
+void hl_mem_mgr_idr_destroy(struct hl_mem_mgr *mmg);
int hl_mem_mgr_mmap(struct hl_mem_mgr *mmg, struct vm_area_struct *vma,
void *args);
struct hl_mmap_mem_buf *hl_mmap_mem_buf_get(struct hl_mem_mgr *mmg,
diff --git a/drivers/misc/habanalabs/common/habanalabs_drv.c b/drivers/misc/habanalabs/common/habanalabs_drv.c
index 7815c60df54e2..82d0242ea8670 100644
--- a/drivers/misc/habanalabs/common/habanalabs_drv.c
+++ b/drivers/misc/habanalabs/common/habanalabs_drv.c
@@ -235,6 +235,7 @@ int hl_device_open(struct inode *inode, struct file *filp)
out_err:
mutex_unlock(&hdev->fpriv_list_lock);
hl_mem_mgr_fini(&hpriv->mem_mgr);
+ hl_mem_mgr_idr_destroy(&hpriv->mem_mgr);
hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
filp->private_data = NULL;
mutex_destroy(&hpriv->ctx_lock);
diff --git a/drivers/misc/habanalabs/common/memory_mgr.c b/drivers/misc/habanalabs/common/memory_mgr.c
index 1936d653699ed..93a2b9faf419f 100644
--- a/drivers/misc/habanalabs/common/memory_mgr.c
+++ b/drivers/misc/habanalabs/common/memory_mgr.c
@@ -342,8 +342,19 @@ void hl_mem_mgr_fini(struct hl_mem_mgr *mmg)
"%s: Buff handle %u for CTX is still alive\n",
topic, id);
}
+}
- /* TODO: can it happen that some buffer is still in use at this point? */
+/**
+ * hl_mem_mgr_idr_destroy() - destroy memory manager IDR.
+ * @mmg: parent unified memory manager
+ *
+ * Destroy the memory manager IDR.
+ * Shall be called when IDR is empty and no memory buffers are in use.
+ */
+void hl_mem_mgr_idr_destroy(struct hl_mem_mgr *mmg)
+{
+ if (!idr_is_empty(&mmg->handles))
+ dev_crit(mmg->dev, "memory manager IDR is destroyed while it is not empty!\n");
idr_destroy(&mmg->handles);
}
--
2.39.2
^ permalink raw reply related [relevance 10%]
* [PATCH AUTOSEL 6.3 11/44] accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release()
@ 2023-05-01 2:55 10% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2023-05-01 2:55 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Tomer Tayar, Oded Gabbay, Sasha Levin, stanislaw.gruszka, gregkh,
dhirschfeld, dliberman, osharabi, obitton, talcohen, ynudelman,
fkassabri, bjauhari, colin.i.king, dri-devel
From: Tomer Tayar <ttayar@habana.ai>
[ Upstream commit 2e8e9a895c4589f124a37fc84d123b5114406e94 ]
The memory manager IDR is currently destroyed when user releases the
file descriptor.
However, at this point the user context might be still held, and memory
buffers might be still in use.
Later on, calls to release those buffers will fail due to not finding
their handles in the IDR, leading to a memory leak.
To avoid this leak, split the IDR destruction from the memory manager
fini, and postpone it to hpriv_release() when there is no user context
and no buffers are used.
Signed-off-by: Tomer Tayar <ttayar@habana.ai>
Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/accel/habanalabs/common/device.c | 9 +++++++++
drivers/accel/habanalabs/common/habanalabs.h | 1 +
drivers/accel/habanalabs/common/habanalabs_drv.c | 1 +
drivers/accel/habanalabs/common/memory_mgr.c | 13 ++++++++++++-
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/accel/habanalabs/common/device.c b/drivers/accel/habanalabs/common/device.c
index 9933e5858a363..c91436609f080 100644
--- a/drivers/accel/habanalabs/common/device.c
+++ b/drivers/accel/habanalabs/common/device.c
@@ -423,6 +423,9 @@ static void hpriv_release(struct kref *ref)
mutex_destroy(&hpriv->ctx_lock);
mutex_destroy(&hpriv->restore_phase_mutex);
+ /* There should be no memory buffers at this point and handles IDR can be destroyed */
+ hl_mem_mgr_idr_destroy(&hpriv->mem_mgr);
+
/* Device should be reset if reset-upon-device-release is enabled, or if there is a pending
* reset that waits for device release.
*/
@@ -514,6 +517,10 @@ static int hl_device_release(struct inode *inode, struct file *filp)
}
hl_ctx_mgr_fini(hdev, &hpriv->ctx_mgr);
+
+ /* Memory buffers might be still in use at this point and thus the handles IDR destruction
+ * is postponed to hpriv_release().
+ */
hl_mem_mgr_fini(&hpriv->mem_mgr);
hdev->compute_ctx_in_release = 1;
@@ -887,6 +894,7 @@ static int device_early_init(struct hl_device *hdev)
free_cb_mgr:
hl_mem_mgr_fini(&hdev->kernel_mem_mgr);
+ hl_mem_mgr_idr_destroy(&hdev->kernel_mem_mgr);
free_chip_info:
kfree(hdev->hl_chip_info);
free_prefetch_wq:
@@ -930,6 +938,7 @@ static void device_early_fini(struct hl_device *hdev)
mutex_destroy(&hdev->clk_throttling.lock);
hl_mem_mgr_fini(&hdev->kernel_mem_mgr);
+ hl_mem_mgr_idr_destroy(&hdev->kernel_mem_mgr);
kfree(hdev->hl_chip_info);
diff --git a/drivers/accel/habanalabs/common/habanalabs.h b/drivers/accel/habanalabs/common/habanalabs.h
index fa05e76d3d21a..829b30ab1961a 100644
--- a/drivers/accel/habanalabs/common/habanalabs.h
+++ b/drivers/accel/habanalabs/common/habanalabs.h
@@ -3861,6 +3861,7 @@ const char *hl_sync_engine_to_string(enum hl_sync_engine_type engine_type);
void hl_mem_mgr_init(struct device *dev, struct hl_mem_mgr *mmg);
void hl_mem_mgr_fini(struct hl_mem_mgr *mmg);
+void hl_mem_mgr_idr_destroy(struct hl_mem_mgr *mmg);
int hl_mem_mgr_mmap(struct hl_mem_mgr *mmg, struct vm_area_struct *vma,
void *args);
struct hl_mmap_mem_buf *hl_mmap_mem_buf_get(struct hl_mem_mgr *mmg,
diff --git a/drivers/accel/habanalabs/common/habanalabs_drv.c b/drivers/accel/habanalabs/common/habanalabs_drv.c
index 03dae57dc8386..e3781cfe8a7fe 100644
--- a/drivers/accel/habanalabs/common/habanalabs_drv.c
+++ b/drivers/accel/habanalabs/common/habanalabs_drv.c
@@ -237,6 +237,7 @@ int hl_device_open(struct inode *inode, struct file *filp)
out_err:
mutex_unlock(&hdev->fpriv_list_lock);
hl_mem_mgr_fini(&hpriv->mem_mgr);
+ hl_mem_mgr_idr_destroy(&hpriv->mem_mgr);
hl_ctx_mgr_fini(hpriv->hdev, &hpriv->ctx_mgr);
filp->private_data = NULL;
mutex_destroy(&hpriv->ctx_lock);
diff --git a/drivers/accel/habanalabs/common/memory_mgr.c b/drivers/accel/habanalabs/common/memory_mgr.c
index 0f2759e265477..f8e8261cc83d8 100644
--- a/drivers/accel/habanalabs/common/memory_mgr.c
+++ b/drivers/accel/habanalabs/common/memory_mgr.c
@@ -341,8 +341,19 @@ void hl_mem_mgr_fini(struct hl_mem_mgr *mmg)
"%s: Buff handle %u for CTX is still alive\n",
topic, id);
}
+}
- /* TODO: can it happen that some buffer is still in use at this point? */
+/**
+ * hl_mem_mgr_idr_destroy() - destroy memory manager IDR.
+ * @mmg: parent unified memory manager
+ *
+ * Destroy the memory manager IDR.
+ * Shall be called when IDR is empty and no memory buffers are in use.
+ */
+void hl_mem_mgr_idr_destroy(struct hl_mem_mgr *mmg)
+{
+ if (!idr_is_empty(&mmg->handles))
+ dev_crit(mmg->dev, "memory manager IDR is destroyed while it is not empty!\n");
idr_destroy(&mmg->handles);
}
--
2.39.2
^ permalink raw reply related [relevance 10%]
* [PATCH 14/21] drm/amd/display: Fix in secure display context creation
[not found] <20230420234951.1772270-1-Rodrigo.Siqueira@amd.com>
@ 2023-04-20 23:49 5% ` Rodrigo Siqueira
0 siblings, 0 replies; 200+ results
From: Rodrigo Siqueira @ 2023-04-20 23:49 UTC (permalink / raw)
To: amd-gfx
Cc: Harry.Wentland, Sunpeng.Li, Bhawanpreet.Lakha, Rodrigo.Siqueira,
Aurabindo.Pillai, qingqing.zhuo, roman.li, wayne.lin,
stylon.wang, solomon.chiu, pavle.kotarac, agustin.gutierrez,
Alan Liu, stable, Wayne Lin
From: Alan Liu <HaoPing.Liu@amd.com>
[Why & How]
We need to store CRTC information in secure_display_ctx, so postpone
the call to amdgpu_dm_crtc_secure_display_create_contexts() until we
initialize all CRTCs.
Cc: stable@vger.kernel.org
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alan Liu <HaoPing.Liu@amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++++------
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 2 +-
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 4db4f5a371a5..48c94e7c3839 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1775,12 +1775,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
dc_init_callbacks(adev->dm.dc, &init_params);
}
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
- adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
- if (!adev->dm.secure_display_ctxs) {
- DRM_ERROR("amdgpu: failed to initialize secure_display_ctxs.\n");
- }
-#endif
if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
init_completion(&adev->dm.dmub_aux_transfer_done);
adev->dm.dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_KERNEL);
@@ -1839,6 +1833,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
goto error;
}
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+ adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
+ if (!adev->dm.secure_display_ctxs)
+ DRM_ERROR("amdgpu: failed to initialize secure display contexts.\n");
+#endif
DRM_DEBUG_DRIVER("KMS initialized.\n");
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
index 935adca6f048..748e80ef40d0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
@@ -100,7 +100,7 @@ struct secure_display_context *amdgpu_dm_crtc_secure_display_create_contexts(
#else
#define amdgpu_dm_crc_window_is_activated(x)
#define amdgpu_dm_crtc_handle_crc_window_irq(x)
-#define amdgpu_dm_crtc_secure_display_create_contexts()
+#define amdgpu_dm_crtc_secure_display_create_contexts(x)
#endif
#endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */
--
2.39.2
^ permalink raw reply related [relevance 5%]
* Re: Linux 6.2.11
@ 2023-04-13 15:19 1% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-04-13 15:19 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/Documentation/devicetree/bindings/serial/renesas,scif.yaml b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
index f81f2d67a1ed..38391a5d96bf 100644
--- a/Documentation/devicetree/bindings/serial/renesas,scif.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
@@ -92,7 +92,7 @@ properties:
- description: Error interrupt
- description: Receive buffer full interrupt
- description: Transmit buffer empty interrupt
- - description: Transmit End interrupt
+ - description: Break interrupt
- items:
- description: Error interrupt
- description: Receive buffer full interrupt
@@ -107,7 +107,7 @@ properties:
- const: eri
- const: rxi
- const: txi
- - const: tei
+ - const: bri
- items:
- const: eri
- const: rxi
diff --git a/Documentation/mm/zsmalloc.rst b/Documentation/mm/zsmalloc.rst
index 6e79893d6132..d98607aa9c1f 100644
--- a/Documentation/mm/zsmalloc.rst
+++ b/Documentation/mm/zsmalloc.rst
@@ -68,6 +68,8 @@ pages_used
the number of pages allocated for the class
pages_per_zspage
the number of 0-order pages to make a zspage
+freeable
+ the approximate number of pages class compaction can free
We assign a zspage to ZS_ALMOST_EMPTY fullness group when n <= N / f, where
diff --git a/Makefile b/Makefile
index 6ec0ec452e46..416490daa76a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 2
-SUBLEVEL = 10
+SUBLEVEL = 11
EXTRAVERSION =
NAME = Hurr durr I'ma ninja sloth
diff --git a/arch/arm64/kernel/compat_alignment.c b/arch/arm64/kernel/compat_alignment.c
index 5edec2f49ec9..deff21bfa680 100644
--- a/arch/arm64/kernel/compat_alignment.c
+++ b/arch/arm64/kernel/compat_alignment.c
@@ -314,36 +314,32 @@ int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs)
int (*handler)(unsigned long addr, u32 instr, struct pt_regs *regs);
unsigned int type;
u32 instr = 0;
- u16 tinstr = 0;
int isize = 4;
int thumb2_32b = 0;
- int fault;
instrptr = instruction_pointer(regs);
if (compat_thumb_mode(regs)) {
__le16 __user *ptr = (__le16 __user *)(instrptr & ~1);
+ u16 tinstr, tinst2;
- fault = alignment_get_thumb(regs, ptr, &tinstr);
- if (!fault) {
- if (IS_T32(tinstr)) {
- /* Thumb-2 32-bit */
- u16 tinst2;
- fault = alignment_get_thumb(regs, ptr + 1, &tinst2);
- instr = ((u32)tinstr << 16) | tinst2;
- thumb2_32b = 1;
- } else {
- isize = 2;
- instr = thumb2arm(tinstr);
- }
+ if (alignment_get_thumb(regs, ptr, &tinstr))
+ return 1;
+
+ if (IS_T32(tinstr)) { /* Thumb-2 32-bit */
+ if (alignment_get_thumb(regs, ptr + 1, &tinst2))
+ return 1;
+ instr = ((u32)tinstr << 16) | tinst2;
+ thumb2_32b = 1;
+ } else {
+ isize = 2;
+ instr = thumb2arm(tinstr);
}
} else {
- fault = alignment_get_arm(regs, (__le32 __user *)instrptr, &instr);
+ if (alignment_get_arm(regs, (__le32 __user *)instrptr, &instr))
+ return 1;
}
- if (fault)
- return 1;
-
switch (CODING_BITS(instr)) {
case 0x00000000: /* 3.13.4 load/store instruction extensions */
if (LDSTHD_I_BIT(instr))
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 0ee02dae14b2..2cda8d9d7c6e 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -271,10 +271,18 @@ static int handle_prog(struct kvm_vcpu *vcpu)
* handle_external_interrupt - used for external interruption interceptions
* @vcpu: virtual cpu
*
- * This interception only occurs if the CPUSTAT_EXT_INT bit was set, or if
- * the new PSW does not have external interrupts disabled. In the first case,
- * we've got to deliver the interrupt manually, and in the second case, we
- * drop to userspace to handle the situation there.
+ * This interception occurs if:
+ * - the CPUSTAT_EXT_INT bit was already set when the external interrupt
+ * occurred. In this case, the interrupt needs to be injected manually to
+ * preserve interrupt priority.
+ * - the external new PSW has external interrupts enabled, which will cause an
+ * interruption loop. We drop to userspace in this case.
+ *
+ * The latter case can be detected by inspecting the external mask bit in the
+ * external new psw.
+ *
+ * Under PV, only the latter case can occur, since interrupt priorities are
+ * handled in the ultravisor.
*/
static int handle_external_interrupt(struct kvm_vcpu *vcpu)
{
@@ -285,10 +293,18 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu)
vcpu->stat.exit_external_interrupt++;
- rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t));
- if (rc)
- return rc;
- /* We can not handle clock comparator or timer interrupt with bad PSW */
+ if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+ newpsw = vcpu->arch.sie_block->gpsw;
+ } else {
+ rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t));
+ if (rc)
+ return rc;
+ }
+
+ /*
+ * Clock comparator or timer interrupt with external interrupt enabled
+ * will cause interrupt loop. Drop to userspace.
+ */
if ((eic == EXT_IRQ_CLK_COMP || eic == EXT_IRQ_CPU_TIMER) &&
(newpsw.mask & PSW_MASK_EXT))
return -EOPNOTSUPP;
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 518bda50068c..0f762070a5e1 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -146,7 +146,11 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
pr_debug("Local APIC address 0x%08x\n", madt->address);
}
- if (madt->header.revision >= 5)
+
+ /* ACPI 6.3 and newer support the online capable bit. */
+ if (acpi_gbl_FADT.header.revision > 6 ||
+ (acpi_gbl_FADT.header.revision == 6 &&
+ acpi_gbl_FADT.minor_revision >= 3))
acpi_support_online_capable = true;
default_acpi_madt_oem_check(madt->header.oem_id,
@@ -193,7 +197,8 @@ static bool __init acpi_is_processor_usable(u32 lapic_flags)
if (lapic_flags & ACPI_MADT_ENABLED)
return true;
- if (acpi_support_online_capable && (lapic_flags & ACPI_MADT_ONLINE_CAPABLE))
+ if (!acpi_support_online_capable ||
+ (lapic_flags & ACPI_MADT_ONLINE_CAPABLE))
return true;
return false;
diff --git a/arch/x86/kvm/kvm_onhyperv.h b/arch/x86/kvm/kvm_onhyperv.h
index 287e98ef9df3..6272dabec02d 100644
--- a/arch/x86/kvm/kvm_onhyperv.h
+++ b/arch/x86/kvm/kvm_onhyperv.h
@@ -12,6 +12,11 @@ int hv_remote_flush_tlb_with_range(struct kvm *kvm,
int hv_remote_flush_tlb(struct kvm *kvm);
void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp);
#else /* !CONFIG_HYPERV */
+static inline int hv_remote_flush_tlb(struct kvm *kvm)
+{
+ return -EOPNOTSUPP;
+}
+
static inline void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp)
{
}
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index f03bdaf79c88..a682ca4c9fe1 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3718,7 +3718,7 @@ static void svm_enable_nmi_window(struct kvm_vcpu *vcpu)
svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
}
-static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
+static void svm_flush_tlb_asid(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -3742,6 +3742,37 @@ static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
svm->current_vmcb->asid_generation--;
}
+static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
+{
+ hpa_t root_tdp = vcpu->arch.mmu->root.hpa;
+
+ /*
+ * When running on Hyper-V with EnlightenedNptTlb enabled, explicitly
+ * flush the NPT mappings via hypercall as flushing the ASID only
+ * affects virtual to physical mappings, it does not invalidate guest
+ * physical to host physical mappings.
+ */
+ if (svm_hv_is_enlightened_tlb_enabled(vcpu) && VALID_PAGE(root_tdp))
+ hyperv_flush_guest_mapping(root_tdp);
+
+ svm_flush_tlb_asid(vcpu);
+}
+
+static void svm_flush_tlb_all(struct kvm_vcpu *vcpu)
+{
+ /*
+ * When running on Hyper-V with EnlightenedNptTlb enabled, remote TLB
+ * flushes should be routed to hv_remote_flush_tlb() without requesting
+ * a "regular" remote flush. Reaching this point means either there's
+ * a KVM bug or a prior hv_remote_flush_tlb() call failed, both of
+ * which might be fatal to the guest. Yell, but try to recover.
+ */
+ if (WARN_ON_ONCE(svm_hv_is_enlightened_tlb_enabled(vcpu)))
+ hv_remote_flush_tlb(vcpu->kvm);
+
+ svm_flush_tlb_asid(vcpu);
+}
+
static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -4747,10 +4778,10 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
.set_rflags = svm_set_rflags,
.get_if_flag = svm_get_if_flag,
- .flush_tlb_all = svm_flush_tlb_current,
+ .flush_tlb_all = svm_flush_tlb_all,
.flush_tlb_current = svm_flush_tlb_current,
.flush_tlb_gva = svm_flush_tlb_gva,
- .flush_tlb_guest = svm_flush_tlb_current,
+ .flush_tlb_guest = svm_flush_tlb_asid,
.vcpu_pre_run = svm_vcpu_pre_run,
.vcpu_run = svm_vcpu_run,
diff --git a/arch/x86/kvm/svm/svm_onhyperv.h b/arch/x86/kvm/svm/svm_onhyperv.h
index 65c355b4b8bf..345b87acf9b0 100644
--- a/arch/x86/kvm/svm/svm_onhyperv.h
+++ b/arch/x86/kvm/svm/svm_onhyperv.h
@@ -6,6 +6,8 @@
#ifndef __ARCH_X86_KVM_SVM_ONHYPERV_H__
#define __ARCH_X86_KVM_SVM_ONHYPERV_H__
+#include <asm/mshyperv.h>
+
#if IS_ENABLED(CONFIG_HYPERV)
#include "kvm_onhyperv.h"
@@ -15,6 +17,14 @@ static struct kvm_x86_ops svm_x86_ops;
int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu);
+static inline bool svm_hv_is_enlightened_tlb_enabled(struct kvm_vcpu *vcpu)
+{
+ struct hv_vmcb_enlightenments *hve = &to_svm(vcpu)->vmcb->control.hv_enlightenments;
+
+ return ms_hyperv.nested_features & HV_X64_NESTED_ENLIGHTENED_TLB &&
+ !!hve->hv_enlightenments_control.enlightened_npt_tlb;
+}
+
static inline void svm_hv_init_vmcb(struct vmcb *vmcb)
{
struct hv_vmcb_enlightenments *hve = &vmcb->control.hv_enlightenments;
@@ -80,6 +90,11 @@ static inline void svm_hv_update_vp_id(struct vmcb *vmcb, struct kvm_vcpu *vcpu)
}
#else
+static inline bool svm_hv_is_enlightened_tlb_enabled(struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+
static inline void svm_hv_init_vmcb(struct vmcb *vmcb)
{
}
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index bceb5ad409c6..b7f2e59d50ee 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -3873,7 +3873,12 @@ static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu)
exit_qual = 0;
}
- if (ex->has_error_code) {
+ /*
+ * Unlike AMD's Paged Real Mode, which reports an error code on #PF
+ * VM-Exits even if the CPU is in Real Mode, Intel VMX never sets the
+ * "has error code" flags on VM-Exit if the CPU is in Real Mode.
+ */
+ if (ex->has_error_code && is_protmode(vcpu)) {
/*
* Intel CPUs do not generate error codes with bits 31:16 set,
* and more importantly VMX disallows setting bits 31:16 in the
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0ec7a0cb5da8..2d76c254582b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9795,13 +9795,20 @@ int kvm_check_nested_events(struct kvm_vcpu *vcpu)
static void kvm_inject_exception(struct kvm_vcpu *vcpu)
{
+ /*
+ * Suppress the error code if the vCPU is in Real Mode, as Real Mode
+ * exceptions don't report error codes. The presence of an error code
+ * is carried with the exception and only stripped when the exception
+ * is injected as intercepted #PF VM-Exits for AMD's Paged Real Mode do
+ * report an error code despite the CPU being in Real Mode.
+ */
+ vcpu->arch.exception.has_error_code &= is_protmode(vcpu);
+
trace_kvm_inj_exception(vcpu->arch.exception.vector,
vcpu->arch.exception.has_error_code,
vcpu->arch.exception.error_code,
vcpu->arch.exception.injected);
- if (vcpu->arch.exception.error_code && !is_protmode(vcpu))
- vcpu->arch.exception.error_code = false;
static_call(kvm_x86_inject_exception)(vcpu);
}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index c021fb05161b..86425167594c 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1359,8 +1359,6 @@ bool blk_rq_is_poll(struct request *rq)
return false;
if (rq->mq_hctx->type != HCTX_TYPE_POLL)
return false;
- if (WARN_ON_ONCE(!rq->bio))
- return false;
return true;
}
EXPORT_SYMBOL_GPL(blk_rq_is_poll);
@@ -1368,7 +1366,7 @@ EXPORT_SYMBOL_GPL(blk_rq_is_poll);
static void blk_rq_poll_completion(struct request *rq, struct completion *wait)
{
do {
- bio_poll(rq->bio, NULL, 0);
+ blk_mq_poll(rq->q, blk_rq_to_qc(rq), NULL, 0);
cond_resched();
} while (!completion_done(wait));
}
diff --git a/block/genhd.c b/block/genhd.c
index 9c4c9aa559ab..708203263603 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -368,7 +368,6 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
if (disk->open_partitions)
return -EBUSY;
- set_bit(GD_NEED_PART_SCAN, &disk->state);
/*
* If the device is opened exclusively by current thread already, it's
* safe to scan partitons, otherwise, use bd_prepare_to_claim() to
@@ -381,12 +380,19 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
return ret;
}
+ set_bit(GD_NEED_PART_SCAN, &disk->state);
bdev = blkdev_get_by_dev(disk_devt(disk), mode & ~FMODE_EXCL, NULL);
if (IS_ERR(bdev))
ret = PTR_ERR(bdev);
else
blkdev_put(bdev, mode & ~FMODE_EXCL);
+ /*
+ * If blkdev_get_by_dev() failed early, GD_NEED_PART_SCAN is still set,
+ * and this will cause that re-assemble partitioned raid device will
+ * creat partition for underlying disk.
+ */
+ clear_bit(GD_NEED_PART_SCAN, &disk->state);
if (!(mode & FMODE_EXCL))
bd_abort_claiming(disk->part0, disk_scan_partitions);
return ret;
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index 97b711e57bff..c7a6d0b69dab 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -1984,6 +1984,7 @@ static int instance;
static int acpi_video_bus_add(struct acpi_device *device)
{
struct acpi_video_bus *video;
+ bool auto_detect;
int error;
acpi_status status;
@@ -2045,10 +2046,20 @@ static int acpi_video_bus_add(struct acpi_device *device)
mutex_unlock(&video_list_lock);
/*
- * The userspace visible backlight_device gets registered separately
- * from acpi_video_register_backlight().
+ * If backlight-type auto-detection is used then a native backlight may
+ * show up later and this may change the result from video to native.
+ * Therefor normally the userspace visible /sys/class/backlight device
+ * gets registered separately by the GPU driver calling
+ * acpi_video_register_backlight() when an internal panel is detected.
+ * Register the backlight now when not using auto-detection, so that
+ * when the kernel cmdline or DMI-quirks are used the backlight will
+ * get registered even if acpi_video_register_backlight() is not called.
*/
acpi_video_run_bcl_for_osi(video);
+ if (__acpi_video_get_backlight_type(false, &auto_detect) == acpi_backlight_video &&
+ !auto_detect)
+ acpi_video_bus_register_backlight(video);
+
acpi_video_bus_add_notify_handler(video);
return 0;
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 14d6d81e536f..b3b0b06971df 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -276,6 +276,43 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
},
+ /*
+ * Models which need acpi_video backlight control where the GPU drivers
+ * do not call acpi_video_register_backlight() because no internal panel
+ * is detected. Typically these are all-in-ones (monitors with builtin
+ * PC) where the panel connection shows up as regular DP instead of eDP.
+ */
+ {
+ .callback = video_detect_force_video,
+ /* Apple iMac14,1 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac14,1"),
+ },
+ },
+ {
+ .callback = video_detect_force_video,
+ /* Apple iMac14,2 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac14,2"),
+ },
+ },
+
+ /*
+ * Older models with nvidia GPU which need acpi_video backlight
+ * control and where the old nvidia binary driver series does not
+ * call acpi_video_register_backlight().
+ */
+ {
+ .callback = video_detect_force_video,
+ /* ThinkPad W530 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"),
+ },
+ },
+
/*
* These models have a working acpi_video backlight control, and using
* native backlight causes a regression where backlight does not work
@@ -774,7 +811,7 @@ static bool prefer_native_over_acpi_video(void)
* Determine which type of backlight interface to use on this system,
* First check cmdline, then dmi quirks, then do autodetect.
*/
-static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
+enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto_detect)
{
static DEFINE_MUTEX(init_mutex);
static bool nvidia_wmi_ec_present;
@@ -799,6 +836,9 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
native_available = true;
mutex_unlock(&init_mutex);
+ if (auto_detect)
+ *auto_detect = false;
+
/*
* The below heuristics / detection steps are in order of descending
* presedence. The commandline takes presedence over anything else.
@@ -810,6 +850,9 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
if (acpi_backlight_dmi != acpi_backlight_undef)
return acpi_backlight_dmi;
+ if (auto_detect)
+ *auto_detect = true;
+
/* Special cases such as nvidia_wmi_ec and apple gmux. */
if (nvidia_wmi_ec_present)
return acpi_backlight_nvidia_wmi_ec;
@@ -829,15 +872,4 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
/* No ACPI video/native (old hw), use vendor specific fw methods. */
return acpi_backlight_vendor;
}
-
-enum acpi_backlight_type acpi_video_get_backlight_type(void)
-{
- return __acpi_video_get_backlight_type(false);
-}
-EXPORT_SYMBOL(acpi_video_get_backlight_type);
-
-bool acpi_video_backlight_use_native(void)
-{
- return __acpi_video_get_backlight_type(true) == acpi_backlight_native;
-}
-EXPORT_SYMBOL(acpi_video_backlight_use_native);
+EXPORT_SYMBOL(__acpi_video_get_backlight_type);
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 22a790d51284..2ed994a313a9 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -233,7 +233,7 @@ static int ublk_validate_params(const struct ublk_device *ub)
if (ub->params.types & UBLK_PARAM_TYPE_BASIC) {
const struct ublk_param_basic *p = &ub->params.basic;
- if (p->logical_bs_shift > PAGE_SHIFT)
+ if (p->logical_bs_shift > PAGE_SHIFT || p->logical_bs_shift < 9)
return -EINVAL;
if (p->logical_bs_shift > p->physical_bs_shift)
@@ -1202,9 +1202,10 @@ static void ublk_handle_need_get_data(struct ublk_device *ub, int q_id,
ublk_queue_cmd(ubq, req);
}
-static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
+static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
+ unsigned int issue_flags,
+ struct ublksrv_io_cmd *ub_cmd)
{
- struct ublksrv_io_cmd *ub_cmd = (struct ublksrv_io_cmd *)cmd->cmd;
struct ublk_device *ub = cmd->file->private_data;
struct ublk_queue *ubq;
struct ublk_io *io;
@@ -1306,6 +1307,23 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
return -EIOCBQUEUED;
}
+static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
+{
+ struct ublksrv_io_cmd *ub_src = (struct ublksrv_io_cmd *) cmd->cmd;
+ struct ublksrv_io_cmd ub_cmd;
+
+ /*
+ * Not necessary for async retry, but let's keep it simple and always
+ * copy the values to avoid any potential reuse.
+ */
+ ub_cmd.q_id = READ_ONCE(ub_src->q_id);
+ ub_cmd.tag = READ_ONCE(ub_src->tag);
+ ub_cmd.result = READ_ONCE(ub_src->result);
+ ub_cmd.addr = READ_ONCE(ub_src->addr);
+
+ return __ublk_ch_uring_cmd(cmd, issue_flags, &ub_cmd);
+}
+
static const struct file_operations ublk_ch_fops = {
.owner = THIS_MODULE,
.open = ublk_ch_open,
@@ -1886,6 +1904,8 @@ static int ublk_ctrl_set_params(struct io_uring_cmd *cmd)
/* clear all we don't support yet */
ub->params.types &= UBLK_PARAM_TYPE_ALL;
ret = ublk_validate_params(ub);
+ if (ret)
+ ub->params.types = 0;
}
mutex_unlock(&ub->mutex);
ublk_put_device(ub);
diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
index deed4afadb29..d9cb937665cf 100644
--- a/drivers/counter/104-quad-8.c
+++ b/drivers/counter/104-quad-8.c
@@ -97,10 +97,6 @@ struct quad8 {
struct quad8_reg __iomem *reg;
};
-/* Borrow Toggle flip-flop */
-#define QUAD8_FLAG_BT BIT(0)
-/* Carry Toggle flip-flop */
-#define QUAD8_FLAG_CT BIT(1)
/* Error flag */
#define QUAD8_FLAG_E BIT(4)
/* Up/Down flag */
@@ -133,6 +129,9 @@ struct quad8 {
#define QUAD8_CMR_QUADRATURE_X2 0x10
#define QUAD8_CMR_QUADRATURE_X4 0x18
+/* Each Counter is 24 bits wide */
+#define LS7267_CNTR_MAX GENMASK(23, 0)
+
static int quad8_signal_read(struct counter_device *counter,
struct counter_signal *signal,
enum counter_signal_level *level)
@@ -156,18 +155,10 @@ static int quad8_count_read(struct counter_device *counter,
{
struct quad8 *const priv = counter_priv(counter);
struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
- unsigned int flags;
- unsigned int borrow;
- unsigned int carry;
unsigned long irqflags;
int i;
- flags = ioread8(&chan->control);
- borrow = flags & QUAD8_FLAG_BT;
- carry = !!(flags & QUAD8_FLAG_CT);
-
- /* Borrow XOR Carry effectively doubles count range */
- *val = (unsigned long)(borrow ^ carry) << 24;
+ *val = 0;
spin_lock_irqsave(&priv->lock, irqflags);
@@ -191,8 +182,7 @@ static int quad8_count_write(struct counter_device *counter,
unsigned long irqflags;
int i;
- /* Only 24-bit values are supported */
- if (val > 0xFFFFFF)
+ if (val > LS7267_CNTR_MAX)
return -ERANGE;
spin_lock_irqsave(&priv->lock, irqflags);
@@ -378,7 +368,7 @@ static int quad8_action_read(struct counter_device *counter,
/* Handle Index signals */
if (synapse->signal->id >= 16) {
- if (priv->preset_enable[count->id])
+ if (!priv->preset_enable[count->id])
*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
else
*action = COUNTER_SYNAPSE_ACTION_NONE;
@@ -806,8 +796,7 @@ static int quad8_count_preset_write(struct counter_device *counter,
struct quad8 *const priv = counter_priv(counter);
unsigned long irqflags;
- /* Only 24-bit values are supported */
- if (preset > 0xFFFFFF)
+ if (preset > LS7267_CNTR_MAX)
return -ERANGE;
spin_lock_irqsave(&priv->lock, irqflags);
@@ -834,8 +823,7 @@ static int quad8_count_ceiling_read(struct counter_device *counter,
*ceiling = priv->preset[count->id];
break;
default:
- /* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
- *ceiling = 0x1FFFFFF;
+ *ceiling = LS7267_CNTR_MAX;
break;
}
@@ -850,8 +838,7 @@ static int quad8_count_ceiling_write(struct counter_device *counter,
struct quad8 *const priv = counter_priv(counter);
unsigned long irqflags;
- /* Only 24-bit values are supported */
- if (ceiling > 0xFFFFFF)
+ if (ceiling > LS7267_CNTR_MAX)
return -ERANGE;
spin_lock_irqsave(&priv->lock, irqflags);
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 57764e9cd19d..76596cd18621 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -480,7 +480,7 @@ static struct pci_doe_mb *find_cdat_doe(struct device *uport)
return NULL;
}
-#define CDAT_DOE_REQ(entry_handle) \
+#define CDAT_DOE_REQ(entry_handle) cpu_to_le32 \
(FIELD_PREP(CXL_DOE_TABLE_ACCESS_REQ_CODE, \
CXL_DOE_TABLE_ACCESS_REQ_CODE_READ) | \
FIELD_PREP(CXL_DOE_TABLE_ACCESS_TABLE_TYPE, \
@@ -493,8 +493,8 @@ static void cxl_doe_task_complete(struct pci_doe_task *task)
}
struct cdat_doe_task {
- u32 request_pl;
- u32 response_pl[32];
+ __le32 request_pl;
+ __le32 response_pl[32];
struct completion c;
struct pci_doe_task task;
};
@@ -528,10 +528,10 @@ static int cxl_cdat_get_length(struct device *dev,
return rc;
}
wait_for_completion(&t.c);
- if (t.task.rv < sizeof(u32))
+ if (t.task.rv < 2 * sizeof(__le32))
return -EIO;
- *length = t.response_pl[1];
+ *length = le32_to_cpu(t.response_pl[1]);
dev_dbg(dev, "CDAT length %zu\n", *length);
return 0;
@@ -542,13 +542,13 @@ static int cxl_cdat_read_table(struct device *dev,
struct cxl_cdat *cdat)
{
size_t length = cdat->length;
- u32 *data = cdat->table;
+ __le32 *data = cdat->table;
int entry_handle = 0;
do {
DECLARE_CDAT_DOE_TASK(CDAT_DOE_REQ(entry_handle), t);
+ struct cdat_entry_header *entry;
size_t entry_dw;
- u32 *entry;
int rc;
rc = pci_doe_submit_task(cdat_doe, &t.task);
@@ -557,26 +557,34 @@ static int cxl_cdat_read_table(struct device *dev,
return rc;
}
wait_for_completion(&t.c);
- /* 1 DW header + 1 DW data min */
- if (t.task.rv < (2 * sizeof(u32)))
+
+ /* 1 DW Table Access Response Header + CDAT entry */
+ entry = (struct cdat_entry_header *)(t.response_pl + 1);
+ if ((entry_handle == 0 &&
+ t.task.rv != sizeof(__le32) + sizeof(struct cdat_header)) ||
+ (entry_handle > 0 &&
+ (t.task.rv < sizeof(__le32) + sizeof(*entry) ||
+ t.task.rv != sizeof(__le32) + le16_to_cpu(entry->length))))
return -EIO;
/* Get the CXL table access header entry handle */
entry_handle = FIELD_GET(CXL_DOE_TABLE_ACCESS_ENTRY_HANDLE,
- t.response_pl[0]);
- entry = t.response_pl + 1;
- entry_dw = t.task.rv / sizeof(u32);
+ le32_to_cpu(t.response_pl[0]));
+ entry_dw = t.task.rv / sizeof(__le32);
/* Skip Header */
entry_dw -= 1;
- entry_dw = min(length / sizeof(u32), entry_dw);
+ entry_dw = min(length / sizeof(__le32), entry_dw);
/* Prevent length < 1 DW from causing a buffer overflow */
if (entry_dw) {
- memcpy(data, entry, entry_dw * sizeof(u32));
- length -= entry_dw * sizeof(u32);
+ memcpy(data, entry, entry_dw * sizeof(__le32));
+ length -= entry_dw * sizeof(__le32);
data += entry_dw;
}
} while (entry_handle != CXL_DOE_TABLE_ACCESS_LAST_ENTRY);
+ /* Length in CDAT header may exceed concatenation of CDAT entries */
+ cdat->length -= length;
+
return 0;
}
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index 920909791bb9..104ad2b72516 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -62,6 +62,20 @@ enum cxl_regloc_type {
CXL_REGLOC_RBI_TYPES
};
+struct cdat_header {
+ __le32 length;
+ u8 revision;
+ u8 checksum;
+ u8 reserved[6];
+ __le32 sequence;
+} __packed;
+
+struct cdat_entry_header {
+ u8 type;
+ u8 reserved;
+ __le16 length;
+} __packed;
+
int devm_cxl_port_enumerate_dports(struct cxl_port *port);
struct cxl_dev_state;
int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e9917a45b005..42e5042d0149 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -100,7 +100,7 @@ config GPIO_GENERIC
tristate
config GPIO_REGMAP
- depends on REGMAP
+ select REGMAP
tristate
# put drivers in the right section, in alphabetical order
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index fa51a91afa54..7a26919ff127 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -325,7 +325,7 @@ static struct irq_chip gpio_irqchip = {
.irq_enable = gpio_irq_enable,
.irq_disable = gpio_irq_disable,
.irq_set_type = gpio_irq_type,
- .flags = IRQCHIP_SET_TYPE_MASKED,
+ .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE,
};
static void gpio_irq_handler(struct irq_desc *desc)
@@ -642,9 +642,6 @@ static void davinci_gpio_save_context(struct davinci_gpio_controller *chips,
context->set_falling = readl_relaxed(&g->set_falling);
}
- /* Clear Bank interrupt enable bit */
- writel_relaxed(0, base + BINTEN);
-
/* Clear all interrupt status registers */
writel_relaxed(GENMASK(31, 0), &g->intstat);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d5e14a3aa05d..3dac1e139c5f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3045,6 +3045,24 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_MES))
continue;
+ /* SDMA 5.x+ is part of GFX power domain so it's covered by GFXOFF */
+ if (adev->in_s0ix &&
+ (adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(5, 0, 0)) &&
+ (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
+ continue;
+
+ /* Once swPSP provides the IMU, RLC FW binaries to TOS during cold-boot.
+ * These are in TMR, hence are expected to be reused by PSP-TOS to reload
+ * from this location and RLC Autoload automatically also gets loaded
+ * from here based on PMFW -> PSP message during re-init sequence.
+ * Therefore, the psp suspend & resume should be skipped to avoid destroy
+ * the TMR and reload FWs again for IMU enabled APU ASICs.
+ */
+ if (amdgpu_in_reset(adev) &&
+ (adev->flags & AMD_IS_APU) && adev->gfx.imu.funcs &&
+ adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
+ continue;
+
/* XXX handle errors */
r = adev->ip_blocks[i].version->funcs->suspend(adev);
/* XXX handle errors */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 8661de32d80a..7fa1728384bf 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2183,6 +2183,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev)
DRM_ERROR("DM_MST: Failed to start MST\n");
aconnector->dc_link->type =
dc_connection_single;
+ ret = dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx,
+ aconnector->dc_link);
break;
}
}
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c
index 3b77238ca4af..ae8c6d9d4095 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
@@ -258,6 +258,7 @@ static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode
{ 0x8126, 0x55 },
{ 0x8127, 0x66 },
{ 0x8128, 0x88 },
+ { 0x812a, 0x20 },
};
regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg));
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index c3928d28cd44..85a38d794dd9 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -46,6 +46,11 @@ struct intel_color_funcs {
* registers involved with the same commit.
*/
void (*color_commit_arm)(const struct intel_crtc_state *crtc_state);
+ /*
+ * Perform any extra tasks needed after all the
+ * double buffered registers have been latched.
+ */
+ void (*color_post_update)(const struct intel_crtc_state *crtc_state);
/*
* Load LUTs (and other single buffered color management
* registers). Will (hopefully) be called during the vblank
@@ -1220,6 +1225,24 @@ void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
i915->display.funcs.color->color_commit_arm(crtc_state);
}
+void intel_color_post_update(const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+ if (i915->display.funcs.color->color_post_update)
+ i915->display.funcs.color->color_post_update(crtc_state);
+}
+
+void intel_color_prepare_commit(struct intel_crtc_state *crtc_state)
+{
+ intel_dsb_prepare(crtc_state);
+}
+
+void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
+{
+ intel_dsb_cleanup(crtc_state);
+}
+
static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h
index 2a5ada67774d..0256f49c3910 100644
--- a/drivers/gpu/drm/i915/display/intel_color.h
+++ b/drivers/gpu/drm/i915/display/intel_color.h
@@ -17,8 +17,11 @@ void intel_color_init_hooks(struct drm_i915_private *i915);
int intel_color_init(struct drm_i915_private *i915);
void intel_color_crtc_init(struct intel_crtc *crtc);
int intel_color_check(struct intel_crtc_state *crtc_state);
+void intel_color_prepare_commit(struct intel_crtc_state *crtc_state);
+void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
+void intel_color_post_update(const struct intel_crtc_state *crtc_state);
void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
void intel_color_get_config(struct intel_crtc_state *crtc_state);
int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index f0aad2403109..2d46dcf820a2 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -93,7 +93,6 @@
#include "intel_dp_link_training.h"
#include "intel_dpio_phy.h"
#include "intel_dpt.h"
-#include "intel_dsb.h"
#include "intel_fbc.h"
#include "intel_fbdev.h"
#include "intel_fdi.h"
@@ -1264,6 +1263,9 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
if (needs_cursorclk_wa(old_crtc_state) &&
!needs_cursorclk_wa(new_crtc_state))
icl_wa_cursorclkgating(dev_priv, pipe, false);
+
+ if (intel_crtc_needs_color_update(new_crtc_state))
+ intel_color_post_update(new_crtc_state);
}
static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
@@ -6946,7 +6948,7 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
if (intel_crtc_needs_color_update(crtc_state))
- intel_dsb_prepare(crtc_state);
+ intel_color_prepare_commit(crtc_state);
}
return 0;
@@ -7399,24 +7401,18 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat
&wait_reset);
}
-static void intel_cleanup_dsbs(struct intel_atomic_state *state)
-{
- struct intel_crtc_state *old_crtc_state, *new_crtc_state;
- struct intel_crtc *crtc;
- int i;
-
- for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
- new_crtc_state, i)
- intel_dsb_cleanup(old_crtc_state);
-}
-
static void intel_atomic_cleanup_work(struct work_struct *work)
{
struct intel_atomic_state *state =
container_of(work, struct intel_atomic_state, base.commit_work);
struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_crtc_state *old_crtc_state;
+ struct intel_crtc *crtc;
+ int i;
+
+ for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i)
+ intel_color_cleanup_commit(old_crtc_state);
- intel_cleanup_dsbs(state);
drm_atomic_helper_cleanup_planes(&i915->drm, &state->base);
drm_atomic_helper_commit_cleanup_done(&state->base);
drm_atomic_state_put(&state->base);
@@ -7624,6 +7620,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
* DSB cleanup is done in cleanup_work aligning with framebuffer
* cleanup. So copy and reset the dsb structure to sync with
* commit_done and later do dsb cleanup in cleanup_work.
+ *
+ * FIXME get rid of this funny new->old swapping
*/
old_crtc_state->dsb = fetch_and_zero(&new_crtc_state->dsb);
}
@@ -7774,7 +7772,7 @@ static int intel_atomic_commit(struct drm_device *dev,
i915_sw_fence_commit(&state->commit_ready);
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
- intel_dsb_cleanup(new_crtc_state);
+ intel_color_cleanup_commit(new_crtc_state);
drm_atomic_helper_cleanup_planes(dev, &state->base);
intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 714030136b7f..ef73730f32b0 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -440,6 +440,14 @@ enum hpd_pin {
(__i)++) \
for_each_if(plane)
+#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
+ for ((__i) = 0; \
+ (__i) < (__state)->base.dev->mode_config.num_crtc && \
+ ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
+ (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), 1); \
+ (__i)++) \
+ for_each_if(crtc)
+
#define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \
for ((__i) = 0; \
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index 3c573d41d404..eefd327c4278 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -2018,6 +2018,8 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
* inspecting the queue to see if we need to resumbit.
*/
if (*prev != *execlists->active) { /* elide lite-restores */
+ struct intel_context *prev_ce = NULL, *active_ce = NULL;
+
/*
* Note the inherent discrepancy between the HW runtime,
* recorded as part of the context switch, and the CPU
@@ -2029,9 +2031,15 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
* and correct overselves later when updating from HW.
*/
if (*prev)
- lrc_runtime_stop((*prev)->context);
+ prev_ce = (*prev)->context;
if (*execlists->active)
- lrc_runtime_start((*execlists->active)->context);
+ active_ce = (*execlists->active)->context;
+ if (prev_ce != active_ce) {
+ if (prev_ce)
+ lrc_runtime_stop(prev_ce);
+ if (active_ce)
+ lrc_runtime_start(active_ce);
+ }
new_timeslice(execlists);
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
index 410905da8e97..0c103ca160d1 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
@@ -235,6 +235,13 @@ static void delayed_huc_load_fini(struct intel_huc *huc)
i915_sw_fence_fini(&huc->delayed_load.fence);
}
+int intel_huc_sanitize(struct intel_huc *huc)
+{
+ delayed_huc_load_complete(huc);
+ intel_uc_fw_sanitize(&huc->fw);
+ return 0;
+}
+
static bool vcs_supported(struct intel_gt *gt)
{
intel_engine_mask_t mask = gt->info.engine_mask;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.h b/drivers/gpu/drm/i915/gt/uc/intel_huc.h
index 52db03620c60..db555b3c1f56 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.h
@@ -41,6 +41,7 @@ struct intel_huc {
} delayed_load;
};
+int intel_huc_sanitize(struct intel_huc *huc);
void intel_huc_init_early(struct intel_huc *huc);
int intel_huc_init(struct intel_huc *huc);
void intel_huc_fini(struct intel_huc *huc);
@@ -54,12 +55,6 @@ bool intel_huc_is_authenticated(struct intel_huc *huc);
void intel_huc_register_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
-static inline int intel_huc_sanitize(struct intel_huc *huc)
-{
- intel_uc_fw_sanitize(&huc->fw);
- return 0;
-}
-
static inline bool intel_huc_is_supported(struct intel_huc *huc)
{
return intel_uc_fw_is_supported(&huc->fw);
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 7d5e2c53c23a..1a1b74b80e08 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -4612,13 +4612,13 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
err = oa_config->id;
goto sysfs_err;
}
-
- mutex_unlock(&perf->metrics_lock);
+ id = oa_config->id;
drm_dbg(&perf->i915->drm,
"Added config %s id=%i\n", oa_config->uuid, oa_config->id);
+ mutex_unlock(&perf->metrics_lock);
- return oa_config->id;
+ return id;
sysfs_err:
mutex_unlock(&perf->metrics_lock);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index ed9d374147b8..5bb777ff1313 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -363,6 +363,35 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,
return 0;
}
+static void
+nv50_outp_atomic_fix_depth(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state)
+{
+ struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct drm_display_mode *mode = &asyh->state.adjusted_mode;
+ unsigned int max_rate, mode_rate;
+
+ switch (nv_encoder->dcb->type) {
+ case DCB_OUTPUT_DP:
+ max_rate = nv_encoder->dp.link_nr * nv_encoder->dp.link_bw;
+
+ /* we don't support more than 10 anyway */
+ asyh->or.bpc = min_t(u8, asyh->or.bpc, 10);
+
+ /* reduce the bpc until it works out */
+ while (asyh->or.bpc > 6) {
+ mode_rate = DIV_ROUND_UP(mode->clock * asyh->or.bpc * 3, 8);
+ if (mode_rate <= max_rate)
+ break;
+
+ asyh->or.bpc -= 2;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
static int
nv50_outp_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
@@ -381,6 +410,9 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,
if (crtc_state->mode_changed || crtc_state->connectors_changed)
asyh->or.bpc = connector->display_info.bpc;
+ /* We might have to reduce the bpc */
+ nv50_outp_atomic_fix_depth(encoder, crtc_state);
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index e00876f92aee..d49b4875fc3c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -263,8 +263,6 @@ nouveau_dp_irq(struct work_struct *work)
}
/* TODO:
- * - Use the minimum possible BPC here, once we add support for the max bpc
- * property.
* - Validate against the DP caps advertised by the GPU (we don't check these
* yet)
*/
@@ -276,7 +274,11 @@ nv50_dp_mode_valid(struct drm_connector *connector,
{
const unsigned int min_clock = 25000;
unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock;
- const u8 bpp = connector->display_info.bpc * 3;
+ /* Check with the minmum bpc always, so we can advertise better modes.
+ * In particlar not doing this causes modes to be dropped on HDR
+ * displays as we might check with a bpc of 16 even.
+ */
+ const u8 bpp = 6 * 3;
if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
return MODE_NO_INTERLACE;
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 666a5e53fe19..e961fa27702c 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -504,6 +504,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
if (IS_ERR(pages[i])) {
mutex_unlock(&bo->base.pages_lock);
ret = PTR_ERR(pages[i]);
+ pages[i] = NULL;
goto err_pages;
}
}
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 9dc27e5d367a..da51b50787df 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -409,6 +409,10 @@ void vmbus_disconnect(void)
*/
struct vmbus_channel *relid2channel(u32 relid)
{
+ if (vmbus_connection.channels == NULL) {
+ pr_warn_once("relid2channel: relid=%d: No channels mapped!\n", relid);
+ return NULL;
+ }
if (WARN_ON(relid >= MAX_CHANNEL_RELIDS))
return NULL;
return READ_ONCE(vmbus_connection.channels[relid]);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 77bca6932f01..a65b41017cec 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -454,7 +454,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
if (etm4x_sspcicrn_present(drvdata, i))
etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i));
}
- for (i = 0; i < drvdata->nr_addr_cmp; i++) {
+ for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
etm4x_relaxed_write64(csa, config->addr_val[i], TRCACVRn(i));
etm4x_relaxed_write64(csa, config->addr_acc[i], TRCACATRn(i));
}
@@ -1013,25 +1013,21 @@ static bool etm4_init_iomem_access(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
{
u32 devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
- u32 idr1 = readl_relaxed(drvdata->base + TRCIDR1);
/*
* All ETMs must implement TRCDEVARCH to indicate that
- * the component is an ETMv4. To support any broken
- * implementations we fall back to TRCIDR1 check, which
- * is not really reliable.
+ * the component is an ETMv4. Even though TRCIDR1 also
+ * contains the information, it is part of the "Trace"
+ * register and must be accessed with the OSLK cleared,
+ * with MMIO. But we cannot touch the OSLK until we are
+ * sure this is an ETM. So rely only on the TRCDEVARCH.
*/
- if ((devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH) {
- drvdata->arch = etm_devarch_to_arch(devarch);
- } else {
- pr_warn("CPU%d: ETM4x incompatible TRCDEVARCH: %x, falling back to TRCIDR1\n",
- smp_processor_id(), devarch);
-
- if (ETM_TRCIDR1_ARCH_MAJOR(idr1) != ETM_TRCIDR1_ARCH_ETMv4)
- return false;
- drvdata->arch = etm_trcidr_to_arch(idr1);
+ if ((devarch & ETM_DEVARCH_ID_MASK) != ETM_DEVARCH_ETMv4x_ARCH) {
+ pr_warn_once("TRCDEVARCH doesn't match ETMv4 architecture\n");
+ return false;
}
+ drvdata->arch = etm_devarch_to_arch(devarch);
*csa = CSDEV_ACCESS_IOMEM(drvdata->base);
return true;
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 4b21bb79f168..0174fbf1a963 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -753,14 +753,12 @@
* TRCDEVARCH - CoreSight architected register
* - Bits[15:12] - Major version
* - Bits[19:16] - Minor version
- * TRCIDR1 - ETM architected register
- * - Bits[11:8] - Major version
- * - Bits[7:4] - Minor version
- * We must rely on TRCDEVARCH for the version information,
- * however we don't want to break the support for potential
- * old implementations which might not implement it. Thus
- * we fall back to TRCIDR1 if TRCDEVARCH is not implemented
- * for memory mapped components.
+ *
+ * We must rely only on TRCDEVARCH for the version information. Even though,
+ * TRCIDR1 also provides the architecture version, it is a "Trace" register
+ * and as such must be accessed only with Trace power domain ON. This may
+ * not be available at probe time.
+ *
* Now to make certain decisions easier based on the version
* we use an internal representation of the version in the
* driver, as follows :
@@ -786,12 +784,6 @@ static inline u8 etm_devarch_to_arch(u32 devarch)
ETM_DEVARCH_REVISION(devarch));
}
-static inline u8 etm_trcidr_to_arch(u32 trcidr1)
-{
- return ETM_ARCH_VERSION(ETM_TRCIDR1_ARCH_MAJOR(trcidr1),
- ETM_TRCIDR1_ARCH_MINOR(trcidr1));
-}
-
enum etm_impdef_type {
ETM4_IMPDEF_HISI_CORE_COMMIT,
ETM4_IMPDEF_FEATURE_MAX,
diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c
index f866859855cd..1c3a72380fb8 100644
--- a/drivers/iio/accel/kionix-kx022a.c
+++ b/drivers/iio/accel/kionix-kx022a.c
@@ -864,7 +864,7 @@ static irqreturn_t kx022a_trigger_handler(int irq, void *p)
if (ret < 0)
goto err_read;
- iio_push_to_buffers_with_timestamp(idev, data->buffer, pf->timestamp);
+ iio_push_to_buffers_with_timestamp(idev, data->buffer, data->timestamp);
err_read:
iio_trigger_notify_done(idev->trig);
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index fee8d129a5f0..86effe8501b4 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -253,7 +253,7 @@ static const struct ad_sigma_delta_info ad7791_sigma_delta_info = {
.has_registers = true,
.addr_shift = 4,
.read_mask = BIT(3),
- .irq_flags = IRQF_TRIGGER_LOW,
+ .irq_flags = IRQF_TRIGGER_FALLING,
};
static int ad7791_read_raw(struct iio_dev *indio_dev,
diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c
index 17370c5eb6fe..ec198c6f13d6 100644
--- a/drivers/iio/adc/ltc2497.c
+++ b/drivers/iio/adc/ltc2497.c
@@ -28,7 +28,6 @@ struct ltc2497_driverdata {
struct ltc2497core_driverdata common_ddata;
struct i2c_client *client;
u32 recv_size;
- u32 sub_lsb;
/*
* DMA (thus cache coherency maintenance) may require the
* transfer buffers to live in their own cache lines.
@@ -65,10 +64,10 @@ static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata,
* equivalent to a sign extension.
*/
if (st->recv_size == 3) {
- *val = (get_unaligned_be24(st->data.d8) >> st->sub_lsb)
+ *val = (get_unaligned_be24(st->data.d8) >> 6)
- BIT(ddata->chip_info->resolution + 1);
} else {
- *val = (be32_to_cpu(st->data.d32) >> st->sub_lsb)
+ *val = (be32_to_cpu(st->data.d32) >> 6)
- BIT(ddata->chip_info->resolution + 1);
}
@@ -122,7 +121,6 @@ static int ltc2497_probe(struct i2c_client *client)
st->common_ddata.chip_info = chip_info;
resolution = chip_info->resolution;
- st->sub_lsb = 31 - (resolution + 1);
st->recv_size = BITS_TO_BYTES(resolution) + 1;
return ltc2497core_probe(dev, indio_dev);
diff --git a/drivers/iio/adc/max11410.c b/drivers/iio/adc/max11410.c
index fdc9f03135b5..e64cd979688d 100644
--- a/drivers/iio/adc/max11410.c
+++ b/drivers/iio/adc/max11410.c
@@ -413,13 +413,17 @@ static int max11410_sample(struct max11410_state *st, int *sample_raw,
if (!ret)
return -ETIMEDOUT;
} else {
+ int ret2;
+
/* Wait for status register Conversion Ready flag */
- ret = read_poll_timeout(max11410_read_reg, ret,
- ret || (val & MAX11410_STATUS_CONV_READY_BIT),
+ ret = read_poll_timeout(max11410_read_reg, ret2,
+ ret2 || (val & MAX11410_STATUS_CONV_READY_BIT),
5000, MAX11410_CONVERSION_TIMEOUT_MS * 1000,
true, st, MAX11410_REG_STATUS, &val);
if (ret)
return ret;
+ if (ret2)
+ return ret2;
}
/* Read ADC Data */
@@ -850,17 +854,21 @@ static int max11410_init_vref(struct device *dev,
static int max11410_calibrate(struct max11410_state *st, u32 cal_type)
{
- int ret, val;
+ int ret, ret2, val;
ret = max11410_write_reg(st, MAX11410_REG_CAL_START, cal_type);
if (ret)
return ret;
/* Wait for status register Calibration Ready flag */
- return read_poll_timeout(max11410_read_reg, ret,
- ret || (val & MAX11410_STATUS_CAL_READY_BIT),
- 50000, MAX11410_CALIB_TIMEOUT_MS * 1000, true,
- st, MAX11410_REG_STATUS, &val);
+ ret = read_poll_timeout(max11410_read_reg, ret2,
+ ret2 || (val & MAX11410_STATUS_CAL_READY_BIT),
+ 50000, MAX11410_CALIB_TIMEOUT_MS * 1000, true,
+ st, MAX11410_REG_STATUS, &val);
+ if (ret)
+ return ret;
+
+ return ret2;
}
static int max11410_self_calibrate(struct max11410_state *st)
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
index 821fee60a765..d1b86570768a 100644
--- a/drivers/iio/adc/qcom-spmi-adc5.c
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -626,12 +626,20 @@ static int adc5_get_fw_channel_data(struct adc5_chip *adc,
struct fwnode_handle *fwnode,
const struct adc5_data *data)
{
- const char *name = fwnode_get_name(fwnode), *channel_name;
+ const char *channel_name;
+ char *name;
u32 chan, value, varr[2];
u32 sid = 0;
int ret;
struct device *dev = adc->dev;
+ name = devm_kasprintf(dev, GFP_KERNEL, "%pfwP", fwnode);
+ if (!name)
+ return -ENOMEM;
+
+ /* Cut the address part */
+ name[strchrnul(name, '@') - name] = '\0';
+
ret = fwnode_property_read_u32(fwnode, "reg", &chan);
if (ret) {
dev_err(dev, "invalid channel number %s\n", name);
diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c
index 2cc9a9bd9db6..263fc3a1b87e 100644
--- a/drivers/iio/adc/ti-ads7950.c
+++ b/drivers/iio/adc/ti-ads7950.c
@@ -634,6 +634,7 @@ static int ti_ads7950_probe(struct spi_device *spi)
st->chip.label = dev_name(&st->spi->dev);
st->chip.parent = &st->spi->dev;
st->chip.owner = THIS_MODULE;
+ st->chip.can_sleep = true;
st->chip.base = -1;
st->chip.ngpio = TI_ADS7950_NUM_GPIOS;
st->chip.get_direction = ti_ads7950_get_direction;
diff --git a/drivers/iio/dac/cio-dac.c b/drivers/iio/dac/cio-dac.c
index 791dd999cf29..18a64f72fc18 100644
--- a/drivers/iio/dac/cio-dac.c
+++ b/drivers/iio/dac/cio-dac.c
@@ -66,8 +66,8 @@ static int cio_dac_write_raw(struct iio_dev *indio_dev,
if (mask != IIO_CHAN_INFO_RAW)
return -EINVAL;
- /* DAC can only accept up to a 16-bit value */
- if ((unsigned int)val > 65535)
+ /* DAC can only accept up to a 12-bit value */
+ if ((unsigned int)val > 4095)
return -EINVAL;
priv->chan_out_states[chan->channel] = val;
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index f1d7d4b5e222..c2f97629e9cd 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -47,6 +47,7 @@ config ADIS16480
depends on SPI
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+ select CRC32
help
Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
ADIS16485, ADIS16488 inertial sensors.
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 80c78bd6bbef..a7a080bed180 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -203,24 +203,27 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
break;
}
+ if (filp->f_flags & O_NONBLOCK) {
+ if (!written)
+ ret = -EAGAIN;
+ break;
+ }
+
wait_woken(&wait, TASK_INTERRUPTIBLE,
MAX_SCHEDULE_TIMEOUT);
continue;
}
ret = rb->access->write(rb, n - written, buf + written);
- if (ret == 0 && (filp->f_flags & O_NONBLOCK))
- ret = -EAGAIN;
+ if (ret < 0)
+ break;
- if (ret > 0) {
- written += ret;
- if (written != n && !(filp->f_flags & O_NONBLOCK))
- continue;
- }
- } while (ret == 0);
+ written += ret;
+
+ } while (written != n);
remove_wait_queue(&rb->pollq, &wait);
- return ret < 0 ? ret : n;
+ return ret < 0 ? ret : written;
}
/**
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index b1674a5bfa36..d4a34a3bf00d 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -429,6 +429,14 @@ static const struct iio_info cm32181_info = {
.attrs = &cm32181_attribute_group,
};
+static void cm32181_unregister_dummy_client(void *data)
+{
+ struct i2c_client *client = data;
+
+ /* Unregister the dummy client */
+ i2c_unregister_device(client);
+}
+
static int cm32181_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -460,6 +468,10 @@ static int cm32181_probe(struct i2c_client *client)
client = i2c_acpi_new_device(dev, 1, &board_info);
if (IS_ERR(client))
return PTR_ERR(client);
+
+ ret = devm_add_action_or_reset(dev, cm32181_unregister_dummy_client, client);
+ if (ret)
+ return ret;
}
cm32181 = iio_priv(indio_dev);
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index cc1a2062e76d..69c5bc987e26 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -199,7 +199,6 @@ static int vcnl4000_init(struct vcnl4000_data *data)
data->rev = ret & 0xf;
data->al_scale = 250000;
- mutex_init(&data->vcnl4000_lock);
return data->chip_spec->set_power_state(data, true);
};
@@ -1197,6 +1196,8 @@ static int vcnl4000_probe(struct i2c_client *client)
data->id = id->driver_data;
data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];
+ mutex_init(&data->vcnl4000_lock);
+
ret = data->chip_spec->init(data);
if (ret < 0)
return ret;
diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c
index 1e1d3509efae..105e0c4dc199 100644
--- a/drivers/iommu/iommufd/pages.c
+++ b/drivers/iommu/iommufd/pages.c
@@ -294,9 +294,9 @@ static void batch_clear_carry(struct pfn_batch *batch, unsigned int keep_pfns)
batch->npfns[batch->end - 1] < keep_pfns);
batch->total_pfns = keep_pfns;
- batch->npfns[0] = keep_pfns;
batch->pfns[0] = batch->pfns[batch->end - 1] +
(batch->npfns[batch->end - 1] - keep_pfns);
+ batch->npfns[0] = keep_pfns;
batch->end = 0;
}
@@ -1140,6 +1140,7 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
bool writable)
{
struct iopt_pages *pages;
+ unsigned long end;
/*
* The iommu API uses size_t as the length, and protect the DIV_ROUND_UP
@@ -1148,6 +1149,9 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
if (length > SIZE_MAX - PAGE_SIZE || length == 0)
return ERR_PTR(-EINVAL);
+ if (check_add_overflow((unsigned long)uptr, length, &end))
+ return ERR_PTR(-EOVERFLOW);
+
pages = kzalloc(sizeof(*pages), GFP_KERNEL_ACCOUNT);
if (!pages)
return ERR_PTR(-ENOMEM);
@@ -1201,13 +1205,21 @@ iopt_area_unpin_domain(struct pfn_batch *batch, struct iopt_area *area,
unsigned long start =
max(start_index, *unmapped_end_index);
+ if (IS_ENABLED(CONFIG_IOMMUFD_TEST) &&
+ batch->total_pfns)
+ WARN_ON(*unmapped_end_index -
+ batch->total_pfns !=
+ start_index);
batch_from_domain(batch, domain, area, start,
last_index);
- batch_last_index = start + batch->total_pfns - 1;
+ batch_last_index = start_index + batch->total_pfns - 1;
} else {
batch_last_index = last_index;
}
+ if (IS_ENABLED(CONFIG_IOMMUFD_TEST))
+ WARN_ON(batch_last_index > real_last_index);
+
/*
* unmaps must always 'cut' at a place where the pfns are not
* contiguous to pair with the maps that always install
diff --git a/drivers/md/dm-bio-prison-v1.c b/drivers/md/dm-bio-prison-v1.c
index 1f8f98efd97a..138067abe14b 100644
--- a/drivers/md/dm-bio-prison-v1.c
+++ b/drivers/md/dm-bio-prison-v1.c
@@ -285,14 +285,14 @@ EXPORT_SYMBOL_GPL(dm_cell_promote_or_release);
struct dm_deferred_entry {
struct dm_deferred_set *ds;
- unsigned count;
+ unsigned int count;
struct list_head work_items;
};
struct dm_deferred_set {
spinlock_t lock;
- unsigned current_entry;
- unsigned sweeper;
+ unsigned int current_entry;
+ unsigned int sweeper;
struct dm_deferred_entry entries[DEFERRED_SET_SIZE];
};
@@ -338,7 +338,7 @@ struct dm_deferred_entry *dm_deferred_entry_inc(struct dm_deferred_set *ds)
}
EXPORT_SYMBOL_GPL(dm_deferred_entry_inc);
-static unsigned ds_next(unsigned index)
+static unsigned int ds_next(unsigned int index)
{
return (index + 1) % DEFERRED_SET_SIZE;
}
@@ -373,7 +373,7 @@ EXPORT_SYMBOL_GPL(dm_deferred_entry_dec);
int dm_deferred_set_add_work(struct dm_deferred_set *ds, struct list_head *work)
{
int r = 1;
- unsigned next_entry;
+ unsigned int next_entry;
spin_lock_irq(&ds->lock);
if ((ds->sweeper == ds->current_entry) &&
diff --git a/drivers/md/dm-bio-prison-v2.c b/drivers/md/dm-bio-prison-v2.c
index 9dec3b61cf70..0cc0d13c40e5 100644
--- a/drivers/md/dm-bio-prison-v2.c
+++ b/drivers/md/dm-bio-prison-v2.c
@@ -148,7 +148,7 @@ static bool __find_or_insert(struct dm_bio_prison_v2 *prison,
static bool __get(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct bio *inmate,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell)
@@ -171,7 +171,7 @@ static bool __get(struct dm_bio_prison_v2 *prison,
bool dm_cell_get_v2(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct bio *inmate,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result)
@@ -224,7 +224,7 @@ EXPORT_SYMBOL_GPL(dm_cell_put_v2);
static int __lock(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result)
{
@@ -255,7 +255,7 @@ static int __lock(struct dm_bio_prison_v2 *prison,
int dm_cell_lock_v2(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result)
{
@@ -291,7 +291,7 @@ EXPORT_SYMBOL_GPL(dm_cell_quiesce_v2);
static int __promote(struct dm_bio_prison_v2 *prison,
struct dm_bio_prison_cell_v2 *cell,
- unsigned new_lock_level)
+ unsigned int new_lock_level)
{
if (!cell->exclusive_lock)
return -EINVAL;
@@ -302,7 +302,7 @@ static int __promote(struct dm_bio_prison_v2 *prison,
int dm_cell_lock_promote_v2(struct dm_bio_prison_v2 *prison,
struct dm_bio_prison_cell_v2 *cell,
- unsigned new_lock_level)
+ unsigned int new_lock_level)
{
int r;
diff --git a/drivers/md/dm-bio-prison-v2.h b/drivers/md/dm-bio-prison-v2.h
index 6e04234268db..5a7d996bbbd8 100644
--- a/drivers/md/dm-bio-prison-v2.h
+++ b/drivers/md/dm-bio-prison-v2.h
@@ -44,8 +44,8 @@ struct dm_cell_key_v2 {
struct dm_bio_prison_cell_v2 {
// FIXME: pack these
bool exclusive_lock;
- unsigned exclusive_level;
- unsigned shared_count;
+ unsigned int exclusive_level;
+ unsigned int shared_count;
struct work_struct *quiesce_continuation;
struct rb_node node;
@@ -86,7 +86,7 @@ void dm_bio_prison_free_cell_v2(struct dm_bio_prison_v2 *prison,
*/
bool dm_cell_get_v2(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct bio *inmate,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result);
@@ -114,7 +114,7 @@ bool dm_cell_put_v2(struct dm_bio_prison_v2 *prison,
*/
int dm_cell_lock_v2(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result);
@@ -132,7 +132,7 @@ void dm_cell_quiesce_v2(struct dm_bio_prison_v2 *prison,
*/
int dm_cell_lock_promote_v2(struct dm_bio_prison_v2 *prison,
struct dm_bio_prison_cell_v2 *cell,
- unsigned new_lock_level);
+ unsigned int new_lock_level);
/*
* Adds any held bios to the bio list.
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 19caaf684ee3..382c5cc47195 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -89,7 +89,7 @@ struct dm_bufio_client {
unsigned long n_buffers[LIST_SIZE];
struct block_device *bdev;
- unsigned block_size;
+ unsigned int block_size;
s8 sectors_per_block_bits;
void (*alloc_callback)(struct dm_buffer *);
void (*write_callback)(struct dm_buffer *);
@@ -98,9 +98,9 @@ struct dm_bufio_client {
struct dm_io_client *dm_io;
struct list_head reserved_buffers;
- unsigned need_reserved_buffers;
+ unsigned int need_reserved_buffers;
- unsigned minimum_buffers;
+ unsigned int minimum_buffers;
struct rb_root buffer_tree;
wait_queue_head_t free_buffer_wait;
@@ -145,14 +145,14 @@ struct dm_buffer {
unsigned char list_mode; /* LIST_* */
blk_status_t read_error;
blk_status_t write_error;
- unsigned accessed;
- unsigned hold_count;
+ unsigned int accessed;
+ unsigned int hold_count;
unsigned long state;
unsigned long last_accessed;
- unsigned dirty_start;
- unsigned dirty_end;
- unsigned write_start;
- unsigned write_end;
+ unsigned int dirty_start;
+ unsigned int dirty_end;
+ unsigned int write_start;
+ unsigned int write_end;
struct dm_bufio_client *c;
struct list_head write_list;
void (*end_io)(struct dm_buffer *, blk_status_t);
@@ -220,7 +220,7 @@ static unsigned long global_num = 0;
/*
* Buffers are freed after this timeout
*/
-static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
+static unsigned int dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
static unsigned long dm_bufio_peak_allocated;
@@ -438,7 +438,7 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
* as if GFP_NOIO was specified.
*/
if (gfp_mask & __GFP_NORETRY) {
- unsigned noio_flag = memalloc_noio_save();
+ unsigned int noio_flag = memalloc_noio_save();
void *ptr = __vmalloc(c->block_size, gfp_mask);
memalloc_noio_restore(noio_flag);
@@ -591,7 +591,7 @@ static void dmio_complete(unsigned long error, void *context)
}
static void use_dmio(struct dm_buffer *b, enum req_op op, sector_t sector,
- unsigned n_sectors, unsigned offset)
+ unsigned int n_sectors, unsigned int offset)
{
int r;
struct dm_io_request io_req = {
@@ -629,11 +629,11 @@ static void bio_complete(struct bio *bio)
}
static void use_bio(struct dm_buffer *b, enum req_op op, sector_t sector,
- unsigned n_sectors, unsigned offset)
+ unsigned int n_sectors, unsigned int offset)
{
struct bio *bio;
char *ptr;
- unsigned vec_size, len;
+ unsigned int vec_size, len;
vec_size = b->c->block_size >> PAGE_SHIFT;
if (unlikely(b->c->sectors_per_block_bits < PAGE_SHIFT - SECTOR_SHIFT))
@@ -654,7 +654,7 @@ static void use_bio(struct dm_buffer *b, enum req_op op, sector_t sector,
len = n_sectors << SECTOR_SHIFT;
do {
- unsigned this_step = min((unsigned)(PAGE_SIZE - offset_in_page(ptr)), len);
+ unsigned int this_step = min((unsigned int)(PAGE_SIZE - offset_in_page(ptr)), len);
if (!bio_add_page(bio, virt_to_page(ptr), this_step,
offset_in_page(ptr))) {
bio_put(bio);
@@ -684,9 +684,9 @@ static inline sector_t block_to_sector(struct dm_bufio_client *c, sector_t block
static void submit_io(struct dm_buffer *b, enum req_op op,
void (*end_io)(struct dm_buffer *, blk_status_t))
{
- unsigned n_sectors;
+ unsigned int n_sectors;
sector_t sector;
- unsigned offset, end;
+ unsigned int offset, end;
b->end_io = end_io;
@@ -1156,7 +1156,7 @@ void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
EXPORT_SYMBOL_GPL(dm_bufio_new);
void dm_bufio_prefetch(struct dm_bufio_client *c,
- sector_t block, unsigned n_blocks)
+ sector_t block, unsigned int n_blocks)
{
struct blk_plug plug;
@@ -1232,7 +1232,7 @@ void dm_bufio_release(struct dm_buffer *b)
EXPORT_SYMBOL_GPL(dm_bufio_release);
void dm_bufio_mark_partial_buffer_dirty(struct dm_buffer *b,
- unsigned start, unsigned end)
+ unsigned int start, unsigned int end)
{
struct dm_bufio_client *c = b->c;
@@ -1529,13 +1529,13 @@ void dm_bufio_forget_buffers(struct dm_bufio_client *c, sector_t block, sector_t
}
EXPORT_SYMBOL_GPL(dm_bufio_forget_buffers);
-void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n)
+void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned int n)
{
c->minimum_buffers = n;
}
EXPORT_SYMBOL_GPL(dm_bufio_set_minimum_buffers);
-unsigned dm_bufio_get_block_size(struct dm_bufio_client *c)
+unsigned int dm_bufio_get_block_size(struct dm_bufio_client *c)
{
return c->block_size;
}
@@ -1734,15 +1734,15 @@ static unsigned long dm_bufio_shrink_count(struct shrinker *shrink, struct shrin
/*
* Create the buffering interface
*/
-struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
- unsigned reserved_buffers, unsigned aux_size,
+struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned int block_size,
+ unsigned int reserved_buffers, unsigned int aux_size,
void (*alloc_callback)(struct dm_buffer *),
void (*write_callback)(struct dm_buffer *),
unsigned int flags)
{
int r;
struct dm_bufio_client *c;
- unsigned i;
+ unsigned int i;
char slab_name[27];
if (!block_size || block_size & ((1 << SECTOR_SHIFT) - 1)) {
@@ -1796,7 +1796,7 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
if (block_size <= KMALLOC_MAX_SIZE &&
(block_size < PAGE_SIZE || !is_power_of_2(block_size))) {
- unsigned align = min(1U << __ffs(block_size), (unsigned)PAGE_SIZE);
+ unsigned int align = min(1U << __ffs(block_size), (unsigned int)PAGE_SIZE);
snprintf(slab_name, sizeof slab_name, "dm_bufio_cache-%u", block_size);
c->slab_cache = kmem_cache_create(slab_name, block_size, align,
SLAB_RECLAIM_ACCOUNT, NULL);
@@ -1872,7 +1872,7 @@ EXPORT_SYMBOL_GPL(dm_bufio_client_create);
*/
void dm_bufio_client_destroy(struct dm_bufio_client *c)
{
- unsigned i;
+ unsigned int i;
drop_buffers(c);
@@ -1920,9 +1920,9 @@ void dm_bufio_set_sector_offset(struct dm_bufio_client *c, sector_t start)
}
EXPORT_SYMBOL_GPL(dm_bufio_set_sector_offset);
-static unsigned get_max_age_hz(void)
+static unsigned int get_max_age_hz(void)
{
- unsigned max_age = READ_ONCE(dm_bufio_max_age);
+ unsigned int max_age = READ_ONCE(dm_bufio_max_age);
if (max_age > UINT_MAX / HZ)
max_age = UINT_MAX / HZ;
@@ -1973,7 +1973,7 @@ static void do_global_cleanup(struct work_struct *w)
struct dm_bufio_client *locked_client = NULL;
struct dm_bufio_client *current_client;
struct dm_buffer *b;
- unsigned spinlock_hold_count;
+ unsigned int spinlock_hold_count;
unsigned long threshold = dm_bufio_cache_size -
dm_bufio_cache_size / DM_BUFIO_LOW_WATERMARK_RATIO;
unsigned long loops = global_num * 2;
diff --git a/drivers/md/dm-cache-background-tracker.c b/drivers/md/dm-cache-background-tracker.c
index 7887f99b82bd..c606e6bfc3f8 100644
--- a/drivers/md/dm-cache-background-tracker.c
+++ b/drivers/md/dm-cache-background-tracker.c
@@ -17,7 +17,7 @@ struct bt_work {
};
struct background_tracker {
- unsigned max_work;
+ unsigned int max_work;
atomic_t pending_promotes;
atomic_t pending_writebacks;
atomic_t pending_demotes;
@@ -29,7 +29,7 @@ struct background_tracker {
struct kmem_cache *work_cache;
};
-struct background_tracker *btracker_create(unsigned max_work)
+struct background_tracker *btracker_create(unsigned int max_work)
{
struct background_tracker *b = kmalloc(sizeof(*b), GFP_KERNEL);
@@ -155,13 +155,13 @@ static void update_stats(struct background_tracker *b, struct policy_work *w, in
}
}
-unsigned btracker_nr_writebacks_queued(struct background_tracker *b)
+unsigned int btracker_nr_writebacks_queued(struct background_tracker *b)
{
return atomic_read(&b->pending_writebacks);
}
EXPORT_SYMBOL_GPL(btracker_nr_writebacks_queued);
-unsigned btracker_nr_demotions_queued(struct background_tracker *b)
+unsigned int btracker_nr_demotions_queued(struct background_tracker *b)
{
return atomic_read(&b->pending_demotes);
}
diff --git a/drivers/md/dm-cache-background-tracker.h b/drivers/md/dm-cache-background-tracker.h
index 27ab90dbc275..14d3d53dc77a 100644
--- a/drivers/md/dm-cache-background-tracker.h
+++ b/drivers/md/dm-cache-background-tracker.h
@@ -12,19 +12,44 @@
/*----------------------------------------------------------------*/
+/*
+ * The cache policy decides what background work should be performed,
+ * such as promotions, demotions and writebacks. The core cache target
+ * is in charge of performing the work, and does so when it sees fit.
+ *
+ * The background_tracker acts as a go between. Keeping track of future
+ * work that the policy has decided upon, and handing (issuing) it to
+ * the core target when requested.
+ *
+ * There is no locking in this, so calls will probably need to be
+ * protected with a spinlock.
+ */
+
struct background_work;
struct background_tracker;
/*
- * FIXME: discuss lack of locking in all methods.
+ * Create a new tracker, it will not be able to queue more than
+ * 'max_work' entries.
+ */
+struct background_tracker *btracker_create(unsigned int max_work);
+
+/*
+ * Destroy the tracker. No issued, but not complete, work should
+ * exist when this is called. It is fine to have queued but unissued
+ * work.
*/
-struct background_tracker *btracker_create(unsigned max_work);
void btracker_destroy(struct background_tracker *b);
-unsigned btracker_nr_writebacks_queued(struct background_tracker *b);
-unsigned btracker_nr_demotions_queued(struct background_tracker *b);
+unsigned int btracker_nr_writebacks_queued(struct background_tracker *b);
+unsigned int btracker_nr_demotions_queued(struct background_tracker *b);
/*
+ * Queue some work within the tracker. 'work' should point to the work
+ * to queue, this will be copied (ownership doesn't pass). If pwork
+ * is not NULL then it will be set to point to the tracker's internal
+ * copy of the work.
+ *
* returns -EINVAL iff the work is already queued. -ENOMEM if the work
* couldn't be queued for another reason.
*/
@@ -33,11 +58,20 @@ int btracker_queue(struct background_tracker *b,
struct policy_work **pwork);
/*
+ * Hands out the next piece of work to be performed.
* Returns -ENODATA if there's no work.
*/
int btracker_issue(struct background_tracker *b, struct policy_work **work);
-void btracker_complete(struct background_tracker *b,
- struct policy_work *op);
+
+/*
+ * Informs the tracker that the work has been completed and it may forget
+ * about it.
+ */
+void btracker_complete(struct background_tracker *b, struct policy_work *op);
+
+/*
+ * Predicate to see if an origin block is already scheduled for promotion.
+ */
bool btracker_promotion_already_present(struct background_tracker *b,
dm_oblock_t oblock);
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index 83a5975bcc72..f5b4c996dc05 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -104,7 +104,7 @@ struct dm_cache_metadata {
refcount_t ref_count;
struct list_head list;
- unsigned version;
+ unsigned int version;
struct block_device *bdev;
struct dm_block_manager *bm;
struct dm_space_map *metadata_sm;
@@ -129,7 +129,7 @@ struct dm_cache_metadata {
bool clean_when_opened:1;
char policy_name[CACHE_POLICY_NAME_SIZE];
- unsigned policy_version[CACHE_POLICY_VERSION_SIZE];
+ unsigned int policy_version[CACHE_POLICY_VERSION_SIZE];
size_t policy_hint_size;
struct dm_cache_statistics stats;
@@ -260,10 +260,10 @@ static int superblock_lock(struct dm_cache_metadata *cmd,
static int __superblock_all_zeroes(struct dm_block_manager *bm, bool *result)
{
int r;
- unsigned i;
+ unsigned int i;
struct dm_block *b;
__le64 *data_le, zero = cpu_to_le64(0);
- unsigned sb_block_size = dm_bm_block_size(bm) / sizeof(__le64);
+ unsigned int sb_block_size = dm_bm_block_size(bm) / sizeof(__le64);
/*
* We can't use a validator here - it may be all zeroes.
@@ -727,7 +727,7 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
*/
#define FLAGS_MASK ((1 << 16) - 1)
-static __le64 pack_value(dm_oblock_t block, unsigned flags)
+static __le64 pack_value(dm_oblock_t block, unsigned int flags)
{
uint64_t value = from_oblock(block);
value <<= 16;
@@ -735,7 +735,7 @@ static __le64 pack_value(dm_oblock_t block, unsigned flags)
return cpu_to_le64(value);
}
-static void unpack_value(__le64 value_le, dm_oblock_t *block, unsigned *flags)
+static void unpack_value(__le64 value_le, dm_oblock_t *block, unsigned int *flags)
{
uint64_t value = le64_to_cpu(value_le);
uint64_t b = value >> 16;
@@ -749,7 +749,7 @@ static struct dm_cache_metadata *metadata_open(struct block_device *bdev,
sector_t data_block_size,
bool may_format_device,
size_t policy_hint_size,
- unsigned metadata_version)
+ unsigned int metadata_version)
{
int r;
struct dm_cache_metadata *cmd;
@@ -810,7 +810,7 @@ static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev,
sector_t data_block_size,
bool may_format_device,
size_t policy_hint_size,
- unsigned metadata_version)
+ unsigned int metadata_version)
{
struct dm_cache_metadata *cmd, *cmd2;
@@ -855,7 +855,7 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
sector_t data_block_size,
bool may_format_device,
size_t policy_hint_size,
- unsigned metadata_version)
+ unsigned int metadata_version)
{
struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size, may_format_device,
policy_hint_size, metadata_version);
@@ -890,7 +890,7 @@ static int block_clean_combined_dirty(struct dm_cache_metadata *cmd, dm_cblock_t
int r;
__le64 value;
dm_oblock_t ob;
- unsigned flags;
+ unsigned int flags;
r = dm_array_get_value(&cmd->info, cmd->root, from_cblock(b), &value);
if (r)
@@ -1288,7 +1288,7 @@ static bool policy_unchanged(struct dm_cache_metadata *cmd,
struct dm_cache_policy *policy)
{
const char *policy_name = dm_cache_policy_get_name(policy);
- const unsigned *policy_version = dm_cache_policy_get_version(policy);
+ const unsigned int *policy_version = dm_cache_policy_get_version(policy);
size_t policy_hint_size = dm_cache_policy_get_hint_size(policy);
/*
@@ -1339,7 +1339,7 @@ static int __load_mapping_v1(struct dm_cache_metadata *cmd,
__le32 *hint_value_le;
dm_oblock_t oblock;
- unsigned flags;
+ unsigned int flags;
bool dirty = true;
dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le);
@@ -1381,7 +1381,7 @@ static int __load_mapping_v2(struct dm_cache_metadata *cmd,
__le32 *hint_value_le;
dm_oblock_t oblock;
- unsigned flags;
+ unsigned int flags;
bool dirty = true;
dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le);
@@ -1513,7 +1513,7 @@ static int __dump_mapping(void *context, uint64_t cblock, void *leaf)
{
__le64 value;
dm_oblock_t oblock;
- unsigned flags;
+ unsigned int flags;
memcpy(&value, leaf, sizeof(value));
unpack_value(value, &oblock, &flags);
@@ -1547,7 +1547,7 @@ int dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd)
static int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty)
{
int r;
- unsigned flags;
+ unsigned int flags;
dm_oblock_t oblock;
__le64 value;
@@ -1574,10 +1574,10 @@ static int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty
}
-static int __set_dirty_bits_v1(struct dm_cache_metadata *cmd, unsigned nr_bits, unsigned long *bits)
+static int __set_dirty_bits_v1(struct dm_cache_metadata *cmd, unsigned int nr_bits, unsigned long *bits)
{
int r;
- unsigned i;
+ unsigned int i;
for (i = 0; i < nr_bits; i++) {
r = __dirty(cmd, to_cblock(i), test_bit(i, bits));
if (r)
@@ -1594,7 +1594,7 @@ static int is_dirty_callback(uint32_t index, bool *value, void *context)
return 0;
}
-static int __set_dirty_bits_v2(struct dm_cache_metadata *cmd, unsigned nr_bits, unsigned long *bits)
+static int __set_dirty_bits_v2(struct dm_cache_metadata *cmd, unsigned int nr_bits, unsigned long *bits)
{
int r = 0;
@@ -1613,7 +1613,7 @@ static int __set_dirty_bits_v2(struct dm_cache_metadata *cmd, unsigned nr_bits,
}
int dm_cache_set_dirty_bits(struct dm_cache_metadata *cmd,
- unsigned nr_bits,
+ unsigned int nr_bits,
unsigned long *bits)
{
int r;
@@ -1712,7 +1712,7 @@ static int write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *po
int r;
size_t hint_size;
const char *policy_name = dm_cache_policy_get_name(policy);
- const unsigned *policy_version = dm_cache_policy_get_version(policy);
+ const unsigned int *policy_version = dm_cache_policy_get_version(policy);
if (!policy_name[0] ||
(strlen(policy_name) > sizeof(cmd->policy_name) - 1))
diff --git a/drivers/md/dm-cache-metadata.h b/drivers/md/dm-cache-metadata.h
index 0905f2c1615e..b40322bc44cf 100644
--- a/drivers/md/dm-cache-metadata.h
+++ b/drivers/md/dm-cache-metadata.h
@@ -60,7 +60,7 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
sector_t data_block_size,
bool may_format_device,
size_t policy_hint_size,
- unsigned metadata_version);
+ unsigned int metadata_version);
void dm_cache_metadata_close(struct dm_cache_metadata *cmd);
@@ -96,7 +96,7 @@ int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
void *context);
int dm_cache_set_dirty_bits(struct dm_cache_metadata *cmd,
- unsigned nr_bits, unsigned long *bits);
+ unsigned int nr_bits, unsigned long *bits);
struct dm_cache_statistics {
uint32_t read_hits;
diff --git a/drivers/md/dm-cache-policy-internal.h b/drivers/md/dm-cache-policy-internal.h
index 56f0a23f698c..8e49baa78dc1 100644
--- a/drivers/md/dm-cache-policy-internal.h
+++ b/drivers/md/dm-cache-policy-internal.h
@@ -85,7 +85,7 @@ static inline void policy_tick(struct dm_cache_policy *p, bool can_block)
}
static inline int policy_emit_config_values(struct dm_cache_policy *p, char *result,
- unsigned maxlen, ssize_t *sz_ptr)
+ unsigned int maxlen, ssize_t *sz_ptr)
{
ssize_t sz = *sz_ptr;
if (p->emit_config_values)
@@ -112,18 +112,18 @@ static inline void policy_allow_migrations(struct dm_cache_policy *p, bool allow
/*
* Some utility functions commonly used by policies and the core target.
*/
-static inline size_t bitset_size_in_bytes(unsigned nr_entries)
+static inline size_t bitset_size_in_bytes(unsigned int nr_entries)
{
return sizeof(unsigned long) * dm_div_up(nr_entries, BITS_PER_LONG);
}
-static inline unsigned long *alloc_bitset(unsigned nr_entries)
+static inline unsigned long *alloc_bitset(unsigned int nr_entries)
{
size_t s = bitset_size_in_bytes(nr_entries);
return vzalloc(s);
}
-static inline void clear_bitset(void *bitset, unsigned nr_entries)
+static inline void clear_bitset(void *bitset, unsigned int nr_entries)
{
size_t s = bitset_size_in_bytes(nr_entries);
memset(bitset, 0, s);
@@ -154,7 +154,7 @@ void dm_cache_policy_destroy(struct dm_cache_policy *p);
*/
const char *dm_cache_policy_get_name(struct dm_cache_policy *p);
-const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p);
+const unsigned int *dm_cache_policy_get_version(struct dm_cache_policy *p);
size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p);
diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
index a3d281fc14c3..54343812223e 100644
--- a/drivers/md/dm-cache-policy-smq.c
+++ b/drivers/md/dm-cache-policy-smq.c
@@ -23,12 +23,12 @@
/*
* Safe division functions that return zero on divide by zero.
*/
-static unsigned safe_div(unsigned n, unsigned d)
+static unsigned int safe_div(unsigned int n, unsigned int d)
{
return d ? n / d : 0u;
}
-static unsigned safe_mod(unsigned n, unsigned d)
+static unsigned int safe_mod(unsigned int n, unsigned int d)
{
return d ? n % d : 0u;
}
@@ -36,10 +36,10 @@ static unsigned safe_mod(unsigned n, unsigned d)
/*----------------------------------------------------------------*/
struct entry {
- unsigned hash_next:28;
- unsigned prev:28;
- unsigned next:28;
- unsigned level:6;
+ unsigned int hash_next:28;
+ unsigned int prev:28;
+ unsigned int next:28;
+ unsigned int level:6;
bool dirty:1;
bool allocated:1;
bool sentinel:1;
@@ -62,7 +62,7 @@ struct entry_space {
struct entry *end;
};
-static int space_init(struct entry_space *es, unsigned nr_entries)
+static int space_init(struct entry_space *es, unsigned int nr_entries)
{
if (!nr_entries) {
es->begin = es->end = NULL;
@@ -82,7 +82,7 @@ static void space_exit(struct entry_space *es)
vfree(es->begin);
}
-static struct entry *__get_entry(struct entry_space *es, unsigned block)
+static struct entry *__get_entry(struct entry_space *es, unsigned int block)
{
struct entry *e;
@@ -92,13 +92,13 @@ static struct entry *__get_entry(struct entry_space *es, unsigned block)
return e;
}
-static unsigned to_index(struct entry_space *es, struct entry *e)
+static unsigned int to_index(struct entry_space *es, struct entry *e)
{
BUG_ON(e < es->begin || e >= es->end);
return e - es->begin;
}
-static struct entry *to_entry(struct entry_space *es, unsigned block)
+static struct entry *to_entry(struct entry_space *es, unsigned int block)
{
if (block == INDEXER_NULL)
return NULL;
@@ -109,8 +109,8 @@ static struct entry *to_entry(struct entry_space *es, unsigned block)
/*----------------------------------------------------------------*/
struct ilist {
- unsigned nr_elts; /* excluding sentinel entries */
- unsigned head, tail;
+ unsigned int nr_elts; /* excluding sentinel entries */
+ unsigned int head, tail;
};
static void l_init(struct ilist *l)
@@ -252,23 +252,23 @@ static struct entry *l_pop_tail(struct entry_space *es, struct ilist *l)
struct queue {
struct entry_space *es;
- unsigned nr_elts;
- unsigned nr_levels;
+ unsigned int nr_elts;
+ unsigned int nr_levels;
struct ilist qs[MAX_LEVELS];
/*
* We maintain a count of the number of entries we would like in each
* level.
*/
- unsigned last_target_nr_elts;
- unsigned nr_top_levels;
- unsigned nr_in_top_levels;
- unsigned target_count[MAX_LEVELS];
+ unsigned int last_target_nr_elts;
+ unsigned int nr_top_levels;
+ unsigned int nr_in_top_levels;
+ unsigned int target_count[MAX_LEVELS];
};
-static void q_init(struct queue *q, struct entry_space *es, unsigned nr_levels)
+static void q_init(struct queue *q, struct entry_space *es, unsigned int nr_levels)
{
- unsigned i;
+ unsigned int i;
q->es = es;
q->nr_elts = 0;
@@ -284,7 +284,7 @@ static void q_init(struct queue *q, struct entry_space *es, unsigned nr_levels)
q->nr_in_top_levels = 0u;
}
-static unsigned q_size(struct queue *q)
+static unsigned int q_size(struct queue *q)
{
return q->nr_elts;
}
@@ -332,9 +332,9 @@ static void q_del(struct queue *q, struct entry *e)
/*
* Return the oldest entry of the lowest populated level.
*/
-static struct entry *q_peek(struct queue *q, unsigned max_level, bool can_cross_sentinel)
+static struct entry *q_peek(struct queue *q, unsigned int max_level, bool can_cross_sentinel)
{
- unsigned level;
+ unsigned int level;
struct entry *e;
max_level = min(max_level, q->nr_levels);
@@ -369,7 +369,7 @@ static struct entry *q_pop(struct queue *q)
* used by redistribute, so we know this is true. It also doesn't adjust
* the q->nr_elts count.
*/
-static struct entry *__redist_pop_from(struct queue *q, unsigned level)
+static struct entry *__redist_pop_from(struct queue *q, unsigned int level)
{
struct entry *e;
@@ -383,9 +383,10 @@ static struct entry *__redist_pop_from(struct queue *q, unsigned level)
return NULL;
}
-static void q_set_targets_subrange_(struct queue *q, unsigned nr_elts, unsigned lbegin, unsigned lend)
+static void q_set_targets_subrange_(struct queue *q, unsigned int nr_elts,
+ unsigned int lbegin, unsigned int lend)
{
- unsigned level, nr_levels, entries_per_level, remainder;
+ unsigned int level, nr_levels, entries_per_level, remainder;
BUG_ON(lbegin > lend);
BUG_ON(lend > q->nr_levels);
@@ -426,7 +427,7 @@ static void q_set_targets(struct queue *q)
static void q_redistribute(struct queue *q)
{
- unsigned target, level;
+ unsigned int target, level;
struct ilist *l, *l_above;
struct entry *e;
@@ -467,12 +468,12 @@ static void q_redistribute(struct queue *q)
}
}
-static void q_requeue(struct queue *q, struct entry *e, unsigned extra_levels,
+static void q_requeue(struct queue *q, struct entry *e, unsigned int extra_levels,
struct entry *s1, struct entry *s2)
{
struct entry *de;
- unsigned sentinels_passed = 0;
- unsigned new_level = min(q->nr_levels - 1u, e->level + extra_levels);
+ unsigned int sentinels_passed = 0;
+ unsigned int new_level = min(q->nr_levels - 1u, e->level + extra_levels);
/* try and find an entry to swap with */
if (extra_levels && (e->level < q->nr_levels - 1u)) {
@@ -512,9 +513,9 @@ static void q_requeue(struct queue *q, struct entry *e, unsigned extra_levels,
#define EIGHTH (1u << (FP_SHIFT - 3u))
struct stats {
- unsigned hit_threshold;
- unsigned hits;
- unsigned misses;
+ unsigned int hit_threshold;
+ unsigned int hits;
+ unsigned int misses;
};
enum performance {
@@ -523,7 +524,7 @@ enum performance {
Q_WELL
};
-static void stats_init(struct stats *s, unsigned nr_levels)
+static void stats_init(struct stats *s, unsigned int nr_levels)
{
s->hit_threshold = (nr_levels * 3u) / 4u;
s->hits = 0u;
@@ -535,7 +536,7 @@ static void stats_reset(struct stats *s)
s->hits = s->misses = 0u;
}
-static void stats_level_accessed(struct stats *s, unsigned level)
+static void stats_level_accessed(struct stats *s, unsigned int level)
{
if (level >= s->hit_threshold)
s->hits++;
@@ -556,7 +557,7 @@ static void stats_miss(struct stats *s)
*/
static enum performance stats_assess(struct stats *s)
{
- unsigned confidence = safe_div(s->hits << FP_SHIFT, s->hits + s->misses);
+ unsigned int confidence = safe_div(s->hits << FP_SHIFT, s->hits + s->misses);
if (confidence < SIXTEENTH)
return Q_POOR;
@@ -573,16 +574,16 @@ static enum performance stats_assess(struct stats *s)
struct smq_hash_table {
struct entry_space *es;
unsigned long long hash_bits;
- unsigned *buckets;
+ unsigned int *buckets;
};
/*
* All cache entries are stored in a chained hash table. To save space we
* use indexing again, and only store indexes to the next entry.
*/
-static int h_init(struct smq_hash_table *ht, struct entry_space *es, unsigned nr_entries)
+static int h_init(struct smq_hash_table *ht, struct entry_space *es, unsigned int nr_entries)
{
- unsigned i, nr_buckets;
+ unsigned int i, nr_buckets;
ht->es = es;
nr_buckets = roundup_pow_of_two(max(nr_entries / 4u, 16u));
@@ -603,7 +604,7 @@ static void h_exit(struct smq_hash_table *ht)
vfree(ht->buckets);
}
-static struct entry *h_head(struct smq_hash_table *ht, unsigned bucket)
+static struct entry *h_head(struct smq_hash_table *ht, unsigned int bucket)
{
return to_entry(ht->es, ht->buckets[bucket]);
}
@@ -613,7 +614,7 @@ static struct entry *h_next(struct smq_hash_table *ht, struct entry *e)
return to_entry(ht->es, e->hash_next);
}
-static void __h_insert(struct smq_hash_table *ht, unsigned bucket, struct entry *e)
+static void __h_insert(struct smq_hash_table *ht, unsigned int bucket, struct entry *e)
{
e->hash_next = ht->buckets[bucket];
ht->buckets[bucket] = to_index(ht->es, e);
@@ -621,11 +622,11 @@ static void __h_insert(struct smq_hash_table *ht, unsigned bucket, struct entry
static void h_insert(struct smq_hash_table *ht, struct entry *e)
{
- unsigned h = hash_64(from_oblock(e->oblock), ht->hash_bits);
+ unsigned int h = hash_64(from_oblock(e->oblock), ht->hash_bits);
__h_insert(ht, h, e);
}
-static struct entry *__h_lookup(struct smq_hash_table *ht, unsigned h, dm_oblock_t oblock,
+static struct entry *__h_lookup(struct smq_hash_table *ht, unsigned int h, dm_oblock_t oblock,
struct entry **prev)
{
struct entry *e;
@@ -641,7 +642,7 @@ static struct entry *__h_lookup(struct smq_hash_table *ht, unsigned h, dm_oblock
return NULL;
}
-static void __h_unlink(struct smq_hash_table *ht, unsigned h,
+static void __h_unlink(struct smq_hash_table *ht, unsigned int h,
struct entry *e, struct entry *prev)
{
if (prev)
@@ -656,7 +657,7 @@ static void __h_unlink(struct smq_hash_table *ht, unsigned h,
static struct entry *h_lookup(struct smq_hash_table *ht, dm_oblock_t oblock)
{
struct entry *e, *prev;
- unsigned h = hash_64(from_oblock(oblock), ht->hash_bits);
+ unsigned int h = hash_64(from_oblock(oblock), ht->hash_bits);
e = __h_lookup(ht, h, oblock, &prev);
if (e && prev) {
@@ -673,7 +674,7 @@ static struct entry *h_lookup(struct smq_hash_table *ht, dm_oblock_t oblock)
static void h_remove(struct smq_hash_table *ht, struct entry *e)
{
- unsigned h = hash_64(from_oblock(e->oblock), ht->hash_bits);
+ unsigned int h = hash_64(from_oblock(e->oblock), ht->hash_bits);
struct entry *prev;
/*
@@ -689,16 +690,16 @@ static void h_remove(struct smq_hash_table *ht, struct entry *e)
struct entry_alloc {
struct entry_space *es;
- unsigned begin;
+ unsigned int begin;
- unsigned nr_allocated;
+ unsigned int nr_allocated;
struct ilist free;
};
static void init_allocator(struct entry_alloc *ea, struct entry_space *es,
- unsigned begin, unsigned end)
+ unsigned int begin, unsigned int end)
{
- unsigned i;
+ unsigned int i;
ea->es = es;
ea->nr_allocated = 0u;
@@ -742,7 +743,7 @@ static struct entry *alloc_entry(struct entry_alloc *ea)
/*
* This assumes the cblock hasn't already been allocated.
*/
-static struct entry *alloc_particular_entry(struct entry_alloc *ea, unsigned i)
+static struct entry *alloc_particular_entry(struct entry_alloc *ea, unsigned int i)
{
struct entry *e = __get_entry(ea->es, ea->begin + i);
@@ -770,12 +771,12 @@ static bool allocator_empty(struct entry_alloc *ea)
return l_empty(&ea->free);
}
-static unsigned get_index(struct entry_alloc *ea, struct entry *e)
+static unsigned int get_index(struct entry_alloc *ea, struct entry *e)
{
return to_index(ea->es, e) - ea->begin;
}
-static struct entry *get_entry(struct entry_alloc *ea, unsigned index)
+static struct entry *get_entry(struct entry_alloc *ea, unsigned int index)
{
return __get_entry(ea->es, ea->begin + index);
}
@@ -800,9 +801,9 @@ struct smq_policy {
sector_t cache_block_size;
sector_t hotspot_block_size;
- unsigned nr_hotspot_blocks;
- unsigned cache_blocks_per_hotspot_block;
- unsigned hotspot_level_jump;
+ unsigned int nr_hotspot_blocks;
+ unsigned int cache_blocks_per_hotspot_block;
+ unsigned int hotspot_level_jump;
struct entry_space es;
struct entry_alloc writeback_sentinel_alloc;
@@ -831,7 +832,7 @@ struct smq_policy {
* Keeps track of time, incremented by the core. We use this to
* avoid attributing multiple hits within the same tick.
*/
- unsigned tick;
+ unsigned int tick;
/*
* The hash tables allows us to quickly find an entry by origin
@@ -846,8 +847,8 @@ struct smq_policy {
bool current_demote_sentinels;
unsigned long next_demote_period;
- unsigned write_promote_level;
- unsigned read_promote_level;
+ unsigned int write_promote_level;
+ unsigned int read_promote_level;
unsigned long next_hotspot_period;
unsigned long next_cache_period;
@@ -859,24 +860,24 @@ struct smq_policy {
/*----------------------------------------------------------------*/
-static struct entry *get_sentinel(struct entry_alloc *ea, unsigned level, bool which)
+static struct entry *get_sentinel(struct entry_alloc *ea, unsigned int level, bool which)
{
return get_entry(ea, which ? level : NR_CACHE_LEVELS + level);
}
-static struct entry *writeback_sentinel(struct smq_policy *mq, unsigned level)
+static struct entry *writeback_sentinel(struct smq_policy *mq, unsigned int level)
{
return get_sentinel(&mq->writeback_sentinel_alloc, level, mq->current_writeback_sentinels);
}
-static struct entry *demote_sentinel(struct smq_policy *mq, unsigned level)
+static struct entry *demote_sentinel(struct smq_policy *mq, unsigned int level)
{
return get_sentinel(&mq->demote_sentinel_alloc, level, mq->current_demote_sentinels);
}
static void __update_writeback_sentinels(struct smq_policy *mq)
{
- unsigned level;
+ unsigned int level;
struct queue *q = &mq->dirty;
struct entry *sentinel;
@@ -889,7 +890,7 @@ static void __update_writeback_sentinels(struct smq_policy *mq)
static void __update_demote_sentinels(struct smq_policy *mq)
{
- unsigned level;
+ unsigned int level;
struct queue *q = &mq->clean;
struct entry *sentinel;
@@ -917,7 +918,7 @@ static void update_sentinels(struct smq_policy *mq)
static void __sentinels_init(struct smq_policy *mq)
{
- unsigned level;
+ unsigned int level;
struct entry *sentinel;
for (level = 0; level < NR_CACHE_LEVELS; level++) {
@@ -1008,7 +1009,7 @@ static void requeue(struct smq_policy *mq, struct entry *e)
}
}
-static unsigned default_promote_level(struct smq_policy *mq)
+static unsigned int default_promote_level(struct smq_policy *mq)
{
/*
* The promote level depends on the current performance of the
@@ -1030,9 +1031,9 @@ static unsigned default_promote_level(struct smq_policy *mq)
1, 1, 1, 2, 4, 6, 7, 8, 7, 6, 4, 4, 3, 3, 2, 2, 1
};
- unsigned hits = mq->cache_stats.hits;
- unsigned misses = mq->cache_stats.misses;
- unsigned index = safe_div(hits << 4u, hits + misses);
+ unsigned int hits = mq->cache_stats.hits;
+ unsigned int misses = mq->cache_stats.misses;
+ unsigned int index = safe_div(hits << 4u, hits + misses);
return table[index];
}
@@ -1042,7 +1043,7 @@ static void update_promote_levels(struct smq_policy *mq)
* If there are unused cache entries then we want to be really
* eager to promote.
*/
- unsigned threshold_level = allocator_empty(&mq->cache_alloc) ?
+ unsigned int threshold_level = allocator_empty(&mq->cache_alloc) ?
default_promote_level(mq) : (NR_HOTSPOT_LEVELS / 2u);
threshold_level = max(threshold_level, NR_HOTSPOT_LEVELS);
@@ -1124,7 +1125,7 @@ static void end_cache_period(struct smq_policy *mq)
#define CLEAN_TARGET 25u
#define FREE_TARGET 25u
-static unsigned percent_to_target(struct smq_policy *mq, unsigned p)
+static unsigned int percent_to_target(struct smq_policy *mq, unsigned int p)
{
return from_cblock(mq->cache_size) * p / 100u;
}
@@ -1150,7 +1151,7 @@ static bool clean_target_met(struct smq_policy *mq, bool idle)
static bool free_target_met(struct smq_policy *mq)
{
- unsigned nr_free;
+ unsigned int nr_free;
nr_free = from_cblock(mq->cache_size) - mq->cache_alloc.nr_allocated;
return (nr_free + btracker_nr_demotions_queued(mq->bg_work)) >=
@@ -1300,7 +1301,7 @@ static dm_oblock_t to_hblock(struct smq_policy *mq, dm_oblock_t b)
static struct entry *update_hotspot_queue(struct smq_policy *mq, dm_oblock_t b)
{
- unsigned hi;
+ unsigned int hi;
dm_oblock_t hb = to_hblock(mq, b);
struct entry *e = h_lookup(&mq->hotspot_table, hb);
@@ -1549,7 +1550,7 @@ static void smq_clear_dirty(struct dm_cache_policy *p, dm_cblock_t cblock)
spin_unlock_irqrestore(&mq->lock, flags);
}
-static unsigned random_level(dm_cblock_t cblock)
+static unsigned int random_level(dm_cblock_t cblock)
{
return hash_32(from_cblock(cblock), 9) & (NR_CACHE_LEVELS - 1);
}
@@ -1660,7 +1661,7 @@ static int mq_set_config_value(struct dm_cache_policy *p,
}
static int mq_emit_config_values(struct dm_cache_policy *p, char *result,
- unsigned maxlen, ssize_t *sz_ptr)
+ unsigned int maxlen, ssize_t *sz_ptr)
{
ssize_t sz = *sz_ptr;
@@ -1699,16 +1700,16 @@ static void init_policy_functions(struct smq_policy *mq, bool mimic_mq)
static bool too_many_hotspot_blocks(sector_t origin_size,
sector_t hotspot_block_size,
- unsigned nr_hotspot_blocks)
+ unsigned int nr_hotspot_blocks)
{
return (hotspot_block_size * nr_hotspot_blocks) > origin_size;
}
static void calc_hotspot_params(sector_t origin_size,
sector_t cache_block_size,
- unsigned nr_cache_blocks,
+ unsigned int nr_cache_blocks,
sector_t *hotspot_block_size,
- unsigned *nr_hotspot_blocks)
+ unsigned int *nr_hotspot_blocks)
{
*hotspot_block_size = cache_block_size * 16u;
*nr_hotspot_blocks = max(nr_cache_blocks / 4u, 1024u);
@@ -1724,9 +1725,9 @@ static struct dm_cache_policy *__smq_create(dm_cblock_t cache_size,
bool mimic_mq,
bool migrations_allowed)
{
- unsigned i;
- unsigned nr_sentinels_per_queue = 2u * NR_CACHE_LEVELS;
- unsigned total_sentinels = 2u * nr_sentinels_per_queue;
+ unsigned int i;
+ unsigned int nr_sentinels_per_queue = 2u * NR_CACHE_LEVELS;
+ unsigned int total_sentinels = 2u * nr_sentinels_per_queue;
struct smq_policy *mq = kzalloc(sizeof(*mq), GFP_KERNEL);
if (!mq)
diff --git a/drivers/md/dm-cache-policy.c b/drivers/md/dm-cache-policy.c
index c1a3cee99b44..2e58bbcf3e3b 100644
--- a/drivers/md/dm-cache-policy.c
+++ b/drivers/md/dm-cache-policy.c
@@ -154,7 +154,7 @@ const char *dm_cache_policy_get_name(struct dm_cache_policy *p)
}
EXPORT_SYMBOL_GPL(dm_cache_policy_get_name);
-const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p)
+const unsigned int *dm_cache_policy_get_version(struct dm_cache_policy *p)
{
struct dm_cache_policy_type *t = p->private;
diff --git a/drivers/md/dm-cache-policy.h b/drivers/md/dm-cache-policy.h
index 06eb31af626f..6ba3e9c91af5 100644
--- a/drivers/md/dm-cache-policy.h
+++ b/drivers/md/dm-cache-policy.h
@@ -128,7 +128,7 @@ struct dm_cache_policy {
* Configuration.
*/
int (*emit_config_values)(struct dm_cache_policy *p, char *result,
- unsigned maxlen, ssize_t *sz_ptr);
+ unsigned int maxlen, ssize_t *sz_ptr);
int (*set_config_value)(struct dm_cache_policy *p,
const char *key, const char *value);
@@ -157,7 +157,7 @@ struct dm_cache_policy_type {
* what gets passed on the target line to select your policy.
*/
char name[CACHE_POLICY_NAME_SIZE];
- unsigned version[CACHE_POLICY_VERSION_SIZE];
+ unsigned int version[CACHE_POLICY_VERSION_SIZE];
/*
* For use by an alias dm_cache_policy_type to point to the
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 17fde3e5a1f7..8f7426b71e02 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -275,7 +275,7 @@ enum cache_io_mode {
struct cache_features {
enum cache_metadata_mode mode;
enum cache_io_mode io_mode;
- unsigned metadata_version;
+ unsigned int metadata_version;
bool discard_passdown:1;
};
@@ -362,7 +362,7 @@ struct cache {
* Rather than reconstructing the table line for the status we just
* save it and regurgitate.
*/
- unsigned nr_ctr_args;
+ unsigned int nr_ctr_args;
const char **ctr_args;
struct dm_kcopyd_client *copier;
@@ -378,7 +378,7 @@ struct cache {
unsigned long *dirty_bitset;
atomic_t nr_dirty;
- unsigned policy_nr_args;
+ unsigned int policy_nr_args;
struct dm_cache_policy *policy;
/*
@@ -409,7 +409,7 @@ struct cache {
struct per_bio_data {
bool tick:1;
- unsigned req_nr:2;
+ unsigned int req_nr:2;
struct dm_bio_prison_cell_v2 *cell;
struct dm_hook_info hook_info;
sector_t len;
@@ -517,7 +517,7 @@ static void build_key(dm_oblock_t begin, dm_oblock_t end, struct dm_cell_key_v2
#define WRITE_LOCK_LEVEL 0
#define READ_WRITE_LOCK_LEVEL 1
-static unsigned lock_level(struct bio *bio)
+static unsigned int lock_level(struct bio *bio)
{
return bio_data_dir(bio) == WRITE ?
WRITE_LOCK_LEVEL :
@@ -1884,7 +1884,7 @@ static void check_migrations(struct work_struct *ws)
*/
static void destroy(struct cache *cache)
{
- unsigned i;
+ unsigned int i;
mempool_exit(&cache->migration_pool);
@@ -2124,7 +2124,7 @@ static int parse_features(struct cache_args *ca, struct dm_arg_set *as,
};
int r, mode_ctr = 0;
- unsigned argc;
+ unsigned int argc;
const char *arg;
struct cache_features *cf = &ca->features;
@@ -2544,7 +2544,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
static int copy_ctr_args(struct cache *cache, int argc, const char **argv)
{
- unsigned i;
+ unsigned int i;
const char **copy;
copy = kcalloc(argc, sizeof(*copy), GFP_KERNEL);
@@ -2566,7 +2566,7 @@ static int copy_ctr_args(struct cache *cache, int argc, const char **argv)
return 0;
}
-static int cache_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int cache_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
int r = -EINVAL;
struct cache_args *ca;
@@ -2669,7 +2669,7 @@ static int write_dirty_bitset(struct cache *cache)
static int write_discard_bitset(struct cache *cache)
{
- unsigned i, r;
+ unsigned int i, r;
if (get_cache_mode(cache) >= CM_READ_ONLY)
return -EINVAL;
@@ -2983,11 +2983,11 @@ static void cache_resume(struct dm_target *ti)
}
static void emit_flags(struct cache *cache, char *result,
- unsigned maxlen, ssize_t *sz_ptr)
+ unsigned int maxlen, ssize_t *sz_ptr)
{
ssize_t sz = *sz_ptr;
struct cache_features *cf = &cache->features;
- unsigned count = (cf->metadata_version == 2) + !cf->discard_passdown + 1;
+ unsigned int count = (cf->metadata_version == 2) + !cf->discard_passdown + 1;
DMEMIT("%u ", count);
@@ -3027,10 +3027,10 @@ static void emit_flags(struct cache *cache, char *result,
* <policy name> <#policy args> <policy args>* <cache metadata mode> <needs_check>
*/
static void cache_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int r = 0;
- unsigned i;
+ unsigned int i;
ssize_t sz = 0;
dm_block_t nr_free_blocks_metadata = 0;
dm_block_t nr_blocks_metadata = 0;
@@ -3067,18 +3067,18 @@ static void cache_status(struct dm_target *ti, status_type_t type,
residency = policy_residency(cache->policy);
DMEMIT("%u %llu/%llu %llu %llu/%llu %u %u %u %u %u %u %lu ",
- (unsigned)DM_CACHE_METADATA_BLOCK_SIZE,
+ (unsigned int)DM_CACHE_METADATA_BLOCK_SIZE,
(unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
(unsigned long long)nr_blocks_metadata,
(unsigned long long)cache->sectors_per_block,
(unsigned long long) from_cblock(residency),
(unsigned long long) from_cblock(cache->cache_size),
- (unsigned) atomic_read(&cache->stats.read_hit),
- (unsigned) atomic_read(&cache->stats.read_miss),
- (unsigned) atomic_read(&cache->stats.write_hit),
- (unsigned) atomic_read(&cache->stats.write_miss),
- (unsigned) atomic_read(&cache->stats.demotion),
- (unsigned) atomic_read(&cache->stats.promotion),
+ (unsigned int) atomic_read(&cache->stats.read_hit),
+ (unsigned int) atomic_read(&cache->stats.read_miss),
+ (unsigned int) atomic_read(&cache->stats.write_hit),
+ (unsigned int) atomic_read(&cache->stats.write_miss),
+ (unsigned int) atomic_read(&cache->stats.demotion),
+ (unsigned int) atomic_read(&cache->stats.promotion),
(unsigned long) atomic_read(&cache->nr_dirty));
emit_flags(cache, result, maxlen, &sz);
@@ -3257,11 +3257,11 @@ static int request_invalidation(struct cache *cache, struct cblock_range *range)
return r;
}
-static int process_invalidate_cblocks_message(struct cache *cache, unsigned count,
+static int process_invalidate_cblocks_message(struct cache *cache, unsigned int count,
const char **cblock_ranges)
{
int r = 0;
- unsigned i;
+ unsigned int i;
struct cblock_range range;
if (!passthrough_mode(cache)) {
@@ -3298,8 +3298,8 @@ static int process_invalidate_cblocks_message(struct cache *cache, unsigned coun
*
* The key migration_threshold is supported by the cache target core.
*/
-static int cache_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int cache_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
struct cache *cache = ti->private;
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index 6c6bd24774f2..28c641352de9 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -119,7 +119,7 @@ struct mapped_device {
struct dm_stats stats;
/* the number of internal suspends */
- unsigned internal_suspend_count;
+ unsigned int internal_suspend_count;
int swap_bios;
struct semaphore swap_bios_semaphore;
@@ -326,9 +326,9 @@ static inline struct completion *dm_get_completion_from_kobject(struct kobject *
return &container_of(kobj, struct dm_kobject_holder, kobj)->completion;
}
-unsigned __dm_get_module_param(unsigned *module_param, unsigned def, unsigned max);
+unsigned int __dm_get_module_param(unsigned int *module_param, unsigned int def, unsigned int max);
-static inline bool dm_message_test_buffer_overflow(char *result, unsigned maxlen)
+static inline bool dm_message_test_buffer_overflow(char *result, unsigned int maxlen)
{
return !maxlen || strlen(result) + 1 >= maxlen;
}
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index dc2d0d61ade9..ee269b1d09fa 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -173,14 +173,14 @@ struct crypt_config {
} iv_gen_private;
u64 iv_offset;
unsigned int iv_size;
- unsigned short int sector_size;
+ unsigned short sector_size;
unsigned char sector_shift;
union {
struct crypto_skcipher **tfms;
struct crypto_aead **tfms_aead;
} cipher_tfm;
- unsigned tfms_count;
+ unsigned int tfms_count;
unsigned long cipher_flags;
/*
@@ -214,7 +214,7 @@ struct crypt_config {
* pool for per bio private data, crypto requests,
* encryption requeusts/buffer pages and integrity tags
*/
- unsigned tag_pool_max_sectors;
+ unsigned int tag_pool_max_sectors;
mempool_t tag_pool;
mempool_t req_pool;
mempool_t page_pool;
@@ -231,7 +231,7 @@ struct crypt_config {
#define POOL_ENTRY_SIZE 512
static DEFINE_SPINLOCK(dm_crypt_clients_lock);
-static unsigned dm_crypt_clients_n = 0;
+static unsigned int dm_crypt_clients_n = 0;
static volatile unsigned long dm_crypt_pages_per_client;
#define DM_CRYPT_MEMORY_PERCENT 2
#define DM_CRYPT_MIN_PAGES_PER_CLIENT (BIO_MAX_VECS * 16)
@@ -356,7 +356,7 @@ static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv,
static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
const char *opts)
{
- unsigned bs;
+ unsigned int bs;
int log;
if (crypt_integrity_aead(cc))
@@ -1466,7 +1466,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
static int crypt_alloc_req_skcipher(struct crypt_config *cc,
struct convert_context *ctx)
{
- unsigned key_index = ctx->cc_sector & (cc->tfms_count - 1);
+ unsigned int key_index = ctx->cc_sector & (cc->tfms_count - 1);
if (!ctx->r.req) {
ctx->r.req = mempool_alloc(&cc->req_pool, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
@@ -1660,13 +1660,13 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone);
* non-blocking allocations without a mutex first but on failure we fallback
* to blocking allocations with a mutex.
*/
-static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
+static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size)
{
struct crypt_config *cc = io->cc;
struct bio *clone;
unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM;
- unsigned i, len, remaining_size;
+ unsigned int i, len, remaining_size;
struct page *page;
retry:
@@ -1806,7 +1806,7 @@ static void crypt_endio(struct bio *clone)
{
struct dm_crypt_io *io = clone->bi_private;
struct crypt_config *cc = io->cc;
- unsigned rw = bio_data_dir(clone);
+ unsigned int rw = bio_data_dir(clone);
blk_status_t error;
/*
@@ -2261,7 +2261,7 @@ static void crypt_free_tfms_aead(struct crypt_config *cc)
static void crypt_free_tfms_skcipher(struct crypt_config *cc)
{
- unsigned i;
+ unsigned int i;
if (!cc->cipher_tfm.tfms)
return;
@@ -2286,7 +2286,7 @@ static void crypt_free_tfms(struct crypt_config *cc)
static int crypt_alloc_tfms_skcipher(struct crypt_config *cc, char *ciphermode)
{
- unsigned i;
+ unsigned int i;
int err;
cc->cipher_tfm.tfms = kcalloc(cc->tfms_count,
@@ -2344,12 +2344,12 @@ static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode)
return crypt_alloc_tfms_skcipher(cc, ciphermode);
}
-static unsigned crypt_subkey_size(struct crypt_config *cc)
+static unsigned int crypt_subkey_size(struct crypt_config *cc)
{
return (cc->key_size - cc->key_extra_size) >> ilog2(cc->tfms_count);
}
-static unsigned crypt_authenckey_size(struct crypt_config *cc)
+static unsigned int crypt_authenckey_size(struct crypt_config *cc)
{
return crypt_subkey_size(cc) + RTA_SPACE(sizeof(struct crypto_authenc_key_param));
}
@@ -2360,7 +2360,7 @@ static unsigned crypt_authenckey_size(struct crypt_config *cc)
* This funcion converts cc->key to this special format.
*/
static void crypt_copy_authenckey(char *p, const void *key,
- unsigned enckeylen, unsigned authkeylen)
+ unsigned int enckeylen, unsigned int authkeylen)
{
struct crypto_authenc_key_param *param;
struct rtattr *rta;
@@ -2378,7 +2378,7 @@ static void crypt_copy_authenckey(char *p, const void *key,
static int crypt_setkey(struct crypt_config *cc)
{
- unsigned subkey_size;
+ unsigned int subkey_size;
int err = 0, i, r;
/* Ignore extra keys (which are used for IV etc) */
@@ -3417,7 +3417,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
if (cc->on_disk_tag_size) {
- unsigned tag_len = cc->on_disk_tag_size * (bio_sectors(bio) >> cc->sector_shift);
+ unsigned int tag_len = cc->on_disk_tag_size * (bio_sectors(bio) >> cc->sector_shift);
if (unlikely(tag_len > KMALLOC_MAX_SIZE) ||
unlikely(!(io->integrity_metadata = kmalloc(tag_len,
@@ -3445,14 +3445,14 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
static char hex2asc(unsigned char c)
{
- return c + '0' + ((unsigned)(9 - c) >> 4 & 0x27);
+ return c + '0' + ((unsigned int)(9 - c) >> 4 & 0x27);
}
static void crypt_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct crypt_config *cc = ti->private;
- unsigned i, sz = 0;
+ unsigned int i, sz = 0;
int num_feature_args = 0;
switch (type) {
@@ -3568,8 +3568,8 @@ static void crypt_resume(struct dm_target *ti)
* key set <key>
* key wipe
*/
-static int crypt_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int crypt_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
struct crypt_config *cc = ti->private;
int key_size, ret = -EINVAL;
@@ -3630,10 +3630,10 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
limits->max_segment_size = PAGE_SIZE;
limits->logical_block_size =
- max_t(unsigned, limits->logical_block_size, cc->sector_size);
+ max_t(unsigned int, limits->logical_block_size, cc->sector_size);
limits->physical_block_size =
- max_t(unsigned, limits->physical_block_size, cc->sector_size);
- limits->io_min = max_t(unsigned, limits->io_min, cc->sector_size);
+ max_t(unsigned int, limits->physical_block_size, cc->sector_size);
+ limits->io_min = max_t(unsigned int, limits->io_min, cc->sector_size);
limits->dma_alignment = limits->logical_block_size - 1;
}
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 869afef5654a..02b8f4e81827 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -20,8 +20,8 @@
struct delay_class {
struct dm_dev *dev;
sector_t start;
- unsigned delay;
- unsigned ops;
+ unsigned int delay;
+ unsigned int ops;
};
struct delay_c {
@@ -305,7 +305,7 @@ static int delay_map(struct dm_target *ti, struct bio *bio)
DMEMIT("%s %llu %u", (c)->dev->name, (unsigned long long)(c)->start, (c)->delay)
static void delay_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct delay_c *dc = ti->private;
int sz = 0;
diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c
index 512cc6cea095..7606c6695a0e 100644
--- a/drivers/md/dm-ebs-target.c
+++ b/drivers/md/dm-ebs-target.c
@@ -390,7 +390,7 @@ static int ebs_map(struct dm_target *ti, struct bio *bio)
}
static void ebs_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct ebs_c *ec = ti->private;
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index e92c1afc3677..a96290103cca 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -51,7 +51,7 @@ static void writeset_free(struct writeset *ws)
}
static int setup_on_disk_bitset(struct dm_disk_bitset *info,
- unsigned nr_bits, dm_block_t *root)
+ unsigned int nr_bits, dm_block_t *root)
{
int r;
@@ -62,7 +62,7 @@ static int setup_on_disk_bitset(struct dm_disk_bitset *info,
return dm_bitset_resize(info, *root, 0, nr_bits, false, root);
}
-static size_t bitset_size(unsigned nr_bits)
+static size_t bitset_size(unsigned int nr_bits)
{
return sizeof(unsigned long) * dm_div_up(nr_bits, BITS_PER_LONG);
}
@@ -323,10 +323,10 @@ static int superblock_lock(struct era_metadata *md,
static int superblock_all_zeroes(struct dm_block_manager *bm, bool *result)
{
int r;
- unsigned i;
+ unsigned int i;
struct dm_block *b;
__le64 *data_le, zero = cpu_to_le64(0);
- unsigned sb_block_size = dm_bm_block_size(bm) / sizeof(__le64);
+ unsigned int sb_block_size = dm_bm_block_size(bm) / sizeof(__le64);
/*
* We can't use a validator here - it may be all zeroes.
@@ -363,12 +363,12 @@ static void ws_unpack(const struct writeset_disk *disk, struct writeset_metadata
core->root = le64_to_cpu(disk->root);
}
-static void ws_inc(void *context, const void *value, unsigned count)
+static void ws_inc(void *context, const void *value, unsigned int count)
{
struct era_metadata *md = context;
struct writeset_disk ws_d;
dm_block_t b;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++) {
memcpy(&ws_d, value + (i * sizeof(ws_d)), sizeof(ws_d));
@@ -377,12 +377,12 @@ static void ws_inc(void *context, const void *value, unsigned count)
}
}
-static void ws_dec(void *context, const void *value, unsigned count)
+static void ws_dec(void *context, const void *value, unsigned int count)
{
struct era_metadata *md = context;
struct writeset_disk ws_d;
dm_block_t b;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++) {
memcpy(&ws_d, value + (i * sizeof(ws_d)), sizeof(ws_d));
@@ -667,7 +667,7 @@ static void swap_writeset(struct era_metadata *md, struct writeset *new_writeset
*--------------------------------------------------------------*/
struct digest {
uint32_t era;
- unsigned nr_bits, current_bit;
+ unsigned int nr_bits, current_bit;
struct writeset_metadata writeset;
__le32 value;
struct dm_disk_bitset info;
@@ -702,7 +702,7 @@ static int metadata_digest_transcribe_writeset(struct era_metadata *md,
{
int r;
bool marked;
- unsigned b, e = min(d->current_bit + INSERTS_PER_STEP, d->nr_bits);
+ unsigned int b, e = min(d->current_bit + INSERTS_PER_STEP, d->nr_bits);
for (b = d->current_bit; b < e; b++) {
r = writeset_marked_on_disk(&d->info, &d->writeset, b, &marked);
@@ -1439,7 +1439,7 @@ static bool valid_block_size(dm_block_t block_size)
/*
* <metadata dev> <data dev> <data block size (sectors)>
*/
-static int era_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int era_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
int r;
char dummy;
@@ -1618,7 +1618,7 @@ static int era_preresume(struct dm_target *ti)
* <current era> <held metadata root | '-'>
*/
static void era_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int r;
struct era *era = ti->private;
@@ -1633,10 +1633,10 @@ static void era_status(struct dm_target *ti, status_type_t type,
goto err;
DMEMIT("%u %llu/%llu %u",
- (unsigned) (DM_ERA_METADATA_BLOCK_SIZE >> SECTOR_SHIFT),
+ (unsigned int) (DM_ERA_METADATA_BLOCK_SIZE >> SECTOR_SHIFT),
(unsigned long long) stats.used,
(unsigned long long) stats.total,
- (unsigned) stats.era);
+ (unsigned int) stats.era);
if (stats.snap != SUPERBLOCK_LOCATION)
DMEMIT(" %llu", stats.snap);
@@ -1662,8 +1662,8 @@ static void era_status(struct dm_target *ti, status_type_t type,
DMEMIT("Error");
}
-static int era_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int era_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
struct era *era = ti->private;
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 3997f34cfebc..cc3987c97eb9 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -142,7 +142,7 @@ EXPORT_SYMBOL(dm_exception_store_type_unregister);
static int set_chunk_size(struct dm_exception_store *store,
const char *chunk_size_arg, char **error)
{
- unsigned chunk_size;
+ unsigned int chunk_size;
if (kstrtouint(chunk_size_arg, 10, &chunk_size)) {
*error = "Invalid chunk size";
@@ -158,7 +158,7 @@ static int set_chunk_size(struct dm_exception_store *store,
}
int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
- unsigned chunk_size,
+ unsigned int chunk_size,
char **error)
{
/* Check chunk_size is a power of 2 */
@@ -190,7 +190,7 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
struct dm_snapshot *snap,
- unsigned *args_used,
+ unsigned int *args_used,
struct dm_exception_store **store)
{
int r = 0;
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
index b5f20eba3641..862df68a7db0 100644
--- a/drivers/md/dm-exception-store.h
+++ b/drivers/md/dm-exception-store.h
@@ -96,9 +96,9 @@ struct dm_exception_store_type {
*/
void (*drop_snapshot) (struct dm_exception_store *store);
- unsigned (*status) (struct dm_exception_store *store,
- status_type_t status, char *result,
- unsigned maxlen);
+ unsigned int (*status) (struct dm_exception_store *store,
+ status_type_t status, char *result,
+ unsigned int maxlen);
/*
* Return how full the snapshot is.
@@ -118,9 +118,9 @@ struct dm_exception_store {
struct dm_snapshot *snap;
/* Size of data blocks saved - must be a power of 2 */
- unsigned chunk_size;
- unsigned chunk_mask;
- unsigned chunk_shift;
+ unsigned int chunk_size;
+ unsigned int chunk_mask;
+ unsigned int chunk_shift;
void *context;
@@ -144,7 +144,7 @@ static inline chunk_t dm_chunk_number(chunk_t chunk)
return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
}
-static inline unsigned dm_consecutive_chunk_count(struct dm_exception *e)
+static inline unsigned int dm_consecutive_chunk_count(struct dm_exception *e)
{
return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
}
@@ -181,12 +181,12 @@ int dm_exception_store_type_register(struct dm_exception_store_type *type);
int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
- unsigned chunk_size,
+ unsigned int chunk_size,
char **error);
int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
struct dm_snapshot *snap,
- unsigned *args_used,
+ unsigned int *args_used,
struct dm_exception_store **store);
void dm_exception_store_destroy(struct dm_exception_store *store);
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 335684a1aeaa..7efbdb42cf3b 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -26,12 +26,12 @@ struct flakey_c {
struct dm_dev *dev;
unsigned long start_time;
sector_t start;
- unsigned up_interval;
- unsigned down_interval;
+ unsigned int up_interval;
+ unsigned int down_interval;
unsigned long flags;
- unsigned corrupt_bio_byte;
- unsigned corrupt_bio_rw;
- unsigned corrupt_bio_value;
+ unsigned int corrupt_bio_byte;
+ unsigned int corrupt_bio_rw;
+ unsigned int corrupt_bio_value;
blk_opf_t corrupt_bio_flags;
};
@@ -48,7 +48,7 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
struct dm_target *ti)
{
int r;
- unsigned argc;
+ unsigned int argc;
const char *arg_name;
static const struct dm_arg _args[] = {
@@ -148,7 +148,7 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
BUILD_BUG_ON(sizeof(fc->corrupt_bio_flags) !=
sizeof(unsigned int));
r = dm_read_arg(_args + 3, as,
- (__force unsigned *)&fc->corrupt_bio_flags,
+ (__force unsigned int *)&fc->corrupt_bio_flags,
&ti->error);
if (r)
return r;
@@ -324,7 +324,7 @@ static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc)
static int flakey_map(struct dm_target *ti, struct bio *bio)
{
struct flakey_c *fc = ti->private;
- unsigned elapsed;
+ unsigned int elapsed;
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
pb->bio_submitted = false;
@@ -417,11 +417,11 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
}
static void flakey_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct flakey_c *fc = ti->private;
- unsigned drop_writes, error_writes;
+ unsigned int drop_writes, error_writes;
switch (type) {
case STATUSTYPE_INFO:
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 1388ee35571e..53f9f765df9f 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -157,13 +157,13 @@ struct alg_spec {
char *alg_string;
char *key_string;
__u8 *key;
- unsigned key_size;
+ unsigned int key_size;
};
struct dm_integrity_c {
struct dm_dev *dev;
struct dm_dev *meta_dev;
- unsigned tag_size;
+ unsigned int tag_size;
__s8 log2_tag_size;
sector_t start;
mempool_t journal_io_mempool;
@@ -171,8 +171,8 @@ struct dm_integrity_c {
struct dm_bufio_client *bufio;
struct workqueue_struct *metadata_wq;
struct superblock *sb;
- unsigned journal_pages;
- unsigned n_bitmap_blocks;
+ unsigned int journal_pages;
+ unsigned int n_bitmap_blocks;
struct page_list *journal;
struct page_list *journal_io;
@@ -180,7 +180,7 @@ struct dm_integrity_c {
struct page_list *recalc_bitmap;
struct page_list *may_write_bitmap;
struct bitmap_block_status *bbs;
- unsigned bitmap_flush_interval;
+ unsigned int bitmap_flush_interval;
int synchronous_mode;
struct bio_list synchronous_bios;
struct delayed_work bitmap_flush_work;
@@ -201,12 +201,12 @@ struct dm_integrity_c {
unsigned char journal_entries_per_sector;
unsigned char journal_section_entries;
unsigned short journal_section_sectors;
- unsigned journal_sections;
- unsigned journal_entries;
+ unsigned int journal_sections;
+ unsigned int journal_entries;
sector_t data_device_sectors;
sector_t meta_device_sectors;
- unsigned initial_sectors;
- unsigned metadata_run;
+ unsigned int initial_sectors;
+ unsigned int metadata_run;
__s8 log2_metadata_run;
__u8 log2_buffer_sectors;
__u8 sectors_per_block;
@@ -230,17 +230,17 @@ struct dm_integrity_c {
unsigned char commit_seq;
commit_id_t commit_ids[N_COMMIT_IDS];
- unsigned committed_section;
- unsigned n_committed_sections;
+ unsigned int committed_section;
+ unsigned int n_committed_sections;
- unsigned uncommitted_section;
- unsigned n_uncommitted_sections;
+ unsigned int uncommitted_section;
+ unsigned int n_uncommitted_sections;
- unsigned free_section;
+ unsigned int free_section;
unsigned char free_section_entry;
- unsigned free_sectors;
+ unsigned int free_sectors;
- unsigned free_sectors_threshold;
+ unsigned int free_sectors_threshold;
struct workqueue_struct *commit_wq;
struct work_struct commit_work;
@@ -257,7 +257,7 @@ struct dm_integrity_c {
unsigned long autocommit_jiffies;
struct timer_list autocommit_timer;
- unsigned autocommit_msec;
+ unsigned int autocommit_msec;
wait_queue_head_t copy_to_journal_wait;
@@ -305,7 +305,7 @@ struct dm_integrity_io {
struct dm_integrity_range range;
sector_t metadata_block;
- unsigned metadata_offset;
+ unsigned int metadata_offset;
atomic_t in_flight;
blk_status_t bi_status;
@@ -329,7 +329,7 @@ struct journal_io {
struct bitmap_block_status {
struct work_struct work;
struct dm_integrity_c *ic;
- unsigned idx;
+ unsigned int idx;
unsigned long *bitmap;
struct bio_list bio_queue;
spinlock_t bio_queue_lock;
@@ -410,8 +410,8 @@ static bool dm_integrity_disable_recalculate(struct dm_integrity_c *ic)
return false;
}
-static commit_id_t dm_integrity_commit_id(struct dm_integrity_c *ic, unsigned i,
- unsigned j, unsigned char seq)
+static commit_id_t dm_integrity_commit_id(struct dm_integrity_c *ic, unsigned int i,
+ unsigned int j, unsigned char seq)
{
/*
* Xor the number with section and sector, so that if a piece of
@@ -426,7 +426,7 @@ static void get_area_and_offset(struct dm_integrity_c *ic, sector_t data_sector,
if (!ic->meta_dev) {
__u8 log2_interleave_sectors = ic->sb->log2_interleave_sectors;
*area = data_sector >> log2_interleave_sectors;
- *offset = (unsigned)data_sector & ((1U << log2_interleave_sectors) - 1);
+ *offset = (unsigned int)data_sector & ((1U << log2_interleave_sectors) - 1);
} else {
*area = 0;
*offset = data_sector;
@@ -435,15 +435,15 @@ static void get_area_and_offset(struct dm_integrity_c *ic, sector_t data_sector,
#define sector_to_block(ic, n) \
do { \
- BUG_ON((n) & (unsigned)((ic)->sectors_per_block - 1)); \
+ BUG_ON((n) & (unsigned int)((ic)->sectors_per_block - 1)); \
(n) >>= (ic)->sb->log2_sectors_per_block; \
} while (0)
static __u64 get_metadata_sector_and_offset(struct dm_integrity_c *ic, sector_t area,
- sector_t offset, unsigned *metadata_offset)
+ sector_t offset, unsigned int *metadata_offset)
{
__u64 ms;
- unsigned mo;
+ unsigned int mo;
ms = area << ic->sb->log2_interleave_sectors;
if (likely(ic->log2_metadata_run >= 0))
@@ -484,7 +484,7 @@ static sector_t get_data_sector(struct dm_integrity_c *ic, sector_t area, sector
return result;
}
-static void wraparound_section(struct dm_integrity_c *ic, unsigned *sec_ptr)
+static void wraparound_section(struct dm_integrity_c *ic, unsigned int *sec_ptr)
{
if (unlikely(*sec_ptr >= ic->journal_sections))
*sec_ptr -= ic->journal_sections;
@@ -508,7 +508,7 @@ static int sb_mac(struct dm_integrity_c *ic, bool wr)
{
SHASH_DESC_ON_STACK(desc, ic->journal_mac);
int r;
- unsigned size = crypto_shash_digestsize(ic->journal_mac);
+ unsigned int size = crypto_shash_digestsize(ic->journal_mac);
if (sizeof(struct superblock) + size > 1 << SECTOR_SHIFT) {
dm_integrity_io_error(ic, "digest is too long", -EINVAL);
@@ -704,8 +704,8 @@ static bool block_bitmap_op(struct dm_integrity_c *ic, struct page_list *bitmap,
static void block_bitmap_copy(struct dm_integrity_c *ic, struct page_list *dst, struct page_list *src)
{
- unsigned n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
- unsigned i;
+ unsigned int n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
+ unsigned int i;
for (i = 0; i < n_bitmap_pages; i++) {
unsigned long *dst_data = lowmem_page_address(dst[i].page);
@@ -716,18 +716,18 @@ static void block_bitmap_copy(struct dm_integrity_c *ic, struct page_list *dst,
static struct bitmap_block_status *sector_to_bitmap_block(struct dm_integrity_c *ic, sector_t sector)
{
- unsigned bit = sector >> (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
- unsigned bitmap_block = bit / (BITMAP_BLOCK_SIZE * 8);
+ unsigned int bit = sector >> (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
+ unsigned int bitmap_block = bit / (BITMAP_BLOCK_SIZE * 8);
BUG_ON(bitmap_block >= ic->n_bitmap_blocks);
return &ic->bbs[bitmap_block];
}
-static void access_journal_check(struct dm_integrity_c *ic, unsigned section, unsigned offset,
+static void access_journal_check(struct dm_integrity_c *ic, unsigned int section, unsigned int offset,
bool e, const char *function)
{
#if defined(CONFIG_DM_DEBUG) || defined(INTERNAL_VERIFY)
- unsigned limit = e ? ic->journal_section_entries : ic->journal_section_sectors;
+ unsigned int limit = e ? ic->journal_section_entries : ic->journal_section_sectors;
if (unlikely(section >= ic->journal_sections) ||
unlikely(offset >= limit)) {
@@ -738,10 +738,10 @@ static void access_journal_check(struct dm_integrity_c *ic, unsigned section, un
#endif
}
-static void page_list_location(struct dm_integrity_c *ic, unsigned section, unsigned offset,
- unsigned *pl_index, unsigned *pl_offset)
+static void page_list_location(struct dm_integrity_c *ic, unsigned int section, unsigned int offset,
+ unsigned int *pl_index, unsigned int *pl_offset)
{
- unsigned sector;
+ unsigned int sector;
access_journal_check(ic, section, offset, false, "page_list_location");
@@ -752,9 +752,9 @@ static void page_list_location(struct dm_integrity_c *ic, unsigned section, unsi
}
static struct journal_sector *access_page_list(struct dm_integrity_c *ic, struct page_list *pl,
- unsigned section, unsigned offset, unsigned *n_sectors)
+ unsigned int section, unsigned int offset, unsigned int *n_sectors)
{
- unsigned pl_index, pl_offset;
+ unsigned int pl_index, pl_offset;
char *va;
page_list_location(ic, section, offset, &pl_index, &pl_offset);
@@ -767,14 +767,14 @@ static struct journal_sector *access_page_list(struct dm_integrity_c *ic, struct
return (struct journal_sector *)(va + pl_offset);
}
-static struct journal_sector *access_journal(struct dm_integrity_c *ic, unsigned section, unsigned offset)
+static struct journal_sector *access_journal(struct dm_integrity_c *ic, unsigned int section, unsigned int offset)
{
return access_page_list(ic, ic->journal, section, offset, NULL);
}
-static struct journal_entry *access_journal_entry(struct dm_integrity_c *ic, unsigned section, unsigned n)
+static struct journal_entry *access_journal_entry(struct dm_integrity_c *ic, unsigned int section, unsigned int n)
{
- unsigned rel_sector, offset;
+ unsigned int rel_sector, offset;
struct journal_sector *js;
access_journal_check(ic, section, n, true, "access_journal_entry");
@@ -786,7 +786,7 @@ static struct journal_entry *access_journal_entry(struct dm_integrity_c *ic, uns
return (struct journal_entry *)((char *)js + offset * ic->journal_entry_size);
}
-static struct journal_sector *access_journal_data(struct dm_integrity_c *ic, unsigned section, unsigned n)
+static struct journal_sector *access_journal_data(struct dm_integrity_c *ic, unsigned int section, unsigned int n)
{
n <<= ic->sb->log2_sectors_per_block;
@@ -797,11 +797,11 @@ static struct journal_sector *access_journal_data(struct dm_integrity_c *ic, uns
return access_journal(ic, section, n);
}
-static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result[JOURNAL_MAC_SIZE])
+static void section_mac(struct dm_integrity_c *ic, unsigned int section, __u8 result[JOURNAL_MAC_SIZE])
{
SHASH_DESC_ON_STACK(desc, ic->journal_mac);
int r;
- unsigned j, size;
+ unsigned int j, size;
desc->tfm = ic->journal_mac;
@@ -866,10 +866,10 @@ static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result
memset(result, 0, JOURNAL_MAC_SIZE);
}
-static void rw_section_mac(struct dm_integrity_c *ic, unsigned section, bool wr)
+static void rw_section_mac(struct dm_integrity_c *ic, unsigned int section, bool wr)
{
__u8 result[JOURNAL_MAC_SIZE];
- unsigned j;
+ unsigned int j;
if (!ic->journal_mac)
return;
@@ -898,12 +898,12 @@ static void complete_journal_op(void *context)
complete(&comp->comp);
}
-static void xor_journal(struct dm_integrity_c *ic, bool encrypt, unsigned section,
- unsigned n_sections, struct journal_completion *comp)
+static void xor_journal(struct dm_integrity_c *ic, bool encrypt, unsigned int section,
+ unsigned int n_sections, struct journal_completion *comp)
{
struct async_submit_ctl submit;
size_t n_bytes = (size_t)(n_sections * ic->journal_section_sectors) << SECTOR_SHIFT;
- unsigned pl_index, pl_offset, section_index;
+ unsigned int pl_index, pl_offset, section_index;
struct page_list *source_pl, *target_pl;
if (likely(encrypt)) {
@@ -928,7 +928,7 @@ static void xor_journal(struct dm_integrity_c *ic, bool encrypt, unsigned sectio
struct page *dst_page;
while (unlikely(pl_index == section_index)) {
- unsigned dummy;
+ unsigned int dummy;
if (likely(encrypt))
rw_section_mac(ic, section, true);
section++;
@@ -990,8 +990,8 @@ static bool do_crypt(bool encrypt, struct skcipher_request *req, struct journal_
return false;
}
-static void crypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned section,
- unsigned n_sections, struct journal_completion *comp)
+static void crypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned int section,
+ unsigned int n_sections, struct journal_completion *comp)
{
struct scatterlist **source_sg;
struct scatterlist **target_sg;
@@ -1008,7 +1008,7 @@ static void crypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned sect
do {
struct skcipher_request *req;
- unsigned ivsize;
+ unsigned int ivsize;
char *iv;
if (likely(encrypt))
@@ -1034,8 +1034,8 @@ static void crypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned sect
complete_journal_op(comp);
}
-static void encrypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned section,
- unsigned n_sections, struct journal_completion *comp)
+static void encrypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned int section,
+ unsigned int n_sections, struct journal_completion *comp)
{
if (ic->journal_xor)
return xor_journal(ic, encrypt, section, n_sections, comp);
@@ -1052,12 +1052,12 @@ static void complete_journal_io(unsigned long error, void *context)
}
static void rw_journal_sectors(struct dm_integrity_c *ic, blk_opf_t opf,
- unsigned sector, unsigned n_sectors,
+ unsigned int sector, unsigned int n_sectors,
struct journal_completion *comp)
{
struct dm_io_request io_req;
struct dm_io_region io_loc;
- unsigned pl_index, pl_offset;
+ unsigned int pl_index, pl_offset;
int r;
if (unlikely(dm_integrity_failed(ic))) {
@@ -1099,10 +1099,10 @@ static void rw_journal_sectors(struct dm_integrity_c *ic, blk_opf_t opf,
}
static void rw_journal(struct dm_integrity_c *ic, blk_opf_t opf,
- unsigned section, unsigned n_sections,
+ unsigned int section, unsigned int n_sections,
struct journal_completion *comp)
{
- unsigned sector, n_sectors;
+ unsigned int sector, n_sectors;
sector = section * ic->journal_section_sectors;
n_sectors = n_sections * ic->journal_section_sectors;
@@ -1110,12 +1110,12 @@ static void rw_journal(struct dm_integrity_c *ic, blk_opf_t opf,
rw_journal_sectors(ic, opf, sector, n_sectors, comp);
}
-static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsigned commit_sections)
+static void write_journal(struct dm_integrity_c *ic, unsigned int commit_start, unsigned int commit_sections)
{
struct journal_completion io_comp;
struct journal_completion crypt_comp_1;
struct journal_completion crypt_comp_2;
- unsigned i;
+ unsigned int i;
io_comp.ic = ic;
init_completion(&io_comp.comp);
@@ -1135,7 +1135,7 @@ static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsi
rw_journal(ic, REQ_OP_WRITE | REQ_FUA | REQ_SYNC, commit_start,
commit_sections, &io_comp);
} else {
- unsigned to_end;
+ unsigned int to_end;
io_comp.in_flight = (atomic_t)ATOMIC_INIT(2);
to_end = ic->journal_sections - commit_start;
if (ic->journal_io) {
@@ -1172,15 +1172,15 @@ static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsi
wait_for_completion_io(&io_comp.comp);
}
-static void copy_from_journal(struct dm_integrity_c *ic, unsigned section, unsigned offset,
- unsigned n_sectors, sector_t target, io_notify_fn fn, void *data)
+static void copy_from_journal(struct dm_integrity_c *ic, unsigned int section, unsigned int offset,
+ unsigned int n_sectors, sector_t target, io_notify_fn fn, void *data)
{
struct dm_io_request io_req;
struct dm_io_region io_loc;
int r;
- unsigned sector, pl_index, pl_offset;
+ unsigned int sector, pl_index, pl_offset;
- BUG_ON((target | n_sectors | offset) & (unsigned)(ic->sectors_per_block - 1));
+ BUG_ON((target | n_sectors | offset) & (unsigned int)(ic->sectors_per_block - 1));
if (unlikely(dm_integrity_failed(ic))) {
fn(-1UL, data);
@@ -1221,7 +1221,7 @@ static bool add_new_range(struct dm_integrity_c *ic, struct dm_integrity_range *
struct rb_node **n = &ic->in_progress.rb_node;
struct rb_node *parent;
- BUG_ON((new_range->logical_sector | new_range->n_sectors) & (unsigned)(ic->sectors_per_block - 1));
+ BUG_ON((new_range->logical_sector | new_range->n_sectors) & (unsigned int)(ic->sectors_per_block - 1));
if (likely(check_waiting)) {
struct dm_integrity_range *range;
@@ -1339,10 +1339,10 @@ static void remove_journal_node(struct dm_integrity_c *ic, struct journal_node *
#define NOT_FOUND (-1U)
-static unsigned find_journal_node(struct dm_integrity_c *ic, sector_t sector, sector_t *next_sector)
+static unsigned int find_journal_node(struct dm_integrity_c *ic, sector_t sector, sector_t *next_sector)
{
struct rb_node *n = ic->journal_tree_root.rb_node;
- unsigned found = NOT_FOUND;
+ unsigned int found = NOT_FOUND;
*next_sector = (sector_t)-1;
while (n) {
struct journal_node *j = container_of(n, struct journal_node, node);
@@ -1360,7 +1360,7 @@ static unsigned find_journal_node(struct dm_integrity_c *ic, sector_t sector, se
return found;
}
-static bool test_journal_node(struct dm_integrity_c *ic, unsigned pos, sector_t sector)
+static bool test_journal_node(struct dm_integrity_c *ic, unsigned int pos, sector_t sector)
{
struct journal_node *node, *next_node;
struct rb_node *next;
@@ -1385,7 +1385,7 @@ static bool find_newer_committed_node(struct dm_integrity_c *ic, struct journal_
{
struct rb_node *next;
struct journal_node *next_node;
- unsigned next_section;
+ unsigned int next_section;
BUG_ON(RB_EMPTY_NODE(&node->node));
@@ -1398,7 +1398,7 @@ static bool find_newer_committed_node(struct dm_integrity_c *ic, struct journal_
if (next_node->sector != node->sector)
return false;
- next_section = (unsigned)(next_node - ic->journal_tree) / ic->journal_section_entries;
+ next_section = (unsigned int)(next_node - ic->journal_tree) / ic->journal_section_entries;
if (next_section >= ic->committed_section &&
next_section < ic->committed_section + ic->n_committed_sections)
return true;
@@ -1413,17 +1413,17 @@ static bool find_newer_committed_node(struct dm_integrity_c *ic, struct journal_
#define TAG_CMP 2
static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, sector_t *metadata_block,
- unsigned *metadata_offset, unsigned total_size, int op)
+ unsigned int *metadata_offset, unsigned int total_size, int op)
{
#define MAY_BE_FILLER 1
#define MAY_BE_HASH 2
- unsigned hash_offset = 0;
- unsigned may_be = MAY_BE_HASH | (ic->discard ? MAY_BE_FILLER : 0);
+ unsigned int hash_offset = 0;
+ unsigned int may_be = MAY_BE_HASH | (ic->discard ? MAY_BE_FILLER : 0);
do {
unsigned char *data, *dp;
struct dm_buffer *b;
- unsigned to_copy;
+ unsigned int to_copy;
int r;
r = dm_integrity_failed(ic);
@@ -1453,7 +1453,7 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se
goto thorough_test;
}
} else {
- unsigned i, ts;
+ unsigned int i, ts;
thorough_test:
ts = total_size;
@@ -1652,7 +1652,7 @@ static void integrity_sector_checksum(struct dm_integrity_c *ic, sector_t sector
__le64 sector_le = cpu_to_le64(sector);
SHASH_DESC_ON_STACK(req, ic->internal_hash);
int r;
- unsigned digest_size;
+ unsigned int digest_size;
req->tfm = ic->internal_hash;
@@ -1709,13 +1709,13 @@ static void integrity_metadata(struct work_struct *w)
if (ic->internal_hash) {
struct bvec_iter iter;
struct bio_vec bv;
- unsigned digest_size = crypto_shash_digestsize(ic->internal_hash);
+ unsigned int digest_size = crypto_shash_digestsize(ic->internal_hash);
struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
char *checksums;
- unsigned extra_space = unlikely(digest_size > ic->tag_size) ? digest_size - ic->tag_size : 0;
+ unsigned int extra_space = unlikely(digest_size > ic->tag_size) ? digest_size - ic->tag_size : 0;
char checksums_onstack[max((size_t)HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
sector_t sector;
- unsigned sectors_to_process;
+ unsigned int sectors_to_process;
if (unlikely(ic->mode == 'R'))
goto skip_io;
@@ -1735,14 +1735,13 @@ static void integrity_metadata(struct work_struct *w)
}
if (unlikely(dio->op == REQ_OP_DISCARD)) {
- sector_t bi_sector = dio->bio_details.bi_iter.bi_sector;
- unsigned bi_size = dio->bio_details.bi_iter.bi_size;
- unsigned max_size = likely(checksums != checksums_onstack) ? PAGE_SIZE : HASH_MAX_DIGESTSIZE;
- unsigned max_blocks = max_size / ic->tag_size;
+ unsigned int bi_size = dio->bio_details.bi_iter.bi_size;
+ unsigned int max_size = likely(checksums != checksums_onstack) ? PAGE_SIZE : HASH_MAX_DIGESTSIZE;
+ unsigned int max_blocks = max_size / ic->tag_size;
memset(checksums, DISCARD_FILLER, max_size);
while (bi_size) {
- unsigned this_step_blocks = bi_size >> (SECTOR_SHIFT + ic->sb->log2_sectors_per_block);
+ unsigned int this_step_blocks = bi_size >> (SECTOR_SHIFT + ic->sb->log2_sectors_per_block);
this_step_blocks = min(this_step_blocks, max_blocks);
r = dm_integrity_rw_tag(ic, checksums, &dio->metadata_block, &dio->metadata_offset,
this_step_blocks * ic->tag_size, TAG_WRITE);
@@ -1752,13 +1751,7 @@ static void integrity_metadata(struct work_struct *w)
goto error;
}
- /*if (bi_size < this_step_blocks << (SECTOR_SHIFT + ic->sb->log2_sectors_per_block)) {
- printk("BUGG: bi_sector: %llx, bi_size: %u\n", bi_sector, bi_size);
- printk("BUGG: this_step_blocks: %u\n", this_step_blocks);
- BUG();
- }*/
bi_size -= this_step_blocks << (SECTOR_SHIFT + ic->sb->log2_sectors_per_block);
- bi_sector += this_step_blocks << ic->sb->log2_sectors_per_block;
}
if (likely(checksums != checksums_onstack))
@@ -1770,7 +1763,7 @@ static void integrity_metadata(struct work_struct *w)
sectors_to_process = dio->range.n_sectors;
__bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) {
- unsigned pos;
+ unsigned int pos;
char *mem, *checksums_ptr;
again:
@@ -1823,13 +1816,13 @@ static void integrity_metadata(struct work_struct *w)
if (bip) {
struct bio_vec biv;
struct bvec_iter iter;
- unsigned data_to_process = dio->range.n_sectors;
+ unsigned int data_to_process = dio->range.n_sectors;
sector_to_block(ic, data_to_process);
data_to_process *= ic->tag_size;
bip_for_each_vec(biv, bip, iter) {
unsigned char *tag;
- unsigned this_len;
+ unsigned int this_len;
BUG_ON(PageHighMem(biv.bv_page));
tag = bvec_virt(&biv);
@@ -1867,7 +1860,7 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
if (unlikely(dio->op == REQ_OP_DISCARD)) {
if (ti->max_io_len) {
sector_t sec = dm_target_offset(ti, bio->bi_iter.bi_sector);
- unsigned log2_max_io_len = __fls(ti->max_io_len);
+ unsigned int log2_max_io_len = __fls(ti->max_io_len);
sector_t start_boundary = sec >> log2_max_io_len;
sector_t end_boundary = (sec + bio_sectors(bio) - 1) >> log2_max_io_len;
if (start_boundary < end_boundary) {
@@ -1897,7 +1890,7 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
ic->provided_data_sectors);
return DM_MAPIO_KILL;
}
- if (unlikely((dio->range.logical_sector | bio_sectors(bio)) & (unsigned)(ic->sectors_per_block - 1))) {
+ if (unlikely((dio->range.logical_sector | bio_sectors(bio)) & (unsigned int)(ic->sectors_per_block - 1))) {
DMERR("Bio not aligned on %u sectors: 0x%llx, 0x%x",
ic->sectors_per_block,
dio->range.logical_sector, bio_sectors(bio));
@@ -1919,7 +1912,7 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
bip = bio_integrity(bio);
if (!ic->internal_hash) {
if (bip) {
- unsigned wanted_tag_size = bio_sectors(bio) >> ic->sb->log2_sectors_per_block;
+ unsigned int wanted_tag_size = bio_sectors(bio) >> ic->sb->log2_sectors_per_block;
if (ic->log2_tag_size >= 0)
wanted_tag_size <<= ic->log2_tag_size;
else
@@ -1949,11 +1942,11 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
}
static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
- unsigned journal_section, unsigned journal_entry)
+ unsigned int journal_section, unsigned int journal_entry)
{
struct dm_integrity_c *ic = dio->ic;
sector_t logical_sector;
- unsigned n_sectors;
+ unsigned int n_sectors;
logical_sector = dio->range.logical_sector;
n_sectors = dio->range.n_sectors;
@@ -1976,7 +1969,7 @@ static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
if (unlikely(dio->op == REQ_OP_READ)) {
struct journal_sector *js;
char *mem_ptr;
- unsigned s;
+ unsigned int s;
if (unlikely(journal_entry_is_inprogress(je))) {
flush_dcache_page(bv.bv_page);
@@ -2013,12 +2006,12 @@ static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
if (!ic->internal_hash) {
struct bio_integrity_payload *bip = bio_integrity(bio);
- unsigned tag_todo = ic->tag_size;
+ unsigned int tag_todo = ic->tag_size;
char *tag_ptr = journal_entry_tag(ic, je);
if (bip) do {
struct bio_vec biv = bvec_iter_bvec(bip->bip_vec, bip->bip_iter);
- unsigned tag_now = min(biv.bv_len, tag_todo);
+ unsigned int tag_now = min(biv.bv_len, tag_todo);
char *tag_addr;
BUG_ON(PageHighMem(biv.bv_page));
tag_addr = bvec_virt(&biv);
@@ -2037,7 +2030,7 @@ static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
if (likely(dio->op == REQ_OP_WRITE)) {
struct journal_sector *js;
- unsigned s;
+ unsigned int s;
js = access_journal_data(ic, journal_section, journal_entry);
memcpy(js, mem + bv.bv_offset, ic->sectors_per_block << SECTOR_SHIFT);
@@ -2048,7 +2041,7 @@ static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
} while (++s < ic->sectors_per_block);
if (ic->internal_hash) {
- unsigned digest_size = crypto_shash_digestsize(ic->internal_hash);
+ unsigned int digest_size = crypto_shash_digestsize(ic->internal_hash);
if (unlikely(digest_size > ic->tag_size)) {
char checksums_onstack[HASH_MAX_DIGESTSIZE];
integrity_sector_checksum(ic, logical_sector, (char *)js, checksums_onstack);
@@ -2105,8 +2098,8 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
{
struct dm_integrity_c *ic = dio->ic;
struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
- unsigned journal_section, journal_entry;
- unsigned journal_read_pos;
+ unsigned int journal_section, journal_entry;
+ unsigned int journal_read_pos;
struct completion read_comp;
bool discard_retried = false;
bool need_sync_io = ic->internal_hash && dio->op == REQ_OP_READ;
@@ -2131,8 +2124,8 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
journal_read_pos = NOT_FOUND;
if (ic->mode == 'J' && likely(dio->op != REQ_OP_DISCARD)) {
if (dio->op == REQ_OP_WRITE) {
- unsigned next_entry, i, pos;
- unsigned ws, we, range_sectors;
+ unsigned int next_entry, i, pos;
+ unsigned int ws, we, range_sectors;
dio->range.n_sectors = min(dio->range.n_sectors,
(sector_t)ic->free_sectors << ic->sb->log2_sectors_per_block);
@@ -2185,8 +2178,8 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
if (unlikely(dio->range.n_sectors > next_sector - dio->range.logical_sector))
dio->range.n_sectors = next_sector - dio->range.logical_sector;
} else {
- unsigned i;
- unsigned jp = journal_read_pos + 1;
+ unsigned int i;
+ unsigned int jp = journal_read_pos + 1;
for (i = ic->sectors_per_block; i < dio->range.n_sectors; i += ic->sectors_per_block, jp++) {
if (!test_journal_node(ic, jp, dio->range.logical_sector + i))
break;
@@ -2218,7 +2211,7 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
*/
if (journal_read_pos != NOT_FOUND) {
sector_t next_sector;
- unsigned new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
+ unsigned int new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
if (unlikely(new_pos != journal_read_pos)) {
remove_range_unlocked(ic, &dio->range);
goto retry;
@@ -2227,7 +2220,7 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
}
if (ic->mode == 'J' && likely(dio->op == REQ_OP_DISCARD) && !discard_retried) {
sector_t next_sector;
- unsigned new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
+ unsigned int new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
if (unlikely(new_pos != NOT_FOUND) ||
unlikely(next_sector < dio->range.logical_sector - dio->range.n_sectors)) {
remove_range_unlocked(ic, &dio->range);
@@ -2354,8 +2347,8 @@ static void pad_uncommitted(struct dm_integrity_c *ic)
static void integrity_commit(struct work_struct *w)
{
struct dm_integrity_c *ic = container_of(w, struct dm_integrity_c, commit_work);
- unsigned commit_start, commit_sections;
- unsigned i, j, n;
+ unsigned int commit_start, commit_sections;
+ unsigned int i, j, n;
struct bio *flushes;
del_timer(&ic->autocommit_timer);
@@ -2433,17 +2426,17 @@ static void complete_copy_from_journal(unsigned long error, void *context)
static void restore_last_bytes(struct dm_integrity_c *ic, struct journal_sector *js,
struct journal_entry *je)
{
- unsigned s = 0;
+ unsigned int s = 0;
do {
js->commit_id = je->last_bytes[s];
js++;
} while (++s < ic->sectors_per_block);
}
-static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
- unsigned write_sections, bool from_replay)
+static void do_journal_write(struct dm_integrity_c *ic, unsigned int write_start,
+ unsigned int write_sections, bool from_replay)
{
- unsigned i, j, n;
+ unsigned int i, j, n;
struct journal_completion comp;
struct blk_plug plug;
@@ -2462,9 +2455,9 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
for (j = 0; j < ic->journal_section_entries; j++) {
struct journal_entry *je = access_journal_entry(ic, i, j);
sector_t sec, area, offset;
- unsigned k, l, next_loop;
+ unsigned int k, l, next_loop;
sector_t metadata_block;
- unsigned metadata_offset;
+ unsigned int metadata_offset;
struct journal_io *io;
if (journal_entry_is_unused(je))
@@ -2472,7 +2465,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
BUG_ON(unlikely(journal_entry_is_inprogress(je)) && !from_replay);
sec = journal_entry_get_sector(je);
if (unlikely(from_replay)) {
- if (unlikely(sec & (unsigned)(ic->sectors_per_block - 1))) {
+ if (unlikely(sec & (unsigned int)(ic->sectors_per_block - 1))) {
dm_integrity_io_error(ic, "invalid sector in journal", -EIO);
sec &= ~(sector_t)(ic->sectors_per_block - 1);
}
@@ -2590,9 +2583,9 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
static void integrity_writer(struct work_struct *w)
{
struct dm_integrity_c *ic = container_of(w, struct dm_integrity_c, writer_work);
- unsigned write_start, write_sections;
+ unsigned int write_start, write_sections;
- unsigned prev_free_sectors;
+ unsigned int prev_free_sectors;
spin_lock_irq(&ic->endio_wait.lock);
write_start = ic->committed_section;
@@ -2639,12 +2632,12 @@ static void integrity_recalc(struct work_struct *w)
struct dm_io_region io_loc;
sector_t area, offset;
sector_t metadata_block;
- unsigned metadata_offset;
+ unsigned int metadata_offset;
sector_t logical_sector, n_sectors;
__u8 *t;
- unsigned i;
+ unsigned int i;
int r;
- unsigned super_counter = 0;
+ unsigned int super_counter = 0;
DEBUG_print("start recalculation... (position %llx)\n", le64_to_cpu(ic->sb->recalc_sector));
@@ -2668,7 +2661,7 @@ static void integrity_recalc(struct work_struct *w)
get_area_and_offset(ic, range.logical_sector, &area, &offset);
range.n_sectors = min((sector_t)RECALC_SECTORS, ic->provided_data_sectors - range.logical_sector);
if (!ic->meta_dev)
- range.n_sectors = min(range.n_sectors, ((sector_t)1U << ic->sb->log2_interleave_sectors) - (unsigned)offset);
+ range.n_sectors = min(range.n_sectors, ((sector_t)1U << ic->sb->log2_interleave_sectors) - (unsigned int)offset);
add_new_range_and_wait(ic, &range);
spin_unlock_irq(&ic->endio_wait.lock);
@@ -2859,10 +2852,10 @@ static void bitmap_flush_work(struct work_struct *work)
}
-static void init_journal(struct dm_integrity_c *ic, unsigned start_section,
- unsigned n_sections, unsigned char commit_seq)
+static void init_journal(struct dm_integrity_c *ic, unsigned int start_section,
+ unsigned int n_sections, unsigned char commit_seq)
{
- unsigned i, j, n;
+ unsigned int i, j, n;
if (!n_sections)
return;
@@ -2885,7 +2878,7 @@ static void init_journal(struct dm_integrity_c *ic, unsigned start_section,
write_journal(ic, start_section, n_sections);
}
-static int find_commit_seq(struct dm_integrity_c *ic, unsigned i, unsigned j, commit_id_t id)
+static int find_commit_seq(struct dm_integrity_c *ic, unsigned int i, unsigned int j, commit_id_t id)
{
unsigned char k;
for (k = 0; k < N_COMMIT_IDS; k++) {
@@ -2898,11 +2891,11 @@ static int find_commit_seq(struct dm_integrity_c *ic, unsigned i, unsigned j, co
static void replay_journal(struct dm_integrity_c *ic)
{
- unsigned i, j;
+ unsigned int i, j;
bool used_commit_ids[N_COMMIT_IDS];
- unsigned max_commit_id_sections[N_COMMIT_IDS];
- unsigned write_start, write_sections;
- unsigned continue_section;
+ unsigned int max_commit_id_sections[N_COMMIT_IDS];
+ unsigned int write_start, write_sections;
+ unsigned int continue_section;
bool journal_empty;
unsigned char unused, last_used, want_commit_seq;
@@ -3020,7 +3013,7 @@ static void replay_journal(struct dm_integrity_c *ic)
ic->commit_seq = want_commit_seq;
DEBUG_print("continuing from section %u, commit seq %d\n", write_start, ic->commit_seq);
} else {
- unsigned s;
+ unsigned int s;
unsigned char erase_seq;
clear_journal:
DEBUG_print("clearing journal\n");
@@ -3252,10 +3245,10 @@ static void dm_integrity_resume(struct dm_target *ti)
}
static void dm_integrity_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct dm_integrity_c *ic = (struct dm_integrity_c *)ti->private;
- unsigned arg_count;
+ unsigned int arg_count;
size_t sz = 0;
switch (type) {
@@ -3305,7 +3298,7 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors);
DMEMIT(" buffer_sectors:%u", 1U << ic->log2_buffer_sectors);
if (ic->mode == 'J') {
- DMEMIT(" journal_watermark:%u", (unsigned)watermark_percentage);
+ DMEMIT(" journal_watermark:%u", (unsigned int)watermark_percentage);
DMEMIT(" commit_time:%u", ic->autocommit_msec);
}
if (ic->mode == 'B') {
@@ -3384,7 +3377,7 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
static void calculate_journal_section_size(struct dm_integrity_c *ic)
{
- unsigned sector_space = JOURNAL_SECTOR_DATA;
+ unsigned int sector_space = JOURNAL_SECTOR_DATA;
ic->journal_sections = le32_to_cpu(ic->sb->journal_sections);
ic->journal_entry_size = roundup(offsetof(struct journal_entry, last_bytes[ic->sectors_per_block]) + ic->tag_size,
@@ -3461,9 +3454,10 @@ static void get_provided_data_sectors(struct dm_integrity_c *ic)
}
}
-static int initialize_superblock(struct dm_integrity_c *ic, unsigned journal_sectors, unsigned interleave_sectors)
+static int initialize_superblock(struct dm_integrity_c *ic,
+ unsigned int journal_sectors, unsigned int interleave_sectors)
{
- unsigned journal_sections;
+ unsigned int journal_sections;
int test_bit;
memset(ic->sb, 0, SB_SECTORS << SECTOR_SHIFT);
@@ -3548,7 +3542,7 @@ static void dm_integrity_set(struct dm_target *ti, struct dm_integrity_c *ic)
static void dm_integrity_free_page_list(struct page_list *pl)
{
- unsigned i;
+ unsigned int i;
if (!pl)
return;
@@ -3557,10 +3551,10 @@ static void dm_integrity_free_page_list(struct page_list *pl)
kvfree(pl);
}
-static struct page_list *dm_integrity_alloc_page_list(unsigned n_pages)
+static struct page_list *dm_integrity_alloc_page_list(unsigned int n_pages)
{
struct page_list *pl;
- unsigned i;
+ unsigned int i;
pl = kvmalloc_array(n_pages + 1, sizeof(struct page_list), GFP_KERNEL | __GFP_ZERO);
if (!pl)
@@ -3583,7 +3577,7 @@ static struct page_list *dm_integrity_alloc_page_list(unsigned n_pages)
static void dm_integrity_free_journal_scatterlist(struct dm_integrity_c *ic, struct scatterlist **sl)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < ic->journal_sections; i++)
kvfree(sl[i]);
kvfree(sl);
@@ -3593,7 +3587,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
struct page_list *pl)
{
struct scatterlist **sl;
- unsigned i;
+ unsigned int i;
sl = kvmalloc_array(ic->journal_sections,
sizeof(struct scatterlist *),
@@ -3603,10 +3597,10 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
for (i = 0; i < ic->journal_sections; i++) {
struct scatterlist *s;
- unsigned start_index, start_offset;
- unsigned end_index, end_offset;
- unsigned n_pages;
- unsigned idx;
+ unsigned int start_index, start_offset;
+ unsigned int end_index, end_offset;
+ unsigned int n_pages;
+ unsigned int idx;
page_list_location(ic, i, 0, &start_index, &start_offset);
page_list_location(ic, i, ic->journal_section_sectors - 1,
@@ -3624,7 +3618,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
sg_init_table(s, n_pages);
for (idx = start_index; idx <= end_index; idx++) {
char *va = lowmem_page_address(pl[idx].page);
- unsigned start = 0, end = PAGE_SIZE;
+ unsigned int start = 0, end = PAGE_SIZE;
if (idx == start_index)
start = start_offset;
if (idx == end_index)
@@ -3711,7 +3705,7 @@ static int get_mac(struct crypto_shash **hash, struct alg_spec *a, char **error,
static int create_journal(struct dm_integrity_c *ic, char **error)
{
int r = 0;
- unsigned i;
+ unsigned int i;
__u64 journal_pages, journal_desc_size, journal_tree_size;
unsigned char *crypt_data = NULL, *crypt_iv = NULL;
struct skcipher_request *req = NULL;
@@ -3738,7 +3732,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
goto bad;
}
if (ic->journal_crypt_alg.alg_string) {
- unsigned ivsize, blocksize;
+ unsigned int ivsize, blocksize;
struct journal_completion comp;
comp.ic = ic;
@@ -3827,7 +3821,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
crypto_free_skcipher(ic->journal_crypt);
ic->journal_crypt = NULL;
} else {
- unsigned crypt_len = roundup(ivsize, blocksize);
+ unsigned int crypt_len = roundup(ivsize, blocksize);
req = skcipher_request_alloc(ic->journal_crypt, GFP_KERNEL);
if (!req) {
@@ -3915,7 +3909,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
}
for (i = 0; i < N_COMMIT_IDS; i++) {
- unsigned j;
+ unsigned int j;
retest_commit_id:
for (j = 0; j < i; j++) {
if (ic->commit_ids[j] == ic->commit_ids[i]) {
@@ -3969,17 +3963,17 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
* journal_mac
* recalculate
*/
-static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct dm_integrity_c *ic;
char dummy;
int r;
- unsigned extra_args;
+ unsigned int extra_args;
struct dm_arg_set as;
static const struct dm_arg _args[] = {
{0, 18, "Invalid number of feature args"},
};
- unsigned journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec;
+ unsigned int journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec;
bool should_write_sb;
__u64 threshold;
unsigned long long start;
@@ -4058,7 +4052,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
while (extra_args--) {
const char *opt_string;
- unsigned val;
+ unsigned int val;
unsigned long long llval;
opt_string = dm_shift_arg(&as);
if (!opt_string) {
@@ -4391,7 +4385,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
DEBUG_print(" journal_entries_per_sector %u\n", ic->journal_entries_per_sector);
DEBUG_print(" journal_section_entries %u\n", ic->journal_section_entries);
DEBUG_print(" journal_section_sectors %u\n", ic->journal_section_sectors);
- DEBUG_print(" journal_sections %u\n", (unsigned)le32_to_cpu(ic->sb->journal_sections));
+ DEBUG_print(" journal_sections %u\n", (unsigned int)le32_to_cpu(ic->sb->journal_sections));
DEBUG_print(" journal_entries %u\n", ic->journal_entries);
DEBUG_print(" log2_interleave_sectors %d\n", ic->sb->log2_interleave_sectors);
DEBUG_print(" data_device_sectors 0x%llx\n", bdev_nr_sectors(ic->dev->bdev));
@@ -4465,8 +4459,8 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
}
if (ic->mode == 'B') {
- unsigned i;
- unsigned n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
+ unsigned int i;
+ unsigned int n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
ic->recalc_bitmap = dm_integrity_alloc_page_list(n_bitmap_pages);
if (!ic->recalc_bitmap) {
@@ -4486,7 +4480,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
INIT_DELAYED_WORK(&ic->bitmap_flush_work, bitmap_flush_work);
for (i = 0; i < ic->n_bitmap_blocks; i++) {
struct bitmap_block_status *bbs = &ic->bbs[i];
- unsigned sector, pl_index, pl_offset;
+ unsigned int sector, pl_index, pl_offset;
INIT_WORK(&bbs->work, bitmap_block_work);
bbs->ic = ic;
@@ -4523,7 +4517,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto bad;
}
if (ic->mode == 'B') {
- unsigned max_io_len = ((sector_t)ic->sectors_per_block << ic->log2_blocks_per_bitmap_bit) * (BITMAP_BLOCK_SIZE * 8);
+ unsigned int max_io_len = ((sector_t)ic->sectors_per_block << ic->log2_blocks_per_bitmap_bit) * (BITMAP_BLOCK_SIZE * 8);
if (!max_io_len)
max_io_len = 1U << 31;
DEBUG_print("max_io_len: old %u, new %u\n", ti->max_io_len, max_io_len);
@@ -4594,7 +4588,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
if (ic->journal_io_scatterlist)
dm_integrity_free_journal_scatterlist(ic, ic->journal_io_scatterlist);
if (ic->sk_requests) {
- unsigned i;
+ unsigned int i;
for (i = 0; i < ic->journal_sections; i++) {
struct skcipher_request *req = ic->sk_requests[i];
diff --git a/drivers/md/dm-io-rewind.c b/drivers/md/dm-io-rewind.c
index 0db53ccb94ba..773c4cff8b89 100644
--- a/drivers/md/dm-io-rewind.c
+++ b/drivers/md/dm-io-rewind.c
@@ -57,7 +57,7 @@ static void dm_bio_integrity_rewind(struct bio *bio, unsigned int bytes_done)
{
struct bio_integrity_payload *bip = bio_integrity(bio);
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
- unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
+ unsigned int bytes = bio_integrity_bytes(bi, bytes_done >> 9);
bip->bip_iter.bi_sector -= bio_integrity_intervals(bi, bytes_done >> 9);
dm_bvec_iter_rewind(bip->bip_vec, &bip->bip_iter, bytes);
@@ -131,7 +131,7 @@ static inline void dm_bio_rewind_iter(const struct bio *bio,
* rewinding from end of bio and restoring its original position.
* Caller is also responsibile for restoring bio's size.
*/
-static void dm_bio_rewind(struct bio *bio, unsigned bytes)
+static void dm_bio_rewind(struct bio *bio, unsigned int bytes)
{
if (bio_integrity(bio))
dm_bio_integrity_rewind(bio, bytes);
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 783564533459..e488b05e35fa 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -48,7 +48,7 @@ static struct kmem_cache *_dm_io_cache;
struct dm_io_client *dm_io_client_create(void)
{
struct dm_io_client *client;
- unsigned min_ios = dm_get_reserved_bio_based_ios();
+ unsigned int min_ios = dm_get_reserved_bio_based_ios();
int ret;
client = kzalloc(sizeof(*client), GFP_KERNEL);
@@ -88,7 +88,7 @@ EXPORT_SYMBOL(dm_io_client_destroy);
* bi_private.
*---------------------------------------------------------------*/
static void store_io_and_region_in_bio(struct bio *bio, struct io *io,
- unsigned region)
+ unsigned int region)
{
if (unlikely(!IS_ALIGNED((unsigned long)io, DM_IO_MAX_REGIONS))) {
DMCRIT("Unaligned struct io pointer %p", io);
@@ -99,7 +99,7 @@ static void store_io_and_region_in_bio(struct bio *bio, struct io *io,
}
static void retrieve_io_and_region_from_bio(struct bio *bio, struct io **io,
- unsigned *region)
+ unsigned int *region)
{
unsigned long val = (unsigned long)bio->bi_private;
@@ -137,7 +137,7 @@ static void dec_count(struct io *io, unsigned int region, blk_status_t error)
static void endio(struct bio *bio)
{
struct io *io;
- unsigned region;
+ unsigned int region;
blk_status_t error;
if (bio->bi_status && bio_data_dir(bio) == READ)
@@ -160,11 +160,11 @@ static void endio(struct bio *bio)
*---------------------------------------------------------------*/
struct dpages {
void (*get_page)(struct dpages *dp,
- struct page **p, unsigned long *len, unsigned *offset);
+ struct page **p, unsigned long *len, unsigned int *offset);
void (*next_page)(struct dpages *dp);
union {
- unsigned context_u;
+ unsigned int context_u;
struct bvec_iter context_bi;
};
void *context_ptr;
@@ -177,9 +177,9 @@ struct dpages {
* Functions for getting the pages from a list.
*/
static void list_get_page(struct dpages *dp,
- struct page **p, unsigned long *len, unsigned *offset)
+ struct page **p, unsigned long *len, unsigned int *offset)
{
- unsigned o = dp->context_u;
+ unsigned int o = dp->context_u;
struct page_list *pl = (struct page_list *) dp->context_ptr;
*p = pl->page;
@@ -194,7 +194,7 @@ static void list_next_page(struct dpages *dp)
dp->context_u = 0;
}
-static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offset)
+static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned int offset)
{
dp->get_page = list_get_page;
dp->next_page = list_next_page;
@@ -206,7 +206,7 @@ static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offse
* Functions for getting the pages from a bvec.
*/
static void bio_get_page(struct dpages *dp, struct page **p,
- unsigned long *len, unsigned *offset)
+ unsigned long *len, unsigned int *offset)
{
struct bio_vec bvec = bvec_iter_bvec((struct bio_vec *)dp->context_ptr,
dp->context_bi);
@@ -244,7 +244,7 @@ static void bio_dp_init(struct dpages *dp, struct bio *bio)
* Functions for getting the pages from a VMA.
*/
static void vm_get_page(struct dpages *dp,
- struct page **p, unsigned long *len, unsigned *offset)
+ struct page **p, unsigned long *len, unsigned int *offset)
{
*p = vmalloc_to_page(dp->context_ptr);
*offset = dp->context_u;
@@ -269,7 +269,7 @@ static void vm_dp_init(struct dpages *dp, void *data)
* Functions for getting the pages from kernel memory.
*/
static void km_get_page(struct dpages *dp, struct page **p, unsigned long *len,
- unsigned *offset)
+ unsigned int *offset)
{
*p = virt_to_page(dp->context_ptr);
*offset = dp->context_u;
@@ -293,15 +293,15 @@ static void km_dp_init(struct dpages *dp, void *data)
/*-----------------------------------------------------------------
* IO routines that accept a list of pages.
*---------------------------------------------------------------*/
-static void do_region(const blk_opf_t opf, unsigned region,
+static void do_region(const blk_opf_t opf, unsigned int region,
struct dm_io_region *where, struct dpages *dp,
struct io *io)
{
struct bio *bio;
struct page *page;
unsigned long len;
- unsigned offset;
- unsigned num_bvecs;
+ unsigned int offset;
+ unsigned int num_bvecs;
sector_t remaining = where->count;
struct request_queue *q = bdev_get_queue(where->bdev);
sector_t num_sectors;
@@ -508,7 +508,7 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp,
return 0;
}
-int dm_io(struct dm_io_request *io_req, unsigned num_regions,
+int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
struct dm_io_region *where, unsigned long *sync_error_bits)
{
int r;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index e031088ff15c..37f5ea7337cc 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -31,7 +31,7 @@ struct dm_file {
* poll will wait until the global event number is greater than
* this value.
*/
- volatile unsigned global_event_nr;
+ volatile unsigned int global_event_nr;
};
/*-----------------------------------------------------------------
@@ -413,7 +413,7 @@ static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
struct hash_cell *hc;
struct dm_table *table;
struct mapped_device *md;
- unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
+ unsigned int change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
int srcu_idx;
/*
@@ -1021,7 +1021,7 @@ static int dev_rename(struct file *filp, struct dm_ioctl *param, size_t param_si
int r;
char *new_data = (char *) param + param->data_start;
struct mapped_device *md;
- unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
+ unsigned int change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
if (new_data < param->data ||
invalid_str(new_data, (void *) param + param_size) || !*new_data ||
@@ -1096,7 +1096,7 @@ static int dev_set_geometry(struct file *filp, struct dm_ioctl *param, size_t pa
static int do_suspend(struct dm_ioctl *param)
{
int r = 0;
- unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
+ unsigned int suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
struct mapped_device *md;
md = find_device(param);
@@ -1125,7 +1125,7 @@ static int do_suspend(struct dm_ioctl *param)
static int do_resume(struct dm_ioctl *param)
{
int r = 0;
- unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
+ unsigned int suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
struct hash_cell *hc;
struct mapped_device *md;
struct dm_table *new_map, *old_map = NULL;
@@ -1243,7 +1243,7 @@ static void retrieve_status(struct dm_table *table,
char *outbuf, *outptr;
status_type_t type;
size_t remaining, len, used = 0;
- unsigned status_flags = 0;
+ unsigned int status_flags = 0;
outptr = outbuf = get_result_buffer(param, param_size, &len);
@@ -1648,8 +1648,8 @@ static int table_status(struct file *filp, struct dm_ioctl *param, size_t param_
* Returns a number <= 1 if message was processed by device mapper.
* Returns 2 if message should be delivered to the target.
*/
-static int message_for_md(struct mapped_device *md, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int message_for_md(struct mapped_device *md, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r;
@@ -1859,7 +1859,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
struct dm_ioctl *dmi;
int secure_data;
const size_t minimum_data_size = offsetof(struct dm_ioctl, data);
- unsigned noio_flag;
+ unsigned int noio_flag;
if (copy_from_user(param_kernel, user, minimum_data_size))
return -EFAULT;
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 4d3bbbea2e9a..0ef78e56aa88 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -34,14 +34,14 @@
#define DEFAULT_SUB_JOB_SIZE_KB 512
#define MAX_SUB_JOB_SIZE_KB 1024
-static unsigned kcopyd_subjob_size_kb = DEFAULT_SUB_JOB_SIZE_KB;
+static unsigned int kcopyd_subjob_size_kb = DEFAULT_SUB_JOB_SIZE_KB;
module_param(kcopyd_subjob_size_kb, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(kcopyd_subjob_size_kb, "Sub-job size for dm-kcopyd clients");
-static unsigned dm_get_kcopyd_subjob_size(void)
+static unsigned int dm_get_kcopyd_subjob_size(void)
{
- unsigned sub_job_size_kb;
+ unsigned int sub_job_size_kb;
sub_job_size_kb = __dm_get_module_param(&kcopyd_subjob_size_kb,
DEFAULT_SUB_JOB_SIZE_KB,
@@ -56,9 +56,9 @@ static unsigned dm_get_kcopyd_subjob_size(void)
*---------------------------------------------------------------*/
struct dm_kcopyd_client {
struct page_list *pages;
- unsigned nr_reserved_pages;
- unsigned nr_free_pages;
- unsigned sub_job_size;
+ unsigned int nr_reserved_pages;
+ unsigned int nr_free_pages;
+ unsigned int sub_job_size;
struct dm_io_client *io_client;
@@ -119,7 +119,7 @@ static DEFINE_SPINLOCK(throttle_spinlock);
static void io_job_start(struct dm_kcopyd_throttle *t)
{
- unsigned throttle, now, difference;
+ unsigned int throttle, now, difference;
int slept = 0, skew;
if (unlikely(!t))
@@ -182,7 +182,7 @@ static void io_job_finish(struct dm_kcopyd_throttle *t)
goto skip_limit;
if (!t->num_io_jobs) {
- unsigned now, difference;
+ unsigned int now, difference;
now = jiffies;
difference = now - t->last_jiffies;
@@ -303,9 +303,9 @@ static void drop_pages(struct page_list *pl)
/*
* Allocate and reserve nr_pages for the use of a specific client.
*/
-static int client_reserve_pages(struct dm_kcopyd_client *kc, unsigned nr_pages)
+static int client_reserve_pages(struct dm_kcopyd_client *kc, unsigned int nr_pages)
{
- unsigned i;
+ unsigned int i;
struct page_list *pl = NULL, *next;
for (i = 0; i < nr_pages; i++) {
@@ -341,7 +341,7 @@ static void client_free_pages(struct dm_kcopyd_client *kc)
struct kcopyd_job {
struct dm_kcopyd_client *kc;
struct list_head list;
- unsigned flags;
+ unsigned int flags;
/*
* Error state of the job.
@@ -582,7 +582,7 @@ static int run_io_job(struct kcopyd_job *job)
static int run_pages_job(struct kcopyd_job *job)
{
int r;
- unsigned nr_pages = dm_div_up(job->dests[0].count, PAGE_SIZE >> 9);
+ unsigned int nr_pages = dm_div_up(job->dests[0].count, PAGE_SIZE >> 9);
r = kcopyd_get_pages(job->kc, nr_pages, &job->pages);
if (!r) {
@@ -849,8 +849,8 @@ void dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
EXPORT_SYMBOL(dm_kcopyd_copy);
void dm_kcopyd_zero(struct dm_kcopyd_client *kc,
- unsigned num_dests, struct dm_io_region *dests,
- unsigned flags, dm_kcopyd_notify_fn fn, void *context)
+ unsigned int num_dests, struct dm_io_region *dests,
+ unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
{
dm_kcopyd_copy(kc, NULL, num_dests, dests, flags, fn, context);
}
@@ -906,7 +906,7 @@ int kcopyd_cancel(struct kcopyd_job *job, int block)
struct dm_kcopyd_client *dm_kcopyd_client_create(struct dm_kcopyd_throttle *throttle)
{
int r;
- unsigned reserve_pages;
+ unsigned int reserve_pages;
struct dm_kcopyd_client *kc;
kc = kzalloc(sizeof(*kc), GFP_KERNEL);
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 3212ef6aa81b..26b1af646177 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -95,7 +95,7 @@ static int linear_map(struct dm_target *ti, struct bio *bio)
}
static void linear_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct linear_c *lc = (struct linear_c *) ti->private;
size_t sz = 0;
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c
index 9ab93ebea889..9fc69382692b 100644
--- a/drivers/md/dm-log-userspace-base.c
+++ b/drivers/md/dm-log-userspace-base.c
@@ -123,7 +123,7 @@ static int userspace_do_request(struct log_c *lc, const char *uuid,
}
static int build_constructor_string(struct dm_target *ti,
- unsigned argc, char **argv,
+ unsigned int argc, char **argv,
char **ctr_str)
{
int i, str_size;
@@ -188,7 +188,7 @@ static void do_flush(struct work_struct *work)
* to the userspace ctr function.
*/
static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
int r = 0;
int str_size;
@@ -792,7 +792,7 @@ static region_t userspace_get_sync_count(struct dm_dirty_log *log)
* Returns: amount of space consumed
*/
static int userspace_status(struct dm_dirty_log *log, status_type_t status_type,
- char *result, unsigned maxlen)
+ char *result, unsigned int maxlen)
{
int r = 0;
char *table_args;
diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c
index fdf8ec304f8d..072559b709ed 100644
--- a/drivers/md/dm-log-userspace-transfer.c
+++ b/drivers/md/dm-log-userspace-transfer.c
@@ -142,7 +142,7 @@ static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
fill_pkg(msg, NULL);
else if (msg->len < sizeof(*tfr))
DMERR("Incomplete message received (expected %u, got %u): [%u]",
- (unsigned)sizeof(*tfr), msg->len, msg->seq);
+ (unsigned int)sizeof(*tfr), msg->len, msg->seq);
else
fill_pkg(NULL, tfr);
spin_unlock(&receiving_list_lock);
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index 178e13a5b059..efdfb2e1868a 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -792,10 +792,10 @@ static int normal_end_io(struct dm_target *ti, struct bio *bio,
* INFO format: <logged entries> <highest allocated sector>
*/
static void log_writes_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result,
- unsigned maxlen)
+ unsigned int status_flags, char *result,
+ unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct log_writes_c *lc = ti->private;
switch (type) {
@@ -844,8 +844,8 @@ static int log_writes_iterate_devices(struct dm_target *ti,
* Messages supported:
* mark <mark data> - specify the marked data.
*/
-static int log_writes_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int log_writes_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r = -EINVAL;
struct log_writes_c *lc = ti->private;
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index cf10fa667797..159f2c05dfd3 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -223,7 +223,7 @@ struct log_c {
unsigned int region_count;
region_t sync_count;
- unsigned bitset_uint32_count;
+ unsigned int bitset_uint32_count;
uint32_t *clean_bits;
uint32_t *sync_bits;
uint32_t *recovering_bits; /* FIXME: this seems excessive */
@@ -255,20 +255,20 @@ struct log_c {
* The touched member needs to be updated every time we access
* one of the bitsets.
*/
-static inline int log_test_bit(uint32_t *bs, unsigned bit)
+static inline int log_test_bit(uint32_t *bs, unsigned int bit)
{
return test_bit_le(bit, bs) ? 1 : 0;
}
static inline void log_set_bit(struct log_c *l,
- uint32_t *bs, unsigned bit)
+ uint32_t *bs, unsigned int bit)
{
__set_bit_le(bit, bs);
l->touched_cleaned = 1;
}
static inline void log_clear_bit(struct log_c *l,
- uint32_t *bs, unsigned bit)
+ uint32_t *bs, unsigned int bit)
{
__clear_bit_le(bit, bs);
l->touched_dirtied = 1;
@@ -582,7 +582,7 @@ static void fail_log_device(struct log_c *lc)
static int disk_resume(struct dm_dirty_log *log)
{
int r;
- unsigned i;
+ unsigned int i;
struct log_c *lc = (struct log_c *) log->context;
size_t size = lc->bitset_uint32_count * sizeof(uint32_t);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 0e325469a252..91c25ad8eed8 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -29,7 +29,7 @@
#define DM_MSG_PREFIX "multipath"
#define DM_PG_INIT_DELAY_MSECS 2000
-#define DM_PG_INIT_DELAY_DEFAULT ((unsigned) -1)
+#define DM_PG_INIT_DELAY_DEFAULT ((unsigned int) -1)
#define QUEUE_IF_NO_PATH_TIMEOUT_DEFAULT 0
static unsigned long queue_if_no_path_timeout_secs = QUEUE_IF_NO_PATH_TIMEOUT_DEFAULT;
@@ -39,7 +39,7 @@ struct pgpath {
struct list_head list;
struct priority_group *pg; /* Owning PG */
- unsigned fail_count; /* Cumulative failure count */
+ unsigned int fail_count; /* Cumulative failure count */
struct dm_path path;
struct delayed_work activate_path;
@@ -59,8 +59,8 @@ struct priority_group {
struct multipath *m; /* Owning multipath instance */
struct path_selector ps;
- unsigned pg_num; /* Reference number */
- unsigned nr_pgpaths; /* Number of paths in PG */
+ unsigned int pg_num; /* Reference number */
+ unsigned int nr_pgpaths; /* Number of paths in PG */
struct list_head pgpaths;
bool bypassed:1; /* Temporarily bypass this PG? */
@@ -78,14 +78,14 @@ struct multipath {
struct priority_group *next_pg; /* Switch to this PG if set */
atomic_t nr_valid_paths; /* Total number of usable paths */
- unsigned nr_priority_groups;
+ unsigned int nr_priority_groups;
struct list_head priority_groups;
const char *hw_handler_name;
char *hw_handler_params;
wait_queue_head_t pg_init_wait; /* Wait for pg_init completion */
- unsigned pg_init_retries; /* Number of times to retry pg_init */
- unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */
+ unsigned int pg_init_retries; /* Number of times to retry pg_init */
+ unsigned int pg_init_delay_msecs; /* Number of msecs before pg_init retry */
atomic_t pg_init_in_progress; /* Only one pg_init allowed at once */
atomic_t pg_init_count; /* Number of times pg_init called */
@@ -397,7 +397,7 @@ static struct pgpath *choose_pgpath(struct multipath *m, size_t nr_bytes)
unsigned long flags;
struct priority_group *pg;
struct pgpath *pgpath;
- unsigned bypassed = 1;
+ unsigned int bypassed = 1;
if (!atomic_read(&m->nr_valid_paths)) {
spin_lock_irqsave(&m->lock, flags);
@@ -840,7 +840,7 @@ static int parse_path_selector(struct dm_arg_set *as, struct priority_group *pg,
{
int r;
struct path_selector_type *pst;
- unsigned ps_argc;
+ unsigned int ps_argc;
static const struct dm_arg _args[] = {
{0, 1024, "invalid number of path selector args"},
@@ -983,7 +983,7 @@ static struct priority_group *parse_priority_group(struct dm_arg_set *as,
};
int r;
- unsigned i, nr_selector_args, nr_args;
+ unsigned int i, nr_selector_args, nr_args;
struct priority_group *pg;
struct dm_target *ti = m->ti;
@@ -1049,7 +1049,7 @@ static struct priority_group *parse_priority_group(struct dm_arg_set *as,
static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m)
{
- unsigned hw_argc;
+ unsigned int hw_argc;
int ret;
struct dm_target *ti = m->ti;
@@ -1101,7 +1101,7 @@ static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m)
static int parse_features(struct dm_arg_set *as, struct multipath *m)
{
int r;
- unsigned argc;
+ unsigned int argc;
struct dm_target *ti = m->ti;
const char *arg_name;
@@ -1170,7 +1170,7 @@ static int parse_features(struct dm_arg_set *as, struct multipath *m)
return r;
}
-static int multipath_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int multipath_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
/* target arguments */
static const struct dm_arg _args[] = {
@@ -1181,8 +1181,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned argc, char **argv)
int r;
struct multipath *m;
struct dm_arg_set as;
- unsigned pg_count = 0;
- unsigned next_pg_num;
+ unsigned int pg_count = 0;
+ unsigned int next_pg_num;
unsigned long flags;
as.argc = argc;
@@ -1224,7 +1224,7 @@ static int multipath_ctr(struct dm_target *ti, unsigned argc, char **argv)
/* parse the priority groups */
while (as.argc) {
struct priority_group *pg;
- unsigned nr_valid_paths = atomic_read(&m->nr_valid_paths);
+ unsigned int nr_valid_paths = atomic_read(&m->nr_valid_paths);
pg = parse_priority_group(&as, m);
if (IS_ERR(pg)) {
@@ -1365,7 +1365,7 @@ static int reinstate_path(struct pgpath *pgpath)
int r = 0, run_queue = 0;
unsigned long flags;
struct multipath *m = pgpath->pg->m;
- unsigned nr_valid_paths;
+ unsigned int nr_valid_paths;
spin_lock_irqsave(&m->lock, flags);
@@ -1454,7 +1454,7 @@ static void bypass_pg(struct multipath *m, struct priority_group *pg,
static int switch_pg_num(struct multipath *m, const char *pgstr)
{
struct priority_group *pg;
- unsigned pgnum;
+ unsigned int pgnum;
unsigned long flags;
char dummy;
@@ -1487,7 +1487,7 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
static int bypass_pg_num(struct multipath *m, const char *pgstr, bool bypassed)
{
struct priority_group *pg;
- unsigned pgnum;
+ unsigned int pgnum;
char dummy;
if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
@@ -1789,14 +1789,14 @@ static void multipath_resume(struct dm_target *ti)
* num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
*/
static void multipath_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int sz = 0, pg_counter, pgpath_counter;
unsigned long flags;
struct multipath *m = ti->private;
struct priority_group *pg;
struct pgpath *p;
- unsigned pg_num;
+ unsigned int pg_num;
char state;
spin_lock_irqsave(&m->lock, flags);
@@ -1948,8 +1948,8 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
spin_unlock_irqrestore(&m->lock, flags);
}
-static int multipath_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int multipath_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r = -EINVAL;
struct dm_dev *dev;
diff --git a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h
index e230f7196259..5343698fe5f1 100644
--- a/drivers/md/dm-mpath.h
+++ b/drivers/md/dm-mpath.h
@@ -17,6 +17,6 @@ struct dm_path {
};
/* Callback for hwh_pg_init_fn to use when complete */
-void dm_pg_init_complete(struct dm_path *path, unsigned err_flags);
+void dm_pg_init_complete(struct dm_path *path, unsigned int err_flags);
#endif
diff --git a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h
index 83cac2b04b66..0f2b37af8766 100644
--- a/drivers/md/dm-path-selector.h
+++ b/drivers/md/dm-path-selector.h
@@ -52,7 +52,7 @@ struct path_selector_type {
/*
* Constructs a path selector object, takes custom arguments
*/
- int (*create) (struct path_selector *ps, unsigned argc, char **argv);
+ int (*create) (struct path_selector *ps, unsigned int argc, char **argv);
void (*destroy) (struct path_selector *ps);
/*
diff --git a/drivers/md/dm-ps-io-affinity.c b/drivers/md/dm-ps-io-affinity.c
index f74501e65a8e..76ce4ce87222 100644
--- a/drivers/md/dm-ps-io-affinity.c
+++ b/drivers/md/dm-ps-io-affinity.c
@@ -108,7 +108,7 @@ static int ioa_add_path(struct path_selector *ps, struct dm_path *path,
return ret;
}
-static int ioa_create(struct path_selector *ps, unsigned argc, char **argv)
+static int ioa_create(struct path_selector *ps, unsigned int argc, char **argv)
{
struct selector *s;
@@ -138,7 +138,7 @@ static int ioa_create(struct path_selector *ps, unsigned argc, char **argv)
static void ioa_destroy(struct path_selector *ps)
{
struct selector *s = ps->context;
- unsigned cpu;
+ unsigned int cpu;
for_each_cpu(cpu, s->path_mask)
ioa_free_path(s, cpu);
diff --git a/drivers/md/dm-ps-queue-length.c b/drivers/md/dm-ps-queue-length.c
index cef70657bbbc..6fbec9fc242d 100644
--- a/drivers/md/dm-ps-queue-length.c
+++ b/drivers/md/dm-ps-queue-length.c
@@ -35,7 +35,7 @@ struct selector {
struct path_info {
struct list_head list;
struct dm_path *path;
- unsigned repeat_count;
+ unsigned int repeat_count;
atomic_t qlen; /* the number of in-flight I/Os */
};
@@ -52,7 +52,7 @@ static struct selector *alloc_selector(void)
return s;
}
-static int ql_create(struct path_selector *ps, unsigned argc, char **argv)
+static int ql_create(struct path_selector *ps, unsigned int argc, char **argv)
{
struct selector *s = alloc_selector();
@@ -84,9 +84,9 @@ static void ql_destroy(struct path_selector *ps)
}
static int ql_status(struct path_selector *ps, struct dm_path *path,
- status_type_t type, char *result, unsigned maxlen)
+ status_type_t type, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct path_info *pi;
/* When called with NULL path, return selector status/args. */
@@ -116,7 +116,7 @@ static int ql_add_path(struct path_selector *ps, struct dm_path *path,
{
struct selector *s = ps->context;
struct path_info *pi;
- unsigned repeat_count = QL_MIN_IO;
+ unsigned int repeat_count = QL_MIN_IO;
char dummy;
unsigned long flags;
diff --git a/drivers/md/dm-ps-round-robin.c b/drivers/md/dm-ps-round-robin.c
index 27f44c5fa04e..1d07392b5ed4 100644
--- a/drivers/md/dm-ps-round-robin.c
+++ b/drivers/md/dm-ps-round-robin.c
@@ -26,7 +26,7 @@
struct path_info {
struct list_head list;
struct dm_path *path;
- unsigned repeat_count;
+ unsigned int repeat_count;
};
static void free_paths(struct list_head *paths)
@@ -62,7 +62,7 @@ static struct selector *alloc_selector(void)
return s;
}
-static int rr_create(struct path_selector *ps, unsigned argc, char **argv)
+static int rr_create(struct path_selector *ps, unsigned int argc, char **argv)
{
struct selector *s;
@@ -119,7 +119,7 @@ static int rr_add_path(struct path_selector *ps, struct dm_path *path,
{
struct selector *s = ps->context;
struct path_info *pi;
- unsigned repeat_count = RR_MIN_IO;
+ unsigned int repeat_count = RR_MIN_IO;
char dummy;
unsigned long flags;
diff --git a/drivers/md/dm-ps-service-time.c b/drivers/md/dm-ps-service-time.c
index 3ec9c33265c5..84d26234dc05 100644
--- a/drivers/md/dm-ps-service-time.c
+++ b/drivers/md/dm-ps-service-time.c
@@ -30,8 +30,8 @@ struct selector {
struct path_info {
struct list_head list;
struct dm_path *path;
- unsigned repeat_count;
- unsigned relative_throughput;
+ unsigned int repeat_count;
+ unsigned int relative_throughput;
atomic_t in_flight_size; /* Total size of in-flight I/Os */
};
@@ -48,7 +48,7 @@ static struct selector *alloc_selector(void)
return s;
}
-static int st_create(struct path_selector *ps, unsigned argc, char **argv)
+static int st_create(struct path_selector *ps, unsigned int argc, char **argv)
{
struct selector *s = alloc_selector();
@@ -80,9 +80,9 @@ static void st_destroy(struct path_selector *ps)
}
static int st_status(struct path_selector *ps, struct dm_path *path,
- status_type_t type, char *result, unsigned maxlen)
+ status_type_t type, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct path_info *pi;
if (!path)
@@ -113,8 +113,8 @@ static int st_add_path(struct path_selector *ps, struct dm_path *path,
{
struct selector *s = ps->context;
struct path_info *pi;
- unsigned repeat_count = ST_MIN_IO;
- unsigned relative_throughput = 1;
+ unsigned int repeat_count = ST_MIN_IO;
+ unsigned int relative_throughput = 1;
char dummy;
unsigned long flags;
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 54263679a7b1..b26c12856b1d 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3712,7 +3712,7 @@ static void raid_status(struct dm_target *ti, status_type_t type,
}
static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
- char *result, unsigned maxlen)
+ char *result, unsigned int maxlen)
{
struct raid_set *rs = ti->private;
struct mddev *mddev = &rs->md;
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 06a38dc32025..8bd7e87d3538 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -82,7 +82,7 @@ struct mirror_set {
struct work_struct trigger_event;
- unsigned nr_mirrors;
+ unsigned int nr_mirrors;
struct mirror mirror[];
};
@@ -327,7 +327,7 @@ static void recovery_complete(int read_err, unsigned long write_err,
static void recover(struct mirror_set *ms, struct dm_region *reg)
{
- unsigned i;
+ unsigned int i;
struct dm_io_region from, to[DM_KCOPYD_MAX_REGIONS], *dest;
struct mirror *m;
unsigned long flags = 0;
@@ -593,7 +593,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
static void write_callback(unsigned long error, void *context)
{
- unsigned i;
+ unsigned int i;
struct bio *bio = (struct bio *) context;
struct mirror_set *ms;
int should_wake = 0;
@@ -963,10 +963,10 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
* Create dirty log: log_type #log_params <log_params>
*/
static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
- unsigned argc, char **argv,
- unsigned *args_used)
+ unsigned int argc, char **argv,
+ unsigned int *args_used)
{
- unsigned param_count;
+ unsigned int param_count;
struct dm_dirty_log *dl;
char dummy;
@@ -997,10 +997,10 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
return dl;
}
-static int parse_features(struct mirror_set *ms, unsigned argc, char **argv,
- unsigned *args_used)
+static int parse_features(struct mirror_set *ms, unsigned int argc, char **argv,
+ unsigned int *args_used)
{
- unsigned num_features;
+ unsigned int num_features;
struct dm_target *ti = ms->ti;
char dummy;
int i;
@@ -1389,7 +1389,7 @@ static char device_status_char(struct mirror *m)
static void mirror_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
unsigned int m, sz = 0;
int num_feature_args = 0;
@@ -1458,7 +1458,7 @@ static int mirror_iterate_devices(struct dm_target *ti,
{
struct mirror_set *ms = ti->private;
int ret = 0;
- unsigned i;
+ unsigned int i;
for (i = 0; !ret && i < ms->nr_mirrors; i++)
ret = fn(ti, ms->mirror[i].dev,
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index 1f760451e6f4..adbdb4b67137 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -56,17 +56,17 @@
*---------------------------------------------------------------*/
struct dm_region_hash {
uint32_t region_size;
- unsigned region_shift;
+ unsigned int region_shift;
/* holds persistent region state */
struct dm_dirty_log *log;
/* hash table */
rwlock_t hash_lock;
- unsigned mask;
- unsigned nr_buckets;
- unsigned prime;
- unsigned shift;
+ unsigned int mask;
+ unsigned int nr_buckets;
+ unsigned int prime;
+ unsigned int shift;
struct list_head *buckets;
/*
@@ -74,7 +74,7 @@ struct dm_region_hash {
*/
int flush_failure;
- unsigned max_recovery; /* Max # of regions to recover in parallel */
+ unsigned int max_recovery; /* Max # of regions to recover in parallel */
spinlock_t region_lock;
atomic_t recovery_in_flight;
@@ -163,12 +163,12 @@ struct dm_region_hash *dm_region_hash_create(
struct bio_list *bios),
void (*wakeup_workers)(void *context),
void (*wakeup_all_recovery_waiters)(void *context),
- sector_t target_begin, unsigned max_recovery,
+ sector_t target_begin, unsigned int max_recovery,
struct dm_dirty_log *log, uint32_t region_size,
region_t nr_regions)
{
struct dm_region_hash *rh;
- unsigned nr_buckets, max_buckets;
+ unsigned int nr_buckets, max_buckets;
size_t i;
int ret;
@@ -236,7 +236,7 @@ EXPORT_SYMBOL_GPL(dm_region_hash_create);
void dm_region_hash_destroy(struct dm_region_hash *rh)
{
- unsigned h;
+ unsigned int h;
struct dm_region *reg, *nreg;
BUG_ON(!list_empty(&rh->quiesced_regions));
@@ -263,9 +263,9 @@ struct dm_dirty_log *dm_rh_dirty_log(struct dm_region_hash *rh)
}
EXPORT_SYMBOL_GPL(dm_rh_dirty_log);
-static unsigned rh_hash(struct dm_region_hash *rh, region_t region)
+static unsigned int rh_hash(struct dm_region_hash *rh, region_t region)
{
- return (unsigned) ((region * rh->prime) >> rh->shift) & rh->mask;
+ return (unsigned int) ((region * rh->prime) >> rh->shift) & rh->mask;
}
static struct dm_region *__rh_lookup(struct dm_region_hash *rh, region_t region)
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index a41209a43506..80f46e01bca4 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -23,33 +23,33 @@ struct dm_rq_target_io {
union map_info info;
struct dm_stats_aux stats_aux;
unsigned long duration_jiffies;
- unsigned n_sectors;
- unsigned completed;
+ unsigned int n_sectors;
+ unsigned int completed;
};
#define DM_MQ_NR_HW_QUEUES 1
#define DM_MQ_QUEUE_DEPTH 2048
-static unsigned dm_mq_nr_hw_queues = DM_MQ_NR_HW_QUEUES;
-static unsigned dm_mq_queue_depth = DM_MQ_QUEUE_DEPTH;
+static unsigned int dm_mq_nr_hw_queues = DM_MQ_NR_HW_QUEUES;
+static unsigned int dm_mq_queue_depth = DM_MQ_QUEUE_DEPTH;
/*
* Request-based DM's mempools' reserved IOs set by the user.
*/
#define RESERVED_REQUEST_BASED_IOS 256
-static unsigned reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS;
+static unsigned int reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS;
-unsigned dm_get_reserved_rq_based_ios(void)
+unsigned int dm_get_reserved_rq_based_ios(void)
{
return __dm_get_module_param(&reserved_rq_based_ios,
RESERVED_REQUEST_BASED_IOS, DM_RESERVED_MAX_IOS);
}
-static unsigned dm_get_blk_mq_nr_hw_queues(void)
+static unsigned int dm_get_blk_mq_nr_hw_queues(void)
{
return __dm_get_module_param(&dm_mq_nr_hw_queues, 1, 32);
}
-static unsigned dm_get_blk_mq_queue_depth(void)
+static unsigned int dm_get_blk_mq_queue_depth(void)
{
return __dm_get_module_param(&dm_mq_queue_depth,
DM_MQ_QUEUE_DEPTH, BLK_MQ_MAX_DEPTH);
diff --git a/drivers/md/dm-rq.h b/drivers/md/dm-rq.h
index 1eea0da641db..2c97ad145140 100644
--- a/drivers/md/dm-rq.h
+++ b/drivers/md/dm-rq.h
@@ -38,7 +38,7 @@ void dm_stop_queue(struct request_queue *q);
void dm_mq_kick_requeue_list(struct mapped_device *md);
-unsigned dm_get_reserved_rq_based_ios(void);
+unsigned int dm_get_reserved_rq_based_ios(void);
ssize_t dm_attr_rq_based_seq_io_merge_deadline_show(struct mapped_device *md, char *buf);
ssize_t dm_attr_rq_based_seq_io_merge_deadline_store(struct mapped_device *md,
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index 680cc05ec654..5176810f5d24 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -303,7 +303,7 @@ static int read_header(struct pstore *ps, int *new_snapshot)
{
int r;
struct disk_header *dh;
- unsigned chunk_size;
+ unsigned int chunk_size;
int chunk_size_supplied = 1;
char *chunk_err;
@@ -895,11 +895,11 @@ static int persistent_ctr(struct dm_exception_store *store, char *options)
return r;
}
-static unsigned persistent_status(struct dm_exception_store *store,
+static unsigned int persistent_status(struct dm_exception_store *store,
status_type_t status, char *result,
- unsigned maxlen)
+ unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
switch (status) {
case STATUSTYPE_INFO:
diff --git a/drivers/md/dm-snap-transient.c b/drivers/md/dm-snap-transient.c
index 0e0ae4c36b37..d83a0565bd10 100644
--- a/drivers/md/dm-snap-transient.c
+++ b/drivers/md/dm-snap-transient.c
@@ -84,11 +84,11 @@ static int transient_ctr(struct dm_exception_store *store, char *options)
return 0;
}
-static unsigned transient_status(struct dm_exception_store *store,
+static unsigned int transient_status(struct dm_exception_store *store,
status_type_t status, char *result,
- unsigned maxlen)
+ unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
switch (status) {
case STATUSTYPE_INFO:
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index d1c2f84d27e3..c64d987c544d 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -41,7 +41,7 @@ static const char dm_snapshot_merge_target_name[] = "snapshot-merge";
struct dm_exception_table {
uint32_t hash_mask;
- unsigned hash_shift;
+ unsigned int hash_shift;
struct hlist_bl_head *table;
};
@@ -106,7 +106,7 @@ struct dm_snapshot {
/* The on disk metadata handler */
struct dm_exception_store *store;
- unsigned in_progress;
+ unsigned int in_progress;
struct wait_queue_head in_progress_wait;
struct dm_kcopyd_client *kcopyd_client;
@@ -161,7 +161,7 @@ struct dm_snapshot {
*/
#define DEFAULT_COW_THRESHOLD 2048
-static unsigned cow_threshold = DEFAULT_COW_THRESHOLD;
+static unsigned int cow_threshold = DEFAULT_COW_THRESHOLD;
module_param_named(snapshot_cow_threshold, cow_threshold, uint, 0644);
MODULE_PARM_DESC(snapshot_cow_threshold, "Maximum number of chunks being copied on write");
@@ -324,7 +324,7 @@ struct origin {
struct dm_origin {
struct dm_dev *dev;
struct dm_target *ti;
- unsigned split_boundary;
+ unsigned int split_boundary;
struct list_head hash_list;
};
@@ -377,7 +377,7 @@ static void exit_origin_hash(void)
kfree(_dm_origins);
}
-static unsigned origin_hash(struct block_device *bdev)
+static unsigned int origin_hash(struct block_device *bdev)
{
return bdev->bd_dev & ORIGIN_MASK;
}
@@ -652,7 +652,7 @@ static void dm_exception_table_unlock(struct dm_exception_table_lock *lock)
}
static int dm_exception_table_init(struct dm_exception_table *et,
- uint32_t size, unsigned hash_shift)
+ uint32_t size, unsigned int hash_shift)
{
unsigned int i;
@@ -850,7 +850,7 @@ static int dm_add_exception(void *context, chunk_t old, chunk_t new)
static uint32_t __minimum_chunk_size(struct origin *o)
{
struct dm_snapshot *snap;
- unsigned chunk_size = rounddown_pow_of_two(UINT_MAX);
+ unsigned int chunk_size = rounddown_pow_of_two(UINT_MAX);
if (o)
list_for_each_entry(snap, &o->snapshots, list)
@@ -1010,7 +1010,7 @@ static int remove_single_exception_chunk(struct dm_snapshot *s)
}
static int origin_write_extent(struct dm_snapshot *merging_snap,
- sector_t sector, unsigned chunk_size);
+ sector_t sector, unsigned int chunk_size);
static void merge_callback(int read_err, unsigned long write_err,
void *context);
@@ -1183,7 +1183,7 @@ static int parse_snapshot_features(struct dm_arg_set *as, struct dm_snapshot *s,
struct dm_target *ti)
{
int r;
- unsigned argc;
+ unsigned int argc;
const char *arg_name;
static const struct dm_arg _args[] = {
@@ -1241,7 +1241,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
int r = -EINVAL;
char *origin_path, *cow_path;
dev_t origin_dev, cow_dev;
- unsigned args_used, num_flush_bios = 1;
+ unsigned int args_used, num_flush_bios = 1;
fmode_t origin_mode = FMODE_READ;
if (argc < 4) {
@@ -2315,11 +2315,11 @@ static void snapshot_merge_resume(struct dm_target *ti)
}
static void snapshot_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct dm_snapshot *snap = ti->private;
- unsigned num_features;
+ unsigned int num_features;
switch (type) {
case STATUSTYPE_INFO:
@@ -2592,7 +2592,7 @@ static int do_origin(struct dm_dev *origin, struct bio *bio, bool limit)
* size must be a multiple of merging_snap's chunk_size.
*/
static int origin_write_extent(struct dm_snapshot *merging_snap,
- sector_t sector, unsigned size)
+ sector_t sector, unsigned int size)
{
int must_wait = 0;
sector_t n;
@@ -2668,7 +2668,7 @@ static void origin_dtr(struct dm_target *ti)
static int origin_map(struct dm_target *ti, struct bio *bio)
{
struct dm_origin *o = ti->private;
- unsigned available_sectors;
+ unsigned int available_sectors;
bio_set_dev(bio, o->dev->bdev);
@@ -2679,7 +2679,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio)
return DM_MAPIO_REMAPPED;
available_sectors = o->split_boundary -
- ((unsigned)bio->bi_iter.bi_sector & (o->split_boundary - 1));
+ ((unsigned int)bio->bi_iter.bi_sector & (o->split_boundary - 1));
if (bio_sectors(bio) > available_sectors)
dm_accept_partial_bio(bio, available_sectors);
@@ -2713,7 +2713,7 @@ static void origin_postsuspend(struct dm_target *ti)
}
static void origin_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct dm_origin *o = ti->private;
diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c
index d12ba9bce145..7eeb3c2a2492 100644
--- a/drivers/md/dm-stats.c
+++ b/drivers/md/dm-stats.c
@@ -42,12 +42,12 @@ struct dm_stat_shared {
struct dm_stat {
struct list_head list_entry;
int id;
- unsigned stat_flags;
+ unsigned int stat_flags;
size_t n_entries;
sector_t start;
sector_t end;
sector_t step;
- unsigned n_histogram_entries;
+ unsigned int n_histogram_entries;
unsigned long long *histogram_boundaries;
const char *program_id;
const char *aux_data;
@@ -63,7 +63,7 @@ struct dm_stat {
struct dm_stats_last_position {
sector_t last_sector;
- unsigned last_rw;
+ unsigned int last_rw;
};
/*
@@ -255,8 +255,8 @@ static void dm_stats_recalc_precise_timestamps(struct dm_stats *stats)
}
static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end,
- sector_t step, unsigned stat_flags,
- unsigned n_histogram_entries,
+ sector_t step, unsigned int stat_flags,
+ unsigned int n_histogram_entries,
unsigned long long *histogram_boundaries,
const char *program_id, const char *aux_data,
void (*suspend_callback)(struct mapped_device *),
@@ -475,11 +475,11 @@ static int dm_stats_delete(struct dm_stats *stats, int id)
}
static int dm_stats_list(struct dm_stats *stats, const char *program,
- char *result, unsigned maxlen)
+ char *result, unsigned int maxlen)
{
struct dm_stat *s;
sector_t len;
- unsigned sz = 0;
+ unsigned int sz = 0;
/*
* Output format:
@@ -499,7 +499,7 @@ static int dm_stats_list(struct dm_stats *stats, const char *program,
if (s->stat_flags & STAT_PRECISE_TIMESTAMPS)
DMEMIT(" precise_timestamps");
if (s->n_histogram_entries) {
- unsigned i;
+ unsigned int i;
DMEMIT(" histogram:");
for (i = 0; i < s->n_histogram_entries; i++) {
if (i)
@@ -523,7 +523,7 @@ static void dm_stat_round(struct dm_stat *s, struct dm_stat_shared *shared,
* This is racy, but so is part_round_stats_single.
*/
unsigned long long now, difference;
- unsigned in_flight_read, in_flight_write;
+ unsigned int in_flight_read, in_flight_write;
if (likely(!(s->stat_flags & STAT_PRECISE_TIMESTAMPS)))
now = jiffies;
@@ -534,8 +534,8 @@ static void dm_stat_round(struct dm_stat *s, struct dm_stat_shared *shared,
if (!difference)
return;
- in_flight_read = (unsigned)atomic_read(&shared->in_flight[READ]);
- in_flight_write = (unsigned)atomic_read(&shared->in_flight[WRITE]);
+ in_flight_read = (unsigned int)atomic_read(&shared->in_flight[READ]);
+ in_flight_write = (unsigned int)atomic_read(&shared->in_flight[WRITE]);
if (in_flight_read)
p->io_ticks[READ] += difference;
if (in_flight_write)
@@ -596,9 +596,9 @@ static void dm_stat_for_entry(struct dm_stat *s, size_t entry,
duration = stats_aux->duration_ns;
}
if (s->n_histogram_entries) {
- unsigned lo = 0, hi = s->n_histogram_entries + 1;
+ unsigned int lo = 0, hi = s->n_histogram_entries + 1;
while (lo + 1 < hi) {
- unsigned mid = (lo + hi) / 2;
+ unsigned int mid = (lo + hi) / 2;
if (s->histogram_boundaries[mid - 1] > duration) {
hi = mid;
} else {
@@ -656,7 +656,7 @@ static void __dm_stat_bio(struct dm_stat *s, int bi_rw,
}
void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
- sector_t bi_sector, unsigned bi_sectors, bool end,
+ sector_t bi_sector, unsigned int bi_sectors, bool end,
unsigned long start_time,
struct dm_stats_aux *stats_aux)
{
@@ -745,7 +745,7 @@ static void __dm_stat_init_temporary_percpu_totals(struct dm_stat_shared *shared
shared->tmp.io_ticks_total += READ_ONCE(p->io_ticks_total);
shared->tmp.time_in_queue += READ_ONCE(p->time_in_queue);
if (s->n_histogram_entries) {
- unsigned i;
+ unsigned int i;
for (i = 0; i < s->n_histogram_entries + 1; i++)
shared->tmp.histogram[i] += READ_ONCE(p->histogram[i]);
}
@@ -779,7 +779,7 @@ static void __dm_stat_clear(struct dm_stat *s, size_t idx_start, size_t idx_end,
p->time_in_queue -= shared->tmp.time_in_queue;
local_irq_enable();
if (s->n_histogram_entries) {
- unsigned i;
+ unsigned int i;
for (i = 0; i < s->n_histogram_entries + 1; i++) {
local_irq_disable();
p = &s->stat_percpu[smp_processor_id()][x];
@@ -816,7 +816,7 @@ static int dm_stats_clear(struct dm_stats *stats, int id)
static unsigned long long dm_jiffies_to_msec64(struct dm_stat *s, unsigned long long j)
{
unsigned long long result;
- unsigned mult;
+ unsigned int mult;
if (s->stat_flags & STAT_PRECISE_TIMESTAMPS)
return j;
@@ -836,9 +836,9 @@ static unsigned long long dm_jiffies_to_msec64(struct dm_stat *s, unsigned long
static int dm_stats_print(struct dm_stats *stats, int id,
size_t idx_start, size_t idx_len,
- bool clear, char *result, unsigned maxlen)
+ bool clear, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct dm_stat *s;
size_t x;
sector_t start, end, step;
@@ -894,7 +894,7 @@ static int dm_stats_print(struct dm_stats *stats, int id,
dm_jiffies_to_msec64(s, shared->tmp.io_ticks[READ]),
dm_jiffies_to_msec64(s, shared->tmp.io_ticks[WRITE]));
if (s->n_histogram_entries) {
- unsigned i;
+ unsigned int i;
for (i = 0; i < s->n_histogram_entries + 1; i++) {
DMEMIT("%s%llu", !i ? " " : ":", shared->tmp.histogram[i]);
}
@@ -943,11 +943,11 @@ static int dm_stats_set_aux(struct dm_stats *stats, int id, const char *aux_data
return 0;
}
-static int parse_histogram(const char *h, unsigned *n_histogram_entries,
+static int parse_histogram(const char *h, unsigned int *n_histogram_entries,
unsigned long long **histogram_boundaries)
{
const char *q;
- unsigned n;
+ unsigned int n;
unsigned long long last;
*n_histogram_entries = 1;
@@ -982,23 +982,23 @@ static int parse_histogram(const char *h, unsigned *n_histogram_entries,
}
static int message_stats_create(struct mapped_device *md,
- unsigned argc, char **argv,
- char *result, unsigned maxlen)
+ unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r;
int id;
char dummy;
unsigned long long start, end, len, step;
- unsigned divisor;
+ unsigned int divisor;
const char *program_id, *aux_data;
- unsigned stat_flags = 0;
+ unsigned int stat_flags = 0;
- unsigned n_histogram_entries = 0;
+ unsigned int n_histogram_entries = 0;
unsigned long long *histogram_boundaries = NULL;
struct dm_arg_set as, as_backup;
const char *a;
- unsigned feature_args;
+ unsigned int feature_args;
/*
* Input format:
@@ -1107,7 +1107,7 @@ static int message_stats_create(struct mapped_device *md,
}
static int message_stats_delete(struct mapped_device *md,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
int id;
char dummy;
@@ -1122,7 +1122,7 @@ static int message_stats_delete(struct mapped_device *md,
}
static int message_stats_clear(struct mapped_device *md,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
int id;
char dummy;
@@ -1137,8 +1137,8 @@ static int message_stats_clear(struct mapped_device *md,
}
static int message_stats_list(struct mapped_device *md,
- unsigned argc, char **argv,
- char *result, unsigned maxlen)
+ unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r;
const char *program = NULL;
@@ -1160,8 +1160,8 @@ static int message_stats_list(struct mapped_device *md,
}
static int message_stats_print(struct mapped_device *md,
- unsigned argc, char **argv, bool clear,
- char *result, unsigned maxlen)
+ unsigned int argc, char **argv, bool clear,
+ char *result, unsigned int maxlen)
{
int id;
char dummy;
@@ -1187,7 +1187,7 @@ static int message_stats_print(struct mapped_device *md,
}
static int message_stats_set_aux(struct mapped_device *md,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
int id;
char dummy;
@@ -1201,8 +1201,8 @@ static int message_stats_set_aux(struct mapped_device *md,
return dm_stats_set_aux(dm_get_stats(md), id, argv[2]);
}
-int dm_stats_message(struct mapped_device *md, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+int dm_stats_message(struct mapped_device *md, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r;
diff --git a/drivers/md/dm-stats.h b/drivers/md/dm-stats.h
index ee32b099f1cf..c6728c8b4159 100644
--- a/drivers/md/dm-stats.h
+++ b/drivers/md/dm-stats.h
@@ -26,11 +26,11 @@ void dm_stats_cleanup(struct dm_stats *st);
struct mapped_device;
-int dm_stats_message(struct mapped_device *md, unsigned argc, char **argv,
- char *result, unsigned maxlen);
+int dm_stats_message(struct mapped_device *md, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen);
void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
- sector_t bi_sector, unsigned bi_sectors, bool end,
+ sector_t bi_sector, unsigned int bi_sectors, bool end,
unsigned long start_time,
struct dm_stats_aux *aux);
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index baa085cc67bd..a81ed080730a 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -273,7 +273,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio)
{
struct stripe_c *sc = ti->private;
uint32_t stripe;
- unsigned target_bio_nr;
+ unsigned int target_bio_nr;
if (bio->bi_opf & REQ_PREFLUSH) {
target_bio_nr = dm_bio_get_target_bio_nr(bio);
@@ -359,7 +359,7 @@ static size_t stripe_dax_recovery_write(struct dm_target *ti, pgoff_t pgoff,
*/
static void stripe_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct stripe_c *sc = (struct stripe_c *) ti->private;
unsigned int sz = 0;
@@ -406,7 +406,7 @@ static void stripe_status(struct dm_target *ti, status_type_t type,
static int stripe_end_io(struct dm_target *ti, struct bio *bio,
blk_status_t *error)
{
- unsigned i;
+ unsigned int i;
char major_minor[16];
struct stripe_c *sc = ti->private;
@@ -444,7 +444,7 @@ static int stripe_iterate_devices(struct dm_target *ti,
{
struct stripe_c *sc = ti->private;
int ret = 0;
- unsigned i = 0;
+ unsigned int i = 0;
do {
ret = fn(ti, sc->stripe[i].dev,
@@ -459,7 +459,7 @@ static void stripe_io_hints(struct dm_target *ti,
struct queue_limits *limits)
{
struct stripe_c *sc = ti->private;
- unsigned chunk_size = sc->chunk_size << SECTOR_SHIFT;
+ unsigned int chunk_size = sc->chunk_size << SECTOR_SHIFT;
blk_limits_io_min(limits, chunk_size);
blk_limits_io_opt(limits, chunk_size * sc->stripes);
diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c
index 534dc2ca8bb0..f734b5a09744 100644
--- a/drivers/md/dm-switch.c
+++ b/drivers/md/dm-switch.c
@@ -38,9 +38,9 @@ struct switch_path {
struct switch_ctx {
struct dm_target *ti;
- unsigned nr_paths; /* Number of paths in path_list. */
+ unsigned int nr_paths; /* Number of paths in path_list. */
- unsigned region_size; /* Region size in 512-byte sectors */
+ unsigned int region_size; /* Region size in 512-byte sectors */
unsigned long nr_regions; /* Number of regions making up the device */
signed char region_size_bits; /* log2 of region_size or -1 */
@@ -56,8 +56,8 @@ struct switch_ctx {
struct switch_path path_list[];
};
-static struct switch_ctx *alloc_switch_ctx(struct dm_target *ti, unsigned nr_paths,
- unsigned region_size)
+static struct switch_ctx *alloc_switch_ctx(struct dm_target *ti, unsigned int nr_paths,
+ unsigned int region_size)
{
struct switch_ctx *sctx;
@@ -73,7 +73,7 @@ static struct switch_ctx *alloc_switch_ctx(struct dm_target *ti, unsigned nr_pat
return sctx;
}
-static int alloc_region_table(struct dm_target *ti, unsigned nr_paths)
+static int alloc_region_table(struct dm_target *ti, unsigned int nr_paths)
{
struct switch_ctx *sctx = ti->private;
sector_t nr_regions = ti->len;
@@ -124,7 +124,7 @@ static int alloc_region_table(struct dm_target *ti, unsigned nr_paths)
}
static void switch_get_position(struct switch_ctx *sctx, unsigned long region_nr,
- unsigned long *region_index, unsigned *bit)
+ unsigned long *region_index, unsigned int *bit)
{
if (sctx->region_entries_per_slot_bits >= 0) {
*region_index = region_nr >> sctx->region_entries_per_slot_bits;
@@ -137,10 +137,10 @@ static void switch_get_position(struct switch_ctx *sctx, unsigned long region_nr
*bit *= sctx->region_table_entry_bits;
}
-static unsigned switch_region_table_read(struct switch_ctx *sctx, unsigned long region_nr)
+static unsigned int switch_region_table_read(struct switch_ctx *sctx, unsigned long region_nr)
{
unsigned long region_index;
- unsigned bit;
+ unsigned int bit;
switch_get_position(sctx, region_nr, ®ion_index, &bit);
@@ -151,9 +151,9 @@ static unsigned switch_region_table_read(struct switch_ctx *sctx, unsigned long
/*
* Find which path to use at given offset.
*/
-static unsigned switch_get_path_nr(struct switch_ctx *sctx, sector_t offset)
+static unsigned int switch_get_path_nr(struct switch_ctx *sctx, sector_t offset)
{
- unsigned path_nr;
+ unsigned int path_nr;
sector_t p;
p = offset;
@@ -172,10 +172,10 @@ static unsigned switch_get_path_nr(struct switch_ctx *sctx, sector_t offset)
}
static void switch_region_table_write(struct switch_ctx *sctx, unsigned long region_nr,
- unsigned value)
+ unsigned int value)
{
unsigned long region_index;
- unsigned bit;
+ unsigned int bit;
region_table_slot_t pte;
switch_get_position(sctx, region_nr, ®ion_index, &bit);
@@ -191,7 +191,7 @@ static void switch_region_table_write(struct switch_ctx *sctx, unsigned long reg
*/
static void initialise_region_table(struct switch_ctx *sctx)
{
- unsigned path_nr = 0;
+ unsigned int path_nr = 0;
unsigned long region_nr;
for (region_nr = 0; region_nr < sctx->nr_regions; region_nr++) {
@@ -249,7 +249,7 @@ static void switch_dtr(struct dm_target *ti)
* Optional args are to allow for future extension: currently this
* parameter must be 0.
*/
-static int switch_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int switch_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
static const struct dm_arg _args[] = {
{1, (KMALLOC_MAX_SIZE - sizeof(struct switch_ctx)) / sizeof(struct switch_path), "Invalid number of paths"},
@@ -259,7 +259,7 @@ static int switch_ctr(struct dm_target *ti, unsigned argc, char **argv)
struct switch_ctx *sctx;
struct dm_arg_set as;
- unsigned nr_paths, region_size, nr_optional_args;
+ unsigned int nr_paths, region_size, nr_optional_args;
int r;
as.argc = argc;
@@ -320,7 +320,7 @@ static int switch_map(struct dm_target *ti, struct bio *bio)
{
struct switch_ctx *sctx = ti->private;
sector_t offset = dm_target_offset(ti, bio->bi_iter.bi_sector);
- unsigned path_nr = switch_get_path_nr(sctx, offset);
+ unsigned int path_nr = switch_get_path_nr(sctx, offset);
bio_set_dev(bio, sctx->path_list[path_nr].dmdev->bdev);
bio->bi_iter.bi_sector = sctx->path_list[path_nr].start + offset;
@@ -371,9 +371,9 @@ static __always_inline unsigned long parse_hex(const char **string)
}
static int process_set_region_mappings(struct switch_ctx *sctx,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
- unsigned i;
+ unsigned int i;
unsigned long region_index = 0;
for (i = 1; i < argc; i++) {
@@ -466,8 +466,8 @@ static int process_set_region_mappings(struct switch_ctx *sctx,
*
* Only set_region_mappings is supported.
*/
-static int switch_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int switch_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
static DEFINE_MUTEX(message_mutex);
@@ -487,10 +487,10 @@ static int switch_message(struct dm_target *ti, unsigned argc, char **argv,
}
static void switch_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct switch_ctx *sctx = ti->private;
- unsigned sz = 0;
+ unsigned int sz = 0;
int path_nr;
switch (type) {
@@ -519,7 +519,7 @@ static void switch_status(struct dm_target *ti, status_type_t type,
static int switch_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
{
struct switch_ctx *sctx = ti->private;
- unsigned path_nr;
+ unsigned int path_nr;
path_nr = switch_get_path_nr(sctx, 0);
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 8541d5688f3a..c571f2385b57 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -126,7 +126,7 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
}
int dm_table_create(struct dm_table **result, fmode_t mode,
- unsigned num_targets, struct mapped_device *md)
+ unsigned int num_targets, struct mapped_device *md)
{
struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
@@ -470,10 +470,10 @@ static int adjoin(struct dm_table *t, struct dm_target *ti)
* On the other hand, dm-switch needs to process bulk data using messages and
* excessive use of GFP_NOIO could cause trouble.
*/
-static char **realloc_argv(unsigned *size, char **old_argv)
+static char **realloc_argv(unsigned int *size, char **old_argv)
{
char **argv;
- unsigned new_size;
+ unsigned int new_size;
gfp_t gfp;
if (*size) {
@@ -499,7 +499,7 @@ static char **realloc_argv(unsigned *size, char **old_argv)
int dm_split_args(int *argc, char ***argvp, char *input)
{
char *start, *end = input, *out, **argv = NULL;
- unsigned array_size = 0;
+ unsigned int array_size = 0;
*argc = 0;
@@ -732,9 +732,8 @@ int dm_table_add_target(struct dm_table *t, const char *type,
/*
* Target argument parsing helpers.
*/
-static int validate_next_arg(const struct dm_arg *arg,
- struct dm_arg_set *arg_set,
- unsigned *value, char **error, unsigned grouped)
+static int validate_next_arg(const struct dm_arg *arg, struct dm_arg_set *arg_set,
+ unsigned int *value, char **error, unsigned int grouped)
{
const char *arg_str = dm_shift_arg(arg_set);
char dummy;
@@ -752,14 +751,14 @@ static int validate_next_arg(const struct dm_arg *arg,
}
int dm_read_arg(const struct dm_arg *arg, struct dm_arg_set *arg_set,
- unsigned *value, char **error)
+ unsigned int *value, char **error)
{
return validate_next_arg(arg, arg_set, value, error, 0);
}
EXPORT_SYMBOL(dm_read_arg);
int dm_read_arg_group(const struct dm_arg *arg, struct dm_arg_set *arg_set,
- unsigned *value, char **error)
+ unsigned int *value, char **error)
{
return validate_next_arg(arg, arg_set, value, error, 1);
}
@@ -780,7 +779,7 @@ const char *dm_shift_arg(struct dm_arg_set *as)
}
EXPORT_SYMBOL(dm_shift_arg);
-void dm_consume_args(struct dm_arg_set *as, unsigned num_args)
+void dm_consume_args(struct dm_arg_set *as, unsigned int num_args)
{
BUG_ON(as->argc < num_args);
as->argc -= num_args;
@@ -856,7 +855,7 @@ static int device_is_rq_stackable(struct dm_target *ti, struct dm_dev *dev,
static int dm_table_determine_type(struct dm_table *t)
{
- unsigned bio_based = 0, request_based = 0, hybrid = 0;
+ unsigned int bio_based = 0, request_based = 0, hybrid = 0;
struct dm_target *ti;
struct list_head *devices = dm_table_get_devices(t);
enum dm_queue_mode live_md_type = dm_get_md_type(t->md);
@@ -1535,7 +1534,7 @@ static bool dm_table_any_dev_attr(struct dm_table *t,
static int count_device(struct dm_target *ti, struct dm_dev *dev,
sector_t start, sector_t len, void *data)
{
- unsigned *num_devices = data;
+ unsigned int *num_devices = data;
(*num_devices)++;
@@ -1565,7 +1564,7 @@ bool dm_table_has_no_data_devices(struct dm_table *t)
{
for (unsigned int i = 0; i < t->num_targets; i++) {
struct dm_target *ti = dm_table_get_target(t, i);
- unsigned num_devices = 0;
+ unsigned int num_devices = 0;
if (!ti->type->iterate_devices)
return false;
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 6bcc4c4786d8..80545ec54121 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -318,12 +318,12 @@ static void unpack_block_time(uint64_t v, dm_block_t *b, uint32_t *t)
*/
typedef int (*run_fn)(struct dm_space_map *, dm_block_t, dm_block_t);
-static void with_runs(struct dm_space_map *sm, const __le64 *value_le, unsigned count, run_fn fn)
+static void with_runs(struct dm_space_map *sm, const __le64 *value_le, unsigned int count, run_fn fn)
{
uint64_t b, begin, end;
uint32_t t;
bool in_run = false;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, value_le++) {
/* We know value_le is 8 byte aligned */
@@ -348,13 +348,13 @@ static void with_runs(struct dm_space_map *sm, const __le64 *value_le, unsigned
fn(sm, begin, end);
}
-static void data_block_inc(void *context, const void *value_le, unsigned count)
+static void data_block_inc(void *context, const void *value_le, unsigned int count)
{
with_runs((struct dm_space_map *) context,
(const __le64 *) value_le, count, dm_sm_inc_blocks);
}
-static void data_block_dec(void *context, const void *value_le, unsigned count)
+static void data_block_dec(void *context, const void *value_le, unsigned int count)
{
with_runs((struct dm_space_map *) context,
(const __le64 *) value_le, count, dm_sm_dec_blocks);
@@ -374,21 +374,21 @@ static int data_block_equal(void *context, const void *value1_le, const void *va
return b1 == b2;
}
-static void subtree_inc(void *context, const void *value, unsigned count)
+static void subtree_inc(void *context, const void *value, unsigned int count)
{
struct dm_btree_info *info = context;
const __le64 *root_le = value;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, root_le++)
dm_tm_inc(info->tm, le64_to_cpu(*root_le));
}
-static void subtree_dec(void *context, const void *value, unsigned count)
+static void subtree_dec(void *context, const void *value, unsigned int count)
{
struct dm_btree_info *info = context;
const __le64 *root_le = value;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, root_le++)
if (dm_btree_del(info, le64_to_cpu(*root_le)))
@@ -448,10 +448,10 @@ static int superblock_lock(struct dm_pool_metadata *pmd,
static int __superblock_all_zeroes(struct dm_block_manager *bm, int *result)
{
int r;
- unsigned i;
+ unsigned int i;
struct dm_block *b;
__le64 *data_le, zero = cpu_to_le64(0);
- unsigned block_size = dm_bm_block_size(bm) / sizeof(__le64);
+ unsigned int block_size = dm_bm_block_size(bm) / sizeof(__le64);
/*
* We can't use a validator here - it may be all zeroes.
@@ -971,7 +971,7 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
{
int r;
- unsigned open_devices = 0;
+ unsigned int open_devices = 0;
struct dm_thin_device *td, *tmp;
down_read(&pmd->root_lock);
@@ -1679,7 +1679,7 @@ int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_t end)
{
int r;
- unsigned count, total_count = 0;
+ unsigned int count, total_count = 0;
struct dm_pool_metadata *pmd = td->pmd;
dm_block_t keys[1] = { td->id };
__le64 value;
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index e6e5ab29a95d..ba4ba6be7e23 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -32,7 +32,7 @@
#define COMMIT_PERIOD HZ
#define NO_SPACE_TIMEOUT_SECS 60
-static unsigned no_space_timeout_secs = NO_SPACE_TIMEOUT_SECS;
+static unsigned int no_space_timeout_secs = NO_SPACE_TIMEOUT_SECS;
DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,
"A percentage of time allocated for copy on write");
@@ -254,7 +254,7 @@ struct pool {
struct delayed_work no_space_timeout;
unsigned long last_commit_jiffies;
- unsigned ref_count;
+ unsigned int ref_count;
spinlock_t lock;
struct bio_list deferred_flush_bios;
@@ -2159,7 +2159,7 @@ static void process_thin_deferred_bios(struct thin_c *tc)
struct bio *bio;
struct bio_list bios;
struct blk_plug plug;
- unsigned count = 0;
+ unsigned int count = 0;
if (tc->requeue_mode) {
error_thin_bio_list(tc, &tc->deferred_bio_list,
@@ -2229,9 +2229,9 @@ static int cmp_cells(const void *lhs, const void *rhs)
return 0;
}
-static unsigned sort_cells(struct pool *pool, struct list_head *cells)
+static unsigned int sort_cells(struct pool *pool, struct list_head *cells)
{
- unsigned count = 0;
+ unsigned int count = 0;
struct dm_bio_prison_cell *cell, *tmp;
list_for_each_entry_safe(cell, tmp, cells, user_list) {
@@ -2252,7 +2252,7 @@ static void process_thin_deferred_cells(struct thin_c *tc)
struct pool *pool = tc->pool;
struct list_head cells;
struct dm_bio_prison_cell *cell;
- unsigned i, j, count;
+ unsigned int i, j, count;
INIT_LIST_HEAD(&cells);
@@ -3115,7 +3115,7 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
struct dm_target *ti)
{
int r;
- unsigned argc;
+ unsigned int argc;
const char *arg_name;
static const struct dm_arg _args[] = {
@@ -3252,7 +3252,7 @@ static dm_block_t calc_metadata_threshold(struct pool_c *pt)
* read_only: Don't allow any changes to be made to the pool metadata.
* error_if_no_space: error IOs, instead of queueing, if no space.
*/
-static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
int r, pool_created = 0;
struct pool_c *pt;
@@ -3648,7 +3648,7 @@ static void pool_postsuspend(struct dm_target *ti)
(void) commit(pool);
}
-static int check_arg_count(unsigned argc, unsigned args_required)
+static int check_arg_count(unsigned int argc, unsigned int args_required)
{
if (argc != args_required) {
DMWARN("Message received with %u arguments instead of %u.",
@@ -3671,7 +3671,7 @@ static int read_dev_id(char *arg, dm_thin_id *dev_id, int warning)
return -EINVAL;
}
-static int process_create_thin_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_create_thin_mesg(unsigned int argc, char **argv, struct pool *pool)
{
dm_thin_id dev_id;
int r;
@@ -3694,7 +3694,7 @@ static int process_create_thin_mesg(unsigned argc, char **argv, struct pool *poo
return 0;
}
-static int process_create_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_create_snap_mesg(unsigned int argc, char **argv, struct pool *pool)
{
dm_thin_id dev_id;
dm_thin_id origin_dev_id;
@@ -3722,7 +3722,7 @@ static int process_create_snap_mesg(unsigned argc, char **argv, struct pool *poo
return 0;
}
-static int process_delete_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_delete_mesg(unsigned int argc, char **argv, struct pool *pool)
{
dm_thin_id dev_id;
int r;
@@ -3742,7 +3742,7 @@ static int process_delete_mesg(unsigned argc, char **argv, struct pool *pool)
return r;
}
-static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_set_transaction_id_mesg(unsigned int argc, char **argv, struct pool *pool)
{
dm_thin_id old_id, new_id;
int r;
@@ -3771,7 +3771,7 @@ static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct po
return 0;
}
-static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_reserve_metadata_snap_mesg(unsigned int argc, char **argv, struct pool *pool)
{
int r;
@@ -3788,7 +3788,7 @@ static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct
return r;
}
-static int process_release_metadata_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_release_metadata_snap_mesg(unsigned int argc, char **argv, struct pool *pool)
{
int r;
@@ -3812,8 +3812,8 @@ static int process_release_metadata_snap_mesg(unsigned argc, char **argv, struct
* reserve_metadata_snap
* release_metadata_snap
*/
-static int pool_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int pool_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r = -EINVAL;
struct pool_c *pt = ti->private;
@@ -3853,9 +3853,9 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv,
}
static void emit_flags(struct pool_features *pf, char *result,
- unsigned sz, unsigned maxlen)
+ unsigned int sz, unsigned int maxlen)
{
- unsigned count = !pf->zero_new_blocks + !pf->discard_enabled +
+ unsigned int count = !pf->zero_new_blocks + !pf->discard_enabled +
!pf->discard_passdown + (pf->mode == PM_READ_ONLY) +
pf->error_if_no_space;
DMEMIT("%u ", count);
@@ -3883,10 +3883,10 @@ static void emit_flags(struct pool_features *pf, char *result,
* <pool mode> <discard config> <no space config> <needs_check>
*/
static void pool_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int r;
- unsigned sz = 0;
+ unsigned int sz = 0;
uint64_t transaction_id;
dm_block_t nr_free_blocks_data;
dm_block_t nr_free_blocks_metadata;
@@ -4148,7 +4148,7 @@ static void thin_dtr(struct dm_target *ti)
* If the pool device has discards disabled, they get disabled for the thin
* device as well.
*/
-static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int thin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
int r;
struct thin_c *tc;
@@ -4371,7 +4371,7 @@ static int thin_preresume(struct dm_target *ti)
* <nr mapped sectors> <highest mapped sector>
*/
static void thin_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int r;
ssize_t sz = 0;
diff --git a/drivers/md/dm-uevent.c b/drivers/md/dm-uevent.c
index 8671267200d8..a02b3f6ea47a 100644
--- a/drivers/md/dm-uevent.c
+++ b/drivers/md/dm-uevent.c
@@ -60,7 +60,7 @@ static struct dm_uevent *dm_build_path_uevent(struct mapped_device *md,
enum kobject_action action,
const char *dm_action,
const char *path,
- unsigned nr_valid_paths)
+ unsigned int nr_valid_paths)
{
struct dm_uevent *event;
@@ -168,7 +168,7 @@ EXPORT_SYMBOL_GPL(dm_send_uevents);
*
*/
void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
- const char *path, unsigned nr_valid_paths)
+ const char *path, unsigned int nr_valid_paths)
{
struct mapped_device *md = dm_table_get_md(ti->table);
struct dm_uevent *event;
diff --git a/drivers/md/dm-uevent.h b/drivers/md/dm-uevent.h
index d30d226f2a18..2c9ba561fd8e 100644
--- a/drivers/md/dm-uevent.h
+++ b/drivers/md/dm-uevent.h
@@ -20,7 +20,7 @@ extern void dm_uevent_exit(void);
extern void dm_send_uevents(struct list_head *events, struct kobject *kobj);
extern void dm_path_uevent(enum dm_uevent_type event_type,
struct dm_target *ti, const char *path,
- unsigned nr_valid_paths);
+ unsigned int nr_valid_paths);
#else
@@ -37,7 +37,7 @@ static inline void dm_send_uevents(struct list_head *events,
}
static inline void dm_path_uevent(enum dm_uevent_type event_type,
struct dm_target *ti, const char *path,
- unsigned nr_valid_paths)
+ unsigned int nr_valid_paths)
{
}
diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c
index 23cffce56403..962fc32c947c 100644
--- a/drivers/md/dm-verity-fec.c
+++ b/drivers/md/dm-verity-fec.c
@@ -59,14 +59,14 @@ static int fec_decode_rs8(struct dm_verity *v, struct dm_verity_fec_io *fio,
* to the data block. Caller is responsible for releasing buf.
*/
static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
- unsigned *offset, struct dm_buffer **buf)
+ unsigned int *offset, struct dm_buffer **buf)
{
u64 position, block, rem;
u8 *res;
position = (index + rsb) * v->fec->roots;
block = div64_u64_rem(position, v->fec->io_size, &rem);
- *offset = (unsigned)rem;
+ *offset = (unsigned int)rem;
res = dm_bufio_read(v->fec->bufio, block, buf);
if (IS_ERR(res)) {
@@ -102,7 +102,7 @@ static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
*/
static inline u8 *fec_buffer_rs_block(struct dm_verity *v,
struct dm_verity_fec_io *fio,
- unsigned i, unsigned j)
+ unsigned int i, unsigned int j)
{
return &fio->bufs[i][j * v->fec->rsn];
}
@@ -111,7 +111,7 @@ static inline u8 *fec_buffer_rs_block(struct dm_verity *v,
* Return an index to the current RS block when called inside
* fec_for_each_buffer_rs_block.
*/
-static inline unsigned fec_buffer_rs_index(unsigned i, unsigned j)
+static inline unsigned int fec_buffer_rs_index(unsigned int i, unsigned int j)
{
return (i << DM_VERITY_FEC_BUF_RS_BITS) + j;
}
@@ -121,12 +121,12 @@ static inline unsigned fec_buffer_rs_index(unsigned i, unsigned j)
* starting from block_offset.
*/
static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio,
- u64 rsb, int byte_index, unsigned block_offset,
+ u64 rsb, int byte_index, unsigned int block_offset,
int neras)
{
int r, corrected = 0, res;
struct dm_buffer *buf;
- unsigned n, i, offset;
+ unsigned int n, i, offset;
u8 *par, *block;
par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
@@ -197,7 +197,7 @@ static int fec_is_erasure(struct dm_verity *v, struct dm_verity_io *io,
* fits into buffers. Check for erasure locations if @neras is non-NULL.
*/
static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
- u64 rsb, u64 target, unsigned block_offset,
+ u64 rsb, u64 target, unsigned int block_offset,
int *neras)
{
bool is_zero;
@@ -208,7 +208,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
u64 block, ileaved;
u8 *bbuf, *rs_block;
u8 want_digest[HASH_MAX_DIGESTSIZE];
- unsigned n, k;
+ unsigned int n, k;
if (neras)
*neras = 0;
@@ -304,7 +304,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
*/
static int fec_alloc_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio)
{
- unsigned n;
+ unsigned int n;
if (!fio->rs)
fio->rs = mempool_alloc(&v->fec->rs_pool, GFP_NOIO);
@@ -344,7 +344,7 @@ static int fec_alloc_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio)
*/
static void fec_init_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio)
{
- unsigned n;
+ unsigned int n;
fec_for_each_buffer(fio, n)
memset(fio->bufs[n], 0, v->fec->rsn << DM_VERITY_FEC_BUF_RS_BITS);
@@ -362,7 +362,7 @@ static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io,
bool use_erasures)
{
int r, neras = 0;
- unsigned pos;
+ unsigned int pos;
r = fec_alloc_bufs(v, fio);
if (unlikely(r < 0))
@@ -484,7 +484,7 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
*/
void verity_fec_finish_io(struct dm_verity_io *io)
{
- unsigned n;
+ unsigned int n;
struct dm_verity_fec *f = io->v->fec;
struct dm_verity_fec_io *fio = fec_io(io);
@@ -522,8 +522,8 @@ void verity_fec_init_io(struct dm_verity_io *io)
/*
* Append feature arguments and values to the status table.
*/
-unsigned verity_fec_status_table(struct dm_verity *v, unsigned sz,
- char *result, unsigned maxlen)
+unsigned int verity_fec_status_table(struct dm_verity *v, unsigned int sz,
+ char *result, unsigned int maxlen)
{
if (!verity_fec_is_enabled(v))
return sz;
@@ -589,7 +589,7 @@ bool verity_is_fec_opt_arg(const char *arg_name)
}
int verity_fec_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
- unsigned *argc, const char *arg_name)
+ unsigned int *argc, const char *arg_name)
{
int r;
struct dm_target *ti = v->ti;
diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h
index 3c46c8d61883..8454070d2824 100644
--- a/drivers/md/dm-verity-fec.h
+++ b/drivers/md/dm-verity-fec.h
@@ -55,10 +55,10 @@ struct dm_verity_fec_io {
struct rs_control *rs; /* Reed-Solomon state */
int erasures[DM_VERITY_FEC_MAX_RSN]; /* erasures for decode_rs8 */
u8 *bufs[DM_VERITY_FEC_BUF_MAX]; /* bufs for deinterleaving */
- unsigned nbufs; /* number of buffers allocated */
+ unsigned int nbufs; /* number of buffers allocated */
u8 *output; /* buffer for corrected output */
size_t output_pos;
- unsigned level; /* recursion level */
+ unsigned int level; /* recursion level */
};
#ifdef CONFIG_DM_VERITY_FEC
@@ -72,15 +72,15 @@ extern int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
enum verity_block_type type, sector_t block,
u8 *dest, struct bvec_iter *iter);
-extern unsigned verity_fec_status_table(struct dm_verity *v, unsigned sz,
- char *result, unsigned maxlen);
+extern unsigned int verity_fec_status_table(struct dm_verity *v, unsigned int sz,
+ char *result, unsigned int maxlen);
extern void verity_fec_finish_io(struct dm_verity_io *io);
extern void verity_fec_init_io(struct dm_verity_io *io);
extern bool verity_is_fec_opt_arg(const char *arg_name);
extern int verity_fec_parse_opt_args(struct dm_arg_set *as,
- struct dm_verity *v, unsigned *argc,
+ struct dm_verity *v, unsigned int *argc,
const char *arg_name);
extern void verity_fec_dtr(struct dm_verity *v);
@@ -106,9 +106,9 @@ static inline int verity_fec_decode(struct dm_verity *v,
return -EOPNOTSUPP;
}
-static inline unsigned verity_fec_status_table(struct dm_verity *v,
- unsigned sz, char *result,
- unsigned maxlen)
+static inline unsigned int verity_fec_status_table(struct dm_verity *v,
+ unsigned int sz, char *result,
+ unsigned int maxlen)
{
return sz;
}
@@ -128,7 +128,7 @@ static inline bool verity_is_fec_opt_arg(const char *arg_name)
static inline int verity_fec_parse_opt_args(struct dm_arg_set *as,
struct dm_verity *v,
- unsigned *argc,
+ unsigned int *argc,
const char *arg_name)
{
return -EINVAL;
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index ccf5b852fbf7..64e8ac429984 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -41,7 +41,7 @@
#define DM_VERITY_OPTS_MAX (4 + DM_VERITY_OPTS_FEC + \
DM_VERITY_ROOT_HASH_VERIFICATION_OPTS)
-static unsigned dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE;
+static unsigned int dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE;
module_param_named(prefetch_cluster, dm_verity_prefetch_cluster, uint, S_IRUGO | S_IWUSR);
@@ -51,7 +51,7 @@ struct dm_verity_prefetch_work {
struct work_struct work;
struct dm_verity *v;
sector_t block;
- unsigned n_blocks;
+ unsigned int n_blocks;
};
/*
@@ -196,10 +196,10 @@ int verity_hash(struct dm_verity *v, struct ahash_request *req,
}
static void verity_hash_at_level(struct dm_verity *v, sector_t block, int level,
- sector_t *hash_block, unsigned *offset)
+ sector_t *hash_block, unsigned int *offset)
{
sector_t position = verity_position_at_level(v, block, level);
- unsigned idx;
+ unsigned int idx;
*hash_block = v->hash_level_block[level] + (position >> v->hash_per_block_bits);
@@ -287,7 +287,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
u8 *data;
int r;
sector_t hash_block;
- unsigned offset;
+ unsigned int offset;
verity_hash_at_level(v, block, level, &hash_block, &offset);
@@ -445,13 +445,13 @@ int verity_for_bv_block(struct dm_verity *v, struct dm_verity_io *io,
struct dm_verity_io *io, u8 *data,
size_t len))
{
- unsigned todo = 1 << v->data_dev_block_bits;
+ unsigned int todo = 1 << v->data_dev_block_bits;
struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
do {
int r;
u8 *page;
- unsigned len;
+ unsigned int len;
struct bio_vec bv = bio_iter_iovec(bio, *iter);
page = bvec_kmap_local(&bv);
@@ -688,7 +688,7 @@ static void verity_prefetch_io(struct work_struct *work)
verity_hash_at_level(v, pw->block, i, &hash_block_start, NULL);
verity_hash_at_level(v, pw->block + pw->n_blocks - 1, i, &hash_block_end, NULL);
if (!i) {
- unsigned cluster = READ_ONCE(dm_verity_prefetch_cluster);
+ unsigned int cluster = READ_ONCE(dm_verity_prefetch_cluster);
cluster >>= v->data_dev_block_bits;
if (unlikely(!cluster))
@@ -753,7 +753,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
bio_set_dev(bio, v->data_dev->bdev);
bio->bi_iter.bi_sector = verity_map_sector(v, bio->bi_iter.bi_sector);
- if (((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) &
+ if (((unsigned int)bio->bi_iter.bi_sector | bio_sectors(bio)) &
((1 << (v->data_dev_block_bits - SECTOR_SHIFT)) - 1)) {
DMERR_LIMIT("unaligned io");
return DM_MAPIO_KILL;
@@ -789,12 +789,12 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
* Status: V (valid) or C (corruption found)
*/
static void verity_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct dm_verity *v = ti->private;
- unsigned args = 0;
- unsigned sz = 0;
- unsigned x;
+ unsigned int args = 0;
+ unsigned int sz = 0;
+ unsigned int x;
switch (type) {
case STATUSTYPE_INFO:
@@ -1054,7 +1054,7 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
bool only_modifier_opts)
{
int r = 0;
- unsigned argc;
+ unsigned int argc;
struct dm_target *ti = v->ti;
const char *arg_name;
@@ -1156,7 +1156,7 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
* <digest>
* <salt> Hex string or "-" if no salt.
*/
-static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct dm_verity *v;
struct dm_verity_sig_opts verify_args = {0};
diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h
index 98f306ec6a33..2f555b420367 100644
--- a/drivers/md/dm-verity.h
+++ b/drivers/md/dm-verity.h
@@ -42,7 +42,7 @@ struct dm_verity {
u8 *root_digest; /* digest of the root block */
u8 *salt; /* salt: its size is salt_size */
u8 *zero_digest; /* digest for a zero block */
- unsigned salt_size;
+ unsigned int salt_size;
sector_t data_start; /* data offset in 512-byte sectors */
sector_t hash_start; /* hash start in blocks */
sector_t data_blocks; /* the number of data blocks */
@@ -54,10 +54,10 @@ struct dm_verity {
unsigned char version;
bool hash_failed:1; /* set if hash of any block failed */
bool use_tasklet:1; /* try to verify in tasklet before work-queue */
- unsigned digest_size; /* digest size for the current hash algorithm */
+ unsigned int digest_size; /* digest size for the current hash algorithm */
unsigned int ahash_reqsize;/* the size of temporary space for crypto */
enum verity_mode mode; /* mode for handling verification errors */
- unsigned corrupted_errs;/* Number of errors for corrupted blocks */
+ unsigned int corrupted_errs;/* Number of errors for corrupted blocks */
struct workqueue_struct *verify_wq;
@@ -77,7 +77,7 @@ struct dm_verity_io {
bio_end_io_t *orig_bi_end_io;
sector_t block;
- unsigned n_blocks;
+ unsigned int n_blocks;
bool in_tasklet;
struct bvec_iter iter;
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
index 96a003eb7323..431c84595ddb 100644
--- a/drivers/md/dm-writecache.c
+++ b/drivers/md/dm-writecache.c
@@ -128,9 +128,9 @@ struct dm_writecache {
unsigned long max_age;
unsigned long pause;
- unsigned uncommitted_blocks;
- unsigned autocommit_blocks;
- unsigned max_writeback_jobs;
+ unsigned int uncommitted_blocks;
+ unsigned int autocommit_blocks;
+ unsigned int max_writeback_jobs;
int error;
@@ -155,7 +155,7 @@ struct dm_writecache {
sector_t data_device_sectors;
void *block_start;
struct wc_entry *entries;
- unsigned block_size;
+ unsigned int block_size;
unsigned char block_size_bits;
bool pmem_mode:1;
@@ -178,13 +178,13 @@ struct dm_writecache {
bool metadata_only:1;
bool pause_set:1;
- unsigned high_wm_percent_value;
- unsigned low_wm_percent_value;
- unsigned autocommit_time_value;
- unsigned max_age_value;
- unsigned pause_value;
+ unsigned int high_wm_percent_value;
+ unsigned int low_wm_percent_value;
+ unsigned int autocommit_time_value;
+ unsigned int max_age_value;
+ unsigned int pause_value;
- unsigned writeback_all;
+ unsigned int writeback_all;
struct workqueue_struct *writeback_wq;
struct work_struct writeback_work;
struct work_struct flush_work;
@@ -202,7 +202,7 @@ struct dm_writecache {
struct dm_kcopyd_client *dm_kcopyd;
unsigned long *dirty_bitmap;
- unsigned dirty_bitmap_size;
+ unsigned int dirty_bitmap_size;
struct bio_set bio_set;
mempool_t copy_pool;
@@ -227,7 +227,7 @@ struct writeback_struct {
struct list_head endio_entry;
struct dm_writecache *wc;
struct wc_entry **wc_list;
- unsigned wc_list_n;
+ unsigned int wc_list_n;
struct wc_entry *wc_list_inline[WB_LIST_INLINE];
struct bio bio;
};
@@ -236,7 +236,7 @@ struct copy_struct {
struct list_head endio_entry;
struct dm_writecache *wc;
struct wc_entry *e;
- unsigned n_entries;
+ unsigned int n_entries;
int error;
};
@@ -369,7 +369,7 @@ static struct page *persistent_memory_page(void *addr)
return virt_to_page(addr);
}
-static unsigned persistent_memory_page_offset(void *addr)
+static unsigned int persistent_memory_page_offset(void *addr)
{
return (unsigned long)addr & (PAGE_SIZE - 1);
}
@@ -502,11 +502,11 @@ static void ssd_commit_flushed(struct dm_writecache *wc, bool wait_for_ios)
COMPLETION_INITIALIZER_ONSTACK(endio.c),
ATOMIC_INIT(1),
};
- unsigned bitmap_bits = wc->dirty_bitmap_size * 8;
- unsigned i = 0;
+ unsigned int bitmap_bits = wc->dirty_bitmap_size * 8;
+ unsigned int i = 0;
while (1) {
- unsigned j;
+ unsigned int j;
i = find_next_bit(wc->dirty_bitmap, bitmap_bits, i);
if (unlikely(i == bitmap_bits))
break;
@@ -1100,7 +1100,7 @@ static void writecache_resume(struct dm_target *ti)
wc_unlock(wc);
}
-static int process_flush_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+static int process_flush_mesg(unsigned int argc, char **argv, struct dm_writecache *wc)
{
if (argc != 1)
return -EINVAL;
@@ -1133,7 +1133,7 @@ static int process_flush_mesg(unsigned argc, char **argv, struct dm_writecache *
return 0;
}
-static int process_flush_on_suspend_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+static int process_flush_on_suspend_mesg(unsigned int argc, char **argv, struct dm_writecache *wc)
{
if (argc != 1)
return -EINVAL;
@@ -1153,7 +1153,7 @@ static void activate_cleaner(struct dm_writecache *wc)
wc->freelist_low_watermark = wc->n_blocks;
}
-static int process_cleaner_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+static int process_cleaner_mesg(unsigned int argc, char **argv, struct dm_writecache *wc)
{
if (argc != 1)
return -EINVAL;
@@ -1167,7 +1167,7 @@ static int process_cleaner_mesg(unsigned argc, char **argv, struct dm_writecache
return 0;
}
-static int process_clear_stats_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+static int process_clear_stats_mesg(unsigned int argc, char **argv, struct dm_writecache *wc)
{
if (argc != 1)
return -EINVAL;
@@ -1179,8 +1179,8 @@ static int process_clear_stats_mesg(unsigned argc, char **argv, struct dm_writec
return 0;
}
-static int writecache_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int writecache_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r = -EINVAL;
struct dm_writecache *wc = ti->private;
@@ -1238,9 +1238,9 @@ static void memcpy_flushcache_optimized(void *dest, void *source, size_t size)
static void bio_copy_block(struct dm_writecache *wc, struct bio *bio, void *data)
{
void *buf;
- unsigned size;
+ unsigned int size;
int rw = bio_data_dir(bio);
- unsigned remaining_size = wc->block_size;
+ unsigned int remaining_size = wc->block_size;
do {
struct bio_vec bv = bio_iter_iovec(bio, bio->bi_iter);
@@ -1371,7 +1371,7 @@ static enum wc_map_op writecache_map_read(struct dm_writecache *wc, struct bio *
static void writecache_bio_copy_ssd(struct dm_writecache *wc, struct bio *bio,
struct wc_entry *e, bool search_used)
{
- unsigned bio_size = wc->block_size;
+ unsigned int bio_size = wc->block_size;
sector_t start_cache_sec = cache_sector(wc, e);
sector_t current_cache_sec = start_cache_sec + (bio_size >> SECTOR_SHIFT);
@@ -1540,7 +1540,7 @@ static int writecache_map(struct dm_target *ti, struct bio *bio)
bio->bi_iter.bi_sector = dm_target_offset(ti, bio->bi_iter.bi_sector);
- if (unlikely((((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) &
+ if (unlikely((((unsigned int)bio->bi_iter.bi_sector | bio_sectors(bio)) &
(wc->block_size / 512 - 1)) != 0)) {
DMERR("I/O is not aligned, sector %llu, size %u, block size %u",
(unsigned long long)bio->bi_iter.bi_sector,
@@ -1666,7 +1666,7 @@ static void writecache_copy_endio(int read_err, unsigned long write_err, void *p
static void __writecache_endio_pmem(struct dm_writecache *wc, struct list_head *list)
{
- unsigned i;
+ unsigned int i;
struct writeback_struct *wb;
struct wc_entry *e;
unsigned long n_walked = 0;
@@ -1782,7 +1782,7 @@ static int writecache_endio_thread(void *data)
static bool wc_add_block(struct writeback_struct *wb, struct wc_entry *e)
{
struct dm_writecache *wc = wb->wc;
- unsigned block_size = wc->block_size;
+ unsigned int block_size = wc->block_size;
void *address = memory_data(wc, e);
persistent_memory_flush_cache(address, block_size);
@@ -1817,7 +1817,7 @@ static void __writecache_writeback_pmem(struct dm_writecache *wc, struct writeba
struct wc_entry *e, *f;
struct bio *bio;
struct writeback_struct *wb;
- unsigned max_pages;
+ unsigned int max_pages;
while (wbl->size) {
wbl->size--;
@@ -1880,7 +1880,7 @@ static void __writecache_writeback_ssd(struct dm_writecache *wc, struct writebac
struct copy_struct *c;
while (wbl->size) {
- unsigned n_sectors;
+ unsigned int n_sectors;
wbl->size--;
e = container_of(wbl->list.prev, struct wc_entry, lru);
@@ -2092,7 +2092,7 @@ static void writecache_writeback(struct work_struct *work)
}
}
-static int calculate_memory_size(uint64_t device_size, unsigned block_size,
+static int calculate_memory_size(uint64_t device_size, unsigned int block_size,
size_t *n_blocks_p, size_t *n_metadata_blocks_p)
{
uint64_t n_blocks, offset;
@@ -2207,12 +2207,12 @@ static void writecache_dtr(struct dm_target *ti)
kfree(wc);
}
-static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int writecache_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct dm_writecache *wc;
struct dm_arg_set as;
const char *string;
- unsigned opt_params;
+ unsigned int opt_params;
size_t offset, data_size;
int i, r;
char dummy;
@@ -2419,7 +2419,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto invalid_optional;
wc->autocommit_blocks_set = true;
} else if (!strcasecmp(string, "autocommit_time") && opt_params >= 1) {
- unsigned autocommit_msecs;
+ unsigned int autocommit_msecs;
string = dm_shift_arg(&as), opt_params--;
if (sscanf(string, "%u%c", &autocommit_msecs, &dummy) != 1)
goto invalid_optional;
@@ -2429,7 +2429,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
wc->autocommit_time_value = autocommit_msecs;
wc->autocommit_time_set = true;
} else if (!strcasecmp(string, "max_age") && opt_params >= 1) {
- unsigned max_age_msecs;
+ unsigned int max_age_msecs;
string = dm_shift_arg(&as), opt_params--;
if (sscanf(string, "%u%c", &max_age_msecs, &dummy) != 1)
goto invalid_optional;
@@ -2454,7 +2454,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
} else if (!strcasecmp(string, "metadata_only")) {
wc->metadata_only = true;
} else if (!strcasecmp(string, "pause_writeback") && opt_params >= 1) {
- unsigned pause_msecs;
+ unsigned int pause_msecs;
if (WC_MODE_PMEM(wc))
goto invalid_optional;
string = dm_shift_arg(&as), opt_params--;
@@ -2653,11 +2653,11 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
}
static void writecache_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct dm_writecache *wc = ti->private;
- unsigned extra_args;
- unsigned sz = 0;
+ unsigned int extra_args;
+ unsigned int sz = 0;
switch (type) {
case STATUSTYPE_INFO:
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 1b6c3c783a8e..cdbf24def8af 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -83,7 +83,7 @@ struct clone_info {
struct bio *bio;
struct dm_io *io;
sector_t sector;
- unsigned sector_count;
+ unsigned int sector_count;
bool is_abnormal_io:1;
bool submit_as_polled:1;
};
@@ -111,7 +111,7 @@ struct bio *dm_bio_from_per_bio_data(void *data, size_t data_size)
}
EXPORT_SYMBOL_GPL(dm_bio_from_per_bio_data);
-unsigned dm_bio_get_target_bio_nr(const struct bio *bio)
+unsigned int dm_bio_get_target_bio_nr(const struct bio *bio)
{
return container_of(bio, struct dm_target_io, clone)->target_bio_nr;
}
@@ -142,7 +142,7 @@ struct table_device {
* Bio-based DM's mempools' reserved IOs set by the user.
*/
#define RESERVED_BIO_BASED_IOS 16
-static unsigned reserved_bio_based_ios = RESERVED_BIO_BASED_IOS;
+static unsigned int reserved_bio_based_ios = RESERVED_BIO_BASED_IOS;
static int __dm_get_module_param_int(int *module_param, int min, int max)
{
@@ -165,11 +165,10 @@ static int __dm_get_module_param_int(int *module_param, int min, int max)
return param;
}
-unsigned __dm_get_module_param(unsigned *module_param,
- unsigned def, unsigned max)
+unsigned int __dm_get_module_param(unsigned int *module_param, unsigned int def, unsigned int max)
{
- unsigned param = READ_ONCE(*module_param);
- unsigned modified_param = 0;
+ unsigned int param = READ_ONCE(*module_param);
+ unsigned int modified_param = 0;
if (!param)
modified_param = def;
@@ -184,14 +183,14 @@ unsigned __dm_get_module_param(unsigned *module_param,
return param;
}
-unsigned dm_get_reserved_bio_based_ios(void)
+unsigned int dm_get_reserved_bio_based_ios(void)
{
return __dm_get_module_param(&reserved_bio_based_ios,
RESERVED_BIO_BASED_IOS, DM_RESERVED_MAX_IOS);
}
EXPORT_SYMBOL_GPL(dm_get_reserved_bio_based_ios);
-static unsigned dm_get_numa_node(void)
+static unsigned int dm_get_numa_node(void)
{
return __dm_get_module_param_int(&dm_numa_node,
DM_NUMA_NODE, num_online_nodes() - 1);
@@ -603,7 +602,7 @@ static void free_io(struct dm_io *io)
}
static struct bio *alloc_tio(struct clone_info *ci, struct dm_target *ti,
- unsigned target_bio_nr, unsigned *len, gfp_t gfp_mask)
+ unsigned int target_bio_nr, unsigned int *len, gfp_t gfp_mask)
{
struct mapped_device *md = ci->io->md;
struct dm_target_io *tio;
@@ -1314,11 +1313,11 @@ static size_t dm_dax_recovery_write(struct dax_device *dax_dev, pgoff_t pgoff,
* the partially processed part (the sum of regions 1+2) must be the same for all
* copies of the bio.
*/
-void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors)
+void dm_accept_partial_bio(struct bio *bio, unsigned int n_sectors)
{
struct dm_target_io *tio = clone_to_tio(bio);
struct dm_io *io = tio->io;
- unsigned bio_sectors = bio_sectors(bio);
+ unsigned int bio_sectors = bio_sectors(bio);
BUG_ON(dm_tio_flagged(tio, DM_TIO_IS_DUPLICATE_BIO));
BUG_ON(op_is_zone_mgmt(bio_op(bio)));
@@ -1447,7 +1446,7 @@ static void __map_bio(struct bio *clone)
}
}
-static void setup_split_accounting(struct clone_info *ci, unsigned len)
+static void setup_split_accounting(struct clone_info *ci, unsigned int len)
{
struct dm_io *io = ci->io;
@@ -1463,7 +1462,8 @@ static void setup_split_accounting(struct clone_info *ci, unsigned len)
}
static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
- struct dm_target *ti, unsigned num_bios)
+ struct dm_target *ti, unsigned int num_bios,
+ unsigned *len)
{
struct bio *bio;
int try;
@@ -1474,7 +1474,7 @@ static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
if (try)
mutex_lock(&ci->io->md->table_devices_lock);
for (bio_nr = 0; bio_nr < num_bios; bio_nr++) {
- bio = alloc_tio(ci, ti, bio_nr, NULL,
+ bio = alloc_tio(ci, ti, bio_nr, len,
try ? GFP_NOIO : GFP_NOWAIT);
if (!bio)
break;
@@ -1492,7 +1492,7 @@ static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
}
static int __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
- unsigned int num_bios, unsigned *len)
+ unsigned int num_bios, unsigned int *len)
{
struct bio_list blist = BIO_EMPTY_LIST;
struct bio *clone;
@@ -1512,7 +1512,7 @@ static int __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
if (len)
setup_split_accounting(ci, *len);
/* dm_accept_partial_bio() is not supported with shared tio->len_ptr */
- alloc_multiple_bios(&blist, ci, ti, num_bios);
+ alloc_multiple_bios(&blist, ci, ti, num_bios, len);
while ((clone = bio_list_pop(&blist))) {
dm_tio_set_flag(clone_to_tio(clone), DM_TIO_IS_DUPLICATE_BIO);
__map_bio(clone);
@@ -1560,10 +1560,9 @@ static void __send_empty_flush(struct clone_info *ci)
}
static void __send_changing_extent_only(struct clone_info *ci, struct dm_target *ti,
- unsigned num_bios)
+ unsigned int num_bios)
{
- unsigned len;
- unsigned int bios;
+ unsigned int len, bios;
len = min_t(sector_t, ci->sector_count,
max_io_len_target_boundary(ti, dm_target_offset(ti, ci->sector)));
@@ -1601,7 +1600,7 @@ static bool is_abnormal_io(struct bio *bio)
static blk_status_t __process_abnormal_io(struct clone_info *ci,
struct dm_target *ti)
{
- unsigned num_bios = 0;
+ unsigned int num_bios = 0;
switch (bio_op(ci->bio)) {
case REQ_OP_DISCARD:
@@ -1679,7 +1678,7 @@ static blk_status_t __split_and_process_bio(struct clone_info *ci)
{
struct bio *clone;
struct dm_target *ti;
- unsigned len;
+ unsigned int len;
ti = dm_table_find_target(ci->map, ci->sector);
if (unlikely(!ti))
@@ -2376,7 +2375,7 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
struct mapped_device *dm_get_md(dev_t dev)
{
struct mapped_device *md;
- unsigned minor = MINOR(dev);
+ unsigned int minor = MINOR(dev);
if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
return NULL;
@@ -2659,7 +2658,7 @@ static void unlock_fs(struct mapped_device *md)
* are being added to md->deferred list.
*/
static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
- unsigned suspend_flags, unsigned int task_state,
+ unsigned int suspend_flags, unsigned int task_state,
int dmf_suspended_flag)
{
bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
@@ -2766,7 +2765,7 @@ static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
*
* To abort suspend, start the request_queue.
*/
-int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
+int dm_suspend(struct mapped_device *md, unsigned int suspend_flags)
{
struct dm_table *map = NULL;
int r = 0;
@@ -2868,7 +2867,7 @@ int dm_resume(struct mapped_device *md)
* It may be used only from the kernel.
*/
-static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_flags)
+static void __dm_internal_suspend(struct mapped_device *md, unsigned int suspend_flags)
{
struct dm_table *map = NULL;
@@ -2970,10 +2969,10 @@ EXPORT_SYMBOL_GPL(dm_internal_resume_fast);
* Event notification.
*---------------------------------------------------------------*/
int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
- unsigned cookie, bool need_resize_uevent)
+ unsigned int cookie, bool need_resize_uevent)
{
int r;
- unsigned noio_flag;
+ unsigned int noio_flag;
char udev_cookie[DM_COOKIE_LENGTH];
char *envp[3] = { NULL, NULL, NULL };
char **envpp = envp;
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index a9a3ffcad084..a7917df09caf 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -203,7 +203,7 @@ int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode,
void dm_put_table_device(struct mapped_device *md, struct dm_dev *d);
int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
- unsigned cookie, bool need_resize_uevent);
+ unsigned int cookie, bool need_resize_uevent);
void dm_internal_suspend(struct mapped_device *md);
void dm_internal_resume(struct mapped_device *md);
@@ -222,6 +222,6 @@ void dm_free_md_mempools(struct dm_md_mempools *pools);
/*
* Various helpers
*/
-unsigned dm_get_reserved_bio_based_ios(void);
+unsigned int dm_get_reserved_bio_based_ios(void);
#endif
diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c
index 3a963d783a86..eff9b41869f2 100644
--- a/drivers/md/persistent-data/dm-array.c
+++ b/drivers/md/persistent-data/dm-array.c
@@ -68,8 +68,8 @@ static int array_block_check(struct dm_block_validator *v,
CSUM_XOR));
if (csum_disk != bh_le->csum) {
DMERR_LIMIT("array_block_check failed: csum %u != wanted %u",
- (unsigned) le32_to_cpu(csum_disk),
- (unsigned) le32_to_cpu(bh_le->csum));
+ (unsigned int) le32_to_cpu(csum_disk),
+ (unsigned int) le32_to_cpu(bh_le->csum));
return -EILSEQ;
}
@@ -94,7 +94,7 @@ static struct dm_block_validator array_validator = {
* index - The index into _this_ specific block.
*/
static void *element_at(struct dm_array_info *info, struct array_block *ab,
- unsigned index)
+ unsigned int index)
{
unsigned char *entry = (unsigned char *) (ab + 1);
@@ -108,9 +108,9 @@ static void *element_at(struct dm_array_info *info, struct array_block *ab,
* in an array block.
*/
static void on_entries(struct dm_array_info *info, struct array_block *ab,
- void (*fn)(void *, const void *, unsigned))
+ void (*fn)(void *, const void *, unsigned int))
{
- unsigned nr_entries = le32_to_cpu(ab->nr_entries);
+ unsigned int nr_entries = le32_to_cpu(ab->nr_entries);
fn(info->value_type.context, element_at(info, ab, 0), nr_entries);
}
@@ -171,7 +171,7 @@ static int alloc_ablock(struct dm_array_info *info, size_t size_of_block,
* the current number of entries.
*/
static void fill_ablock(struct dm_array_info *info, struct array_block *ab,
- const void *value, unsigned new_nr)
+ const void *value, unsigned int new_nr)
{
uint32_t nr_entries, delta, i;
struct dm_btree_value_type *vt = &info->value_type;
@@ -194,7 +194,7 @@ static void fill_ablock(struct dm_array_info *info, struct array_block *ab,
* entries.
*/
static void trim_ablock(struct dm_array_info *info, struct array_block *ab,
- unsigned new_nr)
+ unsigned int new_nr)
{
uint32_t nr_entries, delta;
struct dm_btree_value_type *vt = &info->value_type;
@@ -247,7 +247,7 @@ static void unlock_ablock(struct dm_array_info *info, struct dm_block *block)
* / max_entries).
*/
static int lookup_ablock(struct dm_array_info *info, dm_block_t root,
- unsigned index, struct dm_block **block,
+ unsigned int index, struct dm_block **block,
struct array_block **ab)
{
int r;
@@ -295,7 +295,7 @@ static int __shadow_ablock(struct dm_array_info *info, dm_block_t b,
* The shadow op will often be a noop. Only insert if it really
* copied data.
*/
-static int __reinsert_ablock(struct dm_array_info *info, unsigned index,
+static int __reinsert_ablock(struct dm_array_info *info, unsigned int index,
struct dm_block *block, dm_block_t b,
dm_block_t *root)
{
@@ -321,7 +321,7 @@ static int __reinsert_ablock(struct dm_array_info *info, unsigned index,
* for both the current root block, and the new one.
*/
static int shadow_ablock(struct dm_array_info *info, dm_block_t *root,
- unsigned index, struct dm_block **block,
+ unsigned int index, struct dm_block **block,
struct array_block **ab)
{
int r;
@@ -346,7 +346,7 @@ static int shadow_ablock(struct dm_array_info *info, dm_block_t *root,
*/
static int insert_new_ablock(struct dm_array_info *info, size_t size_of_block,
uint32_t max_entries,
- unsigned block_index, uint32_t nr,
+ unsigned int block_index, uint32_t nr,
const void *value, dm_block_t *root)
{
int r;
@@ -365,8 +365,8 @@ static int insert_new_ablock(struct dm_array_info *info, size_t size_of_block,
}
static int insert_full_ablocks(struct dm_array_info *info, size_t size_of_block,
- unsigned begin_block, unsigned end_block,
- unsigned max_entries, const void *value,
+ unsigned int begin_block, unsigned int end_block,
+ unsigned int max_entries, const void *value,
dm_block_t *root)
{
int r = 0;
@@ -402,20 +402,20 @@ struct resize {
/*
* Maximum nr entries in an array block.
*/
- unsigned max_entries;
+ unsigned int max_entries;
/*
* nr of completely full blocks in the array.
*
* 'old' refers to before the resize, 'new' after.
*/
- unsigned old_nr_full_blocks, new_nr_full_blocks;
+ unsigned int old_nr_full_blocks, new_nr_full_blocks;
/*
* Number of entries in the final block. 0 iff only full blocks in
* the array.
*/
- unsigned old_nr_entries_in_last_block, new_nr_entries_in_last_block;
+ unsigned int old_nr_entries_in_last_block, new_nr_entries_in_last_block;
/*
* The default value used when growing the array.
@@ -430,8 +430,8 @@ struct resize {
* begin_index - the index of the first array block to remove.
* end_index - the one-past-the-end value. ie. this block is not removed.
*/
-static int drop_blocks(struct resize *resize, unsigned begin_index,
- unsigned end_index)
+static int drop_blocks(struct resize *resize, unsigned int begin_index,
+ unsigned int end_index)
{
int r;
@@ -449,8 +449,8 @@ static int drop_blocks(struct resize *resize, unsigned begin_index,
/*
* Calculates how many blocks are needed for the array.
*/
-static unsigned total_nr_blocks_needed(unsigned nr_full_blocks,
- unsigned nr_entries_in_last_block)
+static unsigned int total_nr_blocks_needed(unsigned int nr_full_blocks,
+ unsigned int nr_entries_in_last_block)
{
return nr_full_blocks + (nr_entries_in_last_block ? 1 : 0);
}
@@ -461,7 +461,7 @@ static unsigned total_nr_blocks_needed(unsigned nr_full_blocks,
static int shrink(struct resize *resize)
{
int r;
- unsigned begin, end;
+ unsigned int begin, end;
struct dm_block *block;
struct array_block *ab;
@@ -527,7 +527,7 @@ static int grow_add_tail_block(struct resize *resize)
static int grow_needs_more_blocks(struct resize *resize)
{
int r;
- unsigned old_nr_blocks = resize->old_nr_full_blocks;
+ unsigned int old_nr_blocks = resize->old_nr_full_blocks;
if (resize->old_nr_entries_in_last_block > 0) {
old_nr_blocks++;
@@ -569,11 +569,11 @@ static int grow(struct resize *resize)
* These are the value_type functions for the btree elements, which point
* to array blocks.
*/
-static void block_inc(void *context, const void *value, unsigned count)
+static void block_inc(void *context, const void *value, unsigned int count)
{
const __le64 *block_le = value;
struct dm_array_info *info = context;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, block_le++)
dm_tm_inc(info->btree_info.tm, le64_to_cpu(*block_le));
@@ -618,9 +618,9 @@ static void __block_dec(void *context, const void *value)
dm_tm_dec(info->btree_info.tm, b);
}
-static void block_dec(void *context, const void *value, unsigned count)
+static void block_dec(void *context, const void *value, unsigned int count)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, value += sizeof(__le64))
__block_dec(context, value);
}
@@ -700,10 +700,11 @@ int dm_array_resize(struct dm_array_info *info, dm_block_t root,
EXPORT_SYMBOL_GPL(dm_array_resize);
static int populate_ablock_with_values(struct dm_array_info *info, struct array_block *ab,
- value_fn fn, void *context, unsigned base, unsigned new_nr)
+ value_fn fn, void *context,
+ unsigned int base, unsigned int new_nr)
{
int r;
- unsigned i;
+ unsigned int i;
struct dm_btree_value_type *vt = &info->value_type;
BUG_ON(le32_to_cpu(ab->nr_entries));
@@ -728,7 +729,7 @@ int dm_array_new(struct dm_array_info *info, dm_block_t *root,
int r;
struct dm_block *block;
struct array_block *ab;
- unsigned block_index, end_block, size_of_block, max_entries;
+ unsigned int block_index, end_block, size_of_block, max_entries;
r = dm_array_empty(info, root);
if (r)
@@ -776,7 +777,7 @@ int dm_array_get_value(struct dm_array_info *info, dm_block_t root,
struct dm_block *block;
struct array_block *ab;
size_t size_of_block;
- unsigned entry, max_entries;
+ unsigned int entry, max_entries;
size_of_block = dm_bm_block_size(dm_tm_get_bm(info->btree_info.tm));
max_entries = calc_max_entries(info->value_type.size, size_of_block);
@@ -804,8 +805,8 @@ static int array_set_value(struct dm_array_info *info, dm_block_t root,
struct dm_block *block;
struct array_block *ab;
size_t size_of_block;
- unsigned max_entries;
- unsigned entry;
+ unsigned int max_entries;
+ unsigned int entry;
void *old_value;
struct dm_btree_value_type *vt = &info->value_type;
@@ -861,9 +862,9 @@ static int walk_ablock(void *context, uint64_t *keys, void *leaf)
struct walk_info *wi = context;
int r;
- unsigned i;
+ unsigned int i;
__le64 block_le;
- unsigned nr_entries, max_entries;
+ unsigned int nr_entries, max_entries;
struct dm_block *block;
struct array_block *ab;
diff --git a/drivers/md/persistent-data/dm-array.h b/drivers/md/persistent-data/dm-array.h
index d7d2d579c662..b6c7077c7359 100644
--- a/drivers/md/persistent-data/dm-array.h
+++ b/drivers/md/persistent-data/dm-array.h
@@ -198,7 +198,7 @@ struct dm_array_cursor {
struct dm_block *block;
struct array_block *ab;
- unsigned index;
+ unsigned int index;
};
int dm_array_cursor_begin(struct dm_array_info *info,
diff --git a/drivers/md/persistent-data/dm-bitset.c b/drivers/md/persistent-data/dm-bitset.c
index b7208d82e748..625d93498cdd 100644
--- a/drivers/md/persistent-data/dm-bitset.c
+++ b/drivers/md/persistent-data/dm-bitset.c
@@ -41,7 +41,7 @@ EXPORT_SYMBOL_GPL(dm_bitset_empty);
struct packer_context {
bit_value_fn fn;
- unsigned nr_bits;
+ unsigned int nr_bits;
void *context;
};
@@ -49,7 +49,7 @@ static int pack_bits(uint32_t index, void *value, void *context)
{
int r;
struct packer_context *p = context;
- unsigned bit, nr = min(64u, p->nr_bits - (index * 64));
+ unsigned int bit, nr = min(64u, p->nr_bits - (index * 64));
uint64_t word = 0;
bool bv;
@@ -147,7 +147,7 @@ static int get_array_entry(struct dm_disk_bitset *info, dm_block_t root,
uint32_t index, dm_block_t *new_root)
{
int r;
- unsigned array_index = index / BITS_PER_ARRAY_ENTRY;
+ unsigned int array_index = index / BITS_PER_ARRAY_ENTRY;
if (info->current_index_set) {
if (info->current_index == array_index)
@@ -165,7 +165,7 @@ int dm_bitset_set_bit(struct dm_disk_bitset *info, dm_block_t root,
uint32_t index, dm_block_t *new_root)
{
int r;
- unsigned b = index % BITS_PER_ARRAY_ENTRY;
+ unsigned int b = index % BITS_PER_ARRAY_ENTRY;
r = get_array_entry(info, root, index, new_root);
if (r)
@@ -182,7 +182,7 @@ int dm_bitset_clear_bit(struct dm_disk_bitset *info, dm_block_t root,
uint32_t index, dm_block_t *new_root)
{
int r;
- unsigned b = index % BITS_PER_ARRAY_ENTRY;
+ unsigned int b = index % BITS_PER_ARRAY_ENTRY;
r = get_array_entry(info, root, index, new_root);
if (r)
@@ -199,7 +199,7 @@ int dm_bitset_test_bit(struct dm_disk_bitset *info, dm_block_t root,
uint32_t index, dm_block_t *new_root, bool *result)
{
int r;
- unsigned b = index % BITS_PER_ARRAY_ENTRY;
+ unsigned int b = index % BITS_PER_ARRAY_ENTRY;
r = get_array_entry(info, root, index, new_root);
if (r)
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
index 11935864f50f..1f40100908d7 100644
--- a/drivers/md/persistent-data/dm-block-manager.c
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -57,10 +57,10 @@ struct waiter {
int wants_write;
};
-static unsigned __find_holder(struct block_lock *lock,
+static unsigned int __find_holder(struct block_lock *lock,
struct task_struct *task)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < MAX_HOLDERS; i++)
if (lock->holders[i] == task)
@@ -73,7 +73,7 @@ static unsigned __find_holder(struct block_lock *lock,
/* call this *after* you increment lock->count */
static void __add_holder(struct block_lock *lock, struct task_struct *task)
{
- unsigned h = __find_holder(lock, NULL);
+ unsigned int h = __find_holder(lock, NULL);
#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
struct stack_store *t;
#endif
@@ -90,14 +90,14 @@ static void __add_holder(struct block_lock *lock, struct task_struct *task)
/* call this *before* you decrement lock->count */
static void __del_holder(struct block_lock *lock, struct task_struct *task)
{
- unsigned h = __find_holder(lock, task);
+ unsigned int h = __find_holder(lock, task);
lock->holders[h] = NULL;
put_task_struct(task);
}
static int __check_holder(struct block_lock *lock)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < MAX_HOLDERS; i++) {
if (lock->holders[i] == current) {
@@ -376,8 +376,8 @@ struct dm_block_manager {
};
struct dm_block_manager *dm_block_manager_create(struct block_device *bdev,
- unsigned block_size,
- unsigned max_held_per_thread)
+ unsigned int block_size,
+ unsigned int max_held_per_thread)
{
int r;
struct dm_block_manager *bm;
@@ -415,7 +415,7 @@ void dm_block_manager_destroy(struct dm_block_manager *bm)
}
EXPORT_SYMBOL_GPL(dm_block_manager_destroy);
-unsigned dm_bm_block_size(struct dm_block_manager *bm)
+unsigned int dm_bm_block_size(struct dm_block_manager *bm)
{
return dm_bufio_get_block_size(bm->bufio);
}
diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h
index e728937f376a..58a23b8ec190 100644
--- a/drivers/md/persistent-data/dm-block-manager.h
+++ b/drivers/md/persistent-data/dm-block-manager.h
@@ -32,11 +32,11 @@ void *dm_block_data(struct dm_block *b);
*/
struct dm_block_manager;
struct dm_block_manager *dm_block_manager_create(
- struct block_device *bdev, unsigned block_size,
- unsigned max_held_per_thread);
+ struct block_device *bdev, unsigned int block_size,
+ unsigned int max_held_per_thread);
void dm_block_manager_destroy(struct dm_block_manager *bm);
-unsigned dm_bm_block_size(struct dm_block_manager *bm);
+unsigned int dm_bm_block_size(struct dm_block_manager *bm);
dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm);
/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c
index 4ead31e0d8ce..ac213138b021 100644
--- a/drivers/md/persistent-data/dm-btree-remove.c
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -124,10 +124,10 @@ static int node_copy(struct btree_node *left, struct btree_node *right, int shif
/*
* Delete a specific entry from a leaf node.
*/
-static void delete_at(struct btree_node *n, unsigned index)
+static void delete_at(struct btree_node *n, unsigned int index)
{
- unsigned nr_entries = le32_to_cpu(n->header.nr_entries);
- unsigned nr_to_copy = nr_entries - (index + 1);
+ unsigned int nr_entries = le32_to_cpu(n->header.nr_entries);
+ unsigned int nr_to_copy = nr_entries - (index + 1);
uint32_t value_size = le32_to_cpu(n->header.value_size);
BUG_ON(index >= nr_entries);
@@ -144,20 +144,20 @@ static void delete_at(struct btree_node *n, unsigned index)
n->header.nr_entries = cpu_to_le32(nr_entries - 1);
}
-static unsigned merge_threshold(struct btree_node *n)
+static unsigned int merge_threshold(struct btree_node *n)
{
return le32_to_cpu(n->header.max_entries) / 3;
}
struct child {
- unsigned index;
+ unsigned int index;
struct dm_block *block;
struct btree_node *n;
};
static int init_child(struct dm_btree_info *info, struct dm_btree_value_type *vt,
struct btree_node *parent,
- unsigned index, struct child *result)
+ unsigned int index, struct child *result)
{
int r, inc;
dm_block_t root;
@@ -263,7 +263,7 @@ static int __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
/*
* Rebalance.
*/
- unsigned target_left = (nr_left + nr_right) / 2;
+ unsigned int target_left = (nr_left + nr_right) / 2;
ret = shift(left, right, nr_left - target_left);
if (ret)
return ret;
@@ -273,7 +273,7 @@ static int __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
}
static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
- struct dm_btree_value_type *vt, unsigned left_index)
+ struct dm_btree_value_type *vt, unsigned int left_index)
{
int r;
struct btree_node *parent;
@@ -310,7 +310,7 @@ static int delete_center_node(struct dm_btree_info *info, struct btree_node *par
uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
{
uint32_t max_entries = le32_to_cpu(left->header.max_entries);
- unsigned shift = min(max_entries - nr_left, nr_center);
+ unsigned int shift = min(max_entries - nr_left, nr_center);
if (nr_left + shift > max_entries) {
DMERR("node shift out of bounds");
@@ -351,10 +351,10 @@ static int redistribute3(struct dm_btree_info *info, struct btree_node *parent,
{
int s, ret;
uint32_t max_entries = le32_to_cpu(left->header.max_entries);
- unsigned total = nr_left + nr_center + nr_right;
- unsigned target_right = total / 3;
- unsigned remainder = (target_right * 3) != total;
- unsigned target_left = target_right + remainder;
+ unsigned int total = nr_left + nr_center + nr_right;
+ unsigned int target_right = total / 3;
+ unsigned int remainder = (target_right * 3) != total;
+ unsigned int target_left = target_right + remainder;
BUG_ON(target_left > max_entries);
BUG_ON(target_right > max_entries);
@@ -422,7 +422,7 @@ static int __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
- unsigned threshold = merge_threshold(left) * 4 + 1;
+ unsigned int threshold = merge_threshold(left) * 4 + 1;
if ((left->header.max_entries != center->header.max_entries) ||
(center->header.max_entries != right->header.max_entries)) {
@@ -440,7 +440,7 @@ static int __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
}
static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
- struct dm_btree_value_type *vt, unsigned left_index)
+ struct dm_btree_value_type *vt, unsigned int left_index)
{
int r;
struct btree_node *parent = dm_block_data(shadow_current(s));
@@ -519,7 +519,7 @@ static int rebalance_children(struct shadow_spine *s,
return r;
}
-static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index)
+static int do_leaf(struct btree_node *n, uint64_t key, unsigned int *index)
{
int i = lower_bound(n, key);
@@ -539,7 +539,7 @@ static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index)
*/
static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
struct dm_btree_value_type *vt, dm_block_t root,
- uint64_t key, unsigned *index)
+ uint64_t key, unsigned int *index)
{
int i = *index, r;
struct btree_node *n;
@@ -589,7 +589,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, dm_block_t *new_root)
{
- unsigned level, last_level = info->levels - 1;
+ unsigned int level, last_level = info->levels - 1;
int index = 0, r = 0;
struct shadow_spine spine;
struct btree_node *n;
@@ -601,7 +601,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
r = remove_raw(&spine, info,
(level == last_level ?
&info->value_type : &le64_vt),
- root, keys[level], (unsigned *)&index);
+ root, keys[level], (unsigned int *)&index);
if (r < 0)
break;
@@ -685,9 +685,9 @@ static int remove_nearest(struct shadow_spine *s, struct dm_btree_info *info,
static int remove_one(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, uint64_t end_key,
- dm_block_t *new_root, unsigned *nr_removed)
+ dm_block_t *new_root, unsigned int *nr_removed)
{
- unsigned level, last_level = info->levels - 1;
+ unsigned int level, last_level = info->levels - 1;
int index = 0, r = 0;
struct shadow_spine spine;
struct btree_node *n;
@@ -698,7 +698,7 @@ static int remove_one(struct dm_btree_info *info, dm_block_t root,
init_shadow_spine(&spine, info);
for (level = 0; level < last_level; level++) {
r = remove_raw(&spine, info, &le64_vt,
- root, keys[level], (unsigned *) &index);
+ root, keys[level], (unsigned int *) &index);
if (r < 0)
goto out;
@@ -742,7 +742,7 @@ static int remove_one(struct dm_btree_info *info, dm_block_t root,
int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root,
uint64_t *first_key, uint64_t end_key,
- dm_block_t *new_root, unsigned *nr_removed)
+ dm_block_t *new_root, unsigned int *nr_removed)
{
int r;
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c
index e653458888a7..45a39d4f1c10 100644
--- a/drivers/md/persistent-data/dm-btree-spine.c
+++ b/drivers/md/persistent-data/dm-btree-spine.c
@@ -234,12 +234,12 @@ dm_block_t shadow_root(struct shadow_spine *s)
return s->root;
}
-static void le64_inc(void *context, const void *value_le, unsigned count)
+static void le64_inc(void *context, const void *value_le, unsigned int count)
{
dm_tm_with_runs(context, value_le, count, dm_tm_inc_range);
}
-static void le64_dec(void *context, const void *value_le, unsigned count)
+static void le64_dec(void *context, const void *value_le, unsigned int count)
{
dm_tm_with_runs(context, value_le, count, dm_tm_dec_range);
}
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
index 5ce64e93aae7..1cc783d7030d 100644
--- a/drivers/md/persistent-data/dm-btree.c
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -23,8 +23,8 @@ static void memcpy_disk(void *dest, const void *src, size_t len)
__dm_unbless_for_disk(src);
}
-static void array_insert(void *base, size_t elt_size, unsigned nr_elts,
- unsigned index, void *elt)
+static void array_insert(void *base, size_t elt_size, unsigned int nr_elts,
+ unsigned int index, void *elt)
__dm_written_to_disk(elt)
{
if (index < nr_elts)
@@ -80,7 +80,7 @@ void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
vt->inc(vt->context, value_ptr(n, 0), nr_entries);
}
-static int insert_at(size_t value_size, struct btree_node *node, unsigned index,
+static int insert_at(size_t value_size, struct btree_node *node, unsigned int index,
uint64_t key, void *value)
__dm_written_to_disk(value)
{
@@ -162,9 +162,9 @@ EXPORT_SYMBOL_GPL(dm_btree_empty);
struct frame {
struct dm_block *b;
struct btree_node *n;
- unsigned level;
- unsigned nr_children;
- unsigned current_child;
+ unsigned int level;
+ unsigned int nr_children;
+ unsigned int current_child;
};
struct del_stack {
@@ -193,7 +193,7 @@ static int unprocessed_frames(struct del_stack *s)
static void prefetch_children(struct del_stack *s, struct frame *f)
{
- unsigned i;
+ unsigned int i;
struct dm_block_manager *bm = dm_tm_get_bm(s->tm);
for (i = 0; i < f->nr_children; i++)
@@ -205,7 +205,7 @@ static bool is_internal_level(struct dm_btree_info *info, struct frame *f)
return f->level < (info->levels - 1);
}
-static int push_frame(struct del_stack *s, dm_block_t b, unsigned level)
+static int push_frame(struct del_stack *s, dm_block_t b, unsigned int level)
{
int r;
uint32_t ref_count;
@@ -371,7 +371,7 @@ static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, void *value_le)
{
- unsigned level, last_level = info->levels - 1;
+ unsigned int level, last_level = info->levels - 1;
int r = -ENODATA;
uint64_t rkey;
__le64 internal_value_le;
@@ -467,7 +467,7 @@ static int dm_btree_lookup_next_single(struct dm_btree_info *info, dm_block_t ro
int dm_btree_lookup_next(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, uint64_t *rkey, void *value_le)
{
- unsigned level;
+ unsigned int level;
int r = -ENODATA;
__le64 internal_value_le;
struct ro_spine spine;
@@ -502,9 +502,9 @@ EXPORT_SYMBOL_GPL(dm_btree_lookup_next);
* Copies entries from one region of a btree node to another. The regions
* must not overlap.
*/
-static void copy_entries(struct btree_node *dest, unsigned dest_offset,
- struct btree_node *src, unsigned src_offset,
- unsigned count)
+static void copy_entries(struct btree_node *dest, unsigned int dest_offset,
+ struct btree_node *src, unsigned int src_offset,
+ unsigned int count)
{
size_t value_size = le32_to_cpu(dest->header.value_size);
memcpy(dest->keys + dest_offset, src->keys + src_offset, count * sizeof(uint64_t));
@@ -515,9 +515,9 @@ static void copy_entries(struct btree_node *dest, unsigned dest_offset,
* Moves entries from one region fo a btree node to another. The regions
* may overlap.
*/
-static void move_entries(struct btree_node *dest, unsigned dest_offset,
- struct btree_node *src, unsigned src_offset,
- unsigned count)
+static void move_entries(struct btree_node *dest, unsigned int dest_offset,
+ struct btree_node *src, unsigned int src_offset,
+ unsigned int count)
{
size_t value_size = le32_to_cpu(dest->header.value_size);
memmove(dest->keys + dest_offset, src->keys + src_offset, count * sizeof(uint64_t));
@@ -528,7 +528,7 @@ static void move_entries(struct btree_node *dest, unsigned dest_offset,
* Erases the first 'count' entries of a btree node, shifting following
* entries down into their place.
*/
-static void shift_down(struct btree_node *n, unsigned count)
+static void shift_down(struct btree_node *n, unsigned int count)
{
move_entries(n, 0, n, count, le32_to_cpu(n->header.nr_entries) - count);
}
@@ -537,7 +537,7 @@ static void shift_down(struct btree_node *n, unsigned count)
* Moves entries in a btree node up 'count' places, making space for
* new entries at the start of the node.
*/
-static void shift_up(struct btree_node *n, unsigned count)
+static void shift_up(struct btree_node *n, unsigned int count)
{
move_entries(n, count, n, 0, le32_to_cpu(n->header.nr_entries));
}
@@ -548,18 +548,18 @@ static void shift_up(struct btree_node *n, unsigned count)
*/
static void redistribute2(struct btree_node *left, struct btree_node *right)
{
- unsigned nr_left = le32_to_cpu(left->header.nr_entries);
- unsigned nr_right = le32_to_cpu(right->header.nr_entries);
- unsigned total = nr_left + nr_right;
- unsigned target_left = total / 2;
- unsigned target_right = total - target_left;
+ unsigned int nr_left = le32_to_cpu(left->header.nr_entries);
+ unsigned int nr_right = le32_to_cpu(right->header.nr_entries);
+ unsigned int total = nr_left + nr_right;
+ unsigned int target_left = total / 2;
+ unsigned int target_right = total - target_left;
if (nr_left < target_left) {
- unsigned delta = target_left - nr_left;
+ unsigned int delta = target_left - nr_left;
copy_entries(left, nr_left, right, 0, delta);
shift_down(right, delta);
} else if (nr_left > target_left) {
- unsigned delta = nr_left - target_left;
+ unsigned int delta = nr_left - target_left;
if (nr_right)
shift_up(right, delta);
copy_entries(right, 0, left, target_left, delta);
@@ -576,10 +576,10 @@ static void redistribute2(struct btree_node *left, struct btree_node *right)
static void redistribute3(struct btree_node *left, struct btree_node *center,
struct btree_node *right)
{
- unsigned nr_left = le32_to_cpu(left->header.nr_entries);
- unsigned nr_center = le32_to_cpu(center->header.nr_entries);
- unsigned nr_right = le32_to_cpu(right->header.nr_entries);
- unsigned total, target_left, target_center, target_right;
+ unsigned int nr_left = le32_to_cpu(left->header.nr_entries);
+ unsigned int nr_center = le32_to_cpu(center->header.nr_entries);
+ unsigned int nr_right = le32_to_cpu(right->header.nr_entries);
+ unsigned int total, target_left, target_center, target_right;
BUG_ON(nr_center);
@@ -589,19 +589,19 @@ static void redistribute3(struct btree_node *left, struct btree_node *center,
target_right = (total - target_left - target_center);
if (nr_left < target_left) {
- unsigned left_short = target_left - nr_left;
+ unsigned int left_short = target_left - nr_left;
copy_entries(left, nr_left, right, 0, left_short);
copy_entries(center, 0, right, left_short, target_center);
shift_down(right, nr_right - target_right);
} else if (nr_left < (target_left + target_center)) {
- unsigned left_to_center = nr_left - target_left;
+ unsigned int left_to_center = nr_left - target_left;
copy_entries(center, 0, left, target_left, left_to_center);
copy_entries(center, left_to_center, right, 0, target_center - left_to_center);
shift_down(right, nr_right - target_right);
} else {
- unsigned right_short = target_right - nr_right;
+ unsigned int right_short = target_right - nr_right;
shift_up(right, right_short);
copy_entries(right, 0, left, nr_left - right_short, right_short);
copy_entries(center, 0, left, target_left, nr_left - target_left);
@@ -642,7 +642,7 @@ static void redistribute3(struct btree_node *left, struct btree_node *center,
*
* Where A* is a shadow of A.
*/
-static int split_one_into_two(struct shadow_spine *s, unsigned parent_index,
+static int split_one_into_two(struct shadow_spine *s, unsigned int parent_index,
struct dm_btree_value_type *vt, uint64_t key)
{
int r;
@@ -696,7 +696,7 @@ static int split_one_into_two(struct shadow_spine *s, unsigned parent_index,
* to the new shadow.
*/
static int shadow_child(struct dm_btree_info *info, struct dm_btree_value_type *vt,
- struct btree_node *parent, unsigned index,
+ struct btree_node *parent, unsigned int index,
struct dm_block **result)
{
int r, inc;
@@ -725,11 +725,11 @@ static int shadow_child(struct dm_btree_info *info, struct dm_btree_value_type *
* Splits two nodes into three. This is more work, but results in fuller
* nodes, so saves metadata space.
*/
-static int split_two_into_three(struct shadow_spine *s, unsigned parent_index,
+static int split_two_into_three(struct shadow_spine *s, unsigned int parent_index,
struct dm_btree_value_type *vt, uint64_t key)
{
int r;
- unsigned middle_index;
+ unsigned int middle_index;
struct dm_block *left, *middle, *right, *parent;
struct btree_node *ln, *rn, *mn, *pn;
__le64 location;
@@ -830,7 +830,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
{
int r;
size_t size;
- unsigned nr_left, nr_right;
+ unsigned int nr_left, nr_right;
struct dm_block *left, *right, *new_parent;
struct btree_node *pn, *ln, *rn;
__le64 val;
@@ -904,7 +904,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
* Redistributes a node's entries with its left sibling.
*/
static int rebalance_left(struct shadow_spine *s, struct dm_btree_value_type *vt,
- unsigned parent_index, uint64_t key)
+ unsigned int parent_index, uint64_t key)
{
int r;
struct dm_block *sib;
@@ -933,7 +933,7 @@ static int rebalance_left(struct shadow_spine *s, struct dm_btree_value_type *vt
* Redistributes a nodes entries with its right sibling.
*/
static int rebalance_right(struct shadow_spine *s, struct dm_btree_value_type *vt,
- unsigned parent_index, uint64_t key)
+ unsigned int parent_index, uint64_t key)
{
int r;
struct dm_block *sib;
@@ -961,10 +961,10 @@ static int rebalance_right(struct shadow_spine *s, struct dm_btree_value_type *v
/*
* Returns the number of spare entries in a node.
*/
-static int get_node_free_space(struct dm_btree_info *info, dm_block_t b, unsigned *space)
+static int get_node_free_space(struct dm_btree_info *info, dm_block_t b, unsigned int *space)
{
int r;
- unsigned nr_entries;
+ unsigned int nr_entries;
struct dm_block *block;
struct btree_node *node;
@@ -990,12 +990,12 @@ static int get_node_free_space(struct dm_btree_info *info, dm_block_t b, unsigne
*/
#define SPACE_THRESHOLD 8
static int rebalance_or_split(struct shadow_spine *s, struct dm_btree_value_type *vt,
- unsigned parent_index, uint64_t key)
+ unsigned int parent_index, uint64_t key)
{
int r;
struct btree_node *parent = dm_block_data(shadow_parent(s));
- unsigned nr_parent = le32_to_cpu(parent->header.nr_entries);
- unsigned free_space;
+ unsigned int nr_parent = le32_to_cpu(parent->header.nr_entries);
+ unsigned int free_space;
int left_shared = 0, right_shared = 0;
/* Should we move entries to the left sibling? */
@@ -1080,7 +1080,7 @@ static bool has_space_for_insert(struct btree_node *node, uint64_t key)
static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
struct dm_btree_value_type *vt,
- uint64_t key, unsigned *index)
+ uint64_t key, unsigned int *index)
{
int r, i = *index, top = 1;
struct btree_node *node;
@@ -1214,7 +1214,7 @@ int btree_get_overwrite_leaf(struct dm_btree_info *info, dm_block_t root,
}
static bool need_insert(struct btree_node *node, uint64_t *keys,
- unsigned level, unsigned index)
+ unsigned int level, unsigned int index)
{
return ((index >= le32_to_cpu(node->header.nr_entries)) ||
(le64_to_cpu(node->keys[index]) != keys[level]));
@@ -1226,7 +1226,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root,
__dm_written_to_disk(value)
{
int r;
- unsigned level, index = -1, last_level = info->levels - 1;
+ unsigned int level, index = -1, last_level = info->levels - 1;
dm_block_t block = root;
struct shadow_spine spine;
struct btree_node *n;
@@ -1412,7 +1412,7 @@ static int walk_node(struct dm_btree_info *info, dm_block_t block,
void *context)
{
int r;
- unsigned i, nr;
+ unsigned int i, nr;
struct dm_block *node;
struct btree_node *n;
uint64_t keys;
@@ -1455,7 +1455,7 @@ EXPORT_SYMBOL_GPL(dm_btree_walk);
static void prefetch_values(struct dm_btree_cursor *c)
{
- unsigned i, nr;
+ unsigned int i, nr;
__le64 value_le;
struct cursor_node *n = c->nodes + c->depth - 1;
struct btree_node *bn = dm_block_data(n->b);
diff --git a/drivers/md/persistent-data/dm-btree.h b/drivers/md/persistent-data/dm-btree.h
index d2ae5aa4d00b..5566e7c32e82 100644
--- a/drivers/md/persistent-data/dm-btree.h
+++ b/drivers/md/persistent-data/dm-btree.h
@@ -58,14 +58,14 @@ struct dm_btree_value_type {
* somewhere.) This method is _not_ called for insertion of a new
* value: It is assumed the ref count is already 1.
*/
- void (*inc)(void *context, const void *value, unsigned count);
+ void (*inc)(void *context, const void *value, unsigned int count);
/*
* These values are being deleted. The btree takes care of freeing
* the memory pointed to by @value. Often the del function just
* needs to decrement a reference counts somewhere.
*/
- void (*dec)(void *context, const void *value, unsigned count);
+ void (*dec)(void *context, const void *value, unsigned int count);
/*
* A test for equality between two values. When a value is
@@ -84,7 +84,7 @@ struct dm_btree_info {
/*
* Number of nested btrees. (Not the depth of a single tree.)
*/
- unsigned levels;
+ unsigned int levels;
struct dm_btree_value_type value_type;
};
@@ -149,7 +149,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
*/
int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, uint64_t end_key,
- dm_block_t *new_root, unsigned *nr_removed);
+ dm_block_t *new_root, unsigned int *nr_removed);
/*
* Returns < 0 on failure. Otherwise the number of key entries that have
@@ -188,7 +188,7 @@ int dm_btree_walk(struct dm_btree_info *info, dm_block_t root,
struct cursor_node {
struct dm_block *b;
- unsigned index;
+ unsigned int index;
};
struct dm_btree_cursor {
@@ -196,7 +196,7 @@ struct dm_btree_cursor {
dm_block_t root;
bool prefetch_leaves;
- unsigned depth;
+ unsigned int depth;
struct cursor_node nodes[DM_BTREE_CURSOR_MAX_DEPTH];
};
diff --git a/drivers/md/persistent-data/dm-persistent-data-internal.h b/drivers/md/persistent-data/dm-persistent-data-internal.h
index c49e26fff36c..b945a2be93fb 100644
--- a/drivers/md/persistent-data/dm-persistent-data-internal.h
+++ b/drivers/md/persistent-data/dm-persistent-data-internal.h
@@ -9,11 +9,11 @@
#include "dm-block-manager.h"
-static inline unsigned dm_hash_block(dm_block_t b, unsigned hash_mask)
+static inline unsigned int dm_hash_block(dm_block_t b, unsigned int hash_mask)
{
- const unsigned BIG_PRIME = 4294967291UL;
+ const unsigned int BIG_PRIME = 4294967291UL;
- return (((unsigned) b) * BIG_PRIME) & hash_mask;
+ return (((unsigned int) b) * BIG_PRIME) & hash_mask;
}
#endif /* _PERSISTENT_DATA_INTERNAL_H */
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
index bfbfa750e016..af800efed9f3 100644
--- a/drivers/md/persistent-data/dm-space-map-common.c
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -126,7 +126,7 @@ static void *dm_bitmap_data(struct dm_block *b)
#define WORD_MASK_HIGH 0xAAAAAAAAAAAAAAAAULL
-static unsigned dm_bitmap_word_used(void *addr, unsigned b)
+static unsigned int dm_bitmap_word_used(void *addr, unsigned int b)
{
__le64 *words_le = addr;
__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
@@ -137,11 +137,11 @@ static unsigned dm_bitmap_word_used(void *addr, unsigned b)
return !(~bits & mask);
}
-static unsigned sm_lookup_bitmap(void *addr, unsigned b)
+static unsigned int sm_lookup_bitmap(void *addr, unsigned int b)
{
__le64 *words_le = addr;
__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
- unsigned hi, lo;
+ unsigned int hi, lo;
b = (b & (ENTRIES_PER_WORD - 1)) << 1;
hi = !!test_bit_le(b, (void *) w_le);
@@ -149,7 +149,7 @@ static unsigned sm_lookup_bitmap(void *addr, unsigned b)
return (hi << 1) | lo;
}
-static void sm_set_bitmap(void *addr, unsigned b, unsigned val)
+static void sm_set_bitmap(void *addr, unsigned int b, unsigned int val)
{
__le64 *words_le = addr;
__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
@@ -167,8 +167,8 @@ static void sm_set_bitmap(void *addr, unsigned b, unsigned val)
__clear_bit_le(b + 1, (void *) w_le);
}
-static int sm_find_free(void *addr, unsigned begin, unsigned end,
- unsigned *result)
+static int sm_find_free(void *addr, unsigned int begin, unsigned int end,
+ unsigned int *result)
{
while (begin < end) {
if (!(begin & (ENTRIES_PER_WORD - 1)) &&
@@ -237,7 +237,7 @@ int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks)
{
int r;
dm_block_t i, nr_blocks, nr_indexes;
- unsigned old_blocks, blocks;
+ unsigned int old_blocks, blocks;
nr_blocks = ll->nr_blocks + extra_blocks;
old_blocks = dm_sector_div_up(ll->nr_blocks, ll->entries_per_block);
@@ -351,7 +351,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
for (i = index_begin; i < index_end; i++, begin = 0) {
struct dm_block *blk;
- unsigned position;
+ unsigned int position;
uint32_t bit_end;
r = ll->load_ie(ll, i, &ie_disk);
@@ -369,7 +369,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
bit_end = (i == index_end - 1) ? end : ll->entries_per_block;
r = sm_find_free(dm_bitmap_data(blk),
- max_t(unsigned, begin, le32_to_cpu(ie_disk.none_free_before)),
+ max_t(unsigned int, begin, le32_to_cpu(ie_disk.none_free_before)),
bit_end, &position);
if (r == -ENOSPC) {
/*
@@ -1097,7 +1097,7 @@ static inline int ie_cache_writeback(struct ll_disk *ll, struct ie_cache *iec)
&iec->index, &iec->ie, &ll->bitmap_root);
}
-static inline unsigned hash_index(dm_block_t index)
+static inline unsigned int hash_index(dm_block_t index)
{
return dm_hash_block(index, IE_CACHE_MASK);
}
@@ -1106,7 +1106,7 @@ static int disk_ll_load_ie(struct ll_disk *ll, dm_block_t index,
struct disk_index_entry *ie)
{
int r;
- unsigned h = hash_index(index);
+ unsigned int h = hash_index(index);
struct ie_cache *iec = ll->ie_cache + h;
if (iec->valid) {
@@ -1137,7 +1137,7 @@ static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
struct disk_index_entry *ie)
{
int r;
- unsigned h = hash_index(index);
+ unsigned int h = hash_index(index);
struct ie_cache *iec = ll->ie_cache + h;
ll->bitmap_index_changed = true;
@@ -1164,7 +1164,7 @@ static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
static int disk_ll_init_index(struct ll_disk *ll)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < IE_CACHE_SIZE; i++) {
struct ie_cache *iec = ll->ie_cache + i;
iec->valid = false;
@@ -1186,7 +1186,7 @@ static dm_block_t disk_ll_max_entries(struct ll_disk *ll)
static int disk_ll_commit(struct ll_disk *ll)
{
int r = 0;
- unsigned i;
+ unsigned int i;
for (i = 0; i < IE_CACHE_SIZE; i++) {
struct ie_cache *iec = ll->ie_cache + i;
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c
index 392ae26134a4..0d1fcdf29c83 100644
--- a/drivers/md/persistent-data/dm-space-map-metadata.c
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -94,8 +94,8 @@ struct block_op {
};
struct bop_ring_buffer {
- unsigned begin;
- unsigned end;
+ unsigned int begin;
+ unsigned int end;
struct block_op bops[MAX_RECURSIVE_ALLOCATIONS + 1];
};
@@ -110,9 +110,9 @@ static bool brb_empty(struct bop_ring_buffer *brb)
return brb->begin == brb->end;
}
-static unsigned brb_next(struct bop_ring_buffer *brb, unsigned old)
+static unsigned int brb_next(struct bop_ring_buffer *brb, unsigned int old)
{
- unsigned r = old + 1;
+ unsigned int r = old + 1;
return r >= ARRAY_SIZE(brb->bops) ? 0 : r;
}
@@ -120,7 +120,7 @@ static int brb_push(struct bop_ring_buffer *brb,
enum block_op_type type, dm_block_t b, dm_block_t e)
{
struct block_op *bop;
- unsigned next = brb_next(brb, brb->end);
+ unsigned int next = brb_next(brb, brb->end);
/*
* We don't allow the last bop to be filled, this way we can
@@ -171,8 +171,8 @@ struct sm_metadata {
dm_block_t begin;
- unsigned recursion_count;
- unsigned allocated_this_transaction;
+ unsigned int recursion_count;
+ unsigned int allocated_this_transaction;
struct bop_ring_buffer uncommitted;
struct threshold threshold;
@@ -300,9 +300,9 @@ static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b,
uint32_t *result)
{
int r;
- unsigned i;
+ unsigned int i;
struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
- unsigned adjustment = 0;
+ unsigned int adjustment = 0;
/*
* We may have some uncommitted adjustments to add. This list
@@ -340,7 +340,7 @@ static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm,
dm_block_t b, int *result)
{
int r, adjustment = 0;
- unsigned i;
+ unsigned int i;
struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
uint32_t rc;
diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c
index 16643fc974e8..39885f835584 100644
--- a/drivers/md/persistent-data/dm-transaction-manager.c
+++ b/drivers/md/persistent-data/dm-transaction-manager.c
@@ -28,14 +28,14 @@ struct prefetch_set {
dm_block_t blocks[PREFETCH_SIZE];
};
-static unsigned prefetch_hash(dm_block_t b)
+static unsigned int prefetch_hash(dm_block_t b)
{
return hash_64(b, PREFETCH_BITS);
}
static void prefetch_wipe(struct prefetch_set *p)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < PREFETCH_SIZE; i++)
p->blocks[i] = PREFETCH_SENTINEL;
}
@@ -48,7 +48,7 @@ static void prefetch_init(struct prefetch_set *p)
static void prefetch_add(struct prefetch_set *p, dm_block_t b)
{
- unsigned h = prefetch_hash(b);
+ unsigned int h = prefetch_hash(b);
mutex_lock(&p->lock);
if (p->blocks[h] == PREFETCH_SENTINEL)
@@ -59,7 +59,7 @@ static void prefetch_add(struct prefetch_set *p, dm_block_t b)
static void prefetch_issue(struct prefetch_set *p, struct dm_block_manager *bm)
{
- unsigned i;
+ unsigned int i;
mutex_lock(&p->lock);
@@ -103,7 +103,7 @@ struct dm_transaction_manager {
static int is_shadow(struct dm_transaction_manager *tm, dm_block_t b)
{
int r = 0;
- unsigned bucket = dm_hash_block(b, DM_HASH_MASK);
+ unsigned int bucket = dm_hash_block(b, DM_HASH_MASK);
struct shadow_info *si;
spin_lock(&tm->lock);
@@ -123,7 +123,7 @@ static int is_shadow(struct dm_transaction_manager *tm, dm_block_t b)
*/
static void insert_shadow(struct dm_transaction_manager *tm, dm_block_t b)
{
- unsigned bucket;
+ unsigned int bucket;
struct shadow_info *si;
si = kmalloc(sizeof(*si), GFP_NOIO);
@@ -393,11 +393,11 @@ void dm_tm_dec_range(struct dm_transaction_manager *tm, dm_block_t b, dm_block_t
EXPORT_SYMBOL_GPL(dm_tm_dec_range);
void dm_tm_with_runs(struct dm_transaction_manager *tm,
- const __le64 *value_le, unsigned count, dm_tm_run_fn fn)
+ const __le64 *value_le, unsigned int count, dm_tm_run_fn fn)
{
uint64_t b, begin, end;
bool in_run = false;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, value_le++) {
b = le64_to_cpu(*value_le);
diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h
index 906c02ed0365..0f573a4a01ae 100644
--- a/drivers/md/persistent-data/dm-transaction-manager.h
+++ b/drivers/md/persistent-data/dm-transaction-manager.h
@@ -111,7 +111,7 @@ void dm_tm_dec_range(struct dm_transaction_manager *tm, dm_block_t b, dm_block_t
*/
typedef void (*dm_tm_run_fn)(struct dm_transaction_manager *, dm_block_t, dm_block_t);
void dm_tm_with_runs(struct dm_transaction_manager *tm,
- const __le64 *value_le, unsigned count, dm_tm_run_fn fn);
+ const __le64 *value_le, unsigned int count, dm_tm_run_fn fn);
int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b, uint32_t *result);
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 8211a4d373e8..e57d86484a3a 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -5518,7 +5518,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
* .port_set_upstream_port method.
*/
.set_egress_port = mv88e6393x_set_egress_port,
- .watchdog_ops = &mv88e6390_watchdog_ops,
+ .watchdog_ops = &mv88e6393x_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,
.pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index fa65ecd9cb85..ec49939968fa 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -931,6 +931,26 @@ const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
.irq_free = mv88e6390_watchdog_free,
};
+static int mv88e6393x_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
+{
+ mv88e6390_watchdog_action(chip, irq);
+
+ /* Fix for clearing the force WD event bit.
+ * Unreleased erratum on mv88e6393x.
+ */
+ mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
+ MV88E6390_G2_WDOG_CTL_UPDATE |
+ MV88E6390_G2_WDOG_CTL_PTR_EVENT);
+
+ return IRQ_HANDLED;
+}
+
+const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops = {
+ .irq_action = mv88e6393x_watchdog_action,
+ .irq_setup = mv88e6390_watchdog_setup,
+ .irq_free = mv88e6390_watchdog_free,
+};
+
static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id)
{
struct mv88e6xxx_chip *chip = dev_id;
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index 7536b8b0ad01..c05fad5c9f19 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -363,6 +363,7 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;
extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
+extern const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops;
extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops;
extern const struct mv88e6xxx_avb_ops mv88e6352_avb_ops;
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 64eb0442c82f..005cb9dfe078 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -47,6 +47,8 @@
#define GVE_RX_BUFFER_SIZE_DQO 2048
+#define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182
+
/* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */
struct gve_rx_desc_queue {
struct gve_rx_desc *desc_ring; /* the descriptor ring */
diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c
index 4888bf05fbed..5e11b8236754 100644
--- a/drivers/net/ethernet/google/gve/gve_tx.c
+++ b/drivers/net/ethernet/google/gve/gve_tx.c
@@ -284,8 +284,8 @@ static inline int gve_skb_fifo_bytes_required(struct gve_tx_ring *tx,
int bytes;
int hlen;
- hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) +
- tcp_hdrlen(skb) : skb_headlen(skb);
+ hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) + tcp_hdrlen(skb) :
+ min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len);
pad_bytes = gve_tx_fifo_pad_alloc_one_frag(&tx->tx_fifo,
hlen);
@@ -454,13 +454,11 @@ static int gve_tx_add_skb_copy(struct gve_priv *priv, struct gve_tx_ring *tx, st
pkt_desc = &tx->desc[idx];
l4_hdr_offset = skb_checksum_start_offset(skb);
- /* If the skb is gso, then we want the tcp header in the first segment
- * otherwise we want the linear portion of the skb (which will contain
- * the checksum because skb->csum_start and skb->csum_offset are given
- * relative to skb->head) in the first segment.
+ /* If the skb is gso, then we want the tcp header alone in the first segment
+ * otherwise we want the minimum required by the gVNIC spec.
*/
hlen = is_gso ? l4_hdr_offset + tcp_hdrlen(skb) :
- skb_headlen(skb);
+ min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len);
info->skb = skb;
/* We don't want to split the header, so if necessary, pad to the end
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
index a2645ff3100e..7f7260407972 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
@@ -541,6 +541,21 @@ static void ice_vc_fdir_rem_prof_all(struct ice_vf *vf)
}
}
+/**
+ * ice_vc_fdir_reset_cnt_all - reset all FDIR counters for this VF FDIR
+ * @fdir: pointer to the VF FDIR structure
+ */
+static void ice_vc_fdir_reset_cnt_all(struct ice_vf_fdir *fdir)
+{
+ enum ice_fltr_ptype flow;
+
+ for (flow = ICE_FLTR_PTYPE_NONF_NONE;
+ flow < ICE_FLTR_PTYPE_MAX; flow++) {
+ fdir->fdir_fltr_cnt[flow][0] = 0;
+ fdir->fdir_fltr_cnt[flow][1] = 0;
+ }
+}
+
/**
* ice_vc_fdir_has_prof_conflict
* @vf: pointer to the VF structure
@@ -1871,7 +1886,7 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)
v_ret = VIRTCHNL_STATUS_SUCCESS;
stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id);
- goto err_free_conf;
+ goto err_rem_entry;
}
ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun);
@@ -1880,15 +1895,16 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)
stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",
vf->vf_id, ret);
- goto err_rem_entry;
+ goto err_clr_irq;
}
exit:
kfree(stat);
return ret;
-err_rem_entry:
+err_clr_irq:
ice_vc_fdir_clear_irq_ctx(vf);
+err_rem_entry:
ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);
err_free_conf:
devm_kfree(dev, conf);
@@ -1997,6 +2013,7 @@ void ice_vf_fdir_init(struct ice_vf *vf)
spin_lock_init(&fdir->ctx_lock);
fdir->ctx_irq.flags = 0;
fdir->ctx_done.flags = 0;
+ ice_vc_fdir_reset_cnt_all(fdir);
}
/**
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index bd7c18c839d4..f56d4e7d4ae5 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -703,6 +703,7 @@ static void mtk_mac_link_up(struct phylink_config *config,
MAC_MCR_FORCE_RX_FC);
/* Configure speed */
+ mac->speed = speed;
switch (speed) {
case SPEED_2500:
case SPEED_1000:
@@ -3169,6 +3170,9 @@ static int mtk_device_event(struct notifier_block *n, unsigned long event, void
if (dp->index >= MTK_QDMA_NUM_QUEUES)
return NOTIFY_DONE;
+ if (mac->speed > 0 && mac->speed <= s.base.speed)
+ s.base.speed = 0;
+
mtk_set_queue_speed(eth, dp->index + 3, s.base.speed);
return NOTIFY_DONE;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 13aa919633b4..ab9f876b6df7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -251,7 +251,6 @@ static void intel_speed_mode_2500(struct net_device *ndev, void *intel_data)
priv->plat->mdio_bus_data->xpcs_an_inband = false;
} else {
priv->plat->max_speed = 1000;
- priv->plat->mdio_bus_data->xpcs_an_inband = true;
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 7389718b4797..014ce97f96b1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1134,20 +1134,26 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
static int stmmac_init_phy(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ struct fwnode_handle *phy_fwnode;
struct fwnode_handle *fwnode;
int ret;
+ if (!phylink_expects_phy(priv->phylink))
+ return 0;
+
fwnode = of_fwnode_handle(priv->plat->phylink_node);
if (!fwnode)
fwnode = dev_fwnode(priv->device);
if (fwnode)
- ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
+ phy_fwnode = fwnode_get_phy_node(fwnode);
+ else
+ phy_fwnode = NULL;
/* Some DT bindings do not set-up the PHY handle. Let's try to
* manually parse it
*/
- if (!fwnode || ret) {
+ if (!phy_fwnode || IS_ERR(phy_fwnode)) {
int addr = priv->plat->phy_addr;
struct phy_device *phydev;
@@ -1163,6 +1169,9 @@ static int stmmac_init_phy(struct net_device *dev)
}
ret = phylink_connect_phy(priv->phylink, phydev);
+ } else {
+ fwnode_handle_put(phy_fwnode);
+ ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
}
if (!priv->plat->pmt) {
@@ -6620,6 +6629,8 @@ int stmmac_xdp_open(struct net_device *dev)
goto init_error;
}
+ stmmac_reset_queues_param(priv);
+
/* DMA CSR Channel configuration */
for (chan = 0; chan < dma_csr_ch; chan++) {
stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
@@ -6946,7 +6957,7 @@ static void stmmac_napi_del(struct net_device *dev)
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
{
struct stmmac_priv *priv = netdev_priv(dev);
- int ret = 0;
+ int ret = 0, i;
if (netif_running(dev))
stmmac_release(dev);
@@ -6955,6 +6966,10 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
priv->plat->rx_queues_to_use = rx_cnt;
priv->plat->tx_queues_to_use = tx_cnt;
+ if (!netif_is_rxfh_configured(dev))
+ for (i = 0; i < ARRAY_SIZE(priv->rss.table); i++)
+ priv->rss.table[i] = ethtool_rxfh_indir_default(i,
+ rx_cnt);
stmmac_napi_add(dev);
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 3e1715279855..9286b2b3353e 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2854,7 +2854,8 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
am65_cpsw_nuss_phylink_cleanup(common);
am65_cpts_release(common->cpts);
err_of_clear:
- of_platform_device_destroy(common->mdio_dev, NULL);
+ if (common->mdio_dev)
+ of_platform_device_destroy(common->mdio_dev, NULL);
err_pm_clear:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
@@ -2883,7 +2884,8 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev)
am65_cpsw_nuss_phylink_cleanup(common);
am65_cpts_release(common->cpts);
- of_platform_device_destroy(common->mdio_dev, NULL);
+ if (common->mdio_dev)
+ of_platform_device_destroy(common->mdio_dev, NULL);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 4d2519cdb801..bf8a8ed5d5d7 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1571,6 +1571,25 @@ void phylink_destroy(struct phylink *pl)
}
EXPORT_SYMBOL_GPL(phylink_destroy);
+/**
+ * phylink_expects_phy() - Determine if phylink expects a phy to be attached
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * When using fixed-link mode, or in-band mode with 1000base-X or 2500base-X,
+ * no PHY is needed.
+ *
+ * Returns true if phylink will be expecting a PHY.
+ */
+bool phylink_expects_phy(struct phylink *pl)
+{
+ if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
+ (pl->cfg_link_an_mode == MLO_AN_INBAND &&
+ phy_interface_mode_is_8023z(pl->link_config.interface)))
+ return false;
+ return true;
+}
+EXPORT_SYMBOL_GPL(phylink_expects_phy);
+
static void phylink_phy_change(struct phy_device *phydev, bool up)
{
struct phylink *pl = phydev->phylink;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index b7c918f241c9..65d4799a5658 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -994,15 +994,34 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
-static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
- int val)
+static void brcmf_sdiod_acpi_save_power_manageable(struct brcmf_sdio_dev *sdiodev)
{
#if IS_ENABLED(CONFIG_ACPI)
struct acpi_device *adev;
- adev = ACPI_COMPANION(dev);
+ adev = ACPI_COMPANION(&sdiodev->func1->dev);
if (adev)
- adev->flags.power_manageable = 0;
+ sdiodev->func1_power_manageable = adev->flags.power_manageable;
+
+ adev = ACPI_COMPANION(&sdiodev->func2->dev);
+ if (adev)
+ sdiodev->func2_power_manageable = adev->flags.power_manageable;
+#endif
+}
+
+static void brcmf_sdiod_acpi_set_power_manageable(struct brcmf_sdio_dev *sdiodev,
+ int enable)
+{
+#if IS_ENABLED(CONFIG_ACPI)
+ struct acpi_device *adev;
+
+ adev = ACPI_COMPANION(&sdiodev->func1->dev);
+ if (adev)
+ adev->flags.power_manageable = enable ? sdiodev->func1_power_manageable : 0;
+
+ adev = ACPI_COMPANION(&sdiodev->func2->dev);
+ if (adev)
+ adev->flags.power_manageable = enable ? sdiodev->func2_power_manageable : 0;
#endif
}
@@ -1012,7 +1031,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
int err;
struct brcmf_sdio_dev *sdiodev;
struct brcmf_bus *bus_if;
- struct device *dev;
brcmf_dbg(SDIO, "Enter\n");
brcmf_dbg(SDIO, "Class=%x\n", func->class);
@@ -1020,14 +1038,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
- dev = &func->dev;
-
/* Set MMC_QUIRK_LENIENT_FN0 for this card */
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
- /* prohibit ACPI power management for this device */
- brcmf_sdiod_acpi_set_power_manageable(dev, 0);
-
/* Consume func num 1 but dont do anything with it. */
if (func->num == 1)
return 0;
@@ -1059,6 +1072,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
dev_set_drvdata(&sdiodev->func1->dev, bus_if);
sdiodev->dev = &sdiodev->func1->dev;
+ brcmf_sdiod_acpi_save_power_manageable(sdiodev);
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
@@ -1124,6 +1138,8 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
if (sdiodev->settings->bus.sdio.oob_irq_supported ||
pm_caps & MMC_PM_WAKE_SDIO_IRQ) {
+ /* Stop ACPI from turning off the device when wowl is enabled */
+ brcmf_sdiod_acpi_set_power_manageable(sdiodev, !enabled);
sdiodev->wowl_enabled = enabled;
brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
return;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index b76d34d36bde..0d18ed15b403 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -188,6 +188,8 @@ struct brcmf_sdio_dev {
char nvram_name[BRCMF_FW_NAME_LEN];
char clm_name[BRCMF_FW_NAME_LEN];
bool wowl_enabled;
+ bool func1_power_manageable;
+ bool func2_power_manageable;
enum brcmf_sdiod_state state;
struct brcmf_sdiod_freezer *freezer;
const struct firmware *clm_fw;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index ca50feb0b3a9..1b1358c6bb46 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -512,15 +512,15 @@ mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
return -EOPNOTSUPP;
- if (cmd == SET_KEY) {
- key->hw_key_idx = wcid->idx;
- wcid->hw_key_idx = idx;
- } else {
+ if (cmd != SET_KEY) {
if (idx == wcid->hw_key_idx)
wcid->hw_key_idx = -1;
- key = NULL;
+ return 0;
}
+
+ key->hw_key_idx = wcid->idx;
+ wcid->hw_key_idx = idx;
mt76_wcid_key_setup(&dev->mt76, wcid, key);
return mt7603_wtbl_set_key(dev, wcid->idx, key);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index a95602473359..51a968a6afdc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -1193,8 +1193,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtscts);
static int
mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key,
- enum mt76_cipher_type cipher, u16 cipher_mask,
- enum set_key_cmd cmd)
+ enum mt76_cipher_type cipher, u16 cipher_mask)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
u8 data[32] = {};
@@ -1203,27 +1202,18 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
return -EINVAL;
mt76_rr_copy(dev, addr, data, sizeof(data));
- if (cmd == SET_KEY) {
- if (cipher == MT_CIPHER_TKIP) {
- /* Rx/Tx MIC keys are swapped */
- memcpy(data, key->key, 16);
- memcpy(data + 16, key->key + 24, 8);
- memcpy(data + 24, key->key + 16, 8);
- } else {
- if (cipher_mask == BIT(cipher))
- memcpy(data, key->key, key->keylen);
- else if (cipher != MT_CIPHER_BIP_CMAC_128)
- memcpy(data, key->key, 16);
- if (cipher == MT_CIPHER_BIP_CMAC_128)
- memcpy(data + 16, key->key, 16);
- }
+ if (cipher == MT_CIPHER_TKIP) {
+ /* Rx/Tx MIC keys are swapped */
+ memcpy(data, key->key, 16);
+ memcpy(data + 16, key->key + 24, 8);
+ memcpy(data + 24, key->key + 16, 8);
} else {
+ if (cipher_mask == BIT(cipher))
+ memcpy(data, key->key, key->keylen);
+ else if (cipher != MT_CIPHER_BIP_CMAC_128)
+ memcpy(data, key->key, 16);
if (cipher == MT_CIPHER_BIP_CMAC_128)
- memset(data + 16, 0, 16);
- else if (cipher_mask)
- memset(data, 0, 16);
- if (!cipher_mask)
- memset(data, 0, sizeof(data));
+ memcpy(data + 16, key->key, 16);
}
mt76_wr_copy(dev, addr, data, sizeof(data));
@@ -1234,7 +1224,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static int
mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
enum mt76_cipher_type cipher, u16 cipher_mask,
- int keyidx, enum set_key_cmd cmd)
+ int keyidx)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;
@@ -1253,9 +1243,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
else
w0 &= ~MT_WTBL_W0_RX_IK_VALID;
- if (cmd == SET_KEY &&
- (cipher != MT_CIPHER_BIP_CMAC_128 ||
- cipher_mask == BIT(cipher))) {
+ if (cipher != MT_CIPHER_BIP_CMAC_128 || cipher_mask == BIT(cipher)) {
w0 &= ~MT_WTBL_W0_KEY_IDX;
w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
}
@@ -1272,19 +1260,10 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static void
mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
- enum mt76_cipher_type cipher, u16 cipher_mask,
- enum set_key_cmd cmd)
+ enum mt76_cipher_type cipher, u16 cipher_mask)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
- if (!cipher_mask) {
- mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
- return;
- }
-
- if (cmd != SET_KEY)
- return;
-
if (cipher == MT_CIPHER_BIP_CMAC_128 &&
cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))
return;
@@ -1295,8 +1274,7 @@ mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key,
- enum set_key_cmd cmd)
+ struct ieee80211_key_conf *key)
{
enum mt76_cipher_type cipher;
u16 cipher_mask = wcid->cipher;
@@ -1306,19 +1284,14 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
if (cipher == MT_CIPHER_NONE)
return -EOPNOTSUPP;
- if (cmd == SET_KEY)
- cipher_mask |= BIT(cipher);
- else
- cipher_mask &= ~BIT(cipher);
-
- mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd);
- err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask,
- cmd);
+ cipher_mask |= BIT(cipher);
+ mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask);
+ err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask);
if (err < 0)
return err;
err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,
- key->keyidx, cmd);
+ key->keyidx);
if (err < 0)
return err;
@@ -1329,13 +1302,12 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key,
- enum set_key_cmd cmd)
+ struct ieee80211_key_conf *key)
{
int err;
spin_lock_bh(&dev->mt76.lock);
- err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+ err = __mt7615_mac_wtbl_set_key(dev, wcid, key);
spin_unlock_bh(&dev->mt76.lock);
return err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index ab4c1b4478aa..dadb13f2ca09 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -391,18 +391,17 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (cmd == SET_KEY)
*wcid_keyidx = idx;
- else if (idx == *wcid_keyidx)
- *wcid_keyidx = -1;
- else
+ else {
+ if (idx == *wcid_keyidx)
+ *wcid_keyidx = -1;
goto out;
+ }
- mt76_wcid_key_setup(&dev->mt76, wcid,
- cmd == SET_KEY ? key : NULL);
-
+ mt76_wcid_key_setup(&dev->mt76, wcid, key);
if (mt76_is_mmio(&dev->mt76))
- err = mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+ err = mt7615_mac_wtbl_set_key(dev, wcid, key);
else
- err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+ err = __mt7615_mac_wtbl_set_key(dev, wcid, key);
out:
mt7615_mutex_release(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index 087d4886162e..ab10ad0ecded 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -484,11 +484,9 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
void mt7615_mac_set_timing(struct mt7615_phy *phy);
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key,
- enum set_key_cmd cmd);
+ struct ieee80211_key_conf *key);
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key,
- enum set_key_cmd cmd);
+ struct ieee80211_key_conf *key);
void mt7615_mac_reset_work(struct work_struct *work);
u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 604ddcc21123..324535a0dd6d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -455,20 +455,20 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
wcid = msta ? &msta->wcid : &mvif->group_wcid;
- if (cmd == SET_KEY) {
- key->hw_key_idx = wcid->idx;
- wcid->hw_key_idx = idx;
- if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
- key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
- wcid->sw_iv = true;
- }
- } else {
+ if (cmd != SET_KEY) {
if (idx == wcid->hw_key_idx) {
wcid->hw_key_idx = -1;
wcid->sw_iv = false;
}
- key = NULL;
+ return 0;
+ }
+
+ key->hw_key_idx = wcid->idx;
+ wcid->hw_key_idx = idx;
+ if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
+ wcid->sw_iv = true;
}
mt76_wcid_key_setup(&dev->mt76, wcid, key);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 7589af4b3dab..06c1045177e2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -410,16 +410,15 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mt7915_mcu_add_bss_info(phy, vif, true);
}
- if (cmd == SET_KEY)
+ if (cmd == SET_KEY) {
*wcid_keyidx = idx;
- else if (idx == *wcid_keyidx)
- *wcid_keyidx = -1;
- else
+ } else {
+ if (idx == *wcid_keyidx)
+ *wcid_keyidx = -1;
goto out;
+ }
- mt76_wcid_key_setup(&dev->mt76, wcid,
- cmd == SET_KEY ? key : NULL);
-
+ mt76_wcid_key_setup(&dev->mt76, wcid, key);
err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
key, MCU_EXT_CMD(STA_REC_UPDATE),
&msta->wcid, cmd);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index cdb0d6190393..744382be36f8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -569,16 +569,15 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mt7921_mutex_acquire(dev);
- if (cmd == SET_KEY)
+ if (cmd == SET_KEY) {
*wcid_keyidx = idx;
- else if (idx == *wcid_keyidx)
- *wcid_keyidx = -1;
- else
+ } else {
+ if (idx == *wcid_keyidx)
+ *wcid_keyidx = -1;
goto out;
+ }
- mt76_wcid_key_setup(&dev->mt76, wcid,
- cmd == SET_KEY ? key : NULL);
-
+ mt76_wcid_key_setup(&dev->mt76, wcid, key);
err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
key, MCU_UNI_CMD(STA_REC_UPDATE),
&msta->wcid, cmd);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index cb72ded37256..5c23c827abe4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -20,7 +20,7 @@ static const struct pci_device_id mt7921_pci_device_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0608),
.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0616),
- .driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
+ .driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
{ },
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index c423b052e4f4..2734aae5449b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -351,16 +351,15 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mt7996_mcu_add_bss_info(phy, vif, true);
}
- if (cmd == SET_KEY)
+ if (cmd == SET_KEY) {
*wcid_keyidx = idx;
- else if (idx == *wcid_keyidx)
- *wcid_keyidx = -1;
- else
+ } else {
+ if (idx == *wcid_keyidx)
+ *wcid_keyidx = -1;
goto out;
+ }
- mt76_wcid_key_setup(&dev->mt76, wcid,
- cmd == SET_KEY ? key : NULL);
-
+ mt76_wcid_key_setup(&dev->mt76, wcid, key);
err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip,
key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
&msta->wcid, cmd);
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 70b5e891f6b3..ee1b075d12cf 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1717,6 +1717,9 @@ static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns)
struct request_queue *queue = disk->queue;
u32 size = queue_logical_block_size(queue);
+ if (ctrl->dmrsl && ctrl->dmrsl <= nvme_sect_to_lba(ns, UINT_MAX))
+ ctrl->max_discard_sectors = nvme_lba_to_sect(ns, ctrl->dmrsl);
+
if (ctrl->max_discard_sectors == 0) {
blk_queue_max_discard_sectors(queue, 0);
return;
@@ -1731,9 +1734,6 @@ static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns)
if (queue->limits.max_discard_sectors)
return;
- if (ctrl->dmrsl && ctrl->dmrsl <= nvme_sect_to_lba(ns, UINT_MAX))
- ctrl->max_discard_sectors = nvme_lba_to_sect(ns, ctrl->dmrsl);
-
blk_queue_max_discard_sectors(queue, ctrl->max_discard_sectors);
blk_queue_max_discard_segments(queue, ctrl->max_discard_segments);
diff --git a/drivers/pci/doe.c b/drivers/pci/doe.c
index 66d9ab288646..e5e9b287b976 100644
--- a/drivers/pci/doe.c
+++ b/drivers/pci/doe.c
@@ -128,7 +128,7 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb,
return -EIO;
/* Length is 2 DW of header + length of payload in DW */
- length = 2 + task->request_pl_sz / sizeof(u32);
+ length = 2 + task->request_pl_sz / sizeof(__le32);
if (length > PCI_DOE_MAX_LENGTH)
return -EIO;
if (length == PCI_DOE_MAX_LENGTH)
@@ -141,9 +141,9 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb,
pci_write_config_dword(pdev, offset + PCI_DOE_WRITE,
FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH,
length));
- for (i = 0; i < task->request_pl_sz / sizeof(u32); i++)
+ for (i = 0; i < task->request_pl_sz / sizeof(__le32); i++)
pci_write_config_dword(pdev, offset + PCI_DOE_WRITE,
- task->request_pl[i]);
+ le32_to_cpu(task->request_pl[i]));
pci_doe_write_ctrl(doe_mb, PCI_DOE_CTRL_GO);
@@ -195,11 +195,11 @@ static int pci_doe_recv_resp(struct pci_doe_mb *doe_mb, struct pci_doe_task *tas
/* First 2 dwords have already been read */
length -= 2;
- payload_length = min(length, task->response_pl_sz / sizeof(u32));
+ payload_length = min(length, task->response_pl_sz / sizeof(__le32));
/* Read the rest of the response payload */
for (i = 0; i < payload_length; i++) {
- pci_read_config_dword(pdev, offset + PCI_DOE_READ,
- &task->response_pl[i]);
+ pci_read_config_dword(pdev, offset + PCI_DOE_READ, &val);
+ task->response_pl[i] = cpu_to_le32(val);
/* Prior to the last ack, ensure Data Object Ready */
if (i == (payload_length - 1) && !pci_doe_data_obj_ready(doe_mb))
return -EIO;
@@ -217,13 +217,14 @@ static int pci_doe_recv_resp(struct pci_doe_mb *doe_mb, struct pci_doe_task *tas
if (FIELD_GET(PCI_DOE_STATUS_ERROR, val))
return -EIO;
- return min(length, task->response_pl_sz / sizeof(u32)) * sizeof(u32);
+ return min(length, task->response_pl_sz / sizeof(__le32)) * sizeof(__le32);
}
static void signal_task_complete(struct pci_doe_task *task, int rv)
{
task->rv = rv;
task->complete(task);
+ destroy_work_on_stack(&task->work);
}
static void signal_task_abort(struct pci_doe_task *task, int rv)
@@ -317,14 +318,16 @@ static int pci_doe_discovery(struct pci_doe_mb *doe_mb, u8 *index, u16 *vid,
{
u32 request_pl = FIELD_PREP(PCI_DOE_DATA_OBJECT_DISC_REQ_3_INDEX,
*index);
+ __le32 request_pl_le = cpu_to_le32(request_pl);
+ __le32 response_pl_le;
u32 response_pl;
DECLARE_COMPLETION_ONSTACK(c);
struct pci_doe_task task = {
.prot.vid = PCI_VENDOR_ID_PCI_SIG,
.prot.type = PCI_DOE_PROTOCOL_DISCOVERY,
- .request_pl = &request_pl,
+ .request_pl = &request_pl_le,
.request_pl_sz = sizeof(request_pl),
- .response_pl = &response_pl,
+ .response_pl = &response_pl_le,
.response_pl_sz = sizeof(response_pl),
.complete = pci_doe_task_complete,
.private = &c,
@@ -340,6 +343,7 @@ static int pci_doe_discovery(struct pci_doe_mb *doe_mb, u8 *index, u16 *vid,
if (task.rv != sizeof(response_pl))
return -EIO;
+ response_pl = le32_to_cpu(response_pl_le);
*vid = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_RSP_3_VID, response_pl);
*protocol = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL,
response_pl);
@@ -520,6 +524,8 @@ EXPORT_SYMBOL_GPL(pci_doe_supports_prot);
* task->complete will be called when the state machine is done processing this
* task.
*
+ * @task must be allocated on the stack.
+ *
* Excess data will be discarded.
*
* RETURNS: 0 when task has been successfully queued, -ERRNO on error
@@ -533,15 +539,15 @@ int pci_doe_submit_task(struct pci_doe_mb *doe_mb, struct pci_doe_task *task)
* DOE requests must be a whole number of DW and the response needs to
* be big enough for at least 1 DW
*/
- if (task->request_pl_sz % sizeof(u32) ||
- task->response_pl_sz < sizeof(u32))
+ if (task->request_pl_sz % sizeof(__le32) ||
+ task->response_pl_sz < sizeof(__le32))
return -EINVAL;
if (test_bit(PCI_DOE_FLAG_DEAD, &doe_mb->flags))
return -EIO;
task->doe_mb = doe_mb;
- INIT_WORK(&task->work, doe_statemachine_work);
+ INIT_WORK_ONSTACK(&task->work, doe_statemachine_work);
queue_work(doe_mb->work_queue, &task->work);
return 0;
}
diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
index 74af3e593b2c..336b9029d151 100644
--- a/drivers/platform/x86/think-lmi.c
+++ b/drivers/platform/x86/think-lmi.c
@@ -920,7 +920,7 @@ static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *at
static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
- char *item, *value;
+ char *item, *value, *p;
int ret;
ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID);
@@ -930,10 +930,15 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a
/* validate and split from `item,value` -> `value` */
value = strpbrk(item, ",");
if (!value || value == item || !strlen(value + 1))
- return -EINVAL;
-
- ret = sysfs_emit(buf, "%s\n", value + 1);
+ ret = -EINVAL;
+ else {
+ /* On Workstations remove the Options part after the value */
+ p = strchrnul(value, ';');
+ *p = '\0';
+ ret = sysfs_emit(buf, "%s\n", value + 1);
+ }
kfree(item);
+
return ret;
}
@@ -1457,10 +1462,10 @@ static int tlmi_analyze(void)
* name string.
* Try and pull that out if it's available.
*/
- char *item, *optstart, *optend;
+ char *optitem, *optstart, *optend;
- if (!tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID)) {
- optstart = strstr(item, "[Optional:");
+ if (!tlmi_setting(setting->index, &optitem, LENOVO_BIOS_SETTING_GUID)) {
+ optstart = strstr(optitem, "[Optional:");
if (optstart) {
optstart += strlen("[Optional:");
optend = strstr(optstart, "]");
@@ -1469,6 +1474,7 @@ static int tlmi_analyze(void)
kstrndup(optstart, optend - optstart,
GFP_KERNEL);
}
+ kfree(optitem);
}
}
/*
diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c
index 86df6702cb83..ad18b0ebe3f1 100644
--- a/drivers/pwm/pwm-cros-ec.c
+++ b/drivers/pwm/pwm-cros-ec.c
@@ -198,6 +198,7 @@ static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->enabled = (ret > 0);
state->period = EC_PWM_MAX_DUTY;
+ state->polarity = PWM_POLARITY_NORMAL;
/*
* Note that "disabled" and "duty cycle == 0" are treated the same. If
diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c
index 12c05c155cab..1b9274c5ad87 100644
--- a/drivers/pwm/pwm-hibvt.c
+++ b/drivers/pwm/pwm-hibvt.c
@@ -146,6 +146,7 @@ static int hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
value = readl(base + PWM_CTRL_ADDR(pwm->hwpwm));
state->enabled = (PWM_ENABLE_MASK & value);
+ state->polarity = (PWM_POLARITY_MASK & value) ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
return 0;
}
diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c
index 4987ca940b64..01208c2f5884 100644
--- a/drivers/pwm/pwm-iqs620a.c
+++ b/drivers/pwm/pwm-iqs620a.c
@@ -126,6 +126,7 @@ static int iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
mutex_unlock(&iqs620_pwm->lock);
state->period = IQS620_PWM_PERIOD_NS;
+ state->polarity = PWM_POLARITY_NORMAL;
return 0;
}
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
index 16d79ca5d8f5..5cd7b90872c6 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -162,6 +162,12 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
duty = state->duty_cycle;
period = state->period;
+ /*
+ * Note this is wrong. The result is an output wave that isn't really
+ * inverted and so is wrongly identified by .get_state as normal.
+ * Fixing this needs some care however as some machines might rely on
+ * this.
+ */
if (state->polarity == PWM_POLARITY_INVERSED)
duty = period - duty;
@@ -358,6 +364,8 @@ static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->duty_cycle = 0;
}
+ state->polarity = PWM_POLARITY_NORMAL;
+
return 0;
}
diff --git a/drivers/pwm/pwm-sprd.c b/drivers/pwm/pwm-sprd.c
index d866ce345f97..bde579a338c2 100644
--- a/drivers/pwm/pwm-sprd.c
+++ b/drivers/pwm/pwm-sprd.c
@@ -109,6 +109,7 @@ static int sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
duty = val & SPRD_PWM_DUTY_MSK;
tmp = (prescale + 1) * NSEC_PER_SEC * duty;
state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);
+ state->polarity = PWM_POLARITY_NORMAL;
/* Disable PWM clocks if the PWM channel is not in enable state. */
if (!state->enabled)
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 0454d94e8cf0..e7a6fc01d9ca 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -768,13 +768,12 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
iscsi_set_param(cls_conn, param, buf, buflen);
break;
case ISCSI_PARAM_DATADGST_EN:
- iscsi_set_param(cls_conn, param, buf, buflen);
-
mutex_lock(&tcp_sw_conn->sock_lock);
if (!tcp_sw_conn->sock) {
mutex_unlock(&tcp_sw_conn->sock_lock);
return -ENOTCONN;
}
+ iscsi_set_param(cls_conn, param, buf, buflen);
tcp_sw_conn->sendpage = conn->datadgst_en ?
sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
mutex_unlock(&tcp_sw_conn->sock_lock);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 02913cc75195..901c5c8035ef 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3607,6 +3607,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
probe_failed:
qla_enode_stop(base_vha);
qla_edb_stop(base_vha);
+ vfree(base_vha->scan.l);
if (base_vha->gnl.l) {
dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
base_vha->gnl.l, base_vha->gnl.ldma);
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index beba8f38b3dc..d006467ec784 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1896,6 +1896,17 @@ EXPORT_SYMBOL_GPL(serial8250_modem_status);
static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
{
switch (iir & 0x3f) {
+ case UART_IIR_THRI:
+ /*
+ * Postpone DMA or not decision to IIR_RDI or IIR_RX_TIMEOUT
+ * because it's impossible to do an informed decision about
+ * that with IIR_THRI.
+ *
+ * This also fixes one known DMA Rx corruption issue where
+ * DR is asserted but DMA Rx only gets a corrupted zero byte
+ * (too early DR?).
+ */
+ return false;
case UART_IIR_RDI:
if (!up->dma->rx_running)
break;
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 812216b24db8..59c10bceebbe 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -832,11 +832,17 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
struct lpuart_port, port);
unsigned long stat = lpuart32_read(port, UARTSTAT);
unsigned long sfifo = lpuart32_read(port, UARTFIFO);
+ unsigned long ctrl = lpuart32_read(port, UARTCTRL);
if (sport->dma_tx_in_progress)
return 0;
- if (stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT)
+ /*
+ * LPUART Transmission Complete Flag may never be set while queuing a break
+ * character, so avoid checking for transmission complete when UARTCTRL_SBK
+ * is asserted.
+ */
+ if ((stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT) || ctrl & UARTCTRL_SBK)
return TIOCSER_TEMT;
return 0;
@@ -2890,7 +2896,7 @@ static bool lpuart_uport_is_active(struct lpuart_port *sport)
tty = tty_port_tty_get(port);
if (tty) {
tty_dev = tty->dev;
- may_wake = device_may_wakeup(tty_dev);
+ may_wake = tty_dev && device_may_wakeup(tty_dev);
tty_kref_put(tty);
}
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 7bd080720929..caa09a0c48f4 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -31,6 +31,7 @@
#include <linux/ioport.h>
#include <linux/ktime.h>
#include <linux/major.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/of.h>
@@ -2864,6 +2865,13 @@ static int sci_init_single(struct platform_device *dev,
sci_port->irqs[i] = platform_get_irq(dev, i);
}
+ /*
+ * The fourth interrupt on SCI port is transmit end interrupt, so
+ * shuffle the interrupts.
+ */
+ if (p->type == PORT_SCI)
+ swap(sci_port->irqs[SCIx_BRI_IRQ], sci_port->irqs[SCIx_TEI_IRQ]);
+
/* The SCI generates several interrupts. They can be muxed together or
* connected to different interrupt lines. In the muxed case only one
* interrupt resource is specified as there is only one interrupt ID.
@@ -2929,7 +2937,7 @@ static int sci_init_single(struct platform_device *dev,
port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags;
port->fifosize = sci_port->params->fifosize;
- if (port->type == PORT_SCI) {
+ if (port->type == PORT_SCI && !dev->dev.of_node) {
if (sci_port->reg_size >= 0x20)
port->regshift = 2;
else
diff --git a/drivers/usb/cdns3/cdnsp-ep0.c b/drivers/usb/cdns3/cdnsp-ep0.c
index d63d5d92f255..f317d3c84781 100644
--- a/drivers/usb/cdns3/cdnsp-ep0.c
+++ b/drivers/usb/cdns3/cdnsp-ep0.c
@@ -414,7 +414,7 @@ static int cdnsp_ep0_std_request(struct cdnsp_device *pdev,
void cdnsp_setup_analyze(struct cdnsp_device *pdev)
{
struct usb_ctrlrequest *ctrl = &pdev->setup;
- int ret = 0;
+ int ret = -EINVAL;
u16 len;
trace_cdnsp_ctrl_req(ctrl);
@@ -424,7 +424,6 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
if (pdev->gadget.state == USB_STATE_NOTATTACHED) {
dev_err(pdev->dev, "ERR: Setup detected in unattached state\n");
- ret = -EINVAL;
goto out;
}
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index a23ddbb81979..560793545362 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -49,6 +49,7 @@
#define PCI_DEVICE_ID_INTEL_RPLS 0x7a61
#define PCI_DEVICE_ID_INTEL_MTLM 0x7eb1
#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1
+#define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
#define PCI_DEVICE_ID_INTEL_TGL 0x9a15
#define PCI_DEVICE_ID_AMD_MR 0x163a
@@ -474,6 +475,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLP),
(kernel_ulong_t) &dwc3_pci_intel_swnode, },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLS),
+ (kernel_ulong_t) &dwc3_pci_intel_swnode, },
+
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL),
(kernel_ulong_t) &dwc3_pci_intel_swnode, },
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index fb988e4ea924..6db07ca419c3 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -771,12 +771,11 @@ static struct pci_driver xhci_pci_driver = {
/* suspend and resume implemented later */
.shutdown = usb_hcd_pci_shutdown,
- .driver = {
#ifdef CONFIG_PM
- .pm = &usb_hcd_pci_pm_ops,
-#endif
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ .driver = {
+ .pm = &usb_hcd_pci_pm_ops
},
+#endif
};
static int __init xhci_pci_init(void)
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index bdb776553826..32df571bb233 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1225,6 +1225,9 @@ static void tegra_xhci_id_work(struct work_struct *work)
mutex_unlock(&tegra->lock);
+ tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(tegra->padctl,
+ tegra->otg_usb2_port);
+
if (tegra->host_mode) {
/* switch to host mode */
if (tegra->otg_usb3_port >= 0) {
@@ -1339,9 +1342,6 @@ static int tegra_xhci_id_notify(struct notifier_block *nb,
}
tegra->otg_usb2_port = tegra_xusb_get_usb2_port(tegra, usbphy);
- tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(
- tegra->padctl,
- tegra->otg_usb2_port);
tegra->host_mode = (usbphy->last_event == USB_EVENT_ID) ? true : false;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 2b280beb0011..c02ad4f76bb3 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -9,6 +9,7 @@
*/
#include <linux/pci.h>
+#include <linux/iommu.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/log2.h>
@@ -228,6 +229,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
{
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+ struct iommu_domain *domain;
int err, i;
u64 val;
u32 intrs;
@@ -246,7 +248,9 @@ static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
* an iommu. Doing anything when there is no iommu is definitely
* unsafe...
*/
- if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !device_iommu_mapped(dev))
+ domain = iommu_get_domain_for_dev(dev);
+ if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !domain ||
+ domain->type == IOMMU_DOMAIN_IDENTITY)
return;
xhci_info(xhci, "Zeroing 64bit base registers, expecting fault\n");
@@ -4406,6 +4410,7 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
if (!virt_dev || max_exit_latency == virt_dev->current_mel) {
spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_free_command(xhci, command);
return 0;
}
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 832ad592b7ef..cdea1bff3b70 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -120,6 +120,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */
{ USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */
{ USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */
+ { USB_DEVICE(0x10C4, 0x82AA) }, /* Silicon Labs IFS-USB-DATACABLE used with Quint UPS */
{ USB_DEVICE(0x10C4, 0x82EF) }, /* CESINEL FALCO 6105 AC Power Supply */
{ USB_DEVICE(0x10C4, 0x82F1) }, /* CESINEL MEDCAL EFD Earth Fault Detector */
{ USB_DEVICE(0x10C4, 0x82F2) }, /* CESINEL MEDCAL ST Network Analyzer */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index e6d8d9b35ad0..f31cc3c76329 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1198,6 +1198,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0900, 0xff, 0, 0), /* RM500U-CN */
+ .driver_info = ZLP },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
@@ -1300,6 +1302,14 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */
.driver_info = RSVD(0) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */
+ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990 (MBIM) */
+ .driver_info = NCTRL(0) | RSVD(1) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1082, 0xff), /* Telit FE990 (RNDIS) */
+ .driver_info = NCTRL(2) | RSVD(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990 (ECM) */
+ .driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 50b24096eb7f..0ea50b44effe 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -112,8 +112,12 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
if (dp->data.status & DP_STATUS_PREFER_MULTI_FUNC &&
pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK)
pin_assign &= DP_PIN_ASSIGN_MULTI_FUNC_MASK;
- else if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK)
+ else if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK) {
pin_assign &= DP_PIN_ASSIGN_DP_ONLY_MASK;
+ /* Default to pin assign C if available */
+ if (pin_assign & BIT(DP_PIN_ASSIGN_C))
+ pin_assign = BIT(DP_PIN_ASSIGN_C);
+ }
if (!pin_assign)
return -EINVAL;
diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c
index 6d13f8207e96..ace11a1a7c8a 100644
--- a/fs/cifs/fs_context.c
+++ b/fs/cifs/fs_context.c
@@ -441,13 +441,14 @@ int smb3_parse_opt(const char *options, const char *key, char **val)
* but there are some bugs that prevent rename from working if there are
* multiple delimiters.
*
- * Returns a sanitized duplicate of @path. The caller is responsible for
- * cleaning up the original.
+ * Returns a sanitized duplicate of @path. @gfp indicates the GFP_* flags
+ * for kstrdup.
+ * The caller is responsible for freeing the original.
*/
#define IS_DELIM(c) ((c) == '/' || (c) == '\\')
-static char *sanitize_path(char *path)
+char *cifs_sanitize_prepath(char *prepath, gfp_t gfp)
{
- char *cursor1 = path, *cursor2 = path;
+ char *cursor1 = prepath, *cursor2 = prepath;
/* skip all prepended delimiters */
while (IS_DELIM(*cursor1))
@@ -469,7 +470,7 @@ static char *sanitize_path(char *path)
cursor2--;
*(cursor2) = '\0';
- return kstrdup(path, GFP_KERNEL);
+ return kstrdup(prepath, gfp);
}
/*
@@ -531,7 +532,7 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
if (!*pos)
return 0;
- ctx->prepath = sanitize_path(pos);
+ ctx->prepath = cifs_sanitize_prepath(pos, GFP_KERNEL);
if (!ctx->prepath)
return -ENOMEM;
diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h
index 3de00e7127ec..f4eaf8558902 100644
--- a/fs/cifs/fs_context.h
+++ b/fs/cifs/fs_context.h
@@ -287,4 +287,7 @@ extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
*/
#define SMB3_MAX_DCLOSETIMEO (1 << 30)
#define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */
+
+extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp);
+
#endif
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 5542893ef03f..2fae6b08314d 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1297,7 +1297,7 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
kfree(cifs_sb->prepath);
if (prefix && *prefix) {
- cifs_sb->prepath = kstrdup(prefix, GFP_ATOMIC);
+ cifs_sb->prepath = cifs_sanitize_prepath(prefix, GFP_ATOMIC);
if (!cifs_sb->prepath)
return -ENOMEM;
diff --git a/fs/dax.c b/fs/dax.c
index 3e457a16c7d1..2ababb89918d 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -781,6 +781,33 @@ static int __dax_invalidate_entry(struct address_space *mapping,
return ret;
}
+static int __dax_clear_dirty_range(struct address_space *mapping,
+ pgoff_t start, pgoff_t end)
+{
+ XA_STATE(xas, &mapping->i_pages, start);
+ unsigned int scanned = 0;
+ void *entry;
+
+ xas_lock_irq(&xas);
+ xas_for_each(&xas, entry, end) {
+ entry = get_unlocked_entry(&xas, 0);
+ xas_clear_mark(&xas, PAGECACHE_TAG_DIRTY);
+ xas_clear_mark(&xas, PAGECACHE_TAG_TOWRITE);
+ put_unlocked_entry(&xas, entry, WAKE_NEXT);
+
+ if (++scanned % XA_CHECK_SCHED)
+ continue;
+
+ xas_pause(&xas);
+ xas_unlock_irq(&xas);
+ cond_resched();
+ xas_lock_irq(&xas);
+ }
+ xas_unlock_irq(&xas);
+
+ return 0;
+}
+
/*
* Delete DAX entry at @index from @mapping. Wait for it
* to be unlocked before deleting it.
@@ -1258,15 +1285,20 @@ static s64 dax_unshare_iter(struct iomap_iter *iter)
/* don't bother with blocks that are not shared to start with */
if (!(iomap->flags & IOMAP_F_SHARED))
return length;
- /* don't bother with holes or unwritten extents */
- if (srcmap->type == IOMAP_HOLE || srcmap->type == IOMAP_UNWRITTEN)
- return length;
id = dax_read_lock();
ret = dax_iomap_direct_access(iomap, pos, length, &daddr, NULL);
if (ret < 0)
goto out_unlock;
+ /* zero the distance if srcmap is HOLE or UNWRITTEN */
+ if (srcmap->flags & IOMAP_F_SHARED || srcmap->type == IOMAP_UNWRITTEN) {
+ memset(daddr, 0, length);
+ dax_flush(iomap->dax_dev, daddr, length);
+ ret = length;
+ goto out_unlock;
+ }
+
ret = dax_iomap_direct_access(srcmap, pos, length, &saddr, NULL);
if (ret < 0)
goto out_unlock;
@@ -1435,6 +1467,16 @@ static loff_t dax_iomap_iter(const struct iomap_iter *iomi,
* written by write(2) is visible in mmap.
*/
if (iomap->flags & IOMAP_F_NEW || cow) {
+ /*
+ * Filesystem allows CoW on non-shared extents. The src extents
+ * may have been mmapped with dirty mark before. To be able to
+ * invalidate its dax entries, we need to clear the dirty mark
+ * in advance.
+ */
+ if (cow)
+ __dax_clear_dirty_range(iomi->inode->i_mapping,
+ pos >> PAGE_SHIFT,
+ (end - 1) >> PAGE_SHIFT);
invalidate_inode_pages2_range(iomi->inode->i_mapping,
pos >> PAGE_SHIFT,
(end - 1) >> PAGE_SHIFT);
@@ -2022,8 +2064,8 @@ int dax_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
while ((ret = iomap_iter(&src_iter, ops)) > 0 &&
(ret = iomap_iter(&dst_iter, ops)) > 0) {
- compared = dax_range_compare_iter(&src_iter, &dst_iter, len,
- same);
+ compared = dax_range_compare_iter(&src_iter, &dst_iter,
+ min(src_iter.len, dst_iter.len), same);
if (compared < 0)
return ret;
src_iter.processed = dst_iter.processed = compared;
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 2be9d7460494..b8f9d627f241 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -326,10 +326,7 @@ int ksmbd_conn_handler_loop(void *p)
/* 4 for rfc1002 length field */
size = pdu_size + 4;
- conn->request_buf = kvmalloc(size,
- GFP_KERNEL |
- __GFP_NOWARN |
- __GFP_NORETRY);
+ conn->request_buf = kvmalloc(size, GFP_KERNEL);
if (!conn->request_buf)
break;
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index 394b6ceac431..0d8242789dc8 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -289,10 +289,7 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
work->request_buf = conn->request_buf;
conn->request_buf = NULL;
- if (ksmbd_init_smb_server(work)) {
- ksmbd_free_work_struct(work);
- return -EINVAL;
- }
+ ksmbd_init_smb_server(work);
ksmbd_conn_enqueue_request(work);
atomic_inc(&conn->r_count);
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index d0e76e2a1498..7e0b62f94a07 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -235,9 +235,6 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
struct smb2_negotiate_rsp *rsp;
struct ksmbd_conn *conn = work->conn;
- if (conn->need_neg == false)
- return -EINVAL;
-
*(__be32 *)work->response_buf =
cpu_to_be32(conn->vals->header_size);
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index 5ab93fe0dec3..212dfff8e764 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -283,20 +283,121 @@ static int ksmbd_negotiate_smb_dialect(void *buf)
return BAD_PROT_ID;
}
-int ksmbd_init_smb_server(struct ksmbd_work *work)
+#define SMB_COM_NEGOTIATE_EX 0x0
+
+/**
+ * get_smb1_cmd_val() - get smb command value from smb header
+ * @work: smb work containing smb header
+ *
+ * Return: smb command value
+ */
+static u16 get_smb1_cmd_val(struct ksmbd_work *work)
{
- struct ksmbd_conn *conn = work->conn;
+ return SMB_COM_NEGOTIATE_EX;
+}
- if (conn->need_neg == false)
+/**
+ * init_smb1_rsp_hdr() - initialize smb negotiate response header
+ * @work: smb work containing smb request
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+static int init_smb1_rsp_hdr(struct ksmbd_work *work)
+{
+ struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
+ struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
+
+ /*
+ * Remove 4 byte direct TCP header.
+ */
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(sizeof(struct smb_hdr) - 4);
+
+ rsp_hdr->Command = SMB_COM_NEGOTIATE;
+ *(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
+ rsp_hdr->Flags = SMBFLG_RESPONSE;
+ rsp_hdr->Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
+ SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
+ rsp_hdr->Pid = rcv_hdr->Pid;
+ rsp_hdr->Mid = rcv_hdr->Mid;
+ return 0;
+}
+
+/**
+ * smb1_check_user_session() - check for valid session for a user
+ * @work: smb work containing smb request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int smb1_check_user_session(struct ksmbd_work *work)
+{
+ unsigned int cmd = work->conn->ops->get_cmd_val(work);
+
+ if (cmd == SMB_COM_NEGOTIATE_EX)
return 0;
- init_smb3_11_server(conn);
+ return -EINVAL;
+}
+
+/**
+ * smb1_allocate_rsp_buf() - allocate response buffer for a command
+ * @work: smb work containing smb request
+ *
+ * Return: 0 on success, otherwise -ENOMEM
+ */
+static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
+{
+ work->response_buf = kmalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
+ GFP_KERNEL | __GFP_ZERO);
+ work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
+
+ if (!work->response_buf) {
+ pr_err("Failed to allocate %u bytes buffer\n",
+ MAX_CIFS_SMALL_BUFFER_SIZE);
+ return -ENOMEM;
+ }
- if (conn->ops->get_cmd_val(work) != SMB_COM_NEGOTIATE)
- conn->need_neg = false;
return 0;
}
+static struct smb_version_ops smb1_server_ops = {
+ .get_cmd_val = get_smb1_cmd_val,
+ .init_rsp_hdr = init_smb1_rsp_hdr,
+ .allocate_rsp_buf = smb1_allocate_rsp_buf,
+ .check_user_session = smb1_check_user_session,
+};
+
+static int smb1_negotiate(struct ksmbd_work *work)
+{
+ return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE);
+}
+
+static struct smb_version_cmds smb1_server_cmds[1] = {
+ [SMB_COM_NEGOTIATE_EX] = { .proc = smb1_negotiate, },
+};
+
+static void init_smb1_server(struct ksmbd_conn *conn)
+{
+ conn->ops = &smb1_server_ops;
+ conn->cmds = smb1_server_cmds;
+ conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
+}
+
+void ksmbd_init_smb_server(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ __le32 proto;
+
+ if (conn->need_neg == false)
+ return;
+
+ proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
+ if (proto == SMB1_PROTO_NUMBER)
+ init_smb1_server(conn);
+ else
+ init_smb3_11_server(conn);
+}
+
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
struct ksmbd_file *dir,
struct ksmbd_dir_info *d_info,
@@ -444,20 +545,10 @@ static int smb_handle_negotiate(struct ksmbd_work *work)
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
- /*
- * Remove 4 byte direct TCP header, add 2 byte bcc and
- * 2 byte DialectIndex.
- */
- *(__be32 *)work->response_buf =
- cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2 + 2);
+ /* Add 2 byte bcc and 2 byte DialectIndex. */
+ inc_rfc1001_len(work->response_buf, 4);
neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
- neg_rsp->hdr.Command = SMB_COM_NEGOTIATE;
- *(__le32 *)neg_rsp->hdr.Protocol = SMB1_PROTO_NUMBER;
- neg_rsp->hdr.Flags = SMBFLG_RESPONSE;
- neg_rsp->hdr.Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
- SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
-
neg_rsp->hdr.WordCount = 1;
neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
neg_rsp->ByteCount = 0;
@@ -473,24 +564,13 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
ksmbd_negotiate_smb_dialect(work->request_buf);
ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
- if (command == SMB2_NEGOTIATE_HE) {
- struct smb2_hdr *smb2_hdr = smb2_get_msg(work->request_buf);
-
- if (smb2_hdr->ProtocolId != SMB2_PROTO_NUMBER) {
- ksmbd_debug(SMB, "Downgrade to SMB1 negotiation\n");
- command = SMB_COM_NEGOTIATE;
- }
- }
-
if (command == SMB2_NEGOTIATE_HE) {
ret = smb2_handle_negotiate(work);
- init_smb2_neg_rsp(work);
return ret;
}
if (command == SMB_COM_NEGOTIATE) {
if (__smb2_negotiate(conn)) {
- conn->need_neg = true;
init_smb3_11_server(conn);
init_smb2_neg_rsp(work);
ksmbd_debug(SMB, "Upgrade to SMB2 negotiation\n");
diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h
index d30ce4c1a151..9130d2e3cd78 100644
--- a/fs/ksmbd/smb_common.h
+++ b/fs/ksmbd/smb_common.h
@@ -427,7 +427,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);
int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
-int ksmbd_init_smb_server(struct ksmbd_work *work);
+void ksmbd_init_smb_server(struct ksmbd_work *work);
struct ksmbd_kstat;
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
diff --git a/fs/namespace.c b/fs/namespace.c
index ab467ee58341..14fa31f17d77 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -4286,9 +4286,9 @@ static int do_mount_setattr(struct path *path, struct mount_kattr *kattr)
unlock_mount_hash();
if (kattr->propagation) {
- namespace_unlock();
if (err)
cleanup_group_ids(mnt, NULL);
+ namespace_unlock();
}
return err;
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index 04697f8dc37d..01d7fd108cf3 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -297,6 +297,7 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
out_free_dev:
kfree(dev);
+ gdp->gd_device = NULL;
return ret;
}
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 2a815f5a52c4..4039ffcf90ba 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -946,8 +946,8 @@ static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct r
if (!kcred)
return NULL;
- kcred->uid = ses->se_cb_sec.uid;
- kcred->gid = ses->se_cb_sec.gid;
+ kcred->fsuid = ses->se_cb_sec.uid;
+ kcred->fsgid = ses->se_cb_sec.gid;
return kcred;
}
}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 97edb32be77f..7799835c2196 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2476,10 +2476,12 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
for (i = 0; i < argp->opcnt; i++) {
op = &argp->ops[i];
op->replay = NULL;
+ op->opdesc = NULL;
if (xdr_stream_decode_u32(argp->xdr, &op->opnum) < 0)
return false;
if (nfsd4_opnum_in_range(argp, op)) {
+ op->opdesc = OPDESC(op);
op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
if (op->status != nfs_ok)
trace_nfsd_compound_decode_err(argp->rqstp,
@@ -2490,7 +2492,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
op->opnum = OP_ILLEGAL;
op->status = nfserr_op_illegal;
}
- op->opdesc = OPDESC(op);
+
/*
* We'll try to cache the result in the DRC if any one
* op in the compound wants to be cached:
@@ -5398,10 +5400,8 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
__be32 *p;
p = xdr_reserve_space(xdr, 8);
- if (!p) {
- WARN_ON_ONCE(1);
- return;
- }
+ if (!p)
+ goto release;
*p++ = cpu_to_be32(op->opnum);
post_err_offset = xdr->buf->len;
@@ -5416,8 +5416,6 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
op->status = encoder(resp, op->status, &op->u);
if (op->status)
trace_nfsd_compound_encode_err(rqstp, op->opnum, op->status);
- if (opdesc && opdesc->op_release)
- opdesc->op_release(&op->u);
xdr_commit_encode(xdr);
/* nfsd4_check_resp_size guarantees enough room for error status */
@@ -5458,6 +5456,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
}
status:
*p = op->status;
+release:
+ if (opdesc && opdesc->op_release)
+ opdesc->op_release(&op->u);
}
/*
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 76c3bd88b858..7aea13c33ddf 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -2607,11 +2607,10 @@ static int nilfs_segctor_thread(void *arg)
goto loop;
end_thread:
- spin_unlock(&sci->sc_state_lock);
-
/* end sync. */
sci->sc_task = NULL;
wake_up(&sci->sc_wait_task); /* for nilfs_segctor_kill_thread() */
+ spin_unlock(&sci->sc_state_lock);
return 0;
}
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 1422b8ba24ed..77f1e5778d1c 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -482,6 +482,7 @@ static void nilfs_put_super(struct super_block *sb)
up_write(&nilfs->ns_sem);
}
+ nilfs_sysfs_delete_device_group(nilfs);
iput(nilfs->ns_sufile);
iput(nilfs->ns_cpfile);
iput(nilfs->ns_dat);
@@ -1105,6 +1106,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
nilfs_put_root(fsroot);
failed_unload:
+ nilfs_sysfs_delete_device_group(nilfs);
iput(nilfs->ns_sufile);
iput(nilfs->ns_cpfile);
iput(nilfs->ns_dat);
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 3a4c9c150cbf..2894152a6b25 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -87,7 +87,6 @@ void destroy_nilfs(struct the_nilfs *nilfs)
{
might_sleep();
if (nilfs_init(nilfs)) {
- nilfs_sysfs_delete_device_group(nilfs);
brelse(nilfs->ns_sbh[0]);
brelse(nilfs->ns_sbh[1]);
}
@@ -305,6 +304,10 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
goto failed;
}
+ err = nilfs_sysfs_create_device_group(sb);
+ if (unlikely(err))
+ goto sysfs_error;
+
if (valid_fs)
goto skip_recovery;
@@ -366,6 +369,9 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
goto failed;
failed_unload:
+ nilfs_sysfs_delete_device_group(nilfs);
+
+ sysfs_error:
iput(nilfs->ns_cpfile);
iput(nilfs->ns_sufile);
iput(nilfs->ns_dat);
@@ -697,10 +703,6 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
if (err)
goto failed_sbh;
- err = nilfs_sysfs_create_device_group(sb);
- if (err)
- goto failed_sbh;
-
set_nilfs_init(nilfs);
err = 0;
out:
diff --git a/include/acpi/video.h b/include/acpi/video.h
index 8ed9bec03e53..ff5a8da5d883 100644
--- a/include/acpi/video.h
+++ b/include/acpi/video.h
@@ -59,8 +59,6 @@ extern void acpi_video_unregister(void);
extern void acpi_video_register_backlight(void);
extern int acpi_video_get_edid(struct acpi_device *device, int type,
int device_id, void **edid);
-extern enum acpi_backlight_type acpi_video_get_backlight_type(void);
-extern bool acpi_video_backlight_use_native(void);
/*
* Note: The value returned by acpi_video_handles_brightness_key_presses()
* may change over time and should not be cached.
@@ -69,6 +67,19 @@ extern bool acpi_video_handles_brightness_key_presses(void);
extern int acpi_video_get_levels(struct acpi_device *device,
struct acpi_video_device_brightness **dev_br,
int *pmax_level);
+
+extern enum acpi_backlight_type __acpi_video_get_backlight_type(bool native,
+ bool *auto_detect);
+
+static inline enum acpi_backlight_type acpi_video_get_backlight_type(void)
+{
+ return __acpi_video_get_backlight_type(false, NULL);
+}
+
+static inline bool acpi_video_backlight_use_native(void)
+{
+ return __acpi_video_get_backlight_type(true, NULL) == acpi_backlight_native;
+}
#else
static inline void acpi_video_report_nolcd(void) { return; };
static inline int acpi_video_register(void) { return -ENODEV; }
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 04c6acf7faaa..201dd1ab7f1c 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -87,10 +87,10 @@ typedef int (*dm_preresume_fn) (struct dm_target *ti);
typedef void (*dm_resume_fn) (struct dm_target *ti);
typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
- unsigned status_flags, char *result, unsigned maxlen);
+ unsigned int status_flags, char *result, unsigned int maxlen);
-typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen);
+typedef int (*dm_message_fn) (struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen);
typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti, struct block_device **bdev);
@@ -187,7 +187,7 @@ struct target_type {
uint64_t features;
const char *name;
struct module *module;
- unsigned version[3];
+ unsigned int version[3];
dm_ctr_fn ctr;
dm_dtr_fn dtr;
dm_map_fn map;
@@ -313,31 +313,31 @@ struct dm_target {
* It is a responsibility of the target driver to remap these bios
* to the real underlying devices.
*/
- unsigned num_flush_bios;
+ unsigned int num_flush_bios;
/*
* The number of discard bios that will be submitted to the target.
* The bio number can be accessed with dm_bio_get_target_bio_nr.
*/
- unsigned num_discard_bios;
+ unsigned int num_discard_bios;
/*
* The number of secure erase bios that will be submitted to the target.
* The bio number can be accessed with dm_bio_get_target_bio_nr.
*/
- unsigned num_secure_erase_bios;
+ unsigned int num_secure_erase_bios;
/*
* The number of WRITE ZEROES bios that will be submitted to the target.
* The bio number can be accessed with dm_bio_get_target_bio_nr.
*/
- unsigned num_write_zeroes_bios;
+ unsigned int num_write_zeroes_bios;
/*
* The minimum number of extra bytes allocated in each io for the
* target to use.
*/
- unsigned per_io_data_size;
+ unsigned int per_io_data_size;
/* target specific data */
void *private;
@@ -383,7 +383,7 @@ struct dm_target {
void *dm_per_bio_data(struct bio *bio, size_t data_size);
struct bio *dm_bio_from_per_bio_data(void *data, size_t data_size);
-unsigned dm_bio_get_target_bio_nr(const struct bio *bio);
+unsigned int dm_bio_get_target_bio_nr(const struct bio *bio);
u64 dm_start_time_ns_from_clone(struct bio *bio);
@@ -394,7 +394,7 @@ void dm_unregister_target(struct target_type *t);
* Target argument parsing.
*/
struct dm_arg_set {
- unsigned argc;
+ unsigned int argc;
char **argv;
};
@@ -403,8 +403,8 @@ struct dm_arg_set {
* the error message to use if the number is found to be outside that range.
*/
struct dm_arg {
- unsigned min;
- unsigned max;
+ unsigned int min;
+ unsigned int max;
char *error;
};
@@ -413,7 +413,7 @@ struct dm_arg {
* returning -EINVAL and setting *error.
*/
int dm_read_arg(const struct dm_arg *arg, struct dm_arg_set *arg_set,
- unsigned *value, char **error);
+ unsigned int *value, char **error);
/*
* Process the next argument as the start of a group containing between
@@ -421,7 +421,7 @@ int dm_read_arg(const struct dm_arg *arg, struct dm_arg_set *arg_set,
* *num_args or, if invalid, return -EINVAL and set *error.
*/
int dm_read_arg_group(const struct dm_arg *arg, struct dm_arg_set *arg_set,
- unsigned *num_args, char **error);
+ unsigned int *num_args, char **error);
/*
* Return the current argument and shift to the next.
@@ -431,7 +431,7 @@ const char *dm_shift_arg(struct dm_arg_set *as);
/*
* Move through num_args arguments.
*/
-void dm_consume_args(struct dm_arg_set *as, unsigned num_args);
+void dm_consume_args(struct dm_arg_set *as, unsigned int num_args);
/*-----------------------------------------------------------------
* Functions for creating and manipulating mapped devices.
@@ -461,7 +461,7 @@ void *dm_get_mdptr(struct mapped_device *md);
/*
* A device can still be used while suspended, but I/O is deferred.
*/
-int dm_suspend(struct mapped_device *md, unsigned suspend_flags);
+int dm_suspend(struct mapped_device *md, unsigned int suspend_flags);
int dm_resume(struct mapped_device *md);
/*
@@ -481,7 +481,7 @@ struct gendisk *dm_disk(struct mapped_device *md);
int dm_suspended(struct dm_target *ti);
int dm_post_suspending(struct dm_target *ti);
int dm_noflush_suspending(struct dm_target *ti);
-void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors);
+void dm_accept_partial_bio(struct bio *bio, unsigned int n_sectors);
void dm_submit_bio_remap(struct bio *clone, struct bio *tgt_clone);
union map_info *dm_get_rq_mapinfo(struct request *rq);
@@ -525,7 +525,7 @@ int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo);
* First create an empty table.
*/
int dm_table_create(struct dm_table **result, fmode_t mode,
- unsigned num_targets, struct mapped_device *md);
+ unsigned int num_targets, struct mapped_device *md);
/*
* Then call this once for each target.
diff --git a/include/linux/dm-bufio.h b/include/linux/dm-bufio.h
index 15d9e15ca830..1262d92ab88f 100644
--- a/include/linux/dm-bufio.h
+++ b/include/linux/dm-bufio.h
@@ -26,8 +26,8 @@ struct dm_buffer;
* Create a buffered IO cache on a given device
*/
struct dm_bufio_client *
-dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
- unsigned reserved_buffers, unsigned aux_size,
+dm_bufio_client_create(struct block_device *bdev, unsigned int block_size,
+ unsigned int reserved_buffers, unsigned int aux_size,
void (*alloc_callback)(struct dm_buffer *),
void (*write_callback)(struct dm_buffer *),
unsigned int flags);
@@ -81,7 +81,7 @@ void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
* I/O to finish.
*/
void dm_bufio_prefetch(struct dm_bufio_client *c,
- sector_t block, unsigned n_blocks);
+ sector_t block, unsigned int n_blocks);
/*
* Release a reference obtained with dm_bufio_{read,get,new}. The data
@@ -106,7 +106,7 @@ void dm_bufio_mark_buffer_dirty(struct dm_buffer *b);
* write the specified part of the buffer or it may write a larger superset.
*/
void dm_bufio_mark_partial_buffer_dirty(struct dm_buffer *b,
- unsigned start, unsigned end);
+ unsigned int start, unsigned int end);
/*
* Initiate writing of dirty buffers, without waiting for completion.
@@ -152,9 +152,9 @@ void dm_bufio_forget_buffers(struct dm_bufio_client *c, sector_t block, sector_t
/*
* Set the minimum number of buffers before cleanup happens.
*/
-void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n);
+void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned int n);
-unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
+unsigned int dm_bufio_get_block_size(struct dm_bufio_client *c);
sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c);
sector_t dm_bufio_get_block_number(struct dm_buffer *b);
diff --git a/include/linux/dm-dirty-log.h b/include/linux/dm-dirty-log.h
index 7084503c3405..843c857f07b0 100644
--- a/include/linux/dm-dirty-log.h
+++ b/include/linux/dm-dirty-log.h
@@ -33,7 +33,7 @@ struct dm_dirty_log_type {
struct list_head list;
int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti,
- unsigned argc, char **argv);
+ unsigned int argc, char **argv);
void (*dtr)(struct dm_dirty_log *log);
/*
@@ -116,7 +116,7 @@ struct dm_dirty_log_type {
* Support function for mirror status requests.
*/
int (*status)(struct dm_dirty_log *log, status_type_t status_type,
- char *result, unsigned maxlen);
+ char *result, unsigned int maxlen);
/*
* is_remote_recovering is necessary for cluster mirroring. It provides
@@ -139,7 +139,7 @@ int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type);
struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
struct dm_target *ti,
int (*flush_callback_fn)(struct dm_target *ti),
- unsigned argc, char **argv);
+ unsigned int argc, char **argv);
void dm_dirty_log_destroy(struct dm_dirty_log *log);
#endif /* __KERNEL__ */
diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h
index 8e1c4ab5df04..92e7abfe04f9 100644
--- a/include/linux/dm-io.h
+++ b/include/linux/dm-io.h
@@ -26,7 +26,7 @@ struct page_list {
struct page *page;
};
-typedef void (*io_notify_fn)(unsigned long error, void *context);
+typedef void (*io_notify_fn)(unsigned int long error, void *context);
enum dm_io_mem_type {
DM_IO_PAGE_LIST,/* Page list */
@@ -38,7 +38,7 @@ enum dm_io_mem_type {
struct dm_io_memory {
enum dm_io_mem_type type;
- unsigned offset;
+ unsigned int offset;
union {
struct page_list *pl;
@@ -78,8 +78,8 @@ void dm_io_client_destroy(struct dm_io_client *client);
* Each bit in the optional 'sync_error_bits' bitset indicates whether an
* error occurred doing io to the corresponding region.
*/
-int dm_io(struct dm_io_request *io_req, unsigned num_regions,
- struct dm_io_region *region, unsigned long *sync_error_bits);
+int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
+ struct dm_io_region *region, unsigned int long *sync_error_bits);
#endif /* __KERNEL__ */
#endif /* _LINUX_DM_IO_H */
diff --git a/include/linux/dm-kcopyd.h b/include/linux/dm-kcopyd.h
index c1707ee5b540..68c412b31b78 100644
--- a/include/linux/dm-kcopyd.h
+++ b/include/linux/dm-kcopyd.h
@@ -23,11 +23,11 @@
#define DM_KCOPYD_WRITE_SEQ 2
struct dm_kcopyd_throttle {
- unsigned throttle;
- unsigned num_io_jobs;
- unsigned io_period;
- unsigned total_period;
- unsigned last_jiffies;
+ unsigned int throttle;
+ unsigned int num_io_jobs;
+ unsigned int io_period;
+ unsigned int total_period;
+ unsigned int last_jiffies;
};
/*
@@ -60,12 +60,12 @@ void dm_kcopyd_client_flush(struct dm_kcopyd_client *kc);
* read_err is a boolean,
* write_err is a bitset, with 1 bit for each destination region
*/
-typedef void (*dm_kcopyd_notify_fn)(int read_err, unsigned long write_err,
+typedef void (*dm_kcopyd_notify_fn)(int read_err, unsigned int long write_err,
void *context);
void dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
- unsigned num_dests, struct dm_io_region *dests,
- unsigned flags, dm_kcopyd_notify_fn fn, void *context);
+ unsigned int num_dests, struct dm_io_region *dests,
+ unsigned int flags, dm_kcopyd_notify_fn fn, void *context);
/*
* Prepare a callback and submit it via the kcopyd thread.
@@ -80,11 +80,11 @@ void dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
*/
void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
dm_kcopyd_notify_fn fn, void *context);
-void dm_kcopyd_do_callback(void *job, int read_err, unsigned long write_err);
+void dm_kcopyd_do_callback(void *job, int read_err, unsigned int long write_err);
void dm_kcopyd_zero(struct dm_kcopyd_client *kc,
- unsigned num_dests, struct dm_io_region *dests,
- unsigned flags, dm_kcopyd_notify_fn fn, void *context);
+ unsigned int num_dests, struct dm_io_region *dests,
+ unsigned int flags, dm_kcopyd_notify_fn fn, void *context);
#endif /* __KERNEL__ */
#endif /* _LINUX_DM_KCOPYD_H */
diff --git a/include/linux/dm-region-hash.h b/include/linux/dm-region-hash.h
index 9e2a7a401df5..e8691539e1d7 100644
--- a/include/linux/dm-region-hash.h
+++ b/include/linux/dm-region-hash.h
@@ -37,7 +37,7 @@ struct dm_region_hash *dm_region_hash_create(
struct bio_list *bios),
void (*wakeup_workers)(void *context),
void (*wakeup_all_recovery_waiters)(void *context),
- sector_t target_begin, unsigned max_recovery,
+ sector_t target_begin, unsigned int max_recovery,
struct dm_dirty_log *log, uint32_t region_size,
region_t nr_regions);
void dm_region_hash_destroy(struct dm_region_hash *rh);
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 99f1146614c0..f4f9787d6a86 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -970,7 +970,7 @@ static inline void __ftrace_enabled_restore(int enabled)
#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
-static inline unsigned long get_lock_parent_ip(void)
+static __always_inline unsigned long get_lock_parent_ip(void)
{
unsigned long addr = CALLER_ADDR0;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 9757067c3053..0e41359d364a 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -810,7 +810,8 @@ struct mm_struct {
unsigned long cpu_bitmap[];
};
-#define MM_MT_FLAGS (MT_FLAGS_ALLOC_RANGE | MT_FLAGS_LOCK_EXTERN)
+#define MM_MT_FLAGS (MT_FLAGS_ALLOC_RANGE | MT_FLAGS_LOCK_EXTERN | \
+ MT_FLAGS_USE_RCU)
extern struct mm_struct init_mm;
/* Pointer magic because the dynamic array size confuses some compilers. */
diff --git a/include/linux/pci-doe.h b/include/linux/pci-doe.h
index ed9b4df792b8..43765eaf2342 100644
--- a/include/linux/pci-doe.h
+++ b/include/linux/pci-doe.h
@@ -34,6 +34,10 @@ struct pci_doe_mb;
* @work: Used internally by the mailbox
* @doe_mb: Used internally by the mailbox
*
+ * Payloads are treated as opaque byte streams which are transmitted verbatim,
+ * without byte-swapping. If payloads contain little-endian register values,
+ * the caller is responsible for conversion with cpu_to_le32() / le32_to_cpu().
+ *
* The payload sizes and rv are specified in bytes with the following
* restrictions concerning the protocol.
*
@@ -45,9 +49,9 @@ struct pci_doe_mb;
*/
struct pci_doe_task {
struct pci_doe_protocol prot;
- u32 *request_pl;
+ __le32 *request_pl;
size_t request_pl_sz;
- u32 *response_pl;
+ __le32 *response_pl;
size_t response_pl_sz;
int rv;
void (*complete)(struct pci_doe_task *task);
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index c492c26202b5..637698ed5cb6 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -574,6 +574,7 @@ struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *,
phy_interface_t iface,
const struct phylink_mac_ops *mac_ops);
void phylink_destroy(struct phylink *);
+bool phylink_expects_phy(struct phylink *pl);
int phylink_connect_phy(struct phylink *, struct phy_device *);
int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
diff --git a/include/net/raw.h b/include/net/raw.h
index 5e665934ebc7..3af5289fdead 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -15,6 +15,8 @@
#include <net/inet_sock.h>
#include <net/protocol.h>
+#include <net/netns/hash.h>
+#include <linux/hash.h>
#include <linux/icmp.h>
extern struct proto raw_prot;
@@ -29,20 +31,27 @@ int raw_local_deliver(struct sk_buff *, int);
int raw_rcv(struct sock *, struct sk_buff *);
-#define RAW_HTABLE_SIZE MAX_INET_PROTOS
+#define RAW_HTABLE_LOG 8
+#define RAW_HTABLE_SIZE (1U << RAW_HTABLE_LOG)
struct raw_hashinfo {
spinlock_t lock;
- struct hlist_nulls_head ht[RAW_HTABLE_SIZE];
+
+ struct hlist_head ht[RAW_HTABLE_SIZE] ____cacheline_aligned;
};
+static inline u32 raw_hashfunc(const struct net *net, u32 proto)
+{
+ return hash_32(net_hash_mix(net) ^ proto, RAW_HTABLE_LOG);
+}
+
static inline void raw_hashinfo_init(struct raw_hashinfo *hashinfo)
{
int i;
spin_lock_init(&hashinfo->lock);
for (i = 0; i < RAW_HTABLE_SIZE; i++)
- INIT_HLIST_NULLS_HEAD(&hashinfo->ht[i], i);
+ INIT_HLIST_HEAD(&hashinfo->ht[i]);
}
#ifdef CONFIG_PROC_FS
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index a4e9dbc7b67a..add5cff7952c 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -2722,8 +2722,8 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
io_eventfd_unregister(ctx);
io_alloc_cache_free(&ctx->apoll_cache, io_apoll_cache_free);
io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
- mutex_unlock(&ctx->uring_lock);
io_destroy_buffers(ctx);
+ mutex_unlock(&ctx->uring_lock);
if (ctx->sq_creds)
put_cred(ctx->sq_creds);
if (ctx->submitter_task)
diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
index 3002dc827195..a90c820ce99e 100644
--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -228,17 +228,18 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx,
return i;
}
- /* the head kbuf is the list itself */
+ /* protects io_buffers_cache */
+ lockdep_assert_held(&ctx->uring_lock);
+
while (!list_empty(&bl->buf_list)) {
struct io_buffer *nxt;
nxt = list_first_entry(&bl->buf_list, struct io_buffer, list);
- list_del(&nxt->list);
+ list_move(&nxt->list, &ctx->io_buffers_cache);
if (++i == nbufs)
return i;
cond_resched();
}
- i++;
return i;
}
diff --git a/kernel/events/core.c b/kernel/events/core.c
index fad170b47592..daecb8c9126b 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -12155,7 +12155,7 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
/*
* If its not a per-cpu rb, it must be the same task.
*/
- if (output_event->cpu == -1 && output_event->ctx != event->ctx)
+ if (output_event->cpu == -1 && output_event->hw.target != event->hw.target)
goto out;
/*
@@ -12875,12 +12875,14 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
__perf_pmu_remove(src_ctx, src_cpu, pmu, &src_ctx->pinned_groups, &events);
__perf_pmu_remove(src_ctx, src_cpu, pmu, &src_ctx->flexible_groups, &events);
- /*
- * Wait for the events to quiesce before re-instating them.
- */
- synchronize_rcu();
+ if (!list_empty(&events)) {
+ /*
+ * Wait for the events to quiesce before re-instating them.
+ */
+ synchronize_rcu();
- __perf_pmu_install(dst_ctx, dst_cpu, pmu, &events);
+ __perf_pmu_install(dst_ctx, dst_cpu, pmu, &events);
+ }
mutex_unlock(&dst_ctx->mutex);
mutex_unlock(&src_ctx->mutex);
diff --git a/kernel/fork.c b/kernel/fork.c
index 8dd0127ddcb8..e8808ffbea61 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -617,6 +617,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
if (retval)
goto out;
+ mt_clear_in_rcu(mas.tree);
mas_for_each(&old_mas, mpnt, ULONG_MAX) {
struct file *file;
@@ -703,6 +704,8 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
retval = arch_dup_mmap(oldmm, mm);
loop_out:
mas_destroy(&mas);
+ if (!retval)
+ mt_set_in_rcu(mas.tree);
out:
mmap_write_unlock(mm);
flush_tlb_mm(oldmm);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index a47f7d93e32d..5f662d135372 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -5568,12 +5568,15 @@ int modify_ftrace_direct(unsigned long ip,
ret = 0;
}
- if (unlikely(ret && new_direct)) {
- direct->count++;
- list_del_rcu(&new_direct->next);
- synchronize_rcu_tasks();
- kfree(new_direct);
- ftrace_direct_func_count--;
+ if (ret) {
+ direct->addr = old_addr;
+ if (unlikely(new_direct)) {
+ direct->count++;
+ list_del_rcu(&new_direct->next);
+ synchronize_rcu_tasks();
+ kfree(new_direct);
+ ftrace_direct_func_count--;
+ }
}
out_unlock:
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 20cd8c9d245e..12da17243747 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -3102,6 +3102,10 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
if (RB_WARN_ON(cpu_buffer,
rb_is_reader_page(cpu_buffer->tail_page)))
return;
+ /*
+ * No need for a memory barrier here, as the update
+ * of the tail_page did it for this page.
+ */
local_set(&cpu_buffer->commit_page->page->commit,
rb_page_write(cpu_buffer->commit_page));
rb_inc_page(&cpu_buffer->commit_page);
@@ -3111,6 +3115,8 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
while (rb_commit_index(cpu_buffer) !=
rb_page_write(cpu_buffer->commit_page)) {
+ /* Make sure the readers see the content of what is committed. */
+ smp_wmb();
local_set(&cpu_buffer->commit_page->page->commit,
rb_page_write(cpu_buffer->commit_page));
RB_WARN_ON(cpu_buffer,
@@ -4688,7 +4694,12 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
/*
* Make sure we see any padding after the write update
- * (see rb_reset_tail())
+ * (see rb_reset_tail()).
+ *
+ * In addition, a writer may be writing on the reader page
+ * if the page has not been fully filled, so the read barrier
+ * is also needed to make sure we see the content of what is
+ * committed by the writer (see rb_set_commit_to_write()).
*/
smp_rmb();
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 1b692574fb0c..1a931896ba04 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9472,6 +9472,7 @@ static int __remove_instance(struct trace_array *tr)
tracefs_remove(tr->dir);
free_percpu(tr->last_func_repeats);
free_trace_buffers(tr);
+ clear_tracing_err_log(tr);
for (i = 0; i < tr->nr_topts; i++) {
kfree(tr->topts[i].topts);
diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
index 67592eed0be8..89083ae1aebe 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -44,14 +44,21 @@ enum { ERRORS };
static const char *err_text[] = { ERRORS };
+static DEFINE_MUTEX(lastcmd_mutex);
static char *last_cmd;
static int errpos(const char *str)
{
+ int ret = 0;
+
+ mutex_lock(&lastcmd_mutex);
if (!str || !last_cmd)
- return 0;
+ goto out;
- return err_pos(last_cmd, str);
+ ret = err_pos(last_cmd, str);
+ out:
+ mutex_unlock(&lastcmd_mutex);
+ return ret;
}
static void last_cmd_set(const char *str)
@@ -59,18 +66,22 @@ static void last_cmd_set(const char *str)
if (!str)
return;
+ mutex_lock(&lastcmd_mutex);
kfree(last_cmd);
-
last_cmd = kstrdup(str, GFP_KERNEL);
+ mutex_unlock(&lastcmd_mutex);
}
static void synth_err(u8 err_type, u16 err_pos)
{
+ mutex_lock(&lastcmd_mutex);
if (!last_cmd)
- return;
+ goto out;
tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
err_type, err_pos);
+ out:
+ mutex_unlock(&lastcmd_mutex);
}
static int create_synth_event(const char *raw_command);
diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c
index 210e1f168392..2a1b337ac643 100644
--- a/kernel/trace/trace_osnoise.c
+++ b/kernel/trace/trace_osnoise.c
@@ -1296,7 +1296,7 @@ static void notify_new_max_latency(u64 latency)
rcu_read_lock();
list_for_each_entry_rcu(inst, &osnoise_instances, list) {
tr = inst->tr;
- if (tr->max_latency < latency) {
+ if (tracer_tracing_is_on(tr) && tr->max_latency < latency) {
tr->max_latency = latency;
latency_fsnotify(tr);
}
@@ -1738,6 +1738,8 @@ static int timerlat_main(void *data)
trace_timerlat_sample(&s);
+ notify_new_max_latency(diff);
+
timerlat_dump_stack(time_to_us(diff));
tlat->tracing_thread = false;
diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index a63594bef72e..fb452873914f 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -149,13 +149,12 @@ struct maple_subtree_state {
/* Functions */
static inline struct maple_node *mt_alloc_one(gfp_t gfp)
{
- return kmem_cache_alloc(maple_node_cache, gfp | __GFP_ZERO);
+ return kmem_cache_alloc(maple_node_cache, gfp);
}
static inline int mt_alloc_bulk(gfp_t gfp, size_t size, void **nodes)
{
- return kmem_cache_alloc_bulk(maple_node_cache, gfp | __GFP_ZERO, size,
- nodes);
+ return kmem_cache_alloc_bulk(maple_node_cache, gfp, size, nodes);
}
static inline void mt_free_bulk(size_t size, void __rcu **nodes)
@@ -535,11 +534,14 @@ static inline struct maple_node *mte_parent(const struct maple_enode *enode)
*/
static inline bool ma_dead_node(const struct maple_node *node)
{
- struct maple_node *parent = (void *)((unsigned long)
- node->parent & ~MAPLE_NODE_MASK);
+ struct maple_node *parent;
+ /* Do not reorder reads from the node prior to the parent check */
+ smp_rmb();
+ parent = (void *)((unsigned long) node->parent & ~MAPLE_NODE_MASK);
return (parent == node);
}
+
/*
* mte_dead_node() - check if the @enode is dead.
* @enode: The encoded maple node
@@ -551,6 +553,8 @@ static inline bool mte_dead_node(const struct maple_enode *enode)
struct maple_node *parent, *node;
node = mte_to_node(enode);
+ /* Do not reorder reads from the node prior to the parent check */
+ smp_rmb();
parent = mte_parent(enode);
return (parent == node);
}
@@ -621,6 +625,8 @@ static inline unsigned int mas_alloc_req(const struct ma_state *mas)
* @node - the maple node
* @type - the node type
*
+ * In the event of a dead node, this array may be %NULL
+ *
* Return: A pointer to the maple node pivots
*/
static inline unsigned long *ma_pivots(struct maple_node *node,
@@ -813,6 +819,11 @@ static inline void *mt_slot(const struct maple_tree *mt,
return rcu_dereference_check(slots[offset], mt_locked(mt));
}
+static inline void *mt_slot_locked(struct maple_tree *mt, void __rcu **slots,
+ unsigned char offset)
+{
+ return rcu_dereference_protected(slots[offset], mt_locked(mt));
+}
/*
* mas_slot_locked() - Get the slot value when holding the maple tree lock.
* @mas: The maple state
@@ -824,7 +835,7 @@ static inline void *mt_slot(const struct maple_tree *mt,
static inline void *mas_slot_locked(struct ma_state *mas, void __rcu **slots,
unsigned char offset)
{
- return rcu_dereference_protected(slots[offset], mt_locked(mas->tree));
+ return mt_slot_locked(mas->tree, slots, offset);
}
/*
@@ -895,6 +906,45 @@ static inline void ma_set_meta(struct maple_node *mn, enum maple_type mt,
meta->end = end;
}
+/*
+ * mt_clear_meta() - clear the metadata information of a node, if it exists
+ * @mt: The maple tree
+ * @mn: The maple node
+ * @type: The maple node type
+ * @offset: The offset of the highest sub-gap in this node.
+ * @end: The end of the data in this node.
+ */
+static inline void mt_clear_meta(struct maple_tree *mt, struct maple_node *mn,
+ enum maple_type type)
+{
+ struct maple_metadata *meta;
+ unsigned long *pivots;
+ void __rcu **slots;
+ void *next;
+
+ switch (type) {
+ case maple_range_64:
+ pivots = mn->mr64.pivot;
+ if (unlikely(pivots[MAPLE_RANGE64_SLOTS - 2])) {
+ slots = mn->mr64.slot;
+ next = mt_slot_locked(mt, slots,
+ MAPLE_RANGE64_SLOTS - 1);
+ if (unlikely((mte_to_node(next) &&
+ mte_node_type(next))))
+ return; /* no metadata, could be node */
+ }
+ fallthrough;
+ case maple_arange_64:
+ meta = ma_meta(mn, type);
+ break;
+ default:
+ return;
+ }
+
+ meta->gap = 0;
+ meta->end = 0;
+}
+
/*
* ma_meta_end() - Get the data end of a node from the metadata
* @mn: The maple node
@@ -1092,8 +1142,11 @@ static int mas_ascend(struct ma_state *mas)
a_type = mas_parent_enum(mas, p_enode);
a_node = mte_parent(p_enode);
a_slot = mte_parent_slot(p_enode);
- pivots = ma_pivots(a_node, a_type);
a_enode = mt_mk_node(a_node, a_type);
+ pivots = ma_pivots(a_node, a_type);
+
+ if (unlikely(ma_dead_node(a_node)))
+ return 1;
if (!set_min && a_slot) {
set_min = true;
@@ -1128,9 +1181,10 @@ static inline struct maple_node *mas_pop_node(struct ma_state *mas)
{
struct maple_alloc *ret, *node = mas->alloc;
unsigned long total = mas_allocated(mas);
+ unsigned int req = mas_alloc_req(mas);
/* nothing or a request pending. */
- if (unlikely(!total))
+ if (WARN_ON(!total))
return NULL;
if (total == 1) {
@@ -1140,27 +1194,25 @@ static inline struct maple_node *mas_pop_node(struct ma_state *mas)
goto single_node;
}
- if (!node->node_count) {
+ if (node->node_count == 1) {
/* Single allocation in this node. */
mas->alloc = node->slot[0];
- node->slot[0] = NULL;
mas->alloc->total = node->total - 1;
ret = node;
goto new_head;
}
-
node->total--;
- ret = node->slot[node->node_count];
- node->slot[node->node_count--] = NULL;
+ ret = node->slot[--node->node_count];
+ node->slot[node->node_count] = NULL;
single_node:
new_head:
- ret->total = 0;
- ret->node_count = 0;
- if (ret->request_count) {
- mas_set_alloc_req(mas, ret->request_count + 1);
- ret->request_count = 0;
+ if (req) {
+ req++;
+ mas_set_alloc_req(mas, req);
}
+
+ memset(ret, 0, sizeof(*ret));
return (struct maple_node *)ret;
}
@@ -1179,21 +1231,20 @@ static inline void mas_push_node(struct ma_state *mas, struct maple_node *used)
unsigned long count;
unsigned int requested = mas_alloc_req(mas);
- memset(reuse, 0, sizeof(*reuse));
count = mas_allocated(mas);
- if (count && (head->node_count < MAPLE_ALLOC_SLOTS - 1)) {
- if (head->slot[0])
- head->node_count++;
- head->slot[head->node_count] = reuse;
+ reuse->request_count = 0;
+ reuse->node_count = 0;
+ if (count && (head->node_count < MAPLE_ALLOC_SLOTS)) {
+ head->slot[head->node_count++] = reuse;
head->total++;
goto done;
}
reuse->total = 1;
if ((head) && !((unsigned long)head & 0x1)) {
- head->request_count = 0;
reuse->slot[0] = head;
+ reuse->node_count = 1;
reuse->total += head->total;
}
@@ -1212,7 +1263,6 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
{
struct maple_alloc *node;
unsigned long allocated = mas_allocated(mas);
- unsigned long success = allocated;
unsigned int requested = mas_alloc_req(mas);
unsigned int count;
void **slots = NULL;
@@ -1228,24 +1278,29 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
WARN_ON(!allocated);
}
- if (!allocated || mas->alloc->node_count == MAPLE_ALLOC_SLOTS - 1) {
+ if (!allocated || mas->alloc->node_count == MAPLE_ALLOC_SLOTS) {
node = (struct maple_alloc *)mt_alloc_one(gfp);
if (!node)
goto nomem_one;
- if (allocated)
+ if (allocated) {
node->slot[0] = mas->alloc;
+ node->node_count = 1;
+ } else {
+ node->node_count = 0;
+ }
- success++;
mas->alloc = node;
+ node->total = ++allocated;
requested--;
}
node = mas->alloc;
+ node->request_count = 0;
while (requested) {
max_req = MAPLE_ALLOC_SLOTS;
- if (node->slot[0]) {
- unsigned int offset = node->node_count + 1;
+ if (node->node_count) {
+ unsigned int offset = node->node_count;
slots = (void **)&node->slot[offset];
max_req -= offset;
@@ -1259,15 +1314,13 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
goto nomem_bulk;
node->node_count += count;
- /* zero indexed. */
- if (slots == (void **)&node->slot)
- node->node_count--;
-
- success += count;
+ allocated += count;
node = node->slot[0];
+ node->node_count = 0;
+ node->request_count = 0;
requested -= count;
}
- mas->alloc->total = success;
+ mas->alloc->total = allocated;
return;
nomem_bulk:
@@ -1276,7 +1329,7 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
nomem_one:
mas_set_alloc_req(mas, requested);
if (mas->alloc && !(((unsigned long)mas->alloc & 0x1)))
- mas->alloc->total = success;
+ mas->alloc->total = allocated;
mas_set_err(mas, -ENOMEM);
return;
@@ -1334,7 +1387,7 @@ static void mas_node_count(struct ma_state *mas, int count)
* mas_start() - Sets up maple state for operations.
* @mas: The maple state.
*
- * If mas->node == MAS_START, then set the min, max, depth, and offset to
+ * If mas->node == MAS_START, then set the min, max and depth to
* defaults.
*
* Return:
@@ -1348,22 +1401,26 @@ static inline struct maple_enode *mas_start(struct ma_state *mas)
if (likely(mas_is_start(mas))) {
struct maple_enode *root;
- mas->node = MAS_NONE;
mas->min = 0;
mas->max = ULONG_MAX;
mas->depth = 0;
- mas->offset = 0;
+retry:
root = mas_root(mas);
/* Tree with nodes */
if (likely(xa_is_node(root))) {
mas->depth = 1;
mas->node = mte_safe_root(root);
+ mas->offset = 0;
+ if (mte_dead_node(mas->node))
+ goto retry;
+
return NULL;
}
/* empty tree */
if (unlikely(!root)) {
+ mas->node = MAS_NONE;
mas->offset = MAPLE_NODE_SLOTS;
return NULL;
}
@@ -1399,6 +1456,9 @@ static inline unsigned char ma_data_end(struct maple_node *node,
{
unsigned char offset;
+ if (!pivots)
+ return 0;
+
if (type == maple_arange_64)
return ma_meta_end(node, type);
@@ -1434,6 +1494,9 @@ static inline unsigned char mas_data_end(struct ma_state *mas)
return ma_meta_end(node, type);
pivots = ma_pivots(node, type);
+ if (unlikely(ma_dead_node(node)))
+ return 0;
+
offset = mt_pivots[type] - 1;
if (likely(!pivots[offset]))
return ma_meta_end(node, type);
@@ -3659,10 +3722,9 @@ static inline int mas_root_expand(struct ma_state *mas, void *entry)
slot++;
mas->depth = 1;
mas_set_height(mas);
-
+ ma_set_meta(node, maple_leaf_64, 0, slot);
/* swap the new root into the tree */
rcu_assign_pointer(mas->tree->ma_root, mte_mk_root(mas->node));
- ma_set_meta(node, maple_leaf_64, 0, slot);
return slot;
}
@@ -3875,18 +3937,13 @@ static inline void *mtree_lookup_walk(struct ma_state *mas)
end = ma_data_end(node, type, pivots, max);
if (unlikely(ma_dead_node(node)))
goto dead_node;
-
- if (pivots[offset] >= mas->index)
- goto next;
-
do {
- offset++;
- } while ((offset < end) && (pivots[offset] < mas->index));
-
- if (likely(offset > end))
- max = pivots[offset];
+ if (pivots[offset] >= mas->index) {
+ max = pivots[offset];
+ break;
+ }
+ } while (++offset < end);
-next:
slots = ma_slots(node, type);
next = mt_slot(mas->tree, slots, offset);
if (unlikely(ma_dead_node(node)))
@@ -4505,6 +4562,9 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
node = mas_mn(mas);
slots = ma_slots(node, mt);
pivots = ma_pivots(node, mt);
+ if (unlikely(ma_dead_node(node)))
+ return 1;
+
mas->max = pivots[offset];
if (offset)
mas->min = pivots[offset - 1] + 1;
@@ -4526,6 +4586,9 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
slots = ma_slots(node, mt);
pivots = ma_pivots(node, mt);
offset = ma_data_end(node, mt, pivots, mas->max);
+ if (unlikely(ma_dead_node(node)))
+ return 1;
+
if (offset)
mas->min = pivots[offset - 1] + 1;
@@ -4574,6 +4637,7 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
struct maple_enode *enode;
int level = 0;
unsigned char offset;
+ unsigned char node_end;
enum maple_type mt;
void __rcu **slots;
@@ -4597,7 +4661,11 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
node = mas_mn(mas);
mt = mte_node_type(mas->node);
pivots = ma_pivots(node, mt);
- } while (unlikely(offset == ma_data_end(node, mt, pivots, mas->max)));
+ node_end = ma_data_end(node, mt, pivots, mas->max);
+ if (unlikely(ma_dead_node(node)))
+ return 1;
+
+ } while (unlikely(offset == node_end));
slots = ma_slots(node, mt);
pivot = mas_safe_pivot(mas, pivots, ++offset, mt);
@@ -4613,6 +4681,9 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
mt = mte_node_type(mas->node);
slots = ma_slots(node, mt);
pivots = ma_pivots(node, mt);
+ if (unlikely(ma_dead_node(node)))
+ return 1;
+
offset = 0;
pivot = pivots[0];
}
@@ -4659,16 +4730,19 @@ static inline void *mas_next_nentry(struct ma_state *mas,
return NULL;
}
- pivots = ma_pivots(node, type);
slots = ma_slots(node, type);
+ pivots = ma_pivots(node, type);
+ count = ma_data_end(node, type, pivots, mas->max);
+ if (unlikely(ma_dead_node(node)))
+ return NULL;
+
mas->index = mas_safe_min(mas, pivots, mas->offset);
- if (ma_dead_node(node))
+ if (unlikely(ma_dead_node(node)))
return NULL;
if (mas->index > max)
return NULL;
- count = ma_data_end(node, type, pivots, mas->max);
if (mas->offset > count)
return NULL;
@@ -4743,6 +4817,11 @@ static inline void *mas_next_entry(struct ma_state *mas, unsigned long limit)
unsigned long last;
enum maple_type mt;
+ if (mas->index > limit) {
+ mas->index = mas->last = limit;
+ mas_pause(mas);
+ return NULL;
+ }
last = mas->last;
retry:
offset = mas->offset;
@@ -4816,6 +4895,11 @@ static inline void *mas_prev_nentry(struct ma_state *mas, unsigned long limit,
slots = ma_slots(mn, mt);
pivots = ma_pivots(mn, mt);
+ if (unlikely(ma_dead_node(mn))) {
+ mas_rewalk(mas, index);
+ goto retry;
+ }
+
if (offset == mt_pivots[mt])
pivot = mas->max;
else
@@ -4849,6 +4933,11 @@ static inline void *mas_prev_entry(struct ma_state *mas, unsigned long min)
{
void *entry;
+ if (mas->index < min) {
+ mas->index = mas->last = min;
+ mas->node = MAS_NONE;
+ return NULL;
+ }
retry:
while (likely(!mas_is_none(mas))) {
entry = mas_prev_nentry(mas, min, mas->index);
@@ -5394,24 +5483,26 @@ static inline int mas_rev_alloc(struct ma_state *mas, unsigned long min,
}
/*
- * mas_dead_leaves() - Mark all leaves of a node as dead.
+ * mte_dead_leaves() - Mark all leaves of a node as dead.
* @mas: The maple state
* @slots: Pointer to the slot array
+ * @type: The maple node type
*
* Must hold the write lock.
*
* Return: The number of leaves marked as dead.
*/
static inline
-unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots)
+unsigned char mte_dead_leaves(struct maple_enode *enode, struct maple_tree *mt,
+ void __rcu **slots)
{
struct maple_node *node;
enum maple_type type;
void *entry;
int offset;
- for (offset = 0; offset < mt_slot_count(mas->node); offset++) {
- entry = mas_slot_locked(mas, slots, offset);
+ for (offset = 0; offset < mt_slot_count(enode); offset++) {
+ entry = mt_slot(mt, slots, offset);
type = mte_node_type(entry);
node = mte_to_node(entry);
/* Use both node and type to catch LE & BE metadata */
@@ -5419,7 +5510,6 @@ unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots)
break;
mte_set_node_dead(entry);
- smp_wmb(); /* Needed for RCU */
node->type = type;
rcu_assign_pointer(slots[offset], node);
}
@@ -5427,151 +5517,160 @@ unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots)
return offset;
}
-static void __rcu **mas_dead_walk(struct ma_state *mas, unsigned char offset)
+/**
+ * mte_dead_walk() - Walk down a dead tree to just before the leaves
+ * @enode: The maple encoded node
+ * @offset: The starting offset
+ *
+ * Note: This can only be used from the RCU callback context.
+ */
+static void __rcu **mte_dead_walk(struct maple_enode **enode, unsigned char offset)
{
struct maple_node *node, *next;
void __rcu **slots = NULL;
- next = mas_mn(mas);
+ next = mte_to_node(*enode);
do {
- mas->node = ma_enode_ptr(next);
- node = mas_mn(mas);
+ *enode = ma_enode_ptr(next);
+ node = mte_to_node(*enode);
slots = ma_slots(node, node->type);
- next = mas_slot_locked(mas, slots, offset);
+ next = rcu_dereference_protected(slots[offset],
+ lock_is_held(&rcu_callback_map));
offset = 0;
} while (!ma_is_leaf(next->type));
return slots;
}
+/**
+ * mt_free_walk() - Walk & free a tree in the RCU callback context
+ * @head: The RCU head that's within the node.
+ *
+ * Note: This can only be used from the RCU callback context.
+ */
static void mt_free_walk(struct rcu_head *head)
{
void __rcu **slots;
struct maple_node *node, *start;
- struct maple_tree mt;
+ struct maple_enode *enode;
unsigned char offset;
enum maple_type type;
- MA_STATE(mas, &mt, 0, 0);
node = container_of(head, struct maple_node, rcu);
if (ma_is_leaf(node->type))
goto free_leaf;
- mt_init_flags(&mt, node->ma_flags);
- mas_lock(&mas);
start = node;
- mas.node = mt_mk_node(node, node->type);
- slots = mas_dead_walk(&mas, 0);
- node = mas_mn(&mas);
+ enode = mt_mk_node(node, node->type);
+ slots = mte_dead_walk(&enode, 0);
+ node = mte_to_node(enode);
do {
mt_free_bulk(node->slot_len, slots);
offset = node->parent_slot + 1;
- mas.node = node->piv_parent;
- if (mas_mn(&mas) == node)
- goto start_slots_free;
-
- type = mte_node_type(mas.node);
- slots = ma_slots(mte_to_node(mas.node), type);
- if ((offset < mt_slots[type]) && (slots[offset]))
- slots = mas_dead_walk(&mas, offset);
-
- node = mas_mn(&mas);
+ enode = node->piv_parent;
+ if (mte_to_node(enode) == node)
+ goto free_leaf;
+
+ type = mte_node_type(enode);
+ slots = ma_slots(mte_to_node(enode), type);
+ if ((offset < mt_slots[type]) &&
+ rcu_dereference_protected(slots[offset],
+ lock_is_held(&rcu_callback_map)))
+ slots = mte_dead_walk(&enode, offset);
+ node = mte_to_node(enode);
} while ((node != start) || (node->slot_len < offset));
slots = ma_slots(node, node->type);
mt_free_bulk(node->slot_len, slots);
-start_slots_free:
- mas_unlock(&mas);
free_leaf:
mt_free_rcu(&node->rcu);
}
-static inline void __rcu **mas_destroy_descend(struct ma_state *mas,
- struct maple_enode *prev, unsigned char offset)
+static inline void __rcu **mte_destroy_descend(struct maple_enode **enode,
+ struct maple_tree *mt, struct maple_enode *prev, unsigned char offset)
{
struct maple_node *node;
- struct maple_enode *next = mas->node;
+ struct maple_enode *next = *enode;
void __rcu **slots = NULL;
+ enum maple_type type;
+ unsigned char next_offset = 0;
do {
- mas->node = next;
- node = mas_mn(mas);
- slots = ma_slots(node, mte_node_type(mas->node));
- next = mas_slot_locked(mas, slots, 0);
+ *enode = next;
+ node = mte_to_node(*enode);
+ type = mte_node_type(*enode);
+ slots = ma_slots(node, type);
+ next = mt_slot_locked(mt, slots, next_offset);
if ((mte_dead_node(next)))
- next = mas_slot_locked(mas, slots, 1);
+ next = mt_slot_locked(mt, slots, ++next_offset);
- mte_set_node_dead(mas->node);
- node->type = mte_node_type(mas->node);
+ mte_set_node_dead(*enode);
+ node->type = type;
node->piv_parent = prev;
node->parent_slot = offset;
- offset = 0;
- prev = mas->node;
+ offset = next_offset;
+ next_offset = 0;
+ prev = *enode;
} while (!mte_is_leaf(next));
return slots;
}
-static void mt_destroy_walk(struct maple_enode *enode, unsigned char ma_flags,
+static void mt_destroy_walk(struct maple_enode *enode, struct maple_tree *mt,
bool free)
{
void __rcu **slots;
struct maple_node *node = mte_to_node(enode);
struct maple_enode *start;
- struct maple_tree mt;
-
- MA_STATE(mas, &mt, 0, 0);
- if (mte_is_leaf(enode))
+ if (mte_is_leaf(enode)) {
+ node->type = mte_node_type(enode);
goto free_leaf;
+ }
- mt_init_flags(&mt, ma_flags);
- mas_lock(&mas);
-
- mas.node = start = enode;
- slots = mas_destroy_descend(&mas, start, 0);
- node = mas_mn(&mas);
+ start = enode;
+ slots = mte_destroy_descend(&enode, mt, start, 0);
+ node = mte_to_node(enode); // Updated in the above call.
do {
enum maple_type type;
unsigned char offset;
struct maple_enode *parent, *tmp;
- node->slot_len = mas_dead_leaves(&mas, slots);
+ node->slot_len = mte_dead_leaves(enode, mt, slots);
if (free)
mt_free_bulk(node->slot_len, slots);
offset = node->parent_slot + 1;
- mas.node = node->piv_parent;
- if (mas_mn(&mas) == node)
- goto start_slots_free;
+ enode = node->piv_parent;
+ if (mte_to_node(enode) == node)
+ goto free_leaf;
- type = mte_node_type(mas.node);
- slots = ma_slots(mte_to_node(mas.node), type);
+ type = mte_node_type(enode);
+ slots = ma_slots(mte_to_node(enode), type);
if (offset >= mt_slots[type])
goto next;
- tmp = mas_slot_locked(&mas, slots, offset);
+ tmp = mt_slot_locked(mt, slots, offset);
if (mte_node_type(tmp) && mte_to_node(tmp)) {
- parent = mas.node;
- mas.node = tmp;
- slots = mas_destroy_descend(&mas, parent, offset);
+ parent = enode;
+ enode = tmp;
+ slots = mte_destroy_descend(&enode, mt, parent, offset);
}
next:
- node = mas_mn(&mas);
- } while (start != mas.node);
+ node = mte_to_node(enode);
+ } while (start != enode);
- node = mas_mn(&mas);
- node->slot_len = mas_dead_leaves(&mas, slots);
+ node = mte_to_node(enode);
+ node->slot_len = mte_dead_leaves(enode, mt, slots);
if (free)
mt_free_bulk(node->slot_len, slots);
-start_slots_free:
- mas_unlock(&mas);
-
free_leaf:
if (free)
mt_free_rcu(&node->rcu);
+ else
+ mt_clear_meta(mt, node, node->type);
}
/*
@@ -5587,15 +5686,18 @@ static inline void mte_destroy_walk(struct maple_enode *enode,
struct maple_node *node = mte_to_node(enode);
if (mt_in_rcu(mt)) {
- mt_destroy_walk(enode, mt->ma_flags, false);
+ mt_destroy_walk(enode, mt, false);
call_rcu(&node->rcu, mt_free_walk);
} else {
- mt_destroy_walk(enode, mt->ma_flags, true);
+ mt_destroy_walk(enode, mt, true);
}
}
static void mas_wr_store_setup(struct ma_wr_state *wr_mas)
{
+ if (unlikely(mas_is_paused(wr_mas->mas)))
+ mas_reset(wr_mas->mas);
+
if (!mas_is_start(wr_mas->mas)) {
if (mas_is_none(wr_mas->mas)) {
mas_reset(wr_mas->mas);
@@ -5731,6 +5833,7 @@ int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp)
void mas_destroy(struct ma_state *mas)
{
struct maple_alloc *node;
+ unsigned long total;
/*
* When using mas_for_each() to insert an expected number of elements,
@@ -5753,14 +5856,20 @@ void mas_destroy(struct ma_state *mas)
}
mas->mas_flags &= ~(MA_STATE_BULK|MA_STATE_PREALLOC);
- while (mas->alloc && !((unsigned long)mas->alloc & 0x1)) {
+ total = mas_allocated(mas);
+ while (total) {
node = mas->alloc;
mas->alloc = node->slot[0];
- if (node->node_count > 0)
- mt_free_bulk(node->node_count,
- (void __rcu **)&node->slot[1]);
+ if (node->node_count > 1) {
+ size_t count = node->node_count - 1;
+
+ mt_free_bulk(count, (void __rcu **)&node->slot[1]);
+ total -= count;
+ }
kmem_cache_free(maple_node_cache, node);
+ total--;
}
+
mas->alloc = NULL;
}
EXPORT_SYMBOL_GPL(mas_destroy);
@@ -5898,6 +6007,7 @@ void *mas_prev(struct ma_state *mas, unsigned long min)
if (!mas->index) {
/* Nothing comes before 0 */
mas->last = 0;
+ mas->node = MAS_NONE;
return NULL;
}
@@ -5988,6 +6098,9 @@ void *mas_find(struct ma_state *mas, unsigned long max)
mas->index = ++mas->last;
}
+ if (unlikely(mas_is_none(mas)))
+ mas->node = MAS_START;
+
if (unlikely(mas_is_start(mas))) {
/* First run or continue */
void *entry;
@@ -6599,11 +6712,11 @@ static inline void *mas_first_entry(struct ma_state *mas, struct maple_node *mn,
while (likely(!ma_is_leaf(mt))) {
MT_BUG_ON(mas->tree, mte_dead_node(mas->node));
slots = ma_slots(mn, mt);
- pivots = ma_pivots(mn, mt);
- max = pivots[0];
entry = mas_slot(mas, slots, 0);
+ pivots = ma_pivots(mn, mt);
if (unlikely(ma_dead_node(mn)))
return NULL;
+ max = pivots[0];
mas->node = entry;
mn = mas_mn(mas);
mt = mte_node_type(mas->node);
@@ -6623,13 +6736,13 @@ static inline void *mas_first_entry(struct ma_state *mas, struct maple_node *mn,
if (likely(entry))
return entry;
- pivots = ma_pivots(mn, mt);
- mas->index = pivots[0] + 1;
mas->offset = 1;
entry = mas_slot(mas, slots, 1);
+ pivots = ma_pivots(mn, mt);
if (unlikely(ma_dead_node(mn)))
return NULL;
+ mas->index = pivots[0] + 1;
if (mas->index > limit)
goto none;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index bdbfeb6fb393..4d338f70155c 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -5476,7 +5476,7 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
struct page *pagecache_page, spinlock_t *ptl)
{
const bool unshare = flags & FAULT_FLAG_UNSHARE;
- pte_t pte;
+ pte_t pte = huge_ptep_get(ptep);
struct hstate *h = hstate_vma(vma);
struct page *old_page, *new_page;
int outside_reserve = 0;
@@ -5484,6 +5484,17 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long haddr = address & huge_page_mask(h);
struct mmu_notifier_range range;
+ /*
+ * Never handle CoW for uffd-wp protected pages. It should be only
+ * handled when the uffd-wp protection is removed.
+ *
+ * Note that only the CoW optimization path (in hugetlb_no_page())
+ * can trigger this, because hugetlb_fault() will always resolve
+ * uffd-wp bit first.
+ */
+ if (!unshare && huge_pte_uffd_wp(pte))
+ return 0;
+
/*
* hugetlb does not support FOLL_FORCE-style write faults that keep the
* PTE mapped R/O such as maybe_mkwrite() would do.
@@ -5497,7 +5508,6 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
return 0;
}
- pte = huge_ptep_get(ptep);
old_page = pte_page(pte);
delayacct_wpcopy_start();
diff --git a/mm/kfence/core.c b/mm/kfence/core.c
index 79c94ee55f97..1065e0568d05 100644
--- a/mm/kfence/core.c
+++ b/mm/kfence/core.c
@@ -556,15 +556,11 @@ static unsigned long kfence_init_pool(void)
* enters __slab_free() slow-path.
*/
for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) {
- struct slab *slab = page_slab(&pages[i]);
+ struct slab *slab = page_slab(nth_page(pages, i));
if (!i || (i % 2))
continue;
- /* Verify we do not have a compound head page. */
- if (WARN_ON(compound_head(&pages[i]) != &pages[i]))
- return addr;
-
__folio_set_slab(slab_folio(slab));
#ifdef CONFIG_MEMCG
slab->memcg_data = (unsigned long)&kfence_metadata[i / 2 - 1].objcg |
@@ -597,12 +593,26 @@ static unsigned long kfence_init_pool(void)
/* Protect the right redzone. */
if (unlikely(!kfence_protect(addr + PAGE_SIZE)))
- return addr;
+ goto reset_slab;
addr += 2 * PAGE_SIZE;
}
return 0;
+
+reset_slab:
+ for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) {
+ struct slab *slab = page_slab(nth_page(pages, i));
+
+ if (!i || (i % 2))
+ continue;
+#ifdef CONFIG_MEMCG
+ slab->memcg_data = 0;
+#endif
+ __folio_clear_slab(slab_folio(slab));
+ }
+
+ return addr;
}
static bool __init kfence_init_pool_early(void)
@@ -632,16 +642,6 @@ static bool __init kfence_init_pool_early(void)
* fails for the first page, and therefore expect addr==__kfence_pool in
* most failure cases.
*/
- for (char *p = (char *)addr; p < __kfence_pool + KFENCE_POOL_SIZE; p += PAGE_SIZE) {
- struct slab *slab = virt_to_slab(p);
-
- if (!slab)
- continue;
-#ifdef CONFIG_MEMCG
- slab->memcg_data = 0;
-#endif
- __folio_clear_slab(slab_folio(slab));
- }
memblock_free_late(__pa(addr), KFENCE_POOL_SIZE - (addr - (unsigned long)__kfence_pool));
__kfence_pool = NULL;
return false;
diff --git a/mm/memory.c b/mm/memory.c
index f526b9152bef..6a99e9dc07e6 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3580,8 +3580,21 @@ static vm_fault_t remove_device_exclusive_entry(struct vm_fault *vmf)
struct vm_area_struct *vma = vmf->vma;
struct mmu_notifier_range range;
- if (!folio_lock_or_retry(folio, vma->vm_mm, vmf->flags))
+ /*
+ * We need a reference to lock the folio because we don't hold
+ * the PTL so a racing thread can remove the device-exclusive
+ * entry and unmap it. If the folio is free the entry must
+ * have been removed already. If it happens to have already
+ * been re-allocated after being freed all we do is lock and
+ * unlock it.
+ */
+ if (!folio_try_get(folio))
+ return 0;
+
+ if (!folio_lock_or_retry(folio, vma->vm_mm, vmf->flags)) {
+ folio_put(folio);
return VM_FAULT_RETRY;
+ }
mmu_notifier_range_init_owner(&range, MMU_NOTIFY_EXCLUSIVE, 0, vma,
vma->vm_mm, vmf->address & PAGE_MASK,
(vmf->address & PAGE_MASK) + PAGE_SIZE, NULL);
@@ -3594,6 +3607,7 @@ static vm_fault_t remove_device_exclusive_entry(struct vm_fault *vmf)
pte_unmap_unlock(vmf->pte, vmf->ptl);
folio_unlock(folio);
+ folio_put(folio);
mmu_notifier_invalidate_range_end(&range);
return 0;
diff --git a/mm/mmap.c b/mm/mmap.c
index 425a9349e610..1931da077b2f 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2308,7 +2308,7 @@ do_mas_align_munmap(struct ma_state *mas, struct vm_area_struct *vma,
int count = 0;
int error = -ENOMEM;
MA_STATE(mas_detach, &mt_detach, 0, 0);
- mt_init_flags(&mt_detach, MT_FLAGS_LOCK_EXTERN);
+ mt_init_flags(&mt_detach, mas->tree->ma_flags & MT_FLAGS_LOCK_MASK);
mt_set_external_lock(&mt_detach, &mm->mmap_lock);
if (mas_preallocate(mas, vma, GFP_KERNEL))
@@ -3095,6 +3095,7 @@ void exit_mmap(struct mm_struct *mm)
*/
set_bit(MMF_OOM_SKIP, &mm->flags);
mmap_write_lock(mm);
+ mt_clear_in_rcu(&mm->mm_mt);
free_pgtables(&tlb, &mm->mm_mt, vma, FIRST_USER_ADDRESS,
USER_PGTABLES_CEILING);
tlb_finish_mmu(&tlb);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index eb9b0bf1fcdd..36899c425301 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -679,6 +679,7 @@ static void __del_from_avail_list(struct swap_info_struct *p)
{
int nid;
+ assert_spin_locked(&p->lock);
for_each_node(nid)
plist_del(&p->avail_lists[nid], &swap_avail_heads[nid]);
}
@@ -2435,8 +2436,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
spin_unlock(&swap_lock);
goto out_dput;
}
- del_from_avail_list(p);
spin_lock(&p->lock);
+ del_from_avail_list(p);
if (p->prio < 0) {
struct swap_info_struct *si = p;
int nid;
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index ca71de7c9d77..b2249d01b3a2 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -3070,9 +3070,11 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
* allocation request, free them via __vfree() if any.
*/
if (area->nr_pages != nr_small_pages) {
- warn_alloc(gfp_mask, NULL,
- "vmalloc error: size %lu, page order %u, failed to allocate pages",
- area->nr_pages * PAGE_SIZE, page_order);
+ /* vm_area_alloc_pages() can also fail due to a fatal signal */
+ if (!fatal_signal_pending(current))
+ warn_alloc(gfp_mask, NULL,
+ "vmalloc error: size %lu, page order %u, failed to allocate pages",
+ area->nr_pages * PAGE_SIZE, page_order);
goto fail;
}
diff --git a/net/can/isotp.c b/net/can/isotp.c
index 9bc344851704..5761d4ab839d 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -119,7 +119,8 @@ enum {
ISOTP_WAIT_FIRST_FC,
ISOTP_WAIT_FC,
ISOTP_WAIT_DATA,
- ISOTP_SENDING
+ ISOTP_SENDING,
+ ISOTP_SHUTDOWN,
};
struct tpcon {
@@ -880,8 +881,8 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
txtimer);
struct sock *sk = &so->sk;
- /* don't handle timeouts in IDLE state */
- if (so->tx.state == ISOTP_IDLE)
+ /* don't handle timeouts in IDLE or SHUTDOWN state */
+ if (so->tx.state == ISOTP_IDLE || so->tx.state == ISOTP_SHUTDOWN)
return HRTIMER_NORESTART;
/* we did not get any flow control or echo frame in time */
@@ -918,7 +919,6 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
{
struct sock *sk = sock->sk;
struct isotp_sock *so = isotp_sk(sk);
- u32 old_state = so->tx.state;
struct sk_buff *skb;
struct net_device *dev;
struct canfd_frame *cf;
@@ -928,23 +928,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
int off;
int err;
- if (!so->bound)
+ if (!so->bound || so->tx.state == ISOTP_SHUTDOWN)
return -EADDRNOTAVAIL;
+wait_free_buffer:
/* we do not support multiple buffers - for now */
- if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE ||
- wq_has_sleeper(&so->wait)) {
- if (msg->msg_flags & MSG_DONTWAIT) {
- err = -EAGAIN;
- goto err_out;
- }
+ if (wq_has_sleeper(&so->wait) && (msg->msg_flags & MSG_DONTWAIT))
+ return -EAGAIN;
- /* wait for complete transmission of current pdu */
- err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
- if (err)
- goto err_out;
+ /* wait for complete transmission of current pdu */
+ err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ if (err)
+ goto err_event_drop;
- so->tx.state = ISOTP_SENDING;
+ if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) {
+ if (so->tx.state == ISOTP_SHUTDOWN)
+ return -EADDRNOTAVAIL;
+
+ goto wait_free_buffer;
}
if (!size || size > MAX_MSG_LENGTH) {
@@ -1074,7 +1075,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (wait_tx_done) {
/* wait for complete transmission of current pdu */
- wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ if (err)
+ goto err_event_drop;
if (sk->sk_err)
return -sk->sk_err;
@@ -1082,13 +1085,15 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
return size;
+err_event_drop:
+ /* got signal: force tx state machine to be idle */
+ so->tx.state = ISOTP_IDLE;
+ hrtimer_cancel(&so->txfrtimer);
+ hrtimer_cancel(&so->txtimer);
err_out_drop:
/* drop this PDU and unlock a potential wait queue */
- old_state = ISOTP_IDLE;
-err_out:
- so->tx.state = old_state;
- if (so->tx.state == ISOTP_IDLE)
- wake_up_interruptible(&so->wait);
+ so->tx.state = ISOTP_IDLE;
+ wake_up_interruptible(&so->wait);
return err;
}
@@ -1120,7 +1125,7 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
if (ret < 0)
goto out_err;
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_cmsgs(msg, sk, skb);
if (msg->msg_name) {
__sockaddr_check_size(ISOTP_MIN_NAMELEN);
@@ -1150,10 +1155,12 @@ static int isotp_release(struct socket *sock)
net = sock_net(sk);
/* wait for complete transmission of current pdu */
- wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ while (wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0 &&
+ cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SHUTDOWN) != ISOTP_IDLE)
+ ;
/* force state machines to be idle also when a signal occurred */
- so->tx.state = ISOTP_IDLE;
+ so->tx.state = ISOTP_SHUTDOWN;
so->rx.state = ISOTP_IDLE;
spin_lock(&isotp_notifier_lock);
@@ -1608,6 +1615,21 @@ static int isotp_init(struct sock *sk)
return 0;
}
+static __poll_t isotp_poll(struct file *file, struct socket *sock, poll_table *wait)
+{
+ struct sock *sk = sock->sk;
+ struct isotp_sock *so = isotp_sk(sk);
+
+ __poll_t mask = datagram_poll(file, sock, wait);
+ poll_wait(file, &so->wait, wait);
+
+ /* Check for false positives due to TX state */
+ if ((mask & EPOLLWRNORM) && (so->tx.state != ISOTP_IDLE))
+ mask &= ~(EPOLLOUT | EPOLLWRNORM);
+
+ return mask;
+}
+
static int isotp_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd,
unsigned long arg)
{
@@ -1623,7 +1645,7 @@ static const struct proto_ops isotp_ops = {
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = isotp_getname,
- .poll = datagram_poll,
+ .poll = isotp_poll,
.ioctl = isotp_sock_no_ioctlcmd,
.gettstamp = sock_gettstamp,
.listen = sock_no_listen,
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index fb92c3609e17..fe3df23a2595 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -604,7 +604,10 @@ sk_buff *j1939_tp_tx_dat_new(struct j1939_priv *priv,
/* reserve CAN header */
skb_reserve(skb, offsetof(struct can_frame, data));
- memcpy(skb->cb, re_skcb, sizeof(skb->cb));
+ /* skb->cb must be large enough to hold a j1939_sk_buff_cb structure */
+ BUILD_BUG_ON(sizeof(skb->cb) < sizeof(*re_skcb));
+
+ memcpy(skb->cb, re_skcb, sizeof(*re_skcb));
skcb = j1939_skb_to_cb(skb);
if (swap_src_dst)
j1939_skbcb_swap(skcb);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 9be762e1d042..4ac8d0ad9f6f 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -137,6 +137,20 @@ static void queue_process(struct work_struct *work)
}
}
+static int netif_local_xmit_active(struct net_device *dev)
+{
+ int i;
+
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+
+ if (READ_ONCE(txq->xmit_lock_owner) == smp_processor_id())
+ return 1;
+ }
+
+ return 0;
+}
+
static void poll_one_napi(struct napi_struct *napi)
{
int work;
@@ -183,7 +197,10 @@ void netpoll_poll_dev(struct net_device *dev)
if (!ni || down_trylock(&ni->dev_lock))
return;
- if (!netif_running(dev)) {
+ /* Some drivers will take the same locks in poll and xmit,
+ * we can't poll if local CPU is already in xmit.
+ */
+ if (!netif_running(dev) || netif_local_xmit_active(dev)) {
up(&ni->dev_lock);
return;
}
diff --git a/net/ethtool/linkmodes.c b/net/ethtool/linkmodes.c
index 126e06c713a3..2d91f2a8c762 100644
--- a/net/ethtool/linkmodes.c
+++ b/net/ethtool/linkmodes.c
@@ -282,11 +282,12 @@ static int ethnl_update_linkmodes(struct genl_info *info, struct nlattr **tb,
"lanes configuration not supported by device");
return -EOPNOTSUPP;
}
- } else if (!lsettings->autoneg) {
- /* If autoneg is off and lanes parameter is not passed from user,
- * set the lanes parameter to 0.
+ } else if (!lsettings->autoneg && ksettings->lanes) {
+ /* If autoneg is off and lanes parameter is not passed from user but
+ * it was defined previously then set the lanes parameter to 0.
*/
ksettings->lanes = 0;
+ *mod = true;
}
ret = ethnl_update_bitset(ksettings->link_modes.advertising,
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 46aa2d65e40a..635ed4f05749 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -746,6 +746,11 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
room = 576;
room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen;
room -= sizeof(struct icmphdr);
+ /* Guard against tiny mtu. We need to include at least one
+ * IP network header for this message to make any sense.
+ */
+ if (room <= (int)sizeof(struct iphdr))
+ goto ende;
icmp_param.data_len = skb_in->len - icmp_param.offset;
if (icmp_param.data_len > room)
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 409ec2a1f95b..5178a3f3cb53 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -1089,13 +1089,13 @@ static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos)
}
void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family)
- __acquires(RCU)
+ __acquires(ping_table.lock)
{
struct ping_iter_state *state = seq->private;
state->bucket = 0;
state->family = family;
- rcu_read_lock();
+ spin_lock(&ping_table.lock);
return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN;
}
@@ -1121,9 +1121,9 @@ void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos)
EXPORT_SYMBOL_GPL(ping_seq_next);
void ping_seq_stop(struct seq_file *seq, void *v)
- __releases(RCU)
+ __releases(ping_table.lock)
{
- rcu_read_unlock();
+ spin_unlock(&ping_table.lock);
}
EXPORT_SYMBOL_GPL(ping_seq_stop);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 006c1f0ed8b4..af03aa8a8e51 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -91,12 +91,12 @@ EXPORT_SYMBOL_GPL(raw_v4_hashinfo);
int raw_hash_sk(struct sock *sk)
{
struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
- struct hlist_nulls_head *hlist;
+ struct hlist_head *hlist;
- hlist = &h->ht[inet_sk(sk)->inet_num & (RAW_HTABLE_SIZE - 1)];
+ hlist = &h->ht[raw_hashfunc(sock_net(sk), inet_sk(sk)->inet_num)];
spin_lock(&h->lock);
- __sk_nulls_add_node_rcu(sk, hlist);
+ sk_add_node_rcu(sk, hlist);
sock_set_flag(sk, SOCK_RCU_FREE);
spin_unlock(&h->lock);
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
@@ -110,7 +110,7 @@ void raw_unhash_sk(struct sock *sk)
struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
spin_lock(&h->lock);
- if (__sk_nulls_del_node_init_rcu(sk))
+ if (sk_del_node_init_rcu(sk))
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
spin_unlock(&h->lock);
}
@@ -160,19 +160,18 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
* RFC 1122: SHOULD pass TOS value up to the transport layer.
* -> It does. And not only TOS, but all IP header.
*/
-static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
+static int raw_v4_input(struct net *net, struct sk_buff *skb,
+ const struct iphdr *iph, int hash)
{
- struct net *net = dev_net(skb->dev);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
int sdif = inet_sdif(skb);
+ struct hlist_head *hlist;
int dif = inet_iif(skb);
int delivered = 0;
struct sock *sk;
hlist = &raw_v4_hashinfo.ht[hash];
rcu_read_lock();
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
if (!raw_v4_match(net, sk, iph->protocol,
iph->saddr, iph->daddr, dif, sdif))
continue;
@@ -193,9 +192,10 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
int raw_local_deliver(struct sk_buff *skb, int protocol)
{
- int hash = protocol & (RAW_HTABLE_SIZE - 1);
+ struct net *net = dev_net(skb->dev);
- return raw_v4_input(skb, ip_hdr(skb), hash);
+ return raw_v4_input(net, skb, ip_hdr(skb),
+ raw_hashfunc(net, protocol));
}
static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
@@ -263,19 +263,18 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
{
struct net *net = dev_net(skb->dev);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
int dif = skb->dev->ifindex;
int sdif = inet_sdif(skb);
+ struct hlist_head *hlist;
const struct iphdr *iph;
struct sock *sk;
int hash;
- hash = protocol & (RAW_HTABLE_SIZE - 1);
+ hash = raw_hashfunc(net, protocol);
hlist = &raw_v4_hashinfo.ht[hash];
rcu_read_lock();
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
iph = (const struct iphdr *)skb->data;
if (!raw_v4_match(net, sk, iph->protocol,
iph->daddr, iph->saddr, dif, sdif))
@@ -947,14 +946,13 @@ static struct sock *raw_get_first(struct seq_file *seq, int bucket)
{
struct raw_hashinfo *h = pde_data(file_inode(seq->file));
struct raw_iter_state *state = raw_seq_private(seq);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
+ struct hlist_head *hlist;
struct sock *sk;
for (state->bucket = bucket; state->bucket < RAW_HTABLE_SIZE;
++state->bucket) {
hlist = &h->ht[state->bucket];
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each(sk, hlist) {
if (sock_net(sk) == seq_file_net(seq))
return sk;
}
@@ -967,7 +965,7 @@ static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk)
struct raw_iter_state *state = raw_seq_private(seq);
do {
- sk = sk_nulls_next(sk);
+ sk = sk_next(sk);
} while (sk && sock_net(sk) != seq_file_net(seq));
if (!sk)
@@ -986,9 +984,12 @@ static struct sock *raw_get_idx(struct seq_file *seq, loff_t pos)
}
void *raw_seq_start(struct seq_file *seq, loff_t *pos)
- __acquires(RCU)
+ __acquires(&h->lock)
{
- rcu_read_lock();
+ struct raw_hashinfo *h = pde_data(file_inode(seq->file));
+
+ spin_lock(&h->lock);
+
return *pos ? raw_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
}
EXPORT_SYMBOL_GPL(raw_seq_start);
@@ -1007,9 +1008,11 @@ void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos)
EXPORT_SYMBOL_GPL(raw_seq_next);
void raw_seq_stop(struct seq_file *seq, void *v)
- __releases(RCU)
+ __releases(&h->lock)
{
- rcu_read_unlock();
+ struct raw_hashinfo *h = pde_data(file_inode(seq->file));
+
+ spin_unlock(&h->lock);
}
EXPORT_SYMBOL_GPL(raw_seq_stop);
diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c
index 999321834b94..da3591a66a16 100644
--- a/net/ipv4/raw_diag.c
+++ b/net/ipv4/raw_diag.c
@@ -57,8 +57,7 @@ static bool raw_lookup(struct net *net, struct sock *sk,
static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 *r)
{
struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
+ struct hlist_head *hlist;
struct sock *sk;
int slot;
@@ -68,7 +67,7 @@ static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2
rcu_read_lock();
for (slot = 0; slot < RAW_HTABLE_SIZE; slot++) {
hlist = &hashinfo->ht[slot];
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
if (raw_lookup(net, sk, r)) {
/*
* Grab it and keep until we fill
@@ -142,9 +141,8 @@ static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
struct net *net = sock_net(skb->sk);
struct inet_diag_dump_data *cb_data;
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
int num, s_num, slot, s_slot;
+ struct hlist_head *hlist;
struct sock *sk = NULL;
struct nlattr *bc;
@@ -161,7 +159,7 @@ static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
num = 0;
hlist = &hashinfo->ht[slot];
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
struct inet_sock *inet = inet_sk(sk);
if (!net_eq(sock_net(sk), net))
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index c314fdde0097..95a55c6630ad 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1965,8 +1965,13 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
if (proto == IPPROTO_ICMPV6) {
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
+ u8 icmp6_type;
- ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type);
+ if (sk->sk_socket->type == SOCK_RAW && !inet_sk(sk)->hdrincl)
+ icmp6_type = fl6->fl6_icmp_type;
+ else
+ icmp6_type = icmp6_hdr(skb)->icmp6_type;
+ ICMP6MSGOUT_INC_STATS(net, idev, icmp6_type);
ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index ada087b50541..4fc511bdf176 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -141,10 +141,9 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister);
static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
{
struct net *net = dev_net(skb->dev);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
const struct in6_addr *saddr;
const struct in6_addr *daddr;
+ struct hlist_head *hlist;
struct sock *sk;
bool delivered = false;
__u8 hash;
@@ -152,10 +151,10 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
saddr = &ipv6_hdr(skb)->saddr;
daddr = saddr + 1;
- hash = nexthdr & (RAW_HTABLE_SIZE - 1);
+ hash = raw_hashfunc(net, nexthdr);
hlist = &raw_v6_hashinfo.ht[hash];
rcu_read_lock();
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
int filtered;
if (!raw_v6_match(net, sk, nexthdr, daddr, saddr,
@@ -333,15 +332,14 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
u8 type, u8 code, int inner_offset, __be32 info)
{
struct net *net = dev_net(skb->dev);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
+ struct hlist_head *hlist;
struct sock *sk;
int hash;
- hash = nexthdr & (RAW_HTABLE_SIZE - 1);
+ hash = raw_hashfunc(net, nexthdr);
hlist = &raw_v6_hashinfo.ht[hash];
rcu_read_lock();
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
/* Note: ipv6_hdr(skb) != skb->data */
const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data;
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 4db5a554bdbd..41a74fc84ca1 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -677,8 +677,8 @@ MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
MODULE_DESCRIPTION("L2TP over IP");
MODULE_VERSION("1.0");
-/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like
- * enums
+/* Use the values of SOCK_DGRAM (2) as type and IPPROTO_L2TP (115) as protocol,
+ * because __stringify doesn't like enums
*/
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP);
-MODULE_ALIAS_NET_PF_PROTO(PF_INET, IPPROTO_L2TP);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 115, 2);
+MODULE_ALIAS_NET_PF_PROTO(PF_INET, 115);
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 2478aa60145f..5137ea1861ce 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -806,8 +806,8 @@ MODULE_AUTHOR("Chris Elston <celston@katalix.com>");
MODULE_DESCRIPTION("L2TP IP encapsulation for IPv6");
MODULE_VERSION("1.0");
-/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like
- * enums
+/* Use the values of SOCK_DGRAM (2) as type and IPPROTO_L2TP (115) as protocol,
+ * because __stringify doesn't like enums
*/
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 2, IPPROTO_L2TP);
-MODULE_ALIAS_NET_PF_PROTO(PF_INET6, IPPROTO_L2TP);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 115, 2);
+MODULE_ALIAS_NET_PF_PROTO(PF_INET6, 115);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 34cb833db25f..39731ef51e03 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1261,7 +1261,8 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
list_del_rcu(&sta->list);
sta->removed = true;
- drv_sta_pre_rcu_remove(local, sta->sdata, sta);
+ if (sta->uploaded)
+ drv_sta_pre_rcu_remove(local, sta->sdata, sta);
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
rcu_access_pointer(sdata->u.vlan.sta) == sta)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 9c219e525ede..ed9e659f49f6 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -4906,7 +4906,7 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype)
&eht_cap->eht_cap_elem,
is_ap);
return 2 + 1 +
- sizeof(he_cap->he_cap_elem) + n +
+ sizeof(eht_cap->eht_cap_elem) + n +
ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
eht_cap->eht_cap_elem.phy_cap_info);
return 0;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index c64277659753..f365dfdd672d 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1952,7 +1952,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
struct scm_cookie scm;
struct sock *sk = sock->sk;
struct netlink_sock *nlk = nlk_sk(sk);
- size_t copied;
+ size_t copied, max_recvmsg_len;
struct sk_buff *skb, *data_skb;
int err, ret;
@@ -1985,9 +1985,10 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
#endif
/* Record the max length of recvmsg() calls for future allocations */
- nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len);
- nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len,
- SKB_WITH_OVERHEAD(32768));
+ max_recvmsg_len = max(READ_ONCE(nlk->max_recvmsg_len), len);
+ max_recvmsg_len = min_t(size_t, max_recvmsg_len,
+ SKB_WITH_OVERHEAD(32768));
+ WRITE_ONCE(nlk->max_recvmsg_len, max_recvmsg_len);
copied = data_skb->len;
if (len < copied) {
@@ -2236,6 +2237,7 @@ static int netlink_dump(struct sock *sk)
struct netlink_ext_ack extack = {};
struct netlink_callback *cb;
struct sk_buff *skb = NULL;
+ size_t max_recvmsg_len;
struct module *module;
int err = -ENOBUFS;
int alloc_min_size;
@@ -2258,8 +2260,9 @@ static int netlink_dump(struct sock *sk)
cb = &nlk->cb;
alloc_min_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
- if (alloc_min_size < nlk->max_recvmsg_len) {
- alloc_size = nlk->max_recvmsg_len;
+ max_recvmsg_len = READ_ONCE(nlk->max_recvmsg_len);
+ if (alloc_min_size < max_recvmsg_len) {
+ alloc_size = max_recvmsg_len;
skb = alloc_skb(alloc_size,
(GFP_KERNEL & ~__GFP_DIRECT_RECLAIM) |
__GFP_NOWARN | __GFP_NORETRY);
diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c
index 5c2fb992803b..3a70255c8d02 100644
--- a/net/qrtr/af_qrtr.c
+++ b/net/qrtr/af_qrtr.c
@@ -393,10 +393,12 @@ static struct qrtr_node *qrtr_node_lookup(unsigned int nid)
struct qrtr_node *node;
unsigned long flags;
+ mutex_lock(&qrtr_node_lock);
spin_lock_irqsave(&qrtr_nodes_lock, flags);
node = radix_tree_lookup(&qrtr_nodes, nid);
node = qrtr_node_acquire(node);
spin_unlock_irqrestore(&qrtr_nodes_lock, flags);
+ mutex_unlock(&qrtr_node_lock);
return node;
}
diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c
index e595079c2caf..3e40a1ba48f7 100644
--- a/net/qrtr/ns.c
+++ b/net/qrtr/ns.c
@@ -273,7 +273,7 @@ static struct qrtr_server *server_add(unsigned int service,
return NULL;
}
-static int server_del(struct qrtr_node *node, unsigned int port)
+static int server_del(struct qrtr_node *node, unsigned int port, bool bcast)
{
struct qrtr_lookup *lookup;
struct qrtr_server *srv;
@@ -286,7 +286,7 @@ static int server_del(struct qrtr_node *node, unsigned int port)
radix_tree_delete(&node->servers, port);
/* Broadcast the removal of local servers */
- if (srv->node == qrtr_ns.local_node)
+ if (srv->node == qrtr_ns.local_node && bcast)
service_announce_del(&qrtr_ns.bcast_sq, srv);
/* Announce the service's disappearance to observers */
@@ -372,7 +372,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from)
}
slot = radix_tree_iter_resume(slot, &iter);
rcu_read_unlock();
- server_del(node, srv->port);
+ server_del(node, srv->port, true);
rcu_read_lock();
}
rcu_read_unlock();
@@ -458,10 +458,13 @@ static int ctrl_cmd_del_client(struct sockaddr_qrtr *from,
kfree(lookup);
}
- /* Remove the server belonging to this port */
+ /* Remove the server belonging to this port but don't broadcast
+ * DEL_SERVER. Neighbours would've already removed the server belonging
+ * to this port due to the DEL_CLIENT broadcast from qrtr_port_remove().
+ */
node = node_get(node_id);
if (node)
- server_del(node, port);
+ server_del(node, port, false);
/* Advertise the removal of this client to all local servers */
local_node = node_get(qrtr_ns.local_node);
@@ -566,7 +569,7 @@ static int ctrl_cmd_del_server(struct sockaddr_qrtr *from,
if (!node)
return -ENOENT;
- return server_del(node, port);
+ return server_del(node, port, true);
}
static int ctrl_cmd_new_lookup(struct sockaddr_qrtr *from,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 84021a6c4f9d..ec7d1a89efbb 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1829,6 +1829,10 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len);
if (err)
goto err;
+ if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) {
+ err = -EINVAL;
+ goto err;
+ }
}
if (sctp_state(asoc, CLOSED)) {
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index b1efc34db6ed..609ade4fb49e 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -416,14 +416,23 @@ static int unix_gid_hash(kuid_t uid)
return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS);
}
-static void unix_gid_put(struct kref *kref)
+static void unix_gid_free(struct rcu_head *rcu)
{
- struct cache_head *item = container_of(kref, struct cache_head, ref);
- struct unix_gid *ug = container_of(item, struct unix_gid, h);
+ struct unix_gid *ug = container_of(rcu, struct unix_gid, rcu);
+ struct cache_head *item = &ug->h;
+
if (test_bit(CACHE_VALID, &item->flags) &&
!test_bit(CACHE_NEGATIVE, &item->flags))
put_group_info(ug->gi);
- kfree_rcu(ug, rcu);
+ kfree(ug);
+}
+
+static void unix_gid_put(struct kref *kref)
+{
+ struct cache_head *item = container_of(kref, struct cache_head, ref);
+ struct unix_gid *ug = container_of(item, struct unix_gid, h);
+
+ call_rcu(&ug->rcu, unix_gid_free);
}
static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 9ea633fe9339..4ffa3a59f419 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -81,6 +81,7 @@ struct hdmi_spec_per_pin {
struct delayed_work work;
struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/
int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */
+ int prev_pcm_idx; /* previously assigned pcm index */
int repoll_count;
bool setup; /* the stream has been set up by prepare callback */
bool silent_stream;
@@ -1380,9 +1381,17 @@ static void hdmi_attach_hda_pcm(struct hdmi_spec *spec,
/* pcm already be attached to the pin */
if (per_pin->pcm)
return;
+ /* try the previously used slot at first */
+ idx = per_pin->prev_pcm_idx;
+ if (idx >= 0) {
+ if (!test_bit(idx, &spec->pcm_bitmap))
+ goto found;
+ per_pin->prev_pcm_idx = -1; /* no longer valid, clear it */
+ }
idx = hdmi_find_pcm_slot(spec, per_pin);
if (idx == -EBUSY)
return;
+ found:
per_pin->pcm_idx = idx;
per_pin->pcm = get_hdmi_pcm(spec, idx);
set_bit(idx, &spec->pcm_bitmap);
@@ -1398,6 +1407,7 @@ static void hdmi_detach_hda_pcm(struct hdmi_spec *spec,
return;
idx = per_pin->pcm_idx;
per_pin->pcm_idx = -1;
+ per_pin->prev_pcm_idx = idx; /* remember the previous index */
per_pin->pcm = NULL;
if (idx >= 0 && idx < spec->pcm_used)
clear_bit(idx, &spec->pcm_bitmap);
@@ -1924,6 +1934,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
per_pin->pcm = NULL;
per_pin->pcm_idx = -1;
+ per_pin->prev_pcm_idx = -1;
per_pin->pin_nid = pin_nid;
per_pin->pin_nid_idx = spec->num_nids;
per_pin->dev_id = i;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 070150bbd355..50b8573b5206 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2624,6 +2624,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
+ SND_PCI_QUIRK(0x1558, 0x3702, "Clevo X370SN[VW]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
@@ -9442,6 +9443,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8b47, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+ SND_PCI_QUIRK(0x103c, 0x8b66, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b7a, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b7d, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b87, "HP", ALC236_FIXUP_HP_GPIO_LED),
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index ed4f7cdda04f..8b6b76029694 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -436,23 +436,28 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_device *hdev,
return 0;
}
-static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai,
- unsigned int tx_mask, unsigned int rx_mask,
- int slots, int slot_width)
+static int hdac_hdmi_set_stream(struct snd_soc_dai *dai,
+ void *stream, int direction)
{
struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai);
struct hdac_device *hdev = hdmi->hdev;
struct hdac_hdmi_dai_port_map *dai_map;
struct hdac_hdmi_pcm *pcm;
+ struct hdac_stream *hstream;
- dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, tx_mask);
+ if (!stream)
+ return -EINVAL;
+
+ hstream = (struct hdac_stream *)stream;
+
+ dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, hstream->stream_tag);
dai_map = &hdmi->dai_map[dai->id];
pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
if (pcm)
- pcm->stream_tag = (tx_mask << 4);
+ pcm->stream_tag = (hstream->stream_tag << 4);
return 0;
}
@@ -1544,7 +1549,7 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = {
.startup = hdac_hdmi_pcm_open,
.shutdown = hdac_hdmi_pcm_close,
.hw_params = hdac_hdmi_set_hw_params,
- .set_tdm_slot = hdac_hdmi_set_tdm_slot,
+ .set_stream = hdac_hdmi_set_stream,
};
/*
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
index 8621cfabcf5b..1639f3b66fac 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -3667,9 +3667,9 @@ static int __maybe_unused rx_macro_runtime_suspend(struct device *dev)
regcache_cache_only(rx->regmap, true);
regcache_mark_dirty(rx->regmap);
- clk_disable_unprepare(rx->mclk);
- clk_disable_unprepare(rx->npl);
clk_disable_unprepare(rx->fsgen);
+ clk_disable_unprepare(rx->npl);
+ clk_disable_unprepare(rx->mclk);
return 0;
}
diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c
index 8facdb922f07..9f33289ce217 100644
--- a/sound/soc/codecs/lpass-tx-macro.c
+++ b/sound/soc/codecs/lpass-tx-macro.c
@@ -2093,9 +2093,9 @@ static int __maybe_unused tx_macro_runtime_suspend(struct device *dev)
regcache_cache_only(tx->regmap, true);
regcache_mark_dirty(tx->regmap);
- clk_disable_unprepare(tx->mclk);
- clk_disable_unprepare(tx->npl);
clk_disable_unprepare(tx->fsgen);
+ clk_disable_unprepare(tx->npl);
+ clk_disable_unprepare(tx->mclk);
return 0;
}
diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
index c0b86d69c72e..01149b20b4c9 100644
--- a/sound/soc/codecs/lpass-wsa-macro.c
+++ b/sound/soc/codecs/lpass-wsa-macro.c
@@ -2504,9 +2504,9 @@ static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev)
regcache_cache_only(wsa->regmap, true);
regcache_mark_dirty(wsa->regmap);
- clk_disable_unprepare(wsa->mclk);
- clk_disable_unprepare(wsa->npl);
clk_disable_unprepare(wsa->fsgen);
+ clk_disable_unprepare(wsa->npl);
+ clk_disable_unprepare(wsa->mclk);
return 0;
}
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 6da6137fa2cb..4f7adbe671f3 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -1686,6 +1686,14 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *
u32 header, extension;
int ret;
+ if (!src_fw_module || !sink_fw_module) {
+ /* The NULL module will print as "(efault)" */
+ dev_err(sdev->dev, "source %s or sink %s widget weren't set up properly\n",
+ src_fw_module->man4_module_entry.name,
+ sink_fw_module->man4_module_entry.name);
+ return -ENODEV;
+ }
+
sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget,
SOF_PIN_TYPE_SOURCE);
if (sroute->src_queue_id < 0) {
diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c
index 74cd7e956019..280fc89043b1 100644
--- a/sound/soc/sof/ipc4.c
+++ b/sound/soc/sof/ipc4.c
@@ -393,6 +393,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_
static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
size_t payload_bytes, bool set)
{
+ const struct sof_dsp_power_state target_state = {
+ .state = SOF_DSP_PM_D0,
+ };
size_t payload_limit = sdev->ipc->max_payload_size;
struct sof_ipc4_msg *ipc4_msg = data;
struct sof_ipc4_msg tx = {{ 0 }};
@@ -423,6 +426,11 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
tx.extension |= SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(1);
+ /* ensure the DSP is in D0i0 before sending IPC */
+ ret = snd_sof_dsp_set_power_state(sdev, &target_state);
+ if (ret < 0)
+ return ret;
+
/* Serialise IPC TX */
mutex_lock(&sdev->ipc->tx_mutex);
diff --git a/tools/testing/radix-tree/maple.c b/tools/testing/radix-tree/maple.c
index 81fa7ec2e66a..1f36bc1c5d36 100644
--- a/tools/testing/radix-tree/maple.c
+++ b/tools/testing/radix-tree/maple.c
@@ -173,11 +173,11 @@ static noinline void check_new_node(struct maple_tree *mt)
if (!MAPLE_32BIT) {
if (i >= 35)
- e = i - 35;
+ e = i - 34;
else if (i >= 5)
- e = i - 5;
+ e = i - 4;
else if (i >= 2)
- e = i - 2;
+ e = i - 1;
} else {
if (i >= 4)
e = i - 4;
@@ -305,17 +305,17 @@ static noinline void check_new_node(struct maple_tree *mt)
MT_BUG_ON(mt, mas.node != MA_ERROR(-ENOMEM));
MT_BUG_ON(mt, !mas_nomem(&mas, GFP_KERNEL));
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 1);
- MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 1);
+ MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS);
mn = mas_pop_node(&mas); /* get the next node. */
MT_BUG_ON(mt, mn == NULL);
MT_BUG_ON(mt, not_empty(mn));
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS);
- MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 2);
+ MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 1);
mas_push_node(&mas, mn);
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 1);
- MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 1);
+ MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS);
/* Check the limit of pop/push/pop */
mas_node_count(&mas, MAPLE_ALLOC_SLOTS + 2); /* Request */
@@ -323,14 +323,14 @@ static noinline void check_new_node(struct maple_tree *mt)
MT_BUG_ON(mt, mas.node != MA_ERROR(-ENOMEM));
MT_BUG_ON(mt, !mas_nomem(&mas, GFP_KERNEL));
MT_BUG_ON(mt, mas_alloc_req(&mas));
- MT_BUG_ON(mt, mas.alloc->node_count);
+ MT_BUG_ON(mt, mas.alloc->node_count != 1);
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 2);
mn = mas_pop_node(&mas);
MT_BUG_ON(mt, not_empty(mn));
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 1);
- MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 1);
+ MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS);
mas_push_node(&mas, mn);
- MT_BUG_ON(mt, mas.alloc->node_count);
+ MT_BUG_ON(mt, mas.alloc->node_count != 1);
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 2);
mn = mas_pop_node(&mas);
MT_BUG_ON(mt, not_empty(mn));
^ permalink raw reply related [relevance 1%]
* Re: Linux 6.1.24
@ 2023-04-13 15:19 1% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-04-13 15:19 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/Documentation/devicetree/bindings/serial/renesas,scif.yaml b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
index f930e7f1349f..52c094873863 100644
--- a/Documentation/devicetree/bindings/serial/renesas,scif.yaml
+++ b/Documentation/devicetree/bindings/serial/renesas,scif.yaml
@@ -91,7 +91,7 @@ properties:
- description: Error interrupt
- description: Receive buffer full interrupt
- description: Transmit buffer empty interrupt
- - description: Transmit End interrupt
+ - description: Break interrupt
- items:
- description: Error interrupt
- description: Receive buffer full interrupt
@@ -106,7 +106,7 @@ properties:
- const: eri
- const: rxi
- const: txi
- - const: tei
+ - const: bri
- items:
- const: eri
- const: rxi
diff --git a/Documentation/mm/zsmalloc.rst b/Documentation/mm/zsmalloc.rst
index 6e79893d6132..d98607aa9c1f 100644
--- a/Documentation/mm/zsmalloc.rst
+++ b/Documentation/mm/zsmalloc.rst
@@ -68,6 +68,8 @@ pages_used
the number of pages allocated for the class
pages_per_zspage
the number of 0-order pages to make a zspage
+freeable
+ the approximate number of pages class compaction can free
We assign a zspage to ZS_ALMOST_EMPTY fullness group when n <= N / f, where
diff --git a/Makefile b/Makefile
index a162f6cdf77c..4f9939dec2c2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
-SUBLEVEL = 23
+SUBLEVEL = 24
EXTRAVERSION =
NAME = Hurr durr I'ma ninja sloth
diff --git a/arch/arm64/kernel/compat_alignment.c b/arch/arm64/kernel/compat_alignment.c
index 5edec2f49ec9..deff21bfa680 100644
--- a/arch/arm64/kernel/compat_alignment.c
+++ b/arch/arm64/kernel/compat_alignment.c
@@ -314,36 +314,32 @@ int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs)
int (*handler)(unsigned long addr, u32 instr, struct pt_regs *regs);
unsigned int type;
u32 instr = 0;
- u16 tinstr = 0;
int isize = 4;
int thumb2_32b = 0;
- int fault;
instrptr = instruction_pointer(regs);
if (compat_thumb_mode(regs)) {
__le16 __user *ptr = (__le16 __user *)(instrptr & ~1);
+ u16 tinstr, tinst2;
- fault = alignment_get_thumb(regs, ptr, &tinstr);
- if (!fault) {
- if (IS_T32(tinstr)) {
- /* Thumb-2 32-bit */
- u16 tinst2;
- fault = alignment_get_thumb(regs, ptr + 1, &tinst2);
- instr = ((u32)tinstr << 16) | tinst2;
- thumb2_32b = 1;
- } else {
- isize = 2;
- instr = thumb2arm(tinstr);
- }
+ if (alignment_get_thumb(regs, ptr, &tinstr))
+ return 1;
+
+ if (IS_T32(tinstr)) { /* Thumb-2 32-bit */
+ if (alignment_get_thumb(regs, ptr + 1, &tinst2))
+ return 1;
+ instr = ((u32)tinstr << 16) | tinst2;
+ thumb2_32b = 1;
+ } else {
+ isize = 2;
+ instr = thumb2arm(tinstr);
}
} else {
- fault = alignment_get_arm(regs, (__le32 __user *)instrptr, &instr);
+ if (alignment_get_arm(regs, (__le32 __user *)instrptr, &instr))
+ return 1;
}
- if (fault)
- return 1;
-
switch (CODING_BITS(instr)) {
case 0x00000000: /* 3.13.4 load/store instruction extensions */
if (LDSTHD_I_BIT(instr))
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 0003c7d37533..67770375c5ee 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -15,16 +15,14 @@
#include <kvm/arm_pmu.h>
#include <kvm/arm_vgic.h>
+#define PERF_ATTR_CFG1_COUNTER_64BIT BIT(0)
+
DEFINE_STATIC_KEY_FALSE(kvm_arm_pmu_available);
static LIST_HEAD(arm_pmus);
static DEFINE_MUTEX(arm_pmus_lock);
static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx);
-static void kvm_pmu_update_pmc_chained(struct kvm_vcpu *vcpu, u64 select_idx);
-static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc);
-
-#define PERF_ATTR_CFG1_KVM_PMU_CHAINED 0x1
static u32 kvm_pmu_event_mask(struct kvm *kvm)
{
@@ -52,11 +50,22 @@ static u32 kvm_pmu_event_mask(struct kvm *kvm)
* @select_idx: The counter index
*/
static bool kvm_pmu_idx_is_64bit(struct kvm_vcpu *vcpu, u64 select_idx)
+{
+ return (select_idx == ARMV8_PMU_CYCLE_IDX);
+}
+
+static bool kvm_pmu_idx_has_64bit_overflow(struct kvm_vcpu *vcpu, u64 select_idx)
{
return (select_idx == ARMV8_PMU_CYCLE_IDX &&
__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_LC);
}
+static bool kvm_pmu_counter_can_chain(struct kvm_vcpu *vcpu, u64 idx)
+{
+ return (!(idx & 1) && (idx + 1) < ARMV8_PMU_CYCLE_IDX &&
+ !kvm_pmu_idx_has_64bit_overflow(vcpu, idx));
+}
+
static struct kvm_vcpu *kvm_pmc_to_vcpu(struct kvm_pmc *pmc)
{
struct kvm_pmu *pmu;
@@ -69,91 +78,22 @@ static struct kvm_vcpu *kvm_pmc_to_vcpu(struct kvm_pmc *pmc)
}
/**
- * kvm_pmu_pmc_is_chained - determine if the pmc is chained
- * @pmc: The PMU counter pointer
- */
-static bool kvm_pmu_pmc_is_chained(struct kvm_pmc *pmc)
-{
- struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
-
- return test_bit(pmc->idx >> 1, vcpu->arch.pmu.chained);
-}
-
-/**
- * kvm_pmu_idx_is_high_counter - determine if select_idx is a high/low counter
- * @select_idx: The counter index
- */
-static bool kvm_pmu_idx_is_high_counter(u64 select_idx)
-{
- return select_idx & 0x1;
-}
-
-/**
- * kvm_pmu_get_canonical_pmc - obtain the canonical pmc
- * @pmc: The PMU counter pointer
- *
- * When a pair of PMCs are chained together we use the low counter (canonical)
- * to hold the underlying perf event.
- */
-static struct kvm_pmc *kvm_pmu_get_canonical_pmc(struct kvm_pmc *pmc)
-{
- if (kvm_pmu_pmc_is_chained(pmc) &&
- kvm_pmu_idx_is_high_counter(pmc->idx))
- return pmc - 1;
-
- return pmc;
-}
-static struct kvm_pmc *kvm_pmu_get_alternate_pmc(struct kvm_pmc *pmc)
-{
- if (kvm_pmu_idx_is_high_counter(pmc->idx))
- return pmc - 1;
- else
- return pmc + 1;
-}
-
-/**
- * kvm_pmu_idx_has_chain_evtype - determine if the event type is chain
+ * kvm_pmu_get_counter_value - get PMU counter value
* @vcpu: The vcpu pointer
* @select_idx: The counter index
*/
-static bool kvm_pmu_idx_has_chain_evtype(struct kvm_vcpu *vcpu, u64 select_idx)
-{
- u64 eventsel, reg;
-
- select_idx |= 0x1;
-
- if (select_idx == ARMV8_PMU_CYCLE_IDX)
- return false;
-
- reg = PMEVTYPER0_EL0 + select_idx;
- eventsel = __vcpu_sys_reg(vcpu, reg) & kvm_pmu_event_mask(vcpu->kvm);
-
- return eventsel == ARMV8_PMUV3_PERFCTR_CHAIN;
-}
-
-/**
- * kvm_pmu_get_pair_counter_value - get PMU counter value
- * @vcpu: The vcpu pointer
- * @pmc: The PMU counter pointer
- */
-static u64 kvm_pmu_get_pair_counter_value(struct kvm_vcpu *vcpu,
- struct kvm_pmc *pmc)
+u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
{
- u64 counter, counter_high, reg, enabled, running;
-
- if (kvm_pmu_pmc_is_chained(pmc)) {
- pmc = kvm_pmu_get_canonical_pmc(pmc);
- reg = PMEVCNTR0_EL0 + pmc->idx;
+ u64 counter, reg, enabled, running;
+ struct kvm_pmu *pmu = &vcpu->arch.pmu;
+ struct kvm_pmc *pmc = &pmu->pmc[select_idx];
- counter = __vcpu_sys_reg(vcpu, reg);
- counter_high = __vcpu_sys_reg(vcpu, reg + 1);
+ if (!kvm_vcpu_has_pmu(vcpu))
+ return 0;
- counter = lower_32_bits(counter) | (counter_high << 32);
- } else {
- reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX)
- ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx;
- counter = __vcpu_sys_reg(vcpu, reg);
- }
+ reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX)
+ ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx;
+ counter = __vcpu_sys_reg(vcpu, reg);
/*
* The real counter value is equal to the value of counter register plus
@@ -163,29 +103,7 @@ static u64 kvm_pmu_get_pair_counter_value(struct kvm_vcpu *vcpu,
counter += perf_event_read_value(pmc->perf_event, &enabled,
&running);
- return counter;
-}
-
-/**
- * kvm_pmu_get_counter_value - get PMU counter value
- * @vcpu: The vcpu pointer
- * @select_idx: The counter index
- */
-u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
-{
- u64 counter;
- struct kvm_pmu *pmu = &vcpu->arch.pmu;
- struct kvm_pmc *pmc = &pmu->pmc[select_idx];
-
- if (!kvm_vcpu_has_pmu(vcpu))
- return 0;
-
- counter = kvm_pmu_get_pair_counter_value(vcpu, pmc);
-
- if (kvm_pmu_pmc_is_chained(pmc) &&
- kvm_pmu_idx_is_high_counter(select_idx))
- counter = upper_32_bits(counter);
- else if (select_idx != ARMV8_PMU_CYCLE_IDX)
+ if (!kvm_pmu_idx_is_64bit(vcpu, select_idx))
counter = lower_32_bits(counter);
return counter;
@@ -218,7 +136,6 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
*/
static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc)
{
- pmc = kvm_pmu_get_canonical_pmc(pmc);
if (pmc->perf_event) {
perf_event_disable(pmc->perf_event);
perf_event_release_kernel(pmc->perf_event);
@@ -236,11 +153,10 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
{
u64 counter, reg, val;
- pmc = kvm_pmu_get_canonical_pmc(pmc);
if (!pmc->perf_event)
return;
- counter = kvm_pmu_get_pair_counter_value(vcpu, pmc);
+ counter = kvm_pmu_get_counter_value(vcpu, pmc->idx);
if (pmc->idx == ARMV8_PMU_CYCLE_IDX) {
reg = PMCCNTR_EL0;
@@ -252,9 +168,6 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
__vcpu_sys_reg(vcpu, reg) = val;
- if (kvm_pmu_pmc_is_chained(pmc))
- __vcpu_sys_reg(vcpu, reg + 1) = upper_32_bits(counter);
-
kvm_pmu_release_perf_event(pmc);
}
@@ -285,8 +198,6 @@ void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu)
for_each_set_bit(i, &mask, 32)
kvm_pmu_stop_counter(vcpu, &pmu->pmc[i]);
-
- bitmap_zero(vcpu->arch.pmu.chained, ARMV8_PMU_MAX_COUNTER_PAIRS);
}
/**
@@ -340,12 +251,9 @@ void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
pmc = &pmu->pmc[i];
- /* A change in the enable state may affect the chain state */
- kvm_pmu_update_pmc_chained(vcpu, i);
- kvm_pmu_create_perf_event(vcpu, i);
-
- /* At this point, pmc must be the canonical */
- if (pmc->perf_event) {
+ if (!pmc->perf_event) {
+ kvm_pmu_create_perf_event(vcpu, i);
+ } else {
perf_event_enable(pmc->perf_event);
if (pmc->perf_event->state != PERF_EVENT_STATE_ACTIVE)
kvm_debug("fail to enable perf event\n");
@@ -375,11 +283,6 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
pmc = &pmu->pmc[i];
- /* A change in the enable state may affect the chain state */
- kvm_pmu_update_pmc_chained(vcpu, i);
- kvm_pmu_create_perf_event(vcpu, i);
-
- /* At this point, pmc must be the canonical */
if (pmc->perf_event)
perf_event_disable(pmc->perf_event);
}
@@ -484,6 +387,65 @@ static void kvm_pmu_perf_overflow_notify_vcpu(struct irq_work *work)
kvm_vcpu_kick(vcpu);
}
+/*
+ * Perform an increment on any of the counters described in @mask,
+ * generating the overflow if required, and propagate it as a chained
+ * event if possible.
+ */
+static void kvm_pmu_counter_increment(struct kvm_vcpu *vcpu,
+ unsigned long mask, u32 event)
+{
+ int i;
+
+ if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E))
+ return;
+
+ /* Weed out disabled counters */
+ mask &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
+
+ for_each_set_bit(i, &mask, ARMV8_PMU_CYCLE_IDX) {
+ u64 type, reg;
+
+ /* Filter on event type */
+ type = __vcpu_sys_reg(vcpu, PMEVTYPER0_EL0 + i);
+ type &= kvm_pmu_event_mask(vcpu->kvm);
+ if (type != event)
+ continue;
+
+ /* Increment this counter */
+ reg = __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) + 1;
+ reg = lower_32_bits(reg);
+ __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) = reg;
+
+ if (reg) /* No overflow? move on */
+ continue;
+
+ /* Mark overflow */
+ __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i);
+
+ if (kvm_pmu_counter_can_chain(vcpu, i))
+ kvm_pmu_counter_increment(vcpu, BIT(i + 1),
+ ARMV8_PMUV3_PERFCTR_CHAIN);
+ }
+}
+
+/* Compute the sample period for a given counter value */
+static u64 compute_period(struct kvm_vcpu *vcpu, u64 select_idx, u64 counter)
+{
+ u64 val;
+
+ if (kvm_pmu_idx_is_64bit(vcpu, select_idx)) {
+ if (!kvm_pmu_idx_has_64bit_overflow(vcpu, select_idx))
+ val = -(counter & GENMASK(31, 0));
+ else
+ val = (-counter) & GENMASK(63, 0);
+ } else {
+ val = (-counter) & GENMASK(31, 0);
+ }
+
+ return val;
+}
+
/**
* When the perf event overflows, set the overflow status and inform the vcpu.
*/
@@ -503,10 +465,7 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
* Reset the sample period to the architectural limit,
* i.e. the point where the counter overflows.
*/
- period = -(local64_read(&perf_event->count));
-
- if (!kvm_pmu_idx_is_64bit(vcpu, pmc->idx))
- period &= GENMASK(31, 0);
+ period = compute_period(vcpu, idx, local64_read(&perf_event->count));
local64_set(&perf_event->hw.period_left, 0);
perf_event->attr.sample_period = period;
@@ -514,6 +473,10 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
__vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx);
+ if (kvm_pmu_counter_can_chain(vcpu, idx))
+ kvm_pmu_counter_increment(vcpu, BIT(idx + 1),
+ ARMV8_PMUV3_PERFCTR_CHAIN);
+
if (kvm_pmu_overflow_status(vcpu)) {
kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
@@ -533,50 +496,7 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
*/
void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val)
{
- struct kvm_pmu *pmu = &vcpu->arch.pmu;
- int i;
-
- if (!kvm_vcpu_has_pmu(vcpu))
- return;
-
- if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E))
- return;
-
- /* Weed out disabled counters */
- val &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
-
- for (i = 0; i < ARMV8_PMU_CYCLE_IDX; i++) {
- u64 type, reg;
-
- if (!(val & BIT(i)))
- continue;
-
- /* PMSWINC only applies to ... SW_INC! */
- type = __vcpu_sys_reg(vcpu, PMEVTYPER0_EL0 + i);
- type &= kvm_pmu_event_mask(vcpu->kvm);
- if (type != ARMV8_PMUV3_PERFCTR_SW_INCR)
- continue;
-
- /* increment this even SW_INC counter */
- reg = __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) + 1;
- reg = lower_32_bits(reg);
- __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) = reg;
-
- if (reg) /* no overflow on the low part */
- continue;
-
- if (kvm_pmu_pmc_is_chained(&pmu->pmc[i])) {
- /* increment the high counter */
- reg = __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i + 1) + 1;
- reg = lower_32_bits(reg);
- __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i + 1) = reg;
- if (!reg) /* mark overflow on the high counter */
- __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i + 1);
- } else {
- /* mark overflow on low counter */
- __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i);
- }
- }
+ kvm_pmu_counter_increment(vcpu, val, ARMV8_PMUV3_PERFCTR_SW_INCR);
}
/**
@@ -591,6 +511,9 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
if (!kvm_vcpu_has_pmu(vcpu))
return;
+ /* The reset bits don't indicate any state, and shouldn't be saved. */
+ __vcpu_sys_reg(vcpu, PMCR_EL0) = val & ~(ARMV8_PMU_PMCR_C | ARMV8_PMU_PMCR_P);
+
if (val & ARMV8_PMU_PMCR_E) {
kvm_pmu_enable_counter_mask(vcpu,
__vcpu_sys_reg(vcpu, PMCNTENSET_EL0));
@@ -625,18 +548,11 @@ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx)
{
struct arm_pmu *arm_pmu = vcpu->kvm->arch.arm_pmu;
struct kvm_pmu *pmu = &vcpu->arch.pmu;
- struct kvm_pmc *pmc;
+ struct kvm_pmc *pmc = &pmu->pmc[select_idx];
struct perf_event *event;
struct perf_event_attr attr;
u64 eventsel, counter, reg, data;
- /*
- * For chained counters the event type and filtering attributes are
- * obtained from the low/even counter. We also use this counter to
- * determine if the event is enabled/disabled.
- */
- pmc = kvm_pmu_get_canonical_pmc(&pmu->pmc[select_idx]);
-
reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX)
? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + pmc->idx;
data = __vcpu_sys_reg(vcpu, reg);
@@ -647,8 +563,12 @@ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx)
else
eventsel = data & kvm_pmu_event_mask(vcpu->kvm);
- /* Software increment event doesn't need to be backed by a perf event */
- if (eventsel == ARMV8_PMUV3_PERFCTR_SW_INCR)
+ /*
+ * Neither SW increment nor chained events need to be backed
+ * by a perf event.
+ */
+ if (eventsel == ARMV8_PMUV3_PERFCTR_SW_INCR ||
+ eventsel == ARMV8_PMUV3_PERFCTR_CHAIN)
return;
/*
@@ -670,30 +590,20 @@ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx)
attr.exclude_host = 1; /* Don't count host events */
attr.config = eventsel;
- counter = kvm_pmu_get_pair_counter_value(vcpu, pmc);
+ counter = kvm_pmu_get_counter_value(vcpu, select_idx);
- if (kvm_pmu_pmc_is_chained(pmc)) {
- /**
- * The initial sample period (overflow count) of an event. For
- * chained counters we only support overflow interrupts on the
- * high counter.
- */
- attr.sample_period = (-counter) & GENMASK(63, 0);
- attr.config1 |= PERF_ATTR_CFG1_KVM_PMU_CHAINED;
+ /*
+ * If counting with a 64bit counter, advertise it to the perf
+ * code, carefully dealing with the initial sample period
+ * which also depends on the overflow.
+ */
+ if (kvm_pmu_idx_is_64bit(vcpu, select_idx))
+ attr.config1 |= PERF_ATTR_CFG1_COUNTER_64BIT;
- event = perf_event_create_kernel_counter(&attr, -1, current,
- kvm_pmu_perf_overflow,
- pmc + 1);
- } else {
- /* The initial sample period (overflow count) of an event. */
- if (kvm_pmu_idx_is_64bit(vcpu, pmc->idx))
- attr.sample_period = (-counter) & GENMASK(63, 0);
- else
- attr.sample_period = (-counter) & GENMASK(31, 0);
+ attr.sample_period = compute_period(vcpu, select_idx, counter);
- event = perf_event_create_kernel_counter(&attr, -1, current,
+ event = perf_event_create_kernel_counter(&attr, -1, current,
kvm_pmu_perf_overflow, pmc);
- }
if (IS_ERR(event)) {
pr_err_once("kvm: pmu event creation failed %ld\n",
@@ -704,41 +614,6 @@ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx)
pmc->perf_event = event;
}
-/**
- * kvm_pmu_update_pmc_chained - update chained bitmap
- * @vcpu: The vcpu pointer
- * @select_idx: The number of selected counter
- *
- * Update the chained bitmap based on the event type written in the
- * typer register and the enable state of the odd register.
- */
-static void kvm_pmu_update_pmc_chained(struct kvm_vcpu *vcpu, u64 select_idx)
-{
- struct kvm_pmu *pmu = &vcpu->arch.pmu;
- struct kvm_pmc *pmc = &pmu->pmc[select_idx], *canonical_pmc;
- bool new_state, old_state;
-
- old_state = kvm_pmu_pmc_is_chained(pmc);
- new_state = kvm_pmu_idx_has_chain_evtype(vcpu, pmc->idx) &&
- kvm_pmu_counter_is_enabled(vcpu, pmc->idx | 0x1);
-
- if (old_state == new_state)
- return;
-
- canonical_pmc = kvm_pmu_get_canonical_pmc(pmc);
- kvm_pmu_stop_counter(vcpu, canonical_pmc);
- if (new_state) {
- /*
- * During promotion from !chained to chained we must ensure
- * the adjacent counter is stopped and its event destroyed
- */
- kvm_pmu_stop_counter(vcpu, kvm_pmu_get_alternate_pmc(pmc));
- set_bit(pmc->idx >> 1, vcpu->arch.pmu.chained);
- return;
- }
- clear_bit(pmc->idx >> 1, vcpu->arch.pmu.chained);
-}
-
/**
* kvm_pmu_set_counter_event_type - set selected counter to monitor some event
* @vcpu: The vcpu pointer
@@ -766,7 +641,6 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
__vcpu_sys_reg(vcpu, reg) = data & mask;
- kvm_pmu_update_pmc_chained(vcpu, select_idx);
kvm_pmu_create_perf_event(vcpu, select_idx);
}
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index bfe4f17232b3..1f80e17a6460 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -697,13 +697,15 @@ static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
return false;
if (p->is_write) {
- /* Only update writeable bits of PMCR */
+ /*
+ * Only update writeable bits of PMCR (continuing into
+ * kvm_pmu_handle_pmcr() as well)
+ */
val = __vcpu_sys_reg(vcpu, PMCR_EL0);
val &= ~ARMV8_PMU_PMCR_MASK;
val |= p->regval & ARMV8_PMU_PMCR_MASK;
if (!kvm_supports_32bit_el0())
val |= ARMV8_PMU_PMCR_LC;
- __vcpu_sys_reg(vcpu, PMCR_EL0) = val;
kvm_pmu_handle_pmcr(vcpu, val);
kvm_vcpu_pmu_restore_guest(vcpu);
} else {
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 88112065d941..ee7478a60144 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -271,10 +271,18 @@ static int handle_prog(struct kvm_vcpu *vcpu)
* handle_external_interrupt - used for external interruption interceptions
* @vcpu: virtual cpu
*
- * This interception only occurs if the CPUSTAT_EXT_INT bit was set, or if
- * the new PSW does not have external interrupts disabled. In the first case,
- * we've got to deliver the interrupt manually, and in the second case, we
- * drop to userspace to handle the situation there.
+ * This interception occurs if:
+ * - the CPUSTAT_EXT_INT bit was already set when the external interrupt
+ * occurred. In this case, the interrupt needs to be injected manually to
+ * preserve interrupt priority.
+ * - the external new PSW has external interrupts enabled, which will cause an
+ * interruption loop. We drop to userspace in this case.
+ *
+ * The latter case can be detected by inspecting the external mask bit in the
+ * external new psw.
+ *
+ * Under PV, only the latter case can occur, since interrupt priorities are
+ * handled in the ultravisor.
*/
static int handle_external_interrupt(struct kvm_vcpu *vcpu)
{
@@ -285,10 +293,18 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu)
vcpu->stat.exit_external_interrupt++;
- rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t));
- if (rc)
- return rc;
- /* We can not handle clock comparator or timer interrupt with bad PSW */
+ if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+ newpsw = vcpu->arch.sie_block->gpsw;
+ } else {
+ rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t));
+ if (rc)
+ return rc;
+ }
+
+ /*
+ * Clock comparator or timer interrupt with external interrupt enabled
+ * will cause interrupt loop. Drop to userspace.
+ */
if ((eic == EXT_IRQ_CLK_COMP || eic == EXT_IRQ_CPU_TIMER) &&
(newpsw.mask & PSW_MASK_EXT))
return -EOPNOTSUPP;
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 518bda50068c..0f762070a5e1 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -146,7 +146,11 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
pr_debug("Local APIC address 0x%08x\n", madt->address);
}
- if (madt->header.revision >= 5)
+
+ /* ACPI 6.3 and newer support the online capable bit. */
+ if (acpi_gbl_FADT.header.revision > 6 ||
+ (acpi_gbl_FADT.header.revision == 6 &&
+ acpi_gbl_FADT.minor_revision >= 3))
acpi_support_online_capable = true;
default_acpi_madt_oem_check(madt->header.oem_id,
@@ -193,7 +197,8 @@ static bool __init acpi_is_processor_usable(u32 lapic_flags)
if (lapic_flags & ACPI_MADT_ENABLED)
return true;
- if (acpi_support_online_capable && (lapic_flags & ACPI_MADT_ONLINE_CAPABLE))
+ if (!acpi_support_online_capable ||
+ (lapic_flags & ACPI_MADT_ONLINE_CAPABLE))
return true;
return false;
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 1d00f7824da1..8e56ec6e72e9 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -3845,7 +3845,12 @@ static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu)
exit_qual = 0;
}
- if (ex->has_error_code) {
+ /*
+ * Unlike AMD's Paged Real Mode, which reports an error code on #PF
+ * VM-Exits even if the CPU is in Real Mode, Intel VMX never sets the
+ * "has error code" flags on VM-Exit if the CPU is in Real Mode.
+ */
+ if (ex->has_error_code && is_protmode(vcpu)) {
/*
* Intel CPUs do not generate error codes with bits 31:16 set,
* and more importantly VMX disallows setting bits 31:16 in the
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ab09d292bded..3463ef7f3019 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9853,13 +9853,20 @@ int kvm_check_nested_events(struct kvm_vcpu *vcpu)
static void kvm_inject_exception(struct kvm_vcpu *vcpu)
{
+ /*
+ * Suppress the error code if the vCPU is in Real Mode, as Real Mode
+ * exceptions don't report error codes. The presence of an error code
+ * is carried with the exception and only stripped when the exception
+ * is injected as intercepted #PF VM-Exits for AMD's Paged Real Mode do
+ * report an error code despite the CPU being in Real Mode.
+ */
+ vcpu->arch.exception.has_error_code &= is_protmode(vcpu);
+
trace_kvm_inj_exception(vcpu->arch.exception.vector,
vcpu->arch.exception.has_error_code,
vcpu->arch.exception.error_code,
vcpu->arch.exception.injected);
- if (vcpu->arch.exception.error_code && !is_protmode(vcpu))
- vcpu->arch.exception.error_code = false;
static_call(kvm_x86_inject_exception)(vcpu);
}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index aa67a52c5a06..1b04a1c48ee5 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1327,8 +1327,6 @@ bool blk_rq_is_poll(struct request *rq)
return false;
if (rq->mq_hctx->type != HCTX_TYPE_POLL)
return false;
- if (WARN_ON_ONCE(!rq->bio))
- return false;
return true;
}
EXPORT_SYMBOL_GPL(blk_rq_is_poll);
@@ -1336,7 +1334,7 @@ EXPORT_SYMBOL_GPL(blk_rq_is_poll);
static void blk_rq_poll_completion(struct request *rq, struct completion *wait)
{
do {
- bio_poll(rq->bio, NULL, 0);
+ blk_mq_poll(rq->q, blk_rq_to_qc(rq), NULL, 0);
cond_resched();
} while (!completion_done(wait));
}
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 847721dc2b2b..f1bc600c4ded 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1066,7 +1066,6 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw)
sq->nr_queued[rw]--;
throtl_charge_bio(tg, bio);
- bio_set_flag(bio, BIO_BPS_THROTTLED);
/*
* If our parent is another tg, we just need to transfer @bio to
@@ -1079,6 +1078,7 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw)
throtl_add_bio_tg(bio, &tg->qnode_on_parent[rw], parent_tg);
start_parent_slice_with_credit(tg, parent_tg, rw);
} else {
+ bio_set_flag(bio, BIO_BPS_THROTTLED);
throtl_qnode_add_bio(bio, &tg->qnode_on_parent[rw],
&parent_sq->queued[rw]);
BUG_ON(tg->td->nr_queued[rw] <= 0);
diff --git a/block/genhd.c b/block/genhd.c
index 0b6928e948f3..62a61388e752 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -368,7 +368,6 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
if (disk->open_partitions)
return -EBUSY;
- set_bit(GD_NEED_PART_SCAN, &disk->state);
/*
* If the device is opened exclusively by current thread already, it's
* safe to scan partitons, otherwise, use bd_prepare_to_claim() to
@@ -381,12 +380,19 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
return ret;
}
+ set_bit(GD_NEED_PART_SCAN, &disk->state);
bdev = blkdev_get_by_dev(disk_devt(disk), mode & ~FMODE_EXCL, NULL);
if (IS_ERR(bdev))
ret = PTR_ERR(bdev);
else
blkdev_put(bdev, mode & ~FMODE_EXCL);
+ /*
+ * If blkdev_get_by_dev() failed early, GD_NEED_PART_SCAN is still set,
+ * and this will cause that re-assemble partitioned raid device will
+ * creat partition for underlying disk.
+ */
+ clear_bit(GD_NEED_PART_SCAN, &disk->state);
if (!(mode & FMODE_EXCL))
bd_abort_claiming(disk->part0, disk_scan_partitions);
return ret;
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index 0c79f463fbfd..ed318485eb19 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -1984,6 +1984,7 @@ static int instance;
static int acpi_video_bus_add(struct acpi_device *device)
{
struct acpi_video_bus *video;
+ bool auto_detect;
int error;
acpi_status status;
@@ -2045,10 +2046,20 @@ static int acpi_video_bus_add(struct acpi_device *device)
mutex_unlock(&video_list_lock);
/*
- * The userspace visible backlight_device gets registered separately
- * from acpi_video_register_backlight().
+ * If backlight-type auto-detection is used then a native backlight may
+ * show up later and this may change the result from video to native.
+ * Therefor normally the userspace visible /sys/class/backlight device
+ * gets registered separately by the GPU driver calling
+ * acpi_video_register_backlight() when an internal panel is detected.
+ * Register the backlight now when not using auto-detection, so that
+ * when the kernel cmdline or DMI-quirks are used the backlight will
+ * get registered even if acpi_video_register_backlight() is not called.
*/
acpi_video_run_bcl_for_osi(video);
+ if (__acpi_video_get_backlight_type(false, &auto_detect) == acpi_backlight_video &&
+ !auto_detect)
+ acpi_video_bus_register_backlight(video);
+
acpi_video_bus_add_notify_handler(video);
return 0;
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index f06b3d355671..42b5af5490a1 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -274,6 +274,43 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
},
+ /*
+ * Models which need acpi_video backlight control where the GPU drivers
+ * do not call acpi_video_register_backlight() because no internal panel
+ * is detected. Typically these are all-in-ones (monitors with builtin
+ * PC) where the panel connection shows up as regular DP instead of eDP.
+ */
+ {
+ .callback = video_detect_force_video,
+ /* Apple iMac14,1 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac14,1"),
+ },
+ },
+ {
+ .callback = video_detect_force_video,
+ /* Apple iMac14,2 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac14,2"),
+ },
+ },
+
+ /*
+ * Older models with nvidia GPU which need acpi_video backlight
+ * control and where the old nvidia binary driver series does not
+ * call acpi_video_register_backlight().
+ */
+ {
+ .callback = video_detect_force_video,
+ /* ThinkPad W530 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"),
+ },
+ },
+
/*
* These models have a working acpi_video backlight control, and using
* native backlight causes a regression where backlight does not work
@@ -772,7 +809,7 @@ static bool prefer_native_over_acpi_video(void)
* Determine which type of backlight interface to use on this system,
* First check cmdline, then dmi quirks, then do autodetect.
*/
-static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
+enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto_detect)
{
static DEFINE_MUTEX(init_mutex);
static bool nvidia_wmi_ec_present;
@@ -797,6 +834,9 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
native_available = true;
mutex_unlock(&init_mutex);
+ if (auto_detect)
+ *auto_detect = false;
+
/*
* The below heuristics / detection steps are in order of descending
* presedence. The commandline takes presedence over anything else.
@@ -808,6 +848,9 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
if (acpi_backlight_dmi != acpi_backlight_undef)
return acpi_backlight_dmi;
+ if (auto_detect)
+ *auto_detect = true;
+
/* Special cases such as nvidia_wmi_ec and apple gmux. */
if (nvidia_wmi_ec_present)
return acpi_backlight_nvidia_wmi_ec;
@@ -827,15 +870,4 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
/* No ACPI video/native (old hw), use vendor specific fw methods. */
return acpi_backlight_vendor;
}
-
-enum acpi_backlight_type acpi_video_get_backlight_type(void)
-{
- return __acpi_video_get_backlight_type(false);
-}
-EXPORT_SYMBOL(acpi_video_get_backlight_type);
-
-bool acpi_video_backlight_use_native(void)
-{
- return __acpi_video_get_backlight_type(true) == acpi_backlight_native;
-}
-EXPORT_SYMBOL(acpi_video_backlight_use_native);
+EXPORT_SYMBOL(__acpi_video_get_backlight_type);
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 22a790d51284..2ed994a313a9 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -233,7 +233,7 @@ static int ublk_validate_params(const struct ublk_device *ub)
if (ub->params.types & UBLK_PARAM_TYPE_BASIC) {
const struct ublk_param_basic *p = &ub->params.basic;
- if (p->logical_bs_shift > PAGE_SHIFT)
+ if (p->logical_bs_shift > PAGE_SHIFT || p->logical_bs_shift < 9)
return -EINVAL;
if (p->logical_bs_shift > p->physical_bs_shift)
@@ -1202,9 +1202,10 @@ static void ublk_handle_need_get_data(struct ublk_device *ub, int q_id,
ublk_queue_cmd(ubq, req);
}
-static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
+static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
+ unsigned int issue_flags,
+ struct ublksrv_io_cmd *ub_cmd)
{
- struct ublksrv_io_cmd *ub_cmd = (struct ublksrv_io_cmd *)cmd->cmd;
struct ublk_device *ub = cmd->file->private_data;
struct ublk_queue *ubq;
struct ublk_io *io;
@@ -1306,6 +1307,23 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
return -EIOCBQUEUED;
}
+static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
+{
+ struct ublksrv_io_cmd *ub_src = (struct ublksrv_io_cmd *) cmd->cmd;
+ struct ublksrv_io_cmd ub_cmd;
+
+ /*
+ * Not necessary for async retry, but let's keep it simple and always
+ * copy the values to avoid any potential reuse.
+ */
+ ub_cmd.q_id = READ_ONCE(ub_src->q_id);
+ ub_cmd.tag = READ_ONCE(ub_src->tag);
+ ub_cmd.result = READ_ONCE(ub_src->result);
+ ub_cmd.addr = READ_ONCE(ub_src->addr);
+
+ return __ublk_ch_uring_cmd(cmd, issue_flags, &ub_cmd);
+}
+
static const struct file_operations ublk_ch_fops = {
.owner = THIS_MODULE,
.open = ublk_ch_open,
@@ -1886,6 +1904,8 @@ static int ublk_ctrl_set_params(struct io_uring_cmd *cmd)
/* clear all we don't support yet */
ub->params.types &= UBLK_PARAM_TYPE_ALL;
ret = ublk_validate_params(ub);
+ if (ret)
+ ub->params.types = 0;
}
mutex_unlock(&ub->mutex);
ublk_put_device(ub);
diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
index deed4afadb29..d9cb937665cf 100644
--- a/drivers/counter/104-quad-8.c
+++ b/drivers/counter/104-quad-8.c
@@ -97,10 +97,6 @@ struct quad8 {
struct quad8_reg __iomem *reg;
};
-/* Borrow Toggle flip-flop */
-#define QUAD8_FLAG_BT BIT(0)
-/* Carry Toggle flip-flop */
-#define QUAD8_FLAG_CT BIT(1)
/* Error flag */
#define QUAD8_FLAG_E BIT(4)
/* Up/Down flag */
@@ -133,6 +129,9 @@ struct quad8 {
#define QUAD8_CMR_QUADRATURE_X2 0x10
#define QUAD8_CMR_QUADRATURE_X4 0x18
+/* Each Counter is 24 bits wide */
+#define LS7267_CNTR_MAX GENMASK(23, 0)
+
static int quad8_signal_read(struct counter_device *counter,
struct counter_signal *signal,
enum counter_signal_level *level)
@@ -156,18 +155,10 @@ static int quad8_count_read(struct counter_device *counter,
{
struct quad8 *const priv = counter_priv(counter);
struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
- unsigned int flags;
- unsigned int borrow;
- unsigned int carry;
unsigned long irqflags;
int i;
- flags = ioread8(&chan->control);
- borrow = flags & QUAD8_FLAG_BT;
- carry = !!(flags & QUAD8_FLAG_CT);
-
- /* Borrow XOR Carry effectively doubles count range */
- *val = (unsigned long)(borrow ^ carry) << 24;
+ *val = 0;
spin_lock_irqsave(&priv->lock, irqflags);
@@ -191,8 +182,7 @@ static int quad8_count_write(struct counter_device *counter,
unsigned long irqflags;
int i;
- /* Only 24-bit values are supported */
- if (val > 0xFFFFFF)
+ if (val > LS7267_CNTR_MAX)
return -ERANGE;
spin_lock_irqsave(&priv->lock, irqflags);
@@ -378,7 +368,7 @@ static int quad8_action_read(struct counter_device *counter,
/* Handle Index signals */
if (synapse->signal->id >= 16) {
- if (priv->preset_enable[count->id])
+ if (!priv->preset_enable[count->id])
*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
else
*action = COUNTER_SYNAPSE_ACTION_NONE;
@@ -806,8 +796,7 @@ static int quad8_count_preset_write(struct counter_device *counter,
struct quad8 *const priv = counter_priv(counter);
unsigned long irqflags;
- /* Only 24-bit values are supported */
- if (preset > 0xFFFFFF)
+ if (preset > LS7267_CNTR_MAX)
return -ERANGE;
spin_lock_irqsave(&priv->lock, irqflags);
@@ -834,8 +823,7 @@ static int quad8_count_ceiling_read(struct counter_device *counter,
*ceiling = priv->preset[count->id];
break;
default:
- /* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
- *ceiling = 0x1FFFFFF;
+ *ceiling = LS7267_CNTR_MAX;
break;
}
@@ -850,8 +838,7 @@ static int quad8_count_ceiling_write(struct counter_device *counter,
struct quad8 *const priv = counter_priv(counter);
unsigned long irqflags;
- /* Only 24-bit values are supported */
- if (ceiling > 0xFFFFFF)
+ if (ceiling > LS7267_CNTR_MAX)
return -ERANGE;
spin_lock_irqsave(&priv->lock, irqflags);
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 9240df53ed87..a8456d5441fc 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -483,7 +483,7 @@ static struct pci_doe_mb *find_cdat_doe(struct device *uport)
return NULL;
}
-#define CDAT_DOE_REQ(entry_handle) \
+#define CDAT_DOE_REQ(entry_handle) cpu_to_le32 \
(FIELD_PREP(CXL_DOE_TABLE_ACCESS_REQ_CODE, \
CXL_DOE_TABLE_ACCESS_REQ_CODE_READ) | \
FIELD_PREP(CXL_DOE_TABLE_ACCESS_TABLE_TYPE, \
@@ -496,8 +496,8 @@ static void cxl_doe_task_complete(struct pci_doe_task *task)
}
struct cdat_doe_task {
- u32 request_pl;
- u32 response_pl[32];
+ __le32 request_pl;
+ __le32 response_pl[32];
struct completion c;
struct pci_doe_task task;
};
@@ -531,10 +531,10 @@ static int cxl_cdat_get_length(struct device *dev,
return rc;
}
wait_for_completion(&t.c);
- if (t.task.rv < sizeof(u32))
+ if (t.task.rv < 2 * sizeof(__le32))
return -EIO;
- *length = t.response_pl[1];
+ *length = le32_to_cpu(t.response_pl[1]);
dev_dbg(dev, "CDAT length %zu\n", *length);
return 0;
@@ -545,13 +545,13 @@ static int cxl_cdat_read_table(struct device *dev,
struct cxl_cdat *cdat)
{
size_t length = cdat->length;
- u32 *data = cdat->table;
+ __le32 *data = cdat->table;
int entry_handle = 0;
do {
DECLARE_CDAT_DOE_TASK(CDAT_DOE_REQ(entry_handle), t);
+ struct cdat_entry_header *entry;
size_t entry_dw;
- u32 *entry;
int rc;
rc = pci_doe_submit_task(cdat_doe, &t.task);
@@ -560,26 +560,34 @@ static int cxl_cdat_read_table(struct device *dev,
return rc;
}
wait_for_completion(&t.c);
- /* 1 DW header + 1 DW data min */
- if (t.task.rv < (2 * sizeof(u32)))
+
+ /* 1 DW Table Access Response Header + CDAT entry */
+ entry = (struct cdat_entry_header *)(t.response_pl + 1);
+ if ((entry_handle == 0 &&
+ t.task.rv != sizeof(__le32) + sizeof(struct cdat_header)) ||
+ (entry_handle > 0 &&
+ (t.task.rv < sizeof(__le32) + sizeof(*entry) ||
+ t.task.rv != sizeof(__le32) + le16_to_cpu(entry->length))))
return -EIO;
/* Get the CXL table access header entry handle */
entry_handle = FIELD_GET(CXL_DOE_TABLE_ACCESS_ENTRY_HANDLE,
- t.response_pl[0]);
- entry = t.response_pl + 1;
- entry_dw = t.task.rv / sizeof(u32);
+ le32_to_cpu(t.response_pl[0]));
+ entry_dw = t.task.rv / sizeof(__le32);
/* Skip Header */
entry_dw -= 1;
- entry_dw = min(length / sizeof(u32), entry_dw);
+ entry_dw = min(length / sizeof(__le32), entry_dw);
/* Prevent length < 1 DW from causing a buffer overflow */
if (entry_dw) {
- memcpy(data, entry, entry_dw * sizeof(u32));
- length -= entry_dw * sizeof(u32);
+ memcpy(data, entry, entry_dw * sizeof(__le32));
+ length -= entry_dw * sizeof(__le32);
data += entry_dw;
}
} while (entry_handle != CXL_DOE_TABLE_ACCESS_LAST_ENTRY);
+ /* Length in CDAT header may exceed concatenation of CDAT entries */
+ cdat->length -= length;
+
return 0;
}
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index eec597dbe763..79e5603dfc82 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -71,6 +71,20 @@ static inline resource_size_t cxl_regmap_to_base(struct pci_dev *pdev,
return pci_resource_start(pdev, map->barno) + map->block_offset;
}
+struct cdat_header {
+ __le32 length;
+ u8 revision;
+ u8 checksum;
+ u8 reserved[6];
+ __le32 sequence;
+} __packed;
+
+struct cdat_entry_header {
+ u8 type;
+ u8 reserved;
+ __le16 length;
+} __packed;
+
int devm_cxl_port_enumerate_dports(struct cxl_port *port);
struct cxl_dev_state;
int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a01af1180616..e3af86f06c63 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -100,7 +100,7 @@ config GPIO_GENERIC
tristate
config GPIO_REGMAP
- depends on REGMAP
+ select REGMAP
tristate
# put drivers in the right section, in alphabetical order
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 59c4c48d8296..69f3d864f69d 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -328,7 +328,7 @@ static struct irq_chip gpio_irqchip = {
.irq_enable = gpio_irq_enable,
.irq_disable = gpio_irq_disable,
.irq_set_type = gpio_irq_type,
- .flags = IRQCHIP_SET_TYPE_MASKED,
+ .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE,
};
static void gpio_irq_handler(struct irq_desc *desc)
@@ -645,9 +645,6 @@ static void davinci_gpio_save_context(struct davinci_gpio_controller *chips,
context->set_falling = readl_relaxed(&g->set_falling);
}
- /* Clear Bank interrupt enable bit */
- writel_relaxed(0, base + BINTEN);
-
/* Clear all interrupt status registers */
writel_relaxed(GENMASK(31, 0), &g->intstat);
}
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 1bb317b8dcce..91a4232ee58c 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -657,9 +657,10 @@ static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
spin_unlock_irqrestore(&mvpwm->lock, flags);
}
-static void mvebu_pwm_get_state(struct pwm_chip *chip,
- struct pwm_device *pwm,
- struct pwm_state *state) {
+static int mvebu_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
+{
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
@@ -693,6 +694,8 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
state->enabled = false;
spin_unlock_irqrestore(&mvpwm->lock, flags);
+
+ return 0;
}
static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 9ef83f3ab3a7..9df5dcedaf3e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3034,6 +3034,24 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_MES))
continue;
+ /* SDMA 5.x+ is part of GFX power domain so it's covered by GFXOFF */
+ if (adev->in_s0ix &&
+ (adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(5, 0, 0)) &&
+ (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
+ continue;
+
+ /* Once swPSP provides the IMU, RLC FW binaries to TOS during cold-boot.
+ * These are in TMR, hence are expected to be reused by PSP-TOS to reload
+ * from this location and RLC Autoload automatically also gets loaded
+ * from here based on PMFW -> PSP message during re-init sequence.
+ * Therefore, the psp suspend & resume should be skipped to avoid destroy
+ * the TMR and reload FWs again for IMU enabled APU ASICs.
+ */
+ if (amdgpu_in_reset(adev) &&
+ (adev->flags & AMD_IS_APU) && adev->gfx.imu.funcs &&
+ adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
+ continue;
+
/* XXX handle errors */
r = adev->ip_blocks[i].version->funcs->suspend(adev);
/* XXX handle errors */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 050e7a52c8f6..6c5ea99223ba 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2175,6 +2175,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev)
DRM_ERROR("DM_MST: Failed to start MST\n");
aconnector->dc_link->type =
dc_connection_single;
+ ret = dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx,
+ aconnector->dc_link);
break;
}
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 57454967617f..6bd7e4537014 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -206,7 +206,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
if (enable)
drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
else
- drm_dp_remove_payload(mst_mgr, mst_state, payload);
+ drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
* AUX message. The sequence is slot 1-63 allocated sequence for each
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c
index 3b77238ca4af..ae8c6d9d4095 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
@@ -258,6 +258,7 @@ static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode
{ 0x8126, 0x55 },
{ 0x8127, 0x66 },
{ 0x8128, 0x88 },
+ { 0x812a, 0x20 },
};
regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg));
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index eb24322df721..aeca9c066bf2 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -1500,8 +1500,8 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
-static void ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct ti_sn65dsi86 *pdata = pwm_chip_to_ti_sn_bridge(chip);
unsigned int pwm_en_inv;
@@ -1512,19 +1512,19 @@ static void ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
ret = regmap_read(pdata->regmap, SN_PWM_EN_INV_REG, &pwm_en_inv);
if (ret)
- return;
+ return 0;
ret = ti_sn65dsi86_read_u16(pdata, SN_BACKLIGHT_SCALE_REG, &scale);
if (ret)
- return;
+ return 0;
ret = ti_sn65dsi86_read_u16(pdata, SN_BACKLIGHT_REG, &backlight);
if (ret)
- return;
+ return 0;
ret = regmap_read(pdata->regmap, SN_PWM_PRE_DIV_REG, &pre_div);
if (ret)
- return;
+ return 0;
state->enabled = FIELD_GET(SN_PWM_EN_MASK, pwm_en_inv);
if (FIELD_GET(SN_PWM_INV_MASK, pwm_en_inv))
@@ -1539,6 +1539,8 @@ static void ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
if (state->duty_cycle > state->period)
state->duty_cycle = state->period;
+
+ return 0;
}
static const struct pwm_ops ti_sn_pwm_ops = {
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index e77c674b37ca..38dab76ae69e 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
* drm_dp_remove_payload() - Remove an MST payload
* @mgr: Manager to use.
* @mst_state: The MST atomic state
- * @payload: The payload to write
+ * @old_payload: The payload with its old state
+ * @new_payload: The payload to write
*
* Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
* the starting time slots of all other payloads which would have been shifted towards the start of
@@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
*/
void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_topology_state *mst_state,
- struct drm_dp_mst_atomic_payload *payload)
+ const struct drm_dp_mst_atomic_payload *old_payload,
+ struct drm_dp_mst_atomic_payload *new_payload)
{
struct drm_dp_mst_atomic_payload *pos;
bool send_remove = false;
/* We failed to make the payload, so nothing to do */
- if (payload->vc_start_slot == -1)
+ if (new_payload->vc_start_slot == -1)
return;
mutex_lock(&mgr->lock);
- send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
+ send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
mutex_unlock(&mgr->lock);
if (send_remove)
- drm_dp_destroy_payload_step1(mgr, mst_state, payload);
+ drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
else
drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
- payload->vcpi);
+ new_payload->vcpi);
list_for_each_entry(pos, &mst_state->payloads, next) {
- if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
- pos->vc_start_slot -= payload->time_slots;
+ if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
+ pos->vc_start_slot -= old_payload->time_slots;
}
- payload->vc_start_slot = -1;
+ new_payload->vc_start_slot = -1;
mgr->payload_count--;
- mgr->next_start_slot -= payload->time_slots;
+ mgr->next_start_slot -= old_payload->time_slots;
- if (payload->delete)
- drm_dp_mst_put_port_malloc(payload->port);
+ if (new_payload->delete)
+ drm_dp_mst_put_port_malloc(new_payload->port);
}
EXPORT_SYMBOL(drm_dp_remove_payload);
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index c85757f55112..78211e583fd7 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -2098,6 +2098,25 @@ static void glk_read_luts(struct intel_crtc_state *crtc_state)
}
}
+static void icl_color_commit_arm(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+
+ /*
+ * We don't (yet) allow userspace to control the pipe background color,
+ * so force it to black.
+ */
+ intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), 0);
+
+ intel_de_write(i915, GAMMA_MODE(crtc->pipe),
+ crtc_state->gamma_mode);
+
+ intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
+ crtc_state->csc_mode);
+}
+
static struct drm_property_blob *
icl_read_lut_multi_segment(struct intel_crtc *crtc)
{
@@ -2183,7 +2202,7 @@ static const struct intel_color_funcs i9xx_color_funcs = {
static const struct intel_color_funcs icl_color_funcs = {
.color_check = icl_color_check,
.color_commit_noarm = icl_color_commit_noarm,
- .color_commit_arm = skl_color_commit_arm,
+ .color_commit_arm = icl_color_commit_arm,
.load_luts = icl_load_luts,
.read_luts = icl_read_luts,
};
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 27c2098dd707..9a6822256ddf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -364,8 +364,14 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
struct intel_dp *intel_dp = &dig_port->dp;
struct intel_connector *connector =
to_intel_connector(old_conn_state->connector);
- struct drm_dp_mst_topology_state *mst_state =
- drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+ struct drm_dp_mst_topology_state *old_mst_state =
+ drm_atomic_get_old_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+ struct drm_dp_mst_topology_state *new_mst_state =
+ drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+ const struct drm_dp_mst_atomic_payload *old_payload =
+ drm_atomic_get_mst_payload_state(old_mst_state, connector->port);
+ struct drm_dp_mst_atomic_payload *new_payload =
+ drm_atomic_get_mst_payload_state(new_mst_state, connector->port);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
drm_dbg_kms(&i915->drm, "active links %d\n",
@@ -373,8 +379,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
intel_hdcp_disable(intel_mst->connector);
- drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
- drm_atomic_get_mst_payload_state(mst_state, connector->port));
+ drm_dp_remove_payload(&intel_dp->mst_mgr, new_mst_state,
+ old_payload, new_payload);
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
}
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index bfd1ffc71a48..fc4a84628985 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -2017,6 +2017,8 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
* inspecting the queue to see if we need to resumbit.
*/
if (*prev != *execlists->active) { /* elide lite-restores */
+ struct intel_context *prev_ce = NULL, *active_ce = NULL;
+
/*
* Note the inherent discrepancy between the HW runtime,
* recorded as part of the context switch, and the CPU
@@ -2028,9 +2030,15 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
* and correct overselves later when updating from HW.
*/
if (*prev)
- lrc_runtime_stop((*prev)->context);
+ prev_ce = (*prev)->context;
if (*execlists->active)
- lrc_runtime_start((*execlists->active)->context);
+ active_ce = (*execlists->active)->context;
+ if (prev_ce != active_ce) {
+ if (prev_ce)
+ lrc_runtime_stop(prev_ce);
+ if (active_ce)
+ lrc_runtime_start(active_ce);
+ }
new_timeslice(execlists);
}
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 0defbb43ceea..3ce49c118b83 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -4270,13 +4270,13 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
err = oa_config->id;
goto sysfs_err;
}
-
- mutex_unlock(&perf->metrics_lock);
+ id = oa_config->id;
drm_dbg(&perf->i915->drm,
"Added config %s id=%i\n", oa_config->uuid, oa_config->id);
+ mutex_unlock(&perf->metrics_lock);
- return oa_config->id;
+ return id;
sysfs_err:
mutex_unlock(&perf->metrics_lock);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 64eacd11b8bf..2372bfa04aa8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3747,9 +3747,10 @@
/* Skylake+ pipe bottom (background) color */
#define _SKL_BOTTOM_COLOR_A 0x70034
+#define _SKL_BOTTOM_COLOR_B 0x71034
#define SKL_BOTTOM_COLOR_GAMMA_ENABLE REG_BIT(31)
#define SKL_BOTTOM_COLOR_CSC_ENABLE REG_BIT(30)
-#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE2(pipe, _SKL_BOTTOM_COLOR_A)
+#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE(pipe, _SKL_BOTTOM_COLOR_A, _SKL_BOTTOM_COLOR_B)
#define _ICL_PIPE_A_STATUS 0x70058
#define ICL_PIPESTATUS(pipe) _MMIO_PIPE2(pipe, _ICL_PIPE_A_STATUS)
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 33c97d510999..006cb76adaa9 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -410,6 +410,35 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,
return 0;
}
+static void
+nv50_outp_atomic_fix_depth(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state)
+{
+ struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct drm_display_mode *mode = &asyh->state.adjusted_mode;
+ unsigned int max_rate, mode_rate;
+
+ switch (nv_encoder->dcb->type) {
+ case DCB_OUTPUT_DP:
+ max_rate = nv_encoder->dp.link_nr * nv_encoder->dp.link_bw;
+
+ /* we don't support more than 10 anyway */
+ asyh->or.bpc = min_t(u8, asyh->or.bpc, 10);
+
+ /* reduce the bpc until it works out */
+ while (asyh->or.bpc > 6) {
+ mode_rate = DIV_ROUND_UP(mode->clock * asyh->or.bpc * 3, 8);
+ if (mode_rate <= max_rate)
+ break;
+
+ asyh->or.bpc -= 2;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
static int
nv50_outp_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
@@ -428,6 +457,9 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,
if (crtc_state->mode_changed || crtc_state->connectors_changed)
asyh->or.bpc = connector->display_info.bpc;
+ /* We might have to reduce the bpc */
+ nv50_outp_atomic_fix_depth(encoder, crtc_state);
+
return 0;
}
@@ -996,7 +1028,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
if (msto->disabled) {
- drm_dp_remove_payload(mgr, mst_state, payload);
+ drm_dp_remove_payload(mgr, mst_state, payload, payload);
} else {
if (msto->enabled)
drm_dp_add_payload_part1(mgr, mst_state, payload);
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 20db8ea1a0ba..53185746fb3d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -245,8 +245,6 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
}
/* TODO:
- * - Use the minimum possible BPC here, once we add support for the max bpc
- * property.
* - Validate against the DP caps advertised by the GPU (we don't check these
* yet)
*/
@@ -258,7 +256,11 @@ nv50_dp_mode_valid(struct drm_connector *connector,
{
const unsigned int min_clock = 25000;
unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock;
- const u8 bpp = connector->display_info.bpc * 3;
+ /* Check with the minmum bpc always, so we can advertise better modes.
+ * In particlar not doing this causes modes to be dropped on HDR
+ * displays as we might check with a bpc of 16 even.
+ */
+ const u8 bpp = 6 * 3;
if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
return MODE_NO_INTERLACE;
diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
index 666a5e53fe19..e961fa27702c 100644
--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -504,6 +504,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
if (IS_ERR(pages[i])) {
mutex_unlock(&bo->base.pages_lock);
ret = PTR_ERR(pages[i]);
+ pages[i] = NULL;
goto err_pages;
}
}
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 9dc27e5d367a..da51b50787df 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -409,6 +409,10 @@ void vmbus_disconnect(void)
*/
struct vmbus_channel *relid2channel(u32 relid)
{
+ if (vmbus_connection.channels == NULL) {
+ pr_warn_once("relid2channel: relid=%d: No channels mapped!\n", relid);
+ return NULL;
+ }
if (WARN_ON(relid >= MAX_CHANNEL_RELIDS))
return NULL;
return READ_ONCE(vmbus_connection.channels[relid]);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index c7a65d1524fc..1cf7478da6ee 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -451,7 +451,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
if (etm4x_sspcicrn_present(drvdata, i))
etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i));
}
- for (i = 0; i < drvdata->nr_addr_cmp; i++) {
+ for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
etm4x_relaxed_write64(csa, config->addr_val[i], TRCACVRn(i));
etm4x_relaxed_write64(csa, config->addr_acc[i], TRCACATRn(i));
}
@@ -1010,25 +1010,21 @@ static bool etm4_init_iomem_access(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
{
u32 devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
- u32 idr1 = readl_relaxed(drvdata->base + TRCIDR1);
/*
* All ETMs must implement TRCDEVARCH to indicate that
- * the component is an ETMv4. To support any broken
- * implementations we fall back to TRCIDR1 check, which
- * is not really reliable.
+ * the component is an ETMv4. Even though TRCIDR1 also
+ * contains the information, it is part of the "Trace"
+ * register and must be accessed with the OSLK cleared,
+ * with MMIO. But we cannot touch the OSLK until we are
+ * sure this is an ETM. So rely only on the TRCDEVARCH.
*/
- if ((devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH) {
- drvdata->arch = etm_devarch_to_arch(devarch);
- } else {
- pr_warn("CPU%d: ETM4x incompatible TRCDEVARCH: %x, falling back to TRCIDR1\n",
- smp_processor_id(), devarch);
-
- if (ETM_TRCIDR1_ARCH_MAJOR(idr1) != ETM_TRCIDR1_ARCH_ETMv4)
- return false;
- drvdata->arch = etm_trcidr_to_arch(idr1);
+ if ((devarch & ETM_DEVARCH_ID_MASK) != ETM_DEVARCH_ETMv4x_ARCH) {
+ pr_warn_once("TRCDEVARCH doesn't match ETMv4 architecture\n");
+ return false;
}
+ drvdata->arch = etm_devarch_to_arch(devarch);
*csa = CSDEV_ACCESS_IOMEM(drvdata->base);
return true;
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 4b21bb79f168..0174fbf1a963 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -753,14 +753,12 @@
* TRCDEVARCH - CoreSight architected register
* - Bits[15:12] - Major version
* - Bits[19:16] - Minor version
- * TRCIDR1 - ETM architected register
- * - Bits[11:8] - Major version
- * - Bits[7:4] - Minor version
- * We must rely on TRCDEVARCH for the version information,
- * however we don't want to break the support for potential
- * old implementations which might not implement it. Thus
- * we fall back to TRCIDR1 if TRCDEVARCH is not implemented
- * for memory mapped components.
+ *
+ * We must rely only on TRCDEVARCH for the version information. Even though,
+ * TRCIDR1 also provides the architecture version, it is a "Trace" register
+ * and as such must be accessed only with Trace power domain ON. This may
+ * not be available at probe time.
+ *
* Now to make certain decisions easier based on the version
* we use an internal representation of the version in the
* driver, as follows :
@@ -786,12 +784,6 @@ static inline u8 etm_devarch_to_arch(u32 devarch)
ETM_DEVARCH_REVISION(devarch));
}
-static inline u8 etm_trcidr_to_arch(u32 trcidr1)
-{
- return ETM_ARCH_VERSION(ETM_TRCIDR1_ARCH_MAJOR(trcidr1),
- ETM_TRCIDR1_ARCH_MINOR(trcidr1));
-}
-
enum etm_impdef_type {
ETM4_IMPDEF_HISI_CORE_COMMIT,
ETM4_IMPDEF_FEATURE_MAX,
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index fee8d129a5f0..86effe8501b4 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -253,7 +253,7 @@ static const struct ad_sigma_delta_info ad7791_sigma_delta_info = {
.has_registers = true,
.addr_shift = 4,
.read_mask = BIT(3),
- .irq_flags = IRQF_TRIGGER_LOW,
+ .irq_flags = IRQF_TRIGGER_FALLING,
};
static int ad7791_read_raw(struct iio_dev *indio_dev,
diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c
index 556f10dfb502..e1e14f5d237d 100644
--- a/drivers/iio/adc/ltc2497.c
+++ b/drivers/iio/adc/ltc2497.c
@@ -28,7 +28,6 @@ struct ltc2497_driverdata {
struct ltc2497core_driverdata common_ddata;
struct i2c_client *client;
u32 recv_size;
- u32 sub_lsb;
/*
* DMA (thus cache coherency maintenance) may require the
* transfer buffers to live in their own cache lines.
@@ -65,10 +64,10 @@ static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata,
* equivalent to a sign extension.
*/
if (st->recv_size == 3) {
- *val = (get_unaligned_be24(st->data.d8) >> st->sub_lsb)
+ *val = (get_unaligned_be24(st->data.d8) >> 6)
- BIT(ddata->chip_info->resolution + 1);
} else {
- *val = (be32_to_cpu(st->data.d32) >> st->sub_lsb)
+ *val = (be32_to_cpu(st->data.d32) >> 6)
- BIT(ddata->chip_info->resolution + 1);
}
@@ -122,7 +121,6 @@ static int ltc2497_probe(struct i2c_client *client,
st->common_ddata.chip_info = chip_info;
resolution = chip_info->resolution;
- st->sub_lsb = 31 - (resolution + 1);
st->recv_size = BITS_TO_BYTES(resolution) + 1;
return ltc2497core_probe(dev, indio_dev);
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
index 821fee60a765..d1b86570768a 100644
--- a/drivers/iio/adc/qcom-spmi-adc5.c
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -626,12 +626,20 @@ static int adc5_get_fw_channel_data(struct adc5_chip *adc,
struct fwnode_handle *fwnode,
const struct adc5_data *data)
{
- const char *name = fwnode_get_name(fwnode), *channel_name;
+ const char *channel_name;
+ char *name;
u32 chan, value, varr[2];
u32 sid = 0;
int ret;
struct device *dev = adc->dev;
+ name = devm_kasprintf(dev, GFP_KERNEL, "%pfwP", fwnode);
+ if (!name)
+ return -ENOMEM;
+
+ /* Cut the address part */
+ name[strchrnul(name, '@') - name] = '\0';
+
ret = fwnode_property_read_u32(fwnode, "reg", &chan);
if (ret) {
dev_err(dev, "invalid channel number %s\n", name);
diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c
index 2cc9a9bd9db6..263fc3a1b87e 100644
--- a/drivers/iio/adc/ti-ads7950.c
+++ b/drivers/iio/adc/ti-ads7950.c
@@ -634,6 +634,7 @@ static int ti_ads7950_probe(struct spi_device *spi)
st->chip.label = dev_name(&st->spi->dev);
st->chip.parent = &st->spi->dev;
st->chip.owner = THIS_MODULE;
+ st->chip.can_sleep = true;
st->chip.base = -1;
st->chip.ngpio = TI_ADS7950_NUM_GPIOS;
st->chip.get_direction = ti_ads7950_get_direction;
diff --git a/drivers/iio/dac/cio-dac.c b/drivers/iio/dac/cio-dac.c
index 791dd999cf29..18a64f72fc18 100644
--- a/drivers/iio/dac/cio-dac.c
+++ b/drivers/iio/dac/cio-dac.c
@@ -66,8 +66,8 @@ static int cio_dac_write_raw(struct iio_dev *indio_dev,
if (mask != IIO_CHAN_INFO_RAW)
return -EINVAL;
- /* DAC can only accept up to a 16-bit value */
- if ((unsigned int)val > 65535)
+ /* DAC can only accept up to a 12-bit value */
+ if ((unsigned int)val > 4095)
return -EINVAL;
priv->chan_out_states[chan->channel] = val;
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index f1d7d4b5e222..c2f97629e9cd 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -47,6 +47,7 @@ config ADIS16480
depends on SPI
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+ select CRC32
help
Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
ADIS16485, ADIS16488 inertial sensors.
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 228598b82a2f..7e7ee307a3f7 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -203,24 +203,27 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
break;
}
+ if (filp->f_flags & O_NONBLOCK) {
+ if (!written)
+ ret = -EAGAIN;
+ break;
+ }
+
wait_woken(&wait, TASK_INTERRUPTIBLE,
MAX_SCHEDULE_TIMEOUT);
continue;
}
ret = rb->access->write(rb, n - written, buf + written);
- if (ret == 0 && (filp->f_flags & O_NONBLOCK))
- ret = -EAGAIN;
+ if (ret < 0)
+ break;
- if (ret > 0) {
- written += ret;
- if (written != n && !(filp->f_flags & O_NONBLOCK))
- continue;
- }
- } while (ret == 0);
+ written += ret;
+
+ } while (written != n);
remove_wait_queue(&rb->pollq, &wait);
- return ret < 0 ? ret : n;
+ return ret < 0 ? ret : written;
}
/**
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index b1674a5bfa36..d4a34a3bf00d 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -429,6 +429,14 @@ static const struct iio_info cm32181_info = {
.attrs = &cm32181_attribute_group,
};
+static void cm32181_unregister_dummy_client(void *data)
+{
+ struct i2c_client *client = data;
+
+ /* Unregister the dummy client */
+ i2c_unregister_device(client);
+}
+
static int cm32181_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -460,6 +468,10 @@ static int cm32181_probe(struct i2c_client *client)
client = i2c_acpi_new_device(dev, 1, &board_info);
if (IS_ERR(client))
return PTR_ERR(client);
+
+ ret = devm_add_action_or_reset(dev, cm32181_unregister_dummy_client, client);
+ if (ret)
+ return ret;
}
cm32181 = iio_priv(indio_dev);
diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c
index c1a56259226f..f1c2419334e6 100644
--- a/drivers/leds/rgb/leds-qcom-lpg.c
+++ b/drivers/leds/rgb/leds-qcom-lpg.c
@@ -972,8 +972,8 @@ static int lpg_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
-static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct lpg *lpg = container_of(chip, struct lpg, pwm);
struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
@@ -986,20 +986,20 @@ static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
ret = regmap_read(lpg->map, chan->base + LPG_SIZE_CLK_REG, &val);
if (ret)
- return;
+ return 0;
refclk = lpg_clk_rates[val & PWM_CLK_SELECT_MASK];
if (refclk) {
ret = regmap_read(lpg->map, chan->base + LPG_PREDIV_CLK_REG, &val);
if (ret)
- return;
+ return 0;
pre_div = lpg_pre_divs[FIELD_GET(PWM_FREQ_PRE_DIV_MASK, val)];
m = FIELD_GET(PWM_FREQ_EXP_MASK, val);
ret = regmap_bulk_read(lpg->map, chan->base + PWM_VALUE_REG, &pwm_value, sizeof(pwm_value));
if (ret)
- return;
+ return 0;
state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * LPG_RESOLUTION * pre_div * (1 << m), refclk);
state->duty_cycle = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * pwm_value * pre_div * (1 << m), refclk);
@@ -1010,13 +1010,15 @@ static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
ret = regmap_read(lpg->map, chan->base + PWM_ENABLE_CONTROL_REG, &val);
if (ret)
- return;
+ return 0;
state->enabled = FIELD_GET(LPG_ENABLE_CONTROL_OUTPUT, val);
state->polarity = PWM_POLARITY_NORMAL;
if (state->duty_cycle > state->period)
state->duty_cycle = state->period;
+
+ return 0;
}
static const struct pwm_ops lpg_pwm_ops = {
diff --git a/drivers/md/dm-bio-prison-v1.c b/drivers/md/dm-bio-prison-v1.c
index 1f8f98efd97a..138067abe14b 100644
--- a/drivers/md/dm-bio-prison-v1.c
+++ b/drivers/md/dm-bio-prison-v1.c
@@ -285,14 +285,14 @@ EXPORT_SYMBOL_GPL(dm_cell_promote_or_release);
struct dm_deferred_entry {
struct dm_deferred_set *ds;
- unsigned count;
+ unsigned int count;
struct list_head work_items;
};
struct dm_deferred_set {
spinlock_t lock;
- unsigned current_entry;
- unsigned sweeper;
+ unsigned int current_entry;
+ unsigned int sweeper;
struct dm_deferred_entry entries[DEFERRED_SET_SIZE];
};
@@ -338,7 +338,7 @@ struct dm_deferred_entry *dm_deferred_entry_inc(struct dm_deferred_set *ds)
}
EXPORT_SYMBOL_GPL(dm_deferred_entry_inc);
-static unsigned ds_next(unsigned index)
+static unsigned int ds_next(unsigned int index)
{
return (index + 1) % DEFERRED_SET_SIZE;
}
@@ -373,7 +373,7 @@ EXPORT_SYMBOL_GPL(dm_deferred_entry_dec);
int dm_deferred_set_add_work(struct dm_deferred_set *ds, struct list_head *work)
{
int r = 1;
- unsigned next_entry;
+ unsigned int next_entry;
spin_lock_irq(&ds->lock);
if ((ds->sweeper == ds->current_entry) &&
diff --git a/drivers/md/dm-bio-prison-v2.c b/drivers/md/dm-bio-prison-v2.c
index 9dec3b61cf70..0cc0d13c40e5 100644
--- a/drivers/md/dm-bio-prison-v2.c
+++ b/drivers/md/dm-bio-prison-v2.c
@@ -148,7 +148,7 @@ static bool __find_or_insert(struct dm_bio_prison_v2 *prison,
static bool __get(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct bio *inmate,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell)
@@ -171,7 +171,7 @@ static bool __get(struct dm_bio_prison_v2 *prison,
bool dm_cell_get_v2(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct bio *inmate,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result)
@@ -224,7 +224,7 @@ EXPORT_SYMBOL_GPL(dm_cell_put_v2);
static int __lock(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result)
{
@@ -255,7 +255,7 @@ static int __lock(struct dm_bio_prison_v2 *prison,
int dm_cell_lock_v2(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result)
{
@@ -291,7 +291,7 @@ EXPORT_SYMBOL_GPL(dm_cell_quiesce_v2);
static int __promote(struct dm_bio_prison_v2 *prison,
struct dm_bio_prison_cell_v2 *cell,
- unsigned new_lock_level)
+ unsigned int new_lock_level)
{
if (!cell->exclusive_lock)
return -EINVAL;
@@ -302,7 +302,7 @@ static int __promote(struct dm_bio_prison_v2 *prison,
int dm_cell_lock_promote_v2(struct dm_bio_prison_v2 *prison,
struct dm_bio_prison_cell_v2 *cell,
- unsigned new_lock_level)
+ unsigned int new_lock_level)
{
int r;
diff --git a/drivers/md/dm-bio-prison-v2.h b/drivers/md/dm-bio-prison-v2.h
index 6e04234268db..5a7d996bbbd8 100644
--- a/drivers/md/dm-bio-prison-v2.h
+++ b/drivers/md/dm-bio-prison-v2.h
@@ -44,8 +44,8 @@ struct dm_cell_key_v2 {
struct dm_bio_prison_cell_v2 {
// FIXME: pack these
bool exclusive_lock;
- unsigned exclusive_level;
- unsigned shared_count;
+ unsigned int exclusive_level;
+ unsigned int shared_count;
struct work_struct *quiesce_continuation;
struct rb_node node;
@@ -86,7 +86,7 @@ void dm_bio_prison_free_cell_v2(struct dm_bio_prison_v2 *prison,
*/
bool dm_cell_get_v2(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct bio *inmate,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result);
@@ -114,7 +114,7 @@ bool dm_cell_put_v2(struct dm_bio_prison_v2 *prison,
*/
int dm_cell_lock_v2(struct dm_bio_prison_v2 *prison,
struct dm_cell_key_v2 *key,
- unsigned lock_level,
+ unsigned int lock_level,
struct dm_bio_prison_cell_v2 *cell_prealloc,
struct dm_bio_prison_cell_v2 **cell_result);
@@ -132,7 +132,7 @@ void dm_cell_quiesce_v2(struct dm_bio_prison_v2 *prison,
*/
int dm_cell_lock_promote_v2(struct dm_bio_prison_v2 *prison,
struct dm_bio_prison_cell_v2 *cell,
- unsigned new_lock_level);
+ unsigned int new_lock_level);
/*
* Adds any held bios to the bio list.
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 19caaf684ee3..382c5cc47195 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -89,7 +89,7 @@ struct dm_bufio_client {
unsigned long n_buffers[LIST_SIZE];
struct block_device *bdev;
- unsigned block_size;
+ unsigned int block_size;
s8 sectors_per_block_bits;
void (*alloc_callback)(struct dm_buffer *);
void (*write_callback)(struct dm_buffer *);
@@ -98,9 +98,9 @@ struct dm_bufio_client {
struct dm_io_client *dm_io;
struct list_head reserved_buffers;
- unsigned need_reserved_buffers;
+ unsigned int need_reserved_buffers;
- unsigned minimum_buffers;
+ unsigned int minimum_buffers;
struct rb_root buffer_tree;
wait_queue_head_t free_buffer_wait;
@@ -145,14 +145,14 @@ struct dm_buffer {
unsigned char list_mode; /* LIST_* */
blk_status_t read_error;
blk_status_t write_error;
- unsigned accessed;
- unsigned hold_count;
+ unsigned int accessed;
+ unsigned int hold_count;
unsigned long state;
unsigned long last_accessed;
- unsigned dirty_start;
- unsigned dirty_end;
- unsigned write_start;
- unsigned write_end;
+ unsigned int dirty_start;
+ unsigned int dirty_end;
+ unsigned int write_start;
+ unsigned int write_end;
struct dm_bufio_client *c;
struct list_head write_list;
void (*end_io)(struct dm_buffer *, blk_status_t);
@@ -220,7 +220,7 @@ static unsigned long global_num = 0;
/*
* Buffers are freed after this timeout
*/
-static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
+static unsigned int dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
static unsigned long dm_bufio_peak_allocated;
@@ -438,7 +438,7 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
* as if GFP_NOIO was specified.
*/
if (gfp_mask & __GFP_NORETRY) {
- unsigned noio_flag = memalloc_noio_save();
+ unsigned int noio_flag = memalloc_noio_save();
void *ptr = __vmalloc(c->block_size, gfp_mask);
memalloc_noio_restore(noio_flag);
@@ -591,7 +591,7 @@ static void dmio_complete(unsigned long error, void *context)
}
static void use_dmio(struct dm_buffer *b, enum req_op op, sector_t sector,
- unsigned n_sectors, unsigned offset)
+ unsigned int n_sectors, unsigned int offset)
{
int r;
struct dm_io_request io_req = {
@@ -629,11 +629,11 @@ static void bio_complete(struct bio *bio)
}
static void use_bio(struct dm_buffer *b, enum req_op op, sector_t sector,
- unsigned n_sectors, unsigned offset)
+ unsigned int n_sectors, unsigned int offset)
{
struct bio *bio;
char *ptr;
- unsigned vec_size, len;
+ unsigned int vec_size, len;
vec_size = b->c->block_size >> PAGE_SHIFT;
if (unlikely(b->c->sectors_per_block_bits < PAGE_SHIFT - SECTOR_SHIFT))
@@ -654,7 +654,7 @@ static void use_bio(struct dm_buffer *b, enum req_op op, sector_t sector,
len = n_sectors << SECTOR_SHIFT;
do {
- unsigned this_step = min((unsigned)(PAGE_SIZE - offset_in_page(ptr)), len);
+ unsigned int this_step = min((unsigned int)(PAGE_SIZE - offset_in_page(ptr)), len);
if (!bio_add_page(bio, virt_to_page(ptr), this_step,
offset_in_page(ptr))) {
bio_put(bio);
@@ -684,9 +684,9 @@ static inline sector_t block_to_sector(struct dm_bufio_client *c, sector_t block
static void submit_io(struct dm_buffer *b, enum req_op op,
void (*end_io)(struct dm_buffer *, blk_status_t))
{
- unsigned n_sectors;
+ unsigned int n_sectors;
sector_t sector;
- unsigned offset, end;
+ unsigned int offset, end;
b->end_io = end_io;
@@ -1156,7 +1156,7 @@ void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
EXPORT_SYMBOL_GPL(dm_bufio_new);
void dm_bufio_prefetch(struct dm_bufio_client *c,
- sector_t block, unsigned n_blocks)
+ sector_t block, unsigned int n_blocks)
{
struct blk_plug plug;
@@ -1232,7 +1232,7 @@ void dm_bufio_release(struct dm_buffer *b)
EXPORT_SYMBOL_GPL(dm_bufio_release);
void dm_bufio_mark_partial_buffer_dirty(struct dm_buffer *b,
- unsigned start, unsigned end)
+ unsigned int start, unsigned int end)
{
struct dm_bufio_client *c = b->c;
@@ -1529,13 +1529,13 @@ void dm_bufio_forget_buffers(struct dm_bufio_client *c, sector_t block, sector_t
}
EXPORT_SYMBOL_GPL(dm_bufio_forget_buffers);
-void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n)
+void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned int n)
{
c->minimum_buffers = n;
}
EXPORT_SYMBOL_GPL(dm_bufio_set_minimum_buffers);
-unsigned dm_bufio_get_block_size(struct dm_bufio_client *c)
+unsigned int dm_bufio_get_block_size(struct dm_bufio_client *c)
{
return c->block_size;
}
@@ -1734,15 +1734,15 @@ static unsigned long dm_bufio_shrink_count(struct shrinker *shrink, struct shrin
/*
* Create the buffering interface
*/
-struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
- unsigned reserved_buffers, unsigned aux_size,
+struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned int block_size,
+ unsigned int reserved_buffers, unsigned int aux_size,
void (*alloc_callback)(struct dm_buffer *),
void (*write_callback)(struct dm_buffer *),
unsigned int flags)
{
int r;
struct dm_bufio_client *c;
- unsigned i;
+ unsigned int i;
char slab_name[27];
if (!block_size || block_size & ((1 << SECTOR_SHIFT) - 1)) {
@@ -1796,7 +1796,7 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
if (block_size <= KMALLOC_MAX_SIZE &&
(block_size < PAGE_SIZE || !is_power_of_2(block_size))) {
- unsigned align = min(1U << __ffs(block_size), (unsigned)PAGE_SIZE);
+ unsigned int align = min(1U << __ffs(block_size), (unsigned int)PAGE_SIZE);
snprintf(slab_name, sizeof slab_name, "dm_bufio_cache-%u", block_size);
c->slab_cache = kmem_cache_create(slab_name, block_size, align,
SLAB_RECLAIM_ACCOUNT, NULL);
@@ -1872,7 +1872,7 @@ EXPORT_SYMBOL_GPL(dm_bufio_client_create);
*/
void dm_bufio_client_destroy(struct dm_bufio_client *c)
{
- unsigned i;
+ unsigned int i;
drop_buffers(c);
@@ -1920,9 +1920,9 @@ void dm_bufio_set_sector_offset(struct dm_bufio_client *c, sector_t start)
}
EXPORT_SYMBOL_GPL(dm_bufio_set_sector_offset);
-static unsigned get_max_age_hz(void)
+static unsigned int get_max_age_hz(void)
{
- unsigned max_age = READ_ONCE(dm_bufio_max_age);
+ unsigned int max_age = READ_ONCE(dm_bufio_max_age);
if (max_age > UINT_MAX / HZ)
max_age = UINT_MAX / HZ;
@@ -1973,7 +1973,7 @@ static void do_global_cleanup(struct work_struct *w)
struct dm_bufio_client *locked_client = NULL;
struct dm_bufio_client *current_client;
struct dm_buffer *b;
- unsigned spinlock_hold_count;
+ unsigned int spinlock_hold_count;
unsigned long threshold = dm_bufio_cache_size -
dm_bufio_cache_size / DM_BUFIO_LOW_WATERMARK_RATIO;
unsigned long loops = global_num * 2;
diff --git a/drivers/md/dm-cache-background-tracker.c b/drivers/md/dm-cache-background-tracker.c
index 7887f99b82bd..c606e6bfc3f8 100644
--- a/drivers/md/dm-cache-background-tracker.c
+++ b/drivers/md/dm-cache-background-tracker.c
@@ -17,7 +17,7 @@ struct bt_work {
};
struct background_tracker {
- unsigned max_work;
+ unsigned int max_work;
atomic_t pending_promotes;
atomic_t pending_writebacks;
atomic_t pending_demotes;
@@ -29,7 +29,7 @@ struct background_tracker {
struct kmem_cache *work_cache;
};
-struct background_tracker *btracker_create(unsigned max_work)
+struct background_tracker *btracker_create(unsigned int max_work)
{
struct background_tracker *b = kmalloc(sizeof(*b), GFP_KERNEL);
@@ -155,13 +155,13 @@ static void update_stats(struct background_tracker *b, struct policy_work *w, in
}
}
-unsigned btracker_nr_writebacks_queued(struct background_tracker *b)
+unsigned int btracker_nr_writebacks_queued(struct background_tracker *b)
{
return atomic_read(&b->pending_writebacks);
}
EXPORT_SYMBOL_GPL(btracker_nr_writebacks_queued);
-unsigned btracker_nr_demotions_queued(struct background_tracker *b)
+unsigned int btracker_nr_demotions_queued(struct background_tracker *b)
{
return atomic_read(&b->pending_demotes);
}
diff --git a/drivers/md/dm-cache-background-tracker.h b/drivers/md/dm-cache-background-tracker.h
index 27ab90dbc275..14d3d53dc77a 100644
--- a/drivers/md/dm-cache-background-tracker.h
+++ b/drivers/md/dm-cache-background-tracker.h
@@ -12,19 +12,44 @@
/*----------------------------------------------------------------*/
+/*
+ * The cache policy decides what background work should be performed,
+ * such as promotions, demotions and writebacks. The core cache target
+ * is in charge of performing the work, and does so when it sees fit.
+ *
+ * The background_tracker acts as a go between. Keeping track of future
+ * work that the policy has decided upon, and handing (issuing) it to
+ * the core target when requested.
+ *
+ * There is no locking in this, so calls will probably need to be
+ * protected with a spinlock.
+ */
+
struct background_work;
struct background_tracker;
/*
- * FIXME: discuss lack of locking in all methods.
+ * Create a new tracker, it will not be able to queue more than
+ * 'max_work' entries.
+ */
+struct background_tracker *btracker_create(unsigned int max_work);
+
+/*
+ * Destroy the tracker. No issued, but not complete, work should
+ * exist when this is called. It is fine to have queued but unissued
+ * work.
*/
-struct background_tracker *btracker_create(unsigned max_work);
void btracker_destroy(struct background_tracker *b);
-unsigned btracker_nr_writebacks_queued(struct background_tracker *b);
-unsigned btracker_nr_demotions_queued(struct background_tracker *b);
+unsigned int btracker_nr_writebacks_queued(struct background_tracker *b);
+unsigned int btracker_nr_demotions_queued(struct background_tracker *b);
/*
+ * Queue some work within the tracker. 'work' should point to the work
+ * to queue, this will be copied (ownership doesn't pass). If pwork
+ * is not NULL then it will be set to point to the tracker's internal
+ * copy of the work.
+ *
* returns -EINVAL iff the work is already queued. -ENOMEM if the work
* couldn't be queued for another reason.
*/
@@ -33,11 +58,20 @@ int btracker_queue(struct background_tracker *b,
struct policy_work **pwork);
/*
+ * Hands out the next piece of work to be performed.
* Returns -ENODATA if there's no work.
*/
int btracker_issue(struct background_tracker *b, struct policy_work **work);
-void btracker_complete(struct background_tracker *b,
- struct policy_work *op);
+
+/*
+ * Informs the tracker that the work has been completed and it may forget
+ * about it.
+ */
+void btracker_complete(struct background_tracker *b, struct policy_work *op);
+
+/*
+ * Predicate to see if an origin block is already scheduled for promotion.
+ */
bool btracker_promotion_already_present(struct background_tracker *b,
dm_oblock_t oblock);
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index 83a5975bcc72..f5b4c996dc05 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -104,7 +104,7 @@ struct dm_cache_metadata {
refcount_t ref_count;
struct list_head list;
- unsigned version;
+ unsigned int version;
struct block_device *bdev;
struct dm_block_manager *bm;
struct dm_space_map *metadata_sm;
@@ -129,7 +129,7 @@ struct dm_cache_metadata {
bool clean_when_opened:1;
char policy_name[CACHE_POLICY_NAME_SIZE];
- unsigned policy_version[CACHE_POLICY_VERSION_SIZE];
+ unsigned int policy_version[CACHE_POLICY_VERSION_SIZE];
size_t policy_hint_size;
struct dm_cache_statistics stats;
@@ -260,10 +260,10 @@ static int superblock_lock(struct dm_cache_metadata *cmd,
static int __superblock_all_zeroes(struct dm_block_manager *bm, bool *result)
{
int r;
- unsigned i;
+ unsigned int i;
struct dm_block *b;
__le64 *data_le, zero = cpu_to_le64(0);
- unsigned sb_block_size = dm_bm_block_size(bm) / sizeof(__le64);
+ unsigned int sb_block_size = dm_bm_block_size(bm) / sizeof(__le64);
/*
* We can't use a validator here - it may be all zeroes.
@@ -727,7 +727,7 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
*/
#define FLAGS_MASK ((1 << 16) - 1)
-static __le64 pack_value(dm_oblock_t block, unsigned flags)
+static __le64 pack_value(dm_oblock_t block, unsigned int flags)
{
uint64_t value = from_oblock(block);
value <<= 16;
@@ -735,7 +735,7 @@ static __le64 pack_value(dm_oblock_t block, unsigned flags)
return cpu_to_le64(value);
}
-static void unpack_value(__le64 value_le, dm_oblock_t *block, unsigned *flags)
+static void unpack_value(__le64 value_le, dm_oblock_t *block, unsigned int *flags)
{
uint64_t value = le64_to_cpu(value_le);
uint64_t b = value >> 16;
@@ -749,7 +749,7 @@ static struct dm_cache_metadata *metadata_open(struct block_device *bdev,
sector_t data_block_size,
bool may_format_device,
size_t policy_hint_size,
- unsigned metadata_version)
+ unsigned int metadata_version)
{
int r;
struct dm_cache_metadata *cmd;
@@ -810,7 +810,7 @@ static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev,
sector_t data_block_size,
bool may_format_device,
size_t policy_hint_size,
- unsigned metadata_version)
+ unsigned int metadata_version)
{
struct dm_cache_metadata *cmd, *cmd2;
@@ -855,7 +855,7 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
sector_t data_block_size,
bool may_format_device,
size_t policy_hint_size,
- unsigned metadata_version)
+ unsigned int metadata_version)
{
struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size, may_format_device,
policy_hint_size, metadata_version);
@@ -890,7 +890,7 @@ static int block_clean_combined_dirty(struct dm_cache_metadata *cmd, dm_cblock_t
int r;
__le64 value;
dm_oblock_t ob;
- unsigned flags;
+ unsigned int flags;
r = dm_array_get_value(&cmd->info, cmd->root, from_cblock(b), &value);
if (r)
@@ -1288,7 +1288,7 @@ static bool policy_unchanged(struct dm_cache_metadata *cmd,
struct dm_cache_policy *policy)
{
const char *policy_name = dm_cache_policy_get_name(policy);
- const unsigned *policy_version = dm_cache_policy_get_version(policy);
+ const unsigned int *policy_version = dm_cache_policy_get_version(policy);
size_t policy_hint_size = dm_cache_policy_get_hint_size(policy);
/*
@@ -1339,7 +1339,7 @@ static int __load_mapping_v1(struct dm_cache_metadata *cmd,
__le32 *hint_value_le;
dm_oblock_t oblock;
- unsigned flags;
+ unsigned int flags;
bool dirty = true;
dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le);
@@ -1381,7 +1381,7 @@ static int __load_mapping_v2(struct dm_cache_metadata *cmd,
__le32 *hint_value_le;
dm_oblock_t oblock;
- unsigned flags;
+ unsigned int flags;
bool dirty = true;
dm_array_cursor_get_value(mapping_cursor, (void **) &mapping_value_le);
@@ -1513,7 +1513,7 @@ static int __dump_mapping(void *context, uint64_t cblock, void *leaf)
{
__le64 value;
dm_oblock_t oblock;
- unsigned flags;
+ unsigned int flags;
memcpy(&value, leaf, sizeof(value));
unpack_value(value, &oblock, &flags);
@@ -1547,7 +1547,7 @@ int dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd)
static int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty)
{
int r;
- unsigned flags;
+ unsigned int flags;
dm_oblock_t oblock;
__le64 value;
@@ -1574,10 +1574,10 @@ static int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty
}
-static int __set_dirty_bits_v1(struct dm_cache_metadata *cmd, unsigned nr_bits, unsigned long *bits)
+static int __set_dirty_bits_v1(struct dm_cache_metadata *cmd, unsigned int nr_bits, unsigned long *bits)
{
int r;
- unsigned i;
+ unsigned int i;
for (i = 0; i < nr_bits; i++) {
r = __dirty(cmd, to_cblock(i), test_bit(i, bits));
if (r)
@@ -1594,7 +1594,7 @@ static int is_dirty_callback(uint32_t index, bool *value, void *context)
return 0;
}
-static int __set_dirty_bits_v2(struct dm_cache_metadata *cmd, unsigned nr_bits, unsigned long *bits)
+static int __set_dirty_bits_v2(struct dm_cache_metadata *cmd, unsigned int nr_bits, unsigned long *bits)
{
int r = 0;
@@ -1613,7 +1613,7 @@ static int __set_dirty_bits_v2(struct dm_cache_metadata *cmd, unsigned nr_bits,
}
int dm_cache_set_dirty_bits(struct dm_cache_metadata *cmd,
- unsigned nr_bits,
+ unsigned int nr_bits,
unsigned long *bits)
{
int r;
@@ -1712,7 +1712,7 @@ static int write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *po
int r;
size_t hint_size;
const char *policy_name = dm_cache_policy_get_name(policy);
- const unsigned *policy_version = dm_cache_policy_get_version(policy);
+ const unsigned int *policy_version = dm_cache_policy_get_version(policy);
if (!policy_name[0] ||
(strlen(policy_name) > sizeof(cmd->policy_name) - 1))
diff --git a/drivers/md/dm-cache-metadata.h b/drivers/md/dm-cache-metadata.h
index 0905f2c1615e..b40322bc44cf 100644
--- a/drivers/md/dm-cache-metadata.h
+++ b/drivers/md/dm-cache-metadata.h
@@ -60,7 +60,7 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev,
sector_t data_block_size,
bool may_format_device,
size_t policy_hint_size,
- unsigned metadata_version);
+ unsigned int metadata_version);
void dm_cache_metadata_close(struct dm_cache_metadata *cmd);
@@ -96,7 +96,7 @@ int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
void *context);
int dm_cache_set_dirty_bits(struct dm_cache_metadata *cmd,
- unsigned nr_bits, unsigned long *bits);
+ unsigned int nr_bits, unsigned long *bits);
struct dm_cache_statistics {
uint32_t read_hits;
diff --git a/drivers/md/dm-cache-policy-internal.h b/drivers/md/dm-cache-policy-internal.h
index 56f0a23f698c..8e49baa78dc1 100644
--- a/drivers/md/dm-cache-policy-internal.h
+++ b/drivers/md/dm-cache-policy-internal.h
@@ -85,7 +85,7 @@ static inline void policy_tick(struct dm_cache_policy *p, bool can_block)
}
static inline int policy_emit_config_values(struct dm_cache_policy *p, char *result,
- unsigned maxlen, ssize_t *sz_ptr)
+ unsigned int maxlen, ssize_t *sz_ptr)
{
ssize_t sz = *sz_ptr;
if (p->emit_config_values)
@@ -112,18 +112,18 @@ static inline void policy_allow_migrations(struct dm_cache_policy *p, bool allow
/*
* Some utility functions commonly used by policies and the core target.
*/
-static inline size_t bitset_size_in_bytes(unsigned nr_entries)
+static inline size_t bitset_size_in_bytes(unsigned int nr_entries)
{
return sizeof(unsigned long) * dm_div_up(nr_entries, BITS_PER_LONG);
}
-static inline unsigned long *alloc_bitset(unsigned nr_entries)
+static inline unsigned long *alloc_bitset(unsigned int nr_entries)
{
size_t s = bitset_size_in_bytes(nr_entries);
return vzalloc(s);
}
-static inline void clear_bitset(void *bitset, unsigned nr_entries)
+static inline void clear_bitset(void *bitset, unsigned int nr_entries)
{
size_t s = bitset_size_in_bytes(nr_entries);
memset(bitset, 0, s);
@@ -154,7 +154,7 @@ void dm_cache_policy_destroy(struct dm_cache_policy *p);
*/
const char *dm_cache_policy_get_name(struct dm_cache_policy *p);
-const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p);
+const unsigned int *dm_cache_policy_get_version(struct dm_cache_policy *p);
size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p);
diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
index a3d281fc14c3..54343812223e 100644
--- a/drivers/md/dm-cache-policy-smq.c
+++ b/drivers/md/dm-cache-policy-smq.c
@@ -23,12 +23,12 @@
/*
* Safe division functions that return zero on divide by zero.
*/
-static unsigned safe_div(unsigned n, unsigned d)
+static unsigned int safe_div(unsigned int n, unsigned int d)
{
return d ? n / d : 0u;
}
-static unsigned safe_mod(unsigned n, unsigned d)
+static unsigned int safe_mod(unsigned int n, unsigned int d)
{
return d ? n % d : 0u;
}
@@ -36,10 +36,10 @@ static unsigned safe_mod(unsigned n, unsigned d)
/*----------------------------------------------------------------*/
struct entry {
- unsigned hash_next:28;
- unsigned prev:28;
- unsigned next:28;
- unsigned level:6;
+ unsigned int hash_next:28;
+ unsigned int prev:28;
+ unsigned int next:28;
+ unsigned int level:6;
bool dirty:1;
bool allocated:1;
bool sentinel:1;
@@ -62,7 +62,7 @@ struct entry_space {
struct entry *end;
};
-static int space_init(struct entry_space *es, unsigned nr_entries)
+static int space_init(struct entry_space *es, unsigned int nr_entries)
{
if (!nr_entries) {
es->begin = es->end = NULL;
@@ -82,7 +82,7 @@ static void space_exit(struct entry_space *es)
vfree(es->begin);
}
-static struct entry *__get_entry(struct entry_space *es, unsigned block)
+static struct entry *__get_entry(struct entry_space *es, unsigned int block)
{
struct entry *e;
@@ -92,13 +92,13 @@ static struct entry *__get_entry(struct entry_space *es, unsigned block)
return e;
}
-static unsigned to_index(struct entry_space *es, struct entry *e)
+static unsigned int to_index(struct entry_space *es, struct entry *e)
{
BUG_ON(e < es->begin || e >= es->end);
return e - es->begin;
}
-static struct entry *to_entry(struct entry_space *es, unsigned block)
+static struct entry *to_entry(struct entry_space *es, unsigned int block)
{
if (block == INDEXER_NULL)
return NULL;
@@ -109,8 +109,8 @@ static struct entry *to_entry(struct entry_space *es, unsigned block)
/*----------------------------------------------------------------*/
struct ilist {
- unsigned nr_elts; /* excluding sentinel entries */
- unsigned head, tail;
+ unsigned int nr_elts; /* excluding sentinel entries */
+ unsigned int head, tail;
};
static void l_init(struct ilist *l)
@@ -252,23 +252,23 @@ static struct entry *l_pop_tail(struct entry_space *es, struct ilist *l)
struct queue {
struct entry_space *es;
- unsigned nr_elts;
- unsigned nr_levels;
+ unsigned int nr_elts;
+ unsigned int nr_levels;
struct ilist qs[MAX_LEVELS];
/*
* We maintain a count of the number of entries we would like in each
* level.
*/
- unsigned last_target_nr_elts;
- unsigned nr_top_levels;
- unsigned nr_in_top_levels;
- unsigned target_count[MAX_LEVELS];
+ unsigned int last_target_nr_elts;
+ unsigned int nr_top_levels;
+ unsigned int nr_in_top_levels;
+ unsigned int target_count[MAX_LEVELS];
};
-static void q_init(struct queue *q, struct entry_space *es, unsigned nr_levels)
+static void q_init(struct queue *q, struct entry_space *es, unsigned int nr_levels)
{
- unsigned i;
+ unsigned int i;
q->es = es;
q->nr_elts = 0;
@@ -284,7 +284,7 @@ static void q_init(struct queue *q, struct entry_space *es, unsigned nr_levels)
q->nr_in_top_levels = 0u;
}
-static unsigned q_size(struct queue *q)
+static unsigned int q_size(struct queue *q)
{
return q->nr_elts;
}
@@ -332,9 +332,9 @@ static void q_del(struct queue *q, struct entry *e)
/*
* Return the oldest entry of the lowest populated level.
*/
-static struct entry *q_peek(struct queue *q, unsigned max_level, bool can_cross_sentinel)
+static struct entry *q_peek(struct queue *q, unsigned int max_level, bool can_cross_sentinel)
{
- unsigned level;
+ unsigned int level;
struct entry *e;
max_level = min(max_level, q->nr_levels);
@@ -369,7 +369,7 @@ static struct entry *q_pop(struct queue *q)
* used by redistribute, so we know this is true. It also doesn't adjust
* the q->nr_elts count.
*/
-static struct entry *__redist_pop_from(struct queue *q, unsigned level)
+static struct entry *__redist_pop_from(struct queue *q, unsigned int level)
{
struct entry *e;
@@ -383,9 +383,10 @@ static struct entry *__redist_pop_from(struct queue *q, unsigned level)
return NULL;
}
-static void q_set_targets_subrange_(struct queue *q, unsigned nr_elts, unsigned lbegin, unsigned lend)
+static void q_set_targets_subrange_(struct queue *q, unsigned int nr_elts,
+ unsigned int lbegin, unsigned int lend)
{
- unsigned level, nr_levels, entries_per_level, remainder;
+ unsigned int level, nr_levels, entries_per_level, remainder;
BUG_ON(lbegin > lend);
BUG_ON(lend > q->nr_levels);
@@ -426,7 +427,7 @@ static void q_set_targets(struct queue *q)
static void q_redistribute(struct queue *q)
{
- unsigned target, level;
+ unsigned int target, level;
struct ilist *l, *l_above;
struct entry *e;
@@ -467,12 +468,12 @@ static void q_redistribute(struct queue *q)
}
}
-static void q_requeue(struct queue *q, struct entry *e, unsigned extra_levels,
+static void q_requeue(struct queue *q, struct entry *e, unsigned int extra_levels,
struct entry *s1, struct entry *s2)
{
struct entry *de;
- unsigned sentinels_passed = 0;
- unsigned new_level = min(q->nr_levels - 1u, e->level + extra_levels);
+ unsigned int sentinels_passed = 0;
+ unsigned int new_level = min(q->nr_levels - 1u, e->level + extra_levels);
/* try and find an entry to swap with */
if (extra_levels && (e->level < q->nr_levels - 1u)) {
@@ -512,9 +513,9 @@ static void q_requeue(struct queue *q, struct entry *e, unsigned extra_levels,
#define EIGHTH (1u << (FP_SHIFT - 3u))
struct stats {
- unsigned hit_threshold;
- unsigned hits;
- unsigned misses;
+ unsigned int hit_threshold;
+ unsigned int hits;
+ unsigned int misses;
};
enum performance {
@@ -523,7 +524,7 @@ enum performance {
Q_WELL
};
-static void stats_init(struct stats *s, unsigned nr_levels)
+static void stats_init(struct stats *s, unsigned int nr_levels)
{
s->hit_threshold = (nr_levels * 3u) / 4u;
s->hits = 0u;
@@ -535,7 +536,7 @@ static void stats_reset(struct stats *s)
s->hits = s->misses = 0u;
}
-static void stats_level_accessed(struct stats *s, unsigned level)
+static void stats_level_accessed(struct stats *s, unsigned int level)
{
if (level >= s->hit_threshold)
s->hits++;
@@ -556,7 +557,7 @@ static void stats_miss(struct stats *s)
*/
static enum performance stats_assess(struct stats *s)
{
- unsigned confidence = safe_div(s->hits << FP_SHIFT, s->hits + s->misses);
+ unsigned int confidence = safe_div(s->hits << FP_SHIFT, s->hits + s->misses);
if (confidence < SIXTEENTH)
return Q_POOR;
@@ -573,16 +574,16 @@ static enum performance stats_assess(struct stats *s)
struct smq_hash_table {
struct entry_space *es;
unsigned long long hash_bits;
- unsigned *buckets;
+ unsigned int *buckets;
};
/*
* All cache entries are stored in a chained hash table. To save space we
* use indexing again, and only store indexes to the next entry.
*/
-static int h_init(struct smq_hash_table *ht, struct entry_space *es, unsigned nr_entries)
+static int h_init(struct smq_hash_table *ht, struct entry_space *es, unsigned int nr_entries)
{
- unsigned i, nr_buckets;
+ unsigned int i, nr_buckets;
ht->es = es;
nr_buckets = roundup_pow_of_two(max(nr_entries / 4u, 16u));
@@ -603,7 +604,7 @@ static void h_exit(struct smq_hash_table *ht)
vfree(ht->buckets);
}
-static struct entry *h_head(struct smq_hash_table *ht, unsigned bucket)
+static struct entry *h_head(struct smq_hash_table *ht, unsigned int bucket)
{
return to_entry(ht->es, ht->buckets[bucket]);
}
@@ -613,7 +614,7 @@ static struct entry *h_next(struct smq_hash_table *ht, struct entry *e)
return to_entry(ht->es, e->hash_next);
}
-static void __h_insert(struct smq_hash_table *ht, unsigned bucket, struct entry *e)
+static void __h_insert(struct smq_hash_table *ht, unsigned int bucket, struct entry *e)
{
e->hash_next = ht->buckets[bucket];
ht->buckets[bucket] = to_index(ht->es, e);
@@ -621,11 +622,11 @@ static void __h_insert(struct smq_hash_table *ht, unsigned bucket, struct entry
static void h_insert(struct smq_hash_table *ht, struct entry *e)
{
- unsigned h = hash_64(from_oblock(e->oblock), ht->hash_bits);
+ unsigned int h = hash_64(from_oblock(e->oblock), ht->hash_bits);
__h_insert(ht, h, e);
}
-static struct entry *__h_lookup(struct smq_hash_table *ht, unsigned h, dm_oblock_t oblock,
+static struct entry *__h_lookup(struct smq_hash_table *ht, unsigned int h, dm_oblock_t oblock,
struct entry **prev)
{
struct entry *e;
@@ -641,7 +642,7 @@ static struct entry *__h_lookup(struct smq_hash_table *ht, unsigned h, dm_oblock
return NULL;
}
-static void __h_unlink(struct smq_hash_table *ht, unsigned h,
+static void __h_unlink(struct smq_hash_table *ht, unsigned int h,
struct entry *e, struct entry *prev)
{
if (prev)
@@ -656,7 +657,7 @@ static void __h_unlink(struct smq_hash_table *ht, unsigned h,
static struct entry *h_lookup(struct smq_hash_table *ht, dm_oblock_t oblock)
{
struct entry *e, *prev;
- unsigned h = hash_64(from_oblock(oblock), ht->hash_bits);
+ unsigned int h = hash_64(from_oblock(oblock), ht->hash_bits);
e = __h_lookup(ht, h, oblock, &prev);
if (e && prev) {
@@ -673,7 +674,7 @@ static struct entry *h_lookup(struct smq_hash_table *ht, dm_oblock_t oblock)
static void h_remove(struct smq_hash_table *ht, struct entry *e)
{
- unsigned h = hash_64(from_oblock(e->oblock), ht->hash_bits);
+ unsigned int h = hash_64(from_oblock(e->oblock), ht->hash_bits);
struct entry *prev;
/*
@@ -689,16 +690,16 @@ static void h_remove(struct smq_hash_table *ht, struct entry *e)
struct entry_alloc {
struct entry_space *es;
- unsigned begin;
+ unsigned int begin;
- unsigned nr_allocated;
+ unsigned int nr_allocated;
struct ilist free;
};
static void init_allocator(struct entry_alloc *ea, struct entry_space *es,
- unsigned begin, unsigned end)
+ unsigned int begin, unsigned int end)
{
- unsigned i;
+ unsigned int i;
ea->es = es;
ea->nr_allocated = 0u;
@@ -742,7 +743,7 @@ static struct entry *alloc_entry(struct entry_alloc *ea)
/*
* This assumes the cblock hasn't already been allocated.
*/
-static struct entry *alloc_particular_entry(struct entry_alloc *ea, unsigned i)
+static struct entry *alloc_particular_entry(struct entry_alloc *ea, unsigned int i)
{
struct entry *e = __get_entry(ea->es, ea->begin + i);
@@ -770,12 +771,12 @@ static bool allocator_empty(struct entry_alloc *ea)
return l_empty(&ea->free);
}
-static unsigned get_index(struct entry_alloc *ea, struct entry *e)
+static unsigned int get_index(struct entry_alloc *ea, struct entry *e)
{
return to_index(ea->es, e) - ea->begin;
}
-static struct entry *get_entry(struct entry_alloc *ea, unsigned index)
+static struct entry *get_entry(struct entry_alloc *ea, unsigned int index)
{
return __get_entry(ea->es, ea->begin + index);
}
@@ -800,9 +801,9 @@ struct smq_policy {
sector_t cache_block_size;
sector_t hotspot_block_size;
- unsigned nr_hotspot_blocks;
- unsigned cache_blocks_per_hotspot_block;
- unsigned hotspot_level_jump;
+ unsigned int nr_hotspot_blocks;
+ unsigned int cache_blocks_per_hotspot_block;
+ unsigned int hotspot_level_jump;
struct entry_space es;
struct entry_alloc writeback_sentinel_alloc;
@@ -831,7 +832,7 @@ struct smq_policy {
* Keeps track of time, incremented by the core. We use this to
* avoid attributing multiple hits within the same tick.
*/
- unsigned tick;
+ unsigned int tick;
/*
* The hash tables allows us to quickly find an entry by origin
@@ -846,8 +847,8 @@ struct smq_policy {
bool current_demote_sentinels;
unsigned long next_demote_period;
- unsigned write_promote_level;
- unsigned read_promote_level;
+ unsigned int write_promote_level;
+ unsigned int read_promote_level;
unsigned long next_hotspot_period;
unsigned long next_cache_period;
@@ -859,24 +860,24 @@ struct smq_policy {
/*----------------------------------------------------------------*/
-static struct entry *get_sentinel(struct entry_alloc *ea, unsigned level, bool which)
+static struct entry *get_sentinel(struct entry_alloc *ea, unsigned int level, bool which)
{
return get_entry(ea, which ? level : NR_CACHE_LEVELS + level);
}
-static struct entry *writeback_sentinel(struct smq_policy *mq, unsigned level)
+static struct entry *writeback_sentinel(struct smq_policy *mq, unsigned int level)
{
return get_sentinel(&mq->writeback_sentinel_alloc, level, mq->current_writeback_sentinels);
}
-static struct entry *demote_sentinel(struct smq_policy *mq, unsigned level)
+static struct entry *demote_sentinel(struct smq_policy *mq, unsigned int level)
{
return get_sentinel(&mq->demote_sentinel_alloc, level, mq->current_demote_sentinels);
}
static void __update_writeback_sentinels(struct smq_policy *mq)
{
- unsigned level;
+ unsigned int level;
struct queue *q = &mq->dirty;
struct entry *sentinel;
@@ -889,7 +890,7 @@ static void __update_writeback_sentinels(struct smq_policy *mq)
static void __update_demote_sentinels(struct smq_policy *mq)
{
- unsigned level;
+ unsigned int level;
struct queue *q = &mq->clean;
struct entry *sentinel;
@@ -917,7 +918,7 @@ static void update_sentinels(struct smq_policy *mq)
static void __sentinels_init(struct smq_policy *mq)
{
- unsigned level;
+ unsigned int level;
struct entry *sentinel;
for (level = 0; level < NR_CACHE_LEVELS; level++) {
@@ -1008,7 +1009,7 @@ static void requeue(struct smq_policy *mq, struct entry *e)
}
}
-static unsigned default_promote_level(struct smq_policy *mq)
+static unsigned int default_promote_level(struct smq_policy *mq)
{
/*
* The promote level depends on the current performance of the
@@ -1030,9 +1031,9 @@ static unsigned default_promote_level(struct smq_policy *mq)
1, 1, 1, 2, 4, 6, 7, 8, 7, 6, 4, 4, 3, 3, 2, 2, 1
};
- unsigned hits = mq->cache_stats.hits;
- unsigned misses = mq->cache_stats.misses;
- unsigned index = safe_div(hits << 4u, hits + misses);
+ unsigned int hits = mq->cache_stats.hits;
+ unsigned int misses = mq->cache_stats.misses;
+ unsigned int index = safe_div(hits << 4u, hits + misses);
return table[index];
}
@@ -1042,7 +1043,7 @@ static void update_promote_levels(struct smq_policy *mq)
* If there are unused cache entries then we want to be really
* eager to promote.
*/
- unsigned threshold_level = allocator_empty(&mq->cache_alloc) ?
+ unsigned int threshold_level = allocator_empty(&mq->cache_alloc) ?
default_promote_level(mq) : (NR_HOTSPOT_LEVELS / 2u);
threshold_level = max(threshold_level, NR_HOTSPOT_LEVELS);
@@ -1124,7 +1125,7 @@ static void end_cache_period(struct smq_policy *mq)
#define CLEAN_TARGET 25u
#define FREE_TARGET 25u
-static unsigned percent_to_target(struct smq_policy *mq, unsigned p)
+static unsigned int percent_to_target(struct smq_policy *mq, unsigned int p)
{
return from_cblock(mq->cache_size) * p / 100u;
}
@@ -1150,7 +1151,7 @@ static bool clean_target_met(struct smq_policy *mq, bool idle)
static bool free_target_met(struct smq_policy *mq)
{
- unsigned nr_free;
+ unsigned int nr_free;
nr_free = from_cblock(mq->cache_size) - mq->cache_alloc.nr_allocated;
return (nr_free + btracker_nr_demotions_queued(mq->bg_work)) >=
@@ -1300,7 +1301,7 @@ static dm_oblock_t to_hblock(struct smq_policy *mq, dm_oblock_t b)
static struct entry *update_hotspot_queue(struct smq_policy *mq, dm_oblock_t b)
{
- unsigned hi;
+ unsigned int hi;
dm_oblock_t hb = to_hblock(mq, b);
struct entry *e = h_lookup(&mq->hotspot_table, hb);
@@ -1549,7 +1550,7 @@ static void smq_clear_dirty(struct dm_cache_policy *p, dm_cblock_t cblock)
spin_unlock_irqrestore(&mq->lock, flags);
}
-static unsigned random_level(dm_cblock_t cblock)
+static unsigned int random_level(dm_cblock_t cblock)
{
return hash_32(from_cblock(cblock), 9) & (NR_CACHE_LEVELS - 1);
}
@@ -1660,7 +1661,7 @@ static int mq_set_config_value(struct dm_cache_policy *p,
}
static int mq_emit_config_values(struct dm_cache_policy *p, char *result,
- unsigned maxlen, ssize_t *sz_ptr)
+ unsigned int maxlen, ssize_t *sz_ptr)
{
ssize_t sz = *sz_ptr;
@@ -1699,16 +1700,16 @@ static void init_policy_functions(struct smq_policy *mq, bool mimic_mq)
static bool too_many_hotspot_blocks(sector_t origin_size,
sector_t hotspot_block_size,
- unsigned nr_hotspot_blocks)
+ unsigned int nr_hotspot_blocks)
{
return (hotspot_block_size * nr_hotspot_blocks) > origin_size;
}
static void calc_hotspot_params(sector_t origin_size,
sector_t cache_block_size,
- unsigned nr_cache_blocks,
+ unsigned int nr_cache_blocks,
sector_t *hotspot_block_size,
- unsigned *nr_hotspot_blocks)
+ unsigned int *nr_hotspot_blocks)
{
*hotspot_block_size = cache_block_size * 16u;
*nr_hotspot_blocks = max(nr_cache_blocks / 4u, 1024u);
@@ -1724,9 +1725,9 @@ static struct dm_cache_policy *__smq_create(dm_cblock_t cache_size,
bool mimic_mq,
bool migrations_allowed)
{
- unsigned i;
- unsigned nr_sentinels_per_queue = 2u * NR_CACHE_LEVELS;
- unsigned total_sentinels = 2u * nr_sentinels_per_queue;
+ unsigned int i;
+ unsigned int nr_sentinels_per_queue = 2u * NR_CACHE_LEVELS;
+ unsigned int total_sentinels = 2u * nr_sentinels_per_queue;
struct smq_policy *mq = kzalloc(sizeof(*mq), GFP_KERNEL);
if (!mq)
diff --git a/drivers/md/dm-cache-policy.c b/drivers/md/dm-cache-policy.c
index c1a3cee99b44..2e58bbcf3e3b 100644
--- a/drivers/md/dm-cache-policy.c
+++ b/drivers/md/dm-cache-policy.c
@@ -154,7 +154,7 @@ const char *dm_cache_policy_get_name(struct dm_cache_policy *p)
}
EXPORT_SYMBOL_GPL(dm_cache_policy_get_name);
-const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p)
+const unsigned int *dm_cache_policy_get_version(struct dm_cache_policy *p)
{
struct dm_cache_policy_type *t = p->private;
diff --git a/drivers/md/dm-cache-policy.h b/drivers/md/dm-cache-policy.h
index 06eb31af626f..6ba3e9c91af5 100644
--- a/drivers/md/dm-cache-policy.h
+++ b/drivers/md/dm-cache-policy.h
@@ -128,7 +128,7 @@ struct dm_cache_policy {
* Configuration.
*/
int (*emit_config_values)(struct dm_cache_policy *p, char *result,
- unsigned maxlen, ssize_t *sz_ptr);
+ unsigned int maxlen, ssize_t *sz_ptr);
int (*set_config_value)(struct dm_cache_policy *p,
const char *key, const char *value);
@@ -157,7 +157,7 @@ struct dm_cache_policy_type {
* what gets passed on the target line to select your policy.
*/
char name[CACHE_POLICY_NAME_SIZE];
- unsigned version[CACHE_POLICY_VERSION_SIZE];
+ unsigned int version[CACHE_POLICY_VERSION_SIZE];
/*
* For use by an alias dm_cache_policy_type to point to the
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 17fde3e5a1f7..8f7426b71e02 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -275,7 +275,7 @@ enum cache_io_mode {
struct cache_features {
enum cache_metadata_mode mode;
enum cache_io_mode io_mode;
- unsigned metadata_version;
+ unsigned int metadata_version;
bool discard_passdown:1;
};
@@ -362,7 +362,7 @@ struct cache {
* Rather than reconstructing the table line for the status we just
* save it and regurgitate.
*/
- unsigned nr_ctr_args;
+ unsigned int nr_ctr_args;
const char **ctr_args;
struct dm_kcopyd_client *copier;
@@ -378,7 +378,7 @@ struct cache {
unsigned long *dirty_bitset;
atomic_t nr_dirty;
- unsigned policy_nr_args;
+ unsigned int policy_nr_args;
struct dm_cache_policy *policy;
/*
@@ -409,7 +409,7 @@ struct cache {
struct per_bio_data {
bool tick:1;
- unsigned req_nr:2;
+ unsigned int req_nr:2;
struct dm_bio_prison_cell_v2 *cell;
struct dm_hook_info hook_info;
sector_t len;
@@ -517,7 +517,7 @@ static void build_key(dm_oblock_t begin, dm_oblock_t end, struct dm_cell_key_v2
#define WRITE_LOCK_LEVEL 0
#define READ_WRITE_LOCK_LEVEL 1
-static unsigned lock_level(struct bio *bio)
+static unsigned int lock_level(struct bio *bio)
{
return bio_data_dir(bio) == WRITE ?
WRITE_LOCK_LEVEL :
@@ -1884,7 +1884,7 @@ static void check_migrations(struct work_struct *ws)
*/
static void destroy(struct cache *cache)
{
- unsigned i;
+ unsigned int i;
mempool_exit(&cache->migration_pool);
@@ -2124,7 +2124,7 @@ static int parse_features(struct cache_args *ca, struct dm_arg_set *as,
};
int r, mode_ctr = 0;
- unsigned argc;
+ unsigned int argc;
const char *arg;
struct cache_features *cf = &ca->features;
@@ -2544,7 +2544,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
static int copy_ctr_args(struct cache *cache, int argc, const char **argv)
{
- unsigned i;
+ unsigned int i;
const char **copy;
copy = kcalloc(argc, sizeof(*copy), GFP_KERNEL);
@@ -2566,7 +2566,7 @@ static int copy_ctr_args(struct cache *cache, int argc, const char **argv)
return 0;
}
-static int cache_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int cache_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
int r = -EINVAL;
struct cache_args *ca;
@@ -2669,7 +2669,7 @@ static int write_dirty_bitset(struct cache *cache)
static int write_discard_bitset(struct cache *cache)
{
- unsigned i, r;
+ unsigned int i, r;
if (get_cache_mode(cache) >= CM_READ_ONLY)
return -EINVAL;
@@ -2983,11 +2983,11 @@ static void cache_resume(struct dm_target *ti)
}
static void emit_flags(struct cache *cache, char *result,
- unsigned maxlen, ssize_t *sz_ptr)
+ unsigned int maxlen, ssize_t *sz_ptr)
{
ssize_t sz = *sz_ptr;
struct cache_features *cf = &cache->features;
- unsigned count = (cf->metadata_version == 2) + !cf->discard_passdown + 1;
+ unsigned int count = (cf->metadata_version == 2) + !cf->discard_passdown + 1;
DMEMIT("%u ", count);
@@ -3027,10 +3027,10 @@ static void emit_flags(struct cache *cache, char *result,
* <policy name> <#policy args> <policy args>* <cache metadata mode> <needs_check>
*/
static void cache_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int r = 0;
- unsigned i;
+ unsigned int i;
ssize_t sz = 0;
dm_block_t nr_free_blocks_metadata = 0;
dm_block_t nr_blocks_metadata = 0;
@@ -3067,18 +3067,18 @@ static void cache_status(struct dm_target *ti, status_type_t type,
residency = policy_residency(cache->policy);
DMEMIT("%u %llu/%llu %llu %llu/%llu %u %u %u %u %u %u %lu ",
- (unsigned)DM_CACHE_METADATA_BLOCK_SIZE,
+ (unsigned int)DM_CACHE_METADATA_BLOCK_SIZE,
(unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
(unsigned long long)nr_blocks_metadata,
(unsigned long long)cache->sectors_per_block,
(unsigned long long) from_cblock(residency),
(unsigned long long) from_cblock(cache->cache_size),
- (unsigned) atomic_read(&cache->stats.read_hit),
- (unsigned) atomic_read(&cache->stats.read_miss),
- (unsigned) atomic_read(&cache->stats.write_hit),
- (unsigned) atomic_read(&cache->stats.write_miss),
- (unsigned) atomic_read(&cache->stats.demotion),
- (unsigned) atomic_read(&cache->stats.promotion),
+ (unsigned int) atomic_read(&cache->stats.read_hit),
+ (unsigned int) atomic_read(&cache->stats.read_miss),
+ (unsigned int) atomic_read(&cache->stats.write_hit),
+ (unsigned int) atomic_read(&cache->stats.write_miss),
+ (unsigned int) atomic_read(&cache->stats.demotion),
+ (unsigned int) atomic_read(&cache->stats.promotion),
(unsigned long) atomic_read(&cache->nr_dirty));
emit_flags(cache, result, maxlen, &sz);
@@ -3257,11 +3257,11 @@ static int request_invalidation(struct cache *cache, struct cblock_range *range)
return r;
}
-static int process_invalidate_cblocks_message(struct cache *cache, unsigned count,
+static int process_invalidate_cblocks_message(struct cache *cache, unsigned int count,
const char **cblock_ranges)
{
int r = 0;
- unsigned i;
+ unsigned int i;
struct cblock_range range;
if (!passthrough_mode(cache)) {
@@ -3298,8 +3298,8 @@ static int process_invalidate_cblocks_message(struct cache *cache, unsigned coun
*
* The key migration_threshold is supported by the cache target core.
*/
-static int cache_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int cache_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
struct cache *cache = ti->private;
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index 6c6bd24774f2..28c641352de9 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -119,7 +119,7 @@ struct mapped_device {
struct dm_stats stats;
/* the number of internal suspends */
- unsigned internal_suspend_count;
+ unsigned int internal_suspend_count;
int swap_bios;
struct semaphore swap_bios_semaphore;
@@ -326,9 +326,9 @@ static inline struct completion *dm_get_completion_from_kobject(struct kobject *
return &container_of(kobj, struct dm_kobject_holder, kobj)->completion;
}
-unsigned __dm_get_module_param(unsigned *module_param, unsigned def, unsigned max);
+unsigned int __dm_get_module_param(unsigned int *module_param, unsigned int def, unsigned int max);
-static inline bool dm_message_test_buffer_overflow(char *result, unsigned maxlen)
+static inline bool dm_message_test_buffer_overflow(char *result, unsigned int maxlen)
{
return !maxlen || strlen(result) + 1 >= maxlen;
}
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index dc2d0d61ade9..ee269b1d09fa 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -173,14 +173,14 @@ struct crypt_config {
} iv_gen_private;
u64 iv_offset;
unsigned int iv_size;
- unsigned short int sector_size;
+ unsigned short sector_size;
unsigned char sector_shift;
union {
struct crypto_skcipher **tfms;
struct crypto_aead **tfms_aead;
} cipher_tfm;
- unsigned tfms_count;
+ unsigned int tfms_count;
unsigned long cipher_flags;
/*
@@ -214,7 +214,7 @@ struct crypt_config {
* pool for per bio private data, crypto requests,
* encryption requeusts/buffer pages and integrity tags
*/
- unsigned tag_pool_max_sectors;
+ unsigned int tag_pool_max_sectors;
mempool_t tag_pool;
mempool_t req_pool;
mempool_t page_pool;
@@ -231,7 +231,7 @@ struct crypt_config {
#define POOL_ENTRY_SIZE 512
static DEFINE_SPINLOCK(dm_crypt_clients_lock);
-static unsigned dm_crypt_clients_n = 0;
+static unsigned int dm_crypt_clients_n = 0;
static volatile unsigned long dm_crypt_pages_per_client;
#define DM_CRYPT_MEMORY_PERCENT 2
#define DM_CRYPT_MIN_PAGES_PER_CLIENT (BIO_MAX_VECS * 16)
@@ -356,7 +356,7 @@ static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv,
static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
const char *opts)
{
- unsigned bs;
+ unsigned int bs;
int log;
if (crypt_integrity_aead(cc))
@@ -1466,7 +1466,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
static int crypt_alloc_req_skcipher(struct crypt_config *cc,
struct convert_context *ctx)
{
- unsigned key_index = ctx->cc_sector & (cc->tfms_count - 1);
+ unsigned int key_index = ctx->cc_sector & (cc->tfms_count - 1);
if (!ctx->r.req) {
ctx->r.req = mempool_alloc(&cc->req_pool, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
@@ -1660,13 +1660,13 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone);
* non-blocking allocations without a mutex first but on failure we fallback
* to blocking allocations with a mutex.
*/
-static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
+static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size)
{
struct crypt_config *cc = io->cc;
struct bio *clone;
unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM;
- unsigned i, len, remaining_size;
+ unsigned int i, len, remaining_size;
struct page *page;
retry:
@@ -1806,7 +1806,7 @@ static void crypt_endio(struct bio *clone)
{
struct dm_crypt_io *io = clone->bi_private;
struct crypt_config *cc = io->cc;
- unsigned rw = bio_data_dir(clone);
+ unsigned int rw = bio_data_dir(clone);
blk_status_t error;
/*
@@ -2261,7 +2261,7 @@ static void crypt_free_tfms_aead(struct crypt_config *cc)
static void crypt_free_tfms_skcipher(struct crypt_config *cc)
{
- unsigned i;
+ unsigned int i;
if (!cc->cipher_tfm.tfms)
return;
@@ -2286,7 +2286,7 @@ static void crypt_free_tfms(struct crypt_config *cc)
static int crypt_alloc_tfms_skcipher(struct crypt_config *cc, char *ciphermode)
{
- unsigned i;
+ unsigned int i;
int err;
cc->cipher_tfm.tfms = kcalloc(cc->tfms_count,
@@ -2344,12 +2344,12 @@ static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode)
return crypt_alloc_tfms_skcipher(cc, ciphermode);
}
-static unsigned crypt_subkey_size(struct crypt_config *cc)
+static unsigned int crypt_subkey_size(struct crypt_config *cc)
{
return (cc->key_size - cc->key_extra_size) >> ilog2(cc->tfms_count);
}
-static unsigned crypt_authenckey_size(struct crypt_config *cc)
+static unsigned int crypt_authenckey_size(struct crypt_config *cc)
{
return crypt_subkey_size(cc) + RTA_SPACE(sizeof(struct crypto_authenc_key_param));
}
@@ -2360,7 +2360,7 @@ static unsigned crypt_authenckey_size(struct crypt_config *cc)
* This funcion converts cc->key to this special format.
*/
static void crypt_copy_authenckey(char *p, const void *key,
- unsigned enckeylen, unsigned authkeylen)
+ unsigned int enckeylen, unsigned int authkeylen)
{
struct crypto_authenc_key_param *param;
struct rtattr *rta;
@@ -2378,7 +2378,7 @@ static void crypt_copy_authenckey(char *p, const void *key,
static int crypt_setkey(struct crypt_config *cc)
{
- unsigned subkey_size;
+ unsigned int subkey_size;
int err = 0, i, r;
/* Ignore extra keys (which are used for IV etc) */
@@ -3417,7 +3417,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
if (cc->on_disk_tag_size) {
- unsigned tag_len = cc->on_disk_tag_size * (bio_sectors(bio) >> cc->sector_shift);
+ unsigned int tag_len = cc->on_disk_tag_size * (bio_sectors(bio) >> cc->sector_shift);
if (unlikely(tag_len > KMALLOC_MAX_SIZE) ||
unlikely(!(io->integrity_metadata = kmalloc(tag_len,
@@ -3445,14 +3445,14 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
static char hex2asc(unsigned char c)
{
- return c + '0' + ((unsigned)(9 - c) >> 4 & 0x27);
+ return c + '0' + ((unsigned int)(9 - c) >> 4 & 0x27);
}
static void crypt_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct crypt_config *cc = ti->private;
- unsigned i, sz = 0;
+ unsigned int i, sz = 0;
int num_feature_args = 0;
switch (type) {
@@ -3568,8 +3568,8 @@ static void crypt_resume(struct dm_target *ti)
* key set <key>
* key wipe
*/
-static int crypt_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int crypt_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
struct crypt_config *cc = ti->private;
int key_size, ret = -EINVAL;
@@ -3630,10 +3630,10 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
limits->max_segment_size = PAGE_SIZE;
limits->logical_block_size =
- max_t(unsigned, limits->logical_block_size, cc->sector_size);
+ max_t(unsigned int, limits->logical_block_size, cc->sector_size);
limits->physical_block_size =
- max_t(unsigned, limits->physical_block_size, cc->sector_size);
- limits->io_min = max_t(unsigned, limits->io_min, cc->sector_size);
+ max_t(unsigned int, limits->physical_block_size, cc->sector_size);
+ limits->io_min = max_t(unsigned int, limits->io_min, cc->sector_size);
limits->dma_alignment = limits->logical_block_size - 1;
}
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 869afef5654a..02b8f4e81827 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -20,8 +20,8 @@
struct delay_class {
struct dm_dev *dev;
sector_t start;
- unsigned delay;
- unsigned ops;
+ unsigned int delay;
+ unsigned int ops;
};
struct delay_c {
@@ -305,7 +305,7 @@ static int delay_map(struct dm_target *ti, struct bio *bio)
DMEMIT("%s %llu %u", (c)->dev->name, (unsigned long long)(c)->start, (c)->delay)
static void delay_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct delay_c *dc = ti->private;
int sz = 0;
diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c
index 512cc6cea095..7606c6695a0e 100644
--- a/drivers/md/dm-ebs-target.c
+++ b/drivers/md/dm-ebs-target.c
@@ -390,7 +390,7 @@ static int ebs_map(struct dm_target *ti, struct bio *bio)
}
static void ebs_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct ebs_c *ec = ti->private;
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index e92c1afc3677..a96290103cca 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -51,7 +51,7 @@ static void writeset_free(struct writeset *ws)
}
static int setup_on_disk_bitset(struct dm_disk_bitset *info,
- unsigned nr_bits, dm_block_t *root)
+ unsigned int nr_bits, dm_block_t *root)
{
int r;
@@ -62,7 +62,7 @@ static int setup_on_disk_bitset(struct dm_disk_bitset *info,
return dm_bitset_resize(info, *root, 0, nr_bits, false, root);
}
-static size_t bitset_size(unsigned nr_bits)
+static size_t bitset_size(unsigned int nr_bits)
{
return sizeof(unsigned long) * dm_div_up(nr_bits, BITS_PER_LONG);
}
@@ -323,10 +323,10 @@ static int superblock_lock(struct era_metadata *md,
static int superblock_all_zeroes(struct dm_block_manager *bm, bool *result)
{
int r;
- unsigned i;
+ unsigned int i;
struct dm_block *b;
__le64 *data_le, zero = cpu_to_le64(0);
- unsigned sb_block_size = dm_bm_block_size(bm) / sizeof(__le64);
+ unsigned int sb_block_size = dm_bm_block_size(bm) / sizeof(__le64);
/*
* We can't use a validator here - it may be all zeroes.
@@ -363,12 +363,12 @@ static void ws_unpack(const struct writeset_disk *disk, struct writeset_metadata
core->root = le64_to_cpu(disk->root);
}
-static void ws_inc(void *context, const void *value, unsigned count)
+static void ws_inc(void *context, const void *value, unsigned int count)
{
struct era_metadata *md = context;
struct writeset_disk ws_d;
dm_block_t b;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++) {
memcpy(&ws_d, value + (i * sizeof(ws_d)), sizeof(ws_d));
@@ -377,12 +377,12 @@ static void ws_inc(void *context, const void *value, unsigned count)
}
}
-static void ws_dec(void *context, const void *value, unsigned count)
+static void ws_dec(void *context, const void *value, unsigned int count)
{
struct era_metadata *md = context;
struct writeset_disk ws_d;
dm_block_t b;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++) {
memcpy(&ws_d, value + (i * sizeof(ws_d)), sizeof(ws_d));
@@ -667,7 +667,7 @@ static void swap_writeset(struct era_metadata *md, struct writeset *new_writeset
*--------------------------------------------------------------*/
struct digest {
uint32_t era;
- unsigned nr_bits, current_bit;
+ unsigned int nr_bits, current_bit;
struct writeset_metadata writeset;
__le32 value;
struct dm_disk_bitset info;
@@ -702,7 +702,7 @@ static int metadata_digest_transcribe_writeset(struct era_metadata *md,
{
int r;
bool marked;
- unsigned b, e = min(d->current_bit + INSERTS_PER_STEP, d->nr_bits);
+ unsigned int b, e = min(d->current_bit + INSERTS_PER_STEP, d->nr_bits);
for (b = d->current_bit; b < e; b++) {
r = writeset_marked_on_disk(&d->info, &d->writeset, b, &marked);
@@ -1439,7 +1439,7 @@ static bool valid_block_size(dm_block_t block_size)
/*
* <metadata dev> <data dev> <data block size (sectors)>
*/
-static int era_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int era_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
int r;
char dummy;
@@ -1618,7 +1618,7 @@ static int era_preresume(struct dm_target *ti)
* <current era> <held metadata root | '-'>
*/
static void era_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int r;
struct era *era = ti->private;
@@ -1633,10 +1633,10 @@ static void era_status(struct dm_target *ti, status_type_t type,
goto err;
DMEMIT("%u %llu/%llu %u",
- (unsigned) (DM_ERA_METADATA_BLOCK_SIZE >> SECTOR_SHIFT),
+ (unsigned int) (DM_ERA_METADATA_BLOCK_SIZE >> SECTOR_SHIFT),
(unsigned long long) stats.used,
(unsigned long long) stats.total,
- (unsigned) stats.era);
+ (unsigned int) stats.era);
if (stats.snap != SUPERBLOCK_LOCATION)
DMEMIT(" %llu", stats.snap);
@@ -1662,8 +1662,8 @@ static void era_status(struct dm_target *ti, status_type_t type,
DMEMIT("Error");
}
-static int era_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int era_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
struct era *era = ti->private;
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 3997f34cfebc..cc3987c97eb9 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -142,7 +142,7 @@ EXPORT_SYMBOL(dm_exception_store_type_unregister);
static int set_chunk_size(struct dm_exception_store *store,
const char *chunk_size_arg, char **error)
{
- unsigned chunk_size;
+ unsigned int chunk_size;
if (kstrtouint(chunk_size_arg, 10, &chunk_size)) {
*error = "Invalid chunk size";
@@ -158,7 +158,7 @@ static int set_chunk_size(struct dm_exception_store *store,
}
int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
- unsigned chunk_size,
+ unsigned int chunk_size,
char **error)
{
/* Check chunk_size is a power of 2 */
@@ -190,7 +190,7 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
struct dm_snapshot *snap,
- unsigned *args_used,
+ unsigned int *args_used,
struct dm_exception_store **store)
{
int r = 0;
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
index b5f20eba3641..862df68a7db0 100644
--- a/drivers/md/dm-exception-store.h
+++ b/drivers/md/dm-exception-store.h
@@ -96,9 +96,9 @@ struct dm_exception_store_type {
*/
void (*drop_snapshot) (struct dm_exception_store *store);
- unsigned (*status) (struct dm_exception_store *store,
- status_type_t status, char *result,
- unsigned maxlen);
+ unsigned int (*status) (struct dm_exception_store *store,
+ status_type_t status, char *result,
+ unsigned int maxlen);
/*
* Return how full the snapshot is.
@@ -118,9 +118,9 @@ struct dm_exception_store {
struct dm_snapshot *snap;
/* Size of data blocks saved - must be a power of 2 */
- unsigned chunk_size;
- unsigned chunk_mask;
- unsigned chunk_shift;
+ unsigned int chunk_size;
+ unsigned int chunk_mask;
+ unsigned int chunk_shift;
void *context;
@@ -144,7 +144,7 @@ static inline chunk_t dm_chunk_number(chunk_t chunk)
return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
}
-static inline unsigned dm_consecutive_chunk_count(struct dm_exception *e)
+static inline unsigned int dm_consecutive_chunk_count(struct dm_exception *e)
{
return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
}
@@ -181,12 +181,12 @@ int dm_exception_store_type_register(struct dm_exception_store_type *type);
int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
- unsigned chunk_size,
+ unsigned int chunk_size,
char **error);
int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
struct dm_snapshot *snap,
- unsigned *args_used,
+ unsigned int *args_used,
struct dm_exception_store **store);
void dm_exception_store_destroy(struct dm_exception_store *store);
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 335684a1aeaa..7efbdb42cf3b 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -26,12 +26,12 @@ struct flakey_c {
struct dm_dev *dev;
unsigned long start_time;
sector_t start;
- unsigned up_interval;
- unsigned down_interval;
+ unsigned int up_interval;
+ unsigned int down_interval;
unsigned long flags;
- unsigned corrupt_bio_byte;
- unsigned corrupt_bio_rw;
- unsigned corrupt_bio_value;
+ unsigned int corrupt_bio_byte;
+ unsigned int corrupt_bio_rw;
+ unsigned int corrupt_bio_value;
blk_opf_t corrupt_bio_flags;
};
@@ -48,7 +48,7 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
struct dm_target *ti)
{
int r;
- unsigned argc;
+ unsigned int argc;
const char *arg_name;
static const struct dm_arg _args[] = {
@@ -148,7 +148,7 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
BUILD_BUG_ON(sizeof(fc->corrupt_bio_flags) !=
sizeof(unsigned int));
r = dm_read_arg(_args + 3, as,
- (__force unsigned *)&fc->corrupt_bio_flags,
+ (__force unsigned int *)&fc->corrupt_bio_flags,
&ti->error);
if (r)
return r;
@@ -324,7 +324,7 @@ static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc)
static int flakey_map(struct dm_target *ti, struct bio *bio)
{
struct flakey_c *fc = ti->private;
- unsigned elapsed;
+ unsigned int elapsed;
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
pb->bio_submitted = false;
@@ -417,11 +417,11 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
}
static void flakey_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct flakey_c *fc = ti->private;
- unsigned drop_writes, error_writes;
+ unsigned int drop_writes, error_writes;
switch (type) {
case STATUSTYPE_INFO:
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 1388ee35571e..53f9f765df9f 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -157,13 +157,13 @@ struct alg_spec {
char *alg_string;
char *key_string;
__u8 *key;
- unsigned key_size;
+ unsigned int key_size;
};
struct dm_integrity_c {
struct dm_dev *dev;
struct dm_dev *meta_dev;
- unsigned tag_size;
+ unsigned int tag_size;
__s8 log2_tag_size;
sector_t start;
mempool_t journal_io_mempool;
@@ -171,8 +171,8 @@ struct dm_integrity_c {
struct dm_bufio_client *bufio;
struct workqueue_struct *metadata_wq;
struct superblock *sb;
- unsigned journal_pages;
- unsigned n_bitmap_blocks;
+ unsigned int journal_pages;
+ unsigned int n_bitmap_blocks;
struct page_list *journal;
struct page_list *journal_io;
@@ -180,7 +180,7 @@ struct dm_integrity_c {
struct page_list *recalc_bitmap;
struct page_list *may_write_bitmap;
struct bitmap_block_status *bbs;
- unsigned bitmap_flush_interval;
+ unsigned int bitmap_flush_interval;
int synchronous_mode;
struct bio_list synchronous_bios;
struct delayed_work bitmap_flush_work;
@@ -201,12 +201,12 @@ struct dm_integrity_c {
unsigned char journal_entries_per_sector;
unsigned char journal_section_entries;
unsigned short journal_section_sectors;
- unsigned journal_sections;
- unsigned journal_entries;
+ unsigned int journal_sections;
+ unsigned int journal_entries;
sector_t data_device_sectors;
sector_t meta_device_sectors;
- unsigned initial_sectors;
- unsigned metadata_run;
+ unsigned int initial_sectors;
+ unsigned int metadata_run;
__s8 log2_metadata_run;
__u8 log2_buffer_sectors;
__u8 sectors_per_block;
@@ -230,17 +230,17 @@ struct dm_integrity_c {
unsigned char commit_seq;
commit_id_t commit_ids[N_COMMIT_IDS];
- unsigned committed_section;
- unsigned n_committed_sections;
+ unsigned int committed_section;
+ unsigned int n_committed_sections;
- unsigned uncommitted_section;
- unsigned n_uncommitted_sections;
+ unsigned int uncommitted_section;
+ unsigned int n_uncommitted_sections;
- unsigned free_section;
+ unsigned int free_section;
unsigned char free_section_entry;
- unsigned free_sectors;
+ unsigned int free_sectors;
- unsigned free_sectors_threshold;
+ unsigned int free_sectors_threshold;
struct workqueue_struct *commit_wq;
struct work_struct commit_work;
@@ -257,7 +257,7 @@ struct dm_integrity_c {
unsigned long autocommit_jiffies;
struct timer_list autocommit_timer;
- unsigned autocommit_msec;
+ unsigned int autocommit_msec;
wait_queue_head_t copy_to_journal_wait;
@@ -305,7 +305,7 @@ struct dm_integrity_io {
struct dm_integrity_range range;
sector_t metadata_block;
- unsigned metadata_offset;
+ unsigned int metadata_offset;
atomic_t in_flight;
blk_status_t bi_status;
@@ -329,7 +329,7 @@ struct journal_io {
struct bitmap_block_status {
struct work_struct work;
struct dm_integrity_c *ic;
- unsigned idx;
+ unsigned int idx;
unsigned long *bitmap;
struct bio_list bio_queue;
spinlock_t bio_queue_lock;
@@ -410,8 +410,8 @@ static bool dm_integrity_disable_recalculate(struct dm_integrity_c *ic)
return false;
}
-static commit_id_t dm_integrity_commit_id(struct dm_integrity_c *ic, unsigned i,
- unsigned j, unsigned char seq)
+static commit_id_t dm_integrity_commit_id(struct dm_integrity_c *ic, unsigned int i,
+ unsigned int j, unsigned char seq)
{
/*
* Xor the number with section and sector, so that if a piece of
@@ -426,7 +426,7 @@ static void get_area_and_offset(struct dm_integrity_c *ic, sector_t data_sector,
if (!ic->meta_dev) {
__u8 log2_interleave_sectors = ic->sb->log2_interleave_sectors;
*area = data_sector >> log2_interleave_sectors;
- *offset = (unsigned)data_sector & ((1U << log2_interleave_sectors) - 1);
+ *offset = (unsigned int)data_sector & ((1U << log2_interleave_sectors) - 1);
} else {
*area = 0;
*offset = data_sector;
@@ -435,15 +435,15 @@ static void get_area_and_offset(struct dm_integrity_c *ic, sector_t data_sector,
#define sector_to_block(ic, n) \
do { \
- BUG_ON((n) & (unsigned)((ic)->sectors_per_block - 1)); \
+ BUG_ON((n) & (unsigned int)((ic)->sectors_per_block - 1)); \
(n) >>= (ic)->sb->log2_sectors_per_block; \
} while (0)
static __u64 get_metadata_sector_and_offset(struct dm_integrity_c *ic, sector_t area,
- sector_t offset, unsigned *metadata_offset)
+ sector_t offset, unsigned int *metadata_offset)
{
__u64 ms;
- unsigned mo;
+ unsigned int mo;
ms = area << ic->sb->log2_interleave_sectors;
if (likely(ic->log2_metadata_run >= 0))
@@ -484,7 +484,7 @@ static sector_t get_data_sector(struct dm_integrity_c *ic, sector_t area, sector
return result;
}
-static void wraparound_section(struct dm_integrity_c *ic, unsigned *sec_ptr)
+static void wraparound_section(struct dm_integrity_c *ic, unsigned int *sec_ptr)
{
if (unlikely(*sec_ptr >= ic->journal_sections))
*sec_ptr -= ic->journal_sections;
@@ -508,7 +508,7 @@ static int sb_mac(struct dm_integrity_c *ic, bool wr)
{
SHASH_DESC_ON_STACK(desc, ic->journal_mac);
int r;
- unsigned size = crypto_shash_digestsize(ic->journal_mac);
+ unsigned int size = crypto_shash_digestsize(ic->journal_mac);
if (sizeof(struct superblock) + size > 1 << SECTOR_SHIFT) {
dm_integrity_io_error(ic, "digest is too long", -EINVAL);
@@ -704,8 +704,8 @@ static bool block_bitmap_op(struct dm_integrity_c *ic, struct page_list *bitmap,
static void block_bitmap_copy(struct dm_integrity_c *ic, struct page_list *dst, struct page_list *src)
{
- unsigned n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
- unsigned i;
+ unsigned int n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
+ unsigned int i;
for (i = 0; i < n_bitmap_pages; i++) {
unsigned long *dst_data = lowmem_page_address(dst[i].page);
@@ -716,18 +716,18 @@ static void block_bitmap_copy(struct dm_integrity_c *ic, struct page_list *dst,
static struct bitmap_block_status *sector_to_bitmap_block(struct dm_integrity_c *ic, sector_t sector)
{
- unsigned bit = sector >> (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
- unsigned bitmap_block = bit / (BITMAP_BLOCK_SIZE * 8);
+ unsigned int bit = sector >> (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
+ unsigned int bitmap_block = bit / (BITMAP_BLOCK_SIZE * 8);
BUG_ON(bitmap_block >= ic->n_bitmap_blocks);
return &ic->bbs[bitmap_block];
}
-static void access_journal_check(struct dm_integrity_c *ic, unsigned section, unsigned offset,
+static void access_journal_check(struct dm_integrity_c *ic, unsigned int section, unsigned int offset,
bool e, const char *function)
{
#if defined(CONFIG_DM_DEBUG) || defined(INTERNAL_VERIFY)
- unsigned limit = e ? ic->journal_section_entries : ic->journal_section_sectors;
+ unsigned int limit = e ? ic->journal_section_entries : ic->journal_section_sectors;
if (unlikely(section >= ic->journal_sections) ||
unlikely(offset >= limit)) {
@@ -738,10 +738,10 @@ static void access_journal_check(struct dm_integrity_c *ic, unsigned section, un
#endif
}
-static void page_list_location(struct dm_integrity_c *ic, unsigned section, unsigned offset,
- unsigned *pl_index, unsigned *pl_offset)
+static void page_list_location(struct dm_integrity_c *ic, unsigned int section, unsigned int offset,
+ unsigned int *pl_index, unsigned int *pl_offset)
{
- unsigned sector;
+ unsigned int sector;
access_journal_check(ic, section, offset, false, "page_list_location");
@@ -752,9 +752,9 @@ static void page_list_location(struct dm_integrity_c *ic, unsigned section, unsi
}
static struct journal_sector *access_page_list(struct dm_integrity_c *ic, struct page_list *pl,
- unsigned section, unsigned offset, unsigned *n_sectors)
+ unsigned int section, unsigned int offset, unsigned int *n_sectors)
{
- unsigned pl_index, pl_offset;
+ unsigned int pl_index, pl_offset;
char *va;
page_list_location(ic, section, offset, &pl_index, &pl_offset);
@@ -767,14 +767,14 @@ static struct journal_sector *access_page_list(struct dm_integrity_c *ic, struct
return (struct journal_sector *)(va + pl_offset);
}
-static struct journal_sector *access_journal(struct dm_integrity_c *ic, unsigned section, unsigned offset)
+static struct journal_sector *access_journal(struct dm_integrity_c *ic, unsigned int section, unsigned int offset)
{
return access_page_list(ic, ic->journal, section, offset, NULL);
}
-static struct journal_entry *access_journal_entry(struct dm_integrity_c *ic, unsigned section, unsigned n)
+static struct journal_entry *access_journal_entry(struct dm_integrity_c *ic, unsigned int section, unsigned int n)
{
- unsigned rel_sector, offset;
+ unsigned int rel_sector, offset;
struct journal_sector *js;
access_journal_check(ic, section, n, true, "access_journal_entry");
@@ -786,7 +786,7 @@ static struct journal_entry *access_journal_entry(struct dm_integrity_c *ic, uns
return (struct journal_entry *)((char *)js + offset * ic->journal_entry_size);
}
-static struct journal_sector *access_journal_data(struct dm_integrity_c *ic, unsigned section, unsigned n)
+static struct journal_sector *access_journal_data(struct dm_integrity_c *ic, unsigned int section, unsigned int n)
{
n <<= ic->sb->log2_sectors_per_block;
@@ -797,11 +797,11 @@ static struct journal_sector *access_journal_data(struct dm_integrity_c *ic, uns
return access_journal(ic, section, n);
}
-static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result[JOURNAL_MAC_SIZE])
+static void section_mac(struct dm_integrity_c *ic, unsigned int section, __u8 result[JOURNAL_MAC_SIZE])
{
SHASH_DESC_ON_STACK(desc, ic->journal_mac);
int r;
- unsigned j, size;
+ unsigned int j, size;
desc->tfm = ic->journal_mac;
@@ -866,10 +866,10 @@ static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result
memset(result, 0, JOURNAL_MAC_SIZE);
}
-static void rw_section_mac(struct dm_integrity_c *ic, unsigned section, bool wr)
+static void rw_section_mac(struct dm_integrity_c *ic, unsigned int section, bool wr)
{
__u8 result[JOURNAL_MAC_SIZE];
- unsigned j;
+ unsigned int j;
if (!ic->journal_mac)
return;
@@ -898,12 +898,12 @@ static void complete_journal_op(void *context)
complete(&comp->comp);
}
-static void xor_journal(struct dm_integrity_c *ic, bool encrypt, unsigned section,
- unsigned n_sections, struct journal_completion *comp)
+static void xor_journal(struct dm_integrity_c *ic, bool encrypt, unsigned int section,
+ unsigned int n_sections, struct journal_completion *comp)
{
struct async_submit_ctl submit;
size_t n_bytes = (size_t)(n_sections * ic->journal_section_sectors) << SECTOR_SHIFT;
- unsigned pl_index, pl_offset, section_index;
+ unsigned int pl_index, pl_offset, section_index;
struct page_list *source_pl, *target_pl;
if (likely(encrypt)) {
@@ -928,7 +928,7 @@ static void xor_journal(struct dm_integrity_c *ic, bool encrypt, unsigned sectio
struct page *dst_page;
while (unlikely(pl_index == section_index)) {
- unsigned dummy;
+ unsigned int dummy;
if (likely(encrypt))
rw_section_mac(ic, section, true);
section++;
@@ -990,8 +990,8 @@ static bool do_crypt(bool encrypt, struct skcipher_request *req, struct journal_
return false;
}
-static void crypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned section,
- unsigned n_sections, struct journal_completion *comp)
+static void crypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned int section,
+ unsigned int n_sections, struct journal_completion *comp)
{
struct scatterlist **source_sg;
struct scatterlist **target_sg;
@@ -1008,7 +1008,7 @@ static void crypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned sect
do {
struct skcipher_request *req;
- unsigned ivsize;
+ unsigned int ivsize;
char *iv;
if (likely(encrypt))
@@ -1034,8 +1034,8 @@ static void crypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned sect
complete_journal_op(comp);
}
-static void encrypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned section,
- unsigned n_sections, struct journal_completion *comp)
+static void encrypt_journal(struct dm_integrity_c *ic, bool encrypt, unsigned int section,
+ unsigned int n_sections, struct journal_completion *comp)
{
if (ic->journal_xor)
return xor_journal(ic, encrypt, section, n_sections, comp);
@@ -1052,12 +1052,12 @@ static void complete_journal_io(unsigned long error, void *context)
}
static void rw_journal_sectors(struct dm_integrity_c *ic, blk_opf_t opf,
- unsigned sector, unsigned n_sectors,
+ unsigned int sector, unsigned int n_sectors,
struct journal_completion *comp)
{
struct dm_io_request io_req;
struct dm_io_region io_loc;
- unsigned pl_index, pl_offset;
+ unsigned int pl_index, pl_offset;
int r;
if (unlikely(dm_integrity_failed(ic))) {
@@ -1099,10 +1099,10 @@ static void rw_journal_sectors(struct dm_integrity_c *ic, blk_opf_t opf,
}
static void rw_journal(struct dm_integrity_c *ic, blk_opf_t opf,
- unsigned section, unsigned n_sections,
+ unsigned int section, unsigned int n_sections,
struct journal_completion *comp)
{
- unsigned sector, n_sectors;
+ unsigned int sector, n_sectors;
sector = section * ic->journal_section_sectors;
n_sectors = n_sections * ic->journal_section_sectors;
@@ -1110,12 +1110,12 @@ static void rw_journal(struct dm_integrity_c *ic, blk_opf_t opf,
rw_journal_sectors(ic, opf, sector, n_sectors, comp);
}
-static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsigned commit_sections)
+static void write_journal(struct dm_integrity_c *ic, unsigned int commit_start, unsigned int commit_sections)
{
struct journal_completion io_comp;
struct journal_completion crypt_comp_1;
struct journal_completion crypt_comp_2;
- unsigned i;
+ unsigned int i;
io_comp.ic = ic;
init_completion(&io_comp.comp);
@@ -1135,7 +1135,7 @@ static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsi
rw_journal(ic, REQ_OP_WRITE | REQ_FUA | REQ_SYNC, commit_start,
commit_sections, &io_comp);
} else {
- unsigned to_end;
+ unsigned int to_end;
io_comp.in_flight = (atomic_t)ATOMIC_INIT(2);
to_end = ic->journal_sections - commit_start;
if (ic->journal_io) {
@@ -1172,15 +1172,15 @@ static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsi
wait_for_completion_io(&io_comp.comp);
}
-static void copy_from_journal(struct dm_integrity_c *ic, unsigned section, unsigned offset,
- unsigned n_sectors, sector_t target, io_notify_fn fn, void *data)
+static void copy_from_journal(struct dm_integrity_c *ic, unsigned int section, unsigned int offset,
+ unsigned int n_sectors, sector_t target, io_notify_fn fn, void *data)
{
struct dm_io_request io_req;
struct dm_io_region io_loc;
int r;
- unsigned sector, pl_index, pl_offset;
+ unsigned int sector, pl_index, pl_offset;
- BUG_ON((target | n_sectors | offset) & (unsigned)(ic->sectors_per_block - 1));
+ BUG_ON((target | n_sectors | offset) & (unsigned int)(ic->sectors_per_block - 1));
if (unlikely(dm_integrity_failed(ic))) {
fn(-1UL, data);
@@ -1221,7 +1221,7 @@ static bool add_new_range(struct dm_integrity_c *ic, struct dm_integrity_range *
struct rb_node **n = &ic->in_progress.rb_node;
struct rb_node *parent;
- BUG_ON((new_range->logical_sector | new_range->n_sectors) & (unsigned)(ic->sectors_per_block - 1));
+ BUG_ON((new_range->logical_sector | new_range->n_sectors) & (unsigned int)(ic->sectors_per_block - 1));
if (likely(check_waiting)) {
struct dm_integrity_range *range;
@@ -1339,10 +1339,10 @@ static void remove_journal_node(struct dm_integrity_c *ic, struct journal_node *
#define NOT_FOUND (-1U)
-static unsigned find_journal_node(struct dm_integrity_c *ic, sector_t sector, sector_t *next_sector)
+static unsigned int find_journal_node(struct dm_integrity_c *ic, sector_t sector, sector_t *next_sector)
{
struct rb_node *n = ic->journal_tree_root.rb_node;
- unsigned found = NOT_FOUND;
+ unsigned int found = NOT_FOUND;
*next_sector = (sector_t)-1;
while (n) {
struct journal_node *j = container_of(n, struct journal_node, node);
@@ -1360,7 +1360,7 @@ static unsigned find_journal_node(struct dm_integrity_c *ic, sector_t sector, se
return found;
}
-static bool test_journal_node(struct dm_integrity_c *ic, unsigned pos, sector_t sector)
+static bool test_journal_node(struct dm_integrity_c *ic, unsigned int pos, sector_t sector)
{
struct journal_node *node, *next_node;
struct rb_node *next;
@@ -1385,7 +1385,7 @@ static bool find_newer_committed_node(struct dm_integrity_c *ic, struct journal_
{
struct rb_node *next;
struct journal_node *next_node;
- unsigned next_section;
+ unsigned int next_section;
BUG_ON(RB_EMPTY_NODE(&node->node));
@@ -1398,7 +1398,7 @@ static bool find_newer_committed_node(struct dm_integrity_c *ic, struct journal_
if (next_node->sector != node->sector)
return false;
- next_section = (unsigned)(next_node - ic->journal_tree) / ic->journal_section_entries;
+ next_section = (unsigned int)(next_node - ic->journal_tree) / ic->journal_section_entries;
if (next_section >= ic->committed_section &&
next_section < ic->committed_section + ic->n_committed_sections)
return true;
@@ -1413,17 +1413,17 @@ static bool find_newer_committed_node(struct dm_integrity_c *ic, struct journal_
#define TAG_CMP 2
static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, sector_t *metadata_block,
- unsigned *metadata_offset, unsigned total_size, int op)
+ unsigned int *metadata_offset, unsigned int total_size, int op)
{
#define MAY_BE_FILLER 1
#define MAY_BE_HASH 2
- unsigned hash_offset = 0;
- unsigned may_be = MAY_BE_HASH | (ic->discard ? MAY_BE_FILLER : 0);
+ unsigned int hash_offset = 0;
+ unsigned int may_be = MAY_BE_HASH | (ic->discard ? MAY_BE_FILLER : 0);
do {
unsigned char *data, *dp;
struct dm_buffer *b;
- unsigned to_copy;
+ unsigned int to_copy;
int r;
r = dm_integrity_failed(ic);
@@ -1453,7 +1453,7 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se
goto thorough_test;
}
} else {
- unsigned i, ts;
+ unsigned int i, ts;
thorough_test:
ts = total_size;
@@ -1652,7 +1652,7 @@ static void integrity_sector_checksum(struct dm_integrity_c *ic, sector_t sector
__le64 sector_le = cpu_to_le64(sector);
SHASH_DESC_ON_STACK(req, ic->internal_hash);
int r;
- unsigned digest_size;
+ unsigned int digest_size;
req->tfm = ic->internal_hash;
@@ -1709,13 +1709,13 @@ static void integrity_metadata(struct work_struct *w)
if (ic->internal_hash) {
struct bvec_iter iter;
struct bio_vec bv;
- unsigned digest_size = crypto_shash_digestsize(ic->internal_hash);
+ unsigned int digest_size = crypto_shash_digestsize(ic->internal_hash);
struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
char *checksums;
- unsigned extra_space = unlikely(digest_size > ic->tag_size) ? digest_size - ic->tag_size : 0;
+ unsigned int extra_space = unlikely(digest_size > ic->tag_size) ? digest_size - ic->tag_size : 0;
char checksums_onstack[max((size_t)HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
sector_t sector;
- unsigned sectors_to_process;
+ unsigned int sectors_to_process;
if (unlikely(ic->mode == 'R'))
goto skip_io;
@@ -1735,14 +1735,13 @@ static void integrity_metadata(struct work_struct *w)
}
if (unlikely(dio->op == REQ_OP_DISCARD)) {
- sector_t bi_sector = dio->bio_details.bi_iter.bi_sector;
- unsigned bi_size = dio->bio_details.bi_iter.bi_size;
- unsigned max_size = likely(checksums != checksums_onstack) ? PAGE_SIZE : HASH_MAX_DIGESTSIZE;
- unsigned max_blocks = max_size / ic->tag_size;
+ unsigned int bi_size = dio->bio_details.bi_iter.bi_size;
+ unsigned int max_size = likely(checksums != checksums_onstack) ? PAGE_SIZE : HASH_MAX_DIGESTSIZE;
+ unsigned int max_blocks = max_size / ic->tag_size;
memset(checksums, DISCARD_FILLER, max_size);
while (bi_size) {
- unsigned this_step_blocks = bi_size >> (SECTOR_SHIFT + ic->sb->log2_sectors_per_block);
+ unsigned int this_step_blocks = bi_size >> (SECTOR_SHIFT + ic->sb->log2_sectors_per_block);
this_step_blocks = min(this_step_blocks, max_blocks);
r = dm_integrity_rw_tag(ic, checksums, &dio->metadata_block, &dio->metadata_offset,
this_step_blocks * ic->tag_size, TAG_WRITE);
@@ -1752,13 +1751,7 @@ static void integrity_metadata(struct work_struct *w)
goto error;
}
- /*if (bi_size < this_step_blocks << (SECTOR_SHIFT + ic->sb->log2_sectors_per_block)) {
- printk("BUGG: bi_sector: %llx, bi_size: %u\n", bi_sector, bi_size);
- printk("BUGG: this_step_blocks: %u\n", this_step_blocks);
- BUG();
- }*/
bi_size -= this_step_blocks << (SECTOR_SHIFT + ic->sb->log2_sectors_per_block);
- bi_sector += this_step_blocks << ic->sb->log2_sectors_per_block;
}
if (likely(checksums != checksums_onstack))
@@ -1770,7 +1763,7 @@ static void integrity_metadata(struct work_struct *w)
sectors_to_process = dio->range.n_sectors;
__bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) {
- unsigned pos;
+ unsigned int pos;
char *mem, *checksums_ptr;
again:
@@ -1823,13 +1816,13 @@ static void integrity_metadata(struct work_struct *w)
if (bip) {
struct bio_vec biv;
struct bvec_iter iter;
- unsigned data_to_process = dio->range.n_sectors;
+ unsigned int data_to_process = dio->range.n_sectors;
sector_to_block(ic, data_to_process);
data_to_process *= ic->tag_size;
bip_for_each_vec(biv, bip, iter) {
unsigned char *tag;
- unsigned this_len;
+ unsigned int this_len;
BUG_ON(PageHighMem(biv.bv_page));
tag = bvec_virt(&biv);
@@ -1867,7 +1860,7 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
if (unlikely(dio->op == REQ_OP_DISCARD)) {
if (ti->max_io_len) {
sector_t sec = dm_target_offset(ti, bio->bi_iter.bi_sector);
- unsigned log2_max_io_len = __fls(ti->max_io_len);
+ unsigned int log2_max_io_len = __fls(ti->max_io_len);
sector_t start_boundary = sec >> log2_max_io_len;
sector_t end_boundary = (sec + bio_sectors(bio) - 1) >> log2_max_io_len;
if (start_boundary < end_boundary) {
@@ -1897,7 +1890,7 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
ic->provided_data_sectors);
return DM_MAPIO_KILL;
}
- if (unlikely((dio->range.logical_sector | bio_sectors(bio)) & (unsigned)(ic->sectors_per_block - 1))) {
+ if (unlikely((dio->range.logical_sector | bio_sectors(bio)) & (unsigned int)(ic->sectors_per_block - 1))) {
DMERR("Bio not aligned on %u sectors: 0x%llx, 0x%x",
ic->sectors_per_block,
dio->range.logical_sector, bio_sectors(bio));
@@ -1919,7 +1912,7 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
bip = bio_integrity(bio);
if (!ic->internal_hash) {
if (bip) {
- unsigned wanted_tag_size = bio_sectors(bio) >> ic->sb->log2_sectors_per_block;
+ unsigned int wanted_tag_size = bio_sectors(bio) >> ic->sb->log2_sectors_per_block;
if (ic->log2_tag_size >= 0)
wanted_tag_size <<= ic->log2_tag_size;
else
@@ -1949,11 +1942,11 @@ static int dm_integrity_map(struct dm_target *ti, struct bio *bio)
}
static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
- unsigned journal_section, unsigned journal_entry)
+ unsigned int journal_section, unsigned int journal_entry)
{
struct dm_integrity_c *ic = dio->ic;
sector_t logical_sector;
- unsigned n_sectors;
+ unsigned int n_sectors;
logical_sector = dio->range.logical_sector;
n_sectors = dio->range.n_sectors;
@@ -1976,7 +1969,7 @@ static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
if (unlikely(dio->op == REQ_OP_READ)) {
struct journal_sector *js;
char *mem_ptr;
- unsigned s;
+ unsigned int s;
if (unlikely(journal_entry_is_inprogress(je))) {
flush_dcache_page(bv.bv_page);
@@ -2013,12 +2006,12 @@ static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
if (!ic->internal_hash) {
struct bio_integrity_payload *bip = bio_integrity(bio);
- unsigned tag_todo = ic->tag_size;
+ unsigned int tag_todo = ic->tag_size;
char *tag_ptr = journal_entry_tag(ic, je);
if (bip) do {
struct bio_vec biv = bvec_iter_bvec(bip->bip_vec, bip->bip_iter);
- unsigned tag_now = min(biv.bv_len, tag_todo);
+ unsigned int tag_now = min(biv.bv_len, tag_todo);
char *tag_addr;
BUG_ON(PageHighMem(biv.bv_page));
tag_addr = bvec_virt(&biv);
@@ -2037,7 +2030,7 @@ static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
if (likely(dio->op == REQ_OP_WRITE)) {
struct journal_sector *js;
- unsigned s;
+ unsigned int s;
js = access_journal_data(ic, journal_section, journal_entry);
memcpy(js, mem + bv.bv_offset, ic->sectors_per_block << SECTOR_SHIFT);
@@ -2048,7 +2041,7 @@ static bool __journal_read_write(struct dm_integrity_io *dio, struct bio *bio,
} while (++s < ic->sectors_per_block);
if (ic->internal_hash) {
- unsigned digest_size = crypto_shash_digestsize(ic->internal_hash);
+ unsigned int digest_size = crypto_shash_digestsize(ic->internal_hash);
if (unlikely(digest_size > ic->tag_size)) {
char checksums_onstack[HASH_MAX_DIGESTSIZE];
integrity_sector_checksum(ic, logical_sector, (char *)js, checksums_onstack);
@@ -2105,8 +2098,8 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
{
struct dm_integrity_c *ic = dio->ic;
struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
- unsigned journal_section, journal_entry;
- unsigned journal_read_pos;
+ unsigned int journal_section, journal_entry;
+ unsigned int journal_read_pos;
struct completion read_comp;
bool discard_retried = false;
bool need_sync_io = ic->internal_hash && dio->op == REQ_OP_READ;
@@ -2131,8 +2124,8 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
journal_read_pos = NOT_FOUND;
if (ic->mode == 'J' && likely(dio->op != REQ_OP_DISCARD)) {
if (dio->op == REQ_OP_WRITE) {
- unsigned next_entry, i, pos;
- unsigned ws, we, range_sectors;
+ unsigned int next_entry, i, pos;
+ unsigned int ws, we, range_sectors;
dio->range.n_sectors = min(dio->range.n_sectors,
(sector_t)ic->free_sectors << ic->sb->log2_sectors_per_block);
@@ -2185,8 +2178,8 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
if (unlikely(dio->range.n_sectors > next_sector - dio->range.logical_sector))
dio->range.n_sectors = next_sector - dio->range.logical_sector;
} else {
- unsigned i;
- unsigned jp = journal_read_pos + 1;
+ unsigned int i;
+ unsigned int jp = journal_read_pos + 1;
for (i = ic->sectors_per_block; i < dio->range.n_sectors; i += ic->sectors_per_block, jp++) {
if (!test_journal_node(ic, jp, dio->range.logical_sector + i))
break;
@@ -2218,7 +2211,7 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
*/
if (journal_read_pos != NOT_FOUND) {
sector_t next_sector;
- unsigned new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
+ unsigned int new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
if (unlikely(new_pos != journal_read_pos)) {
remove_range_unlocked(ic, &dio->range);
goto retry;
@@ -2227,7 +2220,7 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
}
if (ic->mode == 'J' && likely(dio->op == REQ_OP_DISCARD) && !discard_retried) {
sector_t next_sector;
- unsigned new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
+ unsigned int new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
if (unlikely(new_pos != NOT_FOUND) ||
unlikely(next_sector < dio->range.logical_sector - dio->range.n_sectors)) {
remove_range_unlocked(ic, &dio->range);
@@ -2354,8 +2347,8 @@ static void pad_uncommitted(struct dm_integrity_c *ic)
static void integrity_commit(struct work_struct *w)
{
struct dm_integrity_c *ic = container_of(w, struct dm_integrity_c, commit_work);
- unsigned commit_start, commit_sections;
- unsigned i, j, n;
+ unsigned int commit_start, commit_sections;
+ unsigned int i, j, n;
struct bio *flushes;
del_timer(&ic->autocommit_timer);
@@ -2433,17 +2426,17 @@ static void complete_copy_from_journal(unsigned long error, void *context)
static void restore_last_bytes(struct dm_integrity_c *ic, struct journal_sector *js,
struct journal_entry *je)
{
- unsigned s = 0;
+ unsigned int s = 0;
do {
js->commit_id = je->last_bytes[s];
js++;
} while (++s < ic->sectors_per_block);
}
-static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
- unsigned write_sections, bool from_replay)
+static void do_journal_write(struct dm_integrity_c *ic, unsigned int write_start,
+ unsigned int write_sections, bool from_replay)
{
- unsigned i, j, n;
+ unsigned int i, j, n;
struct journal_completion comp;
struct blk_plug plug;
@@ -2462,9 +2455,9 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
for (j = 0; j < ic->journal_section_entries; j++) {
struct journal_entry *je = access_journal_entry(ic, i, j);
sector_t sec, area, offset;
- unsigned k, l, next_loop;
+ unsigned int k, l, next_loop;
sector_t metadata_block;
- unsigned metadata_offset;
+ unsigned int metadata_offset;
struct journal_io *io;
if (journal_entry_is_unused(je))
@@ -2472,7 +2465,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
BUG_ON(unlikely(journal_entry_is_inprogress(je)) && !from_replay);
sec = journal_entry_get_sector(je);
if (unlikely(from_replay)) {
- if (unlikely(sec & (unsigned)(ic->sectors_per_block - 1))) {
+ if (unlikely(sec & (unsigned int)(ic->sectors_per_block - 1))) {
dm_integrity_io_error(ic, "invalid sector in journal", -EIO);
sec &= ~(sector_t)(ic->sectors_per_block - 1);
}
@@ -2590,9 +2583,9 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
static void integrity_writer(struct work_struct *w)
{
struct dm_integrity_c *ic = container_of(w, struct dm_integrity_c, writer_work);
- unsigned write_start, write_sections;
+ unsigned int write_start, write_sections;
- unsigned prev_free_sectors;
+ unsigned int prev_free_sectors;
spin_lock_irq(&ic->endio_wait.lock);
write_start = ic->committed_section;
@@ -2639,12 +2632,12 @@ static void integrity_recalc(struct work_struct *w)
struct dm_io_region io_loc;
sector_t area, offset;
sector_t metadata_block;
- unsigned metadata_offset;
+ unsigned int metadata_offset;
sector_t logical_sector, n_sectors;
__u8 *t;
- unsigned i;
+ unsigned int i;
int r;
- unsigned super_counter = 0;
+ unsigned int super_counter = 0;
DEBUG_print("start recalculation... (position %llx)\n", le64_to_cpu(ic->sb->recalc_sector));
@@ -2668,7 +2661,7 @@ static void integrity_recalc(struct work_struct *w)
get_area_and_offset(ic, range.logical_sector, &area, &offset);
range.n_sectors = min((sector_t)RECALC_SECTORS, ic->provided_data_sectors - range.logical_sector);
if (!ic->meta_dev)
- range.n_sectors = min(range.n_sectors, ((sector_t)1U << ic->sb->log2_interleave_sectors) - (unsigned)offset);
+ range.n_sectors = min(range.n_sectors, ((sector_t)1U << ic->sb->log2_interleave_sectors) - (unsigned int)offset);
add_new_range_and_wait(ic, &range);
spin_unlock_irq(&ic->endio_wait.lock);
@@ -2859,10 +2852,10 @@ static void bitmap_flush_work(struct work_struct *work)
}
-static void init_journal(struct dm_integrity_c *ic, unsigned start_section,
- unsigned n_sections, unsigned char commit_seq)
+static void init_journal(struct dm_integrity_c *ic, unsigned int start_section,
+ unsigned int n_sections, unsigned char commit_seq)
{
- unsigned i, j, n;
+ unsigned int i, j, n;
if (!n_sections)
return;
@@ -2885,7 +2878,7 @@ static void init_journal(struct dm_integrity_c *ic, unsigned start_section,
write_journal(ic, start_section, n_sections);
}
-static int find_commit_seq(struct dm_integrity_c *ic, unsigned i, unsigned j, commit_id_t id)
+static int find_commit_seq(struct dm_integrity_c *ic, unsigned int i, unsigned int j, commit_id_t id)
{
unsigned char k;
for (k = 0; k < N_COMMIT_IDS; k++) {
@@ -2898,11 +2891,11 @@ static int find_commit_seq(struct dm_integrity_c *ic, unsigned i, unsigned j, co
static void replay_journal(struct dm_integrity_c *ic)
{
- unsigned i, j;
+ unsigned int i, j;
bool used_commit_ids[N_COMMIT_IDS];
- unsigned max_commit_id_sections[N_COMMIT_IDS];
- unsigned write_start, write_sections;
- unsigned continue_section;
+ unsigned int max_commit_id_sections[N_COMMIT_IDS];
+ unsigned int write_start, write_sections;
+ unsigned int continue_section;
bool journal_empty;
unsigned char unused, last_used, want_commit_seq;
@@ -3020,7 +3013,7 @@ static void replay_journal(struct dm_integrity_c *ic)
ic->commit_seq = want_commit_seq;
DEBUG_print("continuing from section %u, commit seq %d\n", write_start, ic->commit_seq);
} else {
- unsigned s;
+ unsigned int s;
unsigned char erase_seq;
clear_journal:
DEBUG_print("clearing journal\n");
@@ -3252,10 +3245,10 @@ static void dm_integrity_resume(struct dm_target *ti)
}
static void dm_integrity_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct dm_integrity_c *ic = (struct dm_integrity_c *)ti->private;
- unsigned arg_count;
+ unsigned int arg_count;
size_t sz = 0;
switch (type) {
@@ -3305,7 +3298,7 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors);
DMEMIT(" buffer_sectors:%u", 1U << ic->log2_buffer_sectors);
if (ic->mode == 'J') {
- DMEMIT(" journal_watermark:%u", (unsigned)watermark_percentage);
+ DMEMIT(" journal_watermark:%u", (unsigned int)watermark_percentage);
DMEMIT(" commit_time:%u", ic->autocommit_msec);
}
if (ic->mode == 'B') {
@@ -3384,7 +3377,7 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
static void calculate_journal_section_size(struct dm_integrity_c *ic)
{
- unsigned sector_space = JOURNAL_SECTOR_DATA;
+ unsigned int sector_space = JOURNAL_SECTOR_DATA;
ic->journal_sections = le32_to_cpu(ic->sb->journal_sections);
ic->journal_entry_size = roundup(offsetof(struct journal_entry, last_bytes[ic->sectors_per_block]) + ic->tag_size,
@@ -3461,9 +3454,10 @@ static void get_provided_data_sectors(struct dm_integrity_c *ic)
}
}
-static int initialize_superblock(struct dm_integrity_c *ic, unsigned journal_sectors, unsigned interleave_sectors)
+static int initialize_superblock(struct dm_integrity_c *ic,
+ unsigned int journal_sectors, unsigned int interleave_sectors)
{
- unsigned journal_sections;
+ unsigned int journal_sections;
int test_bit;
memset(ic->sb, 0, SB_SECTORS << SECTOR_SHIFT);
@@ -3548,7 +3542,7 @@ static void dm_integrity_set(struct dm_target *ti, struct dm_integrity_c *ic)
static void dm_integrity_free_page_list(struct page_list *pl)
{
- unsigned i;
+ unsigned int i;
if (!pl)
return;
@@ -3557,10 +3551,10 @@ static void dm_integrity_free_page_list(struct page_list *pl)
kvfree(pl);
}
-static struct page_list *dm_integrity_alloc_page_list(unsigned n_pages)
+static struct page_list *dm_integrity_alloc_page_list(unsigned int n_pages)
{
struct page_list *pl;
- unsigned i;
+ unsigned int i;
pl = kvmalloc_array(n_pages + 1, sizeof(struct page_list), GFP_KERNEL | __GFP_ZERO);
if (!pl)
@@ -3583,7 +3577,7 @@ static struct page_list *dm_integrity_alloc_page_list(unsigned n_pages)
static void dm_integrity_free_journal_scatterlist(struct dm_integrity_c *ic, struct scatterlist **sl)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < ic->journal_sections; i++)
kvfree(sl[i]);
kvfree(sl);
@@ -3593,7 +3587,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
struct page_list *pl)
{
struct scatterlist **sl;
- unsigned i;
+ unsigned int i;
sl = kvmalloc_array(ic->journal_sections,
sizeof(struct scatterlist *),
@@ -3603,10 +3597,10 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
for (i = 0; i < ic->journal_sections; i++) {
struct scatterlist *s;
- unsigned start_index, start_offset;
- unsigned end_index, end_offset;
- unsigned n_pages;
- unsigned idx;
+ unsigned int start_index, start_offset;
+ unsigned int end_index, end_offset;
+ unsigned int n_pages;
+ unsigned int idx;
page_list_location(ic, i, 0, &start_index, &start_offset);
page_list_location(ic, i, ic->journal_section_sectors - 1,
@@ -3624,7 +3618,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
sg_init_table(s, n_pages);
for (idx = start_index; idx <= end_index; idx++) {
char *va = lowmem_page_address(pl[idx].page);
- unsigned start = 0, end = PAGE_SIZE;
+ unsigned int start = 0, end = PAGE_SIZE;
if (idx == start_index)
start = start_offset;
if (idx == end_index)
@@ -3711,7 +3705,7 @@ static int get_mac(struct crypto_shash **hash, struct alg_spec *a, char **error,
static int create_journal(struct dm_integrity_c *ic, char **error)
{
int r = 0;
- unsigned i;
+ unsigned int i;
__u64 journal_pages, journal_desc_size, journal_tree_size;
unsigned char *crypt_data = NULL, *crypt_iv = NULL;
struct skcipher_request *req = NULL;
@@ -3738,7 +3732,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
goto bad;
}
if (ic->journal_crypt_alg.alg_string) {
- unsigned ivsize, blocksize;
+ unsigned int ivsize, blocksize;
struct journal_completion comp;
comp.ic = ic;
@@ -3827,7 +3821,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
crypto_free_skcipher(ic->journal_crypt);
ic->journal_crypt = NULL;
} else {
- unsigned crypt_len = roundup(ivsize, blocksize);
+ unsigned int crypt_len = roundup(ivsize, blocksize);
req = skcipher_request_alloc(ic->journal_crypt, GFP_KERNEL);
if (!req) {
@@ -3915,7 +3909,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
}
for (i = 0; i < N_COMMIT_IDS; i++) {
- unsigned j;
+ unsigned int j;
retest_commit_id:
for (j = 0; j < i; j++) {
if (ic->commit_ids[j] == ic->commit_ids[i]) {
@@ -3969,17 +3963,17 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
* journal_mac
* recalculate
*/
-static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct dm_integrity_c *ic;
char dummy;
int r;
- unsigned extra_args;
+ unsigned int extra_args;
struct dm_arg_set as;
static const struct dm_arg _args[] = {
{0, 18, "Invalid number of feature args"},
};
- unsigned journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec;
+ unsigned int journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec;
bool should_write_sb;
__u64 threshold;
unsigned long long start;
@@ -4058,7 +4052,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
while (extra_args--) {
const char *opt_string;
- unsigned val;
+ unsigned int val;
unsigned long long llval;
opt_string = dm_shift_arg(&as);
if (!opt_string) {
@@ -4391,7 +4385,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
DEBUG_print(" journal_entries_per_sector %u\n", ic->journal_entries_per_sector);
DEBUG_print(" journal_section_entries %u\n", ic->journal_section_entries);
DEBUG_print(" journal_section_sectors %u\n", ic->journal_section_sectors);
- DEBUG_print(" journal_sections %u\n", (unsigned)le32_to_cpu(ic->sb->journal_sections));
+ DEBUG_print(" journal_sections %u\n", (unsigned int)le32_to_cpu(ic->sb->journal_sections));
DEBUG_print(" journal_entries %u\n", ic->journal_entries);
DEBUG_print(" log2_interleave_sectors %d\n", ic->sb->log2_interleave_sectors);
DEBUG_print(" data_device_sectors 0x%llx\n", bdev_nr_sectors(ic->dev->bdev));
@@ -4465,8 +4459,8 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
}
if (ic->mode == 'B') {
- unsigned i;
- unsigned n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
+ unsigned int i;
+ unsigned int n_bitmap_pages = DIV_ROUND_UP(ic->n_bitmap_blocks, PAGE_SIZE / BITMAP_BLOCK_SIZE);
ic->recalc_bitmap = dm_integrity_alloc_page_list(n_bitmap_pages);
if (!ic->recalc_bitmap) {
@@ -4486,7 +4480,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
INIT_DELAYED_WORK(&ic->bitmap_flush_work, bitmap_flush_work);
for (i = 0; i < ic->n_bitmap_blocks; i++) {
struct bitmap_block_status *bbs = &ic->bbs[i];
- unsigned sector, pl_index, pl_offset;
+ unsigned int sector, pl_index, pl_offset;
INIT_WORK(&bbs->work, bitmap_block_work);
bbs->ic = ic;
@@ -4523,7 +4517,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto bad;
}
if (ic->mode == 'B') {
- unsigned max_io_len = ((sector_t)ic->sectors_per_block << ic->log2_blocks_per_bitmap_bit) * (BITMAP_BLOCK_SIZE * 8);
+ unsigned int max_io_len = ((sector_t)ic->sectors_per_block << ic->log2_blocks_per_bitmap_bit) * (BITMAP_BLOCK_SIZE * 8);
if (!max_io_len)
max_io_len = 1U << 31;
DEBUG_print("max_io_len: old %u, new %u\n", ti->max_io_len, max_io_len);
@@ -4594,7 +4588,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
if (ic->journal_io_scatterlist)
dm_integrity_free_journal_scatterlist(ic, ic->journal_io_scatterlist);
if (ic->sk_requests) {
- unsigned i;
+ unsigned int i;
for (i = 0; i < ic->journal_sections; i++) {
struct skcipher_request *req = ic->sk_requests[i];
diff --git a/drivers/md/dm-io-rewind.c b/drivers/md/dm-io-rewind.c
index 0db53ccb94ba..773c4cff8b89 100644
--- a/drivers/md/dm-io-rewind.c
+++ b/drivers/md/dm-io-rewind.c
@@ -57,7 +57,7 @@ static void dm_bio_integrity_rewind(struct bio *bio, unsigned int bytes_done)
{
struct bio_integrity_payload *bip = bio_integrity(bio);
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
- unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
+ unsigned int bytes = bio_integrity_bytes(bi, bytes_done >> 9);
bip->bip_iter.bi_sector -= bio_integrity_intervals(bi, bytes_done >> 9);
dm_bvec_iter_rewind(bip->bip_vec, &bip->bip_iter, bytes);
@@ -131,7 +131,7 @@ static inline void dm_bio_rewind_iter(const struct bio *bio,
* rewinding from end of bio and restoring its original position.
* Caller is also responsibile for restoring bio's size.
*/
-static void dm_bio_rewind(struct bio *bio, unsigned bytes)
+static void dm_bio_rewind(struct bio *bio, unsigned int bytes)
{
if (bio_integrity(bio))
dm_bio_integrity_rewind(bio, bytes);
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 783564533459..e488b05e35fa 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -48,7 +48,7 @@ static struct kmem_cache *_dm_io_cache;
struct dm_io_client *dm_io_client_create(void)
{
struct dm_io_client *client;
- unsigned min_ios = dm_get_reserved_bio_based_ios();
+ unsigned int min_ios = dm_get_reserved_bio_based_ios();
int ret;
client = kzalloc(sizeof(*client), GFP_KERNEL);
@@ -88,7 +88,7 @@ EXPORT_SYMBOL(dm_io_client_destroy);
* bi_private.
*---------------------------------------------------------------*/
static void store_io_and_region_in_bio(struct bio *bio, struct io *io,
- unsigned region)
+ unsigned int region)
{
if (unlikely(!IS_ALIGNED((unsigned long)io, DM_IO_MAX_REGIONS))) {
DMCRIT("Unaligned struct io pointer %p", io);
@@ -99,7 +99,7 @@ static void store_io_and_region_in_bio(struct bio *bio, struct io *io,
}
static void retrieve_io_and_region_from_bio(struct bio *bio, struct io **io,
- unsigned *region)
+ unsigned int *region)
{
unsigned long val = (unsigned long)bio->bi_private;
@@ -137,7 +137,7 @@ static void dec_count(struct io *io, unsigned int region, blk_status_t error)
static void endio(struct bio *bio)
{
struct io *io;
- unsigned region;
+ unsigned int region;
blk_status_t error;
if (bio->bi_status && bio_data_dir(bio) == READ)
@@ -160,11 +160,11 @@ static void endio(struct bio *bio)
*---------------------------------------------------------------*/
struct dpages {
void (*get_page)(struct dpages *dp,
- struct page **p, unsigned long *len, unsigned *offset);
+ struct page **p, unsigned long *len, unsigned int *offset);
void (*next_page)(struct dpages *dp);
union {
- unsigned context_u;
+ unsigned int context_u;
struct bvec_iter context_bi;
};
void *context_ptr;
@@ -177,9 +177,9 @@ struct dpages {
* Functions for getting the pages from a list.
*/
static void list_get_page(struct dpages *dp,
- struct page **p, unsigned long *len, unsigned *offset)
+ struct page **p, unsigned long *len, unsigned int *offset)
{
- unsigned o = dp->context_u;
+ unsigned int o = dp->context_u;
struct page_list *pl = (struct page_list *) dp->context_ptr;
*p = pl->page;
@@ -194,7 +194,7 @@ static void list_next_page(struct dpages *dp)
dp->context_u = 0;
}
-static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offset)
+static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned int offset)
{
dp->get_page = list_get_page;
dp->next_page = list_next_page;
@@ -206,7 +206,7 @@ static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offse
* Functions for getting the pages from a bvec.
*/
static void bio_get_page(struct dpages *dp, struct page **p,
- unsigned long *len, unsigned *offset)
+ unsigned long *len, unsigned int *offset)
{
struct bio_vec bvec = bvec_iter_bvec((struct bio_vec *)dp->context_ptr,
dp->context_bi);
@@ -244,7 +244,7 @@ static void bio_dp_init(struct dpages *dp, struct bio *bio)
* Functions for getting the pages from a VMA.
*/
static void vm_get_page(struct dpages *dp,
- struct page **p, unsigned long *len, unsigned *offset)
+ struct page **p, unsigned long *len, unsigned int *offset)
{
*p = vmalloc_to_page(dp->context_ptr);
*offset = dp->context_u;
@@ -269,7 +269,7 @@ static void vm_dp_init(struct dpages *dp, void *data)
* Functions for getting the pages from kernel memory.
*/
static void km_get_page(struct dpages *dp, struct page **p, unsigned long *len,
- unsigned *offset)
+ unsigned int *offset)
{
*p = virt_to_page(dp->context_ptr);
*offset = dp->context_u;
@@ -293,15 +293,15 @@ static void km_dp_init(struct dpages *dp, void *data)
/*-----------------------------------------------------------------
* IO routines that accept a list of pages.
*---------------------------------------------------------------*/
-static void do_region(const blk_opf_t opf, unsigned region,
+static void do_region(const blk_opf_t opf, unsigned int region,
struct dm_io_region *where, struct dpages *dp,
struct io *io)
{
struct bio *bio;
struct page *page;
unsigned long len;
- unsigned offset;
- unsigned num_bvecs;
+ unsigned int offset;
+ unsigned int num_bvecs;
sector_t remaining = where->count;
struct request_queue *q = bdev_get_queue(where->bdev);
sector_t num_sectors;
@@ -508,7 +508,7 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp,
return 0;
}
-int dm_io(struct dm_io_request *io_req, unsigned num_regions,
+int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
struct dm_io_region *where, unsigned long *sync_error_bits)
{
int r;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index fdb7846a97a4..41d55218b076 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -31,7 +31,7 @@ struct dm_file {
* poll will wait until the global event number is greater than
* this value.
*/
- volatile unsigned global_event_nr;
+ volatile unsigned int global_event_nr;
};
/*-----------------------------------------------------------------
@@ -413,7 +413,7 @@ static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
struct hash_cell *hc;
struct dm_table *table;
struct mapped_device *md;
- unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
+ unsigned int change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
int srcu_idx;
/*
@@ -1021,7 +1021,7 @@ static int dev_rename(struct file *filp, struct dm_ioctl *param, size_t param_si
int r;
char *new_data = (char *) param + param->data_start;
struct mapped_device *md;
- unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
+ unsigned int change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
if (new_data < param->data ||
invalid_str(new_data, (void *) param + param_size) || !*new_data ||
@@ -1096,7 +1096,7 @@ static int dev_set_geometry(struct file *filp, struct dm_ioctl *param, size_t pa
static int do_suspend(struct dm_ioctl *param)
{
int r = 0;
- unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
+ unsigned int suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
struct mapped_device *md;
md = find_device(param);
@@ -1125,7 +1125,7 @@ static int do_suspend(struct dm_ioctl *param)
static int do_resume(struct dm_ioctl *param)
{
int r = 0;
- unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
+ unsigned int suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
struct hash_cell *hc;
struct mapped_device *md;
struct dm_table *new_map, *old_map = NULL;
@@ -1243,7 +1243,7 @@ static void retrieve_status(struct dm_table *table,
char *outbuf, *outptr;
status_type_t type;
size_t remaining, len, used = 0;
- unsigned status_flags = 0;
+ unsigned int status_flags = 0;
outptr = outbuf = get_result_buffer(param, param_size, &len);
@@ -1648,8 +1648,8 @@ static int table_status(struct file *filp, struct dm_ioctl *param, size_t param_
* Returns a number <= 1 if message was processed by device mapper.
* Returns 2 if message should be delivered to the target.
*/
-static int message_for_md(struct mapped_device *md, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int message_for_md(struct mapped_device *md, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r;
@@ -1859,7 +1859,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
struct dm_ioctl *dmi;
int secure_data;
const size_t minimum_data_size = offsetof(struct dm_ioctl, data);
- unsigned noio_flag;
+ unsigned int noio_flag;
if (copy_from_user(param_kernel, user, minimum_data_size))
return -EFAULT;
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 4d3bbbea2e9a..0ef78e56aa88 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -34,14 +34,14 @@
#define DEFAULT_SUB_JOB_SIZE_KB 512
#define MAX_SUB_JOB_SIZE_KB 1024
-static unsigned kcopyd_subjob_size_kb = DEFAULT_SUB_JOB_SIZE_KB;
+static unsigned int kcopyd_subjob_size_kb = DEFAULT_SUB_JOB_SIZE_KB;
module_param(kcopyd_subjob_size_kb, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(kcopyd_subjob_size_kb, "Sub-job size for dm-kcopyd clients");
-static unsigned dm_get_kcopyd_subjob_size(void)
+static unsigned int dm_get_kcopyd_subjob_size(void)
{
- unsigned sub_job_size_kb;
+ unsigned int sub_job_size_kb;
sub_job_size_kb = __dm_get_module_param(&kcopyd_subjob_size_kb,
DEFAULT_SUB_JOB_SIZE_KB,
@@ -56,9 +56,9 @@ static unsigned dm_get_kcopyd_subjob_size(void)
*---------------------------------------------------------------*/
struct dm_kcopyd_client {
struct page_list *pages;
- unsigned nr_reserved_pages;
- unsigned nr_free_pages;
- unsigned sub_job_size;
+ unsigned int nr_reserved_pages;
+ unsigned int nr_free_pages;
+ unsigned int sub_job_size;
struct dm_io_client *io_client;
@@ -119,7 +119,7 @@ static DEFINE_SPINLOCK(throttle_spinlock);
static void io_job_start(struct dm_kcopyd_throttle *t)
{
- unsigned throttle, now, difference;
+ unsigned int throttle, now, difference;
int slept = 0, skew;
if (unlikely(!t))
@@ -182,7 +182,7 @@ static void io_job_finish(struct dm_kcopyd_throttle *t)
goto skip_limit;
if (!t->num_io_jobs) {
- unsigned now, difference;
+ unsigned int now, difference;
now = jiffies;
difference = now - t->last_jiffies;
@@ -303,9 +303,9 @@ static void drop_pages(struct page_list *pl)
/*
* Allocate and reserve nr_pages for the use of a specific client.
*/
-static int client_reserve_pages(struct dm_kcopyd_client *kc, unsigned nr_pages)
+static int client_reserve_pages(struct dm_kcopyd_client *kc, unsigned int nr_pages)
{
- unsigned i;
+ unsigned int i;
struct page_list *pl = NULL, *next;
for (i = 0; i < nr_pages; i++) {
@@ -341,7 +341,7 @@ static void client_free_pages(struct dm_kcopyd_client *kc)
struct kcopyd_job {
struct dm_kcopyd_client *kc;
struct list_head list;
- unsigned flags;
+ unsigned int flags;
/*
* Error state of the job.
@@ -582,7 +582,7 @@ static int run_io_job(struct kcopyd_job *job)
static int run_pages_job(struct kcopyd_job *job)
{
int r;
- unsigned nr_pages = dm_div_up(job->dests[0].count, PAGE_SIZE >> 9);
+ unsigned int nr_pages = dm_div_up(job->dests[0].count, PAGE_SIZE >> 9);
r = kcopyd_get_pages(job->kc, nr_pages, &job->pages);
if (!r) {
@@ -849,8 +849,8 @@ void dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
EXPORT_SYMBOL(dm_kcopyd_copy);
void dm_kcopyd_zero(struct dm_kcopyd_client *kc,
- unsigned num_dests, struct dm_io_region *dests,
- unsigned flags, dm_kcopyd_notify_fn fn, void *context)
+ unsigned int num_dests, struct dm_io_region *dests,
+ unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
{
dm_kcopyd_copy(kc, NULL, num_dests, dests, flags, fn, context);
}
@@ -906,7 +906,7 @@ int kcopyd_cancel(struct kcopyd_job *job, int block)
struct dm_kcopyd_client *dm_kcopyd_client_create(struct dm_kcopyd_throttle *throttle)
{
int r;
- unsigned reserve_pages;
+ unsigned int reserve_pages;
struct dm_kcopyd_client *kc;
kc = kzalloc(sizeof(*kc), GFP_KERNEL);
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 3212ef6aa81b..26b1af646177 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -95,7 +95,7 @@ static int linear_map(struct dm_target *ti, struct bio *bio)
}
static void linear_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct linear_c *lc = (struct linear_c *) ti->private;
size_t sz = 0;
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c
index 9ab93ebea889..9fc69382692b 100644
--- a/drivers/md/dm-log-userspace-base.c
+++ b/drivers/md/dm-log-userspace-base.c
@@ -123,7 +123,7 @@ static int userspace_do_request(struct log_c *lc, const char *uuid,
}
static int build_constructor_string(struct dm_target *ti,
- unsigned argc, char **argv,
+ unsigned int argc, char **argv,
char **ctr_str)
{
int i, str_size;
@@ -188,7 +188,7 @@ static void do_flush(struct work_struct *work)
* to the userspace ctr function.
*/
static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
int r = 0;
int str_size;
@@ -792,7 +792,7 @@ static region_t userspace_get_sync_count(struct dm_dirty_log *log)
* Returns: amount of space consumed
*/
static int userspace_status(struct dm_dirty_log *log, status_type_t status_type,
- char *result, unsigned maxlen)
+ char *result, unsigned int maxlen)
{
int r = 0;
char *table_args;
diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c
index fdf8ec304f8d..072559b709ed 100644
--- a/drivers/md/dm-log-userspace-transfer.c
+++ b/drivers/md/dm-log-userspace-transfer.c
@@ -142,7 +142,7 @@ static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
fill_pkg(msg, NULL);
else if (msg->len < sizeof(*tfr))
DMERR("Incomplete message received (expected %u, got %u): [%u]",
- (unsigned)sizeof(*tfr), msg->len, msg->seq);
+ (unsigned int)sizeof(*tfr), msg->len, msg->seq);
else
fill_pkg(NULL, tfr);
spin_unlock(&receiving_list_lock);
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index 178e13a5b059..efdfb2e1868a 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -792,10 +792,10 @@ static int normal_end_io(struct dm_target *ti, struct bio *bio,
* INFO format: <logged entries> <highest allocated sector>
*/
static void log_writes_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result,
- unsigned maxlen)
+ unsigned int status_flags, char *result,
+ unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct log_writes_c *lc = ti->private;
switch (type) {
@@ -844,8 +844,8 @@ static int log_writes_iterate_devices(struct dm_target *ti,
* Messages supported:
* mark <mark data> - specify the marked data.
*/
-static int log_writes_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int log_writes_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r = -EINVAL;
struct log_writes_c *lc = ti->private;
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index cf10fa667797..159f2c05dfd3 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -223,7 +223,7 @@ struct log_c {
unsigned int region_count;
region_t sync_count;
- unsigned bitset_uint32_count;
+ unsigned int bitset_uint32_count;
uint32_t *clean_bits;
uint32_t *sync_bits;
uint32_t *recovering_bits; /* FIXME: this seems excessive */
@@ -255,20 +255,20 @@ struct log_c {
* The touched member needs to be updated every time we access
* one of the bitsets.
*/
-static inline int log_test_bit(uint32_t *bs, unsigned bit)
+static inline int log_test_bit(uint32_t *bs, unsigned int bit)
{
return test_bit_le(bit, bs) ? 1 : 0;
}
static inline void log_set_bit(struct log_c *l,
- uint32_t *bs, unsigned bit)
+ uint32_t *bs, unsigned int bit)
{
__set_bit_le(bit, bs);
l->touched_cleaned = 1;
}
static inline void log_clear_bit(struct log_c *l,
- uint32_t *bs, unsigned bit)
+ uint32_t *bs, unsigned int bit)
{
__clear_bit_le(bit, bs);
l->touched_dirtied = 1;
@@ -582,7 +582,7 @@ static void fail_log_device(struct log_c *lc)
static int disk_resume(struct dm_dirty_log *log)
{
int r;
- unsigned i;
+ unsigned int i;
struct log_c *lc = (struct log_c *) log->context;
size_t size = lc->bitset_uint32_count * sizeof(uint32_t);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 0e325469a252..91c25ad8eed8 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -29,7 +29,7 @@
#define DM_MSG_PREFIX "multipath"
#define DM_PG_INIT_DELAY_MSECS 2000
-#define DM_PG_INIT_DELAY_DEFAULT ((unsigned) -1)
+#define DM_PG_INIT_DELAY_DEFAULT ((unsigned int) -1)
#define QUEUE_IF_NO_PATH_TIMEOUT_DEFAULT 0
static unsigned long queue_if_no_path_timeout_secs = QUEUE_IF_NO_PATH_TIMEOUT_DEFAULT;
@@ -39,7 +39,7 @@ struct pgpath {
struct list_head list;
struct priority_group *pg; /* Owning PG */
- unsigned fail_count; /* Cumulative failure count */
+ unsigned int fail_count; /* Cumulative failure count */
struct dm_path path;
struct delayed_work activate_path;
@@ -59,8 +59,8 @@ struct priority_group {
struct multipath *m; /* Owning multipath instance */
struct path_selector ps;
- unsigned pg_num; /* Reference number */
- unsigned nr_pgpaths; /* Number of paths in PG */
+ unsigned int pg_num; /* Reference number */
+ unsigned int nr_pgpaths; /* Number of paths in PG */
struct list_head pgpaths;
bool bypassed:1; /* Temporarily bypass this PG? */
@@ -78,14 +78,14 @@ struct multipath {
struct priority_group *next_pg; /* Switch to this PG if set */
atomic_t nr_valid_paths; /* Total number of usable paths */
- unsigned nr_priority_groups;
+ unsigned int nr_priority_groups;
struct list_head priority_groups;
const char *hw_handler_name;
char *hw_handler_params;
wait_queue_head_t pg_init_wait; /* Wait for pg_init completion */
- unsigned pg_init_retries; /* Number of times to retry pg_init */
- unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */
+ unsigned int pg_init_retries; /* Number of times to retry pg_init */
+ unsigned int pg_init_delay_msecs; /* Number of msecs before pg_init retry */
atomic_t pg_init_in_progress; /* Only one pg_init allowed at once */
atomic_t pg_init_count; /* Number of times pg_init called */
@@ -397,7 +397,7 @@ static struct pgpath *choose_pgpath(struct multipath *m, size_t nr_bytes)
unsigned long flags;
struct priority_group *pg;
struct pgpath *pgpath;
- unsigned bypassed = 1;
+ unsigned int bypassed = 1;
if (!atomic_read(&m->nr_valid_paths)) {
spin_lock_irqsave(&m->lock, flags);
@@ -840,7 +840,7 @@ static int parse_path_selector(struct dm_arg_set *as, struct priority_group *pg,
{
int r;
struct path_selector_type *pst;
- unsigned ps_argc;
+ unsigned int ps_argc;
static const struct dm_arg _args[] = {
{0, 1024, "invalid number of path selector args"},
@@ -983,7 +983,7 @@ static struct priority_group *parse_priority_group(struct dm_arg_set *as,
};
int r;
- unsigned i, nr_selector_args, nr_args;
+ unsigned int i, nr_selector_args, nr_args;
struct priority_group *pg;
struct dm_target *ti = m->ti;
@@ -1049,7 +1049,7 @@ static struct priority_group *parse_priority_group(struct dm_arg_set *as,
static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m)
{
- unsigned hw_argc;
+ unsigned int hw_argc;
int ret;
struct dm_target *ti = m->ti;
@@ -1101,7 +1101,7 @@ static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m)
static int parse_features(struct dm_arg_set *as, struct multipath *m)
{
int r;
- unsigned argc;
+ unsigned int argc;
struct dm_target *ti = m->ti;
const char *arg_name;
@@ -1170,7 +1170,7 @@ static int parse_features(struct dm_arg_set *as, struct multipath *m)
return r;
}
-static int multipath_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int multipath_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
/* target arguments */
static const struct dm_arg _args[] = {
@@ -1181,8 +1181,8 @@ static int multipath_ctr(struct dm_target *ti, unsigned argc, char **argv)
int r;
struct multipath *m;
struct dm_arg_set as;
- unsigned pg_count = 0;
- unsigned next_pg_num;
+ unsigned int pg_count = 0;
+ unsigned int next_pg_num;
unsigned long flags;
as.argc = argc;
@@ -1224,7 +1224,7 @@ static int multipath_ctr(struct dm_target *ti, unsigned argc, char **argv)
/* parse the priority groups */
while (as.argc) {
struct priority_group *pg;
- unsigned nr_valid_paths = atomic_read(&m->nr_valid_paths);
+ unsigned int nr_valid_paths = atomic_read(&m->nr_valid_paths);
pg = parse_priority_group(&as, m);
if (IS_ERR(pg)) {
@@ -1365,7 +1365,7 @@ static int reinstate_path(struct pgpath *pgpath)
int r = 0, run_queue = 0;
unsigned long flags;
struct multipath *m = pgpath->pg->m;
- unsigned nr_valid_paths;
+ unsigned int nr_valid_paths;
spin_lock_irqsave(&m->lock, flags);
@@ -1454,7 +1454,7 @@ static void bypass_pg(struct multipath *m, struct priority_group *pg,
static int switch_pg_num(struct multipath *m, const char *pgstr)
{
struct priority_group *pg;
- unsigned pgnum;
+ unsigned int pgnum;
unsigned long flags;
char dummy;
@@ -1487,7 +1487,7 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
static int bypass_pg_num(struct multipath *m, const char *pgstr, bool bypassed)
{
struct priority_group *pg;
- unsigned pgnum;
+ unsigned int pgnum;
char dummy;
if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
@@ -1789,14 +1789,14 @@ static void multipath_resume(struct dm_target *ti)
* num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
*/
static void multipath_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int sz = 0, pg_counter, pgpath_counter;
unsigned long flags;
struct multipath *m = ti->private;
struct priority_group *pg;
struct pgpath *p;
- unsigned pg_num;
+ unsigned int pg_num;
char state;
spin_lock_irqsave(&m->lock, flags);
@@ -1948,8 +1948,8 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
spin_unlock_irqrestore(&m->lock, flags);
}
-static int multipath_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int multipath_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r = -EINVAL;
struct dm_dev *dev;
diff --git a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h
index e230f7196259..5343698fe5f1 100644
--- a/drivers/md/dm-mpath.h
+++ b/drivers/md/dm-mpath.h
@@ -17,6 +17,6 @@ struct dm_path {
};
/* Callback for hwh_pg_init_fn to use when complete */
-void dm_pg_init_complete(struct dm_path *path, unsigned err_flags);
+void dm_pg_init_complete(struct dm_path *path, unsigned int err_flags);
#endif
diff --git a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h
index 83cac2b04b66..0f2b37af8766 100644
--- a/drivers/md/dm-path-selector.h
+++ b/drivers/md/dm-path-selector.h
@@ -52,7 +52,7 @@ struct path_selector_type {
/*
* Constructs a path selector object, takes custom arguments
*/
- int (*create) (struct path_selector *ps, unsigned argc, char **argv);
+ int (*create) (struct path_selector *ps, unsigned int argc, char **argv);
void (*destroy) (struct path_selector *ps);
/*
diff --git a/drivers/md/dm-ps-io-affinity.c b/drivers/md/dm-ps-io-affinity.c
index f74501e65a8e..76ce4ce87222 100644
--- a/drivers/md/dm-ps-io-affinity.c
+++ b/drivers/md/dm-ps-io-affinity.c
@@ -108,7 +108,7 @@ static int ioa_add_path(struct path_selector *ps, struct dm_path *path,
return ret;
}
-static int ioa_create(struct path_selector *ps, unsigned argc, char **argv)
+static int ioa_create(struct path_selector *ps, unsigned int argc, char **argv)
{
struct selector *s;
@@ -138,7 +138,7 @@ static int ioa_create(struct path_selector *ps, unsigned argc, char **argv)
static void ioa_destroy(struct path_selector *ps)
{
struct selector *s = ps->context;
- unsigned cpu;
+ unsigned int cpu;
for_each_cpu(cpu, s->path_mask)
ioa_free_path(s, cpu);
diff --git a/drivers/md/dm-ps-queue-length.c b/drivers/md/dm-ps-queue-length.c
index cef70657bbbc..6fbec9fc242d 100644
--- a/drivers/md/dm-ps-queue-length.c
+++ b/drivers/md/dm-ps-queue-length.c
@@ -35,7 +35,7 @@ struct selector {
struct path_info {
struct list_head list;
struct dm_path *path;
- unsigned repeat_count;
+ unsigned int repeat_count;
atomic_t qlen; /* the number of in-flight I/Os */
};
@@ -52,7 +52,7 @@ static struct selector *alloc_selector(void)
return s;
}
-static int ql_create(struct path_selector *ps, unsigned argc, char **argv)
+static int ql_create(struct path_selector *ps, unsigned int argc, char **argv)
{
struct selector *s = alloc_selector();
@@ -84,9 +84,9 @@ static void ql_destroy(struct path_selector *ps)
}
static int ql_status(struct path_selector *ps, struct dm_path *path,
- status_type_t type, char *result, unsigned maxlen)
+ status_type_t type, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct path_info *pi;
/* When called with NULL path, return selector status/args. */
@@ -116,7 +116,7 @@ static int ql_add_path(struct path_selector *ps, struct dm_path *path,
{
struct selector *s = ps->context;
struct path_info *pi;
- unsigned repeat_count = QL_MIN_IO;
+ unsigned int repeat_count = QL_MIN_IO;
char dummy;
unsigned long flags;
diff --git a/drivers/md/dm-ps-round-robin.c b/drivers/md/dm-ps-round-robin.c
index 27f44c5fa04e..1d07392b5ed4 100644
--- a/drivers/md/dm-ps-round-robin.c
+++ b/drivers/md/dm-ps-round-robin.c
@@ -26,7 +26,7 @@
struct path_info {
struct list_head list;
struct dm_path *path;
- unsigned repeat_count;
+ unsigned int repeat_count;
};
static void free_paths(struct list_head *paths)
@@ -62,7 +62,7 @@ static struct selector *alloc_selector(void)
return s;
}
-static int rr_create(struct path_selector *ps, unsigned argc, char **argv)
+static int rr_create(struct path_selector *ps, unsigned int argc, char **argv)
{
struct selector *s;
@@ -119,7 +119,7 @@ static int rr_add_path(struct path_selector *ps, struct dm_path *path,
{
struct selector *s = ps->context;
struct path_info *pi;
- unsigned repeat_count = RR_MIN_IO;
+ unsigned int repeat_count = RR_MIN_IO;
char dummy;
unsigned long flags;
diff --git a/drivers/md/dm-ps-service-time.c b/drivers/md/dm-ps-service-time.c
index 3ec9c33265c5..84d26234dc05 100644
--- a/drivers/md/dm-ps-service-time.c
+++ b/drivers/md/dm-ps-service-time.c
@@ -30,8 +30,8 @@ struct selector {
struct path_info {
struct list_head list;
struct dm_path *path;
- unsigned repeat_count;
- unsigned relative_throughput;
+ unsigned int repeat_count;
+ unsigned int relative_throughput;
atomic_t in_flight_size; /* Total size of in-flight I/Os */
};
@@ -48,7 +48,7 @@ static struct selector *alloc_selector(void)
return s;
}
-static int st_create(struct path_selector *ps, unsigned argc, char **argv)
+static int st_create(struct path_selector *ps, unsigned int argc, char **argv)
{
struct selector *s = alloc_selector();
@@ -80,9 +80,9 @@ static void st_destroy(struct path_selector *ps)
}
static int st_status(struct path_selector *ps, struct dm_path *path,
- status_type_t type, char *result, unsigned maxlen)
+ status_type_t type, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct path_info *pi;
if (!path)
@@ -113,8 +113,8 @@ static int st_add_path(struct path_selector *ps, struct dm_path *path,
{
struct selector *s = ps->context;
struct path_info *pi;
- unsigned repeat_count = ST_MIN_IO;
- unsigned relative_throughput = 1;
+ unsigned int repeat_count = ST_MIN_IO;
+ unsigned int relative_throughput = 1;
char dummy;
unsigned long flags;
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 54263679a7b1..b26c12856b1d 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3712,7 +3712,7 @@ static void raid_status(struct dm_target *ti, status_type_t type,
}
static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
- char *result, unsigned maxlen)
+ char *result, unsigned int maxlen)
{
struct raid_set *rs = ti->private;
struct mddev *mddev = &rs->md;
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 06a38dc32025..8bd7e87d3538 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -82,7 +82,7 @@ struct mirror_set {
struct work_struct trigger_event;
- unsigned nr_mirrors;
+ unsigned int nr_mirrors;
struct mirror mirror[];
};
@@ -327,7 +327,7 @@ static void recovery_complete(int read_err, unsigned long write_err,
static void recover(struct mirror_set *ms, struct dm_region *reg)
{
- unsigned i;
+ unsigned int i;
struct dm_io_region from, to[DM_KCOPYD_MAX_REGIONS], *dest;
struct mirror *m;
unsigned long flags = 0;
@@ -593,7 +593,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
static void write_callback(unsigned long error, void *context)
{
- unsigned i;
+ unsigned int i;
struct bio *bio = (struct bio *) context;
struct mirror_set *ms;
int should_wake = 0;
@@ -963,10 +963,10 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
* Create dirty log: log_type #log_params <log_params>
*/
static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
- unsigned argc, char **argv,
- unsigned *args_used)
+ unsigned int argc, char **argv,
+ unsigned int *args_used)
{
- unsigned param_count;
+ unsigned int param_count;
struct dm_dirty_log *dl;
char dummy;
@@ -997,10 +997,10 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
return dl;
}
-static int parse_features(struct mirror_set *ms, unsigned argc, char **argv,
- unsigned *args_used)
+static int parse_features(struct mirror_set *ms, unsigned int argc, char **argv,
+ unsigned int *args_used)
{
- unsigned num_features;
+ unsigned int num_features;
struct dm_target *ti = ms->ti;
char dummy;
int i;
@@ -1389,7 +1389,7 @@ static char device_status_char(struct mirror *m)
static void mirror_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
unsigned int m, sz = 0;
int num_feature_args = 0;
@@ -1458,7 +1458,7 @@ static int mirror_iterate_devices(struct dm_target *ti,
{
struct mirror_set *ms = ti->private;
int ret = 0;
- unsigned i;
+ unsigned int i;
for (i = 0; !ret && i < ms->nr_mirrors; i++)
ret = fn(ti, ms->mirror[i].dev,
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index 1f760451e6f4..adbdb4b67137 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -56,17 +56,17 @@
*---------------------------------------------------------------*/
struct dm_region_hash {
uint32_t region_size;
- unsigned region_shift;
+ unsigned int region_shift;
/* holds persistent region state */
struct dm_dirty_log *log;
/* hash table */
rwlock_t hash_lock;
- unsigned mask;
- unsigned nr_buckets;
- unsigned prime;
- unsigned shift;
+ unsigned int mask;
+ unsigned int nr_buckets;
+ unsigned int prime;
+ unsigned int shift;
struct list_head *buckets;
/*
@@ -74,7 +74,7 @@ struct dm_region_hash {
*/
int flush_failure;
- unsigned max_recovery; /* Max # of regions to recover in parallel */
+ unsigned int max_recovery; /* Max # of regions to recover in parallel */
spinlock_t region_lock;
atomic_t recovery_in_flight;
@@ -163,12 +163,12 @@ struct dm_region_hash *dm_region_hash_create(
struct bio_list *bios),
void (*wakeup_workers)(void *context),
void (*wakeup_all_recovery_waiters)(void *context),
- sector_t target_begin, unsigned max_recovery,
+ sector_t target_begin, unsigned int max_recovery,
struct dm_dirty_log *log, uint32_t region_size,
region_t nr_regions)
{
struct dm_region_hash *rh;
- unsigned nr_buckets, max_buckets;
+ unsigned int nr_buckets, max_buckets;
size_t i;
int ret;
@@ -236,7 +236,7 @@ EXPORT_SYMBOL_GPL(dm_region_hash_create);
void dm_region_hash_destroy(struct dm_region_hash *rh)
{
- unsigned h;
+ unsigned int h;
struct dm_region *reg, *nreg;
BUG_ON(!list_empty(&rh->quiesced_regions));
@@ -263,9 +263,9 @@ struct dm_dirty_log *dm_rh_dirty_log(struct dm_region_hash *rh)
}
EXPORT_SYMBOL_GPL(dm_rh_dirty_log);
-static unsigned rh_hash(struct dm_region_hash *rh, region_t region)
+static unsigned int rh_hash(struct dm_region_hash *rh, region_t region)
{
- return (unsigned) ((region * rh->prime) >> rh->shift) & rh->mask;
+ return (unsigned int) ((region * rh->prime) >> rh->shift) & rh->mask;
}
static struct dm_region *__rh_lookup(struct dm_region_hash *rh, region_t region)
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index a41209a43506..80f46e01bca4 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -23,33 +23,33 @@ struct dm_rq_target_io {
union map_info info;
struct dm_stats_aux stats_aux;
unsigned long duration_jiffies;
- unsigned n_sectors;
- unsigned completed;
+ unsigned int n_sectors;
+ unsigned int completed;
};
#define DM_MQ_NR_HW_QUEUES 1
#define DM_MQ_QUEUE_DEPTH 2048
-static unsigned dm_mq_nr_hw_queues = DM_MQ_NR_HW_QUEUES;
-static unsigned dm_mq_queue_depth = DM_MQ_QUEUE_DEPTH;
+static unsigned int dm_mq_nr_hw_queues = DM_MQ_NR_HW_QUEUES;
+static unsigned int dm_mq_queue_depth = DM_MQ_QUEUE_DEPTH;
/*
* Request-based DM's mempools' reserved IOs set by the user.
*/
#define RESERVED_REQUEST_BASED_IOS 256
-static unsigned reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS;
+static unsigned int reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS;
-unsigned dm_get_reserved_rq_based_ios(void)
+unsigned int dm_get_reserved_rq_based_ios(void)
{
return __dm_get_module_param(&reserved_rq_based_ios,
RESERVED_REQUEST_BASED_IOS, DM_RESERVED_MAX_IOS);
}
-static unsigned dm_get_blk_mq_nr_hw_queues(void)
+static unsigned int dm_get_blk_mq_nr_hw_queues(void)
{
return __dm_get_module_param(&dm_mq_nr_hw_queues, 1, 32);
}
-static unsigned dm_get_blk_mq_queue_depth(void)
+static unsigned int dm_get_blk_mq_queue_depth(void)
{
return __dm_get_module_param(&dm_mq_queue_depth,
DM_MQ_QUEUE_DEPTH, BLK_MQ_MAX_DEPTH);
diff --git a/drivers/md/dm-rq.h b/drivers/md/dm-rq.h
index 1eea0da641db..2c97ad145140 100644
--- a/drivers/md/dm-rq.h
+++ b/drivers/md/dm-rq.h
@@ -38,7 +38,7 @@ void dm_stop_queue(struct request_queue *q);
void dm_mq_kick_requeue_list(struct mapped_device *md);
-unsigned dm_get_reserved_rq_based_ios(void);
+unsigned int dm_get_reserved_rq_based_ios(void);
ssize_t dm_attr_rq_based_seq_io_merge_deadline_show(struct mapped_device *md, char *buf);
ssize_t dm_attr_rq_based_seq_io_merge_deadline_store(struct mapped_device *md,
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index 680cc05ec654..5176810f5d24 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -303,7 +303,7 @@ static int read_header(struct pstore *ps, int *new_snapshot)
{
int r;
struct disk_header *dh;
- unsigned chunk_size;
+ unsigned int chunk_size;
int chunk_size_supplied = 1;
char *chunk_err;
@@ -895,11 +895,11 @@ static int persistent_ctr(struct dm_exception_store *store, char *options)
return r;
}
-static unsigned persistent_status(struct dm_exception_store *store,
+static unsigned int persistent_status(struct dm_exception_store *store,
status_type_t status, char *result,
- unsigned maxlen)
+ unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
switch (status) {
case STATUSTYPE_INFO:
diff --git a/drivers/md/dm-snap-transient.c b/drivers/md/dm-snap-transient.c
index 0e0ae4c36b37..d83a0565bd10 100644
--- a/drivers/md/dm-snap-transient.c
+++ b/drivers/md/dm-snap-transient.c
@@ -84,11 +84,11 @@ static int transient_ctr(struct dm_exception_store *store, char *options)
return 0;
}
-static unsigned transient_status(struct dm_exception_store *store,
+static unsigned int transient_status(struct dm_exception_store *store,
status_type_t status, char *result,
- unsigned maxlen)
+ unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
switch (status) {
case STATUSTYPE_INFO:
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index d1c2f84d27e3..c64d987c544d 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -41,7 +41,7 @@ static const char dm_snapshot_merge_target_name[] = "snapshot-merge";
struct dm_exception_table {
uint32_t hash_mask;
- unsigned hash_shift;
+ unsigned int hash_shift;
struct hlist_bl_head *table;
};
@@ -106,7 +106,7 @@ struct dm_snapshot {
/* The on disk metadata handler */
struct dm_exception_store *store;
- unsigned in_progress;
+ unsigned int in_progress;
struct wait_queue_head in_progress_wait;
struct dm_kcopyd_client *kcopyd_client;
@@ -161,7 +161,7 @@ struct dm_snapshot {
*/
#define DEFAULT_COW_THRESHOLD 2048
-static unsigned cow_threshold = DEFAULT_COW_THRESHOLD;
+static unsigned int cow_threshold = DEFAULT_COW_THRESHOLD;
module_param_named(snapshot_cow_threshold, cow_threshold, uint, 0644);
MODULE_PARM_DESC(snapshot_cow_threshold, "Maximum number of chunks being copied on write");
@@ -324,7 +324,7 @@ struct origin {
struct dm_origin {
struct dm_dev *dev;
struct dm_target *ti;
- unsigned split_boundary;
+ unsigned int split_boundary;
struct list_head hash_list;
};
@@ -377,7 +377,7 @@ static void exit_origin_hash(void)
kfree(_dm_origins);
}
-static unsigned origin_hash(struct block_device *bdev)
+static unsigned int origin_hash(struct block_device *bdev)
{
return bdev->bd_dev & ORIGIN_MASK;
}
@@ -652,7 +652,7 @@ static void dm_exception_table_unlock(struct dm_exception_table_lock *lock)
}
static int dm_exception_table_init(struct dm_exception_table *et,
- uint32_t size, unsigned hash_shift)
+ uint32_t size, unsigned int hash_shift)
{
unsigned int i;
@@ -850,7 +850,7 @@ static int dm_add_exception(void *context, chunk_t old, chunk_t new)
static uint32_t __minimum_chunk_size(struct origin *o)
{
struct dm_snapshot *snap;
- unsigned chunk_size = rounddown_pow_of_two(UINT_MAX);
+ unsigned int chunk_size = rounddown_pow_of_two(UINT_MAX);
if (o)
list_for_each_entry(snap, &o->snapshots, list)
@@ -1010,7 +1010,7 @@ static int remove_single_exception_chunk(struct dm_snapshot *s)
}
static int origin_write_extent(struct dm_snapshot *merging_snap,
- sector_t sector, unsigned chunk_size);
+ sector_t sector, unsigned int chunk_size);
static void merge_callback(int read_err, unsigned long write_err,
void *context);
@@ -1183,7 +1183,7 @@ static int parse_snapshot_features(struct dm_arg_set *as, struct dm_snapshot *s,
struct dm_target *ti)
{
int r;
- unsigned argc;
+ unsigned int argc;
const char *arg_name;
static const struct dm_arg _args[] = {
@@ -1241,7 +1241,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
int r = -EINVAL;
char *origin_path, *cow_path;
dev_t origin_dev, cow_dev;
- unsigned args_used, num_flush_bios = 1;
+ unsigned int args_used, num_flush_bios = 1;
fmode_t origin_mode = FMODE_READ;
if (argc < 4) {
@@ -2315,11 +2315,11 @@ static void snapshot_merge_resume(struct dm_target *ti)
}
static void snapshot_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct dm_snapshot *snap = ti->private;
- unsigned num_features;
+ unsigned int num_features;
switch (type) {
case STATUSTYPE_INFO:
@@ -2592,7 +2592,7 @@ static int do_origin(struct dm_dev *origin, struct bio *bio, bool limit)
* size must be a multiple of merging_snap's chunk_size.
*/
static int origin_write_extent(struct dm_snapshot *merging_snap,
- sector_t sector, unsigned size)
+ sector_t sector, unsigned int size)
{
int must_wait = 0;
sector_t n;
@@ -2668,7 +2668,7 @@ static void origin_dtr(struct dm_target *ti)
static int origin_map(struct dm_target *ti, struct bio *bio)
{
struct dm_origin *o = ti->private;
- unsigned available_sectors;
+ unsigned int available_sectors;
bio_set_dev(bio, o->dev->bdev);
@@ -2679,7 +2679,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio)
return DM_MAPIO_REMAPPED;
available_sectors = o->split_boundary -
- ((unsigned)bio->bi_iter.bi_sector & (o->split_boundary - 1));
+ ((unsigned int)bio->bi_iter.bi_sector & (o->split_boundary - 1));
if (bio_sectors(bio) > available_sectors)
dm_accept_partial_bio(bio, available_sectors);
@@ -2713,7 +2713,7 @@ static void origin_postsuspend(struct dm_target *ti)
}
static void origin_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct dm_origin *o = ti->private;
diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c
index d12ba9bce145..7eeb3c2a2492 100644
--- a/drivers/md/dm-stats.c
+++ b/drivers/md/dm-stats.c
@@ -42,12 +42,12 @@ struct dm_stat_shared {
struct dm_stat {
struct list_head list_entry;
int id;
- unsigned stat_flags;
+ unsigned int stat_flags;
size_t n_entries;
sector_t start;
sector_t end;
sector_t step;
- unsigned n_histogram_entries;
+ unsigned int n_histogram_entries;
unsigned long long *histogram_boundaries;
const char *program_id;
const char *aux_data;
@@ -63,7 +63,7 @@ struct dm_stat {
struct dm_stats_last_position {
sector_t last_sector;
- unsigned last_rw;
+ unsigned int last_rw;
};
/*
@@ -255,8 +255,8 @@ static void dm_stats_recalc_precise_timestamps(struct dm_stats *stats)
}
static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end,
- sector_t step, unsigned stat_flags,
- unsigned n_histogram_entries,
+ sector_t step, unsigned int stat_flags,
+ unsigned int n_histogram_entries,
unsigned long long *histogram_boundaries,
const char *program_id, const char *aux_data,
void (*suspend_callback)(struct mapped_device *),
@@ -475,11 +475,11 @@ static int dm_stats_delete(struct dm_stats *stats, int id)
}
static int dm_stats_list(struct dm_stats *stats, const char *program,
- char *result, unsigned maxlen)
+ char *result, unsigned int maxlen)
{
struct dm_stat *s;
sector_t len;
- unsigned sz = 0;
+ unsigned int sz = 0;
/*
* Output format:
@@ -499,7 +499,7 @@ static int dm_stats_list(struct dm_stats *stats, const char *program,
if (s->stat_flags & STAT_PRECISE_TIMESTAMPS)
DMEMIT(" precise_timestamps");
if (s->n_histogram_entries) {
- unsigned i;
+ unsigned int i;
DMEMIT(" histogram:");
for (i = 0; i < s->n_histogram_entries; i++) {
if (i)
@@ -523,7 +523,7 @@ static void dm_stat_round(struct dm_stat *s, struct dm_stat_shared *shared,
* This is racy, but so is part_round_stats_single.
*/
unsigned long long now, difference;
- unsigned in_flight_read, in_flight_write;
+ unsigned int in_flight_read, in_flight_write;
if (likely(!(s->stat_flags & STAT_PRECISE_TIMESTAMPS)))
now = jiffies;
@@ -534,8 +534,8 @@ static void dm_stat_round(struct dm_stat *s, struct dm_stat_shared *shared,
if (!difference)
return;
- in_flight_read = (unsigned)atomic_read(&shared->in_flight[READ]);
- in_flight_write = (unsigned)atomic_read(&shared->in_flight[WRITE]);
+ in_flight_read = (unsigned int)atomic_read(&shared->in_flight[READ]);
+ in_flight_write = (unsigned int)atomic_read(&shared->in_flight[WRITE]);
if (in_flight_read)
p->io_ticks[READ] += difference;
if (in_flight_write)
@@ -596,9 +596,9 @@ static void dm_stat_for_entry(struct dm_stat *s, size_t entry,
duration = stats_aux->duration_ns;
}
if (s->n_histogram_entries) {
- unsigned lo = 0, hi = s->n_histogram_entries + 1;
+ unsigned int lo = 0, hi = s->n_histogram_entries + 1;
while (lo + 1 < hi) {
- unsigned mid = (lo + hi) / 2;
+ unsigned int mid = (lo + hi) / 2;
if (s->histogram_boundaries[mid - 1] > duration) {
hi = mid;
} else {
@@ -656,7 +656,7 @@ static void __dm_stat_bio(struct dm_stat *s, int bi_rw,
}
void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
- sector_t bi_sector, unsigned bi_sectors, bool end,
+ sector_t bi_sector, unsigned int bi_sectors, bool end,
unsigned long start_time,
struct dm_stats_aux *stats_aux)
{
@@ -745,7 +745,7 @@ static void __dm_stat_init_temporary_percpu_totals(struct dm_stat_shared *shared
shared->tmp.io_ticks_total += READ_ONCE(p->io_ticks_total);
shared->tmp.time_in_queue += READ_ONCE(p->time_in_queue);
if (s->n_histogram_entries) {
- unsigned i;
+ unsigned int i;
for (i = 0; i < s->n_histogram_entries + 1; i++)
shared->tmp.histogram[i] += READ_ONCE(p->histogram[i]);
}
@@ -779,7 +779,7 @@ static void __dm_stat_clear(struct dm_stat *s, size_t idx_start, size_t idx_end,
p->time_in_queue -= shared->tmp.time_in_queue;
local_irq_enable();
if (s->n_histogram_entries) {
- unsigned i;
+ unsigned int i;
for (i = 0; i < s->n_histogram_entries + 1; i++) {
local_irq_disable();
p = &s->stat_percpu[smp_processor_id()][x];
@@ -816,7 +816,7 @@ static int dm_stats_clear(struct dm_stats *stats, int id)
static unsigned long long dm_jiffies_to_msec64(struct dm_stat *s, unsigned long long j)
{
unsigned long long result;
- unsigned mult;
+ unsigned int mult;
if (s->stat_flags & STAT_PRECISE_TIMESTAMPS)
return j;
@@ -836,9 +836,9 @@ static unsigned long long dm_jiffies_to_msec64(struct dm_stat *s, unsigned long
static int dm_stats_print(struct dm_stats *stats, int id,
size_t idx_start, size_t idx_len,
- bool clear, char *result, unsigned maxlen)
+ bool clear, char *result, unsigned int maxlen)
{
- unsigned sz = 0;
+ unsigned int sz = 0;
struct dm_stat *s;
size_t x;
sector_t start, end, step;
@@ -894,7 +894,7 @@ static int dm_stats_print(struct dm_stats *stats, int id,
dm_jiffies_to_msec64(s, shared->tmp.io_ticks[READ]),
dm_jiffies_to_msec64(s, shared->tmp.io_ticks[WRITE]));
if (s->n_histogram_entries) {
- unsigned i;
+ unsigned int i;
for (i = 0; i < s->n_histogram_entries + 1; i++) {
DMEMIT("%s%llu", !i ? " " : ":", shared->tmp.histogram[i]);
}
@@ -943,11 +943,11 @@ static int dm_stats_set_aux(struct dm_stats *stats, int id, const char *aux_data
return 0;
}
-static int parse_histogram(const char *h, unsigned *n_histogram_entries,
+static int parse_histogram(const char *h, unsigned int *n_histogram_entries,
unsigned long long **histogram_boundaries)
{
const char *q;
- unsigned n;
+ unsigned int n;
unsigned long long last;
*n_histogram_entries = 1;
@@ -982,23 +982,23 @@ static int parse_histogram(const char *h, unsigned *n_histogram_entries,
}
static int message_stats_create(struct mapped_device *md,
- unsigned argc, char **argv,
- char *result, unsigned maxlen)
+ unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r;
int id;
char dummy;
unsigned long long start, end, len, step;
- unsigned divisor;
+ unsigned int divisor;
const char *program_id, *aux_data;
- unsigned stat_flags = 0;
+ unsigned int stat_flags = 0;
- unsigned n_histogram_entries = 0;
+ unsigned int n_histogram_entries = 0;
unsigned long long *histogram_boundaries = NULL;
struct dm_arg_set as, as_backup;
const char *a;
- unsigned feature_args;
+ unsigned int feature_args;
/*
* Input format:
@@ -1107,7 +1107,7 @@ static int message_stats_create(struct mapped_device *md,
}
static int message_stats_delete(struct mapped_device *md,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
int id;
char dummy;
@@ -1122,7 +1122,7 @@ static int message_stats_delete(struct mapped_device *md,
}
static int message_stats_clear(struct mapped_device *md,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
int id;
char dummy;
@@ -1137,8 +1137,8 @@ static int message_stats_clear(struct mapped_device *md,
}
static int message_stats_list(struct mapped_device *md,
- unsigned argc, char **argv,
- char *result, unsigned maxlen)
+ unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r;
const char *program = NULL;
@@ -1160,8 +1160,8 @@ static int message_stats_list(struct mapped_device *md,
}
static int message_stats_print(struct mapped_device *md,
- unsigned argc, char **argv, bool clear,
- char *result, unsigned maxlen)
+ unsigned int argc, char **argv, bool clear,
+ char *result, unsigned int maxlen)
{
int id;
char dummy;
@@ -1187,7 +1187,7 @@ static int message_stats_print(struct mapped_device *md,
}
static int message_stats_set_aux(struct mapped_device *md,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
int id;
char dummy;
@@ -1201,8 +1201,8 @@ static int message_stats_set_aux(struct mapped_device *md,
return dm_stats_set_aux(dm_get_stats(md), id, argv[2]);
}
-int dm_stats_message(struct mapped_device *md, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+int dm_stats_message(struct mapped_device *md, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r;
diff --git a/drivers/md/dm-stats.h b/drivers/md/dm-stats.h
index ee32b099f1cf..c6728c8b4159 100644
--- a/drivers/md/dm-stats.h
+++ b/drivers/md/dm-stats.h
@@ -26,11 +26,11 @@ void dm_stats_cleanup(struct dm_stats *st);
struct mapped_device;
-int dm_stats_message(struct mapped_device *md, unsigned argc, char **argv,
- char *result, unsigned maxlen);
+int dm_stats_message(struct mapped_device *md, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen);
void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw,
- sector_t bi_sector, unsigned bi_sectors, bool end,
+ sector_t bi_sector, unsigned int bi_sectors, bool end,
unsigned long start_time,
struct dm_stats_aux *aux);
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index baa085cc67bd..a81ed080730a 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -273,7 +273,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio)
{
struct stripe_c *sc = ti->private;
uint32_t stripe;
- unsigned target_bio_nr;
+ unsigned int target_bio_nr;
if (bio->bi_opf & REQ_PREFLUSH) {
target_bio_nr = dm_bio_get_target_bio_nr(bio);
@@ -359,7 +359,7 @@ static size_t stripe_dax_recovery_write(struct dm_target *ti, pgoff_t pgoff,
*/
static void stripe_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct stripe_c *sc = (struct stripe_c *) ti->private;
unsigned int sz = 0;
@@ -406,7 +406,7 @@ static void stripe_status(struct dm_target *ti, status_type_t type,
static int stripe_end_io(struct dm_target *ti, struct bio *bio,
blk_status_t *error)
{
- unsigned i;
+ unsigned int i;
char major_minor[16];
struct stripe_c *sc = ti->private;
@@ -444,7 +444,7 @@ static int stripe_iterate_devices(struct dm_target *ti,
{
struct stripe_c *sc = ti->private;
int ret = 0;
- unsigned i = 0;
+ unsigned int i = 0;
do {
ret = fn(ti, sc->stripe[i].dev,
@@ -459,7 +459,7 @@ static void stripe_io_hints(struct dm_target *ti,
struct queue_limits *limits)
{
struct stripe_c *sc = ti->private;
- unsigned chunk_size = sc->chunk_size << SECTOR_SHIFT;
+ unsigned int chunk_size = sc->chunk_size << SECTOR_SHIFT;
blk_limits_io_min(limits, chunk_size);
blk_limits_io_opt(limits, chunk_size * sc->stripes);
diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c
index 534dc2ca8bb0..f734b5a09744 100644
--- a/drivers/md/dm-switch.c
+++ b/drivers/md/dm-switch.c
@@ -38,9 +38,9 @@ struct switch_path {
struct switch_ctx {
struct dm_target *ti;
- unsigned nr_paths; /* Number of paths in path_list. */
+ unsigned int nr_paths; /* Number of paths in path_list. */
- unsigned region_size; /* Region size in 512-byte sectors */
+ unsigned int region_size; /* Region size in 512-byte sectors */
unsigned long nr_regions; /* Number of regions making up the device */
signed char region_size_bits; /* log2 of region_size or -1 */
@@ -56,8 +56,8 @@ struct switch_ctx {
struct switch_path path_list[];
};
-static struct switch_ctx *alloc_switch_ctx(struct dm_target *ti, unsigned nr_paths,
- unsigned region_size)
+static struct switch_ctx *alloc_switch_ctx(struct dm_target *ti, unsigned int nr_paths,
+ unsigned int region_size)
{
struct switch_ctx *sctx;
@@ -73,7 +73,7 @@ static struct switch_ctx *alloc_switch_ctx(struct dm_target *ti, unsigned nr_pat
return sctx;
}
-static int alloc_region_table(struct dm_target *ti, unsigned nr_paths)
+static int alloc_region_table(struct dm_target *ti, unsigned int nr_paths)
{
struct switch_ctx *sctx = ti->private;
sector_t nr_regions = ti->len;
@@ -124,7 +124,7 @@ static int alloc_region_table(struct dm_target *ti, unsigned nr_paths)
}
static void switch_get_position(struct switch_ctx *sctx, unsigned long region_nr,
- unsigned long *region_index, unsigned *bit)
+ unsigned long *region_index, unsigned int *bit)
{
if (sctx->region_entries_per_slot_bits >= 0) {
*region_index = region_nr >> sctx->region_entries_per_slot_bits;
@@ -137,10 +137,10 @@ static void switch_get_position(struct switch_ctx *sctx, unsigned long region_nr
*bit *= sctx->region_table_entry_bits;
}
-static unsigned switch_region_table_read(struct switch_ctx *sctx, unsigned long region_nr)
+static unsigned int switch_region_table_read(struct switch_ctx *sctx, unsigned long region_nr)
{
unsigned long region_index;
- unsigned bit;
+ unsigned int bit;
switch_get_position(sctx, region_nr, ®ion_index, &bit);
@@ -151,9 +151,9 @@ static unsigned switch_region_table_read(struct switch_ctx *sctx, unsigned long
/*
* Find which path to use at given offset.
*/
-static unsigned switch_get_path_nr(struct switch_ctx *sctx, sector_t offset)
+static unsigned int switch_get_path_nr(struct switch_ctx *sctx, sector_t offset)
{
- unsigned path_nr;
+ unsigned int path_nr;
sector_t p;
p = offset;
@@ -172,10 +172,10 @@ static unsigned switch_get_path_nr(struct switch_ctx *sctx, sector_t offset)
}
static void switch_region_table_write(struct switch_ctx *sctx, unsigned long region_nr,
- unsigned value)
+ unsigned int value)
{
unsigned long region_index;
- unsigned bit;
+ unsigned int bit;
region_table_slot_t pte;
switch_get_position(sctx, region_nr, ®ion_index, &bit);
@@ -191,7 +191,7 @@ static void switch_region_table_write(struct switch_ctx *sctx, unsigned long reg
*/
static void initialise_region_table(struct switch_ctx *sctx)
{
- unsigned path_nr = 0;
+ unsigned int path_nr = 0;
unsigned long region_nr;
for (region_nr = 0; region_nr < sctx->nr_regions; region_nr++) {
@@ -249,7 +249,7 @@ static void switch_dtr(struct dm_target *ti)
* Optional args are to allow for future extension: currently this
* parameter must be 0.
*/
-static int switch_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int switch_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
static const struct dm_arg _args[] = {
{1, (KMALLOC_MAX_SIZE - sizeof(struct switch_ctx)) / sizeof(struct switch_path), "Invalid number of paths"},
@@ -259,7 +259,7 @@ static int switch_ctr(struct dm_target *ti, unsigned argc, char **argv)
struct switch_ctx *sctx;
struct dm_arg_set as;
- unsigned nr_paths, region_size, nr_optional_args;
+ unsigned int nr_paths, region_size, nr_optional_args;
int r;
as.argc = argc;
@@ -320,7 +320,7 @@ static int switch_map(struct dm_target *ti, struct bio *bio)
{
struct switch_ctx *sctx = ti->private;
sector_t offset = dm_target_offset(ti, bio->bi_iter.bi_sector);
- unsigned path_nr = switch_get_path_nr(sctx, offset);
+ unsigned int path_nr = switch_get_path_nr(sctx, offset);
bio_set_dev(bio, sctx->path_list[path_nr].dmdev->bdev);
bio->bi_iter.bi_sector = sctx->path_list[path_nr].start + offset;
@@ -371,9 +371,9 @@ static __always_inline unsigned long parse_hex(const char **string)
}
static int process_set_region_mappings(struct switch_ctx *sctx,
- unsigned argc, char **argv)
+ unsigned int argc, char **argv)
{
- unsigned i;
+ unsigned int i;
unsigned long region_index = 0;
for (i = 1; i < argc; i++) {
@@ -466,8 +466,8 @@ static int process_set_region_mappings(struct switch_ctx *sctx,
*
* Only set_region_mappings is supported.
*/
-static int switch_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int switch_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
static DEFINE_MUTEX(message_mutex);
@@ -487,10 +487,10 @@ static int switch_message(struct dm_target *ti, unsigned argc, char **argv,
}
static void switch_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct switch_ctx *sctx = ti->private;
- unsigned sz = 0;
+ unsigned int sz = 0;
int path_nr;
switch (type) {
@@ -519,7 +519,7 @@ static void switch_status(struct dm_target *ti, status_type_t type,
static int switch_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
{
struct switch_ctx *sctx = ti->private;
- unsigned path_nr;
+ unsigned int path_nr;
path_nr = switch_get_path_nr(sctx, 0);
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 078da18bb86d..32b2d3b99d78 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -126,7 +126,7 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
}
int dm_table_create(struct dm_table **result, fmode_t mode,
- unsigned num_targets, struct mapped_device *md)
+ unsigned int num_targets, struct mapped_device *md)
{
struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
@@ -470,10 +470,10 @@ static int adjoin(struct dm_table *t, struct dm_target *ti)
* On the other hand, dm-switch needs to process bulk data using messages and
* excessive use of GFP_NOIO could cause trouble.
*/
-static char **realloc_argv(unsigned *size, char **old_argv)
+static char **realloc_argv(unsigned int *size, char **old_argv)
{
char **argv;
- unsigned new_size;
+ unsigned int new_size;
gfp_t gfp;
if (*size) {
@@ -499,7 +499,7 @@ static char **realloc_argv(unsigned *size, char **old_argv)
int dm_split_args(int *argc, char ***argvp, char *input)
{
char *start, *end = input, *out, **argv = NULL;
- unsigned array_size = 0;
+ unsigned int array_size = 0;
*argc = 0;
@@ -732,9 +732,8 @@ int dm_table_add_target(struct dm_table *t, const char *type,
/*
* Target argument parsing helpers.
*/
-static int validate_next_arg(const struct dm_arg *arg,
- struct dm_arg_set *arg_set,
- unsigned *value, char **error, unsigned grouped)
+static int validate_next_arg(const struct dm_arg *arg, struct dm_arg_set *arg_set,
+ unsigned int *value, char **error, unsigned int grouped)
{
const char *arg_str = dm_shift_arg(arg_set);
char dummy;
@@ -752,14 +751,14 @@ static int validate_next_arg(const struct dm_arg *arg,
}
int dm_read_arg(const struct dm_arg *arg, struct dm_arg_set *arg_set,
- unsigned *value, char **error)
+ unsigned int *value, char **error)
{
return validate_next_arg(arg, arg_set, value, error, 0);
}
EXPORT_SYMBOL(dm_read_arg);
int dm_read_arg_group(const struct dm_arg *arg, struct dm_arg_set *arg_set,
- unsigned *value, char **error)
+ unsigned int *value, char **error)
{
return validate_next_arg(arg, arg_set, value, error, 1);
}
@@ -780,7 +779,7 @@ const char *dm_shift_arg(struct dm_arg_set *as)
}
EXPORT_SYMBOL(dm_shift_arg);
-void dm_consume_args(struct dm_arg_set *as, unsigned num_args)
+void dm_consume_args(struct dm_arg_set *as, unsigned int num_args)
{
BUG_ON(as->argc < num_args);
as->argc -= num_args;
@@ -856,7 +855,7 @@ static int device_is_rq_stackable(struct dm_target *ti, struct dm_dev *dev,
static int dm_table_determine_type(struct dm_table *t)
{
- unsigned bio_based = 0, request_based = 0, hybrid = 0;
+ unsigned int bio_based = 0, request_based = 0, hybrid = 0;
struct dm_target *ti;
struct list_head *devices = dm_table_get_devices(t);
enum dm_queue_mode live_md_type = dm_get_md_type(t->md);
@@ -1535,7 +1534,7 @@ static bool dm_table_any_dev_attr(struct dm_table *t,
static int count_device(struct dm_target *ti, struct dm_dev *dev,
sector_t start, sector_t len, void *data)
{
- unsigned *num_devices = data;
+ unsigned int *num_devices = data;
(*num_devices)++;
@@ -1565,7 +1564,7 @@ bool dm_table_has_no_data_devices(struct dm_table *t)
{
for (unsigned int i = 0; i < t->num_targets; i++) {
struct dm_target *ti = dm_table_get_target(t, i);
- unsigned num_devices = 0;
+ unsigned int num_devices = 0;
if (!ti->type->iterate_devices)
return false;
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 6bcc4c4786d8..80545ec54121 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -318,12 +318,12 @@ static void unpack_block_time(uint64_t v, dm_block_t *b, uint32_t *t)
*/
typedef int (*run_fn)(struct dm_space_map *, dm_block_t, dm_block_t);
-static void with_runs(struct dm_space_map *sm, const __le64 *value_le, unsigned count, run_fn fn)
+static void with_runs(struct dm_space_map *sm, const __le64 *value_le, unsigned int count, run_fn fn)
{
uint64_t b, begin, end;
uint32_t t;
bool in_run = false;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, value_le++) {
/* We know value_le is 8 byte aligned */
@@ -348,13 +348,13 @@ static void with_runs(struct dm_space_map *sm, const __le64 *value_le, unsigned
fn(sm, begin, end);
}
-static void data_block_inc(void *context, const void *value_le, unsigned count)
+static void data_block_inc(void *context, const void *value_le, unsigned int count)
{
with_runs((struct dm_space_map *) context,
(const __le64 *) value_le, count, dm_sm_inc_blocks);
}
-static void data_block_dec(void *context, const void *value_le, unsigned count)
+static void data_block_dec(void *context, const void *value_le, unsigned int count)
{
with_runs((struct dm_space_map *) context,
(const __le64 *) value_le, count, dm_sm_dec_blocks);
@@ -374,21 +374,21 @@ static int data_block_equal(void *context, const void *value1_le, const void *va
return b1 == b2;
}
-static void subtree_inc(void *context, const void *value, unsigned count)
+static void subtree_inc(void *context, const void *value, unsigned int count)
{
struct dm_btree_info *info = context;
const __le64 *root_le = value;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, root_le++)
dm_tm_inc(info->tm, le64_to_cpu(*root_le));
}
-static void subtree_dec(void *context, const void *value, unsigned count)
+static void subtree_dec(void *context, const void *value, unsigned int count)
{
struct dm_btree_info *info = context;
const __le64 *root_le = value;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, root_le++)
if (dm_btree_del(info, le64_to_cpu(*root_le)))
@@ -448,10 +448,10 @@ static int superblock_lock(struct dm_pool_metadata *pmd,
static int __superblock_all_zeroes(struct dm_block_manager *bm, int *result)
{
int r;
- unsigned i;
+ unsigned int i;
struct dm_block *b;
__le64 *data_le, zero = cpu_to_le64(0);
- unsigned block_size = dm_bm_block_size(bm) / sizeof(__le64);
+ unsigned int block_size = dm_bm_block_size(bm) / sizeof(__le64);
/*
* We can't use a validator here - it may be all zeroes.
@@ -971,7 +971,7 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
{
int r;
- unsigned open_devices = 0;
+ unsigned int open_devices = 0;
struct dm_thin_device *td, *tmp;
down_read(&pmd->root_lock);
@@ -1679,7 +1679,7 @@ int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_t end)
{
int r;
- unsigned count, total_count = 0;
+ unsigned int count, total_count = 0;
struct dm_pool_metadata *pmd = td->pmd;
dm_block_t keys[1] = { td->id };
__le64 value;
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 90df6c3da77a..d12aff50974a 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -32,7 +32,7 @@
#define COMMIT_PERIOD HZ
#define NO_SPACE_TIMEOUT_SECS 60
-static unsigned no_space_timeout_secs = NO_SPACE_TIMEOUT_SECS;
+static unsigned int no_space_timeout_secs = NO_SPACE_TIMEOUT_SECS;
DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,
"A percentage of time allocated for copy on write");
@@ -254,7 +254,7 @@ struct pool {
struct delayed_work no_space_timeout;
unsigned long last_commit_jiffies;
- unsigned ref_count;
+ unsigned int ref_count;
spinlock_t lock;
struct bio_list deferred_flush_bios;
@@ -2159,7 +2159,7 @@ static void process_thin_deferred_bios(struct thin_c *tc)
struct bio *bio;
struct bio_list bios;
struct blk_plug plug;
- unsigned count = 0;
+ unsigned int count = 0;
if (tc->requeue_mode) {
error_thin_bio_list(tc, &tc->deferred_bio_list,
@@ -2229,9 +2229,9 @@ static int cmp_cells(const void *lhs, const void *rhs)
return 0;
}
-static unsigned sort_cells(struct pool *pool, struct list_head *cells)
+static unsigned int sort_cells(struct pool *pool, struct list_head *cells)
{
- unsigned count = 0;
+ unsigned int count = 0;
struct dm_bio_prison_cell *cell, *tmp;
list_for_each_entry_safe(cell, tmp, cells, user_list) {
@@ -2252,7 +2252,7 @@ static void process_thin_deferred_cells(struct thin_c *tc)
struct pool *pool = tc->pool;
struct list_head cells;
struct dm_bio_prison_cell *cell;
- unsigned i, j, count;
+ unsigned int i, j, count;
INIT_LIST_HEAD(&cells);
@@ -3115,7 +3115,7 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
struct dm_target *ti)
{
int r;
- unsigned argc;
+ unsigned int argc;
const char *arg_name;
static const struct dm_arg _args[] = {
@@ -3252,7 +3252,7 @@ static dm_block_t calc_metadata_threshold(struct pool_c *pt)
* read_only: Don't allow any changes to be made to the pool metadata.
* error_if_no_space: error IOs, instead of queueing, if no space.
*/
-static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
int r, pool_created = 0;
struct pool_c *pt;
@@ -3648,7 +3648,7 @@ static void pool_postsuspend(struct dm_target *ti)
(void) commit(pool);
}
-static int check_arg_count(unsigned argc, unsigned args_required)
+static int check_arg_count(unsigned int argc, unsigned int args_required)
{
if (argc != args_required) {
DMWARN("Message received with %u arguments instead of %u.",
@@ -3671,7 +3671,7 @@ static int read_dev_id(char *arg, dm_thin_id *dev_id, int warning)
return -EINVAL;
}
-static int process_create_thin_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_create_thin_mesg(unsigned int argc, char **argv, struct pool *pool)
{
dm_thin_id dev_id;
int r;
@@ -3694,7 +3694,7 @@ static int process_create_thin_mesg(unsigned argc, char **argv, struct pool *poo
return 0;
}
-static int process_create_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_create_snap_mesg(unsigned int argc, char **argv, struct pool *pool)
{
dm_thin_id dev_id;
dm_thin_id origin_dev_id;
@@ -3722,7 +3722,7 @@ static int process_create_snap_mesg(unsigned argc, char **argv, struct pool *poo
return 0;
}
-static int process_delete_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_delete_mesg(unsigned int argc, char **argv, struct pool *pool)
{
dm_thin_id dev_id;
int r;
@@ -3742,7 +3742,7 @@ static int process_delete_mesg(unsigned argc, char **argv, struct pool *pool)
return r;
}
-static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_set_transaction_id_mesg(unsigned int argc, char **argv, struct pool *pool)
{
dm_thin_id old_id, new_id;
int r;
@@ -3771,7 +3771,7 @@ static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct po
return 0;
}
-static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_reserve_metadata_snap_mesg(unsigned int argc, char **argv, struct pool *pool)
{
int r;
@@ -3788,7 +3788,7 @@ static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct
return r;
}
-static int process_release_metadata_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+static int process_release_metadata_snap_mesg(unsigned int argc, char **argv, struct pool *pool)
{
int r;
@@ -3812,8 +3812,8 @@ static int process_release_metadata_snap_mesg(unsigned argc, char **argv, struct
* reserve_metadata_snap
* release_metadata_snap
*/
-static int pool_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int pool_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r = -EINVAL;
struct pool_c *pt = ti->private;
@@ -3853,9 +3853,9 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv,
}
static void emit_flags(struct pool_features *pf, char *result,
- unsigned sz, unsigned maxlen)
+ unsigned int sz, unsigned int maxlen)
{
- unsigned count = !pf->zero_new_blocks + !pf->discard_enabled +
+ unsigned int count = !pf->zero_new_blocks + !pf->discard_enabled +
!pf->discard_passdown + (pf->mode == PM_READ_ONLY) +
pf->error_if_no_space;
DMEMIT("%u ", count);
@@ -3883,10 +3883,10 @@ static void emit_flags(struct pool_features *pf, char *result,
* <pool mode> <discard config> <no space config> <needs_check>
*/
static void pool_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int r;
- unsigned sz = 0;
+ unsigned int sz = 0;
uint64_t transaction_id;
dm_block_t nr_free_blocks_data;
dm_block_t nr_free_blocks_metadata;
@@ -4148,7 +4148,7 @@ static void thin_dtr(struct dm_target *ti)
* If the pool device has discards disabled, they get disabled for the thin
* device as well.
*/
-static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int thin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
int r;
struct thin_c *tc;
@@ -4371,7 +4371,7 @@ static int thin_preresume(struct dm_target *ti)
* <nr mapped sectors> <highest mapped sector>
*/
static void thin_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
int r;
ssize_t sz = 0;
diff --git a/drivers/md/dm-uevent.c b/drivers/md/dm-uevent.c
index 8671267200d8..a02b3f6ea47a 100644
--- a/drivers/md/dm-uevent.c
+++ b/drivers/md/dm-uevent.c
@@ -60,7 +60,7 @@ static struct dm_uevent *dm_build_path_uevent(struct mapped_device *md,
enum kobject_action action,
const char *dm_action,
const char *path,
- unsigned nr_valid_paths)
+ unsigned int nr_valid_paths)
{
struct dm_uevent *event;
@@ -168,7 +168,7 @@ EXPORT_SYMBOL_GPL(dm_send_uevents);
*
*/
void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
- const char *path, unsigned nr_valid_paths)
+ const char *path, unsigned int nr_valid_paths)
{
struct mapped_device *md = dm_table_get_md(ti->table);
struct dm_uevent *event;
diff --git a/drivers/md/dm-uevent.h b/drivers/md/dm-uevent.h
index d30d226f2a18..2c9ba561fd8e 100644
--- a/drivers/md/dm-uevent.h
+++ b/drivers/md/dm-uevent.h
@@ -20,7 +20,7 @@ extern void dm_uevent_exit(void);
extern void dm_send_uevents(struct list_head *events, struct kobject *kobj);
extern void dm_path_uevent(enum dm_uevent_type event_type,
struct dm_target *ti, const char *path,
- unsigned nr_valid_paths);
+ unsigned int nr_valid_paths);
#else
@@ -37,7 +37,7 @@ static inline void dm_send_uevents(struct list_head *events,
}
static inline void dm_path_uevent(enum dm_uevent_type event_type,
struct dm_target *ti, const char *path,
- unsigned nr_valid_paths)
+ unsigned int nr_valid_paths)
{
}
diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c
index 23cffce56403..962fc32c947c 100644
--- a/drivers/md/dm-verity-fec.c
+++ b/drivers/md/dm-verity-fec.c
@@ -59,14 +59,14 @@ static int fec_decode_rs8(struct dm_verity *v, struct dm_verity_fec_io *fio,
* to the data block. Caller is responsible for releasing buf.
*/
static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
- unsigned *offset, struct dm_buffer **buf)
+ unsigned int *offset, struct dm_buffer **buf)
{
u64 position, block, rem;
u8 *res;
position = (index + rsb) * v->fec->roots;
block = div64_u64_rem(position, v->fec->io_size, &rem);
- *offset = (unsigned)rem;
+ *offset = (unsigned int)rem;
res = dm_bufio_read(v->fec->bufio, block, buf);
if (IS_ERR(res)) {
@@ -102,7 +102,7 @@ static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
*/
static inline u8 *fec_buffer_rs_block(struct dm_verity *v,
struct dm_verity_fec_io *fio,
- unsigned i, unsigned j)
+ unsigned int i, unsigned int j)
{
return &fio->bufs[i][j * v->fec->rsn];
}
@@ -111,7 +111,7 @@ static inline u8 *fec_buffer_rs_block(struct dm_verity *v,
* Return an index to the current RS block when called inside
* fec_for_each_buffer_rs_block.
*/
-static inline unsigned fec_buffer_rs_index(unsigned i, unsigned j)
+static inline unsigned int fec_buffer_rs_index(unsigned int i, unsigned int j)
{
return (i << DM_VERITY_FEC_BUF_RS_BITS) + j;
}
@@ -121,12 +121,12 @@ static inline unsigned fec_buffer_rs_index(unsigned i, unsigned j)
* starting from block_offset.
*/
static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio,
- u64 rsb, int byte_index, unsigned block_offset,
+ u64 rsb, int byte_index, unsigned int block_offset,
int neras)
{
int r, corrected = 0, res;
struct dm_buffer *buf;
- unsigned n, i, offset;
+ unsigned int n, i, offset;
u8 *par, *block;
par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
@@ -197,7 +197,7 @@ static int fec_is_erasure(struct dm_verity *v, struct dm_verity_io *io,
* fits into buffers. Check for erasure locations if @neras is non-NULL.
*/
static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
- u64 rsb, u64 target, unsigned block_offset,
+ u64 rsb, u64 target, unsigned int block_offset,
int *neras)
{
bool is_zero;
@@ -208,7 +208,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
u64 block, ileaved;
u8 *bbuf, *rs_block;
u8 want_digest[HASH_MAX_DIGESTSIZE];
- unsigned n, k;
+ unsigned int n, k;
if (neras)
*neras = 0;
@@ -304,7 +304,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
*/
static int fec_alloc_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio)
{
- unsigned n;
+ unsigned int n;
if (!fio->rs)
fio->rs = mempool_alloc(&v->fec->rs_pool, GFP_NOIO);
@@ -344,7 +344,7 @@ static int fec_alloc_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio)
*/
static void fec_init_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio)
{
- unsigned n;
+ unsigned int n;
fec_for_each_buffer(fio, n)
memset(fio->bufs[n], 0, v->fec->rsn << DM_VERITY_FEC_BUF_RS_BITS);
@@ -362,7 +362,7 @@ static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io,
bool use_erasures)
{
int r, neras = 0;
- unsigned pos;
+ unsigned int pos;
r = fec_alloc_bufs(v, fio);
if (unlikely(r < 0))
@@ -484,7 +484,7 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
*/
void verity_fec_finish_io(struct dm_verity_io *io)
{
- unsigned n;
+ unsigned int n;
struct dm_verity_fec *f = io->v->fec;
struct dm_verity_fec_io *fio = fec_io(io);
@@ -522,8 +522,8 @@ void verity_fec_init_io(struct dm_verity_io *io)
/*
* Append feature arguments and values to the status table.
*/
-unsigned verity_fec_status_table(struct dm_verity *v, unsigned sz,
- char *result, unsigned maxlen)
+unsigned int verity_fec_status_table(struct dm_verity *v, unsigned int sz,
+ char *result, unsigned int maxlen)
{
if (!verity_fec_is_enabled(v))
return sz;
@@ -589,7 +589,7 @@ bool verity_is_fec_opt_arg(const char *arg_name)
}
int verity_fec_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
- unsigned *argc, const char *arg_name)
+ unsigned int *argc, const char *arg_name)
{
int r;
struct dm_target *ti = v->ti;
diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h
index 3c46c8d61883..8454070d2824 100644
--- a/drivers/md/dm-verity-fec.h
+++ b/drivers/md/dm-verity-fec.h
@@ -55,10 +55,10 @@ struct dm_verity_fec_io {
struct rs_control *rs; /* Reed-Solomon state */
int erasures[DM_VERITY_FEC_MAX_RSN]; /* erasures for decode_rs8 */
u8 *bufs[DM_VERITY_FEC_BUF_MAX]; /* bufs for deinterleaving */
- unsigned nbufs; /* number of buffers allocated */
+ unsigned int nbufs; /* number of buffers allocated */
u8 *output; /* buffer for corrected output */
size_t output_pos;
- unsigned level; /* recursion level */
+ unsigned int level; /* recursion level */
};
#ifdef CONFIG_DM_VERITY_FEC
@@ -72,15 +72,15 @@ extern int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
enum verity_block_type type, sector_t block,
u8 *dest, struct bvec_iter *iter);
-extern unsigned verity_fec_status_table(struct dm_verity *v, unsigned sz,
- char *result, unsigned maxlen);
+extern unsigned int verity_fec_status_table(struct dm_verity *v, unsigned int sz,
+ char *result, unsigned int maxlen);
extern void verity_fec_finish_io(struct dm_verity_io *io);
extern void verity_fec_init_io(struct dm_verity_io *io);
extern bool verity_is_fec_opt_arg(const char *arg_name);
extern int verity_fec_parse_opt_args(struct dm_arg_set *as,
- struct dm_verity *v, unsigned *argc,
+ struct dm_verity *v, unsigned int *argc,
const char *arg_name);
extern void verity_fec_dtr(struct dm_verity *v);
@@ -106,9 +106,9 @@ static inline int verity_fec_decode(struct dm_verity *v,
return -EOPNOTSUPP;
}
-static inline unsigned verity_fec_status_table(struct dm_verity *v,
- unsigned sz, char *result,
- unsigned maxlen)
+static inline unsigned int verity_fec_status_table(struct dm_verity *v,
+ unsigned int sz, char *result,
+ unsigned int maxlen)
{
return sz;
}
@@ -128,7 +128,7 @@ static inline bool verity_is_fec_opt_arg(const char *arg_name)
static inline int verity_fec_parse_opt_args(struct dm_arg_set *as,
struct dm_verity *v,
- unsigned *argc,
+ unsigned int *argc,
const char *arg_name)
{
return -EINVAL;
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index ccf5b852fbf7..64e8ac429984 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -41,7 +41,7 @@
#define DM_VERITY_OPTS_MAX (4 + DM_VERITY_OPTS_FEC + \
DM_VERITY_ROOT_HASH_VERIFICATION_OPTS)
-static unsigned dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE;
+static unsigned int dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE;
module_param_named(prefetch_cluster, dm_verity_prefetch_cluster, uint, S_IRUGO | S_IWUSR);
@@ -51,7 +51,7 @@ struct dm_verity_prefetch_work {
struct work_struct work;
struct dm_verity *v;
sector_t block;
- unsigned n_blocks;
+ unsigned int n_blocks;
};
/*
@@ -196,10 +196,10 @@ int verity_hash(struct dm_verity *v, struct ahash_request *req,
}
static void verity_hash_at_level(struct dm_verity *v, sector_t block, int level,
- sector_t *hash_block, unsigned *offset)
+ sector_t *hash_block, unsigned int *offset)
{
sector_t position = verity_position_at_level(v, block, level);
- unsigned idx;
+ unsigned int idx;
*hash_block = v->hash_level_block[level] + (position >> v->hash_per_block_bits);
@@ -287,7 +287,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
u8 *data;
int r;
sector_t hash_block;
- unsigned offset;
+ unsigned int offset;
verity_hash_at_level(v, block, level, &hash_block, &offset);
@@ -445,13 +445,13 @@ int verity_for_bv_block(struct dm_verity *v, struct dm_verity_io *io,
struct dm_verity_io *io, u8 *data,
size_t len))
{
- unsigned todo = 1 << v->data_dev_block_bits;
+ unsigned int todo = 1 << v->data_dev_block_bits;
struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
do {
int r;
u8 *page;
- unsigned len;
+ unsigned int len;
struct bio_vec bv = bio_iter_iovec(bio, *iter);
page = bvec_kmap_local(&bv);
@@ -688,7 +688,7 @@ static void verity_prefetch_io(struct work_struct *work)
verity_hash_at_level(v, pw->block, i, &hash_block_start, NULL);
verity_hash_at_level(v, pw->block + pw->n_blocks - 1, i, &hash_block_end, NULL);
if (!i) {
- unsigned cluster = READ_ONCE(dm_verity_prefetch_cluster);
+ unsigned int cluster = READ_ONCE(dm_verity_prefetch_cluster);
cluster >>= v->data_dev_block_bits;
if (unlikely(!cluster))
@@ -753,7 +753,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
bio_set_dev(bio, v->data_dev->bdev);
bio->bi_iter.bi_sector = verity_map_sector(v, bio->bi_iter.bi_sector);
- if (((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) &
+ if (((unsigned int)bio->bi_iter.bi_sector | bio_sectors(bio)) &
((1 << (v->data_dev_block_bits - SECTOR_SHIFT)) - 1)) {
DMERR_LIMIT("unaligned io");
return DM_MAPIO_KILL;
@@ -789,12 +789,12 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
* Status: V (valid) or C (corruption found)
*/
static void verity_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct dm_verity *v = ti->private;
- unsigned args = 0;
- unsigned sz = 0;
- unsigned x;
+ unsigned int args = 0;
+ unsigned int sz = 0;
+ unsigned int x;
switch (type) {
case STATUSTYPE_INFO:
@@ -1054,7 +1054,7 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
bool only_modifier_opts)
{
int r = 0;
- unsigned argc;
+ unsigned int argc;
struct dm_target *ti = v->ti;
const char *arg_name;
@@ -1156,7 +1156,7 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
* <digest>
* <salt> Hex string or "-" if no salt.
*/
-static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct dm_verity *v;
struct dm_verity_sig_opts verify_args = {0};
diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h
index 98f306ec6a33..2f555b420367 100644
--- a/drivers/md/dm-verity.h
+++ b/drivers/md/dm-verity.h
@@ -42,7 +42,7 @@ struct dm_verity {
u8 *root_digest; /* digest of the root block */
u8 *salt; /* salt: its size is salt_size */
u8 *zero_digest; /* digest for a zero block */
- unsigned salt_size;
+ unsigned int salt_size;
sector_t data_start; /* data offset in 512-byte sectors */
sector_t hash_start; /* hash start in blocks */
sector_t data_blocks; /* the number of data blocks */
@@ -54,10 +54,10 @@ struct dm_verity {
unsigned char version;
bool hash_failed:1; /* set if hash of any block failed */
bool use_tasklet:1; /* try to verify in tasklet before work-queue */
- unsigned digest_size; /* digest size for the current hash algorithm */
+ unsigned int digest_size; /* digest size for the current hash algorithm */
unsigned int ahash_reqsize;/* the size of temporary space for crypto */
enum verity_mode mode; /* mode for handling verification errors */
- unsigned corrupted_errs;/* Number of errors for corrupted blocks */
+ unsigned int corrupted_errs;/* Number of errors for corrupted blocks */
struct workqueue_struct *verify_wq;
@@ -77,7 +77,7 @@ struct dm_verity_io {
bio_end_io_t *orig_bi_end_io;
sector_t block;
- unsigned n_blocks;
+ unsigned int n_blocks;
bool in_tasklet;
struct bvec_iter iter;
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
index 96a003eb7323..431c84595ddb 100644
--- a/drivers/md/dm-writecache.c
+++ b/drivers/md/dm-writecache.c
@@ -128,9 +128,9 @@ struct dm_writecache {
unsigned long max_age;
unsigned long pause;
- unsigned uncommitted_blocks;
- unsigned autocommit_blocks;
- unsigned max_writeback_jobs;
+ unsigned int uncommitted_blocks;
+ unsigned int autocommit_blocks;
+ unsigned int max_writeback_jobs;
int error;
@@ -155,7 +155,7 @@ struct dm_writecache {
sector_t data_device_sectors;
void *block_start;
struct wc_entry *entries;
- unsigned block_size;
+ unsigned int block_size;
unsigned char block_size_bits;
bool pmem_mode:1;
@@ -178,13 +178,13 @@ struct dm_writecache {
bool metadata_only:1;
bool pause_set:1;
- unsigned high_wm_percent_value;
- unsigned low_wm_percent_value;
- unsigned autocommit_time_value;
- unsigned max_age_value;
- unsigned pause_value;
+ unsigned int high_wm_percent_value;
+ unsigned int low_wm_percent_value;
+ unsigned int autocommit_time_value;
+ unsigned int max_age_value;
+ unsigned int pause_value;
- unsigned writeback_all;
+ unsigned int writeback_all;
struct workqueue_struct *writeback_wq;
struct work_struct writeback_work;
struct work_struct flush_work;
@@ -202,7 +202,7 @@ struct dm_writecache {
struct dm_kcopyd_client *dm_kcopyd;
unsigned long *dirty_bitmap;
- unsigned dirty_bitmap_size;
+ unsigned int dirty_bitmap_size;
struct bio_set bio_set;
mempool_t copy_pool;
@@ -227,7 +227,7 @@ struct writeback_struct {
struct list_head endio_entry;
struct dm_writecache *wc;
struct wc_entry **wc_list;
- unsigned wc_list_n;
+ unsigned int wc_list_n;
struct wc_entry *wc_list_inline[WB_LIST_INLINE];
struct bio bio;
};
@@ -236,7 +236,7 @@ struct copy_struct {
struct list_head endio_entry;
struct dm_writecache *wc;
struct wc_entry *e;
- unsigned n_entries;
+ unsigned int n_entries;
int error;
};
@@ -369,7 +369,7 @@ static struct page *persistent_memory_page(void *addr)
return virt_to_page(addr);
}
-static unsigned persistent_memory_page_offset(void *addr)
+static unsigned int persistent_memory_page_offset(void *addr)
{
return (unsigned long)addr & (PAGE_SIZE - 1);
}
@@ -502,11 +502,11 @@ static void ssd_commit_flushed(struct dm_writecache *wc, bool wait_for_ios)
COMPLETION_INITIALIZER_ONSTACK(endio.c),
ATOMIC_INIT(1),
};
- unsigned bitmap_bits = wc->dirty_bitmap_size * 8;
- unsigned i = 0;
+ unsigned int bitmap_bits = wc->dirty_bitmap_size * 8;
+ unsigned int i = 0;
while (1) {
- unsigned j;
+ unsigned int j;
i = find_next_bit(wc->dirty_bitmap, bitmap_bits, i);
if (unlikely(i == bitmap_bits))
break;
@@ -1100,7 +1100,7 @@ static void writecache_resume(struct dm_target *ti)
wc_unlock(wc);
}
-static int process_flush_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+static int process_flush_mesg(unsigned int argc, char **argv, struct dm_writecache *wc)
{
if (argc != 1)
return -EINVAL;
@@ -1133,7 +1133,7 @@ static int process_flush_mesg(unsigned argc, char **argv, struct dm_writecache *
return 0;
}
-static int process_flush_on_suspend_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+static int process_flush_on_suspend_mesg(unsigned int argc, char **argv, struct dm_writecache *wc)
{
if (argc != 1)
return -EINVAL;
@@ -1153,7 +1153,7 @@ static void activate_cleaner(struct dm_writecache *wc)
wc->freelist_low_watermark = wc->n_blocks;
}
-static int process_cleaner_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+static int process_cleaner_mesg(unsigned int argc, char **argv, struct dm_writecache *wc)
{
if (argc != 1)
return -EINVAL;
@@ -1167,7 +1167,7 @@ static int process_cleaner_mesg(unsigned argc, char **argv, struct dm_writecache
return 0;
}
-static int process_clear_stats_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+static int process_clear_stats_mesg(unsigned int argc, char **argv, struct dm_writecache *wc)
{
if (argc != 1)
return -EINVAL;
@@ -1179,8 +1179,8 @@ static int process_clear_stats_mesg(unsigned argc, char **argv, struct dm_writec
return 0;
}
-static int writecache_message(struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen)
+static int writecache_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
{
int r = -EINVAL;
struct dm_writecache *wc = ti->private;
@@ -1238,9 +1238,9 @@ static void memcpy_flushcache_optimized(void *dest, void *source, size_t size)
static void bio_copy_block(struct dm_writecache *wc, struct bio *bio, void *data)
{
void *buf;
- unsigned size;
+ unsigned int size;
int rw = bio_data_dir(bio);
- unsigned remaining_size = wc->block_size;
+ unsigned int remaining_size = wc->block_size;
do {
struct bio_vec bv = bio_iter_iovec(bio, bio->bi_iter);
@@ -1371,7 +1371,7 @@ static enum wc_map_op writecache_map_read(struct dm_writecache *wc, struct bio *
static void writecache_bio_copy_ssd(struct dm_writecache *wc, struct bio *bio,
struct wc_entry *e, bool search_used)
{
- unsigned bio_size = wc->block_size;
+ unsigned int bio_size = wc->block_size;
sector_t start_cache_sec = cache_sector(wc, e);
sector_t current_cache_sec = start_cache_sec + (bio_size >> SECTOR_SHIFT);
@@ -1540,7 +1540,7 @@ static int writecache_map(struct dm_target *ti, struct bio *bio)
bio->bi_iter.bi_sector = dm_target_offset(ti, bio->bi_iter.bi_sector);
- if (unlikely((((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) &
+ if (unlikely((((unsigned int)bio->bi_iter.bi_sector | bio_sectors(bio)) &
(wc->block_size / 512 - 1)) != 0)) {
DMERR("I/O is not aligned, sector %llu, size %u, block size %u",
(unsigned long long)bio->bi_iter.bi_sector,
@@ -1666,7 +1666,7 @@ static void writecache_copy_endio(int read_err, unsigned long write_err, void *p
static void __writecache_endio_pmem(struct dm_writecache *wc, struct list_head *list)
{
- unsigned i;
+ unsigned int i;
struct writeback_struct *wb;
struct wc_entry *e;
unsigned long n_walked = 0;
@@ -1782,7 +1782,7 @@ static int writecache_endio_thread(void *data)
static bool wc_add_block(struct writeback_struct *wb, struct wc_entry *e)
{
struct dm_writecache *wc = wb->wc;
- unsigned block_size = wc->block_size;
+ unsigned int block_size = wc->block_size;
void *address = memory_data(wc, e);
persistent_memory_flush_cache(address, block_size);
@@ -1817,7 +1817,7 @@ static void __writecache_writeback_pmem(struct dm_writecache *wc, struct writeba
struct wc_entry *e, *f;
struct bio *bio;
struct writeback_struct *wb;
- unsigned max_pages;
+ unsigned int max_pages;
while (wbl->size) {
wbl->size--;
@@ -1880,7 +1880,7 @@ static void __writecache_writeback_ssd(struct dm_writecache *wc, struct writebac
struct copy_struct *c;
while (wbl->size) {
- unsigned n_sectors;
+ unsigned int n_sectors;
wbl->size--;
e = container_of(wbl->list.prev, struct wc_entry, lru);
@@ -2092,7 +2092,7 @@ static void writecache_writeback(struct work_struct *work)
}
}
-static int calculate_memory_size(uint64_t device_size, unsigned block_size,
+static int calculate_memory_size(uint64_t device_size, unsigned int block_size,
size_t *n_blocks_p, size_t *n_metadata_blocks_p)
{
uint64_t n_blocks, offset;
@@ -2207,12 +2207,12 @@ static void writecache_dtr(struct dm_target *ti)
kfree(wc);
}
-static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
+static int writecache_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct dm_writecache *wc;
struct dm_arg_set as;
const char *string;
- unsigned opt_params;
+ unsigned int opt_params;
size_t offset, data_size;
int i, r;
char dummy;
@@ -2419,7 +2419,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto invalid_optional;
wc->autocommit_blocks_set = true;
} else if (!strcasecmp(string, "autocommit_time") && opt_params >= 1) {
- unsigned autocommit_msecs;
+ unsigned int autocommit_msecs;
string = dm_shift_arg(&as), opt_params--;
if (sscanf(string, "%u%c", &autocommit_msecs, &dummy) != 1)
goto invalid_optional;
@@ -2429,7 +2429,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
wc->autocommit_time_value = autocommit_msecs;
wc->autocommit_time_set = true;
} else if (!strcasecmp(string, "max_age") && opt_params >= 1) {
- unsigned max_age_msecs;
+ unsigned int max_age_msecs;
string = dm_shift_arg(&as), opt_params--;
if (sscanf(string, "%u%c", &max_age_msecs, &dummy) != 1)
goto invalid_optional;
@@ -2454,7 +2454,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
} else if (!strcasecmp(string, "metadata_only")) {
wc->metadata_only = true;
} else if (!strcasecmp(string, "pause_writeback") && opt_params >= 1) {
- unsigned pause_msecs;
+ unsigned int pause_msecs;
if (WC_MODE_PMEM(wc))
goto invalid_optional;
string = dm_shift_arg(&as), opt_params--;
@@ -2653,11 +2653,11 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
}
static void writecache_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
struct dm_writecache *wc = ti->private;
- unsigned extra_args;
- unsigned sz = 0;
+ unsigned int extra_args;
+ unsigned int sz = 0;
switch (type) {
case STATUSTYPE_INFO:
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 38d8aa21ef7a..24284d22f15b 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -83,7 +83,7 @@ struct clone_info {
struct bio *bio;
struct dm_io *io;
sector_t sector;
- unsigned sector_count;
+ unsigned int sector_count;
bool is_abnormal_io:1;
bool submit_as_polled:1;
};
@@ -111,7 +111,7 @@ struct bio *dm_bio_from_per_bio_data(void *data, size_t data_size)
}
EXPORT_SYMBOL_GPL(dm_bio_from_per_bio_data);
-unsigned dm_bio_get_target_bio_nr(const struct bio *bio)
+unsigned int dm_bio_get_target_bio_nr(const struct bio *bio)
{
return container_of(bio, struct dm_target_io, clone)->target_bio_nr;
}
@@ -142,7 +142,7 @@ struct table_device {
* Bio-based DM's mempools' reserved IOs set by the user.
*/
#define RESERVED_BIO_BASED_IOS 16
-static unsigned reserved_bio_based_ios = RESERVED_BIO_BASED_IOS;
+static unsigned int reserved_bio_based_ios = RESERVED_BIO_BASED_IOS;
static int __dm_get_module_param_int(int *module_param, int min, int max)
{
@@ -165,11 +165,10 @@ static int __dm_get_module_param_int(int *module_param, int min, int max)
return param;
}
-unsigned __dm_get_module_param(unsigned *module_param,
- unsigned def, unsigned max)
+unsigned int __dm_get_module_param(unsigned int *module_param, unsigned int def, unsigned int max)
{
- unsigned param = READ_ONCE(*module_param);
- unsigned modified_param = 0;
+ unsigned int param = READ_ONCE(*module_param);
+ unsigned int modified_param = 0;
if (!param)
modified_param = def;
@@ -184,14 +183,14 @@ unsigned __dm_get_module_param(unsigned *module_param,
return param;
}
-unsigned dm_get_reserved_bio_based_ios(void)
+unsigned int dm_get_reserved_bio_based_ios(void)
{
return __dm_get_module_param(&reserved_bio_based_ios,
RESERVED_BIO_BASED_IOS, DM_RESERVED_MAX_IOS);
}
EXPORT_SYMBOL_GPL(dm_get_reserved_bio_based_ios);
-static unsigned dm_get_numa_node(void)
+static unsigned int dm_get_numa_node(void)
{
return __dm_get_module_param_int(&dm_numa_node,
DM_NUMA_NODE, num_online_nodes() - 1);
@@ -603,7 +602,7 @@ static void free_io(struct dm_io *io)
}
static struct bio *alloc_tio(struct clone_info *ci, struct dm_target *ti,
- unsigned target_bio_nr, unsigned *len, gfp_t gfp_mask)
+ unsigned int target_bio_nr, unsigned int *len, gfp_t gfp_mask)
{
struct mapped_device *md = ci->io->md;
struct dm_target_io *tio;
@@ -1327,11 +1326,11 @@ static size_t dm_dax_recovery_write(struct dax_device *dax_dev, pgoff_t pgoff,
* the partially processed part (the sum of regions 1+2) must be the same for all
* copies of the bio.
*/
-void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors)
+void dm_accept_partial_bio(struct bio *bio, unsigned int n_sectors)
{
struct dm_target_io *tio = clone_to_tio(bio);
struct dm_io *io = tio->io;
- unsigned bio_sectors = bio_sectors(bio);
+ unsigned int bio_sectors = bio_sectors(bio);
BUG_ON(dm_tio_flagged(tio, DM_TIO_IS_DUPLICATE_BIO));
BUG_ON(op_is_zone_mgmt(bio_op(bio)));
@@ -1460,7 +1459,7 @@ static void __map_bio(struct bio *clone)
}
}
-static void setup_split_accounting(struct clone_info *ci, unsigned len)
+static void setup_split_accounting(struct clone_info *ci, unsigned int len)
{
struct dm_io *io = ci->io;
@@ -1476,7 +1475,8 @@ static void setup_split_accounting(struct clone_info *ci, unsigned len)
}
static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
- struct dm_target *ti, unsigned num_bios)
+ struct dm_target *ti, unsigned int num_bios,
+ unsigned *len)
{
struct bio *bio;
int try;
@@ -1487,7 +1487,7 @@ static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
if (try)
mutex_lock(&ci->io->md->table_devices_lock);
for (bio_nr = 0; bio_nr < num_bios; bio_nr++) {
- bio = alloc_tio(ci, ti, bio_nr, NULL,
+ bio = alloc_tio(ci, ti, bio_nr, len,
try ? GFP_NOIO : GFP_NOWAIT);
if (!bio)
break;
@@ -1505,7 +1505,7 @@ static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
}
static int __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
- unsigned int num_bios, unsigned *len)
+ unsigned int num_bios, unsigned int *len)
{
struct bio_list blist = BIO_EMPTY_LIST;
struct bio *clone;
@@ -1525,7 +1525,7 @@ static int __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
if (len)
setup_split_accounting(ci, *len);
/* dm_accept_partial_bio() is not supported with shared tio->len_ptr */
- alloc_multiple_bios(&blist, ci, ti, num_bios);
+ alloc_multiple_bios(&blist, ci, ti, num_bios, len);
while ((clone = bio_list_pop(&blist))) {
dm_tio_set_flag(clone_to_tio(clone), DM_TIO_IS_DUPLICATE_BIO);
__map_bio(clone);
@@ -1573,10 +1573,9 @@ static void __send_empty_flush(struct clone_info *ci)
}
static void __send_changing_extent_only(struct clone_info *ci, struct dm_target *ti,
- unsigned num_bios)
+ unsigned int num_bios)
{
- unsigned len;
- unsigned int bios;
+ unsigned int len, bios;
len = min_t(sector_t, ci->sector_count,
max_io_len_target_boundary(ti, dm_target_offset(ti, ci->sector)));
@@ -1614,7 +1613,7 @@ static bool is_abnormal_io(struct bio *bio)
static blk_status_t __process_abnormal_io(struct clone_info *ci,
struct dm_target *ti)
{
- unsigned num_bios = 0;
+ unsigned int num_bios = 0;
switch (bio_op(ci->bio)) {
case REQ_OP_DISCARD:
@@ -1692,7 +1691,7 @@ static blk_status_t __split_and_process_bio(struct clone_info *ci)
{
struct bio *clone;
struct dm_target *ti;
- unsigned len;
+ unsigned int len;
ti = dm_table_find_target(ci->map, ci->sector);
if (unlikely(!ti))
@@ -2389,7 +2388,7 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
struct mapped_device *dm_get_md(dev_t dev)
{
struct mapped_device *md;
- unsigned minor = MINOR(dev);
+ unsigned int minor = MINOR(dev);
if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
return NULL;
@@ -2672,7 +2671,7 @@ static void unlock_fs(struct mapped_device *md)
* are being added to md->deferred list.
*/
static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
- unsigned suspend_flags, unsigned int task_state,
+ unsigned int suspend_flags, unsigned int task_state,
int dmf_suspended_flag)
{
bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
@@ -2779,7 +2778,7 @@ static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
*
* To abort suspend, start the request_queue.
*/
-int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
+int dm_suspend(struct mapped_device *md, unsigned int suspend_flags)
{
struct dm_table *map = NULL;
int r = 0;
@@ -2881,7 +2880,7 @@ int dm_resume(struct mapped_device *md)
* It may be used only from the kernel.
*/
-static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_flags)
+static void __dm_internal_suspend(struct mapped_device *md, unsigned int suspend_flags)
{
struct dm_table *map = NULL;
@@ -2983,10 +2982,10 @@ EXPORT_SYMBOL_GPL(dm_internal_resume_fast);
* Event notification.
*---------------------------------------------------------------*/
int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
- unsigned cookie, bool need_resize_uevent)
+ unsigned int cookie, bool need_resize_uevent)
{
int r;
- unsigned noio_flag;
+ unsigned int noio_flag;
char udev_cookie[DM_COOKIE_LENGTH];
char *envp[3] = { NULL, NULL, NULL };
char **envpp = envp;
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index a9a3ffcad084..a7917df09caf 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -203,7 +203,7 @@ int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode,
void dm_put_table_device(struct mapped_device *md, struct dm_dev *d);
int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
- unsigned cookie, bool need_resize_uevent);
+ unsigned int cookie, bool need_resize_uevent);
void dm_internal_suspend(struct mapped_device *md);
void dm_internal_resume(struct mapped_device *md);
@@ -222,6 +222,6 @@ void dm_free_md_mempools(struct dm_md_mempools *pools);
/*
* Various helpers
*/
-unsigned dm_get_reserved_bio_based_ios(void);
+unsigned int dm_get_reserved_bio_based_ios(void);
#endif
diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c
index 3a963d783a86..eff9b41869f2 100644
--- a/drivers/md/persistent-data/dm-array.c
+++ b/drivers/md/persistent-data/dm-array.c
@@ -68,8 +68,8 @@ static int array_block_check(struct dm_block_validator *v,
CSUM_XOR));
if (csum_disk != bh_le->csum) {
DMERR_LIMIT("array_block_check failed: csum %u != wanted %u",
- (unsigned) le32_to_cpu(csum_disk),
- (unsigned) le32_to_cpu(bh_le->csum));
+ (unsigned int) le32_to_cpu(csum_disk),
+ (unsigned int) le32_to_cpu(bh_le->csum));
return -EILSEQ;
}
@@ -94,7 +94,7 @@ static struct dm_block_validator array_validator = {
* index - The index into _this_ specific block.
*/
static void *element_at(struct dm_array_info *info, struct array_block *ab,
- unsigned index)
+ unsigned int index)
{
unsigned char *entry = (unsigned char *) (ab + 1);
@@ -108,9 +108,9 @@ static void *element_at(struct dm_array_info *info, struct array_block *ab,
* in an array block.
*/
static void on_entries(struct dm_array_info *info, struct array_block *ab,
- void (*fn)(void *, const void *, unsigned))
+ void (*fn)(void *, const void *, unsigned int))
{
- unsigned nr_entries = le32_to_cpu(ab->nr_entries);
+ unsigned int nr_entries = le32_to_cpu(ab->nr_entries);
fn(info->value_type.context, element_at(info, ab, 0), nr_entries);
}
@@ -171,7 +171,7 @@ static int alloc_ablock(struct dm_array_info *info, size_t size_of_block,
* the current number of entries.
*/
static void fill_ablock(struct dm_array_info *info, struct array_block *ab,
- const void *value, unsigned new_nr)
+ const void *value, unsigned int new_nr)
{
uint32_t nr_entries, delta, i;
struct dm_btree_value_type *vt = &info->value_type;
@@ -194,7 +194,7 @@ static void fill_ablock(struct dm_array_info *info, struct array_block *ab,
* entries.
*/
static void trim_ablock(struct dm_array_info *info, struct array_block *ab,
- unsigned new_nr)
+ unsigned int new_nr)
{
uint32_t nr_entries, delta;
struct dm_btree_value_type *vt = &info->value_type;
@@ -247,7 +247,7 @@ static void unlock_ablock(struct dm_array_info *info, struct dm_block *block)
* / max_entries).
*/
static int lookup_ablock(struct dm_array_info *info, dm_block_t root,
- unsigned index, struct dm_block **block,
+ unsigned int index, struct dm_block **block,
struct array_block **ab)
{
int r;
@@ -295,7 +295,7 @@ static int __shadow_ablock(struct dm_array_info *info, dm_block_t b,
* The shadow op will often be a noop. Only insert if it really
* copied data.
*/
-static int __reinsert_ablock(struct dm_array_info *info, unsigned index,
+static int __reinsert_ablock(struct dm_array_info *info, unsigned int index,
struct dm_block *block, dm_block_t b,
dm_block_t *root)
{
@@ -321,7 +321,7 @@ static int __reinsert_ablock(struct dm_array_info *info, unsigned index,
* for both the current root block, and the new one.
*/
static int shadow_ablock(struct dm_array_info *info, dm_block_t *root,
- unsigned index, struct dm_block **block,
+ unsigned int index, struct dm_block **block,
struct array_block **ab)
{
int r;
@@ -346,7 +346,7 @@ static int shadow_ablock(struct dm_array_info *info, dm_block_t *root,
*/
static int insert_new_ablock(struct dm_array_info *info, size_t size_of_block,
uint32_t max_entries,
- unsigned block_index, uint32_t nr,
+ unsigned int block_index, uint32_t nr,
const void *value, dm_block_t *root)
{
int r;
@@ -365,8 +365,8 @@ static int insert_new_ablock(struct dm_array_info *info, size_t size_of_block,
}
static int insert_full_ablocks(struct dm_array_info *info, size_t size_of_block,
- unsigned begin_block, unsigned end_block,
- unsigned max_entries, const void *value,
+ unsigned int begin_block, unsigned int end_block,
+ unsigned int max_entries, const void *value,
dm_block_t *root)
{
int r = 0;
@@ -402,20 +402,20 @@ struct resize {
/*
* Maximum nr entries in an array block.
*/
- unsigned max_entries;
+ unsigned int max_entries;
/*
* nr of completely full blocks in the array.
*
* 'old' refers to before the resize, 'new' after.
*/
- unsigned old_nr_full_blocks, new_nr_full_blocks;
+ unsigned int old_nr_full_blocks, new_nr_full_blocks;
/*
* Number of entries in the final block. 0 iff only full blocks in
* the array.
*/
- unsigned old_nr_entries_in_last_block, new_nr_entries_in_last_block;
+ unsigned int old_nr_entries_in_last_block, new_nr_entries_in_last_block;
/*
* The default value used when growing the array.
@@ -430,8 +430,8 @@ struct resize {
* begin_index - the index of the first array block to remove.
* end_index - the one-past-the-end value. ie. this block is not removed.
*/
-static int drop_blocks(struct resize *resize, unsigned begin_index,
- unsigned end_index)
+static int drop_blocks(struct resize *resize, unsigned int begin_index,
+ unsigned int end_index)
{
int r;
@@ -449,8 +449,8 @@ static int drop_blocks(struct resize *resize, unsigned begin_index,
/*
* Calculates how many blocks are needed for the array.
*/
-static unsigned total_nr_blocks_needed(unsigned nr_full_blocks,
- unsigned nr_entries_in_last_block)
+static unsigned int total_nr_blocks_needed(unsigned int nr_full_blocks,
+ unsigned int nr_entries_in_last_block)
{
return nr_full_blocks + (nr_entries_in_last_block ? 1 : 0);
}
@@ -461,7 +461,7 @@ static unsigned total_nr_blocks_needed(unsigned nr_full_blocks,
static int shrink(struct resize *resize)
{
int r;
- unsigned begin, end;
+ unsigned int begin, end;
struct dm_block *block;
struct array_block *ab;
@@ -527,7 +527,7 @@ static int grow_add_tail_block(struct resize *resize)
static int grow_needs_more_blocks(struct resize *resize)
{
int r;
- unsigned old_nr_blocks = resize->old_nr_full_blocks;
+ unsigned int old_nr_blocks = resize->old_nr_full_blocks;
if (resize->old_nr_entries_in_last_block > 0) {
old_nr_blocks++;
@@ -569,11 +569,11 @@ static int grow(struct resize *resize)
* These are the value_type functions for the btree elements, which point
* to array blocks.
*/
-static void block_inc(void *context, const void *value, unsigned count)
+static void block_inc(void *context, const void *value, unsigned int count)
{
const __le64 *block_le = value;
struct dm_array_info *info = context;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, block_le++)
dm_tm_inc(info->btree_info.tm, le64_to_cpu(*block_le));
@@ -618,9 +618,9 @@ static void __block_dec(void *context, const void *value)
dm_tm_dec(info->btree_info.tm, b);
}
-static void block_dec(void *context, const void *value, unsigned count)
+static void block_dec(void *context, const void *value, unsigned int count)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, value += sizeof(__le64))
__block_dec(context, value);
}
@@ -700,10 +700,11 @@ int dm_array_resize(struct dm_array_info *info, dm_block_t root,
EXPORT_SYMBOL_GPL(dm_array_resize);
static int populate_ablock_with_values(struct dm_array_info *info, struct array_block *ab,
- value_fn fn, void *context, unsigned base, unsigned new_nr)
+ value_fn fn, void *context,
+ unsigned int base, unsigned int new_nr)
{
int r;
- unsigned i;
+ unsigned int i;
struct dm_btree_value_type *vt = &info->value_type;
BUG_ON(le32_to_cpu(ab->nr_entries));
@@ -728,7 +729,7 @@ int dm_array_new(struct dm_array_info *info, dm_block_t *root,
int r;
struct dm_block *block;
struct array_block *ab;
- unsigned block_index, end_block, size_of_block, max_entries;
+ unsigned int block_index, end_block, size_of_block, max_entries;
r = dm_array_empty(info, root);
if (r)
@@ -776,7 +777,7 @@ int dm_array_get_value(struct dm_array_info *info, dm_block_t root,
struct dm_block *block;
struct array_block *ab;
size_t size_of_block;
- unsigned entry, max_entries;
+ unsigned int entry, max_entries;
size_of_block = dm_bm_block_size(dm_tm_get_bm(info->btree_info.tm));
max_entries = calc_max_entries(info->value_type.size, size_of_block);
@@ -804,8 +805,8 @@ static int array_set_value(struct dm_array_info *info, dm_block_t root,
struct dm_block *block;
struct array_block *ab;
size_t size_of_block;
- unsigned max_entries;
- unsigned entry;
+ unsigned int max_entries;
+ unsigned int entry;
void *old_value;
struct dm_btree_value_type *vt = &info->value_type;
@@ -861,9 +862,9 @@ static int walk_ablock(void *context, uint64_t *keys, void *leaf)
struct walk_info *wi = context;
int r;
- unsigned i;
+ unsigned int i;
__le64 block_le;
- unsigned nr_entries, max_entries;
+ unsigned int nr_entries, max_entries;
struct dm_block *block;
struct array_block *ab;
diff --git a/drivers/md/persistent-data/dm-array.h b/drivers/md/persistent-data/dm-array.h
index d7d2d579c662..b6c7077c7359 100644
--- a/drivers/md/persistent-data/dm-array.h
+++ b/drivers/md/persistent-data/dm-array.h
@@ -198,7 +198,7 @@ struct dm_array_cursor {
struct dm_block *block;
struct array_block *ab;
- unsigned index;
+ unsigned int index;
};
int dm_array_cursor_begin(struct dm_array_info *info,
diff --git a/drivers/md/persistent-data/dm-bitset.c b/drivers/md/persistent-data/dm-bitset.c
index b7208d82e748..625d93498cdd 100644
--- a/drivers/md/persistent-data/dm-bitset.c
+++ b/drivers/md/persistent-data/dm-bitset.c
@@ -41,7 +41,7 @@ EXPORT_SYMBOL_GPL(dm_bitset_empty);
struct packer_context {
bit_value_fn fn;
- unsigned nr_bits;
+ unsigned int nr_bits;
void *context;
};
@@ -49,7 +49,7 @@ static int pack_bits(uint32_t index, void *value, void *context)
{
int r;
struct packer_context *p = context;
- unsigned bit, nr = min(64u, p->nr_bits - (index * 64));
+ unsigned int bit, nr = min(64u, p->nr_bits - (index * 64));
uint64_t word = 0;
bool bv;
@@ -147,7 +147,7 @@ static int get_array_entry(struct dm_disk_bitset *info, dm_block_t root,
uint32_t index, dm_block_t *new_root)
{
int r;
- unsigned array_index = index / BITS_PER_ARRAY_ENTRY;
+ unsigned int array_index = index / BITS_PER_ARRAY_ENTRY;
if (info->current_index_set) {
if (info->current_index == array_index)
@@ -165,7 +165,7 @@ int dm_bitset_set_bit(struct dm_disk_bitset *info, dm_block_t root,
uint32_t index, dm_block_t *new_root)
{
int r;
- unsigned b = index % BITS_PER_ARRAY_ENTRY;
+ unsigned int b = index % BITS_PER_ARRAY_ENTRY;
r = get_array_entry(info, root, index, new_root);
if (r)
@@ -182,7 +182,7 @@ int dm_bitset_clear_bit(struct dm_disk_bitset *info, dm_block_t root,
uint32_t index, dm_block_t *new_root)
{
int r;
- unsigned b = index % BITS_PER_ARRAY_ENTRY;
+ unsigned int b = index % BITS_PER_ARRAY_ENTRY;
r = get_array_entry(info, root, index, new_root);
if (r)
@@ -199,7 +199,7 @@ int dm_bitset_test_bit(struct dm_disk_bitset *info, dm_block_t root,
uint32_t index, dm_block_t *new_root, bool *result)
{
int r;
- unsigned b = index % BITS_PER_ARRAY_ENTRY;
+ unsigned int b = index % BITS_PER_ARRAY_ENTRY;
r = get_array_entry(info, root, index, new_root);
if (r)
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
index 11935864f50f..1f40100908d7 100644
--- a/drivers/md/persistent-data/dm-block-manager.c
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -57,10 +57,10 @@ struct waiter {
int wants_write;
};
-static unsigned __find_holder(struct block_lock *lock,
+static unsigned int __find_holder(struct block_lock *lock,
struct task_struct *task)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < MAX_HOLDERS; i++)
if (lock->holders[i] == task)
@@ -73,7 +73,7 @@ static unsigned __find_holder(struct block_lock *lock,
/* call this *after* you increment lock->count */
static void __add_holder(struct block_lock *lock, struct task_struct *task)
{
- unsigned h = __find_holder(lock, NULL);
+ unsigned int h = __find_holder(lock, NULL);
#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
struct stack_store *t;
#endif
@@ -90,14 +90,14 @@ static void __add_holder(struct block_lock *lock, struct task_struct *task)
/* call this *before* you decrement lock->count */
static void __del_holder(struct block_lock *lock, struct task_struct *task)
{
- unsigned h = __find_holder(lock, task);
+ unsigned int h = __find_holder(lock, task);
lock->holders[h] = NULL;
put_task_struct(task);
}
static int __check_holder(struct block_lock *lock)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < MAX_HOLDERS; i++) {
if (lock->holders[i] == current) {
@@ -376,8 +376,8 @@ struct dm_block_manager {
};
struct dm_block_manager *dm_block_manager_create(struct block_device *bdev,
- unsigned block_size,
- unsigned max_held_per_thread)
+ unsigned int block_size,
+ unsigned int max_held_per_thread)
{
int r;
struct dm_block_manager *bm;
@@ -415,7 +415,7 @@ void dm_block_manager_destroy(struct dm_block_manager *bm)
}
EXPORT_SYMBOL_GPL(dm_block_manager_destroy);
-unsigned dm_bm_block_size(struct dm_block_manager *bm)
+unsigned int dm_bm_block_size(struct dm_block_manager *bm)
{
return dm_bufio_get_block_size(bm->bufio);
}
diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h
index e728937f376a..58a23b8ec190 100644
--- a/drivers/md/persistent-data/dm-block-manager.h
+++ b/drivers/md/persistent-data/dm-block-manager.h
@@ -32,11 +32,11 @@ void *dm_block_data(struct dm_block *b);
*/
struct dm_block_manager;
struct dm_block_manager *dm_block_manager_create(
- struct block_device *bdev, unsigned block_size,
- unsigned max_held_per_thread);
+ struct block_device *bdev, unsigned int block_size,
+ unsigned int max_held_per_thread);
void dm_block_manager_destroy(struct dm_block_manager *bm);
-unsigned dm_bm_block_size(struct dm_block_manager *bm);
+unsigned int dm_bm_block_size(struct dm_block_manager *bm);
dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm);
/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c
index 4ead31e0d8ce..ac213138b021 100644
--- a/drivers/md/persistent-data/dm-btree-remove.c
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -124,10 +124,10 @@ static int node_copy(struct btree_node *left, struct btree_node *right, int shif
/*
* Delete a specific entry from a leaf node.
*/
-static void delete_at(struct btree_node *n, unsigned index)
+static void delete_at(struct btree_node *n, unsigned int index)
{
- unsigned nr_entries = le32_to_cpu(n->header.nr_entries);
- unsigned nr_to_copy = nr_entries - (index + 1);
+ unsigned int nr_entries = le32_to_cpu(n->header.nr_entries);
+ unsigned int nr_to_copy = nr_entries - (index + 1);
uint32_t value_size = le32_to_cpu(n->header.value_size);
BUG_ON(index >= nr_entries);
@@ -144,20 +144,20 @@ static void delete_at(struct btree_node *n, unsigned index)
n->header.nr_entries = cpu_to_le32(nr_entries - 1);
}
-static unsigned merge_threshold(struct btree_node *n)
+static unsigned int merge_threshold(struct btree_node *n)
{
return le32_to_cpu(n->header.max_entries) / 3;
}
struct child {
- unsigned index;
+ unsigned int index;
struct dm_block *block;
struct btree_node *n;
};
static int init_child(struct dm_btree_info *info, struct dm_btree_value_type *vt,
struct btree_node *parent,
- unsigned index, struct child *result)
+ unsigned int index, struct child *result)
{
int r, inc;
dm_block_t root;
@@ -263,7 +263,7 @@ static int __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
/*
* Rebalance.
*/
- unsigned target_left = (nr_left + nr_right) / 2;
+ unsigned int target_left = (nr_left + nr_right) / 2;
ret = shift(left, right, nr_left - target_left);
if (ret)
return ret;
@@ -273,7 +273,7 @@ static int __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
}
static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
- struct dm_btree_value_type *vt, unsigned left_index)
+ struct dm_btree_value_type *vt, unsigned int left_index)
{
int r;
struct btree_node *parent;
@@ -310,7 +310,7 @@ static int delete_center_node(struct dm_btree_info *info, struct btree_node *par
uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
{
uint32_t max_entries = le32_to_cpu(left->header.max_entries);
- unsigned shift = min(max_entries - nr_left, nr_center);
+ unsigned int shift = min(max_entries - nr_left, nr_center);
if (nr_left + shift > max_entries) {
DMERR("node shift out of bounds");
@@ -351,10 +351,10 @@ static int redistribute3(struct dm_btree_info *info, struct btree_node *parent,
{
int s, ret;
uint32_t max_entries = le32_to_cpu(left->header.max_entries);
- unsigned total = nr_left + nr_center + nr_right;
- unsigned target_right = total / 3;
- unsigned remainder = (target_right * 3) != total;
- unsigned target_left = target_right + remainder;
+ unsigned int total = nr_left + nr_center + nr_right;
+ unsigned int target_right = total / 3;
+ unsigned int remainder = (target_right * 3) != total;
+ unsigned int target_left = target_right + remainder;
BUG_ON(target_left > max_entries);
BUG_ON(target_right > max_entries);
@@ -422,7 +422,7 @@ static int __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
- unsigned threshold = merge_threshold(left) * 4 + 1;
+ unsigned int threshold = merge_threshold(left) * 4 + 1;
if ((left->header.max_entries != center->header.max_entries) ||
(center->header.max_entries != right->header.max_entries)) {
@@ -440,7 +440,7 @@ static int __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
}
static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
- struct dm_btree_value_type *vt, unsigned left_index)
+ struct dm_btree_value_type *vt, unsigned int left_index)
{
int r;
struct btree_node *parent = dm_block_data(shadow_current(s));
@@ -519,7 +519,7 @@ static int rebalance_children(struct shadow_spine *s,
return r;
}
-static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index)
+static int do_leaf(struct btree_node *n, uint64_t key, unsigned int *index)
{
int i = lower_bound(n, key);
@@ -539,7 +539,7 @@ static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index)
*/
static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
struct dm_btree_value_type *vt, dm_block_t root,
- uint64_t key, unsigned *index)
+ uint64_t key, unsigned int *index)
{
int i = *index, r;
struct btree_node *n;
@@ -589,7 +589,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, dm_block_t *new_root)
{
- unsigned level, last_level = info->levels - 1;
+ unsigned int level, last_level = info->levels - 1;
int index = 0, r = 0;
struct shadow_spine spine;
struct btree_node *n;
@@ -601,7 +601,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
r = remove_raw(&spine, info,
(level == last_level ?
&info->value_type : &le64_vt),
- root, keys[level], (unsigned *)&index);
+ root, keys[level], (unsigned int *)&index);
if (r < 0)
break;
@@ -685,9 +685,9 @@ static int remove_nearest(struct shadow_spine *s, struct dm_btree_info *info,
static int remove_one(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, uint64_t end_key,
- dm_block_t *new_root, unsigned *nr_removed)
+ dm_block_t *new_root, unsigned int *nr_removed)
{
- unsigned level, last_level = info->levels - 1;
+ unsigned int level, last_level = info->levels - 1;
int index = 0, r = 0;
struct shadow_spine spine;
struct btree_node *n;
@@ -698,7 +698,7 @@ static int remove_one(struct dm_btree_info *info, dm_block_t root,
init_shadow_spine(&spine, info);
for (level = 0; level < last_level; level++) {
r = remove_raw(&spine, info, &le64_vt,
- root, keys[level], (unsigned *) &index);
+ root, keys[level], (unsigned int *) &index);
if (r < 0)
goto out;
@@ -742,7 +742,7 @@ static int remove_one(struct dm_btree_info *info, dm_block_t root,
int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root,
uint64_t *first_key, uint64_t end_key,
- dm_block_t *new_root, unsigned *nr_removed)
+ dm_block_t *new_root, unsigned int *nr_removed)
{
int r;
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c
index e653458888a7..45a39d4f1c10 100644
--- a/drivers/md/persistent-data/dm-btree-spine.c
+++ b/drivers/md/persistent-data/dm-btree-spine.c
@@ -234,12 +234,12 @@ dm_block_t shadow_root(struct shadow_spine *s)
return s->root;
}
-static void le64_inc(void *context, const void *value_le, unsigned count)
+static void le64_inc(void *context, const void *value_le, unsigned int count)
{
dm_tm_with_runs(context, value_le, count, dm_tm_inc_range);
}
-static void le64_dec(void *context, const void *value_le, unsigned count)
+static void le64_dec(void *context, const void *value_le, unsigned int count)
{
dm_tm_with_runs(context, value_le, count, dm_tm_dec_range);
}
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
index 5ce64e93aae7..1cc783d7030d 100644
--- a/drivers/md/persistent-data/dm-btree.c
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -23,8 +23,8 @@ static void memcpy_disk(void *dest, const void *src, size_t len)
__dm_unbless_for_disk(src);
}
-static void array_insert(void *base, size_t elt_size, unsigned nr_elts,
- unsigned index, void *elt)
+static void array_insert(void *base, size_t elt_size, unsigned int nr_elts,
+ unsigned int index, void *elt)
__dm_written_to_disk(elt)
{
if (index < nr_elts)
@@ -80,7 +80,7 @@ void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
vt->inc(vt->context, value_ptr(n, 0), nr_entries);
}
-static int insert_at(size_t value_size, struct btree_node *node, unsigned index,
+static int insert_at(size_t value_size, struct btree_node *node, unsigned int index,
uint64_t key, void *value)
__dm_written_to_disk(value)
{
@@ -162,9 +162,9 @@ EXPORT_SYMBOL_GPL(dm_btree_empty);
struct frame {
struct dm_block *b;
struct btree_node *n;
- unsigned level;
- unsigned nr_children;
- unsigned current_child;
+ unsigned int level;
+ unsigned int nr_children;
+ unsigned int current_child;
};
struct del_stack {
@@ -193,7 +193,7 @@ static int unprocessed_frames(struct del_stack *s)
static void prefetch_children(struct del_stack *s, struct frame *f)
{
- unsigned i;
+ unsigned int i;
struct dm_block_manager *bm = dm_tm_get_bm(s->tm);
for (i = 0; i < f->nr_children; i++)
@@ -205,7 +205,7 @@ static bool is_internal_level(struct dm_btree_info *info, struct frame *f)
return f->level < (info->levels - 1);
}
-static int push_frame(struct del_stack *s, dm_block_t b, unsigned level)
+static int push_frame(struct del_stack *s, dm_block_t b, unsigned int level)
{
int r;
uint32_t ref_count;
@@ -371,7 +371,7 @@ static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, void *value_le)
{
- unsigned level, last_level = info->levels - 1;
+ unsigned int level, last_level = info->levels - 1;
int r = -ENODATA;
uint64_t rkey;
__le64 internal_value_le;
@@ -467,7 +467,7 @@ static int dm_btree_lookup_next_single(struct dm_btree_info *info, dm_block_t ro
int dm_btree_lookup_next(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, uint64_t *rkey, void *value_le)
{
- unsigned level;
+ unsigned int level;
int r = -ENODATA;
__le64 internal_value_le;
struct ro_spine spine;
@@ -502,9 +502,9 @@ EXPORT_SYMBOL_GPL(dm_btree_lookup_next);
* Copies entries from one region of a btree node to another. The regions
* must not overlap.
*/
-static void copy_entries(struct btree_node *dest, unsigned dest_offset,
- struct btree_node *src, unsigned src_offset,
- unsigned count)
+static void copy_entries(struct btree_node *dest, unsigned int dest_offset,
+ struct btree_node *src, unsigned int src_offset,
+ unsigned int count)
{
size_t value_size = le32_to_cpu(dest->header.value_size);
memcpy(dest->keys + dest_offset, src->keys + src_offset, count * sizeof(uint64_t));
@@ -515,9 +515,9 @@ static void copy_entries(struct btree_node *dest, unsigned dest_offset,
* Moves entries from one region fo a btree node to another. The regions
* may overlap.
*/
-static void move_entries(struct btree_node *dest, unsigned dest_offset,
- struct btree_node *src, unsigned src_offset,
- unsigned count)
+static void move_entries(struct btree_node *dest, unsigned int dest_offset,
+ struct btree_node *src, unsigned int src_offset,
+ unsigned int count)
{
size_t value_size = le32_to_cpu(dest->header.value_size);
memmove(dest->keys + dest_offset, src->keys + src_offset, count * sizeof(uint64_t));
@@ -528,7 +528,7 @@ static void move_entries(struct btree_node *dest, unsigned dest_offset,
* Erases the first 'count' entries of a btree node, shifting following
* entries down into their place.
*/
-static void shift_down(struct btree_node *n, unsigned count)
+static void shift_down(struct btree_node *n, unsigned int count)
{
move_entries(n, 0, n, count, le32_to_cpu(n->header.nr_entries) - count);
}
@@ -537,7 +537,7 @@ static void shift_down(struct btree_node *n, unsigned count)
* Moves entries in a btree node up 'count' places, making space for
* new entries at the start of the node.
*/
-static void shift_up(struct btree_node *n, unsigned count)
+static void shift_up(struct btree_node *n, unsigned int count)
{
move_entries(n, count, n, 0, le32_to_cpu(n->header.nr_entries));
}
@@ -548,18 +548,18 @@ static void shift_up(struct btree_node *n, unsigned count)
*/
static void redistribute2(struct btree_node *left, struct btree_node *right)
{
- unsigned nr_left = le32_to_cpu(left->header.nr_entries);
- unsigned nr_right = le32_to_cpu(right->header.nr_entries);
- unsigned total = nr_left + nr_right;
- unsigned target_left = total / 2;
- unsigned target_right = total - target_left;
+ unsigned int nr_left = le32_to_cpu(left->header.nr_entries);
+ unsigned int nr_right = le32_to_cpu(right->header.nr_entries);
+ unsigned int total = nr_left + nr_right;
+ unsigned int target_left = total / 2;
+ unsigned int target_right = total - target_left;
if (nr_left < target_left) {
- unsigned delta = target_left - nr_left;
+ unsigned int delta = target_left - nr_left;
copy_entries(left, nr_left, right, 0, delta);
shift_down(right, delta);
} else if (nr_left > target_left) {
- unsigned delta = nr_left - target_left;
+ unsigned int delta = nr_left - target_left;
if (nr_right)
shift_up(right, delta);
copy_entries(right, 0, left, target_left, delta);
@@ -576,10 +576,10 @@ static void redistribute2(struct btree_node *left, struct btree_node *right)
static void redistribute3(struct btree_node *left, struct btree_node *center,
struct btree_node *right)
{
- unsigned nr_left = le32_to_cpu(left->header.nr_entries);
- unsigned nr_center = le32_to_cpu(center->header.nr_entries);
- unsigned nr_right = le32_to_cpu(right->header.nr_entries);
- unsigned total, target_left, target_center, target_right;
+ unsigned int nr_left = le32_to_cpu(left->header.nr_entries);
+ unsigned int nr_center = le32_to_cpu(center->header.nr_entries);
+ unsigned int nr_right = le32_to_cpu(right->header.nr_entries);
+ unsigned int total, target_left, target_center, target_right;
BUG_ON(nr_center);
@@ -589,19 +589,19 @@ static void redistribute3(struct btree_node *left, struct btree_node *center,
target_right = (total - target_left - target_center);
if (nr_left < target_left) {
- unsigned left_short = target_left - nr_left;
+ unsigned int left_short = target_left - nr_left;
copy_entries(left, nr_left, right, 0, left_short);
copy_entries(center, 0, right, left_short, target_center);
shift_down(right, nr_right - target_right);
} else if (nr_left < (target_left + target_center)) {
- unsigned left_to_center = nr_left - target_left;
+ unsigned int left_to_center = nr_left - target_left;
copy_entries(center, 0, left, target_left, left_to_center);
copy_entries(center, left_to_center, right, 0, target_center - left_to_center);
shift_down(right, nr_right - target_right);
} else {
- unsigned right_short = target_right - nr_right;
+ unsigned int right_short = target_right - nr_right;
shift_up(right, right_short);
copy_entries(right, 0, left, nr_left - right_short, right_short);
copy_entries(center, 0, left, target_left, nr_left - target_left);
@@ -642,7 +642,7 @@ static void redistribute3(struct btree_node *left, struct btree_node *center,
*
* Where A* is a shadow of A.
*/
-static int split_one_into_two(struct shadow_spine *s, unsigned parent_index,
+static int split_one_into_two(struct shadow_spine *s, unsigned int parent_index,
struct dm_btree_value_type *vt, uint64_t key)
{
int r;
@@ -696,7 +696,7 @@ static int split_one_into_two(struct shadow_spine *s, unsigned parent_index,
* to the new shadow.
*/
static int shadow_child(struct dm_btree_info *info, struct dm_btree_value_type *vt,
- struct btree_node *parent, unsigned index,
+ struct btree_node *parent, unsigned int index,
struct dm_block **result)
{
int r, inc;
@@ -725,11 +725,11 @@ static int shadow_child(struct dm_btree_info *info, struct dm_btree_value_type *
* Splits two nodes into three. This is more work, but results in fuller
* nodes, so saves metadata space.
*/
-static int split_two_into_three(struct shadow_spine *s, unsigned parent_index,
+static int split_two_into_three(struct shadow_spine *s, unsigned int parent_index,
struct dm_btree_value_type *vt, uint64_t key)
{
int r;
- unsigned middle_index;
+ unsigned int middle_index;
struct dm_block *left, *middle, *right, *parent;
struct btree_node *ln, *rn, *mn, *pn;
__le64 location;
@@ -830,7 +830,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
{
int r;
size_t size;
- unsigned nr_left, nr_right;
+ unsigned int nr_left, nr_right;
struct dm_block *left, *right, *new_parent;
struct btree_node *pn, *ln, *rn;
__le64 val;
@@ -904,7 +904,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
* Redistributes a node's entries with its left sibling.
*/
static int rebalance_left(struct shadow_spine *s, struct dm_btree_value_type *vt,
- unsigned parent_index, uint64_t key)
+ unsigned int parent_index, uint64_t key)
{
int r;
struct dm_block *sib;
@@ -933,7 +933,7 @@ static int rebalance_left(struct shadow_spine *s, struct dm_btree_value_type *vt
* Redistributes a nodes entries with its right sibling.
*/
static int rebalance_right(struct shadow_spine *s, struct dm_btree_value_type *vt,
- unsigned parent_index, uint64_t key)
+ unsigned int parent_index, uint64_t key)
{
int r;
struct dm_block *sib;
@@ -961,10 +961,10 @@ static int rebalance_right(struct shadow_spine *s, struct dm_btree_value_type *v
/*
* Returns the number of spare entries in a node.
*/
-static int get_node_free_space(struct dm_btree_info *info, dm_block_t b, unsigned *space)
+static int get_node_free_space(struct dm_btree_info *info, dm_block_t b, unsigned int *space)
{
int r;
- unsigned nr_entries;
+ unsigned int nr_entries;
struct dm_block *block;
struct btree_node *node;
@@ -990,12 +990,12 @@ static int get_node_free_space(struct dm_btree_info *info, dm_block_t b, unsigne
*/
#define SPACE_THRESHOLD 8
static int rebalance_or_split(struct shadow_spine *s, struct dm_btree_value_type *vt,
- unsigned parent_index, uint64_t key)
+ unsigned int parent_index, uint64_t key)
{
int r;
struct btree_node *parent = dm_block_data(shadow_parent(s));
- unsigned nr_parent = le32_to_cpu(parent->header.nr_entries);
- unsigned free_space;
+ unsigned int nr_parent = le32_to_cpu(parent->header.nr_entries);
+ unsigned int free_space;
int left_shared = 0, right_shared = 0;
/* Should we move entries to the left sibling? */
@@ -1080,7 +1080,7 @@ static bool has_space_for_insert(struct btree_node *node, uint64_t key)
static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
struct dm_btree_value_type *vt,
- uint64_t key, unsigned *index)
+ uint64_t key, unsigned int *index)
{
int r, i = *index, top = 1;
struct btree_node *node;
@@ -1214,7 +1214,7 @@ int btree_get_overwrite_leaf(struct dm_btree_info *info, dm_block_t root,
}
static bool need_insert(struct btree_node *node, uint64_t *keys,
- unsigned level, unsigned index)
+ unsigned int level, unsigned int index)
{
return ((index >= le32_to_cpu(node->header.nr_entries)) ||
(le64_to_cpu(node->keys[index]) != keys[level]));
@@ -1226,7 +1226,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root,
__dm_written_to_disk(value)
{
int r;
- unsigned level, index = -1, last_level = info->levels - 1;
+ unsigned int level, index = -1, last_level = info->levels - 1;
dm_block_t block = root;
struct shadow_spine spine;
struct btree_node *n;
@@ -1412,7 +1412,7 @@ static int walk_node(struct dm_btree_info *info, dm_block_t block,
void *context)
{
int r;
- unsigned i, nr;
+ unsigned int i, nr;
struct dm_block *node;
struct btree_node *n;
uint64_t keys;
@@ -1455,7 +1455,7 @@ EXPORT_SYMBOL_GPL(dm_btree_walk);
static void prefetch_values(struct dm_btree_cursor *c)
{
- unsigned i, nr;
+ unsigned int i, nr;
__le64 value_le;
struct cursor_node *n = c->nodes + c->depth - 1;
struct btree_node *bn = dm_block_data(n->b);
diff --git a/drivers/md/persistent-data/dm-btree.h b/drivers/md/persistent-data/dm-btree.h
index d2ae5aa4d00b..5566e7c32e82 100644
--- a/drivers/md/persistent-data/dm-btree.h
+++ b/drivers/md/persistent-data/dm-btree.h
@@ -58,14 +58,14 @@ struct dm_btree_value_type {
* somewhere.) This method is _not_ called for insertion of a new
* value: It is assumed the ref count is already 1.
*/
- void (*inc)(void *context, const void *value, unsigned count);
+ void (*inc)(void *context, const void *value, unsigned int count);
/*
* These values are being deleted. The btree takes care of freeing
* the memory pointed to by @value. Often the del function just
* needs to decrement a reference counts somewhere.
*/
- void (*dec)(void *context, const void *value, unsigned count);
+ void (*dec)(void *context, const void *value, unsigned int count);
/*
* A test for equality between two values. When a value is
@@ -84,7 +84,7 @@ struct dm_btree_info {
/*
* Number of nested btrees. (Not the depth of a single tree.)
*/
- unsigned levels;
+ unsigned int levels;
struct dm_btree_value_type value_type;
};
@@ -149,7 +149,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
*/
int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, uint64_t end_key,
- dm_block_t *new_root, unsigned *nr_removed);
+ dm_block_t *new_root, unsigned int *nr_removed);
/*
* Returns < 0 on failure. Otherwise the number of key entries that have
@@ -188,7 +188,7 @@ int dm_btree_walk(struct dm_btree_info *info, dm_block_t root,
struct cursor_node {
struct dm_block *b;
- unsigned index;
+ unsigned int index;
};
struct dm_btree_cursor {
@@ -196,7 +196,7 @@ struct dm_btree_cursor {
dm_block_t root;
bool prefetch_leaves;
- unsigned depth;
+ unsigned int depth;
struct cursor_node nodes[DM_BTREE_CURSOR_MAX_DEPTH];
};
diff --git a/drivers/md/persistent-data/dm-persistent-data-internal.h b/drivers/md/persistent-data/dm-persistent-data-internal.h
index c49e26fff36c..b945a2be93fb 100644
--- a/drivers/md/persistent-data/dm-persistent-data-internal.h
+++ b/drivers/md/persistent-data/dm-persistent-data-internal.h
@@ -9,11 +9,11 @@
#include "dm-block-manager.h"
-static inline unsigned dm_hash_block(dm_block_t b, unsigned hash_mask)
+static inline unsigned int dm_hash_block(dm_block_t b, unsigned int hash_mask)
{
- const unsigned BIG_PRIME = 4294967291UL;
+ const unsigned int BIG_PRIME = 4294967291UL;
- return (((unsigned) b) * BIG_PRIME) & hash_mask;
+ return (((unsigned int) b) * BIG_PRIME) & hash_mask;
}
#endif /* _PERSISTENT_DATA_INTERNAL_H */
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
index bfbfa750e016..af800efed9f3 100644
--- a/drivers/md/persistent-data/dm-space-map-common.c
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -126,7 +126,7 @@ static void *dm_bitmap_data(struct dm_block *b)
#define WORD_MASK_HIGH 0xAAAAAAAAAAAAAAAAULL
-static unsigned dm_bitmap_word_used(void *addr, unsigned b)
+static unsigned int dm_bitmap_word_used(void *addr, unsigned int b)
{
__le64 *words_le = addr;
__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
@@ -137,11 +137,11 @@ static unsigned dm_bitmap_word_used(void *addr, unsigned b)
return !(~bits & mask);
}
-static unsigned sm_lookup_bitmap(void *addr, unsigned b)
+static unsigned int sm_lookup_bitmap(void *addr, unsigned int b)
{
__le64 *words_le = addr;
__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
- unsigned hi, lo;
+ unsigned int hi, lo;
b = (b & (ENTRIES_PER_WORD - 1)) << 1;
hi = !!test_bit_le(b, (void *) w_le);
@@ -149,7 +149,7 @@ static unsigned sm_lookup_bitmap(void *addr, unsigned b)
return (hi << 1) | lo;
}
-static void sm_set_bitmap(void *addr, unsigned b, unsigned val)
+static void sm_set_bitmap(void *addr, unsigned int b, unsigned int val)
{
__le64 *words_le = addr;
__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
@@ -167,8 +167,8 @@ static void sm_set_bitmap(void *addr, unsigned b, unsigned val)
__clear_bit_le(b + 1, (void *) w_le);
}
-static int sm_find_free(void *addr, unsigned begin, unsigned end,
- unsigned *result)
+static int sm_find_free(void *addr, unsigned int begin, unsigned int end,
+ unsigned int *result)
{
while (begin < end) {
if (!(begin & (ENTRIES_PER_WORD - 1)) &&
@@ -237,7 +237,7 @@ int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks)
{
int r;
dm_block_t i, nr_blocks, nr_indexes;
- unsigned old_blocks, blocks;
+ unsigned int old_blocks, blocks;
nr_blocks = ll->nr_blocks + extra_blocks;
old_blocks = dm_sector_div_up(ll->nr_blocks, ll->entries_per_block);
@@ -351,7 +351,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
for (i = index_begin; i < index_end; i++, begin = 0) {
struct dm_block *blk;
- unsigned position;
+ unsigned int position;
uint32_t bit_end;
r = ll->load_ie(ll, i, &ie_disk);
@@ -369,7 +369,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
bit_end = (i == index_end - 1) ? end : ll->entries_per_block;
r = sm_find_free(dm_bitmap_data(blk),
- max_t(unsigned, begin, le32_to_cpu(ie_disk.none_free_before)),
+ max_t(unsigned int, begin, le32_to_cpu(ie_disk.none_free_before)),
bit_end, &position);
if (r == -ENOSPC) {
/*
@@ -1097,7 +1097,7 @@ static inline int ie_cache_writeback(struct ll_disk *ll, struct ie_cache *iec)
&iec->index, &iec->ie, &ll->bitmap_root);
}
-static inline unsigned hash_index(dm_block_t index)
+static inline unsigned int hash_index(dm_block_t index)
{
return dm_hash_block(index, IE_CACHE_MASK);
}
@@ -1106,7 +1106,7 @@ static int disk_ll_load_ie(struct ll_disk *ll, dm_block_t index,
struct disk_index_entry *ie)
{
int r;
- unsigned h = hash_index(index);
+ unsigned int h = hash_index(index);
struct ie_cache *iec = ll->ie_cache + h;
if (iec->valid) {
@@ -1137,7 +1137,7 @@ static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
struct disk_index_entry *ie)
{
int r;
- unsigned h = hash_index(index);
+ unsigned int h = hash_index(index);
struct ie_cache *iec = ll->ie_cache + h;
ll->bitmap_index_changed = true;
@@ -1164,7 +1164,7 @@ static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
static int disk_ll_init_index(struct ll_disk *ll)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < IE_CACHE_SIZE; i++) {
struct ie_cache *iec = ll->ie_cache + i;
iec->valid = false;
@@ -1186,7 +1186,7 @@ static dm_block_t disk_ll_max_entries(struct ll_disk *ll)
static int disk_ll_commit(struct ll_disk *ll)
{
int r = 0;
- unsigned i;
+ unsigned int i;
for (i = 0; i < IE_CACHE_SIZE; i++) {
struct ie_cache *iec = ll->ie_cache + i;
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c
index 392ae26134a4..0d1fcdf29c83 100644
--- a/drivers/md/persistent-data/dm-space-map-metadata.c
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -94,8 +94,8 @@ struct block_op {
};
struct bop_ring_buffer {
- unsigned begin;
- unsigned end;
+ unsigned int begin;
+ unsigned int end;
struct block_op bops[MAX_RECURSIVE_ALLOCATIONS + 1];
};
@@ -110,9 +110,9 @@ static bool brb_empty(struct bop_ring_buffer *brb)
return brb->begin == brb->end;
}
-static unsigned brb_next(struct bop_ring_buffer *brb, unsigned old)
+static unsigned int brb_next(struct bop_ring_buffer *brb, unsigned int old)
{
- unsigned r = old + 1;
+ unsigned int r = old + 1;
return r >= ARRAY_SIZE(brb->bops) ? 0 : r;
}
@@ -120,7 +120,7 @@ static int brb_push(struct bop_ring_buffer *brb,
enum block_op_type type, dm_block_t b, dm_block_t e)
{
struct block_op *bop;
- unsigned next = brb_next(brb, brb->end);
+ unsigned int next = brb_next(brb, brb->end);
/*
* We don't allow the last bop to be filled, this way we can
@@ -171,8 +171,8 @@ struct sm_metadata {
dm_block_t begin;
- unsigned recursion_count;
- unsigned allocated_this_transaction;
+ unsigned int recursion_count;
+ unsigned int allocated_this_transaction;
struct bop_ring_buffer uncommitted;
struct threshold threshold;
@@ -300,9 +300,9 @@ static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b,
uint32_t *result)
{
int r;
- unsigned i;
+ unsigned int i;
struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
- unsigned adjustment = 0;
+ unsigned int adjustment = 0;
/*
* We may have some uncommitted adjustments to add. This list
@@ -340,7 +340,7 @@ static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm,
dm_block_t b, int *result)
{
int r, adjustment = 0;
- unsigned i;
+ unsigned int i;
struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
uint32_t rc;
diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c
index 16643fc974e8..39885f835584 100644
--- a/drivers/md/persistent-data/dm-transaction-manager.c
+++ b/drivers/md/persistent-data/dm-transaction-manager.c
@@ -28,14 +28,14 @@ struct prefetch_set {
dm_block_t blocks[PREFETCH_SIZE];
};
-static unsigned prefetch_hash(dm_block_t b)
+static unsigned int prefetch_hash(dm_block_t b)
{
return hash_64(b, PREFETCH_BITS);
}
static void prefetch_wipe(struct prefetch_set *p)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < PREFETCH_SIZE; i++)
p->blocks[i] = PREFETCH_SENTINEL;
}
@@ -48,7 +48,7 @@ static void prefetch_init(struct prefetch_set *p)
static void prefetch_add(struct prefetch_set *p, dm_block_t b)
{
- unsigned h = prefetch_hash(b);
+ unsigned int h = prefetch_hash(b);
mutex_lock(&p->lock);
if (p->blocks[h] == PREFETCH_SENTINEL)
@@ -59,7 +59,7 @@ static void prefetch_add(struct prefetch_set *p, dm_block_t b)
static void prefetch_issue(struct prefetch_set *p, struct dm_block_manager *bm)
{
- unsigned i;
+ unsigned int i;
mutex_lock(&p->lock);
@@ -103,7 +103,7 @@ struct dm_transaction_manager {
static int is_shadow(struct dm_transaction_manager *tm, dm_block_t b)
{
int r = 0;
- unsigned bucket = dm_hash_block(b, DM_HASH_MASK);
+ unsigned int bucket = dm_hash_block(b, DM_HASH_MASK);
struct shadow_info *si;
spin_lock(&tm->lock);
@@ -123,7 +123,7 @@ static int is_shadow(struct dm_transaction_manager *tm, dm_block_t b)
*/
static void insert_shadow(struct dm_transaction_manager *tm, dm_block_t b)
{
- unsigned bucket;
+ unsigned int bucket;
struct shadow_info *si;
si = kmalloc(sizeof(*si), GFP_NOIO);
@@ -393,11 +393,11 @@ void dm_tm_dec_range(struct dm_transaction_manager *tm, dm_block_t b, dm_block_t
EXPORT_SYMBOL_GPL(dm_tm_dec_range);
void dm_tm_with_runs(struct dm_transaction_manager *tm,
- const __le64 *value_le, unsigned count, dm_tm_run_fn fn)
+ const __le64 *value_le, unsigned int count, dm_tm_run_fn fn)
{
uint64_t b, begin, end;
bool in_run = false;
- unsigned i;
+ unsigned int i;
for (i = 0; i < count; i++, value_le++) {
b = le64_to_cpu(*value_le);
diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h
index 906c02ed0365..0f573a4a01ae 100644
--- a/drivers/md/persistent-data/dm-transaction-manager.h
+++ b/drivers/md/persistent-data/dm-transaction-manager.h
@@ -111,7 +111,7 @@ void dm_tm_dec_range(struct dm_transaction_manager *tm, dm_block_t b, dm_block_t
*/
typedef void (*dm_tm_run_fn)(struct dm_transaction_manager *, dm_block_t, dm_block_t);
void dm_tm_with_runs(struct dm_transaction_manager *tm,
- const __le64 *value_le, unsigned count, dm_tm_run_fn fn);
+ const __le64 *value_le, unsigned int count, dm_tm_run_fn fn);
int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b, uint32_t *result);
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 8cf27e2654fc..f1d9ee2a78b0 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -5514,7 +5514,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
* .port_set_upstream_port method.
*/
.set_egress_port = mv88e6393x_set_egress_port,
- .watchdog_ops = &mv88e6390_watchdog_ops,
+ .watchdog_ops = &mv88e6393x_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,
.pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6352_g1_reset,
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index fa65ecd9cb85..ec49939968fa 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -931,6 +931,26 @@ const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
.irq_free = mv88e6390_watchdog_free,
};
+static int mv88e6393x_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
+{
+ mv88e6390_watchdog_action(chip, irq);
+
+ /* Fix for clearing the force WD event bit.
+ * Unreleased erratum on mv88e6393x.
+ */
+ mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
+ MV88E6390_G2_WDOG_CTL_UPDATE |
+ MV88E6390_G2_WDOG_CTL_PTR_EVENT);
+
+ return IRQ_HANDLED;
+}
+
+const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops = {
+ .irq_action = mv88e6393x_watchdog_action,
+ .irq_setup = mv88e6390_watchdog_setup,
+ .irq_free = mv88e6390_watchdog_free,
+};
+
static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id)
{
struct mv88e6xxx_chip *chip = dev_id;
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index 7536b8b0ad01..c05fad5c9f19 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -363,6 +363,7 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;
extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
+extern const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops;
extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops;
extern const struct mv88e6xxx_avb_ops mv88e6352_avb_ops;
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 160735484465..458149a77ebe 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -47,6 +47,8 @@
#define GVE_RX_BUFFER_SIZE_DQO 2048
+#define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182
+
/* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */
struct gve_rx_desc_queue {
struct gve_rx_desc *desc_ring; /* the descriptor ring */
diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c
index 4888bf05fbed..5e11b8236754 100644
--- a/drivers/net/ethernet/google/gve/gve_tx.c
+++ b/drivers/net/ethernet/google/gve/gve_tx.c
@@ -284,8 +284,8 @@ static inline int gve_skb_fifo_bytes_required(struct gve_tx_ring *tx,
int bytes;
int hlen;
- hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) +
- tcp_hdrlen(skb) : skb_headlen(skb);
+ hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) + tcp_hdrlen(skb) :
+ min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len);
pad_bytes = gve_tx_fifo_pad_alloc_one_frag(&tx->tx_fifo,
hlen);
@@ -454,13 +454,11 @@ static int gve_tx_add_skb_copy(struct gve_priv *priv, struct gve_tx_ring *tx, st
pkt_desc = &tx->desc[idx];
l4_hdr_offset = skb_checksum_start_offset(skb);
- /* If the skb is gso, then we want the tcp header in the first segment
- * otherwise we want the linear portion of the skb (which will contain
- * the checksum because skb->csum_start and skb->csum_offset are given
- * relative to skb->head) in the first segment.
+ /* If the skb is gso, then we want the tcp header alone in the first segment
+ * otherwise we want the minimum required by the gVNIC spec.
*/
hlen = is_gso ? l4_hdr_offset + tcp_hdrlen(skb) :
- skb_headlen(skb);
+ min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len);
info->skb = skb;
/* We don't want to split the header, so if necessary, pad to the end
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
index a2645ff3100e..7f7260407972 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
@@ -541,6 +541,21 @@ static void ice_vc_fdir_rem_prof_all(struct ice_vf *vf)
}
}
+/**
+ * ice_vc_fdir_reset_cnt_all - reset all FDIR counters for this VF FDIR
+ * @fdir: pointer to the VF FDIR structure
+ */
+static void ice_vc_fdir_reset_cnt_all(struct ice_vf_fdir *fdir)
+{
+ enum ice_fltr_ptype flow;
+
+ for (flow = ICE_FLTR_PTYPE_NONF_NONE;
+ flow < ICE_FLTR_PTYPE_MAX; flow++) {
+ fdir->fdir_fltr_cnt[flow][0] = 0;
+ fdir->fdir_fltr_cnt[flow][1] = 0;
+ }
+}
+
/**
* ice_vc_fdir_has_prof_conflict
* @vf: pointer to the VF structure
@@ -1871,7 +1886,7 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)
v_ret = VIRTCHNL_STATUS_SUCCESS;
stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id);
- goto err_free_conf;
+ goto err_rem_entry;
}
ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun);
@@ -1880,15 +1895,16 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)
stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",
vf->vf_id, ret);
- goto err_rem_entry;
+ goto err_clr_irq;
}
exit:
kfree(stat);
return ret;
-err_rem_entry:
+err_clr_irq:
ice_vc_fdir_clear_irq_ctx(vf);
+err_rem_entry:
ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);
err_free_conf:
devm_kfree(dev, conf);
@@ -1997,6 +2013,7 @@ void ice_vf_fdir_init(struct ice_vf *vf)
spin_lock_init(&fdir->ctx_lock);
fdir->ctx_irq.flags = 0;
fdir->ctx_done.flags = 0;
+ ice_vc_fdir_reset_cnt_all(fdir);
}
/**
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
index 13aa919633b4..ab9f876b6df7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
@@ -251,7 +251,6 @@ static void intel_speed_mode_2500(struct net_device *ndev, void *intel_data)
priv->plat->mdio_bus_data->xpcs_an_inband = false;
} else {
priv->plat->max_speed = 1000;
- priv->plat->mdio_bus_data->xpcs_an_inband = true;
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 93321437f093..fa3ce3b0d9a5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1132,20 +1132,26 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
static int stmmac_init_phy(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ struct fwnode_handle *phy_fwnode;
struct fwnode_handle *fwnode;
int ret;
+ if (!phylink_expects_phy(priv->phylink))
+ return 0;
+
fwnode = of_fwnode_handle(priv->plat->phylink_node);
if (!fwnode)
fwnode = dev_fwnode(priv->device);
if (fwnode)
- ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
+ phy_fwnode = fwnode_get_phy_node(fwnode);
+ else
+ phy_fwnode = NULL;
/* Some DT bindings do not set-up the PHY handle. Let's try to
* manually parse it
*/
- if (!fwnode || ret) {
+ if (!phy_fwnode || IS_ERR(phy_fwnode)) {
int addr = priv->plat->phy_addr;
struct phy_device *phydev;
@@ -1161,6 +1167,9 @@ static int stmmac_init_phy(struct net_device *dev)
}
ret = phylink_connect_phy(priv->phylink, phydev);
+ } else {
+ fwnode_handle_put(phy_fwnode);
+ ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
}
if (!priv->plat->pmt) {
@@ -6618,6 +6627,8 @@ int stmmac_xdp_open(struct net_device *dev)
goto init_error;
}
+ stmmac_reset_queues_param(priv);
+
/* DMA CSR Channel configuration */
for (chan = 0; chan < dma_csr_ch; chan++) {
stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
@@ -6944,7 +6955,7 @@ static void stmmac_napi_del(struct net_device *dev)
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
{
struct stmmac_priv *priv = netdev_priv(dev);
- int ret = 0;
+ int ret = 0, i;
if (netif_running(dev))
stmmac_release(dev);
@@ -6953,6 +6964,10 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
priv->plat->rx_queues_to_use = rx_cnt;
priv->plat->tx_queues_to_use = tx_cnt;
+ if (!netif_is_rxfh_configured(dev))
+ for (i = 0; i < ARRAY_SIZE(priv->rss.table); i++)
+ priv->rss.table[i] = ethtool_rxfh_indir_default(i,
+ rx_cnt);
stmmac_napi_add(dev);
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 8ff1c84a23ce..25466cbdc16b 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2819,7 +2819,8 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
am65_cpsw_nuss_phylink_cleanup(common);
am65_cpts_release(common->cpts);
err_of_clear:
- of_platform_device_destroy(common->mdio_dev, NULL);
+ if (common->mdio_dev)
+ of_platform_device_destroy(common->mdio_dev, NULL);
err_pm_clear:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
@@ -2848,7 +2849,8 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev)
am65_cpsw_nuss_phylink_cleanup(common);
am65_cpts_release(common->cpts);
- of_platform_device_destroy(common->mdio_dev, NULL);
+ if (common->mdio_dev)
+ of_platform_device_destroy(common->mdio_dev, NULL);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index a202ce6611fd..4073e8243df3 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1552,6 +1552,25 @@ void phylink_destroy(struct phylink *pl)
}
EXPORT_SYMBOL_GPL(phylink_destroy);
+/**
+ * phylink_expects_phy() - Determine if phylink expects a phy to be attached
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * When using fixed-link mode, or in-band mode with 1000base-X or 2500base-X,
+ * no PHY is needed.
+ *
+ * Returns true if phylink will be expecting a PHY.
+ */
+bool phylink_expects_phy(struct phylink *pl)
+{
+ if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
+ (pl->cfg_link_an_mode == MLO_AN_INBAND &&
+ phy_interface_mode_is_8023z(pl->link_config.interface)))
+ return false;
+ return true;
+}
+EXPORT_SYMBOL_GPL(phylink_expects_phy);
+
static void phylink_phy_change(struct phy_device *phydev, bool up)
{
struct phylink *pl = phydev->phylink;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index d0daef674e72..e300278ea38c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -991,15 +991,34 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
-static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
- int val)
+static void brcmf_sdiod_acpi_save_power_manageable(struct brcmf_sdio_dev *sdiodev)
{
#if IS_ENABLED(CONFIG_ACPI)
struct acpi_device *adev;
- adev = ACPI_COMPANION(dev);
+ adev = ACPI_COMPANION(&sdiodev->func1->dev);
if (adev)
- adev->flags.power_manageable = 0;
+ sdiodev->func1_power_manageable = adev->flags.power_manageable;
+
+ adev = ACPI_COMPANION(&sdiodev->func2->dev);
+ if (adev)
+ sdiodev->func2_power_manageable = adev->flags.power_manageable;
+#endif
+}
+
+static void brcmf_sdiod_acpi_set_power_manageable(struct brcmf_sdio_dev *sdiodev,
+ int enable)
+{
+#if IS_ENABLED(CONFIG_ACPI)
+ struct acpi_device *adev;
+
+ adev = ACPI_COMPANION(&sdiodev->func1->dev);
+ if (adev)
+ adev->flags.power_manageable = enable ? sdiodev->func1_power_manageable : 0;
+
+ adev = ACPI_COMPANION(&sdiodev->func2->dev);
+ if (adev)
+ adev->flags.power_manageable = enable ? sdiodev->func2_power_manageable : 0;
#endif
}
@@ -1009,7 +1028,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
int err;
struct brcmf_sdio_dev *sdiodev;
struct brcmf_bus *bus_if;
- struct device *dev;
brcmf_dbg(SDIO, "Enter\n");
brcmf_dbg(SDIO, "Class=%x\n", func->class);
@@ -1017,14 +1035,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
- dev = &func->dev;
-
/* Set MMC_QUIRK_LENIENT_FN0 for this card */
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
- /* prohibit ACPI power management for this device */
- brcmf_sdiod_acpi_set_power_manageable(dev, 0);
-
/* Consume func num 1 but dont do anything with it. */
if (func->num == 1)
return 0;
@@ -1055,6 +1068,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
dev_set_drvdata(&sdiodev->func1->dev, bus_if);
sdiodev->dev = &sdiodev->func1->dev;
+ brcmf_sdiod_acpi_save_power_manageable(sdiodev);
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
@@ -1120,6 +1134,8 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
if (sdiodev->settings->bus.sdio.oob_irq_supported ||
pm_caps & MMC_PM_WAKE_SDIO_IRQ) {
+ /* Stop ACPI from turning off the device when wowl is enabled */
+ brcmf_sdiod_acpi_set_power_manageable(sdiodev, !enabled);
sdiodev->wowl_enabled = enabled;
brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
return;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index b76d34d36bde..0d18ed15b403 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -188,6 +188,8 @@ struct brcmf_sdio_dev {
char nvram_name[BRCMF_FW_NAME_LEN];
char clm_name[BRCMF_FW_NAME_LEN];
bool wowl_enabled;
+ bool func1_power_manageable;
+ bool func2_power_manageable;
enum brcmf_sdiod_state state;
struct brcmf_sdiod_freezer *freezer;
const struct firmware *clm_fw;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index ca50feb0b3a9..1b1358c6bb46 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -512,15 +512,15 @@ mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
return -EOPNOTSUPP;
- if (cmd == SET_KEY) {
- key->hw_key_idx = wcid->idx;
- wcid->hw_key_idx = idx;
- } else {
+ if (cmd != SET_KEY) {
if (idx == wcid->hw_key_idx)
wcid->hw_key_idx = -1;
- key = NULL;
+ return 0;
}
+
+ key->hw_key_idx = wcid->idx;
+ wcid->hw_key_idx = idx;
mt76_wcid_key_setup(&dev->mt76, wcid, key);
return mt7603_wtbl_set_key(dev, wcid->idx, key);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index 2ce1705c0f43..a0412a29fb49 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -1180,8 +1180,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);
static int
mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key,
- enum mt76_cipher_type cipher, u16 cipher_mask,
- enum set_key_cmd cmd)
+ enum mt76_cipher_type cipher, u16 cipher_mask)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
u8 data[32] = {};
@@ -1190,27 +1189,18 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
return -EINVAL;
mt76_rr_copy(dev, addr, data, sizeof(data));
- if (cmd == SET_KEY) {
- if (cipher == MT_CIPHER_TKIP) {
- /* Rx/Tx MIC keys are swapped */
- memcpy(data, key->key, 16);
- memcpy(data + 16, key->key + 24, 8);
- memcpy(data + 24, key->key + 16, 8);
- } else {
- if (cipher_mask == BIT(cipher))
- memcpy(data, key->key, key->keylen);
- else if (cipher != MT_CIPHER_BIP_CMAC_128)
- memcpy(data, key->key, 16);
- if (cipher == MT_CIPHER_BIP_CMAC_128)
- memcpy(data + 16, key->key, 16);
- }
+ if (cipher == MT_CIPHER_TKIP) {
+ /* Rx/Tx MIC keys are swapped */
+ memcpy(data, key->key, 16);
+ memcpy(data + 16, key->key + 24, 8);
+ memcpy(data + 24, key->key + 16, 8);
} else {
+ if (cipher_mask == BIT(cipher))
+ memcpy(data, key->key, key->keylen);
+ else if (cipher != MT_CIPHER_BIP_CMAC_128)
+ memcpy(data, key->key, 16);
if (cipher == MT_CIPHER_BIP_CMAC_128)
- memset(data + 16, 0, 16);
- else if (cipher_mask)
- memset(data, 0, 16);
- if (!cipher_mask)
- memset(data, 0, sizeof(data));
+ memcpy(data + 16, key->key, 16);
}
mt76_wr_copy(dev, addr, data, sizeof(data));
@@ -1221,7 +1211,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static int
mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
enum mt76_cipher_type cipher, u16 cipher_mask,
- int keyidx, enum set_key_cmd cmd)
+ int keyidx)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;
@@ -1240,9 +1230,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
else
w0 &= ~MT_WTBL_W0_RX_IK_VALID;
- if (cmd == SET_KEY &&
- (cipher != MT_CIPHER_BIP_CMAC_128 ||
- cipher_mask == BIT(cipher))) {
+ if (cipher != MT_CIPHER_BIP_CMAC_128 || cipher_mask == BIT(cipher)) {
w0 &= ~MT_WTBL_W0_KEY_IDX;
w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
}
@@ -1259,19 +1247,10 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static void
mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
- enum mt76_cipher_type cipher, u16 cipher_mask,
- enum set_key_cmd cmd)
+ enum mt76_cipher_type cipher, u16 cipher_mask)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
- if (!cipher_mask) {
- mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
- return;
- }
-
- if (cmd != SET_KEY)
- return;
-
if (cipher == MT_CIPHER_BIP_CMAC_128 &&
cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))
return;
@@ -1282,8 +1261,7 @@ mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key,
- enum set_key_cmd cmd)
+ struct ieee80211_key_conf *key)
{
enum mt76_cipher_type cipher;
u16 cipher_mask = wcid->cipher;
@@ -1293,19 +1271,14 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
if (cipher == MT_CIPHER_NONE)
return -EOPNOTSUPP;
- if (cmd == SET_KEY)
- cipher_mask |= BIT(cipher);
- else
- cipher_mask &= ~BIT(cipher);
-
- mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd);
- err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask,
- cmd);
+ cipher_mask |= BIT(cipher);
+ mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask);
+ err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask);
if (err < 0)
return err;
err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,
- key->keyidx, cmd);
+ key->keyidx);
if (err < 0)
return err;
@@ -1316,13 +1289,12 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key,
- enum set_key_cmd cmd)
+ struct ieee80211_key_conf *key)
{
int err;
spin_lock_bh(&dev->mt76.lock);
- err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+ err = __mt7615_mac_wtbl_set_key(dev, wcid, key);
spin_unlock_bh(&dev->mt76.lock);
return err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index 8d4733f87cda..a3b0d4e9146a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -391,18 +391,17 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (cmd == SET_KEY)
*wcid_keyidx = idx;
- else if (idx == *wcid_keyidx)
- *wcid_keyidx = -1;
- else
+ else {
+ if (idx == *wcid_keyidx)
+ *wcid_keyidx = -1;
goto out;
+ }
- mt76_wcid_key_setup(&dev->mt76, wcid,
- cmd == SET_KEY ? key : NULL);
-
+ mt76_wcid_key_setup(&dev->mt76, wcid, key);
if (mt76_is_mmio(&dev->mt76))
- err = mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+ err = mt7615_mac_wtbl_set_key(dev, wcid, key);
else
- err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+ err = __mt7615_mac_wtbl_set_key(dev, wcid, key);
out:
mt7615_mutex_release(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index 060d52c81d9e..c0e62082b62d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -482,11 +482,9 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
void mt7615_mac_set_timing(struct mt7615_phy *phy);
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key,
- enum set_key_cmd cmd);
+ struct ieee80211_key_conf *key);
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key,
- enum set_key_cmd cmd);
+ struct ieee80211_key_conf *key);
void mt7615_mac_reset_work(struct work_struct *work);
u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 604ddcc21123..324535a0dd6d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -455,20 +455,20 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
wcid = msta ? &msta->wcid : &mvif->group_wcid;
- if (cmd == SET_KEY) {
- key->hw_key_idx = wcid->idx;
- wcid->hw_key_idx = idx;
- if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
- key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
- wcid->sw_iv = true;
- }
- } else {
+ if (cmd != SET_KEY) {
if (idx == wcid->hw_key_idx) {
wcid->hw_key_idx = -1;
wcid->sw_iv = false;
}
- key = NULL;
+ return 0;
+ }
+
+ key->hw_key_idx = wcid->idx;
+ wcid->hw_key_idx = idx;
+ if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
+ wcid->sw_iv = true;
}
mt76_wcid_key_setup(&dev->mt76, wcid, key);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 060cb88e82e3..bda26bd62412 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -393,16 +393,15 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mt7915_mcu_add_bss_info(phy, vif, true);
}
- if (cmd == SET_KEY)
+ if (cmd == SET_KEY) {
*wcid_keyidx = idx;
- else if (idx == *wcid_keyidx)
- *wcid_keyidx = -1;
- else
+ } else {
+ if (idx == *wcid_keyidx)
+ *wcid_keyidx = -1;
goto out;
+ }
- mt76_wcid_key_setup(&dev->mt76, wcid,
- cmd == SET_KEY ? key : NULL);
-
+ mt76_wcid_key_setup(&dev->mt76, wcid, key);
err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
key, MCU_EXT_CMD(STA_REC_UPDATE),
&msta->wcid, cmd);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 111d9221b94f..60fbbd1ac2f7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -464,16 +464,15 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mt7921_mutex_acquire(dev);
- if (cmd == SET_KEY)
+ if (cmd == SET_KEY) {
*wcid_keyidx = idx;
- else if (idx == *wcid_keyidx)
- *wcid_keyidx = -1;
- else
+ } else {
+ if (idx == *wcid_keyidx)
+ *wcid_keyidx = -1;
goto out;
+ }
- mt76_wcid_key_setup(&dev->mt76, wcid,
- cmd == SET_KEY ? key : NULL);
-
+ mt76_wcid_key_setup(&dev->mt76, wcid, key);
err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
key, MCU_UNI_CMD(STA_REC_UPDATE),
&msta->wcid, cmd);
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index a95e48b51da6..cb71ce3413c2 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1711,6 +1711,9 @@ static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns)
struct request_queue *queue = disk->queue;
u32 size = queue_logical_block_size(queue);
+ if (ctrl->dmrsl && ctrl->dmrsl <= nvme_sect_to_lba(ns, UINT_MAX))
+ ctrl->max_discard_sectors = nvme_lba_to_sect(ns, ctrl->dmrsl);
+
if (ctrl->max_discard_sectors == 0) {
blk_queue_max_discard_sectors(queue, 0);
return;
@@ -1725,9 +1728,6 @@ static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns)
if (queue->limits.max_discard_sectors)
return;
- if (ctrl->dmrsl && ctrl->dmrsl <= nvme_sect_to_lba(ns, UINT_MAX))
- ctrl->max_discard_sectors = nvme_lba_to_sect(ns, ctrl->dmrsl);
-
blk_queue_max_discard_sectors(queue, ctrl->max_discard_sectors);
blk_queue_max_discard_segments(queue, ctrl->max_discard_segments);
diff --git a/drivers/pci/doe.c b/drivers/pci/doe.c
index 66d9ab288646..e5e9b287b976 100644
--- a/drivers/pci/doe.c
+++ b/drivers/pci/doe.c
@@ -128,7 +128,7 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb,
return -EIO;
/* Length is 2 DW of header + length of payload in DW */
- length = 2 + task->request_pl_sz / sizeof(u32);
+ length = 2 + task->request_pl_sz / sizeof(__le32);
if (length > PCI_DOE_MAX_LENGTH)
return -EIO;
if (length == PCI_DOE_MAX_LENGTH)
@@ -141,9 +141,9 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb,
pci_write_config_dword(pdev, offset + PCI_DOE_WRITE,
FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH,
length));
- for (i = 0; i < task->request_pl_sz / sizeof(u32); i++)
+ for (i = 0; i < task->request_pl_sz / sizeof(__le32); i++)
pci_write_config_dword(pdev, offset + PCI_DOE_WRITE,
- task->request_pl[i]);
+ le32_to_cpu(task->request_pl[i]));
pci_doe_write_ctrl(doe_mb, PCI_DOE_CTRL_GO);
@@ -195,11 +195,11 @@ static int pci_doe_recv_resp(struct pci_doe_mb *doe_mb, struct pci_doe_task *tas
/* First 2 dwords have already been read */
length -= 2;
- payload_length = min(length, task->response_pl_sz / sizeof(u32));
+ payload_length = min(length, task->response_pl_sz / sizeof(__le32));
/* Read the rest of the response payload */
for (i = 0; i < payload_length; i++) {
- pci_read_config_dword(pdev, offset + PCI_DOE_READ,
- &task->response_pl[i]);
+ pci_read_config_dword(pdev, offset + PCI_DOE_READ, &val);
+ task->response_pl[i] = cpu_to_le32(val);
/* Prior to the last ack, ensure Data Object Ready */
if (i == (payload_length - 1) && !pci_doe_data_obj_ready(doe_mb))
return -EIO;
@@ -217,13 +217,14 @@ static int pci_doe_recv_resp(struct pci_doe_mb *doe_mb, struct pci_doe_task *tas
if (FIELD_GET(PCI_DOE_STATUS_ERROR, val))
return -EIO;
- return min(length, task->response_pl_sz / sizeof(u32)) * sizeof(u32);
+ return min(length, task->response_pl_sz / sizeof(__le32)) * sizeof(__le32);
}
static void signal_task_complete(struct pci_doe_task *task, int rv)
{
task->rv = rv;
task->complete(task);
+ destroy_work_on_stack(&task->work);
}
static void signal_task_abort(struct pci_doe_task *task, int rv)
@@ -317,14 +318,16 @@ static int pci_doe_discovery(struct pci_doe_mb *doe_mb, u8 *index, u16 *vid,
{
u32 request_pl = FIELD_PREP(PCI_DOE_DATA_OBJECT_DISC_REQ_3_INDEX,
*index);
+ __le32 request_pl_le = cpu_to_le32(request_pl);
+ __le32 response_pl_le;
u32 response_pl;
DECLARE_COMPLETION_ONSTACK(c);
struct pci_doe_task task = {
.prot.vid = PCI_VENDOR_ID_PCI_SIG,
.prot.type = PCI_DOE_PROTOCOL_DISCOVERY,
- .request_pl = &request_pl,
+ .request_pl = &request_pl_le,
.request_pl_sz = sizeof(request_pl),
- .response_pl = &response_pl,
+ .response_pl = &response_pl_le,
.response_pl_sz = sizeof(response_pl),
.complete = pci_doe_task_complete,
.private = &c,
@@ -340,6 +343,7 @@ static int pci_doe_discovery(struct pci_doe_mb *doe_mb, u8 *index, u16 *vid,
if (task.rv != sizeof(response_pl))
return -EIO;
+ response_pl = le32_to_cpu(response_pl_le);
*vid = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_RSP_3_VID, response_pl);
*protocol = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL,
response_pl);
@@ -520,6 +524,8 @@ EXPORT_SYMBOL_GPL(pci_doe_supports_prot);
* task->complete will be called when the state machine is done processing this
* task.
*
+ * @task must be allocated on the stack.
+ *
* Excess data will be discarded.
*
* RETURNS: 0 when task has been successfully queued, -ERRNO on error
@@ -533,15 +539,15 @@ int pci_doe_submit_task(struct pci_doe_mb *doe_mb, struct pci_doe_task *task)
* DOE requests must be a whole number of DW and the response needs to
* be big enough for at least 1 DW
*/
- if (task->request_pl_sz % sizeof(u32) ||
- task->response_pl_sz < sizeof(u32))
+ if (task->request_pl_sz % sizeof(__le32) ||
+ task->response_pl_sz < sizeof(__le32))
return -EINVAL;
if (test_bit(PCI_DOE_FLAG_DEAD, &doe_mb->flags))
return -EIO;
task->doe_mb = doe_mb;
- INIT_WORK(&task->work, doe_statemachine_work);
+ INIT_WORK_ONSTACK(&task->work, doe_statemachine_work);
queue_work(doe_mb->work_queue, &task->work);
return 0;
}
diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
index 74af3e593b2c..336b9029d151 100644
--- a/drivers/platform/x86/think-lmi.c
+++ b/drivers/platform/x86/think-lmi.c
@@ -920,7 +920,7 @@ static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *at
static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
- char *item, *value;
+ char *item, *value, *p;
int ret;
ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID);
@@ -930,10 +930,15 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a
/* validate and split from `item,value` -> `value` */
value = strpbrk(item, ",");
if (!value || value == item || !strlen(value + 1))
- return -EINVAL;
-
- ret = sysfs_emit(buf, "%s\n", value + 1);
+ ret = -EINVAL;
+ else {
+ /* On Workstations remove the Options part after the value */
+ p = strchrnul(value, ';');
+ *p = '\0';
+ ret = sysfs_emit(buf, "%s\n", value + 1);
+ }
kfree(item);
+
return ret;
}
@@ -1457,10 +1462,10 @@ static int tlmi_analyze(void)
* name string.
* Try and pull that out if it's available.
*/
- char *item, *optstart, *optend;
+ char *optitem, *optstart, *optend;
- if (!tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID)) {
- optstart = strstr(item, "[Optional:");
+ if (!tlmi_setting(setting->index, &optitem, LENOVO_BIOS_SETTING_GUID)) {
+ optstart = strstr(optitem, "[Optional:");
if (optstart) {
optstart += strlen("[Optional:");
optend = strstr(optstart, "]");
@@ -1469,6 +1474,7 @@ static int tlmi_analyze(void)
kstrndup(optstart, optend - optstart,
GFP_KERNEL);
}
+ kfree(optitem);
}
}
/*
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
index 8e00a4286145..cdbc23649032 100644
--- a/drivers/pwm/pwm-atmel.c
+++ b/drivers/pwm/pwm-atmel.c
@@ -356,8 +356,8 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
-static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
u32 sr, cmr;
@@ -396,6 +396,8 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->polarity = PWM_POLARITY_INVERSED;
else
state->polarity = PWM_POLARITY_NORMAL;
+
+ return 0;
}
static const struct pwm_ops atmel_pwm_ops = {
diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c
index 7251037d4dd5..97ec131eb7c1 100644
--- a/drivers/pwm/pwm-bcm-iproc.c
+++ b/drivers/pwm/pwm-bcm-iproc.c
@@ -68,8 +68,8 @@ static void iproc_pwmc_disable(struct iproc_pwmc *ip, unsigned int channel)
ndelay(400);
}
-static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct iproc_pwmc *ip = to_iproc_pwmc(chip);
u64 tmp, multi, rate;
@@ -91,7 +91,7 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
if (rate == 0) {
state->period = 0;
state->duty_cycle = 0;
- return;
+ return 0;
}
value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
@@ -107,6 +107,8 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
value = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm));
tmp = (value & IPROC_PWM_PERIOD_MAX) * multi;
state->duty_cycle = div64_u64(tmp, rate);
+
+ return 0;
}
static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c
index 7b357d1cf642..4099850117ba 100644
--- a/drivers/pwm/pwm-crc.c
+++ b/drivers/pwm/pwm-crc.c
@@ -121,8 +121,8 @@ static int crc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
-static void crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct crystalcove_pwm *crc_pwm = to_crc_pwm(chip);
struct device *dev = crc_pwm->chip.dev;
@@ -132,13 +132,13 @@ static void crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
error = regmap_read(crc_pwm->regmap, PWM0_CLK_DIV, &clk_div_reg);
if (error) {
dev_err(dev, "Error reading PWM0_CLK_DIV %d\n", error);
- return;
+ return 0;
}
error = regmap_read(crc_pwm->regmap, PWM0_DUTY_CYCLE, &duty_cycle_reg);
if (error) {
dev_err(dev, "Error reading PWM0_DUTY_CYCLE %d\n", error);
- return;
+ return 0;
}
clk_div = (clk_div_reg & ~PWM_OUTPUT_ENABLE) + 1;
@@ -149,6 +149,8 @@ static void crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
DIV_ROUND_UP_ULL(duty_cycle_reg * state->period, PWM_MAX_LEVEL);
state->polarity = PWM_POLARITY_NORMAL;
state->enabled = !!(clk_div_reg & PWM_OUTPUT_ENABLE);
+
+ return 0;
}
static const struct pwm_ops crc_pwm_ops = {
diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c
index 7f10f56c3eb6..e55bc36ed497 100644
--- a/drivers/pwm/pwm-cros-ec.c
+++ b/drivers/pwm/pwm-cros-ec.c
@@ -183,8 +183,8 @@ static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
-static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
struct cros_ec_pwm *channel = pwm_get_chip_data(pwm);
@@ -193,11 +193,12 @@ static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
ret = cros_ec_pwm_get_duty(ec_pwm, pwm->hwpwm);
if (ret < 0) {
dev_err(chip->dev, "error getting initial duty: %d\n", ret);
- return;
+ return 0;
}
state->enabled = (ret > 0);
state->period = EC_PWM_MAX_DUTY;
+ state->polarity = PWM_POLARITY_NORMAL;
/*
* Note that "disabled" and "duty cycle == 0" are treated the same. If
@@ -212,6 +213,8 @@ static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->duty_cycle = channel->duty_cycle;
else
state->duty_cycle = ret;
+
+ return 0;
}
static struct pwm_device *
diff --git a/drivers/pwm/pwm-dwc.c b/drivers/pwm/pwm-dwc.c
index 7568300bb11e..bd2308812096 100644
--- a/drivers/pwm/pwm-dwc.c
+++ b/drivers/pwm/pwm-dwc.c
@@ -163,8 +163,8 @@ static int dwc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
-static void dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct dwc_pwm *dwc = to_dwc_pwm(chip);
u64 duty, period;
@@ -188,6 +188,8 @@ static void dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->polarity = PWM_POLARITY_INVERSED;
pm_runtime_put_sync(chip->dev);
+
+ return 0;
}
static const struct pwm_ops dwc_pwm_ops = {
diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c
index 333f1b18ff4e..1b9274c5ad87 100644
--- a/drivers/pwm/pwm-hibvt.c
+++ b/drivers/pwm/pwm-hibvt.c
@@ -128,8 +128,8 @@ static void hibvt_pwm_set_polarity(struct pwm_chip *chip,
PWM_POLARITY_MASK, (0x0 << PWM_POLARITY_SHIFT));
}
-static void hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip);
void __iomem *base;
@@ -146,6 +146,9 @@ static void hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
value = readl(base + PWM_CTRL_ADDR(pwm->hwpwm));
state->enabled = (PWM_ENABLE_MASK & value);
+ state->polarity = (PWM_POLARITY_MASK & value) ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
+
+ return 0;
}
static int hibvt_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c
index e5e7b7c339a8..ed1aad96fff0 100644
--- a/drivers/pwm/pwm-imx-tpm.c
+++ b/drivers/pwm/pwm-imx-tpm.c
@@ -132,9 +132,9 @@ static int pwm_imx_tpm_round_state(struct pwm_chip *chip,
return 0;
}
-static void pwm_imx_tpm_get_state(struct pwm_chip *chip,
- struct pwm_device *pwm,
- struct pwm_state *state)
+static int pwm_imx_tpm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct imx_tpm_pwm_chip *tpm = to_imx_tpm_pwm_chip(chip);
u32 rate, val, prescale;
@@ -164,6 +164,8 @@ static void pwm_imx_tpm_get_state(struct pwm_chip *chip,
/* get channel status */
state->enabled = FIELD_GET(PWM_IMX_TPM_CnSC_ELS, val) ? true : false;
+
+ return 0;
}
/* this function is supposed to be called with mutex hold */
diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
index ea91a2f81a9f..3a22c2fddc45 100644
--- a/drivers/pwm/pwm-imx27.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -118,8 +118,8 @@ static void pwm_imx27_clk_disable_unprepare(struct pwm_imx27_chip *imx)
clk_disable_unprepare(imx->clk_ipg);
}
-static void pwm_imx27_get_state(struct pwm_chip *chip,
- struct pwm_device *pwm, struct pwm_state *state)
+static int pwm_imx27_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm, struct pwm_state *state)
{
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
u32 period, prescaler, pwm_clk, val;
@@ -128,7 +128,7 @@ static void pwm_imx27_get_state(struct pwm_chip *chip,
ret = pwm_imx27_clk_prepare_enable(imx);
if (ret < 0)
- return;
+ return 0;
val = readl(imx->mmio_base + MX3_PWMCR);
@@ -170,6 +170,8 @@ static void pwm_imx27_get_state(struct pwm_chip *chip,
state->duty_cycle = DIV_ROUND_UP_ULL(tmp, pwm_clk);
pwm_imx27_clk_disable_unprepare(imx);
+
+ return 0;
}
static void pwm_imx27_sw_reset(struct pwm_chip *chip)
diff --git a/drivers/pwm/pwm-intel-lgm.c b/drivers/pwm/pwm-intel-lgm.c
index b66c35074087..0cd7dd548e82 100644
--- a/drivers/pwm/pwm-intel-lgm.c
+++ b/drivers/pwm/pwm-intel-lgm.c
@@ -86,8 +86,8 @@ static int lgm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return lgm_pwm_enable(chip, 1);
}
-static void lgm_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int lgm_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct lgm_pwm_chip *pc = to_lgm_pwm_chip(chip);
u32 duty, val;
@@ -100,6 +100,8 @@ static void lgm_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
regmap_read(pc->regmap, LGM_PWM_FAN_CON0, &val);
duty = FIELD_GET(LGM_PWM_FAN_DC_MSK, val);
state->duty_cycle = DIV_ROUND_UP(duty * pc->period, LGM_PWM_MAX_DUTY_CYCLE);
+
+ return 0;
}
static const struct pwm_ops lgm_pwm_ops = {
diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c
index 54bd95a5cab0..aeb19a274acc 100644
--- a/drivers/pwm/pwm-iqs620a.c
+++ b/drivers/pwm/pwm-iqs620a.c
@@ -104,8 +104,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
-static void iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct iqs620_pwm_private *iqs620_pwm;
@@ -126,6 +126,9 @@ static void iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
mutex_unlock(&iqs620_pwm->lock);
state->period = IQS620_PWM_PERIOD_NS;
+ state->polarity = PWM_POLARITY_NORMAL;
+
+ return 0;
}
static int iqs620_pwm_notifier(struct notifier_block *notifier,
diff --git a/drivers/pwm/pwm-keembay.c b/drivers/pwm/pwm-keembay.c
index 733811b05721..ac02d8bb4a0b 100644
--- a/drivers/pwm/pwm-keembay.c
+++ b/drivers/pwm/pwm-keembay.c
@@ -89,8 +89,8 @@ static void keembay_pwm_disable(struct keembay_pwm *priv, int ch)
KMB_PWM_LEADIN_OFFSET(ch));
}
-static void keembay_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int keembay_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct keembay_pwm *priv = to_keembay_pwm_dev(chip);
unsigned long long high, low;
@@ -113,6 +113,8 @@ static void keembay_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->duty_cycle = DIV_ROUND_UP_ULL(high, clk_rate);
state->period = DIV_ROUND_UP_ULL(high + low, clk_rate);
state->polarity = PWM_POLARITY_NORMAL;
+
+ return 0;
}
static int keembay_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index accdef5dd58e..81ac297b8ba5 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -205,8 +205,8 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
-static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct pwm_lpss_chip *lpwm = to_lpwm(chip);
unsigned long base_unit_range;
@@ -236,6 +236,8 @@ static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->enabled = !!(ctrl & PWM_ENABLE);
pm_runtime_put(chip->dev);
+
+ return 0;
}
static const struct pwm_ops pwm_lpss_ops = {
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
index 57112f438c6d..5cd7b90872c6 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -162,6 +162,12 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
duty = state->duty_cycle;
period = state->period;
+ /*
+ * Note this is wrong. The result is an output wave that isn't really
+ * inverted and so is wrongly identified by .get_state as normal.
+ * Fixing this needs some care however as some machines might rely on
+ * this.
+ */
if (state->polarity == PWM_POLARITY_INVERSED)
duty = period - duty;
@@ -318,8 +324,8 @@ static unsigned int meson_pwm_cnt_to_ns(struct pwm_chip *chip,
return cnt * fin_ns * (channel->pre_div + 1);
}
-static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct meson_pwm *meson = to_meson_pwm(chip);
struct meson_pwm_channel_data *channel_data;
@@ -327,7 +333,7 @@ static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
u32 value, tmp;
if (!state)
- return;
+ return 0;
channel = &meson->channels[pwm->hwpwm];
channel_data = &meson_pwm_per_channel_data[pwm->hwpwm];
@@ -357,6 +363,10 @@ static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->period = 0;
state->duty_cycle = 0;
}
+
+ state->polarity = PWM_POLARITY_NORMAL;
+
+ return 0;
}
static const struct pwm_ops meson_pwm_ops = {
diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c
index 3fbb4bae93a4..ccf0ccdef29d 100644
--- a/drivers/pwm/pwm-mtk-disp.c
+++ b/drivers/pwm/pwm-mtk-disp.c
@@ -172,9 +172,9 @@ static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
-static void mtk_disp_pwm_get_state(struct pwm_chip *chip,
- struct pwm_device *pwm,
- struct pwm_state *state)
+static int mtk_disp_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
u64 rate, period, high_width;
@@ -184,14 +184,14 @@ static void mtk_disp_pwm_get_state(struct pwm_chip *chip,
err = clk_prepare_enable(mdp->clk_main);
if (err < 0) {
dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err));
- return;
+ return 0;
}
err = clk_prepare_enable(mdp->clk_mm);
if (err < 0) {
dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err));
clk_disable_unprepare(mdp->clk_main);
- return;
+ return 0;
}
rate = clk_get_rate(mdp->clk_main);
@@ -212,6 +212,8 @@ static void mtk_disp_pwm_get_state(struct pwm_chip *chip,
state->polarity = PWM_POLARITY_NORMAL;
clk_disable_unprepare(mdp->clk_mm);
clk_disable_unprepare(mdp->clk_main);
+
+ return 0;
}
static const struct pwm_ops mtk_disp_pwm_ops = {
diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
index f230c10d28bb..41be244e7dd3 100644
--- a/drivers/pwm/pwm-pca9685.c
+++ b/drivers/pwm/pwm-pca9685.c
@@ -431,8 +431,8 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
-static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct pca9685 *pca = to_pca(chip);
unsigned long long duty;
@@ -458,12 +458,14 @@ static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
*/
state->duty_cycle = 0;
state->enabled = false;
- return;
+ return 0;
}
state->enabled = true;
duty = pca9685_pwm_get_duty(pca, pwm->hwpwm);
state->duty_cycle = DIV_ROUND_DOWN_ULL(duty * state->period, PCA9685_COUNTER_RANGE);
+
+ return 0;
}
static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
diff --git a/drivers/pwm/pwm-raspberrypi-poe.c b/drivers/pwm/pwm-raspberrypi-poe.c
index 6ff73029f367..2939b71a7ba7 100644
--- a/drivers/pwm/pwm-raspberrypi-poe.c
+++ b/drivers/pwm/pwm-raspberrypi-poe.c
@@ -82,9 +82,9 @@ static int raspberrypi_pwm_get_property(struct rpi_firmware *firmware,
return 0;
}
-static void raspberrypi_pwm_get_state(struct pwm_chip *chip,
- struct pwm_device *pwm,
- struct pwm_state *state)
+static int raspberrypi_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct raspberrypi_pwm *rpipwm = raspberrypi_pwm_from_chip(chip);
@@ -93,6 +93,8 @@ static void raspberrypi_pwm_get_state(struct pwm_chip *chip,
RPI_PWM_MAX_DUTY);
state->enabled = !!(rpipwm->duty_cycle);
state->polarity = PWM_POLARITY_NORMAL;
+
+ return 0;
}
static int raspberrypi_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index a5af859217c1..3ec7d1756903 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -57,9 +57,9 @@ static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
return container_of(c, struct rockchip_pwm_chip, chip);
}
-static void rockchip_pwm_get_state(struct pwm_chip *chip,
- struct pwm_device *pwm,
- struct pwm_state *state)
+static int rockchip_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
u32 enable_conf = pc->data->enable_conf;
@@ -70,11 +70,11 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip,
ret = clk_enable(pc->pclk);
if (ret)
- return;
+ return 0;
ret = clk_enable(pc->clk);
if (ret)
- return;
+ return 0;
clk_rate = clk_get_rate(pc->clk);
@@ -96,6 +96,8 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip,
clk_disable(pc->clk);
clk_disable(pc->pclk);
+
+ return 0;
}
static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c
index 89d53a0f91e6..393a4b97fc19 100644
--- a/drivers/pwm/pwm-sifive.c
+++ b/drivers/pwm/pwm-sifive.c
@@ -105,8 +105,8 @@ static void pwm_sifive_update_clock(struct pwm_sifive_ddata *ddata,
"New real_period = %u ns\n", ddata->real_period);
}
-static void pwm_sifive_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int pwm_sifive_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct pwm_sifive_ddata *ddata = pwm_sifive_chip_to_ddata(chip);
u32 duty, val;
@@ -123,6 +123,8 @@ static void pwm_sifive_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->duty_cycle =
(u64)duty * ddata->real_period >> PWM_SIFIVE_CMPWIDTH;
state->polarity = PWM_POLARITY_INVERSED;
+
+ return 0;
}
static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,
diff --git a/drivers/pwm/pwm-sl28cpld.c b/drivers/pwm/pwm-sl28cpld.c
index 589aeaaa6ac8..e64900ad4ba1 100644
--- a/drivers/pwm/pwm-sl28cpld.c
+++ b/drivers/pwm/pwm-sl28cpld.c
@@ -87,9 +87,9 @@ struct sl28cpld_pwm {
#define sl28cpld_pwm_from_chip(_chip) \
container_of(_chip, struct sl28cpld_pwm, pwm_chip)
-static void sl28cpld_pwm_get_state(struct pwm_chip *chip,
- struct pwm_device *pwm,
- struct pwm_state *state)
+static int sl28cpld_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct sl28cpld_pwm *priv = sl28cpld_pwm_from_chip(chip);
unsigned int reg;
@@ -115,6 +115,8 @@ static void sl28cpld_pwm_get_state(struct pwm_chip *chip,
* the PWM core.
*/
state->duty_cycle = min(state->duty_cycle, state->period);
+
+ return 0;
}
static int sl28cpld_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
diff --git a/drivers/pwm/pwm-sprd.c b/drivers/pwm/pwm-sprd.c
index 7004f55bbf11..87d5cb7f67d6 100644
--- a/drivers/pwm/pwm-sprd.c
+++ b/drivers/pwm/pwm-sprd.c
@@ -65,8 +65,8 @@ static void sprd_pwm_write(struct sprd_pwm_chip *spc, u32 hwid,
writel_relaxed(val, spc->base + offset);
}
-static void sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct sprd_pwm_chip *spc =
container_of(chip, struct sprd_pwm_chip, chip);
@@ -83,7 +83,7 @@ static void sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
if (ret) {
dev_err(spc->dev, "failed to enable pwm%u clocks\n",
pwm->hwpwm);
- return;
+ return 0;
}
val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_ENABLE);
@@ -109,10 +109,13 @@ static void sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
duty = val & SPRD_PWM_DUTY_MSK;
tmp = (prescale + 1) * NSEC_PER_SEC * duty;
state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);
+ state->polarity = PWM_POLARITY_NORMAL;
/* Disable PWM clocks if the PWM channel is not in enable state. */
if (!state->enabled)
clk_bulk_disable_unprepare(SPRD_PWM_CHN_CLKS_NUM, chn->clks);
+
+ return 0;
}
static int sprd_pwm_config(struct sprd_pwm_chip *spc, struct pwm_device *pwm,
diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c
index 61a1c87cd501..31a185c6b8da 100644
--- a/drivers/pwm/pwm-stm32-lp.c
+++ b/drivers/pwm/pwm-stm32-lp.c
@@ -157,9 +157,9 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
-static void stm32_pwm_lp_get_state(struct pwm_chip *chip,
- struct pwm_device *pwm,
- struct pwm_state *state)
+static int stm32_pwm_lp_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);
unsigned long rate = clk_get_rate(priv->clk);
@@ -185,6 +185,8 @@ static void stm32_pwm_lp_get_state(struct pwm_chip *chip,
tmp = prd - val;
tmp = (tmp << presc) * NSEC_PER_SEC;
state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
+
+ return 0;
}
static const struct pwm_ops stm32_pwm_lp_ops = {
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index c8445b0a3339..37d75e252d4e 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -108,9 +108,9 @@ static inline void sun4i_pwm_writel(struct sun4i_pwm_chip *chip,
writel(val, chip->base + offset);
}
-static void sun4i_pwm_get_state(struct pwm_chip *chip,
- struct pwm_device *pwm,
- struct pwm_state *state)
+static int sun4i_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip);
u64 clk_rate, tmp;
@@ -132,7 +132,7 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip,
state->duty_cycle = DIV_ROUND_UP_ULL(state->period, 2);
state->polarity = PWM_POLARITY_NORMAL;
state->enabled = true;
- return;
+ return 0;
}
if ((PWM_REG_PRESCAL(val, pwm->hwpwm) == PWM_PRESCAL_MASK) &&
@@ -142,7 +142,7 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip,
prescaler = prescaler_table[PWM_REG_PRESCAL(val, pwm->hwpwm)];
if (prescaler == 0)
- return;
+ return 0;
if (val & BIT_CH(PWM_ACT_STATE, pwm->hwpwm))
state->polarity = PWM_POLARITY_NORMAL;
@@ -162,6 +162,8 @@ static void sun4i_pwm_get_state(struct pwm_chip *chip,
tmp = (u64)prescaler * NSEC_PER_SEC * PWM_REG_PRD(val);
state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
+
+ return 0;
}
static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
diff --git a/drivers/pwm/pwm-sunplus.c b/drivers/pwm/pwm-sunplus.c
index e776fd16512d..d6ebe9f03b35 100644
--- a/drivers/pwm/pwm-sunplus.c
+++ b/drivers/pwm/pwm-sunplus.c
@@ -124,8 +124,8 @@ static int sunplus_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
-static void sunplus_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int sunplus_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct sunplus_pwm *priv = to_sunplus_pwm(chip);
u32 mode0, dd_freq, duty;
@@ -155,6 +155,8 @@ static void sunplus_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
}
state->polarity = PWM_POLARITY_NORMAL;
+
+ return 0;
}
static const struct pwm_ops sunplus_pwm_ops = {
diff --git a/drivers/pwm/pwm-visconti.c b/drivers/pwm/pwm-visconti.c
index 927c4cbb1daf..e3fb79b3e2a7 100644
--- a/drivers/pwm/pwm-visconti.c
+++ b/drivers/pwm/pwm-visconti.c
@@ -103,8 +103,8 @@ static int visconti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
-static void visconti_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state)
+static int visconti_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct visconti_pwm_chip *priv = visconti_pwm_from_chip(chip);
u32 period, duty, pwmc0, pwmc0_clk;
@@ -122,6 +122,8 @@ static void visconti_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm
state->polarity = PWM_POLARITY_NORMAL;
state->enabled = true;
+
+ return 0;
}
static const struct pwm_ops visconti_pwm_ops = {
diff --git a/drivers/pwm/pwm-xilinx.c b/drivers/pwm/pwm-xilinx.c
index 4dab2b86c427..f7a50fdcd9a5 100644
--- a/drivers/pwm/pwm-xilinx.c
+++ b/drivers/pwm/pwm-xilinx.c
@@ -169,9 +169,9 @@ static int xilinx_pwm_apply(struct pwm_chip *chip, struct pwm_device *unused,
return 0;
}
-static void xilinx_pwm_get_state(struct pwm_chip *chip,
- struct pwm_device *unused,
- struct pwm_state *state)
+static int xilinx_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *unused,
+ struct pwm_state *state)
{
struct xilinx_timer_priv *priv = xilinx_pwm_chip_to_priv(chip);
u32 tlr0, tlr1, tcsr0, tcsr1;
@@ -191,6 +191,8 @@ static void xilinx_pwm_get_state(struct pwm_chip *chip,
*/
if (state->period == state->duty_cycle)
state->duty_cycle = 0;
+
+ return 0;
}
static const struct pwm_ops xilinx_pwm_ops = {
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index c3ad04ad66e0..8009eab3b7be 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -767,13 +767,12 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
iscsi_set_param(cls_conn, param, buf, buflen);
break;
case ISCSI_PARAM_DATADGST_EN:
- iscsi_set_param(cls_conn, param, buf, buflen);
-
mutex_lock(&tcp_sw_conn->sock_lock);
if (!tcp_sw_conn->sock) {
mutex_unlock(&tcp_sw_conn->sock_lock);
return -ENOTCONN;
}
+ iscsi_set_param(cls_conn, param, buf, buflen);
tcp_sw_conn->sendpage = conn->datadgst_en ?
sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
mutex_unlock(&tcp_sw_conn->sock_lock);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7d2d872bae3c..08dc825fbf4f 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3608,6 +3608,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
probe_failed:
qla_enode_stop(base_vha);
qla_edb_stop(base_vha);
+ vfree(base_vha->scan.l);
if (base_vha->gnl.l) {
dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
base_vha->gnl.l, base_vha->gnl.ldma);
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 388172289627..2a3bd6918c77 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1897,6 +1897,17 @@ EXPORT_SYMBOL_GPL(serial8250_modem_status);
static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
{
switch (iir & 0x3f) {
+ case UART_IIR_THRI:
+ /*
+ * Postpone DMA or not decision to IIR_RDI or IIR_RX_TIMEOUT
+ * because it's impossible to do an informed decision about
+ * that with IIR_THRI.
+ *
+ * This also fixes one known DMA Rx corruption issue where
+ * DR is asserted but DMA Rx only gets a corrupted zero byte
+ * (too early DR?).
+ */
+ return false;
case UART_IIR_RDI:
if (!up->dma->rx_running)
break;
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index cd98c04de033..48eb5fea62fd 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -838,11 +838,17 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
struct lpuart_port, port);
unsigned long stat = lpuart32_read(port, UARTSTAT);
unsigned long sfifo = lpuart32_read(port, UARTFIFO);
+ unsigned long ctrl = lpuart32_read(port, UARTCTRL);
if (sport->dma_tx_in_progress)
return 0;
- if (stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT)
+ /*
+ * LPUART Transmission Complete Flag may never be set while queuing a break
+ * character, so avoid checking for transmission complete when UARTCTRL_SBK
+ * is asserted.
+ */
+ if ((stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT) || ctrl & UARTCTRL_SBK)
return TIOCSER_TEMT;
return 0;
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 62f773286d44..e67d3a886bf4 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -31,6 +31,7 @@
#include <linux/ioport.h>
#include <linux/ktime.h>
#include <linux/major.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/of.h>
@@ -2867,6 +2868,13 @@ static int sci_init_single(struct platform_device *dev,
sci_port->irqs[i] = platform_get_irq(dev, i);
}
+ /*
+ * The fourth interrupt on SCI port is transmit end interrupt, so
+ * shuffle the interrupts.
+ */
+ if (p->type == PORT_SCI)
+ swap(sci_port->irqs[SCIx_BRI_IRQ], sci_port->irqs[SCIx_TEI_IRQ]);
+
/* The SCI generates several interrupts. They can be muxed together or
* connected to different interrupt lines. In the muxed case only one
* interrupt resource is specified as there is only one interrupt ID.
@@ -2932,7 +2940,7 @@ static int sci_init_single(struct platform_device *dev,
port->flags = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags;
port->fifosize = sci_port->params->fifosize;
- if (port->type == PORT_SCI) {
+ if (port->type == PORT_SCI && !dev->dev.of_node) {
if (sci_port->reg_size >= 0x20)
port->regshift = 2;
else
diff --git a/drivers/usb/cdns3/cdnsp-ep0.c b/drivers/usb/cdns3/cdnsp-ep0.c
index d63d5d92f255..f317d3c84781 100644
--- a/drivers/usb/cdns3/cdnsp-ep0.c
+++ b/drivers/usb/cdns3/cdnsp-ep0.c
@@ -414,7 +414,7 @@ static int cdnsp_ep0_std_request(struct cdnsp_device *pdev,
void cdnsp_setup_analyze(struct cdnsp_device *pdev)
{
struct usb_ctrlrequest *ctrl = &pdev->setup;
- int ret = 0;
+ int ret = -EINVAL;
u16 len;
trace_cdnsp_ctrl_req(ctrl);
@@ -424,7 +424,6 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
if (pdev->gadget.state == USB_STATE_NOTATTACHED) {
dev_err(pdev->dev, "ERR: Setup detected in unattached state\n");
- ret = -EINVAL;
goto out;
}
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index a23ddbb81979..560793545362 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -49,6 +49,7 @@
#define PCI_DEVICE_ID_INTEL_RPLS 0x7a61
#define PCI_DEVICE_ID_INTEL_MTLM 0x7eb1
#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1
+#define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
#define PCI_DEVICE_ID_INTEL_TGL 0x9a15
#define PCI_DEVICE_ID_AMD_MR 0x163a
@@ -474,6 +475,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLP),
(kernel_ulong_t) &dwc3_pci_intel_swnode, },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLS),
+ (kernel_ulong_t) &dwc3_pci_intel_swnode, },
+
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL),
(kernel_ulong_t) &dwc3_pci_intel_swnode, },
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index bdb776553826..32df571bb233 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1225,6 +1225,9 @@ static void tegra_xhci_id_work(struct work_struct *work)
mutex_unlock(&tegra->lock);
+ tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(tegra->padctl,
+ tegra->otg_usb2_port);
+
if (tegra->host_mode) {
/* switch to host mode */
if (tegra->otg_usb3_port >= 0) {
@@ -1339,9 +1342,6 @@ static int tegra_xhci_id_notify(struct notifier_block *nb,
}
tegra->otg_usb2_port = tegra_xusb_get_usb2_port(tegra, usbphy);
- tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(
- tegra->padctl,
- tegra->otg_usb2_port);
tegra->host_mode = (usbphy->last_event == USB_EVENT_ID) ? true : false;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 2b280beb0011..c02ad4f76bb3 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -9,6 +9,7 @@
*/
#include <linux/pci.h>
+#include <linux/iommu.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/log2.h>
@@ -228,6 +229,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
{
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+ struct iommu_domain *domain;
int err, i;
u64 val;
u32 intrs;
@@ -246,7 +248,9 @@ static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
* an iommu. Doing anything when there is no iommu is definitely
* unsafe...
*/
- if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !device_iommu_mapped(dev))
+ domain = iommu_get_domain_for_dev(dev);
+ if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !domain ||
+ domain->type == IOMMU_DOMAIN_IDENTITY)
return;
xhci_info(xhci, "Zeroing 64bit base registers, expecting fault\n");
@@ -4406,6 +4410,7 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
if (!virt_dev || max_exit_latency == virt_dev->current_mel) {
spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_free_command(xhci, command);
return 0;
}
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index ba5638471de4..f1d7a5a863aa 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -120,6 +120,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */
{ USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */
{ USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */
+ { USB_DEVICE(0x10C4, 0x82AA) }, /* Silicon Labs IFS-USB-DATACABLE used with Quint UPS */
{ USB_DEVICE(0x10C4, 0x82EF) }, /* CESINEL FALCO 6105 AC Power Supply */
{ USB_DEVICE(0x10C4, 0x82F1) }, /* CESINEL MEDCAL EFD Earth Fault Detector */
{ USB_DEVICE(0x10C4, 0x82F2) }, /* CESINEL MEDCAL ST Network Analyzer */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index a8534065e0d6..fc12fee66141 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1198,6 +1198,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0900, 0xff, 0, 0), /* RM500U-CN */
+ .driver_info = ZLP },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
@@ -1300,6 +1302,14 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */
.driver_info = RSVD(0) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */
+ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990 (MBIM) */
+ .driver_info = NCTRL(0) | RSVD(1) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1082, 0xff), /* Telit FE990 (RNDIS) */
+ .driver_info = NCTRL(2) | RSVD(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990 (ECM) */
+ .driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 3a42313d0d66..4075c0d7e6a2 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -112,8 +112,12 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
if (dp->data.status & DP_STATUS_PREFER_MULTI_FUNC &&
pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK)
pin_assign &= DP_PIN_ASSIGN_MULTI_FUNC_MASK;
- else if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK)
+ else if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK) {
pin_assign &= DP_PIN_ASSIGN_DP_ONLY_MASK;
+ /* Default to pin assign C if available */
+ if (pin_assign & BIT(DP_PIN_ASSIGN_C))
+ pin_assign = BIT(DP_PIN_ASSIGN_C);
+ }
if (!pin_assign)
return -EINVAL;
diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c
index 45119597c765..89e810b27a4b 100644
--- a/fs/cifs/fs_context.c
+++ b/fs/cifs/fs_context.c
@@ -441,13 +441,14 @@ int smb3_parse_opt(const char *options, const char *key, char **val)
* but there are some bugs that prevent rename from working if there are
* multiple delimiters.
*
- * Returns a sanitized duplicate of @path. The caller is responsible for
- * cleaning up the original.
+ * Returns a sanitized duplicate of @path. @gfp indicates the GFP_* flags
+ * for kstrdup.
+ * The caller is responsible for freeing the original.
*/
#define IS_DELIM(c) ((c) == '/' || (c) == '\\')
-static char *sanitize_path(char *path)
+char *cifs_sanitize_prepath(char *prepath, gfp_t gfp)
{
- char *cursor1 = path, *cursor2 = path;
+ char *cursor1 = prepath, *cursor2 = prepath;
/* skip all prepended delimiters */
while (IS_DELIM(*cursor1))
@@ -469,7 +470,7 @@ static char *sanitize_path(char *path)
cursor2--;
*(cursor2) = '\0';
- return kstrdup(path, GFP_KERNEL);
+ return kstrdup(prepath, gfp);
}
/*
@@ -531,7 +532,7 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
if (!*pos)
return 0;
- ctx->prepath = sanitize_path(pos);
+ ctx->prepath = cifs_sanitize_prepath(pos, GFP_KERNEL);
if (!ctx->prepath)
return -ENOMEM;
diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h
index a268896d05d5..26093f54d3e6 100644
--- a/fs/cifs/fs_context.h
+++ b/fs/cifs/fs_context.h
@@ -287,4 +287,7 @@ extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
*/
#define SMB3_MAX_DCLOSETIMEO (1 << 30)
#define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */
+
+extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp);
+
#endif
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 832856aef4b7..cf19e6a81ed9 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1304,7 +1304,7 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
kfree(cifs_sb->prepath);
if (prefix && *prefix) {
- cifs_sb->prepath = kstrdup(prefix, GFP_ATOMIC);
+ cifs_sb->prepath = cifs_sanitize_prepath(prefix, GFP_ATOMIC);
if (!cifs_sb->prepath)
return -ENOMEM;
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
index 2be9d7460494..b8f9d627f241 100644
--- a/fs/ksmbd/connection.c
+++ b/fs/ksmbd/connection.c
@@ -326,10 +326,7 @@ int ksmbd_conn_handler_loop(void *p)
/* 4 for rfc1002 length field */
size = pdu_size + 4;
- conn->request_buf = kvmalloc(size,
- GFP_KERNEL |
- __GFP_NOWARN |
- __GFP_NORETRY);
+ conn->request_buf = kvmalloc(size, GFP_KERNEL);
if (!conn->request_buf)
break;
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index a0d635304754..651d1d01234b 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -289,10 +289,7 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
work->request_buf = conn->request_buf;
conn->request_buf = NULL;
- if (ksmbd_init_smb_server(work)) {
- ksmbd_free_work_struct(work);
- return -EINVAL;
- }
+ ksmbd_init_smb_server(work);
ksmbd_conn_enqueue_request(work);
atomic_inc(&conn->r_count);
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index daaee7a89e05..4effe8df5ae9 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -235,9 +235,6 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
struct smb2_negotiate_rsp *rsp;
struct ksmbd_conn *conn = work->conn;
- if (conn->need_neg == false)
- return -EINVAL;
-
*(__be32 *)work->response_buf =
cpu_to_be32(conn->vals->header_size);
diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c
index 3d9e8d8a5762..95afb6b23a91 100644
--- a/fs/ksmbd/smb_common.c
+++ b/fs/ksmbd/smb_common.c
@@ -283,20 +283,121 @@ static int ksmbd_negotiate_smb_dialect(void *buf)
return BAD_PROT_ID;
}
-int ksmbd_init_smb_server(struct ksmbd_work *work)
+#define SMB_COM_NEGOTIATE_EX 0x0
+
+/**
+ * get_smb1_cmd_val() - get smb command value from smb header
+ * @work: smb work containing smb header
+ *
+ * Return: smb command value
+ */
+static u16 get_smb1_cmd_val(struct ksmbd_work *work)
{
- struct ksmbd_conn *conn = work->conn;
+ return SMB_COM_NEGOTIATE_EX;
+}
- if (conn->need_neg == false)
+/**
+ * init_smb1_rsp_hdr() - initialize smb negotiate response header
+ * @work: smb work containing smb request
+ *
+ * Return: 0 on success, otherwise -EINVAL
+ */
+static int init_smb1_rsp_hdr(struct ksmbd_work *work)
+{
+ struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
+ struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
+
+ /*
+ * Remove 4 byte direct TCP header.
+ */
+ *(__be32 *)work->response_buf =
+ cpu_to_be32(sizeof(struct smb_hdr) - 4);
+
+ rsp_hdr->Command = SMB_COM_NEGOTIATE;
+ *(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
+ rsp_hdr->Flags = SMBFLG_RESPONSE;
+ rsp_hdr->Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
+ SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
+ rsp_hdr->Pid = rcv_hdr->Pid;
+ rsp_hdr->Mid = rcv_hdr->Mid;
+ return 0;
+}
+
+/**
+ * smb1_check_user_session() - check for valid session for a user
+ * @work: smb work containing smb request buffer
+ *
+ * Return: 0 on success, otherwise error
+ */
+static int smb1_check_user_session(struct ksmbd_work *work)
+{
+ unsigned int cmd = work->conn->ops->get_cmd_val(work);
+
+ if (cmd == SMB_COM_NEGOTIATE_EX)
return 0;
- init_smb3_11_server(conn);
+ return -EINVAL;
+}
+
+/**
+ * smb1_allocate_rsp_buf() - allocate response buffer for a command
+ * @work: smb work containing smb request
+ *
+ * Return: 0 on success, otherwise -ENOMEM
+ */
+static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
+{
+ work->response_buf = kmalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
+ GFP_KERNEL | __GFP_ZERO);
+ work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
+
+ if (!work->response_buf) {
+ pr_err("Failed to allocate %u bytes buffer\n",
+ MAX_CIFS_SMALL_BUFFER_SIZE);
+ return -ENOMEM;
+ }
- if (conn->ops->get_cmd_val(work) != SMB_COM_NEGOTIATE)
- conn->need_neg = false;
return 0;
}
+static struct smb_version_ops smb1_server_ops = {
+ .get_cmd_val = get_smb1_cmd_val,
+ .init_rsp_hdr = init_smb1_rsp_hdr,
+ .allocate_rsp_buf = smb1_allocate_rsp_buf,
+ .check_user_session = smb1_check_user_session,
+};
+
+static int smb1_negotiate(struct ksmbd_work *work)
+{
+ return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE);
+}
+
+static struct smb_version_cmds smb1_server_cmds[1] = {
+ [SMB_COM_NEGOTIATE_EX] = { .proc = smb1_negotiate, },
+};
+
+static void init_smb1_server(struct ksmbd_conn *conn)
+{
+ conn->ops = &smb1_server_ops;
+ conn->cmds = smb1_server_cmds;
+ conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
+}
+
+void ksmbd_init_smb_server(struct ksmbd_work *work)
+{
+ struct ksmbd_conn *conn = work->conn;
+ __le32 proto;
+
+ if (conn->need_neg == false)
+ return;
+
+ proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
+ if (proto == SMB1_PROTO_NUMBER)
+ init_smb1_server(conn);
+ else
+ init_smb3_11_server(conn);
+}
+
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
struct ksmbd_file *dir,
struct ksmbd_dir_info *d_info,
@@ -444,20 +545,10 @@ static int smb_handle_negotiate(struct ksmbd_work *work)
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
- /*
- * Remove 4 byte direct TCP header, add 2 byte bcc and
- * 2 byte DialectIndex.
- */
- *(__be32 *)work->response_buf =
- cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2 + 2);
+ /* Add 2 byte bcc and 2 byte DialectIndex. */
+ inc_rfc1001_len(work->response_buf, 4);
neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
- neg_rsp->hdr.Command = SMB_COM_NEGOTIATE;
- *(__le32 *)neg_rsp->hdr.Protocol = SMB1_PROTO_NUMBER;
- neg_rsp->hdr.Flags = SMBFLG_RESPONSE;
- neg_rsp->hdr.Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
- SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
-
neg_rsp->hdr.WordCount = 1;
neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
neg_rsp->ByteCount = 0;
@@ -473,24 +564,13 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
ksmbd_negotiate_smb_dialect(work->request_buf);
ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
- if (command == SMB2_NEGOTIATE_HE) {
- struct smb2_hdr *smb2_hdr = smb2_get_msg(work->request_buf);
-
- if (smb2_hdr->ProtocolId != SMB2_PROTO_NUMBER) {
- ksmbd_debug(SMB, "Downgrade to SMB1 negotiation\n");
- command = SMB_COM_NEGOTIATE;
- }
- }
-
if (command == SMB2_NEGOTIATE_HE) {
ret = smb2_handle_negotiate(work);
- init_smb2_neg_rsp(work);
return ret;
}
if (command == SMB_COM_NEGOTIATE) {
if (__smb2_negotiate(conn)) {
- conn->need_neg = true;
init_smb3_11_server(conn);
init_smb2_neg_rsp(work);
ksmbd_debug(SMB, "Upgrade to SMB2 negotiation\n");
diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h
index c1f3006792ff..78c44978a906 100644
--- a/fs/ksmbd/smb_common.h
+++ b/fs/ksmbd/smb_common.h
@@ -427,7 +427,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);
int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
-int ksmbd_init_smb_server(struct ksmbd_work *work);
+void ksmbd_init_smb_server(struct ksmbd_work *work);
struct ksmbd_kstat;
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
diff --git a/fs/namespace.c b/fs/namespace.c
index df137ba19d37..e04a9e9e3f14 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -4180,9 +4180,9 @@ static int do_mount_setattr(struct path *path, struct mount_kattr *kattr)
unlock_mount_hash();
if (kattr->propagation) {
- namespace_unlock();
if (err)
cleanup_group_ids(mnt, NULL);
+ namespace_unlock();
}
return err;
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index b6d01d51a746..e7e6e78d965d 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -296,6 +296,7 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
out_free_dev:
kfree(dev);
+ gdp->gd_device = NULL;
return ret;
}
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 6253cbe5f81b..39989c14c8a1 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -874,8 +874,8 @@ static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct r
if (!kcred)
return NULL;
- kcred->uid = ses->se_cb_sec.uid;
- kcred->gid = ses->se_cb_sec.gid;
+ kcred->fsuid = ses->se_cb_sec.uid;
+ kcred->fsgid = ses->se_cb_sec.gid;
return kcred;
}
}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 8377e14b8fba..8f5b41dc0773 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2417,10 +2417,12 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
for (i = 0; i < argp->opcnt; i++) {
op = &argp->ops[i];
op->replay = NULL;
+ op->opdesc = NULL;
if (xdr_stream_decode_u32(argp->xdr, &op->opnum) < 0)
return false;
if (nfsd4_opnum_in_range(argp, op)) {
+ op->opdesc = OPDESC(op);
op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
if (op->status != nfs_ok)
trace_nfsd_compound_decode_err(argp->rqstp,
@@ -2431,7 +2433,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
op->opnum = OP_ILLEGAL;
op->status = nfserr_op_illegal;
}
- op->opdesc = OPDESC(op);
+
/*
* We'll try to cache the result in the DRC if any one
* op in the compound wants to be cached:
@@ -5351,10 +5353,8 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
__be32 *p;
p = xdr_reserve_space(xdr, 8);
- if (!p) {
- WARN_ON_ONCE(1);
- return;
- }
+ if (!p)
+ goto release;
*p++ = cpu_to_be32(op->opnum);
post_err_offset = xdr->buf->len;
@@ -5369,8 +5369,6 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
op->status = encoder(resp, op->status, &op->u);
if (op->status)
trace_nfsd_compound_encode_err(rqstp, op->opnum, op->status);
- if (opdesc && opdesc->op_release)
- opdesc->op_release(&op->u);
xdr_commit_encode(xdr);
/* nfsd4_check_resp_size guarantees enough room for error status */
@@ -5411,6 +5409,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
}
status:
*p = op->status;
+release:
+ if (opdesc && opdesc->op_release)
+ opdesc->op_release(&op->u);
}
/*
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 3335ef352915..63d96a1733b2 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -2607,11 +2607,10 @@ static int nilfs_segctor_thread(void *arg)
goto loop;
end_thread:
- spin_unlock(&sci->sc_state_lock);
-
/* end sync. */
sci->sc_task = NULL;
wake_up(&sci->sc_wait_task); /* for nilfs_segctor_kill_thread() */
+ spin_unlock(&sci->sc_state_lock);
return 0;
}
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 1422b8ba24ed..77f1e5778d1c 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -482,6 +482,7 @@ static void nilfs_put_super(struct super_block *sb)
up_write(&nilfs->ns_sem);
}
+ nilfs_sysfs_delete_device_group(nilfs);
iput(nilfs->ns_sufile);
iput(nilfs->ns_cpfile);
iput(nilfs->ns_dat);
@@ -1105,6 +1106,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
nilfs_put_root(fsroot);
failed_unload:
+ nilfs_sysfs_delete_device_group(nilfs);
iput(nilfs->ns_sufile);
iput(nilfs->ns_cpfile);
iput(nilfs->ns_dat);
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 3a4c9c150cbf..2894152a6b25 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -87,7 +87,6 @@ void destroy_nilfs(struct the_nilfs *nilfs)
{
might_sleep();
if (nilfs_init(nilfs)) {
- nilfs_sysfs_delete_device_group(nilfs);
brelse(nilfs->ns_sbh[0]);
brelse(nilfs->ns_sbh[1]);
}
@@ -305,6 +304,10 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
goto failed;
}
+ err = nilfs_sysfs_create_device_group(sb);
+ if (unlikely(err))
+ goto sysfs_error;
+
if (valid_fs)
goto skip_recovery;
@@ -366,6 +369,9 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
goto failed;
failed_unload:
+ nilfs_sysfs_delete_device_group(nilfs);
+
+ sysfs_error:
iput(nilfs->ns_cpfile);
iput(nilfs->ns_sufile);
iput(nilfs->ns_dat);
@@ -697,10 +703,6 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
if (err)
goto failed_sbh;
- err = nilfs_sysfs_create_device_group(sb);
- if (err)
- goto failed_sbh;
-
set_nilfs_init(nilfs);
err = 0;
out:
diff --git a/include/acpi/video.h b/include/acpi/video.h
index 8ed9bec03e53..ff5a8da5d883 100644
--- a/include/acpi/video.h
+++ b/include/acpi/video.h
@@ -59,8 +59,6 @@ extern void acpi_video_unregister(void);
extern void acpi_video_register_backlight(void);
extern int acpi_video_get_edid(struct acpi_device *device, int type,
int device_id, void **edid);
-extern enum acpi_backlight_type acpi_video_get_backlight_type(void);
-extern bool acpi_video_backlight_use_native(void);
/*
* Note: The value returned by acpi_video_handles_brightness_key_presses()
* may change over time and should not be cached.
@@ -69,6 +67,19 @@ extern bool acpi_video_handles_brightness_key_presses(void);
extern int acpi_video_get_levels(struct acpi_device *device,
struct acpi_video_device_brightness **dev_br,
int *pmax_level);
+
+extern enum acpi_backlight_type __acpi_video_get_backlight_type(bool native,
+ bool *auto_detect);
+
+static inline enum acpi_backlight_type acpi_video_get_backlight_type(void)
+{
+ return __acpi_video_get_backlight_type(false, NULL);
+}
+
+static inline bool acpi_video_backlight_use_native(void)
+{
+ return __acpi_video_get_backlight_type(true, NULL) == acpi_backlight_native;
+}
#else
static inline void acpi_video_report_nolcd(void) { return; };
static inline int acpi_video_register(void) { return -ENODEV; }
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index 6c0c3dc3d3ac..32c764fb9cb5 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_atomic_payload *payload);
void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_topology_state *mst_state,
- struct drm_dp_mst_atomic_payload *payload);
+ const struct drm_dp_mst_atomic_payload *old_payload,
+ struct drm_dp_mst_atomic_payload *new_payload);
int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index c0b868ce6a8f..96b192139a23 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -11,7 +11,6 @@
#include <asm/perf_event.h>
#define ARMV8_PMU_CYCLE_IDX (ARMV8_PMU_MAX_COUNTERS - 1)
-#define ARMV8_PMU_MAX_COUNTER_PAIRS ((ARMV8_PMU_MAX_COUNTERS + 1) >> 1)
#ifdef CONFIG_HW_PERF_EVENTS
@@ -29,7 +28,6 @@ struct kvm_pmu {
struct irq_work overflow_work;
struct kvm_pmu_events events;
struct kvm_pmc pmc[ARMV8_PMU_MAX_COUNTERS];
- DECLARE_BITMAP(chained, ARMV8_PMU_MAX_COUNTER_PAIRS);
int irq_num;
bool created;
bool irq_level;
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 04c6acf7faaa..201dd1ab7f1c 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -87,10 +87,10 @@ typedef int (*dm_preresume_fn) (struct dm_target *ti);
typedef void (*dm_resume_fn) (struct dm_target *ti);
typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
- unsigned status_flags, char *result, unsigned maxlen);
+ unsigned int status_flags, char *result, unsigned int maxlen);
-typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv,
- char *result, unsigned maxlen);
+typedef int (*dm_message_fn) (struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen);
typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti, struct block_device **bdev);
@@ -187,7 +187,7 @@ struct target_type {
uint64_t features;
const char *name;
struct module *module;
- unsigned version[3];
+ unsigned int version[3];
dm_ctr_fn ctr;
dm_dtr_fn dtr;
dm_map_fn map;
@@ -313,31 +313,31 @@ struct dm_target {
* It is a responsibility of the target driver to remap these bios
* to the real underlying devices.
*/
- unsigned num_flush_bios;
+ unsigned int num_flush_bios;
/*
* The number of discard bios that will be submitted to the target.
* The bio number can be accessed with dm_bio_get_target_bio_nr.
*/
- unsigned num_discard_bios;
+ unsigned int num_discard_bios;
/*
* The number of secure erase bios that will be submitted to the target.
* The bio number can be accessed with dm_bio_get_target_bio_nr.
*/
- unsigned num_secure_erase_bios;
+ unsigned int num_secure_erase_bios;
/*
* The number of WRITE ZEROES bios that will be submitted to the target.
* The bio number can be accessed with dm_bio_get_target_bio_nr.
*/
- unsigned num_write_zeroes_bios;
+ unsigned int num_write_zeroes_bios;
/*
* The minimum number of extra bytes allocated in each io for the
* target to use.
*/
- unsigned per_io_data_size;
+ unsigned int per_io_data_size;
/* target specific data */
void *private;
@@ -383,7 +383,7 @@ struct dm_target {
void *dm_per_bio_data(struct bio *bio, size_t data_size);
struct bio *dm_bio_from_per_bio_data(void *data, size_t data_size);
-unsigned dm_bio_get_target_bio_nr(const struct bio *bio);
+unsigned int dm_bio_get_target_bio_nr(const struct bio *bio);
u64 dm_start_time_ns_from_clone(struct bio *bio);
@@ -394,7 +394,7 @@ void dm_unregister_target(struct target_type *t);
* Target argument parsing.
*/
struct dm_arg_set {
- unsigned argc;
+ unsigned int argc;
char **argv;
};
@@ -403,8 +403,8 @@ struct dm_arg_set {
* the error message to use if the number is found to be outside that range.
*/
struct dm_arg {
- unsigned min;
- unsigned max;
+ unsigned int min;
+ unsigned int max;
char *error;
};
@@ -413,7 +413,7 @@ struct dm_arg {
* returning -EINVAL and setting *error.
*/
int dm_read_arg(const struct dm_arg *arg, struct dm_arg_set *arg_set,
- unsigned *value, char **error);
+ unsigned int *value, char **error);
/*
* Process the next argument as the start of a group containing between
@@ -421,7 +421,7 @@ int dm_read_arg(const struct dm_arg *arg, struct dm_arg_set *arg_set,
* *num_args or, if invalid, return -EINVAL and set *error.
*/
int dm_read_arg_group(const struct dm_arg *arg, struct dm_arg_set *arg_set,
- unsigned *num_args, char **error);
+ unsigned int *num_args, char **error);
/*
* Return the current argument and shift to the next.
@@ -431,7 +431,7 @@ const char *dm_shift_arg(struct dm_arg_set *as);
/*
* Move through num_args arguments.
*/
-void dm_consume_args(struct dm_arg_set *as, unsigned num_args);
+void dm_consume_args(struct dm_arg_set *as, unsigned int num_args);
/*-----------------------------------------------------------------
* Functions for creating and manipulating mapped devices.
@@ -461,7 +461,7 @@ void *dm_get_mdptr(struct mapped_device *md);
/*
* A device can still be used while suspended, but I/O is deferred.
*/
-int dm_suspend(struct mapped_device *md, unsigned suspend_flags);
+int dm_suspend(struct mapped_device *md, unsigned int suspend_flags);
int dm_resume(struct mapped_device *md);
/*
@@ -481,7 +481,7 @@ struct gendisk *dm_disk(struct mapped_device *md);
int dm_suspended(struct dm_target *ti);
int dm_post_suspending(struct dm_target *ti);
int dm_noflush_suspending(struct dm_target *ti);
-void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors);
+void dm_accept_partial_bio(struct bio *bio, unsigned int n_sectors);
void dm_submit_bio_remap(struct bio *clone, struct bio *tgt_clone);
union map_info *dm_get_rq_mapinfo(struct request *rq);
@@ -525,7 +525,7 @@ int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo);
* First create an empty table.
*/
int dm_table_create(struct dm_table **result, fmode_t mode,
- unsigned num_targets, struct mapped_device *md);
+ unsigned int num_targets, struct mapped_device *md);
/*
* Then call this once for each target.
diff --git a/include/linux/dm-bufio.h b/include/linux/dm-bufio.h
index 15d9e15ca830..1262d92ab88f 100644
--- a/include/linux/dm-bufio.h
+++ b/include/linux/dm-bufio.h
@@ -26,8 +26,8 @@ struct dm_buffer;
* Create a buffered IO cache on a given device
*/
struct dm_bufio_client *
-dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
- unsigned reserved_buffers, unsigned aux_size,
+dm_bufio_client_create(struct block_device *bdev, unsigned int block_size,
+ unsigned int reserved_buffers, unsigned int aux_size,
void (*alloc_callback)(struct dm_buffer *),
void (*write_callback)(struct dm_buffer *),
unsigned int flags);
@@ -81,7 +81,7 @@ void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
* I/O to finish.
*/
void dm_bufio_prefetch(struct dm_bufio_client *c,
- sector_t block, unsigned n_blocks);
+ sector_t block, unsigned int n_blocks);
/*
* Release a reference obtained with dm_bufio_{read,get,new}. The data
@@ -106,7 +106,7 @@ void dm_bufio_mark_buffer_dirty(struct dm_buffer *b);
* write the specified part of the buffer or it may write a larger superset.
*/
void dm_bufio_mark_partial_buffer_dirty(struct dm_buffer *b,
- unsigned start, unsigned end);
+ unsigned int start, unsigned int end);
/*
* Initiate writing of dirty buffers, without waiting for completion.
@@ -152,9 +152,9 @@ void dm_bufio_forget_buffers(struct dm_bufio_client *c, sector_t block, sector_t
/*
* Set the minimum number of buffers before cleanup happens.
*/
-void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n);
+void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned int n);
-unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
+unsigned int dm_bufio_get_block_size(struct dm_bufio_client *c);
sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c);
sector_t dm_bufio_get_block_number(struct dm_buffer *b);
diff --git a/include/linux/dm-dirty-log.h b/include/linux/dm-dirty-log.h
index 7084503c3405..843c857f07b0 100644
--- a/include/linux/dm-dirty-log.h
+++ b/include/linux/dm-dirty-log.h
@@ -33,7 +33,7 @@ struct dm_dirty_log_type {
struct list_head list;
int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti,
- unsigned argc, char **argv);
+ unsigned int argc, char **argv);
void (*dtr)(struct dm_dirty_log *log);
/*
@@ -116,7 +116,7 @@ struct dm_dirty_log_type {
* Support function for mirror status requests.
*/
int (*status)(struct dm_dirty_log *log, status_type_t status_type,
- char *result, unsigned maxlen);
+ char *result, unsigned int maxlen);
/*
* is_remote_recovering is necessary for cluster mirroring. It provides
@@ -139,7 +139,7 @@ int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type);
struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
struct dm_target *ti,
int (*flush_callback_fn)(struct dm_target *ti),
- unsigned argc, char **argv);
+ unsigned int argc, char **argv);
void dm_dirty_log_destroy(struct dm_dirty_log *log);
#endif /* __KERNEL__ */
diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h
index 8e1c4ab5df04..92e7abfe04f9 100644
--- a/include/linux/dm-io.h
+++ b/include/linux/dm-io.h
@@ -26,7 +26,7 @@ struct page_list {
struct page *page;
};
-typedef void (*io_notify_fn)(unsigned long error, void *context);
+typedef void (*io_notify_fn)(unsigned int long error, void *context);
enum dm_io_mem_type {
DM_IO_PAGE_LIST,/* Page list */
@@ -38,7 +38,7 @@ enum dm_io_mem_type {
struct dm_io_memory {
enum dm_io_mem_type type;
- unsigned offset;
+ unsigned int offset;
union {
struct page_list *pl;
@@ -78,8 +78,8 @@ void dm_io_client_destroy(struct dm_io_client *client);
* Each bit in the optional 'sync_error_bits' bitset indicates whether an
* error occurred doing io to the corresponding region.
*/
-int dm_io(struct dm_io_request *io_req, unsigned num_regions,
- struct dm_io_region *region, unsigned long *sync_error_bits);
+int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
+ struct dm_io_region *region, unsigned int long *sync_error_bits);
#endif /* __KERNEL__ */
#endif /* _LINUX_DM_IO_H */
diff --git a/include/linux/dm-kcopyd.h b/include/linux/dm-kcopyd.h
index c1707ee5b540..68c412b31b78 100644
--- a/include/linux/dm-kcopyd.h
+++ b/include/linux/dm-kcopyd.h
@@ -23,11 +23,11 @@
#define DM_KCOPYD_WRITE_SEQ 2
struct dm_kcopyd_throttle {
- unsigned throttle;
- unsigned num_io_jobs;
- unsigned io_period;
- unsigned total_period;
- unsigned last_jiffies;
+ unsigned int throttle;
+ unsigned int num_io_jobs;
+ unsigned int io_period;
+ unsigned int total_period;
+ unsigned int last_jiffies;
};
/*
@@ -60,12 +60,12 @@ void dm_kcopyd_client_flush(struct dm_kcopyd_client *kc);
* read_err is a boolean,
* write_err is a bitset, with 1 bit for each destination region
*/
-typedef void (*dm_kcopyd_notify_fn)(int read_err, unsigned long write_err,
+typedef void (*dm_kcopyd_notify_fn)(int read_err, unsigned int long write_err,
void *context);
void dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
- unsigned num_dests, struct dm_io_region *dests,
- unsigned flags, dm_kcopyd_notify_fn fn, void *context);
+ unsigned int num_dests, struct dm_io_region *dests,
+ unsigned int flags, dm_kcopyd_notify_fn fn, void *context);
/*
* Prepare a callback and submit it via the kcopyd thread.
@@ -80,11 +80,11 @@ void dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
*/
void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
dm_kcopyd_notify_fn fn, void *context);
-void dm_kcopyd_do_callback(void *job, int read_err, unsigned long write_err);
+void dm_kcopyd_do_callback(void *job, int read_err, unsigned int long write_err);
void dm_kcopyd_zero(struct dm_kcopyd_client *kc,
- unsigned num_dests, struct dm_io_region *dests,
- unsigned flags, dm_kcopyd_notify_fn fn, void *context);
+ unsigned int num_dests, struct dm_io_region *dests,
+ unsigned int flags, dm_kcopyd_notify_fn fn, void *context);
#endif /* __KERNEL__ */
#endif /* _LINUX_DM_KCOPYD_H */
diff --git a/include/linux/dm-region-hash.h b/include/linux/dm-region-hash.h
index 9e2a7a401df5..e8691539e1d7 100644
--- a/include/linux/dm-region-hash.h
+++ b/include/linux/dm-region-hash.h
@@ -37,7 +37,7 @@ struct dm_region_hash *dm_region_hash_create(
struct bio_list *bios),
void (*wakeup_workers)(void *context),
void (*wakeup_all_recovery_waiters)(void *context),
- sector_t target_begin, unsigned max_recovery,
+ sector_t target_begin, unsigned int max_recovery,
struct dm_dirty_log *log, uint32_t region_size,
region_t nr_regions);
void dm_region_hash_destroy(struct dm_region_hash *rh);
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 62557d4bffc2..8128059db5ed 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -943,7 +943,7 @@ static inline void __ftrace_enabled_restore(int enabled)
#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
-static inline unsigned long get_lock_parent_ip(void)
+static __always_inline unsigned long get_lock_parent_ip(void)
{
unsigned long addr = CALLER_ADDR0;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 500e536796ca..247aedb18d5c 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -725,7 +725,8 @@ struct mm_struct {
unsigned long cpu_bitmap[];
};
-#define MM_MT_FLAGS (MT_FLAGS_ALLOC_RANGE | MT_FLAGS_LOCK_EXTERN)
+#define MM_MT_FLAGS (MT_FLAGS_ALLOC_RANGE | MT_FLAGS_LOCK_EXTERN | \
+ MT_FLAGS_USE_RCU)
extern struct mm_struct init_mm;
/* Pointer magic because the dynamic array size confuses some compilers. */
diff --git a/include/linux/pci-doe.h b/include/linux/pci-doe.h
index ed9b4df792b8..43765eaf2342 100644
--- a/include/linux/pci-doe.h
+++ b/include/linux/pci-doe.h
@@ -34,6 +34,10 @@ struct pci_doe_mb;
* @work: Used internally by the mailbox
* @doe_mb: Used internally by the mailbox
*
+ * Payloads are treated as opaque byte streams which are transmitted verbatim,
+ * without byte-swapping. If payloads contain little-endian register values,
+ * the caller is responsible for conversion with cpu_to_le32() / le32_to_cpu().
+ *
* The payload sizes and rv are specified in bytes with the following
* restrictions concerning the protocol.
*
@@ -45,9 +49,9 @@ struct pci_doe_mb;
*/
struct pci_doe_task {
struct pci_doe_protocol prot;
- u32 *request_pl;
+ __le32 *request_pl;
size_t request_pl_sz;
- u32 *response_pl;
+ __le32 *response_pl;
size_t response_pl_sz;
int rv;
void (*complete)(struct pci_doe_task *task);
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 3f01ac8017e0..6d62c9ea2e04 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -566,6 +566,7 @@ struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *,
phy_interface_t iface,
const struct phylink_mac_ops *mac_ops);
void phylink_destroy(struct phylink *);
+bool phylink_expects_phy(struct phylink *pl);
int phylink_connect_phy(struct phylink *, struct phy_device *);
int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index d70c6e5a839d..4de09163c968 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -276,8 +276,8 @@ struct pwm_ops {
struct pwm_capture *result, unsigned long timeout);
int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state);
- void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
- struct pwm_state *state);
+ int (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state);
struct module *owner;
};
diff --git a/include/net/raw.h b/include/net/raw.h
index 5e665934ebc7..3af5289fdead 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -15,6 +15,8 @@
#include <net/inet_sock.h>
#include <net/protocol.h>
+#include <net/netns/hash.h>
+#include <linux/hash.h>
#include <linux/icmp.h>
extern struct proto raw_prot;
@@ -29,20 +31,27 @@ int raw_local_deliver(struct sk_buff *, int);
int raw_rcv(struct sock *, struct sk_buff *);
-#define RAW_HTABLE_SIZE MAX_INET_PROTOS
+#define RAW_HTABLE_LOG 8
+#define RAW_HTABLE_SIZE (1U << RAW_HTABLE_LOG)
struct raw_hashinfo {
spinlock_t lock;
- struct hlist_nulls_head ht[RAW_HTABLE_SIZE];
+
+ struct hlist_head ht[RAW_HTABLE_SIZE] ____cacheline_aligned;
};
+static inline u32 raw_hashfunc(const struct net *net, u32 proto)
+{
+ return hash_32(net_hash_mix(net) ^ proto, RAW_HTABLE_LOG);
+}
+
static inline void raw_hashinfo_init(struct raw_hashinfo *hashinfo)
{
int i;
spin_lock_init(&hashinfo->lock);
for (i = 0; i < RAW_HTABLE_SIZE; i++)
- INIT_HLIST_NULLS_HEAD(&hashinfo->ht[i], i);
+ INIT_HLIST_HEAD(&hashinfo->ht[i]);
}
#ifdef CONFIG_PROC_FS
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index ce4969d3e20d..cc35aba1e495 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -2585,8 +2585,8 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
io_eventfd_unregister(ctx);
io_alloc_cache_free(&ctx->apoll_cache, io_apoll_cache_free);
io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
- mutex_unlock(&ctx->uring_lock);
io_destroy_buffers(ctx);
+ mutex_unlock(&ctx->uring_lock);
if (ctx->sq_creds)
put_cred(ctx->sq_creds);
if (ctx->submitter_task)
diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
index 746b137b96e9..acc37e5a6d4e 100644
--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -228,17 +228,18 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx,
return i;
}
- /* the head kbuf is the list itself */
+ /* protects io_buffers_cache */
+ lockdep_assert_held(&ctx->uring_lock);
+
while (!list_empty(&bl->buf_list)) {
struct io_buffer *nxt;
nxt = list_first_entry(&bl->buf_list, struct io_buffer, list);
- list_del(&nxt->list);
+ list_move(&nxt->list, &ctx->io_buffers_cache);
if (++i == nbufs)
return i;
cond_resched();
}
- i++;
return i;
}
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 2aa286b4151b..7699b99706ad 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -12040,7 +12040,7 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
/*
* If its not a per-cpu rb, it must be the same task.
*/
- if (output_event->cpu == -1 && output_event->ctx != event->ctx)
+ if (output_event->cpu == -1 && output_event->hw.target != event->hw.target)
goto out;
/*
diff --git a/kernel/fork.c b/kernel/fork.c
index a6d243a50be3..ec913b13c5ed 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -617,6 +617,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
if (retval)
goto out;
+ mt_clear_in_rcu(mas.tree);
mas_for_each(&old_mas, mpnt, ULONG_MAX) {
struct file *file;
@@ -703,6 +704,8 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
retval = arch_dup_mmap(oldmm, mm);
loop_out:
mas_destroy(&mas);
+ if (!retval)
+ mt_set_in_rcu(mas.tree);
out:
mmap_write_unlock(mm);
flush_tlb_mm(oldmm);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 59062fedeaf7..57db50c2dce8 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -5557,12 +5557,15 @@ int modify_ftrace_direct(unsigned long ip,
ret = 0;
}
- if (unlikely(ret && new_direct)) {
- direct->count++;
- list_del_rcu(&new_direct->next);
- synchronize_rcu_tasks();
- kfree(new_direct);
- ftrace_direct_func_count--;
+ if (ret) {
+ direct->addr = old_addr;
+ if (unlikely(new_direct)) {
+ direct->count++;
+ list_del_rcu(&new_direct->next);
+ synchronize_rcu_tasks();
+ kfree(new_direct);
+ ftrace_direct_func_count--;
+ }
}
out_unlock:
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 361bd8beafdf..9d8538531a54 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -3084,6 +3084,10 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
if (RB_WARN_ON(cpu_buffer,
rb_is_reader_page(cpu_buffer->tail_page)))
return;
+ /*
+ * No need for a memory barrier here, as the update
+ * of the tail_page did it for this page.
+ */
local_set(&cpu_buffer->commit_page->page->commit,
rb_page_write(cpu_buffer->commit_page));
rb_inc_page(&cpu_buffer->commit_page);
@@ -3093,6 +3097,8 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
while (rb_commit_index(cpu_buffer) !=
rb_page_write(cpu_buffer->commit_page)) {
+ /* Make sure the readers see the content of what is committed. */
+ smp_wmb();
local_set(&cpu_buffer->commit_page->page->commit,
rb_page_write(cpu_buffer->commit_page));
RB_WARN_ON(cpu_buffer,
@@ -4672,7 +4678,12 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
/*
* Make sure we see any padding after the write update
- * (see rb_reset_tail())
+ * (see rb_reset_tail()).
+ *
+ * In addition, a writer may be writing on the reader page
+ * if the page has not been fully filled, so the read barrier
+ * is also needed to make sure we see the content of what is
+ * committed by the writer (see rb_set_commit_to_write()).
*/
smp_rmb();
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 78d69b9488e4..78855e74e355 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9470,6 +9470,7 @@ static int __remove_instance(struct trace_array *tr)
tracefs_remove(tr->dir);
free_percpu(tr->last_func_repeats);
free_trace_buffers(tr);
+ clear_tracing_err_log(tr);
for (i = 0; i < tr->nr_topts; i++) {
kfree(tr->topts[i].topts);
diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
index 67592eed0be8..89083ae1aebe 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -44,14 +44,21 @@ enum { ERRORS };
static const char *err_text[] = { ERRORS };
+static DEFINE_MUTEX(lastcmd_mutex);
static char *last_cmd;
static int errpos(const char *str)
{
+ int ret = 0;
+
+ mutex_lock(&lastcmd_mutex);
if (!str || !last_cmd)
- return 0;
+ goto out;
- return err_pos(last_cmd, str);
+ ret = err_pos(last_cmd, str);
+ out:
+ mutex_unlock(&lastcmd_mutex);
+ return ret;
}
static void last_cmd_set(const char *str)
@@ -59,18 +66,22 @@ static void last_cmd_set(const char *str)
if (!str)
return;
+ mutex_lock(&lastcmd_mutex);
kfree(last_cmd);
-
last_cmd = kstrdup(str, GFP_KERNEL);
+ mutex_unlock(&lastcmd_mutex);
}
static void synth_err(u8 err_type, u16 err_pos)
{
+ mutex_lock(&lastcmd_mutex);
if (!last_cmd)
- return;
+ goto out;
tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
err_type, err_pos);
+ out:
+ mutex_unlock(&lastcmd_mutex);
}
static int create_synth_event(const char *raw_command);
diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c
index 1c07efcb3d46..689361097bb0 100644
--- a/kernel/trace/trace_osnoise.c
+++ b/kernel/trace/trace_osnoise.c
@@ -1270,7 +1270,7 @@ static void notify_new_max_latency(u64 latency)
rcu_read_lock();
list_for_each_entry_rcu(inst, &osnoise_instances, list) {
tr = inst->tr;
- if (tr->max_latency < latency) {
+ if (tracer_tracing_is_on(tr) && tr->max_latency < latency) {
tr->max_latency = latency;
latency_fsnotify(tr);
}
@@ -1681,6 +1681,8 @@ static int timerlat_main(void *data)
trace_timerlat_sample(&s);
+ notify_new_max_latency(diff);
+
timerlat_dump_stack(time_to_us(diff));
tlat->tracing_thread = false;
diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index 96be96a1f35d..84530fb73bd9 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -149,13 +149,12 @@ struct maple_subtree_state {
/* Functions */
static inline struct maple_node *mt_alloc_one(gfp_t gfp)
{
- return kmem_cache_alloc(maple_node_cache, gfp | __GFP_ZERO);
+ return kmem_cache_alloc(maple_node_cache, gfp);
}
static inline int mt_alloc_bulk(gfp_t gfp, size_t size, void **nodes)
{
- return kmem_cache_alloc_bulk(maple_node_cache, gfp | __GFP_ZERO, size,
- nodes);
+ return kmem_cache_alloc_bulk(maple_node_cache, gfp, size, nodes);
}
static inline void mt_free_bulk(size_t size, void __rcu **nodes)
@@ -530,11 +529,14 @@ static inline struct maple_node *mte_parent(const struct maple_enode *enode)
*/
static inline bool ma_dead_node(const struct maple_node *node)
{
- struct maple_node *parent = (void *)((unsigned long)
- node->parent & ~MAPLE_NODE_MASK);
+ struct maple_node *parent;
+ /* Do not reorder reads from the node prior to the parent check */
+ smp_rmb();
+ parent = (void *)((unsigned long) node->parent & ~MAPLE_NODE_MASK);
return (parent == node);
}
+
/*
* mte_dead_node() - check if the @enode is dead.
* @enode: The encoded maple node
@@ -546,6 +548,8 @@ static inline bool mte_dead_node(const struct maple_enode *enode)
struct maple_node *parent, *node;
node = mte_to_node(enode);
+ /* Do not reorder reads from the node prior to the parent check */
+ smp_rmb();
parent = mte_parent(enode);
return (parent == node);
}
@@ -616,6 +620,8 @@ static inline unsigned int mas_alloc_req(const struct ma_state *mas)
* @node - the maple node
* @type - the node type
*
+ * In the event of a dead node, this array may be %NULL
+ *
* Return: A pointer to the maple node pivots
*/
static inline unsigned long *ma_pivots(struct maple_node *node,
@@ -808,6 +814,11 @@ static inline void *mt_slot(const struct maple_tree *mt,
return rcu_dereference_check(slots[offset], mt_locked(mt));
}
+static inline void *mt_slot_locked(struct maple_tree *mt, void __rcu **slots,
+ unsigned char offset)
+{
+ return rcu_dereference_protected(slots[offset], mt_locked(mt));
+}
/*
* mas_slot_locked() - Get the slot value when holding the maple tree lock.
* @mas: The maple state
@@ -819,7 +830,7 @@ static inline void *mt_slot(const struct maple_tree *mt,
static inline void *mas_slot_locked(struct ma_state *mas, void __rcu **slots,
unsigned char offset)
{
- return rcu_dereference_protected(slots[offset], mt_locked(mas->tree));
+ return mt_slot_locked(mas->tree, slots, offset);
}
/*
@@ -890,6 +901,45 @@ static inline void ma_set_meta(struct maple_node *mn, enum maple_type mt,
meta->end = end;
}
+/*
+ * mt_clear_meta() - clear the metadata information of a node, if it exists
+ * @mt: The maple tree
+ * @mn: The maple node
+ * @type: The maple node type
+ * @offset: The offset of the highest sub-gap in this node.
+ * @end: The end of the data in this node.
+ */
+static inline void mt_clear_meta(struct maple_tree *mt, struct maple_node *mn,
+ enum maple_type type)
+{
+ struct maple_metadata *meta;
+ unsigned long *pivots;
+ void __rcu **slots;
+ void *next;
+
+ switch (type) {
+ case maple_range_64:
+ pivots = mn->mr64.pivot;
+ if (unlikely(pivots[MAPLE_RANGE64_SLOTS - 2])) {
+ slots = mn->mr64.slot;
+ next = mt_slot_locked(mt, slots,
+ MAPLE_RANGE64_SLOTS - 1);
+ if (unlikely((mte_to_node(next) &&
+ mte_node_type(next))))
+ return; /* no metadata, could be node */
+ }
+ fallthrough;
+ case maple_arange_64:
+ meta = ma_meta(mn, type);
+ break;
+ default:
+ return;
+ }
+
+ meta->gap = 0;
+ meta->end = 0;
+}
+
/*
* ma_meta_end() - Get the data end of a node from the metadata
* @mn: The maple node
@@ -1087,8 +1137,11 @@ static int mas_ascend(struct ma_state *mas)
a_type = mas_parent_enum(mas, p_enode);
a_node = mte_parent(p_enode);
a_slot = mte_parent_slot(p_enode);
- pivots = ma_pivots(a_node, a_type);
a_enode = mt_mk_node(a_node, a_type);
+ pivots = ma_pivots(a_node, a_type);
+
+ if (unlikely(ma_dead_node(a_node)))
+ return 1;
if (!set_min && a_slot) {
set_min = true;
@@ -1123,9 +1176,10 @@ static inline struct maple_node *mas_pop_node(struct ma_state *mas)
{
struct maple_alloc *ret, *node = mas->alloc;
unsigned long total = mas_allocated(mas);
+ unsigned int req = mas_alloc_req(mas);
/* nothing or a request pending. */
- if (unlikely(!total))
+ if (WARN_ON(!total))
return NULL;
if (total == 1) {
@@ -1135,27 +1189,25 @@ static inline struct maple_node *mas_pop_node(struct ma_state *mas)
goto single_node;
}
- if (!node->node_count) {
+ if (node->node_count == 1) {
/* Single allocation in this node. */
mas->alloc = node->slot[0];
- node->slot[0] = NULL;
mas->alloc->total = node->total - 1;
ret = node;
goto new_head;
}
-
node->total--;
- ret = node->slot[node->node_count];
- node->slot[node->node_count--] = NULL;
+ ret = node->slot[--node->node_count];
+ node->slot[node->node_count] = NULL;
single_node:
new_head:
- ret->total = 0;
- ret->node_count = 0;
- if (ret->request_count) {
- mas_set_alloc_req(mas, ret->request_count + 1);
- ret->request_count = 0;
+ if (req) {
+ req++;
+ mas_set_alloc_req(mas, req);
}
+
+ memset(ret, 0, sizeof(*ret));
return (struct maple_node *)ret;
}
@@ -1174,21 +1226,20 @@ static inline void mas_push_node(struct ma_state *mas, struct maple_node *used)
unsigned long count;
unsigned int requested = mas_alloc_req(mas);
- memset(reuse, 0, sizeof(*reuse));
count = mas_allocated(mas);
- if (count && (head->node_count < MAPLE_ALLOC_SLOTS - 1)) {
- if (head->slot[0])
- head->node_count++;
- head->slot[head->node_count] = reuse;
+ reuse->request_count = 0;
+ reuse->node_count = 0;
+ if (count && (head->node_count < MAPLE_ALLOC_SLOTS)) {
+ head->slot[head->node_count++] = reuse;
head->total++;
goto done;
}
reuse->total = 1;
if ((head) && !((unsigned long)head & 0x1)) {
- head->request_count = 0;
reuse->slot[0] = head;
+ reuse->node_count = 1;
reuse->total += head->total;
}
@@ -1207,7 +1258,6 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
{
struct maple_alloc *node;
unsigned long allocated = mas_allocated(mas);
- unsigned long success = allocated;
unsigned int requested = mas_alloc_req(mas);
unsigned int count;
void **slots = NULL;
@@ -1223,24 +1273,29 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
WARN_ON(!allocated);
}
- if (!allocated || mas->alloc->node_count == MAPLE_ALLOC_SLOTS - 1) {
+ if (!allocated || mas->alloc->node_count == MAPLE_ALLOC_SLOTS) {
node = (struct maple_alloc *)mt_alloc_one(gfp);
if (!node)
goto nomem_one;
- if (allocated)
+ if (allocated) {
node->slot[0] = mas->alloc;
+ node->node_count = 1;
+ } else {
+ node->node_count = 0;
+ }
- success++;
mas->alloc = node;
+ node->total = ++allocated;
requested--;
}
node = mas->alloc;
+ node->request_count = 0;
while (requested) {
max_req = MAPLE_ALLOC_SLOTS;
- if (node->slot[0]) {
- unsigned int offset = node->node_count + 1;
+ if (node->node_count) {
+ unsigned int offset = node->node_count;
slots = (void **)&node->slot[offset];
max_req -= offset;
@@ -1254,15 +1309,13 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
goto nomem_bulk;
node->node_count += count;
- /* zero indexed. */
- if (slots == (void **)&node->slot)
- node->node_count--;
-
- success += count;
+ allocated += count;
node = node->slot[0];
+ node->node_count = 0;
+ node->request_count = 0;
requested -= count;
}
- mas->alloc->total = success;
+ mas->alloc->total = allocated;
return;
nomem_bulk:
@@ -1271,7 +1324,7 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
nomem_one:
mas_set_alloc_req(mas, requested);
if (mas->alloc && !(((unsigned long)mas->alloc & 0x1)))
- mas->alloc->total = success;
+ mas->alloc->total = allocated;
mas_set_err(mas, -ENOMEM);
return;
@@ -1329,7 +1382,7 @@ static void mas_node_count(struct ma_state *mas, int count)
* mas_start() - Sets up maple state for operations.
* @mas: The maple state.
*
- * If mas->node == MAS_START, then set the min, max, depth, and offset to
+ * If mas->node == MAS_START, then set the min, max and depth to
* defaults.
*
* Return:
@@ -1343,22 +1396,26 @@ static inline struct maple_enode *mas_start(struct ma_state *mas)
if (likely(mas_is_start(mas))) {
struct maple_enode *root;
- mas->node = MAS_NONE;
mas->min = 0;
mas->max = ULONG_MAX;
mas->depth = 0;
- mas->offset = 0;
+retry:
root = mas_root(mas);
/* Tree with nodes */
if (likely(xa_is_node(root))) {
mas->depth = 1;
mas->node = mte_safe_root(root);
+ mas->offset = 0;
+ if (mte_dead_node(mas->node))
+ goto retry;
+
return NULL;
}
/* empty tree */
if (unlikely(!root)) {
+ mas->node = MAS_NONE;
mas->offset = MAPLE_NODE_SLOTS;
return NULL;
}
@@ -1394,6 +1451,9 @@ static inline unsigned char ma_data_end(struct maple_node *node,
{
unsigned char offset;
+ if (!pivots)
+ return 0;
+
if (type == maple_arange_64)
return ma_meta_end(node, type);
@@ -1429,6 +1489,9 @@ static inline unsigned char mas_data_end(struct ma_state *mas)
return ma_meta_end(node, type);
pivots = ma_pivots(node, type);
+ if (unlikely(ma_dead_node(node)))
+ return 0;
+
offset = mt_pivots[type] - 1;
if (likely(!pivots[offset]))
return ma_meta_end(node, type);
@@ -3654,10 +3717,9 @@ static inline int mas_root_expand(struct ma_state *mas, void *entry)
slot++;
mas->depth = 1;
mas_set_height(mas);
-
+ ma_set_meta(node, maple_leaf_64, 0, slot);
/* swap the new root into the tree */
rcu_assign_pointer(mas->tree->ma_root, mte_mk_root(mas->node));
- ma_set_meta(node, maple_leaf_64, 0, slot);
return slot;
}
@@ -3870,18 +3932,13 @@ static inline void *mtree_lookup_walk(struct ma_state *mas)
end = ma_data_end(node, type, pivots, max);
if (unlikely(ma_dead_node(node)))
goto dead_node;
-
- if (pivots[offset] >= mas->index)
- goto next;
-
do {
- offset++;
- } while ((offset < end) && (pivots[offset] < mas->index));
-
- if (likely(offset > end))
- max = pivots[offset];
+ if (pivots[offset] >= mas->index) {
+ max = pivots[offset];
+ break;
+ }
+ } while (++offset < end);
-next:
slots = ma_slots(node, type);
next = mt_slot(mas->tree, slots, offset);
if (unlikely(ma_dead_node(node)))
@@ -4500,6 +4557,9 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
node = mas_mn(mas);
slots = ma_slots(node, mt);
pivots = ma_pivots(node, mt);
+ if (unlikely(ma_dead_node(node)))
+ return 1;
+
mas->max = pivots[offset];
if (offset)
mas->min = pivots[offset - 1] + 1;
@@ -4521,6 +4581,9 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
slots = ma_slots(node, mt);
pivots = ma_pivots(node, mt);
offset = ma_data_end(node, mt, pivots, mas->max);
+ if (unlikely(ma_dead_node(node)))
+ return 1;
+
if (offset)
mas->min = pivots[offset - 1] + 1;
@@ -4569,6 +4632,7 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
struct maple_enode *enode;
int level = 0;
unsigned char offset;
+ unsigned char node_end;
enum maple_type mt;
void __rcu **slots;
@@ -4592,7 +4656,11 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
node = mas_mn(mas);
mt = mte_node_type(mas->node);
pivots = ma_pivots(node, mt);
- } while (unlikely(offset == ma_data_end(node, mt, pivots, mas->max)));
+ node_end = ma_data_end(node, mt, pivots, mas->max);
+ if (unlikely(ma_dead_node(node)))
+ return 1;
+
+ } while (unlikely(offset == node_end));
slots = ma_slots(node, mt);
pivot = mas_safe_pivot(mas, pivots, ++offset, mt);
@@ -4608,6 +4676,9 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
mt = mte_node_type(mas->node);
slots = ma_slots(node, mt);
pivots = ma_pivots(node, mt);
+ if (unlikely(ma_dead_node(node)))
+ return 1;
+
offset = 0;
pivot = pivots[0];
}
@@ -4654,16 +4725,19 @@ static inline void *mas_next_nentry(struct ma_state *mas,
return NULL;
}
- pivots = ma_pivots(node, type);
slots = ma_slots(node, type);
+ pivots = ma_pivots(node, type);
+ count = ma_data_end(node, type, pivots, mas->max);
+ if (unlikely(ma_dead_node(node)))
+ return NULL;
+
mas->index = mas_safe_min(mas, pivots, mas->offset);
- if (ma_dead_node(node))
+ if (unlikely(ma_dead_node(node)))
return NULL;
if (mas->index > max)
return NULL;
- count = ma_data_end(node, type, pivots, mas->max);
if (mas->offset > count)
return NULL;
@@ -4738,6 +4812,11 @@ static inline void *mas_next_entry(struct ma_state *mas, unsigned long limit)
unsigned long last;
enum maple_type mt;
+ if (mas->index > limit) {
+ mas->index = mas->last = limit;
+ mas_pause(mas);
+ return NULL;
+ }
last = mas->last;
retry:
offset = mas->offset;
@@ -4811,6 +4890,11 @@ static inline void *mas_prev_nentry(struct ma_state *mas, unsigned long limit,
slots = ma_slots(mn, mt);
pivots = ma_pivots(mn, mt);
+ if (unlikely(ma_dead_node(mn))) {
+ mas_rewalk(mas, index);
+ goto retry;
+ }
+
if (offset == mt_pivots[mt])
pivot = mas->max;
else
@@ -4844,6 +4928,11 @@ static inline void *mas_prev_entry(struct ma_state *mas, unsigned long min)
{
void *entry;
+ if (mas->index < min) {
+ mas->index = mas->last = min;
+ mas->node = MAS_NONE;
+ return NULL;
+ }
retry:
while (likely(!mas_is_none(mas))) {
entry = mas_prev_nentry(mas, min, mas->index);
@@ -5389,24 +5478,26 @@ static inline int mas_rev_alloc(struct ma_state *mas, unsigned long min,
}
/*
- * mas_dead_leaves() - Mark all leaves of a node as dead.
+ * mte_dead_leaves() - Mark all leaves of a node as dead.
* @mas: The maple state
* @slots: Pointer to the slot array
+ * @type: The maple node type
*
* Must hold the write lock.
*
* Return: The number of leaves marked as dead.
*/
static inline
-unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots)
+unsigned char mte_dead_leaves(struct maple_enode *enode, struct maple_tree *mt,
+ void __rcu **slots)
{
struct maple_node *node;
enum maple_type type;
void *entry;
int offset;
- for (offset = 0; offset < mt_slot_count(mas->node); offset++) {
- entry = mas_slot_locked(mas, slots, offset);
+ for (offset = 0; offset < mt_slot_count(enode); offset++) {
+ entry = mt_slot(mt, slots, offset);
type = mte_node_type(entry);
node = mte_to_node(entry);
/* Use both node and type to catch LE & BE metadata */
@@ -5414,7 +5505,6 @@ unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots)
break;
mte_set_node_dead(entry);
- smp_wmb(); /* Needed for RCU */
node->type = type;
rcu_assign_pointer(slots[offset], node);
}
@@ -5422,151 +5512,160 @@ unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots)
return offset;
}
-static void __rcu **mas_dead_walk(struct ma_state *mas, unsigned char offset)
+/**
+ * mte_dead_walk() - Walk down a dead tree to just before the leaves
+ * @enode: The maple encoded node
+ * @offset: The starting offset
+ *
+ * Note: This can only be used from the RCU callback context.
+ */
+static void __rcu **mte_dead_walk(struct maple_enode **enode, unsigned char offset)
{
struct maple_node *node, *next;
void __rcu **slots = NULL;
- next = mas_mn(mas);
+ next = mte_to_node(*enode);
do {
- mas->node = ma_enode_ptr(next);
- node = mas_mn(mas);
+ *enode = ma_enode_ptr(next);
+ node = mte_to_node(*enode);
slots = ma_slots(node, node->type);
- next = mas_slot_locked(mas, slots, offset);
+ next = rcu_dereference_protected(slots[offset],
+ lock_is_held(&rcu_callback_map));
offset = 0;
} while (!ma_is_leaf(next->type));
return slots;
}
+/**
+ * mt_free_walk() - Walk & free a tree in the RCU callback context
+ * @head: The RCU head that's within the node.
+ *
+ * Note: This can only be used from the RCU callback context.
+ */
static void mt_free_walk(struct rcu_head *head)
{
void __rcu **slots;
struct maple_node *node, *start;
- struct maple_tree mt;
+ struct maple_enode *enode;
unsigned char offset;
enum maple_type type;
- MA_STATE(mas, &mt, 0, 0);
node = container_of(head, struct maple_node, rcu);
if (ma_is_leaf(node->type))
goto free_leaf;
- mt_init_flags(&mt, node->ma_flags);
- mas_lock(&mas);
start = node;
- mas.node = mt_mk_node(node, node->type);
- slots = mas_dead_walk(&mas, 0);
- node = mas_mn(&mas);
+ enode = mt_mk_node(node, node->type);
+ slots = mte_dead_walk(&enode, 0);
+ node = mte_to_node(enode);
do {
mt_free_bulk(node->slot_len, slots);
offset = node->parent_slot + 1;
- mas.node = node->piv_parent;
- if (mas_mn(&mas) == node)
- goto start_slots_free;
-
- type = mte_node_type(mas.node);
- slots = ma_slots(mte_to_node(mas.node), type);
- if ((offset < mt_slots[type]) && (slots[offset]))
- slots = mas_dead_walk(&mas, offset);
-
- node = mas_mn(&mas);
+ enode = node->piv_parent;
+ if (mte_to_node(enode) == node)
+ goto free_leaf;
+
+ type = mte_node_type(enode);
+ slots = ma_slots(mte_to_node(enode), type);
+ if ((offset < mt_slots[type]) &&
+ rcu_dereference_protected(slots[offset],
+ lock_is_held(&rcu_callback_map)))
+ slots = mte_dead_walk(&enode, offset);
+ node = mte_to_node(enode);
} while ((node != start) || (node->slot_len < offset));
slots = ma_slots(node, node->type);
mt_free_bulk(node->slot_len, slots);
-start_slots_free:
- mas_unlock(&mas);
free_leaf:
mt_free_rcu(&node->rcu);
}
-static inline void __rcu **mas_destroy_descend(struct ma_state *mas,
- struct maple_enode *prev, unsigned char offset)
+static inline void __rcu **mte_destroy_descend(struct maple_enode **enode,
+ struct maple_tree *mt, struct maple_enode *prev, unsigned char offset)
{
struct maple_node *node;
- struct maple_enode *next = mas->node;
+ struct maple_enode *next = *enode;
void __rcu **slots = NULL;
+ enum maple_type type;
+ unsigned char next_offset = 0;
do {
- mas->node = next;
- node = mas_mn(mas);
- slots = ma_slots(node, mte_node_type(mas->node));
- next = mas_slot_locked(mas, slots, 0);
+ *enode = next;
+ node = mte_to_node(*enode);
+ type = mte_node_type(*enode);
+ slots = ma_slots(node, type);
+ next = mt_slot_locked(mt, slots, next_offset);
if ((mte_dead_node(next)))
- next = mas_slot_locked(mas, slots, 1);
+ next = mt_slot_locked(mt, slots, ++next_offset);
- mte_set_node_dead(mas->node);
- node->type = mte_node_type(mas->node);
+ mte_set_node_dead(*enode);
+ node->type = type;
node->piv_parent = prev;
node->parent_slot = offset;
- offset = 0;
- prev = mas->node;
+ offset = next_offset;
+ next_offset = 0;
+ prev = *enode;
} while (!mte_is_leaf(next));
return slots;
}
-static void mt_destroy_walk(struct maple_enode *enode, unsigned char ma_flags,
+static void mt_destroy_walk(struct maple_enode *enode, struct maple_tree *mt,
bool free)
{
void __rcu **slots;
struct maple_node *node = mte_to_node(enode);
struct maple_enode *start;
- struct maple_tree mt;
-
- MA_STATE(mas, &mt, 0, 0);
- if (mte_is_leaf(enode))
+ if (mte_is_leaf(enode)) {
+ node->type = mte_node_type(enode);
goto free_leaf;
+ }
- mt_init_flags(&mt, ma_flags);
- mas_lock(&mas);
-
- mas.node = start = enode;
- slots = mas_destroy_descend(&mas, start, 0);
- node = mas_mn(&mas);
+ start = enode;
+ slots = mte_destroy_descend(&enode, mt, start, 0);
+ node = mte_to_node(enode); // Updated in the above call.
do {
enum maple_type type;
unsigned char offset;
struct maple_enode *parent, *tmp;
- node->slot_len = mas_dead_leaves(&mas, slots);
+ node->slot_len = mte_dead_leaves(enode, mt, slots);
if (free)
mt_free_bulk(node->slot_len, slots);
offset = node->parent_slot + 1;
- mas.node = node->piv_parent;
- if (mas_mn(&mas) == node)
- goto start_slots_free;
+ enode = node->piv_parent;
+ if (mte_to_node(enode) == node)
+ goto free_leaf;
- type = mte_node_type(mas.node);
- slots = ma_slots(mte_to_node(mas.node), type);
+ type = mte_node_type(enode);
+ slots = ma_slots(mte_to_node(enode), type);
if (offset >= mt_slots[type])
goto next;
- tmp = mas_slot_locked(&mas, slots, offset);
+ tmp = mt_slot_locked(mt, slots, offset);
if (mte_node_type(tmp) && mte_to_node(tmp)) {
- parent = mas.node;
- mas.node = tmp;
- slots = mas_destroy_descend(&mas, parent, offset);
+ parent = enode;
+ enode = tmp;
+ slots = mte_destroy_descend(&enode, mt, parent, offset);
}
next:
- node = mas_mn(&mas);
- } while (start != mas.node);
+ node = mte_to_node(enode);
+ } while (start != enode);
- node = mas_mn(&mas);
- node->slot_len = mas_dead_leaves(&mas, slots);
+ node = mte_to_node(enode);
+ node->slot_len = mte_dead_leaves(enode, mt, slots);
if (free)
mt_free_bulk(node->slot_len, slots);
-start_slots_free:
- mas_unlock(&mas);
-
free_leaf:
if (free)
mt_free_rcu(&node->rcu);
+ else
+ mt_clear_meta(mt, node, node->type);
}
/*
@@ -5582,15 +5681,18 @@ static inline void mte_destroy_walk(struct maple_enode *enode,
struct maple_node *node = mte_to_node(enode);
if (mt_in_rcu(mt)) {
- mt_destroy_walk(enode, mt->ma_flags, false);
+ mt_destroy_walk(enode, mt, false);
call_rcu(&node->rcu, mt_free_walk);
} else {
- mt_destroy_walk(enode, mt->ma_flags, true);
+ mt_destroy_walk(enode, mt, true);
}
}
static void mas_wr_store_setup(struct ma_wr_state *wr_mas)
{
+ if (unlikely(mas_is_paused(wr_mas->mas)))
+ mas_reset(wr_mas->mas);
+
if (!mas_is_start(wr_mas->mas)) {
if (mas_is_none(wr_mas->mas)) {
mas_reset(wr_mas->mas);
@@ -5726,6 +5828,7 @@ int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp)
void mas_destroy(struct ma_state *mas)
{
struct maple_alloc *node;
+ unsigned long total;
/*
* When using mas_for_each() to insert an expected number of elements,
@@ -5748,14 +5851,20 @@ void mas_destroy(struct ma_state *mas)
}
mas->mas_flags &= ~(MA_STATE_BULK|MA_STATE_PREALLOC);
- while (mas->alloc && !((unsigned long)mas->alloc & 0x1)) {
+ total = mas_allocated(mas);
+ while (total) {
node = mas->alloc;
mas->alloc = node->slot[0];
- if (node->node_count > 0)
- mt_free_bulk(node->node_count,
- (void __rcu **)&node->slot[1]);
+ if (node->node_count > 1) {
+ size_t count = node->node_count - 1;
+
+ mt_free_bulk(count, (void __rcu **)&node->slot[1]);
+ total -= count;
+ }
kmem_cache_free(maple_node_cache, node);
+ total--;
}
+
mas->alloc = NULL;
}
EXPORT_SYMBOL_GPL(mas_destroy);
@@ -5893,6 +6002,7 @@ void *mas_prev(struct ma_state *mas, unsigned long min)
if (!mas->index) {
/* Nothing comes before 0 */
mas->last = 0;
+ mas->node = MAS_NONE;
return NULL;
}
@@ -5983,6 +6093,9 @@ void *mas_find(struct ma_state *mas, unsigned long max)
mas->index = ++mas->last;
}
+ if (unlikely(mas_is_none(mas)))
+ mas->node = MAS_START;
+
if (unlikely(mas_is_start(mas))) {
/* First run or continue */
void *entry;
@@ -6594,11 +6707,11 @@ static inline void *mas_first_entry(struct ma_state *mas, struct maple_node *mn,
while (likely(!ma_is_leaf(mt))) {
MT_BUG_ON(mas->tree, mte_dead_node(mas->node));
slots = ma_slots(mn, mt);
- pivots = ma_pivots(mn, mt);
- max = pivots[0];
entry = mas_slot(mas, slots, 0);
+ pivots = ma_pivots(mn, mt);
if (unlikely(ma_dead_node(mn)))
return NULL;
+ max = pivots[0];
mas->node = entry;
mn = mas_mn(mas);
mt = mte_node_type(mas->node);
@@ -6618,13 +6731,13 @@ static inline void *mas_first_entry(struct ma_state *mas, struct maple_node *mn,
if (likely(entry))
return entry;
- pivots = ma_pivots(mn, mt);
- mas->index = pivots[0] + 1;
mas->offset = 1;
entry = mas_slot(mas, slots, 1);
+ pivots = ma_pivots(mn, mt);
if (unlikely(ma_dead_node(mn)))
return NULL;
+ mas->index = pivots[0] + 1;
if (mas->index > limit)
goto none;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 52475c4262e4..d3ffa0fd49e5 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -5469,7 +5469,7 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
struct page *pagecache_page, spinlock_t *ptl)
{
const bool unshare = flags & FAULT_FLAG_UNSHARE;
- pte_t pte;
+ pte_t pte = huge_ptep_get(ptep);
struct hstate *h = hstate_vma(vma);
struct page *old_page, *new_page;
int outside_reserve = 0;
@@ -5480,6 +5480,17 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
VM_BUG_ON(unshare && (flags & FOLL_WRITE));
VM_BUG_ON(!unshare && !(flags & FOLL_WRITE));
+ /*
+ * Never handle CoW for uffd-wp protected pages. It should be only
+ * handled when the uffd-wp protection is removed.
+ *
+ * Note that only the CoW optimization path (in hugetlb_no_page())
+ * can trigger this, because hugetlb_fault() will always resolve
+ * uffd-wp bit first.
+ */
+ if (!unshare && huge_pte_uffd_wp(pte))
+ return 0;
+
/*
* hugetlb does not support FOLL_FORCE-style write faults that keep the
* PTE mapped R/O such as maybe_mkwrite() would do.
@@ -5495,7 +5506,6 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
return 0;
}
- pte = huge_ptep_get(ptep);
old_page = pte_page(pte);
delayacct_wpcopy_start();
diff --git a/mm/kfence/core.c b/mm/kfence/core.c
index c3d04753806a..a477b7fb8aa3 100644
--- a/mm/kfence/core.c
+++ b/mm/kfence/core.c
@@ -557,15 +557,11 @@ static unsigned long kfence_init_pool(void)
* enters __slab_free() slow-path.
*/
for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) {
- struct slab *slab = page_slab(&pages[i]);
+ struct slab *slab = page_slab(nth_page(pages, i));
if (!i || (i % 2))
continue;
- /* Verify we do not have a compound head page. */
- if (WARN_ON(compound_head(&pages[i]) != &pages[i]))
- return addr;
-
__folio_set_slab(slab_folio(slab));
#ifdef CONFIG_MEMCG
slab->memcg_data = (unsigned long)&kfence_metadata[i / 2 - 1].objcg |
@@ -598,12 +594,26 @@ static unsigned long kfence_init_pool(void)
/* Protect the right redzone. */
if (unlikely(!kfence_protect(addr + PAGE_SIZE)))
- return addr;
+ goto reset_slab;
addr += 2 * PAGE_SIZE;
}
return 0;
+
+reset_slab:
+ for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) {
+ struct slab *slab = page_slab(nth_page(pages, i));
+
+ if (!i || (i % 2))
+ continue;
+#ifdef CONFIG_MEMCG
+ slab->memcg_data = 0;
+#endif
+ __folio_clear_slab(slab_folio(slab));
+ }
+
+ return addr;
}
static bool __init kfence_init_pool_early(void)
@@ -633,16 +643,6 @@ static bool __init kfence_init_pool_early(void)
* fails for the first page, and therefore expect addr==__kfence_pool in
* most failure cases.
*/
- for (char *p = (char *)addr; p < __kfence_pool + KFENCE_POOL_SIZE; p += PAGE_SIZE) {
- struct slab *slab = virt_to_slab(p);
-
- if (!slab)
- continue;
-#ifdef CONFIG_MEMCG
- slab->memcg_data = 0;
-#endif
- __folio_clear_slab(slab_folio(slab));
- }
memblock_free_late(__pa(addr), KFENCE_POOL_SIZE - (addr - (unsigned long)__kfence_pool));
__kfence_pool = NULL;
return false;
diff --git a/mm/memory.c b/mm/memory.c
index f6f93e5b6b02..747b7ea30f89 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3619,8 +3619,21 @@ static vm_fault_t remove_device_exclusive_entry(struct vm_fault *vmf)
struct vm_area_struct *vma = vmf->vma;
struct mmu_notifier_range range;
- if (!folio_lock_or_retry(folio, vma->vm_mm, vmf->flags))
+ /*
+ * We need a reference to lock the folio because we don't hold
+ * the PTL so a racing thread can remove the device-exclusive
+ * entry and unmap it. If the folio is free the entry must
+ * have been removed already. If it happens to have already
+ * been re-allocated after being freed all we do is lock and
+ * unlock it.
+ */
+ if (!folio_try_get(folio))
+ return 0;
+
+ if (!folio_lock_or_retry(folio, vma->vm_mm, vmf->flags)) {
+ folio_put(folio);
return VM_FAULT_RETRY;
+ }
mmu_notifier_range_init_owner(&range, MMU_NOTIFY_EXCLUSIVE, 0, vma,
vma->vm_mm, vmf->address & PAGE_MASK,
(vmf->address & PAGE_MASK) + PAGE_SIZE, NULL);
@@ -3633,6 +3646,7 @@ static vm_fault_t remove_device_exclusive_entry(struct vm_fault *vmf)
pte_unmap_unlock(vmf->pte, vmf->ptl);
folio_unlock(folio);
+ folio_put(folio);
mmu_notifier_invalidate_range_end(&range);
return 0;
diff --git a/mm/mmap.c b/mm/mmap.c
index 177714886849..fe1db604dc49 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2308,7 +2308,7 @@ do_mas_align_munmap(struct ma_state *mas, struct vm_area_struct *vma,
int count = 0;
int error = -ENOMEM;
MA_STATE(mas_detach, &mt_detach, 0, 0);
- mt_init_flags(&mt_detach, MT_FLAGS_LOCK_EXTERN);
+ mt_init_flags(&mt_detach, mas->tree->ma_flags & MT_FLAGS_LOCK_MASK);
mt_set_external_lock(&mt_detach, &mm->mmap_lock);
if (mas_preallocate(mas, vma, GFP_KERNEL))
@@ -3095,6 +3095,7 @@ void exit_mmap(struct mm_struct *mm)
*/
set_bit(MMF_OOM_SKIP, &mm->flags);
mmap_write_lock(mm);
+ mt_clear_in_rcu(&mm->mm_mt);
free_pgtables(&tlb, &mm->mm_mt, vma, FIRST_USER_ADDRESS,
USER_PGTABLES_CEILING);
tlb_finish_mmu(&tlb);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index b72908df52ac..71db6d8a1ea3 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -679,6 +679,7 @@ static void __del_from_avail_list(struct swap_info_struct *p)
{
int nid;
+ assert_spin_locked(&p->lock);
for_each_node(nid)
plist_del(&p->avail_lists[nid], &swap_avail_heads[nid]);
}
@@ -2428,8 +2429,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
spin_unlock(&swap_lock);
goto out_dput;
}
- del_from_avail_list(p);
spin_lock(&p->lock);
+ del_from_avail_list(p);
if (p->prio < 0) {
struct swap_info_struct *si = p;
int nid;
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index ccaa461998f3..d606e53c650e 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -3056,9 +3056,11 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
* allocation request, free them via __vfree() if any.
*/
if (area->nr_pages != nr_small_pages) {
- warn_alloc(gfp_mask, NULL,
- "vmalloc error: size %lu, page order %u, failed to allocate pages",
- area->nr_pages * PAGE_SIZE, page_order);
+ /* vm_area_alloc_pages() can also fail due to a fatal signal */
+ if (!fatal_signal_pending(current))
+ warn_alloc(gfp_mask, NULL,
+ "vmalloc error: size %lu, page order %u, failed to allocate pages",
+ area->nr_pages * PAGE_SIZE, page_order);
goto fail;
}
diff --git a/net/can/isotp.c b/net/can/isotp.c
index 9bc344851704..5761d4ab839d 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -119,7 +119,8 @@ enum {
ISOTP_WAIT_FIRST_FC,
ISOTP_WAIT_FC,
ISOTP_WAIT_DATA,
- ISOTP_SENDING
+ ISOTP_SENDING,
+ ISOTP_SHUTDOWN,
};
struct tpcon {
@@ -880,8 +881,8 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
txtimer);
struct sock *sk = &so->sk;
- /* don't handle timeouts in IDLE state */
- if (so->tx.state == ISOTP_IDLE)
+ /* don't handle timeouts in IDLE or SHUTDOWN state */
+ if (so->tx.state == ISOTP_IDLE || so->tx.state == ISOTP_SHUTDOWN)
return HRTIMER_NORESTART;
/* we did not get any flow control or echo frame in time */
@@ -918,7 +919,6 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
{
struct sock *sk = sock->sk;
struct isotp_sock *so = isotp_sk(sk);
- u32 old_state = so->tx.state;
struct sk_buff *skb;
struct net_device *dev;
struct canfd_frame *cf;
@@ -928,23 +928,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
int off;
int err;
- if (!so->bound)
+ if (!so->bound || so->tx.state == ISOTP_SHUTDOWN)
return -EADDRNOTAVAIL;
+wait_free_buffer:
/* we do not support multiple buffers - for now */
- if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE ||
- wq_has_sleeper(&so->wait)) {
- if (msg->msg_flags & MSG_DONTWAIT) {
- err = -EAGAIN;
- goto err_out;
- }
+ if (wq_has_sleeper(&so->wait) && (msg->msg_flags & MSG_DONTWAIT))
+ return -EAGAIN;
- /* wait for complete transmission of current pdu */
- err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
- if (err)
- goto err_out;
+ /* wait for complete transmission of current pdu */
+ err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ if (err)
+ goto err_event_drop;
- so->tx.state = ISOTP_SENDING;
+ if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) {
+ if (so->tx.state == ISOTP_SHUTDOWN)
+ return -EADDRNOTAVAIL;
+
+ goto wait_free_buffer;
}
if (!size || size > MAX_MSG_LENGTH) {
@@ -1074,7 +1075,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (wait_tx_done) {
/* wait for complete transmission of current pdu */
- wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ if (err)
+ goto err_event_drop;
if (sk->sk_err)
return -sk->sk_err;
@@ -1082,13 +1085,15 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
return size;
+err_event_drop:
+ /* got signal: force tx state machine to be idle */
+ so->tx.state = ISOTP_IDLE;
+ hrtimer_cancel(&so->txfrtimer);
+ hrtimer_cancel(&so->txtimer);
err_out_drop:
/* drop this PDU and unlock a potential wait queue */
- old_state = ISOTP_IDLE;
-err_out:
- so->tx.state = old_state;
- if (so->tx.state == ISOTP_IDLE)
- wake_up_interruptible(&so->wait);
+ so->tx.state = ISOTP_IDLE;
+ wake_up_interruptible(&so->wait);
return err;
}
@@ -1120,7 +1125,7 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
if (ret < 0)
goto out_err;
- sock_recv_timestamp(msg, sk, skb);
+ sock_recv_cmsgs(msg, sk, skb);
if (msg->msg_name) {
__sockaddr_check_size(ISOTP_MIN_NAMELEN);
@@ -1150,10 +1155,12 @@ static int isotp_release(struct socket *sock)
net = sock_net(sk);
/* wait for complete transmission of current pdu */
- wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ while (wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0 &&
+ cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SHUTDOWN) != ISOTP_IDLE)
+ ;
/* force state machines to be idle also when a signal occurred */
- so->tx.state = ISOTP_IDLE;
+ so->tx.state = ISOTP_SHUTDOWN;
so->rx.state = ISOTP_IDLE;
spin_lock(&isotp_notifier_lock);
@@ -1608,6 +1615,21 @@ static int isotp_init(struct sock *sk)
return 0;
}
+static __poll_t isotp_poll(struct file *file, struct socket *sock, poll_table *wait)
+{
+ struct sock *sk = sock->sk;
+ struct isotp_sock *so = isotp_sk(sk);
+
+ __poll_t mask = datagram_poll(file, sock, wait);
+ poll_wait(file, &so->wait, wait);
+
+ /* Check for false positives due to TX state */
+ if ((mask & EPOLLWRNORM) && (so->tx.state != ISOTP_IDLE))
+ mask &= ~(EPOLLOUT | EPOLLWRNORM);
+
+ return mask;
+}
+
static int isotp_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd,
unsigned long arg)
{
@@ -1623,7 +1645,7 @@ static const struct proto_ops isotp_ops = {
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = isotp_getname,
- .poll = datagram_poll,
+ .poll = isotp_poll,
.ioctl = isotp_sock_no_ioctlcmd,
.gettstamp = sock_gettstamp,
.listen = sock_no_listen,
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index 848b60c9ef79..bd8ec2433832 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -604,7 +604,10 @@ sk_buff *j1939_tp_tx_dat_new(struct j1939_priv *priv,
/* reserve CAN header */
skb_reserve(skb, offsetof(struct can_frame, data));
- memcpy(skb->cb, re_skcb, sizeof(skb->cb));
+ /* skb->cb must be large enough to hold a j1939_sk_buff_cb structure */
+ BUILD_BUG_ON(sizeof(skb->cb) < sizeof(*re_skcb));
+
+ memcpy(skb->cb, re_skcb, sizeof(*re_skcb));
skcb = j1939_skb_to_cb(skb);
if (swap_src_dst)
j1939_skbcb_swap(skcb);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 9be762e1d042..4ac8d0ad9f6f 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -137,6 +137,20 @@ static void queue_process(struct work_struct *work)
}
}
+static int netif_local_xmit_active(struct net_device *dev)
+{
+ int i;
+
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+
+ if (READ_ONCE(txq->xmit_lock_owner) == smp_processor_id())
+ return 1;
+ }
+
+ return 0;
+}
+
static void poll_one_napi(struct napi_struct *napi)
{
int work;
@@ -183,7 +197,10 @@ void netpoll_poll_dev(struct net_device *dev)
if (!ni || down_trylock(&ni->dev_lock))
return;
- if (!netif_running(dev)) {
+ /* Some drivers will take the same locks in poll and xmit,
+ * we can't poll if local CPU is already in xmit.
+ */
+ if (!netif_running(dev) || netif_local_xmit_active(dev)) {
up(&ni->dev_lock);
return;
}
diff --git a/net/ethtool/linkmodes.c b/net/ethtool/linkmodes.c
index 126e06c713a3..2d91f2a8c762 100644
--- a/net/ethtool/linkmodes.c
+++ b/net/ethtool/linkmodes.c
@@ -282,11 +282,12 @@ static int ethnl_update_linkmodes(struct genl_info *info, struct nlattr **tb,
"lanes configuration not supported by device");
return -EOPNOTSUPP;
}
- } else if (!lsettings->autoneg) {
- /* If autoneg is off and lanes parameter is not passed from user,
- * set the lanes parameter to 0.
+ } else if (!lsettings->autoneg && ksettings->lanes) {
+ /* If autoneg is off and lanes parameter is not passed from user but
+ * it was defined previously then set the lanes parameter to 0.
*/
ksettings->lanes = 0;
+ *mod = true;
}
ret = ethnl_update_bitset(ksettings->link_modes.advertising,
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index d5d745c3e345..2b09ef70752f 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -746,6 +746,11 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
room = 576;
room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen;
room -= sizeof(struct icmphdr);
+ /* Guard against tiny mtu. We need to include at least one
+ * IP network header for this message to make any sense.
+ */
+ if (room <= (int)sizeof(struct iphdr))
+ goto ende;
icmp_param.data_len = skb_in->len - icmp_param.offset;
if (icmp_param.data_len > room)
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 409ec2a1f95b..5178a3f3cb53 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -1089,13 +1089,13 @@ static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos)
}
void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family)
- __acquires(RCU)
+ __acquires(ping_table.lock)
{
struct ping_iter_state *state = seq->private;
state->bucket = 0;
state->family = family;
- rcu_read_lock();
+ spin_lock(&ping_table.lock);
return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN;
}
@@ -1121,9 +1121,9 @@ void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos)
EXPORT_SYMBOL_GPL(ping_seq_next);
void ping_seq_stop(struct seq_file *seq, void *v)
- __releases(RCU)
+ __releases(ping_table.lock)
{
- rcu_read_unlock();
+ spin_unlock(&ping_table.lock);
}
EXPORT_SYMBOL_GPL(ping_seq_stop);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 006c1f0ed8b4..af03aa8a8e51 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -91,12 +91,12 @@ EXPORT_SYMBOL_GPL(raw_v4_hashinfo);
int raw_hash_sk(struct sock *sk)
{
struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
- struct hlist_nulls_head *hlist;
+ struct hlist_head *hlist;
- hlist = &h->ht[inet_sk(sk)->inet_num & (RAW_HTABLE_SIZE - 1)];
+ hlist = &h->ht[raw_hashfunc(sock_net(sk), inet_sk(sk)->inet_num)];
spin_lock(&h->lock);
- __sk_nulls_add_node_rcu(sk, hlist);
+ sk_add_node_rcu(sk, hlist);
sock_set_flag(sk, SOCK_RCU_FREE);
spin_unlock(&h->lock);
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
@@ -110,7 +110,7 @@ void raw_unhash_sk(struct sock *sk)
struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
spin_lock(&h->lock);
- if (__sk_nulls_del_node_init_rcu(sk))
+ if (sk_del_node_init_rcu(sk))
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
spin_unlock(&h->lock);
}
@@ -160,19 +160,18 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
* RFC 1122: SHOULD pass TOS value up to the transport layer.
* -> It does. And not only TOS, but all IP header.
*/
-static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
+static int raw_v4_input(struct net *net, struct sk_buff *skb,
+ const struct iphdr *iph, int hash)
{
- struct net *net = dev_net(skb->dev);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
int sdif = inet_sdif(skb);
+ struct hlist_head *hlist;
int dif = inet_iif(skb);
int delivered = 0;
struct sock *sk;
hlist = &raw_v4_hashinfo.ht[hash];
rcu_read_lock();
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
if (!raw_v4_match(net, sk, iph->protocol,
iph->saddr, iph->daddr, dif, sdif))
continue;
@@ -193,9 +192,10 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
int raw_local_deliver(struct sk_buff *skb, int protocol)
{
- int hash = protocol & (RAW_HTABLE_SIZE - 1);
+ struct net *net = dev_net(skb->dev);
- return raw_v4_input(skb, ip_hdr(skb), hash);
+ return raw_v4_input(net, skb, ip_hdr(skb),
+ raw_hashfunc(net, protocol));
}
static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
@@ -263,19 +263,18 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
{
struct net *net = dev_net(skb->dev);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
int dif = skb->dev->ifindex;
int sdif = inet_sdif(skb);
+ struct hlist_head *hlist;
const struct iphdr *iph;
struct sock *sk;
int hash;
- hash = protocol & (RAW_HTABLE_SIZE - 1);
+ hash = raw_hashfunc(net, protocol);
hlist = &raw_v4_hashinfo.ht[hash];
rcu_read_lock();
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
iph = (const struct iphdr *)skb->data;
if (!raw_v4_match(net, sk, iph->protocol,
iph->daddr, iph->saddr, dif, sdif))
@@ -947,14 +946,13 @@ static struct sock *raw_get_first(struct seq_file *seq, int bucket)
{
struct raw_hashinfo *h = pde_data(file_inode(seq->file));
struct raw_iter_state *state = raw_seq_private(seq);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
+ struct hlist_head *hlist;
struct sock *sk;
for (state->bucket = bucket; state->bucket < RAW_HTABLE_SIZE;
++state->bucket) {
hlist = &h->ht[state->bucket];
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each(sk, hlist) {
if (sock_net(sk) == seq_file_net(seq))
return sk;
}
@@ -967,7 +965,7 @@ static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk)
struct raw_iter_state *state = raw_seq_private(seq);
do {
- sk = sk_nulls_next(sk);
+ sk = sk_next(sk);
} while (sk && sock_net(sk) != seq_file_net(seq));
if (!sk)
@@ -986,9 +984,12 @@ static struct sock *raw_get_idx(struct seq_file *seq, loff_t pos)
}
void *raw_seq_start(struct seq_file *seq, loff_t *pos)
- __acquires(RCU)
+ __acquires(&h->lock)
{
- rcu_read_lock();
+ struct raw_hashinfo *h = pde_data(file_inode(seq->file));
+
+ spin_lock(&h->lock);
+
return *pos ? raw_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
}
EXPORT_SYMBOL_GPL(raw_seq_start);
@@ -1007,9 +1008,11 @@ void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos)
EXPORT_SYMBOL_GPL(raw_seq_next);
void raw_seq_stop(struct seq_file *seq, void *v)
- __releases(RCU)
+ __releases(&h->lock)
{
- rcu_read_unlock();
+ struct raw_hashinfo *h = pde_data(file_inode(seq->file));
+
+ spin_unlock(&h->lock);
}
EXPORT_SYMBOL_GPL(raw_seq_stop);
diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c
index 999321834b94..da3591a66a16 100644
--- a/net/ipv4/raw_diag.c
+++ b/net/ipv4/raw_diag.c
@@ -57,8 +57,7 @@ static bool raw_lookup(struct net *net, struct sock *sk,
static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 *r)
{
struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
+ struct hlist_head *hlist;
struct sock *sk;
int slot;
@@ -68,7 +67,7 @@ static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2
rcu_read_lock();
for (slot = 0; slot < RAW_HTABLE_SIZE; slot++) {
hlist = &hashinfo->ht[slot];
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
if (raw_lookup(net, sk, r)) {
/*
* Grab it and keep until we fill
@@ -142,9 +141,8 @@ static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
struct net *net = sock_net(skb->sk);
struct inet_diag_dump_data *cb_data;
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
int num, s_num, slot, s_slot;
+ struct hlist_head *hlist;
struct sock *sk = NULL;
struct nlattr *bc;
@@ -161,7 +159,7 @@ static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
num = 0;
hlist = &hashinfo->ht[slot];
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
struct inet_sock *inet = inet_sk(sk);
if (!net_eq(sock_net(sk), net))
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index c314fdde0097..95a55c6630ad 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1965,8 +1965,13 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
if (proto == IPPROTO_ICMPV6) {
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
+ u8 icmp6_type;
- ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type);
+ if (sk->sk_socket->type == SOCK_RAW && !inet_sk(sk)->hdrincl)
+ icmp6_type = fl6->fl6_icmp_type;
+ else
+ icmp6_type = icmp6_hdr(skb)->icmp6_type;
+ ICMP6MSGOUT_INC_STATS(net, idev, icmp6_type);
ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 8ffeac745656..9ee1506e23ab 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -141,10 +141,9 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister);
static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
{
struct net *net = dev_net(skb->dev);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
const struct in6_addr *saddr;
const struct in6_addr *daddr;
+ struct hlist_head *hlist;
struct sock *sk;
bool delivered = false;
__u8 hash;
@@ -152,10 +151,10 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
saddr = &ipv6_hdr(skb)->saddr;
daddr = saddr + 1;
- hash = nexthdr & (RAW_HTABLE_SIZE - 1);
+ hash = raw_hashfunc(net, nexthdr);
hlist = &raw_v6_hashinfo.ht[hash];
rcu_read_lock();
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
int filtered;
if (!raw_v6_match(net, sk, nexthdr, daddr, saddr,
@@ -333,15 +332,14 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
u8 type, u8 code, int inner_offset, __be32 info)
{
struct net *net = dev_net(skb->dev);
- struct hlist_nulls_head *hlist;
- struct hlist_nulls_node *hnode;
+ struct hlist_head *hlist;
struct sock *sk;
int hash;
- hash = nexthdr & (RAW_HTABLE_SIZE - 1);
+ hash = raw_hashfunc(net, nexthdr);
hlist = &raw_v6_hashinfo.ht[hash];
rcu_read_lock();
- sk_nulls_for_each(sk, hnode, hlist) {
+ sk_for_each_rcu(sk, hlist) {
/* Note: ipv6_hdr(skb) != skb->data */
const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data;
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 4db5a554bdbd..41a74fc84ca1 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -677,8 +677,8 @@ MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
MODULE_DESCRIPTION("L2TP over IP");
MODULE_VERSION("1.0");
-/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like
- * enums
+/* Use the values of SOCK_DGRAM (2) as type and IPPROTO_L2TP (115) as protocol,
+ * because __stringify doesn't like enums
*/
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP);
-MODULE_ALIAS_NET_PF_PROTO(PF_INET, IPPROTO_L2TP);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 115, 2);
+MODULE_ALIAS_NET_PF_PROTO(PF_INET, 115);
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 9dbd801ddb98..9db7f4f5a441 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -808,8 +808,8 @@ MODULE_AUTHOR("Chris Elston <celston@katalix.com>");
MODULE_DESCRIPTION("L2TP IP encapsulation for IPv6");
MODULE_VERSION("1.0");
-/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like
- * enums
+/* Use the values of SOCK_DGRAM (2) as type and IPPROTO_L2TP (115) as protocol,
+ * because __stringify doesn't like enums
*/
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 2, IPPROTO_L2TP);
-MODULE_ALIAS_NET_PF_PROTO(PF_INET6, IPPROTO_L2TP);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 115, 2);
+MODULE_ALIAS_NET_PF_PROTO(PF_INET6, 115);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 3603cbc16757..30efa26f977f 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1242,7 +1242,8 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
list_del_rcu(&sta->list);
sta->removed = true;
- drv_sta_pre_rcu_remove(local, sta->sdata, sta);
+ if (sta->uploaded)
+ drv_sta_pre_rcu_remove(local, sta->sdata, sta);
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
rcu_access_pointer(sdata->u.vlan.sta) == sta)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index ed53c51bbc32..0785d9393e71 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -4785,7 +4785,7 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype)
&eht_cap->eht_cap_elem,
is_ap);
return 2 + 1 +
- sizeof(he_cap->he_cap_elem) + n +
+ sizeof(eht_cap->eht_cap_elem) + n +
ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
eht_cap->eht_cap_elem.phy_cap_info);
return 0;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index e50671296791..99622c64081c 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1941,7 +1941,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
struct scm_cookie scm;
struct sock *sk = sock->sk;
struct netlink_sock *nlk = nlk_sk(sk);
- size_t copied;
+ size_t copied, max_recvmsg_len;
struct sk_buff *skb, *data_skb;
int err, ret;
@@ -1974,9 +1974,10 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
#endif
/* Record the max length of recvmsg() calls for future allocations */
- nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len);
- nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len,
- SKB_WITH_OVERHEAD(32768));
+ max_recvmsg_len = max(READ_ONCE(nlk->max_recvmsg_len), len);
+ max_recvmsg_len = min_t(size_t, max_recvmsg_len,
+ SKB_WITH_OVERHEAD(32768));
+ WRITE_ONCE(nlk->max_recvmsg_len, max_recvmsg_len);
copied = data_skb->len;
if (len < copied) {
@@ -2225,6 +2226,7 @@ static int netlink_dump(struct sock *sk)
struct netlink_ext_ack extack = {};
struct netlink_callback *cb;
struct sk_buff *skb = NULL;
+ size_t max_recvmsg_len;
struct module *module;
int err = -ENOBUFS;
int alloc_min_size;
@@ -2247,8 +2249,9 @@ static int netlink_dump(struct sock *sk)
cb = &nlk->cb;
alloc_min_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
- if (alloc_min_size < nlk->max_recvmsg_len) {
- alloc_size = nlk->max_recvmsg_len;
+ max_recvmsg_len = READ_ONCE(nlk->max_recvmsg_len);
+ if (alloc_min_size < max_recvmsg_len) {
+ alloc_size = max_recvmsg_len;
skb = alloc_skb(alloc_size,
(GFP_KERNEL & ~__GFP_DIRECT_RECLAIM) |
__GFP_NOWARN | __GFP_NORETRY);
diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c
index 5c2fb992803b..3a70255c8d02 100644
--- a/net/qrtr/af_qrtr.c
+++ b/net/qrtr/af_qrtr.c
@@ -393,10 +393,12 @@ static struct qrtr_node *qrtr_node_lookup(unsigned int nid)
struct qrtr_node *node;
unsigned long flags;
+ mutex_lock(&qrtr_node_lock);
spin_lock_irqsave(&qrtr_nodes_lock, flags);
node = radix_tree_lookup(&qrtr_nodes, nid);
node = qrtr_node_acquire(node);
spin_unlock_irqrestore(&qrtr_nodes_lock, flags);
+ mutex_unlock(&qrtr_node_lock);
return node;
}
diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c
index e595079c2caf..3e40a1ba48f7 100644
--- a/net/qrtr/ns.c
+++ b/net/qrtr/ns.c
@@ -273,7 +273,7 @@ static struct qrtr_server *server_add(unsigned int service,
return NULL;
}
-static int server_del(struct qrtr_node *node, unsigned int port)
+static int server_del(struct qrtr_node *node, unsigned int port, bool bcast)
{
struct qrtr_lookup *lookup;
struct qrtr_server *srv;
@@ -286,7 +286,7 @@ static int server_del(struct qrtr_node *node, unsigned int port)
radix_tree_delete(&node->servers, port);
/* Broadcast the removal of local servers */
- if (srv->node == qrtr_ns.local_node)
+ if (srv->node == qrtr_ns.local_node && bcast)
service_announce_del(&qrtr_ns.bcast_sq, srv);
/* Announce the service's disappearance to observers */
@@ -372,7 +372,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from)
}
slot = radix_tree_iter_resume(slot, &iter);
rcu_read_unlock();
- server_del(node, srv->port);
+ server_del(node, srv->port, true);
rcu_read_lock();
}
rcu_read_unlock();
@@ -458,10 +458,13 @@ static int ctrl_cmd_del_client(struct sockaddr_qrtr *from,
kfree(lookup);
}
- /* Remove the server belonging to this port */
+ /* Remove the server belonging to this port but don't broadcast
+ * DEL_SERVER. Neighbours would've already removed the server belonging
+ * to this port due to the DEL_CLIENT broadcast from qrtr_port_remove().
+ */
node = node_get(node_id);
if (node)
- server_del(node, port);
+ server_del(node, port, false);
/* Advertise the removal of this client to all local servers */
local_node = node_get(qrtr_ns.local_node);
@@ -566,7 +569,7 @@ static int ctrl_cmd_del_server(struct sockaddr_qrtr *from,
if (!node)
return -ENOENT;
- return server_del(node, port);
+ return server_del(node, port, true);
}
static int ctrl_cmd_new_lookup(struct sockaddr_qrtr *from,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 83628c347744..507b2ad5ef7c 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1829,6 +1829,10 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len);
if (err)
goto err;
+ if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) {
+ err = -EINVAL;
+ goto err;
+ }
}
if (sctp_state(asoc, CLOSED)) {
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index b1efc34db6ed..609ade4fb49e 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -416,14 +416,23 @@ static int unix_gid_hash(kuid_t uid)
return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS);
}
-static void unix_gid_put(struct kref *kref)
+static void unix_gid_free(struct rcu_head *rcu)
{
- struct cache_head *item = container_of(kref, struct cache_head, ref);
- struct unix_gid *ug = container_of(item, struct unix_gid, h);
+ struct unix_gid *ug = container_of(rcu, struct unix_gid, rcu);
+ struct cache_head *item = &ug->h;
+
if (test_bit(CACHE_VALID, &item->flags) &&
!test_bit(CACHE_NEGATIVE, &item->flags))
put_group_info(ug->gi);
- kfree_rcu(ug, rcu);
+ kfree(ug);
+}
+
+static void unix_gid_put(struct kref *kref)
+{
+ struct cache_head *item = container_of(kref, struct cache_head, ref);
+ struct unix_gid *ug = container_of(item, struct unix_gid, h);
+
+ call_rcu(&ug->rcu, unix_gid_free);
}
static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 9ea633fe9339..4ffa3a59f419 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -81,6 +81,7 @@ struct hdmi_spec_per_pin {
struct delayed_work work;
struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/
int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */
+ int prev_pcm_idx; /* previously assigned pcm index */
int repoll_count;
bool setup; /* the stream has been set up by prepare callback */
bool silent_stream;
@@ -1380,9 +1381,17 @@ static void hdmi_attach_hda_pcm(struct hdmi_spec *spec,
/* pcm already be attached to the pin */
if (per_pin->pcm)
return;
+ /* try the previously used slot at first */
+ idx = per_pin->prev_pcm_idx;
+ if (idx >= 0) {
+ if (!test_bit(idx, &spec->pcm_bitmap))
+ goto found;
+ per_pin->prev_pcm_idx = -1; /* no longer valid, clear it */
+ }
idx = hdmi_find_pcm_slot(spec, per_pin);
if (idx == -EBUSY)
return;
+ found:
per_pin->pcm_idx = idx;
per_pin->pcm = get_hdmi_pcm(spec, idx);
set_bit(idx, &spec->pcm_bitmap);
@@ -1398,6 +1407,7 @@ static void hdmi_detach_hda_pcm(struct hdmi_spec *spec,
return;
idx = per_pin->pcm_idx;
per_pin->pcm_idx = -1;
+ per_pin->prev_pcm_idx = idx; /* remember the previous index */
per_pin->pcm = NULL;
if (idx >= 0 && idx < spec->pcm_used)
clear_bit(idx, &spec->pcm_bitmap);
@@ -1924,6 +1934,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
per_pin->pcm = NULL;
per_pin->pcm_idx = -1;
+ per_pin->prev_pcm_idx = -1;
per_pin->pin_nid = pin_nid;
per_pin->pin_nid_idx = spec->num_nids;
per_pin->dev_id = i;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 070150bbd355..50b8573b5206 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2624,6 +2624,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
+ SND_PCI_QUIRK(0x1558, 0x3702, "Clevo X370SN[VW]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
@@ -9442,6 +9443,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8b47, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+ SND_PCI_QUIRK(0x103c, 0x8b66, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b7a, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b7d, "HP", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b87, "HP", ALC236_FIXUP_HP_GPIO_LED),
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index cb23650ad522..d8e83150ea28 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -436,23 +436,28 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_device *hdev,
return 0;
}
-static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai,
- unsigned int tx_mask, unsigned int rx_mask,
- int slots, int slot_width)
+static int hdac_hdmi_set_stream(struct snd_soc_dai *dai,
+ void *stream, int direction)
{
struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai);
struct hdac_device *hdev = hdmi->hdev;
struct hdac_hdmi_dai_port_map *dai_map;
struct hdac_hdmi_pcm *pcm;
+ struct hdac_stream *hstream;
- dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, tx_mask);
+ if (!stream)
+ return -EINVAL;
+
+ hstream = (struct hdac_stream *)stream;
+
+ dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, hstream->stream_tag);
dai_map = &hdmi->dai_map[dai->id];
pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
if (pcm)
- pcm->stream_tag = (tx_mask << 4);
+ pcm->stream_tag = (hstream->stream_tag << 4);
return 0;
}
@@ -1544,7 +1549,7 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = {
.startup = hdac_hdmi_pcm_open,
.shutdown = hdac_hdmi_pcm_close,
.hw_params = hdac_hdmi_set_hw_params,
- .set_tdm_slot = hdac_hdmi_set_tdm_slot,
+ .set_stream = hdac_hdmi_set_stream,
};
/*
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
index 8621cfabcf5b..1639f3b66fac 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -3667,9 +3667,9 @@ static int __maybe_unused rx_macro_runtime_suspend(struct device *dev)
regcache_cache_only(rx->regmap, true);
regcache_mark_dirty(rx->regmap);
- clk_disable_unprepare(rx->mclk);
- clk_disable_unprepare(rx->npl);
clk_disable_unprepare(rx->fsgen);
+ clk_disable_unprepare(rx->npl);
+ clk_disable_unprepare(rx->mclk);
return 0;
}
diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c
index e5611f655bed..d1d9d8d2df2d 100644
--- a/sound/soc/codecs/lpass-tx-macro.c
+++ b/sound/soc/codecs/lpass-tx-macro.c
@@ -1946,9 +1946,9 @@ static int __maybe_unused tx_macro_runtime_suspend(struct device *dev)
regcache_cache_only(tx->regmap, true);
regcache_mark_dirty(tx->regmap);
- clk_disable_unprepare(tx->mclk);
- clk_disable_unprepare(tx->npl);
clk_disable_unprepare(tx->fsgen);
+ clk_disable_unprepare(tx->npl);
+ clk_disable_unprepare(tx->mclk);
return 0;
}
diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
index c012033fb69e..8ed48c86ccb3 100644
--- a/sound/soc/codecs/lpass-wsa-macro.c
+++ b/sound/soc/codecs/lpass-wsa-macro.c
@@ -2502,9 +2502,9 @@ static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev)
regcache_cache_only(wsa->regmap, true);
regcache_mark_dirty(wsa->regmap);
- clk_disable_unprepare(wsa->mclk);
- clk_disable_unprepare(wsa->npl);
clk_disable_unprepare(wsa->fsgen);
+ clk_disable_unprepare(wsa->npl);
+ clk_disable_unprepare(wsa->mclk);
return 0;
}
diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c
index 6eaa18e27e5a..c08f3960ddd9 100644
--- a/sound/soc/sof/ipc4.c
+++ b/sound/soc/sof/ipc4.c
@@ -392,6 +392,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_
static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
size_t payload_bytes, bool set)
{
+ const struct sof_dsp_power_state target_state = {
+ .state = SOF_DSP_PM_D0,
+ };
size_t payload_limit = sdev->ipc->max_payload_size;
struct sof_ipc4_msg *ipc4_msg = data;
struct sof_ipc4_msg tx = {{ 0 }};
@@ -422,6 +425,11 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
tx.extension |= SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(1);
+ /* ensure the DSP is in D0i0 before sending IPC */
+ ret = snd_sof_dsp_set_power_state(sdev, &target_state);
+ if (ret < 0)
+ return ret;
+
/* Serialise IPC TX */
mutex_lock(&sdev->ipc->tx_mutex);
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index 56102711f395..80a15a680209 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -1011,7 +1011,11 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
if (is_struct)
btf_dump_emit_bit_padding(d, off, t->size * 8, align, false, lvl + 1);
- if (vlen)
+ /*
+ * Keep `struct empty {}` on a single line,
+ * only print newline when there are regular or padding fields.
+ */
+ if (vlen || t->size)
btf_dump_printf(d, "\n");
btf_dump_printf(d, "%s}", pfx(lvl));
if (packed)
diff --git a/tools/testing/radix-tree/maple.c b/tools/testing/radix-tree/maple.c
index 2e91973fbaa6..aceb6011315c 100644
--- a/tools/testing/radix-tree/maple.c
+++ b/tools/testing/radix-tree/maple.c
@@ -172,11 +172,11 @@ static noinline void check_new_node(struct maple_tree *mt)
if (!MAPLE_32BIT) {
if (i >= 35)
- e = i - 35;
+ e = i - 34;
else if (i >= 5)
- e = i - 5;
+ e = i - 4;
else if (i >= 2)
- e = i - 2;
+ e = i - 1;
} else {
if (i >= 4)
e = i - 4;
@@ -304,17 +304,17 @@ static noinline void check_new_node(struct maple_tree *mt)
MT_BUG_ON(mt, mas.node != MA_ERROR(-ENOMEM));
MT_BUG_ON(mt, !mas_nomem(&mas, GFP_KERNEL));
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 1);
- MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 1);
+ MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS);
mn = mas_pop_node(&mas); /* get the next node. */
MT_BUG_ON(mt, mn == NULL);
MT_BUG_ON(mt, not_empty(mn));
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS);
- MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 2);
+ MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 1);
mas_push_node(&mas, mn);
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 1);
- MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 1);
+ MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS);
/* Check the limit of pop/push/pop */
mas_node_count(&mas, MAPLE_ALLOC_SLOTS + 2); /* Request */
@@ -322,14 +322,14 @@ static noinline void check_new_node(struct maple_tree *mt)
MT_BUG_ON(mt, mas.node != MA_ERROR(-ENOMEM));
MT_BUG_ON(mt, !mas_nomem(&mas, GFP_KERNEL));
MT_BUG_ON(mt, mas_alloc_req(&mas));
- MT_BUG_ON(mt, mas.alloc->node_count);
+ MT_BUG_ON(mt, mas.alloc->node_count != 1);
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 2);
mn = mas_pop_node(&mas);
MT_BUG_ON(mt, not_empty(mn));
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 1);
- MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS - 1);
+ MT_BUG_ON(mt, mas.alloc->node_count != MAPLE_ALLOC_SLOTS);
mas_push_node(&mas, mn);
- MT_BUG_ON(mt, mas.alloc->node_count);
+ MT_BUG_ON(mt, mas.alloc->node_count != 1);
MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 2);
mn = mas_pop_node(&mas);
MT_BUG_ON(mt, not_empty(mn));
^ permalink raw reply related [relevance 1%]
* [PATCH 6.2 092/173] serial: 8250: Prevent starting up DMA Rx on THRI interrupt
@ 2023-04-12 8:33 6% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-04-12 8:33 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Hans de Goede, Ilpo Järvinen
From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
commit 90b8596ac46043e4a782d9111f5b285251b13756 upstream.
Hans de Goede reported Bluetooth adapters (HCIs) connected over an UART
connection failed due corrupted Rx payload. The problem was narrowed
down to DMA Rx starting on UART_IIR_THRI interrupt. The problem occurs
despite LSR having DR bit set, which is precondition for attempting to
start DMA Rx in the first place.
>From a debug patch:
[x.807834] 8250irq: iir=cc lsr+saved=60 received=0/15 ier=0f dma_t/rx/err=0/0/0
[x.808676] 8250irq: iir=c2 lsr+saved=61 received=0/0 ier=0f dma_t/rx/err=0/0/0
[x.808776] 8250irq: iir=cc lsr+saved=60 received=1/12 ier=0d dma_t/rx/err=0/1/0
[x.808870] Bluetooth: hci0: Frame reassembly failed (-84)
In the debug snippet, received field indicates 1 byte was transferred
over DMA and 12 bytes after that with the non-DMA Rx. The sole byte DMA
handled was corrupted (gets zeroed) which leads to the HCI failure.
This problem became apparent after commit e8ffbb71f783 ("serial: 8250:
use THRE & __stop_tx also with DMA") changed Tx stop behavior. Tx stop
is now triggered from a THRI interrupt.
Despite that this problem looks like a HW bug, this fix is not adding
UART_BUG_xx flag to the driver beucase it seems useful in general to
avoid starting DMA when there are only a few bytes to transfer.
Skipping DMA for small transfers avoids the extra overhead DMA incurs.
Thus, don't setup DMA Rx on UART_IIR_THRI but leave it to a subsequent
interrupt which has Rx a related IIR value.
By returning false from handle_rx_dma(), the DMA vs non-DMA decision is
postponed until either UART_IIR_RDI (FIFO threshold worth of bytes
awaiting) or UART_IIR_TIMEOUT (inter-character timeout) triggers at a
later time which allows better to discern whether the number of bytes
warrants starting DMA or not.
Reported-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Fixes: e8ffbb71f783 ("serial: 8250: use THRE & __stop_tx also with DMA")
Cc: stable@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20230317103034.12881-1-ilpo.jarvinen@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/8250/8250_port.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1896,6 +1896,17 @@ EXPORT_SYMBOL_GPL(serial8250_modem_statu
static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
{
switch (iir & 0x3f) {
+ case UART_IIR_THRI:
+ /*
+ * Postpone DMA or not decision to IIR_RDI or IIR_RX_TIMEOUT
+ * because it's impossible to do an informed decision about
+ * that with IIR_THRI.
+ *
+ * This also fixes one known DMA Rx corruption issue where
+ * DR is asserted but DMA Rx only gets a corrupted zero byte
+ * (too early DR?).
+ */
+ return false;
case UART_IIR_RDI:
if (!up->dma->rx_running)
break;
^ permalink raw reply [relevance 6%]
* [PATCH 6.1 085/164] serial: 8250: Prevent starting up DMA Rx on THRI interrupt
@ 2023-04-12 8:33 6% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-04-12 8:33 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Hans de Goede, Ilpo Järvinen
From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
commit 90b8596ac46043e4a782d9111f5b285251b13756 upstream.
Hans de Goede reported Bluetooth adapters (HCIs) connected over an UART
connection failed due corrupted Rx payload. The problem was narrowed
down to DMA Rx starting on UART_IIR_THRI interrupt. The problem occurs
despite LSR having DR bit set, which is precondition for attempting to
start DMA Rx in the first place.
>From a debug patch:
[x.807834] 8250irq: iir=cc lsr+saved=60 received=0/15 ier=0f dma_t/rx/err=0/0/0
[x.808676] 8250irq: iir=c2 lsr+saved=61 received=0/0 ier=0f dma_t/rx/err=0/0/0
[x.808776] 8250irq: iir=cc lsr+saved=60 received=1/12 ier=0d dma_t/rx/err=0/1/0
[x.808870] Bluetooth: hci0: Frame reassembly failed (-84)
In the debug snippet, received field indicates 1 byte was transferred
over DMA and 12 bytes after that with the non-DMA Rx. The sole byte DMA
handled was corrupted (gets zeroed) which leads to the HCI failure.
This problem became apparent after commit e8ffbb71f783 ("serial: 8250:
use THRE & __stop_tx also with DMA") changed Tx stop behavior. Tx stop
is now triggered from a THRI interrupt.
Despite that this problem looks like a HW bug, this fix is not adding
UART_BUG_xx flag to the driver beucase it seems useful in general to
avoid starting DMA when there are only a few bytes to transfer.
Skipping DMA for small transfers avoids the extra overhead DMA incurs.
Thus, don't setup DMA Rx on UART_IIR_THRI but leave it to a subsequent
interrupt which has Rx a related IIR value.
By returning false from handle_rx_dma(), the DMA vs non-DMA decision is
postponed until either UART_IIR_RDI (FIFO threshold worth of bytes
awaiting) or UART_IIR_TIMEOUT (inter-character timeout) triggers at a
later time which allows better to discern whether the number of bytes
warrants starting DMA or not.
Reported-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Fixes: e8ffbb71f783 ("serial: 8250: use THRE & __stop_tx also with DMA")
Cc: stable@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20230317103034.12881-1-ilpo.jarvinen@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/8250/8250_port.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1897,6 +1897,17 @@ EXPORT_SYMBOL_GPL(serial8250_modem_statu
static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
{
switch (iir & 0x3f) {
+ case UART_IIR_THRI:
+ /*
+ * Postpone DMA or not decision to IIR_RDI or IIR_RX_TIMEOUT
+ * because it's impossible to do an informed decision about
+ * that with IIR_THRI.
+ *
+ * This also fixes one known DMA Rx corruption issue where
+ * DR is asserted but DMA Rx only gets a corrupted zero byte
+ * (too early DR?).
+ */
+ return false;
case UART_IIR_RDI:
if (!up->dma->rx_running)
break;
^ permalink raw reply [relevance 6%]
* Re: Linux 4.19.280
@ 2023-04-05 9:46 1% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-04-05 9:46 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 02a323c43261..2a9dbac38b4e 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -94,8 +94,8 @@ gianfar.txt
- Gianfar Ethernet Driver.
i40e.txt
- README for the Intel Ethernet Controller XL710 Driver (i40e).
-i40evf.txt
- - Short note on the Driver for the Intel(R) XL710 X710 Virtual Function
+iavf.txt
+ - README for the Intel Ethernet Adaptive Virtual Function Driver (iavf).
ieee802154.txt
- Linux IEEE 802.15.4 implementation, API and drivers
igb.txt
diff --git a/Documentation/networking/i40evf.txt b/Documentation/networking/i40evf.txt
deleted file mode 100644
index e9b3035b95d0..000000000000
--- a/Documentation/networking/i40evf.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-Linux* Base Driver for Intel(R) Network Connection
-==================================================
-
-Intel Ethernet Adaptive Virtual Function Linux driver.
-Copyright(c) 2013-2017 Intel Corporation.
-
-Contents
-========
-
-- Identifying Your Adapter
-- Known Issues/Troubleshooting
-- Support
-
-This file describes the i40evf Linux* Base Driver.
-
-The i40evf driver supports the below mentioned virtual function
-devices and can only be activated on kernels running the i40e or
-newer Physical Function (PF) driver compiled with CONFIG_PCI_IOV.
-The i40evf driver requires CONFIG_PCI_MSI to be enabled.
-
-The guest OS loading the i40evf driver must support MSI-X interrupts.
-
-Supported Hardware
-==================
-Intel XL710 X710 Virtual Function
-Intel Ethernet Adaptive Virtual Function
-Intel X722 Virtual Function
-
-Identifying Your Adapter
-========================
-
-For more information on how to identify your adapter, go to the
-Adapter & Driver ID Guide at:
-
- http://support.intel.com/support/go/network/adapter/idguide.htm
-
-Known Issues/Troubleshooting
-============================
-
-
-Support
-=======
-
-For general information, go to the Intel support website at:
-
- http://support.intel.com
-
-or the Intel Wired Networking project hosted by Sourceforge at:
-
- http://sourceforge.net/projects/e1000
-
-If an issue is identified with the released source code on the supported
-kernel with a supported adapter, email the specific information related
-to the issue to e1000-devel@lists.sf.net
diff --git a/Documentation/networking/iavf.txt b/Documentation/networking/iavf.txt
new file mode 100644
index 000000000000..cc902a2369d6
--- /dev/null
+++ b/Documentation/networking/iavf.txt
@@ -0,0 +1,56 @@
+Linux* Base Driver for Intel(R) Network Connection
+==================================================
+
+Intel Ethernet Adaptive Virtual Function Linux driver.
+Copyright(c) 2013-2018 Intel Corporation.
+
+Contents
+========
+
+- Identifying Your Adapter
+- Known Issues/Troubleshooting
+- Support
+
+This file describes the iavf Linux* Base Driver. This driver
+was formerly called i40evf.
+
+The iavf driver supports the below mentioned virtual function
+devices and can only be activated on kernels running the i40e or
+newer Physical Function (PF) driver compiled with CONFIG_PCI_IOV.
+The iavf driver requires CONFIG_PCI_MSI to be enabled.
+
+The guest OS loading the iavf driver must support MSI-X interrupts.
+
+Supported Hardware
+==================
+Intel XL710 X710 Virtual Function
+Intel X722 Virtual Function
+Intel Ethernet Adaptive Virtual Function
+
+Identifying Your Adapter
+========================
+
+For more information on how to identify your adapter, go to the
+Adapter & Driver ID Guide at:
+
+ https://www.intel.com/content/www/us/en/support/articles/000005584/network-and-i-o/ethernet-products.html
+
+
+Known Issues/Troubleshooting
+============================
+
+
+Support
+=======
+
+For general information, go to the Intel support website at:
+
+ http://support.intel.com
+
+or the Intel Wired Networking project hosted by Sourceforge at:
+
+ http://sourceforge.net/projects/e1000
+
+If an issue is identified with the released source code on the supported
+kernel with a supported adapter, email the specific information related
+to the issue to e1000-devel@lists.sf.net
diff --git a/MAINTAINERS b/MAINTAINERS
index af0f322cf2f7..a8015db6b37e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7377,7 +7377,7 @@ F: Documentation/networking/ixgb.txt
F: Documentation/networking/ixgbe.txt
F: Documentation/networking/ixgbevf.txt
F: Documentation/networking/i40e.txt
-F: Documentation/networking/i40evf.txt
+F: Documentation/networking/iavf.txt
F: Documentation/networking/ice.txt
F: drivers/net/ethernet/intel/
F: drivers/net/ethernet/intel/*/
diff --git a/Makefile b/Makefile
index d6c4a53bf505..c70637ed93cd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 4
PATCHLEVEL = 19
-SUBLEVEL = 279
+SUBLEVEL = 280
EXTRAVERSION =
NAME = "People's Front"
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 9b70a7f5e705..35f706d836c5 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -30,6 +30,7 @@
#include <linux/init.h>
#include <linux/ptrace.h>
#include <linux/kallsyms.h>
+#include <linux/extable.h>
#include <asm/setup.h>
#include <asm/fpu.h>
@@ -550,7 +551,8 @@ static inline void bus_error030 (struct frame *fp)
errorcode |= 2;
if (mmusr & (MMU_I | MMU_WP)) {
- if (ssw & 4) {
+ /* We might have an exception table for this PC */
+ if (ssw & 4 && !search_exception_tables(fp->ptregs.pc)) {
pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",
ssw & RW ? "read" : "write",
fp->un.fmtb.daddr,
diff --git a/arch/riscv/include/uapi/asm/setup.h b/arch/riscv/include/uapi/asm/setup.h
new file mode 100644
index 000000000000..66b13a522880
--- /dev/null
+++ b/arch/riscv/include/uapi/asm/setup.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
+
+#ifndef _UAPI_ASM_RISCV_SETUP_H
+#define _UAPI_ASM_RISCV_SETUP_H
+
+#define COMMAND_LINE_SIZE 1024
+
+#endif /* _UAPI_ASM_RISCV_SETUP_H */
diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c
index 0267405ab7c6..fcfd78f99cb4 100644
--- a/arch/s390/lib/uaccess.c
+++ b/arch/s390/lib/uaccess.c
@@ -339,7 +339,7 @@ static inline unsigned long clear_user_mvcos(void __user *to, unsigned long size
"4: slgr %0,%0\n"
"5:\n"
EX_TABLE(0b,2b) EX_TABLE(3b,5b)
- : "+a" (size), "+a" (to), "+a" (tmp1), "=a" (tmp2)
+ : "+&a" (size), "+&a" (to), "+a" (tmp1), "=&a" (tmp2)
: "a" (empty_zero_page), "d" (reg0) : "cc", "memory");
return size;
}
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h
index 95100d8a0b7b..fc94603724b8 100644
--- a/arch/sh/include/asm/processor_32.h
+++ b/arch/sh/include/asm/processor_32.h
@@ -57,6 +57,7 @@
#define SR_FD 0x00008000
#define SR_MD 0x40000000
+#define SR_USER_MASK 0x00000303 // M, Q, S, T bits
/*
* DSP structure and data
*/
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index c46c0020ff55..ce93ae78c300 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -116,6 +116,7 @@ static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p)
{
unsigned int err = 0;
+ unsigned int sr = regs->sr & ~SR_USER_MASK;
#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
COPY(regs[1]);
@@ -131,6 +132,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
COPY(sr); COPY(pc);
#undef COPY
+ regs->sr = (regs->sr & SR_USER_MASK) | sr;
+
#ifdef CONFIG_SH_FPU
if (boot_cpu_data.flags & CPU_HAS_FPU) {
int owned_fp;
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index bc06f5919839..3380322df98e 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -2915,6 +2915,7 @@ close_card_oam(struct idt77252_dev *card)
recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
}
+ kfree(vc);
}
}
}
@@ -2958,6 +2959,15 @@ open_card_ubr0(struct idt77252_dev *card)
return 0;
}
+static void
+close_card_ubr0(struct idt77252_dev *card)
+{
+ struct vc_map *vc = card->vcs[0];
+
+ free_scq(card, vc->scq);
+ kfree(vc);
+}
+
static int
idt77252_dev_open(struct idt77252_dev *card)
{
@@ -3007,6 +3017,7 @@ static void idt77252_dev_close(struct atm_dev *dev)
struct idt77252_dev *card = dev->dev_data;
u32 conf;
+ close_card_ubr0(card);
close_card_oam(card);
conf = SAR_CFG_RXPTH | /* enable receive path */
diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c
index 874172aa8e41..a698b1f6394b 100644
--- a/drivers/bluetooth/btqcomsmd.c
+++ b/drivers/bluetooth/btqcomsmd.c
@@ -146,6 +146,21 @@ static int btqcomsmd_setup(struct hci_dev *hdev)
return 0;
}
+static int btqcomsmd_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+ int ret;
+
+ ret = qca_set_bdaddr_rome(hdev, bdaddr);
+ if (ret)
+ return ret;
+
+ /* The firmware stops responding for a while after setting the bdaddr,
+ * causing timeouts for subsequent commands. Sleep a bit to avoid this.
+ */
+ usleep_range(1000, 10000);
+ return 0;
+}
+
static int btqcomsmd_probe(struct platform_device *pdev)
{
struct btqcomsmd *btq;
@@ -195,7 +210,7 @@ static int btqcomsmd_probe(struct platform_device *pdev)
hdev->close = btqcomsmd_close;
hdev->send = btqcomsmd_send;
hdev->setup = btqcomsmd_setup;
- hdev->set_bdaddr = qca_set_bdaddr_rome;
+ hdev->set_bdaddr = btqcomsmd_set_bdaddr;
ret = hci_register_dev(hdev);
if (ret < 0)
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index 20142bc77554..bd55bf7a9914 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -353,6 +353,7 @@ static void btsdio_remove(struct sdio_func *func)
BT_DBG("func %p", func);
+ cancel_work_sync(&data->work);
if (!data)
return;
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 6a94aa6a22c2..1a0f977904b6 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -146,8 +146,8 @@ static int __init weim_parse_dt(struct platform_device *pdev,
const struct of_device_id *of_id = of_match_device(weim_id_table,
&pdev->dev);
const struct imx_weim_devtype *devtype = of_id->data;
+ int ret = 0, have_child = 0;
struct device_node *child;
- int ret, have_child = 0;
if (devtype == &imx50_weim_devtype) {
ret = imx_weim_gpr_setup(pdev);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index e8cd66705ad7..5ccbbb3eb68e 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -705,6 +705,39 @@ static int scmi_remove(struct platform_device *pdev)
return ret;
}
+static int scmi_mailbox_chan_validate(struct device *cdev)
+{
+ int num_mb, num_sh, ret = 0;
+ struct device_node *np = cdev->of_node;
+
+ num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
+ num_sh = of_count_phandle_with_args(np, "shmem", NULL);
+ /* Bail out if mboxes and shmem descriptors are inconsistent */
+ if (num_mb <= 0 || num_sh > 2 || num_mb != num_sh) {
+ dev_warn(cdev, "Invalid channel descriptor for '%s'\n",
+ of_node_full_name(np));
+ return -EINVAL;
+ }
+
+ if (num_sh > 1) {
+ struct device_node *np_tx, *np_rx;
+
+ np_tx = of_parse_phandle(np, "shmem", 0);
+ np_rx = of_parse_phandle(np, "shmem", 1);
+ /* SCMI Tx and Rx shared mem areas have to be distinct */
+ if (!np_tx || !np_rx || np_tx == np_rx) {
+ dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
+ of_node_full_name(np));
+ ret = -EINVAL;
+ }
+
+ of_node_put(np_tx);
+ of_node_put(np_rx);
+ }
+
+ return ret;
+}
+
static inline int
scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
{
@@ -720,6 +753,10 @@ scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, int prot_id)
goto idr_alloc;
}
+ ret = scmi_mailbox_chan_validate(dev);
+ if (ret)
+ return ret;
+
cinfo = devm_kzalloc(info->dev, sizeof(*cinfo), GFP_KERNEL);
if (!cinfo)
return -ENOMEM;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
index f21529e635e3..a9506a390f98 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
@@ -91,7 +91,15 @@ static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj)
static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
struct vm_area_struct *vma)
{
- return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
+ int ret;
+
+ ret = dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
+ if (!ret) {
+ /* Drop the reference acquired by drm_gem_mmap_obj(). */
+ drm_gem_object_put(&etnaviv_obj->base);
+ }
+
+ return ret;
}
static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index f8499cb95fec..4e4e151760db 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -495,6 +495,8 @@ static const struct it87_devices it87_devices[] = {
#define has_pwm_freq2(data) ((data)->features & FEAT_PWM_FREQ2)
#define has_six_temp(data) ((data)->features & FEAT_SIX_TEMP)
#define has_vin3_5v(data) ((data)->features & FEAT_VIN3_5V)
+#define has_scaling(data) ((data)->features & (FEAT_12MV_ADC | \
+ FEAT_10_9MV_ADC))
struct it87_sio_data {
int sioaddr;
@@ -3107,7 +3109,7 @@ static int it87_probe(struct platform_device *pdev)
"Detected broken BIOS defaults, disabling PWM interface\n");
/* Starting with IT8721F, we handle scaling of internal voltages */
- if (has_12mv_adc(data)) {
+ if (has_scaling(data)) {
if (sio_data->internal & BIT(0))
data->in_scaled |= BIT(3); /* in3 is AVCC */
if (sio_data->internal & BIT(1))
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 06c4c767af32..90c510d16651 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -508,10 +508,14 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
{
struct lpi2c_imx_struct *lpi2c_imx = dev_id;
+ unsigned int enabled;
unsigned int temp;
+ enabled = readl(lpi2c_imx->base + LPI2C_MIER);
+
lpi2c_imx_intctrl(lpi2c_imx, 0);
temp = readl(lpi2c_imx->base + LPI2C_MSR);
+ temp &= enabled;
if (temp & MSR_RDF)
lpi2c_imx_read_rxfifo(lpi2c_imx);
diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c
index a7ac746018ad..7a746f413535 100644
--- a/drivers/i2c/busses/i2c-xgene-slimpro.c
+++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
@@ -321,6 +321,9 @@ static int slimpro_i2c_blkwr(struct slimpro_i2c_dev *ctx, u32 chip,
u32 msg[3];
int rc;
+ if (writelen > I2C_SMBUS_BLOCK_MAX)
+ return -EINVAL;
+
memcpy(ctx->dma_buffer, data, writelen);
paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen,
DMA_TO_DEVICE);
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index dd80ff6cc427..b53da6360235 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -855,8 +855,8 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
x = y = z = 0;
/* Divide 4 since trackpoint's speed is too fast */
- input_report_rel(dev2, REL_X, (char)x / 4);
- input_report_rel(dev2, REL_Y, -((char)y / 4));
+ input_report_rel(dev2, REL_X, (s8)x / 4);
+ input_report_rel(dev2, REL_Y, -((s8)y / 4));
psmouse_report_standard_buttons(dev2, packet[3]);
@@ -1107,8 +1107,8 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
((packet[3] & 0x20) << 1);
z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
- input_report_rel(dev2, REL_X, (char)x);
- input_report_rel(dev2, REL_Y, -((char)y));
+ input_report_rel(dev2, REL_X, (s8)x);
+ input_report_rel(dev2, REL_Y, -((s8)y));
input_report_abs(dev2, ABS_PRESSURE, z);
psmouse_report_standard_buttons(dev2, packet[1]);
@@ -2297,20 +2297,20 @@ static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch)
if (reg < 0)
return reg;
- x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+ x_pitch = (s8)(reg << 4) >> 4; /* sign extend lower 4 bits */
x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
- y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */
+ y_pitch = (s8)reg >> 4; /* sign extend upper 4 bits */
y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
if (reg < 0)
return reg;
- x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+ x_electrode = (s8)(reg << 4) >> 4; /* sign extend lower 4 bits */
x_electrode = 17 + x_electrode;
- y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */
+ y_electrode = (s8)reg >> 4; /* sign extend upper 4 bits */
y_electrode = 13 + y_electrode;
x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
diff --git a/drivers/input/mouse/focaltech.c b/drivers/input/mouse/focaltech.c
index a7d39689bbfb..4bd48b81ed98 100644
--- a/drivers/input/mouse/focaltech.c
+++ b/drivers/input/mouse/focaltech.c
@@ -206,8 +206,8 @@ static void focaltech_process_rel_packet(struct psmouse *psmouse,
state->pressed = packet[0] >> 7;
finger1 = ((packet[0] >> 4) & 0x7) - 1;
if (finger1 < FOC_MAX_FINGERS) {
- state->fingers[finger1].x += (char)packet[1];
- state->fingers[finger1].y += (char)packet[2];
+ state->fingers[finger1].x += (s8)packet[1];
+ state->fingers[finger1].y += (s8)packet[2];
} else {
psmouse_err(psmouse, "First finger in rel packet invalid: %d\n",
finger1);
@@ -222,8 +222,8 @@ static void focaltech_process_rel_packet(struct psmouse *psmouse,
*/
finger2 = ((packet[3] >> 4) & 0x7) - 1;
if (finger2 < FOC_MAX_FINGERS) {
- state->fingers[finger2].x += (char)packet[4];
- state->fingers[finger2].y += (char)packet[5];
+ state->fingers[finger2].x += (s8)packet[4];
+ state->fingers[finger2].y += (s8)packet[5];
}
}
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index e38c713e882e..908bf0768827 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1661,6 +1661,7 @@ static int dmcrypt_write(void *data)
io = crypt_io_from_node(rb_first(&write_tree));
rb_erase(&io->rb_node, &write_tree);
kcryptd_io_write(io);
+ cond_resched();
} while (!RB_EMPTY_ROOT(&write_tree));
blk_finish_plug(&plug);
}
diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c
index 3d59f3e208c5..0eb48e739f7e 100644
--- a/drivers/md/dm-stats.c
+++ b/drivers/md/dm-stats.c
@@ -188,7 +188,7 @@ static int dm_stat_in_flight(struct dm_stat_shared *shared)
atomic_read(&shared->in_flight[WRITE]);
}
-void dm_stats_init(struct dm_stats *stats)
+int dm_stats_init(struct dm_stats *stats)
{
int cpu;
struct dm_stats_last_position *last;
@@ -196,11 +196,16 @@ void dm_stats_init(struct dm_stats *stats)
mutex_init(&stats->mutex);
INIT_LIST_HEAD(&stats->list);
stats->last = alloc_percpu(struct dm_stats_last_position);
+ if (!stats->last)
+ return -ENOMEM;
+
for_each_possible_cpu(cpu) {
last = per_cpu_ptr(stats->last, cpu);
last->last_sector = (sector_t)ULLONG_MAX;
last->last_rw = UINT_MAX;
}
+
+ return 0;
}
void dm_stats_cleanup(struct dm_stats *stats)
diff --git a/drivers/md/dm-stats.h b/drivers/md/dm-stats.h
index 2ddfae678f32..dcac11fce03b 100644
--- a/drivers/md/dm-stats.h
+++ b/drivers/md/dm-stats.h
@@ -22,7 +22,7 @@ struct dm_stats_aux {
unsigned long long duration_ns;
};
-void dm_stats_init(struct dm_stats *st);
+int dm_stats_init(struct dm_stats *st);
void dm_stats_cleanup(struct dm_stats *st);
struct mapped_device;
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 969ea013c74e..a1bbf00e60e5 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -3365,6 +3365,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
pt->low_water_blocks = low_water_blocks;
pt->adjusted_pf = pt->requested_pf = pf;
ti->num_flush_bios = 1;
+ ti->limit_swap_bios = true;
/*
* Only need to enable discards if the pool should pass
@@ -4245,6 +4246,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto bad;
ti->num_flush_bios = 1;
+ ti->limit_swap_bios = true;
ti->flush_supported = true;
ti->per_io_data_size = sizeof(struct dm_thin_endio_hook);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 3d9a77f4e20f..9a9b2adcf39e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -2021,7 +2021,9 @@ static struct mapped_device *alloc_dev(int minor)
bio_set_dev(&md->flush_bio, md->bdev);
md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC;
- dm_stats_init(&md->stats);
+ r = dm_stats_init(&md->stats);
+ if (r < 0)
+ goto bad;
/* Populate the mapping, nobody knows we exist yet */
spin_lock(&_minor_lock);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 89d4dcc5253e..f8c111b36992 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2991,6 +2991,9 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
err = kstrtouint(buf, 10, (unsigned int *)&slot);
if (err < 0)
return err;
+ if (slot < 0)
+ /* overflow */
+ return -ENOSPC;
}
if (rdev->mddev->pers && slot == -1) {
/* Setting 'slot' on an active array requires also
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index be064bcfd70a..6b310f723580 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2237,9 +2237,14 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
* If this is the upstream port for this switch, enable
* forwarding of unknown unicasts and multicasts.
*/
- reg = MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP |
- MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
+ reg = MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
+ /* Forward any IPv4 IGMP or IPv6 MLD frames received
+ * by a USER port to the CPU port to allow snooping.
+ */
+ if (dsa_is_user_port(ds, port))
+ reg |= MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP;
+
err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
if (err)
return err;
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 1ab613eb5796..b542aba6f0e8 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -235,20 +235,27 @@ config I40E_DCB
If unsure, say N.
+# this is here to allow seamless migration from I40EVF --> IAVF name
+# so that CONFIG_IAVF symbol will always mirror the state of CONFIG_I40EVF
+config IAVF
+ tristate
config I40EVF
tristate "Intel(R) Ethernet Adaptive Virtual Function support"
+ select IAVF
depends on PCI_MSI
---help---
This driver supports virtual functions for Intel XL710,
- X710, X722, and all devices advertising support for Intel
- Ethernet Adaptive Virtual Function devices. For more
+ X710, X722, XXV710, and all devices advertising support for
+ Intel Ethernet Adaptive Virtual Function devices. For more
information on how to identify your adapter, go to the Adapter
& Driver ID Guide that can be located at:
- <http://support.intel.com>
+ <https://support.intel.com>
+
+ This driver was formerly named i40evf.
To compile this driver as a module, choose M here. The module
- will be called i40evf. MSI-X interrupt support is required
+ will be called iavf. MSI-X interrupt support is required
for this driver to work correctly.
config ICE
diff --git a/drivers/net/ethernet/intel/Makefile b/drivers/net/ethernet/intel/Makefile
index 807a4f8c7e4e..b91153df6ee8 100644
--- a/drivers/net/ethernet/intel/Makefile
+++ b/drivers/net/ethernet/intel/Makefile
@@ -12,6 +12,6 @@ obj-$(CONFIG_IXGBE) += ixgbe/
obj-$(CONFIG_IXGBEVF) += ixgbevf/
obj-$(CONFIG_I40E) += i40e/
obj-$(CONFIG_IXGB) += ixgb/
-obj-$(CONFIG_I40EVF) += i40evf/
+obj-$(CONFIG_IAVF) += iavf/
obj-$(CONFIG_FM10K) += fm10k/
obj-$(CONFIG_ICE) += ice/
diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.c b/drivers/net/ethernet/intel/i40e/i40e_diag.c
index ef4d3762bf37..ca229b0efeb6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_diag.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_diag.c
@@ -44,7 +44,7 @@ static i40e_status i40e_diag_reg_pattern_test(struct i40e_hw *hw,
return 0;
}
-struct i40e_diag_reg_test_info i40e_reg_list[] = {
+const struct i40e_diag_reg_test_info i40e_reg_list[] = {
/* offset mask elements stride */
{I40E_QTX_CTL(0), 0x0000FFBF, 1,
I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
@@ -78,27 +78,28 @@ i40e_status i40e_diag_reg_test(struct i40e_hw *hw)
{
i40e_status ret_code = 0;
u32 reg, mask;
+ u32 elements;
u32 i, j;
for (i = 0; i40e_reg_list[i].offset != 0 &&
!ret_code; i++) {
+ elements = i40e_reg_list[i].elements;
/* set actual reg range for dynamically allocated resources */
if (i40e_reg_list[i].offset == I40E_QTX_CTL(0) &&
hw->func_caps.num_tx_qp != 0)
- i40e_reg_list[i].elements = hw->func_caps.num_tx_qp;
+ elements = hw->func_caps.num_tx_qp;
if ((i40e_reg_list[i].offset == I40E_PFINT_ITRN(0, 0) ||
i40e_reg_list[i].offset == I40E_PFINT_ITRN(1, 0) ||
i40e_reg_list[i].offset == I40E_PFINT_ITRN(2, 0) ||
i40e_reg_list[i].offset == I40E_QINT_TQCTL(0) ||
i40e_reg_list[i].offset == I40E_QINT_RQCTL(0)) &&
hw->func_caps.num_msix_vectors != 0)
- i40e_reg_list[i].elements =
- hw->func_caps.num_msix_vectors - 1;
+ elements = hw->func_caps.num_msix_vectors - 1;
/* test register access */
mask = i40e_reg_list[i].mask;
- for (j = 0; j < i40e_reg_list[i].elements && !ret_code; j++) {
+ for (j = 0; j < elements && !ret_code; j++) {
reg = i40e_reg_list[i].offset +
(j * i40e_reg_list[i].stride);
ret_code = i40e_diag_reg_pattern_test(hw, reg, mask);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_diag.h b/drivers/net/ethernet/intel/i40e/i40e_diag.h
index c3340f320a18..1db7c6d57231 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_diag.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_diag.h
@@ -20,7 +20,7 @@ struct i40e_diag_reg_test_info {
u32 stride; /* bytes between each element */
};
-extern struct i40e_diag_reg_test_info i40e_reg_list[];
+extern const struct i40e_diag_reg_test_info i40e_reg_list[];
i40e_status i40e_diag_reg_test(struct i40e_hw *hw);
i40e_status i40e_diag_eeprom_test(struct i40e_hw *hw);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 240083201dbf..1527c67b487b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -2595,7 +2595,7 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
!is_multicast_ether_addr(addr) && vf->pf_set_mac &&
!ether_addr_equal(addr, vf->default_lan_addr.addr)) {
dev_err(&pf->pdev->dev,
- "VF attempting to override administratively set MAC address, reload the VF driver to resume normal operation\n");
+ "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n");
return -EPERM;
}
}
@@ -4019,9 +4019,11 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
mac, vf_id);
}
- /* Force the VF driver stop so it has to reload with new MAC address */
+ /* Force the VF interface down so it has to bring up with new MAC
+ * address
+ */
i40e_vc_disable_vf(vf);
- dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
+ dev_info(&pf->pdev->dev, "Bring down and up the VF interface to make this change effective.\n");
error_param:
return ret;
diff --git a/drivers/net/ethernet/intel/i40evf/Makefile b/drivers/net/ethernet/intel/i40evf/Makefile
deleted file mode 100644
index 3c5c6e962280..000000000000
--- a/drivers/net/ethernet/intel/i40evf/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# Copyright(c) 2013 - 2018 Intel Corporation.
-
-#
-## Makefile for the Intel(R) 40GbE VF driver
-#
-#
-
-ccflags-y += -I$(src)
-subdir-ccflags-y += -I$(src)
-
-obj-$(CONFIG_I40EVF) += i40evf.o
-
-i40evf-objs := i40evf_main.o i40evf_ethtool.o i40evf_virtchnl.o \
- i40e_txrx.o i40e_common.o i40e_adminq.o i40evf_client.o
-
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
deleted file mode 100644
index 21a0dbf6ccf6..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
+++ /dev/null
@@ -1,967 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#include "i40e_status.h"
-#include "i40e_type.h"
-#include "i40e_register.h"
-#include "i40e_adminq.h"
-#include "i40e_prototype.h"
-
-/**
- * i40e_is_nvm_update_op - return true if this is an NVM update operation
- * @desc: API request descriptor
- **/
-static inline bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc)
-{
- return (desc->opcode == i40e_aqc_opc_nvm_erase) ||
- (desc->opcode == i40e_aqc_opc_nvm_update);
-}
-
-/**
- * i40e_adminq_init_regs - Initialize AdminQ registers
- * @hw: pointer to the hardware structure
- *
- * This assumes the alloc_asq and alloc_arq functions have already been called
- **/
-static void i40e_adminq_init_regs(struct i40e_hw *hw)
-{
- /* set head and tail registers in our local struct */
- if (i40e_is_vf(hw)) {
- hw->aq.asq.tail = I40E_VF_ATQT1;
- hw->aq.asq.head = I40E_VF_ATQH1;
- hw->aq.asq.len = I40E_VF_ATQLEN1;
- hw->aq.asq.bal = I40E_VF_ATQBAL1;
- hw->aq.asq.bah = I40E_VF_ATQBAH1;
- hw->aq.arq.tail = I40E_VF_ARQT1;
- hw->aq.arq.head = I40E_VF_ARQH1;
- hw->aq.arq.len = I40E_VF_ARQLEN1;
- hw->aq.arq.bal = I40E_VF_ARQBAL1;
- hw->aq.arq.bah = I40E_VF_ARQBAH1;
- }
-}
-
-/**
- * i40e_alloc_adminq_asq_ring - Allocate Admin Queue send rings
- * @hw: pointer to the hardware structure
- **/
-static i40e_status i40e_alloc_adminq_asq_ring(struct i40e_hw *hw)
-{
- i40e_status ret_code;
-
- ret_code = i40e_allocate_dma_mem(hw, &hw->aq.asq.desc_buf,
- i40e_mem_atq_ring,
- (hw->aq.num_asq_entries *
- sizeof(struct i40e_aq_desc)),
- I40E_ADMINQ_DESC_ALIGNMENT);
- if (ret_code)
- return ret_code;
-
- ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.cmd_buf,
- (hw->aq.num_asq_entries *
- sizeof(struct i40e_asq_cmd_details)));
- if (ret_code) {
- i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
- return ret_code;
- }
-
- return ret_code;
-}
-
-/**
- * i40e_alloc_adminq_arq_ring - Allocate Admin Queue receive rings
- * @hw: pointer to the hardware structure
- **/
-static i40e_status i40e_alloc_adminq_arq_ring(struct i40e_hw *hw)
-{
- i40e_status ret_code;
-
- ret_code = i40e_allocate_dma_mem(hw, &hw->aq.arq.desc_buf,
- i40e_mem_arq_ring,
- (hw->aq.num_arq_entries *
- sizeof(struct i40e_aq_desc)),
- I40E_ADMINQ_DESC_ALIGNMENT);
-
- return ret_code;
-}
-
-/**
- * i40e_free_adminq_asq - Free Admin Queue send rings
- * @hw: pointer to the hardware structure
- *
- * This assumes the posted send buffers have already been cleaned
- * and de-allocated
- **/
-static void i40e_free_adminq_asq(struct i40e_hw *hw)
-{
- i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
-}
-
-/**
- * i40e_free_adminq_arq - Free Admin Queue receive rings
- * @hw: pointer to the hardware structure
- *
- * This assumes the posted receive buffers have already been cleaned
- * and de-allocated
- **/
-static void i40e_free_adminq_arq(struct i40e_hw *hw)
-{
- i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
-}
-
-/**
- * i40e_alloc_arq_bufs - Allocate pre-posted buffers for the receive queue
- * @hw: pointer to the hardware structure
- **/
-static i40e_status i40e_alloc_arq_bufs(struct i40e_hw *hw)
-{
- i40e_status ret_code;
- struct i40e_aq_desc *desc;
- struct i40e_dma_mem *bi;
- int i;
-
- /* We'll be allocating the buffer info memory first, then we can
- * allocate the mapped buffers for the event processing
- */
-
- /* buffer_info structures do not need alignment */
- ret_code = i40e_allocate_virt_mem(hw, &hw->aq.arq.dma_head,
- (hw->aq.num_arq_entries * sizeof(struct i40e_dma_mem)));
- if (ret_code)
- goto alloc_arq_bufs;
- hw->aq.arq.r.arq_bi = (struct i40e_dma_mem *)hw->aq.arq.dma_head.va;
-
- /* allocate the mapped buffers */
- for (i = 0; i < hw->aq.num_arq_entries; i++) {
- bi = &hw->aq.arq.r.arq_bi[i];
- ret_code = i40e_allocate_dma_mem(hw, bi,
- i40e_mem_arq_buf,
- hw->aq.arq_buf_size,
- I40E_ADMINQ_DESC_ALIGNMENT);
- if (ret_code)
- goto unwind_alloc_arq_bufs;
-
- /* now configure the descriptors for use */
- desc = I40E_ADMINQ_DESC(hw->aq.arq, i);
-
- desc->flags = cpu_to_le16(I40E_AQ_FLAG_BUF);
- if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
- desc->flags |= cpu_to_le16(I40E_AQ_FLAG_LB);
- desc->opcode = 0;
- /* This is in accordance with Admin queue design, there is no
- * register for buffer size configuration
- */
- desc->datalen = cpu_to_le16((u16)bi->size);
- desc->retval = 0;
- desc->cookie_high = 0;
- desc->cookie_low = 0;
- desc->params.external.addr_high =
- cpu_to_le32(upper_32_bits(bi->pa));
- desc->params.external.addr_low =
- cpu_to_le32(lower_32_bits(bi->pa));
- desc->params.external.param0 = 0;
- desc->params.external.param1 = 0;
- }
-
-alloc_arq_bufs:
- return ret_code;
-
-unwind_alloc_arq_bufs:
- /* don't try to free the one that failed... */
- i--;
- for (; i >= 0; i--)
- i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
- i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
-
- return ret_code;
-}
-
-/**
- * i40e_alloc_asq_bufs - Allocate empty buffer structs for the send queue
- * @hw: pointer to the hardware structure
- **/
-static i40e_status i40e_alloc_asq_bufs(struct i40e_hw *hw)
-{
- i40e_status ret_code;
- struct i40e_dma_mem *bi;
- int i;
-
- /* No mapped memory needed yet, just the buffer info structures */
- ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.dma_head,
- (hw->aq.num_asq_entries * sizeof(struct i40e_dma_mem)));
- if (ret_code)
- goto alloc_asq_bufs;
- hw->aq.asq.r.asq_bi = (struct i40e_dma_mem *)hw->aq.asq.dma_head.va;
-
- /* allocate the mapped buffers */
- for (i = 0; i < hw->aq.num_asq_entries; i++) {
- bi = &hw->aq.asq.r.asq_bi[i];
- ret_code = i40e_allocate_dma_mem(hw, bi,
- i40e_mem_asq_buf,
- hw->aq.asq_buf_size,
- I40E_ADMINQ_DESC_ALIGNMENT);
- if (ret_code)
- goto unwind_alloc_asq_bufs;
- }
-alloc_asq_bufs:
- return ret_code;
-
-unwind_alloc_asq_bufs:
- /* don't try to free the one that failed... */
- i--;
- for (; i >= 0; i--)
- i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
- i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
-
- return ret_code;
-}
-
-/**
- * i40e_free_arq_bufs - Free receive queue buffer info elements
- * @hw: pointer to the hardware structure
- **/
-static void i40e_free_arq_bufs(struct i40e_hw *hw)
-{
- int i;
-
- /* free descriptors */
- for (i = 0; i < hw->aq.num_arq_entries; i++)
- i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
-
- /* free the descriptor memory */
- i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
-
- /* free the dma header */
- i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
-}
-
-/**
- * i40e_free_asq_bufs - Free send queue buffer info elements
- * @hw: pointer to the hardware structure
- **/
-static void i40e_free_asq_bufs(struct i40e_hw *hw)
-{
- int i;
-
- /* only unmap if the address is non-NULL */
- for (i = 0; i < hw->aq.num_asq_entries; i++)
- if (hw->aq.asq.r.asq_bi[i].pa)
- i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
-
- /* free the buffer info list */
- i40e_free_virt_mem(hw, &hw->aq.asq.cmd_buf);
-
- /* free the descriptor memory */
- i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
-
- /* free the dma header */
- i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
-}
-
-/**
- * i40e_config_asq_regs - configure ASQ registers
- * @hw: pointer to the hardware structure
- *
- * Configure base address and length registers for the transmit queue
- **/
-static i40e_status i40e_config_asq_regs(struct i40e_hw *hw)
-{
- i40e_status ret_code = 0;
- u32 reg = 0;
-
- /* Clear Head and Tail */
- wr32(hw, hw->aq.asq.head, 0);
- wr32(hw, hw->aq.asq.tail, 0);
-
- /* set starting point */
- wr32(hw, hw->aq.asq.len, (hw->aq.num_asq_entries |
- I40E_VF_ATQLEN1_ATQENABLE_MASK));
- wr32(hw, hw->aq.asq.bal, lower_32_bits(hw->aq.asq.desc_buf.pa));
- wr32(hw, hw->aq.asq.bah, upper_32_bits(hw->aq.asq.desc_buf.pa));
-
- /* Check one register to verify that config was applied */
- reg = rd32(hw, hw->aq.asq.bal);
- if (reg != lower_32_bits(hw->aq.asq.desc_buf.pa))
- ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
-
- return ret_code;
-}
-
-/**
- * i40e_config_arq_regs - ARQ register configuration
- * @hw: pointer to the hardware structure
- *
- * Configure base address and length registers for the receive (event queue)
- **/
-static i40e_status i40e_config_arq_regs(struct i40e_hw *hw)
-{
- i40e_status ret_code = 0;
- u32 reg = 0;
-
- /* Clear Head and Tail */
- wr32(hw, hw->aq.arq.head, 0);
- wr32(hw, hw->aq.arq.tail, 0);
-
- /* set starting point */
- wr32(hw, hw->aq.arq.len, (hw->aq.num_arq_entries |
- I40E_VF_ARQLEN1_ARQENABLE_MASK));
- wr32(hw, hw->aq.arq.bal, lower_32_bits(hw->aq.arq.desc_buf.pa));
- wr32(hw, hw->aq.arq.bah, upper_32_bits(hw->aq.arq.desc_buf.pa));
-
- /* Update tail in the HW to post pre-allocated buffers */
- wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1);
-
- /* Check one register to verify that config was applied */
- reg = rd32(hw, hw->aq.arq.bal);
- if (reg != lower_32_bits(hw->aq.arq.desc_buf.pa))
- ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
-
- return ret_code;
-}
-
-/**
- * i40e_init_asq - main initialization routine for ASQ
- * @hw: pointer to the hardware structure
- *
- * This is the main initialization routine for the Admin Send Queue
- * Prior to calling this function, drivers *MUST* set the following fields
- * in the hw->aq structure:
- * - hw->aq.num_asq_entries
- * - hw->aq.arq_buf_size
- *
- * Do *NOT* hold the lock when calling this as the memory allocation routines
- * called are not going to be atomic context safe
- **/
-static i40e_status i40e_init_asq(struct i40e_hw *hw)
-{
- i40e_status ret_code = 0;
-
- if (hw->aq.asq.count > 0) {
- /* queue already initialized */
- ret_code = I40E_ERR_NOT_READY;
- goto init_adminq_exit;
- }
-
- /* verify input for valid configuration */
- if ((hw->aq.num_asq_entries == 0) ||
- (hw->aq.asq_buf_size == 0)) {
- ret_code = I40E_ERR_CONFIG;
- goto init_adminq_exit;
- }
-
- hw->aq.asq.next_to_use = 0;
- hw->aq.asq.next_to_clean = 0;
-
- /* allocate the ring memory */
- ret_code = i40e_alloc_adminq_asq_ring(hw);
- if (ret_code)
- goto init_adminq_exit;
-
- /* allocate buffers in the rings */
- ret_code = i40e_alloc_asq_bufs(hw);
- if (ret_code)
- goto init_adminq_free_rings;
-
- /* initialize base registers */
- ret_code = i40e_config_asq_regs(hw);
- if (ret_code)
- goto init_adminq_free_rings;
-
- /* success! */
- hw->aq.asq.count = hw->aq.num_asq_entries;
- goto init_adminq_exit;
-
-init_adminq_free_rings:
- i40e_free_adminq_asq(hw);
-
-init_adminq_exit:
- return ret_code;
-}
-
-/**
- * i40e_init_arq - initialize ARQ
- * @hw: pointer to the hardware structure
- *
- * The main initialization routine for the Admin Receive (Event) Queue.
- * Prior to calling this function, drivers *MUST* set the following fields
- * in the hw->aq structure:
- * - hw->aq.num_asq_entries
- * - hw->aq.arq_buf_size
- *
- * Do *NOT* hold the lock when calling this as the memory allocation routines
- * called are not going to be atomic context safe
- **/
-static i40e_status i40e_init_arq(struct i40e_hw *hw)
-{
- i40e_status ret_code = 0;
-
- if (hw->aq.arq.count > 0) {
- /* queue already initialized */
- ret_code = I40E_ERR_NOT_READY;
- goto init_adminq_exit;
- }
-
- /* verify input for valid configuration */
- if ((hw->aq.num_arq_entries == 0) ||
- (hw->aq.arq_buf_size == 0)) {
- ret_code = I40E_ERR_CONFIG;
- goto init_adminq_exit;
- }
-
- hw->aq.arq.next_to_use = 0;
- hw->aq.arq.next_to_clean = 0;
-
- /* allocate the ring memory */
- ret_code = i40e_alloc_adminq_arq_ring(hw);
- if (ret_code)
- goto init_adminq_exit;
-
- /* allocate buffers in the rings */
- ret_code = i40e_alloc_arq_bufs(hw);
- if (ret_code)
- goto init_adminq_free_rings;
-
- /* initialize base registers */
- ret_code = i40e_config_arq_regs(hw);
- if (ret_code)
- goto init_adminq_free_rings;
-
- /* success! */
- hw->aq.arq.count = hw->aq.num_arq_entries;
- goto init_adminq_exit;
-
-init_adminq_free_rings:
- i40e_free_adminq_arq(hw);
-
-init_adminq_exit:
- return ret_code;
-}
-
-/**
- * i40e_shutdown_asq - shutdown the ASQ
- * @hw: pointer to the hardware structure
- *
- * The main shutdown routine for the Admin Send Queue
- **/
-static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
-{
- i40e_status ret_code = 0;
-
- mutex_lock(&hw->aq.asq_mutex);
-
- if (hw->aq.asq.count == 0) {
- ret_code = I40E_ERR_NOT_READY;
- goto shutdown_asq_out;
- }
-
- /* Stop firmware AdminQ processing */
- wr32(hw, hw->aq.asq.head, 0);
- wr32(hw, hw->aq.asq.tail, 0);
- wr32(hw, hw->aq.asq.len, 0);
- wr32(hw, hw->aq.asq.bal, 0);
- wr32(hw, hw->aq.asq.bah, 0);
-
- hw->aq.asq.count = 0; /* to indicate uninitialized queue */
-
- /* free ring buffers */
- i40e_free_asq_bufs(hw);
-
-shutdown_asq_out:
- mutex_unlock(&hw->aq.asq_mutex);
- return ret_code;
-}
-
-/**
- * i40e_shutdown_arq - shutdown ARQ
- * @hw: pointer to the hardware structure
- *
- * The main shutdown routine for the Admin Receive Queue
- **/
-static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
-{
- i40e_status ret_code = 0;
-
- mutex_lock(&hw->aq.arq_mutex);
-
- if (hw->aq.arq.count == 0) {
- ret_code = I40E_ERR_NOT_READY;
- goto shutdown_arq_out;
- }
-
- /* Stop firmware AdminQ processing */
- wr32(hw, hw->aq.arq.head, 0);
- wr32(hw, hw->aq.arq.tail, 0);
- wr32(hw, hw->aq.arq.len, 0);
- wr32(hw, hw->aq.arq.bal, 0);
- wr32(hw, hw->aq.arq.bah, 0);
-
- hw->aq.arq.count = 0; /* to indicate uninitialized queue */
-
- /* free ring buffers */
- i40e_free_arq_bufs(hw);
-
-shutdown_arq_out:
- mutex_unlock(&hw->aq.arq_mutex);
- return ret_code;
-}
-
-/**
- * i40evf_init_adminq - main initialization routine for Admin Queue
- * @hw: pointer to the hardware structure
- *
- * Prior to calling this function, drivers *MUST* set the following fields
- * in the hw->aq structure:
- * - hw->aq.num_asq_entries
- * - hw->aq.num_arq_entries
- * - hw->aq.arq_buf_size
- * - hw->aq.asq_buf_size
- **/
-i40e_status i40evf_init_adminq(struct i40e_hw *hw)
-{
- i40e_status ret_code;
-
- /* verify input for valid configuration */
- if ((hw->aq.num_arq_entries == 0) ||
- (hw->aq.num_asq_entries == 0) ||
- (hw->aq.arq_buf_size == 0) ||
- (hw->aq.asq_buf_size == 0)) {
- ret_code = I40E_ERR_CONFIG;
- goto init_adminq_exit;
- }
-
- /* Set up register offsets */
- i40e_adminq_init_regs(hw);
-
- /* setup ASQ command write back timeout */
- hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT;
-
- /* allocate the ASQ */
- ret_code = i40e_init_asq(hw);
- if (ret_code)
- goto init_adminq_destroy_locks;
-
- /* allocate the ARQ */
- ret_code = i40e_init_arq(hw);
- if (ret_code)
- goto init_adminq_free_asq;
-
- /* success! */
- goto init_adminq_exit;
-
-init_adminq_free_asq:
- i40e_shutdown_asq(hw);
-init_adminq_destroy_locks:
-
-init_adminq_exit:
- return ret_code;
-}
-
-/**
- * i40evf_shutdown_adminq - shutdown routine for the Admin Queue
- * @hw: pointer to the hardware structure
- **/
-i40e_status i40evf_shutdown_adminq(struct i40e_hw *hw)
-{
- i40e_status ret_code = 0;
-
- if (i40evf_check_asq_alive(hw))
- i40evf_aq_queue_shutdown(hw, true);
-
- i40e_shutdown_asq(hw);
- i40e_shutdown_arq(hw);
-
- if (hw->nvm_buff.va)
- i40e_free_virt_mem(hw, &hw->nvm_buff);
-
- return ret_code;
-}
-
-/**
- * i40e_clean_asq - cleans Admin send queue
- * @hw: pointer to the hardware structure
- *
- * returns the number of free desc
- **/
-static u16 i40e_clean_asq(struct i40e_hw *hw)
-{
- struct i40e_adminq_ring *asq = &(hw->aq.asq);
- struct i40e_asq_cmd_details *details;
- u16 ntc = asq->next_to_clean;
- struct i40e_aq_desc desc_cb;
- struct i40e_aq_desc *desc;
-
- desc = I40E_ADMINQ_DESC(*asq, ntc);
- details = I40E_ADMINQ_DETAILS(*asq, ntc);
- while (rd32(hw, hw->aq.asq.head) != ntc) {
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "ntc %d head %d.\n", ntc, rd32(hw, hw->aq.asq.head));
-
- if (details->callback) {
- I40E_ADMINQ_CALLBACK cb_func =
- (I40E_ADMINQ_CALLBACK)details->callback;
- desc_cb = *desc;
- cb_func(hw, &desc_cb);
- }
- memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
- memset((void *)details, 0,
- sizeof(struct i40e_asq_cmd_details));
- ntc++;
- if (ntc == asq->count)
- ntc = 0;
- desc = I40E_ADMINQ_DESC(*asq, ntc);
- details = I40E_ADMINQ_DETAILS(*asq, ntc);
- }
-
- asq->next_to_clean = ntc;
-
- return I40E_DESC_UNUSED(asq);
-}
-
-/**
- * i40evf_asq_done - check if FW has processed the Admin Send Queue
- * @hw: pointer to the hw struct
- *
- * Returns true if the firmware has processed all descriptors on the
- * admin send queue. Returns false if there are still requests pending.
- **/
-bool i40evf_asq_done(struct i40e_hw *hw)
-{
- /* AQ designers suggest use of head for better
- * timing reliability than DD bit
- */
- return rd32(hw, hw->aq.asq.head) == hw->aq.asq.next_to_use;
-
-}
-
-/**
- * i40evf_asq_send_command - send command to Admin Queue
- * @hw: pointer to the hw struct
- * @desc: prefilled descriptor describing the command (non DMA mem)
- * @buff: buffer to use for indirect commands
- * @buff_size: size of buffer for indirect commands
- * @cmd_details: pointer to command details structure
- *
- * This is the main send command driver routine for the Admin Queue send
- * queue. It runs the queue, cleans the queue, etc
- **/
-i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
- struct i40e_aq_desc *desc,
- void *buff, /* can be NULL */
- u16 buff_size,
- struct i40e_asq_cmd_details *cmd_details)
-{
- i40e_status status = 0;
- struct i40e_dma_mem *dma_buff = NULL;
- struct i40e_asq_cmd_details *details;
- struct i40e_aq_desc *desc_on_ring;
- bool cmd_completed = false;
- u16 retval = 0;
- u32 val = 0;
-
- mutex_lock(&hw->aq.asq_mutex);
-
- if (hw->aq.asq.count == 0) {
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: Admin queue not initialized.\n");
- status = I40E_ERR_QUEUE_EMPTY;
- goto asq_send_command_error;
- }
-
- hw->aq.asq_last_status = I40E_AQ_RC_OK;
-
- val = rd32(hw, hw->aq.asq.head);
- if (val >= hw->aq.num_asq_entries) {
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: head overrun at %d\n", val);
- status = I40E_ERR_QUEUE_EMPTY;
- goto asq_send_command_error;
- }
-
- details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
- if (cmd_details) {
- *details = *cmd_details;
-
- /* If the cmd_details are defined copy the cookie. The
- * cpu_to_le32 is not needed here because the data is ignored
- * by the FW, only used by the driver
- */
- if (details->cookie) {
- desc->cookie_high =
- cpu_to_le32(upper_32_bits(details->cookie));
- desc->cookie_low =
- cpu_to_le32(lower_32_bits(details->cookie));
- }
- } else {
- memset(details, 0, sizeof(struct i40e_asq_cmd_details));
- }
-
- /* clear requested flags and then set additional flags if defined */
- desc->flags &= ~cpu_to_le16(details->flags_dis);
- desc->flags |= cpu_to_le16(details->flags_ena);
-
- if (buff_size > hw->aq.asq_buf_size) {
- i40e_debug(hw,
- I40E_DEBUG_AQ_MESSAGE,
- "AQTX: Invalid buffer size: %d.\n",
- buff_size);
- status = I40E_ERR_INVALID_SIZE;
- goto asq_send_command_error;
- }
-
- if (details->postpone && !details->async) {
- i40e_debug(hw,
- I40E_DEBUG_AQ_MESSAGE,
- "AQTX: Async flag not set along with postpone flag");
- status = I40E_ERR_PARAM;
- goto asq_send_command_error;
- }
-
- /* call clean and check queue available function to reclaim the
- * descriptors that were processed by FW, the function returns the
- * number of desc available
- */
- /* the clean function called here could be called in a separate thread
- * in case of asynchronous completions
- */
- if (i40e_clean_asq(hw) == 0) {
- i40e_debug(hw,
- I40E_DEBUG_AQ_MESSAGE,
- "AQTX: Error queue is full.\n");
- status = I40E_ERR_ADMIN_QUEUE_FULL;
- goto asq_send_command_error;
- }
-
- /* initialize the temp desc pointer with the right desc */
- desc_on_ring = I40E_ADMINQ_DESC(hw->aq.asq, hw->aq.asq.next_to_use);
-
- /* if the desc is available copy the temp desc to the right place */
- *desc_on_ring = *desc;
-
- /* if buff is not NULL assume indirect command */
- if (buff != NULL) {
- dma_buff = &(hw->aq.asq.r.asq_bi[hw->aq.asq.next_to_use]);
- /* copy the user buff into the respective DMA buff */
- memcpy(dma_buff->va, buff, buff_size);
- desc_on_ring->datalen = cpu_to_le16(buff_size);
-
- /* Update the address values in the desc with the pa value
- * for respective buffer
- */
- desc_on_ring->params.external.addr_high =
- cpu_to_le32(upper_32_bits(dma_buff->pa));
- desc_on_ring->params.external.addr_low =
- cpu_to_le32(lower_32_bits(dma_buff->pa));
- }
-
- /* bump the tail */
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer:\n");
- i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring,
- buff, buff_size);
- (hw->aq.asq.next_to_use)++;
- if (hw->aq.asq.next_to_use == hw->aq.asq.count)
- hw->aq.asq.next_to_use = 0;
- if (!details->postpone)
- wr32(hw, hw->aq.asq.tail, hw->aq.asq.next_to_use);
-
- /* if cmd_details are not defined or async flag is not set,
- * we need to wait for desc write back
- */
- if (!details->async && !details->postpone) {
- u32 total_delay = 0;
-
- do {
- /* AQ designers suggest use of head for better
- * timing reliability than DD bit
- */
- if (i40evf_asq_done(hw))
- break;
- udelay(50);
- total_delay += 50;
- } while (total_delay < hw->aq.asq_cmd_timeout);
- }
-
- /* if ready, copy the desc back to temp */
- if (i40evf_asq_done(hw)) {
- *desc = *desc_on_ring;
- if (buff != NULL)
- memcpy(buff, dma_buff->va, buff_size);
- retval = le16_to_cpu(desc->retval);
- if (retval != 0) {
- i40e_debug(hw,
- I40E_DEBUG_AQ_MESSAGE,
- "AQTX: Command completed with error 0x%X.\n",
- retval);
-
- /* strip off FW internal code */
- retval &= 0xff;
- }
- cmd_completed = true;
- if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_OK)
- status = 0;
- else if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_EBUSY)
- status = I40E_ERR_NOT_READY;
- else
- status = I40E_ERR_ADMIN_QUEUE_ERROR;
- hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
- }
-
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: desc and buffer writeback:\n");
- i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff,
- buff_size);
-
- /* save writeback aq if requested */
- if (details->wb_desc)
- *details->wb_desc = *desc_on_ring;
-
- /* update the error if time out occurred */
- if ((!cmd_completed) &&
- (!details->async && !details->postpone)) {
- if (rd32(hw, hw->aq.asq.len) & I40E_VF_ATQLEN1_ATQCRIT_MASK) {
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: AQ Critical error.\n");
- status = I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR;
- } else {
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: Writeback timeout.\n");
- status = I40E_ERR_ADMIN_QUEUE_TIMEOUT;
- }
- }
-
-asq_send_command_error:
- mutex_unlock(&hw->aq.asq_mutex);
- return status;
-}
-
-/**
- * i40evf_fill_default_direct_cmd_desc - AQ descriptor helper function
- * @desc: pointer to the temp descriptor (non DMA mem)
- * @opcode: the opcode can be used to decide which flags to turn off or on
- *
- * Fill the desc with default values
- **/
-void i40evf_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
- u16 opcode)
-{
- /* zero out the desc */
- memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
- desc->opcode = cpu_to_le16(opcode);
- desc->flags = cpu_to_le16(I40E_AQ_FLAG_SI);
-}
-
-/**
- * i40evf_clean_arq_element
- * @hw: pointer to the hw struct
- * @e: event info from the receive descriptor, includes any buffers
- * @pending: number of events that could be left to process
- *
- * This function cleans one Admin Receive Queue element and returns
- * the contents through e. It can also return how many events are
- * left to process through 'pending'
- **/
-i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
- struct i40e_arq_event_info *e,
- u16 *pending)
-{
- i40e_status ret_code = 0;
- u16 ntc = hw->aq.arq.next_to_clean;
- struct i40e_aq_desc *desc;
- struct i40e_dma_mem *bi;
- u16 desc_idx;
- u16 datalen;
- u16 flags;
- u16 ntu;
-
- /* pre-clean the event info */
- memset(&e->desc, 0, sizeof(e->desc));
-
- /* take the lock before we start messing with the ring */
- mutex_lock(&hw->aq.arq_mutex);
-
- if (hw->aq.arq.count == 0) {
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQRX: Admin queue not initialized.\n");
- ret_code = I40E_ERR_QUEUE_EMPTY;
- goto clean_arq_element_err;
- }
-
- /* set next_to_use to head */
- ntu = rd32(hw, hw->aq.arq.head) & I40E_VF_ARQH1_ARQH_MASK;
- if (ntu == ntc) {
- /* nothing to do - shouldn't need to update ring's values */
- ret_code = I40E_ERR_ADMIN_QUEUE_NO_WORK;
- goto clean_arq_element_out;
- }
-
- /* now clean the next descriptor */
- desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
- desc_idx = ntc;
-
- hw->aq.arq_last_status =
- (enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
- flags = le16_to_cpu(desc->flags);
- if (flags & I40E_AQ_FLAG_ERR) {
- ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
- i40e_debug(hw,
- I40E_DEBUG_AQ_MESSAGE,
- "AQRX: Event received with error 0x%X.\n",
- hw->aq.arq_last_status);
- }
-
- e->desc = *desc;
- datalen = le16_to_cpu(desc->datalen);
- e->msg_len = min(datalen, e->buf_len);
- if (e->msg_buf != NULL && (e->msg_len != 0))
- memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
- e->msg_len);
-
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n");
- i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf,
- hw->aq.arq_buf_size);
-
- /* Restore the original datalen and buffer address in the desc,
- * FW updates datalen to indicate the event message
- * size
- */
- bi = &hw->aq.arq.r.arq_bi[ntc];
- memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
-
- desc->flags = cpu_to_le16(I40E_AQ_FLAG_BUF);
- if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
- desc->flags |= cpu_to_le16(I40E_AQ_FLAG_LB);
- desc->datalen = cpu_to_le16((u16)bi->size);
- desc->params.external.addr_high = cpu_to_le32(upper_32_bits(bi->pa));
- desc->params.external.addr_low = cpu_to_le32(lower_32_bits(bi->pa));
-
- /* set tail = the last cleaned desc index. */
- wr32(hw, hw->aq.arq.tail, ntc);
- /* ntc is updated to tail + 1 */
- ntc++;
- if (ntc == hw->aq.num_arq_entries)
- ntc = 0;
- hw->aq.arq.next_to_clean = ntc;
- hw->aq.arq.next_to_use = ntu;
-
-clean_arq_element_out:
- /* Set pending if needed, unlock and return */
- if (pending != NULL)
- *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
-
-clean_arq_element_err:
- mutex_unlock(&hw->aq.arq_mutex);
-
- return ret_code;
-}
-
-void i40evf_resume_aq(struct i40e_hw *hw)
-{
- /* Registers are reset after PF reset */
- hw->aq.asq.next_to_use = 0;
- hw->aq.asq.next_to_clean = 0;
-
- i40e_config_asq_regs(hw);
-
- hw->aq.arq.next_to_use = 0;
- hw->aq.arq.next_to_clean = 0;
-
- i40e_config_arq_regs(hw);
-}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
deleted file mode 100644
index 1f264b9b6805..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_ADMINQ_H_
-#define _I40E_ADMINQ_H_
-
-#include "i40e_osdep.h"
-#include "i40e_status.h"
-#include "i40e_adminq_cmd.h"
-
-#define I40E_ADMINQ_DESC(R, i) \
- (&(((struct i40e_aq_desc *)((R).desc_buf.va))[i]))
-
-#define I40E_ADMINQ_DESC_ALIGNMENT 4096
-
-struct i40e_adminq_ring {
- struct i40e_virt_mem dma_head; /* space for dma structures */
- struct i40e_dma_mem desc_buf; /* descriptor ring memory */
- struct i40e_virt_mem cmd_buf; /* command buffer memory */
-
- union {
- struct i40e_dma_mem *asq_bi;
- struct i40e_dma_mem *arq_bi;
- } r;
-
- u16 count; /* Number of descriptors */
- u16 rx_buf_len; /* Admin Receive Queue buffer length */
-
- /* used for interrupt processing */
- u16 next_to_use;
- u16 next_to_clean;
-
- /* used for queue tracking */
- u32 head;
- u32 tail;
- u32 len;
- u32 bah;
- u32 bal;
-};
-
-/* ASQ transaction details */
-struct i40e_asq_cmd_details {
- void *callback; /* cast from type I40E_ADMINQ_CALLBACK */
- u64 cookie;
- u16 flags_ena;
- u16 flags_dis;
- bool async;
- bool postpone;
- struct i40e_aq_desc *wb_desc;
-};
-
-#define I40E_ADMINQ_DETAILS(R, i) \
- (&(((struct i40e_asq_cmd_details *)((R).cmd_buf.va))[i]))
-
-/* ARQ event information */
-struct i40e_arq_event_info {
- struct i40e_aq_desc desc;
- u16 msg_len;
- u16 buf_len;
- u8 *msg_buf;
-};
-
-/* Admin Queue information */
-struct i40e_adminq_info {
- struct i40e_adminq_ring arq; /* receive queue */
- struct i40e_adminq_ring asq; /* send queue */
- u32 asq_cmd_timeout; /* send queue cmd write back timeout*/
- u16 num_arq_entries; /* receive queue depth */
- u16 num_asq_entries; /* send queue depth */
- u16 arq_buf_size; /* receive queue buffer size */
- u16 asq_buf_size; /* send queue buffer size */
- u16 fw_maj_ver; /* firmware major version */
- u16 fw_min_ver; /* firmware minor version */
- u32 fw_build; /* firmware build number */
- u16 api_maj_ver; /* api major version */
- u16 api_min_ver; /* api minor version */
-
- struct mutex asq_mutex; /* Send queue lock */
- struct mutex arq_mutex; /* Receive queue lock */
-
- /* last status values on send and receive queues */
- enum i40e_admin_queue_err asq_last_status;
- enum i40e_admin_queue_err arq_last_status;
-};
-
-/**
- * i40e_aq_rc_to_posix - convert errors to user-land codes
- * aq_ret: AdminQ handler error code can override aq_rc
- * aq_rc: AdminQ firmware error code to convert
- **/
-static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
-{
- int aq_to_posix[] = {
- 0, /* I40E_AQ_RC_OK */
- -EPERM, /* I40E_AQ_RC_EPERM */
- -ENOENT, /* I40E_AQ_RC_ENOENT */
- -ESRCH, /* I40E_AQ_RC_ESRCH */
- -EINTR, /* I40E_AQ_RC_EINTR */
- -EIO, /* I40E_AQ_RC_EIO */
- -ENXIO, /* I40E_AQ_RC_ENXIO */
- -E2BIG, /* I40E_AQ_RC_E2BIG */
- -EAGAIN, /* I40E_AQ_RC_EAGAIN */
- -ENOMEM, /* I40E_AQ_RC_ENOMEM */
- -EACCES, /* I40E_AQ_RC_EACCES */
- -EFAULT, /* I40E_AQ_RC_EFAULT */
- -EBUSY, /* I40E_AQ_RC_EBUSY */
- -EEXIST, /* I40E_AQ_RC_EEXIST */
- -EINVAL, /* I40E_AQ_RC_EINVAL */
- -ENOTTY, /* I40E_AQ_RC_ENOTTY */
- -ENOSPC, /* I40E_AQ_RC_ENOSPC */
- -ENOSYS, /* I40E_AQ_RC_ENOSYS */
- -ERANGE, /* I40E_AQ_RC_ERANGE */
- -EPIPE, /* I40E_AQ_RC_EFLUSHED */
- -ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
- -EROFS, /* I40E_AQ_RC_EMODE */
- -EFBIG, /* I40E_AQ_RC_EFBIG */
- };
-
- /* aq_rc is invalid if AQ timed out */
- if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT)
- return -EAGAIN;
-
- if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
- return -ERANGE;
-
- return aq_to_posix[aq_rc];
-}
-
-/* general information */
-#define I40E_AQ_LARGE_BUF 512
-#define I40E_ASQ_CMD_TIMEOUT 250000 /* usecs */
-
-void i40evf_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
- u16 opcode);
-
-#endif /* _I40E_ADMINQ_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
deleted file mode 100644
index 5fd8529465d4..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
+++ /dev/null
@@ -1,2717 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_ADMINQ_CMD_H_
-#define _I40E_ADMINQ_CMD_H_
-
-/* This header file defines the i40e Admin Queue commands and is shared between
- * i40e Firmware and Software.
- *
- * This file needs to comply with the Linux Kernel coding style.
- */
-
-#define I40E_FW_API_VERSION_MAJOR 0x0001
-#define I40E_FW_API_VERSION_MINOR_X722 0x0005
-#define I40E_FW_API_VERSION_MINOR_X710 0x0007
-
-#define I40E_FW_MINOR_VERSION(_h) ((_h)->mac.type == I40E_MAC_XL710 ? \
- I40E_FW_API_VERSION_MINOR_X710 : \
- I40E_FW_API_VERSION_MINOR_X722)
-
-/* API version 1.7 implements additional link and PHY-specific APIs */
-#define I40E_MINOR_VER_GET_LINK_INFO_XL710 0x0007
-
-struct i40e_aq_desc {
- __le16 flags;
- __le16 opcode;
- __le16 datalen;
- __le16 retval;
- __le32 cookie_high;
- __le32 cookie_low;
- union {
- struct {
- __le32 param0;
- __le32 param1;
- __le32 param2;
- __le32 param3;
- } internal;
- struct {
- __le32 param0;
- __le32 param1;
- __le32 addr_high;
- __le32 addr_low;
- } external;
- u8 raw[16];
- } params;
-};
-
-/* Flags sub-structure
- * |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |
- * |DD |CMP|ERR|VFE| * * RESERVED * * |LB |RD |VFC|BUF|SI |EI |FE |
- */
-
-/* command flags and offsets*/
-#define I40E_AQ_FLAG_DD_SHIFT 0
-#define I40E_AQ_FLAG_CMP_SHIFT 1
-#define I40E_AQ_FLAG_ERR_SHIFT 2
-#define I40E_AQ_FLAG_VFE_SHIFT 3
-#define I40E_AQ_FLAG_LB_SHIFT 9
-#define I40E_AQ_FLAG_RD_SHIFT 10
-#define I40E_AQ_FLAG_VFC_SHIFT 11
-#define I40E_AQ_FLAG_BUF_SHIFT 12
-#define I40E_AQ_FLAG_SI_SHIFT 13
-#define I40E_AQ_FLAG_EI_SHIFT 14
-#define I40E_AQ_FLAG_FE_SHIFT 15
-
-#define I40E_AQ_FLAG_DD BIT(I40E_AQ_FLAG_DD_SHIFT) /* 0x1 */
-#define I40E_AQ_FLAG_CMP BIT(I40E_AQ_FLAG_CMP_SHIFT) /* 0x2 */
-#define I40E_AQ_FLAG_ERR BIT(I40E_AQ_FLAG_ERR_SHIFT) /* 0x4 */
-#define I40E_AQ_FLAG_VFE BIT(I40E_AQ_FLAG_VFE_SHIFT) /* 0x8 */
-#define I40E_AQ_FLAG_LB BIT(I40E_AQ_FLAG_LB_SHIFT) /* 0x200 */
-#define I40E_AQ_FLAG_RD BIT(I40E_AQ_FLAG_RD_SHIFT) /* 0x400 */
-#define I40E_AQ_FLAG_VFC BIT(I40E_AQ_FLAG_VFC_SHIFT) /* 0x800 */
-#define I40E_AQ_FLAG_BUF BIT(I40E_AQ_FLAG_BUF_SHIFT) /* 0x1000 */
-#define I40E_AQ_FLAG_SI BIT(I40E_AQ_FLAG_SI_SHIFT) /* 0x2000 */
-#define I40E_AQ_FLAG_EI BIT(I40E_AQ_FLAG_EI_SHIFT) /* 0x4000 */
-#define I40E_AQ_FLAG_FE BIT(I40E_AQ_FLAG_FE_SHIFT) /* 0x8000 */
-
-/* error codes */
-enum i40e_admin_queue_err {
- I40E_AQ_RC_OK = 0, /* success */
- I40E_AQ_RC_EPERM = 1, /* Operation not permitted */
- I40E_AQ_RC_ENOENT = 2, /* No such element */
- I40E_AQ_RC_ESRCH = 3, /* Bad opcode */
- I40E_AQ_RC_EINTR = 4, /* operation interrupted */
- I40E_AQ_RC_EIO = 5, /* I/O error */
- I40E_AQ_RC_ENXIO = 6, /* No such resource */
- I40E_AQ_RC_E2BIG = 7, /* Arg too long */
- I40E_AQ_RC_EAGAIN = 8, /* Try again */
- I40E_AQ_RC_ENOMEM = 9, /* Out of memory */
- I40E_AQ_RC_EACCES = 10, /* Permission denied */
- I40E_AQ_RC_EFAULT = 11, /* Bad address */
- I40E_AQ_RC_EBUSY = 12, /* Device or resource busy */
- I40E_AQ_RC_EEXIST = 13, /* object already exists */
- I40E_AQ_RC_EINVAL = 14, /* Invalid argument */
- I40E_AQ_RC_ENOTTY = 15, /* Not a typewriter */
- I40E_AQ_RC_ENOSPC = 16, /* No space left or alloc failure */
- I40E_AQ_RC_ENOSYS = 17, /* Function not implemented */
- I40E_AQ_RC_ERANGE = 18, /* Parameter out of range */
- I40E_AQ_RC_EFLUSHED = 19, /* Cmd flushed due to prev cmd error */
- I40E_AQ_RC_BAD_ADDR = 20, /* Descriptor contains a bad pointer */
- I40E_AQ_RC_EMODE = 21, /* Op not allowed in current dev mode */
- I40E_AQ_RC_EFBIG = 22, /* File too large */
-};
-
-/* Admin Queue command opcodes */
-enum i40e_admin_queue_opc {
- /* aq commands */
- i40e_aqc_opc_get_version = 0x0001,
- i40e_aqc_opc_driver_version = 0x0002,
- i40e_aqc_opc_queue_shutdown = 0x0003,
- i40e_aqc_opc_set_pf_context = 0x0004,
-
- /* resource ownership */
- i40e_aqc_opc_request_resource = 0x0008,
- i40e_aqc_opc_release_resource = 0x0009,
-
- i40e_aqc_opc_list_func_capabilities = 0x000A,
- i40e_aqc_opc_list_dev_capabilities = 0x000B,
-
- /* Proxy commands */
- i40e_aqc_opc_set_proxy_config = 0x0104,
- i40e_aqc_opc_set_ns_proxy_table_entry = 0x0105,
-
- /* LAA */
- i40e_aqc_opc_mac_address_read = 0x0107,
- i40e_aqc_opc_mac_address_write = 0x0108,
-
- /* PXE */
- i40e_aqc_opc_clear_pxe_mode = 0x0110,
-
- /* WoL commands */
- i40e_aqc_opc_set_wol_filter = 0x0120,
- i40e_aqc_opc_get_wake_reason = 0x0121,
-
- /* internal switch commands */
- i40e_aqc_opc_get_switch_config = 0x0200,
- i40e_aqc_opc_add_statistics = 0x0201,
- i40e_aqc_opc_remove_statistics = 0x0202,
- i40e_aqc_opc_set_port_parameters = 0x0203,
- i40e_aqc_opc_get_switch_resource_alloc = 0x0204,
- i40e_aqc_opc_set_switch_config = 0x0205,
- i40e_aqc_opc_rx_ctl_reg_read = 0x0206,
- i40e_aqc_opc_rx_ctl_reg_write = 0x0207,
-
- i40e_aqc_opc_add_vsi = 0x0210,
- i40e_aqc_opc_update_vsi_parameters = 0x0211,
- i40e_aqc_opc_get_vsi_parameters = 0x0212,
-
- i40e_aqc_opc_add_pv = 0x0220,
- i40e_aqc_opc_update_pv_parameters = 0x0221,
- i40e_aqc_opc_get_pv_parameters = 0x0222,
-
- i40e_aqc_opc_add_veb = 0x0230,
- i40e_aqc_opc_update_veb_parameters = 0x0231,
- i40e_aqc_opc_get_veb_parameters = 0x0232,
-
- i40e_aqc_opc_delete_element = 0x0243,
-
- i40e_aqc_opc_add_macvlan = 0x0250,
- i40e_aqc_opc_remove_macvlan = 0x0251,
- i40e_aqc_opc_add_vlan = 0x0252,
- i40e_aqc_opc_remove_vlan = 0x0253,
- i40e_aqc_opc_set_vsi_promiscuous_modes = 0x0254,
- i40e_aqc_opc_add_tag = 0x0255,
- i40e_aqc_opc_remove_tag = 0x0256,
- i40e_aqc_opc_add_multicast_etag = 0x0257,
- i40e_aqc_opc_remove_multicast_etag = 0x0258,
- i40e_aqc_opc_update_tag = 0x0259,
- i40e_aqc_opc_add_control_packet_filter = 0x025A,
- i40e_aqc_opc_remove_control_packet_filter = 0x025B,
- i40e_aqc_opc_add_cloud_filters = 0x025C,
- i40e_aqc_opc_remove_cloud_filters = 0x025D,
- i40e_aqc_opc_clear_wol_switch_filters = 0x025E,
-
- i40e_aqc_opc_add_mirror_rule = 0x0260,
- i40e_aqc_opc_delete_mirror_rule = 0x0261,
-
- /* Dynamic Device Personalization */
- i40e_aqc_opc_write_personalization_profile = 0x0270,
- i40e_aqc_opc_get_personalization_profile_list = 0x0271,
-
- /* DCB commands */
- i40e_aqc_opc_dcb_ignore_pfc = 0x0301,
- i40e_aqc_opc_dcb_updated = 0x0302,
- i40e_aqc_opc_set_dcb_parameters = 0x0303,
-
- /* TX scheduler */
- i40e_aqc_opc_configure_vsi_bw_limit = 0x0400,
- i40e_aqc_opc_configure_vsi_ets_sla_bw_limit = 0x0406,
- i40e_aqc_opc_configure_vsi_tc_bw = 0x0407,
- i40e_aqc_opc_query_vsi_bw_config = 0x0408,
- i40e_aqc_opc_query_vsi_ets_sla_config = 0x040A,
- i40e_aqc_opc_configure_switching_comp_bw_limit = 0x0410,
-
- i40e_aqc_opc_enable_switching_comp_ets = 0x0413,
- i40e_aqc_opc_modify_switching_comp_ets = 0x0414,
- i40e_aqc_opc_disable_switching_comp_ets = 0x0415,
- i40e_aqc_opc_configure_switching_comp_ets_bw_limit = 0x0416,
- i40e_aqc_opc_configure_switching_comp_bw_config = 0x0417,
- i40e_aqc_opc_query_switching_comp_ets_config = 0x0418,
- i40e_aqc_opc_query_port_ets_config = 0x0419,
- i40e_aqc_opc_query_switching_comp_bw_config = 0x041A,
- i40e_aqc_opc_suspend_port_tx = 0x041B,
- i40e_aqc_opc_resume_port_tx = 0x041C,
- i40e_aqc_opc_configure_partition_bw = 0x041D,
- /* hmc */
- i40e_aqc_opc_query_hmc_resource_profile = 0x0500,
- i40e_aqc_opc_set_hmc_resource_profile = 0x0501,
-
- /* phy commands*/
- i40e_aqc_opc_get_phy_abilities = 0x0600,
- i40e_aqc_opc_set_phy_config = 0x0601,
- i40e_aqc_opc_set_mac_config = 0x0603,
- i40e_aqc_opc_set_link_restart_an = 0x0605,
- i40e_aqc_opc_get_link_status = 0x0607,
- i40e_aqc_opc_set_phy_int_mask = 0x0613,
- i40e_aqc_opc_get_local_advt_reg = 0x0614,
- i40e_aqc_opc_set_local_advt_reg = 0x0615,
- i40e_aqc_opc_get_partner_advt = 0x0616,
- i40e_aqc_opc_set_lb_modes = 0x0618,
- i40e_aqc_opc_get_phy_wol_caps = 0x0621,
- i40e_aqc_opc_set_phy_debug = 0x0622,
- i40e_aqc_opc_upload_ext_phy_fm = 0x0625,
- i40e_aqc_opc_run_phy_activity = 0x0626,
- i40e_aqc_opc_set_phy_register = 0x0628,
- i40e_aqc_opc_get_phy_register = 0x0629,
-
- /* NVM commands */
- i40e_aqc_opc_nvm_read = 0x0701,
- i40e_aqc_opc_nvm_erase = 0x0702,
- i40e_aqc_opc_nvm_update = 0x0703,
- i40e_aqc_opc_nvm_config_read = 0x0704,
- i40e_aqc_opc_nvm_config_write = 0x0705,
- i40e_aqc_opc_oem_post_update = 0x0720,
- i40e_aqc_opc_thermal_sensor = 0x0721,
-
- /* virtualization commands */
- i40e_aqc_opc_send_msg_to_pf = 0x0801,
- i40e_aqc_opc_send_msg_to_vf = 0x0802,
- i40e_aqc_opc_send_msg_to_peer = 0x0803,
-
- /* alternate structure */
- i40e_aqc_opc_alternate_write = 0x0900,
- i40e_aqc_opc_alternate_write_indirect = 0x0901,
- i40e_aqc_opc_alternate_read = 0x0902,
- i40e_aqc_opc_alternate_read_indirect = 0x0903,
- i40e_aqc_opc_alternate_write_done = 0x0904,
- i40e_aqc_opc_alternate_set_mode = 0x0905,
- i40e_aqc_opc_alternate_clear_port = 0x0906,
-
- /* LLDP commands */
- i40e_aqc_opc_lldp_get_mib = 0x0A00,
- i40e_aqc_opc_lldp_update_mib = 0x0A01,
- i40e_aqc_opc_lldp_add_tlv = 0x0A02,
- i40e_aqc_opc_lldp_update_tlv = 0x0A03,
- i40e_aqc_opc_lldp_delete_tlv = 0x0A04,
- i40e_aqc_opc_lldp_stop = 0x0A05,
- i40e_aqc_opc_lldp_start = 0x0A06,
-
- /* Tunnel commands */
- i40e_aqc_opc_add_udp_tunnel = 0x0B00,
- i40e_aqc_opc_del_udp_tunnel = 0x0B01,
- i40e_aqc_opc_set_rss_key = 0x0B02,
- i40e_aqc_opc_set_rss_lut = 0x0B03,
- i40e_aqc_opc_get_rss_key = 0x0B04,
- i40e_aqc_opc_get_rss_lut = 0x0B05,
-
- /* Async Events */
- i40e_aqc_opc_event_lan_overflow = 0x1001,
-
- /* OEM commands */
- i40e_aqc_opc_oem_parameter_change = 0xFE00,
- i40e_aqc_opc_oem_device_status_change = 0xFE01,
- i40e_aqc_opc_oem_ocsd_initialize = 0xFE02,
- i40e_aqc_opc_oem_ocbb_initialize = 0xFE03,
-
- /* debug commands */
- i40e_aqc_opc_debug_read_reg = 0xFF03,
- i40e_aqc_opc_debug_write_reg = 0xFF04,
- i40e_aqc_opc_debug_modify_reg = 0xFF07,
- i40e_aqc_opc_debug_dump_internals = 0xFF08,
-};
-
-/* command structures and indirect data structures */
-
-/* Structure naming conventions:
- * - no suffix for direct command descriptor structures
- * - _data for indirect sent data
- * - _resp for indirect return data (data which is both will use _data)
- * - _completion for direct return data
- * - _element_ for repeated elements (may also be _data or _resp)
- *
- * Command structures are expected to overlay the params.raw member of the basic
- * descriptor, and as such cannot exceed 16 bytes in length.
- */
-
-/* This macro is used to generate a compilation error if a structure
- * is not exactly the correct length. It gives a divide by zero error if the
- * structure is not of the correct size, otherwise it creates an enum that is
- * never used.
- */
-#define I40E_CHECK_STRUCT_LEN(n, X) enum i40e_static_assert_enum_##X \
- { i40e_static_assert_##X = (n)/((sizeof(struct X) == (n)) ? 1 : 0) }
-
-/* This macro is used extensively to ensure that command structures are 16
- * bytes in length as they have to map to the raw array of that size.
- */
-#define I40E_CHECK_CMD_LENGTH(X) I40E_CHECK_STRUCT_LEN(16, X)
-
-/* internal (0x00XX) commands */
-
-/* Get version (direct 0x0001) */
-struct i40e_aqc_get_version {
- __le32 rom_ver;
- __le32 fw_build;
- __le16 fw_major;
- __le16 fw_minor;
- __le16 api_major;
- __le16 api_minor;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_version);
-
-/* Send driver version (indirect 0x0002) */
-struct i40e_aqc_driver_version {
- u8 driver_major_ver;
- u8 driver_minor_ver;
- u8 driver_build_ver;
- u8 driver_subbuild_ver;
- u8 reserved[4];
- __le32 address_high;
- __le32 address_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_driver_version);
-
-/* Queue Shutdown (direct 0x0003) */
-struct i40e_aqc_queue_shutdown {
- __le32 driver_unloading;
-#define I40E_AQ_DRIVER_UNLOADING 0x1
- u8 reserved[12];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_queue_shutdown);
-
-/* Set PF context (0x0004, direct) */
-struct i40e_aqc_set_pf_context {
- u8 pf_id;
- u8 reserved[15];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_pf_context);
-
-/* Request resource ownership (direct 0x0008)
- * Release resource ownership (direct 0x0009)
- */
-#define I40E_AQ_RESOURCE_NVM 1
-#define I40E_AQ_RESOURCE_SDP 2
-#define I40E_AQ_RESOURCE_ACCESS_READ 1
-#define I40E_AQ_RESOURCE_ACCESS_WRITE 2
-#define I40E_AQ_RESOURCE_NVM_READ_TIMEOUT 3000
-#define I40E_AQ_RESOURCE_NVM_WRITE_TIMEOUT 180000
-
-struct i40e_aqc_request_resource {
- __le16 resource_id;
- __le16 access_type;
- __le32 timeout;
- __le32 resource_number;
- u8 reserved[4];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_request_resource);
-
-/* Get function capabilities (indirect 0x000A)
- * Get device capabilities (indirect 0x000B)
- */
-struct i40e_aqc_list_capabilites {
- u8 command_flags;
-#define I40E_AQ_LIST_CAP_PF_INDEX_EN 1
- u8 pf_index;
- u8 reserved[2];
- __le32 count;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_list_capabilites);
-
-struct i40e_aqc_list_capabilities_element_resp {
- __le16 id;
- u8 major_rev;
- u8 minor_rev;
- __le32 number;
- __le32 logical_id;
- __le32 phys_id;
- u8 reserved[16];
-};
-
-/* list of caps */
-
-#define I40E_AQ_CAP_ID_SWITCH_MODE 0x0001
-#define I40E_AQ_CAP_ID_MNG_MODE 0x0002
-#define I40E_AQ_CAP_ID_NPAR_ACTIVE 0x0003
-#define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004
-#define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005
-#define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006
-#define I40E_AQ_CAP_ID_WOL_AND_PROXY 0x0008
-#define I40E_AQ_CAP_ID_SRIOV 0x0012
-#define I40E_AQ_CAP_ID_VF 0x0013
-#define I40E_AQ_CAP_ID_VMDQ 0x0014
-#define I40E_AQ_CAP_ID_8021QBG 0x0015
-#define I40E_AQ_CAP_ID_8021QBR 0x0016
-#define I40E_AQ_CAP_ID_VSI 0x0017
-#define I40E_AQ_CAP_ID_DCB 0x0018
-#define I40E_AQ_CAP_ID_FCOE 0x0021
-#define I40E_AQ_CAP_ID_ISCSI 0x0022
-#define I40E_AQ_CAP_ID_RSS 0x0040
-#define I40E_AQ_CAP_ID_RXQ 0x0041
-#define I40E_AQ_CAP_ID_TXQ 0x0042
-#define I40E_AQ_CAP_ID_MSIX 0x0043
-#define I40E_AQ_CAP_ID_VF_MSIX 0x0044
-#define I40E_AQ_CAP_ID_FLOW_DIRECTOR 0x0045
-#define I40E_AQ_CAP_ID_1588 0x0046
-#define I40E_AQ_CAP_ID_IWARP 0x0051
-#define I40E_AQ_CAP_ID_LED 0x0061
-#define I40E_AQ_CAP_ID_SDP 0x0062
-#define I40E_AQ_CAP_ID_MDIO 0x0063
-#define I40E_AQ_CAP_ID_WSR_PROT 0x0064
-#define I40E_AQ_CAP_ID_NVM_MGMT 0x0080
-#define I40E_AQ_CAP_ID_FLEX10 0x00F1
-#define I40E_AQ_CAP_ID_CEM 0x00F2
-
-/* Set CPPM Configuration (direct 0x0103) */
-struct i40e_aqc_cppm_configuration {
- __le16 command_flags;
-#define I40E_AQ_CPPM_EN_LTRC 0x0800
-#define I40E_AQ_CPPM_EN_DMCTH 0x1000
-#define I40E_AQ_CPPM_EN_DMCTLX 0x2000
-#define I40E_AQ_CPPM_EN_HPTC 0x4000
-#define I40E_AQ_CPPM_EN_DMARC 0x8000
- __le16 ttlx;
- __le32 dmacr;
- __le16 dmcth;
- u8 hptc;
- u8 reserved;
- __le32 pfltrc;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_cppm_configuration);
-
-/* Set ARP Proxy command / response (indirect 0x0104) */
-struct i40e_aqc_arp_proxy_data {
- __le16 command_flags;
-#define I40E_AQ_ARP_INIT_IPV4 0x0800
-#define I40E_AQ_ARP_UNSUP_CTL 0x1000
-#define I40E_AQ_ARP_ENA 0x2000
-#define I40E_AQ_ARP_ADD_IPV4 0x4000
-#define I40E_AQ_ARP_DEL_IPV4 0x8000
- __le16 table_id;
- __le32 enabled_offloads;
-#define I40E_AQ_ARP_DIRECTED_OFFLOAD_ENABLE 0x00000020
-#define I40E_AQ_ARP_OFFLOAD_ENABLE 0x00000800
- __le32 ip_addr;
- u8 mac_addr[6];
- u8 reserved[2];
-};
-
-I40E_CHECK_STRUCT_LEN(0x14, i40e_aqc_arp_proxy_data);
-
-/* Set NS Proxy Table Entry Command (indirect 0x0105) */
-struct i40e_aqc_ns_proxy_data {
- __le16 table_idx_mac_addr_0;
- __le16 table_idx_mac_addr_1;
- __le16 table_idx_ipv6_0;
- __le16 table_idx_ipv6_1;
- __le16 control;
-#define I40E_AQ_NS_PROXY_ADD_0 0x0001
-#define I40E_AQ_NS_PROXY_DEL_0 0x0002
-#define I40E_AQ_NS_PROXY_ADD_1 0x0004
-#define I40E_AQ_NS_PROXY_DEL_1 0x0008
-#define I40E_AQ_NS_PROXY_ADD_IPV6_0 0x0010
-#define I40E_AQ_NS_PROXY_DEL_IPV6_0 0x0020
-#define I40E_AQ_NS_PROXY_ADD_IPV6_1 0x0040
-#define I40E_AQ_NS_PROXY_DEL_IPV6_1 0x0080
-#define I40E_AQ_NS_PROXY_COMMAND_SEQ 0x0100
-#define I40E_AQ_NS_PROXY_INIT_IPV6_TBL 0x0200
-#define I40E_AQ_NS_PROXY_INIT_MAC_TBL 0x0400
-#define I40E_AQ_NS_PROXY_OFFLOAD_ENABLE 0x0800
-#define I40E_AQ_NS_PROXY_DIRECTED_OFFLOAD_ENABLE 0x1000
- u8 mac_addr_0[6];
- u8 mac_addr_1[6];
- u8 local_mac_addr[6];
- u8 ipv6_addr_0[16]; /* Warning! spec specifies BE byte order */
- u8 ipv6_addr_1[16];
-};
-
-I40E_CHECK_STRUCT_LEN(0x3c, i40e_aqc_ns_proxy_data);
-
-/* Manage LAA Command (0x0106) - obsolete */
-struct i40e_aqc_mng_laa {
- __le16 command_flags;
-#define I40E_AQ_LAA_FLAG_WR 0x8000
- u8 reserved[2];
- __le32 sal;
- __le16 sah;
- u8 reserved2[6];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_mng_laa);
-
-/* Manage MAC Address Read Command (indirect 0x0107) */
-struct i40e_aqc_mac_address_read {
- __le16 command_flags;
-#define I40E_AQC_LAN_ADDR_VALID 0x10
-#define I40E_AQC_SAN_ADDR_VALID 0x20
-#define I40E_AQC_PORT_ADDR_VALID 0x40
-#define I40E_AQC_WOL_ADDR_VALID 0x80
-#define I40E_AQC_MC_MAG_EN_VALID 0x100
-#define I40E_AQC_ADDR_VALID_MASK 0x3F0
- u8 reserved[6];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_read);
-
-struct i40e_aqc_mac_address_read_data {
- u8 pf_lan_mac[6];
- u8 pf_san_mac[6];
- u8 port_mac[6];
- u8 pf_wol_mac[6];
-};
-
-I40E_CHECK_STRUCT_LEN(24, i40e_aqc_mac_address_read_data);
-
-/* Manage MAC Address Write Command (0x0108) */
-struct i40e_aqc_mac_address_write {
- __le16 command_flags;
-#define I40E_AQC_WRITE_TYPE_LAA_ONLY 0x0000
-#define I40E_AQC_WRITE_TYPE_LAA_WOL 0x4000
-#define I40E_AQC_WRITE_TYPE_PORT 0x8000
-#define I40E_AQC_WRITE_TYPE_UPDATE_MC_MAG 0xC000
-#define I40E_AQC_WRITE_TYPE_MASK 0xC000
-
- __le16 mac_sah;
- __le32 mac_sal;
- u8 reserved[8];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_write);
-
-/* PXE commands (0x011x) */
-
-/* Clear PXE Command and response (direct 0x0110) */
-struct i40e_aqc_clear_pxe {
- u8 rx_cnt;
- u8 reserved[15];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_clear_pxe);
-
-/* Set WoL Filter (0x0120) */
-
-struct i40e_aqc_set_wol_filter {
- __le16 filter_index;
-#define I40E_AQC_MAX_NUM_WOL_FILTERS 8
-#define I40E_AQC_SET_WOL_FILTER_TYPE_MAGIC_SHIFT 15
-#define I40E_AQC_SET_WOL_FILTER_TYPE_MAGIC_MASK (0x1 << \
- I40E_AQC_SET_WOL_FILTER_TYPE_MAGIC_SHIFT)
-
-#define I40E_AQC_SET_WOL_FILTER_INDEX_SHIFT 0
-#define I40E_AQC_SET_WOL_FILTER_INDEX_MASK (0x7 << \
- I40E_AQC_SET_WOL_FILTER_INDEX_SHIFT)
- __le16 cmd_flags;
-#define I40E_AQC_SET_WOL_FILTER 0x8000
-#define I40E_AQC_SET_WOL_FILTER_NO_TCO_WOL 0x4000
-#define I40E_AQC_SET_WOL_FILTER_WOL_PRESERVE_ON_PFR 0x2000
-#define I40E_AQC_SET_WOL_FILTER_ACTION_CLEAR 0
-#define I40E_AQC_SET_WOL_FILTER_ACTION_SET 1
- __le16 valid_flags;
-#define I40E_AQC_SET_WOL_FILTER_ACTION_VALID 0x8000
-#define I40E_AQC_SET_WOL_FILTER_NO_TCO_ACTION_VALID 0x4000
- u8 reserved[2];
- __le32 address_high;
- __le32 address_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_wol_filter);
-
-struct i40e_aqc_set_wol_filter_data {
- u8 filter[128];
- u8 mask[16];
-};
-
-I40E_CHECK_STRUCT_LEN(0x90, i40e_aqc_set_wol_filter_data);
-
-/* Get Wake Reason (0x0121) */
-
-struct i40e_aqc_get_wake_reason_completion {
- u8 reserved_1[2];
- __le16 wake_reason;
-#define I40E_AQC_GET_WAKE_UP_REASON_WOL_REASON_MATCHED_INDEX_SHIFT 0
-#define I40E_AQC_GET_WAKE_UP_REASON_WOL_REASON_MATCHED_INDEX_MASK (0xFF << \
- I40E_AQC_GET_WAKE_UP_REASON_WOL_REASON_MATCHED_INDEX_SHIFT)
-#define I40E_AQC_GET_WAKE_UP_REASON_WOL_REASON_RESERVED_SHIFT 8
-#define I40E_AQC_GET_WAKE_UP_REASON_WOL_REASON_RESERVED_MASK (0xFF << \
- I40E_AQC_GET_WAKE_UP_REASON_WOL_REASON_RESERVED_SHIFT)
- u8 reserved_2[12];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_wake_reason_completion);
-
-/* Switch configuration commands (0x02xx) */
-
-/* Used by many indirect commands that only pass an seid and a buffer in the
- * command
- */
-struct i40e_aqc_switch_seid {
- __le16 seid;
- u8 reserved[6];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_switch_seid);
-
-/* Get Switch Configuration command (indirect 0x0200)
- * uses i40e_aqc_switch_seid for the descriptor
- */
-struct i40e_aqc_get_switch_config_header_resp {
- __le16 num_reported;
- __le16 num_total;
- u8 reserved[12];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_switch_config_header_resp);
-
-struct i40e_aqc_switch_config_element_resp {
- u8 element_type;
-#define I40E_AQ_SW_ELEM_TYPE_MAC 1
-#define I40E_AQ_SW_ELEM_TYPE_PF 2
-#define I40E_AQ_SW_ELEM_TYPE_VF 3
-#define I40E_AQ_SW_ELEM_TYPE_EMP 4
-#define I40E_AQ_SW_ELEM_TYPE_BMC 5
-#define I40E_AQ_SW_ELEM_TYPE_PV 16
-#define I40E_AQ_SW_ELEM_TYPE_VEB 17
-#define I40E_AQ_SW_ELEM_TYPE_PA 18
-#define I40E_AQ_SW_ELEM_TYPE_VSI 19
- u8 revision;
-#define I40E_AQ_SW_ELEM_REV_1 1
- __le16 seid;
- __le16 uplink_seid;
- __le16 downlink_seid;
- u8 reserved[3];
- u8 connection_type;
-#define I40E_AQ_CONN_TYPE_REGULAR 0x1
-#define I40E_AQ_CONN_TYPE_DEFAULT 0x2
-#define I40E_AQ_CONN_TYPE_CASCADED 0x3
- __le16 scheduler_id;
- __le16 element_info;
-};
-
-I40E_CHECK_STRUCT_LEN(0x10, i40e_aqc_switch_config_element_resp);
-
-/* Get Switch Configuration (indirect 0x0200)
- * an array of elements are returned in the response buffer
- * the first in the array is the header, remainder are elements
- */
-struct i40e_aqc_get_switch_config_resp {
- struct i40e_aqc_get_switch_config_header_resp header;
- struct i40e_aqc_switch_config_element_resp element[1];
-};
-
-I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_get_switch_config_resp);
-
-/* Add Statistics (direct 0x0201)
- * Remove Statistics (direct 0x0202)
- */
-struct i40e_aqc_add_remove_statistics {
- __le16 seid;
- __le16 vlan;
- __le16 stat_index;
- u8 reserved[10];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_statistics);
-
-/* Set Port Parameters command (direct 0x0203) */
-struct i40e_aqc_set_port_parameters {
- __le16 command_flags;
-#define I40E_AQ_SET_P_PARAMS_SAVE_BAD_PACKETS 1
-#define I40E_AQ_SET_P_PARAMS_PAD_SHORT_PACKETS 2 /* must set! */
-#define I40E_AQ_SET_P_PARAMS_DOUBLE_VLAN_ENA 4
- __le16 bad_frame_vsi;
-#define I40E_AQ_SET_P_PARAMS_BFRAME_SEID_SHIFT 0x0
-#define I40E_AQ_SET_P_PARAMS_BFRAME_SEID_MASK 0x3FF
- __le16 default_seid; /* reserved for command */
- u8 reserved[10];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_port_parameters);
-
-/* Get Switch Resource Allocation (indirect 0x0204) */
-struct i40e_aqc_get_switch_resource_alloc {
- u8 num_entries; /* reserved for command */
- u8 reserved[7];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_switch_resource_alloc);
-
-/* expect an array of these structs in the response buffer */
-struct i40e_aqc_switch_resource_alloc_element_resp {
- u8 resource_type;
-#define I40E_AQ_RESOURCE_TYPE_VEB 0x0
-#define I40E_AQ_RESOURCE_TYPE_VSI 0x1
-#define I40E_AQ_RESOURCE_TYPE_MACADDR 0x2
-#define I40E_AQ_RESOURCE_TYPE_STAG 0x3
-#define I40E_AQ_RESOURCE_TYPE_ETAG 0x4
-#define I40E_AQ_RESOURCE_TYPE_MULTICAST_HASH 0x5
-#define I40E_AQ_RESOURCE_TYPE_UNICAST_HASH 0x6
-#define I40E_AQ_RESOURCE_TYPE_VLAN 0x7
-#define I40E_AQ_RESOURCE_TYPE_VSI_LIST_ENTRY 0x8
-#define I40E_AQ_RESOURCE_TYPE_ETAG_LIST_ENTRY 0x9
-#define I40E_AQ_RESOURCE_TYPE_VLAN_STAT_POOL 0xA
-#define I40E_AQ_RESOURCE_TYPE_MIRROR_RULE 0xB
-#define I40E_AQ_RESOURCE_TYPE_QUEUE_SETS 0xC
-#define I40E_AQ_RESOURCE_TYPE_VLAN_FILTERS 0xD
-#define I40E_AQ_RESOURCE_TYPE_INNER_MAC_FILTERS 0xF
-#define I40E_AQ_RESOURCE_TYPE_IP_FILTERS 0x10
-#define I40E_AQ_RESOURCE_TYPE_GRE_VN_KEYS 0x11
-#define I40E_AQ_RESOURCE_TYPE_VN2_KEYS 0x12
-#define I40E_AQ_RESOURCE_TYPE_TUNNEL_PORTS 0x13
- u8 reserved1;
- __le16 guaranteed;
- __le16 total;
- __le16 used;
- __le16 total_unalloced;
- u8 reserved2[6];
-};
-
-I40E_CHECK_STRUCT_LEN(0x10, i40e_aqc_switch_resource_alloc_element_resp);
-
-/* Set Switch Configuration (direct 0x0205) */
-struct i40e_aqc_set_switch_config {
- __le16 flags;
-/* flags used for both fields below */
-#define I40E_AQ_SET_SWITCH_CFG_PROMISC 0x0001
-#define I40E_AQ_SET_SWITCH_CFG_L2_FILTER 0x0002
- __le16 valid_flags;
- /* The ethertype in switch_tag is dropped on ingress and used
- * internally by the switch. Set this to zero for the default
- * of 0x88a8 (802.1ad). Should be zero for firmware API
- * versions lower than 1.7.
- */
- __le16 switch_tag;
- /* The ethertypes in first_tag and second_tag are used to
- * match the outer and inner VLAN tags (respectively) when HW
- * double VLAN tagging is enabled via the set port parameters
- * AQ command. Otherwise these are both ignored. Set them to
- * zero for their defaults of 0x8100 (802.1Q). Should be zero
- * for firmware API versions lower than 1.7.
- */
- __le16 first_tag;
- __le16 second_tag;
- u8 reserved[6];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_switch_config);
-
-/* Read Receive control registers (direct 0x0206)
- * Write Receive control registers (direct 0x0207)
- * used for accessing Rx control registers that can be
- * slow and need special handling when under high Rx load
- */
-struct i40e_aqc_rx_ctl_reg_read_write {
- __le32 reserved1;
- __le32 address;
- __le32 reserved2;
- __le32 value;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_rx_ctl_reg_read_write);
-
-/* Add VSI (indirect 0x0210)
- * this indirect command uses struct i40e_aqc_vsi_properties_data
- * as the indirect buffer (128 bytes)
- *
- * Update VSI (indirect 0x211)
- * uses the same data structure as Add VSI
- *
- * Get VSI (indirect 0x0212)
- * uses the same completion and data structure as Add VSI
- */
-struct i40e_aqc_add_get_update_vsi {
- __le16 uplink_seid;
- u8 connection_type;
-#define I40E_AQ_VSI_CONN_TYPE_NORMAL 0x1
-#define I40E_AQ_VSI_CONN_TYPE_DEFAULT 0x2
-#define I40E_AQ_VSI_CONN_TYPE_CASCADED 0x3
- u8 reserved1;
- u8 vf_id;
- u8 reserved2;
- __le16 vsi_flags;
-#define I40E_AQ_VSI_TYPE_SHIFT 0x0
-#define I40E_AQ_VSI_TYPE_MASK (0x3 << I40E_AQ_VSI_TYPE_SHIFT)
-#define I40E_AQ_VSI_TYPE_VF 0x0
-#define I40E_AQ_VSI_TYPE_VMDQ2 0x1
-#define I40E_AQ_VSI_TYPE_PF 0x2
-#define I40E_AQ_VSI_TYPE_EMP_MNG 0x3
-#define I40E_AQ_VSI_FLAG_CASCADED_PV 0x4
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi);
-
-struct i40e_aqc_add_get_update_vsi_completion {
- __le16 seid;
- __le16 vsi_number;
- __le16 vsi_used;
- __le16 vsi_free;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi_completion);
-
-struct i40e_aqc_vsi_properties_data {
- /* first 96 byte are written by SW */
- __le16 valid_sections;
-#define I40E_AQ_VSI_PROP_SWITCH_VALID 0x0001
-#define I40E_AQ_VSI_PROP_SECURITY_VALID 0x0002
-#define I40E_AQ_VSI_PROP_VLAN_VALID 0x0004
-#define I40E_AQ_VSI_PROP_CAS_PV_VALID 0x0008
-#define I40E_AQ_VSI_PROP_INGRESS_UP_VALID 0x0010
-#define I40E_AQ_VSI_PROP_EGRESS_UP_VALID 0x0020
-#define I40E_AQ_VSI_PROP_QUEUE_MAP_VALID 0x0040
-#define I40E_AQ_VSI_PROP_QUEUE_OPT_VALID 0x0080
-#define I40E_AQ_VSI_PROP_OUTER_UP_VALID 0x0100
-#define I40E_AQ_VSI_PROP_SCHED_VALID 0x0200
- /* switch section */
- __le16 switch_id; /* 12bit id combined with flags below */
-#define I40E_AQ_VSI_SW_ID_SHIFT 0x0000
-#define I40E_AQ_VSI_SW_ID_MASK (0xFFF << I40E_AQ_VSI_SW_ID_SHIFT)
-#define I40E_AQ_VSI_SW_ID_FLAG_NOT_STAG 0x1000
-#define I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB 0x2000
-#define I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB 0x4000
- u8 sw_reserved[2];
- /* security section */
- u8 sec_flags;
-#define I40E_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD 0x01
-#define I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK 0x02
-#define I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK 0x04
- u8 sec_reserved;
- /* VLAN section */
- __le16 pvid; /* VLANS include priority bits */
- __le16 fcoe_pvid;
- u8 port_vlan_flags;
-#define I40E_AQ_VSI_PVLAN_MODE_SHIFT 0x00
-#define I40E_AQ_VSI_PVLAN_MODE_MASK (0x03 << \
- I40E_AQ_VSI_PVLAN_MODE_SHIFT)
-#define I40E_AQ_VSI_PVLAN_MODE_TAGGED 0x01
-#define I40E_AQ_VSI_PVLAN_MODE_UNTAGGED 0x02
-#define I40E_AQ_VSI_PVLAN_MODE_ALL 0x03
-#define I40E_AQ_VSI_PVLAN_INSERT_PVID 0x04
-#define I40E_AQ_VSI_PVLAN_EMOD_SHIFT 0x03
-#define I40E_AQ_VSI_PVLAN_EMOD_MASK (0x3 << \
- I40E_AQ_VSI_PVLAN_EMOD_SHIFT)
-#define I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH 0x0
-#define I40E_AQ_VSI_PVLAN_EMOD_STR_UP 0x08
-#define I40E_AQ_VSI_PVLAN_EMOD_STR 0x10
-#define I40E_AQ_VSI_PVLAN_EMOD_NOTHING 0x18
- u8 pvlan_reserved[3];
- /* ingress egress up sections */
- __le32 ingress_table; /* bitmap, 3 bits per up */
-#define I40E_AQ_VSI_UP_TABLE_UP0_SHIFT 0
-#define I40E_AQ_VSI_UP_TABLE_UP0_MASK (0x7 << \
- I40E_AQ_VSI_UP_TABLE_UP0_SHIFT)
-#define I40E_AQ_VSI_UP_TABLE_UP1_SHIFT 3
-#define I40E_AQ_VSI_UP_TABLE_UP1_MASK (0x7 << \
- I40E_AQ_VSI_UP_TABLE_UP1_SHIFT)
-#define I40E_AQ_VSI_UP_TABLE_UP2_SHIFT 6
-#define I40E_AQ_VSI_UP_TABLE_UP2_MASK (0x7 << \
- I40E_AQ_VSI_UP_TABLE_UP2_SHIFT)
-#define I40E_AQ_VSI_UP_TABLE_UP3_SHIFT 9
-#define I40E_AQ_VSI_UP_TABLE_UP3_MASK (0x7 << \
- I40E_AQ_VSI_UP_TABLE_UP3_SHIFT)
-#define I40E_AQ_VSI_UP_TABLE_UP4_SHIFT 12
-#define I40E_AQ_VSI_UP_TABLE_UP4_MASK (0x7 << \
- I40E_AQ_VSI_UP_TABLE_UP4_SHIFT)
-#define I40E_AQ_VSI_UP_TABLE_UP5_SHIFT 15
-#define I40E_AQ_VSI_UP_TABLE_UP5_MASK (0x7 << \
- I40E_AQ_VSI_UP_TABLE_UP5_SHIFT)
-#define I40E_AQ_VSI_UP_TABLE_UP6_SHIFT 18
-#define I40E_AQ_VSI_UP_TABLE_UP6_MASK (0x7 << \
- I40E_AQ_VSI_UP_TABLE_UP6_SHIFT)
-#define I40E_AQ_VSI_UP_TABLE_UP7_SHIFT 21
-#define I40E_AQ_VSI_UP_TABLE_UP7_MASK (0x7 << \
- I40E_AQ_VSI_UP_TABLE_UP7_SHIFT)
- __le32 egress_table; /* same defines as for ingress table */
- /* cascaded PV section */
- __le16 cas_pv_tag;
- u8 cas_pv_flags;
-#define I40E_AQ_VSI_CAS_PV_TAGX_SHIFT 0x00
-#define I40E_AQ_VSI_CAS_PV_TAGX_MASK (0x03 << \
- I40E_AQ_VSI_CAS_PV_TAGX_SHIFT)
-#define I40E_AQ_VSI_CAS_PV_TAGX_LEAVE 0x00
-#define I40E_AQ_VSI_CAS_PV_TAGX_REMOVE 0x01
-#define I40E_AQ_VSI_CAS_PV_TAGX_COPY 0x02
-#define I40E_AQ_VSI_CAS_PV_INSERT_TAG 0x10
-#define I40E_AQ_VSI_CAS_PV_ETAG_PRUNE 0x20
-#define I40E_AQ_VSI_CAS_PV_ACCEPT_HOST_TAG 0x40
- u8 cas_pv_reserved;
- /* queue mapping section */
- __le16 mapping_flags;
-#define I40E_AQ_VSI_QUE_MAP_CONTIG 0x0
-#define I40E_AQ_VSI_QUE_MAP_NONCONTIG 0x1
- __le16 queue_mapping[16];
-#define I40E_AQ_VSI_QUEUE_SHIFT 0x0
-#define I40E_AQ_VSI_QUEUE_MASK (0x7FF << I40E_AQ_VSI_QUEUE_SHIFT)
- __le16 tc_mapping[8];
-#define I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT 0
-#define I40E_AQ_VSI_TC_QUE_OFFSET_MASK (0x1FF << \
- I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT)
-#define I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT 9
-#define I40E_AQ_VSI_TC_QUE_NUMBER_MASK (0x7 << \
- I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT)
- /* queueing option section */
- u8 queueing_opt_flags;
-#define I40E_AQ_VSI_QUE_OPT_MULTICAST_UDP_ENA 0x04
-#define I40E_AQ_VSI_QUE_OPT_UNICAST_UDP_ENA 0x08
-#define I40E_AQ_VSI_QUE_OPT_TCP_ENA 0x10
-#define I40E_AQ_VSI_QUE_OPT_FCOE_ENA 0x20
-#define I40E_AQ_VSI_QUE_OPT_RSS_LUT_PF 0x00
-#define I40E_AQ_VSI_QUE_OPT_RSS_LUT_VSI 0x40
- u8 queueing_opt_reserved[3];
- /* scheduler section */
- u8 up_enable_bits;
- u8 sched_reserved;
- /* outer up section */
- __le32 outer_up_table; /* same structure and defines as ingress tbl */
- u8 cmd_reserved[8];
- /* last 32 bytes are written by FW */
- __le16 qs_handle[8];
-#define I40E_AQ_VSI_QS_HANDLE_INVALID 0xFFFF
- __le16 stat_counter_idx;
- __le16 sched_id;
- u8 resp_reserved[12];
-};
-
-I40E_CHECK_STRUCT_LEN(128, i40e_aqc_vsi_properties_data);
-
-/* Add Port Virtualizer (direct 0x0220)
- * also used for update PV (direct 0x0221) but only flags are used
- * (IS_CTRL_PORT only works on add PV)
- */
-struct i40e_aqc_add_update_pv {
- __le16 command_flags;
-#define I40E_AQC_PV_FLAG_PV_TYPE 0x1
-#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_STAG_EN 0x2
-#define I40E_AQC_PV_FLAG_FWD_UNKNOWN_ETAG_EN 0x4
-#define I40E_AQC_PV_FLAG_IS_CTRL_PORT 0x8
- __le16 uplink_seid;
- __le16 connected_seid;
- u8 reserved[10];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv);
-
-struct i40e_aqc_add_update_pv_completion {
- /* reserved for update; for add also encodes error if rc == ENOSPC */
- __le16 pv_seid;
-#define I40E_AQC_PV_ERR_FLAG_NO_PV 0x1
-#define I40E_AQC_PV_ERR_FLAG_NO_SCHED 0x2
-#define I40E_AQC_PV_ERR_FLAG_NO_COUNTER 0x4
-#define I40E_AQC_PV_ERR_FLAG_NO_ENTRY 0x8
- u8 reserved[14];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv_completion);
-
-/* Get PV Params (direct 0x0222)
- * uses i40e_aqc_switch_seid for the descriptor
- */
-
-struct i40e_aqc_get_pv_params_completion {
- __le16 seid;
- __le16 default_stag;
- __le16 pv_flags; /* same flags as add_pv */
-#define I40E_AQC_GET_PV_PV_TYPE 0x1
-#define I40E_AQC_GET_PV_FRWD_UNKNOWN_STAG 0x2
-#define I40E_AQC_GET_PV_FRWD_UNKNOWN_ETAG 0x4
- u8 reserved[8];
- __le16 default_port_seid;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_pv_params_completion);
-
-/* Add VEB (direct 0x0230) */
-struct i40e_aqc_add_veb {
- __le16 uplink_seid;
- __le16 downlink_seid;
- __le16 veb_flags;
-#define I40E_AQC_ADD_VEB_FLOATING 0x1
-#define I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT 1
-#define I40E_AQC_ADD_VEB_PORT_TYPE_MASK (0x3 << \
- I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT)
-#define I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT 0x2
-#define I40E_AQC_ADD_VEB_PORT_TYPE_DATA 0x4
-#define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8 /* deprecated */
-#define I40E_AQC_ADD_VEB_ENABLE_DISABLE_STATS 0x10
- u8 enable_tcs;
- u8 reserved[9];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb);
-
-struct i40e_aqc_add_veb_completion {
- u8 reserved[6];
- __le16 switch_seid;
- /* also encodes error if rc == ENOSPC; codes are the same as add_pv */
- __le16 veb_seid;
-#define I40E_AQC_VEB_ERR_FLAG_NO_VEB 0x1
-#define I40E_AQC_VEB_ERR_FLAG_NO_SCHED 0x2
-#define I40E_AQC_VEB_ERR_FLAG_NO_COUNTER 0x4
-#define I40E_AQC_VEB_ERR_FLAG_NO_ENTRY 0x8
- __le16 statistic_index;
- __le16 vebs_used;
- __le16 vebs_free;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb_completion);
-
-/* Get VEB Parameters (direct 0x0232)
- * uses i40e_aqc_switch_seid for the descriptor
- */
-struct i40e_aqc_get_veb_parameters_completion {
- __le16 seid;
- __le16 switch_id;
- __le16 veb_flags; /* only the first/last flags from 0x0230 is valid */
- __le16 statistic_index;
- __le16 vebs_used;
- __le16 vebs_free;
- u8 reserved[4];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_veb_parameters_completion);
-
-/* Delete Element (direct 0x0243)
- * uses the generic i40e_aqc_switch_seid
- */
-
-/* Add MAC-VLAN (indirect 0x0250) */
-
-/* used for the command for most vlan commands */
-struct i40e_aqc_macvlan {
- __le16 num_addresses;
- __le16 seid[3];
-#define I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT 0
-#define I40E_AQC_MACVLAN_CMD_SEID_NUM_MASK (0x3FF << \
- I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT)
-#define I40E_AQC_MACVLAN_CMD_SEID_VALID 0x8000
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_macvlan);
-
-/* indirect data for command and response */
-struct i40e_aqc_add_macvlan_element_data {
- u8 mac_addr[6];
- __le16 vlan_tag;
- __le16 flags;
-#define I40E_AQC_MACVLAN_ADD_PERFECT_MATCH 0x0001
-#define I40E_AQC_MACVLAN_ADD_HASH_MATCH 0x0002
-#define I40E_AQC_MACVLAN_ADD_IGNORE_VLAN 0x0004
-#define I40E_AQC_MACVLAN_ADD_TO_QUEUE 0x0008
-#define I40E_AQC_MACVLAN_ADD_USE_SHARED_MAC 0x0010
- __le16 queue_number;
-#define I40E_AQC_MACVLAN_CMD_QUEUE_SHIFT 0
-#define I40E_AQC_MACVLAN_CMD_QUEUE_MASK (0x7FF << \
- I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT)
- /* response section */
- u8 match_method;
-#define I40E_AQC_MM_PERFECT_MATCH 0x01
-#define I40E_AQC_MM_HASH_MATCH 0x02
-#define I40E_AQC_MM_ERR_NO_RES 0xFF
- u8 reserved1[3];
-};
-
-struct i40e_aqc_add_remove_macvlan_completion {
- __le16 perfect_mac_used;
- __le16 perfect_mac_free;
- __le16 unicast_hash_free;
- __le16 multicast_hash_free;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_macvlan_completion);
-
-/* Remove MAC-VLAN (indirect 0x0251)
- * uses i40e_aqc_macvlan for the descriptor
- * data points to an array of num_addresses of elements
- */
-
-struct i40e_aqc_remove_macvlan_element_data {
- u8 mac_addr[6];
- __le16 vlan_tag;
- u8 flags;
-#define I40E_AQC_MACVLAN_DEL_PERFECT_MATCH 0x01
-#define I40E_AQC_MACVLAN_DEL_HASH_MATCH 0x02
-#define I40E_AQC_MACVLAN_DEL_IGNORE_VLAN 0x08
-#define I40E_AQC_MACVLAN_DEL_ALL_VSIS 0x10
- u8 reserved[3];
- /* reply section */
- u8 error_code;
-#define I40E_AQC_REMOVE_MACVLAN_SUCCESS 0x0
-#define I40E_AQC_REMOVE_MACVLAN_FAIL 0xFF
- u8 reply_reserved[3];
-};
-
-/* Add VLAN (indirect 0x0252)
- * Remove VLAN (indirect 0x0253)
- * use the generic i40e_aqc_macvlan for the command
- */
-struct i40e_aqc_add_remove_vlan_element_data {
- __le16 vlan_tag;
- u8 vlan_flags;
-/* flags for add VLAN */
-#define I40E_AQC_ADD_VLAN_LOCAL 0x1
-#define I40E_AQC_ADD_PVLAN_TYPE_SHIFT 1
-#define I40E_AQC_ADD_PVLAN_TYPE_MASK (0x3 << I40E_AQC_ADD_PVLAN_TYPE_SHIFT)
-#define I40E_AQC_ADD_PVLAN_TYPE_REGULAR 0x0
-#define I40E_AQC_ADD_PVLAN_TYPE_PRIMARY 0x2
-#define I40E_AQC_ADD_PVLAN_TYPE_SECONDARY 0x4
-#define I40E_AQC_VLAN_PTYPE_SHIFT 3
-#define I40E_AQC_VLAN_PTYPE_MASK (0x3 << I40E_AQC_VLAN_PTYPE_SHIFT)
-#define I40E_AQC_VLAN_PTYPE_REGULAR_VSI 0x0
-#define I40E_AQC_VLAN_PTYPE_PROMISC_VSI 0x8
-#define I40E_AQC_VLAN_PTYPE_COMMUNITY_VSI 0x10
-#define I40E_AQC_VLAN_PTYPE_ISOLATED_VSI 0x18
-/* flags for remove VLAN */
-#define I40E_AQC_REMOVE_VLAN_ALL 0x1
- u8 reserved;
- u8 result;
-/* flags for add VLAN */
-#define I40E_AQC_ADD_VLAN_SUCCESS 0x0
-#define I40E_AQC_ADD_VLAN_FAIL_REQUEST 0xFE
-#define I40E_AQC_ADD_VLAN_FAIL_RESOURCE 0xFF
-/* flags for remove VLAN */
-#define I40E_AQC_REMOVE_VLAN_SUCCESS 0x0
-#define I40E_AQC_REMOVE_VLAN_FAIL 0xFF
- u8 reserved1[3];
-};
-
-struct i40e_aqc_add_remove_vlan_completion {
- u8 reserved[4];
- __le16 vlans_used;
- __le16 vlans_free;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-/* Set VSI Promiscuous Modes (direct 0x0254) */
-struct i40e_aqc_set_vsi_promiscuous_modes {
- __le16 promiscuous_flags;
- __le16 valid_flags;
-/* flags used for both fields above */
-#define I40E_AQC_SET_VSI_PROMISC_UNICAST 0x01
-#define I40E_AQC_SET_VSI_PROMISC_MULTICAST 0x02
-#define I40E_AQC_SET_VSI_PROMISC_BROADCAST 0x04
-#define I40E_AQC_SET_VSI_DEFAULT 0x08
-#define I40E_AQC_SET_VSI_PROMISC_VLAN 0x10
-#define I40E_AQC_SET_VSI_PROMISC_TX 0x8000
- __le16 seid;
-#define I40E_AQC_VSI_PROM_CMD_SEID_MASK 0x3FF
- __le16 vlan_tag;
-#define I40E_AQC_SET_VSI_VLAN_MASK 0x0FFF
-#define I40E_AQC_SET_VSI_VLAN_VALID 0x8000
- u8 reserved[8];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_vsi_promiscuous_modes);
-
-/* Add S/E-tag command (direct 0x0255)
- * Uses generic i40e_aqc_add_remove_tag_completion for completion
- */
-struct i40e_aqc_add_tag {
- __le16 flags;
-#define I40E_AQC_ADD_TAG_FLAG_TO_QUEUE 0x0001
- __le16 seid;
-#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT 0
-#define I40E_AQC_ADD_TAG_CMD_SEID_NUM_MASK (0x3FF << \
- I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT)
- __le16 tag;
- __le16 queue_number;
- u8 reserved[8];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_tag);
-
-struct i40e_aqc_add_remove_tag_completion {
- u8 reserved[12];
- __le16 tags_used;
- __le16 tags_free;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_tag_completion);
-
-/* Remove S/E-tag command (direct 0x0256)
- * Uses generic i40e_aqc_add_remove_tag_completion for completion
- */
-struct i40e_aqc_remove_tag {
- __le16 seid;
-#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT 0
-#define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_MASK (0x3FF << \
- I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT)
- __le16 tag;
- u8 reserved[12];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_tag);
-
-/* Add multicast E-Tag (direct 0x0257)
- * del multicast E-Tag (direct 0x0258) only uses pv_seid and etag fields
- * and no external data
- */
-struct i40e_aqc_add_remove_mcast_etag {
- __le16 pv_seid;
- __le16 etag;
- u8 num_unicast_etags;
- u8 reserved[3];
- __le32 addr_high; /* address of array of 2-byte s-tags */
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag);
-
-struct i40e_aqc_add_remove_mcast_etag_completion {
- u8 reserved[4];
- __le16 mcast_etags_used;
- __le16 mcast_etags_free;
- __le32 addr_high;
- __le32 addr_low;
-
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag_completion);
-
-/* Update S/E-Tag (direct 0x0259) */
-struct i40e_aqc_update_tag {
- __le16 seid;
-#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT 0
-#define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_MASK (0x3FF << \
- I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT)
- __le16 old_tag;
- __le16 new_tag;
- u8 reserved[10];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag);
-
-struct i40e_aqc_update_tag_completion {
- u8 reserved[12];
- __le16 tags_used;
- __le16 tags_free;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag_completion);
-
-/* Add Control Packet filter (direct 0x025A)
- * Remove Control Packet filter (direct 0x025B)
- * uses the i40e_aqc_add_oveb_cloud,
- * and the generic direct completion structure
- */
-struct i40e_aqc_add_remove_control_packet_filter {
- u8 mac[6];
- __le16 etype;
- __le16 flags;
-#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC 0x0001
-#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP 0x0002
-#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE 0x0004
-#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX 0x0008
-#define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_RX 0x0000
- __le16 seid;
-#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT 0
-#define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_MASK (0x3FF << \
- I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT)
- __le16 queue;
- u8 reserved[2];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter);
-
-struct i40e_aqc_add_remove_control_packet_filter_completion {
- __le16 mac_etype_used;
- __le16 etype_used;
- __le16 mac_etype_free;
- __le16 etype_free;
- u8 reserved[8];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter_completion);
-
-/* Add Cloud filters (indirect 0x025C)
- * Remove Cloud filters (indirect 0x025D)
- * uses the i40e_aqc_add_remove_cloud_filters,
- * and the generic indirect completion structure
- */
-struct i40e_aqc_add_remove_cloud_filters {
- u8 num_filters;
- u8 reserved;
- __le16 seid;
-#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT 0
-#define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK (0x3FF << \
- I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT)
- u8 big_buffer_flag;
-#define I40E_AQC_ADD_CLOUD_CMD_BB 1
- u8 reserved2[3];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_cloud_filters);
-
-struct i40e_aqc_cloud_filters_element_data {
- u8 outer_mac[6];
- u8 inner_mac[6];
- __le16 inner_vlan;
- union {
- struct {
- u8 reserved[12];
- u8 data[4];
- } v4;
- struct {
- u8 data[16];
- } v6;
- struct {
- __le16 data[8];
- } raw_v6;
- } ipaddr;
- __le16 flags;
-#define I40E_AQC_ADD_CLOUD_FILTER_SHIFT 0
-#define I40E_AQC_ADD_CLOUD_FILTER_MASK (0x3F << \
- I40E_AQC_ADD_CLOUD_FILTER_SHIFT)
-/* 0x0000 reserved */
-#define I40E_AQC_ADD_CLOUD_FILTER_OIP 0x0001
-/* 0x0002 reserved */
-#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN 0x0003
-#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID 0x0004
-/* 0x0005 reserved */
-#define I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID 0x0006
-/* 0x0007 reserved */
-/* 0x0008 reserved */
-#define I40E_AQC_ADD_CLOUD_FILTER_OMAC 0x0009
-#define I40E_AQC_ADD_CLOUD_FILTER_IMAC 0x000A
-#define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC 0x000B
-#define I40E_AQC_ADD_CLOUD_FILTER_IIP 0x000C
-/* 0x0010 to 0x0017 is for custom filters */
-#define I40E_AQC_ADD_CLOUD_FILTER_IP_PORT 0x0010 /* Dest IP + L4 Port */
-#define I40E_AQC_ADD_CLOUD_FILTER_MAC_PORT 0x0011 /* Dest MAC + L4 Port */
-#define I40E_AQC_ADD_CLOUD_FILTER_MAC_VLAN_PORT 0x0012 /* Dest MAC + VLAN + L4 Port */
-
-#define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE 0x0080
-#define I40E_AQC_ADD_CLOUD_VNK_SHIFT 6
-#define I40E_AQC_ADD_CLOUD_VNK_MASK 0x00C0
-#define I40E_AQC_ADD_CLOUD_FLAGS_IPV4 0
-#define I40E_AQC_ADD_CLOUD_FLAGS_IPV6 0x0100
-
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN 0
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE 2
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_RESERVED 4
-#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN_GPE 5
-
-#define I40E_AQC_ADD_CLOUD_FLAGS_SHARED_OUTER_MAC 0x2000
-#define I40E_AQC_ADD_CLOUD_FLAGS_SHARED_INNER_MAC 0x4000
-#define I40E_AQC_ADD_CLOUD_FLAGS_SHARED_OUTER_IP 0x8000
-
- __le32 tenant_id;
- u8 reserved[4];
- __le16 queue_number;
-#define I40E_AQC_ADD_CLOUD_QUEUE_SHIFT 0
-#define I40E_AQC_ADD_CLOUD_QUEUE_MASK (0x7FF << \
- I40E_AQC_ADD_CLOUD_QUEUE_SHIFT)
- u8 reserved2[14];
- /* response section */
- u8 allocation_result;
-#define I40E_AQC_ADD_CLOUD_FILTER_SUCCESS 0x0
-#define I40E_AQC_ADD_CLOUD_FILTER_FAIL 0xFF
- u8 response_reserved[7];
-};
-
-I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_cloud_filters_element_data);
-
-/* i40e_aqc_cloud_filters_element_bb is used when
- * I40E_AQC_ADD_CLOUD_CMD_BB flag is set.
- */
-struct i40e_aqc_cloud_filters_element_bb {
- struct i40e_aqc_cloud_filters_element_data element;
- u16 general_fields[32];
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0 0
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1 1
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2 2
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0 3
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1 4
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2 5
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD0 6
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD1 7
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X12_WORD2 8
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD0 9
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD1 10
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X13_WORD2 11
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD0 12
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD1 13
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X14_WORD2 14
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD0 15
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD1 16
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD2 17
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD3 18
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD4 19
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD5 20
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD6 21
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X16_WORD7 22
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD0 23
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD1 24
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD2 25
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD3 26
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD4 27
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD5 28
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD6 29
-#define I40E_AQC_ADD_CLOUD_FV_FLU_0X17_WORD7 30
-};
-
-I40E_CHECK_STRUCT_LEN(0x80, i40e_aqc_cloud_filters_element_bb);
-
-struct i40e_aqc_remove_cloud_filters_completion {
- __le16 perfect_ovlan_used;
- __le16 perfect_ovlan_free;
- __le16 vlan_used;
- __le16 vlan_free;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_cloud_filters_completion);
-
-/* Replace filter Command 0x025F
- * uses the i40e_aqc_replace_cloud_filters,
- * and the generic indirect completion structure
- */
-struct i40e_filter_data {
- u8 filter_type;
- u8 input[3];
-};
-
-I40E_CHECK_STRUCT_LEN(4, i40e_filter_data);
-
-struct i40e_aqc_replace_cloud_filters_cmd {
- u8 valid_flags;
-#define I40E_AQC_REPLACE_L1_FILTER 0x0
-#define I40E_AQC_REPLACE_CLOUD_FILTER 0x1
-#define I40E_AQC_GET_CLOUD_FILTERS 0x2
-#define I40E_AQC_MIRROR_CLOUD_FILTER 0x4
-#define I40E_AQC_HIGH_PRIORITY_CLOUD_FILTER 0x8
- u8 old_filter_type;
- u8 new_filter_type;
- u8 tr_bit;
- u8 reserved[4];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_replace_cloud_filters_cmd);
-
-struct i40e_aqc_replace_cloud_filters_cmd_buf {
- u8 data[32];
-/* Filter type INPUT codes*/
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_ENTRIES_MAX 3
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED BIT(7)
-
-/* Field Vector offsets */
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_MAC_DA 0
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_ETH 6
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG 7
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_VLAN 8
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_OVLAN 9
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN 10
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY 11
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IMAC 12
-/* big FLU */
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_IP_DA 14
-/* big FLU */
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_OIP_DA 15
-
-#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_INNER_VLAN 37
- struct i40e_filter_data filters[8];
-};
-
-I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_replace_cloud_filters_cmd_buf);
-
-/* Add Mirror Rule (indirect or direct 0x0260)
- * Delete Mirror Rule (indirect or direct 0x0261)
- * note: some rule types (4,5) do not use an external buffer.
- * take care to set the flags correctly.
- */
-struct i40e_aqc_add_delete_mirror_rule {
- __le16 seid;
- __le16 rule_type;
-#define I40E_AQC_MIRROR_RULE_TYPE_SHIFT 0
-#define I40E_AQC_MIRROR_RULE_TYPE_MASK (0x7 << \
- I40E_AQC_MIRROR_RULE_TYPE_SHIFT)
-#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_INGRESS 1
-#define I40E_AQC_MIRROR_RULE_TYPE_VPORT_EGRESS 2
-#define I40E_AQC_MIRROR_RULE_TYPE_VLAN 3
-#define I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS 4
-#define I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS 5
- __le16 num_entries;
- __le16 destination; /* VSI for add, rule id for delete */
- __le32 addr_high; /* address of array of 2-byte VSI or VLAN ids */
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule);
-
-struct i40e_aqc_add_delete_mirror_rule_completion {
- u8 reserved[2];
- __le16 rule_id; /* only used on add */
- __le16 mirror_rules_used;
- __le16 mirror_rules_free;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion);
-
-/* Dynamic Device Personalization */
-struct i40e_aqc_write_personalization_profile {
- u8 flags;
- u8 reserved[3];
- __le32 profile_track_id;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_write_personalization_profile);
-
-struct i40e_aqc_write_ddp_resp {
- __le32 error_offset;
- __le32 error_info;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-struct i40e_aqc_get_applied_profiles {
- u8 flags;
-#define I40E_AQC_GET_DDP_GET_CONF 0x1
-#define I40E_AQC_GET_DDP_GET_RDPU_CONF 0x2
- u8 rsv[3];
- __le32 reserved;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_applied_profiles);
-
-/* DCB 0x03xx*/
-
-/* PFC Ignore (direct 0x0301)
- * the command and response use the same descriptor structure
- */
-struct i40e_aqc_pfc_ignore {
- u8 tc_bitmap;
- u8 command_flags; /* unused on response */
-#define I40E_AQC_PFC_IGNORE_SET 0x80
-#define I40E_AQC_PFC_IGNORE_CLEAR 0x0
- u8 reserved[14];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_pfc_ignore);
-
-/* DCB Update (direct 0x0302) uses the i40e_aq_desc structure
- * with no parameters
- */
-
-/* TX scheduler 0x04xx */
-
-/* Almost all the indirect commands use
- * this generic struct to pass the SEID in param0
- */
-struct i40e_aqc_tx_sched_ind {
- __le16 vsi_seid;
- u8 reserved[6];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_tx_sched_ind);
-
-/* Several commands respond with a set of queue set handles */
-struct i40e_aqc_qs_handles_resp {
- __le16 qs_handles[8];
-};
-
-/* Configure VSI BW limits (direct 0x0400) */
-struct i40e_aqc_configure_vsi_bw_limit {
- __le16 vsi_seid;
- u8 reserved[2];
- __le16 credit;
- u8 reserved1[2];
- u8 max_credit; /* 0-3, limit = 2^max */
- u8 reserved2[7];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_vsi_bw_limit);
-
-/* Configure VSI Bandwidth Limit per Traffic Type (indirect 0x0406)
- * responds with i40e_aqc_qs_handles_resp
- */
-struct i40e_aqc_configure_vsi_ets_sla_bw_data {
- u8 tc_valid_bits;
- u8 reserved[15];
- __le16 tc_bw_credits[8]; /* FW writesback QS handles here */
-
- /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */
- __le16 tc_bw_max[2];
- u8 reserved1[28];
-};
-
-I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_configure_vsi_ets_sla_bw_data);
-
-/* Configure VSI Bandwidth Allocation per Traffic Type (indirect 0x0407)
- * responds with i40e_aqc_qs_handles_resp
- */
-struct i40e_aqc_configure_vsi_tc_bw_data {
- u8 tc_valid_bits;
- u8 reserved[3];
- u8 tc_bw_credits[8];
- u8 reserved1[4];
- __le16 qs_handles[8];
-};
-
-I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_configure_vsi_tc_bw_data);
-
-/* Query vsi bw configuration (indirect 0x0408) */
-struct i40e_aqc_query_vsi_bw_config_resp {
- u8 tc_valid_bits;
- u8 tc_suspended_bits;
- u8 reserved[14];
- __le16 qs_handles[8];
- u8 reserved1[4];
- __le16 port_bw_limit;
- u8 reserved2[2];
- u8 max_bw; /* 0-3, limit = 2^max */
- u8 reserved3[23];
-};
-
-I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_query_vsi_bw_config_resp);
-
-/* Query VSI Bandwidth Allocation per Traffic Type (indirect 0x040A) */
-struct i40e_aqc_query_vsi_ets_sla_config_resp {
- u8 tc_valid_bits;
- u8 reserved[3];
- u8 share_credits[8];
- __le16 credits[8];
-
- /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */
- __le16 tc_bw_max[2];
-};
-
-I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_query_vsi_ets_sla_config_resp);
-
-/* Configure Switching Component Bandwidth Limit (direct 0x0410) */
-struct i40e_aqc_configure_switching_comp_bw_limit {
- __le16 seid;
- u8 reserved[2];
- __le16 credit;
- u8 reserved1[2];
- u8 max_bw; /* 0-3, limit = 2^max */
- u8 reserved2[7];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_switching_comp_bw_limit);
-
-/* Enable Physical Port ETS (indirect 0x0413)
- * Modify Physical Port ETS (indirect 0x0414)
- * Disable Physical Port ETS (indirect 0x0415)
- */
-struct i40e_aqc_configure_switching_comp_ets_data {
- u8 reserved[4];
- u8 tc_valid_bits;
- u8 seepage;
-#define I40E_AQ_ETS_SEEPAGE_EN_MASK 0x1
- u8 tc_strict_priority_flags;
- u8 reserved1[17];
- u8 tc_bw_share_credits[8];
- u8 reserved2[96];
-};
-
-I40E_CHECK_STRUCT_LEN(0x80, i40e_aqc_configure_switching_comp_ets_data);
-
-/* Configure Switching Component Bandwidth Limits per Tc (indirect 0x0416) */
-struct i40e_aqc_configure_switching_comp_ets_bw_limit_data {
- u8 tc_valid_bits;
- u8 reserved[15];
- __le16 tc_bw_credit[8];
-
- /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */
- __le16 tc_bw_max[2];
- u8 reserved1[28];
-};
-
-I40E_CHECK_STRUCT_LEN(0x40,
- i40e_aqc_configure_switching_comp_ets_bw_limit_data);
-
-/* Configure Switching Component Bandwidth Allocation per Tc
- * (indirect 0x0417)
- */
-struct i40e_aqc_configure_switching_comp_bw_config_data {
- u8 tc_valid_bits;
- u8 reserved[2];
- u8 absolute_credits; /* bool */
- u8 tc_bw_share_credits[8];
- u8 reserved1[20];
-};
-
-I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_configure_switching_comp_bw_config_data);
-
-/* Query Switching Component Configuration (indirect 0x0418) */
-struct i40e_aqc_query_switching_comp_ets_config_resp {
- u8 tc_valid_bits;
- u8 reserved[35];
- __le16 port_bw_limit;
- u8 reserved1[2];
- u8 tc_bw_max; /* 0-3, limit = 2^max */
- u8 reserved2[23];
-};
-
-I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_query_switching_comp_ets_config_resp);
-
-/* Query PhysicalPort ETS Configuration (indirect 0x0419) */
-struct i40e_aqc_query_port_ets_config_resp {
- u8 reserved[4];
- u8 tc_valid_bits;
- u8 reserved1;
- u8 tc_strict_priority_bits;
- u8 reserved2;
- u8 tc_bw_share_credits[8];
- __le16 tc_bw_limits[8];
-
- /* 4 bits per tc 0-7, 4th bit reserved, limit = 2^max */
- __le16 tc_bw_max[2];
- u8 reserved3[32];
-};
-
-I40E_CHECK_STRUCT_LEN(0x44, i40e_aqc_query_port_ets_config_resp);
-
-/* Query Switching Component Bandwidth Allocation per Traffic Type
- * (indirect 0x041A)
- */
-struct i40e_aqc_query_switching_comp_bw_config_resp {
- u8 tc_valid_bits;
- u8 reserved[2];
- u8 absolute_credits_enable; /* bool */
- u8 tc_bw_share_credits[8];
- __le16 tc_bw_limits[8];
-
- /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */
- __le16 tc_bw_max[2];
-};
-
-I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_query_switching_comp_bw_config_resp);
-
-/* Suspend/resume port TX traffic
- * (direct 0x041B and 0x041C) uses the generic SEID struct
- */
-
-/* Configure partition BW
- * (indirect 0x041D)
- */
-struct i40e_aqc_configure_partition_bw_data {
- __le16 pf_valid_bits;
- u8 min_bw[16]; /* guaranteed bandwidth */
- u8 max_bw[16]; /* bandwidth limit */
-};
-
-I40E_CHECK_STRUCT_LEN(0x22, i40e_aqc_configure_partition_bw_data);
-
-/* Get and set the active HMC resource profile and status.
- * (direct 0x0500) and (direct 0x0501)
- */
-struct i40e_aq_get_set_hmc_resource_profile {
- u8 pm_profile;
- u8 pe_vf_enabled;
- u8 reserved[14];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aq_get_set_hmc_resource_profile);
-
-enum i40e_aq_hmc_profile {
- /* I40E_HMC_PROFILE_NO_CHANGE = 0, reserved */
- I40E_HMC_PROFILE_DEFAULT = 1,
- I40E_HMC_PROFILE_FAVOR_VF = 2,
- I40E_HMC_PROFILE_EQUAL = 3,
-};
-
-/* Get PHY Abilities (indirect 0x0600) uses the generic indirect struct */
-
-/* set in param0 for get phy abilities to report qualified modules */
-#define I40E_AQ_PHY_REPORT_QUALIFIED_MODULES 0x0001
-#define I40E_AQ_PHY_REPORT_INITIAL_VALUES 0x0002
-
-enum i40e_aq_phy_type {
- I40E_PHY_TYPE_SGMII = 0x0,
- I40E_PHY_TYPE_1000BASE_KX = 0x1,
- I40E_PHY_TYPE_10GBASE_KX4 = 0x2,
- I40E_PHY_TYPE_10GBASE_KR = 0x3,
- I40E_PHY_TYPE_40GBASE_KR4 = 0x4,
- I40E_PHY_TYPE_XAUI = 0x5,
- I40E_PHY_TYPE_XFI = 0x6,
- I40E_PHY_TYPE_SFI = 0x7,
- I40E_PHY_TYPE_XLAUI = 0x8,
- I40E_PHY_TYPE_XLPPI = 0x9,
- I40E_PHY_TYPE_40GBASE_CR4_CU = 0xA,
- I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB,
- I40E_PHY_TYPE_10GBASE_AOC = 0xC,
- I40E_PHY_TYPE_40GBASE_AOC = 0xD,
- I40E_PHY_TYPE_UNRECOGNIZED = 0xE,
- I40E_PHY_TYPE_UNSUPPORTED = 0xF,
- I40E_PHY_TYPE_100BASE_TX = 0x11,
- I40E_PHY_TYPE_1000BASE_T = 0x12,
- I40E_PHY_TYPE_10GBASE_T = 0x13,
- I40E_PHY_TYPE_10GBASE_SR = 0x14,
- I40E_PHY_TYPE_10GBASE_LR = 0x15,
- I40E_PHY_TYPE_10GBASE_SFPP_CU = 0x16,
- I40E_PHY_TYPE_10GBASE_CR1 = 0x17,
- I40E_PHY_TYPE_40GBASE_CR4 = 0x18,
- I40E_PHY_TYPE_40GBASE_SR4 = 0x19,
- I40E_PHY_TYPE_40GBASE_LR4 = 0x1A,
- I40E_PHY_TYPE_1000BASE_SX = 0x1B,
- I40E_PHY_TYPE_1000BASE_LX = 0x1C,
- I40E_PHY_TYPE_1000BASE_T_OPTICAL = 0x1D,
- I40E_PHY_TYPE_20GBASE_KR2 = 0x1E,
- I40E_PHY_TYPE_25GBASE_KR = 0x1F,
- I40E_PHY_TYPE_25GBASE_CR = 0x20,
- I40E_PHY_TYPE_25GBASE_SR = 0x21,
- I40E_PHY_TYPE_25GBASE_LR = 0x22,
- I40E_PHY_TYPE_25GBASE_AOC = 0x23,
- I40E_PHY_TYPE_25GBASE_ACC = 0x24,
- I40E_PHY_TYPE_MAX,
- I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP = 0xFD,
- I40E_PHY_TYPE_EMPTY = 0xFE,
- I40E_PHY_TYPE_DEFAULT = 0xFF,
-};
-
-#define I40E_LINK_SPEED_100MB_SHIFT 0x1
-#define I40E_LINK_SPEED_1000MB_SHIFT 0x2
-#define I40E_LINK_SPEED_10GB_SHIFT 0x3
-#define I40E_LINK_SPEED_40GB_SHIFT 0x4
-#define I40E_LINK_SPEED_20GB_SHIFT 0x5
-#define I40E_LINK_SPEED_25GB_SHIFT 0x6
-
-enum i40e_aq_link_speed {
- I40E_LINK_SPEED_UNKNOWN = 0,
- I40E_LINK_SPEED_100MB = BIT(I40E_LINK_SPEED_100MB_SHIFT),
- I40E_LINK_SPEED_1GB = BIT(I40E_LINK_SPEED_1000MB_SHIFT),
- I40E_LINK_SPEED_10GB = BIT(I40E_LINK_SPEED_10GB_SHIFT),
- I40E_LINK_SPEED_40GB = BIT(I40E_LINK_SPEED_40GB_SHIFT),
- I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT),
- I40E_LINK_SPEED_25GB = BIT(I40E_LINK_SPEED_25GB_SHIFT),
-};
-
-struct i40e_aqc_module_desc {
- u8 oui[3];
- u8 reserved1;
- u8 part_number[16];
- u8 revision[4];
- u8 reserved2[8];
-};
-
-I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_module_desc);
-
-struct i40e_aq_get_phy_abilities_resp {
- __le32 phy_type; /* bitmap using the above enum for offsets */
- u8 link_speed; /* bitmap using the above enum bit patterns */
- u8 abilities;
-#define I40E_AQ_PHY_FLAG_PAUSE_TX 0x01
-#define I40E_AQ_PHY_FLAG_PAUSE_RX 0x02
-#define I40E_AQ_PHY_FLAG_LOW_POWER 0x04
-#define I40E_AQ_PHY_LINK_ENABLED 0x08
-#define I40E_AQ_PHY_AN_ENABLED 0x10
-#define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20
-#define I40E_AQ_PHY_FEC_ABILITY_KR 0x40
-#define I40E_AQ_PHY_FEC_ABILITY_RS 0x80
- __le16 eee_capability;
-#define I40E_AQ_EEE_100BASE_TX 0x0002
-#define I40E_AQ_EEE_1000BASE_T 0x0004
-#define I40E_AQ_EEE_10GBASE_T 0x0008
-#define I40E_AQ_EEE_1000BASE_KX 0x0010
-#define I40E_AQ_EEE_10GBASE_KX4 0x0020
-#define I40E_AQ_EEE_10GBASE_KR 0x0040
- __le32 eeer_val;
- u8 d3_lpan;
-#define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01
- u8 phy_type_ext;
-#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
-#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
-#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
-#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
-#define I40E_AQ_PHY_TYPE_EXT_25G_AOC 0x10
-#define I40E_AQ_PHY_TYPE_EXT_25G_ACC 0x20
- u8 fec_cfg_curr_mod_ext_info;
-#define I40E_AQ_ENABLE_FEC_KR 0x01
-#define I40E_AQ_ENABLE_FEC_RS 0x02
-#define I40E_AQ_REQUEST_FEC_KR 0x04
-#define I40E_AQ_REQUEST_FEC_RS 0x08
-#define I40E_AQ_ENABLE_FEC_AUTO 0x10
-#define I40E_AQ_FEC
-#define I40E_AQ_MODULE_TYPE_EXT_MASK 0xE0
-#define I40E_AQ_MODULE_TYPE_EXT_SHIFT 5
-
- u8 ext_comp_code;
- u8 phy_id[4];
- u8 module_type[3];
- u8 qualified_module_count;
-#define I40E_AQ_PHY_MAX_QMS 16
- struct i40e_aqc_module_desc qualified_module[I40E_AQ_PHY_MAX_QMS];
-};
-
-I40E_CHECK_STRUCT_LEN(0x218, i40e_aq_get_phy_abilities_resp);
-
-/* Set PHY Config (direct 0x0601) */
-struct i40e_aq_set_phy_config { /* same bits as above in all */
- __le32 phy_type;
- u8 link_speed;
- u8 abilities;
-/* bits 0-2 use the values from get_phy_abilities_resp */
-#define I40E_AQ_PHY_ENABLE_LINK 0x08
-#define I40E_AQ_PHY_ENABLE_AN 0x10
-#define I40E_AQ_PHY_ENABLE_ATOMIC_LINK 0x20
- __le16 eee_capability;
- __le32 eeer;
- u8 low_power_ctrl;
- u8 phy_type_ext;
-#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
-#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
-#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
-#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
- u8 fec_config;
-#define I40E_AQ_SET_FEC_ABILITY_KR BIT(0)
-#define I40E_AQ_SET_FEC_ABILITY_RS BIT(1)
-#define I40E_AQ_SET_FEC_REQUEST_KR BIT(2)
-#define I40E_AQ_SET_FEC_REQUEST_RS BIT(3)
-#define I40E_AQ_SET_FEC_AUTO BIT(4)
-#define I40E_AQ_PHY_FEC_CONFIG_SHIFT 0x0
-#define I40E_AQ_PHY_FEC_CONFIG_MASK (0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT)
- u8 reserved;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
-
-/* Set MAC Config command data structure (direct 0x0603) */
-struct i40e_aq_set_mac_config {
- __le16 max_frame_size;
- u8 params;
-#define I40E_AQ_SET_MAC_CONFIG_CRC_EN 0x04
-#define I40E_AQ_SET_MAC_CONFIG_PACING_MASK 0x78
-#define I40E_AQ_SET_MAC_CONFIG_PACING_SHIFT 3
-#define I40E_AQ_SET_MAC_CONFIG_PACING_NONE 0x0
-#define I40E_AQ_SET_MAC_CONFIG_PACING_1B_13TX 0xF
-#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_9TX 0x9
-#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_4TX 0x8
-#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_7TX 0x7
-#define I40E_AQ_SET_MAC_CONFIG_PACING_2DW_3TX 0x6
-#define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_1TX 0x5
-#define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_2TX 0x4
-#define I40E_AQ_SET_MAC_CONFIG_PACING_7DW_3TX 0x3
-#define I40E_AQ_SET_MAC_CONFIG_PACING_4DW_1TX 0x2
-#define I40E_AQ_SET_MAC_CONFIG_PACING_9DW_1TX 0x1
- u8 tx_timer_priority; /* bitmap */
- __le16 tx_timer_value;
- __le16 fc_refresh_threshold;
- u8 reserved[8];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aq_set_mac_config);
-
-/* Restart Auto-Negotiation (direct 0x605) */
-struct i40e_aqc_set_link_restart_an {
- u8 command;
-#define I40E_AQ_PHY_RESTART_AN 0x02
-#define I40E_AQ_PHY_LINK_ENABLE 0x04
- u8 reserved[15];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_link_restart_an);
-
-/* Get Link Status cmd & response data structure (direct 0x0607) */
-struct i40e_aqc_get_link_status {
- __le16 command_flags; /* only field set on command */
-#define I40E_AQ_LSE_MASK 0x3
-#define I40E_AQ_LSE_NOP 0x0
-#define I40E_AQ_LSE_DISABLE 0x2
-#define I40E_AQ_LSE_ENABLE 0x3
-/* only response uses this flag */
-#define I40E_AQ_LSE_IS_ENABLED 0x1
- u8 phy_type; /* i40e_aq_phy_type */
- u8 link_speed; /* i40e_aq_link_speed */
- u8 link_info;
-#define I40E_AQ_LINK_UP 0x01 /* obsolete */
-#define I40E_AQ_LINK_UP_FUNCTION 0x01
-#define I40E_AQ_LINK_FAULT 0x02
-#define I40E_AQ_LINK_FAULT_TX 0x04
-#define I40E_AQ_LINK_FAULT_RX 0x08
-#define I40E_AQ_LINK_FAULT_REMOTE 0x10
-#define I40E_AQ_LINK_UP_PORT 0x20
-#define I40E_AQ_MEDIA_AVAILABLE 0x40
-#define I40E_AQ_SIGNAL_DETECT 0x80
- u8 an_info;
-#define I40E_AQ_AN_COMPLETED 0x01
-#define I40E_AQ_LP_AN_ABILITY 0x02
-#define I40E_AQ_PD_FAULT 0x04
-#define I40E_AQ_FEC_EN 0x08
-#define I40E_AQ_PHY_LOW_POWER 0x10
-#define I40E_AQ_LINK_PAUSE_TX 0x20
-#define I40E_AQ_LINK_PAUSE_RX 0x40
-#define I40E_AQ_QUALIFIED_MODULE 0x80
- u8 ext_info;
-#define I40E_AQ_LINK_PHY_TEMP_ALARM 0x01
-#define I40E_AQ_LINK_XCESSIVE_ERRORS 0x02
-#define I40E_AQ_LINK_TX_SHIFT 0x02
-#define I40E_AQ_LINK_TX_MASK (0x03 << I40E_AQ_LINK_TX_SHIFT)
-#define I40E_AQ_LINK_TX_ACTIVE 0x00
-#define I40E_AQ_LINK_TX_DRAINED 0x01
-#define I40E_AQ_LINK_TX_FLUSHED 0x03
-#define I40E_AQ_LINK_FORCED_40G 0x10
-/* 25G Error Codes */
-#define I40E_AQ_25G_NO_ERR 0X00
-#define I40E_AQ_25G_NOT_PRESENT 0X01
-#define I40E_AQ_25G_NVM_CRC_ERR 0X02
-#define I40E_AQ_25G_SBUS_UCODE_ERR 0X03
-#define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
-#define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
- u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
-/* Since firmware API 1.7 loopback field keeps power class info as well */
-#define I40E_AQ_LOOPBACK_MASK 0x07
-#define I40E_AQ_PWR_CLASS_SHIFT_LB 6
-#define I40E_AQ_PWR_CLASS_MASK_LB (0x03 << I40E_AQ_PWR_CLASS_SHIFT_LB)
- __le16 max_frame_size;
- u8 config;
-#define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
-#define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
-#define I40E_AQ_CONFIG_CRC_ENA 0x04
-#define I40E_AQ_CONFIG_PACING_MASK 0x78
- union {
- struct {
- u8 power_desc;
-#define I40E_AQ_LINK_POWER_CLASS_1 0x00
-#define I40E_AQ_LINK_POWER_CLASS_2 0x01
-#define I40E_AQ_LINK_POWER_CLASS_3 0x02
-#define I40E_AQ_LINK_POWER_CLASS_4 0x03
-#define I40E_AQ_PWR_CLASS_MASK 0x03
- u8 reserved[4];
- };
- struct {
- u8 link_type[4];
- u8 link_type_ext;
- };
- };
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status);
-
-/* Set event mask command (direct 0x613) */
-struct i40e_aqc_set_phy_int_mask {
- u8 reserved[8];
- __le16 event_mask;
-#define I40E_AQ_EVENT_LINK_UPDOWN 0x0002
-#define I40E_AQ_EVENT_MEDIA_NA 0x0004
-#define I40E_AQ_EVENT_LINK_FAULT 0x0008
-#define I40E_AQ_EVENT_PHY_TEMP_ALARM 0x0010
-#define I40E_AQ_EVENT_EXCESSIVE_ERRORS 0x0020
-#define I40E_AQ_EVENT_SIGNAL_DETECT 0x0040
-#define I40E_AQ_EVENT_AN_COMPLETED 0x0080
-#define I40E_AQ_EVENT_MODULE_QUAL_FAIL 0x0100
-#define I40E_AQ_EVENT_PORT_TX_SUSPENDED 0x0200
- u8 reserved1[6];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_int_mask);
-
-/* Get Local AN advt register (direct 0x0614)
- * Set Local AN advt register (direct 0x0615)
- * Get Link Partner AN advt register (direct 0x0616)
- */
-struct i40e_aqc_an_advt_reg {
- __le32 local_an_reg0;
- __le16 local_an_reg1;
- u8 reserved[10];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_an_advt_reg);
-
-/* Set Loopback mode (0x0618) */
-struct i40e_aqc_set_lb_mode {
- __le16 lb_mode;
-#define I40E_AQ_LB_PHY_LOCAL 0x01
-#define I40E_AQ_LB_PHY_REMOTE 0x02
-#define I40E_AQ_LB_MAC_LOCAL 0x04
- u8 reserved[14];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_lb_mode);
-
-/* Set PHY Debug command (0x0622) */
-struct i40e_aqc_set_phy_debug {
- u8 command_flags;
-#define I40E_AQ_PHY_DEBUG_RESET_INTERNAL 0x02
-#define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SHIFT 2
-#define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_MASK (0x03 << \
- I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SHIFT)
-#define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_NONE 0x00
-#define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_HARD 0x01
-#define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SOFT 0x02
-#define I40E_AQ_PHY_DEBUG_DISABLE_LINK_FW 0x10
- u8 reserved[15];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_debug);
-
-enum i40e_aq_phy_reg_type {
- I40E_AQC_PHY_REG_INTERNAL = 0x1,
- I40E_AQC_PHY_REG_EXERNAL_BASET = 0x2,
- I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3
-};
-
-/* Run PHY Activity (0x0626) */
-struct i40e_aqc_run_phy_activity {
- __le16 activity_id;
- u8 flags;
- u8 reserved1;
- __le32 control;
- __le32 data;
- u8 reserved2[4];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity);
-
-/* Set PHY Register command (0x0628) */
-/* Get PHY Register command (0x0629) */
-struct i40e_aqc_phy_register_access {
- u8 phy_interface;
-#define I40E_AQ_PHY_REG_ACCESS_INTERNAL 0
-#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL 1
-#define I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE 2
- u8 dev_address;
- u8 reserved1[2];
- __le32 reg_address;
- __le32 reg_value;
- u8 reserved2[4];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_phy_register_access);
-
-/* NVM Read command (indirect 0x0701)
- * NVM Erase commands (direct 0x0702)
- * NVM Update commands (indirect 0x0703)
- */
-struct i40e_aqc_nvm_update {
- u8 command_flags;
-#define I40E_AQ_NVM_LAST_CMD 0x01
-#define I40E_AQ_NVM_REARRANGE_TO_FLAT 0x20
-#define I40E_AQ_NVM_REARRANGE_TO_STRUCT 0x40
-#define I40E_AQ_NVM_FLASH_ONLY 0x80
-#define I40E_AQ_NVM_PRESERVATION_FLAGS_SHIFT 1
-#define I40E_AQ_NVM_PRESERVATION_FLAGS_MASK 0x03
-#define I40E_AQ_NVM_PRESERVATION_FLAGS_SELECTED 0x03
-#define I40E_AQ_NVM_PRESERVATION_FLAGS_ALL 0x01
- u8 module_pointer;
- __le16 length;
- __le32 offset;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_update);
-
-/* NVM Config Read (indirect 0x0704) */
-struct i40e_aqc_nvm_config_read {
- __le16 cmd_flags;
-#define I40E_AQ_ANVM_SINGLE_OR_MULTIPLE_FEATURES_MASK 1
-#define I40E_AQ_ANVM_READ_SINGLE_FEATURE 0
-#define I40E_AQ_ANVM_READ_MULTIPLE_FEATURES 1
- __le16 element_count;
- __le16 element_id; /* Feature/field ID */
- __le16 element_id_msw; /* MSWord of field ID */
- __le32 address_high;
- __le32 address_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_config_read);
-
-/* NVM Config Write (indirect 0x0705) */
-struct i40e_aqc_nvm_config_write {
- __le16 cmd_flags;
- __le16 element_count;
- u8 reserved[4];
- __le32 address_high;
- __le32 address_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_config_write);
-
-/* Used for 0x0704 as well as for 0x0705 commands */
-#define I40E_AQ_ANVM_FEATURE_OR_IMMEDIATE_SHIFT 1
-#define I40E_AQ_ANVM_FEATURE_OR_IMMEDIATE_MASK \
- BIT(I40E_AQ_ANVM_FEATURE_OR_IMMEDIATE_SHIFT)
-#define I40E_AQ_ANVM_FEATURE 0
-#define I40E_AQ_ANVM_IMMEDIATE_FIELD BIT(FEATURE_OR_IMMEDIATE_SHIFT)
-struct i40e_aqc_nvm_config_data_feature {
- __le16 feature_id;
-#define I40E_AQ_ANVM_FEATURE_OPTION_OEM_ONLY 0x01
-#define I40E_AQ_ANVM_FEATURE_OPTION_DWORD_MAP 0x08
-#define I40E_AQ_ANVM_FEATURE_OPTION_POR_CSR 0x10
- __le16 feature_options;
- __le16 feature_selection;
-};
-
-I40E_CHECK_STRUCT_LEN(0x6, i40e_aqc_nvm_config_data_feature);
-
-struct i40e_aqc_nvm_config_data_immediate_field {
- __le32 field_id;
- __le32 field_value;
- __le16 field_options;
- __le16 reserved;
-};
-
-I40E_CHECK_STRUCT_LEN(0xc, i40e_aqc_nvm_config_data_immediate_field);
-
-/* OEM Post Update (indirect 0x0720)
- * no command data struct used
- */
- struct i40e_aqc_nvm_oem_post_update {
-#define I40E_AQ_NVM_OEM_POST_UPDATE_EXTERNAL_DATA 0x01
- u8 sel_data;
- u8 reserved[7];
-};
-
-I40E_CHECK_STRUCT_LEN(0x8, i40e_aqc_nvm_oem_post_update);
-
-struct i40e_aqc_nvm_oem_post_update_buffer {
- u8 str_len;
- u8 dev_addr;
- __le16 eeprom_addr;
- u8 data[36];
-};
-
-I40E_CHECK_STRUCT_LEN(0x28, i40e_aqc_nvm_oem_post_update_buffer);
-
-/* Thermal Sensor (indirect 0x0721)
- * read or set thermal sensor configs and values
- * takes a sensor and command specific data buffer, not detailed here
- */
-struct i40e_aqc_thermal_sensor {
- u8 sensor_action;
-#define I40E_AQ_THERMAL_SENSOR_READ_CONFIG 0
-#define I40E_AQ_THERMAL_SENSOR_SET_CONFIG 1
-#define I40E_AQ_THERMAL_SENSOR_READ_TEMP 2
- u8 reserved[7];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_thermal_sensor);
-
-/* Send to PF command (indirect 0x0801) id is only used by PF
- * Send to VF command (indirect 0x0802) id is only used by PF
- * Send to Peer PF command (indirect 0x0803)
- */
-struct i40e_aqc_pf_vf_message {
- __le32 id;
- u8 reserved[4];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_pf_vf_message);
-
-/* Alternate structure */
-
-/* Direct write (direct 0x0900)
- * Direct read (direct 0x0902)
- */
-struct i40e_aqc_alternate_write {
- __le32 address0;
- __le32 data0;
- __le32 address1;
- __le32 data1;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_write);
-
-/* Indirect write (indirect 0x0901)
- * Indirect read (indirect 0x0903)
- */
-
-struct i40e_aqc_alternate_ind_write {
- __le32 address;
- __le32 length;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_ind_write);
-
-/* Done alternate write (direct 0x0904)
- * uses i40e_aq_desc
- */
-struct i40e_aqc_alternate_write_done {
- __le16 cmd_flags;
-#define I40E_AQ_ALTERNATE_MODE_BIOS_MASK 1
-#define I40E_AQ_ALTERNATE_MODE_BIOS_LEGACY 0
-#define I40E_AQ_ALTERNATE_MODE_BIOS_UEFI 1
-#define I40E_AQ_ALTERNATE_RESET_NEEDED 2
- u8 reserved[14];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_write_done);
-
-/* Set OEM mode (direct 0x0905) */
-struct i40e_aqc_alternate_set_mode {
- __le32 mode;
-#define I40E_AQ_ALTERNATE_MODE_NONE 0
-#define I40E_AQ_ALTERNATE_MODE_OEM 1
- u8 reserved[12];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_set_mode);
-
-/* Clear port Alternate RAM (direct 0x0906) uses i40e_aq_desc */
-
-/* async events 0x10xx */
-
-/* Lan Queue Overflow Event (direct, 0x1001) */
-struct i40e_aqc_lan_overflow {
- __le32 prtdcb_rupto;
- __le32 otx_ctl;
- u8 reserved[8];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_lan_overflow);
-
-/* Get LLDP MIB (indirect 0x0A00) */
-struct i40e_aqc_lldp_get_mib {
- u8 type;
- u8 reserved1;
-#define I40E_AQ_LLDP_MIB_TYPE_MASK 0x3
-#define I40E_AQ_LLDP_MIB_LOCAL 0x0
-#define I40E_AQ_LLDP_MIB_REMOTE 0x1
-#define I40E_AQ_LLDP_MIB_LOCAL_AND_REMOTE 0x2
-#define I40E_AQ_LLDP_BRIDGE_TYPE_MASK 0xC
-#define I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT 0x2
-#define I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE 0x0
-#define I40E_AQ_LLDP_BRIDGE_TYPE_NON_TPMR 0x1
-#define I40E_AQ_LLDP_TX_SHIFT 0x4
-#define I40E_AQ_LLDP_TX_MASK (0x03 << I40E_AQ_LLDP_TX_SHIFT)
-/* TX pause flags use I40E_AQ_LINK_TX_* above */
- __le16 local_len;
- __le16 remote_len;
- u8 reserved2[2];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_get_mib);
-
-/* Configure LLDP MIB Change Event (direct 0x0A01)
- * also used for the event (with type in the command field)
- */
-struct i40e_aqc_lldp_update_mib {
- u8 command;
-#define I40E_AQ_LLDP_MIB_UPDATE_ENABLE 0x0
-#define I40E_AQ_LLDP_MIB_UPDATE_DISABLE 0x1
- u8 reserved[7];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_mib);
-
-/* Add LLDP TLV (indirect 0x0A02)
- * Delete LLDP TLV (indirect 0x0A04)
- */
-struct i40e_aqc_lldp_add_tlv {
- u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */
- u8 reserved1[1];
- __le16 len;
- u8 reserved2[4];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_add_tlv);
-
-/* Update LLDP TLV (indirect 0x0A03) */
-struct i40e_aqc_lldp_update_tlv {
- u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */
- u8 reserved;
- __le16 old_len;
- __le16 new_offset;
- __le16 new_len;
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_tlv);
-
-/* Stop LLDP (direct 0x0A05) */
-struct i40e_aqc_lldp_stop {
- u8 command;
-#define I40E_AQ_LLDP_AGENT_STOP 0x0
-#define I40E_AQ_LLDP_AGENT_SHUTDOWN 0x1
- u8 reserved[15];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop);
-
-/* Start LLDP (direct 0x0A06) */
-
-struct i40e_aqc_lldp_start {
- u8 command;
-#define I40E_AQ_LLDP_AGENT_START 0x1
- u8 reserved[15];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start);
-
-/* Set DCB (direct 0x0303) */
-struct i40e_aqc_set_dcb_parameters {
- u8 command;
-#define I40E_AQ_DCB_SET_AGENT 0x1
-#define I40E_DCB_VALID 0x1
- u8 valid_flags;
- u8 reserved[14];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_set_dcb_parameters);
-
-/* Apply MIB changes (0x0A07)
- * uses the generic struc as it contains no data
- */
-
-/* Add Udp Tunnel command and completion (direct 0x0B00) */
-struct i40e_aqc_add_udp_tunnel {
- __le16 udp_port;
- u8 reserved0[3];
- u8 protocol_type;
-#define I40E_AQC_TUNNEL_TYPE_VXLAN 0x00
-#define I40E_AQC_TUNNEL_TYPE_NGE 0x01
-#define I40E_AQC_TUNNEL_TYPE_TEREDO 0x10
-#define I40E_AQC_TUNNEL_TYPE_VXLAN_GPE 0x11
- u8 reserved1[10];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel);
-
-struct i40e_aqc_add_udp_tunnel_completion {
- __le16 udp_port;
- u8 filter_entry_index;
- u8 multiple_pfs;
-#define I40E_AQC_SINGLE_PF 0x0
-#define I40E_AQC_MULTIPLE_PFS 0x1
- u8 total_filters;
- u8 reserved[11];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel_completion);
-
-/* remove UDP Tunnel command (0x0B01) */
-struct i40e_aqc_remove_udp_tunnel {
- u8 reserved[2];
- u8 index; /* 0 to 15 */
- u8 reserved2[13];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_udp_tunnel);
-
-struct i40e_aqc_del_udp_tunnel_completion {
- __le16 udp_port;
- u8 index; /* 0 to 15 */
- u8 multiple_pfs;
- u8 total_filters_used;
- u8 reserved1[11];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_del_udp_tunnel_completion);
-
-struct i40e_aqc_get_set_rss_key {
-#define I40E_AQC_SET_RSS_KEY_VSI_VALID BIT(15)
-#define I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT 0
-#define I40E_AQC_SET_RSS_KEY_VSI_ID_MASK (0x3FF << \
- I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT)
- __le16 vsi_id;
- u8 reserved[6];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_set_rss_key);
-
-struct i40e_aqc_get_set_rss_key_data {
- u8 standard_rss_key[0x28];
- u8 extended_hash_key[0xc];
-};
-
-I40E_CHECK_STRUCT_LEN(0x34, i40e_aqc_get_set_rss_key_data);
-
-struct i40e_aqc_get_set_rss_lut {
-#define I40E_AQC_SET_RSS_LUT_VSI_VALID BIT(15)
-#define I40E_AQC_SET_RSS_LUT_VSI_ID_SHIFT 0
-#define I40E_AQC_SET_RSS_LUT_VSI_ID_MASK (0x3FF << \
- I40E_AQC_SET_RSS_LUT_VSI_ID_SHIFT)
- __le16 vsi_id;
-#define I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT 0
-#define I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK \
- BIT(I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT)
-
-#define I40E_AQC_SET_RSS_LUT_TABLE_TYPE_VSI 0
-#define I40E_AQC_SET_RSS_LUT_TABLE_TYPE_PF 1
- __le16 flags;
- u8 reserved[4];
- __le32 addr_high;
- __le32 addr_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_get_set_rss_lut);
-
-/* tunnel key structure 0x0B10 */
-
-struct i40e_aqc_tunnel_key_structure_A0 {
- __le16 key1_off;
- __le16 key1_len;
- __le16 key2_off;
- __le16 key2_len;
- __le16 flags;
-#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01
-/* response flags */
-#define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS 0x01
-#define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED 0x02
-#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03
- u8 resreved[6];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_tunnel_key_structure_A0);
-
-struct i40e_aqc_tunnel_key_structure {
- u8 key1_off;
- u8 key2_off;
- u8 key1_len; /* 0 to 15 */
- u8 key2_len; /* 0 to 15 */
- u8 flags;
-#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01
-/* response flags */
-#define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS 0x01
-#define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED 0x02
-#define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03
- u8 network_key_index;
-#define I40E_AQC_NETWORK_KEY_INDEX_VXLAN 0x0
-#define I40E_AQC_NETWORK_KEY_INDEX_NGE 0x1
-#define I40E_AQC_NETWORK_KEY_INDEX_FLEX_MAC_IN_UDP 0x2
-#define I40E_AQC_NETWORK_KEY_INDEX_GRE 0x3
- u8 reserved[10];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_tunnel_key_structure);
-
-/* OEM mode commands (direct 0xFE0x) */
-struct i40e_aqc_oem_param_change {
- __le32 param_type;
-#define I40E_AQ_OEM_PARAM_TYPE_PF_CTL 0
-#define I40E_AQ_OEM_PARAM_TYPE_BW_CTL 1
-#define I40E_AQ_OEM_PARAM_MAC 2
- __le32 param_value1;
- __le16 param_value2;
- u8 reserved[6];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_param_change);
-
-struct i40e_aqc_oem_state_change {
- __le32 state;
-#define I40E_AQ_OEM_STATE_LINK_DOWN 0x0
-#define I40E_AQ_OEM_STATE_LINK_UP 0x1
- u8 reserved[12];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_state_change);
-
-/* Initialize OCSD (0xFE02, direct) */
-struct i40e_aqc_opc_oem_ocsd_initialize {
- u8 type_status;
- u8 reserved1[3];
- __le32 ocsd_memory_block_addr_high;
- __le32 ocsd_memory_block_addr_low;
- __le32 requested_update_interval;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_opc_oem_ocsd_initialize);
-
-/* Initialize OCBB (0xFE03, direct) */
-struct i40e_aqc_opc_oem_ocbb_initialize {
- u8 type_status;
- u8 reserved1[3];
- __le32 ocbb_memory_block_addr_high;
- __le32 ocbb_memory_block_addr_low;
- u8 reserved2[4];
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_opc_oem_ocbb_initialize);
-
-/* debug commands */
-
-/* get device id (0xFF00) uses the generic structure */
-
-/* set test more (0xFF01, internal) */
-
-struct i40e_acq_set_test_mode {
- u8 mode;
-#define I40E_AQ_TEST_PARTIAL 0
-#define I40E_AQ_TEST_FULL 1
-#define I40E_AQ_TEST_NVM 2
- u8 reserved[3];
- u8 command;
-#define I40E_AQ_TEST_OPEN 0
-#define I40E_AQ_TEST_CLOSE 1
-#define I40E_AQ_TEST_INC 2
- u8 reserved2[3];
- __le32 address_high;
- __le32 address_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_acq_set_test_mode);
-
-/* Debug Read Register command (0xFF03)
- * Debug Write Register command (0xFF04)
- */
-struct i40e_aqc_debug_reg_read_write {
- __le32 reserved;
- __le32 address;
- __le32 value_high;
- __le32 value_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_reg_read_write);
-
-/* Scatter/gather Reg Read (indirect 0xFF05)
- * Scatter/gather Reg Write (indirect 0xFF06)
- */
-
-/* i40e_aq_desc is used for the command */
-struct i40e_aqc_debug_reg_sg_element_data {
- __le32 address;
- __le32 value;
-};
-
-/* Debug Modify register (direct 0xFF07) */
-struct i40e_aqc_debug_modify_reg {
- __le32 address;
- __le32 value;
- __le32 clear_mask;
- __le32 set_mask;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_reg);
-
-/* dump internal data (0xFF08, indirect) */
-
-#define I40E_AQ_CLUSTER_ID_AUX 0
-#define I40E_AQ_CLUSTER_ID_SWITCH_FLU 1
-#define I40E_AQ_CLUSTER_ID_TXSCHED 2
-#define I40E_AQ_CLUSTER_ID_HMC 3
-#define I40E_AQ_CLUSTER_ID_MAC0 4
-#define I40E_AQ_CLUSTER_ID_MAC1 5
-#define I40E_AQ_CLUSTER_ID_MAC2 6
-#define I40E_AQ_CLUSTER_ID_MAC3 7
-#define I40E_AQ_CLUSTER_ID_DCB 8
-#define I40E_AQ_CLUSTER_ID_EMP_MEM 9
-#define I40E_AQ_CLUSTER_ID_PKT_BUF 10
-#define I40E_AQ_CLUSTER_ID_ALTRAM 11
-
-struct i40e_aqc_debug_dump_internals {
- u8 cluster_id;
- u8 table_id;
- __le16 data_size;
- __le32 idx;
- __le32 address_high;
- __le32 address_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_dump_internals);
-
-struct i40e_aqc_debug_modify_internals {
- u8 cluster_id;
- u8 cluster_specific_params[7];
- __le32 address_high;
- __le32 address_low;
-};
-
-I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_internals);
-
-#endif /* _I40E_ADMINQ_CMD_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_alloc.h b/drivers/net/ethernet/intel/i40evf/i40e_alloc.h
deleted file mode 100644
index cb8689222c8b..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_alloc.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_ALLOC_H_
-#define _I40E_ALLOC_H_
-
-struct i40e_hw;
-
-/* Memory allocation types */
-enum i40e_memory_type {
- i40e_mem_arq_buf = 0, /* ARQ indirect command buffer */
- i40e_mem_asq_buf = 1,
- i40e_mem_atq_buf = 2, /* ATQ indirect command buffer */
- i40e_mem_arq_ring = 3, /* ARQ descriptor ring */
- i40e_mem_atq_ring = 4, /* ATQ descriptor ring */
- i40e_mem_pd = 5, /* Page Descriptor */
- i40e_mem_bp = 6, /* Backing Page - 4KB */
- i40e_mem_bp_jumbo = 7, /* Backing Page - > 4KB */
- i40e_mem_reserved
-};
-
-/* prototype for functions used for dynamic memory allocation */
-i40e_status i40e_allocate_dma_mem(struct i40e_hw *hw,
- struct i40e_dma_mem *mem,
- enum i40e_memory_type type,
- u64 size, u32 alignment);
-i40e_status i40e_free_dma_mem(struct i40e_hw *hw,
- struct i40e_dma_mem *mem);
-i40e_status i40e_allocate_virt_mem(struct i40e_hw *hw,
- struct i40e_virt_mem *mem,
- u32 size);
-i40e_status i40e_free_virt_mem(struct i40e_hw *hw,
- struct i40e_virt_mem *mem);
-
-#endif /* _I40E_ALLOC_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c
deleted file mode 100644
index eea280ba411e..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_common.c
+++ /dev/null
@@ -1,1320 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#include "i40e_type.h"
-#include "i40e_adminq.h"
-#include "i40e_prototype.h"
-#include <linux/avf/virtchnl.h>
-
-/**
- * i40e_set_mac_type - Sets MAC type
- * @hw: pointer to the HW structure
- *
- * This function sets the mac type of the adapter based on the
- * vendor ID and device ID stored in the hw structure.
- **/
-i40e_status i40e_set_mac_type(struct i40e_hw *hw)
-{
- i40e_status status = 0;
-
- if (hw->vendor_id == PCI_VENDOR_ID_INTEL) {
- switch (hw->device_id) {
- case I40E_DEV_ID_SFP_XL710:
- case I40E_DEV_ID_QEMU:
- case I40E_DEV_ID_KX_B:
- case I40E_DEV_ID_KX_C:
- case I40E_DEV_ID_QSFP_A:
- case I40E_DEV_ID_QSFP_B:
- case I40E_DEV_ID_QSFP_C:
- case I40E_DEV_ID_10G_BASE_T:
- case I40E_DEV_ID_10G_BASE_T4:
- case I40E_DEV_ID_20G_KR2:
- case I40E_DEV_ID_20G_KR2_A:
- case I40E_DEV_ID_25G_B:
- case I40E_DEV_ID_25G_SFP28:
- hw->mac.type = I40E_MAC_XL710;
- break;
- case I40E_DEV_ID_SFP_X722:
- case I40E_DEV_ID_1G_BASE_T_X722:
- case I40E_DEV_ID_10G_BASE_T_X722:
- case I40E_DEV_ID_SFP_I_X722:
- hw->mac.type = I40E_MAC_X722;
- break;
- case I40E_DEV_ID_X722_VF:
- hw->mac.type = I40E_MAC_X722_VF;
- break;
- case I40E_DEV_ID_VF:
- case I40E_DEV_ID_VF_HV:
- case I40E_DEV_ID_ADAPTIVE_VF:
- hw->mac.type = I40E_MAC_VF;
- break;
- default:
- hw->mac.type = I40E_MAC_GENERIC;
- break;
- }
- } else {
- status = I40E_ERR_DEVICE_NOT_SUPPORTED;
- }
-
- hw_dbg(hw, "i40e_set_mac_type found mac: %d, returns: %d\n",
- hw->mac.type, status);
- return status;
-}
-
-/**
- * i40evf_aq_str - convert AQ err code to a string
- * @hw: pointer to the HW structure
- * @aq_err: the AQ error code to convert
- **/
-const char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err)
-{
- switch (aq_err) {
- case I40E_AQ_RC_OK:
- return "OK";
- case I40E_AQ_RC_EPERM:
- return "I40E_AQ_RC_EPERM";
- case I40E_AQ_RC_ENOENT:
- return "I40E_AQ_RC_ENOENT";
- case I40E_AQ_RC_ESRCH:
- return "I40E_AQ_RC_ESRCH";
- case I40E_AQ_RC_EINTR:
- return "I40E_AQ_RC_EINTR";
- case I40E_AQ_RC_EIO:
- return "I40E_AQ_RC_EIO";
- case I40E_AQ_RC_ENXIO:
- return "I40E_AQ_RC_ENXIO";
- case I40E_AQ_RC_E2BIG:
- return "I40E_AQ_RC_E2BIG";
- case I40E_AQ_RC_EAGAIN:
- return "I40E_AQ_RC_EAGAIN";
- case I40E_AQ_RC_ENOMEM:
- return "I40E_AQ_RC_ENOMEM";
- case I40E_AQ_RC_EACCES:
- return "I40E_AQ_RC_EACCES";
- case I40E_AQ_RC_EFAULT:
- return "I40E_AQ_RC_EFAULT";
- case I40E_AQ_RC_EBUSY:
- return "I40E_AQ_RC_EBUSY";
- case I40E_AQ_RC_EEXIST:
- return "I40E_AQ_RC_EEXIST";
- case I40E_AQ_RC_EINVAL:
- return "I40E_AQ_RC_EINVAL";
- case I40E_AQ_RC_ENOTTY:
- return "I40E_AQ_RC_ENOTTY";
- case I40E_AQ_RC_ENOSPC:
- return "I40E_AQ_RC_ENOSPC";
- case I40E_AQ_RC_ENOSYS:
- return "I40E_AQ_RC_ENOSYS";
- case I40E_AQ_RC_ERANGE:
- return "I40E_AQ_RC_ERANGE";
- case I40E_AQ_RC_EFLUSHED:
- return "I40E_AQ_RC_EFLUSHED";
- case I40E_AQ_RC_BAD_ADDR:
- return "I40E_AQ_RC_BAD_ADDR";
- case I40E_AQ_RC_EMODE:
- return "I40E_AQ_RC_EMODE";
- case I40E_AQ_RC_EFBIG:
- return "I40E_AQ_RC_EFBIG";
- }
-
- snprintf(hw->err_str, sizeof(hw->err_str), "%d", aq_err);
- return hw->err_str;
-}
-
-/**
- * i40evf_stat_str - convert status err code to a string
- * @hw: pointer to the HW structure
- * @stat_err: the status error code to convert
- **/
-const char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err)
-{
- switch (stat_err) {
- case 0:
- return "OK";
- case I40E_ERR_NVM:
- return "I40E_ERR_NVM";
- case I40E_ERR_NVM_CHECKSUM:
- return "I40E_ERR_NVM_CHECKSUM";
- case I40E_ERR_PHY:
- return "I40E_ERR_PHY";
- case I40E_ERR_CONFIG:
- return "I40E_ERR_CONFIG";
- case I40E_ERR_PARAM:
- return "I40E_ERR_PARAM";
- case I40E_ERR_MAC_TYPE:
- return "I40E_ERR_MAC_TYPE";
- case I40E_ERR_UNKNOWN_PHY:
- return "I40E_ERR_UNKNOWN_PHY";
- case I40E_ERR_LINK_SETUP:
- return "I40E_ERR_LINK_SETUP";
- case I40E_ERR_ADAPTER_STOPPED:
- return "I40E_ERR_ADAPTER_STOPPED";
- case I40E_ERR_INVALID_MAC_ADDR:
- return "I40E_ERR_INVALID_MAC_ADDR";
- case I40E_ERR_DEVICE_NOT_SUPPORTED:
- return "I40E_ERR_DEVICE_NOT_SUPPORTED";
- case I40E_ERR_MASTER_REQUESTS_PENDING:
- return "I40E_ERR_MASTER_REQUESTS_PENDING";
- case I40E_ERR_INVALID_LINK_SETTINGS:
- return "I40E_ERR_INVALID_LINK_SETTINGS";
- case I40E_ERR_AUTONEG_NOT_COMPLETE:
- return "I40E_ERR_AUTONEG_NOT_COMPLETE";
- case I40E_ERR_RESET_FAILED:
- return "I40E_ERR_RESET_FAILED";
- case I40E_ERR_SWFW_SYNC:
- return "I40E_ERR_SWFW_SYNC";
- case I40E_ERR_NO_AVAILABLE_VSI:
- return "I40E_ERR_NO_AVAILABLE_VSI";
- case I40E_ERR_NO_MEMORY:
- return "I40E_ERR_NO_MEMORY";
- case I40E_ERR_BAD_PTR:
- return "I40E_ERR_BAD_PTR";
- case I40E_ERR_RING_FULL:
- return "I40E_ERR_RING_FULL";
- case I40E_ERR_INVALID_PD_ID:
- return "I40E_ERR_INVALID_PD_ID";
- case I40E_ERR_INVALID_QP_ID:
- return "I40E_ERR_INVALID_QP_ID";
- case I40E_ERR_INVALID_CQ_ID:
- return "I40E_ERR_INVALID_CQ_ID";
- case I40E_ERR_INVALID_CEQ_ID:
- return "I40E_ERR_INVALID_CEQ_ID";
- case I40E_ERR_INVALID_AEQ_ID:
- return "I40E_ERR_INVALID_AEQ_ID";
- case I40E_ERR_INVALID_SIZE:
- return "I40E_ERR_INVALID_SIZE";
- case I40E_ERR_INVALID_ARP_INDEX:
- return "I40E_ERR_INVALID_ARP_INDEX";
- case I40E_ERR_INVALID_FPM_FUNC_ID:
- return "I40E_ERR_INVALID_FPM_FUNC_ID";
- case I40E_ERR_QP_INVALID_MSG_SIZE:
- return "I40E_ERR_QP_INVALID_MSG_SIZE";
- case I40E_ERR_QP_TOOMANY_WRS_POSTED:
- return "I40E_ERR_QP_TOOMANY_WRS_POSTED";
- case I40E_ERR_INVALID_FRAG_COUNT:
- return "I40E_ERR_INVALID_FRAG_COUNT";
- case I40E_ERR_QUEUE_EMPTY:
- return "I40E_ERR_QUEUE_EMPTY";
- case I40E_ERR_INVALID_ALIGNMENT:
- return "I40E_ERR_INVALID_ALIGNMENT";
- case I40E_ERR_FLUSHED_QUEUE:
- return "I40E_ERR_FLUSHED_QUEUE";
- case I40E_ERR_INVALID_PUSH_PAGE_INDEX:
- return "I40E_ERR_INVALID_PUSH_PAGE_INDEX";
- case I40E_ERR_INVALID_IMM_DATA_SIZE:
- return "I40E_ERR_INVALID_IMM_DATA_SIZE";
- case I40E_ERR_TIMEOUT:
- return "I40E_ERR_TIMEOUT";
- case I40E_ERR_OPCODE_MISMATCH:
- return "I40E_ERR_OPCODE_MISMATCH";
- case I40E_ERR_CQP_COMPL_ERROR:
- return "I40E_ERR_CQP_COMPL_ERROR";
- case I40E_ERR_INVALID_VF_ID:
- return "I40E_ERR_INVALID_VF_ID";
- case I40E_ERR_INVALID_HMCFN_ID:
- return "I40E_ERR_INVALID_HMCFN_ID";
- case I40E_ERR_BACKING_PAGE_ERROR:
- return "I40E_ERR_BACKING_PAGE_ERROR";
- case I40E_ERR_NO_PBLCHUNKS_AVAILABLE:
- return "I40E_ERR_NO_PBLCHUNKS_AVAILABLE";
- case I40E_ERR_INVALID_PBLE_INDEX:
- return "I40E_ERR_INVALID_PBLE_INDEX";
- case I40E_ERR_INVALID_SD_INDEX:
- return "I40E_ERR_INVALID_SD_INDEX";
- case I40E_ERR_INVALID_PAGE_DESC_INDEX:
- return "I40E_ERR_INVALID_PAGE_DESC_INDEX";
- case I40E_ERR_INVALID_SD_TYPE:
- return "I40E_ERR_INVALID_SD_TYPE";
- case I40E_ERR_MEMCPY_FAILED:
- return "I40E_ERR_MEMCPY_FAILED";
- case I40E_ERR_INVALID_HMC_OBJ_INDEX:
- return "I40E_ERR_INVALID_HMC_OBJ_INDEX";
- case I40E_ERR_INVALID_HMC_OBJ_COUNT:
- return "I40E_ERR_INVALID_HMC_OBJ_COUNT";
- case I40E_ERR_INVALID_SRQ_ARM_LIMIT:
- return "I40E_ERR_INVALID_SRQ_ARM_LIMIT";
- case I40E_ERR_SRQ_ENABLED:
- return "I40E_ERR_SRQ_ENABLED";
- case I40E_ERR_ADMIN_QUEUE_ERROR:
- return "I40E_ERR_ADMIN_QUEUE_ERROR";
- case I40E_ERR_ADMIN_QUEUE_TIMEOUT:
- return "I40E_ERR_ADMIN_QUEUE_TIMEOUT";
- case I40E_ERR_BUF_TOO_SHORT:
- return "I40E_ERR_BUF_TOO_SHORT";
- case I40E_ERR_ADMIN_QUEUE_FULL:
- return "I40E_ERR_ADMIN_QUEUE_FULL";
- case I40E_ERR_ADMIN_QUEUE_NO_WORK:
- return "I40E_ERR_ADMIN_QUEUE_NO_WORK";
- case I40E_ERR_BAD_IWARP_CQE:
- return "I40E_ERR_BAD_IWARP_CQE";
- case I40E_ERR_NVM_BLANK_MODE:
- return "I40E_ERR_NVM_BLANK_MODE";
- case I40E_ERR_NOT_IMPLEMENTED:
- return "I40E_ERR_NOT_IMPLEMENTED";
- case I40E_ERR_PE_DOORBELL_NOT_ENABLED:
- return "I40E_ERR_PE_DOORBELL_NOT_ENABLED";
- case I40E_ERR_DIAG_TEST_FAILED:
- return "I40E_ERR_DIAG_TEST_FAILED";
- case I40E_ERR_NOT_READY:
- return "I40E_ERR_NOT_READY";
- case I40E_NOT_SUPPORTED:
- return "I40E_NOT_SUPPORTED";
- case I40E_ERR_FIRMWARE_API_VERSION:
- return "I40E_ERR_FIRMWARE_API_VERSION";
- case I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR:
- return "I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR";
- }
-
- snprintf(hw->err_str, sizeof(hw->err_str), "%d", stat_err);
- return hw->err_str;
-}
-
-/**
- * i40evf_debug_aq
- * @hw: debug mask related to admin queue
- * @mask: debug mask
- * @desc: pointer to admin queue descriptor
- * @buffer: pointer to command buffer
- * @buf_len: max length of buffer
- *
- * Dumps debug log about adminq command with descriptor contents.
- **/
-void i40evf_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
- void *buffer, u16 buf_len)
-{
- struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc;
- u8 *buf = (u8 *)buffer;
-
- if ((!(mask & hw->debug_mask)) || (desc == NULL))
- return;
-
- i40e_debug(hw, mask,
- "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
- le16_to_cpu(aq_desc->opcode),
- le16_to_cpu(aq_desc->flags),
- le16_to_cpu(aq_desc->datalen),
- le16_to_cpu(aq_desc->retval));
- i40e_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n",
- le32_to_cpu(aq_desc->cookie_high),
- le32_to_cpu(aq_desc->cookie_low));
- i40e_debug(hw, mask, "\tparam (0,1) 0x%08X 0x%08X\n",
- le32_to_cpu(aq_desc->params.internal.param0),
- le32_to_cpu(aq_desc->params.internal.param1));
- i40e_debug(hw, mask, "\taddr (h,l) 0x%08X 0x%08X\n",
- le32_to_cpu(aq_desc->params.external.addr_high),
- le32_to_cpu(aq_desc->params.external.addr_low));
-
- if ((buffer != NULL) && (aq_desc->datalen != 0)) {
- u16 len = le16_to_cpu(aq_desc->datalen);
-
- i40e_debug(hw, mask, "AQ CMD Buffer:\n");
- if (buf_len < len)
- len = buf_len;
- /* write the full 16-byte chunks */
- if (hw->debug_mask & mask) {
- char prefix[27];
-
- snprintf(prefix, sizeof(prefix),
- "i40evf %02x:%02x.%x: \t0x",
- hw->bus.bus_id,
- hw->bus.device,
- hw->bus.func);
-
- print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET,
- 16, 1, buf, len, false);
- }
- }
-}
-
-/**
- * i40evf_check_asq_alive
- * @hw: pointer to the hw struct
- *
- * Returns true if Queue is enabled else false.
- **/
-bool i40evf_check_asq_alive(struct i40e_hw *hw)
-{
- if (hw->aq.asq.len)
- return !!(rd32(hw, hw->aq.asq.len) &
- I40E_VF_ATQLEN1_ATQENABLE_MASK);
- else
- return false;
-}
-
-/**
- * i40evf_aq_queue_shutdown
- * @hw: pointer to the hw struct
- * @unloading: is the driver unloading itself
- *
- * Tell the Firmware that we're shutting down the AdminQ and whether
- * or not the driver is unloading as well.
- **/
-i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw,
- bool unloading)
-{
- struct i40e_aq_desc desc;
- struct i40e_aqc_queue_shutdown *cmd =
- (struct i40e_aqc_queue_shutdown *)&desc.params.raw;
- i40e_status status;
-
- i40evf_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_queue_shutdown);
-
- if (unloading)
- cmd->driver_unloading = cpu_to_le32(I40E_AQ_DRIVER_UNLOADING);
- status = i40evf_asq_send_command(hw, &desc, NULL, 0, NULL);
-
- return status;
-}
-
-/**
- * i40e_aq_get_set_rss_lut
- * @hw: pointer to the hardware structure
- * @vsi_id: vsi fw index
- * @pf_lut: for PF table set true, for VSI table set false
- * @lut: pointer to the lut buffer provided by the caller
- * @lut_size: size of the lut buffer
- * @set: set true to set the table, false to get the table
- *
- * Internal function to get or set RSS look up table
- **/
-static i40e_status i40e_aq_get_set_rss_lut(struct i40e_hw *hw,
- u16 vsi_id, bool pf_lut,
- u8 *lut, u16 lut_size,
- bool set)
-{
- i40e_status status;
- struct i40e_aq_desc desc;
- struct i40e_aqc_get_set_rss_lut *cmd_resp =
- (struct i40e_aqc_get_set_rss_lut *)&desc.params.raw;
-
- if (set)
- i40evf_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_set_rss_lut);
- else
- i40evf_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_get_rss_lut);
-
- /* Indirect command */
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_RD);
-
- cmd_resp->vsi_id =
- cpu_to_le16((u16)((vsi_id <<
- I40E_AQC_SET_RSS_LUT_VSI_ID_SHIFT) &
- I40E_AQC_SET_RSS_LUT_VSI_ID_MASK));
- cmd_resp->vsi_id |= cpu_to_le16((u16)I40E_AQC_SET_RSS_LUT_VSI_VALID);
-
- if (pf_lut)
- cmd_resp->flags |= cpu_to_le16((u16)
- ((I40E_AQC_SET_RSS_LUT_TABLE_TYPE_PF <<
- I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) &
- I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK));
- else
- cmd_resp->flags |= cpu_to_le16((u16)
- ((I40E_AQC_SET_RSS_LUT_TABLE_TYPE_VSI <<
- I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) &
- I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK));
-
- status = i40evf_asq_send_command(hw, &desc, lut, lut_size, NULL);
-
- return status;
-}
-
-/**
- * i40evf_aq_get_rss_lut
- * @hw: pointer to the hardware structure
- * @vsi_id: vsi fw index
- * @pf_lut: for PF table set true, for VSI table set false
- * @lut: pointer to the lut buffer provided by the caller
- * @lut_size: size of the lut buffer
- *
- * get the RSS lookup table, PF or VSI type
- **/
-i40e_status i40evf_aq_get_rss_lut(struct i40e_hw *hw, u16 vsi_id,
- bool pf_lut, u8 *lut, u16 lut_size)
-{
- return i40e_aq_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size,
- false);
-}
-
-/**
- * i40evf_aq_set_rss_lut
- * @hw: pointer to the hardware structure
- * @vsi_id: vsi fw index
- * @pf_lut: for PF table set true, for VSI table set false
- * @lut: pointer to the lut buffer provided by the caller
- * @lut_size: size of the lut buffer
- *
- * set the RSS lookup table, PF or VSI type
- **/
-i40e_status i40evf_aq_set_rss_lut(struct i40e_hw *hw, u16 vsi_id,
- bool pf_lut, u8 *lut, u16 lut_size)
-{
- return i40e_aq_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size, true);
-}
-
-/**
- * i40e_aq_get_set_rss_key
- * @hw: pointer to the hw struct
- * @vsi_id: vsi fw index
- * @key: pointer to key info struct
- * @set: set true to set the key, false to get the key
- *
- * get the RSS key per VSI
- **/
-static i40e_status i40e_aq_get_set_rss_key(struct i40e_hw *hw,
- u16 vsi_id,
- struct i40e_aqc_get_set_rss_key_data *key,
- bool set)
-{
- i40e_status status;
- struct i40e_aq_desc desc;
- struct i40e_aqc_get_set_rss_key *cmd_resp =
- (struct i40e_aqc_get_set_rss_key *)&desc.params.raw;
- u16 key_size = sizeof(struct i40e_aqc_get_set_rss_key_data);
-
- if (set)
- i40evf_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_set_rss_key);
- else
- i40evf_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_get_rss_key);
-
- /* Indirect command */
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_RD);
-
- cmd_resp->vsi_id =
- cpu_to_le16((u16)((vsi_id <<
- I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT) &
- I40E_AQC_SET_RSS_KEY_VSI_ID_MASK));
- cmd_resp->vsi_id |= cpu_to_le16((u16)I40E_AQC_SET_RSS_KEY_VSI_VALID);
-
- status = i40evf_asq_send_command(hw, &desc, key, key_size, NULL);
-
- return status;
-}
-
-/**
- * i40evf_aq_get_rss_key
- * @hw: pointer to the hw struct
- * @vsi_id: vsi fw index
- * @key: pointer to key info struct
- *
- **/
-i40e_status i40evf_aq_get_rss_key(struct i40e_hw *hw,
- u16 vsi_id,
- struct i40e_aqc_get_set_rss_key_data *key)
-{
- return i40e_aq_get_set_rss_key(hw, vsi_id, key, false);
-}
-
-/**
- * i40evf_aq_set_rss_key
- * @hw: pointer to the hw struct
- * @vsi_id: vsi fw index
- * @key: pointer to key info struct
- *
- * set the RSS key per VSI
- **/
-i40e_status i40evf_aq_set_rss_key(struct i40e_hw *hw,
- u16 vsi_id,
- struct i40e_aqc_get_set_rss_key_data *key)
-{
- return i40e_aq_get_set_rss_key(hw, vsi_id, key, true);
-}
-
-
-/* The i40evf_ptype_lookup table is used to convert from the 8-bit ptype in the
- * hardware to a bit-field that can be used by SW to more easily determine the
- * packet type.
- *
- * Macros are used to shorten the table lines and make this table human
- * readable.
- *
- * We store the PTYPE in the top byte of the bit field - this is just so that
- * we can check that the table doesn't have a row missing, as the index into
- * the table should be the PTYPE.
- *
- * Typical work flow:
- *
- * IF NOT i40evf_ptype_lookup[ptype].known
- * THEN
- * Packet is unknown
- * ELSE IF i40evf_ptype_lookup[ptype].outer_ip == I40E_RX_PTYPE_OUTER_IP
- * Use the rest of the fields to look at the tunnels, inner protocols, etc
- * ELSE
- * Use the enum i40e_rx_l2_ptype to decode the packet type
- * ENDIF
- */
-
-/* macro to make the table lines short */
-#define I40E_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\
- { PTYPE, \
- 1, \
- I40E_RX_PTYPE_OUTER_##OUTER_IP, \
- I40E_RX_PTYPE_OUTER_##OUTER_IP_VER, \
- I40E_RX_PTYPE_##OUTER_FRAG, \
- I40E_RX_PTYPE_TUNNEL_##T, \
- I40E_RX_PTYPE_TUNNEL_END_##TE, \
- I40E_RX_PTYPE_##TEF, \
- I40E_RX_PTYPE_INNER_PROT_##I, \
- I40E_RX_PTYPE_PAYLOAD_LAYER_##PL }
-
-#define I40E_PTT_UNUSED_ENTRY(PTYPE) \
- { PTYPE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-
-/* shorter macros makes the table fit but are terse */
-#define I40E_RX_PTYPE_NOF I40E_RX_PTYPE_NOT_FRAG
-#define I40E_RX_PTYPE_FRG I40E_RX_PTYPE_FRAG
-#define I40E_RX_PTYPE_INNER_PROT_TS I40E_RX_PTYPE_INNER_PROT_TIMESYNC
-
-/* Lookup table mapping the HW PTYPE to the bit field for decoding */
-struct i40e_rx_ptype_decoded i40evf_ptype_lookup[] = {
- /* L2 Packet types */
- I40E_PTT_UNUSED_ENTRY(0),
- I40E_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
- I40E_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, TS, PAY2),
- I40E_PTT(3, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
- I40E_PTT_UNUSED_ENTRY(4),
- I40E_PTT_UNUSED_ENTRY(5),
- I40E_PTT(6, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
- I40E_PTT(7, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
- I40E_PTT_UNUSED_ENTRY(8),
- I40E_PTT_UNUSED_ENTRY(9),
- I40E_PTT(10, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
- I40E_PTT(11, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE),
- I40E_PTT(12, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(13, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(14, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(15, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(16, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(17, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(18, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(19, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(20, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(21, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
-
- /* Non Tunneled IPv4 */
- I40E_PTT(22, IP, IPV4, FRG, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(23, IP, IPV4, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(24, IP, IPV4, NOF, NONE, NONE, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(25),
- I40E_PTT(26, IP, IPV4, NOF, NONE, NONE, NOF, TCP, PAY4),
- I40E_PTT(27, IP, IPV4, NOF, NONE, NONE, NOF, SCTP, PAY4),
- I40E_PTT(28, IP, IPV4, NOF, NONE, NONE, NOF, ICMP, PAY4),
-
- /* IPv4 --> IPv4 */
- I40E_PTT(29, IP, IPV4, NOF, IP_IP, IPV4, FRG, NONE, PAY3),
- I40E_PTT(30, IP, IPV4, NOF, IP_IP, IPV4, NOF, NONE, PAY3),
- I40E_PTT(31, IP, IPV4, NOF, IP_IP, IPV4, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(32),
- I40E_PTT(33, IP, IPV4, NOF, IP_IP, IPV4, NOF, TCP, PAY4),
- I40E_PTT(34, IP, IPV4, NOF, IP_IP, IPV4, NOF, SCTP, PAY4),
- I40E_PTT(35, IP, IPV4, NOF, IP_IP, IPV4, NOF, ICMP, PAY4),
-
- /* IPv4 --> IPv6 */
- I40E_PTT(36, IP, IPV4, NOF, IP_IP, IPV6, FRG, NONE, PAY3),
- I40E_PTT(37, IP, IPV4, NOF, IP_IP, IPV6, NOF, NONE, PAY3),
- I40E_PTT(38, IP, IPV4, NOF, IP_IP, IPV6, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(39),
- I40E_PTT(40, IP, IPV4, NOF, IP_IP, IPV6, NOF, TCP, PAY4),
- I40E_PTT(41, IP, IPV4, NOF, IP_IP, IPV6, NOF, SCTP, PAY4),
- I40E_PTT(42, IP, IPV4, NOF, IP_IP, IPV6, NOF, ICMP, PAY4),
-
- /* IPv4 --> GRE/NAT */
- I40E_PTT(43, IP, IPV4, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3),
-
- /* IPv4 --> GRE/NAT --> IPv4 */
- I40E_PTT(44, IP, IPV4, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3),
- I40E_PTT(45, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3),
- I40E_PTT(46, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(47),
- I40E_PTT(48, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4),
- I40E_PTT(49, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4),
- I40E_PTT(50, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4),
-
- /* IPv4 --> GRE/NAT --> IPv6 */
- I40E_PTT(51, IP, IPV4, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3),
- I40E_PTT(52, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3),
- I40E_PTT(53, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(54),
- I40E_PTT(55, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4),
- I40E_PTT(56, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4),
- I40E_PTT(57, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4),
-
- /* IPv4 --> GRE/NAT --> MAC */
- I40E_PTT(58, IP, IPV4, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3),
-
- /* IPv4 --> GRE/NAT --> MAC --> IPv4 */
- I40E_PTT(59, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3),
- I40E_PTT(60, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3),
- I40E_PTT(61, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(62),
- I40E_PTT(63, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4),
- I40E_PTT(64, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4),
- I40E_PTT(65, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4),
-
- /* IPv4 --> GRE/NAT -> MAC --> IPv6 */
- I40E_PTT(66, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3),
- I40E_PTT(67, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3),
- I40E_PTT(68, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(69),
- I40E_PTT(70, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4),
- I40E_PTT(71, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4),
- I40E_PTT(72, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4),
-
- /* IPv4 --> GRE/NAT --> MAC/VLAN */
- I40E_PTT(73, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3),
-
- /* IPv4 ---> GRE/NAT -> MAC/VLAN --> IPv4 */
- I40E_PTT(74, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3),
- I40E_PTT(75, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3),
- I40E_PTT(76, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(77),
- I40E_PTT(78, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4),
- I40E_PTT(79, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4),
- I40E_PTT(80, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4),
-
- /* IPv4 -> GRE/NAT -> MAC/VLAN --> IPv6 */
- I40E_PTT(81, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3),
- I40E_PTT(82, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3),
- I40E_PTT(83, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(84),
- I40E_PTT(85, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4),
- I40E_PTT(86, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4),
- I40E_PTT(87, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4),
-
- /* Non Tunneled IPv6 */
- I40E_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3),
- I40E_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY3),
- I40E_PTT_UNUSED_ENTRY(91),
- I40E_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4),
- I40E_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4),
- I40E_PTT(94, IP, IPV6, NOF, NONE, NONE, NOF, ICMP, PAY4),
-
- /* IPv6 --> IPv4 */
- I40E_PTT(95, IP, IPV6, NOF, IP_IP, IPV4, FRG, NONE, PAY3),
- I40E_PTT(96, IP, IPV6, NOF, IP_IP, IPV4, NOF, NONE, PAY3),
- I40E_PTT(97, IP, IPV6, NOF, IP_IP, IPV4, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(98),
- I40E_PTT(99, IP, IPV6, NOF, IP_IP, IPV4, NOF, TCP, PAY4),
- I40E_PTT(100, IP, IPV6, NOF, IP_IP, IPV4, NOF, SCTP, PAY4),
- I40E_PTT(101, IP, IPV6, NOF, IP_IP, IPV4, NOF, ICMP, PAY4),
-
- /* IPv6 --> IPv6 */
- I40E_PTT(102, IP, IPV6, NOF, IP_IP, IPV6, FRG, NONE, PAY3),
- I40E_PTT(103, IP, IPV6, NOF, IP_IP, IPV6, NOF, NONE, PAY3),
- I40E_PTT(104, IP, IPV6, NOF, IP_IP, IPV6, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(105),
- I40E_PTT(106, IP, IPV6, NOF, IP_IP, IPV6, NOF, TCP, PAY4),
- I40E_PTT(107, IP, IPV6, NOF, IP_IP, IPV6, NOF, SCTP, PAY4),
- I40E_PTT(108, IP, IPV6, NOF, IP_IP, IPV6, NOF, ICMP, PAY4),
-
- /* IPv6 --> GRE/NAT */
- I40E_PTT(109, IP, IPV6, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3),
-
- /* IPv6 --> GRE/NAT -> IPv4 */
- I40E_PTT(110, IP, IPV6, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3),
- I40E_PTT(111, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3),
- I40E_PTT(112, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(113),
- I40E_PTT(114, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4),
- I40E_PTT(115, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4),
- I40E_PTT(116, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4),
-
- /* IPv6 --> GRE/NAT -> IPv6 */
- I40E_PTT(117, IP, IPV6, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3),
- I40E_PTT(118, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3),
- I40E_PTT(119, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(120),
- I40E_PTT(121, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4),
- I40E_PTT(122, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4),
- I40E_PTT(123, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4),
-
- /* IPv6 --> GRE/NAT -> MAC */
- I40E_PTT(124, IP, IPV6, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3),
-
- /* IPv6 --> GRE/NAT -> MAC -> IPv4 */
- I40E_PTT(125, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3),
- I40E_PTT(126, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3),
- I40E_PTT(127, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(128),
- I40E_PTT(129, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4),
- I40E_PTT(130, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4),
- I40E_PTT(131, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4),
-
- /* IPv6 --> GRE/NAT -> MAC -> IPv6 */
- I40E_PTT(132, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3),
- I40E_PTT(133, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3),
- I40E_PTT(134, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(135),
- I40E_PTT(136, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4),
- I40E_PTT(137, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4),
- I40E_PTT(138, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4),
-
- /* IPv6 --> GRE/NAT -> MAC/VLAN */
- I40E_PTT(139, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3),
-
- /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv4 */
- I40E_PTT(140, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3),
- I40E_PTT(141, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3),
- I40E_PTT(142, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(143),
- I40E_PTT(144, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4),
- I40E_PTT(145, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4),
- I40E_PTT(146, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4),
-
- /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv6 */
- I40E_PTT(147, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3),
- I40E_PTT(148, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3),
- I40E_PTT(149, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4),
- I40E_PTT_UNUSED_ENTRY(150),
- I40E_PTT(151, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4),
- I40E_PTT(152, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4),
- I40E_PTT(153, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4),
-
- /* unused entries */
- I40E_PTT_UNUSED_ENTRY(154),
- I40E_PTT_UNUSED_ENTRY(155),
- I40E_PTT_UNUSED_ENTRY(156),
- I40E_PTT_UNUSED_ENTRY(157),
- I40E_PTT_UNUSED_ENTRY(158),
- I40E_PTT_UNUSED_ENTRY(159),
-
- I40E_PTT_UNUSED_ENTRY(160),
- I40E_PTT_UNUSED_ENTRY(161),
- I40E_PTT_UNUSED_ENTRY(162),
- I40E_PTT_UNUSED_ENTRY(163),
- I40E_PTT_UNUSED_ENTRY(164),
- I40E_PTT_UNUSED_ENTRY(165),
- I40E_PTT_UNUSED_ENTRY(166),
- I40E_PTT_UNUSED_ENTRY(167),
- I40E_PTT_UNUSED_ENTRY(168),
- I40E_PTT_UNUSED_ENTRY(169),
-
- I40E_PTT_UNUSED_ENTRY(170),
- I40E_PTT_UNUSED_ENTRY(171),
- I40E_PTT_UNUSED_ENTRY(172),
- I40E_PTT_UNUSED_ENTRY(173),
- I40E_PTT_UNUSED_ENTRY(174),
- I40E_PTT_UNUSED_ENTRY(175),
- I40E_PTT_UNUSED_ENTRY(176),
- I40E_PTT_UNUSED_ENTRY(177),
- I40E_PTT_UNUSED_ENTRY(178),
- I40E_PTT_UNUSED_ENTRY(179),
-
- I40E_PTT_UNUSED_ENTRY(180),
- I40E_PTT_UNUSED_ENTRY(181),
- I40E_PTT_UNUSED_ENTRY(182),
- I40E_PTT_UNUSED_ENTRY(183),
- I40E_PTT_UNUSED_ENTRY(184),
- I40E_PTT_UNUSED_ENTRY(185),
- I40E_PTT_UNUSED_ENTRY(186),
- I40E_PTT_UNUSED_ENTRY(187),
- I40E_PTT_UNUSED_ENTRY(188),
- I40E_PTT_UNUSED_ENTRY(189),
-
- I40E_PTT_UNUSED_ENTRY(190),
- I40E_PTT_UNUSED_ENTRY(191),
- I40E_PTT_UNUSED_ENTRY(192),
- I40E_PTT_UNUSED_ENTRY(193),
- I40E_PTT_UNUSED_ENTRY(194),
- I40E_PTT_UNUSED_ENTRY(195),
- I40E_PTT_UNUSED_ENTRY(196),
- I40E_PTT_UNUSED_ENTRY(197),
- I40E_PTT_UNUSED_ENTRY(198),
- I40E_PTT_UNUSED_ENTRY(199),
-
- I40E_PTT_UNUSED_ENTRY(200),
- I40E_PTT_UNUSED_ENTRY(201),
- I40E_PTT_UNUSED_ENTRY(202),
- I40E_PTT_UNUSED_ENTRY(203),
- I40E_PTT_UNUSED_ENTRY(204),
- I40E_PTT_UNUSED_ENTRY(205),
- I40E_PTT_UNUSED_ENTRY(206),
- I40E_PTT_UNUSED_ENTRY(207),
- I40E_PTT_UNUSED_ENTRY(208),
- I40E_PTT_UNUSED_ENTRY(209),
-
- I40E_PTT_UNUSED_ENTRY(210),
- I40E_PTT_UNUSED_ENTRY(211),
- I40E_PTT_UNUSED_ENTRY(212),
- I40E_PTT_UNUSED_ENTRY(213),
- I40E_PTT_UNUSED_ENTRY(214),
- I40E_PTT_UNUSED_ENTRY(215),
- I40E_PTT_UNUSED_ENTRY(216),
- I40E_PTT_UNUSED_ENTRY(217),
- I40E_PTT_UNUSED_ENTRY(218),
- I40E_PTT_UNUSED_ENTRY(219),
-
- I40E_PTT_UNUSED_ENTRY(220),
- I40E_PTT_UNUSED_ENTRY(221),
- I40E_PTT_UNUSED_ENTRY(222),
- I40E_PTT_UNUSED_ENTRY(223),
- I40E_PTT_UNUSED_ENTRY(224),
- I40E_PTT_UNUSED_ENTRY(225),
- I40E_PTT_UNUSED_ENTRY(226),
- I40E_PTT_UNUSED_ENTRY(227),
- I40E_PTT_UNUSED_ENTRY(228),
- I40E_PTT_UNUSED_ENTRY(229),
-
- I40E_PTT_UNUSED_ENTRY(230),
- I40E_PTT_UNUSED_ENTRY(231),
- I40E_PTT_UNUSED_ENTRY(232),
- I40E_PTT_UNUSED_ENTRY(233),
- I40E_PTT_UNUSED_ENTRY(234),
- I40E_PTT_UNUSED_ENTRY(235),
- I40E_PTT_UNUSED_ENTRY(236),
- I40E_PTT_UNUSED_ENTRY(237),
- I40E_PTT_UNUSED_ENTRY(238),
- I40E_PTT_UNUSED_ENTRY(239),
-
- I40E_PTT_UNUSED_ENTRY(240),
- I40E_PTT_UNUSED_ENTRY(241),
- I40E_PTT_UNUSED_ENTRY(242),
- I40E_PTT_UNUSED_ENTRY(243),
- I40E_PTT_UNUSED_ENTRY(244),
- I40E_PTT_UNUSED_ENTRY(245),
- I40E_PTT_UNUSED_ENTRY(246),
- I40E_PTT_UNUSED_ENTRY(247),
- I40E_PTT_UNUSED_ENTRY(248),
- I40E_PTT_UNUSED_ENTRY(249),
-
- I40E_PTT_UNUSED_ENTRY(250),
- I40E_PTT_UNUSED_ENTRY(251),
- I40E_PTT_UNUSED_ENTRY(252),
- I40E_PTT_UNUSED_ENTRY(253),
- I40E_PTT_UNUSED_ENTRY(254),
- I40E_PTT_UNUSED_ENTRY(255)
-};
-
-/**
- * i40evf_aq_rx_ctl_read_register - use FW to read from an Rx control register
- * @hw: pointer to the hw struct
- * @reg_addr: register address
- * @reg_val: ptr to register value
- * @cmd_details: pointer to command details structure or NULL
- *
- * Use the firmware to read the Rx control register,
- * especially useful if the Rx unit is under heavy pressure
- **/
-i40e_status i40evf_aq_rx_ctl_read_register(struct i40e_hw *hw,
- u32 reg_addr, u32 *reg_val,
- struct i40e_asq_cmd_details *cmd_details)
-{
- struct i40e_aq_desc desc;
- struct i40e_aqc_rx_ctl_reg_read_write *cmd_resp =
- (struct i40e_aqc_rx_ctl_reg_read_write *)&desc.params.raw;
- i40e_status status;
-
- if (!reg_val)
- return I40E_ERR_PARAM;
-
- i40evf_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_rx_ctl_reg_read);
-
- cmd_resp->address = cpu_to_le32(reg_addr);
-
- status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
-
- if (status == 0)
- *reg_val = le32_to_cpu(cmd_resp->value);
-
- return status;
-}
-
-/**
- * i40evf_read_rx_ctl - read from an Rx control register
- * @hw: pointer to the hw struct
- * @reg_addr: register address
- **/
-u32 i40evf_read_rx_ctl(struct i40e_hw *hw, u32 reg_addr)
-{
- i40e_status status = 0;
- bool use_register;
- int retry = 5;
- u32 val = 0;
-
- use_register = (((hw->aq.api_maj_ver == 1) &&
- (hw->aq.api_min_ver < 5)) ||
- (hw->mac.type == I40E_MAC_X722));
- if (!use_register) {
-do_retry:
- status = i40evf_aq_rx_ctl_read_register(hw, reg_addr,
- &val, NULL);
- if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN && retry) {
- usleep_range(1000, 2000);
- retry--;
- goto do_retry;
- }
- }
-
- /* if the AQ access failed, try the old-fashioned way */
- if (status || use_register)
- val = rd32(hw, reg_addr);
-
- return val;
-}
-
-/**
- * i40evf_aq_rx_ctl_write_register
- * @hw: pointer to the hw struct
- * @reg_addr: register address
- * @reg_val: register value
- * @cmd_details: pointer to command details structure or NULL
- *
- * Use the firmware to write to an Rx control register,
- * especially useful if the Rx unit is under heavy pressure
- **/
-i40e_status i40evf_aq_rx_ctl_write_register(struct i40e_hw *hw,
- u32 reg_addr, u32 reg_val,
- struct i40e_asq_cmd_details *cmd_details)
-{
- struct i40e_aq_desc desc;
- struct i40e_aqc_rx_ctl_reg_read_write *cmd =
- (struct i40e_aqc_rx_ctl_reg_read_write *)&desc.params.raw;
- i40e_status status;
-
- i40evf_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_rx_ctl_reg_write);
-
- cmd->address = cpu_to_le32(reg_addr);
- cmd->value = cpu_to_le32(reg_val);
-
- status = i40evf_asq_send_command(hw, &desc, NULL, 0, cmd_details);
-
- return status;
-}
-
-/**
- * i40evf_write_rx_ctl - write to an Rx control register
- * @hw: pointer to the hw struct
- * @reg_addr: register address
- * @reg_val: register value
- **/
-void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val)
-{
- i40e_status status = 0;
- bool use_register;
- int retry = 5;
-
- use_register = (((hw->aq.api_maj_ver == 1) &&
- (hw->aq.api_min_ver < 5)) ||
- (hw->mac.type == I40E_MAC_X722));
- if (!use_register) {
-do_retry:
- status = i40evf_aq_rx_ctl_write_register(hw, reg_addr,
- reg_val, NULL);
- if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN && retry) {
- usleep_range(1000, 2000);
- retry--;
- goto do_retry;
- }
- }
-
- /* if the AQ access failed, try the old-fashioned way */
- if (status || use_register)
- wr32(hw, reg_addr, reg_val);
-}
-
-/**
- * i40e_aq_send_msg_to_pf
- * @hw: pointer to the hardware structure
- * @v_opcode: opcodes for VF-PF communication
- * @v_retval: return error code
- * @msg: pointer to the msg buffer
- * @msglen: msg length
- * @cmd_details: pointer to command details
- *
- * Send message to PF driver using admin queue. By default, this message
- * is sent asynchronously, i.e. i40evf_asq_send_command() does not wait for
- * completion before returning.
- **/
-i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
- enum virtchnl_ops v_opcode,
- i40e_status v_retval,
- u8 *msg, u16 msglen,
- struct i40e_asq_cmd_details *cmd_details)
-{
- struct i40e_aq_desc desc;
- struct i40e_asq_cmd_details details;
- i40e_status status;
-
- i40evf_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_send_msg_to_pf);
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_SI);
- desc.cookie_high = cpu_to_le32(v_opcode);
- desc.cookie_low = cpu_to_le32(v_retval);
- if (msglen) {
- desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF
- | I40E_AQ_FLAG_RD));
- if (msglen > I40E_AQ_LARGE_BUF)
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
- desc.datalen = cpu_to_le16(msglen);
- }
- if (!cmd_details) {
- memset(&details, 0, sizeof(details));
- details.async = true;
- cmd_details = &details;
- }
- status = i40evf_asq_send_command(hw, &desc, msg, msglen, cmd_details);
- return status;
-}
-
-/**
- * i40e_vf_parse_hw_config
- * @hw: pointer to the hardware structure
- * @msg: pointer to the virtual channel VF resource structure
- *
- * Given a VF resource message from the PF, populate the hw struct
- * with appropriate information.
- **/
-void i40e_vf_parse_hw_config(struct i40e_hw *hw,
- struct virtchnl_vf_resource *msg)
-{
- struct virtchnl_vsi_resource *vsi_res;
- int i;
-
- vsi_res = &msg->vsi_res[0];
-
- hw->dev_caps.num_vsis = msg->num_vsis;
- hw->dev_caps.num_rx_qp = msg->num_queue_pairs;
- hw->dev_caps.num_tx_qp = msg->num_queue_pairs;
- hw->dev_caps.num_msix_vectors_vf = msg->max_vectors;
- hw->dev_caps.dcb = msg->vf_cap_flags &
- VIRTCHNL_VF_OFFLOAD_L2;
- hw->dev_caps.fcoe = 0;
- for (i = 0; i < msg->num_vsis; i++) {
- if (vsi_res->vsi_type == VIRTCHNL_VSI_SRIOV) {
- ether_addr_copy(hw->mac.perm_addr,
- vsi_res->default_mac_addr);
- ether_addr_copy(hw->mac.addr,
- vsi_res->default_mac_addr);
- }
- vsi_res++;
- }
-}
-
-/**
- * i40e_vf_reset
- * @hw: pointer to the hardware structure
- *
- * Send a VF_RESET message to the PF. Does not wait for response from PF
- * as none will be forthcoming. Immediately after calling this function,
- * the admin queue should be shut down and (optionally) reinitialized.
- **/
-i40e_status i40e_vf_reset(struct i40e_hw *hw)
-{
- return i40e_aq_send_msg_to_pf(hw, VIRTCHNL_OP_RESET_VF,
- 0, NULL, 0, NULL);
-}
-
-/**
- * i40evf_aq_write_ddp - Write dynamic device personalization (ddp)
- * @hw: pointer to the hw struct
- * @buff: command buffer (size in bytes = buff_size)
- * @buff_size: buffer size in bytes
- * @track_id: package tracking id
- * @error_offset: returns error offset
- * @error_info: returns error information
- * @cmd_details: pointer to command details structure or NULL
- **/
-enum
-i40e_status_code i40evf_aq_write_ddp(struct i40e_hw *hw, void *buff,
- u16 buff_size, u32 track_id,
- u32 *error_offset, u32 *error_info,
- struct i40e_asq_cmd_details *cmd_details)
-{
- struct i40e_aq_desc desc;
- struct i40e_aqc_write_personalization_profile *cmd =
- (struct i40e_aqc_write_personalization_profile *)
- &desc.params.raw;
- struct i40e_aqc_write_ddp_resp *resp;
- i40e_status status;
-
- i40evf_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_write_personalization_profile);
-
- desc.flags |= cpu_to_le16(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD);
- if (buff_size > I40E_AQ_LARGE_BUF)
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
-
- desc.datalen = cpu_to_le16(buff_size);
-
- cmd->profile_track_id = cpu_to_le32(track_id);
-
- status = i40evf_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
- if (!status) {
- resp = (struct i40e_aqc_write_ddp_resp *)&desc.params.raw;
- if (error_offset)
- *error_offset = le32_to_cpu(resp->error_offset);
- if (error_info)
- *error_info = le32_to_cpu(resp->error_info);
- }
-
- return status;
-}
-
-/**
- * i40evf_aq_get_ddp_list - Read dynamic device personalization (ddp)
- * @hw: pointer to the hw struct
- * @buff: command buffer (size in bytes = buff_size)
- * @buff_size: buffer size in bytes
- * @flags: AdminQ command flags
- * @cmd_details: pointer to command details structure or NULL
- **/
-enum
-i40e_status_code i40evf_aq_get_ddp_list(struct i40e_hw *hw, void *buff,
- u16 buff_size, u8 flags,
- struct i40e_asq_cmd_details *cmd_details)
-{
- struct i40e_aq_desc desc;
- struct i40e_aqc_get_applied_profiles *cmd =
- (struct i40e_aqc_get_applied_profiles *)&desc.params.raw;
- i40e_status status;
-
- i40evf_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_get_personalization_profile_list);
-
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
- if (buff_size > I40E_AQ_LARGE_BUF)
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
- desc.datalen = cpu_to_le16(buff_size);
-
- cmd->flags = flags;
-
- status = i40evf_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
-
- return status;
-}
-
-/**
- * i40evf_find_segment_in_package
- * @segment_type: the segment type to search for (i.e., SEGMENT_TYPE_I40E)
- * @pkg_hdr: pointer to the package header to be searched
- *
- * This function searches a package file for a particular segment type. On
- * success it returns a pointer to the segment header, otherwise it will
- * return NULL.
- **/
-struct i40e_generic_seg_header *
-i40evf_find_segment_in_package(u32 segment_type,
- struct i40e_package_header *pkg_hdr)
-{
- struct i40e_generic_seg_header *segment;
- u32 i;
-
- /* Search all package segments for the requested segment type */
- for (i = 0; i < pkg_hdr->segment_count; i++) {
- segment =
- (struct i40e_generic_seg_header *)((u8 *)pkg_hdr +
- pkg_hdr->segment_offset[i]);
-
- if (segment->type == segment_type)
- return segment;
- }
-
- return NULL;
-}
-
-/**
- * i40evf_write_profile
- * @hw: pointer to the hardware structure
- * @profile: pointer to the profile segment of the package to be downloaded
- * @track_id: package tracking id
- *
- * Handles the download of a complete package.
- */
-enum i40e_status_code
-i40evf_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile,
- u32 track_id)
-{
- i40e_status status = 0;
- struct i40e_section_table *sec_tbl;
- struct i40e_profile_section_header *sec = NULL;
- u32 dev_cnt;
- u32 vendor_dev_id;
- u32 *nvm;
- u32 section_size = 0;
- u32 offset = 0, info = 0;
- u32 i;
-
- dev_cnt = profile->device_table_count;
-
- for (i = 0; i < dev_cnt; i++) {
- vendor_dev_id = profile->device_table[i].vendor_dev_id;
- if ((vendor_dev_id >> 16) == PCI_VENDOR_ID_INTEL)
- if (hw->device_id == (vendor_dev_id & 0xFFFF))
- break;
- }
- if (i == dev_cnt) {
- i40e_debug(hw, I40E_DEBUG_PACKAGE, "Device doesn't support DDP");
- return I40E_ERR_DEVICE_NOT_SUPPORTED;
- }
-
- nvm = (u32 *)&profile->device_table[dev_cnt];
- sec_tbl = (struct i40e_section_table *)&nvm[nvm[0] + 1];
-
- for (i = 0; i < sec_tbl->section_count; i++) {
- sec = (struct i40e_profile_section_header *)((u8 *)profile +
- sec_tbl->section_offset[i]);
-
- /* Skip 'AQ', 'note' and 'name' sections */
- if (sec->section.type != SECTION_TYPE_MMIO)
- continue;
-
- section_size = sec->section.size +
- sizeof(struct i40e_profile_section_header);
-
- /* Write profile */
- status = i40evf_aq_write_ddp(hw, (void *)sec, (u16)section_size,
- track_id, &offset, &info, NULL);
- if (status) {
- i40e_debug(hw, I40E_DEBUG_PACKAGE,
- "Failed to write profile: offset %d, info %d",
- offset, info);
- break;
- }
- }
- return status;
-}
-
-/**
- * i40evf_add_pinfo_to_list
- * @hw: pointer to the hardware structure
- * @profile: pointer to the profile segment of the package
- * @profile_info_sec: buffer for information section
- * @track_id: package tracking id
- *
- * Register a profile to the list of loaded profiles.
- */
-enum i40e_status_code
-i40evf_add_pinfo_to_list(struct i40e_hw *hw,
- struct i40e_profile_segment *profile,
- u8 *profile_info_sec, u32 track_id)
-{
- i40e_status status = 0;
- struct i40e_profile_section_header *sec = NULL;
- struct i40e_profile_info *pinfo;
- u32 offset = 0, info = 0;
-
- sec = (struct i40e_profile_section_header *)profile_info_sec;
- sec->tbl_size = 1;
- sec->data_end = sizeof(struct i40e_profile_section_header) +
- sizeof(struct i40e_profile_info);
- sec->section.type = SECTION_TYPE_INFO;
- sec->section.offset = sizeof(struct i40e_profile_section_header);
- sec->section.size = sizeof(struct i40e_profile_info);
- pinfo = (struct i40e_profile_info *)(profile_info_sec +
- sec->section.offset);
- pinfo->track_id = track_id;
- pinfo->version = profile->version;
- pinfo->op = I40E_DDP_ADD_TRACKID;
- memcpy(pinfo->name, profile->name, I40E_DDP_NAME_SIZE);
-
- status = i40evf_aq_write_ddp(hw, (void *)sec, sec->data_end,
- track_id, &offset, &info, NULL);
- return status;
-}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_devids.h b/drivers/net/ethernet/intel/i40evf/i40e_devids.h
deleted file mode 100644
index f300bf271824..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_devids.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_DEVIDS_H_
-#define _I40E_DEVIDS_H_
-
-/* Device IDs */
-#define I40E_DEV_ID_SFP_XL710 0x1572
-#define I40E_DEV_ID_QEMU 0x1574
-#define I40E_DEV_ID_KX_B 0x1580
-#define I40E_DEV_ID_KX_C 0x1581
-#define I40E_DEV_ID_QSFP_A 0x1583
-#define I40E_DEV_ID_QSFP_B 0x1584
-#define I40E_DEV_ID_QSFP_C 0x1585
-#define I40E_DEV_ID_10G_BASE_T 0x1586
-#define I40E_DEV_ID_20G_KR2 0x1587
-#define I40E_DEV_ID_20G_KR2_A 0x1588
-#define I40E_DEV_ID_10G_BASE_T4 0x1589
-#define I40E_DEV_ID_25G_B 0x158A
-#define I40E_DEV_ID_25G_SFP28 0x158B
-#define I40E_DEV_ID_VF 0x154C
-#define I40E_DEV_ID_VF_HV 0x1571
-#define I40E_DEV_ID_ADAPTIVE_VF 0x1889
-#define I40E_DEV_ID_SFP_X722 0x37D0
-#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1
-#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2
-#define I40E_DEV_ID_SFP_I_X722 0x37D3
-#define I40E_DEV_ID_X722_VF 0x37CD
-
-#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \
- (d) == I40E_DEV_ID_QSFP_B || \
- (d) == I40E_DEV_ID_QSFP_C)
-
-#endif /* _I40E_DEVIDS_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_hmc.h b/drivers/net/ethernet/intel/i40evf/i40e_hmc.h
deleted file mode 100644
index 1c78de838857..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_hmc.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_HMC_H_
-#define _I40E_HMC_H_
-
-#define I40E_HMC_MAX_BP_COUNT 512
-
-/* forward-declare the HW struct for the compiler */
-struct i40e_hw;
-
-#define I40E_HMC_INFO_SIGNATURE 0x484D5347 /* HMSG */
-#define I40E_HMC_PD_CNT_IN_SD 512
-#define I40E_HMC_DIRECT_BP_SIZE 0x200000 /* 2M */
-#define I40E_HMC_PAGED_BP_SIZE 4096
-#define I40E_HMC_PD_BP_BUF_ALIGNMENT 4096
-#define I40E_FIRST_VF_FPM_ID 16
-
-struct i40e_hmc_obj_info {
- u64 base; /* base addr in FPM */
- u32 max_cnt; /* max count available for this hmc func */
- u32 cnt; /* count of objects driver actually wants to create */
- u64 size; /* size in bytes of one object */
-};
-
-enum i40e_sd_entry_type {
- I40E_SD_TYPE_INVALID = 0,
- I40E_SD_TYPE_PAGED = 1,
- I40E_SD_TYPE_DIRECT = 2
-};
-
-struct i40e_hmc_bp {
- enum i40e_sd_entry_type entry_type;
- struct i40e_dma_mem addr; /* populate to be used by hw */
- u32 sd_pd_index;
- u32 ref_cnt;
-};
-
-struct i40e_hmc_pd_entry {
- struct i40e_hmc_bp bp;
- u32 sd_index;
- bool rsrc_pg;
- bool valid;
-};
-
-struct i40e_hmc_pd_table {
- struct i40e_dma_mem pd_page_addr; /* populate to be used by hw */
- struct i40e_hmc_pd_entry *pd_entry; /* [512] for sw book keeping */
- struct i40e_virt_mem pd_entry_virt_mem; /* virt mem for pd_entry */
-
- u32 ref_cnt;
- u32 sd_index;
-};
-
-struct i40e_hmc_sd_entry {
- enum i40e_sd_entry_type entry_type;
- bool valid;
-
- union {
- struct i40e_hmc_pd_table pd_table;
- struct i40e_hmc_bp bp;
- } u;
-};
-
-struct i40e_hmc_sd_table {
- struct i40e_virt_mem addr; /* used to track sd_entry allocations */
- u32 sd_cnt;
- u32 ref_cnt;
- struct i40e_hmc_sd_entry *sd_entry; /* (sd_cnt*512) entries max */
-};
-
-struct i40e_hmc_info {
- u32 signature;
- /* equals to pci func num for PF and dynamically allocated for VFs */
- u8 hmc_fn_id;
- u16 first_sd_index; /* index of the first available SD */
-
- /* hmc objects */
- struct i40e_hmc_obj_info *hmc_obj;
- struct i40e_virt_mem hmc_obj_virt_mem;
- struct i40e_hmc_sd_table sd_table;
-};
-
-#define I40E_INC_SD_REFCNT(sd_table) ((sd_table)->ref_cnt++)
-#define I40E_INC_PD_REFCNT(pd_table) ((pd_table)->ref_cnt++)
-#define I40E_INC_BP_REFCNT(bp) ((bp)->ref_cnt++)
-
-#define I40E_DEC_SD_REFCNT(sd_table) ((sd_table)->ref_cnt--)
-#define I40E_DEC_PD_REFCNT(pd_table) ((pd_table)->ref_cnt--)
-#define I40E_DEC_BP_REFCNT(bp) ((bp)->ref_cnt--)
-
-/**
- * I40E_SET_PF_SD_ENTRY - marks the sd entry as valid in the hardware
- * @hw: pointer to our hw struct
- * @pa: pointer to physical address
- * @sd_index: segment descriptor index
- * @type: if sd entry is direct or paged
- **/
-#define I40E_SET_PF_SD_ENTRY(hw, pa, sd_index, type) \
-{ \
- u32 val1, val2, val3; \
- val1 = (u32)(upper_32_bits(pa)); \
- val2 = (u32)(pa) | (I40E_HMC_MAX_BP_COUNT << \
- I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \
- ((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
- I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) | \
- BIT(I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT); \
- val3 = (sd_index) | BIT_ULL(I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
- wr32((hw), I40E_PFHMC_SDDATAHIGH, val1); \
- wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
- wr32((hw), I40E_PFHMC_SDCMD, val3); \
-}
-
-/**
- * I40E_CLEAR_PF_SD_ENTRY - marks the sd entry as invalid in the hardware
- * @hw: pointer to our hw struct
- * @sd_index: segment descriptor index
- * @type: if sd entry is direct or paged
- **/
-#define I40E_CLEAR_PF_SD_ENTRY(hw, sd_index, type) \
-{ \
- u32 val2, val3; \
- val2 = (I40E_HMC_MAX_BP_COUNT << \
- I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \
- ((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
- I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT); \
- val3 = (sd_index) | BIT_ULL(I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
- wr32((hw), I40E_PFHMC_SDDATAHIGH, 0); \
- wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
- wr32((hw), I40E_PFHMC_SDCMD, val3); \
-}
-
-/**
- * I40E_INVALIDATE_PF_HMC_PD - Invalidates the pd cache in the hardware
- * @hw: pointer to our hw struct
- * @sd_idx: segment descriptor index
- * @pd_idx: page descriptor index
- **/
-#define I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, pd_idx) \
- wr32((hw), I40E_PFHMC_PDINV, \
- (((sd_idx) << I40E_PFHMC_PDINV_PMSDIDX_SHIFT) | \
- ((pd_idx) << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)))
-
-/**
- * I40E_FIND_SD_INDEX_LIMIT - finds segment descriptor index limit
- * @hmc_info: pointer to the HMC configuration information structure
- * @type: type of HMC resources we're searching
- * @index: starting index for the object
- * @cnt: number of objects we're trying to create
- * @sd_idx: pointer to return index of the segment descriptor in question
- * @sd_limit: pointer to return the maximum number of segment descriptors
- *
- * This function calculates the segment descriptor index and index limit
- * for the resource defined by i40e_hmc_rsrc_type.
- **/
-#define I40E_FIND_SD_INDEX_LIMIT(hmc_info, type, index, cnt, sd_idx, sd_limit)\
-{ \
- u64 fpm_addr, fpm_limit; \
- fpm_addr = (hmc_info)->hmc_obj[(type)].base + \
- (hmc_info)->hmc_obj[(type)].size * (index); \
- fpm_limit = fpm_addr + (hmc_info)->hmc_obj[(type)].size * (cnt);\
- *(sd_idx) = (u32)(fpm_addr / I40E_HMC_DIRECT_BP_SIZE); \
- *(sd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_DIRECT_BP_SIZE); \
- /* add one more to the limit to correct our range */ \
- *(sd_limit) += 1; \
-}
-
-/**
- * I40E_FIND_PD_INDEX_LIMIT - finds page descriptor index limit
- * @hmc_info: pointer to the HMC configuration information struct
- * @type: HMC resource type we're examining
- * @idx: starting index for the object
- * @cnt: number of objects we're trying to create
- * @pd_index: pointer to return page descriptor index
- * @pd_limit: pointer to return page descriptor index limit
- *
- * Calculates the page descriptor index and index limit for the resource
- * defined by i40e_hmc_rsrc_type.
- **/
-#define I40E_FIND_PD_INDEX_LIMIT(hmc_info, type, idx, cnt, pd_index, pd_limit)\
-{ \
- u64 fpm_adr, fpm_limit; \
- fpm_adr = (hmc_info)->hmc_obj[(type)].base + \
- (hmc_info)->hmc_obj[(type)].size * (idx); \
- fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt); \
- *(pd_index) = (u32)(fpm_adr / I40E_HMC_PAGED_BP_SIZE); \
- *(pd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_PAGED_BP_SIZE); \
- /* add one more to the limit to correct our range */ \
- *(pd_limit) += 1; \
-}
-i40e_status i40e_add_sd_table_entry(struct i40e_hw *hw,
- struct i40e_hmc_info *hmc_info,
- u32 sd_index,
- enum i40e_sd_entry_type type,
- u64 direct_mode_sz);
-
-i40e_status i40e_add_pd_table_entry(struct i40e_hw *hw,
- struct i40e_hmc_info *hmc_info,
- u32 pd_index,
- struct i40e_dma_mem *rsrc_pg);
-i40e_status i40e_remove_pd_bp(struct i40e_hw *hw,
- struct i40e_hmc_info *hmc_info,
- u32 idx);
-i40e_status i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info,
- u32 idx);
-i40e_status i40e_remove_sd_bp_new(struct i40e_hw *hw,
- struct i40e_hmc_info *hmc_info,
- u32 idx, bool is_pf);
-i40e_status i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info,
- u32 idx);
-i40e_status i40e_remove_pd_page_new(struct i40e_hw *hw,
- struct i40e_hmc_info *hmc_info,
- u32 idx, bool is_pf);
-
-#endif /* _I40E_HMC_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h b/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h
deleted file mode 100644
index 82b00f70a632..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_LAN_HMC_H_
-#define _I40E_LAN_HMC_H_
-
-/* forward-declare the HW struct for the compiler */
-struct i40e_hw;
-
-/* HMC element context information */
-
-/* Rx queue context data
- *
- * The sizes of the variables may be larger than needed due to crossing byte
- * boundaries. If we do not have the width of the variable set to the correct
- * size then we could end up shifting bits off the top of the variable when the
- * variable is at the top of a byte and crosses over into the next byte.
- */
-struct i40e_hmc_obj_rxq {
- u16 head;
- u16 cpuid; /* bigger than needed, see above for reason */
- u64 base;
- u16 qlen;
-#define I40E_RXQ_CTX_DBUFF_SHIFT 7
- u16 dbuff; /* bigger than needed, see above for reason */
-#define I40E_RXQ_CTX_HBUFF_SHIFT 6
- u16 hbuff; /* bigger than needed, see above for reason */
- u8 dtype;
- u8 dsize;
- u8 crcstrip;
- u8 fc_ena;
- u8 l2tsel;
- u8 hsplit_0;
- u8 hsplit_1;
- u8 showiv;
- u32 rxmax; /* bigger than needed, see above for reason */
- u8 tphrdesc_ena;
- u8 tphwdesc_ena;
- u8 tphdata_ena;
- u8 tphhead_ena;
- u16 lrxqthresh; /* bigger than needed, see above for reason */
- u8 prefena; /* NOTE: normally must be set to 1 at init */
-};
-
-/* Tx queue context data
-*
-* The sizes of the variables may be larger than needed due to crossing byte
-* boundaries. If we do not have the width of the variable set to the correct
-* size then we could end up shifting bits off the top of the variable when the
-* variable is at the top of a byte and crosses over into the next byte.
-*/
-struct i40e_hmc_obj_txq {
- u16 head;
- u8 new_context;
- u64 base;
- u8 fc_ena;
- u8 timesync_ena;
- u8 fd_ena;
- u8 alt_vlan_ena;
- u16 thead_wb;
- u8 cpuid;
- u8 head_wb_ena;
- u16 qlen;
- u8 tphrdesc_ena;
- u8 tphrpacket_ena;
- u8 tphwdesc_ena;
- u64 head_wb_addr;
- u32 crc;
- u16 rdylist;
- u8 rdylist_act;
-};
-
-/* for hsplit_0 field of Rx HMC context */
-enum i40e_hmc_obj_rx_hsplit_0 {
- I40E_HMC_OBJ_RX_HSPLIT_0_NO_SPLIT = 0,
- I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_L2 = 1,
- I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_IP = 2,
- I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_TCP_UDP = 4,
- I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_SCTP = 8,
-};
-
-/* fcoe_cntx and fcoe_filt are for debugging purpose only */
-struct i40e_hmc_obj_fcoe_cntx {
- u32 rsv[32];
-};
-
-struct i40e_hmc_obj_fcoe_filt {
- u32 rsv[8];
-};
-
-/* Context sizes for LAN objects */
-enum i40e_hmc_lan_object_size {
- I40E_HMC_LAN_OBJ_SZ_8 = 0x3,
- I40E_HMC_LAN_OBJ_SZ_16 = 0x4,
- I40E_HMC_LAN_OBJ_SZ_32 = 0x5,
- I40E_HMC_LAN_OBJ_SZ_64 = 0x6,
- I40E_HMC_LAN_OBJ_SZ_128 = 0x7,
- I40E_HMC_LAN_OBJ_SZ_256 = 0x8,
- I40E_HMC_LAN_OBJ_SZ_512 = 0x9,
-};
-
-#define I40E_HMC_L2OBJ_BASE_ALIGNMENT 512
-#define I40E_HMC_OBJ_SIZE_TXQ 128
-#define I40E_HMC_OBJ_SIZE_RXQ 32
-#define I40E_HMC_OBJ_SIZE_FCOE_CNTX 128
-#define I40E_HMC_OBJ_SIZE_FCOE_FILT 64
-
-enum i40e_hmc_lan_rsrc_type {
- I40E_HMC_LAN_FULL = 0,
- I40E_HMC_LAN_TX = 1,
- I40E_HMC_LAN_RX = 2,
- I40E_HMC_FCOE_CTX = 3,
- I40E_HMC_FCOE_FILT = 4,
- I40E_HMC_LAN_MAX = 5
-};
-
-enum i40e_hmc_model {
- I40E_HMC_MODEL_DIRECT_PREFERRED = 0,
- I40E_HMC_MODEL_DIRECT_ONLY = 1,
- I40E_HMC_MODEL_PAGED_ONLY = 2,
- I40E_HMC_MODEL_UNKNOWN,
-};
-
-struct i40e_hmc_lan_create_obj_info {
- struct i40e_hmc_info *hmc_info;
- u32 rsrc_type;
- u32 start_idx;
- u32 count;
- enum i40e_sd_entry_type entry_type;
- u64 direct_mode_sz;
-};
-
-struct i40e_hmc_lan_delete_obj_info {
- struct i40e_hmc_info *hmc_info;
- u32 rsrc_type;
- u32 start_idx;
- u32 count;
-};
-
-i40e_status i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num,
- u32 rxq_num, u32 fcoe_cntx_num,
- u32 fcoe_filt_num);
-i40e_status i40e_configure_lan_hmc(struct i40e_hw *hw,
- enum i40e_hmc_model model);
-i40e_status i40e_shutdown_lan_hmc(struct i40e_hw *hw);
-
-i40e_status i40e_clear_lan_tx_queue_context(struct i40e_hw *hw,
- u16 queue);
-i40e_status i40e_set_lan_tx_queue_context(struct i40e_hw *hw,
- u16 queue,
- struct i40e_hmc_obj_txq *s);
-i40e_status i40e_clear_lan_rx_queue_context(struct i40e_hw *hw,
- u16 queue);
-i40e_status i40e_set_lan_rx_queue_context(struct i40e_hw *hw,
- u16 queue,
- struct i40e_hmc_obj_rxq *s);
-
-#endif /* _I40E_LAN_HMC_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h
deleted file mode 100644
index 3ddddb46455b..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_OSDEP_H_
-#define _I40E_OSDEP_H_
-
-#include <linux/types.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/tcp.h>
-#include <linux/pci.h>
-
-/* get readq/writeq support for 32 bit kernels, use the low-first version */
-#include <linux/io-64-nonatomic-lo-hi.h>
-
-/* File to be the magic between shared code and
- * actual OS primitives
- */
-
-#define hw_dbg(hw, S, A...) do {} while (0)
-
-#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
-#define rd32(a, reg) readl((a)->hw_addr + (reg))
-
-#define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg)))
-#define rd64(a, reg) readq((a)->hw_addr + (reg))
-#define i40e_flush(a) readl((a)->hw_addr + I40E_VFGEN_RSTAT)
-
-/* memory allocation tracking */
-struct i40e_dma_mem {
- void *va;
- dma_addr_t pa;
- u32 size;
-};
-
-#define i40e_allocate_dma_mem(h, m, unused, s, a) \
- i40evf_allocate_dma_mem_d(h, m, s, a)
-#define i40e_free_dma_mem(h, m) i40evf_free_dma_mem_d(h, m)
-
-struct i40e_virt_mem {
- void *va;
- u32 size;
-};
-#define i40e_allocate_virt_mem(h, m, s) i40evf_allocate_virt_mem_d(h, m, s)
-#define i40e_free_virt_mem(h, m) i40evf_free_virt_mem_d(h, m)
-
-#define i40e_debug(h, m, s, ...) i40evf_debug_d(h, m, s, ##__VA_ARGS__)
-extern void i40evf_debug_d(void *hw, u32 mask, char *fmt_str, ...)
- __attribute__ ((format(gnu_printf, 3, 4)));
-
-typedef enum i40e_status_code i40e_status;
-#endif /* _I40E_OSDEP_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
deleted file mode 100644
index a358f4b9d5aa..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_PROTOTYPE_H_
-#define _I40E_PROTOTYPE_H_
-
-#include "i40e_type.h"
-#include "i40e_alloc.h"
-#include <linux/avf/virtchnl.h>
-
-/* Prototypes for shared code functions that are not in
- * the standard function pointer structures. These are
- * mostly because they are needed even before the init
- * has happened and will assist in the early SW and FW
- * setup.
- */
-
-/* adminq functions */
-i40e_status i40evf_init_adminq(struct i40e_hw *hw);
-i40e_status i40evf_shutdown_adminq(struct i40e_hw *hw);
-void i40e_adminq_init_ring_data(struct i40e_hw *hw);
-i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
- struct i40e_arq_event_info *e,
- u16 *events_pending);
-i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
- struct i40e_aq_desc *desc,
- void *buff, /* can be NULL */
- u16 buff_size,
- struct i40e_asq_cmd_details *cmd_details);
-bool i40evf_asq_done(struct i40e_hw *hw);
-
-/* debug function for adminq */
-void i40evf_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask,
- void *desc, void *buffer, u16 buf_len);
-
-void i40e_idle_aq(struct i40e_hw *hw);
-void i40evf_resume_aq(struct i40e_hw *hw);
-bool i40evf_check_asq_alive(struct i40e_hw *hw);
-i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw, bool unloading);
-const char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err);
-const char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err);
-
-i40e_status i40evf_aq_get_rss_lut(struct i40e_hw *hw, u16 seid,
- bool pf_lut, u8 *lut, u16 lut_size);
-i40e_status i40evf_aq_set_rss_lut(struct i40e_hw *hw, u16 seid,
- bool pf_lut, u8 *lut, u16 lut_size);
-i40e_status i40evf_aq_get_rss_key(struct i40e_hw *hw,
- u16 seid,
- struct i40e_aqc_get_set_rss_key_data *key);
-i40e_status i40evf_aq_set_rss_key(struct i40e_hw *hw,
- u16 seid,
- struct i40e_aqc_get_set_rss_key_data *key);
-
-i40e_status i40e_set_mac_type(struct i40e_hw *hw);
-
-extern struct i40e_rx_ptype_decoded i40evf_ptype_lookup[];
-
-static inline struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
-{
- return i40evf_ptype_lookup[ptype];
-}
-
-/* prototype for functions used for SW locks */
-
-/* i40e_common for VF drivers*/
-void i40e_vf_parse_hw_config(struct i40e_hw *hw,
- struct virtchnl_vf_resource *msg);
-i40e_status i40e_vf_reset(struct i40e_hw *hw);
-i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
- enum virtchnl_ops v_opcode,
- i40e_status v_retval,
- u8 *msg, u16 msglen,
- struct i40e_asq_cmd_details *cmd_details);
-i40e_status i40e_set_filter_control(struct i40e_hw *hw,
- struct i40e_filter_control_settings *settings);
-i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
- u8 *mac_addr, u16 ethtype, u16 flags,
- u16 vsi_seid, u16 queue, bool is_add,
- struct i40e_control_filter_stats *stats,
- struct i40e_asq_cmd_details *cmd_details);
-void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw,
- u16 vsi_seid);
-i40e_status i40evf_aq_rx_ctl_read_register(struct i40e_hw *hw,
- u32 reg_addr, u32 *reg_val,
- struct i40e_asq_cmd_details *cmd_details);
-u32 i40evf_read_rx_ctl(struct i40e_hw *hw, u32 reg_addr);
-i40e_status i40evf_aq_rx_ctl_write_register(struct i40e_hw *hw,
- u32 reg_addr, u32 reg_val,
- struct i40e_asq_cmd_details *cmd_details);
-void i40evf_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
-i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw,
- u8 phy_select, u8 dev_addr,
- u32 reg_addr, u32 reg_val,
- struct i40e_asq_cmd_details *cmd_details);
-i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw,
- u8 phy_select, u8 dev_addr,
- u32 reg_addr, u32 *reg_val,
- struct i40e_asq_cmd_details *cmd_details);
-
-i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
- u16 reg, u8 phy_addr, u16 *value);
-i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
- u16 reg, u8 phy_addr, u16 value);
-i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
- u8 phy_addr, u16 *value);
-i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
- u8 phy_addr, u16 value);
-u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
-i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
- u32 time, u32 interval);
-i40e_status i40evf_aq_write_ddp(struct i40e_hw *hw, void *buff,
- u16 buff_size, u32 track_id,
- u32 *error_offset, u32 *error_info,
- struct i40e_asq_cmd_details *
- cmd_details);
-i40e_status i40evf_aq_get_ddp_list(struct i40e_hw *hw, void *buff,
- u16 buff_size, u8 flags,
- struct i40e_asq_cmd_details *
- cmd_details);
-struct i40e_generic_seg_header *
-i40evf_find_segment_in_package(u32 segment_type,
- struct i40e_package_header *pkg_header);
-enum i40e_status_code
-i40evf_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg,
- u32 track_id);
-enum i40e_status_code
-i40evf_add_pinfo_to_list(struct i40e_hw *hw,
- struct i40e_profile_segment *profile,
- u8 *profile_info_sec, u32 track_id);
-#endif /* _I40E_PROTOTYPE_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_register.h b/drivers/net/ethernet/intel/i40evf/i40e_register.h
deleted file mode 100644
index 49e1f57d99cc..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_register.h
+++ /dev/null
@@ -1,313 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_REGISTER_H_
-#define _I40E_REGISTER_H_
-
-#define I40E_VFMSIX_PBA1(_i) (0x00002000 + ((_i) * 4)) /* _i=0...19 */ /* Reset: VFLR */
-#define I40E_VFMSIX_PBA1_MAX_INDEX 19
-#define I40E_VFMSIX_PBA1_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA1_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA1_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
-#define I40E_VFMSIX_TADD1_MAX_INDEX 639
-#define I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
-#define I40E_VFMSIX_TADD1_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD1_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
-#define I40E_VFMSIX_TMSG1_MAX_INDEX 639
-#define I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
-#define I40E_VFMSIX_TUADD1_MAX_INDEX 639
-#define I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
-#define I40E_VFMSIX_TVCTRL1_MAX_INDEX 639
-#define I40E_VFMSIX_TVCTRL1_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL1_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
-#define I40E_VF_ARQBAH1 0x00006000 /* Reset: EMPR */
-#define I40E_VF_ARQBAH1_ARQBAH_SHIFT 0
-#define I40E_VF_ARQBAH1_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH1_ARQBAH_SHIFT)
-#define I40E_VF_ARQBAL1 0x00006C00 /* Reset: EMPR */
-#define I40E_VF_ARQBAL1_ARQBAL_SHIFT 0
-#define I40E_VF_ARQBAL1_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL1_ARQBAL_SHIFT)
-#define I40E_VF_ARQH1 0x00007400 /* Reset: EMPR */
-#define I40E_VF_ARQH1_ARQH_SHIFT 0
-#define I40E_VF_ARQH1_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH1_ARQH_SHIFT)
-#define I40E_VF_ARQLEN1 0x00008000 /* Reset: EMPR */
-#define I40E_VF_ARQLEN1_ARQLEN_SHIFT 0
-#define I40E_VF_ARQLEN1_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN1_ARQLEN_SHIFT)
-#define I40E_VF_ARQLEN1_ARQVFE_SHIFT 28
-#define I40E_VF_ARQLEN1_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQVFE_SHIFT)
-#define I40E_VF_ARQLEN1_ARQOVFL_SHIFT 29
-#define I40E_VF_ARQLEN1_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
-#define I40E_VF_ARQLEN1_ARQCRIT_SHIFT 30
-#define I40E_VF_ARQLEN1_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
-#define I40E_VF_ARQLEN1_ARQENABLE_SHIFT 31
-#define I40E_VF_ARQLEN1_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
-#define I40E_VF_ARQT1 0x00007000 /* Reset: EMPR */
-#define I40E_VF_ARQT1_ARQT_SHIFT 0
-#define I40E_VF_ARQT1_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT1_ARQT_SHIFT)
-#define I40E_VF_ATQBAH1 0x00007800 /* Reset: EMPR */
-#define I40E_VF_ATQBAH1_ATQBAH_SHIFT 0
-#define I40E_VF_ATQBAH1_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH1_ATQBAH_SHIFT)
-#define I40E_VF_ATQBAL1 0x00007C00 /* Reset: EMPR */
-#define I40E_VF_ATQBAL1_ATQBAL_SHIFT 0
-#define I40E_VF_ATQBAL1_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL1_ATQBAL_SHIFT)
-#define I40E_VF_ATQH1 0x00006400 /* Reset: EMPR */
-#define I40E_VF_ATQH1_ATQH_SHIFT 0
-#define I40E_VF_ATQH1_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH1_ATQH_SHIFT)
-#define I40E_VF_ATQLEN1 0x00006800 /* Reset: EMPR */
-#define I40E_VF_ATQLEN1_ATQLEN_SHIFT 0
-#define I40E_VF_ATQLEN1_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN1_ATQLEN_SHIFT)
-#define I40E_VF_ATQLEN1_ATQVFE_SHIFT 28
-#define I40E_VF_ATQLEN1_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQVFE_SHIFT)
-#define I40E_VF_ATQLEN1_ATQOVFL_SHIFT 29
-#define I40E_VF_ATQLEN1_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
-#define I40E_VF_ATQLEN1_ATQCRIT_SHIFT 30
-#define I40E_VF_ATQLEN1_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
-#define I40E_VF_ATQLEN1_ATQENABLE_SHIFT 31
-#define I40E_VF_ATQLEN1_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
-#define I40E_VF_ATQT1 0x00008400 /* Reset: EMPR */
-#define I40E_VF_ATQT1_ATQT_SHIFT 0
-#define I40E_VF_ATQT1_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT1_ATQT_SHIFT)
-#define I40E_VFGEN_RSTAT 0x00008800 /* Reset: VFR */
-#define I40E_VFGEN_RSTAT_VFR_STATE_SHIFT 0
-#define I40E_VFGEN_RSTAT_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
-#define I40E_VFINT_DYN_CTL01 0x00005C00 /* Reset: VFR */
-#define I40E_VFINT_DYN_CTL01_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTL01_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
-#define I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
-#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
-#define I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
-#define I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
-#define I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
-#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4)) /* _i=0...15 */ /* Reset: VFR */
-#define I40E_VFINT_DYN_CTLN1_MAX_INDEX 15
-#define I40E_VFINT_DYN_CTLN1_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTLN1_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
-#define I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
-#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
-#define I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
-#define I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
-#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
-#define I40E_VFINT_ICR0_ENA1 0x00005000 /* Reset: CORER */
-#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
-#define I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
-#define I40E_VFINT_ICR0_ENA1_RSVD_SHIFT 31
-#define I40E_VFINT_ICR0_ENA1_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
-#define I40E_VFINT_ICR01 0x00004800 /* Reset: CORER */
-#define I40E_VFINT_ICR01_INTEVENT_SHIFT 0
-#define I40E_VFINT_ICR01_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_INTEVENT_SHIFT)
-#define I40E_VFINT_ICR01_QUEUE_0_SHIFT 1
-#define I40E_VFINT_ICR01_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_0_SHIFT)
-#define I40E_VFINT_ICR01_QUEUE_1_SHIFT 2
-#define I40E_VFINT_ICR01_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_1_SHIFT)
-#define I40E_VFINT_ICR01_QUEUE_2_SHIFT 3
-#define I40E_VFINT_ICR01_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_2_SHIFT)
-#define I40E_VFINT_ICR01_QUEUE_3_SHIFT 4
-#define I40E_VFINT_ICR01_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_3_SHIFT)
-#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
-#define I40E_VFINT_ICR01_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR01_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_ADMINQ_SHIFT)
-#define I40E_VFINT_ICR01_SWINT_SHIFT 31
-#define I40E_VFINT_ICR01_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_SWINT_SHIFT)
-#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */ /* Reset: VFR */
-#define I40E_VFINT_ITR01_MAX_INDEX 2
-#define I40E_VFINT_ITR01_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITR01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR01_INTERVAL_SHIFT)
-#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...15 */ /* Reset: VFR */
-#define I40E_VFINT_ITRN1_MAX_INDEX 2
-#define I40E_VFINT_ITRN1_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITRN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN1_INTERVAL_SHIFT)
-#define I40E_VFINT_STAT_CTL01 0x00005400 /* Reset: CORER */
-#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT 2
-#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
-#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: CORER */
-#define I40E_QRX_TAIL1_MAX_INDEX 15
-#define I40E_QRX_TAIL1_TAIL_SHIFT 0
-#define I40E_QRX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL1_TAIL_SHIFT)
-#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: PFR */
-#define I40E_QTX_TAIL1_MAX_INDEX 15
-#define I40E_QTX_TAIL1_TAIL_SHIFT 0
-#define I40E_QTX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL1_TAIL_SHIFT)
-#define I40E_VFMSIX_PBA 0x00002000 /* Reset: VFLR */
-#define I40E_VFMSIX_PBA_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
-#define I40E_VFMSIX_TADD_MAX_INDEX 16
-#define I40E_VFMSIX_TADD_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
-#define I40E_VFMSIX_TADD_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
-#define I40E_VFMSIX_TMSG_MAX_INDEX 16
-#define I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
-#define I40E_VFMSIX_TUADD_MAX_INDEX 16
-#define I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
-#define I40E_VFMSIX_TVCTRL_MAX_INDEX 16
-#define I40E_VFMSIX_TVCTRL_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL_MASK_SHIFT)
-#define I40E_VFCM_PE_ERRDATA 0x0000DC00 /* Reset: VFR */
-#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
-#define I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
-#define I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
-#define I40E_VFCM_PE_ERRINFO 0x0000D800 /* Reset: VFR */
-#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
-#define I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
-#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
-#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
-#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
-#define I40E_VFQF_HENA_MAX_INDEX 1
-#define I40E_VFQF_HENA_PTYPE_ENA_SHIFT 0
-#define I40E_VFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
-#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
-#define I40E_VFQF_HKEY_MAX_INDEX 12
-#define I40E_VFQF_HKEY_KEY_0_SHIFT 0
-#define I40E_VFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_0_SHIFT)
-#define I40E_VFQF_HKEY_KEY_1_SHIFT 8
-#define I40E_VFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_1_SHIFT)
-#define I40E_VFQF_HKEY_KEY_2_SHIFT 16
-#define I40E_VFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_2_SHIFT)
-#define I40E_VFQF_HKEY_KEY_3_SHIFT 24
-#define I40E_VFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_3_SHIFT)
-#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
-#define I40E_VFQF_HLUT_MAX_INDEX 15
-#define I40E_VFQF_HLUT_LUT0_SHIFT 0
-#define I40E_VFQF_HLUT_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT0_SHIFT)
-#define I40E_VFQF_HLUT_LUT1_SHIFT 8
-#define I40E_VFQF_HLUT_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT1_SHIFT)
-#define I40E_VFQF_HLUT_LUT2_SHIFT 16
-#define I40E_VFQF_HLUT_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT2_SHIFT)
-#define I40E_VFQF_HLUT_LUT3_SHIFT 24
-#define I40E_VFQF_HLUT_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT3_SHIFT)
-#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */ /* Reset: CORER */
-#define I40E_VFQF_HREGION_MAX_INDEX 7
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
-#define I40E_VFQF_HREGION_REGION_0_SHIFT 1
-#define I40E_VFQF_HREGION_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_0_SHIFT)
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
-#define I40E_VFQF_HREGION_REGION_1_SHIFT 5
-#define I40E_VFQF_HREGION_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_1_SHIFT)
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
-#define I40E_VFQF_HREGION_REGION_2_SHIFT 9
-#define I40E_VFQF_HREGION_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_2_SHIFT)
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
-#define I40E_VFQF_HREGION_REGION_3_SHIFT 13
-#define I40E_VFQF_HREGION_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_3_SHIFT)
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
-#define I40E_VFQF_HREGION_REGION_4_SHIFT 17
-#define I40E_VFQF_HREGION_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_4_SHIFT)
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
-#define I40E_VFQF_HREGION_REGION_5_SHIFT 21
-#define I40E_VFQF_HREGION_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_5_SHIFT)
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
-#define I40E_VFQF_HREGION_REGION_6_SHIFT 25
-#define I40E_VFQF_HREGION_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_6_SHIFT)
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
-#define I40E_VFQF_HREGION_REGION_7_SHIFT 29
-#define I40E_VFQF_HREGION_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_7_SHIFT)
-#define I40E_VFINT_DYN_CTL01_WB_ON_ITR_SHIFT 30
-#define I40E_VFINT_DYN_CTL01_WB_ON_ITR_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_WB_ON_ITR_SHIFT)
-#define I40E_VFINT_DYN_CTLN1_WB_ON_ITR_SHIFT 30
-#define I40E_VFINT_DYN_CTLN1_WB_ON_ITR_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_WB_ON_ITR_SHIFT)
-#define I40E_VFPE_AEQALLOC1 0x0000A400 /* Reset: VFR */
-#define I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT 0
-#define I40E_VFPE_AEQALLOC1_AECOUNT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT)
-#define I40E_VFPE_CCQPHIGH1 0x00009800 /* Reset: VFR */
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT 0
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_MASK I40E_MASK(0xFFFFFFFF, I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT)
-#define I40E_VFPE_CCQPLOW1 0x0000AC00 /* Reset: VFR */
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT 0
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_MASK I40E_MASK(0xFFFFFFFF, I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1 0x0000B800 /* Reset: VFR */
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT 0
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_MASK I40E_MASK(0x1, I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1_HMC_PROFILE_SHIFT 4
-#define I40E_VFPE_CCQPSTATUS1_HMC_PROFILE_MASK I40E_MASK(0x7, I40E_VFPE_CCQPSTATUS1_HMC_PROFILE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1_RDMA_EN_VFS_SHIFT 16
-#define I40E_VFPE_CCQPSTATUS1_RDMA_EN_VFS_MASK I40E_MASK(0x3F, I40E_VFPE_CCQPSTATUS1_RDMA_EN_VFS_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT 31
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_MASK I40E_MASK(0x1, I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT)
-#define I40E_VFPE_CQACK1 0x0000B000 /* Reset: VFR */
-#define I40E_VFPE_CQACK1_PECQID_SHIFT 0
-#define I40E_VFPE_CQACK1_PECQID_MASK I40E_MASK(0x1FFFF, I40E_VFPE_CQACK1_PECQID_SHIFT)
-#define I40E_VFPE_CQARM1 0x0000B400 /* Reset: VFR */
-#define I40E_VFPE_CQARM1_PECQID_SHIFT 0
-#define I40E_VFPE_CQARM1_PECQID_MASK I40E_MASK(0x1FFFF, I40E_VFPE_CQARM1_PECQID_SHIFT)
-#define I40E_VFPE_CQPDB1 0x0000BC00 /* Reset: VFR */
-#define I40E_VFPE_CQPDB1_WQHEAD_SHIFT 0
-#define I40E_VFPE_CQPDB1_WQHEAD_MASK I40E_MASK(0x7FF, I40E_VFPE_CQPDB1_WQHEAD_SHIFT)
-#define I40E_VFPE_CQPERRCODES1 0x00009C00 /* Reset: VFR */
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT 0
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_MASK I40E_MASK(0xFFFF, I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT)
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_MASK I40E_MASK(0xFFFF, I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT)
-#define I40E_VFPE_CQPTAIL1 0x0000A000 /* Reset: VFR */
-#define I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT 0
-#define I40E_VFPE_CQPTAIL1_WQTAIL_MASK I40E_MASK(0x7FF, I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT)
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT 31
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_MASK I40E_MASK(0x1, I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT)
-#define I40E_VFPE_IPCONFIG01 0x00008C00 /* Reset: VFR */
-#define I40E_VFPE_IPCONFIG01_PEIPID_SHIFT 0
-#define I40E_VFPE_IPCONFIG01_PEIPID_MASK I40E_MASK(0xFFFF, I40E_VFPE_IPCONFIG01_PEIPID_SHIFT)
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT 16
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_MASK I40E_MASK(0x1, I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_MRTEIDXMASK1 0x00009000 /* Reset: VFR */
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_MASK I40E_MASK(0x1F, I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT)
-#define I40E_VFPE_RCVUNEXPECTEDERROR1 0x00009400 /* Reset: VFR */
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_MASK I40E_MASK(0xFFFFFF, I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_VFPE_TCPNOWTIMER1 0x0000A800 /* Reset: VFR */
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT 0
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_MASK I40E_MASK(0xFFFFFFFF, I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT)
-#define I40E_VFPE_WQEALLOC1 0x0000C000 /* Reset: VFR */
-#define I40E_VFPE_WQEALLOC1_PEQPID_SHIFT 0
-#define I40E_VFPE_WQEALLOC1_PEQPID_MASK I40E_MASK(0x3FFFF, I40E_VFPE_WQEALLOC1_PEQPID_SHIFT)
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT 20
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_MASK I40E_MASK(0xFFF, I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT)
-#endif /* _I40E_REGISTER_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_status.h b/drivers/net/ethernet/intel/i40evf/i40e_status.h
deleted file mode 100644
index 77be0702d07c..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_status.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_STATUS_H_
-#define _I40E_STATUS_H_
-
-/* Error Codes */
-enum i40e_status_code {
- I40E_SUCCESS = 0,
- I40E_ERR_NVM = -1,
- I40E_ERR_NVM_CHECKSUM = -2,
- I40E_ERR_PHY = -3,
- I40E_ERR_CONFIG = -4,
- I40E_ERR_PARAM = -5,
- I40E_ERR_MAC_TYPE = -6,
- I40E_ERR_UNKNOWN_PHY = -7,
- I40E_ERR_LINK_SETUP = -8,
- I40E_ERR_ADAPTER_STOPPED = -9,
- I40E_ERR_INVALID_MAC_ADDR = -10,
- I40E_ERR_DEVICE_NOT_SUPPORTED = -11,
- I40E_ERR_MASTER_REQUESTS_PENDING = -12,
- I40E_ERR_INVALID_LINK_SETTINGS = -13,
- I40E_ERR_AUTONEG_NOT_COMPLETE = -14,
- I40E_ERR_RESET_FAILED = -15,
- I40E_ERR_SWFW_SYNC = -16,
- I40E_ERR_NO_AVAILABLE_VSI = -17,
- I40E_ERR_NO_MEMORY = -18,
- I40E_ERR_BAD_PTR = -19,
- I40E_ERR_RING_FULL = -20,
- I40E_ERR_INVALID_PD_ID = -21,
- I40E_ERR_INVALID_QP_ID = -22,
- I40E_ERR_INVALID_CQ_ID = -23,
- I40E_ERR_INVALID_CEQ_ID = -24,
- I40E_ERR_INVALID_AEQ_ID = -25,
- I40E_ERR_INVALID_SIZE = -26,
- I40E_ERR_INVALID_ARP_INDEX = -27,
- I40E_ERR_INVALID_FPM_FUNC_ID = -28,
- I40E_ERR_QP_INVALID_MSG_SIZE = -29,
- I40E_ERR_QP_TOOMANY_WRS_POSTED = -30,
- I40E_ERR_INVALID_FRAG_COUNT = -31,
- I40E_ERR_QUEUE_EMPTY = -32,
- I40E_ERR_INVALID_ALIGNMENT = -33,
- I40E_ERR_FLUSHED_QUEUE = -34,
- I40E_ERR_INVALID_PUSH_PAGE_INDEX = -35,
- I40E_ERR_INVALID_IMM_DATA_SIZE = -36,
- I40E_ERR_TIMEOUT = -37,
- I40E_ERR_OPCODE_MISMATCH = -38,
- I40E_ERR_CQP_COMPL_ERROR = -39,
- I40E_ERR_INVALID_VF_ID = -40,
- I40E_ERR_INVALID_HMCFN_ID = -41,
- I40E_ERR_BACKING_PAGE_ERROR = -42,
- I40E_ERR_NO_PBLCHUNKS_AVAILABLE = -43,
- I40E_ERR_INVALID_PBLE_INDEX = -44,
- I40E_ERR_INVALID_SD_INDEX = -45,
- I40E_ERR_INVALID_PAGE_DESC_INDEX = -46,
- I40E_ERR_INVALID_SD_TYPE = -47,
- I40E_ERR_MEMCPY_FAILED = -48,
- I40E_ERR_INVALID_HMC_OBJ_INDEX = -49,
- I40E_ERR_INVALID_HMC_OBJ_COUNT = -50,
- I40E_ERR_INVALID_SRQ_ARM_LIMIT = -51,
- I40E_ERR_SRQ_ENABLED = -52,
- I40E_ERR_ADMIN_QUEUE_ERROR = -53,
- I40E_ERR_ADMIN_QUEUE_TIMEOUT = -54,
- I40E_ERR_BUF_TOO_SHORT = -55,
- I40E_ERR_ADMIN_QUEUE_FULL = -56,
- I40E_ERR_ADMIN_QUEUE_NO_WORK = -57,
- I40E_ERR_BAD_IWARP_CQE = -58,
- I40E_ERR_NVM_BLANK_MODE = -59,
- I40E_ERR_NOT_IMPLEMENTED = -60,
- I40E_ERR_PE_DOORBELL_NOT_ENABLED = -61,
- I40E_ERR_DIAG_TEST_FAILED = -62,
- I40E_ERR_NOT_READY = -63,
- I40E_NOT_SUPPORTED = -64,
- I40E_ERR_FIRMWARE_API_VERSION = -65,
- I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR = -66,
-};
-
-#endif /* _I40E_STATUS_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_trace.h b/drivers/net/ethernet/intel/i40evf/i40e_trace.h
deleted file mode 100644
index d7a4e68820a8..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_trace.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-/* Modeled on trace-events-sample.h */
-
-/* The trace subsystem name for i40evf will be "i40evf".
- *
- * This file is named i40e_trace.h.
- *
- * Since this include file's name is different from the trace
- * subsystem name, we'll have to define TRACE_INCLUDE_FILE at the end
- * of this file.
- */
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM i40evf
-
-/* See trace-events-sample.h for a detailed description of why this
- * guard clause is different from most normal include files.
- */
-#if !defined(_I40E_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
-#define _I40E_TRACE_H_
-
-#include <linux/tracepoint.h>
-
-/**
- * i40e_trace() macro enables shared code to refer to trace points
- * like:
- *
- * trace_i40e{,vf}_example(args...)
- *
- * ... as:
- *
- * i40e_trace(example, args...)
- *
- * ... to resolve to the PF or VF version of the tracepoint without
- * ifdefs, and to allow tracepoints to be disabled entirely at build
- * time.
- *
- * Trace point should always be referred to in the driver via this
- * macro.
- *
- * Similarly, i40e_trace_enabled(trace_name) wraps references to
- * trace_i40e{,vf}_<trace_name>_enabled() functions.
- */
-#define _I40E_TRACE_NAME(trace_name) (trace_ ## i40evf ## _ ## trace_name)
-#define I40E_TRACE_NAME(trace_name) _I40E_TRACE_NAME(trace_name)
-
-#define i40e_trace(trace_name, args...) I40E_TRACE_NAME(trace_name)(args)
-
-#define i40e_trace_enabled(trace_name) I40E_TRACE_NAME(trace_name##_enabled)()
-
-/* Events common to PF and VF. Corresponding versions will be defined
- * for both, named trace_i40e_* and trace_i40evf_*. The i40e_trace()
- * macro above will select the right trace point name for the driver
- * being built from shared code.
- */
-
-/* Events related to a vsi & ring */
-DECLARE_EVENT_CLASS(
- i40evf_tx_template,
-
- TP_PROTO(struct i40e_ring *ring,
- struct i40e_tx_desc *desc,
- struct i40e_tx_buffer *buf),
-
- TP_ARGS(ring, desc, buf),
-
- /* The convention here is to make the first fields in the
- * TP_STRUCT match the TP_PROTO exactly. This enables the use
- * of the args struct generated by the tplist tool (from the
- * bcc-tools package) to be used for those fields. To access
- * fields other than the tracepoint args will require the
- * tplist output to be adjusted.
- */
- TP_STRUCT__entry(
- __field(void*, ring)
- __field(void*, desc)
- __field(void*, buf)
- __string(devname, ring->netdev->name)
- ),
-
- TP_fast_assign(
- __entry->ring = ring;
- __entry->desc = desc;
- __entry->buf = buf;
- __assign_str(devname, ring->netdev->name);
- ),
-
- TP_printk(
- "netdev: %s ring: %p desc: %p buf %p",
- __get_str(devname), __entry->ring,
- __entry->desc, __entry->buf)
-);
-
-DEFINE_EVENT(
- i40evf_tx_template, i40evf_clean_tx_irq,
- TP_PROTO(struct i40e_ring *ring,
- struct i40e_tx_desc *desc,
- struct i40e_tx_buffer *buf),
-
- TP_ARGS(ring, desc, buf));
-
-DEFINE_EVENT(
- i40evf_tx_template, i40evf_clean_tx_irq_unmap,
- TP_PROTO(struct i40e_ring *ring,
- struct i40e_tx_desc *desc,
- struct i40e_tx_buffer *buf),
-
- TP_ARGS(ring, desc, buf));
-
-DECLARE_EVENT_CLASS(
- i40evf_rx_template,
-
- TP_PROTO(struct i40e_ring *ring,
- union i40e_32byte_rx_desc *desc,
- struct sk_buff *skb),
-
- TP_ARGS(ring, desc, skb),
-
- TP_STRUCT__entry(
- __field(void*, ring)
- __field(void*, desc)
- __field(void*, skb)
- __string(devname, ring->netdev->name)
- ),
-
- TP_fast_assign(
- __entry->ring = ring;
- __entry->desc = desc;
- __entry->skb = skb;
- __assign_str(devname, ring->netdev->name);
- ),
-
- TP_printk(
- "netdev: %s ring: %p desc: %p skb %p",
- __get_str(devname), __entry->ring,
- __entry->desc, __entry->skb)
-);
-
-DEFINE_EVENT(
- i40evf_rx_template, i40evf_clean_rx_irq,
- TP_PROTO(struct i40e_ring *ring,
- union i40e_32byte_rx_desc *desc,
- struct sk_buff *skb),
-
- TP_ARGS(ring, desc, skb));
-
-DEFINE_EVENT(
- i40evf_rx_template, i40evf_clean_rx_irq_rx,
- TP_PROTO(struct i40e_ring *ring,
- union i40e_32byte_rx_desc *desc,
- struct sk_buff *skb),
-
- TP_ARGS(ring, desc, skb));
-
-DECLARE_EVENT_CLASS(
- i40evf_xmit_template,
-
- TP_PROTO(struct sk_buff *skb,
- struct i40e_ring *ring),
-
- TP_ARGS(skb, ring),
-
- TP_STRUCT__entry(
- __field(void*, skb)
- __field(void*, ring)
- __string(devname, ring->netdev->name)
- ),
-
- TP_fast_assign(
- __entry->skb = skb;
- __entry->ring = ring;
- __assign_str(devname, ring->netdev->name);
- ),
-
- TP_printk(
- "netdev: %s skb: %p ring: %p",
- __get_str(devname), __entry->skb,
- __entry->ring)
-);
-
-DEFINE_EVENT(
- i40evf_xmit_template, i40evf_xmit_frame_ring,
- TP_PROTO(struct sk_buff *skb,
- struct i40e_ring *ring),
-
- TP_ARGS(skb, ring));
-
-DEFINE_EVENT(
- i40evf_xmit_template, i40evf_xmit_frame_ring_drop,
- TP_PROTO(struct sk_buff *skb,
- struct i40e_ring *ring),
-
- TP_ARGS(skb, ring));
-
-/* Events unique to the VF. */
-
-#endif /* _I40E_TRACE_H_ */
-/* This must be outside ifdef _I40E_TRACE_H */
-
-/* This trace include file is not located in the .../include/trace
- * with the kernel tracepoint definitions, because we're a loadable
- * module.
- */
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE i40e_trace
-#include <trace/define_trace.h>
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
deleted file mode 100644
index 1bf9734ae9cf..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ /dev/null
@@ -1,2513 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#include <linux/prefetch.h>
-#include <net/busy_poll.h>
-
-#include "i40evf.h"
-#include "i40e_trace.h"
-#include "i40e_prototype.h"
-
-static inline __le64 build_ctob(u32 td_cmd, u32 td_offset, unsigned int size,
- u32 td_tag)
-{
- return cpu_to_le64(I40E_TX_DESC_DTYPE_DATA |
- ((u64)td_cmd << I40E_TXD_QW1_CMD_SHIFT) |
- ((u64)td_offset << I40E_TXD_QW1_OFFSET_SHIFT) |
- ((u64)size << I40E_TXD_QW1_TX_BUF_SZ_SHIFT) |
- ((u64)td_tag << I40E_TXD_QW1_L2TAG1_SHIFT));
-}
-
-#define I40E_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS)
-
-/**
- * i40e_unmap_and_free_tx_resource - Release a Tx buffer
- * @ring: the ring that owns the buffer
- * @tx_buffer: the buffer to free
- **/
-static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring,
- struct i40e_tx_buffer *tx_buffer)
-{
- if (tx_buffer->skb) {
- if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
- kfree(tx_buffer->raw_buf);
- else
- dev_kfree_skb_any(tx_buffer->skb);
- if (dma_unmap_len(tx_buffer, len))
- dma_unmap_single(ring->dev,
- dma_unmap_addr(tx_buffer, dma),
- dma_unmap_len(tx_buffer, len),
- DMA_TO_DEVICE);
- } else if (dma_unmap_len(tx_buffer, len)) {
- dma_unmap_page(ring->dev,
- dma_unmap_addr(tx_buffer, dma),
- dma_unmap_len(tx_buffer, len),
- DMA_TO_DEVICE);
- }
-
- tx_buffer->next_to_watch = NULL;
- tx_buffer->skb = NULL;
- dma_unmap_len_set(tx_buffer, len, 0);
- /* tx_buffer must be completely set up in the transmit path */
-}
-
-/**
- * i40evf_clean_tx_ring - Free any empty Tx buffers
- * @tx_ring: ring to be cleaned
- **/
-void i40evf_clean_tx_ring(struct i40e_ring *tx_ring)
-{
- unsigned long bi_size;
- u16 i;
-
- /* ring already cleared, nothing to do */
- if (!tx_ring->tx_bi)
- return;
-
- /* Free all the Tx ring sk_buffs */
- for (i = 0; i < tx_ring->count; i++)
- i40e_unmap_and_free_tx_resource(tx_ring, &tx_ring->tx_bi[i]);
-
- bi_size = sizeof(struct i40e_tx_buffer) * tx_ring->count;
- memset(tx_ring->tx_bi, 0, bi_size);
-
- /* Zero out the descriptor ring */
- memset(tx_ring->desc, 0, tx_ring->size);
-
- tx_ring->next_to_use = 0;
- tx_ring->next_to_clean = 0;
-
- if (!tx_ring->netdev)
- return;
-
- /* cleanup Tx queue statistics */
- netdev_tx_reset_queue(txring_txq(tx_ring));
-}
-
-/**
- * i40evf_free_tx_resources - Free Tx resources per queue
- * @tx_ring: Tx descriptor ring for a specific queue
- *
- * Free all transmit software resources
- **/
-void i40evf_free_tx_resources(struct i40e_ring *tx_ring)
-{
- i40evf_clean_tx_ring(tx_ring);
- kfree(tx_ring->tx_bi);
- tx_ring->tx_bi = NULL;
-
- if (tx_ring->desc) {
- dma_free_coherent(tx_ring->dev, tx_ring->size,
- tx_ring->desc, tx_ring->dma);
- tx_ring->desc = NULL;
- }
-}
-
-/**
- * i40evf_get_tx_pending - how many Tx descriptors not processed
- * @ring: the ring of descriptors
- * @in_sw: is tx_pending being checked in SW or HW
- *
- * Since there is no access to the ring head register
- * in XL710, we need to use our local copies
- **/
-u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw)
-{
- u32 head, tail;
-
- /* underlying hardware might not allow access and/or always return
- * 0 for the head/tail registers so just use the cached values
- */
- head = ring->next_to_clean;
- tail = ring->next_to_use;
-
- if (head != tail)
- return (head < tail) ?
- tail - head : (tail + ring->count - head);
-
- return 0;
-}
-
-/**
- * i40evf_detect_recover_hung - Function to detect and recover hung_queues
- * @vsi: pointer to vsi struct with tx queues
- *
- * VSI has netdev and netdev has TX queues. This function is to check each of
- * those TX queues if they are hung, trigger recovery by issuing SW interrupt.
- **/
-void i40evf_detect_recover_hung(struct i40e_vsi *vsi)
-{
- struct i40e_ring *tx_ring = NULL;
- struct net_device *netdev;
- unsigned int i;
- int packets;
-
- if (!vsi)
- return;
-
- if (test_bit(__I40E_VSI_DOWN, vsi->state))
- return;
-
- netdev = vsi->netdev;
- if (!netdev)
- return;
-
- if (!netif_carrier_ok(netdev))
- return;
-
- for (i = 0; i < vsi->back->num_active_queues; i++) {
- tx_ring = &vsi->back->tx_rings[i];
- if (tx_ring && tx_ring->desc) {
- /* If packet counter has not changed the queue is
- * likely stalled, so force an interrupt for this
- * queue.
- *
- * prev_pkt_ctr would be negative if there was no
- * pending work.
- */
- packets = tx_ring->stats.packets & INT_MAX;
- if (tx_ring->tx_stats.prev_pkt_ctr == packets) {
- i40evf_force_wb(vsi, tx_ring->q_vector);
- continue;
- }
-
- /* Memory barrier between read of packet count and call
- * to i40evf_get_tx_pending()
- */
- smp_rmb();
- tx_ring->tx_stats.prev_pkt_ctr =
- i40evf_get_tx_pending(tx_ring, true) ? packets : -1;
- }
- }
-}
-
-#define WB_STRIDE 4
-
-/**
- * i40e_clean_tx_irq - Reclaim resources after transmit completes
- * @vsi: the VSI we care about
- * @tx_ring: Tx ring to clean
- * @napi_budget: Used to determine if we are in netpoll
- *
- * Returns true if there's any budget left (e.g. the clean is finished)
- **/
-static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
- struct i40e_ring *tx_ring, int napi_budget)
-{
- u16 i = tx_ring->next_to_clean;
- struct i40e_tx_buffer *tx_buf;
- struct i40e_tx_desc *tx_desc;
- unsigned int total_bytes = 0, total_packets = 0;
- unsigned int budget = vsi->work_limit;
-
- tx_buf = &tx_ring->tx_bi[i];
- tx_desc = I40E_TX_DESC(tx_ring, i);
- i -= tx_ring->count;
-
- do {
- struct i40e_tx_desc *eop_desc = tx_buf->next_to_watch;
-
- /* if next_to_watch is not set then there is no work pending */
- if (!eop_desc)
- break;
-
- /* prevent any other reads prior to eop_desc */
- smp_rmb();
-
- i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf);
- /* if the descriptor isn't done, no work yet to do */
- if (!(eop_desc->cmd_type_offset_bsz &
- cpu_to_le64(I40E_TX_DESC_DTYPE_DESC_DONE)))
- break;
-
- /* clear next_to_watch to prevent false hangs */
- tx_buf->next_to_watch = NULL;
-
- /* update the statistics for this packet */
- total_bytes += tx_buf->bytecount;
- total_packets += tx_buf->gso_segs;
-
- /* free the skb */
- napi_consume_skb(tx_buf->skb, napi_budget);
-
- /* unmap skb header data */
- dma_unmap_single(tx_ring->dev,
- dma_unmap_addr(tx_buf, dma),
- dma_unmap_len(tx_buf, len),
- DMA_TO_DEVICE);
-
- /* clear tx_buffer data */
- tx_buf->skb = NULL;
- dma_unmap_len_set(tx_buf, len, 0);
-
- /* unmap remaining buffers */
- while (tx_desc != eop_desc) {
- i40e_trace(clean_tx_irq_unmap,
- tx_ring, tx_desc, tx_buf);
-
- tx_buf++;
- tx_desc++;
- i++;
- if (unlikely(!i)) {
- i -= tx_ring->count;
- tx_buf = tx_ring->tx_bi;
- tx_desc = I40E_TX_DESC(tx_ring, 0);
- }
-
- /* unmap any remaining paged data */
- if (dma_unmap_len(tx_buf, len)) {
- dma_unmap_page(tx_ring->dev,
- dma_unmap_addr(tx_buf, dma),
- dma_unmap_len(tx_buf, len),
- DMA_TO_DEVICE);
- dma_unmap_len_set(tx_buf, len, 0);
- }
- }
-
- /* move us one more past the eop_desc for start of next pkt */
- tx_buf++;
- tx_desc++;
- i++;
- if (unlikely(!i)) {
- i -= tx_ring->count;
- tx_buf = tx_ring->tx_bi;
- tx_desc = I40E_TX_DESC(tx_ring, 0);
- }
-
- prefetch(tx_desc);
-
- /* update budget accounting */
- budget--;
- } while (likely(budget));
-
- i += tx_ring->count;
- tx_ring->next_to_clean = i;
- u64_stats_update_begin(&tx_ring->syncp);
- tx_ring->stats.bytes += total_bytes;
- tx_ring->stats.packets += total_packets;
- u64_stats_update_end(&tx_ring->syncp);
- tx_ring->q_vector->tx.total_bytes += total_bytes;
- tx_ring->q_vector->tx.total_packets += total_packets;
-
- if (tx_ring->flags & I40E_TXR_FLAGS_WB_ON_ITR) {
- /* check to see if there are < 4 descriptors
- * waiting to be written back, then kick the hardware to force
- * them to be written back in case we stay in NAPI.
- * In this mode on X722 we do not enable Interrupt.
- */
- unsigned int j = i40evf_get_tx_pending(tx_ring, false);
-
- if (budget &&
- ((j / WB_STRIDE) == 0) && (j > 0) &&
- !test_bit(__I40E_VSI_DOWN, vsi->state) &&
- (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
- tx_ring->arm_wb = true;
- }
-
- /* notify netdev of completed buffers */
- netdev_tx_completed_queue(txring_txq(tx_ring),
- total_packets, total_bytes);
-
-#define TX_WAKE_THRESHOLD ((s16)(DESC_NEEDED * 2))
- if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) &&
- (I40E_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
- /* Make sure that anybody stopping the queue after this
- * sees the new next_to_clean.
- */
- smp_mb();
- if (__netif_subqueue_stopped(tx_ring->netdev,
- tx_ring->queue_index) &&
- !test_bit(__I40E_VSI_DOWN, vsi->state)) {
- netif_wake_subqueue(tx_ring->netdev,
- tx_ring->queue_index);
- ++tx_ring->tx_stats.restart_queue;
- }
- }
-
- return !!budget;
-}
-
-/**
- * i40evf_enable_wb_on_itr - Arm hardware to do a wb, interrupts are not enabled
- * @vsi: the VSI we care about
- * @q_vector: the vector on which to enable writeback
- *
- **/
-static void i40e_enable_wb_on_itr(struct i40e_vsi *vsi,
- struct i40e_q_vector *q_vector)
-{
- u16 flags = q_vector->tx.ring[0].flags;
- u32 val;
-
- if (!(flags & I40E_TXR_FLAGS_WB_ON_ITR))
- return;
-
- if (q_vector->arm_wb_state)
- return;
-
- val = I40E_VFINT_DYN_CTLN1_WB_ON_ITR_MASK |
- I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK; /* set noitr */
-
- wr32(&vsi->back->hw,
- I40E_VFINT_DYN_CTLN1(q_vector->reg_idx), val);
- q_vector->arm_wb_state = true;
-}
-
-/**
- * i40evf_force_wb - Issue SW Interrupt so HW does a wb
- * @vsi: the VSI we care about
- * @q_vector: the vector on which to force writeback
- *
- **/
-void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
-{
- u32 val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
- I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */
- I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
- I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK
- /* allow 00 to be written to the index */;
-
- wr32(&vsi->back->hw,
- I40E_VFINT_DYN_CTLN1(q_vector->reg_idx),
- val);
-}
-
-static inline bool i40e_container_is_rx(struct i40e_q_vector *q_vector,
- struct i40e_ring_container *rc)
-{
- return &q_vector->rx == rc;
-}
-
-static inline unsigned int i40e_itr_divisor(struct i40e_q_vector *q_vector)
-{
- unsigned int divisor;
-
- switch (q_vector->adapter->link_speed) {
- case I40E_LINK_SPEED_40GB:
- divisor = I40E_ITR_ADAPTIVE_MIN_INC * 1024;
- break;
- case I40E_LINK_SPEED_25GB:
- case I40E_LINK_SPEED_20GB:
- divisor = I40E_ITR_ADAPTIVE_MIN_INC * 512;
- break;
- default:
- case I40E_LINK_SPEED_10GB:
- divisor = I40E_ITR_ADAPTIVE_MIN_INC * 256;
- break;
- case I40E_LINK_SPEED_1GB:
- case I40E_LINK_SPEED_100MB:
- divisor = I40E_ITR_ADAPTIVE_MIN_INC * 32;
- break;
- }
-
- return divisor;
-}
-
-/**
- * i40e_update_itr - update the dynamic ITR value based on statistics
- * @q_vector: structure containing interrupt and ring information
- * @rc: structure containing ring performance data
- *
- * Stores a new ITR value based on packets and byte
- * counts during the last interrupt. The advantage of per interrupt
- * computation is faster updates and more accurate ITR for the current
- * traffic pattern. Constants in this function were computed
- * based on theoretical maximum wire speed and thresholds were set based
- * on testing data as well as attempting to minimize response time
- * while increasing bulk throughput.
- **/
-static void i40e_update_itr(struct i40e_q_vector *q_vector,
- struct i40e_ring_container *rc)
-{
- unsigned int avg_wire_size, packets, bytes, itr;
- unsigned long next_update = jiffies;
-
- /* If we don't have any rings just leave ourselves set for maximum
- * possible latency so we take ourselves out of the equation.
- */
- if (!rc->ring || !ITR_IS_DYNAMIC(rc->ring->itr_setting))
- return;
-
- /* For Rx we want to push the delay up and default to low latency.
- * for Tx we want to pull the delay down and default to high latency.
- */
- itr = i40e_container_is_rx(q_vector, rc) ?
- I40E_ITR_ADAPTIVE_MIN_USECS | I40E_ITR_ADAPTIVE_LATENCY :
- I40E_ITR_ADAPTIVE_MAX_USECS | I40E_ITR_ADAPTIVE_LATENCY;
-
- /* If we didn't update within up to 1 - 2 jiffies we can assume
- * that either packets are coming in so slow there hasn't been
- * any work, or that there is so much work that NAPI is dealing
- * with interrupt moderation and we don't need to do anything.
- */
- if (time_after(next_update, rc->next_update))
- goto clear_counts;
-
- /* If itr_countdown is set it means we programmed an ITR within
- * the last 4 interrupt cycles. This has a side effect of us
- * potentially firing an early interrupt. In order to work around
- * this we need to throw out any data received for a few
- * interrupts following the update.
- */
- if (q_vector->itr_countdown) {
- itr = rc->target_itr;
- goto clear_counts;
- }
-
- packets = rc->total_packets;
- bytes = rc->total_bytes;
-
- if (i40e_container_is_rx(q_vector, rc)) {
- /* If Rx there are 1 to 4 packets and bytes are less than
- * 9000 assume insufficient data to use bulk rate limiting
- * approach unless Tx is already in bulk rate limiting. We
- * are likely latency driven.
- */
- if (packets && packets < 4 && bytes < 9000 &&
- (q_vector->tx.target_itr & I40E_ITR_ADAPTIVE_LATENCY)) {
- itr = I40E_ITR_ADAPTIVE_LATENCY;
- goto adjust_by_size;
- }
- } else if (packets < 4) {
- /* If we have Tx and Rx ITR maxed and Tx ITR is running in
- * bulk mode and we are receiving 4 or fewer packets just
- * reset the ITR_ADAPTIVE_LATENCY bit for latency mode so
- * that the Rx can relax.
- */
- if (rc->target_itr == I40E_ITR_ADAPTIVE_MAX_USECS &&
- (q_vector->rx.target_itr & I40E_ITR_MASK) ==
- I40E_ITR_ADAPTIVE_MAX_USECS)
- goto clear_counts;
- } else if (packets > 32) {
- /* If we have processed over 32 packets in a single interrupt
- * for Tx assume we need to switch over to "bulk" mode.
- */
- rc->target_itr &= ~I40E_ITR_ADAPTIVE_LATENCY;
- }
-
- /* We have no packets to actually measure against. This means
- * either one of the other queues on this vector is active or
- * we are a Tx queue doing TSO with too high of an interrupt rate.
- *
- * Between 4 and 56 we can assume that our current interrupt delay
- * is only slightly too low. As such we should increase it by a small
- * fixed amount.
- */
- if (packets < 56) {
- itr = rc->target_itr + I40E_ITR_ADAPTIVE_MIN_INC;
- if ((itr & I40E_ITR_MASK) > I40E_ITR_ADAPTIVE_MAX_USECS) {
- itr &= I40E_ITR_ADAPTIVE_LATENCY;
- itr += I40E_ITR_ADAPTIVE_MAX_USECS;
- }
- goto clear_counts;
- }
-
- if (packets <= 256) {
- itr = min(q_vector->tx.current_itr, q_vector->rx.current_itr);
- itr &= I40E_ITR_MASK;
-
- /* Between 56 and 112 is our "goldilocks" zone where we are
- * working out "just right". Just report that our current
- * ITR is good for us.
- */
- if (packets <= 112)
- goto clear_counts;
-
- /* If packet count is 128 or greater we are likely looking
- * at a slight overrun of the delay we want. Try halving
- * our delay to see if that will cut the number of packets
- * in half per interrupt.
- */
- itr /= 2;
- itr &= I40E_ITR_MASK;
- if (itr < I40E_ITR_ADAPTIVE_MIN_USECS)
- itr = I40E_ITR_ADAPTIVE_MIN_USECS;
-
- goto clear_counts;
- }
-
- /* The paths below assume we are dealing with a bulk ITR since
- * number of packets is greater than 256. We are just going to have
- * to compute a value and try to bring the count under control,
- * though for smaller packet sizes there isn't much we can do as
- * NAPI polling will likely be kicking in sooner rather than later.
- */
- itr = I40E_ITR_ADAPTIVE_BULK;
-
-adjust_by_size:
- /* If packet counts are 256 or greater we can assume we have a gross
- * overestimation of what the rate should be. Instead of trying to fine
- * tune it just use the formula below to try and dial in an exact value
- * give the current packet size of the frame.
- */
- avg_wire_size = bytes / packets;
-
- /* The following is a crude approximation of:
- * wmem_default / (size + overhead) = desired_pkts_per_int
- * rate / bits_per_byte / (size + ethernet overhead) = pkt_rate
- * (desired_pkt_rate / pkt_rate) * usecs_per_sec = ITR value
- *
- * Assuming wmem_default is 212992 and overhead is 640 bytes per
- * packet, (256 skb, 64 headroom, 320 shared info), we can reduce the
- * formula down to
- *
- * (170 * (size + 24)) / (size + 640) = ITR
- *
- * We first do some math on the packet size and then finally bitshift
- * by 8 after rounding up. We also have to account for PCIe link speed
- * difference as ITR scales based on this.
- */
- if (avg_wire_size <= 60) {
- /* Start at 250k ints/sec */
- avg_wire_size = 4096;
- } else if (avg_wire_size <= 380) {
- /* 250K ints/sec to 60K ints/sec */
- avg_wire_size *= 40;
- avg_wire_size += 1696;
- } else if (avg_wire_size <= 1084) {
- /* 60K ints/sec to 36K ints/sec */
- avg_wire_size *= 15;
- avg_wire_size += 11452;
- } else if (avg_wire_size <= 1980) {
- /* 36K ints/sec to 30K ints/sec */
- avg_wire_size *= 5;
- avg_wire_size += 22420;
- } else {
- /* plateau at a limit of 30K ints/sec */
- avg_wire_size = 32256;
- }
-
- /* If we are in low latency mode halve our delay which doubles the
- * rate to somewhere between 100K to 16K ints/sec
- */
- if (itr & I40E_ITR_ADAPTIVE_LATENCY)
- avg_wire_size /= 2;
-
- /* Resultant value is 256 times larger than it needs to be. This
- * gives us room to adjust the value as needed to either increase
- * or decrease the value based on link speeds of 10G, 2.5G, 1G, etc.
- *
- * Use addition as we have already recorded the new latency flag
- * for the ITR value.
- */
- itr += DIV_ROUND_UP(avg_wire_size, i40e_itr_divisor(q_vector)) *
- I40E_ITR_ADAPTIVE_MIN_INC;
-
- if ((itr & I40E_ITR_MASK) > I40E_ITR_ADAPTIVE_MAX_USECS) {
- itr &= I40E_ITR_ADAPTIVE_LATENCY;
- itr += I40E_ITR_ADAPTIVE_MAX_USECS;
- }
-
-clear_counts:
- /* write back value */
- rc->target_itr = itr;
-
- /* next update should occur within next jiffy */
- rc->next_update = next_update + 1;
-
- rc->total_bytes = 0;
- rc->total_packets = 0;
-}
-
-/**
- * i40evf_setup_tx_descriptors - Allocate the Tx descriptors
- * @tx_ring: the tx ring to set up
- *
- * Return 0 on success, negative on error
- **/
-int i40evf_setup_tx_descriptors(struct i40e_ring *tx_ring)
-{
- struct device *dev = tx_ring->dev;
- int bi_size;
-
- if (!dev)
- return -ENOMEM;
-
- /* warn if we are about to overwrite the pointer */
- WARN_ON(tx_ring->tx_bi);
- bi_size = sizeof(struct i40e_tx_buffer) * tx_ring->count;
- tx_ring->tx_bi = kzalloc(bi_size, GFP_KERNEL);
- if (!tx_ring->tx_bi)
- goto err;
-
- /* round up to nearest 4K */
- tx_ring->size = tx_ring->count * sizeof(struct i40e_tx_desc);
- tx_ring->size = ALIGN(tx_ring->size, 4096);
- tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
- &tx_ring->dma, GFP_KERNEL);
- if (!tx_ring->desc) {
- dev_info(dev, "Unable to allocate memory for the Tx descriptor ring, size=%d\n",
- tx_ring->size);
- goto err;
- }
-
- tx_ring->next_to_use = 0;
- tx_ring->next_to_clean = 0;
- tx_ring->tx_stats.prev_pkt_ctr = -1;
- return 0;
-
-err:
- kfree(tx_ring->tx_bi);
- tx_ring->tx_bi = NULL;
- return -ENOMEM;
-}
-
-/**
- * i40evf_clean_rx_ring - Free Rx buffers
- * @rx_ring: ring to be cleaned
- **/
-void i40evf_clean_rx_ring(struct i40e_ring *rx_ring)
-{
- unsigned long bi_size;
- u16 i;
-
- /* ring already cleared, nothing to do */
- if (!rx_ring->rx_bi)
- return;
-
- if (rx_ring->skb) {
- dev_kfree_skb(rx_ring->skb);
- rx_ring->skb = NULL;
- }
-
- /* Free all the Rx ring sk_buffs */
- for (i = 0; i < rx_ring->count; i++) {
- struct i40e_rx_buffer *rx_bi = &rx_ring->rx_bi[i];
-
- if (!rx_bi->page)
- continue;
-
- /* Invalidate cache lines that may have been written to by
- * device so that we avoid corrupting memory.
- */
- dma_sync_single_range_for_cpu(rx_ring->dev,
- rx_bi->dma,
- rx_bi->page_offset,
- rx_ring->rx_buf_len,
- DMA_FROM_DEVICE);
-
- /* free resources associated with mapping */
- dma_unmap_page_attrs(rx_ring->dev, rx_bi->dma,
- i40e_rx_pg_size(rx_ring),
- DMA_FROM_DEVICE,
- I40E_RX_DMA_ATTR);
-
- __page_frag_cache_drain(rx_bi->page, rx_bi->pagecnt_bias);
-
- rx_bi->page = NULL;
- rx_bi->page_offset = 0;
- }
-
- bi_size = sizeof(struct i40e_rx_buffer) * rx_ring->count;
- memset(rx_ring->rx_bi, 0, bi_size);
-
- /* Zero out the descriptor ring */
- memset(rx_ring->desc, 0, rx_ring->size);
-
- rx_ring->next_to_alloc = 0;
- rx_ring->next_to_clean = 0;
- rx_ring->next_to_use = 0;
-}
-
-/**
- * i40evf_free_rx_resources - Free Rx resources
- * @rx_ring: ring to clean the resources from
- *
- * Free all receive software resources
- **/
-void i40evf_free_rx_resources(struct i40e_ring *rx_ring)
-{
- i40evf_clean_rx_ring(rx_ring);
- kfree(rx_ring->rx_bi);
- rx_ring->rx_bi = NULL;
-
- if (rx_ring->desc) {
- dma_free_coherent(rx_ring->dev, rx_ring->size,
- rx_ring->desc, rx_ring->dma);
- rx_ring->desc = NULL;
- }
-}
-
-/**
- * i40evf_setup_rx_descriptors - Allocate Rx descriptors
- * @rx_ring: Rx descriptor ring (for a specific queue) to setup
- *
- * Returns 0 on success, negative on failure
- **/
-int i40evf_setup_rx_descriptors(struct i40e_ring *rx_ring)
-{
- struct device *dev = rx_ring->dev;
- int bi_size;
-
- /* warn if we are about to overwrite the pointer */
- WARN_ON(rx_ring->rx_bi);
- bi_size = sizeof(struct i40e_rx_buffer) * rx_ring->count;
- rx_ring->rx_bi = kzalloc(bi_size, GFP_KERNEL);
- if (!rx_ring->rx_bi)
- goto err;
-
- u64_stats_init(&rx_ring->syncp);
-
- /* Round up to nearest 4K */
- rx_ring->size = rx_ring->count * sizeof(union i40e_32byte_rx_desc);
- rx_ring->size = ALIGN(rx_ring->size, 4096);
- rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
- &rx_ring->dma, GFP_KERNEL);
-
- if (!rx_ring->desc) {
- dev_info(dev, "Unable to allocate memory for the Rx descriptor ring, size=%d\n",
- rx_ring->size);
- goto err;
- }
-
- rx_ring->next_to_alloc = 0;
- rx_ring->next_to_clean = 0;
- rx_ring->next_to_use = 0;
-
- return 0;
-err:
- kfree(rx_ring->rx_bi);
- rx_ring->rx_bi = NULL;
- return -ENOMEM;
-}
-
-/**
- * i40e_release_rx_desc - Store the new tail and head values
- * @rx_ring: ring to bump
- * @val: new head index
- **/
-static inline void i40e_release_rx_desc(struct i40e_ring *rx_ring, u32 val)
-{
- rx_ring->next_to_use = val;
-
- /* update next to alloc since we have filled the ring */
- rx_ring->next_to_alloc = val;
-
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64).
- */
- wmb();
- writel(val, rx_ring->tail);
-}
-
-/**
- * i40e_rx_offset - Return expected offset into page to access data
- * @rx_ring: Ring we are requesting offset of
- *
- * Returns the offset value for ring into the data buffer.
- */
-static inline unsigned int i40e_rx_offset(struct i40e_ring *rx_ring)
-{
- return ring_uses_build_skb(rx_ring) ? I40E_SKB_PAD : 0;
-}
-
-/**
- * i40e_alloc_mapped_page - recycle or make a new page
- * @rx_ring: ring to use
- * @bi: rx_buffer struct to modify
- *
- * Returns true if the page was successfully allocated or
- * reused.
- **/
-static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,
- struct i40e_rx_buffer *bi)
-{
- struct page *page = bi->page;
- dma_addr_t dma;
-
- /* since we are recycling buffers we should seldom need to alloc */
- if (likely(page)) {
- rx_ring->rx_stats.page_reuse_count++;
- return true;
- }
-
- /* alloc new page for storage */
- page = dev_alloc_pages(i40e_rx_pg_order(rx_ring));
- if (unlikely(!page)) {
- rx_ring->rx_stats.alloc_page_failed++;
- return false;
- }
-
- /* map page for use */
- dma = dma_map_page_attrs(rx_ring->dev, page, 0,
- i40e_rx_pg_size(rx_ring),
- DMA_FROM_DEVICE,
- I40E_RX_DMA_ATTR);
-
- /* if mapping failed free memory back to system since
- * there isn't much point in holding memory we can't use
- */
- if (dma_mapping_error(rx_ring->dev, dma)) {
- __free_pages(page, i40e_rx_pg_order(rx_ring));
- rx_ring->rx_stats.alloc_page_failed++;
- return false;
- }
-
- bi->dma = dma;
- bi->page = page;
- bi->page_offset = i40e_rx_offset(rx_ring);
-
- /* initialize pagecnt_bias to 1 representing we fully own page */
- bi->pagecnt_bias = 1;
-
- return true;
-}
-
-/**
- * i40e_receive_skb - Send a completed packet up the stack
- * @rx_ring: rx ring in play
- * @skb: packet to send up
- * @vlan_tag: vlan tag for packet
- **/
-static void i40e_receive_skb(struct i40e_ring *rx_ring,
- struct sk_buff *skb, u16 vlan_tag)
-{
- struct i40e_q_vector *q_vector = rx_ring->q_vector;
-
- if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
- (vlan_tag & VLAN_VID_MASK))
- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
-
- napi_gro_receive(&q_vector->napi, skb);
-}
-
-/**
- * i40evf_alloc_rx_buffers - Replace used receive buffers
- * @rx_ring: ring to place buffers on
- * @cleaned_count: number of buffers to replace
- *
- * Returns false if all allocations were successful, true if any fail
- **/
-bool i40evf_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
-{
- u16 ntu = rx_ring->next_to_use;
- union i40e_rx_desc *rx_desc;
- struct i40e_rx_buffer *bi;
-
- /* do nothing if no valid netdev defined */
- if (!rx_ring->netdev || !cleaned_count)
- return false;
-
- rx_desc = I40E_RX_DESC(rx_ring, ntu);
- bi = &rx_ring->rx_bi[ntu];
-
- do {
- if (!i40e_alloc_mapped_page(rx_ring, bi))
- goto no_buffers;
-
- /* sync the buffer for use by the device */
- dma_sync_single_range_for_device(rx_ring->dev, bi->dma,
- bi->page_offset,
- rx_ring->rx_buf_len,
- DMA_FROM_DEVICE);
-
- /* Refresh the desc even if buffer_addrs didn't change
- * because each write-back erases this info.
- */
- rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
-
- rx_desc++;
- bi++;
- ntu++;
- if (unlikely(ntu == rx_ring->count)) {
- rx_desc = I40E_RX_DESC(rx_ring, 0);
- bi = rx_ring->rx_bi;
- ntu = 0;
- }
-
- /* clear the status bits for the next_to_use descriptor */
- rx_desc->wb.qword1.status_error_len = 0;
-
- cleaned_count--;
- } while (cleaned_count);
-
- if (rx_ring->next_to_use != ntu)
- i40e_release_rx_desc(rx_ring, ntu);
-
- return false;
-
-no_buffers:
- if (rx_ring->next_to_use != ntu)
- i40e_release_rx_desc(rx_ring, ntu);
-
- /* make sure to come back via polling to try again after
- * allocation failure
- */
- return true;
-}
-
-/**
- * i40e_rx_checksum - Indicate in skb if hw indicated a good cksum
- * @vsi: the VSI we care about
- * @skb: skb currently being received and modified
- * @rx_desc: the receive descriptor
- **/
-static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
- struct sk_buff *skb,
- union i40e_rx_desc *rx_desc)
-{
- struct i40e_rx_ptype_decoded decoded;
- u32 rx_error, rx_status;
- bool ipv4, ipv6;
- u8 ptype;
- u64 qword;
-
- qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
- ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT;
- rx_error = (qword & I40E_RXD_QW1_ERROR_MASK) >>
- I40E_RXD_QW1_ERROR_SHIFT;
- rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
- I40E_RXD_QW1_STATUS_SHIFT;
- decoded = decode_rx_desc_ptype(ptype);
-
- skb->ip_summed = CHECKSUM_NONE;
-
- skb_checksum_none_assert(skb);
-
- /* Rx csum enabled and ip headers found? */
- if (!(vsi->netdev->features & NETIF_F_RXCSUM))
- return;
-
- /* did the hardware decode the packet and checksum? */
- if (!(rx_status & BIT(I40E_RX_DESC_STATUS_L3L4P_SHIFT)))
- return;
-
- /* both known and outer_ip must be set for the below code to work */
- if (!(decoded.known && decoded.outer_ip))
- return;
-
- ipv4 = (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP) &&
- (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV4);
- ipv6 = (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP) &&
- (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV6);
-
- if (ipv4 &&
- (rx_error & (BIT(I40E_RX_DESC_ERROR_IPE_SHIFT) |
- BIT(I40E_RX_DESC_ERROR_EIPE_SHIFT))))
- goto checksum_fail;
-
- /* likely incorrect csum if alternate IP extension headers found */
- if (ipv6 &&
- rx_status & BIT(I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
- /* don't increment checksum err here, non-fatal err */
- return;
-
- /* there was some L4 error, count error and punt packet to the stack */
- if (rx_error & BIT(I40E_RX_DESC_ERROR_L4E_SHIFT))
- goto checksum_fail;
-
- /* handle packets that were not able to be checksummed due
- * to arrival speed, in this case the stack can compute
- * the csum.
- */
- if (rx_error & BIT(I40E_RX_DESC_ERROR_PPRS_SHIFT))
- return;
-
- /* Only report checksum unnecessary for TCP, UDP, or SCTP */
- switch (decoded.inner_prot) {
- case I40E_RX_PTYPE_INNER_PROT_TCP:
- case I40E_RX_PTYPE_INNER_PROT_UDP:
- case I40E_RX_PTYPE_INNER_PROT_SCTP:
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- /* fall though */
- default:
- break;
- }
-
- return;
-
-checksum_fail:
- vsi->back->hw_csum_rx_error++;
-}
-
-/**
- * i40e_ptype_to_htype - get a hash type
- * @ptype: the ptype value from the descriptor
- *
- * Returns a hash type to be used by skb_set_hash
- **/
-static inline int i40e_ptype_to_htype(u8 ptype)
-{
- struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype);
-
- if (!decoded.known)
- return PKT_HASH_TYPE_NONE;
-
- if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
- decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4)
- return PKT_HASH_TYPE_L4;
- else if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
- decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3)
- return PKT_HASH_TYPE_L3;
- else
- return PKT_HASH_TYPE_L2;
-}
-
-/**
- * i40e_rx_hash - set the hash value in the skb
- * @ring: descriptor ring
- * @rx_desc: specific descriptor
- * @skb: skb currently being received and modified
- * @rx_ptype: Rx packet type
- **/
-static inline void i40e_rx_hash(struct i40e_ring *ring,
- union i40e_rx_desc *rx_desc,
- struct sk_buff *skb,
- u8 rx_ptype)
-{
- u32 hash;
- const __le64 rss_mask =
- cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
- I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
-
- if (ring->netdev->features & NETIF_F_RXHASH)
- return;
-
- if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
- hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
- skb_set_hash(skb, hash, i40e_ptype_to_htype(rx_ptype));
- }
-}
-
-/**
- * i40evf_process_skb_fields - Populate skb header fields from Rx descriptor
- * @rx_ring: rx descriptor ring packet is being transacted on
- * @rx_desc: pointer to the EOP Rx descriptor
- * @skb: pointer to current skb being populated
- * @rx_ptype: the packet type decoded by hardware
- *
- * This function checks the ring, descriptor, and packet information in
- * order to populate the hash, checksum, VLAN, protocol, and
- * other fields within the skb.
- **/
-static inline
-void i40evf_process_skb_fields(struct i40e_ring *rx_ring,
- union i40e_rx_desc *rx_desc, struct sk_buff *skb,
- u8 rx_ptype)
-{
- i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype);
-
- i40e_rx_checksum(rx_ring->vsi, skb, rx_desc);
-
- skb_record_rx_queue(skb, rx_ring->queue_index);
-
- /* modifies the skb - consumes the enet header */
- skb->protocol = eth_type_trans(skb, rx_ring->netdev);
-}
-
-/**
- * i40e_cleanup_headers - Correct empty headers
- * @rx_ring: rx descriptor ring packet is being transacted on
- * @skb: pointer to current skb being fixed
- *
- * Also address the case where we are pulling data in on pages only
- * and as such no data is present in the skb header.
- *
- * In addition if skb is not at least 60 bytes we need to pad it so that
- * it is large enough to qualify as a valid Ethernet frame.
- *
- * Returns true if an error was encountered and skb was freed.
- **/
-static bool i40e_cleanup_headers(struct i40e_ring *rx_ring, struct sk_buff *skb)
-{
- /* if eth_skb_pad returns an error the skb was freed */
- if (eth_skb_pad(skb))
- return true;
-
- return false;
-}
-
-/**
- * i40e_reuse_rx_page - page flip buffer and store it back on the ring
- * @rx_ring: rx descriptor ring to store buffers on
- * @old_buff: donor buffer to have page reused
- *
- * Synchronizes page for reuse by the adapter
- **/
-static void i40e_reuse_rx_page(struct i40e_ring *rx_ring,
- struct i40e_rx_buffer *old_buff)
-{
- struct i40e_rx_buffer *new_buff;
- u16 nta = rx_ring->next_to_alloc;
-
- new_buff = &rx_ring->rx_bi[nta];
-
- /* update, and store next to alloc */
- nta++;
- rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
-
- /* transfer page from old buffer to new buffer */
- new_buff->dma = old_buff->dma;
- new_buff->page = old_buff->page;
- new_buff->page_offset = old_buff->page_offset;
- new_buff->pagecnt_bias = old_buff->pagecnt_bias;
-}
-
-/**
- * i40e_page_is_reusable - check if any reuse is possible
- * @page: page struct to check
- *
- * A page is not reusable if it was allocated under low memory
- * conditions, or it's not in the same NUMA node as this CPU.
- */
-static inline bool i40e_page_is_reusable(struct page *page)
-{
- return (page_to_nid(page) == numa_mem_id()) &&
- !page_is_pfmemalloc(page);
-}
-
-/**
- * i40e_can_reuse_rx_page - Determine if this page can be reused by
- * the adapter for another receive
- *
- * @rx_buffer: buffer containing the page
- *
- * If page is reusable, rx_buffer->page_offset is adjusted to point to
- * an unused region in the page.
- *
- * For small pages, @truesize will be a constant value, half the size
- * of the memory at page. We'll attempt to alternate between high and
- * low halves of the page, with one half ready for use by the hardware
- * and the other half being consumed by the stack. We use the page
- * ref count to determine whether the stack has finished consuming the
- * portion of this page that was passed up with a previous packet. If
- * the page ref count is >1, we'll assume the "other" half page is
- * still busy, and this page cannot be reused.
- *
- * For larger pages, @truesize will be the actual space used by the
- * received packet (adjusted upward to an even multiple of the cache
- * line size). This will advance through the page by the amount
- * actually consumed by the received packets while there is still
- * space for a buffer. Each region of larger pages will be used at
- * most once, after which the page will not be reused.
- *
- * In either case, if the page is reusable its refcount is increased.
- **/
-static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer)
-{
- unsigned int pagecnt_bias = rx_buffer->pagecnt_bias;
- struct page *page = rx_buffer->page;
-
- /* Is any reuse possible? */
- if (unlikely(!i40e_page_is_reusable(page)))
- return false;
-
-#if (PAGE_SIZE < 8192)
- /* if we are only owner of page we can reuse it */
- if (unlikely((page_count(page) - pagecnt_bias) > 1))
- return false;
-#else
-#define I40E_LAST_OFFSET \
- (SKB_WITH_OVERHEAD(PAGE_SIZE) - I40E_RXBUFFER_2048)
- if (rx_buffer->page_offset > I40E_LAST_OFFSET)
- return false;
-#endif
-
- /* If we have drained the page fragment pool we need to update
- * the pagecnt_bias and page count so that we fully restock the
- * number of references the driver holds.
- */
- if (unlikely(!pagecnt_bias)) {
- page_ref_add(page, USHRT_MAX);
- rx_buffer->pagecnt_bias = USHRT_MAX;
- }
-
- return true;
-}
-
-/**
- * i40e_add_rx_frag - Add contents of Rx buffer to sk_buff
- * @rx_ring: rx descriptor ring to transact packets on
- * @rx_buffer: buffer containing page to add
- * @skb: sk_buff to place the data into
- * @size: packet length from rx_desc
- *
- * This function will add the data contained in rx_buffer->page to the skb.
- * It will just attach the page as a frag to the skb.
- *
- * The function will then update the page offset.
- **/
-static void i40e_add_rx_frag(struct i40e_ring *rx_ring,
- struct i40e_rx_buffer *rx_buffer,
- struct sk_buff *skb,
- unsigned int size)
-{
-#if (PAGE_SIZE < 8192)
- unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
-#else
- unsigned int truesize = SKB_DATA_ALIGN(size + i40e_rx_offset(rx_ring));
-#endif
-
- skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page,
- rx_buffer->page_offset, size, truesize);
-
- /* page is being used so we must update the page offset */
-#if (PAGE_SIZE < 8192)
- rx_buffer->page_offset ^= truesize;
-#else
- rx_buffer->page_offset += truesize;
-#endif
-}
-
-/**
- * i40e_get_rx_buffer - Fetch Rx buffer and synchronize data for use
- * @rx_ring: rx descriptor ring to transact packets on
- * @size: size of buffer to add to skb
- *
- * This function will pull an Rx buffer from the ring and synchronize it
- * for use by the CPU.
- */
-static struct i40e_rx_buffer *i40e_get_rx_buffer(struct i40e_ring *rx_ring,
- const unsigned int size)
-{
- struct i40e_rx_buffer *rx_buffer;
-
- rx_buffer = &rx_ring->rx_bi[rx_ring->next_to_clean];
- prefetchw(rx_buffer->page);
-
- /* we are reusing so sync this buffer for CPU use */
- dma_sync_single_range_for_cpu(rx_ring->dev,
- rx_buffer->dma,
- rx_buffer->page_offset,
- size,
- DMA_FROM_DEVICE);
-
- /* We have pulled a buffer for use, so decrement pagecnt_bias */
- rx_buffer->pagecnt_bias--;
-
- return rx_buffer;
-}
-
-/**
- * i40e_construct_skb - Allocate skb and populate it
- * @rx_ring: rx descriptor ring to transact packets on
- * @rx_buffer: rx buffer to pull data from
- * @size: size of buffer to add to skb
- *
- * This function allocates an skb. It then populates it with the page
- * data from the current receive descriptor, taking care to set up the
- * skb correctly.
- */
-static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring,
- struct i40e_rx_buffer *rx_buffer,
- unsigned int size)
-{
- void *va;
-#if (PAGE_SIZE < 8192)
- unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
-#else
- unsigned int truesize = SKB_DATA_ALIGN(size);
-#endif
- unsigned int headlen;
- struct sk_buff *skb;
-
- /* prefetch first cache line of first page */
- va = page_address(rx_buffer->page) + rx_buffer->page_offset;
- prefetch(va);
-#if L1_CACHE_BYTES < 128
- prefetch(va + L1_CACHE_BYTES);
-#endif
-
- /* allocate a skb to store the frags */
- skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
- I40E_RX_HDR_SIZE,
- GFP_ATOMIC | __GFP_NOWARN);
- if (unlikely(!skb))
- return NULL;
-
- /* Determine available headroom for copy */
- headlen = size;
- if (headlen > I40E_RX_HDR_SIZE)
- headlen = eth_get_headlen(va, I40E_RX_HDR_SIZE);
-
- /* align pull length to size of long to optimize memcpy performance */
- memcpy(__skb_put(skb, headlen), va, ALIGN(headlen, sizeof(long)));
-
- /* update all of the pointers */
- size -= headlen;
- if (size) {
- skb_add_rx_frag(skb, 0, rx_buffer->page,
- rx_buffer->page_offset + headlen,
- size, truesize);
-
- /* buffer is used by skb, update page_offset */
-#if (PAGE_SIZE < 8192)
- rx_buffer->page_offset ^= truesize;
-#else
- rx_buffer->page_offset += truesize;
-#endif
- } else {
- /* buffer is unused, reset bias back to rx_buffer */
- rx_buffer->pagecnt_bias++;
- }
-
- return skb;
-}
-
-/**
- * i40e_build_skb - Build skb around an existing buffer
- * @rx_ring: Rx descriptor ring to transact packets on
- * @rx_buffer: Rx buffer to pull data from
- * @size: size of buffer to add to skb
- *
- * This function builds an skb around an existing Rx buffer, taking care
- * to set up the skb correctly and avoid any memcpy overhead.
- */
-static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
- struct i40e_rx_buffer *rx_buffer,
- unsigned int size)
-{
- void *va;
-#if (PAGE_SIZE < 8192)
- unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
-#else
- unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
- SKB_DATA_ALIGN(I40E_SKB_PAD + size);
-#endif
- struct sk_buff *skb;
-
- /* prefetch first cache line of first page */
- va = page_address(rx_buffer->page) + rx_buffer->page_offset;
- prefetch(va);
-#if L1_CACHE_BYTES < 128
- prefetch(va + L1_CACHE_BYTES);
-#endif
- /* build an skb around the page buffer */
- skb = build_skb(va - I40E_SKB_PAD, truesize);
- if (unlikely(!skb))
- return NULL;
-
- /* update pointers within the skb to store the data */
- skb_reserve(skb, I40E_SKB_PAD);
- __skb_put(skb, size);
-
- /* buffer is used by skb, update page_offset */
-#if (PAGE_SIZE < 8192)
- rx_buffer->page_offset ^= truesize;
-#else
- rx_buffer->page_offset += truesize;
-#endif
-
- return skb;
-}
-
-/**
- * i40e_put_rx_buffer - Clean up used buffer and either recycle or free
- * @rx_ring: rx descriptor ring to transact packets on
- * @rx_buffer: rx buffer to pull data from
- *
- * This function will clean up the contents of the rx_buffer. It will
- * either recycle the buffer or unmap it and free the associated resources.
- */
-static void i40e_put_rx_buffer(struct i40e_ring *rx_ring,
- struct i40e_rx_buffer *rx_buffer)
-{
- if (i40e_can_reuse_rx_page(rx_buffer)) {
- /* hand second half of page back to the ring */
- i40e_reuse_rx_page(rx_ring, rx_buffer);
- rx_ring->rx_stats.page_reuse_count++;
- } else {
- /* we are not reusing the buffer so unmap it */
- dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma,
- i40e_rx_pg_size(rx_ring),
- DMA_FROM_DEVICE, I40E_RX_DMA_ATTR);
- __page_frag_cache_drain(rx_buffer->page,
- rx_buffer->pagecnt_bias);
- }
-
- /* clear contents of buffer_info */
- rx_buffer->page = NULL;
-}
-
-/**
- * i40e_is_non_eop - process handling of non-EOP buffers
- * @rx_ring: Rx ring being processed
- * @rx_desc: Rx descriptor for current buffer
- * @skb: Current socket buffer containing buffer in progress
- *
- * This function updates next to clean. If the buffer is an EOP buffer
- * this function exits returning false, otherwise it will place the
- * sk_buff in the next buffer to be chained and return true indicating
- * that this is in fact a non-EOP buffer.
- **/
-static bool i40e_is_non_eop(struct i40e_ring *rx_ring,
- union i40e_rx_desc *rx_desc,
- struct sk_buff *skb)
-{
- u32 ntc = rx_ring->next_to_clean + 1;
-
- /* fetch, update, and store next to clean */
- ntc = (ntc < rx_ring->count) ? ntc : 0;
- rx_ring->next_to_clean = ntc;
-
- prefetch(I40E_RX_DESC(rx_ring, ntc));
-
- /* if we are the last buffer then there is nothing else to do */
-#define I40E_RXD_EOF BIT(I40E_RX_DESC_STATUS_EOF_SHIFT)
- if (likely(i40e_test_staterr(rx_desc, I40E_RXD_EOF)))
- return false;
-
- rx_ring->rx_stats.non_eop_descs++;
-
- return true;
-}
-
-/**
- * i40e_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf
- * @rx_ring: rx descriptor ring to transact packets on
- * @budget: Total limit on number of packets to process
- *
- * This function provides a "bounce buffer" approach to Rx interrupt
- * processing. The advantage to this is that on systems that have
- * expensive overhead for IOMMU access this provides a means of avoiding
- * it by maintaining the mapping of the page to the system.
- *
- * Returns amount of work completed
- **/
-static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
-{
- unsigned int total_rx_bytes = 0, total_rx_packets = 0;
- struct sk_buff *skb = rx_ring->skb;
- u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
- bool failure = false;
-
- while (likely(total_rx_packets < (unsigned int)budget)) {
- struct i40e_rx_buffer *rx_buffer;
- union i40e_rx_desc *rx_desc;
- unsigned int size;
- u16 vlan_tag;
- u8 rx_ptype;
- u64 qword;
-
- /* return some buffers to hardware, one at a time is too slow */
- if (cleaned_count >= I40E_RX_BUFFER_WRITE) {
- failure = failure ||
- i40evf_alloc_rx_buffers(rx_ring, cleaned_count);
- cleaned_count = 0;
- }
-
- rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean);
-
- /* status_error_len will always be zero for unused descriptors
- * because it's cleared in cleanup, and overlaps with hdr_addr
- * which is always zero because packet split isn't used, if the
- * hardware wrote DD then the length will be non-zero
- */
- qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-
- /* This memory barrier is needed to keep us from reading
- * any other fields out of the rx_desc until we have
- * verified the descriptor has been written back.
- */
- dma_rmb();
-
- size = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) >>
- I40E_RXD_QW1_LENGTH_PBUF_SHIFT;
- if (!size)
- break;
-
- i40e_trace(clean_rx_irq, rx_ring, rx_desc, skb);
- rx_buffer = i40e_get_rx_buffer(rx_ring, size);
-
- /* retrieve a buffer from the ring */
- if (skb)
- i40e_add_rx_frag(rx_ring, rx_buffer, skb, size);
- else if (ring_uses_build_skb(rx_ring))
- skb = i40e_build_skb(rx_ring, rx_buffer, size);
- else
- skb = i40e_construct_skb(rx_ring, rx_buffer, size);
-
- /* exit if we failed to retrieve a buffer */
- if (!skb) {
- rx_ring->rx_stats.alloc_buff_failed++;
- rx_buffer->pagecnt_bias++;
- break;
- }
-
- i40e_put_rx_buffer(rx_ring, rx_buffer);
- cleaned_count++;
-
- if (i40e_is_non_eop(rx_ring, rx_desc, skb))
- continue;
-
- /* ERR_MASK will only have valid bits if EOP set, and
- * what we are doing here is actually checking
- * I40E_RX_DESC_ERROR_RXE_SHIFT, since it is the zeroth bit in
- * the error field
- */
- if (unlikely(i40e_test_staterr(rx_desc, BIT(I40E_RXD_QW1_ERROR_SHIFT)))) {
- dev_kfree_skb_any(skb);
- skb = NULL;
- continue;
- }
-
- if (i40e_cleanup_headers(rx_ring, skb)) {
- skb = NULL;
- continue;
- }
-
- /* probably a little skewed due to removing CRC */
- total_rx_bytes += skb->len;
-
- qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
- rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
- I40E_RXD_QW1_PTYPE_SHIFT;
-
- /* populate checksum, VLAN, and protocol */
- i40evf_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
-
-
- vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?
- le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;
-
- i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
- i40e_receive_skb(rx_ring, skb, vlan_tag);
- skb = NULL;
-
- /* update budget accounting */
- total_rx_packets++;
- }
-
- rx_ring->skb = skb;
-
- u64_stats_update_begin(&rx_ring->syncp);
- rx_ring->stats.packets += total_rx_packets;
- rx_ring->stats.bytes += total_rx_bytes;
- u64_stats_update_end(&rx_ring->syncp);
- rx_ring->q_vector->rx.total_packets += total_rx_packets;
- rx_ring->q_vector->rx.total_bytes += total_rx_bytes;
-
- /* guarantee a trip back through this routine if there was a failure */
- return failure ? budget : (int)total_rx_packets;
-}
-
-static inline u32 i40e_buildreg_itr(const int type, u16 itr)
-{
- u32 val;
-
- /* We don't bother with setting the CLEARPBA bit as the data sheet
- * points out doing so is "meaningless since it was already
- * auto-cleared". The auto-clearing happens when the interrupt is
- * asserted.
- *
- * Hardware errata 28 for also indicates that writing to a
- * xxINT_DYN_CTLx CSR with INTENA_MSK (bit 31) set to 0 will clear
- * an event in the PBA anyway so we need to rely on the automask
- * to hold pending events for us until the interrupt is re-enabled
- *
- * The itr value is reported in microseconds, and the register
- * value is recorded in 2 microsecond units. For this reason we
- * only need to shift by the interval shift - 1 instead of the
- * full value.
- */
- itr &= I40E_ITR_MASK;
-
- val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
- (type << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) |
- (itr << (I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT - 1));
-
- return val;
-}
-
-/* a small macro to shorten up some long lines */
-#define INTREG I40E_VFINT_DYN_CTLN1
-
-/* The act of updating the ITR will cause it to immediately trigger. In order
- * to prevent this from throwing off adaptive update statistics we defer the
- * update so that it can only happen so often. So after either Tx or Rx are
- * updated we make the adaptive scheme wait until either the ITR completely
- * expires via the next_update expiration or we have been through at least
- * 3 interrupts.
- */
-#define ITR_COUNTDOWN_START 3
-
-/**
- * i40e_update_enable_itr - Update itr and re-enable MSIX interrupt
- * @vsi: the VSI we care about
- * @q_vector: q_vector for which itr is being updated and interrupt enabled
- *
- **/
-static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
- struct i40e_q_vector *q_vector)
-{
- struct i40e_hw *hw = &vsi->back->hw;
- u32 intval;
-
- /* These will do nothing if dynamic updates are not enabled */
- i40e_update_itr(q_vector, &q_vector->tx);
- i40e_update_itr(q_vector, &q_vector->rx);
-
- /* This block of logic allows us to get away with only updating
- * one ITR value with each interrupt. The idea is to perform a
- * pseudo-lazy update with the following criteria.
- *
- * 1. Rx is given higher priority than Tx if both are in same state
- * 2. If we must reduce an ITR that is given highest priority.
- * 3. We then give priority to increasing ITR based on amount.
- */
- if (q_vector->rx.target_itr < q_vector->rx.current_itr) {
- /* Rx ITR needs to be reduced, this is highest priority */
- intval = i40e_buildreg_itr(I40E_RX_ITR,
- q_vector->rx.target_itr);
- q_vector->rx.current_itr = q_vector->rx.target_itr;
- q_vector->itr_countdown = ITR_COUNTDOWN_START;
- } else if ((q_vector->tx.target_itr < q_vector->tx.current_itr) ||
- ((q_vector->rx.target_itr - q_vector->rx.current_itr) <
- (q_vector->tx.target_itr - q_vector->tx.current_itr))) {
- /* Tx ITR needs to be reduced, this is second priority
- * Tx ITR needs to be increased more than Rx, fourth priority
- */
- intval = i40e_buildreg_itr(I40E_TX_ITR,
- q_vector->tx.target_itr);
- q_vector->tx.current_itr = q_vector->tx.target_itr;
- q_vector->itr_countdown = ITR_COUNTDOWN_START;
- } else if (q_vector->rx.current_itr != q_vector->rx.target_itr) {
- /* Rx ITR needs to be increased, third priority */
- intval = i40e_buildreg_itr(I40E_RX_ITR,
- q_vector->rx.target_itr);
- q_vector->rx.current_itr = q_vector->rx.target_itr;
- q_vector->itr_countdown = ITR_COUNTDOWN_START;
- } else {
- /* No ITR update, lowest priority */
- intval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
- if (q_vector->itr_countdown)
- q_vector->itr_countdown--;
- }
-
- if (!test_bit(__I40E_VSI_DOWN, vsi->state))
- wr32(hw, INTREG(q_vector->reg_idx), intval);
-}
-
-/**
- * i40evf_napi_poll - NAPI polling Rx/Tx cleanup routine
- * @napi: napi struct with our devices info in it
- * @budget: amount of work driver is allowed to do this pass, in packets
- *
- * This function will clean all queues associated with a q_vector.
- *
- * Returns the amount of work done
- **/
-int i40evf_napi_poll(struct napi_struct *napi, int budget)
-{
- struct i40e_q_vector *q_vector =
- container_of(napi, struct i40e_q_vector, napi);
- struct i40e_vsi *vsi = q_vector->vsi;
- struct i40e_ring *ring;
- bool clean_complete = true;
- bool arm_wb = false;
- int budget_per_ring;
- int work_done = 0;
-
- if (test_bit(__I40E_VSI_DOWN, vsi->state)) {
- napi_complete(napi);
- return 0;
- }
-
- /* Since the actual Tx work is minimal, we can give the Tx a larger
- * budget and be more aggressive about cleaning up the Tx descriptors.
- */
- i40e_for_each_ring(ring, q_vector->tx) {
- if (!i40e_clean_tx_irq(vsi, ring, budget)) {
- clean_complete = false;
- continue;
- }
- arm_wb |= ring->arm_wb;
- ring->arm_wb = false;
- }
-
- /* Handle case where we are called by netpoll with a budget of 0 */
- if (budget <= 0)
- goto tx_only;
-
- /* We attempt to distribute budget to each Rx queue fairly, but don't
- * allow the budget to go below 1 because that would exit polling early.
- */
- budget_per_ring = max(budget/q_vector->num_ringpairs, 1);
-
- i40e_for_each_ring(ring, q_vector->rx) {
- int cleaned = i40e_clean_rx_irq(ring, budget_per_ring);
-
- work_done += cleaned;
- /* if we clean as many as budgeted, we must not be done */
- if (cleaned >= budget_per_ring)
- clean_complete = false;
- }
-
- /* If work not completed, return budget and polling will return */
- if (!clean_complete) {
- int cpu_id = smp_processor_id();
-
- /* It is possible that the interrupt affinity has changed but,
- * if the cpu is pegged at 100%, polling will never exit while
- * traffic continues and the interrupt will be stuck on this
- * cpu. We check to make sure affinity is correct before we
- * continue to poll, otherwise we must stop polling so the
- * interrupt can move to the correct cpu.
- */
- if (!cpumask_test_cpu(cpu_id, &q_vector->affinity_mask)) {
- /* Tell napi that we are done polling */
- napi_complete_done(napi, work_done);
-
- /* Force an interrupt */
- i40evf_force_wb(vsi, q_vector);
-
- /* Return budget-1 so that polling stops */
- return budget - 1;
- }
-tx_only:
- if (arm_wb) {
- q_vector->tx.ring[0].tx_stats.tx_force_wb++;
- i40e_enable_wb_on_itr(vsi, q_vector);
- }
- return budget;
- }
-
- if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
- q_vector->arm_wb_state = false;
-
- /* Work is done so exit the polling mode and re-enable the interrupt */
- napi_complete_done(napi, work_done);
-
- i40e_update_enable_itr(vsi, q_vector);
-
- return min(work_done, budget - 1);
-}
-
-/**
- * i40evf_tx_prepare_vlan_flags - prepare generic TX VLAN tagging flags for HW
- * @skb: send buffer
- * @tx_ring: ring to send buffer on
- * @flags: the tx flags to be set
- *
- * Checks the skb and set up correspondingly several generic transmit flags
- * related to VLAN tagging for the HW, such as VLAN, DCB, etc.
- *
- * Returns error code indicate the frame should be dropped upon error and the
- * otherwise returns 0 to indicate the flags has been set properly.
- **/
-static inline int i40evf_tx_prepare_vlan_flags(struct sk_buff *skb,
- struct i40e_ring *tx_ring,
- u32 *flags)
-{
- __be16 protocol = skb->protocol;
- u32 tx_flags = 0;
-
- if (protocol == htons(ETH_P_8021Q) &&
- !(tx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) {
- /* When HW VLAN acceleration is turned off by the user the
- * stack sets the protocol to 8021q so that the driver
- * can take any steps required to support the SW only
- * VLAN handling. In our case the driver doesn't need
- * to take any further steps so just set the protocol
- * to the encapsulated ethertype.
- */
- skb->protocol = vlan_get_protocol(skb);
- goto out;
- }
-
- /* if we have a HW VLAN tag being added, default to the HW one */
- if (skb_vlan_tag_present(skb)) {
- tx_flags |= skb_vlan_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT;
- tx_flags |= I40E_TX_FLAGS_HW_VLAN;
- /* else if it is a SW VLAN, check the next protocol and store the tag */
- } else if (protocol == htons(ETH_P_8021Q)) {
- struct vlan_hdr *vhdr, _vhdr;
-
- vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr);
- if (!vhdr)
- return -EINVAL;
-
- protocol = vhdr->h_vlan_encapsulated_proto;
- tx_flags |= ntohs(vhdr->h_vlan_TCI) << I40E_TX_FLAGS_VLAN_SHIFT;
- tx_flags |= I40E_TX_FLAGS_SW_VLAN;
- }
-
-out:
- *flags = tx_flags;
- return 0;
-}
-
-/**
- * i40e_tso - set up the tso context descriptor
- * @first: pointer to first Tx buffer for xmit
- * @hdr_len: ptr to the size of the packet header
- * @cd_type_cmd_tso_mss: Quad Word 1
- *
- * Returns 0 if no TSO can happen, 1 if tso is going, or error
- **/
-static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
- u64 *cd_type_cmd_tso_mss)
-{
- struct sk_buff *skb = first->skb;
- u64 cd_cmd, cd_tso_len, cd_mss;
- union {
- struct iphdr *v4;
- struct ipv6hdr *v6;
- unsigned char *hdr;
- } ip;
- union {
- struct tcphdr *tcp;
- struct udphdr *udp;
- unsigned char *hdr;
- } l4;
- u32 paylen, l4_offset;
- u16 gso_segs, gso_size;
- int err;
-
- if (skb->ip_summed != CHECKSUM_PARTIAL)
- return 0;
-
- if (!skb_is_gso(skb))
- return 0;
-
- err = skb_cow_head(skb, 0);
- if (err < 0)
- return err;
-
- ip.hdr = skb_network_header(skb);
- l4.hdr = skb_transport_header(skb);
-
- /* initialize outer IP header fields */
- if (ip.v4->version == 4) {
- ip.v4->tot_len = 0;
- ip.v4->check = 0;
- } else {
- ip.v6->payload_len = 0;
- }
-
- if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
- SKB_GSO_GRE_CSUM |
- SKB_GSO_IPXIP4 |
- SKB_GSO_IPXIP6 |
- SKB_GSO_UDP_TUNNEL |
- SKB_GSO_UDP_TUNNEL_CSUM)) {
- if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
- (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)) {
- l4.udp->len = 0;
-
- /* determine offset of outer transport header */
- l4_offset = l4.hdr - skb->data;
-
- /* remove payload length from outer checksum */
- paylen = skb->len - l4_offset;
- csum_replace_by_diff(&l4.udp->check,
- (__force __wsum)htonl(paylen));
- }
-
- /* reset pointers to inner headers */
- ip.hdr = skb_inner_network_header(skb);
- l4.hdr = skb_inner_transport_header(skb);
-
- /* initialize inner IP header fields */
- if (ip.v4->version == 4) {
- ip.v4->tot_len = 0;
- ip.v4->check = 0;
- } else {
- ip.v6->payload_len = 0;
- }
- }
-
- /* determine offset of inner transport header */
- l4_offset = l4.hdr - skb->data;
-
- /* remove payload length from inner checksum */
- paylen = skb->len - l4_offset;
- csum_replace_by_diff(&l4.tcp->check, (__force __wsum)htonl(paylen));
-
- /* compute length of segmentation header */
- *hdr_len = (l4.tcp->doff * 4) + l4_offset;
-
- /* pull values out of skb_shinfo */
- gso_size = skb_shinfo(skb)->gso_size;
- gso_segs = skb_shinfo(skb)->gso_segs;
-
- /* update GSO size and bytecount with header size */
- first->gso_segs = gso_segs;
- first->bytecount += (first->gso_segs - 1) * *hdr_len;
-
- /* find the field values */
- cd_cmd = I40E_TX_CTX_DESC_TSO;
- cd_tso_len = skb->len - *hdr_len;
- cd_mss = gso_size;
- *cd_type_cmd_tso_mss |= (cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |
- (cd_tso_len << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
- (cd_mss << I40E_TXD_CTX_QW1_MSS_SHIFT);
- return 1;
-}
-
-/**
- * i40e_tx_enable_csum - Enable Tx checksum offloads
- * @skb: send buffer
- * @tx_flags: pointer to Tx flags currently set
- * @td_cmd: Tx descriptor command bits to set
- * @td_offset: Tx descriptor header offsets to set
- * @tx_ring: Tx descriptor ring
- * @cd_tunneling: ptr to context desc bits
- **/
-static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
- u32 *td_cmd, u32 *td_offset,
- struct i40e_ring *tx_ring,
- u32 *cd_tunneling)
-{
- union {
- struct iphdr *v4;
- struct ipv6hdr *v6;
- unsigned char *hdr;
- } ip;
- union {
- struct tcphdr *tcp;
- struct udphdr *udp;
- unsigned char *hdr;
- } l4;
- unsigned char *exthdr;
- u32 offset, cmd = 0;
- __be16 frag_off;
- u8 l4_proto = 0;
-
- if (skb->ip_summed != CHECKSUM_PARTIAL)
- return 0;
-
- ip.hdr = skb_network_header(skb);
- l4.hdr = skb_transport_header(skb);
-
- /* compute outer L2 header size */
- offset = ((ip.hdr - skb->data) / 2) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
-
- if (skb->encapsulation) {
- u32 tunnel = 0;
- /* define outer network header type */
- if (*tx_flags & I40E_TX_FLAGS_IPV4) {
- tunnel |= (*tx_flags & I40E_TX_FLAGS_TSO) ?
- I40E_TX_CTX_EXT_IP_IPV4 :
- I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM;
-
- l4_proto = ip.v4->protocol;
- } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
- tunnel |= I40E_TX_CTX_EXT_IP_IPV6;
-
- exthdr = ip.hdr + sizeof(*ip.v6);
- l4_proto = ip.v6->nexthdr;
- if (l4.hdr != exthdr)
- ipv6_skip_exthdr(skb, exthdr - skb->data,
- &l4_proto, &frag_off);
- }
-
- /* define outer transport */
- switch (l4_proto) {
- case IPPROTO_UDP:
- tunnel |= I40E_TXD_CTX_UDP_TUNNELING;
- *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
- break;
- case IPPROTO_GRE:
- tunnel |= I40E_TXD_CTX_GRE_TUNNELING;
- *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
- break;
- case IPPROTO_IPIP:
- case IPPROTO_IPV6:
- *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
- l4.hdr = skb_inner_network_header(skb);
- break;
- default:
- if (*tx_flags & I40E_TX_FLAGS_TSO)
- return -1;
-
- skb_checksum_help(skb);
- return 0;
- }
-
- /* compute outer L3 header size */
- tunnel |= ((l4.hdr - ip.hdr) / 4) <<
- I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT;
-
- /* switch IP header pointer from outer to inner header */
- ip.hdr = skb_inner_network_header(skb);
-
- /* compute tunnel header size */
- tunnel |= ((ip.hdr - l4.hdr) / 2) <<
- I40E_TXD_CTX_QW0_NATLEN_SHIFT;
-
- /* indicate if we need to offload outer UDP header */
- if ((*tx_flags & I40E_TX_FLAGS_TSO) &&
- !(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
- (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM))
- tunnel |= I40E_TXD_CTX_QW0_L4T_CS_MASK;
-
- /* record tunnel offload values */
- *cd_tunneling |= tunnel;
-
- /* switch L4 header pointer from outer to inner */
- l4.hdr = skb_inner_transport_header(skb);
- l4_proto = 0;
-
- /* reset type as we transition from outer to inner headers */
- *tx_flags &= ~(I40E_TX_FLAGS_IPV4 | I40E_TX_FLAGS_IPV6);
- if (ip.v4->version == 4)
- *tx_flags |= I40E_TX_FLAGS_IPV4;
- if (ip.v6->version == 6)
- *tx_flags |= I40E_TX_FLAGS_IPV6;
- }
-
- /* Enable IP checksum offloads */
- if (*tx_flags & I40E_TX_FLAGS_IPV4) {
- l4_proto = ip.v4->protocol;
- /* the stack computes the IP header already, the only time we
- * need the hardware to recompute it is in the case of TSO.
- */
- cmd |= (*tx_flags & I40E_TX_FLAGS_TSO) ?
- I40E_TX_DESC_CMD_IIPT_IPV4_CSUM :
- I40E_TX_DESC_CMD_IIPT_IPV4;
- } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
- cmd |= I40E_TX_DESC_CMD_IIPT_IPV6;
-
- exthdr = ip.hdr + sizeof(*ip.v6);
- l4_proto = ip.v6->nexthdr;
- if (l4.hdr != exthdr)
- ipv6_skip_exthdr(skb, exthdr - skb->data,
- &l4_proto, &frag_off);
- }
-
- /* compute inner L3 header size */
- offset |= ((l4.hdr - ip.hdr) / 4) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT;
-
- /* Enable L4 checksum offloads */
- switch (l4_proto) {
- case IPPROTO_TCP:
- /* enable checksum offloads */
- cmd |= I40E_TX_DESC_CMD_L4T_EOFT_TCP;
- offset |= l4.tcp->doff << I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
- break;
- case IPPROTO_SCTP:
- /* enable SCTP checksum offload */
- cmd |= I40E_TX_DESC_CMD_L4T_EOFT_SCTP;
- offset |= (sizeof(struct sctphdr) >> 2) <<
- I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
- break;
- case IPPROTO_UDP:
- /* enable UDP checksum offload */
- cmd |= I40E_TX_DESC_CMD_L4T_EOFT_UDP;
- offset |= (sizeof(struct udphdr) >> 2) <<
- I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
- break;
- default:
- if (*tx_flags & I40E_TX_FLAGS_TSO)
- return -1;
- skb_checksum_help(skb);
- return 0;
- }
-
- *td_cmd |= cmd;
- *td_offset |= offset;
-
- return 1;
-}
-
-/**
- * i40e_create_tx_ctx Build the Tx context descriptor
- * @tx_ring: ring to create the descriptor on
- * @cd_type_cmd_tso_mss: Quad Word 1
- * @cd_tunneling: Quad Word 0 - bits 0-31
- * @cd_l2tag2: Quad Word 0 - bits 32-63
- **/
-static void i40e_create_tx_ctx(struct i40e_ring *tx_ring,
- const u64 cd_type_cmd_tso_mss,
- const u32 cd_tunneling, const u32 cd_l2tag2)
-{
- struct i40e_tx_context_desc *context_desc;
- int i = tx_ring->next_to_use;
-
- if ((cd_type_cmd_tso_mss == I40E_TX_DESC_DTYPE_CONTEXT) &&
- !cd_tunneling && !cd_l2tag2)
- return;
-
- /* grab the next descriptor */
- context_desc = I40E_TX_CTXTDESC(tx_ring, i);
-
- i++;
- tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
-
- /* cpu_to_le32 and assign to struct fields */
- context_desc->tunneling_params = cpu_to_le32(cd_tunneling);
- context_desc->l2tag2 = cpu_to_le16(cd_l2tag2);
- context_desc->rsvd = cpu_to_le16(0);
- context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
-}
-
-/**
- * __i40evf_chk_linearize - Check if there are more than 8 buffers per packet
- * @skb: send buffer
- *
- * Note: Our HW can't DMA more than 8 buffers to build a packet on the wire
- * and so we need to figure out the cases where we need to linearize the skb.
- *
- * For TSO we need to count the TSO header and segment payload separately.
- * As such we need to check cases where we have 7 fragments or more as we
- * can potentially require 9 DMA transactions, 1 for the TSO header, 1 for
- * the segment payload in the first descriptor, and another 7 for the
- * fragments.
- **/
-bool __i40evf_chk_linearize(struct sk_buff *skb)
-{
- const struct skb_frag_struct *frag, *stale;
- int nr_frags, sum;
-
- /* no need to check if number of frags is less than 7 */
- nr_frags = skb_shinfo(skb)->nr_frags;
- if (nr_frags < (I40E_MAX_BUFFER_TXD - 1))
- return false;
-
- /* We need to walk through the list and validate that each group
- * of 6 fragments totals at least gso_size.
- */
- nr_frags -= I40E_MAX_BUFFER_TXD - 2;
- frag = &skb_shinfo(skb)->frags[0];
-
- /* Initialize size to the negative value of gso_size minus 1. We
- * use this as the worst case scenerio in which the frag ahead
- * of us only provides one byte which is why we are limited to 6
- * descriptors for a single transmit as the header and previous
- * fragment are already consuming 2 descriptors.
- */
- sum = 1 - skb_shinfo(skb)->gso_size;
-
- /* Add size of frags 0 through 4 to create our initial sum */
- sum += skb_frag_size(frag++);
- sum += skb_frag_size(frag++);
- sum += skb_frag_size(frag++);
- sum += skb_frag_size(frag++);
- sum += skb_frag_size(frag++);
-
- /* Walk through fragments adding latest fragment, testing it, and
- * then removing stale fragments from the sum.
- */
- for (stale = &skb_shinfo(skb)->frags[0];; stale++) {
- int stale_size = skb_frag_size(stale);
-
- sum += skb_frag_size(frag++);
-
- /* The stale fragment may present us with a smaller
- * descriptor than the actual fragment size. To account
- * for that we need to remove all the data on the front and
- * figure out what the remainder would be in the last
- * descriptor associated with the fragment.
- */
- if (stale_size > I40E_MAX_DATA_PER_TXD) {
- int align_pad = -(stale->page_offset) &
- (I40E_MAX_READ_REQ_SIZE - 1);
-
- sum -= align_pad;
- stale_size -= align_pad;
-
- do {
- sum -= I40E_MAX_DATA_PER_TXD_ALIGNED;
- stale_size -= I40E_MAX_DATA_PER_TXD_ALIGNED;
- } while (stale_size > I40E_MAX_DATA_PER_TXD);
- }
-
- /* if sum is negative we failed to make sufficient progress */
- if (sum < 0)
- return true;
-
- if (!nr_frags--)
- break;
-
- sum -= stale_size;
- }
-
- return false;
-}
-
-/**
- * __i40evf_maybe_stop_tx - 2nd level check for tx stop conditions
- * @tx_ring: the ring to be checked
- * @size: the size buffer we want to assure is available
- *
- * Returns -EBUSY if a stop is needed, else 0
- **/
-int __i40evf_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
-{
- netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
- /* Memory barrier before checking head and tail */
- smp_mb();
-
- /* Check again in a case another CPU has just made room available. */
- if (likely(I40E_DESC_UNUSED(tx_ring) < size))
- return -EBUSY;
-
- /* A reprieve! - use start_queue because it doesn't call schedule */
- netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
- ++tx_ring->tx_stats.restart_queue;
- return 0;
-}
-
-/**
- * i40evf_tx_map - Build the Tx descriptor
- * @tx_ring: ring to send buffer on
- * @skb: send buffer
- * @first: first buffer info buffer to use
- * @tx_flags: collected send information
- * @hdr_len: size of the packet header
- * @td_cmd: the command field in the descriptor
- * @td_offset: offset for checksum or crc
- **/
-static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
- struct i40e_tx_buffer *first, u32 tx_flags,
- const u8 hdr_len, u32 td_cmd, u32 td_offset)
-{
- unsigned int data_len = skb->data_len;
- unsigned int size = skb_headlen(skb);
- struct skb_frag_struct *frag;
- struct i40e_tx_buffer *tx_bi;
- struct i40e_tx_desc *tx_desc;
- u16 i = tx_ring->next_to_use;
- u32 td_tag = 0;
- dma_addr_t dma;
-
- if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
- td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
- td_tag = (tx_flags & I40E_TX_FLAGS_VLAN_MASK) >>
- I40E_TX_FLAGS_VLAN_SHIFT;
- }
-
- first->tx_flags = tx_flags;
-
- dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
-
- tx_desc = I40E_TX_DESC(tx_ring, i);
- tx_bi = first;
-
- for (frag = &skb_shinfo(skb)->frags[0];; frag++) {
- unsigned int max_data = I40E_MAX_DATA_PER_TXD_ALIGNED;
-
- if (dma_mapping_error(tx_ring->dev, dma))
- goto dma_error;
-
- /* record length, and DMA address */
- dma_unmap_len_set(tx_bi, len, size);
- dma_unmap_addr_set(tx_bi, dma, dma);
-
- /* align size to end of page */
- max_data += -dma & (I40E_MAX_READ_REQ_SIZE - 1);
- tx_desc->buffer_addr = cpu_to_le64(dma);
-
- while (unlikely(size > I40E_MAX_DATA_PER_TXD)) {
- tx_desc->cmd_type_offset_bsz =
- build_ctob(td_cmd, td_offset,
- max_data, td_tag);
-
- tx_desc++;
- i++;
-
- if (i == tx_ring->count) {
- tx_desc = I40E_TX_DESC(tx_ring, 0);
- i = 0;
- }
-
- dma += max_data;
- size -= max_data;
-
- max_data = I40E_MAX_DATA_PER_TXD_ALIGNED;
- tx_desc->buffer_addr = cpu_to_le64(dma);
- }
-
- if (likely(!data_len))
- break;
-
- tx_desc->cmd_type_offset_bsz = build_ctob(td_cmd, td_offset,
- size, td_tag);
-
- tx_desc++;
- i++;
-
- if (i == tx_ring->count) {
- tx_desc = I40E_TX_DESC(tx_ring, 0);
- i = 0;
- }
-
- size = skb_frag_size(frag);
- data_len -= size;
-
- dma = skb_frag_dma_map(tx_ring->dev, frag, 0, size,
- DMA_TO_DEVICE);
-
- tx_bi = &tx_ring->tx_bi[i];
- }
-
- netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
-
- i++;
- if (i == tx_ring->count)
- i = 0;
-
- tx_ring->next_to_use = i;
-
- i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
-
- /* write last descriptor with RS and EOP bits */
- td_cmd |= I40E_TXD_CMD;
- tx_desc->cmd_type_offset_bsz =
- build_ctob(td_cmd, td_offset, size, td_tag);
-
- /* Force memory writes to complete before letting h/w know there
- * are new descriptors to fetch.
- *
- * We also use this memory barrier to make certain all of the
- * status bits have been updated before next_to_watch is written.
- */
- wmb();
-
- /* set next_to_watch value indicating a packet is present */
- first->next_to_watch = tx_desc;
-
- /* notify HW of packet */
- if (netif_xmit_stopped(txring_txq(tx_ring)) || !skb->xmit_more) {
- writel(i, tx_ring->tail);
-
- /* we need this if more than one processor can write to our tail
- * at a time, it synchronizes IO on IA64/Altix systems
- */
- mmiowb();
- }
-
- return;
-
-dma_error:
- dev_info(tx_ring->dev, "TX DMA map failed\n");
-
- /* clear dma mappings for failed tx_bi map */
- for (;;) {
- tx_bi = &tx_ring->tx_bi[i];
- i40e_unmap_and_free_tx_resource(tx_ring, tx_bi);
- if (tx_bi == first)
- break;
- if (i == 0)
- i = tx_ring->count;
- i--;
- }
-
- tx_ring->next_to_use = i;
-}
-
-/**
- * i40e_xmit_frame_ring - Sends buffer on Tx ring
- * @skb: send buffer
- * @tx_ring: ring to send buffer on
- *
- * Returns NETDEV_TX_OK if sent, else an error code
- **/
-static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
- struct i40e_ring *tx_ring)
-{
- u64 cd_type_cmd_tso_mss = I40E_TX_DESC_DTYPE_CONTEXT;
- u32 cd_tunneling = 0, cd_l2tag2 = 0;
- struct i40e_tx_buffer *first;
- u32 td_offset = 0;
- u32 tx_flags = 0;
- __be16 protocol;
- u32 td_cmd = 0;
- u8 hdr_len = 0;
- int tso, count;
-
- /* prefetch the data, we'll need it later */
- prefetch(skb->data);
-
- i40e_trace(xmit_frame_ring, skb, tx_ring);
-
- count = i40e_xmit_descriptor_count(skb);
- if (i40e_chk_linearize(skb, count)) {
- if (__skb_linearize(skb)) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
- count = i40e_txd_use_count(skb->len);
- tx_ring->tx_stats.tx_linearize++;
- }
-
- /* need: 1 descriptor per page * PAGE_SIZE/I40E_MAX_DATA_PER_TXD,
- * + 1 desc for skb_head_len/I40E_MAX_DATA_PER_TXD,
- * + 4 desc gap to avoid the cache line where head is,
- * + 1 desc for context descriptor,
- * otherwise try next time
- */
- if (i40e_maybe_stop_tx(tx_ring, count + 4 + 1)) {
- tx_ring->tx_stats.tx_busy++;
- return NETDEV_TX_BUSY;
- }
-
- /* record the location of the first descriptor for this packet */
- first = &tx_ring->tx_bi[tx_ring->next_to_use];
- first->skb = skb;
- first->bytecount = skb->len;
- first->gso_segs = 1;
-
- /* prepare the xmit flags */
- if (i40evf_tx_prepare_vlan_flags(skb, tx_ring, &tx_flags))
- goto out_drop;
-
- /* obtain protocol of skb */
- protocol = vlan_get_protocol(skb);
-
- /* setup IPv4/IPv6 offloads */
- if (protocol == htons(ETH_P_IP))
- tx_flags |= I40E_TX_FLAGS_IPV4;
- else if (protocol == htons(ETH_P_IPV6))
- tx_flags |= I40E_TX_FLAGS_IPV6;
-
- tso = i40e_tso(first, &hdr_len, &cd_type_cmd_tso_mss);
-
- if (tso < 0)
- goto out_drop;
- else if (tso)
- tx_flags |= I40E_TX_FLAGS_TSO;
-
- /* Always offload the checksum, since it's in the data descriptor */
- tso = i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
- tx_ring, &cd_tunneling);
- if (tso < 0)
- goto out_drop;
-
- skb_tx_timestamp(skb);
-
- /* always enable CRC insertion offload */
- td_cmd |= I40E_TX_DESC_CMD_ICRC;
-
- i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss,
- cd_tunneling, cd_l2tag2);
-
- i40evf_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
- td_cmd, td_offset);
-
- return NETDEV_TX_OK;
-
-out_drop:
- i40e_trace(xmit_frame_ring_drop, first->skb, tx_ring);
- dev_kfree_skb_any(first->skb);
- first->skb = NULL;
- return NETDEV_TX_OK;
-}
-
-/**
- * i40evf_xmit_frame - Selects the correct VSI and Tx queue to send buffer
- * @skb: send buffer
- * @netdev: network interface device structure
- *
- * Returns NETDEV_TX_OK if sent, else an error code
- **/
-netdev_tx_t i40evf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- struct i40e_ring *tx_ring = &adapter->tx_rings[skb->queue_mapping];
-
- /* hardware can't handle really short frames, hardware padding works
- * beyond this point
- */
- if (unlikely(skb->len < I40E_MIN_TX_LEN)) {
- if (skb_pad(skb, I40E_MIN_TX_LEN - skb->len))
- return NETDEV_TX_OK;
- skb->len = I40E_MIN_TX_LEN;
- skb_set_tail_pointer(skb, I40E_MIN_TX_LEN);
- }
-
- return i40e_xmit_frame_ring(skb, tx_ring);
-}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
deleted file mode 100644
index 3b5a63b3236e..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
+++ /dev/null
@@ -1,524 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_TXRX_H_
-#define _I40E_TXRX_H_
-
-/* Interrupt Throttling and Rate Limiting Goodies */
-#define I40E_DEFAULT_IRQ_WORK 256
-
-/* The datasheet for the X710 and XL710 indicate that the maximum value for
- * the ITR is 8160usec which is then called out as 0xFF0 with a 2usec
- * resolution. 8160 is 0x1FE0 when written out in hex. So instead of storing
- * the register value which is divided by 2 lets use the actual values and
- * avoid an excessive amount of translation.
- */
-#define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */
-#define I40E_ITR_MASK 0x1FFE /* mask for ITR register value */
-#define I40E_MIN_ITR 2 /* reg uses 2 usec resolution */
-#define I40E_ITR_100K 10 /* all values below must be even */
-#define I40E_ITR_50K 20
-#define I40E_ITR_20K 50
-#define I40E_ITR_18K 60
-#define I40E_ITR_8K 122
-#define I40E_MAX_ITR 8160 /* maximum value as per datasheet */
-#define ITR_TO_REG(setting) ((setting) & ~I40E_ITR_DYNAMIC)
-#define ITR_REG_ALIGN(setting) __ALIGN_MASK(setting, ~I40E_ITR_MASK)
-#define ITR_IS_DYNAMIC(setting) (!!((setting) & I40E_ITR_DYNAMIC))
-
-#define I40E_ITR_RX_DEF (I40E_ITR_20K | I40E_ITR_DYNAMIC)
-#define I40E_ITR_TX_DEF (I40E_ITR_20K | I40E_ITR_DYNAMIC)
-
-/* 0x40 is the enable bit for interrupt rate limiting, and must be set if
- * the value of the rate limit is non-zero
- */
-#define INTRL_ENA BIT(6)
-#define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */
-#define INTRL_REG_TO_USEC(intrl) ((intrl & ~INTRL_ENA) << 2)
-#define INTRL_USEC_TO_REG(set) ((set) ? ((set) >> 2) | INTRL_ENA : 0)
-#define I40E_INTRL_8K 125 /* 8000 ints/sec */
-#define I40E_INTRL_62K 16 /* 62500 ints/sec */
-#define I40E_INTRL_83K 12 /* 83333 ints/sec */
-
-#define I40E_QUEUE_END_OF_LIST 0x7FF
-
-/* this enum matches hardware bits and is meant to be used by DYN_CTLN
- * registers and QINT registers or more generally anywhere in the manual
- * mentioning ITR_INDX, ITR_NONE cannot be used as an index 'n' into any
- * register but instead is a special value meaning "don't update" ITR0/1/2.
- */
-enum i40e_dyn_idx_t {
- I40E_IDX_ITR0 = 0,
- I40E_IDX_ITR1 = 1,
- I40E_IDX_ITR2 = 2,
- I40E_ITR_NONE = 3 /* ITR_NONE must not be used as an index */
-};
-
-/* these are indexes into ITRN registers */
-#define I40E_RX_ITR I40E_IDX_ITR0
-#define I40E_TX_ITR I40E_IDX_ITR1
-#define I40E_PE_ITR I40E_IDX_ITR2
-
-/* Supported RSS offloads */
-#define I40E_DEFAULT_RSS_HENA ( \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
- BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
- BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6) | \
- BIT_ULL(I40E_FILTER_PCTYPE_L2_PAYLOAD))
-
-#define I40E_DEFAULT_RSS_HENA_EXPANDED (I40E_DEFAULT_RSS_HENA | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
- BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP))
-
-/* Supported Rx Buffer Sizes (a multiple of 128) */
-#define I40E_RXBUFFER_256 256
-#define I40E_RXBUFFER_1536 1536 /* 128B aligned standard Ethernet frame */
-#define I40E_RXBUFFER_2048 2048
-#define I40E_RXBUFFER_3072 3072 /* Used for large frames w/ padding */
-#define I40E_MAX_RXBUFFER 9728 /* largest size for single descriptor */
-
-/* NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN means we
- * reserve 2 more, and skb_shared_info adds an additional 384 bytes more,
- * this adds up to 512 bytes of extra data meaning the smallest allocation
- * we could have is 1K.
- * i.e. RXBUFFER_256 --> 960 byte skb (size-1024 slab)
- * i.e. RXBUFFER_512 --> 1216 byte skb (size-2048 slab)
- */
-#define I40E_RX_HDR_SIZE I40E_RXBUFFER_256
-#define I40E_PACKET_HDR_PAD (ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2))
-#define i40e_rx_desc i40e_32byte_rx_desc
-
-#define I40E_RX_DMA_ATTR \
- (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
-
-/* Attempt to maximize the headroom available for incoming frames. We
- * use a 2K buffer for receives and need 1536/1534 to store the data for
- * the frame. This leaves us with 512 bytes of room. From that we need
- * to deduct the space needed for the shared info and the padding needed
- * to IP align the frame.
- *
- * Note: For cache line sizes 256 or larger this value is going to end
- * up negative. In these cases we should fall back to the legacy
- * receive path.
- */
-#if (PAGE_SIZE < 8192)
-#define I40E_2K_TOO_SMALL_WITH_PADDING \
-((NET_SKB_PAD + I40E_RXBUFFER_1536) > SKB_WITH_OVERHEAD(I40E_RXBUFFER_2048))
-
-static inline int i40e_compute_pad(int rx_buf_len)
-{
- int page_size, pad_size;
-
- page_size = ALIGN(rx_buf_len, PAGE_SIZE / 2);
- pad_size = SKB_WITH_OVERHEAD(page_size) - rx_buf_len;
-
- return pad_size;
-}
-
-static inline int i40e_skb_pad(void)
-{
- int rx_buf_len;
-
- /* If a 2K buffer cannot handle a standard Ethernet frame then
- * optimize padding for a 3K buffer instead of a 1.5K buffer.
- *
- * For a 3K buffer we need to add enough padding to allow for
- * tailroom due to NET_IP_ALIGN possibly shifting us out of
- * cache-line alignment.
- */
- if (I40E_2K_TOO_SMALL_WITH_PADDING)
- rx_buf_len = I40E_RXBUFFER_3072 + SKB_DATA_ALIGN(NET_IP_ALIGN);
- else
- rx_buf_len = I40E_RXBUFFER_1536;
-
- /* if needed make room for NET_IP_ALIGN */
- rx_buf_len -= NET_IP_ALIGN;
-
- return i40e_compute_pad(rx_buf_len);
-}
-
-#define I40E_SKB_PAD i40e_skb_pad()
-#else
-#define I40E_2K_TOO_SMALL_WITH_PADDING false
-#define I40E_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
-#endif
-
-/**
- * i40e_test_staterr - tests bits in Rx descriptor status and error fields
- * @rx_desc: pointer to receive descriptor (in le64 format)
- * @stat_err_bits: value to mask
- *
- * This function does some fast chicanery in order to return the
- * value of the mask which is really only used for boolean tests.
- * The status_error_len doesn't need to be shifted because it begins
- * at offset zero.
- */
-static inline bool i40e_test_staterr(union i40e_rx_desc *rx_desc,
- const u64 stat_err_bits)
-{
- return !!(rx_desc->wb.qword1.status_error_len &
- cpu_to_le64(stat_err_bits));
-}
-
-/* How many Rx Buffers do we bundle into one write to the hardware ? */
-#define I40E_RX_BUFFER_WRITE 32 /* Must be power of 2 */
-#define I40E_RX_INCREMENT(r, i) \
- do { \
- (i)++; \
- if ((i) == (r)->count) \
- i = 0; \
- r->next_to_clean = i; \
- } while (0)
-
-#define I40E_RX_NEXT_DESC(r, i, n) \
- do { \
- (i)++; \
- if ((i) == (r)->count) \
- i = 0; \
- (n) = I40E_RX_DESC((r), (i)); \
- } while (0)
-
-#define I40E_RX_NEXT_DESC_PREFETCH(r, i, n) \
- do { \
- I40E_RX_NEXT_DESC((r), (i), (n)); \
- prefetch((n)); \
- } while (0)
-
-#define I40E_MAX_BUFFER_TXD 8
-#define I40E_MIN_TX_LEN 17
-
-/* The size limit for a transmit buffer in a descriptor is (16K - 1).
- * In order to align with the read requests we will align the value to
- * the nearest 4K which represents our maximum read request size.
- */
-#define I40E_MAX_READ_REQ_SIZE 4096
-#define I40E_MAX_DATA_PER_TXD (16 * 1024 - 1)
-#define I40E_MAX_DATA_PER_TXD_ALIGNED \
- (I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1))
-
-/**
- * i40e_txd_use_count - estimate the number of descriptors needed for Tx
- * @size: transmit request size in bytes
- *
- * Due to hardware alignment restrictions (4K alignment), we need to
- * assume that we can have no more than 12K of data per descriptor, even
- * though each descriptor can take up to 16K - 1 bytes of aligned memory.
- * Thus, we need to divide by 12K. But division is slow! Instead,
- * we decompose the operation into shifts and one relatively cheap
- * multiply operation.
- *
- * To divide by 12K, we first divide by 4K, then divide by 3:
- * To divide by 4K, shift right by 12 bits
- * To divide by 3, multiply by 85, then divide by 256
- * (Divide by 256 is done by shifting right by 8 bits)
- * Finally, we add one to round up. Because 256 isn't an exact multiple of
- * 3, we'll underestimate near each multiple of 12K. This is actually more
- * accurate as we have 4K - 1 of wiggle room that we can fit into the last
- * segment. For our purposes this is accurate out to 1M which is orders of
- * magnitude greater than our largest possible GSO size.
- *
- * This would then be implemented as:
- * return (((size >> 12) * 85) >> 8) + 1;
- *
- * Since multiplication and division are commutative, we can reorder
- * operations into:
- * return ((size * 85) >> 20) + 1;
- */
-static inline unsigned int i40e_txd_use_count(unsigned int size)
-{
- return ((size * 85) >> 20) + 1;
-}
-
-/* Tx Descriptors needed, worst case */
-#define DESC_NEEDED (MAX_SKB_FRAGS + 6)
-#define I40E_MIN_DESC_PENDING 4
-
-#define I40E_TX_FLAGS_HW_VLAN BIT(1)
-#define I40E_TX_FLAGS_SW_VLAN BIT(2)
-#define I40E_TX_FLAGS_TSO BIT(3)
-#define I40E_TX_FLAGS_IPV4 BIT(4)
-#define I40E_TX_FLAGS_IPV6 BIT(5)
-#define I40E_TX_FLAGS_FCCRC BIT(6)
-#define I40E_TX_FLAGS_FSO BIT(7)
-#define I40E_TX_FLAGS_FD_SB BIT(9)
-#define I40E_TX_FLAGS_VXLAN_TUNNEL BIT(10)
-#define I40E_TX_FLAGS_VLAN_MASK 0xffff0000
-#define I40E_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000
-#define I40E_TX_FLAGS_VLAN_PRIO_SHIFT 29
-#define I40E_TX_FLAGS_VLAN_SHIFT 16
-
-struct i40e_tx_buffer {
- struct i40e_tx_desc *next_to_watch;
- union {
- struct sk_buff *skb;
- void *raw_buf;
- };
- unsigned int bytecount;
- unsigned short gso_segs;
-
- DEFINE_DMA_UNMAP_ADDR(dma);
- DEFINE_DMA_UNMAP_LEN(len);
- u32 tx_flags;
-};
-
-struct i40e_rx_buffer {
- dma_addr_t dma;
- struct page *page;
-#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
- __u32 page_offset;
-#else
- __u16 page_offset;
-#endif
- __u16 pagecnt_bias;
-};
-
-struct i40e_queue_stats {
- u64 packets;
- u64 bytes;
-};
-
-struct i40e_tx_queue_stats {
- u64 restart_queue;
- u64 tx_busy;
- u64 tx_done_old;
- u64 tx_linearize;
- u64 tx_force_wb;
- int prev_pkt_ctr;
- u64 tx_lost_interrupt;
-};
-
-struct i40e_rx_queue_stats {
- u64 non_eop_descs;
- u64 alloc_page_failed;
- u64 alloc_buff_failed;
- u64 page_reuse_count;
- u64 realloc_count;
-};
-
-enum i40e_ring_state_t {
- __I40E_TX_FDIR_INIT_DONE,
- __I40E_TX_XPS_INIT_DONE,
- __I40E_RING_STATE_NBITS /* must be last */
-};
-
-/* some useful defines for virtchannel interface, which
- * is the only remaining user of header split
- */
-#define I40E_RX_DTYPE_NO_SPLIT 0
-#define I40E_RX_DTYPE_HEADER_SPLIT 1
-#define I40E_RX_DTYPE_SPLIT_ALWAYS 2
-#define I40E_RX_SPLIT_L2 0x1
-#define I40E_RX_SPLIT_IP 0x2
-#define I40E_RX_SPLIT_TCP_UDP 0x4
-#define I40E_RX_SPLIT_SCTP 0x8
-
-/* struct that defines a descriptor ring, associated with a VSI */
-struct i40e_ring {
- struct i40e_ring *next; /* pointer to next ring in q_vector */
- void *desc; /* Descriptor ring memory */
- struct device *dev; /* Used for DMA mapping */
- struct net_device *netdev; /* netdev ring maps to */
- union {
- struct i40e_tx_buffer *tx_bi;
- struct i40e_rx_buffer *rx_bi;
- };
- DECLARE_BITMAP(state, __I40E_RING_STATE_NBITS);
- u16 queue_index; /* Queue number of ring */
- u8 dcb_tc; /* Traffic class of ring */
- u8 __iomem *tail;
-
- /* high bit set means dynamic, use accessors routines to read/write.
- * hardware only supports 2us resolution for the ITR registers.
- * these values always store the USER setting, and must be converted
- * before programming to a register.
- */
- u16 itr_setting;
-
- u16 count; /* Number of descriptors */
- u16 reg_idx; /* HW register index of the ring */
- u16 rx_buf_len;
-
- /* used in interrupt processing */
- u16 next_to_use;
- u16 next_to_clean;
-
- u8 atr_sample_rate;
- u8 atr_count;
-
- bool ring_active; /* is ring online or not */
- bool arm_wb; /* do something to arm write back */
- u8 packet_stride;
-
- u16 flags;
-#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
-#define I40E_RXR_FLAGS_BUILD_SKB_ENABLED BIT(1)
-
- /* stats structs */
- struct i40e_queue_stats stats;
- struct u64_stats_sync syncp;
- union {
- struct i40e_tx_queue_stats tx_stats;
- struct i40e_rx_queue_stats rx_stats;
- };
-
- unsigned int size; /* length of descriptor ring in bytes */
- dma_addr_t dma; /* physical address of ring */
-
- struct i40e_vsi *vsi; /* Backreference to associated VSI */
- struct i40e_q_vector *q_vector; /* Backreference to associated vector */
-
- struct rcu_head rcu; /* to avoid race on free */
- u16 next_to_alloc;
- struct sk_buff *skb; /* When i40evf_clean_rx_ring_irq() must
- * return before it sees the EOP for
- * the current packet, we save that skb
- * here and resume receiving this
- * packet the next time
- * i40evf_clean_rx_ring_irq() is called
- * for this ring.
- */
-} ____cacheline_internodealigned_in_smp;
-
-static inline bool ring_uses_build_skb(struct i40e_ring *ring)
-{
- return !!(ring->flags & I40E_RXR_FLAGS_BUILD_SKB_ENABLED);
-}
-
-static inline void set_ring_build_skb_enabled(struct i40e_ring *ring)
-{
- ring->flags |= I40E_RXR_FLAGS_BUILD_SKB_ENABLED;
-}
-
-static inline void clear_ring_build_skb_enabled(struct i40e_ring *ring)
-{
- ring->flags &= ~I40E_RXR_FLAGS_BUILD_SKB_ENABLED;
-}
-
-#define I40E_ITR_ADAPTIVE_MIN_INC 0x0002
-#define I40E_ITR_ADAPTIVE_MIN_USECS 0x0002
-#define I40E_ITR_ADAPTIVE_MAX_USECS 0x007e
-#define I40E_ITR_ADAPTIVE_LATENCY 0x8000
-#define I40E_ITR_ADAPTIVE_BULK 0x0000
-#define ITR_IS_BULK(x) (!((x) & I40E_ITR_ADAPTIVE_LATENCY))
-
-struct i40e_ring_container {
- struct i40e_ring *ring; /* pointer to linked list of ring(s) */
- unsigned long next_update; /* jiffies value of next update */
- unsigned int total_bytes; /* total bytes processed this int */
- unsigned int total_packets; /* total packets processed this int */
- u16 count;
- u16 target_itr; /* target ITR setting for ring(s) */
- u16 current_itr; /* current ITR setting for ring(s) */
-};
-
-/* iterator for handling rings in ring container */
-#define i40e_for_each_ring(pos, head) \
- for (pos = (head).ring; pos != NULL; pos = pos->next)
-
-static inline unsigned int i40e_rx_pg_order(struct i40e_ring *ring)
-{
-#if (PAGE_SIZE < 8192)
- if (ring->rx_buf_len > (PAGE_SIZE / 2))
- return 1;
-#endif
- return 0;
-}
-
-#define i40e_rx_pg_size(_ring) (PAGE_SIZE << i40e_rx_pg_order(_ring))
-
-bool i40evf_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count);
-netdev_tx_t i40evf_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
-void i40evf_clean_tx_ring(struct i40e_ring *tx_ring);
-void i40evf_clean_rx_ring(struct i40e_ring *rx_ring);
-int i40evf_setup_tx_descriptors(struct i40e_ring *tx_ring);
-int i40evf_setup_rx_descriptors(struct i40e_ring *rx_ring);
-void i40evf_free_tx_resources(struct i40e_ring *tx_ring);
-void i40evf_free_rx_resources(struct i40e_ring *rx_ring);
-int i40evf_napi_poll(struct napi_struct *napi, int budget);
-void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector);
-u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw);
-void i40evf_detect_recover_hung(struct i40e_vsi *vsi);
-int __i40evf_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
-bool __i40evf_chk_linearize(struct sk_buff *skb);
-
-/**
- * i40e_xmit_descriptor_count - calculate number of Tx descriptors needed
- * @skb: send buffer
- * @tx_ring: ring to send buffer on
- *
- * Returns number of data descriptors needed for this skb. Returns 0 to indicate
- * there is not enough descriptors available in this ring since we need at least
- * one descriptor.
- **/
-static inline int i40e_xmit_descriptor_count(struct sk_buff *skb)
-{
- const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
- unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
- int count = 0, size = skb_headlen(skb);
-
- for (;;) {
- count += i40e_txd_use_count(size);
-
- if (!nr_frags--)
- break;
-
- size = skb_frag_size(frag++);
- }
-
- return count;
-}
-
-/**
- * i40e_maybe_stop_tx - 1st level check for Tx stop conditions
- * @tx_ring: the ring to be checked
- * @size: the size buffer we want to assure is available
- *
- * Returns 0 if stop is not needed
- **/
-static inline int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
-{
- if (likely(I40E_DESC_UNUSED(tx_ring) >= size))
- return 0;
- return __i40evf_maybe_stop_tx(tx_ring, size);
-}
-
-/**
- * i40e_chk_linearize - Check if there are more than 8 fragments per packet
- * @skb: send buffer
- * @count: number of buffers used
- *
- * Note: Our HW can't scatter-gather more than 8 fragments to build
- * a packet on the wire and so we need to figure out the cases where we
- * need to linearize the skb.
- **/
-static inline bool i40e_chk_linearize(struct sk_buff *skb, int count)
-{
- /* Both TSO and single send will work if count is less than 8 */
- if (likely(count < I40E_MAX_BUFFER_TXD))
- return false;
-
- if (skb_is_gso(skb))
- return __i40evf_chk_linearize(skb);
-
- /* we can support up to 8 data buffers for a single send */
- return count != I40E_MAX_BUFFER_TXD;
-}
-/**
- * @ring: Tx ring to find the netdev equivalent of
- **/
-static inline struct netdev_queue *txring_txq(const struct i40e_ring *ring)
-{
- return netdev_get_tx_queue(ring->netdev, ring->queue_index);
-}
-#endif /* _I40E_TXRX_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
deleted file mode 100644
index 094387db3c11..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ /dev/null
@@ -1,1496 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40E_TYPE_H_
-#define _I40E_TYPE_H_
-
-#include "i40e_status.h"
-#include "i40e_osdep.h"
-#include "i40e_register.h"
-#include "i40e_adminq.h"
-#include "i40e_hmc.h"
-#include "i40e_lan_hmc.h"
-#include "i40e_devids.h"
-
-/* I40E_MASK is a macro used on 32 bit registers */
-#define I40E_MASK(mask, shift) ((u32)(mask) << (shift))
-
-#define I40E_MAX_VSI_QP 16
-#define I40E_MAX_VF_VSI 3
-#define I40E_MAX_CHAINED_RX_BUFFERS 5
-#define I40E_MAX_PF_UDP_OFFLOAD_PORTS 16
-
-/* Max default timeout in ms, */
-#define I40E_MAX_NVM_TIMEOUT 18000
-
-/* Max timeout in ms for the phy to respond */
-#define I40E_MAX_PHY_TIMEOUT 500
-
-/* Switch from ms to the 1usec global time (this is the GTIME resolution) */
-#define I40E_MS_TO_GTIME(time) ((time) * 1000)
-
-/* forward declaration */
-struct i40e_hw;
-typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *);
-
-/* Data type manipulation macros. */
-
-#define I40E_DESC_UNUSED(R) \
- ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
- (R)->next_to_clean - (R)->next_to_use - 1)
-
-/* bitfields for Tx queue mapping in QTX_CTL */
-#define I40E_QTX_CTL_VF_QUEUE 0x0
-#define I40E_QTX_CTL_VM_QUEUE 0x1
-#define I40E_QTX_CTL_PF_QUEUE 0x2
-
-/* debug masks - set these bits in hw->debug_mask to control output */
-enum i40e_debug_mask {
- I40E_DEBUG_INIT = 0x00000001,
- I40E_DEBUG_RELEASE = 0x00000002,
-
- I40E_DEBUG_LINK = 0x00000010,
- I40E_DEBUG_PHY = 0x00000020,
- I40E_DEBUG_HMC = 0x00000040,
- I40E_DEBUG_NVM = 0x00000080,
- I40E_DEBUG_LAN = 0x00000100,
- I40E_DEBUG_FLOW = 0x00000200,
- I40E_DEBUG_DCB = 0x00000400,
- I40E_DEBUG_DIAG = 0x00000800,
- I40E_DEBUG_FD = 0x00001000,
- I40E_DEBUG_PACKAGE = 0x00002000,
-
- I40E_DEBUG_AQ_MESSAGE = 0x01000000,
- I40E_DEBUG_AQ_DESCRIPTOR = 0x02000000,
- I40E_DEBUG_AQ_DESC_BUFFER = 0x04000000,
- I40E_DEBUG_AQ_COMMAND = 0x06000000,
- I40E_DEBUG_AQ = 0x0F000000,
-
- I40E_DEBUG_USER = 0xF0000000,
-
- I40E_DEBUG_ALL = 0xFFFFFFFF
-};
-
-/* These are structs for managing the hardware information and the operations.
- * The structures of function pointers are filled out at init time when we
- * know for sure exactly which hardware we're working with. This gives us the
- * flexibility of using the same main driver code but adapting to slightly
- * different hardware needs as new parts are developed. For this architecture,
- * the Firmware and AdminQ are intended to insulate the driver from most of the
- * future changes, but these structures will also do part of the job.
- */
-enum i40e_mac_type {
- I40E_MAC_UNKNOWN = 0,
- I40E_MAC_XL710,
- I40E_MAC_VF,
- I40E_MAC_X722,
- I40E_MAC_X722_VF,
- I40E_MAC_GENERIC,
-};
-
-enum i40e_media_type {
- I40E_MEDIA_TYPE_UNKNOWN = 0,
- I40E_MEDIA_TYPE_FIBER,
- I40E_MEDIA_TYPE_BASET,
- I40E_MEDIA_TYPE_BACKPLANE,
- I40E_MEDIA_TYPE_CX4,
- I40E_MEDIA_TYPE_DA,
- I40E_MEDIA_TYPE_VIRTUAL
-};
-
-enum i40e_fc_mode {
- I40E_FC_NONE = 0,
- I40E_FC_RX_PAUSE,
- I40E_FC_TX_PAUSE,
- I40E_FC_FULL,
- I40E_FC_PFC,
- I40E_FC_DEFAULT
-};
-
-enum i40e_set_fc_aq_failures {
- I40E_SET_FC_AQ_FAIL_NONE = 0,
- I40E_SET_FC_AQ_FAIL_GET = 1,
- I40E_SET_FC_AQ_FAIL_SET = 2,
- I40E_SET_FC_AQ_FAIL_UPDATE = 4,
- I40E_SET_FC_AQ_FAIL_SET_UPDATE = 6
-};
-
-enum i40e_vsi_type {
- I40E_VSI_MAIN = 0,
- I40E_VSI_VMDQ1 = 1,
- I40E_VSI_VMDQ2 = 2,
- I40E_VSI_CTRL = 3,
- I40E_VSI_FCOE = 4,
- I40E_VSI_MIRROR = 5,
- I40E_VSI_SRIOV = 6,
- I40E_VSI_FDIR = 7,
- I40E_VSI_TYPE_UNKNOWN
-};
-
-enum i40e_queue_type {
- I40E_QUEUE_TYPE_RX = 0,
- I40E_QUEUE_TYPE_TX,
- I40E_QUEUE_TYPE_PE_CEQ,
- I40E_QUEUE_TYPE_UNKNOWN
-};
-
-struct i40e_link_status {
- enum i40e_aq_phy_type phy_type;
- enum i40e_aq_link_speed link_speed;
- u8 link_info;
- u8 an_info;
- u8 req_fec_info;
- u8 fec_info;
- u8 ext_info;
- u8 loopback;
- /* is Link Status Event notification to SW enabled */
- bool lse_enable;
- u16 max_frame_size;
- bool crc_enable;
- u8 pacing;
- u8 requested_speeds;
- u8 module_type[3];
- /* 1st byte: module identifier */
-#define I40E_MODULE_TYPE_SFP 0x03
-#define I40E_MODULE_TYPE_QSFP 0x0D
- /* 2nd byte: ethernet compliance codes for 10/40G */
-#define I40E_MODULE_TYPE_40G_ACTIVE 0x01
-#define I40E_MODULE_TYPE_40G_LR4 0x02
-#define I40E_MODULE_TYPE_40G_SR4 0x04
-#define I40E_MODULE_TYPE_40G_CR4 0x08
-#define I40E_MODULE_TYPE_10G_BASE_SR 0x10
-#define I40E_MODULE_TYPE_10G_BASE_LR 0x20
-#define I40E_MODULE_TYPE_10G_BASE_LRM 0x40
-#define I40E_MODULE_TYPE_10G_BASE_ER 0x80
- /* 3rd byte: ethernet compliance codes for 1G */
-#define I40E_MODULE_TYPE_1000BASE_SX 0x01
-#define I40E_MODULE_TYPE_1000BASE_LX 0x02
-#define I40E_MODULE_TYPE_1000BASE_CX 0x04
-#define I40E_MODULE_TYPE_1000BASE_T 0x08
-};
-
-struct i40e_phy_info {
- struct i40e_link_status link_info;
- struct i40e_link_status link_info_old;
- bool get_link_info;
- enum i40e_media_type media_type;
- /* all the phy types the NVM is capable of */
- u64 phy_types;
-};
-
-#define I40E_CAP_PHY_TYPE_SGMII BIT_ULL(I40E_PHY_TYPE_SGMII)
-#define I40E_CAP_PHY_TYPE_1000BASE_KX BIT_ULL(I40E_PHY_TYPE_1000BASE_KX)
-#define I40E_CAP_PHY_TYPE_10GBASE_KX4 BIT_ULL(I40E_PHY_TYPE_10GBASE_KX4)
-#define I40E_CAP_PHY_TYPE_10GBASE_KR BIT_ULL(I40E_PHY_TYPE_10GBASE_KR)
-#define I40E_CAP_PHY_TYPE_40GBASE_KR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_KR4)
-#define I40E_CAP_PHY_TYPE_XAUI BIT_ULL(I40E_PHY_TYPE_XAUI)
-#define I40E_CAP_PHY_TYPE_XFI BIT_ULL(I40E_PHY_TYPE_XFI)
-#define I40E_CAP_PHY_TYPE_SFI BIT_ULL(I40E_PHY_TYPE_SFI)
-#define I40E_CAP_PHY_TYPE_XLAUI BIT_ULL(I40E_PHY_TYPE_XLAUI)
-#define I40E_CAP_PHY_TYPE_XLPPI BIT_ULL(I40E_PHY_TYPE_XLPPI)
-#define I40E_CAP_PHY_TYPE_40GBASE_CR4_CU BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4_CU)
-#define I40E_CAP_PHY_TYPE_10GBASE_CR1_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1_CU)
-#define I40E_CAP_PHY_TYPE_10GBASE_AOC BIT_ULL(I40E_PHY_TYPE_10GBASE_AOC)
-#define I40E_CAP_PHY_TYPE_40GBASE_AOC BIT_ULL(I40E_PHY_TYPE_40GBASE_AOC)
-#define I40E_CAP_PHY_TYPE_100BASE_TX BIT_ULL(I40E_PHY_TYPE_100BASE_TX)
-#define I40E_CAP_PHY_TYPE_1000BASE_T BIT_ULL(I40E_PHY_TYPE_1000BASE_T)
-#define I40E_CAP_PHY_TYPE_10GBASE_T BIT_ULL(I40E_PHY_TYPE_10GBASE_T)
-#define I40E_CAP_PHY_TYPE_10GBASE_SR BIT_ULL(I40E_PHY_TYPE_10GBASE_SR)
-#define I40E_CAP_PHY_TYPE_10GBASE_LR BIT_ULL(I40E_PHY_TYPE_10GBASE_LR)
-#define I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_SFPP_CU)
-#define I40E_CAP_PHY_TYPE_10GBASE_CR1 BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1)
-#define I40E_CAP_PHY_TYPE_40GBASE_CR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4)
-#define I40E_CAP_PHY_TYPE_40GBASE_SR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_SR4)
-#define I40E_CAP_PHY_TYPE_40GBASE_LR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_LR4)
-#define I40E_CAP_PHY_TYPE_1000BASE_SX BIT_ULL(I40E_PHY_TYPE_1000BASE_SX)
-#define I40E_CAP_PHY_TYPE_1000BASE_LX BIT_ULL(I40E_PHY_TYPE_1000BASE_LX)
-#define I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL \
- BIT_ULL(I40E_PHY_TYPE_1000BASE_T_OPTICAL)
-#define I40E_CAP_PHY_TYPE_20GBASE_KR2 BIT_ULL(I40E_PHY_TYPE_20GBASE_KR2)
-/* Defining the macro I40E_TYPE_OFFSET to implement a bit shift for some
- * PHY types. There is an unused bit (31) in the I40E_CAP_PHY_TYPE_* bit
- * fields but no corresponding gap in the i40e_aq_phy_type enumeration. So,
- * a shift is needed to adjust for this with values larger than 31. The
- * only affected values are I40E_PHY_TYPE_25GBASE_*.
- */
-#define I40E_PHY_TYPE_OFFSET 1
-#define I40E_CAP_PHY_TYPE_25GBASE_KR BIT_ULL(I40E_PHY_TYPE_25GBASE_KR + \
- I40E_PHY_TYPE_OFFSET)
-#define I40E_CAP_PHY_TYPE_25GBASE_CR BIT_ULL(I40E_PHY_TYPE_25GBASE_CR + \
- I40E_PHY_TYPE_OFFSET)
-#define I40E_CAP_PHY_TYPE_25GBASE_SR BIT_ULL(I40E_PHY_TYPE_25GBASE_SR + \
- I40E_PHY_TYPE_OFFSET)
-#define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \
- I40E_PHY_TYPE_OFFSET)
-#define I40E_HW_CAP_MAX_GPIO 30
-/* Capabilities of a PF or a VF or the whole device */
-struct i40e_hw_capabilities {
- u32 switch_mode;
-#define I40E_NVM_IMAGE_TYPE_EVB 0x0
-#define I40E_NVM_IMAGE_TYPE_CLOUD 0x2
-#define I40E_NVM_IMAGE_TYPE_UDP_CLOUD 0x3
-
- u32 management_mode;
- u32 mng_protocols_over_mctp;
-#define I40E_MNG_PROTOCOL_PLDM 0x2
-#define I40E_MNG_PROTOCOL_OEM_COMMANDS 0x4
-#define I40E_MNG_PROTOCOL_NCSI 0x8
- u32 npar_enable;
- u32 os2bmc;
- u32 valid_functions;
- bool sr_iov_1_1;
- bool vmdq;
- bool evb_802_1_qbg; /* Edge Virtual Bridging */
- bool evb_802_1_qbh; /* Bridge Port Extension */
- bool dcb;
- bool fcoe;
- bool iscsi; /* Indicates iSCSI enabled */
- bool flex10_enable;
- bool flex10_capable;
- u32 flex10_mode;
-#define I40E_FLEX10_MODE_UNKNOWN 0x0
-#define I40E_FLEX10_MODE_DCC 0x1
-#define I40E_FLEX10_MODE_DCI 0x2
-
- u32 flex10_status;
-#define I40E_FLEX10_STATUS_DCC_ERROR 0x1
-#define I40E_FLEX10_STATUS_VC_MODE 0x2
-
- bool sec_rev_disabled;
- bool update_disabled;
-#define I40E_NVM_MGMT_SEC_REV_DISABLED 0x1
-#define I40E_NVM_MGMT_UPDATE_DISABLED 0x2
-
- bool mgmt_cem;
- bool ieee_1588;
- bool iwarp;
- bool fd;
- u32 fd_filters_guaranteed;
- u32 fd_filters_best_effort;
- bool rss;
- u32 rss_table_size;
- u32 rss_table_entry_width;
- bool led[I40E_HW_CAP_MAX_GPIO];
- bool sdp[I40E_HW_CAP_MAX_GPIO];
- u32 nvm_image_type;
- u32 num_flow_director_filters;
- u32 num_vfs;
- u32 vf_base_id;
- u32 num_vsis;
- u32 num_rx_qp;
- u32 num_tx_qp;
- u32 base_queue;
- u32 num_msix_vectors;
- u32 num_msix_vectors_vf;
- u32 led_pin_num;
- u32 sdp_pin_num;
- u32 mdio_port_num;
- u32 mdio_port_mode;
- u8 rx_buf_chain_len;
- u32 enabled_tcmap;
- u32 maxtc;
- u64 wr_csr_prot;
-};
-
-struct i40e_mac_info {
- enum i40e_mac_type type;
- u8 addr[ETH_ALEN];
- u8 perm_addr[ETH_ALEN];
- u8 san_addr[ETH_ALEN];
- u16 max_fcoeq;
-};
-
-enum i40e_aq_resources_ids {
- I40E_NVM_RESOURCE_ID = 1
-};
-
-enum i40e_aq_resource_access_type {
- I40E_RESOURCE_READ = 1,
- I40E_RESOURCE_WRITE
-};
-
-struct i40e_nvm_info {
- u64 hw_semaphore_timeout; /* usec global time (GTIME resolution) */
- u32 timeout; /* [ms] */
- u16 sr_size; /* Shadow RAM size in words */
- bool blank_nvm_mode; /* is NVM empty (no FW present)*/
- u16 version; /* NVM package version */
- u32 eetrack; /* NVM data version */
- u32 oem_ver; /* OEM version info */
-};
-
-/* definitions used in NVM update support */
-
-enum i40e_nvmupd_cmd {
- I40E_NVMUPD_INVALID,
- I40E_NVMUPD_READ_CON,
- I40E_NVMUPD_READ_SNT,
- I40E_NVMUPD_READ_LCB,
- I40E_NVMUPD_READ_SA,
- I40E_NVMUPD_WRITE_ERA,
- I40E_NVMUPD_WRITE_CON,
- I40E_NVMUPD_WRITE_SNT,
- I40E_NVMUPD_WRITE_LCB,
- I40E_NVMUPD_WRITE_SA,
- I40E_NVMUPD_CSUM_CON,
- I40E_NVMUPD_CSUM_SA,
- I40E_NVMUPD_CSUM_LCB,
- I40E_NVMUPD_STATUS,
- I40E_NVMUPD_EXEC_AQ,
- I40E_NVMUPD_GET_AQ_RESULT,
- I40E_NVMUPD_GET_AQ_EVENT,
-};
-
-enum i40e_nvmupd_state {
- I40E_NVMUPD_STATE_INIT,
- I40E_NVMUPD_STATE_READING,
- I40E_NVMUPD_STATE_WRITING,
- I40E_NVMUPD_STATE_INIT_WAIT,
- I40E_NVMUPD_STATE_WRITE_WAIT,
- I40E_NVMUPD_STATE_ERROR
-};
-
-/* nvm_access definition and its masks/shifts need to be accessible to
- * application, core driver, and shared code. Where is the right file?
- */
-#define I40E_NVM_READ 0xB
-#define I40E_NVM_WRITE 0xC
-
-#define I40E_NVM_MOD_PNT_MASK 0xFF
-
-#define I40E_NVM_TRANS_SHIFT 8
-#define I40E_NVM_TRANS_MASK (0xf << I40E_NVM_TRANS_SHIFT)
-#define I40E_NVM_PRESERVATION_FLAGS_SHIFT 12
-#define I40E_NVM_PRESERVATION_FLAGS_MASK \
- (0x3 << I40E_NVM_PRESERVATION_FLAGS_SHIFT)
-#define I40E_NVM_PRESERVATION_FLAGS_SELECTED 0x01
-#define I40E_NVM_PRESERVATION_FLAGS_ALL 0x02
-#define I40E_NVM_CON 0x0
-#define I40E_NVM_SNT 0x1
-#define I40E_NVM_LCB 0x2
-#define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB)
-#define I40E_NVM_ERA 0x4
-#define I40E_NVM_CSUM 0x8
-#define I40E_NVM_AQE 0xe
-#define I40E_NVM_EXEC 0xf
-
-#define I40E_NVM_ADAPT_SHIFT 16
-#define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT)
-
-#define I40E_NVMUPD_MAX_DATA 4096
-#define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */
-
-struct i40e_nvm_access {
- u32 command;
- u32 config;
- u32 offset; /* in bytes */
- u32 data_size; /* in bytes */
- u8 data[1];
-};
-
-/* (Q)SFP module access definitions */
-#define I40E_I2C_EEPROM_DEV_ADDR 0xA0
-#define I40E_I2C_EEPROM_DEV_ADDR2 0xA2
-#define I40E_MODULE_TYPE_ADDR 0x00
-#define I40E_MODULE_REVISION_ADDR 0x01
-#define I40E_MODULE_SFF_8472_COMP 0x5E
-#define I40E_MODULE_SFF_8472_SWAP 0x5C
-#define I40E_MODULE_SFF_ADDR_MODE 0x04
-#define I40E_MODULE_TYPE_QSFP_PLUS 0x0D
-#define I40E_MODULE_TYPE_QSFP28 0x11
-#define I40E_MODULE_QSFP_MAX_LEN 640
-
-/* PCI bus types */
-enum i40e_bus_type {
- i40e_bus_type_unknown = 0,
- i40e_bus_type_pci,
- i40e_bus_type_pcix,
- i40e_bus_type_pci_express,
- i40e_bus_type_reserved
-};
-
-/* PCI bus speeds */
-enum i40e_bus_speed {
- i40e_bus_speed_unknown = 0,
- i40e_bus_speed_33 = 33,
- i40e_bus_speed_66 = 66,
- i40e_bus_speed_100 = 100,
- i40e_bus_speed_120 = 120,
- i40e_bus_speed_133 = 133,
- i40e_bus_speed_2500 = 2500,
- i40e_bus_speed_5000 = 5000,
- i40e_bus_speed_8000 = 8000,
- i40e_bus_speed_reserved
-};
-
-/* PCI bus widths */
-enum i40e_bus_width {
- i40e_bus_width_unknown = 0,
- i40e_bus_width_pcie_x1 = 1,
- i40e_bus_width_pcie_x2 = 2,
- i40e_bus_width_pcie_x4 = 4,
- i40e_bus_width_pcie_x8 = 8,
- i40e_bus_width_32 = 32,
- i40e_bus_width_64 = 64,
- i40e_bus_width_reserved
-};
-
-/* Bus parameters */
-struct i40e_bus_info {
- enum i40e_bus_speed speed;
- enum i40e_bus_width width;
- enum i40e_bus_type type;
-
- u16 func;
- u16 device;
- u16 lan_id;
- u16 bus_id;
-};
-
-/* Flow control (FC) parameters */
-struct i40e_fc_info {
- enum i40e_fc_mode current_mode; /* FC mode in effect */
- enum i40e_fc_mode requested_mode; /* FC mode requested by caller */
-};
-
-#define I40E_MAX_TRAFFIC_CLASS 8
-#define I40E_MAX_USER_PRIORITY 8
-#define I40E_DCBX_MAX_APPS 32
-#define I40E_LLDPDU_SIZE 1500
-
-/* IEEE 802.1Qaz ETS Configuration data */
-struct i40e_ieee_ets_config {
- u8 willing;
- u8 cbs;
- u8 maxtcs;
- u8 prioritytable[I40E_MAX_TRAFFIC_CLASS];
- u8 tcbwtable[I40E_MAX_TRAFFIC_CLASS];
- u8 tsatable[I40E_MAX_TRAFFIC_CLASS];
-};
-
-/* IEEE 802.1Qaz ETS Recommendation data */
-struct i40e_ieee_ets_recommend {
- u8 prioritytable[I40E_MAX_TRAFFIC_CLASS];
- u8 tcbwtable[I40E_MAX_TRAFFIC_CLASS];
- u8 tsatable[I40E_MAX_TRAFFIC_CLASS];
-};
-
-/* IEEE 802.1Qaz PFC Configuration data */
-struct i40e_ieee_pfc_config {
- u8 willing;
- u8 mbc;
- u8 pfccap;
- u8 pfcenable;
-};
-
-/* IEEE 802.1Qaz Application Priority data */
-struct i40e_ieee_app_priority_table {
- u8 priority;
- u8 selector;
- u16 protocolid;
-};
-
-struct i40e_dcbx_config {
- u32 numapps;
- u32 tlv_status; /* CEE mode TLV status */
- struct i40e_ieee_ets_config etscfg;
- struct i40e_ieee_ets_recommend etsrec;
- struct i40e_ieee_pfc_config pfc;
- struct i40e_ieee_app_priority_table app[I40E_DCBX_MAX_APPS];
-};
-
-/* Port hardware description */
-struct i40e_hw {
- u8 __iomem *hw_addr;
- void *back;
-
- /* subsystem structs */
- struct i40e_phy_info phy;
- struct i40e_mac_info mac;
- struct i40e_bus_info bus;
- struct i40e_nvm_info nvm;
- struct i40e_fc_info fc;
-
- /* pci info */
- u16 device_id;
- u16 vendor_id;
- u16 subsystem_device_id;
- u16 subsystem_vendor_id;
- u8 revision_id;
- u8 port;
- bool adapter_stopped;
-
- /* capabilities for entire device and PCI func */
- struct i40e_hw_capabilities dev_caps;
- struct i40e_hw_capabilities func_caps;
-
- /* Flow Director shared filter space */
- u16 fdir_shared_filter_count;
-
- /* device profile info */
- u8 pf_id;
- u16 main_vsi_seid;
-
- /* for multi-function MACs */
- u16 partition_id;
- u16 num_partitions;
- u16 num_ports;
-
- /* Closest numa node to the device */
- u16 numa_node;
-
- /* Admin Queue info */
- struct i40e_adminq_info aq;
-
- /* state of nvm update process */
- enum i40e_nvmupd_state nvmupd_state;
- struct i40e_aq_desc nvm_wb_desc;
- struct i40e_aq_desc nvm_aq_event_desc;
- struct i40e_virt_mem nvm_buff;
- bool nvm_release_on_done;
- u16 nvm_wait_opcode;
-
- /* HMC info */
- struct i40e_hmc_info hmc; /* HMC info struct */
-
- /* LLDP/DCBX Status */
- u16 dcbx_status;
-
-#define I40E_HW_FLAG_802_1AD_CAPABLE BIT_ULL(1)
-#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
-
- /* DCBX info */
- struct i40e_dcbx_config local_dcbx_config; /* Oper/Local Cfg */
- struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */
- struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */
-
- /* Used in set switch config AQ command */
- u16 switch_tag;
- u16 first_tag;
- u16 second_tag;
-
- /* debug mask */
- u32 debug_mask;
- char err_str[16];
-};
-
-static inline bool i40e_is_vf(struct i40e_hw *hw)
-{
- return (hw->mac.type == I40E_MAC_VF ||
- hw->mac.type == I40E_MAC_X722_VF);
-}
-
-struct i40e_driver_version {
- u8 major_version;
- u8 minor_version;
- u8 build_version;
- u8 subbuild_version;
- u8 driver_string[32];
-};
-
-/* RX Descriptors */
-union i40e_16byte_rx_desc {
- struct {
- __le64 pkt_addr; /* Packet buffer address */
- __le64 hdr_addr; /* Header buffer address */
- } read;
- struct {
- struct {
- struct {
- union {
- __le16 mirroring_status;
- __le16 fcoe_ctx_id;
- } mirr_fcoe;
- __le16 l2tag1;
- } lo_dword;
- union {
- __le32 rss; /* RSS Hash */
- __le32 fd_id; /* Flow director filter id */
- __le32 fcoe_param; /* FCoE DDP Context id */
- } hi_dword;
- } qword0;
- struct {
- /* ext status/error/pktype/length */
- __le64 status_error_len;
- } qword1;
- } wb; /* writeback */
-};
-
-union i40e_32byte_rx_desc {
- struct {
- __le64 pkt_addr; /* Packet buffer address */
- __le64 hdr_addr; /* Header buffer address */
- /* bit 0 of hdr_buffer_addr is DD bit */
- __le64 rsvd1;
- __le64 rsvd2;
- } read;
- struct {
- struct {
- struct {
- union {
- __le16 mirroring_status;
- __le16 fcoe_ctx_id;
- } mirr_fcoe;
- __le16 l2tag1;
- } lo_dword;
- union {
- __le32 rss; /* RSS Hash */
- __le32 fcoe_param; /* FCoE DDP Context id */
- /* Flow director filter id in case of
- * Programming status desc WB
- */
- __le32 fd_id;
- } hi_dword;
- } qword0;
- struct {
- /* status/error/pktype/length */
- __le64 status_error_len;
- } qword1;
- struct {
- __le16 ext_status; /* extended status */
- __le16 rsvd;
- __le16 l2tag2_1;
- __le16 l2tag2_2;
- } qword2;
- struct {
- union {
- __le32 flex_bytes_lo;
- __le32 pe_status;
- } lo_dword;
- union {
- __le32 flex_bytes_hi;
- __le32 fd_id;
- } hi_dword;
- } qword3;
- } wb; /* writeback */
-};
-
-enum i40e_rx_desc_status_bits {
- /* Note: These are predefined bit offsets */
- I40E_RX_DESC_STATUS_DD_SHIFT = 0,
- I40E_RX_DESC_STATUS_EOF_SHIFT = 1,
- I40E_RX_DESC_STATUS_L2TAG1P_SHIFT = 2,
- I40E_RX_DESC_STATUS_L3L4P_SHIFT = 3,
- I40E_RX_DESC_STATUS_CRCP_SHIFT = 4,
- I40E_RX_DESC_STATUS_TSYNINDX_SHIFT = 5, /* 2 BITS */
- I40E_RX_DESC_STATUS_TSYNVALID_SHIFT = 7,
- /* Note: Bit 8 is reserved in X710 and XL710 */
- I40E_RX_DESC_STATUS_EXT_UDP_0_SHIFT = 8,
- I40E_RX_DESC_STATUS_UMBCAST_SHIFT = 9, /* 2 BITS */
- I40E_RX_DESC_STATUS_FLM_SHIFT = 11,
- I40E_RX_DESC_STATUS_FLTSTAT_SHIFT = 12, /* 2 BITS */
- I40E_RX_DESC_STATUS_LPBK_SHIFT = 14,
- I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT = 15,
- I40E_RX_DESC_STATUS_RESERVED_SHIFT = 16, /* 2 BITS */
- /* Note: For non-tunnel packets INT_UDP_0 is the right status for
- * UDP header
- */
- I40E_RX_DESC_STATUS_INT_UDP_0_SHIFT = 18,
- I40E_RX_DESC_STATUS_LAST /* this entry must be last!!! */
-};
-
-#define I40E_RXD_QW1_STATUS_SHIFT 0
-#define I40E_RXD_QW1_STATUS_MASK ((BIT(I40E_RX_DESC_STATUS_LAST) - 1) \
- << I40E_RXD_QW1_STATUS_SHIFT)
-
-#define I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT I40E_RX_DESC_STATUS_TSYNINDX_SHIFT
-#define I40E_RXD_QW1_STATUS_TSYNINDX_MASK (0x3UL << \
- I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT)
-
-#define I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT I40E_RX_DESC_STATUS_TSYNVALID_SHIFT
-#define I40E_RXD_QW1_STATUS_TSYNVALID_MASK \
- BIT_ULL(I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT)
-
-enum i40e_rx_desc_fltstat_values {
- I40E_RX_DESC_FLTSTAT_NO_DATA = 0,
- I40E_RX_DESC_FLTSTAT_RSV_FD_ID = 1, /* 16byte desc? FD_ID : RSV */
- I40E_RX_DESC_FLTSTAT_RSV = 2,
- I40E_RX_DESC_FLTSTAT_RSS_HASH = 3,
-};
-
-#define I40E_RXD_QW1_ERROR_SHIFT 19
-#define I40E_RXD_QW1_ERROR_MASK (0xFFUL << I40E_RXD_QW1_ERROR_SHIFT)
-
-enum i40e_rx_desc_error_bits {
- /* Note: These are predefined bit offsets */
- I40E_RX_DESC_ERROR_RXE_SHIFT = 0,
- I40E_RX_DESC_ERROR_RECIPE_SHIFT = 1,
- I40E_RX_DESC_ERROR_HBO_SHIFT = 2,
- I40E_RX_DESC_ERROR_L3L4E_SHIFT = 3, /* 3 BITS */
- I40E_RX_DESC_ERROR_IPE_SHIFT = 3,
- I40E_RX_DESC_ERROR_L4E_SHIFT = 4,
- I40E_RX_DESC_ERROR_EIPE_SHIFT = 5,
- I40E_RX_DESC_ERROR_OVERSIZE_SHIFT = 6,
- I40E_RX_DESC_ERROR_PPRS_SHIFT = 7
-};
-
-enum i40e_rx_desc_error_l3l4e_fcoe_masks {
- I40E_RX_DESC_ERROR_L3L4E_NONE = 0,
- I40E_RX_DESC_ERROR_L3L4E_PROT = 1,
- I40E_RX_DESC_ERROR_L3L4E_FC = 2,
- I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR = 3,
- I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN = 4
-};
-
-#define I40E_RXD_QW1_PTYPE_SHIFT 30
-#define I40E_RXD_QW1_PTYPE_MASK (0xFFULL << I40E_RXD_QW1_PTYPE_SHIFT)
-
-/* Packet type non-ip values */
-enum i40e_rx_l2_ptype {
- I40E_RX_PTYPE_L2_RESERVED = 0,
- I40E_RX_PTYPE_L2_MAC_PAY2 = 1,
- I40E_RX_PTYPE_L2_TIMESYNC_PAY2 = 2,
- I40E_RX_PTYPE_L2_FIP_PAY2 = 3,
- I40E_RX_PTYPE_L2_OUI_PAY2 = 4,
- I40E_RX_PTYPE_L2_MACCNTRL_PAY2 = 5,
- I40E_RX_PTYPE_L2_LLDP_PAY2 = 6,
- I40E_RX_PTYPE_L2_ECP_PAY2 = 7,
- I40E_RX_PTYPE_L2_EVB_PAY2 = 8,
- I40E_RX_PTYPE_L2_QCN_PAY2 = 9,
- I40E_RX_PTYPE_L2_EAPOL_PAY2 = 10,
- I40E_RX_PTYPE_L2_ARP = 11,
- I40E_RX_PTYPE_L2_FCOE_PAY3 = 12,
- I40E_RX_PTYPE_L2_FCOE_FCDATA_PAY3 = 13,
- I40E_RX_PTYPE_L2_FCOE_FCRDY_PAY3 = 14,
- I40E_RX_PTYPE_L2_FCOE_FCRSP_PAY3 = 15,
- I40E_RX_PTYPE_L2_FCOE_FCOTHER_PA = 16,
- I40E_RX_PTYPE_L2_FCOE_VFT_PAY3 = 17,
- I40E_RX_PTYPE_L2_FCOE_VFT_FCDATA = 18,
- I40E_RX_PTYPE_L2_FCOE_VFT_FCRDY = 19,
- I40E_RX_PTYPE_L2_FCOE_VFT_FCRSP = 20,
- I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER = 21,
- I40E_RX_PTYPE_GRENAT4_MAC_PAY3 = 58,
- I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4 = 87,
- I40E_RX_PTYPE_GRENAT6_MAC_PAY3 = 124,
- I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4 = 153
-};
-
-struct i40e_rx_ptype_decoded {
- u32 ptype:8;
- u32 known:1;
- u32 outer_ip:1;
- u32 outer_ip_ver:1;
- u32 outer_frag:1;
- u32 tunnel_type:3;
- u32 tunnel_end_prot:2;
- u32 tunnel_end_frag:1;
- u32 inner_prot:4;
- u32 payload_layer:3;
-};
-
-enum i40e_rx_ptype_outer_ip {
- I40E_RX_PTYPE_OUTER_L2 = 0,
- I40E_RX_PTYPE_OUTER_IP = 1
-};
-
-enum i40e_rx_ptype_outer_ip_ver {
- I40E_RX_PTYPE_OUTER_NONE = 0,
- I40E_RX_PTYPE_OUTER_IPV4 = 0,
- I40E_RX_PTYPE_OUTER_IPV6 = 1
-};
-
-enum i40e_rx_ptype_outer_fragmented {
- I40E_RX_PTYPE_NOT_FRAG = 0,
- I40E_RX_PTYPE_FRAG = 1
-};
-
-enum i40e_rx_ptype_tunnel_type {
- I40E_RX_PTYPE_TUNNEL_NONE = 0,
- I40E_RX_PTYPE_TUNNEL_IP_IP = 1,
- I40E_RX_PTYPE_TUNNEL_IP_GRENAT = 2,
- I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC = 3,
- I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4,
-};
-
-enum i40e_rx_ptype_tunnel_end_prot {
- I40E_RX_PTYPE_TUNNEL_END_NONE = 0,
- I40E_RX_PTYPE_TUNNEL_END_IPV4 = 1,
- I40E_RX_PTYPE_TUNNEL_END_IPV6 = 2,
-};
-
-enum i40e_rx_ptype_inner_prot {
- I40E_RX_PTYPE_INNER_PROT_NONE = 0,
- I40E_RX_PTYPE_INNER_PROT_UDP = 1,
- I40E_RX_PTYPE_INNER_PROT_TCP = 2,
- I40E_RX_PTYPE_INNER_PROT_SCTP = 3,
- I40E_RX_PTYPE_INNER_PROT_ICMP = 4,
- I40E_RX_PTYPE_INNER_PROT_TIMESYNC = 5
-};
-
-enum i40e_rx_ptype_payload_layer {
- I40E_RX_PTYPE_PAYLOAD_LAYER_NONE = 0,
- I40E_RX_PTYPE_PAYLOAD_LAYER_PAY2 = 1,
- I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3 = 2,
- I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4 = 3,
-};
-
-#define I40E_RXD_QW1_LENGTH_PBUF_SHIFT 38
-#define I40E_RXD_QW1_LENGTH_PBUF_MASK (0x3FFFULL << \
- I40E_RXD_QW1_LENGTH_PBUF_SHIFT)
-
-#define I40E_RXD_QW1_LENGTH_HBUF_SHIFT 52
-#define I40E_RXD_QW1_LENGTH_HBUF_MASK (0x7FFULL << \
- I40E_RXD_QW1_LENGTH_HBUF_SHIFT)
-
-#define I40E_RXD_QW1_LENGTH_SPH_SHIFT 63
-#define I40E_RXD_QW1_LENGTH_SPH_MASK BIT_ULL(I40E_RXD_QW1_LENGTH_SPH_SHIFT)
-
-enum i40e_rx_desc_ext_status_bits {
- /* Note: These are predefined bit offsets */
- I40E_RX_DESC_EXT_STATUS_L2TAG2P_SHIFT = 0,
- I40E_RX_DESC_EXT_STATUS_L2TAG3P_SHIFT = 1,
- I40E_RX_DESC_EXT_STATUS_FLEXBL_SHIFT = 2, /* 2 BITS */
- I40E_RX_DESC_EXT_STATUS_FLEXBH_SHIFT = 4, /* 2 BITS */
- I40E_RX_DESC_EXT_STATUS_FDLONGB_SHIFT = 9,
- I40E_RX_DESC_EXT_STATUS_FCOELONGB_SHIFT = 10,
- I40E_RX_DESC_EXT_STATUS_PELONGB_SHIFT = 11,
-};
-
-enum i40e_rx_desc_pe_status_bits {
- /* Note: These are predefined bit offsets */
- I40E_RX_DESC_PE_STATUS_QPID_SHIFT = 0, /* 18 BITS */
- I40E_RX_DESC_PE_STATUS_L4PORT_SHIFT = 0, /* 16 BITS */
- I40E_RX_DESC_PE_STATUS_IPINDEX_SHIFT = 16, /* 8 BITS */
- I40E_RX_DESC_PE_STATUS_QPIDHIT_SHIFT = 24,
- I40E_RX_DESC_PE_STATUS_APBVTHIT_SHIFT = 25,
- I40E_RX_DESC_PE_STATUS_PORTV_SHIFT = 26,
- I40E_RX_DESC_PE_STATUS_URG_SHIFT = 27,
- I40E_RX_DESC_PE_STATUS_IPFRAG_SHIFT = 28,
- I40E_RX_DESC_PE_STATUS_IPOPT_SHIFT = 29
-};
-
-#define I40E_RX_PROG_STATUS_DESC_LENGTH_SHIFT 38
-#define I40E_RX_PROG_STATUS_DESC_LENGTH 0x2000000
-
-#define I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT 2
-#define I40E_RX_PROG_STATUS_DESC_QW1_PROGID_MASK (0x7UL << \
- I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT)
-
-#define I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT 19
-#define I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK (0x3FUL << \
- I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT)
-
-enum i40e_rx_prog_status_desc_status_bits {
- /* Note: These are predefined bit offsets */
- I40E_RX_PROG_STATUS_DESC_DD_SHIFT = 0,
- I40E_RX_PROG_STATUS_DESC_PROG_ID_SHIFT = 2 /* 3 BITS */
-};
-
-enum i40e_rx_prog_status_desc_prog_id_masks {
- I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS = 1,
- I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS = 2,
- I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS = 4,
-};
-
-enum i40e_rx_prog_status_desc_error_bits {
- /* Note: These are predefined bit offsets */
- I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT = 0,
- I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT = 1,
- I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT = 2,
- I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT = 3
-};
-
-/* TX Descriptor */
-struct i40e_tx_desc {
- __le64 buffer_addr; /* Address of descriptor's data buf */
- __le64 cmd_type_offset_bsz;
-};
-
-#define I40E_TXD_QW1_DTYPE_SHIFT 0
-#define I40E_TXD_QW1_DTYPE_MASK (0xFUL << I40E_TXD_QW1_DTYPE_SHIFT)
-
-enum i40e_tx_desc_dtype_value {
- I40E_TX_DESC_DTYPE_DATA = 0x0,
- I40E_TX_DESC_DTYPE_NOP = 0x1, /* same as Context desc */
- I40E_TX_DESC_DTYPE_CONTEXT = 0x1,
- I40E_TX_DESC_DTYPE_FCOE_CTX = 0x2,
- I40E_TX_DESC_DTYPE_FILTER_PROG = 0x8,
- I40E_TX_DESC_DTYPE_DDP_CTX = 0x9,
- I40E_TX_DESC_DTYPE_FLEX_DATA = 0xB,
- I40E_TX_DESC_DTYPE_FLEX_CTX_1 = 0xC,
- I40E_TX_DESC_DTYPE_FLEX_CTX_2 = 0xD,
- I40E_TX_DESC_DTYPE_DESC_DONE = 0xF
-};
-
-#define I40E_TXD_QW1_CMD_SHIFT 4
-#define I40E_TXD_QW1_CMD_MASK (0x3FFUL << I40E_TXD_QW1_CMD_SHIFT)
-
-enum i40e_tx_desc_cmd_bits {
- I40E_TX_DESC_CMD_EOP = 0x0001,
- I40E_TX_DESC_CMD_RS = 0x0002,
- I40E_TX_DESC_CMD_ICRC = 0x0004,
- I40E_TX_DESC_CMD_IL2TAG1 = 0x0008,
- I40E_TX_DESC_CMD_DUMMY = 0x0010,
- I40E_TX_DESC_CMD_IIPT_NONIP = 0x0000, /* 2 BITS */
- I40E_TX_DESC_CMD_IIPT_IPV6 = 0x0020, /* 2 BITS */
- I40E_TX_DESC_CMD_IIPT_IPV4 = 0x0040, /* 2 BITS */
- I40E_TX_DESC_CMD_IIPT_IPV4_CSUM = 0x0060, /* 2 BITS */
- I40E_TX_DESC_CMD_FCOET = 0x0080,
- I40E_TX_DESC_CMD_L4T_EOFT_UNK = 0x0000, /* 2 BITS */
- I40E_TX_DESC_CMD_L4T_EOFT_TCP = 0x0100, /* 2 BITS */
- I40E_TX_DESC_CMD_L4T_EOFT_SCTP = 0x0200, /* 2 BITS */
- I40E_TX_DESC_CMD_L4T_EOFT_UDP = 0x0300, /* 2 BITS */
- I40E_TX_DESC_CMD_L4T_EOFT_EOF_N = 0x0000, /* 2 BITS */
- I40E_TX_DESC_CMD_L4T_EOFT_EOF_T = 0x0100, /* 2 BITS */
- I40E_TX_DESC_CMD_L4T_EOFT_EOF_NI = 0x0200, /* 2 BITS */
- I40E_TX_DESC_CMD_L4T_EOFT_EOF_A = 0x0300, /* 2 BITS */
-};
-
-#define I40E_TXD_QW1_OFFSET_SHIFT 16
-#define I40E_TXD_QW1_OFFSET_MASK (0x3FFFFULL << \
- I40E_TXD_QW1_OFFSET_SHIFT)
-
-enum i40e_tx_desc_length_fields {
- /* Note: These are predefined bit offsets */
- I40E_TX_DESC_LENGTH_MACLEN_SHIFT = 0, /* 7 BITS */
- I40E_TX_DESC_LENGTH_IPLEN_SHIFT = 7, /* 7 BITS */
- I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT = 14 /* 4 BITS */
-};
-
-#define I40E_TXD_QW1_TX_BUF_SZ_SHIFT 34
-#define I40E_TXD_QW1_TX_BUF_SZ_MASK (0x3FFFULL << \
- I40E_TXD_QW1_TX_BUF_SZ_SHIFT)
-
-#define I40E_TXD_QW1_L2TAG1_SHIFT 48
-#define I40E_TXD_QW1_L2TAG1_MASK (0xFFFFULL << I40E_TXD_QW1_L2TAG1_SHIFT)
-
-/* Context descriptors */
-struct i40e_tx_context_desc {
- __le32 tunneling_params;
- __le16 l2tag2;
- __le16 rsvd;
- __le64 type_cmd_tso_mss;
-};
-
-#define I40E_TXD_CTX_QW1_DTYPE_SHIFT 0
-#define I40E_TXD_CTX_QW1_DTYPE_MASK (0xFUL << I40E_TXD_CTX_QW1_DTYPE_SHIFT)
-
-#define I40E_TXD_CTX_QW1_CMD_SHIFT 4
-#define I40E_TXD_CTX_QW1_CMD_MASK (0xFFFFUL << I40E_TXD_CTX_QW1_CMD_SHIFT)
-
-enum i40e_tx_ctx_desc_cmd_bits {
- I40E_TX_CTX_DESC_TSO = 0x01,
- I40E_TX_CTX_DESC_TSYN = 0x02,
- I40E_TX_CTX_DESC_IL2TAG2 = 0x04,
- I40E_TX_CTX_DESC_IL2TAG2_IL2H = 0x08,
- I40E_TX_CTX_DESC_SWTCH_NOTAG = 0x00,
- I40E_TX_CTX_DESC_SWTCH_UPLINK = 0x10,
- I40E_TX_CTX_DESC_SWTCH_LOCAL = 0x20,
- I40E_TX_CTX_DESC_SWTCH_VSI = 0x30,
- I40E_TX_CTX_DESC_SWPE = 0x40
-};
-
-#define I40E_TXD_CTX_QW1_TSO_LEN_SHIFT 30
-#define I40E_TXD_CTX_QW1_TSO_LEN_MASK (0x3FFFFULL << \
- I40E_TXD_CTX_QW1_TSO_LEN_SHIFT)
-
-#define I40E_TXD_CTX_QW1_MSS_SHIFT 50
-#define I40E_TXD_CTX_QW1_MSS_MASK (0x3FFFULL << \
- I40E_TXD_CTX_QW1_MSS_SHIFT)
-
-#define I40E_TXD_CTX_QW1_VSI_SHIFT 50
-#define I40E_TXD_CTX_QW1_VSI_MASK (0x1FFULL << I40E_TXD_CTX_QW1_VSI_SHIFT)
-
-#define I40E_TXD_CTX_QW0_EXT_IP_SHIFT 0
-#define I40E_TXD_CTX_QW0_EXT_IP_MASK (0x3ULL << \
- I40E_TXD_CTX_QW0_EXT_IP_SHIFT)
-
-enum i40e_tx_ctx_desc_eipt_offload {
- I40E_TX_CTX_EXT_IP_NONE = 0x0,
- I40E_TX_CTX_EXT_IP_IPV6 = 0x1,
- I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM = 0x2,
- I40E_TX_CTX_EXT_IP_IPV4 = 0x3
-};
-
-#define I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT 2
-#define I40E_TXD_CTX_QW0_EXT_IPLEN_MASK (0x3FULL << \
- I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT)
-
-#define I40E_TXD_CTX_QW0_NATT_SHIFT 9
-#define I40E_TXD_CTX_QW0_NATT_MASK (0x3ULL << I40E_TXD_CTX_QW0_NATT_SHIFT)
-
-#define I40E_TXD_CTX_UDP_TUNNELING BIT_ULL(I40E_TXD_CTX_QW0_NATT_SHIFT)
-#define I40E_TXD_CTX_GRE_TUNNELING (0x2ULL << I40E_TXD_CTX_QW0_NATT_SHIFT)
-
-#define I40E_TXD_CTX_QW0_EIP_NOINC_SHIFT 11
-#define I40E_TXD_CTX_QW0_EIP_NOINC_MASK \
- BIT_ULL(I40E_TXD_CTX_QW0_EIP_NOINC_SHIFT)
-
-#define I40E_TXD_CTX_EIP_NOINC_IPID_CONST I40E_TXD_CTX_QW0_EIP_NOINC_MASK
-
-#define I40E_TXD_CTX_QW0_NATLEN_SHIFT 12
-#define I40E_TXD_CTX_QW0_NATLEN_MASK (0X7FULL << \
- I40E_TXD_CTX_QW0_NATLEN_SHIFT)
-
-#define I40E_TXD_CTX_QW0_DECTTL_SHIFT 19
-#define I40E_TXD_CTX_QW0_DECTTL_MASK (0xFULL << \
- I40E_TXD_CTX_QW0_DECTTL_SHIFT)
-
-#define I40E_TXD_CTX_QW0_L4T_CS_SHIFT 23
-#define I40E_TXD_CTX_QW0_L4T_CS_MASK BIT_ULL(I40E_TXD_CTX_QW0_L4T_CS_SHIFT)
-struct i40e_filter_program_desc {
- __le32 qindex_flex_ptype_vsi;
- __le32 rsvd;
- __le32 dtype_cmd_cntindex;
- __le32 fd_id;
-};
-#define I40E_TXD_FLTR_QW0_QINDEX_SHIFT 0
-#define I40E_TXD_FLTR_QW0_QINDEX_MASK (0x7FFUL << \
- I40E_TXD_FLTR_QW0_QINDEX_SHIFT)
-#define I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT 11
-#define I40E_TXD_FLTR_QW0_FLEXOFF_MASK (0x7UL << \
- I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT)
-#define I40E_TXD_FLTR_QW0_PCTYPE_SHIFT 17
-#define I40E_TXD_FLTR_QW0_PCTYPE_MASK (0x3FUL << \
- I40E_TXD_FLTR_QW0_PCTYPE_SHIFT)
-
-/* Packet Classifier Types for filters */
-enum i40e_filter_pctype {
- /* Note: Values 0-28 are reserved for future use.
- * Value 29, 30, 32 are not supported on XL710 and X710.
- */
- I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP = 29,
- I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP = 30,
- I40E_FILTER_PCTYPE_NONF_IPV4_UDP = 31,
- I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK = 32,
- I40E_FILTER_PCTYPE_NONF_IPV4_TCP = 33,
- I40E_FILTER_PCTYPE_NONF_IPV4_SCTP = 34,
- I40E_FILTER_PCTYPE_NONF_IPV4_OTHER = 35,
- I40E_FILTER_PCTYPE_FRAG_IPV4 = 36,
- /* Note: Values 37-38 are reserved for future use.
- * Value 39, 40, 42 are not supported on XL710 and X710.
- */
- I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP = 39,
- I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP = 40,
- I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41,
- I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK = 42,
- I40E_FILTER_PCTYPE_NONF_IPV6_TCP = 43,
- I40E_FILTER_PCTYPE_NONF_IPV6_SCTP = 44,
- I40E_FILTER_PCTYPE_NONF_IPV6_OTHER = 45,
- I40E_FILTER_PCTYPE_FRAG_IPV6 = 46,
- /* Note: Value 47 is reserved for future use */
- I40E_FILTER_PCTYPE_FCOE_OX = 48,
- I40E_FILTER_PCTYPE_FCOE_RX = 49,
- I40E_FILTER_PCTYPE_FCOE_OTHER = 50,
- /* Note: Values 51-62 are reserved for future use */
- I40E_FILTER_PCTYPE_L2_PAYLOAD = 63,
-};
-
-enum i40e_filter_program_desc_dest {
- I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET = 0x0,
- I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX = 0x1,
- I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER = 0x2,
-};
-
-enum i40e_filter_program_desc_fd_status {
- I40E_FILTER_PROGRAM_DESC_FD_STATUS_NONE = 0x0,
- I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID = 0x1,
- I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID_4FLEX_BYTES = 0x2,
- I40E_FILTER_PROGRAM_DESC_FD_STATUS_8FLEX_BYTES = 0x3,
-};
-
-#define I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT 23
-#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK (0x1FFUL << \
- I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT)
-
-#define I40E_TXD_FLTR_QW1_CMD_SHIFT 4
-#define I40E_TXD_FLTR_QW1_CMD_MASK (0xFFFFULL << \
- I40E_TXD_FLTR_QW1_CMD_SHIFT)
-
-#define I40E_TXD_FLTR_QW1_PCMD_SHIFT (0x0ULL + I40E_TXD_FLTR_QW1_CMD_SHIFT)
-#define I40E_TXD_FLTR_QW1_PCMD_MASK (0x7ULL << I40E_TXD_FLTR_QW1_PCMD_SHIFT)
-
-enum i40e_filter_program_desc_pcmd {
- I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE = 0x1,
- I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE = 0x2,
-};
-
-#define I40E_TXD_FLTR_QW1_DEST_SHIFT (0x3ULL + I40E_TXD_FLTR_QW1_CMD_SHIFT)
-#define I40E_TXD_FLTR_QW1_DEST_MASK (0x3ULL << I40E_TXD_FLTR_QW1_DEST_SHIFT)
-
-#define I40E_TXD_FLTR_QW1_CNT_ENA_SHIFT (0x7ULL + I40E_TXD_FLTR_QW1_CMD_SHIFT)
-#define I40E_TXD_FLTR_QW1_CNT_ENA_MASK BIT_ULL(I40E_TXD_FLTR_QW1_CNT_ENA_SHIFT)
-
-#define I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT (0x9ULL + \
- I40E_TXD_FLTR_QW1_CMD_SHIFT)
-#define I40E_TXD_FLTR_QW1_FD_STATUS_MASK (0x3ULL << \
- I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT)
-
-#define I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT 20
-#define I40E_TXD_FLTR_QW1_CNTINDEX_MASK (0x1FFUL << \
- I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT)
-
-enum i40e_filter_type {
- I40E_FLOW_DIRECTOR_FLTR = 0,
- I40E_PE_QUAD_HASH_FLTR = 1,
- I40E_ETHERTYPE_FLTR,
- I40E_FCOE_CTX_FLTR,
- I40E_MAC_VLAN_FLTR,
- I40E_HASH_FLTR
-};
-
-struct i40e_vsi_context {
- u16 seid;
- u16 uplink_seid;
- u16 vsi_number;
- u16 vsis_allocated;
- u16 vsis_unallocated;
- u16 flags;
- u8 pf_num;
- u8 vf_num;
- u8 connection_type;
- struct i40e_aqc_vsi_properties_data info;
-};
-
-struct i40e_veb_context {
- u16 seid;
- u16 uplink_seid;
- u16 veb_number;
- u16 vebs_allocated;
- u16 vebs_unallocated;
- u16 flags;
- struct i40e_aqc_get_veb_parameters_completion info;
-};
-
-/* Statistics collected by each port, VSI, VEB, and S-channel */
-struct i40e_eth_stats {
- u64 rx_bytes; /* gorc */
- u64 rx_unicast; /* uprc */
- u64 rx_multicast; /* mprc */
- u64 rx_broadcast; /* bprc */
- u64 rx_discards; /* rdpc */
- u64 rx_unknown_protocol; /* rupp */
- u64 tx_bytes; /* gotc */
- u64 tx_unicast; /* uptc */
- u64 tx_multicast; /* mptc */
- u64 tx_broadcast; /* bptc */
- u64 tx_discards; /* tdpc */
- u64 tx_errors; /* tepc */
-};
-
-/* Statistics collected per VEB per TC */
-struct i40e_veb_tc_stats {
- u64 tc_rx_packets[I40E_MAX_TRAFFIC_CLASS];
- u64 tc_rx_bytes[I40E_MAX_TRAFFIC_CLASS];
- u64 tc_tx_packets[I40E_MAX_TRAFFIC_CLASS];
- u64 tc_tx_bytes[I40E_MAX_TRAFFIC_CLASS];
-};
-
-/* Statistics collected by the MAC */
-struct i40e_hw_port_stats {
- /* eth stats collected by the port */
- struct i40e_eth_stats eth;
-
- /* additional port specific stats */
- u64 tx_dropped_link_down; /* tdold */
- u64 crc_errors; /* crcerrs */
- u64 illegal_bytes; /* illerrc */
- u64 error_bytes; /* errbc */
- u64 mac_local_faults; /* mlfc */
- u64 mac_remote_faults; /* mrfc */
- u64 rx_length_errors; /* rlec */
- u64 link_xon_rx; /* lxonrxc */
- u64 link_xoff_rx; /* lxoffrxc */
- u64 priority_xon_rx[8]; /* pxonrxc[8] */
- u64 priority_xoff_rx[8]; /* pxoffrxc[8] */
- u64 link_xon_tx; /* lxontxc */
- u64 link_xoff_tx; /* lxofftxc */
- u64 priority_xon_tx[8]; /* pxontxc[8] */
- u64 priority_xoff_tx[8]; /* pxofftxc[8] */
- u64 priority_xon_2_xoff[8]; /* pxon2offc[8] */
- u64 rx_size_64; /* prc64 */
- u64 rx_size_127; /* prc127 */
- u64 rx_size_255; /* prc255 */
- u64 rx_size_511; /* prc511 */
- u64 rx_size_1023; /* prc1023 */
- u64 rx_size_1522; /* prc1522 */
- u64 rx_size_big; /* prc9522 */
- u64 rx_undersize; /* ruc */
- u64 rx_fragments; /* rfc */
- u64 rx_oversize; /* roc */
- u64 rx_jabber; /* rjc */
- u64 tx_size_64; /* ptc64 */
- u64 tx_size_127; /* ptc127 */
- u64 tx_size_255; /* ptc255 */
- u64 tx_size_511; /* ptc511 */
- u64 tx_size_1023; /* ptc1023 */
- u64 tx_size_1522; /* ptc1522 */
- u64 tx_size_big; /* ptc9522 */
- u64 mac_short_packet_dropped; /* mspdc */
- u64 checksum_error; /* xec */
- /* flow director stats */
- u64 fd_atr_match;
- u64 fd_sb_match;
- u64 fd_atr_tunnel_match;
- u32 fd_atr_status;
- u32 fd_sb_status;
- /* EEE LPI */
- u32 tx_lpi_status;
- u32 rx_lpi_status;
- u64 tx_lpi_count; /* etlpic */
- u64 rx_lpi_count; /* erlpic */
-};
-
-/* Checksum and Shadow RAM pointers */
-#define I40E_SR_NVM_CONTROL_WORD 0x00
-#define I40E_EMP_MODULE_PTR 0x0F
-#define I40E_SR_EMP_MODULE_PTR 0x48
-#define I40E_NVM_OEM_VER_OFF 0x83
-#define I40E_SR_NVM_DEV_STARTER_VERSION 0x18
-#define I40E_SR_NVM_WAKE_ON_LAN 0x19
-#define I40E_SR_ALTERNATE_SAN_MAC_ADDRESS_PTR 0x27
-#define I40E_SR_NVM_EETRACK_LO 0x2D
-#define I40E_SR_NVM_EETRACK_HI 0x2E
-#define I40E_SR_VPD_PTR 0x2F
-#define I40E_SR_PCIE_ALT_AUTO_LOAD_PTR 0x3E
-#define I40E_SR_SW_CHECKSUM_WORD 0x3F
-
-/* Auxiliary field, mask and shift definition for Shadow RAM and NVM Flash */
-#define I40E_SR_VPD_MODULE_MAX_SIZE 1024
-#define I40E_SR_PCIE_ALT_MODULE_MAX_SIZE 1024
-#define I40E_SR_CONTROL_WORD_1_SHIFT 0x06
-#define I40E_SR_CONTROL_WORD_1_MASK (0x03 << I40E_SR_CONTROL_WORD_1_SHIFT)
-#define I40E_SR_CONTROL_WORD_1_NVM_BANK_VALID BIT(5)
-#define I40E_SR_NVM_MAP_STRUCTURE_TYPE BIT(12)
-#define I40E_PTR_TYPE BIT(15)
-
-/* Shadow RAM related */
-#define I40E_SR_SECTOR_SIZE_IN_WORDS 0x800
-#define I40E_SR_WORDS_IN_1KB 512
-/* Checksum should be calculated such that after adding all the words,
- * including the checksum word itself, the sum should be 0xBABA.
- */
-#define I40E_SR_SW_CHECKSUM_BASE 0xBABA
-
-#define I40E_SRRD_SRCTL_ATTEMPTS 100000
-
-enum i40e_switch_element_types {
- I40E_SWITCH_ELEMENT_TYPE_MAC = 1,
- I40E_SWITCH_ELEMENT_TYPE_PF = 2,
- I40E_SWITCH_ELEMENT_TYPE_VF = 3,
- I40E_SWITCH_ELEMENT_TYPE_EMP = 4,
- I40E_SWITCH_ELEMENT_TYPE_BMC = 6,
- I40E_SWITCH_ELEMENT_TYPE_PE = 16,
- I40E_SWITCH_ELEMENT_TYPE_VEB = 17,
- I40E_SWITCH_ELEMENT_TYPE_PA = 18,
- I40E_SWITCH_ELEMENT_TYPE_VSI = 19,
-};
-
-/* Supported EtherType filters */
-enum i40e_ether_type_index {
- I40E_ETHER_TYPE_1588 = 0,
- I40E_ETHER_TYPE_FIP = 1,
- I40E_ETHER_TYPE_OUI_EXTENDED = 2,
- I40E_ETHER_TYPE_MAC_CONTROL = 3,
- I40E_ETHER_TYPE_LLDP = 4,
- I40E_ETHER_TYPE_EVB_PROTOCOL1 = 5,
- I40E_ETHER_TYPE_EVB_PROTOCOL2 = 6,
- I40E_ETHER_TYPE_QCN_CNM = 7,
- I40E_ETHER_TYPE_8021X = 8,
- I40E_ETHER_TYPE_ARP = 9,
- I40E_ETHER_TYPE_RSV1 = 10,
- I40E_ETHER_TYPE_RSV2 = 11,
-};
-
-/* Filter context base size is 1K */
-#define I40E_HASH_FILTER_BASE_SIZE 1024
-/* Supported Hash filter values */
-enum i40e_hash_filter_size {
- I40E_HASH_FILTER_SIZE_1K = 0,
- I40E_HASH_FILTER_SIZE_2K = 1,
- I40E_HASH_FILTER_SIZE_4K = 2,
- I40E_HASH_FILTER_SIZE_8K = 3,
- I40E_HASH_FILTER_SIZE_16K = 4,
- I40E_HASH_FILTER_SIZE_32K = 5,
- I40E_HASH_FILTER_SIZE_64K = 6,
- I40E_HASH_FILTER_SIZE_128K = 7,
- I40E_HASH_FILTER_SIZE_256K = 8,
- I40E_HASH_FILTER_SIZE_512K = 9,
- I40E_HASH_FILTER_SIZE_1M = 10,
-};
-
-/* DMA context base size is 0.5K */
-#define I40E_DMA_CNTX_BASE_SIZE 512
-/* Supported DMA context values */
-enum i40e_dma_cntx_size {
- I40E_DMA_CNTX_SIZE_512 = 0,
- I40E_DMA_CNTX_SIZE_1K = 1,
- I40E_DMA_CNTX_SIZE_2K = 2,
- I40E_DMA_CNTX_SIZE_4K = 3,
- I40E_DMA_CNTX_SIZE_8K = 4,
- I40E_DMA_CNTX_SIZE_16K = 5,
- I40E_DMA_CNTX_SIZE_32K = 6,
- I40E_DMA_CNTX_SIZE_64K = 7,
- I40E_DMA_CNTX_SIZE_128K = 8,
- I40E_DMA_CNTX_SIZE_256K = 9,
-};
-
-/* Supported Hash look up table (LUT) sizes */
-enum i40e_hash_lut_size {
- I40E_HASH_LUT_SIZE_128 = 0,
- I40E_HASH_LUT_SIZE_512 = 1,
-};
-
-/* Structure to hold a per PF filter control settings */
-struct i40e_filter_control_settings {
- /* number of PE Quad Hash filter buckets */
- enum i40e_hash_filter_size pe_filt_num;
- /* number of PE Quad Hash contexts */
- enum i40e_dma_cntx_size pe_cntx_num;
- /* number of FCoE filter buckets */
- enum i40e_hash_filter_size fcoe_filt_num;
- /* number of FCoE DDP contexts */
- enum i40e_dma_cntx_size fcoe_cntx_num;
- /* size of the Hash LUT */
- enum i40e_hash_lut_size hash_lut_size;
- /* enable FDIR filters for PF and its VFs */
- bool enable_fdir;
- /* enable Ethertype filters for PF and its VFs */
- bool enable_ethtype;
- /* enable MAC/VLAN filters for PF and its VFs */
- bool enable_macvlan;
-};
-
-/* Structure to hold device level control filter counts */
-struct i40e_control_filter_stats {
- u16 mac_etype_used; /* Used perfect match MAC/EtherType filters */
- u16 etype_used; /* Used perfect EtherType filters */
- u16 mac_etype_free; /* Un-used perfect match MAC/EtherType filters */
- u16 etype_free; /* Un-used perfect EtherType filters */
-};
-
-enum i40e_reset_type {
- I40E_RESET_POR = 0,
- I40E_RESET_CORER = 1,
- I40E_RESET_GLOBR = 2,
- I40E_RESET_EMPR = 3,
-};
-
-/* IEEE 802.1AB LLDP Agent Variables from NVM */
-#define I40E_NVM_LLDP_CFG_PTR 0x06
-#define I40E_SR_LLDP_CFG_PTR 0x31
-
-/* RSS Hash Table Size */
-#define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000
-
-/* INPUT SET MASK for RSS, flow director and flexible payload */
-#define I40E_FD_INSET_L3_SRC_SHIFT 47
-#define I40E_FD_INSET_L3_SRC_WORD_MASK (0x3ULL << \
- I40E_FD_INSET_L3_SRC_SHIFT)
-#define I40E_FD_INSET_L3_DST_SHIFT 35
-#define I40E_FD_INSET_L3_DST_WORD_MASK (0x3ULL << \
- I40E_FD_INSET_L3_DST_SHIFT)
-#define I40E_FD_INSET_L4_SRC_SHIFT 34
-#define I40E_FD_INSET_L4_SRC_WORD_MASK (0x1ULL << \
- I40E_FD_INSET_L4_SRC_SHIFT)
-#define I40E_FD_INSET_L4_DST_SHIFT 33
-#define I40E_FD_INSET_L4_DST_WORD_MASK (0x1ULL << \
- I40E_FD_INSET_L4_DST_SHIFT)
-#define I40E_FD_INSET_VERIFY_TAG_SHIFT 31
-#define I40E_FD_INSET_VERIFY_TAG_WORD_MASK (0x3ULL << \
- I40E_FD_INSET_VERIFY_TAG_SHIFT)
-
-#define I40E_FD_INSET_FLEX_WORD50_SHIFT 17
-#define I40E_FD_INSET_FLEX_WORD50_MASK (0x1ULL << \
- I40E_FD_INSET_FLEX_WORD50_SHIFT)
-#define I40E_FD_INSET_FLEX_WORD51_SHIFT 16
-#define I40E_FD_INSET_FLEX_WORD51_MASK (0x1ULL << \
- I40E_FD_INSET_FLEX_WORD51_SHIFT)
-#define I40E_FD_INSET_FLEX_WORD52_SHIFT 15
-#define I40E_FD_INSET_FLEX_WORD52_MASK (0x1ULL << \
- I40E_FD_INSET_FLEX_WORD52_SHIFT)
-#define I40E_FD_INSET_FLEX_WORD53_SHIFT 14
-#define I40E_FD_INSET_FLEX_WORD53_MASK (0x1ULL << \
- I40E_FD_INSET_FLEX_WORD53_SHIFT)
-#define I40E_FD_INSET_FLEX_WORD54_SHIFT 13
-#define I40E_FD_INSET_FLEX_WORD54_MASK (0x1ULL << \
- I40E_FD_INSET_FLEX_WORD54_SHIFT)
-#define I40E_FD_INSET_FLEX_WORD55_SHIFT 12
-#define I40E_FD_INSET_FLEX_WORD55_MASK (0x1ULL << \
- I40E_FD_INSET_FLEX_WORD55_SHIFT)
-#define I40E_FD_INSET_FLEX_WORD56_SHIFT 11
-#define I40E_FD_INSET_FLEX_WORD56_MASK (0x1ULL << \
- I40E_FD_INSET_FLEX_WORD56_SHIFT)
-#define I40E_FD_INSET_FLEX_WORD57_SHIFT 10
-#define I40E_FD_INSET_FLEX_WORD57_MASK (0x1ULL << \
- I40E_FD_INSET_FLEX_WORD57_SHIFT)
-
-/* Version format for Dynamic Device Personalization(DDP) */
-struct i40e_ddp_version {
- u8 major;
- u8 minor;
- u8 update;
- u8 draft;
-};
-
-#define I40E_DDP_NAME_SIZE 32
-
-/* Package header */
-struct i40e_package_header {
- struct i40e_ddp_version version;
- u32 segment_count;
- u32 segment_offset[1];
-};
-
-/* Generic segment header */
-struct i40e_generic_seg_header {
-#define SEGMENT_TYPE_METADATA 0x00000001
-#define SEGMENT_TYPE_NOTES 0x00000002
-#define SEGMENT_TYPE_I40E 0x00000011
-#define SEGMENT_TYPE_X722 0x00000012
- u32 type;
- struct i40e_ddp_version version;
- u32 size;
- char name[I40E_DDP_NAME_SIZE];
-};
-
-struct i40e_metadata_segment {
- struct i40e_generic_seg_header header;
- struct i40e_ddp_version version;
- u32 track_id;
- char name[I40E_DDP_NAME_SIZE];
-};
-
-struct i40e_device_id_entry {
- u32 vendor_dev_id;
- u32 sub_vendor_dev_id;
-};
-
-struct i40e_profile_segment {
- struct i40e_generic_seg_header header;
- struct i40e_ddp_version version;
- char name[I40E_DDP_NAME_SIZE];
- u32 device_table_count;
- struct i40e_device_id_entry device_table[1];
-};
-
-struct i40e_section_table {
- u32 section_count;
- u32 section_offset[1];
-};
-
-struct i40e_profile_section_header {
- u16 tbl_size;
- u16 data_end;
- struct {
-#define SECTION_TYPE_INFO 0x00000010
-#define SECTION_TYPE_MMIO 0x00000800
-#define SECTION_TYPE_AQ 0x00000801
-#define SECTION_TYPE_NOTE 0x80000000
-#define SECTION_TYPE_NAME 0x80000001
- u32 type;
- u32 offset;
- u32 size;
- } section;
-};
-
-struct i40e_profile_info {
- u32 track_id;
- struct i40e_ddp_version version;
- u8 op;
-#define I40E_DDP_ADD_TRACKID 0x01
-#define I40E_DDP_REMOVE_TRACKID 0x02
- u8 reserved[7];
- u8 name[I40E_DDP_NAME_SIZE];
-};
-#endif /* _I40E_TYPE_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
deleted file mode 100644
index 96e537a35000..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40evf.h
+++ /dev/null
@@ -1,427 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40EVF_H_
-#define _I40EVF_H_
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/aer.h>
-#include <linux/netdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/ethtool.h>
-#include <linux/if_vlan.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/sctp.h>
-#include <linux/ipv6.h>
-#include <linux/kernel.h>
-#include <linux/bitops.h>
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <linux/skbuff.h>
-#include <linux/dma-mapping.h>
-#include <linux/etherdevice.h>
-#include <linux/socket.h>
-#include <linux/jiffies.h>
-#include <net/ip6_checksum.h>
-#include <net/pkt_cls.h>
-#include <net/udp.h>
-#include <net/tc_act/tc_gact.h>
-#include <net/tc_act/tc_mirred.h>
-
-#include "i40e_type.h"
-#include <linux/avf/virtchnl.h>
-#include "i40e_txrx.h"
-
-#define DEFAULT_DEBUG_LEVEL_SHIFT 3
-#define PFX "i40evf: "
-
-/* VSI state flags shared with common code */
-enum i40evf_vsi_state_t {
- __I40E_VSI_DOWN,
- /* This must be last as it determines the size of the BITMAP */
- __I40E_VSI_STATE_SIZE__,
-};
-
-/* dummy struct to make common code less painful */
-struct i40e_vsi {
- struct i40evf_adapter *back;
- struct net_device *netdev;
- unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
- u16 seid;
- u16 id;
- DECLARE_BITMAP(state, __I40E_VSI_STATE_SIZE__);
- int base_vector;
- u16 work_limit;
- u16 qs_handle;
- void *priv; /* client driver data reference. */
-};
-
-/* How many Rx Buffers do we bundle into one write to the hardware ? */
-#define I40EVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */
-#define I40EVF_DEFAULT_TXD 512
-#define I40EVF_DEFAULT_RXD 512
-#define I40EVF_MAX_TXD 4096
-#define I40EVF_MIN_TXD 64
-#define I40EVF_MAX_RXD 4096
-#define I40EVF_MIN_RXD 64
-#define I40EVF_REQ_DESCRIPTOR_MULTIPLE 32
-#define I40EVF_MAX_AQ_BUF_SIZE 4096
-#define I40EVF_AQ_LEN 32
-#define I40EVF_AQ_MAX_ERR 20 /* times to try before resetting AQ */
-
-#define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
-
-#define I40E_RX_DESC(R, i) (&(((union i40e_32byte_rx_desc *)((R)->desc))[i]))
-#define I40E_TX_DESC(R, i) (&(((struct i40e_tx_desc *)((R)->desc))[i]))
-#define I40E_TX_CTXTDESC(R, i) \
- (&(((struct i40e_tx_context_desc *)((R)->desc))[i]))
-#define I40EVF_MAX_REQ_QUEUES 4
-
-#define I40EVF_HKEY_ARRAY_SIZE ((I40E_VFQF_HKEY_MAX_INDEX + 1) * 4)
-#define I40EVF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT_MAX_INDEX + 1) * 4)
-#define I40EVF_MBPS_DIVISOR 125000 /* divisor to convert to Mbps */
-
-/* MAX_MSIX_Q_VECTORS of these are allocated,
- * but we only use one per queue-specific vector.
- */
-struct i40e_q_vector {
- struct i40evf_adapter *adapter;
- struct i40e_vsi *vsi;
- struct napi_struct napi;
- struct i40e_ring_container rx;
- struct i40e_ring_container tx;
- u32 ring_mask;
- u8 itr_countdown; /* when 0 should adjust adaptive ITR */
- u8 num_ringpairs; /* total number of ring pairs in vector */
- u16 v_idx; /* index in the vsi->q_vector array. */
- u16 reg_idx; /* register index of the interrupt */
- char name[IFNAMSIZ + 15];
- bool arm_wb_state;
- cpumask_t affinity_mask;
- struct irq_affinity_notify affinity_notify;
-};
-
-/* Helper macros to switch between ints/sec and what the register uses.
- * And yes, it's the same math going both ways. The lowest value
- * supported by all of the i40e hardware is 8.
- */
-#define EITR_INTS_PER_SEC_TO_REG(_eitr) \
- ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8)
-#define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG
-
-#define I40EVF_DESC_UNUSED(R) \
- ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
- (R)->next_to_clean - (R)->next_to_use - 1)
-
-#define I40EVF_RX_DESC_ADV(R, i) \
- (&(((union i40e_adv_rx_desc *)((R).desc))[i]))
-#define I40EVF_TX_DESC_ADV(R, i) \
- (&(((union i40e_adv_tx_desc *)((R).desc))[i]))
-#define I40EVF_TX_CTXTDESC_ADV(R, i) \
- (&(((struct i40e_adv_tx_context_desc *)((R).desc))[i]))
-
-#define OTHER_VECTOR 1
-#define NONQ_VECS (OTHER_VECTOR)
-
-#define MIN_MSIX_Q_VECTORS 1
-#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NONQ_VECS)
-
-#define I40EVF_QUEUE_END_OF_LIST 0x7FF
-#define I40EVF_FREE_VECTOR 0x7FFF
-struct i40evf_mac_filter {
- struct list_head list;
- u8 macaddr[ETH_ALEN];
- bool remove; /* filter needs to be removed */
- bool add; /* filter needs to be added */
-};
-
-struct i40evf_vlan_filter {
- struct list_head list;
- u16 vlan;
- bool remove; /* filter needs to be removed */
- bool add; /* filter needs to be added */
-};
-
-#define I40EVF_MAX_TRAFFIC_CLASS 4
-/* State of traffic class creation */
-enum i40evf_tc_state_t {
- __I40EVF_TC_INVALID, /* no traffic class, default state */
- __I40EVF_TC_RUNNING, /* traffic classes have been created */
-};
-
-/* channel info */
-struct i40evf_channel_config {
- struct virtchnl_channel_info ch_info[I40EVF_MAX_TRAFFIC_CLASS];
- enum i40evf_tc_state_t state;
- u8 total_qps;
-};
-
-/* State of cloud filter */
-enum i40evf_cloud_filter_state_t {
- __I40EVF_CF_INVALID, /* cloud filter not added */
- __I40EVF_CF_ADD_PENDING, /* cloud filter pending add by the PF */
- __I40EVF_CF_DEL_PENDING, /* cloud filter pending del by the PF */
- __I40EVF_CF_ACTIVE, /* cloud filter is active */
-};
-
-/* Driver state. The order of these is important! */
-enum i40evf_state_t {
- __I40EVF_STARTUP, /* driver loaded, probe complete */
- __I40EVF_REMOVE, /* driver is being unloaded */
- __I40EVF_INIT_VERSION_CHECK, /* aq msg sent, awaiting reply */
- __I40EVF_INIT_GET_RESOURCES, /* aq msg sent, awaiting reply */
- __I40EVF_INIT_SW, /* got resources, setting up structs */
- __I40EVF_RESETTING, /* in reset */
- /* Below here, watchdog is running */
- __I40EVF_DOWN, /* ready, can be opened */
- __I40EVF_DOWN_PENDING, /* descending, waiting for watchdog */
- __I40EVF_TESTING, /* in ethtool self-test */
- __I40EVF_RUNNING, /* opened, working */
-};
-
-enum i40evf_critical_section_t {
- __I40EVF_IN_CRITICAL_TASK, /* cannot be interrupted */
- __I40EVF_IN_CLIENT_TASK,
- __I40EVF_IN_REMOVE_TASK, /* device being removed */
-};
-
-#define I40EVF_CLOUD_FIELD_OMAC 0x01
-#define I40EVF_CLOUD_FIELD_IMAC 0x02
-#define I40EVF_CLOUD_FIELD_IVLAN 0x04
-#define I40EVF_CLOUD_FIELD_TEN_ID 0x08
-#define I40EVF_CLOUD_FIELD_IIP 0x10
-
-#define I40EVF_CF_FLAGS_OMAC I40EVF_CLOUD_FIELD_OMAC
-#define I40EVF_CF_FLAGS_IMAC I40EVF_CLOUD_FIELD_IMAC
-#define I40EVF_CF_FLAGS_IMAC_IVLAN (I40EVF_CLOUD_FIELD_IMAC |\
- I40EVF_CLOUD_FIELD_IVLAN)
-#define I40EVF_CF_FLAGS_IMAC_TEN_ID (I40EVF_CLOUD_FIELD_IMAC |\
- I40EVF_CLOUD_FIELD_TEN_ID)
-#define I40EVF_CF_FLAGS_OMAC_TEN_ID_IMAC (I40EVF_CLOUD_FIELD_OMAC |\
- I40EVF_CLOUD_FIELD_IMAC |\
- I40EVF_CLOUD_FIELD_TEN_ID)
-#define I40EVF_CF_FLAGS_IMAC_IVLAN_TEN_ID (I40EVF_CLOUD_FIELD_IMAC |\
- I40EVF_CLOUD_FIELD_IVLAN |\
- I40EVF_CLOUD_FIELD_TEN_ID)
-#define I40EVF_CF_FLAGS_IIP I40E_CLOUD_FIELD_IIP
-
-/* bookkeeping of cloud filters */
-struct i40evf_cloud_filter {
- enum i40evf_cloud_filter_state_t state;
- struct list_head list;
- struct virtchnl_filter f;
- unsigned long cookie;
- bool del; /* filter needs to be deleted */
- bool add; /* filter needs to be added */
-};
-
-/* board specific private data structure */
-struct i40evf_adapter {
- struct timer_list watchdog_timer;
- struct work_struct reset_task;
- struct work_struct adminq_task;
- struct delayed_work client_task;
- struct delayed_work init_task;
- wait_queue_head_t down_waitqueue;
- struct i40e_q_vector *q_vectors;
- struct list_head vlan_filter_list;
- struct list_head mac_filter_list;
- /* Lock to protect accesses to MAC and VLAN lists */
- spinlock_t mac_vlan_list_lock;
- char misc_vector_name[IFNAMSIZ + 9];
- int num_active_queues;
- int num_req_queues;
-
- /* TX */
- struct i40e_ring *tx_rings;
- u32 tx_timeout_count;
- u32 tx_desc_count;
-
- /* RX */
- struct i40e_ring *rx_rings;
- u64 hw_csum_rx_error;
- u32 rx_desc_count;
- int num_msix_vectors;
- int num_iwarp_msix;
- int iwarp_base_vector;
- u32 client_pending;
- struct i40e_client_instance *cinst;
- struct msix_entry *msix_entries;
-
- u32 flags;
-#define I40EVF_FLAG_RX_CSUM_ENABLED BIT(0)
-#define I40EVF_FLAG_PF_COMMS_FAILED BIT(3)
-#define I40EVF_FLAG_RESET_PENDING BIT(4)
-#define I40EVF_FLAG_RESET_NEEDED BIT(5)
-#define I40EVF_FLAG_WB_ON_ITR_CAPABLE BIT(6)
-#define I40EVF_FLAG_ADDR_SET_BY_PF BIT(8)
-#define I40EVF_FLAG_SERVICE_CLIENT_REQUESTED BIT(9)
-#define I40EVF_FLAG_CLIENT_NEEDS_OPEN BIT(10)
-#define I40EVF_FLAG_CLIENT_NEEDS_CLOSE BIT(11)
-#define I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS BIT(12)
-#define I40EVF_FLAG_PROMISC_ON BIT(13)
-#define I40EVF_FLAG_ALLMULTI_ON BIT(14)
-#define I40EVF_FLAG_LEGACY_RX BIT(15)
-#define I40EVF_FLAG_REINIT_ITR_NEEDED BIT(16)
-#define I40EVF_FLAG_QUEUES_DISABLED BIT(17)
-/* duplicates for common code */
-#define I40E_FLAG_DCB_ENABLED 0
-#define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED
-#define I40E_FLAG_LEGACY_RX I40EVF_FLAG_LEGACY_RX
- /* flags for admin queue service task */
- u32 aq_required;
-#define I40EVF_FLAG_AQ_ENABLE_QUEUES BIT(0)
-#define I40EVF_FLAG_AQ_DISABLE_QUEUES BIT(1)
-#define I40EVF_FLAG_AQ_ADD_MAC_FILTER BIT(2)
-#define I40EVF_FLAG_AQ_ADD_VLAN_FILTER BIT(3)
-#define I40EVF_FLAG_AQ_DEL_MAC_FILTER BIT(4)
-#define I40EVF_FLAG_AQ_DEL_VLAN_FILTER BIT(5)
-#define I40EVF_FLAG_AQ_CONFIGURE_QUEUES BIT(6)
-#define I40EVF_FLAG_AQ_MAP_VECTORS BIT(7)
-#define I40EVF_FLAG_AQ_HANDLE_RESET BIT(8)
-#define I40EVF_FLAG_AQ_CONFIGURE_RSS BIT(9) /* direct AQ config */
-#define I40EVF_FLAG_AQ_GET_CONFIG BIT(10)
-/* Newer style, RSS done by the PF so we can ignore hardware vagaries. */
-#define I40EVF_FLAG_AQ_GET_HENA BIT(11)
-#define I40EVF_FLAG_AQ_SET_HENA BIT(12)
-#define I40EVF_FLAG_AQ_SET_RSS_KEY BIT(13)
-#define I40EVF_FLAG_AQ_SET_RSS_LUT BIT(14)
-#define I40EVF_FLAG_AQ_REQUEST_PROMISC BIT(15)
-#define I40EVF_FLAG_AQ_RELEASE_PROMISC BIT(16)
-#define I40EVF_FLAG_AQ_REQUEST_ALLMULTI BIT(17)
-#define I40EVF_FLAG_AQ_RELEASE_ALLMULTI BIT(18)
-#define I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING BIT(19)
-#define I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING BIT(20)
-#define I40EVF_FLAG_AQ_ENABLE_CHANNELS BIT(21)
-#define I40EVF_FLAG_AQ_DISABLE_CHANNELS BIT(22)
-#define I40EVF_FLAG_AQ_ADD_CLOUD_FILTER BIT(23)
-#define I40EVF_FLAG_AQ_DEL_CLOUD_FILTER BIT(24)
-
- /* OS defined structs */
- struct net_device *netdev;
- struct pci_dev *pdev;
-
- struct i40e_hw hw; /* defined in i40e_type.h */
-
- enum i40evf_state_t state;
- unsigned long crit_section;
-
- struct work_struct watchdog_task;
- bool netdev_registered;
- bool link_up;
- enum virtchnl_link_speed link_speed;
- enum virtchnl_ops current_op;
-#define CLIENT_ALLOWED(_a) ((_a)->vf_res ? \
- (_a)->vf_res->vf_cap_flags & \
- VIRTCHNL_VF_OFFLOAD_IWARP : \
- 0)
-#define CLIENT_ENABLED(_a) ((_a)->cinst)
-/* RSS by the PF should be preferred over RSS via other methods. */
-#define RSS_PF(_a) ((_a)->vf_res->vf_cap_flags & \
- VIRTCHNL_VF_OFFLOAD_RSS_PF)
-#define RSS_AQ(_a) ((_a)->vf_res->vf_cap_flags & \
- VIRTCHNL_VF_OFFLOAD_RSS_AQ)
-#define RSS_REG(_a) (!((_a)->vf_res->vf_cap_flags & \
- (VIRTCHNL_VF_OFFLOAD_RSS_AQ | \
- VIRTCHNL_VF_OFFLOAD_RSS_PF)))
-#define VLAN_ALLOWED(_a) ((_a)->vf_res->vf_cap_flags & \
- VIRTCHNL_VF_OFFLOAD_VLAN)
- struct virtchnl_vf_resource *vf_res; /* incl. all VSIs */
- struct virtchnl_vsi_resource *vsi_res; /* our LAN VSI */
- struct virtchnl_version_info pf_version;
-#define PF_IS_V11(_a) (((_a)->pf_version.major == 1) && \
- ((_a)->pf_version.minor == 1))
- u16 msg_enable;
- struct i40e_eth_stats current_stats;
- struct i40e_vsi vsi;
- u32 aq_wait_count;
- /* RSS stuff */
- u64 hena;
- u16 rss_key_size;
- u16 rss_lut_size;
- u8 *rss_key;
- u8 *rss_lut;
- /* ADQ related members */
- struct i40evf_channel_config ch_config;
- u8 num_tc;
- struct list_head cloud_filter_list;
- /* lock to protest access to the cloud filter list */
- spinlock_t cloud_filter_list_lock;
- u16 num_cloud_filters;
-};
-
-
-/* Ethtool Private Flags */
-
-/* lan device */
-struct i40e_device {
- struct list_head list;
- struct i40evf_adapter *vf;
-};
-
-/* needed by i40evf_ethtool.c */
-extern char i40evf_driver_name[];
-extern const char i40evf_driver_version[];
-
-int i40evf_up(struct i40evf_adapter *adapter);
-void i40evf_down(struct i40evf_adapter *adapter);
-int i40evf_process_config(struct i40evf_adapter *adapter);
-void i40evf_schedule_reset(struct i40evf_adapter *adapter);
-void i40evf_reset(struct i40evf_adapter *adapter);
-void i40evf_set_ethtool_ops(struct net_device *netdev);
-void i40evf_update_stats(struct i40evf_adapter *adapter);
-void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter);
-int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter);
-void i40evf_irq_enable_queues(struct i40evf_adapter *adapter, u32 mask);
-void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter);
-void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter);
-
-void i40e_napi_add_all(struct i40evf_adapter *adapter);
-void i40e_napi_del_all(struct i40evf_adapter *adapter);
-
-int i40evf_send_api_ver(struct i40evf_adapter *adapter);
-int i40evf_verify_api_ver(struct i40evf_adapter *adapter);
-int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter);
-int i40evf_get_vf_config(struct i40evf_adapter *adapter);
-void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush);
-void i40evf_configure_queues(struct i40evf_adapter *adapter);
-void i40evf_deconfigure_queues(struct i40evf_adapter *adapter);
-void i40evf_enable_queues(struct i40evf_adapter *adapter);
-void i40evf_disable_queues(struct i40evf_adapter *adapter);
-void i40evf_map_queues(struct i40evf_adapter *adapter);
-int i40evf_request_queues(struct i40evf_adapter *adapter, int num);
-void i40evf_add_ether_addrs(struct i40evf_adapter *adapter);
-void i40evf_del_ether_addrs(struct i40evf_adapter *adapter);
-void i40evf_add_vlans(struct i40evf_adapter *adapter);
-void i40evf_del_vlans(struct i40evf_adapter *adapter);
-void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags);
-void i40evf_request_stats(struct i40evf_adapter *adapter);
-void i40evf_request_reset(struct i40evf_adapter *adapter);
-void i40evf_get_hena(struct i40evf_adapter *adapter);
-void i40evf_set_hena(struct i40evf_adapter *adapter);
-void i40evf_set_rss_key(struct i40evf_adapter *adapter);
-void i40evf_set_rss_lut(struct i40evf_adapter *adapter);
-void i40evf_enable_vlan_stripping(struct i40evf_adapter *adapter);
-void i40evf_disable_vlan_stripping(struct i40evf_adapter *adapter);
-void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
- enum virtchnl_ops v_opcode,
- i40e_status v_retval, u8 *msg, u16 msglen);
-int i40evf_config_rss(struct i40evf_adapter *adapter);
-int i40evf_lan_add_device(struct i40evf_adapter *adapter);
-int i40evf_lan_del_device(struct i40evf_adapter *adapter);
-void i40evf_client_subtask(struct i40evf_adapter *adapter);
-void i40evf_notify_client_message(struct i40e_vsi *vsi, u8 *msg, u16 len);
-void i40evf_notify_client_l2_params(struct i40e_vsi *vsi);
-void i40evf_notify_client_open(struct i40e_vsi *vsi);
-void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset);
-void i40evf_enable_channels(struct i40evf_adapter *adapter);
-void i40evf_disable_channels(struct i40evf_adapter *adapter);
-void i40evf_add_cloud_filter(struct i40evf_adapter *adapter);
-void i40evf_del_cloud_filter(struct i40evf_adapter *adapter);
-#endif /* _I40EVF_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_client.c b/drivers/net/ethernet/intel/i40evf/i40evf_client.c
deleted file mode 100644
index 3cc9d60d0d72..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40evf_client.c
+++ /dev/null
@@ -1,579 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#include <linux/list.h>
-#include <linux/errno.h>
-
-#include "i40evf.h"
-#include "i40e_prototype.h"
-#include "i40evf_client.h"
-
-static
-const char i40evf_client_interface_version_str[] = I40EVF_CLIENT_VERSION_STR;
-static struct i40e_client *vf_registered_client;
-static LIST_HEAD(i40evf_devices);
-static DEFINE_MUTEX(i40evf_device_mutex);
-
-static u32 i40evf_client_virtchnl_send(struct i40e_info *ldev,
- struct i40e_client *client,
- u8 *msg, u16 len);
-
-static int i40evf_client_setup_qvlist(struct i40e_info *ldev,
- struct i40e_client *client,
- struct i40e_qvlist_info *qvlist_info);
-
-static struct i40e_ops i40evf_lan_ops = {
- .virtchnl_send = i40evf_client_virtchnl_send,
- .setup_qvlist = i40evf_client_setup_qvlist,
-};
-
-/**
- * i40evf_client_get_params - retrieve relevant client parameters
- * @vsi: VSI with parameters
- * @params: client param struct
- **/
-static
-void i40evf_client_get_params(struct i40e_vsi *vsi, struct i40e_params *params)
-{
- int i;
-
- memset(params, 0, sizeof(struct i40e_params));
- params->mtu = vsi->netdev->mtu;
- params->link_up = vsi->back->link_up;
-
- for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
- params->qos.prio_qos[i].tc = 0;
- params->qos.prio_qos[i].qs_handle = vsi->qs_handle;
- }
-}
-
-/**
- * i40evf_notify_client_message - call the client message receive callback
- * @vsi: the VSI associated with this client
- * @msg: message buffer
- * @len: length of message
- *
- * If there is a client to this VSI, call the client
- **/
-void i40evf_notify_client_message(struct i40e_vsi *vsi, u8 *msg, u16 len)
-{
- struct i40e_client_instance *cinst;
-
- if (!vsi)
- return;
-
- cinst = vsi->back->cinst;
- if (!cinst || !cinst->client || !cinst->client->ops ||
- !cinst->client->ops->virtchnl_receive) {
- dev_dbg(&vsi->back->pdev->dev,
- "Cannot locate client instance virtchnl_receive function\n");
- return;
- }
- cinst->client->ops->virtchnl_receive(&cinst->lan_info, cinst->client,
- msg, len);
-}
-
-/**
- * i40evf_notify_client_l2_params - call the client notify callback
- * @vsi: the VSI with l2 param changes
- *
- * If there is a client to this VSI, call the client
- **/
-void i40evf_notify_client_l2_params(struct i40e_vsi *vsi)
-{
- struct i40e_client_instance *cinst;
- struct i40e_params params;
-
- if (!vsi)
- return;
-
- cinst = vsi->back->cinst;
-
- if (!cinst || !cinst->client || !cinst->client->ops ||
- !cinst->client->ops->l2_param_change) {
- dev_dbg(&vsi->back->pdev->dev,
- "Cannot locate client instance l2_param_change function\n");
- return;
- }
- i40evf_client_get_params(vsi, ¶ms);
- cinst->lan_info.params = params;
- cinst->client->ops->l2_param_change(&cinst->lan_info, cinst->client,
- ¶ms);
-}
-
-/**
- * i40evf_notify_client_open - call the client open callback
- * @vsi: the VSI with netdev opened
- *
- * If there is a client to this netdev, call the client with open
- **/
-void i40evf_notify_client_open(struct i40e_vsi *vsi)
-{
- struct i40evf_adapter *adapter = vsi->back;
- struct i40e_client_instance *cinst = adapter->cinst;
- int ret;
-
- if (!cinst || !cinst->client || !cinst->client->ops ||
- !cinst->client->ops->open) {
- dev_dbg(&vsi->back->pdev->dev,
- "Cannot locate client instance open function\n");
- return;
- }
- if (!(test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state))) {
- ret = cinst->client->ops->open(&cinst->lan_info, cinst->client);
- if (!ret)
- set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
- }
-}
-
-/**
- * i40evf_client_release_qvlist - send a message to the PF to release iwarp qv map
- * @ldev: pointer to L2 context.
- *
- * Return 0 on success or < 0 on error
- **/
-static int i40evf_client_release_qvlist(struct i40e_info *ldev)
-{
- struct i40evf_adapter *adapter = ldev->vf;
- i40e_status err;
-
- if (adapter->aq_required)
- return -EAGAIN;
-
- err = i40e_aq_send_msg_to_pf(&adapter->hw,
- VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP,
- I40E_SUCCESS, NULL, 0, NULL);
-
- if (err)
- dev_err(&adapter->pdev->dev,
- "Unable to send iWarp vector release message to PF, error %d, aq status %d\n",
- err, adapter->hw.aq.asq_last_status);
-
- return err;
-}
-
-/**
- * i40evf_notify_client_close - call the client close callback
- * @vsi: the VSI with netdev closed
- * @reset: true when close called due to reset pending
- *
- * If there is a client to this netdev, call the client with close
- **/
-void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset)
-{
- struct i40evf_adapter *adapter = vsi->back;
- struct i40e_client_instance *cinst = adapter->cinst;
-
- if (!cinst || !cinst->client || !cinst->client->ops ||
- !cinst->client->ops->close) {
- dev_dbg(&vsi->back->pdev->dev,
- "Cannot locate client instance close function\n");
- return;
- }
- cinst->client->ops->close(&cinst->lan_info, cinst->client, reset);
- i40evf_client_release_qvlist(&cinst->lan_info);
- clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
-}
-
-/**
- * i40evf_client_add_instance - add a client instance to the instance list
- * @adapter: pointer to the board struct
- *
- * Returns cinst ptr on success, NULL on failure
- **/
-static struct i40e_client_instance *
-i40evf_client_add_instance(struct i40evf_adapter *adapter)
-{
- struct i40e_client_instance *cinst = NULL;
- struct i40e_vsi *vsi = &adapter->vsi;
- struct netdev_hw_addr *mac = NULL;
- struct i40e_params params;
-
- if (!vf_registered_client)
- goto out;
-
- if (adapter->cinst) {
- cinst = adapter->cinst;
- goto out;
- }
-
- cinst = kzalloc(sizeof(*cinst), GFP_KERNEL);
- if (!cinst)
- goto out;
-
- cinst->lan_info.vf = (void *)adapter;
- cinst->lan_info.netdev = vsi->netdev;
- cinst->lan_info.pcidev = adapter->pdev;
- cinst->lan_info.fid = 0;
- cinst->lan_info.ftype = I40E_CLIENT_FTYPE_VF;
- cinst->lan_info.hw_addr = adapter->hw.hw_addr;
- cinst->lan_info.ops = &i40evf_lan_ops;
- cinst->lan_info.version.major = I40EVF_CLIENT_VERSION_MAJOR;
- cinst->lan_info.version.minor = I40EVF_CLIENT_VERSION_MINOR;
- cinst->lan_info.version.build = I40EVF_CLIENT_VERSION_BUILD;
- i40evf_client_get_params(vsi, ¶ms);
- cinst->lan_info.params = params;
- set_bit(__I40E_CLIENT_INSTANCE_NONE, &cinst->state);
-
- cinst->lan_info.msix_count = adapter->num_iwarp_msix;
- cinst->lan_info.msix_entries =
- &adapter->msix_entries[adapter->iwarp_base_vector];
-
- mac = list_first_entry(&cinst->lan_info.netdev->dev_addrs.list,
- struct netdev_hw_addr, list);
- if (mac)
- ether_addr_copy(cinst->lan_info.lanmac, mac->addr);
- else
- dev_err(&adapter->pdev->dev, "MAC address list is empty!\n");
-
- cinst->client = vf_registered_client;
- adapter->cinst = cinst;
-out:
- return cinst;
-}
-
-/**
- * i40evf_client_del_instance - removes a client instance from the list
- * @adapter: pointer to the board struct
- *
- **/
-static
-void i40evf_client_del_instance(struct i40evf_adapter *adapter)
-{
- kfree(adapter->cinst);
- adapter->cinst = NULL;
-}
-
-/**
- * i40evf_client_subtask - client maintenance work
- * @adapter: board private structure
- **/
-void i40evf_client_subtask(struct i40evf_adapter *adapter)
-{
- struct i40e_client *client = vf_registered_client;
- struct i40e_client_instance *cinst;
- int ret = 0;
-
- if (adapter->state < __I40EVF_DOWN)
- return;
-
- /* first check client is registered */
- if (!client)
- return;
-
- /* Add the client instance to the instance list */
- cinst = i40evf_client_add_instance(adapter);
- if (!cinst)
- return;
-
- dev_info(&adapter->pdev->dev, "Added instance of Client %s\n",
- client->name);
-
- if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {
- /* Send an Open request to the client */
-
- if (client->ops && client->ops->open)
- ret = client->ops->open(&cinst->lan_info, client);
- if (!ret)
- set_bit(__I40E_CLIENT_INSTANCE_OPENED,
- &cinst->state);
- else
- /* remove client instance */
- i40evf_client_del_instance(adapter);
- }
-}
-
-/**
- * i40evf_lan_add_device - add a lan device struct to the list of lan devices
- * @adapter: pointer to the board struct
- *
- * Returns 0 on success or none 0 on error
- **/
-int i40evf_lan_add_device(struct i40evf_adapter *adapter)
-{
- struct i40e_device *ldev;
- int ret = 0;
-
- mutex_lock(&i40evf_device_mutex);
- list_for_each_entry(ldev, &i40evf_devices, list) {
- if (ldev->vf == adapter) {
- ret = -EEXIST;
- goto out;
- }
- }
- ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
- if (!ldev) {
- ret = -ENOMEM;
- goto out;
- }
- ldev->vf = adapter;
- INIT_LIST_HEAD(&ldev->list);
- list_add(&ldev->list, &i40evf_devices);
- dev_info(&adapter->pdev->dev, "Added LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
- adapter->hw.bus.bus_id, adapter->hw.bus.device,
- adapter->hw.bus.func);
-
- /* Since in some cases register may have happened before a device gets
- * added, we can schedule a subtask to go initiate the clients.
- */
- adapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
-
-out:
- mutex_unlock(&i40evf_device_mutex);
- return ret;
-}
-
-/**
- * i40evf_lan_del_device - removes a lan device from the device list
- * @adapter: pointer to the board struct
- *
- * Returns 0 on success or non-0 on error
- **/
-int i40evf_lan_del_device(struct i40evf_adapter *adapter)
-{
- struct i40e_device *ldev, *tmp;
- int ret = -ENODEV;
-
- mutex_lock(&i40evf_device_mutex);
- list_for_each_entry_safe(ldev, tmp, &i40evf_devices, list) {
- if (ldev->vf == adapter) {
- dev_info(&adapter->pdev->dev,
- "Deleted LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
- adapter->hw.bus.bus_id, adapter->hw.bus.device,
- adapter->hw.bus.func);
- list_del(&ldev->list);
- kfree(ldev);
- ret = 0;
- break;
- }
- }
-
- mutex_unlock(&i40evf_device_mutex);
- return ret;
-}
-
-/**
- * i40evf_client_release - release client specific resources
- * @client: pointer to the registered client
- *
- **/
-static void i40evf_client_release(struct i40e_client *client)
-{
- struct i40e_client_instance *cinst;
- struct i40e_device *ldev;
- struct i40evf_adapter *adapter;
-
- mutex_lock(&i40evf_device_mutex);
- list_for_each_entry(ldev, &i40evf_devices, list) {
- adapter = ldev->vf;
- cinst = adapter->cinst;
- if (!cinst)
- continue;
- if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {
- if (client->ops && client->ops->close)
- client->ops->close(&cinst->lan_info, client,
- false);
- i40evf_client_release_qvlist(&cinst->lan_info);
- clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
-
- dev_warn(&adapter->pdev->dev,
- "Client %s instance closed\n", client->name);
- }
- /* delete the client instance */
- i40evf_client_del_instance(adapter);
- dev_info(&adapter->pdev->dev, "Deleted client instance of Client %s\n",
- client->name);
- }
- mutex_unlock(&i40evf_device_mutex);
-}
-
-/**
- * i40evf_client_prepare - prepare client specific resources
- * @client: pointer to the registered client
- *
- **/
-static void i40evf_client_prepare(struct i40e_client *client)
-{
- struct i40e_device *ldev;
- struct i40evf_adapter *adapter;
-
- mutex_lock(&i40evf_device_mutex);
- list_for_each_entry(ldev, &i40evf_devices, list) {
- adapter = ldev->vf;
- /* Signal the watchdog to service the client */
- adapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
- }
- mutex_unlock(&i40evf_device_mutex);
-}
-
-/**
- * i40evf_client_virtchnl_send - send a message to the PF instance
- * @ldev: pointer to L2 context.
- * @client: Client pointer.
- * @msg: pointer to message buffer
- * @len: message length
- *
- * Return 0 on success or < 0 on error
- **/
-static u32 i40evf_client_virtchnl_send(struct i40e_info *ldev,
- struct i40e_client *client,
- u8 *msg, u16 len)
-{
- struct i40evf_adapter *adapter = ldev->vf;
- i40e_status err;
-
- if (adapter->aq_required)
- return -EAGAIN;
-
- err = i40e_aq_send_msg_to_pf(&adapter->hw, VIRTCHNL_OP_IWARP,
- I40E_SUCCESS, msg, len, NULL);
- if (err)
- dev_err(&adapter->pdev->dev, "Unable to send iWarp message to PF, error %d, aq status %d\n",
- err, adapter->hw.aq.asq_last_status);
-
- return err;
-}
-
-/**
- * i40evf_client_setup_qvlist - send a message to the PF to setup iwarp qv map
- * @ldev: pointer to L2 context.
- * @client: Client pointer.
- * @qvlist_info: queue and vector list
- *
- * Return 0 on success or < 0 on error
- **/
-static int i40evf_client_setup_qvlist(struct i40e_info *ldev,
- struct i40e_client *client,
- struct i40e_qvlist_info *qvlist_info)
-{
- struct virtchnl_iwarp_qvlist_info *v_qvlist_info;
- struct i40evf_adapter *adapter = ldev->vf;
- struct i40e_qv_info *qv_info;
- i40e_status err;
- u32 v_idx, i;
- u32 msg_size;
-
- if (adapter->aq_required)
- return -EAGAIN;
-
- /* A quick check on whether the vectors belong to the client */
- for (i = 0; i < qvlist_info->num_vectors; i++) {
- qv_info = &qvlist_info->qv_info[i];
- if (!qv_info)
- continue;
- v_idx = qv_info->v_idx;
- if ((v_idx >=
- (adapter->iwarp_base_vector + adapter->num_iwarp_msix)) ||
- (v_idx < adapter->iwarp_base_vector))
- return -EINVAL;
- }
-
- v_qvlist_info = (struct virtchnl_iwarp_qvlist_info *)qvlist_info;
- msg_size = sizeof(struct virtchnl_iwarp_qvlist_info) +
- (sizeof(struct virtchnl_iwarp_qv_info) *
- (v_qvlist_info->num_vectors - 1));
-
- adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP);
- err = i40e_aq_send_msg_to_pf(&adapter->hw,
- VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP,
- I40E_SUCCESS, (u8 *)v_qvlist_info, msg_size, NULL);
-
- if (err) {
- dev_err(&adapter->pdev->dev,
- "Unable to send iWarp vector config message to PF, error %d, aq status %d\n",
- err, adapter->hw.aq.asq_last_status);
- goto out;
- }
-
- err = -EBUSY;
- for (i = 0; i < 5; i++) {
- msleep(100);
- if (!(adapter->client_pending &
- BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP))) {
- err = 0;
- break;
- }
- }
-out:
- return err;
-}
-
-/**
- * i40evf_register_client - Register a i40e client driver with the L2 driver
- * @client: pointer to the i40e_client struct
- *
- * Returns 0 on success or non-0 on error
- **/
-int i40evf_register_client(struct i40e_client *client)
-{
- int ret = 0;
-
- if (!client) {
- ret = -EIO;
- goto out;
- }
-
- if (strlen(client->name) == 0) {
- pr_info("i40evf: Failed to register client with no name\n");
- ret = -EIO;
- goto out;
- }
-
- if (vf_registered_client) {
- pr_info("i40evf: Client %s has already been registered!\n",
- client->name);
- ret = -EEXIST;
- goto out;
- }
-
- if ((client->version.major != I40EVF_CLIENT_VERSION_MAJOR) ||
- (client->version.minor != I40EVF_CLIENT_VERSION_MINOR)) {
- pr_info("i40evf: Failed to register client %s due to mismatched client interface version\n",
- client->name);
- pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n",
- client->version.major, client->version.minor,
- client->version.build,
- i40evf_client_interface_version_str);
- ret = -EIO;
- goto out;
- }
-
- vf_registered_client = client;
-
- i40evf_client_prepare(client);
-
- pr_info("i40evf: Registered client %s with return code %d\n",
- client->name, ret);
-out:
- return ret;
-}
-EXPORT_SYMBOL(i40evf_register_client);
-
-/**
- * i40evf_unregister_client - Unregister a i40e client driver with the L2 driver
- * @client: pointer to the i40e_client struct
- *
- * Returns 0 on success or non-0 on error
- **/
-int i40evf_unregister_client(struct i40e_client *client)
-{
- int ret = 0;
-
- /* When a unregister request comes through we would have to send
- * a close for each of the client instances that were opened.
- * client_release function is called to handle this.
- */
- i40evf_client_release(client);
-
- if (vf_registered_client != client) {
- pr_info("i40evf: Client %s has not been registered\n",
- client->name);
- ret = -ENODEV;
- goto out;
- }
- vf_registered_client = NULL;
- pr_info("i40evf: Unregistered client %s\n", client->name);
-out:
- return ret;
-}
-EXPORT_SYMBOL(i40evf_unregister_client);
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_client.h b/drivers/net/ethernet/intel/i40evf/i40evf_client.h
deleted file mode 100644
index 5585f362048a..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40evf_client.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#ifndef _I40EVF_CLIENT_H_
-#define _I40EVF_CLIENT_H_
-
-#define I40EVF_CLIENT_STR_LENGTH 10
-
-/* Client interface version should be updated anytime there is a change in the
- * existing APIs or data structures.
- */
-#define I40EVF_CLIENT_VERSION_MAJOR 0
-#define I40EVF_CLIENT_VERSION_MINOR 01
-#define I40EVF_CLIENT_VERSION_BUILD 00
-#define I40EVF_CLIENT_VERSION_STR \
- __stringify(I40EVF_CLIENT_VERSION_MAJOR) "." \
- __stringify(I40EVF_CLIENT_VERSION_MINOR) "." \
- __stringify(I40EVF_CLIENT_VERSION_BUILD)
-
-struct i40e_client_version {
- u8 major;
- u8 minor;
- u8 build;
- u8 rsvd;
-};
-
-enum i40e_client_state {
- __I40E_CLIENT_NULL,
- __I40E_CLIENT_REGISTERED
-};
-
-enum i40e_client_instance_state {
- __I40E_CLIENT_INSTANCE_NONE,
- __I40E_CLIENT_INSTANCE_OPENED,
-};
-
-struct i40e_ops;
-struct i40e_client;
-
-/* HW does not define a type value for AEQ; only for RX/TX and CEQ.
- * In order for us to keep the interface simple, SW will define a
- * unique type value for AEQ.
- */
-#define I40E_QUEUE_TYPE_PE_AEQ 0x80
-#define I40E_QUEUE_INVALID_IDX 0xFFFF
-
-struct i40e_qv_info {
- u32 v_idx; /* msix_vector */
- u16 ceq_idx;
- u16 aeq_idx;
- u8 itr_idx;
-};
-
-struct i40e_qvlist_info {
- u32 num_vectors;
- struct i40e_qv_info qv_info[1];
-};
-
-#define I40E_CLIENT_MSIX_ALL 0xFFFFFFFF
-
-/* set of LAN parameters useful for clients managed by LAN */
-
-/* Struct to hold per priority info */
-struct i40e_prio_qos_params {
- u16 qs_handle; /* qs handle for prio */
- u8 tc; /* TC mapped to prio */
- u8 reserved;
-};
-
-#define I40E_CLIENT_MAX_USER_PRIORITY 8
-/* Struct to hold Client QoS */
-struct i40e_qos_params {
- struct i40e_prio_qos_params prio_qos[I40E_CLIENT_MAX_USER_PRIORITY];
-};
-
-struct i40e_params {
- struct i40e_qos_params qos;
- u16 mtu;
- u16 link_up; /* boolean */
-};
-
-/* Structure to hold LAN device info for a client device */
-struct i40e_info {
- struct i40e_client_version version;
- u8 lanmac[6];
- struct net_device *netdev;
- struct pci_dev *pcidev;
- u8 __iomem *hw_addr;
- u8 fid; /* function id, PF id or VF id */
-#define I40E_CLIENT_FTYPE_PF 0
-#define I40E_CLIENT_FTYPE_VF 1
- u8 ftype; /* function type, PF or VF */
- void *vf; /* cast to i40evf_adapter */
-
- /* All L2 params that could change during the life span of the device
- * and needs to be communicated to the client when they change
- */
- struct i40e_params params;
- struct i40e_ops *ops;
-
- u16 msix_count; /* number of msix vectors*/
- /* Array down below will be dynamically allocated based on msix_count */
- struct msix_entry *msix_entries;
- u16 itr_index; /* Which ITR index the PE driver is suppose to use */
-};
-
-struct i40e_ops {
- /* setup_q_vector_list enables queues with a particular vector */
- int (*setup_qvlist)(struct i40e_info *ldev, struct i40e_client *client,
- struct i40e_qvlist_info *qv_info);
-
- u32 (*virtchnl_send)(struct i40e_info *ldev, struct i40e_client *client,
- u8 *msg, u16 len);
-
- /* If the PE Engine is unresponsive, RDMA driver can request a reset.*/
- void (*request_reset)(struct i40e_info *ldev,
- struct i40e_client *client);
-};
-
-struct i40e_client_ops {
- /* Should be called from register_client() or whenever the driver is
- * ready to create a specific client instance.
- */
- int (*open)(struct i40e_info *ldev, struct i40e_client *client);
-
- /* Should be closed when netdev is unavailable or when unregister
- * call comes in. If the close happens due to a reset, set the reset
- * bit to true.
- */
- void (*close)(struct i40e_info *ldev, struct i40e_client *client,
- bool reset);
-
- /* called when some l2 managed parameters changes - mss */
- void (*l2_param_change)(struct i40e_info *ldev,
- struct i40e_client *client,
- struct i40e_params *params);
-
- /* called when a message is received from the PF */
- int (*virtchnl_receive)(struct i40e_info *ldev,
- struct i40e_client *client,
- u8 *msg, u16 len);
-};
-
-/* Client device */
-struct i40e_client_instance {
- struct list_head list;
- struct i40e_info lan_info;
- struct i40e_client *client;
- unsigned long state;
-};
-
-struct i40e_client {
- struct list_head list; /* list of registered clients */
- char name[I40EVF_CLIENT_STR_LENGTH];
- struct i40e_client_version version;
- unsigned long state; /* client state */
- atomic_t ref_cnt; /* Count of all the client devices of this kind */
- u32 flags;
-#define I40E_CLIENT_FLAGS_LAUNCH_ON_PROBE BIT(0)
-#define I40E_TX_FLAGS_NOTIFY_OTHER_EVENTS BIT(2)
- u8 type;
-#define I40E_CLIENT_IWARP 0
- struct i40e_client_ops *ops; /* client ops provided by the client */
-};
-
-/* used by clients */
-int i40evf_register_client(struct i40e_client *client);
-int i40evf_unregister_client(struct i40e_client *client);
-#endif /* _I40EVF_CLIENT_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
deleted file mode 100644
index 69efe0aec76a..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ /dev/null
@@ -1,820 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-/* ethtool support for i40evf */
-#include "i40evf.h"
-
-#include <linux/uaccess.h>
-
-struct i40evf_stats {
- char stat_string[ETH_GSTRING_LEN];
- int stat_offset;
-};
-
-#define I40EVF_STAT(_name, _stat) { \
- .stat_string = _name, \
- .stat_offset = offsetof(struct i40evf_adapter, _stat) \
-}
-
-/* All stats are u64, so we don't need to track the size of the field. */
-static const struct i40evf_stats i40evf_gstrings_stats[] = {
- I40EVF_STAT("rx_bytes", current_stats.rx_bytes),
- I40EVF_STAT("rx_unicast", current_stats.rx_unicast),
- I40EVF_STAT("rx_multicast", current_stats.rx_multicast),
- I40EVF_STAT("rx_broadcast", current_stats.rx_broadcast),
- I40EVF_STAT("rx_discards", current_stats.rx_discards),
- I40EVF_STAT("rx_unknown_protocol", current_stats.rx_unknown_protocol),
- I40EVF_STAT("tx_bytes", current_stats.tx_bytes),
- I40EVF_STAT("tx_unicast", current_stats.tx_unicast),
- I40EVF_STAT("tx_multicast", current_stats.tx_multicast),
- I40EVF_STAT("tx_broadcast", current_stats.tx_broadcast),
- I40EVF_STAT("tx_discards", current_stats.tx_discards),
- I40EVF_STAT("tx_errors", current_stats.tx_errors),
-};
-
-#define I40EVF_GLOBAL_STATS_LEN ARRAY_SIZE(i40evf_gstrings_stats)
-#define I40EVF_QUEUE_STATS_LEN(_dev) \
- (((struct i40evf_adapter *)\
- netdev_priv(_dev))->num_active_queues \
- * 2 * (sizeof(struct i40e_queue_stats) / sizeof(u64)))
-#define I40EVF_STATS_LEN(_dev) \
- (I40EVF_GLOBAL_STATS_LEN + I40EVF_QUEUE_STATS_LEN(_dev))
-
-/* For now we have one and only one private flag and it is only defined
- * when we have support for the SKIP_CPU_SYNC DMA attribute. Instead
- * of leaving all this code sitting around empty we will strip it unless
- * our one private flag is actually available.
- */
-struct i40evf_priv_flags {
- char flag_string[ETH_GSTRING_LEN];
- u32 flag;
- bool read_only;
-};
-
-#define I40EVF_PRIV_FLAG(_name, _flag, _read_only) { \
- .flag_string = _name, \
- .flag = _flag, \
- .read_only = _read_only, \
-}
-
-static const struct i40evf_priv_flags i40evf_gstrings_priv_flags[] = {
- I40EVF_PRIV_FLAG("legacy-rx", I40EVF_FLAG_LEGACY_RX, 0),
-};
-
-#define I40EVF_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40evf_gstrings_priv_flags)
-
-/**
- * i40evf_get_link_ksettings - Get Link Speed and Duplex settings
- * @netdev: network interface device structure
- * @cmd: ethtool command
- *
- * Reports speed/duplex settings. Because this is a VF, we don't know what
- * kind of link we really have, so we fake it.
- **/
-static int i40evf_get_link_ksettings(struct net_device *netdev,
- struct ethtool_link_ksettings *cmd)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- ethtool_link_ksettings_zero_link_mode(cmd, supported);
- cmd->base.autoneg = AUTONEG_DISABLE;
- cmd->base.port = PORT_NONE;
- /* Set speed and duplex */
- switch (adapter->link_speed) {
- case I40E_LINK_SPEED_40GB:
- cmd->base.speed = SPEED_40000;
- break;
- case I40E_LINK_SPEED_25GB:
-#ifdef SPEED_25000
- cmd->base.speed = SPEED_25000;
-#else
- netdev_info(netdev,
- "Speed is 25G, display not supported by this version of ethtool.\n");
-#endif
- break;
- case I40E_LINK_SPEED_20GB:
- cmd->base.speed = SPEED_20000;
- break;
- case I40E_LINK_SPEED_10GB:
- cmd->base.speed = SPEED_10000;
- break;
- case I40E_LINK_SPEED_1GB:
- cmd->base.speed = SPEED_1000;
- break;
- case I40E_LINK_SPEED_100MB:
- cmd->base.speed = SPEED_100;
- break;
- default:
- break;
- }
- cmd->base.duplex = DUPLEX_FULL;
-
- return 0;
-}
-
-/**
- * i40evf_get_sset_count - Get length of string set
- * @netdev: network interface device structure
- * @sset: id of string set
- *
- * Reports size of string table. This driver only supports
- * strings for statistics.
- **/
-static int i40evf_get_sset_count(struct net_device *netdev, int sset)
-{
- if (sset == ETH_SS_STATS)
- return I40EVF_STATS_LEN(netdev);
- else if (sset == ETH_SS_PRIV_FLAGS)
- return I40EVF_PRIV_FLAGS_STR_LEN;
- else
- return -EINVAL;
-}
-
-/**
- * i40evf_get_ethtool_stats - report device statistics
- * @netdev: network interface device structure
- * @stats: ethtool statistics structure
- * @data: pointer to data buffer
- *
- * All statistics are added to the data buffer as an array of u64.
- **/
-static void i40evf_get_ethtool_stats(struct net_device *netdev,
- struct ethtool_stats *stats, u64 *data)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- unsigned int i, j;
- char *p;
-
- for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
- p = (char *)adapter + i40evf_gstrings_stats[i].stat_offset;
- data[i] = *(u64 *)p;
- }
- for (j = 0; j < adapter->num_active_queues; j++) {
- data[i++] = adapter->tx_rings[j].stats.packets;
- data[i++] = adapter->tx_rings[j].stats.bytes;
- }
- for (j = 0; j < adapter->num_active_queues; j++) {
- data[i++] = adapter->rx_rings[j].stats.packets;
- data[i++] = adapter->rx_rings[j].stats.bytes;
- }
-}
-
-/**
- * i40evf_get_strings - Get string set
- * @netdev: network interface device structure
- * @sset: id of string set
- * @data: buffer for string data
- *
- * Builds stats string table.
- **/
-static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- u8 *p = data;
- int i;
-
- if (sset == ETH_SS_STATS) {
- for (i = 0; i < (int)I40EVF_GLOBAL_STATS_LEN; i++) {
- memcpy(p, i40evf_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
- for (i = 0; i < adapter->num_active_queues; i++) {
- snprintf(p, ETH_GSTRING_LEN, "tx-%u.packets", i);
- p += ETH_GSTRING_LEN;
- snprintf(p, ETH_GSTRING_LEN, "tx-%u.bytes", i);
- p += ETH_GSTRING_LEN;
- }
- for (i = 0; i < adapter->num_active_queues; i++) {
- snprintf(p, ETH_GSTRING_LEN, "rx-%u.packets", i);
- p += ETH_GSTRING_LEN;
- snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i);
- p += ETH_GSTRING_LEN;
- }
- } else if (sset == ETH_SS_PRIV_FLAGS) {
- for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
- snprintf(p, ETH_GSTRING_LEN, "%s",
- i40evf_gstrings_priv_flags[i].flag_string);
- p += ETH_GSTRING_LEN;
- }
- }
-}
-
-/**
- * i40evf_get_priv_flags - report device private flags
- * @netdev: network interface device structure
- *
- * The get string set count and the string set should be matched for each
- * flag returned. Add new strings for each flag to the i40e_gstrings_priv_flags
- * array.
- *
- * Returns a u32 bitmap of flags.
- **/
-static u32 i40evf_get_priv_flags(struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- u32 i, ret_flags = 0;
-
- for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
- const struct i40evf_priv_flags *priv_flags;
-
- priv_flags = &i40evf_gstrings_priv_flags[i];
-
- if (priv_flags->flag & adapter->flags)
- ret_flags |= BIT(i);
- }
-
- return ret_flags;
-}
-
-/**
- * i40evf_set_priv_flags - set private flags
- * @netdev: network interface device structure
- * @flags: bit flags to be set
- **/
-static int i40evf_set_priv_flags(struct net_device *netdev, u32 flags)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- u32 orig_flags, new_flags, changed_flags;
- u32 i;
-
- orig_flags = READ_ONCE(adapter->flags);
- new_flags = orig_flags;
-
- for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
- const struct i40evf_priv_flags *priv_flags;
-
- priv_flags = &i40evf_gstrings_priv_flags[i];
-
- if (flags & BIT(i))
- new_flags |= priv_flags->flag;
- else
- new_flags &= ~(priv_flags->flag);
-
- if (priv_flags->read_only &&
- ((orig_flags ^ new_flags) & ~BIT(i)))
- return -EOPNOTSUPP;
- }
-
- /* Before we finalize any flag changes, any checks which we need to
- * perform to determine if the new flags will be supported should go
- * here...
- */
-
- /* Compare and exchange the new flags into place. If we failed, that
- * is if cmpxchg returns anything but the old value, this means
- * something else must have modified the flags variable since we
- * copied it. We'll just punt with an error and log something in the
- * message buffer.
- */
- if (cmpxchg(&adapter->flags, orig_flags, new_flags) != orig_flags) {
- dev_warn(&adapter->pdev->dev,
- "Unable to update adapter->flags as it was modified by another thread...\n");
- return -EAGAIN;
- }
-
- changed_flags = orig_flags ^ new_flags;
-
- /* Process any additional changes needed as a result of flag changes.
- * The changed_flags value reflects the list of bits that were changed
- * in the code above.
- */
-
- /* issue a reset to force legacy-rx change to take effect */
- if (changed_flags & I40EVF_FLAG_LEGACY_RX) {
- if (netif_running(netdev)) {
- adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
- schedule_work(&adapter->reset_task);
- }
- }
-
- return 0;
-}
-
-/**
- * i40evf_get_msglevel - Get debug message level
- * @netdev: network interface device structure
- *
- * Returns current debug message level.
- **/
-static u32 i40evf_get_msglevel(struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- return adapter->msg_enable;
-}
-
-/**
- * i40evf_set_msglevel - Set debug message level
- * @netdev: network interface device structure
- * @data: message level
- *
- * Set current debug message level. Higher values cause the driver to
- * be noisier.
- **/
-static void i40evf_set_msglevel(struct net_device *netdev, u32 data)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- if (I40E_DEBUG_USER & data)
- adapter->hw.debug_mask = data;
- adapter->msg_enable = data;
-}
-
-/**
- * i40evf_get_drvinfo - Get driver info
- * @netdev: network interface device structure
- * @drvinfo: ethool driver info structure
- *
- * Returns information about the driver and device for display to the user.
- **/
-static void i40evf_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *drvinfo)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- strlcpy(drvinfo->driver, i40evf_driver_name, 32);
- strlcpy(drvinfo->version, i40evf_driver_version, 32);
- strlcpy(drvinfo->fw_version, "N/A", 4);
- strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
- drvinfo->n_priv_flags = I40EVF_PRIV_FLAGS_STR_LEN;
-}
-
-/**
- * i40evf_get_ringparam - Get ring parameters
- * @netdev: network interface device structure
- * @ring: ethtool ringparam structure
- *
- * Returns current ring parameters. TX and RX rings are reported separately,
- * but the number of rings is not reported.
- **/
-static void i40evf_get_ringparam(struct net_device *netdev,
- struct ethtool_ringparam *ring)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- ring->rx_max_pending = I40EVF_MAX_RXD;
- ring->tx_max_pending = I40EVF_MAX_TXD;
- ring->rx_pending = adapter->rx_desc_count;
- ring->tx_pending = adapter->tx_desc_count;
-}
-
-/**
- * i40evf_set_ringparam - Set ring parameters
- * @netdev: network interface device structure
- * @ring: ethtool ringparam structure
- *
- * Sets ring parameters. TX and RX rings are controlled separately, but the
- * number of rings is not specified, so all rings get the same settings.
- **/
-static int i40evf_set_ringparam(struct net_device *netdev,
- struct ethtool_ringparam *ring)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- u32 new_rx_count, new_tx_count;
-
- if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
- return -EINVAL;
-
- new_tx_count = clamp_t(u32, ring->tx_pending,
- I40EVF_MIN_TXD,
- I40EVF_MAX_TXD);
- new_tx_count = ALIGN(new_tx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
-
- new_rx_count = clamp_t(u32, ring->rx_pending,
- I40EVF_MIN_RXD,
- I40EVF_MAX_RXD);
- new_rx_count = ALIGN(new_rx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
-
- /* if nothing to do return success */
- if ((new_tx_count == adapter->tx_desc_count) &&
- (new_rx_count == adapter->rx_desc_count))
- return 0;
-
- adapter->tx_desc_count = new_tx_count;
- adapter->rx_desc_count = new_rx_count;
-
- if (netif_running(netdev)) {
- adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
- schedule_work(&adapter->reset_task);
- }
-
- return 0;
-}
-
-/**
- * __i40evf_get_coalesce - get per-queue coalesce settings
- * @netdev: the netdev to check
- * @ec: ethtool coalesce data structure
- * @queue: which queue to pick
- *
- * Gets the per-queue settings for coalescence. Specifically Rx and Tx usecs
- * are per queue. If queue is <0 then we default to queue 0 as the
- * representative value.
- **/
-static int __i40evf_get_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *ec,
- int queue)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- struct i40e_vsi *vsi = &adapter->vsi;
- struct i40e_ring *rx_ring, *tx_ring;
-
- ec->tx_max_coalesced_frames = vsi->work_limit;
- ec->rx_max_coalesced_frames = vsi->work_limit;
-
- /* Rx and Tx usecs per queue value. If user doesn't specify the
- * queue, return queue 0's value to represent.
- */
- if (queue < 0)
- queue = 0;
- else if (queue >= adapter->num_active_queues)
- return -EINVAL;
-
- rx_ring = &adapter->rx_rings[queue];
- tx_ring = &adapter->tx_rings[queue];
-
- if (ITR_IS_DYNAMIC(rx_ring->itr_setting))
- ec->use_adaptive_rx_coalesce = 1;
-
- if (ITR_IS_DYNAMIC(tx_ring->itr_setting))
- ec->use_adaptive_tx_coalesce = 1;
-
- ec->rx_coalesce_usecs = rx_ring->itr_setting & ~I40E_ITR_DYNAMIC;
- ec->tx_coalesce_usecs = tx_ring->itr_setting & ~I40E_ITR_DYNAMIC;
-
- return 0;
-}
-
-/**
- * i40evf_get_coalesce - Get interrupt coalescing settings
- * @netdev: network interface device structure
- * @ec: ethtool coalesce structure
- *
- * Returns current coalescing settings. This is referred to elsewhere in the
- * driver as Interrupt Throttle Rate, as this is how the hardware describes
- * this functionality. Note that if per-queue settings have been modified this
- * only represents the settings of queue 0.
- **/
-static int i40evf_get_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *ec)
-{
- return __i40evf_get_coalesce(netdev, ec, -1);
-}
-
-/**
- * i40evf_get_per_queue_coalesce - get coalesce values for specific queue
- * @netdev: netdev to read
- * @ec: coalesce settings from ethtool
- * @queue: the queue to read
- *
- * Read specific queue's coalesce settings.
- **/
-static int i40evf_get_per_queue_coalesce(struct net_device *netdev,
- u32 queue,
- struct ethtool_coalesce *ec)
-{
- return __i40evf_get_coalesce(netdev, ec, queue);
-}
-
-/**
- * i40evf_set_itr_per_queue - set ITR values for specific queue
- * @adapter: the VF adapter struct to set values for
- * @ec: coalesce settings from ethtool
- * @queue: the queue to modify
- *
- * Change the ITR settings for a specific queue.
- **/
-static void i40evf_set_itr_per_queue(struct i40evf_adapter *adapter,
- struct ethtool_coalesce *ec,
- int queue)
-{
- struct i40e_ring *rx_ring = &adapter->rx_rings[queue];
- struct i40e_ring *tx_ring = &adapter->tx_rings[queue];
- struct i40e_q_vector *q_vector;
-
- rx_ring->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs);
- tx_ring->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs);
-
- rx_ring->itr_setting |= I40E_ITR_DYNAMIC;
- if (!ec->use_adaptive_rx_coalesce)
- rx_ring->itr_setting ^= I40E_ITR_DYNAMIC;
-
- tx_ring->itr_setting |= I40E_ITR_DYNAMIC;
- if (!ec->use_adaptive_tx_coalesce)
- tx_ring->itr_setting ^= I40E_ITR_DYNAMIC;
-
- q_vector = rx_ring->q_vector;
- q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);
-
- q_vector = tx_ring->q_vector;
- q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);
-
- /* The interrupt handler itself will take care of programming
- * the Tx and Rx ITR values based on the values we have entered
- * into the q_vector, no need to write the values now.
- */
-}
-
-/**
- * __i40evf_set_coalesce - set coalesce settings for particular queue
- * @netdev: the netdev to change
- * @ec: ethtool coalesce settings
- * @queue: the queue to change
- *
- * Sets the coalesce settings for a particular queue.
- **/
-static int __i40evf_set_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *ec,
- int queue)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- struct i40e_vsi *vsi = &adapter->vsi;
- int i;
-
- if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
- vsi->work_limit = ec->tx_max_coalesced_frames_irq;
-
- if (ec->rx_coalesce_usecs == 0) {
- if (ec->use_adaptive_rx_coalesce)
- netif_info(adapter, drv, netdev, "rx-usecs=0, need to disable adaptive-rx for a complete disable\n");
- } else if ((ec->rx_coalesce_usecs < I40E_MIN_ITR) ||
- (ec->rx_coalesce_usecs > I40E_MAX_ITR)) {
- netif_info(adapter, drv, netdev, "Invalid value, rx-usecs range is 0-8160\n");
- return -EINVAL;
- }
-
- else
- if (ec->tx_coalesce_usecs == 0) {
- if (ec->use_adaptive_tx_coalesce)
- netif_info(adapter, drv, netdev, "tx-usecs=0, need to disable adaptive-tx for a complete disable\n");
- } else if ((ec->tx_coalesce_usecs < I40E_MIN_ITR) ||
- (ec->tx_coalesce_usecs > I40E_MAX_ITR)) {
- netif_info(adapter, drv, netdev, "Invalid value, tx-usecs range is 0-8160\n");
- return -EINVAL;
- }
-
- /* Rx and Tx usecs has per queue value. If user doesn't specify the
- * queue, apply to all queues.
- */
- if (queue < 0) {
- for (i = 0; i < adapter->num_active_queues; i++)
- i40evf_set_itr_per_queue(adapter, ec, i);
- } else if (queue < adapter->num_active_queues) {
- i40evf_set_itr_per_queue(adapter, ec, queue);
- } else {
- netif_info(adapter, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",
- adapter->num_active_queues - 1);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/**
- * i40evf_set_coalesce - Set interrupt coalescing settings
- * @netdev: network interface device structure
- * @ec: ethtool coalesce structure
- *
- * Change current coalescing settings for every queue.
- **/
-static int i40evf_set_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *ec)
-{
- return __i40evf_set_coalesce(netdev, ec, -1);
-}
-
-/**
- * i40evf_set_per_queue_coalesce - set specific queue's coalesce settings
- * @netdev: the netdev to change
- * @ec: ethtool's coalesce settings
- * @queue: the queue to modify
- *
- * Modifies a specific queue's coalesce settings.
- */
-static int i40evf_set_per_queue_coalesce(struct net_device *netdev,
- u32 queue,
- struct ethtool_coalesce *ec)
-{
- return __i40evf_set_coalesce(netdev, ec, queue);
-}
-
-/**
- * i40evf_get_rxnfc - command to get RX flow classification rules
- * @netdev: network interface device structure
- * @cmd: ethtool rxnfc command
- * @rule_locs: pointer to store rule locations
- *
- * Returns Success if the command is supported.
- **/
-static int i40evf_get_rxnfc(struct net_device *netdev,
- struct ethtool_rxnfc *cmd,
- u32 *rule_locs)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- int ret = -EOPNOTSUPP;
-
- switch (cmd->cmd) {
- case ETHTOOL_GRXRINGS:
- cmd->data = adapter->num_active_queues;
- ret = 0;
- break;
- case ETHTOOL_GRXFH:
- netdev_info(netdev,
- "RSS hash info is not available to vf, use pf.\n");
- break;
- default:
- break;
- }
-
- return ret;
-}
-/**
- * i40evf_get_channels: get the number of channels supported by the device
- * @netdev: network interface device structure
- * @ch: channel information structure
- *
- * For the purposes of our device, we only use combined channels, i.e. a tx/rx
- * queue pair. Report one extra channel to match our "other" MSI-X vector.
- **/
-static void i40evf_get_channels(struct net_device *netdev,
- struct ethtool_channels *ch)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- /* Report maximum channels */
- ch->max_combined = I40EVF_MAX_REQ_QUEUES;
-
- ch->max_other = NONQ_VECS;
- ch->other_count = NONQ_VECS;
-
- ch->combined_count = adapter->num_active_queues;
-}
-
-/**
- * i40evf_set_channels: set the new channel count
- * @netdev: network interface device structure
- * @ch: channel information structure
- *
- * Negotiate a new number of channels with the PF then do a reset. During
- * reset we'll realloc queues and fix the RSS table. Returns 0 on success,
- * negative on failure.
- **/
-static int i40evf_set_channels(struct net_device *netdev,
- struct ethtool_channels *ch)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- int num_req = ch->combined_count;
-
- if (num_req != adapter->num_active_queues &&
- !(adapter->vf_res->vf_cap_flags &
- VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)) {
- dev_info(&adapter->pdev->dev, "PF is not capable of queue negotiation.\n");
- return -EINVAL;
- }
-
- if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
- adapter->num_tc) {
- dev_info(&adapter->pdev->dev, "Cannot set channels since ADq is enabled.\n");
- return -EINVAL;
- }
-
- /* All of these should have already been checked by ethtool before this
- * even gets to us, but just to be sure.
- */
- if (num_req <= 0 || num_req > I40EVF_MAX_REQ_QUEUES)
- return -EINVAL;
-
- if (ch->rx_count || ch->tx_count || ch->other_count != NONQ_VECS)
- return -EINVAL;
-
- adapter->num_req_queues = num_req;
- return i40evf_request_queues(adapter, num_req);
-}
-
-/**
- * i40evf_get_rxfh_key_size - get the RSS hash key size
- * @netdev: network interface device structure
- *
- * Returns the table size.
- **/
-static u32 i40evf_get_rxfh_key_size(struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- return adapter->rss_key_size;
-}
-
-/**
- * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size
- * @netdev: network interface device structure
- *
- * Returns the table size.
- **/
-static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- return adapter->rss_lut_size;
-}
-
-/**
- * i40evf_get_rxfh - get the rx flow hash indirection table
- * @netdev: network interface device structure
- * @indir: indirection table
- * @key: hash key
- * @hfunc: hash function in use
- *
- * Reads the indirection table directly from the hardware. Always returns 0.
- **/
-static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
- u8 *hfunc)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- u16 i;
-
- if (hfunc)
- *hfunc = ETH_RSS_HASH_TOP;
- if (!indir)
- return 0;
-
- memcpy(key, adapter->rss_key, adapter->rss_key_size);
-
- /* Each 32 bits pointed by 'indir' is stored with a lut entry */
- for (i = 0; i < adapter->rss_lut_size; i++)
- indir[i] = (u32)adapter->rss_lut[i];
-
- return 0;
-}
-
-/**
- * i40evf_set_rxfh - set the rx flow hash indirection table
- * @netdev: network interface device structure
- * @indir: indirection table
- * @key: hash key
- * @hfunc: hash function to use
- *
- * Returns -EINVAL if the table specifies an inavlid queue id, otherwise
- * returns 0 after programming the table.
- **/
-static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
- const u8 *key, const u8 hfunc)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- u16 i;
-
- /* We do not allow change in unsupported parameters */
- if (key ||
- (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
- return -EOPNOTSUPP;
- if (!indir)
- return 0;
-
- if (key) {
- memcpy(adapter->rss_key, key, adapter->rss_key_size);
- }
-
- /* Each 32 bits pointed by 'indir' is stored with a lut entry */
- for (i = 0; i < adapter->rss_lut_size; i++)
- adapter->rss_lut[i] = (u8)(indir[i]);
-
- return i40evf_config_rss(adapter);
-}
-
-static const struct ethtool_ops i40evf_ethtool_ops = {
- .get_drvinfo = i40evf_get_drvinfo,
- .get_link = ethtool_op_get_link,
- .get_ringparam = i40evf_get_ringparam,
- .set_ringparam = i40evf_set_ringparam,
- .get_strings = i40evf_get_strings,
- .get_ethtool_stats = i40evf_get_ethtool_stats,
- .get_sset_count = i40evf_get_sset_count,
- .get_priv_flags = i40evf_get_priv_flags,
- .set_priv_flags = i40evf_set_priv_flags,
- .get_msglevel = i40evf_get_msglevel,
- .set_msglevel = i40evf_set_msglevel,
- .get_coalesce = i40evf_get_coalesce,
- .set_coalesce = i40evf_set_coalesce,
- .get_per_queue_coalesce = i40evf_get_per_queue_coalesce,
- .set_per_queue_coalesce = i40evf_set_per_queue_coalesce,
- .get_rxnfc = i40evf_get_rxnfc,
- .get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
- .get_rxfh = i40evf_get_rxfh,
- .set_rxfh = i40evf_set_rxfh,
- .get_channels = i40evf_get_channels,
- .set_channels = i40evf_set_channels,
- .get_rxfh_key_size = i40evf_get_rxfh_key_size,
- .get_link_ksettings = i40evf_get_link_ksettings,
-};
-
-/**
- * i40evf_set_ethtool_ops - Initialize ethtool ops struct
- * @netdev: network interface device structure
- *
- * Sets ethtool ops struct in our netdev so that ethtool can call
- * our functions.
- **/
-void i40evf_set_ethtool_ops(struct net_device *netdev)
-{
- netdev->ethtool_ops = &i40evf_ethtool_ops;
-}
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
deleted file mode 100644
index 5a6e579e9e65..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ /dev/null
@@ -1,3989 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#include "i40evf.h"
-#include "i40e_prototype.h"
-#include "i40evf_client.h"
-/* All i40evf tracepoints are defined by the include below, which must
- * be included exactly once across the whole kernel with
- * CREATE_TRACE_POINTS defined
- */
-#define CREATE_TRACE_POINTS
-#include "i40e_trace.h"
-
-static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter);
-static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter);
-static int i40evf_close(struct net_device *netdev);
-
-char i40evf_driver_name[] = "i40evf";
-static const char i40evf_driver_string[] =
- "Intel(R) 40-10 Gigabit Virtual Function Network Driver";
-
-#define DRV_KERN "-k"
-
-#define DRV_VERSION_MAJOR 3
-#define DRV_VERSION_MINOR 2
-#define DRV_VERSION_BUILD 2
-#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
- __stringify(DRV_VERSION_MINOR) "." \
- __stringify(DRV_VERSION_BUILD) \
- DRV_KERN
-const char i40evf_driver_version[] = DRV_VERSION;
-static const char i40evf_copyright[] =
- "Copyright (c) 2013 - 2015 Intel Corporation.";
-
-/* i40evf_pci_tbl - PCI Device ID Table
- *
- * Wildcard entries (PCI_ANY_ID) should come last
- * Last entry must be all 0s
- *
- * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
- * Class, Class Mask, private data (not used) }
- */
-static const struct pci_device_id i40evf_pci_tbl[] = {
- {PCI_VDEVICE(INTEL, I40E_DEV_ID_VF), 0},
- {PCI_VDEVICE(INTEL, I40E_DEV_ID_VF_HV), 0},
- {PCI_VDEVICE(INTEL, I40E_DEV_ID_X722_VF), 0},
- {PCI_VDEVICE(INTEL, I40E_DEV_ID_ADAPTIVE_VF), 0},
- /* required last entry */
- {0, }
-};
-
-MODULE_DEVICE_TABLE(pci, i40evf_pci_tbl);
-
-MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
-MODULE_DESCRIPTION("Intel(R) XL710 X710 Virtual Function Network Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-static struct workqueue_struct *i40evf_wq;
-
-/**
- * i40evf_allocate_dma_mem_d - OS specific memory alloc for shared code
- * @hw: pointer to the HW structure
- * @mem: ptr to mem struct to fill out
- * @size: size of memory requested
- * @alignment: what to align the allocation to
- **/
-i40e_status i40evf_allocate_dma_mem_d(struct i40e_hw *hw,
- struct i40e_dma_mem *mem,
- u64 size, u32 alignment)
-{
- struct i40evf_adapter *adapter = (struct i40evf_adapter *)hw->back;
-
- if (!mem)
- return I40E_ERR_PARAM;
-
- mem->size = ALIGN(size, alignment);
- mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size,
- (dma_addr_t *)&mem->pa, GFP_KERNEL);
- if (mem->va)
- return 0;
- else
- return I40E_ERR_NO_MEMORY;
-}
-
-/**
- * i40evf_free_dma_mem_d - OS specific memory free for shared code
- * @hw: pointer to the HW structure
- * @mem: ptr to mem struct to free
- **/
-i40e_status i40evf_free_dma_mem_d(struct i40e_hw *hw, struct i40e_dma_mem *mem)
-{
- struct i40evf_adapter *adapter = (struct i40evf_adapter *)hw->back;
-
- if (!mem || !mem->va)
- return I40E_ERR_PARAM;
- dma_free_coherent(&adapter->pdev->dev, mem->size,
- mem->va, (dma_addr_t)mem->pa);
- return 0;
-}
-
-/**
- * i40evf_allocate_virt_mem_d - OS specific memory alloc for shared code
- * @hw: pointer to the HW structure
- * @mem: ptr to mem struct to fill out
- * @size: size of memory requested
- **/
-i40e_status i40evf_allocate_virt_mem_d(struct i40e_hw *hw,
- struct i40e_virt_mem *mem, u32 size)
-{
- if (!mem)
- return I40E_ERR_PARAM;
-
- mem->size = size;
- mem->va = kzalloc(size, GFP_KERNEL);
-
- if (mem->va)
- return 0;
- else
- return I40E_ERR_NO_MEMORY;
-}
-
-/**
- * i40evf_free_virt_mem_d - OS specific memory free for shared code
- * @hw: pointer to the HW structure
- * @mem: ptr to mem struct to free
- **/
-i40e_status i40evf_free_virt_mem_d(struct i40e_hw *hw,
- struct i40e_virt_mem *mem)
-{
- if (!mem)
- return I40E_ERR_PARAM;
-
- /* it's ok to kfree a NULL pointer */
- kfree(mem->va);
-
- return 0;
-}
-
-/**
- * i40evf_debug_d - OS dependent version of debug printing
- * @hw: pointer to the HW structure
- * @mask: debug level mask
- * @fmt_str: printf-type format description
- **/
-void i40evf_debug_d(void *hw, u32 mask, char *fmt_str, ...)
-{
- char buf[512];
- va_list argptr;
-
- if (!(mask & ((struct i40e_hw *)hw)->debug_mask))
- return;
-
- va_start(argptr, fmt_str);
- vsnprintf(buf, sizeof(buf), fmt_str, argptr);
- va_end(argptr);
-
- /* the debug string is already formatted with a newline */
- pr_info("%s", buf);
-}
-
-/**
- * i40evf_schedule_reset - Set the flags and schedule a reset event
- * @adapter: board private structure
- **/
-void i40evf_schedule_reset(struct i40evf_adapter *adapter)
-{
- if (!(adapter->flags &
- (I40EVF_FLAG_RESET_PENDING | I40EVF_FLAG_RESET_NEEDED))) {
- adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
- schedule_work(&adapter->reset_task);
- }
-}
-
-/**
- * i40evf_tx_timeout - Respond to a Tx Hang
- * @netdev: network interface device structure
- **/
-static void i40evf_tx_timeout(struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- adapter->tx_timeout_count++;
- i40evf_schedule_reset(adapter);
-}
-
-/**
- * i40evf_misc_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
-static void i40evf_misc_irq_disable(struct i40evf_adapter *adapter)
-{
- struct i40e_hw *hw = &adapter->hw;
-
- if (!adapter->msix_entries)
- return;
-
- wr32(hw, I40E_VFINT_DYN_CTL01, 0);
-
- /* read flush */
- rd32(hw, I40E_VFGEN_RSTAT);
-
- synchronize_irq(adapter->msix_entries[0].vector);
-}
-
-/**
- * i40evf_misc_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-static void i40evf_misc_irq_enable(struct i40evf_adapter *adapter)
-{
- struct i40e_hw *hw = &adapter->hw;
-
- wr32(hw, I40E_VFINT_DYN_CTL01, I40E_VFINT_DYN_CTL01_INTENA_MASK |
- I40E_VFINT_DYN_CTL01_ITR_INDX_MASK);
- wr32(hw, I40E_VFINT_ICR0_ENA1, I40E_VFINT_ICR0_ENA1_ADMINQ_MASK);
-
- /* read flush */
- rd32(hw, I40E_VFGEN_RSTAT);
-}
-
-/**
- * i40evf_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
-static void i40evf_irq_disable(struct i40evf_adapter *adapter)
-{
- int i;
- struct i40e_hw *hw = &adapter->hw;
-
- if (!adapter->msix_entries)
- return;
-
- for (i = 1; i < adapter->num_msix_vectors; i++) {
- wr32(hw, I40E_VFINT_DYN_CTLN1(i - 1), 0);
- synchronize_irq(adapter->msix_entries[i].vector);
- }
- /* read flush */
- rd32(hw, I40E_VFGEN_RSTAT);
-}
-
-/**
- * i40evf_irq_enable_queues - Enable interrupt for specified queues
- * @adapter: board private structure
- * @mask: bitmap of queues to enable
- **/
-void i40evf_irq_enable_queues(struct i40evf_adapter *adapter, u32 mask)
-{
- struct i40e_hw *hw = &adapter->hw;
- int i;
-
- for (i = 1; i < adapter->num_msix_vectors; i++) {
- if (mask & BIT(i - 1)) {
- wr32(hw, I40E_VFINT_DYN_CTLN1(i - 1),
- I40E_VFINT_DYN_CTLN1_INTENA_MASK |
- I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK);
- }
- }
-}
-
-/**
- * i40evf_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- * @flush: boolean value whether to run rd32()
- **/
-void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush)
-{
- struct i40e_hw *hw = &adapter->hw;
-
- i40evf_misc_irq_enable(adapter);
- i40evf_irq_enable_queues(adapter, ~0);
-
- if (flush)
- rd32(hw, I40E_VFGEN_RSTAT);
-}
-
-/**
- * i40evf_msix_aq - Interrupt handler for vector 0
- * @irq: interrupt number
- * @data: pointer to netdev
- **/
-static irqreturn_t i40evf_msix_aq(int irq, void *data)
-{
- struct net_device *netdev = data;
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- struct i40e_hw *hw = &adapter->hw;
-
- /* handle non-queue interrupts, these reads clear the registers */
- rd32(hw, I40E_VFINT_ICR01);
- rd32(hw, I40E_VFINT_ICR0_ENA1);
-
- /* schedule work on the private workqueue */
- schedule_work(&adapter->adminq_task);
-
- return IRQ_HANDLED;
-}
-
-/**
- * i40evf_msix_clean_rings - MSIX mode Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a q_vector
- **/
-static irqreturn_t i40evf_msix_clean_rings(int irq, void *data)
-{
- struct i40e_q_vector *q_vector = data;
-
- if (!q_vector->tx.ring && !q_vector->rx.ring)
- return IRQ_HANDLED;
-
- napi_schedule_irqoff(&q_vector->napi);
-
- return IRQ_HANDLED;
-}
-
-/**
- * i40evf_map_vector_to_rxq - associate irqs with rx queues
- * @adapter: board private structure
- * @v_idx: interrupt number
- * @r_idx: queue number
- **/
-static void
-i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx)
-{
- struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx];
- struct i40e_ring *rx_ring = &adapter->rx_rings[r_idx];
- struct i40e_hw *hw = &adapter->hw;
-
- rx_ring->q_vector = q_vector;
- rx_ring->next = q_vector->rx.ring;
- rx_ring->vsi = &adapter->vsi;
- q_vector->rx.ring = rx_ring;
- q_vector->rx.count++;
- q_vector->rx.next_update = jiffies + 1;
- q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);
- q_vector->ring_mask |= BIT(r_idx);
- wr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, q_vector->reg_idx),
- q_vector->rx.current_itr);
- q_vector->rx.current_itr = q_vector->rx.target_itr;
-}
-
-/**
- * i40evf_map_vector_to_txq - associate irqs with tx queues
- * @adapter: board private structure
- * @v_idx: interrupt number
- * @t_idx: queue number
- **/
-static void
-i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)
-{
- struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx];
- struct i40e_ring *tx_ring = &adapter->tx_rings[t_idx];
- struct i40e_hw *hw = &adapter->hw;
-
- tx_ring->q_vector = q_vector;
- tx_ring->next = q_vector->tx.ring;
- tx_ring->vsi = &adapter->vsi;
- q_vector->tx.ring = tx_ring;
- q_vector->tx.count++;
- q_vector->tx.next_update = jiffies + 1;
- q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);
- q_vector->num_ringpairs++;
- wr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, q_vector->reg_idx),
- q_vector->tx.target_itr);
- q_vector->tx.current_itr = q_vector->tx.target_itr;
-}
-
-/**
- * i40evf_map_rings_to_vectors - Maps descriptor rings to vectors
- * @adapter: board private structure to initialize
- *
- * This function maps descriptor rings to the queue-specific vectors
- * we were allotted through the MSI-X enabling code. Ideally, we'd have
- * one vector per ring/queue, but on a constrained vector budget, we
- * group the rings as "efficiently" as possible. You would add new
- * mapping configurations in here.
- **/
-static void i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
-{
- int rings_remaining = adapter->num_active_queues;
- int ridx = 0, vidx = 0;
- int q_vectors;
-
- q_vectors = adapter->num_msix_vectors - NONQ_VECS;
-
- for (; ridx < rings_remaining; ridx++) {
- i40evf_map_vector_to_rxq(adapter, vidx, ridx);
- i40evf_map_vector_to_txq(adapter, vidx, ridx);
-
- /* In the case where we have more queues than vectors, continue
- * round-robin on vectors until all queues are mapped.
- */
- if (++vidx >= q_vectors)
- vidx = 0;
- }
-
- adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
-}
-
-/**
- * i40evf_irq_affinity_notify - Callback for affinity changes
- * @notify: context as to what irq was changed
- * @mask: the new affinity mask
- *
- * This is a callback function used by the irq_set_affinity_notifier function
- * so that we may register to receive changes to the irq affinity masks.
- **/
-static void i40evf_irq_affinity_notify(struct irq_affinity_notify *notify,
- const cpumask_t *mask)
-{
- struct i40e_q_vector *q_vector =
- container_of(notify, struct i40e_q_vector, affinity_notify);
-
- cpumask_copy(&q_vector->affinity_mask, mask);
-}
-
-/**
- * i40evf_irq_affinity_release - Callback for affinity notifier release
- * @ref: internal core kernel usage
- *
- * This is a callback function used by the irq_set_affinity_notifier function
- * to inform the current notification subscriber that they will no longer
- * receive notifications.
- **/
-static void i40evf_irq_affinity_release(struct kref *ref) {}
-
-/**
- * i40evf_request_traffic_irqs - Initialize MSI-X interrupts
- * @adapter: board private structure
- * @basename: device basename
- *
- * Allocates MSI-X vectors for tx and rx handling, and requests
- * interrupts from the kernel.
- **/
-static int
-i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
-{
- unsigned int vector, q_vectors;
- unsigned int rx_int_idx = 0, tx_int_idx = 0;
- int irq_num, err;
- int cpu;
-
- i40evf_irq_disable(adapter);
- /* Decrement for Other and TCP Timer vectors */
- q_vectors = adapter->num_msix_vectors - NONQ_VECS;
-
- for (vector = 0; vector < q_vectors; vector++) {
- struct i40e_q_vector *q_vector = &adapter->q_vectors[vector];
- irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
-
- if (q_vector->tx.ring && q_vector->rx.ring) {
- snprintf(q_vector->name, sizeof(q_vector->name),
- "i40evf-%s-TxRx-%d", basename, rx_int_idx++);
- tx_int_idx++;
- } else if (q_vector->rx.ring) {
- snprintf(q_vector->name, sizeof(q_vector->name),
- "i40evf-%s-rx-%d", basename, rx_int_idx++);
- } else if (q_vector->tx.ring) {
- snprintf(q_vector->name, sizeof(q_vector->name),
- "i40evf-%s-tx-%d", basename, tx_int_idx++);
- } else {
- /* skip this unused q_vector */
- continue;
- }
- err = request_irq(irq_num,
- i40evf_msix_clean_rings,
- 0,
- q_vector->name,
- q_vector);
- if (err) {
- dev_info(&adapter->pdev->dev,
- "Request_irq failed, error: %d\n", err);
- goto free_queue_irqs;
- }
- /* register for affinity change notifications */
- q_vector->affinity_notify.notify = i40evf_irq_affinity_notify;
- q_vector->affinity_notify.release =
- i40evf_irq_affinity_release;
- irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
- /* Spread the IRQ affinity hints across online CPUs. Note that
- * get_cpu_mask returns a mask with a permanent lifetime so
- * it's safe to use as a hint for irq_set_affinity_hint.
- */
- cpu = cpumask_local_spread(q_vector->v_idx, -1);
- irq_set_affinity_hint(irq_num, get_cpu_mask(cpu));
- }
-
- return 0;
-
-free_queue_irqs:
- while (vector) {
- vector--;
- irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
- irq_set_affinity_notifier(irq_num, NULL);
- irq_set_affinity_hint(irq_num, NULL);
- free_irq(irq_num, &adapter->q_vectors[vector]);
- }
- return err;
-}
-
-/**
- * i40evf_request_misc_irq - Initialize MSI-X interrupts
- * @adapter: board private structure
- *
- * Allocates MSI-X vector 0 and requests interrupts from the kernel. This
- * vector is only for the admin queue, and stays active even when the netdev
- * is closed.
- **/
-static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- int err;
-
- snprintf(adapter->misc_vector_name,
- sizeof(adapter->misc_vector_name) - 1, "i40evf-%s:mbx",
- dev_name(&adapter->pdev->dev));
- err = request_irq(adapter->msix_entries[0].vector,
- &i40evf_msix_aq, 0,
- adapter->misc_vector_name, netdev);
- if (err) {
- dev_err(&adapter->pdev->dev,
- "request_irq for %s failed: %d\n",
- adapter->misc_vector_name, err);
- free_irq(adapter->msix_entries[0].vector, netdev);
- }
- return err;
-}
-
-/**
- * i40evf_free_traffic_irqs - Free MSI-X interrupts
- * @adapter: board private structure
- *
- * Frees all MSI-X vectors other than 0.
- **/
-static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter)
-{
- int vector, irq_num, q_vectors;
-
- if (!adapter->msix_entries)
- return;
-
- q_vectors = adapter->num_msix_vectors - NONQ_VECS;
-
- for (vector = 0; vector < q_vectors; vector++) {
- irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
- irq_set_affinity_notifier(irq_num, NULL);
- irq_set_affinity_hint(irq_num, NULL);
- free_irq(irq_num, &adapter->q_vectors[vector]);
- }
-}
-
-/**
- * i40evf_free_misc_irq - Free MSI-X miscellaneous vector
- * @adapter: board private structure
- *
- * Frees MSI-X vector 0.
- **/
-static void i40evf_free_misc_irq(struct i40evf_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
-
- if (!adapter->msix_entries)
- return;
-
- free_irq(adapter->msix_entries[0].vector, netdev);
-}
-
-/**
- * i40evf_configure_tx - Configure Transmit Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx unit of the MAC after a reset.
- **/
-static void i40evf_configure_tx(struct i40evf_adapter *adapter)
-{
- struct i40e_hw *hw = &adapter->hw;
- int i;
-
- for (i = 0; i < adapter->num_active_queues; i++)
- adapter->tx_rings[i].tail = hw->hw_addr + I40E_QTX_TAIL1(i);
-}
-
-/**
- * i40evf_configure_rx - Configure Receive Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Rx unit of the MAC after a reset.
- **/
-static void i40evf_configure_rx(struct i40evf_adapter *adapter)
-{
- unsigned int rx_buf_len = I40E_RXBUFFER_2048;
- struct i40e_hw *hw = &adapter->hw;
- int i;
-
- /* Legacy Rx will always default to a 2048 buffer size. */
-#if (PAGE_SIZE < 8192)
- if (!(adapter->flags & I40EVF_FLAG_LEGACY_RX)) {
- struct net_device *netdev = adapter->netdev;
-
- /* For jumbo frames on systems with 4K pages we have to use
- * an order 1 page, so we might as well increase the size
- * of our Rx buffer to make better use of the available space
- */
- rx_buf_len = I40E_RXBUFFER_3072;
-
- /* We use a 1536 buffer size for configurations with
- * standard Ethernet mtu. On x86 this gives us enough room
- * for shared info and 192 bytes of padding.
- */
- if (!I40E_2K_TOO_SMALL_WITH_PADDING &&
- (netdev->mtu <= ETH_DATA_LEN))
- rx_buf_len = I40E_RXBUFFER_1536 - NET_IP_ALIGN;
- }
-#endif
-
- for (i = 0; i < adapter->num_active_queues; i++) {
- adapter->rx_rings[i].tail = hw->hw_addr + I40E_QRX_TAIL1(i);
- adapter->rx_rings[i].rx_buf_len = rx_buf_len;
-
- if (adapter->flags & I40EVF_FLAG_LEGACY_RX)
- clear_ring_build_skb_enabled(&adapter->rx_rings[i]);
- else
- set_ring_build_skb_enabled(&adapter->rx_rings[i]);
- }
-}
-
-/**
- * i40evf_find_vlan - Search filter list for specific vlan filter
- * @adapter: board private structure
- * @vlan: vlan tag
- *
- * Returns ptr to the filter object or NULL. Must be called while holding the
- * mac_vlan_list_lock.
- **/
-static struct
-i40evf_vlan_filter *i40evf_find_vlan(struct i40evf_adapter *adapter, u16 vlan)
-{
- struct i40evf_vlan_filter *f;
-
- list_for_each_entry(f, &adapter->vlan_filter_list, list) {
- if (vlan == f->vlan)
- return f;
- }
- return NULL;
-}
-
-/**
- * i40evf_add_vlan - Add a vlan filter to the list
- * @adapter: board private structure
- * @vlan: VLAN tag
- *
- * Returns ptr to the filter object or NULL when no memory available.
- **/
-static struct
-i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan)
-{
- struct i40evf_vlan_filter *f = NULL;
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- f = i40evf_find_vlan(adapter, vlan);
- if (!f) {
- f = kzalloc(sizeof(*f), GFP_KERNEL);
- if (!f)
- goto clearout;
-
- f->vlan = vlan;
-
- INIT_LIST_HEAD(&f->list);
- list_add(&f->list, &adapter->vlan_filter_list);
- f->add = true;
- adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
- }
-
-clearout:
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return f;
-}
-
-/**
- * i40evf_del_vlan - Remove a vlan filter from the list
- * @adapter: board private structure
- * @vlan: VLAN tag
- **/
-static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan)
-{
- struct i40evf_vlan_filter *f;
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- f = i40evf_find_vlan(adapter, vlan);
- if (f) {
- f->remove = true;
- adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
- }
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-}
-
-/**
- * i40evf_vlan_rx_add_vid - Add a VLAN filter to a device
- * @netdev: network device struct
- * @proto: unused protocol data
- * @vid: VLAN tag
- **/
-static int i40evf_vlan_rx_add_vid(struct net_device *netdev,
- __always_unused __be16 proto, u16 vid)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- if (!VLAN_ALLOWED(adapter))
- return -EIO;
- if (i40evf_add_vlan(adapter, vid) == NULL)
- return -ENOMEM;
- return 0;
-}
-
-/**
- * i40evf_vlan_rx_kill_vid - Remove a VLAN filter from a device
- * @netdev: network device struct
- * @proto: unused protocol data
- * @vid: VLAN tag
- **/
-static int i40evf_vlan_rx_kill_vid(struct net_device *netdev,
- __always_unused __be16 proto, u16 vid)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- if (VLAN_ALLOWED(adapter)) {
- i40evf_del_vlan(adapter, vid);
- return 0;
- }
- return -EIO;
-}
-
-/**
- * i40evf_find_filter - Search filter list for specific mac filter
- * @adapter: board private structure
- * @macaddr: the MAC address
- *
- * Returns ptr to the filter object or NULL. Must be called while holding the
- * mac_vlan_list_lock.
- **/
-static struct
-i40evf_mac_filter *i40evf_find_filter(struct i40evf_adapter *adapter,
- const u8 *macaddr)
-{
- struct i40evf_mac_filter *f;
-
- if (!macaddr)
- return NULL;
-
- list_for_each_entry(f, &adapter->mac_filter_list, list) {
- if (ether_addr_equal(macaddr, f->macaddr))
- return f;
- }
- return NULL;
-}
-
-/**
- * i40e_add_filter - Add a mac filter to the filter list
- * @adapter: board private structure
- * @macaddr: the MAC address
- *
- * Returns ptr to the filter object or NULL when no memory available.
- **/
-static struct
-i40evf_mac_filter *i40evf_add_filter(struct i40evf_adapter *adapter,
- const u8 *macaddr)
-{
- struct i40evf_mac_filter *f;
-
- if (!macaddr)
- return NULL;
-
- f = i40evf_find_filter(adapter, macaddr);
- if (!f) {
- f = kzalloc(sizeof(*f), GFP_ATOMIC);
- if (!f)
- return f;
-
- ether_addr_copy(f->macaddr, macaddr);
-
- list_add_tail(&f->list, &adapter->mac_filter_list);
- f->add = true;
- adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
- } else {
- f->remove = false;
- }
-
- return f;
-}
-
-/**
- * i40evf_set_mac - NDO callback to set port mac address
- * @netdev: network interface device structure
- * @p: pointer to an address structure
- *
- * Returns 0 on success, negative on failure
- **/
-static int i40evf_set_mac(struct net_device *netdev, void *p)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- struct i40e_hw *hw = &adapter->hw;
- struct i40evf_mac_filter *f;
- struct sockaddr *addr = p;
-
- if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
-
- if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
- return 0;
-
- if (adapter->flags & I40EVF_FLAG_ADDR_SET_BY_PF)
- return -EPERM;
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- f = i40evf_find_filter(adapter, hw->mac.addr);
- if (f) {
- f->remove = true;
- adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
- }
-
- f = i40evf_add_filter(adapter, addr->sa_data);
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- if (f) {
- ether_addr_copy(hw->mac.addr, addr->sa_data);
- ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
- }
-
- return (f == NULL) ? -ENOMEM : 0;
-}
-
-/**
- * i40evf_addr_sync - Callback for dev_(mc|uc)_sync to add address
- * @netdev: the netdevice
- * @addr: address to add
- *
- * Called by __dev_(mc|uc)_sync when an address needs to be added. We call
- * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
- */
-static int i40evf_addr_sync(struct net_device *netdev, const u8 *addr)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- if (i40evf_add_filter(adapter, addr))
- return 0;
- else
- return -ENOMEM;
-}
-
-/**
- * i40evf_addr_unsync - Callback for dev_(mc|uc)_sync to remove address
- * @netdev: the netdevice
- * @addr: address to add
- *
- * Called by __dev_(mc|uc)_sync when an address needs to be removed. We call
- * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
- */
-static int i40evf_addr_unsync(struct net_device *netdev, const u8 *addr)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- struct i40evf_mac_filter *f;
-
- /* Under some circumstances, we might receive a request to delete
- * our own device address from our uc list. Because we store the
- * device address in the VSI's MAC/VLAN filter list, we need to ignore
- * such requests and not delete our device address from this list.
- */
- if (ether_addr_equal(addr, netdev->dev_addr))
- return 0;
-
- f = i40evf_find_filter(adapter, addr);
- if (f) {
- f->remove = true;
- adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
- }
- return 0;
-}
-
-/**
- * i40evf_set_rx_mode - NDO callback to set the netdev filters
- * @netdev: network interface device structure
- **/
-static void i40evf_set_rx_mode(struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
- __dev_uc_sync(netdev, i40evf_addr_sync, i40evf_addr_unsync);
- __dev_mc_sync(netdev, i40evf_addr_sync, i40evf_addr_unsync);
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- if (netdev->flags & IFF_PROMISC &&
- !(adapter->flags & I40EVF_FLAG_PROMISC_ON))
- adapter->aq_required |= I40EVF_FLAG_AQ_REQUEST_PROMISC;
- else if (!(netdev->flags & IFF_PROMISC) &&
- adapter->flags & I40EVF_FLAG_PROMISC_ON)
- adapter->aq_required |= I40EVF_FLAG_AQ_RELEASE_PROMISC;
-
- if (netdev->flags & IFF_ALLMULTI &&
- !(adapter->flags & I40EVF_FLAG_ALLMULTI_ON))
- adapter->aq_required |= I40EVF_FLAG_AQ_REQUEST_ALLMULTI;
- else if (!(netdev->flags & IFF_ALLMULTI) &&
- adapter->flags & I40EVF_FLAG_ALLMULTI_ON)
- adapter->aq_required |= I40EVF_FLAG_AQ_RELEASE_ALLMULTI;
-}
-
-/**
- * i40evf_napi_enable_all - enable NAPI on all queue vectors
- * @adapter: board private structure
- **/
-static void i40evf_napi_enable_all(struct i40evf_adapter *adapter)
-{
- int q_idx;
- struct i40e_q_vector *q_vector;
- int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
-
- for (q_idx = 0; q_idx < q_vectors; q_idx++) {
- struct napi_struct *napi;
-
- q_vector = &adapter->q_vectors[q_idx];
- napi = &q_vector->napi;
- napi_enable(napi);
- }
-}
-
-/**
- * i40evf_napi_disable_all - disable NAPI on all queue vectors
- * @adapter: board private structure
- **/
-static void i40evf_napi_disable_all(struct i40evf_adapter *adapter)
-{
- int q_idx;
- struct i40e_q_vector *q_vector;
- int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
-
- for (q_idx = 0; q_idx < q_vectors; q_idx++) {
- q_vector = &adapter->q_vectors[q_idx];
- napi_disable(&q_vector->napi);
- }
-}
-
-/**
- * i40evf_configure - set up transmit and receive data structures
- * @adapter: board private structure
- **/
-static void i40evf_configure(struct i40evf_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- int i;
-
- i40evf_set_rx_mode(netdev);
-
- i40evf_configure_tx(adapter);
- i40evf_configure_rx(adapter);
- adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
-
- for (i = 0; i < adapter->num_active_queues; i++) {
- struct i40e_ring *ring = &adapter->rx_rings[i];
-
- i40evf_alloc_rx_buffers(ring, I40E_DESC_UNUSED(ring));
- }
-}
-
-/**
- * i40evf_up_complete - Finish the last steps of bringing up a connection
- * @adapter: board private structure
- *
- * Expects to be called while holding the __I40EVF_IN_CRITICAL_TASK bit lock.
- **/
-static void i40evf_up_complete(struct i40evf_adapter *adapter)
-{
- adapter->state = __I40EVF_RUNNING;
- clear_bit(__I40E_VSI_DOWN, adapter->vsi.state);
-
- i40evf_napi_enable_all(adapter);
-
- adapter->aq_required |= I40EVF_FLAG_AQ_ENABLE_QUEUES;
- if (CLIENT_ENABLED(adapter))
- adapter->flags |= I40EVF_FLAG_CLIENT_NEEDS_OPEN;
- mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
-}
-
-/**
- * i40e_down - Shutdown the connection processing
- * @adapter: board private structure
- *
- * Expects to be called while holding the __I40EVF_IN_CRITICAL_TASK bit lock.
- **/
-void i40evf_down(struct i40evf_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- struct i40evf_vlan_filter *vlf;
- struct i40evf_mac_filter *f;
- struct i40evf_cloud_filter *cf;
-
- if (adapter->state <= __I40EVF_DOWN_PENDING)
- return;
-
- netif_carrier_off(netdev);
- netif_tx_disable(netdev);
- adapter->link_up = false;
- i40evf_napi_disable_all(adapter);
- i40evf_irq_disable(adapter);
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- /* clear the sync flag on all filters */
- __dev_uc_unsync(adapter->netdev, NULL);
- __dev_mc_unsync(adapter->netdev, NULL);
-
- /* remove all MAC filters */
- list_for_each_entry(f, &adapter->mac_filter_list, list) {
- f->remove = true;
- }
-
- /* remove all VLAN filters */
- list_for_each_entry(vlf, &adapter->vlan_filter_list, list) {
- vlf->remove = true;
- }
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- /* remove all cloud filters */
- spin_lock_bh(&adapter->cloud_filter_list_lock);
- list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
- cf->del = true;
- }
- spin_unlock_bh(&adapter->cloud_filter_list_lock);
-
- if (!(adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) &&
- adapter->state != __I40EVF_RESETTING) {
- /* cancel any current operation */
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
- /* Schedule operations to close down the HW. Don't wait
- * here for this to complete. The watchdog is still running
- * and it will take care of this.
- */
- adapter->aq_required = I40EVF_FLAG_AQ_DEL_MAC_FILTER;
- adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
- adapter->aq_required |= I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;
- adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
- }
-
- mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
-}
-
-/**
- * i40evf_acquire_msix_vectors - Setup the MSIX capability
- * @adapter: board private structure
- * @vectors: number of vectors to request
- *
- * Work with the OS to set up the MSIX vectors needed.
- *
- * Returns 0 on success, negative on failure
- **/
-static int
-i40evf_acquire_msix_vectors(struct i40evf_adapter *adapter, int vectors)
-{
- int err, vector_threshold;
-
- /* We'll want at least 3 (vector_threshold):
- * 0) Other (Admin Queue and link, mostly)
- * 1) TxQ[0] Cleanup
- * 2) RxQ[0] Cleanup
- */
- vector_threshold = MIN_MSIX_COUNT;
-
- /* The more we get, the more we will assign to Tx/Rx Cleanup
- * for the separate queues...where Rx Cleanup >= Tx Cleanup.
- * Right now, we simply care about how many we'll get; we'll
- * set them up later while requesting irq's.
- */
- err = pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
- vector_threshold, vectors);
- if (err < 0) {
- dev_err(&adapter->pdev->dev, "Unable to allocate MSI-X interrupts\n");
- kfree(adapter->msix_entries);
- adapter->msix_entries = NULL;
- return err;
- }
-
- /* Adjust for only the vectors we'll use, which is minimum
- * of max_msix_q_vectors + NONQ_VECS, or the number of
- * vectors we were allocated.
- */
- adapter->num_msix_vectors = err;
- return 0;
-}
-
-/**
- * i40evf_free_queues - Free memory for all rings
- * @adapter: board private structure to initialize
- *
- * Free all of the memory associated with queue pairs.
- **/
-static void i40evf_free_queues(struct i40evf_adapter *adapter)
-{
- if (!adapter->vsi_res)
- return;
- adapter->num_active_queues = 0;
- kfree(adapter->tx_rings);
- adapter->tx_rings = NULL;
- kfree(adapter->rx_rings);
- adapter->rx_rings = NULL;
-}
-
-/**
- * i40evf_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- *
- * We allocate one ring per queue at run-time since we don't know the
- * number of queues at compile-time. The polling_netdev array is
- * intended for Multiqueue, but should work fine with a single queue.
- **/
-static int i40evf_alloc_queues(struct i40evf_adapter *adapter)
-{
- int i, num_active_queues;
-
- /* If we're in reset reallocating queues we don't actually know yet for
- * certain the PF gave us the number of queues we asked for but we'll
- * assume it did. Once basic reset is finished we'll confirm once we
- * start negotiating config with PF.
- */
- if (adapter->num_req_queues)
- num_active_queues = adapter->num_req_queues;
- else if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
- adapter->num_tc)
- num_active_queues = adapter->ch_config.total_qps;
- else
- num_active_queues = min_t(int,
- adapter->vsi_res->num_queue_pairs,
- (int)(num_online_cpus()));
-
-
- adapter->tx_rings = kcalloc(num_active_queues,
- sizeof(struct i40e_ring), GFP_KERNEL);
- if (!adapter->tx_rings)
- goto err_out;
- adapter->rx_rings = kcalloc(num_active_queues,
- sizeof(struct i40e_ring), GFP_KERNEL);
- if (!adapter->rx_rings)
- goto err_out;
-
- for (i = 0; i < num_active_queues; i++) {
- struct i40e_ring *tx_ring;
- struct i40e_ring *rx_ring;
-
- tx_ring = &adapter->tx_rings[i];
-
- tx_ring->queue_index = i;
- tx_ring->netdev = adapter->netdev;
- tx_ring->dev = &adapter->pdev->dev;
- tx_ring->count = adapter->tx_desc_count;
- tx_ring->itr_setting = I40E_ITR_TX_DEF;
- if (adapter->flags & I40EVF_FLAG_WB_ON_ITR_CAPABLE)
- tx_ring->flags |= I40E_TXR_FLAGS_WB_ON_ITR;
-
- rx_ring = &adapter->rx_rings[i];
- rx_ring->queue_index = i;
- rx_ring->netdev = adapter->netdev;
- rx_ring->dev = &adapter->pdev->dev;
- rx_ring->count = adapter->rx_desc_count;
- rx_ring->itr_setting = I40E_ITR_RX_DEF;
- }
-
- adapter->num_active_queues = num_active_queues;
-
- return 0;
-
-err_out:
- i40evf_free_queues(adapter);
- return -ENOMEM;
-}
-
-/**
- * i40evf_set_interrupt_capability - set MSI-X or FAIL if not supported
- * @adapter: board private structure to initialize
- *
- * Attempt to configure the interrupts using the best available
- * capabilities of the hardware and the kernel.
- **/
-static int i40evf_set_interrupt_capability(struct i40evf_adapter *adapter)
-{
- int vector, v_budget;
- int pairs = 0;
- int err = 0;
-
- if (!adapter->vsi_res) {
- err = -EIO;
- goto out;
- }
- pairs = adapter->num_active_queues;
-
- /* It's easy to be greedy for MSI-X vectors, but it really doesn't do
- * us much good if we have more vectors than CPUs. However, we already
- * limit the total number of queues by the number of CPUs so we do not
- * need any further limiting here.
- */
- v_budget = min_t(int, pairs + NONQ_VECS,
- (int)adapter->vf_res->max_vectors);
-
- adapter->msix_entries = kcalloc(v_budget,
- sizeof(struct msix_entry), GFP_KERNEL);
- if (!adapter->msix_entries) {
- err = -ENOMEM;
- goto out;
- }
-
- for (vector = 0; vector < v_budget; vector++)
- adapter->msix_entries[vector].entry = vector;
-
- err = i40evf_acquire_msix_vectors(adapter, v_budget);
-
-out:
- netif_set_real_num_rx_queues(adapter->netdev, pairs);
- netif_set_real_num_tx_queues(adapter->netdev, pairs);
- return err;
-}
-
-/**
- * i40e_config_rss_aq - Configure RSS keys and lut by using AQ commands
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- **/
-static int i40evf_config_rss_aq(struct i40evf_adapter *adapter)
-{
- struct i40e_aqc_get_set_rss_key_data *rss_key =
- (struct i40e_aqc_get_set_rss_key_data *)adapter->rss_key;
- struct i40e_hw *hw = &adapter->hw;
- int ret = 0;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot configure RSS, command %d pending\n",
- adapter->current_op);
- return -EBUSY;
- }
-
- ret = i40evf_aq_set_rss_key(hw, adapter->vsi.id, rss_key);
- if (ret) {
- dev_err(&adapter->pdev->dev, "Cannot set RSS key, err %s aq_err %s\n",
- i40evf_stat_str(hw, ret),
- i40evf_aq_str(hw, hw->aq.asq_last_status));
- return ret;
-
- }
-
- ret = i40evf_aq_set_rss_lut(hw, adapter->vsi.id, false,
- adapter->rss_lut, adapter->rss_lut_size);
- if (ret) {
- dev_err(&adapter->pdev->dev, "Cannot set RSS lut, err %s aq_err %s\n",
- i40evf_stat_str(hw, ret),
- i40evf_aq_str(hw, hw->aq.asq_last_status));
- }
-
- return ret;
-
-}
-
-/**
- * i40evf_config_rss_reg - Configure RSS keys and lut by writing registers
- * @adapter: board private structure
- *
- * Returns 0 on success, negative on failure
- **/
-static int i40evf_config_rss_reg(struct i40evf_adapter *adapter)
-{
- struct i40e_hw *hw = &adapter->hw;
- u32 *dw;
- u16 i;
-
- dw = (u32 *)adapter->rss_key;
- for (i = 0; i <= adapter->rss_key_size / 4; i++)
- wr32(hw, I40E_VFQF_HKEY(i), dw[i]);
-
- dw = (u32 *)adapter->rss_lut;
- for (i = 0; i <= adapter->rss_lut_size / 4; i++)
- wr32(hw, I40E_VFQF_HLUT(i), dw[i]);
-
- i40e_flush(hw);
-
- return 0;
-}
-
-/**
- * i40evf_config_rss - Configure RSS keys and lut
- * @adapter: board private structure
- *
- * Returns 0 on success, negative on failure
- **/
-int i40evf_config_rss(struct i40evf_adapter *adapter)
-{
-
- if (RSS_PF(adapter)) {
- adapter->aq_required |= I40EVF_FLAG_AQ_SET_RSS_LUT |
- I40EVF_FLAG_AQ_SET_RSS_KEY;
- return 0;
- } else if (RSS_AQ(adapter)) {
- return i40evf_config_rss_aq(adapter);
- } else {
- return i40evf_config_rss_reg(adapter);
- }
-}
-
-/**
- * i40evf_fill_rss_lut - Fill the lut with default values
- * @adapter: board private structure
- **/
-static void i40evf_fill_rss_lut(struct i40evf_adapter *adapter)
-{
- u16 i;
-
- for (i = 0; i < adapter->rss_lut_size; i++)
- adapter->rss_lut[i] = i % adapter->num_active_queues;
-}
-
-/**
- * i40evf_init_rss - Prepare for RSS
- * @adapter: board private structure
- *
- * Return 0 on success, negative on failure
- **/
-static int i40evf_init_rss(struct i40evf_adapter *adapter)
-{
- struct i40e_hw *hw = &adapter->hw;
- int ret;
-
- if (!RSS_PF(adapter)) {
- /* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */
- if (adapter->vf_res->vf_cap_flags &
- VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
- adapter->hena = I40E_DEFAULT_RSS_HENA_EXPANDED;
- else
- adapter->hena = I40E_DEFAULT_RSS_HENA;
-
- wr32(hw, I40E_VFQF_HENA(0), (u32)adapter->hena);
- wr32(hw, I40E_VFQF_HENA(1), (u32)(adapter->hena >> 32));
- }
-
- i40evf_fill_rss_lut(adapter);
-
- netdev_rss_key_fill((void *)adapter->rss_key, adapter->rss_key_size);
- ret = i40evf_config_rss(adapter);
-
- return ret;
-}
-
-/**
- * i40evf_alloc_q_vectors - Allocate memory for interrupt vectors
- * @adapter: board private structure to initialize
- *
- * We allocate one q_vector per queue interrupt. If allocation fails we
- * return -ENOMEM.
- **/
-static int i40evf_alloc_q_vectors(struct i40evf_adapter *adapter)
-{
- int q_idx = 0, num_q_vectors;
- struct i40e_q_vector *q_vector;
-
- num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
- adapter->q_vectors = kcalloc(num_q_vectors, sizeof(*q_vector),
- GFP_KERNEL);
- if (!adapter->q_vectors)
- return -ENOMEM;
-
- for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
- q_vector = &adapter->q_vectors[q_idx];
- q_vector->adapter = adapter;
- q_vector->vsi = &adapter->vsi;
- q_vector->v_idx = q_idx;
- q_vector->reg_idx = q_idx;
- cpumask_copy(&q_vector->affinity_mask, cpu_possible_mask);
- netif_napi_add(adapter->netdev, &q_vector->napi,
- i40evf_napi_poll, NAPI_POLL_WEIGHT);
- }
-
- return 0;
-}
-
-/**
- * i40evf_free_q_vectors - Free memory allocated for interrupt vectors
- * @adapter: board private structure to initialize
- *
- * This function frees the memory allocated to the q_vectors. In addition if
- * NAPI is enabled it will delete any references to the NAPI struct prior
- * to freeing the q_vector.
- **/
-static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)
-{
- int q_idx, num_q_vectors;
- int napi_vectors;
-
- if (!adapter->q_vectors)
- return;
-
- num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
- napi_vectors = adapter->num_active_queues;
-
- for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
- struct i40e_q_vector *q_vector = &adapter->q_vectors[q_idx];
- if (q_idx < napi_vectors)
- netif_napi_del(&q_vector->napi);
- }
- kfree(adapter->q_vectors);
- adapter->q_vectors = NULL;
-}
-
-/**
- * i40evf_reset_interrupt_capability - Reset MSIX setup
- * @adapter: board private structure
- *
- **/
-void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter)
-{
- if (!adapter->msix_entries)
- return;
-
- pci_disable_msix(adapter->pdev);
- kfree(adapter->msix_entries);
- adapter->msix_entries = NULL;
-}
-
-/**
- * i40evf_init_interrupt_scheme - Determine if MSIX is supported and init
- * @adapter: board private structure to initialize
- *
- **/
-int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter)
-{
- int err;
-
- err = i40evf_alloc_queues(adapter);
- if (err) {
- dev_err(&adapter->pdev->dev,
- "Unable to allocate memory for queues\n");
- goto err_alloc_queues;
- }
-
- rtnl_lock();
- err = i40evf_set_interrupt_capability(adapter);
- rtnl_unlock();
- if (err) {
- dev_err(&adapter->pdev->dev,
- "Unable to setup interrupt capabilities\n");
- goto err_set_interrupt;
- }
-
- err = i40evf_alloc_q_vectors(adapter);
- if (err) {
- dev_err(&adapter->pdev->dev,
- "Unable to allocate memory for queue vectors\n");
- goto err_alloc_q_vectors;
- }
-
- /* If we've made it so far while ADq flag being ON, then we haven't
- * bailed out anywhere in middle. And ADq isn't just enabled but actual
- * resources have been allocated in the reset path.
- * Now we can truly claim that ADq is enabled.
- */
- if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
- adapter->num_tc)
- dev_info(&adapter->pdev->dev, "ADq Enabled, %u TCs created",
- adapter->num_tc);
-
- dev_info(&adapter->pdev->dev, "Multiqueue %s: Queue pair count = %u",
- (adapter->num_active_queues > 1) ? "Enabled" : "Disabled",
- adapter->num_active_queues);
-
- return 0;
-err_alloc_q_vectors:
- i40evf_reset_interrupt_capability(adapter);
-err_set_interrupt:
- i40evf_free_queues(adapter);
-err_alloc_queues:
- return err;
-}
-
-/**
- * i40evf_free_rss - Free memory used by RSS structs
- * @adapter: board private structure
- **/
-static void i40evf_free_rss(struct i40evf_adapter *adapter)
-{
- kfree(adapter->rss_key);
- adapter->rss_key = NULL;
-
- kfree(adapter->rss_lut);
- adapter->rss_lut = NULL;
-}
-
-/**
- * i40evf_reinit_interrupt_scheme - Reallocate queues and vectors
- * @adapter: board private structure
- *
- * Returns 0 on success, negative on failure
- **/
-static int i40evf_reinit_interrupt_scheme(struct i40evf_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- int err;
-
- if (netif_running(netdev))
- i40evf_free_traffic_irqs(adapter);
- i40evf_free_misc_irq(adapter);
- i40evf_reset_interrupt_capability(adapter);
- i40evf_free_q_vectors(adapter);
- i40evf_free_queues(adapter);
-
- err = i40evf_init_interrupt_scheme(adapter);
- if (err)
- goto err;
-
- netif_tx_stop_all_queues(netdev);
-
- err = i40evf_request_misc_irq(adapter);
- if (err)
- goto err;
-
- set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
-
- i40evf_map_rings_to_vectors(adapter);
-
- if (RSS_AQ(adapter))
- adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS;
- else
- err = i40evf_init_rss(adapter);
-err:
- return err;
-}
-
-/**
- * i40evf_watchdog_timer - Periodic call-back timer
- * @data: pointer to adapter disguised as unsigned long
- **/
-static void i40evf_watchdog_timer(struct timer_list *t)
-{
- struct i40evf_adapter *adapter = from_timer(adapter, t,
- watchdog_timer);
-
- schedule_work(&adapter->watchdog_task);
- /* timer will be rescheduled in watchdog task */
-}
-
-/**
- * i40evf_watchdog_task - Periodic call-back task
- * @work: pointer to work_struct
- **/
-static void i40evf_watchdog_task(struct work_struct *work)
-{
- struct i40evf_adapter *adapter = container_of(work,
- struct i40evf_adapter,
- watchdog_task);
- struct i40e_hw *hw = &adapter->hw;
- u32 reg_val;
-
- if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
- goto restart_watchdog;
-
- if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
- reg_val = rd32(hw, I40E_VFGEN_RSTAT) &
- I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- if ((reg_val == VIRTCHNL_VFR_VFACTIVE) ||
- (reg_val == VIRTCHNL_VFR_COMPLETED)) {
- /* A chance for redemption! */
- dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n");
- adapter->state = __I40EVF_STARTUP;
- adapter->flags &= ~I40EVF_FLAG_PF_COMMS_FAILED;
- schedule_delayed_work(&adapter->init_task, 10);
- clear_bit(__I40EVF_IN_CRITICAL_TASK,
- &adapter->crit_section);
- /* Don't reschedule the watchdog, since we've restarted
- * the init task. When init_task contacts the PF and
- * gets everything set up again, it'll restart the
- * watchdog for us. Down, boy. Sit. Stay. Woof.
- */
- return;
- }
- adapter->aq_required = 0;
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
- goto watchdog_done;
- }
-
- if ((adapter->state < __I40EVF_DOWN) ||
- (adapter->flags & I40EVF_FLAG_RESET_PENDING))
- goto watchdog_done;
-
- /* check for reset */
- reg_val = rd32(hw, I40E_VF_ARQLEN1) & I40E_VF_ARQLEN1_ARQENABLE_MASK;
- if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) && !reg_val) {
- adapter->state = __I40EVF_RESETTING;
- adapter->flags |= I40EVF_FLAG_RESET_PENDING;
- dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
- schedule_work(&adapter->reset_task);
- adapter->aq_required = 0;
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
- goto watchdog_done;
- }
-
- /* Process admin queue tasks. After init, everything gets done
- * here so we don't race on the admin queue.
- */
- if (adapter->current_op) {
- if (!i40evf_asq_done(hw)) {
- dev_dbg(&adapter->pdev->dev, "Admin queue timeout\n");
- i40evf_send_api_ver(adapter);
- }
- goto watchdog_done;
- }
- if (adapter->aq_required & I40EVF_FLAG_AQ_GET_CONFIG) {
- i40evf_send_vf_config_msg(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_QUEUES) {
- i40evf_disable_queues(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_MAP_VECTORS) {
- i40evf_map_queues(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_ADD_MAC_FILTER) {
- i40evf_add_ether_addrs(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_ADD_VLAN_FILTER) {
- i40evf_add_vlans(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_DEL_MAC_FILTER) {
- i40evf_del_ether_addrs(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_DEL_VLAN_FILTER) {
- i40evf_del_vlans(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING) {
- i40evf_enable_vlan_stripping(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING) {
- i40evf_disable_vlan_stripping(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_CONFIGURE_QUEUES) {
- i40evf_configure_queues(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_ENABLE_QUEUES) {
- i40evf_enable_queues(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_CONFIGURE_RSS) {
- /* This message goes straight to the firmware, not the
- * PF, so we don't have to set current_op as we will
- * not get a response through the ARQ.
- */
- i40evf_init_rss(adapter);
- adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_RSS;
- goto watchdog_done;
- }
- if (adapter->aq_required & I40EVF_FLAG_AQ_GET_HENA) {
- i40evf_get_hena(adapter);
- goto watchdog_done;
- }
- if (adapter->aq_required & I40EVF_FLAG_AQ_SET_HENA) {
- i40evf_set_hena(adapter);
- goto watchdog_done;
- }
- if (adapter->aq_required & I40EVF_FLAG_AQ_SET_RSS_KEY) {
- i40evf_set_rss_key(adapter);
- goto watchdog_done;
- }
- if (adapter->aq_required & I40EVF_FLAG_AQ_SET_RSS_LUT) {
- i40evf_set_rss_lut(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_REQUEST_PROMISC) {
- i40evf_set_promiscuous(adapter, FLAG_VF_UNICAST_PROMISC |
- FLAG_VF_MULTICAST_PROMISC);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_REQUEST_ALLMULTI) {
- i40evf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC);
- goto watchdog_done;
- }
-
- if ((adapter->aq_required & I40EVF_FLAG_AQ_RELEASE_PROMISC) &&
- (adapter->aq_required & I40EVF_FLAG_AQ_RELEASE_ALLMULTI)) {
- i40evf_set_promiscuous(adapter, 0);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_ENABLE_CHANNELS) {
- i40evf_enable_channels(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_CHANNELS) {
- i40evf_disable_channels(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_ADD_CLOUD_FILTER) {
- i40evf_add_cloud_filter(adapter);
- goto watchdog_done;
- }
-
- if (adapter->aq_required & I40EVF_FLAG_AQ_DEL_CLOUD_FILTER) {
- i40evf_del_cloud_filter(adapter);
- goto watchdog_done;
- }
-
- schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5));
-
- if (adapter->state == __I40EVF_RUNNING)
- i40evf_request_stats(adapter);
-watchdog_done:
- if (adapter->state == __I40EVF_RUNNING)
- i40evf_detect_recover_hung(&adapter->vsi);
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
-restart_watchdog:
- if (adapter->state == __I40EVF_REMOVE)
- return;
- if (adapter->aq_required)
- mod_timer(&adapter->watchdog_timer,
- jiffies + msecs_to_jiffies(20));
- else
- mod_timer(&adapter->watchdog_timer, jiffies + (HZ * 2));
- schedule_work(&adapter->adminq_task);
-}
-
-static void i40evf_disable_vf(struct i40evf_adapter *adapter)
-{
- struct i40evf_mac_filter *f, *ftmp;
- struct i40evf_vlan_filter *fv, *fvtmp;
- struct i40evf_cloud_filter *cf, *cftmp;
-
- adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
-
- /* We don't use netif_running() because it may be true prior to
- * ndo_open() returning, so we can't assume it means all our open
- * tasks have finished, since we're not holding the rtnl_lock here.
- */
- if (adapter->state == __I40EVF_RUNNING) {
- set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
- netif_carrier_off(adapter->netdev);
- netif_tx_disable(adapter->netdev);
- adapter->link_up = false;
- i40evf_napi_disable_all(adapter);
- i40evf_irq_disable(adapter);
- i40evf_free_traffic_irqs(adapter);
- i40evf_free_all_tx_resources(adapter);
- i40evf_free_all_rx_resources(adapter);
- }
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- /* Delete all of the filters */
- list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
- list_del(&f->list);
- kfree(f);
- }
-
- list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list, list) {
- list_del(&fv->list);
- kfree(fv);
- }
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- spin_lock_bh(&adapter->cloud_filter_list_lock);
- list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {
- list_del(&cf->list);
- kfree(cf);
- adapter->num_cloud_filters--;
- }
- spin_unlock_bh(&adapter->cloud_filter_list_lock);
-
- i40evf_free_misc_irq(adapter);
- i40evf_reset_interrupt_capability(adapter);
- i40evf_free_queues(adapter);
- i40evf_free_q_vectors(adapter);
- kfree(adapter->vf_res);
- i40evf_shutdown_adminq(&adapter->hw);
- adapter->netdev->flags &= ~IFF_UP;
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
- adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
- adapter->state = __I40EVF_DOWN;
- wake_up(&adapter->down_waitqueue);
- dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
-}
-
-#define I40EVF_RESET_WAIT_MS 10
-#define I40EVF_RESET_WAIT_COUNT 500
-/**
- * i40evf_reset_task - Call-back task to handle hardware reset
- * @work: pointer to work_struct
- *
- * During reset we need to shut down and reinitialize the admin queue
- * before we can use it to communicate with the PF again. We also clear
- * and reinit the rings because that context is lost as well.
- **/
-static void i40evf_reset_task(struct work_struct *work)
-{
- struct i40evf_adapter *adapter = container_of(work,
- struct i40evf_adapter,
- reset_task);
- struct virtchnl_vf_resource *vfres = adapter->vf_res;
- struct net_device *netdev = adapter->netdev;
- struct i40e_hw *hw = &adapter->hw;
- struct i40evf_vlan_filter *vlf;
- struct i40evf_cloud_filter *cf;
- struct i40evf_mac_filter *f;
- u32 reg_val;
- int i = 0, err;
- bool running;
-
- /* When device is being removed it doesn't make sense to run the reset
- * task, just return in such a case.
- */
- if (test_bit(__I40EVF_IN_REMOVE_TASK, &adapter->crit_section))
- return;
-
- while (test_and_set_bit(__I40EVF_IN_CLIENT_TASK,
- &adapter->crit_section))
- usleep_range(500, 1000);
- if (CLIENT_ENABLED(adapter)) {
- adapter->flags &= ~(I40EVF_FLAG_CLIENT_NEEDS_OPEN |
- I40EVF_FLAG_CLIENT_NEEDS_CLOSE |
- I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS |
- I40EVF_FLAG_SERVICE_CLIENT_REQUESTED);
- cancel_delayed_work_sync(&adapter->client_task);
- i40evf_notify_client_close(&adapter->vsi, true);
- }
- i40evf_misc_irq_disable(adapter);
- if (adapter->flags & I40EVF_FLAG_RESET_NEEDED) {
- adapter->flags &= ~I40EVF_FLAG_RESET_NEEDED;
- /* Restart the AQ here. If we have been reset but didn't
- * detect it, or if the PF had to reinit, our AQ will be hosed.
- */
- i40evf_shutdown_adminq(hw);
- i40evf_init_adminq(hw);
- i40evf_request_reset(adapter);
- }
- adapter->flags |= I40EVF_FLAG_RESET_PENDING;
-
- /* poll until we see the reset actually happen */
- for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
- reg_val = rd32(hw, I40E_VF_ARQLEN1) &
- I40E_VF_ARQLEN1_ARQENABLE_MASK;
- if (!reg_val)
- break;
- usleep_range(5000, 10000);
- }
- if (i == I40EVF_RESET_WAIT_COUNT) {
- dev_info(&adapter->pdev->dev, "Never saw reset\n");
- goto continue_reset; /* act like the reset happened */
- }
-
- /* wait until the reset is complete and the PF is responding to us */
- for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
- /* sleep first to make sure a minimum wait time is met */
- msleep(I40EVF_RESET_WAIT_MS);
-
- reg_val = rd32(hw, I40E_VFGEN_RSTAT) &
- I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- if (reg_val == VIRTCHNL_VFR_VFACTIVE)
- break;
- }
-
- pci_set_master(adapter->pdev);
-
- if (i == I40EVF_RESET_WAIT_COUNT) {
- dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
- reg_val);
- i40evf_disable_vf(adapter);
- clear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);
- return; /* Do not attempt to reinit. It's dead, Jim. */
- }
-
-continue_reset:
- /* We don't use netif_running() because it may be true prior to
- * ndo_open() returning, so we can't assume it means all our open
- * tasks have finished, since we're not holding the rtnl_lock here.
- */
- running = ((adapter->state == __I40EVF_RUNNING) ||
- (adapter->state == __I40EVF_RESETTING));
-
- if (running) {
- netif_carrier_off(netdev);
- netif_tx_stop_all_queues(netdev);
- adapter->link_up = false;
- i40evf_napi_disable_all(adapter);
- }
- i40evf_irq_disable(adapter);
-
- adapter->state = __I40EVF_RESETTING;
- adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
-
- /* free the Tx/Rx rings and descriptors, might be better to just
- * re-use them sometime in the future
- */
- i40evf_free_all_rx_resources(adapter);
- i40evf_free_all_tx_resources(adapter);
-
- adapter->flags |= I40EVF_FLAG_QUEUES_DISABLED;
- /* kill and reinit the admin queue */
- i40evf_shutdown_adminq(hw);
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
- err = i40evf_init_adminq(hw);
- if (err)
- dev_info(&adapter->pdev->dev, "Failed to init adminq: %d\n",
- err);
- adapter->aq_required = 0;
-
- if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
- err = i40evf_reinit_interrupt_scheme(adapter);
- if (err)
- goto reset_err;
- }
-
- adapter->aq_required |= I40EVF_FLAG_AQ_GET_CONFIG;
- adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- /* re-add all MAC filters */
- list_for_each_entry(f, &adapter->mac_filter_list, list) {
- f->add = true;
- }
- /* re-add all VLAN filters */
- list_for_each_entry(vlf, &adapter->vlan_filter_list, list) {
- vlf->add = true;
- }
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- /* check if TCs are running and re-add all cloud filters */
- spin_lock_bh(&adapter->cloud_filter_list_lock);
- if ((vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
- adapter->num_tc) {
- list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
- cf->add = true;
- }
- }
- spin_unlock_bh(&adapter->cloud_filter_list_lock);
-
- adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
- adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
- adapter->aq_required |= I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;
- i40evf_misc_irq_enable(adapter);
-
- mod_timer(&adapter->watchdog_timer, jiffies + 2);
-
- /* We were running when the reset started, so we need to restore some
- * state here.
- */
- if (running) {
- /* allocate transmit descriptors */
- err = i40evf_setup_all_tx_resources(adapter);
- if (err)
- goto reset_err;
-
- /* allocate receive descriptors */
- err = i40evf_setup_all_rx_resources(adapter);
- if (err)
- goto reset_err;
-
- if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
- err = i40evf_request_traffic_irqs(adapter,
- netdev->name);
- if (err)
- goto reset_err;
-
- adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
- }
-
- i40evf_configure(adapter);
-
- i40evf_up_complete(adapter);
-
- i40evf_irq_enable(adapter, true);
- } else {
- adapter->state = __I40EVF_DOWN;
- wake_up(&adapter->down_waitqueue);
- }
- clear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
-
- return;
-reset_err:
- clear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
- dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
- i40evf_close(netdev);
-}
-
-/**
- * i40evf_adminq_task - worker thread to clean the admin queue
- * @work: pointer to work_struct containing our data
- **/
-static void i40evf_adminq_task(struct work_struct *work)
-{
- struct i40evf_adapter *adapter =
- container_of(work, struct i40evf_adapter, adminq_task);
- struct i40e_hw *hw = &adapter->hw;
- struct i40e_arq_event_info event;
- enum virtchnl_ops v_op;
- i40e_status ret, v_ret;
- u32 val, oldval;
- u16 pending;
-
- if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED)
- goto out;
-
- event.buf_len = I40EVF_MAX_AQ_BUF_SIZE;
- event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
- if (!event.msg_buf)
- goto out;
-
- do {
- ret = i40evf_clean_arq_element(hw, &event, &pending);
- v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
- v_ret = (i40e_status)le32_to_cpu(event.desc.cookie_low);
-
- if (ret || !v_op)
- break; /* No event to process or error cleaning ARQ */
-
- i40evf_virtchnl_completion(adapter, v_op, v_ret, event.msg_buf,
- event.msg_len);
- if (pending != 0)
- memset(event.msg_buf, 0, I40EVF_MAX_AQ_BUF_SIZE);
- } while (pending);
-
- if ((adapter->flags &
- (I40EVF_FLAG_RESET_PENDING | I40EVF_FLAG_RESET_NEEDED)) ||
- adapter->state == __I40EVF_RESETTING)
- goto freedom;
-
- /* check for error indications */
- val = rd32(hw, hw->aq.arq.len);
- if (val == 0xdeadbeef || val == 0xffffffff) /* device in reset */
- goto freedom;
- oldval = val;
- if (val & I40E_VF_ARQLEN1_ARQVFE_MASK) {
- dev_info(&adapter->pdev->dev, "ARQ VF Error detected\n");
- val &= ~I40E_VF_ARQLEN1_ARQVFE_MASK;
- }
- if (val & I40E_VF_ARQLEN1_ARQOVFL_MASK) {
- dev_info(&adapter->pdev->dev, "ARQ Overflow Error detected\n");
- val &= ~I40E_VF_ARQLEN1_ARQOVFL_MASK;
- }
- if (val & I40E_VF_ARQLEN1_ARQCRIT_MASK) {
- dev_info(&adapter->pdev->dev, "ARQ Critical Error detected\n");
- val &= ~I40E_VF_ARQLEN1_ARQCRIT_MASK;
- }
- if (oldval != val)
- wr32(hw, hw->aq.arq.len, val);
-
- val = rd32(hw, hw->aq.asq.len);
- oldval = val;
- if (val & I40E_VF_ATQLEN1_ATQVFE_MASK) {
- dev_info(&adapter->pdev->dev, "ASQ VF Error detected\n");
- val &= ~I40E_VF_ATQLEN1_ATQVFE_MASK;
- }
- if (val & I40E_VF_ATQLEN1_ATQOVFL_MASK) {
- dev_info(&adapter->pdev->dev, "ASQ Overflow Error detected\n");
- val &= ~I40E_VF_ATQLEN1_ATQOVFL_MASK;
- }
- if (val & I40E_VF_ATQLEN1_ATQCRIT_MASK) {
- dev_info(&adapter->pdev->dev, "ASQ Critical Error detected\n");
- val &= ~I40E_VF_ATQLEN1_ATQCRIT_MASK;
- }
- if (oldval != val)
- wr32(hw, hw->aq.asq.len, val);
-
-freedom:
- kfree(event.msg_buf);
-out:
- /* re-enable Admin queue interrupt cause */
- i40evf_misc_irq_enable(adapter);
-}
-
-/**
- * i40evf_client_task - worker thread to perform client work
- * @work: pointer to work_struct containing our data
- *
- * This task handles client interactions. Because client calls can be
- * reentrant, we can't handle them in the watchdog.
- **/
-static void i40evf_client_task(struct work_struct *work)
-{
- struct i40evf_adapter *adapter =
- container_of(work, struct i40evf_adapter, client_task.work);
-
- /* If we can't get the client bit, just give up. We'll be rescheduled
- * later.
- */
-
- if (test_and_set_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section))
- return;
-
- if (adapter->flags & I40EVF_FLAG_SERVICE_CLIENT_REQUESTED) {
- i40evf_client_subtask(adapter);
- adapter->flags &= ~I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
- goto out;
- }
- if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS) {
- i40evf_notify_client_l2_params(&adapter->vsi);
- adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS;
- goto out;
- }
- if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_CLOSE) {
- i40evf_notify_client_close(&adapter->vsi, false);
- adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_CLOSE;
- goto out;
- }
- if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_OPEN) {
- i40evf_notify_client_open(&adapter->vsi);
- adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_OPEN;
- }
-out:
- clear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);
-}
-
-/**
- * i40evf_free_all_tx_resources - Free Tx Resources for All Queues
- * @adapter: board private structure
- *
- * Free all transmit software resources
- **/
-void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter)
-{
- int i;
-
- if (!adapter->tx_rings)
- return;
-
- for (i = 0; i < adapter->num_active_queues; i++)
- if (adapter->tx_rings[i].desc)
- i40evf_free_tx_resources(&adapter->tx_rings[i]);
-}
-
-/**
- * i40evf_setup_all_tx_resources - allocate all queues Tx resources
- * @adapter: board private structure
- *
- * If this function returns with an error, then it's possible one or
- * more of the rings is populated (while the rest are not). It is the
- * callers duty to clean those orphaned rings.
- *
- * Return 0 on success, negative on failure
- **/
-static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter)
-{
- int i, err = 0;
-
- for (i = 0; i < adapter->num_active_queues; i++) {
- adapter->tx_rings[i].count = adapter->tx_desc_count;
- err = i40evf_setup_tx_descriptors(&adapter->tx_rings[i]);
- if (!err)
- continue;
- dev_err(&adapter->pdev->dev,
- "Allocation for Tx Queue %u failed\n", i);
- break;
- }
-
- return err;
-}
-
-/**
- * i40evf_setup_all_rx_resources - allocate all queues Rx resources
- * @adapter: board private structure
- *
- * If this function returns with an error, then it's possible one or
- * more of the rings is populated (while the rest are not). It is the
- * callers duty to clean those orphaned rings.
- *
- * Return 0 on success, negative on failure
- **/
-static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter)
-{
- int i, err = 0;
-
- for (i = 0; i < adapter->num_active_queues; i++) {
- adapter->rx_rings[i].count = adapter->rx_desc_count;
- err = i40evf_setup_rx_descriptors(&adapter->rx_rings[i]);
- if (!err)
- continue;
- dev_err(&adapter->pdev->dev,
- "Allocation for Rx Queue %u failed\n", i);
- break;
- }
- return err;
-}
-
-/**
- * i40evf_free_all_rx_resources - Free Rx Resources for All Queues
- * @adapter: board private structure
- *
- * Free all receive software resources
- **/
-void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter)
-{
- int i;
-
- if (!adapter->rx_rings)
- return;
-
- for (i = 0; i < adapter->num_active_queues; i++)
- if (adapter->rx_rings[i].desc)
- i40evf_free_rx_resources(&adapter->rx_rings[i]);
-}
-
-/**
- * i40evf_validate_tx_bandwidth - validate the max Tx bandwidth
- * @adapter: board private structure
- * @max_tx_rate: max Tx bw for a tc
- **/
-static int i40evf_validate_tx_bandwidth(struct i40evf_adapter *adapter,
- u64 max_tx_rate)
-{
- int speed = 0, ret = 0;
-
- switch (adapter->link_speed) {
- case I40E_LINK_SPEED_40GB:
- speed = 40000;
- break;
- case I40E_LINK_SPEED_25GB:
- speed = 25000;
- break;
- case I40E_LINK_SPEED_20GB:
- speed = 20000;
- break;
- case I40E_LINK_SPEED_10GB:
- speed = 10000;
- break;
- case I40E_LINK_SPEED_1GB:
- speed = 1000;
- break;
- case I40E_LINK_SPEED_100MB:
- speed = 100;
- break;
- default:
- break;
- }
-
- if (max_tx_rate > speed) {
- dev_err(&adapter->pdev->dev,
- "Invalid tx rate specified\n");
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-/**
- * i40evf_validate_channel_config - validate queue mapping info
- * @adapter: board private structure
- * @mqprio_qopt: queue parameters
- *
- * This function validates if the config provided by the user to
- * configure queue channels is valid or not. Returns 0 on a valid
- * config.
- **/
-static int i40evf_validate_ch_config(struct i40evf_adapter *adapter,
- struct tc_mqprio_qopt_offload *mqprio_qopt)
-{
- u64 total_max_rate = 0;
- int i, num_qps = 0;
- u64 tx_rate = 0;
- int ret = 0;
-
- if (mqprio_qopt->qopt.num_tc > I40EVF_MAX_TRAFFIC_CLASS ||
- mqprio_qopt->qopt.num_tc < 1)
- return -EINVAL;
-
- for (i = 0; i <= mqprio_qopt->qopt.num_tc - 1; i++) {
- if (!mqprio_qopt->qopt.count[i] ||
- mqprio_qopt->qopt.offset[i] != num_qps)
- return -EINVAL;
- if (mqprio_qopt->min_rate[i]) {
- dev_err(&adapter->pdev->dev,
- "Invalid min tx rate (greater than 0) specified\n");
- return -EINVAL;
- }
- /*convert to Mbps */
- tx_rate = div_u64(mqprio_qopt->max_rate[i],
- I40EVF_MBPS_DIVISOR);
- total_max_rate += tx_rate;
- num_qps += mqprio_qopt->qopt.count[i];
- }
- if (num_qps > I40EVF_MAX_REQ_QUEUES)
- return -EINVAL;
-
- ret = i40evf_validate_tx_bandwidth(adapter, total_max_rate);
- return ret;
-}
-
-/**
- * i40evf_del_all_cloud_filters - delete all cloud filters
- * on the traffic classes
- **/
-static void i40evf_del_all_cloud_filters(struct i40evf_adapter *adapter)
-{
- struct i40evf_cloud_filter *cf, *cftmp;
-
- spin_lock_bh(&adapter->cloud_filter_list_lock);
- list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list,
- list) {
- list_del(&cf->list);
- kfree(cf);
- adapter->num_cloud_filters--;
- }
- spin_unlock_bh(&adapter->cloud_filter_list_lock);
-}
-
-/**
- * __i40evf_setup_tc - configure multiple traffic classes
- * @netdev: network interface device structure
- * @type_date: tc offload data
- *
- * This function processes the config information provided by the
- * user to configure traffic classes/queue channels and packages the
- * information to request the PF to setup traffic classes.
- *
- * Returns 0 on success.
- **/
-static int __i40evf_setup_tc(struct net_device *netdev, void *type_data)
-{
- struct tc_mqprio_qopt_offload *mqprio_qopt = type_data;
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- struct virtchnl_vf_resource *vfres = adapter->vf_res;
- u8 num_tc = 0, total_qps = 0;
- int ret = 0, netdev_tc = 0;
- u64 max_tx_rate;
- u16 mode;
- int i;
-
- num_tc = mqprio_qopt->qopt.num_tc;
- mode = mqprio_qopt->mode;
-
- /* delete queue_channel */
- if (!mqprio_qopt->qopt.hw) {
- if (adapter->ch_config.state == __I40EVF_TC_RUNNING) {
- /* reset the tc configuration */
- netdev_reset_tc(netdev);
- adapter->num_tc = 0;
- netif_tx_stop_all_queues(netdev);
- netif_tx_disable(netdev);
- i40evf_del_all_cloud_filters(adapter);
- adapter->aq_required = I40EVF_FLAG_AQ_DISABLE_CHANNELS;
- goto exit;
- } else {
- return -EINVAL;
- }
- }
-
- /* add queue channel */
- if (mode == TC_MQPRIO_MODE_CHANNEL) {
- if (!(vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ)) {
- dev_err(&adapter->pdev->dev, "ADq not supported\n");
- return -EOPNOTSUPP;
- }
- if (adapter->ch_config.state != __I40EVF_TC_INVALID) {
- dev_err(&adapter->pdev->dev, "TC configuration already exists\n");
- return -EINVAL;
- }
-
- ret = i40evf_validate_ch_config(adapter, mqprio_qopt);
- if (ret)
- return ret;
- /* Return if same TC config is requested */
- if (adapter->num_tc == num_tc)
- return 0;
- adapter->num_tc = num_tc;
-
- for (i = 0; i < I40EVF_MAX_TRAFFIC_CLASS; i++) {
- if (i < num_tc) {
- adapter->ch_config.ch_info[i].count =
- mqprio_qopt->qopt.count[i];
- adapter->ch_config.ch_info[i].offset =
- mqprio_qopt->qopt.offset[i];
- total_qps += mqprio_qopt->qopt.count[i];
- max_tx_rate = mqprio_qopt->max_rate[i];
- /* convert to Mbps */
- max_tx_rate = div_u64(max_tx_rate,
- I40EVF_MBPS_DIVISOR);
- adapter->ch_config.ch_info[i].max_tx_rate =
- max_tx_rate;
- } else {
- adapter->ch_config.ch_info[i].count = 1;
- adapter->ch_config.ch_info[i].offset = 0;
- }
- }
- adapter->ch_config.total_qps = total_qps;
- netif_tx_stop_all_queues(netdev);
- netif_tx_disable(netdev);
- adapter->aq_required |= I40EVF_FLAG_AQ_ENABLE_CHANNELS;
- netdev_reset_tc(netdev);
- /* Report the tc mapping up the stack */
- netdev_set_num_tc(adapter->netdev, num_tc);
- for (i = 0; i < I40EVF_MAX_TRAFFIC_CLASS; i++) {
- u16 qcount = mqprio_qopt->qopt.count[i];
- u16 qoffset = mqprio_qopt->qopt.offset[i];
-
- if (i < num_tc)
- netdev_set_tc_queue(netdev, netdev_tc++, qcount,
- qoffset);
- }
- }
-exit:
- return ret;
-}
-
-/**
- * i40evf_parse_cls_flower - Parse tc flower filters provided by kernel
- * @adapter: board private structure
- * @cls_flower: pointer to struct tc_cls_flower_offload
- * @filter: pointer to cloud filter structure
- */
-static int i40evf_parse_cls_flower(struct i40evf_adapter *adapter,
- struct tc_cls_flower_offload *f,
- struct i40evf_cloud_filter *filter)
-{
- u16 n_proto_mask = 0;
- u16 n_proto_key = 0;
- u8 field_flags = 0;
- u16 addr_type = 0;
- u16 n_proto = 0;
- int i = 0;
- struct virtchnl_filter *vf = &filter->f;
-
- if (f->dissector->used_keys &
- ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
- BIT(FLOW_DISSECTOR_KEY_BASIC) |
- BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
- BIT(FLOW_DISSECTOR_KEY_VLAN) |
- BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
- BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
- BIT(FLOW_DISSECTOR_KEY_PORTS) |
- BIT(FLOW_DISSECTOR_KEY_ENC_KEYID))) {
- dev_err(&adapter->pdev->dev, "Unsupported key used: 0x%x\n",
- f->dissector->used_keys);
- return -EOPNOTSUPP;
- }
-
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
- struct flow_dissector_key_keyid *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ENC_KEYID,
- f->mask);
-
- if (mask->keyid != 0)
- field_flags |= I40EVF_CLOUD_FIELD_TEN_ID;
- }
-
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
- struct flow_dissector_key_basic *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->key);
-
- struct flow_dissector_key_basic *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_BASIC,
- f->mask);
- n_proto_key = ntohs(key->n_proto);
- n_proto_mask = ntohs(mask->n_proto);
-
- if (n_proto_key == ETH_P_ALL) {
- n_proto_key = 0;
- n_proto_mask = 0;
- }
- n_proto = n_proto_key & n_proto_mask;
- if (n_proto != ETH_P_IP && n_proto != ETH_P_IPV6)
- return -EINVAL;
- if (n_proto == ETH_P_IPV6) {
- /* specify flow type as TCP IPv6 */
- vf->flow_type = VIRTCHNL_TCP_V6_FLOW;
- }
-
- if (key->ip_proto != IPPROTO_TCP) {
- dev_info(&adapter->pdev->dev, "Only TCP transport is supported\n");
- return -EINVAL;
- }
- }
-
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
- struct flow_dissector_key_eth_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->key);
-
- struct flow_dissector_key_eth_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_ETH_ADDRS,
- f->mask);
- /* use is_broadcast and is_zero to check for all 0xf or 0 */
- if (!is_zero_ether_addr(mask->dst)) {
- if (is_broadcast_ether_addr(mask->dst)) {
- field_flags |= I40EVF_CLOUD_FIELD_OMAC;
- } else {
- dev_err(&adapter->pdev->dev, "Bad ether dest mask %pM\n",
- mask->dst);
- return I40E_ERR_CONFIG;
- }
- }
-
- if (!is_zero_ether_addr(mask->src)) {
- if (is_broadcast_ether_addr(mask->src)) {
- field_flags |= I40EVF_CLOUD_FIELD_IMAC;
- } else {
- dev_err(&adapter->pdev->dev, "Bad ether src mask %pM\n",
- mask->src);
- return I40E_ERR_CONFIG;
- }
- }
-
- if (!is_zero_ether_addr(key->dst))
- if (is_valid_ether_addr(key->dst) ||
- is_multicast_ether_addr(key->dst)) {
- /* set the mask if a valid dst_mac address */
- for (i = 0; i < ETH_ALEN; i++)
- vf->mask.tcp_spec.dst_mac[i] |= 0xff;
- ether_addr_copy(vf->data.tcp_spec.dst_mac,
- key->dst);
- }
-
- if (!is_zero_ether_addr(key->src))
- if (is_valid_ether_addr(key->src) ||
- is_multicast_ether_addr(key->src)) {
- /* set the mask if a valid dst_mac address */
- for (i = 0; i < ETH_ALEN; i++)
- vf->mask.tcp_spec.src_mac[i] |= 0xff;
- ether_addr_copy(vf->data.tcp_spec.src_mac,
- key->src);
- }
- }
-
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_dissector_key_vlan *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->key);
- struct flow_dissector_key_vlan *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_VLAN,
- f->mask);
-
- if (mask->vlan_id) {
- if (mask->vlan_id == VLAN_VID_MASK) {
- field_flags |= I40EVF_CLOUD_FIELD_IVLAN;
- } else {
- dev_err(&adapter->pdev->dev, "Bad vlan mask %u\n",
- mask->vlan_id);
- return I40E_ERR_CONFIG;
- }
- }
- vf->mask.tcp_spec.vlan_id |= cpu_to_be16(0xffff);
- vf->data.tcp_spec.vlan_id = cpu_to_be16(key->vlan_id);
- }
-
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
- struct flow_dissector_key_control *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_CONTROL,
- f->key);
-
- addr_type = key->addr_type;
- }
-
- if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
- struct flow_dissector_key_ipv4_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->key);
- struct flow_dissector_key_ipv4_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV4_ADDRS,
- f->mask);
-
- if (mask->dst) {
- if (mask->dst == cpu_to_be32(0xffffffff)) {
- field_flags |= I40EVF_CLOUD_FIELD_IIP;
- } else {
- dev_err(&adapter->pdev->dev, "Bad ip dst mask 0x%08x\n",
- be32_to_cpu(mask->dst));
- return I40E_ERR_CONFIG;
- }
- }
-
- if (mask->src) {
- if (mask->src == cpu_to_be32(0xffffffff)) {
- field_flags |= I40EVF_CLOUD_FIELD_IIP;
- } else {
- dev_err(&adapter->pdev->dev, "Bad ip src mask 0x%08x\n",
- be32_to_cpu(mask->dst));
- return I40E_ERR_CONFIG;
- }
- }
-
- if (field_flags & I40EVF_CLOUD_FIELD_TEN_ID) {
- dev_info(&adapter->pdev->dev, "Tenant id not allowed for ip filter\n");
- return I40E_ERR_CONFIG;
- }
- if (key->dst) {
- vf->mask.tcp_spec.dst_ip[0] |= cpu_to_be32(0xffffffff);
- vf->data.tcp_spec.dst_ip[0] = key->dst;
- }
- if (key->src) {
- vf->mask.tcp_spec.src_ip[0] |= cpu_to_be32(0xffffffff);
- vf->data.tcp_spec.src_ip[0] = key->src;
- }
- }
-
- if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
- struct flow_dissector_key_ipv6_addrs *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->key);
- struct flow_dissector_key_ipv6_addrs *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_IPV6_ADDRS,
- f->mask);
-
- /* validate mask, make sure it is not IPV6_ADDR_ANY */
- if (ipv6_addr_any(&mask->dst)) {
- dev_err(&adapter->pdev->dev, "Bad ipv6 dst mask 0x%02x\n",
- IPV6_ADDR_ANY);
- return I40E_ERR_CONFIG;
- }
-
- /* src and dest IPv6 address should not be LOOPBACK
- * (0:0:0:0:0:0:0:1) which can be represented as ::1
- */
- if (ipv6_addr_loopback(&key->dst) ||
- ipv6_addr_loopback(&key->src)) {
- dev_err(&adapter->pdev->dev,
- "ipv6 addr should not be loopback\n");
- return I40E_ERR_CONFIG;
- }
- if (!ipv6_addr_any(&mask->dst) || !ipv6_addr_any(&mask->src))
- field_flags |= I40EVF_CLOUD_FIELD_IIP;
-
- for (i = 0; i < 4; i++)
- vf->mask.tcp_spec.dst_ip[i] |= cpu_to_be32(0xffffffff);
- memcpy(&vf->data.tcp_spec.dst_ip, &key->dst.s6_addr32,
- sizeof(vf->data.tcp_spec.dst_ip));
- for (i = 0; i < 4; i++)
- vf->mask.tcp_spec.src_ip[i] |= cpu_to_be32(0xffffffff);
- memcpy(&vf->data.tcp_spec.src_ip, &key->src.s6_addr32,
- sizeof(vf->data.tcp_spec.src_ip));
- }
- if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
- struct flow_dissector_key_ports *key =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->key);
- struct flow_dissector_key_ports *mask =
- skb_flow_dissector_target(f->dissector,
- FLOW_DISSECTOR_KEY_PORTS,
- f->mask);
-
- if (mask->src) {
- if (mask->src == cpu_to_be16(0xffff)) {
- field_flags |= I40EVF_CLOUD_FIELD_IIP;
- } else {
- dev_err(&adapter->pdev->dev, "Bad src port mask %u\n",
- be16_to_cpu(mask->src));
- return I40E_ERR_CONFIG;
- }
- }
-
- if (mask->dst) {
- if (mask->dst == cpu_to_be16(0xffff)) {
- field_flags |= I40EVF_CLOUD_FIELD_IIP;
- } else {
- dev_err(&adapter->pdev->dev, "Bad dst port mask %u\n",
- be16_to_cpu(mask->dst));
- return I40E_ERR_CONFIG;
- }
- }
- if (key->dst) {
- vf->mask.tcp_spec.dst_port |= cpu_to_be16(0xffff);
- vf->data.tcp_spec.dst_port = key->dst;
- }
-
- if (key->src) {
- vf->mask.tcp_spec.src_port |= cpu_to_be16(0xffff);
- vf->data.tcp_spec.src_port = key->src;
- }
- }
- vf->field_flags = field_flags;
-
- return 0;
-}
-
-/**
- * i40evf_handle_tclass - Forward to a traffic class on the device
- * @adapter: board private structure
- * @tc: traffic class index on the device
- * @filter: pointer to cloud filter structure
- */
-static int i40evf_handle_tclass(struct i40evf_adapter *adapter, u32 tc,
- struct i40evf_cloud_filter *filter)
-{
- if (tc == 0)
- return 0;
- if (tc < adapter->num_tc) {
- if (!filter->f.data.tcp_spec.dst_port) {
- dev_err(&adapter->pdev->dev,
- "Specify destination port to redirect to traffic class other than TC0\n");
- return -EINVAL;
- }
- }
- /* redirect to a traffic class on the same device */
- filter->f.action = VIRTCHNL_ACTION_TC_REDIRECT;
- filter->f.action_meta = tc;
- return 0;
-}
-
-/**
- * i40evf_configure_clsflower - Add tc flower filters
- * @adapter: board private structure
- * @cls_flower: Pointer to struct tc_cls_flower_offload
- */
-static int i40evf_configure_clsflower(struct i40evf_adapter *adapter,
- struct tc_cls_flower_offload *cls_flower)
-{
- int tc = tc_classid_to_hwtc(adapter->netdev, cls_flower->classid);
- struct i40evf_cloud_filter *filter = NULL;
- int err = -EINVAL, count = 50;
-
- if (tc < 0) {
- dev_err(&adapter->pdev->dev, "Invalid traffic class\n");
- return -EINVAL;
- }
-
- filter = kzalloc(sizeof(*filter), GFP_KERNEL);
- if (!filter)
- return -ENOMEM;
-
- while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
- &adapter->crit_section)) {
- if (--count == 0)
- goto err;
- udelay(1);
- }
-
- filter->cookie = cls_flower->cookie;
-
- /* set the mask to all zeroes to begin with */
- memset(&filter->f.mask.tcp_spec, 0, sizeof(struct virtchnl_l4_spec));
- /* start out with flow type and eth type IPv4 to begin with */
- filter->f.flow_type = VIRTCHNL_TCP_V4_FLOW;
- err = i40evf_parse_cls_flower(adapter, cls_flower, filter);
- if (err < 0)
- goto err;
-
- err = i40evf_handle_tclass(adapter, tc, filter);
- if (err < 0)
- goto err;
-
- /* add filter to the list */
- spin_lock_bh(&adapter->cloud_filter_list_lock);
- list_add_tail(&filter->list, &adapter->cloud_filter_list);
- adapter->num_cloud_filters++;
- filter->add = true;
- adapter->aq_required |= I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;
- spin_unlock_bh(&adapter->cloud_filter_list_lock);
-err:
- if (err)
- kfree(filter);
-
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
- return err;
-}
-
-/* i40evf_find_cf - Find the cloud filter in the list
- * @adapter: Board private structure
- * @cookie: filter specific cookie
- *
- * Returns ptr to the filter object or NULL. Must be called while holding the
- * cloud_filter_list_lock.
- */
-static struct i40evf_cloud_filter *i40evf_find_cf(struct i40evf_adapter *adapter,
- unsigned long *cookie)
-{
- struct i40evf_cloud_filter *filter = NULL;
-
- if (!cookie)
- return NULL;
-
- list_for_each_entry(filter, &adapter->cloud_filter_list, list) {
- if (!memcmp(cookie, &filter->cookie, sizeof(filter->cookie)))
- return filter;
- }
- return NULL;
-}
-
-/**
- * i40evf_delete_clsflower - Remove tc flower filters
- * @adapter: board private structure
- * @cls_flower: Pointer to struct tc_cls_flower_offload
- */
-static int i40evf_delete_clsflower(struct i40evf_adapter *adapter,
- struct tc_cls_flower_offload *cls_flower)
-{
- struct i40evf_cloud_filter *filter = NULL;
- int err = 0;
-
- spin_lock_bh(&adapter->cloud_filter_list_lock);
- filter = i40evf_find_cf(adapter, &cls_flower->cookie);
- if (filter) {
- filter->del = true;
- adapter->aq_required |= I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;
- } else {
- err = -EINVAL;
- }
- spin_unlock_bh(&adapter->cloud_filter_list_lock);
-
- return err;
-}
-
-/**
- * i40evf_setup_tc_cls_flower - flower classifier offloads
- * @netdev: net device to configure
- * @type_data: offload data
- */
-static int i40evf_setup_tc_cls_flower(struct i40evf_adapter *adapter,
- struct tc_cls_flower_offload *cls_flower)
-{
- if (cls_flower->common.chain_index)
- return -EOPNOTSUPP;
-
- switch (cls_flower->command) {
- case TC_CLSFLOWER_REPLACE:
- return i40evf_configure_clsflower(adapter, cls_flower);
- case TC_CLSFLOWER_DESTROY:
- return i40evf_delete_clsflower(adapter, cls_flower);
- case TC_CLSFLOWER_STATS:
- return -EOPNOTSUPP;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-/**
- * i40evf_setup_tc_block_cb - block callback for tc
- * @type: type of offload
- * @type_data: offload data
- * @cb_priv:
- *
- * This function is the block callback for traffic classes
- **/
-static int i40evf_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
- void *cb_priv)
-{
- switch (type) {
- case TC_SETUP_CLSFLOWER:
- return i40evf_setup_tc_cls_flower(cb_priv, type_data);
- default:
- return -EOPNOTSUPP;
- }
-}
-
-/**
- * i40evf_setup_tc_block - register callbacks for tc
- * @netdev: network interface device structure
- * @f: tc offload data
- *
- * This function registers block callbacks for tc
- * offloads
- **/
-static int i40evf_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
-{
- struct i40evf_adapter *adapter = netdev_priv(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, i40evf_setup_tc_block_cb,
- adapter, adapter, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, i40evf_setup_tc_block_cb,
- adapter);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-/**
- * i40evf_setup_tc - configure multiple traffic classes
- * @netdev: network interface device structure
- * @type: type of offload
- * @type_date: tc offload data
- *
- * This function is the callback to ndo_setup_tc in the
- * netdev_ops.
- *
- * Returns 0 on success
- **/
-static int i40evf_setup_tc(struct net_device *netdev, enum tc_setup_type type,
- void *type_data)
-{
- switch (type) {
- case TC_SETUP_QDISC_MQPRIO:
- return __i40evf_setup_tc(netdev, type_data);
- case TC_SETUP_BLOCK:
- return i40evf_setup_tc_block(netdev, type_data);
- default:
- return -EOPNOTSUPP;
- }
-}
-
-/**
- * i40evf_open - Called when a network interface is made active
- * @netdev: network interface device structure
- *
- * Returns 0 on success, negative value on failure
- *
- * The open entry point is called when a network interface is made
- * active by the system (IFF_UP). At this point all resources needed
- * for transmit and receive operations are allocated, the interrupt
- * handler is registered with the OS, the watchdog timer is started,
- * and the stack is notified that the interface is ready.
- **/
-static int i40evf_open(struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- int err;
-
- if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
- dev_err(&adapter->pdev->dev, "Unable to open device due to PF driver failure.\n");
- return -EIO;
- }
-
- while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
- &adapter->crit_section))
- usleep_range(500, 1000);
-
- if (adapter->state != __I40EVF_DOWN) {
- err = -EBUSY;
- goto err_unlock;
- }
-
- /* allocate transmit descriptors */
- err = i40evf_setup_all_tx_resources(adapter);
- if (err)
- goto err_setup_tx;
-
- /* allocate receive descriptors */
- err = i40evf_setup_all_rx_resources(adapter);
- if (err)
- goto err_setup_rx;
-
- /* clear any pending interrupts, may auto mask */
- err = i40evf_request_traffic_irqs(adapter, netdev->name);
- if (err)
- goto err_req_irq;
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- i40evf_add_filter(adapter, adapter->hw.mac.addr);
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- i40evf_configure(adapter);
-
- i40evf_up_complete(adapter);
-
- i40evf_irq_enable(adapter, true);
-
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
-
- return 0;
-
-err_req_irq:
- i40evf_down(adapter);
- i40evf_free_traffic_irqs(adapter);
-err_setup_rx:
- i40evf_free_all_rx_resources(adapter);
-err_setup_tx:
- i40evf_free_all_tx_resources(adapter);
-err_unlock:
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
-
- return err;
-}
-
-/**
- * i40evf_close - Disables a network interface
- * @netdev: network interface device structure
- *
- * Returns 0, this is not allowed to fail
- *
- * The close entry point is called when an interface is de-activated
- * by the OS. The hardware is still under the drivers control, but
- * needs to be disabled. All IRQs except vector 0 (reserved for admin queue)
- * are freed, along with all transmit and receive resources.
- **/
-static int i40evf_close(struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- int status;
-
- if (adapter->state <= __I40EVF_DOWN_PENDING)
- return 0;
-
- while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
- &adapter->crit_section))
- usleep_range(500, 1000);
-
- set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
- if (CLIENT_ENABLED(adapter))
- adapter->flags |= I40EVF_FLAG_CLIENT_NEEDS_CLOSE;
-
- i40evf_down(adapter);
- adapter->state = __I40EVF_DOWN_PENDING;
- i40evf_free_traffic_irqs(adapter);
-
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
-
- /* We explicitly don't free resources here because the hardware is
- * still active and can DMA into memory. Resources are cleared in
- * i40evf_virtchnl_completion() after we get confirmation from the PF
- * driver that the rings have been stopped.
- *
- * Also, we wait for state to transition to __I40EVF_DOWN before
- * returning. State change occurs in i40evf_virtchnl_completion() after
- * VF resources are released (which occurs after PF driver processes and
- * responds to admin queue commands).
- */
-
- status = wait_event_timeout(adapter->down_waitqueue,
- adapter->state == __I40EVF_DOWN,
- msecs_to_jiffies(200));
- if (!status)
- netdev_warn(netdev, "Device resources not yet released\n");
- return 0;
-}
-
-/**
- * i40evf_change_mtu - Change the Maximum Transfer Unit
- * @netdev: network interface device structure
- * @new_mtu: new value for maximum frame size
- *
- * Returns 0 on success, negative on failure
- **/
-static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- netdev->mtu = new_mtu;
- if (CLIENT_ENABLED(adapter)) {
- i40evf_notify_client_l2_params(&adapter->vsi);
- adapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
- }
- adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
- schedule_work(&adapter->reset_task);
-
- return 0;
-}
-
-/**
- * i40e_set_features - set the netdev feature flags
- * @netdev: ptr to the netdev being adjusted
- * @features: the feature set that the stack is suggesting
- * Note: expects to be called while under rtnl_lock()
- **/
-static int i40evf_set_features(struct net_device *netdev,
- netdev_features_t features)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- /* Don't allow changing VLAN_RX flag when adapter is not capable
- * of VLAN offload
- */
- if (!VLAN_ALLOWED(adapter)) {
- if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX)
- return -EINVAL;
- } else if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX) {
- if (features & NETIF_F_HW_VLAN_CTAG_RX)
- adapter->aq_required |=
- I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING;
- else
- adapter->aq_required |=
- I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING;
- }
-
- return 0;
-}
-
-/**
- * i40evf_features_check - Validate encapsulated packet conforms to limits
- * @skb: skb buff
- * @dev: This physical port's netdev
- * @features: Offload features that the stack believes apply
- **/
-static netdev_features_t i40evf_features_check(struct sk_buff *skb,
- struct net_device *dev,
- netdev_features_t features)
-{
- size_t len;
-
- /* No point in doing any of this if neither checksum nor GSO are
- * being requested for this frame. We can rule out both by just
- * checking for CHECKSUM_PARTIAL
- */
- if (skb->ip_summed != CHECKSUM_PARTIAL)
- return features;
-
- /* We cannot support GSO if the MSS is going to be less than
- * 64 bytes. If it is then we need to drop support for GSO.
- */
- if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
- features &= ~NETIF_F_GSO_MASK;
-
- /* MACLEN can support at most 63 words */
- len = skb_network_header(skb) - skb->data;
- if (len & ~(63 * 2))
- goto out_err;
-
- /* IPLEN and EIPLEN can support at most 127 dwords */
- len = skb_transport_header(skb) - skb_network_header(skb);
- if (len & ~(127 * 4))
- goto out_err;
-
- if (skb->encapsulation) {
- /* L4TUNLEN can support 127 words */
- len = skb_inner_network_header(skb) - skb_transport_header(skb);
- if (len & ~(127 * 2))
- goto out_err;
-
- /* IPLEN can support at most 127 dwords */
- len = skb_inner_transport_header(skb) -
- skb_inner_network_header(skb);
- if (len & ~(127 * 4))
- goto out_err;
- }
-
- /* No need to validate L4LEN as TCP is the only protocol with a
- * a flexible value and we support all possible values supported
- * by TCP, which is at most 15 dwords
- */
-
- return features;
-out_err:
- return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
-}
-
-/**
- * i40evf_fix_features - fix up the netdev feature bits
- * @netdev: our net device
- * @features: desired feature bits
- *
- * Returns fixed-up features bits
- **/
-static netdev_features_t i40evf_fix_features(struct net_device *netdev,
- netdev_features_t features)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- if (adapter->vf_res &&
- !(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
- features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
- NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_VLAN_CTAG_FILTER);
-
- return features;
-}
-
-static const struct net_device_ops i40evf_netdev_ops = {
- .ndo_open = i40evf_open,
- .ndo_stop = i40evf_close,
- .ndo_start_xmit = i40evf_xmit_frame,
- .ndo_set_rx_mode = i40evf_set_rx_mode,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = i40evf_set_mac,
- .ndo_change_mtu = i40evf_change_mtu,
- .ndo_tx_timeout = i40evf_tx_timeout,
- .ndo_vlan_rx_add_vid = i40evf_vlan_rx_add_vid,
- .ndo_vlan_rx_kill_vid = i40evf_vlan_rx_kill_vid,
- .ndo_features_check = i40evf_features_check,
- .ndo_fix_features = i40evf_fix_features,
- .ndo_set_features = i40evf_set_features,
- .ndo_setup_tc = i40evf_setup_tc,
-};
-
-/**
- * i40evf_check_reset_complete - check that VF reset is complete
- * @hw: pointer to hw struct
- *
- * Returns 0 if device is ready to use, or -EBUSY if it's in reset.
- **/
-static int i40evf_check_reset_complete(struct i40e_hw *hw)
-{
- u32 rstat;
- int i;
-
- for (i = 0; i < 100; i++) {
- rstat = rd32(hw, I40E_VFGEN_RSTAT) &
- I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- if ((rstat == VIRTCHNL_VFR_VFACTIVE) ||
- (rstat == VIRTCHNL_VFR_COMPLETED))
- return 0;
- usleep_range(10, 20);
- }
- return -EBUSY;
-}
-
-/**
- * i40evf_process_config - Process the config information we got from the PF
- * @adapter: board private structure
- *
- * Verify that we have a valid config struct, and set up our netdev features
- * and our VSI struct.
- **/
-int i40evf_process_config(struct i40evf_adapter *adapter)
-{
- struct virtchnl_vf_resource *vfres = adapter->vf_res;
- int i, num_req_queues = adapter->num_req_queues;
- struct net_device *netdev = adapter->netdev;
- struct i40e_vsi *vsi = &adapter->vsi;
- netdev_features_t hw_enc_features;
- netdev_features_t hw_features;
-
- /* got VF config message back from PF, now we can parse it */
- for (i = 0; i < vfres->num_vsis; i++) {
- if (vfres->vsi_res[i].vsi_type == VIRTCHNL_VSI_SRIOV)
- adapter->vsi_res = &vfres->vsi_res[i];
- }
- if (!adapter->vsi_res) {
- dev_err(&adapter->pdev->dev, "No LAN VSI found\n");
- return -ENODEV;
- }
-
- if (num_req_queues &&
- num_req_queues != adapter->vsi_res->num_queue_pairs) {
- /* Problem. The PF gave us fewer queues than what we had
- * negotiated in our request. Need a reset to see if we can't
- * get back to a working state.
- */
- dev_err(&adapter->pdev->dev,
- "Requested %d queues, but PF only gave us %d.\n",
- num_req_queues,
- adapter->vsi_res->num_queue_pairs);
- adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
- adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
- i40evf_schedule_reset(adapter);
- return -ENODEV;
- }
- adapter->num_req_queues = 0;
-
- hw_enc_features = NETIF_F_SG |
- NETIF_F_IP_CSUM |
- NETIF_F_IPV6_CSUM |
- NETIF_F_HIGHDMA |
- NETIF_F_SOFT_FEATURES |
- NETIF_F_TSO |
- NETIF_F_TSO_ECN |
- NETIF_F_TSO6 |
- NETIF_F_SCTP_CRC |
- NETIF_F_RXHASH |
- NETIF_F_RXCSUM |
- 0;
-
- /* advertise to stack only if offloads for encapsulated packets is
- * supported
- */
- if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ENCAP) {
- hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL |
- NETIF_F_GSO_GRE |
- NETIF_F_GSO_GRE_CSUM |
- NETIF_F_GSO_IPXIP4 |
- NETIF_F_GSO_IPXIP6 |
- NETIF_F_GSO_UDP_TUNNEL_CSUM |
- NETIF_F_GSO_PARTIAL |
- 0;
-
- if (!(vfres->vf_cap_flags &
- VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM))
- netdev->gso_partial_features |=
- NETIF_F_GSO_UDP_TUNNEL_CSUM;
-
- netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
- netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
- netdev->hw_enc_features |= hw_enc_features;
- }
- /* record features VLANs can make use of */
- netdev->vlan_features |= hw_enc_features | NETIF_F_TSO_MANGLEID;
-
- /* Write features and hw_features separately to avoid polluting
- * with, or dropping, features that are set when we registered.
- */
- hw_features = hw_enc_features;
-
- /* Enable VLAN features if supported */
- if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
- hw_features |= (NETIF_F_HW_VLAN_CTAG_TX |
- NETIF_F_HW_VLAN_CTAG_RX);
- /* Enable cloud filter if ADQ is supported */
- if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ)
- hw_features |= NETIF_F_HW_TC;
-
- netdev->hw_features |= hw_features;
-
- netdev->features |= hw_features;
-
- if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
- netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
-
- netdev->priv_flags |= IFF_UNICAST_FLT;
-
- /* Do not turn on offloads when they are requested to be turned off.
- * TSO needs minimum 576 bytes to work correctly.
- */
- if (netdev->wanted_features) {
- if (!(netdev->wanted_features & NETIF_F_TSO) ||
- netdev->mtu < 576)
- netdev->features &= ~NETIF_F_TSO;
- if (!(netdev->wanted_features & NETIF_F_TSO6) ||
- netdev->mtu < 576)
- netdev->features &= ~NETIF_F_TSO6;
- if (!(netdev->wanted_features & NETIF_F_TSO_ECN))
- netdev->features &= ~NETIF_F_TSO_ECN;
- if (!(netdev->wanted_features & NETIF_F_GRO))
- netdev->features &= ~NETIF_F_GRO;
- if (!(netdev->wanted_features & NETIF_F_GSO))
- netdev->features &= ~NETIF_F_GSO;
- }
-
- adapter->vsi.id = adapter->vsi_res->vsi_id;
-
- adapter->vsi.back = adapter;
- adapter->vsi.base_vector = 1;
- adapter->vsi.work_limit = I40E_DEFAULT_IRQ_WORK;
- vsi->netdev = adapter->netdev;
- vsi->qs_handle = adapter->vsi_res->qset_handle;
- if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
- adapter->rss_key_size = vfres->rss_key_size;
- adapter->rss_lut_size = vfres->rss_lut_size;
- } else {
- adapter->rss_key_size = I40EVF_HKEY_ARRAY_SIZE;
- adapter->rss_lut_size = I40EVF_HLUT_ARRAY_SIZE;
- }
-
- return 0;
-}
-
-/**
- * i40evf_init_task - worker thread to perform delayed initialization
- * @work: pointer to work_struct containing our data
- *
- * This task completes the work that was begun in probe. Due to the nature
- * of VF-PF communications, we may need to wait tens of milliseconds to get
- * responses back from the PF. Rather than busy-wait in probe and bog down the
- * whole system, we'll do it in a task so we can sleep.
- * This task only runs during driver init. Once we've established
- * communications with the PF driver and set up our netdev, the watchdog
- * takes over.
- **/
-static void i40evf_init_task(struct work_struct *work)
-{
- struct i40evf_adapter *adapter = container_of(work,
- struct i40evf_adapter,
- init_task.work);
- struct net_device *netdev = adapter->netdev;
- struct i40e_hw *hw = &adapter->hw;
- struct pci_dev *pdev = adapter->pdev;
- int err, bufsz;
-
- switch (adapter->state) {
- case __I40EVF_STARTUP:
- /* driver loaded, probe complete */
- adapter->flags &= ~I40EVF_FLAG_PF_COMMS_FAILED;
- adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
- err = i40e_set_mac_type(hw);
- if (err) {
- dev_err(&pdev->dev, "Failed to set MAC type (%d)\n",
- err);
- goto err;
- }
- err = i40evf_check_reset_complete(hw);
- if (err) {
- dev_info(&pdev->dev, "Device is still in reset (%d), retrying\n",
- err);
- goto err;
- }
- hw->aq.num_arq_entries = I40EVF_AQ_LEN;
- hw->aq.num_asq_entries = I40EVF_AQ_LEN;
- hw->aq.arq_buf_size = I40EVF_MAX_AQ_BUF_SIZE;
- hw->aq.asq_buf_size = I40EVF_MAX_AQ_BUF_SIZE;
-
- err = i40evf_init_adminq(hw);
- if (err) {
- dev_err(&pdev->dev, "Failed to init Admin Queue (%d)\n",
- err);
- goto err;
- }
- err = i40evf_send_api_ver(adapter);
- if (err) {
- dev_err(&pdev->dev, "Unable to send to PF (%d)\n", err);
- i40evf_shutdown_adminq(hw);
- goto err;
- }
- adapter->state = __I40EVF_INIT_VERSION_CHECK;
- goto restart;
- case __I40EVF_INIT_VERSION_CHECK:
- if (!i40evf_asq_done(hw)) {
- dev_err(&pdev->dev, "Admin queue command never completed\n");
- i40evf_shutdown_adminq(hw);
- adapter->state = __I40EVF_STARTUP;
- goto err;
- }
-
- /* aq msg sent, awaiting reply */
- err = i40evf_verify_api_ver(adapter);
- if (err) {
- if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK)
- err = i40evf_send_api_ver(adapter);
- else
- dev_err(&pdev->dev, "Unsupported PF API version %d.%d, expected %d.%d\n",
- adapter->pf_version.major,
- adapter->pf_version.minor,
- VIRTCHNL_VERSION_MAJOR,
- VIRTCHNL_VERSION_MINOR);
- goto err;
- }
- err = i40evf_send_vf_config_msg(adapter);
- if (err) {
- dev_err(&pdev->dev, "Unable to send config request (%d)\n",
- err);
- goto err;
- }
- adapter->state = __I40EVF_INIT_GET_RESOURCES;
- goto restart;
- case __I40EVF_INIT_GET_RESOURCES:
- /* aq msg sent, awaiting reply */
- if (!adapter->vf_res) {
- bufsz = sizeof(struct virtchnl_vf_resource) +
- (I40E_MAX_VF_VSI *
- sizeof(struct virtchnl_vsi_resource));
- adapter->vf_res = kzalloc(bufsz, GFP_KERNEL);
- if (!adapter->vf_res)
- goto err;
- }
- err = i40evf_get_vf_config(adapter);
- if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) {
- err = i40evf_send_vf_config_msg(adapter);
- goto err;
- } else if (err == I40E_ERR_PARAM) {
- /* We only get ERR_PARAM if the device is in a very bad
- * state or if we've been disabled for previous bad
- * behavior. Either way, we're done now.
- */
- i40evf_shutdown_adminq(hw);
- dev_err(&pdev->dev, "Unable to get VF config due to PF error condition, not retrying\n");
- return;
- }
- if (err) {
- dev_err(&pdev->dev, "Unable to get VF config (%d)\n",
- err);
- goto err_alloc;
- }
- adapter->state = __I40EVF_INIT_SW;
- break;
- default:
- goto err_alloc;
- }
-
- if (i40evf_process_config(adapter))
- goto err_alloc;
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
-
- adapter->flags |= I40EVF_FLAG_RX_CSUM_ENABLED;
-
- netdev->netdev_ops = &i40evf_netdev_ops;
- i40evf_set_ethtool_ops(netdev);
- netdev->watchdog_timeo = 5 * HZ;
-
- /* MTU range: 68 - 9710 */
- netdev->min_mtu = ETH_MIN_MTU;
- netdev->max_mtu = I40E_MAX_RXBUFFER - I40E_PACKET_HDR_PAD;
-
- if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
- dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n",
- adapter->hw.mac.addr);
- eth_hw_addr_random(netdev);
- ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
- } else {
- adapter->flags |= I40EVF_FLAG_ADDR_SET_BY_PF;
- ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
- ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr);
- }
-
- timer_setup(&adapter->watchdog_timer, i40evf_watchdog_timer, 0);
- mod_timer(&adapter->watchdog_timer, jiffies + 1);
-
- adapter->tx_desc_count = I40EVF_DEFAULT_TXD;
- adapter->rx_desc_count = I40EVF_DEFAULT_RXD;
- err = i40evf_init_interrupt_scheme(adapter);
- if (err)
- goto err_sw_init;
- i40evf_map_rings_to_vectors(adapter);
- if (adapter->vf_res->vf_cap_flags &
- VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
- adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE;
-
- err = i40evf_request_misc_irq(adapter);
- if (err)
- goto err_sw_init;
-
- netif_carrier_off(netdev);
- adapter->link_up = false;
-
- if (!adapter->netdev_registered) {
- err = register_netdev(netdev);
- if (err)
- goto err_register;
- }
-
- adapter->netdev_registered = true;
-
- netif_tx_stop_all_queues(netdev);
- if (CLIENT_ALLOWED(adapter)) {
- err = i40evf_lan_add_device(adapter);
- if (err)
- dev_info(&pdev->dev, "Failed to add VF to client API service list: %d\n",
- err);
- }
-
- dev_info(&pdev->dev, "MAC address: %pM\n", adapter->hw.mac.addr);
- if (netdev->features & NETIF_F_GRO)
- dev_info(&pdev->dev, "GRO is enabled\n");
-
- adapter->state = __I40EVF_DOWN;
- set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
- i40evf_misc_irq_enable(adapter);
- wake_up(&adapter->down_waitqueue);
-
- adapter->rss_key = kzalloc(adapter->rss_key_size, GFP_KERNEL);
- adapter->rss_lut = kzalloc(adapter->rss_lut_size, GFP_KERNEL);
- if (!adapter->rss_key || !adapter->rss_lut)
- goto err_mem;
-
- if (RSS_AQ(adapter)) {
- adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS;
- mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
- } else {
- i40evf_init_rss(adapter);
- }
- return;
-restart:
- schedule_delayed_work(&adapter->init_task, msecs_to_jiffies(30));
- return;
-err_mem:
- i40evf_free_rss(adapter);
-err_register:
- i40evf_free_misc_irq(adapter);
-err_sw_init:
- i40evf_reset_interrupt_capability(adapter);
-err_alloc:
- kfree(adapter->vf_res);
- adapter->vf_res = NULL;
-err:
- /* Things went into the weeds, so try again later */
- if (++adapter->aq_wait_count > I40EVF_AQ_MAX_ERR) {
- dev_err(&pdev->dev, "Failed to communicate with PF; waiting before retry\n");
- adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
- i40evf_shutdown_adminq(hw);
- adapter->state = __I40EVF_STARTUP;
- schedule_delayed_work(&adapter->init_task, HZ * 5);
- return;
- }
- schedule_delayed_work(&adapter->init_task, HZ);
-}
-
-/**
- * i40evf_shutdown - Shutdown the device in preparation for a reboot
- * @pdev: pci device structure
- **/
-static void i40evf_shutdown(struct pci_dev *pdev)
-{
- struct net_device *netdev = pci_get_drvdata(pdev);
- struct i40evf_adapter *adapter = netdev_priv(netdev);
-
- netif_device_detach(netdev);
-
- if (netif_running(netdev))
- i40evf_close(netdev);
-
- /* Prevent the watchdog from running. */
- adapter->state = __I40EVF_REMOVE;
- adapter->aq_required = 0;
-
-#ifdef CONFIG_PM
- pci_save_state(pdev);
-
-#endif
- pci_disable_device(pdev);
-}
-
-/**
- * i40evf_probe - Device Initialization Routine
- * @pdev: PCI device information struct
- * @ent: entry in i40evf_pci_tbl
- *
- * Returns 0 on success, negative on failure
- *
- * i40evf_probe initializes an adapter identified by a pci_dev structure.
- * The OS initialization, configuring of the adapter private structure,
- * and a hardware reset occur.
- **/
-static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- struct net_device *netdev;
- struct i40evf_adapter *adapter = NULL;
- struct i40e_hw *hw = NULL;
- int err;
-
- err = pci_enable_device(pdev);
- if (err)
- return err;
-
- err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
- if (err) {
- err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
- if (err) {
- dev_err(&pdev->dev,
- "DMA configuration failed: 0x%x\n", err);
- goto err_dma;
- }
- }
-
- err = pci_request_regions(pdev, i40evf_driver_name);
- if (err) {
- dev_err(&pdev->dev,
- "pci_request_regions failed 0x%x\n", err);
- goto err_pci_reg;
- }
-
- pci_enable_pcie_error_reporting(pdev);
-
- pci_set_master(pdev);
-
- netdev = alloc_etherdev_mq(sizeof(struct i40evf_adapter),
- I40EVF_MAX_REQ_QUEUES);
- if (!netdev) {
- err = -ENOMEM;
- goto err_alloc_etherdev;
- }
-
- SET_NETDEV_DEV(netdev, &pdev->dev);
-
- pci_set_drvdata(pdev, netdev);
- adapter = netdev_priv(netdev);
-
- adapter->netdev = netdev;
- adapter->pdev = pdev;
-
- hw = &adapter->hw;
- hw->back = adapter;
-
- adapter->msg_enable = BIT(DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
- adapter->state = __I40EVF_STARTUP;
-
- /* Call save state here because it relies on the adapter struct. */
- pci_save_state(pdev);
-
- hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (!hw->hw_addr) {
- err = -EIO;
- goto err_ioremap;
- }
- hw->vendor_id = pdev->vendor;
- hw->device_id = pdev->device;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
- hw->subsystem_vendor_id = pdev->subsystem_vendor;
- hw->subsystem_device_id = pdev->subsystem_device;
- hw->bus.device = PCI_SLOT(pdev->devfn);
- hw->bus.func = PCI_FUNC(pdev->devfn);
- hw->bus.bus_id = pdev->bus->number;
-
- /* set up the locks for the AQ, do this only once in probe
- * and destroy them only once in remove
- */
- mutex_init(&hw->aq.asq_mutex);
- mutex_init(&hw->aq.arq_mutex);
-
- spin_lock_init(&adapter->mac_vlan_list_lock);
- spin_lock_init(&adapter->cloud_filter_list_lock);
-
- INIT_LIST_HEAD(&adapter->mac_filter_list);
- INIT_LIST_HEAD(&adapter->vlan_filter_list);
- INIT_LIST_HEAD(&adapter->cloud_filter_list);
-
- INIT_WORK(&adapter->reset_task, i40evf_reset_task);
- INIT_WORK(&adapter->adminq_task, i40evf_adminq_task);
- INIT_WORK(&adapter->watchdog_task, i40evf_watchdog_task);
- INIT_DELAYED_WORK(&adapter->client_task, i40evf_client_task);
- INIT_DELAYED_WORK(&adapter->init_task, i40evf_init_task);
- schedule_delayed_work(&adapter->init_task,
- msecs_to_jiffies(5 * (pdev->devfn & 0x07)));
-
- /* Setup the wait queue for indicating transition to down status */
- init_waitqueue_head(&adapter->down_waitqueue);
-
- return 0;
-
-err_ioremap:
- free_netdev(netdev);
-err_alloc_etherdev:
- pci_disable_pcie_error_reporting(pdev);
- pci_release_regions(pdev);
-err_pci_reg:
-err_dma:
- pci_disable_device(pdev);
- return err;
-}
-
-#ifdef CONFIG_PM
-/**
- * i40evf_suspend - Power management suspend routine
- * @pdev: PCI device information struct
- * @state: unused
- *
- * Called when the system (VM) is entering sleep/suspend.
- **/
-static int i40evf_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *netdev = pci_get_drvdata(pdev);
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- int retval = 0;
-
- netif_device_detach(netdev);
-
- while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
- &adapter->crit_section))
- usleep_range(500, 1000);
-
- if (netif_running(netdev)) {
- rtnl_lock();
- i40evf_down(adapter);
- rtnl_unlock();
- }
- i40evf_free_misc_irq(adapter);
- i40evf_reset_interrupt_capability(adapter);
-
- clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
-
- retval = pci_save_state(pdev);
- if (retval)
- return retval;
-
- pci_disable_device(pdev);
-
- return 0;
-}
-
-/**
- * i40evf_resume - Power management resume routine
- * @pdev: PCI device information struct
- *
- * Called when the system (VM) is resumed from sleep/suspend.
- **/
-static int i40evf_resume(struct pci_dev *pdev)
-{
- struct i40evf_adapter *adapter = pci_get_drvdata(pdev);
- struct net_device *netdev = adapter->netdev;
- u32 err;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- /* pci_restore_state clears dev->state_saved so call
- * pci_save_state to restore it.
- */
- pci_save_state(pdev);
-
- err = pci_enable_device_mem(pdev);
- if (err) {
- dev_err(&pdev->dev, "Cannot enable PCI device from suspend.\n");
- return err;
- }
- pci_set_master(pdev);
-
- rtnl_lock();
- err = i40evf_set_interrupt_capability(adapter);
- if (err) {
- rtnl_unlock();
- dev_err(&pdev->dev, "Cannot enable MSI-X interrupts.\n");
- return err;
- }
- err = i40evf_request_misc_irq(adapter);
- rtnl_unlock();
- if (err) {
- dev_err(&pdev->dev, "Cannot get interrupt vector.\n");
- return err;
- }
-
- schedule_work(&adapter->reset_task);
-
- netif_device_attach(netdev);
-
- return err;
-}
-
-#endif /* CONFIG_PM */
-/**
- * i40evf_remove - Device Removal Routine
- * @pdev: PCI device information struct
- *
- * i40evf_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device. The could be caused by a
- * Hot-Plug event, or because the driver is going to be removed from
- * memory.
- **/
-static void i40evf_remove(struct pci_dev *pdev)
-{
- struct net_device *netdev = pci_get_drvdata(pdev);
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- struct i40evf_vlan_filter *vlf, *vlftmp;
- struct i40evf_mac_filter *f, *ftmp;
- struct i40evf_cloud_filter *cf, *cftmp;
- struct i40e_hw *hw = &adapter->hw;
- int err;
- /* Indicate we are in remove and not to run reset_task */
- set_bit(__I40EVF_IN_REMOVE_TASK, &adapter->crit_section);
- cancel_delayed_work_sync(&adapter->init_task);
- cancel_work_sync(&adapter->reset_task);
- cancel_delayed_work_sync(&adapter->client_task);
- if (adapter->netdev_registered) {
- unregister_netdev(netdev);
- adapter->netdev_registered = false;
- }
- if (CLIENT_ALLOWED(adapter)) {
- err = i40evf_lan_del_device(adapter);
- if (err)
- dev_warn(&pdev->dev, "Failed to delete client device: %d\n",
- err);
- }
-
- /* Shut down all the garbage mashers on the detention level */
- adapter->state = __I40EVF_REMOVE;
- adapter->aq_required = 0;
- adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
- i40evf_request_reset(adapter);
- msleep(50);
- /* If the FW isn't responding, kick it once, but only once. */
- if (!i40evf_asq_done(hw)) {
- i40evf_request_reset(adapter);
- msleep(50);
- }
- i40evf_free_all_tx_resources(adapter);
- i40evf_free_all_rx_resources(adapter);
- i40evf_misc_irq_disable(adapter);
- i40evf_free_misc_irq(adapter);
- i40evf_reset_interrupt_capability(adapter);
- i40evf_free_q_vectors(adapter);
-
- if (adapter->watchdog_timer.function)
- del_timer_sync(&adapter->watchdog_timer);
-
- cancel_work_sync(&adapter->adminq_task);
-
- i40evf_free_rss(adapter);
-
- if (hw->aq.asq.count)
- i40evf_shutdown_adminq(hw);
-
- /* destroy the locks only once, here */
- mutex_destroy(&hw->aq.arq_mutex);
- mutex_destroy(&hw->aq.asq_mutex);
-
- iounmap(hw->hw_addr);
- pci_release_regions(pdev);
- i40evf_free_all_tx_resources(adapter);
- i40evf_free_all_rx_resources(adapter);
- i40evf_free_queues(adapter);
- kfree(adapter->vf_res);
- spin_lock_bh(&adapter->mac_vlan_list_lock);
- /* If we got removed before an up/down sequence, we've got a filter
- * hanging out there that we need to get rid of.
- */
- list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
- list_del(&f->list);
- kfree(f);
- }
- list_for_each_entry_safe(vlf, vlftmp, &adapter->vlan_filter_list,
- list) {
- list_del(&vlf->list);
- kfree(vlf);
- }
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- spin_lock_bh(&adapter->cloud_filter_list_lock);
- list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {
- list_del(&cf->list);
- kfree(cf);
- }
- spin_unlock_bh(&adapter->cloud_filter_list_lock);
-
- free_netdev(netdev);
-
- pci_disable_pcie_error_reporting(pdev);
-
- pci_disable_device(pdev);
-}
-
-static struct pci_driver i40evf_driver = {
- .name = i40evf_driver_name,
- .id_table = i40evf_pci_tbl,
- .probe = i40evf_probe,
- .remove = i40evf_remove,
-#ifdef CONFIG_PM
- .suspend = i40evf_suspend,
- .resume = i40evf_resume,
-#endif
- .shutdown = i40evf_shutdown,
-};
-
-/**
- * i40e_init_module - Driver Registration Routine
- *
- * i40e_init_module is the first routine called when the driver is
- * loaded. All it does is register with the PCI subsystem.
- **/
-static int __init i40evf_init_module(void)
-{
- int ret;
-
- pr_info("i40evf: %s - version %s\n", i40evf_driver_string,
- i40evf_driver_version);
-
- pr_info("%s\n", i40evf_copyright);
-
- i40evf_wq = alloc_workqueue("%s", WQ_UNBOUND | WQ_MEM_RECLAIM, 1,
- i40evf_driver_name);
- if (!i40evf_wq) {
- pr_err("%s: Failed to create workqueue\n", i40evf_driver_name);
- return -ENOMEM;
- }
- ret = pci_register_driver(&i40evf_driver);
- return ret;
-}
-
-module_init(i40evf_init_module);
-
-/**
- * i40e_exit_module - Driver Exit Cleanup Routine
- *
- * i40e_exit_module is called just before the driver is removed
- * from memory.
- **/
-static void __exit i40evf_exit_module(void)
-{
- pci_unregister_driver(&i40evf_driver);
- destroy_workqueue(i40evf_wq);
-}
-
-module_exit(i40evf_exit_module);
-
-/* i40evf_main.c */
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
deleted file mode 100644
index 94dabc9d89f7..000000000000
--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
+++ /dev/null
@@ -1,1458 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2013 - 2018 Intel Corporation. */
-
-#include "i40evf.h"
-#include "i40e_prototype.h"
-#include "i40evf_client.h"
-
-/* busy wait delay in msec */
-#define I40EVF_BUSY_WAIT_DELAY 10
-#define I40EVF_BUSY_WAIT_COUNT 50
-
-/**
- * i40evf_send_pf_msg
- * @adapter: adapter structure
- * @op: virtual channel opcode
- * @msg: pointer to message buffer
- * @len: message length
- *
- * Send message to PF and print status if failure.
- **/
-static int i40evf_send_pf_msg(struct i40evf_adapter *adapter,
- enum virtchnl_ops op, u8 *msg, u16 len)
-{
- struct i40e_hw *hw = &adapter->hw;
- i40e_status err;
-
- if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED)
- return 0; /* nothing to see here, move along */
-
- err = i40e_aq_send_msg_to_pf(hw, op, 0, msg, len, NULL);
- if (err)
- dev_dbg(&adapter->pdev->dev, "Unable to send opcode %d to PF, err %s, aq_err %s\n",
- op, i40evf_stat_str(hw, err),
- i40evf_aq_str(hw, hw->aq.asq_last_status));
- return err;
-}
-
-/**
- * i40evf_send_api_ver
- * @adapter: adapter structure
- *
- * Send API version admin queue message to the PF. The reply is not checked
- * in this function. Returns 0 if the message was successfully
- * sent, or one of the I40E_ADMIN_QUEUE_ERROR_ statuses if not.
- **/
-int i40evf_send_api_ver(struct i40evf_adapter *adapter)
-{
- struct virtchnl_version_info vvi;
-
- vvi.major = VIRTCHNL_VERSION_MAJOR;
- vvi.minor = VIRTCHNL_VERSION_MINOR;
-
- return i40evf_send_pf_msg(adapter, VIRTCHNL_OP_VERSION, (u8 *)&vvi,
- sizeof(vvi));
-}
-
-/**
- * i40evf_verify_api_ver
- * @adapter: adapter structure
- *
- * Compare API versions with the PF. Must be called after admin queue is
- * initialized. Returns 0 if API versions match, -EIO if they do not,
- * I40E_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty, and any errors
- * from the firmware are propagated.
- **/
-int i40evf_verify_api_ver(struct i40evf_adapter *adapter)
-{
- struct virtchnl_version_info *pf_vvi;
- struct i40e_hw *hw = &adapter->hw;
- struct i40e_arq_event_info event;
- enum virtchnl_ops op;
- i40e_status err;
-
- event.buf_len = I40EVF_MAX_AQ_BUF_SIZE;
- event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
- if (!event.msg_buf) {
- err = -ENOMEM;
- goto out;
- }
-
- while (1) {
- err = i40evf_clean_arq_element(hw, &event, NULL);
- /* When the AQ is empty, i40evf_clean_arq_element will return
- * nonzero and this loop will terminate.
- */
- if (err)
- goto out_alloc;
- op =
- (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
- if (op == VIRTCHNL_OP_VERSION)
- break;
- }
-
-
- err = (i40e_status)le32_to_cpu(event.desc.cookie_low);
- if (err)
- goto out_alloc;
-
- if (op != VIRTCHNL_OP_VERSION) {
- dev_info(&adapter->pdev->dev, "Invalid reply type %d from PF\n",
- op);
- err = -EIO;
- goto out_alloc;
- }
-
- pf_vvi = (struct virtchnl_version_info *)event.msg_buf;
- adapter->pf_version = *pf_vvi;
-
- if ((pf_vvi->major > VIRTCHNL_VERSION_MAJOR) ||
- ((pf_vvi->major == VIRTCHNL_VERSION_MAJOR) &&
- (pf_vvi->minor > VIRTCHNL_VERSION_MINOR)))
- err = -EIO;
-
-out_alloc:
- kfree(event.msg_buf);
-out:
- return err;
-}
-
-/**
- * i40evf_send_vf_config_msg
- * @adapter: adapter structure
- *
- * Send VF configuration request admin queue message to the PF. The reply
- * is not checked in this function. Returns 0 if the message was
- * successfully sent, or one of the I40E_ADMIN_QUEUE_ERROR_ statuses if not.
- **/
-int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
-{
- u32 caps;
-
- caps = VIRTCHNL_VF_OFFLOAD_L2 |
- VIRTCHNL_VF_OFFLOAD_RSS_PF |
- VIRTCHNL_VF_OFFLOAD_RSS_AQ |
- VIRTCHNL_VF_OFFLOAD_RSS_REG |
- VIRTCHNL_VF_OFFLOAD_VLAN |
- VIRTCHNL_VF_OFFLOAD_WB_ON_ITR |
- VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 |
- VIRTCHNL_VF_OFFLOAD_ENCAP |
- VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
- VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
- VIRTCHNL_VF_OFFLOAD_ADQ;
-
- adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG;
- if (PF_IS_V11(adapter))
- return i40evf_send_pf_msg(adapter,
- VIRTCHNL_OP_GET_VF_RESOURCES,
- (u8 *)&caps, sizeof(caps));
- else
- return i40evf_send_pf_msg(adapter,
- VIRTCHNL_OP_GET_VF_RESOURCES,
- NULL, 0);
-}
-
-/**
- * i40evf_validate_num_queues
- * @adapter: adapter structure
- *
- * Validate that the number of queues the PF has sent in
- * VIRTCHNL_OP_GET_VF_RESOURCES is not larger than the VF can handle.
- **/
-static void i40evf_validate_num_queues(struct i40evf_adapter *adapter)
-{
- if (adapter->vf_res->num_queue_pairs > I40EVF_MAX_REQ_QUEUES) {
- struct virtchnl_vsi_resource *vsi_res;
- int i;
-
- dev_info(&adapter->pdev->dev, "Received %d queues, but can only have a max of %d\n",
- adapter->vf_res->num_queue_pairs,
- I40EVF_MAX_REQ_QUEUES);
- dev_info(&adapter->pdev->dev, "Fixing by reducing queues to %d\n",
- I40EVF_MAX_REQ_QUEUES);
- adapter->vf_res->num_queue_pairs = I40EVF_MAX_REQ_QUEUES;
- for (i = 0; i < adapter->vf_res->num_vsis; i++) {
- vsi_res = &adapter->vf_res->vsi_res[i];
- vsi_res->num_queue_pairs = I40EVF_MAX_REQ_QUEUES;
- }
- }
-}
-
-/**
- * i40evf_get_vf_config
- * @adapter: private adapter structure
- *
- * Get VF configuration from PF and populate hw structure. Must be called after
- * admin queue is initialized. Busy waits until response is received from PF,
- * with maximum timeout. Response from PF is returned in the buffer for further
- * processing by the caller.
- **/
-int i40evf_get_vf_config(struct i40evf_adapter *adapter)
-{
- struct i40e_hw *hw = &adapter->hw;
- struct i40e_arq_event_info event;
- enum virtchnl_ops op;
- i40e_status err;
- u16 len;
-
- len = sizeof(struct virtchnl_vf_resource) +
- I40E_MAX_VF_VSI * sizeof(struct virtchnl_vsi_resource);
- event.buf_len = len;
- event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
- if (!event.msg_buf) {
- err = -ENOMEM;
- goto out;
- }
-
- while (1) {
- /* When the AQ is empty, i40evf_clean_arq_element will return
- * nonzero and this loop will terminate.
- */
- err = i40evf_clean_arq_element(hw, &event, NULL);
- if (err)
- goto out_alloc;
- op =
- (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
- if (op == VIRTCHNL_OP_GET_VF_RESOURCES)
- break;
- }
-
- err = (i40e_status)le32_to_cpu(event.desc.cookie_low);
- memcpy(adapter->vf_res, event.msg_buf, min(event.msg_len, len));
-
- /* some PFs send more queues than we should have so validate that
- * we aren't getting too many queues
- */
- if (!err)
- i40evf_validate_num_queues(adapter);
- i40e_vf_parse_hw_config(hw, adapter->vf_res);
-out_alloc:
- kfree(event.msg_buf);
-out:
- return err;
-}
-
-/**
- * i40evf_configure_queues
- * @adapter: adapter structure
- *
- * Request that the PF set up our (previously allocated) queues.
- **/
-void i40evf_configure_queues(struct i40evf_adapter *adapter)
-{
- struct virtchnl_vsi_queue_config_info *vqci;
- struct virtchnl_queue_pair_info *vqpi;
- int pairs = adapter->num_active_queues;
- int i, len, max_frame = I40E_MAX_RXBUFFER;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot configure queues, command %d pending\n",
- adapter->current_op);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_CONFIG_VSI_QUEUES;
- len = sizeof(struct virtchnl_vsi_queue_config_info) +
- (sizeof(struct virtchnl_queue_pair_info) * pairs);
- vqci = kzalloc(len, GFP_KERNEL);
- if (!vqci)
- return;
-
- /* Limit maximum frame size when jumbo frames is not enabled */
- if (!(adapter->flags & I40EVF_FLAG_LEGACY_RX) &&
- (adapter->netdev->mtu <= ETH_DATA_LEN))
- max_frame = I40E_RXBUFFER_1536 - NET_IP_ALIGN;
-
- vqci->vsi_id = adapter->vsi_res->vsi_id;
- vqci->num_queue_pairs = pairs;
- vqpi = vqci->qpair;
- /* Size check is not needed here - HW max is 16 queue pairs, and we
- * can fit info for 31 of them into the AQ buffer before it overflows.
- */
- for (i = 0; i < pairs; i++) {
- vqpi->txq.vsi_id = vqci->vsi_id;
- vqpi->txq.queue_id = i;
- vqpi->txq.ring_len = adapter->tx_rings[i].count;
- vqpi->txq.dma_ring_addr = adapter->tx_rings[i].dma;
- vqpi->rxq.vsi_id = vqci->vsi_id;
- vqpi->rxq.queue_id = i;
- vqpi->rxq.ring_len = adapter->rx_rings[i].count;
- vqpi->rxq.dma_ring_addr = adapter->rx_rings[i].dma;
- vqpi->rxq.max_pkt_size = max_frame;
- vqpi->rxq.databuffer_size =
- ALIGN(adapter->rx_rings[i].rx_buf_len,
- BIT_ULL(I40E_RXQ_CTX_DBUFF_SHIFT));
- vqpi++;
- }
-
- adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
- (u8 *)vqci, len);
- kfree(vqci);
-}
-
-/**
- * i40evf_enable_queues
- * @adapter: adapter structure
- *
- * Request that the PF enable all of our queues.
- **/
-void i40evf_enable_queues(struct i40evf_adapter *adapter)
-{
- struct virtchnl_queue_select vqs;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot enable queues, command %d pending\n",
- adapter->current_op);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_ENABLE_QUEUES;
- vqs.vsi_id = adapter->vsi_res->vsi_id;
- vqs.tx_queues = BIT(adapter->num_active_queues) - 1;
- vqs.rx_queues = vqs.tx_queues;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_QUEUES;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_QUEUES,
- (u8 *)&vqs, sizeof(vqs));
-}
-
-/**
- * i40evf_disable_queues
- * @adapter: adapter structure
- *
- * Request that the PF disable all of our queues.
- **/
-void i40evf_disable_queues(struct i40evf_adapter *adapter)
-{
- struct virtchnl_queue_select vqs;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot disable queues, command %d pending\n",
- adapter->current_op);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_DISABLE_QUEUES;
- vqs.vsi_id = adapter->vsi_res->vsi_id;
- vqs.tx_queues = BIT(adapter->num_active_queues) - 1;
- vqs.rx_queues = vqs.tx_queues;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_QUEUES;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_QUEUES,
- (u8 *)&vqs, sizeof(vqs));
-}
-
-/**
- * i40evf_map_queues
- * @adapter: adapter structure
- *
- * Request that the PF map queues to interrupt vectors. Misc causes, including
- * admin queue, are always mapped to vector 0.
- **/
-void i40evf_map_queues(struct i40evf_adapter *adapter)
-{
- struct virtchnl_irq_map_info *vimi;
- struct virtchnl_vector_map *vecmap;
- int v_idx, q_vectors, len;
- struct i40e_q_vector *q_vector;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot map queues to vectors, command %d pending\n",
- adapter->current_op);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_CONFIG_IRQ_MAP;
-
- q_vectors = adapter->num_msix_vectors - NONQ_VECS;
-
- len = sizeof(struct virtchnl_irq_map_info) +
- (adapter->num_msix_vectors *
- sizeof(struct virtchnl_vector_map));
- vimi = kzalloc(len, GFP_KERNEL);
- if (!vimi)
- return;
-
- vimi->num_vectors = adapter->num_msix_vectors;
- /* Queue vectors first */
- for (v_idx = 0; v_idx < q_vectors; v_idx++) {
- q_vector = &adapter->q_vectors[v_idx];
- vecmap = &vimi->vecmap[v_idx];
-
- vecmap->vsi_id = adapter->vsi_res->vsi_id;
- vecmap->vector_id = v_idx + NONQ_VECS;
- vecmap->txq_map = q_vector->ring_mask;
- vecmap->rxq_map = q_vector->ring_mask;
- vecmap->rxitr_idx = I40E_RX_ITR;
- vecmap->txitr_idx = I40E_TX_ITR;
- }
- /* Misc vector last - this is only for AdminQ messages */
- vecmap = &vimi->vecmap[v_idx];
- vecmap->vsi_id = adapter->vsi_res->vsi_id;
- vecmap->vector_id = 0;
- vecmap->txq_map = 0;
- vecmap->rxq_map = 0;
-
- adapter->aq_required &= ~I40EVF_FLAG_AQ_MAP_VECTORS;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_IRQ_MAP,
- (u8 *)vimi, len);
- kfree(vimi);
-}
-
-/**
- * i40evf_request_queues
- * @adapter: adapter structure
- * @num: number of requested queues
- *
- * We get a default number of queues from the PF. This enables us to request a
- * different number. Returns 0 on success, negative on failure
- **/
-int i40evf_request_queues(struct i40evf_adapter *adapter, int num)
-{
- struct virtchnl_vf_res_request vfres;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot request queues, command %d pending\n",
- adapter->current_op);
- return -EBUSY;
- }
-
- vfres.num_queue_pairs = num;
-
- adapter->current_op = VIRTCHNL_OP_REQUEST_QUEUES;
- adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
- return i40evf_send_pf_msg(adapter, VIRTCHNL_OP_REQUEST_QUEUES,
- (u8 *)&vfres, sizeof(vfres));
-}
-
-/**
- * i40evf_add_ether_addrs
- * @adapter: adapter structure
- *
- * Request that the PF add one or more addresses to our filters.
- **/
-void i40evf_add_ether_addrs(struct i40evf_adapter *adapter)
-{
- struct virtchnl_ether_addr_list *veal;
- int len, i = 0, count = 0;
- struct i40evf_mac_filter *f;
- bool more = false;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot add filters, command %d pending\n",
- adapter->current_op);
- return;
- }
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- list_for_each_entry(f, &adapter->mac_filter_list, list) {
- if (f->add)
- count++;
- }
- if (!count) {
- adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_ADD_ETH_ADDR;
-
- len = sizeof(struct virtchnl_ether_addr_list) +
- (count * sizeof(struct virtchnl_ether_addr));
- if (len > I40EVF_MAX_AQ_BUF_SIZE) {
- dev_warn(&adapter->pdev->dev, "Too many add MAC changes in one request\n");
- count = (I40EVF_MAX_AQ_BUF_SIZE -
- sizeof(struct virtchnl_ether_addr_list)) /
- sizeof(struct virtchnl_ether_addr);
- len = sizeof(struct virtchnl_ether_addr_list) +
- (count * sizeof(struct virtchnl_ether_addr));
- more = true;
- }
-
- veal = kzalloc(len, GFP_ATOMIC);
- if (!veal) {
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
- }
-
- veal->vsi_id = adapter->vsi_res->vsi_id;
- veal->num_elements = count;
- list_for_each_entry(f, &adapter->mac_filter_list, list) {
- if (f->add) {
- ether_addr_copy(veal->list[i].addr, f->macaddr);
- i++;
- f->add = false;
- if (i == count)
- break;
- }
- }
- if (!more)
- adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR,
- (u8 *)veal, len);
- kfree(veal);
-}
-
-/**
- * i40evf_del_ether_addrs
- * @adapter: adapter structure
- *
- * Request that the PF remove one or more addresses from our filters.
- **/
-void i40evf_del_ether_addrs(struct i40evf_adapter *adapter)
-{
- struct virtchnl_ether_addr_list *veal;
- struct i40evf_mac_filter *f, *ftmp;
- int len, i = 0, count = 0;
- bool more = false;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot remove filters, command %d pending\n",
- adapter->current_op);
- return;
- }
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- list_for_each_entry(f, &adapter->mac_filter_list, list) {
- if (f->remove)
- count++;
- }
- if (!count) {
- adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_DEL_ETH_ADDR;
-
- len = sizeof(struct virtchnl_ether_addr_list) +
- (count * sizeof(struct virtchnl_ether_addr));
- if (len > I40EVF_MAX_AQ_BUF_SIZE) {
- dev_warn(&adapter->pdev->dev, "Too many delete MAC changes in one request\n");
- count = (I40EVF_MAX_AQ_BUF_SIZE -
- sizeof(struct virtchnl_ether_addr_list)) /
- sizeof(struct virtchnl_ether_addr);
- len = sizeof(struct virtchnl_ether_addr_list) +
- (count * sizeof(struct virtchnl_ether_addr));
- more = true;
- }
- veal = kzalloc(len, GFP_ATOMIC);
- if (!veal) {
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
- }
-
- veal->vsi_id = adapter->vsi_res->vsi_id;
- veal->num_elements = count;
- list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
- if (f->remove) {
- ether_addr_copy(veal->list[i].addr, f->macaddr);
- i++;
- list_del(&f->list);
- kfree(f);
- if (i == count)
- break;
- }
- }
- if (!more)
- adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_ETH_ADDR,
- (u8 *)veal, len);
- kfree(veal);
-}
-
-/**
- * i40evf_add_vlans
- * @adapter: adapter structure
- *
- * Request that the PF add one or more VLAN filters to our VSI.
- **/
-void i40evf_add_vlans(struct i40evf_adapter *adapter)
-{
- struct virtchnl_vlan_filter_list *vvfl;
- int len, i = 0, count = 0;
- struct i40evf_vlan_filter *f;
- bool more = false;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot add VLANs, command %d pending\n",
- adapter->current_op);
- return;
- }
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- list_for_each_entry(f, &adapter->vlan_filter_list, list) {
- if (f->add)
- count++;
- }
- if (!count) {
- adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_ADD_VLAN;
-
- len = sizeof(struct virtchnl_vlan_filter_list) +
- (count * sizeof(u16));
- if (len > I40EVF_MAX_AQ_BUF_SIZE) {
- dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
- count = (I40EVF_MAX_AQ_BUF_SIZE -
- sizeof(struct virtchnl_vlan_filter_list)) /
- sizeof(u16);
- len = sizeof(struct virtchnl_vlan_filter_list) +
- (count * sizeof(u16));
- more = true;
- }
- vvfl = kzalloc(len, GFP_ATOMIC);
- if (!vvfl) {
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
- }
-
- vvfl->vsi_id = adapter->vsi_res->vsi_id;
- vvfl->num_elements = count;
- list_for_each_entry(f, &adapter->vlan_filter_list, list) {
- if (f->add) {
- vvfl->vlan_id[i] = f->vlan;
- i++;
- f->add = false;
- if (i == count)
- break;
- }
- }
- if (!more)
- adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
- kfree(vvfl);
-}
-
-/**
- * i40evf_del_vlans
- * @adapter: adapter structure
- *
- * Request that the PF remove one or more VLAN filters from our VSI.
- **/
-void i40evf_del_vlans(struct i40evf_adapter *adapter)
-{
- struct virtchnl_vlan_filter_list *vvfl;
- struct i40evf_vlan_filter *f, *ftmp;
- int len, i = 0, count = 0;
- bool more = false;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot remove VLANs, command %d pending\n",
- adapter->current_op);
- return;
- }
-
- spin_lock_bh(&adapter->mac_vlan_list_lock);
-
- list_for_each_entry(f, &adapter->vlan_filter_list, list) {
- if (f->remove)
- count++;
- }
- if (!count) {
- adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_DEL_VLAN;
-
- len = sizeof(struct virtchnl_vlan_filter_list) +
- (count * sizeof(u16));
- if (len > I40EVF_MAX_AQ_BUF_SIZE) {
- dev_warn(&adapter->pdev->dev, "Too many delete VLAN changes in one request\n");
- count = (I40EVF_MAX_AQ_BUF_SIZE -
- sizeof(struct virtchnl_vlan_filter_list)) /
- sizeof(u16);
- len = sizeof(struct virtchnl_vlan_filter_list) +
- (count * sizeof(u16));
- more = true;
- }
- vvfl = kzalloc(len, GFP_ATOMIC);
- if (!vvfl) {
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
- return;
- }
-
- vvfl->vsi_id = adapter->vsi_res->vsi_id;
- vvfl->num_elements = count;
- list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
- if (f->remove) {
- vvfl->vlan_id[i] = f->vlan;
- i++;
- list_del(&f->list);
- kfree(f);
- if (i == count)
- break;
- }
- }
- if (!more)
- adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
-
- spin_unlock_bh(&adapter->mac_vlan_list_lock);
-
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
- kfree(vvfl);
-}
-
-/**
- * i40evf_set_promiscuous
- * @adapter: adapter structure
- * @flags: bitmask to control unicast/multicast promiscuous.
- *
- * Request that the PF enable promiscuous mode for our VSI.
- **/
-void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags)
-{
- struct virtchnl_promisc_info vpi;
- int promisc_all;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot set promiscuous mode, command %d pending\n",
- adapter->current_op);
- return;
- }
-
- promisc_all = FLAG_VF_UNICAST_PROMISC |
- FLAG_VF_MULTICAST_PROMISC;
- if ((flags & promisc_all) == promisc_all) {
- adapter->flags |= I40EVF_FLAG_PROMISC_ON;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_REQUEST_PROMISC;
- dev_info(&adapter->pdev->dev, "Entering promiscuous mode\n");
- }
-
- if (flags & FLAG_VF_MULTICAST_PROMISC) {
- adapter->flags |= I40EVF_FLAG_ALLMULTI_ON;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_REQUEST_ALLMULTI;
- dev_info(&adapter->pdev->dev, "Entering multicast promiscuous mode\n");
- }
-
- if (!flags) {
- adapter->flags &= ~(I40EVF_FLAG_PROMISC_ON |
- I40EVF_FLAG_ALLMULTI_ON);
- adapter->aq_required &= ~(I40EVF_FLAG_AQ_RELEASE_PROMISC |
- I40EVF_FLAG_AQ_RELEASE_ALLMULTI);
- dev_info(&adapter->pdev->dev, "Leaving promiscuous mode\n");
- }
-
- adapter->current_op = VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE;
- vpi.vsi_id = adapter->vsi_res->vsi_id;
- vpi.flags = flags;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
- (u8 *)&vpi, sizeof(vpi));
-}
-
-/**
- * i40evf_request_stats
- * @adapter: adapter structure
- *
- * Request VSI statistics from PF.
- **/
-void i40evf_request_stats(struct i40evf_adapter *adapter)
-{
- struct virtchnl_queue_select vqs;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* no error message, this isn't crucial */
- return;
- }
- adapter->current_op = VIRTCHNL_OP_GET_STATS;
- vqs.vsi_id = adapter->vsi_res->vsi_id;
- /* queue maps are ignored for this message - only the vsi is used */
- if (i40evf_send_pf_msg(adapter, VIRTCHNL_OP_GET_STATS,
- (u8 *)&vqs, sizeof(vqs)))
- /* if the request failed, don't lock out others */
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
-}
-
-/**
- * i40evf_get_hena
- * @adapter: adapter structure
- *
- * Request hash enable capabilities from PF
- **/
-void i40evf_get_hena(struct i40evf_adapter *adapter)
-{
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot get RSS hash capabilities, command %d pending\n",
- adapter->current_op);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_GET_RSS_HENA_CAPS;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_HENA;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_GET_RSS_HENA_CAPS,
- NULL, 0);
-}
-
-/**
- * i40evf_set_hena
- * @adapter: adapter structure
- *
- * Request the PF to set our RSS hash capabilities
- **/
-void i40evf_set_hena(struct i40evf_adapter *adapter)
-{
- struct virtchnl_rss_hena vrh;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot set RSS hash enable, command %d pending\n",
- adapter->current_op);
- return;
- }
- vrh.hena = adapter->hena;
- adapter->current_op = VIRTCHNL_OP_SET_RSS_HENA;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_HENA;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_SET_RSS_HENA,
- (u8 *)&vrh, sizeof(vrh));
-}
-
-/**
- * i40evf_set_rss_key
- * @adapter: adapter structure
- *
- * Request the PF to set our RSS hash key
- **/
-void i40evf_set_rss_key(struct i40evf_adapter *adapter)
-{
- struct virtchnl_rss_key *vrk;
- int len;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot set RSS key, command %d pending\n",
- adapter->current_op);
- return;
- }
- len = sizeof(struct virtchnl_rss_key) +
- (adapter->rss_key_size * sizeof(u8)) - 1;
- vrk = kzalloc(len, GFP_KERNEL);
- if (!vrk)
- return;
- vrk->vsi_id = adapter->vsi.id;
- vrk->key_len = adapter->rss_key_size;
- memcpy(vrk->key, adapter->rss_key, adapter->rss_key_size);
-
- adapter->current_op = VIRTCHNL_OP_CONFIG_RSS_KEY;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_RSS_KEY;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_RSS_KEY,
- (u8 *)vrk, len);
- kfree(vrk);
-}
-
-/**
- * i40evf_set_rss_lut
- * @adapter: adapter structure
- *
- * Request the PF to set our RSS lookup table
- **/
-void i40evf_set_rss_lut(struct i40evf_adapter *adapter)
-{
- struct virtchnl_rss_lut *vrl;
- int len;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot set RSS LUT, command %d pending\n",
- adapter->current_op);
- return;
- }
- len = sizeof(struct virtchnl_rss_lut) +
- (adapter->rss_lut_size * sizeof(u8)) - 1;
- vrl = kzalloc(len, GFP_KERNEL);
- if (!vrl)
- return;
- vrl->vsi_id = adapter->vsi.id;
- vrl->lut_entries = adapter->rss_lut_size;
- memcpy(vrl->lut, adapter->rss_lut, adapter->rss_lut_size);
- adapter->current_op = VIRTCHNL_OP_CONFIG_RSS_LUT;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_RSS_LUT;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_RSS_LUT,
- (u8 *)vrl, len);
- kfree(vrl);
-}
-
-/**
- * i40evf_enable_vlan_stripping
- * @adapter: adapter structure
- *
- * Request VLAN header stripping to be enabled
- **/
-void i40evf_enable_vlan_stripping(struct i40evf_adapter *adapter)
-{
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot enable stripping, command %d pending\n",
- adapter->current_op);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_ENABLE_VLAN_STRIPPING;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
- NULL, 0);
-}
-
-/**
- * i40evf_disable_vlan_stripping
- * @adapter: adapter structure
- *
- * Request VLAN header stripping to be disabled
- **/
-void i40evf_disable_vlan_stripping(struct i40evf_adapter *adapter)
-{
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot disable stripping, command %d pending\n",
- adapter->current_op);
- return;
- }
- adapter->current_op = VIRTCHNL_OP_DISABLE_VLAN_STRIPPING;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
- NULL, 0);
-}
-
-/**
- * i40evf_print_link_message - print link up or down
- * @adapter: adapter structure
- *
- * Log a message telling the world of our wonderous link status
- */
-static void i40evf_print_link_message(struct i40evf_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- char *speed = "Unknown ";
-
- if (!adapter->link_up) {
- netdev_info(netdev, "NIC Link is Down\n");
- return;
- }
-
- switch (adapter->link_speed) {
- case I40E_LINK_SPEED_40GB:
- speed = "40 G";
- break;
- case I40E_LINK_SPEED_25GB:
- speed = "25 G";
- break;
- case I40E_LINK_SPEED_20GB:
- speed = "20 G";
- break;
- case I40E_LINK_SPEED_10GB:
- speed = "10 G";
- break;
- case I40E_LINK_SPEED_1GB:
- speed = "1000 M";
- break;
- case I40E_LINK_SPEED_100MB:
- speed = "100 M";
- break;
- default:
- break;
- }
-
- netdev_info(netdev, "NIC Link is Up %sbps Full Duplex\n", speed);
-}
-
-/**
- * i40evf_enable_channel
- * @adapter: adapter structure
- *
- * Request that the PF enable channels as specified by
- * the user via tc tool.
- **/
-void i40evf_enable_channels(struct i40evf_adapter *adapter)
-{
- struct virtchnl_tc_info *vti = NULL;
- u16 len;
- int i;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot configure mqprio, command %d pending\n",
- adapter->current_op);
- return;
- }
-
- len = (adapter->num_tc * sizeof(struct virtchnl_channel_info)) +
- sizeof(struct virtchnl_tc_info);
-
- vti = kzalloc(len, GFP_KERNEL);
- if (!vti)
- return;
- vti->num_tc = adapter->num_tc;
- for (i = 0; i < vti->num_tc; i++) {
- vti->list[i].count = adapter->ch_config.ch_info[i].count;
- vti->list[i].offset = adapter->ch_config.ch_info[i].offset;
- vti->list[i].pad = 0;
- vti->list[i].max_tx_rate =
- adapter->ch_config.ch_info[i].max_tx_rate;
- }
-
- adapter->ch_config.state = __I40EVF_TC_RUNNING;
- adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
- adapter->current_op = VIRTCHNL_OP_ENABLE_CHANNELS;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_CHANNELS;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_CHANNELS,
- (u8 *)vti, len);
- kfree(vti);
-}
-
-/**
- * i40evf_disable_channel
- * @adapter: adapter structure
- *
- * Request that the PF disable channels that are configured
- **/
-void i40evf_disable_channels(struct i40evf_adapter *adapter)
-{
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot configure mqprio, command %d pending\n",
- adapter->current_op);
- return;
- }
-
- adapter->ch_config.state = __I40EVF_TC_INVALID;
- adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
- adapter->current_op = VIRTCHNL_OP_DISABLE_CHANNELS;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_CHANNELS;
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_CHANNELS,
- NULL, 0);
-}
-
-/**
- * i40evf_print_cloud_filter
- * @adapter: adapter structure
- * @f: cloud filter to print
- *
- * Print the cloud filter
- **/
-static void i40evf_print_cloud_filter(struct i40evf_adapter *adapter,
- struct virtchnl_filter *f)
-{
- switch (f->flow_type) {
- case VIRTCHNL_TCP_V4_FLOW:
- dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI4 src_ip %pI4 dst_port %hu src_port %hu\n",
- &f->data.tcp_spec.dst_mac,
- &f->data.tcp_spec.src_mac,
- ntohs(f->data.tcp_spec.vlan_id),
- &f->data.tcp_spec.dst_ip[0],
- &f->data.tcp_spec.src_ip[0],
- ntohs(f->data.tcp_spec.dst_port),
- ntohs(f->data.tcp_spec.src_port));
- break;
- case VIRTCHNL_TCP_V6_FLOW:
- dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI6 src_ip %pI6 dst_port %hu src_port %hu\n",
- &f->data.tcp_spec.dst_mac,
- &f->data.tcp_spec.src_mac,
- ntohs(f->data.tcp_spec.vlan_id),
- &f->data.tcp_spec.dst_ip,
- &f->data.tcp_spec.src_ip,
- ntohs(f->data.tcp_spec.dst_port),
- ntohs(f->data.tcp_spec.src_port));
- break;
- }
-}
-
-/**
- * i40evf_add_cloud_filter
- * @adapter: adapter structure
- *
- * Request that the PF add cloud filters as specified
- * by the user via tc tool.
- **/
-void i40evf_add_cloud_filter(struct i40evf_adapter *adapter)
-{
- struct i40evf_cloud_filter *cf;
- struct virtchnl_filter *f;
- int len = 0, count = 0;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot add cloud filter, command %d pending\n",
- adapter->current_op);
- return;
- }
- list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
- if (cf->add) {
- count++;
- break;
- }
- }
- if (!count) {
- adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;
- return;
- }
- adapter->current_op = VIRTCHNL_OP_ADD_CLOUD_FILTER;
-
- len = sizeof(struct virtchnl_filter);
- f = kzalloc(len, GFP_KERNEL);
- if (!f)
- return;
-
- list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
- if (cf->add) {
- memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
- cf->add = false;
- cf->state = __I40EVF_CF_ADD_PENDING;
- i40evf_send_pf_msg(adapter,
- VIRTCHNL_OP_ADD_CLOUD_FILTER,
- (u8 *)f, len);
- }
- }
- kfree(f);
-}
-
-/**
- * i40evf_del_cloud_filter
- * @adapter: adapter structure
- *
- * Request that the PF delete cloud filters as specified
- * by the user via tc tool.
- **/
-void i40evf_del_cloud_filter(struct i40evf_adapter *adapter)
-{
- struct i40evf_cloud_filter *cf, *cftmp;
- struct virtchnl_filter *f;
- int len = 0, count = 0;
-
- if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
- /* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot remove cloud filter, command %d pending\n",
- adapter->current_op);
- return;
- }
- list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
- if (cf->del) {
- count++;
- break;
- }
- }
- if (!count) {
- adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;
- return;
- }
- adapter->current_op = VIRTCHNL_OP_DEL_CLOUD_FILTER;
-
- len = sizeof(struct virtchnl_filter);
- f = kzalloc(len, GFP_KERNEL);
- if (!f)
- return;
-
- list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {
- if (cf->del) {
- memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
- cf->del = false;
- cf->state = __I40EVF_CF_DEL_PENDING;
- i40evf_send_pf_msg(adapter,
- VIRTCHNL_OP_DEL_CLOUD_FILTER,
- (u8 *)f, len);
- }
- }
- kfree(f);
-}
-
-/**
- * i40evf_request_reset
- * @adapter: adapter structure
- *
- * Request that the PF reset this VF. No response is expected.
- **/
-void i40evf_request_reset(struct i40evf_adapter *adapter)
-{
- /* Don't check CURRENT_OP - this is always higher priority */
- i40evf_send_pf_msg(adapter, VIRTCHNL_OP_RESET_VF, NULL, 0);
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
-}
-
-/**
- * i40evf_virtchnl_completion
- * @adapter: adapter structure
- * @v_opcode: opcode sent by PF
- * @v_retval: retval sent by PF
- * @msg: message sent by PF
- * @msglen: message length
- *
- * Asynchronous completion function for admin queue messages. Rather than busy
- * wait, we fire off our requests and assume that no errors will be returned.
- * This function handles the reply messages.
- **/
-void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
- enum virtchnl_ops v_opcode,
- i40e_status v_retval,
- u8 *msg, u16 msglen)
-{
- struct net_device *netdev = adapter->netdev;
-
- if (v_opcode == VIRTCHNL_OP_EVENT) {
- struct virtchnl_pf_event *vpe =
- (struct virtchnl_pf_event *)msg;
- bool link_up = vpe->event_data.link_event.link_status;
- switch (vpe->event) {
- case VIRTCHNL_EVENT_LINK_CHANGE:
- adapter->link_speed =
- vpe->event_data.link_event.link_speed;
-
- /* we've already got the right link status, bail */
- if (adapter->link_up == link_up)
- break;
-
- if (link_up) {
- /* If we get link up message and start queues
- * before our queues are configured it will
- * trigger a TX hang. In that case, just ignore
- * the link status message,we'll get another one
- * after we enable queues and actually prepared
- * to send traffic.
- */
- if (adapter->state != __I40EVF_RUNNING)
- break;
-
- /* For ADq enabled VF, we reconfigure VSIs and
- * re-allocate queues. Hence wait till all
- * queues are enabled.
- */
- if (adapter->flags &
- I40EVF_FLAG_QUEUES_DISABLED)
- break;
- }
-
- adapter->link_up = link_up;
- if (link_up) {
- netif_tx_start_all_queues(netdev);
- netif_carrier_on(netdev);
- } else {
- netif_tx_stop_all_queues(netdev);
- netif_carrier_off(netdev);
- }
- i40evf_print_link_message(adapter);
- break;
- case VIRTCHNL_EVENT_RESET_IMPENDING:
- dev_info(&adapter->pdev->dev, "Reset warning received from the PF\n");
- if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING)) {
- adapter->flags |= I40EVF_FLAG_RESET_PENDING;
- dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
- schedule_work(&adapter->reset_task);
- }
- break;
- default:
- dev_err(&adapter->pdev->dev, "Unknown event %d from PF\n",
- vpe->event);
- break;
- }
- return;
- }
- if (v_retval) {
- switch (v_opcode) {
- case VIRTCHNL_OP_ADD_VLAN:
- dev_err(&adapter->pdev->dev, "Failed to add VLAN filter, error %s\n",
- i40evf_stat_str(&adapter->hw, v_retval));
- break;
- case VIRTCHNL_OP_ADD_ETH_ADDR:
- dev_err(&adapter->pdev->dev, "Failed to add MAC filter, error %s\n",
- i40evf_stat_str(&adapter->hw, v_retval));
- break;
- case VIRTCHNL_OP_DEL_VLAN:
- dev_err(&adapter->pdev->dev, "Failed to delete VLAN filter, error %s\n",
- i40evf_stat_str(&adapter->hw, v_retval));
- break;
- case VIRTCHNL_OP_DEL_ETH_ADDR:
- dev_err(&adapter->pdev->dev, "Failed to delete MAC filter, error %s\n",
- i40evf_stat_str(&adapter->hw, v_retval));
- break;
- case VIRTCHNL_OP_ENABLE_CHANNELS:
- dev_err(&adapter->pdev->dev, "Failed to configure queue channels, error %s\n",
- i40evf_stat_str(&adapter->hw, v_retval));
- adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
- adapter->ch_config.state = __I40EVF_TC_INVALID;
- netdev_reset_tc(netdev);
- netif_tx_start_all_queues(netdev);
- break;
- case VIRTCHNL_OP_DISABLE_CHANNELS:
- dev_err(&adapter->pdev->dev, "Failed to disable queue channels, error %s\n",
- i40evf_stat_str(&adapter->hw, v_retval));
- adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
- adapter->ch_config.state = __I40EVF_TC_RUNNING;
- netif_tx_start_all_queues(netdev);
- break;
- case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
- struct i40evf_cloud_filter *cf, *cftmp;
-
- list_for_each_entry_safe(cf, cftmp,
- &adapter->cloud_filter_list,
- list) {
- if (cf->state == __I40EVF_CF_ADD_PENDING) {
- cf->state = __I40EVF_CF_INVALID;
- dev_info(&adapter->pdev->dev, "Failed to add cloud filter, error %s\n",
- i40evf_stat_str(&adapter->hw,
- v_retval));
- i40evf_print_cloud_filter(adapter,
- &cf->f);
- list_del(&cf->list);
- kfree(cf);
- adapter->num_cloud_filters--;
- }
- }
- }
- break;
- case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
- struct i40evf_cloud_filter *cf;
-
- list_for_each_entry(cf, &adapter->cloud_filter_list,
- list) {
- if (cf->state == __I40EVF_CF_DEL_PENDING) {
- cf->state = __I40EVF_CF_ACTIVE;
- dev_info(&adapter->pdev->dev, "Failed to del cloud filter, error %s\n",
- i40evf_stat_str(&adapter->hw,
- v_retval));
- i40evf_print_cloud_filter(adapter,
- &cf->f);
- }
- }
- }
- break;
- default:
- dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
- v_retval,
- i40evf_stat_str(&adapter->hw, v_retval),
- v_opcode);
- }
- }
- switch (v_opcode) {
- case VIRTCHNL_OP_GET_STATS: {
- struct i40e_eth_stats *stats =
- (struct i40e_eth_stats *)msg;
- netdev->stats.rx_packets = stats->rx_unicast +
- stats->rx_multicast +
- stats->rx_broadcast;
- netdev->stats.tx_packets = stats->tx_unicast +
- stats->tx_multicast +
- stats->tx_broadcast;
- netdev->stats.rx_bytes = stats->rx_bytes;
- netdev->stats.tx_bytes = stats->tx_bytes;
- netdev->stats.tx_errors = stats->tx_errors;
- netdev->stats.rx_dropped = stats->rx_discards;
- netdev->stats.tx_dropped = stats->tx_discards;
- adapter->current_stats = *stats;
- }
- break;
- case VIRTCHNL_OP_GET_VF_RESOURCES: {
- u16 len = sizeof(struct virtchnl_vf_resource) +
- I40E_MAX_VF_VSI *
- sizeof(struct virtchnl_vsi_resource);
- memcpy(adapter->vf_res, msg, min(msglen, len));
- i40evf_validate_num_queues(adapter);
- i40e_vf_parse_hw_config(&adapter->hw, adapter->vf_res);
- /* restore current mac address */
- ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
- i40evf_process_config(adapter);
- }
- break;
- case VIRTCHNL_OP_ENABLE_QUEUES:
- /* enable transmits */
- i40evf_irq_enable(adapter, true);
- adapter->flags &= ~I40EVF_FLAG_QUEUES_DISABLED;
- break;
- case VIRTCHNL_OP_DISABLE_QUEUES:
- i40evf_free_all_tx_resources(adapter);
- i40evf_free_all_rx_resources(adapter);
- if (adapter->state == __I40EVF_DOWN_PENDING) {
- adapter->state = __I40EVF_DOWN;
- wake_up(&adapter->down_waitqueue);
- }
- break;
- case VIRTCHNL_OP_VERSION:
- case VIRTCHNL_OP_CONFIG_IRQ_MAP:
- /* Don't display an error if we get these out of sequence.
- * If the firmware needed to get kicked, we'll get these and
- * it's no problem.
- */
- if (v_opcode != adapter->current_op)
- return;
- break;
- case VIRTCHNL_OP_IWARP:
- /* Gobble zero-length replies from the PF. They indicate that
- * a previous message was received OK, and the client doesn't
- * care about that.
- */
- if (msglen && CLIENT_ENABLED(adapter))
- i40evf_notify_client_message(&adapter->vsi,
- msg, msglen);
- break;
-
- case VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP:
- adapter->client_pending &=
- ~(BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP));
- break;
- case VIRTCHNL_OP_GET_RSS_HENA_CAPS: {
- struct virtchnl_rss_hena *vrh = (struct virtchnl_rss_hena *)msg;
- if (msglen == sizeof(*vrh))
- adapter->hena = vrh->hena;
- else
- dev_warn(&adapter->pdev->dev,
- "Invalid message %d from PF\n", v_opcode);
- }
- break;
- case VIRTCHNL_OP_REQUEST_QUEUES: {
- struct virtchnl_vf_res_request *vfres =
- (struct virtchnl_vf_res_request *)msg;
- if (vfres->num_queue_pairs != adapter->num_req_queues) {
- dev_info(&adapter->pdev->dev,
- "Requested %d queues, PF can support %d\n",
- adapter->num_req_queues,
- vfres->num_queue_pairs);
- adapter->num_req_queues = 0;
- adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
- }
- }
- break;
- case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
- struct i40evf_cloud_filter *cf;
-
- list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
- if (cf->state == __I40EVF_CF_ADD_PENDING)
- cf->state = __I40EVF_CF_ACTIVE;
- }
- }
- break;
- case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
- struct i40evf_cloud_filter *cf, *cftmp;
-
- list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list,
- list) {
- if (cf->state == __I40EVF_CF_DEL_PENDING) {
- cf->state = __I40EVF_CF_INVALID;
- list_del(&cf->list);
- kfree(cf);
- adapter->num_cloud_filters--;
- }
- }
- }
- break;
- default:
- if (adapter->current_op && (v_opcode != adapter->current_op))
- dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
- adapter->current_op, v_opcode);
- break;
- } /* switch v_opcode */
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
-}
diff --git a/drivers/net/ethernet/intel/iavf/Makefile b/drivers/net/ethernet/intel/iavf/Makefile
new file mode 100644
index 000000000000..1b050d9d5f49
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/Makefile
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright(c) 2013 - 2018 Intel Corporation.
+#
+# Makefile for the Intel(R) Ethernet Adaptive Virtual Function (iavf)
+# driver
+#
+#
+
+ccflags-y += -I$(src)
+subdir-ccflags-y += -I$(src)
+
+obj-$(CONFIG_IAVF) += iavf.o
+
+iavf-objs := i40evf_main.o i40evf_ethtool.o i40evf_virtchnl.o \
+ i40e_txrx.o i40e_common.o i40e_adminq.o i40evf_client.o
diff --git a/drivers/net/ethernet/intel/iavf/i40e_adminq.c b/drivers/net/ethernet/intel/iavf/i40e_adminq.c
new file mode 100644
index 000000000000..32e0e2d9cdc5
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_adminq.c
@@ -0,0 +1,940 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#include "i40e_status.h"
+#include "i40e_type.h"
+#include "i40e_register.h"
+#include "i40e_adminq.h"
+#include "i40e_prototype.h"
+
+/**
+ * i40e_adminq_init_regs - Initialize AdminQ registers
+ * @hw: pointer to the hardware structure
+ *
+ * This assumes the alloc_asq and alloc_arq functions have already been called
+ **/
+static void i40e_adminq_init_regs(struct i40e_hw *hw)
+{
+ /* set head and tail registers in our local struct */
+ if (i40e_is_vf(hw)) {
+ hw->aq.asq.tail = I40E_VF_ATQT1;
+ hw->aq.asq.head = I40E_VF_ATQH1;
+ hw->aq.asq.len = I40E_VF_ATQLEN1;
+ hw->aq.asq.bal = I40E_VF_ATQBAL1;
+ hw->aq.asq.bah = I40E_VF_ATQBAH1;
+ hw->aq.arq.tail = I40E_VF_ARQT1;
+ hw->aq.arq.head = I40E_VF_ARQH1;
+ hw->aq.arq.len = I40E_VF_ARQLEN1;
+ hw->aq.arq.bal = I40E_VF_ARQBAL1;
+ hw->aq.arq.bah = I40E_VF_ARQBAH1;
+ }
+}
+
+/**
+ * i40e_alloc_adminq_asq_ring - Allocate Admin Queue send rings
+ * @hw: pointer to the hardware structure
+ **/
+static i40e_status i40e_alloc_adminq_asq_ring(struct i40e_hw *hw)
+{
+ i40e_status ret_code;
+
+ ret_code = i40e_allocate_dma_mem(hw, &hw->aq.asq.desc_buf,
+ i40e_mem_atq_ring,
+ (hw->aq.num_asq_entries *
+ sizeof(struct i40e_aq_desc)),
+ I40E_ADMINQ_DESC_ALIGNMENT);
+ if (ret_code)
+ return ret_code;
+
+ ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.cmd_buf,
+ (hw->aq.num_asq_entries *
+ sizeof(struct i40e_asq_cmd_details)));
+ if (ret_code) {
+ i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
+ return ret_code;
+ }
+
+ return ret_code;
+}
+
+/**
+ * i40e_alloc_adminq_arq_ring - Allocate Admin Queue receive rings
+ * @hw: pointer to the hardware structure
+ **/
+static i40e_status i40e_alloc_adminq_arq_ring(struct i40e_hw *hw)
+{
+ i40e_status ret_code;
+
+ ret_code = i40e_allocate_dma_mem(hw, &hw->aq.arq.desc_buf,
+ i40e_mem_arq_ring,
+ (hw->aq.num_arq_entries *
+ sizeof(struct i40e_aq_desc)),
+ I40E_ADMINQ_DESC_ALIGNMENT);
+
+ return ret_code;
+}
+
+/**
+ * i40e_free_adminq_asq - Free Admin Queue send rings
+ * @hw: pointer to the hardware structure
+ *
+ * This assumes the posted send buffers have already been cleaned
+ * and de-allocated
+ **/
+static void i40e_free_adminq_asq(struct i40e_hw *hw)
+{
+ i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
+}
+
+/**
+ * i40e_free_adminq_arq - Free Admin Queue receive rings
+ * @hw: pointer to the hardware structure
+ *
+ * This assumes the posted receive buffers have already been cleaned
+ * and de-allocated
+ **/
+static void i40e_free_adminq_arq(struct i40e_hw *hw)
+{
+ i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
+}
+
+/**
+ * i40e_alloc_arq_bufs - Allocate pre-posted buffers for the receive queue
+ * @hw: pointer to the hardware structure
+ **/
+static i40e_status i40e_alloc_arq_bufs(struct i40e_hw *hw)
+{
+ i40e_status ret_code;
+ struct i40e_aq_desc *desc;
+ struct i40e_dma_mem *bi;
+ int i;
+
+ /* We'll be allocating the buffer info memory first, then we can
+ * allocate the mapped buffers for the event processing
+ */
+
+ /* buffer_info structures do not need alignment */
+ ret_code = i40e_allocate_virt_mem(hw, &hw->aq.arq.dma_head,
+ (hw->aq.num_arq_entries * sizeof(struct i40e_dma_mem)));
+ if (ret_code)
+ goto alloc_arq_bufs;
+ hw->aq.arq.r.arq_bi = (struct i40e_dma_mem *)hw->aq.arq.dma_head.va;
+
+ /* allocate the mapped buffers */
+ for (i = 0; i < hw->aq.num_arq_entries; i++) {
+ bi = &hw->aq.arq.r.arq_bi[i];
+ ret_code = i40e_allocate_dma_mem(hw, bi,
+ i40e_mem_arq_buf,
+ hw->aq.arq_buf_size,
+ I40E_ADMINQ_DESC_ALIGNMENT);
+ if (ret_code)
+ goto unwind_alloc_arq_bufs;
+
+ /* now configure the descriptors for use */
+ desc = I40E_ADMINQ_DESC(hw->aq.arq, i);
+
+ desc->flags = cpu_to_le16(I40E_AQ_FLAG_BUF);
+ if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
+ desc->flags |= cpu_to_le16(I40E_AQ_FLAG_LB);
+ desc->opcode = 0;
+ /* This is in accordance with Admin queue design, there is no
+ * register for buffer size configuration
+ */
+ desc->datalen = cpu_to_le16((u16)bi->size);
+ desc->retval = 0;
+ desc->cookie_high = 0;
+ desc->cookie_low = 0;
+ desc->params.external.addr_high =
+ cpu_to_le32(upper_32_bits(bi->pa));
+ desc->params.external.addr_low =
+ cpu_to_le32(lower_32_bits(bi->pa));
+ desc->params.external.param0 = 0;
+ desc->params.external.param1 = 0;
+ }
+
+alloc_arq_bufs:
+ return ret_code;
+
+unwind_alloc_arq_bufs:
+ /* don't try to free the one that failed... */
+ i--;
+ for (; i >= 0; i--)
+ i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
+ i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
+
+ return ret_code;
+}
+
+/**
+ * i40e_alloc_asq_bufs - Allocate empty buffer structs for the send queue
+ * @hw: pointer to the hardware structure
+ **/
+static i40e_status i40e_alloc_asq_bufs(struct i40e_hw *hw)
+{
+ i40e_status ret_code;
+ struct i40e_dma_mem *bi;
+ int i;
+
+ /* No mapped memory needed yet, just the buffer info structures */
+ ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.dma_head,
+ (hw->aq.num_asq_entries * sizeof(struct i40e_dma_mem)));
+ if (ret_code)
+ goto alloc_asq_bufs;
+ hw->aq.asq.r.asq_bi = (struct i40e_dma_mem *)hw->aq.asq.dma_head.va;
+
+ /* allocate the mapped buffers */
+ for (i = 0; i < hw->aq.num_asq_entries; i++) {
+ bi = &hw->aq.asq.r.asq_bi[i];
+ ret_code = i40e_allocate_dma_mem(hw, bi,
+ i40e_mem_asq_buf,
+ hw->aq.asq_buf_size,
+ I40E_ADMINQ_DESC_ALIGNMENT);
+ if (ret_code)
+ goto unwind_alloc_asq_bufs;
+ }
+alloc_asq_bufs:
+ return ret_code;
+
+unwind_alloc_asq_bufs:
+ /* don't try to free the one that failed... */
+ i--;
+ for (; i >= 0; i--)
+ i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
+ i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
+
+ return ret_code;
+}
+
+/**
+ * i40e_free_arq_bufs - Free receive queue buffer info elements
+ * @hw: pointer to the hardware structure
+ **/
+static void i40e_free_arq_bufs(struct i40e_hw *hw)
+{
+ int i;
+
+ /* free descriptors */
+ for (i = 0; i < hw->aq.num_arq_entries; i++)
+ i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
+
+ /* free the descriptor memory */
+ i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf);
+
+ /* free the dma header */
+ i40e_free_virt_mem(hw, &hw->aq.arq.dma_head);
+}
+
+/**
+ * i40e_free_asq_bufs - Free send queue buffer info elements
+ * @hw: pointer to the hardware structure
+ **/
+static void i40e_free_asq_bufs(struct i40e_hw *hw)
+{
+ int i;
+
+ /* only unmap if the address is non-NULL */
+ for (i = 0; i < hw->aq.num_asq_entries; i++)
+ if (hw->aq.asq.r.asq_bi[i].pa)
+ i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
+
+ /* free the buffer info list */
+ i40e_free_virt_mem(hw, &hw->aq.asq.cmd_buf);
+
+ /* free the descriptor memory */
+ i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf);
+
+ /* free the dma header */
+ i40e_free_virt_mem(hw, &hw->aq.asq.dma_head);
+}
+
+/**
+ * i40e_config_asq_regs - configure ASQ registers
+ * @hw: pointer to the hardware structure
+ *
+ * Configure base address and length registers for the transmit queue
+ **/
+static i40e_status i40e_config_asq_regs(struct i40e_hw *hw)
+{
+ i40e_status ret_code = 0;
+ u32 reg = 0;
+
+ /* Clear Head and Tail */
+ wr32(hw, hw->aq.asq.head, 0);
+ wr32(hw, hw->aq.asq.tail, 0);
+
+ /* set starting point */
+ wr32(hw, hw->aq.asq.len, (hw->aq.num_asq_entries |
+ I40E_VF_ATQLEN1_ATQENABLE_MASK));
+ wr32(hw, hw->aq.asq.bal, lower_32_bits(hw->aq.asq.desc_buf.pa));
+ wr32(hw, hw->aq.asq.bah, upper_32_bits(hw->aq.asq.desc_buf.pa));
+
+ /* Check one register to verify that config was applied */
+ reg = rd32(hw, hw->aq.asq.bal);
+ if (reg != lower_32_bits(hw->aq.asq.desc_buf.pa))
+ ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
+
+ return ret_code;
+}
+
+/**
+ * i40e_config_arq_regs - ARQ register configuration
+ * @hw: pointer to the hardware structure
+ *
+ * Configure base address and length registers for the receive (event queue)
+ **/
+static i40e_status i40e_config_arq_regs(struct i40e_hw *hw)
+{
+ i40e_status ret_code = 0;
+ u32 reg = 0;
+
+ /* Clear Head and Tail */
+ wr32(hw, hw->aq.arq.head, 0);
+ wr32(hw, hw->aq.arq.tail, 0);
+
+ /* set starting point */
+ wr32(hw, hw->aq.arq.len, (hw->aq.num_arq_entries |
+ I40E_VF_ARQLEN1_ARQENABLE_MASK));
+ wr32(hw, hw->aq.arq.bal, lower_32_bits(hw->aq.arq.desc_buf.pa));
+ wr32(hw, hw->aq.arq.bah, upper_32_bits(hw->aq.arq.desc_buf.pa));
+
+ /* Update tail in the HW to post pre-allocated buffers */
+ wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1);
+
+ /* Check one register to verify that config was applied */
+ reg = rd32(hw, hw->aq.arq.bal);
+ if (reg != lower_32_bits(hw->aq.arq.desc_buf.pa))
+ ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
+
+ return ret_code;
+}
+
+/**
+ * i40e_init_asq - main initialization routine for ASQ
+ * @hw: pointer to the hardware structure
+ *
+ * This is the main initialization routine for the Admin Send Queue
+ * Prior to calling this function, drivers *MUST* set the following fields
+ * in the hw->aq structure:
+ * - hw->aq.num_asq_entries
+ * - hw->aq.arq_buf_size
+ *
+ * Do *NOT* hold the lock when calling this as the memory allocation routines
+ * called are not going to be atomic context safe
+ **/
+static i40e_status i40e_init_asq(struct i40e_hw *hw)
+{
+ i40e_status ret_code = 0;
+
+ if (hw->aq.asq.count > 0) {
+ /* queue already initialized */
+ ret_code = I40E_ERR_NOT_READY;
+ goto init_adminq_exit;
+ }
+
+ /* verify input for valid configuration */
+ if ((hw->aq.num_asq_entries == 0) ||
+ (hw->aq.asq_buf_size == 0)) {
+ ret_code = I40E_ERR_CONFIG;
+ goto init_adminq_exit;
+ }
+
+ hw->aq.asq.next_to_use = 0;
+ hw->aq.asq.next_to_clean = 0;
+
+ /* allocate the ring memory */
+ ret_code = i40e_alloc_adminq_asq_ring(hw);
+ if (ret_code)
+ goto init_adminq_exit;
+
+ /* allocate buffers in the rings */
+ ret_code = i40e_alloc_asq_bufs(hw);
+ if (ret_code)
+ goto init_adminq_free_rings;
+
+ /* initialize base registers */
+ ret_code = i40e_config_asq_regs(hw);
+ if (ret_code)
+ goto init_adminq_free_rings;
+
+ /* success! */
+ hw->aq.asq.count = hw->aq.num_asq_entries;
+ goto init_adminq_exit;
+
+init_adminq_free_rings:
+ i40e_free_adminq_asq(hw);
+
+init_adminq_exit:
+ return ret_code;
+}
+
+/**
+ * i40e_init_arq - initialize ARQ
+ * @hw: pointer to the hardware structure
+ *
+ * The main initialization routine for the Admin Receive (Event) Queue.
+ * Prior to calling this function, drivers *MUST* set the following fields
+ * in the hw->aq structure:
+ * - hw->aq.num_asq_entries
+ * - hw->aq.arq_buf_size
+ *
+ * Do *NOT* hold the lock when calling this as the memory allocation routines
+ * called are not going to be atomic context safe
+ **/
+static i40e_status i40e_init_arq(struct i40e_hw *hw)
+{
+ i40e_status ret_code = 0;
+
+ if (hw->aq.arq.count > 0) {
+ /* queue already initialized */
+ ret_code = I40E_ERR_NOT_READY;
+ goto init_adminq_exit;
+ }
+
+ /* verify input for valid configuration */
+ if ((hw->aq.num_arq_entries == 0) ||
+ (hw->aq.arq_buf_size == 0)) {
+ ret_code = I40E_ERR_CONFIG;
+ goto init_adminq_exit;
+ }
+
+ hw->aq.arq.next_to_use = 0;
+ hw->aq.arq.next_to_clean = 0;
+
+ /* allocate the ring memory */
+ ret_code = i40e_alloc_adminq_arq_ring(hw);
+ if (ret_code)
+ goto init_adminq_exit;
+
+ /* allocate buffers in the rings */
+ ret_code = i40e_alloc_arq_bufs(hw);
+ if (ret_code)
+ goto init_adminq_free_rings;
+
+ /* initialize base registers */
+ ret_code = i40e_config_arq_regs(hw);
+ if (ret_code)
+ goto init_adminq_free_rings;
+
+ /* success! */
+ hw->aq.arq.count = hw->aq.num_arq_entries;
+ goto init_adminq_exit;
+
+init_adminq_free_rings:
+ i40e_free_adminq_arq(hw);
+
+init_adminq_exit:
+ return ret_code;
+}
+
+/**
+ * i40e_shutdown_asq - shutdown the ASQ
+ * @hw: pointer to the hardware structure
+ *
+ * The main shutdown routine for the Admin Send Queue
+ **/
+static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
+{
+ i40e_status ret_code = 0;
+
+ mutex_lock(&hw->aq.asq_mutex);
+
+ if (hw->aq.asq.count == 0) {
+ ret_code = I40E_ERR_NOT_READY;
+ goto shutdown_asq_out;
+ }
+
+ /* Stop firmware AdminQ processing */
+ wr32(hw, hw->aq.asq.head, 0);
+ wr32(hw, hw->aq.asq.tail, 0);
+ wr32(hw, hw->aq.asq.len, 0);
+ wr32(hw, hw->aq.asq.bal, 0);
+ wr32(hw, hw->aq.asq.bah, 0);
+
+ hw->aq.asq.count = 0; /* to indicate uninitialized queue */
+
+ /* free ring buffers */
+ i40e_free_asq_bufs(hw);
+
+shutdown_asq_out:
+ mutex_unlock(&hw->aq.asq_mutex);
+ return ret_code;
+}
+
+/**
+ * i40e_shutdown_arq - shutdown ARQ
+ * @hw: pointer to the hardware structure
+ *
+ * The main shutdown routine for the Admin Receive Queue
+ **/
+static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
+{
+ i40e_status ret_code = 0;
+
+ mutex_lock(&hw->aq.arq_mutex);
+
+ if (hw->aq.arq.count == 0) {
+ ret_code = I40E_ERR_NOT_READY;
+ goto shutdown_arq_out;
+ }
+
+ /* Stop firmware AdminQ processing */
+ wr32(hw, hw->aq.arq.head, 0);
+ wr32(hw, hw->aq.arq.tail, 0);
+ wr32(hw, hw->aq.arq.len, 0);
+ wr32(hw, hw->aq.arq.bal, 0);
+ wr32(hw, hw->aq.arq.bah, 0);
+
+ hw->aq.arq.count = 0; /* to indicate uninitialized queue */
+
+ /* free ring buffers */
+ i40e_free_arq_bufs(hw);
+
+shutdown_arq_out:
+ mutex_unlock(&hw->aq.arq_mutex);
+ return ret_code;
+}
+
+/**
+ * i40evf_init_adminq - main initialization routine for Admin Queue
+ * @hw: pointer to the hardware structure
+ *
+ * Prior to calling this function, drivers *MUST* set the following fields
+ * in the hw->aq structure:
+ * - hw->aq.num_asq_entries
+ * - hw->aq.num_arq_entries
+ * - hw->aq.arq_buf_size
+ * - hw->aq.asq_buf_size
+ **/
+i40e_status i40evf_init_adminq(struct i40e_hw *hw)
+{
+ i40e_status ret_code;
+
+ /* verify input for valid configuration */
+ if ((hw->aq.num_arq_entries == 0) ||
+ (hw->aq.num_asq_entries == 0) ||
+ (hw->aq.arq_buf_size == 0) ||
+ (hw->aq.asq_buf_size == 0)) {
+ ret_code = I40E_ERR_CONFIG;
+ goto init_adminq_exit;
+ }
+
+ /* Set up register offsets */
+ i40e_adminq_init_regs(hw);
+
+ /* setup ASQ command write back timeout */
+ hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT;
+
+ /* allocate the ASQ */
+ ret_code = i40e_init_asq(hw);
+ if (ret_code)
+ goto init_adminq_destroy_locks;
+
+ /* allocate the ARQ */
+ ret_code = i40e_init_arq(hw);
+ if (ret_code)
+ goto init_adminq_free_asq;
+
+ /* success! */
+ goto init_adminq_exit;
+
+init_adminq_free_asq:
+ i40e_shutdown_asq(hw);
+init_adminq_destroy_locks:
+
+init_adminq_exit:
+ return ret_code;
+}
+
+/**
+ * i40evf_shutdown_adminq - shutdown routine for the Admin Queue
+ * @hw: pointer to the hardware structure
+ **/
+i40e_status i40evf_shutdown_adminq(struct i40e_hw *hw)
+{
+ i40e_status ret_code = 0;
+
+ if (i40evf_check_asq_alive(hw))
+ i40evf_aq_queue_shutdown(hw, true);
+
+ i40e_shutdown_asq(hw);
+ i40e_shutdown_arq(hw);
+
+ return ret_code;
+}
+
+/**
+ * i40e_clean_asq - cleans Admin send queue
+ * @hw: pointer to the hardware structure
+ *
+ * returns the number of free desc
+ **/
+static u16 i40e_clean_asq(struct i40e_hw *hw)
+{
+ struct i40e_adminq_ring *asq = &(hw->aq.asq);
+ struct i40e_asq_cmd_details *details;
+ u16 ntc = asq->next_to_clean;
+ struct i40e_aq_desc desc_cb;
+ struct i40e_aq_desc *desc;
+
+ desc = I40E_ADMINQ_DESC(*asq, ntc);
+ details = I40E_ADMINQ_DETAILS(*asq, ntc);
+ while (rd32(hw, hw->aq.asq.head) != ntc) {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "ntc %d head %d.\n", ntc, rd32(hw, hw->aq.asq.head));
+
+ if (details->callback) {
+ I40E_ADMINQ_CALLBACK cb_func =
+ (I40E_ADMINQ_CALLBACK)details->callback;
+ desc_cb = *desc;
+ cb_func(hw, &desc_cb);
+ }
+ memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
+ memset((void *)details, 0,
+ sizeof(struct i40e_asq_cmd_details));
+ ntc++;
+ if (ntc == asq->count)
+ ntc = 0;
+ desc = I40E_ADMINQ_DESC(*asq, ntc);
+ details = I40E_ADMINQ_DETAILS(*asq, ntc);
+ }
+
+ asq->next_to_clean = ntc;
+
+ return I40E_DESC_UNUSED(asq);
+}
+
+/**
+ * i40evf_asq_done - check if FW has processed the Admin Send Queue
+ * @hw: pointer to the hw struct
+ *
+ * Returns true if the firmware has processed all descriptors on the
+ * admin send queue. Returns false if there are still requests pending.
+ **/
+bool i40evf_asq_done(struct i40e_hw *hw)
+{
+ /* AQ designers suggest use of head for better
+ * timing reliability than DD bit
+ */
+ return rd32(hw, hw->aq.asq.head) == hw->aq.asq.next_to_use;
+
+}
+
+/**
+ * i40evf_asq_send_command - send command to Admin Queue
+ * @hw: pointer to the hw struct
+ * @desc: prefilled descriptor describing the command (non DMA mem)
+ * @buff: buffer to use for indirect commands
+ * @buff_size: size of buffer for indirect commands
+ * @cmd_details: pointer to command details structure
+ *
+ * This is the main send command driver routine for the Admin Queue send
+ * queue. It runs the queue, cleans the queue, etc
+ **/
+i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
+ struct i40e_aq_desc *desc,
+ void *buff, /* can be NULL */
+ u16 buff_size,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ i40e_status status = 0;
+ struct i40e_dma_mem *dma_buff = NULL;
+ struct i40e_asq_cmd_details *details;
+ struct i40e_aq_desc *desc_on_ring;
+ bool cmd_completed = false;
+ u16 retval = 0;
+ u32 val = 0;
+
+ mutex_lock(&hw->aq.asq_mutex);
+
+ if (hw->aq.asq.count == 0) {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: Admin queue not initialized.\n");
+ status = I40E_ERR_QUEUE_EMPTY;
+ goto asq_send_command_error;
+ }
+
+ hw->aq.asq_last_status = I40E_AQ_RC_OK;
+
+ val = rd32(hw, hw->aq.asq.head);
+ if (val >= hw->aq.num_asq_entries) {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: head overrun at %d\n", val);
+ status = I40E_ERR_QUEUE_EMPTY;
+ goto asq_send_command_error;
+ }
+
+ details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
+ if (cmd_details) {
+ *details = *cmd_details;
+
+ /* If the cmd_details are defined copy the cookie. The
+ * cpu_to_le32 is not needed here because the data is ignored
+ * by the FW, only used by the driver
+ */
+ if (details->cookie) {
+ desc->cookie_high =
+ cpu_to_le32(upper_32_bits(details->cookie));
+ desc->cookie_low =
+ cpu_to_le32(lower_32_bits(details->cookie));
+ }
+ } else {
+ memset(details, 0, sizeof(struct i40e_asq_cmd_details));
+ }
+
+ /* clear requested flags and then set additional flags if defined */
+ desc->flags &= ~cpu_to_le16(details->flags_dis);
+ desc->flags |= cpu_to_le16(details->flags_ena);
+
+ if (buff_size > hw->aq.asq_buf_size) {
+ i40e_debug(hw,
+ I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: Invalid buffer size: %d.\n",
+ buff_size);
+ status = I40E_ERR_INVALID_SIZE;
+ goto asq_send_command_error;
+ }
+
+ if (details->postpone && !details->async) {
+ i40e_debug(hw,
+ I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: Async flag not set along with postpone flag");
+ status = I40E_ERR_PARAM;
+ goto asq_send_command_error;
+ }
+
+ /* call clean and check queue available function to reclaim the
+ * descriptors that were processed by FW, the function returns the
+ * number of desc available
+ */
+ /* the clean function called here could be called in a separate thread
+ * in case of asynchronous completions
+ */
+ if (i40e_clean_asq(hw) == 0) {
+ i40e_debug(hw,
+ I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: Error queue is full.\n");
+ status = I40E_ERR_ADMIN_QUEUE_FULL;
+ goto asq_send_command_error;
+ }
+
+ /* initialize the temp desc pointer with the right desc */
+ desc_on_ring = I40E_ADMINQ_DESC(hw->aq.asq, hw->aq.asq.next_to_use);
+
+ /* if the desc is available copy the temp desc to the right place */
+ *desc_on_ring = *desc;
+
+ /* if buff is not NULL assume indirect command */
+ if (buff != NULL) {
+ dma_buff = &(hw->aq.asq.r.asq_bi[hw->aq.asq.next_to_use]);
+ /* copy the user buff into the respective DMA buff */
+ memcpy(dma_buff->va, buff, buff_size);
+ desc_on_ring->datalen = cpu_to_le16(buff_size);
+
+ /* Update the address values in the desc with the pa value
+ * for respective buffer
+ */
+ desc_on_ring->params.external.addr_high =
+ cpu_to_le32(upper_32_bits(dma_buff->pa));
+ desc_on_ring->params.external.addr_low =
+ cpu_to_le32(lower_32_bits(dma_buff->pa));
+ }
+
+ /* bump the tail */
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer:\n");
+ i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring,
+ buff, buff_size);
+ (hw->aq.asq.next_to_use)++;
+ if (hw->aq.asq.next_to_use == hw->aq.asq.count)
+ hw->aq.asq.next_to_use = 0;
+ if (!details->postpone)
+ wr32(hw, hw->aq.asq.tail, hw->aq.asq.next_to_use);
+
+ /* if cmd_details are not defined or async flag is not set,
+ * we need to wait for desc write back
+ */
+ if (!details->async && !details->postpone) {
+ u32 total_delay = 0;
+
+ do {
+ /* AQ designers suggest use of head for better
+ * timing reliability than DD bit
+ */
+ if (i40evf_asq_done(hw))
+ break;
+ udelay(50);
+ total_delay += 50;
+ } while (total_delay < hw->aq.asq_cmd_timeout);
+ }
+
+ /* if ready, copy the desc back to temp */
+ if (i40evf_asq_done(hw)) {
+ *desc = *desc_on_ring;
+ if (buff != NULL)
+ memcpy(buff, dma_buff->va, buff_size);
+ retval = le16_to_cpu(desc->retval);
+ if (retval != 0) {
+ i40e_debug(hw,
+ I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: Command completed with error 0x%X.\n",
+ retval);
+
+ /* strip off FW internal code */
+ retval &= 0xff;
+ }
+ cmd_completed = true;
+ if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_OK)
+ status = 0;
+ else if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_EBUSY)
+ status = I40E_ERR_NOT_READY;
+ else
+ status = I40E_ERR_ADMIN_QUEUE_ERROR;
+ hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
+ }
+
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: desc and buffer writeback:\n");
+ i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff,
+ buff_size);
+
+ /* save writeback aq if requested */
+ if (details->wb_desc)
+ *details->wb_desc = *desc_on_ring;
+
+ /* update the error if time out occurred */
+ if ((!cmd_completed) &&
+ (!details->async && !details->postpone)) {
+ if (rd32(hw, hw->aq.asq.len) & I40E_VF_ATQLEN1_ATQCRIT_MASK) {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: AQ Critical error.\n");
+ status = I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR;
+ } else {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: Writeback timeout.\n");
+ status = I40E_ERR_ADMIN_QUEUE_TIMEOUT;
+ }
+ }
+
+asq_send_command_error:
+ mutex_unlock(&hw->aq.asq_mutex);
+ return status;
+}
+
+/**
+ * i40evf_fill_default_direct_cmd_desc - AQ descriptor helper function
+ * @desc: pointer to the temp descriptor (non DMA mem)
+ * @opcode: the opcode can be used to decide which flags to turn off or on
+ *
+ * Fill the desc with default values
+ **/
+void i40evf_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
+ u16 opcode)
+{
+ /* zero out the desc */
+ memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
+ desc->opcode = cpu_to_le16(opcode);
+ desc->flags = cpu_to_le16(I40E_AQ_FLAG_SI);
+}
+
+/**
+ * i40evf_clean_arq_element
+ * @hw: pointer to the hw struct
+ * @e: event info from the receive descriptor, includes any buffers
+ * @pending: number of events that could be left to process
+ *
+ * This function cleans one Admin Receive Queue element and returns
+ * the contents through e. It can also return how many events are
+ * left to process through 'pending'
+ **/
+i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
+ struct i40e_arq_event_info *e,
+ u16 *pending)
+{
+ i40e_status ret_code = 0;
+ u16 ntc = hw->aq.arq.next_to_clean;
+ struct i40e_aq_desc *desc;
+ struct i40e_dma_mem *bi;
+ u16 desc_idx;
+ u16 datalen;
+ u16 flags;
+ u16 ntu;
+
+ /* pre-clean the event info */
+ memset(&e->desc, 0, sizeof(e->desc));
+
+ /* take the lock before we start messing with the ring */
+ mutex_lock(&hw->aq.arq_mutex);
+
+ if (hw->aq.arq.count == 0) {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQRX: Admin queue not initialized.\n");
+ ret_code = I40E_ERR_QUEUE_EMPTY;
+ goto clean_arq_element_err;
+ }
+
+ /* set next_to_use to head */
+ ntu = rd32(hw, hw->aq.arq.head) & I40E_VF_ARQH1_ARQH_MASK;
+ if (ntu == ntc) {
+ /* nothing to do - shouldn't need to update ring's values */
+ ret_code = I40E_ERR_ADMIN_QUEUE_NO_WORK;
+ goto clean_arq_element_out;
+ }
+
+ /* now clean the next descriptor */
+ desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
+ desc_idx = ntc;
+
+ hw->aq.arq_last_status =
+ (enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
+ flags = le16_to_cpu(desc->flags);
+ if (flags & I40E_AQ_FLAG_ERR) {
+ ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
+ i40e_debug(hw,
+ I40E_DEBUG_AQ_MESSAGE,
+ "AQRX: Event received with error 0x%X.\n",
+ hw->aq.arq_last_status);
+ }
+
+ e->desc = *desc;
+ datalen = le16_to_cpu(desc->datalen);
+ e->msg_len = min(datalen, e->buf_len);
+ if (e->msg_buf != NULL && (e->msg_len != 0))
+ memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
+ e->msg_len);
+
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n");
+ i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf,
+ hw->aq.arq_buf_size);
+
+ /* Restore the original datalen and buffer address in the desc,
+ * FW updates datalen to indicate the event message
+ * size
+ */
+ bi = &hw->aq.arq.r.arq_bi[ntc];
+ memset((void *)desc, 0, sizeof(struct i40e_aq_desc));
+
+ desc->flags = cpu_to_le16(I40E_AQ_FLAG_BUF);
+ if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF)
+ desc->flags |= cpu_to_le16(I40E_AQ_FLAG_LB);
+ desc->datalen = cpu_to_le16((u16)bi->size);
+ desc->params.external.addr_high = cpu_to_le32(upper_32_bits(bi->pa));
+ desc->params.external.addr_low = cpu_to_le32(lower_32_bits(bi->pa));
+
+ /* set tail = the last cleaned desc index. */
+ wr32(hw, hw->aq.arq.tail, ntc);
+ /* ntc is updated to tail + 1 */
+ ntc++;
+ if (ntc == hw->aq.num_arq_entries)
+ ntc = 0;
+ hw->aq.arq.next_to_clean = ntc;
+ hw->aq.arq.next_to_use = ntu;
+
+clean_arq_element_out:
+ /* Set pending if needed, unlock and return */
+ if (pending != NULL)
+ *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
+
+clean_arq_element_err:
+ mutex_unlock(&hw->aq.arq_mutex);
+
+ return ret_code;
+}
diff --git a/drivers/net/ethernet/intel/iavf/i40e_adminq.h b/drivers/net/ethernet/intel/iavf/i40e_adminq.h
new file mode 100644
index 000000000000..1f264b9b6805
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_adminq.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_ADMINQ_H_
+#define _I40E_ADMINQ_H_
+
+#include "i40e_osdep.h"
+#include "i40e_status.h"
+#include "i40e_adminq_cmd.h"
+
+#define I40E_ADMINQ_DESC(R, i) \
+ (&(((struct i40e_aq_desc *)((R).desc_buf.va))[i]))
+
+#define I40E_ADMINQ_DESC_ALIGNMENT 4096
+
+struct i40e_adminq_ring {
+ struct i40e_virt_mem dma_head; /* space for dma structures */
+ struct i40e_dma_mem desc_buf; /* descriptor ring memory */
+ struct i40e_virt_mem cmd_buf; /* command buffer memory */
+
+ union {
+ struct i40e_dma_mem *asq_bi;
+ struct i40e_dma_mem *arq_bi;
+ } r;
+
+ u16 count; /* Number of descriptors */
+ u16 rx_buf_len; /* Admin Receive Queue buffer length */
+
+ /* used for interrupt processing */
+ u16 next_to_use;
+ u16 next_to_clean;
+
+ /* used for queue tracking */
+ u32 head;
+ u32 tail;
+ u32 len;
+ u32 bah;
+ u32 bal;
+};
+
+/* ASQ transaction details */
+struct i40e_asq_cmd_details {
+ void *callback; /* cast from type I40E_ADMINQ_CALLBACK */
+ u64 cookie;
+ u16 flags_ena;
+ u16 flags_dis;
+ bool async;
+ bool postpone;
+ struct i40e_aq_desc *wb_desc;
+};
+
+#define I40E_ADMINQ_DETAILS(R, i) \
+ (&(((struct i40e_asq_cmd_details *)((R).cmd_buf.va))[i]))
+
+/* ARQ event information */
+struct i40e_arq_event_info {
+ struct i40e_aq_desc desc;
+ u16 msg_len;
+ u16 buf_len;
+ u8 *msg_buf;
+};
+
+/* Admin Queue information */
+struct i40e_adminq_info {
+ struct i40e_adminq_ring arq; /* receive queue */
+ struct i40e_adminq_ring asq; /* send queue */
+ u32 asq_cmd_timeout; /* send queue cmd write back timeout*/
+ u16 num_arq_entries; /* receive queue depth */
+ u16 num_asq_entries; /* send queue depth */
+ u16 arq_buf_size; /* receive queue buffer size */
+ u16 asq_buf_size; /* send queue buffer size */
+ u16 fw_maj_ver; /* firmware major version */
+ u16 fw_min_ver; /* firmware minor version */
+ u32 fw_build; /* firmware build number */
+ u16 api_maj_ver; /* api major version */
+ u16 api_min_ver; /* api minor version */
+
+ struct mutex asq_mutex; /* Send queue lock */
+ struct mutex arq_mutex; /* Receive queue lock */
+
+ /* last status values on send and receive queues */
+ enum i40e_admin_queue_err asq_last_status;
+ enum i40e_admin_queue_err arq_last_status;
+};
+
+/**
+ * i40e_aq_rc_to_posix - convert errors to user-land codes
+ * aq_ret: AdminQ handler error code can override aq_rc
+ * aq_rc: AdminQ firmware error code to convert
+ **/
+static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc)
+{
+ int aq_to_posix[] = {
+ 0, /* I40E_AQ_RC_OK */
+ -EPERM, /* I40E_AQ_RC_EPERM */
+ -ENOENT, /* I40E_AQ_RC_ENOENT */
+ -ESRCH, /* I40E_AQ_RC_ESRCH */
+ -EINTR, /* I40E_AQ_RC_EINTR */
+ -EIO, /* I40E_AQ_RC_EIO */
+ -ENXIO, /* I40E_AQ_RC_ENXIO */
+ -E2BIG, /* I40E_AQ_RC_E2BIG */
+ -EAGAIN, /* I40E_AQ_RC_EAGAIN */
+ -ENOMEM, /* I40E_AQ_RC_ENOMEM */
+ -EACCES, /* I40E_AQ_RC_EACCES */
+ -EFAULT, /* I40E_AQ_RC_EFAULT */
+ -EBUSY, /* I40E_AQ_RC_EBUSY */
+ -EEXIST, /* I40E_AQ_RC_EEXIST */
+ -EINVAL, /* I40E_AQ_RC_EINVAL */
+ -ENOTTY, /* I40E_AQ_RC_ENOTTY */
+ -ENOSPC, /* I40E_AQ_RC_ENOSPC */
+ -ENOSYS, /* I40E_AQ_RC_ENOSYS */
+ -ERANGE, /* I40E_AQ_RC_ERANGE */
+ -EPIPE, /* I40E_AQ_RC_EFLUSHED */
+ -ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
+ -EROFS, /* I40E_AQ_RC_EMODE */
+ -EFBIG, /* I40E_AQ_RC_EFBIG */
+ };
+
+ /* aq_rc is invalid if AQ timed out */
+ if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT)
+ return -EAGAIN;
+
+ if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))))
+ return -ERANGE;
+
+ return aq_to_posix[aq_rc];
+}
+
+/* general information */
+#define I40E_AQ_LARGE_BUF 512
+#define I40E_ASQ_CMD_TIMEOUT 250000 /* usecs */
+
+void i40evf_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
+ u16 opcode);
+
+#endif /* _I40E_ADMINQ_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/iavf/i40e_adminq_cmd.h
new file mode 100644
index 000000000000..493bdc5331f7
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_adminq_cmd.h
@@ -0,0 +1,528 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_ADMINQ_CMD_H_
+#define _I40E_ADMINQ_CMD_H_
+
+/* This header file defines the i40e Admin Queue commands and is shared between
+ * i40e Firmware and Software.
+ *
+ * This file needs to comply with the Linux Kernel coding style.
+ */
+
+#define I40E_FW_API_VERSION_MAJOR 0x0001
+#define I40E_FW_API_VERSION_MINOR_X722 0x0005
+#define I40E_FW_API_VERSION_MINOR_X710 0x0007
+
+#define I40E_FW_MINOR_VERSION(_h) ((_h)->mac.type == I40E_MAC_XL710 ? \
+ I40E_FW_API_VERSION_MINOR_X710 : \
+ I40E_FW_API_VERSION_MINOR_X722)
+
+/* API version 1.7 implements additional link and PHY-specific APIs */
+#define I40E_MINOR_VER_GET_LINK_INFO_XL710 0x0007
+
+struct i40e_aq_desc {
+ __le16 flags;
+ __le16 opcode;
+ __le16 datalen;
+ __le16 retval;
+ __le32 cookie_high;
+ __le32 cookie_low;
+ union {
+ struct {
+ __le32 param0;
+ __le32 param1;
+ __le32 param2;
+ __le32 param3;
+ } internal;
+ struct {
+ __le32 param0;
+ __le32 param1;
+ __le32 addr_high;
+ __le32 addr_low;
+ } external;
+ u8 raw[16];
+ } params;
+};
+
+/* Flags sub-structure
+ * |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |
+ * |DD |CMP|ERR|VFE| * * RESERVED * * |LB |RD |VFC|BUF|SI |EI |FE |
+ */
+
+/* command flags and offsets*/
+#define I40E_AQ_FLAG_DD_SHIFT 0
+#define I40E_AQ_FLAG_CMP_SHIFT 1
+#define I40E_AQ_FLAG_ERR_SHIFT 2
+#define I40E_AQ_FLAG_VFE_SHIFT 3
+#define I40E_AQ_FLAG_LB_SHIFT 9
+#define I40E_AQ_FLAG_RD_SHIFT 10
+#define I40E_AQ_FLAG_VFC_SHIFT 11
+#define I40E_AQ_FLAG_BUF_SHIFT 12
+#define I40E_AQ_FLAG_SI_SHIFT 13
+#define I40E_AQ_FLAG_EI_SHIFT 14
+#define I40E_AQ_FLAG_FE_SHIFT 15
+
+#define I40E_AQ_FLAG_DD BIT(I40E_AQ_FLAG_DD_SHIFT) /* 0x1 */
+#define I40E_AQ_FLAG_CMP BIT(I40E_AQ_FLAG_CMP_SHIFT) /* 0x2 */
+#define I40E_AQ_FLAG_ERR BIT(I40E_AQ_FLAG_ERR_SHIFT) /* 0x4 */
+#define I40E_AQ_FLAG_VFE BIT(I40E_AQ_FLAG_VFE_SHIFT) /* 0x8 */
+#define I40E_AQ_FLAG_LB BIT(I40E_AQ_FLAG_LB_SHIFT) /* 0x200 */
+#define I40E_AQ_FLAG_RD BIT(I40E_AQ_FLAG_RD_SHIFT) /* 0x400 */
+#define I40E_AQ_FLAG_VFC BIT(I40E_AQ_FLAG_VFC_SHIFT) /* 0x800 */
+#define I40E_AQ_FLAG_BUF BIT(I40E_AQ_FLAG_BUF_SHIFT) /* 0x1000 */
+#define I40E_AQ_FLAG_SI BIT(I40E_AQ_FLAG_SI_SHIFT) /* 0x2000 */
+#define I40E_AQ_FLAG_EI BIT(I40E_AQ_FLAG_EI_SHIFT) /* 0x4000 */
+#define I40E_AQ_FLAG_FE BIT(I40E_AQ_FLAG_FE_SHIFT) /* 0x8000 */
+
+/* error codes */
+enum i40e_admin_queue_err {
+ I40E_AQ_RC_OK = 0, /* success */
+ I40E_AQ_RC_EPERM = 1, /* Operation not permitted */
+ I40E_AQ_RC_ENOENT = 2, /* No such element */
+ I40E_AQ_RC_ESRCH = 3, /* Bad opcode */
+ I40E_AQ_RC_EINTR = 4, /* operation interrupted */
+ I40E_AQ_RC_EIO = 5, /* I/O error */
+ I40E_AQ_RC_ENXIO = 6, /* No such resource */
+ I40E_AQ_RC_E2BIG = 7, /* Arg too long */
+ I40E_AQ_RC_EAGAIN = 8, /* Try again */
+ I40E_AQ_RC_ENOMEM = 9, /* Out of memory */
+ I40E_AQ_RC_EACCES = 10, /* Permission denied */
+ I40E_AQ_RC_EFAULT = 11, /* Bad address */
+ I40E_AQ_RC_EBUSY = 12, /* Device or resource busy */
+ I40E_AQ_RC_EEXIST = 13, /* object already exists */
+ I40E_AQ_RC_EINVAL = 14, /* Invalid argument */
+ I40E_AQ_RC_ENOTTY = 15, /* Not a typewriter */
+ I40E_AQ_RC_ENOSPC = 16, /* No space left or alloc failure */
+ I40E_AQ_RC_ENOSYS = 17, /* Function not implemented */
+ I40E_AQ_RC_ERANGE = 18, /* Parameter out of range */
+ I40E_AQ_RC_EFLUSHED = 19, /* Cmd flushed due to prev cmd error */
+ I40E_AQ_RC_BAD_ADDR = 20, /* Descriptor contains a bad pointer */
+ I40E_AQ_RC_EMODE = 21, /* Op not allowed in current dev mode */
+ I40E_AQ_RC_EFBIG = 22, /* File too large */
+};
+
+/* Admin Queue command opcodes */
+enum i40e_admin_queue_opc {
+ /* aq commands */
+ i40e_aqc_opc_get_version = 0x0001,
+ i40e_aqc_opc_driver_version = 0x0002,
+ i40e_aqc_opc_queue_shutdown = 0x0003,
+ i40e_aqc_opc_set_pf_context = 0x0004,
+
+ /* resource ownership */
+ i40e_aqc_opc_request_resource = 0x0008,
+ i40e_aqc_opc_release_resource = 0x0009,
+
+ i40e_aqc_opc_list_func_capabilities = 0x000A,
+ i40e_aqc_opc_list_dev_capabilities = 0x000B,
+
+ /* Proxy commands */
+ i40e_aqc_opc_set_proxy_config = 0x0104,
+ i40e_aqc_opc_set_ns_proxy_table_entry = 0x0105,
+
+ /* LAA */
+ i40e_aqc_opc_mac_address_read = 0x0107,
+ i40e_aqc_opc_mac_address_write = 0x0108,
+
+ /* PXE */
+ i40e_aqc_opc_clear_pxe_mode = 0x0110,
+
+ /* WoL commands */
+ i40e_aqc_opc_set_wol_filter = 0x0120,
+ i40e_aqc_opc_get_wake_reason = 0x0121,
+
+ /* internal switch commands */
+ i40e_aqc_opc_get_switch_config = 0x0200,
+ i40e_aqc_opc_add_statistics = 0x0201,
+ i40e_aqc_opc_remove_statistics = 0x0202,
+ i40e_aqc_opc_set_port_parameters = 0x0203,
+ i40e_aqc_opc_get_switch_resource_alloc = 0x0204,
+ i40e_aqc_opc_set_switch_config = 0x0205,
+ i40e_aqc_opc_rx_ctl_reg_read = 0x0206,
+ i40e_aqc_opc_rx_ctl_reg_write = 0x0207,
+
+ i40e_aqc_opc_add_vsi = 0x0210,
+ i40e_aqc_opc_update_vsi_parameters = 0x0211,
+ i40e_aqc_opc_get_vsi_parameters = 0x0212,
+
+ i40e_aqc_opc_add_pv = 0x0220,
+ i40e_aqc_opc_update_pv_parameters = 0x0221,
+ i40e_aqc_opc_get_pv_parameters = 0x0222,
+
+ i40e_aqc_opc_add_veb = 0x0230,
+ i40e_aqc_opc_update_veb_parameters = 0x0231,
+ i40e_aqc_opc_get_veb_parameters = 0x0232,
+
+ i40e_aqc_opc_delete_element = 0x0243,
+
+ i40e_aqc_opc_add_macvlan = 0x0250,
+ i40e_aqc_opc_remove_macvlan = 0x0251,
+ i40e_aqc_opc_add_vlan = 0x0252,
+ i40e_aqc_opc_remove_vlan = 0x0253,
+ i40e_aqc_opc_set_vsi_promiscuous_modes = 0x0254,
+ i40e_aqc_opc_add_tag = 0x0255,
+ i40e_aqc_opc_remove_tag = 0x0256,
+ i40e_aqc_opc_add_multicast_etag = 0x0257,
+ i40e_aqc_opc_remove_multicast_etag = 0x0258,
+ i40e_aqc_opc_update_tag = 0x0259,
+ i40e_aqc_opc_add_control_packet_filter = 0x025A,
+ i40e_aqc_opc_remove_control_packet_filter = 0x025B,
+ i40e_aqc_opc_add_cloud_filters = 0x025C,
+ i40e_aqc_opc_remove_cloud_filters = 0x025D,
+ i40e_aqc_opc_clear_wol_switch_filters = 0x025E,
+
+ i40e_aqc_opc_add_mirror_rule = 0x0260,
+ i40e_aqc_opc_delete_mirror_rule = 0x0261,
+
+ /* Dynamic Device Personalization */
+ i40e_aqc_opc_write_personalization_profile = 0x0270,
+ i40e_aqc_opc_get_personalization_profile_list = 0x0271,
+
+ /* DCB commands */
+ i40e_aqc_opc_dcb_ignore_pfc = 0x0301,
+ i40e_aqc_opc_dcb_updated = 0x0302,
+ i40e_aqc_opc_set_dcb_parameters = 0x0303,
+
+ /* TX scheduler */
+ i40e_aqc_opc_configure_vsi_bw_limit = 0x0400,
+ i40e_aqc_opc_configure_vsi_ets_sla_bw_limit = 0x0406,
+ i40e_aqc_opc_configure_vsi_tc_bw = 0x0407,
+ i40e_aqc_opc_query_vsi_bw_config = 0x0408,
+ i40e_aqc_opc_query_vsi_ets_sla_config = 0x040A,
+ i40e_aqc_opc_configure_switching_comp_bw_limit = 0x0410,
+
+ i40e_aqc_opc_enable_switching_comp_ets = 0x0413,
+ i40e_aqc_opc_modify_switching_comp_ets = 0x0414,
+ i40e_aqc_opc_disable_switching_comp_ets = 0x0415,
+ i40e_aqc_opc_configure_switching_comp_ets_bw_limit = 0x0416,
+ i40e_aqc_opc_configure_switching_comp_bw_config = 0x0417,
+ i40e_aqc_opc_query_switching_comp_ets_config = 0x0418,
+ i40e_aqc_opc_query_port_ets_config = 0x0419,
+ i40e_aqc_opc_query_switching_comp_bw_config = 0x041A,
+ i40e_aqc_opc_suspend_port_tx = 0x041B,
+ i40e_aqc_opc_resume_port_tx = 0x041C,
+ i40e_aqc_opc_configure_partition_bw = 0x041D,
+ /* hmc */
+ i40e_aqc_opc_query_hmc_resource_profile = 0x0500,
+ i40e_aqc_opc_set_hmc_resource_profile = 0x0501,
+
+ /* phy commands*/
+ i40e_aqc_opc_get_phy_abilities = 0x0600,
+ i40e_aqc_opc_set_phy_config = 0x0601,
+ i40e_aqc_opc_set_mac_config = 0x0603,
+ i40e_aqc_opc_set_link_restart_an = 0x0605,
+ i40e_aqc_opc_get_link_status = 0x0607,
+ i40e_aqc_opc_set_phy_int_mask = 0x0613,
+ i40e_aqc_opc_get_local_advt_reg = 0x0614,
+ i40e_aqc_opc_set_local_advt_reg = 0x0615,
+ i40e_aqc_opc_get_partner_advt = 0x0616,
+ i40e_aqc_opc_set_lb_modes = 0x0618,
+ i40e_aqc_opc_get_phy_wol_caps = 0x0621,
+ i40e_aqc_opc_set_phy_debug = 0x0622,
+ i40e_aqc_opc_upload_ext_phy_fm = 0x0625,
+ i40e_aqc_opc_run_phy_activity = 0x0626,
+ i40e_aqc_opc_set_phy_register = 0x0628,
+ i40e_aqc_opc_get_phy_register = 0x0629,
+
+ /* NVM commands */
+ i40e_aqc_opc_nvm_read = 0x0701,
+ i40e_aqc_opc_nvm_erase = 0x0702,
+ i40e_aqc_opc_nvm_update = 0x0703,
+ i40e_aqc_opc_nvm_config_read = 0x0704,
+ i40e_aqc_opc_nvm_config_write = 0x0705,
+ i40e_aqc_opc_oem_post_update = 0x0720,
+ i40e_aqc_opc_thermal_sensor = 0x0721,
+
+ /* virtualization commands */
+ i40e_aqc_opc_send_msg_to_pf = 0x0801,
+ i40e_aqc_opc_send_msg_to_vf = 0x0802,
+ i40e_aqc_opc_send_msg_to_peer = 0x0803,
+
+ /* alternate structure */
+ i40e_aqc_opc_alternate_write = 0x0900,
+ i40e_aqc_opc_alternate_write_indirect = 0x0901,
+ i40e_aqc_opc_alternate_read = 0x0902,
+ i40e_aqc_opc_alternate_read_indirect = 0x0903,
+ i40e_aqc_opc_alternate_write_done = 0x0904,
+ i40e_aqc_opc_alternate_set_mode = 0x0905,
+ i40e_aqc_opc_alternate_clear_port = 0x0906,
+
+ /* LLDP commands */
+ i40e_aqc_opc_lldp_get_mib = 0x0A00,
+ i40e_aqc_opc_lldp_update_mib = 0x0A01,
+ i40e_aqc_opc_lldp_add_tlv = 0x0A02,
+ i40e_aqc_opc_lldp_update_tlv = 0x0A03,
+ i40e_aqc_opc_lldp_delete_tlv = 0x0A04,
+ i40e_aqc_opc_lldp_stop = 0x0A05,
+ i40e_aqc_opc_lldp_start = 0x0A06,
+
+ /* Tunnel commands */
+ i40e_aqc_opc_add_udp_tunnel = 0x0B00,
+ i40e_aqc_opc_del_udp_tunnel = 0x0B01,
+ i40e_aqc_opc_set_rss_key = 0x0B02,
+ i40e_aqc_opc_set_rss_lut = 0x0B03,
+ i40e_aqc_opc_get_rss_key = 0x0B04,
+ i40e_aqc_opc_get_rss_lut = 0x0B05,
+
+ /* Async Events */
+ i40e_aqc_opc_event_lan_overflow = 0x1001,
+
+ /* OEM commands */
+ i40e_aqc_opc_oem_parameter_change = 0xFE00,
+ i40e_aqc_opc_oem_device_status_change = 0xFE01,
+ i40e_aqc_opc_oem_ocsd_initialize = 0xFE02,
+ i40e_aqc_opc_oem_ocbb_initialize = 0xFE03,
+
+ /* debug commands */
+ i40e_aqc_opc_debug_read_reg = 0xFF03,
+ i40e_aqc_opc_debug_write_reg = 0xFF04,
+ i40e_aqc_opc_debug_modify_reg = 0xFF07,
+ i40e_aqc_opc_debug_dump_internals = 0xFF08,
+};
+
+/* command structures and indirect data structures */
+
+/* Structure naming conventions:
+ * - no suffix for direct command descriptor structures
+ * - _data for indirect sent data
+ * - _resp for indirect return data (data which is both will use _data)
+ * - _completion for direct return data
+ * - _element_ for repeated elements (may also be _data or _resp)
+ *
+ * Command structures are expected to overlay the params.raw member of the basic
+ * descriptor, and as such cannot exceed 16 bytes in length.
+ */
+
+/* This macro is used to generate a compilation error if a structure
+ * is not exactly the correct length. It gives a divide by zero error if the
+ * structure is not of the correct size, otherwise it creates an enum that is
+ * never used.
+ */
+#define I40E_CHECK_STRUCT_LEN(n, X) enum i40e_static_assert_enum_##X \
+ { i40e_static_assert_##X = (n)/((sizeof(struct X) == (n)) ? 1 : 0) }
+
+/* This macro is used extensively to ensure that command structures are 16
+ * bytes in length as they have to map to the raw array of that size.
+ */
+#define I40E_CHECK_CMD_LENGTH(X) I40E_CHECK_STRUCT_LEN(16, X)
+
+/* Queue Shutdown (direct 0x0003) */
+struct i40e_aqc_queue_shutdown {
+ __le32 driver_unloading;
+#define I40E_AQ_DRIVER_UNLOADING 0x1
+ u8 reserved[12];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_queue_shutdown);
+
+struct i40e_aqc_vsi_properties_data {
+ /* first 96 byte are written by SW */
+ __le16 valid_sections;
+#define I40E_AQ_VSI_PROP_SWITCH_VALID 0x0001
+#define I40E_AQ_VSI_PROP_SECURITY_VALID 0x0002
+#define I40E_AQ_VSI_PROP_VLAN_VALID 0x0004
+#define I40E_AQ_VSI_PROP_CAS_PV_VALID 0x0008
+#define I40E_AQ_VSI_PROP_INGRESS_UP_VALID 0x0010
+#define I40E_AQ_VSI_PROP_EGRESS_UP_VALID 0x0020
+#define I40E_AQ_VSI_PROP_QUEUE_MAP_VALID 0x0040
+#define I40E_AQ_VSI_PROP_QUEUE_OPT_VALID 0x0080
+#define I40E_AQ_VSI_PROP_OUTER_UP_VALID 0x0100
+#define I40E_AQ_VSI_PROP_SCHED_VALID 0x0200
+ /* switch section */
+ __le16 switch_id; /* 12bit id combined with flags below */
+#define I40E_AQ_VSI_SW_ID_SHIFT 0x0000
+#define I40E_AQ_VSI_SW_ID_MASK (0xFFF << I40E_AQ_VSI_SW_ID_SHIFT)
+#define I40E_AQ_VSI_SW_ID_FLAG_NOT_STAG 0x1000
+#define I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB 0x2000
+#define I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB 0x4000
+ u8 sw_reserved[2];
+ /* security section */
+ u8 sec_flags;
+#define I40E_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD 0x01
+#define I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK 0x02
+#define I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK 0x04
+ u8 sec_reserved;
+ /* VLAN section */
+ __le16 pvid; /* VLANS include priority bits */
+ __le16 fcoe_pvid;
+ u8 port_vlan_flags;
+#define I40E_AQ_VSI_PVLAN_MODE_SHIFT 0x00
+#define I40E_AQ_VSI_PVLAN_MODE_MASK (0x03 << \
+ I40E_AQ_VSI_PVLAN_MODE_SHIFT)
+#define I40E_AQ_VSI_PVLAN_MODE_TAGGED 0x01
+#define I40E_AQ_VSI_PVLAN_MODE_UNTAGGED 0x02
+#define I40E_AQ_VSI_PVLAN_MODE_ALL 0x03
+#define I40E_AQ_VSI_PVLAN_INSERT_PVID 0x04
+#define I40E_AQ_VSI_PVLAN_EMOD_SHIFT 0x03
+#define I40E_AQ_VSI_PVLAN_EMOD_MASK (0x3 << \
+ I40E_AQ_VSI_PVLAN_EMOD_SHIFT)
+#define I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH 0x0
+#define I40E_AQ_VSI_PVLAN_EMOD_STR_UP 0x08
+#define I40E_AQ_VSI_PVLAN_EMOD_STR 0x10
+#define I40E_AQ_VSI_PVLAN_EMOD_NOTHING 0x18
+ u8 pvlan_reserved[3];
+ /* ingress egress up sections */
+ __le32 ingress_table; /* bitmap, 3 bits per up */
+#define I40E_AQ_VSI_UP_TABLE_UP0_SHIFT 0
+#define I40E_AQ_VSI_UP_TABLE_UP0_MASK (0x7 << \
+ I40E_AQ_VSI_UP_TABLE_UP0_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP1_SHIFT 3
+#define I40E_AQ_VSI_UP_TABLE_UP1_MASK (0x7 << \
+ I40E_AQ_VSI_UP_TABLE_UP1_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP2_SHIFT 6
+#define I40E_AQ_VSI_UP_TABLE_UP2_MASK (0x7 << \
+ I40E_AQ_VSI_UP_TABLE_UP2_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP3_SHIFT 9
+#define I40E_AQ_VSI_UP_TABLE_UP3_MASK (0x7 << \
+ I40E_AQ_VSI_UP_TABLE_UP3_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP4_SHIFT 12
+#define I40E_AQ_VSI_UP_TABLE_UP4_MASK (0x7 << \
+ I40E_AQ_VSI_UP_TABLE_UP4_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP5_SHIFT 15
+#define I40E_AQ_VSI_UP_TABLE_UP5_MASK (0x7 << \
+ I40E_AQ_VSI_UP_TABLE_UP5_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP6_SHIFT 18
+#define I40E_AQ_VSI_UP_TABLE_UP6_MASK (0x7 << \
+ I40E_AQ_VSI_UP_TABLE_UP6_SHIFT)
+#define I40E_AQ_VSI_UP_TABLE_UP7_SHIFT 21
+#define I40E_AQ_VSI_UP_TABLE_UP7_MASK (0x7 << \
+ I40E_AQ_VSI_UP_TABLE_UP7_SHIFT)
+ __le32 egress_table; /* same defines as for ingress table */
+ /* cascaded PV section */
+ __le16 cas_pv_tag;
+ u8 cas_pv_flags;
+#define I40E_AQ_VSI_CAS_PV_TAGX_SHIFT 0x00
+#define I40E_AQ_VSI_CAS_PV_TAGX_MASK (0x03 << \
+ I40E_AQ_VSI_CAS_PV_TAGX_SHIFT)
+#define I40E_AQ_VSI_CAS_PV_TAGX_LEAVE 0x00
+#define I40E_AQ_VSI_CAS_PV_TAGX_REMOVE 0x01
+#define I40E_AQ_VSI_CAS_PV_TAGX_COPY 0x02
+#define I40E_AQ_VSI_CAS_PV_INSERT_TAG 0x10
+#define I40E_AQ_VSI_CAS_PV_ETAG_PRUNE 0x20
+#define I40E_AQ_VSI_CAS_PV_ACCEPT_HOST_TAG 0x40
+ u8 cas_pv_reserved;
+ /* queue mapping section */
+ __le16 mapping_flags;
+#define I40E_AQ_VSI_QUE_MAP_CONTIG 0x0
+#define I40E_AQ_VSI_QUE_MAP_NONCONTIG 0x1
+ __le16 queue_mapping[16];
+#define I40E_AQ_VSI_QUEUE_SHIFT 0x0
+#define I40E_AQ_VSI_QUEUE_MASK (0x7FF << I40E_AQ_VSI_QUEUE_SHIFT)
+ __le16 tc_mapping[8];
+#define I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT 0
+#define I40E_AQ_VSI_TC_QUE_OFFSET_MASK (0x1FF << \
+ I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT)
+#define I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT 9
+#define I40E_AQ_VSI_TC_QUE_NUMBER_MASK (0x7 << \
+ I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT)
+ /* queueing option section */
+ u8 queueing_opt_flags;
+#define I40E_AQ_VSI_QUE_OPT_MULTICAST_UDP_ENA 0x04
+#define I40E_AQ_VSI_QUE_OPT_UNICAST_UDP_ENA 0x08
+#define I40E_AQ_VSI_QUE_OPT_TCP_ENA 0x10
+#define I40E_AQ_VSI_QUE_OPT_FCOE_ENA 0x20
+#define I40E_AQ_VSI_QUE_OPT_RSS_LUT_PF 0x00
+#define I40E_AQ_VSI_QUE_OPT_RSS_LUT_VSI 0x40
+ u8 queueing_opt_reserved[3];
+ /* scheduler section */
+ u8 up_enable_bits;
+ u8 sched_reserved;
+ /* outer up section */
+ __le32 outer_up_table; /* same structure and defines as ingress tbl */
+ u8 cmd_reserved[8];
+ /* last 32 bytes are written by FW */
+ __le16 qs_handle[8];
+#define I40E_AQ_VSI_QS_HANDLE_INVALID 0xFFFF
+ __le16 stat_counter_idx;
+ __le16 sched_id;
+ u8 resp_reserved[12];
+};
+
+I40E_CHECK_STRUCT_LEN(128, i40e_aqc_vsi_properties_data);
+
+/* Get VEB Parameters (direct 0x0232)
+ * uses i40e_aqc_switch_seid for the descriptor
+ */
+struct i40e_aqc_get_veb_parameters_completion {
+ __le16 seid;
+ __le16 switch_id;
+ __le16 veb_flags; /* only the first/last flags from 0x0230 is valid */
+ __le16 statistic_index;
+ __le16 vebs_used;
+ __le16 vebs_free;
+ u8 reserved[4];
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_get_veb_parameters_completion);
+
+#define I40E_LINK_SPEED_100MB_SHIFT 0x1
+#define I40E_LINK_SPEED_1000MB_SHIFT 0x2
+#define I40E_LINK_SPEED_10GB_SHIFT 0x3
+#define I40E_LINK_SPEED_40GB_SHIFT 0x4
+#define I40E_LINK_SPEED_20GB_SHIFT 0x5
+#define I40E_LINK_SPEED_25GB_SHIFT 0x6
+
+enum i40e_aq_link_speed {
+ I40E_LINK_SPEED_UNKNOWN = 0,
+ I40E_LINK_SPEED_100MB = BIT(I40E_LINK_SPEED_100MB_SHIFT),
+ I40E_LINK_SPEED_1GB = BIT(I40E_LINK_SPEED_1000MB_SHIFT),
+ I40E_LINK_SPEED_10GB = BIT(I40E_LINK_SPEED_10GB_SHIFT),
+ I40E_LINK_SPEED_40GB = BIT(I40E_LINK_SPEED_40GB_SHIFT),
+ I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT),
+ I40E_LINK_SPEED_25GB = BIT(I40E_LINK_SPEED_25GB_SHIFT),
+};
+
+/* Send to PF command (indirect 0x0801) id is only used by PF
+ * Send to VF command (indirect 0x0802) id is only used by PF
+ * Send to Peer PF command (indirect 0x0803)
+ */
+struct i40e_aqc_pf_vf_message {
+ __le32 id;
+ u8 reserved[4];
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_pf_vf_message);
+
+struct i40e_aqc_get_set_rss_key {
+#define I40E_AQC_SET_RSS_KEY_VSI_VALID BIT(15)
+#define I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT 0
+#define I40E_AQC_SET_RSS_KEY_VSI_ID_MASK (0x3FF << \
+ I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT)
+ __le16 vsi_id;
+ u8 reserved[6];
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_get_set_rss_key);
+
+struct i40e_aqc_get_set_rss_key_data {
+ u8 standard_rss_key[0x28];
+ u8 extended_hash_key[0xc];
+};
+
+I40E_CHECK_STRUCT_LEN(0x34, i40e_aqc_get_set_rss_key_data);
+
+struct i40e_aqc_get_set_rss_lut {
+#define I40E_AQC_SET_RSS_LUT_VSI_VALID BIT(15)
+#define I40E_AQC_SET_RSS_LUT_VSI_ID_SHIFT 0
+#define I40E_AQC_SET_RSS_LUT_VSI_ID_MASK (0x3FF << \
+ I40E_AQC_SET_RSS_LUT_VSI_ID_SHIFT)
+ __le16 vsi_id;
+#define I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT 0
+#define I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK \
+ BIT(I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT)
+
+#define I40E_AQC_SET_RSS_LUT_TABLE_TYPE_VSI 0
+#define I40E_AQC_SET_RSS_LUT_TABLE_TYPE_PF 1
+ __le16 flags;
+ u8 reserved[4];
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+I40E_CHECK_CMD_LENGTH(i40e_aqc_get_set_rss_lut);
+#endif /* _I40E_ADMINQ_CMD_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40e_alloc.h b/drivers/net/ethernet/intel/iavf/i40e_alloc.h
new file mode 100644
index 000000000000..cb8689222c8b
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_alloc.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_ALLOC_H_
+#define _I40E_ALLOC_H_
+
+struct i40e_hw;
+
+/* Memory allocation types */
+enum i40e_memory_type {
+ i40e_mem_arq_buf = 0, /* ARQ indirect command buffer */
+ i40e_mem_asq_buf = 1,
+ i40e_mem_atq_buf = 2, /* ATQ indirect command buffer */
+ i40e_mem_arq_ring = 3, /* ARQ descriptor ring */
+ i40e_mem_atq_ring = 4, /* ATQ descriptor ring */
+ i40e_mem_pd = 5, /* Page Descriptor */
+ i40e_mem_bp = 6, /* Backing Page - 4KB */
+ i40e_mem_bp_jumbo = 7, /* Backing Page - > 4KB */
+ i40e_mem_reserved
+};
+
+/* prototype for functions used for dynamic memory allocation */
+i40e_status i40e_allocate_dma_mem(struct i40e_hw *hw,
+ struct i40e_dma_mem *mem,
+ enum i40e_memory_type type,
+ u64 size, u32 alignment);
+i40e_status i40e_free_dma_mem(struct i40e_hw *hw,
+ struct i40e_dma_mem *mem);
+i40e_status i40e_allocate_virt_mem(struct i40e_hw *hw,
+ struct i40e_virt_mem *mem,
+ u32 size);
+i40e_status i40e_free_virt_mem(struct i40e_hw *hw,
+ struct i40e_virt_mem *mem);
+
+#endif /* _I40E_ALLOC_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40e_common.c b/drivers/net/ethernet/intel/iavf/i40e_common.c
new file mode 100644
index 000000000000..f34091d96f49
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_common.c
@@ -0,0 +1,982 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#include "i40e_type.h"
+#include "i40e_adminq.h"
+#include "i40e_prototype.h"
+#include <linux/avf/virtchnl.h>
+
+/**
+ * i40e_set_mac_type - Sets MAC type
+ * @hw: pointer to the HW structure
+ *
+ * This function sets the mac type of the adapter based on the
+ * vendor ID and device ID stored in the hw structure.
+ **/
+i40e_status i40e_set_mac_type(struct i40e_hw *hw)
+{
+ i40e_status status = 0;
+
+ if (hw->vendor_id == PCI_VENDOR_ID_INTEL) {
+ switch (hw->device_id) {
+ case I40E_DEV_ID_SFP_XL710:
+ case I40E_DEV_ID_QEMU:
+ case I40E_DEV_ID_KX_B:
+ case I40E_DEV_ID_KX_C:
+ case I40E_DEV_ID_QSFP_A:
+ case I40E_DEV_ID_QSFP_B:
+ case I40E_DEV_ID_QSFP_C:
+ case I40E_DEV_ID_10G_BASE_T:
+ case I40E_DEV_ID_10G_BASE_T4:
+ case I40E_DEV_ID_20G_KR2:
+ case I40E_DEV_ID_20G_KR2_A:
+ case I40E_DEV_ID_25G_B:
+ case I40E_DEV_ID_25G_SFP28:
+ hw->mac.type = I40E_MAC_XL710;
+ break;
+ case I40E_DEV_ID_SFP_X722:
+ case I40E_DEV_ID_1G_BASE_T_X722:
+ case I40E_DEV_ID_10G_BASE_T_X722:
+ case I40E_DEV_ID_SFP_I_X722:
+ hw->mac.type = I40E_MAC_X722;
+ break;
+ case I40E_DEV_ID_X722_VF:
+ hw->mac.type = I40E_MAC_X722_VF;
+ break;
+ case I40E_DEV_ID_VF:
+ case I40E_DEV_ID_VF_HV:
+ case I40E_DEV_ID_ADAPTIVE_VF:
+ hw->mac.type = I40E_MAC_VF;
+ break;
+ default:
+ hw->mac.type = I40E_MAC_GENERIC;
+ break;
+ }
+ } else {
+ status = I40E_ERR_DEVICE_NOT_SUPPORTED;
+ }
+
+ hw_dbg(hw, "i40e_set_mac_type found mac: %d, returns: %d\n",
+ hw->mac.type, status);
+ return status;
+}
+
+/**
+ * i40evf_aq_str - convert AQ err code to a string
+ * @hw: pointer to the HW structure
+ * @aq_err: the AQ error code to convert
+ **/
+const char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err)
+{
+ switch (aq_err) {
+ case I40E_AQ_RC_OK:
+ return "OK";
+ case I40E_AQ_RC_EPERM:
+ return "I40E_AQ_RC_EPERM";
+ case I40E_AQ_RC_ENOENT:
+ return "I40E_AQ_RC_ENOENT";
+ case I40E_AQ_RC_ESRCH:
+ return "I40E_AQ_RC_ESRCH";
+ case I40E_AQ_RC_EINTR:
+ return "I40E_AQ_RC_EINTR";
+ case I40E_AQ_RC_EIO:
+ return "I40E_AQ_RC_EIO";
+ case I40E_AQ_RC_ENXIO:
+ return "I40E_AQ_RC_ENXIO";
+ case I40E_AQ_RC_E2BIG:
+ return "I40E_AQ_RC_E2BIG";
+ case I40E_AQ_RC_EAGAIN:
+ return "I40E_AQ_RC_EAGAIN";
+ case I40E_AQ_RC_ENOMEM:
+ return "I40E_AQ_RC_ENOMEM";
+ case I40E_AQ_RC_EACCES:
+ return "I40E_AQ_RC_EACCES";
+ case I40E_AQ_RC_EFAULT:
+ return "I40E_AQ_RC_EFAULT";
+ case I40E_AQ_RC_EBUSY:
+ return "I40E_AQ_RC_EBUSY";
+ case I40E_AQ_RC_EEXIST:
+ return "I40E_AQ_RC_EEXIST";
+ case I40E_AQ_RC_EINVAL:
+ return "I40E_AQ_RC_EINVAL";
+ case I40E_AQ_RC_ENOTTY:
+ return "I40E_AQ_RC_ENOTTY";
+ case I40E_AQ_RC_ENOSPC:
+ return "I40E_AQ_RC_ENOSPC";
+ case I40E_AQ_RC_ENOSYS:
+ return "I40E_AQ_RC_ENOSYS";
+ case I40E_AQ_RC_ERANGE:
+ return "I40E_AQ_RC_ERANGE";
+ case I40E_AQ_RC_EFLUSHED:
+ return "I40E_AQ_RC_EFLUSHED";
+ case I40E_AQ_RC_BAD_ADDR:
+ return "I40E_AQ_RC_BAD_ADDR";
+ case I40E_AQ_RC_EMODE:
+ return "I40E_AQ_RC_EMODE";
+ case I40E_AQ_RC_EFBIG:
+ return "I40E_AQ_RC_EFBIG";
+ }
+
+ snprintf(hw->err_str, sizeof(hw->err_str), "%d", aq_err);
+ return hw->err_str;
+}
+
+/**
+ * i40evf_stat_str - convert status err code to a string
+ * @hw: pointer to the HW structure
+ * @stat_err: the status error code to convert
+ **/
+const char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err)
+{
+ switch (stat_err) {
+ case 0:
+ return "OK";
+ case I40E_ERR_NVM:
+ return "I40E_ERR_NVM";
+ case I40E_ERR_NVM_CHECKSUM:
+ return "I40E_ERR_NVM_CHECKSUM";
+ case I40E_ERR_PHY:
+ return "I40E_ERR_PHY";
+ case I40E_ERR_CONFIG:
+ return "I40E_ERR_CONFIG";
+ case I40E_ERR_PARAM:
+ return "I40E_ERR_PARAM";
+ case I40E_ERR_MAC_TYPE:
+ return "I40E_ERR_MAC_TYPE";
+ case I40E_ERR_UNKNOWN_PHY:
+ return "I40E_ERR_UNKNOWN_PHY";
+ case I40E_ERR_LINK_SETUP:
+ return "I40E_ERR_LINK_SETUP";
+ case I40E_ERR_ADAPTER_STOPPED:
+ return "I40E_ERR_ADAPTER_STOPPED";
+ case I40E_ERR_INVALID_MAC_ADDR:
+ return "I40E_ERR_INVALID_MAC_ADDR";
+ case I40E_ERR_DEVICE_NOT_SUPPORTED:
+ return "I40E_ERR_DEVICE_NOT_SUPPORTED";
+ case I40E_ERR_MASTER_REQUESTS_PENDING:
+ return "I40E_ERR_MASTER_REQUESTS_PENDING";
+ case I40E_ERR_INVALID_LINK_SETTINGS:
+ return "I40E_ERR_INVALID_LINK_SETTINGS";
+ case I40E_ERR_AUTONEG_NOT_COMPLETE:
+ return "I40E_ERR_AUTONEG_NOT_COMPLETE";
+ case I40E_ERR_RESET_FAILED:
+ return "I40E_ERR_RESET_FAILED";
+ case I40E_ERR_SWFW_SYNC:
+ return "I40E_ERR_SWFW_SYNC";
+ case I40E_ERR_NO_AVAILABLE_VSI:
+ return "I40E_ERR_NO_AVAILABLE_VSI";
+ case I40E_ERR_NO_MEMORY:
+ return "I40E_ERR_NO_MEMORY";
+ case I40E_ERR_BAD_PTR:
+ return "I40E_ERR_BAD_PTR";
+ case I40E_ERR_RING_FULL:
+ return "I40E_ERR_RING_FULL";
+ case I40E_ERR_INVALID_PD_ID:
+ return "I40E_ERR_INVALID_PD_ID";
+ case I40E_ERR_INVALID_QP_ID:
+ return "I40E_ERR_INVALID_QP_ID";
+ case I40E_ERR_INVALID_CQ_ID:
+ return "I40E_ERR_INVALID_CQ_ID";
+ case I40E_ERR_INVALID_CEQ_ID:
+ return "I40E_ERR_INVALID_CEQ_ID";
+ case I40E_ERR_INVALID_AEQ_ID:
+ return "I40E_ERR_INVALID_AEQ_ID";
+ case I40E_ERR_INVALID_SIZE:
+ return "I40E_ERR_INVALID_SIZE";
+ case I40E_ERR_INVALID_ARP_INDEX:
+ return "I40E_ERR_INVALID_ARP_INDEX";
+ case I40E_ERR_INVALID_FPM_FUNC_ID:
+ return "I40E_ERR_INVALID_FPM_FUNC_ID";
+ case I40E_ERR_QP_INVALID_MSG_SIZE:
+ return "I40E_ERR_QP_INVALID_MSG_SIZE";
+ case I40E_ERR_QP_TOOMANY_WRS_POSTED:
+ return "I40E_ERR_QP_TOOMANY_WRS_POSTED";
+ case I40E_ERR_INVALID_FRAG_COUNT:
+ return "I40E_ERR_INVALID_FRAG_COUNT";
+ case I40E_ERR_QUEUE_EMPTY:
+ return "I40E_ERR_QUEUE_EMPTY";
+ case I40E_ERR_INVALID_ALIGNMENT:
+ return "I40E_ERR_INVALID_ALIGNMENT";
+ case I40E_ERR_FLUSHED_QUEUE:
+ return "I40E_ERR_FLUSHED_QUEUE";
+ case I40E_ERR_INVALID_PUSH_PAGE_INDEX:
+ return "I40E_ERR_INVALID_PUSH_PAGE_INDEX";
+ case I40E_ERR_INVALID_IMM_DATA_SIZE:
+ return "I40E_ERR_INVALID_IMM_DATA_SIZE";
+ case I40E_ERR_TIMEOUT:
+ return "I40E_ERR_TIMEOUT";
+ case I40E_ERR_OPCODE_MISMATCH:
+ return "I40E_ERR_OPCODE_MISMATCH";
+ case I40E_ERR_CQP_COMPL_ERROR:
+ return "I40E_ERR_CQP_COMPL_ERROR";
+ case I40E_ERR_INVALID_VF_ID:
+ return "I40E_ERR_INVALID_VF_ID";
+ case I40E_ERR_INVALID_HMCFN_ID:
+ return "I40E_ERR_INVALID_HMCFN_ID";
+ case I40E_ERR_BACKING_PAGE_ERROR:
+ return "I40E_ERR_BACKING_PAGE_ERROR";
+ case I40E_ERR_NO_PBLCHUNKS_AVAILABLE:
+ return "I40E_ERR_NO_PBLCHUNKS_AVAILABLE";
+ case I40E_ERR_INVALID_PBLE_INDEX:
+ return "I40E_ERR_INVALID_PBLE_INDEX";
+ case I40E_ERR_INVALID_SD_INDEX:
+ return "I40E_ERR_INVALID_SD_INDEX";
+ case I40E_ERR_INVALID_PAGE_DESC_INDEX:
+ return "I40E_ERR_INVALID_PAGE_DESC_INDEX";
+ case I40E_ERR_INVALID_SD_TYPE:
+ return "I40E_ERR_INVALID_SD_TYPE";
+ case I40E_ERR_MEMCPY_FAILED:
+ return "I40E_ERR_MEMCPY_FAILED";
+ case I40E_ERR_INVALID_HMC_OBJ_INDEX:
+ return "I40E_ERR_INVALID_HMC_OBJ_INDEX";
+ case I40E_ERR_INVALID_HMC_OBJ_COUNT:
+ return "I40E_ERR_INVALID_HMC_OBJ_COUNT";
+ case I40E_ERR_INVALID_SRQ_ARM_LIMIT:
+ return "I40E_ERR_INVALID_SRQ_ARM_LIMIT";
+ case I40E_ERR_SRQ_ENABLED:
+ return "I40E_ERR_SRQ_ENABLED";
+ case I40E_ERR_ADMIN_QUEUE_ERROR:
+ return "I40E_ERR_ADMIN_QUEUE_ERROR";
+ case I40E_ERR_ADMIN_QUEUE_TIMEOUT:
+ return "I40E_ERR_ADMIN_QUEUE_TIMEOUT";
+ case I40E_ERR_BUF_TOO_SHORT:
+ return "I40E_ERR_BUF_TOO_SHORT";
+ case I40E_ERR_ADMIN_QUEUE_FULL:
+ return "I40E_ERR_ADMIN_QUEUE_FULL";
+ case I40E_ERR_ADMIN_QUEUE_NO_WORK:
+ return "I40E_ERR_ADMIN_QUEUE_NO_WORK";
+ case I40E_ERR_BAD_IWARP_CQE:
+ return "I40E_ERR_BAD_IWARP_CQE";
+ case I40E_ERR_NVM_BLANK_MODE:
+ return "I40E_ERR_NVM_BLANK_MODE";
+ case I40E_ERR_NOT_IMPLEMENTED:
+ return "I40E_ERR_NOT_IMPLEMENTED";
+ case I40E_ERR_PE_DOORBELL_NOT_ENABLED:
+ return "I40E_ERR_PE_DOORBELL_NOT_ENABLED";
+ case I40E_ERR_DIAG_TEST_FAILED:
+ return "I40E_ERR_DIAG_TEST_FAILED";
+ case I40E_ERR_NOT_READY:
+ return "I40E_ERR_NOT_READY";
+ case I40E_NOT_SUPPORTED:
+ return "I40E_NOT_SUPPORTED";
+ case I40E_ERR_FIRMWARE_API_VERSION:
+ return "I40E_ERR_FIRMWARE_API_VERSION";
+ case I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR:
+ return "I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR";
+ }
+
+ snprintf(hw->err_str, sizeof(hw->err_str), "%d", stat_err);
+ return hw->err_str;
+}
+
+/**
+ * i40evf_debug_aq
+ * @hw: debug mask related to admin queue
+ * @mask: debug mask
+ * @desc: pointer to admin queue descriptor
+ * @buffer: pointer to command buffer
+ * @buf_len: max length of buffer
+ *
+ * Dumps debug log about adminq command with descriptor contents.
+ **/
+void i40evf_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
+ void *buffer, u16 buf_len)
+{
+ struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc;
+ u8 *buf = (u8 *)buffer;
+
+ if ((!(mask & hw->debug_mask)) || (desc == NULL))
+ return;
+
+ i40e_debug(hw, mask,
+ "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
+ le16_to_cpu(aq_desc->opcode),
+ le16_to_cpu(aq_desc->flags),
+ le16_to_cpu(aq_desc->datalen),
+ le16_to_cpu(aq_desc->retval));
+ i40e_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n",
+ le32_to_cpu(aq_desc->cookie_high),
+ le32_to_cpu(aq_desc->cookie_low));
+ i40e_debug(hw, mask, "\tparam (0,1) 0x%08X 0x%08X\n",
+ le32_to_cpu(aq_desc->params.internal.param0),
+ le32_to_cpu(aq_desc->params.internal.param1));
+ i40e_debug(hw, mask, "\taddr (h,l) 0x%08X 0x%08X\n",
+ le32_to_cpu(aq_desc->params.external.addr_high),
+ le32_to_cpu(aq_desc->params.external.addr_low));
+
+ if ((buffer != NULL) && (aq_desc->datalen != 0)) {
+ u16 len = le16_to_cpu(aq_desc->datalen);
+
+ i40e_debug(hw, mask, "AQ CMD Buffer:\n");
+ if (buf_len < len)
+ len = buf_len;
+ /* write the full 16-byte chunks */
+ if (hw->debug_mask & mask) {
+ char prefix[27];
+
+ snprintf(prefix, sizeof(prefix),
+ "i40evf %02x:%02x.%x: \t0x",
+ hw->bus.bus_id,
+ hw->bus.device,
+ hw->bus.func);
+
+ print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET,
+ 16, 1, buf, len, false);
+ }
+ }
+}
+
+/**
+ * i40evf_check_asq_alive
+ * @hw: pointer to the hw struct
+ *
+ * Returns true if Queue is enabled else false.
+ **/
+bool i40evf_check_asq_alive(struct i40e_hw *hw)
+{
+ if (hw->aq.asq.len)
+ return !!(rd32(hw, hw->aq.asq.len) &
+ I40E_VF_ATQLEN1_ATQENABLE_MASK);
+ else
+ return false;
+}
+
+/**
+ * i40evf_aq_queue_shutdown
+ * @hw: pointer to the hw struct
+ * @unloading: is the driver unloading itself
+ *
+ * Tell the Firmware that we're shutting down the AdminQ and whether
+ * or not the driver is unloading as well.
+ **/
+i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw,
+ bool unloading)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_queue_shutdown *cmd =
+ (struct i40e_aqc_queue_shutdown *)&desc.params.raw;
+ i40e_status status;
+
+ i40evf_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_queue_shutdown);
+
+ if (unloading)
+ cmd->driver_unloading = cpu_to_le32(I40E_AQ_DRIVER_UNLOADING);
+ status = i40evf_asq_send_command(hw, &desc, NULL, 0, NULL);
+
+ return status;
+}
+
+/**
+ * i40e_aq_get_set_rss_lut
+ * @hw: pointer to the hardware structure
+ * @vsi_id: vsi fw index
+ * @pf_lut: for PF table set true, for VSI table set false
+ * @lut: pointer to the lut buffer provided by the caller
+ * @lut_size: size of the lut buffer
+ * @set: set true to set the table, false to get the table
+ *
+ * Internal function to get or set RSS look up table
+ **/
+static i40e_status i40e_aq_get_set_rss_lut(struct i40e_hw *hw,
+ u16 vsi_id, bool pf_lut,
+ u8 *lut, u16 lut_size,
+ bool set)
+{
+ i40e_status status;
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_get_set_rss_lut *cmd_resp =
+ (struct i40e_aqc_get_set_rss_lut *)&desc.params.raw;
+
+ if (set)
+ i40evf_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_set_rss_lut);
+ else
+ i40evf_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_get_rss_lut);
+
+ /* Indirect command */
+ desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
+ desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_RD);
+
+ cmd_resp->vsi_id =
+ cpu_to_le16((u16)((vsi_id <<
+ I40E_AQC_SET_RSS_LUT_VSI_ID_SHIFT) &
+ I40E_AQC_SET_RSS_LUT_VSI_ID_MASK));
+ cmd_resp->vsi_id |= cpu_to_le16((u16)I40E_AQC_SET_RSS_LUT_VSI_VALID);
+
+ if (pf_lut)
+ cmd_resp->flags |= cpu_to_le16((u16)
+ ((I40E_AQC_SET_RSS_LUT_TABLE_TYPE_PF <<
+ I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) &
+ I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK));
+ else
+ cmd_resp->flags |= cpu_to_le16((u16)
+ ((I40E_AQC_SET_RSS_LUT_TABLE_TYPE_VSI <<
+ I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) &
+ I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK));
+
+ status = i40evf_asq_send_command(hw, &desc, lut, lut_size, NULL);
+
+ return status;
+}
+
+/**
+ * i40evf_aq_get_rss_lut
+ * @hw: pointer to the hardware structure
+ * @vsi_id: vsi fw index
+ * @pf_lut: for PF table set true, for VSI table set false
+ * @lut: pointer to the lut buffer provided by the caller
+ * @lut_size: size of the lut buffer
+ *
+ * get the RSS lookup table, PF or VSI type
+ **/
+i40e_status i40evf_aq_get_rss_lut(struct i40e_hw *hw, u16 vsi_id,
+ bool pf_lut, u8 *lut, u16 lut_size)
+{
+ return i40e_aq_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size,
+ false);
+}
+
+/**
+ * i40evf_aq_set_rss_lut
+ * @hw: pointer to the hardware structure
+ * @vsi_id: vsi fw index
+ * @pf_lut: for PF table set true, for VSI table set false
+ * @lut: pointer to the lut buffer provided by the caller
+ * @lut_size: size of the lut buffer
+ *
+ * set the RSS lookup table, PF or VSI type
+ **/
+i40e_status i40evf_aq_set_rss_lut(struct i40e_hw *hw, u16 vsi_id,
+ bool pf_lut, u8 *lut, u16 lut_size)
+{
+ return i40e_aq_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size, true);
+}
+
+/**
+ * i40e_aq_get_set_rss_key
+ * @hw: pointer to the hw struct
+ * @vsi_id: vsi fw index
+ * @key: pointer to key info struct
+ * @set: set true to set the key, false to get the key
+ *
+ * get the RSS key per VSI
+ **/
+static i40e_status i40e_aq_get_set_rss_key(struct i40e_hw *hw,
+ u16 vsi_id,
+ struct i40e_aqc_get_set_rss_key_data *key,
+ bool set)
+{
+ i40e_status status;
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_get_set_rss_key *cmd_resp =
+ (struct i40e_aqc_get_set_rss_key *)&desc.params.raw;
+ u16 key_size = sizeof(struct i40e_aqc_get_set_rss_key_data);
+
+ if (set)
+ i40evf_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_set_rss_key);
+ else
+ i40evf_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_get_rss_key);
+
+ /* Indirect command */
+ desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
+ desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_RD);
+
+ cmd_resp->vsi_id =
+ cpu_to_le16((u16)((vsi_id <<
+ I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT) &
+ I40E_AQC_SET_RSS_KEY_VSI_ID_MASK));
+ cmd_resp->vsi_id |= cpu_to_le16((u16)I40E_AQC_SET_RSS_KEY_VSI_VALID);
+
+ status = i40evf_asq_send_command(hw, &desc, key, key_size, NULL);
+
+ return status;
+}
+
+/**
+ * i40evf_aq_get_rss_key
+ * @hw: pointer to the hw struct
+ * @vsi_id: vsi fw index
+ * @key: pointer to key info struct
+ *
+ **/
+i40e_status i40evf_aq_get_rss_key(struct i40e_hw *hw,
+ u16 vsi_id,
+ struct i40e_aqc_get_set_rss_key_data *key)
+{
+ return i40e_aq_get_set_rss_key(hw, vsi_id, key, false);
+}
+
+/**
+ * i40evf_aq_set_rss_key
+ * @hw: pointer to the hw struct
+ * @vsi_id: vsi fw index
+ * @key: pointer to key info struct
+ *
+ * set the RSS key per VSI
+ **/
+i40e_status i40evf_aq_set_rss_key(struct i40e_hw *hw,
+ u16 vsi_id,
+ struct i40e_aqc_get_set_rss_key_data *key)
+{
+ return i40e_aq_get_set_rss_key(hw, vsi_id, key, true);
+}
+
+/* The i40evf_ptype_lookup table is used to convert from the 8-bit ptype in the
+ * hardware to a bit-field that can be used by SW to more easily determine the
+ * packet type.
+ *
+ * Macros are used to shorten the table lines and make this table human
+ * readable.
+ *
+ * We store the PTYPE in the top byte of the bit field - this is just so that
+ * we can check that the table doesn't have a row missing, as the index into
+ * the table should be the PTYPE.
+ *
+ * Typical work flow:
+ *
+ * IF NOT i40evf_ptype_lookup[ptype].known
+ * THEN
+ * Packet is unknown
+ * ELSE IF i40evf_ptype_lookup[ptype].outer_ip == I40E_RX_PTYPE_OUTER_IP
+ * Use the rest of the fields to look at the tunnels, inner protocols, etc
+ * ELSE
+ * Use the enum i40e_rx_l2_ptype to decode the packet type
+ * ENDIF
+ */
+
+/* macro to make the table lines short */
+#define I40E_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\
+ { PTYPE, \
+ 1, \
+ I40E_RX_PTYPE_OUTER_##OUTER_IP, \
+ I40E_RX_PTYPE_OUTER_##OUTER_IP_VER, \
+ I40E_RX_PTYPE_##OUTER_FRAG, \
+ I40E_RX_PTYPE_TUNNEL_##T, \
+ I40E_RX_PTYPE_TUNNEL_END_##TE, \
+ I40E_RX_PTYPE_##TEF, \
+ I40E_RX_PTYPE_INNER_PROT_##I, \
+ I40E_RX_PTYPE_PAYLOAD_LAYER_##PL }
+
+#define I40E_PTT_UNUSED_ENTRY(PTYPE) \
+ { PTYPE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+/* shorter macros makes the table fit but are terse */
+#define I40E_RX_PTYPE_NOF I40E_RX_PTYPE_NOT_FRAG
+#define I40E_RX_PTYPE_FRG I40E_RX_PTYPE_FRAG
+#define I40E_RX_PTYPE_INNER_PROT_TS I40E_RX_PTYPE_INNER_PROT_TIMESYNC
+
+/* Lookup table mapping the HW PTYPE to the bit field for decoding */
+struct i40e_rx_ptype_decoded i40evf_ptype_lookup[] = {
+ /* L2 Packet types */
+ I40E_PTT_UNUSED_ENTRY(0),
+ I40E_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
+ I40E_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, TS, PAY2),
+ I40E_PTT(3, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
+ I40E_PTT_UNUSED_ENTRY(4),
+ I40E_PTT_UNUSED_ENTRY(5),
+ I40E_PTT(6, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
+ I40E_PTT(7, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
+ I40E_PTT_UNUSED_ENTRY(8),
+ I40E_PTT_UNUSED_ENTRY(9),
+ I40E_PTT(10, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
+ I40E_PTT(11, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE),
+ I40E_PTT(12, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(13, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(14, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(15, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(16, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(17, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(18, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(19, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(20, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(21, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
+
+ /* Non Tunneled IPv4 */
+ I40E_PTT(22, IP, IPV4, FRG, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(23, IP, IPV4, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(24, IP, IPV4, NOF, NONE, NONE, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(25),
+ I40E_PTT(26, IP, IPV4, NOF, NONE, NONE, NOF, TCP, PAY4),
+ I40E_PTT(27, IP, IPV4, NOF, NONE, NONE, NOF, SCTP, PAY4),
+ I40E_PTT(28, IP, IPV4, NOF, NONE, NONE, NOF, ICMP, PAY4),
+
+ /* IPv4 --> IPv4 */
+ I40E_PTT(29, IP, IPV4, NOF, IP_IP, IPV4, FRG, NONE, PAY3),
+ I40E_PTT(30, IP, IPV4, NOF, IP_IP, IPV4, NOF, NONE, PAY3),
+ I40E_PTT(31, IP, IPV4, NOF, IP_IP, IPV4, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(32),
+ I40E_PTT(33, IP, IPV4, NOF, IP_IP, IPV4, NOF, TCP, PAY4),
+ I40E_PTT(34, IP, IPV4, NOF, IP_IP, IPV4, NOF, SCTP, PAY4),
+ I40E_PTT(35, IP, IPV4, NOF, IP_IP, IPV4, NOF, ICMP, PAY4),
+
+ /* IPv4 --> IPv6 */
+ I40E_PTT(36, IP, IPV4, NOF, IP_IP, IPV6, FRG, NONE, PAY3),
+ I40E_PTT(37, IP, IPV4, NOF, IP_IP, IPV6, NOF, NONE, PAY3),
+ I40E_PTT(38, IP, IPV4, NOF, IP_IP, IPV6, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(39),
+ I40E_PTT(40, IP, IPV4, NOF, IP_IP, IPV6, NOF, TCP, PAY4),
+ I40E_PTT(41, IP, IPV4, NOF, IP_IP, IPV6, NOF, SCTP, PAY4),
+ I40E_PTT(42, IP, IPV4, NOF, IP_IP, IPV6, NOF, ICMP, PAY4),
+
+ /* IPv4 --> GRE/NAT */
+ I40E_PTT(43, IP, IPV4, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3),
+
+ /* IPv4 --> GRE/NAT --> IPv4 */
+ I40E_PTT(44, IP, IPV4, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3),
+ I40E_PTT(45, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3),
+ I40E_PTT(46, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(47),
+ I40E_PTT(48, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4),
+ I40E_PTT(49, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4),
+ I40E_PTT(50, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4),
+
+ /* IPv4 --> GRE/NAT --> IPv6 */
+ I40E_PTT(51, IP, IPV4, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3),
+ I40E_PTT(52, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3),
+ I40E_PTT(53, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(54),
+ I40E_PTT(55, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4),
+ I40E_PTT(56, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4),
+ I40E_PTT(57, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4),
+
+ /* IPv4 --> GRE/NAT --> MAC */
+ I40E_PTT(58, IP, IPV4, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3),
+
+ /* IPv4 --> GRE/NAT --> MAC --> IPv4 */
+ I40E_PTT(59, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3),
+ I40E_PTT(60, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3),
+ I40E_PTT(61, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(62),
+ I40E_PTT(63, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4),
+ I40E_PTT(64, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4),
+ I40E_PTT(65, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4),
+
+ /* IPv4 --> GRE/NAT -> MAC --> IPv6 */
+ I40E_PTT(66, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3),
+ I40E_PTT(67, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3),
+ I40E_PTT(68, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(69),
+ I40E_PTT(70, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4),
+ I40E_PTT(71, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4),
+ I40E_PTT(72, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4),
+
+ /* IPv4 --> GRE/NAT --> MAC/VLAN */
+ I40E_PTT(73, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3),
+
+ /* IPv4 ---> GRE/NAT -> MAC/VLAN --> IPv4 */
+ I40E_PTT(74, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3),
+ I40E_PTT(75, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3),
+ I40E_PTT(76, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(77),
+ I40E_PTT(78, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4),
+ I40E_PTT(79, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4),
+ I40E_PTT(80, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4),
+
+ /* IPv4 -> GRE/NAT -> MAC/VLAN --> IPv6 */
+ I40E_PTT(81, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3),
+ I40E_PTT(82, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3),
+ I40E_PTT(83, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(84),
+ I40E_PTT(85, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4),
+ I40E_PTT(86, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4),
+ I40E_PTT(87, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4),
+
+ /* Non Tunneled IPv6 */
+ I40E_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3),
+ I40E_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY3),
+ I40E_PTT_UNUSED_ENTRY(91),
+ I40E_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4),
+ I40E_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4),
+ I40E_PTT(94, IP, IPV6, NOF, NONE, NONE, NOF, ICMP, PAY4),
+
+ /* IPv6 --> IPv4 */
+ I40E_PTT(95, IP, IPV6, NOF, IP_IP, IPV4, FRG, NONE, PAY3),
+ I40E_PTT(96, IP, IPV6, NOF, IP_IP, IPV4, NOF, NONE, PAY3),
+ I40E_PTT(97, IP, IPV6, NOF, IP_IP, IPV4, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(98),
+ I40E_PTT(99, IP, IPV6, NOF, IP_IP, IPV4, NOF, TCP, PAY4),
+ I40E_PTT(100, IP, IPV6, NOF, IP_IP, IPV4, NOF, SCTP, PAY4),
+ I40E_PTT(101, IP, IPV6, NOF, IP_IP, IPV4, NOF, ICMP, PAY4),
+
+ /* IPv6 --> IPv6 */
+ I40E_PTT(102, IP, IPV6, NOF, IP_IP, IPV6, FRG, NONE, PAY3),
+ I40E_PTT(103, IP, IPV6, NOF, IP_IP, IPV6, NOF, NONE, PAY3),
+ I40E_PTT(104, IP, IPV6, NOF, IP_IP, IPV6, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(105),
+ I40E_PTT(106, IP, IPV6, NOF, IP_IP, IPV6, NOF, TCP, PAY4),
+ I40E_PTT(107, IP, IPV6, NOF, IP_IP, IPV6, NOF, SCTP, PAY4),
+ I40E_PTT(108, IP, IPV6, NOF, IP_IP, IPV6, NOF, ICMP, PAY4),
+
+ /* IPv6 --> GRE/NAT */
+ I40E_PTT(109, IP, IPV6, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3),
+
+ /* IPv6 --> GRE/NAT -> IPv4 */
+ I40E_PTT(110, IP, IPV6, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3),
+ I40E_PTT(111, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3),
+ I40E_PTT(112, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(113),
+ I40E_PTT(114, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4),
+ I40E_PTT(115, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4),
+ I40E_PTT(116, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> IPv6 */
+ I40E_PTT(117, IP, IPV6, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3),
+ I40E_PTT(118, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3),
+ I40E_PTT(119, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(120),
+ I40E_PTT(121, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4),
+ I40E_PTT(122, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4),
+ I40E_PTT(123, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> MAC */
+ I40E_PTT(124, IP, IPV6, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3),
+
+ /* IPv6 --> GRE/NAT -> MAC -> IPv4 */
+ I40E_PTT(125, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3),
+ I40E_PTT(126, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3),
+ I40E_PTT(127, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(128),
+ I40E_PTT(129, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4),
+ I40E_PTT(130, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4),
+ I40E_PTT(131, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> MAC -> IPv6 */
+ I40E_PTT(132, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3),
+ I40E_PTT(133, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3),
+ I40E_PTT(134, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(135),
+ I40E_PTT(136, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4),
+ I40E_PTT(137, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4),
+ I40E_PTT(138, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> MAC/VLAN */
+ I40E_PTT(139, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3),
+
+ /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv4 */
+ I40E_PTT(140, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3),
+ I40E_PTT(141, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3),
+ I40E_PTT(142, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(143),
+ I40E_PTT(144, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4),
+ I40E_PTT(145, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4),
+ I40E_PTT(146, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv6 */
+ I40E_PTT(147, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3),
+ I40E_PTT(148, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3),
+ I40E_PTT(149, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4),
+ I40E_PTT_UNUSED_ENTRY(150),
+ I40E_PTT(151, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4),
+ I40E_PTT(152, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4),
+ I40E_PTT(153, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4),
+
+ /* unused entries */
+ I40E_PTT_UNUSED_ENTRY(154),
+ I40E_PTT_UNUSED_ENTRY(155),
+ I40E_PTT_UNUSED_ENTRY(156),
+ I40E_PTT_UNUSED_ENTRY(157),
+ I40E_PTT_UNUSED_ENTRY(158),
+ I40E_PTT_UNUSED_ENTRY(159),
+
+ I40E_PTT_UNUSED_ENTRY(160),
+ I40E_PTT_UNUSED_ENTRY(161),
+ I40E_PTT_UNUSED_ENTRY(162),
+ I40E_PTT_UNUSED_ENTRY(163),
+ I40E_PTT_UNUSED_ENTRY(164),
+ I40E_PTT_UNUSED_ENTRY(165),
+ I40E_PTT_UNUSED_ENTRY(166),
+ I40E_PTT_UNUSED_ENTRY(167),
+ I40E_PTT_UNUSED_ENTRY(168),
+ I40E_PTT_UNUSED_ENTRY(169),
+
+ I40E_PTT_UNUSED_ENTRY(170),
+ I40E_PTT_UNUSED_ENTRY(171),
+ I40E_PTT_UNUSED_ENTRY(172),
+ I40E_PTT_UNUSED_ENTRY(173),
+ I40E_PTT_UNUSED_ENTRY(174),
+ I40E_PTT_UNUSED_ENTRY(175),
+ I40E_PTT_UNUSED_ENTRY(176),
+ I40E_PTT_UNUSED_ENTRY(177),
+ I40E_PTT_UNUSED_ENTRY(178),
+ I40E_PTT_UNUSED_ENTRY(179),
+
+ I40E_PTT_UNUSED_ENTRY(180),
+ I40E_PTT_UNUSED_ENTRY(181),
+ I40E_PTT_UNUSED_ENTRY(182),
+ I40E_PTT_UNUSED_ENTRY(183),
+ I40E_PTT_UNUSED_ENTRY(184),
+ I40E_PTT_UNUSED_ENTRY(185),
+ I40E_PTT_UNUSED_ENTRY(186),
+ I40E_PTT_UNUSED_ENTRY(187),
+ I40E_PTT_UNUSED_ENTRY(188),
+ I40E_PTT_UNUSED_ENTRY(189),
+
+ I40E_PTT_UNUSED_ENTRY(190),
+ I40E_PTT_UNUSED_ENTRY(191),
+ I40E_PTT_UNUSED_ENTRY(192),
+ I40E_PTT_UNUSED_ENTRY(193),
+ I40E_PTT_UNUSED_ENTRY(194),
+ I40E_PTT_UNUSED_ENTRY(195),
+ I40E_PTT_UNUSED_ENTRY(196),
+ I40E_PTT_UNUSED_ENTRY(197),
+ I40E_PTT_UNUSED_ENTRY(198),
+ I40E_PTT_UNUSED_ENTRY(199),
+
+ I40E_PTT_UNUSED_ENTRY(200),
+ I40E_PTT_UNUSED_ENTRY(201),
+ I40E_PTT_UNUSED_ENTRY(202),
+ I40E_PTT_UNUSED_ENTRY(203),
+ I40E_PTT_UNUSED_ENTRY(204),
+ I40E_PTT_UNUSED_ENTRY(205),
+ I40E_PTT_UNUSED_ENTRY(206),
+ I40E_PTT_UNUSED_ENTRY(207),
+ I40E_PTT_UNUSED_ENTRY(208),
+ I40E_PTT_UNUSED_ENTRY(209),
+
+ I40E_PTT_UNUSED_ENTRY(210),
+ I40E_PTT_UNUSED_ENTRY(211),
+ I40E_PTT_UNUSED_ENTRY(212),
+ I40E_PTT_UNUSED_ENTRY(213),
+ I40E_PTT_UNUSED_ENTRY(214),
+ I40E_PTT_UNUSED_ENTRY(215),
+ I40E_PTT_UNUSED_ENTRY(216),
+ I40E_PTT_UNUSED_ENTRY(217),
+ I40E_PTT_UNUSED_ENTRY(218),
+ I40E_PTT_UNUSED_ENTRY(219),
+
+ I40E_PTT_UNUSED_ENTRY(220),
+ I40E_PTT_UNUSED_ENTRY(221),
+ I40E_PTT_UNUSED_ENTRY(222),
+ I40E_PTT_UNUSED_ENTRY(223),
+ I40E_PTT_UNUSED_ENTRY(224),
+ I40E_PTT_UNUSED_ENTRY(225),
+ I40E_PTT_UNUSED_ENTRY(226),
+ I40E_PTT_UNUSED_ENTRY(227),
+ I40E_PTT_UNUSED_ENTRY(228),
+ I40E_PTT_UNUSED_ENTRY(229),
+
+ I40E_PTT_UNUSED_ENTRY(230),
+ I40E_PTT_UNUSED_ENTRY(231),
+ I40E_PTT_UNUSED_ENTRY(232),
+ I40E_PTT_UNUSED_ENTRY(233),
+ I40E_PTT_UNUSED_ENTRY(234),
+ I40E_PTT_UNUSED_ENTRY(235),
+ I40E_PTT_UNUSED_ENTRY(236),
+ I40E_PTT_UNUSED_ENTRY(237),
+ I40E_PTT_UNUSED_ENTRY(238),
+ I40E_PTT_UNUSED_ENTRY(239),
+
+ I40E_PTT_UNUSED_ENTRY(240),
+ I40E_PTT_UNUSED_ENTRY(241),
+ I40E_PTT_UNUSED_ENTRY(242),
+ I40E_PTT_UNUSED_ENTRY(243),
+ I40E_PTT_UNUSED_ENTRY(244),
+ I40E_PTT_UNUSED_ENTRY(245),
+ I40E_PTT_UNUSED_ENTRY(246),
+ I40E_PTT_UNUSED_ENTRY(247),
+ I40E_PTT_UNUSED_ENTRY(248),
+ I40E_PTT_UNUSED_ENTRY(249),
+
+ I40E_PTT_UNUSED_ENTRY(250),
+ I40E_PTT_UNUSED_ENTRY(251),
+ I40E_PTT_UNUSED_ENTRY(252),
+ I40E_PTT_UNUSED_ENTRY(253),
+ I40E_PTT_UNUSED_ENTRY(254),
+ I40E_PTT_UNUSED_ENTRY(255)
+};
+
+/**
+ * i40e_aq_send_msg_to_pf
+ * @hw: pointer to the hardware structure
+ * @v_opcode: opcodes for VF-PF communication
+ * @v_retval: return error code
+ * @msg: pointer to the msg buffer
+ * @msglen: msg length
+ * @cmd_details: pointer to command details
+ *
+ * Send message to PF driver using admin queue. By default, this message
+ * is sent asynchronously, i.e. i40evf_asq_send_command() does not wait for
+ * completion before returning.
+ **/
+i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
+ enum virtchnl_ops v_opcode,
+ i40e_status v_retval,
+ u8 *msg, u16 msglen,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_asq_cmd_details details;
+ i40e_status status;
+
+ i40evf_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_send_msg_to_pf);
+ desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_SI);
+ desc.cookie_high = cpu_to_le32(v_opcode);
+ desc.cookie_low = cpu_to_le32(v_retval);
+ if (msglen) {
+ desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF
+ | I40E_AQ_FLAG_RD));
+ if (msglen > I40E_AQ_LARGE_BUF)
+ desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
+ desc.datalen = cpu_to_le16(msglen);
+ }
+ if (!cmd_details) {
+ memset(&details, 0, sizeof(details));
+ details.async = true;
+ cmd_details = &details;
+ }
+ status = i40evf_asq_send_command(hw, &desc, msg, msglen, cmd_details);
+ return status;
+}
+
+/**
+ * i40e_vf_parse_hw_config
+ * @hw: pointer to the hardware structure
+ * @msg: pointer to the virtual channel VF resource structure
+ *
+ * Given a VF resource message from the PF, populate the hw struct
+ * with appropriate information.
+ **/
+void i40e_vf_parse_hw_config(struct i40e_hw *hw,
+ struct virtchnl_vf_resource *msg)
+{
+ struct virtchnl_vsi_resource *vsi_res;
+ int i;
+
+ vsi_res = &msg->vsi_res[0];
+
+ hw->dev_caps.num_vsis = msg->num_vsis;
+ hw->dev_caps.num_rx_qp = msg->num_queue_pairs;
+ hw->dev_caps.num_tx_qp = msg->num_queue_pairs;
+ hw->dev_caps.num_msix_vectors_vf = msg->max_vectors;
+ hw->dev_caps.dcb = msg->vf_cap_flags &
+ VIRTCHNL_VF_OFFLOAD_L2;
+ hw->dev_caps.fcoe = 0;
+ for (i = 0; i < msg->num_vsis; i++) {
+ if (vsi_res->vsi_type == VIRTCHNL_VSI_SRIOV) {
+ ether_addr_copy(hw->mac.perm_addr,
+ vsi_res->default_mac_addr);
+ ether_addr_copy(hw->mac.addr,
+ vsi_res->default_mac_addr);
+ }
+ vsi_res++;
+ }
+}
+
+/**
+ * i40e_vf_reset
+ * @hw: pointer to the hardware structure
+ *
+ * Send a VF_RESET message to the PF. Does not wait for response from PF
+ * as none will be forthcoming. Immediately after calling this function,
+ * the admin queue should be shut down and (optionally) reinitialized.
+ **/
+i40e_status i40e_vf_reset(struct i40e_hw *hw)
+{
+ return i40e_aq_send_msg_to_pf(hw, VIRTCHNL_OP_RESET_VF,
+ 0, NULL, 0, NULL);
+}
diff --git a/drivers/net/ethernet/intel/iavf/i40e_devids.h b/drivers/net/ethernet/intel/iavf/i40e_devids.h
new file mode 100644
index 000000000000..f300bf271824
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_devids.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_DEVIDS_H_
+#define _I40E_DEVIDS_H_
+
+/* Device IDs */
+#define I40E_DEV_ID_SFP_XL710 0x1572
+#define I40E_DEV_ID_QEMU 0x1574
+#define I40E_DEV_ID_KX_B 0x1580
+#define I40E_DEV_ID_KX_C 0x1581
+#define I40E_DEV_ID_QSFP_A 0x1583
+#define I40E_DEV_ID_QSFP_B 0x1584
+#define I40E_DEV_ID_QSFP_C 0x1585
+#define I40E_DEV_ID_10G_BASE_T 0x1586
+#define I40E_DEV_ID_20G_KR2 0x1587
+#define I40E_DEV_ID_20G_KR2_A 0x1588
+#define I40E_DEV_ID_10G_BASE_T4 0x1589
+#define I40E_DEV_ID_25G_B 0x158A
+#define I40E_DEV_ID_25G_SFP28 0x158B
+#define I40E_DEV_ID_VF 0x154C
+#define I40E_DEV_ID_VF_HV 0x1571
+#define I40E_DEV_ID_ADAPTIVE_VF 0x1889
+#define I40E_DEV_ID_SFP_X722 0x37D0
+#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1
+#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2
+#define I40E_DEV_ID_SFP_I_X722 0x37D3
+#define I40E_DEV_ID_X722_VF 0x37CD
+
+#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \
+ (d) == I40E_DEV_ID_QSFP_B || \
+ (d) == I40E_DEV_ID_QSFP_C)
+
+#endif /* _I40E_DEVIDS_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40e_osdep.h b/drivers/net/ethernet/intel/iavf/i40e_osdep.h
new file mode 100644
index 000000000000..3ddddb46455b
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_osdep.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_OSDEP_H_
+#define _I40E_OSDEP_H_
+
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/tcp.h>
+#include <linux/pci.h>
+
+/* get readq/writeq support for 32 bit kernels, use the low-first version */
+#include <linux/io-64-nonatomic-lo-hi.h>
+
+/* File to be the magic between shared code and
+ * actual OS primitives
+ */
+
+#define hw_dbg(hw, S, A...) do {} while (0)
+
+#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
+#define rd32(a, reg) readl((a)->hw_addr + (reg))
+
+#define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg)))
+#define rd64(a, reg) readq((a)->hw_addr + (reg))
+#define i40e_flush(a) readl((a)->hw_addr + I40E_VFGEN_RSTAT)
+
+/* memory allocation tracking */
+struct i40e_dma_mem {
+ void *va;
+ dma_addr_t pa;
+ u32 size;
+};
+
+#define i40e_allocate_dma_mem(h, m, unused, s, a) \
+ i40evf_allocate_dma_mem_d(h, m, s, a)
+#define i40e_free_dma_mem(h, m) i40evf_free_dma_mem_d(h, m)
+
+struct i40e_virt_mem {
+ void *va;
+ u32 size;
+};
+#define i40e_allocate_virt_mem(h, m, s) i40evf_allocate_virt_mem_d(h, m, s)
+#define i40e_free_virt_mem(h, m) i40evf_free_virt_mem_d(h, m)
+
+#define i40e_debug(h, m, s, ...) i40evf_debug_d(h, m, s, ##__VA_ARGS__)
+extern void i40evf_debug_d(void *hw, u32 mask, char *fmt_str, ...)
+ __attribute__ ((format(gnu_printf, 3, 4)));
+
+typedef enum i40e_status_code i40e_status;
+#endif /* _I40E_OSDEP_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40e_prototype.h b/drivers/net/ethernet/intel/iavf/i40e_prototype.h
new file mode 100644
index 000000000000..ef7f74489bfc
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_prototype.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_PROTOTYPE_H_
+#define _I40E_PROTOTYPE_H_
+
+#include "i40e_type.h"
+#include "i40e_alloc.h"
+#include <linux/avf/virtchnl.h>
+
+/* Prototypes for shared code functions that are not in
+ * the standard function pointer structures. These are
+ * mostly because they are needed even before the init
+ * has happened and will assist in the early SW and FW
+ * setup.
+ */
+
+/* adminq functions */
+i40e_status i40evf_init_adminq(struct i40e_hw *hw);
+i40e_status i40evf_shutdown_adminq(struct i40e_hw *hw);
+void i40e_adminq_init_ring_data(struct i40e_hw *hw);
+i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
+ struct i40e_arq_event_info *e,
+ u16 *events_pending);
+i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
+ struct i40e_aq_desc *desc,
+ void *buff, /* can be NULL */
+ u16 buff_size,
+ struct i40e_asq_cmd_details *cmd_details);
+bool i40evf_asq_done(struct i40e_hw *hw);
+
+/* debug function for adminq */
+void i40evf_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask,
+ void *desc, void *buffer, u16 buf_len);
+
+void i40e_idle_aq(struct i40e_hw *hw);
+void i40evf_resume_aq(struct i40e_hw *hw);
+bool i40evf_check_asq_alive(struct i40e_hw *hw);
+i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw, bool unloading);
+const char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err);
+const char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err);
+
+i40e_status i40evf_aq_get_rss_lut(struct i40e_hw *hw, u16 seid,
+ bool pf_lut, u8 *lut, u16 lut_size);
+i40e_status i40evf_aq_set_rss_lut(struct i40e_hw *hw, u16 seid,
+ bool pf_lut, u8 *lut, u16 lut_size);
+i40e_status i40evf_aq_get_rss_key(struct i40e_hw *hw,
+ u16 seid,
+ struct i40e_aqc_get_set_rss_key_data *key);
+i40e_status i40evf_aq_set_rss_key(struct i40e_hw *hw,
+ u16 seid,
+ struct i40e_aqc_get_set_rss_key_data *key);
+
+i40e_status i40e_set_mac_type(struct i40e_hw *hw);
+
+extern struct i40e_rx_ptype_decoded i40evf_ptype_lookup[];
+
+static inline struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
+{
+ return i40evf_ptype_lookup[ptype];
+}
+
+/* i40e_common for VF drivers*/
+void i40e_vf_parse_hw_config(struct i40e_hw *hw,
+ struct virtchnl_vf_resource *msg);
+i40e_status i40e_vf_reset(struct i40e_hw *hw);
+i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
+ enum virtchnl_ops v_opcode,
+ i40e_status v_retval, u8 *msg, u16 msglen,
+ struct i40e_asq_cmd_details *cmd_details);
+#endif /* _I40E_PROTOTYPE_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40e_register.h b/drivers/net/ethernet/intel/iavf/i40e_register.h
new file mode 100644
index 000000000000..20b464ac1542
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_register.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_REGISTER_H_
+#define _I40E_REGISTER_H_
+
+#define I40E_VF_ARQBAH1 0x00006000 /* Reset: EMPR */
+#define I40E_VF_ARQBAL1 0x00006C00 /* Reset: EMPR */
+#define I40E_VF_ARQH1 0x00007400 /* Reset: EMPR */
+#define I40E_VF_ARQH1_ARQH_SHIFT 0
+#define I40E_VF_ARQH1_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH1_ARQH_SHIFT)
+#define I40E_VF_ARQLEN1 0x00008000 /* Reset: EMPR */
+#define I40E_VF_ARQLEN1_ARQVFE_SHIFT 28
+#define I40E_VF_ARQLEN1_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN1_ARQOVFL_SHIFT 29
+#define I40E_VF_ARQLEN1_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN1_ARQCRIT_SHIFT 30
+#define I40E_VF_ARQLEN1_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN1_ARQENABLE_SHIFT 31
+#define I40E_VF_ARQLEN1_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT1 0x00007000 /* Reset: EMPR */
+#define I40E_VF_ATQBAH1 0x00007800 /* Reset: EMPR */
+#define I40E_VF_ATQBAL1 0x00007C00 /* Reset: EMPR */
+#define I40E_VF_ATQH1 0x00006400 /* Reset: EMPR */
+#define I40E_VF_ATQLEN1 0x00006800 /* Reset: EMPR */
+#define I40E_VF_ATQLEN1_ATQVFE_SHIFT 28
+#define I40E_VF_ATQLEN1_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN1_ATQOVFL_SHIFT 29
+#define I40E_VF_ATQLEN1_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN1_ATQCRIT_SHIFT 30
+#define I40E_VF_ATQLEN1_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN1_ATQENABLE_SHIFT 31
+#define I40E_VF_ATQLEN1_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT1 0x00008400 /* Reset: EMPR */
+#define I40E_VFGEN_RSTAT 0x00008800 /* Reset: VFR */
+#define I40E_VFGEN_RSTAT_VFR_STATE_SHIFT 0
+#define I40E_VFGEN_RSTAT_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
+#define I40E_VFINT_DYN_CTL01 0x00005C00 /* Reset: VFR */
+#define I40E_VFINT_DYN_CTL01_INTENA_SHIFT 0
+#define I40E_VFINT_DYN_CTL01_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT 3
+#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4)) /* _i=0...15 */ /* Reset: VFR */
+#define I40E_VFINT_DYN_CTLN1_INTENA_SHIFT 0
+#define I40E_VFINT_DYN_CTLN1_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT 2
+#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT 3
+#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT 5
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT 24
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_ICR0_ENA1 0x00005000 /* Reset: CORER */
+#define I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT 30
+#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_RSVD_SHIFT 31
+#define I40E_VFINT_ICR01 0x00004800 /* Reset: CORER */
+#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...15 */ /* Reset: VFR */
+#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: CORER */
+#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: PFR */
+#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
+#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
+#define I40E_VFQF_HKEY_MAX_INDEX 12
+#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
+#define I40E_VFQF_HLUT_MAX_INDEX 15
+#define I40E_VFINT_DYN_CTLN1_WB_ON_ITR_SHIFT 30
+#define I40E_VFINT_DYN_CTLN1_WB_ON_ITR_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_WB_ON_ITR_SHIFT)
+#endif /* _I40E_REGISTER_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40e_status.h b/drivers/net/ethernet/intel/iavf/i40e_status.h
new file mode 100644
index 000000000000..77be0702d07c
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_status.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_STATUS_H_
+#define _I40E_STATUS_H_
+
+/* Error Codes */
+enum i40e_status_code {
+ I40E_SUCCESS = 0,
+ I40E_ERR_NVM = -1,
+ I40E_ERR_NVM_CHECKSUM = -2,
+ I40E_ERR_PHY = -3,
+ I40E_ERR_CONFIG = -4,
+ I40E_ERR_PARAM = -5,
+ I40E_ERR_MAC_TYPE = -6,
+ I40E_ERR_UNKNOWN_PHY = -7,
+ I40E_ERR_LINK_SETUP = -8,
+ I40E_ERR_ADAPTER_STOPPED = -9,
+ I40E_ERR_INVALID_MAC_ADDR = -10,
+ I40E_ERR_DEVICE_NOT_SUPPORTED = -11,
+ I40E_ERR_MASTER_REQUESTS_PENDING = -12,
+ I40E_ERR_INVALID_LINK_SETTINGS = -13,
+ I40E_ERR_AUTONEG_NOT_COMPLETE = -14,
+ I40E_ERR_RESET_FAILED = -15,
+ I40E_ERR_SWFW_SYNC = -16,
+ I40E_ERR_NO_AVAILABLE_VSI = -17,
+ I40E_ERR_NO_MEMORY = -18,
+ I40E_ERR_BAD_PTR = -19,
+ I40E_ERR_RING_FULL = -20,
+ I40E_ERR_INVALID_PD_ID = -21,
+ I40E_ERR_INVALID_QP_ID = -22,
+ I40E_ERR_INVALID_CQ_ID = -23,
+ I40E_ERR_INVALID_CEQ_ID = -24,
+ I40E_ERR_INVALID_AEQ_ID = -25,
+ I40E_ERR_INVALID_SIZE = -26,
+ I40E_ERR_INVALID_ARP_INDEX = -27,
+ I40E_ERR_INVALID_FPM_FUNC_ID = -28,
+ I40E_ERR_QP_INVALID_MSG_SIZE = -29,
+ I40E_ERR_QP_TOOMANY_WRS_POSTED = -30,
+ I40E_ERR_INVALID_FRAG_COUNT = -31,
+ I40E_ERR_QUEUE_EMPTY = -32,
+ I40E_ERR_INVALID_ALIGNMENT = -33,
+ I40E_ERR_FLUSHED_QUEUE = -34,
+ I40E_ERR_INVALID_PUSH_PAGE_INDEX = -35,
+ I40E_ERR_INVALID_IMM_DATA_SIZE = -36,
+ I40E_ERR_TIMEOUT = -37,
+ I40E_ERR_OPCODE_MISMATCH = -38,
+ I40E_ERR_CQP_COMPL_ERROR = -39,
+ I40E_ERR_INVALID_VF_ID = -40,
+ I40E_ERR_INVALID_HMCFN_ID = -41,
+ I40E_ERR_BACKING_PAGE_ERROR = -42,
+ I40E_ERR_NO_PBLCHUNKS_AVAILABLE = -43,
+ I40E_ERR_INVALID_PBLE_INDEX = -44,
+ I40E_ERR_INVALID_SD_INDEX = -45,
+ I40E_ERR_INVALID_PAGE_DESC_INDEX = -46,
+ I40E_ERR_INVALID_SD_TYPE = -47,
+ I40E_ERR_MEMCPY_FAILED = -48,
+ I40E_ERR_INVALID_HMC_OBJ_INDEX = -49,
+ I40E_ERR_INVALID_HMC_OBJ_COUNT = -50,
+ I40E_ERR_INVALID_SRQ_ARM_LIMIT = -51,
+ I40E_ERR_SRQ_ENABLED = -52,
+ I40E_ERR_ADMIN_QUEUE_ERROR = -53,
+ I40E_ERR_ADMIN_QUEUE_TIMEOUT = -54,
+ I40E_ERR_BUF_TOO_SHORT = -55,
+ I40E_ERR_ADMIN_QUEUE_FULL = -56,
+ I40E_ERR_ADMIN_QUEUE_NO_WORK = -57,
+ I40E_ERR_BAD_IWARP_CQE = -58,
+ I40E_ERR_NVM_BLANK_MODE = -59,
+ I40E_ERR_NOT_IMPLEMENTED = -60,
+ I40E_ERR_PE_DOORBELL_NOT_ENABLED = -61,
+ I40E_ERR_DIAG_TEST_FAILED = -62,
+ I40E_ERR_NOT_READY = -63,
+ I40E_NOT_SUPPORTED = -64,
+ I40E_ERR_FIRMWARE_API_VERSION = -65,
+ I40E_ERR_ADMIN_QUEUE_CRITICAL_ERROR = -66,
+};
+
+#endif /* _I40E_STATUS_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40e_trace.h b/drivers/net/ethernet/intel/iavf/i40e_trace.h
new file mode 100644
index 000000000000..d7a4e68820a8
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_trace.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+/* Modeled on trace-events-sample.h */
+
+/* The trace subsystem name for i40evf will be "i40evf".
+ *
+ * This file is named i40e_trace.h.
+ *
+ * Since this include file's name is different from the trace
+ * subsystem name, we'll have to define TRACE_INCLUDE_FILE at the end
+ * of this file.
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM i40evf
+
+/* See trace-events-sample.h for a detailed description of why this
+ * guard clause is different from most normal include files.
+ */
+#if !defined(_I40E_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _I40E_TRACE_H_
+
+#include <linux/tracepoint.h>
+
+/**
+ * i40e_trace() macro enables shared code to refer to trace points
+ * like:
+ *
+ * trace_i40e{,vf}_example(args...)
+ *
+ * ... as:
+ *
+ * i40e_trace(example, args...)
+ *
+ * ... to resolve to the PF or VF version of the tracepoint without
+ * ifdefs, and to allow tracepoints to be disabled entirely at build
+ * time.
+ *
+ * Trace point should always be referred to in the driver via this
+ * macro.
+ *
+ * Similarly, i40e_trace_enabled(trace_name) wraps references to
+ * trace_i40e{,vf}_<trace_name>_enabled() functions.
+ */
+#define _I40E_TRACE_NAME(trace_name) (trace_ ## i40evf ## _ ## trace_name)
+#define I40E_TRACE_NAME(trace_name) _I40E_TRACE_NAME(trace_name)
+
+#define i40e_trace(trace_name, args...) I40E_TRACE_NAME(trace_name)(args)
+
+#define i40e_trace_enabled(trace_name) I40E_TRACE_NAME(trace_name##_enabled)()
+
+/* Events common to PF and VF. Corresponding versions will be defined
+ * for both, named trace_i40e_* and trace_i40evf_*. The i40e_trace()
+ * macro above will select the right trace point name for the driver
+ * being built from shared code.
+ */
+
+/* Events related to a vsi & ring */
+DECLARE_EVENT_CLASS(
+ i40evf_tx_template,
+
+ TP_PROTO(struct i40e_ring *ring,
+ struct i40e_tx_desc *desc,
+ struct i40e_tx_buffer *buf),
+
+ TP_ARGS(ring, desc, buf),
+
+ /* The convention here is to make the first fields in the
+ * TP_STRUCT match the TP_PROTO exactly. This enables the use
+ * of the args struct generated by the tplist tool (from the
+ * bcc-tools package) to be used for those fields. To access
+ * fields other than the tracepoint args will require the
+ * tplist output to be adjusted.
+ */
+ TP_STRUCT__entry(
+ __field(void*, ring)
+ __field(void*, desc)
+ __field(void*, buf)
+ __string(devname, ring->netdev->name)
+ ),
+
+ TP_fast_assign(
+ __entry->ring = ring;
+ __entry->desc = desc;
+ __entry->buf = buf;
+ __assign_str(devname, ring->netdev->name);
+ ),
+
+ TP_printk(
+ "netdev: %s ring: %p desc: %p buf %p",
+ __get_str(devname), __entry->ring,
+ __entry->desc, __entry->buf)
+);
+
+DEFINE_EVENT(
+ i40evf_tx_template, i40evf_clean_tx_irq,
+ TP_PROTO(struct i40e_ring *ring,
+ struct i40e_tx_desc *desc,
+ struct i40e_tx_buffer *buf),
+
+ TP_ARGS(ring, desc, buf));
+
+DEFINE_EVENT(
+ i40evf_tx_template, i40evf_clean_tx_irq_unmap,
+ TP_PROTO(struct i40e_ring *ring,
+ struct i40e_tx_desc *desc,
+ struct i40e_tx_buffer *buf),
+
+ TP_ARGS(ring, desc, buf));
+
+DECLARE_EVENT_CLASS(
+ i40evf_rx_template,
+
+ TP_PROTO(struct i40e_ring *ring,
+ union i40e_32byte_rx_desc *desc,
+ struct sk_buff *skb),
+
+ TP_ARGS(ring, desc, skb),
+
+ TP_STRUCT__entry(
+ __field(void*, ring)
+ __field(void*, desc)
+ __field(void*, skb)
+ __string(devname, ring->netdev->name)
+ ),
+
+ TP_fast_assign(
+ __entry->ring = ring;
+ __entry->desc = desc;
+ __entry->skb = skb;
+ __assign_str(devname, ring->netdev->name);
+ ),
+
+ TP_printk(
+ "netdev: %s ring: %p desc: %p skb %p",
+ __get_str(devname), __entry->ring,
+ __entry->desc, __entry->skb)
+);
+
+DEFINE_EVENT(
+ i40evf_rx_template, i40evf_clean_rx_irq,
+ TP_PROTO(struct i40e_ring *ring,
+ union i40e_32byte_rx_desc *desc,
+ struct sk_buff *skb),
+
+ TP_ARGS(ring, desc, skb));
+
+DEFINE_EVENT(
+ i40evf_rx_template, i40evf_clean_rx_irq_rx,
+ TP_PROTO(struct i40e_ring *ring,
+ union i40e_32byte_rx_desc *desc,
+ struct sk_buff *skb),
+
+ TP_ARGS(ring, desc, skb));
+
+DECLARE_EVENT_CLASS(
+ i40evf_xmit_template,
+
+ TP_PROTO(struct sk_buff *skb,
+ struct i40e_ring *ring),
+
+ TP_ARGS(skb, ring),
+
+ TP_STRUCT__entry(
+ __field(void*, skb)
+ __field(void*, ring)
+ __string(devname, ring->netdev->name)
+ ),
+
+ TP_fast_assign(
+ __entry->skb = skb;
+ __entry->ring = ring;
+ __assign_str(devname, ring->netdev->name);
+ ),
+
+ TP_printk(
+ "netdev: %s skb: %p ring: %p",
+ __get_str(devname), __entry->skb,
+ __entry->ring)
+);
+
+DEFINE_EVENT(
+ i40evf_xmit_template, i40evf_xmit_frame_ring,
+ TP_PROTO(struct sk_buff *skb,
+ struct i40e_ring *ring),
+
+ TP_ARGS(skb, ring));
+
+DEFINE_EVENT(
+ i40evf_xmit_template, i40evf_xmit_frame_ring_drop,
+ TP_PROTO(struct sk_buff *skb,
+ struct i40e_ring *ring),
+
+ TP_ARGS(skb, ring));
+
+/* Events unique to the VF. */
+
+#endif /* _I40E_TRACE_H_ */
+/* This must be outside ifdef _I40E_TRACE_H */
+
+/* This trace include file is not located in the .../include/trace
+ * with the kernel tracepoint definitions, because we're a loadable
+ * module.
+ */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE i40e_trace
+#include <trace/define_trace.h>
diff --git a/drivers/net/ethernet/intel/iavf/i40e_txrx.c b/drivers/net/ethernet/intel/iavf/i40e_txrx.c
new file mode 100644
index 000000000000..d4bd06adc145
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_txrx.c
@@ -0,0 +1,2513 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#include <linux/prefetch.h>
+#include <net/busy_poll.h>
+
+#include "i40evf.h"
+#include "i40e_trace.h"
+#include "i40e_prototype.h"
+
+static inline __le64 build_ctob(u32 td_cmd, u32 td_offset, unsigned int size,
+ u32 td_tag)
+{
+ return cpu_to_le64(I40E_TX_DESC_DTYPE_DATA |
+ ((u64)td_cmd << I40E_TXD_QW1_CMD_SHIFT) |
+ ((u64)td_offset << I40E_TXD_QW1_OFFSET_SHIFT) |
+ ((u64)size << I40E_TXD_QW1_TX_BUF_SZ_SHIFT) |
+ ((u64)td_tag << I40E_TXD_QW1_L2TAG1_SHIFT));
+}
+
+#define I40E_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS)
+
+/**
+ * i40e_unmap_and_free_tx_resource - Release a Tx buffer
+ * @ring: the ring that owns the buffer
+ * @tx_buffer: the buffer to free
+ **/
+static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring,
+ struct i40e_tx_buffer *tx_buffer)
+{
+ if (tx_buffer->skb) {
+ if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
+ kfree(tx_buffer->raw_buf);
+ else
+ dev_kfree_skb_any(tx_buffer->skb);
+ if (dma_unmap_len(tx_buffer, len))
+ dma_unmap_single(ring->dev,
+ dma_unmap_addr(tx_buffer, dma),
+ dma_unmap_len(tx_buffer, len),
+ DMA_TO_DEVICE);
+ } else if (dma_unmap_len(tx_buffer, len)) {
+ dma_unmap_page(ring->dev,
+ dma_unmap_addr(tx_buffer, dma),
+ dma_unmap_len(tx_buffer, len),
+ DMA_TO_DEVICE);
+ }
+
+ tx_buffer->next_to_watch = NULL;
+ tx_buffer->skb = NULL;
+ dma_unmap_len_set(tx_buffer, len, 0);
+ /* tx_buffer must be completely set up in the transmit path */
+}
+
+/**
+ * i40evf_clean_tx_ring - Free any empty Tx buffers
+ * @tx_ring: ring to be cleaned
+ **/
+void i40evf_clean_tx_ring(struct i40e_ring *tx_ring)
+{
+ unsigned long bi_size;
+ u16 i;
+
+ /* ring already cleared, nothing to do */
+ if (!tx_ring->tx_bi)
+ return;
+
+ /* Free all the Tx ring sk_buffs */
+ for (i = 0; i < tx_ring->count; i++)
+ i40e_unmap_and_free_tx_resource(tx_ring, &tx_ring->tx_bi[i]);
+
+ bi_size = sizeof(struct i40e_tx_buffer) * tx_ring->count;
+ memset(tx_ring->tx_bi, 0, bi_size);
+
+ /* Zero out the descriptor ring */
+ memset(tx_ring->desc, 0, tx_ring->size);
+
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
+
+ if (!tx_ring->netdev)
+ return;
+
+ /* cleanup Tx queue statistics */
+ netdev_tx_reset_queue(txring_txq(tx_ring));
+}
+
+/**
+ * i40evf_free_tx_resources - Free Tx resources per queue
+ * @tx_ring: Tx descriptor ring for a specific queue
+ *
+ * Free all transmit software resources
+ **/
+void i40evf_free_tx_resources(struct i40e_ring *tx_ring)
+{
+ i40evf_clean_tx_ring(tx_ring);
+ kfree(tx_ring->tx_bi);
+ tx_ring->tx_bi = NULL;
+
+ if (tx_ring->desc) {
+ dma_free_coherent(tx_ring->dev, tx_ring->size,
+ tx_ring->desc, tx_ring->dma);
+ tx_ring->desc = NULL;
+ }
+}
+
+/**
+ * i40evf_get_tx_pending - how many Tx descriptors not processed
+ * @ring: the ring of descriptors
+ * @in_sw: is tx_pending being checked in SW or HW
+ *
+ * Since there is no access to the ring head register
+ * in XL710, we need to use our local copies
+ **/
+u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw)
+{
+ u32 head, tail;
+
+ /* underlying hardware might not allow access and/or always return
+ * 0 for the head/tail registers so just use the cached values
+ */
+ head = ring->next_to_clean;
+ tail = ring->next_to_use;
+
+ if (head != tail)
+ return (head < tail) ?
+ tail - head : (tail + ring->count - head);
+
+ return 0;
+}
+
+/**
+ * i40evf_detect_recover_hung - Function to detect and recover hung_queues
+ * @vsi: pointer to vsi struct with tx queues
+ *
+ * VSI has netdev and netdev has TX queues. This function is to check each of
+ * those TX queues if they are hung, trigger recovery by issuing SW interrupt.
+ **/
+void i40evf_detect_recover_hung(struct i40e_vsi *vsi)
+{
+ struct i40e_ring *tx_ring = NULL;
+ struct net_device *netdev;
+ unsigned int i;
+ int packets;
+
+ if (!vsi)
+ return;
+
+ if (test_bit(__I40E_VSI_DOWN, vsi->state))
+ return;
+
+ netdev = vsi->netdev;
+ if (!netdev)
+ return;
+
+ if (!netif_carrier_ok(netdev))
+ return;
+
+ for (i = 0; i < vsi->back->num_active_queues; i++) {
+ tx_ring = &vsi->back->tx_rings[i];
+ if (tx_ring && tx_ring->desc) {
+ /* If packet counter has not changed the queue is
+ * likely stalled, so force an interrupt for this
+ * queue.
+ *
+ * prev_pkt_ctr would be negative if there was no
+ * pending work.
+ */
+ packets = tx_ring->stats.packets & INT_MAX;
+ if (tx_ring->tx_stats.prev_pkt_ctr == packets) {
+ i40evf_force_wb(vsi, tx_ring->q_vector);
+ continue;
+ }
+
+ /* Memory barrier between read of packet count and call
+ * to i40evf_get_tx_pending()
+ */
+ smp_rmb();
+ tx_ring->tx_stats.prev_pkt_ctr =
+ i40evf_get_tx_pending(tx_ring, true) ? packets : -1;
+ }
+ }
+}
+
+#define WB_STRIDE 4
+
+/**
+ * i40e_clean_tx_irq - Reclaim resources after transmit completes
+ * @vsi: the VSI we care about
+ * @tx_ring: Tx ring to clean
+ * @napi_budget: Used to determine if we are in netpoll
+ *
+ * Returns true if there's any budget left (e.g. the clean is finished)
+ **/
+static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
+ struct i40e_ring *tx_ring, int napi_budget)
+{
+ u16 i = tx_ring->next_to_clean;
+ struct i40e_tx_buffer *tx_buf;
+ struct i40e_tx_desc *tx_desc;
+ unsigned int total_bytes = 0, total_packets = 0;
+ unsigned int budget = vsi->work_limit;
+
+ tx_buf = &tx_ring->tx_bi[i];
+ tx_desc = I40E_TX_DESC(tx_ring, i);
+ i -= tx_ring->count;
+
+ do {
+ struct i40e_tx_desc *eop_desc = tx_buf->next_to_watch;
+
+ /* if next_to_watch is not set then there is no work pending */
+ if (!eop_desc)
+ break;
+
+ /* prevent any other reads prior to eop_desc */
+ smp_rmb();
+
+ i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf);
+ /* if the descriptor isn't done, no work yet to do */
+ if (!(eop_desc->cmd_type_offset_bsz &
+ cpu_to_le64(I40E_TX_DESC_DTYPE_DESC_DONE)))
+ break;
+
+ /* clear next_to_watch to prevent false hangs */
+ tx_buf->next_to_watch = NULL;
+
+ /* update the statistics for this packet */
+ total_bytes += tx_buf->bytecount;
+ total_packets += tx_buf->gso_segs;
+
+ /* free the skb */
+ napi_consume_skb(tx_buf->skb, napi_budget);
+
+ /* unmap skb header data */
+ dma_unmap_single(tx_ring->dev,
+ dma_unmap_addr(tx_buf, dma),
+ dma_unmap_len(tx_buf, len),
+ DMA_TO_DEVICE);
+
+ /* clear tx_buffer data */
+ tx_buf->skb = NULL;
+ dma_unmap_len_set(tx_buf, len, 0);
+
+ /* unmap remaining buffers */
+ while (tx_desc != eop_desc) {
+ i40e_trace(clean_tx_irq_unmap,
+ tx_ring, tx_desc, tx_buf);
+
+ tx_buf++;
+ tx_desc++;
+ i++;
+ if (unlikely(!i)) {
+ i -= tx_ring->count;
+ tx_buf = tx_ring->tx_bi;
+ tx_desc = I40E_TX_DESC(tx_ring, 0);
+ }
+
+ /* unmap any remaining paged data */
+ if (dma_unmap_len(tx_buf, len)) {
+ dma_unmap_page(tx_ring->dev,
+ dma_unmap_addr(tx_buf, dma),
+ dma_unmap_len(tx_buf, len),
+ DMA_TO_DEVICE);
+ dma_unmap_len_set(tx_buf, len, 0);
+ }
+ }
+
+ /* move us one more past the eop_desc for start of next pkt */
+ tx_buf++;
+ tx_desc++;
+ i++;
+ if (unlikely(!i)) {
+ i -= tx_ring->count;
+ tx_buf = tx_ring->tx_bi;
+ tx_desc = I40E_TX_DESC(tx_ring, 0);
+ }
+
+ prefetch(tx_desc);
+
+ /* update budget accounting */
+ budget--;
+ } while (likely(budget));
+
+ i += tx_ring->count;
+ tx_ring->next_to_clean = i;
+ u64_stats_update_begin(&tx_ring->syncp);
+ tx_ring->stats.bytes += total_bytes;
+ tx_ring->stats.packets += total_packets;
+ u64_stats_update_end(&tx_ring->syncp);
+ tx_ring->q_vector->tx.total_bytes += total_bytes;
+ tx_ring->q_vector->tx.total_packets += total_packets;
+
+ if (tx_ring->flags & I40E_TXR_FLAGS_WB_ON_ITR) {
+ /* check to see if there are < 4 descriptors
+ * waiting to be written back, then kick the hardware to force
+ * them to be written back in case we stay in NAPI.
+ * In this mode on X722 we do not enable Interrupt.
+ */
+ unsigned int j = i40evf_get_tx_pending(tx_ring, false);
+
+ if (budget &&
+ ((j / WB_STRIDE) == 0) && (j > 0) &&
+ !test_bit(__I40E_VSI_DOWN, vsi->state) &&
+ (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
+ tx_ring->arm_wb = true;
+ }
+
+ /* notify netdev of completed buffers */
+ netdev_tx_completed_queue(txring_txq(tx_ring),
+ total_packets, total_bytes);
+
+#define TX_WAKE_THRESHOLD ((s16)(DESC_NEEDED * 2))
+ if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) &&
+ (I40E_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) {
+ /* Make sure that anybody stopping the queue after this
+ * sees the new next_to_clean.
+ */
+ smp_mb();
+ if (__netif_subqueue_stopped(tx_ring->netdev,
+ tx_ring->queue_index) &&
+ !test_bit(__I40E_VSI_DOWN, vsi->state)) {
+ netif_wake_subqueue(tx_ring->netdev,
+ tx_ring->queue_index);
+ ++tx_ring->tx_stats.restart_queue;
+ }
+ }
+
+ return !!budget;
+}
+
+/**
+ * i40evf_enable_wb_on_itr - Arm hardware to do a wb, interrupts are not enabled
+ * @vsi: the VSI we care about
+ * @q_vector: the vector on which to enable writeback
+ *
+ **/
+static void i40e_enable_wb_on_itr(struct i40e_vsi *vsi,
+ struct i40e_q_vector *q_vector)
+{
+ u16 flags = q_vector->tx.ring[0].flags;
+ u32 val;
+
+ if (!(flags & I40E_TXR_FLAGS_WB_ON_ITR))
+ return;
+
+ if (q_vector->arm_wb_state)
+ return;
+
+ val = I40E_VFINT_DYN_CTLN1_WB_ON_ITR_MASK |
+ I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK; /* set noitr */
+
+ wr32(&vsi->back->hw,
+ I40E_VFINT_DYN_CTLN1(q_vector->reg_idx), val);
+ q_vector->arm_wb_state = true;
+}
+
+/**
+ * i40evf_force_wb - Issue SW Interrupt so HW does a wb
+ * @vsi: the VSI we care about
+ * @q_vector: the vector on which to force writeback
+ *
+ **/
+void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
+{
+ u32 val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+ I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */
+ I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
+ I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK
+ /* allow 00 to be written to the index */;
+
+ wr32(&vsi->back->hw,
+ I40E_VFINT_DYN_CTLN1(q_vector->reg_idx),
+ val);
+}
+
+static inline bool i40e_container_is_rx(struct i40e_q_vector *q_vector,
+ struct i40e_ring_container *rc)
+{
+ return &q_vector->rx == rc;
+}
+
+static inline unsigned int i40e_itr_divisor(struct i40e_q_vector *q_vector)
+{
+ unsigned int divisor;
+
+ switch (q_vector->adapter->link_speed) {
+ case I40E_LINK_SPEED_40GB:
+ divisor = I40E_ITR_ADAPTIVE_MIN_INC * 1024;
+ break;
+ case I40E_LINK_SPEED_25GB:
+ case I40E_LINK_SPEED_20GB:
+ divisor = I40E_ITR_ADAPTIVE_MIN_INC * 512;
+ break;
+ default:
+ case I40E_LINK_SPEED_10GB:
+ divisor = I40E_ITR_ADAPTIVE_MIN_INC * 256;
+ break;
+ case I40E_LINK_SPEED_1GB:
+ case I40E_LINK_SPEED_100MB:
+ divisor = I40E_ITR_ADAPTIVE_MIN_INC * 32;
+ break;
+ }
+
+ return divisor;
+}
+
+/**
+ * i40e_update_itr - update the dynamic ITR value based on statistics
+ * @q_vector: structure containing interrupt and ring information
+ * @rc: structure containing ring performance data
+ *
+ * Stores a new ITR value based on packets and byte
+ * counts during the last interrupt. The advantage of per interrupt
+ * computation is faster updates and more accurate ITR for the current
+ * traffic pattern. Constants in this function were computed
+ * based on theoretical maximum wire speed and thresholds were set based
+ * on testing data as well as attempting to minimize response time
+ * while increasing bulk throughput.
+ **/
+static void i40e_update_itr(struct i40e_q_vector *q_vector,
+ struct i40e_ring_container *rc)
+{
+ unsigned int avg_wire_size, packets, bytes, itr;
+ unsigned long next_update = jiffies;
+
+ /* If we don't have any rings just leave ourselves set for maximum
+ * possible latency so we take ourselves out of the equation.
+ */
+ if (!rc->ring || !ITR_IS_DYNAMIC(rc->ring->itr_setting))
+ return;
+
+ /* For Rx we want to push the delay up and default to low latency.
+ * for Tx we want to pull the delay down and default to high latency.
+ */
+ itr = i40e_container_is_rx(q_vector, rc) ?
+ I40E_ITR_ADAPTIVE_MIN_USECS | I40E_ITR_ADAPTIVE_LATENCY :
+ I40E_ITR_ADAPTIVE_MAX_USECS | I40E_ITR_ADAPTIVE_LATENCY;
+
+ /* If we didn't update within up to 1 - 2 jiffies we can assume
+ * that either packets are coming in so slow there hasn't been
+ * any work, or that there is so much work that NAPI is dealing
+ * with interrupt moderation and we don't need to do anything.
+ */
+ if (time_after(next_update, rc->next_update))
+ goto clear_counts;
+
+ /* If itr_countdown is set it means we programmed an ITR within
+ * the last 4 interrupt cycles. This has a side effect of us
+ * potentially firing an early interrupt. In order to work around
+ * this we need to throw out any data received for a few
+ * interrupts following the update.
+ */
+ if (q_vector->itr_countdown) {
+ itr = rc->target_itr;
+ goto clear_counts;
+ }
+
+ packets = rc->total_packets;
+ bytes = rc->total_bytes;
+
+ if (i40e_container_is_rx(q_vector, rc)) {
+ /* If Rx there are 1 to 4 packets and bytes are less than
+ * 9000 assume insufficient data to use bulk rate limiting
+ * approach unless Tx is already in bulk rate limiting. We
+ * are likely latency driven.
+ */
+ if (packets && packets < 4 && bytes < 9000 &&
+ (q_vector->tx.target_itr & I40E_ITR_ADAPTIVE_LATENCY)) {
+ itr = I40E_ITR_ADAPTIVE_LATENCY;
+ goto adjust_by_size;
+ }
+ } else if (packets < 4) {
+ /* If we have Tx and Rx ITR maxed and Tx ITR is running in
+ * bulk mode and we are receiving 4 or fewer packets just
+ * reset the ITR_ADAPTIVE_LATENCY bit for latency mode so
+ * that the Rx can relax.
+ */
+ if (rc->target_itr == I40E_ITR_ADAPTIVE_MAX_USECS &&
+ (q_vector->rx.target_itr & I40E_ITR_MASK) ==
+ I40E_ITR_ADAPTIVE_MAX_USECS)
+ goto clear_counts;
+ } else if (packets > 32) {
+ /* If we have processed over 32 packets in a single interrupt
+ * for Tx assume we need to switch over to "bulk" mode.
+ */
+ rc->target_itr &= ~I40E_ITR_ADAPTIVE_LATENCY;
+ }
+
+ /* We have no packets to actually measure against. This means
+ * either one of the other queues on this vector is active or
+ * we are a Tx queue doing TSO with too high of an interrupt rate.
+ *
+ * Between 4 and 56 we can assume that our current interrupt delay
+ * is only slightly too low. As such we should increase it by a small
+ * fixed amount.
+ */
+ if (packets < 56) {
+ itr = rc->target_itr + I40E_ITR_ADAPTIVE_MIN_INC;
+ if ((itr & I40E_ITR_MASK) > I40E_ITR_ADAPTIVE_MAX_USECS) {
+ itr &= I40E_ITR_ADAPTIVE_LATENCY;
+ itr += I40E_ITR_ADAPTIVE_MAX_USECS;
+ }
+ goto clear_counts;
+ }
+
+ if (packets <= 256) {
+ itr = min(q_vector->tx.current_itr, q_vector->rx.current_itr);
+ itr &= I40E_ITR_MASK;
+
+ /* Between 56 and 112 is our "goldilocks" zone where we are
+ * working out "just right". Just report that our current
+ * ITR is good for us.
+ */
+ if (packets <= 112)
+ goto clear_counts;
+
+ /* If packet count is 128 or greater we are likely looking
+ * at a slight overrun of the delay we want. Try halving
+ * our delay to see if that will cut the number of packets
+ * in half per interrupt.
+ */
+ itr /= 2;
+ itr &= I40E_ITR_MASK;
+ if (itr < I40E_ITR_ADAPTIVE_MIN_USECS)
+ itr = I40E_ITR_ADAPTIVE_MIN_USECS;
+
+ goto clear_counts;
+ }
+
+ /* The paths below assume we are dealing with a bulk ITR since
+ * number of packets is greater than 256. We are just going to have
+ * to compute a value and try to bring the count under control,
+ * though for smaller packet sizes there isn't much we can do as
+ * NAPI polling will likely be kicking in sooner rather than later.
+ */
+ itr = I40E_ITR_ADAPTIVE_BULK;
+
+adjust_by_size:
+ /* If packet counts are 256 or greater we can assume we have a gross
+ * overestimation of what the rate should be. Instead of trying to fine
+ * tune it just use the formula below to try and dial in an exact value
+ * give the current packet size of the frame.
+ */
+ avg_wire_size = bytes / packets;
+
+ /* The following is a crude approximation of:
+ * wmem_default / (size + overhead) = desired_pkts_per_int
+ * rate / bits_per_byte / (size + ethernet overhead) = pkt_rate
+ * (desired_pkt_rate / pkt_rate) * usecs_per_sec = ITR value
+ *
+ * Assuming wmem_default is 212992 and overhead is 640 bytes per
+ * packet, (256 skb, 64 headroom, 320 shared info), we can reduce the
+ * formula down to
+ *
+ * (170 * (size + 24)) / (size + 640) = ITR
+ *
+ * We first do some math on the packet size and then finally bitshift
+ * by 8 after rounding up. We also have to account for PCIe link speed
+ * difference as ITR scales based on this.
+ */
+ if (avg_wire_size <= 60) {
+ /* Start at 250k ints/sec */
+ avg_wire_size = 4096;
+ } else if (avg_wire_size <= 380) {
+ /* 250K ints/sec to 60K ints/sec */
+ avg_wire_size *= 40;
+ avg_wire_size += 1696;
+ } else if (avg_wire_size <= 1084) {
+ /* 60K ints/sec to 36K ints/sec */
+ avg_wire_size *= 15;
+ avg_wire_size += 11452;
+ } else if (avg_wire_size <= 1980) {
+ /* 36K ints/sec to 30K ints/sec */
+ avg_wire_size *= 5;
+ avg_wire_size += 22420;
+ } else {
+ /* plateau at a limit of 30K ints/sec */
+ avg_wire_size = 32256;
+ }
+
+ /* If we are in low latency mode halve our delay which doubles the
+ * rate to somewhere between 100K to 16K ints/sec
+ */
+ if (itr & I40E_ITR_ADAPTIVE_LATENCY)
+ avg_wire_size /= 2;
+
+ /* Resultant value is 256 times larger than it needs to be. This
+ * gives us room to adjust the value as needed to either increase
+ * or decrease the value based on link speeds of 10G, 2.5G, 1G, etc.
+ *
+ * Use addition as we have already recorded the new latency flag
+ * for the ITR value.
+ */
+ itr += DIV_ROUND_UP(avg_wire_size, i40e_itr_divisor(q_vector)) *
+ I40E_ITR_ADAPTIVE_MIN_INC;
+
+ if ((itr & I40E_ITR_MASK) > I40E_ITR_ADAPTIVE_MAX_USECS) {
+ itr &= I40E_ITR_ADAPTIVE_LATENCY;
+ itr += I40E_ITR_ADAPTIVE_MAX_USECS;
+ }
+
+clear_counts:
+ /* write back value */
+ rc->target_itr = itr;
+
+ /* next update should occur within next jiffy */
+ rc->next_update = next_update + 1;
+
+ rc->total_bytes = 0;
+ rc->total_packets = 0;
+}
+
+/**
+ * i40evf_setup_tx_descriptors - Allocate the Tx descriptors
+ * @tx_ring: the tx ring to set up
+ *
+ * Return 0 on success, negative on error
+ **/
+int i40evf_setup_tx_descriptors(struct i40e_ring *tx_ring)
+{
+ struct device *dev = tx_ring->dev;
+ int bi_size;
+
+ if (!dev)
+ return -ENOMEM;
+
+ /* warn if we are about to overwrite the pointer */
+ WARN_ON(tx_ring->tx_bi);
+ bi_size = sizeof(struct i40e_tx_buffer) * tx_ring->count;
+ tx_ring->tx_bi = kzalloc(bi_size, GFP_KERNEL);
+ if (!tx_ring->tx_bi)
+ goto err;
+
+ /* round up to nearest 4K */
+ tx_ring->size = tx_ring->count * sizeof(struct i40e_tx_desc);
+ tx_ring->size = ALIGN(tx_ring->size, 4096);
+ tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
+ &tx_ring->dma, GFP_KERNEL);
+ if (!tx_ring->desc) {
+ dev_info(dev, "Unable to allocate memory for the Tx descriptor ring, size=%d\n",
+ tx_ring->size);
+ goto err;
+ }
+
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
+ tx_ring->tx_stats.prev_pkt_ctr = -1;
+ return 0;
+
+err:
+ kfree(tx_ring->tx_bi);
+ tx_ring->tx_bi = NULL;
+ return -ENOMEM;
+}
+
+/**
+ * i40evf_clean_rx_ring - Free Rx buffers
+ * @rx_ring: ring to be cleaned
+ **/
+void i40evf_clean_rx_ring(struct i40e_ring *rx_ring)
+{
+ unsigned long bi_size;
+ u16 i;
+
+ /* ring already cleared, nothing to do */
+ if (!rx_ring->rx_bi)
+ return;
+
+ if (rx_ring->skb) {
+ dev_kfree_skb(rx_ring->skb);
+ rx_ring->skb = NULL;
+ }
+
+ /* Free all the Rx ring sk_buffs */
+ for (i = 0; i < rx_ring->count; i++) {
+ struct i40e_rx_buffer *rx_bi = &rx_ring->rx_bi[i];
+
+ if (!rx_bi->page)
+ continue;
+
+ /* Invalidate cache lines that may have been written to by
+ * device so that we avoid corrupting memory.
+ */
+ dma_sync_single_range_for_cpu(rx_ring->dev,
+ rx_bi->dma,
+ rx_bi->page_offset,
+ rx_ring->rx_buf_len,
+ DMA_FROM_DEVICE);
+
+ /* free resources associated with mapping */
+ dma_unmap_page_attrs(rx_ring->dev, rx_bi->dma,
+ i40e_rx_pg_size(rx_ring),
+ DMA_FROM_DEVICE,
+ I40E_RX_DMA_ATTR);
+
+ __page_frag_cache_drain(rx_bi->page, rx_bi->pagecnt_bias);
+
+ rx_bi->page = NULL;
+ rx_bi->page_offset = 0;
+ }
+
+ bi_size = sizeof(struct i40e_rx_buffer) * rx_ring->count;
+ memset(rx_ring->rx_bi, 0, bi_size);
+
+ /* Zero out the descriptor ring */
+ memset(rx_ring->desc, 0, rx_ring->size);
+
+ rx_ring->next_to_alloc = 0;
+ rx_ring->next_to_clean = 0;
+ rx_ring->next_to_use = 0;
+}
+
+/**
+ * i40evf_free_rx_resources - Free Rx resources
+ * @rx_ring: ring to clean the resources from
+ *
+ * Free all receive software resources
+ **/
+void i40evf_free_rx_resources(struct i40e_ring *rx_ring)
+{
+ i40evf_clean_rx_ring(rx_ring);
+ kfree(rx_ring->rx_bi);
+ rx_ring->rx_bi = NULL;
+
+ if (rx_ring->desc) {
+ dma_free_coherent(rx_ring->dev, rx_ring->size,
+ rx_ring->desc, rx_ring->dma);
+ rx_ring->desc = NULL;
+ }
+}
+
+/**
+ * i40evf_setup_rx_descriptors - Allocate Rx descriptors
+ * @rx_ring: Rx descriptor ring (for a specific queue) to setup
+ *
+ * Returns 0 on success, negative on failure
+ **/
+int i40evf_setup_rx_descriptors(struct i40e_ring *rx_ring)
+{
+ struct device *dev = rx_ring->dev;
+ int bi_size;
+
+ /* warn if we are about to overwrite the pointer */
+ WARN_ON(rx_ring->rx_bi);
+ bi_size = sizeof(struct i40e_rx_buffer) * rx_ring->count;
+ rx_ring->rx_bi = kzalloc(bi_size, GFP_KERNEL);
+ if (!rx_ring->rx_bi)
+ goto err;
+
+ u64_stats_init(&rx_ring->syncp);
+
+ /* Round up to nearest 4K */
+ rx_ring->size = rx_ring->count * sizeof(union i40e_32byte_rx_desc);
+ rx_ring->size = ALIGN(rx_ring->size, 4096);
+ rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
+ &rx_ring->dma, GFP_KERNEL);
+
+ if (!rx_ring->desc) {
+ dev_info(dev, "Unable to allocate memory for the Rx descriptor ring, size=%d\n",
+ rx_ring->size);
+ goto err;
+ }
+
+ rx_ring->next_to_alloc = 0;
+ rx_ring->next_to_clean = 0;
+ rx_ring->next_to_use = 0;
+
+ return 0;
+err:
+ kfree(rx_ring->rx_bi);
+ rx_ring->rx_bi = NULL;
+ return -ENOMEM;
+}
+
+/**
+ * i40e_release_rx_desc - Store the new tail and head values
+ * @rx_ring: ring to bump
+ * @val: new head index
+ **/
+static inline void i40e_release_rx_desc(struct i40e_ring *rx_ring, u32 val)
+{
+ rx_ring->next_to_use = val;
+
+ /* update next to alloc since we have filled the ring */
+ rx_ring->next_to_alloc = val;
+
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64).
+ */
+ wmb();
+ writel(val, rx_ring->tail);
+}
+
+/**
+ * i40e_rx_offset - Return expected offset into page to access data
+ * @rx_ring: Ring we are requesting offset of
+ *
+ * Returns the offset value for ring into the data buffer.
+ */
+static inline unsigned int i40e_rx_offset(struct i40e_ring *rx_ring)
+{
+ return ring_uses_build_skb(rx_ring) ? I40E_SKB_PAD : 0;
+}
+
+/**
+ * i40e_alloc_mapped_page - recycle or make a new page
+ * @rx_ring: ring to use
+ * @bi: rx_buffer struct to modify
+ *
+ * Returns true if the page was successfully allocated or
+ * reused.
+ **/
+static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,
+ struct i40e_rx_buffer *bi)
+{
+ struct page *page = bi->page;
+ dma_addr_t dma;
+
+ /* since we are recycling buffers we should seldom need to alloc */
+ if (likely(page)) {
+ rx_ring->rx_stats.page_reuse_count++;
+ return true;
+ }
+
+ /* alloc new page for storage */
+ page = dev_alloc_pages(i40e_rx_pg_order(rx_ring));
+ if (unlikely(!page)) {
+ rx_ring->rx_stats.alloc_page_failed++;
+ return false;
+ }
+
+ /* map page for use */
+ dma = dma_map_page_attrs(rx_ring->dev, page, 0,
+ i40e_rx_pg_size(rx_ring),
+ DMA_FROM_DEVICE,
+ I40E_RX_DMA_ATTR);
+
+ /* if mapping failed free memory back to system since
+ * there isn't much point in holding memory we can't use
+ */
+ if (dma_mapping_error(rx_ring->dev, dma)) {
+ __free_pages(page, i40e_rx_pg_order(rx_ring));
+ rx_ring->rx_stats.alloc_page_failed++;
+ return false;
+ }
+
+ bi->dma = dma;
+ bi->page = page;
+ bi->page_offset = i40e_rx_offset(rx_ring);
+
+ /* initialize pagecnt_bias to 1 representing we fully own page */
+ bi->pagecnt_bias = 1;
+
+ return true;
+}
+
+/**
+ * i40e_receive_skb - Send a completed packet up the stack
+ * @rx_ring: rx ring in play
+ * @skb: packet to send up
+ * @vlan_tag: vlan tag for packet
+ **/
+static void i40e_receive_skb(struct i40e_ring *rx_ring,
+ struct sk_buff *skb, u16 vlan_tag)
+{
+ struct i40e_q_vector *q_vector = rx_ring->q_vector;
+
+ if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+ (vlan_tag & VLAN_VID_MASK))
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
+
+ napi_gro_receive(&q_vector->napi, skb);
+}
+
+/**
+ * i40evf_alloc_rx_buffers - Replace used receive buffers
+ * @rx_ring: ring to place buffers on
+ * @cleaned_count: number of buffers to replace
+ *
+ * Returns false if all allocations were successful, true if any fail
+ **/
+bool i40evf_alloc_rx_buffers(struct i40e_ring *rx_ring, u16 cleaned_count)
+{
+ u16 ntu = rx_ring->next_to_use;
+ union i40e_rx_desc *rx_desc;
+ struct i40e_rx_buffer *bi;
+
+ /* do nothing if no valid netdev defined */
+ if (!rx_ring->netdev || !cleaned_count)
+ return false;
+
+ rx_desc = I40E_RX_DESC(rx_ring, ntu);
+ bi = &rx_ring->rx_bi[ntu];
+
+ do {
+ if (!i40e_alloc_mapped_page(rx_ring, bi))
+ goto no_buffers;
+
+ /* sync the buffer for use by the device */
+ dma_sync_single_range_for_device(rx_ring->dev, bi->dma,
+ bi->page_offset,
+ rx_ring->rx_buf_len,
+ DMA_FROM_DEVICE);
+
+ /* Refresh the desc even if buffer_addrs didn't change
+ * because each write-back erases this info.
+ */
+ rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
+
+ rx_desc++;
+ bi++;
+ ntu++;
+ if (unlikely(ntu == rx_ring->count)) {
+ rx_desc = I40E_RX_DESC(rx_ring, 0);
+ bi = rx_ring->rx_bi;
+ ntu = 0;
+ }
+
+ /* clear the status bits for the next_to_use descriptor */
+ rx_desc->wb.qword1.status_error_len = 0;
+
+ cleaned_count--;
+ } while (cleaned_count);
+
+ if (rx_ring->next_to_use != ntu)
+ i40e_release_rx_desc(rx_ring, ntu);
+
+ return false;
+
+no_buffers:
+ if (rx_ring->next_to_use != ntu)
+ i40e_release_rx_desc(rx_ring, ntu);
+
+ /* make sure to come back via polling to try again after
+ * allocation failure
+ */
+ return true;
+}
+
+/**
+ * i40e_rx_checksum - Indicate in skb if hw indicated a good cksum
+ * @vsi: the VSI we care about
+ * @skb: skb currently being received and modified
+ * @rx_desc: the receive descriptor
+ **/
+static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
+ struct sk_buff *skb,
+ union i40e_rx_desc *rx_desc)
+{
+ struct i40e_rx_ptype_decoded decoded;
+ u32 rx_error, rx_status;
+ bool ipv4, ipv6;
+ u8 ptype;
+ u64 qword;
+
+ qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+ ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT;
+ rx_error = (qword & I40E_RXD_QW1_ERROR_MASK) >>
+ I40E_RXD_QW1_ERROR_SHIFT;
+ rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
+ I40E_RXD_QW1_STATUS_SHIFT;
+ decoded = decode_rx_desc_ptype(ptype);
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+ skb_checksum_none_assert(skb);
+
+ /* Rx csum enabled and ip headers found? */
+ if (!(vsi->netdev->features & NETIF_F_RXCSUM))
+ return;
+
+ /* did the hardware decode the packet and checksum? */
+ if (!(rx_status & BIT(I40E_RX_DESC_STATUS_L3L4P_SHIFT)))
+ return;
+
+ /* both known and outer_ip must be set for the below code to work */
+ if (!(decoded.known && decoded.outer_ip))
+ return;
+
+ ipv4 = (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP) &&
+ (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV4);
+ ipv6 = (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP) &&
+ (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV6);
+
+ if (ipv4 &&
+ (rx_error & (BIT(I40E_RX_DESC_ERROR_IPE_SHIFT) |
+ BIT(I40E_RX_DESC_ERROR_EIPE_SHIFT))))
+ goto checksum_fail;
+
+ /* likely incorrect csum if alternate IP extension headers found */
+ if (ipv6 &&
+ rx_status & BIT(I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
+ /* don't increment checksum err here, non-fatal err */
+ return;
+
+ /* there was some L4 error, count error and punt packet to the stack */
+ if (rx_error & BIT(I40E_RX_DESC_ERROR_L4E_SHIFT))
+ goto checksum_fail;
+
+ /* handle packets that were not able to be checksummed due
+ * to arrival speed, in this case the stack can compute
+ * the csum.
+ */
+ if (rx_error & BIT(I40E_RX_DESC_ERROR_PPRS_SHIFT))
+ return;
+
+ /* Only report checksum unnecessary for TCP, UDP, or SCTP */
+ switch (decoded.inner_prot) {
+ case I40E_RX_PTYPE_INNER_PROT_TCP:
+ case I40E_RX_PTYPE_INNER_PROT_UDP:
+ case I40E_RX_PTYPE_INNER_PROT_SCTP:
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ /* fall though */
+ default:
+ break;
+ }
+
+ return;
+
+checksum_fail:
+ vsi->back->hw_csum_rx_error++;
+}
+
+/**
+ * i40e_ptype_to_htype - get a hash type
+ * @ptype: the ptype value from the descriptor
+ *
+ * Returns a hash type to be used by skb_set_hash
+ **/
+static inline int i40e_ptype_to_htype(u8 ptype)
+{
+ struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype);
+
+ if (!decoded.known)
+ return PKT_HASH_TYPE_NONE;
+
+ if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
+ decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4)
+ return PKT_HASH_TYPE_L4;
+ else if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
+ decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3)
+ return PKT_HASH_TYPE_L3;
+ else
+ return PKT_HASH_TYPE_L2;
+}
+
+/**
+ * i40e_rx_hash - set the hash value in the skb
+ * @ring: descriptor ring
+ * @rx_desc: specific descriptor
+ * @skb: skb currently being received and modified
+ * @rx_ptype: Rx packet type
+ **/
+static inline void i40e_rx_hash(struct i40e_ring *ring,
+ union i40e_rx_desc *rx_desc,
+ struct sk_buff *skb,
+ u8 rx_ptype)
+{
+ u32 hash;
+ const __le64 rss_mask =
+ cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
+ I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
+
+ if (!(ring->netdev->features & NETIF_F_RXHASH))
+ return;
+
+ if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
+ hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
+ skb_set_hash(skb, hash, i40e_ptype_to_htype(rx_ptype));
+ }
+}
+
+/**
+ * i40evf_process_skb_fields - Populate skb header fields from Rx descriptor
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being populated
+ * @rx_ptype: the packet type decoded by hardware
+ *
+ * This function checks the ring, descriptor, and packet information in
+ * order to populate the hash, checksum, VLAN, protocol, and
+ * other fields within the skb.
+ **/
+static inline
+void i40evf_process_skb_fields(struct i40e_ring *rx_ring,
+ union i40e_rx_desc *rx_desc, struct sk_buff *skb,
+ u8 rx_ptype)
+{
+ i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype);
+
+ i40e_rx_checksum(rx_ring->vsi, skb, rx_desc);
+
+ skb_record_rx_queue(skb, rx_ring->queue_index);
+
+ /* modifies the skb - consumes the enet header */
+ skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+}
+
+/**
+ * i40e_cleanup_headers - Correct empty headers
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @skb: pointer to current skb being fixed
+ *
+ * Also address the case where we are pulling data in on pages only
+ * and as such no data is present in the skb header.
+ *
+ * In addition if skb is not at least 60 bytes we need to pad it so that
+ * it is large enough to qualify as a valid Ethernet frame.
+ *
+ * Returns true if an error was encountered and skb was freed.
+ **/
+static bool i40e_cleanup_headers(struct i40e_ring *rx_ring, struct sk_buff *skb)
+{
+ /* if eth_skb_pad returns an error the skb was freed */
+ if (eth_skb_pad(skb))
+ return true;
+
+ return false;
+}
+
+/**
+ * i40e_reuse_rx_page - page flip buffer and store it back on the ring
+ * @rx_ring: rx descriptor ring to store buffers on
+ * @old_buff: donor buffer to have page reused
+ *
+ * Synchronizes page for reuse by the adapter
+ **/
+static void i40e_reuse_rx_page(struct i40e_ring *rx_ring,
+ struct i40e_rx_buffer *old_buff)
+{
+ struct i40e_rx_buffer *new_buff;
+ u16 nta = rx_ring->next_to_alloc;
+
+ new_buff = &rx_ring->rx_bi[nta];
+
+ /* update, and store next to alloc */
+ nta++;
+ rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
+
+ /* transfer page from old buffer to new buffer */
+ new_buff->dma = old_buff->dma;
+ new_buff->page = old_buff->page;
+ new_buff->page_offset = old_buff->page_offset;
+ new_buff->pagecnt_bias = old_buff->pagecnt_bias;
+}
+
+/**
+ * i40e_page_is_reusable - check if any reuse is possible
+ * @page: page struct to check
+ *
+ * A page is not reusable if it was allocated under low memory
+ * conditions, or it's not in the same NUMA node as this CPU.
+ */
+static inline bool i40e_page_is_reusable(struct page *page)
+{
+ return (page_to_nid(page) == numa_mem_id()) &&
+ !page_is_pfmemalloc(page);
+}
+
+/**
+ * i40e_can_reuse_rx_page - Determine if this page can be reused by
+ * the adapter for another receive
+ *
+ * @rx_buffer: buffer containing the page
+ *
+ * If page is reusable, rx_buffer->page_offset is adjusted to point to
+ * an unused region in the page.
+ *
+ * For small pages, @truesize will be a constant value, half the size
+ * of the memory at page. We'll attempt to alternate between high and
+ * low halves of the page, with one half ready for use by the hardware
+ * and the other half being consumed by the stack. We use the page
+ * ref count to determine whether the stack has finished consuming the
+ * portion of this page that was passed up with a previous packet. If
+ * the page ref count is >1, we'll assume the "other" half page is
+ * still busy, and this page cannot be reused.
+ *
+ * For larger pages, @truesize will be the actual space used by the
+ * received packet (adjusted upward to an even multiple of the cache
+ * line size). This will advance through the page by the amount
+ * actually consumed by the received packets while there is still
+ * space for a buffer. Each region of larger pages will be used at
+ * most once, after which the page will not be reused.
+ *
+ * In either case, if the page is reusable its refcount is increased.
+ **/
+static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer)
+{
+ unsigned int pagecnt_bias = rx_buffer->pagecnt_bias;
+ struct page *page = rx_buffer->page;
+
+ /* Is any reuse possible? */
+ if (unlikely(!i40e_page_is_reusable(page)))
+ return false;
+
+#if (PAGE_SIZE < 8192)
+ /* if we are only owner of page we can reuse it */
+ if (unlikely((page_count(page) - pagecnt_bias) > 1))
+ return false;
+#else
+#define I40E_LAST_OFFSET \
+ (SKB_WITH_OVERHEAD(PAGE_SIZE) - I40E_RXBUFFER_2048)
+ if (rx_buffer->page_offset > I40E_LAST_OFFSET)
+ return false;
+#endif
+
+ /* If we have drained the page fragment pool we need to update
+ * the pagecnt_bias and page count so that we fully restock the
+ * number of references the driver holds.
+ */
+ if (unlikely(!pagecnt_bias)) {
+ page_ref_add(page, USHRT_MAX);
+ rx_buffer->pagecnt_bias = USHRT_MAX;
+ }
+
+ return true;
+}
+
+/**
+ * i40e_add_rx_frag - Add contents of Rx buffer to sk_buff
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: buffer containing page to add
+ * @skb: sk_buff to place the data into
+ * @size: packet length from rx_desc
+ *
+ * This function will add the data contained in rx_buffer->page to the skb.
+ * It will just attach the page as a frag to the skb.
+ *
+ * The function will then update the page offset.
+ **/
+static void i40e_add_rx_frag(struct i40e_ring *rx_ring,
+ struct i40e_rx_buffer *rx_buffer,
+ struct sk_buff *skb,
+ unsigned int size)
+{
+#if (PAGE_SIZE < 8192)
+ unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
+#else
+ unsigned int truesize = SKB_DATA_ALIGN(size + i40e_rx_offset(rx_ring));
+#endif
+
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page,
+ rx_buffer->page_offset, size, truesize);
+
+ /* page is being used so we must update the page offset */
+#if (PAGE_SIZE < 8192)
+ rx_buffer->page_offset ^= truesize;
+#else
+ rx_buffer->page_offset += truesize;
+#endif
+}
+
+/**
+ * i40e_get_rx_buffer - Fetch Rx buffer and synchronize data for use
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @size: size of buffer to add to skb
+ *
+ * This function will pull an Rx buffer from the ring and synchronize it
+ * for use by the CPU.
+ */
+static struct i40e_rx_buffer *i40e_get_rx_buffer(struct i40e_ring *rx_ring,
+ const unsigned int size)
+{
+ struct i40e_rx_buffer *rx_buffer;
+
+ rx_buffer = &rx_ring->rx_bi[rx_ring->next_to_clean];
+ prefetchw(rx_buffer->page);
+
+ /* we are reusing so sync this buffer for CPU use */
+ dma_sync_single_range_for_cpu(rx_ring->dev,
+ rx_buffer->dma,
+ rx_buffer->page_offset,
+ size,
+ DMA_FROM_DEVICE);
+
+ /* We have pulled a buffer for use, so decrement pagecnt_bias */
+ rx_buffer->pagecnt_bias--;
+
+ return rx_buffer;
+}
+
+/**
+ * i40e_construct_skb - Allocate skb and populate it
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: rx buffer to pull data from
+ * @size: size of buffer to add to skb
+ *
+ * This function allocates an skb. It then populates it with the page
+ * data from the current receive descriptor, taking care to set up the
+ * skb correctly.
+ */
+static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring,
+ struct i40e_rx_buffer *rx_buffer,
+ unsigned int size)
+{
+ void *va;
+#if (PAGE_SIZE < 8192)
+ unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
+#else
+ unsigned int truesize = SKB_DATA_ALIGN(size);
+#endif
+ unsigned int headlen;
+ struct sk_buff *skb;
+
+ /* prefetch first cache line of first page */
+ va = page_address(rx_buffer->page) + rx_buffer->page_offset;
+ prefetch(va);
+#if L1_CACHE_BYTES < 128
+ prefetch(va + L1_CACHE_BYTES);
+#endif
+
+ /* allocate a skb to store the frags */
+ skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
+ I40E_RX_HDR_SIZE,
+ GFP_ATOMIC | __GFP_NOWARN);
+ if (unlikely(!skb))
+ return NULL;
+
+ /* Determine available headroom for copy */
+ headlen = size;
+ if (headlen > I40E_RX_HDR_SIZE)
+ headlen = eth_get_headlen(va, I40E_RX_HDR_SIZE);
+
+ /* align pull length to size of long to optimize memcpy performance */
+ memcpy(__skb_put(skb, headlen), va, ALIGN(headlen, sizeof(long)));
+
+ /* update all of the pointers */
+ size -= headlen;
+ if (size) {
+ skb_add_rx_frag(skb, 0, rx_buffer->page,
+ rx_buffer->page_offset + headlen,
+ size, truesize);
+
+ /* buffer is used by skb, update page_offset */
+#if (PAGE_SIZE < 8192)
+ rx_buffer->page_offset ^= truesize;
+#else
+ rx_buffer->page_offset += truesize;
+#endif
+ } else {
+ /* buffer is unused, reset bias back to rx_buffer */
+ rx_buffer->pagecnt_bias++;
+ }
+
+ return skb;
+}
+
+/**
+ * i40e_build_skb - Build skb around an existing buffer
+ * @rx_ring: Rx descriptor ring to transact packets on
+ * @rx_buffer: Rx buffer to pull data from
+ * @size: size of buffer to add to skb
+ *
+ * This function builds an skb around an existing Rx buffer, taking care
+ * to set up the skb correctly and avoid any memcpy overhead.
+ */
+static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
+ struct i40e_rx_buffer *rx_buffer,
+ unsigned int size)
+{
+ void *va;
+#if (PAGE_SIZE < 8192)
+ unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
+#else
+ unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
+ SKB_DATA_ALIGN(I40E_SKB_PAD + size);
+#endif
+ struct sk_buff *skb;
+
+ /* prefetch first cache line of first page */
+ va = page_address(rx_buffer->page) + rx_buffer->page_offset;
+ prefetch(va);
+#if L1_CACHE_BYTES < 128
+ prefetch(va + L1_CACHE_BYTES);
+#endif
+ /* build an skb around the page buffer */
+ skb = build_skb(va - I40E_SKB_PAD, truesize);
+ if (unlikely(!skb))
+ return NULL;
+
+ /* update pointers within the skb to store the data */
+ skb_reserve(skb, I40E_SKB_PAD);
+ __skb_put(skb, size);
+
+ /* buffer is used by skb, update page_offset */
+#if (PAGE_SIZE < 8192)
+ rx_buffer->page_offset ^= truesize;
+#else
+ rx_buffer->page_offset += truesize;
+#endif
+
+ return skb;
+}
+
+/**
+ * i40e_put_rx_buffer - Clean up used buffer and either recycle or free
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: rx buffer to pull data from
+ *
+ * This function will clean up the contents of the rx_buffer. It will
+ * either recycle the buffer or unmap it and free the associated resources.
+ */
+static void i40e_put_rx_buffer(struct i40e_ring *rx_ring,
+ struct i40e_rx_buffer *rx_buffer)
+{
+ if (i40e_can_reuse_rx_page(rx_buffer)) {
+ /* hand second half of page back to the ring */
+ i40e_reuse_rx_page(rx_ring, rx_buffer);
+ rx_ring->rx_stats.page_reuse_count++;
+ } else {
+ /* we are not reusing the buffer so unmap it */
+ dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma,
+ i40e_rx_pg_size(rx_ring),
+ DMA_FROM_DEVICE, I40E_RX_DMA_ATTR);
+ __page_frag_cache_drain(rx_buffer->page,
+ rx_buffer->pagecnt_bias);
+ }
+
+ /* clear contents of buffer_info */
+ rx_buffer->page = NULL;
+}
+
+/**
+ * i40e_is_non_eop - process handling of non-EOP buffers
+ * @rx_ring: Rx ring being processed
+ * @rx_desc: Rx descriptor for current buffer
+ * @skb: Current socket buffer containing buffer in progress
+ *
+ * This function updates next to clean. If the buffer is an EOP buffer
+ * this function exits returning false, otherwise it will place the
+ * sk_buff in the next buffer to be chained and return true indicating
+ * that this is in fact a non-EOP buffer.
+ **/
+static bool i40e_is_non_eop(struct i40e_ring *rx_ring,
+ union i40e_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ u32 ntc = rx_ring->next_to_clean + 1;
+
+ /* fetch, update, and store next to clean */
+ ntc = (ntc < rx_ring->count) ? ntc : 0;
+ rx_ring->next_to_clean = ntc;
+
+ prefetch(I40E_RX_DESC(rx_ring, ntc));
+
+ /* if we are the last buffer then there is nothing else to do */
+#define I40E_RXD_EOF BIT(I40E_RX_DESC_STATUS_EOF_SHIFT)
+ if (likely(i40e_test_staterr(rx_desc, I40E_RXD_EOF)))
+ return false;
+
+ rx_ring->rx_stats.non_eop_descs++;
+
+ return true;
+}
+
+/**
+ * i40e_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @budget: Total limit on number of packets to process
+ *
+ * This function provides a "bounce buffer" approach to Rx interrupt
+ * processing. The advantage to this is that on systems that have
+ * expensive overhead for IOMMU access this provides a means of avoiding
+ * it by maintaining the mapping of the page to the system.
+ *
+ * Returns amount of work completed
+ **/
+static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
+{
+ unsigned int total_rx_bytes = 0, total_rx_packets = 0;
+ struct sk_buff *skb = rx_ring->skb;
+ u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
+ bool failure = false;
+
+ while (likely(total_rx_packets < (unsigned int)budget)) {
+ struct i40e_rx_buffer *rx_buffer;
+ union i40e_rx_desc *rx_desc;
+ unsigned int size;
+ u16 vlan_tag;
+ u8 rx_ptype;
+ u64 qword;
+
+ /* return some buffers to hardware, one at a time is too slow */
+ if (cleaned_count >= I40E_RX_BUFFER_WRITE) {
+ failure = failure ||
+ i40evf_alloc_rx_buffers(rx_ring, cleaned_count);
+ cleaned_count = 0;
+ }
+
+ rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean);
+
+ /* status_error_len will always be zero for unused descriptors
+ * because it's cleared in cleanup, and overlaps with hdr_addr
+ * which is always zero because packet split isn't used, if the
+ * hardware wrote DD then the length will be non-zero
+ */
+ qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+
+ /* This memory barrier is needed to keep us from reading
+ * any other fields out of the rx_desc until we have
+ * verified the descriptor has been written back.
+ */
+ dma_rmb();
+
+ size = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) >>
+ I40E_RXD_QW1_LENGTH_PBUF_SHIFT;
+ if (!size)
+ break;
+
+ i40e_trace(clean_rx_irq, rx_ring, rx_desc, skb);
+ rx_buffer = i40e_get_rx_buffer(rx_ring, size);
+
+ /* retrieve a buffer from the ring */
+ if (skb)
+ i40e_add_rx_frag(rx_ring, rx_buffer, skb, size);
+ else if (ring_uses_build_skb(rx_ring))
+ skb = i40e_build_skb(rx_ring, rx_buffer, size);
+ else
+ skb = i40e_construct_skb(rx_ring, rx_buffer, size);
+
+ /* exit if we failed to retrieve a buffer */
+ if (!skb) {
+ rx_ring->rx_stats.alloc_buff_failed++;
+ rx_buffer->pagecnt_bias++;
+ break;
+ }
+
+ i40e_put_rx_buffer(rx_ring, rx_buffer);
+ cleaned_count++;
+
+ if (i40e_is_non_eop(rx_ring, rx_desc, skb))
+ continue;
+
+ /* ERR_MASK will only have valid bits if EOP set, and
+ * what we are doing here is actually checking
+ * I40E_RX_DESC_ERROR_RXE_SHIFT, since it is the zeroth bit in
+ * the error field
+ */
+ if (unlikely(i40e_test_staterr(rx_desc, BIT(I40E_RXD_QW1_ERROR_SHIFT)))) {
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+ continue;
+ }
+
+ if (i40e_cleanup_headers(rx_ring, skb)) {
+ skb = NULL;
+ continue;
+ }
+
+ /* probably a little skewed due to removing CRC */
+ total_rx_bytes += skb->len;
+
+ qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+ rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+ I40E_RXD_QW1_PTYPE_SHIFT;
+
+ /* populate checksum, VLAN, and protocol */
+ i40evf_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
+
+
+ vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?
+ le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;
+
+ i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
+ i40e_receive_skb(rx_ring, skb, vlan_tag);
+ skb = NULL;
+
+ /* update budget accounting */
+ total_rx_packets++;
+ }
+
+ rx_ring->skb = skb;
+
+ u64_stats_update_begin(&rx_ring->syncp);
+ rx_ring->stats.packets += total_rx_packets;
+ rx_ring->stats.bytes += total_rx_bytes;
+ u64_stats_update_end(&rx_ring->syncp);
+ rx_ring->q_vector->rx.total_packets += total_rx_packets;
+ rx_ring->q_vector->rx.total_bytes += total_rx_bytes;
+
+ /* guarantee a trip back through this routine if there was a failure */
+ return failure ? budget : (int)total_rx_packets;
+}
+
+static inline u32 i40e_buildreg_itr(const int type, u16 itr)
+{
+ u32 val;
+
+ /* We don't bother with setting the CLEARPBA bit as the data sheet
+ * points out doing so is "meaningless since it was already
+ * auto-cleared". The auto-clearing happens when the interrupt is
+ * asserted.
+ *
+ * Hardware errata 28 for also indicates that writing to a
+ * xxINT_DYN_CTLx CSR with INTENA_MSK (bit 31) set to 0 will clear
+ * an event in the PBA anyway so we need to rely on the automask
+ * to hold pending events for us until the interrupt is re-enabled
+ *
+ * The itr value is reported in microseconds, and the register
+ * value is recorded in 2 microsecond units. For this reason we
+ * only need to shift by the interval shift - 1 instead of the
+ * full value.
+ */
+ itr &= I40E_ITR_MASK;
+
+ val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+ (type << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) |
+ (itr << (I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT - 1));
+
+ return val;
+}
+
+/* a small macro to shorten up some long lines */
+#define INTREG I40E_VFINT_DYN_CTLN1
+
+/* The act of updating the ITR will cause it to immediately trigger. In order
+ * to prevent this from throwing off adaptive update statistics we defer the
+ * update so that it can only happen so often. So after either Tx or Rx are
+ * updated we make the adaptive scheme wait until either the ITR completely
+ * expires via the next_update expiration or we have been through at least
+ * 3 interrupts.
+ */
+#define ITR_COUNTDOWN_START 3
+
+/**
+ * i40e_update_enable_itr - Update itr and re-enable MSIX interrupt
+ * @vsi: the VSI we care about
+ * @q_vector: q_vector for which itr is being updated and interrupt enabled
+ *
+ **/
+static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
+ struct i40e_q_vector *q_vector)
+{
+ struct i40e_hw *hw = &vsi->back->hw;
+ u32 intval;
+
+ /* These will do nothing if dynamic updates are not enabled */
+ i40e_update_itr(q_vector, &q_vector->tx);
+ i40e_update_itr(q_vector, &q_vector->rx);
+
+ /* This block of logic allows us to get away with only updating
+ * one ITR value with each interrupt. The idea is to perform a
+ * pseudo-lazy update with the following criteria.
+ *
+ * 1. Rx is given higher priority than Tx if both are in same state
+ * 2. If we must reduce an ITR that is given highest priority.
+ * 3. We then give priority to increasing ITR based on amount.
+ */
+ if (q_vector->rx.target_itr < q_vector->rx.current_itr) {
+ /* Rx ITR needs to be reduced, this is highest priority */
+ intval = i40e_buildreg_itr(I40E_RX_ITR,
+ q_vector->rx.target_itr);
+ q_vector->rx.current_itr = q_vector->rx.target_itr;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+ } else if ((q_vector->tx.target_itr < q_vector->tx.current_itr) ||
+ ((q_vector->rx.target_itr - q_vector->rx.current_itr) <
+ (q_vector->tx.target_itr - q_vector->tx.current_itr))) {
+ /* Tx ITR needs to be reduced, this is second priority
+ * Tx ITR needs to be increased more than Rx, fourth priority
+ */
+ intval = i40e_buildreg_itr(I40E_TX_ITR,
+ q_vector->tx.target_itr);
+ q_vector->tx.current_itr = q_vector->tx.target_itr;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+ } else if (q_vector->rx.current_itr != q_vector->rx.target_itr) {
+ /* Rx ITR needs to be increased, third priority */
+ intval = i40e_buildreg_itr(I40E_RX_ITR,
+ q_vector->rx.target_itr);
+ q_vector->rx.current_itr = q_vector->rx.target_itr;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+ } else {
+ /* No ITR update, lowest priority */
+ intval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
+ if (q_vector->itr_countdown)
+ q_vector->itr_countdown--;
+ }
+
+ if (!test_bit(__I40E_VSI_DOWN, vsi->state))
+ wr32(hw, INTREG(q_vector->reg_idx), intval);
+}
+
+/**
+ * i40evf_napi_poll - NAPI polling Rx/Tx cleanup routine
+ * @napi: napi struct with our devices info in it
+ * @budget: amount of work driver is allowed to do this pass, in packets
+ *
+ * This function will clean all queues associated with a q_vector.
+ *
+ * Returns the amount of work done
+ **/
+int i40evf_napi_poll(struct napi_struct *napi, int budget)
+{
+ struct i40e_q_vector *q_vector =
+ container_of(napi, struct i40e_q_vector, napi);
+ struct i40e_vsi *vsi = q_vector->vsi;
+ struct i40e_ring *ring;
+ bool clean_complete = true;
+ bool arm_wb = false;
+ int budget_per_ring;
+ int work_done = 0;
+
+ if (test_bit(__I40E_VSI_DOWN, vsi->state)) {
+ napi_complete(napi);
+ return 0;
+ }
+
+ /* Since the actual Tx work is minimal, we can give the Tx a larger
+ * budget and be more aggressive about cleaning up the Tx descriptors.
+ */
+ i40e_for_each_ring(ring, q_vector->tx) {
+ if (!i40e_clean_tx_irq(vsi, ring, budget)) {
+ clean_complete = false;
+ continue;
+ }
+ arm_wb |= ring->arm_wb;
+ ring->arm_wb = false;
+ }
+
+ /* Handle case where we are called by netpoll with a budget of 0 */
+ if (budget <= 0)
+ goto tx_only;
+
+ /* We attempt to distribute budget to each Rx queue fairly, but don't
+ * allow the budget to go below 1 because that would exit polling early.
+ */
+ budget_per_ring = max(budget/q_vector->num_ringpairs, 1);
+
+ i40e_for_each_ring(ring, q_vector->rx) {
+ int cleaned = i40e_clean_rx_irq(ring, budget_per_ring);
+
+ work_done += cleaned;
+ /* if we clean as many as budgeted, we must not be done */
+ if (cleaned >= budget_per_ring)
+ clean_complete = false;
+ }
+
+ /* If work not completed, return budget and polling will return */
+ if (!clean_complete) {
+ int cpu_id = smp_processor_id();
+
+ /* It is possible that the interrupt affinity has changed but,
+ * if the cpu is pegged at 100%, polling will never exit while
+ * traffic continues and the interrupt will be stuck on this
+ * cpu. We check to make sure affinity is correct before we
+ * continue to poll, otherwise we must stop polling so the
+ * interrupt can move to the correct cpu.
+ */
+ if (!cpumask_test_cpu(cpu_id, &q_vector->affinity_mask)) {
+ /* Tell napi that we are done polling */
+ napi_complete_done(napi, work_done);
+
+ /* Force an interrupt */
+ i40evf_force_wb(vsi, q_vector);
+
+ /* Return budget-1 so that polling stops */
+ return budget - 1;
+ }
+tx_only:
+ if (arm_wb) {
+ q_vector->tx.ring[0].tx_stats.tx_force_wb++;
+ i40e_enable_wb_on_itr(vsi, q_vector);
+ }
+ return budget;
+ }
+
+ if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
+ q_vector->arm_wb_state = false;
+
+ /* Work is done so exit the polling mode and re-enable the interrupt */
+ napi_complete_done(napi, work_done);
+
+ i40e_update_enable_itr(vsi, q_vector);
+
+ return min(work_done, budget - 1);
+}
+
+/**
+ * i40evf_tx_prepare_vlan_flags - prepare generic TX VLAN tagging flags for HW
+ * @skb: send buffer
+ * @tx_ring: ring to send buffer on
+ * @flags: the tx flags to be set
+ *
+ * Checks the skb and set up correspondingly several generic transmit flags
+ * related to VLAN tagging for the HW, such as VLAN, DCB, etc.
+ *
+ * Returns error code indicate the frame should be dropped upon error and the
+ * otherwise returns 0 to indicate the flags has been set properly.
+ **/
+static inline int i40evf_tx_prepare_vlan_flags(struct sk_buff *skb,
+ struct i40e_ring *tx_ring,
+ u32 *flags)
+{
+ __be16 protocol = skb->protocol;
+ u32 tx_flags = 0;
+
+ if (protocol == htons(ETH_P_8021Q) &&
+ !(tx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) {
+ /* When HW VLAN acceleration is turned off by the user the
+ * stack sets the protocol to 8021q so that the driver
+ * can take any steps required to support the SW only
+ * VLAN handling. In our case the driver doesn't need
+ * to take any further steps so just set the protocol
+ * to the encapsulated ethertype.
+ */
+ skb->protocol = vlan_get_protocol(skb);
+ goto out;
+ }
+
+ /* if we have a HW VLAN tag being added, default to the HW one */
+ if (skb_vlan_tag_present(skb)) {
+ tx_flags |= skb_vlan_tag_get(skb) << I40E_TX_FLAGS_VLAN_SHIFT;
+ tx_flags |= I40E_TX_FLAGS_HW_VLAN;
+ /* else if it is a SW VLAN, check the next protocol and store the tag */
+ } else if (protocol == htons(ETH_P_8021Q)) {
+ struct vlan_hdr *vhdr, _vhdr;
+
+ vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr);
+ if (!vhdr)
+ return -EINVAL;
+
+ protocol = vhdr->h_vlan_encapsulated_proto;
+ tx_flags |= ntohs(vhdr->h_vlan_TCI) << I40E_TX_FLAGS_VLAN_SHIFT;
+ tx_flags |= I40E_TX_FLAGS_SW_VLAN;
+ }
+
+out:
+ *flags = tx_flags;
+ return 0;
+}
+
+/**
+ * i40e_tso - set up the tso context descriptor
+ * @first: pointer to first Tx buffer for xmit
+ * @hdr_len: ptr to the size of the packet header
+ * @cd_type_cmd_tso_mss: Quad Word 1
+ *
+ * Returns 0 if no TSO can happen, 1 if tso is going, or error
+ **/
+static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
+ u64 *cd_type_cmd_tso_mss)
+{
+ struct sk_buff *skb = first->skb;
+ u64 cd_cmd, cd_tso_len, cd_mss;
+ union {
+ struct iphdr *v4;
+ struct ipv6hdr *v6;
+ unsigned char *hdr;
+ } ip;
+ union {
+ struct tcphdr *tcp;
+ struct udphdr *udp;
+ unsigned char *hdr;
+ } l4;
+ u32 paylen, l4_offset;
+ u16 gso_segs, gso_size;
+ int err;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
+
+ if (!skb_is_gso(skb))
+ return 0;
+
+ err = skb_cow_head(skb, 0);
+ if (err < 0)
+ return err;
+
+ ip.hdr = skb_network_header(skb);
+ l4.hdr = skb_transport_header(skb);
+
+ /* initialize outer IP header fields */
+ if (ip.v4->version == 4) {
+ ip.v4->tot_len = 0;
+ ip.v4->check = 0;
+ } else {
+ ip.v6->payload_len = 0;
+ }
+
+ if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
+ SKB_GSO_GRE_CSUM |
+ SKB_GSO_IPXIP4 |
+ SKB_GSO_IPXIP6 |
+ SKB_GSO_UDP_TUNNEL |
+ SKB_GSO_UDP_TUNNEL_CSUM)) {
+ if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
+ (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)) {
+ l4.udp->len = 0;
+
+ /* determine offset of outer transport header */
+ l4_offset = l4.hdr - skb->data;
+
+ /* remove payload length from outer checksum */
+ paylen = skb->len - l4_offset;
+ csum_replace_by_diff(&l4.udp->check,
+ (__force __wsum)htonl(paylen));
+ }
+
+ /* reset pointers to inner headers */
+ ip.hdr = skb_inner_network_header(skb);
+ l4.hdr = skb_inner_transport_header(skb);
+
+ /* initialize inner IP header fields */
+ if (ip.v4->version == 4) {
+ ip.v4->tot_len = 0;
+ ip.v4->check = 0;
+ } else {
+ ip.v6->payload_len = 0;
+ }
+ }
+
+ /* determine offset of inner transport header */
+ l4_offset = l4.hdr - skb->data;
+
+ /* remove payload length from inner checksum */
+ paylen = skb->len - l4_offset;
+ csum_replace_by_diff(&l4.tcp->check, (__force __wsum)htonl(paylen));
+
+ /* compute length of segmentation header */
+ *hdr_len = (l4.tcp->doff * 4) + l4_offset;
+
+ /* pull values out of skb_shinfo */
+ gso_size = skb_shinfo(skb)->gso_size;
+ gso_segs = skb_shinfo(skb)->gso_segs;
+
+ /* update GSO size and bytecount with header size */
+ first->gso_segs = gso_segs;
+ first->bytecount += (first->gso_segs - 1) * *hdr_len;
+
+ /* find the field values */
+ cd_cmd = I40E_TX_CTX_DESC_TSO;
+ cd_tso_len = skb->len - *hdr_len;
+ cd_mss = gso_size;
+ *cd_type_cmd_tso_mss |= (cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |
+ (cd_tso_len << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
+ (cd_mss << I40E_TXD_CTX_QW1_MSS_SHIFT);
+ return 1;
+}
+
+/**
+ * i40e_tx_enable_csum - Enable Tx checksum offloads
+ * @skb: send buffer
+ * @tx_flags: pointer to Tx flags currently set
+ * @td_cmd: Tx descriptor command bits to set
+ * @td_offset: Tx descriptor header offsets to set
+ * @tx_ring: Tx descriptor ring
+ * @cd_tunneling: ptr to context desc bits
+ **/
+static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
+ u32 *td_cmd, u32 *td_offset,
+ struct i40e_ring *tx_ring,
+ u32 *cd_tunneling)
+{
+ union {
+ struct iphdr *v4;
+ struct ipv6hdr *v6;
+ unsigned char *hdr;
+ } ip;
+ union {
+ struct tcphdr *tcp;
+ struct udphdr *udp;
+ unsigned char *hdr;
+ } l4;
+ unsigned char *exthdr;
+ u32 offset, cmd = 0;
+ __be16 frag_off;
+ u8 l4_proto = 0;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
+
+ ip.hdr = skb_network_header(skb);
+ l4.hdr = skb_transport_header(skb);
+
+ /* compute outer L2 header size */
+ offset = ((ip.hdr - skb->data) / 2) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
+
+ if (skb->encapsulation) {
+ u32 tunnel = 0;
+ /* define outer network header type */
+ if (*tx_flags & I40E_TX_FLAGS_IPV4) {
+ tunnel |= (*tx_flags & I40E_TX_FLAGS_TSO) ?
+ I40E_TX_CTX_EXT_IP_IPV4 :
+ I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM;
+
+ l4_proto = ip.v4->protocol;
+ } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
+ tunnel |= I40E_TX_CTX_EXT_IP_IPV6;
+
+ exthdr = ip.hdr + sizeof(*ip.v6);
+ l4_proto = ip.v6->nexthdr;
+ if (l4.hdr != exthdr)
+ ipv6_skip_exthdr(skb, exthdr - skb->data,
+ &l4_proto, &frag_off);
+ }
+
+ /* define outer transport */
+ switch (l4_proto) {
+ case IPPROTO_UDP:
+ tunnel |= I40E_TXD_CTX_UDP_TUNNELING;
+ *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
+ break;
+ case IPPROTO_GRE:
+ tunnel |= I40E_TXD_CTX_GRE_TUNNELING;
+ *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
+ break;
+ case IPPROTO_IPIP:
+ case IPPROTO_IPV6:
+ *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
+ l4.hdr = skb_inner_network_header(skb);
+ break;
+ default:
+ if (*tx_flags & I40E_TX_FLAGS_TSO)
+ return -1;
+
+ skb_checksum_help(skb);
+ return 0;
+ }
+
+ /* compute outer L3 header size */
+ tunnel |= ((l4.hdr - ip.hdr) / 4) <<
+ I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT;
+
+ /* switch IP header pointer from outer to inner header */
+ ip.hdr = skb_inner_network_header(skb);
+
+ /* compute tunnel header size */
+ tunnel |= ((ip.hdr - l4.hdr) / 2) <<
+ I40E_TXD_CTX_QW0_NATLEN_SHIFT;
+
+ /* indicate if we need to offload outer UDP header */
+ if ((*tx_flags & I40E_TX_FLAGS_TSO) &&
+ !(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
+ (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM))
+ tunnel |= I40E_TXD_CTX_QW0_L4T_CS_MASK;
+
+ /* record tunnel offload values */
+ *cd_tunneling |= tunnel;
+
+ /* switch L4 header pointer from outer to inner */
+ l4.hdr = skb_inner_transport_header(skb);
+ l4_proto = 0;
+
+ /* reset type as we transition from outer to inner headers */
+ *tx_flags &= ~(I40E_TX_FLAGS_IPV4 | I40E_TX_FLAGS_IPV6);
+ if (ip.v4->version == 4)
+ *tx_flags |= I40E_TX_FLAGS_IPV4;
+ if (ip.v6->version == 6)
+ *tx_flags |= I40E_TX_FLAGS_IPV6;
+ }
+
+ /* Enable IP checksum offloads */
+ if (*tx_flags & I40E_TX_FLAGS_IPV4) {
+ l4_proto = ip.v4->protocol;
+ /* the stack computes the IP header already, the only time we
+ * need the hardware to recompute it is in the case of TSO.
+ */
+ cmd |= (*tx_flags & I40E_TX_FLAGS_TSO) ?
+ I40E_TX_DESC_CMD_IIPT_IPV4_CSUM :
+ I40E_TX_DESC_CMD_IIPT_IPV4;
+ } else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
+ cmd |= I40E_TX_DESC_CMD_IIPT_IPV6;
+
+ exthdr = ip.hdr + sizeof(*ip.v6);
+ l4_proto = ip.v6->nexthdr;
+ if (l4.hdr != exthdr)
+ ipv6_skip_exthdr(skb, exthdr - skb->data,
+ &l4_proto, &frag_off);
+ }
+
+ /* compute inner L3 header size */
+ offset |= ((l4.hdr - ip.hdr) / 4) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT;
+
+ /* Enable L4 checksum offloads */
+ switch (l4_proto) {
+ case IPPROTO_TCP:
+ /* enable checksum offloads */
+ cmd |= I40E_TX_DESC_CMD_L4T_EOFT_TCP;
+ offset |= l4.tcp->doff << I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
+ break;
+ case IPPROTO_SCTP:
+ /* enable SCTP checksum offload */
+ cmd |= I40E_TX_DESC_CMD_L4T_EOFT_SCTP;
+ offset |= (sizeof(struct sctphdr) >> 2) <<
+ I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
+ break;
+ case IPPROTO_UDP:
+ /* enable UDP checksum offload */
+ cmd |= I40E_TX_DESC_CMD_L4T_EOFT_UDP;
+ offset |= (sizeof(struct udphdr) >> 2) <<
+ I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT;
+ break;
+ default:
+ if (*tx_flags & I40E_TX_FLAGS_TSO)
+ return -1;
+ skb_checksum_help(skb);
+ return 0;
+ }
+
+ *td_cmd |= cmd;
+ *td_offset |= offset;
+
+ return 1;
+}
+
+/**
+ * i40e_create_tx_ctx Build the Tx context descriptor
+ * @tx_ring: ring to create the descriptor on
+ * @cd_type_cmd_tso_mss: Quad Word 1
+ * @cd_tunneling: Quad Word 0 - bits 0-31
+ * @cd_l2tag2: Quad Word 0 - bits 32-63
+ **/
+static void i40e_create_tx_ctx(struct i40e_ring *tx_ring,
+ const u64 cd_type_cmd_tso_mss,
+ const u32 cd_tunneling, const u32 cd_l2tag2)
+{
+ struct i40e_tx_context_desc *context_desc;
+ int i = tx_ring->next_to_use;
+
+ if ((cd_type_cmd_tso_mss == I40E_TX_DESC_DTYPE_CONTEXT) &&
+ !cd_tunneling && !cd_l2tag2)
+ return;
+
+ /* grab the next descriptor */
+ context_desc = I40E_TX_CTXTDESC(tx_ring, i);
+
+ i++;
+ tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
+
+ /* cpu_to_le32 and assign to struct fields */
+ context_desc->tunneling_params = cpu_to_le32(cd_tunneling);
+ context_desc->l2tag2 = cpu_to_le16(cd_l2tag2);
+ context_desc->rsvd = cpu_to_le16(0);
+ context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
+}
+
+/**
+ * __i40evf_chk_linearize - Check if there are more than 8 buffers per packet
+ * @skb: send buffer
+ *
+ * Note: Our HW can't DMA more than 8 buffers to build a packet on the wire
+ * and so we need to figure out the cases where we need to linearize the skb.
+ *
+ * For TSO we need to count the TSO header and segment payload separately.
+ * As such we need to check cases where we have 7 fragments or more as we
+ * can potentially require 9 DMA transactions, 1 for the TSO header, 1 for
+ * the segment payload in the first descriptor, and another 7 for the
+ * fragments.
+ **/
+bool __i40evf_chk_linearize(struct sk_buff *skb)
+{
+ const struct skb_frag_struct *frag, *stale;
+ int nr_frags, sum;
+
+ /* no need to check if number of frags is less than 7 */
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ if (nr_frags < (I40E_MAX_BUFFER_TXD - 1))
+ return false;
+
+ /* We need to walk through the list and validate that each group
+ * of 6 fragments totals at least gso_size.
+ */
+ nr_frags -= I40E_MAX_BUFFER_TXD - 2;
+ frag = &skb_shinfo(skb)->frags[0];
+
+ /* Initialize size to the negative value of gso_size minus 1. We
+ * use this as the worst case scenerio in which the frag ahead
+ * of us only provides one byte which is why we are limited to 6
+ * descriptors for a single transmit as the header and previous
+ * fragment are already consuming 2 descriptors.
+ */
+ sum = 1 - skb_shinfo(skb)->gso_size;
+
+ /* Add size of frags 0 through 4 to create our initial sum */
+ sum += skb_frag_size(frag++);
+ sum += skb_frag_size(frag++);
+ sum += skb_frag_size(frag++);
+ sum += skb_frag_size(frag++);
+ sum += skb_frag_size(frag++);
+
+ /* Walk through fragments adding latest fragment, testing it, and
+ * then removing stale fragments from the sum.
+ */
+ for (stale = &skb_shinfo(skb)->frags[0];; stale++) {
+ int stale_size = skb_frag_size(stale);
+
+ sum += skb_frag_size(frag++);
+
+ /* The stale fragment may present us with a smaller
+ * descriptor than the actual fragment size. To account
+ * for that we need to remove all the data on the front and
+ * figure out what the remainder would be in the last
+ * descriptor associated with the fragment.
+ */
+ if (stale_size > I40E_MAX_DATA_PER_TXD) {
+ int align_pad = -(stale->page_offset) &
+ (I40E_MAX_READ_REQ_SIZE - 1);
+
+ sum -= align_pad;
+ stale_size -= align_pad;
+
+ do {
+ sum -= I40E_MAX_DATA_PER_TXD_ALIGNED;
+ stale_size -= I40E_MAX_DATA_PER_TXD_ALIGNED;
+ } while (stale_size > I40E_MAX_DATA_PER_TXD);
+ }
+
+ /* if sum is negative we failed to make sufficient progress */
+ if (sum < 0)
+ return true;
+
+ if (!nr_frags--)
+ break;
+
+ sum -= stale_size;
+ }
+
+ return false;
+}
+
+/**
+ * __i40evf_maybe_stop_tx - 2nd level check for tx stop conditions
+ * @tx_ring: the ring to be checked
+ * @size: the size buffer we want to assure is available
+ *
+ * Returns -EBUSY if a stop is needed, else 0
+ **/
+int __i40evf_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+{
+ netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+ /* Memory barrier before checking head and tail */
+ smp_mb();
+
+ /* Check again in a case another CPU has just made room available. */
+ if (likely(I40E_DESC_UNUSED(tx_ring) < size))
+ return -EBUSY;
+
+ /* A reprieve! - use start_queue because it doesn't call schedule */
+ netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index);
+ ++tx_ring->tx_stats.restart_queue;
+ return 0;
+}
+
+/**
+ * i40evf_tx_map - Build the Tx descriptor
+ * @tx_ring: ring to send buffer on
+ * @skb: send buffer
+ * @first: first buffer info buffer to use
+ * @tx_flags: collected send information
+ * @hdr_len: size of the packet header
+ * @td_cmd: the command field in the descriptor
+ * @td_offset: offset for checksum or crc
+ **/
+static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
+ struct i40e_tx_buffer *first, u32 tx_flags,
+ const u8 hdr_len, u32 td_cmd, u32 td_offset)
+{
+ unsigned int data_len = skb->data_len;
+ unsigned int size = skb_headlen(skb);
+ struct skb_frag_struct *frag;
+ struct i40e_tx_buffer *tx_bi;
+ struct i40e_tx_desc *tx_desc;
+ u16 i = tx_ring->next_to_use;
+ u32 td_tag = 0;
+ dma_addr_t dma;
+
+ if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
+ td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
+ td_tag = (tx_flags & I40E_TX_FLAGS_VLAN_MASK) >>
+ I40E_TX_FLAGS_VLAN_SHIFT;
+ }
+
+ first->tx_flags = tx_flags;
+
+ dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
+
+ tx_desc = I40E_TX_DESC(tx_ring, i);
+ tx_bi = first;
+
+ for (frag = &skb_shinfo(skb)->frags[0];; frag++) {
+ unsigned int max_data = I40E_MAX_DATA_PER_TXD_ALIGNED;
+
+ if (dma_mapping_error(tx_ring->dev, dma))
+ goto dma_error;
+
+ /* record length, and DMA address */
+ dma_unmap_len_set(tx_bi, len, size);
+ dma_unmap_addr_set(tx_bi, dma, dma);
+
+ /* align size to end of page */
+ max_data += -dma & (I40E_MAX_READ_REQ_SIZE - 1);
+ tx_desc->buffer_addr = cpu_to_le64(dma);
+
+ while (unlikely(size > I40E_MAX_DATA_PER_TXD)) {
+ tx_desc->cmd_type_offset_bsz =
+ build_ctob(td_cmd, td_offset,
+ max_data, td_tag);
+
+ tx_desc++;
+ i++;
+
+ if (i == tx_ring->count) {
+ tx_desc = I40E_TX_DESC(tx_ring, 0);
+ i = 0;
+ }
+
+ dma += max_data;
+ size -= max_data;
+
+ max_data = I40E_MAX_DATA_PER_TXD_ALIGNED;
+ tx_desc->buffer_addr = cpu_to_le64(dma);
+ }
+
+ if (likely(!data_len))
+ break;
+
+ tx_desc->cmd_type_offset_bsz = build_ctob(td_cmd, td_offset,
+ size, td_tag);
+
+ tx_desc++;
+ i++;
+
+ if (i == tx_ring->count) {
+ tx_desc = I40E_TX_DESC(tx_ring, 0);
+ i = 0;
+ }
+
+ size = skb_frag_size(frag);
+ data_len -= size;
+
+ dma = skb_frag_dma_map(tx_ring->dev, frag, 0, size,
+ DMA_TO_DEVICE);
+
+ tx_bi = &tx_ring->tx_bi[i];
+ }
+
+ netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
+
+ i++;
+ if (i == tx_ring->count)
+ i = 0;
+
+ tx_ring->next_to_use = i;
+
+ i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
+
+ /* write last descriptor with RS and EOP bits */
+ td_cmd |= I40E_TXD_CMD;
+ tx_desc->cmd_type_offset_bsz =
+ build_ctob(td_cmd, td_offset, size, td_tag);
+
+ /* Force memory writes to complete before letting h/w know there
+ * are new descriptors to fetch.
+ *
+ * We also use this memory barrier to make certain all of the
+ * status bits have been updated before next_to_watch is written.
+ */
+ wmb();
+
+ /* set next_to_watch value indicating a packet is present */
+ first->next_to_watch = tx_desc;
+
+ /* notify HW of packet */
+ if (netif_xmit_stopped(txring_txq(tx_ring)) || !skb->xmit_more) {
+ writel(i, tx_ring->tail);
+
+ /* we need this if more than one processor can write to our tail
+ * at a time, it synchronizes IO on IA64/Altix systems
+ */
+ mmiowb();
+ }
+
+ return;
+
+dma_error:
+ dev_info(tx_ring->dev, "TX DMA map failed\n");
+
+ /* clear dma mappings for failed tx_bi map */
+ for (;;) {
+ tx_bi = &tx_ring->tx_bi[i];
+ i40e_unmap_and_free_tx_resource(tx_ring, tx_bi);
+ if (tx_bi == first)
+ break;
+ if (i == 0)
+ i = tx_ring->count;
+ i--;
+ }
+
+ tx_ring->next_to_use = i;
+}
+
+/**
+ * i40e_xmit_frame_ring - Sends buffer on Tx ring
+ * @skb: send buffer
+ * @tx_ring: ring to send buffer on
+ *
+ * Returns NETDEV_TX_OK if sent, else an error code
+ **/
+static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
+ struct i40e_ring *tx_ring)
+{
+ u64 cd_type_cmd_tso_mss = I40E_TX_DESC_DTYPE_CONTEXT;
+ u32 cd_tunneling = 0, cd_l2tag2 = 0;
+ struct i40e_tx_buffer *first;
+ u32 td_offset = 0;
+ u32 tx_flags = 0;
+ __be16 protocol;
+ u32 td_cmd = 0;
+ u8 hdr_len = 0;
+ int tso, count;
+
+ /* prefetch the data, we'll need it later */
+ prefetch(skb->data);
+
+ i40e_trace(xmit_frame_ring, skb, tx_ring);
+
+ count = i40e_xmit_descriptor_count(skb);
+ if (i40e_chk_linearize(skb, count)) {
+ if (__skb_linearize(skb)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ count = i40e_txd_use_count(skb->len);
+ tx_ring->tx_stats.tx_linearize++;
+ }
+
+ /* need: 1 descriptor per page * PAGE_SIZE/I40E_MAX_DATA_PER_TXD,
+ * + 1 desc for skb_head_len/I40E_MAX_DATA_PER_TXD,
+ * + 4 desc gap to avoid the cache line where head is,
+ * + 1 desc for context descriptor,
+ * otherwise try next time
+ */
+ if (i40e_maybe_stop_tx(tx_ring, count + 4 + 1)) {
+ tx_ring->tx_stats.tx_busy++;
+ return NETDEV_TX_BUSY;
+ }
+
+ /* record the location of the first descriptor for this packet */
+ first = &tx_ring->tx_bi[tx_ring->next_to_use];
+ first->skb = skb;
+ first->bytecount = skb->len;
+ first->gso_segs = 1;
+
+ /* prepare the xmit flags */
+ if (i40evf_tx_prepare_vlan_flags(skb, tx_ring, &tx_flags))
+ goto out_drop;
+
+ /* obtain protocol of skb */
+ protocol = vlan_get_protocol(skb);
+
+ /* setup IPv4/IPv6 offloads */
+ if (protocol == htons(ETH_P_IP))
+ tx_flags |= I40E_TX_FLAGS_IPV4;
+ else if (protocol == htons(ETH_P_IPV6))
+ tx_flags |= I40E_TX_FLAGS_IPV6;
+
+ tso = i40e_tso(first, &hdr_len, &cd_type_cmd_tso_mss);
+
+ if (tso < 0)
+ goto out_drop;
+ else if (tso)
+ tx_flags |= I40E_TX_FLAGS_TSO;
+
+ /* Always offload the checksum, since it's in the data descriptor */
+ tso = i40e_tx_enable_csum(skb, &tx_flags, &td_cmd, &td_offset,
+ tx_ring, &cd_tunneling);
+ if (tso < 0)
+ goto out_drop;
+
+ skb_tx_timestamp(skb);
+
+ /* always enable CRC insertion offload */
+ td_cmd |= I40E_TX_DESC_CMD_ICRC;
+
+ i40e_create_tx_ctx(tx_ring, cd_type_cmd_tso_mss,
+ cd_tunneling, cd_l2tag2);
+
+ i40evf_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
+ td_cmd, td_offset);
+
+ return NETDEV_TX_OK;
+
+out_drop:
+ i40e_trace(xmit_frame_ring_drop, first->skb, tx_ring);
+ dev_kfree_skb_any(first->skb);
+ first->skb = NULL;
+ return NETDEV_TX_OK;
+}
+
+/**
+ * i40evf_xmit_frame - Selects the correct VSI and Tx queue to send buffer
+ * @skb: send buffer
+ * @netdev: network interface device structure
+ *
+ * Returns NETDEV_TX_OK if sent, else an error code
+ **/
+netdev_tx_t i40evf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ struct i40e_ring *tx_ring = &adapter->tx_rings[skb->queue_mapping];
+
+ /* hardware can't handle really short frames, hardware padding works
+ * beyond this point
+ */
+ if (unlikely(skb->len < I40E_MIN_TX_LEN)) {
+ if (skb_pad(skb, I40E_MIN_TX_LEN - skb->len))
+ return NETDEV_TX_OK;
+ skb->len = I40E_MIN_TX_LEN;
+ skb_set_tail_pointer(skb, I40E_MIN_TX_LEN);
+ }
+
+ return i40e_xmit_frame_ring(skb, tx_ring);
+}
diff --git a/drivers/net/ethernet/intel/iavf/i40e_txrx.h b/drivers/net/ethernet/intel/iavf/i40e_txrx.h
new file mode 100644
index 000000000000..3b5a63b3236e
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_txrx.h
@@ -0,0 +1,524 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_TXRX_H_
+#define _I40E_TXRX_H_
+
+/* Interrupt Throttling and Rate Limiting Goodies */
+#define I40E_DEFAULT_IRQ_WORK 256
+
+/* The datasheet for the X710 and XL710 indicate that the maximum value for
+ * the ITR is 8160usec which is then called out as 0xFF0 with a 2usec
+ * resolution. 8160 is 0x1FE0 when written out in hex. So instead of storing
+ * the register value which is divided by 2 lets use the actual values and
+ * avoid an excessive amount of translation.
+ */
+#define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */
+#define I40E_ITR_MASK 0x1FFE /* mask for ITR register value */
+#define I40E_MIN_ITR 2 /* reg uses 2 usec resolution */
+#define I40E_ITR_100K 10 /* all values below must be even */
+#define I40E_ITR_50K 20
+#define I40E_ITR_20K 50
+#define I40E_ITR_18K 60
+#define I40E_ITR_8K 122
+#define I40E_MAX_ITR 8160 /* maximum value as per datasheet */
+#define ITR_TO_REG(setting) ((setting) & ~I40E_ITR_DYNAMIC)
+#define ITR_REG_ALIGN(setting) __ALIGN_MASK(setting, ~I40E_ITR_MASK)
+#define ITR_IS_DYNAMIC(setting) (!!((setting) & I40E_ITR_DYNAMIC))
+
+#define I40E_ITR_RX_DEF (I40E_ITR_20K | I40E_ITR_DYNAMIC)
+#define I40E_ITR_TX_DEF (I40E_ITR_20K | I40E_ITR_DYNAMIC)
+
+/* 0x40 is the enable bit for interrupt rate limiting, and must be set if
+ * the value of the rate limit is non-zero
+ */
+#define INTRL_ENA BIT(6)
+#define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */
+#define INTRL_REG_TO_USEC(intrl) ((intrl & ~INTRL_ENA) << 2)
+#define INTRL_USEC_TO_REG(set) ((set) ? ((set) >> 2) | INTRL_ENA : 0)
+#define I40E_INTRL_8K 125 /* 8000 ints/sec */
+#define I40E_INTRL_62K 16 /* 62500 ints/sec */
+#define I40E_INTRL_83K 12 /* 83333 ints/sec */
+
+#define I40E_QUEUE_END_OF_LIST 0x7FF
+
+/* this enum matches hardware bits and is meant to be used by DYN_CTLN
+ * registers and QINT registers or more generally anywhere in the manual
+ * mentioning ITR_INDX, ITR_NONE cannot be used as an index 'n' into any
+ * register but instead is a special value meaning "don't update" ITR0/1/2.
+ */
+enum i40e_dyn_idx_t {
+ I40E_IDX_ITR0 = 0,
+ I40E_IDX_ITR1 = 1,
+ I40E_IDX_ITR2 = 2,
+ I40E_ITR_NONE = 3 /* ITR_NONE must not be used as an index */
+};
+
+/* these are indexes into ITRN registers */
+#define I40E_RX_ITR I40E_IDX_ITR0
+#define I40E_TX_ITR I40E_IDX_ITR1
+#define I40E_PE_ITR I40E_IDX_ITR2
+
+/* Supported RSS offloads */
+#define I40E_DEFAULT_RSS_HENA ( \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_L2_PAYLOAD))
+
+#define I40E_DEFAULT_RSS_HENA_EXPANDED (I40E_DEFAULT_RSS_HENA | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
+ BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP))
+
+/* Supported Rx Buffer Sizes (a multiple of 128) */
+#define I40E_RXBUFFER_256 256
+#define I40E_RXBUFFER_1536 1536 /* 128B aligned standard Ethernet frame */
+#define I40E_RXBUFFER_2048 2048
+#define I40E_RXBUFFER_3072 3072 /* Used for large frames w/ padding */
+#define I40E_MAX_RXBUFFER 9728 /* largest size for single descriptor */
+
+/* NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN means we
+ * reserve 2 more, and skb_shared_info adds an additional 384 bytes more,
+ * this adds up to 512 bytes of extra data meaning the smallest allocation
+ * we could have is 1K.
+ * i.e. RXBUFFER_256 --> 960 byte skb (size-1024 slab)
+ * i.e. RXBUFFER_512 --> 1216 byte skb (size-2048 slab)
+ */
+#define I40E_RX_HDR_SIZE I40E_RXBUFFER_256
+#define I40E_PACKET_HDR_PAD (ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2))
+#define i40e_rx_desc i40e_32byte_rx_desc
+
+#define I40E_RX_DMA_ATTR \
+ (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
+
+/* Attempt to maximize the headroom available for incoming frames. We
+ * use a 2K buffer for receives and need 1536/1534 to store the data for
+ * the frame. This leaves us with 512 bytes of room. From that we need
+ * to deduct the space needed for the shared info and the padding needed
+ * to IP align the frame.
+ *
+ * Note: For cache line sizes 256 or larger this value is going to end
+ * up negative. In these cases we should fall back to the legacy
+ * receive path.
+ */
+#if (PAGE_SIZE < 8192)
+#define I40E_2K_TOO_SMALL_WITH_PADDING \
+((NET_SKB_PAD + I40E_RXBUFFER_1536) > SKB_WITH_OVERHEAD(I40E_RXBUFFER_2048))
+
+static inline int i40e_compute_pad(int rx_buf_len)
+{
+ int page_size, pad_size;
+
+ page_size = ALIGN(rx_buf_len, PAGE_SIZE / 2);
+ pad_size = SKB_WITH_OVERHEAD(page_size) - rx_buf_len;
+
+ return pad_size;
+}
+
+static inline int i40e_skb_pad(void)
+{
+ int rx_buf_len;
+
+ /* If a 2K buffer cannot handle a standard Ethernet frame then
+ * optimize padding for a 3K buffer instead of a 1.5K buffer.
+ *
+ * For a 3K buffer we need to add enough padding to allow for
+ * tailroom due to NET_IP_ALIGN possibly shifting us out of
+ * cache-line alignment.
+ */
+ if (I40E_2K_TOO_SMALL_WITH_PADDING)
+ rx_buf_len = I40E_RXBUFFER_3072 + SKB_DATA_ALIGN(NET_IP_ALIGN);
+ else
+ rx_buf_len = I40E_RXBUFFER_1536;
+
+ /* if needed make room for NET_IP_ALIGN */
+ rx_buf_len -= NET_IP_ALIGN;
+
+ return i40e_compute_pad(rx_buf_len);
+}
+
+#define I40E_SKB_PAD i40e_skb_pad()
+#else
+#define I40E_2K_TOO_SMALL_WITH_PADDING false
+#define I40E_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
+#endif
+
+/**
+ * i40e_test_staterr - tests bits in Rx descriptor status and error fields
+ * @rx_desc: pointer to receive descriptor (in le64 format)
+ * @stat_err_bits: value to mask
+ *
+ * This function does some fast chicanery in order to return the
+ * value of the mask which is really only used for boolean tests.
+ * The status_error_len doesn't need to be shifted because it begins
+ * at offset zero.
+ */
+static inline bool i40e_test_staterr(union i40e_rx_desc *rx_desc,
+ const u64 stat_err_bits)
+{
+ return !!(rx_desc->wb.qword1.status_error_len &
+ cpu_to_le64(stat_err_bits));
+}
+
+/* How many Rx Buffers do we bundle into one write to the hardware ? */
+#define I40E_RX_BUFFER_WRITE 32 /* Must be power of 2 */
+#define I40E_RX_INCREMENT(r, i) \
+ do { \
+ (i)++; \
+ if ((i) == (r)->count) \
+ i = 0; \
+ r->next_to_clean = i; \
+ } while (0)
+
+#define I40E_RX_NEXT_DESC(r, i, n) \
+ do { \
+ (i)++; \
+ if ((i) == (r)->count) \
+ i = 0; \
+ (n) = I40E_RX_DESC((r), (i)); \
+ } while (0)
+
+#define I40E_RX_NEXT_DESC_PREFETCH(r, i, n) \
+ do { \
+ I40E_RX_NEXT_DESC((r), (i), (n)); \
+ prefetch((n)); \
+ } while (0)
+
+#define I40E_MAX_BUFFER_TXD 8
+#define I40E_MIN_TX_LEN 17
+
+/* The size limit for a transmit buffer in a descriptor is (16K - 1).
+ * In order to align with the read requests we will align the value to
+ * the nearest 4K which represents our maximum read request size.
+ */
+#define I40E_MAX_READ_REQ_SIZE 4096
+#define I40E_MAX_DATA_PER_TXD (16 * 1024 - 1)
+#define I40E_MAX_DATA_PER_TXD_ALIGNED \
+ (I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1))
+
+/**
+ * i40e_txd_use_count - estimate the number of descriptors needed for Tx
+ * @size: transmit request size in bytes
+ *
+ * Due to hardware alignment restrictions (4K alignment), we need to
+ * assume that we can have no more than 12K of data per descriptor, even
+ * though each descriptor can take up to 16K - 1 bytes of aligned memory.
+ * Thus, we need to divide by 12K. But division is slow! Instead,
+ * we decompose the operation into shifts and one relatively cheap
+ * multiply operation.
+ *
+ * To divide by 12K, we first divide by 4K, then divide by 3:
+ * To divide by 4K, shift right by 12 bits
+ * To divide by 3, multiply by 85, then divide by 256
+ * (Divide by 256 is done by shifting right by 8 bits)
+ * Finally, we add one to round up. Because 256 isn't an exact multiple of
+ * 3, we'll underestimate near each multiple of 12K. This is actually more
+ * accurate as we have 4K - 1 of wiggle room that we can fit into the last
+ * segment. For our purposes this is accurate out to 1M which is orders of
+ * magnitude greater than our largest possible GSO size.
+ *
+ * This would then be implemented as:
+ * return (((size >> 12) * 85) >> 8) + 1;
+ *
+ * Since multiplication and division are commutative, we can reorder
+ * operations into:
+ * return ((size * 85) >> 20) + 1;
+ */
+static inline unsigned int i40e_txd_use_count(unsigned int size)
+{
+ return ((size * 85) >> 20) + 1;
+}
+
+/* Tx Descriptors needed, worst case */
+#define DESC_NEEDED (MAX_SKB_FRAGS + 6)
+#define I40E_MIN_DESC_PENDING 4
+
+#define I40E_TX_FLAGS_HW_VLAN BIT(1)
+#define I40E_TX_FLAGS_SW_VLAN BIT(2)
+#define I40E_TX_FLAGS_TSO BIT(3)
+#define I40E_TX_FLAGS_IPV4 BIT(4)
+#define I40E_TX_FLAGS_IPV6 BIT(5)
+#define I40E_TX_FLAGS_FCCRC BIT(6)
+#define I40E_TX_FLAGS_FSO BIT(7)
+#define I40E_TX_FLAGS_FD_SB BIT(9)
+#define I40E_TX_FLAGS_VXLAN_TUNNEL BIT(10)
+#define I40E_TX_FLAGS_VLAN_MASK 0xffff0000
+#define I40E_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000
+#define I40E_TX_FLAGS_VLAN_PRIO_SHIFT 29
+#define I40E_TX_FLAGS_VLAN_SHIFT 16
+
+struct i40e_tx_buffer {
+ struct i40e_tx_desc *next_to_watch;
+ union {
+ struct sk_buff *skb;
+ void *raw_buf;
+ };
+ unsigned int bytecount;
+ unsigned short gso_segs;
+
+ DEFINE_DMA_UNMAP_ADDR(dma);
+ DEFINE_DMA_UNMAP_LEN(len);
+ u32 tx_flags;
+};
+
+struct i40e_rx_buffer {
+ dma_addr_t dma;
+ struct page *page;
+#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
+ __u32 page_offset;
+#else
+ __u16 page_offset;
+#endif
+ __u16 pagecnt_bias;
+};
+
+struct i40e_queue_stats {
+ u64 packets;
+ u64 bytes;
+};
+
+struct i40e_tx_queue_stats {
+ u64 restart_queue;
+ u64 tx_busy;
+ u64 tx_done_old;
+ u64 tx_linearize;
+ u64 tx_force_wb;
+ int prev_pkt_ctr;
+ u64 tx_lost_interrupt;
+};
+
+struct i40e_rx_queue_stats {
+ u64 non_eop_descs;
+ u64 alloc_page_failed;
+ u64 alloc_buff_failed;
+ u64 page_reuse_count;
+ u64 realloc_count;
+};
+
+enum i40e_ring_state_t {
+ __I40E_TX_FDIR_INIT_DONE,
+ __I40E_TX_XPS_INIT_DONE,
+ __I40E_RING_STATE_NBITS /* must be last */
+};
+
+/* some useful defines for virtchannel interface, which
+ * is the only remaining user of header split
+ */
+#define I40E_RX_DTYPE_NO_SPLIT 0
+#define I40E_RX_DTYPE_HEADER_SPLIT 1
+#define I40E_RX_DTYPE_SPLIT_ALWAYS 2
+#define I40E_RX_SPLIT_L2 0x1
+#define I40E_RX_SPLIT_IP 0x2
+#define I40E_RX_SPLIT_TCP_UDP 0x4
+#define I40E_RX_SPLIT_SCTP 0x8
+
+/* struct that defines a descriptor ring, associated with a VSI */
+struct i40e_ring {
+ struct i40e_ring *next; /* pointer to next ring in q_vector */
+ void *desc; /* Descriptor ring memory */
+ struct device *dev; /* Used for DMA mapping */
+ struct net_device *netdev; /* netdev ring maps to */
+ union {
+ struct i40e_tx_buffer *tx_bi;
+ struct i40e_rx_buffer *rx_bi;
+ };
+ DECLARE_BITMAP(state, __I40E_RING_STATE_NBITS);
+ u16 queue_index; /* Queue number of ring */
+ u8 dcb_tc; /* Traffic class of ring */
+ u8 __iomem *tail;
+
+ /* high bit set means dynamic, use accessors routines to read/write.
+ * hardware only supports 2us resolution for the ITR registers.
+ * these values always store the USER setting, and must be converted
+ * before programming to a register.
+ */
+ u16 itr_setting;
+
+ u16 count; /* Number of descriptors */
+ u16 reg_idx; /* HW register index of the ring */
+ u16 rx_buf_len;
+
+ /* used in interrupt processing */
+ u16 next_to_use;
+ u16 next_to_clean;
+
+ u8 atr_sample_rate;
+ u8 atr_count;
+
+ bool ring_active; /* is ring online or not */
+ bool arm_wb; /* do something to arm write back */
+ u8 packet_stride;
+
+ u16 flags;
+#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
+#define I40E_RXR_FLAGS_BUILD_SKB_ENABLED BIT(1)
+
+ /* stats structs */
+ struct i40e_queue_stats stats;
+ struct u64_stats_sync syncp;
+ union {
+ struct i40e_tx_queue_stats tx_stats;
+ struct i40e_rx_queue_stats rx_stats;
+ };
+
+ unsigned int size; /* length of descriptor ring in bytes */
+ dma_addr_t dma; /* physical address of ring */
+
+ struct i40e_vsi *vsi; /* Backreference to associated VSI */
+ struct i40e_q_vector *q_vector; /* Backreference to associated vector */
+
+ struct rcu_head rcu; /* to avoid race on free */
+ u16 next_to_alloc;
+ struct sk_buff *skb; /* When i40evf_clean_rx_ring_irq() must
+ * return before it sees the EOP for
+ * the current packet, we save that skb
+ * here and resume receiving this
+ * packet the next time
+ * i40evf_clean_rx_ring_irq() is called
+ * for this ring.
+ */
+} ____cacheline_internodealigned_in_smp;
+
+static inline bool ring_uses_build_skb(struct i40e_ring *ring)
+{
+ return !!(ring->flags & I40E_RXR_FLAGS_BUILD_SKB_ENABLED);
+}
+
+static inline void set_ring_build_skb_enabled(struct i40e_ring *ring)
+{
+ ring->flags |= I40E_RXR_FLAGS_BUILD_SKB_ENABLED;
+}
+
+static inline void clear_ring_build_skb_enabled(struct i40e_ring *ring)
+{
+ ring->flags &= ~I40E_RXR_FLAGS_BUILD_SKB_ENABLED;
+}
+
+#define I40E_ITR_ADAPTIVE_MIN_INC 0x0002
+#define I40E_ITR_ADAPTIVE_MIN_USECS 0x0002
+#define I40E_ITR_ADAPTIVE_MAX_USECS 0x007e
+#define I40E_ITR_ADAPTIVE_LATENCY 0x8000
+#define I40E_ITR_ADAPTIVE_BULK 0x0000
+#define ITR_IS_BULK(x) (!((x) & I40E_ITR_ADAPTIVE_LATENCY))
+
+struct i40e_ring_container {
+ struct i40e_ring *ring; /* pointer to linked list of ring(s) */
+ unsigned long next_update; /* jiffies value of next update */
+ unsigned int total_bytes; /* total bytes processed this int */
+ unsigned int total_packets; /* total packets processed this int */
+ u16 count;
+ u16 target_itr; /* target ITR setting for ring(s) */
+ u16 current_itr; /* current ITR setting for ring(s) */
+};
+
+/* iterator for handling rings in ring container */
+#define i40e_for_each_ring(pos, head) \
+ for (pos = (head).ring; pos != NULL; pos = pos->next)
+
+static inline unsigned int i40e_rx_pg_order(struct i40e_ring *ring)
+{
+#if (PAGE_SIZE < 8192)
+ if (ring->rx_buf_len > (PAGE_SIZE / 2))
+ return 1;
+#endif
+ return 0;
+}
+
+#define i40e_rx_pg_size(_ring) (PAGE_SIZE << i40e_rx_pg_order(_ring))
+
+bool i40evf_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count);
+netdev_tx_t i40evf_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+void i40evf_clean_tx_ring(struct i40e_ring *tx_ring);
+void i40evf_clean_rx_ring(struct i40e_ring *rx_ring);
+int i40evf_setup_tx_descriptors(struct i40e_ring *tx_ring);
+int i40evf_setup_rx_descriptors(struct i40e_ring *rx_ring);
+void i40evf_free_tx_resources(struct i40e_ring *tx_ring);
+void i40evf_free_rx_resources(struct i40e_ring *rx_ring);
+int i40evf_napi_poll(struct napi_struct *napi, int budget);
+void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector);
+u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw);
+void i40evf_detect_recover_hung(struct i40e_vsi *vsi);
+int __i40evf_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
+bool __i40evf_chk_linearize(struct sk_buff *skb);
+
+/**
+ * i40e_xmit_descriptor_count - calculate number of Tx descriptors needed
+ * @skb: send buffer
+ * @tx_ring: ring to send buffer on
+ *
+ * Returns number of data descriptors needed for this skb. Returns 0 to indicate
+ * there is not enough descriptors available in this ring since we need at least
+ * one descriptor.
+ **/
+static inline int i40e_xmit_descriptor_count(struct sk_buff *skb)
+{
+ const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
+ unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
+ int count = 0, size = skb_headlen(skb);
+
+ for (;;) {
+ count += i40e_txd_use_count(size);
+
+ if (!nr_frags--)
+ break;
+
+ size = skb_frag_size(frag++);
+ }
+
+ return count;
+}
+
+/**
+ * i40e_maybe_stop_tx - 1st level check for Tx stop conditions
+ * @tx_ring: the ring to be checked
+ * @size: the size buffer we want to assure is available
+ *
+ * Returns 0 if stop is not needed
+ **/
+static inline int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+{
+ if (likely(I40E_DESC_UNUSED(tx_ring) >= size))
+ return 0;
+ return __i40evf_maybe_stop_tx(tx_ring, size);
+}
+
+/**
+ * i40e_chk_linearize - Check if there are more than 8 fragments per packet
+ * @skb: send buffer
+ * @count: number of buffers used
+ *
+ * Note: Our HW can't scatter-gather more than 8 fragments to build
+ * a packet on the wire and so we need to figure out the cases where we
+ * need to linearize the skb.
+ **/
+static inline bool i40e_chk_linearize(struct sk_buff *skb, int count)
+{
+ /* Both TSO and single send will work if count is less than 8 */
+ if (likely(count < I40E_MAX_BUFFER_TXD))
+ return false;
+
+ if (skb_is_gso(skb))
+ return __i40evf_chk_linearize(skb);
+
+ /* we can support up to 8 data buffers for a single send */
+ return count != I40E_MAX_BUFFER_TXD;
+}
+/**
+ * @ring: Tx ring to find the netdev equivalent of
+ **/
+static inline struct netdev_queue *txring_txq(const struct i40e_ring *ring)
+{
+ return netdev_get_tx_queue(ring->netdev, ring->queue_index);
+}
+#endif /* _I40E_TXRX_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40e_type.h b/drivers/net/ethernet/intel/iavf/i40e_type.h
new file mode 100644
index 000000000000..8f1344094bc9
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40e_type.h
@@ -0,0 +1,719 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40E_TYPE_H_
+#define _I40E_TYPE_H_
+
+#include "i40e_status.h"
+#include "i40e_osdep.h"
+#include "i40e_register.h"
+#include "i40e_adminq.h"
+#include "i40e_devids.h"
+
+#define I40E_RXQ_CTX_DBUFF_SHIFT 7
+
+/* I40E_MASK is a macro used on 32 bit registers */
+#define I40E_MASK(mask, shift) ((u32)(mask) << (shift))
+
+#define I40E_MAX_VSI_QP 16
+#define I40E_MAX_VF_VSI 3
+#define I40E_MAX_CHAINED_RX_BUFFERS 5
+
+/* forward declaration */
+struct i40e_hw;
+typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *);
+
+/* Data type manipulation macros. */
+
+#define I40E_DESC_UNUSED(R) \
+ ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
+ (R)->next_to_clean - (R)->next_to_use - 1)
+
+/* bitfields for Tx queue mapping in QTX_CTL */
+#define I40E_QTX_CTL_VF_QUEUE 0x0
+#define I40E_QTX_CTL_VM_QUEUE 0x1
+#define I40E_QTX_CTL_PF_QUEUE 0x2
+
+/* debug masks - set these bits in hw->debug_mask to control output */
+enum i40e_debug_mask {
+ I40E_DEBUG_INIT = 0x00000001,
+ I40E_DEBUG_RELEASE = 0x00000002,
+
+ I40E_DEBUG_LINK = 0x00000010,
+ I40E_DEBUG_PHY = 0x00000020,
+ I40E_DEBUG_HMC = 0x00000040,
+ I40E_DEBUG_NVM = 0x00000080,
+ I40E_DEBUG_LAN = 0x00000100,
+ I40E_DEBUG_FLOW = 0x00000200,
+ I40E_DEBUG_DCB = 0x00000400,
+ I40E_DEBUG_DIAG = 0x00000800,
+ I40E_DEBUG_FD = 0x00001000,
+ I40E_DEBUG_PACKAGE = 0x00002000,
+
+ I40E_DEBUG_AQ_MESSAGE = 0x01000000,
+ I40E_DEBUG_AQ_DESCRIPTOR = 0x02000000,
+ I40E_DEBUG_AQ_DESC_BUFFER = 0x04000000,
+ I40E_DEBUG_AQ_COMMAND = 0x06000000,
+ I40E_DEBUG_AQ = 0x0F000000,
+
+ I40E_DEBUG_USER = 0xF0000000,
+
+ I40E_DEBUG_ALL = 0xFFFFFFFF
+};
+
+/* These are structs for managing the hardware information and the operations.
+ * The structures of function pointers are filled out at init time when we
+ * know for sure exactly which hardware we're working with. This gives us the
+ * flexibility of using the same main driver code but adapting to slightly
+ * different hardware needs as new parts are developed. For this architecture,
+ * the Firmware and AdminQ are intended to insulate the driver from most of the
+ * future changes, but these structures will also do part of the job.
+ */
+enum i40e_mac_type {
+ I40E_MAC_UNKNOWN = 0,
+ I40E_MAC_XL710,
+ I40E_MAC_VF,
+ I40E_MAC_X722,
+ I40E_MAC_X722_VF,
+ I40E_MAC_GENERIC,
+};
+
+enum i40e_vsi_type {
+ I40E_VSI_MAIN = 0,
+ I40E_VSI_VMDQ1 = 1,
+ I40E_VSI_VMDQ2 = 2,
+ I40E_VSI_CTRL = 3,
+ I40E_VSI_FCOE = 4,
+ I40E_VSI_MIRROR = 5,
+ I40E_VSI_SRIOV = 6,
+ I40E_VSI_FDIR = 7,
+ I40E_VSI_TYPE_UNKNOWN
+};
+
+enum i40e_queue_type {
+ I40E_QUEUE_TYPE_RX = 0,
+ I40E_QUEUE_TYPE_TX,
+ I40E_QUEUE_TYPE_PE_CEQ,
+ I40E_QUEUE_TYPE_UNKNOWN
+};
+
+#define I40E_HW_CAP_MAX_GPIO 30
+/* Capabilities of a PF or a VF or the whole device */
+struct i40e_hw_capabilities {
+ bool dcb;
+ bool fcoe;
+ u32 num_vsis;
+ u32 num_rx_qp;
+ u32 num_tx_qp;
+ u32 base_queue;
+ u32 num_msix_vectors_vf;
+};
+
+struct i40e_mac_info {
+ enum i40e_mac_type type;
+ u8 addr[ETH_ALEN];
+ u8 perm_addr[ETH_ALEN];
+ u8 san_addr[ETH_ALEN];
+ u16 max_fcoeq;
+};
+
+/* PCI bus types */
+enum i40e_bus_type {
+ i40e_bus_type_unknown = 0,
+ i40e_bus_type_pci,
+ i40e_bus_type_pcix,
+ i40e_bus_type_pci_express,
+ i40e_bus_type_reserved
+};
+
+/* PCI bus speeds */
+enum i40e_bus_speed {
+ i40e_bus_speed_unknown = 0,
+ i40e_bus_speed_33 = 33,
+ i40e_bus_speed_66 = 66,
+ i40e_bus_speed_100 = 100,
+ i40e_bus_speed_120 = 120,
+ i40e_bus_speed_133 = 133,
+ i40e_bus_speed_2500 = 2500,
+ i40e_bus_speed_5000 = 5000,
+ i40e_bus_speed_8000 = 8000,
+ i40e_bus_speed_reserved
+};
+
+/* PCI bus widths */
+enum i40e_bus_width {
+ i40e_bus_width_unknown = 0,
+ i40e_bus_width_pcie_x1 = 1,
+ i40e_bus_width_pcie_x2 = 2,
+ i40e_bus_width_pcie_x4 = 4,
+ i40e_bus_width_pcie_x8 = 8,
+ i40e_bus_width_32 = 32,
+ i40e_bus_width_64 = 64,
+ i40e_bus_width_reserved
+};
+
+/* Bus parameters */
+struct i40e_bus_info {
+ enum i40e_bus_speed speed;
+ enum i40e_bus_width width;
+ enum i40e_bus_type type;
+
+ u16 func;
+ u16 device;
+ u16 lan_id;
+ u16 bus_id;
+};
+
+#define I40E_MAX_TRAFFIC_CLASS 8
+#define I40E_MAX_USER_PRIORITY 8
+/* Port hardware description */
+struct i40e_hw {
+ u8 __iomem *hw_addr;
+ void *back;
+
+ /* subsystem structs */
+ struct i40e_mac_info mac;
+ struct i40e_bus_info bus;
+
+ /* pci info */
+ u16 device_id;
+ u16 vendor_id;
+ u16 subsystem_device_id;
+ u16 subsystem_vendor_id;
+ u8 revision_id;
+
+ /* capabilities for entire device and PCI func */
+ struct i40e_hw_capabilities dev_caps;
+
+ /* Admin Queue info */
+ struct i40e_adminq_info aq;
+
+ /* debug mask */
+ u32 debug_mask;
+ char err_str[16];
+};
+
+static inline bool i40e_is_vf(struct i40e_hw *hw)
+{
+ return (hw->mac.type == I40E_MAC_VF ||
+ hw->mac.type == I40E_MAC_X722_VF);
+}
+
+struct i40e_driver_version {
+ u8 major_version;
+ u8 minor_version;
+ u8 build_version;
+ u8 subbuild_version;
+ u8 driver_string[32];
+};
+
+/* RX Descriptors */
+union i40e_16byte_rx_desc {
+ struct {
+ __le64 pkt_addr; /* Packet buffer address */
+ __le64 hdr_addr; /* Header buffer address */
+ } read;
+ struct {
+ struct {
+ struct {
+ union {
+ __le16 mirroring_status;
+ __le16 fcoe_ctx_id;
+ } mirr_fcoe;
+ __le16 l2tag1;
+ } lo_dword;
+ union {
+ __le32 rss; /* RSS Hash */
+ __le32 fd_id; /* Flow director filter id */
+ __le32 fcoe_param; /* FCoE DDP Context id */
+ } hi_dword;
+ } qword0;
+ struct {
+ /* ext status/error/pktype/length */
+ __le64 status_error_len;
+ } qword1;
+ } wb; /* writeback */
+};
+
+union i40e_32byte_rx_desc {
+ struct {
+ __le64 pkt_addr; /* Packet buffer address */
+ __le64 hdr_addr; /* Header buffer address */
+ /* bit 0 of hdr_buffer_addr is DD bit */
+ __le64 rsvd1;
+ __le64 rsvd2;
+ } read;
+ struct {
+ struct {
+ struct {
+ union {
+ __le16 mirroring_status;
+ __le16 fcoe_ctx_id;
+ } mirr_fcoe;
+ __le16 l2tag1;
+ } lo_dword;
+ union {
+ __le32 rss; /* RSS Hash */
+ __le32 fcoe_param; /* FCoE DDP Context id */
+ /* Flow director filter id in case of
+ * Programming status desc WB
+ */
+ __le32 fd_id;
+ } hi_dword;
+ } qword0;
+ struct {
+ /* status/error/pktype/length */
+ __le64 status_error_len;
+ } qword1;
+ struct {
+ __le16 ext_status; /* extended status */
+ __le16 rsvd;
+ __le16 l2tag2_1;
+ __le16 l2tag2_2;
+ } qword2;
+ struct {
+ union {
+ __le32 flex_bytes_lo;
+ __le32 pe_status;
+ } lo_dword;
+ union {
+ __le32 flex_bytes_hi;
+ __le32 fd_id;
+ } hi_dword;
+ } qword3;
+ } wb; /* writeback */
+};
+
+enum i40e_rx_desc_status_bits {
+ /* Note: These are predefined bit offsets */
+ I40E_RX_DESC_STATUS_DD_SHIFT = 0,
+ I40E_RX_DESC_STATUS_EOF_SHIFT = 1,
+ I40E_RX_DESC_STATUS_L2TAG1P_SHIFT = 2,
+ I40E_RX_DESC_STATUS_L3L4P_SHIFT = 3,
+ I40E_RX_DESC_STATUS_CRCP_SHIFT = 4,
+ I40E_RX_DESC_STATUS_TSYNINDX_SHIFT = 5, /* 2 BITS */
+ I40E_RX_DESC_STATUS_TSYNVALID_SHIFT = 7,
+ /* Note: Bit 8 is reserved in X710 and XL710 */
+ I40E_RX_DESC_STATUS_EXT_UDP_0_SHIFT = 8,
+ I40E_RX_DESC_STATUS_UMBCAST_SHIFT = 9, /* 2 BITS */
+ I40E_RX_DESC_STATUS_FLM_SHIFT = 11,
+ I40E_RX_DESC_STATUS_FLTSTAT_SHIFT = 12, /* 2 BITS */
+ I40E_RX_DESC_STATUS_LPBK_SHIFT = 14,
+ I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT = 15,
+ I40E_RX_DESC_STATUS_RESERVED_SHIFT = 16, /* 2 BITS */
+ /* Note: For non-tunnel packets INT_UDP_0 is the right status for
+ * UDP header
+ */
+ I40E_RX_DESC_STATUS_INT_UDP_0_SHIFT = 18,
+ I40E_RX_DESC_STATUS_LAST /* this entry must be last!!! */
+};
+
+#define I40E_RXD_QW1_STATUS_SHIFT 0
+#define I40E_RXD_QW1_STATUS_MASK ((BIT(I40E_RX_DESC_STATUS_LAST) - 1) \
+ << I40E_RXD_QW1_STATUS_SHIFT)
+
+#define I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT I40E_RX_DESC_STATUS_TSYNINDX_SHIFT
+#define I40E_RXD_QW1_STATUS_TSYNINDX_MASK (0x3UL << \
+ I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT)
+
+#define I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT I40E_RX_DESC_STATUS_TSYNVALID_SHIFT
+#define I40E_RXD_QW1_STATUS_TSYNVALID_MASK \
+ BIT_ULL(I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT)
+
+enum i40e_rx_desc_fltstat_values {
+ I40E_RX_DESC_FLTSTAT_NO_DATA = 0,
+ I40E_RX_DESC_FLTSTAT_RSV_FD_ID = 1, /* 16byte desc? FD_ID : RSV */
+ I40E_RX_DESC_FLTSTAT_RSV = 2,
+ I40E_RX_DESC_FLTSTAT_RSS_HASH = 3,
+};
+
+#define I40E_RXD_QW1_ERROR_SHIFT 19
+#define I40E_RXD_QW1_ERROR_MASK (0xFFUL << I40E_RXD_QW1_ERROR_SHIFT)
+
+enum i40e_rx_desc_error_bits {
+ /* Note: These are predefined bit offsets */
+ I40E_RX_DESC_ERROR_RXE_SHIFT = 0,
+ I40E_RX_DESC_ERROR_RECIPE_SHIFT = 1,
+ I40E_RX_DESC_ERROR_HBO_SHIFT = 2,
+ I40E_RX_DESC_ERROR_L3L4E_SHIFT = 3, /* 3 BITS */
+ I40E_RX_DESC_ERROR_IPE_SHIFT = 3,
+ I40E_RX_DESC_ERROR_L4E_SHIFT = 4,
+ I40E_RX_DESC_ERROR_EIPE_SHIFT = 5,
+ I40E_RX_DESC_ERROR_OVERSIZE_SHIFT = 6,
+ I40E_RX_DESC_ERROR_PPRS_SHIFT = 7
+};
+
+enum i40e_rx_desc_error_l3l4e_fcoe_masks {
+ I40E_RX_DESC_ERROR_L3L4E_NONE = 0,
+ I40E_RX_DESC_ERROR_L3L4E_PROT = 1,
+ I40E_RX_DESC_ERROR_L3L4E_FC = 2,
+ I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR = 3,
+ I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN = 4
+};
+
+#define I40E_RXD_QW1_PTYPE_SHIFT 30
+#define I40E_RXD_QW1_PTYPE_MASK (0xFFULL << I40E_RXD_QW1_PTYPE_SHIFT)
+
+/* Packet type non-ip values */
+enum i40e_rx_l2_ptype {
+ I40E_RX_PTYPE_L2_RESERVED = 0,
+ I40E_RX_PTYPE_L2_MAC_PAY2 = 1,
+ I40E_RX_PTYPE_L2_TIMESYNC_PAY2 = 2,
+ I40E_RX_PTYPE_L2_FIP_PAY2 = 3,
+ I40E_RX_PTYPE_L2_OUI_PAY2 = 4,
+ I40E_RX_PTYPE_L2_MACCNTRL_PAY2 = 5,
+ I40E_RX_PTYPE_L2_LLDP_PAY2 = 6,
+ I40E_RX_PTYPE_L2_ECP_PAY2 = 7,
+ I40E_RX_PTYPE_L2_EVB_PAY2 = 8,
+ I40E_RX_PTYPE_L2_QCN_PAY2 = 9,
+ I40E_RX_PTYPE_L2_EAPOL_PAY2 = 10,
+ I40E_RX_PTYPE_L2_ARP = 11,
+ I40E_RX_PTYPE_L2_FCOE_PAY3 = 12,
+ I40E_RX_PTYPE_L2_FCOE_FCDATA_PAY3 = 13,
+ I40E_RX_PTYPE_L2_FCOE_FCRDY_PAY3 = 14,
+ I40E_RX_PTYPE_L2_FCOE_FCRSP_PAY3 = 15,
+ I40E_RX_PTYPE_L2_FCOE_FCOTHER_PA = 16,
+ I40E_RX_PTYPE_L2_FCOE_VFT_PAY3 = 17,
+ I40E_RX_PTYPE_L2_FCOE_VFT_FCDATA = 18,
+ I40E_RX_PTYPE_L2_FCOE_VFT_FCRDY = 19,
+ I40E_RX_PTYPE_L2_FCOE_VFT_FCRSP = 20,
+ I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER = 21,
+ I40E_RX_PTYPE_GRENAT4_MAC_PAY3 = 58,
+ I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4 = 87,
+ I40E_RX_PTYPE_GRENAT6_MAC_PAY3 = 124,
+ I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4 = 153
+};
+
+struct i40e_rx_ptype_decoded {
+ u32 ptype:8;
+ u32 known:1;
+ u32 outer_ip:1;
+ u32 outer_ip_ver:1;
+ u32 outer_frag:1;
+ u32 tunnel_type:3;
+ u32 tunnel_end_prot:2;
+ u32 tunnel_end_frag:1;
+ u32 inner_prot:4;
+ u32 payload_layer:3;
+};
+
+enum i40e_rx_ptype_outer_ip {
+ I40E_RX_PTYPE_OUTER_L2 = 0,
+ I40E_RX_PTYPE_OUTER_IP = 1
+};
+
+enum i40e_rx_ptype_outer_ip_ver {
+ I40E_RX_PTYPE_OUTER_NONE = 0,
+ I40E_RX_PTYPE_OUTER_IPV4 = 0,
+ I40E_RX_PTYPE_OUTER_IPV6 = 1
+};
+
+enum i40e_rx_ptype_outer_fragmented {
+ I40E_RX_PTYPE_NOT_FRAG = 0,
+ I40E_RX_PTYPE_FRAG = 1
+};
+
+enum i40e_rx_ptype_tunnel_type {
+ I40E_RX_PTYPE_TUNNEL_NONE = 0,
+ I40E_RX_PTYPE_TUNNEL_IP_IP = 1,
+ I40E_RX_PTYPE_TUNNEL_IP_GRENAT = 2,
+ I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC = 3,
+ I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4,
+};
+
+enum i40e_rx_ptype_tunnel_end_prot {
+ I40E_RX_PTYPE_TUNNEL_END_NONE = 0,
+ I40E_RX_PTYPE_TUNNEL_END_IPV4 = 1,
+ I40E_RX_PTYPE_TUNNEL_END_IPV6 = 2,
+};
+
+enum i40e_rx_ptype_inner_prot {
+ I40E_RX_PTYPE_INNER_PROT_NONE = 0,
+ I40E_RX_PTYPE_INNER_PROT_UDP = 1,
+ I40E_RX_PTYPE_INNER_PROT_TCP = 2,
+ I40E_RX_PTYPE_INNER_PROT_SCTP = 3,
+ I40E_RX_PTYPE_INNER_PROT_ICMP = 4,
+ I40E_RX_PTYPE_INNER_PROT_TIMESYNC = 5
+};
+
+enum i40e_rx_ptype_payload_layer {
+ I40E_RX_PTYPE_PAYLOAD_LAYER_NONE = 0,
+ I40E_RX_PTYPE_PAYLOAD_LAYER_PAY2 = 1,
+ I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3 = 2,
+ I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4 = 3,
+};
+
+#define I40E_RXD_QW1_LENGTH_PBUF_SHIFT 38
+#define I40E_RXD_QW1_LENGTH_PBUF_MASK (0x3FFFULL << \
+ I40E_RXD_QW1_LENGTH_PBUF_SHIFT)
+
+#define I40E_RXD_QW1_LENGTH_HBUF_SHIFT 52
+#define I40E_RXD_QW1_LENGTH_HBUF_MASK (0x7FFULL << \
+ I40E_RXD_QW1_LENGTH_HBUF_SHIFT)
+
+#define I40E_RXD_QW1_LENGTH_SPH_SHIFT 63
+#define I40E_RXD_QW1_LENGTH_SPH_MASK BIT_ULL(I40E_RXD_QW1_LENGTH_SPH_SHIFT)
+
+enum i40e_rx_desc_ext_status_bits {
+ /* Note: These are predefined bit offsets */
+ I40E_RX_DESC_EXT_STATUS_L2TAG2P_SHIFT = 0,
+ I40E_RX_DESC_EXT_STATUS_L2TAG3P_SHIFT = 1,
+ I40E_RX_DESC_EXT_STATUS_FLEXBL_SHIFT = 2, /* 2 BITS */
+ I40E_RX_DESC_EXT_STATUS_FLEXBH_SHIFT = 4, /* 2 BITS */
+ I40E_RX_DESC_EXT_STATUS_FDLONGB_SHIFT = 9,
+ I40E_RX_DESC_EXT_STATUS_FCOELONGB_SHIFT = 10,
+ I40E_RX_DESC_EXT_STATUS_PELONGB_SHIFT = 11,
+};
+
+enum i40e_rx_desc_pe_status_bits {
+ /* Note: These are predefined bit offsets */
+ I40E_RX_DESC_PE_STATUS_QPID_SHIFT = 0, /* 18 BITS */
+ I40E_RX_DESC_PE_STATUS_L4PORT_SHIFT = 0, /* 16 BITS */
+ I40E_RX_DESC_PE_STATUS_IPINDEX_SHIFT = 16, /* 8 BITS */
+ I40E_RX_DESC_PE_STATUS_QPIDHIT_SHIFT = 24,
+ I40E_RX_DESC_PE_STATUS_APBVTHIT_SHIFT = 25,
+ I40E_RX_DESC_PE_STATUS_PORTV_SHIFT = 26,
+ I40E_RX_DESC_PE_STATUS_URG_SHIFT = 27,
+ I40E_RX_DESC_PE_STATUS_IPFRAG_SHIFT = 28,
+ I40E_RX_DESC_PE_STATUS_IPOPT_SHIFT = 29
+};
+
+#define I40E_RX_PROG_STATUS_DESC_LENGTH_SHIFT 38
+#define I40E_RX_PROG_STATUS_DESC_LENGTH 0x2000000
+
+#define I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT 2
+#define I40E_RX_PROG_STATUS_DESC_QW1_PROGID_MASK (0x7UL << \
+ I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT)
+
+#define I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT 19
+#define I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK (0x3FUL << \
+ I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT)
+
+enum i40e_rx_prog_status_desc_status_bits {
+ /* Note: These are predefined bit offsets */
+ I40E_RX_PROG_STATUS_DESC_DD_SHIFT = 0,
+ I40E_RX_PROG_STATUS_DESC_PROG_ID_SHIFT = 2 /* 3 BITS */
+};
+
+enum i40e_rx_prog_status_desc_prog_id_masks {
+ I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS = 1,
+ I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS = 2,
+ I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS = 4,
+};
+
+enum i40e_rx_prog_status_desc_error_bits {
+ /* Note: These are predefined bit offsets */
+ I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT = 0,
+ I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT = 1,
+ I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT = 2,
+ I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT = 3
+};
+
+/* TX Descriptor */
+struct i40e_tx_desc {
+ __le64 buffer_addr; /* Address of descriptor's data buf */
+ __le64 cmd_type_offset_bsz;
+};
+
+#define I40E_TXD_QW1_DTYPE_SHIFT 0
+#define I40E_TXD_QW1_DTYPE_MASK (0xFUL << I40E_TXD_QW1_DTYPE_SHIFT)
+
+enum i40e_tx_desc_dtype_value {
+ I40E_TX_DESC_DTYPE_DATA = 0x0,
+ I40E_TX_DESC_DTYPE_NOP = 0x1, /* same as Context desc */
+ I40E_TX_DESC_DTYPE_CONTEXT = 0x1,
+ I40E_TX_DESC_DTYPE_FCOE_CTX = 0x2,
+ I40E_TX_DESC_DTYPE_FILTER_PROG = 0x8,
+ I40E_TX_DESC_DTYPE_DDP_CTX = 0x9,
+ I40E_TX_DESC_DTYPE_FLEX_DATA = 0xB,
+ I40E_TX_DESC_DTYPE_FLEX_CTX_1 = 0xC,
+ I40E_TX_DESC_DTYPE_FLEX_CTX_2 = 0xD,
+ I40E_TX_DESC_DTYPE_DESC_DONE = 0xF
+};
+
+#define I40E_TXD_QW1_CMD_SHIFT 4
+#define I40E_TXD_QW1_CMD_MASK (0x3FFUL << I40E_TXD_QW1_CMD_SHIFT)
+
+enum i40e_tx_desc_cmd_bits {
+ I40E_TX_DESC_CMD_EOP = 0x0001,
+ I40E_TX_DESC_CMD_RS = 0x0002,
+ I40E_TX_DESC_CMD_ICRC = 0x0004,
+ I40E_TX_DESC_CMD_IL2TAG1 = 0x0008,
+ I40E_TX_DESC_CMD_DUMMY = 0x0010,
+ I40E_TX_DESC_CMD_IIPT_NONIP = 0x0000, /* 2 BITS */
+ I40E_TX_DESC_CMD_IIPT_IPV6 = 0x0020, /* 2 BITS */
+ I40E_TX_DESC_CMD_IIPT_IPV4 = 0x0040, /* 2 BITS */
+ I40E_TX_DESC_CMD_IIPT_IPV4_CSUM = 0x0060, /* 2 BITS */
+ I40E_TX_DESC_CMD_FCOET = 0x0080,
+ I40E_TX_DESC_CMD_L4T_EOFT_UNK = 0x0000, /* 2 BITS */
+ I40E_TX_DESC_CMD_L4T_EOFT_TCP = 0x0100, /* 2 BITS */
+ I40E_TX_DESC_CMD_L4T_EOFT_SCTP = 0x0200, /* 2 BITS */
+ I40E_TX_DESC_CMD_L4T_EOFT_UDP = 0x0300, /* 2 BITS */
+ I40E_TX_DESC_CMD_L4T_EOFT_EOF_N = 0x0000, /* 2 BITS */
+ I40E_TX_DESC_CMD_L4T_EOFT_EOF_T = 0x0100, /* 2 BITS */
+ I40E_TX_DESC_CMD_L4T_EOFT_EOF_NI = 0x0200, /* 2 BITS */
+ I40E_TX_DESC_CMD_L4T_EOFT_EOF_A = 0x0300, /* 2 BITS */
+};
+
+#define I40E_TXD_QW1_OFFSET_SHIFT 16
+#define I40E_TXD_QW1_OFFSET_MASK (0x3FFFFULL << \
+ I40E_TXD_QW1_OFFSET_SHIFT)
+
+enum i40e_tx_desc_length_fields {
+ /* Note: These are predefined bit offsets */
+ I40E_TX_DESC_LENGTH_MACLEN_SHIFT = 0, /* 7 BITS */
+ I40E_TX_DESC_LENGTH_IPLEN_SHIFT = 7, /* 7 BITS */
+ I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT = 14 /* 4 BITS */
+};
+
+#define I40E_TXD_QW1_TX_BUF_SZ_SHIFT 34
+#define I40E_TXD_QW1_TX_BUF_SZ_MASK (0x3FFFULL << \
+ I40E_TXD_QW1_TX_BUF_SZ_SHIFT)
+
+#define I40E_TXD_QW1_L2TAG1_SHIFT 48
+#define I40E_TXD_QW1_L2TAG1_MASK (0xFFFFULL << I40E_TXD_QW1_L2TAG1_SHIFT)
+
+/* Context descriptors */
+struct i40e_tx_context_desc {
+ __le32 tunneling_params;
+ __le16 l2tag2;
+ __le16 rsvd;
+ __le64 type_cmd_tso_mss;
+};
+
+#define I40E_TXD_CTX_QW1_CMD_SHIFT 4
+#define I40E_TXD_CTX_QW1_CMD_MASK (0xFFFFUL << I40E_TXD_CTX_QW1_CMD_SHIFT)
+
+enum i40e_tx_ctx_desc_cmd_bits {
+ I40E_TX_CTX_DESC_TSO = 0x01,
+ I40E_TX_CTX_DESC_TSYN = 0x02,
+ I40E_TX_CTX_DESC_IL2TAG2 = 0x04,
+ I40E_TX_CTX_DESC_IL2TAG2_IL2H = 0x08,
+ I40E_TX_CTX_DESC_SWTCH_NOTAG = 0x00,
+ I40E_TX_CTX_DESC_SWTCH_UPLINK = 0x10,
+ I40E_TX_CTX_DESC_SWTCH_LOCAL = 0x20,
+ I40E_TX_CTX_DESC_SWTCH_VSI = 0x30,
+ I40E_TX_CTX_DESC_SWPE = 0x40
+};
+
+#define I40E_TXD_CTX_QW1_TSO_LEN_SHIFT 30
+#define I40E_TXD_CTX_QW1_TSO_LEN_MASK (0x3FFFFULL << \
+ I40E_TXD_CTX_QW1_TSO_LEN_SHIFT)
+
+#define I40E_TXD_CTX_QW1_MSS_SHIFT 50
+#define I40E_TXD_CTX_QW1_MSS_MASK (0x3FFFULL << \
+ I40E_TXD_CTX_QW1_MSS_SHIFT)
+
+#define I40E_TXD_CTX_QW1_VSI_SHIFT 50
+#define I40E_TXD_CTX_QW1_VSI_MASK (0x1FFULL << I40E_TXD_CTX_QW1_VSI_SHIFT)
+
+#define I40E_TXD_CTX_QW0_EXT_IP_SHIFT 0
+#define I40E_TXD_CTX_QW0_EXT_IP_MASK (0x3ULL << \
+ I40E_TXD_CTX_QW0_EXT_IP_SHIFT)
+
+enum i40e_tx_ctx_desc_eipt_offload {
+ I40E_TX_CTX_EXT_IP_NONE = 0x0,
+ I40E_TX_CTX_EXT_IP_IPV6 = 0x1,
+ I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM = 0x2,
+ I40E_TX_CTX_EXT_IP_IPV4 = 0x3
+};
+
+#define I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT 2
+#define I40E_TXD_CTX_QW0_EXT_IPLEN_MASK (0x3FULL << \
+ I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT)
+
+#define I40E_TXD_CTX_QW0_NATT_SHIFT 9
+#define I40E_TXD_CTX_QW0_NATT_MASK (0x3ULL << I40E_TXD_CTX_QW0_NATT_SHIFT)
+
+#define I40E_TXD_CTX_UDP_TUNNELING BIT_ULL(I40E_TXD_CTX_QW0_NATT_SHIFT)
+#define I40E_TXD_CTX_GRE_TUNNELING (0x2ULL << I40E_TXD_CTX_QW0_NATT_SHIFT)
+
+#define I40E_TXD_CTX_QW0_EIP_NOINC_SHIFT 11
+#define I40E_TXD_CTX_QW0_EIP_NOINC_MASK \
+ BIT_ULL(I40E_TXD_CTX_QW0_EIP_NOINC_SHIFT)
+
+#define I40E_TXD_CTX_EIP_NOINC_IPID_CONST I40E_TXD_CTX_QW0_EIP_NOINC_MASK
+
+#define I40E_TXD_CTX_QW0_NATLEN_SHIFT 12
+#define I40E_TXD_CTX_QW0_NATLEN_MASK (0X7FULL << \
+ I40E_TXD_CTX_QW0_NATLEN_SHIFT)
+
+#define I40E_TXD_CTX_QW0_DECTTL_SHIFT 19
+#define I40E_TXD_CTX_QW0_DECTTL_MASK (0xFULL << \
+ I40E_TXD_CTX_QW0_DECTTL_SHIFT)
+
+#define I40E_TXD_CTX_QW0_L4T_CS_SHIFT 23
+#define I40E_TXD_CTX_QW0_L4T_CS_MASK BIT_ULL(I40E_TXD_CTX_QW0_L4T_CS_SHIFT)
+
+/* Packet Classifier Types for filters */
+enum i40e_filter_pctype {
+ /* Note: Values 0-28 are reserved for future use.
+ * Value 29, 30, 32 are not supported on XL710 and X710.
+ */
+ I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP = 29,
+ I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP = 30,
+ I40E_FILTER_PCTYPE_NONF_IPV4_UDP = 31,
+ I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK = 32,
+ I40E_FILTER_PCTYPE_NONF_IPV4_TCP = 33,
+ I40E_FILTER_PCTYPE_NONF_IPV4_SCTP = 34,
+ I40E_FILTER_PCTYPE_NONF_IPV4_OTHER = 35,
+ I40E_FILTER_PCTYPE_FRAG_IPV4 = 36,
+ /* Note: Values 37-38 are reserved for future use.
+ * Value 39, 40, 42 are not supported on XL710 and X710.
+ */
+ I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP = 39,
+ I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP = 40,
+ I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41,
+ I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK = 42,
+ I40E_FILTER_PCTYPE_NONF_IPV6_TCP = 43,
+ I40E_FILTER_PCTYPE_NONF_IPV6_SCTP = 44,
+ I40E_FILTER_PCTYPE_NONF_IPV6_OTHER = 45,
+ I40E_FILTER_PCTYPE_FRAG_IPV6 = 46,
+ /* Note: Value 47 is reserved for future use */
+ I40E_FILTER_PCTYPE_FCOE_OX = 48,
+ I40E_FILTER_PCTYPE_FCOE_RX = 49,
+ I40E_FILTER_PCTYPE_FCOE_OTHER = 50,
+ /* Note: Values 51-62 are reserved for future use */
+ I40E_FILTER_PCTYPE_L2_PAYLOAD = 63,
+};
+
+
+struct i40e_vsi_context {
+ u16 seid;
+ u16 uplink_seid;
+ u16 vsi_number;
+ u16 vsis_allocated;
+ u16 vsis_unallocated;
+ u16 flags;
+ u8 pf_num;
+ u8 vf_num;
+ u8 connection_type;
+ struct i40e_aqc_vsi_properties_data info;
+};
+
+struct i40e_veb_context {
+ u16 seid;
+ u16 uplink_seid;
+ u16 veb_number;
+ u16 vebs_allocated;
+ u16 vebs_unallocated;
+ u16 flags;
+ struct i40e_aqc_get_veb_parameters_completion info;
+};
+
+/* Statistics collected by each port, VSI, VEB, and S-channel */
+struct i40e_eth_stats {
+ u64 rx_bytes; /* gorc */
+ u64 rx_unicast; /* uprc */
+ u64 rx_multicast; /* mprc */
+ u64 rx_broadcast; /* bprc */
+ u64 rx_discards; /* rdpc */
+ u64 rx_unknown_protocol; /* rupp */
+ u64 tx_bytes; /* gotc */
+ u64 tx_unicast; /* uptc */
+ u64 tx_multicast; /* mptc */
+ u64 tx_broadcast; /* bptc */
+ u64 tx_discards; /* tdpc */
+ u64 tx_errors; /* tepc */
+};
+#endif /* _I40E_TYPE_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40evf.h b/drivers/net/ethernet/intel/iavf/i40evf.h
new file mode 100644
index 000000000000..96e537a35000
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40evf.h
@@ -0,0 +1,427 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40EVF_H_
+#define _I40EVF_H_
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/sctp.h>
+#include <linux/ipv6.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/socket.h>
+#include <linux/jiffies.h>
+#include <net/ip6_checksum.h>
+#include <net/pkt_cls.h>
+#include <net/udp.h>
+#include <net/tc_act/tc_gact.h>
+#include <net/tc_act/tc_mirred.h>
+
+#include "i40e_type.h"
+#include <linux/avf/virtchnl.h>
+#include "i40e_txrx.h"
+
+#define DEFAULT_DEBUG_LEVEL_SHIFT 3
+#define PFX "i40evf: "
+
+/* VSI state flags shared with common code */
+enum i40evf_vsi_state_t {
+ __I40E_VSI_DOWN,
+ /* This must be last as it determines the size of the BITMAP */
+ __I40E_VSI_STATE_SIZE__,
+};
+
+/* dummy struct to make common code less painful */
+struct i40e_vsi {
+ struct i40evf_adapter *back;
+ struct net_device *netdev;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+ u16 seid;
+ u16 id;
+ DECLARE_BITMAP(state, __I40E_VSI_STATE_SIZE__);
+ int base_vector;
+ u16 work_limit;
+ u16 qs_handle;
+ void *priv; /* client driver data reference. */
+};
+
+/* How many Rx Buffers do we bundle into one write to the hardware ? */
+#define I40EVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */
+#define I40EVF_DEFAULT_TXD 512
+#define I40EVF_DEFAULT_RXD 512
+#define I40EVF_MAX_TXD 4096
+#define I40EVF_MIN_TXD 64
+#define I40EVF_MAX_RXD 4096
+#define I40EVF_MIN_RXD 64
+#define I40EVF_REQ_DESCRIPTOR_MULTIPLE 32
+#define I40EVF_MAX_AQ_BUF_SIZE 4096
+#define I40EVF_AQ_LEN 32
+#define I40EVF_AQ_MAX_ERR 20 /* times to try before resetting AQ */
+
+#define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
+
+#define I40E_RX_DESC(R, i) (&(((union i40e_32byte_rx_desc *)((R)->desc))[i]))
+#define I40E_TX_DESC(R, i) (&(((struct i40e_tx_desc *)((R)->desc))[i]))
+#define I40E_TX_CTXTDESC(R, i) \
+ (&(((struct i40e_tx_context_desc *)((R)->desc))[i]))
+#define I40EVF_MAX_REQ_QUEUES 4
+
+#define I40EVF_HKEY_ARRAY_SIZE ((I40E_VFQF_HKEY_MAX_INDEX + 1) * 4)
+#define I40EVF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT_MAX_INDEX + 1) * 4)
+#define I40EVF_MBPS_DIVISOR 125000 /* divisor to convert to Mbps */
+
+/* MAX_MSIX_Q_VECTORS of these are allocated,
+ * but we only use one per queue-specific vector.
+ */
+struct i40e_q_vector {
+ struct i40evf_adapter *adapter;
+ struct i40e_vsi *vsi;
+ struct napi_struct napi;
+ struct i40e_ring_container rx;
+ struct i40e_ring_container tx;
+ u32 ring_mask;
+ u8 itr_countdown; /* when 0 should adjust adaptive ITR */
+ u8 num_ringpairs; /* total number of ring pairs in vector */
+ u16 v_idx; /* index in the vsi->q_vector array. */
+ u16 reg_idx; /* register index of the interrupt */
+ char name[IFNAMSIZ + 15];
+ bool arm_wb_state;
+ cpumask_t affinity_mask;
+ struct irq_affinity_notify affinity_notify;
+};
+
+/* Helper macros to switch between ints/sec and what the register uses.
+ * And yes, it's the same math going both ways. The lowest value
+ * supported by all of the i40e hardware is 8.
+ */
+#define EITR_INTS_PER_SEC_TO_REG(_eitr) \
+ ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8)
+#define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG
+
+#define I40EVF_DESC_UNUSED(R) \
+ ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
+ (R)->next_to_clean - (R)->next_to_use - 1)
+
+#define I40EVF_RX_DESC_ADV(R, i) \
+ (&(((union i40e_adv_rx_desc *)((R).desc))[i]))
+#define I40EVF_TX_DESC_ADV(R, i) \
+ (&(((union i40e_adv_tx_desc *)((R).desc))[i]))
+#define I40EVF_TX_CTXTDESC_ADV(R, i) \
+ (&(((struct i40e_adv_tx_context_desc *)((R).desc))[i]))
+
+#define OTHER_VECTOR 1
+#define NONQ_VECS (OTHER_VECTOR)
+
+#define MIN_MSIX_Q_VECTORS 1
+#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NONQ_VECS)
+
+#define I40EVF_QUEUE_END_OF_LIST 0x7FF
+#define I40EVF_FREE_VECTOR 0x7FFF
+struct i40evf_mac_filter {
+ struct list_head list;
+ u8 macaddr[ETH_ALEN];
+ bool remove; /* filter needs to be removed */
+ bool add; /* filter needs to be added */
+};
+
+struct i40evf_vlan_filter {
+ struct list_head list;
+ u16 vlan;
+ bool remove; /* filter needs to be removed */
+ bool add; /* filter needs to be added */
+};
+
+#define I40EVF_MAX_TRAFFIC_CLASS 4
+/* State of traffic class creation */
+enum i40evf_tc_state_t {
+ __I40EVF_TC_INVALID, /* no traffic class, default state */
+ __I40EVF_TC_RUNNING, /* traffic classes have been created */
+};
+
+/* channel info */
+struct i40evf_channel_config {
+ struct virtchnl_channel_info ch_info[I40EVF_MAX_TRAFFIC_CLASS];
+ enum i40evf_tc_state_t state;
+ u8 total_qps;
+};
+
+/* State of cloud filter */
+enum i40evf_cloud_filter_state_t {
+ __I40EVF_CF_INVALID, /* cloud filter not added */
+ __I40EVF_CF_ADD_PENDING, /* cloud filter pending add by the PF */
+ __I40EVF_CF_DEL_PENDING, /* cloud filter pending del by the PF */
+ __I40EVF_CF_ACTIVE, /* cloud filter is active */
+};
+
+/* Driver state. The order of these is important! */
+enum i40evf_state_t {
+ __I40EVF_STARTUP, /* driver loaded, probe complete */
+ __I40EVF_REMOVE, /* driver is being unloaded */
+ __I40EVF_INIT_VERSION_CHECK, /* aq msg sent, awaiting reply */
+ __I40EVF_INIT_GET_RESOURCES, /* aq msg sent, awaiting reply */
+ __I40EVF_INIT_SW, /* got resources, setting up structs */
+ __I40EVF_RESETTING, /* in reset */
+ /* Below here, watchdog is running */
+ __I40EVF_DOWN, /* ready, can be opened */
+ __I40EVF_DOWN_PENDING, /* descending, waiting for watchdog */
+ __I40EVF_TESTING, /* in ethtool self-test */
+ __I40EVF_RUNNING, /* opened, working */
+};
+
+enum i40evf_critical_section_t {
+ __I40EVF_IN_CRITICAL_TASK, /* cannot be interrupted */
+ __I40EVF_IN_CLIENT_TASK,
+ __I40EVF_IN_REMOVE_TASK, /* device being removed */
+};
+
+#define I40EVF_CLOUD_FIELD_OMAC 0x01
+#define I40EVF_CLOUD_FIELD_IMAC 0x02
+#define I40EVF_CLOUD_FIELD_IVLAN 0x04
+#define I40EVF_CLOUD_FIELD_TEN_ID 0x08
+#define I40EVF_CLOUD_FIELD_IIP 0x10
+
+#define I40EVF_CF_FLAGS_OMAC I40EVF_CLOUD_FIELD_OMAC
+#define I40EVF_CF_FLAGS_IMAC I40EVF_CLOUD_FIELD_IMAC
+#define I40EVF_CF_FLAGS_IMAC_IVLAN (I40EVF_CLOUD_FIELD_IMAC |\
+ I40EVF_CLOUD_FIELD_IVLAN)
+#define I40EVF_CF_FLAGS_IMAC_TEN_ID (I40EVF_CLOUD_FIELD_IMAC |\
+ I40EVF_CLOUD_FIELD_TEN_ID)
+#define I40EVF_CF_FLAGS_OMAC_TEN_ID_IMAC (I40EVF_CLOUD_FIELD_OMAC |\
+ I40EVF_CLOUD_FIELD_IMAC |\
+ I40EVF_CLOUD_FIELD_TEN_ID)
+#define I40EVF_CF_FLAGS_IMAC_IVLAN_TEN_ID (I40EVF_CLOUD_FIELD_IMAC |\
+ I40EVF_CLOUD_FIELD_IVLAN |\
+ I40EVF_CLOUD_FIELD_TEN_ID)
+#define I40EVF_CF_FLAGS_IIP I40E_CLOUD_FIELD_IIP
+
+/* bookkeeping of cloud filters */
+struct i40evf_cloud_filter {
+ enum i40evf_cloud_filter_state_t state;
+ struct list_head list;
+ struct virtchnl_filter f;
+ unsigned long cookie;
+ bool del; /* filter needs to be deleted */
+ bool add; /* filter needs to be added */
+};
+
+/* board specific private data structure */
+struct i40evf_adapter {
+ struct timer_list watchdog_timer;
+ struct work_struct reset_task;
+ struct work_struct adminq_task;
+ struct delayed_work client_task;
+ struct delayed_work init_task;
+ wait_queue_head_t down_waitqueue;
+ struct i40e_q_vector *q_vectors;
+ struct list_head vlan_filter_list;
+ struct list_head mac_filter_list;
+ /* Lock to protect accesses to MAC and VLAN lists */
+ spinlock_t mac_vlan_list_lock;
+ char misc_vector_name[IFNAMSIZ + 9];
+ int num_active_queues;
+ int num_req_queues;
+
+ /* TX */
+ struct i40e_ring *tx_rings;
+ u32 tx_timeout_count;
+ u32 tx_desc_count;
+
+ /* RX */
+ struct i40e_ring *rx_rings;
+ u64 hw_csum_rx_error;
+ u32 rx_desc_count;
+ int num_msix_vectors;
+ int num_iwarp_msix;
+ int iwarp_base_vector;
+ u32 client_pending;
+ struct i40e_client_instance *cinst;
+ struct msix_entry *msix_entries;
+
+ u32 flags;
+#define I40EVF_FLAG_RX_CSUM_ENABLED BIT(0)
+#define I40EVF_FLAG_PF_COMMS_FAILED BIT(3)
+#define I40EVF_FLAG_RESET_PENDING BIT(4)
+#define I40EVF_FLAG_RESET_NEEDED BIT(5)
+#define I40EVF_FLAG_WB_ON_ITR_CAPABLE BIT(6)
+#define I40EVF_FLAG_ADDR_SET_BY_PF BIT(8)
+#define I40EVF_FLAG_SERVICE_CLIENT_REQUESTED BIT(9)
+#define I40EVF_FLAG_CLIENT_NEEDS_OPEN BIT(10)
+#define I40EVF_FLAG_CLIENT_NEEDS_CLOSE BIT(11)
+#define I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS BIT(12)
+#define I40EVF_FLAG_PROMISC_ON BIT(13)
+#define I40EVF_FLAG_ALLMULTI_ON BIT(14)
+#define I40EVF_FLAG_LEGACY_RX BIT(15)
+#define I40EVF_FLAG_REINIT_ITR_NEEDED BIT(16)
+#define I40EVF_FLAG_QUEUES_DISABLED BIT(17)
+/* duplicates for common code */
+#define I40E_FLAG_DCB_ENABLED 0
+#define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED
+#define I40E_FLAG_LEGACY_RX I40EVF_FLAG_LEGACY_RX
+ /* flags for admin queue service task */
+ u32 aq_required;
+#define I40EVF_FLAG_AQ_ENABLE_QUEUES BIT(0)
+#define I40EVF_FLAG_AQ_DISABLE_QUEUES BIT(1)
+#define I40EVF_FLAG_AQ_ADD_MAC_FILTER BIT(2)
+#define I40EVF_FLAG_AQ_ADD_VLAN_FILTER BIT(3)
+#define I40EVF_FLAG_AQ_DEL_MAC_FILTER BIT(4)
+#define I40EVF_FLAG_AQ_DEL_VLAN_FILTER BIT(5)
+#define I40EVF_FLAG_AQ_CONFIGURE_QUEUES BIT(6)
+#define I40EVF_FLAG_AQ_MAP_VECTORS BIT(7)
+#define I40EVF_FLAG_AQ_HANDLE_RESET BIT(8)
+#define I40EVF_FLAG_AQ_CONFIGURE_RSS BIT(9) /* direct AQ config */
+#define I40EVF_FLAG_AQ_GET_CONFIG BIT(10)
+/* Newer style, RSS done by the PF so we can ignore hardware vagaries. */
+#define I40EVF_FLAG_AQ_GET_HENA BIT(11)
+#define I40EVF_FLAG_AQ_SET_HENA BIT(12)
+#define I40EVF_FLAG_AQ_SET_RSS_KEY BIT(13)
+#define I40EVF_FLAG_AQ_SET_RSS_LUT BIT(14)
+#define I40EVF_FLAG_AQ_REQUEST_PROMISC BIT(15)
+#define I40EVF_FLAG_AQ_RELEASE_PROMISC BIT(16)
+#define I40EVF_FLAG_AQ_REQUEST_ALLMULTI BIT(17)
+#define I40EVF_FLAG_AQ_RELEASE_ALLMULTI BIT(18)
+#define I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING BIT(19)
+#define I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING BIT(20)
+#define I40EVF_FLAG_AQ_ENABLE_CHANNELS BIT(21)
+#define I40EVF_FLAG_AQ_DISABLE_CHANNELS BIT(22)
+#define I40EVF_FLAG_AQ_ADD_CLOUD_FILTER BIT(23)
+#define I40EVF_FLAG_AQ_DEL_CLOUD_FILTER BIT(24)
+
+ /* OS defined structs */
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+
+ struct i40e_hw hw; /* defined in i40e_type.h */
+
+ enum i40evf_state_t state;
+ unsigned long crit_section;
+
+ struct work_struct watchdog_task;
+ bool netdev_registered;
+ bool link_up;
+ enum virtchnl_link_speed link_speed;
+ enum virtchnl_ops current_op;
+#define CLIENT_ALLOWED(_a) ((_a)->vf_res ? \
+ (_a)->vf_res->vf_cap_flags & \
+ VIRTCHNL_VF_OFFLOAD_IWARP : \
+ 0)
+#define CLIENT_ENABLED(_a) ((_a)->cinst)
+/* RSS by the PF should be preferred over RSS via other methods. */
+#define RSS_PF(_a) ((_a)->vf_res->vf_cap_flags & \
+ VIRTCHNL_VF_OFFLOAD_RSS_PF)
+#define RSS_AQ(_a) ((_a)->vf_res->vf_cap_flags & \
+ VIRTCHNL_VF_OFFLOAD_RSS_AQ)
+#define RSS_REG(_a) (!((_a)->vf_res->vf_cap_flags & \
+ (VIRTCHNL_VF_OFFLOAD_RSS_AQ | \
+ VIRTCHNL_VF_OFFLOAD_RSS_PF)))
+#define VLAN_ALLOWED(_a) ((_a)->vf_res->vf_cap_flags & \
+ VIRTCHNL_VF_OFFLOAD_VLAN)
+ struct virtchnl_vf_resource *vf_res; /* incl. all VSIs */
+ struct virtchnl_vsi_resource *vsi_res; /* our LAN VSI */
+ struct virtchnl_version_info pf_version;
+#define PF_IS_V11(_a) (((_a)->pf_version.major == 1) && \
+ ((_a)->pf_version.minor == 1))
+ u16 msg_enable;
+ struct i40e_eth_stats current_stats;
+ struct i40e_vsi vsi;
+ u32 aq_wait_count;
+ /* RSS stuff */
+ u64 hena;
+ u16 rss_key_size;
+ u16 rss_lut_size;
+ u8 *rss_key;
+ u8 *rss_lut;
+ /* ADQ related members */
+ struct i40evf_channel_config ch_config;
+ u8 num_tc;
+ struct list_head cloud_filter_list;
+ /* lock to protest access to the cloud filter list */
+ spinlock_t cloud_filter_list_lock;
+ u16 num_cloud_filters;
+};
+
+
+/* Ethtool Private Flags */
+
+/* lan device */
+struct i40e_device {
+ struct list_head list;
+ struct i40evf_adapter *vf;
+};
+
+/* needed by i40evf_ethtool.c */
+extern char i40evf_driver_name[];
+extern const char i40evf_driver_version[];
+
+int i40evf_up(struct i40evf_adapter *adapter);
+void i40evf_down(struct i40evf_adapter *adapter);
+int i40evf_process_config(struct i40evf_adapter *adapter);
+void i40evf_schedule_reset(struct i40evf_adapter *adapter);
+void i40evf_reset(struct i40evf_adapter *adapter);
+void i40evf_set_ethtool_ops(struct net_device *netdev);
+void i40evf_update_stats(struct i40evf_adapter *adapter);
+void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter);
+int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter);
+void i40evf_irq_enable_queues(struct i40evf_adapter *adapter, u32 mask);
+void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter);
+void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter);
+
+void i40e_napi_add_all(struct i40evf_adapter *adapter);
+void i40e_napi_del_all(struct i40evf_adapter *adapter);
+
+int i40evf_send_api_ver(struct i40evf_adapter *adapter);
+int i40evf_verify_api_ver(struct i40evf_adapter *adapter);
+int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter);
+int i40evf_get_vf_config(struct i40evf_adapter *adapter);
+void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush);
+void i40evf_configure_queues(struct i40evf_adapter *adapter);
+void i40evf_deconfigure_queues(struct i40evf_adapter *adapter);
+void i40evf_enable_queues(struct i40evf_adapter *adapter);
+void i40evf_disable_queues(struct i40evf_adapter *adapter);
+void i40evf_map_queues(struct i40evf_adapter *adapter);
+int i40evf_request_queues(struct i40evf_adapter *adapter, int num);
+void i40evf_add_ether_addrs(struct i40evf_adapter *adapter);
+void i40evf_del_ether_addrs(struct i40evf_adapter *adapter);
+void i40evf_add_vlans(struct i40evf_adapter *adapter);
+void i40evf_del_vlans(struct i40evf_adapter *adapter);
+void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags);
+void i40evf_request_stats(struct i40evf_adapter *adapter);
+void i40evf_request_reset(struct i40evf_adapter *adapter);
+void i40evf_get_hena(struct i40evf_adapter *adapter);
+void i40evf_set_hena(struct i40evf_adapter *adapter);
+void i40evf_set_rss_key(struct i40evf_adapter *adapter);
+void i40evf_set_rss_lut(struct i40evf_adapter *adapter);
+void i40evf_enable_vlan_stripping(struct i40evf_adapter *adapter);
+void i40evf_disable_vlan_stripping(struct i40evf_adapter *adapter);
+void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
+ enum virtchnl_ops v_opcode,
+ i40e_status v_retval, u8 *msg, u16 msglen);
+int i40evf_config_rss(struct i40evf_adapter *adapter);
+int i40evf_lan_add_device(struct i40evf_adapter *adapter);
+int i40evf_lan_del_device(struct i40evf_adapter *adapter);
+void i40evf_client_subtask(struct i40evf_adapter *adapter);
+void i40evf_notify_client_message(struct i40e_vsi *vsi, u8 *msg, u16 len);
+void i40evf_notify_client_l2_params(struct i40e_vsi *vsi);
+void i40evf_notify_client_open(struct i40e_vsi *vsi);
+void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset);
+void i40evf_enable_channels(struct i40evf_adapter *adapter);
+void i40evf_disable_channels(struct i40evf_adapter *adapter);
+void i40evf_add_cloud_filter(struct i40evf_adapter *adapter);
+void i40evf_del_cloud_filter(struct i40evf_adapter *adapter);
+#endif /* _I40EVF_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40evf_client.c b/drivers/net/ethernet/intel/iavf/i40evf_client.c
new file mode 100644
index 000000000000..3cc9d60d0d72
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40evf_client.c
@@ -0,0 +1,579 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#include <linux/list.h>
+#include <linux/errno.h>
+
+#include "i40evf.h"
+#include "i40e_prototype.h"
+#include "i40evf_client.h"
+
+static
+const char i40evf_client_interface_version_str[] = I40EVF_CLIENT_VERSION_STR;
+static struct i40e_client *vf_registered_client;
+static LIST_HEAD(i40evf_devices);
+static DEFINE_MUTEX(i40evf_device_mutex);
+
+static u32 i40evf_client_virtchnl_send(struct i40e_info *ldev,
+ struct i40e_client *client,
+ u8 *msg, u16 len);
+
+static int i40evf_client_setup_qvlist(struct i40e_info *ldev,
+ struct i40e_client *client,
+ struct i40e_qvlist_info *qvlist_info);
+
+static struct i40e_ops i40evf_lan_ops = {
+ .virtchnl_send = i40evf_client_virtchnl_send,
+ .setup_qvlist = i40evf_client_setup_qvlist,
+};
+
+/**
+ * i40evf_client_get_params - retrieve relevant client parameters
+ * @vsi: VSI with parameters
+ * @params: client param struct
+ **/
+static
+void i40evf_client_get_params(struct i40e_vsi *vsi, struct i40e_params *params)
+{
+ int i;
+
+ memset(params, 0, sizeof(struct i40e_params));
+ params->mtu = vsi->netdev->mtu;
+ params->link_up = vsi->back->link_up;
+
+ for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
+ params->qos.prio_qos[i].tc = 0;
+ params->qos.prio_qos[i].qs_handle = vsi->qs_handle;
+ }
+}
+
+/**
+ * i40evf_notify_client_message - call the client message receive callback
+ * @vsi: the VSI associated with this client
+ * @msg: message buffer
+ * @len: length of message
+ *
+ * If there is a client to this VSI, call the client
+ **/
+void i40evf_notify_client_message(struct i40e_vsi *vsi, u8 *msg, u16 len)
+{
+ struct i40e_client_instance *cinst;
+
+ if (!vsi)
+ return;
+
+ cinst = vsi->back->cinst;
+ if (!cinst || !cinst->client || !cinst->client->ops ||
+ !cinst->client->ops->virtchnl_receive) {
+ dev_dbg(&vsi->back->pdev->dev,
+ "Cannot locate client instance virtchnl_receive function\n");
+ return;
+ }
+ cinst->client->ops->virtchnl_receive(&cinst->lan_info, cinst->client,
+ msg, len);
+}
+
+/**
+ * i40evf_notify_client_l2_params - call the client notify callback
+ * @vsi: the VSI with l2 param changes
+ *
+ * If there is a client to this VSI, call the client
+ **/
+void i40evf_notify_client_l2_params(struct i40e_vsi *vsi)
+{
+ struct i40e_client_instance *cinst;
+ struct i40e_params params;
+
+ if (!vsi)
+ return;
+
+ cinst = vsi->back->cinst;
+
+ if (!cinst || !cinst->client || !cinst->client->ops ||
+ !cinst->client->ops->l2_param_change) {
+ dev_dbg(&vsi->back->pdev->dev,
+ "Cannot locate client instance l2_param_change function\n");
+ return;
+ }
+ i40evf_client_get_params(vsi, ¶ms);
+ cinst->lan_info.params = params;
+ cinst->client->ops->l2_param_change(&cinst->lan_info, cinst->client,
+ ¶ms);
+}
+
+/**
+ * i40evf_notify_client_open - call the client open callback
+ * @vsi: the VSI with netdev opened
+ *
+ * If there is a client to this netdev, call the client with open
+ **/
+void i40evf_notify_client_open(struct i40e_vsi *vsi)
+{
+ struct i40evf_adapter *adapter = vsi->back;
+ struct i40e_client_instance *cinst = adapter->cinst;
+ int ret;
+
+ if (!cinst || !cinst->client || !cinst->client->ops ||
+ !cinst->client->ops->open) {
+ dev_dbg(&vsi->back->pdev->dev,
+ "Cannot locate client instance open function\n");
+ return;
+ }
+ if (!(test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state))) {
+ ret = cinst->client->ops->open(&cinst->lan_info, cinst->client);
+ if (!ret)
+ set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
+ }
+}
+
+/**
+ * i40evf_client_release_qvlist - send a message to the PF to release iwarp qv map
+ * @ldev: pointer to L2 context.
+ *
+ * Return 0 on success or < 0 on error
+ **/
+static int i40evf_client_release_qvlist(struct i40e_info *ldev)
+{
+ struct i40evf_adapter *adapter = ldev->vf;
+ i40e_status err;
+
+ if (adapter->aq_required)
+ return -EAGAIN;
+
+ err = i40e_aq_send_msg_to_pf(&adapter->hw,
+ VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP,
+ I40E_SUCCESS, NULL, 0, NULL);
+
+ if (err)
+ dev_err(&adapter->pdev->dev,
+ "Unable to send iWarp vector release message to PF, error %d, aq status %d\n",
+ err, adapter->hw.aq.asq_last_status);
+
+ return err;
+}
+
+/**
+ * i40evf_notify_client_close - call the client close callback
+ * @vsi: the VSI with netdev closed
+ * @reset: true when close called due to reset pending
+ *
+ * If there is a client to this netdev, call the client with close
+ **/
+void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset)
+{
+ struct i40evf_adapter *adapter = vsi->back;
+ struct i40e_client_instance *cinst = adapter->cinst;
+
+ if (!cinst || !cinst->client || !cinst->client->ops ||
+ !cinst->client->ops->close) {
+ dev_dbg(&vsi->back->pdev->dev,
+ "Cannot locate client instance close function\n");
+ return;
+ }
+ cinst->client->ops->close(&cinst->lan_info, cinst->client, reset);
+ i40evf_client_release_qvlist(&cinst->lan_info);
+ clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
+}
+
+/**
+ * i40evf_client_add_instance - add a client instance to the instance list
+ * @adapter: pointer to the board struct
+ *
+ * Returns cinst ptr on success, NULL on failure
+ **/
+static struct i40e_client_instance *
+i40evf_client_add_instance(struct i40evf_adapter *adapter)
+{
+ struct i40e_client_instance *cinst = NULL;
+ struct i40e_vsi *vsi = &adapter->vsi;
+ struct netdev_hw_addr *mac = NULL;
+ struct i40e_params params;
+
+ if (!vf_registered_client)
+ goto out;
+
+ if (adapter->cinst) {
+ cinst = adapter->cinst;
+ goto out;
+ }
+
+ cinst = kzalloc(sizeof(*cinst), GFP_KERNEL);
+ if (!cinst)
+ goto out;
+
+ cinst->lan_info.vf = (void *)adapter;
+ cinst->lan_info.netdev = vsi->netdev;
+ cinst->lan_info.pcidev = adapter->pdev;
+ cinst->lan_info.fid = 0;
+ cinst->lan_info.ftype = I40E_CLIENT_FTYPE_VF;
+ cinst->lan_info.hw_addr = adapter->hw.hw_addr;
+ cinst->lan_info.ops = &i40evf_lan_ops;
+ cinst->lan_info.version.major = I40EVF_CLIENT_VERSION_MAJOR;
+ cinst->lan_info.version.minor = I40EVF_CLIENT_VERSION_MINOR;
+ cinst->lan_info.version.build = I40EVF_CLIENT_VERSION_BUILD;
+ i40evf_client_get_params(vsi, ¶ms);
+ cinst->lan_info.params = params;
+ set_bit(__I40E_CLIENT_INSTANCE_NONE, &cinst->state);
+
+ cinst->lan_info.msix_count = adapter->num_iwarp_msix;
+ cinst->lan_info.msix_entries =
+ &adapter->msix_entries[adapter->iwarp_base_vector];
+
+ mac = list_first_entry(&cinst->lan_info.netdev->dev_addrs.list,
+ struct netdev_hw_addr, list);
+ if (mac)
+ ether_addr_copy(cinst->lan_info.lanmac, mac->addr);
+ else
+ dev_err(&adapter->pdev->dev, "MAC address list is empty!\n");
+
+ cinst->client = vf_registered_client;
+ adapter->cinst = cinst;
+out:
+ return cinst;
+}
+
+/**
+ * i40evf_client_del_instance - removes a client instance from the list
+ * @adapter: pointer to the board struct
+ *
+ **/
+static
+void i40evf_client_del_instance(struct i40evf_adapter *adapter)
+{
+ kfree(adapter->cinst);
+ adapter->cinst = NULL;
+}
+
+/**
+ * i40evf_client_subtask - client maintenance work
+ * @adapter: board private structure
+ **/
+void i40evf_client_subtask(struct i40evf_adapter *adapter)
+{
+ struct i40e_client *client = vf_registered_client;
+ struct i40e_client_instance *cinst;
+ int ret = 0;
+
+ if (adapter->state < __I40EVF_DOWN)
+ return;
+
+ /* first check client is registered */
+ if (!client)
+ return;
+
+ /* Add the client instance to the instance list */
+ cinst = i40evf_client_add_instance(adapter);
+ if (!cinst)
+ return;
+
+ dev_info(&adapter->pdev->dev, "Added instance of Client %s\n",
+ client->name);
+
+ if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {
+ /* Send an Open request to the client */
+
+ if (client->ops && client->ops->open)
+ ret = client->ops->open(&cinst->lan_info, client);
+ if (!ret)
+ set_bit(__I40E_CLIENT_INSTANCE_OPENED,
+ &cinst->state);
+ else
+ /* remove client instance */
+ i40evf_client_del_instance(adapter);
+ }
+}
+
+/**
+ * i40evf_lan_add_device - add a lan device struct to the list of lan devices
+ * @adapter: pointer to the board struct
+ *
+ * Returns 0 on success or none 0 on error
+ **/
+int i40evf_lan_add_device(struct i40evf_adapter *adapter)
+{
+ struct i40e_device *ldev;
+ int ret = 0;
+
+ mutex_lock(&i40evf_device_mutex);
+ list_for_each_entry(ldev, &i40evf_devices, list) {
+ if (ldev->vf == adapter) {
+ ret = -EEXIST;
+ goto out;
+ }
+ }
+ ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
+ if (!ldev) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ ldev->vf = adapter;
+ INIT_LIST_HEAD(&ldev->list);
+ list_add(&ldev->list, &i40evf_devices);
+ dev_info(&adapter->pdev->dev, "Added LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
+ adapter->hw.bus.bus_id, adapter->hw.bus.device,
+ adapter->hw.bus.func);
+
+ /* Since in some cases register may have happened before a device gets
+ * added, we can schedule a subtask to go initiate the clients.
+ */
+ adapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
+
+out:
+ mutex_unlock(&i40evf_device_mutex);
+ return ret;
+}
+
+/**
+ * i40evf_lan_del_device - removes a lan device from the device list
+ * @adapter: pointer to the board struct
+ *
+ * Returns 0 on success or non-0 on error
+ **/
+int i40evf_lan_del_device(struct i40evf_adapter *adapter)
+{
+ struct i40e_device *ldev, *tmp;
+ int ret = -ENODEV;
+
+ mutex_lock(&i40evf_device_mutex);
+ list_for_each_entry_safe(ldev, tmp, &i40evf_devices, list) {
+ if (ldev->vf == adapter) {
+ dev_info(&adapter->pdev->dev,
+ "Deleted LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
+ adapter->hw.bus.bus_id, adapter->hw.bus.device,
+ adapter->hw.bus.func);
+ list_del(&ldev->list);
+ kfree(ldev);
+ ret = 0;
+ break;
+ }
+ }
+
+ mutex_unlock(&i40evf_device_mutex);
+ return ret;
+}
+
+/**
+ * i40evf_client_release - release client specific resources
+ * @client: pointer to the registered client
+ *
+ **/
+static void i40evf_client_release(struct i40e_client *client)
+{
+ struct i40e_client_instance *cinst;
+ struct i40e_device *ldev;
+ struct i40evf_adapter *adapter;
+
+ mutex_lock(&i40evf_device_mutex);
+ list_for_each_entry(ldev, &i40evf_devices, list) {
+ adapter = ldev->vf;
+ cinst = adapter->cinst;
+ if (!cinst)
+ continue;
+ if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {
+ if (client->ops && client->ops->close)
+ client->ops->close(&cinst->lan_info, client,
+ false);
+ i40evf_client_release_qvlist(&cinst->lan_info);
+ clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
+
+ dev_warn(&adapter->pdev->dev,
+ "Client %s instance closed\n", client->name);
+ }
+ /* delete the client instance */
+ i40evf_client_del_instance(adapter);
+ dev_info(&adapter->pdev->dev, "Deleted client instance of Client %s\n",
+ client->name);
+ }
+ mutex_unlock(&i40evf_device_mutex);
+}
+
+/**
+ * i40evf_client_prepare - prepare client specific resources
+ * @client: pointer to the registered client
+ *
+ **/
+static void i40evf_client_prepare(struct i40e_client *client)
+{
+ struct i40e_device *ldev;
+ struct i40evf_adapter *adapter;
+
+ mutex_lock(&i40evf_device_mutex);
+ list_for_each_entry(ldev, &i40evf_devices, list) {
+ adapter = ldev->vf;
+ /* Signal the watchdog to service the client */
+ adapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
+ }
+ mutex_unlock(&i40evf_device_mutex);
+}
+
+/**
+ * i40evf_client_virtchnl_send - send a message to the PF instance
+ * @ldev: pointer to L2 context.
+ * @client: Client pointer.
+ * @msg: pointer to message buffer
+ * @len: message length
+ *
+ * Return 0 on success or < 0 on error
+ **/
+static u32 i40evf_client_virtchnl_send(struct i40e_info *ldev,
+ struct i40e_client *client,
+ u8 *msg, u16 len)
+{
+ struct i40evf_adapter *adapter = ldev->vf;
+ i40e_status err;
+
+ if (adapter->aq_required)
+ return -EAGAIN;
+
+ err = i40e_aq_send_msg_to_pf(&adapter->hw, VIRTCHNL_OP_IWARP,
+ I40E_SUCCESS, msg, len, NULL);
+ if (err)
+ dev_err(&adapter->pdev->dev, "Unable to send iWarp message to PF, error %d, aq status %d\n",
+ err, adapter->hw.aq.asq_last_status);
+
+ return err;
+}
+
+/**
+ * i40evf_client_setup_qvlist - send a message to the PF to setup iwarp qv map
+ * @ldev: pointer to L2 context.
+ * @client: Client pointer.
+ * @qvlist_info: queue and vector list
+ *
+ * Return 0 on success or < 0 on error
+ **/
+static int i40evf_client_setup_qvlist(struct i40e_info *ldev,
+ struct i40e_client *client,
+ struct i40e_qvlist_info *qvlist_info)
+{
+ struct virtchnl_iwarp_qvlist_info *v_qvlist_info;
+ struct i40evf_adapter *adapter = ldev->vf;
+ struct i40e_qv_info *qv_info;
+ i40e_status err;
+ u32 v_idx, i;
+ u32 msg_size;
+
+ if (adapter->aq_required)
+ return -EAGAIN;
+
+ /* A quick check on whether the vectors belong to the client */
+ for (i = 0; i < qvlist_info->num_vectors; i++) {
+ qv_info = &qvlist_info->qv_info[i];
+ if (!qv_info)
+ continue;
+ v_idx = qv_info->v_idx;
+ if ((v_idx >=
+ (adapter->iwarp_base_vector + adapter->num_iwarp_msix)) ||
+ (v_idx < adapter->iwarp_base_vector))
+ return -EINVAL;
+ }
+
+ v_qvlist_info = (struct virtchnl_iwarp_qvlist_info *)qvlist_info;
+ msg_size = sizeof(struct virtchnl_iwarp_qvlist_info) +
+ (sizeof(struct virtchnl_iwarp_qv_info) *
+ (v_qvlist_info->num_vectors - 1));
+
+ adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP);
+ err = i40e_aq_send_msg_to_pf(&adapter->hw,
+ VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP,
+ I40E_SUCCESS, (u8 *)v_qvlist_info, msg_size, NULL);
+
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Unable to send iWarp vector config message to PF, error %d, aq status %d\n",
+ err, adapter->hw.aq.asq_last_status);
+ goto out;
+ }
+
+ err = -EBUSY;
+ for (i = 0; i < 5; i++) {
+ msleep(100);
+ if (!(adapter->client_pending &
+ BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP))) {
+ err = 0;
+ break;
+ }
+ }
+out:
+ return err;
+}
+
+/**
+ * i40evf_register_client - Register a i40e client driver with the L2 driver
+ * @client: pointer to the i40e_client struct
+ *
+ * Returns 0 on success or non-0 on error
+ **/
+int i40evf_register_client(struct i40e_client *client)
+{
+ int ret = 0;
+
+ if (!client) {
+ ret = -EIO;
+ goto out;
+ }
+
+ if (strlen(client->name) == 0) {
+ pr_info("i40evf: Failed to register client with no name\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ if (vf_registered_client) {
+ pr_info("i40evf: Client %s has already been registered!\n",
+ client->name);
+ ret = -EEXIST;
+ goto out;
+ }
+
+ if ((client->version.major != I40EVF_CLIENT_VERSION_MAJOR) ||
+ (client->version.minor != I40EVF_CLIENT_VERSION_MINOR)) {
+ pr_info("i40evf: Failed to register client %s due to mismatched client interface version\n",
+ client->name);
+ pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n",
+ client->version.major, client->version.minor,
+ client->version.build,
+ i40evf_client_interface_version_str);
+ ret = -EIO;
+ goto out;
+ }
+
+ vf_registered_client = client;
+
+ i40evf_client_prepare(client);
+
+ pr_info("i40evf: Registered client %s with return code %d\n",
+ client->name, ret);
+out:
+ return ret;
+}
+EXPORT_SYMBOL(i40evf_register_client);
+
+/**
+ * i40evf_unregister_client - Unregister a i40e client driver with the L2 driver
+ * @client: pointer to the i40e_client struct
+ *
+ * Returns 0 on success or non-0 on error
+ **/
+int i40evf_unregister_client(struct i40e_client *client)
+{
+ int ret = 0;
+
+ /* When a unregister request comes through we would have to send
+ * a close for each of the client instances that were opened.
+ * client_release function is called to handle this.
+ */
+ i40evf_client_release(client);
+
+ if (vf_registered_client != client) {
+ pr_info("i40evf: Client %s has not been registered\n",
+ client->name);
+ ret = -ENODEV;
+ goto out;
+ }
+ vf_registered_client = NULL;
+ pr_info("i40evf: Unregistered client %s\n", client->name);
+out:
+ return ret;
+}
+EXPORT_SYMBOL(i40evf_unregister_client);
diff --git a/drivers/net/ethernet/intel/iavf/i40evf_client.h b/drivers/net/ethernet/intel/iavf/i40evf_client.h
new file mode 100644
index 000000000000..5585f362048a
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40evf_client.h
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#ifndef _I40EVF_CLIENT_H_
+#define _I40EVF_CLIENT_H_
+
+#define I40EVF_CLIENT_STR_LENGTH 10
+
+/* Client interface version should be updated anytime there is a change in the
+ * existing APIs or data structures.
+ */
+#define I40EVF_CLIENT_VERSION_MAJOR 0
+#define I40EVF_CLIENT_VERSION_MINOR 01
+#define I40EVF_CLIENT_VERSION_BUILD 00
+#define I40EVF_CLIENT_VERSION_STR \
+ __stringify(I40EVF_CLIENT_VERSION_MAJOR) "." \
+ __stringify(I40EVF_CLIENT_VERSION_MINOR) "." \
+ __stringify(I40EVF_CLIENT_VERSION_BUILD)
+
+struct i40e_client_version {
+ u8 major;
+ u8 minor;
+ u8 build;
+ u8 rsvd;
+};
+
+enum i40e_client_state {
+ __I40E_CLIENT_NULL,
+ __I40E_CLIENT_REGISTERED
+};
+
+enum i40e_client_instance_state {
+ __I40E_CLIENT_INSTANCE_NONE,
+ __I40E_CLIENT_INSTANCE_OPENED,
+};
+
+struct i40e_ops;
+struct i40e_client;
+
+/* HW does not define a type value for AEQ; only for RX/TX and CEQ.
+ * In order for us to keep the interface simple, SW will define a
+ * unique type value for AEQ.
+ */
+#define I40E_QUEUE_TYPE_PE_AEQ 0x80
+#define I40E_QUEUE_INVALID_IDX 0xFFFF
+
+struct i40e_qv_info {
+ u32 v_idx; /* msix_vector */
+ u16 ceq_idx;
+ u16 aeq_idx;
+ u8 itr_idx;
+};
+
+struct i40e_qvlist_info {
+ u32 num_vectors;
+ struct i40e_qv_info qv_info[1];
+};
+
+#define I40E_CLIENT_MSIX_ALL 0xFFFFFFFF
+
+/* set of LAN parameters useful for clients managed by LAN */
+
+/* Struct to hold per priority info */
+struct i40e_prio_qos_params {
+ u16 qs_handle; /* qs handle for prio */
+ u8 tc; /* TC mapped to prio */
+ u8 reserved;
+};
+
+#define I40E_CLIENT_MAX_USER_PRIORITY 8
+/* Struct to hold Client QoS */
+struct i40e_qos_params {
+ struct i40e_prio_qos_params prio_qos[I40E_CLIENT_MAX_USER_PRIORITY];
+};
+
+struct i40e_params {
+ struct i40e_qos_params qos;
+ u16 mtu;
+ u16 link_up; /* boolean */
+};
+
+/* Structure to hold LAN device info for a client device */
+struct i40e_info {
+ struct i40e_client_version version;
+ u8 lanmac[6];
+ struct net_device *netdev;
+ struct pci_dev *pcidev;
+ u8 __iomem *hw_addr;
+ u8 fid; /* function id, PF id or VF id */
+#define I40E_CLIENT_FTYPE_PF 0
+#define I40E_CLIENT_FTYPE_VF 1
+ u8 ftype; /* function type, PF or VF */
+ void *vf; /* cast to i40evf_adapter */
+
+ /* All L2 params that could change during the life span of the device
+ * and needs to be communicated to the client when they change
+ */
+ struct i40e_params params;
+ struct i40e_ops *ops;
+
+ u16 msix_count; /* number of msix vectors*/
+ /* Array down below will be dynamically allocated based on msix_count */
+ struct msix_entry *msix_entries;
+ u16 itr_index; /* Which ITR index the PE driver is suppose to use */
+};
+
+struct i40e_ops {
+ /* setup_q_vector_list enables queues with a particular vector */
+ int (*setup_qvlist)(struct i40e_info *ldev, struct i40e_client *client,
+ struct i40e_qvlist_info *qv_info);
+
+ u32 (*virtchnl_send)(struct i40e_info *ldev, struct i40e_client *client,
+ u8 *msg, u16 len);
+
+ /* If the PE Engine is unresponsive, RDMA driver can request a reset.*/
+ void (*request_reset)(struct i40e_info *ldev,
+ struct i40e_client *client);
+};
+
+struct i40e_client_ops {
+ /* Should be called from register_client() or whenever the driver is
+ * ready to create a specific client instance.
+ */
+ int (*open)(struct i40e_info *ldev, struct i40e_client *client);
+
+ /* Should be closed when netdev is unavailable or when unregister
+ * call comes in. If the close happens due to a reset, set the reset
+ * bit to true.
+ */
+ void (*close)(struct i40e_info *ldev, struct i40e_client *client,
+ bool reset);
+
+ /* called when some l2 managed parameters changes - mss */
+ void (*l2_param_change)(struct i40e_info *ldev,
+ struct i40e_client *client,
+ struct i40e_params *params);
+
+ /* called when a message is received from the PF */
+ int (*virtchnl_receive)(struct i40e_info *ldev,
+ struct i40e_client *client,
+ u8 *msg, u16 len);
+};
+
+/* Client device */
+struct i40e_client_instance {
+ struct list_head list;
+ struct i40e_info lan_info;
+ struct i40e_client *client;
+ unsigned long state;
+};
+
+struct i40e_client {
+ struct list_head list; /* list of registered clients */
+ char name[I40EVF_CLIENT_STR_LENGTH];
+ struct i40e_client_version version;
+ unsigned long state; /* client state */
+ atomic_t ref_cnt; /* Count of all the client devices of this kind */
+ u32 flags;
+#define I40E_CLIENT_FLAGS_LAUNCH_ON_PROBE BIT(0)
+#define I40E_TX_FLAGS_NOTIFY_OTHER_EVENTS BIT(2)
+ u8 type;
+#define I40E_CLIENT_IWARP 0
+ struct i40e_client_ops *ops; /* client ops provided by the client */
+};
+
+/* used by clients */
+int i40evf_register_client(struct i40e_client *client);
+int i40evf_unregister_client(struct i40e_client *client);
+#endif /* _I40EVF_CLIENT_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/i40evf_ethtool.c b/drivers/net/ethernet/intel/iavf/i40evf_ethtool.c
new file mode 100644
index 000000000000..69efe0aec76a
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40evf_ethtool.c
@@ -0,0 +1,820 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+/* ethtool support for i40evf */
+#include "i40evf.h"
+
+#include <linux/uaccess.h>
+
+struct i40evf_stats {
+ char stat_string[ETH_GSTRING_LEN];
+ int stat_offset;
+};
+
+#define I40EVF_STAT(_name, _stat) { \
+ .stat_string = _name, \
+ .stat_offset = offsetof(struct i40evf_adapter, _stat) \
+}
+
+/* All stats are u64, so we don't need to track the size of the field. */
+static const struct i40evf_stats i40evf_gstrings_stats[] = {
+ I40EVF_STAT("rx_bytes", current_stats.rx_bytes),
+ I40EVF_STAT("rx_unicast", current_stats.rx_unicast),
+ I40EVF_STAT("rx_multicast", current_stats.rx_multicast),
+ I40EVF_STAT("rx_broadcast", current_stats.rx_broadcast),
+ I40EVF_STAT("rx_discards", current_stats.rx_discards),
+ I40EVF_STAT("rx_unknown_protocol", current_stats.rx_unknown_protocol),
+ I40EVF_STAT("tx_bytes", current_stats.tx_bytes),
+ I40EVF_STAT("tx_unicast", current_stats.tx_unicast),
+ I40EVF_STAT("tx_multicast", current_stats.tx_multicast),
+ I40EVF_STAT("tx_broadcast", current_stats.tx_broadcast),
+ I40EVF_STAT("tx_discards", current_stats.tx_discards),
+ I40EVF_STAT("tx_errors", current_stats.tx_errors),
+};
+
+#define I40EVF_GLOBAL_STATS_LEN ARRAY_SIZE(i40evf_gstrings_stats)
+#define I40EVF_QUEUE_STATS_LEN(_dev) \
+ (((struct i40evf_adapter *)\
+ netdev_priv(_dev))->num_active_queues \
+ * 2 * (sizeof(struct i40e_queue_stats) / sizeof(u64)))
+#define I40EVF_STATS_LEN(_dev) \
+ (I40EVF_GLOBAL_STATS_LEN + I40EVF_QUEUE_STATS_LEN(_dev))
+
+/* For now we have one and only one private flag and it is only defined
+ * when we have support for the SKIP_CPU_SYNC DMA attribute. Instead
+ * of leaving all this code sitting around empty we will strip it unless
+ * our one private flag is actually available.
+ */
+struct i40evf_priv_flags {
+ char flag_string[ETH_GSTRING_LEN];
+ u32 flag;
+ bool read_only;
+};
+
+#define I40EVF_PRIV_FLAG(_name, _flag, _read_only) { \
+ .flag_string = _name, \
+ .flag = _flag, \
+ .read_only = _read_only, \
+}
+
+static const struct i40evf_priv_flags i40evf_gstrings_priv_flags[] = {
+ I40EVF_PRIV_FLAG("legacy-rx", I40EVF_FLAG_LEGACY_RX, 0),
+};
+
+#define I40EVF_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40evf_gstrings_priv_flags)
+
+/**
+ * i40evf_get_link_ksettings - Get Link Speed and Duplex settings
+ * @netdev: network interface device structure
+ * @cmd: ethtool command
+ *
+ * Reports speed/duplex settings. Because this is a VF, we don't know what
+ * kind of link we really have, so we fake it.
+ **/
+static int i40evf_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ ethtool_link_ksettings_zero_link_mode(cmd, supported);
+ cmd->base.autoneg = AUTONEG_DISABLE;
+ cmd->base.port = PORT_NONE;
+ /* Set speed and duplex */
+ switch (adapter->link_speed) {
+ case I40E_LINK_SPEED_40GB:
+ cmd->base.speed = SPEED_40000;
+ break;
+ case I40E_LINK_SPEED_25GB:
+#ifdef SPEED_25000
+ cmd->base.speed = SPEED_25000;
+#else
+ netdev_info(netdev,
+ "Speed is 25G, display not supported by this version of ethtool.\n");
+#endif
+ break;
+ case I40E_LINK_SPEED_20GB:
+ cmd->base.speed = SPEED_20000;
+ break;
+ case I40E_LINK_SPEED_10GB:
+ cmd->base.speed = SPEED_10000;
+ break;
+ case I40E_LINK_SPEED_1GB:
+ cmd->base.speed = SPEED_1000;
+ break;
+ case I40E_LINK_SPEED_100MB:
+ cmd->base.speed = SPEED_100;
+ break;
+ default:
+ break;
+ }
+ cmd->base.duplex = DUPLEX_FULL;
+
+ return 0;
+}
+
+/**
+ * i40evf_get_sset_count - Get length of string set
+ * @netdev: network interface device structure
+ * @sset: id of string set
+ *
+ * Reports size of string table. This driver only supports
+ * strings for statistics.
+ **/
+static int i40evf_get_sset_count(struct net_device *netdev, int sset)
+{
+ if (sset == ETH_SS_STATS)
+ return I40EVF_STATS_LEN(netdev);
+ else if (sset == ETH_SS_PRIV_FLAGS)
+ return I40EVF_PRIV_FLAGS_STR_LEN;
+ else
+ return -EINVAL;
+}
+
+/**
+ * i40evf_get_ethtool_stats - report device statistics
+ * @netdev: network interface device structure
+ * @stats: ethtool statistics structure
+ * @data: pointer to data buffer
+ *
+ * All statistics are added to the data buffer as an array of u64.
+ **/
+static void i40evf_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ unsigned int i, j;
+ char *p;
+
+ for (i = 0; i < I40EVF_GLOBAL_STATS_LEN; i++) {
+ p = (char *)adapter + i40evf_gstrings_stats[i].stat_offset;
+ data[i] = *(u64 *)p;
+ }
+ for (j = 0; j < adapter->num_active_queues; j++) {
+ data[i++] = adapter->tx_rings[j].stats.packets;
+ data[i++] = adapter->tx_rings[j].stats.bytes;
+ }
+ for (j = 0; j < adapter->num_active_queues; j++) {
+ data[i++] = adapter->rx_rings[j].stats.packets;
+ data[i++] = adapter->rx_rings[j].stats.bytes;
+ }
+}
+
+/**
+ * i40evf_get_strings - Get string set
+ * @netdev: network interface device structure
+ * @sset: id of string set
+ * @data: buffer for string data
+ *
+ * Builds stats string table.
+ **/
+static void i40evf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ u8 *p = data;
+ int i;
+
+ if (sset == ETH_SS_STATS) {
+ for (i = 0; i < (int)I40EVF_GLOBAL_STATS_LEN; i++) {
+ memcpy(p, i40evf_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < adapter->num_active_queues; i++) {
+ snprintf(p, ETH_GSTRING_LEN, "tx-%u.packets", i);
+ p += ETH_GSTRING_LEN;
+ snprintf(p, ETH_GSTRING_LEN, "tx-%u.bytes", i);
+ p += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < adapter->num_active_queues; i++) {
+ snprintf(p, ETH_GSTRING_LEN, "rx-%u.packets", i);
+ p += ETH_GSTRING_LEN;
+ snprintf(p, ETH_GSTRING_LEN, "rx-%u.bytes", i);
+ p += ETH_GSTRING_LEN;
+ }
+ } else if (sset == ETH_SS_PRIV_FLAGS) {
+ for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
+ snprintf(p, ETH_GSTRING_LEN, "%s",
+ i40evf_gstrings_priv_flags[i].flag_string);
+ p += ETH_GSTRING_LEN;
+ }
+ }
+}
+
+/**
+ * i40evf_get_priv_flags - report device private flags
+ * @netdev: network interface device structure
+ *
+ * The get string set count and the string set should be matched for each
+ * flag returned. Add new strings for each flag to the i40e_gstrings_priv_flags
+ * array.
+ *
+ * Returns a u32 bitmap of flags.
+ **/
+static u32 i40evf_get_priv_flags(struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ u32 i, ret_flags = 0;
+
+ for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
+ const struct i40evf_priv_flags *priv_flags;
+
+ priv_flags = &i40evf_gstrings_priv_flags[i];
+
+ if (priv_flags->flag & adapter->flags)
+ ret_flags |= BIT(i);
+ }
+
+ return ret_flags;
+}
+
+/**
+ * i40evf_set_priv_flags - set private flags
+ * @netdev: network interface device structure
+ * @flags: bit flags to be set
+ **/
+static int i40evf_set_priv_flags(struct net_device *netdev, u32 flags)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ u32 orig_flags, new_flags, changed_flags;
+ u32 i;
+
+ orig_flags = READ_ONCE(adapter->flags);
+ new_flags = orig_flags;
+
+ for (i = 0; i < I40EVF_PRIV_FLAGS_STR_LEN; i++) {
+ const struct i40evf_priv_flags *priv_flags;
+
+ priv_flags = &i40evf_gstrings_priv_flags[i];
+
+ if (flags & BIT(i))
+ new_flags |= priv_flags->flag;
+ else
+ new_flags &= ~(priv_flags->flag);
+
+ if (priv_flags->read_only &&
+ ((orig_flags ^ new_flags) & ~BIT(i)))
+ return -EOPNOTSUPP;
+ }
+
+ /* Before we finalize any flag changes, any checks which we need to
+ * perform to determine if the new flags will be supported should go
+ * here...
+ */
+
+ /* Compare and exchange the new flags into place. If we failed, that
+ * is if cmpxchg returns anything but the old value, this means
+ * something else must have modified the flags variable since we
+ * copied it. We'll just punt with an error and log something in the
+ * message buffer.
+ */
+ if (cmpxchg(&adapter->flags, orig_flags, new_flags) != orig_flags) {
+ dev_warn(&adapter->pdev->dev,
+ "Unable to update adapter->flags as it was modified by another thread...\n");
+ return -EAGAIN;
+ }
+
+ changed_flags = orig_flags ^ new_flags;
+
+ /* Process any additional changes needed as a result of flag changes.
+ * The changed_flags value reflects the list of bits that were changed
+ * in the code above.
+ */
+
+ /* issue a reset to force legacy-rx change to take effect */
+ if (changed_flags & I40EVF_FLAG_LEGACY_RX) {
+ if (netif_running(netdev)) {
+ adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
+ schedule_work(&adapter->reset_task);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * i40evf_get_msglevel - Get debug message level
+ * @netdev: network interface device structure
+ *
+ * Returns current debug message level.
+ **/
+static u32 i40evf_get_msglevel(struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ return adapter->msg_enable;
+}
+
+/**
+ * i40evf_set_msglevel - Set debug message level
+ * @netdev: network interface device structure
+ * @data: message level
+ *
+ * Set current debug message level. Higher values cause the driver to
+ * be noisier.
+ **/
+static void i40evf_set_msglevel(struct net_device *netdev, u32 data)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ if (I40E_DEBUG_USER & data)
+ adapter->hw.debug_mask = data;
+ adapter->msg_enable = data;
+}
+
+/**
+ * i40evf_get_drvinfo - Get driver info
+ * @netdev: network interface device structure
+ * @drvinfo: ethool driver info structure
+ *
+ * Returns information about the driver and device for display to the user.
+ **/
+static void i40evf_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ strlcpy(drvinfo->driver, i40evf_driver_name, 32);
+ strlcpy(drvinfo->version, i40evf_driver_version, 32);
+ strlcpy(drvinfo->fw_version, "N/A", 4);
+ strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+ drvinfo->n_priv_flags = I40EVF_PRIV_FLAGS_STR_LEN;
+}
+
+/**
+ * i40evf_get_ringparam - Get ring parameters
+ * @netdev: network interface device structure
+ * @ring: ethtool ringparam structure
+ *
+ * Returns current ring parameters. TX and RX rings are reported separately,
+ * but the number of rings is not reported.
+ **/
+static void i40evf_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ ring->rx_max_pending = I40EVF_MAX_RXD;
+ ring->tx_max_pending = I40EVF_MAX_TXD;
+ ring->rx_pending = adapter->rx_desc_count;
+ ring->tx_pending = adapter->tx_desc_count;
+}
+
+/**
+ * i40evf_set_ringparam - Set ring parameters
+ * @netdev: network interface device structure
+ * @ring: ethtool ringparam structure
+ *
+ * Sets ring parameters. TX and RX rings are controlled separately, but the
+ * number of rings is not specified, so all rings get the same settings.
+ **/
+static int i40evf_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ u32 new_rx_count, new_tx_count;
+
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ return -EINVAL;
+
+ new_tx_count = clamp_t(u32, ring->tx_pending,
+ I40EVF_MIN_TXD,
+ I40EVF_MAX_TXD);
+ new_tx_count = ALIGN(new_tx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
+
+ new_rx_count = clamp_t(u32, ring->rx_pending,
+ I40EVF_MIN_RXD,
+ I40EVF_MAX_RXD);
+ new_rx_count = ALIGN(new_rx_count, I40EVF_REQ_DESCRIPTOR_MULTIPLE);
+
+ /* if nothing to do return success */
+ if ((new_tx_count == adapter->tx_desc_count) &&
+ (new_rx_count == adapter->rx_desc_count))
+ return 0;
+
+ adapter->tx_desc_count = new_tx_count;
+ adapter->rx_desc_count = new_rx_count;
+
+ if (netif_running(netdev)) {
+ adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
+ schedule_work(&adapter->reset_task);
+ }
+
+ return 0;
+}
+
+/**
+ * __i40evf_get_coalesce - get per-queue coalesce settings
+ * @netdev: the netdev to check
+ * @ec: ethtool coalesce data structure
+ * @queue: which queue to pick
+ *
+ * Gets the per-queue settings for coalescence. Specifically Rx and Tx usecs
+ * are per queue. If queue is <0 then we default to queue 0 as the
+ * representative value.
+ **/
+static int __i40evf_get_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ec,
+ int queue)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ struct i40e_vsi *vsi = &adapter->vsi;
+ struct i40e_ring *rx_ring, *tx_ring;
+
+ ec->tx_max_coalesced_frames = vsi->work_limit;
+ ec->rx_max_coalesced_frames = vsi->work_limit;
+
+ /* Rx and Tx usecs per queue value. If user doesn't specify the
+ * queue, return queue 0's value to represent.
+ */
+ if (queue < 0)
+ queue = 0;
+ else if (queue >= adapter->num_active_queues)
+ return -EINVAL;
+
+ rx_ring = &adapter->rx_rings[queue];
+ tx_ring = &adapter->tx_rings[queue];
+
+ if (ITR_IS_DYNAMIC(rx_ring->itr_setting))
+ ec->use_adaptive_rx_coalesce = 1;
+
+ if (ITR_IS_DYNAMIC(tx_ring->itr_setting))
+ ec->use_adaptive_tx_coalesce = 1;
+
+ ec->rx_coalesce_usecs = rx_ring->itr_setting & ~I40E_ITR_DYNAMIC;
+ ec->tx_coalesce_usecs = tx_ring->itr_setting & ~I40E_ITR_DYNAMIC;
+
+ return 0;
+}
+
+/**
+ * i40evf_get_coalesce - Get interrupt coalescing settings
+ * @netdev: network interface device structure
+ * @ec: ethtool coalesce structure
+ *
+ * Returns current coalescing settings. This is referred to elsewhere in the
+ * driver as Interrupt Throttle Rate, as this is how the hardware describes
+ * this functionality. Note that if per-queue settings have been modified this
+ * only represents the settings of queue 0.
+ **/
+static int i40evf_get_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ec)
+{
+ return __i40evf_get_coalesce(netdev, ec, -1);
+}
+
+/**
+ * i40evf_get_per_queue_coalesce - get coalesce values for specific queue
+ * @netdev: netdev to read
+ * @ec: coalesce settings from ethtool
+ * @queue: the queue to read
+ *
+ * Read specific queue's coalesce settings.
+ **/
+static int i40evf_get_per_queue_coalesce(struct net_device *netdev,
+ u32 queue,
+ struct ethtool_coalesce *ec)
+{
+ return __i40evf_get_coalesce(netdev, ec, queue);
+}
+
+/**
+ * i40evf_set_itr_per_queue - set ITR values for specific queue
+ * @adapter: the VF adapter struct to set values for
+ * @ec: coalesce settings from ethtool
+ * @queue: the queue to modify
+ *
+ * Change the ITR settings for a specific queue.
+ **/
+static void i40evf_set_itr_per_queue(struct i40evf_adapter *adapter,
+ struct ethtool_coalesce *ec,
+ int queue)
+{
+ struct i40e_ring *rx_ring = &adapter->rx_rings[queue];
+ struct i40e_ring *tx_ring = &adapter->tx_rings[queue];
+ struct i40e_q_vector *q_vector;
+
+ rx_ring->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs);
+ tx_ring->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs);
+
+ rx_ring->itr_setting |= I40E_ITR_DYNAMIC;
+ if (!ec->use_adaptive_rx_coalesce)
+ rx_ring->itr_setting ^= I40E_ITR_DYNAMIC;
+
+ tx_ring->itr_setting |= I40E_ITR_DYNAMIC;
+ if (!ec->use_adaptive_tx_coalesce)
+ tx_ring->itr_setting ^= I40E_ITR_DYNAMIC;
+
+ q_vector = rx_ring->q_vector;
+ q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);
+
+ q_vector = tx_ring->q_vector;
+ q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);
+
+ /* The interrupt handler itself will take care of programming
+ * the Tx and Rx ITR values based on the values we have entered
+ * into the q_vector, no need to write the values now.
+ */
+}
+
+/**
+ * __i40evf_set_coalesce - set coalesce settings for particular queue
+ * @netdev: the netdev to change
+ * @ec: ethtool coalesce settings
+ * @queue: the queue to change
+ *
+ * Sets the coalesce settings for a particular queue.
+ **/
+static int __i40evf_set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ec,
+ int queue)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ struct i40e_vsi *vsi = &adapter->vsi;
+ int i;
+
+ if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
+ vsi->work_limit = ec->tx_max_coalesced_frames_irq;
+
+ if (ec->rx_coalesce_usecs == 0) {
+ if (ec->use_adaptive_rx_coalesce)
+ netif_info(adapter, drv, netdev, "rx-usecs=0, need to disable adaptive-rx for a complete disable\n");
+ } else if ((ec->rx_coalesce_usecs < I40E_MIN_ITR) ||
+ (ec->rx_coalesce_usecs > I40E_MAX_ITR)) {
+ netif_info(adapter, drv, netdev, "Invalid value, rx-usecs range is 0-8160\n");
+ return -EINVAL;
+ }
+
+ else
+ if (ec->tx_coalesce_usecs == 0) {
+ if (ec->use_adaptive_tx_coalesce)
+ netif_info(adapter, drv, netdev, "tx-usecs=0, need to disable adaptive-tx for a complete disable\n");
+ } else if ((ec->tx_coalesce_usecs < I40E_MIN_ITR) ||
+ (ec->tx_coalesce_usecs > I40E_MAX_ITR)) {
+ netif_info(adapter, drv, netdev, "Invalid value, tx-usecs range is 0-8160\n");
+ return -EINVAL;
+ }
+
+ /* Rx and Tx usecs has per queue value. If user doesn't specify the
+ * queue, apply to all queues.
+ */
+ if (queue < 0) {
+ for (i = 0; i < adapter->num_active_queues; i++)
+ i40evf_set_itr_per_queue(adapter, ec, i);
+ } else if (queue < adapter->num_active_queues) {
+ i40evf_set_itr_per_queue(adapter, ec, queue);
+ } else {
+ netif_info(adapter, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",
+ adapter->num_active_queues - 1);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * i40evf_set_coalesce - Set interrupt coalescing settings
+ * @netdev: network interface device structure
+ * @ec: ethtool coalesce structure
+ *
+ * Change current coalescing settings for every queue.
+ **/
+static int i40evf_set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ec)
+{
+ return __i40evf_set_coalesce(netdev, ec, -1);
+}
+
+/**
+ * i40evf_set_per_queue_coalesce - set specific queue's coalesce settings
+ * @netdev: the netdev to change
+ * @ec: ethtool's coalesce settings
+ * @queue: the queue to modify
+ *
+ * Modifies a specific queue's coalesce settings.
+ */
+static int i40evf_set_per_queue_coalesce(struct net_device *netdev,
+ u32 queue,
+ struct ethtool_coalesce *ec)
+{
+ return __i40evf_set_coalesce(netdev, ec, queue);
+}
+
+/**
+ * i40evf_get_rxnfc - command to get RX flow classification rules
+ * @netdev: network interface device structure
+ * @cmd: ethtool rxnfc command
+ * @rule_locs: pointer to store rule locations
+ *
+ * Returns Success if the command is supported.
+ **/
+static int i40evf_get_rxnfc(struct net_device *netdev,
+ struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = adapter->num_active_queues;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXFH:
+ netdev_info(netdev,
+ "RSS hash info is not available to vf, use pf.\n");
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+/**
+ * i40evf_get_channels: get the number of channels supported by the device
+ * @netdev: network interface device structure
+ * @ch: channel information structure
+ *
+ * For the purposes of our device, we only use combined channels, i.e. a tx/rx
+ * queue pair. Report one extra channel to match our "other" MSI-X vector.
+ **/
+static void i40evf_get_channels(struct net_device *netdev,
+ struct ethtool_channels *ch)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ /* Report maximum channels */
+ ch->max_combined = I40EVF_MAX_REQ_QUEUES;
+
+ ch->max_other = NONQ_VECS;
+ ch->other_count = NONQ_VECS;
+
+ ch->combined_count = adapter->num_active_queues;
+}
+
+/**
+ * i40evf_set_channels: set the new channel count
+ * @netdev: network interface device structure
+ * @ch: channel information structure
+ *
+ * Negotiate a new number of channels with the PF then do a reset. During
+ * reset we'll realloc queues and fix the RSS table. Returns 0 on success,
+ * negative on failure.
+ **/
+static int i40evf_set_channels(struct net_device *netdev,
+ struct ethtool_channels *ch)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ int num_req = ch->combined_count;
+
+ if (num_req != adapter->num_active_queues &&
+ !(adapter->vf_res->vf_cap_flags &
+ VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)) {
+ dev_info(&adapter->pdev->dev, "PF is not capable of queue negotiation.\n");
+ return -EINVAL;
+ }
+
+ if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
+ adapter->num_tc) {
+ dev_info(&adapter->pdev->dev, "Cannot set channels since ADq is enabled.\n");
+ return -EINVAL;
+ }
+
+ /* All of these should have already been checked by ethtool before this
+ * even gets to us, but just to be sure.
+ */
+ if (num_req <= 0 || num_req > I40EVF_MAX_REQ_QUEUES)
+ return -EINVAL;
+
+ if (ch->rx_count || ch->tx_count || ch->other_count != NONQ_VECS)
+ return -EINVAL;
+
+ adapter->num_req_queues = num_req;
+ return i40evf_request_queues(adapter, num_req);
+}
+
+/**
+ * i40evf_get_rxfh_key_size - get the RSS hash key size
+ * @netdev: network interface device structure
+ *
+ * Returns the table size.
+ **/
+static u32 i40evf_get_rxfh_key_size(struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ return adapter->rss_key_size;
+}
+
+/**
+ * i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size
+ * @netdev: network interface device structure
+ *
+ * Returns the table size.
+ **/
+static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ return adapter->rss_lut_size;
+}
+
+/**
+ * i40evf_get_rxfh - get the rx flow hash indirection table
+ * @netdev: network interface device structure
+ * @indir: indirection table
+ * @key: hash key
+ * @hfunc: hash function in use
+ *
+ * Reads the indirection table directly from the hardware. Always returns 0.
+ **/
+static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
+ u8 *hfunc)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ u16 i;
+
+ if (hfunc)
+ *hfunc = ETH_RSS_HASH_TOP;
+ if (!indir)
+ return 0;
+
+ memcpy(key, adapter->rss_key, adapter->rss_key_size);
+
+ /* Each 32 bits pointed by 'indir' is stored with a lut entry */
+ for (i = 0; i < adapter->rss_lut_size; i++)
+ indir[i] = (u32)adapter->rss_lut[i];
+
+ return 0;
+}
+
+/**
+ * i40evf_set_rxfh - set the rx flow hash indirection table
+ * @netdev: network interface device structure
+ * @indir: indirection table
+ * @key: hash key
+ * @hfunc: hash function to use
+ *
+ * Returns -EINVAL if the table specifies an inavlid queue id, otherwise
+ * returns 0 after programming the table.
+ **/
+static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
+ const u8 *key, const u8 hfunc)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ u16 i;
+
+ /* We do not allow change in unsupported parameters */
+ if (key ||
+ (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
+ return -EOPNOTSUPP;
+ if (!indir)
+ return 0;
+
+ if (key) {
+ memcpy(adapter->rss_key, key, adapter->rss_key_size);
+ }
+
+ /* Each 32 bits pointed by 'indir' is stored with a lut entry */
+ for (i = 0; i < adapter->rss_lut_size; i++)
+ adapter->rss_lut[i] = (u8)(indir[i]);
+
+ return i40evf_config_rss(adapter);
+}
+
+static const struct ethtool_ops i40evf_ethtool_ops = {
+ .get_drvinfo = i40evf_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_ringparam = i40evf_get_ringparam,
+ .set_ringparam = i40evf_set_ringparam,
+ .get_strings = i40evf_get_strings,
+ .get_ethtool_stats = i40evf_get_ethtool_stats,
+ .get_sset_count = i40evf_get_sset_count,
+ .get_priv_flags = i40evf_get_priv_flags,
+ .set_priv_flags = i40evf_set_priv_flags,
+ .get_msglevel = i40evf_get_msglevel,
+ .set_msglevel = i40evf_set_msglevel,
+ .get_coalesce = i40evf_get_coalesce,
+ .set_coalesce = i40evf_set_coalesce,
+ .get_per_queue_coalesce = i40evf_get_per_queue_coalesce,
+ .set_per_queue_coalesce = i40evf_set_per_queue_coalesce,
+ .get_rxnfc = i40evf_get_rxnfc,
+ .get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
+ .get_rxfh = i40evf_get_rxfh,
+ .set_rxfh = i40evf_set_rxfh,
+ .get_channels = i40evf_get_channels,
+ .set_channels = i40evf_set_channels,
+ .get_rxfh_key_size = i40evf_get_rxfh_key_size,
+ .get_link_ksettings = i40evf_get_link_ksettings,
+};
+
+/**
+ * i40evf_set_ethtool_ops - Initialize ethtool ops struct
+ * @netdev: network interface device structure
+ *
+ * Sets ethtool ops struct in our netdev so that ethtool can call
+ * our functions.
+ **/
+void i40evf_set_ethtool_ops(struct net_device *netdev)
+{
+ netdev->ethtool_ops = &i40evf_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/intel/iavf/i40evf_main.c b/drivers/net/ethernet/intel/iavf/i40evf_main.c
new file mode 100644
index 000000000000..60c2e5df5827
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40evf_main.c
@@ -0,0 +1,3990 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#include "i40evf.h"
+#include "i40e_prototype.h"
+#include "i40evf_client.h"
+/* All i40evf tracepoints are defined by the include below, which must
+ * be included exactly once across the whole kernel with
+ * CREATE_TRACE_POINTS defined
+ */
+#define CREATE_TRACE_POINTS
+#include "i40e_trace.h"
+
+static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter);
+static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter);
+static int i40evf_close(struct net_device *netdev);
+
+char i40evf_driver_name[] = "i40evf";
+static const char i40evf_driver_string[] =
+ "Intel(R) Ethernet Adaptive Virtual Function Network Driver";
+
+#define DRV_KERN "-k"
+
+#define DRV_VERSION_MAJOR 3
+#define DRV_VERSION_MINOR 2
+#define DRV_VERSION_BUILD 3
+#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
+ __stringify(DRV_VERSION_MINOR) "." \
+ __stringify(DRV_VERSION_BUILD) \
+ DRV_KERN
+const char i40evf_driver_version[] = DRV_VERSION;
+static const char i40evf_copyright[] =
+ "Copyright (c) 2013 - 2018 Intel Corporation.";
+
+/* i40evf_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ * Class, Class Mask, private data (not used) }
+ */
+static const struct pci_device_id i40evf_pci_tbl[] = {
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_VF), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_VF_HV), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_X722_VF), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_ADAPTIVE_VF), 0},
+ /* required last entry */
+ {0, }
+};
+
+MODULE_DEVICE_TABLE(pci, i40evf_pci_tbl);
+
+MODULE_ALIAS("i40evf");
+MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
+MODULE_DESCRIPTION("Intel(R) XL710 X710 Virtual Function Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static struct workqueue_struct *i40evf_wq;
+
+/**
+ * i40evf_allocate_dma_mem_d - OS specific memory alloc for shared code
+ * @hw: pointer to the HW structure
+ * @mem: ptr to mem struct to fill out
+ * @size: size of memory requested
+ * @alignment: what to align the allocation to
+ **/
+i40e_status i40evf_allocate_dma_mem_d(struct i40e_hw *hw,
+ struct i40e_dma_mem *mem,
+ u64 size, u32 alignment)
+{
+ struct i40evf_adapter *adapter = (struct i40evf_adapter *)hw->back;
+
+ if (!mem)
+ return I40E_ERR_PARAM;
+
+ mem->size = ALIGN(size, alignment);
+ mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size,
+ (dma_addr_t *)&mem->pa, GFP_KERNEL);
+ if (mem->va)
+ return 0;
+ else
+ return I40E_ERR_NO_MEMORY;
+}
+
+/**
+ * i40evf_free_dma_mem_d - OS specific memory free for shared code
+ * @hw: pointer to the HW structure
+ * @mem: ptr to mem struct to free
+ **/
+i40e_status i40evf_free_dma_mem_d(struct i40e_hw *hw, struct i40e_dma_mem *mem)
+{
+ struct i40evf_adapter *adapter = (struct i40evf_adapter *)hw->back;
+
+ if (!mem || !mem->va)
+ return I40E_ERR_PARAM;
+ dma_free_coherent(&adapter->pdev->dev, mem->size,
+ mem->va, (dma_addr_t)mem->pa);
+ return 0;
+}
+
+/**
+ * i40evf_allocate_virt_mem_d - OS specific memory alloc for shared code
+ * @hw: pointer to the HW structure
+ * @mem: ptr to mem struct to fill out
+ * @size: size of memory requested
+ **/
+i40e_status i40evf_allocate_virt_mem_d(struct i40e_hw *hw,
+ struct i40e_virt_mem *mem, u32 size)
+{
+ if (!mem)
+ return I40E_ERR_PARAM;
+
+ mem->size = size;
+ mem->va = kzalloc(size, GFP_KERNEL);
+
+ if (mem->va)
+ return 0;
+ else
+ return I40E_ERR_NO_MEMORY;
+}
+
+/**
+ * i40evf_free_virt_mem_d - OS specific memory free for shared code
+ * @hw: pointer to the HW structure
+ * @mem: ptr to mem struct to free
+ **/
+i40e_status i40evf_free_virt_mem_d(struct i40e_hw *hw,
+ struct i40e_virt_mem *mem)
+{
+ if (!mem)
+ return I40E_ERR_PARAM;
+
+ /* it's ok to kfree a NULL pointer */
+ kfree(mem->va);
+
+ return 0;
+}
+
+/**
+ * i40evf_debug_d - OS dependent version of debug printing
+ * @hw: pointer to the HW structure
+ * @mask: debug level mask
+ * @fmt_str: printf-type format description
+ **/
+void i40evf_debug_d(void *hw, u32 mask, char *fmt_str, ...)
+{
+ char buf[512];
+ va_list argptr;
+
+ if (!(mask & ((struct i40e_hw *)hw)->debug_mask))
+ return;
+
+ va_start(argptr, fmt_str);
+ vsnprintf(buf, sizeof(buf), fmt_str, argptr);
+ va_end(argptr);
+
+ /* the debug string is already formatted with a newline */
+ pr_info("%s", buf);
+}
+
+/**
+ * i40evf_schedule_reset - Set the flags and schedule a reset event
+ * @adapter: board private structure
+ **/
+void i40evf_schedule_reset(struct i40evf_adapter *adapter)
+{
+ if (!(adapter->flags &
+ (I40EVF_FLAG_RESET_PENDING | I40EVF_FLAG_RESET_NEEDED))) {
+ adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
+ schedule_work(&adapter->reset_task);
+ }
+}
+
+/**
+ * i40evf_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ **/
+static void i40evf_tx_timeout(struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ adapter->tx_timeout_count++;
+ i40evf_schedule_reset(adapter);
+}
+
+/**
+ * i40evf_misc_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+static void i40evf_misc_irq_disable(struct i40evf_adapter *adapter)
+{
+ struct i40e_hw *hw = &adapter->hw;
+
+ if (!adapter->msix_entries)
+ return;
+
+ wr32(hw, I40E_VFINT_DYN_CTL01, 0);
+
+ /* read flush */
+ rd32(hw, I40E_VFGEN_RSTAT);
+
+ synchronize_irq(adapter->msix_entries[0].vector);
+}
+
+/**
+ * i40evf_misc_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+static void i40evf_misc_irq_enable(struct i40evf_adapter *adapter)
+{
+ struct i40e_hw *hw = &adapter->hw;
+
+ wr32(hw, I40E_VFINT_DYN_CTL01, I40E_VFINT_DYN_CTL01_INTENA_MASK |
+ I40E_VFINT_DYN_CTL01_ITR_INDX_MASK);
+ wr32(hw, I40E_VFINT_ICR0_ENA1, I40E_VFINT_ICR0_ENA1_ADMINQ_MASK);
+
+ /* read flush */
+ rd32(hw, I40E_VFGEN_RSTAT);
+}
+
+/**
+ * i40evf_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+static void i40evf_irq_disable(struct i40evf_adapter *adapter)
+{
+ int i;
+ struct i40e_hw *hw = &adapter->hw;
+
+ if (!adapter->msix_entries)
+ return;
+
+ for (i = 1; i < adapter->num_msix_vectors; i++) {
+ wr32(hw, I40E_VFINT_DYN_CTLN1(i - 1), 0);
+ synchronize_irq(adapter->msix_entries[i].vector);
+ }
+ /* read flush */
+ rd32(hw, I40E_VFGEN_RSTAT);
+}
+
+/**
+ * i40evf_irq_enable_queues - Enable interrupt for specified queues
+ * @adapter: board private structure
+ * @mask: bitmap of queues to enable
+ **/
+void i40evf_irq_enable_queues(struct i40evf_adapter *adapter, u32 mask)
+{
+ struct i40e_hw *hw = &adapter->hw;
+ int i;
+
+ for (i = 1; i < adapter->num_msix_vectors; i++) {
+ if (mask & BIT(i - 1)) {
+ wr32(hw, I40E_VFINT_DYN_CTLN1(i - 1),
+ I40E_VFINT_DYN_CTLN1_INTENA_MASK |
+ I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK);
+ }
+ }
+}
+
+/**
+ * i40evf_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ * @flush: boolean value whether to run rd32()
+ **/
+void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush)
+{
+ struct i40e_hw *hw = &adapter->hw;
+
+ i40evf_misc_irq_enable(adapter);
+ i40evf_irq_enable_queues(adapter, ~0);
+
+ if (flush)
+ rd32(hw, I40E_VFGEN_RSTAT);
+}
+
+/**
+ * i40evf_msix_aq - Interrupt handler for vector 0
+ * @irq: interrupt number
+ * @data: pointer to netdev
+ **/
+static irqreturn_t i40evf_msix_aq(int irq, void *data)
+{
+ struct net_device *netdev = data;
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ struct i40e_hw *hw = &adapter->hw;
+
+ /* handle non-queue interrupts, these reads clear the registers */
+ rd32(hw, I40E_VFINT_ICR01);
+ rd32(hw, I40E_VFINT_ICR0_ENA1);
+
+ /* schedule work on the private workqueue */
+ schedule_work(&adapter->adminq_task);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * i40evf_msix_clean_rings - MSIX mode Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a q_vector
+ **/
+static irqreturn_t i40evf_msix_clean_rings(int irq, void *data)
+{
+ struct i40e_q_vector *q_vector = data;
+
+ if (!q_vector->tx.ring && !q_vector->rx.ring)
+ return IRQ_HANDLED;
+
+ napi_schedule_irqoff(&q_vector->napi);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * i40evf_map_vector_to_rxq - associate irqs with rx queues
+ * @adapter: board private structure
+ * @v_idx: interrupt number
+ * @r_idx: queue number
+ **/
+static void
+i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx)
+{
+ struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx];
+ struct i40e_ring *rx_ring = &adapter->rx_rings[r_idx];
+ struct i40e_hw *hw = &adapter->hw;
+
+ rx_ring->q_vector = q_vector;
+ rx_ring->next = q_vector->rx.ring;
+ rx_ring->vsi = &adapter->vsi;
+ q_vector->rx.ring = rx_ring;
+ q_vector->rx.count++;
+ q_vector->rx.next_update = jiffies + 1;
+ q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);
+ q_vector->ring_mask |= BIT(r_idx);
+ wr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, q_vector->reg_idx),
+ q_vector->rx.current_itr);
+ q_vector->rx.current_itr = q_vector->rx.target_itr;
+}
+
+/**
+ * i40evf_map_vector_to_txq - associate irqs with tx queues
+ * @adapter: board private structure
+ * @v_idx: interrupt number
+ * @t_idx: queue number
+ **/
+static void
+i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)
+{
+ struct i40e_q_vector *q_vector = &adapter->q_vectors[v_idx];
+ struct i40e_ring *tx_ring = &adapter->tx_rings[t_idx];
+ struct i40e_hw *hw = &adapter->hw;
+
+ tx_ring->q_vector = q_vector;
+ tx_ring->next = q_vector->tx.ring;
+ tx_ring->vsi = &adapter->vsi;
+ q_vector->tx.ring = tx_ring;
+ q_vector->tx.count++;
+ q_vector->tx.next_update = jiffies + 1;
+ q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);
+ q_vector->num_ringpairs++;
+ wr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, q_vector->reg_idx),
+ q_vector->tx.target_itr);
+ q_vector->tx.current_itr = q_vector->tx.target_itr;
+}
+
+/**
+ * i40evf_map_rings_to_vectors - Maps descriptor rings to vectors
+ * @adapter: board private structure to initialize
+ *
+ * This function maps descriptor rings to the queue-specific vectors
+ * we were allotted through the MSI-X enabling code. Ideally, we'd have
+ * one vector per ring/queue, but on a constrained vector budget, we
+ * group the rings as "efficiently" as possible. You would add new
+ * mapping configurations in here.
+ **/
+static void i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
+{
+ int rings_remaining = adapter->num_active_queues;
+ int ridx = 0, vidx = 0;
+ int q_vectors;
+
+ q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+ for (; ridx < rings_remaining; ridx++) {
+ i40evf_map_vector_to_rxq(adapter, vidx, ridx);
+ i40evf_map_vector_to_txq(adapter, vidx, ridx);
+
+ /* In the case where we have more queues than vectors, continue
+ * round-robin on vectors until all queues are mapped.
+ */
+ if (++vidx >= q_vectors)
+ vidx = 0;
+ }
+
+ adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
+}
+
+/**
+ * i40evf_irq_affinity_notify - Callback for affinity changes
+ * @notify: context as to what irq was changed
+ * @mask: the new affinity mask
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * so that we may register to receive changes to the irq affinity masks.
+ **/
+static void i40evf_irq_affinity_notify(struct irq_affinity_notify *notify,
+ const cpumask_t *mask)
+{
+ struct i40e_q_vector *q_vector =
+ container_of(notify, struct i40e_q_vector, affinity_notify);
+
+ cpumask_copy(&q_vector->affinity_mask, mask);
+}
+
+/**
+ * i40evf_irq_affinity_release - Callback for affinity notifier release
+ * @ref: internal core kernel usage
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * to inform the current notification subscriber that they will no longer
+ * receive notifications.
+ **/
+static void i40evf_irq_affinity_release(struct kref *ref) {}
+
+/**
+ * i40evf_request_traffic_irqs - Initialize MSI-X interrupts
+ * @adapter: board private structure
+ * @basename: device basename
+ *
+ * Allocates MSI-X vectors for tx and rx handling, and requests
+ * interrupts from the kernel.
+ **/
+static int
+i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename)
+{
+ unsigned int vector, q_vectors;
+ unsigned int rx_int_idx = 0, tx_int_idx = 0;
+ int irq_num, err;
+ int cpu;
+
+ i40evf_irq_disable(adapter);
+ /* Decrement for Other and TCP Timer vectors */
+ q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+ for (vector = 0; vector < q_vectors; vector++) {
+ struct i40e_q_vector *q_vector = &adapter->q_vectors[vector];
+ irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+
+ if (q_vector->tx.ring && q_vector->rx.ring) {
+ snprintf(q_vector->name, sizeof(q_vector->name),
+ "i40evf-%s-TxRx-%d", basename, rx_int_idx++);
+ tx_int_idx++;
+ } else if (q_vector->rx.ring) {
+ snprintf(q_vector->name, sizeof(q_vector->name),
+ "i40evf-%s-rx-%d", basename, rx_int_idx++);
+ } else if (q_vector->tx.ring) {
+ snprintf(q_vector->name, sizeof(q_vector->name),
+ "i40evf-%s-tx-%d", basename, tx_int_idx++);
+ } else {
+ /* skip this unused q_vector */
+ continue;
+ }
+ err = request_irq(irq_num,
+ i40evf_msix_clean_rings,
+ 0,
+ q_vector->name,
+ q_vector);
+ if (err) {
+ dev_info(&adapter->pdev->dev,
+ "Request_irq failed, error: %d\n", err);
+ goto free_queue_irqs;
+ }
+ /* register for affinity change notifications */
+ q_vector->affinity_notify.notify = i40evf_irq_affinity_notify;
+ q_vector->affinity_notify.release =
+ i40evf_irq_affinity_release;
+ irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
+ /* Spread the IRQ affinity hints across online CPUs. Note that
+ * get_cpu_mask returns a mask with a permanent lifetime so
+ * it's safe to use as a hint for irq_set_affinity_hint.
+ */
+ cpu = cpumask_local_spread(q_vector->v_idx, -1);
+ irq_set_affinity_hint(irq_num, get_cpu_mask(cpu));
+ }
+
+ return 0;
+
+free_queue_irqs:
+ while (vector) {
+ vector--;
+ irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+ irq_set_affinity_notifier(irq_num, NULL);
+ irq_set_affinity_hint(irq_num, NULL);
+ free_irq(irq_num, &adapter->q_vectors[vector]);
+ }
+ return err;
+}
+
+/**
+ * i40evf_request_misc_irq - Initialize MSI-X interrupts
+ * @adapter: board private structure
+ *
+ * Allocates MSI-X vector 0 and requests interrupts from the kernel. This
+ * vector is only for the admin queue, and stays active even when the netdev
+ * is closed.
+ **/
+static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err;
+
+ snprintf(adapter->misc_vector_name,
+ sizeof(adapter->misc_vector_name) - 1, "i40evf-%s:mbx",
+ dev_name(&adapter->pdev->dev));
+ err = request_irq(adapter->msix_entries[0].vector,
+ &i40evf_msix_aq, 0,
+ adapter->misc_vector_name, netdev);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "request_irq for %s failed: %d\n",
+ adapter->misc_vector_name, err);
+ free_irq(adapter->msix_entries[0].vector, netdev);
+ }
+ return err;
+}
+
+/**
+ * i40evf_free_traffic_irqs - Free MSI-X interrupts
+ * @adapter: board private structure
+ *
+ * Frees all MSI-X vectors other than 0.
+ **/
+static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter)
+{
+ int vector, irq_num, q_vectors;
+
+ if (!adapter->msix_entries)
+ return;
+
+ q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+ for (vector = 0; vector < q_vectors; vector++) {
+ irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+ irq_set_affinity_notifier(irq_num, NULL);
+ irq_set_affinity_hint(irq_num, NULL);
+ free_irq(irq_num, &adapter->q_vectors[vector]);
+ }
+}
+
+/**
+ * i40evf_free_misc_irq - Free MSI-X miscellaneous vector
+ * @adapter: board private structure
+ *
+ * Frees MSI-X vector 0.
+ **/
+static void i40evf_free_misc_irq(struct i40evf_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ if (!adapter->msix_entries)
+ return;
+
+ free_irq(adapter->msix_entries[0].vector, netdev);
+}
+
+/**
+ * i40evf_configure_tx - Configure Transmit Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+static void i40evf_configure_tx(struct i40evf_adapter *adapter)
+{
+ struct i40e_hw *hw = &adapter->hw;
+ int i;
+
+ for (i = 0; i < adapter->num_active_queues; i++)
+ adapter->tx_rings[i].tail = hw->hw_addr + I40E_QTX_TAIL1(i);
+}
+
+/**
+ * i40evf_configure_rx - Configure Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+static void i40evf_configure_rx(struct i40evf_adapter *adapter)
+{
+ unsigned int rx_buf_len = I40E_RXBUFFER_2048;
+ struct i40e_hw *hw = &adapter->hw;
+ int i;
+
+ /* Legacy Rx will always default to a 2048 buffer size. */
+#if (PAGE_SIZE < 8192)
+ if (!(adapter->flags & I40EVF_FLAG_LEGACY_RX)) {
+ struct net_device *netdev = adapter->netdev;
+
+ /* For jumbo frames on systems with 4K pages we have to use
+ * an order 1 page, so we might as well increase the size
+ * of our Rx buffer to make better use of the available space
+ */
+ rx_buf_len = I40E_RXBUFFER_3072;
+
+ /* We use a 1536 buffer size for configurations with
+ * standard Ethernet mtu. On x86 this gives us enough room
+ * for shared info and 192 bytes of padding.
+ */
+ if (!I40E_2K_TOO_SMALL_WITH_PADDING &&
+ (netdev->mtu <= ETH_DATA_LEN))
+ rx_buf_len = I40E_RXBUFFER_1536 - NET_IP_ALIGN;
+ }
+#endif
+
+ for (i = 0; i < adapter->num_active_queues; i++) {
+ adapter->rx_rings[i].tail = hw->hw_addr + I40E_QRX_TAIL1(i);
+ adapter->rx_rings[i].rx_buf_len = rx_buf_len;
+
+ if (adapter->flags & I40EVF_FLAG_LEGACY_RX)
+ clear_ring_build_skb_enabled(&adapter->rx_rings[i]);
+ else
+ set_ring_build_skb_enabled(&adapter->rx_rings[i]);
+ }
+}
+
+/**
+ * i40evf_find_vlan - Search filter list for specific vlan filter
+ * @adapter: board private structure
+ * @vlan: vlan tag
+ *
+ * Returns ptr to the filter object or NULL. Must be called while holding the
+ * mac_vlan_list_lock.
+ **/
+static struct
+i40evf_vlan_filter *i40evf_find_vlan(struct i40evf_adapter *adapter, u16 vlan)
+{
+ struct i40evf_vlan_filter *f;
+
+ list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+ if (vlan == f->vlan)
+ return f;
+ }
+ return NULL;
+}
+
+/**
+ * i40evf_add_vlan - Add a vlan filter to the list
+ * @adapter: board private structure
+ * @vlan: VLAN tag
+ *
+ * Returns ptr to the filter object or NULL when no memory available.
+ **/
+static struct
+i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan)
+{
+ struct i40evf_vlan_filter *f = NULL;
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ f = i40evf_find_vlan(adapter, vlan);
+ if (!f) {
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
+ if (!f)
+ goto clearout;
+
+ f->vlan = vlan;
+
+ INIT_LIST_HEAD(&f->list);
+ list_add(&f->list, &adapter->vlan_filter_list);
+ f->add = true;
+ adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+ }
+
+clearout:
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return f;
+}
+
+/**
+ * i40evf_del_vlan - Remove a vlan filter from the list
+ * @adapter: board private structure
+ * @vlan: VLAN tag
+ **/
+static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan)
+{
+ struct i40evf_vlan_filter *f;
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ f = i40evf_find_vlan(adapter, vlan);
+ if (f) {
+ f->remove = true;
+ adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+ }
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+}
+
+/**
+ * i40evf_vlan_rx_add_vid - Add a VLAN filter to a device
+ * @netdev: network device struct
+ * @proto: unused protocol data
+ * @vid: VLAN tag
+ **/
+static int i40evf_vlan_rx_add_vid(struct net_device *netdev,
+ __always_unused __be16 proto, u16 vid)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ if (!VLAN_ALLOWED(adapter))
+ return -EIO;
+ if (i40evf_add_vlan(adapter, vid) == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * i40evf_vlan_rx_kill_vid - Remove a VLAN filter from a device
+ * @netdev: network device struct
+ * @proto: unused protocol data
+ * @vid: VLAN tag
+ **/
+static int i40evf_vlan_rx_kill_vid(struct net_device *netdev,
+ __always_unused __be16 proto, u16 vid)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ if (VLAN_ALLOWED(adapter)) {
+ i40evf_del_vlan(adapter, vid);
+ return 0;
+ }
+ return -EIO;
+}
+
+/**
+ * i40evf_find_filter - Search filter list for specific mac filter
+ * @adapter: board private structure
+ * @macaddr: the MAC address
+ *
+ * Returns ptr to the filter object or NULL. Must be called while holding the
+ * mac_vlan_list_lock.
+ **/
+static struct
+i40evf_mac_filter *i40evf_find_filter(struct i40evf_adapter *adapter,
+ const u8 *macaddr)
+{
+ struct i40evf_mac_filter *f;
+
+ if (!macaddr)
+ return NULL;
+
+ list_for_each_entry(f, &adapter->mac_filter_list, list) {
+ if (ether_addr_equal(macaddr, f->macaddr))
+ return f;
+ }
+ return NULL;
+}
+
+/**
+ * i40e_add_filter - Add a mac filter to the filter list
+ * @adapter: board private structure
+ * @macaddr: the MAC address
+ *
+ * Returns ptr to the filter object or NULL when no memory available.
+ **/
+static struct
+i40evf_mac_filter *i40evf_add_filter(struct i40evf_adapter *adapter,
+ const u8 *macaddr)
+{
+ struct i40evf_mac_filter *f;
+
+ if (!macaddr)
+ return NULL;
+
+ f = i40evf_find_filter(adapter, macaddr);
+ if (!f) {
+ f = kzalloc(sizeof(*f), GFP_ATOMIC);
+ if (!f)
+ return f;
+
+ ether_addr_copy(f->macaddr, macaddr);
+
+ list_add_tail(&f->list, &adapter->mac_filter_list);
+ f->add = true;
+ adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+ } else {
+ f->remove = false;
+ }
+
+ return f;
+}
+
+/**
+ * i40evf_set_mac - NDO callback to set port mac address
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int i40evf_set_mac(struct net_device *netdev, void *p)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ struct i40e_hw *hw = &adapter->hw;
+ struct i40evf_mac_filter *f;
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
+ return 0;
+
+ if (adapter->flags & I40EVF_FLAG_ADDR_SET_BY_PF)
+ return -EPERM;
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ f = i40evf_find_filter(adapter, hw->mac.addr);
+ if (f) {
+ f->remove = true;
+ adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+ }
+
+ f = i40evf_add_filter(adapter, addr->sa_data);
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ if (f) {
+ ether_addr_copy(hw->mac.addr, addr->sa_data);
+ ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
+ }
+
+ return (f == NULL) ? -ENOMEM : 0;
+}
+
+/**
+ * i40evf_addr_sync - Callback for dev_(mc|uc)_sync to add address
+ * @netdev: the netdevice
+ * @addr: address to add
+ *
+ * Called by __dev_(mc|uc)_sync when an address needs to be added. We call
+ * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
+ */
+static int i40evf_addr_sync(struct net_device *netdev, const u8 *addr)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ if (i40evf_add_filter(adapter, addr))
+ return 0;
+ else
+ return -ENOMEM;
+}
+
+/**
+ * i40evf_addr_unsync - Callback for dev_(mc|uc)_sync to remove address
+ * @netdev: the netdevice
+ * @addr: address to add
+ *
+ * Called by __dev_(mc|uc)_sync when an address needs to be removed. We call
+ * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
+ */
+static int i40evf_addr_unsync(struct net_device *netdev, const u8 *addr)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ struct i40evf_mac_filter *f;
+
+ /* Under some circumstances, we might receive a request to delete
+ * our own device address from our uc list. Because we store the
+ * device address in the VSI's MAC/VLAN filter list, we need to ignore
+ * such requests and not delete our device address from this list.
+ */
+ if (ether_addr_equal(addr, netdev->dev_addr))
+ return 0;
+
+ f = i40evf_find_filter(adapter, addr);
+ if (f) {
+ f->remove = true;
+ adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+ }
+ return 0;
+}
+
+/**
+ * i40evf_set_rx_mode - NDO callback to set the netdev filters
+ * @netdev: network interface device structure
+ **/
+static void i40evf_set_rx_mode(struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+ __dev_uc_sync(netdev, i40evf_addr_sync, i40evf_addr_unsync);
+ __dev_mc_sync(netdev, i40evf_addr_sync, i40evf_addr_unsync);
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ if (netdev->flags & IFF_PROMISC &&
+ !(adapter->flags & I40EVF_FLAG_PROMISC_ON))
+ adapter->aq_required |= I40EVF_FLAG_AQ_REQUEST_PROMISC;
+ else if (!(netdev->flags & IFF_PROMISC) &&
+ adapter->flags & I40EVF_FLAG_PROMISC_ON)
+ adapter->aq_required |= I40EVF_FLAG_AQ_RELEASE_PROMISC;
+
+ if (netdev->flags & IFF_ALLMULTI &&
+ !(adapter->flags & I40EVF_FLAG_ALLMULTI_ON))
+ adapter->aq_required |= I40EVF_FLAG_AQ_REQUEST_ALLMULTI;
+ else if (!(netdev->flags & IFF_ALLMULTI) &&
+ adapter->flags & I40EVF_FLAG_ALLMULTI_ON)
+ adapter->aq_required |= I40EVF_FLAG_AQ_RELEASE_ALLMULTI;
+}
+
+/**
+ * i40evf_napi_enable_all - enable NAPI on all queue vectors
+ * @adapter: board private structure
+ **/
+static void i40evf_napi_enable_all(struct i40evf_adapter *adapter)
+{
+ int q_idx;
+ struct i40e_q_vector *q_vector;
+ int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+ for (q_idx = 0; q_idx < q_vectors; q_idx++) {
+ struct napi_struct *napi;
+
+ q_vector = &adapter->q_vectors[q_idx];
+ napi = &q_vector->napi;
+ napi_enable(napi);
+ }
+}
+
+/**
+ * i40evf_napi_disable_all - disable NAPI on all queue vectors
+ * @adapter: board private structure
+ **/
+static void i40evf_napi_disable_all(struct i40evf_adapter *adapter)
+{
+ int q_idx;
+ struct i40e_q_vector *q_vector;
+ int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+ for (q_idx = 0; q_idx < q_vectors; q_idx++) {
+ q_vector = &adapter->q_vectors[q_idx];
+ napi_disable(&q_vector->napi);
+ }
+}
+
+/**
+ * i40evf_configure - set up transmit and receive data structures
+ * @adapter: board private structure
+ **/
+static void i40evf_configure(struct i40evf_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int i;
+
+ i40evf_set_rx_mode(netdev);
+
+ i40evf_configure_tx(adapter);
+ i40evf_configure_rx(adapter);
+ adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
+
+ for (i = 0; i < adapter->num_active_queues; i++) {
+ struct i40e_ring *ring = &adapter->rx_rings[i];
+
+ i40evf_alloc_rx_buffers(ring, I40E_DESC_UNUSED(ring));
+ }
+}
+
+/**
+ * i40evf_up_complete - Finish the last steps of bringing up a connection
+ * @adapter: board private structure
+ *
+ * Expects to be called while holding the __I40EVF_IN_CRITICAL_TASK bit lock.
+ **/
+static void i40evf_up_complete(struct i40evf_adapter *adapter)
+{
+ adapter->state = __I40EVF_RUNNING;
+ clear_bit(__I40E_VSI_DOWN, adapter->vsi.state);
+
+ i40evf_napi_enable_all(adapter);
+
+ adapter->aq_required |= I40EVF_FLAG_AQ_ENABLE_QUEUES;
+ if (CLIENT_ENABLED(adapter))
+ adapter->flags |= I40EVF_FLAG_CLIENT_NEEDS_OPEN;
+ mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
+}
+
+/**
+ * i40e_down - Shutdown the connection processing
+ * @adapter: board private structure
+ *
+ * Expects to be called while holding the __I40EVF_IN_CRITICAL_TASK bit lock.
+ **/
+void i40evf_down(struct i40evf_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct i40evf_vlan_filter *vlf;
+ struct i40evf_mac_filter *f;
+ struct i40evf_cloud_filter *cf;
+
+ if (adapter->state <= __I40EVF_DOWN_PENDING)
+ return;
+
+ netif_carrier_off(netdev);
+ netif_tx_disable(netdev);
+ adapter->link_up = false;
+ i40evf_napi_disable_all(adapter);
+ i40evf_irq_disable(adapter);
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ /* clear the sync flag on all filters */
+ __dev_uc_unsync(adapter->netdev, NULL);
+ __dev_mc_unsync(adapter->netdev, NULL);
+
+ /* remove all MAC filters */
+ list_for_each_entry(f, &adapter->mac_filter_list, list) {
+ f->remove = true;
+ }
+
+ /* remove all VLAN filters */
+ list_for_each_entry(vlf, &adapter->vlan_filter_list, list) {
+ vlf->remove = true;
+ }
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ /* remove all cloud filters */
+ spin_lock_bh(&adapter->cloud_filter_list_lock);
+ list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
+ cf->del = true;
+ }
+ spin_unlock_bh(&adapter->cloud_filter_list_lock);
+
+ if (!(adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) &&
+ adapter->state != __I40EVF_RESETTING) {
+ /* cancel any current operation */
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+ /* Schedule operations to close down the HW. Don't wait
+ * here for this to complete. The watchdog is still running
+ * and it will take care of this.
+ */
+ adapter->aq_required = I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+ adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+ adapter->aq_required |= I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;
+ adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
+ }
+
+ mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
+}
+
+/**
+ * i40evf_acquire_msix_vectors - Setup the MSIX capability
+ * @adapter: board private structure
+ * @vectors: number of vectors to request
+ *
+ * Work with the OS to set up the MSIX vectors needed.
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int
+i40evf_acquire_msix_vectors(struct i40evf_adapter *adapter, int vectors)
+{
+ int err, vector_threshold;
+
+ /* We'll want at least 3 (vector_threshold):
+ * 0) Other (Admin Queue and link, mostly)
+ * 1) TxQ[0] Cleanup
+ * 2) RxQ[0] Cleanup
+ */
+ vector_threshold = MIN_MSIX_COUNT;
+
+ /* The more we get, the more we will assign to Tx/Rx Cleanup
+ * for the separate queues...where Rx Cleanup >= Tx Cleanup.
+ * Right now, we simply care about how many we'll get; we'll
+ * set them up later while requesting irq's.
+ */
+ err = pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+ vector_threshold, vectors);
+ if (err < 0) {
+ dev_err(&adapter->pdev->dev, "Unable to allocate MSI-X interrupts\n");
+ kfree(adapter->msix_entries);
+ adapter->msix_entries = NULL;
+ return err;
+ }
+
+ /* Adjust for only the vectors we'll use, which is minimum
+ * of max_msix_q_vectors + NONQ_VECS, or the number of
+ * vectors we were allocated.
+ */
+ adapter->num_msix_vectors = err;
+ return 0;
+}
+
+/**
+ * i40evf_free_queues - Free memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ * Free all of the memory associated with queue pairs.
+ **/
+static void i40evf_free_queues(struct i40evf_adapter *adapter)
+{
+ if (!adapter->vsi_res)
+ return;
+ adapter->num_active_queues = 0;
+ kfree(adapter->tx_rings);
+ adapter->tx_rings = NULL;
+ kfree(adapter->rx_rings);
+ adapter->rx_rings = NULL;
+}
+
+/**
+ * i40evf_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one ring per queue at run-time since we don't know the
+ * number of queues at compile-time. The polling_netdev array is
+ * intended for Multiqueue, but should work fine with a single queue.
+ **/
+static int i40evf_alloc_queues(struct i40evf_adapter *adapter)
+{
+ int i, num_active_queues;
+
+ /* If we're in reset reallocating queues we don't actually know yet for
+ * certain the PF gave us the number of queues we asked for but we'll
+ * assume it did. Once basic reset is finished we'll confirm once we
+ * start negotiating config with PF.
+ */
+ if (adapter->num_req_queues)
+ num_active_queues = adapter->num_req_queues;
+ else if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
+ adapter->num_tc)
+ num_active_queues = adapter->ch_config.total_qps;
+ else
+ num_active_queues = min_t(int,
+ adapter->vsi_res->num_queue_pairs,
+ (int)(num_online_cpus()));
+
+
+ adapter->tx_rings = kcalloc(num_active_queues,
+ sizeof(struct i40e_ring), GFP_KERNEL);
+ if (!adapter->tx_rings)
+ goto err_out;
+ adapter->rx_rings = kcalloc(num_active_queues,
+ sizeof(struct i40e_ring), GFP_KERNEL);
+ if (!adapter->rx_rings)
+ goto err_out;
+
+ for (i = 0; i < num_active_queues; i++) {
+ struct i40e_ring *tx_ring;
+ struct i40e_ring *rx_ring;
+
+ tx_ring = &adapter->tx_rings[i];
+
+ tx_ring->queue_index = i;
+ tx_ring->netdev = adapter->netdev;
+ tx_ring->dev = &adapter->pdev->dev;
+ tx_ring->count = adapter->tx_desc_count;
+ tx_ring->itr_setting = I40E_ITR_TX_DEF;
+ if (adapter->flags & I40EVF_FLAG_WB_ON_ITR_CAPABLE)
+ tx_ring->flags |= I40E_TXR_FLAGS_WB_ON_ITR;
+
+ rx_ring = &adapter->rx_rings[i];
+ rx_ring->queue_index = i;
+ rx_ring->netdev = adapter->netdev;
+ rx_ring->dev = &adapter->pdev->dev;
+ rx_ring->count = adapter->rx_desc_count;
+ rx_ring->itr_setting = I40E_ITR_RX_DEF;
+ }
+
+ adapter->num_active_queues = num_active_queues;
+
+ return 0;
+
+err_out:
+ i40evf_free_queues(adapter);
+ return -ENOMEM;
+}
+
+/**
+ * i40evf_set_interrupt_capability - set MSI-X or FAIL if not supported
+ * @adapter: board private structure to initialize
+ *
+ * Attempt to configure the interrupts using the best available
+ * capabilities of the hardware and the kernel.
+ **/
+static int i40evf_set_interrupt_capability(struct i40evf_adapter *adapter)
+{
+ int vector, v_budget;
+ int pairs = 0;
+ int err = 0;
+
+ if (!adapter->vsi_res) {
+ err = -EIO;
+ goto out;
+ }
+ pairs = adapter->num_active_queues;
+
+ /* It's easy to be greedy for MSI-X vectors, but it really doesn't do
+ * us much good if we have more vectors than CPUs. However, we already
+ * limit the total number of queues by the number of CPUs so we do not
+ * need any further limiting here.
+ */
+ v_budget = min_t(int, pairs + NONQ_VECS,
+ (int)adapter->vf_res->max_vectors);
+
+ adapter->msix_entries = kcalloc(v_budget,
+ sizeof(struct msix_entry), GFP_KERNEL);
+ if (!adapter->msix_entries) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ for (vector = 0; vector < v_budget; vector++)
+ adapter->msix_entries[vector].entry = vector;
+
+ err = i40evf_acquire_msix_vectors(adapter, v_budget);
+
+out:
+ netif_set_real_num_rx_queues(adapter->netdev, pairs);
+ netif_set_real_num_tx_queues(adapter->netdev, pairs);
+ return err;
+}
+
+/**
+ * i40e_config_rss_aq - Configure RSS keys and lut by using AQ commands
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ **/
+static int i40evf_config_rss_aq(struct i40evf_adapter *adapter)
+{
+ struct i40e_aqc_get_set_rss_key_data *rss_key =
+ (struct i40e_aqc_get_set_rss_key_data *)adapter->rss_key;
+ struct i40e_hw *hw = &adapter->hw;
+ int ret = 0;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot configure RSS, command %d pending\n",
+ adapter->current_op);
+ return -EBUSY;
+ }
+
+ ret = i40evf_aq_set_rss_key(hw, adapter->vsi.id, rss_key);
+ if (ret) {
+ dev_err(&adapter->pdev->dev, "Cannot set RSS key, err %s aq_err %s\n",
+ i40evf_stat_str(hw, ret),
+ i40evf_aq_str(hw, hw->aq.asq_last_status));
+ return ret;
+
+ }
+
+ ret = i40evf_aq_set_rss_lut(hw, adapter->vsi.id, false,
+ adapter->rss_lut, adapter->rss_lut_size);
+ if (ret) {
+ dev_err(&adapter->pdev->dev, "Cannot set RSS lut, err %s aq_err %s\n",
+ i40evf_stat_str(hw, ret),
+ i40evf_aq_str(hw, hw->aq.asq_last_status));
+ }
+
+ return ret;
+
+}
+
+/**
+ * i40evf_config_rss_reg - Configure RSS keys and lut by writing registers
+ * @adapter: board private structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int i40evf_config_rss_reg(struct i40evf_adapter *adapter)
+{
+ struct i40e_hw *hw = &adapter->hw;
+ u32 *dw;
+ u16 i;
+
+ dw = (u32 *)adapter->rss_key;
+ for (i = 0; i <= adapter->rss_key_size / 4; i++)
+ wr32(hw, I40E_VFQF_HKEY(i), dw[i]);
+
+ dw = (u32 *)adapter->rss_lut;
+ for (i = 0; i <= adapter->rss_lut_size / 4; i++)
+ wr32(hw, I40E_VFQF_HLUT(i), dw[i]);
+
+ i40e_flush(hw);
+
+ return 0;
+}
+
+/**
+ * i40evf_config_rss - Configure RSS keys and lut
+ * @adapter: board private structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+int i40evf_config_rss(struct i40evf_adapter *adapter)
+{
+
+ if (RSS_PF(adapter)) {
+ adapter->aq_required |= I40EVF_FLAG_AQ_SET_RSS_LUT |
+ I40EVF_FLAG_AQ_SET_RSS_KEY;
+ return 0;
+ } else if (RSS_AQ(adapter)) {
+ return i40evf_config_rss_aq(adapter);
+ } else {
+ return i40evf_config_rss_reg(adapter);
+ }
+}
+
+/**
+ * i40evf_fill_rss_lut - Fill the lut with default values
+ * @adapter: board private structure
+ **/
+static void i40evf_fill_rss_lut(struct i40evf_adapter *adapter)
+{
+ u16 i;
+
+ for (i = 0; i < adapter->rss_lut_size; i++)
+ adapter->rss_lut[i] = i % adapter->num_active_queues;
+}
+
+/**
+ * i40evf_init_rss - Prepare for RSS
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ **/
+static int i40evf_init_rss(struct i40evf_adapter *adapter)
+{
+ struct i40e_hw *hw = &adapter->hw;
+ int ret;
+
+ if (!RSS_PF(adapter)) {
+ /* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */
+ if (adapter->vf_res->vf_cap_flags &
+ VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
+ adapter->hena = I40E_DEFAULT_RSS_HENA_EXPANDED;
+ else
+ adapter->hena = I40E_DEFAULT_RSS_HENA;
+
+ wr32(hw, I40E_VFQF_HENA(0), (u32)adapter->hena);
+ wr32(hw, I40E_VFQF_HENA(1), (u32)(adapter->hena >> 32));
+ }
+
+ i40evf_fill_rss_lut(adapter);
+
+ netdev_rss_key_fill((void *)adapter->rss_key, adapter->rss_key_size);
+ ret = i40evf_config_rss(adapter);
+
+ return ret;
+}
+
+/**
+ * i40evf_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one q_vector per queue interrupt. If allocation fails we
+ * return -ENOMEM.
+ **/
+static int i40evf_alloc_q_vectors(struct i40evf_adapter *adapter)
+{
+ int q_idx = 0, num_q_vectors;
+ struct i40e_q_vector *q_vector;
+
+ num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+ adapter->q_vectors = kcalloc(num_q_vectors, sizeof(*q_vector),
+ GFP_KERNEL);
+ if (!adapter->q_vectors)
+ return -ENOMEM;
+
+ for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
+ q_vector = &adapter->q_vectors[q_idx];
+ q_vector->adapter = adapter;
+ q_vector->vsi = &adapter->vsi;
+ q_vector->v_idx = q_idx;
+ q_vector->reg_idx = q_idx;
+ cpumask_copy(&q_vector->affinity_mask, cpu_possible_mask);
+ netif_napi_add(adapter->netdev, &q_vector->napi,
+ i40evf_napi_poll, NAPI_POLL_WEIGHT);
+ }
+
+ return 0;
+}
+
+/**
+ * i40evf_free_q_vectors - Free memory allocated for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * This function frees the memory allocated to the q_vectors. In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void i40evf_free_q_vectors(struct i40evf_adapter *adapter)
+{
+ int q_idx, num_q_vectors;
+ int napi_vectors;
+
+ if (!adapter->q_vectors)
+ return;
+
+ num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+ napi_vectors = adapter->num_active_queues;
+
+ for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
+ struct i40e_q_vector *q_vector = &adapter->q_vectors[q_idx];
+ if (q_idx < napi_vectors)
+ netif_napi_del(&q_vector->napi);
+ }
+ kfree(adapter->q_vectors);
+ adapter->q_vectors = NULL;
+}
+
+/**
+ * i40evf_reset_interrupt_capability - Reset MSIX setup
+ * @adapter: board private structure
+ *
+ **/
+void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter)
+{
+ if (!adapter->msix_entries)
+ return;
+
+ pci_disable_msix(adapter->pdev);
+ kfree(adapter->msix_entries);
+ adapter->msix_entries = NULL;
+}
+
+/**
+ * i40evf_init_interrupt_scheme - Determine if MSIX is supported and init
+ * @adapter: board private structure to initialize
+ *
+ **/
+int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter)
+{
+ int err;
+
+ err = i40evf_alloc_queues(adapter);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Unable to allocate memory for queues\n");
+ goto err_alloc_queues;
+ }
+
+ rtnl_lock();
+ err = i40evf_set_interrupt_capability(adapter);
+ rtnl_unlock();
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Unable to setup interrupt capabilities\n");
+ goto err_set_interrupt;
+ }
+
+ err = i40evf_alloc_q_vectors(adapter);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Unable to allocate memory for queue vectors\n");
+ goto err_alloc_q_vectors;
+ }
+
+ /* If we've made it so far while ADq flag being ON, then we haven't
+ * bailed out anywhere in middle. And ADq isn't just enabled but actual
+ * resources have been allocated in the reset path.
+ * Now we can truly claim that ADq is enabled.
+ */
+ if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
+ adapter->num_tc)
+ dev_info(&adapter->pdev->dev, "ADq Enabled, %u TCs created",
+ adapter->num_tc);
+
+ dev_info(&adapter->pdev->dev, "Multiqueue %s: Queue pair count = %u",
+ (adapter->num_active_queues > 1) ? "Enabled" : "Disabled",
+ adapter->num_active_queues);
+
+ return 0;
+err_alloc_q_vectors:
+ i40evf_reset_interrupt_capability(adapter);
+err_set_interrupt:
+ i40evf_free_queues(adapter);
+err_alloc_queues:
+ return err;
+}
+
+/**
+ * i40evf_free_rss - Free memory used by RSS structs
+ * @adapter: board private structure
+ **/
+static void i40evf_free_rss(struct i40evf_adapter *adapter)
+{
+ kfree(adapter->rss_key);
+ adapter->rss_key = NULL;
+
+ kfree(adapter->rss_lut);
+ adapter->rss_lut = NULL;
+}
+
+/**
+ * i40evf_reinit_interrupt_scheme - Reallocate queues and vectors
+ * @adapter: board private structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int i40evf_reinit_interrupt_scheme(struct i40evf_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err;
+
+ if (netif_running(netdev))
+ i40evf_free_traffic_irqs(adapter);
+ i40evf_free_misc_irq(adapter);
+ i40evf_reset_interrupt_capability(adapter);
+ i40evf_free_q_vectors(adapter);
+ i40evf_free_queues(adapter);
+
+ err = i40evf_init_interrupt_scheme(adapter);
+ if (err)
+ goto err;
+
+ netif_tx_stop_all_queues(netdev);
+
+ err = i40evf_request_misc_irq(adapter);
+ if (err)
+ goto err;
+
+ set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
+
+ i40evf_map_rings_to_vectors(adapter);
+
+ if (RSS_AQ(adapter))
+ adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS;
+ else
+ err = i40evf_init_rss(adapter);
+err:
+ return err;
+}
+
+/**
+ * i40evf_watchdog_timer - Periodic call-back timer
+ * @data: pointer to adapter disguised as unsigned long
+ **/
+static void i40evf_watchdog_timer(struct timer_list *t)
+{
+ struct i40evf_adapter *adapter = from_timer(adapter, t,
+ watchdog_timer);
+
+ schedule_work(&adapter->watchdog_task);
+ /* timer will be rescheduled in watchdog task */
+}
+
+/**
+ * i40evf_watchdog_task - Periodic call-back task
+ * @work: pointer to work_struct
+ **/
+static void i40evf_watchdog_task(struct work_struct *work)
+{
+ struct i40evf_adapter *adapter = container_of(work,
+ struct i40evf_adapter,
+ watchdog_task);
+ struct i40e_hw *hw = &adapter->hw;
+ u32 reg_val;
+
+ if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
+ goto restart_watchdog;
+
+ if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
+ reg_val = rd32(hw, I40E_VFGEN_RSTAT) &
+ I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+ if ((reg_val == VIRTCHNL_VFR_VFACTIVE) ||
+ (reg_val == VIRTCHNL_VFR_COMPLETED)) {
+ /* A chance for redemption! */
+ dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n");
+ adapter->state = __I40EVF_STARTUP;
+ adapter->flags &= ~I40EVF_FLAG_PF_COMMS_FAILED;
+ schedule_delayed_work(&adapter->init_task, 10);
+ clear_bit(__I40EVF_IN_CRITICAL_TASK,
+ &adapter->crit_section);
+ /* Don't reschedule the watchdog, since we've restarted
+ * the init task. When init_task contacts the PF and
+ * gets everything set up again, it'll restart the
+ * watchdog for us. Down, boy. Sit. Stay. Woof.
+ */
+ return;
+ }
+ adapter->aq_required = 0;
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+ goto watchdog_done;
+ }
+
+ if ((adapter->state < __I40EVF_DOWN) ||
+ (adapter->flags & I40EVF_FLAG_RESET_PENDING))
+ goto watchdog_done;
+
+ /* check for reset */
+ reg_val = rd32(hw, I40E_VF_ARQLEN1) & I40E_VF_ARQLEN1_ARQENABLE_MASK;
+ if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) && !reg_val) {
+ adapter->state = __I40EVF_RESETTING;
+ adapter->flags |= I40EVF_FLAG_RESET_PENDING;
+ dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
+ schedule_work(&adapter->reset_task);
+ adapter->aq_required = 0;
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+ goto watchdog_done;
+ }
+
+ /* Process admin queue tasks. After init, everything gets done
+ * here so we don't race on the admin queue.
+ */
+ if (adapter->current_op) {
+ if (!i40evf_asq_done(hw)) {
+ dev_dbg(&adapter->pdev->dev, "Admin queue timeout\n");
+ i40evf_send_api_ver(adapter);
+ }
+ goto watchdog_done;
+ }
+ if (adapter->aq_required & I40EVF_FLAG_AQ_GET_CONFIG) {
+ i40evf_send_vf_config_msg(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_QUEUES) {
+ i40evf_disable_queues(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_MAP_VECTORS) {
+ i40evf_map_queues(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_ADD_MAC_FILTER) {
+ i40evf_add_ether_addrs(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_ADD_VLAN_FILTER) {
+ i40evf_add_vlans(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_DEL_MAC_FILTER) {
+ i40evf_del_ether_addrs(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_DEL_VLAN_FILTER) {
+ i40evf_del_vlans(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING) {
+ i40evf_enable_vlan_stripping(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING) {
+ i40evf_disable_vlan_stripping(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_CONFIGURE_QUEUES) {
+ i40evf_configure_queues(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_ENABLE_QUEUES) {
+ i40evf_enable_queues(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_CONFIGURE_RSS) {
+ /* This message goes straight to the firmware, not the
+ * PF, so we don't have to set current_op as we will
+ * not get a response through the ARQ.
+ */
+ i40evf_init_rss(adapter);
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_RSS;
+ goto watchdog_done;
+ }
+ if (adapter->aq_required & I40EVF_FLAG_AQ_GET_HENA) {
+ i40evf_get_hena(adapter);
+ goto watchdog_done;
+ }
+ if (adapter->aq_required & I40EVF_FLAG_AQ_SET_HENA) {
+ i40evf_set_hena(adapter);
+ goto watchdog_done;
+ }
+ if (adapter->aq_required & I40EVF_FLAG_AQ_SET_RSS_KEY) {
+ i40evf_set_rss_key(adapter);
+ goto watchdog_done;
+ }
+ if (adapter->aq_required & I40EVF_FLAG_AQ_SET_RSS_LUT) {
+ i40evf_set_rss_lut(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_REQUEST_PROMISC) {
+ i40evf_set_promiscuous(adapter, FLAG_VF_UNICAST_PROMISC |
+ FLAG_VF_MULTICAST_PROMISC);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_REQUEST_ALLMULTI) {
+ i40evf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC);
+ goto watchdog_done;
+ }
+
+ if ((adapter->aq_required & I40EVF_FLAG_AQ_RELEASE_PROMISC) &&
+ (adapter->aq_required & I40EVF_FLAG_AQ_RELEASE_ALLMULTI)) {
+ i40evf_set_promiscuous(adapter, 0);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_ENABLE_CHANNELS) {
+ i40evf_enable_channels(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_CHANNELS) {
+ i40evf_disable_channels(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_ADD_CLOUD_FILTER) {
+ i40evf_add_cloud_filter(adapter);
+ goto watchdog_done;
+ }
+
+ if (adapter->aq_required & I40EVF_FLAG_AQ_DEL_CLOUD_FILTER) {
+ i40evf_del_cloud_filter(adapter);
+ goto watchdog_done;
+ }
+
+ schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5));
+
+ if (adapter->state == __I40EVF_RUNNING)
+ i40evf_request_stats(adapter);
+watchdog_done:
+ if (adapter->state == __I40EVF_RUNNING)
+ i40evf_detect_recover_hung(&adapter->vsi);
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+restart_watchdog:
+ if (adapter->state == __I40EVF_REMOVE)
+ return;
+ if (adapter->aq_required)
+ mod_timer(&adapter->watchdog_timer,
+ jiffies + msecs_to_jiffies(20));
+ else
+ mod_timer(&adapter->watchdog_timer, jiffies + (HZ * 2));
+ schedule_work(&adapter->adminq_task);
+}
+
+static void i40evf_disable_vf(struct i40evf_adapter *adapter)
+{
+ struct i40evf_mac_filter *f, *ftmp;
+ struct i40evf_vlan_filter *fv, *fvtmp;
+ struct i40evf_cloud_filter *cf, *cftmp;
+
+ adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
+
+ /* We don't use netif_running() because it may be true prior to
+ * ndo_open() returning, so we can't assume it means all our open
+ * tasks have finished, since we're not holding the rtnl_lock here.
+ */
+ if (adapter->state == __I40EVF_RUNNING) {
+ set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
+ netif_carrier_off(adapter->netdev);
+ netif_tx_disable(adapter->netdev);
+ adapter->link_up = false;
+ i40evf_napi_disable_all(adapter);
+ i40evf_irq_disable(adapter);
+ i40evf_free_traffic_irqs(adapter);
+ i40evf_free_all_tx_resources(adapter);
+ i40evf_free_all_rx_resources(adapter);
+ }
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ /* Delete all of the filters */
+ list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+ list_del(&f->list);
+ kfree(f);
+ }
+
+ list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list, list) {
+ list_del(&fv->list);
+ kfree(fv);
+ }
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ spin_lock_bh(&adapter->cloud_filter_list_lock);
+ list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {
+ list_del(&cf->list);
+ kfree(cf);
+ adapter->num_cloud_filters--;
+ }
+ spin_unlock_bh(&adapter->cloud_filter_list_lock);
+
+ i40evf_free_misc_irq(adapter);
+ i40evf_reset_interrupt_capability(adapter);
+ i40evf_free_queues(adapter);
+ i40evf_free_q_vectors(adapter);
+ kfree(adapter->vf_res);
+ i40evf_shutdown_adminq(&adapter->hw);
+ adapter->netdev->flags &= ~IFF_UP;
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+ adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
+ adapter->state = __I40EVF_DOWN;
+ wake_up(&adapter->down_waitqueue);
+ dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
+}
+
+#define I40EVF_RESET_WAIT_MS 10
+#define I40EVF_RESET_WAIT_COUNT 500
+/**
+ * i40evf_reset_task - Call-back task to handle hardware reset
+ * @work: pointer to work_struct
+ *
+ * During reset we need to shut down and reinitialize the admin queue
+ * before we can use it to communicate with the PF again. We also clear
+ * and reinit the rings because that context is lost as well.
+ **/
+static void i40evf_reset_task(struct work_struct *work)
+{
+ struct i40evf_adapter *adapter = container_of(work,
+ struct i40evf_adapter,
+ reset_task);
+ struct virtchnl_vf_resource *vfres = adapter->vf_res;
+ struct net_device *netdev = adapter->netdev;
+ struct i40e_hw *hw = &adapter->hw;
+ struct i40evf_vlan_filter *vlf;
+ struct i40evf_cloud_filter *cf;
+ struct i40evf_mac_filter *f;
+ u32 reg_val;
+ int i = 0, err;
+ bool running;
+
+ /* When device is being removed it doesn't make sense to run the reset
+ * task, just return in such a case.
+ */
+ if (test_bit(__I40EVF_IN_REMOVE_TASK, &adapter->crit_section))
+ return;
+
+ while (test_and_set_bit(__I40EVF_IN_CLIENT_TASK,
+ &adapter->crit_section))
+ usleep_range(500, 1000);
+ if (CLIENT_ENABLED(adapter)) {
+ adapter->flags &= ~(I40EVF_FLAG_CLIENT_NEEDS_OPEN |
+ I40EVF_FLAG_CLIENT_NEEDS_CLOSE |
+ I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS |
+ I40EVF_FLAG_SERVICE_CLIENT_REQUESTED);
+ cancel_delayed_work_sync(&adapter->client_task);
+ i40evf_notify_client_close(&adapter->vsi, true);
+ }
+ i40evf_misc_irq_disable(adapter);
+ if (adapter->flags & I40EVF_FLAG_RESET_NEEDED) {
+ adapter->flags &= ~I40EVF_FLAG_RESET_NEEDED;
+ /* Restart the AQ here. If we have been reset but didn't
+ * detect it, or if the PF had to reinit, our AQ will be hosed.
+ */
+ i40evf_shutdown_adminq(hw);
+ i40evf_init_adminq(hw);
+ i40evf_request_reset(adapter);
+ }
+ adapter->flags |= I40EVF_FLAG_RESET_PENDING;
+
+ /* poll until we see the reset actually happen */
+ for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
+ reg_val = rd32(hw, I40E_VF_ARQLEN1) &
+ I40E_VF_ARQLEN1_ARQENABLE_MASK;
+ if (!reg_val)
+ break;
+ usleep_range(5000, 10000);
+ }
+ if (i == I40EVF_RESET_WAIT_COUNT) {
+ dev_info(&adapter->pdev->dev, "Never saw reset\n");
+ goto continue_reset; /* act like the reset happened */
+ }
+
+ /* wait until the reset is complete and the PF is responding to us */
+ for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
+ /* sleep first to make sure a minimum wait time is met */
+ msleep(I40EVF_RESET_WAIT_MS);
+
+ reg_val = rd32(hw, I40E_VFGEN_RSTAT) &
+ I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+ if (reg_val == VIRTCHNL_VFR_VFACTIVE)
+ break;
+ }
+
+ pci_set_master(adapter->pdev);
+
+ if (i == I40EVF_RESET_WAIT_COUNT) {
+ dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
+ reg_val);
+ i40evf_disable_vf(adapter);
+ clear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);
+ return; /* Do not attempt to reinit. It's dead, Jim. */
+ }
+
+continue_reset:
+ /* We don't use netif_running() because it may be true prior to
+ * ndo_open() returning, so we can't assume it means all our open
+ * tasks have finished, since we're not holding the rtnl_lock here.
+ */
+ running = ((adapter->state == __I40EVF_RUNNING) ||
+ (adapter->state == __I40EVF_RESETTING));
+
+ if (running) {
+ netif_carrier_off(netdev);
+ netif_tx_stop_all_queues(netdev);
+ adapter->link_up = false;
+ i40evf_napi_disable_all(adapter);
+ }
+ i40evf_irq_disable(adapter);
+
+ adapter->state = __I40EVF_RESETTING;
+ adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
+
+ /* free the Tx/Rx rings and descriptors, might be better to just
+ * re-use them sometime in the future
+ */
+ i40evf_free_all_rx_resources(adapter);
+ i40evf_free_all_tx_resources(adapter);
+
+ adapter->flags |= I40EVF_FLAG_QUEUES_DISABLED;
+ /* kill and reinit the admin queue */
+ i40evf_shutdown_adminq(hw);
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+ err = i40evf_init_adminq(hw);
+ if (err)
+ dev_info(&adapter->pdev->dev, "Failed to init adminq: %d\n",
+ err);
+ adapter->aq_required = 0;
+
+ if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
+ err = i40evf_reinit_interrupt_scheme(adapter);
+ if (err)
+ goto reset_err;
+ }
+
+ adapter->aq_required |= I40EVF_FLAG_AQ_GET_CONFIG;
+ adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ /* re-add all MAC filters */
+ list_for_each_entry(f, &adapter->mac_filter_list, list) {
+ f->add = true;
+ }
+ /* re-add all VLAN filters */
+ list_for_each_entry(vlf, &adapter->vlan_filter_list, list) {
+ vlf->add = true;
+ }
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ /* check if TCs are running and re-add all cloud filters */
+ spin_lock_bh(&adapter->cloud_filter_list_lock);
+ if ((vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
+ adapter->num_tc) {
+ list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
+ cf->add = true;
+ }
+ }
+ spin_unlock_bh(&adapter->cloud_filter_list_lock);
+
+ adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+ adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+ adapter->aq_required |= I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;
+ i40evf_misc_irq_enable(adapter);
+
+ mod_timer(&adapter->watchdog_timer, jiffies + 2);
+
+ /* We were running when the reset started, so we need to restore some
+ * state here.
+ */
+ if (running) {
+ /* allocate transmit descriptors */
+ err = i40evf_setup_all_tx_resources(adapter);
+ if (err)
+ goto reset_err;
+
+ /* allocate receive descriptors */
+ err = i40evf_setup_all_rx_resources(adapter);
+ if (err)
+ goto reset_err;
+
+ if (adapter->flags & I40EVF_FLAG_REINIT_ITR_NEEDED) {
+ err = i40evf_request_traffic_irqs(adapter,
+ netdev->name);
+ if (err)
+ goto reset_err;
+
+ adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
+ }
+
+ i40evf_configure(adapter);
+
+ i40evf_up_complete(adapter);
+
+ i40evf_irq_enable(adapter, true);
+ } else {
+ adapter->state = __I40EVF_DOWN;
+ wake_up(&adapter->down_waitqueue);
+ }
+ clear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+
+ return;
+reset_err:
+ clear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+ dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
+ i40evf_close(netdev);
+}
+
+/**
+ * i40evf_adminq_task - worker thread to clean the admin queue
+ * @work: pointer to work_struct containing our data
+ **/
+static void i40evf_adminq_task(struct work_struct *work)
+{
+ struct i40evf_adapter *adapter =
+ container_of(work, struct i40evf_adapter, adminq_task);
+ struct i40e_hw *hw = &adapter->hw;
+ struct i40e_arq_event_info event;
+ enum virtchnl_ops v_op;
+ i40e_status ret, v_ret;
+ u32 val, oldval;
+ u16 pending;
+
+ if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED)
+ goto out;
+
+ event.buf_len = I40EVF_MAX_AQ_BUF_SIZE;
+ event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
+ if (!event.msg_buf)
+ goto out;
+
+ do {
+ ret = i40evf_clean_arq_element(hw, &event, &pending);
+ v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
+ v_ret = (i40e_status)le32_to_cpu(event.desc.cookie_low);
+
+ if (ret || !v_op)
+ break; /* No event to process or error cleaning ARQ */
+
+ i40evf_virtchnl_completion(adapter, v_op, v_ret, event.msg_buf,
+ event.msg_len);
+ if (pending != 0)
+ memset(event.msg_buf, 0, I40EVF_MAX_AQ_BUF_SIZE);
+ } while (pending);
+
+ if ((adapter->flags &
+ (I40EVF_FLAG_RESET_PENDING | I40EVF_FLAG_RESET_NEEDED)) ||
+ adapter->state == __I40EVF_RESETTING)
+ goto freedom;
+
+ /* check for error indications */
+ val = rd32(hw, hw->aq.arq.len);
+ if (val == 0xdeadbeef || val == 0xffffffff) /* device in reset */
+ goto freedom;
+ oldval = val;
+ if (val & I40E_VF_ARQLEN1_ARQVFE_MASK) {
+ dev_info(&adapter->pdev->dev, "ARQ VF Error detected\n");
+ val &= ~I40E_VF_ARQLEN1_ARQVFE_MASK;
+ }
+ if (val & I40E_VF_ARQLEN1_ARQOVFL_MASK) {
+ dev_info(&adapter->pdev->dev, "ARQ Overflow Error detected\n");
+ val &= ~I40E_VF_ARQLEN1_ARQOVFL_MASK;
+ }
+ if (val & I40E_VF_ARQLEN1_ARQCRIT_MASK) {
+ dev_info(&adapter->pdev->dev, "ARQ Critical Error detected\n");
+ val &= ~I40E_VF_ARQLEN1_ARQCRIT_MASK;
+ }
+ if (oldval != val)
+ wr32(hw, hw->aq.arq.len, val);
+
+ val = rd32(hw, hw->aq.asq.len);
+ oldval = val;
+ if (val & I40E_VF_ATQLEN1_ATQVFE_MASK) {
+ dev_info(&adapter->pdev->dev, "ASQ VF Error detected\n");
+ val &= ~I40E_VF_ATQLEN1_ATQVFE_MASK;
+ }
+ if (val & I40E_VF_ATQLEN1_ATQOVFL_MASK) {
+ dev_info(&adapter->pdev->dev, "ASQ Overflow Error detected\n");
+ val &= ~I40E_VF_ATQLEN1_ATQOVFL_MASK;
+ }
+ if (val & I40E_VF_ATQLEN1_ATQCRIT_MASK) {
+ dev_info(&adapter->pdev->dev, "ASQ Critical Error detected\n");
+ val &= ~I40E_VF_ATQLEN1_ATQCRIT_MASK;
+ }
+ if (oldval != val)
+ wr32(hw, hw->aq.asq.len, val);
+
+freedom:
+ kfree(event.msg_buf);
+out:
+ /* re-enable Admin queue interrupt cause */
+ i40evf_misc_irq_enable(adapter);
+}
+
+/**
+ * i40evf_client_task - worker thread to perform client work
+ * @work: pointer to work_struct containing our data
+ *
+ * This task handles client interactions. Because client calls can be
+ * reentrant, we can't handle them in the watchdog.
+ **/
+static void i40evf_client_task(struct work_struct *work)
+{
+ struct i40evf_adapter *adapter =
+ container_of(work, struct i40evf_adapter, client_task.work);
+
+ /* If we can't get the client bit, just give up. We'll be rescheduled
+ * later.
+ */
+
+ if (test_and_set_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section))
+ return;
+
+ if (adapter->flags & I40EVF_FLAG_SERVICE_CLIENT_REQUESTED) {
+ i40evf_client_subtask(adapter);
+ adapter->flags &= ~I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
+ goto out;
+ }
+ if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS) {
+ i40evf_notify_client_l2_params(&adapter->vsi);
+ adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_L2_PARAMS;
+ goto out;
+ }
+ if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_CLOSE) {
+ i40evf_notify_client_close(&adapter->vsi, false);
+ adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_CLOSE;
+ goto out;
+ }
+ if (adapter->flags & I40EVF_FLAG_CLIENT_NEEDS_OPEN) {
+ i40evf_notify_client_open(&adapter->vsi);
+ adapter->flags &= ~I40EVF_FLAG_CLIENT_NEEDS_OPEN;
+ }
+out:
+ clear_bit(__I40EVF_IN_CLIENT_TASK, &adapter->crit_section);
+}
+
+/**
+ * i40evf_free_all_tx_resources - Free Tx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ **/
+void i40evf_free_all_tx_resources(struct i40evf_adapter *adapter)
+{
+ int i;
+
+ if (!adapter->tx_rings)
+ return;
+
+ for (i = 0; i < adapter->num_active_queues; i++)
+ if (adapter->tx_rings[i].desc)
+ i40evf_free_tx_resources(&adapter->tx_rings[i]);
+}
+
+/**
+ * i40evf_setup_all_tx_resources - allocate all queues Tx resources
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not). It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter)
+{
+ int i, err = 0;
+
+ for (i = 0; i < adapter->num_active_queues; i++) {
+ adapter->tx_rings[i].count = adapter->tx_desc_count;
+ err = i40evf_setup_tx_descriptors(&adapter->tx_rings[i]);
+ if (!err)
+ continue;
+ dev_err(&adapter->pdev->dev,
+ "Allocation for Tx Queue %u failed\n", i);
+ break;
+ }
+
+ return err;
+}
+
+/**
+ * i40evf_setup_all_rx_resources - allocate all queues Rx resources
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+ * more of the rings is populated (while the rest are not). It is the
+ * callers duty to clean those orphaned rings.
+ *
+ * Return 0 on success, negative on failure
+ **/
+static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter)
+{
+ int i, err = 0;
+
+ for (i = 0; i < adapter->num_active_queues; i++) {
+ adapter->rx_rings[i].count = adapter->rx_desc_count;
+ err = i40evf_setup_rx_descriptors(&adapter->rx_rings[i]);
+ if (!err)
+ continue;
+ dev_err(&adapter->pdev->dev,
+ "Allocation for Rx Queue %u failed\n", i);
+ break;
+ }
+ return err;
+}
+
+/**
+ * i40evf_free_all_rx_resources - Free Rx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+void i40evf_free_all_rx_resources(struct i40evf_adapter *adapter)
+{
+ int i;
+
+ if (!adapter->rx_rings)
+ return;
+
+ for (i = 0; i < adapter->num_active_queues; i++)
+ if (adapter->rx_rings[i].desc)
+ i40evf_free_rx_resources(&adapter->rx_rings[i]);
+}
+
+/**
+ * i40evf_validate_tx_bandwidth - validate the max Tx bandwidth
+ * @adapter: board private structure
+ * @max_tx_rate: max Tx bw for a tc
+ **/
+static int i40evf_validate_tx_bandwidth(struct i40evf_adapter *adapter,
+ u64 max_tx_rate)
+{
+ int speed = 0, ret = 0;
+
+ switch (adapter->link_speed) {
+ case I40E_LINK_SPEED_40GB:
+ speed = 40000;
+ break;
+ case I40E_LINK_SPEED_25GB:
+ speed = 25000;
+ break;
+ case I40E_LINK_SPEED_20GB:
+ speed = 20000;
+ break;
+ case I40E_LINK_SPEED_10GB:
+ speed = 10000;
+ break;
+ case I40E_LINK_SPEED_1GB:
+ speed = 1000;
+ break;
+ case I40E_LINK_SPEED_100MB:
+ speed = 100;
+ break;
+ default:
+ break;
+ }
+
+ if (max_tx_rate > speed) {
+ dev_err(&adapter->pdev->dev,
+ "Invalid tx rate specified\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/**
+ * i40evf_validate_channel_config - validate queue mapping info
+ * @adapter: board private structure
+ * @mqprio_qopt: queue parameters
+ *
+ * This function validates if the config provided by the user to
+ * configure queue channels is valid or not. Returns 0 on a valid
+ * config.
+ **/
+static int i40evf_validate_ch_config(struct i40evf_adapter *adapter,
+ struct tc_mqprio_qopt_offload *mqprio_qopt)
+{
+ u64 total_max_rate = 0;
+ int i, num_qps = 0;
+ u64 tx_rate = 0;
+ int ret = 0;
+
+ if (mqprio_qopt->qopt.num_tc > I40EVF_MAX_TRAFFIC_CLASS ||
+ mqprio_qopt->qopt.num_tc < 1)
+ return -EINVAL;
+
+ for (i = 0; i <= mqprio_qopt->qopt.num_tc - 1; i++) {
+ if (!mqprio_qopt->qopt.count[i] ||
+ mqprio_qopt->qopt.offset[i] != num_qps)
+ return -EINVAL;
+ if (mqprio_qopt->min_rate[i]) {
+ dev_err(&adapter->pdev->dev,
+ "Invalid min tx rate (greater than 0) specified\n");
+ return -EINVAL;
+ }
+ /*convert to Mbps */
+ tx_rate = div_u64(mqprio_qopt->max_rate[i],
+ I40EVF_MBPS_DIVISOR);
+ total_max_rate += tx_rate;
+ num_qps += mqprio_qopt->qopt.count[i];
+ }
+ if (num_qps > I40EVF_MAX_REQ_QUEUES)
+ return -EINVAL;
+
+ ret = i40evf_validate_tx_bandwidth(adapter, total_max_rate);
+ return ret;
+}
+
+/**
+ * i40evf_del_all_cloud_filters - delete all cloud filters
+ * on the traffic classes
+ **/
+static void i40evf_del_all_cloud_filters(struct i40evf_adapter *adapter)
+{
+ struct i40evf_cloud_filter *cf, *cftmp;
+
+ spin_lock_bh(&adapter->cloud_filter_list_lock);
+ list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list,
+ list) {
+ list_del(&cf->list);
+ kfree(cf);
+ adapter->num_cloud_filters--;
+ }
+ spin_unlock_bh(&adapter->cloud_filter_list_lock);
+}
+
+/**
+ * __i40evf_setup_tc - configure multiple traffic classes
+ * @netdev: network interface device structure
+ * @type_date: tc offload data
+ *
+ * This function processes the config information provided by the
+ * user to configure traffic classes/queue channels and packages the
+ * information to request the PF to setup traffic classes.
+ *
+ * Returns 0 on success.
+ **/
+static int __i40evf_setup_tc(struct net_device *netdev, void *type_data)
+{
+ struct tc_mqprio_qopt_offload *mqprio_qopt = type_data;
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ struct virtchnl_vf_resource *vfres = adapter->vf_res;
+ u8 num_tc = 0, total_qps = 0;
+ int ret = 0, netdev_tc = 0;
+ u64 max_tx_rate;
+ u16 mode;
+ int i;
+
+ num_tc = mqprio_qopt->qopt.num_tc;
+ mode = mqprio_qopt->mode;
+
+ /* delete queue_channel */
+ if (!mqprio_qopt->qopt.hw) {
+ if (adapter->ch_config.state == __I40EVF_TC_RUNNING) {
+ /* reset the tc configuration */
+ netdev_reset_tc(netdev);
+ adapter->num_tc = 0;
+ netif_tx_stop_all_queues(netdev);
+ netif_tx_disable(netdev);
+ i40evf_del_all_cloud_filters(adapter);
+ adapter->aq_required = I40EVF_FLAG_AQ_DISABLE_CHANNELS;
+ goto exit;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ /* add queue channel */
+ if (mode == TC_MQPRIO_MODE_CHANNEL) {
+ if (!(vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ)) {
+ dev_err(&adapter->pdev->dev, "ADq not supported\n");
+ return -EOPNOTSUPP;
+ }
+ if (adapter->ch_config.state != __I40EVF_TC_INVALID) {
+ dev_err(&adapter->pdev->dev, "TC configuration already exists\n");
+ return -EINVAL;
+ }
+
+ ret = i40evf_validate_ch_config(adapter, mqprio_qopt);
+ if (ret)
+ return ret;
+ /* Return if same TC config is requested */
+ if (adapter->num_tc == num_tc)
+ return 0;
+ adapter->num_tc = num_tc;
+
+ for (i = 0; i < I40EVF_MAX_TRAFFIC_CLASS; i++) {
+ if (i < num_tc) {
+ adapter->ch_config.ch_info[i].count =
+ mqprio_qopt->qopt.count[i];
+ adapter->ch_config.ch_info[i].offset =
+ mqprio_qopt->qopt.offset[i];
+ total_qps += mqprio_qopt->qopt.count[i];
+ max_tx_rate = mqprio_qopt->max_rate[i];
+ /* convert to Mbps */
+ max_tx_rate = div_u64(max_tx_rate,
+ I40EVF_MBPS_DIVISOR);
+ adapter->ch_config.ch_info[i].max_tx_rate =
+ max_tx_rate;
+ } else {
+ adapter->ch_config.ch_info[i].count = 1;
+ adapter->ch_config.ch_info[i].offset = 0;
+ }
+ }
+ adapter->ch_config.total_qps = total_qps;
+ netif_tx_stop_all_queues(netdev);
+ netif_tx_disable(netdev);
+ adapter->aq_required |= I40EVF_FLAG_AQ_ENABLE_CHANNELS;
+ netdev_reset_tc(netdev);
+ /* Report the tc mapping up the stack */
+ netdev_set_num_tc(adapter->netdev, num_tc);
+ for (i = 0; i < I40EVF_MAX_TRAFFIC_CLASS; i++) {
+ u16 qcount = mqprio_qopt->qopt.count[i];
+ u16 qoffset = mqprio_qopt->qopt.offset[i];
+
+ if (i < num_tc)
+ netdev_set_tc_queue(netdev, netdev_tc++, qcount,
+ qoffset);
+ }
+ }
+exit:
+ return ret;
+}
+
+/**
+ * i40evf_parse_cls_flower - Parse tc flower filters provided by kernel
+ * @adapter: board private structure
+ * @cls_flower: pointer to struct tc_cls_flower_offload
+ * @filter: pointer to cloud filter structure
+ */
+static int i40evf_parse_cls_flower(struct i40evf_adapter *adapter,
+ struct tc_cls_flower_offload *f,
+ struct i40evf_cloud_filter *filter)
+{
+ u16 n_proto_mask = 0;
+ u16 n_proto_key = 0;
+ u8 field_flags = 0;
+ u16 addr_type = 0;
+ u16 n_proto = 0;
+ int i = 0;
+ struct virtchnl_filter *vf = &filter->f;
+
+ if (f->dissector->used_keys &
+ ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
+ BIT(FLOW_DISSECTOR_KEY_BASIC) |
+ BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
+ BIT(FLOW_DISSECTOR_KEY_VLAN) |
+ BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
+ BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
+ BIT(FLOW_DISSECTOR_KEY_PORTS) |
+ BIT(FLOW_DISSECTOR_KEY_ENC_KEYID))) {
+ dev_err(&adapter->pdev->dev, "Unsupported key used: 0x%x\n",
+ f->dissector->used_keys);
+ return -EOPNOTSUPP;
+ }
+
+ if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+ struct flow_dissector_key_keyid *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ENC_KEYID,
+ f->mask);
+
+ if (mask->keyid != 0)
+ field_flags |= I40EVF_CLOUD_FIELD_TEN_ID;
+ }
+
+ if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+ struct flow_dissector_key_basic *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_BASIC,
+ f->key);
+
+ struct flow_dissector_key_basic *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_BASIC,
+ f->mask);
+ n_proto_key = ntohs(key->n_proto);
+ n_proto_mask = ntohs(mask->n_proto);
+
+ if (n_proto_key == ETH_P_ALL) {
+ n_proto_key = 0;
+ n_proto_mask = 0;
+ }
+ n_proto = n_proto_key & n_proto_mask;
+ if (n_proto != ETH_P_IP && n_proto != ETH_P_IPV6)
+ return -EINVAL;
+ if (n_proto == ETH_P_IPV6) {
+ /* specify flow type as TCP IPv6 */
+ vf->flow_type = VIRTCHNL_TCP_V6_FLOW;
+ }
+
+ if (key->ip_proto != IPPROTO_TCP) {
+ dev_info(&adapter->pdev->dev, "Only TCP transport is supported\n");
+ return -EINVAL;
+ }
+ }
+
+ if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+ struct flow_dissector_key_eth_addrs *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ETH_ADDRS,
+ f->key);
+
+ struct flow_dissector_key_eth_addrs *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_ETH_ADDRS,
+ f->mask);
+ /* use is_broadcast and is_zero to check for all 0xf or 0 */
+ if (!is_zero_ether_addr(mask->dst)) {
+ if (is_broadcast_ether_addr(mask->dst)) {
+ field_flags |= I40EVF_CLOUD_FIELD_OMAC;
+ } else {
+ dev_err(&adapter->pdev->dev, "Bad ether dest mask %pM\n",
+ mask->dst);
+ return I40E_ERR_CONFIG;
+ }
+ }
+
+ if (!is_zero_ether_addr(mask->src)) {
+ if (is_broadcast_ether_addr(mask->src)) {
+ field_flags |= I40EVF_CLOUD_FIELD_IMAC;
+ } else {
+ dev_err(&adapter->pdev->dev, "Bad ether src mask %pM\n",
+ mask->src);
+ return I40E_ERR_CONFIG;
+ }
+ }
+
+ if (!is_zero_ether_addr(key->dst))
+ if (is_valid_ether_addr(key->dst) ||
+ is_multicast_ether_addr(key->dst)) {
+ /* set the mask if a valid dst_mac address */
+ for (i = 0; i < ETH_ALEN; i++)
+ vf->mask.tcp_spec.dst_mac[i] |= 0xff;
+ ether_addr_copy(vf->data.tcp_spec.dst_mac,
+ key->dst);
+ }
+
+ if (!is_zero_ether_addr(key->src))
+ if (is_valid_ether_addr(key->src) ||
+ is_multicast_ether_addr(key->src)) {
+ /* set the mask if a valid dst_mac address */
+ for (i = 0; i < ETH_ALEN; i++)
+ vf->mask.tcp_spec.src_mac[i] |= 0xff;
+ ether_addr_copy(vf->data.tcp_spec.src_mac,
+ key->src);
+ }
+ }
+
+ if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
+ struct flow_dissector_key_vlan *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_VLAN,
+ f->key);
+ struct flow_dissector_key_vlan *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_VLAN,
+ f->mask);
+
+ if (mask->vlan_id) {
+ if (mask->vlan_id == VLAN_VID_MASK) {
+ field_flags |= I40EVF_CLOUD_FIELD_IVLAN;
+ } else {
+ dev_err(&adapter->pdev->dev, "Bad vlan mask %u\n",
+ mask->vlan_id);
+ return I40E_ERR_CONFIG;
+ }
+ }
+ vf->mask.tcp_spec.vlan_id |= cpu_to_be16(0xffff);
+ vf->data.tcp_spec.vlan_id = cpu_to_be16(key->vlan_id);
+ }
+
+ if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
+ struct flow_dissector_key_control *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_CONTROL,
+ f->key);
+
+ addr_type = key->addr_type;
+ }
+
+ if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
+ struct flow_dissector_key_ipv4_addrs *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+ f->key);
+ struct flow_dissector_key_ipv4_addrs *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+ f->mask);
+
+ if (mask->dst) {
+ if (mask->dst == cpu_to_be32(0xffffffff)) {
+ field_flags |= I40EVF_CLOUD_FIELD_IIP;
+ } else {
+ dev_err(&adapter->pdev->dev, "Bad ip dst mask 0x%08x\n",
+ be32_to_cpu(mask->dst));
+ return I40E_ERR_CONFIG;
+ }
+ }
+
+ if (mask->src) {
+ if (mask->src == cpu_to_be32(0xffffffff)) {
+ field_flags |= I40EVF_CLOUD_FIELD_IIP;
+ } else {
+ dev_err(&adapter->pdev->dev, "Bad ip src mask 0x%08x\n",
+ be32_to_cpu(mask->dst));
+ return I40E_ERR_CONFIG;
+ }
+ }
+
+ if (field_flags & I40EVF_CLOUD_FIELD_TEN_ID) {
+ dev_info(&adapter->pdev->dev, "Tenant id not allowed for ip filter\n");
+ return I40E_ERR_CONFIG;
+ }
+ if (key->dst) {
+ vf->mask.tcp_spec.dst_ip[0] |= cpu_to_be32(0xffffffff);
+ vf->data.tcp_spec.dst_ip[0] = key->dst;
+ }
+ if (key->src) {
+ vf->mask.tcp_spec.src_ip[0] |= cpu_to_be32(0xffffffff);
+ vf->data.tcp_spec.src_ip[0] = key->src;
+ }
+ }
+
+ if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
+ struct flow_dissector_key_ipv6_addrs *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+ f->key);
+ struct flow_dissector_key_ipv6_addrs *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+ f->mask);
+
+ /* validate mask, make sure it is not IPV6_ADDR_ANY */
+ if (ipv6_addr_any(&mask->dst)) {
+ dev_err(&adapter->pdev->dev, "Bad ipv6 dst mask 0x%02x\n",
+ IPV6_ADDR_ANY);
+ return I40E_ERR_CONFIG;
+ }
+
+ /* src and dest IPv6 address should not be LOOPBACK
+ * (0:0:0:0:0:0:0:1) which can be represented as ::1
+ */
+ if (ipv6_addr_loopback(&key->dst) ||
+ ipv6_addr_loopback(&key->src)) {
+ dev_err(&adapter->pdev->dev,
+ "ipv6 addr should not be loopback\n");
+ return I40E_ERR_CONFIG;
+ }
+ if (!ipv6_addr_any(&mask->dst) || !ipv6_addr_any(&mask->src))
+ field_flags |= I40EVF_CLOUD_FIELD_IIP;
+
+ for (i = 0; i < 4; i++)
+ vf->mask.tcp_spec.dst_ip[i] |= cpu_to_be32(0xffffffff);
+ memcpy(&vf->data.tcp_spec.dst_ip, &key->dst.s6_addr32,
+ sizeof(vf->data.tcp_spec.dst_ip));
+ for (i = 0; i < 4; i++)
+ vf->mask.tcp_spec.src_ip[i] |= cpu_to_be32(0xffffffff);
+ memcpy(&vf->data.tcp_spec.src_ip, &key->src.s6_addr32,
+ sizeof(vf->data.tcp_spec.src_ip));
+ }
+ if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
+ struct flow_dissector_key_ports *key =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_PORTS,
+ f->key);
+ struct flow_dissector_key_ports *mask =
+ skb_flow_dissector_target(f->dissector,
+ FLOW_DISSECTOR_KEY_PORTS,
+ f->mask);
+
+ if (mask->src) {
+ if (mask->src == cpu_to_be16(0xffff)) {
+ field_flags |= I40EVF_CLOUD_FIELD_IIP;
+ } else {
+ dev_err(&adapter->pdev->dev, "Bad src port mask %u\n",
+ be16_to_cpu(mask->src));
+ return I40E_ERR_CONFIG;
+ }
+ }
+
+ if (mask->dst) {
+ if (mask->dst == cpu_to_be16(0xffff)) {
+ field_flags |= I40EVF_CLOUD_FIELD_IIP;
+ } else {
+ dev_err(&adapter->pdev->dev, "Bad dst port mask %u\n",
+ be16_to_cpu(mask->dst));
+ return I40E_ERR_CONFIG;
+ }
+ }
+ if (key->dst) {
+ vf->mask.tcp_spec.dst_port |= cpu_to_be16(0xffff);
+ vf->data.tcp_spec.dst_port = key->dst;
+ }
+
+ if (key->src) {
+ vf->mask.tcp_spec.src_port |= cpu_to_be16(0xffff);
+ vf->data.tcp_spec.src_port = key->src;
+ }
+ }
+ vf->field_flags = field_flags;
+
+ return 0;
+}
+
+/**
+ * i40evf_handle_tclass - Forward to a traffic class on the device
+ * @adapter: board private structure
+ * @tc: traffic class index on the device
+ * @filter: pointer to cloud filter structure
+ */
+static int i40evf_handle_tclass(struct i40evf_adapter *adapter, u32 tc,
+ struct i40evf_cloud_filter *filter)
+{
+ if (tc == 0)
+ return 0;
+ if (tc < adapter->num_tc) {
+ if (!filter->f.data.tcp_spec.dst_port) {
+ dev_err(&adapter->pdev->dev,
+ "Specify destination port to redirect to traffic class other than TC0\n");
+ return -EINVAL;
+ }
+ }
+ /* redirect to a traffic class on the same device */
+ filter->f.action = VIRTCHNL_ACTION_TC_REDIRECT;
+ filter->f.action_meta = tc;
+ return 0;
+}
+
+/**
+ * i40evf_configure_clsflower - Add tc flower filters
+ * @adapter: board private structure
+ * @cls_flower: Pointer to struct tc_cls_flower_offload
+ */
+static int i40evf_configure_clsflower(struct i40evf_adapter *adapter,
+ struct tc_cls_flower_offload *cls_flower)
+{
+ int tc = tc_classid_to_hwtc(adapter->netdev, cls_flower->classid);
+ struct i40evf_cloud_filter *filter = NULL;
+ int err = -EINVAL, count = 50;
+
+ if (tc < 0) {
+ dev_err(&adapter->pdev->dev, "Invalid traffic class\n");
+ return -EINVAL;
+ }
+
+ filter = kzalloc(sizeof(*filter), GFP_KERNEL);
+ if (!filter)
+ return -ENOMEM;
+
+ while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
+ &adapter->crit_section)) {
+ if (--count == 0)
+ goto err;
+ udelay(1);
+ }
+
+ filter->cookie = cls_flower->cookie;
+
+ /* set the mask to all zeroes to begin with */
+ memset(&filter->f.mask.tcp_spec, 0, sizeof(struct virtchnl_l4_spec));
+ /* start out with flow type and eth type IPv4 to begin with */
+ filter->f.flow_type = VIRTCHNL_TCP_V4_FLOW;
+ err = i40evf_parse_cls_flower(adapter, cls_flower, filter);
+ if (err < 0)
+ goto err;
+
+ err = i40evf_handle_tclass(adapter, tc, filter);
+ if (err < 0)
+ goto err;
+
+ /* add filter to the list */
+ spin_lock_bh(&adapter->cloud_filter_list_lock);
+ list_add_tail(&filter->list, &adapter->cloud_filter_list);
+ adapter->num_cloud_filters++;
+ filter->add = true;
+ adapter->aq_required |= I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;
+ spin_unlock_bh(&adapter->cloud_filter_list_lock);
+err:
+ if (err)
+ kfree(filter);
+
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+ return err;
+}
+
+/* i40evf_find_cf - Find the cloud filter in the list
+ * @adapter: Board private structure
+ * @cookie: filter specific cookie
+ *
+ * Returns ptr to the filter object or NULL. Must be called while holding the
+ * cloud_filter_list_lock.
+ */
+static struct i40evf_cloud_filter *i40evf_find_cf(struct i40evf_adapter *adapter,
+ unsigned long *cookie)
+{
+ struct i40evf_cloud_filter *filter = NULL;
+
+ if (!cookie)
+ return NULL;
+
+ list_for_each_entry(filter, &adapter->cloud_filter_list, list) {
+ if (!memcmp(cookie, &filter->cookie, sizeof(filter->cookie)))
+ return filter;
+ }
+ return NULL;
+}
+
+/**
+ * i40evf_delete_clsflower - Remove tc flower filters
+ * @adapter: board private structure
+ * @cls_flower: Pointer to struct tc_cls_flower_offload
+ */
+static int i40evf_delete_clsflower(struct i40evf_adapter *adapter,
+ struct tc_cls_flower_offload *cls_flower)
+{
+ struct i40evf_cloud_filter *filter = NULL;
+ int err = 0;
+
+ spin_lock_bh(&adapter->cloud_filter_list_lock);
+ filter = i40evf_find_cf(adapter, &cls_flower->cookie);
+ if (filter) {
+ filter->del = true;
+ adapter->aq_required |= I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;
+ } else {
+ err = -EINVAL;
+ }
+ spin_unlock_bh(&adapter->cloud_filter_list_lock);
+
+ return err;
+}
+
+/**
+ * i40evf_setup_tc_cls_flower - flower classifier offloads
+ * @netdev: net device to configure
+ * @type_data: offload data
+ */
+static int i40evf_setup_tc_cls_flower(struct i40evf_adapter *adapter,
+ struct tc_cls_flower_offload *cls_flower)
+{
+ if (cls_flower->common.chain_index)
+ return -EOPNOTSUPP;
+
+ switch (cls_flower->command) {
+ case TC_CLSFLOWER_REPLACE:
+ return i40evf_configure_clsflower(adapter, cls_flower);
+ case TC_CLSFLOWER_DESTROY:
+ return i40evf_delete_clsflower(adapter, cls_flower);
+ case TC_CLSFLOWER_STATS:
+ return -EOPNOTSUPP;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/**
+ * i40evf_setup_tc_block_cb - block callback for tc
+ * @type: type of offload
+ * @type_data: offload data
+ * @cb_priv:
+ *
+ * This function is the block callback for traffic classes
+ **/
+static int i40evf_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
+ void *cb_priv)
+{
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
+ return i40evf_setup_tc_cls_flower(cb_priv, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/**
+ * i40evf_setup_tc_block - register callbacks for tc
+ * @netdev: network interface device structure
+ * @f: tc offload data
+ *
+ * This function registers block callbacks for tc
+ * offloads
+ **/
+static int i40evf_setup_tc_block(struct net_device *dev,
+ struct tc_block_offload *f)
+{
+ struct i40evf_adapter *adapter = netdev_priv(dev);
+
+ if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block, i40evf_setup_tc_block_cb,
+ adapter, adapter, f->extack);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block, i40evf_setup_tc_block_cb,
+ adapter);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/**
+ * i40evf_setup_tc - configure multiple traffic classes
+ * @netdev: network interface device structure
+ * @type: type of offload
+ * @type_date: tc offload data
+ *
+ * This function is the callback to ndo_setup_tc in the
+ * netdev_ops.
+ *
+ * Returns 0 on success
+ **/
+static int i40evf_setup_tc(struct net_device *netdev, enum tc_setup_type type,
+ void *type_data)
+{
+ switch (type) {
+ case TC_SETUP_QDISC_MQPRIO:
+ return __i40evf_setup_tc(netdev, type_data);
+ case TC_SETUP_BLOCK:
+ return i40evf_setup_tc_block(netdev, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/**
+ * i40evf_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ **/
+static int i40evf_open(struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ int err;
+
+ if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
+ dev_err(&adapter->pdev->dev, "Unable to open device due to PF driver failure.\n");
+ return -EIO;
+ }
+
+ while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
+ &adapter->crit_section))
+ usleep_range(500, 1000);
+
+ if (adapter->state != __I40EVF_DOWN) {
+ err = -EBUSY;
+ goto err_unlock;
+ }
+
+ /* allocate transmit descriptors */
+ err = i40evf_setup_all_tx_resources(adapter);
+ if (err)
+ goto err_setup_tx;
+
+ /* allocate receive descriptors */
+ err = i40evf_setup_all_rx_resources(adapter);
+ if (err)
+ goto err_setup_rx;
+
+ /* clear any pending interrupts, may auto mask */
+ err = i40evf_request_traffic_irqs(adapter, netdev->name);
+ if (err)
+ goto err_req_irq;
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ i40evf_add_filter(adapter, adapter->hw.mac.addr);
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ i40evf_configure(adapter);
+
+ i40evf_up_complete(adapter);
+
+ i40evf_irq_enable(adapter, true);
+
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+
+ return 0;
+
+err_req_irq:
+ i40evf_down(adapter);
+ i40evf_free_traffic_irqs(adapter);
+err_setup_rx:
+ i40evf_free_all_rx_resources(adapter);
+err_setup_tx:
+ i40evf_free_all_tx_resources(adapter);
+err_unlock:
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+
+ return err;
+}
+
+/**
+ * i40evf_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. All IRQs except vector 0 (reserved for admin queue)
+ * are freed, along with all transmit and receive resources.
+ **/
+static int i40evf_close(struct net_device *netdev)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ int status;
+
+ if (adapter->state <= __I40EVF_DOWN_PENDING)
+ return 0;
+
+ while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
+ &adapter->crit_section))
+ usleep_range(500, 1000);
+
+ set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
+ if (CLIENT_ENABLED(adapter))
+ adapter->flags |= I40EVF_FLAG_CLIENT_NEEDS_CLOSE;
+
+ i40evf_down(adapter);
+ adapter->state = __I40EVF_DOWN_PENDING;
+ i40evf_free_traffic_irqs(adapter);
+
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+
+ /* We explicitly don't free resources here because the hardware is
+ * still active and can DMA into memory. Resources are cleared in
+ * i40evf_virtchnl_completion() after we get confirmation from the PF
+ * driver that the rings have been stopped.
+ *
+ * Also, we wait for state to transition to __I40EVF_DOWN before
+ * returning. State change occurs in i40evf_virtchnl_completion() after
+ * VF resources are released (which occurs after PF driver processes and
+ * responds to admin queue commands).
+ */
+
+ status = wait_event_timeout(adapter->down_waitqueue,
+ adapter->state == __I40EVF_DOWN,
+ msecs_to_jiffies(200));
+ if (!status)
+ netdev_warn(netdev, "Device resources not yet released\n");
+ return 0;
+}
+
+/**
+ * i40evf_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ netdev->mtu = new_mtu;
+ if (CLIENT_ENABLED(adapter)) {
+ i40evf_notify_client_l2_params(&adapter->vsi);
+ adapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
+ }
+ adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
+ schedule_work(&adapter->reset_task);
+
+ return 0;
+}
+
+/**
+ * i40e_set_features - set the netdev feature flags
+ * @netdev: ptr to the netdev being adjusted
+ * @features: the feature set that the stack is suggesting
+ * Note: expects to be called while under rtnl_lock()
+ **/
+static int i40evf_set_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ /* Don't allow changing VLAN_RX flag when adapter is not capable
+ * of VLAN offload
+ */
+ if (!VLAN_ALLOWED(adapter)) {
+ if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX)
+ return -EINVAL;
+ } else if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX) {
+ if (features & NETIF_F_HW_VLAN_CTAG_RX)
+ adapter->aq_required |=
+ I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING;
+ else
+ adapter->aq_required |=
+ I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING;
+ }
+
+ return 0;
+}
+
+/**
+ * i40evf_features_check - Validate encapsulated packet conforms to limits
+ * @skb: skb buff
+ * @dev: This physical port's netdev
+ * @features: Offload features that the stack believes apply
+ **/
+static netdev_features_t i40evf_features_check(struct sk_buff *skb,
+ struct net_device *dev,
+ netdev_features_t features)
+{
+ size_t len;
+
+ /* No point in doing any of this if neither checksum nor GSO are
+ * being requested for this frame. We can rule out both by just
+ * checking for CHECKSUM_PARTIAL
+ */
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return features;
+
+ /* We cannot support GSO if the MSS is going to be less than
+ * 64 bytes. If it is then we need to drop support for GSO.
+ */
+ if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
+ features &= ~NETIF_F_GSO_MASK;
+
+ /* MACLEN can support at most 63 words */
+ len = skb_network_header(skb) - skb->data;
+ if (len & ~(63 * 2))
+ goto out_err;
+
+ /* IPLEN and EIPLEN can support at most 127 dwords */
+ len = skb_transport_header(skb) - skb_network_header(skb);
+ if (len & ~(127 * 4))
+ goto out_err;
+
+ if (skb->encapsulation) {
+ /* L4TUNLEN can support 127 words */
+ len = skb_inner_network_header(skb) - skb_transport_header(skb);
+ if (len & ~(127 * 2))
+ goto out_err;
+
+ /* IPLEN can support at most 127 dwords */
+ len = skb_inner_transport_header(skb) -
+ skb_inner_network_header(skb);
+ if (len & ~(127 * 4))
+ goto out_err;
+ }
+
+ /* No need to validate L4LEN as TCP is the only protocol with a
+ * a flexible value and we support all possible values supported
+ * by TCP, which is at most 15 dwords
+ */
+
+ return features;
+out_err:
+ return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+}
+
+/**
+ * i40evf_fix_features - fix up the netdev feature bits
+ * @netdev: our net device
+ * @features: desired feature bits
+ *
+ * Returns fixed-up features bits
+ **/
+static netdev_features_t i40evf_fix_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ if (adapter->vf_res &&
+ !(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
+ features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_CTAG_FILTER);
+
+ return features;
+}
+
+static const struct net_device_ops i40evf_netdev_ops = {
+ .ndo_open = i40evf_open,
+ .ndo_stop = i40evf_close,
+ .ndo_start_xmit = i40evf_xmit_frame,
+ .ndo_set_rx_mode = i40evf_set_rx_mode,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = i40evf_set_mac,
+ .ndo_change_mtu = i40evf_change_mtu,
+ .ndo_tx_timeout = i40evf_tx_timeout,
+ .ndo_vlan_rx_add_vid = i40evf_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = i40evf_vlan_rx_kill_vid,
+ .ndo_features_check = i40evf_features_check,
+ .ndo_fix_features = i40evf_fix_features,
+ .ndo_set_features = i40evf_set_features,
+ .ndo_setup_tc = i40evf_setup_tc,
+};
+
+/**
+ * i40evf_check_reset_complete - check that VF reset is complete
+ * @hw: pointer to hw struct
+ *
+ * Returns 0 if device is ready to use, or -EBUSY if it's in reset.
+ **/
+static int i40evf_check_reset_complete(struct i40e_hw *hw)
+{
+ u32 rstat;
+ int i;
+
+ for (i = 0; i < 100; i++) {
+ rstat = rd32(hw, I40E_VFGEN_RSTAT) &
+ I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+ if ((rstat == VIRTCHNL_VFR_VFACTIVE) ||
+ (rstat == VIRTCHNL_VFR_COMPLETED))
+ return 0;
+ usleep_range(10, 20);
+ }
+ return -EBUSY;
+}
+
+/**
+ * i40evf_process_config - Process the config information we got from the PF
+ * @adapter: board private structure
+ *
+ * Verify that we have a valid config struct, and set up our netdev features
+ * and our VSI struct.
+ **/
+int i40evf_process_config(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_vf_resource *vfres = adapter->vf_res;
+ int i, num_req_queues = adapter->num_req_queues;
+ struct net_device *netdev = adapter->netdev;
+ struct i40e_vsi *vsi = &adapter->vsi;
+ netdev_features_t hw_enc_features;
+ netdev_features_t hw_features;
+
+ /* got VF config message back from PF, now we can parse it */
+ for (i = 0; i < vfres->num_vsis; i++) {
+ if (vfres->vsi_res[i].vsi_type == VIRTCHNL_VSI_SRIOV)
+ adapter->vsi_res = &vfres->vsi_res[i];
+ }
+ if (!adapter->vsi_res) {
+ dev_err(&adapter->pdev->dev, "No LAN VSI found\n");
+ return -ENODEV;
+ }
+
+ if (num_req_queues &&
+ num_req_queues != adapter->vsi_res->num_queue_pairs) {
+ /* Problem. The PF gave us fewer queues than what we had
+ * negotiated in our request. Need a reset to see if we can't
+ * get back to a working state.
+ */
+ dev_err(&adapter->pdev->dev,
+ "Requested %d queues, but PF only gave us %d.\n",
+ num_req_queues,
+ adapter->vsi_res->num_queue_pairs);
+ adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
+ adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
+ i40evf_schedule_reset(adapter);
+ return -ENODEV;
+ }
+ adapter->num_req_queues = 0;
+
+ hw_enc_features = NETIF_F_SG |
+ NETIF_F_IP_CSUM |
+ NETIF_F_IPV6_CSUM |
+ NETIF_F_HIGHDMA |
+ NETIF_F_SOFT_FEATURES |
+ NETIF_F_TSO |
+ NETIF_F_TSO_ECN |
+ NETIF_F_TSO6 |
+ NETIF_F_SCTP_CRC |
+ NETIF_F_RXHASH |
+ NETIF_F_RXCSUM |
+ 0;
+
+ /* advertise to stack only if offloads for encapsulated packets is
+ * supported
+ */
+ if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ENCAP) {
+ hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL |
+ NETIF_F_GSO_GRE |
+ NETIF_F_GSO_GRE_CSUM |
+ NETIF_F_GSO_IPXIP4 |
+ NETIF_F_GSO_IPXIP6 |
+ NETIF_F_GSO_UDP_TUNNEL_CSUM |
+ NETIF_F_GSO_PARTIAL |
+ 0;
+
+ if (!(vfres->vf_cap_flags &
+ VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM))
+ netdev->gso_partial_features |=
+ NETIF_F_GSO_UDP_TUNNEL_CSUM;
+
+ netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
+ netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
+ netdev->hw_enc_features |= hw_enc_features;
+ }
+ /* record features VLANs can make use of */
+ netdev->vlan_features |= hw_enc_features | NETIF_F_TSO_MANGLEID;
+
+ /* Write features and hw_features separately to avoid polluting
+ * with, or dropping, features that are set when we registered.
+ */
+ hw_features = hw_enc_features;
+
+ /* Enable VLAN features if supported */
+ if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
+ hw_features |= (NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX);
+ /* Enable cloud filter if ADQ is supported */
+ if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ)
+ hw_features |= NETIF_F_HW_TC;
+
+ netdev->hw_features |= hw_features;
+
+ netdev->features |= hw_features;
+
+ if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
+ netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
+ /* Do not turn on offloads when they are requested to be turned off.
+ * TSO needs minimum 576 bytes to work correctly.
+ */
+ if (netdev->wanted_features) {
+ if (!(netdev->wanted_features & NETIF_F_TSO) ||
+ netdev->mtu < 576)
+ netdev->features &= ~NETIF_F_TSO;
+ if (!(netdev->wanted_features & NETIF_F_TSO6) ||
+ netdev->mtu < 576)
+ netdev->features &= ~NETIF_F_TSO6;
+ if (!(netdev->wanted_features & NETIF_F_TSO_ECN))
+ netdev->features &= ~NETIF_F_TSO_ECN;
+ if (!(netdev->wanted_features & NETIF_F_GRO))
+ netdev->features &= ~NETIF_F_GRO;
+ if (!(netdev->wanted_features & NETIF_F_GSO))
+ netdev->features &= ~NETIF_F_GSO;
+ }
+
+ adapter->vsi.id = adapter->vsi_res->vsi_id;
+
+ adapter->vsi.back = adapter;
+ adapter->vsi.base_vector = 1;
+ adapter->vsi.work_limit = I40E_DEFAULT_IRQ_WORK;
+ vsi->netdev = adapter->netdev;
+ vsi->qs_handle = adapter->vsi_res->qset_handle;
+ if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
+ adapter->rss_key_size = vfres->rss_key_size;
+ adapter->rss_lut_size = vfres->rss_lut_size;
+ } else {
+ adapter->rss_key_size = I40EVF_HKEY_ARRAY_SIZE;
+ adapter->rss_lut_size = I40EVF_HLUT_ARRAY_SIZE;
+ }
+
+ return 0;
+}
+
+/**
+ * i40evf_init_task - worker thread to perform delayed initialization
+ * @work: pointer to work_struct containing our data
+ *
+ * This task completes the work that was begun in probe. Due to the nature
+ * of VF-PF communications, we may need to wait tens of milliseconds to get
+ * responses back from the PF. Rather than busy-wait in probe and bog down the
+ * whole system, we'll do it in a task so we can sleep.
+ * This task only runs during driver init. Once we've established
+ * communications with the PF driver and set up our netdev, the watchdog
+ * takes over.
+ **/
+static void i40evf_init_task(struct work_struct *work)
+{
+ struct i40evf_adapter *adapter = container_of(work,
+ struct i40evf_adapter,
+ init_task.work);
+ struct net_device *netdev = adapter->netdev;
+ struct i40e_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
+ int err, bufsz;
+
+ switch (adapter->state) {
+ case __I40EVF_STARTUP:
+ /* driver loaded, probe complete */
+ adapter->flags &= ~I40EVF_FLAG_PF_COMMS_FAILED;
+ adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
+ err = i40e_set_mac_type(hw);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to set MAC type (%d)\n",
+ err);
+ goto err;
+ }
+ err = i40evf_check_reset_complete(hw);
+ if (err) {
+ dev_info(&pdev->dev, "Device is still in reset (%d), retrying\n",
+ err);
+ goto err;
+ }
+ hw->aq.num_arq_entries = I40EVF_AQ_LEN;
+ hw->aq.num_asq_entries = I40EVF_AQ_LEN;
+ hw->aq.arq_buf_size = I40EVF_MAX_AQ_BUF_SIZE;
+ hw->aq.asq_buf_size = I40EVF_MAX_AQ_BUF_SIZE;
+
+ err = i40evf_init_adminq(hw);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to init Admin Queue (%d)\n",
+ err);
+ goto err;
+ }
+ err = i40evf_send_api_ver(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to send to PF (%d)\n", err);
+ i40evf_shutdown_adminq(hw);
+ goto err;
+ }
+ adapter->state = __I40EVF_INIT_VERSION_CHECK;
+ goto restart;
+ case __I40EVF_INIT_VERSION_CHECK:
+ if (!i40evf_asq_done(hw)) {
+ dev_err(&pdev->dev, "Admin queue command never completed\n");
+ i40evf_shutdown_adminq(hw);
+ adapter->state = __I40EVF_STARTUP;
+ goto err;
+ }
+
+ /* aq msg sent, awaiting reply */
+ err = i40evf_verify_api_ver(adapter);
+ if (err) {
+ if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK)
+ err = i40evf_send_api_ver(adapter);
+ else
+ dev_err(&pdev->dev, "Unsupported PF API version %d.%d, expected %d.%d\n",
+ adapter->pf_version.major,
+ adapter->pf_version.minor,
+ VIRTCHNL_VERSION_MAJOR,
+ VIRTCHNL_VERSION_MINOR);
+ goto err;
+ }
+ err = i40evf_send_vf_config_msg(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to send config request (%d)\n",
+ err);
+ goto err;
+ }
+ adapter->state = __I40EVF_INIT_GET_RESOURCES;
+ goto restart;
+ case __I40EVF_INIT_GET_RESOURCES:
+ /* aq msg sent, awaiting reply */
+ if (!adapter->vf_res) {
+ bufsz = sizeof(struct virtchnl_vf_resource) +
+ (I40E_MAX_VF_VSI *
+ sizeof(struct virtchnl_vsi_resource));
+ adapter->vf_res = kzalloc(bufsz, GFP_KERNEL);
+ if (!adapter->vf_res)
+ goto err;
+ }
+ err = i40evf_get_vf_config(adapter);
+ if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) {
+ err = i40evf_send_vf_config_msg(adapter);
+ goto err;
+ } else if (err == I40E_ERR_PARAM) {
+ /* We only get ERR_PARAM if the device is in a very bad
+ * state or if we've been disabled for previous bad
+ * behavior. Either way, we're done now.
+ */
+ i40evf_shutdown_adminq(hw);
+ dev_err(&pdev->dev, "Unable to get VF config due to PF error condition, not retrying\n");
+ return;
+ }
+ if (err) {
+ dev_err(&pdev->dev, "Unable to get VF config (%d)\n",
+ err);
+ goto err_alloc;
+ }
+ adapter->state = __I40EVF_INIT_SW;
+ break;
+ default:
+ goto err_alloc;
+ }
+
+ if (i40evf_process_config(adapter))
+ goto err_alloc;
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+
+ adapter->flags |= I40EVF_FLAG_RX_CSUM_ENABLED;
+
+ netdev->netdev_ops = &i40evf_netdev_ops;
+ i40evf_set_ethtool_ops(netdev);
+ netdev->watchdog_timeo = 5 * HZ;
+
+ /* MTU range: 68 - 9710 */
+ netdev->min_mtu = ETH_MIN_MTU;
+ netdev->max_mtu = I40E_MAX_RXBUFFER - I40E_PACKET_HDR_PAD;
+
+ if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
+ dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n",
+ adapter->hw.mac.addr);
+ eth_hw_addr_random(netdev);
+ ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
+ } else {
+ adapter->flags |= I40EVF_FLAG_ADDR_SET_BY_PF;
+ ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
+ ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr);
+ }
+
+ timer_setup(&adapter->watchdog_timer, i40evf_watchdog_timer, 0);
+ mod_timer(&adapter->watchdog_timer, jiffies + 1);
+
+ adapter->tx_desc_count = I40EVF_DEFAULT_TXD;
+ adapter->rx_desc_count = I40EVF_DEFAULT_RXD;
+ err = i40evf_init_interrupt_scheme(adapter);
+ if (err)
+ goto err_sw_init;
+ i40evf_map_rings_to_vectors(adapter);
+ if (adapter->vf_res->vf_cap_flags &
+ VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
+ adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE;
+
+ err = i40evf_request_misc_irq(adapter);
+ if (err)
+ goto err_sw_init;
+
+ netif_carrier_off(netdev);
+ adapter->link_up = false;
+
+ if (!adapter->netdev_registered) {
+ err = register_netdev(netdev);
+ if (err)
+ goto err_register;
+ }
+
+ adapter->netdev_registered = true;
+
+ netif_tx_stop_all_queues(netdev);
+ if (CLIENT_ALLOWED(adapter)) {
+ err = i40evf_lan_add_device(adapter);
+ if (err)
+ dev_info(&pdev->dev, "Failed to add VF to client API service list: %d\n",
+ err);
+ }
+
+ dev_info(&pdev->dev, "MAC address: %pM\n", adapter->hw.mac.addr);
+ if (netdev->features & NETIF_F_GRO)
+ dev_info(&pdev->dev, "GRO is enabled\n");
+
+ adapter->state = __I40EVF_DOWN;
+ set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
+ i40evf_misc_irq_enable(adapter);
+ wake_up(&adapter->down_waitqueue);
+
+ adapter->rss_key = kzalloc(adapter->rss_key_size, GFP_KERNEL);
+ adapter->rss_lut = kzalloc(adapter->rss_lut_size, GFP_KERNEL);
+ if (!adapter->rss_key || !adapter->rss_lut)
+ goto err_mem;
+
+ if (RSS_AQ(adapter)) {
+ adapter->aq_required |= I40EVF_FLAG_AQ_CONFIGURE_RSS;
+ mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
+ } else {
+ i40evf_init_rss(adapter);
+ }
+ return;
+restart:
+ schedule_delayed_work(&adapter->init_task, msecs_to_jiffies(30));
+ return;
+err_mem:
+ i40evf_free_rss(adapter);
+err_register:
+ i40evf_free_misc_irq(adapter);
+err_sw_init:
+ i40evf_reset_interrupt_capability(adapter);
+err_alloc:
+ kfree(adapter->vf_res);
+ adapter->vf_res = NULL;
+err:
+ /* Things went into the weeds, so try again later */
+ if (++adapter->aq_wait_count > I40EVF_AQ_MAX_ERR) {
+ dev_err(&pdev->dev, "Failed to communicate with PF; waiting before retry\n");
+ adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
+ i40evf_shutdown_adminq(hw);
+ adapter->state = __I40EVF_STARTUP;
+ schedule_delayed_work(&adapter->init_task, HZ * 5);
+ return;
+ }
+ schedule_delayed_work(&adapter->init_task, HZ);
+}
+
+/**
+ * i40evf_shutdown - Shutdown the device in preparation for a reboot
+ * @pdev: pci device structure
+ **/
+static void i40evf_shutdown(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev))
+ i40evf_close(netdev);
+
+ /* Prevent the watchdog from running. */
+ adapter->state = __I40EVF_REMOVE;
+ adapter->aq_required = 0;
+
+#ifdef CONFIG_PM
+ pci_save_state(pdev);
+
+#endif
+ pci_disable_device(pdev);
+}
+
+/**
+ * i40evf_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in i40evf_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * i40evf_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ **/
+static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct net_device *netdev;
+ struct i40evf_adapter *adapter = NULL;
+ struct i40e_hw *hw = NULL;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (err) {
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (err) {
+ dev_err(&pdev->dev,
+ "DMA configuration failed: 0x%x\n", err);
+ goto err_dma;
+ }
+ }
+
+ err = pci_request_regions(pdev, i40evf_driver_name);
+ if (err) {
+ dev_err(&pdev->dev,
+ "pci_request_regions failed 0x%x\n", err);
+ goto err_pci_reg;
+ }
+
+ pci_enable_pcie_error_reporting(pdev);
+
+ pci_set_master(pdev);
+
+ netdev = alloc_etherdev_mq(sizeof(struct i40evf_adapter),
+ I40EVF_MAX_REQ_QUEUES);
+ if (!netdev) {
+ err = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ pci_set_drvdata(pdev, netdev);
+ adapter = netdev_priv(netdev);
+
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
+
+ hw = &adapter->hw;
+ hw->back = adapter;
+
+ adapter->msg_enable = BIT(DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
+ adapter->state = __I40EVF_STARTUP;
+
+ /* Call save state here because it relies on the adapter struct. */
+ pci_save_state(pdev);
+
+ hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (!hw->hw_addr) {
+ err = -EIO;
+ goto err_ioremap;
+ }
+ hw->vendor_id = pdev->vendor;
+ hw->device_id = pdev->device;
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+ hw->subsystem_vendor_id = pdev->subsystem_vendor;
+ hw->subsystem_device_id = pdev->subsystem_device;
+ hw->bus.device = PCI_SLOT(pdev->devfn);
+ hw->bus.func = PCI_FUNC(pdev->devfn);
+ hw->bus.bus_id = pdev->bus->number;
+
+ /* set up the locks for the AQ, do this only once in probe
+ * and destroy them only once in remove
+ */
+ mutex_init(&hw->aq.asq_mutex);
+ mutex_init(&hw->aq.arq_mutex);
+
+ spin_lock_init(&adapter->mac_vlan_list_lock);
+ spin_lock_init(&adapter->cloud_filter_list_lock);
+
+ INIT_LIST_HEAD(&adapter->mac_filter_list);
+ INIT_LIST_HEAD(&adapter->vlan_filter_list);
+ INIT_LIST_HEAD(&adapter->cloud_filter_list);
+
+ INIT_WORK(&adapter->reset_task, i40evf_reset_task);
+ INIT_WORK(&adapter->adminq_task, i40evf_adminq_task);
+ INIT_WORK(&adapter->watchdog_task, i40evf_watchdog_task);
+ INIT_DELAYED_WORK(&adapter->client_task, i40evf_client_task);
+ INIT_DELAYED_WORK(&adapter->init_task, i40evf_init_task);
+ schedule_delayed_work(&adapter->init_task,
+ msecs_to_jiffies(5 * (pdev->devfn & 0x07)));
+
+ /* Setup the wait queue for indicating transition to down status */
+ init_waitqueue_head(&adapter->down_waitqueue);
+
+ return 0;
+
+err_ioremap:
+ free_netdev(netdev);
+err_alloc_etherdev:
+ pci_disable_pcie_error_reporting(pdev);
+ pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+ pci_disable_device(pdev);
+ return err;
+}
+
+#ifdef CONFIG_PM
+/**
+ * i40evf_suspend - Power management suspend routine
+ * @pdev: PCI device information struct
+ * @state: unused
+ *
+ * Called when the system (VM) is entering sleep/suspend.
+ **/
+static int i40evf_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ int retval = 0;
+
+ netif_device_detach(netdev);
+
+ while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
+ &adapter->crit_section))
+ usleep_range(500, 1000);
+
+ if (netif_running(netdev)) {
+ rtnl_lock();
+ i40evf_down(adapter);
+ rtnl_unlock();
+ }
+ i40evf_free_misc_irq(adapter);
+ i40evf_reset_interrupt_capability(adapter);
+
+ clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+
+ retval = pci_save_state(pdev);
+ if (retval)
+ return retval;
+
+ pci_disable_device(pdev);
+
+ return 0;
+}
+
+/**
+ * i40evf_resume - Power management resume routine
+ * @pdev: PCI device information struct
+ *
+ * Called when the system (VM) is resumed from sleep/suspend.
+ **/
+static int i40evf_resume(struct pci_dev *pdev)
+{
+ struct i40evf_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+ u32 err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ /* pci_restore_state clears dev->state_saved so call
+ * pci_save_state to restore it.
+ */
+ pci_save_state(pdev);
+
+ err = pci_enable_device_mem(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "Cannot enable PCI device from suspend.\n");
+ return err;
+ }
+ pci_set_master(pdev);
+
+ rtnl_lock();
+ err = i40evf_set_interrupt_capability(adapter);
+ if (err) {
+ rtnl_unlock();
+ dev_err(&pdev->dev, "Cannot enable MSI-X interrupts.\n");
+ return err;
+ }
+ err = i40evf_request_misc_irq(adapter);
+ rtnl_unlock();
+ if (err) {
+ dev_err(&pdev->dev, "Cannot get interrupt vector.\n");
+ return err;
+ }
+
+ schedule_work(&adapter->reset_task);
+
+ netif_device_attach(netdev);
+
+ return err;
+}
+
+#endif /* CONFIG_PM */
+/**
+ * i40evf_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * i40evf_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device. The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ **/
+static void i40evf_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct i40evf_adapter *adapter = netdev_priv(netdev);
+ struct i40evf_vlan_filter *vlf, *vlftmp;
+ struct i40evf_mac_filter *f, *ftmp;
+ struct i40evf_cloud_filter *cf, *cftmp;
+ struct i40e_hw *hw = &adapter->hw;
+ int err;
+ /* Indicate we are in remove and not to run reset_task */
+ set_bit(__I40EVF_IN_REMOVE_TASK, &adapter->crit_section);
+ cancel_delayed_work_sync(&adapter->init_task);
+ cancel_work_sync(&adapter->reset_task);
+ cancel_delayed_work_sync(&adapter->client_task);
+ if (adapter->netdev_registered) {
+ unregister_netdev(netdev);
+ adapter->netdev_registered = false;
+ }
+ if (CLIENT_ALLOWED(adapter)) {
+ err = i40evf_lan_del_device(adapter);
+ if (err)
+ dev_warn(&pdev->dev, "Failed to delete client device: %d\n",
+ err);
+ }
+
+ /* Shut down all the garbage mashers on the detention level */
+ adapter->state = __I40EVF_REMOVE;
+ adapter->aq_required = 0;
+ adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
+ i40evf_request_reset(adapter);
+ msleep(50);
+ /* If the FW isn't responding, kick it once, but only once. */
+ if (!i40evf_asq_done(hw)) {
+ i40evf_request_reset(adapter);
+ msleep(50);
+ }
+ i40evf_free_all_tx_resources(adapter);
+ i40evf_free_all_rx_resources(adapter);
+ i40evf_misc_irq_disable(adapter);
+ i40evf_free_misc_irq(adapter);
+ i40evf_reset_interrupt_capability(adapter);
+ i40evf_free_q_vectors(adapter);
+
+ if (adapter->watchdog_timer.function)
+ del_timer_sync(&adapter->watchdog_timer);
+
+ cancel_work_sync(&adapter->adminq_task);
+
+ i40evf_free_rss(adapter);
+
+ if (hw->aq.asq.count)
+ i40evf_shutdown_adminq(hw);
+
+ /* destroy the locks only once, here */
+ mutex_destroy(&hw->aq.arq_mutex);
+ mutex_destroy(&hw->aq.asq_mutex);
+
+ iounmap(hw->hw_addr);
+ pci_release_regions(pdev);
+ i40evf_free_all_tx_resources(adapter);
+ i40evf_free_all_rx_resources(adapter);
+ i40evf_free_queues(adapter);
+ kfree(adapter->vf_res);
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+ /* If we got removed before an up/down sequence, we've got a filter
+ * hanging out there that we need to get rid of.
+ */
+ list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+ list_del(&f->list);
+ kfree(f);
+ }
+ list_for_each_entry_safe(vlf, vlftmp, &adapter->vlan_filter_list,
+ list) {
+ list_del(&vlf->list);
+ kfree(vlf);
+ }
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ spin_lock_bh(&adapter->cloud_filter_list_lock);
+ list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {
+ list_del(&cf->list);
+ kfree(cf);
+ }
+ spin_unlock_bh(&adapter->cloud_filter_list_lock);
+
+ free_netdev(netdev);
+
+ pci_disable_pcie_error_reporting(pdev);
+
+ pci_disable_device(pdev);
+}
+
+static struct pci_driver i40evf_driver = {
+ .name = i40evf_driver_name,
+ .id_table = i40evf_pci_tbl,
+ .probe = i40evf_probe,
+ .remove = i40evf_remove,
+#ifdef CONFIG_PM
+ .suspend = i40evf_suspend,
+ .resume = i40evf_resume,
+#endif
+ .shutdown = i40evf_shutdown,
+};
+
+/**
+ * i40e_init_module - Driver Registration Routine
+ *
+ * i40e_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ **/
+static int __init i40evf_init_module(void)
+{
+ int ret;
+
+ pr_info("i40evf: %s - version %s\n", i40evf_driver_string,
+ i40evf_driver_version);
+
+ pr_info("%s\n", i40evf_copyright);
+
+ i40evf_wq = alloc_workqueue("%s", WQ_UNBOUND | WQ_MEM_RECLAIM, 1,
+ i40evf_driver_name);
+ if (!i40evf_wq) {
+ pr_err("%s: Failed to create workqueue\n", i40evf_driver_name);
+ return -ENOMEM;
+ }
+ ret = pci_register_driver(&i40evf_driver);
+ return ret;
+}
+
+module_init(i40evf_init_module);
+
+/**
+ * i40e_exit_module - Driver Exit Cleanup Routine
+ *
+ * i40e_exit_module is called just before the driver is removed
+ * from memory.
+ **/
+static void __exit i40evf_exit_module(void)
+{
+ pci_unregister_driver(&i40evf_driver);
+ destroy_workqueue(i40evf_wq);
+}
+
+module_exit(i40evf_exit_module);
+
+/* i40evf_main.c */
diff --git a/drivers/net/ethernet/intel/iavf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/iavf/i40evf_virtchnl.c
new file mode 100644
index 000000000000..6579dabab78c
--- /dev/null
+++ b/drivers/net/ethernet/intel/iavf/i40evf_virtchnl.c
@@ -0,0 +1,1465 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2013 - 2018 Intel Corporation. */
+
+#include "i40evf.h"
+#include "i40e_prototype.h"
+#include "i40evf_client.h"
+
+/* busy wait delay in msec */
+#define I40EVF_BUSY_WAIT_DELAY 10
+#define I40EVF_BUSY_WAIT_COUNT 50
+
+/**
+ * i40evf_send_pf_msg
+ * @adapter: adapter structure
+ * @op: virtual channel opcode
+ * @msg: pointer to message buffer
+ * @len: message length
+ *
+ * Send message to PF and print status if failure.
+ **/
+static int i40evf_send_pf_msg(struct i40evf_adapter *adapter,
+ enum virtchnl_ops op, u8 *msg, u16 len)
+{
+ struct i40e_hw *hw = &adapter->hw;
+ i40e_status err;
+
+ if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED)
+ return 0; /* nothing to see here, move along */
+
+ err = i40e_aq_send_msg_to_pf(hw, op, 0, msg, len, NULL);
+ if (err)
+ dev_dbg(&adapter->pdev->dev, "Unable to send opcode %d to PF, err %s, aq_err %s\n",
+ op, i40evf_stat_str(hw, err),
+ i40evf_aq_str(hw, hw->aq.asq_last_status));
+ return err;
+}
+
+/**
+ * i40evf_send_api_ver
+ * @adapter: adapter structure
+ *
+ * Send API version admin queue message to the PF. The reply is not checked
+ * in this function. Returns 0 if the message was successfully
+ * sent, or one of the I40E_ADMIN_QUEUE_ERROR_ statuses if not.
+ **/
+int i40evf_send_api_ver(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_version_info vvi;
+
+ vvi.major = VIRTCHNL_VERSION_MAJOR;
+ vvi.minor = VIRTCHNL_VERSION_MINOR;
+
+ return i40evf_send_pf_msg(adapter, VIRTCHNL_OP_VERSION, (u8 *)&vvi,
+ sizeof(vvi));
+}
+
+/**
+ * i40evf_verify_api_ver
+ * @adapter: adapter structure
+ *
+ * Compare API versions with the PF. Must be called after admin queue is
+ * initialized. Returns 0 if API versions match, -EIO if they do not,
+ * I40E_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty, and any errors
+ * from the firmware are propagated.
+ **/
+int i40evf_verify_api_ver(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_version_info *pf_vvi;
+ struct i40e_hw *hw = &adapter->hw;
+ struct i40e_arq_event_info event;
+ enum virtchnl_ops op;
+ i40e_status err;
+
+ event.buf_len = I40EVF_MAX_AQ_BUF_SIZE;
+ event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
+ if (!event.msg_buf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ while (1) {
+ err = i40evf_clean_arq_element(hw, &event, NULL);
+ /* When the AQ is empty, i40evf_clean_arq_element will return
+ * nonzero and this loop will terminate.
+ */
+ if (err)
+ goto out_alloc;
+ op =
+ (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
+ if (op == VIRTCHNL_OP_VERSION)
+ break;
+ }
+
+
+ err = (i40e_status)le32_to_cpu(event.desc.cookie_low);
+ if (err)
+ goto out_alloc;
+
+ if (op != VIRTCHNL_OP_VERSION) {
+ dev_info(&adapter->pdev->dev, "Invalid reply type %d from PF\n",
+ op);
+ err = -EIO;
+ goto out_alloc;
+ }
+
+ pf_vvi = (struct virtchnl_version_info *)event.msg_buf;
+ adapter->pf_version = *pf_vvi;
+
+ if ((pf_vvi->major > VIRTCHNL_VERSION_MAJOR) ||
+ ((pf_vvi->major == VIRTCHNL_VERSION_MAJOR) &&
+ (pf_vvi->minor > VIRTCHNL_VERSION_MINOR)))
+ err = -EIO;
+
+out_alloc:
+ kfree(event.msg_buf);
+out:
+ return err;
+}
+
+/**
+ * i40evf_send_vf_config_msg
+ * @adapter: adapter structure
+ *
+ * Send VF configuration request admin queue message to the PF. The reply
+ * is not checked in this function. Returns 0 if the message was
+ * successfully sent, or one of the I40E_ADMIN_QUEUE_ERROR_ statuses if not.
+ **/
+int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
+{
+ u32 caps;
+
+ caps = VIRTCHNL_VF_OFFLOAD_L2 |
+ VIRTCHNL_VF_OFFLOAD_RSS_PF |
+ VIRTCHNL_VF_OFFLOAD_RSS_AQ |
+ VIRTCHNL_VF_OFFLOAD_RSS_REG |
+ VIRTCHNL_VF_OFFLOAD_VLAN |
+ VIRTCHNL_VF_OFFLOAD_WB_ON_ITR |
+ VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 |
+ VIRTCHNL_VF_OFFLOAD_ENCAP |
+ VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
+ VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
+ VIRTCHNL_VF_OFFLOAD_ADQ;
+
+ adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG;
+ if (PF_IS_V11(adapter))
+ return i40evf_send_pf_msg(adapter,
+ VIRTCHNL_OP_GET_VF_RESOURCES,
+ (u8 *)&caps, sizeof(caps));
+ else
+ return i40evf_send_pf_msg(adapter,
+ VIRTCHNL_OP_GET_VF_RESOURCES,
+ NULL, 0);
+}
+
+/**
+ * i40evf_validate_num_queues
+ * @adapter: adapter structure
+ *
+ * Validate that the number of queues the PF has sent in
+ * VIRTCHNL_OP_GET_VF_RESOURCES is not larger than the VF can handle.
+ **/
+static void i40evf_validate_num_queues(struct i40evf_adapter *adapter)
+{
+ if (adapter->vf_res->num_queue_pairs > I40EVF_MAX_REQ_QUEUES) {
+ struct virtchnl_vsi_resource *vsi_res;
+ int i;
+
+ dev_info(&adapter->pdev->dev, "Received %d queues, but can only have a max of %d\n",
+ adapter->vf_res->num_queue_pairs,
+ I40EVF_MAX_REQ_QUEUES);
+ dev_info(&adapter->pdev->dev, "Fixing by reducing queues to %d\n",
+ I40EVF_MAX_REQ_QUEUES);
+ adapter->vf_res->num_queue_pairs = I40EVF_MAX_REQ_QUEUES;
+ for (i = 0; i < adapter->vf_res->num_vsis; i++) {
+ vsi_res = &adapter->vf_res->vsi_res[i];
+ vsi_res->num_queue_pairs = I40EVF_MAX_REQ_QUEUES;
+ }
+ }
+}
+
+/**
+ * i40evf_get_vf_config
+ * @adapter: private adapter structure
+ *
+ * Get VF configuration from PF and populate hw structure. Must be called after
+ * admin queue is initialized. Busy waits until response is received from PF,
+ * with maximum timeout. Response from PF is returned in the buffer for further
+ * processing by the caller.
+ **/
+int i40evf_get_vf_config(struct i40evf_adapter *adapter)
+{
+ struct i40e_hw *hw = &adapter->hw;
+ struct i40e_arq_event_info event;
+ enum virtchnl_ops op;
+ i40e_status err;
+ u16 len;
+
+ len = sizeof(struct virtchnl_vf_resource) +
+ I40E_MAX_VF_VSI * sizeof(struct virtchnl_vsi_resource);
+ event.buf_len = len;
+ event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
+ if (!event.msg_buf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ while (1) {
+ /* When the AQ is empty, i40evf_clean_arq_element will return
+ * nonzero and this loop will terminate.
+ */
+ err = i40evf_clean_arq_element(hw, &event, NULL);
+ if (err)
+ goto out_alloc;
+ op =
+ (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
+ if (op == VIRTCHNL_OP_GET_VF_RESOURCES)
+ break;
+ }
+
+ err = (i40e_status)le32_to_cpu(event.desc.cookie_low);
+ memcpy(adapter->vf_res, event.msg_buf, min(event.msg_len, len));
+
+ /* some PFs send more queues than we should have so validate that
+ * we aren't getting too many queues
+ */
+ if (!err)
+ i40evf_validate_num_queues(adapter);
+ i40e_vf_parse_hw_config(hw, adapter->vf_res);
+out_alloc:
+ kfree(event.msg_buf);
+out:
+ return err;
+}
+
+/**
+ * i40evf_configure_queues
+ * @adapter: adapter structure
+ *
+ * Request that the PF set up our (previously allocated) queues.
+ **/
+void i40evf_configure_queues(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_vsi_queue_config_info *vqci;
+ struct virtchnl_queue_pair_info *vqpi;
+ int pairs = adapter->num_active_queues;
+ int i, len, max_frame = I40E_MAX_RXBUFFER;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot configure queues, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_CONFIG_VSI_QUEUES;
+ len = sizeof(struct virtchnl_vsi_queue_config_info) +
+ (sizeof(struct virtchnl_queue_pair_info) * pairs);
+ vqci = kzalloc(len, GFP_KERNEL);
+ if (!vqci)
+ return;
+
+ /* Limit maximum frame size when jumbo frames is not enabled */
+ if (!(adapter->flags & I40EVF_FLAG_LEGACY_RX) &&
+ (adapter->netdev->mtu <= ETH_DATA_LEN))
+ max_frame = I40E_RXBUFFER_1536 - NET_IP_ALIGN;
+
+ vqci->vsi_id = adapter->vsi_res->vsi_id;
+ vqci->num_queue_pairs = pairs;
+ vqpi = vqci->qpair;
+ /* Size check is not needed here - HW max is 16 queue pairs, and we
+ * can fit info for 31 of them into the AQ buffer before it overflows.
+ */
+ for (i = 0; i < pairs; i++) {
+ vqpi->txq.vsi_id = vqci->vsi_id;
+ vqpi->txq.queue_id = i;
+ vqpi->txq.ring_len = adapter->tx_rings[i].count;
+ vqpi->txq.dma_ring_addr = adapter->tx_rings[i].dma;
+ vqpi->rxq.vsi_id = vqci->vsi_id;
+ vqpi->rxq.queue_id = i;
+ vqpi->rxq.ring_len = adapter->rx_rings[i].count;
+ vqpi->rxq.dma_ring_addr = adapter->rx_rings[i].dma;
+ vqpi->rxq.max_pkt_size = max_frame;
+ vqpi->rxq.databuffer_size =
+ ALIGN(adapter->rx_rings[i].rx_buf_len,
+ BIT_ULL(I40E_RXQ_CTX_DBUFF_SHIFT));
+ vqpi++;
+ }
+
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
+ (u8 *)vqci, len);
+ kfree(vqci);
+}
+
+/**
+ * i40evf_enable_queues
+ * @adapter: adapter structure
+ *
+ * Request that the PF enable all of our queues.
+ **/
+void i40evf_enable_queues(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_queue_select vqs;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot enable queues, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_ENABLE_QUEUES;
+ vqs.vsi_id = adapter->vsi_res->vsi_id;
+ vqs.tx_queues = BIT(adapter->num_active_queues) - 1;
+ vqs.rx_queues = vqs.tx_queues;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_QUEUES;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_QUEUES,
+ (u8 *)&vqs, sizeof(vqs));
+}
+
+/**
+ * i40evf_disable_queues
+ * @adapter: adapter structure
+ *
+ * Request that the PF disable all of our queues.
+ **/
+void i40evf_disable_queues(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_queue_select vqs;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot disable queues, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_DISABLE_QUEUES;
+ vqs.vsi_id = adapter->vsi_res->vsi_id;
+ vqs.tx_queues = BIT(adapter->num_active_queues) - 1;
+ vqs.rx_queues = vqs.tx_queues;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_QUEUES;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_QUEUES,
+ (u8 *)&vqs, sizeof(vqs));
+}
+
+/**
+ * i40evf_map_queues
+ * @adapter: adapter structure
+ *
+ * Request that the PF map queues to interrupt vectors. Misc causes, including
+ * admin queue, are always mapped to vector 0.
+ **/
+void i40evf_map_queues(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_irq_map_info *vimi;
+ struct virtchnl_vector_map *vecmap;
+ int v_idx, q_vectors, len;
+ struct i40e_q_vector *q_vector;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot map queues to vectors, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_CONFIG_IRQ_MAP;
+
+ q_vectors = adapter->num_msix_vectors - NONQ_VECS;
+
+ len = sizeof(struct virtchnl_irq_map_info) +
+ (adapter->num_msix_vectors *
+ sizeof(struct virtchnl_vector_map));
+ vimi = kzalloc(len, GFP_KERNEL);
+ if (!vimi)
+ return;
+
+ vimi->num_vectors = adapter->num_msix_vectors;
+ /* Queue vectors first */
+ for (v_idx = 0; v_idx < q_vectors; v_idx++) {
+ q_vector = &adapter->q_vectors[v_idx];
+ vecmap = &vimi->vecmap[v_idx];
+
+ vecmap->vsi_id = adapter->vsi_res->vsi_id;
+ vecmap->vector_id = v_idx + NONQ_VECS;
+ vecmap->txq_map = q_vector->ring_mask;
+ vecmap->rxq_map = q_vector->ring_mask;
+ vecmap->rxitr_idx = I40E_RX_ITR;
+ vecmap->txitr_idx = I40E_TX_ITR;
+ }
+ /* Misc vector last - this is only for AdminQ messages */
+ vecmap = &vimi->vecmap[v_idx];
+ vecmap->vsi_id = adapter->vsi_res->vsi_id;
+ vecmap->vector_id = 0;
+ vecmap->txq_map = 0;
+ vecmap->rxq_map = 0;
+
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_MAP_VECTORS;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_IRQ_MAP,
+ (u8 *)vimi, len);
+ kfree(vimi);
+}
+
+/**
+ * i40evf_request_queues
+ * @adapter: adapter structure
+ * @num: number of requested queues
+ *
+ * We get a default number of queues from the PF. This enables us to request a
+ * different number. Returns 0 on success, negative on failure
+ **/
+int i40evf_request_queues(struct i40evf_adapter *adapter, int num)
+{
+ struct virtchnl_vf_res_request vfres;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot request queues, command %d pending\n",
+ adapter->current_op);
+ return -EBUSY;
+ }
+
+ vfres.num_queue_pairs = num;
+
+ adapter->current_op = VIRTCHNL_OP_REQUEST_QUEUES;
+ adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
+ return i40evf_send_pf_msg(adapter, VIRTCHNL_OP_REQUEST_QUEUES,
+ (u8 *)&vfres, sizeof(vfres));
+}
+
+/**
+ * i40evf_add_ether_addrs
+ * @adapter: adapter structure
+ *
+ * Request that the PF add one or more addresses to our filters.
+ **/
+void i40evf_add_ether_addrs(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_ether_addr_list *veal;
+ int len, i = 0, count = 0;
+ struct i40evf_mac_filter *f;
+ bool more = false;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot add filters, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ list_for_each_entry(f, &adapter->mac_filter_list, list) {
+ if (f->add)
+ count++;
+ }
+ if (!count) {
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_ADD_ETH_ADDR;
+
+ len = sizeof(struct virtchnl_ether_addr_list) +
+ (count * sizeof(struct virtchnl_ether_addr));
+ if (len > I40EVF_MAX_AQ_BUF_SIZE) {
+ dev_warn(&adapter->pdev->dev, "Too many add MAC changes in one request\n");
+ count = (I40EVF_MAX_AQ_BUF_SIZE -
+ sizeof(struct virtchnl_ether_addr_list)) /
+ sizeof(struct virtchnl_ether_addr);
+ len = sizeof(struct virtchnl_ether_addr_list) +
+ (count * sizeof(struct virtchnl_ether_addr));
+ more = true;
+ }
+
+ veal = kzalloc(len, GFP_ATOMIC);
+ if (!veal) {
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return;
+ }
+
+ veal->vsi_id = adapter->vsi_res->vsi_id;
+ veal->num_elements = count;
+ list_for_each_entry(f, &adapter->mac_filter_list, list) {
+ if (f->add) {
+ ether_addr_copy(veal->list[i].addr, f->macaddr);
+ i++;
+ f->add = false;
+ if (i == count)
+ break;
+ }
+ }
+ if (!more)
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_ETH_ADDR,
+ (u8 *)veal, len);
+ kfree(veal);
+}
+
+/**
+ * i40evf_del_ether_addrs
+ * @adapter: adapter structure
+ *
+ * Request that the PF remove one or more addresses from our filters.
+ **/
+void i40evf_del_ether_addrs(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_ether_addr_list *veal;
+ struct i40evf_mac_filter *f, *ftmp;
+ int len, i = 0, count = 0;
+ bool more = false;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot remove filters, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ list_for_each_entry(f, &adapter->mac_filter_list, list) {
+ if (f->remove)
+ count++;
+ }
+ if (!count) {
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_DEL_ETH_ADDR;
+
+ len = sizeof(struct virtchnl_ether_addr_list) +
+ (count * sizeof(struct virtchnl_ether_addr));
+ if (len > I40EVF_MAX_AQ_BUF_SIZE) {
+ dev_warn(&adapter->pdev->dev, "Too many delete MAC changes in one request\n");
+ count = (I40EVF_MAX_AQ_BUF_SIZE -
+ sizeof(struct virtchnl_ether_addr_list)) /
+ sizeof(struct virtchnl_ether_addr);
+ len = sizeof(struct virtchnl_ether_addr_list) +
+ (count * sizeof(struct virtchnl_ether_addr));
+ more = true;
+ }
+ veal = kzalloc(len, GFP_ATOMIC);
+ if (!veal) {
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return;
+ }
+
+ veal->vsi_id = adapter->vsi_res->vsi_id;
+ veal->num_elements = count;
+ list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+ if (f->remove) {
+ ether_addr_copy(veal->list[i].addr, f->macaddr);
+ i++;
+ list_del(&f->list);
+ kfree(f);
+ if (i == count)
+ break;
+ }
+ }
+ if (!more)
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_ETH_ADDR,
+ (u8 *)veal, len);
+ kfree(veal);
+}
+
+/**
+ * i40evf_add_vlans
+ * @adapter: adapter structure
+ *
+ * Request that the PF add one or more VLAN filters to our VSI.
+ **/
+void i40evf_add_vlans(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_vlan_filter_list *vvfl;
+ int len, i = 0, count = 0;
+ struct i40evf_vlan_filter *f;
+ bool more = false;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot add VLANs, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+ if (f->add)
+ count++;
+ }
+ if (!count) {
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_ADD_VLAN;
+
+ len = sizeof(struct virtchnl_vlan_filter_list) +
+ (count * sizeof(u16));
+ if (len > I40EVF_MAX_AQ_BUF_SIZE) {
+ dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
+ count = (I40EVF_MAX_AQ_BUF_SIZE -
+ sizeof(struct virtchnl_vlan_filter_list)) /
+ sizeof(u16);
+ len = sizeof(struct virtchnl_vlan_filter_list) +
+ (count * sizeof(u16));
+ more = true;
+ }
+ vvfl = kzalloc(len, GFP_ATOMIC);
+ if (!vvfl) {
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return;
+ }
+
+ vvfl->vsi_id = adapter->vsi_res->vsi_id;
+ vvfl->num_elements = count;
+ list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+ if (f->add) {
+ vvfl->vlan_id[i] = f->vlan;
+ i++;
+ f->add = false;
+ if (i == count)
+ break;
+ }
+ }
+ if (!more)
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
+ kfree(vvfl);
+}
+
+/**
+ * i40evf_del_vlans
+ * @adapter: adapter structure
+ *
+ * Request that the PF remove one or more VLAN filters from our VSI.
+ **/
+void i40evf_del_vlans(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_vlan_filter_list *vvfl;
+ struct i40evf_vlan_filter *f, *ftmp;
+ int len, i = 0, count = 0;
+ bool more = false;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot remove VLANs, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+ list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+ if (f->remove)
+ count++;
+ }
+ if (!count) {
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_DEL_VLAN;
+
+ len = sizeof(struct virtchnl_vlan_filter_list) +
+ (count * sizeof(u16));
+ if (len > I40EVF_MAX_AQ_BUF_SIZE) {
+ dev_warn(&adapter->pdev->dev, "Too many delete VLAN changes in one request\n");
+ count = (I40EVF_MAX_AQ_BUF_SIZE -
+ sizeof(struct virtchnl_vlan_filter_list)) /
+ sizeof(u16);
+ len = sizeof(struct virtchnl_vlan_filter_list) +
+ (count * sizeof(u16));
+ more = true;
+ }
+ vvfl = kzalloc(len, GFP_ATOMIC);
+ if (!vvfl) {
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return;
+ }
+
+ vvfl->vsi_id = adapter->vsi_res->vsi_id;
+ vvfl->num_elements = count;
+ list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
+ if (f->remove) {
+ vvfl->vlan_id[i] = f->vlan;
+ i++;
+ list_del(&f->list);
+ kfree(f);
+ if (i == count)
+ break;
+ }
+ }
+ if (!more)
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
+ kfree(vvfl);
+}
+
+/**
+ * i40evf_set_promiscuous
+ * @adapter: adapter structure
+ * @flags: bitmask to control unicast/multicast promiscuous.
+ *
+ * Request that the PF enable promiscuous mode for our VSI.
+ **/
+void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags)
+{
+ struct virtchnl_promisc_info vpi;
+ int promisc_all;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot set promiscuous mode, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ promisc_all = FLAG_VF_UNICAST_PROMISC |
+ FLAG_VF_MULTICAST_PROMISC;
+ if ((flags & promisc_all) == promisc_all) {
+ adapter->flags |= I40EVF_FLAG_PROMISC_ON;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_REQUEST_PROMISC;
+ dev_info(&adapter->pdev->dev, "Entering promiscuous mode\n");
+ }
+
+ if (flags & FLAG_VF_MULTICAST_PROMISC) {
+ adapter->flags |= I40EVF_FLAG_ALLMULTI_ON;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_REQUEST_ALLMULTI;
+ dev_info(&adapter->pdev->dev, "Entering multicast promiscuous mode\n");
+ }
+
+ if (!flags) {
+ adapter->flags &= ~(I40EVF_FLAG_PROMISC_ON |
+ I40EVF_FLAG_ALLMULTI_ON);
+ adapter->aq_required &= ~(I40EVF_FLAG_AQ_RELEASE_PROMISC |
+ I40EVF_FLAG_AQ_RELEASE_ALLMULTI);
+ dev_info(&adapter->pdev->dev, "Leaving promiscuous mode\n");
+ }
+
+ adapter->current_op = VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE;
+ vpi.vsi_id = adapter->vsi_res->vsi_id;
+ vpi.flags = flags;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
+ (u8 *)&vpi, sizeof(vpi));
+}
+
+/**
+ * i40evf_request_stats
+ * @adapter: adapter structure
+ *
+ * Request VSI statistics from PF.
+ **/
+void i40evf_request_stats(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_queue_select vqs;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* no error message, this isn't crucial */
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_GET_STATS;
+ vqs.vsi_id = adapter->vsi_res->vsi_id;
+ /* queue maps are ignored for this message - only the vsi is used */
+ if (i40evf_send_pf_msg(adapter, VIRTCHNL_OP_GET_STATS,
+ (u8 *)&vqs, sizeof(vqs)))
+ /* if the request failed, don't lock out others */
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+}
+
+/**
+ * i40evf_get_hena
+ * @adapter: adapter structure
+ *
+ * Request hash enable capabilities from PF
+ **/
+void i40evf_get_hena(struct i40evf_adapter *adapter)
+{
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot get RSS hash capabilities, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_GET_RSS_HENA_CAPS;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_HENA;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_GET_RSS_HENA_CAPS,
+ NULL, 0);
+}
+
+/**
+ * i40evf_set_hena
+ * @adapter: adapter structure
+ *
+ * Request the PF to set our RSS hash capabilities
+ **/
+void i40evf_set_hena(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_rss_hena vrh;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot set RSS hash enable, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ vrh.hena = adapter->hena;
+ adapter->current_op = VIRTCHNL_OP_SET_RSS_HENA;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_HENA;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_SET_RSS_HENA,
+ (u8 *)&vrh, sizeof(vrh));
+}
+
+/**
+ * i40evf_set_rss_key
+ * @adapter: adapter structure
+ *
+ * Request the PF to set our RSS hash key
+ **/
+void i40evf_set_rss_key(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_rss_key *vrk;
+ int len;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot set RSS key, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ len = sizeof(struct virtchnl_rss_key) +
+ (adapter->rss_key_size * sizeof(u8)) - 1;
+ vrk = kzalloc(len, GFP_KERNEL);
+ if (!vrk)
+ return;
+ vrk->vsi_id = adapter->vsi.id;
+ vrk->key_len = adapter->rss_key_size;
+ memcpy(vrk->key, adapter->rss_key, adapter->rss_key_size);
+
+ adapter->current_op = VIRTCHNL_OP_CONFIG_RSS_KEY;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_RSS_KEY;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_RSS_KEY,
+ (u8 *)vrk, len);
+ kfree(vrk);
+}
+
+/**
+ * i40evf_set_rss_lut
+ * @adapter: adapter structure
+ *
+ * Request the PF to set our RSS lookup table
+ **/
+void i40evf_set_rss_lut(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_rss_lut *vrl;
+ int len;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot set RSS LUT, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ len = sizeof(struct virtchnl_rss_lut) +
+ (adapter->rss_lut_size * sizeof(u8)) - 1;
+ vrl = kzalloc(len, GFP_KERNEL);
+ if (!vrl)
+ return;
+ vrl->vsi_id = adapter->vsi.id;
+ vrl->lut_entries = adapter->rss_lut_size;
+ memcpy(vrl->lut, adapter->rss_lut, adapter->rss_lut_size);
+ adapter->current_op = VIRTCHNL_OP_CONFIG_RSS_LUT;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_RSS_LUT;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_CONFIG_RSS_LUT,
+ (u8 *)vrl, len);
+ kfree(vrl);
+}
+
+/**
+ * i40evf_enable_vlan_stripping
+ * @adapter: adapter structure
+ *
+ * Request VLAN header stripping to be enabled
+ **/
+void i40evf_enable_vlan_stripping(struct i40evf_adapter *adapter)
+{
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot enable stripping, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_ENABLE_VLAN_STRIPPING;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
+ NULL, 0);
+}
+
+/**
+ * i40evf_disable_vlan_stripping
+ * @adapter: adapter structure
+ *
+ * Request VLAN header stripping to be disabled
+ **/
+void i40evf_disable_vlan_stripping(struct i40evf_adapter *adapter)
+{
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot disable stripping, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_DISABLE_VLAN_STRIPPING;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
+ NULL, 0);
+}
+
+/**
+ * i40evf_print_link_message - print link up or down
+ * @adapter: adapter structure
+ *
+ * Log a message telling the world of our wonderous link status
+ */
+static void i40evf_print_link_message(struct i40evf_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ char *speed = "Unknown ";
+
+ if (!adapter->link_up) {
+ netdev_info(netdev, "NIC Link is Down\n");
+ return;
+ }
+
+ switch (adapter->link_speed) {
+ case I40E_LINK_SPEED_40GB:
+ speed = "40 G";
+ break;
+ case I40E_LINK_SPEED_25GB:
+ speed = "25 G";
+ break;
+ case I40E_LINK_SPEED_20GB:
+ speed = "20 G";
+ break;
+ case I40E_LINK_SPEED_10GB:
+ speed = "10 G";
+ break;
+ case I40E_LINK_SPEED_1GB:
+ speed = "1000 M";
+ break;
+ case I40E_LINK_SPEED_100MB:
+ speed = "100 M";
+ break;
+ default:
+ break;
+ }
+
+ netdev_info(netdev, "NIC Link is Up %sbps Full Duplex\n", speed);
+}
+
+/**
+ * i40evf_enable_channel
+ * @adapter: adapter structure
+ *
+ * Request that the PF enable channels as specified by
+ * the user via tc tool.
+ **/
+void i40evf_enable_channels(struct i40evf_adapter *adapter)
+{
+ struct virtchnl_tc_info *vti = NULL;
+ u16 len;
+ int i;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot configure mqprio, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ len = (adapter->num_tc * sizeof(struct virtchnl_channel_info)) +
+ sizeof(struct virtchnl_tc_info);
+
+ vti = kzalloc(len, GFP_KERNEL);
+ if (!vti)
+ return;
+ vti->num_tc = adapter->num_tc;
+ for (i = 0; i < vti->num_tc; i++) {
+ vti->list[i].count = adapter->ch_config.ch_info[i].count;
+ vti->list[i].offset = adapter->ch_config.ch_info[i].offset;
+ vti->list[i].pad = 0;
+ vti->list[i].max_tx_rate =
+ adapter->ch_config.ch_info[i].max_tx_rate;
+ }
+
+ adapter->ch_config.state = __I40EVF_TC_RUNNING;
+ adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
+ adapter->current_op = VIRTCHNL_OP_ENABLE_CHANNELS;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_CHANNELS;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_CHANNELS,
+ (u8 *)vti, len);
+ kfree(vti);
+}
+
+/**
+ * i40evf_disable_channel
+ * @adapter: adapter structure
+ *
+ * Request that the PF disable channels that are configured
+ **/
+void i40evf_disable_channels(struct i40evf_adapter *adapter)
+{
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot configure mqprio, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+
+ adapter->ch_config.state = __I40EVF_TC_INVALID;
+ adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
+ adapter->current_op = VIRTCHNL_OP_DISABLE_CHANNELS;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_CHANNELS;
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_CHANNELS,
+ NULL, 0);
+}
+
+/**
+ * i40evf_print_cloud_filter
+ * @adapter: adapter structure
+ * @f: cloud filter to print
+ *
+ * Print the cloud filter
+ **/
+static void i40evf_print_cloud_filter(struct i40evf_adapter *adapter,
+ struct virtchnl_filter *f)
+{
+ switch (f->flow_type) {
+ case VIRTCHNL_TCP_V4_FLOW:
+ dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI4 src_ip %pI4 dst_port %hu src_port %hu\n",
+ &f->data.tcp_spec.dst_mac,
+ &f->data.tcp_spec.src_mac,
+ ntohs(f->data.tcp_spec.vlan_id),
+ &f->data.tcp_spec.dst_ip[0],
+ &f->data.tcp_spec.src_ip[0],
+ ntohs(f->data.tcp_spec.dst_port),
+ ntohs(f->data.tcp_spec.src_port));
+ break;
+ case VIRTCHNL_TCP_V6_FLOW:
+ dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI6 src_ip %pI6 dst_port %hu src_port %hu\n",
+ &f->data.tcp_spec.dst_mac,
+ &f->data.tcp_spec.src_mac,
+ ntohs(f->data.tcp_spec.vlan_id),
+ &f->data.tcp_spec.dst_ip,
+ &f->data.tcp_spec.src_ip,
+ ntohs(f->data.tcp_spec.dst_port),
+ ntohs(f->data.tcp_spec.src_port));
+ break;
+ }
+}
+
+/**
+ * i40evf_add_cloud_filter
+ * @adapter: adapter structure
+ *
+ * Request that the PF add cloud filters as specified
+ * by the user via tc tool.
+ **/
+void i40evf_add_cloud_filter(struct i40evf_adapter *adapter)
+{
+ struct i40evf_cloud_filter *cf;
+ struct virtchnl_filter *f;
+ int len = 0, count = 0;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot add cloud filter, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
+ if (cf->add) {
+ count++;
+ break;
+ }
+ }
+ if (!count) {
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_ADD_CLOUD_FILTER;
+
+ len = sizeof(struct virtchnl_filter);
+ f = kzalloc(len, GFP_KERNEL);
+ if (!f)
+ return;
+
+ list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
+ if (cf->add) {
+ memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
+ cf->add = false;
+ cf->state = __I40EVF_CF_ADD_PENDING;
+ i40evf_send_pf_msg(adapter,
+ VIRTCHNL_OP_ADD_CLOUD_FILTER,
+ (u8 *)f, len);
+ }
+ }
+ kfree(f);
+}
+
+/**
+ * i40evf_del_cloud_filter
+ * @adapter: adapter structure
+ *
+ * Request that the PF delete cloud filters as specified
+ * by the user via tc tool.
+ **/
+void i40evf_del_cloud_filter(struct i40evf_adapter *adapter)
+{
+ struct i40evf_cloud_filter *cf, *cftmp;
+ struct virtchnl_filter *f;
+ int len = 0, count = 0;
+
+ if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
+ /* bail because we already have a command pending */
+ dev_err(&adapter->pdev->dev, "Cannot remove cloud filter, command %d pending\n",
+ adapter->current_op);
+ return;
+ }
+ list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
+ if (cf->del) {
+ count++;
+ break;
+ }
+ }
+ if (!count) {
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;
+ return;
+ }
+ adapter->current_op = VIRTCHNL_OP_DEL_CLOUD_FILTER;
+
+ len = sizeof(struct virtchnl_filter);
+ f = kzalloc(len, GFP_KERNEL);
+ if (!f)
+ return;
+
+ list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {
+ if (cf->del) {
+ memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
+ cf->del = false;
+ cf->state = __I40EVF_CF_DEL_PENDING;
+ i40evf_send_pf_msg(adapter,
+ VIRTCHNL_OP_DEL_CLOUD_FILTER,
+ (u8 *)f, len);
+ }
+ }
+ kfree(f);
+}
+
+/**
+ * i40evf_request_reset
+ * @adapter: adapter structure
+ *
+ * Request that the PF reset this VF. No response is expected.
+ **/
+void i40evf_request_reset(struct i40evf_adapter *adapter)
+{
+ /* Don't check CURRENT_OP - this is always higher priority */
+ i40evf_send_pf_msg(adapter, VIRTCHNL_OP_RESET_VF, NULL, 0);
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+}
+
+/**
+ * i40evf_virtchnl_completion
+ * @adapter: adapter structure
+ * @v_opcode: opcode sent by PF
+ * @v_retval: retval sent by PF
+ * @msg: message sent by PF
+ * @msglen: message length
+ *
+ * Asynchronous completion function for admin queue messages. Rather than busy
+ * wait, we fire off our requests and assume that no errors will be returned.
+ * This function handles the reply messages.
+ **/
+void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
+ enum virtchnl_ops v_opcode,
+ i40e_status v_retval,
+ u8 *msg, u16 msglen)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ if (v_opcode == VIRTCHNL_OP_EVENT) {
+ struct virtchnl_pf_event *vpe =
+ (struct virtchnl_pf_event *)msg;
+ bool link_up = vpe->event_data.link_event.link_status;
+ switch (vpe->event) {
+ case VIRTCHNL_EVENT_LINK_CHANGE:
+ adapter->link_speed =
+ vpe->event_data.link_event.link_speed;
+
+ /* we've already got the right link status, bail */
+ if (adapter->link_up == link_up)
+ break;
+
+ if (link_up) {
+ /* If we get link up message and start queues
+ * before our queues are configured it will
+ * trigger a TX hang. In that case, just ignore
+ * the link status message,we'll get another one
+ * after we enable queues and actually prepared
+ * to send traffic.
+ */
+ if (adapter->state != __I40EVF_RUNNING)
+ break;
+
+ /* For ADq enabled VF, we reconfigure VSIs and
+ * re-allocate queues. Hence wait till all
+ * queues are enabled.
+ */
+ if (adapter->flags &
+ I40EVF_FLAG_QUEUES_DISABLED)
+ break;
+ }
+
+ adapter->link_up = link_up;
+ if (link_up) {
+ netif_tx_start_all_queues(netdev);
+ netif_carrier_on(netdev);
+ } else {
+ netif_tx_stop_all_queues(netdev);
+ netif_carrier_off(netdev);
+ }
+ i40evf_print_link_message(adapter);
+ break;
+ case VIRTCHNL_EVENT_RESET_IMPENDING:
+ dev_info(&adapter->pdev->dev, "Reset warning received from the PF\n");
+ if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING)) {
+ adapter->flags |= I40EVF_FLAG_RESET_PENDING;
+ dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
+ schedule_work(&adapter->reset_task);
+ }
+ break;
+ default:
+ dev_err(&adapter->pdev->dev, "Unknown event %d from PF\n",
+ vpe->event);
+ break;
+ }
+ return;
+ }
+ if (v_retval) {
+ switch (v_opcode) {
+ case VIRTCHNL_OP_ADD_VLAN:
+ dev_err(&adapter->pdev->dev, "Failed to add VLAN filter, error %s\n",
+ i40evf_stat_str(&adapter->hw, v_retval));
+ break;
+ case VIRTCHNL_OP_ADD_ETH_ADDR:
+ dev_err(&adapter->pdev->dev, "Failed to add MAC filter, error %s\n",
+ i40evf_stat_str(&adapter->hw, v_retval));
+ break;
+ case VIRTCHNL_OP_DEL_VLAN:
+ dev_err(&adapter->pdev->dev, "Failed to delete VLAN filter, error %s\n",
+ i40evf_stat_str(&adapter->hw, v_retval));
+ break;
+ case VIRTCHNL_OP_DEL_ETH_ADDR:
+ dev_err(&adapter->pdev->dev, "Failed to delete MAC filter, error %s\n",
+ i40evf_stat_str(&adapter->hw, v_retval));
+ break;
+ case VIRTCHNL_OP_ENABLE_CHANNELS:
+ dev_err(&adapter->pdev->dev, "Failed to configure queue channels, error %s\n",
+ i40evf_stat_str(&adapter->hw, v_retval));
+ adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
+ adapter->ch_config.state = __I40EVF_TC_INVALID;
+ netdev_reset_tc(netdev);
+ netif_tx_start_all_queues(netdev);
+ break;
+ case VIRTCHNL_OP_DISABLE_CHANNELS:
+ dev_err(&adapter->pdev->dev, "Failed to disable queue channels, error %s\n",
+ i40evf_stat_str(&adapter->hw, v_retval));
+ adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
+ adapter->ch_config.state = __I40EVF_TC_RUNNING;
+ netif_tx_start_all_queues(netdev);
+ break;
+ case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
+ struct i40evf_cloud_filter *cf, *cftmp;
+
+ list_for_each_entry_safe(cf, cftmp,
+ &adapter->cloud_filter_list,
+ list) {
+ if (cf->state == __I40EVF_CF_ADD_PENDING) {
+ cf->state = __I40EVF_CF_INVALID;
+ dev_info(&adapter->pdev->dev, "Failed to add cloud filter, error %s\n",
+ i40evf_stat_str(&adapter->hw,
+ v_retval));
+ i40evf_print_cloud_filter(adapter,
+ &cf->f);
+ list_del(&cf->list);
+ kfree(cf);
+ adapter->num_cloud_filters--;
+ }
+ }
+ }
+ break;
+ case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
+ struct i40evf_cloud_filter *cf;
+
+ list_for_each_entry(cf, &adapter->cloud_filter_list,
+ list) {
+ if (cf->state == __I40EVF_CF_DEL_PENDING) {
+ cf->state = __I40EVF_CF_ACTIVE;
+ dev_info(&adapter->pdev->dev, "Failed to del cloud filter, error %s\n",
+ i40evf_stat_str(&adapter->hw,
+ v_retval));
+ i40evf_print_cloud_filter(adapter,
+ &cf->f);
+ }
+ }
+ }
+ break;
+ default:
+ dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
+ v_retval,
+ i40evf_stat_str(&adapter->hw, v_retval),
+ v_opcode);
+ }
+ }
+ switch (v_opcode) {
+ case VIRTCHNL_OP_GET_STATS: {
+ struct i40e_eth_stats *stats =
+ (struct i40e_eth_stats *)msg;
+ netdev->stats.rx_packets = stats->rx_unicast +
+ stats->rx_multicast +
+ stats->rx_broadcast;
+ netdev->stats.tx_packets = stats->tx_unicast +
+ stats->tx_multicast +
+ stats->tx_broadcast;
+ netdev->stats.rx_bytes = stats->rx_bytes;
+ netdev->stats.tx_bytes = stats->tx_bytes;
+ netdev->stats.tx_errors = stats->tx_errors;
+ netdev->stats.rx_dropped = stats->rx_discards;
+ netdev->stats.tx_dropped = stats->tx_discards;
+ adapter->current_stats = *stats;
+ }
+ break;
+ case VIRTCHNL_OP_GET_VF_RESOURCES: {
+ u16 len = sizeof(struct virtchnl_vf_resource) +
+ I40E_MAX_VF_VSI *
+ sizeof(struct virtchnl_vsi_resource);
+ memcpy(adapter->vf_res, msg, min(msglen, len));
+ i40evf_validate_num_queues(adapter);
+ i40e_vf_parse_hw_config(&adapter->hw, adapter->vf_res);
+ if (is_zero_ether_addr(adapter->hw.mac.addr)) {
+ /* restore current mac address */
+ ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
+ } else {
+ /* refresh current mac address if changed */
+ ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
+ ether_addr_copy(netdev->perm_addr,
+ adapter->hw.mac.addr);
+ }
+ i40evf_process_config(adapter);
+ }
+ break;
+ case VIRTCHNL_OP_ENABLE_QUEUES:
+ /* enable transmits */
+ i40evf_irq_enable(adapter, true);
+ adapter->flags &= ~I40EVF_FLAG_QUEUES_DISABLED;
+ break;
+ case VIRTCHNL_OP_DISABLE_QUEUES:
+ i40evf_free_all_tx_resources(adapter);
+ i40evf_free_all_rx_resources(adapter);
+ if (adapter->state == __I40EVF_DOWN_PENDING) {
+ adapter->state = __I40EVF_DOWN;
+ wake_up(&adapter->down_waitqueue);
+ }
+ break;
+ case VIRTCHNL_OP_VERSION:
+ case VIRTCHNL_OP_CONFIG_IRQ_MAP:
+ /* Don't display an error if we get these out of sequence.
+ * If the firmware needed to get kicked, we'll get these and
+ * it's no problem.
+ */
+ if (v_opcode != adapter->current_op)
+ return;
+ break;
+ case VIRTCHNL_OP_IWARP:
+ /* Gobble zero-length replies from the PF. They indicate that
+ * a previous message was received OK, and the client doesn't
+ * care about that.
+ */
+ if (msglen && CLIENT_ENABLED(adapter))
+ i40evf_notify_client_message(&adapter->vsi,
+ msg, msglen);
+ break;
+
+ case VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP:
+ adapter->client_pending &=
+ ~(BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP));
+ break;
+ case VIRTCHNL_OP_GET_RSS_HENA_CAPS: {
+ struct virtchnl_rss_hena *vrh = (struct virtchnl_rss_hena *)msg;
+ if (msglen == sizeof(*vrh))
+ adapter->hena = vrh->hena;
+ else
+ dev_warn(&adapter->pdev->dev,
+ "Invalid message %d from PF\n", v_opcode);
+ }
+ break;
+ case VIRTCHNL_OP_REQUEST_QUEUES: {
+ struct virtchnl_vf_res_request *vfres =
+ (struct virtchnl_vf_res_request *)msg;
+ if (vfres->num_queue_pairs != adapter->num_req_queues) {
+ dev_info(&adapter->pdev->dev,
+ "Requested %d queues, PF can support %d\n",
+ adapter->num_req_queues,
+ vfres->num_queue_pairs);
+ adapter->num_req_queues = 0;
+ adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
+ }
+ }
+ break;
+ case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
+ struct i40evf_cloud_filter *cf;
+
+ list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
+ if (cf->state == __I40EVF_CF_ADD_PENDING)
+ cf->state = __I40EVF_CF_ACTIVE;
+ }
+ }
+ break;
+ case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
+ struct i40evf_cloud_filter *cf, *cftmp;
+
+ list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list,
+ list) {
+ if (cf->state == __I40EVF_CF_DEL_PENDING) {
+ cf->state = __I40EVF_CF_INVALID;
+ list_del(&cf->list);
+ kfree(cf);
+ adapter->num_cloud_filters--;
+ }
+ }
+ }
+ break;
+ default:
+ if (adapter->current_op && (v_opcode != adapter->current_op))
+ dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
+ adapter->current_op, v_opcode);
+ break;
+ } /* switch v_opcode */
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
+}
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 87f98170ac93..6f9d563deb6b 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3700,9 +3700,7 @@ static void igb_remove(struct pci_dev *pdev)
igb_release_hw_control(adapter);
#ifdef CONFIG_PCI_IOV
- rtnl_lock();
igb_disable_sriov(pdev);
- rtnl_unlock();
#endif
unregister_netdev(netdev);
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index df827c254162..70f5f28bfd9e 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1070,7 +1070,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
igbvf_intr_msix_rx, 0, adapter->rx_ring->name,
netdev);
if (err)
- goto out;
+ goto free_irq_tx;
adapter->rx_ring->itr_register = E1000_EITR(vector);
adapter->rx_ring->itr_val = adapter->current_itr;
@@ -1079,10 +1079,14 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
err = request_irq(adapter->msix_entries[vector].vector,
igbvf_msix_other, 0, netdev->name, netdev);
if (err)
- goto out;
+ goto free_irq_rx;
igbvf_configure_msix(adapter);
return 0;
+free_irq_rx:
+ free_irq(adapter->msix_entries[--vector].vector, netdev);
+free_irq_tx:
+ free_irq(adapter->msix_entries[--vector].vector, netdev);
out:
return err;
}
diff --git a/drivers/net/ethernet/intel/igbvf/vf.c b/drivers/net/ethernet/intel/igbvf/vf.c
index b8ba3f94c363..a47a2e3e548c 100644
--- a/drivers/net/ethernet/intel/igbvf/vf.c
+++ b/drivers/net/ethernet/intel/igbvf/vf.c
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009 - 2018 Intel Corporation. */
+#include <linux/etherdevice.h>
+
#include "vf.h"
static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
@@ -131,11 +133,16 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
/* set our "perm_addr" based on info provided by PF */
ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
if (!ret_val) {
- if (msgbuf[0] == (E1000_VF_RESET |
- E1000_VT_MSGTYPE_ACK))
+ switch (msgbuf[0]) {
+ case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK:
memcpy(hw->mac.perm_addr, addr, ETH_ALEN);
- else
+ break;
+ case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK:
+ eth_zero_addr(hw->mac.perm_addr);
+ break;
+ default:
ret_val = -E1000_ERR_MAC_INIT;
+ }
}
}
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index fd1311681200..f1a4b11ce0d1 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -542,6 +542,20 @@ struct mvneta_rx_desc {
};
#endif
+enum mvneta_tx_buf_type {
+ MVNETA_TYPE_SKB,
+ MVNETA_TYPE_XDP_TX,
+ MVNETA_TYPE_XDP_NDO,
+};
+
+struct mvneta_tx_buf {
+ enum mvneta_tx_buf_type type;
+ union {
+ struct xdp_frame *xdpf;
+ struct sk_buff *skb;
+ };
+};
+
struct mvneta_tx_queue {
/* Number of this TX queue, in the range 0-7 */
u8 id;
@@ -557,8 +571,8 @@ struct mvneta_tx_queue {
int tx_stop_threshold;
int tx_wake_threshold;
- /* Array of transmitted skb */
- struct sk_buff **tx_skb;
+ /* Array of transmitted buffers */
+ struct mvneta_tx_buf *buf;
/* Index of last TX DMA descriptor that was inserted */
int txq_put_index;
@@ -1767,14 +1781,9 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
int i;
for (i = 0; i < num; i++) {
+ struct mvneta_tx_buf *buf = &txq->buf[txq->txq_get_index];
struct mvneta_tx_desc *tx_desc = txq->descs +
txq->txq_get_index;
- struct sk_buff *skb = txq->tx_skb[txq->txq_get_index];
-
- if (skb) {
- bytes_compl += skb->len;
- pkts_compl++;
- }
mvneta_txq_inc_get(txq);
@@ -1782,9 +1791,12 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
dma_unmap_single(pp->dev->dev.parent,
tx_desc->buf_phys_addr,
tx_desc->data_size, DMA_TO_DEVICE);
- if (!skb)
+ if (!buf->skb)
continue;
- dev_kfree_skb_any(skb);
+
+ bytes_compl += buf->skb->len;
+ pkts_compl++;
+ dev_kfree_skb_any(buf->skb);
}
netdev_tx_completed_queue(nq, pkts_compl, bytes_compl);
@@ -2238,16 +2250,19 @@ static inline void
mvneta_tso_put_hdr(struct sk_buff *skb,
struct mvneta_port *pp, struct mvneta_tx_queue *txq)
{
- struct mvneta_tx_desc *tx_desc;
int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
+ struct mvneta_tx_desc *tx_desc;
- txq->tx_skb[txq->txq_put_index] = NULL;
tx_desc = mvneta_txq_next_desc_get(txq);
tx_desc->data_size = hdr_len;
tx_desc->command = mvneta_skb_tx_csum(pp, skb);
tx_desc->command |= MVNETA_TXD_F_DESC;
tx_desc->buf_phys_addr = txq->tso_hdrs_phys +
txq->txq_put_index * TSO_HEADER_SIZE;
+ buf->type = MVNETA_TYPE_SKB;
+ buf->skb = NULL;
+
mvneta_txq_inc_put(txq);
}
@@ -2256,6 +2271,7 @@ mvneta_tso_put_data(struct net_device *dev, struct mvneta_tx_queue *txq,
struct sk_buff *skb, char *data, int size,
bool last_tcp, bool is_last)
{
+ struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
struct mvneta_tx_desc *tx_desc;
tx_desc = mvneta_txq_next_desc_get(txq);
@@ -2269,7 +2285,8 @@ mvneta_tso_put_data(struct net_device *dev, struct mvneta_tx_queue *txq,
}
tx_desc->command = 0;
- txq->tx_skb[txq->txq_put_index] = NULL;
+ buf->type = MVNETA_TYPE_SKB;
+ buf->skb = NULL;
if (last_tcp) {
/* last descriptor in the TCP packet */
@@ -2277,7 +2294,7 @@ mvneta_tso_put_data(struct net_device *dev, struct mvneta_tx_queue *txq,
/* last descriptor in SKB */
if (is_last)
- txq->tx_skb[txq->txq_put_index] = skb;
+ buf->skb = skb;
}
mvneta_txq_inc_put(txq);
return 0;
@@ -2362,6 +2379,7 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,
int i, nr_frags = skb_shinfo(skb)->nr_frags;
for (i = 0; i < nr_frags; i++) {
+ struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
void *addr = page_address(frag->page.p) + frag->page_offset;
@@ -2381,12 +2399,13 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,
if (i == nr_frags - 1) {
/* Last descriptor */
tx_desc->command = MVNETA_TXD_L_DESC | MVNETA_TXD_Z_PAD;
- txq->tx_skb[txq->txq_put_index] = skb;
+ buf->skb = skb;
} else {
/* Descriptor in the middle: Not First, Not Last */
tx_desc->command = 0;
- txq->tx_skb[txq->txq_put_index] = NULL;
+ buf->skb = NULL;
}
+ buf->type = MVNETA_TYPE_SKB;
mvneta_txq_inc_put(txq);
}
@@ -2414,6 +2433,7 @@ static netdev_tx_t mvneta_tx(struct sk_buff *skb, struct net_device *dev)
struct mvneta_port *pp = netdev_priv(dev);
u16 txq_id = skb_get_queue_mapping(skb);
struct mvneta_tx_queue *txq = &pp->txqs[txq_id];
+ struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
struct mvneta_tx_desc *tx_desc;
int len = skb->len;
int frags = 0;
@@ -2446,16 +2466,17 @@ static netdev_tx_t mvneta_tx(struct sk_buff *skb, struct net_device *dev)
goto out;
}
+ buf->type = MVNETA_TYPE_SKB;
if (frags == 1) {
/* First and Last descriptor */
tx_cmd |= MVNETA_TXD_FLZ_DESC;
tx_desc->command = tx_cmd;
- txq->tx_skb[txq->txq_put_index] = skb;
+ buf->skb = skb;
mvneta_txq_inc_put(txq);
} else {
/* First but not Last */
tx_cmd |= MVNETA_TXD_F_DESC;
- txq->tx_skb[txq->txq_put_index] = NULL;
+ buf->skb = NULL;
mvneta_txq_inc_put(txq);
tx_desc->command = tx_cmd;
/* Continue with other skb fragments */
@@ -3000,9 +3021,8 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp,
txq->last_desc = txq->size - 1;
- txq->tx_skb = kmalloc_array(txq->size, sizeof(*txq->tx_skb),
- GFP_KERNEL);
- if (!txq->tx_skb) {
+ txq->buf = kmalloc_array(txq->size, sizeof(*txq->buf), GFP_KERNEL);
+ if (!txq->buf) {
dma_free_coherent(pp->dev->dev.parent,
txq->size * MVNETA_DESC_ALIGNED_SIZE,
txq->descs, txq->descs_phys);
@@ -3014,7 +3034,7 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp,
txq->size * TSO_HEADER_SIZE,
&txq->tso_hdrs_phys, GFP_KERNEL);
if (!txq->tso_hdrs) {
- kfree(txq->tx_skb);
+ kfree(txq->buf);
dma_free_coherent(pp->dev->dev.parent,
txq->size * MVNETA_DESC_ALIGNED_SIZE,
txq->descs, txq->descs_phys);
@@ -3069,7 +3089,7 @@ static void mvneta_txq_sw_deinit(struct mvneta_port *pp,
{
struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id);
- kfree(txq->tx_skb);
+ kfree(txq->buf);
if (txq->tso_hdrs)
dma_free_coherent(pp->dev->dev.parent,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 722998d68564..6f1f53f91ed8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -109,12 +109,14 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
if (!MLX5_CAP_GEN(priv->mdev, ets))
return -EOPNOTSUPP;
- ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
- for (i = 0; i < ets->ets_cap; i++) {
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
if (err)
return err;
+ }
+ ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
+ for (i = 0; i < ets->ets_cap; i++) {
err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]);
if (err)
return err;
diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c
index 69282f31d519..fe54bcab705f 100644
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -255,7 +255,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
*/
laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
- if (!laddr) {
+ if (dma_mapping_error(lp->device, laddr)) {
pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name);
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
@@ -473,7 +473,7 @@ static bool sonic_alloc_rb(struct net_device *dev, struct sonic_local *lp,
*new_addr = dma_map_single(lp->device, skb_put(*new_skb, SONIC_RBSIZE),
SONIC_RBSIZE, DMA_FROM_DEVICE);
- if (!*new_addr) {
+ if (dma_mapping_error(lp->device, *new_addr)) {
dev_kfree_skb(*new_skb);
*new_skb = NULL;
return false;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
index 402c1c3d84ce..5c8eaded6b30 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
@@ -4403,6 +4403,9 @@ qed_iov_configure_min_tx_rate(struct qed_dev *cdev, int vfid, u32 rate)
}
vf = qed_iov_get_vf_info(QED_LEADING_HWFN(cdev), (u16)vfid, true);
+ if (!vf)
+ return -EINVAL;
+
vport_id = vf->vport_id;
return qed_configure_vport_wfq(cdev, vport_id, rate);
@@ -5142,7 +5145,7 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
/* Validate that the VF has a configured vport */
vf = qed_iov_get_vf_info(hwfn, i, true);
- if (!vf->vport_instance)
+ if (!vf || !vf->vport_instance)
continue;
memset(¶ms, 0, sizeof(params));
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 76a9b37c8680..3c764c28d5db 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -752,9 +752,15 @@ static int emac_remove(struct platform_device *pdev)
struct net_device *netdev = dev_get_drvdata(&pdev->dev);
struct emac_adapter *adpt = netdev_priv(netdev);
+ netif_carrier_off(netdev);
+ netif_tx_disable(netdev);
+
unregister_netdev(netdev);
netif_napi_del(&adpt->rx_q.napi);
+ free_irq(adpt->irq.irq, &adpt->irq);
+ cancel_work_sync(&adpt->work_thread);
+
emac_clks_teardown(adpt);
put_device(&adpt->phydev->mdio.dev);
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
index 75237c81c63d..572294678faf 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -330,15 +330,17 @@ static int gelic_card_init_chain(struct gelic_card *card,
/* set up the hardware pointers in each descriptor */
for (i = 0; i < no; i++, descr++) {
+ dma_addr_t cpu_addr;
+
gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE);
- descr->bus_addr =
- dma_map_single(ctodev(card), descr,
- GELIC_DESCR_SIZE,
- DMA_BIDIRECTIONAL);
- if (!descr->bus_addr)
+ cpu_addr = dma_map_single(ctodev(card), descr,
+ GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL);
+
+ if (dma_mapping_error(ctodev(card), cpu_addr))
goto iommu_error;
+ descr->bus_addr = cpu_to_be32(cpu_addr);
descr->next = descr + 1;
descr->prev = descr - 1;
}
@@ -378,28 +380,30 @@ static int gelic_card_init_chain(struct gelic_card *card,
*
* allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
* Activate the descriptor state-wise
+ *
+ * Gelic RX sk_buffs must be aligned to GELIC_NET_RXBUF_ALIGN and the length
+ * must be a multiple of GELIC_NET_RXBUF_ALIGN.
*/
static int gelic_descr_prepare_rx(struct gelic_card *card,
struct gelic_descr *descr)
{
+ static const unsigned int rx_skb_size =
+ ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN) +
+ GELIC_NET_RXBUF_ALIGN - 1;
+ dma_addr_t cpu_addr;
int offset;
- unsigned int bufsize;
if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE)
dev_info(ctodev(card), "%s: ERROR status\n", __func__);
- /* we need to round up the buffer size to a multiple of 128 */
- bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN);
- /* and we need to have it 128 byte aligned, therefore we allocate a
- * bit more */
- descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1);
+ descr->skb = netdev_alloc_skb(*card->netdev, rx_skb_size);
if (!descr->skb) {
descr->buf_addr = 0; /* tell DMAC don't touch memory */
dev_info(ctodev(card),
"%s:allocate skb failed !!\n", __func__);
return -ENOMEM;
}
- descr->buf_size = cpu_to_be32(bufsize);
+ descr->buf_size = cpu_to_be32(rx_skb_size);
descr->dmac_cmd_status = 0;
descr->result_size = 0;
descr->valid_size = 0;
@@ -410,11 +414,10 @@ static int gelic_descr_prepare_rx(struct gelic_card *card,
if (offset)
skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset);
/* io-mmu-map the skb */
- descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card),
- descr->skb->data,
- GELIC_NET_MAX_MTU,
- DMA_FROM_DEVICE));
- if (!descr->buf_addr) {
+ cpu_addr = dma_map_single(ctodev(card), descr->skb->data,
+ GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE);
+ descr->buf_addr = cpu_to_be32(cpu_addr);
+ if (dma_mapping_error(ctodev(card), cpu_addr)) {
dev_kfree_skb_any(descr->skb);
descr->skb = NULL;
dev_info(ctodev(card),
@@ -794,7 +797,7 @@ static int gelic_descr_prepare_tx(struct gelic_card *card,
buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE);
- if (!buf) {
+ if (dma_mapping_error(ctodev(card), buf)) {
dev_err(ctodev(card),
"dma map 2 failed (%p, %i). Dropping packet\n",
skb->data, skb->len);
@@ -930,7 +933,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr,
data_error = be32_to_cpu(descr->data_error);
/* unmap skb buffer */
dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr),
- GELIC_NET_MAX_MTU,
+ GELIC_NET_MAX_FRAME,
DMA_FROM_DEVICE);
skb_put(skb, be32_to_cpu(descr->valid_size)?
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.h b/drivers/net/ethernet/toshiba/ps3_gelic_net.h
index fbbf9b54b173..0e592fc19f6c 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.h
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.h
@@ -32,8 +32,9 @@
#define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */
#define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */
-#define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN
-#define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN
+#define GELIC_NET_MAX_FRAME 2312
+#define GELIC_NET_MAX_MTU 2294
+#define GELIC_NET_MIN_MTU 64
#define GELIC_NET_RXBUF_ALIGN 128
#define GELIC_CARD_RX_CSUM_DEFAULT 1 /* hw chksum */
#define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ
diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c
index fd5288ff53b5..e3438cef5f9c 100644
--- a/drivers/net/ethernet/xircom/xirc2ps_cs.c
+++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c
@@ -503,6 +503,11 @@ static void
xirc2ps_detach(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
+ struct local_info *local = netdev_priv(dev);
+
+ netif_carrier_off(dev);
+ netif_tx_disable(dev);
+ cancel_work_sync(&local->tx_timeout_task);
dev_dbg(&link->dev, "detach\n");
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index 917edb3d04b7..f75faec23cc9 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -1943,10 +1943,9 @@ static int ca8210_skb_tx(
struct ca8210_priv *priv
)
{
- int status;
struct ieee802154_hdr header = { };
struct secspec secspec;
- unsigned int mac_len;
+ int mac_len, status;
dev_dbg(&priv->spi->dev, "%s called\n", __func__);
@@ -1954,6 +1953,8 @@ static int ca8210_skb_tx(
* packet
*/
mac_len = ieee802154_hdr_peek_addrs(skb, &header);
+ if (mac_len < 0)
+ return mac_len;
secspec.security_level = header.sec.level;
secspec.key_id_mode = header.sec.key_id_mode;
diff --git a/drivers/net/phy/mdio-thunder.c b/drivers/net/phy/mdio-thunder.c
index c0c922eff760..959bf342133a 100644
--- a/drivers/net/phy/mdio-thunder.c
+++ b/drivers/net/phy/mdio-thunder.c
@@ -107,6 +107,7 @@ static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
if (i >= ARRAY_SIZE(nexus->buses))
break;
}
+ fwnode_handle_put(fwn);
return 0;
err_release_regions:
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 5194b2ccd4b7..e61f02f7642c 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -256,6 +256,9 @@ struct tun_struct {
struct tun_prog __rcu *steering_prog;
struct tun_prog __rcu *filter_prog;
struct ethtool_link_ksettings link_ksettings;
+ /* init args */
+ struct file *file;
+ struct ifreq *ifr;
};
struct veth {
@@ -281,6 +284,9 @@ void *tun_ptr_to_xdp(void *ptr)
}
EXPORT_SYMBOL(tun_ptr_to_xdp);
+static void tun_flow_init(struct tun_struct *tun);
+static void tun_flow_uninit(struct tun_struct *tun);
+
static int tun_napi_receive(struct napi_struct *napi, int budget)
{
struct tun_file *tfile = container_of(napi, struct tun_file, napi);
@@ -1038,6 +1044,49 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb)
static const struct ethtool_ops tun_ethtool_ops;
+static int tun_net_init(struct net_device *dev)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+ struct ifreq *ifr = tun->ifr;
+ int err;
+
+ tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats);
+ if (!tun->pcpu_stats)
+ return -ENOMEM;
+
+ spin_lock_init(&tun->lock);
+
+ err = security_tun_dev_alloc_security(&tun->security);
+ if (err < 0) {
+ free_percpu(tun->pcpu_stats);
+ return err;
+ }
+
+ tun_flow_init(tun);
+
+ dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
+ TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_STAG_TX;
+ dev->features = dev->hw_features | NETIF_F_LLTX;
+ dev->vlan_features = dev->features &
+ ~(NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_STAG_TX);
+
+ tun->flags = (tun->flags & ~TUN_FEATURES) |
+ (ifr->ifr_flags & TUN_FEATURES);
+
+ INIT_LIST_HEAD(&tun->disabled);
+ err = tun_attach(tun, tun->file, false, ifr->ifr_flags & IFF_NAPI,
+ ifr->ifr_flags & IFF_NAPI_FRAGS, false);
+ if (err < 0) {
+ tun_flow_uninit(tun);
+ security_tun_dev_free_security(tun->security);
+ free_percpu(tun->pcpu_stats);
+ return err;
+ }
+ return 0;
+}
+
/* Net device detach from fd. */
static void tun_net_uninit(struct net_device *dev)
{
@@ -1268,6 +1317,7 @@ static int tun_xdp(struct net_device *dev, struct netdev_bpf *xdp)
}
static const struct net_device_ops tun_netdev_ops = {
+ .ndo_init = tun_net_init,
.ndo_uninit = tun_net_uninit,
.ndo_open = tun_net_open,
.ndo_stop = tun_net_close,
@@ -1347,6 +1397,7 @@ static int tun_xdp_tx(struct net_device *dev, struct xdp_buff *xdp)
}
static const struct net_device_ops tap_netdev_ops = {
+ .ndo_init = tun_net_init,
.ndo_uninit = tun_net_uninit,
.ndo_open = tun_net_open,
.ndo_stop = tun_net_close,
@@ -1386,7 +1437,7 @@ static void tun_flow_uninit(struct tun_struct *tun)
#define MAX_MTU 65535
/* Initialize net device. */
-static void tun_net_init(struct net_device *dev)
+static void tun_net_initialize(struct net_device *dev)
{
struct tun_struct *tun = netdev_priv(dev);
@@ -2658,9 +2709,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
if (!dev)
return -ENOMEM;
- err = dev_get_valid_name(net, dev, name);
- if (err < 0)
- goto err_free_dev;
dev_net_set(dev, net);
dev->rtnl_link_ops = &tun_link_ops;
@@ -2679,41 +2727,16 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
tun->rx_batched = 0;
RCU_INIT_POINTER(tun->steering_prog, NULL);
- tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats);
- if (!tun->pcpu_stats) {
- err = -ENOMEM;
- goto err_free_dev;
- }
-
- spin_lock_init(&tun->lock);
-
- err = security_tun_dev_alloc_security(&tun->security);
- if (err < 0)
- goto err_free_stat;
-
- tun_net_init(dev);
- tun_flow_init(tun);
-
- dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
- TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
- NETIF_F_HW_VLAN_STAG_TX;
- dev->features = dev->hw_features | NETIF_F_LLTX;
- dev->vlan_features = dev->features &
- ~(NETIF_F_HW_VLAN_CTAG_TX |
- NETIF_F_HW_VLAN_STAG_TX);
+ tun->ifr = ifr;
+ tun->file = file;
- tun->flags = (tun->flags & ~TUN_FEATURES) |
- (ifr->ifr_flags & TUN_FEATURES);
-
- INIT_LIST_HEAD(&tun->disabled);
- err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI,
- ifr->ifr_flags & IFF_NAPI_FRAGS, false);
- if (err < 0)
- goto err_free_flow;
+ tun_net_initialize(dev);
err = register_netdevice(tun->dev);
- if (err < 0)
- goto err_detach;
+ if (err < 0) {
+ free_netdev(dev);
+ return err;
+ }
/* free_netdev() won't check refcnt, to aovid race
* with dev_put() we need publish tun after registration.
*/
@@ -2732,20 +2755,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
strcpy(ifr->ifr_name, tun->dev->name);
return 0;
-
-err_detach:
- tun_detach_all(dev);
- /* register_netdevice() already called tun_free_netdev() */
- goto err_free_dev;
-
-err_free_flow:
- tun_flow_uninit(tun);
- security_tun_dev_free_security(tun->security);
-err_free_stat:
- free_percpu(tun->pcpu_stats);
-err_free_dev:
- free_netdev(dev);
- return err;
}
static void tun_get_iff(struct net *net, struct tun_struct *tun,
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 41bac861ca99..72a93dc2df86 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -665,6 +665,11 @@ static const struct usb_device_id mbim_devs[] = {
.driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle,
},
+ /* Telit FE990 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1081, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle,
+ },
+
/* default entry */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&cdc_mbim_info_zlp,
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 24ce49b311c4..5417932242e7 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1322,6 +1322,7 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1050, 2)}, /* Telit FN980 */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990 */
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1080, 2)}, /* Telit FE990 */
{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */
{QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */
{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 4f29010e1aef..085048686413 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1950,6 +1950,12 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
size = (u16)((header & RX_STS_FL_) >> 16);
align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
+ if (unlikely(size > skb->len)) {
+ netif_dbg(dev, rx_err, dev->net,
+ "size err header=0x%08x\n", header);
+ return 0;
+ }
+
if (unlikely(header & RX_STS_ES_)) {
netif_dbg(dev, rx_err, dev->net,
"Error header=0x%08x\n", header);
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 92d30ebdb111..2b984c5bae24 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -166,7 +166,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */
struct pending_tx_info pending_tx_info[MAX_PENDING_REQS];
grant_handle_t grant_tx_handle[MAX_PENDING_REQS];
- struct gnttab_copy tx_copy_ops[MAX_PENDING_REQS];
+ struct gnttab_copy tx_copy_ops[2 * MAX_PENDING_REQS];
struct gnttab_map_grant_ref tx_map_ops[MAX_PENDING_REQS];
struct gnttab_unmap_grant_ref tx_unmap_ops[MAX_PENDING_REQS];
/* passed to gnttab_[un]map_refs with pages under (un)mapping */
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index fc389f2bba7a..ed644b6824ce 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -327,6 +327,7 @@ static int xenvif_count_requests(struct xenvif_queue *queue,
struct xenvif_tx_cb {
u16 copy_pending_idx[XEN_NETBK_LEGACY_SLOTS_MAX + 1];
u8 copy_count;
+ u32 split_mask;
};
#define XENVIF_TX_CB(skb) ((struct xenvif_tx_cb *)(skb)->cb)
@@ -354,6 +355,8 @@ static inline struct sk_buff *xenvif_alloc_skb(unsigned int size)
struct sk_buff *skb =
alloc_skb(size + NET_SKB_PAD + NET_IP_ALIGN,
GFP_ATOMIC | __GFP_NOWARN);
+
+ BUILD_BUG_ON(sizeof(*XENVIF_TX_CB(skb)) > sizeof(skb->cb));
if (unlikely(skb == NULL))
return NULL;
@@ -389,11 +392,13 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
nr_slots = shinfo->nr_frags + 1;
copy_count(skb) = 0;
+ XENVIF_TX_CB(skb)->split_mask = 0;
/* Create copy ops for exactly data_len bytes into the skb head. */
__skb_put(skb, data_len);
while (data_len > 0) {
int amount = data_len > txp->size ? txp->size : data_len;
+ bool split = false;
cop->source.u.ref = txp->gref;
cop->source.domid = queue->vif->domid;
@@ -406,6 +411,13 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
cop->dest.u.gmfn = virt_to_gfn(skb->data + skb_headlen(skb)
- data_len);
+ /* Don't cross local page boundary! */
+ if (cop->dest.offset + amount > XEN_PAGE_SIZE) {
+ amount = XEN_PAGE_SIZE - cop->dest.offset;
+ XENVIF_TX_CB(skb)->split_mask |= 1U << copy_count(skb);
+ split = true;
+ }
+
cop->len = amount;
cop->flags = GNTCOPY_source_gref;
@@ -413,7 +425,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
pending_idx = queue->pending_ring[index];
callback_param(queue, pending_idx).ctx = NULL;
copy_pending_idx(skb, copy_count(skb)) = pending_idx;
- copy_count(skb)++;
+ if (!split)
+ copy_count(skb)++;
cop++;
data_len -= amount;
@@ -434,7 +447,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
nr_slots--;
} else {
/* The copy op partially covered the tx_request.
- * The remainder will be mapped.
+ * The remainder will be mapped or copied in the next
+ * iteration.
*/
txp->offset += amount;
txp->size -= amount;
@@ -532,6 +546,13 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
pending_idx = copy_pending_idx(skb, i);
newerr = (*gopp_copy)->status;
+
+ /* Split copies need to be handled together. */
+ if (XENVIF_TX_CB(skb)->split_mask & (1U << i)) {
+ (*gopp_copy)++;
+ if (!newerr)
+ newerr = (*gopp_copy)->status;
+ }
if (likely(!newerr)) {
/* The first frag might still have this slot mapped */
if (i < copy_count(skb) - 1 || !sharedslot)
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 89d88e447d44..5b883eb49ce9 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -1080,7 +1080,6 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
dev_err(dev, "can't add the irq domain\n");
return -ENODEV;
}
- atmel_pioctrl->irq_domain->name = "atmel gpio";
for (i = 0; i < atmel_pioctrl->npins; i++) {
int irq = irq_create_mapping(atmel_pioctrl->irq_domain, i);
diff --git a/drivers/power/supply/da9150-charger.c b/drivers/power/supply/da9150-charger.c
index 60099815296e..b2d38eb32288 100644
--- a/drivers/power/supply/da9150-charger.c
+++ b/drivers/power/supply/da9150-charger.c
@@ -666,6 +666,7 @@ static int da9150_charger_remove(struct platform_device *pdev)
if (!IS_ERR_OR_NULL(charger->usb_phy))
usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
+ cancel_work_sync(&charger->otg_work);
power_supply_unregister(charger->battery);
power_supply_unregister(charger->usb);
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 4cf7c3348bff..9be913c19a6e 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -1050,10 +1050,12 @@ static int alua_activate(struct scsi_device *sdev,
rcu_read_unlock();
mutex_unlock(&h->init_mutex);
- if (alua_rtpg_queue(pg, sdev, qdata, true))
+ if (alua_rtpg_queue(pg, sdev, qdata, true)) {
fn = NULL;
- else
+ } else {
+ kfree(qdata);
err = SCSI_DH_DEV_OFFLINED;
+ }
kref_put(&pg->kref, release_port_group);
out:
if (fn)
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index bdb12bf0d5c7..b400167f9ad4 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -4367,7 +4367,7 @@ int megasas_task_abort_fusion(struct scsi_cmnd *scmd)
devhandle = megasas_get_tm_devhandle(scmd->device);
if (devhandle == (u16)ULONG_MAX) {
- ret = SUCCESS;
+ ret = FAILED;
sdev_printk(KERN_INFO, scmd->device,
"task abort issued for invalid devhandle\n");
mutex_unlock(&instance->reset_mutex);
@@ -4440,7 +4440,7 @@ int megasas_reset_target_fusion(struct scsi_cmnd *scmd)
devhandle = megasas_get_tm_devhandle(scmd->device);
if (devhandle == (u16)ULONG_MAX) {
- ret = SUCCESS;
+ ret = FAILED;
sdev_printk(KERN_INFO, scmd->device,
"target reset issued for invalid devhandle\n");
mutex_unlock(&instance->reset_mutex);
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 6a2a413cc97e..d8557a00e1ec 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -232,6 +232,7 @@ static struct {
{"SGI", "RAID5", "*", BLIST_SPARSELUN},
{"SGI", "TP9100", "*", BLIST_REPORTLUN2},
{"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
+ {"SKhynix", "H28U74301AMR", NULL, BLIST_SKIP_VPD_PAGES},
{"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
{"SUN", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
{"DELL", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index abc156cf05f6..b45cd6c98bad 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -8228,5 +8228,6 @@ EXPORT_SYMBOL_GPL(ufshcd_init);
MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
MODULE_DESCRIPTION("Generic UFS host controller driver Core");
+MODULE_SOFTDEP("pre: governor_simpleondemand");
MODULE_LICENSE("GPL");
MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 29a37b242d30..01f93de93c8c 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -1270,18 +1270,20 @@ static struct iscsi_param *iscsi_check_key(
return param;
if (!(param->phase & phase)) {
- pr_err("Key \"%s\" may not be negotiated during ",
- param->name);
+ char *phase_name;
+
switch (phase) {
case PHASE_SECURITY:
- pr_debug("Security phase.\n");
+ phase_name = "Security";
break;
case PHASE_OPERATIONAL:
- pr_debug("Operational phase.\n");
+ phase_name = "Operational";
break;
default:
- pr_debug("Unknown phase.\n");
+ phase_name = "Unknown";
}
+ pr_err("Key \"%s\" may not be negotiated during %s phase.\n",
+ param->name, phase_name);
return NULL;
}
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index 384623c49cfe..d22c7216d68c 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -38,7 +38,7 @@
#define NHI_MAILBOX_TIMEOUT 500 /* ms */
-static int ring_interrupt_index(struct tb_ring *ring)
+static int ring_interrupt_index(const struct tb_ring *ring)
{
int bit = ring->hop;
if (!ring->is_tx)
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index 47ffb485ff34..59d85bdd132b 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -43,6 +43,7 @@ struct xencons_info {
int irq;
int vtermno;
grant_ref_t gntref;
+ spinlock_t ring_lock;
};
static LIST_HEAD(xenconsoles);
@@ -89,12 +90,15 @@ static int __write_console(struct xencons_info *xencons,
XENCONS_RING_IDX cons, prod;
struct xencons_interface *intf = xencons->intf;
int sent = 0;
+ unsigned long flags;
+ spin_lock_irqsave(&xencons->ring_lock, flags);
cons = intf->out_cons;
prod = intf->out_prod;
mb(); /* update queue values before going on */
if ((prod - cons) > sizeof(intf->out)) {
+ spin_unlock_irqrestore(&xencons->ring_lock, flags);
pr_err_once("xencons: Illegal ring page indices");
return -EINVAL;
}
@@ -104,6 +108,7 @@ static int __write_console(struct xencons_info *xencons,
wmb(); /* write ring before updating pointer */
intf->out_prod = prod;
+ spin_unlock_irqrestore(&xencons->ring_lock, flags);
if (sent)
notify_daemon(xencons);
@@ -146,16 +151,19 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
int recv = 0;
struct xencons_info *xencons = vtermno_to_xencons(vtermno);
unsigned int eoiflag = 0;
+ unsigned long flags;
if (xencons == NULL)
return -EINVAL;
intf = xencons->intf;
+ spin_lock_irqsave(&xencons->ring_lock, flags);
cons = intf->in_cons;
prod = intf->in_prod;
mb(); /* get pointers before reading ring */
if ((prod - cons) > sizeof(intf->in)) {
+ spin_unlock_irqrestore(&xencons->ring_lock, flags);
pr_err_once("xencons: Illegal ring page indices");
return -EINVAL;
}
@@ -179,10 +187,13 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
xencons->out_cons = intf->out_cons;
xencons->out_cons_same = 0;
}
+ if (!recv && xencons->out_cons_same++ > 1) {
+ eoiflag = XEN_EOI_FLAG_SPURIOUS;
+ }
+ spin_unlock_irqrestore(&xencons->ring_lock, flags);
+
if (recv) {
notify_daemon(xencons);
- } else if (xencons->out_cons_same++ > 1) {
- eoiflag = XEN_EOI_FLAG_SPURIOUS;
}
xen_irq_lateeoi(xencons->irq, eoiflag);
@@ -239,6 +250,7 @@ static int xen_hvm_console_init(void)
info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
+ spin_lock_init(&info->ring_lock);
} else if (info->intf != NULL) {
/* already configured */
return 0;
@@ -275,6 +287,7 @@ static int xen_hvm_console_init(void)
static int xencons_info_pv_init(struct xencons_info *info, int vtermno)
{
+ spin_lock_init(&info->ring_lock);
info->evtchn = xen_start_info->console.domU.evtchn;
/* GFN == MFN for PV guest */
info->intf = gfn_to_virt(xen_start_info->console.domU.mfn);
@@ -325,6 +338,7 @@ static int xen_initial_domain_console_init(void)
info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
+ spin_lock_init(&info->ring_lock);
}
info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
@@ -482,6 +496,7 @@ static int xencons_probe(struct xenbus_device *dev,
info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
+ spin_lock_init(&info->ring_lock);
dev_set_drvdata(&dev->dev, info);
info->xbdev = dev;
info->vtermno = xenbus_devid_to_vtermno(devid);
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 6a2cc5cd0281..d0e9f3265f5a 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -202,6 +202,7 @@ struct hw_bank {
* @in_lpm: if the core in low power mode
* @wakeup_int: if wakeup interrupt occur
* @rev: The revision number for controller
+ * @mutex: protect code from concorrent running when doing role switch
*/
struct ci_hdrc {
struct device *dev;
@@ -254,6 +255,7 @@ struct ci_hdrc {
bool in_lpm;
bool wakeup_int;
enum ci_revision rev;
+ struct mutex mutex;
};
static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index c13f9a153a5c..3fd1073a345d 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -872,9 +872,16 @@ static ssize_t role_store(struct device *dev,
strlen(ci->roles[role]->name)))
break;
- if (role == CI_ROLE_END || role == ci->role)
+ if (role == CI_ROLE_END)
return -EINVAL;
+ mutex_lock(&ci->mutex);
+
+ if (role == ci->role) {
+ mutex_unlock(&ci->mutex);
+ return n;
+ }
+
pm_runtime_get_sync(dev);
disable_irq(ci->irq);
ci_role_stop(ci);
@@ -883,6 +890,7 @@ static ssize_t role_store(struct device *dev,
ci_handle_vbus_change(ci);
enable_irq(ci->irq);
pm_runtime_put_sync(dev);
+ mutex_unlock(&ci->mutex);
return (ret == 0) ? n : ret;
}
@@ -921,6 +929,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENOMEM;
spin_lock_init(&ci->lock);
+ mutex_init(&ci->mutex);
ci->dev = dev;
ci->platdata = dev_get_platdata(dev);
ci->imx28_write_fix = !!(ci->platdata->flags &
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index f25d4827fd49..a714cf3f0ab7 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -164,8 +164,10 @@ static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
static void ci_handle_id_switch(struct ci_hdrc *ci)
{
- enum ci_role role = ci_otg_role(ci);
+ enum ci_role role;
+ mutex_lock(&ci->mutex);
+ role = ci_otg_role(ci);
if (role != ci->role) {
dev_dbg(ci->dev, "switching from %s to %s\n",
ci_role(ci)->name, ci->roles[role]->name);
@@ -188,6 +190,7 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
if (role == CI_ROLE_GADGET)
ci_handle_vbus_change(ci);
}
+ mutex_unlock(&ci->mutex);
}
/**
* ci_otg_work - perform otg (vbus/id) event handle
diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c
index 168303f21bf4..3136a239e782 100644
--- a/drivers/usb/gadget/function/u_audio.c
+++ b/drivers/usb/gadget/function/u_audio.c
@@ -626,7 +626,7 @@ void g_audio_cleanup(struct g_audio *g_audio)
uac = g_audio->uac;
card = uac->card;
if (card)
- snd_card_free(card);
+ snd_card_free_when_closed(card);
kfree(uac->p_prm.ureq);
kfree(uac->c_prm.ureq);
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 3e2474959735..7679fb583e41 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -148,7 +148,7 @@ static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *pxa_ohci, int mode)
uhcrhda |= RH_A_NPS;
break;
case PMM_GLOBAL_MODE:
- uhcrhda &= ~(RH_A_NPS & RH_A_PSM);
+ uhcrhda &= ~(RH_A_NPS | RH_A_PSM);
break;
case PMM_PERPORT_MODE:
uhcrhda &= ~(RH_A_NPS);
diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h
index d4fa29b623ff..a4513dd931b2 100644
--- a/drivers/usb/storage/unusual_uas.h
+++ b/drivers/usb/storage/unusual_uas.h
@@ -111,6 +111,13 @@ UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x9999,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_BROKEN_FUA),
+/* Reported by: Yaroslav Furman <yaro330@gmail.com> */
+UNUSUAL_DEV(0x152d, 0x0583, 0x0000, 0x9999,
+ "JMicron",
+ "JMS583Gen 2",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_NO_REPORT_OPCODES),
+
/* Reported-by: Thinh Nguyen <thinhn@synopsys.com> */
UNUSUAL_DEV(0x154b, 0xf00b, 0x0000, 0x9999,
"PNY",
diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c
index 3872ccef4cb2..f8e83a951918 100644
--- a/drivers/video/fbdev/au1200fb.c
+++ b/drivers/video/fbdev/au1200fb.c
@@ -1039,6 +1039,9 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
u32 pixclock;
int screen_size, plane;
+ if (!var->pixclock)
+ return -EINVAL;
+
plane = fbdev->plane;
/* Make sure that the mode respect all LCD controller and
diff --git a/drivers/video/fbdev/geode/lxfb_core.c b/drivers/video/fbdev/geode/lxfb_core.c
index 138da6cb6cbc..4345246b4c79 100644
--- a/drivers/video/fbdev/geode/lxfb_core.c
+++ b/drivers/video/fbdev/geode/lxfb_core.c
@@ -247,6 +247,9 @@ static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
+ if (!var->pixclock)
+ return -EINVAL;
+
if (var->xres > 1920 || var->yres > 1440)
return -EINVAL;
diff --git a/drivers/video/fbdev/intelfb/intelfbdrv.c b/drivers/video/fbdev/intelfb/intelfbdrv.c
index d7463a2a5d83..c97c0c851480 100644
--- a/drivers/video/fbdev/intelfb/intelfbdrv.c
+++ b/drivers/video/fbdev/intelfb/intelfbdrv.c
@@ -1215,6 +1215,9 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
dinfo = GET_DINFO(info);
+ if (!var->pixclock)
+ return -EINVAL;
+
/* update the pitch */
if (intelfbhw_validate_mode(dinfo, var) != 0)
return -EINVAL;
diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c
index fbeeed5afe35..aa502b3ba25a 100644
--- a/drivers/video/fbdev/nvidia/nvidia.c
+++ b/drivers/video/fbdev/nvidia/nvidia.c
@@ -766,6 +766,8 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var,
int pitch, err = 0;
NVTRACE_ENTER();
+ if (!var->pixclock)
+ return -EINVAL;
var->transp.offset = 0;
var->transp.length = 0;
diff --git a/drivers/video/fbdev/tgafb.c b/drivers/video/fbdev/tgafb.c
index 65ba9921506e..9d2912947eef 100644
--- a/drivers/video/fbdev/tgafb.c
+++ b/drivers/video/fbdev/tgafb.c
@@ -166,6 +166,9 @@ tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct tga_par *par = (struct tga_par *)info->par;
+ if (!var->pixclock)
+ return -EINVAL;
+
if (par->tga_type == TGA_TYPE_8PLANE) {
if (var->bits_per_pixel != 8)
return -EINVAL;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index f047e87871a1..c1d5daa4b351 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -121,7 +121,10 @@ extern const struct dentry_operations cifs_ci_dentry_ops;
#ifdef CONFIG_CIFS_DFS_UPCALL
extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
#else
-#define cifs_dfs_d_automount NULL
+static inline struct vfsmount *cifs_dfs_d_automount(struct path *path)
+{
+ return ERR_PTR(-EREMOTE);
+}
#endif
/* Functions related to symlinks */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index cb70f0c6aa1b..d16fd8d1f291 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -4895,8 +4895,13 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
return -ENODEV;
getDFSRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
- (void **) &pSMBr);
+ /*
+ * Use smb_init_no_reconnect() instead of smb_init() as
+ * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
+ * causing an infinite recursion.
+ */
+ rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
+ (void **)&pSMB, (void **)&pSMBr);
if (rc)
return rc;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index f906984eb25b..118bcb351af9 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -475,7 +475,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
if (rc == -EOPNOTSUPP) {
cifs_dbg(FYI,
"server does not support query network interfaces\n");
- goto out;
+ ret_data_len = 0;
} else if (rc != 0) {
cifs_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
goto out;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e844d91c461b..7aaf4dafd3e7 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1428,7 +1428,8 @@ static int ext4_write_end(struct file *file,
int inline_data = ext4_has_inline_data(inode);
trace_ext4_write_end(inode, pos, len, copied);
- if (inline_data) {
+ if (inline_data &&
+ ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
ret = ext4_write_inline_data_end(inode, pos, len,
copied, page);
if (ret < 0) {
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index c5390421cca2..d9866d89f2fb 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -480,8 +480,6 @@ int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
return error;
kaddr = kmap_atomic(page);
- if (dsize > gfs2_max_stuffed_size(ip))
- dsize = gfs2_max_stuffed_size(ip);
memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
memset(kaddr + dsize, 0, PAGE_SIZE - dsize);
kunmap_atomic(kaddr);
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 150cec85c416..ccafd45b63f6 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -72,9 +72,6 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
void *kaddr = kmap(page);
u64 dsize = i_size_read(inode);
- if (dsize > gfs2_max_stuffed_size(ip))
- dsize = gfs2_max_stuffed_size(ip);
-
memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
memset(kaddr + dsize, 0, PAGE_SIZE - dsize);
kunmap(page);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 20f08f4391c9..a7a423adf7c8 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -388,6 +388,9 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
ip->i_depth = (u8)depth;
ip->i_entries = be32_to_cpu(str->di_entries);
+ if (gfs2_is_stuffed(ip) && ip->i_inode.i_size > gfs2_max_stuffed_size(ip))
+ goto corrupt;
+
if (S_ISREG(ip->i_inode.i_mode))
gfs2_set_aops(&ip->i_inode);
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 708aa1b92036..dfb2083b8ce1 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -70,7 +70,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
if (argv->v_index > ~(__u64)0 - argv->v_nmembs)
return -EINVAL;
- buf = (void *)__get_free_pages(GFP_NOFS, 0);
+ buf = (void *)get_zeroed_page(GFP_NOFS);
if (unlikely(!buf))
return -ENOMEM;
maxmembs = PAGE_SIZE / argv->v_size;
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index b6948813eb06..1353db3f7f48 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -2003,11 +2003,25 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
}
if (unlikely(copied < len) && wc->w_target_page) {
+ loff_t new_isize;
+
if (!PageUptodate(wc->w_target_page))
copied = 0;
- ocfs2_zero_new_buffers(wc->w_target_page, start+copied,
- start+len);
+ new_isize = max_t(loff_t, i_size_read(inode), pos + copied);
+ if (new_isize > page_offset(wc->w_target_page))
+ ocfs2_zero_new_buffers(wc->w_target_page, start+copied,
+ start+len);
+ else {
+ /*
+ * When page is fully beyond new isize (data copy
+ * failed), do not bother zeroing the page. Invalidate
+ * it instead so that writeback does not get confused
+ * put page & buffer dirty bits into inconsistent
+ * state.
+ */
+ block_invalidatepage(wc->w_target_page, 0, PAGE_SIZE);
+ }
}
if (wc->w_target_page)
flush_dcache_page(wc->w_target_page);
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 934633a05d20..7f1478c26a33 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -40,14 +40,14 @@ static inline bool cpusets_enabled(void)
static inline void cpuset_inc(void)
{
- static_branch_inc(&cpusets_pre_enable_key);
- static_branch_inc(&cpusets_enabled_key);
+ static_branch_inc_cpuslocked(&cpusets_pre_enable_key);
+ static_branch_inc_cpuslocked(&cpusets_enabled_key);
}
static inline void cpuset_dec(void)
{
- static_branch_dec(&cpusets_enabled_key);
- static_branch_dec(&cpusets_pre_enable_key);
+ static_branch_dec_cpuslocked(&cpusets_enabled_key);
+ static_branch_dec_cpuslocked(&cpusets_pre_enable_key);
}
extern int cpuset_init(void);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 24e16538e4d7..285101772c75 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -603,7 +603,7 @@ static int __init bpf_jit_charge_init(void)
{
/* Only used as heuristic here to derive limit. */
bpf_jit_limit_max = bpf_jit_alloc_exec_limit();
- bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 2,
+ bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 1,
PAGE_SIZE), LONG_MAX);
return 0;
}
diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
index 61644976225a..c0ebb70808b6 100644
--- a/kernel/cgroup/cgroup-v1.c
+++ b/kernel/cgroup/cgroup-v1.c
@@ -13,6 +13,7 @@
#include <linux/delayacct.h>
#include <linux/pid_namespace.h>
#include <linux/cgroupstats.h>
+#include <linux/cpu.h>
#include <trace/events/cgroup.h>
@@ -55,6 +56,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
int retval = 0;
mutex_lock(&cgroup_mutex);
+ get_online_cpus();
percpu_down_write(&cgroup_threadgroup_rwsem);
for_each_root(root) {
struct cgroup *from_cgrp;
@@ -71,6 +73,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
break;
}
percpu_up_write(&cgroup_threadgroup_rwsem);
+ put_online_cpus();
mutex_unlock(&cgroup_mutex);
return retval;
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index a892a99eb4bf..a8185cdb8587 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -55,6 +55,7 @@
#include <linux/nsproxy.h>
#include <linux/file.h>
#include <linux/sched/cputime.h>
+#include <linux/cpu.h>
#include <net/sock.h>
#define CREATE_TRACE_POINTS
@@ -2209,6 +2210,45 @@ int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen)
}
EXPORT_SYMBOL_GPL(task_cgroup_path);
+/**
+ * cgroup_attach_lock - Lock for ->attach()
+ * @lock_threadgroup: whether to down_write cgroup_threadgroup_rwsem
+ *
+ * cgroup migration sometimes needs to stabilize threadgroups against forks and
+ * exits by write-locking cgroup_threadgroup_rwsem. However, some ->attach()
+ * implementations (e.g. cpuset), also need to disable CPU hotplug.
+ * Unfortunately, letting ->attach() operations acquire cpus_read_lock() can
+ * lead to deadlocks.
+ *
+ * Bringing up a CPU may involve creating and destroying tasks which requires
+ * read-locking threadgroup_rwsem, so threadgroup_rwsem nests inside
+ * cpus_read_lock(). If we call an ->attach() which acquires the cpus lock while
+ * write-locking threadgroup_rwsem, the locking order is reversed and we end up
+ * waiting for an on-going CPU hotplug operation which in turn is waiting for
+ * the threadgroup_rwsem to be released to create new tasks. For more details:
+ *
+ * http://lkml.kernel.org/r/20220711174629.uehfmqegcwn2lqzu@wubuntu
+ *
+ * Resolve the situation by always acquiring cpus_read_lock() before optionally
+ * write-locking cgroup_threadgroup_rwsem. This allows ->attach() to assume that
+ * CPU hotplug is disabled on entry.
+ */
+static void cgroup_attach_lock(void)
+{
+ get_online_cpus();
+ percpu_down_write(&cgroup_threadgroup_rwsem);
+}
+
+/**
+ * cgroup_attach_unlock - Undo cgroup_attach_lock()
+ * @lock_threadgroup: whether to up_write cgroup_threadgroup_rwsem
+ */
+static void cgroup_attach_unlock(void)
+{
+ percpu_up_write(&cgroup_threadgroup_rwsem);
+ put_online_cpus();
+}
+
/**
* cgroup_migrate_add_task - add a migration target task to a migration context
* @task: target task
@@ -2694,7 +2734,7 @@ struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup)
if (kstrtoint(strstrip(buf), 0, &pid) || pid < 0)
return ERR_PTR(-EINVAL);
- percpu_down_write(&cgroup_threadgroup_rwsem);
+ cgroup_attach_lock();
rcu_read_lock();
if (pid) {
@@ -2725,7 +2765,7 @@ struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup)
goto out_unlock_rcu;
out_unlock_threadgroup:
- percpu_up_write(&cgroup_threadgroup_rwsem);
+ cgroup_attach_unlock();
out_unlock_rcu:
rcu_read_unlock();
return tsk;
@@ -2740,7 +2780,7 @@ void cgroup_procs_write_finish(struct task_struct *task)
/* release reference from cgroup_procs_write_start() */
put_task_struct(task);
- percpu_up_write(&cgroup_threadgroup_rwsem);
+ cgroup_attach_unlock();
for_each_subsys(ss, ssid)
if (ss->post_attach)
ss->post_attach();
@@ -2799,7 +2839,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
lockdep_assert_held(&cgroup_mutex);
- percpu_down_write(&cgroup_threadgroup_rwsem);
+ cgroup_attach_lock();
/* look up all csses currently attached to @cgrp's subtree */
spin_lock_irq(&css_set_lock);
@@ -2830,7 +2870,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
ret = cgroup_migrate_execute(&mgctx);
out_finish:
cgroup_migrate_finish(&mgctx);
- percpu_up_write(&cgroup_threadgroup_rwsem);
+ cgroup_attach_unlock();
return ret;
}
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index dcd5755b1fe2..c6d412cebc43 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -830,8 +830,8 @@ static void rebuild_sched_domains_locked(void)
cpumask_var_t *doms;
int ndoms;
+ lockdep_assert_cpus_held();
lockdep_assert_held(&cpuset_mutex);
- get_online_cpus();
/*
* We have raced with CPU hotplug. Don't do anything to avoid
@@ -839,15 +839,13 @@ static void rebuild_sched_domains_locked(void)
* Anyways, hotplug work item will rebuild sched domains.
*/
if (!cpumask_equal(top_cpuset.effective_cpus, cpu_active_mask))
- goto out;
+ return;
/* Generate domain masks and attrs */
ndoms = generate_sched_domains(&doms, &attr);
/* Have scheduler rebuild the domains */
partition_sched_domains(ndoms, doms, attr);
-out:
- put_online_cpus();
}
#else /* !CONFIG_SMP */
static void rebuild_sched_domains_locked(void)
@@ -857,9 +855,11 @@ static void rebuild_sched_domains_locked(void)
void rebuild_sched_domains(void)
{
+ get_online_cpus();
mutex_lock(&cpuset_mutex);
rebuild_sched_domains_locked();
mutex_unlock(&cpuset_mutex);
+ put_online_cpus();
}
/**
@@ -1528,13 +1528,9 @@ static void cpuset_attach(struct cgroup_taskset *tset)
cgroup_taskset_first(tset, &css);
cs = css_cs(css);
+ lockdep_assert_cpus_held(); /* see cgroup_attach_lock() */
mutex_lock(&cpuset_mutex);
- /*
- * It should hold cpus lock because a cpu offline event can
- * cause set_cpus_allowed_ptr() failed.
- */
- get_online_cpus();
/* prepare for attach */
if (cs == &top_cpuset)
cpumask_copy(cpus_attach, cpu_possible_mask);
@@ -1553,7 +1549,6 @@ static void cpuset_attach(struct cgroup_taskset *tset)
cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
cpuset_update_task_spread_flag(cs, task);
}
- put_online_cpus();
/*
* Change mm for all threadgroup leaders. This is expensive and may
@@ -1617,6 +1612,7 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft,
cpuset_filetype_t type = cft->private;
int retval = 0;
+ get_online_cpus();
mutex_lock(&cpuset_mutex);
if (!is_cpuset_online(cs)) {
retval = -ENODEV;
@@ -1654,6 +1650,7 @@ static int cpuset_write_u64(struct cgroup_subsys_state *css, struct cftype *cft,
}
out_unlock:
mutex_unlock(&cpuset_mutex);
+ put_online_cpus();
return retval;
}
@@ -1664,6 +1661,7 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft,
cpuset_filetype_t type = cft->private;
int retval = -ENODEV;
+ get_online_cpus();
mutex_lock(&cpuset_mutex);
if (!is_cpuset_online(cs))
goto out_unlock;
@@ -1678,6 +1676,7 @@ static int cpuset_write_s64(struct cgroup_subsys_state *css, struct cftype *cft,
}
out_unlock:
mutex_unlock(&cpuset_mutex);
+ put_online_cpus();
return retval;
}
@@ -1716,6 +1715,7 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
kernfs_break_active_protection(of->kn);
flush_work(&cpuset_hotplug_work);
+ get_online_cpus();
mutex_lock(&cpuset_mutex);
if (!is_cpuset_online(cs))
goto out_unlock;
@@ -1741,6 +1741,7 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
free_trial_cpuset(trialcs);
out_unlock:
mutex_unlock(&cpuset_mutex);
+ put_online_cpus();
kernfs_unbreak_active_protection(of->kn);
css_put(&cs->css);
flush_workqueue(cpuset_migrate_mm_wq);
@@ -1985,6 +1986,7 @@ static int cpuset_css_online(struct cgroup_subsys_state *css)
if (!parent)
return 0;
+ get_online_cpus();
mutex_lock(&cpuset_mutex);
set_bit(CS_ONLINE, &cs->flags);
@@ -2035,6 +2037,7 @@ static int cpuset_css_online(struct cgroup_subsys_state *css)
spin_unlock_irq(&callback_lock);
out_unlock:
mutex_unlock(&cpuset_mutex);
+ put_online_cpus();
return 0;
}
@@ -2048,6 +2051,7 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css)
{
struct cpuset *cs = css_cs(css);
+ get_online_cpus();
mutex_lock(&cpuset_mutex);
if (is_sched_load_balance(cs))
@@ -2057,6 +2061,7 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css)
clear_bit(CS_ONLINE, &cs->flags);
mutex_unlock(&cpuset_mutex);
+ put_online_cpus();
}
static void cpuset_css_free(struct cgroup_subsys_state *css)
diff --git a/kernel/compat.c b/kernel/compat.c
index e4548a9e9c52..5f320b0db8d0 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -307,7 +307,7 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t, pid, unsigned int, len,
if (len & (sizeof(compat_ulong_t)-1))
return -EINVAL;
- if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+ if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
return -ENOMEM;
ret = sched_getaffinity(pid, mask);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 46227cc48124..8d5a9fa8a951 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -741,6 +741,9 @@ static inline void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
void activate_task(struct rq *rq, struct task_struct *p, int flags)
{
+ if (task_on_rq_migrating(p))
+ flags |= ENQUEUE_MIGRATED;
+
if (task_contributes_to_load(p))
rq->nr_uninterruptible--;
@@ -4950,14 +4953,14 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
if (len & (sizeof(unsigned long)-1))
return -EINVAL;
- if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+ if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
return -ENOMEM;
ret = sched_getaffinity(pid, mask);
if (ret == 0) {
unsigned int retlen = min(len, cpumask_size());
- if (copy_to_user(user_mask_ptr, mask, retlen))
+ if (copy_to_user(user_mask_ptr, cpumask_bits(mask), retlen))
ret = -EFAULT;
else
ret = retlen;
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 84e7efda98da..eb67f42fb96b 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3854,6 +3854,29 @@ static void check_spread(struct cfs_rq *cfs_rq, struct sched_entity *se)
#endif
}
+static inline bool entity_is_long_sleeper(struct sched_entity *se)
+{
+ struct cfs_rq *cfs_rq;
+ u64 sleep_time;
+
+ if (se->exec_start == 0)
+ return false;
+
+ cfs_rq = cfs_rq_of(se);
+
+ sleep_time = rq_clock_task(rq_of(cfs_rq));
+
+ /* Happen while migrating because of clock task divergence */
+ if (sleep_time <= se->exec_start)
+ return false;
+
+ sleep_time -= se->exec_start;
+ if (sleep_time > ((1ULL << 63) / scale_load_down(NICE_0_LOAD)))
+ return true;
+
+ return false;
+}
+
static void
place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
{
@@ -3882,8 +3905,29 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
vruntime -= thresh;
}
- /* ensure we never gain time by being placed backwards. */
- se->vruntime = max_vruntime(se->vruntime, vruntime);
+ /*
+ * Pull vruntime of the entity being placed to the base level of
+ * cfs_rq, to prevent boosting it if placed backwards.
+ * However, min_vruntime can advance much faster than real time, with
+ * the extreme being when an entity with the minimal weight always runs
+ * on the cfs_rq. If the waking entity slept for a long time, its
+ * vruntime difference from min_vruntime may overflow s64 and their
+ * comparison may get inversed, so ignore the entity's original
+ * vruntime in that case.
+ * The maximal vruntime speedup is given by the ratio of normal to
+ * minimal weight: scale_load_down(NICE_0_LOAD) / MIN_SHARES.
+ * When placing a migrated waking entity, its exec_start has been set
+ * from a different rq. In order to take into account a possible
+ * divergence between new and prev rq's clocks task because of irq and
+ * stolen time, we take an additional margin.
+ * So, cutting off on the sleep time of
+ * 2^63 / scale_load_down(NICE_0_LOAD) ~ 104 days
+ * should be safe.
+ */
+ if (entity_is_long_sleeper(se))
+ se->vruntime = vruntime;
+ else
+ se->vruntime = max_vruntime(se->vruntime, vruntime);
}
static void check_enqueue_throttle(struct cfs_rq *cfs_rq);
@@ -3978,6 +4022,9 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
if (flags & ENQUEUE_WAKEUP)
place_entity(cfs_rq, se, 0);
+ /* Entity has migrated, no longer consider this task hot */
+ if (flags & ENQUEUE_MIGRATED)
+ se->exec_start = 0;
check_schedstat_required();
update_stats_enqueue(cfs_rq, se, flags);
@@ -6544,9 +6591,6 @@ static void migrate_task_rq_fair(struct task_struct *p, int new_cpu)
/* Tell new CPU we are migrated */
p->se.avg.last_update_time = 0;
- /* We have migrated, no longer consider this task hot */
- p->se.exec_start = 0;
-
update_scan_period(p, new_cpu);
}
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 74e555a22de7..61269cc2fa82 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -935,6 +935,8 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
cf = op->frames + op->cfsiz * i;
err = memcpy_from_msg((u8 *)cf, msg, op->cfsiz);
+ if (err < 0)
+ goto free_op;
if (op->flags & CAN_FD_FRAME) {
if (cf->len > 64)
@@ -944,12 +946,8 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
err = -EINVAL;
}
- if (err < 0) {
- if (op->frames != &op->sframe)
- kfree(op->frames);
- kfree(op);
- return err;
- }
+ if (err < 0)
+ goto free_op;
if (msg_head->flags & TX_CP_CAN_ID) {
/* copy can_id into frame */
@@ -1020,6 +1018,12 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
bcm_tx_start_timer(op);
return msg_head->nframes * op->cfsiz + MHSIZ;
+
+free_op:
+ if (op->frames != &op->sframe)
+ kfree(op->frames);
+ kfree(op);
+ return err;
}
/*
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index c72432ce9bf5..898753328c17 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -603,7 +603,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
truncate = true;
}
- nhoff = skb_network_header(skb) - skb_mac_header(skb);
+ nhoff = skb_network_offset(skb);
if (skb->protocol == htons(ETH_P_IP) &&
(ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
truncate = true;
@@ -612,7 +612,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
int thoff;
if (skb_transport_header_was_set(skb))
- thoff = skb_transport_header(skb) - skb_mac_header(skb);
+ thoff = skb_transport_offset(skb);
else
thoff = nhoff + sizeof(struct ipv6hdr);
if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 00601bc4fdfa..166b7544e54a 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -961,7 +961,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
truncate = true;
}
- nhoff = skb_network_header(skb) - skb_mac_header(skb);
+ nhoff = skb_network_offset(skb);
if (skb->protocol == htons(ETH_P_IP) &&
(ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
truncate = true;
@@ -970,7 +970,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
int thoff;
if (skb_transport_header_was_set(skb))
- thoff = skb_transport_header(skb) - skb_mac_header(skb);
+ thoff = skb_transport_offset(skb);
else
thoff = nhoff + sizeof(struct ipv6hdr);
if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 0a76ad05e5ae..2974f7262f88 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -236,6 +236,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
result = tcf_classify(skb, fl, &res, true);
if (!fl || result < 0)
goto fallback;
+ if (result == TC_ACT_SHOT)
+ return NULL;
cl = (void *)res.class;
if (!cl) {
@@ -256,8 +258,6 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
case TC_ACT_TRAP:
*qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
/* fall through */
- case TC_ACT_SHOT:
- return NULL;
case TC_ACT_RECLASSIFY:
return cbq_reclassify(skb, cl);
}
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c
index 2864698436a5..6a49f897c4d9 100644
--- a/sound/pci/asihpi/hpi6205.c
+++ b/sound/pci/asihpi/hpi6205.c
@@ -441,7 +441,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
pao = hpi_find_adapter(phm->adapter_index);
} else {
/* subsys messages don't address an adapter */
- _HPI_6205(NULL, phm, phr);
+ phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
return;
}
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index ca8a37388d56..9f0e6bbc523c 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -3620,8 +3620,10 @@ static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid,
for (i = 0; i < TUNING_CTLS_COUNT; i++)
if (nid == ca0132_tuning_ctls[i].nid)
- break;
+ goto found;
+ return -EINVAL;
+found:
snd_hda_power_up(codec);
dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20,
ca0132_tuning_ctls[i].req,
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 69f88d3abf50..cfa958dc2dd5 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -952,7 +952,10 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x17aa, 0x3905, "Lenovo G50-30", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_PINCFG_LENOVO_NOTEBOOK),
+ /* NOTE: we'd need to extend the quirk for 17aa:3977 as the same
+ * PCI SSID is used on multiple Lenovo models
+ */
+ SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo G50-70", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI),
@@ -974,6 +977,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
{ .id = CXT_FIXUP_HP_DOCK, .name = "hp-dock" },
{ .id = CXT_FIXUP_MUTE_LED_GPIO, .name = "mute-led-gpio" },
{ .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" },
+ { .id = CXT_PINCFG_LENOVO_NOTEBOOK, .name = "lenovo-20149" },
{}
};
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 01ba7a939ac4..342d6edb06ad 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -53,8 +53,12 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
case UAC_VERSION_1:
default: {
struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
- if (format >= 64)
- return 0; /* invalid format */
+ if (format >= 64) {
+ usb_audio_info(chip,
+ "%u:%d: invalid format type 0x%llx is detected, processed as PCM\n",
+ fp->iface, fp->altsetting, format);
+ format = UAC_FORMAT_TYPE_I_PCM;
+ }
sample_width = fmt->bBitResolution;
sample_bytes = fmt->bSubframeSize;
format = 1ULL << format;
^ permalink raw reply related [relevance 1%]
* Re: [PATCH 1/1] serial: 8250: Prevent starting up DMA Rx on THRI interrupt
2023-03-17 10:30 6% [PATCH 1/1] serial: 8250: Prevent starting up DMA Rx on THRI interrupt Ilpo Järvinen
@ 2023-03-20 9:52 0% ` Hans de Goede
0 siblings, 0 replies; 200+ results
From: Hans de Goede @ 2023-03-20 9:52 UTC (permalink / raw)
To: Ilpo Järvinen, Greg Kroah-Hartman, Jiri Slaby, linux-serial,
linux-kernel
Cc: stable
Hi,
On 3/17/23 11:30, Ilpo Järvinen wrote:
> Hans de Goede reported Bluetooth adapters (HCIs) connected over an UART
> connection failed due corrupted Rx payload. The problem was narrowed
> down to DMA Rx starting on UART_IIR_THRI interrupt. The problem occurs
> despite LSR having DR bit set, which is precondition for attempting to
> start DMA Rx in the first place.
>
> From a debug patch:
> [x.807834] 8250irq: iir=cc lsr+saved=60 received=0/15 ier=0f dma_t/rx/err=0/0/0
> [x.808676] 8250irq: iir=c2 lsr+saved=61 received=0/0 ier=0f dma_t/rx/err=0/0/0
> [x.808776] 8250irq: iir=cc lsr+saved=60 received=1/12 ier=0d dma_t/rx/err=0/1/0
> [x.808870] Bluetooth: hci0: Frame reassembly failed (-84)
>
> In the debug snippet, received field indicates 1 byte was transferred
> over DMA and 12 bytes after that with the non-DMA Rx. The sole byte DMA
> handled was corrupted (gets zeroed) which leads to the HCI failure.
>
> This problem became apparent after commit e8ffbb71f783 ("serial: 8250:
> use THRE & __stop_tx also with DMA") changed Tx stop behavior. Tx stop
> is now triggered from a THRI interrupt.
>
> Despite that this problem looks like a HW bug, this fix is not adding
> UART_BUG_xx flag to the driver beucase it seems useful in general to
> avoid starting DMA when there are only a few bytes to transfer.
> Skipping DMA for small transfers avoids the extra overhead DMA incurs.
>
> Thus, don't setup DMA Rx on UART_IIR_THRI but leave it to a subsequent
> interrupt which has Rx a related IIR value.
>
> By returning false from handle_rx_dma(), the DMA vs non-DMA decision is
> postponed until either UART_IIR_RDI (FIFO threshold worth of bytes
> awaiting) or UART_IIR_TIMEOUT (inter-character timeout) triggers at a
> later time which allows better to discern whether the number of bytes
> warrants starting DMA or not.
>
> Reported-by: Hans de Goede <hdegoede@redhat.com>
> Tested-by: Hans de Goede <hdegoede@redhat.com>
> Fixes: e8ffbb71f783 ("serial: 8250: use THRE & __stop_tx also with DMA")
> Cc: stable@vger.kernel.org
> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Thanks, patch looks good to me:
Acked-by: Hans de Goede <hdegoede@redhat.com>
Regards,
Hans
> ---
> drivers/tty/serial/8250/8250_port.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> index fa43df05342b..3ba9c8b93ae6 100644
> --- a/drivers/tty/serial/8250/8250_port.c
> +++ b/drivers/tty/serial/8250/8250_port.c
> @@ -1903,6 +1903,17 @@ EXPORT_SYMBOL_GPL(serial8250_modem_status);
> static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
> {
> switch (iir & 0x3f) {
> + case UART_IIR_THRI:
> + /*
> + * Postpone DMA or not decision to IIR_RDI or IIR_RX_TIMEOUT
> + * because it's impossible to do an informed decision about
> + * that with IIR_THRI.
> + *
> + * This also fixes one known DMA Rx corruption issue where
> + * DR is asserted but DMA Rx only gets a corrupted zero byte
> + * (too early DR?).
> + */
> + return false;
> case UART_IIR_RDI:
> if (!up->dma->rx_running)
> break;
^ permalink raw reply [relevance 0%]
* [PATCH 1/1] serial: 8250: Prevent starting up DMA Rx on THRI interrupt
@ 2023-03-17 10:30 6% Ilpo Järvinen
2023-03-20 9:52 0% ` Hans de Goede
0 siblings, 1 reply; 200+ results
From: Ilpo Järvinen @ 2023-03-17 10:30 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Ilpo Järvinen, linux-serial,
linux-kernel
Cc: Hans de Goede, stable
Hans de Goede reported Bluetooth adapters (HCIs) connected over an UART
connection failed due corrupted Rx payload. The problem was narrowed
down to DMA Rx starting on UART_IIR_THRI interrupt. The problem occurs
despite LSR having DR bit set, which is precondition for attempting to
start DMA Rx in the first place.
From a debug patch:
[x.807834] 8250irq: iir=cc lsr+saved=60 received=0/15 ier=0f dma_t/rx/err=0/0/0
[x.808676] 8250irq: iir=c2 lsr+saved=61 received=0/0 ier=0f dma_t/rx/err=0/0/0
[x.808776] 8250irq: iir=cc lsr+saved=60 received=1/12 ier=0d dma_t/rx/err=0/1/0
[x.808870] Bluetooth: hci0: Frame reassembly failed (-84)
In the debug snippet, received field indicates 1 byte was transferred
over DMA and 12 bytes after that with the non-DMA Rx. The sole byte DMA
handled was corrupted (gets zeroed) which leads to the HCI failure.
This problem became apparent after commit e8ffbb71f783 ("serial: 8250:
use THRE & __stop_tx also with DMA") changed Tx stop behavior. Tx stop
is now triggered from a THRI interrupt.
Despite that this problem looks like a HW bug, this fix is not adding
UART_BUG_xx flag to the driver beucase it seems useful in general to
avoid starting DMA when there are only a few bytes to transfer.
Skipping DMA for small transfers avoids the extra overhead DMA incurs.
Thus, don't setup DMA Rx on UART_IIR_THRI but leave it to a subsequent
interrupt which has Rx a related IIR value.
By returning false from handle_rx_dma(), the DMA vs non-DMA decision is
postponed until either UART_IIR_RDI (FIFO threshold worth of bytes
awaiting) or UART_IIR_TIMEOUT (inter-character timeout) triggers at a
later time which allows better to discern whether the number of bytes
warrants starting DMA or not.
Reported-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Fixes: e8ffbb71f783 ("serial: 8250: use THRE & __stop_tx also with DMA")
Cc: stable@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
drivers/tty/serial/8250/8250_port.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index fa43df05342b..3ba9c8b93ae6 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1903,6 +1903,17 @@ EXPORT_SYMBOL_GPL(serial8250_modem_status);
static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
{
switch (iir & 0x3f) {
+ case UART_IIR_THRI:
+ /*
+ * Postpone DMA or not decision to IIR_RDI or IIR_RX_TIMEOUT
+ * because it's impossible to do an informed decision about
+ * that with IIR_THRI.
+ *
+ * This also fixes one known DMA Rx corruption issue where
+ * DR is asserted but DMA Rx only gets a corrupted zero byte
+ * (too early DR?).
+ */
+ return false;
case UART_IIR_RDI:
if (!up->dma->rx_running)
break;
--
2.30.2
^ permalink raw reply related [relevance 6%]
* [PATCH 6.2 084/141] m68k: mm: Move initrd phys_to_virt handling after paging_init()
@ 2023-03-15 12:13 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-03-15 12:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Stephen Walsh,
John Paul Adrian Glaubitz, Geert Uytterhoeven, Finn Thain,
Sasha Levin
From: Geert Uytterhoeven <geert@linux-m68k.org>
[ Upstream commit d4b97925e87eb133e400fe4a482d750c74ce392f ]
When booting with an initial ramdisk on platforms where physical memory
does not start at address zero (e.g. on Amiga):
initrd: 0ef0602c - 0f800000
Zone ranges:
DMA [mem 0x0000000008000000-0x000000f7ffffffff]
Normal empty
Movable zone start for each node
Early memory node ranges
node 0: [mem 0x0000000008000000-0x000000000f7fffff]
Initmem setup node 0 [mem 0x0000000008000000-0x000000000f7fffff]
Unable to handle kernel access at virtual address (ptrval)
Oops: 00000000
Modules linked in:
PC: [<00201d3c>] memcmp+0x28/0x56
As phys_to_virt() relies on m68k_memoffset and module_fixup(), it must
not be called before paging_init(). Hence postpone the phys_to_virt
handling for the initial ramdisk until after calling paging_init().
While at it, reduce #ifdef clutter by using IS_ENABLED() instead.
Fixes: 376e3fdecb0dcae2 ("m68k: Enable memtest functionality")
Reported-by: Stephen Walsh <vk3heg@vk3heg.net>
Link: https://lists.debian.org/debian-68k/2022/09/msg00007.html
Reported-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Link: https://lore.kernel.org/r/4f45f05f377bf3f5baf88dbd5c3c8aeac59d94f0.camel@physik.fu-berlin.de
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Finn Thain <fthain@linux-m68k.org>
Link: https://lore.kernel.org/r/dff216da09ab7a60217c3fc2147e671ae07d636f.1677528627.git.geert@linux-m68k.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/m68k/kernel/setup_mm.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index 3a2bb2e8fdad4..fbff1cea62caa 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -326,16 +326,16 @@ void __init setup_arch(char **cmdline_p)
panic("No configuration setup");
}
-#ifdef CONFIG_BLK_DEV_INITRD
- if (m68k_ramdisk.size) {
+ if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && m68k_ramdisk.size)
memblock_reserve(m68k_ramdisk.addr, m68k_ramdisk.size);
+
+ paging_init();
+
+ if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && m68k_ramdisk.size) {
initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
initrd_end = initrd_start + m68k_ramdisk.size;
pr_info("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
}
-#endif
-
- paging_init();
#ifdef CONFIG_NATFEAT
nf_init();
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 6.1 090/143] m68k: mm: Move initrd phys_to_virt handling after paging_init()
@ 2023-03-15 12:12 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-03-15 12:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Stephen Walsh,
John Paul Adrian Glaubitz, Geert Uytterhoeven, Finn Thain,
Sasha Levin
From: Geert Uytterhoeven <geert@linux-m68k.org>
[ Upstream commit d4b97925e87eb133e400fe4a482d750c74ce392f ]
When booting with an initial ramdisk on platforms where physical memory
does not start at address zero (e.g. on Amiga):
initrd: 0ef0602c - 0f800000
Zone ranges:
DMA [mem 0x0000000008000000-0x000000f7ffffffff]
Normal empty
Movable zone start for each node
Early memory node ranges
node 0: [mem 0x0000000008000000-0x000000000f7fffff]
Initmem setup node 0 [mem 0x0000000008000000-0x000000000f7fffff]
Unable to handle kernel access at virtual address (ptrval)
Oops: 00000000
Modules linked in:
PC: [<00201d3c>] memcmp+0x28/0x56
As phys_to_virt() relies on m68k_memoffset and module_fixup(), it must
not be called before paging_init(). Hence postpone the phys_to_virt
handling for the initial ramdisk until after calling paging_init().
While at it, reduce #ifdef clutter by using IS_ENABLED() instead.
Fixes: 376e3fdecb0dcae2 ("m68k: Enable memtest functionality")
Reported-by: Stephen Walsh <vk3heg@vk3heg.net>
Link: https://lists.debian.org/debian-68k/2022/09/msg00007.html
Reported-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Link: https://lore.kernel.org/r/4f45f05f377bf3f5baf88dbd5c3c8aeac59d94f0.camel@physik.fu-berlin.de
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Finn Thain <fthain@linux-m68k.org>
Link: https://lore.kernel.org/r/dff216da09ab7a60217c3fc2147e671ae07d636f.1677528627.git.geert@linux-m68k.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/m68k/kernel/setup_mm.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index 3a2bb2e8fdad4..fbff1cea62caa 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -326,16 +326,16 @@ void __init setup_arch(char **cmdline_p)
panic("No configuration setup");
}
-#ifdef CONFIG_BLK_DEV_INITRD
- if (m68k_ramdisk.size) {
+ if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && m68k_ramdisk.size)
memblock_reserve(m68k_ramdisk.addr, m68k_ramdisk.size);
+
+ paging_init();
+
+ if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && m68k_ramdisk.size) {
initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
initrd_end = initrd_start + m68k_ramdisk.size;
pr_info("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
}
-#endif
-
- paging_init();
#ifdef CONFIG_NATFEAT
nf_init();
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 5.4 13/68] drm/edid: fix AVI infoframe aspect ratio handling
@ 2023-03-15 12:12 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-03-15 12:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, William Tseng,
Ville Syrjälä,
Jani Nikula, Sasha Levin
From: Jani Nikula <jani.nikula@intel.com>
[ Upstream commit 1cbc1f0d324ba6c4d1b10ac6362b5e0b029f63d5 ]
We try to avoid sending VICs defined in the later specs in AVI
infoframes to sinks that conform to the earlier specs, to not upset
them, and use 0 for the VIC instead. However, we do this detection and
conversion to 0 too early, as we'll need the actual VIC to figure out
the aspect ratio.
In particular, for a mode with 64:27 aspect ratio, 0 for VIC fails the
AVI infoframe generation altogether with -EINVAL.
Separate the VIC lookup from the "filtering", and postpone the
filtering, to use the proper VIC for aspect ratio handling, and the 0
VIC for the infoframe video code as needed.
Reported-by: William Tseng <william.tseng@intel.com>
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6153
Cc: <stable@vger.kernel.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/c3e78cc6d01ed237f71ad0038826b08d83d75eef.1672826282.git.jani.nikula@intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/drm_edid.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index f9735861741c1..2e73042e5d070 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5095,8 +5095,6 @@ static u8 drm_mode_hdmi_vic(struct drm_connector *connector,
static u8 drm_mode_cea_vic(struct drm_connector *connector,
const struct drm_display_mode *mode)
{
- u8 vic;
-
/*
* HDMI spec says if a mode is found in HDMI 1.4b 4K modes
* we should send its VIC in vendor infoframes, else send the
@@ -5106,13 +5104,18 @@ static u8 drm_mode_cea_vic(struct drm_connector *connector,
if (drm_mode_hdmi_vic(connector, mode))
return 0;
- vic = drm_match_cea_mode(mode);
+ return drm_match_cea_mode(mode);
+}
- /*
- * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
- * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
- * have to make sure we dont break HDMI 1.4 sinks.
- */
+/*
+ * Avoid sending VICs defined in HDMI 2.0 in AVI infoframes to sinks that
+ * conform to HDMI 1.4.
+ *
+ * HDMI 1.4 (CTA-861-D) VIC range: [1..64]
+ * HDMI 2.0 (CTA-861-F) VIC range: [1..107]
+ */
+static u8 vic_for_avi_infoframe(const struct drm_connector *connector, u8 vic)
+{
if (!is_hdmi2_sink(connector) && vic > 64)
return 0;
@@ -5191,7 +5194,7 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
picture_aspect = HDMI_PICTURE_ASPECT_NONE;
}
- frame->video_code = vic;
+ frame->video_code = vic_for_avi_infoframe(connector, vic);
frame->picture_aspect = picture_aspect;
frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 5.10 425/529] drm/edid: fix AVI infoframe aspect ratio handling
@ 2023-03-10 13:39 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-03-10 13:39 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, William Tseng,
Ville Syrjälä,
Jani Nikula
From: Jani Nikula <jani.nikula@intel.com>
commit 1cbc1f0d324ba6c4d1b10ac6362b5e0b029f63d5 upstream.
We try to avoid sending VICs defined in the later specs in AVI
infoframes to sinks that conform to the earlier specs, to not upset
them, and use 0 for the VIC instead. However, we do this detection and
conversion to 0 too early, as we'll need the actual VIC to figure out
the aspect ratio.
In particular, for a mode with 64:27 aspect ratio, 0 for VIC fails the
AVI infoframe generation altogether with -EINVAL.
Separate the VIC lookup from the "filtering", and postpone the
filtering, to use the proper VIC for aspect ratio handling, and the 0
VIC for the infoframe video code as needed.
Reported-by: William Tseng <william.tseng@intel.com>
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6153
Cc: <stable@vger.kernel.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/c3e78cc6d01ed237f71ad0038826b08d83d75eef.1672826282.git.jani.nikula@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_edid.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5560,8 +5560,6 @@ static u8 drm_mode_hdmi_vic(const struct
static u8 drm_mode_cea_vic(const struct drm_connector *connector,
const struct drm_display_mode *mode)
{
- u8 vic;
-
/*
* HDMI spec says if a mode is found in HDMI 1.4b 4K modes
* we should send its VIC in vendor infoframes, else send the
@@ -5571,13 +5569,18 @@ static u8 drm_mode_cea_vic(const struct
if (drm_mode_hdmi_vic(connector, mode))
return 0;
- vic = drm_match_cea_mode(mode);
+ return drm_match_cea_mode(mode);
+}
- /*
- * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
- * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
- * have to make sure we dont break HDMI 1.4 sinks.
- */
+/*
+ * Avoid sending VICs defined in HDMI 2.0 in AVI infoframes to sinks that
+ * conform to HDMI 1.4.
+ *
+ * HDMI 1.4 (CTA-861-D) VIC range: [1..64]
+ * HDMI 2.0 (CTA-861-F) VIC range: [1..107]
+ */
+static u8 vic_for_avi_infoframe(const struct drm_connector *connector, u8 vic)
+{
if (!is_hdmi2_sink(connector) && vic > 64)
return 0;
@@ -5653,7 +5656,7 @@ drm_hdmi_avi_infoframe_from_display_mode
picture_aspect = HDMI_PICTURE_ASPECT_NONE;
}
- frame->video_code = vic;
+ frame->video_code = vic_for_avi_infoframe(connector, vic);
frame->picture_aspect = picture_aspect;
frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
^ permalink raw reply [relevance 5%]
* [PATCH 6.1 107/200] ASoC: apple: mca: Improve handling of unavailable DMA channels
@ 2023-03-10 13:38 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-03-10 13:38 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Martin Povišer, Mark Brown,
Sasha Levin
From: Martin Povišer <povik+lin@cutebit.org>
[ Upstream commit fb1847cc460c127b12720119eae5f438ffc62e85 ]
When we fail to obtain a DMA channel, don't return a blanket -EINVAL,
instead return the original error code if there's one. This makes
deferring work as it should. Also don't print an error message for
-EPROBE_DEFER.
Fixes: 4ec8179c212f ("ASoC: apple: mca: Postpone requesting of DMA channels")
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Link: https://lore.kernel.org/r/20230224153302.45365-3-povik+lin@cutebit.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/apple/mca.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c
index aea08c7b2ee85..64750db9b9639 100644
--- a/sound/soc/apple/mca.c
+++ b/sound/soc/apple/mca.c
@@ -950,10 +950,17 @@ static int mca_pcm_new(struct snd_soc_component *component,
chan = mca_request_dma_channel(cl, i);
if (IS_ERR_OR_NULL(chan)) {
+ mca_pcm_free(component, rtd->pcm);
+
+ if (chan && PTR_ERR(chan) == -EPROBE_DEFER)
+ return PTR_ERR(chan);
+
dev_err(component->dev, "unable to obtain DMA channel (stream %d cluster %d): %pe\n",
i, cl->no, chan);
- mca_pcm_free(component, rtd->pcm);
- return -EINVAL;
+
+ if (!chan)
+ return -EINVAL;
+ return PTR_ERR(chan);
}
cl->dma_chans[i] = chan;
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 6.2 116/211] ASoC: apple: mca: Improve handling of unavailable DMA channels
@ 2023-03-10 13:38 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-03-10 13:38 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Martin Povišer, Mark Brown,
Sasha Levin
From: Martin Povišer <povik+lin@cutebit.org>
[ Upstream commit fb1847cc460c127b12720119eae5f438ffc62e85 ]
When we fail to obtain a DMA channel, don't return a blanket -EINVAL,
instead return the original error code if there's one. This makes
deferring work as it should. Also don't print an error message for
-EPROBE_DEFER.
Fixes: 4ec8179c212f ("ASoC: apple: mca: Postpone requesting of DMA channels")
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Link: https://lore.kernel.org/r/20230224153302.45365-3-povik+lin@cutebit.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/apple/mca.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c
index aea08c7b2ee85..64750db9b9639 100644
--- a/sound/soc/apple/mca.c
+++ b/sound/soc/apple/mca.c
@@ -950,10 +950,17 @@ static int mca_pcm_new(struct snd_soc_component *component,
chan = mca_request_dma_channel(cl, i);
if (IS_ERR_OR_NULL(chan)) {
+ mca_pcm_free(component, rtd->pcm);
+
+ if (chan && PTR_ERR(chan) == -EPROBE_DEFER)
+ return PTR_ERR(chan);
+
dev_err(component->dev, "unable to obtain DMA channel (stream %d cluster %d): %pe\n",
i, cl->no, chan);
- mca_pcm_free(component, rtd->pcm);
- return -EINVAL;
+
+ if (!chan)
+ return -EINVAL;
+ return PTR_ERR(chan);
}
cl->dma_chans[i] = chan;
--
2.39.2
^ permalink raw reply related [relevance 5%]
* [PATCH 5.15 567/567] drm/edid: fix AVI infoframe aspect ratio handling
@ 2023-03-07 17:05 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-03-07 17:05 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, William Tseng,
Ville Syrjälä,
Jani Nikula
From: Jani Nikula <jani.nikula@intel.com>
commit 1cbc1f0d324ba6c4d1b10ac6362b5e0b029f63d5 upstream.
We try to avoid sending VICs defined in the later specs in AVI
infoframes to sinks that conform to the earlier specs, to not upset
them, and use 0 for the VIC instead. However, we do this detection and
conversion to 0 too early, as we'll need the actual VIC to figure out
the aspect ratio.
In particular, for a mode with 64:27 aspect ratio, 0 for VIC fails the
AVI infoframe generation altogether with -EINVAL.
Separate the VIC lookup from the "filtering", and postpone the
filtering, to use the proper VIC for aspect ratio handling, and the 0
VIC for the infoframe video code as needed.
Reported-by: William Tseng <william.tseng@intel.com>
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6153
Cc: <stable@vger.kernel.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/c3e78cc6d01ed237f71ad0038826b08d83d75eef.1672826282.git.jani.nikula@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_edid.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5598,8 +5598,6 @@ static u8 drm_mode_hdmi_vic(const struct
static u8 drm_mode_cea_vic(const struct drm_connector *connector,
const struct drm_display_mode *mode)
{
- u8 vic;
-
/*
* HDMI spec says if a mode is found in HDMI 1.4b 4K modes
* we should send its VIC in vendor infoframes, else send the
@@ -5609,13 +5607,18 @@ static u8 drm_mode_cea_vic(const struct
if (drm_mode_hdmi_vic(connector, mode))
return 0;
- vic = drm_match_cea_mode(mode);
+ return drm_match_cea_mode(mode);
+}
- /*
- * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
- * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
- * have to make sure we dont break HDMI 1.4 sinks.
- */
+/*
+ * Avoid sending VICs defined in HDMI 2.0 in AVI infoframes to sinks that
+ * conform to HDMI 1.4.
+ *
+ * HDMI 1.4 (CTA-861-D) VIC range: [1..64]
+ * HDMI 2.0 (CTA-861-F) VIC range: [1..107]
+ */
+static u8 vic_for_avi_infoframe(const struct drm_connector *connector, u8 vic)
+{
if (!is_hdmi2_sink(connector) && vic > 64)
return 0;
@@ -5691,7 +5694,7 @@ drm_hdmi_avi_infoframe_from_display_mode
picture_aspect = HDMI_PICTURE_ASPECT_NONE;
}
- frame->video_code = vic;
+ frame->video_code = vic_for_avi_infoframe(connector, vic);
frame->picture_aspect = picture_aspect;
frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
^ permalink raw reply [relevance 5%]
* [PATCH 6.1 884/885] drm/edid: fix AVI infoframe aspect ratio handling
@ 2023-03-07 17:03 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-03-07 17:03 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, William Tseng,
Ville Syrjälä,
Jani Nikula
From: Jani Nikula <jani.nikula@intel.com>
commit 1cbc1f0d324ba6c4d1b10ac6362b5e0b029f63d5 upstream.
We try to avoid sending VICs defined in the later specs in AVI
infoframes to sinks that conform to the earlier specs, to not upset
them, and use 0 for the VIC instead. However, we do this detection and
conversion to 0 too early, as we'll need the actual VIC to figure out
the aspect ratio.
In particular, for a mode with 64:27 aspect ratio, 0 for VIC fails the
AVI infoframe generation altogether with -EINVAL.
Separate the VIC lookup from the "filtering", and postpone the
filtering, to use the proper VIC for aspect ratio handling, and the 0
VIC for the infoframe video code as needed.
Reported-by: William Tseng <william.tseng@intel.com>
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6153
Cc: <stable@vger.kernel.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/c3e78cc6d01ed237f71ad0038826b08d83d75eef.1672826282.git.jani.nikula@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_edid.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6705,8 +6705,6 @@ static u8 drm_mode_hdmi_vic(const struct
static u8 drm_mode_cea_vic(const struct drm_connector *connector,
const struct drm_display_mode *mode)
{
- u8 vic;
-
/*
* HDMI spec says if a mode is found in HDMI 1.4b 4K modes
* we should send its VIC in vendor infoframes, else send the
@@ -6716,13 +6714,18 @@ static u8 drm_mode_cea_vic(const struct
if (drm_mode_hdmi_vic(connector, mode))
return 0;
- vic = drm_match_cea_mode(mode);
+ return drm_match_cea_mode(mode);
+}
- /*
- * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
- * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
- * have to make sure we dont break HDMI 1.4 sinks.
- */
+/*
+ * Avoid sending VICs defined in HDMI 2.0 in AVI infoframes to sinks that
+ * conform to HDMI 1.4.
+ *
+ * HDMI 1.4 (CTA-861-D) VIC range: [1..64]
+ * HDMI 2.0 (CTA-861-F) VIC range: [1..107]
+ */
+static u8 vic_for_avi_infoframe(const struct drm_connector *connector, u8 vic)
+{
if (!is_hdmi2_sink(connector) && vic > 64)
return 0;
@@ -6798,7 +6801,7 @@ drm_hdmi_avi_infoframe_from_display_mode
picture_aspect = HDMI_PICTURE_ASPECT_NONE;
}
- frame->video_code = vic;
+ frame->video_code = vic_for_avi_infoframe(connector, vic);
frame->picture_aspect = picture_aspect;
frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
^ permalink raw reply [relevance 5%]
* [PATCH 6.2 1000/1001] drm/edid: fix AVI infoframe aspect ratio handling
@ 2023-03-07 17:02 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-03-07 17:02 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, William Tseng,
Ville Syrjälä,
Jani Nikula
From: Jani Nikula <jani.nikula@intel.com>
commit 1cbc1f0d324ba6c4d1b10ac6362b5e0b029f63d5 upstream.
We try to avoid sending VICs defined in the later specs in AVI
infoframes to sinks that conform to the earlier specs, to not upset
them, and use 0 for the VIC instead. However, we do this detection and
conversion to 0 too early, as we'll need the actual VIC to figure out
the aspect ratio.
In particular, for a mode with 64:27 aspect ratio, 0 for VIC fails the
AVI infoframe generation altogether with -EINVAL.
Separate the VIC lookup from the "filtering", and postpone the
filtering, to use the proper VIC for aspect ratio handling, and the 0
VIC for the infoframe video code as needed.
Reported-by: William Tseng <william.tseng@intel.com>
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6153
Cc: <stable@vger.kernel.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/c3e78cc6d01ed237f71ad0038826b08d83d75eef.1672826282.git.jani.nikula@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_edid.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6885,8 +6885,6 @@ static u8 drm_mode_hdmi_vic(const struct
static u8 drm_mode_cea_vic(const struct drm_connector *connector,
const struct drm_display_mode *mode)
{
- u8 vic;
-
/*
* HDMI spec says if a mode is found in HDMI 1.4b 4K modes
* we should send its VIC in vendor infoframes, else send the
@@ -6896,13 +6894,18 @@ static u8 drm_mode_cea_vic(const struct
if (drm_mode_hdmi_vic(connector, mode))
return 0;
- vic = drm_match_cea_mode(mode);
+ return drm_match_cea_mode(mode);
+}
- /*
- * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
- * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
- * have to make sure we dont break HDMI 1.4 sinks.
- */
+/*
+ * Avoid sending VICs defined in HDMI 2.0 in AVI infoframes to sinks that
+ * conform to HDMI 1.4.
+ *
+ * HDMI 1.4 (CTA-861-D) VIC range: [1..64]
+ * HDMI 2.0 (CTA-861-F) VIC range: [1..107]
+ */
+static u8 vic_for_avi_infoframe(const struct drm_connector *connector, u8 vic)
+{
if (!is_hdmi2_sink(connector) && vic > 64)
return 0;
@@ -6978,7 +6981,7 @@ drm_hdmi_avi_infoframe_from_display_mode
picture_aspect = HDMI_PICTURE_ASPECT_NONE;
}
- frame->video_code = vic;
+ frame->video_code = vic_for_avi_infoframe(connector, vic);
frame->picture_aspect = picture_aspect;
frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
^ permalink raw reply [relevance 5%]
* Re: Linux 4.19.273
@ 2023-02-22 12:03 1% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2023-02-22 12:03 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/Makefile b/Makefile
index e3822e492543..bbc26e110a13 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 4
PATCHLEVEL = 19
-SUBLEVEL = 272
+SUBLEVEL = 273
EXTRAVERSION =
NAME = "People's Front"
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index 3c34f14fa508..90e9cbcc891f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -167,7 +167,7 @@
sd_emmc_b: sd@5000 {
compatible = "amlogic,meson-axg-mmc";
reg = <0x0 0x5000 0x0 0x800>;
- interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
clocks = <&clkc CLKID_SD_EMMC_B>,
<&clkc CLKID_SD_EMMC_B_CLK0>,
@@ -179,7 +179,7 @@
sd_emmc_c: mmc@7000 {
compatible = "amlogic,meson-axg-mmc";
reg = <0x0 0x7000 0x0 0x800>;
- interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
clocks = <&clkc CLKID_SD_EMMC_C>,
<&clkc CLKID_SD_EMMC_C_CLK0>,
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index 4252119bfd90..a127657526c7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -470,21 +470,21 @@
sd_emmc_a: mmc@70000 {
compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
reg = <0x0 0x70000 0x0 0x800>;
- interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
sd_emmc_b: mmc@72000 {
compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
reg = <0x0 0x72000 0x0 0x800>;
- interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
sd_emmc_c: mmc@74000 {
compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
reg = <0x0 0x74000 0x0 0x800>;
- interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
};
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 6d471c00c71a..906b7c882587 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -1197,7 +1197,7 @@ static char __attribute__((aligned(64))) iodc_dbuf[4096];
*/
int pdc_iodc_print(const unsigned char *str, unsigned count)
{
- unsigned int i;
+ unsigned int i, found = 0;
unsigned long flags;
for (i = 0; i < count;) {
@@ -1206,6 +1206,7 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
iodc_dbuf[i+0] = '\r';
iodc_dbuf[i+1] = '\n';
i += 2;
+ found = 1;
goto print;
default:
iodc_dbuf[i] = str[i];
@@ -1222,7 +1223,7 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
__pa(iodc_retbuf), 0, __pa(iodc_dbuf), i, 0);
spin_unlock_irqrestore(&pdc_lock, flags);
- return i;
+ return i - found;
}
#if !defined(BOOTLOADER)
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index de2998cb189e..bc94acdbf478 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -128,6 +128,12 @@ long arch_ptrace(struct task_struct *child, long request,
unsigned long tmp;
long ret = -EIO;
+ unsigned long user_regs_struct_size = sizeof(struct user_regs_struct);
+#ifdef CONFIG_64BIT
+ if (is_compat_task())
+ user_regs_struct_size /= 2;
+#endif
+
switch (request) {
/* Read the word at location addr in the USER area. For ptraced
@@ -183,14 +189,14 @@ long arch_ptrace(struct task_struct *child, long request,
return copy_regset_to_user(child,
task_user_regset_view(current),
REGSET_GENERAL,
- 0, sizeof(struct user_regs_struct),
+ 0, user_regs_struct_size,
datap);
case PTRACE_SETREGS: /* Set all gp regs in the child. */
return copy_regset_from_user(child,
task_user_regset_view(current),
REGSET_GENERAL,
- 0, sizeof(struct user_regs_struct),
+ 0, user_regs_struct_size,
datap);
case PTRACE_GETFPREGS: /* Get the child FPU state. */
@@ -304,6 +310,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
}
}
break;
+ case PTRACE_GETREGS:
+ case PTRACE_SETREGS:
+ case PTRACE_GETFPREGS:
+ case PTRACE_SETFPREGS:
+ return arch_ptrace(child, request, addr, data);
default:
ret = compat_ptrace_request(child, request, addr, data);
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index e6d09ad417e5..a374e255336b 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -72,6 +72,9 @@ ifeq ($(CONFIG_MODULE_SECTIONS),y)
KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/riscv/kernel/module.lds
endif
+# Avoid generating .eh_frame sections.
+KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
+
KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax)
KBUILD_AFLAGS_MODULE += $(call as-option,-Wa$(comma)-mno-relax)
diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c
index 498c0a0814fe..62f8be2fdbb8 100644
--- a/arch/riscv/mm/cacheflush.c
+++ b/arch/riscv/mm/cacheflush.c
@@ -18,6 +18,8 @@ void flush_icache_pte(pte_t pte)
{
struct page *page = pte_page(pte);
- if (!test_and_set_bit(PG_dcache_clean, &page->flags))
+ if (!test_bit(PG_dcache_clean, &page->flags)) {
flush_icache_all();
+ set_bit(PG_dcache_clean, &page->flags);
+ }
}
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index a3a570df6be1..9692ccc583bb 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -138,6 +138,9 @@ static void __init fpu__init_system_generic(void)
unsigned int fpu_kernel_xstate_size;
EXPORT_SYMBOL_GPL(fpu_kernel_xstate_size);
+/* Get alignment of the TYPE. */
+#define TYPE_ALIGN(TYPE) offsetof(struct { char x; TYPE test; }, test)
+
/*
* Enforce that 'MEMBER' is the last field of 'TYPE'.
*
@@ -145,8 +148,8 @@ EXPORT_SYMBOL_GPL(fpu_kernel_xstate_size);
* because that's how C aligns structs.
*/
#define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \
- BUILD_BUG_ON(sizeof(TYPE) != \
- ALIGN(offsetofend(TYPE, MEMBER), _Alignof(TYPE)))
+ BUILD_BUG_ON(sizeof(TYPE) != ALIGN(offsetofend(TYPE, MEMBER), \
+ TYPE_ALIGN(TYPE)))
/*
* We append the 'struct fpu' to the task_struct:
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index dc4f2fdf5e57..13fd54de5449 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -16,7 +16,7 @@ kvm-y += x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
hyperv.o page_track.o debugfs.o
-kvm-intel-y += vmx.o pmu_intel.o
+kvm-intel-y += vmx/vmx.o vmx/pmu_intel.o
kvm-amd-y += svm.o pmu_amd.o
obj-$(CONFIG_KVM) += kvm.o
diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c
deleted file mode 100644
index 611f9e60f815..000000000000
--- a/arch/x86/kvm/pmu_intel.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * KVM PMU support for Intel CPUs
- *
- * Copyright 2011 Red Hat, Inc. and/or its affiliates.
- *
- * Authors:
- * Avi Kivity <avi@redhat.com>
- * Gleb Natapov <gleb@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- */
-#include <linux/types.h>
-#include <linux/kvm_host.h>
-#include <linux/perf_event.h>
-#include <asm/perf_event.h>
-#include "x86.h"
-#include "cpuid.h"
-#include "lapic.h"
-#include "pmu.h"
-
-static struct kvm_event_hw_type_mapping intel_arch_events[] = {
- /* Index must match CPUID 0x0A.EBX bit vector */
- [0] = { 0x3c, 0x00, PERF_COUNT_HW_CPU_CYCLES },
- [1] = { 0xc0, 0x00, PERF_COUNT_HW_INSTRUCTIONS },
- [2] = { 0x3c, 0x01, PERF_COUNT_HW_BUS_CYCLES },
- [3] = { 0x2e, 0x4f, PERF_COUNT_HW_CACHE_REFERENCES },
- [4] = { 0x2e, 0x41, PERF_COUNT_HW_CACHE_MISSES },
- [5] = { 0xc4, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
- [6] = { 0xc5, 0x00, PERF_COUNT_HW_BRANCH_MISSES },
- [7] = { 0x00, 0x03, PERF_COUNT_HW_REF_CPU_CYCLES },
-};
-
-/* mapping between fixed pmc index and intel_arch_events array */
-static int fixed_pmc_events[] = {1, 0, 7};
-
-static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
-{
- int i;
-
- for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
- u8 new_ctrl = fixed_ctrl_field(data, i);
- u8 old_ctrl = fixed_ctrl_field(pmu->fixed_ctr_ctrl, i);
- struct kvm_pmc *pmc;
-
- pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
-
- if (old_ctrl == new_ctrl)
- continue;
-
- reprogram_fixed_counter(pmc, new_ctrl, i);
- }
-
- pmu->fixed_ctr_ctrl = data;
-}
-
-/* function is called when global control register has been updated. */
-static void global_ctrl_changed(struct kvm_pmu *pmu, u64 data)
-{
- int bit;
- u64 diff = pmu->global_ctrl ^ data;
-
- pmu->global_ctrl = data;
-
- for_each_set_bit(bit, (unsigned long *)&diff, X86_PMC_IDX_MAX)
- reprogram_counter(pmu, bit);
-}
-
-static unsigned intel_find_arch_event(struct kvm_pmu *pmu,
- u8 event_select,
- u8 unit_mask)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(intel_arch_events); i++)
- if (intel_arch_events[i].eventsel == event_select
- && intel_arch_events[i].unit_mask == unit_mask
- && (pmu->available_event_types & (1 << i)))
- break;
-
- if (i == ARRAY_SIZE(intel_arch_events))
- return PERF_COUNT_HW_MAX;
-
- return intel_arch_events[i].event_type;
-}
-
-static unsigned intel_find_fixed_event(int idx)
-{
- u32 event;
- size_t size = ARRAY_SIZE(fixed_pmc_events);
-
- if (idx >= size)
- return PERF_COUNT_HW_MAX;
-
- event = fixed_pmc_events[array_index_nospec(idx, size)];
- return intel_arch_events[event].event_type;
-}
-
-/* check if a PMC is enabled by comparing it with globl_ctrl bits. */
-static bool intel_pmc_is_enabled(struct kvm_pmc *pmc)
-{
- struct kvm_pmu *pmu = pmc_to_pmu(pmc);
-
- return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl);
-}
-
-static struct kvm_pmc *intel_pmc_idx_to_pmc(struct kvm_pmu *pmu, int pmc_idx)
-{
- if (pmc_idx < INTEL_PMC_IDX_FIXED)
- return get_gp_pmc(pmu, MSR_P6_EVNTSEL0 + pmc_idx,
- MSR_P6_EVNTSEL0);
- else {
- u32 idx = pmc_idx - INTEL_PMC_IDX_FIXED;
-
- return get_fixed_pmc(pmu, idx + MSR_CORE_PERF_FIXED_CTR0);
- }
-}
-
-/* returns 0 if idx's corresponding MSR exists; otherwise returns 1. */
-static int intel_is_valid_msr_idx(struct kvm_vcpu *vcpu, unsigned idx)
-{
- struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
- bool fixed = idx & (1u << 30);
-
- idx &= ~(3u << 30);
-
- return (!fixed && idx >= pmu->nr_arch_gp_counters) ||
- (fixed && idx >= pmu->nr_arch_fixed_counters);
-}
-
-static struct kvm_pmc *intel_msr_idx_to_pmc(struct kvm_vcpu *vcpu,
- unsigned idx, u64 *mask)
-{
- struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
- bool fixed = idx & (1u << 30);
- struct kvm_pmc *counters;
- unsigned int num_counters;
-
- idx &= ~(3u << 30);
- if (fixed) {
- counters = pmu->fixed_counters;
- num_counters = pmu->nr_arch_fixed_counters;
- } else {
- counters = pmu->gp_counters;
- num_counters = pmu->nr_arch_gp_counters;
- }
- if (idx >= num_counters)
- return NULL;
- *mask &= pmu->counter_bitmask[fixed ? KVM_PMC_FIXED : KVM_PMC_GP];
- return &counters[array_index_nospec(idx, num_counters)];
-}
-
-static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
-{
- struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
- int ret;
-
- switch (msr) {
- case MSR_CORE_PERF_FIXED_CTR_CTRL:
- case MSR_CORE_PERF_GLOBAL_STATUS:
- case MSR_CORE_PERF_GLOBAL_CTRL:
- case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
- ret = pmu->version > 1;
- break;
- default:
- ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) ||
- get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) ||
- get_fixed_pmc(pmu, msr);
- break;
- }
-
- return ret;
-}
-
-static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *data)
-{
- struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
- struct kvm_pmc *pmc;
-
- switch (msr) {
- case MSR_CORE_PERF_FIXED_CTR_CTRL:
- *data = pmu->fixed_ctr_ctrl;
- return 0;
- case MSR_CORE_PERF_GLOBAL_STATUS:
- *data = pmu->global_status;
- return 0;
- case MSR_CORE_PERF_GLOBAL_CTRL:
- *data = pmu->global_ctrl;
- return 0;
- case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
- *data = pmu->global_ovf_ctrl;
- return 0;
- default:
- if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0))) {
- u64 val = pmc_read_counter(pmc);
- *data = val & pmu->counter_bitmask[KVM_PMC_GP];
- return 0;
- } else if ((pmc = get_fixed_pmc(pmu, msr))) {
- u64 val = pmc_read_counter(pmc);
- *data = val & pmu->counter_bitmask[KVM_PMC_FIXED];
- return 0;
- } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) {
- *data = pmc->eventsel;
- return 0;
- }
- }
-
- return 1;
-}
-
-static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
-{
- struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
- struct kvm_pmc *pmc;
- u32 msr = msr_info->index;
- u64 data = msr_info->data;
-
- switch (msr) {
- case MSR_CORE_PERF_FIXED_CTR_CTRL:
- if (pmu->fixed_ctr_ctrl == data)
- return 0;
- if (!(data & 0xfffffffffffff444ull)) {
- reprogram_fixed_counters(pmu, data);
- return 0;
- }
- break;
- case MSR_CORE_PERF_GLOBAL_STATUS:
- if (msr_info->host_initiated) {
- pmu->global_status = data;
- return 0;
- }
- break; /* RO MSR */
- case MSR_CORE_PERF_GLOBAL_CTRL:
- if (pmu->global_ctrl == data)
- return 0;
- if (!(data & pmu->global_ctrl_mask)) {
- global_ctrl_changed(pmu, data);
- return 0;
- }
- break;
- case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
- if (!(data & (pmu->global_ctrl_mask & ~(3ull<<62)))) {
- if (!msr_info->host_initiated)
- pmu->global_status &= ~data;
- pmu->global_ovf_ctrl = data;
- return 0;
- }
- break;
- default:
- if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0))) {
- if (msr_info->host_initiated)
- pmc->counter = data;
- else
- pmc->counter = (s32)data;
- return 0;
- } else if ((pmc = get_fixed_pmc(pmu, msr))) {
- pmc->counter = data;
- return 0;
- } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) {
- if (data == pmc->eventsel)
- return 0;
- if (!(data & pmu->reserved_bits)) {
- reprogram_gp_counter(pmc, data);
- return 0;
- }
- }
- }
-
- return 1;
-}
-
-static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
-{
- struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
- struct kvm_cpuid_entry2 *entry;
- union cpuid10_eax eax;
- union cpuid10_edx edx;
-
- pmu->nr_arch_gp_counters = 0;
- pmu->nr_arch_fixed_counters = 0;
- pmu->counter_bitmask[KVM_PMC_GP] = 0;
- pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
- pmu->version = 0;
- pmu->reserved_bits = 0xffffffff00200000ull;
-
- entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
- if (!entry)
- return;
- eax.full = entry->eax;
- edx.full = entry->edx;
-
- pmu->version = eax.split.version_id;
- if (!pmu->version)
- return;
-
- pmu->nr_arch_gp_counters = min_t(int, eax.split.num_counters,
- INTEL_PMC_MAX_GENERIC);
- pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << eax.split.bit_width) - 1;
- pmu->available_event_types = ~entry->ebx &
- ((1ull << eax.split.mask_length) - 1);
-
- if (pmu->version == 1) {
- pmu->nr_arch_fixed_counters = 0;
- } else {
- pmu->nr_arch_fixed_counters =
- min_t(int, edx.split.num_counters_fixed,
- INTEL_PMC_MAX_FIXED);
- pmu->counter_bitmask[KVM_PMC_FIXED] =
- ((u64)1 << edx.split.bit_width_fixed) - 1;
- }
-
- pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) |
- (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
- pmu->global_ctrl_mask = ~pmu->global_ctrl;
-
- entry = kvm_find_cpuid_entry(vcpu, 7, 0);
- if (entry &&
- (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
- (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM)))
- pmu->reserved_bits ^= HSW_IN_TX|HSW_IN_TX_CHECKPOINTED;
-}
-
-static void intel_pmu_init(struct kvm_vcpu *vcpu)
-{
- int i;
- struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
-
- for (i = 0; i < INTEL_PMC_MAX_GENERIC; i++) {
- pmu->gp_counters[i].type = KVM_PMC_GP;
- pmu->gp_counters[i].vcpu = vcpu;
- pmu->gp_counters[i].idx = i;
- }
-
- for (i = 0; i < INTEL_PMC_MAX_FIXED; i++) {
- pmu->fixed_counters[i].type = KVM_PMC_FIXED;
- pmu->fixed_counters[i].vcpu = vcpu;
- pmu->fixed_counters[i].idx = i + INTEL_PMC_IDX_FIXED;
- }
-}
-
-static void intel_pmu_reset(struct kvm_vcpu *vcpu)
-{
- struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
- int i;
-
- for (i = 0; i < INTEL_PMC_MAX_GENERIC; i++) {
- struct kvm_pmc *pmc = &pmu->gp_counters[i];
-
- pmc_stop_counter(pmc);
- pmc->counter = pmc->eventsel = 0;
- }
-
- for (i = 0; i < INTEL_PMC_MAX_FIXED; i++)
- pmc_stop_counter(&pmu->fixed_counters[i]);
-
- pmu->fixed_ctr_ctrl = pmu->global_ctrl = pmu->global_status =
- pmu->global_ovf_ctrl = 0;
-}
-
-struct kvm_pmu_ops intel_pmu_ops = {
- .find_arch_event = intel_find_arch_event,
- .find_fixed_event = intel_find_fixed_event,
- .pmc_is_enabled = intel_pmc_is_enabled,
- .pmc_idx_to_pmc = intel_pmc_idx_to_pmc,
- .msr_idx_to_pmc = intel_msr_idx_to_pmc,
- .is_valid_msr_idx = intel_is_valid_msr_idx,
- .is_valid_msr = intel_is_valid_msr,
- .get_msr = intel_pmu_get_msr,
- .set_msr = intel_pmu_set_msr,
- .refresh = intel_pmu_refresh,
- .init = intel_pmu_init,
- .reset = intel_pmu_reset,
-};
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
deleted file mode 100644
index 9bb696d7300c..000000000000
--- a/arch/x86/kvm/vmx.c
+++ /dev/null
@@ -1,14757 +0,0 @@
-/*
- * Kernel-based Virtual Machine driver for Linux
- *
- * This module enables machines with Intel VT-x extensions to run virtual
- * machines without emulation or binary translation.
- *
- * Copyright (C) 2006 Qumranet, Inc.
- * Copyright 2010 Red Hat, Inc. and/or its affiliates.
- *
- * Authors:
- * Avi Kivity <avi@qumranet.com>
- * Yaniv Kamay <yaniv@qumranet.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- */
-
-#include "irq.h"
-#include "mmu.h"
-#include "cpuid.h"
-#include "lapic.h"
-
-#include <linux/kvm_host.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/sched.h>
-#include <linux/sched/smt.h>
-#include <linux/moduleparam.h>
-#include <linux/mod_devicetable.h>
-#include <linux/trace_events.h>
-#include <linux/slab.h>
-#include <linux/tboot.h>
-#include <linux/hrtimer.h>
-#include <linux/frame.h>
-#include <linux/nospec.h>
-#include "kvm_cache_regs.h"
-#include "x86.h"
-
-#include <asm/asm.h>
-#include <asm/cpu.h>
-#include <asm/cpu_device_id.h>
-#include <asm/io.h>
-#include <asm/desc.h>
-#include <asm/vmx.h>
-#include <asm/virtext.h>
-#include <asm/mce.h>
-#include <asm/fpu/internal.h>
-#include <asm/perf_event.h>
-#include <asm/debugreg.h>
-#include <asm/kexec.h>
-#include <asm/apic.h>
-#include <asm/irq_remapping.h>
-#include <asm/mmu_context.h>
-#include <asm/spec-ctrl.h>
-#include <asm/mshyperv.h>
-
-#include "trace.h"
-#include "pmu.h"
-#include "vmx_evmcs.h"
-
-#define __ex(x) __kvm_handle_fault_on_reboot(x)
-#define __ex_clear(x, reg) \
- ____kvm_handle_fault_on_reboot(x, "xor " reg " , " reg)
-
-MODULE_AUTHOR("Qumranet");
-MODULE_LICENSE("GPL");
-
-static const struct x86_cpu_id vmx_cpu_id[] = {
- X86_FEATURE_MATCH(X86_FEATURE_VMX),
- {}
-};
-MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);
-
-static bool __read_mostly enable_vpid = 1;
-module_param_named(vpid, enable_vpid, bool, 0444);
-
-static bool __read_mostly enable_vnmi = 1;
-module_param_named(vnmi, enable_vnmi, bool, S_IRUGO);
-
-static bool __read_mostly flexpriority_enabled = 1;
-module_param_named(flexpriority, flexpriority_enabled, bool, S_IRUGO);
-
-static bool __read_mostly enable_ept = 1;
-module_param_named(ept, enable_ept, bool, S_IRUGO);
-
-static bool __read_mostly enable_unrestricted_guest = 1;
-module_param_named(unrestricted_guest,
- enable_unrestricted_guest, bool, S_IRUGO);
-
-static bool __read_mostly enable_ept_ad_bits = 1;
-module_param_named(eptad, enable_ept_ad_bits, bool, S_IRUGO);
-
-static bool __read_mostly emulate_invalid_guest_state = true;
-module_param(emulate_invalid_guest_state, bool, S_IRUGO);
-
-static bool __read_mostly fasteoi = 1;
-module_param(fasteoi, bool, S_IRUGO);
-
-static bool __read_mostly enable_apicv = 1;
-module_param(enable_apicv, bool, S_IRUGO);
-
-static bool __read_mostly enable_shadow_vmcs = 1;
-module_param_named(enable_shadow_vmcs, enable_shadow_vmcs, bool, S_IRUGO);
-/*
- * If nested=1, nested virtualization is supported, i.e., guests may use
- * VMX and be a hypervisor for its own guests. If nested=0, guests may not
- * use VMX instructions.
- */
-static bool __read_mostly nested = 0;
-module_param(nested, bool, S_IRUGO);
-
-static u64 __read_mostly host_xss;
-
-static bool __read_mostly enable_pml = 1;
-module_param_named(pml, enable_pml, bool, S_IRUGO);
-
-#define MSR_TYPE_R 1
-#define MSR_TYPE_W 2
-#define MSR_TYPE_RW 3
-
-#define MSR_BITMAP_MODE_X2APIC 1
-#define MSR_BITMAP_MODE_X2APIC_APICV 2
-
-#define KVM_VMX_TSC_MULTIPLIER_MAX 0xffffffffffffffffULL
-
-/* Guest_tsc -> host_tsc conversion requires 64-bit division. */
-static int __read_mostly cpu_preemption_timer_multi;
-static bool __read_mostly enable_preemption_timer = 1;
-#ifdef CONFIG_X86_64
-module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
-#endif
-
-#define KVM_GUEST_CR0_MASK (X86_CR0_NW | X86_CR0_CD)
-#define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR0_NE
-#define KVM_VM_CR0_ALWAYS_ON \
- (KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | \
- X86_CR0_WP | X86_CR0_PG | X86_CR0_PE)
-#define KVM_CR4_GUEST_OWNED_BITS \
- (X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR \
- | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_TSD)
-
-#define KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR4_VMXE
-#define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)
-#define KVM_RMODE_VM_CR4_ALWAYS_ON (X86_CR4_VME | X86_CR4_PAE | X86_CR4_VMXE)
-
-#define RMODE_GUEST_OWNED_EFLAGS_BITS (~(X86_EFLAGS_IOPL | X86_EFLAGS_VM))
-
-#define VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE 5
-
-/*
- * Hyper-V requires all of these, so mark them as supported even though
- * they are just treated the same as all-context.
- */
-#define VMX_VPID_EXTENT_SUPPORTED_MASK \
- (VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT | \
- VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT | \
- VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT | \
- VMX_VPID_EXTENT_SINGLE_NON_GLOBAL_BIT)
-
-/*
- * These 2 parameters are used to config the controls for Pause-Loop Exiting:
- * ple_gap: upper bound on the amount of time between two successive
- * executions of PAUSE in a loop. Also indicate if ple enabled.
- * According to test, this time is usually smaller than 128 cycles.
- * ple_window: upper bound on the amount of time a guest is allowed to execute
- * in a PAUSE loop. Tests indicate that most spinlocks are held for
- * less than 2^12 cycles
- * Time is measured based on a counter that runs at the same rate as the TSC,
- * refer SDM volume 3b section 21.6.13 & 22.1.3.
- */
-static unsigned int ple_gap = KVM_DEFAULT_PLE_GAP;
-module_param(ple_gap, uint, 0444);
-
-static unsigned int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
-module_param(ple_window, uint, 0444);
-
-/* Default doubles per-vcpu window every exit. */
-static unsigned int ple_window_grow = KVM_DEFAULT_PLE_WINDOW_GROW;
-module_param(ple_window_grow, uint, 0444);
-
-/* Default resets per-vcpu window every exit to ple_window. */
-static unsigned int ple_window_shrink = KVM_DEFAULT_PLE_WINDOW_SHRINK;
-module_param(ple_window_shrink, uint, 0444);
-
-/* Default is to compute the maximum so we can never overflow. */
-static unsigned int ple_window_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
-module_param(ple_window_max, uint, 0444);
-
-extern const ulong vmx_return;
-
-static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush);
-static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond);
-static DEFINE_MUTEX(vmx_l1d_flush_mutex);
-
-/* Storage for pre module init parameter parsing */
-static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush_param = VMENTER_L1D_FLUSH_AUTO;
-
-static const struct {
- const char *option;
- bool for_parse;
-} vmentry_l1d_param[] = {
- [VMENTER_L1D_FLUSH_AUTO] = {"auto", true},
- [VMENTER_L1D_FLUSH_NEVER] = {"never", true},
- [VMENTER_L1D_FLUSH_COND] = {"cond", true},
- [VMENTER_L1D_FLUSH_ALWAYS] = {"always", true},
- [VMENTER_L1D_FLUSH_EPT_DISABLED] = {"EPT disabled", false},
- [VMENTER_L1D_FLUSH_NOT_REQUIRED] = {"not required", false},
-};
-
-#define L1D_CACHE_ORDER 4
-static void *vmx_l1d_flush_pages;
-
-/* Control for disabling CPU Fill buffer clear */
-static bool __read_mostly vmx_fb_clear_ctrl_available;
-
-static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
-{
- struct page *page;
- unsigned int i;
-
- if (!enable_ept) {
- l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED;
- return 0;
- }
-
- if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) {
- u64 msr;
-
- rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr);
- if (msr & ARCH_CAP_SKIP_VMENTRY_L1DFLUSH) {
- l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_NOT_REQUIRED;
- return 0;
- }
- }
-
- /* If set to auto use the default l1tf mitigation method */
- if (l1tf == VMENTER_L1D_FLUSH_AUTO) {
- switch (l1tf_mitigation) {
- case L1TF_MITIGATION_OFF:
- l1tf = VMENTER_L1D_FLUSH_NEVER;
- break;
- case L1TF_MITIGATION_FLUSH_NOWARN:
- case L1TF_MITIGATION_FLUSH:
- case L1TF_MITIGATION_FLUSH_NOSMT:
- l1tf = VMENTER_L1D_FLUSH_COND;
- break;
- case L1TF_MITIGATION_FULL:
- case L1TF_MITIGATION_FULL_FORCE:
- l1tf = VMENTER_L1D_FLUSH_ALWAYS;
- break;
- }
- } else if (l1tf_mitigation == L1TF_MITIGATION_FULL_FORCE) {
- l1tf = VMENTER_L1D_FLUSH_ALWAYS;
- }
-
- if (l1tf != VMENTER_L1D_FLUSH_NEVER && !vmx_l1d_flush_pages &&
- !boot_cpu_has(X86_FEATURE_FLUSH_L1D)) {
- page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER);
- if (!page)
- return -ENOMEM;
- vmx_l1d_flush_pages = page_address(page);
-
- /*
- * Initialize each page with a different pattern in
- * order to protect against KSM in the nested
- * virtualization case.
- */
- for (i = 0; i < 1u << L1D_CACHE_ORDER; ++i) {
- memset(vmx_l1d_flush_pages + i * PAGE_SIZE, i + 1,
- PAGE_SIZE);
- }
- }
-
- l1tf_vmx_mitigation = l1tf;
-
- if (l1tf != VMENTER_L1D_FLUSH_NEVER)
- static_branch_enable(&vmx_l1d_should_flush);
- else
- static_branch_disable(&vmx_l1d_should_flush);
-
- if (l1tf == VMENTER_L1D_FLUSH_COND)
- static_branch_enable(&vmx_l1d_flush_cond);
- else
- static_branch_disable(&vmx_l1d_flush_cond);
- return 0;
-}
-
-static int vmentry_l1d_flush_parse(const char *s)
-{
- unsigned int i;
-
- if (s) {
- for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) {
- if (vmentry_l1d_param[i].for_parse &&
- sysfs_streq(s, vmentry_l1d_param[i].option))
- return i;
- }
- }
- return -EINVAL;
-}
-
-static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp)
-{
- int l1tf, ret;
-
- l1tf = vmentry_l1d_flush_parse(s);
- if (l1tf < 0)
- return l1tf;
-
- if (!boot_cpu_has(X86_BUG_L1TF))
- return 0;
-
- /*
- * Has vmx_init() run already? If not then this is the pre init
- * parameter parsing. In that case just store the value and let
- * vmx_init() do the proper setup after enable_ept has been
- * established.
- */
- if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO) {
- vmentry_l1d_flush_param = l1tf;
- return 0;
- }
-
- mutex_lock(&vmx_l1d_flush_mutex);
- ret = vmx_setup_l1d_flush(l1tf);
- mutex_unlock(&vmx_l1d_flush_mutex);
- return ret;
-}
-
-static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp)
-{
- if (WARN_ON_ONCE(l1tf_vmx_mitigation >= ARRAY_SIZE(vmentry_l1d_param)))
- return sprintf(s, "???\n");
-
- return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option);
-}
-
-static const struct kernel_param_ops vmentry_l1d_flush_ops = {
- .set = vmentry_l1d_flush_set,
- .get = vmentry_l1d_flush_get,
-};
-module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, NULL, 0644);
-
-enum ept_pointers_status {
- EPT_POINTERS_CHECK = 0,
- EPT_POINTERS_MATCH = 1,
- EPT_POINTERS_MISMATCH = 2
-};
-
-struct kvm_vmx {
- struct kvm kvm;
-
- unsigned int tss_addr;
- bool ept_identity_pagetable_done;
- gpa_t ept_identity_map_addr;
-
- enum ept_pointers_status ept_pointers_match;
- spinlock_t ept_pointer_lock;
-};
-
-#define NR_AUTOLOAD_MSRS 8
-
-struct vmcs_hdr {
- u32 revision_id:31;
- u32 shadow_vmcs:1;
-};
-
-struct vmcs {
- struct vmcs_hdr hdr;
- u32 abort;
- char data[0];
-};
-
-/*
- * vmcs_host_state tracks registers that are loaded from the VMCS on VMEXIT
- * and whose values change infrequently, but are not constant. I.e. this is
- * used as a write-through cache of the corresponding VMCS fields.
- */
-struct vmcs_host_state {
- unsigned long cr3; /* May not match real cr3 */
- unsigned long cr4; /* May not match real cr4 */
- unsigned long gs_base;
- unsigned long fs_base;
-
- u16 fs_sel, gs_sel, ldt_sel;
-#ifdef CONFIG_X86_64
- u16 ds_sel, es_sel;
-#endif
-};
-
-/*
- * Track a VMCS that may be loaded on a certain CPU. If it is (cpu!=-1), also
- * remember whether it was VMLAUNCHed, and maintain a linked list of all VMCSs
- * loaded on this CPU (so we can clear them if the CPU goes down).
- */
-struct loaded_vmcs {
- struct vmcs *vmcs;
- struct vmcs *shadow_vmcs;
- int cpu;
- bool launched;
- bool nmi_known_unmasked;
- bool hv_timer_armed;
- /* Support for vnmi-less CPUs */
- int soft_vnmi_blocked;
- ktime_t entry_time;
- s64 vnmi_blocked_time;
- unsigned long *msr_bitmap;
- struct list_head loaded_vmcss_on_cpu_link;
- struct vmcs_host_state host_state;
-};
-
-struct shared_msr_entry {
- unsigned index;
- u64 data;
- u64 mask;
-};
-
-/*
- * struct vmcs12 describes the state that our guest hypervisor (L1) keeps for a
- * single nested guest (L2), hence the name vmcs12. Any VMX implementation has
- * a VMCS structure, and vmcs12 is our emulated VMX's VMCS. This structure is
- * stored in guest memory specified by VMPTRLD, but is opaque to the guest,
- * which must access it using VMREAD/VMWRITE/VMCLEAR instructions.
- * More than one of these structures may exist, if L1 runs multiple L2 guests.
- * nested_vmx_run() will use the data here to build the vmcs02: a VMCS for the
- * underlying hardware which will be used to run L2.
- * This structure is packed to ensure that its layout is identical across
- * machines (necessary for live migration).
- *
- * IMPORTANT: Changing the layout of existing fields in this structure
- * will break save/restore compatibility with older kvm releases. When
- * adding new fields, either use space in the reserved padding* arrays
- * or add the new fields to the end of the structure.
- */
-typedef u64 natural_width;
-struct __packed vmcs12 {
- /* According to the Intel spec, a VMCS region must start with the
- * following two fields. Then follow implementation-specific data.
- */
- struct vmcs_hdr hdr;
- u32 abort;
-
- u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
- u32 padding[7]; /* room for future expansion */
-
- u64 io_bitmap_a;
- u64 io_bitmap_b;
- u64 msr_bitmap;
- u64 vm_exit_msr_store_addr;
- u64 vm_exit_msr_load_addr;
- u64 vm_entry_msr_load_addr;
- u64 tsc_offset;
- u64 virtual_apic_page_addr;
- u64 apic_access_addr;
- u64 posted_intr_desc_addr;
- u64 ept_pointer;
- u64 eoi_exit_bitmap0;
- u64 eoi_exit_bitmap1;
- u64 eoi_exit_bitmap2;
- u64 eoi_exit_bitmap3;
- u64 xss_exit_bitmap;
- u64 guest_physical_address;
- u64 vmcs_link_pointer;
- u64 guest_ia32_debugctl;
- u64 guest_ia32_pat;
- u64 guest_ia32_efer;
- u64 guest_ia32_perf_global_ctrl;
- u64 guest_pdptr0;
- u64 guest_pdptr1;
- u64 guest_pdptr2;
- u64 guest_pdptr3;
- u64 guest_bndcfgs;
- u64 host_ia32_pat;
- u64 host_ia32_efer;
- u64 host_ia32_perf_global_ctrl;
- u64 vmread_bitmap;
- u64 vmwrite_bitmap;
- u64 vm_function_control;
- u64 eptp_list_address;
- u64 pml_address;
- u64 padding64[3]; /* room for future expansion */
- /*
- * To allow migration of L1 (complete with its L2 guests) between
- * machines of different natural widths (32 or 64 bit), we cannot have
- * unsigned long fields with no explict size. We use u64 (aliased
- * natural_width) instead. Luckily, x86 is little-endian.
- */
- natural_width cr0_guest_host_mask;
- natural_width cr4_guest_host_mask;
- natural_width cr0_read_shadow;
- natural_width cr4_read_shadow;
- natural_width cr3_target_value0;
- natural_width cr3_target_value1;
- natural_width cr3_target_value2;
- natural_width cr3_target_value3;
- natural_width exit_qualification;
- natural_width guest_linear_address;
- natural_width guest_cr0;
- natural_width guest_cr3;
- natural_width guest_cr4;
- natural_width guest_es_base;
- natural_width guest_cs_base;
- natural_width guest_ss_base;
- natural_width guest_ds_base;
- natural_width guest_fs_base;
- natural_width guest_gs_base;
- natural_width guest_ldtr_base;
- natural_width guest_tr_base;
- natural_width guest_gdtr_base;
- natural_width guest_idtr_base;
- natural_width guest_dr7;
- natural_width guest_rsp;
- natural_width guest_rip;
- natural_width guest_rflags;
- natural_width guest_pending_dbg_exceptions;
- natural_width guest_sysenter_esp;
- natural_width guest_sysenter_eip;
- natural_width host_cr0;
- natural_width host_cr3;
- natural_width host_cr4;
- natural_width host_fs_base;
- natural_width host_gs_base;
- natural_width host_tr_base;
- natural_width host_gdtr_base;
- natural_width host_idtr_base;
- natural_width host_ia32_sysenter_esp;
- natural_width host_ia32_sysenter_eip;
- natural_width host_rsp;
- natural_width host_rip;
- natural_width paddingl[8]; /* room for future expansion */
- u32 pin_based_vm_exec_control;
- u32 cpu_based_vm_exec_control;
- u32 exception_bitmap;
- u32 page_fault_error_code_mask;
- u32 page_fault_error_code_match;
- u32 cr3_target_count;
- u32 vm_exit_controls;
- u32 vm_exit_msr_store_count;
- u32 vm_exit_msr_load_count;
- u32 vm_entry_controls;
- u32 vm_entry_msr_load_count;
- u32 vm_entry_intr_info_field;
- u32 vm_entry_exception_error_code;
- u32 vm_entry_instruction_len;
- u32 tpr_threshold;
- u32 secondary_vm_exec_control;
- u32 vm_instruction_error;
- u32 vm_exit_reason;
- u32 vm_exit_intr_info;
- u32 vm_exit_intr_error_code;
- u32 idt_vectoring_info_field;
- u32 idt_vectoring_error_code;
- u32 vm_exit_instruction_len;
- u32 vmx_instruction_info;
- u32 guest_es_limit;
- u32 guest_cs_limit;
- u32 guest_ss_limit;
- u32 guest_ds_limit;
- u32 guest_fs_limit;
- u32 guest_gs_limit;
- u32 guest_ldtr_limit;
- u32 guest_tr_limit;
- u32 guest_gdtr_limit;
- u32 guest_idtr_limit;
- u32 guest_es_ar_bytes;
- u32 guest_cs_ar_bytes;
- u32 guest_ss_ar_bytes;
- u32 guest_ds_ar_bytes;
- u32 guest_fs_ar_bytes;
- u32 guest_gs_ar_bytes;
- u32 guest_ldtr_ar_bytes;
- u32 guest_tr_ar_bytes;
- u32 guest_interruptibility_info;
- u32 guest_activity_state;
- u32 guest_sysenter_cs;
- u32 host_ia32_sysenter_cs;
- u32 vmx_preemption_timer_value;
- u32 padding32[7]; /* room for future expansion */
- u16 virtual_processor_id;
- u16 posted_intr_nv;
- u16 guest_es_selector;
- u16 guest_cs_selector;
- u16 guest_ss_selector;
- u16 guest_ds_selector;
- u16 guest_fs_selector;
- u16 guest_gs_selector;
- u16 guest_ldtr_selector;
- u16 guest_tr_selector;
- u16 guest_intr_status;
- u16 host_es_selector;
- u16 host_cs_selector;
- u16 host_ss_selector;
- u16 host_ds_selector;
- u16 host_fs_selector;
- u16 host_gs_selector;
- u16 host_tr_selector;
- u16 guest_pml_index;
-};
-
-/*
- * For save/restore compatibility, the vmcs12 field offsets must not change.
- */
-#define CHECK_OFFSET(field, loc) \
- BUILD_BUG_ON_MSG(offsetof(struct vmcs12, field) != (loc), \
- "Offset of " #field " in struct vmcs12 has changed.")
-
-static inline void vmx_check_vmcs12_offsets(void) {
- CHECK_OFFSET(hdr, 0);
- CHECK_OFFSET(abort, 4);
- CHECK_OFFSET(launch_state, 8);
- CHECK_OFFSET(io_bitmap_a, 40);
- CHECK_OFFSET(io_bitmap_b, 48);
- CHECK_OFFSET(msr_bitmap, 56);
- CHECK_OFFSET(vm_exit_msr_store_addr, 64);
- CHECK_OFFSET(vm_exit_msr_load_addr, 72);
- CHECK_OFFSET(vm_entry_msr_load_addr, 80);
- CHECK_OFFSET(tsc_offset, 88);
- CHECK_OFFSET(virtual_apic_page_addr, 96);
- CHECK_OFFSET(apic_access_addr, 104);
- CHECK_OFFSET(posted_intr_desc_addr, 112);
- CHECK_OFFSET(ept_pointer, 120);
- CHECK_OFFSET(eoi_exit_bitmap0, 128);
- CHECK_OFFSET(eoi_exit_bitmap1, 136);
- CHECK_OFFSET(eoi_exit_bitmap2, 144);
- CHECK_OFFSET(eoi_exit_bitmap3, 152);
- CHECK_OFFSET(xss_exit_bitmap, 160);
- CHECK_OFFSET(guest_physical_address, 168);
- CHECK_OFFSET(vmcs_link_pointer, 176);
- CHECK_OFFSET(guest_ia32_debugctl, 184);
- CHECK_OFFSET(guest_ia32_pat, 192);
- CHECK_OFFSET(guest_ia32_efer, 200);
- CHECK_OFFSET(guest_ia32_perf_global_ctrl, 208);
- CHECK_OFFSET(guest_pdptr0, 216);
- CHECK_OFFSET(guest_pdptr1, 224);
- CHECK_OFFSET(guest_pdptr2, 232);
- CHECK_OFFSET(guest_pdptr3, 240);
- CHECK_OFFSET(guest_bndcfgs, 248);
- CHECK_OFFSET(host_ia32_pat, 256);
- CHECK_OFFSET(host_ia32_efer, 264);
- CHECK_OFFSET(host_ia32_perf_global_ctrl, 272);
- CHECK_OFFSET(vmread_bitmap, 280);
- CHECK_OFFSET(vmwrite_bitmap, 288);
- CHECK_OFFSET(vm_function_control, 296);
- CHECK_OFFSET(eptp_list_address, 304);
- CHECK_OFFSET(pml_address, 312);
- CHECK_OFFSET(cr0_guest_host_mask, 344);
- CHECK_OFFSET(cr4_guest_host_mask, 352);
- CHECK_OFFSET(cr0_read_shadow, 360);
- CHECK_OFFSET(cr4_read_shadow, 368);
- CHECK_OFFSET(cr3_target_value0, 376);
- CHECK_OFFSET(cr3_target_value1, 384);
- CHECK_OFFSET(cr3_target_value2, 392);
- CHECK_OFFSET(cr3_target_value3, 400);
- CHECK_OFFSET(exit_qualification, 408);
- CHECK_OFFSET(guest_linear_address, 416);
- CHECK_OFFSET(guest_cr0, 424);
- CHECK_OFFSET(guest_cr3, 432);
- CHECK_OFFSET(guest_cr4, 440);
- CHECK_OFFSET(guest_es_base, 448);
- CHECK_OFFSET(guest_cs_base, 456);
- CHECK_OFFSET(guest_ss_base, 464);
- CHECK_OFFSET(guest_ds_base, 472);
- CHECK_OFFSET(guest_fs_base, 480);
- CHECK_OFFSET(guest_gs_base, 488);
- CHECK_OFFSET(guest_ldtr_base, 496);
- CHECK_OFFSET(guest_tr_base, 504);
- CHECK_OFFSET(guest_gdtr_base, 512);
- CHECK_OFFSET(guest_idtr_base, 520);
- CHECK_OFFSET(guest_dr7, 528);
- CHECK_OFFSET(guest_rsp, 536);
- CHECK_OFFSET(guest_rip, 544);
- CHECK_OFFSET(guest_rflags, 552);
- CHECK_OFFSET(guest_pending_dbg_exceptions, 560);
- CHECK_OFFSET(guest_sysenter_esp, 568);
- CHECK_OFFSET(guest_sysenter_eip, 576);
- CHECK_OFFSET(host_cr0, 584);
- CHECK_OFFSET(host_cr3, 592);
- CHECK_OFFSET(host_cr4, 600);
- CHECK_OFFSET(host_fs_base, 608);
- CHECK_OFFSET(host_gs_base, 616);
- CHECK_OFFSET(host_tr_base, 624);
- CHECK_OFFSET(host_gdtr_base, 632);
- CHECK_OFFSET(host_idtr_base, 640);
- CHECK_OFFSET(host_ia32_sysenter_esp, 648);
- CHECK_OFFSET(host_ia32_sysenter_eip, 656);
- CHECK_OFFSET(host_rsp, 664);
- CHECK_OFFSET(host_rip, 672);
- CHECK_OFFSET(pin_based_vm_exec_control, 744);
- CHECK_OFFSET(cpu_based_vm_exec_control, 748);
- CHECK_OFFSET(exception_bitmap, 752);
- CHECK_OFFSET(page_fault_error_code_mask, 756);
- CHECK_OFFSET(page_fault_error_code_match, 760);
- CHECK_OFFSET(cr3_target_count, 764);
- CHECK_OFFSET(vm_exit_controls, 768);
- CHECK_OFFSET(vm_exit_msr_store_count, 772);
- CHECK_OFFSET(vm_exit_msr_load_count, 776);
- CHECK_OFFSET(vm_entry_controls, 780);
- CHECK_OFFSET(vm_entry_msr_load_count, 784);
- CHECK_OFFSET(vm_entry_intr_info_field, 788);
- CHECK_OFFSET(vm_entry_exception_error_code, 792);
- CHECK_OFFSET(vm_entry_instruction_len, 796);
- CHECK_OFFSET(tpr_threshold, 800);
- CHECK_OFFSET(secondary_vm_exec_control, 804);
- CHECK_OFFSET(vm_instruction_error, 808);
- CHECK_OFFSET(vm_exit_reason, 812);
- CHECK_OFFSET(vm_exit_intr_info, 816);
- CHECK_OFFSET(vm_exit_intr_error_code, 820);
- CHECK_OFFSET(idt_vectoring_info_field, 824);
- CHECK_OFFSET(idt_vectoring_error_code, 828);
- CHECK_OFFSET(vm_exit_instruction_len, 832);
- CHECK_OFFSET(vmx_instruction_info, 836);
- CHECK_OFFSET(guest_es_limit, 840);
- CHECK_OFFSET(guest_cs_limit, 844);
- CHECK_OFFSET(guest_ss_limit, 848);
- CHECK_OFFSET(guest_ds_limit, 852);
- CHECK_OFFSET(guest_fs_limit, 856);
- CHECK_OFFSET(guest_gs_limit, 860);
- CHECK_OFFSET(guest_ldtr_limit, 864);
- CHECK_OFFSET(guest_tr_limit, 868);
- CHECK_OFFSET(guest_gdtr_limit, 872);
- CHECK_OFFSET(guest_idtr_limit, 876);
- CHECK_OFFSET(guest_es_ar_bytes, 880);
- CHECK_OFFSET(guest_cs_ar_bytes, 884);
- CHECK_OFFSET(guest_ss_ar_bytes, 888);
- CHECK_OFFSET(guest_ds_ar_bytes, 892);
- CHECK_OFFSET(guest_fs_ar_bytes, 896);
- CHECK_OFFSET(guest_gs_ar_bytes, 900);
- CHECK_OFFSET(guest_ldtr_ar_bytes, 904);
- CHECK_OFFSET(guest_tr_ar_bytes, 908);
- CHECK_OFFSET(guest_interruptibility_info, 912);
- CHECK_OFFSET(guest_activity_state, 916);
- CHECK_OFFSET(guest_sysenter_cs, 920);
- CHECK_OFFSET(host_ia32_sysenter_cs, 924);
- CHECK_OFFSET(vmx_preemption_timer_value, 928);
- CHECK_OFFSET(virtual_processor_id, 960);
- CHECK_OFFSET(posted_intr_nv, 962);
- CHECK_OFFSET(guest_es_selector, 964);
- CHECK_OFFSET(guest_cs_selector, 966);
- CHECK_OFFSET(guest_ss_selector, 968);
- CHECK_OFFSET(guest_ds_selector, 970);
- CHECK_OFFSET(guest_fs_selector, 972);
- CHECK_OFFSET(guest_gs_selector, 974);
- CHECK_OFFSET(guest_ldtr_selector, 976);
- CHECK_OFFSET(guest_tr_selector, 978);
- CHECK_OFFSET(guest_intr_status, 980);
- CHECK_OFFSET(host_es_selector, 982);
- CHECK_OFFSET(host_cs_selector, 984);
- CHECK_OFFSET(host_ss_selector, 986);
- CHECK_OFFSET(host_ds_selector, 988);
- CHECK_OFFSET(host_fs_selector, 990);
- CHECK_OFFSET(host_gs_selector, 992);
- CHECK_OFFSET(host_tr_selector, 994);
- CHECK_OFFSET(guest_pml_index, 996);
-}
-
-/*
- * VMCS12_REVISION is an arbitrary id that should be changed if the content or
- * layout of struct vmcs12 is changed. MSR_IA32_VMX_BASIC returns this id, and
- * VMPTRLD verifies that the VMCS region that L1 is loading contains this id.
- *
- * IMPORTANT: Changing this value will break save/restore compatibility with
- * older kvm releases.
- */
-#define VMCS12_REVISION 0x11e57ed0
-
-/*
- * VMCS12_SIZE is the number of bytes L1 should allocate for the VMXON region
- * and any VMCS region. Although only sizeof(struct vmcs12) are used by the
- * current implementation, 4K are reserved to avoid future complications.
- */
-#define VMCS12_SIZE 0x1000
-
-/*
- * VMCS12_MAX_FIELD_INDEX is the highest index value used in any
- * supported VMCS12 field encoding.
- */
-#define VMCS12_MAX_FIELD_INDEX 0x17
-
-struct nested_vmx_msrs {
- /*
- * We only store the "true" versions of the VMX capability MSRs. We
- * generate the "non-true" versions by setting the must-be-1 bits
- * according to the SDM.
- */
- u32 procbased_ctls_low;
- u32 procbased_ctls_high;
- u32 secondary_ctls_low;
- u32 secondary_ctls_high;
- u32 pinbased_ctls_low;
- u32 pinbased_ctls_high;
- u32 exit_ctls_low;
- u32 exit_ctls_high;
- u32 entry_ctls_low;
- u32 entry_ctls_high;
- u32 misc_low;
- u32 misc_high;
- u32 ept_caps;
- u32 vpid_caps;
- u64 basic;
- u64 cr0_fixed0;
- u64 cr0_fixed1;
- u64 cr4_fixed0;
- u64 cr4_fixed1;
- u64 vmcs_enum;
- u64 vmfunc_controls;
-};
-
-/*
- * The nested_vmx structure is part of vcpu_vmx, and holds information we need
- * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
- */
-struct nested_vmx {
- /* Has the level1 guest done vmxon? */
- bool vmxon;
- gpa_t vmxon_ptr;
- bool pml_full;
-
- /* The guest-physical address of the current VMCS L1 keeps for L2 */
- gpa_t current_vmptr;
- /*
- * Cache of the guest's VMCS, existing outside of guest memory.
- * Loaded from guest memory during VMPTRLD. Flushed to guest
- * memory during VMCLEAR and VMPTRLD.
- */
- struct vmcs12 *cached_vmcs12;
- /*
- * Cache of the guest's shadow VMCS, existing outside of guest
- * memory. Loaded from guest memory during VM entry. Flushed
- * to guest memory during VM exit.
- */
- struct vmcs12 *cached_shadow_vmcs12;
- /*
- * Indicates if the shadow vmcs must be updated with the
- * data hold by vmcs12
- */
- bool sync_shadow_vmcs;
- bool dirty_vmcs12;
-
- bool change_vmcs01_virtual_apic_mode;
-
- /* L2 must run next, and mustn't decide to exit to L1. */
- bool nested_run_pending;
-
- struct loaded_vmcs vmcs02;
-
- /*
- * Guest pages referred to in the vmcs02 with host-physical
- * pointers, so we must keep them pinned while L2 runs.
- */
- struct page *apic_access_page;
- struct page *virtual_apic_page;
- struct page *pi_desc_page;
- struct pi_desc *pi_desc;
- bool pi_pending;
- u16 posted_intr_nv;
-
- struct hrtimer preemption_timer;
- bool preemption_timer_expired;
-
- /* to migrate it to L2 if VM_ENTRY_LOAD_DEBUG_CONTROLS is off */
- u64 vmcs01_debugctl;
- u64 vmcs01_guest_bndcfgs;
-
- u16 vpid02;
- u16 last_vpid;
-
- struct nested_vmx_msrs msrs;
-
- /* SMM related state */
- struct {
- /* in VMX operation on SMM entry? */
- bool vmxon;
- /* in guest mode on SMM entry? */
- bool guest_mode;
- } smm;
-};
-
-#define POSTED_INTR_ON 0
-#define POSTED_INTR_SN 1
-
-/* Posted-Interrupt Descriptor */
-struct pi_desc {
- u32 pir[8]; /* Posted interrupt requested */
- union {
- struct {
- /* bit 256 - Outstanding Notification */
- u16 on : 1,
- /* bit 257 - Suppress Notification */
- sn : 1,
- /* bit 271:258 - Reserved */
- rsvd_1 : 14;
- /* bit 279:272 - Notification Vector */
- u8 nv;
- /* bit 287:280 - Reserved */
- u8 rsvd_2;
- /* bit 319:288 - Notification Destination */
- u32 ndst;
- };
- u64 control;
- };
- u32 rsvd[6];
-} __aligned(64);
-
-static bool pi_test_and_set_on(struct pi_desc *pi_desc)
-{
- return test_and_set_bit(POSTED_INTR_ON,
- (unsigned long *)&pi_desc->control);
-}
-
-static bool pi_test_and_clear_on(struct pi_desc *pi_desc)
-{
- return test_and_clear_bit(POSTED_INTR_ON,
- (unsigned long *)&pi_desc->control);
-}
-
-static int pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
-{
- return test_and_set_bit(vector, (unsigned long *)pi_desc->pir);
-}
-
-static inline void pi_clear_sn(struct pi_desc *pi_desc)
-{
- return clear_bit(POSTED_INTR_SN,
- (unsigned long *)&pi_desc->control);
-}
-
-static inline void pi_set_sn(struct pi_desc *pi_desc)
-{
- return set_bit(POSTED_INTR_SN,
- (unsigned long *)&pi_desc->control);
-}
-
-static inline void pi_clear_on(struct pi_desc *pi_desc)
-{
- clear_bit(POSTED_INTR_ON,
- (unsigned long *)&pi_desc->control);
-}
-
-static inline int pi_test_on(struct pi_desc *pi_desc)
-{
- return test_bit(POSTED_INTR_ON,
- (unsigned long *)&pi_desc->control);
-}
-
-static inline int pi_test_sn(struct pi_desc *pi_desc)
-{
- return test_bit(POSTED_INTR_SN,
- (unsigned long *)&pi_desc->control);
-}
-
-struct vmx_msrs {
- unsigned int nr;
- struct vmx_msr_entry val[NR_AUTOLOAD_MSRS];
-};
-
-struct vcpu_vmx {
- struct kvm_vcpu vcpu;
- unsigned long host_rsp;
- u8 fail;
- u8 msr_bitmap_mode;
- u32 exit_intr_info;
- u32 idt_vectoring_info;
- ulong rflags;
- struct shared_msr_entry *guest_msrs;
- int nmsrs;
- int save_nmsrs;
- bool guest_msrs_dirty;
- unsigned long host_idt_base;
-#ifdef CONFIG_X86_64
- u64 msr_host_kernel_gs_base;
- u64 msr_guest_kernel_gs_base;
-#endif
-
- u64 spec_ctrl;
-
- u32 vm_entry_controls_shadow;
- u32 vm_exit_controls_shadow;
- u32 secondary_exec_control;
-
- /*
- * loaded_vmcs points to the VMCS currently used in this vcpu. For a
- * non-nested (L1) guest, it always points to vmcs01. For a nested
- * guest (L2), it points to a different VMCS. loaded_cpu_state points
- * to the VMCS whose state is loaded into the CPU registers that only
- * need to be switched when transitioning to/from the kernel; a NULL
- * value indicates that host state is loaded.
- */
- struct loaded_vmcs vmcs01;
- struct loaded_vmcs *loaded_vmcs;
- struct loaded_vmcs *loaded_cpu_state;
- bool __launched; /* temporary, used in vmx_vcpu_run */
- struct msr_autoload {
- struct vmx_msrs guest;
- struct vmx_msrs host;
- } msr_autoload;
-
- struct {
- int vm86_active;
- ulong save_rflags;
- struct kvm_segment segs[8];
- } rmode;
- struct {
- u32 bitmask; /* 4 bits per segment (1 bit per field) */
- struct kvm_save_segment {
- u16 selector;
- unsigned long base;
- u32 limit;
- u32 ar;
- } seg[8];
- } segment_cache;
- int vpid;
- bool emulation_required;
-
- u32 exit_reason;
-
- /* Posted interrupt descriptor */
- struct pi_desc pi_desc;
-
- /* Support for a guest hypervisor (nested VMX) */
- struct nested_vmx nested;
-
- /* Dynamic PLE window. */
- int ple_window;
- bool ple_window_dirty;
-
- bool req_immediate_exit;
-
- /* Support for PML */
-#define PML_ENTITY_NUM 512
- struct page *pml_pg;
-
- /* apic deadline value in host tsc */
- u64 hv_deadline_tsc;
-
- u64 current_tsc_ratio;
-
- u32 host_pkru;
-
- unsigned long host_debugctlmsr;
-
- /*
- * Only bits masked by msr_ia32_feature_control_valid_bits can be set in
- * msr_ia32_feature_control. FEATURE_CONTROL_LOCKED is always included
- * in msr_ia32_feature_control_valid_bits.
- */
- u64 msr_ia32_feature_control;
- u64 msr_ia32_feature_control_valid_bits;
- u64 ept_pointer;
- u64 msr_ia32_mcu_opt_ctrl;
- bool disable_fb_clear;
-};
-
-enum segment_cache_field {
- SEG_FIELD_SEL = 0,
- SEG_FIELD_BASE = 1,
- SEG_FIELD_LIMIT = 2,
- SEG_FIELD_AR = 3,
-
- SEG_FIELD_NR = 4
-};
-
-static inline struct kvm_vmx *to_kvm_vmx(struct kvm *kvm)
-{
- return container_of(kvm, struct kvm_vmx, kvm);
-}
-
-static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
-{
- return container_of(vcpu, struct vcpu_vmx, vcpu);
-}
-
-static struct pi_desc *vcpu_to_pi_desc(struct kvm_vcpu *vcpu)
-{
- return &(to_vmx(vcpu)->pi_desc);
-}
-
-#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
-#define VMCS12_OFFSET(x) offsetof(struct vmcs12, x)
-#define FIELD(number, name) [ROL16(number, 6)] = VMCS12_OFFSET(name)
-#define FIELD64(number, name) \
- FIELD(number, name), \
- [ROL16(number##_HIGH, 6)] = VMCS12_OFFSET(name) + sizeof(u32)
-
-
-static u16 shadow_read_only_fields[] = {
-#define SHADOW_FIELD_RO(x) x,
-#include "vmx_shadow_fields.h"
-};
-static int max_shadow_read_only_fields =
- ARRAY_SIZE(shadow_read_only_fields);
-
-static u16 shadow_read_write_fields[] = {
-#define SHADOW_FIELD_RW(x) x,
-#include "vmx_shadow_fields.h"
-};
-static int max_shadow_read_write_fields =
- ARRAY_SIZE(shadow_read_write_fields);
-
-static const unsigned short vmcs_field_to_offset_table[] = {
- FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id),
- FIELD(POSTED_INTR_NV, posted_intr_nv),
- FIELD(GUEST_ES_SELECTOR, guest_es_selector),
- FIELD(GUEST_CS_SELECTOR, guest_cs_selector),
- FIELD(GUEST_SS_SELECTOR, guest_ss_selector),
- FIELD(GUEST_DS_SELECTOR, guest_ds_selector),
- FIELD(GUEST_FS_SELECTOR, guest_fs_selector),
- FIELD(GUEST_GS_SELECTOR, guest_gs_selector),
- FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector),
- FIELD(GUEST_TR_SELECTOR, guest_tr_selector),
- FIELD(GUEST_INTR_STATUS, guest_intr_status),
- FIELD(GUEST_PML_INDEX, guest_pml_index),
- FIELD(HOST_ES_SELECTOR, host_es_selector),
- FIELD(HOST_CS_SELECTOR, host_cs_selector),
- FIELD(HOST_SS_SELECTOR, host_ss_selector),
- FIELD(HOST_DS_SELECTOR, host_ds_selector),
- FIELD(HOST_FS_SELECTOR, host_fs_selector),
- FIELD(HOST_GS_SELECTOR, host_gs_selector),
- FIELD(HOST_TR_SELECTOR, host_tr_selector),
- FIELD64(IO_BITMAP_A, io_bitmap_a),
- FIELD64(IO_BITMAP_B, io_bitmap_b),
- FIELD64(MSR_BITMAP, msr_bitmap),
- FIELD64(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr),
- FIELD64(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr),
- FIELD64(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr),
- FIELD64(PML_ADDRESS, pml_address),
- FIELD64(TSC_OFFSET, tsc_offset),
- FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr),
- FIELD64(APIC_ACCESS_ADDR, apic_access_addr),
- FIELD64(POSTED_INTR_DESC_ADDR, posted_intr_desc_addr),
- FIELD64(VM_FUNCTION_CONTROL, vm_function_control),
- FIELD64(EPT_POINTER, ept_pointer),
- FIELD64(EOI_EXIT_BITMAP0, eoi_exit_bitmap0),
- FIELD64(EOI_EXIT_BITMAP1, eoi_exit_bitmap1),
- FIELD64(EOI_EXIT_BITMAP2, eoi_exit_bitmap2),
- FIELD64(EOI_EXIT_BITMAP3, eoi_exit_bitmap3),
- FIELD64(EPTP_LIST_ADDRESS, eptp_list_address),
- FIELD64(VMREAD_BITMAP, vmread_bitmap),
- FIELD64(VMWRITE_BITMAP, vmwrite_bitmap),
- FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap),
- FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address),
- FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer),
- FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl),
- FIELD64(GUEST_IA32_PAT, guest_ia32_pat),
- FIELD64(GUEST_IA32_EFER, guest_ia32_efer),
- FIELD64(GUEST_IA32_PERF_GLOBAL_CTRL, guest_ia32_perf_global_ctrl),
- FIELD64(GUEST_PDPTR0, guest_pdptr0),
- FIELD64(GUEST_PDPTR1, guest_pdptr1),
- FIELD64(GUEST_PDPTR2, guest_pdptr2),
- FIELD64(GUEST_PDPTR3, guest_pdptr3),
- FIELD64(GUEST_BNDCFGS, guest_bndcfgs),
- FIELD64(HOST_IA32_PAT, host_ia32_pat),
- FIELD64(HOST_IA32_EFER, host_ia32_efer),
- FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl),
- FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control),
- FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control),
- FIELD(EXCEPTION_BITMAP, exception_bitmap),
- FIELD(PAGE_FAULT_ERROR_CODE_MASK, page_fault_error_code_mask),
- FIELD(PAGE_FAULT_ERROR_CODE_MATCH, page_fault_error_code_match),
- FIELD(CR3_TARGET_COUNT, cr3_target_count),
- FIELD(VM_EXIT_CONTROLS, vm_exit_controls),
- FIELD(VM_EXIT_MSR_STORE_COUNT, vm_exit_msr_store_count),
- FIELD(VM_EXIT_MSR_LOAD_COUNT, vm_exit_msr_load_count),
- FIELD(VM_ENTRY_CONTROLS, vm_entry_controls),
- FIELD(VM_ENTRY_MSR_LOAD_COUNT, vm_entry_msr_load_count),
- FIELD(VM_ENTRY_INTR_INFO_FIELD, vm_entry_intr_info_field),
- FIELD(VM_ENTRY_EXCEPTION_ERROR_CODE, vm_entry_exception_error_code),
- FIELD(VM_ENTRY_INSTRUCTION_LEN, vm_entry_instruction_len),
- FIELD(TPR_THRESHOLD, tpr_threshold),
- FIELD(SECONDARY_VM_EXEC_CONTROL, secondary_vm_exec_control),
- FIELD(VM_INSTRUCTION_ERROR, vm_instruction_error),
- FIELD(VM_EXIT_REASON, vm_exit_reason),
- FIELD(VM_EXIT_INTR_INFO, vm_exit_intr_info),
- FIELD(VM_EXIT_INTR_ERROR_CODE, vm_exit_intr_error_code),
- FIELD(IDT_VECTORING_INFO_FIELD, idt_vectoring_info_field),
- FIELD(IDT_VECTORING_ERROR_CODE, idt_vectoring_error_code),
- FIELD(VM_EXIT_INSTRUCTION_LEN, vm_exit_instruction_len),
- FIELD(VMX_INSTRUCTION_INFO, vmx_instruction_info),
- FIELD(GUEST_ES_LIMIT, guest_es_limit),
- FIELD(GUEST_CS_LIMIT, guest_cs_limit),
- FIELD(GUEST_SS_LIMIT, guest_ss_limit),
- FIELD(GUEST_DS_LIMIT, guest_ds_limit),
- FIELD(GUEST_FS_LIMIT, guest_fs_limit),
- FIELD(GUEST_GS_LIMIT, guest_gs_limit),
- FIELD(GUEST_LDTR_LIMIT, guest_ldtr_limit),
- FIELD(GUEST_TR_LIMIT, guest_tr_limit),
- FIELD(GUEST_GDTR_LIMIT, guest_gdtr_limit),
- FIELD(GUEST_IDTR_LIMIT, guest_idtr_limit),
- FIELD(GUEST_ES_AR_BYTES, guest_es_ar_bytes),
- FIELD(GUEST_CS_AR_BYTES, guest_cs_ar_bytes),
- FIELD(GUEST_SS_AR_BYTES, guest_ss_ar_bytes),
- FIELD(GUEST_DS_AR_BYTES, guest_ds_ar_bytes),
- FIELD(GUEST_FS_AR_BYTES, guest_fs_ar_bytes),
- FIELD(GUEST_GS_AR_BYTES, guest_gs_ar_bytes),
- FIELD(GUEST_LDTR_AR_BYTES, guest_ldtr_ar_bytes),
- FIELD(GUEST_TR_AR_BYTES, guest_tr_ar_bytes),
- FIELD(GUEST_INTERRUPTIBILITY_INFO, guest_interruptibility_info),
- FIELD(GUEST_ACTIVITY_STATE, guest_activity_state),
- FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs),
- FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs),
- FIELD(VMX_PREEMPTION_TIMER_VALUE, vmx_preemption_timer_value),
- FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask),
- FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask),
- FIELD(CR0_READ_SHADOW, cr0_read_shadow),
- FIELD(CR4_READ_SHADOW, cr4_read_shadow),
- FIELD(CR3_TARGET_VALUE0, cr3_target_value0),
- FIELD(CR3_TARGET_VALUE1, cr3_target_value1),
- FIELD(CR3_TARGET_VALUE2, cr3_target_value2),
- FIELD(CR3_TARGET_VALUE3, cr3_target_value3),
- FIELD(EXIT_QUALIFICATION, exit_qualification),
- FIELD(GUEST_LINEAR_ADDRESS, guest_linear_address),
- FIELD(GUEST_CR0, guest_cr0),
- FIELD(GUEST_CR3, guest_cr3),
- FIELD(GUEST_CR4, guest_cr4),
- FIELD(GUEST_ES_BASE, guest_es_base),
- FIELD(GUEST_CS_BASE, guest_cs_base),
- FIELD(GUEST_SS_BASE, guest_ss_base),
- FIELD(GUEST_DS_BASE, guest_ds_base),
- FIELD(GUEST_FS_BASE, guest_fs_base),
- FIELD(GUEST_GS_BASE, guest_gs_base),
- FIELD(GUEST_LDTR_BASE, guest_ldtr_base),
- FIELD(GUEST_TR_BASE, guest_tr_base),
- FIELD(GUEST_GDTR_BASE, guest_gdtr_base),
- FIELD(GUEST_IDTR_BASE, guest_idtr_base),
- FIELD(GUEST_DR7, guest_dr7),
- FIELD(GUEST_RSP, guest_rsp),
- FIELD(GUEST_RIP, guest_rip),
- FIELD(GUEST_RFLAGS, guest_rflags),
- FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions),
- FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp),
- FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip),
- FIELD(HOST_CR0, host_cr0),
- FIELD(HOST_CR3, host_cr3),
- FIELD(HOST_CR4, host_cr4),
- FIELD(HOST_FS_BASE, host_fs_base),
- FIELD(HOST_GS_BASE, host_gs_base),
- FIELD(HOST_TR_BASE, host_tr_base),
- FIELD(HOST_GDTR_BASE, host_gdtr_base),
- FIELD(HOST_IDTR_BASE, host_idtr_base),
- FIELD(HOST_IA32_SYSENTER_ESP, host_ia32_sysenter_esp),
- FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip),
- FIELD(HOST_RSP, host_rsp),
- FIELD(HOST_RIP, host_rip),
-};
-
-static inline short vmcs_field_to_offset(unsigned long field)
-{
- const size_t size = ARRAY_SIZE(vmcs_field_to_offset_table);
- unsigned short offset;
- unsigned index;
-
- if (field >> 15)
- return -ENOENT;
-
- index = ROL16(field, 6);
- if (index >= size)
- return -ENOENT;
-
- index = array_index_nospec(index, size);
- offset = vmcs_field_to_offset_table[index];
- if (offset == 0)
- return -ENOENT;
- return offset;
-}
-
-static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
-{
- return to_vmx(vcpu)->nested.cached_vmcs12;
-}
-
-static inline struct vmcs12 *get_shadow_vmcs12(struct kvm_vcpu *vcpu)
-{
- return to_vmx(vcpu)->nested.cached_shadow_vmcs12;
-}
-
-static bool nested_ept_ad_enabled(struct kvm_vcpu *vcpu);
-static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu);
-static u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa);
-static bool vmx_xsaves_supported(void);
-static void vmx_set_segment(struct kvm_vcpu *vcpu,
- struct kvm_segment *var, int seg);
-static void vmx_get_segment(struct kvm_vcpu *vcpu,
- struct kvm_segment *var, int seg);
-static bool guest_state_valid(struct kvm_vcpu *vcpu);
-static u32 vmx_segment_access_rights(struct kvm_segment *var);
-static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx);
-static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu);
-static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked);
-static bool nested_vmx_is_page_fault_vmexit(struct vmcs12 *vmcs12,
- u16 error_code);
-static void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu);
-static __always_inline void vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
- u32 msr, int type);
-
-static DEFINE_PER_CPU(struct vmcs *, vmxarea);
-static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
-/*
- * We maintain a per-CPU linked-list of VMCS loaded on that CPU. This is needed
- * when a CPU is brought down, and we need to VMCLEAR all VMCSs loaded on it.
- */
-static DEFINE_PER_CPU(struct list_head, loaded_vmcss_on_cpu);
-
-/*
- * We maintian a per-CPU linked-list of vCPU, so in wakeup_handler() we
- * can find which vCPU should be waken up.
- */
-static DEFINE_PER_CPU(struct list_head, blocked_vcpu_on_cpu);
-static DEFINE_PER_CPU(spinlock_t, blocked_vcpu_on_cpu_lock);
-
-enum {
- VMX_VMREAD_BITMAP,
- VMX_VMWRITE_BITMAP,
- VMX_BITMAP_NR
-};
-
-static unsigned long *vmx_bitmap[VMX_BITMAP_NR];
-
-#define vmx_vmread_bitmap (vmx_bitmap[VMX_VMREAD_BITMAP])
-#define vmx_vmwrite_bitmap (vmx_bitmap[VMX_VMWRITE_BITMAP])
-
-static bool cpu_has_load_ia32_efer;
-static bool cpu_has_load_perf_global_ctrl;
-
-static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
-static DEFINE_SPINLOCK(vmx_vpid_lock);
-
-static struct vmcs_config {
- int size;
- int order;
- u32 basic_cap;
- u32 revision_id;
- u32 pin_based_exec_ctrl;
- u32 cpu_based_exec_ctrl;
- u32 cpu_based_2nd_exec_ctrl;
- u32 vmexit_ctrl;
- u32 vmentry_ctrl;
- struct nested_vmx_msrs nested;
-} vmcs_config;
-
-static struct vmx_capability {
- u32 ept;
- u32 vpid;
-} vmx_capability;
-
-#define VMX_SEGMENT_FIELD(seg) \
- [VCPU_SREG_##seg] = { \
- .selector = GUEST_##seg##_SELECTOR, \
- .base = GUEST_##seg##_BASE, \
- .limit = GUEST_##seg##_LIMIT, \
- .ar_bytes = GUEST_##seg##_AR_BYTES, \
- }
-
-static const struct kvm_vmx_segment_field {
- unsigned selector;
- unsigned base;
- unsigned limit;
- unsigned ar_bytes;
-} kvm_vmx_segment_fields[] = {
- VMX_SEGMENT_FIELD(CS),
- VMX_SEGMENT_FIELD(DS),
- VMX_SEGMENT_FIELD(ES),
- VMX_SEGMENT_FIELD(FS),
- VMX_SEGMENT_FIELD(GS),
- VMX_SEGMENT_FIELD(SS),
- VMX_SEGMENT_FIELD(TR),
- VMX_SEGMENT_FIELD(LDTR),
-};
-
-static u64 host_efer;
-
-static void ept_save_pdptrs(struct kvm_vcpu *vcpu);
-
-/*
- * Keep MSR_STAR at the end, as setup_msrs() will try to optimize it
- * away by decrementing the array size.
- */
-static const u32 vmx_msr_index[] = {
-#ifdef CONFIG_X86_64
- MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR,
-#endif
- MSR_EFER, MSR_TSC_AUX, MSR_STAR,
-};
-
-DEFINE_STATIC_KEY_FALSE(enable_evmcs);
-
-#define current_evmcs ((struct hv_enlightened_vmcs *)this_cpu_read(current_vmcs))
-
-#define KVM_EVMCS_VERSION 1
-
-#if IS_ENABLED(CONFIG_HYPERV)
-static bool __read_mostly enlightened_vmcs = true;
-module_param(enlightened_vmcs, bool, 0444);
-
-static inline void evmcs_write64(unsigned long field, u64 value)
-{
- u16 clean_field;
- int offset = get_evmcs_offset(field, &clean_field);
-
- if (offset < 0)
- return;
-
- *(u64 *)((char *)current_evmcs + offset) = value;
-
- current_evmcs->hv_clean_fields &= ~clean_field;
-}
-
-static inline void evmcs_write32(unsigned long field, u32 value)
-{
- u16 clean_field;
- int offset = get_evmcs_offset(field, &clean_field);
-
- if (offset < 0)
- return;
-
- *(u32 *)((char *)current_evmcs + offset) = value;
- current_evmcs->hv_clean_fields &= ~clean_field;
-}
-
-static inline void evmcs_write16(unsigned long field, u16 value)
-{
- u16 clean_field;
- int offset = get_evmcs_offset(field, &clean_field);
-
- if (offset < 0)
- return;
-
- *(u16 *)((char *)current_evmcs + offset) = value;
- current_evmcs->hv_clean_fields &= ~clean_field;
-}
-
-static inline u64 evmcs_read64(unsigned long field)
-{
- int offset = get_evmcs_offset(field, NULL);
-
- if (offset < 0)
- return 0;
-
- return *(u64 *)((char *)current_evmcs + offset);
-}
-
-static inline u32 evmcs_read32(unsigned long field)
-{
- int offset = get_evmcs_offset(field, NULL);
-
- if (offset < 0)
- return 0;
-
- return *(u32 *)((char *)current_evmcs + offset);
-}
-
-static inline u16 evmcs_read16(unsigned long field)
-{
- int offset = get_evmcs_offset(field, NULL);
-
- if (offset < 0)
- return 0;
-
- return *(u16 *)((char *)current_evmcs + offset);
-}
-
-static inline void evmcs_touch_msr_bitmap(void)
-{
- if (unlikely(!current_evmcs))
- return;
-
- if (current_evmcs->hv_enlightenments_control.msr_bitmap)
- current_evmcs->hv_clean_fields &=
- ~HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP;
-}
-
-static void evmcs_load(u64 phys_addr)
-{
- struct hv_vp_assist_page *vp_ap =
- hv_get_vp_assist_page(smp_processor_id());
-
- vp_ap->current_nested_vmcs = phys_addr;
- vp_ap->enlighten_vmentry = 1;
-}
-
-static void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
-{
- /*
- * Enlightened VMCSv1 doesn't support these:
- *
- * POSTED_INTR_NV = 0x00000002,
- * GUEST_INTR_STATUS = 0x00000810,
- * APIC_ACCESS_ADDR = 0x00002014,
- * POSTED_INTR_DESC_ADDR = 0x00002016,
- * EOI_EXIT_BITMAP0 = 0x0000201c,
- * EOI_EXIT_BITMAP1 = 0x0000201e,
- * EOI_EXIT_BITMAP2 = 0x00002020,
- * EOI_EXIT_BITMAP3 = 0x00002022,
- */
- vmcs_conf->pin_based_exec_ctrl &= ~PIN_BASED_POSTED_INTR;
- vmcs_conf->cpu_based_2nd_exec_ctrl &=
- ~SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
- vmcs_conf->cpu_based_2nd_exec_ctrl &=
- ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
- vmcs_conf->cpu_based_2nd_exec_ctrl &=
- ~SECONDARY_EXEC_APIC_REGISTER_VIRT;
-
- /*
- * GUEST_PML_INDEX = 0x00000812,
- * PML_ADDRESS = 0x0000200e,
- */
- vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_ENABLE_PML;
-
- /* VM_FUNCTION_CONTROL = 0x00002018, */
- vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_ENABLE_VMFUNC;
-
- /*
- * EPTP_LIST_ADDRESS = 0x00002024,
- * VMREAD_BITMAP = 0x00002026,
- * VMWRITE_BITMAP = 0x00002028,
- */
- vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_SHADOW_VMCS;
-
- /*
- * TSC_MULTIPLIER = 0x00002032,
- */
- vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_TSC_SCALING;
-
- /*
- * PLE_GAP = 0x00004020,
- * PLE_WINDOW = 0x00004022,
- */
- vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
-
- /*
- * VMX_PREEMPTION_TIMER_VALUE = 0x0000482E,
- */
- vmcs_conf->pin_based_exec_ctrl &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
-
- /*
- * GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808,
- * HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04,
- */
- vmcs_conf->vmexit_ctrl &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
- vmcs_conf->vmentry_ctrl &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
-
- /*
- * Currently unsupported in KVM:
- * GUEST_IA32_RTIT_CTL = 0x00002814,
- */
-}
-
-/* check_ept_pointer() should be under protection of ept_pointer_lock. */
-static void check_ept_pointer_match(struct kvm *kvm)
-{
- struct kvm_vcpu *vcpu;
- u64 tmp_eptp = INVALID_PAGE;
- int i;
-
- kvm_for_each_vcpu(i, vcpu, kvm) {
- if (!VALID_PAGE(tmp_eptp)) {
- tmp_eptp = to_vmx(vcpu)->ept_pointer;
- } else if (tmp_eptp != to_vmx(vcpu)->ept_pointer) {
- to_kvm_vmx(kvm)->ept_pointers_match
- = EPT_POINTERS_MISMATCH;
- return;
- }
- }
-
- to_kvm_vmx(kvm)->ept_pointers_match = EPT_POINTERS_MATCH;
-}
-
-static int vmx_hv_remote_flush_tlb(struct kvm *kvm)
-{
- int ret;
-
- spin_lock(&to_kvm_vmx(kvm)->ept_pointer_lock);
-
- if (to_kvm_vmx(kvm)->ept_pointers_match == EPT_POINTERS_CHECK)
- check_ept_pointer_match(kvm);
-
- if (to_kvm_vmx(kvm)->ept_pointers_match != EPT_POINTERS_MATCH) {
- ret = -ENOTSUPP;
- goto out;
- }
-
- /*
- * FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE hypercall needs the address of the
- * base of EPT PML4 table, strip off EPT configuration information.
- */
- ret = hyperv_flush_guest_mapping(
- to_vmx(kvm_get_vcpu(kvm, 0))->ept_pointer & PAGE_MASK);
-
-out:
- spin_unlock(&to_kvm_vmx(kvm)->ept_pointer_lock);
- return ret;
-}
-#else /* !IS_ENABLED(CONFIG_HYPERV) */
-static inline void evmcs_write64(unsigned long field, u64 value) {}
-static inline void evmcs_write32(unsigned long field, u32 value) {}
-static inline void evmcs_write16(unsigned long field, u16 value) {}
-static inline u64 evmcs_read64(unsigned long field) { return 0; }
-static inline u32 evmcs_read32(unsigned long field) { return 0; }
-static inline u16 evmcs_read16(unsigned long field) { return 0; }
-static inline void evmcs_load(u64 phys_addr) {}
-static inline void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) {}
-static inline void evmcs_touch_msr_bitmap(void) {}
-#endif /* IS_ENABLED(CONFIG_HYPERV) */
-
-static inline bool is_exception_n(u32 intr_info, u8 vector)
-{
- return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
- INTR_INFO_VALID_MASK)) ==
- (INTR_TYPE_HARD_EXCEPTION | vector | INTR_INFO_VALID_MASK);
-}
-
-static inline bool is_debug(u32 intr_info)
-{
- return is_exception_n(intr_info, DB_VECTOR);
-}
-
-static inline bool is_breakpoint(u32 intr_info)
-{
- return is_exception_n(intr_info, BP_VECTOR);
-}
-
-static inline bool is_page_fault(u32 intr_info)
-{
- return is_exception_n(intr_info, PF_VECTOR);
-}
-
-static inline bool is_no_device(u32 intr_info)
-{
- return is_exception_n(intr_info, NM_VECTOR);
-}
-
-static inline bool is_invalid_opcode(u32 intr_info)
-{
- return is_exception_n(intr_info, UD_VECTOR);
-}
-
-static inline bool is_gp_fault(u32 intr_info)
-{
- return is_exception_n(intr_info, GP_VECTOR);
-}
-
-static inline bool is_external_interrupt(u32 intr_info)
-{
- return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
- == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
-}
-
-static inline bool is_machine_check(u32 intr_info)
-{
- return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
- INTR_INFO_VALID_MASK)) ==
- (INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK);
-}
-
-/* Undocumented: icebp/int1 */
-static inline bool is_icebp(u32 intr_info)
-{
- return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
- == (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK);
-}
-
-static inline bool cpu_has_vmx_msr_bitmap(void)
-{
- return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
-}
-
-static inline bool cpu_has_vmx_tpr_shadow(void)
-{
- return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
-}
-
-static inline bool cpu_need_tpr_shadow(struct kvm_vcpu *vcpu)
-{
- return cpu_has_vmx_tpr_shadow() && lapic_in_kernel(vcpu);
-}
-
-static inline bool cpu_has_secondary_exec_ctrls(void)
-{
- return vmcs_config.cpu_based_exec_ctrl &
- CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
-}
-
-static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
-}
-
-static inline bool cpu_has_vmx_virtualize_x2apic_mode(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
-}
-
-static inline bool cpu_has_vmx_apic_register_virt(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_APIC_REGISTER_VIRT;
-}
-
-static inline bool cpu_has_vmx_virtual_intr_delivery(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
-}
-
-static inline bool cpu_has_vmx_encls_vmexit(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_ENCLS_EXITING;
-}
-
-/*
- * Comment's format: document - errata name - stepping - processor name.
- * Refer from
- * https://www.virtualbox.org/svn/vbox/trunk/src/VBox/VMM/VMMR0/HMR0.cpp
- */
-static u32 vmx_preemption_cpu_tfms[] = {
-/* 323344.pdf - BA86 - D0 - Xeon 7500 Series */
-0x000206E6,
-/* 323056.pdf - AAX65 - C2 - Xeon L3406 */
-/* 322814.pdf - AAT59 - C2 - i7-600, i5-500, i5-400 and i3-300 Mobile */
-/* 322911.pdf - AAU65 - C2 - i5-600, i3-500 Desktop and Pentium G6950 */
-0x00020652,
-/* 322911.pdf - AAU65 - K0 - i5-600, i3-500 Desktop and Pentium G6950 */
-0x00020655,
-/* 322373.pdf - AAO95 - B1 - Xeon 3400 Series */
-/* 322166.pdf - AAN92 - B1 - i7-800 and i5-700 Desktop */
-/*
- * 320767.pdf - AAP86 - B1 -
- * i7-900 Mobile Extreme, i7-800 and i7-700 Mobile
- */
-0x000106E5,
-/* 321333.pdf - AAM126 - C0 - Xeon 3500 */
-0x000106A0,
-/* 321333.pdf - AAM126 - C1 - Xeon 3500 */
-0x000106A1,
-/* 320836.pdf - AAJ124 - C0 - i7-900 Desktop Extreme and i7-900 Desktop */
-0x000106A4,
- /* 321333.pdf - AAM126 - D0 - Xeon 3500 */
- /* 321324.pdf - AAK139 - D0 - Xeon 5500 */
- /* 320836.pdf - AAJ124 - D0 - i7-900 Extreme and i7-900 Desktop */
-0x000106A5,
-};
-
-static inline bool cpu_has_broken_vmx_preemption_timer(void)
-{
- u32 eax = cpuid_eax(0x00000001), i;
-
- /* Clear the reserved bits */
- eax &= ~(0x3U << 14 | 0xfU << 28);
- for (i = 0; i < ARRAY_SIZE(vmx_preemption_cpu_tfms); i++)
- if (eax == vmx_preemption_cpu_tfms[i])
- return true;
-
- return false;
-}
-
-static inline bool cpu_has_vmx_preemption_timer(void)
-{
- return vmcs_config.pin_based_exec_ctrl &
- PIN_BASED_VMX_PREEMPTION_TIMER;
-}
-
-static inline bool cpu_has_vmx_posted_intr(void)
-{
- return IS_ENABLED(CONFIG_X86_LOCAL_APIC) &&
- vmcs_config.pin_based_exec_ctrl & PIN_BASED_POSTED_INTR;
-}
-
-static inline bool cpu_has_vmx_apicv(void)
-{
- return cpu_has_vmx_apic_register_virt() &&
- cpu_has_vmx_virtual_intr_delivery() &&
- cpu_has_vmx_posted_intr();
-}
-
-static inline bool cpu_has_vmx_flexpriority(void)
-{
- return cpu_has_vmx_tpr_shadow() &&
- cpu_has_vmx_virtualize_apic_accesses();
-}
-
-static inline bool cpu_has_vmx_ept_execute_only(void)
-{
- return vmx_capability.ept & VMX_EPT_EXECUTE_ONLY_BIT;
-}
-
-static inline bool cpu_has_vmx_ept_2m_page(void)
-{
- return vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT;
-}
-
-static inline bool cpu_has_vmx_ept_1g_page(void)
-{
- return vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT;
-}
-
-static inline bool cpu_has_vmx_ept_4levels(void)
-{
- return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT;
-}
-
-static inline bool cpu_has_vmx_ept_mt_wb(void)
-{
- return vmx_capability.ept & VMX_EPTP_WB_BIT;
-}
-
-static inline bool cpu_has_vmx_ept_5levels(void)
-{
- return vmx_capability.ept & VMX_EPT_PAGE_WALK_5_BIT;
-}
-
-static inline bool cpu_has_vmx_ept_ad_bits(void)
-{
- return vmx_capability.ept & VMX_EPT_AD_BIT;
-}
-
-static inline bool cpu_has_vmx_invept_context(void)
-{
- return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
-}
-
-static inline bool cpu_has_vmx_invept_global(void)
-{
- return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
-}
-
-static inline bool cpu_has_vmx_invvpid_individual_addr(void)
-{
- return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT;
-}
-
-static inline bool cpu_has_vmx_invvpid_single(void)
-{
- return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
-}
-
-static inline bool cpu_has_vmx_invvpid_global(void)
-{
- return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
-}
-
-static inline bool cpu_has_vmx_invvpid(void)
-{
- return vmx_capability.vpid & VMX_VPID_INVVPID_BIT;
-}
-
-static inline bool cpu_has_vmx_ept(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_ENABLE_EPT;
-}
-
-static inline bool cpu_has_vmx_unrestricted_guest(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_UNRESTRICTED_GUEST;
-}
-
-static inline bool cpu_has_vmx_ple(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_PAUSE_LOOP_EXITING;
-}
-
-static inline bool cpu_has_vmx_basic_inout(void)
-{
- return (((u64)vmcs_config.basic_cap << 32) & VMX_BASIC_INOUT);
-}
-
-static inline bool cpu_need_virtualize_apic_accesses(struct kvm_vcpu *vcpu)
-{
- return flexpriority_enabled && lapic_in_kernel(vcpu);
-}
-
-static inline bool cpu_has_vmx_vpid(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_ENABLE_VPID;
-}
-
-static inline bool cpu_has_vmx_rdtscp(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_RDTSCP;
-}
-
-static inline bool cpu_has_vmx_invpcid(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_ENABLE_INVPCID;
-}
-
-static inline bool cpu_has_virtual_nmis(void)
-{
- return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
-}
-
-static inline bool cpu_has_vmx_wbinvd_exit(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_WBINVD_EXITING;
-}
-
-static inline bool cpu_has_vmx_shadow_vmcs(void)
-{
- u64 vmx_msr;
- rdmsrl(MSR_IA32_VMX_MISC, vmx_msr);
- /* check if the cpu supports writing r/o exit information fields */
- if (!(vmx_msr & MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS))
- return false;
-
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_SHADOW_VMCS;
-}
-
-static inline bool cpu_has_vmx_pml(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_ENABLE_PML;
-}
-
-static inline bool cpu_has_vmx_tsc_scaling(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_TSC_SCALING;
-}
-
-static inline bool cpu_has_vmx_vmfunc(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_ENABLE_VMFUNC;
-}
-
-static bool vmx_umip_emulated(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_DESC;
-}
-
-static inline bool report_flexpriority(void)
-{
- return flexpriority_enabled;
-}
-
-static inline unsigned nested_cpu_vmx_misc_cr3_count(struct kvm_vcpu *vcpu)
-{
- return vmx_misc_cr3_count(to_vmx(vcpu)->nested.msrs.misc_low);
-}
-
-/*
- * Do the virtual VMX capability MSRs specify that L1 can use VMWRITE
- * to modify any valid field of the VMCS, or are the VM-exit
- * information fields read-only?
- */
-static inline bool nested_cpu_has_vmwrite_any_field(struct kvm_vcpu *vcpu)
-{
- return to_vmx(vcpu)->nested.msrs.misc_low &
- MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS;
-}
-
-static inline bool nested_cpu_has_zero_length_injection(struct kvm_vcpu *vcpu)
-{
- return to_vmx(vcpu)->nested.msrs.misc_low & VMX_MISC_ZERO_LEN_INS;
-}
-
-static inline bool nested_cpu_supports_monitor_trap_flag(struct kvm_vcpu *vcpu)
-{
- return to_vmx(vcpu)->nested.msrs.procbased_ctls_high &
- CPU_BASED_MONITOR_TRAP_FLAG;
-}
-
-static inline bool nested_cpu_has_vmx_shadow_vmcs(struct kvm_vcpu *vcpu)
-{
- return to_vmx(vcpu)->nested.msrs.secondary_ctls_high &
- SECONDARY_EXEC_SHADOW_VMCS;
-}
-
-static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit)
-{
- return vmcs12->cpu_based_vm_exec_control & bit;
-}
-
-static inline bool nested_cpu_has2(struct vmcs12 *vmcs12, u32 bit)
-{
- return (vmcs12->cpu_based_vm_exec_control &
- CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) &&
- (vmcs12->secondary_vm_exec_control & bit);
-}
-
-static inline bool nested_cpu_has_preemption_timer(struct vmcs12 *vmcs12)
-{
- return vmcs12->pin_based_vm_exec_control &
- PIN_BASED_VMX_PREEMPTION_TIMER;
-}
-
-static inline bool nested_cpu_has_nmi_exiting(struct vmcs12 *vmcs12)
-{
- return vmcs12->pin_based_vm_exec_control & PIN_BASED_NMI_EXITING;
-}
-
-static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12)
-{
- return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
-}
-
-static inline int nested_cpu_has_ept(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT);
-}
-
-static inline bool nested_cpu_has_xsaves(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES);
-}
-
-static inline bool nested_cpu_has_pml(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_PML);
-}
-
-static inline bool nested_cpu_has_virt_x2apic_mode(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE);
-}
-
-static inline bool nested_cpu_has_vpid(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_VPID);
-}
-
-static inline bool nested_cpu_has_apic_reg_virt(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_APIC_REGISTER_VIRT);
-}
-
-static inline bool nested_cpu_has_vid(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
-}
-
-static inline bool nested_cpu_has_posted_intr(struct vmcs12 *vmcs12)
-{
- return vmcs12->pin_based_vm_exec_control & PIN_BASED_POSTED_INTR;
-}
-
-static inline bool nested_cpu_has_vmfunc(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_VMFUNC);
-}
-
-static inline bool nested_cpu_has_eptp_switching(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has_vmfunc(vmcs12) &&
- (vmcs12->vm_function_control &
- VMX_VMFUNC_EPTP_SWITCHING);
-}
-
-static inline bool nested_cpu_has_shadow_vmcs(struct vmcs12 *vmcs12)
-{
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_SHADOW_VMCS);
-}
-
-static inline bool is_nmi(u32 intr_info)
-{
- return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
- == (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK);
-}
-
-static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
- u32 exit_intr_info,
- unsigned long exit_qualification);
-static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12,
- u32 reason, unsigned long qualification);
-
-static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
-{
- int i;
-
- for (i = 0; i < vmx->nmsrs; ++i)
- if (vmx_msr_index[vmx->guest_msrs[i].index] == msr)
- return i;
- return -1;
-}
-
-static inline void __invvpid(unsigned long ext, u16 vpid, gva_t gva)
-{
- struct {
- u64 vpid : 16;
- u64 rsvd : 48;
- u64 gva;
- } operand = { vpid, 0, gva };
- bool error;
-
- asm volatile (__ex(ASM_VMX_INVVPID) CC_SET(na)
- : CC_OUT(na) (error) : "a"(&operand), "c"(ext)
- : "memory");
- BUG_ON(error);
-}
-
-static inline void __invept(unsigned long ext, u64 eptp, gpa_t gpa)
-{
- struct {
- u64 eptp, gpa;
- } operand = {eptp, gpa};
- bool error;
-
- asm volatile (__ex(ASM_VMX_INVEPT) CC_SET(na)
- : CC_OUT(na) (error) : "a" (&operand), "c" (ext)
- : "memory");
- BUG_ON(error);
-}
-
-static void vmx_setup_fb_clear_ctrl(void)
-{
- u64 msr;
-
- if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES) &&
- !boot_cpu_has_bug(X86_BUG_MDS) &&
- !boot_cpu_has_bug(X86_BUG_TAA)) {
- rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr);
- if (msr & ARCH_CAP_FB_CLEAR_CTRL)
- vmx_fb_clear_ctrl_available = true;
- }
-}
-
-static __always_inline void vmx_disable_fb_clear(struct vcpu_vmx *vmx)
-{
- u64 msr;
-
- if (!vmx->disable_fb_clear)
- return;
-
- msr = __rdmsr(MSR_IA32_MCU_OPT_CTRL);
- msr |= FB_CLEAR_DIS;
- native_wrmsrl(MSR_IA32_MCU_OPT_CTRL, msr);
- /* Cache the MSR value to avoid reading it later */
- vmx->msr_ia32_mcu_opt_ctrl = msr;
-}
-
-static __always_inline void vmx_enable_fb_clear(struct vcpu_vmx *vmx)
-{
- if (!vmx->disable_fb_clear)
- return;
-
- vmx->msr_ia32_mcu_opt_ctrl &= ~FB_CLEAR_DIS;
- native_wrmsrl(MSR_IA32_MCU_OPT_CTRL, vmx->msr_ia32_mcu_opt_ctrl);
-}
-
-static void vmx_update_fb_clear_dis(struct kvm_vcpu *vcpu, struct vcpu_vmx *vmx)
-{
- vmx->disable_fb_clear = vmx_fb_clear_ctrl_available;
-
- /*
- * If guest will not execute VERW, there is no need to set FB_CLEAR_DIS
- * at VMEntry. Skip the MSR read/write when a guest has no use case to
- * execute VERW.
- */
- if ((vcpu->arch.arch_capabilities & ARCH_CAP_FB_CLEAR) ||
- ((vcpu->arch.arch_capabilities & ARCH_CAP_MDS_NO) &&
- (vcpu->arch.arch_capabilities & ARCH_CAP_TAA_NO) &&
- (vcpu->arch.arch_capabilities & ARCH_CAP_PSDP_NO) &&
- (vcpu->arch.arch_capabilities & ARCH_CAP_FBSDP_NO) &&
- (vcpu->arch.arch_capabilities & ARCH_CAP_SBDR_SSDP_NO)))
- vmx->disable_fb_clear = false;
-}
-
-static struct shared_msr_entry *find_msr_entry(struct vcpu_vmx *vmx, u32 msr)
-{
- int i;
-
- i = __find_msr_index(vmx, msr);
- if (i >= 0)
- return &vmx->guest_msrs[i];
- return NULL;
-}
-
-static void vmcs_clear(struct vmcs *vmcs)
-{
- u64 phys_addr = __pa(vmcs);
- bool error;
-
- asm volatile (__ex(ASM_VMX_VMCLEAR_RAX) CC_SET(na)
- : CC_OUT(na) (error) : "a"(&phys_addr), "m"(phys_addr)
- : "memory");
- if (unlikely(error))
- printk(KERN_ERR "kvm: vmclear fail: %p/%llx\n",
- vmcs, phys_addr);
-}
-
-static inline void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs)
-{
- vmcs_clear(loaded_vmcs->vmcs);
- if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched)
- vmcs_clear(loaded_vmcs->shadow_vmcs);
- loaded_vmcs->cpu = -1;
- loaded_vmcs->launched = 0;
-}
-
-static void vmcs_load(struct vmcs *vmcs)
-{
- u64 phys_addr = __pa(vmcs);
- bool error;
-
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_load(phys_addr);
-
- asm volatile (__ex(ASM_VMX_VMPTRLD_RAX) CC_SET(na)
- : CC_OUT(na) (error) : "a"(&phys_addr), "m"(phys_addr)
- : "memory");
- if (unlikely(error))
- printk(KERN_ERR "kvm: vmptrld %p/%llx failed\n",
- vmcs, phys_addr);
-}
-
-#ifdef CONFIG_KEXEC_CORE
-static void crash_vmclear_local_loaded_vmcss(void)
-{
- int cpu = raw_smp_processor_id();
- struct loaded_vmcs *v;
-
- list_for_each_entry(v, &per_cpu(loaded_vmcss_on_cpu, cpu),
- loaded_vmcss_on_cpu_link)
- vmcs_clear(v->vmcs);
-}
-#endif /* CONFIG_KEXEC_CORE */
-
-static void __loaded_vmcs_clear(void *arg)
-{
- struct loaded_vmcs *loaded_vmcs = arg;
- int cpu = raw_smp_processor_id();
-
- if (loaded_vmcs->cpu != cpu)
- return; /* vcpu migration can race with cpu offline */
- if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs)
- per_cpu(current_vmcs, cpu) = NULL;
-
- vmcs_clear(loaded_vmcs->vmcs);
- if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched)
- vmcs_clear(loaded_vmcs->shadow_vmcs);
-
- list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link);
-
- /*
- * Ensure all writes to loaded_vmcs, including deleting it from its
- * current percpu list, complete before setting loaded_vmcs->vcpu to
- * -1, otherwise a different cpu can see vcpu == -1 first and add
- * loaded_vmcs to its percpu list before it's deleted from this cpu's
- * list. Pairs with the smp_rmb() in vmx_vcpu_load_vmcs().
- */
- smp_wmb();
-
- loaded_vmcs->cpu = -1;
- loaded_vmcs->launched = 0;
-}
-
-static void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs)
-{
- int cpu = loaded_vmcs->cpu;
-
- if (cpu != -1)
- smp_call_function_single(cpu,
- __loaded_vmcs_clear, loaded_vmcs, 1);
-}
-
-static inline bool vpid_sync_vcpu_addr(int vpid, gva_t addr)
-{
- if (vpid == 0)
- return true;
-
- if (cpu_has_vmx_invvpid_individual_addr()) {
- __invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR, vpid, addr);
- return true;
- }
-
- return false;
-}
-
-static inline void vpid_sync_vcpu_single(int vpid)
-{
- if (vpid == 0)
- return;
-
- if (cpu_has_vmx_invvpid_single())
- __invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vpid, 0);
-}
-
-static inline void vpid_sync_vcpu_global(void)
-{
- if (cpu_has_vmx_invvpid_global())
- __invvpid(VMX_VPID_EXTENT_ALL_CONTEXT, 0, 0);
-}
-
-static inline void vpid_sync_context(int vpid)
-{
- if (cpu_has_vmx_invvpid_single())
- vpid_sync_vcpu_single(vpid);
- else
- vpid_sync_vcpu_global();
-}
-
-static inline void ept_sync_global(void)
-{
- __invept(VMX_EPT_EXTENT_GLOBAL, 0, 0);
-}
-
-static inline void ept_sync_context(u64 eptp)
-{
- if (cpu_has_vmx_invept_context())
- __invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
- else
- ept_sync_global();
-}
-
-static __always_inline void vmcs_check16(unsigned long field)
-{
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2000,
- "16-bit accessor invalid for 64-bit field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
- "16-bit accessor invalid for 64-bit high field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
- "16-bit accessor invalid for 32-bit high field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
- "16-bit accessor invalid for natural width field");
-}
-
-static __always_inline void vmcs_check32(unsigned long field)
-{
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
- "32-bit accessor invalid for 16-bit field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
- "32-bit accessor invalid for natural width field");
-}
-
-static __always_inline void vmcs_check64(unsigned long field)
-{
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
- "64-bit accessor invalid for 16-bit field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
- "64-bit accessor invalid for 64-bit high field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
- "64-bit accessor invalid for 32-bit field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
- "64-bit accessor invalid for natural width field");
-}
-
-static __always_inline void vmcs_checkl(unsigned long field)
-{
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
- "Natural width accessor invalid for 16-bit field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2000,
- "Natural width accessor invalid for 64-bit field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
- "Natural width accessor invalid for 64-bit high field");
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
- "Natural width accessor invalid for 32-bit field");
-}
-
-static __always_inline unsigned long __vmcs_readl(unsigned long field)
-{
- unsigned long value;
-
- asm volatile (__ex_clear(ASM_VMX_VMREAD_RDX_RAX, "%0")
- : "=a"(value) : "d"(field) : "cc");
- return value;
-}
-
-static __always_inline u16 vmcs_read16(unsigned long field)
-{
- vmcs_check16(field);
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_read16(field);
- return __vmcs_readl(field);
-}
-
-static __always_inline u32 vmcs_read32(unsigned long field)
-{
- vmcs_check32(field);
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_read32(field);
- return __vmcs_readl(field);
-}
-
-static __always_inline u64 vmcs_read64(unsigned long field)
-{
- vmcs_check64(field);
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_read64(field);
-#ifdef CONFIG_X86_64
- return __vmcs_readl(field);
-#else
- return __vmcs_readl(field) | ((u64)__vmcs_readl(field+1) << 32);
-#endif
-}
-
-static __always_inline unsigned long vmcs_readl(unsigned long field)
-{
- vmcs_checkl(field);
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_read64(field);
- return __vmcs_readl(field);
-}
-
-static noinline void vmwrite_error(unsigned long field, unsigned long value)
-{
- printk(KERN_ERR "vmwrite error: reg %lx value %lx (err %d)\n",
- field, value, vmcs_read32(VM_INSTRUCTION_ERROR));
- dump_stack();
-}
-
-static __always_inline void __vmcs_writel(unsigned long field, unsigned long value)
-{
- bool error;
-
- asm volatile (__ex(ASM_VMX_VMWRITE_RAX_RDX) CC_SET(na)
- : CC_OUT(na) (error) : "a"(value), "d"(field));
- if (unlikely(error))
- vmwrite_error(field, value);
-}
-
-static __always_inline void vmcs_write16(unsigned long field, u16 value)
-{
- vmcs_check16(field);
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_write16(field, value);
-
- __vmcs_writel(field, value);
-}
-
-static __always_inline void vmcs_write32(unsigned long field, u32 value)
-{
- vmcs_check32(field);
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_write32(field, value);
-
- __vmcs_writel(field, value);
-}
-
-static __always_inline void vmcs_write64(unsigned long field, u64 value)
-{
- vmcs_check64(field);
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_write64(field, value);
-
- __vmcs_writel(field, value);
-#ifndef CONFIG_X86_64
- asm volatile ("");
- __vmcs_writel(field+1, value >> 32);
-#endif
-}
-
-static __always_inline void vmcs_writel(unsigned long field, unsigned long value)
-{
- vmcs_checkl(field);
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_write64(field, value);
-
- __vmcs_writel(field, value);
-}
-
-static __always_inline void vmcs_clear_bits(unsigned long field, u32 mask)
-{
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
- "vmcs_clear_bits does not support 64-bit fields");
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_write32(field, evmcs_read32(field) & ~mask);
-
- __vmcs_writel(field, __vmcs_readl(field) & ~mask);
-}
-
-static __always_inline void vmcs_set_bits(unsigned long field, u32 mask)
-{
- BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
- "vmcs_set_bits does not support 64-bit fields");
- if (static_branch_unlikely(&enable_evmcs))
- return evmcs_write32(field, evmcs_read32(field) | mask);
-
- __vmcs_writel(field, __vmcs_readl(field) | mask);
-}
-
-static inline void vm_entry_controls_reset_shadow(struct vcpu_vmx *vmx)
-{
- vmx->vm_entry_controls_shadow = vmcs_read32(VM_ENTRY_CONTROLS);
-}
-
-static inline void vm_entry_controls_init(struct vcpu_vmx *vmx, u32 val)
-{
- vmcs_write32(VM_ENTRY_CONTROLS, val);
- vmx->vm_entry_controls_shadow = val;
-}
-
-static inline void vm_entry_controls_set(struct vcpu_vmx *vmx, u32 val)
-{
- if (vmx->vm_entry_controls_shadow != val)
- vm_entry_controls_init(vmx, val);
-}
-
-static inline u32 vm_entry_controls_get(struct vcpu_vmx *vmx)
-{
- return vmx->vm_entry_controls_shadow;
-}
-
-
-static inline void vm_entry_controls_setbit(struct vcpu_vmx *vmx, u32 val)
-{
- vm_entry_controls_set(vmx, vm_entry_controls_get(vmx) | val);
-}
-
-static inline void vm_entry_controls_clearbit(struct vcpu_vmx *vmx, u32 val)
-{
- vm_entry_controls_set(vmx, vm_entry_controls_get(vmx) & ~val);
-}
-
-static inline void vm_exit_controls_reset_shadow(struct vcpu_vmx *vmx)
-{
- vmx->vm_exit_controls_shadow = vmcs_read32(VM_EXIT_CONTROLS);
-}
-
-static inline void vm_exit_controls_init(struct vcpu_vmx *vmx, u32 val)
-{
- vmcs_write32(VM_EXIT_CONTROLS, val);
- vmx->vm_exit_controls_shadow = val;
-}
-
-static inline void vm_exit_controls_set(struct vcpu_vmx *vmx, u32 val)
-{
- if (vmx->vm_exit_controls_shadow != val)
- vm_exit_controls_init(vmx, val);
-}
-
-static inline u32 vm_exit_controls_get(struct vcpu_vmx *vmx)
-{
- return vmx->vm_exit_controls_shadow;
-}
-
-
-static inline void vm_exit_controls_setbit(struct vcpu_vmx *vmx, u32 val)
-{
- vm_exit_controls_set(vmx, vm_exit_controls_get(vmx) | val);
-}
-
-static inline void vm_exit_controls_clearbit(struct vcpu_vmx *vmx, u32 val)
-{
- vm_exit_controls_set(vmx, vm_exit_controls_get(vmx) & ~val);
-}
-
-static void vmx_segment_cache_clear(struct vcpu_vmx *vmx)
-{
- vmx->segment_cache.bitmask = 0;
-}
-
-static bool vmx_segment_cache_test_set(struct vcpu_vmx *vmx, unsigned seg,
- unsigned field)
-{
- bool ret;
- u32 mask = 1 << (seg * SEG_FIELD_NR + field);
-
- if (!(vmx->vcpu.arch.regs_avail & (1 << VCPU_EXREG_SEGMENTS))) {
- vmx->vcpu.arch.regs_avail |= (1 << VCPU_EXREG_SEGMENTS);
- vmx->segment_cache.bitmask = 0;
- }
- ret = vmx->segment_cache.bitmask & mask;
- vmx->segment_cache.bitmask |= mask;
- return ret;
-}
-
-static u16 vmx_read_guest_seg_selector(struct vcpu_vmx *vmx, unsigned seg)
-{
- u16 *p = &vmx->segment_cache.seg[seg].selector;
-
- if (!vmx_segment_cache_test_set(vmx, seg, SEG_FIELD_SEL))
- *p = vmcs_read16(kvm_vmx_segment_fields[seg].selector);
- return *p;
-}
-
-static ulong vmx_read_guest_seg_base(struct vcpu_vmx *vmx, unsigned seg)
-{
- ulong *p = &vmx->segment_cache.seg[seg].base;
-
- if (!vmx_segment_cache_test_set(vmx, seg, SEG_FIELD_BASE))
- *p = vmcs_readl(kvm_vmx_segment_fields[seg].base);
- return *p;
-}
-
-static u32 vmx_read_guest_seg_limit(struct vcpu_vmx *vmx, unsigned seg)
-{
- u32 *p = &vmx->segment_cache.seg[seg].limit;
-
- if (!vmx_segment_cache_test_set(vmx, seg, SEG_FIELD_LIMIT))
- *p = vmcs_read32(kvm_vmx_segment_fields[seg].limit);
- return *p;
-}
-
-static u32 vmx_read_guest_seg_ar(struct vcpu_vmx *vmx, unsigned seg)
-{
- u32 *p = &vmx->segment_cache.seg[seg].ar;
-
- if (!vmx_segment_cache_test_set(vmx, seg, SEG_FIELD_AR))
- *p = vmcs_read32(kvm_vmx_segment_fields[seg].ar_bytes);
- return *p;
-}
-
-static void update_exception_bitmap(struct kvm_vcpu *vcpu)
-{
- u32 eb;
-
- eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
- (1u << DB_VECTOR) | (1u << AC_VECTOR);
- /*
- * Guest access to VMware backdoor ports could legitimately
- * trigger #GP because of TSS I/O permission bitmap.
- * We intercept those #GP and allow access to them anyway
- * as VMware does.
- */
- if (enable_vmware_backdoor)
- eb |= (1u << GP_VECTOR);
- if ((vcpu->guest_debug &
- (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
- (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP))
- eb |= 1u << BP_VECTOR;
- if (to_vmx(vcpu)->rmode.vm86_active)
- eb = ~0;
- if (enable_ept)
- eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
-
- /* When we are running a nested L2 guest and L1 specified for it a
- * certain exception bitmap, we must trap the same exceptions and pass
- * them to L1. When running L2, we will only handle the exceptions
- * specified above if L1 did not want them.
- */
- if (is_guest_mode(vcpu))
- eb |= get_vmcs12(vcpu)->exception_bitmap;
-
- vmcs_write32(EXCEPTION_BITMAP, eb);
-}
-
-/*
- * Check if MSR is intercepted for currently loaded MSR bitmap.
- */
-static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr)
-{
- unsigned long *msr_bitmap;
- int f = sizeof(unsigned long);
-
- if (!cpu_has_vmx_msr_bitmap())
- return true;
-
- msr_bitmap = to_vmx(vcpu)->loaded_vmcs->msr_bitmap;
-
- if (msr <= 0x1fff) {
- return !!test_bit(msr, msr_bitmap + 0x800 / f);
- } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
- msr &= 0x1fff;
- return !!test_bit(msr, msr_bitmap + 0xc00 / f);
- }
-
- return true;
-}
-
-/*
- * Check if MSR is intercepted for L01 MSR bitmap.
- */
-static bool msr_write_intercepted_l01(struct kvm_vcpu *vcpu, u32 msr)
-{
- unsigned long *msr_bitmap;
- int f = sizeof(unsigned long);
-
- if (!cpu_has_vmx_msr_bitmap())
- return true;
-
- msr_bitmap = to_vmx(vcpu)->vmcs01.msr_bitmap;
-
- if (msr <= 0x1fff) {
- return !!test_bit(msr, msr_bitmap + 0x800 / f);
- } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
- msr &= 0x1fff;
- return !!test_bit(msr, msr_bitmap + 0xc00 / f);
- }
-
- return true;
-}
-
-static void clear_atomic_switch_msr_special(struct vcpu_vmx *vmx,
- unsigned long entry, unsigned long exit)
-{
- vm_entry_controls_clearbit(vmx, entry);
- vm_exit_controls_clearbit(vmx, exit);
-}
-
-static int find_msr(struct vmx_msrs *m, unsigned int msr)
-{
- unsigned int i;
-
- for (i = 0; i < m->nr; ++i) {
- if (m->val[i].index == msr)
- return i;
- }
- return -ENOENT;
-}
-
-static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
-{
- int i;
- struct msr_autoload *m = &vmx->msr_autoload;
-
- switch (msr) {
- case MSR_EFER:
- if (cpu_has_load_ia32_efer) {
- clear_atomic_switch_msr_special(vmx,
- VM_ENTRY_LOAD_IA32_EFER,
- VM_EXIT_LOAD_IA32_EFER);
- return;
- }
- break;
- case MSR_CORE_PERF_GLOBAL_CTRL:
- if (cpu_has_load_perf_global_ctrl) {
- clear_atomic_switch_msr_special(vmx,
- VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
- VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
- return;
- }
- break;
- }
- i = find_msr(&m->guest, msr);
- if (i < 0)
- goto skip_guest;
- --m->guest.nr;
- m->guest.val[i] = m->guest.val[m->guest.nr];
- vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr);
-
-skip_guest:
- i = find_msr(&m->host, msr);
- if (i < 0)
- return;
-
- --m->host.nr;
- m->host.val[i] = m->host.val[m->host.nr];
- vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr);
-}
-
-static void add_atomic_switch_msr_special(struct vcpu_vmx *vmx,
- unsigned long entry, unsigned long exit,
- unsigned long guest_val_vmcs, unsigned long host_val_vmcs,
- u64 guest_val, u64 host_val)
-{
- vmcs_write64(guest_val_vmcs, guest_val);
- vmcs_write64(host_val_vmcs, host_val);
- vm_entry_controls_setbit(vmx, entry);
- vm_exit_controls_setbit(vmx, exit);
-}
-
-static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
- u64 guest_val, u64 host_val, bool entry_only)
-{
- int i, j = 0;
- struct msr_autoload *m = &vmx->msr_autoload;
-
- switch (msr) {
- case MSR_EFER:
- if (cpu_has_load_ia32_efer) {
- add_atomic_switch_msr_special(vmx,
- VM_ENTRY_LOAD_IA32_EFER,
- VM_EXIT_LOAD_IA32_EFER,
- GUEST_IA32_EFER,
- HOST_IA32_EFER,
- guest_val, host_val);
- return;
- }
- break;
- case MSR_CORE_PERF_GLOBAL_CTRL:
- if (cpu_has_load_perf_global_ctrl) {
- add_atomic_switch_msr_special(vmx,
- VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
- VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL,
- GUEST_IA32_PERF_GLOBAL_CTRL,
- HOST_IA32_PERF_GLOBAL_CTRL,
- guest_val, host_val);
- return;
- }
- break;
- case MSR_IA32_PEBS_ENABLE:
- /* PEBS needs a quiescent period after being disabled (to write
- * a record). Disabling PEBS through VMX MSR swapping doesn't
- * provide that period, so a CPU could write host's record into
- * guest's memory.
- */
- wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
- }
-
- i = find_msr(&m->guest, msr);
- if (!entry_only)
- j = find_msr(&m->host, msr);
-
- if ((i < 0 && m->guest.nr == NR_AUTOLOAD_MSRS) ||
- (j < 0 && m->host.nr == NR_AUTOLOAD_MSRS)) {
- printk_once(KERN_WARNING "Not enough msr switch entries. "
- "Can't add msr %x\n", msr);
- return;
- }
- if (i < 0) {
- i = m->guest.nr++;
- vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr);
- }
- m->guest.val[i].index = msr;
- m->guest.val[i].value = guest_val;
-
- if (entry_only)
- return;
-
- if (j < 0) {
- j = m->host.nr++;
- vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr);
- }
- m->host.val[j].index = msr;
- m->host.val[j].value = host_val;
-}
-
-static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
-{
- u64 guest_efer = vmx->vcpu.arch.efer;
- u64 ignore_bits = 0;
-
- /* Shadow paging assumes NX to be available. */
- if (!enable_ept)
- guest_efer |= EFER_NX;
-
- /*
- * LMA and LME handled by hardware; SCE meaningless outside long mode.
- */
- ignore_bits |= EFER_SCE;
-#ifdef CONFIG_X86_64
- ignore_bits |= EFER_LMA | EFER_LME;
- /* SCE is meaningful only in long mode on Intel */
- if (guest_efer & EFER_LMA)
- ignore_bits &= ~(u64)EFER_SCE;
-#endif
-
- clear_atomic_switch_msr(vmx, MSR_EFER);
-
- /*
- * On EPT, we can't emulate NX, so we must switch EFER atomically.
- * On CPUs that support "load IA32_EFER", always switch EFER
- * atomically, since it's faster than switching it manually.
- */
- if (cpu_has_load_ia32_efer ||
- (enable_ept && ((vmx->vcpu.arch.efer ^ host_efer) & EFER_NX))) {
- if (!(guest_efer & EFER_LMA))
- guest_efer &= ~EFER_LME;
- if (guest_efer != host_efer)
- add_atomic_switch_msr(vmx, MSR_EFER,
- guest_efer, host_efer, false);
- return false;
- } else {
- guest_efer &= ~ignore_bits;
- guest_efer |= host_efer & ignore_bits;
-
- vmx->guest_msrs[efer_offset].data = guest_efer;
- vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
-
- return true;
- }
-}
-
-#ifdef CONFIG_X86_32
-/*
- * On 32-bit kernels, VM exits still load the FS and GS bases from the
- * VMCS rather than the segment table. KVM uses this helper to figure
- * out the current bases to poke them into the VMCS before entry.
- */
-static unsigned long segment_base(u16 selector)
-{
- struct desc_struct *table;
- unsigned long v;
-
- if (!(selector & ~SEGMENT_RPL_MASK))
- return 0;
-
- table = get_current_gdt_ro();
-
- if ((selector & SEGMENT_TI_MASK) == SEGMENT_LDT) {
- u16 ldt_selector = kvm_read_ldt();
-
- if (!(ldt_selector & ~SEGMENT_RPL_MASK))
- return 0;
-
- table = (struct desc_struct *)segment_base(ldt_selector);
- }
- v = get_desc_base(&table[selector >> 3]);
- return v;
-}
-#endif
-
-static void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct vmcs_host_state *host_state;
-#ifdef CONFIG_X86_64
- int cpu = raw_smp_processor_id();
-#endif
- unsigned long fs_base, gs_base;
- u16 fs_sel, gs_sel;
- int i;
-
- vmx->req_immediate_exit = false;
-
- /*
- * Note that guest MSRs to be saved/restored can also be changed
- * when guest state is loaded. This happens when guest transitions
- * to/from long-mode by setting MSR_EFER.LMA.
- */
- if (!vmx->loaded_cpu_state || vmx->guest_msrs_dirty) {
- vmx->guest_msrs_dirty = false;
- for (i = 0; i < vmx->save_nmsrs; ++i)
- kvm_set_shared_msr(vmx->guest_msrs[i].index,
- vmx->guest_msrs[i].data,
- vmx->guest_msrs[i].mask);
-
- }
-
- if (vmx->loaded_cpu_state)
- return;
-
- vmx->loaded_cpu_state = vmx->loaded_vmcs;
- host_state = &vmx->loaded_cpu_state->host_state;
-
- /*
- * Set host fs and gs selectors. Unfortunately, 22.2.3 does not
- * allow segment selectors with cpl > 0 or ti == 1.
- */
- host_state->ldt_sel = kvm_read_ldt();
-
-#ifdef CONFIG_X86_64
- savesegment(ds, host_state->ds_sel);
- savesegment(es, host_state->es_sel);
-
- gs_base = cpu_kernelmode_gs_base(cpu);
- if (likely(is_64bit_mm(current->mm))) {
- save_fsgs_for_kvm();
- fs_sel = current->thread.fsindex;
- gs_sel = current->thread.gsindex;
- fs_base = current->thread.fsbase;
- vmx->msr_host_kernel_gs_base = current->thread.gsbase;
- } else {
- savesegment(fs, fs_sel);
- savesegment(gs, gs_sel);
- fs_base = read_msr(MSR_FS_BASE);
- vmx->msr_host_kernel_gs_base = read_msr(MSR_KERNEL_GS_BASE);
- }
-
- wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
-#else
- savesegment(fs, fs_sel);
- savesegment(gs, gs_sel);
- fs_base = segment_base(fs_sel);
- gs_base = segment_base(gs_sel);
-#endif
-
- if (unlikely(fs_sel != host_state->fs_sel)) {
- if (!(fs_sel & 7))
- vmcs_write16(HOST_FS_SELECTOR, fs_sel);
- else
- vmcs_write16(HOST_FS_SELECTOR, 0);
- host_state->fs_sel = fs_sel;
- }
- if (unlikely(gs_sel != host_state->gs_sel)) {
- if (!(gs_sel & 7))
- vmcs_write16(HOST_GS_SELECTOR, gs_sel);
- else
- vmcs_write16(HOST_GS_SELECTOR, 0);
- host_state->gs_sel = gs_sel;
- }
- if (unlikely(fs_base != host_state->fs_base)) {
- vmcs_writel(HOST_FS_BASE, fs_base);
- host_state->fs_base = fs_base;
- }
- if (unlikely(gs_base != host_state->gs_base)) {
- vmcs_writel(HOST_GS_BASE, gs_base);
- host_state->gs_base = gs_base;
- }
-}
-
-static void vmx_prepare_switch_to_host(struct vcpu_vmx *vmx)
-{
- struct vmcs_host_state *host_state;
-
- if (!vmx->loaded_cpu_state)
- return;
-
- WARN_ON_ONCE(vmx->loaded_cpu_state != vmx->loaded_vmcs);
- host_state = &vmx->loaded_cpu_state->host_state;
-
- ++vmx->vcpu.stat.host_state_reload;
- vmx->loaded_cpu_state = NULL;
-
-#ifdef CONFIG_X86_64
- rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
-#endif
- if (host_state->ldt_sel || (host_state->gs_sel & 7)) {
- kvm_load_ldt(host_state->ldt_sel);
-#ifdef CONFIG_X86_64
- load_gs_index(host_state->gs_sel);
-#else
- loadsegment(gs, host_state->gs_sel);
-#endif
- }
- if (host_state->fs_sel & 7)
- loadsegment(fs, host_state->fs_sel);
-#ifdef CONFIG_X86_64
- if (unlikely(host_state->ds_sel | host_state->es_sel)) {
- loadsegment(ds, host_state->ds_sel);
- loadsegment(es, host_state->es_sel);
- }
-#endif
- invalidate_tss_limit();
-#ifdef CONFIG_X86_64
- wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
-#endif
- load_fixmap_gdt(raw_smp_processor_id());
-}
-
-#ifdef CONFIG_X86_64
-static u64 vmx_read_guest_kernel_gs_base(struct vcpu_vmx *vmx)
-{
- preempt_disable();
- if (vmx->loaded_cpu_state)
- rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
- preempt_enable();
- return vmx->msr_guest_kernel_gs_base;
-}
-
-static void vmx_write_guest_kernel_gs_base(struct vcpu_vmx *vmx, u64 data)
-{
- preempt_disable();
- if (vmx->loaded_cpu_state)
- wrmsrl(MSR_KERNEL_GS_BASE, data);
- preempt_enable();
- vmx->msr_guest_kernel_gs_base = data;
-}
-#endif
-
-static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
-{
- struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
- struct pi_desc old, new;
- unsigned int dest;
-
- /*
- * In case of hot-plug or hot-unplug, we may have to undo
- * vmx_vcpu_pi_put even if there is no assigned device. And we
- * always keep PI.NDST up to date for simplicity: it makes the
- * code easier, and CPU migration is not a fast path.
- */
- if (!pi_test_sn(pi_desc) && vcpu->cpu == cpu)
- return;
-
- /*
- * First handle the simple case where no cmpxchg is necessary; just
- * allow posting non-urgent interrupts.
- *
- * If the 'nv' field is POSTED_INTR_WAKEUP_VECTOR, do not change
- * PI.NDST: pi_post_block will do it for us and the wakeup_handler
- * expects the VCPU to be on the blocked_vcpu_list that matches
- * PI.NDST.
- */
- if (pi_desc->nv == POSTED_INTR_WAKEUP_VECTOR ||
- vcpu->cpu == cpu) {
- pi_clear_sn(pi_desc);
- return;
- }
-
- /* The full case. */
- do {
- old.control = new.control = pi_desc->control;
-
- dest = cpu_physical_id(cpu);
-
- if (x2apic_enabled())
- new.ndst = dest;
- else
- new.ndst = (dest << 8) & 0xFF00;
-
- new.sn = 0;
- } while (cmpxchg64(&pi_desc->control, old.control,
- new.control) != old.control);
-}
-
-static void decache_tsc_multiplier(struct vcpu_vmx *vmx)
-{
- vmx->current_tsc_ratio = vmx->vcpu.arch.tsc_scaling_ratio;
- vmcs_write64(TSC_MULTIPLIER, vmx->current_tsc_ratio);
-}
-
-/*
- * Switches to specified vcpu, until a matching vcpu_put(), but assumes
- * vcpu mutex is already taken.
- */
-static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- bool already_loaded = vmx->loaded_vmcs->cpu == cpu;
-
- if (!already_loaded) {
- loaded_vmcs_clear(vmx->loaded_vmcs);
- local_irq_disable();
-
- /*
- * Ensure loaded_vmcs->cpu is read before adding loaded_vmcs to
- * this cpu's percpu list, otherwise it may not yet be deleted
- * from its previous cpu's percpu list. Pairs with the
- * smb_wmb() in __loaded_vmcs_clear().
- */
- smp_rmb();
-
- list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link,
- &per_cpu(loaded_vmcss_on_cpu, cpu));
- local_irq_enable();
- }
-
- if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) {
- per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
- vmcs_load(vmx->loaded_vmcs->vmcs);
- indirect_branch_prediction_barrier();
- }
-
- if (!already_loaded) {
- void *gdt = get_current_gdt_ro();
- unsigned long sysenter_esp;
-
- kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
-
- /*
- * Linux uses per-cpu TSS and GDT, so set these when switching
- * processors. See 22.2.4.
- */
- vmcs_writel(HOST_TR_BASE,
- (unsigned long)&get_cpu_entry_area(cpu)->tss.x86_tss);
- vmcs_writel(HOST_GDTR_BASE, (unsigned long)gdt); /* 22.2.4 */
-
- /*
- * VM exits change the host TR limit to 0x67 after a VM
- * exit. This is okay, since 0x67 covers everything except
- * the IO bitmap and have have code to handle the IO bitmap
- * being lost after a VM exit.
- */
- BUILD_BUG_ON(IO_BITMAP_OFFSET - 1 != 0x67);
-
- rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
- vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
-
- vmx->loaded_vmcs->cpu = cpu;
- }
-
- /* Setup TSC multiplier */
- if (kvm_has_tsc_control &&
- vmx->current_tsc_ratio != vcpu->arch.tsc_scaling_ratio)
- decache_tsc_multiplier(vmx);
-
- vmx_vcpu_pi_load(vcpu, cpu);
- vmx->host_pkru = read_pkru();
- vmx->host_debugctlmsr = get_debugctlmsr();
-}
-
-static void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu)
-{
- struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
-
- if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
- !irq_remapping_cap(IRQ_POSTING_CAP) ||
- !kvm_vcpu_apicv_active(vcpu))
- return;
-
- /* Set SN when the vCPU is preempted */
- if (vcpu->preempted)
- pi_set_sn(pi_desc);
-}
-
-static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
-{
- vmx_vcpu_pi_put(vcpu);
-
- vmx_prepare_switch_to_host(to_vmx(vcpu));
-}
-
-static bool emulation_required(struct kvm_vcpu *vcpu)
-{
- return emulate_invalid_guest_state && !guest_state_valid(vcpu);
-}
-
-static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu);
-
-/*
- * Return the cr0 value that a nested guest would read. This is a combination
- * of the real cr0 used to run the guest (guest_cr0), and the bits shadowed by
- * its hypervisor (cr0_read_shadow).
- */
-static inline unsigned long nested_read_cr0(struct vmcs12 *fields)
-{
- return (fields->guest_cr0 & ~fields->cr0_guest_host_mask) |
- (fields->cr0_read_shadow & fields->cr0_guest_host_mask);
-}
-static inline unsigned long nested_read_cr4(struct vmcs12 *fields)
-{
- return (fields->guest_cr4 & ~fields->cr4_guest_host_mask) |
- (fields->cr4_read_shadow & fields->cr4_guest_host_mask);
-}
-
-static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
-{
- unsigned long rflags, save_rflags;
-
- if (!test_bit(VCPU_EXREG_RFLAGS, (ulong *)&vcpu->arch.regs_avail)) {
- __set_bit(VCPU_EXREG_RFLAGS, (ulong *)&vcpu->arch.regs_avail);
- rflags = vmcs_readl(GUEST_RFLAGS);
- if (to_vmx(vcpu)->rmode.vm86_active) {
- rflags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
- save_rflags = to_vmx(vcpu)->rmode.save_rflags;
- rflags |= save_rflags & ~RMODE_GUEST_OWNED_EFLAGS_BITS;
- }
- to_vmx(vcpu)->rflags = rflags;
- }
- return to_vmx(vcpu)->rflags;
-}
-
-static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
-{
- unsigned long old_rflags = vmx_get_rflags(vcpu);
-
- __set_bit(VCPU_EXREG_RFLAGS, (ulong *)&vcpu->arch.regs_avail);
- to_vmx(vcpu)->rflags = rflags;
- if (to_vmx(vcpu)->rmode.vm86_active) {
- to_vmx(vcpu)->rmode.save_rflags = rflags;
- rflags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM;
- }
- vmcs_writel(GUEST_RFLAGS, rflags);
-
- if ((old_rflags ^ to_vmx(vcpu)->rflags) & X86_EFLAGS_VM)
- to_vmx(vcpu)->emulation_required = emulation_required(vcpu);
-}
-
-static u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu)
-{
- u32 interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
- int ret = 0;
-
- if (interruptibility & GUEST_INTR_STATE_STI)
- ret |= KVM_X86_SHADOW_INT_STI;
- if (interruptibility & GUEST_INTR_STATE_MOV_SS)
- ret |= KVM_X86_SHADOW_INT_MOV_SS;
-
- return ret;
-}
-
-static void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
-{
- u32 interruptibility_old = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
- u32 interruptibility = interruptibility_old;
-
- interruptibility &= ~(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS);
-
- if (mask & KVM_X86_SHADOW_INT_MOV_SS)
- interruptibility |= GUEST_INTR_STATE_MOV_SS;
- else if (mask & KVM_X86_SHADOW_INT_STI)
- interruptibility |= GUEST_INTR_STATE_STI;
-
- if ((interruptibility != interruptibility_old))
- vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, interruptibility);
-}
-
-static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
-{
- unsigned long rip;
-
- rip = kvm_rip_read(vcpu);
- rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
- kvm_rip_write(vcpu, rip);
-
- /* skipping an emulated instruction also counts */
- vmx_set_interrupt_shadow(vcpu, 0);
-}
-
-static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu,
- unsigned long exit_qual)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- unsigned int nr = vcpu->arch.exception.nr;
- u32 intr_info = nr | INTR_INFO_VALID_MASK;
-
- if (vcpu->arch.exception.has_error_code) {
- vmcs12->vm_exit_intr_error_code = vcpu->arch.exception.error_code;
- intr_info |= INTR_INFO_DELIVER_CODE_MASK;
- }
-
- if (kvm_exception_is_soft(nr))
- intr_info |= INTR_TYPE_SOFT_EXCEPTION;
- else
- intr_info |= INTR_TYPE_HARD_EXCEPTION;
-
- if (!(vmcs12->idt_vectoring_info_field & VECTORING_INFO_VALID_MASK) &&
- vmx_get_nmi_mask(vcpu))
- intr_info |= INTR_INFO_UNBLOCK_NMI;
-
- nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, intr_info, exit_qual);
-}
-
-/*
- * KVM wants to inject page-faults which it got to the guest. This function
- * checks whether in a nested guest, we need to inject them to L1 or L2.
- */
-static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned long *exit_qual)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- unsigned int nr = vcpu->arch.exception.nr;
-
- if (nr == PF_VECTOR) {
- if (vcpu->arch.exception.nested_apf) {
- *exit_qual = vcpu->arch.apf.nested_apf_token;
- return 1;
- }
- /*
- * FIXME: we must not write CR2 when L1 intercepts an L2 #PF exception.
- * The fix is to add the ancillary datum (CR2 or DR6) to structs
- * kvm_queued_exception and kvm_vcpu_events, so that CR2 and DR6
- * can be written only when inject_pending_event runs. This should be
- * conditional on a new capability---if the capability is disabled,
- * kvm_multiple_exception would write the ancillary information to
- * CR2 or DR6, for backwards ABI-compatibility.
- */
- if (nested_vmx_is_page_fault_vmexit(vmcs12,
- vcpu->arch.exception.error_code)) {
- *exit_qual = vcpu->arch.cr2;
- return 1;
- }
- } else {
- if (vmcs12->exception_bitmap & (1u << nr)) {
- if (nr == DB_VECTOR) {
- *exit_qual = vcpu->arch.dr6;
- *exit_qual &= ~(DR6_FIXED_1 | DR6_BT);
- *exit_qual ^= DR6_RTM;
- } else {
- *exit_qual = 0;
- }
- return 1;
- }
- }
-
- return 0;
-}
-
-static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
-{
- /*
- * Ensure that we clear the HLT state in the VMCS. We don't need to
- * explicitly skip the instruction because if the HLT state is set,
- * then the instruction is already executing and RIP has already been
- * advanced.
- */
- if (kvm_hlt_in_guest(vcpu->kvm) &&
- vmcs_read32(GUEST_ACTIVITY_STATE) == GUEST_ACTIVITY_HLT)
- vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
-}
-
-static void vmx_queue_exception(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- unsigned nr = vcpu->arch.exception.nr;
- bool has_error_code = vcpu->arch.exception.has_error_code;
- u32 error_code = vcpu->arch.exception.error_code;
- u32 intr_info = nr | INTR_INFO_VALID_MASK;
-
- if (has_error_code) {
- vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
- intr_info |= INTR_INFO_DELIVER_CODE_MASK;
- }
-
- if (vmx->rmode.vm86_active) {
- int inc_eip = 0;
- if (kvm_exception_is_soft(nr))
- inc_eip = vcpu->arch.event_exit_inst_len;
- if (kvm_inject_realmode_interrupt(vcpu, nr, inc_eip) != EMULATE_DONE)
- kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
- return;
- }
-
- WARN_ON_ONCE(vmx->emulation_required);
-
- if (kvm_exception_is_soft(nr)) {
- vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
- vmx->vcpu.arch.event_exit_inst_len);
- intr_info |= INTR_TYPE_SOFT_EXCEPTION;
- } else
- intr_info |= INTR_TYPE_HARD_EXCEPTION;
-
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
-
- vmx_clear_hlt(vcpu);
-}
-
-static bool vmx_rdtscp_supported(void)
-{
- return cpu_has_vmx_rdtscp();
-}
-
-static bool vmx_invpcid_supported(void)
-{
- return cpu_has_vmx_invpcid();
-}
-
-/*
- * Swap MSR entry in host/guest MSR entry array.
- */
-static void move_msr_up(struct vcpu_vmx *vmx, int from, int to)
-{
- struct shared_msr_entry tmp;
-
- tmp = vmx->guest_msrs[to];
- vmx->guest_msrs[to] = vmx->guest_msrs[from];
- vmx->guest_msrs[from] = tmp;
-}
-
-/*
- * Set up the vmcs to automatically save and restore system
- * msrs. Don't touch the 64-bit msrs if the guest is in legacy
- * mode, as fiddling with msrs is very expensive.
- */
-static void setup_msrs(struct vcpu_vmx *vmx)
-{
- int save_nmsrs, index;
-
- save_nmsrs = 0;
-#ifdef CONFIG_X86_64
- if (is_long_mode(&vmx->vcpu)) {
- index = __find_msr_index(vmx, MSR_SYSCALL_MASK);
- if (index >= 0)
- move_msr_up(vmx, index, save_nmsrs++);
- index = __find_msr_index(vmx, MSR_LSTAR);
- if (index >= 0)
- move_msr_up(vmx, index, save_nmsrs++);
- index = __find_msr_index(vmx, MSR_CSTAR);
- if (index >= 0)
- move_msr_up(vmx, index, save_nmsrs++);
- /*
- * MSR_STAR is only needed on long mode guests, and only
- * if efer.sce is enabled.
- */
- index = __find_msr_index(vmx, MSR_STAR);
- if ((index >= 0) && (vmx->vcpu.arch.efer & EFER_SCE))
- move_msr_up(vmx, index, save_nmsrs++);
- }
-#endif
- index = __find_msr_index(vmx, MSR_EFER);
- if (index >= 0 && update_transition_efer(vmx, index))
- move_msr_up(vmx, index, save_nmsrs++);
- index = __find_msr_index(vmx, MSR_TSC_AUX);
- if (index >= 0 && guest_cpuid_has(&vmx->vcpu, X86_FEATURE_RDTSCP))
- move_msr_up(vmx, index, save_nmsrs++);
-
- vmx->save_nmsrs = save_nmsrs;
- vmx->guest_msrs_dirty = true;
-
- if (cpu_has_vmx_msr_bitmap())
- vmx_update_msr_bitmap(&vmx->vcpu);
-}
-
-static u64 vmx_read_l1_tsc_offset(struct kvm_vcpu *vcpu)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
-
- if (is_guest_mode(vcpu) &&
- (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING))
- return vcpu->arch.tsc_offset - vmcs12->tsc_offset;
-
- return vcpu->arch.tsc_offset;
-}
-
-static u64 vmx_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
-{
- u64 active_offset = offset;
- if (is_guest_mode(vcpu)) {
- /*
- * We're here if L1 chose not to trap WRMSR to TSC. According
- * to the spec, this should set L1's TSC; The offset that L1
- * set for L2 remains unchanged, and still needs to be added
- * to the newly set TSC to get L2's TSC.
- */
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- if (nested_cpu_has(vmcs12, CPU_BASED_USE_TSC_OFFSETING))
- active_offset += vmcs12->tsc_offset;
- } else {
- trace_kvm_write_tsc_offset(vcpu->vcpu_id,
- vmcs_read64(TSC_OFFSET), offset);
- }
-
- vmcs_write64(TSC_OFFSET, active_offset);
- return active_offset;
-}
-
-/*
- * nested_vmx_allowed() checks whether a guest should be allowed to use VMX
- * instructions and MSRs (i.e., nested VMX). Nested VMX is disabled for
- * all guests if the "nested" module option is off, and can also be disabled
- * for a single guest by disabling its VMX cpuid bit.
- */
-static inline bool nested_vmx_allowed(struct kvm_vcpu *vcpu)
-{
- return nested && guest_cpuid_has(vcpu, X86_FEATURE_VMX);
-}
-
-/*
- * nested_vmx_setup_ctls_msrs() sets up variables containing the values to be
- * returned for the various VMX controls MSRs when nested VMX is enabled.
- * The same values should also be used to verify that vmcs12 control fields are
- * valid during nested entry from L1 to L2.
- * Each of these control msrs has a low and high 32-bit half: A low bit is on
- * if the corresponding bit in the (32-bit) control field *must* be on, and a
- * bit in the high half is on if the corresponding bit in the control field
- * may be on. See also vmx_control_verify().
- */
-static void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, bool apicv)
-{
- if (!nested) {
- memset(msrs, 0, sizeof(*msrs));
- return;
- }
-
- /*
- * Note that as a general rule, the high half of the MSRs (bits in
- * the control fields which may be 1) should be initialized by the
- * intersection of the underlying hardware's MSR (i.e., features which
- * can be supported) and the list of features we want to expose -
- * because they are known to be properly supported in our code.
- * Also, usually, the low half of the MSRs (bits which must be 1) can
- * be set to 0, meaning that L1 may turn off any of these bits. The
- * reason is that if one of these bits is necessary, it will appear
- * in vmcs01 and prepare_vmcs02, when it bitwise-or's the control
- * fields of vmcs01 and vmcs02, will turn these bits off - and
- * nested_vmx_exit_reflected() will not pass related exits to L1.
- * These rules have exceptions below.
- */
-
- /* pin-based controls */
- rdmsr(MSR_IA32_VMX_PINBASED_CTLS,
- msrs->pinbased_ctls_low,
- msrs->pinbased_ctls_high);
- msrs->pinbased_ctls_low |=
- PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
- msrs->pinbased_ctls_high &=
- PIN_BASED_EXT_INTR_MASK |
- PIN_BASED_NMI_EXITING |
- PIN_BASED_VIRTUAL_NMIS |
- (apicv ? PIN_BASED_POSTED_INTR : 0);
- msrs->pinbased_ctls_high |=
- PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
- PIN_BASED_VMX_PREEMPTION_TIMER;
-
- /* exit controls */
- rdmsr(MSR_IA32_VMX_EXIT_CTLS,
- msrs->exit_ctls_low,
- msrs->exit_ctls_high);
- msrs->exit_ctls_low =
- VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
-
- msrs->exit_ctls_high &=
-#ifdef CONFIG_X86_64
- VM_EXIT_HOST_ADDR_SPACE_SIZE |
-#endif
- VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT;
- msrs->exit_ctls_high |=
- VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |
- VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER |
- VM_EXIT_SAVE_VMX_PREEMPTION_TIMER | VM_EXIT_ACK_INTR_ON_EXIT;
-
- /* We support free control of debug control saving. */
- msrs->exit_ctls_low &= ~VM_EXIT_SAVE_DEBUG_CONTROLS;
-
- /* entry controls */
- rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
- msrs->entry_ctls_low,
- msrs->entry_ctls_high);
- msrs->entry_ctls_low =
- VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
- msrs->entry_ctls_high &=
-#ifdef CONFIG_X86_64
- VM_ENTRY_IA32E_MODE |
-#endif
- VM_ENTRY_LOAD_IA32_PAT;
- msrs->entry_ctls_high |=
- (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | VM_ENTRY_LOAD_IA32_EFER);
-
- /* We support free control of debug control loading. */
- msrs->entry_ctls_low &= ~VM_ENTRY_LOAD_DEBUG_CONTROLS;
-
- /* cpu-based controls */
- rdmsr(MSR_IA32_VMX_PROCBASED_CTLS,
- msrs->procbased_ctls_low,
- msrs->procbased_ctls_high);
- msrs->procbased_ctls_low =
- CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
- msrs->procbased_ctls_high &=
- CPU_BASED_VIRTUAL_INTR_PENDING |
- CPU_BASED_VIRTUAL_NMI_PENDING | CPU_BASED_USE_TSC_OFFSETING |
- CPU_BASED_HLT_EXITING | CPU_BASED_INVLPG_EXITING |
- CPU_BASED_MWAIT_EXITING | CPU_BASED_CR3_LOAD_EXITING |
- CPU_BASED_CR3_STORE_EXITING |
-#ifdef CONFIG_X86_64
- CPU_BASED_CR8_LOAD_EXITING | CPU_BASED_CR8_STORE_EXITING |
-#endif
- CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING |
- CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_TRAP_FLAG |
- CPU_BASED_MONITOR_EXITING | CPU_BASED_RDPMC_EXITING |
- CPU_BASED_RDTSC_EXITING | CPU_BASED_PAUSE_EXITING |
- CPU_BASED_TPR_SHADOW | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
- /*
- * We can allow some features even when not supported by the
- * hardware. For example, L1 can specify an MSR bitmap - and we
- * can use it to avoid exits to L1 - even when L0 runs L2
- * without MSR bitmaps.
- */
- msrs->procbased_ctls_high |=
- CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
- CPU_BASED_USE_MSR_BITMAPS;
-
- /* We support free control of CR3 access interception. */
- msrs->procbased_ctls_low &=
- ~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING);
-
- /*
- * secondary cpu-based controls. Do not include those that
- * depend on CPUID bits, they are added later by vmx_cpuid_update.
- */
- if (msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
- rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
- msrs->secondary_ctls_low,
- msrs->secondary_ctls_high);
-
- msrs->secondary_ctls_low = 0;
- msrs->secondary_ctls_high &=
- SECONDARY_EXEC_DESC |
- SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
- SECONDARY_EXEC_APIC_REGISTER_VIRT |
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
- SECONDARY_EXEC_WBINVD_EXITING;
-
- /*
- * We can emulate "VMCS shadowing," even if the hardware
- * doesn't support it.
- */
- msrs->secondary_ctls_high |=
- SECONDARY_EXEC_SHADOW_VMCS;
-
- if (enable_ept) {
- /* nested EPT: emulate EPT also to L1 */
- msrs->secondary_ctls_high |=
- SECONDARY_EXEC_ENABLE_EPT;
- msrs->ept_caps = VMX_EPT_PAGE_WALK_4_BIT |
- VMX_EPTP_WB_BIT | VMX_EPT_INVEPT_BIT;
- if (cpu_has_vmx_ept_execute_only())
- msrs->ept_caps |=
- VMX_EPT_EXECUTE_ONLY_BIT;
- msrs->ept_caps &= vmx_capability.ept;
- msrs->ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT |
- VMX_EPT_EXTENT_CONTEXT_BIT | VMX_EPT_2MB_PAGE_BIT |
- VMX_EPT_1GB_PAGE_BIT;
- if (enable_ept_ad_bits) {
- msrs->secondary_ctls_high |=
- SECONDARY_EXEC_ENABLE_PML;
- msrs->ept_caps |= VMX_EPT_AD_BIT;
- }
- }
-
- if (cpu_has_vmx_vmfunc()) {
- msrs->secondary_ctls_high |=
- SECONDARY_EXEC_ENABLE_VMFUNC;
- /*
- * Advertise EPTP switching unconditionally
- * since we emulate it
- */
- if (enable_ept)
- msrs->vmfunc_controls =
- VMX_VMFUNC_EPTP_SWITCHING;
- }
-
- /*
- * Old versions of KVM use the single-context version without
- * checking for support, so declare that it is supported even
- * though it is treated as global context. The alternative is
- * not failing the single-context invvpid, and it is worse.
- */
- if (enable_vpid) {
- msrs->secondary_ctls_high |=
- SECONDARY_EXEC_ENABLE_VPID;
- msrs->vpid_caps = VMX_VPID_INVVPID_BIT |
- VMX_VPID_EXTENT_SUPPORTED_MASK;
- }
-
- if (enable_unrestricted_guest)
- msrs->secondary_ctls_high |=
- SECONDARY_EXEC_UNRESTRICTED_GUEST;
-
- if (flexpriority_enabled)
- msrs->secondary_ctls_high |=
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
-
- /* miscellaneous data */
- rdmsr(MSR_IA32_VMX_MISC,
- msrs->misc_low,
- msrs->misc_high);
- msrs->misc_low &= VMX_MISC_SAVE_EFER_LMA;
- msrs->misc_low |=
- MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS |
- VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE |
- VMX_MISC_ACTIVITY_HLT;
- msrs->misc_high = 0;
-
- /*
- * This MSR reports some information about VMX support. We
- * should return information about the VMX we emulate for the
- * guest, and the VMCS structure we give it - not about the
- * VMX support of the underlying hardware.
- */
- msrs->basic =
- VMCS12_REVISION |
- VMX_BASIC_TRUE_CTLS |
- ((u64)VMCS12_SIZE << VMX_BASIC_VMCS_SIZE_SHIFT) |
- (VMX_BASIC_MEM_TYPE_WB << VMX_BASIC_MEM_TYPE_SHIFT);
-
- if (cpu_has_vmx_basic_inout())
- msrs->basic |= VMX_BASIC_INOUT;
-
- /*
- * These MSRs specify bits which the guest must keep fixed on
- * while L1 is in VMXON mode (in L1's root mode, or running an L2).
- * We picked the standard core2 setting.
- */
-#define VMXON_CR0_ALWAYSON (X86_CR0_PE | X86_CR0_PG | X86_CR0_NE)
-#define VMXON_CR4_ALWAYSON X86_CR4_VMXE
- msrs->cr0_fixed0 = VMXON_CR0_ALWAYSON;
- msrs->cr4_fixed0 = VMXON_CR4_ALWAYSON;
-
- /* These MSRs specify bits which the guest must keep fixed off. */
- rdmsrl(MSR_IA32_VMX_CR0_FIXED1, msrs->cr0_fixed1);
- rdmsrl(MSR_IA32_VMX_CR4_FIXED1, msrs->cr4_fixed1);
-
- /* highest index: VMX_PREEMPTION_TIMER_VALUE */
- msrs->vmcs_enum = VMCS12_MAX_FIELD_INDEX << 1;
-}
-
-/*
- * if fixed0[i] == 1: val[i] must be 1
- * if fixed1[i] == 0: val[i] must be 0
- */
-static inline bool fixed_bits_valid(u64 val, u64 fixed0, u64 fixed1)
-{
- return ((val & fixed1) | fixed0) == val;
-}
-
-static inline bool vmx_control_verify(u32 control, u32 low, u32 high)
-{
- return fixed_bits_valid(control, low, high);
-}
-
-static inline u64 vmx_control_msr(u32 low, u32 high)
-{
- return low | ((u64)high << 32);
-}
-
-static bool is_bitwise_subset(u64 superset, u64 subset, u64 mask)
-{
- superset &= mask;
- subset &= mask;
-
- return (superset | subset) == superset;
-}
-
-static int vmx_restore_vmx_basic(struct vcpu_vmx *vmx, u64 data)
-{
- const u64 feature_and_reserved =
- /* feature (except bit 48; see below) */
- BIT_ULL(49) | BIT_ULL(54) | BIT_ULL(55) |
- /* reserved */
- BIT_ULL(31) | GENMASK_ULL(47, 45) | GENMASK_ULL(63, 56);
- u64 vmx_basic = vmx->nested.msrs.basic;
-
- if (!is_bitwise_subset(vmx_basic, data, feature_and_reserved))
- return -EINVAL;
-
- /*
- * KVM does not emulate a version of VMX that constrains physical
- * addresses of VMX structures (e.g. VMCS) to 32-bits.
- */
- if (data & BIT_ULL(48))
- return -EINVAL;
-
- if (vmx_basic_vmcs_revision_id(vmx_basic) !=
- vmx_basic_vmcs_revision_id(data))
- return -EINVAL;
-
- if (vmx_basic_vmcs_size(vmx_basic) > vmx_basic_vmcs_size(data))
- return -EINVAL;
-
- vmx->nested.msrs.basic = data;
- return 0;
-}
-
-static int
-vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
-{
- u64 supported;
- u32 *lowp, *highp;
-
- switch (msr_index) {
- case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
- lowp = &vmx->nested.msrs.pinbased_ctls_low;
- highp = &vmx->nested.msrs.pinbased_ctls_high;
- break;
- case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
- lowp = &vmx->nested.msrs.procbased_ctls_low;
- highp = &vmx->nested.msrs.procbased_ctls_high;
- break;
- case MSR_IA32_VMX_TRUE_EXIT_CTLS:
- lowp = &vmx->nested.msrs.exit_ctls_low;
- highp = &vmx->nested.msrs.exit_ctls_high;
- break;
- case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
- lowp = &vmx->nested.msrs.entry_ctls_low;
- highp = &vmx->nested.msrs.entry_ctls_high;
- break;
- case MSR_IA32_VMX_PROCBASED_CTLS2:
- lowp = &vmx->nested.msrs.secondary_ctls_low;
- highp = &vmx->nested.msrs.secondary_ctls_high;
- break;
- default:
- BUG();
- }
-
- supported = vmx_control_msr(*lowp, *highp);
-
- /* Check must-be-1 bits are still 1. */
- if (!is_bitwise_subset(data, supported, GENMASK_ULL(31, 0)))
- return -EINVAL;
-
- /* Check must-be-0 bits are still 0. */
- if (!is_bitwise_subset(supported, data, GENMASK_ULL(63, 32)))
- return -EINVAL;
-
- *lowp = data;
- *highp = data >> 32;
- return 0;
-}
-
-static int vmx_restore_vmx_misc(struct vcpu_vmx *vmx, u64 data)
-{
- const u64 feature_and_reserved_bits =
- /* feature */
- BIT_ULL(5) | GENMASK_ULL(8, 6) | BIT_ULL(14) | BIT_ULL(15) |
- BIT_ULL(28) | BIT_ULL(29) | BIT_ULL(30) |
- /* reserved */
- GENMASK_ULL(13, 9) | BIT_ULL(31);
- u64 vmx_misc;
-
- vmx_misc = vmx_control_msr(vmx->nested.msrs.misc_low,
- vmx->nested.msrs.misc_high);
-
- if (!is_bitwise_subset(vmx_misc, data, feature_and_reserved_bits))
- return -EINVAL;
-
- if ((vmx->nested.msrs.pinbased_ctls_high &
- PIN_BASED_VMX_PREEMPTION_TIMER) &&
- vmx_misc_preemption_timer_rate(data) !=
- vmx_misc_preemption_timer_rate(vmx_misc))
- return -EINVAL;
-
- if (vmx_misc_cr3_count(data) > vmx_misc_cr3_count(vmx_misc))
- return -EINVAL;
-
- if (vmx_misc_max_msr(data) > vmx_misc_max_msr(vmx_misc))
- return -EINVAL;
-
- if (vmx_misc_mseg_revid(data) != vmx_misc_mseg_revid(vmx_misc))
- return -EINVAL;
-
- vmx->nested.msrs.misc_low = data;
- vmx->nested.msrs.misc_high = data >> 32;
-
- /*
- * If L1 has read-only VM-exit information fields, use the
- * less permissive vmx_vmwrite_bitmap to specify write
- * permissions for the shadow VMCS.
- */
- if (enable_shadow_vmcs && !nested_cpu_has_vmwrite_any_field(&vmx->vcpu))
- vmcs_write64(VMWRITE_BITMAP, __pa(vmx_vmwrite_bitmap));
-
- return 0;
-}
-
-static int vmx_restore_vmx_ept_vpid_cap(struct vcpu_vmx *vmx, u64 data)
-{
- u64 vmx_ept_vpid_cap;
-
- vmx_ept_vpid_cap = vmx_control_msr(vmx->nested.msrs.ept_caps,
- vmx->nested.msrs.vpid_caps);
-
- /* Every bit is either reserved or a feature bit. */
- if (!is_bitwise_subset(vmx_ept_vpid_cap, data, -1ULL))
- return -EINVAL;
-
- vmx->nested.msrs.ept_caps = data;
- vmx->nested.msrs.vpid_caps = data >> 32;
- return 0;
-}
-
-static int vmx_restore_fixed0_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
-{
- u64 *msr;
-
- switch (msr_index) {
- case MSR_IA32_VMX_CR0_FIXED0:
- msr = &vmx->nested.msrs.cr0_fixed0;
- break;
- case MSR_IA32_VMX_CR4_FIXED0:
- msr = &vmx->nested.msrs.cr4_fixed0;
- break;
- default:
- BUG();
- }
-
- /*
- * 1 bits (which indicates bits which "must-be-1" during VMX operation)
- * must be 1 in the restored value.
- */
- if (!is_bitwise_subset(data, *msr, -1ULL))
- return -EINVAL;
-
- *msr = data;
- return 0;
-}
-
-/*
- * Called when userspace is restoring VMX MSRs.
- *
- * Returns 0 on success, non-0 otherwise.
- */
-static int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- /*
- * Don't allow changes to the VMX capability MSRs while the vCPU
- * is in VMX operation.
- */
- if (vmx->nested.vmxon)
- return -EBUSY;
-
- switch (msr_index) {
- case MSR_IA32_VMX_BASIC:
- return vmx_restore_vmx_basic(vmx, data);
- case MSR_IA32_VMX_PINBASED_CTLS:
- case MSR_IA32_VMX_PROCBASED_CTLS:
- case MSR_IA32_VMX_EXIT_CTLS:
- case MSR_IA32_VMX_ENTRY_CTLS:
- /*
- * The "non-true" VMX capability MSRs are generated from the
- * "true" MSRs, so we do not support restoring them directly.
- *
- * If userspace wants to emulate VMX_BASIC[55]=0, userspace
- * should restore the "true" MSRs with the must-be-1 bits
- * set according to the SDM Vol 3. A.2 "RESERVED CONTROLS AND
- * DEFAULT SETTINGS".
- */
- return -EINVAL;
- case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
- case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
- case MSR_IA32_VMX_TRUE_EXIT_CTLS:
- case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
- case MSR_IA32_VMX_PROCBASED_CTLS2:
- return vmx_restore_control_msr(vmx, msr_index, data);
- case MSR_IA32_VMX_MISC:
- return vmx_restore_vmx_misc(vmx, data);
- case MSR_IA32_VMX_CR0_FIXED0:
- case MSR_IA32_VMX_CR4_FIXED0:
- return vmx_restore_fixed0_msr(vmx, msr_index, data);
- case MSR_IA32_VMX_CR0_FIXED1:
- case MSR_IA32_VMX_CR4_FIXED1:
- /*
- * These MSRs are generated based on the vCPU's CPUID, so we
- * do not support restoring them directly.
- */
- return -EINVAL;
- case MSR_IA32_VMX_EPT_VPID_CAP:
- return vmx_restore_vmx_ept_vpid_cap(vmx, data);
- case MSR_IA32_VMX_VMCS_ENUM:
- vmx->nested.msrs.vmcs_enum = data;
- return 0;
- default:
- /*
- * The rest of the VMX capability MSRs do not support restore.
- */
- return -EINVAL;
- }
-}
-
-/* Returns 0 on success, non-0 otherwise. */
-static int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdata)
-{
- switch (msr_index) {
- case MSR_IA32_VMX_BASIC:
- *pdata = msrs->basic;
- break;
- case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
- case MSR_IA32_VMX_PINBASED_CTLS:
- *pdata = vmx_control_msr(
- msrs->pinbased_ctls_low,
- msrs->pinbased_ctls_high);
- if (msr_index == MSR_IA32_VMX_PINBASED_CTLS)
- *pdata |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
- break;
- case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
- case MSR_IA32_VMX_PROCBASED_CTLS:
- *pdata = vmx_control_msr(
- msrs->procbased_ctls_low,
- msrs->procbased_ctls_high);
- if (msr_index == MSR_IA32_VMX_PROCBASED_CTLS)
- *pdata |= CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
- break;
- case MSR_IA32_VMX_TRUE_EXIT_CTLS:
- case MSR_IA32_VMX_EXIT_CTLS:
- *pdata = vmx_control_msr(
- msrs->exit_ctls_low,
- msrs->exit_ctls_high);
- if (msr_index == MSR_IA32_VMX_EXIT_CTLS)
- *pdata |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
- break;
- case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
- case MSR_IA32_VMX_ENTRY_CTLS:
- *pdata = vmx_control_msr(
- msrs->entry_ctls_low,
- msrs->entry_ctls_high);
- if (msr_index == MSR_IA32_VMX_ENTRY_CTLS)
- *pdata |= VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
- break;
- case MSR_IA32_VMX_MISC:
- *pdata = vmx_control_msr(
- msrs->misc_low,
- msrs->misc_high);
- break;
- case MSR_IA32_VMX_CR0_FIXED0:
- *pdata = msrs->cr0_fixed0;
- break;
- case MSR_IA32_VMX_CR0_FIXED1:
- *pdata = msrs->cr0_fixed1;
- break;
- case MSR_IA32_VMX_CR4_FIXED0:
- *pdata = msrs->cr4_fixed0;
- break;
- case MSR_IA32_VMX_CR4_FIXED1:
- *pdata = msrs->cr4_fixed1;
- break;
- case MSR_IA32_VMX_VMCS_ENUM:
- *pdata = msrs->vmcs_enum;
- break;
- case MSR_IA32_VMX_PROCBASED_CTLS2:
- *pdata = vmx_control_msr(
- msrs->secondary_ctls_low,
- msrs->secondary_ctls_high);
- break;
- case MSR_IA32_VMX_EPT_VPID_CAP:
- *pdata = msrs->ept_caps |
- ((u64)msrs->vpid_caps << 32);
- break;
- case MSR_IA32_VMX_VMFUNC:
- *pdata = msrs->vmfunc_controls;
- break;
- default:
- return 1;
- }
-
- return 0;
-}
-
-static inline bool vmx_feature_control_msr_valid(struct kvm_vcpu *vcpu,
- uint64_t val)
-{
- uint64_t valid_bits = to_vmx(vcpu)->msr_ia32_feature_control_valid_bits;
-
- return !(val & ~valid_bits);
-}
-
-static int vmx_get_msr_feature(struct kvm_msr_entry *msr)
-{
- switch (msr->index) {
- case MSR_IA32_VMX_BASIC ... MSR_IA32_VMX_VMFUNC:
- if (!nested)
- return 1;
- return vmx_get_vmx_msr(&vmcs_config.nested, msr->index, &msr->data);
- default:
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Reads an msr value (of 'msr_index') into 'pdata'.
- * Returns 0 on success, non-0 otherwise.
- * Assumes vcpu_load() was already called.
- */
-static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct shared_msr_entry *msr;
-
- switch (msr_info->index) {
-#ifdef CONFIG_X86_64
- case MSR_FS_BASE:
- msr_info->data = vmcs_readl(GUEST_FS_BASE);
- break;
- case MSR_GS_BASE:
- msr_info->data = vmcs_readl(GUEST_GS_BASE);
- break;
- case MSR_KERNEL_GS_BASE:
- msr_info->data = vmx_read_guest_kernel_gs_base(vmx);
- break;
-#endif
- case MSR_EFER:
- return kvm_get_msr_common(vcpu, msr_info);
- case MSR_IA32_SPEC_CTRL:
- if (!msr_info->host_initiated &&
- !guest_has_spec_ctrl_msr(vcpu))
- return 1;
-
- msr_info->data = to_vmx(vcpu)->spec_ctrl;
- break;
- case MSR_IA32_SYSENTER_CS:
- msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
- break;
- case MSR_IA32_SYSENTER_EIP:
- msr_info->data = vmcs_readl(GUEST_SYSENTER_EIP);
- break;
- case MSR_IA32_SYSENTER_ESP:
- msr_info->data = vmcs_readl(GUEST_SYSENTER_ESP);
- break;
- case MSR_IA32_BNDCFGS:
- if (!kvm_mpx_supported() ||
- (!msr_info->host_initiated &&
- !guest_cpuid_has(vcpu, X86_FEATURE_MPX)))
- return 1;
- msr_info->data = vmcs_read64(GUEST_BNDCFGS);
- break;
- case MSR_IA32_MCG_EXT_CTL:
- if (!msr_info->host_initiated &&
- !(vmx->msr_ia32_feature_control &
- FEATURE_CONTROL_LMCE))
- return 1;
- msr_info->data = vcpu->arch.mcg_ext_ctl;
- break;
- case MSR_IA32_FEATURE_CONTROL:
- msr_info->data = vmx->msr_ia32_feature_control;
- break;
- case MSR_IA32_VMX_BASIC ... MSR_IA32_VMX_VMFUNC:
- if (!nested_vmx_allowed(vcpu))
- return 1;
- return vmx_get_vmx_msr(&vmx->nested.msrs, msr_info->index,
- &msr_info->data);
- case MSR_IA32_XSS:
- if (!vmx_xsaves_supported() ||
- (!msr_info->host_initiated &&
- !(guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
- guest_cpuid_has(vcpu, X86_FEATURE_XSAVES))))
- return 1;
- msr_info->data = vcpu->arch.ia32_xss;
- break;
- case MSR_TSC_AUX:
- if (!msr_info->host_initiated &&
- !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
- return 1;
- /* Otherwise falls through */
- default:
- msr = find_msr_entry(vmx, msr_info->index);
- if (msr) {
- msr_info->data = msr->data;
- break;
- }
- return kvm_get_msr_common(vcpu, msr_info);
- }
-
- return 0;
-}
-
-static void vmx_leave_nested(struct kvm_vcpu *vcpu);
-
-/*
- * Writes msr value into into the appropriate "register".
- * Returns 0 on success, non-0 otherwise.
- * Assumes vcpu_load() was already called.
- */
-static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct shared_msr_entry *msr;
- int ret = 0;
- u32 msr_index = msr_info->index;
- u64 data = msr_info->data;
-
- switch (msr_index) {
- case MSR_EFER:
- ret = kvm_set_msr_common(vcpu, msr_info);
- break;
-#ifdef CONFIG_X86_64
- case MSR_FS_BASE:
- vmx_segment_cache_clear(vmx);
- vmcs_writel(GUEST_FS_BASE, data);
- break;
- case MSR_GS_BASE:
- vmx_segment_cache_clear(vmx);
- vmcs_writel(GUEST_GS_BASE, data);
- break;
- case MSR_KERNEL_GS_BASE:
- vmx_write_guest_kernel_gs_base(vmx, data);
- break;
-#endif
- case MSR_IA32_SYSENTER_CS:
- vmcs_write32(GUEST_SYSENTER_CS, data);
- break;
- case MSR_IA32_SYSENTER_EIP:
- vmcs_writel(GUEST_SYSENTER_EIP, data);
- break;
- case MSR_IA32_SYSENTER_ESP:
- vmcs_writel(GUEST_SYSENTER_ESP, data);
- break;
- case MSR_IA32_BNDCFGS:
- if (!kvm_mpx_supported() ||
- (!msr_info->host_initiated &&
- !guest_cpuid_has(vcpu, X86_FEATURE_MPX)))
- return 1;
- if (is_noncanonical_address(data & PAGE_MASK, vcpu) ||
- (data & MSR_IA32_BNDCFGS_RSVD))
- return 1;
- vmcs_write64(GUEST_BNDCFGS, data);
- break;
- case MSR_IA32_SPEC_CTRL:
- if (!msr_info->host_initiated &&
- !guest_has_spec_ctrl_msr(vcpu))
- return 1;
-
- /* The STIBP bit doesn't fault even if it's not advertised */
- if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD))
- return 1;
-
- vmx->spec_ctrl = data;
-
- if (!data)
- break;
-
- /*
- * For non-nested:
- * When it's written (to non-zero) for the first time, pass
- * it through.
- *
- * For nested:
- * The handling of the MSR bitmap for L2 guests is done in
- * nested_vmx_merge_msr_bitmap. We should not touch the
- * vmcs02.msr_bitmap here since it gets completely overwritten
- * in the merging. We update the vmcs01 here for L1 as well
- * since it will end up touching the MSR anyway now.
- */
- vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
- MSR_IA32_SPEC_CTRL,
- MSR_TYPE_RW);
- break;
- case MSR_IA32_PRED_CMD:
- if (!msr_info->host_initiated &&
- !guest_has_pred_cmd_msr(vcpu))
- return 1;
-
- if (data & ~PRED_CMD_IBPB)
- return 1;
-
- if (!data)
- break;
-
- wrmsrl(MSR_IA32_PRED_CMD, PRED_CMD_IBPB);
-
- /*
- * For non-nested:
- * When it's written (to non-zero) for the first time, pass
- * it through.
- *
- * For nested:
- * The handling of the MSR bitmap for L2 guests is done in
- * nested_vmx_merge_msr_bitmap. We should not touch the
- * vmcs02.msr_bitmap here since it gets completely overwritten
- * in the merging.
- */
- vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap, MSR_IA32_PRED_CMD,
- MSR_TYPE_W);
- break;
- case MSR_IA32_CR_PAT:
- if (!kvm_pat_valid(data))
- return 1;
-
- if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
- vmcs_write64(GUEST_IA32_PAT, data);
- vcpu->arch.pat = data;
- break;
- }
- ret = kvm_set_msr_common(vcpu, msr_info);
- break;
- case MSR_IA32_TSC_ADJUST:
- ret = kvm_set_msr_common(vcpu, msr_info);
- break;
- case MSR_IA32_MCG_EXT_CTL:
- if ((!msr_info->host_initiated &&
- !(to_vmx(vcpu)->msr_ia32_feature_control &
- FEATURE_CONTROL_LMCE)) ||
- (data & ~MCG_EXT_CTL_LMCE_EN))
- return 1;
- vcpu->arch.mcg_ext_ctl = data;
- break;
- case MSR_IA32_FEATURE_CONTROL:
- if (!vmx_feature_control_msr_valid(vcpu, data) ||
- (to_vmx(vcpu)->msr_ia32_feature_control &
- FEATURE_CONTROL_LOCKED && !msr_info->host_initiated))
- return 1;
- vmx->msr_ia32_feature_control = data;
- if (msr_info->host_initiated && data == 0)
- vmx_leave_nested(vcpu);
- break;
- case MSR_IA32_VMX_BASIC ... MSR_IA32_VMX_VMFUNC:
- if (!msr_info->host_initiated)
- return 1; /* they are read-only */
- if (!nested_vmx_allowed(vcpu))
- return 1;
- return vmx_set_vmx_msr(vcpu, msr_index, data);
- case MSR_IA32_XSS:
- if (!vmx_xsaves_supported() ||
- (!msr_info->host_initiated &&
- !(guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
- guest_cpuid_has(vcpu, X86_FEATURE_XSAVES))))
- return 1;
- /*
- * The only supported bit as of Skylake is bit 8, but
- * it is not supported on KVM.
- */
- if (data != 0)
- return 1;
- vcpu->arch.ia32_xss = data;
- if (vcpu->arch.ia32_xss != host_xss)
- add_atomic_switch_msr(vmx, MSR_IA32_XSS,
- vcpu->arch.ia32_xss, host_xss, false);
- else
- clear_atomic_switch_msr(vmx, MSR_IA32_XSS);
- break;
- case MSR_TSC_AUX:
- if (!msr_info->host_initiated &&
- !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
- return 1;
- /* Check reserved bit, higher 32 bits should be zero */
- if ((data >> 32) != 0)
- return 1;
- /* Otherwise falls through */
- default:
- msr = find_msr_entry(vmx, msr_index);
- if (msr) {
- u64 old_msr_data = msr->data;
- msr->data = data;
- if (msr - vmx->guest_msrs < vmx->save_nmsrs) {
- preempt_disable();
- ret = kvm_set_shared_msr(msr->index, msr->data,
- msr->mask);
- preempt_enable();
- if (ret)
- msr->data = old_msr_data;
- }
- break;
- }
- ret = kvm_set_msr_common(vcpu, msr_info);
- }
-
- /* FB_CLEAR may have changed, also update the FB_CLEAR_DIS behavior */
- if (msr_index == MSR_IA32_ARCH_CAPABILITIES)
- vmx_update_fb_clear_dis(vcpu, vmx);
-
- return ret;
-}
-
-static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
-{
- __set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
- switch (reg) {
- case VCPU_REGS_RSP:
- vcpu->arch.regs[VCPU_REGS_RSP] = vmcs_readl(GUEST_RSP);
- break;
- case VCPU_REGS_RIP:
- vcpu->arch.regs[VCPU_REGS_RIP] = vmcs_readl(GUEST_RIP);
- break;
- case VCPU_EXREG_PDPTR:
- if (enable_ept)
- ept_save_pdptrs(vcpu);
- break;
- default:
- break;
- }
-}
-
-static __init int cpu_has_kvm_support(void)
-{
- return cpu_has_vmx();
-}
-
-static __init int vmx_disabled_by_bios(void)
-{
- u64 msr;
-
- rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
- if (msr & FEATURE_CONTROL_LOCKED) {
- /* launched w/ TXT and VMX disabled */
- if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
- && tboot_enabled())
- return 1;
- /* launched w/o TXT and VMX only enabled w/ TXT */
- if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
- && (msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
- && !tboot_enabled()) {
- printk(KERN_WARNING "kvm: disable TXT in the BIOS or "
- "activate TXT before enabling KVM\n");
- return 1;
- }
- /* launched w/o TXT and VMX disabled */
- if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
- && !tboot_enabled())
- return 1;
- }
-
- return 0;
-}
-
-static void kvm_cpu_vmxon(u64 addr)
-{
- cr4_set_bits(X86_CR4_VMXE);
- intel_pt_handle_vmx(1);
-
- asm volatile (ASM_VMX_VMXON_RAX
- : : "a"(&addr), "m"(addr)
- : "memory", "cc");
-}
-
-static int hardware_enable(void)
-{
- int cpu = raw_smp_processor_id();
- u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
- u64 old, test_bits;
-
- if (cr4_read_shadow() & X86_CR4_VMXE)
- return -EBUSY;
-
- /*
- * This can happen if we hot-added a CPU but failed to allocate
- * VP assist page for it.
- */
- if (static_branch_unlikely(&enable_evmcs) &&
- !hv_get_vp_assist_page(cpu))
- return -EFAULT;
-
- rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
-
- test_bits = FEATURE_CONTROL_LOCKED;
- test_bits |= FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
- if (tboot_enabled())
- test_bits |= FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX;
-
- if ((old & test_bits) != test_bits) {
- /* enable and lock */
- wrmsrl(MSR_IA32_FEATURE_CONTROL, old | test_bits);
- }
- kvm_cpu_vmxon(phys_addr);
- if (enable_ept)
- ept_sync_global();
-
- return 0;
-}
-
-static void vmclear_local_loaded_vmcss(void)
-{
- int cpu = raw_smp_processor_id();
- struct loaded_vmcs *v, *n;
-
- list_for_each_entry_safe(v, n, &per_cpu(loaded_vmcss_on_cpu, cpu),
- loaded_vmcss_on_cpu_link)
- __loaded_vmcs_clear(v);
-}
-
-
-/* Just like cpu_vmxoff(), but with the __kvm_handle_fault_on_reboot()
- * tricks.
- */
-static void kvm_cpu_vmxoff(void)
-{
- asm volatile (__ex(ASM_VMX_VMXOFF) : : : "cc");
-
- intel_pt_handle_vmx(0);
- cr4_clear_bits(X86_CR4_VMXE);
-}
-
-static void hardware_disable(void)
-{
- vmclear_local_loaded_vmcss();
- kvm_cpu_vmxoff();
-}
-
-static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt,
- u32 msr, u32 *result)
-{
- u32 vmx_msr_low, vmx_msr_high;
- u32 ctl = ctl_min | ctl_opt;
-
- rdmsr(msr, vmx_msr_low, vmx_msr_high);
-
- ctl &= vmx_msr_high; /* bit == 0 in high word ==> must be zero */
- ctl |= vmx_msr_low; /* bit == 1 in low word ==> must be one */
-
- /* Ensure minimum (required) set of control bits are supported. */
- if (ctl_min & ~ctl)
- return -EIO;
-
- *result = ctl;
- return 0;
-}
-
-static __init bool allow_1_setting(u32 msr, u32 ctl)
-{
- u32 vmx_msr_low, vmx_msr_high;
-
- rdmsr(msr, vmx_msr_low, vmx_msr_high);
- return vmx_msr_high & ctl;
-}
-
-static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
-{
- u32 vmx_msr_low, vmx_msr_high;
- u32 min, opt, min2, opt2;
- u32 _pin_based_exec_control = 0;
- u32 _cpu_based_exec_control = 0;
- u32 _cpu_based_2nd_exec_control = 0;
- u32 _vmexit_control = 0;
- u32 _vmentry_control = 0;
-
- memset(vmcs_conf, 0, sizeof(*vmcs_conf));
- min = CPU_BASED_HLT_EXITING |
-#ifdef CONFIG_X86_64
- CPU_BASED_CR8_LOAD_EXITING |
- CPU_BASED_CR8_STORE_EXITING |
-#endif
- CPU_BASED_CR3_LOAD_EXITING |
- CPU_BASED_CR3_STORE_EXITING |
- CPU_BASED_UNCOND_IO_EXITING |
- CPU_BASED_MOV_DR_EXITING |
- CPU_BASED_USE_TSC_OFFSETING |
- CPU_BASED_MWAIT_EXITING |
- CPU_BASED_MONITOR_EXITING |
- CPU_BASED_INVLPG_EXITING |
- CPU_BASED_RDPMC_EXITING;
-
- opt = CPU_BASED_TPR_SHADOW |
- CPU_BASED_USE_MSR_BITMAPS |
- CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
- if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
- &_cpu_based_exec_control) < 0)
- return -EIO;
-#ifdef CONFIG_X86_64
- if ((_cpu_based_exec_control & CPU_BASED_TPR_SHADOW))
- _cpu_based_exec_control &= ~CPU_BASED_CR8_LOAD_EXITING &
- ~CPU_BASED_CR8_STORE_EXITING;
-#endif
- if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
- min2 = 0;
- opt2 = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
- SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
- SECONDARY_EXEC_WBINVD_EXITING |
- SECONDARY_EXEC_ENABLE_VPID |
- SECONDARY_EXEC_ENABLE_EPT |
- SECONDARY_EXEC_UNRESTRICTED_GUEST |
- SECONDARY_EXEC_PAUSE_LOOP_EXITING |
- SECONDARY_EXEC_DESC |
- SECONDARY_EXEC_RDTSCP |
- SECONDARY_EXEC_ENABLE_INVPCID |
- SECONDARY_EXEC_APIC_REGISTER_VIRT |
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
- SECONDARY_EXEC_SHADOW_VMCS |
- SECONDARY_EXEC_XSAVES |
- SECONDARY_EXEC_RDSEED_EXITING |
- SECONDARY_EXEC_RDRAND_EXITING |
- SECONDARY_EXEC_ENABLE_PML |
- SECONDARY_EXEC_TSC_SCALING |
- SECONDARY_EXEC_ENABLE_VMFUNC |
- SECONDARY_EXEC_ENCLS_EXITING;
- if (adjust_vmx_controls(min2, opt2,
- MSR_IA32_VMX_PROCBASED_CTLS2,
- &_cpu_based_2nd_exec_control) < 0)
- return -EIO;
- }
-#ifndef CONFIG_X86_64
- if (!(_cpu_based_2nd_exec_control &
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
- _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW;
-#endif
-
- if (!(_cpu_based_exec_control & CPU_BASED_TPR_SHADOW))
- _cpu_based_2nd_exec_control &= ~(
- SECONDARY_EXEC_APIC_REGISTER_VIRT |
- SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
-
- rdmsr_safe(MSR_IA32_VMX_EPT_VPID_CAP,
- &vmx_capability.ept, &vmx_capability.vpid);
-
- if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) {
- /* CR3 accesses and invlpg don't need to cause VM Exits when EPT
- enabled */
- _cpu_based_exec_control &= ~(CPU_BASED_CR3_LOAD_EXITING |
- CPU_BASED_CR3_STORE_EXITING |
- CPU_BASED_INVLPG_EXITING);
- } else if (vmx_capability.ept) {
- vmx_capability.ept = 0;
- pr_warn_once("EPT CAP should not exist if not support "
- "1-setting enable EPT VM-execution control\n");
- }
- if (!(_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_VPID) &&
- vmx_capability.vpid) {
- vmx_capability.vpid = 0;
- pr_warn_once("VPID CAP should not exist if not support "
- "1-setting enable VPID VM-execution control\n");
- }
-
- min = VM_EXIT_SAVE_DEBUG_CONTROLS | VM_EXIT_ACK_INTR_ON_EXIT;
-#ifdef CONFIG_X86_64
- min |= VM_EXIT_HOST_ADDR_SPACE_SIZE;
-#endif
- opt = VM_EXIT_SAVE_IA32_PAT | VM_EXIT_LOAD_IA32_PAT |
- VM_EXIT_CLEAR_BNDCFGS;
- if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
- &_vmexit_control) < 0)
- return -EIO;
-
- min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
- opt = PIN_BASED_VIRTUAL_NMIS | PIN_BASED_POSTED_INTR |
- PIN_BASED_VMX_PREEMPTION_TIMER;
- if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
- &_pin_based_exec_control) < 0)
- return -EIO;
-
- if (cpu_has_broken_vmx_preemption_timer())
- _pin_based_exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
- if (!(_cpu_based_2nd_exec_control &
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY))
- _pin_based_exec_control &= ~PIN_BASED_POSTED_INTR;
-
- min = VM_ENTRY_LOAD_DEBUG_CONTROLS;
- opt = VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_LOAD_BNDCFGS;
- if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
- &_vmentry_control) < 0)
- return -EIO;
-
- rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high);
-
- /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
- if ((vmx_msr_high & 0x1fff) > PAGE_SIZE)
- return -EIO;
-
-#ifdef CONFIG_X86_64
- /* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */
- if (vmx_msr_high & (1u<<16))
- return -EIO;
-#endif
-
- /* Require Write-Back (WB) memory type for VMCS accesses. */
- if (((vmx_msr_high >> 18) & 15) != 6)
- return -EIO;
-
- vmcs_conf->size = vmx_msr_high & 0x1fff;
- vmcs_conf->order = get_order(vmcs_conf->size);
- vmcs_conf->basic_cap = vmx_msr_high & ~0x1fff;
-
- vmcs_conf->revision_id = vmx_msr_low;
-
- vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control;
- vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control;
- vmcs_conf->cpu_based_2nd_exec_ctrl = _cpu_based_2nd_exec_control;
- vmcs_conf->vmexit_ctrl = _vmexit_control;
- vmcs_conf->vmentry_ctrl = _vmentry_control;
-
- if (static_branch_unlikely(&enable_evmcs))
- evmcs_sanitize_exec_ctrls(vmcs_conf);
-
- cpu_has_load_ia32_efer =
- allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS,
- VM_ENTRY_LOAD_IA32_EFER)
- && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
- VM_EXIT_LOAD_IA32_EFER);
-
- cpu_has_load_perf_global_ctrl =
- allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS,
- VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
- && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
- VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
-
- /*
- * Some cpus support VM_ENTRY_(LOAD|SAVE)_IA32_PERF_GLOBAL_CTRL
- * but due to errata below it can't be used. Workaround is to use
- * msr load mechanism to switch IA32_PERF_GLOBAL_CTRL.
- *
- * VM Exit May Incorrectly Clear IA32_PERF_GLOBAL_CTRL [34:32]
- *
- * AAK155 (model 26)
- * AAP115 (model 30)
- * AAT100 (model 37)
- * BC86,AAY89,BD102 (model 44)
- * BA97 (model 46)
- *
- */
- if (cpu_has_load_perf_global_ctrl && boot_cpu_data.x86 == 0x6) {
- switch (boot_cpu_data.x86_model) {
- case 26:
- case 30:
- case 37:
- case 44:
- case 46:
- cpu_has_load_perf_global_ctrl = false;
- printk_once(KERN_WARNING"kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
- "does not work properly. Using workaround\n");
- break;
- default:
- break;
- }
- }
-
- if (boot_cpu_has(X86_FEATURE_XSAVES))
- rdmsrl(MSR_IA32_XSS, host_xss);
-
- return 0;
-}
-
-static struct vmcs *alloc_vmcs_cpu(bool shadow, int cpu)
-{
- int node = cpu_to_node(cpu);
- struct page *pages;
- struct vmcs *vmcs;
-
- pages = __alloc_pages_node(node, GFP_KERNEL, vmcs_config.order);
- if (!pages)
- return NULL;
- vmcs = page_address(pages);
- memset(vmcs, 0, vmcs_config.size);
-
- /* KVM supports Enlightened VMCS v1 only */
- if (static_branch_unlikely(&enable_evmcs))
- vmcs->hdr.revision_id = KVM_EVMCS_VERSION;
- else
- vmcs->hdr.revision_id = vmcs_config.revision_id;
-
- if (shadow)
- vmcs->hdr.shadow_vmcs = 1;
- return vmcs;
-}
-
-static void free_vmcs(struct vmcs *vmcs)
-{
- free_pages((unsigned long)vmcs, vmcs_config.order);
-}
-
-/*
- * Free a VMCS, but before that VMCLEAR it on the CPU where it was last loaded
- */
-static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
-{
- if (!loaded_vmcs->vmcs)
- return;
- loaded_vmcs_clear(loaded_vmcs);
- free_vmcs(loaded_vmcs->vmcs);
- loaded_vmcs->vmcs = NULL;
- if (loaded_vmcs->msr_bitmap)
- free_page((unsigned long)loaded_vmcs->msr_bitmap);
- WARN_ON(loaded_vmcs->shadow_vmcs != NULL);
-}
-
-static struct vmcs *alloc_vmcs(bool shadow)
-{
- return alloc_vmcs_cpu(shadow, raw_smp_processor_id());
-}
-
-static int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
-{
- loaded_vmcs->vmcs = alloc_vmcs(false);
- if (!loaded_vmcs->vmcs)
- return -ENOMEM;
-
- loaded_vmcs->shadow_vmcs = NULL;
- loaded_vmcs_init(loaded_vmcs);
-
- if (cpu_has_vmx_msr_bitmap()) {
- loaded_vmcs->msr_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL);
- if (!loaded_vmcs->msr_bitmap)
- goto out_vmcs;
- memset(loaded_vmcs->msr_bitmap, 0xff, PAGE_SIZE);
-
- if (IS_ENABLED(CONFIG_HYPERV) &&
- static_branch_unlikely(&enable_evmcs) &&
- (ms_hyperv.nested_features & HV_X64_NESTED_MSR_BITMAP)) {
- struct hv_enlightened_vmcs *evmcs =
- (struct hv_enlightened_vmcs *)loaded_vmcs->vmcs;
-
- evmcs->hv_enlightenments_control.msr_bitmap = 1;
- }
- }
-
- memset(&loaded_vmcs->host_state, 0, sizeof(struct vmcs_host_state));
-
- return 0;
-
-out_vmcs:
- free_loaded_vmcs(loaded_vmcs);
- return -ENOMEM;
-}
-
-static void free_kvm_area(void)
-{
- int cpu;
-
- for_each_possible_cpu(cpu) {
- free_vmcs(per_cpu(vmxarea, cpu));
- per_cpu(vmxarea, cpu) = NULL;
- }
-}
-
-enum vmcs_field_width {
- VMCS_FIELD_WIDTH_U16 = 0,
- VMCS_FIELD_WIDTH_U64 = 1,
- VMCS_FIELD_WIDTH_U32 = 2,
- VMCS_FIELD_WIDTH_NATURAL_WIDTH = 3
-};
-
-static inline int vmcs_field_width(unsigned long field)
-{
- if (0x1 & field) /* the *_HIGH fields are all 32 bit */
- return VMCS_FIELD_WIDTH_U32;
- return (field >> 13) & 0x3 ;
-}
-
-static inline int vmcs_field_readonly(unsigned long field)
-{
- return (((field >> 10) & 0x3) == 1);
-}
-
-static void init_vmcs_shadow_fields(void)
-{
- int i, j;
-
- for (i = j = 0; i < max_shadow_read_only_fields; i++) {
- u16 field = shadow_read_only_fields[i];
- if (vmcs_field_width(field) == VMCS_FIELD_WIDTH_U64 &&
- (i + 1 == max_shadow_read_only_fields ||
- shadow_read_only_fields[i + 1] != field + 1))
- pr_err("Missing field from shadow_read_only_field %x\n",
- field + 1);
-
- clear_bit(field, vmx_vmread_bitmap);
-#ifdef CONFIG_X86_64
- if (field & 1)
- continue;
-#endif
- if (j < i)
- shadow_read_only_fields[j] = field;
- j++;
- }
- max_shadow_read_only_fields = j;
-
- for (i = j = 0; i < max_shadow_read_write_fields; i++) {
- u16 field = shadow_read_write_fields[i];
- if (vmcs_field_width(field) == VMCS_FIELD_WIDTH_U64 &&
- (i + 1 == max_shadow_read_write_fields ||
- shadow_read_write_fields[i + 1] != field + 1))
- pr_err("Missing field from shadow_read_write_field %x\n",
- field + 1);
-
- /*
- * PML and the preemption timer can be emulated, but the
- * processor cannot vmwrite to fields that don't exist
- * on bare metal.
- */
- switch (field) {
- case GUEST_PML_INDEX:
- if (!cpu_has_vmx_pml())
- continue;
- break;
- case VMX_PREEMPTION_TIMER_VALUE:
- if (!cpu_has_vmx_preemption_timer())
- continue;
- break;
- case GUEST_INTR_STATUS:
- if (!cpu_has_vmx_apicv())
- continue;
- break;
- default:
- break;
- }
-
- clear_bit(field, vmx_vmwrite_bitmap);
- clear_bit(field, vmx_vmread_bitmap);
-#ifdef CONFIG_X86_64
- if (field & 1)
- continue;
-#endif
- if (j < i)
- shadow_read_write_fields[j] = field;
- j++;
- }
- max_shadow_read_write_fields = j;
-}
-
-static __init int alloc_kvm_area(void)
-{
- int cpu;
-
- for_each_possible_cpu(cpu) {
- struct vmcs *vmcs;
-
- vmcs = alloc_vmcs_cpu(false, cpu);
- if (!vmcs) {
- free_kvm_area();
- return -ENOMEM;
- }
-
- /*
- * When eVMCS is enabled, alloc_vmcs_cpu() sets
- * vmcs->revision_id to KVM_EVMCS_VERSION instead of
- * revision_id reported by MSR_IA32_VMX_BASIC.
- *
- * However, even though not explictly documented by
- * TLFS, VMXArea passed as VMXON argument should
- * still be marked with revision_id reported by
- * physical CPU.
- */
- if (static_branch_unlikely(&enable_evmcs))
- vmcs->hdr.revision_id = vmcs_config.revision_id;
-
- per_cpu(vmxarea, cpu) = vmcs;
- }
- return 0;
-}
-
-static void fix_pmode_seg(struct kvm_vcpu *vcpu, int seg,
- struct kvm_segment *save)
-{
- if (!emulate_invalid_guest_state) {
- /*
- * CS and SS RPL should be equal during guest entry according
- * to VMX spec, but in reality it is not always so. Since vcpu
- * is in the middle of the transition from real mode to
- * protected mode it is safe to assume that RPL 0 is a good
- * default value.
- */
- if (seg == VCPU_SREG_CS || seg == VCPU_SREG_SS)
- save->selector &= ~SEGMENT_RPL_MASK;
- save->dpl = save->selector & SEGMENT_RPL_MASK;
- save->s = 1;
- }
- vmx_set_segment(vcpu, save, seg);
-}
-
-static void enter_pmode(struct kvm_vcpu *vcpu)
-{
- unsigned long flags;
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- /*
- * Update real mode segment cache. It may be not up-to-date if sement
- * register was written while vcpu was in a guest mode.
- */
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_ES], VCPU_SREG_ES);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_DS], VCPU_SREG_DS);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_FS], VCPU_SREG_FS);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_GS], VCPU_SREG_GS);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_SS], VCPU_SREG_SS);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_CS], VCPU_SREG_CS);
-
- vmx->rmode.vm86_active = 0;
-
- vmx_segment_cache_clear(vmx);
-
- vmx_set_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
-
- flags = vmcs_readl(GUEST_RFLAGS);
- flags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
- flags |= vmx->rmode.save_rflags & ~RMODE_GUEST_OWNED_EFLAGS_BITS;
- vmcs_writel(GUEST_RFLAGS, flags);
-
- vmcs_writel(GUEST_CR4, (vmcs_readl(GUEST_CR4) & ~X86_CR4_VME) |
- (vmcs_readl(CR4_READ_SHADOW) & X86_CR4_VME));
-
- update_exception_bitmap(vcpu);
-
- fix_pmode_seg(vcpu, VCPU_SREG_CS, &vmx->rmode.segs[VCPU_SREG_CS]);
- fix_pmode_seg(vcpu, VCPU_SREG_SS, &vmx->rmode.segs[VCPU_SREG_SS]);
- fix_pmode_seg(vcpu, VCPU_SREG_ES, &vmx->rmode.segs[VCPU_SREG_ES]);
- fix_pmode_seg(vcpu, VCPU_SREG_DS, &vmx->rmode.segs[VCPU_SREG_DS]);
- fix_pmode_seg(vcpu, VCPU_SREG_FS, &vmx->rmode.segs[VCPU_SREG_FS]);
- fix_pmode_seg(vcpu, VCPU_SREG_GS, &vmx->rmode.segs[VCPU_SREG_GS]);
-}
-
-static void fix_rmode_seg(int seg, struct kvm_segment *save)
-{
- const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
- struct kvm_segment var = *save;
-
- var.dpl = 0x3;
- if (seg == VCPU_SREG_CS)
- var.type = 0x3;
-
- if (!emulate_invalid_guest_state) {
- var.selector = var.base >> 4;
- var.base = var.base & 0xffff0;
- var.limit = 0xffff;
- var.g = 0;
- var.db = 0;
- var.present = 1;
- var.s = 1;
- var.l = 0;
- var.unusable = 0;
- var.type = 0x3;
- var.avl = 0;
- if (save->base & 0xf)
- printk_once(KERN_WARNING "kvm: segment base is not "
- "paragraph aligned when entering "
- "protected mode (seg=%d)", seg);
- }
-
- vmcs_write16(sf->selector, var.selector);
- vmcs_writel(sf->base, var.base);
- vmcs_write32(sf->limit, var.limit);
- vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(&var));
-}
-
-static void enter_rmode(struct kvm_vcpu *vcpu)
-{
- unsigned long flags;
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct kvm_vmx *kvm_vmx = to_kvm_vmx(vcpu->kvm);
-
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_ES], VCPU_SREG_ES);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_DS], VCPU_SREG_DS);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_FS], VCPU_SREG_FS);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_GS], VCPU_SREG_GS);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_SS], VCPU_SREG_SS);
- vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_CS], VCPU_SREG_CS);
-
- vmx->rmode.vm86_active = 1;
-
- /*
- * Very old userspace does not call KVM_SET_TSS_ADDR before entering
- * vcpu. Warn the user that an update is overdue.
- */
- if (!kvm_vmx->tss_addr)
- printk_once(KERN_WARNING "kvm: KVM_SET_TSS_ADDR need to be "
- "called before entering vcpu\n");
-
- vmx_segment_cache_clear(vmx);
-
- vmcs_writel(GUEST_TR_BASE, kvm_vmx->tss_addr);
- vmcs_write32(GUEST_TR_LIMIT, RMODE_TSS_SIZE - 1);
- vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
-
- flags = vmcs_readl(GUEST_RFLAGS);
- vmx->rmode.save_rflags = flags;
-
- flags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM;
-
- vmcs_writel(GUEST_RFLAGS, flags);
- vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | X86_CR4_VME);
- update_exception_bitmap(vcpu);
-
- fix_rmode_seg(VCPU_SREG_SS, &vmx->rmode.segs[VCPU_SREG_SS]);
- fix_rmode_seg(VCPU_SREG_CS, &vmx->rmode.segs[VCPU_SREG_CS]);
- fix_rmode_seg(VCPU_SREG_ES, &vmx->rmode.segs[VCPU_SREG_ES]);
- fix_rmode_seg(VCPU_SREG_DS, &vmx->rmode.segs[VCPU_SREG_DS]);
- fix_rmode_seg(VCPU_SREG_GS, &vmx->rmode.segs[VCPU_SREG_GS]);
- fix_rmode_seg(VCPU_SREG_FS, &vmx->rmode.segs[VCPU_SREG_FS]);
-
- kvm_mmu_reset_context(vcpu);
-}
-
-static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct shared_msr_entry *msr = find_msr_entry(vmx, MSR_EFER);
-
- if (!msr)
- return;
-
- vcpu->arch.efer = efer;
- if (efer & EFER_LMA) {
- vm_entry_controls_setbit(to_vmx(vcpu), VM_ENTRY_IA32E_MODE);
- msr->data = efer;
- } else {
- vm_entry_controls_clearbit(to_vmx(vcpu), VM_ENTRY_IA32E_MODE);
-
- msr->data = efer & ~EFER_LME;
- }
- setup_msrs(vmx);
-}
-
-#ifdef CONFIG_X86_64
-
-static void enter_lmode(struct kvm_vcpu *vcpu)
-{
- u32 guest_tr_ar;
-
- vmx_segment_cache_clear(to_vmx(vcpu));
-
- guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
- if ((guest_tr_ar & VMX_AR_TYPE_MASK) != VMX_AR_TYPE_BUSY_64_TSS) {
- pr_debug_ratelimited("%s: tss fixup for long mode. \n",
- __func__);
- vmcs_write32(GUEST_TR_AR_BYTES,
- (guest_tr_ar & ~VMX_AR_TYPE_MASK)
- | VMX_AR_TYPE_BUSY_64_TSS);
- }
- vmx_set_efer(vcpu, vcpu->arch.efer | EFER_LMA);
-}
-
-static void exit_lmode(struct kvm_vcpu *vcpu)
-{
- vm_entry_controls_clearbit(to_vmx(vcpu), VM_ENTRY_IA32E_MODE);
- vmx_set_efer(vcpu, vcpu->arch.efer & ~EFER_LMA);
-}
-
-#endif
-
-static inline void __vmx_flush_tlb(struct kvm_vcpu *vcpu, int vpid,
- bool invalidate_gpa)
-{
- if (enable_ept && (invalidate_gpa || !enable_vpid)) {
- if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
- return;
- ept_sync_context(construct_eptp(vcpu, vcpu->arch.mmu.root_hpa));
- } else {
- vpid_sync_context(vpid);
- }
-}
-
-static void vmx_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
-{
- __vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid, invalidate_gpa);
-}
-
-static void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr)
-{
- int vpid = to_vmx(vcpu)->vpid;
-
- if (!vpid_sync_vcpu_addr(vpid, addr))
- vpid_sync_context(vpid);
-
- /*
- * If VPIDs are not supported or enabled, then the above is a no-op.
- * But we don't really need a TLB flush in that case anyway, because
- * each VM entry/exit includes an implicit flush when VPID is 0.
- */
-}
-
-static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
-{
- ulong cr0_guest_owned_bits = vcpu->arch.cr0_guest_owned_bits;
-
- vcpu->arch.cr0 &= ~cr0_guest_owned_bits;
- vcpu->arch.cr0 |= vmcs_readl(GUEST_CR0) & cr0_guest_owned_bits;
-}
-
-static void vmx_decache_cr3(struct kvm_vcpu *vcpu)
-{
- if (enable_unrestricted_guest || (enable_ept && is_paging(vcpu)))
- vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
- __set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
-}
-
-static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
-{
- ulong cr4_guest_owned_bits = vcpu->arch.cr4_guest_owned_bits;
-
- vcpu->arch.cr4 &= ~cr4_guest_owned_bits;
- vcpu->arch.cr4 |= vmcs_readl(GUEST_CR4) & cr4_guest_owned_bits;
-}
-
-static void ept_load_pdptrs(struct kvm_vcpu *vcpu)
-{
- struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
-
- if (!test_bit(VCPU_EXREG_PDPTR,
- (unsigned long *)&vcpu->arch.regs_dirty))
- return;
-
- if (is_pae_paging(vcpu)) {
- vmcs_write64(GUEST_PDPTR0, mmu->pdptrs[0]);
- vmcs_write64(GUEST_PDPTR1, mmu->pdptrs[1]);
- vmcs_write64(GUEST_PDPTR2, mmu->pdptrs[2]);
- vmcs_write64(GUEST_PDPTR3, mmu->pdptrs[3]);
- }
-}
-
-static void ept_save_pdptrs(struct kvm_vcpu *vcpu)
-{
- struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
-
- if (is_pae_paging(vcpu)) {
- mmu->pdptrs[0] = vmcs_read64(GUEST_PDPTR0);
- mmu->pdptrs[1] = vmcs_read64(GUEST_PDPTR1);
- mmu->pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
- mmu->pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
- }
-
- __set_bit(VCPU_EXREG_PDPTR,
- (unsigned long *)&vcpu->arch.regs_avail);
- __set_bit(VCPU_EXREG_PDPTR,
- (unsigned long *)&vcpu->arch.regs_dirty);
-}
-
-static bool nested_guest_cr0_valid(struct kvm_vcpu *vcpu, unsigned long val)
-{
- u64 fixed0 = to_vmx(vcpu)->nested.msrs.cr0_fixed0;
- u64 fixed1 = to_vmx(vcpu)->nested.msrs.cr0_fixed1;
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
-
- if (to_vmx(vcpu)->nested.msrs.secondary_ctls_high &
- SECONDARY_EXEC_UNRESTRICTED_GUEST &&
- nested_cpu_has2(vmcs12, SECONDARY_EXEC_UNRESTRICTED_GUEST))
- fixed0 &= ~(X86_CR0_PE | X86_CR0_PG);
-
- return fixed_bits_valid(val, fixed0, fixed1);
-}
-
-static bool nested_host_cr0_valid(struct kvm_vcpu *vcpu, unsigned long val)
-{
- u64 fixed0 = to_vmx(vcpu)->nested.msrs.cr0_fixed0;
- u64 fixed1 = to_vmx(vcpu)->nested.msrs.cr0_fixed1;
-
- return fixed_bits_valid(val, fixed0, fixed1);
-}
-
-static bool nested_cr4_valid(struct kvm_vcpu *vcpu, unsigned long val)
-{
- u64 fixed0 = to_vmx(vcpu)->nested.msrs.cr4_fixed0;
- u64 fixed1 = to_vmx(vcpu)->nested.msrs.cr4_fixed1;
-
- return fixed_bits_valid(val, fixed0, fixed1);
-}
-
-/* No difference in the restrictions on guest and host CR4 in VMX operation. */
-#define nested_guest_cr4_valid nested_cr4_valid
-#define nested_host_cr4_valid nested_cr4_valid
-
-static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
-
-static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
- unsigned long cr0,
- struct kvm_vcpu *vcpu)
-{
- if (!test_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail))
- vmx_decache_cr3(vcpu);
- if (!(cr0 & X86_CR0_PG)) {
- /* From paging/starting to nonpaging */
- vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
- vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) |
- (CPU_BASED_CR3_LOAD_EXITING |
- CPU_BASED_CR3_STORE_EXITING));
- vcpu->arch.cr0 = cr0;
- vmx_set_cr4(vcpu, kvm_read_cr4(vcpu));
- } else if (!is_paging(vcpu)) {
- /* From nonpaging to paging */
- vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
- vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) &
- ~(CPU_BASED_CR3_LOAD_EXITING |
- CPU_BASED_CR3_STORE_EXITING));
- vcpu->arch.cr0 = cr0;
- vmx_set_cr4(vcpu, kvm_read_cr4(vcpu));
- }
-
- if (!(cr0 & X86_CR0_WP))
- *hw_cr0 &= ~X86_CR0_WP;
-}
-
-static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- unsigned long hw_cr0;
-
- hw_cr0 = (cr0 & ~KVM_GUEST_CR0_MASK);
- if (enable_unrestricted_guest)
- hw_cr0 |= KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST;
- else {
- hw_cr0 |= KVM_VM_CR0_ALWAYS_ON;
-
- if (vmx->rmode.vm86_active && (cr0 & X86_CR0_PE))
- enter_pmode(vcpu);
-
- if (!vmx->rmode.vm86_active && !(cr0 & X86_CR0_PE))
- enter_rmode(vcpu);
- }
-
-#ifdef CONFIG_X86_64
- if (vcpu->arch.efer & EFER_LME) {
- if (!is_paging(vcpu) && (cr0 & X86_CR0_PG))
- enter_lmode(vcpu);
- if (is_paging(vcpu) && !(cr0 & X86_CR0_PG))
- exit_lmode(vcpu);
- }
-#endif
-
- if (enable_ept && !enable_unrestricted_guest)
- ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
-
- vmcs_writel(CR0_READ_SHADOW, cr0);
- vmcs_writel(GUEST_CR0, hw_cr0);
- vcpu->arch.cr0 = cr0;
-
- /* depends on vcpu->arch.cr0 to be set to a new value */
- vmx->emulation_required = emulation_required(vcpu);
-}
-
-static int get_ept_level(struct kvm_vcpu *vcpu)
-{
- /* Nested EPT currently only supports 4-level walks. */
- if (is_guest_mode(vcpu) && nested_cpu_has_ept(get_vmcs12(vcpu)))
- return 4;
- if (cpu_has_vmx_ept_5levels() && (cpuid_maxphyaddr(vcpu) > 48))
- return 5;
- return 4;
-}
-
-static u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa)
-{
- u64 eptp = VMX_EPTP_MT_WB;
-
- eptp |= (get_ept_level(vcpu) == 5) ? VMX_EPTP_PWL_5 : VMX_EPTP_PWL_4;
-
- if (enable_ept_ad_bits &&
- (!is_guest_mode(vcpu) || nested_ept_ad_enabled(vcpu)))
- eptp |= VMX_EPTP_AD_ENABLE_BIT;
- eptp |= (root_hpa & PAGE_MASK);
-
- return eptp;
-}
-
-static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
-{
- struct kvm *kvm = vcpu->kvm;
- unsigned long guest_cr3;
- u64 eptp;
-
- guest_cr3 = cr3;
- if (enable_ept) {
- eptp = construct_eptp(vcpu, cr3);
- vmcs_write64(EPT_POINTER, eptp);
-
- if (kvm_x86_ops->tlb_remote_flush) {
- spin_lock(&to_kvm_vmx(kvm)->ept_pointer_lock);
- to_vmx(vcpu)->ept_pointer = eptp;
- to_kvm_vmx(kvm)->ept_pointers_match
- = EPT_POINTERS_CHECK;
- spin_unlock(&to_kvm_vmx(kvm)->ept_pointer_lock);
- }
-
- if (enable_unrestricted_guest || is_paging(vcpu) ||
- is_guest_mode(vcpu))
- guest_cr3 = kvm_read_cr3(vcpu);
- else
- guest_cr3 = to_kvm_vmx(kvm)->ept_identity_map_addr;
- ept_load_pdptrs(vcpu);
- }
-
- vmcs_writel(GUEST_CR3, guest_cr3);
-}
-
-static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
-{
- /*
- * Pass through host's Machine Check Enable value to hw_cr4, which
- * is in force while we are in guest mode. Do not let guests control
- * this bit, even if host CR4.MCE == 0.
- */
- unsigned long hw_cr4;
-
- hw_cr4 = (cr4_read_shadow() & X86_CR4_MCE) | (cr4 & ~X86_CR4_MCE);
- if (enable_unrestricted_guest)
- hw_cr4 |= KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST;
- else if (to_vmx(vcpu)->rmode.vm86_active)
- hw_cr4 |= KVM_RMODE_VM_CR4_ALWAYS_ON;
- else
- hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON;
-
- if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated()) {
- if (cr4 & X86_CR4_UMIP) {
- vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
- SECONDARY_EXEC_DESC);
- hw_cr4 &= ~X86_CR4_UMIP;
- } else if (!is_guest_mode(vcpu) ||
- !nested_cpu_has2(get_vmcs12(vcpu), SECONDARY_EXEC_DESC))
- vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
- SECONDARY_EXEC_DESC);
- }
-
- if (cr4 & X86_CR4_VMXE) {
- /*
- * To use VMXON (and later other VMX instructions), a guest
- * must first be able to turn on cr4.VMXE (see handle_vmon()).
- * So basically the check on whether to allow nested VMX
- * is here. We operate under the default treatment of SMM,
- * so VMX cannot be enabled under SMM.
- */
- if (!nested_vmx_allowed(vcpu) || is_smm(vcpu))
- return 1;
- }
-
- if (to_vmx(vcpu)->nested.vmxon && !nested_cr4_valid(vcpu, cr4))
- return 1;
-
- vcpu->arch.cr4 = cr4;
-
- if (!enable_unrestricted_guest) {
- if (enable_ept) {
- if (!is_paging(vcpu)) {
- hw_cr4 &= ~X86_CR4_PAE;
- hw_cr4 |= X86_CR4_PSE;
- } else if (!(cr4 & X86_CR4_PAE)) {
- hw_cr4 &= ~X86_CR4_PAE;
- }
- }
-
- /*
- * SMEP/SMAP/PKU is disabled if CPU is in non-paging mode in
- * hardware. To emulate this behavior, SMEP/SMAP/PKU needs
- * to be manually disabled when guest switches to non-paging
- * mode.
- *
- * If !enable_unrestricted_guest, the CPU is always running
- * with CR0.PG=1 and CR4 needs to be modified.
- * If enable_unrestricted_guest, the CPU automatically
- * disables SMEP/SMAP/PKU when the guest sets CR0.PG=0.
- */
- if (!is_paging(vcpu))
- hw_cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE);
- }
-
- vmcs_writel(CR4_READ_SHADOW, cr4);
- vmcs_writel(GUEST_CR4, hw_cr4);
- return 0;
-}
-
-static void vmx_get_segment(struct kvm_vcpu *vcpu,
- struct kvm_segment *var, int seg)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 ar;
-
- if (vmx->rmode.vm86_active && seg != VCPU_SREG_LDTR) {
- *var = vmx->rmode.segs[seg];
- if (seg == VCPU_SREG_TR
- || var->selector == vmx_read_guest_seg_selector(vmx, seg))
- return;
- var->base = vmx_read_guest_seg_base(vmx, seg);
- var->selector = vmx_read_guest_seg_selector(vmx, seg);
- return;
- }
- var->base = vmx_read_guest_seg_base(vmx, seg);
- var->limit = vmx_read_guest_seg_limit(vmx, seg);
- var->selector = vmx_read_guest_seg_selector(vmx, seg);
- ar = vmx_read_guest_seg_ar(vmx, seg);
- var->unusable = (ar >> 16) & 1;
- var->type = ar & 15;
- var->s = (ar >> 4) & 1;
- var->dpl = (ar >> 5) & 3;
- /*
- * Some userspaces do not preserve unusable property. Since usable
- * segment has to be present according to VMX spec we can use present
- * property to amend userspace bug by making unusable segment always
- * nonpresent. vmx_segment_access_rights() already marks nonpresent
- * segment as unusable.
- */
- var->present = !var->unusable;
- var->avl = (ar >> 12) & 1;
- var->l = (ar >> 13) & 1;
- var->db = (ar >> 14) & 1;
- var->g = (ar >> 15) & 1;
-}
-
-static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
-{
- struct kvm_segment s;
-
- if (to_vmx(vcpu)->rmode.vm86_active) {
- vmx_get_segment(vcpu, &s, seg);
- return s.base;
- }
- return vmx_read_guest_seg_base(to_vmx(vcpu), seg);
-}
-
-static int vmx_get_cpl(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (unlikely(vmx->rmode.vm86_active))
- return 0;
- else {
- int ar = vmx_read_guest_seg_ar(vmx, VCPU_SREG_SS);
- return VMX_AR_DPL(ar);
- }
-}
-
-static u32 vmx_segment_access_rights(struct kvm_segment *var)
-{
- u32 ar;
-
- if (var->unusable || !var->present)
- ar = 1 << 16;
- else {
- ar = var->type & 15;
- ar |= (var->s & 1) << 4;
- ar |= (var->dpl & 3) << 5;
- ar |= (var->present & 1) << 7;
- ar |= (var->avl & 1) << 12;
- ar |= (var->l & 1) << 13;
- ar |= (var->db & 1) << 14;
- ar |= (var->g & 1) << 15;
- }
-
- return ar;
-}
-
-static void vmx_set_segment(struct kvm_vcpu *vcpu,
- struct kvm_segment *var, int seg)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
-
- vmx_segment_cache_clear(vmx);
-
- if (vmx->rmode.vm86_active && seg != VCPU_SREG_LDTR) {
- vmx->rmode.segs[seg] = *var;
- if (seg == VCPU_SREG_TR)
- vmcs_write16(sf->selector, var->selector);
- else if (var->s)
- fix_rmode_seg(seg, &vmx->rmode.segs[seg]);
- goto out;
- }
-
- vmcs_writel(sf->base, var->base);
- vmcs_write32(sf->limit, var->limit);
- vmcs_write16(sf->selector, var->selector);
-
- /*
- * Fix the "Accessed" bit in AR field of segment registers for older
- * qemu binaries.
- * IA32 arch specifies that at the time of processor reset the
- * "Accessed" bit in the AR field of segment registers is 1. And qemu
- * is setting it to 0 in the userland code. This causes invalid guest
- * state vmexit when "unrestricted guest" mode is turned on.
- * Fix for this setup issue in cpu_reset is being pushed in the qemu
- * tree. Newer qemu binaries with that qemu fix would not need this
- * kvm hack.
- */
- if (enable_unrestricted_guest && (seg != VCPU_SREG_LDTR))
- var->type |= 0x1; /* Accessed */
-
- vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(var));
-
-out:
- vmx->emulation_required = emulation_required(vcpu);
-}
-
-static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
-{
- u32 ar = vmx_read_guest_seg_ar(to_vmx(vcpu), VCPU_SREG_CS);
-
- *db = (ar >> 14) & 1;
- *l = (ar >> 13) & 1;
-}
-
-static void vmx_get_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
-{
- dt->size = vmcs_read32(GUEST_IDTR_LIMIT);
- dt->address = vmcs_readl(GUEST_IDTR_BASE);
-}
-
-static void vmx_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
-{
- vmcs_write32(GUEST_IDTR_LIMIT, dt->size);
- vmcs_writel(GUEST_IDTR_BASE, dt->address);
-}
-
-static void vmx_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
-{
- dt->size = vmcs_read32(GUEST_GDTR_LIMIT);
- dt->address = vmcs_readl(GUEST_GDTR_BASE);
-}
-
-static void vmx_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
-{
- vmcs_write32(GUEST_GDTR_LIMIT, dt->size);
- vmcs_writel(GUEST_GDTR_BASE, dt->address);
-}
-
-static bool rmode_segment_valid(struct kvm_vcpu *vcpu, int seg)
-{
- struct kvm_segment var;
- u32 ar;
-
- vmx_get_segment(vcpu, &var, seg);
- var.dpl = 0x3;
- if (seg == VCPU_SREG_CS)
- var.type = 0x3;
- ar = vmx_segment_access_rights(&var);
-
- if (var.base != (var.selector << 4))
- return false;
- if (var.limit != 0xffff)
- return false;
- if (ar != 0xf3)
- return false;
-
- return true;
-}
-
-static bool code_segment_valid(struct kvm_vcpu *vcpu)
-{
- struct kvm_segment cs;
- unsigned int cs_rpl;
-
- vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
- cs_rpl = cs.selector & SEGMENT_RPL_MASK;
-
- if (cs.unusable)
- return false;
- if (~cs.type & (VMX_AR_TYPE_CODE_MASK|VMX_AR_TYPE_ACCESSES_MASK))
- return false;
- if (!cs.s)
- return false;
- if (cs.type & VMX_AR_TYPE_WRITEABLE_MASK) {
- if (cs.dpl > cs_rpl)
- return false;
- } else {
- if (cs.dpl != cs_rpl)
- return false;
- }
- if (!cs.present)
- return false;
-
- /* TODO: Add Reserved field check, this'll require a new member in the kvm_segment_field structure */
- return true;
-}
-
-static bool stack_segment_valid(struct kvm_vcpu *vcpu)
-{
- struct kvm_segment ss;
- unsigned int ss_rpl;
-
- vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
- ss_rpl = ss.selector & SEGMENT_RPL_MASK;
-
- if (ss.unusable)
- return true;
- if (ss.type != 3 && ss.type != 7)
- return false;
- if (!ss.s)
- return false;
- if (ss.dpl != ss_rpl) /* DPL != RPL */
- return false;
- if (!ss.present)
- return false;
-
- return true;
-}
-
-static bool data_segment_valid(struct kvm_vcpu *vcpu, int seg)
-{
- struct kvm_segment var;
- unsigned int rpl;
-
- vmx_get_segment(vcpu, &var, seg);
- rpl = var.selector & SEGMENT_RPL_MASK;
-
- if (var.unusable)
- return true;
- if (!var.s)
- return false;
- if (!var.present)
- return false;
- if (~var.type & (VMX_AR_TYPE_CODE_MASK|VMX_AR_TYPE_WRITEABLE_MASK)) {
- if (var.dpl < rpl) /* DPL < RPL */
- return false;
- }
-
- /* TODO: Add other members to kvm_segment_field to allow checking for other access
- * rights flags
- */
- return true;
-}
-
-static bool tr_valid(struct kvm_vcpu *vcpu)
-{
- struct kvm_segment tr;
-
- vmx_get_segment(vcpu, &tr, VCPU_SREG_TR);
-
- if (tr.unusable)
- return false;
- if (tr.selector & SEGMENT_TI_MASK) /* TI = 1 */
- return false;
- if (tr.type != 3 && tr.type != 11) /* TODO: Check if guest is in IA32e mode */
- return false;
- if (!tr.present)
- return false;
-
- return true;
-}
-
-static bool ldtr_valid(struct kvm_vcpu *vcpu)
-{
- struct kvm_segment ldtr;
-
- vmx_get_segment(vcpu, &ldtr, VCPU_SREG_LDTR);
-
- if (ldtr.unusable)
- return true;
- if (ldtr.selector & SEGMENT_TI_MASK) /* TI = 1 */
- return false;
- if (ldtr.type != 2)
- return false;
- if (!ldtr.present)
- return false;
-
- return true;
-}
-
-static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
-{
- struct kvm_segment cs, ss;
-
- vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
- vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
-
- return ((cs.selector & SEGMENT_RPL_MASK) ==
- (ss.selector & SEGMENT_RPL_MASK));
-}
-
-static bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu,
- unsigned int port, int size);
-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- unsigned long exit_qualification;
- unsigned short port;
- int size;
-
- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
- return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- port = exit_qualification >> 16;
- size = (exit_qualification & 7) + 1;
-
- return nested_vmx_check_io_bitmaps(vcpu, port, size);
-}
-
-/*
- * Check if guest state is valid. Returns true if valid, false if
- * not.
- * We assume that registers are always usable
- */
-static bool guest_state_valid(struct kvm_vcpu *vcpu)
-{
- if (enable_unrestricted_guest)
- return true;
-
- /* real mode guest state checks */
- if (!is_protmode(vcpu) || (vmx_get_rflags(vcpu) & X86_EFLAGS_VM)) {
- if (!rmode_segment_valid(vcpu, VCPU_SREG_CS))
- return false;
- if (!rmode_segment_valid(vcpu, VCPU_SREG_SS))
- return false;
- if (!rmode_segment_valid(vcpu, VCPU_SREG_DS))
- return false;
- if (!rmode_segment_valid(vcpu, VCPU_SREG_ES))
- return false;
- if (!rmode_segment_valid(vcpu, VCPU_SREG_FS))
- return false;
- if (!rmode_segment_valid(vcpu, VCPU_SREG_GS))
- return false;
- } else {
- /* protected mode guest state checks */
- if (!cs_ss_rpl_check(vcpu))
- return false;
- if (!code_segment_valid(vcpu))
- return false;
- if (!stack_segment_valid(vcpu))
- return false;
- if (!data_segment_valid(vcpu, VCPU_SREG_DS))
- return false;
- if (!data_segment_valid(vcpu, VCPU_SREG_ES))
- return false;
- if (!data_segment_valid(vcpu, VCPU_SREG_FS))
- return false;
- if (!data_segment_valid(vcpu, VCPU_SREG_GS))
- return false;
- if (!tr_valid(vcpu))
- return false;
- if (!ldtr_valid(vcpu))
- return false;
- }
- /* TODO:
- * - Add checks on RIP
- * - Add checks on RFLAGS
- */
-
- return true;
-}
-
-static bool page_address_valid(struct kvm_vcpu *vcpu, gpa_t gpa)
-{
- return PAGE_ALIGNED(gpa) && !(gpa >> cpuid_maxphyaddr(vcpu));
-}
-
-static int init_rmode_tss(struct kvm *kvm)
-{
- gfn_t fn;
- u16 data = 0;
- int idx, r;
-
- idx = srcu_read_lock(&kvm->srcu);
- fn = to_kvm_vmx(kvm)->tss_addr >> PAGE_SHIFT;
- r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
- if (r < 0)
- goto out;
- data = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE;
- r = kvm_write_guest_page(kvm, fn++, &data,
- TSS_IOPB_BASE_OFFSET, sizeof(u16));
- if (r < 0)
- goto out;
- r = kvm_clear_guest_page(kvm, fn++, 0, PAGE_SIZE);
- if (r < 0)
- goto out;
- r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
- if (r < 0)
- goto out;
- data = ~0;
- r = kvm_write_guest_page(kvm, fn, &data,
- RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1,
- sizeof(u8));
-out:
- srcu_read_unlock(&kvm->srcu, idx);
- return r;
-}
-
-static int init_rmode_identity_map(struct kvm *kvm)
-{
- struct kvm_vmx *kvm_vmx = to_kvm_vmx(kvm);
- int i, idx, r = 0;
- kvm_pfn_t identity_map_pfn;
- u32 tmp;
-
- /* Protect kvm_vmx->ept_identity_pagetable_done. */
- mutex_lock(&kvm->slots_lock);
-
- if (likely(kvm_vmx->ept_identity_pagetable_done))
- goto out2;
-
- if (!kvm_vmx->ept_identity_map_addr)
- kvm_vmx->ept_identity_map_addr = VMX_EPT_IDENTITY_PAGETABLE_ADDR;
- identity_map_pfn = kvm_vmx->ept_identity_map_addr >> PAGE_SHIFT;
-
- r = __x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT,
- kvm_vmx->ept_identity_map_addr, PAGE_SIZE);
- if (r < 0)
- goto out2;
-
- idx = srcu_read_lock(&kvm->srcu);
- r = kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE);
- if (r < 0)
- goto out;
- /* Set up identity-mapping pagetable for EPT in real mode */
- for (i = 0; i < PT32_ENT_PER_PAGE; i++) {
- tmp = (i << 22) + (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |
- _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE);
- r = kvm_write_guest_page(kvm, identity_map_pfn,
- &tmp, i * sizeof(tmp), sizeof(tmp));
- if (r < 0)
- goto out;
- }
- kvm_vmx->ept_identity_pagetable_done = true;
-
-out:
- srcu_read_unlock(&kvm->srcu, idx);
-
-out2:
- mutex_unlock(&kvm->slots_lock);
- return r;
-}
-
-static void seg_setup(int seg)
-{
- const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
- unsigned int ar;
-
- vmcs_write16(sf->selector, 0);
- vmcs_writel(sf->base, 0);
- vmcs_write32(sf->limit, 0xffff);
- ar = 0x93;
- if (seg == VCPU_SREG_CS)
- ar |= 0x08; /* code segment */
-
- vmcs_write32(sf->ar_bytes, ar);
-}
-
-static int alloc_apic_access_page(struct kvm *kvm)
-{
- struct page *page;
- int r = 0;
-
- mutex_lock(&kvm->slots_lock);
- if (kvm->arch.apic_access_page_done)
- goto out;
- r = __x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
- APIC_DEFAULT_PHYS_BASE, PAGE_SIZE);
- if (r)
- goto out;
-
- page = gfn_to_page(kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
- if (is_error_page(page)) {
- r = -EFAULT;
- goto out;
- }
-
- /*
- * Do not pin the page in memory, so that memory hot-unplug
- * is able to migrate it.
- */
- put_page(page);
- kvm->arch.apic_access_page_done = true;
-out:
- mutex_unlock(&kvm->slots_lock);
- return r;
-}
-
-static int allocate_vpid(void)
-{
- int vpid;
-
- if (!enable_vpid)
- return 0;
- spin_lock(&vmx_vpid_lock);
- vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
- if (vpid < VMX_NR_VPIDS)
- __set_bit(vpid, vmx_vpid_bitmap);
- else
- vpid = 0;
- spin_unlock(&vmx_vpid_lock);
- return vpid;
-}
-
-static void free_vpid(int vpid)
-{
- if (!enable_vpid || vpid == 0)
- return;
- spin_lock(&vmx_vpid_lock);
- __clear_bit(vpid, vmx_vpid_bitmap);
- spin_unlock(&vmx_vpid_lock);
-}
-
-static __always_inline void vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
- u32 msr, int type)
-{
- int f = sizeof(unsigned long);
-
- if (!cpu_has_vmx_msr_bitmap())
- return;
-
- if (static_branch_unlikely(&enable_evmcs))
- evmcs_touch_msr_bitmap();
-
- /*
- * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
- * have the write-low and read-high bitmap offsets the wrong way round.
- * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
- */
- if (msr <= 0x1fff) {
- if (type & MSR_TYPE_R)
- /* read-low */
- __clear_bit(msr, msr_bitmap + 0x000 / f);
-
- if (type & MSR_TYPE_W)
- /* write-low */
- __clear_bit(msr, msr_bitmap + 0x800 / f);
-
- } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
- msr &= 0x1fff;
- if (type & MSR_TYPE_R)
- /* read-high */
- __clear_bit(msr, msr_bitmap + 0x400 / f);
-
- if (type & MSR_TYPE_W)
- /* write-high */
- __clear_bit(msr, msr_bitmap + 0xc00 / f);
-
- }
-}
-
-static __always_inline void vmx_enable_intercept_for_msr(unsigned long *msr_bitmap,
- u32 msr, int type)
-{
- int f = sizeof(unsigned long);
-
- if (!cpu_has_vmx_msr_bitmap())
- return;
-
- if (static_branch_unlikely(&enable_evmcs))
- evmcs_touch_msr_bitmap();
-
- /*
- * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
- * have the write-low and read-high bitmap offsets the wrong way round.
- * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
- */
- if (msr <= 0x1fff) {
- if (type & MSR_TYPE_R)
- /* read-low */
- __set_bit(msr, msr_bitmap + 0x000 / f);
-
- if (type & MSR_TYPE_W)
- /* write-low */
- __set_bit(msr, msr_bitmap + 0x800 / f);
-
- } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
- msr &= 0x1fff;
- if (type & MSR_TYPE_R)
- /* read-high */
- __set_bit(msr, msr_bitmap + 0x400 / f);
-
- if (type & MSR_TYPE_W)
- /* write-high */
- __set_bit(msr, msr_bitmap + 0xc00 / f);
-
- }
-}
-
-static __always_inline void vmx_set_intercept_for_msr(unsigned long *msr_bitmap,
- u32 msr, int type, bool value)
-{
- if (value)
- vmx_enable_intercept_for_msr(msr_bitmap, msr, type);
- else
- vmx_disable_intercept_for_msr(msr_bitmap, msr, type);
-}
-
-/*
- * If a msr is allowed by L0, we should check whether it is allowed by L1.
- * The corresponding bit will be cleared unless both of L0 and L1 allow it.
- */
-static void nested_vmx_disable_intercept_for_msr(unsigned long *msr_bitmap_l1,
- unsigned long *msr_bitmap_nested,
- u32 msr, int type)
-{
- int f = sizeof(unsigned long);
-
- /*
- * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
- * have the write-low and read-high bitmap offsets the wrong way round.
- * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
- */
- if (msr <= 0x1fff) {
- if (type & MSR_TYPE_R &&
- !test_bit(msr, msr_bitmap_l1 + 0x000 / f))
- /* read-low */
- __clear_bit(msr, msr_bitmap_nested + 0x000 / f);
-
- if (type & MSR_TYPE_W &&
- !test_bit(msr, msr_bitmap_l1 + 0x800 / f))
- /* write-low */
- __clear_bit(msr, msr_bitmap_nested + 0x800 / f);
-
- } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
- msr &= 0x1fff;
- if (type & MSR_TYPE_R &&
- !test_bit(msr, msr_bitmap_l1 + 0x400 / f))
- /* read-high */
- __clear_bit(msr, msr_bitmap_nested + 0x400 / f);
-
- if (type & MSR_TYPE_W &&
- !test_bit(msr, msr_bitmap_l1 + 0xc00 / f))
- /* write-high */
- __clear_bit(msr, msr_bitmap_nested + 0xc00 / f);
-
- }
-}
-
-static u8 vmx_msr_bitmap_mode(struct kvm_vcpu *vcpu)
-{
- u8 mode = 0;
-
- if (cpu_has_secondary_exec_ctrls() &&
- (vmcs_read32(SECONDARY_VM_EXEC_CONTROL) &
- SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
- mode |= MSR_BITMAP_MODE_X2APIC;
- if (enable_apicv && kvm_vcpu_apicv_active(vcpu))
- mode |= MSR_BITMAP_MODE_X2APIC_APICV;
- }
-
- return mode;
-}
-
-#define X2APIC_MSR(r) (APIC_BASE_MSR + ((r) >> 4))
-
-static void vmx_update_msr_bitmap_x2apic(unsigned long *msr_bitmap,
- u8 mode)
-{
- int msr;
-
- for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
- unsigned word = msr / BITS_PER_LONG;
- msr_bitmap[word] = (mode & MSR_BITMAP_MODE_X2APIC_APICV) ? 0 : ~0;
- msr_bitmap[word + (0x800 / sizeof(long))] = ~0;
- }
-
- if (mode & MSR_BITMAP_MODE_X2APIC) {
- /*
- * TPR reads and writes can be virtualized even if virtual interrupt
- * delivery is not in use.
- */
- vmx_disable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_TASKPRI), MSR_TYPE_RW);
- if (mode & MSR_BITMAP_MODE_X2APIC_APICV) {
- vmx_enable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_TMCCT), MSR_TYPE_R);
- vmx_disable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_EOI), MSR_TYPE_W);
- vmx_disable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_SELF_IPI), MSR_TYPE_W);
- }
- }
-}
-
-static void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- unsigned long *msr_bitmap = vmx->vmcs01.msr_bitmap;
- u8 mode = vmx_msr_bitmap_mode(vcpu);
- u8 changed = mode ^ vmx->msr_bitmap_mode;
-
- if (!changed)
- return;
-
- if (changed & (MSR_BITMAP_MODE_X2APIC | MSR_BITMAP_MODE_X2APIC_APICV))
- vmx_update_msr_bitmap_x2apic(msr_bitmap, mode);
-
- vmx->msr_bitmap_mode = mode;
-}
-
-static bool vmx_get_enable_apicv(struct kvm_vcpu *vcpu)
-{
- return enable_apicv;
-}
-
-static void nested_mark_vmcs12_pages_dirty(struct kvm_vcpu *vcpu)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- gfn_t gfn;
-
- /*
- * Don't need to mark the APIC access page dirty; it is never
- * written to by the CPU during APIC virtualization.
- */
-
- if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
- gfn = vmcs12->virtual_apic_page_addr >> PAGE_SHIFT;
- kvm_vcpu_mark_page_dirty(vcpu, gfn);
- }
-
- if (nested_cpu_has_posted_intr(vmcs12)) {
- gfn = vmcs12->posted_intr_desc_addr >> PAGE_SHIFT;
- kvm_vcpu_mark_page_dirty(vcpu, gfn);
- }
-}
-
-
-static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int max_irr;
- void *vapic_page;
- u16 status;
-
- if (!vmx->nested.pi_desc || !vmx->nested.pi_pending)
- return;
-
- vmx->nested.pi_pending = false;
- if (!pi_test_and_clear_on(vmx->nested.pi_desc))
- return;
-
- max_irr = find_last_bit((unsigned long *)vmx->nested.pi_desc->pir, 256);
- if (max_irr != 256) {
- vapic_page = kmap(vmx->nested.virtual_apic_page);
- __kvm_apic_update_irr(vmx->nested.pi_desc->pir,
- vapic_page, &max_irr);
- kunmap(vmx->nested.virtual_apic_page);
-
- status = vmcs_read16(GUEST_INTR_STATUS);
- if ((u8)max_irr > ((u8)status & 0xff)) {
- status &= ~0xff;
- status |= (u8)max_irr;
- vmcs_write16(GUEST_INTR_STATUS, status);
- }
- }
-
- nested_mark_vmcs12_pages_dirty(vcpu);
-}
-
-static u8 vmx_get_rvi(void)
-{
- return vmcs_read16(GUEST_INTR_STATUS) & 0xff;
-}
-
-static bool vmx_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- void *vapic_page;
- u32 vppr;
- int rvi;
-
- if (WARN_ON_ONCE(!is_guest_mode(vcpu)) ||
- !nested_cpu_has_vid(get_vmcs12(vcpu)) ||
- WARN_ON_ONCE(!vmx->nested.virtual_apic_page))
- return false;
-
- rvi = vmx_get_rvi();
-
- vapic_page = kmap(vmx->nested.virtual_apic_page);
- vppr = *((u32 *)(vapic_page + APIC_PROCPRI));
- kunmap(vmx->nested.virtual_apic_page);
-
- return ((rvi & 0xf0) > (vppr & 0xf0));
-}
-
-static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
- bool nested)
-{
-#ifdef CONFIG_SMP
- int pi_vec = nested ? POSTED_INTR_NESTED_VECTOR : POSTED_INTR_VECTOR;
-
- if (vcpu->mode == IN_GUEST_MODE) {
- /*
- * The vector of interrupt to be delivered to vcpu had
- * been set in PIR before this function.
- *
- * Following cases will be reached in this block, and
- * we always send a notification event in all cases as
- * explained below.
- *
- * Case 1: vcpu keeps in non-root mode. Sending a
- * notification event posts the interrupt to vcpu.
- *
- * Case 2: vcpu exits to root mode and is still
- * runnable. PIR will be synced to vIRR before the
- * next vcpu entry. Sending a notification event in
- * this case has no effect, as vcpu is not in root
- * mode.
- *
- * Case 3: vcpu exits to root mode and is blocked.
- * vcpu_block() has already synced PIR to vIRR and
- * never blocks vcpu if vIRR is not cleared. Therefore,
- * a blocked vcpu here does not wait for any requested
- * interrupts in PIR, and sending a notification event
- * which has no effect is safe here.
- */
-
- apic->send_IPI_mask(get_cpu_mask(vcpu->cpu), pi_vec);
- return true;
- }
-#endif
- return false;
-}
-
-static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu,
- int vector)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (is_guest_mode(vcpu) &&
- vector == vmx->nested.posted_intr_nv) {
- /*
- * If a posted intr is not recognized by hardware,
- * we will accomplish it in the next vmentry.
- */
- vmx->nested.pi_pending = true;
- kvm_make_request(KVM_REQ_EVENT, vcpu);
- /* the PIR and ON have been set by L1. */
- if (!kvm_vcpu_trigger_posted_interrupt(vcpu, true))
- kvm_vcpu_kick(vcpu);
- return 0;
- }
- return -1;
-}
-/*
- * Send interrupt to vcpu via posted interrupt way.
- * 1. If target vcpu is running(non-root mode), send posted interrupt
- * notification to vcpu and hardware will sync PIR to vIRR atomically.
- * 2. If target vcpu isn't running(root mode), kick it to pick up the
- * interrupt from PIR in next vmentry.
- */
-static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int r;
-
- r = vmx_deliver_nested_posted_interrupt(vcpu, vector);
- if (!r)
- return 0;
-
- if (!vcpu->arch.apicv_active)
- return -1;
-
- if (pi_test_and_set_pir(vector, &vmx->pi_desc))
- return 0;
-
- /* If a previous notification has sent the IPI, nothing to do. */
- if (pi_test_and_set_on(&vmx->pi_desc))
- return 0;
-
- if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false))
- kvm_vcpu_kick(vcpu);
-
- return 0;
-}
-
-/*
- * Set up the vmcs's constant host-state fields, i.e., host-state fields that
- * will not change in the lifetime of the guest.
- * Note that host-state that does change is set elsewhere. E.g., host-state
- * that is set differently for each CPU is set in vmx_vcpu_load(), not here.
- */
-static void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
-{
- u32 low32, high32;
- unsigned long tmpl;
- struct desc_ptr dt;
- unsigned long cr0, cr3, cr4;
-
- cr0 = read_cr0();
- WARN_ON(cr0 & X86_CR0_TS);
- vmcs_writel(HOST_CR0, cr0); /* 22.2.3 */
-
- /*
- * Save the most likely value for this task's CR3 in the VMCS.
- * We can't use __get_current_cr3_fast() because we're not atomic.
- */
- cr3 = __read_cr3();
- vmcs_writel(HOST_CR3, cr3); /* 22.2.3 FIXME: shadow tables */
- vmx->loaded_vmcs->host_state.cr3 = cr3;
-
- /* Save the most likely value for this task's CR4 in the VMCS. */
- cr4 = cr4_read_shadow();
- vmcs_writel(HOST_CR4, cr4); /* 22.2.3, 22.2.5 */
- vmx->loaded_vmcs->host_state.cr4 = cr4;
-
- vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
-#ifdef CONFIG_X86_64
- /*
- * Load null selectors, so we can avoid reloading them in
- * vmx_prepare_switch_to_host(), in case userspace uses
- * the null selectors too (the expected case).
- */
- vmcs_write16(HOST_DS_SELECTOR, 0);
- vmcs_write16(HOST_ES_SELECTOR, 0);
-#else
- vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
- vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
-#endif
- vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
- vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8); /* 22.2.4 */
-
- store_idt(&dt);
- vmcs_writel(HOST_IDTR_BASE, dt.address); /* 22.2.4 */
- vmx->host_idt_base = dt.address;
-
- vmcs_writel(HOST_RIP, vmx_return); /* 22.2.5 */
-
- rdmsr(MSR_IA32_SYSENTER_CS, low32, high32);
- vmcs_write32(HOST_IA32_SYSENTER_CS, low32);
- rdmsrl(MSR_IA32_SYSENTER_EIP, tmpl);
- vmcs_writel(HOST_IA32_SYSENTER_EIP, tmpl); /* 22.2.3 */
-
- if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
- rdmsr(MSR_IA32_CR_PAT, low32, high32);
- vmcs_write64(HOST_IA32_PAT, low32 | ((u64) high32 << 32));
- }
-}
-
-static void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
-{
- BUILD_BUG_ON(KVM_CR4_GUEST_OWNED_BITS & ~KVM_POSSIBLE_CR4_GUEST_BITS);
-
- vmx->vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
- if (enable_ept)
- vmx->vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
- if (is_guest_mode(&vmx->vcpu))
- vmx->vcpu.arch.cr4_guest_owned_bits &=
- ~get_vmcs12(&vmx->vcpu)->cr4_guest_host_mask;
- vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx->vcpu.arch.cr4_guest_owned_bits);
-}
-
-static u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx)
-{
- u32 pin_based_exec_ctrl = vmcs_config.pin_based_exec_ctrl;
-
- if (!kvm_vcpu_apicv_active(&vmx->vcpu))
- pin_based_exec_ctrl &= ~PIN_BASED_POSTED_INTR;
-
- if (!enable_vnmi)
- pin_based_exec_ctrl &= ~PIN_BASED_VIRTUAL_NMIS;
-
- /* Enable the preemption timer dynamically */
- pin_based_exec_ctrl &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
- return pin_based_exec_ctrl;
-}
-
-static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_ctrl(vmx));
- if (cpu_has_secondary_exec_ctrls()) {
- if (kvm_vcpu_apicv_active(vcpu))
- vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
- SECONDARY_EXEC_APIC_REGISTER_VIRT |
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
- else
- vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
- SECONDARY_EXEC_APIC_REGISTER_VIRT |
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
- }
-
- if (cpu_has_vmx_msr_bitmap())
- vmx_update_msr_bitmap(vcpu);
-}
-
-static u32 vmx_exec_control(struct vcpu_vmx *vmx)
-{
- u32 exec_control = vmcs_config.cpu_based_exec_ctrl;
-
- if (vmx->vcpu.arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)
- exec_control &= ~CPU_BASED_MOV_DR_EXITING;
-
- if (!cpu_need_tpr_shadow(&vmx->vcpu)) {
- exec_control &= ~CPU_BASED_TPR_SHADOW;
-#ifdef CONFIG_X86_64
- exec_control |= CPU_BASED_CR8_STORE_EXITING |
- CPU_BASED_CR8_LOAD_EXITING;
-#endif
- }
- if (!enable_ept)
- exec_control |= CPU_BASED_CR3_STORE_EXITING |
- CPU_BASED_CR3_LOAD_EXITING |
- CPU_BASED_INVLPG_EXITING;
- if (kvm_mwait_in_guest(vmx->vcpu.kvm))
- exec_control &= ~(CPU_BASED_MWAIT_EXITING |
- CPU_BASED_MONITOR_EXITING);
- if (kvm_hlt_in_guest(vmx->vcpu.kvm))
- exec_control &= ~CPU_BASED_HLT_EXITING;
- return exec_control;
-}
-
-static bool vmx_rdrand_supported(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_RDRAND_EXITING;
-}
-
-static bool vmx_rdseed_supported(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_RDSEED_EXITING;
-}
-
-static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
-{
- struct kvm_vcpu *vcpu = &vmx->vcpu;
-
- u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
-
- if (!cpu_need_virtualize_apic_accesses(vcpu))
- exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
- if (vmx->vpid == 0)
- exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
- if (!enable_ept) {
- exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
- enable_unrestricted_guest = 0;
- }
- if (!enable_unrestricted_guest)
- exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
- if (kvm_pause_in_guest(vmx->vcpu.kvm))
- exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
- if (!kvm_vcpu_apicv_active(vcpu))
- exec_control &= ~(SECONDARY_EXEC_APIC_REGISTER_VIRT |
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
- exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
-
- /* SECONDARY_EXEC_DESC is enabled/disabled on writes to CR4.UMIP,
- * in vmx_set_cr4. */
- exec_control &= ~SECONDARY_EXEC_DESC;
-
- /* SECONDARY_EXEC_SHADOW_VMCS is enabled when L1 executes VMPTRLD
- (handle_vmptrld).
- We can NOT enable shadow_vmcs here because we don't have yet
- a current VMCS12
- */
- exec_control &= ~SECONDARY_EXEC_SHADOW_VMCS;
-
- if (!enable_pml)
- exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
-
- if (vmx_xsaves_supported()) {
- /* Exposing XSAVES only when XSAVE is exposed */
- bool xsaves_enabled =
- guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
- guest_cpuid_has(vcpu, X86_FEATURE_XSAVES);
-
- if (!xsaves_enabled)
- exec_control &= ~SECONDARY_EXEC_XSAVES;
-
- if (nested) {
- if (xsaves_enabled)
- vmx->nested.msrs.secondary_ctls_high |=
- SECONDARY_EXEC_XSAVES;
- else
- vmx->nested.msrs.secondary_ctls_high &=
- ~SECONDARY_EXEC_XSAVES;
- }
- }
-
- if (vmx_rdtscp_supported()) {
- bool rdtscp_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP);
- if (!rdtscp_enabled)
- exec_control &= ~SECONDARY_EXEC_RDTSCP;
-
- if (nested) {
- if (rdtscp_enabled)
- vmx->nested.msrs.secondary_ctls_high |=
- SECONDARY_EXEC_RDTSCP;
- else
- vmx->nested.msrs.secondary_ctls_high &=
- ~SECONDARY_EXEC_RDTSCP;
- }
- }
-
- if (vmx_invpcid_supported()) {
- /* Exposing INVPCID only when PCID is exposed */
- bool invpcid_enabled =
- guest_cpuid_has(vcpu, X86_FEATURE_INVPCID) &&
- guest_cpuid_has(vcpu, X86_FEATURE_PCID);
-
- if (!invpcid_enabled) {
- exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
- guest_cpuid_clear(vcpu, X86_FEATURE_INVPCID);
- }
-
- if (nested) {
- if (invpcid_enabled)
- vmx->nested.msrs.secondary_ctls_high |=
- SECONDARY_EXEC_ENABLE_INVPCID;
- else
- vmx->nested.msrs.secondary_ctls_high &=
- ~SECONDARY_EXEC_ENABLE_INVPCID;
- }
- }
-
- if (vmx_rdrand_supported()) {
- bool rdrand_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDRAND);
- if (rdrand_enabled)
- exec_control &= ~SECONDARY_EXEC_RDRAND_EXITING;
-
- if (nested) {
- if (rdrand_enabled)
- vmx->nested.msrs.secondary_ctls_high |=
- SECONDARY_EXEC_RDRAND_EXITING;
- else
- vmx->nested.msrs.secondary_ctls_high &=
- ~SECONDARY_EXEC_RDRAND_EXITING;
- }
- }
-
- if (vmx_rdseed_supported()) {
- bool rdseed_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDSEED);
- if (rdseed_enabled)
- exec_control &= ~SECONDARY_EXEC_RDSEED_EXITING;
-
- if (nested) {
- if (rdseed_enabled)
- vmx->nested.msrs.secondary_ctls_high |=
- SECONDARY_EXEC_RDSEED_EXITING;
- else
- vmx->nested.msrs.secondary_ctls_high &=
- ~SECONDARY_EXEC_RDSEED_EXITING;
- }
- }
-
- vmx->secondary_exec_control = exec_control;
-}
-
-static void ept_set_mmio_spte_mask(void)
-{
- /*
- * EPT Misconfigurations can be generated if the value of bits 2:0
- * of an EPT paging-structure entry is 110b (write/execute).
- */
- kvm_mmu_set_mmio_spte_mask(VMX_EPT_RWX_MASK,
- VMX_EPT_MISCONFIG_WX_VALUE);
-}
-
-#define VMX_XSS_EXIT_BITMAP 0
-/*
- * Sets up the vmcs for emulated real mode.
- */
-static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
-{
- int i;
-
- if (enable_shadow_vmcs) {
- /*
- * At vCPU creation, "VMWRITE to any supported field
- * in the VMCS" is supported, so use the more
- * permissive vmx_vmread_bitmap to specify both read
- * and write permissions for the shadow VMCS.
- */
- vmcs_write64(VMREAD_BITMAP, __pa(vmx_vmread_bitmap));
- vmcs_write64(VMWRITE_BITMAP, __pa(vmx_vmread_bitmap));
- }
- if (cpu_has_vmx_msr_bitmap())
- vmcs_write64(MSR_BITMAP, __pa(vmx->vmcs01.msr_bitmap));
-
- vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
-
- /* Control */
- vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_ctrl(vmx));
- vmx->hv_deadline_tsc = -1;
-
- vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, vmx_exec_control(vmx));
-
- if (cpu_has_secondary_exec_ctrls()) {
- vmx_compute_secondary_exec_control(vmx);
- vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
- vmx->secondary_exec_control);
- }
-
- if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
- vmcs_write64(EOI_EXIT_BITMAP0, 0);
- vmcs_write64(EOI_EXIT_BITMAP1, 0);
- vmcs_write64(EOI_EXIT_BITMAP2, 0);
- vmcs_write64(EOI_EXIT_BITMAP3, 0);
-
- vmcs_write16(GUEST_INTR_STATUS, 0);
-
- vmcs_write16(POSTED_INTR_NV, POSTED_INTR_VECTOR);
- vmcs_write64(POSTED_INTR_DESC_ADDR, __pa((&vmx->pi_desc)));
- }
-
- if (!kvm_pause_in_guest(vmx->vcpu.kvm)) {
- vmcs_write32(PLE_GAP, ple_gap);
- vmx->ple_window = ple_window;
- vmx->ple_window_dirty = true;
- }
-
- vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
- vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
- vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */
-
- vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */
- vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */
- vmx_set_constant_host_state(vmx);
- vmcs_writel(HOST_FS_BASE, 0); /* 22.2.4 */
- vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */
-
- if (cpu_has_vmx_vmfunc())
- vmcs_write64(VM_FUNCTION_CONTROL, 0);
-
- vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
- vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0);
- vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host.val));
- vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0);
- vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest.val));
-
- if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT)
- vmcs_write64(GUEST_IA32_PAT, vmx->vcpu.arch.pat);
-
- for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i) {
- u32 index = vmx_msr_index[i];
- u32 data_low, data_high;
- int j = vmx->nmsrs;
-
- if (rdmsr_safe(index, &data_low, &data_high) < 0)
- continue;
- if (wrmsr_safe(index, data_low, data_high) < 0)
- continue;
- vmx->guest_msrs[j].index = i;
- vmx->guest_msrs[j].data = 0;
- vmx->guest_msrs[j].mask = -1ull;
- ++vmx->nmsrs;
- }
-
- vm_exit_controls_init(vmx, vmcs_config.vmexit_ctrl);
-
- /* 22.2.1, 20.8.1 */
- vm_entry_controls_init(vmx, vmcs_config.vmentry_ctrl);
-
- vmx->vcpu.arch.cr0_guest_owned_bits = X86_CR0_TS;
- vmcs_writel(CR0_GUEST_HOST_MASK, ~X86_CR0_TS);
-
- set_cr4_guest_host_mask(vmx);
-
- if (vmx_xsaves_supported())
- vmcs_write64(XSS_EXIT_BITMAP, VMX_XSS_EXIT_BITMAP);
-
- if (enable_pml) {
- ASSERT(vmx->pml_pg);
- vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
- vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
- }
-
- if (cpu_has_vmx_encls_vmexit())
- vmcs_write64(ENCLS_EXITING_BITMAP, -1ull);
-}
-
-static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct msr_data apic_base_msr;
- u64 cr0;
-
- vmx->rmode.vm86_active = 0;
- vmx->spec_ctrl = 0;
-
- vcpu->arch.microcode_version = 0x100000000ULL;
- vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
- kvm_set_cr8(vcpu, 0);
-
- if (!init_event) {
- apic_base_msr.data = APIC_DEFAULT_PHYS_BASE |
- MSR_IA32_APICBASE_ENABLE;
- if (kvm_vcpu_is_reset_bsp(vcpu))
- apic_base_msr.data |= MSR_IA32_APICBASE_BSP;
- apic_base_msr.host_initiated = true;
- kvm_set_apic_base(vcpu, &apic_base_msr);
- }
-
- vmx_segment_cache_clear(vmx);
-
- seg_setup(VCPU_SREG_CS);
- vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
- vmcs_writel(GUEST_CS_BASE, 0xffff0000ul);
-
- seg_setup(VCPU_SREG_DS);
- seg_setup(VCPU_SREG_ES);
- seg_setup(VCPU_SREG_FS);
- seg_setup(VCPU_SREG_GS);
- seg_setup(VCPU_SREG_SS);
-
- vmcs_write16(GUEST_TR_SELECTOR, 0);
- vmcs_writel(GUEST_TR_BASE, 0);
- vmcs_write32(GUEST_TR_LIMIT, 0xffff);
- vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
-
- vmcs_write16(GUEST_LDTR_SELECTOR, 0);
- vmcs_writel(GUEST_LDTR_BASE, 0);
- vmcs_write32(GUEST_LDTR_LIMIT, 0xffff);
- vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082);
-
- if (!init_event) {
- vmcs_write32(GUEST_SYSENTER_CS, 0);
- vmcs_writel(GUEST_SYSENTER_ESP, 0);
- vmcs_writel(GUEST_SYSENTER_EIP, 0);
- vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
- }
-
- kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
- kvm_rip_write(vcpu, 0xfff0);
-
- vmcs_writel(GUEST_GDTR_BASE, 0);
- vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
-
- vmcs_writel(GUEST_IDTR_BASE, 0);
- vmcs_write32(GUEST_IDTR_LIMIT, 0xffff);
-
- vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
- vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
- vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, 0);
- if (kvm_mpx_supported())
- vmcs_write64(GUEST_BNDCFGS, 0);
-
- setup_msrs(vmx);
-
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */
-
- if (cpu_has_vmx_tpr_shadow() && !init_event) {
- vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
- if (cpu_need_tpr_shadow(vcpu))
- vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
- __pa(vcpu->arch.apic->regs));
- vmcs_write32(TPR_THRESHOLD, 0);
- }
-
- kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
-
- if (vmx->vpid != 0)
- vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
-
- cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
- vmx->vcpu.arch.cr0 = cr0;
- vmx_set_cr0(vcpu, cr0); /* enter rmode */
- vmx_set_cr4(vcpu, 0);
- vmx_set_efer(vcpu, 0);
-
- update_exception_bitmap(vcpu);
-
- vpid_sync_context(vmx->vpid);
- if (init_event)
- vmx_clear_hlt(vcpu);
-
- vmx_update_fb_clear_dis(vcpu, vmx);
-}
-
-/*
- * In nested virtualization, check if L1 asked to exit on external interrupts.
- * For most existing hypervisors, this will always return true.
- */
-static bool nested_exit_on_intr(struct kvm_vcpu *vcpu)
-{
- return get_vmcs12(vcpu)->pin_based_vm_exec_control &
- PIN_BASED_EXT_INTR_MASK;
-}
-
-/*
- * In nested virtualization, check if L1 has set
- * VM_EXIT_ACK_INTR_ON_EXIT
- */
-static bool nested_exit_intr_ack_set(struct kvm_vcpu *vcpu)
-{
- return get_vmcs12(vcpu)->vm_exit_controls &
- VM_EXIT_ACK_INTR_ON_EXIT;
-}
-
-static bool nested_exit_on_nmi(struct kvm_vcpu *vcpu)
-{
- return nested_cpu_has_nmi_exiting(get_vmcs12(vcpu));
-}
-
-static void enable_irq_window(struct kvm_vcpu *vcpu)
-{
- vmcs_set_bits(CPU_BASED_VM_EXEC_CONTROL,
- CPU_BASED_VIRTUAL_INTR_PENDING);
-}
-
-static void enable_nmi_window(struct kvm_vcpu *vcpu)
-{
- if (!enable_vnmi ||
- vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) {
- enable_irq_window(vcpu);
- return;
- }
-
- vmcs_set_bits(CPU_BASED_VM_EXEC_CONTROL,
- CPU_BASED_VIRTUAL_NMI_PENDING);
-}
-
-static void vmx_inject_irq(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- uint32_t intr;
- int irq = vcpu->arch.interrupt.nr;
-
- trace_kvm_inj_virq(irq);
-
- ++vcpu->stat.irq_injections;
- if (vmx->rmode.vm86_active) {
- int inc_eip = 0;
- if (vcpu->arch.interrupt.soft)
- inc_eip = vcpu->arch.event_exit_inst_len;
- if (kvm_inject_realmode_interrupt(vcpu, irq, inc_eip) != EMULATE_DONE)
- kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
- return;
- }
- intr = irq | INTR_INFO_VALID_MASK;
- if (vcpu->arch.interrupt.soft) {
- intr |= INTR_TYPE_SOFT_INTR;
- vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
- vmx->vcpu.arch.event_exit_inst_len);
- } else
- intr |= INTR_TYPE_EXT_INTR;
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr);
-
- vmx_clear_hlt(vcpu);
-}
-
-static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (!enable_vnmi) {
- /*
- * Tracking the NMI-blocked state in software is built upon
- * finding the next open IRQ window. This, in turn, depends on
- * well-behaving guests: They have to keep IRQs disabled at
- * least as long as the NMI handler runs. Otherwise we may
- * cause NMI nesting, maybe breaking the guest. But as this is
- * highly unlikely, we can live with the residual risk.
- */
- vmx->loaded_vmcs->soft_vnmi_blocked = 1;
- vmx->loaded_vmcs->vnmi_blocked_time = 0;
- }
-
- ++vcpu->stat.nmi_injections;
- vmx->loaded_vmcs->nmi_known_unmasked = false;
-
- if (vmx->rmode.vm86_active) {
- if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) != EMULATE_DONE)
- kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
- return;
- }
-
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
- INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
-
- vmx_clear_hlt(vcpu);
-}
-
-static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- bool masked;
-
- if (!enable_vnmi)
- return vmx->loaded_vmcs->soft_vnmi_blocked;
- if (vmx->loaded_vmcs->nmi_known_unmasked)
- return false;
- masked = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_NMI;
- vmx->loaded_vmcs->nmi_known_unmasked = !masked;
- return masked;
-}
-
-static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (!enable_vnmi) {
- if (vmx->loaded_vmcs->soft_vnmi_blocked != masked) {
- vmx->loaded_vmcs->soft_vnmi_blocked = masked;
- vmx->loaded_vmcs->vnmi_blocked_time = 0;
- }
- } else {
- vmx->loaded_vmcs->nmi_known_unmasked = !masked;
- if (masked)
- vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_NMI);
- else
- vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_NMI);
- }
-}
-
-static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
-{
- if (to_vmx(vcpu)->nested.nested_run_pending)
- return 0;
-
- if (!enable_vnmi &&
- to_vmx(vcpu)->loaded_vmcs->soft_vnmi_blocked)
- return 0;
-
- return !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
- (GUEST_INTR_STATE_MOV_SS | GUEST_INTR_STATE_STI
- | GUEST_INTR_STATE_NMI));
-}
-
-static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
-{
- if (to_vmx(vcpu)->nested.nested_run_pending)
- return false;
-
- if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu))
- return true;
-
- return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
- !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
- (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
-}
-
-static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
-{
- int ret;
-
- if (enable_unrestricted_guest)
- return 0;
-
- ret = x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, addr,
- PAGE_SIZE * 3);
- if (ret)
- return ret;
- to_kvm_vmx(kvm)->tss_addr = addr;
- return init_rmode_tss(kvm);
-}
-
-static int vmx_set_identity_map_addr(struct kvm *kvm, u64 ident_addr)
-{
- to_kvm_vmx(kvm)->ept_identity_map_addr = ident_addr;
- return 0;
-}
-
-static bool rmode_exception(struct kvm_vcpu *vcpu, int vec)
-{
- switch (vec) {
- case BP_VECTOR:
- /*
- * Update instruction length as we may reinject the exception
- * from user space while in guest debugging mode.
- */
- to_vmx(vcpu)->vcpu.arch.event_exit_inst_len =
- vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
- if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
- return false;
- /* fall through */
- case DB_VECTOR:
- if (vcpu->guest_debug &
- (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
- return false;
- /* fall through */
- case DE_VECTOR:
- case OF_VECTOR:
- case BR_VECTOR:
- case UD_VECTOR:
- case DF_VECTOR:
- case SS_VECTOR:
- case GP_VECTOR:
- case MF_VECTOR:
- return true;
- break;
- }
- return false;
-}
-
-static int handle_rmode_exception(struct kvm_vcpu *vcpu,
- int vec, u32 err_code)
-{
- /*
- * Instruction with address size override prefix opcode 0x67
- * Cause the #SS fault with 0 error code in VM86 mode.
- */
- if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0) {
- if (kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE) {
- if (vcpu->arch.halt_request) {
- vcpu->arch.halt_request = 0;
- return kvm_vcpu_halt(vcpu);
- }
- return 1;
- }
- return 0;
- }
-
- /*
- * Forward all other exceptions that are valid in real mode.
- * FIXME: Breaks guest debugging in real mode, needs to be fixed with
- * the required debugging infrastructure rework.
- */
- kvm_queue_exception(vcpu, vec);
- return 1;
-}
-
-/*
- * Trigger machine check on the host. We assume all the MSRs are already set up
- * by the CPU and that we still run on the same CPU as the MCE occurred on.
- * We pass a fake environment to the machine check handler because we want
- * the guest to be always treated like user space, no matter what context
- * it used internally.
- */
-static void kvm_machine_check(void)
-{
-#if defined(CONFIG_X86_MCE)
- struct pt_regs regs = {
- .cs = 3, /* Fake ring 3 no matter what the guest ran on */
- .flags = X86_EFLAGS_IF,
- };
-
- do_machine_check(®s, 0);
-#endif
-}
-
-static int handle_machine_check(struct kvm_vcpu *vcpu)
-{
- /* already handled by vcpu_run */
- return 1;
-}
-
-static int handle_exception(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct kvm_run *kvm_run = vcpu->run;
- u32 intr_info, ex_no, error_code;
- unsigned long cr2, rip, dr6;
- u32 vect_info;
- enum emulation_result er;
-
- vect_info = vmx->idt_vectoring_info;
- intr_info = vmx->exit_intr_info;
-
- if (is_machine_check(intr_info))
- return handle_machine_check(vcpu);
-
- if (is_nmi(intr_info))
- return 1; /* already handled by vmx_vcpu_run() */
-
- if (is_invalid_opcode(intr_info))
- return handle_ud(vcpu);
-
- error_code = 0;
- if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
- error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
-
- if (!vmx->rmode.vm86_active && is_gp_fault(intr_info)) {
- WARN_ON_ONCE(!enable_vmware_backdoor);
- er = kvm_emulate_instruction(vcpu,
- EMULTYPE_VMWARE | EMULTYPE_NO_UD_ON_FAIL);
- if (er == EMULATE_USER_EXIT)
- return 0;
- else if (er != EMULATE_DONE)
- kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
- return 1;
- }
-
- /*
- * The #PF with PFEC.RSVD = 1 indicates the guest is accessing
- * MMIO, it is better to report an internal error.
- * See the comments in vmx_handle_exit.
- */
- if ((vect_info & VECTORING_INFO_VALID_MASK) &&
- !(is_page_fault(intr_info) && !(error_code & PFERR_RSVD_MASK))) {
- vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
- vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX;
- vcpu->run->internal.ndata = 3;
- vcpu->run->internal.data[0] = vect_info;
- vcpu->run->internal.data[1] = intr_info;
- vcpu->run->internal.data[2] = error_code;
- return 0;
- }
-
- if (is_page_fault(intr_info)) {
- cr2 = vmcs_readl(EXIT_QUALIFICATION);
- /* EPT won't cause page fault directly */
- WARN_ON_ONCE(!vcpu->arch.apf.host_apf_reason && enable_ept);
- return kvm_handle_page_fault(vcpu, error_code, cr2, NULL, 0);
- }
-
- ex_no = intr_info & INTR_INFO_VECTOR_MASK;
-
- if (vmx->rmode.vm86_active && rmode_exception(vcpu, ex_no))
- return handle_rmode_exception(vcpu, ex_no, error_code);
-
- switch (ex_no) {
- case AC_VECTOR:
- kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
- return 1;
- case DB_VECTOR:
- dr6 = vmcs_readl(EXIT_QUALIFICATION);
- if (!(vcpu->guest_debug &
- (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
- vcpu->arch.dr6 &= ~15;
- vcpu->arch.dr6 |= dr6 | DR6_RTM;
- if (is_icebp(intr_info))
- skip_emulated_instruction(vcpu);
-
- kvm_queue_exception(vcpu, DB_VECTOR);
- return 1;
- }
- kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1;
- kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7);
- /* fall through */
- case BP_VECTOR:
- /*
- * Update instruction length as we may reinject #BP from
- * user space while in guest debugging mode. Reading it for
- * #DB as well causes no harm, it is not used in that case.
- */
- vmx->vcpu.arch.event_exit_inst_len =
- vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
- kvm_run->exit_reason = KVM_EXIT_DEBUG;
- rip = kvm_rip_read(vcpu);
- kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
- kvm_run->debug.arch.exception = ex_no;
- break;
- default:
- kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
- kvm_run->ex.exception = ex_no;
- kvm_run->ex.error_code = error_code;
- break;
- }
- return 0;
-}
-
-static int handle_external_interrupt(struct kvm_vcpu *vcpu)
-{
- ++vcpu->stat.irq_exits;
- return 1;
-}
-
-static int handle_triple_fault(struct kvm_vcpu *vcpu)
-{
- vcpu->run->exit_reason = KVM_EXIT_SHUTDOWN;
- vcpu->mmio_needed = 0;
- return 0;
-}
-
-static int handle_io(struct kvm_vcpu *vcpu)
-{
- unsigned long exit_qualification;
- int size, in, string;
- unsigned port;
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
- string = (exit_qualification & 16) != 0;
-
- ++vcpu->stat.io_exits;
-
- if (string)
- return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
-
- port = exit_qualification >> 16;
- size = (exit_qualification & 7) + 1;
- in = (exit_qualification & 8) != 0;
-
- return kvm_fast_pio(vcpu, size, port, in);
-}
-
-static void
-vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
-{
- /*
- * Patch in the VMCALL instruction:
- */
- hypercall[0] = 0x0f;
- hypercall[1] = 0x01;
- hypercall[2] = 0xc1;
-}
-
-/* called to set cr0 as appropriate for a mov-to-cr0 exit. */
-static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
-{
- if (is_guest_mode(vcpu)) {
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- unsigned long orig_val = val;
-
- /*
- * We get here when L2 changed cr0 in a way that did not change
- * any of L1's shadowed bits (see nested_vmx_exit_handled_cr),
- * but did change L0 shadowed bits. So we first calculate the
- * effective cr0 value that L1 would like to write into the
- * hardware. It consists of the L2-owned bits from the new
- * value combined with the L1-owned bits from L1's guest_cr0.
- */
- val = (val & ~vmcs12->cr0_guest_host_mask) |
- (vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask);
-
- if (!nested_guest_cr0_valid(vcpu, val))
- return 1;
-
- if (kvm_set_cr0(vcpu, val))
- return 1;
- vmcs_writel(CR0_READ_SHADOW, orig_val);
- return 0;
- } else {
- if (to_vmx(vcpu)->nested.vmxon &&
- !nested_host_cr0_valid(vcpu, val))
- return 1;
-
- return kvm_set_cr0(vcpu, val);
- }
-}
-
-static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val)
-{
- if (is_guest_mode(vcpu)) {
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- unsigned long orig_val = val;
-
- /* analogously to handle_set_cr0 */
- val = (val & ~vmcs12->cr4_guest_host_mask) |
- (vmcs12->guest_cr4 & vmcs12->cr4_guest_host_mask);
- if (kvm_set_cr4(vcpu, val))
- return 1;
- vmcs_writel(CR4_READ_SHADOW, orig_val);
- return 0;
- } else
- return kvm_set_cr4(vcpu, val);
-}
-
-static int handle_desc(struct kvm_vcpu *vcpu)
-{
- WARN_ON(!(vcpu->arch.cr4 & X86_CR4_UMIP));
- return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
-}
-
-static int handle_cr(struct kvm_vcpu *vcpu)
-{
- unsigned long exit_qualification, val;
- int cr;
- int reg;
- int err;
- int ret;
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
- cr = exit_qualification & 15;
- reg = (exit_qualification >> 8) & 15;
- switch ((exit_qualification >> 4) & 3) {
- case 0: /* mov to cr */
- val = kvm_register_readl(vcpu, reg);
- trace_kvm_cr_write(cr, val);
- switch (cr) {
- case 0:
- err = handle_set_cr0(vcpu, val);
- return kvm_complete_insn_gp(vcpu, err);
- case 3:
- WARN_ON_ONCE(enable_unrestricted_guest);
- err = kvm_set_cr3(vcpu, val);
- return kvm_complete_insn_gp(vcpu, err);
- case 4:
- err = handle_set_cr4(vcpu, val);
- return kvm_complete_insn_gp(vcpu, err);
- case 8: {
- u8 cr8_prev = kvm_get_cr8(vcpu);
- u8 cr8 = (u8)val;
- err = kvm_set_cr8(vcpu, cr8);
- ret = kvm_complete_insn_gp(vcpu, err);
- if (lapic_in_kernel(vcpu))
- return ret;
- if (cr8_prev <= cr8)
- return ret;
- /*
- * TODO: we might be squashing a
- * KVM_GUESTDBG_SINGLESTEP-triggered
- * KVM_EXIT_DEBUG here.
- */
- vcpu->run->exit_reason = KVM_EXIT_SET_TPR;
- return 0;
- }
- }
- break;
- case 2: /* clts */
- WARN_ONCE(1, "Guest should always own CR0.TS");
- vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
- trace_kvm_cr_write(0, kvm_read_cr0(vcpu));
- return kvm_skip_emulated_instruction(vcpu);
- case 1: /*mov from cr*/
- switch (cr) {
- case 3:
- WARN_ON_ONCE(enable_unrestricted_guest);
- val = kvm_read_cr3(vcpu);
- kvm_register_write(vcpu, reg, val);
- trace_kvm_cr_read(cr, val);
- return kvm_skip_emulated_instruction(vcpu);
- case 8:
- val = kvm_get_cr8(vcpu);
- kvm_register_write(vcpu, reg, val);
- trace_kvm_cr_read(cr, val);
- return kvm_skip_emulated_instruction(vcpu);
- }
- break;
- case 3: /* lmsw */
- val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f;
- trace_kvm_cr_write(0, (kvm_read_cr0(vcpu) & ~0xful) | val);
- kvm_lmsw(vcpu, val);
-
- return kvm_skip_emulated_instruction(vcpu);
- default:
- break;
- }
- vcpu->run->exit_reason = 0;
- vcpu_unimpl(vcpu, "unhandled control register: op %d cr %d\n",
- (int)(exit_qualification >> 4) & 3, cr);
- return 0;
-}
-
-static int handle_dr(struct kvm_vcpu *vcpu)
-{
- unsigned long exit_qualification;
- int dr, dr7, reg;
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
- dr = exit_qualification & DEBUG_REG_ACCESS_NUM;
-
- /* First, if DR does not exist, trigger UD */
- if (!kvm_require_dr(vcpu, dr))
- return 1;
-
- /* Do not handle if the CPL > 0, will trigger GP on re-entry */
- if (!kvm_require_cpl(vcpu, 0))
- return 1;
- dr7 = vmcs_readl(GUEST_DR7);
- if (dr7 & DR7_GD) {
- /*
- * As the vm-exit takes precedence over the debug trap, we
- * need to emulate the latter, either for the host or the
- * guest debugging itself.
- */
- if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
- vcpu->run->debug.arch.dr6 = vcpu->arch.dr6;
- vcpu->run->debug.arch.dr7 = dr7;
- vcpu->run->debug.arch.pc = kvm_get_linear_rip(vcpu);
- vcpu->run->debug.arch.exception = DB_VECTOR;
- vcpu->run->exit_reason = KVM_EXIT_DEBUG;
- return 0;
- } else {
- vcpu->arch.dr6 &= ~15;
- vcpu->arch.dr6 |= DR6_BD | DR6_RTM;
- kvm_queue_exception(vcpu, DB_VECTOR);
- return 1;
- }
- }
-
- if (vcpu->guest_debug == 0) {
- vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
- CPU_BASED_MOV_DR_EXITING);
-
- /*
- * No more DR vmexits; force a reload of the debug registers
- * and reenter on this instruction. The next vmexit will
- * retrieve the full state of the debug registers.
- */
- vcpu->arch.switch_db_regs |= KVM_DEBUGREG_WONT_EXIT;
- return 1;
- }
-
- reg = DEBUG_REG_ACCESS_REG(exit_qualification);
- if (exit_qualification & TYPE_MOV_FROM_DR) {
- unsigned long val;
-
- if (kvm_get_dr(vcpu, dr, &val))
- return 1;
- kvm_register_write(vcpu, reg, val);
- } else
- if (kvm_set_dr(vcpu, dr, kvm_register_readl(vcpu, reg)))
- return 1;
-
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static u64 vmx_get_dr6(struct kvm_vcpu *vcpu)
-{
- return vcpu->arch.dr6;
-}
-
-static void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val)
-{
-}
-
-static void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
-{
- get_debugreg(vcpu->arch.db[0], 0);
- get_debugreg(vcpu->arch.db[1], 1);
- get_debugreg(vcpu->arch.db[2], 2);
- get_debugreg(vcpu->arch.db[3], 3);
- get_debugreg(vcpu->arch.dr6, 6);
- vcpu->arch.dr7 = vmcs_readl(GUEST_DR7);
-
- vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_WONT_EXIT;
- vmcs_set_bits(CPU_BASED_VM_EXEC_CONTROL, CPU_BASED_MOV_DR_EXITING);
-}
-
-static void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val)
-{
- vmcs_writel(GUEST_DR7, val);
-}
-
-static int handle_cpuid(struct kvm_vcpu *vcpu)
-{
- return kvm_emulate_cpuid(vcpu);
-}
-
-static int handle_rdmsr(struct kvm_vcpu *vcpu)
-{
- u32 ecx = vcpu->arch.regs[VCPU_REGS_RCX];
- struct msr_data msr_info;
-
- msr_info.index = ecx;
- msr_info.host_initiated = false;
- if (vmx_get_msr(vcpu, &msr_info)) {
- trace_kvm_msr_read_ex(ecx);
- kvm_inject_gp(vcpu, 0);
- return 1;
- }
-
- trace_kvm_msr_read(ecx, msr_info.data);
-
- /* FIXME: handling of bits 32:63 of rax, rdx */
- vcpu->arch.regs[VCPU_REGS_RAX] = msr_info.data & -1u;
- vcpu->arch.regs[VCPU_REGS_RDX] = (msr_info.data >> 32) & -1u;
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static int handle_wrmsr(struct kvm_vcpu *vcpu)
-{
- struct msr_data msr;
- u32 ecx = vcpu->arch.regs[VCPU_REGS_RCX];
- u64 data = (vcpu->arch.regs[VCPU_REGS_RAX] & -1u)
- | ((u64)(vcpu->arch.regs[VCPU_REGS_RDX] & -1u) << 32);
-
- msr.data = data;
- msr.index = ecx;
- msr.host_initiated = false;
- if (kvm_set_msr(vcpu, &msr) != 0) {
- trace_kvm_msr_write_ex(ecx, data);
- kvm_inject_gp(vcpu, 0);
- return 1;
- }
-
- trace_kvm_msr_write(ecx, data);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static int handle_tpr_below_threshold(struct kvm_vcpu *vcpu)
-{
- kvm_apic_update_ppr(vcpu);
- return 1;
-}
-
-static int handle_interrupt_window(struct kvm_vcpu *vcpu)
-{
- vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
- CPU_BASED_VIRTUAL_INTR_PENDING);
-
- kvm_make_request(KVM_REQ_EVENT, vcpu);
-
- ++vcpu->stat.irq_window_exits;
- return 1;
-}
-
-static int handle_halt(struct kvm_vcpu *vcpu)
-{
- return kvm_emulate_halt(vcpu);
-}
-
-static int handle_vmcall(struct kvm_vcpu *vcpu)
-{
- return kvm_emulate_hypercall(vcpu);
-}
-
-static int handle_invd(struct kvm_vcpu *vcpu)
-{
- return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
-}
-
-static int handle_invlpg(struct kvm_vcpu *vcpu)
-{
- unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- kvm_mmu_invlpg(vcpu, exit_qualification);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static int handle_rdpmc(struct kvm_vcpu *vcpu)
-{
- int err;
-
- err = kvm_rdpmc(vcpu);
- return kvm_complete_insn_gp(vcpu, err);
-}
-
-static int handle_wbinvd(struct kvm_vcpu *vcpu)
-{
- return kvm_emulate_wbinvd(vcpu);
-}
-
-static int handle_xsetbv(struct kvm_vcpu *vcpu)
-{
- u64 new_bv = kvm_read_edx_eax(vcpu);
- u32 index = kvm_register_read(vcpu, VCPU_REGS_RCX);
-
- if (kvm_set_xcr(vcpu, index, new_bv) == 0)
- return kvm_skip_emulated_instruction(vcpu);
- return 1;
-}
-
-static int handle_xsaves(struct kvm_vcpu *vcpu)
-{
- kvm_skip_emulated_instruction(vcpu);
- WARN(1, "this should never happen\n");
- return 1;
-}
-
-static int handle_xrstors(struct kvm_vcpu *vcpu)
-{
- kvm_skip_emulated_instruction(vcpu);
- WARN(1, "this should never happen\n");
- return 1;
-}
-
-static int handle_apic_access(struct kvm_vcpu *vcpu)
-{
- if (likely(fasteoi)) {
- unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
- int access_type, offset;
-
- access_type = exit_qualification & APIC_ACCESS_TYPE;
- offset = exit_qualification & APIC_ACCESS_OFFSET;
- /*
- * Sane guest uses MOV to write EOI, with written value
- * not cared. So make a short-circuit here by avoiding
- * heavy instruction emulation.
- */
- if ((access_type == TYPE_LINEAR_APIC_INST_WRITE) &&
- (offset == APIC_EOI)) {
- kvm_lapic_set_eoi(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
- }
- }
- return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
-}
-
-static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
-{
- unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
- int vector = exit_qualification & 0xff;
-
- /* EOI-induced VM exit is trap-like and thus no need to adjust IP */
- kvm_apic_set_eoi_accelerated(vcpu, vector);
- return 1;
-}
-
-static int handle_apic_write(struct kvm_vcpu *vcpu)
-{
- unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
- u32 offset = exit_qualification & 0xfff;
-
- /* APIC-write VM exit is trap-like and thus no need to adjust IP */
- kvm_apic_write_nodecode(vcpu, offset);
- return 1;
-}
-
-static int handle_task_switch(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- unsigned long exit_qualification;
- bool has_error_code = false;
- u32 error_code = 0;
- u16 tss_selector;
- int reason, type, idt_v, idt_index;
-
- idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
- idt_index = (vmx->idt_vectoring_info & VECTORING_INFO_VECTOR_MASK);
- type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- reason = (u32)exit_qualification >> 30;
- if (reason == TASK_SWITCH_GATE && idt_v) {
- switch (type) {
- case INTR_TYPE_NMI_INTR:
- vcpu->arch.nmi_injected = false;
- vmx_set_nmi_mask(vcpu, true);
- break;
- case INTR_TYPE_EXT_INTR:
- case INTR_TYPE_SOFT_INTR:
- kvm_clear_interrupt_queue(vcpu);
- break;
- case INTR_TYPE_HARD_EXCEPTION:
- if (vmx->idt_vectoring_info &
- VECTORING_INFO_DELIVER_CODE_MASK) {
- has_error_code = true;
- error_code =
- vmcs_read32(IDT_VECTORING_ERROR_CODE);
- }
- /* fall through */
- case INTR_TYPE_SOFT_EXCEPTION:
- kvm_clear_exception_queue(vcpu);
- break;
- default:
- break;
- }
- }
- tss_selector = exit_qualification;
-
- if (!idt_v || (type != INTR_TYPE_HARD_EXCEPTION &&
- type != INTR_TYPE_EXT_INTR &&
- type != INTR_TYPE_NMI_INTR))
- skip_emulated_instruction(vcpu);
-
- if (kvm_task_switch(vcpu, tss_selector,
- type == INTR_TYPE_SOFT_INTR ? idt_index : -1, reason,
- has_error_code, error_code) == EMULATE_FAIL) {
- vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
- vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
- vcpu->run->internal.ndata = 0;
- return 0;
- }
-
- /*
- * TODO: What about debug traps on tss switch?
- * Are we supposed to inject them and update dr6?
- */
-
- return 1;
-}
-
-static int handle_ept_violation(struct kvm_vcpu *vcpu)
-{
- unsigned long exit_qualification;
- gpa_t gpa;
- u64 error_code;
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- /*
- * EPT violation happened while executing iret from NMI,
- * "blocked by NMI" bit has to be set before next VM entry.
- * There are errata that may cause this bit to not be set:
- * AAK134, BY25.
- */
- if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
- enable_vnmi &&
- (exit_qualification & INTR_INFO_UNBLOCK_NMI))
- vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, GUEST_INTR_STATE_NMI);
-
- gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
- trace_kvm_page_fault(gpa, exit_qualification);
-
- /* Is it a read fault? */
- error_code = (exit_qualification & EPT_VIOLATION_ACC_READ)
- ? PFERR_USER_MASK : 0;
- /* Is it a write fault? */
- error_code |= (exit_qualification & EPT_VIOLATION_ACC_WRITE)
- ? PFERR_WRITE_MASK : 0;
- /* Is it a fetch fault? */
- error_code |= (exit_qualification & EPT_VIOLATION_ACC_INSTR)
- ? PFERR_FETCH_MASK : 0;
- /* ept page table entry is present? */
- error_code |= (exit_qualification &
- (EPT_VIOLATION_READABLE | EPT_VIOLATION_WRITABLE |
- EPT_VIOLATION_EXECUTABLE))
- ? PFERR_PRESENT_MASK : 0;
-
- error_code |= (exit_qualification & 0x100) != 0 ?
- PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK;
-
- vcpu->arch.exit_qualification = exit_qualification;
- return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0);
-}
-
-static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
-{
- gpa_t gpa;
-
- /*
- * A nested guest cannot optimize MMIO vmexits, because we have an
- * nGPA here instead of the required GPA.
- */
- gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
- if (!is_guest_mode(vcpu) &&
- !kvm_io_bus_write(vcpu, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
- trace_kvm_fast_mmio(gpa);
- /*
- * Doing kvm_skip_emulated_instruction() depends on undefined
- * behavior: Intel's manual doesn't mandate
- * VM_EXIT_INSTRUCTION_LEN to be set in VMCS when EPT MISCONFIG
- * occurs and while on real hardware it was observed to be set,
- * other hypervisors (namely Hyper-V) don't set it, we end up
- * advancing IP with some random value. Disable fast mmio when
- * running nested and keep it for real hardware in hope that
- * VM_EXIT_INSTRUCTION_LEN will always be set correctly.
- */
- if (!static_cpu_has(X86_FEATURE_HYPERVISOR))
- return kvm_skip_emulated_instruction(vcpu);
- else
- return kvm_emulate_instruction(vcpu, EMULTYPE_SKIP) ==
- EMULATE_DONE;
- }
-
- return kvm_mmu_page_fault(vcpu, gpa, PFERR_RSVD_MASK, NULL, 0);
-}
-
-static int handle_nmi_window(struct kvm_vcpu *vcpu)
-{
- WARN_ON_ONCE(!enable_vnmi);
- vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
- CPU_BASED_VIRTUAL_NMI_PENDING);
- ++vcpu->stat.nmi_window_exits;
- kvm_make_request(KVM_REQ_EVENT, vcpu);
-
- return 1;
-}
-
-static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- enum emulation_result err = EMULATE_DONE;
- int ret = 1;
- u32 cpu_exec_ctrl;
- bool intr_window_requested;
- unsigned count = 130;
-
- /*
- * We should never reach the point where we are emulating L2
- * due to invalid guest state as that means we incorrectly
- * allowed a nested VMEntry with an invalid vmcs12.
- */
- WARN_ON_ONCE(vmx->emulation_required && vmx->nested.nested_run_pending);
-
- cpu_exec_ctrl = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
- intr_window_requested = cpu_exec_ctrl & CPU_BASED_VIRTUAL_INTR_PENDING;
-
- while (vmx->emulation_required && count-- != 0) {
- if (intr_window_requested && vmx_interrupt_allowed(vcpu))
- return handle_interrupt_window(&vmx->vcpu);
-
- if (kvm_test_request(KVM_REQ_EVENT, vcpu))
- return 1;
-
- err = kvm_emulate_instruction(vcpu, 0);
-
- if (err == EMULATE_USER_EXIT) {
- ++vcpu->stat.mmio_exits;
- ret = 0;
- goto out;
- }
-
- if (err != EMULATE_DONE)
- goto emulation_error;
-
- if (vmx->emulation_required && !vmx->rmode.vm86_active &&
- vcpu->arch.exception.pending)
- goto emulation_error;
-
- if (vcpu->arch.halt_request) {
- vcpu->arch.halt_request = 0;
- ret = kvm_vcpu_halt(vcpu);
- goto out;
- }
-
- if (signal_pending(current))
- goto out;
- if (need_resched())
- schedule();
- }
-
-out:
- return ret;
-
-emulation_error:
- vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
- vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
- vcpu->run->internal.ndata = 0;
- return 0;
-}
-
-static void grow_ple_window(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int old = vmx->ple_window;
-
- vmx->ple_window = __grow_ple_window(old, ple_window,
- ple_window_grow,
- ple_window_max);
-
- if (vmx->ple_window != old)
- vmx->ple_window_dirty = true;
-
- trace_kvm_ple_window_grow(vcpu->vcpu_id, vmx->ple_window, old);
-}
-
-static void shrink_ple_window(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int old = vmx->ple_window;
-
- vmx->ple_window = __shrink_ple_window(old, ple_window,
- ple_window_shrink,
- ple_window);
-
- if (vmx->ple_window != old)
- vmx->ple_window_dirty = true;
-
- trace_kvm_ple_window_shrink(vcpu->vcpu_id, vmx->ple_window, old);
-}
-
-/*
- * Handler for POSTED_INTERRUPT_WAKEUP_VECTOR.
- */
-static void wakeup_handler(void)
-{
- struct kvm_vcpu *vcpu;
- int cpu = smp_processor_id();
-
- spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
- list_for_each_entry(vcpu, &per_cpu(blocked_vcpu_on_cpu, cpu),
- blocked_vcpu_list) {
- struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
-
- if (pi_test_on(pi_desc) == 1)
- kvm_vcpu_kick(vcpu);
- }
- spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
-}
-
-static void vmx_enable_tdp(void)
-{
- kvm_mmu_set_mask_ptes(VMX_EPT_READABLE_MASK,
- enable_ept_ad_bits ? VMX_EPT_ACCESS_BIT : 0ull,
- enable_ept_ad_bits ? VMX_EPT_DIRTY_BIT : 0ull,
- 0ull, VMX_EPT_EXECUTABLE_MASK,
- cpu_has_vmx_ept_execute_only() ? 0ull : VMX_EPT_READABLE_MASK,
- VMX_EPT_RWX_MASK, 0ull);
-
- ept_set_mmio_spte_mask();
- kvm_enable_tdp();
-}
-
-static __init int hardware_setup(void)
-{
- unsigned long host_bndcfgs;
- int r = -ENOMEM, i;
-
- rdmsrl_safe(MSR_EFER, &host_efer);
-
- for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i)
- kvm_define_shared_msr(i, vmx_msr_index[i]);
-
- for (i = 0; i < VMX_BITMAP_NR; i++) {
- vmx_bitmap[i] = (unsigned long *)__get_free_page(GFP_KERNEL);
- if (!vmx_bitmap[i])
- goto out;
- }
-
- memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
- memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
-
- if (setup_vmcs_config(&vmcs_config) < 0) {
- r = -EIO;
- goto out;
- }
-
- if (boot_cpu_has(X86_FEATURE_NX))
- kvm_enable_efer_bits(EFER_NX);
-
- if (boot_cpu_has(X86_FEATURE_MPX)) {
- rdmsrl(MSR_IA32_BNDCFGS, host_bndcfgs);
- WARN_ONCE(host_bndcfgs, "KVM: BNDCFGS in host will be lost");
- }
-
- if (!cpu_has_vmx_vpid() || !cpu_has_vmx_invvpid() ||
- !(cpu_has_vmx_invvpid_single() || cpu_has_vmx_invvpid_global()))
- enable_vpid = 0;
-
- if (!cpu_has_vmx_ept() ||
- !cpu_has_vmx_ept_4levels() ||
- !cpu_has_vmx_ept_mt_wb() ||
- !cpu_has_vmx_invept_global())
- enable_ept = 0;
-
- if (!cpu_has_vmx_ept_ad_bits() || !enable_ept)
- enable_ept_ad_bits = 0;
-
- if (!cpu_has_vmx_unrestricted_guest() || !enable_ept)
- enable_unrestricted_guest = 0;
-
- if (!cpu_has_vmx_flexpriority())
- flexpriority_enabled = 0;
-
- if (!cpu_has_virtual_nmis())
- enable_vnmi = 0;
-
- /*
- * set_apic_access_page_addr() is used to reload apic access
- * page upon invalidation. No need to do anything if not
- * using the APIC_ACCESS_ADDR VMCS field.
- */
- if (!flexpriority_enabled)
- kvm_x86_ops->set_apic_access_page_addr = NULL;
-
- if (!cpu_has_vmx_tpr_shadow())
- kvm_x86_ops->update_cr8_intercept = NULL;
-
- if (enable_ept && !cpu_has_vmx_ept_2m_page())
- kvm_disable_largepages();
-
-#if IS_ENABLED(CONFIG_HYPERV)
- if (ms_hyperv.nested_features & HV_X64_NESTED_GUEST_MAPPING_FLUSH
- && enable_ept)
- kvm_x86_ops->tlb_remote_flush = vmx_hv_remote_flush_tlb;
-#endif
-
- if (!cpu_has_vmx_ple()) {
- ple_gap = 0;
- ple_window = 0;
- ple_window_grow = 0;
- ple_window_max = 0;
- ple_window_shrink = 0;
- }
-
- if (!cpu_has_vmx_apicv()) {
- enable_apicv = 0;
- kvm_x86_ops->sync_pir_to_irr = NULL;
- }
-
- if (cpu_has_vmx_tsc_scaling()) {
- kvm_has_tsc_control = true;
- kvm_max_tsc_scaling_ratio = KVM_VMX_TSC_MULTIPLIER_MAX;
- kvm_tsc_scaling_ratio_frac_bits = 48;
- }
-
- set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
-
- if (enable_ept)
- vmx_enable_tdp();
- else
- kvm_disable_tdp();
-
- if (!nested) {
- kvm_x86_ops->get_nested_state = NULL;
- kvm_x86_ops->set_nested_state = NULL;
- }
-
- /*
- * Only enable PML when hardware supports PML feature, and both EPT
- * and EPT A/D bit features are enabled -- PML depends on them to work.
- */
- if (!enable_ept || !enable_ept_ad_bits || !cpu_has_vmx_pml())
- enable_pml = 0;
-
- if (!enable_pml) {
- kvm_x86_ops->slot_enable_log_dirty = NULL;
- kvm_x86_ops->slot_disable_log_dirty = NULL;
- kvm_x86_ops->flush_log_dirty = NULL;
- kvm_x86_ops->enable_log_dirty_pt_masked = NULL;
- }
-
- if (!cpu_has_vmx_preemption_timer())
- kvm_x86_ops->request_immediate_exit = __kvm_request_immediate_exit;
-
- if (cpu_has_vmx_preemption_timer() && enable_preemption_timer) {
- u64 vmx_msr;
-
- rdmsrl(MSR_IA32_VMX_MISC, vmx_msr);
- cpu_preemption_timer_multi =
- vmx_msr & VMX_MISC_PREEMPTION_TIMER_RATE_MASK;
- } else {
- kvm_x86_ops->set_hv_timer = NULL;
- kvm_x86_ops->cancel_hv_timer = NULL;
- }
-
- if (!cpu_has_vmx_shadow_vmcs())
- enable_shadow_vmcs = 0;
- if (enable_shadow_vmcs)
- init_vmcs_shadow_fields();
-
- kvm_set_posted_intr_wakeup_handler(wakeup_handler);
- nested_vmx_setup_ctls_msrs(&vmcs_config.nested, enable_apicv);
-
- kvm_mce_cap_supported |= MCG_LMCE_P;
-
- r = alloc_kvm_area();
- if (r)
- goto out;
- return 0;
-
-out:
- for (i = 0; i < VMX_BITMAP_NR; i++)
- free_page((unsigned long)vmx_bitmap[i]);
-
- return r;
-}
-
-static __exit void hardware_unsetup(void)
-{
- int i;
-
- for (i = 0; i < VMX_BITMAP_NR; i++)
- free_page((unsigned long)vmx_bitmap[i]);
-
- free_kvm_area();
-}
-
-/*
- * Indicate a busy-waiting vcpu in spinlock. We do not enable the PAUSE
- * exiting, so only get here on cpu with PAUSE-Loop-Exiting.
- */
-static int handle_pause(struct kvm_vcpu *vcpu)
-{
- if (!kvm_pause_in_guest(vcpu->kvm))
- grow_ple_window(vcpu);
-
- /*
- * Intel sdm vol3 ch-25.1.3 says: The "PAUSE-loop exiting"
- * VM-execution control is ignored if CPL > 0. OTOH, KVM
- * never set PAUSE_EXITING and just set PLE if supported,
- * so the vcpu must be CPL=0 if it gets a PAUSE exit.
- */
- kvm_vcpu_on_spin(vcpu, true);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static int handle_nop(struct kvm_vcpu *vcpu)
-{
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static int handle_mwait(struct kvm_vcpu *vcpu)
-{
- printk_once(KERN_WARNING "kvm: MWAIT instruction emulated as NOP!\n");
- return handle_nop(vcpu);
-}
-
-static int handle_invalid_op(struct kvm_vcpu *vcpu)
-{
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
-}
-
-static int handle_monitor_trap(struct kvm_vcpu *vcpu)
-{
- return 1;
-}
-
-static int handle_monitor(struct kvm_vcpu *vcpu)
-{
- printk_once(KERN_WARNING "kvm: MONITOR instruction emulated as NOP!\n");
- return handle_nop(vcpu);
-}
-
-/*
- * The following 3 functions, nested_vmx_succeed()/failValid()/failInvalid(),
- * set the success or error code of an emulated VMX instruction, as specified
- * by Vol 2B, VMX Instruction Reference, "Conventions".
- */
-static void nested_vmx_succeed(struct kvm_vcpu *vcpu)
-{
- vmx_set_rflags(vcpu, vmx_get_rflags(vcpu)
- & ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
- X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF));
-}
-
-static void nested_vmx_failInvalid(struct kvm_vcpu *vcpu)
-{
- vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
- & ~(X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF |
- X86_EFLAGS_SF | X86_EFLAGS_OF))
- | X86_EFLAGS_CF);
-}
-
-static void nested_vmx_failValid(struct kvm_vcpu *vcpu,
- u32 vm_instruction_error)
-{
- if (to_vmx(vcpu)->nested.current_vmptr == -1ull) {
- /*
- * failValid writes the error number to the current VMCS, which
- * can't be done there isn't a current VMCS.
- */
- nested_vmx_failInvalid(vcpu);
- return;
- }
- vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
- & ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
- X86_EFLAGS_SF | X86_EFLAGS_OF))
- | X86_EFLAGS_ZF);
- get_vmcs12(vcpu)->vm_instruction_error = vm_instruction_error;
- /*
- * We don't need to force a shadow sync because
- * VM_INSTRUCTION_ERROR is not shadowed
- */
-}
-
-static void nested_vmx_abort(struct kvm_vcpu *vcpu, u32 indicator)
-{
- /* TODO: not to reset guest simply here. */
- kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
- pr_debug_ratelimited("kvm: nested vmx abort, indicator %d\n", indicator);
-}
-
-static enum hrtimer_restart vmx_preemption_timer_fn(struct hrtimer *timer)
-{
- struct vcpu_vmx *vmx =
- container_of(timer, struct vcpu_vmx, nested.preemption_timer);
-
- vmx->nested.preemption_timer_expired = true;
- kvm_make_request(KVM_REQ_EVENT, &vmx->vcpu);
- kvm_vcpu_kick(&vmx->vcpu);
-
- return HRTIMER_NORESTART;
-}
-
-/*
- * Decode the memory-address operand of a vmx instruction, as recorded on an
- * exit caused by such an instruction (run by a guest hypervisor).
- * On success, returns 0. When the operand is invalid, returns 1 and throws
- * #UD or #GP.
- */
-static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
- unsigned long exit_qualification,
- u32 vmx_instruction_info, bool wr, gva_t *ret)
-{
- gva_t off;
- bool exn;
- struct kvm_segment s;
-
- /*
- * According to Vol. 3B, "Information for VM Exits Due to Instruction
- * Execution", on an exit, vmx_instruction_info holds most of the
- * addressing components of the operand. Only the displacement part
- * is put in exit_qualification (see 3B, "Basic VM-Exit Information").
- * For how an actual address is calculated from all these components,
- * refer to Vol. 1, "Operand Addressing".
- */
- int scaling = vmx_instruction_info & 3;
- int addr_size = (vmx_instruction_info >> 7) & 7;
- bool is_reg = vmx_instruction_info & (1u << 10);
- int seg_reg = (vmx_instruction_info >> 15) & 7;
- int index_reg = (vmx_instruction_info >> 18) & 0xf;
- bool index_is_valid = !(vmx_instruction_info & (1u << 22));
- int base_reg = (vmx_instruction_info >> 23) & 0xf;
- bool base_is_valid = !(vmx_instruction_info & (1u << 27));
-
- if (is_reg) {
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
- }
-
- /* Addr = segment_base + offset */
- /* offset = base + [index * scale] + displacement */
- off = exit_qualification; /* holds the displacement */
- if (addr_size == 1)
- off = (gva_t)sign_extend64(off, 31);
- else if (addr_size == 0)
- off = (gva_t)sign_extend64(off, 15);
- if (base_is_valid)
- off += kvm_register_read(vcpu, base_reg);
- if (index_is_valid)
- off += kvm_register_read(vcpu, index_reg)<<scaling;
- vmx_get_segment(vcpu, &s, seg_reg);
-
- /*
- * The effective address, i.e. @off, of a memory operand is truncated
- * based on the address size of the instruction. Note that this is
- * the *effective address*, i.e. the address prior to accounting for
- * the segment's base.
- */
- if (addr_size == 1) /* 32 bit */
- off &= 0xffffffff;
- else if (addr_size == 0) /* 16 bit */
- off &= 0xffff;
-
- /* Checks for #GP/#SS exceptions. */
- exn = false;
- if (is_long_mode(vcpu)) {
- /*
- * The virtual/linear address is never truncated in 64-bit
- * mode, e.g. a 32-bit address size can yield a 64-bit virtual
- * address when using FS/GS with a non-zero base.
- */
- *ret = s.base + off;
-
- /* Long mode: #GP(0)/#SS(0) if the memory address is in a
- * non-canonical form. This is the only check on the memory
- * destination for long mode!
- */
- exn = is_noncanonical_address(*ret, vcpu);
- } else if (is_protmode(vcpu)) {
- /*
- * When not in long mode, the virtual/linear address is
- * unconditionally truncated to 32 bits regardless of the
- * address size.
- */
- *ret = (s.base + off) & 0xffffffff;
-
- /* Protected mode: apply checks for segment validity in the
- * following order:
- * - segment type check (#GP(0) may be thrown)
- * - usability check (#GP(0)/#SS(0))
- * - limit check (#GP(0)/#SS(0))
- */
- if (wr)
- /* #GP(0) if the destination operand is located in a
- * read-only data segment or any code segment.
- */
- exn = ((s.type & 0xa) == 0 || (s.type & 8));
- else
- /* #GP(0) if the source operand is located in an
- * execute-only code segment
- */
- exn = ((s.type & 0xa) == 8);
- if (exn) {
- kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
- return 1;
- }
- /* Protected mode: #GP(0)/#SS(0) if the segment is unusable.
- */
- exn = (s.unusable != 0);
-
- /*
- * Protected mode: #GP(0)/#SS(0) if the memory operand is
- * outside the segment limit. All CPUs that support VMX ignore
- * limit checks for flat segments, i.e. segments with base==0,
- * limit==0xffffffff and of type expand-up data or code.
- */
- if (!(s.base == 0 && s.limit == 0xffffffff &&
- ((s.type & 8) || !(s.type & 4))))
- exn = exn || (off + sizeof(u64) > s.limit);
- }
- if (exn) {
- kvm_queue_exception_e(vcpu,
- seg_reg == VCPU_SREG_SS ?
- SS_VECTOR : GP_VECTOR,
- 0);
- return 1;
- }
-
- return 0;
-}
-
-static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer)
-{
- gva_t gva;
- struct x86_exception e;
-
- if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
- vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva))
- return 1;
-
- if (kvm_read_guest_virt(vcpu, gva, vmpointer, sizeof(*vmpointer), &e)) {
- kvm_inject_page_fault(vcpu, &e);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Allocate a shadow VMCS and associate it with the currently loaded
- * VMCS, unless such a shadow VMCS already exists. The newly allocated
- * VMCS is also VMCLEARed, so that it is ready for use.
- */
-static struct vmcs *alloc_shadow_vmcs(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct loaded_vmcs *loaded_vmcs = vmx->loaded_vmcs;
-
- /*
- * We should allocate a shadow vmcs for vmcs01 only when L1
- * executes VMXON and free it when L1 executes VMXOFF.
- * As it is invalid to execute VMXON twice, we shouldn't reach
- * here when vmcs01 already have an allocated shadow vmcs.
- */
- WARN_ON(loaded_vmcs == &vmx->vmcs01 && loaded_vmcs->shadow_vmcs);
-
- if (!loaded_vmcs->shadow_vmcs) {
- loaded_vmcs->shadow_vmcs = alloc_vmcs(true);
- if (loaded_vmcs->shadow_vmcs)
- vmcs_clear(loaded_vmcs->shadow_vmcs);
- }
- return loaded_vmcs->shadow_vmcs;
-}
-
-static int enter_vmx_operation(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int r;
-
- r = alloc_loaded_vmcs(&vmx->nested.vmcs02);
- if (r < 0)
- goto out_vmcs02;
-
- vmx->nested.cached_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
- if (!vmx->nested.cached_vmcs12)
- goto out_cached_vmcs12;
-
- vmx->nested.cached_shadow_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
- if (!vmx->nested.cached_shadow_vmcs12)
- goto out_cached_shadow_vmcs12;
-
- if (enable_shadow_vmcs && !alloc_shadow_vmcs(vcpu))
- goto out_shadow_vmcs;
-
- hrtimer_init(&vmx->nested.preemption_timer, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL_PINNED);
- vmx->nested.preemption_timer.function = vmx_preemption_timer_fn;
-
- vmx->nested.vpid02 = allocate_vpid();
-
- vmx->nested.vmxon = true;
- return 0;
-
-out_shadow_vmcs:
- kfree(vmx->nested.cached_shadow_vmcs12);
-
-out_cached_shadow_vmcs12:
- kfree(vmx->nested.cached_vmcs12);
-
-out_cached_vmcs12:
- free_loaded_vmcs(&vmx->nested.vmcs02);
-
-out_vmcs02:
- return -ENOMEM;
-}
-
-/*
- * Emulate the VMXON instruction.
- * Currently, we just remember that VMX is active, and do not save or even
- * inspect the argument to VMXON (the so-called "VMXON pointer") because we
- * do not currently need to store anything in that guest-allocated memory
- * region. Consequently, VMCLEAR and VMPTRLD also do not verify that the their
- * argument is different from the VMXON pointer (which the spec says they do).
- */
-static int handle_vmon(struct kvm_vcpu *vcpu)
-{
- int ret;
- gpa_t vmptr;
- struct page *page;
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- const u64 VMXON_NEEDED_FEATURES = FEATURE_CONTROL_LOCKED
- | FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
-
- /*
- * The Intel VMX Instruction Reference lists a bunch of bits that are
- * prerequisite to running VMXON, most notably cr4.VMXE must be set to
- * 1 (see vmx_set_cr4() for when we allow the guest to set this).
- * Otherwise, we should fail with #UD. But most faulting conditions
- * have already been checked by hardware, prior to the VM-exit for
- * VMXON. We do test guest cr4.VMXE because processor CR4 always has
- * that bit set to 1 in non-root mode.
- */
- if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE)) {
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
- }
-
- /* CPL=0 must be checked manually. */
- if (vmx_get_cpl(vcpu)) {
- kvm_inject_gp(vcpu, 0);
- return 1;
- }
-
- if (vmx->nested.vmxon) {
- nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- if ((vmx->msr_ia32_feature_control & VMXON_NEEDED_FEATURES)
- != VMXON_NEEDED_FEATURES) {
- kvm_inject_gp(vcpu, 0);
- return 1;
- }
-
- if (nested_vmx_get_vmptr(vcpu, &vmptr))
- return 1;
-
- /*
- * SDM 3: 24.11.5
- * The first 4 bytes of VMXON region contain the supported
- * VMCS revision identifier
- *
- * Note - IA32_VMX_BASIC[48] will never be 1 for the nested case;
- * which replaces physical address width with 32
- */
- if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
- nested_vmx_failInvalid(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- page = kvm_vcpu_gpa_to_page(vcpu, vmptr);
- if (is_error_page(page)) {
- nested_vmx_failInvalid(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
- }
- if (*(u32 *)kmap(page) != VMCS12_REVISION) {
- kunmap(page);
- kvm_release_page_clean(page);
- nested_vmx_failInvalid(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
- }
- kunmap(page);
- kvm_release_page_clean(page);
-
- vmx->nested.vmxon_ptr = vmptr;
- ret = enter_vmx_operation(vcpu);
- if (ret)
- return ret;
-
- nested_vmx_succeed(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-/*
- * Intel's VMX Instruction Reference specifies a common set of prerequisites
- * for running VMX instructions (except VMXON, whose prerequisites are
- * slightly different). It also specifies what exception to inject otherwise.
- * Note that many of these exceptions have priority over VM exits, so they
- * don't have to be checked again here.
- */
-static int nested_vmx_check_permission(struct kvm_vcpu *vcpu)
-{
- if (!to_vmx(vcpu)->nested.vmxon) {
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 0;
- }
-
- if (vmx_get_cpl(vcpu)) {
- kvm_inject_gp(vcpu, 0);
- return 0;
- }
-
- return 1;
-}
-
-static void vmx_disable_shadow_vmcs(struct vcpu_vmx *vmx)
-{
- vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL, SECONDARY_EXEC_SHADOW_VMCS);
- vmcs_write64(VMCS_LINK_POINTER, -1ull);
- vmx->nested.sync_shadow_vmcs = false;
-}
-
-static inline void nested_release_vmcs12(struct vcpu_vmx *vmx)
-{
- if (vmx->nested.current_vmptr == -1ull)
- return;
-
- if (enable_shadow_vmcs) {
- /* copy to memory all shadowed fields in case
- they were modified */
- copy_shadow_to_vmcs12(vmx);
- vmx_disable_shadow_vmcs(vmx);
- }
- vmx->nested.posted_intr_nv = -1;
-
- /* Flush VMCS12 to guest memory */
- kvm_vcpu_write_guest_page(&vmx->vcpu,
- vmx->nested.current_vmptr >> PAGE_SHIFT,
- vmx->nested.cached_vmcs12, 0, VMCS12_SIZE);
-
- vmx->nested.current_vmptr = -1ull;
-}
-
-/*
- * Free whatever needs to be freed from vmx->nested when L1 goes down, or
- * just stops using VMX.
- */
-static void free_nested(struct vcpu_vmx *vmx)
-{
- if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon)
- return;
-
- kvm_clear_request(KVM_REQ_GET_VMCS12_PAGES, &vmx->vcpu);
-
- hrtimer_cancel(&vmx->nested.preemption_timer);
- vmx->nested.vmxon = false;
- vmx->nested.smm.vmxon = false;
- free_vpid(vmx->nested.vpid02);
- vmx->nested.posted_intr_nv = -1;
- vmx->nested.current_vmptr = -1ull;
- if (enable_shadow_vmcs) {
- vmx_disable_shadow_vmcs(vmx);
- vmcs_clear(vmx->vmcs01.shadow_vmcs);
- free_vmcs(vmx->vmcs01.shadow_vmcs);
- vmx->vmcs01.shadow_vmcs = NULL;
- }
- kfree(vmx->nested.cached_vmcs12);
- kfree(vmx->nested.cached_shadow_vmcs12);
- /* Unpin physical memory we referred to in the vmcs02 */
- if (vmx->nested.apic_access_page) {
- kvm_release_page_dirty(vmx->nested.apic_access_page);
- vmx->nested.apic_access_page = NULL;
- }
- if (vmx->nested.virtual_apic_page) {
- kvm_release_page_dirty(vmx->nested.virtual_apic_page);
- vmx->nested.virtual_apic_page = NULL;
- }
- if (vmx->nested.pi_desc_page) {
- kunmap(vmx->nested.pi_desc_page);
- kvm_release_page_dirty(vmx->nested.pi_desc_page);
- vmx->nested.pi_desc_page = NULL;
- vmx->nested.pi_desc = NULL;
- }
-
- free_loaded_vmcs(&vmx->nested.vmcs02);
-}
-
-/* Emulate the VMXOFF instruction */
-static int handle_vmoff(struct kvm_vcpu *vcpu)
-{
- if (!nested_vmx_check_permission(vcpu))
- return 1;
- free_nested(to_vmx(vcpu));
- nested_vmx_succeed(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-/* Emulate the VMCLEAR instruction */
-static int handle_vmclear(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 zero = 0;
- gpa_t vmptr;
-
- if (!nested_vmx_check_permission(vcpu))
- return 1;
-
- if (nested_vmx_get_vmptr(vcpu, &vmptr))
- return 1;
-
- if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
- nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- if (vmptr == vmx->nested.vmxon_ptr) {
- nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_VMXON_POINTER);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- if (vmptr == vmx->nested.current_vmptr)
- nested_release_vmcs12(vmx);
-
- kvm_vcpu_write_guest(vcpu,
- vmptr + offsetof(struct vmcs12, launch_state),
- &zero, sizeof(zero));
-
- nested_vmx_succeed(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch);
-
-/* Emulate the VMLAUNCH instruction */
-static int handle_vmlaunch(struct kvm_vcpu *vcpu)
-{
- return nested_vmx_run(vcpu, true);
-}
-
-/* Emulate the VMRESUME instruction */
-static int handle_vmresume(struct kvm_vcpu *vcpu)
-{
-
- return nested_vmx_run(vcpu, false);
-}
-
-/*
- * Read a vmcs12 field. Since these can have varying lengths and we return
- * one type, we chose the biggest type (u64) and zero-extend the return value
- * to that size. Note that the caller, handle_vmread, might need to use only
- * some of the bits we return here (e.g., on 32-bit guests, only 32 bits of
- * 64-bit fields are to be returned).
- */
-static inline int vmcs12_read_any(struct vmcs12 *vmcs12,
- unsigned long field, u64 *ret)
-{
- short offset = vmcs_field_to_offset(field);
- char *p;
-
- if (offset < 0)
- return offset;
-
- p = (char *)vmcs12 + offset;
-
- switch (vmcs_field_width(field)) {
- case VMCS_FIELD_WIDTH_NATURAL_WIDTH:
- *ret = *((natural_width *)p);
- return 0;
- case VMCS_FIELD_WIDTH_U16:
- *ret = *((u16 *)p);
- return 0;
- case VMCS_FIELD_WIDTH_U32:
- *ret = *((u32 *)p);
- return 0;
- case VMCS_FIELD_WIDTH_U64:
- *ret = *((u64 *)p);
- return 0;
- default:
- WARN_ON(1);
- return -ENOENT;
- }
-}
-
-
-static inline int vmcs12_write_any(struct vmcs12 *vmcs12,
- unsigned long field, u64 field_value){
- short offset = vmcs_field_to_offset(field);
- char *p = (char *)vmcs12 + offset;
- if (offset < 0)
- return offset;
-
- switch (vmcs_field_width(field)) {
- case VMCS_FIELD_WIDTH_U16:
- *(u16 *)p = field_value;
- return 0;
- case VMCS_FIELD_WIDTH_U32:
- *(u32 *)p = field_value;
- return 0;
- case VMCS_FIELD_WIDTH_U64:
- *(u64 *)p = field_value;
- return 0;
- case VMCS_FIELD_WIDTH_NATURAL_WIDTH:
- *(natural_width *)p = field_value;
- return 0;
- default:
- WARN_ON(1);
- return -ENOENT;
- }
-
-}
-
-/*
- * Copy the writable VMCS shadow fields back to the VMCS12, in case
- * they have been modified by the L1 guest. Note that the "read-only"
- * VM-exit information fields are actually writable if the vCPU is
- * configured to support "VMWRITE to any supported field in the VMCS."
- */
-static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)
-{
- const u16 *fields[] = {
- shadow_read_write_fields,
- shadow_read_only_fields
- };
- const int max_fields[] = {
- max_shadow_read_write_fields,
- max_shadow_read_only_fields
- };
- int i, q;
- unsigned long field;
- u64 field_value;
- struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;
-
- if (WARN_ON(!shadow_vmcs))
- return;
-
- preempt_disable();
-
- vmcs_load(shadow_vmcs);
-
- for (q = 0; q < ARRAY_SIZE(fields); q++) {
- for (i = 0; i < max_fields[q]; i++) {
- field = fields[q][i];
- field_value = __vmcs_readl(field);
- vmcs12_write_any(get_vmcs12(&vmx->vcpu), field, field_value);
- }
- /*
- * Skip the VM-exit information fields if they are read-only.
- */
- if (!nested_cpu_has_vmwrite_any_field(&vmx->vcpu))
- break;
- }
-
- vmcs_clear(shadow_vmcs);
- vmcs_load(vmx->loaded_vmcs->vmcs);
-
- preempt_enable();
-}
-
-static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)
-{
- const u16 *fields[] = {
- shadow_read_write_fields,
- shadow_read_only_fields
- };
- const int max_fields[] = {
- max_shadow_read_write_fields,
- max_shadow_read_only_fields
- };
- int i, q;
- unsigned long field;
- u64 field_value = 0;
- struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;
-
- if (WARN_ON(!shadow_vmcs))
- return;
-
- vmcs_load(shadow_vmcs);
-
- for (q = 0; q < ARRAY_SIZE(fields); q++) {
- for (i = 0; i < max_fields[q]; i++) {
- field = fields[q][i];
- vmcs12_read_any(get_vmcs12(&vmx->vcpu), field, &field_value);
- __vmcs_writel(field, field_value);
- }
- }
-
- vmcs_clear(shadow_vmcs);
- vmcs_load(vmx->loaded_vmcs->vmcs);
-}
-
-/*
- * VMX instructions which assume a current vmcs12 (i.e., that VMPTRLD was
- * used before) all generate the same failure when it is missing.
- */
-static int nested_vmx_check_vmcs12(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- if (vmx->nested.current_vmptr == -1ull) {
- nested_vmx_failInvalid(vcpu);
- return 0;
- }
- return 1;
-}
-
-static int handle_vmread(struct kvm_vcpu *vcpu)
-{
- unsigned long field;
- u64 field_value;
- unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
- u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
- gva_t gva = 0;
- struct vmcs12 *vmcs12;
- struct x86_exception e;
-
- if (!nested_vmx_check_permission(vcpu))
- return 1;
-
- if (!nested_vmx_check_vmcs12(vcpu))
- return kvm_skip_emulated_instruction(vcpu);
-
- if (!is_guest_mode(vcpu))
- vmcs12 = get_vmcs12(vcpu);
- else {
- /*
- * When vmcs->vmcs_link_pointer is -1ull, any VMREAD
- * to shadowed-field sets the ALU flags for VMfailInvalid.
- */
- if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull) {
- nested_vmx_failInvalid(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
- }
- vmcs12 = get_shadow_vmcs12(vcpu);
- }
-
- /* Decode instruction info and find the field to read */
- field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
- /* Read the field, zero-extended to a u64 field_value */
- if (vmcs12_read_any(vmcs12, field, &field_value) < 0) {
- nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
- return kvm_skip_emulated_instruction(vcpu);
- }
- /*
- * Now copy part of this value to register or memory, as requested.
- * Note that the number of bits actually copied is 32 or 64 depending
- * on the guest's mode (32 or 64 bit), not on the given field's length.
- */
- if (vmx_instruction_info & (1u << 10)) {
- kvm_register_writel(vcpu, (((vmx_instruction_info) >> 3) & 0xf),
- field_value);
- } else {
- if (get_vmx_mem_address(vcpu, exit_qualification,
- vmx_instruction_info, true, &gva))
- return 1;
- /* _system ok, nested_vmx_check_permission has verified cpl=0 */
- if (kvm_write_guest_virt_system(vcpu, gva, &field_value,
- (is_long_mode(vcpu) ? 8 : 4),
- &e)) {
- kvm_inject_page_fault(vcpu, &e);
- return 1;
- }
- }
-
- nested_vmx_succeed(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-
-static int handle_vmwrite(struct kvm_vcpu *vcpu)
-{
- unsigned long field;
- gva_t gva;
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
- u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
-
- /* The value to write might be 32 or 64 bits, depending on L1's long
- * mode, and eventually we need to write that into a field of several
- * possible lengths. The code below first zero-extends the value to 64
- * bit (field_value), and then copies only the appropriate number of
- * bits into the vmcs12 field.
- */
- u64 field_value = 0;
- struct x86_exception e;
- struct vmcs12 *vmcs12;
-
- if (!nested_vmx_check_permission(vcpu))
- return 1;
-
- if (!nested_vmx_check_vmcs12(vcpu))
- return kvm_skip_emulated_instruction(vcpu);
-
- if (vmx_instruction_info & (1u << 10))
- field_value = kvm_register_readl(vcpu,
- (((vmx_instruction_info) >> 3) & 0xf));
- else {
- if (get_vmx_mem_address(vcpu, exit_qualification,
- vmx_instruction_info, false, &gva))
- return 1;
- if (kvm_read_guest_virt(vcpu, gva, &field_value,
- (is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
- kvm_inject_page_fault(vcpu, &e);
- return 1;
- }
- }
-
-
- field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
- /*
- * If the vCPU supports "VMWRITE to any supported field in the
- * VMCS," then the "read-only" fields are actually read/write.
- */
- if (vmcs_field_readonly(field) &&
- !nested_cpu_has_vmwrite_any_field(vcpu)) {
- nested_vmx_failValid(vcpu,
- VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- if (!is_guest_mode(vcpu))
- vmcs12 = get_vmcs12(vcpu);
- else {
- /*
- * When vmcs->vmcs_link_pointer is -1ull, any VMWRITE
- * to shadowed-field sets the ALU flags for VMfailInvalid.
- */
- if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull) {
- nested_vmx_failInvalid(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
- }
- vmcs12 = get_shadow_vmcs12(vcpu);
-
- }
-
- if (vmcs12_write_any(vmcs12, field, field_value) < 0) {
- nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- /*
- * Do not track vmcs12 dirty-state if in guest-mode
- * as we actually dirty shadow vmcs12 instead of vmcs12.
- */
- if (!is_guest_mode(vcpu)) {
- switch (field) {
-#define SHADOW_FIELD_RW(x) case x:
-#include "vmx_shadow_fields.h"
- /*
- * The fields that can be updated by L1 without a vmexit are
- * always updated in the vmcs02, the others go down the slow
- * path of prepare_vmcs02.
- */
- break;
- default:
- vmx->nested.dirty_vmcs12 = true;
- break;
- }
- }
-
- nested_vmx_succeed(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static void set_current_vmptr(struct vcpu_vmx *vmx, gpa_t vmptr)
-{
- vmx->nested.current_vmptr = vmptr;
- if (enable_shadow_vmcs) {
- vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
- SECONDARY_EXEC_SHADOW_VMCS);
- vmcs_write64(VMCS_LINK_POINTER,
- __pa(vmx->vmcs01.shadow_vmcs));
- vmx->nested.sync_shadow_vmcs = true;
- }
- vmx->nested.dirty_vmcs12 = true;
-}
-
-/* Emulate the VMPTRLD instruction */
-static int handle_vmptrld(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- gpa_t vmptr;
-
- if (!nested_vmx_check_permission(vcpu))
- return 1;
-
- if (nested_vmx_get_vmptr(vcpu, &vmptr))
- return 1;
-
- if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
- nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- if (vmptr == vmx->nested.vmxon_ptr) {
- nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_VMXON_POINTER);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- if (vmx->nested.current_vmptr != vmptr) {
- struct vmcs12 *new_vmcs12;
- struct page *page;
- page = kvm_vcpu_gpa_to_page(vcpu, vmptr);
- if (is_error_page(page)) {
- nested_vmx_failInvalid(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
- }
- new_vmcs12 = kmap(page);
- if (new_vmcs12->hdr.revision_id != VMCS12_REVISION ||
- (new_vmcs12->hdr.shadow_vmcs &&
- !nested_cpu_has_vmx_shadow_vmcs(vcpu))) {
- kunmap(page);
- kvm_release_page_clean(page);
- nested_vmx_failValid(vcpu,
- VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- nested_release_vmcs12(vmx);
- /*
- * Load VMCS12 from guest memory since it is not already
- * cached.
- */
- memcpy(vmx->nested.cached_vmcs12, new_vmcs12, VMCS12_SIZE);
- kunmap(page);
- kvm_release_page_clean(page);
-
- set_current_vmptr(vmx, vmptr);
- }
-
- nested_vmx_succeed(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-/* Emulate the VMPTRST instruction */
-static int handle_vmptrst(struct kvm_vcpu *vcpu)
-{
- unsigned long exit_qual = vmcs_readl(EXIT_QUALIFICATION);
- u32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);
- gpa_t current_vmptr = to_vmx(vcpu)->nested.current_vmptr;
- struct x86_exception e;
- gva_t gva;
-
- if (!nested_vmx_check_permission(vcpu))
- return 1;
-
- if (get_vmx_mem_address(vcpu, exit_qual, instr_info, true, &gva))
- return 1;
- /* *_system ok, nested_vmx_check_permission has verified cpl=0 */
- if (kvm_write_guest_virt_system(vcpu, gva, (void *)¤t_vmptr,
- sizeof(gpa_t), &e)) {
- kvm_inject_page_fault(vcpu, &e);
- return 1;
- }
- nested_vmx_succeed(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-/* Emulate the INVEPT instruction */
-static int handle_invept(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 vmx_instruction_info, types;
- unsigned long type;
- gva_t gva;
- struct x86_exception e;
- struct {
- u64 eptp, gpa;
- } operand;
-
- if (!(vmx->nested.msrs.secondary_ctls_high &
- SECONDARY_EXEC_ENABLE_EPT) ||
- !(vmx->nested.msrs.ept_caps & VMX_EPT_INVEPT_BIT)) {
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
- }
-
- if (!nested_vmx_check_permission(vcpu))
- return 1;
-
- vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
- type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
-
- types = (vmx->nested.msrs.ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6;
-
- if (type >= 32 || !(types & (1 << type))) {
- nested_vmx_failValid(vcpu,
- VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- /* According to the Intel VMX instruction reference, the memory
- * operand is read even if it isn't needed (e.g., for type==global)
- */
- if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
- vmx_instruction_info, false, &gva))
- return 1;
- if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
- kvm_inject_page_fault(vcpu, &e);
- return 1;
- }
-
- switch (type) {
- case VMX_EPT_EXTENT_GLOBAL:
- /*
- * TODO: track mappings and invalidate
- * single context requests appropriately
- */
- case VMX_EPT_EXTENT_CONTEXT:
- kvm_mmu_sync_roots(vcpu);
- kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
- nested_vmx_succeed(vcpu);
- break;
- default:
- BUG_ON(1);
- break;
- }
-
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static int handle_invvpid(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 vmx_instruction_info;
- unsigned long type, types;
- gva_t gva;
- struct x86_exception e;
- struct {
- u64 vpid;
- u64 gla;
- } operand;
-
- if (!(vmx->nested.msrs.secondary_ctls_high &
- SECONDARY_EXEC_ENABLE_VPID) ||
- !(vmx->nested.msrs.vpid_caps & VMX_VPID_INVVPID_BIT)) {
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
- }
-
- if (!nested_vmx_check_permission(vcpu))
- return 1;
-
- vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
- type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
-
- types = (vmx->nested.msrs.vpid_caps &
- VMX_VPID_EXTENT_SUPPORTED_MASK) >> 8;
-
- if (type >= 32 || !(types & (1 << type))) {
- nested_vmx_failValid(vcpu,
- VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- /* according to the intel vmx instruction reference, the memory
- * operand is read even if it isn't needed (e.g., for type==global)
- */
- if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
- vmx_instruction_info, false, &gva))
- return 1;
- if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
- kvm_inject_page_fault(vcpu, &e);
- return 1;
- }
- if (operand.vpid >> 16) {
- nested_vmx_failValid(vcpu,
- VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- switch (type) {
- case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
- if (!operand.vpid ||
- is_noncanonical_address(operand.gla, vcpu)) {
- nested_vmx_failValid(vcpu,
- VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
- return kvm_skip_emulated_instruction(vcpu);
- }
- if (cpu_has_vmx_invvpid_individual_addr() &&
- vmx->nested.vpid02) {
- __invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR,
- vmx->nested.vpid02, operand.gla);
- } else
- __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
- break;
- case VMX_VPID_EXTENT_SINGLE_CONTEXT:
- case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL:
- if (!operand.vpid) {
- nested_vmx_failValid(vcpu,
- VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
- return kvm_skip_emulated_instruction(vcpu);
- }
- __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
- break;
- case VMX_VPID_EXTENT_ALL_CONTEXT:
- __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
- break;
- default:
- WARN_ON_ONCE(1);
- return kvm_skip_emulated_instruction(vcpu);
- }
-
- nested_vmx_succeed(vcpu);
-
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-static int handle_invpcid(struct kvm_vcpu *vcpu)
-{
- u32 vmx_instruction_info;
- unsigned long type;
- bool pcid_enabled;
- gva_t gva;
- struct x86_exception e;
- unsigned i;
- unsigned long roots_to_free = 0;
- struct {
- u64 pcid;
- u64 gla;
- } operand;
-
- if (!guest_cpuid_has(vcpu, X86_FEATURE_INVPCID)) {
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
- }
-
- vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
- type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
-
- if (type > 3) {
- kvm_inject_gp(vcpu, 0);
- return 1;
- }
-
- /* According to the Intel instruction reference, the memory operand
- * is read even if it isn't needed (e.g., for type==all)
- */
- if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
- vmx_instruction_info, false, &gva))
- return 1;
-
- if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
- kvm_inject_page_fault(vcpu, &e);
- return 1;
- }
-
- if (operand.pcid >> 12 != 0) {
- kvm_inject_gp(vcpu, 0);
- return 1;
- }
-
- pcid_enabled = kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE);
-
- switch (type) {
- case INVPCID_TYPE_INDIV_ADDR:
- if ((!pcid_enabled && (operand.pcid != 0)) ||
- is_noncanonical_address(operand.gla, vcpu)) {
- kvm_inject_gp(vcpu, 0);
- return 1;
- }
- kvm_mmu_invpcid_gva(vcpu, operand.gla, operand.pcid);
- return kvm_skip_emulated_instruction(vcpu);
-
- case INVPCID_TYPE_SINGLE_CTXT:
- if (!pcid_enabled && (operand.pcid != 0)) {
- kvm_inject_gp(vcpu, 0);
- return 1;
- }
-
- if (kvm_get_active_pcid(vcpu) == operand.pcid) {
- kvm_mmu_sync_roots(vcpu);
- kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
- }
-
- for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++)
- if (kvm_get_pcid(vcpu, vcpu->arch.mmu.prev_roots[i].cr3)
- == operand.pcid)
- roots_to_free |= KVM_MMU_ROOT_PREVIOUS(i);
-
- kvm_mmu_free_roots(vcpu, roots_to_free);
- /*
- * If neither the current cr3 nor any of the prev_roots use the
- * given PCID, then nothing needs to be done here because a
- * resync will happen anyway before switching to any other CR3.
- */
-
- return kvm_skip_emulated_instruction(vcpu);
-
- case INVPCID_TYPE_ALL_NON_GLOBAL:
- /*
- * Currently, KVM doesn't mark global entries in the shadow
- * page tables, so a non-global flush just degenerates to a
- * global flush. If needed, we could optimize this later by
- * keeping track of global entries in shadow page tables.
- */
-
- /* fall-through */
- case INVPCID_TYPE_ALL_INCL_GLOBAL:
- kvm_mmu_unload(vcpu);
- return kvm_skip_emulated_instruction(vcpu);
-
- default:
- BUG(); /* We have already checked above that type <= 3 */
- }
-}
-
-static int handle_pml_full(struct kvm_vcpu *vcpu)
-{
- unsigned long exit_qualification;
-
- trace_kvm_pml_full(vcpu->vcpu_id);
-
- exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- /*
- * PML buffer FULL happened while executing iret from NMI,
- * "blocked by NMI" bit has to be set before next VM entry.
- */
- if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
- enable_vnmi &&
- (exit_qualification & INTR_INFO_UNBLOCK_NMI))
- vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_NMI);
-
- /*
- * PML buffer already flushed at beginning of VMEXIT. Nothing to do
- * here.., and there's no userspace involvement needed for PML.
- */
- return 1;
-}
-
-static int handle_preemption_timer(struct kvm_vcpu *vcpu)
-{
- if (!to_vmx(vcpu)->req_immediate_exit)
- kvm_lapic_expired_hv_timer(vcpu);
- return 1;
-}
-
-static bool valid_ept_address(struct kvm_vcpu *vcpu, u64 address)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int maxphyaddr = cpuid_maxphyaddr(vcpu);
-
- /* Check for memory type validity */
- switch (address & VMX_EPTP_MT_MASK) {
- case VMX_EPTP_MT_UC:
- if (!(vmx->nested.msrs.ept_caps & VMX_EPTP_UC_BIT))
- return false;
- break;
- case VMX_EPTP_MT_WB:
- if (!(vmx->nested.msrs.ept_caps & VMX_EPTP_WB_BIT))
- return false;
- break;
- default:
- return false;
- }
-
- /* only 4 levels page-walk length are valid */
- if ((address & VMX_EPTP_PWL_MASK) != VMX_EPTP_PWL_4)
- return false;
-
- /* Reserved bits should not be set */
- if (address >> maxphyaddr || ((address >> 7) & 0x1f))
- return false;
-
- /* AD, if set, should be supported */
- if (address & VMX_EPTP_AD_ENABLE_BIT) {
- if (!(vmx->nested.msrs.ept_caps & VMX_EPT_AD_BIT))
- return false;
- }
-
- return true;
-}
-
-static int nested_vmx_eptp_switching(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- u32 index = vcpu->arch.regs[VCPU_REGS_RCX];
- u64 address;
- bool accessed_dirty;
- struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
-
- if (!nested_cpu_has_eptp_switching(vmcs12) ||
- !nested_cpu_has_ept(vmcs12))
- return 1;
-
- if (index >= VMFUNC_EPTP_ENTRIES)
- return 1;
-
-
- if (kvm_vcpu_read_guest_page(vcpu, vmcs12->eptp_list_address >> PAGE_SHIFT,
- &address, index * 8, 8))
- return 1;
-
- accessed_dirty = !!(address & VMX_EPTP_AD_ENABLE_BIT);
-
- /*
- * If the (L2) guest does a vmfunc to the currently
- * active ept pointer, we don't have to do anything else
- */
- if (vmcs12->ept_pointer != address) {
- if (!valid_ept_address(vcpu, address))
- return 1;
-
- kvm_mmu_unload(vcpu);
- mmu->ept_ad = accessed_dirty;
- mmu->base_role.ad_disabled = !accessed_dirty;
- vmcs12->ept_pointer = address;
- /*
- * TODO: Check what's the correct approach in case
- * mmu reload fails. Currently, we just let the next
- * reload potentially fail
- */
- kvm_mmu_reload(vcpu);
- }
-
- return 0;
-}
-
-static int handle_vmfunc(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct vmcs12 *vmcs12;
- u32 function = vcpu->arch.regs[VCPU_REGS_RAX];
-
- /*
- * VMFUNC is only supported for nested guests, but we always enable the
- * secondary control for simplicity; for non-nested mode, fake that we
- * didn't by injecting #UD.
- */
- if (!is_guest_mode(vcpu)) {
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
- }
-
- vmcs12 = get_vmcs12(vcpu);
- if ((vmcs12->vm_function_control & (1 << function)) == 0)
- goto fail;
-
- switch (function) {
- case 0:
- if (nested_vmx_eptp_switching(vcpu, vmcs12))
- goto fail;
- break;
- default:
- goto fail;
- }
- return kvm_skip_emulated_instruction(vcpu);
-
-fail:
- nested_vmx_vmexit(vcpu, vmx->exit_reason,
- vmcs_read32(VM_EXIT_INTR_INFO),
- vmcs_readl(EXIT_QUALIFICATION));
- return 1;
-}
-
-static int handle_encls(struct kvm_vcpu *vcpu)
-{
- /*
- * SGX virtualization is not yet supported. There is no software
- * enable bit for SGX, so we have to trap ENCLS and inject a #UD
- * to prevent the guest from executing ENCLS.
- */
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
-}
-
-/*
- * The exit handlers return 1 if the exit was handled fully and guest execution
- * may resume. Otherwise they set the kvm_run parameter to indicate what needs
- * to be done to userspace and return 0.
- */
-static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
- [EXIT_REASON_EXCEPTION_NMI] = handle_exception,
- [EXIT_REASON_EXTERNAL_INTERRUPT] = handle_external_interrupt,
- [EXIT_REASON_TRIPLE_FAULT] = handle_triple_fault,
- [EXIT_REASON_NMI_WINDOW] = handle_nmi_window,
- [EXIT_REASON_IO_INSTRUCTION] = handle_io,
- [EXIT_REASON_CR_ACCESS] = handle_cr,
- [EXIT_REASON_DR_ACCESS] = handle_dr,
- [EXIT_REASON_CPUID] = handle_cpuid,
- [EXIT_REASON_MSR_READ] = handle_rdmsr,
- [EXIT_REASON_MSR_WRITE] = handle_wrmsr,
- [EXIT_REASON_PENDING_INTERRUPT] = handle_interrupt_window,
- [EXIT_REASON_HLT] = handle_halt,
- [EXIT_REASON_INVD] = handle_invd,
- [EXIT_REASON_INVLPG] = handle_invlpg,
- [EXIT_REASON_RDPMC] = handle_rdpmc,
- [EXIT_REASON_VMCALL] = handle_vmcall,
- [EXIT_REASON_VMCLEAR] = handle_vmclear,
- [EXIT_REASON_VMLAUNCH] = handle_vmlaunch,
- [EXIT_REASON_VMPTRLD] = handle_vmptrld,
- [EXIT_REASON_VMPTRST] = handle_vmptrst,
- [EXIT_REASON_VMREAD] = handle_vmread,
- [EXIT_REASON_VMRESUME] = handle_vmresume,
- [EXIT_REASON_VMWRITE] = handle_vmwrite,
- [EXIT_REASON_VMOFF] = handle_vmoff,
- [EXIT_REASON_VMON] = handle_vmon,
- [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold,
- [EXIT_REASON_APIC_ACCESS] = handle_apic_access,
- [EXIT_REASON_APIC_WRITE] = handle_apic_write,
- [EXIT_REASON_EOI_INDUCED] = handle_apic_eoi_induced,
- [EXIT_REASON_WBINVD] = handle_wbinvd,
- [EXIT_REASON_XSETBV] = handle_xsetbv,
- [EXIT_REASON_TASK_SWITCH] = handle_task_switch,
- [EXIT_REASON_MCE_DURING_VMENTRY] = handle_machine_check,
- [EXIT_REASON_GDTR_IDTR] = handle_desc,
- [EXIT_REASON_LDTR_TR] = handle_desc,
- [EXIT_REASON_EPT_VIOLATION] = handle_ept_violation,
- [EXIT_REASON_EPT_MISCONFIG] = handle_ept_misconfig,
- [EXIT_REASON_PAUSE_INSTRUCTION] = handle_pause,
- [EXIT_REASON_MWAIT_INSTRUCTION] = handle_mwait,
- [EXIT_REASON_MONITOR_TRAP_FLAG] = handle_monitor_trap,
- [EXIT_REASON_MONITOR_INSTRUCTION] = handle_monitor,
- [EXIT_REASON_INVEPT] = handle_invept,
- [EXIT_REASON_INVVPID] = handle_invvpid,
- [EXIT_REASON_RDRAND] = handle_invalid_op,
- [EXIT_REASON_RDSEED] = handle_invalid_op,
- [EXIT_REASON_XSAVES] = handle_xsaves,
- [EXIT_REASON_XRSTORS] = handle_xrstors,
- [EXIT_REASON_PML_FULL] = handle_pml_full,
- [EXIT_REASON_INVPCID] = handle_invpcid,
- [EXIT_REASON_VMFUNC] = handle_vmfunc,
- [EXIT_REASON_PREEMPTION_TIMER] = handle_preemption_timer,
- [EXIT_REASON_ENCLS] = handle_encls,
-};
-
-static const int kvm_vmx_max_exit_handlers =
- ARRAY_SIZE(kvm_vmx_exit_handlers);
-
-/*
- * Return true if an IO instruction with the specified port and size should cause
- * a VM-exit into L1.
- */
-bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
- int size)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- gpa_t bitmap, last_bitmap;
- u8 b;
-
- last_bitmap = (gpa_t)-1;
- b = -1;
-
- while (size > 0) {
- if (port < 0x8000)
- bitmap = vmcs12->io_bitmap_a;
- else if (port < 0x10000)
- bitmap = vmcs12->io_bitmap_b;
- else
- return true;
- bitmap += (port & 0x7fff) / 8;
-
- if (last_bitmap != bitmap)
- if (kvm_vcpu_read_guest(vcpu, bitmap, &b, 1))
- return true;
- if (b & (1 << (port & 7)))
- return true;
-
- port++;
- size--;
- last_bitmap = bitmap;
- }
-
- return false;
-}
-
-/*
- * Return 1 if we should exit from L2 to L1 to handle an MSR access access,
- * rather than handle it ourselves in L0. I.e., check whether L1 expressed
- * disinterest in the current event (read or write a specific MSR) by using an
- * MSR bitmap. This may be the case even when L0 doesn't use MSR bitmaps.
- */
-static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12, u32 exit_reason)
-{
- u32 msr_index = vcpu->arch.regs[VCPU_REGS_RCX];
- gpa_t bitmap;
-
- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_MSR_BITMAPS))
- return true;
-
- /*
- * The MSR_BITMAP page is divided into four 1024-byte bitmaps,
- * for the four combinations of read/write and low/high MSR numbers.
- * First we need to figure out which of the four to use:
- */
- bitmap = vmcs12->msr_bitmap;
- if (exit_reason == EXIT_REASON_MSR_WRITE)
- bitmap += 2048;
- if (msr_index >= 0xc0000000) {
- msr_index -= 0xc0000000;
- bitmap += 1024;
- }
-
- /* Then read the msr_index'th bit from this bitmap: */
- if (msr_index < 1024*8) {
- unsigned char b;
- if (kvm_vcpu_read_guest(vcpu, bitmap + msr_index/8, &b, 1))
- return true;
- return 1 & (b >> (msr_index & 7));
- } else
- return true; /* let L1 handle the wrong parameter */
-}
-
-/*
- * Return 1 if we should exit from L2 to L1 to handle a CR access exit,
- * rather than handle it ourselves in L0. I.e., check if L1 wanted to
- * intercept (via guest_host_mask etc.) the current event.
- */
-static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
- int cr = exit_qualification & 15;
- int reg;
- unsigned long val;
-
- switch ((exit_qualification >> 4) & 3) {
- case 0: /* mov to cr */
- reg = (exit_qualification >> 8) & 15;
- val = kvm_register_readl(vcpu, reg);
- switch (cr) {
- case 0:
- if (vmcs12->cr0_guest_host_mask &
- (val ^ vmcs12->cr0_read_shadow))
- return true;
- break;
- case 3:
- if ((vmcs12->cr3_target_count >= 1 &&
- vmcs12->cr3_target_value0 == val) ||
- (vmcs12->cr3_target_count >= 2 &&
- vmcs12->cr3_target_value1 == val) ||
- (vmcs12->cr3_target_count >= 3 &&
- vmcs12->cr3_target_value2 == val) ||
- (vmcs12->cr3_target_count >= 4 &&
- vmcs12->cr3_target_value3 == val))
- return false;
- if (nested_cpu_has(vmcs12, CPU_BASED_CR3_LOAD_EXITING))
- return true;
- break;
- case 4:
- if (vmcs12->cr4_guest_host_mask &
- (vmcs12->cr4_read_shadow ^ val))
- return true;
- break;
- case 8:
- if (nested_cpu_has(vmcs12, CPU_BASED_CR8_LOAD_EXITING))
- return true;
- break;
- }
- break;
- case 2: /* clts */
- if ((vmcs12->cr0_guest_host_mask & X86_CR0_TS) &&
- (vmcs12->cr0_read_shadow & X86_CR0_TS))
- return true;
- break;
- case 1: /* mov from cr */
- switch (cr) {
- case 3:
- if (vmcs12->cpu_based_vm_exec_control &
- CPU_BASED_CR3_STORE_EXITING)
- return true;
- break;
- case 8:
- if (vmcs12->cpu_based_vm_exec_control &
- CPU_BASED_CR8_STORE_EXITING)
- return true;
- break;
- }
- break;
- case 3: /* lmsw */
- /*
- * lmsw can change bits 1..3 of cr0, and only set bit 0 of
- * cr0. Other attempted changes are ignored, with no exit.
- */
- val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f;
- if (vmcs12->cr0_guest_host_mask & 0xe &
- (val ^ vmcs12->cr0_read_shadow))
- return true;
- if ((vmcs12->cr0_guest_host_mask & 0x1) &&
- !(vmcs12->cr0_read_shadow & 0x1) &&
- (val & 0x1))
- return true;
- break;
- }
- return false;
-}
-
-static bool nested_vmx_exit_handled_vmcs_access(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12, gpa_t bitmap)
-{
- u32 vmx_instruction_info;
- unsigned long field;
- u8 b;
-
- if (!nested_cpu_has_shadow_vmcs(vmcs12))
- return true;
-
- /* Decode instruction info and find the field to access */
- vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
- field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
-
- /* Out-of-range fields always cause a VM exit from L2 to L1 */
- if (field >> 15)
- return true;
-
- if (kvm_vcpu_read_guest(vcpu, bitmap + field/8, &b, 1))
- return true;
-
- return 1 & (b >> (field & 7));
-}
-
-/*
- * Return 1 if we should exit from L2 to L1 to handle an exit, or 0 if we
- * should handle it ourselves in L0 (and then continue L2). Only call this
- * when in is_guest_mode (L2).
- */
-static bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
-{
- u32 intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
-
- if (vmx->nested.nested_run_pending)
- return false;
-
- if (unlikely(vmx->fail)) {
- pr_info_ratelimited("%s failed vm entry %x\n", __func__,
- vmcs_read32(VM_INSTRUCTION_ERROR));
- return true;
- }
-
- /*
- * The host physical addresses of some pages of guest memory
- * are loaded into the vmcs02 (e.g. vmcs12's Virtual APIC
- * Page). The CPU may write to these pages via their host
- * physical address while L2 is running, bypassing any
- * address-translation-based dirty tracking (e.g. EPT write
- * protection).
- *
- * Mark them dirty on every exit from L2 to prevent them from
- * getting out of sync with dirty tracking.
- */
- nested_mark_vmcs12_pages_dirty(vcpu);
-
- trace_kvm_nested_vmexit(kvm_rip_read(vcpu), exit_reason,
- vmcs_readl(EXIT_QUALIFICATION),
- vmx->idt_vectoring_info,
- intr_info,
- vmcs_read32(VM_EXIT_INTR_ERROR_CODE),
- KVM_ISA_VMX);
-
- switch ((u16)exit_reason) {
- case EXIT_REASON_EXCEPTION_NMI:
- if (is_nmi(intr_info))
- return false;
- else if (is_page_fault(intr_info))
- return !vmx->vcpu.arch.apf.host_apf_reason && enable_ept;
- else if (is_no_device(intr_info) &&
- !(vmcs12->guest_cr0 & X86_CR0_TS))
- return false;
- else if (is_debug(intr_info) &&
- vcpu->guest_debug &
- (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
- return false;
- else if (is_breakpoint(intr_info) &&
- vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
- return false;
- return vmcs12->exception_bitmap &
- (1u << (intr_info & INTR_INFO_VECTOR_MASK));
- case EXIT_REASON_EXTERNAL_INTERRUPT:
- return false;
- case EXIT_REASON_TRIPLE_FAULT:
- return true;
- case EXIT_REASON_PENDING_INTERRUPT:
- return nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_INTR_PENDING);
- case EXIT_REASON_NMI_WINDOW:
- return nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_NMI_PENDING);
- case EXIT_REASON_TASK_SWITCH:
- return true;
- case EXIT_REASON_CPUID:
- return true;
- case EXIT_REASON_HLT:
- return nested_cpu_has(vmcs12, CPU_BASED_HLT_EXITING);
- case EXIT_REASON_INVD:
- return true;
- case EXIT_REASON_INVLPG:
- return nested_cpu_has(vmcs12, CPU_BASED_INVLPG_EXITING);
- case EXIT_REASON_RDPMC:
- return nested_cpu_has(vmcs12, CPU_BASED_RDPMC_EXITING);
- case EXIT_REASON_RDRAND:
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDRAND_EXITING);
- case EXIT_REASON_RDSEED:
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDSEED_EXITING);
- case EXIT_REASON_RDTSC: case EXIT_REASON_RDTSCP:
- return nested_cpu_has(vmcs12, CPU_BASED_RDTSC_EXITING);
- case EXIT_REASON_VMREAD:
- return nested_vmx_exit_handled_vmcs_access(vcpu, vmcs12,
- vmcs12->vmread_bitmap);
- case EXIT_REASON_VMWRITE:
- return nested_vmx_exit_handled_vmcs_access(vcpu, vmcs12,
- vmcs12->vmwrite_bitmap);
- case EXIT_REASON_VMCALL: case EXIT_REASON_VMCLEAR:
- case EXIT_REASON_VMLAUNCH: case EXIT_REASON_VMPTRLD:
- case EXIT_REASON_VMPTRST: case EXIT_REASON_VMRESUME:
- case EXIT_REASON_VMOFF: case EXIT_REASON_VMON:
- case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID:
- /*
- * VMX instructions trap unconditionally. This allows L1 to
- * emulate them for its L2 guest, i.e., allows 3-level nesting!
- */
- return true;
- case EXIT_REASON_CR_ACCESS:
- return nested_vmx_exit_handled_cr(vcpu, vmcs12);
- case EXIT_REASON_DR_ACCESS:
- return nested_cpu_has(vmcs12, CPU_BASED_MOV_DR_EXITING);
- case EXIT_REASON_IO_INSTRUCTION:
- return nested_vmx_exit_handled_io(vcpu, vmcs12);
- case EXIT_REASON_GDTR_IDTR: case EXIT_REASON_LDTR_TR:
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC);
- case EXIT_REASON_MSR_READ:
- case EXIT_REASON_MSR_WRITE:
- return nested_vmx_exit_handled_msr(vcpu, vmcs12, exit_reason);
- case EXIT_REASON_INVALID_STATE:
- return true;
- case EXIT_REASON_MWAIT_INSTRUCTION:
- return nested_cpu_has(vmcs12, CPU_BASED_MWAIT_EXITING);
- case EXIT_REASON_MONITOR_TRAP_FLAG:
- return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_TRAP_FLAG);
- case EXIT_REASON_MONITOR_INSTRUCTION:
- return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_EXITING);
- case EXIT_REASON_PAUSE_INSTRUCTION:
- return nested_cpu_has(vmcs12, CPU_BASED_PAUSE_EXITING) ||
- nested_cpu_has2(vmcs12,
- SECONDARY_EXEC_PAUSE_LOOP_EXITING);
- case EXIT_REASON_MCE_DURING_VMENTRY:
- return false;
- case EXIT_REASON_TPR_BELOW_THRESHOLD:
- return nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW);
- case EXIT_REASON_APIC_ACCESS:
- case EXIT_REASON_APIC_WRITE:
- case EXIT_REASON_EOI_INDUCED:
- /*
- * The controls for "virtualize APIC accesses," "APIC-
- * register virtualization," and "virtual-interrupt
- * delivery" only come from vmcs12.
- */
- return true;
- case EXIT_REASON_EPT_VIOLATION:
- /*
- * L0 always deals with the EPT violation. If nested EPT is
- * used, and the nested mmu code discovers that the address is
- * missing in the guest EPT table (EPT12), the EPT violation
- * will be injected with nested_ept_inject_page_fault()
- */
- return false;
- case EXIT_REASON_EPT_MISCONFIG:
- /*
- * L2 never uses directly L1's EPT, but rather L0's own EPT
- * table (shadow on EPT) or a merged EPT table that L0 built
- * (EPT on EPT). So any problems with the structure of the
- * table is L0's fault.
- */
- return false;
- case EXIT_REASON_INVPCID:
- return
- nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_INVPCID) &&
- nested_cpu_has(vmcs12, CPU_BASED_INVLPG_EXITING);
- case EXIT_REASON_WBINVD:
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING);
- case EXIT_REASON_XSETBV:
- return true;
- case EXIT_REASON_XSAVES: case EXIT_REASON_XRSTORS:
- /*
- * This should never happen, since it is not possible to
- * set XSS to a non-zero value---neither in L1 nor in L2.
- * If if it were, XSS would have to be checked against
- * the XSS exit bitmap in vmcs12.
- */
- return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES);
- case EXIT_REASON_PREEMPTION_TIMER:
- return false;
- case EXIT_REASON_PML_FULL:
- /* We emulate PML support to L1. */
- return false;
- case EXIT_REASON_VMFUNC:
- /* VM functions are emulated through L2->L0 vmexits. */
- return false;
- case EXIT_REASON_ENCLS:
- /* SGX is never exposed to L1 */
- return false;
- default:
- return true;
- }
-}
-
-static int nested_vmx_reflect_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason)
-{
- u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
-
- /*
- * At this point, the exit interruption info in exit_intr_info
- * is only valid for EXCEPTION_NMI exits. For EXTERNAL_INTERRUPT
- * we need to query the in-kernel LAPIC.
- */
- WARN_ON(exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT);
- if ((exit_intr_info &
- (INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK)) ==
- (INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK)) {
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- vmcs12->vm_exit_intr_error_code =
- vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
- }
-
- nested_vmx_vmexit(vcpu, exit_reason, exit_intr_info,
- vmcs_readl(EXIT_QUALIFICATION));
- return 1;
-}
-
-static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
-{
- *info1 = vmcs_readl(EXIT_QUALIFICATION);
- *info2 = vmcs_read32(VM_EXIT_INTR_INFO);
-}
-
-static void vmx_destroy_pml_buffer(struct vcpu_vmx *vmx)
-{
- if (vmx->pml_pg) {
- __free_page(vmx->pml_pg);
- vmx->pml_pg = NULL;
- }
-}
-
-static void vmx_flush_pml_buffer(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u64 *pml_buf;
- u16 pml_idx;
-
- pml_idx = vmcs_read16(GUEST_PML_INDEX);
-
- /* Do nothing if PML buffer is empty */
- if (pml_idx == (PML_ENTITY_NUM - 1))
- return;
-
- /* PML index always points to next available PML buffer entity */
- if (pml_idx >= PML_ENTITY_NUM)
- pml_idx = 0;
- else
- pml_idx++;
-
- pml_buf = page_address(vmx->pml_pg);
- for (; pml_idx < PML_ENTITY_NUM; pml_idx++) {
- u64 gpa;
-
- gpa = pml_buf[pml_idx];
- WARN_ON(gpa & (PAGE_SIZE - 1));
- kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
- }
-
- /* reset PML index */
- vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
-}
-
-/*
- * Flush all vcpus' PML buffer and update logged GPAs to dirty_bitmap.
- * Called before reporting dirty_bitmap to userspace.
- */
-static void kvm_flush_pml_buffers(struct kvm *kvm)
-{
- int i;
- struct kvm_vcpu *vcpu;
- /*
- * We only need to kick vcpu out of guest mode here, as PML buffer
- * is flushed at beginning of all VMEXITs, and it's obvious that only
- * vcpus running in guest are possible to have unflushed GPAs in PML
- * buffer.
- */
- kvm_for_each_vcpu(i, vcpu, kvm)
- kvm_vcpu_kick(vcpu);
-}
-
-static void vmx_dump_sel(char *name, uint32_t sel)
-{
- pr_err("%s sel=0x%04x, attr=0x%05x, limit=0x%08x, base=0x%016lx\n",
- name, vmcs_read16(sel),
- vmcs_read32(sel + GUEST_ES_AR_BYTES - GUEST_ES_SELECTOR),
- vmcs_read32(sel + GUEST_ES_LIMIT - GUEST_ES_SELECTOR),
- vmcs_readl(sel + GUEST_ES_BASE - GUEST_ES_SELECTOR));
-}
-
-static void vmx_dump_dtsel(char *name, uint32_t limit)
-{
- pr_err("%s limit=0x%08x, base=0x%016lx\n",
- name, vmcs_read32(limit),
- vmcs_readl(limit + GUEST_GDTR_BASE - GUEST_GDTR_LIMIT));
-}
-
-static void dump_vmcs(void)
-{
- u32 vmentry_ctl = vmcs_read32(VM_ENTRY_CONTROLS);
- u32 vmexit_ctl = vmcs_read32(VM_EXIT_CONTROLS);
- u32 cpu_based_exec_ctrl = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
- u32 pin_based_exec_ctrl = vmcs_read32(PIN_BASED_VM_EXEC_CONTROL);
- u32 secondary_exec_control = 0;
- unsigned long cr4 = vmcs_readl(GUEST_CR4);
- u64 efer = vmcs_read64(GUEST_IA32_EFER);
- int i, n;
-
- if (cpu_has_secondary_exec_ctrls())
- secondary_exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
-
- pr_err("*** Guest State ***\n");
- pr_err("CR0: actual=0x%016lx, shadow=0x%016lx, gh_mask=%016lx\n",
- vmcs_readl(GUEST_CR0), vmcs_readl(CR0_READ_SHADOW),
- vmcs_readl(CR0_GUEST_HOST_MASK));
- pr_err("CR4: actual=0x%016lx, shadow=0x%016lx, gh_mask=%016lx\n",
- cr4, vmcs_readl(CR4_READ_SHADOW), vmcs_readl(CR4_GUEST_HOST_MASK));
- pr_err("CR3 = 0x%016lx\n", vmcs_readl(GUEST_CR3));
- if ((secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT) &&
- (cr4 & X86_CR4_PAE) && !(efer & EFER_LMA))
- {
- pr_err("PDPTR0 = 0x%016llx PDPTR1 = 0x%016llx\n",
- vmcs_read64(GUEST_PDPTR0), vmcs_read64(GUEST_PDPTR1));
- pr_err("PDPTR2 = 0x%016llx PDPTR3 = 0x%016llx\n",
- vmcs_read64(GUEST_PDPTR2), vmcs_read64(GUEST_PDPTR3));
- }
- pr_err("RSP = 0x%016lx RIP = 0x%016lx\n",
- vmcs_readl(GUEST_RSP), vmcs_readl(GUEST_RIP));
- pr_err("RFLAGS=0x%08lx DR7 = 0x%016lx\n",
- vmcs_readl(GUEST_RFLAGS), vmcs_readl(GUEST_DR7));
- pr_err("Sysenter RSP=%016lx CS:RIP=%04x:%016lx\n",
- vmcs_readl(GUEST_SYSENTER_ESP),
- vmcs_read32(GUEST_SYSENTER_CS), vmcs_readl(GUEST_SYSENTER_EIP));
- vmx_dump_sel("CS: ", GUEST_CS_SELECTOR);
- vmx_dump_sel("DS: ", GUEST_DS_SELECTOR);
- vmx_dump_sel("SS: ", GUEST_SS_SELECTOR);
- vmx_dump_sel("ES: ", GUEST_ES_SELECTOR);
- vmx_dump_sel("FS: ", GUEST_FS_SELECTOR);
- vmx_dump_sel("GS: ", GUEST_GS_SELECTOR);
- vmx_dump_dtsel("GDTR:", GUEST_GDTR_LIMIT);
- vmx_dump_sel("LDTR:", GUEST_LDTR_SELECTOR);
- vmx_dump_dtsel("IDTR:", GUEST_IDTR_LIMIT);
- vmx_dump_sel("TR: ", GUEST_TR_SELECTOR);
- if ((vmexit_ctl & (VM_EXIT_SAVE_IA32_PAT | VM_EXIT_SAVE_IA32_EFER)) ||
- (vmentry_ctl & (VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_LOAD_IA32_EFER)))
- pr_err("EFER = 0x%016llx PAT = 0x%016llx\n",
- efer, vmcs_read64(GUEST_IA32_PAT));
- pr_err("DebugCtl = 0x%016llx DebugExceptions = 0x%016lx\n",
- vmcs_read64(GUEST_IA32_DEBUGCTL),
- vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS));
- if (cpu_has_load_perf_global_ctrl &&
- vmentry_ctl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
- pr_err("PerfGlobCtl = 0x%016llx\n",
- vmcs_read64(GUEST_IA32_PERF_GLOBAL_CTRL));
- if (vmentry_ctl & VM_ENTRY_LOAD_BNDCFGS)
- pr_err("BndCfgS = 0x%016llx\n", vmcs_read64(GUEST_BNDCFGS));
- pr_err("Interruptibility = %08x ActivityState = %08x\n",
- vmcs_read32(GUEST_INTERRUPTIBILITY_INFO),
- vmcs_read32(GUEST_ACTIVITY_STATE));
- if (secondary_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)
- pr_err("InterruptStatus = %04x\n",
- vmcs_read16(GUEST_INTR_STATUS));
-
- pr_err("*** Host State ***\n");
- pr_err("RIP = 0x%016lx RSP = 0x%016lx\n",
- vmcs_readl(HOST_RIP), vmcs_readl(HOST_RSP));
- pr_err("CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x TR=%04x\n",
- vmcs_read16(HOST_CS_SELECTOR), vmcs_read16(HOST_SS_SELECTOR),
- vmcs_read16(HOST_DS_SELECTOR), vmcs_read16(HOST_ES_SELECTOR),
- vmcs_read16(HOST_FS_SELECTOR), vmcs_read16(HOST_GS_SELECTOR),
- vmcs_read16(HOST_TR_SELECTOR));
- pr_err("FSBase=%016lx GSBase=%016lx TRBase=%016lx\n",
- vmcs_readl(HOST_FS_BASE), vmcs_readl(HOST_GS_BASE),
- vmcs_readl(HOST_TR_BASE));
- pr_err("GDTBase=%016lx IDTBase=%016lx\n",
- vmcs_readl(HOST_GDTR_BASE), vmcs_readl(HOST_IDTR_BASE));
- pr_err("CR0=%016lx CR3=%016lx CR4=%016lx\n",
- vmcs_readl(HOST_CR0), vmcs_readl(HOST_CR3),
- vmcs_readl(HOST_CR4));
- pr_err("Sysenter RSP=%016lx CS:RIP=%04x:%016lx\n",
- vmcs_readl(HOST_IA32_SYSENTER_ESP),
- vmcs_read32(HOST_IA32_SYSENTER_CS),
- vmcs_readl(HOST_IA32_SYSENTER_EIP));
- if (vmexit_ctl & (VM_EXIT_LOAD_IA32_PAT | VM_EXIT_LOAD_IA32_EFER))
- pr_err("EFER = 0x%016llx PAT = 0x%016llx\n",
- vmcs_read64(HOST_IA32_EFER),
- vmcs_read64(HOST_IA32_PAT));
- if (cpu_has_load_perf_global_ctrl &&
- vmexit_ctl & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
- pr_err("PerfGlobCtl = 0x%016llx\n",
- vmcs_read64(HOST_IA32_PERF_GLOBAL_CTRL));
-
- pr_err("*** Control State ***\n");
- pr_err("PinBased=%08x CPUBased=%08x SecondaryExec=%08x\n",
- pin_based_exec_ctrl, cpu_based_exec_ctrl, secondary_exec_control);
- pr_err("EntryControls=%08x ExitControls=%08x\n", vmentry_ctl, vmexit_ctl);
- pr_err("ExceptionBitmap=%08x PFECmask=%08x PFECmatch=%08x\n",
- vmcs_read32(EXCEPTION_BITMAP),
- vmcs_read32(PAGE_FAULT_ERROR_CODE_MASK),
- vmcs_read32(PAGE_FAULT_ERROR_CODE_MATCH));
- pr_err("VMEntry: intr_info=%08x errcode=%08x ilen=%08x\n",
- vmcs_read32(VM_ENTRY_INTR_INFO_FIELD),
- vmcs_read32(VM_ENTRY_EXCEPTION_ERROR_CODE),
- vmcs_read32(VM_ENTRY_INSTRUCTION_LEN));
- pr_err("VMExit: intr_info=%08x errcode=%08x ilen=%08x\n",
- vmcs_read32(VM_EXIT_INTR_INFO),
- vmcs_read32(VM_EXIT_INTR_ERROR_CODE),
- vmcs_read32(VM_EXIT_INSTRUCTION_LEN));
- pr_err(" reason=%08x qualification=%016lx\n",
- vmcs_read32(VM_EXIT_REASON), vmcs_readl(EXIT_QUALIFICATION));
- pr_err("IDTVectoring: info=%08x errcode=%08x\n",
- vmcs_read32(IDT_VECTORING_INFO_FIELD),
- vmcs_read32(IDT_VECTORING_ERROR_CODE));
- pr_err("TSC Offset = 0x%016llx\n", vmcs_read64(TSC_OFFSET));
- if (secondary_exec_control & SECONDARY_EXEC_TSC_SCALING)
- pr_err("TSC Multiplier = 0x%016llx\n",
- vmcs_read64(TSC_MULTIPLIER));
- if (cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW)
- pr_err("TPR Threshold = 0x%02x\n", vmcs_read32(TPR_THRESHOLD));
- if (pin_based_exec_ctrl & PIN_BASED_POSTED_INTR)
- pr_err("PostedIntrVec = 0x%02x\n", vmcs_read16(POSTED_INTR_NV));
- if ((secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT))
- pr_err("EPT pointer = 0x%016llx\n", vmcs_read64(EPT_POINTER));
- n = vmcs_read32(CR3_TARGET_COUNT);
- for (i = 0; i + 1 < n; i += 4)
- pr_err("CR3 target%u=%016lx target%u=%016lx\n",
- i, vmcs_readl(CR3_TARGET_VALUE0 + i * 2),
- i + 1, vmcs_readl(CR3_TARGET_VALUE0 + i * 2 + 2));
- if (i < n)
- pr_err("CR3 target%u=%016lx\n",
- i, vmcs_readl(CR3_TARGET_VALUE0 + i * 2));
- if (secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING)
- pr_err("PLE Gap=%08x Window=%08x\n",
- vmcs_read32(PLE_GAP), vmcs_read32(PLE_WINDOW));
- if (secondary_exec_control & SECONDARY_EXEC_ENABLE_VPID)
- pr_err("Virtual processor ID = 0x%04x\n",
- vmcs_read16(VIRTUAL_PROCESSOR_ID));
-}
-
-/*
- * The guest has exited. See if we can fix it or if we need userspace
- * assistance.
- */
-static int vmx_handle_exit(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 exit_reason = vmx->exit_reason;
- u32 vectoring_info = vmx->idt_vectoring_info;
-
- trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX);
-
- /*
- * Flush logged GPAs PML buffer, this will make dirty_bitmap more
- * updated. Another good is, in kvm_vm_ioctl_get_dirty_log, before
- * querying dirty_bitmap, we only need to kick all vcpus out of guest
- * mode as if vcpus is in root mode, the PML buffer must has been
- * flushed already.
- */
- if (enable_pml)
- vmx_flush_pml_buffer(vcpu);
-
- /* If guest state is invalid, start emulating */
- if (vmx->emulation_required)
- return handle_invalid_guest_state(vcpu);
-
- if (is_guest_mode(vcpu) && nested_vmx_exit_reflected(vcpu, exit_reason))
- return nested_vmx_reflect_vmexit(vcpu, exit_reason);
-
- if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
- dump_vmcs();
- vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
- vcpu->run->fail_entry.hardware_entry_failure_reason
- = exit_reason;
- return 0;
- }
-
- if (unlikely(vmx->fail)) {
- vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
- vcpu->run->fail_entry.hardware_entry_failure_reason
- = vmcs_read32(VM_INSTRUCTION_ERROR);
- return 0;
- }
-
- /*
- * Note:
- * Do not try to fix EXIT_REASON_EPT_MISCONFIG if it caused by
- * delivery event since it indicates guest is accessing MMIO.
- * The vm-exit can be triggered again after return to guest that
- * will cause infinite loop.
- */
- if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
- (exit_reason != EXIT_REASON_EXCEPTION_NMI &&
- exit_reason != EXIT_REASON_EPT_VIOLATION &&
- exit_reason != EXIT_REASON_PML_FULL &&
- exit_reason != EXIT_REASON_APIC_ACCESS &&
- exit_reason != EXIT_REASON_TASK_SWITCH)) {
- vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
- vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
- vcpu->run->internal.ndata = 3;
- vcpu->run->internal.data[0] = vectoring_info;
- vcpu->run->internal.data[1] = exit_reason;
- vcpu->run->internal.data[2] = vcpu->arch.exit_qualification;
- if (exit_reason == EXIT_REASON_EPT_MISCONFIG) {
- vcpu->run->internal.ndata++;
- vcpu->run->internal.data[3] =
- vmcs_read64(GUEST_PHYSICAL_ADDRESS);
- }
- return 0;
- }
-
- if (unlikely(!enable_vnmi &&
- vmx->loaded_vmcs->soft_vnmi_blocked)) {
- if (vmx_interrupt_allowed(vcpu)) {
- vmx->loaded_vmcs->soft_vnmi_blocked = 0;
- } else if (vmx->loaded_vmcs->vnmi_blocked_time > 1000000000LL &&
- vcpu->arch.nmi_pending) {
- /*
- * This CPU don't support us in finding the end of an
- * NMI-blocked window if the guest runs with IRQs
- * disabled. So we pull the trigger after 1 s of
- * futile waiting, but inform the user about this.
- */
- printk(KERN_WARNING "%s: Breaking out of NMI-blocked "
- "state on VCPU %d after 1 s timeout\n",
- __func__, vcpu->vcpu_id);
- vmx->loaded_vmcs->soft_vnmi_blocked = 0;
- }
- }
-
- if (exit_reason < kvm_vmx_max_exit_handlers
- && kvm_vmx_exit_handlers[exit_reason])
- return kvm_vmx_exit_handlers[exit_reason](vcpu);
- else {
- vcpu_unimpl(vcpu, "vmx: unexpected exit reason 0x%x\n",
- exit_reason);
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
- }
-}
-
-/*
- * Software based L1D cache flush which is used when microcode providing
- * the cache control MSR is not loaded.
- *
- * The L1D cache is 32 KiB on Nehalem and later microarchitectures, but to
- * flush it is required to read in 64 KiB because the replacement algorithm
- * is not exactly LRU. This could be sized at runtime via topology
- * information but as all relevant affected CPUs have 32KiB L1D cache size
- * there is no point in doing so.
- */
-static void vmx_l1d_flush(struct kvm_vcpu *vcpu)
-{
- int size = PAGE_SIZE << L1D_CACHE_ORDER;
-
- /*
- * This code is only executed when the the flush mode is 'cond' or
- * 'always'
- */
- if (static_branch_likely(&vmx_l1d_flush_cond)) {
- bool flush_l1d;
-
- /*
- * Clear the per-vcpu flush bit, it gets set again
- * either from vcpu_run() or from one of the unsafe
- * VMEXIT handlers.
- */
- flush_l1d = vcpu->arch.l1tf_flush_l1d;
- vcpu->arch.l1tf_flush_l1d = false;
-
- /*
- * Clear the per-cpu flush bit, it gets set again from
- * the interrupt handlers.
- */
- flush_l1d |= kvm_get_cpu_l1tf_flush_l1d();
- kvm_clear_cpu_l1tf_flush_l1d();
-
- if (!flush_l1d)
- return;
- }
-
- vcpu->stat.l1d_flush++;
-
- if (static_cpu_has(X86_FEATURE_FLUSH_L1D)) {
- wrmsrl(MSR_IA32_FLUSH_CMD, L1D_FLUSH);
- return;
- }
-
- asm volatile(
- /* First ensure the pages are in the TLB */
- "xorl %%eax, %%eax\n"
- ".Lpopulate_tlb:\n\t"
- "movzbl (%[flush_pages], %%" _ASM_AX "), %%ecx\n\t"
- "addl $4096, %%eax\n\t"
- "cmpl %%eax, %[size]\n\t"
- "jne .Lpopulate_tlb\n\t"
- "xorl %%eax, %%eax\n\t"
- "cpuid\n\t"
- /* Now fill the cache */
- "xorl %%eax, %%eax\n"
- ".Lfill_cache:\n"
- "movzbl (%[flush_pages], %%" _ASM_AX "), %%ecx\n\t"
- "addl $64, %%eax\n\t"
- "cmpl %%eax, %[size]\n\t"
- "jne .Lfill_cache\n\t"
- "lfence\n"
- :: [flush_pages] "r" (vmx_l1d_flush_pages),
- [size] "r" (size)
- : "eax", "ebx", "ecx", "edx");
-}
-
-static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
-
- if (is_guest_mode(vcpu) &&
- nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
- return;
-
- if (irr == -1 || tpr < irr) {
- vmcs_write32(TPR_THRESHOLD, 0);
- return;
- }
-
- vmcs_write32(TPR_THRESHOLD, irr);
-}
-
-static void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
-{
- u32 sec_exec_control;
-
- if (!lapic_in_kernel(vcpu))
- return;
-
- if (!flexpriority_enabled &&
- !cpu_has_vmx_virtualize_x2apic_mode())
- return;
-
- /* Postpone execution until vmcs01 is the current VMCS. */
- if (is_guest_mode(vcpu)) {
- to_vmx(vcpu)->nested.change_vmcs01_virtual_apic_mode = true;
- return;
- }
-
- sec_exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
- sec_exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
- SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE);
-
- switch (kvm_get_apic_mode(vcpu)) {
- case LAPIC_MODE_INVALID:
- WARN_ONCE(true, "Invalid local APIC state");
- case LAPIC_MODE_DISABLED:
- break;
- case LAPIC_MODE_XAPIC:
- if (flexpriority_enabled) {
- sec_exec_control |=
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
- vmx_flush_tlb(vcpu, true);
- }
- break;
- case LAPIC_MODE_X2APIC:
- if (cpu_has_vmx_virtualize_x2apic_mode())
- sec_exec_control |=
- SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
- break;
- }
- vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control);
-
- vmx_update_msr_bitmap(vcpu);
-}
-
-static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa)
-{
- if (!is_guest_mode(vcpu)) {
- vmcs_write64(APIC_ACCESS_ADDR, hpa);
- vmx_flush_tlb(vcpu, true);
- }
-}
-
-static void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
-{
- u16 status;
- u8 old;
-
- if (max_isr == -1)
- max_isr = 0;
-
- status = vmcs_read16(GUEST_INTR_STATUS);
- old = status >> 8;
- if (max_isr != old) {
- status &= 0xff;
- status |= max_isr << 8;
- vmcs_write16(GUEST_INTR_STATUS, status);
- }
-}
-
-static void vmx_set_rvi(int vector)
-{
- u16 status;
- u8 old;
-
- if (vector == -1)
- vector = 0;
-
- status = vmcs_read16(GUEST_INTR_STATUS);
- old = (u8)status & 0xff;
- if ((u8)vector != old) {
- status &= ~0xff;
- status |= (u8)vector;
- vmcs_write16(GUEST_INTR_STATUS, status);
- }
-}
-
-static void vmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)
-{
- /*
- * When running L2, updating RVI is only relevant when
- * vmcs12 virtual-interrupt-delivery enabled.
- * However, it can be enabled only when L1 also
- * intercepts external-interrupts and in that case
- * we should not update vmcs02 RVI but instead intercept
- * interrupt. Therefore, do nothing when running L2.
- */
- if (!is_guest_mode(vcpu))
- vmx_set_rvi(max_irr);
-}
-
-static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int max_irr;
- bool max_irr_updated;
-
- WARN_ON(!vcpu->arch.apicv_active);
- if (pi_test_on(&vmx->pi_desc)) {
- pi_clear_on(&vmx->pi_desc);
- /*
- * IOMMU can write to PIR.ON, so the barrier matters even on UP.
- * But on x86 this is just a compiler barrier anyway.
- */
- smp_mb__after_atomic();
- max_irr_updated =
- kvm_apic_update_irr(vcpu, vmx->pi_desc.pir, &max_irr);
-
- /*
- * If we are running L2 and L1 has a new pending interrupt
- * which can be injected, we should re-evaluate
- * what should be done with this new L1 interrupt.
- * If L1 intercepts external-interrupts, we should
- * exit from L2 to L1. Otherwise, interrupt should be
- * delivered directly to L2.
- */
- if (is_guest_mode(vcpu) && max_irr_updated) {
- if (nested_exit_on_intr(vcpu))
- kvm_vcpu_exiting_guest_mode(vcpu);
- else
- kvm_make_request(KVM_REQ_EVENT, vcpu);
- }
- } else {
- max_irr = kvm_lapic_find_highest_irr(vcpu);
- }
- vmx_hwapic_irr_update(vcpu, max_irr);
- return max_irr;
-}
-
-static u8 vmx_has_apicv_interrupt(struct kvm_vcpu *vcpu)
-{
- u8 rvi = vmx_get_rvi();
- u8 vppr = kvm_lapic_get_reg(vcpu->arch.apic, APIC_PROCPRI);
-
- return ((rvi & 0xf0) > (vppr & 0xf0));
-}
-
-static bool vmx_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
-{
- return pi_test_on(vcpu_to_pi_desc(vcpu));
-}
-
-static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
-{
- if (!kvm_vcpu_apicv_active(vcpu))
- return;
-
- vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]);
- vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]);
- vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]);
- vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);
-}
-
-static void vmx_apicv_post_state_restore(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- pi_clear_on(&vmx->pi_desc);
- memset(vmx->pi_desc.pir, 0, sizeof(vmx->pi_desc.pir));
-}
-
-static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
-{
- if (vmx->exit_reason != EXIT_REASON_EXCEPTION_NMI)
- return;
-
- vmx->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
-
- /* if exit due to PF check for async PF */
- if (is_page_fault(vmx->exit_intr_info))
- vmx->vcpu.arch.apf.host_apf_reason = kvm_read_and_reset_pf_reason();
-
- /* Handle machine checks before interrupts are enabled */
- if (is_machine_check(vmx->exit_intr_info))
- kvm_machine_check();
-
- /* We need to handle NMIs before interrupts are enabled */
- if (is_nmi(vmx->exit_intr_info)) {
- kvm_before_interrupt(&vmx->vcpu);
- asm("int $2");
- kvm_after_interrupt(&vmx->vcpu);
- }
-}
-
-static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
-{
- u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
-
- if ((exit_intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK))
- == (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR)) {
- unsigned int vector;
- unsigned long entry;
- gate_desc *desc;
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-#ifdef CONFIG_X86_64
- unsigned long tmp;
-#endif
-
- vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
- desc = (gate_desc *)vmx->host_idt_base + vector;
- entry = gate_offset(desc);
- asm volatile(
-#ifdef CONFIG_X86_64
- "mov %%" _ASM_SP ", %[sp]\n\t"
- "and $0xfffffffffffffff0, %%" _ASM_SP "\n\t"
- "push $%c[ss]\n\t"
- "push %[sp]\n\t"
-#endif
- "pushf\n\t"
- __ASM_SIZE(push) " $%c[cs]\n\t"
- CALL_NOSPEC
- :
-#ifdef CONFIG_X86_64
- [sp]"=&r"(tmp),
-#endif
- ASM_CALL_CONSTRAINT
- :
- THUNK_TARGET(entry),
- [ss]"i"(__KERNEL_DS),
- [cs]"i"(__KERNEL_CS)
- );
- }
-}
-STACK_FRAME_NON_STANDARD(vmx_handle_external_intr);
-
-static bool vmx_has_emulated_msr(int index)
-{
- switch (index) {
- case MSR_IA32_SMBASE:
- /*
- * We cannot do SMM unless we can run the guest in big
- * real mode.
- */
- return enable_unrestricted_guest || emulate_invalid_guest_state;
- case MSR_AMD64_VIRT_SPEC_CTRL:
- /* This is AMD only. */
- return false;
- default:
- return true;
- }
-}
-
-static bool vmx_mpx_supported(void)
-{
- return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_BNDCFGS) &&
- (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS);
-}
-
-static bool vmx_xsaves_supported(void)
-{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_XSAVES;
-}
-
-static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
-{
- u32 exit_intr_info;
- bool unblock_nmi;
- u8 vector;
- bool idtv_info_valid;
-
- idtv_info_valid = vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK;
-
- if (enable_vnmi) {
- if (vmx->loaded_vmcs->nmi_known_unmasked)
- return;
- /*
- * Can't use vmx->exit_intr_info since we're not sure what
- * the exit reason is.
- */
- exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
- unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
- vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
- /*
- * SDM 3: 27.7.1.2 (September 2008)
- * Re-set bit "block by NMI" before VM entry if vmexit caused by
- * a guest IRET fault.
- * SDM 3: 23.2.2 (September 2008)
- * Bit 12 is undefined in any of the following cases:
- * If the VM exit sets the valid bit in the IDT-vectoring
- * information field.
- * If the VM exit is due to a double fault.
- */
- if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
- vector != DF_VECTOR && !idtv_info_valid)
- vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_NMI);
- else
- vmx->loaded_vmcs->nmi_known_unmasked =
- !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO)
- & GUEST_INTR_STATE_NMI);
- } else if (unlikely(vmx->loaded_vmcs->soft_vnmi_blocked))
- vmx->loaded_vmcs->vnmi_blocked_time +=
- ktime_to_ns(ktime_sub(ktime_get(),
- vmx->loaded_vmcs->entry_time));
-}
-
-static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu,
- u32 idt_vectoring_info,
- int instr_len_field,
- int error_code_field)
-{
- u8 vector;
- int type;
- bool idtv_info_valid;
-
- idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
-
- vcpu->arch.nmi_injected = false;
- kvm_clear_exception_queue(vcpu);
- kvm_clear_interrupt_queue(vcpu);
-
- if (!idtv_info_valid)
- return;
-
- kvm_make_request(KVM_REQ_EVENT, vcpu);
-
- vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
- type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
-
- switch (type) {
- case INTR_TYPE_NMI_INTR:
- vcpu->arch.nmi_injected = true;
- /*
- * SDM 3: 27.7.1.2 (September 2008)
- * Clear bit "block by NMI" before VM entry if a NMI
- * delivery faulted.
- */
- vmx_set_nmi_mask(vcpu, false);
- break;
- case INTR_TYPE_SOFT_EXCEPTION:
- vcpu->arch.event_exit_inst_len = vmcs_read32(instr_len_field);
- /* fall through */
- case INTR_TYPE_HARD_EXCEPTION:
- if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
- u32 err = vmcs_read32(error_code_field);
- kvm_requeue_exception_e(vcpu, vector, err);
- } else
- kvm_requeue_exception(vcpu, vector);
- break;
- case INTR_TYPE_SOFT_INTR:
- vcpu->arch.event_exit_inst_len = vmcs_read32(instr_len_field);
- /* fall through */
- case INTR_TYPE_EXT_INTR:
- kvm_queue_interrupt(vcpu, vector, type == INTR_TYPE_SOFT_INTR);
- break;
- default:
- break;
- }
-}
-
-static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
-{
- __vmx_complete_interrupts(&vmx->vcpu, vmx->idt_vectoring_info,
- VM_EXIT_INSTRUCTION_LEN,
- IDT_VECTORING_ERROR_CODE);
-}
-
-static void vmx_cancel_injection(struct kvm_vcpu *vcpu)
-{
- __vmx_complete_interrupts(vcpu,
- vmcs_read32(VM_ENTRY_INTR_INFO_FIELD),
- VM_ENTRY_INSTRUCTION_LEN,
- VM_ENTRY_EXCEPTION_ERROR_CODE);
-
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
-}
-
-static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
-{
- int i, nr_msrs;
- struct perf_guest_switch_msr *msrs;
-
- msrs = perf_guest_get_msrs(&nr_msrs);
-
- if (!msrs)
- return;
-
- for (i = 0; i < nr_msrs; i++)
- if (msrs[i].host == msrs[i].guest)
- clear_atomic_switch_msr(vmx, msrs[i].msr);
- else
- add_atomic_switch_msr(vmx, msrs[i].msr, msrs[i].guest,
- msrs[i].host, false);
-}
-
-static void vmx_arm_hv_timer(struct vcpu_vmx *vmx, u32 val)
-{
- vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, val);
- if (!vmx->loaded_vmcs->hv_timer_armed)
- vmcs_set_bits(PIN_BASED_VM_EXEC_CONTROL,
- PIN_BASED_VMX_PREEMPTION_TIMER);
- vmx->loaded_vmcs->hv_timer_armed = true;
-}
-
-static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u64 tscl;
- u32 delta_tsc;
-
- if (vmx->req_immediate_exit) {
- vmx_arm_hv_timer(vmx, 0);
- return;
- }
-
- if (vmx->hv_deadline_tsc != -1) {
- tscl = rdtsc();
- if (vmx->hv_deadline_tsc > tscl)
- /* set_hv_timer ensures the delta fits in 32-bits */
- delta_tsc = (u32)((vmx->hv_deadline_tsc - tscl) >>
- cpu_preemption_timer_multi);
- else
- delta_tsc = 0;
-
- vmx_arm_hv_timer(vmx, delta_tsc);
- return;
- }
-
- if (vmx->loaded_vmcs->hv_timer_armed)
- vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL,
- PIN_BASED_VMX_PREEMPTION_TIMER);
- vmx->loaded_vmcs->hv_timer_armed = false;
-}
-
-u64 __always_inline vmx_spec_ctrl_restore_host(struct vcpu_vmx *vmx)
-{
- u64 guestval, hostval = this_cpu_read(x86_spec_ctrl_current);
-
- if (!cpu_feature_enabled(X86_FEATURE_MSR_SPEC_CTRL))
- return 0;
-
- guestval = __rdmsr(MSR_IA32_SPEC_CTRL);
-
- /*
- *
- * For legacy IBRS, the IBRS bit always needs to be written after
- * transitioning from a less privileged predictor mode, regardless of
- * whether the guest/host values differ.
- */
- if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) ||
- guestval != hostval)
- native_wrmsrl(MSR_IA32_SPEC_CTRL, hostval);
-
- barrier_nospec();
-
- return guestval;
-}
-
-static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- unsigned long cr3, cr4, evmcs_rsp;
- u64 spec_ctrl;
-
- /* Record the guest's net vcpu time for enforced NMI injections. */
- if (unlikely(!enable_vnmi &&
- vmx->loaded_vmcs->soft_vnmi_blocked))
- vmx->loaded_vmcs->entry_time = ktime_get();
-
- /* Don't enter VMX if guest state is invalid, let the exit handler
- start emulation until we arrive back to a valid state */
- if (vmx->emulation_required)
- return;
-
- if (vmx->ple_window_dirty) {
- vmx->ple_window_dirty = false;
- vmcs_write32(PLE_WINDOW, vmx->ple_window);
- }
-
- if (vmx->nested.sync_shadow_vmcs) {
- copy_vmcs12_to_shadow(vmx);
- vmx->nested.sync_shadow_vmcs = false;
- }
-
- if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
- vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
- if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
- vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
-
- cr3 = __get_current_cr3_fast();
- if (unlikely(cr3 != vmx->loaded_vmcs->host_state.cr3)) {
- vmcs_writel(HOST_CR3, cr3);
- vmx->loaded_vmcs->host_state.cr3 = cr3;
- }
-
- cr4 = cr4_read_shadow();
- if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) {
- vmcs_writel(HOST_CR4, cr4);
- vmx->loaded_vmcs->host_state.cr4 = cr4;
- }
-
- /* When single-stepping over STI and MOV SS, we must clear the
- * corresponding interruptibility bits in the guest state. Otherwise
- * vmentry fails as it then expects bit 14 (BS) in pending debug
- * exceptions being set, but that's not correct for the guest debugging
- * case. */
- if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
- vmx_set_interrupt_shadow(vcpu, 0);
-
- kvm_load_guest_xcr0(vcpu);
-
- if (static_cpu_has(X86_FEATURE_PKU) &&
- kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
- vcpu->arch.pkru != vmx->host_pkru)
- __write_pkru(vcpu->arch.pkru);
-
- atomic_switch_perf_msrs(vmx);
-
- vmx_update_hv_timer(vcpu);
-
- /*
- * If this vCPU has touched SPEC_CTRL, restore the guest's value if
- * it's non-zero. Since vmentry is serialising on affected CPUs, there
- * is no need to worry about the conditional branch over the wrmsr
- * being speculatively taken.
- */
- x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
-
- vmx->__launched = vmx->loaded_vmcs->launched;
-
- evmcs_rsp = static_branch_unlikely(&enable_evmcs) ?
- (unsigned long)¤t_evmcs->host_rsp : 0;
-
- /* L1D Flush includes CPU buffer clear to mitigate MDS */
- if (static_branch_unlikely(&vmx_l1d_should_flush))
- vmx_l1d_flush(vcpu);
- else if (static_branch_unlikely(&mds_user_clear))
- mds_clear_cpu_buffers();
- else if (static_branch_unlikely(&mmio_stale_data_clear) &&
- kvm_arch_has_assigned_device(vcpu->kvm))
- mds_clear_cpu_buffers();
-
- vmx_disable_fb_clear(vmx);
-
- asm volatile (
- /* Store host registers */
- "push %%" _ASM_DX "; push %%" _ASM_BP ";"
- "push %%" _ASM_CX " \n\t" /* placeholder for guest rcx */
- "push %%" _ASM_CX " \n\t"
- "cmp %%" _ASM_SP ", %c[host_rsp](%%" _ASM_CX ") \n\t"
- "je 1f \n\t"
- "mov %%" _ASM_SP ", %c[host_rsp](%%" _ASM_CX ") \n\t"
- /* Avoid VMWRITE when Enlightened VMCS is in use */
- "test %%" _ASM_SI ", %%" _ASM_SI " \n\t"
- "jz 2f \n\t"
- "mov %%" _ASM_SP ", (%%" _ASM_SI ") \n\t"
- "jmp 1f \n\t"
- "2: \n\t"
- __ex(ASM_VMX_VMWRITE_RSP_RDX) "\n\t"
- "1: \n\t"
- /* Reload cr2 if changed */
- "mov %c[cr2](%%" _ASM_CX "), %%" _ASM_AX " \n\t"
- "mov %%cr2, %%" _ASM_DX " \n\t"
- "cmp %%" _ASM_AX ", %%" _ASM_DX " \n\t"
- "je 3f \n\t"
- "mov %%" _ASM_AX", %%cr2 \n\t"
- "3: \n\t"
- /* Check if vmlaunch of vmresume is needed */
- "cmpb $0, %c[launched](%%" _ASM_CX ") \n\t"
- /* Load guest registers. Don't clobber flags. */
- "mov %c[rax](%%" _ASM_CX "), %%" _ASM_AX " \n\t"
- "mov %c[rbx](%%" _ASM_CX "), %%" _ASM_BX " \n\t"
- "mov %c[rdx](%%" _ASM_CX "), %%" _ASM_DX " \n\t"
- "mov %c[rsi](%%" _ASM_CX "), %%" _ASM_SI " \n\t"
- "mov %c[rdi](%%" _ASM_CX "), %%" _ASM_DI " \n\t"
- "mov %c[rbp](%%" _ASM_CX "), %%" _ASM_BP " \n\t"
-#ifdef CONFIG_X86_64
- "mov %c[r8](%%" _ASM_CX "), %%r8 \n\t"
- "mov %c[r9](%%" _ASM_CX "), %%r9 \n\t"
- "mov %c[r10](%%" _ASM_CX "), %%r10 \n\t"
- "mov %c[r11](%%" _ASM_CX "), %%r11 \n\t"
- "mov %c[r12](%%" _ASM_CX "), %%r12 \n\t"
- "mov %c[r13](%%" _ASM_CX "), %%r13 \n\t"
- "mov %c[r14](%%" _ASM_CX "), %%r14 \n\t"
- "mov %c[r15](%%" _ASM_CX "), %%r15 \n\t"
-#endif
- /* Load guest RCX. This kills the vmx_vcpu pointer! */
- "mov %c[rcx](%%" _ASM_CX "), %%" _ASM_CX " \n\t"
-
- /* Enter guest mode */
- "jne 1f \n\t"
- __ex(ASM_VMX_VMLAUNCH) "\n\t"
- "jmp 2f \n\t"
- "1: " __ex(ASM_VMX_VMRESUME) "\n\t"
- "2: "
-
- /* Save guest's RCX to the stack placeholder (see above) */
- "mov %%" _ASM_CX ", %c[wordsize](%%" _ASM_SP ") \n\t"
-
- /* Load host's RCX, i.e. the vmx_vcpu pointer */
- "pop %%" _ASM_CX " \n\t"
-
- /* Set vmx->fail based on EFLAGS.{CF,ZF} */
- "setbe %c[fail](%%" _ASM_CX ")\n\t"
-
- /* Save all guest registers, including RCX from the stack */
- "mov %%" _ASM_AX ", %c[rax](%%" _ASM_CX ") \n\t"
- "mov %%" _ASM_BX ", %c[rbx](%%" _ASM_CX ") \n\t"
- __ASM_SIZE(pop) " %c[rcx](%%" _ASM_CX ") \n\t"
- "mov %%" _ASM_DX ", %c[rdx](%%" _ASM_CX ") \n\t"
- "mov %%" _ASM_SI ", %c[rsi](%%" _ASM_CX ") \n\t"
- "mov %%" _ASM_DI ", %c[rdi](%%" _ASM_CX ") \n\t"
- "mov %%" _ASM_BP ", %c[rbp](%%" _ASM_CX ") \n\t"
-#ifdef CONFIG_X86_64
- "mov %%r8, %c[r8](%%" _ASM_CX ") \n\t"
- "mov %%r9, %c[r9](%%" _ASM_CX ") \n\t"
- "mov %%r10, %c[r10](%%" _ASM_CX ") \n\t"
- "mov %%r11, %c[r11](%%" _ASM_CX ") \n\t"
- "mov %%r12, %c[r12](%%" _ASM_CX ") \n\t"
- "mov %%r13, %c[r13](%%" _ASM_CX ") \n\t"
- "mov %%r14, %c[r14](%%" _ASM_CX ") \n\t"
- "mov %%r15, %c[r15](%%" _ASM_CX ") \n\t"
-
- /*
- * Clear all general purpose registers (except RSP, which is loaded by
- * the CPU during VM-Exit) to prevent speculative use of the guest's
- * values, even those that are saved/loaded via the stack. In theory,
- * an L1 cache miss when restoring registers could lead to speculative
- * execution with the guest's values. Zeroing XORs are dirt cheap,
- * i.e. the extra paranoia is essentially free.
- */
- "xor %%r8d, %%r8d \n\t"
- "xor %%r9d, %%r9d \n\t"
- "xor %%r10d, %%r10d \n\t"
- "xor %%r11d, %%r11d \n\t"
- "xor %%r12d, %%r12d \n\t"
- "xor %%r13d, %%r13d \n\t"
- "xor %%r14d, %%r14d \n\t"
- "xor %%r15d, %%r15d \n\t"
-#endif
- "mov %%cr2, %%" _ASM_AX " \n\t"
- "mov %%" _ASM_AX ", %c[cr2](%%" _ASM_CX ") \n\t"
-
- "xor %%eax, %%eax \n\t"
- "xor %%ebx, %%ebx \n\t"
- "xor %%ecx, %%ecx \n\t"
- "xor %%edx, %%edx \n\t"
- "xor %%esi, %%esi \n\t"
- "xor %%edi, %%edi \n\t"
- "xor %%ebp, %%ebp \n\t"
- "pop %%" _ASM_BP "; pop %%" _ASM_DX " \n\t"
- ".pushsection .rodata \n\t"
- ".global vmx_return \n\t"
- "vmx_return: " _ASM_PTR " 2b \n\t"
- ".popsection"
- : "=c"((int){0}), "=d"((int){0}), "=S"((int){0})
- : "c"(vmx), "d"((unsigned long)HOST_RSP), "S"(evmcs_rsp),
- [launched]"i"(offsetof(struct vcpu_vmx, __launched)),
- [fail]"i"(offsetof(struct vcpu_vmx, fail)),
- [host_rsp]"i"(offsetof(struct vcpu_vmx, host_rsp)),
- [rax]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RAX])),
- [rbx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBX])),
- [rcx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RCX])),
- [rdx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RDX])),
- [rsi]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RSI])),
- [rdi]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RDI])),
- [rbp]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBP])),
-#ifdef CONFIG_X86_64
- [r8]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R8])),
- [r9]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R9])),
- [r10]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R10])),
- [r11]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R11])),
- [r12]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R12])),
- [r13]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R13])),
- [r14]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R14])),
- [r15]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R15])),
-#endif
- [cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2)),
- [wordsize]"i"(sizeof(ulong))
- : "cc", "memory"
-#ifdef CONFIG_X86_64
- , "rax", "rbx", "rdi"
- , "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
-#else
- , "eax", "ebx", "edi"
-#endif
- );
-
- /*
- * IMPORTANT: RSB filling and SPEC_CTRL handling must be done before
- * the first unbalanced RET after vmexit!
- *
- * For retpoline or IBRS, RSB filling is needed to prevent poisoned RSB
- * entries and (in some cases) RSB underflow.
- *
- * eIBRS has its own protection against poisoned RSB, so it doesn't
- * need the RSB filling sequence. But it does need to be enabled, and a
- * single call to retire, before the first unbalanced RET.
- *
- * So no RETs before vmx_spec_ctrl_restore_host() below.
- */
- vmexit_fill_RSB();
-
- /* Save this for below */
- spec_ctrl = vmx_spec_ctrl_restore_host(vmx);
-
- vmx_enable_fb_clear(vmx);
-
- /*
- * We do not use IBRS in the kernel. If this vCPU has used the
- * SPEC_CTRL MSR it may have left it on; save the value and
- * turn it off. This is much more efficient than blindly adding
- * it to the atomic save/restore list. Especially as the former
- * (Saving guest MSRs on vmexit) doesn't even exist in KVM.
- *
- * For non-nested case:
- * If the L01 MSR bitmap does not intercept the MSR, then we need to
- * save it.
- *
- * For nested case:
- * If the L02 MSR bitmap does not intercept the MSR, then we need to
- * save it.
- */
- if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
- vmx->spec_ctrl = spec_ctrl;
-
- /* All fields are clean at this point */
- if (static_branch_unlikely(&enable_evmcs))
- current_evmcs->hv_clean_fields |=
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL;
-
- /* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */
- if (vmx->host_debugctlmsr)
- update_debugctlmsr(vmx->host_debugctlmsr);
-
-#ifndef CONFIG_X86_64
- /*
- * The sysexit path does not restore ds/es, so we must set them to
- * a reasonable value ourselves.
- *
- * We can't defer this to vmx_prepare_switch_to_host() since that
- * function may be executed in interrupt context, which saves and
- * restore segments around it, nullifying its effect.
- */
- loadsegment(ds, __USER_DS);
- loadsegment(es, __USER_DS);
-#endif
-
- vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)
- | (1 << VCPU_EXREG_RFLAGS)
- | (1 << VCPU_EXREG_PDPTR)
- | (1 << VCPU_EXREG_SEGMENTS)
- | (1 << VCPU_EXREG_CR3));
- vcpu->arch.regs_dirty = 0;
-
- /*
- * eager fpu is enabled if PKEY is supported and CR4 is switched
- * back on host, so it is safe to read guest PKRU from current
- * XSAVE.
- */
- if (static_cpu_has(X86_FEATURE_PKU) &&
- kvm_read_cr4_bits(vcpu, X86_CR4_PKE)) {
- vcpu->arch.pkru = __read_pkru();
- if (vcpu->arch.pkru != vmx->host_pkru)
- __write_pkru(vmx->host_pkru);
- }
-
- kvm_put_guest_xcr0(vcpu);
-
- vmx->nested.nested_run_pending = 0;
- vmx->idt_vectoring_info = 0;
-
- vmx->exit_reason = vmx->fail ? 0xdead : vmcs_read32(VM_EXIT_REASON);
- if ((u16)vmx->exit_reason == EXIT_REASON_MCE_DURING_VMENTRY)
- kvm_machine_check();
-
- if (vmx->fail || (vmx->exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY))
- return;
-
- vmx->loaded_vmcs->launched = 1;
- vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
-
- vmx_complete_atomic_exit(vmx);
- vmx_recover_nmi_blocking(vmx);
- vmx_complete_interrupts(vmx);
-}
-STACK_FRAME_NON_STANDARD(vmx_vcpu_run);
-
-static struct kvm *vmx_vm_alloc(void)
-{
- struct kvm_vmx *kvm_vmx = vzalloc(sizeof(struct kvm_vmx));
-
- if (!kvm_vmx)
- return NULL;
-
- return &kvm_vmx->kvm;
-}
-
-static void vmx_vm_free(struct kvm *kvm)
-{
- vfree(to_kvm_vmx(kvm));
-}
-
-static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int cpu;
-
- if (vmx->loaded_vmcs == vmcs)
- return;
-
- cpu = get_cpu();
- vmx_vcpu_put(vcpu);
- vmx->loaded_vmcs = vmcs;
- vmx_vcpu_load(vcpu, cpu);
- put_cpu();
-}
-
-/*
- * Ensure that the current vmcs of the logical processor is the
- * vmcs01 of the vcpu before calling free_nested().
- */
-static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- vcpu_load(vcpu);
- vmx_switch_vmcs(vcpu, &vmx->vmcs01);
- free_nested(vmx);
- vcpu_put(vcpu);
-}
-
-static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (enable_pml)
- vmx_destroy_pml_buffer(vmx);
- free_vpid(vmx->vpid);
- leave_guest_mode(vcpu);
- vmx_free_vcpu_nested(vcpu);
- free_loaded_vmcs(vmx->loaded_vmcs);
- kfree(vmx->guest_msrs);
- kvm_vcpu_uninit(vcpu);
- kmem_cache_free(kvm_vcpu_cache, vmx);
-}
-
-static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
-{
- int err;
- struct vcpu_vmx *vmx = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
- unsigned long *msr_bitmap;
- int cpu;
-
- if (!vmx)
- return ERR_PTR(-ENOMEM);
-
- vmx->vpid = allocate_vpid();
-
- err = kvm_vcpu_init(&vmx->vcpu, kvm, id);
- if (err)
- goto free_vcpu;
-
- err = -ENOMEM;
-
- /*
- * If PML is turned on, failure on enabling PML just results in failure
- * of creating the vcpu, therefore we can simplify PML logic (by
- * avoiding dealing with cases, such as enabling PML partially on vcpus
- * for the guest, etc.
- */
- if (enable_pml) {
- vmx->pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (!vmx->pml_pg)
- goto uninit_vcpu;
- }
-
- vmx->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
- BUILD_BUG_ON(ARRAY_SIZE(vmx_msr_index) * sizeof(vmx->guest_msrs[0])
- > PAGE_SIZE);
-
- if (!vmx->guest_msrs)
- goto free_pml;
-
- err = alloc_loaded_vmcs(&vmx->vmcs01);
- if (err < 0)
- goto free_msrs;
-
- msr_bitmap = vmx->vmcs01.msr_bitmap;
- vmx_disable_intercept_for_msr(msr_bitmap, MSR_FS_BASE, MSR_TYPE_RW);
- vmx_disable_intercept_for_msr(msr_bitmap, MSR_GS_BASE, MSR_TYPE_RW);
- vmx_disable_intercept_for_msr(msr_bitmap, MSR_KERNEL_GS_BASE, MSR_TYPE_RW);
- vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_CS, MSR_TYPE_RW);
- vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_ESP, MSR_TYPE_RW);
- vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_EIP, MSR_TYPE_RW);
- vmx->msr_bitmap_mode = 0;
-
- vmx->loaded_vmcs = &vmx->vmcs01;
- cpu = get_cpu();
- vmx_vcpu_load(&vmx->vcpu, cpu);
- vmx->vcpu.cpu = cpu;
- vmx_vcpu_setup(vmx);
- vmx_vcpu_put(&vmx->vcpu);
- put_cpu();
- if (cpu_need_virtualize_apic_accesses(&vmx->vcpu)) {
- err = alloc_apic_access_page(kvm);
- if (err)
- goto free_vmcs;
- }
-
- if (enable_ept && !enable_unrestricted_guest) {
- err = init_rmode_identity_map(kvm);
- if (err)
- goto free_vmcs;
- }
-
- if (nested)
- nested_vmx_setup_ctls_msrs(&vmx->nested.msrs,
- kvm_vcpu_apicv_active(&vmx->vcpu));
-
- vmx->nested.posted_intr_nv = -1;
- vmx->nested.current_vmptr = -1ull;
-
- vmx->msr_ia32_feature_control_valid_bits = FEATURE_CONTROL_LOCKED;
-
- /*
- * Enforce invariant: pi_desc.nv is always either POSTED_INTR_VECTOR
- * or POSTED_INTR_WAKEUP_VECTOR.
- */
- vmx->pi_desc.nv = POSTED_INTR_VECTOR;
- vmx->pi_desc.sn = 1;
-
- return &vmx->vcpu;
-
-free_vmcs:
- free_loaded_vmcs(vmx->loaded_vmcs);
-free_msrs:
- kfree(vmx->guest_msrs);
-free_pml:
- vmx_destroy_pml_buffer(vmx);
-uninit_vcpu:
- kvm_vcpu_uninit(&vmx->vcpu);
-free_vcpu:
- free_vpid(vmx->vpid);
- kmem_cache_free(kvm_vcpu_cache, vmx);
- return ERR_PTR(err);
-}
-
-#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n"
-#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n"
-
-static int vmx_vm_init(struct kvm *kvm)
-{
- spin_lock_init(&to_kvm_vmx(kvm)->ept_pointer_lock);
-
- if (!ple_gap)
- kvm->arch.pause_in_guest = true;
-
- if (boot_cpu_has(X86_BUG_L1TF) && enable_ept) {
- switch (l1tf_mitigation) {
- case L1TF_MITIGATION_OFF:
- case L1TF_MITIGATION_FLUSH_NOWARN:
- /* 'I explicitly don't care' is set */
- break;
- case L1TF_MITIGATION_FLUSH:
- case L1TF_MITIGATION_FLUSH_NOSMT:
- case L1TF_MITIGATION_FULL:
- /*
- * Warn upon starting the first VM in a potentially
- * insecure environment.
- */
- if (sched_smt_active())
- pr_warn_once(L1TF_MSG_SMT);
- if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER)
- pr_warn_once(L1TF_MSG_L1D);
- break;
- case L1TF_MITIGATION_FULL_FORCE:
- /* Flush is enforced */
- break;
- }
- }
- return 0;
-}
-
-static void __init vmx_check_processor_compat(void *rtn)
-{
- struct vmcs_config vmcs_conf;
-
- *(int *)rtn = 0;
- if (setup_vmcs_config(&vmcs_conf) < 0)
- *(int *)rtn = -EIO;
- nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, enable_apicv);
- if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) {
- printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n",
- smp_processor_id());
- *(int *)rtn = -EIO;
- }
-}
-
-static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
-{
- u8 cache;
- u64 ipat = 0;
-
- /* For VT-d and EPT combination
- * 1. MMIO: always map as UC
- * 2. EPT with VT-d:
- * a. VT-d without snooping control feature: can't guarantee the
- * result, try to trust guest.
- * b. VT-d with snooping control feature: snooping control feature of
- * VT-d engine can guarantee the cache correctness. Just set it
- * to WB to keep consistent with host. So the same as item 3.
- * 3. EPT without VT-d: always map as WB and set IPAT=1 to keep
- * consistent with host MTRR
- */
- if (is_mmio) {
- cache = MTRR_TYPE_UNCACHABLE;
- goto exit;
- }
-
- if (!kvm_arch_has_noncoherent_dma(vcpu->kvm)) {
- ipat = VMX_EPT_IPAT_BIT;
- cache = MTRR_TYPE_WRBACK;
- goto exit;
- }
-
- if (kvm_read_cr0(vcpu) & X86_CR0_CD) {
- ipat = VMX_EPT_IPAT_BIT;
- if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
- cache = MTRR_TYPE_WRBACK;
- else
- cache = MTRR_TYPE_UNCACHABLE;
- goto exit;
- }
-
- cache = kvm_mtrr_get_guest_memory_type(vcpu, gfn);
-
-exit:
- return (cache << VMX_EPT_MT_EPTE_SHIFT) | ipat;
-}
-
-static int vmx_get_lpage_level(void)
-{
- if (enable_ept && !cpu_has_vmx_ept_1g_page())
- return PT_DIRECTORY_LEVEL;
- else
- /* For shadow and EPT supported 1GB page */
- return PT_PDPE_LEVEL;
-}
-
-static void vmcs_set_secondary_exec_control(u32 new_ctl)
-{
- /*
- * These bits in the secondary execution controls field
- * are dynamic, the others are mostly based on the hypervisor
- * architecture and the guest's CPUID. Do not touch the
- * dynamic bits.
- */
- u32 mask =
- SECONDARY_EXEC_SHADOW_VMCS |
- SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
- SECONDARY_EXEC_DESC;
-
- u32 cur_ctl = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
-
- vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
- (new_ctl & ~mask) | (cur_ctl & mask));
-}
-
-/*
- * Generate MSR_IA32_VMX_CR{0,4}_FIXED1 according to CPUID. Only set bits
- * (indicating "allowed-1") if they are supported in the guest's CPUID.
- */
-static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct kvm_cpuid_entry2 *entry;
-
- vmx->nested.msrs.cr0_fixed1 = 0xffffffff;
- vmx->nested.msrs.cr4_fixed1 = X86_CR4_PCE;
-
-#define cr4_fixed1_update(_cr4_mask, _reg, _cpuid_mask) do { \
- if (entry && (entry->_reg & (_cpuid_mask))) \
- vmx->nested.msrs.cr4_fixed1 |= (_cr4_mask); \
-} while (0)
-
- entry = kvm_find_cpuid_entry(vcpu, 0x1, 0);
- cr4_fixed1_update(X86_CR4_VME, edx, bit(X86_FEATURE_VME));
- cr4_fixed1_update(X86_CR4_PVI, edx, bit(X86_FEATURE_VME));
- cr4_fixed1_update(X86_CR4_TSD, edx, bit(X86_FEATURE_TSC));
- cr4_fixed1_update(X86_CR4_DE, edx, bit(X86_FEATURE_DE));
- cr4_fixed1_update(X86_CR4_PSE, edx, bit(X86_FEATURE_PSE));
- cr4_fixed1_update(X86_CR4_PAE, edx, bit(X86_FEATURE_PAE));
- cr4_fixed1_update(X86_CR4_MCE, edx, bit(X86_FEATURE_MCE));
- cr4_fixed1_update(X86_CR4_PGE, edx, bit(X86_FEATURE_PGE));
- cr4_fixed1_update(X86_CR4_OSFXSR, edx, bit(X86_FEATURE_FXSR));
- cr4_fixed1_update(X86_CR4_OSXMMEXCPT, edx, bit(X86_FEATURE_XMM));
- cr4_fixed1_update(X86_CR4_VMXE, ecx, bit(X86_FEATURE_VMX));
- cr4_fixed1_update(X86_CR4_SMXE, ecx, bit(X86_FEATURE_SMX));
- cr4_fixed1_update(X86_CR4_PCIDE, ecx, bit(X86_FEATURE_PCID));
- cr4_fixed1_update(X86_CR4_OSXSAVE, ecx, bit(X86_FEATURE_XSAVE));
-
- entry = kvm_find_cpuid_entry(vcpu, 0x7, 0);
- cr4_fixed1_update(X86_CR4_FSGSBASE, ebx, bit(X86_FEATURE_FSGSBASE));
- cr4_fixed1_update(X86_CR4_SMEP, ebx, bit(X86_FEATURE_SMEP));
- cr4_fixed1_update(X86_CR4_SMAP, ebx, bit(X86_FEATURE_SMAP));
- cr4_fixed1_update(X86_CR4_PKE, ecx, bit(X86_FEATURE_PKU));
- cr4_fixed1_update(X86_CR4_UMIP, ecx, bit(X86_FEATURE_UMIP));
-
-#undef cr4_fixed1_update
-}
-
-static void nested_vmx_entry_exit_ctls_update(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (kvm_mpx_supported()) {
- bool mpx_enabled = guest_cpuid_has(vcpu, X86_FEATURE_MPX);
-
- if (mpx_enabled) {
- vmx->nested.msrs.entry_ctls_high |= VM_ENTRY_LOAD_BNDCFGS;
- vmx->nested.msrs.exit_ctls_high |= VM_EXIT_CLEAR_BNDCFGS;
- } else {
- vmx->nested.msrs.entry_ctls_high &= ~VM_ENTRY_LOAD_BNDCFGS;
- vmx->nested.msrs.exit_ctls_high &= ~VM_EXIT_CLEAR_BNDCFGS;
- }
- }
-}
-
-static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (cpu_has_secondary_exec_ctrls()) {
- vmx_compute_secondary_exec_control(vmx);
- vmcs_set_secondary_exec_control(vmx->secondary_exec_control);
- }
-
- if (nested_vmx_allowed(vcpu))
- to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
- FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
- else
- to_vmx(vcpu)->msr_ia32_feature_control_valid_bits &=
- ~FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
-
- if (nested_vmx_allowed(vcpu)) {
- nested_vmx_cr_fixed1_bits_update(vcpu);
- nested_vmx_entry_exit_ctls_update(vcpu);
- }
-}
-
-static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
-{
- if (func == 1 && nested)
- entry->ecx |= bit(X86_FEATURE_VMX);
-}
-
-static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
- struct x86_exception *fault)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 exit_reason;
- unsigned long exit_qualification = vcpu->arch.exit_qualification;
-
- if (vmx->nested.pml_full) {
- exit_reason = EXIT_REASON_PML_FULL;
- vmx->nested.pml_full = false;
- exit_qualification &= INTR_INFO_UNBLOCK_NMI;
- } else if (fault->error_code & PFERR_RSVD_MASK)
- exit_reason = EXIT_REASON_EPT_MISCONFIG;
- else
- exit_reason = EXIT_REASON_EPT_VIOLATION;
-
- nested_vmx_vmexit(vcpu, exit_reason, 0, exit_qualification);
- vmcs12->guest_physical_address = fault->address;
-}
-
-static bool nested_ept_ad_enabled(struct kvm_vcpu *vcpu)
-{
- return nested_ept_get_cr3(vcpu) & VMX_EPTP_AD_ENABLE_BIT;
-}
-
-/* Callbacks for nested_ept_init_mmu_context: */
-
-static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu)
-{
- /* return the page table to be shadowed - in our case, EPT12 */
- return get_vmcs12(vcpu)->ept_pointer;
-}
-
-static int nested_ept_init_mmu_context(struct kvm_vcpu *vcpu)
-{
- WARN_ON(mmu_is_nested(vcpu));
- if (!valid_ept_address(vcpu, nested_ept_get_cr3(vcpu)))
- return 1;
-
- kvm_init_shadow_ept_mmu(vcpu,
- to_vmx(vcpu)->nested.msrs.ept_caps &
- VMX_EPT_EXECUTE_ONLY_BIT,
- nested_ept_ad_enabled(vcpu),
- nested_ept_get_cr3(vcpu));
- vcpu->arch.mmu.set_cr3 = vmx_set_cr3;
- vcpu->arch.mmu.get_cr3 = nested_ept_get_cr3;
- vcpu->arch.mmu.inject_page_fault = nested_ept_inject_page_fault;
-
- vcpu->arch.walk_mmu = &vcpu->arch.nested_mmu;
- return 0;
-}
-
-static void nested_ept_uninit_mmu_context(struct kvm_vcpu *vcpu)
-{
- vcpu->arch.walk_mmu = &vcpu->arch.mmu;
-}
-
-static bool nested_vmx_is_page_fault_vmexit(struct vmcs12 *vmcs12,
- u16 error_code)
-{
- bool inequality, bit;
-
- bit = (vmcs12->exception_bitmap & (1u << PF_VECTOR)) != 0;
- inequality =
- (error_code & vmcs12->page_fault_error_code_mask) !=
- vmcs12->page_fault_error_code_match;
- return inequality ^ bit;
-}
-
-static void vmx_inject_page_fault_nested(struct kvm_vcpu *vcpu,
- struct x86_exception *fault)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
-
- WARN_ON(!is_guest_mode(vcpu));
-
- if (nested_vmx_is_page_fault_vmexit(vmcs12, fault->error_code) &&
- !to_vmx(vcpu)->nested.nested_run_pending) {
- vmcs12->vm_exit_intr_error_code = fault->error_code;
- nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
- PF_VECTOR | INTR_TYPE_HARD_EXCEPTION |
- INTR_INFO_DELIVER_CODE_MASK | INTR_INFO_VALID_MASK,
- fault->address);
- } else {
- kvm_inject_page_fault(vcpu, fault);
- }
-}
-
-static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12);
-
-static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct page *page;
- u64 hpa;
-
- if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
- /*
- * Translate L1 physical address to host physical
- * address for vmcs02. Keep the page pinned, so this
- * physical address remains valid. We keep a reference
- * to it so we can release it later.
- */
- if (vmx->nested.apic_access_page) { /* shouldn't happen */
- kvm_release_page_dirty(vmx->nested.apic_access_page);
- vmx->nested.apic_access_page = NULL;
- }
- page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->apic_access_addr);
- /*
- * If translation failed, no matter: This feature asks
- * to exit when accessing the given address, and if it
- * can never be accessed, this feature won't do
- * anything anyway.
- */
- if (!is_error_page(page)) {
- vmx->nested.apic_access_page = page;
- hpa = page_to_phys(vmx->nested.apic_access_page);
- vmcs_write64(APIC_ACCESS_ADDR, hpa);
- } else {
- vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
- }
- }
-
- if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
- if (vmx->nested.virtual_apic_page) { /* shouldn't happen */
- kvm_release_page_dirty(vmx->nested.virtual_apic_page);
- vmx->nested.virtual_apic_page = NULL;
- }
- page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->virtual_apic_page_addr);
-
- /*
- * If translation failed, VM entry will fail because
- * prepare_vmcs02 set VIRTUAL_APIC_PAGE_ADDR to -1ull.
- * Failing the vm entry is _not_ what the processor
- * does but it's basically the only possibility we
- * have. We could still enter the guest if CR8 load
- * exits are enabled, CR8 store exits are enabled, and
- * virtualize APIC access is disabled; in this case
- * the processor would never use the TPR shadow and we
- * could simply clear the bit from the execution
- * control. But such a configuration is useless, so
- * let's keep the code simple.
- */
- if (!is_error_page(page)) {
- vmx->nested.virtual_apic_page = page;
- hpa = page_to_phys(vmx->nested.virtual_apic_page);
- vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, hpa);
- }
- }
-
- if (nested_cpu_has_posted_intr(vmcs12)) {
- if (vmx->nested.pi_desc_page) { /* shouldn't happen */
- kunmap(vmx->nested.pi_desc_page);
- kvm_release_page_dirty(vmx->nested.pi_desc_page);
- vmx->nested.pi_desc_page = NULL;
- vmx->nested.pi_desc = NULL;
- vmcs_write64(POSTED_INTR_DESC_ADDR, -1ull);
- }
- page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->posted_intr_desc_addr);
- if (is_error_page(page))
- return;
- vmx->nested.pi_desc_page = page;
- vmx->nested.pi_desc = kmap(vmx->nested.pi_desc_page);
- vmx->nested.pi_desc =
- (struct pi_desc *)((void *)vmx->nested.pi_desc +
- (unsigned long)(vmcs12->posted_intr_desc_addr &
- (PAGE_SIZE - 1)));
- vmcs_write64(POSTED_INTR_DESC_ADDR,
- page_to_phys(vmx->nested.pi_desc_page) +
- (unsigned long)(vmcs12->posted_intr_desc_addr &
- (PAGE_SIZE - 1)));
- }
- if (nested_vmx_prepare_msr_bitmap(vcpu, vmcs12))
- vmcs_set_bits(CPU_BASED_VM_EXEC_CONTROL,
- CPU_BASED_USE_MSR_BITMAPS);
- else
- vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
- CPU_BASED_USE_MSR_BITMAPS);
-}
-
-static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu)
-{
- u64 preemption_timeout = get_vmcs12(vcpu)->vmx_preemption_timer_value;
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- /*
- * A timer value of zero is architecturally guaranteed to cause
- * a VMExit prior to executing any instructions in the guest.
- */
- if (preemption_timeout == 0) {
- vmx_preemption_timer_fn(&vmx->nested.preemption_timer);
- return;
- }
-
- if (vcpu->arch.virtual_tsc_khz == 0)
- return;
-
- preemption_timeout <<= VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE;
- preemption_timeout *= 1000000;
- do_div(preemption_timeout, vcpu->arch.virtual_tsc_khz);
- hrtimer_start(&vmx->nested.preemption_timer,
- ns_to_ktime(preemption_timeout), HRTIMER_MODE_REL);
-}
-
-static int nested_vmx_check_io_bitmap_controls(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
- return 0;
-
- if (!page_address_valid(vcpu, vmcs12->io_bitmap_a) ||
- !page_address_valid(vcpu, vmcs12->io_bitmap_b))
- return -EINVAL;
-
- return 0;
-}
-
-static int nested_vmx_check_msr_bitmap_controls(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_MSR_BITMAPS))
- return 0;
-
- if (!page_address_valid(vcpu, vmcs12->msr_bitmap))
- return -EINVAL;
-
- return 0;
-}
-
-static int nested_vmx_check_tpr_shadow_controls(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- if (!nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
- return 0;
-
- if (!page_address_valid(vcpu, vmcs12->virtual_apic_page_addr))
- return -EINVAL;
-
- return 0;
-}
-
-static inline void enable_x2apic_msr_intercepts(unsigned long *msr_bitmap) {
- int msr;
-
- for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
- unsigned word = msr / BITS_PER_LONG;
-
- msr_bitmap[word] = ~0;
- msr_bitmap[word + (0x800 / sizeof(long))] = ~0;
- }
-}
-
-/*
- * Merge L0's and L1's MSR bitmap, return false to indicate that
- * we do not use the hardware.
- */
-static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- int msr;
- struct page *page;
- unsigned long *msr_bitmap_l1;
- unsigned long *msr_bitmap_l0 = to_vmx(vcpu)->nested.vmcs02.msr_bitmap;
- /*
- * pred_cmd & spec_ctrl are trying to verify two things:
- *
- * 1. L0 gave a permission to L1 to actually passthrough the MSR. This
- * ensures that we do not accidentally generate an L02 MSR bitmap
- * from the L12 MSR bitmap that is too permissive.
- * 2. That L1 or L2s have actually used the MSR. This avoids
- * unnecessarily merging of the bitmap if the MSR is unused. This
- * works properly because we only update the L01 MSR bitmap lazily.
- * So even if L0 should pass L1 these MSRs, the L01 bitmap is only
- * updated to reflect this when L1 (or its L2s) actually write to
- * the MSR.
- */
- bool pred_cmd = !msr_write_intercepted_l01(vcpu, MSR_IA32_PRED_CMD);
- bool spec_ctrl = !msr_write_intercepted_l01(vcpu, MSR_IA32_SPEC_CTRL);
-
- /* Nothing to do if the MSR bitmap is not in use. */
- if (!cpu_has_vmx_msr_bitmap() ||
- !nested_cpu_has(vmcs12, CPU_BASED_USE_MSR_BITMAPS))
- return false;
-
- if (!nested_cpu_has_virt_x2apic_mode(vmcs12) &&
- !pred_cmd && !spec_ctrl)
- return false;
-
- page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->msr_bitmap);
- if (is_error_page(page))
- return false;
-
- msr_bitmap_l1 = (unsigned long *)kmap(page);
-
- /*
- * To keep the control flow simple, pay eight 8-byte writes (sixteen
- * 4-byte writes on 32-bit systems) up front to enable intercepts for
- * the x2APIC MSR range and selectively disable them below.
- */
- enable_x2apic_msr_intercepts(msr_bitmap_l0);
-
- if (nested_cpu_has_virt_x2apic_mode(vmcs12)) {
- if (nested_cpu_has_apic_reg_virt(vmcs12)) {
- /*
- * L0 need not intercept reads for MSRs between 0x800
- * and 0x8ff, it just lets the processor take the value
- * from the virtual-APIC page; take those 256 bits
- * directly from the L1 bitmap.
- */
- for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
- unsigned word = msr / BITS_PER_LONG;
-
- msr_bitmap_l0[word] = msr_bitmap_l1[word];
- }
- }
-
- nested_vmx_disable_intercept_for_msr(
- msr_bitmap_l1, msr_bitmap_l0,
- X2APIC_MSR(APIC_TASKPRI),
- MSR_TYPE_R | MSR_TYPE_W);
-
- if (nested_cpu_has_vid(vmcs12)) {
- nested_vmx_disable_intercept_for_msr(
- msr_bitmap_l1, msr_bitmap_l0,
- X2APIC_MSR(APIC_EOI),
- MSR_TYPE_W);
- nested_vmx_disable_intercept_for_msr(
- msr_bitmap_l1, msr_bitmap_l0,
- X2APIC_MSR(APIC_SELF_IPI),
- MSR_TYPE_W);
- }
- }
-
- if (spec_ctrl)
- nested_vmx_disable_intercept_for_msr(
- msr_bitmap_l1, msr_bitmap_l0,
- MSR_IA32_SPEC_CTRL,
- MSR_TYPE_R | MSR_TYPE_W);
-
- if (pred_cmd)
- nested_vmx_disable_intercept_for_msr(
- msr_bitmap_l1, msr_bitmap_l0,
- MSR_IA32_PRED_CMD,
- MSR_TYPE_W);
-
- kunmap(page);
- kvm_release_page_clean(page);
-
- return true;
-}
-
-static void nested_cache_shadow_vmcs12(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- struct vmcs12 *shadow;
- struct page *page;
-
- if (!nested_cpu_has_shadow_vmcs(vmcs12) ||
- vmcs12->vmcs_link_pointer == -1ull)
- return;
-
- shadow = get_shadow_vmcs12(vcpu);
- page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->vmcs_link_pointer);
-
- memcpy(shadow, kmap(page), VMCS12_SIZE);
-
- kunmap(page);
- kvm_release_page_clean(page);
-}
-
-static void nested_flush_cached_shadow_vmcs12(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (!nested_cpu_has_shadow_vmcs(vmcs12) ||
- vmcs12->vmcs_link_pointer == -1ull)
- return;
-
- kvm_write_guest(vmx->vcpu.kvm, vmcs12->vmcs_link_pointer,
- get_shadow_vmcs12(vcpu), VMCS12_SIZE);
-}
-
-static int nested_vmx_check_apic_access_controls(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) &&
- !page_address_valid(vcpu, vmcs12->apic_access_addr))
- return -EINVAL;
- else
- return 0;
-}
-
-static int nested_vmx_check_apicv_controls(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- if (!nested_cpu_has_virt_x2apic_mode(vmcs12) &&
- !nested_cpu_has_apic_reg_virt(vmcs12) &&
- !nested_cpu_has_vid(vmcs12) &&
- !nested_cpu_has_posted_intr(vmcs12))
- return 0;
-
- /*
- * If virtualize x2apic mode is enabled,
- * virtualize apic access must be disabled.
- */
- if (nested_cpu_has_virt_x2apic_mode(vmcs12) &&
- nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
- return -EINVAL;
-
- /*
- * If virtual interrupt delivery is enabled,
- * we must exit on external interrupts.
- */
- if (nested_cpu_has_vid(vmcs12) &&
- !nested_exit_on_intr(vcpu))
- return -EINVAL;
-
- /*
- * bits 15:8 should be zero in posted_intr_nv,
- * the descriptor address has been already checked
- * in nested_get_vmcs12_pages.
- *
- * bits 5:0 of posted_intr_desc_addr should be zero.
- */
- if (nested_cpu_has_posted_intr(vmcs12) &&
- (!nested_cpu_has_vid(vmcs12) ||
- !nested_exit_intr_ack_set(vcpu) ||
- (vmcs12->posted_intr_nv & 0xff00) ||
- (vmcs12->posted_intr_desc_addr & 0x3f) ||
- (vmcs12->posted_intr_desc_addr >> cpuid_maxphyaddr(vcpu))))
- return -EINVAL;
-
- /* tpr shadow is needed by all apicv features. */
- if (!nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
- return -EINVAL;
-
- return 0;
-}
-
-static int nested_vmx_check_msr_switch(struct kvm_vcpu *vcpu,
- unsigned long count_field,
- unsigned long addr_field)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- int maxphyaddr;
- u64 count, addr;
-
- if (vmcs12_read_any(vmcs12, count_field, &count) ||
- vmcs12_read_any(vmcs12, addr_field, &addr)) {
- WARN_ON(1);
- return -EINVAL;
- }
- if (count == 0)
- return 0;
- maxphyaddr = cpuid_maxphyaddr(vcpu);
- if (!IS_ALIGNED(addr, 16) || addr >> maxphyaddr ||
- (addr + count * sizeof(struct vmx_msr_entry) - 1) >> maxphyaddr) {
- pr_debug_ratelimited(
- "nVMX: invalid MSR switch (0x%lx, %d, %llu, 0x%08llx)",
- addr_field, maxphyaddr, count, addr);
- return -EINVAL;
- }
- return 0;
-}
-
-static int nested_vmx_check_msr_switch_controls(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- if (vmcs12->vm_exit_msr_load_count == 0 &&
- vmcs12->vm_exit_msr_store_count == 0 &&
- vmcs12->vm_entry_msr_load_count == 0)
- return 0; /* Fast path */
- if (nested_vmx_check_msr_switch(vcpu, VM_EXIT_MSR_LOAD_COUNT,
- VM_EXIT_MSR_LOAD_ADDR) ||
- nested_vmx_check_msr_switch(vcpu, VM_EXIT_MSR_STORE_COUNT,
- VM_EXIT_MSR_STORE_ADDR) ||
- nested_vmx_check_msr_switch(vcpu, VM_ENTRY_MSR_LOAD_COUNT,
- VM_ENTRY_MSR_LOAD_ADDR))
- return -EINVAL;
- return 0;
-}
-
-static int nested_vmx_check_pml_controls(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- u64 address = vmcs12->pml_address;
- int maxphyaddr = cpuid_maxphyaddr(vcpu);
-
- if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_PML)) {
- if (!nested_cpu_has_ept(vmcs12) ||
- !IS_ALIGNED(address, 4096) ||
- address >> maxphyaddr)
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int nested_vmx_check_shadow_vmcs_controls(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- if (!nested_cpu_has_shadow_vmcs(vmcs12))
- return 0;
-
- if (!page_address_valid(vcpu, vmcs12->vmread_bitmap) ||
- !page_address_valid(vcpu, vmcs12->vmwrite_bitmap))
- return -EINVAL;
-
- return 0;
-}
-
-static int nested_vmx_msr_check_common(struct kvm_vcpu *vcpu,
- struct vmx_msr_entry *e)
-{
- /* x2APIC MSR accesses are not allowed */
- if (vcpu->arch.apic_base & X2APIC_ENABLE && e->index >> 8 == 0x8)
- return -EINVAL;
- if (e->index == MSR_IA32_UCODE_WRITE || /* SDM Table 35-2 */
- e->index == MSR_IA32_UCODE_REV)
- return -EINVAL;
- if (e->reserved != 0)
- return -EINVAL;
- return 0;
-}
-
-static int nested_vmx_load_msr_check(struct kvm_vcpu *vcpu,
- struct vmx_msr_entry *e)
-{
- if (e->index == MSR_FS_BASE ||
- e->index == MSR_GS_BASE ||
- e->index == MSR_IA32_SMM_MONITOR_CTL || /* SMM is not supported */
- nested_vmx_msr_check_common(vcpu, e))
- return -EINVAL;
- return 0;
-}
-
-static int nested_vmx_store_msr_check(struct kvm_vcpu *vcpu,
- struct vmx_msr_entry *e)
-{
- if (e->index == MSR_IA32_SMBASE || /* SMM is not supported */
- nested_vmx_msr_check_common(vcpu, e))
- return -EINVAL;
- return 0;
-}
-
-/*
- * Load guest's/host's msr at nested entry/exit.
- * return 0 for success, entry index for failure.
- */
-static u32 nested_vmx_load_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count)
-{
- u32 i;
- struct vmx_msr_entry e;
- struct msr_data msr;
-
- msr.host_initiated = false;
- for (i = 0; i < count; i++) {
- if (kvm_vcpu_read_guest(vcpu, gpa + i * sizeof(e),
- &e, sizeof(e))) {
- pr_debug_ratelimited(
- "%s cannot read MSR entry (%u, 0x%08llx)\n",
- __func__, i, gpa + i * sizeof(e));
- goto fail;
- }
- if (nested_vmx_load_msr_check(vcpu, &e)) {
- pr_debug_ratelimited(
- "%s check failed (%u, 0x%x, 0x%x)\n",
- __func__, i, e.index, e.reserved);
- goto fail;
- }
- msr.index = e.index;
- msr.data = e.value;
- if (kvm_set_msr(vcpu, &msr)) {
- pr_debug_ratelimited(
- "%s cannot write MSR (%u, 0x%x, 0x%llx)\n",
- __func__, i, e.index, e.value);
- goto fail;
- }
- }
- return 0;
-fail:
- return i + 1;
-}
-
-static int nested_vmx_store_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count)
-{
- u32 i;
- struct vmx_msr_entry e;
-
- for (i = 0; i < count; i++) {
- struct msr_data msr_info;
- if (kvm_vcpu_read_guest(vcpu,
- gpa + i * sizeof(e),
- &e, 2 * sizeof(u32))) {
- pr_debug_ratelimited(
- "%s cannot read MSR entry (%u, 0x%08llx)\n",
- __func__, i, gpa + i * sizeof(e));
- return -EINVAL;
- }
- if (nested_vmx_store_msr_check(vcpu, &e)) {
- pr_debug_ratelimited(
- "%s check failed (%u, 0x%x, 0x%x)\n",
- __func__, i, e.index, e.reserved);
- return -EINVAL;
- }
- msr_info.host_initiated = false;
- msr_info.index = e.index;
- if (kvm_get_msr(vcpu, &msr_info)) {
- pr_debug_ratelimited(
- "%s cannot read MSR (%u, 0x%x)\n",
- __func__, i, e.index);
- return -EINVAL;
- }
- if (kvm_vcpu_write_guest(vcpu,
- gpa + i * sizeof(e) +
- offsetof(struct vmx_msr_entry, value),
- &msr_info.data, sizeof(msr_info.data))) {
- pr_debug_ratelimited(
- "%s cannot write MSR (%u, 0x%x, 0x%llx)\n",
- __func__, i, e.index, msr_info.data);
- return -EINVAL;
- }
- }
- return 0;
-}
-
-static bool nested_cr3_valid(struct kvm_vcpu *vcpu, unsigned long val)
-{
- unsigned long invalid_mask;
-
- invalid_mask = (~0ULL) << cpuid_maxphyaddr(vcpu);
- return (val & invalid_mask) == 0;
-}
-
-/*
- * Load guest's/host's cr3 at nested entry/exit. nested_ept is true if we are
- * emulating VM entry into a guest with EPT enabled.
- * Returns 0 on success, 1 on failure. Invalid state exit qualification code
- * is assigned to entry_failure_code on failure.
- */
-static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool nested_ept,
- u32 *entry_failure_code)
-{
- if (cr3 != kvm_read_cr3(vcpu) || (!nested_ept && pdptrs_changed(vcpu))) {
- if (!nested_cr3_valid(vcpu, cr3)) {
- *entry_failure_code = ENTRY_FAIL_DEFAULT;
- return 1;
- }
-
- /*
- * If PAE paging and EPT are both on, CR3 is not used by the CPU and
- * must not be dereferenced.
- */
- if (is_pae_paging(vcpu) && !nested_ept) {
- if (!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3)) {
- *entry_failure_code = ENTRY_FAIL_PDPTE;
- return 1;
- }
- }
- }
-
- if (!nested_ept)
- kvm_mmu_new_cr3(vcpu, cr3, false);
-
- vcpu->arch.cr3 = cr3;
- __set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
-
- kvm_init_mmu(vcpu, false);
-
- return 0;
-}
-
-static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector);
- vmcs_write16(GUEST_SS_SELECTOR, vmcs12->guest_ss_selector);
- vmcs_write16(GUEST_DS_SELECTOR, vmcs12->guest_ds_selector);
- vmcs_write16(GUEST_FS_SELECTOR, vmcs12->guest_fs_selector);
- vmcs_write16(GUEST_GS_SELECTOR, vmcs12->guest_gs_selector);
- vmcs_write16(GUEST_LDTR_SELECTOR, vmcs12->guest_ldtr_selector);
- vmcs_write16(GUEST_TR_SELECTOR, vmcs12->guest_tr_selector);
- vmcs_write32(GUEST_ES_LIMIT, vmcs12->guest_es_limit);
- vmcs_write32(GUEST_SS_LIMIT, vmcs12->guest_ss_limit);
- vmcs_write32(GUEST_DS_LIMIT, vmcs12->guest_ds_limit);
- vmcs_write32(GUEST_FS_LIMIT, vmcs12->guest_fs_limit);
- vmcs_write32(GUEST_GS_LIMIT, vmcs12->guest_gs_limit);
- vmcs_write32(GUEST_LDTR_LIMIT, vmcs12->guest_ldtr_limit);
- vmcs_write32(GUEST_TR_LIMIT, vmcs12->guest_tr_limit);
- vmcs_write32(GUEST_GDTR_LIMIT, vmcs12->guest_gdtr_limit);
- vmcs_write32(GUEST_IDTR_LIMIT, vmcs12->guest_idtr_limit);
- vmcs_write32(GUEST_ES_AR_BYTES, vmcs12->guest_es_ar_bytes);
- vmcs_write32(GUEST_SS_AR_BYTES, vmcs12->guest_ss_ar_bytes);
- vmcs_write32(GUEST_DS_AR_BYTES, vmcs12->guest_ds_ar_bytes);
- vmcs_write32(GUEST_FS_AR_BYTES, vmcs12->guest_fs_ar_bytes);
- vmcs_write32(GUEST_GS_AR_BYTES, vmcs12->guest_gs_ar_bytes);
- vmcs_write32(GUEST_LDTR_AR_BYTES, vmcs12->guest_ldtr_ar_bytes);
- vmcs_write32(GUEST_TR_AR_BYTES, vmcs12->guest_tr_ar_bytes);
- vmcs_writel(GUEST_SS_BASE, vmcs12->guest_ss_base);
- vmcs_writel(GUEST_DS_BASE, vmcs12->guest_ds_base);
- vmcs_writel(GUEST_FS_BASE, vmcs12->guest_fs_base);
- vmcs_writel(GUEST_GS_BASE, vmcs12->guest_gs_base);
- vmcs_writel(GUEST_LDTR_BASE, vmcs12->guest_ldtr_base);
- vmcs_writel(GUEST_TR_BASE, vmcs12->guest_tr_base);
- vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base);
- vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base);
-
- vmcs_write32(GUEST_SYSENTER_CS, vmcs12->guest_sysenter_cs);
- vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS,
- vmcs12->guest_pending_dbg_exceptions);
- vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->guest_sysenter_esp);
- vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->guest_sysenter_eip);
-
- if (nested_cpu_has_xsaves(vmcs12))
- vmcs_write64(XSS_EXIT_BITMAP, vmcs12->xss_exit_bitmap);
- vmcs_write64(VMCS_LINK_POINTER, -1ull);
-
- if (cpu_has_vmx_posted_intr())
- vmcs_write16(POSTED_INTR_NV, POSTED_INTR_NESTED_VECTOR);
-
- /*
- * Whether page-faults are trapped is determined by a combination of
- * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF.
- * If enable_ept, L0 doesn't care about page faults and we should
- * set all of these to L1's desires. However, if !enable_ept, L0 does
- * care about (at least some) page faults, and because it is not easy
- * (if at all possible?) to merge L0 and L1's desires, we simply ask
- * to exit on each and every L2 page fault. This is done by setting
- * MASK=MATCH=0 and (see below) EB.PF=1.
- * Note that below we don't need special code to set EB.PF beyond the
- * "or"ing of the EB of vmcs01 and vmcs12, because when enable_ept,
- * vmcs01's EB.PF is 0 so the "or" will take vmcs12's value, and when
- * !enable_ept, EB.PF is 1, so the "or" will always be 1.
- */
- vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK,
- enable_ept ? vmcs12->page_fault_error_code_mask : 0);
- vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH,
- enable_ept ? vmcs12->page_fault_error_code_match : 0);
-
- /* All VMFUNCs are currently emulated through L0 vmexits. */
- if (cpu_has_vmx_vmfunc())
- vmcs_write64(VM_FUNCTION_CONTROL, 0);
-
- if (cpu_has_vmx_apicv()) {
- vmcs_write64(EOI_EXIT_BITMAP0, vmcs12->eoi_exit_bitmap0);
- vmcs_write64(EOI_EXIT_BITMAP1, vmcs12->eoi_exit_bitmap1);
- vmcs_write64(EOI_EXIT_BITMAP2, vmcs12->eoi_exit_bitmap2);
- vmcs_write64(EOI_EXIT_BITMAP3, vmcs12->eoi_exit_bitmap3);
- }
-
- /*
- * Set host-state according to L0's settings (vmcs12 is irrelevant here)
- * Some constant fields are set here by vmx_set_constant_host_state().
- * Other fields are different per CPU, and will be set later when
- * vmx_vcpu_load() is called, and when vmx_prepare_switch_to_guest()
- * is called.
- */
- vmx_set_constant_host_state(vmx);
-
- /*
- * Set the MSR load/store lists to match L0's settings.
- */
- vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
- vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
- vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host.val));
- vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
- vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest.val));
-
- set_cr4_guest_host_mask(vmx);
-
- if (kvm_mpx_supported() && vmx->nested.nested_run_pending &&
- (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
- vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
-
- if (enable_vpid) {
- if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02)
- vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->nested.vpid02);
- else
- vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
- }
-
- /*
- * L1 may access the L2's PDPTR, so save them to construct vmcs12
- */
- if (enable_ept) {
- vmcs_write64(GUEST_PDPTR0, vmcs12->guest_pdptr0);
- vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1);
- vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2);
- vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3);
- }
-
- if (cpu_has_vmx_msr_bitmap())
- vmcs_write64(MSR_BITMAP, __pa(vmx->nested.vmcs02.msr_bitmap));
-}
-
-/*
- * prepare_vmcs02 is called when the L1 guest hypervisor runs its nested
- * L2 guest. L1 has a vmcs for L2 (vmcs12), and this function "merges" it
- * with L0's requirements for its guest (a.k.a. vmcs01), so we can run the L2
- * guest in a way that will both be appropriate to L1's requests, and our
- * needs. In addition to modifying the active vmcs (which is vmcs02), this
- * function also has additional necessary side-effects, like setting various
- * vcpu->arch fields.
- * Returns 0 on success, 1 on failure. Invalid state exit qualification code
- * is assigned to entry_failure_code on failure.
- */
-static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
- u32 *entry_failure_code)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 exec_control, vmcs12_exec_ctrl;
-
- if (vmx->nested.dirty_vmcs12) {
- prepare_vmcs02_full(vcpu, vmcs12);
- vmx->nested.dirty_vmcs12 = false;
- }
-
- /*
- * First, the fields that are shadowed. This must be kept in sync
- * with vmx_shadow_fields.h.
- */
-
- vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector);
- vmcs_write32(GUEST_CS_LIMIT, vmcs12->guest_cs_limit);
- vmcs_write32(GUEST_CS_AR_BYTES, vmcs12->guest_cs_ar_bytes);
- vmcs_writel(GUEST_ES_BASE, vmcs12->guest_es_base);
- vmcs_writel(GUEST_CS_BASE, vmcs12->guest_cs_base);
-
- if (vmx->nested.nested_run_pending &&
- (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) {
- kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
- vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
- } else {
- kvm_set_dr(vcpu, 7, vcpu->arch.dr7);
- vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.vmcs01_debugctl);
- }
- if (kvm_mpx_supported() && (!vmx->nested.nested_run_pending ||
- !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)))
- vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs);
- if (vmx->nested.nested_run_pending) {
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
- vmcs12->vm_entry_intr_info_field);
- vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
- vmcs12->vm_entry_exception_error_code);
- vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
- vmcs12->vm_entry_instruction_len);
- vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
- vmcs12->guest_interruptibility_info);
- vmx->loaded_vmcs->nmi_known_unmasked =
- !(vmcs12->guest_interruptibility_info & GUEST_INTR_STATE_NMI);
- } else {
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
- }
- vmx_set_rflags(vcpu, vmcs12->guest_rflags);
-
- exec_control = vmcs12->pin_based_vm_exec_control;
-
- /* Preemption timer setting is computed directly in vmx_vcpu_run. */
- exec_control |= vmcs_config.pin_based_exec_ctrl;
- exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
- vmx->loaded_vmcs->hv_timer_armed = false;
-
- /* Posted interrupts setting is only taken from vmcs12. */
- if (nested_cpu_has_posted_intr(vmcs12)) {
- vmx->nested.posted_intr_nv = vmcs12->posted_intr_nv;
- vmx->nested.pi_pending = false;
- } else {
- exec_control &= ~PIN_BASED_POSTED_INTR;
- }
-
- vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, exec_control);
-
- vmx->nested.preemption_timer_expired = false;
- if (nested_cpu_has_preemption_timer(vmcs12))
- vmx_start_preemption_timer(vcpu);
-
- if (cpu_has_secondary_exec_ctrls()) {
- exec_control = vmx->secondary_exec_control;
-
- /* Take the following fields only from vmcs12 */
- exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
- SECONDARY_EXEC_ENABLE_INVPCID |
- SECONDARY_EXEC_RDTSCP |
- SECONDARY_EXEC_XSAVES |
- SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
- SECONDARY_EXEC_APIC_REGISTER_VIRT |
- SECONDARY_EXEC_ENABLE_VMFUNC);
- if (nested_cpu_has(vmcs12,
- CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)) {
- vmcs12_exec_ctrl = vmcs12->secondary_vm_exec_control &
- ~SECONDARY_EXEC_ENABLE_PML;
- exec_control |= vmcs12_exec_ctrl;
- }
-
- /* VMCS shadowing for L2 is emulated for now */
- exec_control &= ~SECONDARY_EXEC_SHADOW_VMCS;
-
- if (exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)
- vmcs_write16(GUEST_INTR_STATUS,
- vmcs12->guest_intr_status);
-
- /*
- * Write an illegal value to APIC_ACCESS_ADDR. Later,
- * nested_get_vmcs12_pages will either fix it up or
- * remove the VM execution control.
- */
- if (exec_control & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)
- vmcs_write64(APIC_ACCESS_ADDR, -1ull);
-
- if (exec_control & SECONDARY_EXEC_ENCLS_EXITING)
- vmcs_write64(ENCLS_EXITING_BITMAP, -1ull);
-
- vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
- }
-
- /*
- * HOST_RSP is normally set correctly in vmx_vcpu_run() just before
- * entry, but only if the current (host) sp changed from the value
- * we wrote last (vmx->host_rsp). This cache is no longer relevant
- * if we switch vmcs, and rather than hold a separate cache per vmcs,
- * here we just force the write to happen on entry.
- */
- vmx->host_rsp = 0;
-
- exec_control = vmx_exec_control(vmx); /* L0's desires */
- exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
- exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING;
- exec_control &= ~CPU_BASED_TPR_SHADOW;
- exec_control |= vmcs12->cpu_based_vm_exec_control;
-
- /*
- * Write an illegal value to VIRTUAL_APIC_PAGE_ADDR. Later, if
- * nested_get_vmcs12_pages can't fix it up, the illegal value
- * will result in a VM entry failure.
- */
- if (exec_control & CPU_BASED_TPR_SHADOW) {
- vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, -1ull);
- vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold);
- } else {
-#ifdef CONFIG_X86_64
- exec_control |= CPU_BASED_CR8_LOAD_EXITING |
- CPU_BASED_CR8_STORE_EXITING;
-#endif
- }
-
- /*
- * A vmexit (to either L1 hypervisor or L0 userspace) is always needed
- * for I/O port accesses.
- */
- exec_control &= ~CPU_BASED_USE_IO_BITMAPS;
- exec_control |= CPU_BASED_UNCOND_IO_EXITING;
-
- vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
-
- /* EXCEPTION_BITMAP and CR0_GUEST_HOST_MASK should basically be the
- * bitwise-or of what L1 wants to trap for L2, and what we want to
- * trap. Note that CR0.TS also needs updating - we do this later.
- */
- update_exception_bitmap(vcpu);
- vcpu->arch.cr0_guest_owned_bits &= ~vmcs12->cr0_guest_host_mask;
- vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
-
- /* L2->L1 exit controls are emulated - the hardware exit is to L0 so
- * we should use its exit controls. Note that VM_EXIT_LOAD_IA32_EFER
- * bits are further modified by vmx_set_efer() below.
- */
- vmcs_write32(VM_EXIT_CONTROLS, vmcs_config.vmexit_ctrl);
-
- /* vmcs12's VM_ENTRY_LOAD_IA32_EFER and VM_ENTRY_IA32E_MODE are
- * emulated by vmx_set_efer(), below.
- */
- vm_entry_controls_init(vmx,
- (vmcs12->vm_entry_controls & ~VM_ENTRY_LOAD_IA32_EFER &
- ~VM_ENTRY_IA32E_MODE) |
- (vmcs_config.vmentry_ctrl & ~VM_ENTRY_IA32E_MODE));
-
- if (vmx->nested.nested_run_pending &&
- (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT)) {
- vmcs_write64(GUEST_IA32_PAT, vmcs12->guest_ia32_pat);
- vcpu->arch.pat = vmcs12->guest_ia32_pat;
- } else if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
- vmcs_write64(GUEST_IA32_PAT, vmx->vcpu.arch.pat);
- }
-
- vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
-
- if (kvm_has_tsc_control)
- decache_tsc_multiplier(vmx);
-
- if (enable_vpid) {
- /*
- * There is no direct mapping between vpid02 and vpid12, the
- * vpid02 is per-vCPU for L0 and reused while the value of
- * vpid12 is changed w/ one invvpid during nested vmentry.
- * The vpid12 is allocated by L1 for L2, so it will not
- * influence global bitmap(for vpid01 and vpid02 allocation)
- * even if spawn a lot of nested vCPUs.
- */
- if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02) {
- if (vmcs12->virtual_processor_id != vmx->nested.last_vpid) {
- vmx->nested.last_vpid = vmcs12->virtual_processor_id;
- __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
- }
- } else {
- vmx_flush_tlb(vcpu, true);
- }
- }
-
- if (enable_pml) {
- /*
- * Conceptually we want to copy the PML address and index from
- * vmcs01 here, and then back to vmcs01 on nested vmexit. But,
- * since we always flush the log on each vmexit, this happens
- * to be equivalent to simply resetting the fields in vmcs02.
- */
- ASSERT(vmx->pml_pg);
- vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
- vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
- }
-
- if (nested_cpu_has_ept(vmcs12)) {
- if (nested_ept_init_mmu_context(vcpu)) {
- *entry_failure_code = ENTRY_FAIL_DEFAULT;
- return 1;
- }
- } else if (nested_cpu_has2(vmcs12,
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
- vmx_flush_tlb(vcpu, true);
- }
-
- /*
- * This sets GUEST_CR0 to vmcs12->guest_cr0, possibly modifying those
- * bits which we consider mandatory enabled.
- * The CR0_READ_SHADOW is what L2 should have expected to read given
- * the specifications by L1; It's not enough to take
- * vmcs12->cr0_read_shadow because on our cr0_guest_host_mask we we
- * have more bits than L1 expected.
- */
- vmx_set_cr0(vcpu, vmcs12->guest_cr0);
- vmcs_writel(CR0_READ_SHADOW, nested_read_cr0(vmcs12));
-
- vmx_set_cr4(vcpu, vmcs12->guest_cr4);
- vmcs_writel(CR4_READ_SHADOW, nested_read_cr4(vmcs12));
-
- if (vmx->nested.nested_run_pending &&
- (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER))
- vcpu->arch.efer = vmcs12->guest_ia32_efer;
- else if (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE)
- vcpu->arch.efer |= (EFER_LMA | EFER_LME);
- else
- vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
- /* Note: modifies VM_ENTRY/EXIT_CONTROLS and GUEST/HOST_IA32_EFER */
- vmx_set_efer(vcpu, vcpu->arch.efer);
-
- /*
- * Guest state is invalid and unrestricted guest is disabled,
- * which means L1 attempted VMEntry to L2 with invalid state.
- * Fail the VMEntry.
- */
- if (vmx->emulation_required) {
- *entry_failure_code = ENTRY_FAIL_DEFAULT;
- return 1;
- }
-
- /* Shadow page tables on either EPT or shadow page tables. */
- if (nested_vmx_load_cr3(vcpu, vmcs12->guest_cr3, nested_cpu_has_ept(vmcs12),
- entry_failure_code))
- return 1;
-
- if (!enable_ept)
- vcpu->arch.walk_mmu->inject_page_fault = vmx_inject_page_fault_nested;
-
- kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp);
- kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->guest_rip);
- return 0;
-}
-
-static int nested_vmx_check_nmi_controls(struct vmcs12 *vmcs12)
-{
- if (!nested_cpu_has_nmi_exiting(vmcs12) &&
- nested_cpu_has_virtual_nmis(vmcs12))
- return -EINVAL;
-
- if (!nested_cpu_has_virtual_nmis(vmcs12) &&
- nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_NMI_PENDING))
- return -EINVAL;
-
- return 0;
-}
-
-static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- if (vmcs12->guest_activity_state != GUEST_ACTIVITY_ACTIVE &&
- vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT)
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_cpu_has_vpid(vmcs12) && !vmcs12->virtual_processor_id)
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_vmx_check_io_bitmap_controls(vcpu, vmcs12))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_vmx_check_msr_bitmap_controls(vcpu, vmcs12))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_vmx_check_apic_access_controls(vcpu, vmcs12))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_vmx_check_tpr_shadow_controls(vcpu, vmcs12))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_vmx_check_apicv_controls(vcpu, vmcs12))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_vmx_check_pml_controls(vcpu, vmcs12))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_vmx_check_shadow_vmcs_controls(vcpu, vmcs12))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
- vmx->nested.msrs.procbased_ctls_low,
- vmx->nested.msrs.procbased_ctls_high) ||
- (nested_cpu_has(vmcs12, CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) &&
- !vmx_control_verify(vmcs12->secondary_vm_exec_control,
- vmx->nested.msrs.secondary_ctls_low,
- vmx->nested.msrs.secondary_ctls_high)) ||
- !vmx_control_verify(vmcs12->pin_based_vm_exec_control,
- vmx->nested.msrs.pinbased_ctls_low,
- vmx->nested.msrs.pinbased_ctls_high) ||
- !vmx_control_verify(vmcs12->vm_exit_controls,
- vmx->nested.msrs.exit_ctls_low,
- vmx->nested.msrs.exit_ctls_high) ||
- !vmx_control_verify(vmcs12->vm_entry_controls,
- vmx->nested.msrs.entry_ctls_low,
- vmx->nested.msrs.entry_ctls_high))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_vmx_check_nmi_controls(vmcs12))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_cpu_has_vmfunc(vmcs12)) {
- if (vmcs12->vm_function_control &
- ~vmx->nested.msrs.vmfunc_controls)
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (nested_cpu_has_eptp_switching(vmcs12)) {
- if (!nested_cpu_has_ept(vmcs12) ||
- !page_address_valid(vcpu, vmcs12->eptp_list_address))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
- }
- }
-
- if (vmcs12->cr3_target_count > nested_cpu_vmx_misc_cr3_count(vcpu))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- if (!nested_host_cr0_valid(vcpu, vmcs12->host_cr0) ||
- !nested_host_cr4_valid(vcpu, vmcs12->host_cr4) ||
- !nested_cr3_valid(vcpu, vmcs12->host_cr3))
- return VMXERR_ENTRY_INVALID_HOST_STATE_FIELD;
-
- /*
- * From the Intel SDM, volume 3:
- * Fields relevant to VM-entry event injection must be set properly.
- * These fields are the VM-entry interruption-information field, the
- * VM-entry exception error code, and the VM-entry instruction length.
- */
- if (vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK) {
- u32 intr_info = vmcs12->vm_entry_intr_info_field;
- u8 vector = intr_info & INTR_INFO_VECTOR_MASK;
- u32 intr_type = intr_info & INTR_INFO_INTR_TYPE_MASK;
- bool has_error_code = intr_info & INTR_INFO_DELIVER_CODE_MASK;
- bool should_have_error_code;
- bool urg = nested_cpu_has2(vmcs12,
- SECONDARY_EXEC_UNRESTRICTED_GUEST);
- bool prot_mode = !urg || vmcs12->guest_cr0 & X86_CR0_PE;
-
- /* VM-entry interruption-info field: interruption type */
- if (intr_type == INTR_TYPE_RESERVED ||
- (intr_type == INTR_TYPE_OTHER_EVENT &&
- !nested_cpu_supports_monitor_trap_flag(vcpu)))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- /* VM-entry interruption-info field: vector */
- if ((intr_type == INTR_TYPE_NMI_INTR && vector != NMI_VECTOR) ||
- (intr_type == INTR_TYPE_HARD_EXCEPTION && vector > 31) ||
- (intr_type == INTR_TYPE_OTHER_EVENT && vector != 0))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- /* VM-entry interruption-info field: deliver error code */
- should_have_error_code =
- intr_type == INTR_TYPE_HARD_EXCEPTION && prot_mode &&
- x86_exception_has_error_code(vector);
- if (has_error_code != should_have_error_code)
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- /* VM-entry exception error code */
- if (has_error_code &&
- vmcs12->vm_entry_exception_error_code & GENMASK(31, 16))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- /* VM-entry interruption-info field: reserved bits */
- if (intr_info & INTR_INFO_RESVD_BITS_MASK)
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
-
- /* VM-entry instruction length */
- switch (intr_type) {
- case INTR_TYPE_SOFT_EXCEPTION:
- case INTR_TYPE_SOFT_INTR:
- case INTR_TYPE_PRIV_SW_EXCEPTION:
- if ((vmcs12->vm_entry_instruction_len > 15) ||
- (vmcs12->vm_entry_instruction_len == 0 &&
- !nested_cpu_has_zero_length_injection(vcpu)))
- return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
- }
- }
-
- return 0;
-}
-
-static int nested_vmx_check_vmcs_link_ptr(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- int r;
- struct page *page;
- struct vmcs12 *shadow;
-
- if (vmcs12->vmcs_link_pointer == -1ull)
- return 0;
-
- if (!page_address_valid(vcpu, vmcs12->vmcs_link_pointer))
- return -EINVAL;
-
- page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->vmcs_link_pointer);
- if (is_error_page(page))
- return -EINVAL;
-
- r = 0;
- shadow = kmap(page);
- if (shadow->hdr.revision_id != VMCS12_REVISION ||
- shadow->hdr.shadow_vmcs != nested_cpu_has_shadow_vmcs(vmcs12))
- r = -EINVAL;
- kunmap(page);
- kvm_release_page_clean(page);
- return r;
-}
-
-static int check_vmentry_postreqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
- u32 *exit_qual)
-{
- bool ia32e;
-
- *exit_qual = ENTRY_FAIL_DEFAULT;
-
- if (!nested_guest_cr0_valid(vcpu, vmcs12->guest_cr0) ||
- !nested_guest_cr4_valid(vcpu, vmcs12->guest_cr4))
- return 1;
-
- if (nested_vmx_check_vmcs_link_ptr(vcpu, vmcs12)) {
- *exit_qual = ENTRY_FAIL_VMCS_LINK_PTR;
- return 1;
- }
-
- /*
- * If the load IA32_EFER VM-entry control is 1, the following checks
- * are performed on the field for the IA32_EFER MSR:
- * - Bits reserved in the IA32_EFER MSR must be 0.
- * - Bit 10 (corresponding to IA32_EFER.LMA) must equal the value of
- * the IA-32e mode guest VM-exit control. It must also be identical
- * to bit 8 (LME) if bit 31 in the CR0 field (corresponding to
- * CR0.PG) is 1.
- */
- if (to_vmx(vcpu)->nested.nested_run_pending &&
- (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) {
- ia32e = (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) != 0;
- if (!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer) ||
- ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA) ||
- ((vmcs12->guest_cr0 & X86_CR0_PG) &&
- ia32e != !!(vmcs12->guest_ia32_efer & EFER_LME)))
- return 1;
- }
-
- /*
- * If the load IA32_EFER VM-exit control is 1, bits reserved in the
- * IA32_EFER MSR must be 0 in the field for that register. In addition,
- * the values of the LMA and LME bits in the field must each be that of
- * the host address-space size VM-exit control.
- */
- if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER) {
- ia32e = (vmcs12->vm_exit_controls &
- VM_EXIT_HOST_ADDR_SPACE_SIZE) != 0;
- if (!kvm_valid_efer(vcpu, vmcs12->host_ia32_efer) ||
- ia32e != !!(vmcs12->host_ia32_efer & EFER_LMA) ||
- ia32e != !!(vmcs12->host_ia32_efer & EFER_LME))
- return 1;
- }
-
- if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS) &&
- (is_noncanonical_address(vmcs12->guest_bndcfgs & PAGE_MASK, vcpu) ||
- (vmcs12->guest_bndcfgs & MSR_IA32_BNDCFGS_RSVD)))
- return 1;
-
- return 0;
-}
-
-/*
- * If exit_qual is NULL, this is being called from state restore (either RSM
- * or KVM_SET_NESTED_STATE). Otherwise it's called from vmlaunch/vmresume.
- */
-static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- bool from_vmentry = !!exit_qual;
- u32 dummy_exit_qual;
- bool evaluate_pending_interrupts;
- int r = 0;
-
- evaluate_pending_interrupts = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) &
- (CPU_BASED_VIRTUAL_INTR_PENDING | CPU_BASED_VIRTUAL_NMI_PENDING);
- if (likely(!evaluate_pending_interrupts) && kvm_vcpu_apicv_active(vcpu))
- evaluate_pending_interrupts |= vmx_has_apicv_interrupt(vcpu);
-
- enter_guest_mode(vcpu);
-
- if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
- vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
- if (kvm_mpx_supported() &&
- !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
- vmx->nested.vmcs01_guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
-
- vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02);
- vmx_segment_cache_clear(vmx);
-
- if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
- vcpu->arch.tsc_offset += vmcs12->tsc_offset;
-
- r = EXIT_REASON_INVALID_STATE;
- if (prepare_vmcs02(vcpu, vmcs12, from_vmentry ? exit_qual : &dummy_exit_qual))
- goto fail;
-
- if (from_vmentry) {
- nested_get_vmcs12_pages(vcpu);
-
- r = EXIT_REASON_MSR_LOAD_FAIL;
- *exit_qual = nested_vmx_load_msr(vcpu,
- vmcs12->vm_entry_msr_load_addr,
- vmcs12->vm_entry_msr_load_count);
- if (*exit_qual)
- goto fail;
- } else {
- /*
- * The MMU is not initialized to point at the right entities yet and
- * "get pages" would need to read data from the guest (i.e. we will
- * need to perform gpa to hpa translation). Request a call
- * to nested_get_vmcs12_pages before the next VM-entry. The MSRs
- * have already been set at vmentry time and should not be reset.
- */
- kvm_make_request(KVM_REQ_GET_VMCS12_PAGES, vcpu);
- }
-
- /*
- * If L1 had a pending IRQ/NMI until it executed
- * VMLAUNCH/VMRESUME which wasn't delivered because it was
- * disallowed (e.g. interrupts disabled), L0 needs to
- * evaluate if this pending event should cause an exit from L2
- * to L1 or delivered directly to L2 (e.g. In case L1 don't
- * intercept EXTERNAL_INTERRUPT).
- *
- * Usually this would be handled by the processor noticing an
- * IRQ/NMI window request, or checking RVI during evaluation of
- * pending virtual interrupts. However, this setting was done
- * on VMCS01 and now VMCS02 is active instead. Thus, we force L0
- * to perform pending event evaluation by requesting a KVM_REQ_EVENT.
- */
- if (unlikely(evaluate_pending_interrupts))
- kvm_make_request(KVM_REQ_EVENT, vcpu);
-
- /*
- * Note no nested_vmx_succeed or nested_vmx_fail here. At this point
- * we are no longer running L1, and VMLAUNCH/VMRESUME has not yet
- * returned as far as L1 is concerned. It will only return (and set
- * the success flag) when L2 exits (see nested_vmx_vmexit()).
- */
- return 0;
-
-fail:
- if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
- vcpu->arch.tsc_offset -= vmcs12->tsc_offset;
- leave_guest_mode(vcpu);
- vmx_switch_vmcs(vcpu, &vmx->vmcs01);
- return r;
-}
-
-/*
- * nested_vmx_run() handles a nested entry, i.e., a VMLAUNCH or VMRESUME on L1
- * for running an L2 nested guest.
- */
-static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
-{
- struct vmcs12 *vmcs12;
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 interrupt_shadow = vmx_get_interrupt_shadow(vcpu);
- u32 exit_qual;
- int ret;
-
- if (!nested_vmx_check_permission(vcpu))
- return 1;
-
- if (!nested_vmx_check_vmcs12(vcpu))
- goto out;
-
- vmcs12 = get_vmcs12(vcpu);
-
- /*
- * Can't VMLAUNCH or VMRESUME a shadow VMCS. Despite the fact
- * that there *is* a valid VMCS pointer, RFLAGS.CF is set
- * rather than RFLAGS.ZF, and no error number is stored to the
- * VM-instruction error field.
- */
- if (vmcs12->hdr.shadow_vmcs) {
- nested_vmx_failInvalid(vcpu);
- goto out;
- }
-
- if (enable_shadow_vmcs)
- copy_shadow_to_vmcs12(vmx);
-
- /*
- * The nested entry process starts with enforcing various prerequisites
- * on vmcs12 as required by the Intel SDM, and act appropriately when
- * they fail: As the SDM explains, some conditions should cause the
- * instruction to fail, while others will cause the instruction to seem
- * to succeed, but return an EXIT_REASON_INVALID_STATE.
- * To speed up the normal (success) code path, we should avoid checking
- * for misconfigurations which will anyway be caught by the processor
- * when using the merged vmcs02.
- */
- if (interrupt_shadow & KVM_X86_SHADOW_INT_MOV_SS) {
- nested_vmx_failValid(vcpu,
- VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS);
- goto out;
- }
-
- if (vmcs12->launch_state == launch) {
- nested_vmx_failValid(vcpu,
- launch ? VMXERR_VMLAUNCH_NONCLEAR_VMCS
- : VMXERR_VMRESUME_NONLAUNCHED_VMCS);
- goto out;
- }
-
- ret = check_vmentry_prereqs(vcpu, vmcs12);
- if (ret) {
- nested_vmx_failValid(vcpu, ret);
- goto out;
- }
-
- /*
- * After this point, the trap flag no longer triggers a singlestep trap
- * on the vm entry instructions; don't call kvm_skip_emulated_instruction.
- * This is not 100% correct; for performance reasons, we delegate most
- * of the checks on host state to the processor. If those fail,
- * the singlestep trap is missed.
- */
- skip_emulated_instruction(vcpu);
-
- ret = check_vmentry_postreqs(vcpu, vmcs12, &exit_qual);
- if (ret) {
- nested_vmx_entry_failure(vcpu, vmcs12,
- EXIT_REASON_INVALID_STATE, exit_qual);
- return 1;
- }
-
- /*
- * We're finally done with prerequisite checking, and can start with
- * the nested entry.
- */
-
- vmx->nested.nested_run_pending = 1;
- ret = enter_vmx_non_root_mode(vcpu, &exit_qual);
- if (ret) {
- nested_vmx_entry_failure(vcpu, vmcs12, ret, exit_qual);
- vmx->nested.nested_run_pending = 0;
- return 1;
- }
-
- /* Hide L1D cache contents from the nested guest. */
- vmx->vcpu.arch.l1tf_flush_l1d = true;
-
- /*
- * Must happen outside of enter_vmx_non_root_mode() as it will
- * also be used as part of restoring nVMX state for
- * snapshot restore (migration).
- *
- * In this flow, it is assumed that vmcs12 cache was
- * trasferred as part of captured nVMX state and should
- * therefore not be read from guest memory (which may not
- * exist on destination host yet).
- */
- nested_cache_shadow_vmcs12(vcpu, vmcs12);
-
- /*
- * If we're entering a halted L2 vcpu and the L2 vcpu won't be
- * awakened by event injection or by an NMI-window VM-exit or
- * by an interrupt-window VM-exit, halt the vcpu.
- */
- if ((vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT) &&
- !(vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK) &&
- !(vmcs12->cpu_based_vm_exec_control & CPU_BASED_VIRTUAL_NMI_PENDING) &&
- !((vmcs12->cpu_based_vm_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING) &&
- (vmcs12->guest_rflags & X86_EFLAGS_IF))) {
- vmx->nested.nested_run_pending = 0;
- return kvm_vcpu_halt(vcpu);
- }
- return 1;
-
-out:
- return kvm_skip_emulated_instruction(vcpu);
-}
-
-/*
- * On a nested exit from L2 to L1, vmcs12.guest_cr0 might not be up-to-date
- * because L2 may have changed some cr0 bits directly (CRO_GUEST_HOST_MASK).
- * This function returns the new value we should put in vmcs12.guest_cr0.
- * It's not enough to just return the vmcs02 GUEST_CR0. Rather,
- * 1. Bits that neither L0 nor L1 trapped, were set directly by L2 and are now
- * available in vmcs02 GUEST_CR0. (Note: It's enough to check that L0
- * didn't trap the bit, because if L1 did, so would L0).
- * 2. Bits that L1 asked to trap (and therefore L0 also did) could not have
- * been modified by L2, and L1 knows it. So just leave the old value of
- * the bit from vmcs12.guest_cr0. Note that the bit from vmcs02 GUEST_CR0
- * isn't relevant, because if L0 traps this bit it can set it to anything.
- * 3. Bits that L1 didn't trap, but L0 did. L1 believes the guest could have
- * changed these bits, and therefore they need to be updated, but L0
- * didn't necessarily allow them to be changed in GUEST_CR0 - and rather
- * put them in vmcs02 CR0_READ_SHADOW. So take these bits from there.
- */
-static inline unsigned long
-vmcs12_guest_cr0(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
-{
- return
- /*1*/ (vmcs_readl(GUEST_CR0) & vcpu->arch.cr0_guest_owned_bits) |
- /*2*/ (vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask) |
- /*3*/ (vmcs_readl(CR0_READ_SHADOW) & ~(vmcs12->cr0_guest_host_mask |
- vcpu->arch.cr0_guest_owned_bits));
-}
-
-static inline unsigned long
-vmcs12_guest_cr4(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
-{
- return
- /*1*/ (vmcs_readl(GUEST_CR4) & vcpu->arch.cr4_guest_owned_bits) |
- /*2*/ (vmcs12->guest_cr4 & vmcs12->cr4_guest_host_mask) |
- /*3*/ (vmcs_readl(CR4_READ_SHADOW) & ~(vmcs12->cr4_guest_host_mask |
- vcpu->arch.cr4_guest_owned_bits));
-}
-
-static void vmcs12_save_pending_event(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- u32 idt_vectoring;
- unsigned int nr;
-
- if (vcpu->arch.exception.injected) {
- nr = vcpu->arch.exception.nr;
- idt_vectoring = nr | VECTORING_INFO_VALID_MASK;
-
- if (kvm_exception_is_soft(nr)) {
- vmcs12->vm_exit_instruction_len =
- vcpu->arch.event_exit_inst_len;
- idt_vectoring |= INTR_TYPE_SOFT_EXCEPTION;
- } else
- idt_vectoring |= INTR_TYPE_HARD_EXCEPTION;
-
- if (vcpu->arch.exception.has_error_code) {
- idt_vectoring |= VECTORING_INFO_DELIVER_CODE_MASK;
- vmcs12->idt_vectoring_error_code =
- vcpu->arch.exception.error_code;
- }
-
- vmcs12->idt_vectoring_info_field = idt_vectoring;
- } else if (vcpu->arch.nmi_injected) {
- vmcs12->idt_vectoring_info_field =
- INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR;
- } else if (vcpu->arch.interrupt.injected) {
- nr = vcpu->arch.interrupt.nr;
- idt_vectoring = nr | VECTORING_INFO_VALID_MASK;
-
- if (vcpu->arch.interrupt.soft) {
- idt_vectoring |= INTR_TYPE_SOFT_INTR;
- vmcs12->vm_entry_instruction_len =
- vcpu->arch.event_exit_inst_len;
- } else
- idt_vectoring |= INTR_TYPE_EXT_INTR;
-
- vmcs12->idt_vectoring_info_field = idt_vectoring;
- }
-}
-
-static int vmx_check_nested_events(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- unsigned long exit_qual;
- bool block_nested_events =
- vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu);
-
- if (vcpu->arch.exception.pending &&
- nested_vmx_check_exception(vcpu, &exit_qual)) {
- if (block_nested_events)
- return -EBUSY;
- nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
- return 0;
- }
-
- if (nested_cpu_has_preemption_timer(get_vmcs12(vcpu)) &&
- vmx->nested.preemption_timer_expired) {
- if (block_nested_events)
- return -EBUSY;
- nested_vmx_vmexit(vcpu, EXIT_REASON_PREEMPTION_TIMER, 0, 0);
- return 0;
- }
-
- if (vcpu->arch.nmi_pending && nested_exit_on_nmi(vcpu)) {
- if (block_nested_events)
- return -EBUSY;
- nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
- NMI_VECTOR | INTR_TYPE_NMI_INTR |
- INTR_INFO_VALID_MASK, 0);
- /*
- * The NMI-triggered VM exit counts as injection:
- * clear this one and block further NMIs.
- */
- vcpu->arch.nmi_pending = 0;
- vmx_set_nmi_mask(vcpu, true);
- return 0;
- }
-
- if (kvm_cpu_has_interrupt(vcpu) && nested_exit_on_intr(vcpu)) {
- if (block_nested_events)
- return -EBUSY;
- nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0);
- return 0;
- }
-
- vmx_complete_nested_posted_interrupt(vcpu);
- return 0;
-}
-
-static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu)
-{
- to_vmx(vcpu)->req_immediate_exit = true;
-}
-
-static u32 vmx_get_preemption_timer_value(struct kvm_vcpu *vcpu)
-{
- ktime_t remaining =
- hrtimer_get_remaining(&to_vmx(vcpu)->nested.preemption_timer);
- u64 value;
-
- if (ktime_to_ns(remaining) <= 0)
- return 0;
-
- value = ktime_to_ns(remaining) * vcpu->arch.virtual_tsc_khz;
- do_div(value, 1000000);
- return value >> VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE;
-}
-
-/*
- * Update the guest state fields of vmcs12 to reflect changes that
- * occurred while L2 was running. (The "IA-32e mode guest" bit of the
- * VM-entry controls is also updated, since this is really a guest
- * state bit.)
- */
-static void sync_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
-{
- vmcs12->guest_cr0 = vmcs12_guest_cr0(vcpu, vmcs12);
- vmcs12->guest_cr4 = vmcs12_guest_cr4(vcpu, vmcs12);
-
- vmcs12->guest_rsp = kvm_register_read(vcpu, VCPU_REGS_RSP);
- vmcs12->guest_rip = kvm_register_read(vcpu, VCPU_REGS_RIP);
- vmcs12->guest_rflags = vmcs_readl(GUEST_RFLAGS);
-
- vmcs12->guest_es_selector = vmcs_read16(GUEST_ES_SELECTOR);
- vmcs12->guest_cs_selector = vmcs_read16(GUEST_CS_SELECTOR);
- vmcs12->guest_ss_selector = vmcs_read16(GUEST_SS_SELECTOR);
- vmcs12->guest_ds_selector = vmcs_read16(GUEST_DS_SELECTOR);
- vmcs12->guest_fs_selector = vmcs_read16(GUEST_FS_SELECTOR);
- vmcs12->guest_gs_selector = vmcs_read16(GUEST_GS_SELECTOR);
- vmcs12->guest_ldtr_selector = vmcs_read16(GUEST_LDTR_SELECTOR);
- vmcs12->guest_tr_selector = vmcs_read16(GUEST_TR_SELECTOR);
- vmcs12->guest_es_limit = vmcs_read32(GUEST_ES_LIMIT);
- vmcs12->guest_cs_limit = vmcs_read32(GUEST_CS_LIMIT);
- vmcs12->guest_ss_limit = vmcs_read32(GUEST_SS_LIMIT);
- vmcs12->guest_ds_limit = vmcs_read32(GUEST_DS_LIMIT);
- vmcs12->guest_fs_limit = vmcs_read32(GUEST_FS_LIMIT);
- vmcs12->guest_gs_limit = vmcs_read32(GUEST_GS_LIMIT);
- vmcs12->guest_ldtr_limit = vmcs_read32(GUEST_LDTR_LIMIT);
- vmcs12->guest_tr_limit = vmcs_read32(GUEST_TR_LIMIT);
- vmcs12->guest_gdtr_limit = vmcs_read32(GUEST_GDTR_LIMIT);
- vmcs12->guest_idtr_limit = vmcs_read32(GUEST_IDTR_LIMIT);
- vmcs12->guest_es_ar_bytes = vmcs_read32(GUEST_ES_AR_BYTES);
- vmcs12->guest_cs_ar_bytes = vmcs_read32(GUEST_CS_AR_BYTES);
- vmcs12->guest_ss_ar_bytes = vmcs_read32(GUEST_SS_AR_BYTES);
- vmcs12->guest_ds_ar_bytes = vmcs_read32(GUEST_DS_AR_BYTES);
- vmcs12->guest_fs_ar_bytes = vmcs_read32(GUEST_FS_AR_BYTES);
- vmcs12->guest_gs_ar_bytes = vmcs_read32(GUEST_GS_AR_BYTES);
- vmcs12->guest_ldtr_ar_bytes = vmcs_read32(GUEST_LDTR_AR_BYTES);
- vmcs12->guest_tr_ar_bytes = vmcs_read32(GUEST_TR_AR_BYTES);
- vmcs12->guest_es_base = vmcs_readl(GUEST_ES_BASE);
- vmcs12->guest_cs_base = vmcs_readl(GUEST_CS_BASE);
- vmcs12->guest_ss_base = vmcs_readl(GUEST_SS_BASE);
- vmcs12->guest_ds_base = vmcs_readl(GUEST_DS_BASE);
- vmcs12->guest_fs_base = vmcs_readl(GUEST_FS_BASE);
- vmcs12->guest_gs_base = vmcs_readl(GUEST_GS_BASE);
- vmcs12->guest_ldtr_base = vmcs_readl(GUEST_LDTR_BASE);
- vmcs12->guest_tr_base = vmcs_readl(GUEST_TR_BASE);
- vmcs12->guest_gdtr_base = vmcs_readl(GUEST_GDTR_BASE);
- vmcs12->guest_idtr_base = vmcs_readl(GUEST_IDTR_BASE);
-
- vmcs12->guest_interruptibility_info =
- vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
- vmcs12->guest_pending_dbg_exceptions =
- vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS);
- if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
- vmcs12->guest_activity_state = GUEST_ACTIVITY_HLT;
- else
- vmcs12->guest_activity_state = GUEST_ACTIVITY_ACTIVE;
-
- if (nested_cpu_has_preemption_timer(vmcs12)) {
- if (vmcs12->vm_exit_controls &
- VM_EXIT_SAVE_VMX_PREEMPTION_TIMER)
- vmcs12->vmx_preemption_timer_value =
- vmx_get_preemption_timer_value(vcpu);
- hrtimer_cancel(&to_vmx(vcpu)->nested.preemption_timer);
- }
-
- /*
- * In some cases (usually, nested EPT), L2 is allowed to change its
- * own CR3 without exiting. If it has changed it, we must keep it.
- * Of course, if L0 is using shadow page tables, GUEST_CR3 was defined
- * by L0, not L1 or L2, so we mustn't unconditionally copy it to vmcs12.
- *
- * Additionally, restore L2's PDPTR to vmcs12.
- */
- if (enable_ept) {
- vmcs12->guest_cr3 = vmcs_readl(GUEST_CR3);
- vmcs12->guest_pdptr0 = vmcs_read64(GUEST_PDPTR0);
- vmcs12->guest_pdptr1 = vmcs_read64(GUEST_PDPTR1);
- vmcs12->guest_pdptr2 = vmcs_read64(GUEST_PDPTR2);
- vmcs12->guest_pdptr3 = vmcs_read64(GUEST_PDPTR3);
- }
-
- vmcs12->guest_linear_address = vmcs_readl(GUEST_LINEAR_ADDRESS);
-
- if (nested_cpu_has_vid(vmcs12))
- vmcs12->guest_intr_status = vmcs_read16(GUEST_INTR_STATUS);
-
- vmcs12->vm_entry_controls =
- (vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) |
- (vm_entry_controls_get(to_vmx(vcpu)) & VM_ENTRY_IA32E_MODE);
-
- if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_DEBUG_CONTROLS) {
- kvm_get_dr(vcpu, 7, (unsigned long *)&vmcs12->guest_dr7);
- vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
- }
-
- /* TODO: These cannot have changed unless we have MSR bitmaps and
- * the relevant bit asks not to trap the change */
- if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_PAT)
- vmcs12->guest_ia32_pat = vmcs_read64(GUEST_IA32_PAT);
- if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_EFER)
- vmcs12->guest_ia32_efer = vcpu->arch.efer;
- vmcs12->guest_sysenter_cs = vmcs_read32(GUEST_SYSENTER_CS);
- vmcs12->guest_sysenter_esp = vmcs_readl(GUEST_SYSENTER_ESP);
- vmcs12->guest_sysenter_eip = vmcs_readl(GUEST_SYSENTER_EIP);
- if (kvm_mpx_supported())
- vmcs12->guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
-}
-
-/*
- * prepare_vmcs12 is part of what we need to do when the nested L2 guest exits
- * and we want to prepare to run its L1 parent. L1 keeps a vmcs for L2 (vmcs12),
- * and this function updates it to reflect the changes to the guest state while
- * L2 was running (and perhaps made some exits which were handled directly by L0
- * without going back to L1), and to reflect the exit reason.
- * Note that we do not have to copy here all VMCS fields, just those that
- * could have changed by the L2 guest or the exit - i.e., the guest-state and
- * exit-information fields only. Other fields are modified by L1 with VMWRITE,
- * which already writes to vmcs12 directly.
- */
-static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
- u32 exit_reason, u32 exit_intr_info,
- unsigned long exit_qualification)
-{
- /* update guest state fields: */
- sync_vmcs12(vcpu, vmcs12);
-
- /* update exit information fields: */
-
- vmcs12->vm_exit_reason = exit_reason;
- vmcs12->exit_qualification = exit_qualification;
- vmcs12->vm_exit_intr_info = exit_intr_info;
-
- vmcs12->idt_vectoring_info_field = 0;
- vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
- vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
-
- if (!(vmcs12->vm_exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY)) {
- vmcs12->launch_state = 1;
-
- /* vm_entry_intr_info_field is cleared on exit. Emulate this
- * instead of reading the real value. */
- vmcs12->vm_entry_intr_info_field &= ~INTR_INFO_VALID_MASK;
-
- /*
- * Transfer the event that L0 or L1 may wanted to inject into
- * L2 to IDT_VECTORING_INFO_FIELD.
- */
- vmcs12_save_pending_event(vcpu, vmcs12);
- }
-}
-
-/*
- * A part of what we need to when the nested L2 guest exits and we want to
- * run its L1 parent, is to reset L1's guest state to the host state specified
- * in vmcs12.
- * This function is to be called not only on normal nested exit, but also on
- * a nested entry failure, as explained in Intel's spec, 3B.23.7 ("VM-Entry
- * Failures During or After Loading Guest State").
- * This function should be called when the active VMCS is L1's (vmcs01).
- */
-static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12)
-{
- struct kvm_segment seg;
- u32 entry_failure_code;
-
- if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
- vcpu->arch.efer = vmcs12->host_ia32_efer;
- else if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
- vcpu->arch.efer |= (EFER_LMA | EFER_LME);
- else
- vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
- vmx_set_efer(vcpu, vcpu->arch.efer);
-
- kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->host_rsp);
- kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->host_rip);
- vmx_set_rflags(vcpu, X86_EFLAGS_FIXED);
- /*
- * Note that calling vmx_set_cr0 is important, even if cr0 hasn't
- * actually changed, because vmx_set_cr0 refers to efer set above.
- *
- * CR0_GUEST_HOST_MASK is already set in the original vmcs01
- * (KVM doesn't change it);
- */
- vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
- vmx_set_cr0(vcpu, vmcs12->host_cr0);
-
- /* Same as above - no reason to call set_cr4_guest_host_mask(). */
- vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
- vmx_set_cr4(vcpu, vmcs12->host_cr4);
-
- nested_ept_uninit_mmu_context(vcpu);
-
- /*
- * Only PDPTE load can fail as the value of cr3 was checked on entry and
- * couldn't have changed.
- */
- if (nested_vmx_load_cr3(vcpu, vmcs12->host_cr3, false, &entry_failure_code))
- nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_PDPTE_FAIL);
-
- if (!enable_ept)
- vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault;
-
- /*
- * If vmcs01 don't use VPID, CPU flushes TLB on every
- * VMEntry/VMExit. Thus, no need to flush TLB.
- *
- * If vmcs12 uses VPID, TLB entries populated by L2 are
- * tagged with vmx->nested.vpid02 while L1 entries are tagged
- * with vmx->vpid. Thus, no need to flush TLB.
- *
- * Therefore, flush TLB only in case vmcs01 uses VPID and
- * vmcs12 don't use VPID as in this case L1 & L2 TLB entries
- * are both tagged with vmx->vpid.
- */
- if (enable_vpid &&
- !(nested_cpu_has_vpid(vmcs12) && to_vmx(vcpu)->nested.vpid02)) {
- vmx_flush_tlb(vcpu, true);
- }
-
- vmcs_write32(GUEST_SYSENTER_CS, vmcs12->host_ia32_sysenter_cs);
- vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->host_ia32_sysenter_esp);
- vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->host_ia32_sysenter_eip);
- vmcs_writel(GUEST_IDTR_BASE, vmcs12->host_idtr_base);
- vmcs_writel(GUEST_GDTR_BASE, vmcs12->host_gdtr_base);
- vmcs_write32(GUEST_IDTR_LIMIT, 0xFFFF);
- vmcs_write32(GUEST_GDTR_LIMIT, 0xFFFF);
-
- /* If not VM_EXIT_CLEAR_BNDCFGS, the L2 value propagates to L1. */
- if (vmcs12->vm_exit_controls & VM_EXIT_CLEAR_BNDCFGS)
- vmcs_write64(GUEST_BNDCFGS, 0);
-
- if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PAT) {
- vmcs_write64(GUEST_IA32_PAT, vmcs12->host_ia32_pat);
- vcpu->arch.pat = vmcs12->host_ia32_pat;
- }
- if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
- vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL,
- vmcs12->host_ia32_perf_global_ctrl);
-
- /* Set L1 segment info according to Intel SDM
- 27.5.2 Loading Host Segment and Descriptor-Table Registers */
- seg = (struct kvm_segment) {
- .base = 0,
- .limit = 0xFFFFFFFF,
- .selector = vmcs12->host_cs_selector,
- .type = 11,
- .present = 1,
- .s = 1,
- .g = 1
- };
- if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
- seg.l = 1;
- else
- seg.db = 1;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_CS);
- seg = (struct kvm_segment) {
- .base = 0,
- .limit = 0xFFFFFFFF,
- .type = 3,
- .present = 1,
- .s = 1,
- .db = 1,
- .g = 1
- };
- seg.selector = vmcs12->host_ds_selector;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_DS);
- seg.selector = vmcs12->host_es_selector;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_ES);
- seg.selector = vmcs12->host_ss_selector;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_SS);
- seg.selector = vmcs12->host_fs_selector;
- seg.base = vmcs12->host_fs_base;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_FS);
- seg.selector = vmcs12->host_gs_selector;
- seg.base = vmcs12->host_gs_base;
- vmx_set_segment(vcpu, &seg, VCPU_SREG_GS);
- seg = (struct kvm_segment) {
- .base = vmcs12->host_tr_base,
- .limit = 0x67,
- .selector = vmcs12->host_tr_selector,
- .type = 11,
- .present = 1
- };
- vmx_set_segment(vcpu, &seg, VCPU_SREG_TR);
-
- kvm_set_dr(vcpu, 7, 0x400);
- vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
-
- if (cpu_has_vmx_msr_bitmap())
- vmx_update_msr_bitmap(vcpu);
-
- if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr,
- vmcs12->vm_exit_msr_load_count))
- nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL);
-}
-
-static inline u64 nested_vmx_get_vmcs01_guest_efer(struct vcpu_vmx *vmx)
-{
- struct shared_msr_entry *efer_msr;
- unsigned int i;
-
- if (vm_entry_controls_get(vmx) & VM_ENTRY_LOAD_IA32_EFER)
- return vmcs_read64(GUEST_IA32_EFER);
-
- if (cpu_has_load_ia32_efer)
- return host_efer;
-
- for (i = 0; i < vmx->msr_autoload.guest.nr; ++i) {
- if (vmx->msr_autoload.guest.val[i].index == MSR_EFER)
- return vmx->msr_autoload.guest.val[i].value;
- }
-
- efer_msr = find_msr_entry(vmx, MSR_EFER);
- if (efer_msr)
- return efer_msr->data;
-
- return host_efer;
-}
-
-static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct vmx_msr_entry g, h;
- struct msr_data msr;
- gpa_t gpa;
- u32 i, j;
-
- vcpu->arch.pat = vmcs_read64(GUEST_IA32_PAT);
-
- if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) {
- /*
- * L1's host DR7 is lost if KVM_GUESTDBG_USE_HW_BP is set
- * as vmcs01.GUEST_DR7 contains a userspace defined value
- * and vcpu->arch.dr7 is not squirreled away before the
- * nested VMENTER (not worth adding a variable in nested_vmx).
- */
- if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
- kvm_set_dr(vcpu, 7, DR7_FIXED_1);
- else
- WARN_ON(kvm_set_dr(vcpu, 7, vmcs_readl(GUEST_DR7)));
- }
-
- /*
- * Note that calling vmx_set_{efer,cr0,cr4} is important as they
- * handle a variety of side effects to KVM's software model.
- */
- vmx_set_efer(vcpu, nested_vmx_get_vmcs01_guest_efer(vmx));
-
- vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
- vmx_set_cr0(vcpu, vmcs_readl(CR0_READ_SHADOW));
-
- vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
- vmx_set_cr4(vcpu, vmcs_readl(CR4_READ_SHADOW));
-
- nested_ept_uninit_mmu_context(vcpu);
- vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
- __set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
-
- /*
- * Use ept_save_pdptrs(vcpu) to load the MMU's cached PDPTRs
- * from vmcs01 (if necessary). The PDPTRs are not loaded on
- * VMFail, like everything else we just need to ensure our
- * software model is up-to-date.
- */
- ept_save_pdptrs(vcpu);
-
- kvm_mmu_reset_context(vcpu);
-
- if (cpu_has_vmx_msr_bitmap())
- vmx_update_msr_bitmap(vcpu);
-
- /*
- * This nasty bit of open coding is a compromise between blindly
- * loading L1's MSRs using the exit load lists (incorrect emulation
- * of VMFail), leaving the nested VM's MSRs in the software model
- * (incorrect behavior) and snapshotting the modified MSRs (too
- * expensive since the lists are unbound by hardware). For each
- * MSR that was (prematurely) loaded from the nested VMEntry load
- * list, reload it from the exit load list if it exists and differs
- * from the guest value. The intent is to stuff host state as
- * silently as possible, not to fully process the exit load list.
- */
- msr.host_initiated = false;
- for (i = 0; i < vmcs12->vm_entry_msr_load_count; i++) {
- gpa = vmcs12->vm_entry_msr_load_addr + (i * sizeof(g));
- if (kvm_vcpu_read_guest(vcpu, gpa, &g, sizeof(g))) {
- pr_debug_ratelimited(
- "%s read MSR index failed (%u, 0x%08llx)\n",
- __func__, i, gpa);
- goto vmabort;
- }
-
- for (j = 0; j < vmcs12->vm_exit_msr_load_count; j++) {
- gpa = vmcs12->vm_exit_msr_load_addr + (j * sizeof(h));
- if (kvm_vcpu_read_guest(vcpu, gpa, &h, sizeof(h))) {
- pr_debug_ratelimited(
- "%s read MSR failed (%u, 0x%08llx)\n",
- __func__, j, gpa);
- goto vmabort;
- }
- if (h.index != g.index)
- continue;
- if (h.value == g.value)
- break;
-
- if (nested_vmx_load_msr_check(vcpu, &h)) {
- pr_debug_ratelimited(
- "%s check failed (%u, 0x%x, 0x%x)\n",
- __func__, j, h.index, h.reserved);
- goto vmabort;
- }
-
- msr.index = h.index;
- msr.data = h.value;
- if (kvm_set_msr(vcpu, &msr)) {
- pr_debug_ratelimited(
- "%s WRMSR failed (%u, 0x%x, 0x%llx)\n",
- __func__, j, h.index, h.value);
- goto vmabort;
- }
- }
- }
-
- return;
-
-vmabort:
- nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL);
-}
-
-/*
- * Emulate an exit from nested guest (L2) to L1, i.e., prepare to run L1
- * and modify vmcs12 to make it see what it would expect to see there if
- * L2 was its real guest. Must only be called when in L2 (is_guest_mode())
- */
-static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
- u32 exit_intr_info,
- unsigned long exit_qualification)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
-
- /* trying to cancel vmlaunch/vmresume is a bug */
- WARN_ON_ONCE(vmx->nested.nested_run_pending);
-
- /*
- * The only expected VM-instruction error is "VM entry with
- * invalid control field(s)." Anything else indicates a
- * problem with L0.
- */
- WARN_ON_ONCE(vmx->fail && (vmcs_read32(VM_INSTRUCTION_ERROR) !=
- VMXERR_ENTRY_INVALID_CONTROL_FIELD));
-
- leave_guest_mode(vcpu);
-
- if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
- vcpu->arch.tsc_offset -= vmcs12->tsc_offset;
-
- if (likely(!vmx->fail)) {
- if (exit_reason == -1)
- sync_vmcs12(vcpu, vmcs12);
- else
- prepare_vmcs12(vcpu, vmcs12, exit_reason, exit_intr_info,
- exit_qualification);
-
- /*
- * Must happen outside of sync_vmcs12() as it will
- * also be used to capture vmcs12 cache as part of
- * capturing nVMX state for snapshot (migration).
- *
- * Otherwise, this flush will dirty guest memory at a
- * point it is already assumed by user-space to be
- * immutable.
- */
- nested_flush_cached_shadow_vmcs12(vcpu, vmcs12);
-
- if (nested_vmx_store_msr(vcpu, vmcs12->vm_exit_msr_store_addr,
- vmcs12->vm_exit_msr_store_count))
- nested_vmx_abort(vcpu, VMX_ABORT_SAVE_GUEST_MSR_FAIL);
- }
-
- /*
- * Drop events/exceptions that were queued for re-injection to L2
- * (picked up via vmx_complete_interrupts()), as well as exceptions
- * that were pending for L2. Note, this must NOT be hoisted above
- * prepare_vmcs12(), events/exceptions queued for re-injection need to
- * be captured in vmcs12 (see vmcs12_save_pending_event()).
- */
- vcpu->arch.nmi_injected = false;
- kvm_clear_exception_queue(vcpu);
- kvm_clear_interrupt_queue(vcpu);
-
- vmx_switch_vmcs(vcpu, &vmx->vmcs01);
- vm_entry_controls_reset_shadow(vmx);
- vm_exit_controls_reset_shadow(vmx);
- vmx_segment_cache_clear(vmx);
-
- /* Update any VMCS fields that might have changed while L2 ran */
- vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
- vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
- vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
-
- if (kvm_has_tsc_control)
- decache_tsc_multiplier(vmx);
-
- if (vmx->nested.change_vmcs01_virtual_apic_mode) {
- vmx->nested.change_vmcs01_virtual_apic_mode = false;
- vmx_set_virtual_apic_mode(vcpu);
- } else if (!nested_cpu_has_ept(vmcs12) &&
- nested_cpu_has2(vmcs12,
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
- vmx_flush_tlb(vcpu, true);
- }
-
- /* This is needed for same reason as it was needed in prepare_vmcs02 */
- vmx->host_rsp = 0;
-
- /* Unpin physical memory we referred to in vmcs02 */
- if (vmx->nested.apic_access_page) {
- kvm_release_page_dirty(vmx->nested.apic_access_page);
- vmx->nested.apic_access_page = NULL;
- }
- if (vmx->nested.virtual_apic_page) {
- kvm_release_page_dirty(vmx->nested.virtual_apic_page);
- vmx->nested.virtual_apic_page = NULL;
- }
- if (vmx->nested.pi_desc_page) {
- kunmap(vmx->nested.pi_desc_page);
- kvm_release_page_dirty(vmx->nested.pi_desc_page);
- vmx->nested.pi_desc_page = NULL;
- vmx->nested.pi_desc = NULL;
- }
-
- /*
- * We are now running in L2, mmu_notifier will force to reload the
- * page's hpa for L2 vmcs. Need to reload it for L1 before entering L1.
- */
- kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
-
- if (enable_shadow_vmcs && exit_reason != -1)
- vmx->nested.sync_shadow_vmcs = true;
-
- /* in case we halted in L2 */
- vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
-
- if (likely(!vmx->fail)) {
- if (exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT &&
- nested_exit_intr_ack_set(vcpu)) {
- int irq = kvm_cpu_get_interrupt(vcpu);
- WARN_ON(irq < 0);
- vmcs12->vm_exit_intr_info = irq |
- INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR;
- }
-
- if (exit_reason != -1)
- trace_kvm_nested_vmexit_inject(vmcs12->vm_exit_reason,
- vmcs12->exit_qualification,
- vmcs12->idt_vectoring_info_field,
- vmcs12->vm_exit_intr_info,
- vmcs12->vm_exit_intr_error_code,
- KVM_ISA_VMX);
-
- load_vmcs12_host_state(vcpu, vmcs12);
-
- return;
- }
-
- /*
- * After an early L2 VM-entry failure, we're now back
- * in L1 which thinks it just finished a VMLAUNCH or
- * VMRESUME instruction, so we need to set the failure
- * flag and the VM-instruction error field of the VMCS
- * accordingly.
- */
- nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
-
- /*
- * Restore L1's host state to KVM's software model. We're here
- * because a consistency check was caught by hardware, which
- * means some amount of guest state has been propagated to KVM's
- * model and needs to be unwound to the host's state.
- */
- nested_vmx_restore_host_state(vcpu);
-
- /*
- * The emulated instruction was already skipped in
- * nested_vmx_run, but the updated RIP was never
- * written back to the vmcs01.
- */
- skip_emulated_instruction(vcpu);
- vmx->fail = 0;
-}
-
-/*
- * Forcibly leave nested mode in order to be able to reset the VCPU later on.
- */
-static void vmx_leave_nested(struct kvm_vcpu *vcpu)
-{
- if (is_guest_mode(vcpu)) {
- to_vmx(vcpu)->nested.nested_run_pending = 0;
- nested_vmx_vmexit(vcpu, -1, 0, 0);
- }
- free_nested(to_vmx(vcpu));
-}
-
-/*
- * L1's failure to enter L2 is a subset of a normal exit, as explained in
- * 23.7 "VM-entry failures during or after loading guest state" (this also
- * lists the acceptable exit-reason and exit-qualification parameters).
- * It should only be called before L2 actually succeeded to run, and when
- * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss).
- */
-static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
- struct vmcs12 *vmcs12,
- u32 reason, unsigned long qualification)
-{
- load_vmcs12_host_state(vcpu, vmcs12);
- vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY;
- vmcs12->exit_qualification = qualification;
- nested_vmx_succeed(vcpu);
- if (enable_shadow_vmcs)
- to_vmx(vcpu)->nested.sync_shadow_vmcs = true;
-}
-
-static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
- struct x86_instruction_info *info)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- unsigned short port;
- bool intercept;
- int size;
-
- if (info->intercept == x86_intercept_in ||
- info->intercept == x86_intercept_ins) {
- port = info->src_val;
- size = info->dst_bytes;
- } else {
- port = info->dst_val;
- size = info->src_bytes;
- }
-
- /*
- * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
- * VM-exits depend on the 'unconditional IO exiting' VM-execution
- * control.
- *
- * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
- */
- if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
- intercept = nested_cpu_has(vmcs12,
- CPU_BASED_UNCOND_IO_EXITING);
- else
- intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
-
- /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED. */
- return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
-}
-
-static int vmx_check_intercept(struct kvm_vcpu *vcpu,
- struct x86_instruction_info *info,
- enum x86_intercept_stage stage)
-{
- struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
- struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
-
- switch (info->intercept) {
- /*
- * RDPID causes #UD if disabled through secondary execution controls.
- * Because it is marked as EmulateOnUD, we need to intercept it here.
- */
- case x86_intercept_rdtscp:
- if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
- ctxt->exception.vector = UD_VECTOR;
- ctxt->exception.error_code_valid = false;
- return X86EMUL_PROPAGATE_FAULT;
- }
- break;
-
- case x86_intercept_in:
- case x86_intercept_ins:
- case x86_intercept_out:
- case x86_intercept_outs:
- return vmx_check_intercept_io(vcpu, info);
-
- case x86_intercept_lgdt:
- case x86_intercept_lidt:
- case x86_intercept_lldt:
- case x86_intercept_ltr:
- case x86_intercept_sgdt:
- case x86_intercept_sidt:
- case x86_intercept_sldt:
- case x86_intercept_str:
- if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC))
- return X86EMUL_CONTINUE;
-
- /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED. */
- break;
-
- /* TODO: check more intercepts... */
- default:
- break;
- }
-
- return X86EMUL_UNHANDLEABLE;
-}
-
-#ifdef CONFIG_X86_64
-/* (a << shift) / divisor, return 1 if overflow otherwise 0 */
-static inline int u64_shl_div_u64(u64 a, unsigned int shift,
- u64 divisor, u64 *result)
-{
- u64 low = a << shift, high = a >> (64 - shift);
-
- /* To avoid the overflow on divq */
- if (high >= divisor)
- return 1;
-
- /* Low hold the result, high hold rem which is discarded */
- asm("divq %2\n\t" : "=a" (low), "=d" (high) :
- "rm" (divisor), "0" (low), "1" (high));
- *result = low;
-
- return 0;
-}
-
-static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
-{
- struct vcpu_vmx *vmx;
- u64 tscl, guest_tscl, delta_tsc, lapic_timer_advance_cycles;
-
- if (kvm_mwait_in_guest(vcpu->kvm))
- return -EOPNOTSUPP;
-
- vmx = to_vmx(vcpu);
- tscl = rdtsc();
- guest_tscl = kvm_read_l1_tsc(vcpu, tscl);
- delta_tsc = max(guest_deadline_tsc, guest_tscl) - guest_tscl;
- lapic_timer_advance_cycles = nsec_to_cycles(vcpu, lapic_timer_advance_ns);
-
- if (delta_tsc > lapic_timer_advance_cycles)
- delta_tsc -= lapic_timer_advance_cycles;
- else
- delta_tsc = 0;
-
- /* Convert to host delta tsc if tsc scaling is enabled */
- if (vcpu->arch.tsc_scaling_ratio != kvm_default_tsc_scaling_ratio &&
- u64_shl_div_u64(delta_tsc,
- kvm_tsc_scaling_ratio_frac_bits,
- vcpu->arch.tsc_scaling_ratio,
- &delta_tsc))
- return -ERANGE;
-
- /*
- * If the delta tsc can't fit in the 32 bit after the multi shift,
- * we can't use the preemption timer.
- * It's possible that it fits on later vmentries, but checking
- * on every vmentry is costly so we just use an hrtimer.
- */
- if (delta_tsc >> (cpu_preemption_timer_multi + 32))
- return -ERANGE;
-
- vmx->hv_deadline_tsc = tscl + delta_tsc;
- return delta_tsc == 0;
-}
-
-static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu)
-{
- to_vmx(vcpu)->hv_deadline_tsc = -1;
-}
-#endif
-
-static void vmx_sched_in(struct kvm_vcpu *vcpu, int cpu)
-{
- if (!kvm_pause_in_guest(vcpu->kvm))
- shrink_ple_window(vcpu);
-}
-
-static void vmx_slot_enable_log_dirty(struct kvm *kvm,
- struct kvm_memory_slot *slot)
-{
- kvm_mmu_slot_leaf_clear_dirty(kvm, slot);
- kvm_mmu_slot_largepage_remove_write_access(kvm, slot);
-}
-
-static void vmx_slot_disable_log_dirty(struct kvm *kvm,
- struct kvm_memory_slot *slot)
-{
- kvm_mmu_slot_set_dirty(kvm, slot);
-}
-
-static void vmx_flush_log_dirty(struct kvm *kvm)
-{
- kvm_flush_pml_buffers(kvm);
-}
-
-static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa)
-{
- struct vmcs12 *vmcs12;
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct page *page = NULL;
- u64 *pml_address;
-
- if (is_guest_mode(vcpu)) {
- WARN_ON_ONCE(vmx->nested.pml_full);
-
- /*
- * Check if PML is enabled for the nested guest.
- * Whether eptp bit 6 is set is already checked
- * as part of A/D emulation.
- */
- vmcs12 = get_vmcs12(vcpu);
- if (!nested_cpu_has_pml(vmcs12))
- return 0;
-
- if (vmcs12->guest_pml_index >= PML_ENTITY_NUM) {
- vmx->nested.pml_full = true;
- return 1;
- }
-
- gpa &= ~0xFFFull;
-
- page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->pml_address);
- if (is_error_page(page))
- return 0;
-
- pml_address = kmap(page);
- pml_address[vmcs12->guest_pml_index--] = gpa;
- kunmap(page);
- kvm_release_page_clean(page);
- }
-
- return 0;
-}
-
-static void vmx_enable_log_dirty_pt_masked(struct kvm *kvm,
- struct kvm_memory_slot *memslot,
- gfn_t offset, unsigned long mask)
-{
- kvm_mmu_clear_dirty_pt_masked(kvm, memslot, offset, mask);
-}
-
-static void __pi_post_block(struct kvm_vcpu *vcpu)
-{
- struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
- struct pi_desc old, new;
- unsigned int dest;
-
- do {
- old.control = new.control = pi_desc->control;
- WARN(old.nv != POSTED_INTR_WAKEUP_VECTOR,
- "Wakeup handler not enabled while the VCPU is blocked\n");
-
- dest = cpu_physical_id(vcpu->cpu);
-
- if (x2apic_enabled())
- new.ndst = dest;
- else
- new.ndst = (dest << 8) & 0xFF00;
-
- /* set 'NV' to 'notification vector' */
- new.nv = POSTED_INTR_VECTOR;
- } while (cmpxchg64(&pi_desc->control, old.control,
- new.control) != old.control);
-
- if (!WARN_ON_ONCE(vcpu->pre_pcpu == -1)) {
- spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
- list_del(&vcpu->blocked_vcpu_list);
- spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
- vcpu->pre_pcpu = -1;
- }
-}
-
-/*
- * This routine does the following things for vCPU which is going
- * to be blocked if VT-d PI is enabled.
- * - Store the vCPU to the wakeup list, so when interrupts happen
- * we can find the right vCPU to wake up.
- * - Change the Posted-interrupt descriptor as below:
- * 'NDST' <-- vcpu->pre_pcpu
- * 'NV' <-- POSTED_INTR_WAKEUP_VECTOR
- * - If 'ON' is set during this process, which means at least one
- * interrupt is posted for this vCPU, we cannot block it, in
- * this case, return 1, otherwise, return 0.
- *
- */
-static int pi_pre_block(struct kvm_vcpu *vcpu)
-{
- unsigned int dest;
- struct pi_desc old, new;
- struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
-
- if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
- !irq_remapping_cap(IRQ_POSTING_CAP) ||
- !kvm_vcpu_apicv_active(vcpu))
- return 0;
-
- WARN_ON(irqs_disabled());
- local_irq_disable();
- if (!WARN_ON_ONCE(vcpu->pre_pcpu != -1)) {
- vcpu->pre_pcpu = vcpu->cpu;
- spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
- list_add_tail(&vcpu->blocked_vcpu_list,
- &per_cpu(blocked_vcpu_on_cpu,
- vcpu->pre_pcpu));
- spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
- }
-
- do {
- old.control = new.control = pi_desc->control;
-
- WARN((pi_desc->sn == 1),
- "Warning: SN field of posted-interrupts "
- "is set before blocking\n");
-
- /*
- * Since vCPU can be preempted during this process,
- * vcpu->cpu could be different with pre_pcpu, we
- * need to set pre_pcpu as the destination of wakeup
- * notification event, then we can find the right vCPU
- * to wakeup in wakeup handler if interrupts happen
- * when the vCPU is in blocked state.
- */
- dest = cpu_physical_id(vcpu->pre_pcpu);
-
- if (x2apic_enabled())
- new.ndst = dest;
- else
- new.ndst = (dest << 8) & 0xFF00;
-
- /* set 'NV' to 'wakeup vector' */
- new.nv = POSTED_INTR_WAKEUP_VECTOR;
- } while (cmpxchg64(&pi_desc->control, old.control,
- new.control) != old.control);
-
- /* We should not block the vCPU if an interrupt is posted for it. */
- if (pi_test_on(pi_desc) == 1)
- __pi_post_block(vcpu);
-
- local_irq_enable();
- return (vcpu->pre_pcpu == -1);
-}
-
-static int vmx_pre_block(struct kvm_vcpu *vcpu)
-{
- if (pi_pre_block(vcpu))
- return 1;
-
- if (kvm_lapic_hv_timer_in_use(vcpu))
- kvm_lapic_switch_to_sw_timer(vcpu);
-
- return 0;
-}
-
-static void pi_post_block(struct kvm_vcpu *vcpu)
-{
- if (vcpu->pre_pcpu == -1)
- return;
-
- WARN_ON(irqs_disabled());
- local_irq_disable();
- __pi_post_block(vcpu);
- local_irq_enable();
-}
-
-static void vmx_post_block(struct kvm_vcpu *vcpu)
-{
- if (kvm_x86_ops->set_hv_timer)
- kvm_lapic_switch_to_hv_timer(vcpu);
-
- pi_post_block(vcpu);
-}
-
-/*
- * vmx_update_pi_irte - set IRTE for Posted-Interrupts
- *
- * @kvm: kvm
- * @host_irq: host irq of the interrupt
- * @guest_irq: gsi of the interrupt
- * @set: set or unset PI
- * returns 0 on success, < 0 on failure
- */
-static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
- uint32_t guest_irq, bool set)
-{
- struct kvm_kernel_irq_routing_entry *e;
- struct kvm_irq_routing_table *irq_rt;
- struct kvm_lapic_irq irq;
- struct kvm_vcpu *vcpu;
- struct vcpu_data vcpu_info;
- int idx, ret = 0;
-
- if (!kvm_arch_has_assigned_device(kvm) ||
- !irq_remapping_cap(IRQ_POSTING_CAP) ||
- !kvm_vcpu_apicv_active(kvm->vcpus[0]))
- return 0;
-
- idx = srcu_read_lock(&kvm->irq_srcu);
- irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
- if (guest_irq >= irq_rt->nr_rt_entries ||
- hlist_empty(&irq_rt->map[guest_irq])) {
- pr_warn_once("no route for guest_irq %u/%u (broken user space?)\n",
- guest_irq, irq_rt->nr_rt_entries);
- goto out;
- }
-
- hlist_for_each_entry(e, &irq_rt->map[guest_irq], link) {
- if (e->type != KVM_IRQ_ROUTING_MSI)
- continue;
- /*
- * VT-d PI cannot support posting multicast/broadcast
- * interrupts to a vCPU, we still use interrupt remapping
- * for these kind of interrupts.
- *
- * For lowest-priority interrupts, we only support
- * those with single CPU as the destination, e.g. user
- * configures the interrupts via /proc/irq or uses
- * irqbalance to make the interrupts single-CPU.
- *
- * We will support full lowest-priority interrupt later.
- */
-
- kvm_set_msi_irq(kvm, e, &irq);
- if (!kvm_intr_is_single_vcpu(kvm, &irq, &vcpu)) {
- /*
- * Make sure the IRTE is in remapped mode if
- * we don't handle it in posted mode.
- */
- ret = irq_set_vcpu_affinity(host_irq, NULL);
- if (ret < 0) {
- printk(KERN_INFO
- "failed to back to remapped mode, irq: %u\n",
- host_irq);
- goto out;
- }
-
- continue;
- }
-
- vcpu_info.pi_desc_addr = __pa(vcpu_to_pi_desc(vcpu));
- vcpu_info.vector = irq.vector;
-
- trace_kvm_pi_irte_update(host_irq, vcpu->vcpu_id, e->gsi,
- vcpu_info.vector, vcpu_info.pi_desc_addr, set);
-
- if (set)
- ret = irq_set_vcpu_affinity(host_irq, &vcpu_info);
- else
- ret = irq_set_vcpu_affinity(host_irq, NULL);
-
- if (ret < 0) {
- printk(KERN_INFO "%s: failed to update PI IRTE\n",
- __func__);
- goto out;
- }
- }
-
- ret = 0;
-out:
- srcu_read_unlock(&kvm->irq_srcu, idx);
- return ret;
-}
-
-static void vmx_setup_mce(struct kvm_vcpu *vcpu)
-{
- if (vcpu->arch.mcg_cap & MCG_LMCE_P)
- to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
- FEATURE_CONTROL_LMCE;
- else
- to_vmx(vcpu)->msr_ia32_feature_control_valid_bits &=
- ~FEATURE_CONTROL_LMCE;
-}
-
-static int vmx_smi_allowed(struct kvm_vcpu *vcpu)
-{
- /* we need a nested vmexit to enter SMM, postpone if run is pending */
- if (to_vmx(vcpu)->nested.nested_run_pending)
- return 0;
- return 1;
-}
-
-static int vmx_pre_enter_smm(struct kvm_vcpu *vcpu, char *smstate)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- vmx->nested.smm.guest_mode = is_guest_mode(vcpu);
- if (vmx->nested.smm.guest_mode)
- nested_vmx_vmexit(vcpu, -1, 0, 0);
-
- vmx->nested.smm.vmxon = vmx->nested.vmxon;
- vmx->nested.vmxon = false;
- vmx_clear_hlt(vcpu);
- return 0;
-}
-
-static int vmx_pre_leave_smm(struct kvm_vcpu *vcpu, u64 smbase)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int ret;
-
- if (vmx->nested.smm.vmxon) {
- vmx->nested.vmxon = true;
- vmx->nested.smm.vmxon = false;
- }
-
- if (vmx->nested.smm.guest_mode) {
- vcpu->arch.hflags &= ~HF_SMM_MASK;
- ret = enter_vmx_non_root_mode(vcpu, NULL);
- vcpu->arch.hflags |= HF_SMM_MASK;
- if (ret)
- return ret;
-
- vmx->nested.smm.guest_mode = false;
- }
- return 0;
-}
-
-static int enable_smi_window(struct kvm_vcpu *vcpu)
-{
- return 0;
-}
-
-static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
- struct kvm_nested_state __user *user_kvm_nested_state,
- u32 user_data_size)
-{
- struct vcpu_vmx *vmx;
- struct vmcs12 *vmcs12;
- struct kvm_nested_state kvm_state = {
- .flags = 0,
- .format = 0,
- .size = sizeof(kvm_state),
- .vmx.vmxon_pa = -1ull,
- .vmx.vmcs_pa = -1ull,
- };
-
- if (!vcpu)
- return kvm_state.size + 2 * VMCS12_SIZE;
-
- vmx = to_vmx(vcpu);
- vmcs12 = get_vmcs12(vcpu);
- if (nested_vmx_allowed(vcpu) &&
- (vmx->nested.vmxon || vmx->nested.smm.vmxon)) {
- kvm_state.vmx.vmxon_pa = vmx->nested.vmxon_ptr;
- kvm_state.vmx.vmcs_pa = vmx->nested.current_vmptr;
-
- if (vmx->nested.current_vmptr != -1ull) {
- kvm_state.size += VMCS12_SIZE;
-
- if (is_guest_mode(vcpu) &&
- nested_cpu_has_shadow_vmcs(vmcs12) &&
- vmcs12->vmcs_link_pointer != -1ull)
- kvm_state.size += VMCS12_SIZE;
- }
-
- if (vmx->nested.smm.vmxon)
- kvm_state.vmx.smm.flags |= KVM_STATE_NESTED_SMM_VMXON;
-
- if (vmx->nested.smm.guest_mode)
- kvm_state.vmx.smm.flags |= KVM_STATE_NESTED_SMM_GUEST_MODE;
-
- if (is_guest_mode(vcpu)) {
- kvm_state.flags |= KVM_STATE_NESTED_GUEST_MODE;
-
- if (vmx->nested.nested_run_pending)
- kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING;
- }
- }
-
- if (user_data_size < kvm_state.size)
- goto out;
-
- if (copy_to_user(user_kvm_nested_state, &kvm_state, sizeof(kvm_state)))
- return -EFAULT;
-
- if (vmx->nested.current_vmptr == -1ull)
- goto out;
-
- /*
- * When running L2, the authoritative vmcs12 state is in the
- * vmcs02. When running L1, the authoritative vmcs12 state is
- * in the shadow vmcs linked to vmcs01, unless
- * sync_shadow_vmcs is set, in which case, the authoritative
- * vmcs12 state is in the vmcs12 already.
- */
- if (is_guest_mode(vcpu))
- sync_vmcs12(vcpu, vmcs12);
- else if (enable_shadow_vmcs && !vmx->nested.sync_shadow_vmcs)
- copy_shadow_to_vmcs12(vmx);
-
- /*
- * Copy over the full allocated size of vmcs12 rather than just the size
- * of the struct.
- */
- if (copy_to_user(user_kvm_nested_state->data, vmcs12, VMCS12_SIZE))
- return -EFAULT;
-
- if (nested_cpu_has_shadow_vmcs(vmcs12) &&
- vmcs12->vmcs_link_pointer != -1ull) {
- if (copy_to_user(user_kvm_nested_state->data + VMCS12_SIZE,
- get_shadow_vmcs12(vcpu), VMCS12_SIZE))
- return -EFAULT;
- }
-
-out:
- return kvm_state.size;
-}
-
-static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
- struct kvm_nested_state __user *user_kvm_nested_state,
- struct kvm_nested_state *kvm_state)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- struct vmcs12 *vmcs12;
- u32 exit_qual;
- int ret;
-
- if (kvm_state->format != 0)
- return -EINVAL;
-
- if (!nested_vmx_allowed(vcpu))
- return kvm_state->vmx.vmxon_pa == -1ull ? 0 : -EINVAL;
-
- if (kvm_state->vmx.vmxon_pa == -1ull) {
- if (kvm_state->vmx.smm.flags)
- return -EINVAL;
-
- if (kvm_state->vmx.vmcs_pa != -1ull)
- return -EINVAL;
-
- vmx_leave_nested(vcpu);
- return 0;
- }
-
- if (!page_address_valid(vcpu, kvm_state->vmx.vmxon_pa))
- return -EINVAL;
-
- if ((kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) &&
- (kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE))
- return -EINVAL;
-
- if (kvm_state->vmx.smm.flags &
- ~(KVM_STATE_NESTED_SMM_GUEST_MODE | KVM_STATE_NESTED_SMM_VMXON))
- return -EINVAL;
-
- /*
- * SMM temporarily disables VMX, so we cannot be in guest mode,
- * nor can VMLAUNCH/VMRESUME be pending. Outside SMM, SMM flags
- * must be zero.
- */
- if (is_smm(vcpu) ? kvm_state->flags : kvm_state->vmx.smm.flags)
- return -EINVAL;
-
- if ((kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) &&
- !(kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON))
- return -EINVAL;
-
- vmx_leave_nested(vcpu);
- if (kvm_state->vmx.vmxon_pa == -1ull)
- return 0;
-
- vmx->nested.vmxon_ptr = kvm_state->vmx.vmxon_pa;
- ret = enter_vmx_operation(vcpu);
- if (ret)
- return ret;
-
- /* Empty 'VMXON' state is permitted */
- if (kvm_state->size < sizeof(*kvm_state) + sizeof(*vmcs12))
- return 0;
-
- if (kvm_state->vmx.vmcs_pa == kvm_state->vmx.vmxon_pa ||
- !page_address_valid(vcpu, kvm_state->vmx.vmcs_pa))
- return -EINVAL;
-
- set_current_vmptr(vmx, kvm_state->vmx.vmcs_pa);
-
- if (kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON) {
- vmx->nested.smm.vmxon = true;
- vmx->nested.vmxon = false;
-
- if (kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE)
- vmx->nested.smm.guest_mode = true;
- }
-
- vmcs12 = get_vmcs12(vcpu);
- if (copy_from_user(vmcs12, user_kvm_nested_state->data, sizeof(*vmcs12)))
- return -EFAULT;
-
- if (vmcs12->hdr.revision_id != VMCS12_REVISION)
- return -EINVAL;
-
- if (!(kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE))
- return 0;
-
- vmx->nested.nested_run_pending =
- !!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING);
-
- if (nested_cpu_has_shadow_vmcs(vmcs12) &&
- vmcs12->vmcs_link_pointer != -1ull) {
- struct vmcs12 *shadow_vmcs12 = get_shadow_vmcs12(vcpu);
- if (kvm_state->size < sizeof(*kvm_state) + 2 * sizeof(*vmcs12))
- return -EINVAL;
-
- if (copy_from_user(shadow_vmcs12,
- user_kvm_nested_state->data + VMCS12_SIZE,
- sizeof(*vmcs12)))
- return -EFAULT;
-
- if (shadow_vmcs12->hdr.revision_id != VMCS12_REVISION ||
- !shadow_vmcs12->hdr.shadow_vmcs)
- return -EINVAL;
- }
-
- if (check_vmentry_prereqs(vcpu, vmcs12) ||
- check_vmentry_postreqs(vcpu, vmcs12, &exit_qual))
- return -EINVAL;
-
- vmx->nested.dirty_vmcs12 = true;
- ret = enter_vmx_non_root_mode(vcpu, NULL);
- if (ret)
- return -EINVAL;
-
- return 0;
-}
-
-static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
- .cpu_has_kvm_support = cpu_has_kvm_support,
- .disabled_by_bios = vmx_disabled_by_bios,
- .hardware_setup = hardware_setup,
- .hardware_unsetup = hardware_unsetup,
- .check_processor_compatibility = vmx_check_processor_compat,
- .hardware_enable = hardware_enable,
- .hardware_disable = hardware_disable,
- .cpu_has_accelerated_tpr = report_flexpriority,
- .has_emulated_msr = vmx_has_emulated_msr,
-
- .vm_init = vmx_vm_init,
- .vm_alloc = vmx_vm_alloc,
- .vm_free = vmx_vm_free,
-
- .vcpu_create = vmx_create_vcpu,
- .vcpu_free = vmx_free_vcpu,
- .vcpu_reset = vmx_vcpu_reset,
-
- .prepare_guest_switch = vmx_prepare_switch_to_guest,
- .vcpu_load = vmx_vcpu_load,
- .vcpu_put = vmx_vcpu_put,
-
- .update_bp_intercept = update_exception_bitmap,
- .get_msr_feature = vmx_get_msr_feature,
- .get_msr = vmx_get_msr,
- .set_msr = vmx_set_msr,
- .get_segment_base = vmx_get_segment_base,
- .get_segment = vmx_get_segment,
- .set_segment = vmx_set_segment,
- .get_cpl = vmx_get_cpl,
- .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
- .decache_cr0_guest_bits = vmx_decache_cr0_guest_bits,
- .decache_cr3 = vmx_decache_cr3,
- .decache_cr4_guest_bits = vmx_decache_cr4_guest_bits,
- .set_cr0 = vmx_set_cr0,
- .set_cr3 = vmx_set_cr3,
- .set_cr4 = vmx_set_cr4,
- .set_efer = vmx_set_efer,
- .get_idt = vmx_get_idt,
- .set_idt = vmx_set_idt,
- .get_gdt = vmx_get_gdt,
- .set_gdt = vmx_set_gdt,
- .get_dr6 = vmx_get_dr6,
- .set_dr6 = vmx_set_dr6,
- .set_dr7 = vmx_set_dr7,
- .sync_dirty_debug_regs = vmx_sync_dirty_debug_regs,
- .cache_reg = vmx_cache_reg,
- .get_rflags = vmx_get_rflags,
- .set_rflags = vmx_set_rflags,
-
- .tlb_flush = vmx_flush_tlb,
- .tlb_flush_gva = vmx_flush_tlb_gva,
-
- .run = vmx_vcpu_run,
- .handle_exit = vmx_handle_exit,
- .skip_emulated_instruction = skip_emulated_instruction,
- .set_interrupt_shadow = vmx_set_interrupt_shadow,
- .get_interrupt_shadow = vmx_get_interrupt_shadow,
- .patch_hypercall = vmx_patch_hypercall,
- .set_irq = vmx_inject_irq,
- .set_nmi = vmx_inject_nmi,
- .queue_exception = vmx_queue_exception,
- .cancel_injection = vmx_cancel_injection,
- .interrupt_allowed = vmx_interrupt_allowed,
- .nmi_allowed = vmx_nmi_allowed,
- .get_nmi_mask = vmx_get_nmi_mask,
- .set_nmi_mask = vmx_set_nmi_mask,
- .enable_nmi_window = enable_nmi_window,
- .enable_irq_window = enable_irq_window,
- .update_cr8_intercept = update_cr8_intercept,
- .set_virtual_apic_mode = vmx_set_virtual_apic_mode,
- .set_apic_access_page_addr = vmx_set_apic_access_page_addr,
- .get_enable_apicv = vmx_get_enable_apicv,
- .refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
- .load_eoi_exitmap = vmx_load_eoi_exitmap,
- .apicv_post_state_restore = vmx_apicv_post_state_restore,
- .hwapic_irr_update = vmx_hwapic_irr_update,
- .hwapic_isr_update = vmx_hwapic_isr_update,
- .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
- .sync_pir_to_irr = vmx_sync_pir_to_irr,
- .deliver_posted_interrupt = vmx_deliver_posted_interrupt,
- .dy_apicv_has_pending_interrupt = vmx_dy_apicv_has_pending_interrupt,
-
- .set_tss_addr = vmx_set_tss_addr,
- .set_identity_map_addr = vmx_set_identity_map_addr,
- .get_tdp_level = get_ept_level,
- .get_mt_mask = vmx_get_mt_mask,
-
- .get_exit_info = vmx_get_exit_info,
-
- .get_lpage_level = vmx_get_lpage_level,
-
- .cpuid_update = vmx_cpuid_update,
-
- .rdtscp_supported = vmx_rdtscp_supported,
- .invpcid_supported = vmx_invpcid_supported,
-
- .set_supported_cpuid = vmx_set_supported_cpuid,
-
- .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,
-
- .read_l1_tsc_offset = vmx_read_l1_tsc_offset,
- .write_l1_tsc_offset = vmx_write_l1_tsc_offset,
-
- .set_tdp_cr3 = vmx_set_cr3,
-
- .check_intercept = vmx_check_intercept,
- .handle_external_intr = vmx_handle_external_intr,
- .mpx_supported = vmx_mpx_supported,
- .xsaves_supported = vmx_xsaves_supported,
- .umip_emulated = vmx_umip_emulated,
-
- .check_nested_events = vmx_check_nested_events,
- .request_immediate_exit = vmx_request_immediate_exit,
-
- .sched_in = vmx_sched_in,
-
- .slot_enable_log_dirty = vmx_slot_enable_log_dirty,
- .slot_disable_log_dirty = vmx_slot_disable_log_dirty,
- .flush_log_dirty = vmx_flush_log_dirty,
- .enable_log_dirty_pt_masked = vmx_enable_log_dirty_pt_masked,
- .write_log_dirty = vmx_write_pml_buffer,
-
- .pre_block = vmx_pre_block,
- .post_block = vmx_post_block,
-
- .pmu_ops = &intel_pmu_ops,
-
- .update_pi_irte = vmx_update_pi_irte,
-
-#ifdef CONFIG_X86_64
- .set_hv_timer = vmx_set_hv_timer,
- .cancel_hv_timer = vmx_cancel_hv_timer,
-#endif
-
- .setup_mce = vmx_setup_mce,
-
- .get_nested_state = vmx_get_nested_state,
- .set_nested_state = vmx_set_nested_state,
- .get_vmcs12_pages = nested_get_vmcs12_pages,
-
- .smi_allowed = vmx_smi_allowed,
- .pre_enter_smm = vmx_pre_enter_smm,
- .pre_leave_smm = vmx_pre_leave_smm,
- .enable_smi_window = enable_smi_window,
-};
-
-static void vmx_cleanup_l1d_flush(void)
-{
- if (vmx_l1d_flush_pages) {
- free_pages((unsigned long)vmx_l1d_flush_pages, L1D_CACHE_ORDER);
- vmx_l1d_flush_pages = NULL;
- }
- /* Restore state so sysfs ignores VMX */
- l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO;
-}
-
-static void vmx_exit(void)
-{
-#ifdef CONFIG_KEXEC_CORE
- RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL);
- synchronize_rcu();
-#endif
-
- kvm_exit();
-
-#if IS_ENABLED(CONFIG_HYPERV)
- if (static_branch_unlikely(&enable_evmcs)) {
- int cpu;
- struct hv_vp_assist_page *vp_ap;
- /*
- * Reset everything to support using non-enlightened VMCS
- * access later (e.g. when we reload the module with
- * enlightened_vmcs=0)
- */
- for_each_online_cpu(cpu) {
- vp_ap = hv_get_vp_assist_page(cpu);
-
- if (!vp_ap)
- continue;
-
- vp_ap->current_nested_vmcs = 0;
- vp_ap->enlighten_vmentry = 0;
- }
-
- static_branch_disable(&enable_evmcs);
- }
-#endif
- vmx_cleanup_l1d_flush();
-}
-module_exit(vmx_exit);
-
-static int __init vmx_init(void)
-{
- int r, cpu;
-
-#if IS_ENABLED(CONFIG_HYPERV)
- /*
- * Enlightened VMCS usage should be recommended and the host needs
- * to support eVMCS v1 or above. We can also disable eVMCS support
- * with module parameter.
- */
- if (enlightened_vmcs &&
- ms_hyperv.hints & HV_X64_ENLIGHTENED_VMCS_RECOMMENDED &&
- (ms_hyperv.nested_features & HV_X64_ENLIGHTENED_VMCS_VERSION) >=
- KVM_EVMCS_VERSION) {
- int cpu;
-
- /* Check that we have assist pages on all online CPUs */
- for_each_online_cpu(cpu) {
- if (!hv_get_vp_assist_page(cpu)) {
- enlightened_vmcs = false;
- break;
- }
- }
-
- if (enlightened_vmcs) {
- pr_info("KVM: vmx: using Hyper-V Enlightened VMCS\n");
- static_branch_enable(&enable_evmcs);
- }
- } else {
- enlightened_vmcs = false;
- }
-#endif
-
- r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx),
- __alignof__(struct vcpu_vmx), THIS_MODULE);
- if (r)
- return r;
-
- /*
- * Must be called after kvm_init() so enable_ept is properly set
- * up. Hand the parameter mitigation value in which was stored in
- * the pre module init parser. If no parameter was given, it will
- * contain 'auto' which will be turned into the default 'cond'
- * mitigation mode.
- */
- if (boot_cpu_has(X86_BUG_L1TF)) {
- r = vmx_setup_l1d_flush(vmentry_l1d_flush_param);
- if (r) {
- vmx_exit();
- return r;
- }
- }
-
- vmx_setup_fb_clear_ctrl();
-
- for_each_possible_cpu(cpu) {
- INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
-
- INIT_LIST_HEAD(&per_cpu(blocked_vcpu_on_cpu, cpu));
- spin_lock_init(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
- }
-
-#ifdef CONFIG_KEXEC_CORE
- rcu_assign_pointer(crash_vmclear_loaded_vmcss,
- crash_vmclear_local_loaded_vmcss);
-#endif
- vmx_check_vmcs12_offsets();
-
- return 0;
-}
-module_init(vmx_init);
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
new file mode 100644
index 000000000000..611f9e60f815
--- /dev/null
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -0,0 +1,374 @@
+/*
+ * KVM PMU support for Intel CPUs
+ *
+ * Copyright 2011 Red Hat, Inc. and/or its affiliates.
+ *
+ * Authors:
+ * Avi Kivity <avi@redhat.com>
+ * Gleb Natapov <gleb@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include <linux/types.h>
+#include <linux/kvm_host.h>
+#include <linux/perf_event.h>
+#include <asm/perf_event.h>
+#include "x86.h"
+#include "cpuid.h"
+#include "lapic.h"
+#include "pmu.h"
+
+static struct kvm_event_hw_type_mapping intel_arch_events[] = {
+ /* Index must match CPUID 0x0A.EBX bit vector */
+ [0] = { 0x3c, 0x00, PERF_COUNT_HW_CPU_CYCLES },
+ [1] = { 0xc0, 0x00, PERF_COUNT_HW_INSTRUCTIONS },
+ [2] = { 0x3c, 0x01, PERF_COUNT_HW_BUS_CYCLES },
+ [3] = { 0x2e, 0x4f, PERF_COUNT_HW_CACHE_REFERENCES },
+ [4] = { 0x2e, 0x41, PERF_COUNT_HW_CACHE_MISSES },
+ [5] = { 0xc4, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
+ [6] = { 0xc5, 0x00, PERF_COUNT_HW_BRANCH_MISSES },
+ [7] = { 0x00, 0x03, PERF_COUNT_HW_REF_CPU_CYCLES },
+};
+
+/* mapping between fixed pmc index and intel_arch_events array */
+static int fixed_pmc_events[] = {1, 0, 7};
+
+static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
+{
+ int i;
+
+ for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
+ u8 new_ctrl = fixed_ctrl_field(data, i);
+ u8 old_ctrl = fixed_ctrl_field(pmu->fixed_ctr_ctrl, i);
+ struct kvm_pmc *pmc;
+
+ pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
+
+ if (old_ctrl == new_ctrl)
+ continue;
+
+ reprogram_fixed_counter(pmc, new_ctrl, i);
+ }
+
+ pmu->fixed_ctr_ctrl = data;
+}
+
+/* function is called when global control register has been updated. */
+static void global_ctrl_changed(struct kvm_pmu *pmu, u64 data)
+{
+ int bit;
+ u64 diff = pmu->global_ctrl ^ data;
+
+ pmu->global_ctrl = data;
+
+ for_each_set_bit(bit, (unsigned long *)&diff, X86_PMC_IDX_MAX)
+ reprogram_counter(pmu, bit);
+}
+
+static unsigned intel_find_arch_event(struct kvm_pmu *pmu,
+ u8 event_select,
+ u8 unit_mask)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(intel_arch_events); i++)
+ if (intel_arch_events[i].eventsel == event_select
+ && intel_arch_events[i].unit_mask == unit_mask
+ && (pmu->available_event_types & (1 << i)))
+ break;
+
+ if (i == ARRAY_SIZE(intel_arch_events))
+ return PERF_COUNT_HW_MAX;
+
+ return intel_arch_events[i].event_type;
+}
+
+static unsigned intel_find_fixed_event(int idx)
+{
+ u32 event;
+ size_t size = ARRAY_SIZE(fixed_pmc_events);
+
+ if (idx >= size)
+ return PERF_COUNT_HW_MAX;
+
+ event = fixed_pmc_events[array_index_nospec(idx, size)];
+ return intel_arch_events[event].event_type;
+}
+
+/* check if a PMC is enabled by comparing it with globl_ctrl bits. */
+static bool intel_pmc_is_enabled(struct kvm_pmc *pmc)
+{
+ struct kvm_pmu *pmu = pmc_to_pmu(pmc);
+
+ return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl);
+}
+
+static struct kvm_pmc *intel_pmc_idx_to_pmc(struct kvm_pmu *pmu, int pmc_idx)
+{
+ if (pmc_idx < INTEL_PMC_IDX_FIXED)
+ return get_gp_pmc(pmu, MSR_P6_EVNTSEL0 + pmc_idx,
+ MSR_P6_EVNTSEL0);
+ else {
+ u32 idx = pmc_idx - INTEL_PMC_IDX_FIXED;
+
+ return get_fixed_pmc(pmu, idx + MSR_CORE_PERF_FIXED_CTR0);
+ }
+}
+
+/* returns 0 if idx's corresponding MSR exists; otherwise returns 1. */
+static int intel_is_valid_msr_idx(struct kvm_vcpu *vcpu, unsigned idx)
+{
+ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+ bool fixed = idx & (1u << 30);
+
+ idx &= ~(3u << 30);
+
+ return (!fixed && idx >= pmu->nr_arch_gp_counters) ||
+ (fixed && idx >= pmu->nr_arch_fixed_counters);
+}
+
+static struct kvm_pmc *intel_msr_idx_to_pmc(struct kvm_vcpu *vcpu,
+ unsigned idx, u64 *mask)
+{
+ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+ bool fixed = idx & (1u << 30);
+ struct kvm_pmc *counters;
+ unsigned int num_counters;
+
+ idx &= ~(3u << 30);
+ if (fixed) {
+ counters = pmu->fixed_counters;
+ num_counters = pmu->nr_arch_fixed_counters;
+ } else {
+ counters = pmu->gp_counters;
+ num_counters = pmu->nr_arch_gp_counters;
+ }
+ if (idx >= num_counters)
+ return NULL;
+ *mask &= pmu->counter_bitmask[fixed ? KVM_PMC_FIXED : KVM_PMC_GP];
+ return &counters[array_index_nospec(idx, num_counters)];
+}
+
+static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
+{
+ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+ int ret;
+
+ switch (msr) {
+ case MSR_CORE_PERF_FIXED_CTR_CTRL:
+ case MSR_CORE_PERF_GLOBAL_STATUS:
+ case MSR_CORE_PERF_GLOBAL_CTRL:
+ case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+ ret = pmu->version > 1;
+ break;
+ default:
+ ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) ||
+ get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) ||
+ get_fixed_pmc(pmu, msr);
+ break;
+ }
+
+ return ret;
+}
+
+static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *data)
+{
+ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+ struct kvm_pmc *pmc;
+
+ switch (msr) {
+ case MSR_CORE_PERF_FIXED_CTR_CTRL:
+ *data = pmu->fixed_ctr_ctrl;
+ return 0;
+ case MSR_CORE_PERF_GLOBAL_STATUS:
+ *data = pmu->global_status;
+ return 0;
+ case MSR_CORE_PERF_GLOBAL_CTRL:
+ *data = pmu->global_ctrl;
+ return 0;
+ case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+ *data = pmu->global_ovf_ctrl;
+ return 0;
+ default:
+ if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0))) {
+ u64 val = pmc_read_counter(pmc);
+ *data = val & pmu->counter_bitmask[KVM_PMC_GP];
+ return 0;
+ } else if ((pmc = get_fixed_pmc(pmu, msr))) {
+ u64 val = pmc_read_counter(pmc);
+ *data = val & pmu->counter_bitmask[KVM_PMC_FIXED];
+ return 0;
+ } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) {
+ *data = pmc->eventsel;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+{
+ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+ struct kvm_pmc *pmc;
+ u32 msr = msr_info->index;
+ u64 data = msr_info->data;
+
+ switch (msr) {
+ case MSR_CORE_PERF_FIXED_CTR_CTRL:
+ if (pmu->fixed_ctr_ctrl == data)
+ return 0;
+ if (!(data & 0xfffffffffffff444ull)) {
+ reprogram_fixed_counters(pmu, data);
+ return 0;
+ }
+ break;
+ case MSR_CORE_PERF_GLOBAL_STATUS:
+ if (msr_info->host_initiated) {
+ pmu->global_status = data;
+ return 0;
+ }
+ break; /* RO MSR */
+ case MSR_CORE_PERF_GLOBAL_CTRL:
+ if (pmu->global_ctrl == data)
+ return 0;
+ if (!(data & pmu->global_ctrl_mask)) {
+ global_ctrl_changed(pmu, data);
+ return 0;
+ }
+ break;
+ case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+ if (!(data & (pmu->global_ctrl_mask & ~(3ull<<62)))) {
+ if (!msr_info->host_initiated)
+ pmu->global_status &= ~data;
+ pmu->global_ovf_ctrl = data;
+ return 0;
+ }
+ break;
+ default:
+ if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0))) {
+ if (msr_info->host_initiated)
+ pmc->counter = data;
+ else
+ pmc->counter = (s32)data;
+ return 0;
+ } else if ((pmc = get_fixed_pmc(pmu, msr))) {
+ pmc->counter = data;
+ return 0;
+ } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) {
+ if (data == pmc->eventsel)
+ return 0;
+ if (!(data & pmu->reserved_bits)) {
+ reprogram_gp_counter(pmc, data);
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+{
+ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+ struct kvm_cpuid_entry2 *entry;
+ union cpuid10_eax eax;
+ union cpuid10_edx edx;
+
+ pmu->nr_arch_gp_counters = 0;
+ pmu->nr_arch_fixed_counters = 0;
+ pmu->counter_bitmask[KVM_PMC_GP] = 0;
+ pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
+ pmu->version = 0;
+ pmu->reserved_bits = 0xffffffff00200000ull;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+ if (!entry)
+ return;
+ eax.full = entry->eax;
+ edx.full = entry->edx;
+
+ pmu->version = eax.split.version_id;
+ if (!pmu->version)
+ return;
+
+ pmu->nr_arch_gp_counters = min_t(int, eax.split.num_counters,
+ INTEL_PMC_MAX_GENERIC);
+ pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << eax.split.bit_width) - 1;
+ pmu->available_event_types = ~entry->ebx &
+ ((1ull << eax.split.mask_length) - 1);
+
+ if (pmu->version == 1) {
+ pmu->nr_arch_fixed_counters = 0;
+ } else {
+ pmu->nr_arch_fixed_counters =
+ min_t(int, edx.split.num_counters_fixed,
+ INTEL_PMC_MAX_FIXED);
+ pmu->counter_bitmask[KVM_PMC_FIXED] =
+ ((u64)1 << edx.split.bit_width_fixed) - 1;
+ }
+
+ pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) |
+ (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
+ pmu->global_ctrl_mask = ~pmu->global_ctrl;
+
+ entry = kvm_find_cpuid_entry(vcpu, 7, 0);
+ if (entry &&
+ (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
+ (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM)))
+ pmu->reserved_bits ^= HSW_IN_TX|HSW_IN_TX_CHECKPOINTED;
+}
+
+static void intel_pmu_init(struct kvm_vcpu *vcpu)
+{
+ int i;
+ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+
+ for (i = 0; i < INTEL_PMC_MAX_GENERIC; i++) {
+ pmu->gp_counters[i].type = KVM_PMC_GP;
+ pmu->gp_counters[i].vcpu = vcpu;
+ pmu->gp_counters[i].idx = i;
+ }
+
+ for (i = 0; i < INTEL_PMC_MAX_FIXED; i++) {
+ pmu->fixed_counters[i].type = KVM_PMC_FIXED;
+ pmu->fixed_counters[i].vcpu = vcpu;
+ pmu->fixed_counters[i].idx = i + INTEL_PMC_IDX_FIXED;
+ }
+}
+
+static void intel_pmu_reset(struct kvm_vcpu *vcpu)
+{
+ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+ int i;
+
+ for (i = 0; i < INTEL_PMC_MAX_GENERIC; i++) {
+ struct kvm_pmc *pmc = &pmu->gp_counters[i];
+
+ pmc_stop_counter(pmc);
+ pmc->counter = pmc->eventsel = 0;
+ }
+
+ for (i = 0; i < INTEL_PMC_MAX_FIXED; i++)
+ pmc_stop_counter(&pmu->fixed_counters[i]);
+
+ pmu->fixed_ctr_ctrl = pmu->global_ctrl = pmu->global_status =
+ pmu->global_ovf_ctrl = 0;
+}
+
+struct kvm_pmu_ops intel_pmu_ops = {
+ .find_arch_event = intel_find_arch_event,
+ .find_fixed_event = intel_find_fixed_event,
+ .pmc_is_enabled = intel_pmc_is_enabled,
+ .pmc_idx_to_pmc = intel_pmc_idx_to_pmc,
+ .msr_idx_to_pmc = intel_msr_idx_to_pmc,
+ .is_valid_msr_idx = intel_is_valid_msr_idx,
+ .is_valid_msr = intel_is_valid_msr,
+ .get_msr = intel_pmu_get_msr,
+ .set_msr = intel_pmu_set_msr,
+ .refresh = intel_pmu_refresh,
+ .init = intel_pmu_init,
+ .reset = intel_pmu_reset,
+};
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
new file mode 100644
index 000000000000..ec821a5d131a
--- /dev/null
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -0,0 +1,14764 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ * Copyright 2010 Red Hat, Inc. and/or its affiliates.
+ *
+ * Authors:
+ * Avi Kivity <avi@qumranet.com>
+ * Yaniv Kamay <yaniv@qumranet.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "irq.h"
+#include "mmu.h"
+#include "cpuid.h"
+#include "lapic.h"
+
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+#include <linux/sched/smt.h>
+#include <linux/moduleparam.h>
+#include <linux/mod_devicetable.h>
+#include <linux/trace_events.h>
+#include <linux/slab.h>
+#include <linux/tboot.h>
+#include <linux/hrtimer.h>
+#include <linux/frame.h>
+#include <linux/nospec.h>
+#include "kvm_cache_regs.h"
+#include "x86.h"
+
+#include <asm/asm.h>
+#include <asm/cpu.h>
+#include <asm/cpu_device_id.h>
+#include <asm/io.h>
+#include <asm/desc.h>
+#include <asm/vmx.h>
+#include <asm/virtext.h>
+#include <asm/mce.h>
+#include <asm/fpu/internal.h>
+#include <asm/perf_event.h>
+#include <asm/debugreg.h>
+#include <asm/kexec.h>
+#include <asm/apic.h>
+#include <asm/irq_remapping.h>
+#include <asm/mmu_context.h>
+#include <asm/spec-ctrl.h>
+#include <asm/mshyperv.h>
+
+#include "trace.h"
+#include "pmu.h"
+#include "vmx_evmcs.h"
+
+#define __ex(x) __kvm_handle_fault_on_reboot(x)
+#define __ex_clear(x, reg) \
+ ____kvm_handle_fault_on_reboot(x, "xor " reg " , " reg)
+
+MODULE_AUTHOR("Qumranet");
+MODULE_LICENSE("GPL");
+
+static const struct x86_cpu_id vmx_cpu_id[] = {
+ X86_FEATURE_MATCH(X86_FEATURE_VMX),
+ {}
+};
+MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);
+
+static bool __read_mostly enable_vpid = 1;
+module_param_named(vpid, enable_vpid, bool, 0444);
+
+static bool __read_mostly enable_vnmi = 1;
+module_param_named(vnmi, enable_vnmi, bool, S_IRUGO);
+
+static bool __read_mostly flexpriority_enabled = 1;
+module_param_named(flexpriority, flexpriority_enabled, bool, S_IRUGO);
+
+static bool __read_mostly enable_ept = 1;
+module_param_named(ept, enable_ept, bool, S_IRUGO);
+
+static bool __read_mostly enable_unrestricted_guest = 1;
+module_param_named(unrestricted_guest,
+ enable_unrestricted_guest, bool, S_IRUGO);
+
+static bool __read_mostly enable_ept_ad_bits = 1;
+module_param_named(eptad, enable_ept_ad_bits, bool, S_IRUGO);
+
+static bool __read_mostly emulate_invalid_guest_state = true;
+module_param(emulate_invalid_guest_state, bool, S_IRUGO);
+
+static bool __read_mostly fasteoi = 1;
+module_param(fasteoi, bool, S_IRUGO);
+
+static bool __read_mostly enable_apicv = 1;
+module_param(enable_apicv, bool, S_IRUGO);
+
+static bool __read_mostly enable_shadow_vmcs = 1;
+module_param_named(enable_shadow_vmcs, enable_shadow_vmcs, bool, S_IRUGO);
+/*
+ * If nested=1, nested virtualization is supported, i.e., guests may use
+ * VMX and be a hypervisor for its own guests. If nested=0, guests may not
+ * use VMX instructions.
+ */
+static bool __read_mostly nested = 0;
+module_param(nested, bool, S_IRUGO);
+
+static u64 __read_mostly host_xss;
+
+static bool __read_mostly enable_pml = 1;
+module_param_named(pml, enable_pml, bool, S_IRUGO);
+
+#define MSR_TYPE_R 1
+#define MSR_TYPE_W 2
+#define MSR_TYPE_RW 3
+
+#define MSR_BITMAP_MODE_X2APIC 1
+#define MSR_BITMAP_MODE_X2APIC_APICV 2
+
+#define KVM_VMX_TSC_MULTIPLIER_MAX 0xffffffffffffffffULL
+
+/* Guest_tsc -> host_tsc conversion requires 64-bit division. */
+static int __read_mostly cpu_preemption_timer_multi;
+static bool __read_mostly enable_preemption_timer = 1;
+#ifdef CONFIG_X86_64
+module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
+#endif
+
+#define KVM_GUEST_CR0_MASK (X86_CR0_NW | X86_CR0_CD)
+#define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR0_NE
+#define KVM_VM_CR0_ALWAYS_ON \
+ (KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | \
+ X86_CR0_WP | X86_CR0_PG | X86_CR0_PE)
+#define KVM_CR4_GUEST_OWNED_BITS \
+ (X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR \
+ | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_TSD)
+
+#define KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR4_VMXE
+#define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)
+#define KVM_RMODE_VM_CR4_ALWAYS_ON (X86_CR4_VME | X86_CR4_PAE | X86_CR4_VMXE)
+
+#define RMODE_GUEST_OWNED_EFLAGS_BITS (~(X86_EFLAGS_IOPL | X86_EFLAGS_VM))
+
+#define VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE 5
+
+/*
+ * Hyper-V requires all of these, so mark them as supported even though
+ * they are just treated the same as all-context.
+ */
+#define VMX_VPID_EXTENT_SUPPORTED_MASK \
+ (VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT | \
+ VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT | \
+ VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT | \
+ VMX_VPID_EXTENT_SINGLE_NON_GLOBAL_BIT)
+
+/*
+ * These 2 parameters are used to config the controls for Pause-Loop Exiting:
+ * ple_gap: upper bound on the amount of time between two successive
+ * executions of PAUSE in a loop. Also indicate if ple enabled.
+ * According to test, this time is usually smaller than 128 cycles.
+ * ple_window: upper bound on the amount of time a guest is allowed to execute
+ * in a PAUSE loop. Tests indicate that most spinlocks are held for
+ * less than 2^12 cycles
+ * Time is measured based on a counter that runs at the same rate as the TSC,
+ * refer SDM volume 3b section 21.6.13 & 22.1.3.
+ */
+static unsigned int ple_gap = KVM_DEFAULT_PLE_GAP;
+module_param(ple_gap, uint, 0444);
+
+static unsigned int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
+module_param(ple_window, uint, 0444);
+
+/* Default doubles per-vcpu window every exit. */
+static unsigned int ple_window_grow = KVM_DEFAULT_PLE_WINDOW_GROW;
+module_param(ple_window_grow, uint, 0444);
+
+/* Default resets per-vcpu window every exit to ple_window. */
+static unsigned int ple_window_shrink = KVM_DEFAULT_PLE_WINDOW_SHRINK;
+module_param(ple_window_shrink, uint, 0444);
+
+/* Default is to compute the maximum so we can never overflow. */
+static unsigned int ple_window_max = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
+module_param(ple_window_max, uint, 0444);
+
+extern const ulong vmx_return;
+
+static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush);
+static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond);
+static DEFINE_MUTEX(vmx_l1d_flush_mutex);
+
+/* Storage for pre module init parameter parsing */
+static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush_param = VMENTER_L1D_FLUSH_AUTO;
+
+static const struct {
+ const char *option;
+ bool for_parse;
+} vmentry_l1d_param[] = {
+ [VMENTER_L1D_FLUSH_AUTO] = {"auto", true},
+ [VMENTER_L1D_FLUSH_NEVER] = {"never", true},
+ [VMENTER_L1D_FLUSH_COND] = {"cond", true},
+ [VMENTER_L1D_FLUSH_ALWAYS] = {"always", true},
+ [VMENTER_L1D_FLUSH_EPT_DISABLED] = {"EPT disabled", false},
+ [VMENTER_L1D_FLUSH_NOT_REQUIRED] = {"not required", false},
+};
+
+#define L1D_CACHE_ORDER 4
+static void *vmx_l1d_flush_pages;
+
+/* Control for disabling CPU Fill buffer clear */
+static bool __read_mostly vmx_fb_clear_ctrl_available;
+
+static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
+{
+ struct page *page;
+ unsigned int i;
+
+ if (!enable_ept) {
+ l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED;
+ return 0;
+ }
+
+ if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) {
+ u64 msr;
+
+ rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr);
+ if (msr & ARCH_CAP_SKIP_VMENTRY_L1DFLUSH) {
+ l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_NOT_REQUIRED;
+ return 0;
+ }
+ }
+
+ /* If set to auto use the default l1tf mitigation method */
+ if (l1tf == VMENTER_L1D_FLUSH_AUTO) {
+ switch (l1tf_mitigation) {
+ case L1TF_MITIGATION_OFF:
+ l1tf = VMENTER_L1D_FLUSH_NEVER;
+ break;
+ case L1TF_MITIGATION_FLUSH_NOWARN:
+ case L1TF_MITIGATION_FLUSH:
+ case L1TF_MITIGATION_FLUSH_NOSMT:
+ l1tf = VMENTER_L1D_FLUSH_COND;
+ break;
+ case L1TF_MITIGATION_FULL:
+ case L1TF_MITIGATION_FULL_FORCE:
+ l1tf = VMENTER_L1D_FLUSH_ALWAYS;
+ break;
+ }
+ } else if (l1tf_mitigation == L1TF_MITIGATION_FULL_FORCE) {
+ l1tf = VMENTER_L1D_FLUSH_ALWAYS;
+ }
+
+ if (l1tf != VMENTER_L1D_FLUSH_NEVER && !vmx_l1d_flush_pages &&
+ !boot_cpu_has(X86_FEATURE_FLUSH_L1D)) {
+ page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER);
+ if (!page)
+ return -ENOMEM;
+ vmx_l1d_flush_pages = page_address(page);
+
+ /*
+ * Initialize each page with a different pattern in
+ * order to protect against KSM in the nested
+ * virtualization case.
+ */
+ for (i = 0; i < 1u << L1D_CACHE_ORDER; ++i) {
+ memset(vmx_l1d_flush_pages + i * PAGE_SIZE, i + 1,
+ PAGE_SIZE);
+ }
+ }
+
+ l1tf_vmx_mitigation = l1tf;
+
+ if (l1tf != VMENTER_L1D_FLUSH_NEVER)
+ static_branch_enable(&vmx_l1d_should_flush);
+ else
+ static_branch_disable(&vmx_l1d_should_flush);
+
+ if (l1tf == VMENTER_L1D_FLUSH_COND)
+ static_branch_enable(&vmx_l1d_flush_cond);
+ else
+ static_branch_disable(&vmx_l1d_flush_cond);
+ return 0;
+}
+
+static int vmentry_l1d_flush_parse(const char *s)
+{
+ unsigned int i;
+
+ if (s) {
+ for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) {
+ if (vmentry_l1d_param[i].for_parse &&
+ sysfs_streq(s, vmentry_l1d_param[i].option))
+ return i;
+ }
+ }
+ return -EINVAL;
+}
+
+static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp)
+{
+ int l1tf, ret;
+
+ l1tf = vmentry_l1d_flush_parse(s);
+ if (l1tf < 0)
+ return l1tf;
+
+ if (!boot_cpu_has(X86_BUG_L1TF))
+ return 0;
+
+ /*
+ * Has vmx_init() run already? If not then this is the pre init
+ * parameter parsing. In that case just store the value and let
+ * vmx_init() do the proper setup after enable_ept has been
+ * established.
+ */
+ if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO) {
+ vmentry_l1d_flush_param = l1tf;
+ return 0;
+ }
+
+ mutex_lock(&vmx_l1d_flush_mutex);
+ ret = vmx_setup_l1d_flush(l1tf);
+ mutex_unlock(&vmx_l1d_flush_mutex);
+ return ret;
+}
+
+static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp)
+{
+ if (WARN_ON_ONCE(l1tf_vmx_mitigation >= ARRAY_SIZE(vmentry_l1d_param)))
+ return sprintf(s, "???\n");
+
+ return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option);
+}
+
+static const struct kernel_param_ops vmentry_l1d_flush_ops = {
+ .set = vmentry_l1d_flush_set,
+ .get = vmentry_l1d_flush_get,
+};
+module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, NULL, 0644);
+
+enum ept_pointers_status {
+ EPT_POINTERS_CHECK = 0,
+ EPT_POINTERS_MATCH = 1,
+ EPT_POINTERS_MISMATCH = 2
+};
+
+struct kvm_vmx {
+ struct kvm kvm;
+
+ unsigned int tss_addr;
+ bool ept_identity_pagetable_done;
+ gpa_t ept_identity_map_addr;
+
+ enum ept_pointers_status ept_pointers_match;
+ spinlock_t ept_pointer_lock;
+};
+
+#define NR_AUTOLOAD_MSRS 8
+
+struct vmcs_hdr {
+ u32 revision_id:31;
+ u32 shadow_vmcs:1;
+};
+
+struct vmcs {
+ struct vmcs_hdr hdr;
+ u32 abort;
+ char data[0];
+};
+
+/*
+ * vmcs_host_state tracks registers that are loaded from the VMCS on VMEXIT
+ * and whose values change infrequently, but are not constant. I.e. this is
+ * used as a write-through cache of the corresponding VMCS fields.
+ */
+struct vmcs_host_state {
+ unsigned long cr3; /* May not match real cr3 */
+ unsigned long cr4; /* May not match real cr4 */
+ unsigned long gs_base;
+ unsigned long fs_base;
+
+ u16 fs_sel, gs_sel, ldt_sel;
+#ifdef CONFIG_X86_64
+ u16 ds_sel, es_sel;
+#endif
+};
+
+/*
+ * Track a VMCS that may be loaded on a certain CPU. If it is (cpu!=-1), also
+ * remember whether it was VMLAUNCHed, and maintain a linked list of all VMCSs
+ * loaded on this CPU (so we can clear them if the CPU goes down).
+ */
+struct loaded_vmcs {
+ struct vmcs *vmcs;
+ struct vmcs *shadow_vmcs;
+ int cpu;
+ bool launched;
+ bool nmi_known_unmasked;
+ bool hv_timer_armed;
+ /* Support for vnmi-less CPUs */
+ int soft_vnmi_blocked;
+ ktime_t entry_time;
+ s64 vnmi_blocked_time;
+ unsigned long *msr_bitmap;
+ struct list_head loaded_vmcss_on_cpu_link;
+ struct vmcs_host_state host_state;
+};
+
+struct shared_msr_entry {
+ unsigned index;
+ u64 data;
+ u64 mask;
+};
+
+/*
+ * struct vmcs12 describes the state that our guest hypervisor (L1) keeps for a
+ * single nested guest (L2), hence the name vmcs12. Any VMX implementation has
+ * a VMCS structure, and vmcs12 is our emulated VMX's VMCS. This structure is
+ * stored in guest memory specified by VMPTRLD, but is opaque to the guest,
+ * which must access it using VMREAD/VMWRITE/VMCLEAR instructions.
+ * More than one of these structures may exist, if L1 runs multiple L2 guests.
+ * nested_vmx_run() will use the data here to build the vmcs02: a VMCS for the
+ * underlying hardware which will be used to run L2.
+ * This structure is packed to ensure that its layout is identical across
+ * machines (necessary for live migration).
+ *
+ * IMPORTANT: Changing the layout of existing fields in this structure
+ * will break save/restore compatibility with older kvm releases. When
+ * adding new fields, either use space in the reserved padding* arrays
+ * or add the new fields to the end of the structure.
+ */
+typedef u64 natural_width;
+struct __packed vmcs12 {
+ /* According to the Intel spec, a VMCS region must start with the
+ * following two fields. Then follow implementation-specific data.
+ */
+ struct vmcs_hdr hdr;
+ u32 abort;
+
+ u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
+ u32 padding[7]; /* room for future expansion */
+
+ u64 io_bitmap_a;
+ u64 io_bitmap_b;
+ u64 msr_bitmap;
+ u64 vm_exit_msr_store_addr;
+ u64 vm_exit_msr_load_addr;
+ u64 vm_entry_msr_load_addr;
+ u64 tsc_offset;
+ u64 virtual_apic_page_addr;
+ u64 apic_access_addr;
+ u64 posted_intr_desc_addr;
+ u64 ept_pointer;
+ u64 eoi_exit_bitmap0;
+ u64 eoi_exit_bitmap1;
+ u64 eoi_exit_bitmap2;
+ u64 eoi_exit_bitmap3;
+ u64 xss_exit_bitmap;
+ u64 guest_physical_address;
+ u64 vmcs_link_pointer;
+ u64 guest_ia32_debugctl;
+ u64 guest_ia32_pat;
+ u64 guest_ia32_efer;
+ u64 guest_ia32_perf_global_ctrl;
+ u64 guest_pdptr0;
+ u64 guest_pdptr1;
+ u64 guest_pdptr2;
+ u64 guest_pdptr3;
+ u64 guest_bndcfgs;
+ u64 host_ia32_pat;
+ u64 host_ia32_efer;
+ u64 host_ia32_perf_global_ctrl;
+ u64 vmread_bitmap;
+ u64 vmwrite_bitmap;
+ u64 vm_function_control;
+ u64 eptp_list_address;
+ u64 pml_address;
+ u64 padding64[3]; /* room for future expansion */
+ /*
+ * To allow migration of L1 (complete with its L2 guests) between
+ * machines of different natural widths (32 or 64 bit), we cannot have
+ * unsigned long fields with no explict size. We use u64 (aliased
+ * natural_width) instead. Luckily, x86 is little-endian.
+ */
+ natural_width cr0_guest_host_mask;
+ natural_width cr4_guest_host_mask;
+ natural_width cr0_read_shadow;
+ natural_width cr4_read_shadow;
+ natural_width cr3_target_value0;
+ natural_width cr3_target_value1;
+ natural_width cr3_target_value2;
+ natural_width cr3_target_value3;
+ natural_width exit_qualification;
+ natural_width guest_linear_address;
+ natural_width guest_cr0;
+ natural_width guest_cr3;
+ natural_width guest_cr4;
+ natural_width guest_es_base;
+ natural_width guest_cs_base;
+ natural_width guest_ss_base;
+ natural_width guest_ds_base;
+ natural_width guest_fs_base;
+ natural_width guest_gs_base;
+ natural_width guest_ldtr_base;
+ natural_width guest_tr_base;
+ natural_width guest_gdtr_base;
+ natural_width guest_idtr_base;
+ natural_width guest_dr7;
+ natural_width guest_rsp;
+ natural_width guest_rip;
+ natural_width guest_rflags;
+ natural_width guest_pending_dbg_exceptions;
+ natural_width guest_sysenter_esp;
+ natural_width guest_sysenter_eip;
+ natural_width host_cr0;
+ natural_width host_cr3;
+ natural_width host_cr4;
+ natural_width host_fs_base;
+ natural_width host_gs_base;
+ natural_width host_tr_base;
+ natural_width host_gdtr_base;
+ natural_width host_idtr_base;
+ natural_width host_ia32_sysenter_esp;
+ natural_width host_ia32_sysenter_eip;
+ natural_width host_rsp;
+ natural_width host_rip;
+ natural_width paddingl[8]; /* room for future expansion */
+ u32 pin_based_vm_exec_control;
+ u32 cpu_based_vm_exec_control;
+ u32 exception_bitmap;
+ u32 page_fault_error_code_mask;
+ u32 page_fault_error_code_match;
+ u32 cr3_target_count;
+ u32 vm_exit_controls;
+ u32 vm_exit_msr_store_count;
+ u32 vm_exit_msr_load_count;
+ u32 vm_entry_controls;
+ u32 vm_entry_msr_load_count;
+ u32 vm_entry_intr_info_field;
+ u32 vm_entry_exception_error_code;
+ u32 vm_entry_instruction_len;
+ u32 tpr_threshold;
+ u32 secondary_vm_exec_control;
+ u32 vm_instruction_error;
+ u32 vm_exit_reason;
+ u32 vm_exit_intr_info;
+ u32 vm_exit_intr_error_code;
+ u32 idt_vectoring_info_field;
+ u32 idt_vectoring_error_code;
+ u32 vm_exit_instruction_len;
+ u32 vmx_instruction_info;
+ u32 guest_es_limit;
+ u32 guest_cs_limit;
+ u32 guest_ss_limit;
+ u32 guest_ds_limit;
+ u32 guest_fs_limit;
+ u32 guest_gs_limit;
+ u32 guest_ldtr_limit;
+ u32 guest_tr_limit;
+ u32 guest_gdtr_limit;
+ u32 guest_idtr_limit;
+ u32 guest_es_ar_bytes;
+ u32 guest_cs_ar_bytes;
+ u32 guest_ss_ar_bytes;
+ u32 guest_ds_ar_bytes;
+ u32 guest_fs_ar_bytes;
+ u32 guest_gs_ar_bytes;
+ u32 guest_ldtr_ar_bytes;
+ u32 guest_tr_ar_bytes;
+ u32 guest_interruptibility_info;
+ u32 guest_activity_state;
+ u32 guest_sysenter_cs;
+ u32 host_ia32_sysenter_cs;
+ u32 vmx_preemption_timer_value;
+ u32 padding32[7]; /* room for future expansion */
+ u16 virtual_processor_id;
+ u16 posted_intr_nv;
+ u16 guest_es_selector;
+ u16 guest_cs_selector;
+ u16 guest_ss_selector;
+ u16 guest_ds_selector;
+ u16 guest_fs_selector;
+ u16 guest_gs_selector;
+ u16 guest_ldtr_selector;
+ u16 guest_tr_selector;
+ u16 guest_intr_status;
+ u16 host_es_selector;
+ u16 host_cs_selector;
+ u16 host_ss_selector;
+ u16 host_ds_selector;
+ u16 host_fs_selector;
+ u16 host_gs_selector;
+ u16 host_tr_selector;
+ u16 guest_pml_index;
+};
+
+/*
+ * For save/restore compatibility, the vmcs12 field offsets must not change.
+ */
+#define CHECK_OFFSET(field, loc) \
+ BUILD_BUG_ON_MSG(offsetof(struct vmcs12, field) != (loc), \
+ "Offset of " #field " in struct vmcs12 has changed.")
+
+static inline void vmx_check_vmcs12_offsets(void) {
+ CHECK_OFFSET(hdr, 0);
+ CHECK_OFFSET(abort, 4);
+ CHECK_OFFSET(launch_state, 8);
+ CHECK_OFFSET(io_bitmap_a, 40);
+ CHECK_OFFSET(io_bitmap_b, 48);
+ CHECK_OFFSET(msr_bitmap, 56);
+ CHECK_OFFSET(vm_exit_msr_store_addr, 64);
+ CHECK_OFFSET(vm_exit_msr_load_addr, 72);
+ CHECK_OFFSET(vm_entry_msr_load_addr, 80);
+ CHECK_OFFSET(tsc_offset, 88);
+ CHECK_OFFSET(virtual_apic_page_addr, 96);
+ CHECK_OFFSET(apic_access_addr, 104);
+ CHECK_OFFSET(posted_intr_desc_addr, 112);
+ CHECK_OFFSET(ept_pointer, 120);
+ CHECK_OFFSET(eoi_exit_bitmap0, 128);
+ CHECK_OFFSET(eoi_exit_bitmap1, 136);
+ CHECK_OFFSET(eoi_exit_bitmap2, 144);
+ CHECK_OFFSET(eoi_exit_bitmap3, 152);
+ CHECK_OFFSET(xss_exit_bitmap, 160);
+ CHECK_OFFSET(guest_physical_address, 168);
+ CHECK_OFFSET(vmcs_link_pointer, 176);
+ CHECK_OFFSET(guest_ia32_debugctl, 184);
+ CHECK_OFFSET(guest_ia32_pat, 192);
+ CHECK_OFFSET(guest_ia32_efer, 200);
+ CHECK_OFFSET(guest_ia32_perf_global_ctrl, 208);
+ CHECK_OFFSET(guest_pdptr0, 216);
+ CHECK_OFFSET(guest_pdptr1, 224);
+ CHECK_OFFSET(guest_pdptr2, 232);
+ CHECK_OFFSET(guest_pdptr3, 240);
+ CHECK_OFFSET(guest_bndcfgs, 248);
+ CHECK_OFFSET(host_ia32_pat, 256);
+ CHECK_OFFSET(host_ia32_efer, 264);
+ CHECK_OFFSET(host_ia32_perf_global_ctrl, 272);
+ CHECK_OFFSET(vmread_bitmap, 280);
+ CHECK_OFFSET(vmwrite_bitmap, 288);
+ CHECK_OFFSET(vm_function_control, 296);
+ CHECK_OFFSET(eptp_list_address, 304);
+ CHECK_OFFSET(pml_address, 312);
+ CHECK_OFFSET(cr0_guest_host_mask, 344);
+ CHECK_OFFSET(cr4_guest_host_mask, 352);
+ CHECK_OFFSET(cr0_read_shadow, 360);
+ CHECK_OFFSET(cr4_read_shadow, 368);
+ CHECK_OFFSET(cr3_target_value0, 376);
+ CHECK_OFFSET(cr3_target_value1, 384);
+ CHECK_OFFSET(cr3_target_value2, 392);
+ CHECK_OFFSET(cr3_target_value3, 400);
+ CHECK_OFFSET(exit_qualification, 408);
+ CHECK_OFFSET(guest_linear_address, 416);
+ CHECK_OFFSET(guest_cr0, 424);
+ CHECK_OFFSET(guest_cr3, 432);
+ CHECK_OFFSET(guest_cr4, 440);
+ CHECK_OFFSET(guest_es_base, 448);
+ CHECK_OFFSET(guest_cs_base, 456);
+ CHECK_OFFSET(guest_ss_base, 464);
+ CHECK_OFFSET(guest_ds_base, 472);
+ CHECK_OFFSET(guest_fs_base, 480);
+ CHECK_OFFSET(guest_gs_base, 488);
+ CHECK_OFFSET(guest_ldtr_base, 496);
+ CHECK_OFFSET(guest_tr_base, 504);
+ CHECK_OFFSET(guest_gdtr_base, 512);
+ CHECK_OFFSET(guest_idtr_base, 520);
+ CHECK_OFFSET(guest_dr7, 528);
+ CHECK_OFFSET(guest_rsp, 536);
+ CHECK_OFFSET(guest_rip, 544);
+ CHECK_OFFSET(guest_rflags, 552);
+ CHECK_OFFSET(guest_pending_dbg_exceptions, 560);
+ CHECK_OFFSET(guest_sysenter_esp, 568);
+ CHECK_OFFSET(guest_sysenter_eip, 576);
+ CHECK_OFFSET(host_cr0, 584);
+ CHECK_OFFSET(host_cr3, 592);
+ CHECK_OFFSET(host_cr4, 600);
+ CHECK_OFFSET(host_fs_base, 608);
+ CHECK_OFFSET(host_gs_base, 616);
+ CHECK_OFFSET(host_tr_base, 624);
+ CHECK_OFFSET(host_gdtr_base, 632);
+ CHECK_OFFSET(host_idtr_base, 640);
+ CHECK_OFFSET(host_ia32_sysenter_esp, 648);
+ CHECK_OFFSET(host_ia32_sysenter_eip, 656);
+ CHECK_OFFSET(host_rsp, 664);
+ CHECK_OFFSET(host_rip, 672);
+ CHECK_OFFSET(pin_based_vm_exec_control, 744);
+ CHECK_OFFSET(cpu_based_vm_exec_control, 748);
+ CHECK_OFFSET(exception_bitmap, 752);
+ CHECK_OFFSET(page_fault_error_code_mask, 756);
+ CHECK_OFFSET(page_fault_error_code_match, 760);
+ CHECK_OFFSET(cr3_target_count, 764);
+ CHECK_OFFSET(vm_exit_controls, 768);
+ CHECK_OFFSET(vm_exit_msr_store_count, 772);
+ CHECK_OFFSET(vm_exit_msr_load_count, 776);
+ CHECK_OFFSET(vm_entry_controls, 780);
+ CHECK_OFFSET(vm_entry_msr_load_count, 784);
+ CHECK_OFFSET(vm_entry_intr_info_field, 788);
+ CHECK_OFFSET(vm_entry_exception_error_code, 792);
+ CHECK_OFFSET(vm_entry_instruction_len, 796);
+ CHECK_OFFSET(tpr_threshold, 800);
+ CHECK_OFFSET(secondary_vm_exec_control, 804);
+ CHECK_OFFSET(vm_instruction_error, 808);
+ CHECK_OFFSET(vm_exit_reason, 812);
+ CHECK_OFFSET(vm_exit_intr_info, 816);
+ CHECK_OFFSET(vm_exit_intr_error_code, 820);
+ CHECK_OFFSET(idt_vectoring_info_field, 824);
+ CHECK_OFFSET(idt_vectoring_error_code, 828);
+ CHECK_OFFSET(vm_exit_instruction_len, 832);
+ CHECK_OFFSET(vmx_instruction_info, 836);
+ CHECK_OFFSET(guest_es_limit, 840);
+ CHECK_OFFSET(guest_cs_limit, 844);
+ CHECK_OFFSET(guest_ss_limit, 848);
+ CHECK_OFFSET(guest_ds_limit, 852);
+ CHECK_OFFSET(guest_fs_limit, 856);
+ CHECK_OFFSET(guest_gs_limit, 860);
+ CHECK_OFFSET(guest_ldtr_limit, 864);
+ CHECK_OFFSET(guest_tr_limit, 868);
+ CHECK_OFFSET(guest_gdtr_limit, 872);
+ CHECK_OFFSET(guest_idtr_limit, 876);
+ CHECK_OFFSET(guest_es_ar_bytes, 880);
+ CHECK_OFFSET(guest_cs_ar_bytes, 884);
+ CHECK_OFFSET(guest_ss_ar_bytes, 888);
+ CHECK_OFFSET(guest_ds_ar_bytes, 892);
+ CHECK_OFFSET(guest_fs_ar_bytes, 896);
+ CHECK_OFFSET(guest_gs_ar_bytes, 900);
+ CHECK_OFFSET(guest_ldtr_ar_bytes, 904);
+ CHECK_OFFSET(guest_tr_ar_bytes, 908);
+ CHECK_OFFSET(guest_interruptibility_info, 912);
+ CHECK_OFFSET(guest_activity_state, 916);
+ CHECK_OFFSET(guest_sysenter_cs, 920);
+ CHECK_OFFSET(host_ia32_sysenter_cs, 924);
+ CHECK_OFFSET(vmx_preemption_timer_value, 928);
+ CHECK_OFFSET(virtual_processor_id, 960);
+ CHECK_OFFSET(posted_intr_nv, 962);
+ CHECK_OFFSET(guest_es_selector, 964);
+ CHECK_OFFSET(guest_cs_selector, 966);
+ CHECK_OFFSET(guest_ss_selector, 968);
+ CHECK_OFFSET(guest_ds_selector, 970);
+ CHECK_OFFSET(guest_fs_selector, 972);
+ CHECK_OFFSET(guest_gs_selector, 974);
+ CHECK_OFFSET(guest_ldtr_selector, 976);
+ CHECK_OFFSET(guest_tr_selector, 978);
+ CHECK_OFFSET(guest_intr_status, 980);
+ CHECK_OFFSET(host_es_selector, 982);
+ CHECK_OFFSET(host_cs_selector, 984);
+ CHECK_OFFSET(host_ss_selector, 986);
+ CHECK_OFFSET(host_ds_selector, 988);
+ CHECK_OFFSET(host_fs_selector, 990);
+ CHECK_OFFSET(host_gs_selector, 992);
+ CHECK_OFFSET(host_tr_selector, 994);
+ CHECK_OFFSET(guest_pml_index, 996);
+}
+
+/*
+ * VMCS12_REVISION is an arbitrary id that should be changed if the content or
+ * layout of struct vmcs12 is changed. MSR_IA32_VMX_BASIC returns this id, and
+ * VMPTRLD verifies that the VMCS region that L1 is loading contains this id.
+ *
+ * IMPORTANT: Changing this value will break save/restore compatibility with
+ * older kvm releases.
+ */
+#define VMCS12_REVISION 0x11e57ed0
+
+/*
+ * VMCS12_SIZE is the number of bytes L1 should allocate for the VMXON region
+ * and any VMCS region. Although only sizeof(struct vmcs12) are used by the
+ * current implementation, 4K are reserved to avoid future complications.
+ */
+#define VMCS12_SIZE 0x1000
+
+/*
+ * VMCS12_MAX_FIELD_INDEX is the highest index value used in any
+ * supported VMCS12 field encoding.
+ */
+#define VMCS12_MAX_FIELD_INDEX 0x17
+
+struct nested_vmx_msrs {
+ /*
+ * We only store the "true" versions of the VMX capability MSRs. We
+ * generate the "non-true" versions by setting the must-be-1 bits
+ * according to the SDM.
+ */
+ u32 procbased_ctls_low;
+ u32 procbased_ctls_high;
+ u32 secondary_ctls_low;
+ u32 secondary_ctls_high;
+ u32 pinbased_ctls_low;
+ u32 pinbased_ctls_high;
+ u32 exit_ctls_low;
+ u32 exit_ctls_high;
+ u32 entry_ctls_low;
+ u32 entry_ctls_high;
+ u32 misc_low;
+ u32 misc_high;
+ u32 ept_caps;
+ u32 vpid_caps;
+ u64 basic;
+ u64 cr0_fixed0;
+ u64 cr0_fixed1;
+ u64 cr4_fixed0;
+ u64 cr4_fixed1;
+ u64 vmcs_enum;
+ u64 vmfunc_controls;
+};
+
+/*
+ * The nested_vmx structure is part of vcpu_vmx, and holds information we need
+ * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
+ */
+struct nested_vmx {
+ /* Has the level1 guest done vmxon? */
+ bool vmxon;
+ gpa_t vmxon_ptr;
+ bool pml_full;
+
+ /* The guest-physical address of the current VMCS L1 keeps for L2 */
+ gpa_t current_vmptr;
+ /*
+ * Cache of the guest's VMCS, existing outside of guest memory.
+ * Loaded from guest memory during VMPTRLD. Flushed to guest
+ * memory during VMCLEAR and VMPTRLD.
+ */
+ struct vmcs12 *cached_vmcs12;
+ /*
+ * Cache of the guest's shadow VMCS, existing outside of guest
+ * memory. Loaded from guest memory during VM entry. Flushed
+ * to guest memory during VM exit.
+ */
+ struct vmcs12 *cached_shadow_vmcs12;
+ /*
+ * Indicates if the shadow vmcs must be updated with the
+ * data hold by vmcs12
+ */
+ bool sync_shadow_vmcs;
+ bool dirty_vmcs12;
+
+ bool change_vmcs01_virtual_apic_mode;
+
+ /* L2 must run next, and mustn't decide to exit to L1. */
+ bool nested_run_pending;
+
+ struct loaded_vmcs vmcs02;
+
+ /*
+ * Guest pages referred to in the vmcs02 with host-physical
+ * pointers, so we must keep them pinned while L2 runs.
+ */
+ struct page *apic_access_page;
+ struct page *virtual_apic_page;
+ struct page *pi_desc_page;
+ struct pi_desc *pi_desc;
+ bool pi_pending;
+ u16 posted_intr_nv;
+
+ struct hrtimer preemption_timer;
+ bool preemption_timer_expired;
+
+ /* to migrate it to L2 if VM_ENTRY_LOAD_DEBUG_CONTROLS is off */
+ u64 vmcs01_debugctl;
+ u64 vmcs01_guest_bndcfgs;
+
+ u16 vpid02;
+ u16 last_vpid;
+
+ struct nested_vmx_msrs msrs;
+
+ /* SMM related state */
+ struct {
+ /* in VMX operation on SMM entry? */
+ bool vmxon;
+ /* in guest mode on SMM entry? */
+ bool guest_mode;
+ } smm;
+};
+
+#define POSTED_INTR_ON 0
+#define POSTED_INTR_SN 1
+
+/* Posted-Interrupt Descriptor */
+struct pi_desc {
+ u32 pir[8]; /* Posted interrupt requested */
+ union {
+ struct {
+ /* bit 256 - Outstanding Notification */
+ u16 on : 1,
+ /* bit 257 - Suppress Notification */
+ sn : 1,
+ /* bit 271:258 - Reserved */
+ rsvd_1 : 14;
+ /* bit 279:272 - Notification Vector */
+ u8 nv;
+ /* bit 287:280 - Reserved */
+ u8 rsvd_2;
+ /* bit 319:288 - Notification Destination */
+ u32 ndst;
+ };
+ u64 control;
+ };
+ u32 rsvd[6];
+} __aligned(64);
+
+static bool pi_test_and_set_on(struct pi_desc *pi_desc)
+{
+ return test_and_set_bit(POSTED_INTR_ON,
+ (unsigned long *)&pi_desc->control);
+}
+
+static bool pi_test_and_clear_on(struct pi_desc *pi_desc)
+{
+ return test_and_clear_bit(POSTED_INTR_ON,
+ (unsigned long *)&pi_desc->control);
+}
+
+static int pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
+{
+ return test_and_set_bit(vector, (unsigned long *)pi_desc->pir);
+}
+
+static inline void pi_clear_sn(struct pi_desc *pi_desc)
+{
+ return clear_bit(POSTED_INTR_SN,
+ (unsigned long *)&pi_desc->control);
+}
+
+static inline void pi_set_sn(struct pi_desc *pi_desc)
+{
+ return set_bit(POSTED_INTR_SN,
+ (unsigned long *)&pi_desc->control);
+}
+
+static inline void pi_clear_on(struct pi_desc *pi_desc)
+{
+ clear_bit(POSTED_INTR_ON,
+ (unsigned long *)&pi_desc->control);
+}
+
+static inline int pi_test_on(struct pi_desc *pi_desc)
+{
+ return test_bit(POSTED_INTR_ON,
+ (unsigned long *)&pi_desc->control);
+}
+
+static inline int pi_test_sn(struct pi_desc *pi_desc)
+{
+ return test_bit(POSTED_INTR_SN,
+ (unsigned long *)&pi_desc->control);
+}
+
+struct vmx_msrs {
+ unsigned int nr;
+ struct vmx_msr_entry val[NR_AUTOLOAD_MSRS];
+};
+
+struct vcpu_vmx {
+ struct kvm_vcpu vcpu;
+ unsigned long host_rsp;
+ u8 fail;
+ u8 msr_bitmap_mode;
+ u32 exit_intr_info;
+ u32 idt_vectoring_info;
+ ulong rflags;
+ struct shared_msr_entry *guest_msrs;
+ int nmsrs;
+ int save_nmsrs;
+ bool guest_msrs_dirty;
+ unsigned long host_idt_base;
+#ifdef CONFIG_X86_64
+ u64 msr_host_kernel_gs_base;
+ u64 msr_guest_kernel_gs_base;
+#endif
+
+ u64 spec_ctrl;
+
+ u32 vm_entry_controls_shadow;
+ u32 vm_exit_controls_shadow;
+ u32 secondary_exec_control;
+
+ /*
+ * loaded_vmcs points to the VMCS currently used in this vcpu. For a
+ * non-nested (L1) guest, it always points to vmcs01. For a nested
+ * guest (L2), it points to a different VMCS. loaded_cpu_state points
+ * to the VMCS whose state is loaded into the CPU registers that only
+ * need to be switched when transitioning to/from the kernel; a NULL
+ * value indicates that host state is loaded.
+ */
+ struct loaded_vmcs vmcs01;
+ struct loaded_vmcs *loaded_vmcs;
+ struct loaded_vmcs *loaded_cpu_state;
+ bool __launched; /* temporary, used in vmx_vcpu_run */
+ struct msr_autoload {
+ struct vmx_msrs guest;
+ struct vmx_msrs host;
+ } msr_autoload;
+
+ struct {
+ int vm86_active;
+ ulong save_rflags;
+ struct kvm_segment segs[8];
+ } rmode;
+ struct {
+ u32 bitmask; /* 4 bits per segment (1 bit per field) */
+ struct kvm_save_segment {
+ u16 selector;
+ unsigned long base;
+ u32 limit;
+ u32 ar;
+ } seg[8];
+ } segment_cache;
+ int vpid;
+ bool emulation_required;
+
+ u32 exit_reason;
+
+ /* Posted interrupt descriptor */
+ struct pi_desc pi_desc;
+
+ /* Support for a guest hypervisor (nested VMX) */
+ struct nested_vmx nested;
+
+ /* Dynamic PLE window. */
+ int ple_window;
+ bool ple_window_dirty;
+
+ bool req_immediate_exit;
+
+ /* Support for PML */
+#define PML_ENTITY_NUM 512
+ struct page *pml_pg;
+
+ /* apic deadline value in host tsc */
+ u64 hv_deadline_tsc;
+
+ u64 current_tsc_ratio;
+
+ u32 host_pkru;
+
+ unsigned long host_debugctlmsr;
+
+ /*
+ * Only bits masked by msr_ia32_feature_control_valid_bits can be set in
+ * msr_ia32_feature_control. FEATURE_CONTROL_LOCKED is always included
+ * in msr_ia32_feature_control_valid_bits.
+ */
+ u64 msr_ia32_feature_control;
+ u64 msr_ia32_feature_control_valid_bits;
+ u64 ept_pointer;
+ u64 msr_ia32_mcu_opt_ctrl;
+ bool disable_fb_clear;
+};
+
+enum segment_cache_field {
+ SEG_FIELD_SEL = 0,
+ SEG_FIELD_BASE = 1,
+ SEG_FIELD_LIMIT = 2,
+ SEG_FIELD_AR = 3,
+
+ SEG_FIELD_NR = 4
+};
+
+static inline struct kvm_vmx *to_kvm_vmx(struct kvm *kvm)
+{
+ return container_of(kvm, struct kvm_vmx, kvm);
+}
+
+static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
+{
+ return container_of(vcpu, struct vcpu_vmx, vcpu);
+}
+
+static struct pi_desc *vcpu_to_pi_desc(struct kvm_vcpu *vcpu)
+{
+ return &(to_vmx(vcpu)->pi_desc);
+}
+
+#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
+#define VMCS12_OFFSET(x) offsetof(struct vmcs12, x)
+#define FIELD(number, name) [ROL16(number, 6)] = VMCS12_OFFSET(name)
+#define FIELD64(number, name) \
+ FIELD(number, name), \
+ [ROL16(number##_HIGH, 6)] = VMCS12_OFFSET(name) + sizeof(u32)
+
+
+static u16 shadow_read_only_fields[] = {
+#define SHADOW_FIELD_RO(x) x,
+#include "vmx_shadow_fields.h"
+};
+static int max_shadow_read_only_fields =
+ ARRAY_SIZE(shadow_read_only_fields);
+
+static u16 shadow_read_write_fields[] = {
+#define SHADOW_FIELD_RW(x) x,
+#include "vmx_shadow_fields.h"
+};
+static int max_shadow_read_write_fields =
+ ARRAY_SIZE(shadow_read_write_fields);
+
+static const unsigned short vmcs_field_to_offset_table[] = {
+ FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id),
+ FIELD(POSTED_INTR_NV, posted_intr_nv),
+ FIELD(GUEST_ES_SELECTOR, guest_es_selector),
+ FIELD(GUEST_CS_SELECTOR, guest_cs_selector),
+ FIELD(GUEST_SS_SELECTOR, guest_ss_selector),
+ FIELD(GUEST_DS_SELECTOR, guest_ds_selector),
+ FIELD(GUEST_FS_SELECTOR, guest_fs_selector),
+ FIELD(GUEST_GS_SELECTOR, guest_gs_selector),
+ FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector),
+ FIELD(GUEST_TR_SELECTOR, guest_tr_selector),
+ FIELD(GUEST_INTR_STATUS, guest_intr_status),
+ FIELD(GUEST_PML_INDEX, guest_pml_index),
+ FIELD(HOST_ES_SELECTOR, host_es_selector),
+ FIELD(HOST_CS_SELECTOR, host_cs_selector),
+ FIELD(HOST_SS_SELECTOR, host_ss_selector),
+ FIELD(HOST_DS_SELECTOR, host_ds_selector),
+ FIELD(HOST_FS_SELECTOR, host_fs_selector),
+ FIELD(HOST_GS_SELECTOR, host_gs_selector),
+ FIELD(HOST_TR_SELECTOR, host_tr_selector),
+ FIELD64(IO_BITMAP_A, io_bitmap_a),
+ FIELD64(IO_BITMAP_B, io_bitmap_b),
+ FIELD64(MSR_BITMAP, msr_bitmap),
+ FIELD64(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr),
+ FIELD64(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr),
+ FIELD64(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr),
+ FIELD64(PML_ADDRESS, pml_address),
+ FIELD64(TSC_OFFSET, tsc_offset),
+ FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr),
+ FIELD64(APIC_ACCESS_ADDR, apic_access_addr),
+ FIELD64(POSTED_INTR_DESC_ADDR, posted_intr_desc_addr),
+ FIELD64(VM_FUNCTION_CONTROL, vm_function_control),
+ FIELD64(EPT_POINTER, ept_pointer),
+ FIELD64(EOI_EXIT_BITMAP0, eoi_exit_bitmap0),
+ FIELD64(EOI_EXIT_BITMAP1, eoi_exit_bitmap1),
+ FIELD64(EOI_EXIT_BITMAP2, eoi_exit_bitmap2),
+ FIELD64(EOI_EXIT_BITMAP3, eoi_exit_bitmap3),
+ FIELD64(EPTP_LIST_ADDRESS, eptp_list_address),
+ FIELD64(VMREAD_BITMAP, vmread_bitmap),
+ FIELD64(VMWRITE_BITMAP, vmwrite_bitmap),
+ FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap),
+ FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address),
+ FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer),
+ FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl),
+ FIELD64(GUEST_IA32_PAT, guest_ia32_pat),
+ FIELD64(GUEST_IA32_EFER, guest_ia32_efer),
+ FIELD64(GUEST_IA32_PERF_GLOBAL_CTRL, guest_ia32_perf_global_ctrl),
+ FIELD64(GUEST_PDPTR0, guest_pdptr0),
+ FIELD64(GUEST_PDPTR1, guest_pdptr1),
+ FIELD64(GUEST_PDPTR2, guest_pdptr2),
+ FIELD64(GUEST_PDPTR3, guest_pdptr3),
+ FIELD64(GUEST_BNDCFGS, guest_bndcfgs),
+ FIELD64(HOST_IA32_PAT, host_ia32_pat),
+ FIELD64(HOST_IA32_EFER, host_ia32_efer),
+ FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl),
+ FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control),
+ FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control),
+ FIELD(EXCEPTION_BITMAP, exception_bitmap),
+ FIELD(PAGE_FAULT_ERROR_CODE_MASK, page_fault_error_code_mask),
+ FIELD(PAGE_FAULT_ERROR_CODE_MATCH, page_fault_error_code_match),
+ FIELD(CR3_TARGET_COUNT, cr3_target_count),
+ FIELD(VM_EXIT_CONTROLS, vm_exit_controls),
+ FIELD(VM_EXIT_MSR_STORE_COUNT, vm_exit_msr_store_count),
+ FIELD(VM_EXIT_MSR_LOAD_COUNT, vm_exit_msr_load_count),
+ FIELD(VM_ENTRY_CONTROLS, vm_entry_controls),
+ FIELD(VM_ENTRY_MSR_LOAD_COUNT, vm_entry_msr_load_count),
+ FIELD(VM_ENTRY_INTR_INFO_FIELD, vm_entry_intr_info_field),
+ FIELD(VM_ENTRY_EXCEPTION_ERROR_CODE, vm_entry_exception_error_code),
+ FIELD(VM_ENTRY_INSTRUCTION_LEN, vm_entry_instruction_len),
+ FIELD(TPR_THRESHOLD, tpr_threshold),
+ FIELD(SECONDARY_VM_EXEC_CONTROL, secondary_vm_exec_control),
+ FIELD(VM_INSTRUCTION_ERROR, vm_instruction_error),
+ FIELD(VM_EXIT_REASON, vm_exit_reason),
+ FIELD(VM_EXIT_INTR_INFO, vm_exit_intr_info),
+ FIELD(VM_EXIT_INTR_ERROR_CODE, vm_exit_intr_error_code),
+ FIELD(IDT_VECTORING_INFO_FIELD, idt_vectoring_info_field),
+ FIELD(IDT_VECTORING_ERROR_CODE, idt_vectoring_error_code),
+ FIELD(VM_EXIT_INSTRUCTION_LEN, vm_exit_instruction_len),
+ FIELD(VMX_INSTRUCTION_INFO, vmx_instruction_info),
+ FIELD(GUEST_ES_LIMIT, guest_es_limit),
+ FIELD(GUEST_CS_LIMIT, guest_cs_limit),
+ FIELD(GUEST_SS_LIMIT, guest_ss_limit),
+ FIELD(GUEST_DS_LIMIT, guest_ds_limit),
+ FIELD(GUEST_FS_LIMIT, guest_fs_limit),
+ FIELD(GUEST_GS_LIMIT, guest_gs_limit),
+ FIELD(GUEST_LDTR_LIMIT, guest_ldtr_limit),
+ FIELD(GUEST_TR_LIMIT, guest_tr_limit),
+ FIELD(GUEST_GDTR_LIMIT, guest_gdtr_limit),
+ FIELD(GUEST_IDTR_LIMIT, guest_idtr_limit),
+ FIELD(GUEST_ES_AR_BYTES, guest_es_ar_bytes),
+ FIELD(GUEST_CS_AR_BYTES, guest_cs_ar_bytes),
+ FIELD(GUEST_SS_AR_BYTES, guest_ss_ar_bytes),
+ FIELD(GUEST_DS_AR_BYTES, guest_ds_ar_bytes),
+ FIELD(GUEST_FS_AR_BYTES, guest_fs_ar_bytes),
+ FIELD(GUEST_GS_AR_BYTES, guest_gs_ar_bytes),
+ FIELD(GUEST_LDTR_AR_BYTES, guest_ldtr_ar_bytes),
+ FIELD(GUEST_TR_AR_BYTES, guest_tr_ar_bytes),
+ FIELD(GUEST_INTERRUPTIBILITY_INFO, guest_interruptibility_info),
+ FIELD(GUEST_ACTIVITY_STATE, guest_activity_state),
+ FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs),
+ FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs),
+ FIELD(VMX_PREEMPTION_TIMER_VALUE, vmx_preemption_timer_value),
+ FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask),
+ FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask),
+ FIELD(CR0_READ_SHADOW, cr0_read_shadow),
+ FIELD(CR4_READ_SHADOW, cr4_read_shadow),
+ FIELD(CR3_TARGET_VALUE0, cr3_target_value0),
+ FIELD(CR3_TARGET_VALUE1, cr3_target_value1),
+ FIELD(CR3_TARGET_VALUE2, cr3_target_value2),
+ FIELD(CR3_TARGET_VALUE3, cr3_target_value3),
+ FIELD(EXIT_QUALIFICATION, exit_qualification),
+ FIELD(GUEST_LINEAR_ADDRESS, guest_linear_address),
+ FIELD(GUEST_CR0, guest_cr0),
+ FIELD(GUEST_CR3, guest_cr3),
+ FIELD(GUEST_CR4, guest_cr4),
+ FIELD(GUEST_ES_BASE, guest_es_base),
+ FIELD(GUEST_CS_BASE, guest_cs_base),
+ FIELD(GUEST_SS_BASE, guest_ss_base),
+ FIELD(GUEST_DS_BASE, guest_ds_base),
+ FIELD(GUEST_FS_BASE, guest_fs_base),
+ FIELD(GUEST_GS_BASE, guest_gs_base),
+ FIELD(GUEST_LDTR_BASE, guest_ldtr_base),
+ FIELD(GUEST_TR_BASE, guest_tr_base),
+ FIELD(GUEST_GDTR_BASE, guest_gdtr_base),
+ FIELD(GUEST_IDTR_BASE, guest_idtr_base),
+ FIELD(GUEST_DR7, guest_dr7),
+ FIELD(GUEST_RSP, guest_rsp),
+ FIELD(GUEST_RIP, guest_rip),
+ FIELD(GUEST_RFLAGS, guest_rflags),
+ FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions),
+ FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp),
+ FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip),
+ FIELD(HOST_CR0, host_cr0),
+ FIELD(HOST_CR3, host_cr3),
+ FIELD(HOST_CR4, host_cr4),
+ FIELD(HOST_FS_BASE, host_fs_base),
+ FIELD(HOST_GS_BASE, host_gs_base),
+ FIELD(HOST_TR_BASE, host_tr_base),
+ FIELD(HOST_GDTR_BASE, host_gdtr_base),
+ FIELD(HOST_IDTR_BASE, host_idtr_base),
+ FIELD(HOST_IA32_SYSENTER_ESP, host_ia32_sysenter_esp),
+ FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip),
+ FIELD(HOST_RSP, host_rsp),
+ FIELD(HOST_RIP, host_rip),
+};
+
+static inline short vmcs_field_to_offset(unsigned long field)
+{
+ const size_t size = ARRAY_SIZE(vmcs_field_to_offset_table);
+ unsigned short offset;
+ unsigned index;
+
+ if (field >> 15)
+ return -ENOENT;
+
+ index = ROL16(field, 6);
+ if (index >= size)
+ return -ENOENT;
+
+ index = array_index_nospec(index, size);
+ offset = vmcs_field_to_offset_table[index];
+ if (offset == 0)
+ return -ENOENT;
+ return offset;
+}
+
+static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.cached_vmcs12;
+}
+
+static inline struct vmcs12 *get_shadow_vmcs12(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.cached_shadow_vmcs12;
+}
+
+static bool nested_ept_ad_enabled(struct kvm_vcpu *vcpu);
+static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu);
+static u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa);
+static bool vmx_xsaves_supported(void);
+static void vmx_set_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg);
+static void vmx_get_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg);
+static bool guest_state_valid(struct kvm_vcpu *vcpu);
+static u32 vmx_segment_access_rights(struct kvm_segment *var);
+static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx);
+static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu);
+static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked);
+static bool nested_vmx_is_page_fault_vmexit(struct vmcs12 *vmcs12,
+ u16 error_code);
+static void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu);
+static __always_inline void vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
+ u32 msr, int type);
+
+static DEFINE_PER_CPU(struct vmcs *, vmxarea);
+static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
+/*
+ * We maintain a per-CPU linked-list of VMCS loaded on that CPU. This is needed
+ * when a CPU is brought down, and we need to VMCLEAR all VMCSs loaded on it.
+ */
+static DEFINE_PER_CPU(struct list_head, loaded_vmcss_on_cpu);
+
+/*
+ * We maintian a per-CPU linked-list of vCPU, so in wakeup_handler() we
+ * can find which vCPU should be waken up.
+ */
+static DEFINE_PER_CPU(struct list_head, blocked_vcpu_on_cpu);
+static DEFINE_PER_CPU(spinlock_t, blocked_vcpu_on_cpu_lock);
+
+enum {
+ VMX_VMREAD_BITMAP,
+ VMX_VMWRITE_BITMAP,
+ VMX_BITMAP_NR
+};
+
+static unsigned long *vmx_bitmap[VMX_BITMAP_NR];
+
+#define vmx_vmread_bitmap (vmx_bitmap[VMX_VMREAD_BITMAP])
+#define vmx_vmwrite_bitmap (vmx_bitmap[VMX_VMWRITE_BITMAP])
+
+static bool cpu_has_load_ia32_efer;
+static bool cpu_has_load_perf_global_ctrl;
+
+static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
+static DEFINE_SPINLOCK(vmx_vpid_lock);
+
+static struct vmcs_config {
+ int size;
+ int order;
+ u32 basic_cap;
+ u32 revision_id;
+ u32 pin_based_exec_ctrl;
+ u32 cpu_based_exec_ctrl;
+ u32 cpu_based_2nd_exec_ctrl;
+ u32 vmexit_ctrl;
+ u32 vmentry_ctrl;
+ struct nested_vmx_msrs nested;
+} vmcs_config;
+
+static struct vmx_capability {
+ u32 ept;
+ u32 vpid;
+} vmx_capability;
+
+#define VMX_SEGMENT_FIELD(seg) \
+ [VCPU_SREG_##seg] = { \
+ .selector = GUEST_##seg##_SELECTOR, \
+ .base = GUEST_##seg##_BASE, \
+ .limit = GUEST_##seg##_LIMIT, \
+ .ar_bytes = GUEST_##seg##_AR_BYTES, \
+ }
+
+static const struct kvm_vmx_segment_field {
+ unsigned selector;
+ unsigned base;
+ unsigned limit;
+ unsigned ar_bytes;
+} kvm_vmx_segment_fields[] = {
+ VMX_SEGMENT_FIELD(CS),
+ VMX_SEGMENT_FIELD(DS),
+ VMX_SEGMENT_FIELD(ES),
+ VMX_SEGMENT_FIELD(FS),
+ VMX_SEGMENT_FIELD(GS),
+ VMX_SEGMENT_FIELD(SS),
+ VMX_SEGMENT_FIELD(TR),
+ VMX_SEGMENT_FIELD(LDTR),
+};
+
+static u64 host_efer;
+
+static void ept_save_pdptrs(struct kvm_vcpu *vcpu);
+
+/*
+ * Keep MSR_STAR at the end, as setup_msrs() will try to optimize it
+ * away by decrementing the array size.
+ */
+static const u32 vmx_msr_index[] = {
+#ifdef CONFIG_X86_64
+ MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR,
+#endif
+ MSR_EFER, MSR_TSC_AUX, MSR_STAR,
+};
+
+DEFINE_STATIC_KEY_FALSE(enable_evmcs);
+
+#define current_evmcs ((struct hv_enlightened_vmcs *)this_cpu_read(current_vmcs))
+
+#define KVM_EVMCS_VERSION 1
+
+#if IS_ENABLED(CONFIG_HYPERV)
+static bool __read_mostly enlightened_vmcs = true;
+module_param(enlightened_vmcs, bool, 0444);
+
+static inline void evmcs_write64(unsigned long field, u64 value)
+{
+ u16 clean_field;
+ int offset = get_evmcs_offset(field, &clean_field);
+
+ if (offset < 0)
+ return;
+
+ *(u64 *)((char *)current_evmcs + offset) = value;
+
+ current_evmcs->hv_clean_fields &= ~clean_field;
+}
+
+static inline void evmcs_write32(unsigned long field, u32 value)
+{
+ u16 clean_field;
+ int offset = get_evmcs_offset(field, &clean_field);
+
+ if (offset < 0)
+ return;
+
+ *(u32 *)((char *)current_evmcs + offset) = value;
+ current_evmcs->hv_clean_fields &= ~clean_field;
+}
+
+static inline void evmcs_write16(unsigned long field, u16 value)
+{
+ u16 clean_field;
+ int offset = get_evmcs_offset(field, &clean_field);
+
+ if (offset < 0)
+ return;
+
+ *(u16 *)((char *)current_evmcs + offset) = value;
+ current_evmcs->hv_clean_fields &= ~clean_field;
+}
+
+static inline u64 evmcs_read64(unsigned long field)
+{
+ int offset = get_evmcs_offset(field, NULL);
+
+ if (offset < 0)
+ return 0;
+
+ return *(u64 *)((char *)current_evmcs + offset);
+}
+
+static inline u32 evmcs_read32(unsigned long field)
+{
+ int offset = get_evmcs_offset(field, NULL);
+
+ if (offset < 0)
+ return 0;
+
+ return *(u32 *)((char *)current_evmcs + offset);
+}
+
+static inline u16 evmcs_read16(unsigned long field)
+{
+ int offset = get_evmcs_offset(field, NULL);
+
+ if (offset < 0)
+ return 0;
+
+ return *(u16 *)((char *)current_evmcs + offset);
+}
+
+static inline void evmcs_touch_msr_bitmap(void)
+{
+ if (unlikely(!current_evmcs))
+ return;
+
+ if (current_evmcs->hv_enlightenments_control.msr_bitmap)
+ current_evmcs->hv_clean_fields &=
+ ~HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP;
+}
+
+static void evmcs_load(u64 phys_addr)
+{
+ struct hv_vp_assist_page *vp_ap =
+ hv_get_vp_assist_page(smp_processor_id());
+
+ vp_ap->current_nested_vmcs = phys_addr;
+ vp_ap->enlighten_vmentry = 1;
+}
+
+static void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
+{
+ /*
+ * Enlightened VMCSv1 doesn't support these:
+ *
+ * POSTED_INTR_NV = 0x00000002,
+ * GUEST_INTR_STATUS = 0x00000810,
+ * APIC_ACCESS_ADDR = 0x00002014,
+ * POSTED_INTR_DESC_ADDR = 0x00002016,
+ * EOI_EXIT_BITMAP0 = 0x0000201c,
+ * EOI_EXIT_BITMAP1 = 0x0000201e,
+ * EOI_EXIT_BITMAP2 = 0x00002020,
+ * EOI_EXIT_BITMAP3 = 0x00002022,
+ */
+ vmcs_conf->pin_based_exec_ctrl &= ~PIN_BASED_POSTED_INTR;
+ vmcs_conf->cpu_based_2nd_exec_ctrl &=
+ ~SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
+ vmcs_conf->cpu_based_2nd_exec_ctrl &=
+ ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ vmcs_conf->cpu_based_2nd_exec_ctrl &=
+ ~SECONDARY_EXEC_APIC_REGISTER_VIRT;
+
+ /*
+ * GUEST_PML_INDEX = 0x00000812,
+ * PML_ADDRESS = 0x0000200e,
+ */
+ vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_ENABLE_PML;
+
+ /* VM_FUNCTION_CONTROL = 0x00002018, */
+ vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_ENABLE_VMFUNC;
+
+ /*
+ * EPTP_LIST_ADDRESS = 0x00002024,
+ * VMREAD_BITMAP = 0x00002026,
+ * VMWRITE_BITMAP = 0x00002028,
+ */
+ vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_SHADOW_VMCS;
+
+ /*
+ * TSC_MULTIPLIER = 0x00002032,
+ */
+ vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_TSC_SCALING;
+
+ /*
+ * PLE_GAP = 0x00004020,
+ * PLE_WINDOW = 0x00004022,
+ */
+ vmcs_conf->cpu_based_2nd_exec_ctrl &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
+
+ /*
+ * VMX_PREEMPTION_TIMER_VALUE = 0x0000482E,
+ */
+ vmcs_conf->pin_based_exec_ctrl &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
+
+ /*
+ * GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808,
+ * HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04,
+ */
+ vmcs_conf->vmexit_ctrl &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
+ vmcs_conf->vmentry_ctrl &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
+
+ /*
+ * Currently unsupported in KVM:
+ * GUEST_IA32_RTIT_CTL = 0x00002814,
+ */
+}
+
+/* check_ept_pointer() should be under protection of ept_pointer_lock. */
+static void check_ept_pointer_match(struct kvm *kvm)
+{
+ struct kvm_vcpu *vcpu;
+ u64 tmp_eptp = INVALID_PAGE;
+ int i;
+
+ kvm_for_each_vcpu(i, vcpu, kvm) {
+ if (!VALID_PAGE(tmp_eptp)) {
+ tmp_eptp = to_vmx(vcpu)->ept_pointer;
+ } else if (tmp_eptp != to_vmx(vcpu)->ept_pointer) {
+ to_kvm_vmx(kvm)->ept_pointers_match
+ = EPT_POINTERS_MISMATCH;
+ return;
+ }
+ }
+
+ to_kvm_vmx(kvm)->ept_pointers_match = EPT_POINTERS_MATCH;
+}
+
+static int vmx_hv_remote_flush_tlb(struct kvm *kvm)
+{
+ int ret;
+
+ spin_lock(&to_kvm_vmx(kvm)->ept_pointer_lock);
+
+ if (to_kvm_vmx(kvm)->ept_pointers_match == EPT_POINTERS_CHECK)
+ check_ept_pointer_match(kvm);
+
+ if (to_kvm_vmx(kvm)->ept_pointers_match != EPT_POINTERS_MATCH) {
+ ret = -ENOTSUPP;
+ goto out;
+ }
+
+ /*
+ * FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE hypercall needs the address of the
+ * base of EPT PML4 table, strip off EPT configuration information.
+ */
+ ret = hyperv_flush_guest_mapping(
+ to_vmx(kvm_get_vcpu(kvm, 0))->ept_pointer & PAGE_MASK);
+
+out:
+ spin_unlock(&to_kvm_vmx(kvm)->ept_pointer_lock);
+ return ret;
+}
+#else /* !IS_ENABLED(CONFIG_HYPERV) */
+static inline void evmcs_write64(unsigned long field, u64 value) {}
+static inline void evmcs_write32(unsigned long field, u32 value) {}
+static inline void evmcs_write16(unsigned long field, u16 value) {}
+static inline u64 evmcs_read64(unsigned long field) { return 0; }
+static inline u32 evmcs_read32(unsigned long field) { return 0; }
+static inline u16 evmcs_read16(unsigned long field) { return 0; }
+static inline void evmcs_load(u64 phys_addr) {}
+static inline void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) {}
+static inline void evmcs_touch_msr_bitmap(void) {}
+#endif /* IS_ENABLED(CONFIG_HYPERV) */
+
+static inline bool is_exception_n(u32 intr_info, u8 vector)
+{
+ return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
+ INTR_INFO_VALID_MASK)) ==
+ (INTR_TYPE_HARD_EXCEPTION | vector | INTR_INFO_VALID_MASK);
+}
+
+static inline bool is_debug(u32 intr_info)
+{
+ return is_exception_n(intr_info, DB_VECTOR);
+}
+
+static inline bool is_breakpoint(u32 intr_info)
+{
+ return is_exception_n(intr_info, BP_VECTOR);
+}
+
+static inline bool is_page_fault(u32 intr_info)
+{
+ return is_exception_n(intr_info, PF_VECTOR);
+}
+
+static inline bool is_no_device(u32 intr_info)
+{
+ return is_exception_n(intr_info, NM_VECTOR);
+}
+
+static inline bool is_invalid_opcode(u32 intr_info)
+{
+ return is_exception_n(intr_info, UD_VECTOR);
+}
+
+static inline bool is_gp_fault(u32 intr_info)
+{
+ return is_exception_n(intr_info, GP_VECTOR);
+}
+
+static inline bool is_external_interrupt(u32 intr_info)
+{
+ return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
+ == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
+}
+
+static inline bool is_machine_check(u32 intr_info)
+{
+ return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
+ INTR_INFO_VALID_MASK)) ==
+ (INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK);
+}
+
+/* Undocumented: icebp/int1 */
+static inline bool is_icebp(u32 intr_info)
+{
+ return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
+ == (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK);
+}
+
+static inline bool cpu_has_vmx_msr_bitmap(void)
+{
+ return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
+}
+
+static inline bool cpu_has_vmx_tpr_shadow(void)
+{
+ return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
+}
+
+static inline bool cpu_need_tpr_shadow(struct kvm_vcpu *vcpu)
+{
+ return cpu_has_vmx_tpr_shadow() && lapic_in_kernel(vcpu);
+}
+
+static inline bool cpu_has_secondary_exec_ctrls(void)
+{
+ return vmcs_config.cpu_based_exec_ctrl &
+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+}
+
+static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+}
+
+static inline bool cpu_has_vmx_virtualize_x2apic_mode(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
+}
+
+static inline bool cpu_has_vmx_apic_register_virt(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_APIC_REGISTER_VIRT;
+}
+
+static inline bool cpu_has_vmx_virtual_intr_delivery(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
+}
+
+static inline bool cpu_has_vmx_encls_vmexit(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENCLS_EXITING;
+}
+
+/*
+ * Comment's format: document - errata name - stepping - processor name.
+ * Refer from
+ * https://www.virtualbox.org/svn/vbox/trunk/src/VBox/VMM/VMMR0/HMR0.cpp
+ */
+static u32 vmx_preemption_cpu_tfms[] = {
+/* 323344.pdf - BA86 - D0 - Xeon 7500 Series */
+0x000206E6,
+/* 323056.pdf - AAX65 - C2 - Xeon L3406 */
+/* 322814.pdf - AAT59 - C2 - i7-600, i5-500, i5-400 and i3-300 Mobile */
+/* 322911.pdf - AAU65 - C2 - i5-600, i3-500 Desktop and Pentium G6950 */
+0x00020652,
+/* 322911.pdf - AAU65 - K0 - i5-600, i3-500 Desktop and Pentium G6950 */
+0x00020655,
+/* 322373.pdf - AAO95 - B1 - Xeon 3400 Series */
+/* 322166.pdf - AAN92 - B1 - i7-800 and i5-700 Desktop */
+/*
+ * 320767.pdf - AAP86 - B1 -
+ * i7-900 Mobile Extreme, i7-800 and i7-700 Mobile
+ */
+0x000106E5,
+/* 321333.pdf - AAM126 - C0 - Xeon 3500 */
+0x000106A0,
+/* 321333.pdf - AAM126 - C1 - Xeon 3500 */
+0x000106A1,
+/* 320836.pdf - AAJ124 - C0 - i7-900 Desktop Extreme and i7-900 Desktop */
+0x000106A4,
+ /* 321333.pdf - AAM126 - D0 - Xeon 3500 */
+ /* 321324.pdf - AAK139 - D0 - Xeon 5500 */
+ /* 320836.pdf - AAJ124 - D0 - i7-900 Extreme and i7-900 Desktop */
+0x000106A5,
+};
+
+static inline bool cpu_has_broken_vmx_preemption_timer(void)
+{
+ u32 eax = cpuid_eax(0x00000001), i;
+
+ /* Clear the reserved bits */
+ eax &= ~(0x3U << 14 | 0xfU << 28);
+ for (i = 0; i < ARRAY_SIZE(vmx_preemption_cpu_tfms); i++)
+ if (eax == vmx_preemption_cpu_tfms[i])
+ return true;
+
+ return false;
+}
+
+static inline bool cpu_has_vmx_preemption_timer(void)
+{
+ return vmcs_config.pin_based_exec_ctrl &
+ PIN_BASED_VMX_PREEMPTION_TIMER;
+}
+
+static inline bool cpu_has_vmx_posted_intr(void)
+{
+ return IS_ENABLED(CONFIG_X86_LOCAL_APIC) &&
+ vmcs_config.pin_based_exec_ctrl & PIN_BASED_POSTED_INTR;
+}
+
+static inline bool cpu_has_vmx_apicv(void)
+{
+ return cpu_has_vmx_apic_register_virt() &&
+ cpu_has_vmx_virtual_intr_delivery() &&
+ cpu_has_vmx_posted_intr();
+}
+
+static inline bool cpu_has_vmx_flexpriority(void)
+{
+ return cpu_has_vmx_tpr_shadow() &&
+ cpu_has_vmx_virtualize_apic_accesses();
+}
+
+static inline bool cpu_has_vmx_ept_execute_only(void)
+{
+ return vmx_capability.ept & VMX_EPT_EXECUTE_ONLY_BIT;
+}
+
+static inline bool cpu_has_vmx_ept_2m_page(void)
+{
+ return vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT;
+}
+
+static inline bool cpu_has_vmx_ept_1g_page(void)
+{
+ return vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT;
+}
+
+static inline bool cpu_has_vmx_ept_4levels(void)
+{
+ return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT;
+}
+
+static inline bool cpu_has_vmx_ept_mt_wb(void)
+{
+ return vmx_capability.ept & VMX_EPTP_WB_BIT;
+}
+
+static inline bool cpu_has_vmx_ept_5levels(void)
+{
+ return vmx_capability.ept & VMX_EPT_PAGE_WALK_5_BIT;
+}
+
+static inline bool cpu_has_vmx_ept_ad_bits(void)
+{
+ return vmx_capability.ept & VMX_EPT_AD_BIT;
+}
+
+static inline bool cpu_has_vmx_invept_context(void)
+{
+ return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
+}
+
+static inline bool cpu_has_vmx_invept_global(void)
+{
+ return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
+}
+
+static inline bool cpu_has_vmx_invvpid_individual_addr(void)
+{
+ return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT;
+}
+
+static inline bool cpu_has_vmx_invvpid_single(void)
+{
+ return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
+}
+
+static inline bool cpu_has_vmx_invvpid_global(void)
+{
+ return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
+}
+
+static inline bool cpu_has_vmx_invvpid(void)
+{
+ return vmx_capability.vpid & VMX_VPID_INVVPID_BIT;
+}
+
+static inline bool cpu_has_vmx_ept(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENABLE_EPT;
+}
+
+static inline bool cpu_has_vmx_unrestricted_guest(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_UNRESTRICTED_GUEST;
+}
+
+static inline bool cpu_has_vmx_ple(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_PAUSE_LOOP_EXITING;
+}
+
+static inline bool cpu_has_vmx_basic_inout(void)
+{
+ return (((u64)vmcs_config.basic_cap << 32) & VMX_BASIC_INOUT);
+}
+
+static inline bool cpu_need_virtualize_apic_accesses(struct kvm_vcpu *vcpu)
+{
+ return flexpriority_enabled && lapic_in_kernel(vcpu);
+}
+
+static inline bool cpu_has_vmx_vpid(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENABLE_VPID;
+}
+
+static inline bool cpu_has_vmx_rdtscp(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_RDTSCP;
+}
+
+static inline bool cpu_has_vmx_invpcid(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENABLE_INVPCID;
+}
+
+static inline bool cpu_has_virtual_nmis(void)
+{
+ return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
+}
+
+static inline bool cpu_has_vmx_wbinvd_exit(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_WBINVD_EXITING;
+}
+
+static inline bool cpu_has_vmx_shadow_vmcs(void)
+{
+ u64 vmx_msr;
+ rdmsrl(MSR_IA32_VMX_MISC, vmx_msr);
+ /* check if the cpu supports writing r/o exit information fields */
+ if (!(vmx_msr & MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS))
+ return false;
+
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_SHADOW_VMCS;
+}
+
+static inline bool cpu_has_vmx_pml(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_ENABLE_PML;
+}
+
+static inline bool cpu_has_vmx_tsc_scaling(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_TSC_SCALING;
+}
+
+static inline bool cpu_has_vmx_vmfunc(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_ENABLE_VMFUNC;
+}
+
+static bool vmx_umip_emulated(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_DESC;
+}
+
+static inline bool report_flexpriority(void)
+{
+ return flexpriority_enabled;
+}
+
+static inline unsigned nested_cpu_vmx_misc_cr3_count(struct kvm_vcpu *vcpu)
+{
+ return vmx_misc_cr3_count(to_vmx(vcpu)->nested.msrs.misc_low);
+}
+
+/*
+ * Do the virtual VMX capability MSRs specify that L1 can use VMWRITE
+ * to modify any valid field of the VMCS, or are the VM-exit
+ * information fields read-only?
+ */
+static inline bool nested_cpu_has_vmwrite_any_field(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.msrs.misc_low &
+ MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS;
+}
+
+static inline bool nested_cpu_has_zero_length_injection(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.msrs.misc_low & VMX_MISC_ZERO_LEN_INS;
+}
+
+static inline bool nested_cpu_supports_monitor_trap_flag(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.msrs.procbased_ctls_high &
+ CPU_BASED_MONITOR_TRAP_FLAG;
+}
+
+static inline bool nested_cpu_has_vmx_shadow_vmcs(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.msrs.secondary_ctls_high &
+ SECONDARY_EXEC_SHADOW_VMCS;
+}
+
+static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit)
+{
+ return vmcs12->cpu_based_vm_exec_control & bit;
+}
+
+static inline bool nested_cpu_has2(struct vmcs12 *vmcs12, u32 bit)
+{
+ return (vmcs12->cpu_based_vm_exec_control &
+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) &&
+ (vmcs12->secondary_vm_exec_control & bit);
+}
+
+static inline bool nested_cpu_has_preemption_timer(struct vmcs12 *vmcs12)
+{
+ return vmcs12->pin_based_vm_exec_control &
+ PIN_BASED_VMX_PREEMPTION_TIMER;
+}
+
+static inline bool nested_cpu_has_nmi_exiting(struct vmcs12 *vmcs12)
+{
+ return vmcs12->pin_based_vm_exec_control & PIN_BASED_NMI_EXITING;
+}
+
+static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12)
+{
+ return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
+}
+
+static inline int nested_cpu_has_ept(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT);
+}
+
+static inline bool nested_cpu_has_xsaves(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES);
+}
+
+static inline bool nested_cpu_has_pml(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_PML);
+}
+
+static inline bool nested_cpu_has_virt_x2apic_mode(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE);
+}
+
+static inline bool nested_cpu_has_vpid(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_VPID);
+}
+
+static inline bool nested_cpu_has_apic_reg_virt(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_APIC_REGISTER_VIRT);
+}
+
+static inline bool nested_cpu_has_vid(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
+}
+
+static inline bool nested_cpu_has_posted_intr(struct vmcs12 *vmcs12)
+{
+ return vmcs12->pin_based_vm_exec_control & PIN_BASED_POSTED_INTR;
+}
+
+static inline bool nested_cpu_has_vmfunc(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_VMFUNC);
+}
+
+static inline bool nested_cpu_has_eptp_switching(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has_vmfunc(vmcs12) &&
+ (vmcs12->vm_function_control &
+ VMX_VMFUNC_EPTP_SWITCHING);
+}
+
+static inline bool nested_cpu_has_shadow_vmcs(struct vmcs12 *vmcs12)
+{
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_SHADOW_VMCS);
+}
+
+static inline bool nested_cpu_has_save_preemption_timer(struct vmcs12 *vmcs12)
+{
+ return vmcs12->vm_exit_controls &
+ VM_EXIT_SAVE_VMX_PREEMPTION_TIMER;
+}
+
+static inline bool is_nmi(u32 intr_info)
+{
+ return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
+ == (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK);
+}
+
+static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
+ u32 exit_intr_info,
+ unsigned long exit_qualification);
+static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12,
+ u32 reason, unsigned long qualification);
+
+static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
+{
+ int i;
+
+ for (i = 0; i < vmx->nmsrs; ++i)
+ if (vmx_msr_index[vmx->guest_msrs[i].index] == msr)
+ return i;
+ return -1;
+}
+
+static inline void __invvpid(unsigned long ext, u16 vpid, gva_t gva)
+{
+ struct {
+ u64 vpid : 16;
+ u64 rsvd : 48;
+ u64 gva;
+ } operand = { vpid, 0, gva };
+ bool error;
+
+ asm volatile (__ex(ASM_VMX_INVVPID) CC_SET(na)
+ : CC_OUT(na) (error) : "a"(&operand), "c"(ext)
+ : "memory");
+ BUG_ON(error);
+}
+
+static inline void __invept(unsigned long ext, u64 eptp, gpa_t gpa)
+{
+ struct {
+ u64 eptp, gpa;
+ } operand = {eptp, gpa};
+ bool error;
+
+ asm volatile (__ex(ASM_VMX_INVEPT) CC_SET(na)
+ : CC_OUT(na) (error) : "a" (&operand), "c" (ext)
+ : "memory");
+ BUG_ON(error);
+}
+
+static void vmx_setup_fb_clear_ctrl(void)
+{
+ u64 msr;
+
+ if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES) &&
+ !boot_cpu_has_bug(X86_BUG_MDS) &&
+ !boot_cpu_has_bug(X86_BUG_TAA)) {
+ rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr);
+ if (msr & ARCH_CAP_FB_CLEAR_CTRL)
+ vmx_fb_clear_ctrl_available = true;
+ }
+}
+
+static __always_inline void vmx_disable_fb_clear(struct vcpu_vmx *vmx)
+{
+ u64 msr;
+
+ if (!vmx->disable_fb_clear)
+ return;
+
+ msr = __rdmsr(MSR_IA32_MCU_OPT_CTRL);
+ msr |= FB_CLEAR_DIS;
+ native_wrmsrl(MSR_IA32_MCU_OPT_CTRL, msr);
+ /* Cache the MSR value to avoid reading it later */
+ vmx->msr_ia32_mcu_opt_ctrl = msr;
+}
+
+static __always_inline void vmx_enable_fb_clear(struct vcpu_vmx *vmx)
+{
+ if (!vmx->disable_fb_clear)
+ return;
+
+ vmx->msr_ia32_mcu_opt_ctrl &= ~FB_CLEAR_DIS;
+ native_wrmsrl(MSR_IA32_MCU_OPT_CTRL, vmx->msr_ia32_mcu_opt_ctrl);
+}
+
+static void vmx_update_fb_clear_dis(struct kvm_vcpu *vcpu, struct vcpu_vmx *vmx)
+{
+ vmx->disable_fb_clear = vmx_fb_clear_ctrl_available;
+
+ /*
+ * If guest will not execute VERW, there is no need to set FB_CLEAR_DIS
+ * at VMEntry. Skip the MSR read/write when a guest has no use case to
+ * execute VERW.
+ */
+ if ((vcpu->arch.arch_capabilities & ARCH_CAP_FB_CLEAR) ||
+ ((vcpu->arch.arch_capabilities & ARCH_CAP_MDS_NO) &&
+ (vcpu->arch.arch_capabilities & ARCH_CAP_TAA_NO) &&
+ (vcpu->arch.arch_capabilities & ARCH_CAP_PSDP_NO) &&
+ (vcpu->arch.arch_capabilities & ARCH_CAP_FBSDP_NO) &&
+ (vcpu->arch.arch_capabilities & ARCH_CAP_SBDR_SSDP_NO)))
+ vmx->disable_fb_clear = false;
+}
+
+static struct shared_msr_entry *find_msr_entry(struct vcpu_vmx *vmx, u32 msr)
+{
+ int i;
+
+ i = __find_msr_index(vmx, msr);
+ if (i >= 0)
+ return &vmx->guest_msrs[i];
+ return NULL;
+}
+
+static void vmcs_clear(struct vmcs *vmcs)
+{
+ u64 phys_addr = __pa(vmcs);
+ bool error;
+
+ asm volatile (__ex(ASM_VMX_VMCLEAR_RAX) CC_SET(na)
+ : CC_OUT(na) (error) : "a"(&phys_addr), "m"(phys_addr)
+ : "memory");
+ if (unlikely(error))
+ printk(KERN_ERR "kvm: vmclear fail: %p/%llx\n",
+ vmcs, phys_addr);
+}
+
+static inline void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs)
+{
+ vmcs_clear(loaded_vmcs->vmcs);
+ if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched)
+ vmcs_clear(loaded_vmcs->shadow_vmcs);
+ loaded_vmcs->cpu = -1;
+ loaded_vmcs->launched = 0;
+}
+
+static void vmcs_load(struct vmcs *vmcs)
+{
+ u64 phys_addr = __pa(vmcs);
+ bool error;
+
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_load(phys_addr);
+
+ asm volatile (__ex(ASM_VMX_VMPTRLD_RAX) CC_SET(na)
+ : CC_OUT(na) (error) : "a"(&phys_addr), "m"(phys_addr)
+ : "memory");
+ if (unlikely(error))
+ printk(KERN_ERR "kvm: vmptrld %p/%llx failed\n",
+ vmcs, phys_addr);
+}
+
+#ifdef CONFIG_KEXEC_CORE
+static void crash_vmclear_local_loaded_vmcss(void)
+{
+ int cpu = raw_smp_processor_id();
+ struct loaded_vmcs *v;
+
+ list_for_each_entry(v, &per_cpu(loaded_vmcss_on_cpu, cpu),
+ loaded_vmcss_on_cpu_link)
+ vmcs_clear(v->vmcs);
+}
+#endif /* CONFIG_KEXEC_CORE */
+
+static void __loaded_vmcs_clear(void *arg)
+{
+ struct loaded_vmcs *loaded_vmcs = arg;
+ int cpu = raw_smp_processor_id();
+
+ if (loaded_vmcs->cpu != cpu)
+ return; /* vcpu migration can race with cpu offline */
+ if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs)
+ per_cpu(current_vmcs, cpu) = NULL;
+
+ vmcs_clear(loaded_vmcs->vmcs);
+ if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched)
+ vmcs_clear(loaded_vmcs->shadow_vmcs);
+
+ list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link);
+
+ /*
+ * Ensure all writes to loaded_vmcs, including deleting it from its
+ * current percpu list, complete before setting loaded_vmcs->vcpu to
+ * -1, otherwise a different cpu can see vcpu == -1 first and add
+ * loaded_vmcs to its percpu list before it's deleted from this cpu's
+ * list. Pairs with the smp_rmb() in vmx_vcpu_load_vmcs().
+ */
+ smp_wmb();
+
+ loaded_vmcs->cpu = -1;
+ loaded_vmcs->launched = 0;
+}
+
+static void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs)
+{
+ int cpu = loaded_vmcs->cpu;
+
+ if (cpu != -1)
+ smp_call_function_single(cpu,
+ __loaded_vmcs_clear, loaded_vmcs, 1);
+}
+
+static inline bool vpid_sync_vcpu_addr(int vpid, gva_t addr)
+{
+ if (vpid == 0)
+ return true;
+
+ if (cpu_has_vmx_invvpid_individual_addr()) {
+ __invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR, vpid, addr);
+ return true;
+ }
+
+ return false;
+}
+
+static inline void vpid_sync_vcpu_single(int vpid)
+{
+ if (vpid == 0)
+ return;
+
+ if (cpu_has_vmx_invvpid_single())
+ __invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vpid, 0);
+}
+
+static inline void vpid_sync_vcpu_global(void)
+{
+ if (cpu_has_vmx_invvpid_global())
+ __invvpid(VMX_VPID_EXTENT_ALL_CONTEXT, 0, 0);
+}
+
+static inline void vpid_sync_context(int vpid)
+{
+ if (cpu_has_vmx_invvpid_single())
+ vpid_sync_vcpu_single(vpid);
+ else
+ vpid_sync_vcpu_global();
+}
+
+static inline void ept_sync_global(void)
+{
+ __invept(VMX_EPT_EXTENT_GLOBAL, 0, 0);
+}
+
+static inline void ept_sync_context(u64 eptp)
+{
+ if (cpu_has_vmx_invept_context())
+ __invept(VMX_EPT_EXTENT_CONTEXT, eptp, 0);
+ else
+ ept_sync_global();
+}
+
+static __always_inline void vmcs_check16(unsigned long field)
+{
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2000,
+ "16-bit accessor invalid for 64-bit field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
+ "16-bit accessor invalid for 64-bit high field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
+ "16-bit accessor invalid for 32-bit high field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
+ "16-bit accessor invalid for natural width field");
+}
+
+static __always_inline void vmcs_check32(unsigned long field)
+{
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
+ "32-bit accessor invalid for 16-bit field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
+ "32-bit accessor invalid for natural width field");
+}
+
+static __always_inline void vmcs_check64(unsigned long field)
+{
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
+ "64-bit accessor invalid for 16-bit field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
+ "64-bit accessor invalid for 64-bit high field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
+ "64-bit accessor invalid for 32-bit field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
+ "64-bit accessor invalid for natural width field");
+}
+
+static __always_inline void vmcs_checkl(unsigned long field)
+{
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
+ "Natural width accessor invalid for 16-bit field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2000,
+ "Natural width accessor invalid for 64-bit field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
+ "Natural width accessor invalid for 64-bit high field");
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
+ "Natural width accessor invalid for 32-bit field");
+}
+
+static __always_inline unsigned long __vmcs_readl(unsigned long field)
+{
+ unsigned long value;
+
+ asm volatile (__ex_clear(ASM_VMX_VMREAD_RDX_RAX, "%0")
+ : "=a"(value) : "d"(field) : "cc");
+ return value;
+}
+
+static __always_inline u16 vmcs_read16(unsigned long field)
+{
+ vmcs_check16(field);
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_read16(field);
+ return __vmcs_readl(field);
+}
+
+static __always_inline u32 vmcs_read32(unsigned long field)
+{
+ vmcs_check32(field);
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_read32(field);
+ return __vmcs_readl(field);
+}
+
+static __always_inline u64 vmcs_read64(unsigned long field)
+{
+ vmcs_check64(field);
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_read64(field);
+#ifdef CONFIG_X86_64
+ return __vmcs_readl(field);
+#else
+ return __vmcs_readl(field) | ((u64)__vmcs_readl(field+1) << 32);
+#endif
+}
+
+static __always_inline unsigned long vmcs_readl(unsigned long field)
+{
+ vmcs_checkl(field);
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_read64(field);
+ return __vmcs_readl(field);
+}
+
+static noinline void vmwrite_error(unsigned long field, unsigned long value)
+{
+ printk(KERN_ERR "vmwrite error: reg %lx value %lx (err %d)\n",
+ field, value, vmcs_read32(VM_INSTRUCTION_ERROR));
+ dump_stack();
+}
+
+static __always_inline void __vmcs_writel(unsigned long field, unsigned long value)
+{
+ bool error;
+
+ asm volatile (__ex(ASM_VMX_VMWRITE_RAX_RDX) CC_SET(na)
+ : CC_OUT(na) (error) : "a"(value), "d"(field));
+ if (unlikely(error))
+ vmwrite_error(field, value);
+}
+
+static __always_inline void vmcs_write16(unsigned long field, u16 value)
+{
+ vmcs_check16(field);
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_write16(field, value);
+
+ __vmcs_writel(field, value);
+}
+
+static __always_inline void vmcs_write32(unsigned long field, u32 value)
+{
+ vmcs_check32(field);
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_write32(field, value);
+
+ __vmcs_writel(field, value);
+}
+
+static __always_inline void vmcs_write64(unsigned long field, u64 value)
+{
+ vmcs_check64(field);
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_write64(field, value);
+
+ __vmcs_writel(field, value);
+#ifndef CONFIG_X86_64
+ asm volatile ("");
+ __vmcs_writel(field+1, value >> 32);
+#endif
+}
+
+static __always_inline void vmcs_writel(unsigned long field, unsigned long value)
+{
+ vmcs_checkl(field);
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_write64(field, value);
+
+ __vmcs_writel(field, value);
+}
+
+static __always_inline void vmcs_clear_bits(unsigned long field, u32 mask)
+{
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
+ "vmcs_clear_bits does not support 64-bit fields");
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_write32(field, evmcs_read32(field) & ~mask);
+
+ __vmcs_writel(field, __vmcs_readl(field) & ~mask);
+}
+
+static __always_inline void vmcs_set_bits(unsigned long field, u32 mask)
+{
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
+ "vmcs_set_bits does not support 64-bit fields");
+ if (static_branch_unlikely(&enable_evmcs))
+ return evmcs_write32(field, evmcs_read32(field) | mask);
+
+ __vmcs_writel(field, __vmcs_readl(field) | mask);
+}
+
+static inline void vm_entry_controls_reset_shadow(struct vcpu_vmx *vmx)
+{
+ vmx->vm_entry_controls_shadow = vmcs_read32(VM_ENTRY_CONTROLS);
+}
+
+static inline void vm_entry_controls_init(struct vcpu_vmx *vmx, u32 val)
+{
+ vmcs_write32(VM_ENTRY_CONTROLS, val);
+ vmx->vm_entry_controls_shadow = val;
+}
+
+static inline void vm_entry_controls_set(struct vcpu_vmx *vmx, u32 val)
+{
+ if (vmx->vm_entry_controls_shadow != val)
+ vm_entry_controls_init(vmx, val);
+}
+
+static inline u32 vm_entry_controls_get(struct vcpu_vmx *vmx)
+{
+ return vmx->vm_entry_controls_shadow;
+}
+
+
+static inline void vm_entry_controls_setbit(struct vcpu_vmx *vmx, u32 val)
+{
+ vm_entry_controls_set(vmx, vm_entry_controls_get(vmx) | val);
+}
+
+static inline void vm_entry_controls_clearbit(struct vcpu_vmx *vmx, u32 val)
+{
+ vm_entry_controls_set(vmx, vm_entry_controls_get(vmx) & ~val);
+}
+
+static inline void vm_exit_controls_reset_shadow(struct vcpu_vmx *vmx)
+{
+ vmx->vm_exit_controls_shadow = vmcs_read32(VM_EXIT_CONTROLS);
+}
+
+static inline void vm_exit_controls_init(struct vcpu_vmx *vmx, u32 val)
+{
+ vmcs_write32(VM_EXIT_CONTROLS, val);
+ vmx->vm_exit_controls_shadow = val;
+}
+
+static inline void vm_exit_controls_set(struct vcpu_vmx *vmx, u32 val)
+{
+ if (vmx->vm_exit_controls_shadow != val)
+ vm_exit_controls_init(vmx, val);
+}
+
+static inline u32 vm_exit_controls_get(struct vcpu_vmx *vmx)
+{
+ return vmx->vm_exit_controls_shadow;
+}
+
+
+static inline void vm_exit_controls_setbit(struct vcpu_vmx *vmx, u32 val)
+{
+ vm_exit_controls_set(vmx, vm_exit_controls_get(vmx) | val);
+}
+
+static inline void vm_exit_controls_clearbit(struct vcpu_vmx *vmx, u32 val)
+{
+ vm_exit_controls_set(vmx, vm_exit_controls_get(vmx) & ~val);
+}
+
+static void vmx_segment_cache_clear(struct vcpu_vmx *vmx)
+{
+ vmx->segment_cache.bitmask = 0;
+}
+
+static bool vmx_segment_cache_test_set(struct vcpu_vmx *vmx, unsigned seg,
+ unsigned field)
+{
+ bool ret;
+ u32 mask = 1 << (seg * SEG_FIELD_NR + field);
+
+ if (!(vmx->vcpu.arch.regs_avail & (1 << VCPU_EXREG_SEGMENTS))) {
+ vmx->vcpu.arch.regs_avail |= (1 << VCPU_EXREG_SEGMENTS);
+ vmx->segment_cache.bitmask = 0;
+ }
+ ret = vmx->segment_cache.bitmask & mask;
+ vmx->segment_cache.bitmask |= mask;
+ return ret;
+}
+
+static u16 vmx_read_guest_seg_selector(struct vcpu_vmx *vmx, unsigned seg)
+{
+ u16 *p = &vmx->segment_cache.seg[seg].selector;
+
+ if (!vmx_segment_cache_test_set(vmx, seg, SEG_FIELD_SEL))
+ *p = vmcs_read16(kvm_vmx_segment_fields[seg].selector);
+ return *p;
+}
+
+static ulong vmx_read_guest_seg_base(struct vcpu_vmx *vmx, unsigned seg)
+{
+ ulong *p = &vmx->segment_cache.seg[seg].base;
+
+ if (!vmx_segment_cache_test_set(vmx, seg, SEG_FIELD_BASE))
+ *p = vmcs_readl(kvm_vmx_segment_fields[seg].base);
+ return *p;
+}
+
+static u32 vmx_read_guest_seg_limit(struct vcpu_vmx *vmx, unsigned seg)
+{
+ u32 *p = &vmx->segment_cache.seg[seg].limit;
+
+ if (!vmx_segment_cache_test_set(vmx, seg, SEG_FIELD_LIMIT))
+ *p = vmcs_read32(kvm_vmx_segment_fields[seg].limit);
+ return *p;
+}
+
+static u32 vmx_read_guest_seg_ar(struct vcpu_vmx *vmx, unsigned seg)
+{
+ u32 *p = &vmx->segment_cache.seg[seg].ar;
+
+ if (!vmx_segment_cache_test_set(vmx, seg, SEG_FIELD_AR))
+ *p = vmcs_read32(kvm_vmx_segment_fields[seg].ar_bytes);
+ return *p;
+}
+
+static void update_exception_bitmap(struct kvm_vcpu *vcpu)
+{
+ u32 eb;
+
+ eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
+ (1u << DB_VECTOR) | (1u << AC_VECTOR);
+ /*
+ * Guest access to VMware backdoor ports could legitimately
+ * trigger #GP because of TSS I/O permission bitmap.
+ * We intercept those #GP and allow access to them anyway
+ * as VMware does.
+ */
+ if (enable_vmware_backdoor)
+ eb |= (1u << GP_VECTOR);
+ if ((vcpu->guest_debug &
+ (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
+ (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP))
+ eb |= 1u << BP_VECTOR;
+ if (to_vmx(vcpu)->rmode.vm86_active)
+ eb = ~0;
+ if (enable_ept)
+ eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
+
+ /* When we are running a nested L2 guest and L1 specified for it a
+ * certain exception bitmap, we must trap the same exceptions and pass
+ * them to L1. When running L2, we will only handle the exceptions
+ * specified above if L1 did not want them.
+ */
+ if (is_guest_mode(vcpu))
+ eb |= get_vmcs12(vcpu)->exception_bitmap;
+
+ vmcs_write32(EXCEPTION_BITMAP, eb);
+}
+
+/*
+ * Check if MSR is intercepted for currently loaded MSR bitmap.
+ */
+static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr)
+{
+ unsigned long *msr_bitmap;
+ int f = sizeof(unsigned long);
+
+ if (!cpu_has_vmx_msr_bitmap())
+ return true;
+
+ msr_bitmap = to_vmx(vcpu)->loaded_vmcs->msr_bitmap;
+
+ if (msr <= 0x1fff) {
+ return !!test_bit(msr, msr_bitmap + 0x800 / f);
+ } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
+ msr &= 0x1fff;
+ return !!test_bit(msr, msr_bitmap + 0xc00 / f);
+ }
+
+ return true;
+}
+
+/*
+ * Check if MSR is intercepted for L01 MSR bitmap.
+ */
+static bool msr_write_intercepted_l01(struct kvm_vcpu *vcpu, u32 msr)
+{
+ unsigned long *msr_bitmap;
+ int f = sizeof(unsigned long);
+
+ if (!cpu_has_vmx_msr_bitmap())
+ return true;
+
+ msr_bitmap = to_vmx(vcpu)->vmcs01.msr_bitmap;
+
+ if (msr <= 0x1fff) {
+ return !!test_bit(msr, msr_bitmap + 0x800 / f);
+ } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
+ msr &= 0x1fff;
+ return !!test_bit(msr, msr_bitmap + 0xc00 / f);
+ }
+
+ return true;
+}
+
+static void clear_atomic_switch_msr_special(struct vcpu_vmx *vmx,
+ unsigned long entry, unsigned long exit)
+{
+ vm_entry_controls_clearbit(vmx, entry);
+ vm_exit_controls_clearbit(vmx, exit);
+}
+
+static int find_msr(struct vmx_msrs *m, unsigned int msr)
+{
+ unsigned int i;
+
+ for (i = 0; i < m->nr; ++i) {
+ if (m->val[i].index == msr)
+ return i;
+ }
+ return -ENOENT;
+}
+
+static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
+{
+ int i;
+ struct msr_autoload *m = &vmx->msr_autoload;
+
+ switch (msr) {
+ case MSR_EFER:
+ if (cpu_has_load_ia32_efer) {
+ clear_atomic_switch_msr_special(vmx,
+ VM_ENTRY_LOAD_IA32_EFER,
+ VM_EXIT_LOAD_IA32_EFER);
+ return;
+ }
+ break;
+ case MSR_CORE_PERF_GLOBAL_CTRL:
+ if (cpu_has_load_perf_global_ctrl) {
+ clear_atomic_switch_msr_special(vmx,
+ VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+ VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+ return;
+ }
+ break;
+ }
+ i = find_msr(&m->guest, msr);
+ if (i < 0)
+ goto skip_guest;
+ --m->guest.nr;
+ m->guest.val[i] = m->guest.val[m->guest.nr];
+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr);
+
+skip_guest:
+ i = find_msr(&m->host, msr);
+ if (i < 0)
+ return;
+
+ --m->host.nr;
+ m->host.val[i] = m->host.val[m->host.nr];
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr);
+}
+
+static void add_atomic_switch_msr_special(struct vcpu_vmx *vmx,
+ unsigned long entry, unsigned long exit,
+ unsigned long guest_val_vmcs, unsigned long host_val_vmcs,
+ u64 guest_val, u64 host_val)
+{
+ vmcs_write64(guest_val_vmcs, guest_val);
+ vmcs_write64(host_val_vmcs, host_val);
+ vm_entry_controls_setbit(vmx, entry);
+ vm_exit_controls_setbit(vmx, exit);
+}
+
+static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
+ u64 guest_val, u64 host_val, bool entry_only)
+{
+ int i, j = 0;
+ struct msr_autoload *m = &vmx->msr_autoload;
+
+ switch (msr) {
+ case MSR_EFER:
+ if (cpu_has_load_ia32_efer) {
+ add_atomic_switch_msr_special(vmx,
+ VM_ENTRY_LOAD_IA32_EFER,
+ VM_EXIT_LOAD_IA32_EFER,
+ GUEST_IA32_EFER,
+ HOST_IA32_EFER,
+ guest_val, host_val);
+ return;
+ }
+ break;
+ case MSR_CORE_PERF_GLOBAL_CTRL:
+ if (cpu_has_load_perf_global_ctrl) {
+ add_atomic_switch_msr_special(vmx,
+ VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+ VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL,
+ GUEST_IA32_PERF_GLOBAL_CTRL,
+ HOST_IA32_PERF_GLOBAL_CTRL,
+ guest_val, host_val);
+ return;
+ }
+ break;
+ case MSR_IA32_PEBS_ENABLE:
+ /* PEBS needs a quiescent period after being disabled (to write
+ * a record). Disabling PEBS through VMX MSR swapping doesn't
+ * provide that period, so a CPU could write host's record into
+ * guest's memory.
+ */
+ wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
+ }
+
+ i = find_msr(&m->guest, msr);
+ if (!entry_only)
+ j = find_msr(&m->host, msr);
+
+ if ((i < 0 && m->guest.nr == NR_AUTOLOAD_MSRS) ||
+ (j < 0 && m->host.nr == NR_AUTOLOAD_MSRS)) {
+ printk_once(KERN_WARNING "Not enough msr switch entries. "
+ "Can't add msr %x\n", msr);
+ return;
+ }
+ if (i < 0) {
+ i = m->guest.nr++;
+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr);
+ }
+ m->guest.val[i].index = msr;
+ m->guest.val[i].value = guest_val;
+
+ if (entry_only)
+ return;
+
+ if (j < 0) {
+ j = m->host.nr++;
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr);
+ }
+ m->host.val[j].index = msr;
+ m->host.val[j].value = host_val;
+}
+
+static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
+{
+ u64 guest_efer = vmx->vcpu.arch.efer;
+ u64 ignore_bits = 0;
+
+ /* Shadow paging assumes NX to be available. */
+ if (!enable_ept)
+ guest_efer |= EFER_NX;
+
+ /*
+ * LMA and LME handled by hardware; SCE meaningless outside long mode.
+ */
+ ignore_bits |= EFER_SCE;
+#ifdef CONFIG_X86_64
+ ignore_bits |= EFER_LMA | EFER_LME;
+ /* SCE is meaningful only in long mode on Intel */
+ if (guest_efer & EFER_LMA)
+ ignore_bits &= ~(u64)EFER_SCE;
+#endif
+
+ clear_atomic_switch_msr(vmx, MSR_EFER);
+
+ /*
+ * On EPT, we can't emulate NX, so we must switch EFER atomically.
+ * On CPUs that support "load IA32_EFER", always switch EFER
+ * atomically, since it's faster than switching it manually.
+ */
+ if (cpu_has_load_ia32_efer ||
+ (enable_ept && ((vmx->vcpu.arch.efer ^ host_efer) & EFER_NX))) {
+ if (!(guest_efer & EFER_LMA))
+ guest_efer &= ~EFER_LME;
+ if (guest_efer != host_efer)
+ add_atomic_switch_msr(vmx, MSR_EFER,
+ guest_efer, host_efer, false);
+ return false;
+ } else {
+ guest_efer &= ~ignore_bits;
+ guest_efer |= host_efer & ignore_bits;
+
+ vmx->guest_msrs[efer_offset].data = guest_efer;
+ vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
+
+ return true;
+ }
+}
+
+#ifdef CONFIG_X86_32
+/*
+ * On 32-bit kernels, VM exits still load the FS and GS bases from the
+ * VMCS rather than the segment table. KVM uses this helper to figure
+ * out the current bases to poke them into the VMCS before entry.
+ */
+static unsigned long segment_base(u16 selector)
+{
+ struct desc_struct *table;
+ unsigned long v;
+
+ if (!(selector & ~SEGMENT_RPL_MASK))
+ return 0;
+
+ table = get_current_gdt_ro();
+
+ if ((selector & SEGMENT_TI_MASK) == SEGMENT_LDT) {
+ u16 ldt_selector = kvm_read_ldt();
+
+ if (!(ldt_selector & ~SEGMENT_RPL_MASK))
+ return 0;
+
+ table = (struct desc_struct *)segment_base(ldt_selector);
+ }
+ v = get_desc_base(&table[selector >> 3]);
+ return v;
+}
+#endif
+
+static void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct vmcs_host_state *host_state;
+#ifdef CONFIG_X86_64
+ int cpu = raw_smp_processor_id();
+#endif
+ unsigned long fs_base, gs_base;
+ u16 fs_sel, gs_sel;
+ int i;
+
+ vmx->req_immediate_exit = false;
+
+ /*
+ * Note that guest MSRs to be saved/restored can also be changed
+ * when guest state is loaded. This happens when guest transitions
+ * to/from long-mode by setting MSR_EFER.LMA.
+ */
+ if (!vmx->loaded_cpu_state || vmx->guest_msrs_dirty) {
+ vmx->guest_msrs_dirty = false;
+ for (i = 0; i < vmx->save_nmsrs; ++i)
+ kvm_set_shared_msr(vmx->guest_msrs[i].index,
+ vmx->guest_msrs[i].data,
+ vmx->guest_msrs[i].mask);
+
+ }
+
+ if (vmx->loaded_cpu_state)
+ return;
+
+ vmx->loaded_cpu_state = vmx->loaded_vmcs;
+ host_state = &vmx->loaded_cpu_state->host_state;
+
+ /*
+ * Set host fs and gs selectors. Unfortunately, 22.2.3 does not
+ * allow segment selectors with cpl > 0 or ti == 1.
+ */
+ host_state->ldt_sel = kvm_read_ldt();
+
+#ifdef CONFIG_X86_64
+ savesegment(ds, host_state->ds_sel);
+ savesegment(es, host_state->es_sel);
+
+ gs_base = cpu_kernelmode_gs_base(cpu);
+ if (likely(is_64bit_mm(current->mm))) {
+ save_fsgs_for_kvm();
+ fs_sel = current->thread.fsindex;
+ gs_sel = current->thread.gsindex;
+ fs_base = current->thread.fsbase;
+ vmx->msr_host_kernel_gs_base = current->thread.gsbase;
+ } else {
+ savesegment(fs, fs_sel);
+ savesegment(gs, gs_sel);
+ fs_base = read_msr(MSR_FS_BASE);
+ vmx->msr_host_kernel_gs_base = read_msr(MSR_KERNEL_GS_BASE);
+ }
+
+ wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
+#else
+ savesegment(fs, fs_sel);
+ savesegment(gs, gs_sel);
+ fs_base = segment_base(fs_sel);
+ gs_base = segment_base(gs_sel);
+#endif
+
+ if (unlikely(fs_sel != host_state->fs_sel)) {
+ if (!(fs_sel & 7))
+ vmcs_write16(HOST_FS_SELECTOR, fs_sel);
+ else
+ vmcs_write16(HOST_FS_SELECTOR, 0);
+ host_state->fs_sel = fs_sel;
+ }
+ if (unlikely(gs_sel != host_state->gs_sel)) {
+ if (!(gs_sel & 7))
+ vmcs_write16(HOST_GS_SELECTOR, gs_sel);
+ else
+ vmcs_write16(HOST_GS_SELECTOR, 0);
+ host_state->gs_sel = gs_sel;
+ }
+ if (unlikely(fs_base != host_state->fs_base)) {
+ vmcs_writel(HOST_FS_BASE, fs_base);
+ host_state->fs_base = fs_base;
+ }
+ if (unlikely(gs_base != host_state->gs_base)) {
+ vmcs_writel(HOST_GS_BASE, gs_base);
+ host_state->gs_base = gs_base;
+ }
+}
+
+static void vmx_prepare_switch_to_host(struct vcpu_vmx *vmx)
+{
+ struct vmcs_host_state *host_state;
+
+ if (!vmx->loaded_cpu_state)
+ return;
+
+ WARN_ON_ONCE(vmx->loaded_cpu_state != vmx->loaded_vmcs);
+ host_state = &vmx->loaded_cpu_state->host_state;
+
+ ++vmx->vcpu.stat.host_state_reload;
+ vmx->loaded_cpu_state = NULL;
+
+#ifdef CONFIG_X86_64
+ rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
+#endif
+ if (host_state->ldt_sel || (host_state->gs_sel & 7)) {
+ kvm_load_ldt(host_state->ldt_sel);
+#ifdef CONFIG_X86_64
+ load_gs_index(host_state->gs_sel);
+#else
+ loadsegment(gs, host_state->gs_sel);
+#endif
+ }
+ if (host_state->fs_sel & 7)
+ loadsegment(fs, host_state->fs_sel);
+#ifdef CONFIG_X86_64
+ if (unlikely(host_state->ds_sel | host_state->es_sel)) {
+ loadsegment(ds, host_state->ds_sel);
+ loadsegment(es, host_state->es_sel);
+ }
+#endif
+ invalidate_tss_limit();
+#ifdef CONFIG_X86_64
+ wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
+#endif
+ load_fixmap_gdt(raw_smp_processor_id());
+}
+
+#ifdef CONFIG_X86_64
+static u64 vmx_read_guest_kernel_gs_base(struct vcpu_vmx *vmx)
+{
+ preempt_disable();
+ if (vmx->loaded_cpu_state)
+ rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base);
+ preempt_enable();
+ return vmx->msr_guest_kernel_gs_base;
+}
+
+static void vmx_write_guest_kernel_gs_base(struct vcpu_vmx *vmx, u64 data)
+{
+ preempt_disable();
+ if (vmx->loaded_cpu_state)
+ wrmsrl(MSR_KERNEL_GS_BASE, data);
+ preempt_enable();
+ vmx->msr_guest_kernel_gs_base = data;
+}
+#endif
+
+static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
+{
+ struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
+ struct pi_desc old, new;
+ unsigned int dest;
+
+ /*
+ * In case of hot-plug or hot-unplug, we may have to undo
+ * vmx_vcpu_pi_put even if there is no assigned device. And we
+ * always keep PI.NDST up to date for simplicity: it makes the
+ * code easier, and CPU migration is not a fast path.
+ */
+ if (!pi_test_sn(pi_desc) && vcpu->cpu == cpu)
+ return;
+
+ /*
+ * First handle the simple case where no cmpxchg is necessary; just
+ * allow posting non-urgent interrupts.
+ *
+ * If the 'nv' field is POSTED_INTR_WAKEUP_VECTOR, do not change
+ * PI.NDST: pi_post_block will do it for us and the wakeup_handler
+ * expects the VCPU to be on the blocked_vcpu_list that matches
+ * PI.NDST.
+ */
+ if (pi_desc->nv == POSTED_INTR_WAKEUP_VECTOR ||
+ vcpu->cpu == cpu) {
+ pi_clear_sn(pi_desc);
+ return;
+ }
+
+ /* The full case. */
+ do {
+ old.control = new.control = pi_desc->control;
+
+ dest = cpu_physical_id(cpu);
+
+ if (x2apic_enabled())
+ new.ndst = dest;
+ else
+ new.ndst = (dest << 8) & 0xFF00;
+
+ new.sn = 0;
+ } while (cmpxchg64(&pi_desc->control, old.control,
+ new.control) != old.control);
+}
+
+static void decache_tsc_multiplier(struct vcpu_vmx *vmx)
+{
+ vmx->current_tsc_ratio = vmx->vcpu.arch.tsc_scaling_ratio;
+ vmcs_write64(TSC_MULTIPLIER, vmx->current_tsc_ratio);
+}
+
+/*
+ * Switches to specified vcpu, until a matching vcpu_put(), but assumes
+ * vcpu mutex is already taken.
+ */
+static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ bool already_loaded = vmx->loaded_vmcs->cpu == cpu;
+
+ if (!already_loaded) {
+ loaded_vmcs_clear(vmx->loaded_vmcs);
+ local_irq_disable();
+
+ /*
+ * Ensure loaded_vmcs->cpu is read before adding loaded_vmcs to
+ * this cpu's percpu list, otherwise it may not yet be deleted
+ * from its previous cpu's percpu list. Pairs with the
+ * smb_wmb() in __loaded_vmcs_clear().
+ */
+ smp_rmb();
+
+ list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link,
+ &per_cpu(loaded_vmcss_on_cpu, cpu));
+ local_irq_enable();
+ }
+
+ if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) {
+ per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
+ vmcs_load(vmx->loaded_vmcs->vmcs);
+ indirect_branch_prediction_barrier();
+ }
+
+ if (!already_loaded) {
+ void *gdt = get_current_gdt_ro();
+ unsigned long sysenter_esp;
+
+ kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+
+ /*
+ * Linux uses per-cpu TSS and GDT, so set these when switching
+ * processors. See 22.2.4.
+ */
+ vmcs_writel(HOST_TR_BASE,
+ (unsigned long)&get_cpu_entry_area(cpu)->tss.x86_tss);
+ vmcs_writel(HOST_GDTR_BASE, (unsigned long)gdt); /* 22.2.4 */
+
+ /*
+ * VM exits change the host TR limit to 0x67 after a VM
+ * exit. This is okay, since 0x67 covers everything except
+ * the IO bitmap and have have code to handle the IO bitmap
+ * being lost after a VM exit.
+ */
+ BUILD_BUG_ON(IO_BITMAP_OFFSET - 1 != 0x67);
+
+ rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
+ vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+
+ vmx->loaded_vmcs->cpu = cpu;
+ }
+
+ /* Setup TSC multiplier */
+ if (kvm_has_tsc_control &&
+ vmx->current_tsc_ratio != vcpu->arch.tsc_scaling_ratio)
+ decache_tsc_multiplier(vmx);
+
+ vmx_vcpu_pi_load(vcpu, cpu);
+ vmx->host_pkru = read_pkru();
+ vmx->host_debugctlmsr = get_debugctlmsr();
+}
+
+static void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu)
+{
+ struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
+
+ if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
+ !irq_remapping_cap(IRQ_POSTING_CAP) ||
+ !kvm_vcpu_apicv_active(vcpu))
+ return;
+
+ /* Set SN when the vCPU is preempted */
+ if (vcpu->preempted)
+ pi_set_sn(pi_desc);
+}
+
+static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
+{
+ vmx_vcpu_pi_put(vcpu);
+
+ vmx_prepare_switch_to_host(to_vmx(vcpu));
+}
+
+static bool emulation_required(struct kvm_vcpu *vcpu)
+{
+ return emulate_invalid_guest_state && !guest_state_valid(vcpu);
+}
+
+static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu);
+
+/*
+ * Return the cr0 value that a nested guest would read. This is a combination
+ * of the real cr0 used to run the guest (guest_cr0), and the bits shadowed by
+ * its hypervisor (cr0_read_shadow).
+ */
+static inline unsigned long nested_read_cr0(struct vmcs12 *fields)
+{
+ return (fields->guest_cr0 & ~fields->cr0_guest_host_mask) |
+ (fields->cr0_read_shadow & fields->cr0_guest_host_mask);
+}
+static inline unsigned long nested_read_cr4(struct vmcs12 *fields)
+{
+ return (fields->guest_cr4 & ~fields->cr4_guest_host_mask) |
+ (fields->cr4_read_shadow & fields->cr4_guest_host_mask);
+}
+
+static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
+{
+ unsigned long rflags, save_rflags;
+
+ if (!test_bit(VCPU_EXREG_RFLAGS, (ulong *)&vcpu->arch.regs_avail)) {
+ __set_bit(VCPU_EXREG_RFLAGS, (ulong *)&vcpu->arch.regs_avail);
+ rflags = vmcs_readl(GUEST_RFLAGS);
+ if (to_vmx(vcpu)->rmode.vm86_active) {
+ rflags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
+ save_rflags = to_vmx(vcpu)->rmode.save_rflags;
+ rflags |= save_rflags & ~RMODE_GUEST_OWNED_EFLAGS_BITS;
+ }
+ to_vmx(vcpu)->rflags = rflags;
+ }
+ return to_vmx(vcpu)->rflags;
+}
+
+static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
+{
+ unsigned long old_rflags = vmx_get_rflags(vcpu);
+
+ __set_bit(VCPU_EXREG_RFLAGS, (ulong *)&vcpu->arch.regs_avail);
+ to_vmx(vcpu)->rflags = rflags;
+ if (to_vmx(vcpu)->rmode.vm86_active) {
+ to_vmx(vcpu)->rmode.save_rflags = rflags;
+ rflags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM;
+ }
+ vmcs_writel(GUEST_RFLAGS, rflags);
+
+ if ((old_rflags ^ to_vmx(vcpu)->rflags) & X86_EFLAGS_VM)
+ to_vmx(vcpu)->emulation_required = emulation_required(vcpu);
+}
+
+static u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu)
+{
+ u32 interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+ int ret = 0;
+
+ if (interruptibility & GUEST_INTR_STATE_STI)
+ ret |= KVM_X86_SHADOW_INT_STI;
+ if (interruptibility & GUEST_INTR_STATE_MOV_SS)
+ ret |= KVM_X86_SHADOW_INT_MOV_SS;
+
+ return ret;
+}
+
+static void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+{
+ u32 interruptibility_old = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+ u32 interruptibility = interruptibility_old;
+
+ interruptibility &= ~(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS);
+
+ if (mask & KVM_X86_SHADOW_INT_MOV_SS)
+ interruptibility |= GUEST_INTR_STATE_MOV_SS;
+ else if (mask & KVM_X86_SHADOW_INT_STI)
+ interruptibility |= GUEST_INTR_STATE_STI;
+
+ if ((interruptibility != interruptibility_old))
+ vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, interruptibility);
+}
+
+static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+ unsigned long rip;
+
+ rip = kvm_rip_read(vcpu);
+ rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+ kvm_rip_write(vcpu, rip);
+
+ /* skipping an emulated instruction also counts */
+ vmx_set_interrupt_shadow(vcpu, 0);
+}
+
+static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu,
+ unsigned long exit_qual)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ unsigned int nr = vcpu->arch.exception.nr;
+ u32 intr_info = nr | INTR_INFO_VALID_MASK;
+
+ if (vcpu->arch.exception.has_error_code) {
+ vmcs12->vm_exit_intr_error_code = vcpu->arch.exception.error_code;
+ intr_info |= INTR_INFO_DELIVER_CODE_MASK;
+ }
+
+ if (kvm_exception_is_soft(nr))
+ intr_info |= INTR_TYPE_SOFT_EXCEPTION;
+ else
+ intr_info |= INTR_TYPE_HARD_EXCEPTION;
+
+ if (!(vmcs12->idt_vectoring_info_field & VECTORING_INFO_VALID_MASK) &&
+ vmx_get_nmi_mask(vcpu))
+ intr_info |= INTR_INFO_UNBLOCK_NMI;
+
+ nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, intr_info, exit_qual);
+}
+
+/*
+ * KVM wants to inject page-faults which it got to the guest. This function
+ * checks whether in a nested guest, we need to inject them to L1 or L2.
+ */
+static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned long *exit_qual)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ unsigned int nr = vcpu->arch.exception.nr;
+
+ if (nr == PF_VECTOR) {
+ if (vcpu->arch.exception.nested_apf) {
+ *exit_qual = vcpu->arch.apf.nested_apf_token;
+ return 1;
+ }
+ /*
+ * FIXME: we must not write CR2 when L1 intercepts an L2 #PF exception.
+ * The fix is to add the ancillary datum (CR2 or DR6) to structs
+ * kvm_queued_exception and kvm_vcpu_events, so that CR2 and DR6
+ * can be written only when inject_pending_event runs. This should be
+ * conditional on a new capability---if the capability is disabled,
+ * kvm_multiple_exception would write the ancillary information to
+ * CR2 or DR6, for backwards ABI-compatibility.
+ */
+ if (nested_vmx_is_page_fault_vmexit(vmcs12,
+ vcpu->arch.exception.error_code)) {
+ *exit_qual = vcpu->arch.cr2;
+ return 1;
+ }
+ } else {
+ if (vmcs12->exception_bitmap & (1u << nr)) {
+ if (nr == DB_VECTOR) {
+ *exit_qual = vcpu->arch.dr6;
+ *exit_qual &= ~(DR6_FIXED_1 | DR6_BT);
+ *exit_qual ^= DR6_RTM;
+ } else {
+ *exit_qual = 0;
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
+{
+ /*
+ * Ensure that we clear the HLT state in the VMCS. We don't need to
+ * explicitly skip the instruction because if the HLT state is set,
+ * then the instruction is already executing and RIP has already been
+ * advanced.
+ */
+ if (kvm_hlt_in_guest(vcpu->kvm) &&
+ vmcs_read32(GUEST_ACTIVITY_STATE) == GUEST_ACTIVITY_HLT)
+ vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
+}
+
+static void vmx_queue_exception(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ unsigned nr = vcpu->arch.exception.nr;
+ bool has_error_code = vcpu->arch.exception.has_error_code;
+ u32 error_code = vcpu->arch.exception.error_code;
+ u32 intr_info = nr | INTR_INFO_VALID_MASK;
+
+ if (has_error_code) {
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+ intr_info |= INTR_INFO_DELIVER_CODE_MASK;
+ }
+
+ if (vmx->rmode.vm86_active) {
+ int inc_eip = 0;
+ if (kvm_exception_is_soft(nr))
+ inc_eip = vcpu->arch.event_exit_inst_len;
+ if (kvm_inject_realmode_interrupt(vcpu, nr, inc_eip) != EMULATE_DONE)
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+ return;
+ }
+
+ WARN_ON_ONCE(vmx->emulation_required);
+
+ if (kvm_exception_is_soft(nr)) {
+ vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+ vmx->vcpu.arch.event_exit_inst_len);
+ intr_info |= INTR_TYPE_SOFT_EXCEPTION;
+ } else
+ intr_info |= INTR_TYPE_HARD_EXCEPTION;
+
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
+
+ vmx_clear_hlt(vcpu);
+}
+
+static bool vmx_rdtscp_supported(void)
+{
+ return cpu_has_vmx_rdtscp();
+}
+
+static bool vmx_invpcid_supported(void)
+{
+ return cpu_has_vmx_invpcid();
+}
+
+/*
+ * Swap MSR entry in host/guest MSR entry array.
+ */
+static void move_msr_up(struct vcpu_vmx *vmx, int from, int to)
+{
+ struct shared_msr_entry tmp;
+
+ tmp = vmx->guest_msrs[to];
+ vmx->guest_msrs[to] = vmx->guest_msrs[from];
+ vmx->guest_msrs[from] = tmp;
+}
+
+/*
+ * Set up the vmcs to automatically save and restore system
+ * msrs. Don't touch the 64-bit msrs if the guest is in legacy
+ * mode, as fiddling with msrs is very expensive.
+ */
+static void setup_msrs(struct vcpu_vmx *vmx)
+{
+ int save_nmsrs, index;
+
+ save_nmsrs = 0;
+#ifdef CONFIG_X86_64
+ if (is_long_mode(&vmx->vcpu)) {
+ index = __find_msr_index(vmx, MSR_SYSCALL_MASK);
+ if (index >= 0)
+ move_msr_up(vmx, index, save_nmsrs++);
+ index = __find_msr_index(vmx, MSR_LSTAR);
+ if (index >= 0)
+ move_msr_up(vmx, index, save_nmsrs++);
+ index = __find_msr_index(vmx, MSR_CSTAR);
+ if (index >= 0)
+ move_msr_up(vmx, index, save_nmsrs++);
+ /*
+ * MSR_STAR is only needed on long mode guests, and only
+ * if efer.sce is enabled.
+ */
+ index = __find_msr_index(vmx, MSR_STAR);
+ if ((index >= 0) && (vmx->vcpu.arch.efer & EFER_SCE))
+ move_msr_up(vmx, index, save_nmsrs++);
+ }
+#endif
+ index = __find_msr_index(vmx, MSR_EFER);
+ if (index >= 0 && update_transition_efer(vmx, index))
+ move_msr_up(vmx, index, save_nmsrs++);
+ index = __find_msr_index(vmx, MSR_TSC_AUX);
+ if (index >= 0 && guest_cpuid_has(&vmx->vcpu, X86_FEATURE_RDTSCP))
+ move_msr_up(vmx, index, save_nmsrs++);
+
+ vmx->save_nmsrs = save_nmsrs;
+ vmx->guest_msrs_dirty = true;
+
+ if (cpu_has_vmx_msr_bitmap())
+ vmx_update_msr_bitmap(&vmx->vcpu);
+}
+
+static u64 vmx_read_l1_tsc_offset(struct kvm_vcpu *vcpu)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+ if (is_guest_mode(vcpu) &&
+ (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING))
+ return vcpu->arch.tsc_offset - vmcs12->tsc_offset;
+
+ return vcpu->arch.tsc_offset;
+}
+
+static u64 vmx_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
+{
+ u64 active_offset = offset;
+ if (is_guest_mode(vcpu)) {
+ /*
+ * We're here if L1 chose not to trap WRMSR to TSC. According
+ * to the spec, this should set L1's TSC; The offset that L1
+ * set for L2 remains unchanged, and still needs to be added
+ * to the newly set TSC to get L2's TSC.
+ */
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ if (nested_cpu_has(vmcs12, CPU_BASED_USE_TSC_OFFSETING))
+ active_offset += vmcs12->tsc_offset;
+ } else {
+ trace_kvm_write_tsc_offset(vcpu->vcpu_id,
+ vmcs_read64(TSC_OFFSET), offset);
+ }
+
+ vmcs_write64(TSC_OFFSET, active_offset);
+ return active_offset;
+}
+
+/*
+ * nested_vmx_allowed() checks whether a guest should be allowed to use VMX
+ * instructions and MSRs (i.e., nested VMX). Nested VMX is disabled for
+ * all guests if the "nested" module option is off, and can also be disabled
+ * for a single guest by disabling its VMX cpuid bit.
+ */
+static inline bool nested_vmx_allowed(struct kvm_vcpu *vcpu)
+{
+ return nested && guest_cpuid_has(vcpu, X86_FEATURE_VMX);
+}
+
+/*
+ * nested_vmx_setup_ctls_msrs() sets up variables containing the values to be
+ * returned for the various VMX controls MSRs when nested VMX is enabled.
+ * The same values should also be used to verify that vmcs12 control fields are
+ * valid during nested entry from L1 to L2.
+ * Each of these control msrs has a low and high 32-bit half: A low bit is on
+ * if the corresponding bit in the (32-bit) control field *must* be on, and a
+ * bit in the high half is on if the corresponding bit in the control field
+ * may be on. See also vmx_control_verify().
+ */
+static void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, bool apicv)
+{
+ if (!nested) {
+ memset(msrs, 0, sizeof(*msrs));
+ return;
+ }
+
+ /*
+ * Note that as a general rule, the high half of the MSRs (bits in
+ * the control fields which may be 1) should be initialized by the
+ * intersection of the underlying hardware's MSR (i.e., features which
+ * can be supported) and the list of features we want to expose -
+ * because they are known to be properly supported in our code.
+ * Also, usually, the low half of the MSRs (bits which must be 1) can
+ * be set to 0, meaning that L1 may turn off any of these bits. The
+ * reason is that if one of these bits is necessary, it will appear
+ * in vmcs01 and prepare_vmcs02, when it bitwise-or's the control
+ * fields of vmcs01 and vmcs02, will turn these bits off - and
+ * nested_vmx_exit_reflected() will not pass related exits to L1.
+ * These rules have exceptions below.
+ */
+
+ /* pin-based controls */
+ rdmsr(MSR_IA32_VMX_PINBASED_CTLS,
+ msrs->pinbased_ctls_low,
+ msrs->pinbased_ctls_high);
+ msrs->pinbased_ctls_low |=
+ PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
+ msrs->pinbased_ctls_high &=
+ PIN_BASED_EXT_INTR_MASK |
+ PIN_BASED_NMI_EXITING |
+ PIN_BASED_VIRTUAL_NMIS |
+ (apicv ? PIN_BASED_POSTED_INTR : 0);
+ msrs->pinbased_ctls_high |=
+ PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
+ PIN_BASED_VMX_PREEMPTION_TIMER;
+
+ /* exit controls */
+ rdmsr(MSR_IA32_VMX_EXIT_CTLS,
+ msrs->exit_ctls_low,
+ msrs->exit_ctls_high);
+ msrs->exit_ctls_low =
+ VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
+
+ msrs->exit_ctls_high &=
+#ifdef CONFIG_X86_64
+ VM_EXIT_HOST_ADDR_SPACE_SIZE |
+#endif
+ VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT;
+ msrs->exit_ctls_high |=
+ VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |
+ VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER |
+ VM_EXIT_SAVE_VMX_PREEMPTION_TIMER | VM_EXIT_ACK_INTR_ON_EXIT;
+
+ /* We support free control of debug control saving. */
+ msrs->exit_ctls_low &= ~VM_EXIT_SAVE_DEBUG_CONTROLS;
+
+ /* entry controls */
+ rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
+ msrs->entry_ctls_low,
+ msrs->entry_ctls_high);
+ msrs->entry_ctls_low =
+ VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
+ msrs->entry_ctls_high &=
+#ifdef CONFIG_X86_64
+ VM_ENTRY_IA32E_MODE |
+#endif
+ VM_ENTRY_LOAD_IA32_PAT;
+ msrs->entry_ctls_high |=
+ (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | VM_ENTRY_LOAD_IA32_EFER);
+
+ /* We support free control of debug control loading. */
+ msrs->entry_ctls_low &= ~VM_ENTRY_LOAD_DEBUG_CONTROLS;
+
+ /* cpu-based controls */
+ rdmsr(MSR_IA32_VMX_PROCBASED_CTLS,
+ msrs->procbased_ctls_low,
+ msrs->procbased_ctls_high);
+ msrs->procbased_ctls_low =
+ CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
+ msrs->procbased_ctls_high &=
+ CPU_BASED_VIRTUAL_INTR_PENDING |
+ CPU_BASED_VIRTUAL_NMI_PENDING | CPU_BASED_USE_TSC_OFFSETING |
+ CPU_BASED_HLT_EXITING | CPU_BASED_INVLPG_EXITING |
+ CPU_BASED_MWAIT_EXITING | CPU_BASED_CR3_LOAD_EXITING |
+ CPU_BASED_CR3_STORE_EXITING |
+#ifdef CONFIG_X86_64
+ CPU_BASED_CR8_LOAD_EXITING | CPU_BASED_CR8_STORE_EXITING |
+#endif
+ CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING |
+ CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_TRAP_FLAG |
+ CPU_BASED_MONITOR_EXITING | CPU_BASED_RDPMC_EXITING |
+ CPU_BASED_RDTSC_EXITING | CPU_BASED_PAUSE_EXITING |
+ CPU_BASED_TPR_SHADOW | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+ /*
+ * We can allow some features even when not supported by the
+ * hardware. For example, L1 can specify an MSR bitmap - and we
+ * can use it to avoid exits to L1 - even when L0 runs L2
+ * without MSR bitmaps.
+ */
+ msrs->procbased_ctls_high |=
+ CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
+ CPU_BASED_USE_MSR_BITMAPS;
+
+ /* We support free control of CR3 access interception. */
+ msrs->procbased_ctls_low &=
+ ~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING);
+
+ /*
+ * secondary cpu-based controls. Do not include those that
+ * depend on CPUID bits, they are added later by vmx_cpuid_update.
+ */
+ if (msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
+ rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
+ msrs->secondary_ctls_low,
+ msrs->secondary_ctls_high);
+
+ msrs->secondary_ctls_low = 0;
+ msrs->secondary_ctls_high &=
+ SECONDARY_EXEC_DESC |
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
+ SECONDARY_EXEC_APIC_REGISTER_VIRT |
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
+ SECONDARY_EXEC_WBINVD_EXITING;
+
+ /*
+ * We can emulate "VMCS shadowing," even if the hardware
+ * doesn't support it.
+ */
+ msrs->secondary_ctls_high |=
+ SECONDARY_EXEC_SHADOW_VMCS;
+
+ if (enable_ept) {
+ /* nested EPT: emulate EPT also to L1 */
+ msrs->secondary_ctls_high |=
+ SECONDARY_EXEC_ENABLE_EPT;
+ msrs->ept_caps = VMX_EPT_PAGE_WALK_4_BIT |
+ VMX_EPTP_WB_BIT | VMX_EPT_INVEPT_BIT;
+ if (cpu_has_vmx_ept_execute_only())
+ msrs->ept_caps |=
+ VMX_EPT_EXECUTE_ONLY_BIT;
+ msrs->ept_caps &= vmx_capability.ept;
+ msrs->ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT |
+ VMX_EPT_EXTENT_CONTEXT_BIT | VMX_EPT_2MB_PAGE_BIT |
+ VMX_EPT_1GB_PAGE_BIT;
+ if (enable_ept_ad_bits) {
+ msrs->secondary_ctls_high |=
+ SECONDARY_EXEC_ENABLE_PML;
+ msrs->ept_caps |= VMX_EPT_AD_BIT;
+ }
+ }
+
+ if (cpu_has_vmx_vmfunc()) {
+ msrs->secondary_ctls_high |=
+ SECONDARY_EXEC_ENABLE_VMFUNC;
+ /*
+ * Advertise EPTP switching unconditionally
+ * since we emulate it
+ */
+ if (enable_ept)
+ msrs->vmfunc_controls =
+ VMX_VMFUNC_EPTP_SWITCHING;
+ }
+
+ /*
+ * Old versions of KVM use the single-context version without
+ * checking for support, so declare that it is supported even
+ * though it is treated as global context. The alternative is
+ * not failing the single-context invvpid, and it is worse.
+ */
+ if (enable_vpid) {
+ msrs->secondary_ctls_high |=
+ SECONDARY_EXEC_ENABLE_VPID;
+ msrs->vpid_caps = VMX_VPID_INVVPID_BIT |
+ VMX_VPID_EXTENT_SUPPORTED_MASK;
+ }
+
+ if (enable_unrestricted_guest)
+ msrs->secondary_ctls_high |=
+ SECONDARY_EXEC_UNRESTRICTED_GUEST;
+
+ if (flexpriority_enabled)
+ msrs->secondary_ctls_high |=
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+
+ /* miscellaneous data */
+ rdmsr(MSR_IA32_VMX_MISC,
+ msrs->misc_low,
+ msrs->misc_high);
+ msrs->misc_low &= VMX_MISC_SAVE_EFER_LMA;
+ msrs->misc_low |=
+ MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS |
+ VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE |
+ VMX_MISC_ACTIVITY_HLT;
+ msrs->misc_high = 0;
+
+ /*
+ * This MSR reports some information about VMX support. We
+ * should return information about the VMX we emulate for the
+ * guest, and the VMCS structure we give it - not about the
+ * VMX support of the underlying hardware.
+ */
+ msrs->basic =
+ VMCS12_REVISION |
+ VMX_BASIC_TRUE_CTLS |
+ ((u64)VMCS12_SIZE << VMX_BASIC_VMCS_SIZE_SHIFT) |
+ (VMX_BASIC_MEM_TYPE_WB << VMX_BASIC_MEM_TYPE_SHIFT);
+
+ if (cpu_has_vmx_basic_inout())
+ msrs->basic |= VMX_BASIC_INOUT;
+
+ /*
+ * These MSRs specify bits which the guest must keep fixed on
+ * while L1 is in VMXON mode (in L1's root mode, or running an L2).
+ * We picked the standard core2 setting.
+ */
+#define VMXON_CR0_ALWAYSON (X86_CR0_PE | X86_CR0_PG | X86_CR0_NE)
+#define VMXON_CR4_ALWAYSON X86_CR4_VMXE
+ msrs->cr0_fixed0 = VMXON_CR0_ALWAYSON;
+ msrs->cr4_fixed0 = VMXON_CR4_ALWAYSON;
+
+ /* These MSRs specify bits which the guest must keep fixed off. */
+ rdmsrl(MSR_IA32_VMX_CR0_FIXED1, msrs->cr0_fixed1);
+ rdmsrl(MSR_IA32_VMX_CR4_FIXED1, msrs->cr4_fixed1);
+
+ /* highest index: VMX_PREEMPTION_TIMER_VALUE */
+ msrs->vmcs_enum = VMCS12_MAX_FIELD_INDEX << 1;
+}
+
+/*
+ * if fixed0[i] == 1: val[i] must be 1
+ * if fixed1[i] == 0: val[i] must be 0
+ */
+static inline bool fixed_bits_valid(u64 val, u64 fixed0, u64 fixed1)
+{
+ return ((val & fixed1) | fixed0) == val;
+}
+
+static inline bool vmx_control_verify(u32 control, u32 low, u32 high)
+{
+ return fixed_bits_valid(control, low, high);
+}
+
+static inline u64 vmx_control_msr(u32 low, u32 high)
+{
+ return low | ((u64)high << 32);
+}
+
+static bool is_bitwise_subset(u64 superset, u64 subset, u64 mask)
+{
+ superset &= mask;
+ subset &= mask;
+
+ return (superset | subset) == superset;
+}
+
+static int vmx_restore_vmx_basic(struct vcpu_vmx *vmx, u64 data)
+{
+ const u64 feature_and_reserved =
+ /* feature (except bit 48; see below) */
+ BIT_ULL(49) | BIT_ULL(54) | BIT_ULL(55) |
+ /* reserved */
+ BIT_ULL(31) | GENMASK_ULL(47, 45) | GENMASK_ULL(63, 56);
+ u64 vmx_basic = vmx->nested.msrs.basic;
+
+ if (!is_bitwise_subset(vmx_basic, data, feature_and_reserved))
+ return -EINVAL;
+
+ /*
+ * KVM does not emulate a version of VMX that constrains physical
+ * addresses of VMX structures (e.g. VMCS) to 32-bits.
+ */
+ if (data & BIT_ULL(48))
+ return -EINVAL;
+
+ if (vmx_basic_vmcs_revision_id(vmx_basic) !=
+ vmx_basic_vmcs_revision_id(data))
+ return -EINVAL;
+
+ if (vmx_basic_vmcs_size(vmx_basic) > vmx_basic_vmcs_size(data))
+ return -EINVAL;
+
+ vmx->nested.msrs.basic = data;
+ return 0;
+}
+
+static int
+vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
+{
+ u64 supported;
+ u32 *lowp, *highp;
+
+ switch (msr_index) {
+ case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
+ lowp = &vmx->nested.msrs.pinbased_ctls_low;
+ highp = &vmx->nested.msrs.pinbased_ctls_high;
+ break;
+ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
+ lowp = &vmx->nested.msrs.procbased_ctls_low;
+ highp = &vmx->nested.msrs.procbased_ctls_high;
+ break;
+ case MSR_IA32_VMX_TRUE_EXIT_CTLS:
+ lowp = &vmx->nested.msrs.exit_ctls_low;
+ highp = &vmx->nested.msrs.exit_ctls_high;
+ break;
+ case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+ lowp = &vmx->nested.msrs.entry_ctls_low;
+ highp = &vmx->nested.msrs.entry_ctls_high;
+ break;
+ case MSR_IA32_VMX_PROCBASED_CTLS2:
+ lowp = &vmx->nested.msrs.secondary_ctls_low;
+ highp = &vmx->nested.msrs.secondary_ctls_high;
+ break;
+ default:
+ BUG();
+ }
+
+ supported = vmx_control_msr(*lowp, *highp);
+
+ /* Check must-be-1 bits are still 1. */
+ if (!is_bitwise_subset(data, supported, GENMASK_ULL(31, 0)))
+ return -EINVAL;
+
+ /* Check must-be-0 bits are still 0. */
+ if (!is_bitwise_subset(supported, data, GENMASK_ULL(63, 32)))
+ return -EINVAL;
+
+ *lowp = data;
+ *highp = data >> 32;
+ return 0;
+}
+
+static int vmx_restore_vmx_misc(struct vcpu_vmx *vmx, u64 data)
+{
+ const u64 feature_and_reserved_bits =
+ /* feature */
+ BIT_ULL(5) | GENMASK_ULL(8, 6) | BIT_ULL(14) | BIT_ULL(15) |
+ BIT_ULL(28) | BIT_ULL(29) | BIT_ULL(30) |
+ /* reserved */
+ GENMASK_ULL(13, 9) | BIT_ULL(31);
+ u64 vmx_misc;
+
+ vmx_misc = vmx_control_msr(vmx->nested.msrs.misc_low,
+ vmx->nested.msrs.misc_high);
+
+ if (!is_bitwise_subset(vmx_misc, data, feature_and_reserved_bits))
+ return -EINVAL;
+
+ if ((vmx->nested.msrs.pinbased_ctls_high &
+ PIN_BASED_VMX_PREEMPTION_TIMER) &&
+ vmx_misc_preemption_timer_rate(data) !=
+ vmx_misc_preemption_timer_rate(vmx_misc))
+ return -EINVAL;
+
+ if (vmx_misc_cr3_count(data) > vmx_misc_cr3_count(vmx_misc))
+ return -EINVAL;
+
+ if (vmx_misc_max_msr(data) > vmx_misc_max_msr(vmx_misc))
+ return -EINVAL;
+
+ if (vmx_misc_mseg_revid(data) != vmx_misc_mseg_revid(vmx_misc))
+ return -EINVAL;
+
+ vmx->nested.msrs.misc_low = data;
+ vmx->nested.msrs.misc_high = data >> 32;
+
+ /*
+ * If L1 has read-only VM-exit information fields, use the
+ * less permissive vmx_vmwrite_bitmap to specify write
+ * permissions for the shadow VMCS.
+ */
+ if (enable_shadow_vmcs && !nested_cpu_has_vmwrite_any_field(&vmx->vcpu))
+ vmcs_write64(VMWRITE_BITMAP, __pa(vmx_vmwrite_bitmap));
+
+ return 0;
+}
+
+static int vmx_restore_vmx_ept_vpid_cap(struct vcpu_vmx *vmx, u64 data)
+{
+ u64 vmx_ept_vpid_cap;
+
+ vmx_ept_vpid_cap = vmx_control_msr(vmx->nested.msrs.ept_caps,
+ vmx->nested.msrs.vpid_caps);
+
+ /* Every bit is either reserved or a feature bit. */
+ if (!is_bitwise_subset(vmx_ept_vpid_cap, data, -1ULL))
+ return -EINVAL;
+
+ vmx->nested.msrs.ept_caps = data;
+ vmx->nested.msrs.vpid_caps = data >> 32;
+ return 0;
+}
+
+static int vmx_restore_fixed0_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
+{
+ u64 *msr;
+
+ switch (msr_index) {
+ case MSR_IA32_VMX_CR0_FIXED0:
+ msr = &vmx->nested.msrs.cr0_fixed0;
+ break;
+ case MSR_IA32_VMX_CR4_FIXED0:
+ msr = &vmx->nested.msrs.cr4_fixed0;
+ break;
+ default:
+ BUG();
+ }
+
+ /*
+ * 1 bits (which indicates bits which "must-be-1" during VMX operation)
+ * must be 1 in the restored value.
+ */
+ if (!is_bitwise_subset(data, *msr, -1ULL))
+ return -EINVAL;
+
+ *msr = data;
+ return 0;
+}
+
+/*
+ * Called when userspace is restoring VMX MSRs.
+ *
+ * Returns 0 on success, non-0 otherwise.
+ */
+static int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ /*
+ * Don't allow changes to the VMX capability MSRs while the vCPU
+ * is in VMX operation.
+ */
+ if (vmx->nested.vmxon)
+ return -EBUSY;
+
+ switch (msr_index) {
+ case MSR_IA32_VMX_BASIC:
+ return vmx_restore_vmx_basic(vmx, data);
+ case MSR_IA32_VMX_PINBASED_CTLS:
+ case MSR_IA32_VMX_PROCBASED_CTLS:
+ case MSR_IA32_VMX_EXIT_CTLS:
+ case MSR_IA32_VMX_ENTRY_CTLS:
+ /*
+ * The "non-true" VMX capability MSRs are generated from the
+ * "true" MSRs, so we do not support restoring them directly.
+ *
+ * If userspace wants to emulate VMX_BASIC[55]=0, userspace
+ * should restore the "true" MSRs with the must-be-1 bits
+ * set according to the SDM Vol 3. A.2 "RESERVED CONTROLS AND
+ * DEFAULT SETTINGS".
+ */
+ return -EINVAL;
+ case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
+ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
+ case MSR_IA32_VMX_TRUE_EXIT_CTLS:
+ case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+ case MSR_IA32_VMX_PROCBASED_CTLS2:
+ return vmx_restore_control_msr(vmx, msr_index, data);
+ case MSR_IA32_VMX_MISC:
+ return vmx_restore_vmx_misc(vmx, data);
+ case MSR_IA32_VMX_CR0_FIXED0:
+ case MSR_IA32_VMX_CR4_FIXED0:
+ return vmx_restore_fixed0_msr(vmx, msr_index, data);
+ case MSR_IA32_VMX_CR0_FIXED1:
+ case MSR_IA32_VMX_CR4_FIXED1:
+ /*
+ * These MSRs are generated based on the vCPU's CPUID, so we
+ * do not support restoring them directly.
+ */
+ return -EINVAL;
+ case MSR_IA32_VMX_EPT_VPID_CAP:
+ return vmx_restore_vmx_ept_vpid_cap(vmx, data);
+ case MSR_IA32_VMX_VMCS_ENUM:
+ vmx->nested.msrs.vmcs_enum = data;
+ return 0;
+ default:
+ /*
+ * The rest of the VMX capability MSRs do not support restore.
+ */
+ return -EINVAL;
+ }
+}
+
+/* Returns 0 on success, non-0 otherwise. */
+static int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdata)
+{
+ switch (msr_index) {
+ case MSR_IA32_VMX_BASIC:
+ *pdata = msrs->basic;
+ break;
+ case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
+ case MSR_IA32_VMX_PINBASED_CTLS:
+ *pdata = vmx_control_msr(
+ msrs->pinbased_ctls_low,
+ msrs->pinbased_ctls_high);
+ if (msr_index == MSR_IA32_VMX_PINBASED_CTLS)
+ *pdata |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
+ break;
+ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
+ case MSR_IA32_VMX_PROCBASED_CTLS:
+ *pdata = vmx_control_msr(
+ msrs->procbased_ctls_low,
+ msrs->procbased_ctls_high);
+ if (msr_index == MSR_IA32_VMX_PROCBASED_CTLS)
+ *pdata |= CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
+ break;
+ case MSR_IA32_VMX_TRUE_EXIT_CTLS:
+ case MSR_IA32_VMX_EXIT_CTLS:
+ *pdata = vmx_control_msr(
+ msrs->exit_ctls_low,
+ msrs->exit_ctls_high);
+ if (msr_index == MSR_IA32_VMX_EXIT_CTLS)
+ *pdata |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
+ break;
+ case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+ case MSR_IA32_VMX_ENTRY_CTLS:
+ *pdata = vmx_control_msr(
+ msrs->entry_ctls_low,
+ msrs->entry_ctls_high);
+ if (msr_index == MSR_IA32_VMX_ENTRY_CTLS)
+ *pdata |= VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
+ break;
+ case MSR_IA32_VMX_MISC:
+ *pdata = vmx_control_msr(
+ msrs->misc_low,
+ msrs->misc_high);
+ break;
+ case MSR_IA32_VMX_CR0_FIXED0:
+ *pdata = msrs->cr0_fixed0;
+ break;
+ case MSR_IA32_VMX_CR0_FIXED1:
+ *pdata = msrs->cr0_fixed1;
+ break;
+ case MSR_IA32_VMX_CR4_FIXED0:
+ *pdata = msrs->cr4_fixed0;
+ break;
+ case MSR_IA32_VMX_CR4_FIXED1:
+ *pdata = msrs->cr4_fixed1;
+ break;
+ case MSR_IA32_VMX_VMCS_ENUM:
+ *pdata = msrs->vmcs_enum;
+ break;
+ case MSR_IA32_VMX_PROCBASED_CTLS2:
+ *pdata = vmx_control_msr(
+ msrs->secondary_ctls_low,
+ msrs->secondary_ctls_high);
+ break;
+ case MSR_IA32_VMX_EPT_VPID_CAP:
+ *pdata = msrs->ept_caps |
+ ((u64)msrs->vpid_caps << 32);
+ break;
+ case MSR_IA32_VMX_VMFUNC:
+ *pdata = msrs->vmfunc_controls;
+ break;
+ default:
+ return 1;
+ }
+
+ return 0;
+}
+
+static inline bool vmx_feature_control_msr_valid(struct kvm_vcpu *vcpu,
+ uint64_t val)
+{
+ uint64_t valid_bits = to_vmx(vcpu)->msr_ia32_feature_control_valid_bits;
+
+ return !(val & ~valid_bits);
+}
+
+static int vmx_get_msr_feature(struct kvm_msr_entry *msr)
+{
+ switch (msr->index) {
+ case MSR_IA32_VMX_BASIC ... MSR_IA32_VMX_VMFUNC:
+ if (!nested)
+ return 1;
+ return vmx_get_vmx_msr(&vmcs_config.nested, msr->index, &msr->data);
+ default:
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Reads an msr value (of 'msr_index') into 'pdata'.
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct shared_msr_entry *msr;
+
+ switch (msr_info->index) {
+#ifdef CONFIG_X86_64
+ case MSR_FS_BASE:
+ msr_info->data = vmcs_readl(GUEST_FS_BASE);
+ break;
+ case MSR_GS_BASE:
+ msr_info->data = vmcs_readl(GUEST_GS_BASE);
+ break;
+ case MSR_KERNEL_GS_BASE:
+ msr_info->data = vmx_read_guest_kernel_gs_base(vmx);
+ break;
+#endif
+ case MSR_EFER:
+ return kvm_get_msr_common(vcpu, msr_info);
+ case MSR_IA32_SPEC_CTRL:
+ if (!msr_info->host_initiated &&
+ !guest_has_spec_ctrl_msr(vcpu))
+ return 1;
+
+ msr_info->data = to_vmx(vcpu)->spec_ctrl;
+ break;
+ case MSR_IA32_SYSENTER_CS:
+ msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ msr_info->data = vmcs_readl(GUEST_SYSENTER_EIP);
+ break;
+ case MSR_IA32_SYSENTER_ESP:
+ msr_info->data = vmcs_readl(GUEST_SYSENTER_ESP);
+ break;
+ case MSR_IA32_BNDCFGS:
+ if (!kvm_mpx_supported() ||
+ (!msr_info->host_initiated &&
+ !guest_cpuid_has(vcpu, X86_FEATURE_MPX)))
+ return 1;
+ msr_info->data = vmcs_read64(GUEST_BNDCFGS);
+ break;
+ case MSR_IA32_MCG_EXT_CTL:
+ if (!msr_info->host_initiated &&
+ !(vmx->msr_ia32_feature_control &
+ FEATURE_CONTROL_LMCE))
+ return 1;
+ msr_info->data = vcpu->arch.mcg_ext_ctl;
+ break;
+ case MSR_IA32_FEATURE_CONTROL:
+ msr_info->data = vmx->msr_ia32_feature_control;
+ break;
+ case MSR_IA32_VMX_BASIC ... MSR_IA32_VMX_VMFUNC:
+ if (!nested_vmx_allowed(vcpu))
+ return 1;
+ return vmx_get_vmx_msr(&vmx->nested.msrs, msr_info->index,
+ &msr_info->data);
+ case MSR_IA32_XSS:
+ if (!vmx_xsaves_supported() ||
+ (!msr_info->host_initiated &&
+ !(guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
+ guest_cpuid_has(vcpu, X86_FEATURE_XSAVES))))
+ return 1;
+ msr_info->data = vcpu->arch.ia32_xss;
+ break;
+ case MSR_TSC_AUX:
+ if (!msr_info->host_initiated &&
+ !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
+ return 1;
+ /* Otherwise falls through */
+ default:
+ msr = find_msr_entry(vmx, msr_info->index);
+ if (msr) {
+ msr_info->data = msr->data;
+ break;
+ }
+ return kvm_get_msr_common(vcpu, msr_info);
+ }
+
+ return 0;
+}
+
+static void vmx_leave_nested(struct kvm_vcpu *vcpu);
+
+/*
+ * Writes msr value into into the appropriate "register".
+ * Returns 0 on success, non-0 otherwise.
+ * Assumes vcpu_load() was already called.
+ */
+static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct shared_msr_entry *msr;
+ int ret = 0;
+ u32 msr_index = msr_info->index;
+ u64 data = msr_info->data;
+
+ switch (msr_index) {
+ case MSR_EFER:
+ ret = kvm_set_msr_common(vcpu, msr_info);
+ break;
+#ifdef CONFIG_X86_64
+ case MSR_FS_BASE:
+ vmx_segment_cache_clear(vmx);
+ vmcs_writel(GUEST_FS_BASE, data);
+ break;
+ case MSR_GS_BASE:
+ vmx_segment_cache_clear(vmx);
+ vmcs_writel(GUEST_GS_BASE, data);
+ break;
+ case MSR_KERNEL_GS_BASE:
+ vmx_write_guest_kernel_gs_base(vmx, data);
+ break;
+#endif
+ case MSR_IA32_SYSENTER_CS:
+ vmcs_write32(GUEST_SYSENTER_CS, data);
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ vmcs_writel(GUEST_SYSENTER_EIP, data);
+ break;
+ case MSR_IA32_SYSENTER_ESP:
+ vmcs_writel(GUEST_SYSENTER_ESP, data);
+ break;
+ case MSR_IA32_BNDCFGS:
+ if (!kvm_mpx_supported() ||
+ (!msr_info->host_initiated &&
+ !guest_cpuid_has(vcpu, X86_FEATURE_MPX)))
+ return 1;
+ if (is_noncanonical_address(data & PAGE_MASK, vcpu) ||
+ (data & MSR_IA32_BNDCFGS_RSVD))
+ return 1;
+ vmcs_write64(GUEST_BNDCFGS, data);
+ break;
+ case MSR_IA32_SPEC_CTRL:
+ if (!msr_info->host_initiated &&
+ !guest_has_spec_ctrl_msr(vcpu))
+ return 1;
+
+ /* The STIBP bit doesn't fault even if it's not advertised */
+ if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD))
+ return 1;
+
+ vmx->spec_ctrl = data;
+
+ if (!data)
+ break;
+
+ /*
+ * For non-nested:
+ * When it's written (to non-zero) for the first time, pass
+ * it through.
+ *
+ * For nested:
+ * The handling of the MSR bitmap for L2 guests is done in
+ * nested_vmx_merge_msr_bitmap. We should not touch the
+ * vmcs02.msr_bitmap here since it gets completely overwritten
+ * in the merging. We update the vmcs01 here for L1 as well
+ * since it will end up touching the MSR anyway now.
+ */
+ vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
+ MSR_IA32_SPEC_CTRL,
+ MSR_TYPE_RW);
+ break;
+ case MSR_IA32_PRED_CMD:
+ if (!msr_info->host_initiated &&
+ !guest_has_pred_cmd_msr(vcpu))
+ return 1;
+
+ if (data & ~PRED_CMD_IBPB)
+ return 1;
+
+ if (!data)
+ break;
+
+ wrmsrl(MSR_IA32_PRED_CMD, PRED_CMD_IBPB);
+
+ /*
+ * For non-nested:
+ * When it's written (to non-zero) for the first time, pass
+ * it through.
+ *
+ * For nested:
+ * The handling of the MSR bitmap for L2 guests is done in
+ * nested_vmx_merge_msr_bitmap. We should not touch the
+ * vmcs02.msr_bitmap here since it gets completely overwritten
+ * in the merging.
+ */
+ vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap, MSR_IA32_PRED_CMD,
+ MSR_TYPE_W);
+ break;
+ case MSR_IA32_CR_PAT:
+ if (!kvm_pat_valid(data))
+ return 1;
+
+ if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
+ vmcs_write64(GUEST_IA32_PAT, data);
+ vcpu->arch.pat = data;
+ break;
+ }
+ ret = kvm_set_msr_common(vcpu, msr_info);
+ break;
+ case MSR_IA32_TSC_ADJUST:
+ ret = kvm_set_msr_common(vcpu, msr_info);
+ break;
+ case MSR_IA32_MCG_EXT_CTL:
+ if ((!msr_info->host_initiated &&
+ !(to_vmx(vcpu)->msr_ia32_feature_control &
+ FEATURE_CONTROL_LMCE)) ||
+ (data & ~MCG_EXT_CTL_LMCE_EN))
+ return 1;
+ vcpu->arch.mcg_ext_ctl = data;
+ break;
+ case MSR_IA32_FEATURE_CONTROL:
+ if (!vmx_feature_control_msr_valid(vcpu, data) ||
+ (to_vmx(vcpu)->msr_ia32_feature_control &
+ FEATURE_CONTROL_LOCKED && !msr_info->host_initiated))
+ return 1;
+ vmx->msr_ia32_feature_control = data;
+ if (msr_info->host_initiated && data == 0)
+ vmx_leave_nested(vcpu);
+ break;
+ case MSR_IA32_VMX_BASIC ... MSR_IA32_VMX_VMFUNC:
+ if (!msr_info->host_initiated)
+ return 1; /* they are read-only */
+ if (!nested_vmx_allowed(vcpu))
+ return 1;
+ return vmx_set_vmx_msr(vcpu, msr_index, data);
+ case MSR_IA32_XSS:
+ if (!vmx_xsaves_supported() ||
+ (!msr_info->host_initiated &&
+ !(guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
+ guest_cpuid_has(vcpu, X86_FEATURE_XSAVES))))
+ return 1;
+ /*
+ * The only supported bit as of Skylake is bit 8, but
+ * it is not supported on KVM.
+ */
+ if (data != 0)
+ return 1;
+ vcpu->arch.ia32_xss = data;
+ if (vcpu->arch.ia32_xss != host_xss)
+ add_atomic_switch_msr(vmx, MSR_IA32_XSS,
+ vcpu->arch.ia32_xss, host_xss, false);
+ else
+ clear_atomic_switch_msr(vmx, MSR_IA32_XSS);
+ break;
+ case MSR_TSC_AUX:
+ if (!msr_info->host_initiated &&
+ !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
+ return 1;
+ /* Check reserved bit, higher 32 bits should be zero */
+ if ((data >> 32) != 0)
+ return 1;
+ /* Otherwise falls through */
+ default:
+ msr = find_msr_entry(vmx, msr_index);
+ if (msr) {
+ u64 old_msr_data = msr->data;
+ msr->data = data;
+ if (msr - vmx->guest_msrs < vmx->save_nmsrs) {
+ preempt_disable();
+ ret = kvm_set_shared_msr(msr->index, msr->data,
+ msr->mask);
+ preempt_enable();
+ if (ret)
+ msr->data = old_msr_data;
+ }
+ break;
+ }
+ ret = kvm_set_msr_common(vcpu, msr_info);
+ }
+
+ /* FB_CLEAR may have changed, also update the FB_CLEAR_DIS behavior */
+ if (msr_index == MSR_IA32_ARCH_CAPABILITIES)
+ vmx_update_fb_clear_dis(vcpu, vmx);
+
+ return ret;
+}
+
+static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
+{
+ __set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
+ switch (reg) {
+ case VCPU_REGS_RSP:
+ vcpu->arch.regs[VCPU_REGS_RSP] = vmcs_readl(GUEST_RSP);
+ break;
+ case VCPU_REGS_RIP:
+ vcpu->arch.regs[VCPU_REGS_RIP] = vmcs_readl(GUEST_RIP);
+ break;
+ case VCPU_EXREG_PDPTR:
+ if (enable_ept)
+ ept_save_pdptrs(vcpu);
+ break;
+ default:
+ break;
+ }
+}
+
+static __init int cpu_has_kvm_support(void)
+{
+ return cpu_has_vmx();
+}
+
+static __init int vmx_disabled_by_bios(void)
+{
+ u64 msr;
+
+ rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
+ if (msr & FEATURE_CONTROL_LOCKED) {
+ /* launched w/ TXT and VMX disabled */
+ if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
+ && tboot_enabled())
+ return 1;
+ /* launched w/o TXT and VMX only enabled w/ TXT */
+ if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
+ && (msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
+ && !tboot_enabled()) {
+ printk(KERN_WARNING "kvm: disable TXT in the BIOS or "
+ "activate TXT before enabling KVM\n");
+ return 1;
+ }
+ /* launched w/o TXT and VMX disabled */
+ if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
+ && !tboot_enabled())
+ return 1;
+ }
+
+ return 0;
+}
+
+static void kvm_cpu_vmxon(u64 addr)
+{
+ cr4_set_bits(X86_CR4_VMXE);
+ intel_pt_handle_vmx(1);
+
+ asm volatile (ASM_VMX_VMXON_RAX
+ : : "a"(&addr), "m"(addr)
+ : "memory", "cc");
+}
+
+static int hardware_enable(void)
+{
+ int cpu = raw_smp_processor_id();
+ u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
+ u64 old, test_bits;
+
+ if (cr4_read_shadow() & X86_CR4_VMXE)
+ return -EBUSY;
+
+ /*
+ * This can happen if we hot-added a CPU but failed to allocate
+ * VP assist page for it.
+ */
+ if (static_branch_unlikely(&enable_evmcs) &&
+ !hv_get_vp_assist_page(cpu))
+ return -EFAULT;
+
+ rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
+
+ test_bits = FEATURE_CONTROL_LOCKED;
+ test_bits |= FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
+ if (tboot_enabled())
+ test_bits |= FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX;
+
+ if ((old & test_bits) != test_bits) {
+ /* enable and lock */
+ wrmsrl(MSR_IA32_FEATURE_CONTROL, old | test_bits);
+ }
+ kvm_cpu_vmxon(phys_addr);
+ if (enable_ept)
+ ept_sync_global();
+
+ return 0;
+}
+
+static void vmclear_local_loaded_vmcss(void)
+{
+ int cpu = raw_smp_processor_id();
+ struct loaded_vmcs *v, *n;
+
+ list_for_each_entry_safe(v, n, &per_cpu(loaded_vmcss_on_cpu, cpu),
+ loaded_vmcss_on_cpu_link)
+ __loaded_vmcs_clear(v);
+}
+
+
+/* Just like cpu_vmxoff(), but with the __kvm_handle_fault_on_reboot()
+ * tricks.
+ */
+static void kvm_cpu_vmxoff(void)
+{
+ asm volatile (__ex(ASM_VMX_VMXOFF) : : : "cc");
+
+ intel_pt_handle_vmx(0);
+ cr4_clear_bits(X86_CR4_VMXE);
+}
+
+static void hardware_disable(void)
+{
+ vmclear_local_loaded_vmcss();
+ kvm_cpu_vmxoff();
+}
+
+static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt,
+ u32 msr, u32 *result)
+{
+ u32 vmx_msr_low, vmx_msr_high;
+ u32 ctl = ctl_min | ctl_opt;
+
+ rdmsr(msr, vmx_msr_low, vmx_msr_high);
+
+ ctl &= vmx_msr_high; /* bit == 0 in high word ==> must be zero */
+ ctl |= vmx_msr_low; /* bit == 1 in low word ==> must be one */
+
+ /* Ensure minimum (required) set of control bits are supported. */
+ if (ctl_min & ~ctl)
+ return -EIO;
+
+ *result = ctl;
+ return 0;
+}
+
+static __init bool allow_1_setting(u32 msr, u32 ctl)
+{
+ u32 vmx_msr_low, vmx_msr_high;
+
+ rdmsr(msr, vmx_msr_low, vmx_msr_high);
+ return vmx_msr_high & ctl;
+}
+
+static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
+{
+ u32 vmx_msr_low, vmx_msr_high;
+ u32 min, opt, min2, opt2;
+ u32 _pin_based_exec_control = 0;
+ u32 _cpu_based_exec_control = 0;
+ u32 _cpu_based_2nd_exec_control = 0;
+ u32 _vmexit_control = 0;
+ u32 _vmentry_control = 0;
+
+ memset(vmcs_conf, 0, sizeof(*vmcs_conf));
+ min = CPU_BASED_HLT_EXITING |
+#ifdef CONFIG_X86_64
+ CPU_BASED_CR8_LOAD_EXITING |
+ CPU_BASED_CR8_STORE_EXITING |
+#endif
+ CPU_BASED_CR3_LOAD_EXITING |
+ CPU_BASED_CR3_STORE_EXITING |
+ CPU_BASED_UNCOND_IO_EXITING |
+ CPU_BASED_MOV_DR_EXITING |
+ CPU_BASED_USE_TSC_OFFSETING |
+ CPU_BASED_MWAIT_EXITING |
+ CPU_BASED_MONITOR_EXITING |
+ CPU_BASED_INVLPG_EXITING |
+ CPU_BASED_RDPMC_EXITING;
+
+ opt = CPU_BASED_TPR_SHADOW |
+ CPU_BASED_USE_MSR_BITMAPS |
+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+ if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
+ &_cpu_based_exec_control) < 0)
+ return -EIO;
+#ifdef CONFIG_X86_64
+ if ((_cpu_based_exec_control & CPU_BASED_TPR_SHADOW))
+ _cpu_based_exec_control &= ~CPU_BASED_CR8_LOAD_EXITING &
+ ~CPU_BASED_CR8_STORE_EXITING;
+#endif
+ if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
+ min2 = 0;
+ opt2 = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
+ SECONDARY_EXEC_WBINVD_EXITING |
+ SECONDARY_EXEC_ENABLE_VPID |
+ SECONDARY_EXEC_ENABLE_EPT |
+ SECONDARY_EXEC_UNRESTRICTED_GUEST |
+ SECONDARY_EXEC_PAUSE_LOOP_EXITING |
+ SECONDARY_EXEC_DESC |
+ SECONDARY_EXEC_RDTSCP |
+ SECONDARY_EXEC_ENABLE_INVPCID |
+ SECONDARY_EXEC_APIC_REGISTER_VIRT |
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
+ SECONDARY_EXEC_SHADOW_VMCS |
+ SECONDARY_EXEC_XSAVES |
+ SECONDARY_EXEC_RDSEED_EXITING |
+ SECONDARY_EXEC_RDRAND_EXITING |
+ SECONDARY_EXEC_ENABLE_PML |
+ SECONDARY_EXEC_TSC_SCALING |
+ SECONDARY_EXEC_ENABLE_VMFUNC |
+ SECONDARY_EXEC_ENCLS_EXITING;
+ if (adjust_vmx_controls(min2, opt2,
+ MSR_IA32_VMX_PROCBASED_CTLS2,
+ &_cpu_based_2nd_exec_control) < 0)
+ return -EIO;
+ }
+#ifndef CONFIG_X86_64
+ if (!(_cpu_based_2nd_exec_control &
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
+ _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW;
+#endif
+
+ if (!(_cpu_based_exec_control & CPU_BASED_TPR_SHADOW))
+ _cpu_based_2nd_exec_control &= ~(
+ SECONDARY_EXEC_APIC_REGISTER_VIRT |
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
+
+ rdmsr_safe(MSR_IA32_VMX_EPT_VPID_CAP,
+ &vmx_capability.ept, &vmx_capability.vpid);
+
+ if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) {
+ /* CR3 accesses and invlpg don't need to cause VM Exits when EPT
+ enabled */
+ _cpu_based_exec_control &= ~(CPU_BASED_CR3_LOAD_EXITING |
+ CPU_BASED_CR3_STORE_EXITING |
+ CPU_BASED_INVLPG_EXITING);
+ } else if (vmx_capability.ept) {
+ vmx_capability.ept = 0;
+ pr_warn_once("EPT CAP should not exist if not support "
+ "1-setting enable EPT VM-execution control\n");
+ }
+ if (!(_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_VPID) &&
+ vmx_capability.vpid) {
+ vmx_capability.vpid = 0;
+ pr_warn_once("VPID CAP should not exist if not support "
+ "1-setting enable VPID VM-execution control\n");
+ }
+
+ min = VM_EXIT_SAVE_DEBUG_CONTROLS | VM_EXIT_ACK_INTR_ON_EXIT;
+#ifdef CONFIG_X86_64
+ min |= VM_EXIT_HOST_ADDR_SPACE_SIZE;
+#endif
+ opt = VM_EXIT_SAVE_IA32_PAT | VM_EXIT_LOAD_IA32_PAT |
+ VM_EXIT_CLEAR_BNDCFGS;
+ if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
+ &_vmexit_control) < 0)
+ return -EIO;
+
+ min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
+ opt = PIN_BASED_VIRTUAL_NMIS | PIN_BASED_POSTED_INTR |
+ PIN_BASED_VMX_PREEMPTION_TIMER;
+ if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
+ &_pin_based_exec_control) < 0)
+ return -EIO;
+
+ if (cpu_has_broken_vmx_preemption_timer())
+ _pin_based_exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
+ if (!(_cpu_based_2nd_exec_control &
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY))
+ _pin_based_exec_control &= ~PIN_BASED_POSTED_INTR;
+
+ min = VM_ENTRY_LOAD_DEBUG_CONTROLS;
+ opt = VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_LOAD_BNDCFGS;
+ if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
+ &_vmentry_control) < 0)
+ return -EIO;
+
+ rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high);
+
+ /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
+ if ((vmx_msr_high & 0x1fff) > PAGE_SIZE)
+ return -EIO;
+
+#ifdef CONFIG_X86_64
+ /* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */
+ if (vmx_msr_high & (1u<<16))
+ return -EIO;
+#endif
+
+ /* Require Write-Back (WB) memory type for VMCS accesses. */
+ if (((vmx_msr_high >> 18) & 15) != 6)
+ return -EIO;
+
+ vmcs_conf->size = vmx_msr_high & 0x1fff;
+ vmcs_conf->order = get_order(vmcs_conf->size);
+ vmcs_conf->basic_cap = vmx_msr_high & ~0x1fff;
+
+ vmcs_conf->revision_id = vmx_msr_low;
+
+ vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control;
+ vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control;
+ vmcs_conf->cpu_based_2nd_exec_ctrl = _cpu_based_2nd_exec_control;
+ vmcs_conf->vmexit_ctrl = _vmexit_control;
+ vmcs_conf->vmentry_ctrl = _vmentry_control;
+
+ if (static_branch_unlikely(&enable_evmcs))
+ evmcs_sanitize_exec_ctrls(vmcs_conf);
+
+ cpu_has_load_ia32_efer =
+ allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS,
+ VM_ENTRY_LOAD_IA32_EFER)
+ && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
+ VM_EXIT_LOAD_IA32_EFER);
+
+ cpu_has_load_perf_global_ctrl =
+ allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS,
+ VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
+ && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
+ VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+
+ /*
+ * Some cpus support VM_ENTRY_(LOAD|SAVE)_IA32_PERF_GLOBAL_CTRL
+ * but due to errata below it can't be used. Workaround is to use
+ * msr load mechanism to switch IA32_PERF_GLOBAL_CTRL.
+ *
+ * VM Exit May Incorrectly Clear IA32_PERF_GLOBAL_CTRL [34:32]
+ *
+ * AAK155 (model 26)
+ * AAP115 (model 30)
+ * AAT100 (model 37)
+ * BC86,AAY89,BD102 (model 44)
+ * BA97 (model 46)
+ *
+ */
+ if (cpu_has_load_perf_global_ctrl && boot_cpu_data.x86 == 0x6) {
+ switch (boot_cpu_data.x86_model) {
+ case 26:
+ case 30:
+ case 37:
+ case 44:
+ case 46:
+ cpu_has_load_perf_global_ctrl = false;
+ printk_once(KERN_WARNING"kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
+ "does not work properly. Using workaround\n");
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static struct vmcs *alloc_vmcs_cpu(bool shadow, int cpu)
+{
+ int node = cpu_to_node(cpu);
+ struct page *pages;
+ struct vmcs *vmcs;
+
+ pages = __alloc_pages_node(node, GFP_KERNEL, vmcs_config.order);
+ if (!pages)
+ return NULL;
+ vmcs = page_address(pages);
+ memset(vmcs, 0, vmcs_config.size);
+
+ /* KVM supports Enlightened VMCS v1 only */
+ if (static_branch_unlikely(&enable_evmcs))
+ vmcs->hdr.revision_id = KVM_EVMCS_VERSION;
+ else
+ vmcs->hdr.revision_id = vmcs_config.revision_id;
+
+ if (shadow)
+ vmcs->hdr.shadow_vmcs = 1;
+ return vmcs;
+}
+
+static void free_vmcs(struct vmcs *vmcs)
+{
+ free_pages((unsigned long)vmcs, vmcs_config.order);
+}
+
+/*
+ * Free a VMCS, but before that VMCLEAR it on the CPU where it was last loaded
+ */
+static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
+{
+ if (!loaded_vmcs->vmcs)
+ return;
+ loaded_vmcs_clear(loaded_vmcs);
+ free_vmcs(loaded_vmcs->vmcs);
+ loaded_vmcs->vmcs = NULL;
+ if (loaded_vmcs->msr_bitmap)
+ free_page((unsigned long)loaded_vmcs->msr_bitmap);
+ WARN_ON(loaded_vmcs->shadow_vmcs != NULL);
+}
+
+static struct vmcs *alloc_vmcs(bool shadow)
+{
+ return alloc_vmcs_cpu(shadow, raw_smp_processor_id());
+}
+
+static int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
+{
+ loaded_vmcs->vmcs = alloc_vmcs(false);
+ if (!loaded_vmcs->vmcs)
+ return -ENOMEM;
+
+ loaded_vmcs->shadow_vmcs = NULL;
+ loaded_vmcs_init(loaded_vmcs);
+
+ if (cpu_has_vmx_msr_bitmap()) {
+ loaded_vmcs->msr_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL);
+ if (!loaded_vmcs->msr_bitmap)
+ goto out_vmcs;
+ memset(loaded_vmcs->msr_bitmap, 0xff, PAGE_SIZE);
+
+ if (IS_ENABLED(CONFIG_HYPERV) &&
+ static_branch_unlikely(&enable_evmcs) &&
+ (ms_hyperv.nested_features & HV_X64_NESTED_MSR_BITMAP)) {
+ struct hv_enlightened_vmcs *evmcs =
+ (struct hv_enlightened_vmcs *)loaded_vmcs->vmcs;
+
+ evmcs->hv_enlightenments_control.msr_bitmap = 1;
+ }
+ }
+
+ memset(&loaded_vmcs->host_state, 0, sizeof(struct vmcs_host_state));
+
+ return 0;
+
+out_vmcs:
+ free_loaded_vmcs(loaded_vmcs);
+ return -ENOMEM;
+}
+
+static void free_kvm_area(void)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ free_vmcs(per_cpu(vmxarea, cpu));
+ per_cpu(vmxarea, cpu) = NULL;
+ }
+}
+
+enum vmcs_field_width {
+ VMCS_FIELD_WIDTH_U16 = 0,
+ VMCS_FIELD_WIDTH_U64 = 1,
+ VMCS_FIELD_WIDTH_U32 = 2,
+ VMCS_FIELD_WIDTH_NATURAL_WIDTH = 3
+};
+
+static inline int vmcs_field_width(unsigned long field)
+{
+ if (0x1 & field) /* the *_HIGH fields are all 32 bit */
+ return VMCS_FIELD_WIDTH_U32;
+ return (field >> 13) & 0x3 ;
+}
+
+static inline int vmcs_field_readonly(unsigned long field)
+{
+ return (((field >> 10) & 0x3) == 1);
+}
+
+static void init_vmcs_shadow_fields(void)
+{
+ int i, j;
+
+ for (i = j = 0; i < max_shadow_read_only_fields; i++) {
+ u16 field = shadow_read_only_fields[i];
+ if (vmcs_field_width(field) == VMCS_FIELD_WIDTH_U64 &&
+ (i + 1 == max_shadow_read_only_fields ||
+ shadow_read_only_fields[i + 1] != field + 1))
+ pr_err("Missing field from shadow_read_only_field %x\n",
+ field + 1);
+
+ clear_bit(field, vmx_vmread_bitmap);
+#ifdef CONFIG_X86_64
+ if (field & 1)
+ continue;
+#endif
+ if (j < i)
+ shadow_read_only_fields[j] = field;
+ j++;
+ }
+ max_shadow_read_only_fields = j;
+
+ for (i = j = 0; i < max_shadow_read_write_fields; i++) {
+ u16 field = shadow_read_write_fields[i];
+ if (vmcs_field_width(field) == VMCS_FIELD_WIDTH_U64 &&
+ (i + 1 == max_shadow_read_write_fields ||
+ shadow_read_write_fields[i + 1] != field + 1))
+ pr_err("Missing field from shadow_read_write_field %x\n",
+ field + 1);
+
+ /*
+ * PML and the preemption timer can be emulated, but the
+ * processor cannot vmwrite to fields that don't exist
+ * on bare metal.
+ */
+ switch (field) {
+ case GUEST_PML_INDEX:
+ if (!cpu_has_vmx_pml())
+ continue;
+ break;
+ case VMX_PREEMPTION_TIMER_VALUE:
+ if (!cpu_has_vmx_preemption_timer())
+ continue;
+ break;
+ case GUEST_INTR_STATUS:
+ if (!cpu_has_vmx_apicv())
+ continue;
+ break;
+ default:
+ break;
+ }
+
+ clear_bit(field, vmx_vmwrite_bitmap);
+ clear_bit(field, vmx_vmread_bitmap);
+#ifdef CONFIG_X86_64
+ if (field & 1)
+ continue;
+#endif
+ if (j < i)
+ shadow_read_write_fields[j] = field;
+ j++;
+ }
+ max_shadow_read_write_fields = j;
+}
+
+static __init int alloc_kvm_area(void)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct vmcs *vmcs;
+
+ vmcs = alloc_vmcs_cpu(false, cpu);
+ if (!vmcs) {
+ free_kvm_area();
+ return -ENOMEM;
+ }
+
+ /*
+ * When eVMCS is enabled, alloc_vmcs_cpu() sets
+ * vmcs->revision_id to KVM_EVMCS_VERSION instead of
+ * revision_id reported by MSR_IA32_VMX_BASIC.
+ *
+ * However, even though not explictly documented by
+ * TLFS, VMXArea passed as VMXON argument should
+ * still be marked with revision_id reported by
+ * physical CPU.
+ */
+ if (static_branch_unlikely(&enable_evmcs))
+ vmcs->hdr.revision_id = vmcs_config.revision_id;
+
+ per_cpu(vmxarea, cpu) = vmcs;
+ }
+ return 0;
+}
+
+static void fix_pmode_seg(struct kvm_vcpu *vcpu, int seg,
+ struct kvm_segment *save)
+{
+ if (!emulate_invalid_guest_state) {
+ /*
+ * CS and SS RPL should be equal during guest entry according
+ * to VMX spec, but in reality it is not always so. Since vcpu
+ * is in the middle of the transition from real mode to
+ * protected mode it is safe to assume that RPL 0 is a good
+ * default value.
+ */
+ if (seg == VCPU_SREG_CS || seg == VCPU_SREG_SS)
+ save->selector &= ~SEGMENT_RPL_MASK;
+ save->dpl = save->selector & SEGMENT_RPL_MASK;
+ save->s = 1;
+ }
+ vmx_set_segment(vcpu, save, seg);
+}
+
+static void enter_pmode(struct kvm_vcpu *vcpu)
+{
+ unsigned long flags;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ /*
+ * Update real mode segment cache. It may be not up-to-date if sement
+ * register was written while vcpu was in a guest mode.
+ */
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_ES], VCPU_SREG_ES);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_DS], VCPU_SREG_DS);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_FS], VCPU_SREG_FS);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_GS], VCPU_SREG_GS);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_SS], VCPU_SREG_SS);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_CS], VCPU_SREG_CS);
+
+ vmx->rmode.vm86_active = 0;
+
+ vmx_segment_cache_clear(vmx);
+
+ vmx_set_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
+
+ flags = vmcs_readl(GUEST_RFLAGS);
+ flags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
+ flags |= vmx->rmode.save_rflags & ~RMODE_GUEST_OWNED_EFLAGS_BITS;
+ vmcs_writel(GUEST_RFLAGS, flags);
+
+ vmcs_writel(GUEST_CR4, (vmcs_readl(GUEST_CR4) & ~X86_CR4_VME) |
+ (vmcs_readl(CR4_READ_SHADOW) & X86_CR4_VME));
+
+ update_exception_bitmap(vcpu);
+
+ fix_pmode_seg(vcpu, VCPU_SREG_CS, &vmx->rmode.segs[VCPU_SREG_CS]);
+ fix_pmode_seg(vcpu, VCPU_SREG_SS, &vmx->rmode.segs[VCPU_SREG_SS]);
+ fix_pmode_seg(vcpu, VCPU_SREG_ES, &vmx->rmode.segs[VCPU_SREG_ES]);
+ fix_pmode_seg(vcpu, VCPU_SREG_DS, &vmx->rmode.segs[VCPU_SREG_DS]);
+ fix_pmode_seg(vcpu, VCPU_SREG_FS, &vmx->rmode.segs[VCPU_SREG_FS]);
+ fix_pmode_seg(vcpu, VCPU_SREG_GS, &vmx->rmode.segs[VCPU_SREG_GS]);
+}
+
+static void fix_rmode_seg(int seg, struct kvm_segment *save)
+{
+ const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+ struct kvm_segment var = *save;
+
+ var.dpl = 0x3;
+ if (seg == VCPU_SREG_CS)
+ var.type = 0x3;
+
+ if (!emulate_invalid_guest_state) {
+ var.selector = var.base >> 4;
+ var.base = var.base & 0xffff0;
+ var.limit = 0xffff;
+ var.g = 0;
+ var.db = 0;
+ var.present = 1;
+ var.s = 1;
+ var.l = 0;
+ var.unusable = 0;
+ var.type = 0x3;
+ var.avl = 0;
+ if (save->base & 0xf)
+ printk_once(KERN_WARNING "kvm: segment base is not "
+ "paragraph aligned when entering "
+ "protected mode (seg=%d)", seg);
+ }
+
+ vmcs_write16(sf->selector, var.selector);
+ vmcs_writel(sf->base, var.base);
+ vmcs_write32(sf->limit, var.limit);
+ vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(&var));
+}
+
+static void enter_rmode(struct kvm_vcpu *vcpu)
+{
+ unsigned long flags;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct kvm_vmx *kvm_vmx = to_kvm_vmx(vcpu->kvm);
+
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_ES], VCPU_SREG_ES);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_DS], VCPU_SREG_DS);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_FS], VCPU_SREG_FS);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_GS], VCPU_SREG_GS);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_SS], VCPU_SREG_SS);
+ vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_CS], VCPU_SREG_CS);
+
+ vmx->rmode.vm86_active = 1;
+
+ /*
+ * Very old userspace does not call KVM_SET_TSS_ADDR before entering
+ * vcpu. Warn the user that an update is overdue.
+ */
+ if (!kvm_vmx->tss_addr)
+ printk_once(KERN_WARNING "kvm: KVM_SET_TSS_ADDR need to be "
+ "called before entering vcpu\n");
+
+ vmx_segment_cache_clear(vmx);
+
+ vmcs_writel(GUEST_TR_BASE, kvm_vmx->tss_addr);
+ vmcs_write32(GUEST_TR_LIMIT, RMODE_TSS_SIZE - 1);
+ vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
+
+ flags = vmcs_readl(GUEST_RFLAGS);
+ vmx->rmode.save_rflags = flags;
+
+ flags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM;
+
+ vmcs_writel(GUEST_RFLAGS, flags);
+ vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | X86_CR4_VME);
+ update_exception_bitmap(vcpu);
+
+ fix_rmode_seg(VCPU_SREG_SS, &vmx->rmode.segs[VCPU_SREG_SS]);
+ fix_rmode_seg(VCPU_SREG_CS, &vmx->rmode.segs[VCPU_SREG_CS]);
+ fix_rmode_seg(VCPU_SREG_ES, &vmx->rmode.segs[VCPU_SREG_ES]);
+ fix_rmode_seg(VCPU_SREG_DS, &vmx->rmode.segs[VCPU_SREG_DS]);
+ fix_rmode_seg(VCPU_SREG_GS, &vmx->rmode.segs[VCPU_SREG_GS]);
+ fix_rmode_seg(VCPU_SREG_FS, &vmx->rmode.segs[VCPU_SREG_FS]);
+
+ kvm_mmu_reset_context(vcpu);
+}
+
+static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct shared_msr_entry *msr = find_msr_entry(vmx, MSR_EFER);
+
+ if (!msr)
+ return;
+
+ vcpu->arch.efer = efer;
+ if (efer & EFER_LMA) {
+ vm_entry_controls_setbit(to_vmx(vcpu), VM_ENTRY_IA32E_MODE);
+ msr->data = efer;
+ } else {
+ vm_entry_controls_clearbit(to_vmx(vcpu), VM_ENTRY_IA32E_MODE);
+
+ msr->data = efer & ~EFER_LME;
+ }
+ setup_msrs(vmx);
+}
+
+#ifdef CONFIG_X86_64
+
+static void enter_lmode(struct kvm_vcpu *vcpu)
+{
+ u32 guest_tr_ar;
+
+ vmx_segment_cache_clear(to_vmx(vcpu));
+
+ guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
+ if ((guest_tr_ar & VMX_AR_TYPE_MASK) != VMX_AR_TYPE_BUSY_64_TSS) {
+ pr_debug_ratelimited("%s: tss fixup for long mode. \n",
+ __func__);
+ vmcs_write32(GUEST_TR_AR_BYTES,
+ (guest_tr_ar & ~VMX_AR_TYPE_MASK)
+ | VMX_AR_TYPE_BUSY_64_TSS);
+ }
+ vmx_set_efer(vcpu, vcpu->arch.efer | EFER_LMA);
+}
+
+static void exit_lmode(struct kvm_vcpu *vcpu)
+{
+ vm_entry_controls_clearbit(to_vmx(vcpu), VM_ENTRY_IA32E_MODE);
+ vmx_set_efer(vcpu, vcpu->arch.efer & ~EFER_LMA);
+}
+
+#endif
+
+static inline void __vmx_flush_tlb(struct kvm_vcpu *vcpu, int vpid,
+ bool invalidate_gpa)
+{
+ if (enable_ept && (invalidate_gpa || !enable_vpid)) {
+ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+ return;
+ ept_sync_context(construct_eptp(vcpu, vcpu->arch.mmu.root_hpa));
+ } else {
+ vpid_sync_context(vpid);
+ }
+}
+
+static void vmx_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
+{
+ __vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid, invalidate_gpa);
+}
+
+static void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr)
+{
+ int vpid = to_vmx(vcpu)->vpid;
+
+ if (!vpid_sync_vcpu_addr(vpid, addr))
+ vpid_sync_context(vpid);
+
+ /*
+ * If VPIDs are not supported or enabled, then the above is a no-op.
+ * But we don't really need a TLB flush in that case anyway, because
+ * each VM entry/exit includes an implicit flush when VPID is 0.
+ */
+}
+
+static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
+{
+ ulong cr0_guest_owned_bits = vcpu->arch.cr0_guest_owned_bits;
+
+ vcpu->arch.cr0 &= ~cr0_guest_owned_bits;
+ vcpu->arch.cr0 |= vmcs_readl(GUEST_CR0) & cr0_guest_owned_bits;
+}
+
+static void vmx_decache_cr3(struct kvm_vcpu *vcpu)
+{
+ if (enable_unrestricted_guest || (enable_ept && is_paging(vcpu)))
+ vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
+ __set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
+}
+
+static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
+{
+ ulong cr4_guest_owned_bits = vcpu->arch.cr4_guest_owned_bits;
+
+ vcpu->arch.cr4 &= ~cr4_guest_owned_bits;
+ vcpu->arch.cr4 |= vmcs_readl(GUEST_CR4) & cr4_guest_owned_bits;
+}
+
+static void ept_load_pdptrs(struct kvm_vcpu *vcpu)
+{
+ struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
+
+ if (!test_bit(VCPU_EXREG_PDPTR,
+ (unsigned long *)&vcpu->arch.regs_dirty))
+ return;
+
+ if (is_pae_paging(vcpu)) {
+ vmcs_write64(GUEST_PDPTR0, mmu->pdptrs[0]);
+ vmcs_write64(GUEST_PDPTR1, mmu->pdptrs[1]);
+ vmcs_write64(GUEST_PDPTR2, mmu->pdptrs[2]);
+ vmcs_write64(GUEST_PDPTR3, mmu->pdptrs[3]);
+ }
+}
+
+static void ept_save_pdptrs(struct kvm_vcpu *vcpu)
+{
+ struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
+
+ if (is_pae_paging(vcpu)) {
+ mmu->pdptrs[0] = vmcs_read64(GUEST_PDPTR0);
+ mmu->pdptrs[1] = vmcs_read64(GUEST_PDPTR1);
+ mmu->pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
+ mmu->pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
+ }
+
+ __set_bit(VCPU_EXREG_PDPTR,
+ (unsigned long *)&vcpu->arch.regs_avail);
+ __set_bit(VCPU_EXREG_PDPTR,
+ (unsigned long *)&vcpu->arch.regs_dirty);
+}
+
+static bool nested_guest_cr0_valid(struct kvm_vcpu *vcpu, unsigned long val)
+{
+ u64 fixed0 = to_vmx(vcpu)->nested.msrs.cr0_fixed0;
+ u64 fixed1 = to_vmx(vcpu)->nested.msrs.cr0_fixed1;
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+ if (to_vmx(vcpu)->nested.msrs.secondary_ctls_high &
+ SECONDARY_EXEC_UNRESTRICTED_GUEST &&
+ nested_cpu_has2(vmcs12, SECONDARY_EXEC_UNRESTRICTED_GUEST))
+ fixed0 &= ~(X86_CR0_PE | X86_CR0_PG);
+
+ return fixed_bits_valid(val, fixed0, fixed1);
+}
+
+static bool nested_host_cr0_valid(struct kvm_vcpu *vcpu, unsigned long val)
+{
+ u64 fixed0 = to_vmx(vcpu)->nested.msrs.cr0_fixed0;
+ u64 fixed1 = to_vmx(vcpu)->nested.msrs.cr0_fixed1;
+
+ return fixed_bits_valid(val, fixed0, fixed1);
+}
+
+static bool nested_cr4_valid(struct kvm_vcpu *vcpu, unsigned long val)
+{
+ u64 fixed0 = to_vmx(vcpu)->nested.msrs.cr4_fixed0;
+ u64 fixed1 = to_vmx(vcpu)->nested.msrs.cr4_fixed1;
+
+ return fixed_bits_valid(val, fixed0, fixed1);
+}
+
+/* No difference in the restrictions on guest and host CR4 in VMX operation. */
+#define nested_guest_cr4_valid nested_cr4_valid
+#define nested_host_cr4_valid nested_cr4_valid
+
+static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
+
+static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
+ unsigned long cr0,
+ struct kvm_vcpu *vcpu)
+{
+ if (!test_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail))
+ vmx_decache_cr3(vcpu);
+ if (!(cr0 & X86_CR0_PG)) {
+ /* From paging/starting to nonpaging */
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
+ vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) |
+ (CPU_BASED_CR3_LOAD_EXITING |
+ CPU_BASED_CR3_STORE_EXITING));
+ vcpu->arch.cr0 = cr0;
+ vmx_set_cr4(vcpu, kvm_read_cr4(vcpu));
+ } else if (!is_paging(vcpu)) {
+ /* From nonpaging to paging */
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
+ vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) &
+ ~(CPU_BASED_CR3_LOAD_EXITING |
+ CPU_BASED_CR3_STORE_EXITING));
+ vcpu->arch.cr0 = cr0;
+ vmx_set_cr4(vcpu, kvm_read_cr4(vcpu));
+ }
+
+ if (!(cr0 & X86_CR0_WP))
+ *hw_cr0 &= ~X86_CR0_WP;
+}
+
+static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ unsigned long hw_cr0;
+
+ hw_cr0 = (cr0 & ~KVM_GUEST_CR0_MASK);
+ if (enable_unrestricted_guest)
+ hw_cr0 |= KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST;
+ else {
+ hw_cr0 |= KVM_VM_CR0_ALWAYS_ON;
+
+ if (vmx->rmode.vm86_active && (cr0 & X86_CR0_PE))
+ enter_pmode(vcpu);
+
+ if (!vmx->rmode.vm86_active && !(cr0 & X86_CR0_PE))
+ enter_rmode(vcpu);
+ }
+
+#ifdef CONFIG_X86_64
+ if (vcpu->arch.efer & EFER_LME) {
+ if (!is_paging(vcpu) && (cr0 & X86_CR0_PG))
+ enter_lmode(vcpu);
+ if (is_paging(vcpu) && !(cr0 & X86_CR0_PG))
+ exit_lmode(vcpu);
+ }
+#endif
+
+ if (enable_ept && !enable_unrestricted_guest)
+ ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
+
+ vmcs_writel(CR0_READ_SHADOW, cr0);
+ vmcs_writel(GUEST_CR0, hw_cr0);
+ vcpu->arch.cr0 = cr0;
+
+ /* depends on vcpu->arch.cr0 to be set to a new value */
+ vmx->emulation_required = emulation_required(vcpu);
+}
+
+static int get_ept_level(struct kvm_vcpu *vcpu)
+{
+ /* Nested EPT currently only supports 4-level walks. */
+ if (is_guest_mode(vcpu) && nested_cpu_has_ept(get_vmcs12(vcpu)))
+ return 4;
+ if (cpu_has_vmx_ept_5levels() && (cpuid_maxphyaddr(vcpu) > 48))
+ return 5;
+ return 4;
+}
+
+static u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa)
+{
+ u64 eptp = VMX_EPTP_MT_WB;
+
+ eptp |= (get_ept_level(vcpu) == 5) ? VMX_EPTP_PWL_5 : VMX_EPTP_PWL_4;
+
+ if (enable_ept_ad_bits &&
+ (!is_guest_mode(vcpu) || nested_ept_ad_enabled(vcpu)))
+ eptp |= VMX_EPTP_AD_ENABLE_BIT;
+ eptp |= (root_hpa & PAGE_MASK);
+
+ return eptp;
+}
+
+static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
+{
+ struct kvm *kvm = vcpu->kvm;
+ unsigned long guest_cr3;
+ u64 eptp;
+
+ guest_cr3 = cr3;
+ if (enable_ept) {
+ eptp = construct_eptp(vcpu, cr3);
+ vmcs_write64(EPT_POINTER, eptp);
+
+ if (kvm_x86_ops->tlb_remote_flush) {
+ spin_lock(&to_kvm_vmx(kvm)->ept_pointer_lock);
+ to_vmx(vcpu)->ept_pointer = eptp;
+ to_kvm_vmx(kvm)->ept_pointers_match
+ = EPT_POINTERS_CHECK;
+ spin_unlock(&to_kvm_vmx(kvm)->ept_pointer_lock);
+ }
+
+ if (enable_unrestricted_guest || is_paging(vcpu) ||
+ is_guest_mode(vcpu))
+ guest_cr3 = kvm_read_cr3(vcpu);
+ else
+ guest_cr3 = to_kvm_vmx(kvm)->ept_identity_map_addr;
+ ept_load_pdptrs(vcpu);
+ }
+
+ vmcs_writel(GUEST_CR3, guest_cr3);
+}
+
+static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+{
+ /*
+ * Pass through host's Machine Check Enable value to hw_cr4, which
+ * is in force while we are in guest mode. Do not let guests control
+ * this bit, even if host CR4.MCE == 0.
+ */
+ unsigned long hw_cr4;
+
+ hw_cr4 = (cr4_read_shadow() & X86_CR4_MCE) | (cr4 & ~X86_CR4_MCE);
+ if (enable_unrestricted_guest)
+ hw_cr4 |= KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST;
+ else if (to_vmx(vcpu)->rmode.vm86_active)
+ hw_cr4 |= KVM_RMODE_VM_CR4_ALWAYS_ON;
+ else
+ hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON;
+
+ if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated()) {
+ if (cr4 & X86_CR4_UMIP) {
+ vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
+ SECONDARY_EXEC_DESC);
+ hw_cr4 &= ~X86_CR4_UMIP;
+ } else if (!is_guest_mode(vcpu) ||
+ !nested_cpu_has2(get_vmcs12(vcpu), SECONDARY_EXEC_DESC))
+ vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
+ SECONDARY_EXEC_DESC);
+ }
+
+ if (cr4 & X86_CR4_VMXE) {
+ /*
+ * To use VMXON (and later other VMX instructions), a guest
+ * must first be able to turn on cr4.VMXE (see handle_vmon()).
+ * So basically the check on whether to allow nested VMX
+ * is here. We operate under the default treatment of SMM,
+ * so VMX cannot be enabled under SMM.
+ */
+ if (!nested_vmx_allowed(vcpu) || is_smm(vcpu))
+ return 1;
+ }
+
+ if (to_vmx(vcpu)->nested.vmxon && !nested_cr4_valid(vcpu, cr4))
+ return 1;
+
+ vcpu->arch.cr4 = cr4;
+
+ if (!enable_unrestricted_guest) {
+ if (enable_ept) {
+ if (!is_paging(vcpu)) {
+ hw_cr4 &= ~X86_CR4_PAE;
+ hw_cr4 |= X86_CR4_PSE;
+ } else if (!(cr4 & X86_CR4_PAE)) {
+ hw_cr4 &= ~X86_CR4_PAE;
+ }
+ }
+
+ /*
+ * SMEP/SMAP/PKU is disabled if CPU is in non-paging mode in
+ * hardware. To emulate this behavior, SMEP/SMAP/PKU needs
+ * to be manually disabled when guest switches to non-paging
+ * mode.
+ *
+ * If !enable_unrestricted_guest, the CPU is always running
+ * with CR0.PG=1 and CR4 needs to be modified.
+ * If enable_unrestricted_guest, the CPU automatically
+ * disables SMEP/SMAP/PKU when the guest sets CR0.PG=0.
+ */
+ if (!is_paging(vcpu))
+ hw_cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE);
+ }
+
+ vmcs_writel(CR4_READ_SHADOW, cr4);
+ vmcs_writel(GUEST_CR4, hw_cr4);
+ return 0;
+}
+
+static void vmx_get_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 ar;
+
+ if (vmx->rmode.vm86_active && seg != VCPU_SREG_LDTR) {
+ *var = vmx->rmode.segs[seg];
+ if (seg == VCPU_SREG_TR
+ || var->selector == vmx_read_guest_seg_selector(vmx, seg))
+ return;
+ var->base = vmx_read_guest_seg_base(vmx, seg);
+ var->selector = vmx_read_guest_seg_selector(vmx, seg);
+ return;
+ }
+ var->base = vmx_read_guest_seg_base(vmx, seg);
+ var->limit = vmx_read_guest_seg_limit(vmx, seg);
+ var->selector = vmx_read_guest_seg_selector(vmx, seg);
+ ar = vmx_read_guest_seg_ar(vmx, seg);
+ var->unusable = (ar >> 16) & 1;
+ var->type = ar & 15;
+ var->s = (ar >> 4) & 1;
+ var->dpl = (ar >> 5) & 3;
+ /*
+ * Some userspaces do not preserve unusable property. Since usable
+ * segment has to be present according to VMX spec we can use present
+ * property to amend userspace bug by making unusable segment always
+ * nonpresent. vmx_segment_access_rights() already marks nonpresent
+ * segment as unusable.
+ */
+ var->present = !var->unusable;
+ var->avl = (ar >> 12) & 1;
+ var->l = (ar >> 13) & 1;
+ var->db = (ar >> 14) & 1;
+ var->g = (ar >> 15) & 1;
+}
+
+static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
+{
+ struct kvm_segment s;
+
+ if (to_vmx(vcpu)->rmode.vm86_active) {
+ vmx_get_segment(vcpu, &s, seg);
+ return s.base;
+ }
+ return vmx_read_guest_seg_base(to_vmx(vcpu), seg);
+}
+
+static int vmx_get_cpl(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (unlikely(vmx->rmode.vm86_active))
+ return 0;
+ else {
+ int ar = vmx_read_guest_seg_ar(vmx, VCPU_SREG_SS);
+ return VMX_AR_DPL(ar);
+ }
+}
+
+static u32 vmx_segment_access_rights(struct kvm_segment *var)
+{
+ u32 ar;
+
+ ar = var->type & 15;
+ ar |= (var->s & 1) << 4;
+ ar |= (var->dpl & 3) << 5;
+ ar |= (var->present & 1) << 7;
+ ar |= (var->avl & 1) << 12;
+ ar |= (var->l & 1) << 13;
+ ar |= (var->db & 1) << 14;
+ ar |= (var->g & 1) << 15;
+ ar |= (var->unusable || !var->present) << 16;
+
+ return ar;
+}
+
+static void vmx_set_segment(struct kvm_vcpu *vcpu,
+ struct kvm_segment *var, int seg)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+
+ vmx_segment_cache_clear(vmx);
+
+ if (vmx->rmode.vm86_active && seg != VCPU_SREG_LDTR) {
+ vmx->rmode.segs[seg] = *var;
+ if (seg == VCPU_SREG_TR)
+ vmcs_write16(sf->selector, var->selector);
+ else if (var->s)
+ fix_rmode_seg(seg, &vmx->rmode.segs[seg]);
+ goto out;
+ }
+
+ vmcs_writel(sf->base, var->base);
+ vmcs_write32(sf->limit, var->limit);
+ vmcs_write16(sf->selector, var->selector);
+
+ /*
+ * Fix the "Accessed" bit in AR field of segment registers for older
+ * qemu binaries.
+ * IA32 arch specifies that at the time of processor reset the
+ * "Accessed" bit in the AR field of segment registers is 1. And qemu
+ * is setting it to 0 in the userland code. This causes invalid guest
+ * state vmexit when "unrestricted guest" mode is turned on.
+ * Fix for this setup issue in cpu_reset is being pushed in the qemu
+ * tree. Newer qemu binaries with that qemu fix would not need this
+ * kvm hack.
+ */
+ if (enable_unrestricted_guest && (seg != VCPU_SREG_LDTR))
+ var->type |= 0x1; /* Accessed */
+
+ vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(var));
+
+out:
+ vmx->emulation_required = emulation_required(vcpu);
+}
+
+static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
+{
+ u32 ar = vmx_read_guest_seg_ar(to_vmx(vcpu), VCPU_SREG_CS);
+
+ *db = (ar >> 14) & 1;
+ *l = (ar >> 13) & 1;
+}
+
+static void vmx_get_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
+{
+ dt->size = vmcs_read32(GUEST_IDTR_LIMIT);
+ dt->address = vmcs_readl(GUEST_IDTR_BASE);
+}
+
+static void vmx_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
+{
+ vmcs_write32(GUEST_IDTR_LIMIT, dt->size);
+ vmcs_writel(GUEST_IDTR_BASE, dt->address);
+}
+
+static void vmx_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
+{
+ dt->size = vmcs_read32(GUEST_GDTR_LIMIT);
+ dt->address = vmcs_readl(GUEST_GDTR_BASE);
+}
+
+static void vmx_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
+{
+ vmcs_write32(GUEST_GDTR_LIMIT, dt->size);
+ vmcs_writel(GUEST_GDTR_BASE, dt->address);
+}
+
+static bool rmode_segment_valid(struct kvm_vcpu *vcpu, int seg)
+{
+ struct kvm_segment var;
+ u32 ar;
+
+ vmx_get_segment(vcpu, &var, seg);
+ var.dpl = 0x3;
+ if (seg == VCPU_SREG_CS)
+ var.type = 0x3;
+ ar = vmx_segment_access_rights(&var);
+
+ if (var.base != (var.selector << 4))
+ return false;
+ if (var.limit != 0xffff)
+ return false;
+ if (ar != 0xf3)
+ return false;
+
+ return true;
+}
+
+static bool code_segment_valid(struct kvm_vcpu *vcpu)
+{
+ struct kvm_segment cs;
+ unsigned int cs_rpl;
+
+ vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+ cs_rpl = cs.selector & SEGMENT_RPL_MASK;
+
+ if (cs.unusable)
+ return false;
+ if (~cs.type & (VMX_AR_TYPE_CODE_MASK|VMX_AR_TYPE_ACCESSES_MASK))
+ return false;
+ if (!cs.s)
+ return false;
+ if (cs.type & VMX_AR_TYPE_WRITEABLE_MASK) {
+ if (cs.dpl > cs_rpl)
+ return false;
+ } else {
+ if (cs.dpl != cs_rpl)
+ return false;
+ }
+ if (!cs.present)
+ return false;
+
+ /* TODO: Add Reserved field check, this'll require a new member in the kvm_segment_field structure */
+ return true;
+}
+
+static bool stack_segment_valid(struct kvm_vcpu *vcpu)
+{
+ struct kvm_segment ss;
+ unsigned int ss_rpl;
+
+ vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
+ ss_rpl = ss.selector & SEGMENT_RPL_MASK;
+
+ if (ss.unusable)
+ return true;
+ if (ss.type != 3 && ss.type != 7)
+ return false;
+ if (!ss.s)
+ return false;
+ if (ss.dpl != ss_rpl) /* DPL != RPL */
+ return false;
+ if (!ss.present)
+ return false;
+
+ return true;
+}
+
+static bool data_segment_valid(struct kvm_vcpu *vcpu, int seg)
+{
+ struct kvm_segment var;
+ unsigned int rpl;
+
+ vmx_get_segment(vcpu, &var, seg);
+ rpl = var.selector & SEGMENT_RPL_MASK;
+
+ if (var.unusable)
+ return true;
+ if (!var.s)
+ return false;
+ if (!var.present)
+ return false;
+ if (~var.type & (VMX_AR_TYPE_CODE_MASK|VMX_AR_TYPE_WRITEABLE_MASK)) {
+ if (var.dpl < rpl) /* DPL < RPL */
+ return false;
+ }
+
+ /* TODO: Add other members to kvm_segment_field to allow checking for other access
+ * rights flags
+ */
+ return true;
+}
+
+static bool tr_valid(struct kvm_vcpu *vcpu)
+{
+ struct kvm_segment tr;
+
+ vmx_get_segment(vcpu, &tr, VCPU_SREG_TR);
+
+ if (tr.unusable)
+ return false;
+ if (tr.selector & SEGMENT_TI_MASK) /* TI = 1 */
+ return false;
+ if (tr.type != 3 && tr.type != 11) /* TODO: Check if guest is in IA32e mode */
+ return false;
+ if (!tr.present)
+ return false;
+
+ return true;
+}
+
+static bool ldtr_valid(struct kvm_vcpu *vcpu)
+{
+ struct kvm_segment ldtr;
+
+ vmx_get_segment(vcpu, &ldtr, VCPU_SREG_LDTR);
+
+ if (ldtr.unusable)
+ return true;
+ if (ldtr.selector & SEGMENT_TI_MASK) /* TI = 1 */
+ return false;
+ if (ldtr.type != 2)
+ return false;
+ if (!ldtr.present)
+ return false;
+
+ return true;
+}
+
+static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
+{
+ struct kvm_segment cs, ss;
+
+ vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+ vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
+
+ return ((cs.selector & SEGMENT_RPL_MASK) ==
+ (ss.selector & SEGMENT_RPL_MASK));
+}
+
+static bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu,
+ unsigned int port, int size);
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ unsigned long exit_qualification;
+ unsigned short port;
+ int size;
+
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ port = exit_qualification >> 16;
+ size = (exit_qualification & 7) + 1;
+
+ return nested_vmx_check_io_bitmaps(vcpu, port, size);
+}
+
+/*
+ * Check if guest state is valid. Returns true if valid, false if
+ * not.
+ * We assume that registers are always usable
+ */
+static bool guest_state_valid(struct kvm_vcpu *vcpu)
+{
+ if (enable_unrestricted_guest)
+ return true;
+
+ /* real mode guest state checks */
+ if (!is_protmode(vcpu) || (vmx_get_rflags(vcpu) & X86_EFLAGS_VM)) {
+ if (!rmode_segment_valid(vcpu, VCPU_SREG_CS))
+ return false;
+ if (!rmode_segment_valid(vcpu, VCPU_SREG_SS))
+ return false;
+ if (!rmode_segment_valid(vcpu, VCPU_SREG_DS))
+ return false;
+ if (!rmode_segment_valid(vcpu, VCPU_SREG_ES))
+ return false;
+ if (!rmode_segment_valid(vcpu, VCPU_SREG_FS))
+ return false;
+ if (!rmode_segment_valid(vcpu, VCPU_SREG_GS))
+ return false;
+ } else {
+ /* protected mode guest state checks */
+ if (!cs_ss_rpl_check(vcpu))
+ return false;
+ if (!code_segment_valid(vcpu))
+ return false;
+ if (!stack_segment_valid(vcpu))
+ return false;
+ if (!data_segment_valid(vcpu, VCPU_SREG_DS))
+ return false;
+ if (!data_segment_valid(vcpu, VCPU_SREG_ES))
+ return false;
+ if (!data_segment_valid(vcpu, VCPU_SREG_FS))
+ return false;
+ if (!data_segment_valid(vcpu, VCPU_SREG_GS))
+ return false;
+ if (!tr_valid(vcpu))
+ return false;
+ if (!ldtr_valid(vcpu))
+ return false;
+ }
+ /* TODO:
+ * - Add checks on RIP
+ * - Add checks on RFLAGS
+ */
+
+ return true;
+}
+
+static bool page_address_valid(struct kvm_vcpu *vcpu, gpa_t gpa)
+{
+ return PAGE_ALIGNED(gpa) && !(gpa >> cpuid_maxphyaddr(vcpu));
+}
+
+static int init_rmode_tss(struct kvm *kvm)
+{
+ gfn_t fn;
+ u16 data = 0;
+ int idx, r;
+
+ idx = srcu_read_lock(&kvm->srcu);
+ fn = to_kvm_vmx(kvm)->tss_addr >> PAGE_SHIFT;
+ r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
+ if (r < 0)
+ goto out;
+ data = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE;
+ r = kvm_write_guest_page(kvm, fn++, &data,
+ TSS_IOPB_BASE_OFFSET, sizeof(u16));
+ if (r < 0)
+ goto out;
+ r = kvm_clear_guest_page(kvm, fn++, 0, PAGE_SIZE);
+ if (r < 0)
+ goto out;
+ r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
+ if (r < 0)
+ goto out;
+ data = ~0;
+ r = kvm_write_guest_page(kvm, fn, &data,
+ RMODE_TSS_SIZE - 2 * PAGE_SIZE - 1,
+ sizeof(u8));
+out:
+ srcu_read_unlock(&kvm->srcu, idx);
+ return r;
+}
+
+static int init_rmode_identity_map(struct kvm *kvm)
+{
+ struct kvm_vmx *kvm_vmx = to_kvm_vmx(kvm);
+ int i, idx, r = 0;
+ kvm_pfn_t identity_map_pfn;
+ u32 tmp;
+
+ /* Protect kvm_vmx->ept_identity_pagetable_done. */
+ mutex_lock(&kvm->slots_lock);
+
+ if (likely(kvm_vmx->ept_identity_pagetable_done))
+ goto out2;
+
+ if (!kvm_vmx->ept_identity_map_addr)
+ kvm_vmx->ept_identity_map_addr = VMX_EPT_IDENTITY_PAGETABLE_ADDR;
+ identity_map_pfn = kvm_vmx->ept_identity_map_addr >> PAGE_SHIFT;
+
+ r = __x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT,
+ kvm_vmx->ept_identity_map_addr, PAGE_SIZE);
+ if (r < 0)
+ goto out2;
+
+ idx = srcu_read_lock(&kvm->srcu);
+ r = kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE);
+ if (r < 0)
+ goto out;
+ /* Set up identity-mapping pagetable for EPT in real mode */
+ for (i = 0; i < PT32_ENT_PER_PAGE; i++) {
+ tmp = (i << 22) + (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |
+ _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE);
+ r = kvm_write_guest_page(kvm, identity_map_pfn,
+ &tmp, i * sizeof(tmp), sizeof(tmp));
+ if (r < 0)
+ goto out;
+ }
+ kvm_vmx->ept_identity_pagetable_done = true;
+
+out:
+ srcu_read_unlock(&kvm->srcu, idx);
+
+out2:
+ mutex_unlock(&kvm->slots_lock);
+ return r;
+}
+
+static void seg_setup(int seg)
+{
+ const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+ unsigned int ar;
+
+ vmcs_write16(sf->selector, 0);
+ vmcs_writel(sf->base, 0);
+ vmcs_write32(sf->limit, 0xffff);
+ ar = 0x93;
+ if (seg == VCPU_SREG_CS)
+ ar |= 0x08; /* code segment */
+
+ vmcs_write32(sf->ar_bytes, ar);
+}
+
+static int alloc_apic_access_page(struct kvm *kvm)
+{
+ struct page *page;
+ int r = 0;
+
+ mutex_lock(&kvm->slots_lock);
+ if (kvm->arch.apic_access_page_done)
+ goto out;
+ r = __x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
+ APIC_DEFAULT_PHYS_BASE, PAGE_SIZE);
+ if (r)
+ goto out;
+
+ page = gfn_to_page(kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
+ if (is_error_page(page)) {
+ r = -EFAULT;
+ goto out;
+ }
+
+ /*
+ * Do not pin the page in memory, so that memory hot-unplug
+ * is able to migrate it.
+ */
+ put_page(page);
+ kvm->arch.apic_access_page_done = true;
+out:
+ mutex_unlock(&kvm->slots_lock);
+ return r;
+}
+
+static int allocate_vpid(void)
+{
+ int vpid;
+
+ if (!enable_vpid)
+ return 0;
+ spin_lock(&vmx_vpid_lock);
+ vpid = find_first_zero_bit(vmx_vpid_bitmap, VMX_NR_VPIDS);
+ if (vpid < VMX_NR_VPIDS)
+ __set_bit(vpid, vmx_vpid_bitmap);
+ else
+ vpid = 0;
+ spin_unlock(&vmx_vpid_lock);
+ return vpid;
+}
+
+static void free_vpid(int vpid)
+{
+ if (!enable_vpid || vpid == 0)
+ return;
+ spin_lock(&vmx_vpid_lock);
+ __clear_bit(vpid, vmx_vpid_bitmap);
+ spin_unlock(&vmx_vpid_lock);
+}
+
+static __always_inline void vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
+ u32 msr, int type)
+{
+ int f = sizeof(unsigned long);
+
+ if (!cpu_has_vmx_msr_bitmap())
+ return;
+
+ if (static_branch_unlikely(&enable_evmcs))
+ evmcs_touch_msr_bitmap();
+
+ /*
+ * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
+ * have the write-low and read-high bitmap offsets the wrong way round.
+ * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
+ */
+ if (msr <= 0x1fff) {
+ if (type & MSR_TYPE_R)
+ /* read-low */
+ __clear_bit(msr, msr_bitmap + 0x000 / f);
+
+ if (type & MSR_TYPE_W)
+ /* write-low */
+ __clear_bit(msr, msr_bitmap + 0x800 / f);
+
+ } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
+ msr &= 0x1fff;
+ if (type & MSR_TYPE_R)
+ /* read-high */
+ __clear_bit(msr, msr_bitmap + 0x400 / f);
+
+ if (type & MSR_TYPE_W)
+ /* write-high */
+ __clear_bit(msr, msr_bitmap + 0xc00 / f);
+
+ }
+}
+
+static __always_inline void vmx_enable_intercept_for_msr(unsigned long *msr_bitmap,
+ u32 msr, int type)
+{
+ int f = sizeof(unsigned long);
+
+ if (!cpu_has_vmx_msr_bitmap())
+ return;
+
+ if (static_branch_unlikely(&enable_evmcs))
+ evmcs_touch_msr_bitmap();
+
+ /*
+ * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
+ * have the write-low and read-high bitmap offsets the wrong way round.
+ * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
+ */
+ if (msr <= 0x1fff) {
+ if (type & MSR_TYPE_R)
+ /* read-low */
+ __set_bit(msr, msr_bitmap + 0x000 / f);
+
+ if (type & MSR_TYPE_W)
+ /* write-low */
+ __set_bit(msr, msr_bitmap + 0x800 / f);
+
+ } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
+ msr &= 0x1fff;
+ if (type & MSR_TYPE_R)
+ /* read-high */
+ __set_bit(msr, msr_bitmap + 0x400 / f);
+
+ if (type & MSR_TYPE_W)
+ /* write-high */
+ __set_bit(msr, msr_bitmap + 0xc00 / f);
+
+ }
+}
+
+static __always_inline void vmx_set_intercept_for_msr(unsigned long *msr_bitmap,
+ u32 msr, int type, bool value)
+{
+ if (value)
+ vmx_enable_intercept_for_msr(msr_bitmap, msr, type);
+ else
+ vmx_disable_intercept_for_msr(msr_bitmap, msr, type);
+}
+
+/*
+ * If a msr is allowed by L0, we should check whether it is allowed by L1.
+ * The corresponding bit will be cleared unless both of L0 and L1 allow it.
+ */
+static void nested_vmx_disable_intercept_for_msr(unsigned long *msr_bitmap_l1,
+ unsigned long *msr_bitmap_nested,
+ u32 msr, int type)
+{
+ int f = sizeof(unsigned long);
+
+ /*
+ * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
+ * have the write-low and read-high bitmap offsets the wrong way round.
+ * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
+ */
+ if (msr <= 0x1fff) {
+ if (type & MSR_TYPE_R &&
+ !test_bit(msr, msr_bitmap_l1 + 0x000 / f))
+ /* read-low */
+ __clear_bit(msr, msr_bitmap_nested + 0x000 / f);
+
+ if (type & MSR_TYPE_W &&
+ !test_bit(msr, msr_bitmap_l1 + 0x800 / f))
+ /* write-low */
+ __clear_bit(msr, msr_bitmap_nested + 0x800 / f);
+
+ } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
+ msr &= 0x1fff;
+ if (type & MSR_TYPE_R &&
+ !test_bit(msr, msr_bitmap_l1 + 0x400 / f))
+ /* read-high */
+ __clear_bit(msr, msr_bitmap_nested + 0x400 / f);
+
+ if (type & MSR_TYPE_W &&
+ !test_bit(msr, msr_bitmap_l1 + 0xc00 / f))
+ /* write-high */
+ __clear_bit(msr, msr_bitmap_nested + 0xc00 / f);
+
+ }
+}
+
+static u8 vmx_msr_bitmap_mode(struct kvm_vcpu *vcpu)
+{
+ u8 mode = 0;
+
+ if (cpu_has_secondary_exec_ctrls() &&
+ (vmcs_read32(SECONDARY_VM_EXEC_CONTROL) &
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
+ mode |= MSR_BITMAP_MODE_X2APIC;
+ if (enable_apicv && kvm_vcpu_apicv_active(vcpu))
+ mode |= MSR_BITMAP_MODE_X2APIC_APICV;
+ }
+
+ return mode;
+}
+
+#define X2APIC_MSR(r) (APIC_BASE_MSR + ((r) >> 4))
+
+static void vmx_update_msr_bitmap_x2apic(unsigned long *msr_bitmap,
+ u8 mode)
+{
+ int msr;
+
+ for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
+ unsigned word = msr / BITS_PER_LONG;
+ msr_bitmap[word] = (mode & MSR_BITMAP_MODE_X2APIC_APICV) ? 0 : ~0;
+ msr_bitmap[word + (0x800 / sizeof(long))] = ~0;
+ }
+
+ if (mode & MSR_BITMAP_MODE_X2APIC) {
+ /*
+ * TPR reads and writes can be virtualized even if virtual interrupt
+ * delivery is not in use.
+ */
+ vmx_disable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_TASKPRI), MSR_TYPE_RW);
+ if (mode & MSR_BITMAP_MODE_X2APIC_APICV) {
+ vmx_enable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_TMCCT), MSR_TYPE_R);
+ vmx_disable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_EOI), MSR_TYPE_W);
+ vmx_disable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_SELF_IPI), MSR_TYPE_W);
+ }
+ }
+}
+
+static void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ unsigned long *msr_bitmap = vmx->vmcs01.msr_bitmap;
+ u8 mode = vmx_msr_bitmap_mode(vcpu);
+ u8 changed = mode ^ vmx->msr_bitmap_mode;
+
+ if (!changed)
+ return;
+
+ if (changed & (MSR_BITMAP_MODE_X2APIC | MSR_BITMAP_MODE_X2APIC_APICV))
+ vmx_update_msr_bitmap_x2apic(msr_bitmap, mode);
+
+ vmx->msr_bitmap_mode = mode;
+}
+
+static bool vmx_get_enable_apicv(struct kvm_vcpu *vcpu)
+{
+ return enable_apicv;
+}
+
+static void nested_mark_vmcs12_pages_dirty(struct kvm_vcpu *vcpu)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ gfn_t gfn;
+
+ /*
+ * Don't need to mark the APIC access page dirty; it is never
+ * written to by the CPU during APIC virtualization.
+ */
+
+ if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
+ gfn = vmcs12->virtual_apic_page_addr >> PAGE_SHIFT;
+ kvm_vcpu_mark_page_dirty(vcpu, gfn);
+ }
+
+ if (nested_cpu_has_posted_intr(vmcs12)) {
+ gfn = vmcs12->posted_intr_desc_addr >> PAGE_SHIFT;
+ kvm_vcpu_mark_page_dirty(vcpu, gfn);
+ }
+}
+
+
+static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int max_irr;
+ void *vapic_page;
+ u16 status;
+
+ if (!vmx->nested.pi_desc || !vmx->nested.pi_pending)
+ return;
+
+ vmx->nested.pi_pending = false;
+ if (!pi_test_and_clear_on(vmx->nested.pi_desc))
+ return;
+
+ max_irr = find_last_bit((unsigned long *)vmx->nested.pi_desc->pir, 256);
+ if (max_irr != 256) {
+ vapic_page = kmap(vmx->nested.virtual_apic_page);
+ __kvm_apic_update_irr(vmx->nested.pi_desc->pir,
+ vapic_page, &max_irr);
+ kunmap(vmx->nested.virtual_apic_page);
+
+ status = vmcs_read16(GUEST_INTR_STATUS);
+ if ((u8)max_irr > ((u8)status & 0xff)) {
+ status &= ~0xff;
+ status |= (u8)max_irr;
+ vmcs_write16(GUEST_INTR_STATUS, status);
+ }
+ }
+
+ nested_mark_vmcs12_pages_dirty(vcpu);
+}
+
+static u8 vmx_get_rvi(void)
+{
+ return vmcs_read16(GUEST_INTR_STATUS) & 0xff;
+}
+
+static bool vmx_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ void *vapic_page;
+ u32 vppr;
+ int rvi;
+
+ if (WARN_ON_ONCE(!is_guest_mode(vcpu)) ||
+ !nested_cpu_has_vid(get_vmcs12(vcpu)) ||
+ WARN_ON_ONCE(!vmx->nested.virtual_apic_page))
+ return false;
+
+ rvi = vmx_get_rvi();
+
+ vapic_page = kmap(vmx->nested.virtual_apic_page);
+ vppr = *((u32 *)(vapic_page + APIC_PROCPRI));
+ kunmap(vmx->nested.virtual_apic_page);
+
+ return ((rvi & 0xf0) > (vppr & 0xf0));
+}
+
+static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
+ bool nested)
+{
+#ifdef CONFIG_SMP
+ int pi_vec = nested ? POSTED_INTR_NESTED_VECTOR : POSTED_INTR_VECTOR;
+
+ if (vcpu->mode == IN_GUEST_MODE) {
+ /*
+ * The vector of interrupt to be delivered to vcpu had
+ * been set in PIR before this function.
+ *
+ * Following cases will be reached in this block, and
+ * we always send a notification event in all cases as
+ * explained below.
+ *
+ * Case 1: vcpu keeps in non-root mode. Sending a
+ * notification event posts the interrupt to vcpu.
+ *
+ * Case 2: vcpu exits to root mode and is still
+ * runnable. PIR will be synced to vIRR before the
+ * next vcpu entry. Sending a notification event in
+ * this case has no effect, as vcpu is not in root
+ * mode.
+ *
+ * Case 3: vcpu exits to root mode and is blocked.
+ * vcpu_block() has already synced PIR to vIRR and
+ * never blocks vcpu if vIRR is not cleared. Therefore,
+ * a blocked vcpu here does not wait for any requested
+ * interrupts in PIR, and sending a notification event
+ * which has no effect is safe here.
+ */
+
+ apic->send_IPI_mask(get_cpu_mask(vcpu->cpu), pi_vec);
+ return true;
+ }
+#endif
+ return false;
+}
+
+static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu,
+ int vector)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (is_guest_mode(vcpu) &&
+ vector == vmx->nested.posted_intr_nv) {
+ /*
+ * If a posted intr is not recognized by hardware,
+ * we will accomplish it in the next vmentry.
+ */
+ vmx->nested.pi_pending = true;
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+ /* the PIR and ON have been set by L1. */
+ if (!kvm_vcpu_trigger_posted_interrupt(vcpu, true))
+ kvm_vcpu_kick(vcpu);
+ return 0;
+ }
+ return -1;
+}
+/*
+ * Send interrupt to vcpu via posted interrupt way.
+ * 1. If target vcpu is running(non-root mode), send posted interrupt
+ * notification to vcpu and hardware will sync PIR to vIRR atomically.
+ * 2. If target vcpu isn't running(root mode), kick it to pick up the
+ * interrupt from PIR in next vmentry.
+ */
+static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int r;
+
+ r = vmx_deliver_nested_posted_interrupt(vcpu, vector);
+ if (!r)
+ return 0;
+
+ if (!vcpu->arch.apicv_active)
+ return -1;
+
+ if (pi_test_and_set_pir(vector, &vmx->pi_desc))
+ return 0;
+
+ /* If a previous notification has sent the IPI, nothing to do. */
+ if (pi_test_and_set_on(&vmx->pi_desc))
+ return 0;
+
+ if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false))
+ kvm_vcpu_kick(vcpu);
+
+ return 0;
+}
+
+/*
+ * Set up the vmcs's constant host-state fields, i.e., host-state fields that
+ * will not change in the lifetime of the guest.
+ * Note that host-state that does change is set elsewhere. E.g., host-state
+ * that is set differently for each CPU is set in vmx_vcpu_load(), not here.
+ */
+static void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
+{
+ u32 low32, high32;
+ unsigned long tmpl;
+ struct desc_ptr dt;
+ unsigned long cr0, cr3, cr4;
+
+ cr0 = read_cr0();
+ WARN_ON(cr0 & X86_CR0_TS);
+ vmcs_writel(HOST_CR0, cr0); /* 22.2.3 */
+
+ /*
+ * Save the most likely value for this task's CR3 in the VMCS.
+ * We can't use __get_current_cr3_fast() because we're not atomic.
+ */
+ cr3 = __read_cr3();
+ vmcs_writel(HOST_CR3, cr3); /* 22.2.3 FIXME: shadow tables */
+ vmx->loaded_vmcs->host_state.cr3 = cr3;
+
+ /* Save the most likely value for this task's CR4 in the VMCS. */
+ cr4 = cr4_read_shadow();
+ vmcs_writel(HOST_CR4, cr4); /* 22.2.3, 22.2.5 */
+ vmx->loaded_vmcs->host_state.cr4 = cr4;
+
+ vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
+#ifdef CONFIG_X86_64
+ /*
+ * Load null selectors, so we can avoid reloading them in
+ * vmx_prepare_switch_to_host(), in case userspace uses
+ * the null selectors too (the expected case).
+ */
+ vmcs_write16(HOST_DS_SELECTOR, 0);
+ vmcs_write16(HOST_ES_SELECTOR, 0);
+#else
+ vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+ vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+#endif
+ vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
+ vmcs_write16(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8); /* 22.2.4 */
+
+ store_idt(&dt);
+ vmcs_writel(HOST_IDTR_BASE, dt.address); /* 22.2.4 */
+ vmx->host_idt_base = dt.address;
+
+ vmcs_writel(HOST_RIP, vmx_return); /* 22.2.5 */
+
+ rdmsr(MSR_IA32_SYSENTER_CS, low32, high32);
+ vmcs_write32(HOST_IA32_SYSENTER_CS, low32);
+ rdmsrl(MSR_IA32_SYSENTER_EIP, tmpl);
+ vmcs_writel(HOST_IA32_SYSENTER_EIP, tmpl); /* 22.2.3 */
+
+ if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
+ rdmsr(MSR_IA32_CR_PAT, low32, high32);
+ vmcs_write64(HOST_IA32_PAT, low32 | ((u64) high32 << 32));
+ }
+}
+
+static void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
+{
+ BUILD_BUG_ON(KVM_CR4_GUEST_OWNED_BITS & ~KVM_POSSIBLE_CR4_GUEST_BITS);
+
+ vmx->vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
+ if (enable_ept)
+ vmx->vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
+ if (is_guest_mode(&vmx->vcpu))
+ vmx->vcpu.arch.cr4_guest_owned_bits &=
+ ~get_vmcs12(&vmx->vcpu)->cr4_guest_host_mask;
+ vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx->vcpu.arch.cr4_guest_owned_bits);
+}
+
+static u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx)
+{
+ u32 pin_based_exec_ctrl = vmcs_config.pin_based_exec_ctrl;
+
+ if (!kvm_vcpu_apicv_active(&vmx->vcpu))
+ pin_based_exec_ctrl &= ~PIN_BASED_POSTED_INTR;
+
+ if (!enable_vnmi)
+ pin_based_exec_ctrl &= ~PIN_BASED_VIRTUAL_NMIS;
+
+ /* Enable the preemption timer dynamically */
+ pin_based_exec_ctrl &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
+ return pin_based_exec_ctrl;
+}
+
+static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_ctrl(vmx));
+ if (cpu_has_secondary_exec_ctrls()) {
+ if (kvm_vcpu_apicv_active(vcpu))
+ vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
+ SECONDARY_EXEC_APIC_REGISTER_VIRT |
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
+ else
+ vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
+ SECONDARY_EXEC_APIC_REGISTER_VIRT |
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
+ }
+
+ if (cpu_has_vmx_msr_bitmap())
+ vmx_update_msr_bitmap(vcpu);
+}
+
+static u32 vmx_exec_control(struct vcpu_vmx *vmx)
+{
+ u32 exec_control = vmcs_config.cpu_based_exec_ctrl;
+
+ if (vmx->vcpu.arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)
+ exec_control &= ~CPU_BASED_MOV_DR_EXITING;
+
+ if (!cpu_need_tpr_shadow(&vmx->vcpu)) {
+ exec_control &= ~CPU_BASED_TPR_SHADOW;
+#ifdef CONFIG_X86_64
+ exec_control |= CPU_BASED_CR8_STORE_EXITING |
+ CPU_BASED_CR8_LOAD_EXITING;
+#endif
+ }
+ if (!enable_ept)
+ exec_control |= CPU_BASED_CR3_STORE_EXITING |
+ CPU_BASED_CR3_LOAD_EXITING |
+ CPU_BASED_INVLPG_EXITING;
+ if (kvm_mwait_in_guest(vmx->vcpu.kvm))
+ exec_control &= ~(CPU_BASED_MWAIT_EXITING |
+ CPU_BASED_MONITOR_EXITING);
+ if (kvm_hlt_in_guest(vmx->vcpu.kvm))
+ exec_control &= ~CPU_BASED_HLT_EXITING;
+ return exec_control;
+}
+
+static bool vmx_rdrand_supported(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_RDRAND_EXITING;
+}
+
+static bool vmx_rdseed_supported(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_RDSEED_EXITING;
+}
+
+static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
+{
+ struct kvm_vcpu *vcpu = &vmx->vcpu;
+
+ u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
+
+ if (!cpu_need_virtualize_apic_accesses(vcpu))
+ exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ if (vmx->vpid == 0)
+ exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
+ if (!enable_ept) {
+ exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
+ enable_unrestricted_guest = 0;
+ }
+ if (!enable_unrestricted_guest)
+ exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
+ if (kvm_pause_in_guest(vmx->vcpu.kvm))
+ exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
+ if (!kvm_vcpu_apicv_active(vcpu))
+ exec_control &= ~(SECONDARY_EXEC_APIC_REGISTER_VIRT |
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
+ exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
+
+ /* SECONDARY_EXEC_DESC is enabled/disabled on writes to CR4.UMIP,
+ * in vmx_set_cr4. */
+ exec_control &= ~SECONDARY_EXEC_DESC;
+
+ /* SECONDARY_EXEC_SHADOW_VMCS is enabled when L1 executes VMPTRLD
+ (handle_vmptrld).
+ We can NOT enable shadow_vmcs here because we don't have yet
+ a current VMCS12
+ */
+ exec_control &= ~SECONDARY_EXEC_SHADOW_VMCS;
+
+ if (!enable_pml)
+ exec_control &= ~SECONDARY_EXEC_ENABLE_PML;
+
+ if (vmx_xsaves_supported()) {
+ /* Exposing XSAVES only when XSAVE is exposed */
+ bool xsaves_enabled =
+ guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
+ guest_cpuid_has(vcpu, X86_FEATURE_XSAVES);
+
+ if (!xsaves_enabled)
+ exec_control &= ~SECONDARY_EXEC_XSAVES;
+
+ if (nested) {
+ if (xsaves_enabled)
+ vmx->nested.msrs.secondary_ctls_high |=
+ SECONDARY_EXEC_XSAVES;
+ else
+ vmx->nested.msrs.secondary_ctls_high &=
+ ~SECONDARY_EXEC_XSAVES;
+ }
+ }
+
+ if (vmx_rdtscp_supported()) {
+ bool rdtscp_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP);
+ if (!rdtscp_enabled)
+ exec_control &= ~SECONDARY_EXEC_RDTSCP;
+
+ if (nested) {
+ if (rdtscp_enabled)
+ vmx->nested.msrs.secondary_ctls_high |=
+ SECONDARY_EXEC_RDTSCP;
+ else
+ vmx->nested.msrs.secondary_ctls_high &=
+ ~SECONDARY_EXEC_RDTSCP;
+ }
+ }
+
+ if (vmx_invpcid_supported()) {
+ /* Exposing INVPCID only when PCID is exposed */
+ bool invpcid_enabled =
+ guest_cpuid_has(vcpu, X86_FEATURE_INVPCID) &&
+ guest_cpuid_has(vcpu, X86_FEATURE_PCID);
+
+ if (!invpcid_enabled) {
+ exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
+ guest_cpuid_clear(vcpu, X86_FEATURE_INVPCID);
+ }
+
+ if (nested) {
+ if (invpcid_enabled)
+ vmx->nested.msrs.secondary_ctls_high |=
+ SECONDARY_EXEC_ENABLE_INVPCID;
+ else
+ vmx->nested.msrs.secondary_ctls_high &=
+ ~SECONDARY_EXEC_ENABLE_INVPCID;
+ }
+ }
+
+ if (vmx_rdrand_supported()) {
+ bool rdrand_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDRAND);
+ if (rdrand_enabled)
+ exec_control &= ~SECONDARY_EXEC_RDRAND_EXITING;
+
+ if (nested) {
+ if (rdrand_enabled)
+ vmx->nested.msrs.secondary_ctls_high |=
+ SECONDARY_EXEC_RDRAND_EXITING;
+ else
+ vmx->nested.msrs.secondary_ctls_high &=
+ ~SECONDARY_EXEC_RDRAND_EXITING;
+ }
+ }
+
+ if (vmx_rdseed_supported()) {
+ bool rdseed_enabled = guest_cpuid_has(vcpu, X86_FEATURE_RDSEED);
+ if (rdseed_enabled)
+ exec_control &= ~SECONDARY_EXEC_RDSEED_EXITING;
+
+ if (nested) {
+ if (rdseed_enabled)
+ vmx->nested.msrs.secondary_ctls_high |=
+ SECONDARY_EXEC_RDSEED_EXITING;
+ else
+ vmx->nested.msrs.secondary_ctls_high &=
+ ~SECONDARY_EXEC_RDSEED_EXITING;
+ }
+ }
+
+ vmx->secondary_exec_control = exec_control;
+}
+
+static void ept_set_mmio_spte_mask(void)
+{
+ /*
+ * EPT Misconfigurations can be generated if the value of bits 2:0
+ * of an EPT paging-structure entry is 110b (write/execute).
+ */
+ kvm_mmu_set_mmio_spte_mask(VMX_EPT_RWX_MASK,
+ VMX_EPT_MISCONFIG_WX_VALUE);
+}
+
+#define VMX_XSS_EXIT_BITMAP 0
+/*
+ * Sets up the vmcs for emulated real mode.
+ */
+static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
+{
+ int i;
+
+ if (enable_shadow_vmcs) {
+ /*
+ * At vCPU creation, "VMWRITE to any supported field
+ * in the VMCS" is supported, so use the more
+ * permissive vmx_vmread_bitmap to specify both read
+ * and write permissions for the shadow VMCS.
+ */
+ vmcs_write64(VMREAD_BITMAP, __pa(vmx_vmread_bitmap));
+ vmcs_write64(VMWRITE_BITMAP, __pa(vmx_vmread_bitmap));
+ }
+ if (cpu_has_vmx_msr_bitmap())
+ vmcs_write64(MSR_BITMAP, __pa(vmx->vmcs01.msr_bitmap));
+
+ vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
+
+ /* Control */
+ vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_ctrl(vmx));
+ vmx->hv_deadline_tsc = -1;
+
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, vmx_exec_control(vmx));
+
+ if (cpu_has_secondary_exec_ctrls()) {
+ vmx_compute_secondary_exec_control(vmx);
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
+ vmx->secondary_exec_control);
+ }
+
+ if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
+ vmcs_write64(EOI_EXIT_BITMAP0, 0);
+ vmcs_write64(EOI_EXIT_BITMAP1, 0);
+ vmcs_write64(EOI_EXIT_BITMAP2, 0);
+ vmcs_write64(EOI_EXIT_BITMAP3, 0);
+
+ vmcs_write16(GUEST_INTR_STATUS, 0);
+
+ vmcs_write16(POSTED_INTR_NV, POSTED_INTR_VECTOR);
+ vmcs_write64(POSTED_INTR_DESC_ADDR, __pa((&vmx->pi_desc)));
+ }
+
+ if (!kvm_pause_in_guest(vmx->vcpu.kvm)) {
+ vmcs_write32(PLE_GAP, ple_gap);
+ vmx->ple_window = ple_window;
+ vmx->ple_window_dirty = true;
+ }
+
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
+ vmcs_write32(CR3_TARGET_COUNT, 0); /* 22.2.1 */
+
+ vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */
+ vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */
+ vmx_set_constant_host_state(vmx);
+ vmcs_writel(HOST_FS_BASE, 0); /* 22.2.4 */
+ vmcs_writel(HOST_GS_BASE, 0); /* 22.2.4 */
+
+ if (cpu_has_vmx_vmfunc())
+ vmcs_write64(VM_FUNCTION_CONTROL, 0);
+
+ vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0);
+ vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host.val));
+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0);
+ vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest.val));
+
+ if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT)
+ vmcs_write64(GUEST_IA32_PAT, vmx->vcpu.arch.pat);
+
+ for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i) {
+ u32 index = vmx_msr_index[i];
+ u32 data_low, data_high;
+ int j = vmx->nmsrs;
+
+ if (rdmsr_safe(index, &data_low, &data_high) < 0)
+ continue;
+ if (wrmsr_safe(index, data_low, data_high) < 0)
+ continue;
+ vmx->guest_msrs[j].index = i;
+ vmx->guest_msrs[j].data = 0;
+ vmx->guest_msrs[j].mask = -1ull;
+ ++vmx->nmsrs;
+ }
+
+ vm_exit_controls_init(vmx, vmcs_config.vmexit_ctrl);
+
+ /* 22.2.1, 20.8.1 */
+ vm_entry_controls_init(vmx, vmcs_config.vmentry_ctrl);
+
+ vmx->vcpu.arch.cr0_guest_owned_bits = X86_CR0_TS;
+ vmcs_writel(CR0_GUEST_HOST_MASK, ~X86_CR0_TS);
+
+ set_cr4_guest_host_mask(vmx);
+
+ if (vmx_xsaves_supported())
+ vmcs_write64(XSS_EXIT_BITMAP, VMX_XSS_EXIT_BITMAP);
+
+ if (enable_pml) {
+ ASSERT(vmx->pml_pg);
+ vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
+ vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
+ }
+
+ if (cpu_has_vmx_encls_vmexit())
+ vmcs_write64(ENCLS_EXITING_BITMAP, -1ull);
+}
+
+static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct msr_data apic_base_msr;
+ u64 cr0;
+
+ vmx->rmode.vm86_active = 0;
+ vmx->spec_ctrl = 0;
+
+ vcpu->arch.microcode_version = 0x100000000ULL;
+ vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
+ kvm_set_cr8(vcpu, 0);
+
+ if (!init_event) {
+ apic_base_msr.data = APIC_DEFAULT_PHYS_BASE |
+ MSR_IA32_APICBASE_ENABLE;
+ if (kvm_vcpu_is_reset_bsp(vcpu))
+ apic_base_msr.data |= MSR_IA32_APICBASE_BSP;
+ apic_base_msr.host_initiated = true;
+ kvm_set_apic_base(vcpu, &apic_base_msr);
+ }
+
+ vmx_segment_cache_clear(vmx);
+
+ seg_setup(VCPU_SREG_CS);
+ vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
+ vmcs_writel(GUEST_CS_BASE, 0xffff0000ul);
+
+ seg_setup(VCPU_SREG_DS);
+ seg_setup(VCPU_SREG_ES);
+ seg_setup(VCPU_SREG_FS);
+ seg_setup(VCPU_SREG_GS);
+ seg_setup(VCPU_SREG_SS);
+
+ vmcs_write16(GUEST_TR_SELECTOR, 0);
+ vmcs_writel(GUEST_TR_BASE, 0);
+ vmcs_write32(GUEST_TR_LIMIT, 0xffff);
+ vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
+
+ vmcs_write16(GUEST_LDTR_SELECTOR, 0);
+ vmcs_writel(GUEST_LDTR_BASE, 0);
+ vmcs_write32(GUEST_LDTR_LIMIT, 0xffff);
+ vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082);
+
+ if (!init_event) {
+ vmcs_write32(GUEST_SYSENTER_CS, 0);
+ vmcs_writel(GUEST_SYSENTER_ESP, 0);
+ vmcs_writel(GUEST_SYSENTER_EIP, 0);
+ vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
+ }
+
+ kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
+ kvm_rip_write(vcpu, 0xfff0);
+
+ vmcs_writel(GUEST_GDTR_BASE, 0);
+ vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
+
+ vmcs_writel(GUEST_IDTR_BASE, 0);
+ vmcs_write32(GUEST_IDTR_LIMIT, 0xffff);
+
+ vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
+ vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
+ vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, 0);
+ if (kvm_mpx_supported())
+ vmcs_write64(GUEST_BNDCFGS, 0);
+
+ setup_msrs(vmx);
+
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */
+
+ if (cpu_has_vmx_tpr_shadow() && !init_event) {
+ vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
+ if (cpu_need_tpr_shadow(vcpu))
+ vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
+ __pa(vcpu->arch.apic->regs));
+ vmcs_write32(TPR_THRESHOLD, 0);
+ }
+
+ kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
+
+ if (vmx->vpid != 0)
+ vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
+
+ cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
+ vmx->vcpu.arch.cr0 = cr0;
+ vmx_set_cr0(vcpu, cr0); /* enter rmode */
+ vmx_set_cr4(vcpu, 0);
+ vmx_set_efer(vcpu, 0);
+
+ update_exception_bitmap(vcpu);
+
+ vpid_sync_context(vmx->vpid);
+ if (init_event)
+ vmx_clear_hlt(vcpu);
+
+ vmx_update_fb_clear_dis(vcpu, vmx);
+}
+
+/*
+ * In nested virtualization, check if L1 asked to exit on external interrupts.
+ * For most existing hypervisors, this will always return true.
+ */
+static bool nested_exit_on_intr(struct kvm_vcpu *vcpu)
+{
+ return get_vmcs12(vcpu)->pin_based_vm_exec_control &
+ PIN_BASED_EXT_INTR_MASK;
+}
+
+/*
+ * In nested virtualization, check if L1 has set
+ * VM_EXIT_ACK_INTR_ON_EXIT
+ */
+static bool nested_exit_intr_ack_set(struct kvm_vcpu *vcpu)
+{
+ return get_vmcs12(vcpu)->vm_exit_controls &
+ VM_EXIT_ACK_INTR_ON_EXIT;
+}
+
+static bool nested_exit_on_nmi(struct kvm_vcpu *vcpu)
+{
+ return nested_cpu_has_nmi_exiting(get_vmcs12(vcpu));
+}
+
+static void enable_irq_window(struct kvm_vcpu *vcpu)
+{
+ vmcs_set_bits(CPU_BASED_VM_EXEC_CONTROL,
+ CPU_BASED_VIRTUAL_INTR_PENDING);
+}
+
+static void enable_nmi_window(struct kvm_vcpu *vcpu)
+{
+ if (!enable_vnmi ||
+ vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) {
+ enable_irq_window(vcpu);
+ return;
+ }
+
+ vmcs_set_bits(CPU_BASED_VM_EXEC_CONTROL,
+ CPU_BASED_VIRTUAL_NMI_PENDING);
+}
+
+static void vmx_inject_irq(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ uint32_t intr;
+ int irq = vcpu->arch.interrupt.nr;
+
+ trace_kvm_inj_virq(irq);
+
+ ++vcpu->stat.irq_injections;
+ if (vmx->rmode.vm86_active) {
+ int inc_eip = 0;
+ if (vcpu->arch.interrupt.soft)
+ inc_eip = vcpu->arch.event_exit_inst_len;
+ if (kvm_inject_realmode_interrupt(vcpu, irq, inc_eip) != EMULATE_DONE)
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+ return;
+ }
+ intr = irq | INTR_INFO_VALID_MASK;
+ if (vcpu->arch.interrupt.soft) {
+ intr |= INTR_TYPE_SOFT_INTR;
+ vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+ vmx->vcpu.arch.event_exit_inst_len);
+ } else
+ intr |= INTR_TYPE_EXT_INTR;
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr);
+
+ vmx_clear_hlt(vcpu);
+}
+
+static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (!enable_vnmi) {
+ /*
+ * Tracking the NMI-blocked state in software is built upon
+ * finding the next open IRQ window. This, in turn, depends on
+ * well-behaving guests: They have to keep IRQs disabled at
+ * least as long as the NMI handler runs. Otherwise we may
+ * cause NMI nesting, maybe breaking the guest. But as this is
+ * highly unlikely, we can live with the residual risk.
+ */
+ vmx->loaded_vmcs->soft_vnmi_blocked = 1;
+ vmx->loaded_vmcs->vnmi_blocked_time = 0;
+ }
+
+ ++vcpu->stat.nmi_injections;
+ vmx->loaded_vmcs->nmi_known_unmasked = false;
+
+ if (vmx->rmode.vm86_active) {
+ if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) != EMULATE_DONE)
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+ return;
+ }
+
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
+
+ vmx_clear_hlt(vcpu);
+}
+
+static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ bool masked;
+
+ if (!enable_vnmi)
+ return vmx->loaded_vmcs->soft_vnmi_blocked;
+ if (vmx->loaded_vmcs->nmi_known_unmasked)
+ return false;
+ masked = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_NMI;
+ vmx->loaded_vmcs->nmi_known_unmasked = !masked;
+ return masked;
+}
+
+static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (!enable_vnmi) {
+ if (vmx->loaded_vmcs->soft_vnmi_blocked != masked) {
+ vmx->loaded_vmcs->soft_vnmi_blocked = masked;
+ vmx->loaded_vmcs->vnmi_blocked_time = 0;
+ }
+ } else {
+ vmx->loaded_vmcs->nmi_known_unmasked = !masked;
+ if (masked)
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ else
+ vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ }
+}
+
+static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
+{
+ if (to_vmx(vcpu)->nested.nested_run_pending)
+ return 0;
+
+ if (!enable_vnmi &&
+ to_vmx(vcpu)->loaded_vmcs->soft_vnmi_blocked)
+ return 0;
+
+ return !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+ (GUEST_INTR_STATE_MOV_SS | GUEST_INTR_STATE_STI
+ | GUEST_INTR_STATE_NMI));
+}
+
+static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
+{
+ if (to_vmx(vcpu)->nested.nested_run_pending)
+ return false;
+
+ if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu))
+ return true;
+
+ return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
+ !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+ (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
+}
+
+static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
+{
+ int ret;
+
+ if (enable_unrestricted_guest)
+ return 0;
+
+ ret = x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, addr,
+ PAGE_SIZE * 3);
+ if (ret)
+ return ret;
+ to_kvm_vmx(kvm)->tss_addr = addr;
+ return init_rmode_tss(kvm);
+}
+
+static int vmx_set_identity_map_addr(struct kvm *kvm, u64 ident_addr)
+{
+ to_kvm_vmx(kvm)->ept_identity_map_addr = ident_addr;
+ return 0;
+}
+
+static bool rmode_exception(struct kvm_vcpu *vcpu, int vec)
+{
+ switch (vec) {
+ case BP_VECTOR:
+ /*
+ * Update instruction length as we may reinject the exception
+ * from user space while in guest debugging mode.
+ */
+ to_vmx(vcpu)->vcpu.arch.event_exit_inst_len =
+ vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+ if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
+ return false;
+ /* fall through */
+ case DB_VECTOR:
+ if (vcpu->guest_debug &
+ (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
+ return false;
+ /* fall through */
+ case DE_VECTOR:
+ case OF_VECTOR:
+ case BR_VECTOR:
+ case UD_VECTOR:
+ case DF_VECTOR:
+ case SS_VECTOR:
+ case GP_VECTOR:
+ case MF_VECTOR:
+ return true;
+ break;
+ }
+ return false;
+}
+
+static int handle_rmode_exception(struct kvm_vcpu *vcpu,
+ int vec, u32 err_code)
+{
+ /*
+ * Instruction with address size override prefix opcode 0x67
+ * Cause the #SS fault with 0 error code in VM86 mode.
+ */
+ if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0) {
+ if (kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE) {
+ if (vcpu->arch.halt_request) {
+ vcpu->arch.halt_request = 0;
+ return kvm_vcpu_halt(vcpu);
+ }
+ return 1;
+ }
+ return 0;
+ }
+
+ /*
+ * Forward all other exceptions that are valid in real mode.
+ * FIXME: Breaks guest debugging in real mode, needs to be fixed with
+ * the required debugging infrastructure rework.
+ */
+ kvm_queue_exception(vcpu, vec);
+ return 1;
+}
+
+/*
+ * Trigger machine check on the host. We assume all the MSRs are already set up
+ * by the CPU and that we still run on the same CPU as the MCE occurred on.
+ * We pass a fake environment to the machine check handler because we want
+ * the guest to be always treated like user space, no matter what context
+ * it used internally.
+ */
+static void kvm_machine_check(void)
+{
+#if defined(CONFIG_X86_MCE)
+ struct pt_regs regs = {
+ .cs = 3, /* Fake ring 3 no matter what the guest ran on */
+ .flags = X86_EFLAGS_IF,
+ };
+
+ do_machine_check(®s, 0);
+#endif
+}
+
+static int handle_machine_check(struct kvm_vcpu *vcpu)
+{
+ /* already handled by vcpu_run */
+ return 1;
+}
+
+static int handle_exception(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct kvm_run *kvm_run = vcpu->run;
+ u32 intr_info, ex_no, error_code;
+ unsigned long cr2, rip, dr6;
+ u32 vect_info;
+ enum emulation_result er;
+
+ vect_info = vmx->idt_vectoring_info;
+ intr_info = vmx->exit_intr_info;
+
+ if (is_machine_check(intr_info))
+ return handle_machine_check(vcpu);
+
+ if (is_nmi(intr_info))
+ return 1; /* already handled by vmx_vcpu_run() */
+
+ if (is_invalid_opcode(intr_info))
+ return handle_ud(vcpu);
+
+ error_code = 0;
+ if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
+ error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+
+ if (!vmx->rmode.vm86_active && is_gp_fault(intr_info)) {
+ WARN_ON_ONCE(!enable_vmware_backdoor);
+ er = kvm_emulate_instruction(vcpu,
+ EMULTYPE_VMWARE | EMULTYPE_NO_UD_ON_FAIL);
+ if (er == EMULATE_USER_EXIT)
+ return 0;
+ else if (er != EMULATE_DONE)
+ kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
+ return 1;
+ }
+
+ /*
+ * The #PF with PFEC.RSVD = 1 indicates the guest is accessing
+ * MMIO, it is better to report an internal error.
+ * See the comments in vmx_handle_exit.
+ */
+ if ((vect_info & VECTORING_INFO_VALID_MASK) &&
+ !(is_page_fault(intr_info) && !(error_code & PFERR_RSVD_MASK))) {
+ vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+ vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_SIMUL_EX;
+ vcpu->run->internal.ndata = 3;
+ vcpu->run->internal.data[0] = vect_info;
+ vcpu->run->internal.data[1] = intr_info;
+ vcpu->run->internal.data[2] = error_code;
+ return 0;
+ }
+
+ if (is_page_fault(intr_info)) {
+ cr2 = vmcs_readl(EXIT_QUALIFICATION);
+ /* EPT won't cause page fault directly */
+ WARN_ON_ONCE(!vcpu->arch.apf.host_apf_reason && enable_ept);
+ return kvm_handle_page_fault(vcpu, error_code, cr2, NULL, 0);
+ }
+
+ ex_no = intr_info & INTR_INFO_VECTOR_MASK;
+
+ if (vmx->rmode.vm86_active && rmode_exception(vcpu, ex_no))
+ return handle_rmode_exception(vcpu, ex_no, error_code);
+
+ switch (ex_no) {
+ case AC_VECTOR:
+ kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
+ return 1;
+ case DB_VECTOR:
+ dr6 = vmcs_readl(EXIT_QUALIFICATION);
+ if (!(vcpu->guest_debug &
+ (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
+ vcpu->arch.dr6 &= ~15;
+ vcpu->arch.dr6 |= dr6 | DR6_RTM;
+ if (is_icebp(intr_info))
+ skip_emulated_instruction(vcpu);
+
+ kvm_queue_exception(vcpu, DB_VECTOR);
+ return 1;
+ }
+ kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1;
+ kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7);
+ /* fall through */
+ case BP_VECTOR:
+ /*
+ * Update instruction length as we may reinject #BP from
+ * user space while in guest debugging mode. Reading it for
+ * #DB as well causes no harm, it is not used in that case.
+ */
+ vmx->vcpu.arch.event_exit_inst_len =
+ vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+ kvm_run->exit_reason = KVM_EXIT_DEBUG;
+ rip = kvm_rip_read(vcpu);
+ kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
+ kvm_run->debug.arch.exception = ex_no;
+ break;
+ default:
+ kvm_run->exit_reason = KVM_EXIT_EXCEPTION;
+ kvm_run->ex.exception = ex_no;
+ kvm_run->ex.error_code = error_code;
+ break;
+ }
+ return 0;
+}
+
+static int handle_external_interrupt(struct kvm_vcpu *vcpu)
+{
+ ++vcpu->stat.irq_exits;
+ return 1;
+}
+
+static int handle_triple_fault(struct kvm_vcpu *vcpu)
+{
+ vcpu->run->exit_reason = KVM_EXIT_SHUTDOWN;
+ vcpu->mmio_needed = 0;
+ return 0;
+}
+
+static int handle_io(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qualification;
+ int size, in, string;
+ unsigned port;
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ string = (exit_qualification & 16) != 0;
+
+ ++vcpu->stat.io_exits;
+
+ if (string)
+ return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
+
+ port = exit_qualification >> 16;
+ size = (exit_qualification & 7) + 1;
+ in = (exit_qualification & 8) != 0;
+
+ return kvm_fast_pio(vcpu, size, port, in);
+}
+
+static void
+vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
+{
+ /*
+ * Patch in the VMCALL instruction:
+ */
+ hypercall[0] = 0x0f;
+ hypercall[1] = 0x01;
+ hypercall[2] = 0xc1;
+}
+
+/* called to set cr0 as appropriate for a mov-to-cr0 exit. */
+static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
+{
+ if (is_guest_mode(vcpu)) {
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ unsigned long orig_val = val;
+
+ /*
+ * We get here when L2 changed cr0 in a way that did not change
+ * any of L1's shadowed bits (see nested_vmx_exit_handled_cr),
+ * but did change L0 shadowed bits. So we first calculate the
+ * effective cr0 value that L1 would like to write into the
+ * hardware. It consists of the L2-owned bits from the new
+ * value combined with the L1-owned bits from L1's guest_cr0.
+ */
+ val = (val & ~vmcs12->cr0_guest_host_mask) |
+ (vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask);
+
+ if (!nested_guest_cr0_valid(vcpu, val))
+ return 1;
+
+ if (kvm_set_cr0(vcpu, val))
+ return 1;
+ vmcs_writel(CR0_READ_SHADOW, orig_val);
+ return 0;
+ } else {
+ if (to_vmx(vcpu)->nested.vmxon &&
+ !nested_host_cr0_valid(vcpu, val))
+ return 1;
+
+ return kvm_set_cr0(vcpu, val);
+ }
+}
+
+static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val)
+{
+ if (is_guest_mode(vcpu)) {
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ unsigned long orig_val = val;
+
+ /* analogously to handle_set_cr0 */
+ val = (val & ~vmcs12->cr4_guest_host_mask) |
+ (vmcs12->guest_cr4 & vmcs12->cr4_guest_host_mask);
+ if (kvm_set_cr4(vcpu, val))
+ return 1;
+ vmcs_writel(CR4_READ_SHADOW, orig_val);
+ return 0;
+ } else
+ return kvm_set_cr4(vcpu, val);
+}
+
+static int handle_desc(struct kvm_vcpu *vcpu)
+{
+ WARN_ON(!(vcpu->arch.cr4 & X86_CR4_UMIP));
+ return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
+}
+
+static int handle_cr(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qualification, val;
+ int cr;
+ int reg;
+ int err;
+ int ret;
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ cr = exit_qualification & 15;
+ reg = (exit_qualification >> 8) & 15;
+ switch ((exit_qualification >> 4) & 3) {
+ case 0: /* mov to cr */
+ val = kvm_register_readl(vcpu, reg);
+ trace_kvm_cr_write(cr, val);
+ switch (cr) {
+ case 0:
+ err = handle_set_cr0(vcpu, val);
+ return kvm_complete_insn_gp(vcpu, err);
+ case 3:
+ WARN_ON_ONCE(enable_unrestricted_guest);
+ err = kvm_set_cr3(vcpu, val);
+ return kvm_complete_insn_gp(vcpu, err);
+ case 4:
+ err = handle_set_cr4(vcpu, val);
+ return kvm_complete_insn_gp(vcpu, err);
+ case 8: {
+ u8 cr8_prev = kvm_get_cr8(vcpu);
+ u8 cr8 = (u8)val;
+ err = kvm_set_cr8(vcpu, cr8);
+ ret = kvm_complete_insn_gp(vcpu, err);
+ if (lapic_in_kernel(vcpu))
+ return ret;
+ if (cr8_prev <= cr8)
+ return ret;
+ /*
+ * TODO: we might be squashing a
+ * KVM_GUESTDBG_SINGLESTEP-triggered
+ * KVM_EXIT_DEBUG here.
+ */
+ vcpu->run->exit_reason = KVM_EXIT_SET_TPR;
+ return 0;
+ }
+ }
+ break;
+ case 2: /* clts */
+ WARN_ONCE(1, "Guest should always own CR0.TS");
+ vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
+ trace_kvm_cr_write(0, kvm_read_cr0(vcpu));
+ return kvm_skip_emulated_instruction(vcpu);
+ case 1: /*mov from cr*/
+ switch (cr) {
+ case 3:
+ WARN_ON_ONCE(enable_unrestricted_guest);
+ val = kvm_read_cr3(vcpu);
+ kvm_register_write(vcpu, reg, val);
+ trace_kvm_cr_read(cr, val);
+ return kvm_skip_emulated_instruction(vcpu);
+ case 8:
+ val = kvm_get_cr8(vcpu);
+ kvm_register_write(vcpu, reg, val);
+ trace_kvm_cr_read(cr, val);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ break;
+ case 3: /* lmsw */
+ val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f;
+ trace_kvm_cr_write(0, (kvm_read_cr0(vcpu) & ~0xful) | val);
+ kvm_lmsw(vcpu, val);
+
+ return kvm_skip_emulated_instruction(vcpu);
+ default:
+ break;
+ }
+ vcpu->run->exit_reason = 0;
+ vcpu_unimpl(vcpu, "unhandled control register: op %d cr %d\n",
+ (int)(exit_qualification >> 4) & 3, cr);
+ return 0;
+}
+
+static int handle_dr(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qualification;
+ int dr, dr7, reg;
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ dr = exit_qualification & DEBUG_REG_ACCESS_NUM;
+
+ /* First, if DR does not exist, trigger UD */
+ if (!kvm_require_dr(vcpu, dr))
+ return 1;
+
+ /* Do not handle if the CPL > 0, will trigger GP on re-entry */
+ if (!kvm_require_cpl(vcpu, 0))
+ return 1;
+ dr7 = vmcs_readl(GUEST_DR7);
+ if (dr7 & DR7_GD) {
+ /*
+ * As the vm-exit takes precedence over the debug trap, we
+ * need to emulate the latter, either for the host or the
+ * guest debugging itself.
+ */
+ if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
+ vcpu->run->debug.arch.dr6 = vcpu->arch.dr6;
+ vcpu->run->debug.arch.dr7 = dr7;
+ vcpu->run->debug.arch.pc = kvm_get_linear_rip(vcpu);
+ vcpu->run->debug.arch.exception = DB_VECTOR;
+ vcpu->run->exit_reason = KVM_EXIT_DEBUG;
+ return 0;
+ } else {
+ vcpu->arch.dr6 &= ~15;
+ vcpu->arch.dr6 |= DR6_BD | DR6_RTM;
+ kvm_queue_exception(vcpu, DB_VECTOR);
+ return 1;
+ }
+ }
+
+ if (vcpu->guest_debug == 0) {
+ vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
+ CPU_BASED_MOV_DR_EXITING);
+
+ /*
+ * No more DR vmexits; force a reload of the debug registers
+ * and reenter on this instruction. The next vmexit will
+ * retrieve the full state of the debug registers.
+ */
+ vcpu->arch.switch_db_regs |= KVM_DEBUGREG_WONT_EXIT;
+ return 1;
+ }
+
+ reg = DEBUG_REG_ACCESS_REG(exit_qualification);
+ if (exit_qualification & TYPE_MOV_FROM_DR) {
+ unsigned long val;
+
+ if (kvm_get_dr(vcpu, dr, &val))
+ return 1;
+ kvm_register_write(vcpu, reg, val);
+ } else
+ if (kvm_set_dr(vcpu, dr, kvm_register_readl(vcpu, reg)))
+ return 1;
+
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static u64 vmx_get_dr6(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.dr6;
+}
+
+static void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val)
+{
+}
+
+static void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
+{
+ get_debugreg(vcpu->arch.db[0], 0);
+ get_debugreg(vcpu->arch.db[1], 1);
+ get_debugreg(vcpu->arch.db[2], 2);
+ get_debugreg(vcpu->arch.db[3], 3);
+ get_debugreg(vcpu->arch.dr6, 6);
+ vcpu->arch.dr7 = vmcs_readl(GUEST_DR7);
+
+ vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_WONT_EXIT;
+ vmcs_set_bits(CPU_BASED_VM_EXEC_CONTROL, CPU_BASED_MOV_DR_EXITING);
+}
+
+static void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val)
+{
+ vmcs_writel(GUEST_DR7, val);
+}
+
+static int handle_cpuid(struct kvm_vcpu *vcpu)
+{
+ return kvm_emulate_cpuid(vcpu);
+}
+
+static int handle_rdmsr(struct kvm_vcpu *vcpu)
+{
+ u32 ecx = vcpu->arch.regs[VCPU_REGS_RCX];
+ struct msr_data msr_info;
+
+ msr_info.index = ecx;
+ msr_info.host_initiated = false;
+ if (vmx_get_msr(vcpu, &msr_info)) {
+ trace_kvm_msr_read_ex(ecx);
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ trace_kvm_msr_read(ecx, msr_info.data);
+
+ /* FIXME: handling of bits 32:63 of rax, rdx */
+ vcpu->arch.regs[VCPU_REGS_RAX] = msr_info.data & -1u;
+ vcpu->arch.regs[VCPU_REGS_RDX] = (msr_info.data >> 32) & -1u;
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static int handle_wrmsr(struct kvm_vcpu *vcpu)
+{
+ struct msr_data msr;
+ u32 ecx = vcpu->arch.regs[VCPU_REGS_RCX];
+ u64 data = (vcpu->arch.regs[VCPU_REGS_RAX] & -1u)
+ | ((u64)(vcpu->arch.regs[VCPU_REGS_RDX] & -1u) << 32);
+
+ msr.data = data;
+ msr.index = ecx;
+ msr.host_initiated = false;
+ if (kvm_set_msr(vcpu, &msr) != 0) {
+ trace_kvm_msr_write_ex(ecx, data);
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ trace_kvm_msr_write(ecx, data);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static int handle_tpr_below_threshold(struct kvm_vcpu *vcpu)
+{
+ kvm_apic_update_ppr(vcpu);
+ return 1;
+}
+
+static int handle_interrupt_window(struct kvm_vcpu *vcpu)
+{
+ vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
+ CPU_BASED_VIRTUAL_INTR_PENDING);
+
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+
+ ++vcpu->stat.irq_window_exits;
+ return 1;
+}
+
+static int handle_halt(struct kvm_vcpu *vcpu)
+{
+ return kvm_emulate_halt(vcpu);
+}
+
+static int handle_vmcall(struct kvm_vcpu *vcpu)
+{
+ return kvm_emulate_hypercall(vcpu);
+}
+
+static int handle_invd(struct kvm_vcpu *vcpu)
+{
+ return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
+}
+
+static int handle_invlpg(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ kvm_mmu_invlpg(vcpu, exit_qualification);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static int handle_rdpmc(struct kvm_vcpu *vcpu)
+{
+ int err;
+
+ err = kvm_rdpmc(vcpu);
+ return kvm_complete_insn_gp(vcpu, err);
+}
+
+static int handle_wbinvd(struct kvm_vcpu *vcpu)
+{
+ return kvm_emulate_wbinvd(vcpu);
+}
+
+static int handle_xsetbv(struct kvm_vcpu *vcpu)
+{
+ u64 new_bv = kvm_read_edx_eax(vcpu);
+ u32 index = kvm_register_read(vcpu, VCPU_REGS_RCX);
+
+ if (kvm_set_xcr(vcpu, index, new_bv) == 0)
+ return kvm_skip_emulated_instruction(vcpu);
+ return 1;
+}
+
+static int handle_xsaves(struct kvm_vcpu *vcpu)
+{
+ kvm_skip_emulated_instruction(vcpu);
+ WARN(1, "this should never happen\n");
+ return 1;
+}
+
+static int handle_xrstors(struct kvm_vcpu *vcpu)
+{
+ kvm_skip_emulated_instruction(vcpu);
+ WARN(1, "this should never happen\n");
+ return 1;
+}
+
+static int handle_apic_access(struct kvm_vcpu *vcpu)
+{
+ if (likely(fasteoi)) {
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ int access_type, offset;
+
+ access_type = exit_qualification & APIC_ACCESS_TYPE;
+ offset = exit_qualification & APIC_ACCESS_OFFSET;
+ /*
+ * Sane guest uses MOV to write EOI, with written value
+ * not cared. So make a short-circuit here by avoiding
+ * heavy instruction emulation.
+ */
+ if ((access_type == TYPE_LINEAR_APIC_INST_WRITE) &&
+ (offset == APIC_EOI)) {
+ kvm_lapic_set_eoi(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ }
+ return kvm_emulate_instruction(vcpu, 0) == EMULATE_DONE;
+}
+
+static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ int vector = exit_qualification & 0xff;
+
+ /* EOI-induced VM exit is trap-like and thus no need to adjust IP */
+ kvm_apic_set_eoi_accelerated(vcpu, vector);
+ return 1;
+}
+
+static int handle_apic_write(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ u32 offset = exit_qualification & 0xfff;
+
+ /* APIC-write VM exit is trap-like and thus no need to adjust IP */
+ kvm_apic_write_nodecode(vcpu, offset);
+ return 1;
+}
+
+static int handle_task_switch(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ unsigned long exit_qualification;
+ bool has_error_code = false;
+ u32 error_code = 0;
+ u16 tss_selector;
+ int reason, type, idt_v, idt_index;
+
+ idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+ idt_index = (vmx->idt_vectoring_info & VECTORING_INFO_VECTOR_MASK);
+ type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ reason = (u32)exit_qualification >> 30;
+ if (reason == TASK_SWITCH_GATE && idt_v) {
+ switch (type) {
+ case INTR_TYPE_NMI_INTR:
+ vcpu->arch.nmi_injected = false;
+ vmx_set_nmi_mask(vcpu, true);
+ break;
+ case INTR_TYPE_EXT_INTR:
+ case INTR_TYPE_SOFT_INTR:
+ kvm_clear_interrupt_queue(vcpu);
+ break;
+ case INTR_TYPE_HARD_EXCEPTION:
+ if (vmx->idt_vectoring_info &
+ VECTORING_INFO_DELIVER_CODE_MASK) {
+ has_error_code = true;
+ error_code =
+ vmcs_read32(IDT_VECTORING_ERROR_CODE);
+ }
+ /* fall through */
+ case INTR_TYPE_SOFT_EXCEPTION:
+ kvm_clear_exception_queue(vcpu);
+ break;
+ default:
+ break;
+ }
+ }
+ tss_selector = exit_qualification;
+
+ if (!idt_v || (type != INTR_TYPE_HARD_EXCEPTION &&
+ type != INTR_TYPE_EXT_INTR &&
+ type != INTR_TYPE_NMI_INTR))
+ skip_emulated_instruction(vcpu);
+
+ if (kvm_task_switch(vcpu, tss_selector,
+ type == INTR_TYPE_SOFT_INTR ? idt_index : -1, reason,
+ has_error_code, error_code) == EMULATE_FAIL) {
+ vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+ vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
+ vcpu->run->internal.ndata = 0;
+ return 0;
+ }
+
+ /*
+ * TODO: What about debug traps on tss switch?
+ * Are we supposed to inject them and update dr6?
+ */
+
+ return 1;
+}
+
+static int handle_ept_violation(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qualification;
+ gpa_t gpa;
+ u64 error_code;
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ /*
+ * EPT violation happened while executing iret from NMI,
+ * "blocked by NMI" bit has to be set before next VM entry.
+ * There are errata that may cause this bit to not be set:
+ * AAK134, BY25.
+ */
+ if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
+ enable_vnmi &&
+ (exit_qualification & INTR_INFO_UNBLOCK_NMI))
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, GUEST_INTR_STATE_NMI);
+
+ gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
+ trace_kvm_page_fault(gpa, exit_qualification);
+
+ /* Is it a read fault? */
+ error_code = (exit_qualification & EPT_VIOLATION_ACC_READ)
+ ? PFERR_USER_MASK : 0;
+ /* Is it a write fault? */
+ error_code |= (exit_qualification & EPT_VIOLATION_ACC_WRITE)
+ ? PFERR_WRITE_MASK : 0;
+ /* Is it a fetch fault? */
+ error_code |= (exit_qualification & EPT_VIOLATION_ACC_INSTR)
+ ? PFERR_FETCH_MASK : 0;
+ /* ept page table entry is present? */
+ error_code |= (exit_qualification &
+ (EPT_VIOLATION_READABLE | EPT_VIOLATION_WRITABLE |
+ EPT_VIOLATION_EXECUTABLE))
+ ? PFERR_PRESENT_MASK : 0;
+
+ error_code |= (exit_qualification & 0x100) != 0 ?
+ PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK;
+
+ vcpu->arch.exit_qualification = exit_qualification;
+ return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0);
+}
+
+static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
+{
+ gpa_t gpa;
+
+ /*
+ * A nested guest cannot optimize MMIO vmexits, because we have an
+ * nGPA here instead of the required GPA.
+ */
+ gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
+ if (!is_guest_mode(vcpu) &&
+ !kvm_io_bus_write(vcpu, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
+ trace_kvm_fast_mmio(gpa);
+ /*
+ * Doing kvm_skip_emulated_instruction() depends on undefined
+ * behavior: Intel's manual doesn't mandate
+ * VM_EXIT_INSTRUCTION_LEN to be set in VMCS when EPT MISCONFIG
+ * occurs and while on real hardware it was observed to be set,
+ * other hypervisors (namely Hyper-V) don't set it, we end up
+ * advancing IP with some random value. Disable fast mmio when
+ * running nested and keep it for real hardware in hope that
+ * VM_EXIT_INSTRUCTION_LEN will always be set correctly.
+ */
+ if (!static_cpu_has(X86_FEATURE_HYPERVISOR))
+ return kvm_skip_emulated_instruction(vcpu);
+ else
+ return kvm_emulate_instruction(vcpu, EMULTYPE_SKIP) ==
+ EMULATE_DONE;
+ }
+
+ return kvm_mmu_page_fault(vcpu, gpa, PFERR_RSVD_MASK, NULL, 0);
+}
+
+static int handle_nmi_window(struct kvm_vcpu *vcpu)
+{
+ WARN_ON_ONCE(!enable_vnmi);
+ vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
+ CPU_BASED_VIRTUAL_NMI_PENDING);
+ ++vcpu->stat.nmi_window_exits;
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+
+ return 1;
+}
+
+static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ enum emulation_result err = EMULATE_DONE;
+ int ret = 1;
+ u32 cpu_exec_ctrl;
+ bool intr_window_requested;
+ unsigned count = 130;
+
+ /*
+ * We should never reach the point where we are emulating L2
+ * due to invalid guest state as that means we incorrectly
+ * allowed a nested VMEntry with an invalid vmcs12.
+ */
+ WARN_ON_ONCE(vmx->emulation_required && vmx->nested.nested_run_pending);
+
+ cpu_exec_ctrl = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+ intr_window_requested = cpu_exec_ctrl & CPU_BASED_VIRTUAL_INTR_PENDING;
+
+ while (vmx->emulation_required && count-- != 0) {
+ if (intr_window_requested && vmx_interrupt_allowed(vcpu))
+ return handle_interrupt_window(&vmx->vcpu);
+
+ if (kvm_test_request(KVM_REQ_EVENT, vcpu))
+ return 1;
+
+ err = kvm_emulate_instruction(vcpu, 0);
+
+ if (err == EMULATE_USER_EXIT) {
+ ++vcpu->stat.mmio_exits;
+ ret = 0;
+ goto out;
+ }
+
+ if (err != EMULATE_DONE)
+ goto emulation_error;
+
+ if (vmx->emulation_required && !vmx->rmode.vm86_active &&
+ vcpu->arch.exception.pending)
+ goto emulation_error;
+
+ if (vcpu->arch.halt_request) {
+ vcpu->arch.halt_request = 0;
+ ret = kvm_vcpu_halt(vcpu);
+ goto out;
+ }
+
+ if (signal_pending(current))
+ goto out;
+ if (need_resched())
+ schedule();
+ }
+
+out:
+ return ret;
+
+emulation_error:
+ vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+ vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
+ vcpu->run->internal.ndata = 0;
+ return 0;
+}
+
+static void grow_ple_window(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int old = vmx->ple_window;
+
+ vmx->ple_window = __grow_ple_window(old, ple_window,
+ ple_window_grow,
+ ple_window_max);
+
+ if (vmx->ple_window != old)
+ vmx->ple_window_dirty = true;
+
+ trace_kvm_ple_window_grow(vcpu->vcpu_id, vmx->ple_window, old);
+}
+
+static void shrink_ple_window(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int old = vmx->ple_window;
+
+ vmx->ple_window = __shrink_ple_window(old, ple_window,
+ ple_window_shrink,
+ ple_window);
+
+ if (vmx->ple_window != old)
+ vmx->ple_window_dirty = true;
+
+ trace_kvm_ple_window_shrink(vcpu->vcpu_id, vmx->ple_window, old);
+}
+
+/*
+ * Handler for POSTED_INTERRUPT_WAKEUP_VECTOR.
+ */
+static void wakeup_handler(void)
+{
+ struct kvm_vcpu *vcpu;
+ int cpu = smp_processor_id();
+
+ spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
+ list_for_each_entry(vcpu, &per_cpu(blocked_vcpu_on_cpu, cpu),
+ blocked_vcpu_list) {
+ struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
+
+ if (pi_test_on(pi_desc) == 1)
+ kvm_vcpu_kick(vcpu);
+ }
+ spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
+}
+
+static void vmx_enable_tdp(void)
+{
+ kvm_mmu_set_mask_ptes(VMX_EPT_READABLE_MASK,
+ enable_ept_ad_bits ? VMX_EPT_ACCESS_BIT : 0ull,
+ enable_ept_ad_bits ? VMX_EPT_DIRTY_BIT : 0ull,
+ 0ull, VMX_EPT_EXECUTABLE_MASK,
+ cpu_has_vmx_ept_execute_only() ? 0ull : VMX_EPT_READABLE_MASK,
+ VMX_EPT_RWX_MASK, 0ull);
+
+ ept_set_mmio_spte_mask();
+ kvm_enable_tdp();
+}
+
+static __init int hardware_setup(void)
+{
+ unsigned long host_bndcfgs;
+ int r = -ENOMEM, i;
+
+ rdmsrl_safe(MSR_EFER, &host_efer);
+
+ for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i)
+ kvm_define_shared_msr(i, vmx_msr_index[i]);
+
+ for (i = 0; i < VMX_BITMAP_NR; i++) {
+ vmx_bitmap[i] = (unsigned long *)__get_free_page(GFP_KERNEL);
+ if (!vmx_bitmap[i])
+ goto out;
+ }
+
+ memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
+ memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
+
+ if (setup_vmcs_config(&vmcs_config) < 0) {
+ r = -EIO;
+ goto out;
+ }
+
+ if (boot_cpu_has(X86_FEATURE_NX))
+ kvm_enable_efer_bits(EFER_NX);
+
+ if (boot_cpu_has(X86_FEATURE_MPX)) {
+ rdmsrl(MSR_IA32_BNDCFGS, host_bndcfgs);
+ WARN_ONCE(host_bndcfgs, "KVM: BNDCFGS in host will be lost");
+ }
+
+ if (boot_cpu_has(X86_FEATURE_XSAVES))
+ rdmsrl(MSR_IA32_XSS, host_xss);
+
+ if (!cpu_has_vmx_vpid() || !cpu_has_vmx_invvpid() ||
+ !(cpu_has_vmx_invvpid_single() || cpu_has_vmx_invvpid_global()))
+ enable_vpid = 0;
+
+ if (!cpu_has_vmx_ept() ||
+ !cpu_has_vmx_ept_4levels() ||
+ !cpu_has_vmx_ept_mt_wb() ||
+ !cpu_has_vmx_invept_global())
+ enable_ept = 0;
+
+ if (!cpu_has_vmx_ept_ad_bits() || !enable_ept)
+ enable_ept_ad_bits = 0;
+
+ if (!cpu_has_vmx_unrestricted_guest() || !enable_ept)
+ enable_unrestricted_guest = 0;
+
+ if (!cpu_has_vmx_flexpriority())
+ flexpriority_enabled = 0;
+
+ if (!cpu_has_virtual_nmis())
+ enable_vnmi = 0;
+
+ /*
+ * set_apic_access_page_addr() is used to reload apic access
+ * page upon invalidation. No need to do anything if not
+ * using the APIC_ACCESS_ADDR VMCS field.
+ */
+ if (!flexpriority_enabled)
+ kvm_x86_ops->set_apic_access_page_addr = NULL;
+
+ if (!cpu_has_vmx_tpr_shadow())
+ kvm_x86_ops->update_cr8_intercept = NULL;
+
+ if (enable_ept && !cpu_has_vmx_ept_2m_page())
+ kvm_disable_largepages();
+
+#if IS_ENABLED(CONFIG_HYPERV)
+ if (ms_hyperv.nested_features & HV_X64_NESTED_GUEST_MAPPING_FLUSH
+ && enable_ept)
+ kvm_x86_ops->tlb_remote_flush = vmx_hv_remote_flush_tlb;
+#endif
+
+ if (!cpu_has_vmx_ple()) {
+ ple_gap = 0;
+ ple_window = 0;
+ ple_window_grow = 0;
+ ple_window_max = 0;
+ ple_window_shrink = 0;
+ }
+
+ if (!cpu_has_vmx_apicv()) {
+ enable_apicv = 0;
+ kvm_x86_ops->sync_pir_to_irr = NULL;
+ }
+
+ if (cpu_has_vmx_tsc_scaling()) {
+ kvm_has_tsc_control = true;
+ kvm_max_tsc_scaling_ratio = KVM_VMX_TSC_MULTIPLIER_MAX;
+ kvm_tsc_scaling_ratio_frac_bits = 48;
+ }
+
+ set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
+
+ if (enable_ept)
+ vmx_enable_tdp();
+ else
+ kvm_disable_tdp();
+
+ if (!nested) {
+ kvm_x86_ops->get_nested_state = NULL;
+ kvm_x86_ops->set_nested_state = NULL;
+ }
+
+ /*
+ * Only enable PML when hardware supports PML feature, and both EPT
+ * and EPT A/D bit features are enabled -- PML depends on them to work.
+ */
+ if (!enable_ept || !enable_ept_ad_bits || !cpu_has_vmx_pml())
+ enable_pml = 0;
+
+ if (!enable_pml) {
+ kvm_x86_ops->slot_enable_log_dirty = NULL;
+ kvm_x86_ops->slot_disable_log_dirty = NULL;
+ kvm_x86_ops->flush_log_dirty = NULL;
+ kvm_x86_ops->enable_log_dirty_pt_masked = NULL;
+ }
+
+ if (!cpu_has_vmx_preemption_timer())
+ kvm_x86_ops->request_immediate_exit = __kvm_request_immediate_exit;
+
+ if (cpu_has_vmx_preemption_timer() && enable_preemption_timer) {
+ u64 vmx_msr;
+
+ rdmsrl(MSR_IA32_VMX_MISC, vmx_msr);
+ cpu_preemption_timer_multi =
+ vmx_msr & VMX_MISC_PREEMPTION_TIMER_RATE_MASK;
+ } else {
+ kvm_x86_ops->set_hv_timer = NULL;
+ kvm_x86_ops->cancel_hv_timer = NULL;
+ }
+
+ if (!cpu_has_vmx_shadow_vmcs())
+ enable_shadow_vmcs = 0;
+ if (enable_shadow_vmcs)
+ init_vmcs_shadow_fields();
+
+ kvm_set_posted_intr_wakeup_handler(wakeup_handler);
+ nested_vmx_setup_ctls_msrs(&vmcs_config.nested, enable_apicv);
+
+ kvm_mce_cap_supported |= MCG_LMCE_P;
+
+ r = alloc_kvm_area();
+ if (r)
+ goto out;
+ return 0;
+
+out:
+ for (i = 0; i < VMX_BITMAP_NR; i++)
+ free_page((unsigned long)vmx_bitmap[i]);
+
+ return r;
+}
+
+static __exit void hardware_unsetup(void)
+{
+ int i;
+
+ for (i = 0; i < VMX_BITMAP_NR; i++)
+ free_page((unsigned long)vmx_bitmap[i]);
+
+ free_kvm_area();
+}
+
+/*
+ * Indicate a busy-waiting vcpu in spinlock. We do not enable the PAUSE
+ * exiting, so only get here on cpu with PAUSE-Loop-Exiting.
+ */
+static int handle_pause(struct kvm_vcpu *vcpu)
+{
+ if (!kvm_pause_in_guest(vcpu->kvm))
+ grow_ple_window(vcpu);
+
+ /*
+ * Intel sdm vol3 ch-25.1.3 says: The "PAUSE-loop exiting"
+ * VM-execution control is ignored if CPL > 0. OTOH, KVM
+ * never set PAUSE_EXITING and just set PLE if supported,
+ * so the vcpu must be CPL=0 if it gets a PAUSE exit.
+ */
+ kvm_vcpu_on_spin(vcpu, true);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static int handle_nop(struct kvm_vcpu *vcpu)
+{
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static int handle_mwait(struct kvm_vcpu *vcpu)
+{
+ printk_once(KERN_WARNING "kvm: MWAIT instruction emulated as NOP!\n");
+ return handle_nop(vcpu);
+}
+
+static int handle_invalid_op(struct kvm_vcpu *vcpu)
+{
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+}
+
+static int handle_monitor_trap(struct kvm_vcpu *vcpu)
+{
+ return 1;
+}
+
+static int handle_monitor(struct kvm_vcpu *vcpu)
+{
+ printk_once(KERN_WARNING "kvm: MONITOR instruction emulated as NOP!\n");
+ return handle_nop(vcpu);
+}
+
+/*
+ * The following 3 functions, nested_vmx_succeed()/failValid()/failInvalid(),
+ * set the success or error code of an emulated VMX instruction, as specified
+ * by Vol 2B, VMX Instruction Reference, "Conventions".
+ */
+static void nested_vmx_succeed(struct kvm_vcpu *vcpu)
+{
+ vmx_set_rflags(vcpu, vmx_get_rflags(vcpu)
+ & ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+ X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF));
+}
+
+static void nested_vmx_failInvalid(struct kvm_vcpu *vcpu)
+{
+ vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
+ & ~(X86_EFLAGS_PF | X86_EFLAGS_AF | X86_EFLAGS_ZF |
+ X86_EFLAGS_SF | X86_EFLAGS_OF))
+ | X86_EFLAGS_CF);
+}
+
+static void nested_vmx_failValid(struct kvm_vcpu *vcpu,
+ u32 vm_instruction_error)
+{
+ if (to_vmx(vcpu)->nested.current_vmptr == -1ull) {
+ /*
+ * failValid writes the error number to the current VMCS, which
+ * can't be done there isn't a current VMCS.
+ */
+ nested_vmx_failInvalid(vcpu);
+ return;
+ }
+ vmx_set_rflags(vcpu, (vmx_get_rflags(vcpu)
+ & ~(X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF |
+ X86_EFLAGS_SF | X86_EFLAGS_OF))
+ | X86_EFLAGS_ZF);
+ get_vmcs12(vcpu)->vm_instruction_error = vm_instruction_error;
+ /*
+ * We don't need to force a shadow sync because
+ * VM_INSTRUCTION_ERROR is not shadowed
+ */
+}
+
+static void nested_vmx_abort(struct kvm_vcpu *vcpu, u32 indicator)
+{
+ /* TODO: not to reset guest simply here. */
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+ pr_debug_ratelimited("kvm: nested vmx abort, indicator %d\n", indicator);
+}
+
+static enum hrtimer_restart vmx_preemption_timer_fn(struct hrtimer *timer)
+{
+ struct vcpu_vmx *vmx =
+ container_of(timer, struct vcpu_vmx, nested.preemption_timer);
+
+ vmx->nested.preemption_timer_expired = true;
+ kvm_make_request(KVM_REQ_EVENT, &vmx->vcpu);
+ kvm_vcpu_kick(&vmx->vcpu);
+
+ return HRTIMER_NORESTART;
+}
+
+/*
+ * Decode the memory-address operand of a vmx instruction, as recorded on an
+ * exit caused by such an instruction (run by a guest hypervisor).
+ * On success, returns 0. When the operand is invalid, returns 1 and throws
+ * #UD or #GP.
+ */
+static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
+ unsigned long exit_qualification,
+ u32 vmx_instruction_info, bool wr, gva_t *ret)
+{
+ gva_t off;
+ bool exn;
+ struct kvm_segment s;
+
+ /*
+ * According to Vol. 3B, "Information for VM Exits Due to Instruction
+ * Execution", on an exit, vmx_instruction_info holds most of the
+ * addressing components of the operand. Only the displacement part
+ * is put in exit_qualification (see 3B, "Basic VM-Exit Information").
+ * For how an actual address is calculated from all these components,
+ * refer to Vol. 1, "Operand Addressing".
+ */
+ int scaling = vmx_instruction_info & 3;
+ int addr_size = (vmx_instruction_info >> 7) & 7;
+ bool is_reg = vmx_instruction_info & (1u << 10);
+ int seg_reg = (vmx_instruction_info >> 15) & 7;
+ int index_reg = (vmx_instruction_info >> 18) & 0xf;
+ bool index_is_valid = !(vmx_instruction_info & (1u << 22));
+ int base_reg = (vmx_instruction_info >> 23) & 0xf;
+ bool base_is_valid = !(vmx_instruction_info & (1u << 27));
+
+ if (is_reg) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ /* Addr = segment_base + offset */
+ /* offset = base + [index * scale] + displacement */
+ off = exit_qualification; /* holds the displacement */
+ if (addr_size == 1)
+ off = (gva_t)sign_extend64(off, 31);
+ else if (addr_size == 0)
+ off = (gva_t)sign_extend64(off, 15);
+ if (base_is_valid)
+ off += kvm_register_read(vcpu, base_reg);
+ if (index_is_valid)
+ off += kvm_register_read(vcpu, index_reg)<<scaling;
+ vmx_get_segment(vcpu, &s, seg_reg);
+
+ /*
+ * The effective address, i.e. @off, of a memory operand is truncated
+ * based on the address size of the instruction. Note that this is
+ * the *effective address*, i.e. the address prior to accounting for
+ * the segment's base.
+ */
+ if (addr_size == 1) /* 32 bit */
+ off &= 0xffffffff;
+ else if (addr_size == 0) /* 16 bit */
+ off &= 0xffff;
+
+ /* Checks for #GP/#SS exceptions. */
+ exn = false;
+ if (is_long_mode(vcpu)) {
+ /*
+ * The virtual/linear address is never truncated in 64-bit
+ * mode, e.g. a 32-bit address size can yield a 64-bit virtual
+ * address when using FS/GS with a non-zero base.
+ */
+ *ret = s.base + off;
+
+ /* Long mode: #GP(0)/#SS(0) if the memory address is in a
+ * non-canonical form. This is the only check on the memory
+ * destination for long mode!
+ */
+ exn = is_noncanonical_address(*ret, vcpu);
+ } else if (is_protmode(vcpu)) {
+ /*
+ * When not in long mode, the virtual/linear address is
+ * unconditionally truncated to 32 bits regardless of the
+ * address size.
+ */
+ *ret = (s.base + off) & 0xffffffff;
+
+ /* Protected mode: apply checks for segment validity in the
+ * following order:
+ * - segment type check (#GP(0) may be thrown)
+ * - usability check (#GP(0)/#SS(0))
+ * - limit check (#GP(0)/#SS(0))
+ */
+ if (wr)
+ /* #GP(0) if the destination operand is located in a
+ * read-only data segment or any code segment.
+ */
+ exn = ((s.type & 0xa) == 0 || (s.type & 8));
+ else
+ /* #GP(0) if the source operand is located in an
+ * execute-only code segment
+ */
+ exn = ((s.type & 0xa) == 8);
+ if (exn) {
+ kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
+ return 1;
+ }
+ /* Protected mode: #GP(0)/#SS(0) if the segment is unusable.
+ */
+ exn = (s.unusable != 0);
+
+ /*
+ * Protected mode: #GP(0)/#SS(0) if the memory operand is
+ * outside the segment limit. All CPUs that support VMX ignore
+ * limit checks for flat segments, i.e. segments with base==0,
+ * limit==0xffffffff and of type expand-up data or code.
+ */
+ if (!(s.base == 0 && s.limit == 0xffffffff &&
+ ((s.type & 8) || !(s.type & 4))))
+ exn = exn || (off + sizeof(u64) > s.limit);
+ }
+ if (exn) {
+ kvm_queue_exception_e(vcpu,
+ seg_reg == VCPU_SREG_SS ?
+ SS_VECTOR : GP_VECTOR,
+ 0);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer)
+{
+ gva_t gva;
+ struct x86_exception e;
+
+ if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
+ vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva))
+ return 1;
+
+ if (kvm_read_guest_virt(vcpu, gva, vmpointer, sizeof(*vmpointer), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Allocate a shadow VMCS and associate it with the currently loaded
+ * VMCS, unless such a shadow VMCS already exists. The newly allocated
+ * VMCS is also VMCLEARed, so that it is ready for use.
+ */
+static struct vmcs *alloc_shadow_vmcs(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct loaded_vmcs *loaded_vmcs = vmx->loaded_vmcs;
+
+ /*
+ * We should allocate a shadow vmcs for vmcs01 only when L1
+ * executes VMXON and free it when L1 executes VMXOFF.
+ * As it is invalid to execute VMXON twice, we shouldn't reach
+ * here when vmcs01 already have an allocated shadow vmcs.
+ */
+ WARN_ON(loaded_vmcs == &vmx->vmcs01 && loaded_vmcs->shadow_vmcs);
+
+ if (!loaded_vmcs->shadow_vmcs) {
+ loaded_vmcs->shadow_vmcs = alloc_vmcs(true);
+ if (loaded_vmcs->shadow_vmcs)
+ vmcs_clear(loaded_vmcs->shadow_vmcs);
+ }
+ return loaded_vmcs->shadow_vmcs;
+}
+
+static int enter_vmx_operation(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int r;
+
+ r = alloc_loaded_vmcs(&vmx->nested.vmcs02);
+ if (r < 0)
+ goto out_vmcs02;
+
+ vmx->nested.cached_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
+ if (!vmx->nested.cached_vmcs12)
+ goto out_cached_vmcs12;
+
+ vmx->nested.cached_shadow_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
+ if (!vmx->nested.cached_shadow_vmcs12)
+ goto out_cached_shadow_vmcs12;
+
+ if (enable_shadow_vmcs && !alloc_shadow_vmcs(vcpu))
+ goto out_shadow_vmcs;
+
+ hrtimer_init(&vmx->nested.preemption_timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL_PINNED);
+ vmx->nested.preemption_timer.function = vmx_preemption_timer_fn;
+
+ vmx->nested.vpid02 = allocate_vpid();
+
+ vmx->nested.vmxon = true;
+ return 0;
+
+out_shadow_vmcs:
+ kfree(vmx->nested.cached_shadow_vmcs12);
+
+out_cached_shadow_vmcs12:
+ kfree(vmx->nested.cached_vmcs12);
+
+out_cached_vmcs12:
+ free_loaded_vmcs(&vmx->nested.vmcs02);
+
+out_vmcs02:
+ return -ENOMEM;
+}
+
+/*
+ * Emulate the VMXON instruction.
+ * Currently, we just remember that VMX is active, and do not save or even
+ * inspect the argument to VMXON (the so-called "VMXON pointer") because we
+ * do not currently need to store anything in that guest-allocated memory
+ * region. Consequently, VMCLEAR and VMPTRLD also do not verify that the their
+ * argument is different from the VMXON pointer (which the spec says they do).
+ */
+static int handle_vmon(struct kvm_vcpu *vcpu)
+{
+ int ret;
+ gpa_t vmptr;
+ struct page *page;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ const u64 VMXON_NEEDED_FEATURES = FEATURE_CONTROL_LOCKED
+ | FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
+
+ /*
+ * The Intel VMX Instruction Reference lists a bunch of bits that are
+ * prerequisite to running VMXON, most notably cr4.VMXE must be set to
+ * 1 (see vmx_set_cr4() for when we allow the guest to set this).
+ * Otherwise, we should fail with #UD. But most faulting conditions
+ * have already been checked by hardware, prior to the VM-exit for
+ * VMXON. We do test guest cr4.VMXE because processor CR4 always has
+ * that bit set to 1 in non-root mode.
+ */
+ if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ /* CPL=0 must be checked manually. */
+ if (vmx_get_cpl(vcpu)) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ if (vmx->nested.vmxon) {
+ nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ if ((vmx->msr_ia32_feature_control & VMXON_NEEDED_FEATURES)
+ != VMXON_NEEDED_FEATURES) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ if (nested_vmx_get_vmptr(vcpu, &vmptr))
+ return 1;
+
+ /*
+ * SDM 3: 24.11.5
+ * The first 4 bytes of VMXON region contain the supported
+ * VMCS revision identifier
+ *
+ * Note - IA32_VMX_BASIC[48] will never be 1 for the nested case;
+ * which replaces physical address width with 32
+ */
+ if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
+ nested_vmx_failInvalid(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ page = kvm_vcpu_gpa_to_page(vcpu, vmptr);
+ if (is_error_page(page)) {
+ nested_vmx_failInvalid(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ if (*(u32 *)kmap(page) != VMCS12_REVISION) {
+ kunmap(page);
+ kvm_release_page_clean(page);
+ nested_vmx_failInvalid(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ kunmap(page);
+ kvm_release_page_clean(page);
+
+ vmx->nested.vmxon_ptr = vmptr;
+ ret = enter_vmx_operation(vcpu);
+ if (ret)
+ return ret;
+
+ nested_vmx_succeed(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+/*
+ * Intel's VMX Instruction Reference specifies a common set of prerequisites
+ * for running VMX instructions (except VMXON, whose prerequisites are
+ * slightly different). It also specifies what exception to inject otherwise.
+ * Note that many of these exceptions have priority over VM exits, so they
+ * don't have to be checked again here.
+ */
+static int nested_vmx_check_permission(struct kvm_vcpu *vcpu)
+{
+ if (!to_vmx(vcpu)->nested.vmxon) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 0;
+ }
+
+ if (vmx_get_cpl(vcpu)) {
+ kvm_inject_gp(vcpu, 0);
+ return 0;
+ }
+
+ return 1;
+}
+
+static void vmx_disable_shadow_vmcs(struct vcpu_vmx *vmx)
+{
+ vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL, SECONDARY_EXEC_SHADOW_VMCS);
+ vmcs_write64(VMCS_LINK_POINTER, -1ull);
+ vmx->nested.sync_shadow_vmcs = false;
+}
+
+static inline void nested_release_vmcs12(struct vcpu_vmx *vmx)
+{
+ if (vmx->nested.current_vmptr == -1ull)
+ return;
+
+ if (enable_shadow_vmcs) {
+ /* copy to memory all shadowed fields in case
+ they were modified */
+ copy_shadow_to_vmcs12(vmx);
+ vmx_disable_shadow_vmcs(vmx);
+ }
+ vmx->nested.posted_intr_nv = -1;
+
+ /* Flush VMCS12 to guest memory */
+ kvm_vcpu_write_guest_page(&vmx->vcpu,
+ vmx->nested.current_vmptr >> PAGE_SHIFT,
+ vmx->nested.cached_vmcs12, 0, VMCS12_SIZE);
+
+ vmx->nested.current_vmptr = -1ull;
+}
+
+/*
+ * Free whatever needs to be freed from vmx->nested when L1 goes down, or
+ * just stops using VMX.
+ */
+static void free_nested(struct vcpu_vmx *vmx)
+{
+ if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon)
+ return;
+
+ kvm_clear_request(KVM_REQ_GET_VMCS12_PAGES, &vmx->vcpu);
+
+ hrtimer_cancel(&vmx->nested.preemption_timer);
+ vmx->nested.vmxon = false;
+ vmx->nested.smm.vmxon = false;
+ free_vpid(vmx->nested.vpid02);
+ vmx->nested.posted_intr_nv = -1;
+ vmx->nested.current_vmptr = -1ull;
+ if (enable_shadow_vmcs) {
+ vmx_disable_shadow_vmcs(vmx);
+ vmcs_clear(vmx->vmcs01.shadow_vmcs);
+ free_vmcs(vmx->vmcs01.shadow_vmcs);
+ vmx->vmcs01.shadow_vmcs = NULL;
+ }
+ kfree(vmx->nested.cached_vmcs12);
+ kfree(vmx->nested.cached_shadow_vmcs12);
+ /* Unpin physical memory we referred to in the vmcs02 */
+ if (vmx->nested.apic_access_page) {
+ kvm_release_page_dirty(vmx->nested.apic_access_page);
+ vmx->nested.apic_access_page = NULL;
+ }
+ if (vmx->nested.virtual_apic_page) {
+ kvm_release_page_dirty(vmx->nested.virtual_apic_page);
+ vmx->nested.virtual_apic_page = NULL;
+ }
+ if (vmx->nested.pi_desc_page) {
+ kunmap(vmx->nested.pi_desc_page);
+ kvm_release_page_dirty(vmx->nested.pi_desc_page);
+ vmx->nested.pi_desc_page = NULL;
+ vmx->nested.pi_desc = NULL;
+ }
+
+ free_loaded_vmcs(&vmx->nested.vmcs02);
+}
+
+/* Emulate the VMXOFF instruction */
+static int handle_vmoff(struct kvm_vcpu *vcpu)
+{
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+ free_nested(to_vmx(vcpu));
+ nested_vmx_succeed(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+/* Emulate the VMCLEAR instruction */
+static int handle_vmclear(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 zero = 0;
+ gpa_t vmptr;
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ if (nested_vmx_get_vmptr(vcpu, &vmptr))
+ return 1;
+
+ if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
+ nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ if (vmptr == vmx->nested.vmxon_ptr) {
+ nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_VMXON_POINTER);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ if (vmptr == vmx->nested.current_vmptr)
+ nested_release_vmcs12(vmx);
+
+ kvm_vcpu_write_guest(vcpu,
+ vmptr + offsetof(struct vmcs12, launch_state),
+ &zero, sizeof(zero));
+
+ nested_vmx_succeed(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch);
+
+/* Emulate the VMLAUNCH instruction */
+static int handle_vmlaunch(struct kvm_vcpu *vcpu)
+{
+ return nested_vmx_run(vcpu, true);
+}
+
+/* Emulate the VMRESUME instruction */
+static int handle_vmresume(struct kvm_vcpu *vcpu)
+{
+
+ return nested_vmx_run(vcpu, false);
+}
+
+/*
+ * Read a vmcs12 field. Since these can have varying lengths and we return
+ * one type, we chose the biggest type (u64) and zero-extend the return value
+ * to that size. Note that the caller, handle_vmread, might need to use only
+ * some of the bits we return here (e.g., on 32-bit guests, only 32 bits of
+ * 64-bit fields are to be returned).
+ */
+static inline int vmcs12_read_any(struct vmcs12 *vmcs12,
+ unsigned long field, u64 *ret)
+{
+ short offset = vmcs_field_to_offset(field);
+ char *p;
+
+ if (offset < 0)
+ return offset;
+
+ p = (char *)vmcs12 + offset;
+
+ switch (vmcs_field_width(field)) {
+ case VMCS_FIELD_WIDTH_NATURAL_WIDTH:
+ *ret = *((natural_width *)p);
+ return 0;
+ case VMCS_FIELD_WIDTH_U16:
+ *ret = *((u16 *)p);
+ return 0;
+ case VMCS_FIELD_WIDTH_U32:
+ *ret = *((u32 *)p);
+ return 0;
+ case VMCS_FIELD_WIDTH_U64:
+ *ret = *((u64 *)p);
+ return 0;
+ default:
+ WARN_ON(1);
+ return -ENOENT;
+ }
+}
+
+
+static inline int vmcs12_write_any(struct vmcs12 *vmcs12,
+ unsigned long field, u64 field_value){
+ short offset = vmcs_field_to_offset(field);
+ char *p = (char *)vmcs12 + offset;
+ if (offset < 0)
+ return offset;
+
+ switch (vmcs_field_width(field)) {
+ case VMCS_FIELD_WIDTH_U16:
+ *(u16 *)p = field_value;
+ return 0;
+ case VMCS_FIELD_WIDTH_U32:
+ *(u32 *)p = field_value;
+ return 0;
+ case VMCS_FIELD_WIDTH_U64:
+ *(u64 *)p = field_value;
+ return 0;
+ case VMCS_FIELD_WIDTH_NATURAL_WIDTH:
+ *(natural_width *)p = field_value;
+ return 0;
+ default:
+ WARN_ON(1);
+ return -ENOENT;
+ }
+
+}
+
+/*
+ * Copy the writable VMCS shadow fields back to the VMCS12, in case
+ * they have been modified by the L1 guest. Note that the "read-only"
+ * VM-exit information fields are actually writable if the vCPU is
+ * configured to support "VMWRITE to any supported field in the VMCS."
+ */
+static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)
+{
+ const u16 *fields[] = {
+ shadow_read_write_fields,
+ shadow_read_only_fields
+ };
+ const int max_fields[] = {
+ max_shadow_read_write_fields,
+ max_shadow_read_only_fields
+ };
+ int i, q;
+ unsigned long field;
+ u64 field_value;
+ struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;
+
+ if (WARN_ON(!shadow_vmcs))
+ return;
+
+ preempt_disable();
+
+ vmcs_load(shadow_vmcs);
+
+ for (q = 0; q < ARRAY_SIZE(fields); q++) {
+ for (i = 0; i < max_fields[q]; i++) {
+ field = fields[q][i];
+ field_value = __vmcs_readl(field);
+ vmcs12_write_any(get_vmcs12(&vmx->vcpu), field, field_value);
+ }
+ /*
+ * Skip the VM-exit information fields if they are read-only.
+ */
+ if (!nested_cpu_has_vmwrite_any_field(&vmx->vcpu))
+ break;
+ }
+
+ vmcs_clear(shadow_vmcs);
+ vmcs_load(vmx->loaded_vmcs->vmcs);
+
+ preempt_enable();
+}
+
+static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)
+{
+ const u16 *fields[] = {
+ shadow_read_write_fields,
+ shadow_read_only_fields
+ };
+ const int max_fields[] = {
+ max_shadow_read_write_fields,
+ max_shadow_read_only_fields
+ };
+ int i, q;
+ unsigned long field;
+ u64 field_value = 0;
+ struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;
+
+ if (WARN_ON(!shadow_vmcs))
+ return;
+
+ vmcs_load(shadow_vmcs);
+
+ for (q = 0; q < ARRAY_SIZE(fields); q++) {
+ for (i = 0; i < max_fields[q]; i++) {
+ field = fields[q][i];
+ vmcs12_read_any(get_vmcs12(&vmx->vcpu), field, &field_value);
+ __vmcs_writel(field, field_value);
+ }
+ }
+
+ vmcs_clear(shadow_vmcs);
+ vmcs_load(vmx->loaded_vmcs->vmcs);
+}
+
+/*
+ * VMX instructions which assume a current vmcs12 (i.e., that VMPTRLD was
+ * used before) all generate the same failure when it is missing.
+ */
+static int nested_vmx_check_vmcs12(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ if (vmx->nested.current_vmptr == -1ull) {
+ nested_vmx_failInvalid(vcpu);
+ return 0;
+ }
+ return 1;
+}
+
+static int handle_vmread(struct kvm_vcpu *vcpu)
+{
+ unsigned long field;
+ u64 field_value;
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+ gva_t gva = 0;
+ struct vmcs12 *vmcs12;
+ struct x86_exception e;
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ if (!nested_vmx_check_vmcs12(vcpu))
+ return kvm_skip_emulated_instruction(vcpu);
+
+ if (!is_guest_mode(vcpu))
+ vmcs12 = get_vmcs12(vcpu);
+ else {
+ /*
+ * When vmcs->vmcs_link_pointer is -1ull, any VMREAD
+ * to shadowed-field sets the ALU flags for VMfailInvalid.
+ */
+ if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull) {
+ nested_vmx_failInvalid(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ vmcs12 = get_shadow_vmcs12(vcpu);
+ }
+
+ /* Decode instruction info and find the field to read */
+ field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+ /* Read the field, zero-extended to a u64 field_value */
+ if (vmcs12_read_any(vmcs12, field, &field_value) < 0) {
+ nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ /*
+ * Now copy part of this value to register or memory, as requested.
+ * Note that the number of bits actually copied is 32 or 64 depending
+ * on the guest's mode (32 or 64 bit), not on the given field's length.
+ */
+ if (vmx_instruction_info & (1u << 10)) {
+ kvm_register_writel(vcpu, (((vmx_instruction_info) >> 3) & 0xf),
+ field_value);
+ } else {
+ if (get_vmx_mem_address(vcpu, exit_qualification,
+ vmx_instruction_info, true, &gva))
+ return 1;
+ /* _system ok, nested_vmx_check_permission has verified cpl=0 */
+ if (kvm_write_guest_virt_system(vcpu, gva, &field_value,
+ (is_long_mode(vcpu) ? 8 : 4),
+ &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+ }
+
+ nested_vmx_succeed(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+
+static int handle_vmwrite(struct kvm_vcpu *vcpu)
+{
+ unsigned long field;
+ gva_t gva;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+
+ /* The value to write might be 32 or 64 bits, depending on L1's long
+ * mode, and eventually we need to write that into a field of several
+ * possible lengths. The code below first zero-extends the value to 64
+ * bit (field_value), and then copies only the appropriate number of
+ * bits into the vmcs12 field.
+ */
+ u64 field_value = 0;
+ struct x86_exception e;
+ struct vmcs12 *vmcs12;
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ if (!nested_vmx_check_vmcs12(vcpu))
+ return kvm_skip_emulated_instruction(vcpu);
+
+ if (vmx_instruction_info & (1u << 10))
+ field_value = kvm_register_readl(vcpu,
+ (((vmx_instruction_info) >> 3) & 0xf));
+ else {
+ if (get_vmx_mem_address(vcpu, exit_qualification,
+ vmx_instruction_info, false, &gva))
+ return 1;
+ if (kvm_read_guest_virt(vcpu, gva, &field_value,
+ (is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+ }
+
+
+ field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+ /*
+ * If the vCPU supports "VMWRITE to any supported field in the
+ * VMCS," then the "read-only" fields are actually read/write.
+ */
+ if (vmcs_field_readonly(field) &&
+ !nested_cpu_has_vmwrite_any_field(vcpu)) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ if (!is_guest_mode(vcpu))
+ vmcs12 = get_vmcs12(vcpu);
+ else {
+ /*
+ * When vmcs->vmcs_link_pointer is -1ull, any VMWRITE
+ * to shadowed-field sets the ALU flags for VMfailInvalid.
+ */
+ if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull) {
+ nested_vmx_failInvalid(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ vmcs12 = get_shadow_vmcs12(vcpu);
+
+ }
+
+ if (vmcs12_write_any(vmcs12, field, field_value) < 0) {
+ nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ /*
+ * Do not track vmcs12 dirty-state if in guest-mode
+ * as we actually dirty shadow vmcs12 instead of vmcs12.
+ */
+ if (!is_guest_mode(vcpu)) {
+ switch (field) {
+#define SHADOW_FIELD_RW(x) case x:
+#include "vmx_shadow_fields.h"
+ /*
+ * The fields that can be updated by L1 without a vmexit are
+ * always updated in the vmcs02, the others go down the slow
+ * path of prepare_vmcs02.
+ */
+ break;
+ default:
+ vmx->nested.dirty_vmcs12 = true;
+ break;
+ }
+ }
+
+ nested_vmx_succeed(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static void set_current_vmptr(struct vcpu_vmx *vmx, gpa_t vmptr)
+{
+ vmx->nested.current_vmptr = vmptr;
+ if (enable_shadow_vmcs) {
+ vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
+ SECONDARY_EXEC_SHADOW_VMCS);
+ vmcs_write64(VMCS_LINK_POINTER,
+ __pa(vmx->vmcs01.shadow_vmcs));
+ vmx->nested.sync_shadow_vmcs = true;
+ }
+ vmx->nested.dirty_vmcs12 = true;
+}
+
+/* Emulate the VMPTRLD instruction */
+static int handle_vmptrld(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ gpa_t vmptr;
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ if (nested_vmx_get_vmptr(vcpu, &vmptr))
+ return 1;
+
+ if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
+ nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ if (vmptr == vmx->nested.vmxon_ptr) {
+ nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_VMXON_POINTER);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ if (vmx->nested.current_vmptr != vmptr) {
+ struct vmcs12 *new_vmcs12;
+ struct page *page;
+ page = kvm_vcpu_gpa_to_page(vcpu, vmptr);
+ if (is_error_page(page)) {
+ nested_vmx_failInvalid(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ new_vmcs12 = kmap(page);
+ if (new_vmcs12->hdr.revision_id != VMCS12_REVISION ||
+ (new_vmcs12->hdr.shadow_vmcs &&
+ !nested_cpu_has_vmx_shadow_vmcs(vcpu))) {
+ kunmap(page);
+ kvm_release_page_clean(page);
+ nested_vmx_failValid(vcpu,
+ VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ nested_release_vmcs12(vmx);
+ /*
+ * Load VMCS12 from guest memory since it is not already
+ * cached.
+ */
+ memcpy(vmx->nested.cached_vmcs12, new_vmcs12, VMCS12_SIZE);
+ kunmap(page);
+ kvm_release_page_clean(page);
+
+ set_current_vmptr(vmx, vmptr);
+ }
+
+ nested_vmx_succeed(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+/* Emulate the VMPTRST instruction */
+static int handle_vmptrst(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qual = vmcs_readl(EXIT_QUALIFICATION);
+ u32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+ gpa_t current_vmptr = to_vmx(vcpu)->nested.current_vmptr;
+ struct x86_exception e;
+ gva_t gva;
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ if (get_vmx_mem_address(vcpu, exit_qual, instr_info, true, &gva))
+ return 1;
+ /* *_system ok, nested_vmx_check_permission has verified cpl=0 */
+ if (kvm_write_guest_virt_system(vcpu, gva, (void *)¤t_vmptr,
+ sizeof(gpa_t), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+ nested_vmx_succeed(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+/* Emulate the INVEPT instruction */
+static int handle_invept(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 vmx_instruction_info, types;
+ unsigned long type;
+ gva_t gva;
+ struct x86_exception e;
+ struct {
+ u64 eptp, gpa;
+ } operand;
+
+ if (!(vmx->nested.msrs.secondary_ctls_high &
+ SECONDARY_EXEC_ENABLE_EPT) ||
+ !(vmx->nested.msrs.ept_caps & VMX_EPT_INVEPT_BIT)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+ type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
+
+ types = (vmx->nested.msrs.ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6;
+
+ if (type >= 32 || !(types & (1 << type))) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ /* According to the Intel VMX instruction reference, the memory
+ * operand is read even if it isn't needed (e.g., for type==global)
+ */
+ if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
+ vmx_instruction_info, false, &gva))
+ return 1;
+ if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+
+ switch (type) {
+ case VMX_EPT_EXTENT_GLOBAL:
+ /*
+ * TODO: track mappings and invalidate
+ * single context requests appropriately
+ */
+ case VMX_EPT_EXTENT_CONTEXT:
+ kvm_mmu_sync_roots(vcpu);
+ kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+ nested_vmx_succeed(vcpu);
+ break;
+ default:
+ BUG_ON(1);
+ break;
+ }
+
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static int handle_invvpid(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 vmx_instruction_info;
+ unsigned long type, types;
+ gva_t gva;
+ struct x86_exception e;
+ struct {
+ u64 vpid;
+ u64 gla;
+ } operand;
+
+ if (!(vmx->nested.msrs.secondary_ctls_high &
+ SECONDARY_EXEC_ENABLE_VPID) ||
+ !(vmx->nested.msrs.vpid_caps & VMX_VPID_INVVPID_BIT)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+ type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
+
+ types = (vmx->nested.msrs.vpid_caps &
+ VMX_VPID_EXTENT_SUPPORTED_MASK) >> 8;
+
+ if (type >= 32 || !(types & (1 << type))) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ /* according to the intel vmx instruction reference, the memory
+ * operand is read even if it isn't needed (e.g., for type==global)
+ */
+ if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
+ vmx_instruction_info, false, &gva))
+ return 1;
+ if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+ if (operand.vpid >> 16) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ switch (type) {
+ case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
+ if (!operand.vpid ||
+ is_noncanonical_address(operand.gla, vcpu)) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ if (cpu_has_vmx_invvpid_individual_addr() &&
+ vmx->nested.vpid02) {
+ __invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR,
+ vmx->nested.vpid02, operand.gla);
+ } else
+ __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
+ break;
+ case VMX_VPID_EXTENT_SINGLE_CONTEXT:
+ case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL:
+ if (!operand.vpid) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+ __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
+ break;
+ case VMX_VPID_EXTENT_ALL_CONTEXT:
+ __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return kvm_skip_emulated_instruction(vcpu);
+ }
+
+ nested_vmx_succeed(vcpu);
+
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+static int handle_invpcid(struct kvm_vcpu *vcpu)
+{
+ u32 vmx_instruction_info;
+ unsigned long type;
+ bool pcid_enabled;
+ gva_t gva;
+ struct x86_exception e;
+ unsigned i;
+ unsigned long roots_to_free = 0;
+ struct {
+ u64 pcid;
+ u64 gla;
+ } operand;
+
+ if (!guest_cpuid_has(vcpu, X86_FEATURE_INVPCID)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+ type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
+
+ if (type > 3) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ /* According to the Intel instruction reference, the memory operand
+ * is read even if it isn't needed (e.g., for type==all)
+ */
+ if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
+ vmx_instruction_info, false, &gva))
+ return 1;
+
+ if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
+ kvm_inject_page_fault(vcpu, &e);
+ return 1;
+ }
+
+ if (operand.pcid >> 12 != 0) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ pcid_enabled = kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE);
+
+ switch (type) {
+ case INVPCID_TYPE_INDIV_ADDR:
+ if ((!pcid_enabled && (operand.pcid != 0)) ||
+ is_noncanonical_address(operand.gla, vcpu)) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+ kvm_mmu_invpcid_gva(vcpu, operand.gla, operand.pcid);
+ return kvm_skip_emulated_instruction(vcpu);
+
+ case INVPCID_TYPE_SINGLE_CTXT:
+ if (!pcid_enabled && (operand.pcid != 0)) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ if (kvm_get_active_pcid(vcpu) == operand.pcid) {
+ kvm_mmu_sync_roots(vcpu);
+ kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+ }
+
+ for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++)
+ if (kvm_get_pcid(vcpu, vcpu->arch.mmu.prev_roots[i].cr3)
+ == operand.pcid)
+ roots_to_free |= KVM_MMU_ROOT_PREVIOUS(i);
+
+ kvm_mmu_free_roots(vcpu, roots_to_free);
+ /*
+ * If neither the current cr3 nor any of the prev_roots use the
+ * given PCID, then nothing needs to be done here because a
+ * resync will happen anyway before switching to any other CR3.
+ */
+
+ return kvm_skip_emulated_instruction(vcpu);
+
+ case INVPCID_TYPE_ALL_NON_GLOBAL:
+ /*
+ * Currently, KVM doesn't mark global entries in the shadow
+ * page tables, so a non-global flush just degenerates to a
+ * global flush. If needed, we could optimize this later by
+ * keeping track of global entries in shadow page tables.
+ */
+
+ /* fall-through */
+ case INVPCID_TYPE_ALL_INCL_GLOBAL:
+ kvm_mmu_unload(vcpu);
+ return kvm_skip_emulated_instruction(vcpu);
+
+ default:
+ BUG(); /* We have already checked above that type <= 3 */
+ }
+}
+
+static int handle_pml_full(struct kvm_vcpu *vcpu)
+{
+ unsigned long exit_qualification;
+
+ trace_kvm_pml_full(vcpu->vcpu_id);
+
+ exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ /*
+ * PML buffer FULL happened while executing iret from NMI,
+ * "blocked by NMI" bit has to be set before next VM entry.
+ */
+ if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
+ enable_vnmi &&
+ (exit_qualification & INTR_INFO_UNBLOCK_NMI))
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+
+ /*
+ * PML buffer already flushed at beginning of VMEXIT. Nothing to do
+ * here.., and there's no userspace involvement needed for PML.
+ */
+ return 1;
+}
+
+static int handle_preemption_timer(struct kvm_vcpu *vcpu)
+{
+ if (!to_vmx(vcpu)->req_immediate_exit)
+ kvm_lapic_expired_hv_timer(vcpu);
+ return 1;
+}
+
+static bool valid_ept_address(struct kvm_vcpu *vcpu, u64 address)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int maxphyaddr = cpuid_maxphyaddr(vcpu);
+
+ /* Check for memory type validity */
+ switch (address & VMX_EPTP_MT_MASK) {
+ case VMX_EPTP_MT_UC:
+ if (!(vmx->nested.msrs.ept_caps & VMX_EPTP_UC_BIT))
+ return false;
+ break;
+ case VMX_EPTP_MT_WB:
+ if (!(vmx->nested.msrs.ept_caps & VMX_EPTP_WB_BIT))
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ /* only 4 levels page-walk length are valid */
+ if ((address & VMX_EPTP_PWL_MASK) != VMX_EPTP_PWL_4)
+ return false;
+
+ /* Reserved bits should not be set */
+ if (address >> maxphyaddr || ((address >> 7) & 0x1f))
+ return false;
+
+ /* AD, if set, should be supported */
+ if (address & VMX_EPTP_AD_ENABLE_BIT) {
+ if (!(vmx->nested.msrs.ept_caps & VMX_EPT_AD_BIT))
+ return false;
+ }
+
+ return true;
+}
+
+static int nested_vmx_eptp_switching(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ u32 index = vcpu->arch.regs[VCPU_REGS_RCX];
+ u64 address;
+ bool accessed_dirty;
+ struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
+
+ if (!nested_cpu_has_eptp_switching(vmcs12) ||
+ !nested_cpu_has_ept(vmcs12))
+ return 1;
+
+ if (index >= VMFUNC_EPTP_ENTRIES)
+ return 1;
+
+
+ if (kvm_vcpu_read_guest_page(vcpu, vmcs12->eptp_list_address >> PAGE_SHIFT,
+ &address, index * 8, 8))
+ return 1;
+
+ accessed_dirty = !!(address & VMX_EPTP_AD_ENABLE_BIT);
+
+ /*
+ * If the (L2) guest does a vmfunc to the currently
+ * active ept pointer, we don't have to do anything else
+ */
+ if (vmcs12->ept_pointer != address) {
+ if (!valid_ept_address(vcpu, address))
+ return 1;
+
+ kvm_mmu_unload(vcpu);
+ mmu->ept_ad = accessed_dirty;
+ mmu->base_role.ad_disabled = !accessed_dirty;
+ vmcs12->ept_pointer = address;
+ /*
+ * TODO: Check what's the correct approach in case
+ * mmu reload fails. Currently, we just let the next
+ * reload potentially fail
+ */
+ kvm_mmu_reload(vcpu);
+ }
+
+ return 0;
+}
+
+static int handle_vmfunc(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct vmcs12 *vmcs12;
+ u32 function = vcpu->arch.regs[VCPU_REGS_RAX];
+
+ /*
+ * VMFUNC is only supported for nested guests, but we always enable the
+ * secondary control for simplicity; for non-nested mode, fake that we
+ * didn't by injecting #UD.
+ */
+ if (!is_guest_mode(vcpu)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ vmcs12 = get_vmcs12(vcpu);
+ if ((vmcs12->vm_function_control & (1 << function)) == 0)
+ goto fail;
+
+ switch (function) {
+ case 0:
+ if (nested_vmx_eptp_switching(vcpu, vmcs12))
+ goto fail;
+ break;
+ default:
+ goto fail;
+ }
+ return kvm_skip_emulated_instruction(vcpu);
+
+fail:
+ nested_vmx_vmexit(vcpu, vmx->exit_reason,
+ vmcs_read32(VM_EXIT_INTR_INFO),
+ vmcs_readl(EXIT_QUALIFICATION));
+ return 1;
+}
+
+static int handle_encls(struct kvm_vcpu *vcpu)
+{
+ /*
+ * SGX virtualization is not yet supported. There is no software
+ * enable bit for SGX, so we have to trap ENCLS and inject a #UD
+ * to prevent the guest from executing ENCLS.
+ */
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+}
+
+/*
+ * The exit handlers return 1 if the exit was handled fully and guest execution
+ * may resume. Otherwise they set the kvm_run parameter to indicate what needs
+ * to be done to userspace and return 0.
+ */
+static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
+ [EXIT_REASON_EXCEPTION_NMI] = handle_exception,
+ [EXIT_REASON_EXTERNAL_INTERRUPT] = handle_external_interrupt,
+ [EXIT_REASON_TRIPLE_FAULT] = handle_triple_fault,
+ [EXIT_REASON_NMI_WINDOW] = handle_nmi_window,
+ [EXIT_REASON_IO_INSTRUCTION] = handle_io,
+ [EXIT_REASON_CR_ACCESS] = handle_cr,
+ [EXIT_REASON_DR_ACCESS] = handle_dr,
+ [EXIT_REASON_CPUID] = handle_cpuid,
+ [EXIT_REASON_MSR_READ] = handle_rdmsr,
+ [EXIT_REASON_MSR_WRITE] = handle_wrmsr,
+ [EXIT_REASON_PENDING_INTERRUPT] = handle_interrupt_window,
+ [EXIT_REASON_HLT] = handle_halt,
+ [EXIT_REASON_INVD] = handle_invd,
+ [EXIT_REASON_INVLPG] = handle_invlpg,
+ [EXIT_REASON_RDPMC] = handle_rdpmc,
+ [EXIT_REASON_VMCALL] = handle_vmcall,
+ [EXIT_REASON_VMCLEAR] = handle_vmclear,
+ [EXIT_REASON_VMLAUNCH] = handle_vmlaunch,
+ [EXIT_REASON_VMPTRLD] = handle_vmptrld,
+ [EXIT_REASON_VMPTRST] = handle_vmptrst,
+ [EXIT_REASON_VMREAD] = handle_vmread,
+ [EXIT_REASON_VMRESUME] = handle_vmresume,
+ [EXIT_REASON_VMWRITE] = handle_vmwrite,
+ [EXIT_REASON_VMOFF] = handle_vmoff,
+ [EXIT_REASON_VMON] = handle_vmon,
+ [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold,
+ [EXIT_REASON_APIC_ACCESS] = handle_apic_access,
+ [EXIT_REASON_APIC_WRITE] = handle_apic_write,
+ [EXIT_REASON_EOI_INDUCED] = handle_apic_eoi_induced,
+ [EXIT_REASON_WBINVD] = handle_wbinvd,
+ [EXIT_REASON_XSETBV] = handle_xsetbv,
+ [EXIT_REASON_TASK_SWITCH] = handle_task_switch,
+ [EXIT_REASON_MCE_DURING_VMENTRY] = handle_machine_check,
+ [EXIT_REASON_GDTR_IDTR] = handle_desc,
+ [EXIT_REASON_LDTR_TR] = handle_desc,
+ [EXIT_REASON_EPT_VIOLATION] = handle_ept_violation,
+ [EXIT_REASON_EPT_MISCONFIG] = handle_ept_misconfig,
+ [EXIT_REASON_PAUSE_INSTRUCTION] = handle_pause,
+ [EXIT_REASON_MWAIT_INSTRUCTION] = handle_mwait,
+ [EXIT_REASON_MONITOR_TRAP_FLAG] = handle_monitor_trap,
+ [EXIT_REASON_MONITOR_INSTRUCTION] = handle_monitor,
+ [EXIT_REASON_INVEPT] = handle_invept,
+ [EXIT_REASON_INVVPID] = handle_invvpid,
+ [EXIT_REASON_RDRAND] = handle_invalid_op,
+ [EXIT_REASON_RDSEED] = handle_invalid_op,
+ [EXIT_REASON_XSAVES] = handle_xsaves,
+ [EXIT_REASON_XRSTORS] = handle_xrstors,
+ [EXIT_REASON_PML_FULL] = handle_pml_full,
+ [EXIT_REASON_INVPCID] = handle_invpcid,
+ [EXIT_REASON_VMFUNC] = handle_vmfunc,
+ [EXIT_REASON_PREEMPTION_TIMER] = handle_preemption_timer,
+ [EXIT_REASON_ENCLS] = handle_encls,
+};
+
+static const int kvm_vmx_max_exit_handlers =
+ ARRAY_SIZE(kvm_vmx_exit_handlers);
+
+/*
+ * Return true if an IO instruction with the specified port and size should cause
+ * a VM-exit into L1.
+ */
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+ int size)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ gpa_t bitmap, last_bitmap;
+ u8 b;
+
+ last_bitmap = (gpa_t)-1;
+ b = -1;
+
+ while (size > 0) {
+ if (port < 0x8000)
+ bitmap = vmcs12->io_bitmap_a;
+ else if (port < 0x10000)
+ bitmap = vmcs12->io_bitmap_b;
+ else
+ return true;
+ bitmap += (port & 0x7fff) / 8;
+
+ if (last_bitmap != bitmap)
+ if (kvm_vcpu_read_guest(vcpu, bitmap, &b, 1))
+ return true;
+ if (b & (1 << (port & 7)))
+ return true;
+
+ port++;
+ size--;
+ last_bitmap = bitmap;
+ }
+
+ return false;
+}
+
+/*
+ * Return 1 if we should exit from L2 to L1 to handle an MSR access access,
+ * rather than handle it ourselves in L0. I.e., check whether L1 expressed
+ * disinterest in the current event (read or write a specific MSR) by using an
+ * MSR bitmap. This may be the case even when L0 doesn't use MSR bitmaps.
+ */
+static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12, u32 exit_reason)
+{
+ u32 msr_index = vcpu->arch.regs[VCPU_REGS_RCX];
+ gpa_t bitmap;
+
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_MSR_BITMAPS))
+ return true;
+
+ /*
+ * The MSR_BITMAP page is divided into four 1024-byte bitmaps,
+ * for the four combinations of read/write and low/high MSR numbers.
+ * First we need to figure out which of the four to use:
+ */
+ bitmap = vmcs12->msr_bitmap;
+ if (exit_reason == EXIT_REASON_MSR_WRITE)
+ bitmap += 2048;
+ if (msr_index >= 0xc0000000) {
+ msr_index -= 0xc0000000;
+ bitmap += 1024;
+ }
+
+ /* Then read the msr_index'th bit from this bitmap: */
+ if (msr_index < 1024*8) {
+ unsigned char b;
+ if (kvm_vcpu_read_guest(vcpu, bitmap + msr_index/8, &b, 1))
+ return true;
+ return 1 & (b >> (msr_index & 7));
+ } else
+ return true; /* let L1 handle the wrong parameter */
+}
+
+/*
+ * Return 1 if we should exit from L2 to L1 to handle a CR access exit,
+ * rather than handle it ourselves in L0. I.e., check if L1 wanted to
+ * intercept (via guest_host_mask etc.) the current event.
+ */
+static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+ int cr = exit_qualification & 15;
+ int reg;
+ unsigned long val;
+
+ switch ((exit_qualification >> 4) & 3) {
+ case 0: /* mov to cr */
+ reg = (exit_qualification >> 8) & 15;
+ val = kvm_register_readl(vcpu, reg);
+ switch (cr) {
+ case 0:
+ if (vmcs12->cr0_guest_host_mask &
+ (val ^ vmcs12->cr0_read_shadow))
+ return true;
+ break;
+ case 3:
+ if ((vmcs12->cr3_target_count >= 1 &&
+ vmcs12->cr3_target_value0 == val) ||
+ (vmcs12->cr3_target_count >= 2 &&
+ vmcs12->cr3_target_value1 == val) ||
+ (vmcs12->cr3_target_count >= 3 &&
+ vmcs12->cr3_target_value2 == val) ||
+ (vmcs12->cr3_target_count >= 4 &&
+ vmcs12->cr3_target_value3 == val))
+ return false;
+ if (nested_cpu_has(vmcs12, CPU_BASED_CR3_LOAD_EXITING))
+ return true;
+ break;
+ case 4:
+ if (vmcs12->cr4_guest_host_mask &
+ (vmcs12->cr4_read_shadow ^ val))
+ return true;
+ break;
+ case 8:
+ if (nested_cpu_has(vmcs12, CPU_BASED_CR8_LOAD_EXITING))
+ return true;
+ break;
+ }
+ break;
+ case 2: /* clts */
+ if ((vmcs12->cr0_guest_host_mask & X86_CR0_TS) &&
+ (vmcs12->cr0_read_shadow & X86_CR0_TS))
+ return true;
+ break;
+ case 1: /* mov from cr */
+ switch (cr) {
+ case 3:
+ if (vmcs12->cpu_based_vm_exec_control &
+ CPU_BASED_CR3_STORE_EXITING)
+ return true;
+ break;
+ case 8:
+ if (vmcs12->cpu_based_vm_exec_control &
+ CPU_BASED_CR8_STORE_EXITING)
+ return true;
+ break;
+ }
+ break;
+ case 3: /* lmsw */
+ /*
+ * lmsw can change bits 1..3 of cr0, and only set bit 0 of
+ * cr0. Other attempted changes are ignored, with no exit.
+ */
+ val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f;
+ if (vmcs12->cr0_guest_host_mask & 0xe &
+ (val ^ vmcs12->cr0_read_shadow))
+ return true;
+ if ((vmcs12->cr0_guest_host_mask & 0x1) &&
+ !(vmcs12->cr0_read_shadow & 0x1) &&
+ (val & 0x1))
+ return true;
+ break;
+ }
+ return false;
+}
+
+static bool nested_vmx_exit_handled_vmcs_access(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12, gpa_t bitmap)
+{
+ u32 vmx_instruction_info;
+ unsigned long field;
+ u8 b;
+
+ if (!nested_cpu_has_shadow_vmcs(vmcs12))
+ return true;
+
+ /* Decode instruction info and find the field to access */
+ vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+ field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+
+ /* Out-of-range fields always cause a VM exit from L2 to L1 */
+ if (field >> 15)
+ return true;
+
+ if (kvm_vcpu_read_guest(vcpu, bitmap + field/8, &b, 1))
+ return true;
+
+ return 1 & (b >> (field & 7));
+}
+
+/*
+ * Return 1 if we should exit from L2 to L1 to handle an exit, or 0 if we
+ * should handle it ourselves in L0 (and then continue L2). Only call this
+ * when in is_guest_mode (L2).
+ */
+static bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
+{
+ u32 intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+ if (vmx->nested.nested_run_pending)
+ return false;
+
+ if (unlikely(vmx->fail)) {
+ pr_info_ratelimited("%s failed vm entry %x\n", __func__,
+ vmcs_read32(VM_INSTRUCTION_ERROR));
+ return true;
+ }
+
+ /*
+ * The host physical addresses of some pages of guest memory
+ * are loaded into the vmcs02 (e.g. vmcs12's Virtual APIC
+ * Page). The CPU may write to these pages via their host
+ * physical address while L2 is running, bypassing any
+ * address-translation-based dirty tracking (e.g. EPT write
+ * protection).
+ *
+ * Mark them dirty on every exit from L2 to prevent them from
+ * getting out of sync with dirty tracking.
+ */
+ nested_mark_vmcs12_pages_dirty(vcpu);
+
+ trace_kvm_nested_vmexit(kvm_rip_read(vcpu), exit_reason,
+ vmcs_readl(EXIT_QUALIFICATION),
+ vmx->idt_vectoring_info,
+ intr_info,
+ vmcs_read32(VM_EXIT_INTR_ERROR_CODE),
+ KVM_ISA_VMX);
+
+ switch ((u16)exit_reason) {
+ case EXIT_REASON_EXCEPTION_NMI:
+ if (is_nmi(intr_info))
+ return false;
+ else if (is_page_fault(intr_info))
+ return !vmx->vcpu.arch.apf.host_apf_reason && enable_ept;
+ else if (is_no_device(intr_info) &&
+ !(vmcs12->guest_cr0 & X86_CR0_TS))
+ return false;
+ else if (is_debug(intr_info) &&
+ vcpu->guest_debug &
+ (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
+ return false;
+ else if (is_breakpoint(intr_info) &&
+ vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
+ return false;
+ return vmcs12->exception_bitmap &
+ (1u << (intr_info & INTR_INFO_VECTOR_MASK));
+ case EXIT_REASON_EXTERNAL_INTERRUPT:
+ return false;
+ case EXIT_REASON_TRIPLE_FAULT:
+ return true;
+ case EXIT_REASON_PENDING_INTERRUPT:
+ return nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_INTR_PENDING);
+ case EXIT_REASON_NMI_WINDOW:
+ return nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_NMI_PENDING);
+ case EXIT_REASON_TASK_SWITCH:
+ return true;
+ case EXIT_REASON_CPUID:
+ return true;
+ case EXIT_REASON_HLT:
+ return nested_cpu_has(vmcs12, CPU_BASED_HLT_EXITING);
+ case EXIT_REASON_INVD:
+ return true;
+ case EXIT_REASON_INVLPG:
+ return nested_cpu_has(vmcs12, CPU_BASED_INVLPG_EXITING);
+ case EXIT_REASON_RDPMC:
+ return nested_cpu_has(vmcs12, CPU_BASED_RDPMC_EXITING);
+ case EXIT_REASON_RDRAND:
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDRAND_EXITING);
+ case EXIT_REASON_RDSEED:
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDSEED_EXITING);
+ case EXIT_REASON_RDTSC: case EXIT_REASON_RDTSCP:
+ return nested_cpu_has(vmcs12, CPU_BASED_RDTSC_EXITING);
+ case EXIT_REASON_VMREAD:
+ return nested_vmx_exit_handled_vmcs_access(vcpu, vmcs12,
+ vmcs12->vmread_bitmap);
+ case EXIT_REASON_VMWRITE:
+ return nested_vmx_exit_handled_vmcs_access(vcpu, vmcs12,
+ vmcs12->vmwrite_bitmap);
+ case EXIT_REASON_VMCALL: case EXIT_REASON_VMCLEAR:
+ case EXIT_REASON_VMLAUNCH: case EXIT_REASON_VMPTRLD:
+ case EXIT_REASON_VMPTRST: case EXIT_REASON_VMRESUME:
+ case EXIT_REASON_VMOFF: case EXIT_REASON_VMON:
+ case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID:
+ /*
+ * VMX instructions trap unconditionally. This allows L1 to
+ * emulate them for its L2 guest, i.e., allows 3-level nesting!
+ */
+ return true;
+ case EXIT_REASON_CR_ACCESS:
+ return nested_vmx_exit_handled_cr(vcpu, vmcs12);
+ case EXIT_REASON_DR_ACCESS:
+ return nested_cpu_has(vmcs12, CPU_BASED_MOV_DR_EXITING);
+ case EXIT_REASON_IO_INSTRUCTION:
+ return nested_vmx_exit_handled_io(vcpu, vmcs12);
+ case EXIT_REASON_GDTR_IDTR: case EXIT_REASON_LDTR_TR:
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC);
+ case EXIT_REASON_MSR_READ:
+ case EXIT_REASON_MSR_WRITE:
+ return nested_vmx_exit_handled_msr(vcpu, vmcs12, exit_reason);
+ case EXIT_REASON_INVALID_STATE:
+ return true;
+ case EXIT_REASON_MWAIT_INSTRUCTION:
+ return nested_cpu_has(vmcs12, CPU_BASED_MWAIT_EXITING);
+ case EXIT_REASON_MONITOR_TRAP_FLAG:
+ return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_TRAP_FLAG);
+ case EXIT_REASON_MONITOR_INSTRUCTION:
+ return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_EXITING);
+ case EXIT_REASON_PAUSE_INSTRUCTION:
+ return nested_cpu_has(vmcs12, CPU_BASED_PAUSE_EXITING) ||
+ nested_cpu_has2(vmcs12,
+ SECONDARY_EXEC_PAUSE_LOOP_EXITING);
+ case EXIT_REASON_MCE_DURING_VMENTRY:
+ return false;
+ case EXIT_REASON_TPR_BELOW_THRESHOLD:
+ return nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW);
+ case EXIT_REASON_APIC_ACCESS:
+ case EXIT_REASON_APIC_WRITE:
+ case EXIT_REASON_EOI_INDUCED:
+ /*
+ * The controls for "virtualize APIC accesses," "APIC-
+ * register virtualization," and "virtual-interrupt
+ * delivery" only come from vmcs12.
+ */
+ return true;
+ case EXIT_REASON_EPT_VIOLATION:
+ /*
+ * L0 always deals with the EPT violation. If nested EPT is
+ * used, and the nested mmu code discovers that the address is
+ * missing in the guest EPT table (EPT12), the EPT violation
+ * will be injected with nested_ept_inject_page_fault()
+ */
+ return false;
+ case EXIT_REASON_EPT_MISCONFIG:
+ /*
+ * L2 never uses directly L1's EPT, but rather L0's own EPT
+ * table (shadow on EPT) or a merged EPT table that L0 built
+ * (EPT on EPT). So any problems with the structure of the
+ * table is L0's fault.
+ */
+ return false;
+ case EXIT_REASON_INVPCID:
+ return
+ nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_INVPCID) &&
+ nested_cpu_has(vmcs12, CPU_BASED_INVLPG_EXITING);
+ case EXIT_REASON_WBINVD:
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING);
+ case EXIT_REASON_XSETBV:
+ return true;
+ case EXIT_REASON_XSAVES: case EXIT_REASON_XRSTORS:
+ /*
+ * This should never happen, since it is not possible to
+ * set XSS to a non-zero value---neither in L1 nor in L2.
+ * If if it were, XSS would have to be checked against
+ * the XSS exit bitmap in vmcs12.
+ */
+ return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES);
+ case EXIT_REASON_PREEMPTION_TIMER:
+ return false;
+ case EXIT_REASON_PML_FULL:
+ /* We emulate PML support to L1. */
+ return false;
+ case EXIT_REASON_VMFUNC:
+ /* VM functions are emulated through L2->L0 vmexits. */
+ return false;
+ case EXIT_REASON_ENCLS:
+ /* SGX is never exposed to L1 */
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int nested_vmx_reflect_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason)
+{
+ u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+ /*
+ * At this point, the exit interruption info in exit_intr_info
+ * is only valid for EXCEPTION_NMI exits. For EXTERNAL_INTERRUPT
+ * we need to query the in-kernel LAPIC.
+ */
+ WARN_ON(exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT);
+ if ((exit_intr_info &
+ (INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK)) ==
+ (INTR_INFO_VALID_MASK | INTR_INFO_DELIVER_CODE_MASK)) {
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ vmcs12->vm_exit_intr_error_code =
+ vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
+ }
+
+ nested_vmx_vmexit(vcpu, exit_reason, exit_intr_info,
+ vmcs_readl(EXIT_QUALIFICATION));
+ return 1;
+}
+
+static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
+{
+ *info1 = vmcs_readl(EXIT_QUALIFICATION);
+ *info2 = vmcs_read32(VM_EXIT_INTR_INFO);
+}
+
+static void vmx_destroy_pml_buffer(struct vcpu_vmx *vmx)
+{
+ if (vmx->pml_pg) {
+ __free_page(vmx->pml_pg);
+ vmx->pml_pg = NULL;
+ }
+}
+
+static void vmx_flush_pml_buffer(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u64 *pml_buf;
+ u16 pml_idx;
+
+ pml_idx = vmcs_read16(GUEST_PML_INDEX);
+
+ /* Do nothing if PML buffer is empty */
+ if (pml_idx == (PML_ENTITY_NUM - 1))
+ return;
+
+ /* PML index always points to next available PML buffer entity */
+ if (pml_idx >= PML_ENTITY_NUM)
+ pml_idx = 0;
+ else
+ pml_idx++;
+
+ pml_buf = page_address(vmx->pml_pg);
+ for (; pml_idx < PML_ENTITY_NUM; pml_idx++) {
+ u64 gpa;
+
+ gpa = pml_buf[pml_idx];
+ WARN_ON(gpa & (PAGE_SIZE - 1));
+ kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
+ }
+
+ /* reset PML index */
+ vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
+}
+
+/*
+ * Flush all vcpus' PML buffer and update logged GPAs to dirty_bitmap.
+ * Called before reporting dirty_bitmap to userspace.
+ */
+static void kvm_flush_pml_buffers(struct kvm *kvm)
+{
+ int i;
+ struct kvm_vcpu *vcpu;
+ /*
+ * We only need to kick vcpu out of guest mode here, as PML buffer
+ * is flushed at beginning of all VMEXITs, and it's obvious that only
+ * vcpus running in guest are possible to have unflushed GPAs in PML
+ * buffer.
+ */
+ kvm_for_each_vcpu(i, vcpu, kvm)
+ kvm_vcpu_kick(vcpu);
+}
+
+static void vmx_dump_sel(char *name, uint32_t sel)
+{
+ pr_err("%s sel=0x%04x, attr=0x%05x, limit=0x%08x, base=0x%016lx\n",
+ name, vmcs_read16(sel),
+ vmcs_read32(sel + GUEST_ES_AR_BYTES - GUEST_ES_SELECTOR),
+ vmcs_read32(sel + GUEST_ES_LIMIT - GUEST_ES_SELECTOR),
+ vmcs_readl(sel + GUEST_ES_BASE - GUEST_ES_SELECTOR));
+}
+
+static void vmx_dump_dtsel(char *name, uint32_t limit)
+{
+ pr_err("%s limit=0x%08x, base=0x%016lx\n",
+ name, vmcs_read32(limit),
+ vmcs_readl(limit + GUEST_GDTR_BASE - GUEST_GDTR_LIMIT));
+}
+
+static void dump_vmcs(void)
+{
+ u32 vmentry_ctl = vmcs_read32(VM_ENTRY_CONTROLS);
+ u32 vmexit_ctl = vmcs_read32(VM_EXIT_CONTROLS);
+ u32 cpu_based_exec_ctrl = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+ u32 pin_based_exec_ctrl = vmcs_read32(PIN_BASED_VM_EXEC_CONTROL);
+ u32 secondary_exec_control = 0;
+ unsigned long cr4 = vmcs_readl(GUEST_CR4);
+ u64 efer = vmcs_read64(GUEST_IA32_EFER);
+ int i, n;
+
+ if (cpu_has_secondary_exec_ctrls())
+ secondary_exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+
+ pr_err("*** Guest State ***\n");
+ pr_err("CR0: actual=0x%016lx, shadow=0x%016lx, gh_mask=%016lx\n",
+ vmcs_readl(GUEST_CR0), vmcs_readl(CR0_READ_SHADOW),
+ vmcs_readl(CR0_GUEST_HOST_MASK));
+ pr_err("CR4: actual=0x%016lx, shadow=0x%016lx, gh_mask=%016lx\n",
+ cr4, vmcs_readl(CR4_READ_SHADOW), vmcs_readl(CR4_GUEST_HOST_MASK));
+ pr_err("CR3 = 0x%016lx\n", vmcs_readl(GUEST_CR3));
+ if ((secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT) &&
+ (cr4 & X86_CR4_PAE) && !(efer & EFER_LMA))
+ {
+ pr_err("PDPTR0 = 0x%016llx PDPTR1 = 0x%016llx\n",
+ vmcs_read64(GUEST_PDPTR0), vmcs_read64(GUEST_PDPTR1));
+ pr_err("PDPTR2 = 0x%016llx PDPTR3 = 0x%016llx\n",
+ vmcs_read64(GUEST_PDPTR2), vmcs_read64(GUEST_PDPTR3));
+ }
+ pr_err("RSP = 0x%016lx RIP = 0x%016lx\n",
+ vmcs_readl(GUEST_RSP), vmcs_readl(GUEST_RIP));
+ pr_err("RFLAGS=0x%08lx DR7 = 0x%016lx\n",
+ vmcs_readl(GUEST_RFLAGS), vmcs_readl(GUEST_DR7));
+ pr_err("Sysenter RSP=%016lx CS:RIP=%04x:%016lx\n",
+ vmcs_readl(GUEST_SYSENTER_ESP),
+ vmcs_read32(GUEST_SYSENTER_CS), vmcs_readl(GUEST_SYSENTER_EIP));
+ vmx_dump_sel("CS: ", GUEST_CS_SELECTOR);
+ vmx_dump_sel("DS: ", GUEST_DS_SELECTOR);
+ vmx_dump_sel("SS: ", GUEST_SS_SELECTOR);
+ vmx_dump_sel("ES: ", GUEST_ES_SELECTOR);
+ vmx_dump_sel("FS: ", GUEST_FS_SELECTOR);
+ vmx_dump_sel("GS: ", GUEST_GS_SELECTOR);
+ vmx_dump_dtsel("GDTR:", GUEST_GDTR_LIMIT);
+ vmx_dump_sel("LDTR:", GUEST_LDTR_SELECTOR);
+ vmx_dump_dtsel("IDTR:", GUEST_IDTR_LIMIT);
+ vmx_dump_sel("TR: ", GUEST_TR_SELECTOR);
+ if ((vmexit_ctl & (VM_EXIT_SAVE_IA32_PAT | VM_EXIT_SAVE_IA32_EFER)) ||
+ (vmentry_ctl & (VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_LOAD_IA32_EFER)))
+ pr_err("EFER = 0x%016llx PAT = 0x%016llx\n",
+ efer, vmcs_read64(GUEST_IA32_PAT));
+ pr_err("DebugCtl = 0x%016llx DebugExceptions = 0x%016lx\n",
+ vmcs_read64(GUEST_IA32_DEBUGCTL),
+ vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS));
+ if (cpu_has_load_perf_global_ctrl &&
+ vmentry_ctl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
+ pr_err("PerfGlobCtl = 0x%016llx\n",
+ vmcs_read64(GUEST_IA32_PERF_GLOBAL_CTRL));
+ if (vmentry_ctl & VM_ENTRY_LOAD_BNDCFGS)
+ pr_err("BndCfgS = 0x%016llx\n", vmcs_read64(GUEST_BNDCFGS));
+ pr_err("Interruptibility = %08x ActivityState = %08x\n",
+ vmcs_read32(GUEST_INTERRUPTIBILITY_INFO),
+ vmcs_read32(GUEST_ACTIVITY_STATE));
+ if (secondary_exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)
+ pr_err("InterruptStatus = %04x\n",
+ vmcs_read16(GUEST_INTR_STATUS));
+
+ pr_err("*** Host State ***\n");
+ pr_err("RIP = 0x%016lx RSP = 0x%016lx\n",
+ vmcs_readl(HOST_RIP), vmcs_readl(HOST_RSP));
+ pr_err("CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x TR=%04x\n",
+ vmcs_read16(HOST_CS_SELECTOR), vmcs_read16(HOST_SS_SELECTOR),
+ vmcs_read16(HOST_DS_SELECTOR), vmcs_read16(HOST_ES_SELECTOR),
+ vmcs_read16(HOST_FS_SELECTOR), vmcs_read16(HOST_GS_SELECTOR),
+ vmcs_read16(HOST_TR_SELECTOR));
+ pr_err("FSBase=%016lx GSBase=%016lx TRBase=%016lx\n",
+ vmcs_readl(HOST_FS_BASE), vmcs_readl(HOST_GS_BASE),
+ vmcs_readl(HOST_TR_BASE));
+ pr_err("GDTBase=%016lx IDTBase=%016lx\n",
+ vmcs_readl(HOST_GDTR_BASE), vmcs_readl(HOST_IDTR_BASE));
+ pr_err("CR0=%016lx CR3=%016lx CR4=%016lx\n",
+ vmcs_readl(HOST_CR0), vmcs_readl(HOST_CR3),
+ vmcs_readl(HOST_CR4));
+ pr_err("Sysenter RSP=%016lx CS:RIP=%04x:%016lx\n",
+ vmcs_readl(HOST_IA32_SYSENTER_ESP),
+ vmcs_read32(HOST_IA32_SYSENTER_CS),
+ vmcs_readl(HOST_IA32_SYSENTER_EIP));
+ if (vmexit_ctl & (VM_EXIT_LOAD_IA32_PAT | VM_EXIT_LOAD_IA32_EFER))
+ pr_err("EFER = 0x%016llx PAT = 0x%016llx\n",
+ vmcs_read64(HOST_IA32_EFER),
+ vmcs_read64(HOST_IA32_PAT));
+ if (cpu_has_load_perf_global_ctrl &&
+ vmexit_ctl & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
+ pr_err("PerfGlobCtl = 0x%016llx\n",
+ vmcs_read64(HOST_IA32_PERF_GLOBAL_CTRL));
+
+ pr_err("*** Control State ***\n");
+ pr_err("PinBased=%08x CPUBased=%08x SecondaryExec=%08x\n",
+ pin_based_exec_ctrl, cpu_based_exec_ctrl, secondary_exec_control);
+ pr_err("EntryControls=%08x ExitControls=%08x\n", vmentry_ctl, vmexit_ctl);
+ pr_err("ExceptionBitmap=%08x PFECmask=%08x PFECmatch=%08x\n",
+ vmcs_read32(EXCEPTION_BITMAP),
+ vmcs_read32(PAGE_FAULT_ERROR_CODE_MASK),
+ vmcs_read32(PAGE_FAULT_ERROR_CODE_MATCH));
+ pr_err("VMEntry: intr_info=%08x errcode=%08x ilen=%08x\n",
+ vmcs_read32(VM_ENTRY_INTR_INFO_FIELD),
+ vmcs_read32(VM_ENTRY_EXCEPTION_ERROR_CODE),
+ vmcs_read32(VM_ENTRY_INSTRUCTION_LEN));
+ pr_err("VMExit: intr_info=%08x errcode=%08x ilen=%08x\n",
+ vmcs_read32(VM_EXIT_INTR_INFO),
+ vmcs_read32(VM_EXIT_INTR_ERROR_CODE),
+ vmcs_read32(VM_EXIT_INSTRUCTION_LEN));
+ pr_err(" reason=%08x qualification=%016lx\n",
+ vmcs_read32(VM_EXIT_REASON), vmcs_readl(EXIT_QUALIFICATION));
+ pr_err("IDTVectoring: info=%08x errcode=%08x\n",
+ vmcs_read32(IDT_VECTORING_INFO_FIELD),
+ vmcs_read32(IDT_VECTORING_ERROR_CODE));
+ pr_err("TSC Offset = 0x%016llx\n", vmcs_read64(TSC_OFFSET));
+ if (secondary_exec_control & SECONDARY_EXEC_TSC_SCALING)
+ pr_err("TSC Multiplier = 0x%016llx\n",
+ vmcs_read64(TSC_MULTIPLIER));
+ if (cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW)
+ pr_err("TPR Threshold = 0x%02x\n", vmcs_read32(TPR_THRESHOLD));
+ if (pin_based_exec_ctrl & PIN_BASED_POSTED_INTR)
+ pr_err("PostedIntrVec = 0x%02x\n", vmcs_read16(POSTED_INTR_NV));
+ if ((secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT))
+ pr_err("EPT pointer = 0x%016llx\n", vmcs_read64(EPT_POINTER));
+ n = vmcs_read32(CR3_TARGET_COUNT);
+ for (i = 0; i + 1 < n; i += 4)
+ pr_err("CR3 target%u=%016lx target%u=%016lx\n",
+ i, vmcs_readl(CR3_TARGET_VALUE0 + i * 2),
+ i + 1, vmcs_readl(CR3_TARGET_VALUE0 + i * 2 + 2));
+ if (i < n)
+ pr_err("CR3 target%u=%016lx\n",
+ i, vmcs_readl(CR3_TARGET_VALUE0 + i * 2));
+ if (secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING)
+ pr_err("PLE Gap=%08x Window=%08x\n",
+ vmcs_read32(PLE_GAP), vmcs_read32(PLE_WINDOW));
+ if (secondary_exec_control & SECONDARY_EXEC_ENABLE_VPID)
+ pr_err("Virtual processor ID = 0x%04x\n",
+ vmcs_read16(VIRTUAL_PROCESSOR_ID));
+}
+
+/*
+ * The guest has exited. See if we can fix it or if we need userspace
+ * assistance.
+ */
+static int vmx_handle_exit(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 exit_reason = vmx->exit_reason;
+ u32 vectoring_info = vmx->idt_vectoring_info;
+
+ trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX);
+
+ /*
+ * Flush logged GPAs PML buffer, this will make dirty_bitmap more
+ * updated. Another good is, in kvm_vm_ioctl_get_dirty_log, before
+ * querying dirty_bitmap, we only need to kick all vcpus out of guest
+ * mode as if vcpus is in root mode, the PML buffer must has been
+ * flushed already.
+ */
+ if (enable_pml)
+ vmx_flush_pml_buffer(vcpu);
+
+ /* If guest state is invalid, start emulating */
+ if (vmx->emulation_required)
+ return handle_invalid_guest_state(vcpu);
+
+ if (is_guest_mode(vcpu) && nested_vmx_exit_reflected(vcpu, exit_reason))
+ return nested_vmx_reflect_vmexit(vcpu, exit_reason);
+
+ if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
+ dump_vmcs();
+ vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+ vcpu->run->fail_entry.hardware_entry_failure_reason
+ = exit_reason;
+ return 0;
+ }
+
+ if (unlikely(vmx->fail)) {
+ vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+ vcpu->run->fail_entry.hardware_entry_failure_reason
+ = vmcs_read32(VM_INSTRUCTION_ERROR);
+ return 0;
+ }
+
+ /*
+ * Note:
+ * Do not try to fix EXIT_REASON_EPT_MISCONFIG if it caused by
+ * delivery event since it indicates guest is accessing MMIO.
+ * The vm-exit can be triggered again after return to guest that
+ * will cause infinite loop.
+ */
+ if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
+ (exit_reason != EXIT_REASON_EXCEPTION_NMI &&
+ exit_reason != EXIT_REASON_EPT_VIOLATION &&
+ exit_reason != EXIT_REASON_PML_FULL &&
+ exit_reason != EXIT_REASON_APIC_ACCESS &&
+ exit_reason != EXIT_REASON_TASK_SWITCH)) {
+ vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+ vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
+ vcpu->run->internal.ndata = 3;
+ vcpu->run->internal.data[0] = vectoring_info;
+ vcpu->run->internal.data[1] = exit_reason;
+ vcpu->run->internal.data[2] = vcpu->arch.exit_qualification;
+ if (exit_reason == EXIT_REASON_EPT_MISCONFIG) {
+ vcpu->run->internal.ndata++;
+ vcpu->run->internal.data[3] =
+ vmcs_read64(GUEST_PHYSICAL_ADDRESS);
+ }
+ return 0;
+ }
+
+ if (unlikely(!enable_vnmi &&
+ vmx->loaded_vmcs->soft_vnmi_blocked)) {
+ if (vmx_interrupt_allowed(vcpu)) {
+ vmx->loaded_vmcs->soft_vnmi_blocked = 0;
+ } else if (vmx->loaded_vmcs->vnmi_blocked_time > 1000000000LL &&
+ vcpu->arch.nmi_pending) {
+ /*
+ * This CPU don't support us in finding the end of an
+ * NMI-blocked window if the guest runs with IRQs
+ * disabled. So we pull the trigger after 1 s of
+ * futile waiting, but inform the user about this.
+ */
+ printk(KERN_WARNING "%s: Breaking out of NMI-blocked "
+ "state on VCPU %d after 1 s timeout\n",
+ __func__, vcpu->vcpu_id);
+ vmx->loaded_vmcs->soft_vnmi_blocked = 0;
+ }
+ }
+
+ if (exit_reason < kvm_vmx_max_exit_handlers
+ && kvm_vmx_exit_handlers[exit_reason])
+ return kvm_vmx_exit_handlers[exit_reason](vcpu);
+ else {
+ vcpu_unimpl(vcpu, "vmx: unexpected exit reason 0x%x\n",
+ exit_reason);
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+}
+
+/*
+ * Software based L1D cache flush which is used when microcode providing
+ * the cache control MSR is not loaded.
+ *
+ * The L1D cache is 32 KiB on Nehalem and later microarchitectures, but to
+ * flush it is required to read in 64 KiB because the replacement algorithm
+ * is not exactly LRU. This could be sized at runtime via topology
+ * information but as all relevant affected CPUs have 32KiB L1D cache size
+ * there is no point in doing so.
+ */
+static void vmx_l1d_flush(struct kvm_vcpu *vcpu)
+{
+ int size = PAGE_SIZE << L1D_CACHE_ORDER;
+
+ /*
+ * This code is only executed when the the flush mode is 'cond' or
+ * 'always'
+ */
+ if (static_branch_likely(&vmx_l1d_flush_cond)) {
+ bool flush_l1d;
+
+ /*
+ * Clear the per-vcpu flush bit, it gets set again
+ * either from vcpu_run() or from one of the unsafe
+ * VMEXIT handlers.
+ */
+ flush_l1d = vcpu->arch.l1tf_flush_l1d;
+ vcpu->arch.l1tf_flush_l1d = false;
+
+ /*
+ * Clear the per-cpu flush bit, it gets set again from
+ * the interrupt handlers.
+ */
+ flush_l1d |= kvm_get_cpu_l1tf_flush_l1d();
+ kvm_clear_cpu_l1tf_flush_l1d();
+
+ if (!flush_l1d)
+ return;
+ }
+
+ vcpu->stat.l1d_flush++;
+
+ if (static_cpu_has(X86_FEATURE_FLUSH_L1D)) {
+ wrmsrl(MSR_IA32_FLUSH_CMD, L1D_FLUSH);
+ return;
+ }
+
+ asm volatile(
+ /* First ensure the pages are in the TLB */
+ "xorl %%eax, %%eax\n"
+ ".Lpopulate_tlb:\n\t"
+ "movzbl (%[flush_pages], %%" _ASM_AX "), %%ecx\n\t"
+ "addl $4096, %%eax\n\t"
+ "cmpl %%eax, %[size]\n\t"
+ "jne .Lpopulate_tlb\n\t"
+ "xorl %%eax, %%eax\n\t"
+ "cpuid\n\t"
+ /* Now fill the cache */
+ "xorl %%eax, %%eax\n"
+ ".Lfill_cache:\n"
+ "movzbl (%[flush_pages], %%" _ASM_AX "), %%ecx\n\t"
+ "addl $64, %%eax\n\t"
+ "cmpl %%eax, %[size]\n\t"
+ "jne .Lfill_cache\n\t"
+ "lfence\n"
+ :: [flush_pages] "r" (vmx_l1d_flush_pages),
+ [size] "r" (size)
+ : "eax", "ebx", "ecx", "edx");
+}
+
+static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+ if (is_guest_mode(vcpu) &&
+ nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
+ return;
+
+ if (irr == -1 || tpr < irr) {
+ vmcs_write32(TPR_THRESHOLD, 0);
+ return;
+ }
+
+ vmcs_write32(TPR_THRESHOLD, irr);
+}
+
+static void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
+{
+ u32 sec_exec_control;
+
+ if (!lapic_in_kernel(vcpu))
+ return;
+
+ if (!flexpriority_enabled &&
+ !cpu_has_vmx_virtualize_x2apic_mode())
+ return;
+
+ /* Postpone execution until vmcs01 is the current VMCS. */
+ if (is_guest_mode(vcpu)) {
+ to_vmx(vcpu)->nested.change_vmcs01_virtual_apic_mode = true;
+ return;
+ }
+
+ sec_exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+ sec_exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE);
+
+ switch (kvm_get_apic_mode(vcpu)) {
+ case LAPIC_MODE_INVALID:
+ WARN_ONCE(true, "Invalid local APIC state");
+ case LAPIC_MODE_DISABLED:
+ break;
+ case LAPIC_MODE_XAPIC:
+ if (flexpriority_enabled) {
+ sec_exec_control |=
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ vmx_flush_tlb(vcpu, true);
+ }
+ break;
+ case LAPIC_MODE_X2APIC:
+ if (cpu_has_vmx_virtualize_x2apic_mode())
+ sec_exec_control |=
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
+ break;
+ }
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control);
+
+ vmx_update_msr_bitmap(vcpu);
+}
+
+static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa)
+{
+ if (!is_guest_mode(vcpu)) {
+ vmcs_write64(APIC_ACCESS_ADDR, hpa);
+ vmx_flush_tlb(vcpu, true);
+ }
+}
+
+static void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
+{
+ u16 status;
+ u8 old;
+
+ if (max_isr == -1)
+ max_isr = 0;
+
+ status = vmcs_read16(GUEST_INTR_STATUS);
+ old = status >> 8;
+ if (max_isr != old) {
+ status &= 0xff;
+ status |= max_isr << 8;
+ vmcs_write16(GUEST_INTR_STATUS, status);
+ }
+}
+
+static void vmx_set_rvi(int vector)
+{
+ u16 status;
+ u8 old;
+
+ if (vector == -1)
+ vector = 0;
+
+ status = vmcs_read16(GUEST_INTR_STATUS);
+ old = (u8)status & 0xff;
+ if ((u8)vector != old) {
+ status &= ~0xff;
+ status |= (u8)vector;
+ vmcs_write16(GUEST_INTR_STATUS, status);
+ }
+}
+
+static void vmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)
+{
+ /*
+ * When running L2, updating RVI is only relevant when
+ * vmcs12 virtual-interrupt-delivery enabled.
+ * However, it can be enabled only when L1 also
+ * intercepts external-interrupts and in that case
+ * we should not update vmcs02 RVI but instead intercept
+ * interrupt. Therefore, do nothing when running L2.
+ */
+ if (!is_guest_mode(vcpu))
+ vmx_set_rvi(max_irr);
+}
+
+static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int max_irr;
+ bool max_irr_updated;
+
+ WARN_ON(!vcpu->arch.apicv_active);
+ if (pi_test_on(&vmx->pi_desc)) {
+ pi_clear_on(&vmx->pi_desc);
+ /*
+ * IOMMU can write to PIR.ON, so the barrier matters even on UP.
+ * But on x86 this is just a compiler barrier anyway.
+ */
+ smp_mb__after_atomic();
+ max_irr_updated =
+ kvm_apic_update_irr(vcpu, vmx->pi_desc.pir, &max_irr);
+
+ /*
+ * If we are running L2 and L1 has a new pending interrupt
+ * which can be injected, we should re-evaluate
+ * what should be done with this new L1 interrupt.
+ * If L1 intercepts external-interrupts, we should
+ * exit from L2 to L1. Otherwise, interrupt should be
+ * delivered directly to L2.
+ */
+ if (is_guest_mode(vcpu) && max_irr_updated) {
+ if (nested_exit_on_intr(vcpu))
+ kvm_vcpu_exiting_guest_mode(vcpu);
+ else
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+ }
+ } else {
+ max_irr = kvm_lapic_find_highest_irr(vcpu);
+ }
+ vmx_hwapic_irr_update(vcpu, max_irr);
+ return max_irr;
+}
+
+static u8 vmx_has_apicv_interrupt(struct kvm_vcpu *vcpu)
+{
+ u8 rvi = vmx_get_rvi();
+ u8 vppr = kvm_lapic_get_reg(vcpu->arch.apic, APIC_PROCPRI);
+
+ return ((rvi & 0xf0) > (vppr & 0xf0));
+}
+
+static bool vmx_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
+{
+ return pi_test_on(vcpu_to_pi_desc(vcpu));
+}
+
+static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
+{
+ if (!kvm_vcpu_apicv_active(vcpu))
+ return;
+
+ vmcs_write64(EOI_EXIT_BITMAP0, eoi_exit_bitmap[0]);
+ vmcs_write64(EOI_EXIT_BITMAP1, eoi_exit_bitmap[1]);
+ vmcs_write64(EOI_EXIT_BITMAP2, eoi_exit_bitmap[2]);
+ vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);
+}
+
+static void vmx_apicv_post_state_restore(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ pi_clear_on(&vmx->pi_desc);
+ memset(vmx->pi_desc.pir, 0, sizeof(vmx->pi_desc.pir));
+}
+
+static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
+{
+ if (vmx->exit_reason != EXIT_REASON_EXCEPTION_NMI)
+ return;
+
+ vmx->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+ /* if exit due to PF check for async PF */
+ if (is_page_fault(vmx->exit_intr_info))
+ vmx->vcpu.arch.apf.host_apf_reason = kvm_read_and_reset_pf_reason();
+
+ /* Handle machine checks before interrupts are enabled */
+ if (is_machine_check(vmx->exit_intr_info))
+ kvm_machine_check();
+
+ /* We need to handle NMIs before interrupts are enabled */
+ if (is_nmi(vmx->exit_intr_info)) {
+ kvm_before_interrupt(&vmx->vcpu);
+ asm("int $2");
+ kvm_after_interrupt(&vmx->vcpu);
+ }
+}
+
+static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
+{
+ u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+ if ((exit_intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK))
+ == (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR)) {
+ unsigned int vector;
+ unsigned long entry;
+ gate_desc *desc;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+#ifdef CONFIG_X86_64
+ unsigned long tmp;
+#endif
+
+ vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
+ desc = (gate_desc *)vmx->host_idt_base + vector;
+ entry = gate_offset(desc);
+ asm volatile(
+#ifdef CONFIG_X86_64
+ "mov %%" _ASM_SP ", %[sp]\n\t"
+ "and $0xfffffffffffffff0, %%" _ASM_SP "\n\t"
+ "push $%c[ss]\n\t"
+ "push %[sp]\n\t"
+#endif
+ "pushf\n\t"
+ __ASM_SIZE(push) " $%c[cs]\n\t"
+ CALL_NOSPEC
+ :
+#ifdef CONFIG_X86_64
+ [sp]"=&r"(tmp),
+#endif
+ ASM_CALL_CONSTRAINT
+ :
+ THUNK_TARGET(entry),
+ [ss]"i"(__KERNEL_DS),
+ [cs]"i"(__KERNEL_CS)
+ );
+ }
+}
+STACK_FRAME_NON_STANDARD(vmx_handle_external_intr);
+
+static bool vmx_has_emulated_msr(int index)
+{
+ switch (index) {
+ case MSR_IA32_SMBASE:
+ /*
+ * We cannot do SMM unless we can run the guest in big
+ * real mode.
+ */
+ return enable_unrestricted_guest || emulate_invalid_guest_state;
+ case MSR_AMD64_VIRT_SPEC_CTRL:
+ /* This is AMD only. */
+ return false;
+ default:
+ return true;
+ }
+}
+
+static bool vmx_mpx_supported(void)
+{
+ return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_BNDCFGS) &&
+ (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS);
+}
+
+static bool vmx_xsaves_supported(void)
+{
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+ SECONDARY_EXEC_XSAVES;
+}
+
+static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
+{
+ u32 exit_intr_info;
+ bool unblock_nmi;
+ u8 vector;
+ bool idtv_info_valid;
+
+ idtv_info_valid = vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK;
+
+ if (enable_vnmi) {
+ if (vmx->loaded_vmcs->nmi_known_unmasked)
+ return;
+ /*
+ * Can't use vmx->exit_intr_info since we're not sure what
+ * the exit reason is.
+ */
+ exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+ unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
+ vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
+ /*
+ * SDM 3: 27.7.1.2 (September 2008)
+ * Re-set bit "block by NMI" before VM entry if vmexit caused by
+ * a guest IRET fault.
+ * SDM 3: 23.2.2 (September 2008)
+ * Bit 12 is undefined in any of the following cases:
+ * If the VM exit sets the valid bit in the IDT-vectoring
+ * information field.
+ * If the VM exit is due to a double fault.
+ */
+ if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
+ vector != DF_VECTOR && !idtv_info_valid)
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ else
+ vmx->loaded_vmcs->nmi_known_unmasked =
+ !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO)
+ & GUEST_INTR_STATE_NMI);
+ } else if (unlikely(vmx->loaded_vmcs->soft_vnmi_blocked))
+ vmx->loaded_vmcs->vnmi_blocked_time +=
+ ktime_to_ns(ktime_sub(ktime_get(),
+ vmx->loaded_vmcs->entry_time));
+}
+
+static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu,
+ u32 idt_vectoring_info,
+ int instr_len_field,
+ int error_code_field)
+{
+ u8 vector;
+ int type;
+ bool idtv_info_valid;
+
+ idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
+
+ vcpu->arch.nmi_injected = false;
+ kvm_clear_exception_queue(vcpu);
+ kvm_clear_interrupt_queue(vcpu);
+
+ if (!idtv_info_valid)
+ return;
+
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+
+ vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
+ type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
+
+ switch (type) {
+ case INTR_TYPE_NMI_INTR:
+ vcpu->arch.nmi_injected = true;
+ /*
+ * SDM 3: 27.7.1.2 (September 2008)
+ * Clear bit "block by NMI" before VM entry if a NMI
+ * delivery faulted.
+ */
+ vmx_set_nmi_mask(vcpu, false);
+ break;
+ case INTR_TYPE_SOFT_EXCEPTION:
+ vcpu->arch.event_exit_inst_len = vmcs_read32(instr_len_field);
+ /* fall through */
+ case INTR_TYPE_HARD_EXCEPTION:
+ if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
+ u32 err = vmcs_read32(error_code_field);
+ kvm_requeue_exception_e(vcpu, vector, err);
+ } else
+ kvm_requeue_exception(vcpu, vector);
+ break;
+ case INTR_TYPE_SOFT_INTR:
+ vcpu->arch.event_exit_inst_len = vmcs_read32(instr_len_field);
+ /* fall through */
+ case INTR_TYPE_EXT_INTR:
+ kvm_queue_interrupt(vcpu, vector, type == INTR_TYPE_SOFT_INTR);
+ break;
+ default:
+ break;
+ }
+}
+
+static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
+{
+ __vmx_complete_interrupts(&vmx->vcpu, vmx->idt_vectoring_info,
+ VM_EXIT_INSTRUCTION_LEN,
+ IDT_VECTORING_ERROR_CODE);
+}
+
+static void vmx_cancel_injection(struct kvm_vcpu *vcpu)
+{
+ __vmx_complete_interrupts(vcpu,
+ vmcs_read32(VM_ENTRY_INTR_INFO_FIELD),
+ VM_ENTRY_INSTRUCTION_LEN,
+ VM_ENTRY_EXCEPTION_ERROR_CODE);
+
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
+}
+
+static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
+{
+ int i, nr_msrs;
+ struct perf_guest_switch_msr *msrs;
+
+ msrs = perf_guest_get_msrs(&nr_msrs);
+
+ if (!msrs)
+ return;
+
+ for (i = 0; i < nr_msrs; i++)
+ if (msrs[i].host == msrs[i].guest)
+ clear_atomic_switch_msr(vmx, msrs[i].msr);
+ else
+ add_atomic_switch_msr(vmx, msrs[i].msr, msrs[i].guest,
+ msrs[i].host, false);
+}
+
+static void vmx_arm_hv_timer(struct vcpu_vmx *vmx, u32 val)
+{
+ vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, val);
+ if (!vmx->loaded_vmcs->hv_timer_armed)
+ vmcs_set_bits(PIN_BASED_VM_EXEC_CONTROL,
+ PIN_BASED_VMX_PREEMPTION_TIMER);
+ vmx->loaded_vmcs->hv_timer_armed = true;
+}
+
+static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u64 tscl;
+ u32 delta_tsc;
+
+ if (vmx->req_immediate_exit) {
+ vmx_arm_hv_timer(vmx, 0);
+ return;
+ }
+
+ if (vmx->hv_deadline_tsc != -1) {
+ tscl = rdtsc();
+ if (vmx->hv_deadline_tsc > tscl)
+ /* set_hv_timer ensures the delta fits in 32-bits */
+ delta_tsc = (u32)((vmx->hv_deadline_tsc - tscl) >>
+ cpu_preemption_timer_multi);
+ else
+ delta_tsc = 0;
+
+ vmx_arm_hv_timer(vmx, delta_tsc);
+ return;
+ }
+
+ if (vmx->loaded_vmcs->hv_timer_armed)
+ vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL,
+ PIN_BASED_VMX_PREEMPTION_TIMER);
+ vmx->loaded_vmcs->hv_timer_armed = false;
+}
+
+u64 __always_inline vmx_spec_ctrl_restore_host(struct vcpu_vmx *vmx)
+{
+ u64 guestval, hostval = this_cpu_read(x86_spec_ctrl_current);
+
+ if (!cpu_feature_enabled(X86_FEATURE_MSR_SPEC_CTRL))
+ return 0;
+
+ guestval = __rdmsr(MSR_IA32_SPEC_CTRL);
+
+ /*
+ *
+ * For legacy IBRS, the IBRS bit always needs to be written after
+ * transitioning from a less privileged predictor mode, regardless of
+ * whether the guest/host values differ.
+ */
+ if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) ||
+ guestval != hostval)
+ native_wrmsrl(MSR_IA32_SPEC_CTRL, hostval);
+
+ barrier_nospec();
+
+ return guestval;
+}
+
+static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ unsigned long cr3, cr4, evmcs_rsp;
+ u64 spec_ctrl;
+
+ /* Record the guest's net vcpu time for enforced NMI injections. */
+ if (unlikely(!enable_vnmi &&
+ vmx->loaded_vmcs->soft_vnmi_blocked))
+ vmx->loaded_vmcs->entry_time = ktime_get();
+
+ /* Don't enter VMX if guest state is invalid, let the exit handler
+ start emulation until we arrive back to a valid state */
+ if (vmx->emulation_required)
+ return;
+
+ if (vmx->ple_window_dirty) {
+ vmx->ple_window_dirty = false;
+ vmcs_write32(PLE_WINDOW, vmx->ple_window);
+ }
+
+ if (vmx->nested.sync_shadow_vmcs) {
+ copy_vmcs12_to_shadow(vmx);
+ vmx->nested.sync_shadow_vmcs = false;
+ }
+
+ if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
+ vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
+ if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
+ vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
+
+ cr3 = __get_current_cr3_fast();
+ if (unlikely(cr3 != vmx->loaded_vmcs->host_state.cr3)) {
+ vmcs_writel(HOST_CR3, cr3);
+ vmx->loaded_vmcs->host_state.cr3 = cr3;
+ }
+
+ cr4 = cr4_read_shadow();
+ if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) {
+ vmcs_writel(HOST_CR4, cr4);
+ vmx->loaded_vmcs->host_state.cr4 = cr4;
+ }
+
+ /* When single-stepping over STI and MOV SS, we must clear the
+ * corresponding interruptibility bits in the guest state. Otherwise
+ * vmentry fails as it then expects bit 14 (BS) in pending debug
+ * exceptions being set, but that's not correct for the guest debugging
+ * case. */
+ if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
+ vmx_set_interrupt_shadow(vcpu, 0);
+
+ kvm_load_guest_xcr0(vcpu);
+
+ if (static_cpu_has(X86_FEATURE_PKU) &&
+ kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
+ vcpu->arch.pkru != vmx->host_pkru)
+ __write_pkru(vcpu->arch.pkru);
+
+ atomic_switch_perf_msrs(vmx);
+
+ vmx_update_hv_timer(vcpu);
+
+ /*
+ * If this vCPU has touched SPEC_CTRL, restore the guest's value if
+ * it's non-zero. Since vmentry is serialising on affected CPUs, there
+ * is no need to worry about the conditional branch over the wrmsr
+ * being speculatively taken.
+ */
+ x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
+
+ vmx->__launched = vmx->loaded_vmcs->launched;
+
+ evmcs_rsp = static_branch_unlikely(&enable_evmcs) ?
+ (unsigned long)¤t_evmcs->host_rsp : 0;
+
+ /* L1D Flush includes CPU buffer clear to mitigate MDS */
+ if (static_branch_unlikely(&vmx_l1d_should_flush))
+ vmx_l1d_flush(vcpu);
+ else if (static_branch_unlikely(&mds_user_clear))
+ mds_clear_cpu_buffers();
+ else if (static_branch_unlikely(&mmio_stale_data_clear) &&
+ kvm_arch_has_assigned_device(vcpu->kvm))
+ mds_clear_cpu_buffers();
+
+ vmx_disable_fb_clear(vmx);
+
+ asm volatile (
+ /* Store host registers */
+ "push %%" _ASM_DX "; push %%" _ASM_BP ";"
+ "push %%" _ASM_CX " \n\t" /* placeholder for guest rcx */
+ "push %%" _ASM_CX " \n\t"
+ "cmp %%" _ASM_SP ", %c[host_rsp](%%" _ASM_CX ") \n\t"
+ "je 1f \n\t"
+ "mov %%" _ASM_SP ", %c[host_rsp](%%" _ASM_CX ") \n\t"
+ /* Avoid VMWRITE when Enlightened VMCS is in use */
+ "test %%" _ASM_SI ", %%" _ASM_SI " \n\t"
+ "jz 2f \n\t"
+ "mov %%" _ASM_SP ", (%%" _ASM_SI ") \n\t"
+ "jmp 1f \n\t"
+ "2: \n\t"
+ __ex(ASM_VMX_VMWRITE_RSP_RDX) "\n\t"
+ "1: \n\t"
+ /* Reload cr2 if changed */
+ "mov %c[cr2](%%" _ASM_CX "), %%" _ASM_AX " \n\t"
+ "mov %%cr2, %%" _ASM_DX " \n\t"
+ "cmp %%" _ASM_AX ", %%" _ASM_DX " \n\t"
+ "je 3f \n\t"
+ "mov %%" _ASM_AX", %%cr2 \n\t"
+ "3: \n\t"
+ /* Check if vmlaunch of vmresume is needed */
+ "cmpb $0, %c[launched](%%" _ASM_CX ") \n\t"
+ /* Load guest registers. Don't clobber flags. */
+ "mov %c[rax](%%" _ASM_CX "), %%" _ASM_AX " \n\t"
+ "mov %c[rbx](%%" _ASM_CX "), %%" _ASM_BX " \n\t"
+ "mov %c[rdx](%%" _ASM_CX "), %%" _ASM_DX " \n\t"
+ "mov %c[rsi](%%" _ASM_CX "), %%" _ASM_SI " \n\t"
+ "mov %c[rdi](%%" _ASM_CX "), %%" _ASM_DI " \n\t"
+ "mov %c[rbp](%%" _ASM_CX "), %%" _ASM_BP " \n\t"
+#ifdef CONFIG_X86_64
+ "mov %c[r8](%%" _ASM_CX "), %%r8 \n\t"
+ "mov %c[r9](%%" _ASM_CX "), %%r9 \n\t"
+ "mov %c[r10](%%" _ASM_CX "), %%r10 \n\t"
+ "mov %c[r11](%%" _ASM_CX "), %%r11 \n\t"
+ "mov %c[r12](%%" _ASM_CX "), %%r12 \n\t"
+ "mov %c[r13](%%" _ASM_CX "), %%r13 \n\t"
+ "mov %c[r14](%%" _ASM_CX "), %%r14 \n\t"
+ "mov %c[r15](%%" _ASM_CX "), %%r15 \n\t"
+#endif
+ /* Load guest RCX. This kills the vmx_vcpu pointer! */
+ "mov %c[rcx](%%" _ASM_CX "), %%" _ASM_CX " \n\t"
+
+ /* Enter guest mode */
+ "jne 1f \n\t"
+ __ex(ASM_VMX_VMLAUNCH) "\n\t"
+ "jmp 2f \n\t"
+ "1: " __ex(ASM_VMX_VMRESUME) "\n\t"
+ "2: "
+
+ /* Save guest's RCX to the stack placeholder (see above) */
+ "mov %%" _ASM_CX ", %c[wordsize](%%" _ASM_SP ") \n\t"
+
+ /* Load host's RCX, i.e. the vmx_vcpu pointer */
+ "pop %%" _ASM_CX " \n\t"
+
+ /* Set vmx->fail based on EFLAGS.{CF,ZF} */
+ "setbe %c[fail](%%" _ASM_CX ")\n\t"
+
+ /* Save all guest registers, including RCX from the stack */
+ "mov %%" _ASM_AX ", %c[rax](%%" _ASM_CX ") \n\t"
+ "mov %%" _ASM_BX ", %c[rbx](%%" _ASM_CX ") \n\t"
+ __ASM_SIZE(pop) " %c[rcx](%%" _ASM_CX ") \n\t"
+ "mov %%" _ASM_DX ", %c[rdx](%%" _ASM_CX ") \n\t"
+ "mov %%" _ASM_SI ", %c[rsi](%%" _ASM_CX ") \n\t"
+ "mov %%" _ASM_DI ", %c[rdi](%%" _ASM_CX ") \n\t"
+ "mov %%" _ASM_BP ", %c[rbp](%%" _ASM_CX ") \n\t"
+#ifdef CONFIG_X86_64
+ "mov %%r8, %c[r8](%%" _ASM_CX ") \n\t"
+ "mov %%r9, %c[r9](%%" _ASM_CX ") \n\t"
+ "mov %%r10, %c[r10](%%" _ASM_CX ") \n\t"
+ "mov %%r11, %c[r11](%%" _ASM_CX ") \n\t"
+ "mov %%r12, %c[r12](%%" _ASM_CX ") \n\t"
+ "mov %%r13, %c[r13](%%" _ASM_CX ") \n\t"
+ "mov %%r14, %c[r14](%%" _ASM_CX ") \n\t"
+ "mov %%r15, %c[r15](%%" _ASM_CX ") \n\t"
+
+ /*
+ * Clear all general purpose registers (except RSP, which is loaded by
+ * the CPU during VM-Exit) to prevent speculative use of the guest's
+ * values, even those that are saved/loaded via the stack. In theory,
+ * an L1 cache miss when restoring registers could lead to speculative
+ * execution with the guest's values. Zeroing XORs are dirt cheap,
+ * i.e. the extra paranoia is essentially free.
+ */
+ "xor %%r8d, %%r8d \n\t"
+ "xor %%r9d, %%r9d \n\t"
+ "xor %%r10d, %%r10d \n\t"
+ "xor %%r11d, %%r11d \n\t"
+ "xor %%r12d, %%r12d \n\t"
+ "xor %%r13d, %%r13d \n\t"
+ "xor %%r14d, %%r14d \n\t"
+ "xor %%r15d, %%r15d \n\t"
+#endif
+ "mov %%cr2, %%" _ASM_AX " \n\t"
+ "mov %%" _ASM_AX ", %c[cr2](%%" _ASM_CX ") \n\t"
+
+ "xor %%eax, %%eax \n\t"
+ "xor %%ebx, %%ebx \n\t"
+ "xor %%ecx, %%ecx \n\t"
+ "xor %%edx, %%edx \n\t"
+ "xor %%esi, %%esi \n\t"
+ "xor %%edi, %%edi \n\t"
+ "xor %%ebp, %%ebp \n\t"
+ "pop %%" _ASM_BP "; pop %%" _ASM_DX " \n\t"
+ ".pushsection .rodata \n\t"
+ ".global vmx_return \n\t"
+ "vmx_return: " _ASM_PTR " 2b \n\t"
+ ".popsection"
+ : "=c"((int){0}), "=d"((int){0}), "=S"((int){0})
+ : "c"(vmx), "d"((unsigned long)HOST_RSP), "S"(evmcs_rsp),
+ [launched]"i"(offsetof(struct vcpu_vmx, __launched)),
+ [fail]"i"(offsetof(struct vcpu_vmx, fail)),
+ [host_rsp]"i"(offsetof(struct vcpu_vmx, host_rsp)),
+ [rax]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RAX])),
+ [rbx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBX])),
+ [rcx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RCX])),
+ [rdx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RDX])),
+ [rsi]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RSI])),
+ [rdi]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RDI])),
+ [rbp]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBP])),
+#ifdef CONFIG_X86_64
+ [r8]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R8])),
+ [r9]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R9])),
+ [r10]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R10])),
+ [r11]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R11])),
+ [r12]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R12])),
+ [r13]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R13])),
+ [r14]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R14])),
+ [r15]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R15])),
+#endif
+ [cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2)),
+ [wordsize]"i"(sizeof(ulong))
+ : "cc", "memory"
+#ifdef CONFIG_X86_64
+ , "rax", "rbx", "rdi"
+ , "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+#else
+ , "eax", "ebx", "edi"
+#endif
+ );
+
+ /*
+ * IMPORTANT: RSB filling and SPEC_CTRL handling must be done before
+ * the first unbalanced RET after vmexit!
+ *
+ * For retpoline or IBRS, RSB filling is needed to prevent poisoned RSB
+ * entries and (in some cases) RSB underflow.
+ *
+ * eIBRS has its own protection against poisoned RSB, so it doesn't
+ * need the RSB filling sequence. But it does need to be enabled, and a
+ * single call to retire, before the first unbalanced RET.
+ *
+ * So no RETs before vmx_spec_ctrl_restore_host() below.
+ */
+ vmexit_fill_RSB();
+
+ /* Save this for below */
+ spec_ctrl = vmx_spec_ctrl_restore_host(vmx);
+
+ vmx_enable_fb_clear(vmx);
+
+ /*
+ * We do not use IBRS in the kernel. If this vCPU has used the
+ * SPEC_CTRL MSR it may have left it on; save the value and
+ * turn it off. This is much more efficient than blindly adding
+ * it to the atomic save/restore list. Especially as the former
+ * (Saving guest MSRs on vmexit) doesn't even exist in KVM.
+ *
+ * For non-nested case:
+ * If the L01 MSR bitmap does not intercept the MSR, then we need to
+ * save it.
+ *
+ * For nested case:
+ * If the L02 MSR bitmap does not intercept the MSR, then we need to
+ * save it.
+ */
+ if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
+ vmx->spec_ctrl = spec_ctrl;
+
+ /* All fields are clean at this point */
+ if (static_branch_unlikely(&enable_evmcs))
+ current_evmcs->hv_clean_fields |=
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL;
+
+ /* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */
+ if (vmx->host_debugctlmsr)
+ update_debugctlmsr(vmx->host_debugctlmsr);
+
+#ifndef CONFIG_X86_64
+ /*
+ * The sysexit path does not restore ds/es, so we must set them to
+ * a reasonable value ourselves.
+ *
+ * We can't defer this to vmx_prepare_switch_to_host() since that
+ * function may be executed in interrupt context, which saves and
+ * restore segments around it, nullifying its effect.
+ */
+ loadsegment(ds, __USER_DS);
+ loadsegment(es, __USER_DS);
+#endif
+
+ vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)
+ | (1 << VCPU_EXREG_RFLAGS)
+ | (1 << VCPU_EXREG_PDPTR)
+ | (1 << VCPU_EXREG_SEGMENTS)
+ | (1 << VCPU_EXREG_CR3));
+ vcpu->arch.regs_dirty = 0;
+
+ /*
+ * eager fpu is enabled if PKEY is supported and CR4 is switched
+ * back on host, so it is safe to read guest PKRU from current
+ * XSAVE.
+ */
+ if (static_cpu_has(X86_FEATURE_PKU) &&
+ kvm_read_cr4_bits(vcpu, X86_CR4_PKE)) {
+ vcpu->arch.pkru = __read_pkru();
+ if (vcpu->arch.pkru != vmx->host_pkru)
+ __write_pkru(vmx->host_pkru);
+ }
+
+ kvm_put_guest_xcr0(vcpu);
+
+ vmx->nested.nested_run_pending = 0;
+ vmx->idt_vectoring_info = 0;
+
+ vmx->exit_reason = vmx->fail ? 0xdead : vmcs_read32(VM_EXIT_REASON);
+ if ((u16)vmx->exit_reason == EXIT_REASON_MCE_DURING_VMENTRY)
+ kvm_machine_check();
+
+ if (vmx->fail || (vmx->exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY))
+ return;
+
+ vmx->loaded_vmcs->launched = 1;
+ vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
+
+ vmx_complete_atomic_exit(vmx);
+ vmx_recover_nmi_blocking(vmx);
+ vmx_complete_interrupts(vmx);
+}
+STACK_FRAME_NON_STANDARD(vmx_vcpu_run);
+
+static struct kvm *vmx_vm_alloc(void)
+{
+ struct kvm_vmx *kvm_vmx = vzalloc(sizeof(struct kvm_vmx));
+
+ if (!kvm_vmx)
+ return NULL;
+
+ return &kvm_vmx->kvm;
+}
+
+static void vmx_vm_free(struct kvm *kvm)
+{
+ vfree(to_kvm_vmx(kvm));
+}
+
+static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int cpu;
+
+ if (vmx->loaded_vmcs == vmcs)
+ return;
+
+ cpu = get_cpu();
+ vmx_vcpu_put(vcpu);
+ vmx->loaded_vmcs = vmcs;
+ vmx_vcpu_load(vcpu, cpu);
+ put_cpu();
+}
+
+/*
+ * Ensure that the current vmcs of the logical processor is the
+ * vmcs01 of the vcpu before calling free_nested().
+ */
+static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ vcpu_load(vcpu);
+ vmx_switch_vmcs(vcpu, &vmx->vmcs01);
+ free_nested(vmx);
+ vcpu_put(vcpu);
+}
+
+static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (enable_pml)
+ vmx_destroy_pml_buffer(vmx);
+ free_vpid(vmx->vpid);
+ leave_guest_mode(vcpu);
+ vmx_free_vcpu_nested(vcpu);
+ free_loaded_vmcs(vmx->loaded_vmcs);
+ kfree(vmx->guest_msrs);
+ kvm_vcpu_uninit(vcpu);
+ kmem_cache_free(kvm_vcpu_cache, vmx);
+}
+
+static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
+{
+ int err;
+ struct vcpu_vmx *vmx = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
+ unsigned long *msr_bitmap;
+ int cpu;
+
+ if (!vmx)
+ return ERR_PTR(-ENOMEM);
+
+ vmx->vpid = allocate_vpid();
+
+ err = kvm_vcpu_init(&vmx->vcpu, kvm, id);
+ if (err)
+ goto free_vcpu;
+
+ err = -ENOMEM;
+
+ /*
+ * If PML is turned on, failure on enabling PML just results in failure
+ * of creating the vcpu, therefore we can simplify PML logic (by
+ * avoiding dealing with cases, such as enabling PML partially on vcpus
+ * for the guest, etc.
+ */
+ if (enable_pml) {
+ vmx->pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!vmx->pml_pg)
+ goto uninit_vcpu;
+ }
+
+ vmx->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ BUILD_BUG_ON(ARRAY_SIZE(vmx_msr_index) * sizeof(vmx->guest_msrs[0])
+ > PAGE_SIZE);
+
+ if (!vmx->guest_msrs)
+ goto free_pml;
+
+ err = alloc_loaded_vmcs(&vmx->vmcs01);
+ if (err < 0)
+ goto free_msrs;
+
+ msr_bitmap = vmx->vmcs01.msr_bitmap;
+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_FS_BASE, MSR_TYPE_RW);
+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_GS_BASE, MSR_TYPE_RW);
+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_KERNEL_GS_BASE, MSR_TYPE_RW);
+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_CS, MSR_TYPE_RW);
+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_ESP, MSR_TYPE_RW);
+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_EIP, MSR_TYPE_RW);
+ vmx->msr_bitmap_mode = 0;
+
+ vmx->loaded_vmcs = &vmx->vmcs01;
+ cpu = get_cpu();
+ vmx_vcpu_load(&vmx->vcpu, cpu);
+ vmx->vcpu.cpu = cpu;
+ vmx_vcpu_setup(vmx);
+ vmx_vcpu_put(&vmx->vcpu);
+ put_cpu();
+ if (cpu_need_virtualize_apic_accesses(&vmx->vcpu)) {
+ err = alloc_apic_access_page(kvm);
+ if (err)
+ goto free_vmcs;
+ }
+
+ if (enable_ept && !enable_unrestricted_guest) {
+ err = init_rmode_identity_map(kvm);
+ if (err)
+ goto free_vmcs;
+ }
+
+ if (nested)
+ nested_vmx_setup_ctls_msrs(&vmx->nested.msrs,
+ kvm_vcpu_apicv_active(&vmx->vcpu));
+
+ vmx->nested.posted_intr_nv = -1;
+ vmx->nested.current_vmptr = -1ull;
+
+ vmx->msr_ia32_feature_control_valid_bits = FEATURE_CONTROL_LOCKED;
+
+ /*
+ * Enforce invariant: pi_desc.nv is always either POSTED_INTR_VECTOR
+ * or POSTED_INTR_WAKEUP_VECTOR.
+ */
+ vmx->pi_desc.nv = POSTED_INTR_VECTOR;
+ vmx->pi_desc.sn = 1;
+
+ return &vmx->vcpu;
+
+free_vmcs:
+ free_loaded_vmcs(vmx->loaded_vmcs);
+free_msrs:
+ kfree(vmx->guest_msrs);
+free_pml:
+ vmx_destroy_pml_buffer(vmx);
+uninit_vcpu:
+ kvm_vcpu_uninit(&vmx->vcpu);
+free_vcpu:
+ free_vpid(vmx->vpid);
+ kmem_cache_free(kvm_vcpu_cache, vmx);
+ return ERR_PTR(err);
+}
+
+#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n"
+#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/l1tf.html for details.\n"
+
+static int vmx_vm_init(struct kvm *kvm)
+{
+ spin_lock_init(&to_kvm_vmx(kvm)->ept_pointer_lock);
+
+ if (!ple_gap)
+ kvm->arch.pause_in_guest = true;
+
+ if (boot_cpu_has(X86_BUG_L1TF) && enable_ept) {
+ switch (l1tf_mitigation) {
+ case L1TF_MITIGATION_OFF:
+ case L1TF_MITIGATION_FLUSH_NOWARN:
+ /* 'I explicitly don't care' is set */
+ break;
+ case L1TF_MITIGATION_FLUSH:
+ case L1TF_MITIGATION_FLUSH_NOSMT:
+ case L1TF_MITIGATION_FULL:
+ /*
+ * Warn upon starting the first VM in a potentially
+ * insecure environment.
+ */
+ if (sched_smt_active())
+ pr_warn_once(L1TF_MSG_SMT);
+ if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER)
+ pr_warn_once(L1TF_MSG_L1D);
+ break;
+ case L1TF_MITIGATION_FULL_FORCE:
+ /* Flush is enforced */
+ break;
+ }
+ }
+ return 0;
+}
+
+static void __init vmx_check_processor_compat(void *rtn)
+{
+ struct vmcs_config vmcs_conf;
+
+ *(int *)rtn = 0;
+ if (setup_vmcs_config(&vmcs_conf) < 0)
+ *(int *)rtn = -EIO;
+ nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, enable_apicv);
+ if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) {
+ printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n",
+ smp_processor_id());
+ *(int *)rtn = -EIO;
+ }
+}
+
+static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
+{
+ u8 cache;
+ u64 ipat = 0;
+
+ /* For VT-d and EPT combination
+ * 1. MMIO: always map as UC
+ * 2. EPT with VT-d:
+ * a. VT-d without snooping control feature: can't guarantee the
+ * result, try to trust guest.
+ * b. VT-d with snooping control feature: snooping control feature of
+ * VT-d engine can guarantee the cache correctness. Just set it
+ * to WB to keep consistent with host. So the same as item 3.
+ * 3. EPT without VT-d: always map as WB and set IPAT=1 to keep
+ * consistent with host MTRR
+ */
+ if (is_mmio) {
+ cache = MTRR_TYPE_UNCACHABLE;
+ goto exit;
+ }
+
+ if (!kvm_arch_has_noncoherent_dma(vcpu->kvm)) {
+ ipat = VMX_EPT_IPAT_BIT;
+ cache = MTRR_TYPE_WRBACK;
+ goto exit;
+ }
+
+ if (kvm_read_cr0(vcpu) & X86_CR0_CD) {
+ ipat = VMX_EPT_IPAT_BIT;
+ if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
+ cache = MTRR_TYPE_WRBACK;
+ else
+ cache = MTRR_TYPE_UNCACHABLE;
+ goto exit;
+ }
+
+ cache = kvm_mtrr_get_guest_memory_type(vcpu, gfn);
+
+exit:
+ return (cache << VMX_EPT_MT_EPTE_SHIFT) | ipat;
+}
+
+static int vmx_get_lpage_level(void)
+{
+ if (enable_ept && !cpu_has_vmx_ept_1g_page())
+ return PT_DIRECTORY_LEVEL;
+ else
+ /* For shadow and EPT supported 1GB page */
+ return PT_PDPE_LEVEL;
+}
+
+static void vmcs_set_secondary_exec_control(u32 new_ctl)
+{
+ /*
+ * These bits in the secondary execution controls field
+ * are dynamic, the others are mostly based on the hypervisor
+ * architecture and the guest's CPUID. Do not touch the
+ * dynamic bits.
+ */
+ u32 mask =
+ SECONDARY_EXEC_SHADOW_VMCS |
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+ SECONDARY_EXEC_DESC;
+
+ u32 cur_ctl = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
+ (new_ctl & ~mask) | (cur_ctl & mask));
+}
+
+/*
+ * Generate MSR_IA32_VMX_CR{0,4}_FIXED1 according to CPUID. Only set bits
+ * (indicating "allowed-1") if they are supported in the guest's CPUID.
+ */
+static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct kvm_cpuid_entry2 *entry;
+
+ vmx->nested.msrs.cr0_fixed1 = 0xffffffff;
+ vmx->nested.msrs.cr4_fixed1 = X86_CR4_PCE;
+
+#define cr4_fixed1_update(_cr4_mask, _reg, _cpuid_mask) do { \
+ if (entry && (entry->_reg & (_cpuid_mask))) \
+ vmx->nested.msrs.cr4_fixed1 |= (_cr4_mask); \
+} while (0)
+
+ entry = kvm_find_cpuid_entry(vcpu, 0x1, 0);
+ cr4_fixed1_update(X86_CR4_VME, edx, bit(X86_FEATURE_VME));
+ cr4_fixed1_update(X86_CR4_PVI, edx, bit(X86_FEATURE_VME));
+ cr4_fixed1_update(X86_CR4_TSD, edx, bit(X86_FEATURE_TSC));
+ cr4_fixed1_update(X86_CR4_DE, edx, bit(X86_FEATURE_DE));
+ cr4_fixed1_update(X86_CR4_PSE, edx, bit(X86_FEATURE_PSE));
+ cr4_fixed1_update(X86_CR4_PAE, edx, bit(X86_FEATURE_PAE));
+ cr4_fixed1_update(X86_CR4_MCE, edx, bit(X86_FEATURE_MCE));
+ cr4_fixed1_update(X86_CR4_PGE, edx, bit(X86_FEATURE_PGE));
+ cr4_fixed1_update(X86_CR4_OSFXSR, edx, bit(X86_FEATURE_FXSR));
+ cr4_fixed1_update(X86_CR4_OSXMMEXCPT, edx, bit(X86_FEATURE_XMM));
+ cr4_fixed1_update(X86_CR4_VMXE, ecx, bit(X86_FEATURE_VMX));
+ cr4_fixed1_update(X86_CR4_SMXE, ecx, bit(X86_FEATURE_SMX));
+ cr4_fixed1_update(X86_CR4_PCIDE, ecx, bit(X86_FEATURE_PCID));
+ cr4_fixed1_update(X86_CR4_OSXSAVE, ecx, bit(X86_FEATURE_XSAVE));
+
+ entry = kvm_find_cpuid_entry(vcpu, 0x7, 0);
+ cr4_fixed1_update(X86_CR4_FSGSBASE, ebx, bit(X86_FEATURE_FSGSBASE));
+ cr4_fixed1_update(X86_CR4_SMEP, ebx, bit(X86_FEATURE_SMEP));
+ cr4_fixed1_update(X86_CR4_SMAP, ebx, bit(X86_FEATURE_SMAP));
+ cr4_fixed1_update(X86_CR4_PKE, ecx, bit(X86_FEATURE_PKU));
+ cr4_fixed1_update(X86_CR4_UMIP, ecx, bit(X86_FEATURE_UMIP));
+
+#undef cr4_fixed1_update
+}
+
+static void nested_vmx_entry_exit_ctls_update(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (kvm_mpx_supported()) {
+ bool mpx_enabled = guest_cpuid_has(vcpu, X86_FEATURE_MPX);
+
+ if (mpx_enabled) {
+ vmx->nested.msrs.entry_ctls_high |= VM_ENTRY_LOAD_BNDCFGS;
+ vmx->nested.msrs.exit_ctls_high |= VM_EXIT_CLEAR_BNDCFGS;
+ } else {
+ vmx->nested.msrs.entry_ctls_high &= ~VM_ENTRY_LOAD_BNDCFGS;
+ vmx->nested.msrs.exit_ctls_high &= ~VM_EXIT_CLEAR_BNDCFGS;
+ }
+ }
+}
+
+static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (cpu_has_secondary_exec_ctrls()) {
+ vmx_compute_secondary_exec_control(vmx);
+ vmcs_set_secondary_exec_control(vmx->secondary_exec_control);
+ }
+
+ if (nested_vmx_allowed(vcpu))
+ to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
+ FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
+ else
+ to_vmx(vcpu)->msr_ia32_feature_control_valid_bits &=
+ ~FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
+
+ if (nested_vmx_allowed(vcpu)) {
+ nested_vmx_cr_fixed1_bits_update(vcpu);
+ nested_vmx_entry_exit_ctls_update(vcpu);
+ }
+}
+
+static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
+{
+ if (func == 1 && nested)
+ entry->ecx |= bit(X86_FEATURE_VMX);
+}
+
+static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
+ struct x86_exception *fault)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 exit_reason;
+ unsigned long exit_qualification = vcpu->arch.exit_qualification;
+
+ if (vmx->nested.pml_full) {
+ exit_reason = EXIT_REASON_PML_FULL;
+ vmx->nested.pml_full = false;
+ exit_qualification &= INTR_INFO_UNBLOCK_NMI;
+ } else if (fault->error_code & PFERR_RSVD_MASK)
+ exit_reason = EXIT_REASON_EPT_MISCONFIG;
+ else
+ exit_reason = EXIT_REASON_EPT_VIOLATION;
+
+ nested_vmx_vmexit(vcpu, exit_reason, 0, exit_qualification);
+ vmcs12->guest_physical_address = fault->address;
+}
+
+static bool nested_ept_ad_enabled(struct kvm_vcpu *vcpu)
+{
+ return nested_ept_get_cr3(vcpu) & VMX_EPTP_AD_ENABLE_BIT;
+}
+
+/* Callbacks for nested_ept_init_mmu_context: */
+
+static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu)
+{
+ /* return the page table to be shadowed - in our case, EPT12 */
+ return get_vmcs12(vcpu)->ept_pointer;
+}
+
+static int nested_ept_init_mmu_context(struct kvm_vcpu *vcpu)
+{
+ WARN_ON(mmu_is_nested(vcpu));
+ if (!valid_ept_address(vcpu, nested_ept_get_cr3(vcpu)))
+ return 1;
+
+ kvm_init_shadow_ept_mmu(vcpu,
+ to_vmx(vcpu)->nested.msrs.ept_caps &
+ VMX_EPT_EXECUTE_ONLY_BIT,
+ nested_ept_ad_enabled(vcpu),
+ nested_ept_get_cr3(vcpu));
+ vcpu->arch.mmu.set_cr3 = vmx_set_cr3;
+ vcpu->arch.mmu.get_cr3 = nested_ept_get_cr3;
+ vcpu->arch.mmu.inject_page_fault = nested_ept_inject_page_fault;
+
+ vcpu->arch.walk_mmu = &vcpu->arch.nested_mmu;
+ return 0;
+}
+
+static void nested_ept_uninit_mmu_context(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.walk_mmu = &vcpu->arch.mmu;
+}
+
+static bool nested_vmx_is_page_fault_vmexit(struct vmcs12 *vmcs12,
+ u16 error_code)
+{
+ bool inequality, bit;
+
+ bit = (vmcs12->exception_bitmap & (1u << PF_VECTOR)) != 0;
+ inequality =
+ (error_code & vmcs12->page_fault_error_code_mask) !=
+ vmcs12->page_fault_error_code_match;
+ return inequality ^ bit;
+}
+
+static void vmx_inject_page_fault_nested(struct kvm_vcpu *vcpu,
+ struct x86_exception *fault)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+ WARN_ON(!is_guest_mode(vcpu));
+
+ if (nested_vmx_is_page_fault_vmexit(vmcs12, fault->error_code) &&
+ !to_vmx(vcpu)->nested.nested_run_pending) {
+ vmcs12->vm_exit_intr_error_code = fault->error_code;
+ nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
+ PF_VECTOR | INTR_TYPE_HARD_EXCEPTION |
+ INTR_INFO_DELIVER_CODE_MASK | INTR_INFO_VALID_MASK,
+ fault->address);
+ } else {
+ kvm_inject_page_fault(vcpu, fault);
+ }
+}
+
+static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12);
+
+static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct page *page;
+ u64 hpa;
+
+ if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
+ /*
+ * Translate L1 physical address to host physical
+ * address for vmcs02. Keep the page pinned, so this
+ * physical address remains valid. We keep a reference
+ * to it so we can release it later.
+ */
+ if (vmx->nested.apic_access_page) { /* shouldn't happen */
+ kvm_release_page_dirty(vmx->nested.apic_access_page);
+ vmx->nested.apic_access_page = NULL;
+ }
+ page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->apic_access_addr);
+ /*
+ * If translation failed, no matter: This feature asks
+ * to exit when accessing the given address, and if it
+ * can never be accessed, this feature won't do
+ * anything anyway.
+ */
+ if (!is_error_page(page)) {
+ vmx->nested.apic_access_page = page;
+ hpa = page_to_phys(vmx->nested.apic_access_page);
+ vmcs_write64(APIC_ACCESS_ADDR, hpa);
+ } else {
+ vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
+ }
+ }
+
+ if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
+ if (vmx->nested.virtual_apic_page) { /* shouldn't happen */
+ kvm_release_page_dirty(vmx->nested.virtual_apic_page);
+ vmx->nested.virtual_apic_page = NULL;
+ }
+ page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->virtual_apic_page_addr);
+
+ /*
+ * If translation failed, VM entry will fail because
+ * prepare_vmcs02 set VIRTUAL_APIC_PAGE_ADDR to -1ull.
+ * Failing the vm entry is _not_ what the processor
+ * does but it's basically the only possibility we
+ * have. We could still enter the guest if CR8 load
+ * exits are enabled, CR8 store exits are enabled, and
+ * virtualize APIC access is disabled; in this case
+ * the processor would never use the TPR shadow and we
+ * could simply clear the bit from the execution
+ * control. But such a configuration is useless, so
+ * let's keep the code simple.
+ */
+ if (!is_error_page(page)) {
+ vmx->nested.virtual_apic_page = page;
+ hpa = page_to_phys(vmx->nested.virtual_apic_page);
+ vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, hpa);
+ }
+ }
+
+ if (nested_cpu_has_posted_intr(vmcs12)) {
+ if (vmx->nested.pi_desc_page) { /* shouldn't happen */
+ kunmap(vmx->nested.pi_desc_page);
+ kvm_release_page_dirty(vmx->nested.pi_desc_page);
+ vmx->nested.pi_desc_page = NULL;
+ vmx->nested.pi_desc = NULL;
+ vmcs_write64(POSTED_INTR_DESC_ADDR, -1ull);
+ }
+ page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->posted_intr_desc_addr);
+ if (is_error_page(page))
+ return;
+ vmx->nested.pi_desc_page = page;
+ vmx->nested.pi_desc = kmap(vmx->nested.pi_desc_page);
+ vmx->nested.pi_desc =
+ (struct pi_desc *)((void *)vmx->nested.pi_desc +
+ (unsigned long)(vmcs12->posted_intr_desc_addr &
+ (PAGE_SIZE - 1)));
+ vmcs_write64(POSTED_INTR_DESC_ADDR,
+ page_to_phys(vmx->nested.pi_desc_page) +
+ (unsigned long)(vmcs12->posted_intr_desc_addr &
+ (PAGE_SIZE - 1)));
+ }
+ if (nested_vmx_prepare_msr_bitmap(vcpu, vmcs12))
+ vmcs_set_bits(CPU_BASED_VM_EXEC_CONTROL,
+ CPU_BASED_USE_MSR_BITMAPS);
+ else
+ vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
+ CPU_BASED_USE_MSR_BITMAPS);
+}
+
+static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu)
+{
+ u64 preemption_timeout = get_vmcs12(vcpu)->vmx_preemption_timer_value;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ /*
+ * A timer value of zero is architecturally guaranteed to cause
+ * a VMExit prior to executing any instructions in the guest.
+ */
+ if (preemption_timeout == 0) {
+ vmx_preemption_timer_fn(&vmx->nested.preemption_timer);
+ return;
+ }
+
+ if (vcpu->arch.virtual_tsc_khz == 0)
+ return;
+
+ preemption_timeout <<= VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE;
+ preemption_timeout *= 1000000;
+ do_div(preemption_timeout, vcpu->arch.virtual_tsc_khz);
+ hrtimer_start(&vmx->nested.preemption_timer,
+ ns_to_ktime(preemption_timeout), HRTIMER_MODE_REL);
+}
+
+static int nested_vmx_check_io_bitmap_controls(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ return 0;
+
+ if (!page_address_valid(vcpu, vmcs12->io_bitmap_a) ||
+ !page_address_valid(vcpu, vmcs12->io_bitmap_b))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int nested_vmx_check_msr_bitmap_controls(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_MSR_BITMAPS))
+ return 0;
+
+ if (!page_address_valid(vcpu, vmcs12->msr_bitmap))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int nested_vmx_check_tpr_shadow_controls(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ if (!nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
+ return 0;
+
+ if (!page_address_valid(vcpu, vmcs12->virtual_apic_page_addr))
+ return -EINVAL;
+
+ return 0;
+}
+
+static inline void enable_x2apic_msr_intercepts(unsigned long *msr_bitmap) {
+ int msr;
+
+ for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
+ unsigned word = msr / BITS_PER_LONG;
+
+ msr_bitmap[word] = ~0;
+ msr_bitmap[word + (0x800 / sizeof(long))] = ~0;
+ }
+}
+
+/*
+ * Merge L0's and L1's MSR bitmap, return false to indicate that
+ * we do not use the hardware.
+ */
+static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ int msr;
+ struct page *page;
+ unsigned long *msr_bitmap_l1;
+ unsigned long *msr_bitmap_l0 = to_vmx(vcpu)->nested.vmcs02.msr_bitmap;
+ /*
+ * pred_cmd & spec_ctrl are trying to verify two things:
+ *
+ * 1. L0 gave a permission to L1 to actually passthrough the MSR. This
+ * ensures that we do not accidentally generate an L02 MSR bitmap
+ * from the L12 MSR bitmap that is too permissive.
+ * 2. That L1 or L2s have actually used the MSR. This avoids
+ * unnecessarily merging of the bitmap if the MSR is unused. This
+ * works properly because we only update the L01 MSR bitmap lazily.
+ * So even if L0 should pass L1 these MSRs, the L01 bitmap is only
+ * updated to reflect this when L1 (or its L2s) actually write to
+ * the MSR.
+ */
+ bool pred_cmd = !msr_write_intercepted_l01(vcpu, MSR_IA32_PRED_CMD);
+ bool spec_ctrl = !msr_write_intercepted_l01(vcpu, MSR_IA32_SPEC_CTRL);
+
+ /* Nothing to do if the MSR bitmap is not in use. */
+ if (!cpu_has_vmx_msr_bitmap() ||
+ !nested_cpu_has(vmcs12, CPU_BASED_USE_MSR_BITMAPS))
+ return false;
+
+ if (!nested_cpu_has_virt_x2apic_mode(vmcs12) &&
+ !pred_cmd && !spec_ctrl)
+ return false;
+
+ page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->msr_bitmap);
+ if (is_error_page(page))
+ return false;
+
+ msr_bitmap_l1 = (unsigned long *)kmap(page);
+
+ /*
+ * To keep the control flow simple, pay eight 8-byte writes (sixteen
+ * 4-byte writes on 32-bit systems) up front to enable intercepts for
+ * the x2APIC MSR range and selectively disable them below.
+ */
+ enable_x2apic_msr_intercepts(msr_bitmap_l0);
+
+ if (nested_cpu_has_virt_x2apic_mode(vmcs12)) {
+ if (nested_cpu_has_apic_reg_virt(vmcs12)) {
+ /*
+ * L0 need not intercept reads for MSRs between 0x800
+ * and 0x8ff, it just lets the processor take the value
+ * from the virtual-APIC page; take those 256 bits
+ * directly from the L1 bitmap.
+ */
+ for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
+ unsigned word = msr / BITS_PER_LONG;
+
+ msr_bitmap_l0[word] = msr_bitmap_l1[word];
+ }
+ }
+
+ nested_vmx_disable_intercept_for_msr(
+ msr_bitmap_l1, msr_bitmap_l0,
+ X2APIC_MSR(APIC_TASKPRI),
+ MSR_TYPE_R | MSR_TYPE_W);
+
+ if (nested_cpu_has_vid(vmcs12)) {
+ nested_vmx_disable_intercept_for_msr(
+ msr_bitmap_l1, msr_bitmap_l0,
+ X2APIC_MSR(APIC_EOI),
+ MSR_TYPE_W);
+ nested_vmx_disable_intercept_for_msr(
+ msr_bitmap_l1, msr_bitmap_l0,
+ X2APIC_MSR(APIC_SELF_IPI),
+ MSR_TYPE_W);
+ }
+ }
+
+ if (spec_ctrl)
+ nested_vmx_disable_intercept_for_msr(
+ msr_bitmap_l1, msr_bitmap_l0,
+ MSR_IA32_SPEC_CTRL,
+ MSR_TYPE_R | MSR_TYPE_W);
+
+ if (pred_cmd)
+ nested_vmx_disable_intercept_for_msr(
+ msr_bitmap_l1, msr_bitmap_l0,
+ MSR_IA32_PRED_CMD,
+ MSR_TYPE_W);
+
+ kunmap(page);
+ kvm_release_page_clean(page);
+
+ return true;
+}
+
+static void nested_cache_shadow_vmcs12(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ struct vmcs12 *shadow;
+ struct page *page;
+
+ if (!nested_cpu_has_shadow_vmcs(vmcs12) ||
+ vmcs12->vmcs_link_pointer == -1ull)
+ return;
+
+ shadow = get_shadow_vmcs12(vcpu);
+ page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->vmcs_link_pointer);
+
+ memcpy(shadow, kmap(page), VMCS12_SIZE);
+
+ kunmap(page);
+ kvm_release_page_clean(page);
+}
+
+static void nested_flush_cached_shadow_vmcs12(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (!nested_cpu_has_shadow_vmcs(vmcs12) ||
+ vmcs12->vmcs_link_pointer == -1ull)
+ return;
+
+ kvm_write_guest(vmx->vcpu.kvm, vmcs12->vmcs_link_pointer,
+ get_shadow_vmcs12(vcpu), VMCS12_SIZE);
+}
+
+static int nested_vmx_check_apic_access_controls(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) &&
+ !page_address_valid(vcpu, vmcs12->apic_access_addr))
+ return -EINVAL;
+ else
+ return 0;
+}
+
+static int nested_vmx_check_apicv_controls(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ if (!nested_cpu_has_virt_x2apic_mode(vmcs12) &&
+ !nested_cpu_has_apic_reg_virt(vmcs12) &&
+ !nested_cpu_has_vid(vmcs12) &&
+ !nested_cpu_has_posted_intr(vmcs12))
+ return 0;
+
+ /*
+ * If virtualize x2apic mode is enabled,
+ * virtualize apic access must be disabled.
+ */
+ if (nested_cpu_has_virt_x2apic_mode(vmcs12) &&
+ nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
+ return -EINVAL;
+
+ /*
+ * If virtual interrupt delivery is enabled,
+ * we must exit on external interrupts.
+ */
+ if (nested_cpu_has_vid(vmcs12) &&
+ !nested_exit_on_intr(vcpu))
+ return -EINVAL;
+
+ /*
+ * bits 15:8 should be zero in posted_intr_nv,
+ * the descriptor address has been already checked
+ * in nested_get_vmcs12_pages.
+ *
+ * bits 5:0 of posted_intr_desc_addr should be zero.
+ */
+ if (nested_cpu_has_posted_intr(vmcs12) &&
+ (!nested_cpu_has_vid(vmcs12) ||
+ !nested_exit_intr_ack_set(vcpu) ||
+ (vmcs12->posted_intr_nv & 0xff00) ||
+ (vmcs12->posted_intr_desc_addr & 0x3f) ||
+ (vmcs12->posted_intr_desc_addr >> cpuid_maxphyaddr(vcpu))))
+ return -EINVAL;
+
+ /* tpr shadow is needed by all apicv features. */
+ if (!nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int nested_vmx_check_msr_switch(struct kvm_vcpu *vcpu,
+ unsigned long count_field,
+ unsigned long addr_field)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ int maxphyaddr;
+ u64 count, addr;
+
+ if (vmcs12_read_any(vmcs12, count_field, &count) ||
+ vmcs12_read_any(vmcs12, addr_field, &addr)) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ if (count == 0)
+ return 0;
+ maxphyaddr = cpuid_maxphyaddr(vcpu);
+ if (!IS_ALIGNED(addr, 16) || addr >> maxphyaddr ||
+ (addr + count * sizeof(struct vmx_msr_entry) - 1) >> maxphyaddr) {
+ pr_debug_ratelimited(
+ "nVMX: invalid MSR switch (0x%lx, %d, %llu, 0x%08llx)",
+ addr_field, maxphyaddr, count, addr);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int nested_vmx_check_msr_switch_controls(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ if (vmcs12->vm_exit_msr_load_count == 0 &&
+ vmcs12->vm_exit_msr_store_count == 0 &&
+ vmcs12->vm_entry_msr_load_count == 0)
+ return 0; /* Fast path */
+ if (nested_vmx_check_msr_switch(vcpu, VM_EXIT_MSR_LOAD_COUNT,
+ VM_EXIT_MSR_LOAD_ADDR) ||
+ nested_vmx_check_msr_switch(vcpu, VM_EXIT_MSR_STORE_COUNT,
+ VM_EXIT_MSR_STORE_ADDR) ||
+ nested_vmx_check_msr_switch(vcpu, VM_ENTRY_MSR_LOAD_COUNT,
+ VM_ENTRY_MSR_LOAD_ADDR))
+ return -EINVAL;
+ return 0;
+}
+
+static int nested_vmx_check_pml_controls(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ u64 address = vmcs12->pml_address;
+ int maxphyaddr = cpuid_maxphyaddr(vcpu);
+
+ if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_PML)) {
+ if (!nested_cpu_has_ept(vmcs12) ||
+ !IS_ALIGNED(address, 4096) ||
+ address >> maxphyaddr)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int nested_vmx_check_shadow_vmcs_controls(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ if (!nested_cpu_has_shadow_vmcs(vmcs12))
+ return 0;
+
+ if (!page_address_valid(vcpu, vmcs12->vmread_bitmap) ||
+ !page_address_valid(vcpu, vmcs12->vmwrite_bitmap))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int nested_vmx_msr_check_common(struct kvm_vcpu *vcpu,
+ struct vmx_msr_entry *e)
+{
+ /* x2APIC MSR accesses are not allowed */
+ if (vcpu->arch.apic_base & X2APIC_ENABLE && e->index >> 8 == 0x8)
+ return -EINVAL;
+ if (e->index == MSR_IA32_UCODE_WRITE || /* SDM Table 35-2 */
+ e->index == MSR_IA32_UCODE_REV)
+ return -EINVAL;
+ if (e->reserved != 0)
+ return -EINVAL;
+ return 0;
+}
+
+static int nested_vmx_load_msr_check(struct kvm_vcpu *vcpu,
+ struct vmx_msr_entry *e)
+{
+ if (e->index == MSR_FS_BASE ||
+ e->index == MSR_GS_BASE ||
+ e->index == MSR_IA32_SMM_MONITOR_CTL || /* SMM is not supported */
+ nested_vmx_msr_check_common(vcpu, e))
+ return -EINVAL;
+ return 0;
+}
+
+static int nested_vmx_store_msr_check(struct kvm_vcpu *vcpu,
+ struct vmx_msr_entry *e)
+{
+ if (e->index == MSR_IA32_SMBASE || /* SMM is not supported */
+ nested_vmx_msr_check_common(vcpu, e))
+ return -EINVAL;
+ return 0;
+}
+
+/*
+ * Load guest's/host's msr at nested entry/exit.
+ * return 0 for success, entry index for failure.
+ */
+static u32 nested_vmx_load_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count)
+{
+ u32 i;
+ struct vmx_msr_entry e;
+ struct msr_data msr;
+
+ msr.host_initiated = false;
+ for (i = 0; i < count; i++) {
+ if (kvm_vcpu_read_guest(vcpu, gpa + i * sizeof(e),
+ &e, sizeof(e))) {
+ pr_debug_ratelimited(
+ "%s cannot read MSR entry (%u, 0x%08llx)\n",
+ __func__, i, gpa + i * sizeof(e));
+ goto fail;
+ }
+ if (nested_vmx_load_msr_check(vcpu, &e)) {
+ pr_debug_ratelimited(
+ "%s check failed (%u, 0x%x, 0x%x)\n",
+ __func__, i, e.index, e.reserved);
+ goto fail;
+ }
+ msr.index = e.index;
+ msr.data = e.value;
+ if (kvm_set_msr(vcpu, &msr)) {
+ pr_debug_ratelimited(
+ "%s cannot write MSR (%u, 0x%x, 0x%llx)\n",
+ __func__, i, e.index, e.value);
+ goto fail;
+ }
+ }
+ return 0;
+fail:
+ return i + 1;
+}
+
+static int nested_vmx_store_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count)
+{
+ u32 i;
+ struct vmx_msr_entry e;
+
+ for (i = 0; i < count; i++) {
+ struct msr_data msr_info;
+ if (kvm_vcpu_read_guest(vcpu,
+ gpa + i * sizeof(e),
+ &e, 2 * sizeof(u32))) {
+ pr_debug_ratelimited(
+ "%s cannot read MSR entry (%u, 0x%08llx)\n",
+ __func__, i, gpa + i * sizeof(e));
+ return -EINVAL;
+ }
+ if (nested_vmx_store_msr_check(vcpu, &e)) {
+ pr_debug_ratelimited(
+ "%s check failed (%u, 0x%x, 0x%x)\n",
+ __func__, i, e.index, e.reserved);
+ return -EINVAL;
+ }
+ msr_info.host_initiated = false;
+ msr_info.index = e.index;
+ if (kvm_get_msr(vcpu, &msr_info)) {
+ pr_debug_ratelimited(
+ "%s cannot read MSR (%u, 0x%x)\n",
+ __func__, i, e.index);
+ return -EINVAL;
+ }
+ if (kvm_vcpu_write_guest(vcpu,
+ gpa + i * sizeof(e) +
+ offsetof(struct vmx_msr_entry, value),
+ &msr_info.data, sizeof(msr_info.data))) {
+ pr_debug_ratelimited(
+ "%s cannot write MSR (%u, 0x%x, 0x%llx)\n",
+ __func__, i, e.index, msr_info.data);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static bool nested_cr3_valid(struct kvm_vcpu *vcpu, unsigned long val)
+{
+ unsigned long invalid_mask;
+
+ invalid_mask = (~0ULL) << cpuid_maxphyaddr(vcpu);
+ return (val & invalid_mask) == 0;
+}
+
+/*
+ * Load guest's/host's cr3 at nested entry/exit. nested_ept is true if we are
+ * emulating VM entry into a guest with EPT enabled.
+ * Returns 0 on success, 1 on failure. Invalid state exit qualification code
+ * is assigned to entry_failure_code on failure.
+ */
+static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool nested_ept,
+ u32 *entry_failure_code)
+{
+ if (cr3 != kvm_read_cr3(vcpu) || (!nested_ept && pdptrs_changed(vcpu))) {
+ if (!nested_cr3_valid(vcpu, cr3)) {
+ *entry_failure_code = ENTRY_FAIL_DEFAULT;
+ return 1;
+ }
+
+ /*
+ * If PAE paging and EPT are both on, CR3 is not used by the CPU and
+ * must not be dereferenced.
+ */
+ if (is_pae_paging(vcpu) && !nested_ept) {
+ if (!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3)) {
+ *entry_failure_code = ENTRY_FAIL_PDPTE;
+ return 1;
+ }
+ }
+ }
+
+ if (!nested_ept)
+ kvm_mmu_new_cr3(vcpu, cr3, false);
+
+ vcpu->arch.cr3 = cr3;
+ __set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
+
+ kvm_init_mmu(vcpu, false);
+
+ return 0;
+}
+
+static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector);
+ vmcs_write16(GUEST_SS_SELECTOR, vmcs12->guest_ss_selector);
+ vmcs_write16(GUEST_DS_SELECTOR, vmcs12->guest_ds_selector);
+ vmcs_write16(GUEST_FS_SELECTOR, vmcs12->guest_fs_selector);
+ vmcs_write16(GUEST_GS_SELECTOR, vmcs12->guest_gs_selector);
+ vmcs_write16(GUEST_LDTR_SELECTOR, vmcs12->guest_ldtr_selector);
+ vmcs_write16(GUEST_TR_SELECTOR, vmcs12->guest_tr_selector);
+ vmcs_write32(GUEST_ES_LIMIT, vmcs12->guest_es_limit);
+ vmcs_write32(GUEST_SS_LIMIT, vmcs12->guest_ss_limit);
+ vmcs_write32(GUEST_DS_LIMIT, vmcs12->guest_ds_limit);
+ vmcs_write32(GUEST_FS_LIMIT, vmcs12->guest_fs_limit);
+ vmcs_write32(GUEST_GS_LIMIT, vmcs12->guest_gs_limit);
+ vmcs_write32(GUEST_LDTR_LIMIT, vmcs12->guest_ldtr_limit);
+ vmcs_write32(GUEST_TR_LIMIT, vmcs12->guest_tr_limit);
+ vmcs_write32(GUEST_GDTR_LIMIT, vmcs12->guest_gdtr_limit);
+ vmcs_write32(GUEST_IDTR_LIMIT, vmcs12->guest_idtr_limit);
+ vmcs_write32(GUEST_ES_AR_BYTES, vmcs12->guest_es_ar_bytes);
+ vmcs_write32(GUEST_SS_AR_BYTES, vmcs12->guest_ss_ar_bytes);
+ vmcs_write32(GUEST_DS_AR_BYTES, vmcs12->guest_ds_ar_bytes);
+ vmcs_write32(GUEST_FS_AR_BYTES, vmcs12->guest_fs_ar_bytes);
+ vmcs_write32(GUEST_GS_AR_BYTES, vmcs12->guest_gs_ar_bytes);
+ vmcs_write32(GUEST_LDTR_AR_BYTES, vmcs12->guest_ldtr_ar_bytes);
+ vmcs_write32(GUEST_TR_AR_BYTES, vmcs12->guest_tr_ar_bytes);
+ vmcs_writel(GUEST_SS_BASE, vmcs12->guest_ss_base);
+ vmcs_writel(GUEST_DS_BASE, vmcs12->guest_ds_base);
+ vmcs_writel(GUEST_FS_BASE, vmcs12->guest_fs_base);
+ vmcs_writel(GUEST_GS_BASE, vmcs12->guest_gs_base);
+ vmcs_writel(GUEST_LDTR_BASE, vmcs12->guest_ldtr_base);
+ vmcs_writel(GUEST_TR_BASE, vmcs12->guest_tr_base);
+ vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base);
+ vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base);
+
+ vmcs_write32(GUEST_SYSENTER_CS, vmcs12->guest_sysenter_cs);
+ vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS,
+ vmcs12->guest_pending_dbg_exceptions);
+ vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->guest_sysenter_esp);
+ vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->guest_sysenter_eip);
+
+ if (nested_cpu_has_xsaves(vmcs12))
+ vmcs_write64(XSS_EXIT_BITMAP, vmcs12->xss_exit_bitmap);
+ vmcs_write64(VMCS_LINK_POINTER, -1ull);
+
+ if (cpu_has_vmx_posted_intr())
+ vmcs_write16(POSTED_INTR_NV, POSTED_INTR_NESTED_VECTOR);
+
+ /*
+ * Whether page-faults are trapped is determined by a combination of
+ * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF.
+ * If enable_ept, L0 doesn't care about page faults and we should
+ * set all of these to L1's desires. However, if !enable_ept, L0 does
+ * care about (at least some) page faults, and because it is not easy
+ * (if at all possible?) to merge L0 and L1's desires, we simply ask
+ * to exit on each and every L2 page fault. This is done by setting
+ * MASK=MATCH=0 and (see below) EB.PF=1.
+ * Note that below we don't need special code to set EB.PF beyond the
+ * "or"ing of the EB of vmcs01 and vmcs12, because when enable_ept,
+ * vmcs01's EB.PF is 0 so the "or" will take vmcs12's value, and when
+ * !enable_ept, EB.PF is 1, so the "or" will always be 1.
+ */
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK,
+ enable_ept ? vmcs12->page_fault_error_code_mask : 0);
+ vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH,
+ enable_ept ? vmcs12->page_fault_error_code_match : 0);
+
+ /* All VMFUNCs are currently emulated through L0 vmexits. */
+ if (cpu_has_vmx_vmfunc())
+ vmcs_write64(VM_FUNCTION_CONTROL, 0);
+
+ if (cpu_has_vmx_apicv()) {
+ vmcs_write64(EOI_EXIT_BITMAP0, vmcs12->eoi_exit_bitmap0);
+ vmcs_write64(EOI_EXIT_BITMAP1, vmcs12->eoi_exit_bitmap1);
+ vmcs_write64(EOI_EXIT_BITMAP2, vmcs12->eoi_exit_bitmap2);
+ vmcs_write64(EOI_EXIT_BITMAP3, vmcs12->eoi_exit_bitmap3);
+ }
+
+ /*
+ * Set host-state according to L0's settings (vmcs12 is irrelevant here)
+ * Some constant fields are set here by vmx_set_constant_host_state().
+ * Other fields are different per CPU, and will be set later when
+ * vmx_vcpu_load() is called, and when vmx_prepare_switch_to_guest()
+ * is called.
+ */
+ vmx_set_constant_host_state(vmx);
+
+ /*
+ * Set the MSR load/store lists to match L0's settings.
+ */
+ vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
+ vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host.val));
+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
+ vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest.val));
+
+ set_cr4_guest_host_mask(vmx);
+
+ if (kvm_mpx_supported() && vmx->nested.nested_run_pending &&
+ (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
+ vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs);
+
+ if (enable_vpid) {
+ if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02)
+ vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->nested.vpid02);
+ else
+ vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
+ }
+
+ /*
+ * L1 may access the L2's PDPTR, so save them to construct vmcs12
+ */
+ if (enable_ept) {
+ vmcs_write64(GUEST_PDPTR0, vmcs12->guest_pdptr0);
+ vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1);
+ vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2);
+ vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3);
+ }
+
+ if (cpu_has_vmx_msr_bitmap())
+ vmcs_write64(MSR_BITMAP, __pa(vmx->nested.vmcs02.msr_bitmap));
+}
+
+/*
+ * prepare_vmcs02 is called when the L1 guest hypervisor runs its nested
+ * L2 guest. L1 has a vmcs for L2 (vmcs12), and this function "merges" it
+ * with L0's requirements for its guest (a.k.a. vmcs01), so we can run the L2
+ * guest in a way that will both be appropriate to L1's requests, and our
+ * needs. In addition to modifying the active vmcs (which is vmcs02), this
+ * function also has additional necessary side-effects, like setting various
+ * vcpu->arch fields.
+ * Returns 0 on success, 1 on failure. Invalid state exit qualification code
+ * is assigned to entry_failure_code on failure.
+ */
+static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
+ u32 *entry_failure_code)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 exec_control, vmcs12_exec_ctrl;
+
+ if (vmx->nested.dirty_vmcs12) {
+ prepare_vmcs02_full(vcpu, vmcs12);
+ vmx->nested.dirty_vmcs12 = false;
+ }
+
+ /*
+ * First, the fields that are shadowed. This must be kept in sync
+ * with vmx_shadow_fields.h.
+ */
+
+ vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector);
+ vmcs_write32(GUEST_CS_LIMIT, vmcs12->guest_cs_limit);
+ vmcs_write32(GUEST_CS_AR_BYTES, vmcs12->guest_cs_ar_bytes);
+ vmcs_writel(GUEST_ES_BASE, vmcs12->guest_es_base);
+ vmcs_writel(GUEST_CS_BASE, vmcs12->guest_cs_base);
+
+ if (vmx->nested.nested_run_pending &&
+ (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) {
+ kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
+ vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
+ } else {
+ kvm_set_dr(vcpu, 7, vcpu->arch.dr7);
+ vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.vmcs01_debugctl);
+ }
+ if (kvm_mpx_supported() && (!vmx->nested.nested_run_pending ||
+ !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)))
+ vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs);
+ if (vmx->nested.nested_run_pending) {
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ vmcs12->vm_entry_intr_info_field);
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
+ vmcs12->vm_entry_exception_error_code);
+ vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
+ vmcs12->vm_entry_instruction_len);
+ vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
+ vmcs12->guest_interruptibility_info);
+ vmx->loaded_vmcs->nmi_known_unmasked =
+ !(vmcs12->guest_interruptibility_info & GUEST_INTR_STATE_NMI);
+ } else {
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
+ }
+ vmx_set_rflags(vcpu, vmcs12->guest_rflags);
+
+ exec_control = vmcs12->pin_based_vm_exec_control;
+
+ /* Preemption timer setting is computed directly in vmx_vcpu_run. */
+ exec_control |= vmcs_config.pin_based_exec_ctrl;
+ exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
+ vmx->loaded_vmcs->hv_timer_armed = false;
+
+ /* Posted interrupts setting is only taken from vmcs12. */
+ if (nested_cpu_has_posted_intr(vmcs12)) {
+ vmx->nested.posted_intr_nv = vmcs12->posted_intr_nv;
+ vmx->nested.pi_pending = false;
+ } else {
+ exec_control &= ~PIN_BASED_POSTED_INTR;
+ }
+
+ vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, exec_control);
+
+ vmx->nested.preemption_timer_expired = false;
+ if (nested_cpu_has_preemption_timer(vmcs12))
+ vmx_start_preemption_timer(vcpu);
+
+ if (cpu_has_secondary_exec_ctrls()) {
+ exec_control = vmx->secondary_exec_control;
+
+ /* Take the following fields only from vmcs12 */
+ exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+ SECONDARY_EXEC_ENABLE_INVPCID |
+ SECONDARY_EXEC_RDTSCP |
+ SECONDARY_EXEC_XSAVES |
+ SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
+ SECONDARY_EXEC_APIC_REGISTER_VIRT |
+ SECONDARY_EXEC_ENABLE_VMFUNC);
+ if (nested_cpu_has(vmcs12,
+ CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)) {
+ vmcs12_exec_ctrl = vmcs12->secondary_vm_exec_control &
+ ~SECONDARY_EXEC_ENABLE_PML;
+ exec_control |= vmcs12_exec_ctrl;
+ }
+
+ /* VMCS shadowing for L2 is emulated for now */
+ exec_control &= ~SECONDARY_EXEC_SHADOW_VMCS;
+
+ if (exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)
+ vmcs_write16(GUEST_INTR_STATUS,
+ vmcs12->guest_intr_status);
+
+ /*
+ * Write an illegal value to APIC_ACCESS_ADDR. Later,
+ * nested_get_vmcs12_pages will either fix it up or
+ * remove the VM execution control.
+ */
+ if (exec_control & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)
+ vmcs_write64(APIC_ACCESS_ADDR, -1ull);
+
+ if (exec_control & SECONDARY_EXEC_ENCLS_EXITING)
+ vmcs_write64(ENCLS_EXITING_BITMAP, -1ull);
+
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
+ }
+
+ /*
+ * HOST_RSP is normally set correctly in vmx_vcpu_run() just before
+ * entry, but only if the current (host) sp changed from the value
+ * we wrote last (vmx->host_rsp). This cache is no longer relevant
+ * if we switch vmcs, and rather than hold a separate cache per vmcs,
+ * here we just force the write to happen on entry.
+ */
+ vmx->host_rsp = 0;
+
+ exec_control = vmx_exec_control(vmx); /* L0's desires */
+ exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
+ exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING;
+ exec_control &= ~CPU_BASED_TPR_SHADOW;
+ exec_control |= vmcs12->cpu_based_vm_exec_control;
+
+ /*
+ * Write an illegal value to VIRTUAL_APIC_PAGE_ADDR. Later, if
+ * nested_get_vmcs12_pages can't fix it up, the illegal value
+ * will result in a VM entry failure.
+ */
+ if (exec_control & CPU_BASED_TPR_SHADOW) {
+ vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, -1ull);
+ vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold);
+ } else {
+#ifdef CONFIG_X86_64
+ exec_control |= CPU_BASED_CR8_LOAD_EXITING |
+ CPU_BASED_CR8_STORE_EXITING;
+#endif
+ }
+
+ /*
+ * A vmexit (to either L1 hypervisor or L0 userspace) is always needed
+ * for I/O port accesses.
+ */
+ exec_control &= ~CPU_BASED_USE_IO_BITMAPS;
+ exec_control |= CPU_BASED_UNCOND_IO_EXITING;
+
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
+
+ /* EXCEPTION_BITMAP and CR0_GUEST_HOST_MASK should basically be the
+ * bitwise-or of what L1 wants to trap for L2, and what we want to
+ * trap. Note that CR0.TS also needs updating - we do this later.
+ */
+ update_exception_bitmap(vcpu);
+ vcpu->arch.cr0_guest_owned_bits &= ~vmcs12->cr0_guest_host_mask;
+ vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
+
+ /* L2->L1 exit controls are emulated - the hardware exit is to L0 so
+ * we should use its exit controls. Note that VM_EXIT_LOAD_IA32_EFER
+ * bits are further modified by vmx_set_efer() below.
+ */
+ vmcs_write32(VM_EXIT_CONTROLS, vmcs_config.vmexit_ctrl);
+
+ /* vmcs12's VM_ENTRY_LOAD_IA32_EFER and VM_ENTRY_IA32E_MODE are
+ * emulated by vmx_set_efer(), below.
+ */
+ vm_entry_controls_init(vmx,
+ (vmcs12->vm_entry_controls & ~VM_ENTRY_LOAD_IA32_EFER &
+ ~VM_ENTRY_IA32E_MODE) |
+ (vmcs_config.vmentry_ctrl & ~VM_ENTRY_IA32E_MODE));
+
+ if (vmx->nested.nested_run_pending &&
+ (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT)) {
+ vmcs_write64(GUEST_IA32_PAT, vmcs12->guest_ia32_pat);
+ vcpu->arch.pat = vmcs12->guest_ia32_pat;
+ } else if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
+ vmcs_write64(GUEST_IA32_PAT, vmx->vcpu.arch.pat);
+ }
+
+ vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
+
+ if (kvm_has_tsc_control)
+ decache_tsc_multiplier(vmx);
+
+ if (enable_vpid) {
+ /*
+ * There is no direct mapping between vpid02 and vpid12, the
+ * vpid02 is per-vCPU for L0 and reused while the value of
+ * vpid12 is changed w/ one invvpid during nested vmentry.
+ * The vpid12 is allocated by L1 for L2, so it will not
+ * influence global bitmap(for vpid01 and vpid02 allocation)
+ * even if spawn a lot of nested vCPUs.
+ */
+ if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02) {
+ if (vmcs12->virtual_processor_id != vmx->nested.last_vpid) {
+ vmx->nested.last_vpid = vmcs12->virtual_processor_id;
+ __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
+ }
+ } else {
+ vmx_flush_tlb(vcpu, true);
+ }
+ }
+
+ if (enable_pml) {
+ /*
+ * Conceptually we want to copy the PML address and index from
+ * vmcs01 here, and then back to vmcs01 on nested vmexit. But,
+ * since we always flush the log on each vmexit, this happens
+ * to be equivalent to simply resetting the fields in vmcs02.
+ */
+ ASSERT(vmx->pml_pg);
+ vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
+ vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
+ }
+
+ if (nested_cpu_has_ept(vmcs12)) {
+ if (nested_ept_init_mmu_context(vcpu)) {
+ *entry_failure_code = ENTRY_FAIL_DEFAULT;
+ return 1;
+ }
+ } else if (nested_cpu_has2(vmcs12,
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
+ vmx_flush_tlb(vcpu, true);
+ }
+
+ /*
+ * This sets GUEST_CR0 to vmcs12->guest_cr0, possibly modifying those
+ * bits which we consider mandatory enabled.
+ * The CR0_READ_SHADOW is what L2 should have expected to read given
+ * the specifications by L1; It's not enough to take
+ * vmcs12->cr0_read_shadow because on our cr0_guest_host_mask we we
+ * have more bits than L1 expected.
+ */
+ vmx_set_cr0(vcpu, vmcs12->guest_cr0);
+ vmcs_writel(CR0_READ_SHADOW, nested_read_cr0(vmcs12));
+
+ vmx_set_cr4(vcpu, vmcs12->guest_cr4);
+ vmcs_writel(CR4_READ_SHADOW, nested_read_cr4(vmcs12));
+
+ if (vmx->nested.nested_run_pending &&
+ (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER))
+ vcpu->arch.efer = vmcs12->guest_ia32_efer;
+ else if (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE)
+ vcpu->arch.efer |= (EFER_LMA | EFER_LME);
+ else
+ vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
+ /* Note: modifies VM_ENTRY/EXIT_CONTROLS and GUEST/HOST_IA32_EFER */
+ vmx_set_efer(vcpu, vcpu->arch.efer);
+
+ /*
+ * Guest state is invalid and unrestricted guest is disabled,
+ * which means L1 attempted VMEntry to L2 with invalid state.
+ * Fail the VMEntry.
+ */
+ if (vmx->emulation_required) {
+ *entry_failure_code = ENTRY_FAIL_DEFAULT;
+ return 1;
+ }
+
+ /* Shadow page tables on either EPT or shadow page tables. */
+ if (nested_vmx_load_cr3(vcpu, vmcs12->guest_cr3, nested_cpu_has_ept(vmcs12),
+ entry_failure_code))
+ return 1;
+
+ if (!enable_ept)
+ vcpu->arch.walk_mmu->inject_page_fault = vmx_inject_page_fault_nested;
+
+ kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp);
+ kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->guest_rip);
+ return 0;
+}
+
+static int nested_vmx_check_nmi_controls(struct vmcs12 *vmcs12)
+{
+ if (!nested_cpu_has_nmi_exiting(vmcs12) &&
+ nested_cpu_has_virtual_nmis(vmcs12))
+ return -EINVAL;
+
+ if (!nested_cpu_has_virtual_nmis(vmcs12) &&
+ nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_NMI_PENDING))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (vmcs12->guest_activity_state != GUEST_ACTIVITY_ACTIVE &&
+ vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT)
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_cpu_has_vpid(vmcs12) && !vmcs12->virtual_processor_id)
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_vmx_check_io_bitmap_controls(vcpu, vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_vmx_check_msr_bitmap_controls(vcpu, vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_vmx_check_apic_access_controls(vcpu, vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_vmx_check_tpr_shadow_controls(vcpu, vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_vmx_check_apicv_controls(vcpu, vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (!nested_cpu_has_preemption_timer(vmcs12) &&
+ nested_cpu_has_save_preemption_timer(vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_vmx_check_pml_controls(vcpu, vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_vmx_check_shadow_vmcs_controls(vcpu, vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
+ vmx->nested.msrs.procbased_ctls_low,
+ vmx->nested.msrs.procbased_ctls_high) ||
+ (nested_cpu_has(vmcs12, CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) &&
+ !vmx_control_verify(vmcs12->secondary_vm_exec_control,
+ vmx->nested.msrs.secondary_ctls_low,
+ vmx->nested.msrs.secondary_ctls_high)) ||
+ !vmx_control_verify(vmcs12->pin_based_vm_exec_control,
+ vmx->nested.msrs.pinbased_ctls_low,
+ vmx->nested.msrs.pinbased_ctls_high) ||
+ !vmx_control_verify(vmcs12->vm_exit_controls,
+ vmx->nested.msrs.exit_ctls_low,
+ vmx->nested.msrs.exit_ctls_high) ||
+ !vmx_control_verify(vmcs12->vm_entry_controls,
+ vmx->nested.msrs.entry_ctls_low,
+ vmx->nested.msrs.entry_ctls_high))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_vmx_check_nmi_controls(vmcs12))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_cpu_has_vmfunc(vmcs12)) {
+ if (vmcs12->vm_function_control &
+ ~vmx->nested.msrs.vmfunc_controls)
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (nested_cpu_has_eptp_switching(vmcs12)) {
+ if (!nested_cpu_has_ept(vmcs12) ||
+ !page_address_valid(vcpu, vmcs12->eptp_list_address))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+ }
+ }
+
+ if (vmcs12->cr3_target_count > nested_cpu_vmx_misc_cr3_count(vcpu))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ if (!nested_host_cr0_valid(vcpu, vmcs12->host_cr0) ||
+ !nested_host_cr4_valid(vcpu, vmcs12->host_cr4) ||
+ !nested_cr3_valid(vcpu, vmcs12->host_cr3))
+ return VMXERR_ENTRY_INVALID_HOST_STATE_FIELD;
+
+ /*
+ * From the Intel SDM, volume 3:
+ * Fields relevant to VM-entry event injection must be set properly.
+ * These fields are the VM-entry interruption-information field, the
+ * VM-entry exception error code, and the VM-entry instruction length.
+ */
+ if (vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK) {
+ u32 intr_info = vmcs12->vm_entry_intr_info_field;
+ u8 vector = intr_info & INTR_INFO_VECTOR_MASK;
+ u32 intr_type = intr_info & INTR_INFO_INTR_TYPE_MASK;
+ bool has_error_code = intr_info & INTR_INFO_DELIVER_CODE_MASK;
+ bool should_have_error_code;
+ bool urg = nested_cpu_has2(vmcs12,
+ SECONDARY_EXEC_UNRESTRICTED_GUEST);
+ bool prot_mode = !urg || vmcs12->guest_cr0 & X86_CR0_PE;
+
+ /* VM-entry interruption-info field: interruption type */
+ if (intr_type == INTR_TYPE_RESERVED ||
+ (intr_type == INTR_TYPE_OTHER_EVENT &&
+ !nested_cpu_supports_monitor_trap_flag(vcpu)))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry interruption-info field: vector */
+ if ((intr_type == INTR_TYPE_NMI_INTR && vector != NMI_VECTOR) ||
+ (intr_type == INTR_TYPE_HARD_EXCEPTION && vector > 31) ||
+ (intr_type == INTR_TYPE_OTHER_EVENT && vector != 0))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry interruption-info field: deliver error code */
+ should_have_error_code =
+ intr_type == INTR_TYPE_HARD_EXCEPTION && prot_mode &&
+ x86_exception_has_error_code(vector);
+ if (has_error_code != should_have_error_code)
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry exception error code */
+ if (has_error_code &&
+ vmcs12->vm_entry_exception_error_code & GENMASK(31, 16))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry interruption-info field: reserved bits */
+ if (intr_info & INTR_INFO_RESVD_BITS_MASK)
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry instruction length */
+ switch (intr_type) {
+ case INTR_TYPE_SOFT_EXCEPTION:
+ case INTR_TYPE_SOFT_INTR:
+ case INTR_TYPE_PRIV_SW_EXCEPTION:
+ if ((vmcs12->vm_entry_instruction_len > 15) ||
+ (vmcs12->vm_entry_instruction_len == 0 &&
+ !nested_cpu_has_zero_length_injection(vcpu)))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+ }
+ }
+
+ return 0;
+}
+
+static int nested_vmx_check_vmcs_link_ptr(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ int r;
+ struct page *page;
+ struct vmcs12 *shadow;
+
+ if (vmcs12->vmcs_link_pointer == -1ull)
+ return 0;
+
+ if (!page_address_valid(vcpu, vmcs12->vmcs_link_pointer))
+ return -EINVAL;
+
+ page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->vmcs_link_pointer);
+ if (is_error_page(page))
+ return -EINVAL;
+
+ r = 0;
+ shadow = kmap(page);
+ if (shadow->hdr.revision_id != VMCS12_REVISION ||
+ shadow->hdr.shadow_vmcs != nested_cpu_has_shadow_vmcs(vmcs12))
+ r = -EINVAL;
+ kunmap(page);
+ kvm_release_page_clean(page);
+ return r;
+}
+
+static int check_vmentry_postreqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
+ u32 *exit_qual)
+{
+ bool ia32e;
+
+ *exit_qual = ENTRY_FAIL_DEFAULT;
+
+ if (!nested_guest_cr0_valid(vcpu, vmcs12->guest_cr0) ||
+ !nested_guest_cr4_valid(vcpu, vmcs12->guest_cr4))
+ return 1;
+
+ if (nested_vmx_check_vmcs_link_ptr(vcpu, vmcs12)) {
+ *exit_qual = ENTRY_FAIL_VMCS_LINK_PTR;
+ return 1;
+ }
+
+ /*
+ * If the load IA32_EFER VM-entry control is 1, the following checks
+ * are performed on the field for the IA32_EFER MSR:
+ * - Bits reserved in the IA32_EFER MSR must be 0.
+ * - Bit 10 (corresponding to IA32_EFER.LMA) must equal the value of
+ * the IA-32e mode guest VM-exit control. It must also be identical
+ * to bit 8 (LME) if bit 31 in the CR0 field (corresponding to
+ * CR0.PG) is 1.
+ */
+ if (to_vmx(vcpu)->nested.nested_run_pending &&
+ (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) {
+ ia32e = (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) != 0;
+ if (!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer) ||
+ ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA) ||
+ ((vmcs12->guest_cr0 & X86_CR0_PG) &&
+ ia32e != !!(vmcs12->guest_ia32_efer & EFER_LME)))
+ return 1;
+ }
+
+ /*
+ * If the load IA32_EFER VM-exit control is 1, bits reserved in the
+ * IA32_EFER MSR must be 0 in the field for that register. In addition,
+ * the values of the LMA and LME bits in the field must each be that of
+ * the host address-space size VM-exit control.
+ */
+ if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER) {
+ ia32e = (vmcs12->vm_exit_controls &
+ VM_EXIT_HOST_ADDR_SPACE_SIZE) != 0;
+ if (!kvm_valid_efer(vcpu, vmcs12->host_ia32_efer) ||
+ ia32e != !!(vmcs12->host_ia32_efer & EFER_LMA) ||
+ ia32e != !!(vmcs12->host_ia32_efer & EFER_LME))
+ return 1;
+ }
+
+ if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS) &&
+ (is_noncanonical_address(vmcs12->guest_bndcfgs & PAGE_MASK, vcpu) ||
+ (vmcs12->guest_bndcfgs & MSR_IA32_BNDCFGS_RSVD)))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * If exit_qual is NULL, this is being called from state restore (either RSM
+ * or KVM_SET_NESTED_STATE). Otherwise it's called from vmlaunch/vmresume.
+ */
+static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, u32 *exit_qual)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ bool from_vmentry = !!exit_qual;
+ u32 dummy_exit_qual;
+ bool evaluate_pending_interrupts;
+ int r = 0;
+
+ evaluate_pending_interrupts = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL) &
+ (CPU_BASED_VIRTUAL_INTR_PENDING | CPU_BASED_VIRTUAL_NMI_PENDING);
+ if (likely(!evaluate_pending_interrupts) && kvm_vcpu_apicv_active(vcpu))
+ evaluate_pending_interrupts |= vmx_has_apicv_interrupt(vcpu);
+
+ enter_guest_mode(vcpu);
+
+ if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
+ vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+ if (kvm_mpx_supported() &&
+ !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
+ vmx->nested.vmcs01_guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
+
+ vmx_switch_vmcs(vcpu, &vmx->nested.vmcs02);
+ vmx_segment_cache_clear(vmx);
+
+ if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
+ vcpu->arch.tsc_offset += vmcs12->tsc_offset;
+
+ r = EXIT_REASON_INVALID_STATE;
+ if (prepare_vmcs02(vcpu, vmcs12, from_vmentry ? exit_qual : &dummy_exit_qual))
+ goto fail;
+
+ if (from_vmentry) {
+ nested_get_vmcs12_pages(vcpu);
+
+ r = EXIT_REASON_MSR_LOAD_FAIL;
+ *exit_qual = nested_vmx_load_msr(vcpu,
+ vmcs12->vm_entry_msr_load_addr,
+ vmcs12->vm_entry_msr_load_count);
+ if (*exit_qual)
+ goto fail;
+ } else {
+ /*
+ * The MMU is not initialized to point at the right entities yet and
+ * "get pages" would need to read data from the guest (i.e. we will
+ * need to perform gpa to hpa translation). Request a call
+ * to nested_get_vmcs12_pages before the next VM-entry. The MSRs
+ * have already been set at vmentry time and should not be reset.
+ */
+ kvm_make_request(KVM_REQ_GET_VMCS12_PAGES, vcpu);
+ }
+
+ /*
+ * If L1 had a pending IRQ/NMI until it executed
+ * VMLAUNCH/VMRESUME which wasn't delivered because it was
+ * disallowed (e.g. interrupts disabled), L0 needs to
+ * evaluate if this pending event should cause an exit from L2
+ * to L1 or delivered directly to L2 (e.g. In case L1 don't
+ * intercept EXTERNAL_INTERRUPT).
+ *
+ * Usually this would be handled by the processor noticing an
+ * IRQ/NMI window request, or checking RVI during evaluation of
+ * pending virtual interrupts. However, this setting was done
+ * on VMCS01 and now VMCS02 is active instead. Thus, we force L0
+ * to perform pending event evaluation by requesting a KVM_REQ_EVENT.
+ */
+ if (unlikely(evaluate_pending_interrupts))
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+
+ /*
+ * Note no nested_vmx_succeed or nested_vmx_fail here. At this point
+ * we are no longer running L1, and VMLAUNCH/VMRESUME has not yet
+ * returned as far as L1 is concerned. It will only return (and set
+ * the success flag) when L2 exits (see nested_vmx_vmexit()).
+ */
+ return 0;
+
+fail:
+ if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
+ vcpu->arch.tsc_offset -= vmcs12->tsc_offset;
+ leave_guest_mode(vcpu);
+ vmx_switch_vmcs(vcpu, &vmx->vmcs01);
+ return r;
+}
+
+/*
+ * nested_vmx_run() handles a nested entry, i.e., a VMLAUNCH or VMRESUME on L1
+ * for running an L2 nested guest.
+ */
+static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
+{
+ struct vmcs12 *vmcs12;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ u32 interrupt_shadow = vmx_get_interrupt_shadow(vcpu);
+ u32 exit_qual;
+ int ret;
+
+ if (!nested_vmx_check_permission(vcpu))
+ return 1;
+
+ if (!nested_vmx_check_vmcs12(vcpu))
+ goto out;
+
+ vmcs12 = get_vmcs12(vcpu);
+
+ /*
+ * Can't VMLAUNCH or VMRESUME a shadow VMCS. Despite the fact
+ * that there *is* a valid VMCS pointer, RFLAGS.CF is set
+ * rather than RFLAGS.ZF, and no error number is stored to the
+ * VM-instruction error field.
+ */
+ if (vmcs12->hdr.shadow_vmcs) {
+ nested_vmx_failInvalid(vcpu);
+ goto out;
+ }
+
+ if (enable_shadow_vmcs)
+ copy_shadow_to_vmcs12(vmx);
+
+ /*
+ * The nested entry process starts with enforcing various prerequisites
+ * on vmcs12 as required by the Intel SDM, and act appropriately when
+ * they fail: As the SDM explains, some conditions should cause the
+ * instruction to fail, while others will cause the instruction to seem
+ * to succeed, but return an EXIT_REASON_INVALID_STATE.
+ * To speed up the normal (success) code path, we should avoid checking
+ * for misconfigurations which will anyway be caught by the processor
+ * when using the merged vmcs02.
+ */
+ if (interrupt_shadow & KVM_X86_SHADOW_INT_MOV_SS) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS);
+ goto out;
+ }
+
+ if (vmcs12->launch_state == launch) {
+ nested_vmx_failValid(vcpu,
+ launch ? VMXERR_VMLAUNCH_NONCLEAR_VMCS
+ : VMXERR_VMRESUME_NONLAUNCHED_VMCS);
+ goto out;
+ }
+
+ ret = check_vmentry_prereqs(vcpu, vmcs12);
+ if (ret) {
+ nested_vmx_failValid(vcpu, ret);
+ goto out;
+ }
+
+ /*
+ * After this point, the trap flag no longer triggers a singlestep trap
+ * on the vm entry instructions; don't call kvm_skip_emulated_instruction.
+ * This is not 100% correct; for performance reasons, we delegate most
+ * of the checks on host state to the processor. If those fail,
+ * the singlestep trap is missed.
+ */
+ skip_emulated_instruction(vcpu);
+
+ ret = check_vmentry_postreqs(vcpu, vmcs12, &exit_qual);
+ if (ret) {
+ nested_vmx_entry_failure(vcpu, vmcs12,
+ EXIT_REASON_INVALID_STATE, exit_qual);
+ return 1;
+ }
+
+ /*
+ * We're finally done with prerequisite checking, and can start with
+ * the nested entry.
+ */
+
+ vmx->nested.nested_run_pending = 1;
+ ret = enter_vmx_non_root_mode(vcpu, &exit_qual);
+ if (ret) {
+ nested_vmx_entry_failure(vcpu, vmcs12, ret, exit_qual);
+ vmx->nested.nested_run_pending = 0;
+ return 1;
+ }
+
+ /* Hide L1D cache contents from the nested guest. */
+ vmx->vcpu.arch.l1tf_flush_l1d = true;
+
+ /*
+ * Must happen outside of enter_vmx_non_root_mode() as it will
+ * also be used as part of restoring nVMX state for
+ * snapshot restore (migration).
+ *
+ * In this flow, it is assumed that vmcs12 cache was
+ * trasferred as part of captured nVMX state and should
+ * therefore not be read from guest memory (which may not
+ * exist on destination host yet).
+ */
+ nested_cache_shadow_vmcs12(vcpu, vmcs12);
+
+ /*
+ * If we're entering a halted L2 vcpu and the L2 vcpu won't be
+ * awakened by event injection or by an NMI-window VM-exit or
+ * by an interrupt-window VM-exit, halt the vcpu.
+ */
+ if ((vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT) &&
+ !(vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK) &&
+ !(vmcs12->cpu_based_vm_exec_control & CPU_BASED_VIRTUAL_NMI_PENDING) &&
+ !((vmcs12->cpu_based_vm_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING) &&
+ (vmcs12->guest_rflags & X86_EFLAGS_IF))) {
+ vmx->nested.nested_run_pending = 0;
+ return kvm_vcpu_halt(vcpu);
+ }
+ return 1;
+
+out:
+ return kvm_skip_emulated_instruction(vcpu);
+}
+
+/*
+ * On a nested exit from L2 to L1, vmcs12.guest_cr0 might not be up-to-date
+ * because L2 may have changed some cr0 bits directly (CRO_GUEST_HOST_MASK).
+ * This function returns the new value we should put in vmcs12.guest_cr0.
+ * It's not enough to just return the vmcs02 GUEST_CR0. Rather,
+ * 1. Bits that neither L0 nor L1 trapped, were set directly by L2 and are now
+ * available in vmcs02 GUEST_CR0. (Note: It's enough to check that L0
+ * didn't trap the bit, because if L1 did, so would L0).
+ * 2. Bits that L1 asked to trap (and therefore L0 also did) could not have
+ * been modified by L2, and L1 knows it. So just leave the old value of
+ * the bit from vmcs12.guest_cr0. Note that the bit from vmcs02 GUEST_CR0
+ * isn't relevant, because if L0 traps this bit it can set it to anything.
+ * 3. Bits that L1 didn't trap, but L0 did. L1 believes the guest could have
+ * changed these bits, and therefore they need to be updated, but L0
+ * didn't necessarily allow them to be changed in GUEST_CR0 - and rather
+ * put them in vmcs02 CR0_READ_SHADOW. So take these bits from there.
+ */
+static inline unsigned long
+vmcs12_guest_cr0(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ return
+ /*1*/ (vmcs_readl(GUEST_CR0) & vcpu->arch.cr0_guest_owned_bits) |
+ /*2*/ (vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask) |
+ /*3*/ (vmcs_readl(CR0_READ_SHADOW) & ~(vmcs12->cr0_guest_host_mask |
+ vcpu->arch.cr0_guest_owned_bits));
+}
+
+static inline unsigned long
+vmcs12_guest_cr4(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ return
+ /*1*/ (vmcs_readl(GUEST_CR4) & vcpu->arch.cr4_guest_owned_bits) |
+ /*2*/ (vmcs12->guest_cr4 & vmcs12->cr4_guest_host_mask) |
+ /*3*/ (vmcs_readl(CR4_READ_SHADOW) & ~(vmcs12->cr4_guest_host_mask |
+ vcpu->arch.cr4_guest_owned_bits));
+}
+
+static void vmcs12_save_pending_event(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ u32 idt_vectoring;
+ unsigned int nr;
+
+ if (vcpu->arch.exception.injected) {
+ nr = vcpu->arch.exception.nr;
+ idt_vectoring = nr | VECTORING_INFO_VALID_MASK;
+
+ if (kvm_exception_is_soft(nr)) {
+ vmcs12->vm_exit_instruction_len =
+ vcpu->arch.event_exit_inst_len;
+ idt_vectoring |= INTR_TYPE_SOFT_EXCEPTION;
+ } else
+ idt_vectoring |= INTR_TYPE_HARD_EXCEPTION;
+
+ if (vcpu->arch.exception.has_error_code) {
+ idt_vectoring |= VECTORING_INFO_DELIVER_CODE_MASK;
+ vmcs12->idt_vectoring_error_code =
+ vcpu->arch.exception.error_code;
+ }
+
+ vmcs12->idt_vectoring_info_field = idt_vectoring;
+ } else if (vcpu->arch.nmi_injected) {
+ vmcs12->idt_vectoring_info_field =
+ INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR;
+ } else if (vcpu->arch.interrupt.injected) {
+ nr = vcpu->arch.interrupt.nr;
+ idt_vectoring = nr | VECTORING_INFO_VALID_MASK;
+
+ if (vcpu->arch.interrupt.soft) {
+ idt_vectoring |= INTR_TYPE_SOFT_INTR;
+ vmcs12->vm_entry_instruction_len =
+ vcpu->arch.event_exit_inst_len;
+ } else
+ idt_vectoring |= INTR_TYPE_EXT_INTR;
+
+ vmcs12->idt_vectoring_info_field = idt_vectoring;
+ }
+}
+
+static int vmx_check_nested_events(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ unsigned long exit_qual;
+ bool block_nested_events =
+ vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu);
+
+ if (vcpu->arch.exception.pending &&
+ nested_vmx_check_exception(vcpu, &exit_qual)) {
+ if (block_nested_events)
+ return -EBUSY;
+ nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
+ return 0;
+ }
+
+ if (nested_cpu_has_preemption_timer(get_vmcs12(vcpu)) &&
+ vmx->nested.preemption_timer_expired) {
+ if (block_nested_events)
+ return -EBUSY;
+ nested_vmx_vmexit(vcpu, EXIT_REASON_PREEMPTION_TIMER, 0, 0);
+ return 0;
+ }
+
+ if (vcpu->arch.nmi_pending && nested_exit_on_nmi(vcpu)) {
+ if (block_nested_events)
+ return -EBUSY;
+ nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
+ NMI_VECTOR | INTR_TYPE_NMI_INTR |
+ INTR_INFO_VALID_MASK, 0);
+ /*
+ * The NMI-triggered VM exit counts as injection:
+ * clear this one and block further NMIs.
+ */
+ vcpu->arch.nmi_pending = 0;
+ vmx_set_nmi_mask(vcpu, true);
+ return 0;
+ }
+
+ if (kvm_cpu_has_interrupt(vcpu) && nested_exit_on_intr(vcpu)) {
+ if (block_nested_events)
+ return -EBUSY;
+ nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0);
+ return 0;
+ }
+
+ vmx_complete_nested_posted_interrupt(vcpu);
+ return 0;
+}
+
+static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu)
+{
+ to_vmx(vcpu)->req_immediate_exit = true;
+}
+
+static u32 vmx_get_preemption_timer_value(struct kvm_vcpu *vcpu)
+{
+ ktime_t remaining =
+ hrtimer_get_remaining(&to_vmx(vcpu)->nested.preemption_timer);
+ u64 value;
+
+ if (ktime_to_ns(remaining) <= 0)
+ return 0;
+
+ value = ktime_to_ns(remaining) * vcpu->arch.virtual_tsc_khz;
+ do_div(value, 1000000);
+ return value >> VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE;
+}
+
+/*
+ * Update the guest state fields of vmcs12 to reflect changes that
+ * occurred while L2 was running. (The "IA-32e mode guest" bit of the
+ * VM-entry controls is also updated, since this is really a guest
+ * state bit.)
+ */
+static void sync_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+{
+ vmcs12->guest_cr0 = vmcs12_guest_cr0(vcpu, vmcs12);
+ vmcs12->guest_cr4 = vmcs12_guest_cr4(vcpu, vmcs12);
+
+ vmcs12->guest_rsp = kvm_register_read(vcpu, VCPU_REGS_RSP);
+ vmcs12->guest_rip = kvm_register_read(vcpu, VCPU_REGS_RIP);
+ vmcs12->guest_rflags = vmcs_readl(GUEST_RFLAGS);
+
+ vmcs12->guest_es_selector = vmcs_read16(GUEST_ES_SELECTOR);
+ vmcs12->guest_cs_selector = vmcs_read16(GUEST_CS_SELECTOR);
+ vmcs12->guest_ss_selector = vmcs_read16(GUEST_SS_SELECTOR);
+ vmcs12->guest_ds_selector = vmcs_read16(GUEST_DS_SELECTOR);
+ vmcs12->guest_fs_selector = vmcs_read16(GUEST_FS_SELECTOR);
+ vmcs12->guest_gs_selector = vmcs_read16(GUEST_GS_SELECTOR);
+ vmcs12->guest_ldtr_selector = vmcs_read16(GUEST_LDTR_SELECTOR);
+ vmcs12->guest_tr_selector = vmcs_read16(GUEST_TR_SELECTOR);
+ vmcs12->guest_es_limit = vmcs_read32(GUEST_ES_LIMIT);
+ vmcs12->guest_cs_limit = vmcs_read32(GUEST_CS_LIMIT);
+ vmcs12->guest_ss_limit = vmcs_read32(GUEST_SS_LIMIT);
+ vmcs12->guest_ds_limit = vmcs_read32(GUEST_DS_LIMIT);
+ vmcs12->guest_fs_limit = vmcs_read32(GUEST_FS_LIMIT);
+ vmcs12->guest_gs_limit = vmcs_read32(GUEST_GS_LIMIT);
+ vmcs12->guest_ldtr_limit = vmcs_read32(GUEST_LDTR_LIMIT);
+ vmcs12->guest_tr_limit = vmcs_read32(GUEST_TR_LIMIT);
+ vmcs12->guest_gdtr_limit = vmcs_read32(GUEST_GDTR_LIMIT);
+ vmcs12->guest_idtr_limit = vmcs_read32(GUEST_IDTR_LIMIT);
+ vmcs12->guest_es_ar_bytes = vmcs_read32(GUEST_ES_AR_BYTES);
+ vmcs12->guest_cs_ar_bytes = vmcs_read32(GUEST_CS_AR_BYTES);
+ vmcs12->guest_ss_ar_bytes = vmcs_read32(GUEST_SS_AR_BYTES);
+ vmcs12->guest_ds_ar_bytes = vmcs_read32(GUEST_DS_AR_BYTES);
+ vmcs12->guest_fs_ar_bytes = vmcs_read32(GUEST_FS_AR_BYTES);
+ vmcs12->guest_gs_ar_bytes = vmcs_read32(GUEST_GS_AR_BYTES);
+ vmcs12->guest_ldtr_ar_bytes = vmcs_read32(GUEST_LDTR_AR_BYTES);
+ vmcs12->guest_tr_ar_bytes = vmcs_read32(GUEST_TR_AR_BYTES);
+ vmcs12->guest_es_base = vmcs_readl(GUEST_ES_BASE);
+ vmcs12->guest_cs_base = vmcs_readl(GUEST_CS_BASE);
+ vmcs12->guest_ss_base = vmcs_readl(GUEST_SS_BASE);
+ vmcs12->guest_ds_base = vmcs_readl(GUEST_DS_BASE);
+ vmcs12->guest_fs_base = vmcs_readl(GUEST_FS_BASE);
+ vmcs12->guest_gs_base = vmcs_readl(GUEST_GS_BASE);
+ vmcs12->guest_ldtr_base = vmcs_readl(GUEST_LDTR_BASE);
+ vmcs12->guest_tr_base = vmcs_readl(GUEST_TR_BASE);
+ vmcs12->guest_gdtr_base = vmcs_readl(GUEST_GDTR_BASE);
+ vmcs12->guest_idtr_base = vmcs_readl(GUEST_IDTR_BASE);
+
+ vmcs12->guest_interruptibility_info =
+ vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+ vmcs12->guest_pending_dbg_exceptions =
+ vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS);
+ if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
+ vmcs12->guest_activity_state = GUEST_ACTIVITY_HLT;
+ else
+ vmcs12->guest_activity_state = GUEST_ACTIVITY_ACTIVE;
+
+ if (nested_cpu_has_preemption_timer(vmcs12)) {
+ if (vmcs12->vm_exit_controls &
+ VM_EXIT_SAVE_VMX_PREEMPTION_TIMER)
+ vmcs12->vmx_preemption_timer_value =
+ vmx_get_preemption_timer_value(vcpu);
+ hrtimer_cancel(&to_vmx(vcpu)->nested.preemption_timer);
+ }
+
+ /*
+ * In some cases (usually, nested EPT), L2 is allowed to change its
+ * own CR3 without exiting. If it has changed it, we must keep it.
+ * Of course, if L0 is using shadow page tables, GUEST_CR3 was defined
+ * by L0, not L1 or L2, so we mustn't unconditionally copy it to vmcs12.
+ *
+ * Additionally, restore L2's PDPTR to vmcs12.
+ */
+ if (enable_ept) {
+ vmcs12->guest_cr3 = vmcs_readl(GUEST_CR3);
+ vmcs12->guest_pdptr0 = vmcs_read64(GUEST_PDPTR0);
+ vmcs12->guest_pdptr1 = vmcs_read64(GUEST_PDPTR1);
+ vmcs12->guest_pdptr2 = vmcs_read64(GUEST_PDPTR2);
+ vmcs12->guest_pdptr3 = vmcs_read64(GUEST_PDPTR3);
+ }
+
+ vmcs12->guest_linear_address = vmcs_readl(GUEST_LINEAR_ADDRESS);
+
+ if (nested_cpu_has_vid(vmcs12))
+ vmcs12->guest_intr_status = vmcs_read16(GUEST_INTR_STATUS);
+
+ vmcs12->vm_entry_controls =
+ (vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) |
+ (vm_entry_controls_get(to_vmx(vcpu)) & VM_ENTRY_IA32E_MODE);
+
+ if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_DEBUG_CONTROLS) {
+ kvm_get_dr(vcpu, 7, (unsigned long *)&vmcs12->guest_dr7);
+ vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+ }
+
+ /* TODO: These cannot have changed unless we have MSR bitmaps and
+ * the relevant bit asks not to trap the change */
+ if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_PAT)
+ vmcs12->guest_ia32_pat = vmcs_read64(GUEST_IA32_PAT);
+ if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_EFER)
+ vmcs12->guest_ia32_efer = vcpu->arch.efer;
+ vmcs12->guest_sysenter_cs = vmcs_read32(GUEST_SYSENTER_CS);
+ vmcs12->guest_sysenter_esp = vmcs_readl(GUEST_SYSENTER_ESP);
+ vmcs12->guest_sysenter_eip = vmcs_readl(GUEST_SYSENTER_EIP);
+ if (kvm_mpx_supported())
+ vmcs12->guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
+}
+
+/*
+ * prepare_vmcs12 is part of what we need to do when the nested L2 guest exits
+ * and we want to prepare to run its L1 parent. L1 keeps a vmcs for L2 (vmcs12),
+ * and this function updates it to reflect the changes to the guest state while
+ * L2 was running (and perhaps made some exits which were handled directly by L0
+ * without going back to L1), and to reflect the exit reason.
+ * Note that we do not have to copy here all VMCS fields, just those that
+ * could have changed by the L2 guest or the exit - i.e., the guest-state and
+ * exit-information fields only. Other fields are modified by L1 with VMWRITE,
+ * which already writes to vmcs12 directly.
+ */
+static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
+ u32 exit_reason, u32 exit_intr_info,
+ unsigned long exit_qualification)
+{
+ /* update guest state fields: */
+ sync_vmcs12(vcpu, vmcs12);
+
+ /* update exit information fields: */
+
+ vmcs12->vm_exit_reason = exit_reason;
+ vmcs12->exit_qualification = exit_qualification;
+ vmcs12->vm_exit_intr_info = exit_intr_info;
+
+ vmcs12->idt_vectoring_info_field = 0;
+ vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+ vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+
+ if (!(vmcs12->vm_exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY)) {
+ vmcs12->launch_state = 1;
+
+ /* vm_entry_intr_info_field is cleared on exit. Emulate this
+ * instead of reading the real value. */
+ vmcs12->vm_entry_intr_info_field &= ~INTR_INFO_VALID_MASK;
+
+ /*
+ * Transfer the event that L0 or L1 may wanted to inject into
+ * L2 to IDT_VECTORING_INFO_FIELD.
+ */
+ vmcs12_save_pending_event(vcpu, vmcs12);
+ }
+}
+
+/*
+ * A part of what we need to when the nested L2 guest exits and we want to
+ * run its L1 parent, is to reset L1's guest state to the host state specified
+ * in vmcs12.
+ * This function is to be called not only on normal nested exit, but also on
+ * a nested entry failure, as explained in Intel's spec, 3B.23.7 ("VM-Entry
+ * Failures During or After Loading Guest State").
+ * This function should be called when the active VMCS is L1's (vmcs01).
+ */
+static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12)
+{
+ struct kvm_segment seg;
+ u32 entry_failure_code;
+
+ if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
+ vcpu->arch.efer = vmcs12->host_ia32_efer;
+ else if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
+ vcpu->arch.efer |= (EFER_LMA | EFER_LME);
+ else
+ vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
+ vmx_set_efer(vcpu, vcpu->arch.efer);
+
+ kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->host_rsp);
+ kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->host_rip);
+ vmx_set_rflags(vcpu, X86_EFLAGS_FIXED);
+ /*
+ * Note that calling vmx_set_cr0 is important, even if cr0 hasn't
+ * actually changed, because vmx_set_cr0 refers to efer set above.
+ *
+ * CR0_GUEST_HOST_MASK is already set in the original vmcs01
+ * (KVM doesn't change it);
+ */
+ vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
+ vmx_set_cr0(vcpu, vmcs12->host_cr0);
+
+ /* Same as above - no reason to call set_cr4_guest_host_mask(). */
+ vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
+ vmx_set_cr4(vcpu, vmcs12->host_cr4);
+
+ nested_ept_uninit_mmu_context(vcpu);
+
+ /*
+ * Only PDPTE load can fail as the value of cr3 was checked on entry and
+ * couldn't have changed.
+ */
+ if (nested_vmx_load_cr3(vcpu, vmcs12->host_cr3, false, &entry_failure_code))
+ nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_PDPTE_FAIL);
+
+ if (!enable_ept)
+ vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault;
+
+ /*
+ * If vmcs01 don't use VPID, CPU flushes TLB on every
+ * VMEntry/VMExit. Thus, no need to flush TLB.
+ *
+ * If vmcs12 uses VPID, TLB entries populated by L2 are
+ * tagged with vmx->nested.vpid02 while L1 entries are tagged
+ * with vmx->vpid. Thus, no need to flush TLB.
+ *
+ * Therefore, flush TLB only in case vmcs01 uses VPID and
+ * vmcs12 don't use VPID as in this case L1 & L2 TLB entries
+ * are both tagged with vmx->vpid.
+ */
+ if (enable_vpid &&
+ !(nested_cpu_has_vpid(vmcs12) && to_vmx(vcpu)->nested.vpid02)) {
+ vmx_flush_tlb(vcpu, true);
+ }
+
+ vmcs_write32(GUEST_SYSENTER_CS, vmcs12->host_ia32_sysenter_cs);
+ vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->host_ia32_sysenter_esp);
+ vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->host_ia32_sysenter_eip);
+ vmcs_writel(GUEST_IDTR_BASE, vmcs12->host_idtr_base);
+ vmcs_writel(GUEST_GDTR_BASE, vmcs12->host_gdtr_base);
+ vmcs_write32(GUEST_IDTR_LIMIT, 0xFFFF);
+ vmcs_write32(GUEST_GDTR_LIMIT, 0xFFFF);
+
+ /* If not VM_EXIT_CLEAR_BNDCFGS, the L2 value propagates to L1. */
+ if (vmcs12->vm_exit_controls & VM_EXIT_CLEAR_BNDCFGS)
+ vmcs_write64(GUEST_BNDCFGS, 0);
+
+ if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PAT) {
+ vmcs_write64(GUEST_IA32_PAT, vmcs12->host_ia32_pat);
+ vcpu->arch.pat = vmcs12->host_ia32_pat;
+ }
+ if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
+ vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL,
+ vmcs12->host_ia32_perf_global_ctrl);
+
+ /* Set L1 segment info according to Intel SDM
+ 27.5.2 Loading Host Segment and Descriptor-Table Registers */
+ seg = (struct kvm_segment) {
+ .base = 0,
+ .limit = 0xFFFFFFFF,
+ .selector = vmcs12->host_cs_selector,
+ .type = 11,
+ .present = 1,
+ .s = 1,
+ .g = 1
+ };
+ if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
+ seg.l = 1;
+ else
+ seg.db = 1;
+ vmx_set_segment(vcpu, &seg, VCPU_SREG_CS);
+ seg = (struct kvm_segment) {
+ .base = 0,
+ .limit = 0xFFFFFFFF,
+ .type = 3,
+ .present = 1,
+ .s = 1,
+ .db = 1,
+ .g = 1
+ };
+ seg.selector = vmcs12->host_ds_selector;
+ vmx_set_segment(vcpu, &seg, VCPU_SREG_DS);
+ seg.selector = vmcs12->host_es_selector;
+ vmx_set_segment(vcpu, &seg, VCPU_SREG_ES);
+ seg.selector = vmcs12->host_ss_selector;
+ vmx_set_segment(vcpu, &seg, VCPU_SREG_SS);
+ seg.selector = vmcs12->host_fs_selector;
+ seg.base = vmcs12->host_fs_base;
+ vmx_set_segment(vcpu, &seg, VCPU_SREG_FS);
+ seg.selector = vmcs12->host_gs_selector;
+ seg.base = vmcs12->host_gs_base;
+ vmx_set_segment(vcpu, &seg, VCPU_SREG_GS);
+ seg = (struct kvm_segment) {
+ .base = vmcs12->host_tr_base,
+ .limit = 0x67,
+ .selector = vmcs12->host_tr_selector,
+ .type = 11,
+ .present = 1
+ };
+ vmx_set_segment(vcpu, &seg, VCPU_SREG_TR);
+
+ kvm_set_dr(vcpu, 7, 0x400);
+ vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
+
+ if (cpu_has_vmx_msr_bitmap())
+ vmx_update_msr_bitmap(vcpu);
+
+ if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr,
+ vmcs12->vm_exit_msr_load_count))
+ nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL);
+}
+
+static inline u64 nested_vmx_get_vmcs01_guest_efer(struct vcpu_vmx *vmx)
+{
+ struct shared_msr_entry *efer_msr;
+ unsigned int i;
+
+ if (vm_entry_controls_get(vmx) & VM_ENTRY_LOAD_IA32_EFER)
+ return vmcs_read64(GUEST_IA32_EFER);
+
+ if (cpu_has_load_ia32_efer)
+ return host_efer;
+
+ for (i = 0; i < vmx->msr_autoload.guest.nr; ++i) {
+ if (vmx->msr_autoload.guest.val[i].index == MSR_EFER)
+ return vmx->msr_autoload.guest.val[i].value;
+ }
+
+ efer_msr = find_msr_entry(vmx, MSR_EFER);
+ if (efer_msr)
+ return efer_msr->data;
+
+ return host_efer;
+}
+
+static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct vmx_msr_entry g, h;
+ struct msr_data msr;
+ gpa_t gpa;
+ u32 i, j;
+
+ vcpu->arch.pat = vmcs_read64(GUEST_IA32_PAT);
+
+ if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) {
+ /*
+ * L1's host DR7 is lost if KVM_GUESTDBG_USE_HW_BP is set
+ * as vmcs01.GUEST_DR7 contains a userspace defined value
+ * and vcpu->arch.dr7 is not squirreled away before the
+ * nested VMENTER (not worth adding a variable in nested_vmx).
+ */
+ if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
+ kvm_set_dr(vcpu, 7, DR7_FIXED_1);
+ else
+ WARN_ON(kvm_set_dr(vcpu, 7, vmcs_readl(GUEST_DR7)));
+ }
+
+ /*
+ * Note that calling vmx_set_{efer,cr0,cr4} is important as they
+ * handle a variety of side effects to KVM's software model.
+ */
+ vmx_set_efer(vcpu, nested_vmx_get_vmcs01_guest_efer(vmx));
+
+ vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
+ vmx_set_cr0(vcpu, vmcs_readl(CR0_READ_SHADOW));
+
+ vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
+ vmx_set_cr4(vcpu, vmcs_readl(CR4_READ_SHADOW));
+
+ nested_ept_uninit_mmu_context(vcpu);
+ vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
+ __set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
+
+ /*
+ * Use ept_save_pdptrs(vcpu) to load the MMU's cached PDPTRs
+ * from vmcs01 (if necessary). The PDPTRs are not loaded on
+ * VMFail, like everything else we just need to ensure our
+ * software model is up-to-date.
+ */
+ ept_save_pdptrs(vcpu);
+
+ kvm_mmu_reset_context(vcpu);
+
+ if (cpu_has_vmx_msr_bitmap())
+ vmx_update_msr_bitmap(vcpu);
+
+ /*
+ * This nasty bit of open coding is a compromise between blindly
+ * loading L1's MSRs using the exit load lists (incorrect emulation
+ * of VMFail), leaving the nested VM's MSRs in the software model
+ * (incorrect behavior) and snapshotting the modified MSRs (too
+ * expensive since the lists are unbound by hardware). For each
+ * MSR that was (prematurely) loaded from the nested VMEntry load
+ * list, reload it from the exit load list if it exists and differs
+ * from the guest value. The intent is to stuff host state as
+ * silently as possible, not to fully process the exit load list.
+ */
+ msr.host_initiated = false;
+ for (i = 0; i < vmcs12->vm_entry_msr_load_count; i++) {
+ gpa = vmcs12->vm_entry_msr_load_addr + (i * sizeof(g));
+ if (kvm_vcpu_read_guest(vcpu, gpa, &g, sizeof(g))) {
+ pr_debug_ratelimited(
+ "%s read MSR index failed (%u, 0x%08llx)\n",
+ __func__, i, gpa);
+ goto vmabort;
+ }
+
+ for (j = 0; j < vmcs12->vm_exit_msr_load_count; j++) {
+ gpa = vmcs12->vm_exit_msr_load_addr + (j * sizeof(h));
+ if (kvm_vcpu_read_guest(vcpu, gpa, &h, sizeof(h))) {
+ pr_debug_ratelimited(
+ "%s read MSR failed (%u, 0x%08llx)\n",
+ __func__, j, gpa);
+ goto vmabort;
+ }
+ if (h.index != g.index)
+ continue;
+ if (h.value == g.value)
+ break;
+
+ if (nested_vmx_load_msr_check(vcpu, &h)) {
+ pr_debug_ratelimited(
+ "%s check failed (%u, 0x%x, 0x%x)\n",
+ __func__, j, h.index, h.reserved);
+ goto vmabort;
+ }
+
+ msr.index = h.index;
+ msr.data = h.value;
+ if (kvm_set_msr(vcpu, &msr)) {
+ pr_debug_ratelimited(
+ "%s WRMSR failed (%u, 0x%x, 0x%llx)\n",
+ __func__, j, h.index, h.value);
+ goto vmabort;
+ }
+ }
+ }
+
+ return;
+
+vmabort:
+ nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL);
+}
+
+/*
+ * Emulate an exit from nested guest (L2) to L1, i.e., prepare to run L1
+ * and modify vmcs12 to make it see what it would expect to see there if
+ * L2 was its real guest. Must only be called when in L2 (is_guest_mode())
+ */
+static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
+ u32 exit_intr_info,
+ unsigned long exit_qualification)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+ /* trying to cancel vmlaunch/vmresume is a bug */
+ WARN_ON_ONCE(vmx->nested.nested_run_pending);
+
+ /*
+ * The only expected VM-instruction error is "VM entry with
+ * invalid control field(s)." Anything else indicates a
+ * problem with L0.
+ */
+ WARN_ON_ONCE(vmx->fail && (vmcs_read32(VM_INSTRUCTION_ERROR) !=
+ VMXERR_ENTRY_INVALID_CONTROL_FIELD));
+
+ leave_guest_mode(vcpu);
+
+ if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
+ vcpu->arch.tsc_offset -= vmcs12->tsc_offset;
+
+ if (likely(!vmx->fail)) {
+ if (exit_reason == -1)
+ sync_vmcs12(vcpu, vmcs12);
+ else
+ prepare_vmcs12(vcpu, vmcs12, exit_reason, exit_intr_info,
+ exit_qualification);
+
+ /*
+ * Must happen outside of sync_vmcs12() as it will
+ * also be used to capture vmcs12 cache as part of
+ * capturing nVMX state for snapshot (migration).
+ *
+ * Otherwise, this flush will dirty guest memory at a
+ * point it is already assumed by user-space to be
+ * immutable.
+ */
+ nested_flush_cached_shadow_vmcs12(vcpu, vmcs12);
+
+ if (nested_vmx_store_msr(vcpu, vmcs12->vm_exit_msr_store_addr,
+ vmcs12->vm_exit_msr_store_count))
+ nested_vmx_abort(vcpu, VMX_ABORT_SAVE_GUEST_MSR_FAIL);
+ }
+
+ /*
+ * Drop events/exceptions that were queued for re-injection to L2
+ * (picked up via vmx_complete_interrupts()), as well as exceptions
+ * that were pending for L2. Note, this must NOT be hoisted above
+ * prepare_vmcs12(), events/exceptions queued for re-injection need to
+ * be captured in vmcs12 (see vmcs12_save_pending_event()).
+ */
+ vcpu->arch.nmi_injected = false;
+ kvm_clear_exception_queue(vcpu);
+ kvm_clear_interrupt_queue(vcpu);
+
+ vmx_switch_vmcs(vcpu, &vmx->vmcs01);
+ vm_entry_controls_reset_shadow(vmx);
+ vm_exit_controls_reset_shadow(vmx);
+ vmx_segment_cache_clear(vmx);
+
+ /* Update any VMCS fields that might have changed while L2 ran */
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
+ vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
+
+ if (kvm_has_tsc_control)
+ decache_tsc_multiplier(vmx);
+
+ if (vmx->nested.change_vmcs01_virtual_apic_mode) {
+ vmx->nested.change_vmcs01_virtual_apic_mode = false;
+ vmx_set_virtual_apic_mode(vcpu);
+ } else if (!nested_cpu_has_ept(vmcs12) &&
+ nested_cpu_has2(vmcs12,
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
+ vmx_flush_tlb(vcpu, true);
+ }
+
+ /* This is needed for same reason as it was needed in prepare_vmcs02 */
+ vmx->host_rsp = 0;
+
+ /* Unpin physical memory we referred to in vmcs02 */
+ if (vmx->nested.apic_access_page) {
+ kvm_release_page_dirty(vmx->nested.apic_access_page);
+ vmx->nested.apic_access_page = NULL;
+ }
+ if (vmx->nested.virtual_apic_page) {
+ kvm_release_page_dirty(vmx->nested.virtual_apic_page);
+ vmx->nested.virtual_apic_page = NULL;
+ }
+ if (vmx->nested.pi_desc_page) {
+ kunmap(vmx->nested.pi_desc_page);
+ kvm_release_page_dirty(vmx->nested.pi_desc_page);
+ vmx->nested.pi_desc_page = NULL;
+ vmx->nested.pi_desc = NULL;
+ }
+
+ /*
+ * We are now running in L2, mmu_notifier will force to reload the
+ * page's hpa for L2 vmcs. Need to reload it for L1 before entering L1.
+ */
+ kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
+
+ if (enable_shadow_vmcs && exit_reason != -1)
+ vmx->nested.sync_shadow_vmcs = true;
+
+ /* in case we halted in L2 */
+ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+
+ if (likely(!vmx->fail)) {
+ if (exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT &&
+ nested_exit_intr_ack_set(vcpu)) {
+ int irq = kvm_cpu_get_interrupt(vcpu);
+ WARN_ON(irq < 0);
+ vmcs12->vm_exit_intr_info = irq |
+ INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR;
+ }
+
+ if (exit_reason != -1)
+ trace_kvm_nested_vmexit_inject(vmcs12->vm_exit_reason,
+ vmcs12->exit_qualification,
+ vmcs12->idt_vectoring_info_field,
+ vmcs12->vm_exit_intr_info,
+ vmcs12->vm_exit_intr_error_code,
+ KVM_ISA_VMX);
+
+ load_vmcs12_host_state(vcpu, vmcs12);
+
+ return;
+ }
+
+ /*
+ * After an early L2 VM-entry failure, we're now back
+ * in L1 which thinks it just finished a VMLAUNCH or
+ * VMRESUME instruction, so we need to set the failure
+ * flag and the VM-instruction error field of the VMCS
+ * accordingly.
+ */
+ nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+
+ /*
+ * Restore L1's host state to KVM's software model. We're here
+ * because a consistency check was caught by hardware, which
+ * means some amount of guest state has been propagated to KVM's
+ * model and needs to be unwound to the host's state.
+ */
+ nested_vmx_restore_host_state(vcpu);
+
+ /*
+ * The emulated instruction was already skipped in
+ * nested_vmx_run, but the updated RIP was never
+ * written back to the vmcs01.
+ */
+ skip_emulated_instruction(vcpu);
+ vmx->fail = 0;
+}
+
+/*
+ * Forcibly leave nested mode in order to be able to reset the VCPU later on.
+ */
+static void vmx_leave_nested(struct kvm_vcpu *vcpu)
+{
+ if (is_guest_mode(vcpu)) {
+ to_vmx(vcpu)->nested.nested_run_pending = 0;
+ nested_vmx_vmexit(vcpu, -1, 0, 0);
+ }
+ free_nested(to_vmx(vcpu));
+}
+
+/*
+ * L1's failure to enter L2 is a subset of a normal exit, as explained in
+ * 23.7 "VM-entry failures during or after loading guest state" (this also
+ * lists the acceptable exit-reason and exit-qualification parameters).
+ * It should only be called before L2 actually succeeded to run, and when
+ * vmcs01 is current (it doesn't leave_guest_mode() or switch vmcss).
+ */
+static void nested_vmx_entry_failure(struct kvm_vcpu *vcpu,
+ struct vmcs12 *vmcs12,
+ u32 reason, unsigned long qualification)
+{
+ load_vmcs12_host_state(vcpu, vmcs12);
+ vmcs12->vm_exit_reason = reason | VMX_EXIT_REASONS_FAILED_VMENTRY;
+ vmcs12->exit_qualification = qualification;
+ nested_vmx_succeed(vcpu);
+ if (enable_shadow_vmcs)
+ to_vmx(vcpu)->nested.sync_shadow_vmcs = true;
+}
+
+static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
+ struct x86_instruction_info *info)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ unsigned short port;
+ bool intercept;
+ int size;
+
+ if (info->intercept == x86_intercept_in ||
+ info->intercept == x86_intercept_ins) {
+ port = info->src_val;
+ size = info->dst_bytes;
+ } else {
+ port = info->dst_val;
+ size = info->src_bytes;
+ }
+
+ /*
+ * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
+ * VM-exits depend on the 'unconditional IO exiting' VM-execution
+ * control.
+ *
+ * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
+ */
+ if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+ intercept = nested_cpu_has(vmcs12,
+ CPU_BASED_UNCOND_IO_EXITING);
+ else
+ intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
+
+ /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED. */
+ return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+}
+
+static int vmx_check_intercept(struct kvm_vcpu *vcpu,
+ struct x86_instruction_info *info,
+ enum x86_intercept_stage stage)
+{
+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+ struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
+
+ switch (info->intercept) {
+ /*
+ * RDPID causes #UD if disabled through secondary execution controls.
+ * Because it is marked as EmulateOnUD, we need to intercept it here.
+ */
+ case x86_intercept_rdtscp:
+ if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+ ctxt->exception.vector = UD_VECTOR;
+ ctxt->exception.error_code_valid = false;
+ return X86EMUL_PROPAGATE_FAULT;
+ }
+ break;
+
+ case x86_intercept_in:
+ case x86_intercept_ins:
+ case x86_intercept_out:
+ case x86_intercept_outs:
+ return vmx_check_intercept_io(vcpu, info);
+
+ case x86_intercept_lgdt:
+ case x86_intercept_lidt:
+ case x86_intercept_lldt:
+ case x86_intercept_ltr:
+ case x86_intercept_sgdt:
+ case x86_intercept_sidt:
+ case x86_intercept_sldt:
+ case x86_intercept_str:
+ if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC))
+ return X86EMUL_CONTINUE;
+
+ /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED. */
+ break;
+
+ /* TODO: check more intercepts... */
+ default:
+ break;
+ }
+
+ return X86EMUL_UNHANDLEABLE;
+}
+
+#ifdef CONFIG_X86_64
+/* (a << shift) / divisor, return 1 if overflow otherwise 0 */
+static inline int u64_shl_div_u64(u64 a, unsigned int shift,
+ u64 divisor, u64 *result)
+{
+ u64 low = a << shift, high = a >> (64 - shift);
+
+ /* To avoid the overflow on divq */
+ if (high >= divisor)
+ return 1;
+
+ /* Low hold the result, high hold rem which is discarded */
+ asm("divq %2\n\t" : "=a" (low), "=d" (high) :
+ "rm" (divisor), "0" (low), "1" (high));
+ *result = low;
+
+ return 0;
+}
+
+static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
+{
+ struct vcpu_vmx *vmx;
+ u64 tscl, guest_tscl, delta_tsc, lapic_timer_advance_cycles;
+
+ if (kvm_mwait_in_guest(vcpu->kvm))
+ return -EOPNOTSUPP;
+
+ vmx = to_vmx(vcpu);
+ tscl = rdtsc();
+ guest_tscl = kvm_read_l1_tsc(vcpu, tscl);
+ delta_tsc = max(guest_deadline_tsc, guest_tscl) - guest_tscl;
+ lapic_timer_advance_cycles = nsec_to_cycles(vcpu, lapic_timer_advance_ns);
+
+ if (delta_tsc > lapic_timer_advance_cycles)
+ delta_tsc -= lapic_timer_advance_cycles;
+ else
+ delta_tsc = 0;
+
+ /* Convert to host delta tsc if tsc scaling is enabled */
+ if (vcpu->arch.tsc_scaling_ratio != kvm_default_tsc_scaling_ratio &&
+ u64_shl_div_u64(delta_tsc,
+ kvm_tsc_scaling_ratio_frac_bits,
+ vcpu->arch.tsc_scaling_ratio,
+ &delta_tsc))
+ return -ERANGE;
+
+ /*
+ * If the delta tsc can't fit in the 32 bit after the multi shift,
+ * we can't use the preemption timer.
+ * It's possible that it fits on later vmentries, but checking
+ * on every vmentry is costly so we just use an hrtimer.
+ */
+ if (delta_tsc >> (cpu_preemption_timer_multi + 32))
+ return -ERANGE;
+
+ vmx->hv_deadline_tsc = tscl + delta_tsc;
+ return delta_tsc == 0;
+}
+
+static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu)
+{
+ to_vmx(vcpu)->hv_deadline_tsc = -1;
+}
+#endif
+
+static void vmx_sched_in(struct kvm_vcpu *vcpu, int cpu)
+{
+ if (!kvm_pause_in_guest(vcpu->kvm))
+ shrink_ple_window(vcpu);
+}
+
+static void vmx_slot_enable_log_dirty(struct kvm *kvm,
+ struct kvm_memory_slot *slot)
+{
+ kvm_mmu_slot_leaf_clear_dirty(kvm, slot);
+ kvm_mmu_slot_largepage_remove_write_access(kvm, slot);
+}
+
+static void vmx_slot_disable_log_dirty(struct kvm *kvm,
+ struct kvm_memory_slot *slot)
+{
+ kvm_mmu_slot_set_dirty(kvm, slot);
+}
+
+static void vmx_flush_log_dirty(struct kvm *kvm)
+{
+ kvm_flush_pml_buffers(kvm);
+}
+
+static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa)
+{
+ struct vmcs12 *vmcs12;
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct page *page = NULL;
+ u64 *pml_address;
+
+ if (is_guest_mode(vcpu)) {
+ WARN_ON_ONCE(vmx->nested.pml_full);
+
+ /*
+ * Check if PML is enabled for the nested guest.
+ * Whether eptp bit 6 is set is already checked
+ * as part of A/D emulation.
+ */
+ vmcs12 = get_vmcs12(vcpu);
+ if (!nested_cpu_has_pml(vmcs12))
+ return 0;
+
+ if (vmcs12->guest_pml_index >= PML_ENTITY_NUM) {
+ vmx->nested.pml_full = true;
+ return 1;
+ }
+
+ gpa &= ~0xFFFull;
+
+ page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->pml_address);
+ if (is_error_page(page))
+ return 0;
+
+ pml_address = kmap(page);
+ pml_address[vmcs12->guest_pml_index--] = gpa;
+ kunmap(page);
+ kvm_release_page_clean(page);
+ }
+
+ return 0;
+}
+
+static void vmx_enable_log_dirty_pt_masked(struct kvm *kvm,
+ struct kvm_memory_slot *memslot,
+ gfn_t offset, unsigned long mask)
+{
+ kvm_mmu_clear_dirty_pt_masked(kvm, memslot, offset, mask);
+}
+
+static void __pi_post_block(struct kvm_vcpu *vcpu)
+{
+ struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
+ struct pi_desc old, new;
+ unsigned int dest;
+
+ do {
+ old.control = new.control = pi_desc->control;
+ WARN(old.nv != POSTED_INTR_WAKEUP_VECTOR,
+ "Wakeup handler not enabled while the VCPU is blocked\n");
+
+ dest = cpu_physical_id(vcpu->cpu);
+
+ if (x2apic_enabled())
+ new.ndst = dest;
+ else
+ new.ndst = (dest << 8) & 0xFF00;
+
+ /* set 'NV' to 'notification vector' */
+ new.nv = POSTED_INTR_VECTOR;
+ } while (cmpxchg64(&pi_desc->control, old.control,
+ new.control) != old.control);
+
+ if (!WARN_ON_ONCE(vcpu->pre_pcpu == -1)) {
+ spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
+ list_del(&vcpu->blocked_vcpu_list);
+ spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
+ vcpu->pre_pcpu = -1;
+ }
+}
+
+/*
+ * This routine does the following things for vCPU which is going
+ * to be blocked if VT-d PI is enabled.
+ * - Store the vCPU to the wakeup list, so when interrupts happen
+ * we can find the right vCPU to wake up.
+ * - Change the Posted-interrupt descriptor as below:
+ * 'NDST' <-- vcpu->pre_pcpu
+ * 'NV' <-- POSTED_INTR_WAKEUP_VECTOR
+ * - If 'ON' is set during this process, which means at least one
+ * interrupt is posted for this vCPU, we cannot block it, in
+ * this case, return 1, otherwise, return 0.
+ *
+ */
+static int pi_pre_block(struct kvm_vcpu *vcpu)
+{
+ unsigned int dest;
+ struct pi_desc old, new;
+ struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
+
+ if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
+ !irq_remapping_cap(IRQ_POSTING_CAP) ||
+ !kvm_vcpu_apicv_active(vcpu))
+ return 0;
+
+ WARN_ON(irqs_disabled());
+ local_irq_disable();
+ if (!WARN_ON_ONCE(vcpu->pre_pcpu != -1)) {
+ vcpu->pre_pcpu = vcpu->cpu;
+ spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
+ list_add_tail(&vcpu->blocked_vcpu_list,
+ &per_cpu(blocked_vcpu_on_cpu,
+ vcpu->pre_pcpu));
+ spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
+ }
+
+ do {
+ old.control = new.control = pi_desc->control;
+
+ WARN((pi_desc->sn == 1),
+ "Warning: SN field of posted-interrupts "
+ "is set before blocking\n");
+
+ /*
+ * Since vCPU can be preempted during this process,
+ * vcpu->cpu could be different with pre_pcpu, we
+ * need to set pre_pcpu as the destination of wakeup
+ * notification event, then we can find the right vCPU
+ * to wakeup in wakeup handler if interrupts happen
+ * when the vCPU is in blocked state.
+ */
+ dest = cpu_physical_id(vcpu->pre_pcpu);
+
+ if (x2apic_enabled())
+ new.ndst = dest;
+ else
+ new.ndst = (dest << 8) & 0xFF00;
+
+ /* set 'NV' to 'wakeup vector' */
+ new.nv = POSTED_INTR_WAKEUP_VECTOR;
+ } while (cmpxchg64(&pi_desc->control, old.control,
+ new.control) != old.control);
+
+ /* We should not block the vCPU if an interrupt is posted for it. */
+ if (pi_test_on(pi_desc) == 1)
+ __pi_post_block(vcpu);
+
+ local_irq_enable();
+ return (vcpu->pre_pcpu == -1);
+}
+
+static int vmx_pre_block(struct kvm_vcpu *vcpu)
+{
+ if (pi_pre_block(vcpu))
+ return 1;
+
+ if (kvm_lapic_hv_timer_in_use(vcpu))
+ kvm_lapic_switch_to_sw_timer(vcpu);
+
+ return 0;
+}
+
+static void pi_post_block(struct kvm_vcpu *vcpu)
+{
+ if (vcpu->pre_pcpu == -1)
+ return;
+
+ WARN_ON(irqs_disabled());
+ local_irq_disable();
+ __pi_post_block(vcpu);
+ local_irq_enable();
+}
+
+static void vmx_post_block(struct kvm_vcpu *vcpu)
+{
+ if (kvm_x86_ops->set_hv_timer)
+ kvm_lapic_switch_to_hv_timer(vcpu);
+
+ pi_post_block(vcpu);
+}
+
+/*
+ * vmx_update_pi_irte - set IRTE for Posted-Interrupts
+ *
+ * @kvm: kvm
+ * @host_irq: host irq of the interrupt
+ * @guest_irq: gsi of the interrupt
+ * @set: set or unset PI
+ * returns 0 on success, < 0 on failure
+ */
+static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
+ uint32_t guest_irq, bool set)
+{
+ struct kvm_kernel_irq_routing_entry *e;
+ struct kvm_irq_routing_table *irq_rt;
+ struct kvm_lapic_irq irq;
+ struct kvm_vcpu *vcpu;
+ struct vcpu_data vcpu_info;
+ int idx, ret = 0;
+
+ if (!kvm_arch_has_assigned_device(kvm) ||
+ !irq_remapping_cap(IRQ_POSTING_CAP) ||
+ !kvm_vcpu_apicv_active(kvm->vcpus[0]))
+ return 0;
+
+ idx = srcu_read_lock(&kvm->irq_srcu);
+ irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
+ if (guest_irq >= irq_rt->nr_rt_entries ||
+ hlist_empty(&irq_rt->map[guest_irq])) {
+ pr_warn_once("no route for guest_irq %u/%u (broken user space?)\n",
+ guest_irq, irq_rt->nr_rt_entries);
+ goto out;
+ }
+
+ hlist_for_each_entry(e, &irq_rt->map[guest_irq], link) {
+ if (e->type != KVM_IRQ_ROUTING_MSI)
+ continue;
+ /*
+ * VT-d PI cannot support posting multicast/broadcast
+ * interrupts to a vCPU, we still use interrupt remapping
+ * for these kind of interrupts.
+ *
+ * For lowest-priority interrupts, we only support
+ * those with single CPU as the destination, e.g. user
+ * configures the interrupts via /proc/irq or uses
+ * irqbalance to make the interrupts single-CPU.
+ *
+ * We will support full lowest-priority interrupt later.
+ */
+
+ kvm_set_msi_irq(kvm, e, &irq);
+ if (!kvm_intr_is_single_vcpu(kvm, &irq, &vcpu)) {
+ /*
+ * Make sure the IRTE is in remapped mode if
+ * we don't handle it in posted mode.
+ */
+ ret = irq_set_vcpu_affinity(host_irq, NULL);
+ if (ret < 0) {
+ printk(KERN_INFO
+ "failed to back to remapped mode, irq: %u\n",
+ host_irq);
+ goto out;
+ }
+
+ continue;
+ }
+
+ vcpu_info.pi_desc_addr = __pa(vcpu_to_pi_desc(vcpu));
+ vcpu_info.vector = irq.vector;
+
+ trace_kvm_pi_irte_update(host_irq, vcpu->vcpu_id, e->gsi,
+ vcpu_info.vector, vcpu_info.pi_desc_addr, set);
+
+ if (set)
+ ret = irq_set_vcpu_affinity(host_irq, &vcpu_info);
+ else
+ ret = irq_set_vcpu_affinity(host_irq, NULL);
+
+ if (ret < 0) {
+ printk(KERN_INFO "%s: failed to update PI IRTE\n",
+ __func__);
+ goto out;
+ }
+ }
+
+ ret = 0;
+out:
+ srcu_read_unlock(&kvm->irq_srcu, idx);
+ return ret;
+}
+
+static void vmx_setup_mce(struct kvm_vcpu *vcpu)
+{
+ if (vcpu->arch.mcg_cap & MCG_LMCE_P)
+ to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
+ FEATURE_CONTROL_LMCE;
+ else
+ to_vmx(vcpu)->msr_ia32_feature_control_valid_bits &=
+ ~FEATURE_CONTROL_LMCE;
+}
+
+static int vmx_smi_allowed(struct kvm_vcpu *vcpu)
+{
+ /* we need a nested vmexit to enter SMM, postpone if run is pending */
+ if (to_vmx(vcpu)->nested.nested_run_pending)
+ return 0;
+ return 1;
+}
+
+static int vmx_pre_enter_smm(struct kvm_vcpu *vcpu, char *smstate)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ vmx->nested.smm.guest_mode = is_guest_mode(vcpu);
+ if (vmx->nested.smm.guest_mode)
+ nested_vmx_vmexit(vcpu, -1, 0, 0);
+
+ vmx->nested.smm.vmxon = vmx->nested.vmxon;
+ vmx->nested.vmxon = false;
+ vmx_clear_hlt(vcpu);
+ return 0;
+}
+
+static int vmx_pre_leave_smm(struct kvm_vcpu *vcpu, u64 smbase)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int ret;
+
+ if (vmx->nested.smm.vmxon) {
+ vmx->nested.vmxon = true;
+ vmx->nested.smm.vmxon = false;
+ }
+
+ if (vmx->nested.smm.guest_mode) {
+ vcpu->arch.hflags &= ~HF_SMM_MASK;
+ ret = enter_vmx_non_root_mode(vcpu, NULL);
+ vcpu->arch.hflags |= HF_SMM_MASK;
+ if (ret)
+ return ret;
+
+ vmx->nested.smm.guest_mode = false;
+ }
+ return 0;
+}
+
+static int enable_smi_window(struct kvm_vcpu *vcpu)
+{
+ return 0;
+}
+
+static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
+ struct kvm_nested_state __user *user_kvm_nested_state,
+ u32 user_data_size)
+{
+ struct vcpu_vmx *vmx;
+ struct vmcs12 *vmcs12;
+ struct kvm_nested_state kvm_state = {
+ .flags = 0,
+ .format = 0,
+ .size = sizeof(kvm_state),
+ .vmx.vmxon_pa = -1ull,
+ .vmx.vmcs_pa = -1ull,
+ };
+
+ if (!vcpu)
+ return kvm_state.size + 2 * VMCS12_SIZE;
+
+ vmx = to_vmx(vcpu);
+ vmcs12 = get_vmcs12(vcpu);
+ if (nested_vmx_allowed(vcpu) &&
+ (vmx->nested.vmxon || vmx->nested.smm.vmxon)) {
+ kvm_state.vmx.vmxon_pa = vmx->nested.vmxon_ptr;
+ kvm_state.vmx.vmcs_pa = vmx->nested.current_vmptr;
+
+ if (vmx->nested.current_vmptr != -1ull) {
+ kvm_state.size += VMCS12_SIZE;
+
+ if (is_guest_mode(vcpu) &&
+ nested_cpu_has_shadow_vmcs(vmcs12) &&
+ vmcs12->vmcs_link_pointer != -1ull)
+ kvm_state.size += VMCS12_SIZE;
+ }
+
+ if (vmx->nested.smm.vmxon)
+ kvm_state.vmx.smm.flags |= KVM_STATE_NESTED_SMM_VMXON;
+
+ if (vmx->nested.smm.guest_mode)
+ kvm_state.vmx.smm.flags |= KVM_STATE_NESTED_SMM_GUEST_MODE;
+
+ if (is_guest_mode(vcpu)) {
+ kvm_state.flags |= KVM_STATE_NESTED_GUEST_MODE;
+
+ if (vmx->nested.nested_run_pending)
+ kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING;
+ }
+ }
+
+ if (user_data_size < kvm_state.size)
+ goto out;
+
+ if (copy_to_user(user_kvm_nested_state, &kvm_state, sizeof(kvm_state)))
+ return -EFAULT;
+
+ if (vmx->nested.current_vmptr == -1ull)
+ goto out;
+
+ /*
+ * When running L2, the authoritative vmcs12 state is in the
+ * vmcs02. When running L1, the authoritative vmcs12 state is
+ * in the shadow vmcs linked to vmcs01, unless
+ * sync_shadow_vmcs is set, in which case, the authoritative
+ * vmcs12 state is in the vmcs12 already.
+ */
+ if (is_guest_mode(vcpu))
+ sync_vmcs12(vcpu, vmcs12);
+ else if (enable_shadow_vmcs && !vmx->nested.sync_shadow_vmcs)
+ copy_shadow_to_vmcs12(vmx);
+
+ /*
+ * Copy over the full allocated size of vmcs12 rather than just the size
+ * of the struct.
+ */
+ if (copy_to_user(user_kvm_nested_state->data, vmcs12, VMCS12_SIZE))
+ return -EFAULT;
+
+ if (nested_cpu_has_shadow_vmcs(vmcs12) &&
+ vmcs12->vmcs_link_pointer != -1ull) {
+ if (copy_to_user(user_kvm_nested_state->data + VMCS12_SIZE,
+ get_shadow_vmcs12(vcpu), VMCS12_SIZE))
+ return -EFAULT;
+ }
+
+out:
+ return kvm_state.size;
+}
+
+static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
+ struct kvm_nested_state __user *user_kvm_nested_state,
+ struct kvm_nested_state *kvm_state)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct vmcs12 *vmcs12;
+ u32 exit_qual;
+ int ret;
+
+ if (kvm_state->format != 0)
+ return -EINVAL;
+
+ if (!nested_vmx_allowed(vcpu))
+ return kvm_state->vmx.vmxon_pa == -1ull ? 0 : -EINVAL;
+
+ if (kvm_state->vmx.vmxon_pa == -1ull) {
+ if (kvm_state->vmx.smm.flags)
+ return -EINVAL;
+
+ if (kvm_state->vmx.vmcs_pa != -1ull)
+ return -EINVAL;
+
+ vmx_leave_nested(vcpu);
+ return 0;
+ }
+
+ if (!page_address_valid(vcpu, kvm_state->vmx.vmxon_pa))
+ return -EINVAL;
+
+ if ((kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) &&
+ (kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE))
+ return -EINVAL;
+
+ if (kvm_state->vmx.smm.flags &
+ ~(KVM_STATE_NESTED_SMM_GUEST_MODE | KVM_STATE_NESTED_SMM_VMXON))
+ return -EINVAL;
+
+ /*
+ * SMM temporarily disables VMX, so we cannot be in guest mode,
+ * nor can VMLAUNCH/VMRESUME be pending. Outside SMM, SMM flags
+ * must be zero.
+ */
+ if (is_smm(vcpu) ? kvm_state->flags : kvm_state->vmx.smm.flags)
+ return -EINVAL;
+
+ if ((kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) &&
+ !(kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON))
+ return -EINVAL;
+
+ vmx_leave_nested(vcpu);
+ if (kvm_state->vmx.vmxon_pa == -1ull)
+ return 0;
+
+ vmx->nested.vmxon_ptr = kvm_state->vmx.vmxon_pa;
+ ret = enter_vmx_operation(vcpu);
+ if (ret)
+ return ret;
+
+ /* Empty 'VMXON' state is permitted */
+ if (kvm_state->size < sizeof(*kvm_state) + sizeof(*vmcs12))
+ return 0;
+
+ if (kvm_state->vmx.vmcs_pa == kvm_state->vmx.vmxon_pa ||
+ !page_address_valid(vcpu, kvm_state->vmx.vmcs_pa))
+ return -EINVAL;
+
+ set_current_vmptr(vmx, kvm_state->vmx.vmcs_pa);
+
+ if (kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON) {
+ vmx->nested.smm.vmxon = true;
+ vmx->nested.vmxon = false;
+
+ if (kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE)
+ vmx->nested.smm.guest_mode = true;
+ }
+
+ vmcs12 = get_vmcs12(vcpu);
+ if (copy_from_user(vmcs12, user_kvm_nested_state->data, sizeof(*vmcs12)))
+ return -EFAULT;
+
+ if (vmcs12->hdr.revision_id != VMCS12_REVISION)
+ return -EINVAL;
+
+ if (!(kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE))
+ return 0;
+
+ vmx->nested.nested_run_pending =
+ !!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING);
+
+ if (nested_cpu_has_shadow_vmcs(vmcs12) &&
+ vmcs12->vmcs_link_pointer != -1ull) {
+ struct vmcs12 *shadow_vmcs12 = get_shadow_vmcs12(vcpu);
+ if (kvm_state->size < sizeof(*kvm_state) + 2 * sizeof(*vmcs12))
+ return -EINVAL;
+
+ if (copy_from_user(shadow_vmcs12,
+ user_kvm_nested_state->data + VMCS12_SIZE,
+ sizeof(*vmcs12)))
+ return -EFAULT;
+
+ if (shadow_vmcs12->hdr.revision_id != VMCS12_REVISION ||
+ !shadow_vmcs12->hdr.shadow_vmcs)
+ return -EINVAL;
+ }
+
+ if (check_vmentry_prereqs(vcpu, vmcs12) ||
+ check_vmentry_postreqs(vcpu, vmcs12, &exit_qual))
+ return -EINVAL;
+
+ vmx->nested.dirty_vmcs12 = true;
+ ret = enter_vmx_non_root_mode(vcpu, NULL);
+ if (ret)
+ return -EINVAL;
+
+ return 0;
+}
+
+static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
+ .cpu_has_kvm_support = cpu_has_kvm_support,
+ .disabled_by_bios = vmx_disabled_by_bios,
+ .hardware_setup = hardware_setup,
+ .hardware_unsetup = hardware_unsetup,
+ .check_processor_compatibility = vmx_check_processor_compat,
+ .hardware_enable = hardware_enable,
+ .hardware_disable = hardware_disable,
+ .cpu_has_accelerated_tpr = report_flexpriority,
+ .has_emulated_msr = vmx_has_emulated_msr,
+
+ .vm_init = vmx_vm_init,
+ .vm_alloc = vmx_vm_alloc,
+ .vm_free = vmx_vm_free,
+
+ .vcpu_create = vmx_create_vcpu,
+ .vcpu_free = vmx_free_vcpu,
+ .vcpu_reset = vmx_vcpu_reset,
+
+ .prepare_guest_switch = vmx_prepare_switch_to_guest,
+ .vcpu_load = vmx_vcpu_load,
+ .vcpu_put = vmx_vcpu_put,
+
+ .update_bp_intercept = update_exception_bitmap,
+ .get_msr_feature = vmx_get_msr_feature,
+ .get_msr = vmx_get_msr,
+ .set_msr = vmx_set_msr,
+ .get_segment_base = vmx_get_segment_base,
+ .get_segment = vmx_get_segment,
+ .set_segment = vmx_set_segment,
+ .get_cpl = vmx_get_cpl,
+ .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
+ .decache_cr0_guest_bits = vmx_decache_cr0_guest_bits,
+ .decache_cr3 = vmx_decache_cr3,
+ .decache_cr4_guest_bits = vmx_decache_cr4_guest_bits,
+ .set_cr0 = vmx_set_cr0,
+ .set_cr3 = vmx_set_cr3,
+ .set_cr4 = vmx_set_cr4,
+ .set_efer = vmx_set_efer,
+ .get_idt = vmx_get_idt,
+ .set_idt = vmx_set_idt,
+ .get_gdt = vmx_get_gdt,
+ .set_gdt = vmx_set_gdt,
+ .get_dr6 = vmx_get_dr6,
+ .set_dr6 = vmx_set_dr6,
+ .set_dr7 = vmx_set_dr7,
+ .sync_dirty_debug_regs = vmx_sync_dirty_debug_regs,
+ .cache_reg = vmx_cache_reg,
+ .get_rflags = vmx_get_rflags,
+ .set_rflags = vmx_set_rflags,
+
+ .tlb_flush = vmx_flush_tlb,
+ .tlb_flush_gva = vmx_flush_tlb_gva,
+
+ .run = vmx_vcpu_run,
+ .handle_exit = vmx_handle_exit,
+ .skip_emulated_instruction = skip_emulated_instruction,
+ .set_interrupt_shadow = vmx_set_interrupt_shadow,
+ .get_interrupt_shadow = vmx_get_interrupt_shadow,
+ .patch_hypercall = vmx_patch_hypercall,
+ .set_irq = vmx_inject_irq,
+ .set_nmi = vmx_inject_nmi,
+ .queue_exception = vmx_queue_exception,
+ .cancel_injection = vmx_cancel_injection,
+ .interrupt_allowed = vmx_interrupt_allowed,
+ .nmi_allowed = vmx_nmi_allowed,
+ .get_nmi_mask = vmx_get_nmi_mask,
+ .set_nmi_mask = vmx_set_nmi_mask,
+ .enable_nmi_window = enable_nmi_window,
+ .enable_irq_window = enable_irq_window,
+ .update_cr8_intercept = update_cr8_intercept,
+ .set_virtual_apic_mode = vmx_set_virtual_apic_mode,
+ .set_apic_access_page_addr = vmx_set_apic_access_page_addr,
+ .get_enable_apicv = vmx_get_enable_apicv,
+ .refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
+ .load_eoi_exitmap = vmx_load_eoi_exitmap,
+ .apicv_post_state_restore = vmx_apicv_post_state_restore,
+ .hwapic_irr_update = vmx_hwapic_irr_update,
+ .hwapic_isr_update = vmx_hwapic_isr_update,
+ .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
+ .sync_pir_to_irr = vmx_sync_pir_to_irr,
+ .deliver_posted_interrupt = vmx_deliver_posted_interrupt,
+ .dy_apicv_has_pending_interrupt = vmx_dy_apicv_has_pending_interrupt,
+
+ .set_tss_addr = vmx_set_tss_addr,
+ .set_identity_map_addr = vmx_set_identity_map_addr,
+ .get_tdp_level = get_ept_level,
+ .get_mt_mask = vmx_get_mt_mask,
+
+ .get_exit_info = vmx_get_exit_info,
+
+ .get_lpage_level = vmx_get_lpage_level,
+
+ .cpuid_update = vmx_cpuid_update,
+
+ .rdtscp_supported = vmx_rdtscp_supported,
+ .invpcid_supported = vmx_invpcid_supported,
+
+ .set_supported_cpuid = vmx_set_supported_cpuid,
+
+ .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,
+
+ .read_l1_tsc_offset = vmx_read_l1_tsc_offset,
+ .write_l1_tsc_offset = vmx_write_l1_tsc_offset,
+
+ .set_tdp_cr3 = vmx_set_cr3,
+
+ .check_intercept = vmx_check_intercept,
+ .handle_external_intr = vmx_handle_external_intr,
+ .mpx_supported = vmx_mpx_supported,
+ .xsaves_supported = vmx_xsaves_supported,
+ .umip_emulated = vmx_umip_emulated,
+
+ .check_nested_events = vmx_check_nested_events,
+ .request_immediate_exit = vmx_request_immediate_exit,
+
+ .sched_in = vmx_sched_in,
+
+ .slot_enable_log_dirty = vmx_slot_enable_log_dirty,
+ .slot_disable_log_dirty = vmx_slot_disable_log_dirty,
+ .flush_log_dirty = vmx_flush_log_dirty,
+ .enable_log_dirty_pt_masked = vmx_enable_log_dirty_pt_masked,
+ .write_log_dirty = vmx_write_pml_buffer,
+
+ .pre_block = vmx_pre_block,
+ .post_block = vmx_post_block,
+
+ .pmu_ops = &intel_pmu_ops,
+
+ .update_pi_irte = vmx_update_pi_irte,
+
+#ifdef CONFIG_X86_64
+ .set_hv_timer = vmx_set_hv_timer,
+ .cancel_hv_timer = vmx_cancel_hv_timer,
+#endif
+
+ .setup_mce = vmx_setup_mce,
+
+ .get_nested_state = vmx_get_nested_state,
+ .set_nested_state = vmx_set_nested_state,
+ .get_vmcs12_pages = nested_get_vmcs12_pages,
+
+ .smi_allowed = vmx_smi_allowed,
+ .pre_enter_smm = vmx_pre_enter_smm,
+ .pre_leave_smm = vmx_pre_leave_smm,
+ .enable_smi_window = enable_smi_window,
+};
+
+static void vmx_cleanup_l1d_flush(void)
+{
+ if (vmx_l1d_flush_pages) {
+ free_pages((unsigned long)vmx_l1d_flush_pages, L1D_CACHE_ORDER);
+ vmx_l1d_flush_pages = NULL;
+ }
+ /* Restore state so sysfs ignores VMX */
+ l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO;
+}
+
+static void vmx_exit(void)
+{
+#ifdef CONFIG_KEXEC_CORE
+ RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL);
+ synchronize_rcu();
+#endif
+
+ kvm_exit();
+
+#if IS_ENABLED(CONFIG_HYPERV)
+ if (static_branch_unlikely(&enable_evmcs)) {
+ int cpu;
+ struct hv_vp_assist_page *vp_ap;
+ /*
+ * Reset everything to support using non-enlightened VMCS
+ * access later (e.g. when we reload the module with
+ * enlightened_vmcs=0)
+ */
+ for_each_online_cpu(cpu) {
+ vp_ap = hv_get_vp_assist_page(cpu);
+
+ if (!vp_ap)
+ continue;
+
+ vp_ap->current_nested_vmcs = 0;
+ vp_ap->enlighten_vmentry = 0;
+ }
+
+ static_branch_disable(&enable_evmcs);
+ }
+#endif
+ vmx_cleanup_l1d_flush();
+}
+module_exit(vmx_exit);
+
+static int __init vmx_init(void)
+{
+ int r, cpu;
+
+#if IS_ENABLED(CONFIG_HYPERV)
+ /*
+ * Enlightened VMCS usage should be recommended and the host needs
+ * to support eVMCS v1 or above. We can also disable eVMCS support
+ * with module parameter.
+ */
+ if (enlightened_vmcs &&
+ ms_hyperv.hints & HV_X64_ENLIGHTENED_VMCS_RECOMMENDED &&
+ (ms_hyperv.nested_features & HV_X64_ENLIGHTENED_VMCS_VERSION) >=
+ KVM_EVMCS_VERSION) {
+ int cpu;
+
+ /* Check that we have assist pages on all online CPUs */
+ for_each_online_cpu(cpu) {
+ if (!hv_get_vp_assist_page(cpu)) {
+ enlightened_vmcs = false;
+ break;
+ }
+ }
+
+ if (enlightened_vmcs) {
+ pr_info("KVM: vmx: using Hyper-V Enlightened VMCS\n");
+ static_branch_enable(&enable_evmcs);
+ }
+ } else {
+ enlightened_vmcs = false;
+ }
+#endif
+
+ r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx),
+ __alignof__(struct vcpu_vmx), THIS_MODULE);
+ if (r)
+ return r;
+
+ /*
+ * Must be called after kvm_init() so enable_ept is properly set
+ * up. Hand the parameter mitigation value in which was stored in
+ * the pre module init parser. If no parameter was given, it will
+ * contain 'auto' which will be turned into the default 'cond'
+ * mitigation mode.
+ */
+ if (boot_cpu_has(X86_BUG_L1TF)) {
+ r = vmx_setup_l1d_flush(vmentry_l1d_flush_param);
+ if (r) {
+ vmx_exit();
+ return r;
+ }
+ }
+
+ vmx_setup_fb_clear_ctrl();
+
+ for_each_possible_cpu(cpu) {
+ INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
+
+ INIT_LIST_HEAD(&per_cpu(blocked_vcpu_on_cpu, cpu));
+ spin_lock_init(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
+ }
+
+#ifdef CONFIG_KEXEC_CORE
+ rcu_assign_pointer(crash_vmclear_loaded_vmcss,
+ crash_vmclear_local_loaded_vmcss);
+#endif
+ vmx_check_vmcs12_offsets();
+
+ return 0;
+}
+module_init(vmx_init);
diff --git a/arch/x86/kvm/vmx/vmx_evmcs.h b/arch/x86/kvm/vmx/vmx_evmcs.h
new file mode 100644
index 000000000000..210a884090ad
--- /dev/null
+++ b/arch/x86/kvm/vmx/vmx_evmcs.h
@@ -0,0 +1,324 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __KVM_X86_VMX_EVMCS_H
+#define __KVM_X86_VMX_EVMCS_H
+
+#include <asm/hyperv-tlfs.h>
+
+#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
+#define EVMCS1_OFFSET(x) offsetof(struct hv_enlightened_vmcs, x)
+#define EVMCS1_FIELD(number, name, clean_field)[ROL16(number, 6)] = \
+ {EVMCS1_OFFSET(name), clean_field}
+
+struct evmcs_field {
+ u16 offset;
+ u16 clean_field;
+};
+
+static const struct evmcs_field vmcs_field_to_evmcs_1[] = {
+ /* 64 bit rw */
+ EVMCS1_FIELD(GUEST_RIP, guest_rip,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(GUEST_RSP, guest_rsp,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_BASIC),
+ EVMCS1_FIELD(GUEST_RFLAGS, guest_rflags,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_BASIC),
+ EVMCS1_FIELD(HOST_IA32_PAT, host_ia32_pat,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_IA32_EFER, host_ia32_efer,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_CR0, host_cr0,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_CR3, host_cr3,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_CR4, host_cr4,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_IA32_SYSENTER_ESP, host_ia32_sysenter_esp,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_RIP, host_rip,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(IO_BITMAP_A, io_bitmap_a,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_IO_BITMAP),
+ EVMCS1_FIELD(IO_BITMAP_B, io_bitmap_b,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_IO_BITMAP),
+ EVMCS1_FIELD(MSR_BITMAP, msr_bitmap,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP),
+ EVMCS1_FIELD(GUEST_ES_BASE, guest_es_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_CS_BASE, guest_cs_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_SS_BASE, guest_ss_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_DS_BASE, guest_ds_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_FS_BASE, guest_fs_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_GS_BASE, guest_gs_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_LDTR_BASE, guest_ldtr_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_TR_BASE, guest_tr_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_GDTR_BASE, guest_gdtr_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_IDTR_BASE, guest_idtr_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(TSC_OFFSET, tsc_offset,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP2),
+ EVMCS1_FIELD(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP2),
+ EVMCS1_FIELD(VMCS_LINK_POINTER, vmcs_link_pointer,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_IA32_PAT, guest_ia32_pat,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_IA32_EFER, guest_ia32_efer,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_PDPTR0, guest_pdptr0,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_PDPTR1, guest_pdptr1,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_PDPTR2, guest_pdptr2,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_PDPTR3, guest_pdptr3,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
+ EVMCS1_FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
+ EVMCS1_FIELD(CR0_READ_SHADOW, cr0_read_shadow,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
+ EVMCS1_FIELD(CR4_READ_SHADOW, cr4_read_shadow,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
+ EVMCS1_FIELD(GUEST_CR0, guest_cr0,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
+ EVMCS1_FIELD(GUEST_CR3, guest_cr3,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
+ EVMCS1_FIELD(GUEST_CR4, guest_cr4,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
+ EVMCS1_FIELD(GUEST_DR7, guest_dr7,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
+ EVMCS1_FIELD(HOST_FS_BASE, host_fs_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
+ EVMCS1_FIELD(HOST_GS_BASE, host_gs_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
+ EVMCS1_FIELD(HOST_TR_BASE, host_tr_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
+ EVMCS1_FIELD(HOST_GDTR_BASE, host_gdtr_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
+ EVMCS1_FIELD(HOST_IDTR_BASE, host_idtr_base,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
+ EVMCS1_FIELD(HOST_RSP, host_rsp,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
+ EVMCS1_FIELD(EPT_POINTER, ept_pointer,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_XLAT),
+ EVMCS1_FIELD(GUEST_BNDCFGS, guest_bndcfgs,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(XSS_EXIT_BITMAP, xss_exit_bitmap,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP2),
+
+ /* 64 bit read only */
+ EVMCS1_FIELD(GUEST_PHYSICAL_ADDRESS, guest_physical_address,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(EXIT_QUALIFICATION, exit_qualification,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ /*
+ * Not defined in KVM:
+ *
+ * EVMCS1_FIELD(0x00006402, exit_io_instruction_ecx,
+ * HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE);
+ * EVMCS1_FIELD(0x00006404, exit_io_instruction_esi,
+ * HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE);
+ * EVMCS1_FIELD(0x00006406, exit_io_instruction_esi,
+ * HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE);
+ * EVMCS1_FIELD(0x00006408, exit_io_instruction_eip,
+ * HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE);
+ */
+ EVMCS1_FIELD(GUEST_LINEAR_ADDRESS, guest_linear_address,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+
+ /*
+ * No mask defined in the spec as Hyper-V doesn't currently support
+ * these. Future proof by resetting the whole clean field mask on
+ * access.
+ */
+ EVMCS1_FIELD(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(CR3_TARGET_VALUE0, cr3_target_value0,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(CR3_TARGET_VALUE1, cr3_target_value1,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(CR3_TARGET_VALUE2, cr3_target_value2,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(CR3_TARGET_VALUE3, cr3_target_value3,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+
+ /* 32 bit rw */
+ EVMCS1_FIELD(TPR_THRESHOLD, tpr_threshold,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(GUEST_INTERRUPTIBILITY_INFO, guest_interruptibility_info,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_BASIC),
+ EVMCS1_FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_PROC),
+ EVMCS1_FIELD(EXCEPTION_BITMAP, exception_bitmap,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_EXCPN),
+ EVMCS1_FIELD(VM_ENTRY_CONTROLS, vm_entry_controls,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_ENTRY),
+ EVMCS1_FIELD(VM_ENTRY_INTR_INFO_FIELD, vm_entry_intr_info_field,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_EVENT),
+ EVMCS1_FIELD(VM_ENTRY_EXCEPTION_ERROR_CODE,
+ vm_entry_exception_error_code,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_EVENT),
+ EVMCS1_FIELD(VM_ENTRY_INSTRUCTION_LEN, vm_entry_instruction_len,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_EVENT),
+ EVMCS1_FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP1),
+ EVMCS1_FIELD(VM_EXIT_CONTROLS, vm_exit_controls,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP1),
+ EVMCS1_FIELD(SECONDARY_VM_EXEC_CONTROL, secondary_vm_exec_control,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP1),
+ EVMCS1_FIELD(GUEST_ES_LIMIT, guest_es_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_CS_LIMIT, guest_cs_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_SS_LIMIT, guest_ss_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_DS_LIMIT, guest_ds_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_FS_LIMIT, guest_fs_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_GS_LIMIT, guest_gs_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_LDTR_LIMIT, guest_ldtr_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_TR_LIMIT, guest_tr_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_GDTR_LIMIT, guest_gdtr_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_IDTR_LIMIT, guest_idtr_limit,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_ES_AR_BYTES, guest_es_ar_bytes,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_CS_AR_BYTES, guest_cs_ar_bytes,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_SS_AR_BYTES, guest_ss_ar_bytes,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_DS_AR_BYTES, guest_ds_ar_bytes,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_FS_AR_BYTES, guest_fs_ar_bytes,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_GS_AR_BYTES, guest_gs_ar_bytes,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_LDTR_AR_BYTES, guest_ldtr_ar_bytes,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_TR_AR_BYTES, guest_tr_ar_bytes,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_ACTIVITY_STATE, guest_activity_state,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+ EVMCS1_FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
+
+ /* 32 bit read only */
+ EVMCS1_FIELD(VM_INSTRUCTION_ERROR, vm_instruction_error,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(VM_EXIT_REASON, vm_exit_reason,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(VM_EXIT_INTR_INFO, vm_exit_intr_info,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(VM_EXIT_INTR_ERROR_CODE, vm_exit_intr_error_code,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(IDT_VECTORING_INFO_FIELD, idt_vectoring_info_field,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(IDT_VECTORING_ERROR_CODE, idt_vectoring_error_code,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(VM_EXIT_INSTRUCTION_LEN, vm_exit_instruction_len,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+ EVMCS1_FIELD(VMX_INSTRUCTION_INFO, vmx_instruction_info,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
+
+ /* No mask defined in the spec (not used) */
+ EVMCS1_FIELD(PAGE_FAULT_ERROR_CODE_MASK, page_fault_error_code_mask,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(PAGE_FAULT_ERROR_CODE_MATCH, page_fault_error_code_match,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(CR3_TARGET_COUNT, cr3_target_count,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(VM_EXIT_MSR_STORE_COUNT, vm_exit_msr_store_count,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(VM_EXIT_MSR_LOAD_COUNT, vm_exit_msr_load_count,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+ EVMCS1_FIELD(VM_ENTRY_MSR_LOAD_COUNT, vm_entry_msr_load_count,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
+
+ /* 16 bit rw */
+ EVMCS1_FIELD(HOST_ES_SELECTOR, host_es_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_CS_SELECTOR, host_cs_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_SS_SELECTOR, host_ss_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_DS_SELECTOR, host_ds_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_FS_SELECTOR, host_fs_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_GS_SELECTOR, host_gs_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(HOST_TR_SELECTOR, host_tr_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
+ EVMCS1_FIELD(GUEST_ES_SELECTOR, guest_es_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_CS_SELECTOR, guest_cs_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_SS_SELECTOR, guest_ss_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_DS_SELECTOR, guest_ds_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_FS_SELECTOR, guest_fs_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_GS_SELECTOR, guest_gs_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(GUEST_TR_SELECTOR, guest_tr_selector,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
+ EVMCS1_FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id,
+ HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_XLAT),
+};
+
+static __always_inline int get_evmcs_offset(unsigned long field,
+ u16 *clean_field)
+{
+ unsigned int index = ROL16(field, 6);
+ const struct evmcs_field *evmcs_field;
+
+ if (unlikely(index >= ARRAY_SIZE(vmcs_field_to_evmcs_1))) {
+ WARN_ONCE(1, "KVM: accessing unsupported EVMCS field %lx\n",
+ field);
+ return -ENOENT;
+ }
+
+ evmcs_field = &vmcs_field_to_evmcs_1[index];
+
+ if (clean_field)
+ *clean_field = evmcs_field->clean_field;
+
+ return evmcs_field->offset;
+}
+
+#undef ROL16
+
+#endif /* __KVM_X86_VMX_EVMCS_H */
diff --git a/arch/x86/kvm/vmx/vmx_shadow_fields.h b/arch/x86/kvm/vmx/vmx_shadow_fields.h
new file mode 100644
index 000000000000..cd0c75f6d037
--- /dev/null
+++ b/arch/x86/kvm/vmx/vmx_shadow_fields.h
@@ -0,0 +1,77 @@
+#ifndef SHADOW_FIELD_RO
+#define SHADOW_FIELD_RO(x)
+#endif
+#ifndef SHADOW_FIELD_RW
+#define SHADOW_FIELD_RW(x)
+#endif
+
+/*
+ * We do NOT shadow fields that are modified when L0
+ * traps and emulates any vmx instruction (e.g. VMPTRLD,
+ * VMXON...) executed by L1.
+ * For example, VM_INSTRUCTION_ERROR is read
+ * by L1 if a vmx instruction fails (part of the error path).
+ * Note the code assumes this logic. If for some reason
+ * we start shadowing these fields then we need to
+ * force a shadow sync when L0 emulates vmx instructions
+ * (e.g. force a sync if VM_INSTRUCTION_ERROR is modified
+ * by nested_vmx_failValid)
+ *
+ * When adding or removing fields here, note that shadowed
+ * fields must always be synced by prepare_vmcs02, not just
+ * prepare_vmcs02_full.
+ */
+
+/*
+ * Keeping the fields ordered by size is an attempt at improving
+ * branch prediction in vmcs_read_any and vmcs_write_any.
+ */
+
+/* 16-bits */
+SHADOW_FIELD_RW(GUEST_CS_SELECTOR)
+SHADOW_FIELD_RW(GUEST_INTR_STATUS)
+SHADOW_FIELD_RW(GUEST_PML_INDEX)
+SHADOW_FIELD_RW(HOST_FS_SELECTOR)
+SHADOW_FIELD_RW(HOST_GS_SELECTOR)
+
+/* 32-bits */
+SHADOW_FIELD_RO(VM_EXIT_REASON)
+SHADOW_FIELD_RO(VM_EXIT_INTR_INFO)
+SHADOW_FIELD_RO(VM_EXIT_INSTRUCTION_LEN)
+SHADOW_FIELD_RO(IDT_VECTORING_INFO_FIELD)
+SHADOW_FIELD_RO(IDT_VECTORING_ERROR_CODE)
+SHADOW_FIELD_RO(VM_EXIT_INTR_ERROR_CODE)
+SHADOW_FIELD_RW(CPU_BASED_VM_EXEC_CONTROL)
+SHADOW_FIELD_RW(EXCEPTION_BITMAP)
+SHADOW_FIELD_RW(VM_ENTRY_EXCEPTION_ERROR_CODE)
+SHADOW_FIELD_RW(VM_ENTRY_INTR_INFO_FIELD)
+SHADOW_FIELD_RW(VM_ENTRY_INSTRUCTION_LEN)
+SHADOW_FIELD_RW(TPR_THRESHOLD)
+SHADOW_FIELD_RW(GUEST_CS_LIMIT)
+SHADOW_FIELD_RW(GUEST_CS_AR_BYTES)
+SHADOW_FIELD_RW(GUEST_INTERRUPTIBILITY_INFO)
+SHADOW_FIELD_RW(VMX_PREEMPTION_TIMER_VALUE)
+
+/* Natural width */
+SHADOW_FIELD_RO(EXIT_QUALIFICATION)
+SHADOW_FIELD_RO(GUEST_LINEAR_ADDRESS)
+SHADOW_FIELD_RW(GUEST_RIP)
+SHADOW_FIELD_RW(GUEST_RSP)
+SHADOW_FIELD_RW(GUEST_CR0)
+SHADOW_FIELD_RW(GUEST_CR3)
+SHADOW_FIELD_RW(GUEST_CR4)
+SHADOW_FIELD_RW(GUEST_RFLAGS)
+SHADOW_FIELD_RW(GUEST_CS_BASE)
+SHADOW_FIELD_RW(GUEST_ES_BASE)
+SHADOW_FIELD_RW(CR0_GUEST_HOST_MASK)
+SHADOW_FIELD_RW(CR0_READ_SHADOW)
+SHADOW_FIELD_RW(CR4_READ_SHADOW)
+SHADOW_FIELD_RW(HOST_FS_BASE)
+SHADOW_FIELD_RW(HOST_GS_BASE)
+
+/* 64-bit */
+SHADOW_FIELD_RO(GUEST_PHYSICAL_ADDRESS)
+SHADOW_FIELD_RO(GUEST_PHYSICAL_ADDRESS_HIGH)
+
+#undef SHADOW_FIELD_RO
+#undef SHADOW_FIELD_RW
diff --git a/arch/x86/kvm/vmx_evmcs.h b/arch/x86/kvm/vmx_evmcs.h
deleted file mode 100644
index 210a884090ad..000000000000
--- a/arch/x86/kvm/vmx_evmcs.h
+++ /dev/null
@@ -1,324 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __KVM_X86_VMX_EVMCS_H
-#define __KVM_X86_VMX_EVMCS_H
-
-#include <asm/hyperv-tlfs.h>
-
-#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
-#define EVMCS1_OFFSET(x) offsetof(struct hv_enlightened_vmcs, x)
-#define EVMCS1_FIELD(number, name, clean_field)[ROL16(number, 6)] = \
- {EVMCS1_OFFSET(name), clean_field}
-
-struct evmcs_field {
- u16 offset;
- u16 clean_field;
-};
-
-static const struct evmcs_field vmcs_field_to_evmcs_1[] = {
- /* 64 bit rw */
- EVMCS1_FIELD(GUEST_RIP, guest_rip,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(GUEST_RSP, guest_rsp,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_BASIC),
- EVMCS1_FIELD(GUEST_RFLAGS, guest_rflags,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_BASIC),
- EVMCS1_FIELD(HOST_IA32_PAT, host_ia32_pat,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_IA32_EFER, host_ia32_efer,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_CR0, host_cr0,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_CR3, host_cr3,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_CR4, host_cr4,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_IA32_SYSENTER_ESP, host_ia32_sysenter_esp,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_RIP, host_rip,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(IO_BITMAP_A, io_bitmap_a,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_IO_BITMAP),
- EVMCS1_FIELD(IO_BITMAP_B, io_bitmap_b,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_IO_BITMAP),
- EVMCS1_FIELD(MSR_BITMAP, msr_bitmap,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP),
- EVMCS1_FIELD(GUEST_ES_BASE, guest_es_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_CS_BASE, guest_cs_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_SS_BASE, guest_ss_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_DS_BASE, guest_ds_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_FS_BASE, guest_fs_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_GS_BASE, guest_gs_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_LDTR_BASE, guest_ldtr_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_TR_BASE, guest_tr_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_GDTR_BASE, guest_gdtr_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_IDTR_BASE, guest_idtr_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(TSC_OFFSET, tsc_offset,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP2),
- EVMCS1_FIELD(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP2),
- EVMCS1_FIELD(VMCS_LINK_POINTER, vmcs_link_pointer,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_IA32_PAT, guest_ia32_pat,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_IA32_EFER, guest_ia32_efer,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_PDPTR0, guest_pdptr0,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_PDPTR1, guest_pdptr1,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_PDPTR2, guest_pdptr2,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_PDPTR3, guest_pdptr3,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
- EVMCS1_FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
- EVMCS1_FIELD(CR0_READ_SHADOW, cr0_read_shadow,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
- EVMCS1_FIELD(CR4_READ_SHADOW, cr4_read_shadow,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
- EVMCS1_FIELD(GUEST_CR0, guest_cr0,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
- EVMCS1_FIELD(GUEST_CR3, guest_cr3,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
- EVMCS1_FIELD(GUEST_CR4, guest_cr4,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
- EVMCS1_FIELD(GUEST_DR7, guest_dr7,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CRDR),
- EVMCS1_FIELD(HOST_FS_BASE, host_fs_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
- EVMCS1_FIELD(HOST_GS_BASE, host_gs_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
- EVMCS1_FIELD(HOST_TR_BASE, host_tr_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
- EVMCS1_FIELD(HOST_GDTR_BASE, host_gdtr_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
- EVMCS1_FIELD(HOST_IDTR_BASE, host_idtr_base,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
- EVMCS1_FIELD(HOST_RSP, host_rsp,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER),
- EVMCS1_FIELD(EPT_POINTER, ept_pointer,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_XLAT),
- EVMCS1_FIELD(GUEST_BNDCFGS, guest_bndcfgs,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(XSS_EXIT_BITMAP, xss_exit_bitmap,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP2),
-
- /* 64 bit read only */
- EVMCS1_FIELD(GUEST_PHYSICAL_ADDRESS, guest_physical_address,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(EXIT_QUALIFICATION, exit_qualification,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- /*
- * Not defined in KVM:
- *
- * EVMCS1_FIELD(0x00006402, exit_io_instruction_ecx,
- * HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE);
- * EVMCS1_FIELD(0x00006404, exit_io_instruction_esi,
- * HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE);
- * EVMCS1_FIELD(0x00006406, exit_io_instruction_esi,
- * HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE);
- * EVMCS1_FIELD(0x00006408, exit_io_instruction_eip,
- * HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE);
- */
- EVMCS1_FIELD(GUEST_LINEAR_ADDRESS, guest_linear_address,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
-
- /*
- * No mask defined in the spec as Hyper-V doesn't currently support
- * these. Future proof by resetting the whole clean field mask on
- * access.
- */
- EVMCS1_FIELD(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(CR3_TARGET_VALUE0, cr3_target_value0,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(CR3_TARGET_VALUE1, cr3_target_value1,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(CR3_TARGET_VALUE2, cr3_target_value2,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(CR3_TARGET_VALUE3, cr3_target_value3,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
-
- /* 32 bit rw */
- EVMCS1_FIELD(TPR_THRESHOLD, tpr_threshold,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(GUEST_INTERRUPTIBILITY_INFO, guest_interruptibility_info,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_BASIC),
- EVMCS1_FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_PROC),
- EVMCS1_FIELD(EXCEPTION_BITMAP, exception_bitmap,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_EXCPN),
- EVMCS1_FIELD(VM_ENTRY_CONTROLS, vm_entry_controls,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_ENTRY),
- EVMCS1_FIELD(VM_ENTRY_INTR_INFO_FIELD, vm_entry_intr_info_field,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_EVENT),
- EVMCS1_FIELD(VM_ENTRY_EXCEPTION_ERROR_CODE,
- vm_entry_exception_error_code,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_EVENT),
- EVMCS1_FIELD(VM_ENTRY_INSTRUCTION_LEN, vm_entry_instruction_len,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_EVENT),
- EVMCS1_FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP1),
- EVMCS1_FIELD(VM_EXIT_CONTROLS, vm_exit_controls,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP1),
- EVMCS1_FIELD(SECONDARY_VM_EXEC_CONTROL, secondary_vm_exec_control,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_GRP1),
- EVMCS1_FIELD(GUEST_ES_LIMIT, guest_es_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_CS_LIMIT, guest_cs_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_SS_LIMIT, guest_ss_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_DS_LIMIT, guest_ds_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_FS_LIMIT, guest_fs_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_GS_LIMIT, guest_gs_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_LDTR_LIMIT, guest_ldtr_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_TR_LIMIT, guest_tr_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_GDTR_LIMIT, guest_gdtr_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_IDTR_LIMIT, guest_idtr_limit,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_ES_AR_BYTES, guest_es_ar_bytes,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_CS_AR_BYTES, guest_cs_ar_bytes,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_SS_AR_BYTES, guest_ss_ar_bytes,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_DS_AR_BYTES, guest_ds_ar_bytes,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_FS_AR_BYTES, guest_fs_ar_bytes,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_GS_AR_BYTES, guest_gs_ar_bytes,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_LDTR_AR_BYTES, guest_ldtr_ar_bytes,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_TR_AR_BYTES, guest_tr_ar_bytes,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_ACTIVITY_STATE, guest_activity_state,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
- EVMCS1_FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1),
-
- /* 32 bit read only */
- EVMCS1_FIELD(VM_INSTRUCTION_ERROR, vm_instruction_error,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(VM_EXIT_REASON, vm_exit_reason,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(VM_EXIT_INTR_INFO, vm_exit_intr_info,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(VM_EXIT_INTR_ERROR_CODE, vm_exit_intr_error_code,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(IDT_VECTORING_INFO_FIELD, idt_vectoring_info_field,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(IDT_VECTORING_ERROR_CODE, idt_vectoring_error_code,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(VM_EXIT_INSTRUCTION_LEN, vm_exit_instruction_len,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
- EVMCS1_FIELD(VMX_INSTRUCTION_INFO, vmx_instruction_info,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE),
-
- /* No mask defined in the spec (not used) */
- EVMCS1_FIELD(PAGE_FAULT_ERROR_CODE_MASK, page_fault_error_code_mask,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(PAGE_FAULT_ERROR_CODE_MATCH, page_fault_error_code_match,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(CR3_TARGET_COUNT, cr3_target_count,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(VM_EXIT_MSR_STORE_COUNT, vm_exit_msr_store_count,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(VM_EXIT_MSR_LOAD_COUNT, vm_exit_msr_load_count,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
- EVMCS1_FIELD(VM_ENTRY_MSR_LOAD_COUNT, vm_entry_msr_load_count,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL),
-
- /* 16 bit rw */
- EVMCS1_FIELD(HOST_ES_SELECTOR, host_es_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_CS_SELECTOR, host_cs_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_SS_SELECTOR, host_ss_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_DS_SELECTOR, host_ds_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_FS_SELECTOR, host_fs_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_GS_SELECTOR, host_gs_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(HOST_TR_SELECTOR, host_tr_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_GRP1),
- EVMCS1_FIELD(GUEST_ES_SELECTOR, guest_es_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_CS_SELECTOR, guest_cs_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_SS_SELECTOR, guest_ss_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_DS_SELECTOR, guest_ds_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_FS_SELECTOR, guest_fs_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_GS_SELECTOR, guest_gs_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(GUEST_TR_SELECTOR, guest_tr_selector,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP2),
- EVMCS1_FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id,
- HV_VMX_ENLIGHTENED_CLEAN_FIELD_CONTROL_XLAT),
-};
-
-static __always_inline int get_evmcs_offset(unsigned long field,
- u16 *clean_field)
-{
- unsigned int index = ROL16(field, 6);
- const struct evmcs_field *evmcs_field;
-
- if (unlikely(index >= ARRAY_SIZE(vmcs_field_to_evmcs_1))) {
- WARN_ONCE(1, "KVM: accessing unsupported EVMCS field %lx\n",
- field);
- return -ENOENT;
- }
-
- evmcs_field = &vmcs_field_to_evmcs_1[index];
-
- if (clean_field)
- *clean_field = evmcs_field->clean_field;
-
- return evmcs_field->offset;
-}
-
-#undef ROL16
-
-#endif /* __KVM_X86_VMX_EVMCS_H */
diff --git a/arch/x86/kvm/vmx_shadow_fields.h b/arch/x86/kvm/vmx_shadow_fields.h
deleted file mode 100644
index cd0c75f6d037..000000000000
--- a/arch/x86/kvm/vmx_shadow_fields.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef SHADOW_FIELD_RO
-#define SHADOW_FIELD_RO(x)
-#endif
-#ifndef SHADOW_FIELD_RW
-#define SHADOW_FIELD_RW(x)
-#endif
-
-/*
- * We do NOT shadow fields that are modified when L0
- * traps and emulates any vmx instruction (e.g. VMPTRLD,
- * VMXON...) executed by L1.
- * For example, VM_INSTRUCTION_ERROR is read
- * by L1 if a vmx instruction fails (part of the error path).
- * Note the code assumes this logic. If for some reason
- * we start shadowing these fields then we need to
- * force a shadow sync when L0 emulates vmx instructions
- * (e.g. force a sync if VM_INSTRUCTION_ERROR is modified
- * by nested_vmx_failValid)
- *
- * When adding or removing fields here, note that shadowed
- * fields must always be synced by prepare_vmcs02, not just
- * prepare_vmcs02_full.
- */
-
-/*
- * Keeping the fields ordered by size is an attempt at improving
- * branch prediction in vmcs_read_any and vmcs_write_any.
- */
-
-/* 16-bits */
-SHADOW_FIELD_RW(GUEST_CS_SELECTOR)
-SHADOW_FIELD_RW(GUEST_INTR_STATUS)
-SHADOW_FIELD_RW(GUEST_PML_INDEX)
-SHADOW_FIELD_RW(HOST_FS_SELECTOR)
-SHADOW_FIELD_RW(HOST_GS_SELECTOR)
-
-/* 32-bits */
-SHADOW_FIELD_RO(VM_EXIT_REASON)
-SHADOW_FIELD_RO(VM_EXIT_INTR_INFO)
-SHADOW_FIELD_RO(VM_EXIT_INSTRUCTION_LEN)
-SHADOW_FIELD_RO(IDT_VECTORING_INFO_FIELD)
-SHADOW_FIELD_RO(IDT_VECTORING_ERROR_CODE)
-SHADOW_FIELD_RO(VM_EXIT_INTR_ERROR_CODE)
-SHADOW_FIELD_RW(CPU_BASED_VM_EXEC_CONTROL)
-SHADOW_FIELD_RW(EXCEPTION_BITMAP)
-SHADOW_FIELD_RW(VM_ENTRY_EXCEPTION_ERROR_CODE)
-SHADOW_FIELD_RW(VM_ENTRY_INTR_INFO_FIELD)
-SHADOW_FIELD_RW(VM_ENTRY_INSTRUCTION_LEN)
-SHADOW_FIELD_RW(TPR_THRESHOLD)
-SHADOW_FIELD_RW(GUEST_CS_LIMIT)
-SHADOW_FIELD_RW(GUEST_CS_AR_BYTES)
-SHADOW_FIELD_RW(GUEST_INTERRUPTIBILITY_INFO)
-SHADOW_FIELD_RW(VMX_PREEMPTION_TIMER_VALUE)
-
-/* Natural width */
-SHADOW_FIELD_RO(EXIT_QUALIFICATION)
-SHADOW_FIELD_RO(GUEST_LINEAR_ADDRESS)
-SHADOW_FIELD_RW(GUEST_RIP)
-SHADOW_FIELD_RW(GUEST_RSP)
-SHADOW_FIELD_RW(GUEST_CR0)
-SHADOW_FIELD_RW(GUEST_CR3)
-SHADOW_FIELD_RW(GUEST_CR4)
-SHADOW_FIELD_RW(GUEST_RFLAGS)
-SHADOW_FIELD_RW(GUEST_CS_BASE)
-SHADOW_FIELD_RW(GUEST_ES_BASE)
-SHADOW_FIELD_RW(CR0_GUEST_HOST_MASK)
-SHADOW_FIELD_RW(CR0_READ_SHADOW)
-SHADOW_FIELD_RW(CR4_READ_SHADOW)
-SHADOW_FIELD_RW(HOST_FS_BASE)
-SHADOW_FIELD_RW(HOST_GS_BASE)
-
-/* 64-bit */
-SHADOW_FIELD_RO(GUEST_PHYSICAL_ADDRESS)
-SHADOW_FIELD_RO(GUEST_PHYSICAL_ADDRESS_HIGH)
-
-#undef SHADOW_FIELD_RO
-#undef SHADOW_FIELD_RW
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8fe615df8e5b..ff7ec9b507e3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3637,12 +3637,11 @@ static void kvm_vcpu_ioctl_x86_get_debugregs(struct kvm_vcpu *vcpu,
{
unsigned long val;
+ memset(dbgregs, 0, sizeof(*dbgregs));
memcpy(dbgregs->db, vcpu->arch.db, sizeof(vcpu->arch.db));
kvm_get_dr(vcpu, 6, &val);
dbgregs->dr6 = val;
dbgregs->dr7 = vcpu->arch.dr7;
- dbgregs->flags = 0;
- memset(&dbgregs->reserved, 0, sizeof(dbgregs->reserved));
}
static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 6d110a1c090d..4a7da8f744e0 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -3112,7 +3112,7 @@ int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
*/
if (spd > 1)
mask &= (1 << (spd - 1)) - 1;
- else
+ else if (link->sata_spd)
return -EINVAL;
/* were we already at the bottom? */
diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c
index d3fb350dc9ee..bf4db708f0bd 100644
--- a/drivers/bus/sunxi-rsb.c
+++ b/drivers/bus/sunxi-rsb.c
@@ -783,7 +783,13 @@ static int __init sunxi_rsb_init(void)
return ret;
}
- return platform_driver_register(&sunxi_rsb_driver);
+ ret = platform_driver_register(&sunxi_rsb_driver);
+ if (ret) {
+ bus_unregister(&sunxi_rsb_bus);
+ return ret;
+ }
+
+ return 0;
}
module_init(sunxi_rsb_init);
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index bf03455b6fc2..0d628aa11be5 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -831,8 +831,10 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
r = container_of(resource, struct inbound_transaction_resource,
resource);
- if (is_fcp_request(r->request))
+ if (is_fcp_request(r->request)) {
+ kfree(r->data);
goto out;
+ }
if (a->length != fw_get_response_length(r->request)) {
ret = -EINVAL;
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index e0889922cc6d..a1ef30fca360 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -35,7 +35,7 @@ int __init efi_memattr_init(void)
return -ENOMEM;
}
- if (tbl->version > 1) {
+ if (tbl->version > 2) {
pr_warn("Unexpected EFI Memory Attributes table version %d\n",
tbl->version);
goto unmap;
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index e76ad020a542..61ab462fd94c 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -82,7 +82,7 @@ enum {
#define DEFAULT_SCL_RATE (100 * 1000) /* Hz */
/**
- * struct i2c_spec_values:
+ * struct i2c_spec_values - I2C specification values for various modes
* @min_hold_start_ns: min hold time (repeated) START condition
* @min_low_ns: min LOW period of the SCL clock
* @min_high_ns: min HIGH period of the SCL cloc
@@ -138,7 +138,7 @@ static const struct i2c_spec_values fast_mode_plus_spec = {
};
/**
- * struct rk3x_i2c_calced_timings:
+ * struct rk3x_i2c_calced_timings - calculated V1 timings
* @div_low: Divider output for low
* @div_high: Divider output for high
* @tuning: Used to adjust setup/hold data time,
@@ -161,7 +161,7 @@ enum rk3x_i2c_state {
};
/**
- * struct rk3x_i2c_soc_data:
+ * struct rk3x_i2c_soc_data - SOC-specific data
* @grf_offset: offset inside the grf regmap for setting the i2c type
* @calc_timings: Callback function for i2c timing information calculated
*/
@@ -241,7 +241,8 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c)
}
/**
- * Generate a START condition, which triggers a REG_INT_START interrupt.
+ * rk3x_i2c_start - Generate a START condition, which triggers a REG_INT_START interrupt.
+ * @i2c: target controller data
*/
static void rk3x_i2c_start(struct rk3x_i2c *i2c)
{
@@ -260,8 +261,8 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)
}
/**
- * Generate a STOP condition, which triggers a REG_INT_STOP interrupt.
- *
+ * rk3x_i2c_stop - Generate a STOP condition, which triggers a REG_INT_STOP interrupt.
+ * @i2c: target controller data
* @error: Error code to return in rk3x_i2c_xfer
*/
static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error)
@@ -300,7 +301,8 @@ static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error)
}
/**
- * Setup a read according to i2c->msg
+ * rk3x_i2c_prepare_read - Setup a read according to i2c->msg
+ * @i2c: target controller data
*/
static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c)
{
@@ -331,7 +333,8 @@ static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c)
}
/**
- * Fill the transmit buffer with data from i2c->msg
+ * rk3x_i2c_fill_transmit_buf - Fill the transmit buffer with data from i2c->msg
+ * @i2c: target controller data
*/
static void rk3x_i2c_fill_transmit_buf(struct rk3x_i2c *i2c)
{
@@ -534,11 +537,10 @@ static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id)
}
/**
- * Get timing values of I2C specification
- *
+ * rk3x_i2c_get_spec - Get timing values of I2C specification
* @speed: Desired SCL frequency
*
- * Returns: Matched i2c spec values.
+ * Return: Matched i2c_spec_values.
*/
static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
{
@@ -551,13 +553,12 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
}
/**
- * Calculate divider values for desired SCL frequency
- *
+ * rk3x_i2c_v0_calc_timings - Calculate divider values for desired SCL frequency
* @clk_rate: I2C input clock rate
* @t: Known I2C timing information
* @t_calc: Caculated rk3x private timings that would be written into regs
*
- * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case
* a best-effort divider value is returned in divs. If the target rate is
* too high, we silently use the highest possible rate.
*/
@@ -712,13 +713,12 @@ static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
}
/**
- * Calculate timing values for desired SCL frequency
- *
+ * rk3x_i2c_v1_calc_timings - Calculate timing values for desired SCL frequency
* @clk_rate: I2C input clock rate
* @t: Known I2C timing information
* @t_calc: Caculated rk3x private timings that would be written into regs
*
- * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case
* a best-effort divider value is returned in divs. If the target rate is
* too high, we silently use the highest possible rate.
* The following formulas are v1's method to calculate timings.
@@ -962,14 +962,14 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
}
/**
- * Setup I2C registers for an I2C operation specified by msgs, num.
- *
- * Must be called with i2c->lock held.
- *
+ * rk3x_i2c_setup - Setup I2C registers for an I2C operation specified by msgs, num.
+ * @i2c: target controller data
* @msgs: I2C msgs to process
* @num: Number of msgs
*
- * returns: Number of I2C msgs processed or negative in case of error
+ * Must be called with i2c->lock held.
+ *
+ * Return: Number of I2C msgs processed or negative in case of error
*/
static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num)
{
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 32d5438d4519..d8506a83ba08 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -292,6 +292,7 @@ static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
hid_sensor_convert_timestamp(
&accel_state->common_attributes,
*(int64_t *)raw_data);
+ ret = 0;
break;
default:
break;
diff --git a/drivers/iio/adc/berlin2-adc.c b/drivers/iio/adc/berlin2-adc.c
index 72d8fa94ab31..86fdfea32979 100644
--- a/drivers/iio/adc/berlin2-adc.c
+++ b/drivers/iio/adc/berlin2-adc.c
@@ -289,8 +289,10 @@ static int berlin2_adc_probe(struct platform_device *pdev)
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
- if (!indio_dev)
+ if (!indio_dev) {
+ of_node_put(parent_np);
return -ENOMEM;
+ }
priv = iio_priv(indio_dev);
platform_set_drvdata(pdev, indio_dev);
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 1c492a7f4587..bb90b22b809c 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -1099,6 +1099,7 @@ static const struct of_device_id stm32_dfsdm_adc_match[] = {
},
{}
};
+MODULE_DEVICE_TABLE(of, stm32_dfsdm_adc_match);
static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
{
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index 765aaee157e2..3007cfbf8491 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -71,6 +71,18 @@
#define TWL6030_GPADCS BIT(1)
#define TWL6030_GPADCR BIT(0)
+#define USB_VBUS_CTRL_SET 0x04
+#define USB_ID_CTRL_SET 0x06
+
+#define TWL6030_MISC1 0xE4
+#define VBUS_MEAS 0x01
+#define ID_MEAS 0x01
+
+#define VAC_MEAS 0x04
+#define VBAT_MEAS 0x02
+#define BB_MEAS 0x01
+
+
/**
* struct twl6030_chnl_calib - channel calibration
* @gain: slope coefficient for ideal curve
@@ -943,6 +955,26 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
return ret;
}
+ ret = twl_i2c_write_u8(TWL_MODULE_USB, VBUS_MEAS, USB_VBUS_CTRL_SET);
+ if (ret < 0) {
+ dev_err(dev, "failed to wire up inputs\n");
+ return ret;
+ }
+
+ ret = twl_i2c_write_u8(TWL_MODULE_USB, ID_MEAS, USB_ID_CTRL_SET);
+ if (ret < 0) {
+ dev_err(dev, "failed to wire up inputs\n");
+ return ret;
+ }
+
+ ret = twl_i2c_write_u8(TWL6030_MODULE_ID0,
+ VBAT_MEAS | BB_MEAS | VAC_MEAS,
+ TWL6030_MISC1);
+ if (ret < 0) {
+ dev_err(dev, "failed to wire up inputs\n");
+ return ret;
+ }
+
indio_dev->name = DRIVER_NAME;
indio_dev->dev.parent = dev;
indio_dev->info = &twl6030_gpadc_iio_info;
diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
index be31faf6cc62..071d39c614b2 100644
--- a/drivers/infiniband/hw/hfi1/file_ops.c
+++ b/drivers/infiniband/hw/hfi1/file_ops.c
@@ -1361,12 +1361,15 @@ static int user_exp_rcv_setup(struct hfi1_filedata *fd, unsigned long arg,
addr = arg + offsetof(struct hfi1_tid_info, tidcnt);
if (copy_to_user((void __user *)addr, &tinfo.tidcnt,
sizeof(tinfo.tidcnt)))
- return -EFAULT;
+ ret = -EFAULT;
addr = arg + offsetof(struct hfi1_tid_info, length);
- if (copy_to_user((void __user *)addr, &tinfo.length,
+ if (!ret && copy_to_user((void __user *)addr, &tinfo.length,
sizeof(tinfo.length)))
ret = -EFAULT;
+
+ if (ret)
+ hfi1_user_exp_rcv_invalid(fd, &tinfo);
}
return ret;
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index ee0b0a7237ad..b2ab20c16cc7 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -71,25 +71,84 @@ static inline void i8042_write_command(int val)
#include <linux/dmi.h>
-static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
+#define SERIO_QUIRK_NOKBD BIT(0)
+#define SERIO_QUIRK_NOAUX BIT(1)
+#define SERIO_QUIRK_NOMUX BIT(2)
+#define SERIO_QUIRK_FORCEMUX BIT(3)
+#define SERIO_QUIRK_UNLOCK BIT(4)
+#define SERIO_QUIRK_PROBE_DEFER BIT(5)
+#define SERIO_QUIRK_RESET_ALWAYS BIT(6)
+#define SERIO_QUIRK_RESET_NEVER BIT(7)
+#define SERIO_QUIRK_DIECT BIT(8)
+#define SERIO_QUIRK_DUMBKBD BIT(9)
+#define SERIO_QUIRK_NOLOOP BIT(10)
+#define SERIO_QUIRK_NOTIMEOUT BIT(11)
+#define SERIO_QUIRK_KBDRESET BIT(12)
+#define SERIO_QUIRK_DRITEK BIT(13)
+#define SERIO_QUIRK_NOPNP BIT(14)
+
+/* Quirk table for different mainboards. Options similar or identical to i8042
+ * module parameters.
+ * ORDERING IS IMPORTANT! The first match will be apllied and the rest ignored.
+ * This allows entries to overwrite vendor wide quirks on a per device basis.
+ * Where this is irrelevant, entries are sorted case sensitive by DMI_SYS_VENDOR
+ * and/or DMI_BOARD_VENDOR to make it easier to avoid dublicate entries.
+ */
+static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
{
- /*
- * Arima-Rioworks HDAMB -
- * AUX LOOP command does not raise AUX IRQ
- */
.matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"),
- DMI_MATCH(DMI_BOARD_NAME, "HDAMB"),
- DMI_MATCH(DMI_BOARD_VERSION, "Rev E"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* ASUS G1S */
.matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_BOARD_NAME, "G1S"),
- DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X750LN"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
+ },
+ {
+ /* Asus X450LCP */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_NEVER)
+ },
+ {
+ /* ASUS ZenBook UX425UA */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425UA"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_PROBE_DEFER | SERIO_QUIRK_RESET_NEVER)
+ },
+ {
+ /* ASUS ZenBook UM325UA */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_PROBE_DEFER | SERIO_QUIRK_RESET_NEVER)
+ },
+ /*
+ * On some Asus laptops, just running self tests cause problems.
+ */
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
+ },
+ .driver_data = (void *)(SERIO_QUIRK_RESET_NEVER)
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */
+ },
+ .driver_data = (void *)(SERIO_QUIRK_RESET_NEVER)
},
{
/* ASUS P65UP5 - AUX LOOP command does not raise AUX IRQ */
@@ -98,585 +157,681 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "P/I-P65UP5"),
DMI_MATCH(DMI_BOARD_VERSION, "REV 2.X"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
+ /* ASUS G1S */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "X750LN"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_BOARD_NAME, "G1S"),
+ DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
- DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
+ /* Acer Aspire 5710 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
- DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Dell Embedded Box PC 3000 */
+ /* Acer Aspire 7738 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Embedded Box PC 3000"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* OQO Model 01 */
+ /* Acer Aspire 5536 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* ULI EV4873 - AUX LOOP does not work properly */
+ /*
+ * Acer Aspire 5738z
+ * Touchpad stops working in mux mode when dis- + re-enabled
+ * with the touchpad enable/disable toggle hotkey
+ */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ULI"),
- DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Microsoft Virtual Machine */
+ /* Acer Aspire One 150 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /* Medion MAM 2070 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
- DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A114-31"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /* Medion Akoya E7225 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A314-31"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /* Blue FB5601 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "blue"),
- DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "M606"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-31"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /* Gigabyte M912 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "M912"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "01"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-132"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /* Gigabyte M1022M netbook */
.matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."),
- DMI_MATCH(DMI_BOARD_NAME, "M1022E"),
- DMI_MATCH(DMI_BOARD_VERSION, "1.02"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-332"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /* Gigabyte Spring Peak - defines wrong chassis type */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-432"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /* Gigabyte T1005 - defines wrong chassis type ("Other") */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate Spin B118-RN"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
+ /*
+ * Some Wistron based laptops need us to explicitly enable the 'Dritek
+ * keyboard extension' to make their extra keys start generating scancodes.
+ * Originally, this was just confined to older laptops, but a few Acer laptops
+ * have turned up in 2007 that also need this again.
+ */
{
- /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
+ /* Acer Aspire 5100 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
{
+ /* Acer Aspire 5610 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
{
+ /* Acer Aspire 5630 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
- DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
{
+ /* Acer Aspire 5650 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ByteSpeed LLC"),
- DMI_MATCH(DMI_PRODUCT_NAME, "ByteSpeed Laptop C15B"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
- { }
-};
-
-/*
- * Some Fujitsu notebooks are having trouble with touchpads if
- * active multiplexing mode is activated. Luckily they don't have
- * external PS/2 ports so we can safely disable it.
- * ... apparently some Toshibas don't like MUX mode either and
- * die horrible death on reboot.
- */
-static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
{
- /* Fujitsu Lifebook P7010/P7010D */
+ /* Acer Aspire 5680 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
{
- /* Fujitsu Lifebook P7010 */
+ /* Acer Aspire 5720 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
{
- /* Fujitsu Lifebook P5020D */
+ /* Acer Aspire 9110 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
{
- /* Fujitsu Lifebook S2000 */
+ /* Acer TravelMate 660 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
{
- /* Fujitsu Lifebook S6230 */
+ /* Acer TravelMate 2490 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
{
- /* Fujitsu Lifebook T725 laptop */
+ /* Acer TravelMate 4280 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"),
},
+ .driver_data = (void *)(SERIO_QUIRK_DRITEK)
},
{
- /* Fujitsu Lifebook U745 */
+ /* Amoi M636/A737 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Fujitsu T70H */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ByteSpeed LLC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ByteSpeed Laptop C15B"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Fujitsu-Siemens Lifebook T3010 */
+ /* Compal HEL80I */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"),
+ DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Fujitsu-Siemens Lifebook E4010 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Fujitsu-Siemens Amilo Pro 2010 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Fujitsu-Siemens Amilo Pro 2030 */
+ /* Advent 4211 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"),
+ DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /*
- * No data is coming from the touchscreen unless KBC
- * is in legacy mode.
- */
- /* Panasonic CF-29 */
+ /* Dell Embedded Box PC 3000 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
- DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Embedded Box PC 3000"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /*
- * HP Pavilion DV4017EA -
- * errors on MUX ports are reported without raising AUXDATA
- * causing "spurious NAK" messages.
- */
+ /* Dell XPS M1530 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /*
- * HP Pavilion ZT1000 -
- * like DV4017EA does not raise AUXERR for errors on MUX ports.
- */
+ /* Dell Vostro 1510 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /*
- * HP Pavilion DV4270ca -
- * like DV4017EA does not raise AUXERR for errors on MUX ports.
- */
+ /* Dell Vostro V13 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_NOTIMEOUT)
},
{
+ /* Dell Vostro 1320 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
+ /* Dell Vostro 1520 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
+ /* Dell Vostro 1720 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
+ },
+ {
+ /* Entroware Proteus */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Entroware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Proteus"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "EL07R4"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS)
},
+ /*
+ * Some Fujitsu notebooks are having trouble with touchpads if
+ * active multiplexing mode is activated. Luckily they don't have
+ * external PS/2 ports so we can safely disable it.
+ * ... apparently some Toshibas don't like MUX mode either and
+ * die horrible death on reboot.
+ */
{
+ /* Fujitsu Lifebook P7010/P7010D */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Sharp Actius MM20 */
+ /* Fujitsu Lifebook P5020D */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
- DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Sony Vaio FS-115b */
+ /* Fujitsu Lifebook S2000 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /*
- * Sony Vaio FZ-240E -
- * reset and GET ID commands issued via KBD port are
- * sometimes being delivered to AUX3.
- */
+ /* Fujitsu Lifebook S6230 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /*
- * Most (all?) VAIOs do not have external PS/2 ports nor
- * they implement active multiplexing properly, and
- * MUX discovery usually messes up keyboard/touchpad.
- */
+ /* Fujitsu Lifebook T725 laptop */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_BOARD_NAME, "VAIO"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_NOTIMEOUT)
},
{
- /* Amoi M636/A737 */
+ /* Fujitsu Lifebook U745 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."),
- DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Lenovo 3000 n100 */
+ /* Fujitsu T70H */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Lenovo XiaoXin Air 12 */
+ /* Fujitsu A544 laptop */
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "80UN"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)
},
{
+ /* Fujitsu AH544 laptop */
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)
+ },
+ {
+ /* Fujitsu U574 laptop */
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)
+ },
+ {
+ /* Fujitsu UH554 laptop */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)
+ },
+ {
+ /* Fujitsu Lifebook P7010 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
+ },
+ {
+ /* Fujitsu-Siemens Lifebook T3010 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Acer Aspire 5710 */
+ /* Fujitsu-Siemens Lifebook E4010 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Acer Aspire 7738 */
+ /* Fujitsu-Siemens Amilo Pro 2010 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Gericom Bellagio */
+ /* Fujitsu-Siemens Amilo Pro 2030 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
- DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* IBM 2656 */
+ /* Gigabyte M912 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
- DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M912"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "01"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Dell XPS M1530 */
+ /* Gigabyte Spring Peak - defines wrong chassis type */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Compal HEL80I */
+ /* Gigabyte T1005 - defines wrong chassis type ("Other") */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Dell Vostro 1510 */
+ /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
+ /*
+ * Some laptops need keyboard reset before probing for the trackpad to get
+ * it detected, initialised & finally work.
+ */
{
- /* Acer Aspire 5536 */
+ /* Gigabyte P35 v2 - Elantech touchpad */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"),
},
+ .driver_data = (void *)(SERIO_QUIRK_KBDRESET)
},
- {
- /* Dell Vostro V13 */
+ {
+ /* Aorus branded Gigabyte X3 Plus - Elantech touchpad */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X3"),
},
+ .driver_data = (void *)(SERIO_QUIRK_KBDRESET)
},
{
- /* Newer HP Pavilion dv4 models */
+ /* Gigabyte P34 - Elantech touchpad */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
},
+ .driver_data = (void *)(SERIO_QUIRK_KBDRESET)
},
{
- /* Asus X450LCP */
+ /* Gigabyte P57 - Elantech touchpad */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P57"),
},
+ .driver_data = (void *)(SERIO_QUIRK_KBDRESET)
},
{
- /* Avatar AVIU-145A6 */
+ /* Gericom Bellagio */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
- DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* TUXEDO BU1406 */
+ /* Gigabyte M1022M netbook */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
- DMI_MATCH(DMI_PRODUCT_NAME, "N24_25BU"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."),
+ DMI_MATCH(DMI_BOARD_NAME, "M1022E"),
+ DMI_MATCH(DMI_BOARD_VERSION, "1.02"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Lenovo LaVie Z */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo LaVie Z"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
/*
- * Acer Aspire 5738z
- * Touchpad stops working in mux mode when dis- + re-enabled
- * with the touchpad enable/disable toggle hotkey
+ * HP Pavilion DV4017EA -
+ * errors on MUX ports are reported without raising AUXDATA
+ * causing "spurious NAK" messages.
*/
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Entroware Proteus */
+ /*
+ * HP Pavilion ZT1000 -
+ * like DV4017EA does not raise AUXERR for errors on MUX ports.
+ */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Entroware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Proteus"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "EL07R4"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
- { }
-};
-
-static const struct dmi_system_id i8042_dmi_forcemux_table[] __initconst = {
{
/*
- * Sony Vaio VGN-CS series require MUX or the touch sensor
- * buttons will disturb touchpad operation
+ * HP Pavilion DV4270ca -
+ * like DV4017EA does not raise AUXERR for errors on MUX ports.
*/
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VGN-CS"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
- { }
-};
-
-/*
- * On some Asus laptops, just running self tests cause problems.
- */
-static const struct dmi_system_id i8042_dmi_noselftest_table[] = {
{
+ /* Newer HP Pavilion dv4 models */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
- },
- }, {
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_NOTIMEOUT)
},
- { }
-};
-static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
{
- /* MSI Wind U-100 */
+ /* IBM 2656 */
.matches = {
- DMI_MATCH(DMI_BOARD_NAME, "U-100"),
- DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+ DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* LG Electronics X110 */
+ /* Avatar AVIU-145A6 */
.matches = {
- DMI_MATCH(DMI_BOARD_NAME, "X110"),
- DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Acer Aspire One 150 */
+ /* Intel MBO Desktop D845PESV */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "D845PESV"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOPNP)
},
{
+ /*
+ * Intel NUC D54250WYK - does not have i8042 controller but
+ * declares PS/2 devices in DSDT.
+ */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A114-31"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "D54250WYK"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOPNP)
},
{
+ /* Lenovo 3000 n100 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A314-31"),
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
+ /* Lenovo XiaoXin Air 12 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-31"),
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "80UN"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
+ /* Lenovo LaVie Z */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-132"),
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo LaVie Z"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
+ /* Lenovo Ideapad U455 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-332"),
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
+ /* Lenovo ThinkPad L460 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-432"),
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L460"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
+ /* Lenovo ThinkPad Twist S230u */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate Spin B118-RN"),
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "33474HU"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /* Advent 4211 */
+ /* LG Electronics X110 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
+ DMI_MATCH(DMI_BOARD_NAME, "X110"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
/* Medion Akoya Mini E1210 */
@@ -684,6 +839,7 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
DMI_MATCH(DMI_PRODUCT_NAME, "E1210"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
/* Medion Akoya E1222 */
@@ -691,48 +847,62 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
DMI_MATCH(DMI_PRODUCT_NAME, "E122X"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
{
- /* Mivvy M310 */
+ /* MSI Wind U-100 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "N10"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+ DMI_MATCH(DMI_BOARD_NAME, "U-100"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOPNP)
},
{
- /* Dell Vostro 1320 */
+ /*
+ * No data is coming from the touchscreen unless KBC
+ * is in legacy mode.
+ */
+ /* Panasonic CF-29 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Dell Vostro 1520 */
+ /* Medion Akoya E7225 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Dell Vostro 1720 */
+ /* Microsoft Virtual Machine */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Lenovo Ideapad U455 */
+ /* Medion MAM 2070 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Lenovo ThinkPad L460 */
+ /* TUXEDO BU1406 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L460"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "N24_25BU"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
/* Clevo P650RS, 650RP6, Sager NP8152-S, and others */
@@ -740,282 +910,318 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
+ },
+ {
+ /* OQO Model 01 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Lenovo ThinkPad Twist S230u */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "33474HU"),
+ DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* Entroware Proteus */
+ /* Acer Aspire 5 A515 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Entroware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Proteus"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "EL07R4"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "PK"),
+ DMI_MATCH(DMI_BOARD_NAME, "Grumpy_PK"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOPNP)
},
- { }
-};
-
-#ifdef CONFIG_PNP
-static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = {
{
- /* Intel MBO Desktop D845PESV */
+ /* ULI EV4873 - AUX LOOP does not work properly */
.matches = {
- DMI_MATCH(DMI_BOARD_NAME, "D845PESV"),
- DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ULI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
/*
- * Intel NUC D54250WYK - does not have i8042 controller but
- * declares PS/2 devices in DSDT.
+ * Arima-Rioworks HDAMB -
+ * AUX LOOP command does not raise AUX IRQ
*/
.matches = {
- DMI_MATCH(DMI_BOARD_NAME, "D54250WYK"),
- DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"),
+ DMI_MATCH(DMI_BOARD_NAME, "HDAMB"),
+ DMI_MATCH(DMI_BOARD_VERSION, "Rev E"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
{
- /* MSI Wind U-100 */
+ /* Sharp Actius MM20 */
.matches = {
- DMI_MATCH(DMI_BOARD_NAME, "U-100"),
- DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+ DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Acer Aspire 5 A515 */
+ /*
+ * Sony Vaio FZ-240E -
+ * reset and GET ID commands issued via KBD port are
+ * sometimes being delivered to AUX3.
+ */
.matches = {
- DMI_MATCH(DMI_BOARD_NAME, "Grumpy_PK"),
- DMI_MATCH(DMI_BOARD_VENDOR, "PK"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
- { }
-};
-
-static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = {
{
+ /*
+ * Most (all?) VAIOs do not have external PS/2 ports nor
+ * they implement active multiplexing properly, and
+ * MUX discovery usually messes up keyboard/touchpad.
+ */
.matches = {
- DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "VAIO"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
+ /* Sony Vaio FS-115b */
.matches = {
- DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
+ /*
+ * Sony Vaio VGN-CS series require MUX or the touch sensor
+ * buttons will disturb touchpad operation
+ */
.matches = {
- DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-CS"),
},
+ .driver_data = (void *)(SERIO_QUIRK_FORCEMUX)
},
{
.matches = {
- DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
- { }
-};
-#endif
-
-static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
{
- /* Dell Vostro V13 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
{
- /* Newer HP Pavilion dv4 models */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX)
},
+ /*
+ * A lot of modern Clevo barebones have touchpad and/or keyboard issues
+ * after suspend fixable with nomux + reset + noloop + nopnp. Luckily,
+ * none of them have an external PS/2 port so this can safely be set for
+ * all of them. These two are based on a Clevo design, but have the
+ * board_name changed.
+ */
{
- /* Fujitsu A544 laptop */
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"),
+ DMI_MATCH(DMI_BOARD_NAME, "AURA1501"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
{
- /* Fujitsu AH544 laptop */
- /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"),
+ DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
{
- /* Fujitsu Lifebook T725 laptop */
+ /* Mivvy M310 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"),
+ DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "N10"),
},
+ .driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
},
+ /*
+ * Some laptops need keyboard reset before probing for the trackpad to get
+ * it detected, initialised & finally work.
+ */
{
- /* Fujitsu U574 laptop */
- /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
+ /* Schenker XMG C504 - Elantech touchpad */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
+ DMI_MATCH(DMI_SYS_VENDOR, "XMG"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "C504"),
},
+ .driver_data = (void *)(SERIO_QUIRK_KBDRESET)
},
{
- /* Fujitsu UH554 laptop */
+ /* Blue FB5601 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
- DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"),
+ DMI_MATCH(DMI_SYS_VENDOR, "blue"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "M606"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
- { }
-};
-
-/*
- * Some Wistron based laptops need us to explicitly enable the 'Dritek
- * keyboard extension' to make their extra keys start generating scancodes.
- * Originally, this was just confined to older laptops, but a few Acer laptops
- * have turned up in 2007 that also need this again.
- */
-static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = {
+ /*
+ * A lot of modern Clevo barebones have touchpad and/or keyboard issues
+ * after suspend fixable with nomux + reset + noloop + nopnp. Luckily,
+ * none of them have an external PS/2 port so this can safely be set for
+ * all of them.
+ * Clevo barebones come with board_vendor and/or system_vendor set to
+ * either the very generic string "Notebook" and/or a different value
+ * for each individual reseller. The only somewhat universal way to
+ * identify them is by board_name.
+ */
{
- /* Acer Aspire 5100 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
+ DMI_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
{
- /* Acer Aspire 5610 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
+ DMI_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
{
- /* Acer Aspire 5630 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),
+ DMI_MATCH(DMI_BOARD_NAME, "N140CU"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
{
- /* Acer Aspire 5650 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),
+ DMI_MATCH(DMI_BOARD_NAME, "N141CU"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
{
- /* Acer Aspire 5680 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),
+ DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
{
- /* Acer Aspire 5720 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
+ DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
+ /*
+ * At least one modern Clevo barebone has the touchpad connected both
+ * via PS/2 and i2c interface. This causes a race condition between the
+ * psmouse and i2c-hid driver. Since the full capability of the touchpad
+ * is available via the i2c interface and the device has no external
+ * PS/2 port, it is safe to just ignore all ps2 mouses here to avoid
+ * this issue. The known affected device is the
+ * TUXEDO InfinityBook S17 Gen6 / Clevo NS70MU which comes with one of
+ * the two different dmi strings below. NS50MU is not a typo!
+ */
{
- /* Acer Aspire 9110 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),
+ DMI_MATCH(DMI_BOARD_NAME, "NS50MU"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX |
+ SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP |
+ SERIO_QUIRK_NOPNP)
},
{
- /* Acer TravelMate 660 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
+ DMI_MATCH(DMI_BOARD_NAME, "NS50_70MU"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX |
+ SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP |
+ SERIO_QUIRK_NOPNP)
},
{
- /* Acer TravelMate 2490 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),
+ DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
{
- /* Acer TravelMate 4280 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"),
+ DMI_MATCH(DMI_BOARD_NAME, "PB50_70DFx,DDx"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
- { }
-};
-
-/*
- * Some laptops need keyboard reset before probing for the trackpad to get
- * it detected, initialised & finally work.
- */
-static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {
{
- /* Gigabyte P35 v2 - Elantech touchpad */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"),
+ DMI_MATCH(DMI_BOARD_NAME, "PCX0DX"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
- {
- /* Aorus branded Gigabyte X3 Plus - Elantech touchpad */
+ {
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "X3"),
+ DMI_MATCH(DMI_BOARD_NAME, "X170SM"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
{
- /* Gigabyte P34 - Elantech touchpad */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
+ DMI_MATCH(DMI_BOARD_NAME, "X170KM-G"),
},
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
+ { }
+};
+
+#ifdef CONFIG_PNP
+static const struct dmi_system_id i8042_dmi_laptop_table[] __initconst = {
{
- /* Gigabyte P57 - Elantech touchpad */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "P57"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
},
},
{
- /* Schenker XMG C504 - Elantech touchpad */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "XMG"),
- DMI_MATCH(DMI_PRODUCT_NAME, "C504"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */
},
},
- { }
-};
-
-static const struct dmi_system_id i8042_dmi_probe_defer_table[] __initconst = {
{
- /* ASUS ZenBook UX425UA */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425UA"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
},
},
{
- /* ASUS ZenBook UM325UA */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */
},
},
{ }
};
+#endif
#endif /* CONFIG_X86 */
@@ -1170,11 +1376,6 @@ static int __init i8042_pnp_init(void)
bool pnp_data_busted = false;
int err;
-#ifdef CONFIG_X86
- if (dmi_check_system(i8042_dmi_nopnp_table))
- i8042_nopnp = true;
-#endif
-
if (i8042_nopnp) {
pr_info("PNP detection disabled\n");
return 0;
@@ -1278,6 +1479,59 @@ static inline int i8042_pnp_init(void) { return 0; }
static inline void i8042_pnp_exit(void) { }
#endif /* CONFIG_PNP */
+
+#ifdef CONFIG_X86
+static void __init i8042_check_quirks(void)
+{
+ const struct dmi_system_id *device_quirk_info;
+ uintptr_t quirks;
+
+ device_quirk_info = dmi_first_match(i8042_dmi_quirk_table);
+ if (!device_quirk_info)
+ return;
+
+ quirks = (uintptr_t)device_quirk_info->driver_data;
+
+ if (quirks & SERIO_QUIRK_NOKBD)
+ i8042_nokbd = true;
+ if (quirks & SERIO_QUIRK_NOAUX)
+ i8042_noaux = true;
+ if (quirks & SERIO_QUIRK_NOMUX)
+ i8042_nomux = true;
+ if (quirks & SERIO_QUIRK_FORCEMUX)
+ i8042_nomux = false;
+ if (quirks & SERIO_QUIRK_UNLOCK)
+ i8042_unlock = true;
+ if (quirks & SERIO_QUIRK_PROBE_DEFER)
+ i8042_probe_defer = true;
+ /* Honor module parameter when value is not default */
+ if (i8042_reset == I8042_RESET_DEFAULT) {
+ if (quirks & SERIO_QUIRK_RESET_ALWAYS)
+ i8042_reset = I8042_RESET_ALWAYS;
+ if (quirks & SERIO_QUIRK_RESET_NEVER)
+ i8042_reset = I8042_RESET_NEVER;
+ }
+ if (quirks & SERIO_QUIRK_DIECT)
+ i8042_direct = true;
+ if (quirks & SERIO_QUIRK_DUMBKBD)
+ i8042_dumbkbd = true;
+ if (quirks & SERIO_QUIRK_NOLOOP)
+ i8042_noloop = true;
+ if (quirks & SERIO_QUIRK_NOTIMEOUT)
+ i8042_notimeout = true;
+ if (quirks & SERIO_QUIRK_KBDRESET)
+ i8042_kbdreset = true;
+ if (quirks & SERIO_QUIRK_DRITEK)
+ i8042_dritek = true;
+#ifdef CONFIG_PNP
+ if (quirks & SERIO_QUIRK_NOPNP)
+ i8042_nopnp = true;
+#endif
+}
+#else
+static inline void i8042_check_quirks(void) {}
+#endif
+
static int __init i8042_platform_init(void)
{
int retval;
@@ -1300,45 +1554,17 @@ static int __init i8042_platform_init(void)
i8042_kbd_irq = I8042_MAP_IRQ(1);
i8042_aux_irq = I8042_MAP_IRQ(12);
- retval = i8042_pnp_init();
- if (retval)
- return retval;
-
#if defined(__ia64__)
- i8042_reset = I8042_RESET_ALWAYS;
+ i8042_reset = I8042_RESET_ALWAYS;
#endif
-#ifdef CONFIG_X86
- /* Honor module parameter when value is not default */
- if (i8042_reset == I8042_RESET_DEFAULT) {
- if (dmi_check_system(i8042_dmi_reset_table))
- i8042_reset = I8042_RESET_ALWAYS;
-
- if (dmi_check_system(i8042_dmi_noselftest_table))
- i8042_reset = I8042_RESET_NEVER;
- }
-
- if (dmi_check_system(i8042_dmi_noloop_table))
- i8042_noloop = true;
-
- if (dmi_check_system(i8042_dmi_nomux_table))
- i8042_nomux = true;
-
- if (dmi_check_system(i8042_dmi_forcemux_table))
- i8042_nomux = false;
-
- if (dmi_check_system(i8042_dmi_notimeout_table))
- i8042_notimeout = true;
-
- if (dmi_check_system(i8042_dmi_dritek_table))
- i8042_dritek = true;
-
- if (dmi_check_system(i8042_dmi_kbdreset_table))
- i8042_kbdreset = true;
+ i8042_check_quirks();
- if (dmi_check_system(i8042_dmi_probe_defer_table))
- i8042_probe_defer = true;
+ retval = i8042_pnp_init();
+ if (retval)
+ return retval;
+#ifdef CONFIG_X86
/*
* A20 was already enabled during early kernel init. But some buggy
* BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 8aebdc4ff623..dd73e8e83c72 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -267,6 +267,12 @@ static void sdio_release_func(struct device *dev)
if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO))
sdio_free_func_cis(func);
+ /*
+ * We have now removed the link to the tuples in the
+ * card structure, so remove the reference.
+ */
+ put_device(&func->card->dev);
+
kfree(func->info);
kfree(func->tmpbuf);
kfree(func);
@@ -297,6 +303,12 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)
device_initialize(&func->dev);
+ /*
+ * We may link to tuples in the card structure,
+ * we need make sure we have a reference to it.
+ */
+ get_device(&func->card->dev);
+
func->dev.parent = &card->dev;
func->dev.bus = &sdio_bus_type;
func->dev.release = sdio_release_func;
@@ -350,10 +362,9 @@ int sdio_add_func(struct sdio_func *func)
*/
void sdio_remove_func(struct sdio_func *func)
{
- if (!sdio_func_present(func))
- return;
+ if (sdio_func_present(func))
+ device_del(&func->dev);
- device_del(&func->dev);
of_node_put(func->dev.of_node);
put_device(&func->dev);
}
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index dca72444b312..f741eb24c3de 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -387,12 +387,6 @@ int sdio_read_func_cis(struct sdio_func *func)
if (ret)
return ret;
- /*
- * Since we've linked to tuples in the card structure,
- * we must make sure we have a reference to it.
- */
- get_device(&func->card->dev);
-
/*
* Vendor/device id is optional for function CIS, so
* copy it from the card structure as needed.
@@ -418,11 +412,5 @@ void sdio_free_func_cis(struct sdio_func *func)
}
func->tuples = NULL;
-
- /*
- * We have now removed the link to the tuples in the
- * card structure, so remove the reference.
- */
- put_device(&func->card->dev);
}
diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma.c b/drivers/net/ethernet/broadcom/bgmac-bcma.c
index 77de92eb08b2..b880c0b964be 100644
--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
@@ -228,12 +228,12 @@ static int bgmac_probe(struct bcma_device *core)
bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
- if (ci->pkg == BCMA_PKG_ID_BCM47188 ||
- ci->pkg == BCMA_PKG_ID_BCM47186) {
+ if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) ||
+ (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188)) {
bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
}
- if (ci->pkg == BCMA_PKG_ID_BCM5358)
+ if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM5358)
bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII;
break;
case BCMA_CHIP_ID_BCM53573:
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index dc106212259a..d79281c6d915 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -6118,10 +6118,14 @@ int bnxt_reserve_rings(struct bnxt *bp)
netdev_err(bp->dev, "ring reservation/IRQ init failure rc: %d\n", rc);
return rc;
}
- if (tcs && (bp->tx_nr_rings_per_tc * tcs != bp->tx_nr_rings)) {
+ if (tcs && (bp->tx_nr_rings_per_tc * tcs !=
+ bp->tx_nr_rings - bp->tx_nr_rings_xdp)) {
netdev_err(bp->dev, "tx ring reservation failure\n");
netdev_reset_tc(bp->dev);
- bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
+ if (bp->tx_nr_rings_xdp)
+ bp->tx_nr_rings_per_tc = bp->tx_nr_rings_xdp;
+ else
+ bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
return -ENOMEM;
}
bp->num_stat_ctxs = bp->cp_nr_rings;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 8a5baaf403ae..795f8fe2570e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -2671,7 +2671,7 @@ static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
struct i40e_pf *pf = vsi->back;
if (i40e_enabled_xdp_vsi(vsi)) {
- int frame_size = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+ int frame_size = new_mtu + I40E_PACKET_HDR_PAD;
if (frame_size > i40e_max_xdp_frame_size(vsi))
return -EINVAL;
@@ -11834,6 +11834,8 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
}
br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+ if (!br_spec)
+ return -EINVAL;
nla_for_each_nested(attr, br_spec, rem) {
__u16 mode;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
index e436fa160c7d..59165c0560d7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
@@ -520,9 +520,9 @@ int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
return 0;
}
- val |= PPSCMDx(index, 0x2);
val |= TRGTMODSELx(index, 0x2);
val |= PPSEN0;
+ writel(val, ioaddr + MAC_PPS_CONTROL);
writel(cfg->start.tv_sec, ioaddr + MAC_PPSx_TARGET_TIME_SEC(index));
@@ -547,6 +547,7 @@ int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
writel(period - 1, ioaddr + MAC_PPSx_WIDTH(index));
/* Finally, activate it */
+ val |= PPSCMDx(index, 0x2);
writel(val, ioaddr + MAC_PPS_CONTROL);
return 0;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 9e040eb629ed..f57761a03622 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -518,7 +518,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst");
plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode");
- if (plat->force_thresh_dma_mode) {
+ if (plat->force_thresh_dma_mode && plat->force_sf_dma_mode) {
plat->force_sf_dma_mode = 0;
pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set.");
}
diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
index 7ceebbc4bcc2..75546829b86b 100644
--- a/drivers/net/phy/meson-gxl.c
+++ b/drivers/net/phy/meson-gxl.c
@@ -246,11 +246,26 @@ static struct phy_driver meson_gxl_phy[] = {
.config_intr = meson_gxl_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .read_mmd = genphy_read_mmd_unsupported,
+ .write_mmd = genphy_write_mmd_unsupported,
+ }, {
+ PHY_ID_MATCH_EXACT(0x01803301),
+ .name = "Meson G12A Internal PHY",
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_IS_INTERNAL,
+ .soft_reset = genphy_soft_reset,
+ .ack_interrupt = meson_gxl_ack_interrupt,
+ .config_intr = meson_gxl_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_mmd = genphy_read_mmd_unsupported,
+ .write_mmd = genphy_write_mmd_unsupported,
},
};
static struct mdio_device_id __maybe_unused meson_gxl_tbl[] = {
{ 0x01814400, 0xfffffff0 },
+ { PHY_ID_MATCH_VENDOR(0x01803301) },
{ }
};
diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c
index 0cc6993c279a..93ee909c7939 100644
--- a/drivers/net/usb/kalmia.c
+++ b/drivers/net/usb/kalmia.c
@@ -69,8 +69,8 @@ kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len,
init_msg, init_msg_len, &act_len, KALMIA_USB_TIMEOUT);
if (status != 0) {
netdev_err(dev->net,
- "Error sending init packet. Status %i, length %i\n",
- status, act_len);
+ "Error sending init packet. Status %i\n",
+ status);
return status;
}
else if (act_len != init_msg_len) {
@@ -87,8 +87,8 @@ kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len,
if (status != 0)
netdev_err(dev->net,
- "Error receiving init result. Status %i, length %i\n",
- status, act_len);
+ "Error receiving init result. Status %i\n",
+ status);
else if (act_len != expected_len)
netdev_err(dev->net, "Unexpected init result length: %i\n",
act_len);
diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c
index 6fe59373cba9..8bab7306e5a6 100644
--- a/drivers/net/usb/plusb.c
+++ b/drivers/net/usb/plusb.c
@@ -69,9 +69,7 @@
static inline int
pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
{
- return usbnet_read_cmd(dev, req,
- USB_DIR_IN | USB_TYPE_VENDOR |
- USB_RECIP_DEVICE,
+ return usbnet_write_cmd(dev, req, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
val, index, NULL, 0);
}
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
index 77e4d184bc99..68d128b895ab 100644
--- a/drivers/nvme/target/fc.c
+++ b/drivers/nvme/target/fc.c
@@ -1325,8 +1325,10 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport,
else {
queue = nvmet_fc_alloc_target_queue(iod->assoc, 0,
be16_to_cpu(rqst->assoc_cmd.sqsize));
- if (!queue)
+ if (!queue) {
ret = VERR_QUEUE_ALLOC_FAIL;
+ nvmet_fc_tgt_a_put(iod->assoc);
+ }
}
}
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
index 8dec302dc067..a95289b5e6bf 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
@@ -295,7 +295,7 @@ static int aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
int ret = 0;
if (!exprs)
- return true;
+ return -EINVAL;
while (*exprs && !ret) {
ret = aspeed_sig_expr_disable(*exprs, maps);
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index f9eb37bb3905..b786d9797f40 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -116,7 +116,7 @@ struct intel_pinctrl {
#define padgroup_offset(g, p) ((p) - (g)->base)
static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
- unsigned pin)
+ unsigned int pin)
{
struct intel_community *community;
int i;
@@ -134,7 +134,7 @@ static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
static const struct intel_padgroup *
intel_community_get_padgroup(const struct intel_community *community,
- unsigned pin)
+ unsigned int pin)
{
int i;
@@ -148,11 +148,11 @@ intel_community_get_padgroup(const struct intel_community *community,
return NULL;
}
-static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin,
- unsigned reg)
+static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl,
+ unsigned int pin, unsigned int reg)
{
const struct intel_community *community;
- unsigned padno;
+ unsigned int padno;
size_t nregs;
community = intel_get_community(pctrl, pin);
@@ -168,11 +168,11 @@ static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin,
return community->pad_regs + reg + padno * nregs * 4;
}
-static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
+static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned int pin)
{
const struct intel_community *community;
const struct intel_padgroup *padgrp;
- unsigned gpp, offset, gpp_offset;
+ unsigned int gpp, offset, gpp_offset;
void __iomem *padown;
community = intel_get_community(pctrl, pin);
@@ -193,11 +193,11 @@ static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
return !(readl(padown) & PADOWN_MASK(gpp_offset));
}
-static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned pin)
+static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned int pin)
{
const struct intel_community *community;
const struct intel_padgroup *padgrp;
- unsigned offset, gpp_offset;
+ unsigned int offset, gpp_offset;
void __iomem *hostown;
community = intel_get_community(pctrl, pin);
@@ -217,11 +217,11 @@ static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned pin)
return !(readl(hostown) & BIT(gpp_offset));
}
-static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
+static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned int pin)
{
struct intel_community *community;
const struct intel_padgroup *padgrp;
- unsigned offset, gpp_offset;
+ unsigned int offset, gpp_offset;
u32 value;
community = intel_get_community(pctrl, pin);
@@ -254,7 +254,7 @@ static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
return false;
}
-static bool intel_pad_usable(struct intel_pinctrl *pctrl, unsigned pin)
+static bool intel_pad_usable(struct intel_pinctrl *pctrl, unsigned int pin)
{
return intel_pad_owned_by_host(pctrl, pin) &&
!intel_pad_locked(pctrl, pin);
@@ -268,15 +268,15 @@ static int intel_get_groups_count(struct pinctrl_dev *pctldev)
}
static const char *intel_get_group_name(struct pinctrl_dev *pctldev,
- unsigned group)
+ unsigned int group)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->groups[group].name;
}
-static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
- const unsigned **pins, unsigned *npins)
+static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
+ const unsigned int **pins, unsigned int *npins)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -286,7 +286,7 @@ static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
}
static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
- unsigned pin)
+ unsigned int pin)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
void __iomem *padcfg;
@@ -345,7 +345,7 @@ static int intel_get_functions_count(struct pinctrl_dev *pctldev)
}
static const char *intel_get_function_name(struct pinctrl_dev *pctldev,
- unsigned function)
+ unsigned int function)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -353,9 +353,9 @@ static const char *intel_get_function_name(struct pinctrl_dev *pctldev,
}
static int intel_get_function_groups(struct pinctrl_dev *pctldev,
- unsigned function,
+ unsigned int function,
const char * const **groups,
- unsigned * const ngroups)
+ unsigned int * const ngroups)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -364,8 +364,8 @@ static int intel_get_function_groups(struct pinctrl_dev *pctldev,
return 0;
}
-static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
- unsigned group)
+static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int function, unsigned int group)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
const struct intel_pingroup *grp = &pctrl->soc->groups[group];
@@ -447,7 +447,7 @@ static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
- unsigned pin)
+ unsigned int pin)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
void __iomem *padcfg0;
@@ -485,7 +485,7 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
static int intel_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
- unsigned pin, bool input)
+ unsigned int pin, bool input)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
void __iomem *padcfg0;
@@ -510,7 +510,7 @@ static const struct pinmux_ops intel_pinmux_ops = {
.gpio_set_direction = intel_gpio_set_direction,
};
-static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+static int intel_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *config)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -599,11 +599,11 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
return 0;
}
-static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
+static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
unsigned long config)
{
- unsigned param = pinconf_to_config_param(config);
- unsigned arg = pinconf_to_config_argument(config);
+ unsigned int param = pinconf_to_config_param(config);
+ unsigned int arg = pinconf_to_config_argument(config);
const struct intel_community *community;
void __iomem *padcfg1;
unsigned long flags;
@@ -685,8 +685,8 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
return ret;
}
-static int intel_config_set_debounce(struct intel_pinctrl *pctrl, unsigned pin,
- unsigned debounce)
+static int intel_config_set_debounce(struct intel_pinctrl *pctrl,
+ unsigned int pin, unsigned int debounce)
{
void __iomem *padcfg0, *padcfg2;
unsigned long flags;
@@ -732,8 +732,8 @@ static int intel_config_set_debounce(struct intel_pinctrl *pctrl, unsigned pin,
return ret;
}
-static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin,
- unsigned long *configs, unsigned nconfigs)
+static int intel_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int nconfigs)
{
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
int i, ret;
@@ -790,7 +790,7 @@ static const struct pinctrl_desc intel_pinctrl_desc = {
* automatically translated to pinctrl pin number. This function can be
* used to find out the corresponding pinctrl pin.
*/
-static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset,
+static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned int offset,
const struct intel_community **community,
const struct intel_padgroup **padgrp)
{
@@ -824,7 +824,7 @@ static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset,
return -EINVAL;
}
-static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
+static int intel_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
void __iomem *reg;
@@ -846,7 +846,8 @@ static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
return !!(padcfg0 & PADCFG0_GPIORXSTATE);
}
-static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static void intel_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
{
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
unsigned long flags;
@@ -895,12 +896,12 @@ static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
return !!(padcfg0 & PADCFG0_GPIOTXDIS);
}
-static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
return pinctrl_gpio_direction_input(chip->base + offset);
}
-static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
intel_gpio_set(chip, offset, value);
@@ -929,7 +930,7 @@ static void intel_gpio_irq_ack(struct irq_data *d)
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
if (pin >= 0) {
- unsigned gpp, gpp_offset, is_offset;
+ unsigned int gpp, gpp_offset, is_offset;
gpp = padgrp->reg_num;
gpp_offset = padgroup_offset(padgrp, pin);
@@ -951,7 +952,7 @@ static void intel_gpio_irq_enable(struct irq_data *d)
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
if (pin >= 0) {
- unsigned gpp, gpp_offset, is_offset;
+ unsigned int gpp, gpp_offset, is_offset;
unsigned long flags;
u32 value;
@@ -980,7 +981,7 @@ static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
if (pin >= 0) {
- unsigned gpp, gpp_offset;
+ unsigned int gpp, gpp_offset;
unsigned long flags;
void __iomem *reg;
u32 value;
@@ -1011,11 +1012,11 @@ static void intel_gpio_irq_unmask(struct irq_data *d)
intel_gpio_irq_mask_unmask(d, false);
}
-static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
+static int intel_gpio_irq_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
- unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
+ unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
unsigned long flags;
void __iomem *reg;
u32 value;
@@ -1072,7 +1073,7 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
- unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
+ unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
if (on)
enable_irq_wake(pctrl->irq);
@@ -1167,7 +1168,7 @@ static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
static unsigned intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
{
const struct intel_community *community;
- unsigned ngpio = 0;
+ unsigned int ngpio = 0;
int i, j;
for (i = 0; i < pctrl->ncommunities; i++) {
@@ -1243,8 +1244,8 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
struct intel_community *community)
{
struct intel_padgroup *gpps;
- unsigned npins = community->npins;
- unsigned padown_num = 0;
+ unsigned int npins = community->npins;
+ unsigned int padown_num = 0;
size_t ngpps, i;
if (community->gpps)
@@ -1260,7 +1261,7 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
if (community->gpps) {
gpps[i] = community->gpps[i];
} else {
- unsigned gpp_size = community->gpp_size;
+ unsigned int gpp_size = community->gpp_size;
gpps[i].reg_num = i;
gpps[i].base = community->pin_base + i * gpp_size;
@@ -1431,7 +1432,13 @@ int intel_pinctrl_probe(struct platform_device *pdev,
EXPORT_SYMBOL_GPL(intel_pinctrl_probe);
#ifdef CONFIG_PM_SLEEP
-static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned pin)
+static bool __intel_gpio_is_direct_irq(u32 value)
+{
+ return (value & PADCFG0_GPIROUTIOXAPIC) && (value & PADCFG0_GPIOTXDIS) &&
+ (__intel_gpio_get_gpio_mode(value) == PADCFG0_PMODE_GPIO);
+}
+
+static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin)
{
const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
u32 value;
@@ -1464,8 +1471,7 @@ static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned pin)
* See https://bugzilla.kernel.org/show_bug.cgi?id=214749.
*/
value = readl(intel_get_padcfg(pctrl, pin, PADCFG0));
- if ((value & PADCFG0_GPIROUTIOXAPIC) && (value & PADCFG0_GPIOTXDIS) &&
- (__intel_gpio_get_gpio_mode(value) == PADCFG0_PMODE_GPIO))
+ if (__intel_gpio_is_direct_irq(value))
return true;
return false;
@@ -1502,7 +1508,7 @@ int intel_pinctrl_suspend(struct device *dev)
for (i = 0; i < pctrl->ncommunities; i++) {
struct intel_community *community = &pctrl->communities[i];
void __iomem *base;
- unsigned gpp;
+ unsigned int gpp;
base = community->regs + community->ie_offset;
for (gpp = 0; gpp < community->ngpps; gpp++)
@@ -1520,7 +1526,7 @@ static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
for (i = 0; i < pctrl->ncommunities; i++) {
const struct intel_community *community;
void __iomem *base;
- unsigned gpp;
+ unsigned int gpp;
community = &pctrl->communities[i];
base = community->regs;
@@ -1550,7 +1556,12 @@ int intel_pinctrl_resume(struct device *dev)
void __iomem *padcfg;
u32 val;
- if (!intel_pinctrl_should_save(pctrl, desc->number))
+ if (!(intel_pinctrl_should_save(pctrl, desc->number) ||
+ /*
+ * If the firmware mangled the register contents too much,
+ * check the saved value for the Direct IRQ mode.
+ */
+ __intel_gpio_is_direct_irq(pads[i].padcfg0)))
continue;
padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG0);
@@ -1584,7 +1595,7 @@ int intel_pinctrl_resume(struct device *dev)
for (i = 0; i < pctrl->ncommunities; i++) {
struct intel_community *community = &pctrl->communities[i];
void __iomem *base;
- unsigned gpp;
+ unsigned int gpp;
base = community->regs + community->ie_offset;
for (gpp = 0; gpp < community->ngpps; gpp++) {
diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
index 1785abf157e4..737a545b448f 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.h
+++ b/drivers/pinctrl/intel/pinctrl-intel.h
@@ -25,10 +25,10 @@ struct device;
*/
struct intel_pingroup {
const char *name;
- const unsigned *pins;
+ const unsigned int *pins;
size_t npins;
unsigned short mode;
- const unsigned *modes;
+ const unsigned int *modes;
};
/**
@@ -56,11 +56,11 @@ struct intel_function {
* to specify them.
*/
struct intel_padgroup {
- unsigned reg_num;
- unsigned base;
- unsigned size;
+ unsigned int reg_num;
+ unsigned int base;
+ unsigned int size;
int gpio_base;
- unsigned padown_num;
+ unsigned int padown_num;
};
/**
@@ -96,17 +96,17 @@ struct intel_padgroup {
* pass custom @gpps and @ngpps instead.
*/
struct intel_community {
- unsigned barno;
- unsigned padown_offset;
- unsigned padcfglock_offset;
- unsigned hostown_offset;
- unsigned is_offset;
- unsigned ie_offset;
- unsigned pin_base;
- unsigned gpp_size;
- unsigned gpp_num_padown_regs;
+ unsigned int barno;
+ unsigned int padown_offset;
+ unsigned int padcfglock_offset;
+ unsigned int hostown_offset;
+ unsigned int is_offset;
+ unsigned int ie_offset;
+ unsigned int pin_base;
+ unsigned int gpp_size;
+ unsigned int gpp_num_padown_regs;
size_t npins;
- unsigned features;
+ unsigned int features;
const struct intel_padgroup *gpps;
size_t ngpps;
/* Reserved for the core driver */
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 2b50030ad97e..4143cafbf7e7 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -345,6 +345,8 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
if (!pcs->fmask)
return 0;
function = pinmux_generic_get_function(pctldev, fselector);
+ if (!function)
+ return -EINVAL;
func = function->data;
if (!func)
return -EINVAL;
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 7212e3a13fe6..33fb111e2e19 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -775,7 +775,7 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
enum iscsi_host_param param, char *buf)
{
struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost);
- struct iscsi_session *session = tcp_sw_host->session;
+ struct iscsi_session *session;
struct iscsi_conn *conn;
struct iscsi_tcp_conn *tcp_conn;
struct iscsi_sw_tcp_conn *tcp_sw_conn;
@@ -784,6 +784,7 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
switch (param) {
case ISCSI_HOST_PARAM_IPADDRESS:
+ session = tcp_sw_host->session;
if (!session)
return -ENOTCONN;
@@ -872,12 +873,14 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
if (!cls_session)
goto remove_host;
session = cls_session->dd_data;
- tcp_sw_host = iscsi_host_priv(shost);
- tcp_sw_host->session = session;
shost->can_queue = session->scsi_cmds_max;
if (iscsi_tcp_r2tpool_alloc(session))
goto remove_session;
+
+ /* We are now fully setup so expose the session to sysfs. */
+ tcp_sw_host = iscsi_host_priv(shost);
+ tcp_sw_host->session = session;
return cls_session;
remove_session:
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index 6d1179a7f043..bba24eaea2ce 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -95,8 +95,8 @@ static bool __target_check_io_state(struct se_cmd *se_cmd,
{
struct se_session *sess = se_cmd->se_sess;
- assert_spin_locked(&sess->sess_cmd_lock);
- WARN_ON_ONCE(!irqs_disabled());
+ lockdep_assert_held(&sess->sess_cmd_lock);
+
/*
* If command already reached CMD_T_COMPLETE state within
* target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown,
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
index 9ec27ac1856b..1adcef95f7b9 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
@@ -52,11 +52,13 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
int trip, int *temp)
{
struct int34x_thermal_zone *d = zone->devdata;
- int i;
+ int i, ret = 0;
if (d->override_ops && d->override_ops->get_trip_temp)
return d->override_ops->get_trip_temp(zone, trip, temp);
+ mutex_lock(&d->trip_mutex);
+
if (trip < d->aux_trip_nr)
*temp = d->aux_trips[trip];
else if (trip == d->crt_trip_id)
@@ -74,10 +76,12 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
}
}
if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT)
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+ mutex_unlock(&d->trip_mutex);
+
+ return ret;
}
static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
@@ -85,11 +89,13 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
enum thermal_trip_type *type)
{
struct int34x_thermal_zone *d = zone->devdata;
- int i;
+ int i, ret = 0;
if (d->override_ops && d->override_ops->get_trip_type)
return d->override_ops->get_trip_type(zone, trip, type);
+ mutex_lock(&d->trip_mutex);
+
if (trip < d->aux_trip_nr)
*type = THERMAL_TRIP_PASSIVE;
else if (trip == d->crt_trip_id)
@@ -107,10 +113,12 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
}
}
if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT)
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+ mutex_unlock(&d->trip_mutex);
+
+ return ret;
}
static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
@@ -182,6 +190,8 @@ int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone)
int trip_cnt = int34x_zone->aux_trip_nr;
int i;
+ mutex_lock(&int34x_zone->trip_mutex);
+
int34x_zone->crt_trip_id = -1;
if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_CRT",
&int34x_zone->crt_temp))
@@ -209,6 +219,8 @@ int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone)
int34x_zone->act_trips[i].valid = true;
}
+ mutex_unlock(&int34x_zone->trip_mutex);
+
return trip_cnt;
}
EXPORT_SYMBOL_GPL(int340x_thermal_read_trips);
@@ -232,6 +244,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
if (!int34x_thermal_zone)
return ERR_PTR(-ENOMEM);
+ mutex_init(&int34x_thermal_zone->trip_mutex);
+
int34x_thermal_zone->adev = adev;
int34x_thermal_zone->override_ops = override_ops;
@@ -274,6 +288,7 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
kfree(int34x_thermal_zone->aux_trips);
err_trip_alloc:
+ mutex_destroy(&int34x_thermal_zone->trip_mutex);
kfree(int34x_thermal_zone);
return ERR_PTR(ret);
}
@@ -285,6 +300,7 @@ void int340x_thermal_zone_remove(struct int34x_thermal_zone
thermal_zone_device_unregister(int34x_thermal_zone->zone);
acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
kfree(int34x_thermal_zone->aux_trips);
+ mutex_destroy(&int34x_thermal_zone->trip_mutex);
kfree(int34x_thermal_zone);
}
EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove);
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
index 5f3ba4775c5c..e74648e330c7 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
+++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
@@ -41,6 +41,7 @@ struct int34x_thermal_zone {
struct thermal_zone_device_ops *override_ops;
void *priv_data;
struct acpi_lpat_conversion_table *lpat_table;
+ struct mutex trip_mutex;
};
struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *,
diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
index bfa1a857f3ff..c8b17070faf4 100644
--- a/drivers/tty/serial/8250/8250_dma.c
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -48,19 +48,39 @@ static void __dma_rx_complete(void *param)
struct uart_8250_dma *dma = p->dma;
struct tty_port *tty_port = &p->port.state->port;
struct dma_tx_state state;
+ enum dma_status dma_status;
int count;
- dma->rx_running = 0;
- dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+ /*
+ * New DMA Rx can be started during the completion handler before it
+ * could acquire port's lock and it might still be ongoing. Don't to
+ * anything in such case.
+ */
+ dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+ if (dma_status == DMA_IN_PROGRESS)
+ return;
count = dma->rx_size - state.residue;
tty_insert_flip_string(tty_port, dma->rx_buf, count);
p->port.icount.rx += count;
+ dma->rx_running = 0;
tty_flip_buffer_push(tty_port);
}
+static void dma_rx_complete(void *param)
+{
+ struct uart_8250_port *p = param;
+ struct uart_8250_dma *dma = p->dma;
+ unsigned long flags;
+
+ spin_lock_irqsave(&p->port.lock, flags);
+ if (dma->rx_running)
+ __dma_rx_complete(p);
+ spin_unlock_irqrestore(&p->port.lock, flags);
+}
+
int serial8250_tx_dma(struct uart_8250_port *p)
{
struct uart_8250_dma *dma = p->dma;
@@ -126,7 +146,7 @@ int serial8250_rx_dma(struct uart_8250_port *p)
return -EBUSY;
dma->rx_running = 1;
- desc->callback = __dma_rx_complete;
+ desc->callback = dma_rx_complete;
desc->callback_param = p;
dma->rx_cookie = dmaengine_submit(desc);
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c
index 2fb509d57e88..03fe692d940b 100644
--- a/drivers/tty/vt/vc_screen.c
+++ b/drivers/tty/vt/vc_screen.c
@@ -247,10 +247,6 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
uni_mode = use_unicode(inode);
attr = use_attributes(inode);
- ret = -ENXIO;
- vc = vcs_vc(inode, &viewed);
- if (!vc)
- goto unlock_out;
ret = -EINVAL;
if (pos < 0)
@@ -270,6 +266,11 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
ssize_t orig_count;
long p = pos;
+ ret = -ENXIO;
+ vc = vcs_vc(inode, &viewed);
+ if (!vc)
+ goto unlock_out;
+
/* Check whether we are above size each round,
* as copy_to_user at the end of this loop
* could sleep.
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 35a11f7bcb65..1346c600ebed 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -527,6 +527,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* DJI CineSSD */
{ USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },
+ /* Alcor Link AK9563 SC Reader used in 2022 Lenovo ThinkPads */
+ { USB_DEVICE(0x2ce3, 0x9563), .driver_info = USB_QUIRK_NO_LPM },
+
/* DELL USB GEN2 */
{ USB_DEVICE(0x413c, 0xb062), .driver_info = USB_QUIRK_NO_LPM | USB_QUIRK_RESET_RESUME },
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 9d5320562e81..58e1bc3a77d8 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -85,7 +85,7 @@ static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val)
readl(base + offset);
}
-static void dwc3_qcom_vbus_overrride_enable(struct dwc3_qcom *qcom, bool enable)
+static void dwc3_qcom_vbus_override_enable(struct dwc3_qcom *qcom, bool enable)
{
if (enable) {
dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
@@ -106,7 +106,7 @@ static int dwc3_qcom_vbus_notifier(struct notifier_block *nb,
struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, vbus_nb);
/* enable vbus override for device mode */
- dwc3_qcom_vbus_overrride_enable(qcom, event);
+ dwc3_qcom_vbus_override_enable(qcom, event);
qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST;
return NOTIFY_DONE;
@@ -118,7 +118,7 @@ static int dwc3_qcom_host_notifier(struct notifier_block *nb,
struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, host_nb);
/* disable vbus override in host mode */
- dwc3_qcom_vbus_overrride_enable(qcom, !event);
+ dwc3_qcom_vbus_override_enable(qcom, !event);
qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL;
return NOTIFY_DONE;
@@ -512,8 +512,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev);
/* enable vbus override for device mode */
- if (qcom->mode == USB_DR_MODE_PERIPHERAL)
- dwc3_qcom_vbus_overrride_enable(qcom, true);
+ if (qcom->mode != USB_DR_MODE_HOST)
+ dwc3_qcom_vbus_override_enable(qcom, true);
/* register extcon to override sw_vbus on Vbus change later */
ret = dwc3_qcom_register_extcon(qcom);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 48bdb2a3972b..f9f324f76a72 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -271,8 +271,10 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
struct usb_request *req = ffs->ep0req;
int ret;
- if (!req)
+ if (!req) {
+ spin_unlock_irq(&ffs->ev.waitq.lock);
return -EINVAL;
+ }
req->zero = len < le16_to_cpu(ffs->ev.setup.wLength);
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 2ae3fab36a80..7387f52cb58d 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -526,10 +526,10 @@ static int dp_altmode_probe(struct typec_altmode *alt)
/* FIXME: Port can only be DFP_U. */
/* Make sure we have compatiple pin configurations */
- if (!(DP_CAP_DFP_D_PIN_ASSIGN(port->vdo) &
- DP_CAP_UFP_D_PIN_ASSIGN(alt->vdo)) &&
- !(DP_CAP_UFP_D_PIN_ASSIGN(port->vdo) &
- DP_CAP_DFP_D_PIN_ASSIGN(alt->vdo)))
+ if (!(DP_CAP_PIN_ASSIGN_DFP_D(port->vdo) &
+ DP_CAP_PIN_ASSIGN_UFP_D(alt->vdo)) &&
+ !(DP_CAP_PIN_ASSIGN_UFP_D(port->vdo) &
+ DP_CAP_PIN_ASSIGN_DFP_D(alt->vdo)))
return -ENODEV;
ret = sysfs_create_group(&alt->dev.kobj, &dp_altmode_group);
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 9fcd583b7835..dea5275254ef 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2475,9 +2475,12 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres))
return -EINVAL;
+ if (font->width > 32 || font->height > 32)
+ return -EINVAL;
+
/* Make sure drawing engine can handle the font */
- if (!(info->pixmap.blit_x & (1 << (font->width - 1))) ||
- !(info->pixmap.blit_y & (1 << (font->height - 1))))
+ if (!(info->pixmap.blit_x & BIT(font->width - 1)) ||
+ !(info->pixmap.blit_y & BIT(font->height - 1)))
return -EINVAL;
/* Make sure driver can handle the font length */
diff --git a/drivers/watchdog/diag288_wdt.c b/drivers/watchdog/diag288_wdt.c
index 806a04a676b7..561797c3b202 100644
--- a/drivers/watchdog/diag288_wdt.c
+++ b/drivers/watchdog/diag288_wdt.c
@@ -88,7 +88,7 @@ static int __diag288(unsigned int func, unsigned int timeout,
"1:\n"
EX_TABLE(0b, 1b)
: "+d" (err) : "d"(__func), "d"(__timeout),
- "d"(__action), "d"(__len) : "1", "cc");
+ "d"(__action), "d"(__len) : "1", "cc", "memory");
return err;
}
@@ -274,12 +274,21 @@ static int __init diag288_init(void)
char ebc_begin[] = {
194, 197, 199, 201, 213
};
+ char *ebc_cmd;
watchdog_set_nowayout(&wdt_dev, nowayout_info);
if (MACHINE_IS_VM) {
- if (__diag288_vm(WDT_FUNC_INIT, 15,
- ebc_begin, sizeof(ebc_begin)) != 0) {
+ ebc_cmd = kmalloc(sizeof(ebc_begin), GFP_KERNEL);
+ if (!ebc_cmd) {
+ pr_err("The watchdog cannot be initialized\n");
+ return -ENOMEM;
+ }
+ memcpy(ebc_cmd, ebc_begin, sizeof(ebc_begin));
+ ret = __diag288_vm(WDT_FUNC_INIT, 15,
+ ebc_cmd, sizeof(ebc_begin));
+ kfree(ebc_cmd);
+ if (ret != 0) {
pr_err("The watchdog cannot be initialized\n");
return -EINVAL;
}
diff --git a/fs/aio.c b/fs/aio.c
index 9635c29b83da..1bd934eccbf6 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -332,6 +332,9 @@ static int aio_ring_mremap(struct vm_area_struct *vma)
spin_lock(&mm->ioctx_lock);
rcu_read_lock();
table = rcu_dereference(mm->ioctx_table);
+ if (!table)
+ goto out_unlock;
+
for (i = 0; i < table->nr; i++) {
struct kioctx *ctx;
@@ -345,6 +348,7 @@ static int aio_ring_mremap(struct vm_area_struct *vma)
}
}
+out_unlock:
rcu_read_unlock();
spin_unlock(&mm->ioctx_lock);
return res;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 2b4d33b58a68..0294f519c29e 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1418,7 +1418,7 @@ int find_free_dev_extent_start(struct btrfs_transaction *transaction,
goto out;
}
- while (1) {
+ while (search_start < search_end) {
l = path->nodes[0];
slot = path->slots[0];
if (slot >= btrfs_header_nritems(l)) {
@@ -1441,6 +1441,9 @@ int find_free_dev_extent_start(struct btrfs_transaction *transaction,
if (key.type != BTRFS_DEV_EXTENT_KEY)
goto next;
+ if (key.offset > search_end)
+ break;
+
if (key.offset > search_start) {
hole_size = key.offset - search_start;
@@ -1515,6 +1518,7 @@ int find_free_dev_extent_start(struct btrfs_transaction *transaction,
else
ret = 0;
+ ASSERT(max_hole_start + max_hole_size <= search_end);
out:
btrfs_free_path(path);
*start = max_hole_start;
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 9b96d79eea6c..708aa1b92036 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -1135,7 +1135,14 @@ static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp)
minseg = range[0] + segbytes - 1;
do_div(minseg, segbytes);
+
+ if (range[1] < 4096)
+ goto out;
+
maxseg = NILFS_SB2_OFFSET_BYTES(range[1]);
+ if (maxseg < segbytes)
+ goto out;
+
do_div(maxseg, segbytes);
maxseg--;
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 5e4d7d19102c..2961b5ceb4a7 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -410,6 +410,15 @@ int nilfs_resize_fs(struct super_block *sb, __u64 newsize)
if (newsize > devsize)
goto out;
+ /*
+ * Prevent underflow in second superblock position calculation.
+ * The exact minimum size check is done in nilfs_sufile_resize().
+ */
+ if (newsize < 4096) {
+ ret = -ENOSPC;
+ goto out;
+ }
+
/*
* Write lock is required to protect some functions depending
* on the number of segments, the number of reserved segments,
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 74ef3d313686..6541e29a8b20 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -517,9 +517,15 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
{
struct nilfs_super_block **sbp = nilfs->ns_sbp;
struct buffer_head **sbh = nilfs->ns_sbh;
- u64 sb2off = NILFS_SB2_OFFSET_BYTES(nilfs->ns_bdev->bd_inode->i_size);
+ u64 sb2off, devsize = nilfs->ns_bdev->bd_inode->i_size;
int valid[2], swp = 0;
+ if (devsize < NILFS_SEG_MIN_BLOCKS * NILFS_MIN_BLOCK_SIZE + 4096) {
+ nilfs_msg(sb, KERN_ERR, "device size too small");
+ return -EINVAL;
+ }
+ sb2off = NILFS_SB2_OFFSET_BYTES(devsize);
+
sbp[0] = nilfs_read_super_block(sb, NILFS_SB_OFFSET_BYTES, blocksize,
&sbh[0]);
sbp[1] = nilfs_read_super_block(sb, sb2off, blocksize, &sbh[1]);
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index dc63d4c6029e..2f2afc3c6fc6 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -701,9 +701,7 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,
page = device_private_entry_to_page(swpent);
}
if (page) {
- int mapcount = page_mapcount(page);
-
- if (mapcount >= 2)
+ if (page_mapcount(page) >= 2 || hugetlb_pmd_shared(pte))
mss->shared_hugetlb += huge_page_size(hstate_vma(vma));
else
mss->private_hugetlb += huge_page_size(hstate_vma(vma));
diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
index 10e93345b615..75886e6d9c97 100644
--- a/fs/squashfs/squashfs_fs.h
+++ b/fs/squashfs/squashfs_fs.h
@@ -196,7 +196,7 @@ static inline int squashfs_block_size(__le32 raw)
#define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\
sizeof(u64))
/* xattr id lookup table defines */
-#define SQUASHFS_XATTR_BYTES(A) ((A) * sizeof(struct squashfs_xattr_id))
+#define SQUASHFS_XATTR_BYTES(A) (((u64) (A)) * sizeof(struct squashfs_xattr_id))
#define SQUASHFS_XATTR_BLOCK(A) (SQUASHFS_XATTR_BYTES(A) / \
SQUASHFS_METADATA_SIZE)
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 5234c19a0eab..7ec30a11273e 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -76,7 +76,7 @@ struct squashfs_sb_info {
long long bytes_used;
unsigned int inodes;
unsigned int fragments;
- int xattr_ids;
+ unsigned int xattr_ids;
unsigned int ids;
};
#endif
diff --git a/fs/squashfs/xattr.h b/fs/squashfs/xattr.h
index 86b0a0073e51..f360f27e38f3 100644
--- a/fs/squashfs/xattr.h
+++ b/fs/squashfs/xattr.h
@@ -23,12 +23,12 @@
#ifdef CONFIG_SQUASHFS_XATTR
extern __le64 *squashfs_read_xattr_id_table(struct super_block *, u64,
- u64 *, int *);
+ u64 *, unsigned int *);
extern int squashfs_xattr_lookup(struct super_block *, unsigned int, int *,
unsigned int *, unsigned long long *);
#else
static inline __le64 *squashfs_read_xattr_id_table(struct super_block *sb,
- u64 start, u64 *xattr_table_start, int *xattr_ids)
+ u64 start, u64 *xattr_table_start, unsigned int *xattr_ids)
{
struct squashfs_xattr_id_table *id_table;
diff --git a/fs/squashfs/xattr_id.c b/fs/squashfs/xattr_id.c
index 7f718d2bf357..fe266b3e95f8 100644
--- a/fs/squashfs/xattr_id.c
+++ b/fs/squashfs/xattr_id.c
@@ -69,7 +69,7 @@ int squashfs_xattr_lookup(struct super_block *sb, unsigned int index,
* Read uncompressed xattr id lookup table indexes from disk into memory
*/
__le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 table_start,
- u64 *xattr_table_start, int *xattr_ids)
+ u64 *xattr_table_start, unsigned int *xattr_ids)
{
struct squashfs_sb_info *msblk = sb->s_fs_info;
unsigned int len, indexes;
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index cb7dc38e9c77..354d320c3fd6 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -7,6 +7,7 @@
#include <linux/fs.h>
#include <linux/hugetlb_inline.h>
#include <linux/cgroup.h>
+#include <linux/page_ref.h>
#include <linux/list.h>
#include <linux/kref.h>
#include <asm/pgtable.h>
@@ -404,7 +405,10 @@ static inline struct hstate *hstate_sizelog(int page_size_log)
if (!page_size_log)
return &default_hstate;
- return size_to_hstate(1UL << page_size_log);
+ if (page_size_log < BITS_PER_LONG)
+ return size_to_hstate(1UL << page_size_log);
+
+ return NULL;
}
static inline struct hstate *hstate_vma(struct vm_area_struct *vma)
@@ -626,4 +630,16 @@ static inline spinlock_t *huge_pte_lock(struct hstate *h,
return ptl;
}
+#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
+static inline bool hugetlb_pmd_shared(pte_t *pte)
+{
+ return page_count(virt_to_page(pte)) > 1;
+}
+#else
+static inline bool hugetlb_pmd_shared(pte_t *pte)
+{
+ return false;
+}
+#endif
+
#endif /* _LINUX_HUGETLB_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 42766e7179d3..86a3792c568c 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -667,6 +667,10 @@ struct phy_driver {
#define PHY_ANY_ID "MATCH ANY PHY"
#define PHY_ANY_UID 0xffffffff
+#define PHY_ID_MATCH_EXACT(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 0)
+#define PHY_ID_MATCH_MODEL(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 4)
+#define PHY_ID_MATCH_VENDOR(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 10)
+
/* A Structure for boards to register fixups with the PHY Lib */
struct phy_fixup {
struct list_head list;
diff --git a/include/net/sock.h b/include/net/sock.h
index 30315a03b4ab..9eb656683281 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2134,6 +2134,19 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
sk_mem_charge(sk, skb->truesize);
}
+static inline struct sk_buff *skb_clone_and_charge_r(struct sk_buff *skb, struct sock *sk)
+{
+ skb = skb_clone(skb, sk_gfp_mask(sk, GFP_ATOMIC));
+ if (skb) {
+ if (sk_rmem_schedule(sk, skb, skb->truesize)) {
+ skb_set_owner_r(skb, sk);
+ return skb;
+ }
+ __kfree_skb(skb);
+ }
+ return NULL;
+}
+
void sk_reset_timer(struct sock *sk, struct timer_list *timer,
unsigned long expires);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index e44e737e90a3..35088e830bff 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -571,7 +571,8 @@ static int queue_pages_hugetlb(pte_t *pte, unsigned long hmask,
goto unlock;
/* With MPOL_MF_MOVE, we migrate only unshared hugepage. */
if (flags & (MPOL_MF_MOVE_ALL) ||
- (flags & MPOL_MF_MOVE && page_mapcount(page) == 1))
+ (flags & MPOL_MF_MOVE && page_mapcount(page) == 1 &&
+ !hugetlb_pmd_shared(pte)))
isolate_huge_page(page, qp->pagelist);
unlock:
spin_unlock(ptl);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 057e6907bf7b..f3b2d694a155 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1008,6 +1008,7 @@ int get_swap_pages(int n_goal, swp_entry_t swp_entries[], int entry_size)
goto check_out;
pr_debug("scan_swap_map of si %d failed to find offset\n",
si->type);
+ cond_resched();
spin_lock(&swap_avail_lock);
nextsi:
diff --git a/net/core/filter.c b/net/core/filter.c
index 32d0b8f14aab..dea7132f3813 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4235,7 +4235,6 @@ static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params,
memcpy(params->smac, dev->dev_addr, ETH_ALEN);
params->h_vlan_TCI = 0;
params->h_vlan_proto = 0;
- params->ifindex = dev->ifindex;
return 0;
}
@@ -4333,6 +4332,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
params->ipv4_dst = nh->nh_gw;
params->rt_metric = res.fi->fib_priority;
+ params->ifindex = dev->ifindex;
/* xdp and cls_bpf programs are run in RCU-bh so
* rcu_read_lock_bh is not needed here
@@ -4447,6 +4447,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
dev = f6i->fib6_nh.nh_dev;
params->rt_metric = f6i->fib6_metric;
+ params->ifindex = dev->ifindex;
/* xdp and cls_bpf programs are run in RCU-bh so rcu_read_lock_bh is
* not needed here. Can not use __ipv6_neigh_lookup_noref here
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 72803e1ea10a..b2a26e41f932 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -541,11 +541,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), NULL);
/* Clone pktoptions received with SYN, if we own the req */
if (*own_req && ireq->pktopts) {
- newnp->pktoptions = skb_clone(ireq->pktopts, GFP_ATOMIC);
+ newnp->pktoptions = skb_clone_and_charge_r(ireq->pktopts, newsk);
consume_skb(ireq->pktopts);
ireq->pktopts = NULL;
- if (newnp->pktoptions)
- skb_set_owner_r(newnp->pktoptions, newsk);
}
return newsk;
@@ -605,7 +603,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
--ANK (980728)
*/
if (np->rxopt.all)
- opt_skb = skb_clone(skb, GFP_ATOMIC);
+ opt_skb = skb_clone_and_charge_r(skb, sk);
if (sk->sk_state == DCCP_OPEN) { /* Fast path */
if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
@@ -669,7 +667,6 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
np->flow_label = ip6_flowlabel(ipv6_hdr(opt_skb));
if (ipv6_opt_accepted(sk, opt_skb,
&DCCP_SKB_CB(opt_skb)->header.h6)) {
- skb_set_owner_r(opt_skb, sk);
memmove(IP6CB(opt_skb),
&DCCP_SKB_CB(opt_skb)->header.h6,
sizeof(struct inet6_skb_parm));
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 727f958dd869..45ece6a898bf 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -54,7 +54,7 @@ static void ip6_datagram_flow_key_init(struct flowi6 *fl6, struct sock *sk)
fl6->flowi6_mark = sk->sk_mark;
fl6->fl6_dport = inet->inet_dport;
fl6->fl6_sport = inet->inet_sport;
- fl6->flowlabel = np->flow_label;
+ fl6->flowlabel = ip6_make_flowinfo(np->tclass, np->flow_label);
fl6->flowi6_uid = sk->sk_uid;
if (!fl6->flowi6_oif)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index babf69b2403b..f69c1b83403b 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -257,6 +257,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
fl6.flowi6_proto = IPPROTO_TCP;
fl6.daddr = sk->sk_v6_daddr;
fl6.saddr = saddr ? *saddr : np->saddr;
+ fl6.flowlabel = ip6_make_flowinfo(np->tclass, np->flow_label);
fl6.flowi6_oif = sk->sk_bound_dev_if;
fl6.flowi6_mark = sk->sk_mark;
fl6.fl6_dport = usin->sin6_port;
@@ -1268,14 +1269,11 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
/* Clone pktoptions received with SYN, if we own the req */
if (ireq->pktopts) {
- newnp->pktoptions = skb_clone(ireq->pktopts,
- sk_gfp_mask(sk, GFP_ATOMIC));
+ newnp->pktoptions = skb_clone_and_charge_r(ireq->pktopts, newsk);
consume_skb(ireq->pktopts);
ireq->pktopts = NULL;
- if (newnp->pktoptions) {
+ if (newnp->pktoptions)
tcp_v6_restore_cb(newnp->pktoptions);
- skb_set_owner_r(newnp->pktoptions, newsk);
- }
}
} else {
if (!req_unhash && found_dup_sk) {
@@ -1343,7 +1341,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
--ANK (980728)
*/
if (np->rxopt.all)
- opt_skb = skb_clone(skb, sk_gfp_mask(sk, GFP_ATOMIC));
+ opt_skb = skb_clone_and_charge_r(skb, sk);
if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
struct dst_entry *dst;
@@ -1425,7 +1423,6 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
if (np->repflow)
np->flow_label = ip6_flowlabel(ipv6_hdr(opt_skb));
if (ipv6_opt_accepted(sk, opt_skb, &TCP_SKB_CB(opt_skb)->header.h6)) {
- skb_set_owner_r(opt_skb, sk);
tcp_v6_restore_cb(opt_skb);
opt_skb = xchg(&np->pktoptions, opt_skb);
} else {
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index ea1745cb93ed..40b3e6a52f92 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1375,6 +1375,7 @@ static int mpls_dev_sysctl_register(struct net_device *dev,
free:
kfree(table);
out:
+ mdev->sysctl = NULL;
return -ENOBUFS;
}
@@ -1384,6 +1385,9 @@ static void mpls_dev_sysctl_unregister(struct net_device *dev,
struct net *net = dev_net(dev);
struct ctl_table *table;
+ if (!mdev->sysctl)
+ return;
+
table = mdev->sysctl->ctl_table_arg;
unregister_net_sysctl_table(mdev->sysctl);
kfree(table);
diff --git a/net/netfilter/nft_tproxy.c b/net/netfilter/nft_tproxy.c
index b97ab1198b03..a0e30bf4a845 100644
--- a/net/netfilter/nft_tproxy.c
+++ b/net/netfilter/nft_tproxy.c
@@ -289,6 +289,13 @@ static int nft_tproxy_dump(struct sk_buff *skb,
return 0;
}
+static int nft_tproxy_validate(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nft_data **data)
+{
+ return nft_chain_validate_hooks(ctx->chain, 1 << NF_INET_PRE_ROUTING);
+}
+
static struct nft_expr_type nft_tproxy_type;
static const struct nft_expr_ops nft_tproxy_ops = {
.type = &nft_tproxy_type,
@@ -296,6 +303,7 @@ static const struct nft_expr_ops nft_tproxy_ops = {
.eval = nft_tproxy_eval,
.init = nft_tproxy_init,
.dump = nft_tproxy_dump,
+ .validate = nft_tproxy_validate,
};
static struct nft_expr_type nft_tproxy_type __read_mostly = {
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 43910e50752c..a5d819fa7c89 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -403,6 +403,11 @@ static int nr_listen(struct socket *sock, int backlog)
struct sock *sk = sock->sk;
lock_sock(sk);
+ if (sock->state != SS_UNCONNECTED) {
+ release_sock(sk);
+ return -EINVAL;
+ }
+
if (sk->sk_state != TCP_LISTEN) {
memset(&nr_sk(sk)->user_addr, 0, AX25_ADDR_LEN);
sk->sk_max_ack_backlog = backlog;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index fbc575247268..0551915519d9 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -934,14 +934,14 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
key = kzalloc(sizeof(*key), GFP_KERNEL);
if (!key) {
error = -ENOMEM;
- goto err_kfree_key;
+ goto err_kfree_flow;
}
ovs_match_init(&match, key, false, &mask);
error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
a[OVS_FLOW_ATTR_MASK], log);
if (error)
- goto err_kfree_flow;
+ goto err_kfree_key;
ovs_flow_mask_key(&new_flow->key, key, true, &mask);
@@ -949,14 +949,14 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
key, log);
if (error)
- goto err_kfree_flow;
+ goto err_kfree_key;
/* Validate actions. */
error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS],
&new_flow->key, &acts, log);
if (error) {
OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
- goto err_kfree_flow;
+ goto err_kfree_key;
}
reply = ovs_flow_cmd_alloc_info(acts, &new_flow->id, info, false,
@@ -1056,10 +1056,10 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
kfree_skb(reply);
err_kfree_acts:
ovs_nla_free_flow_actions(acts);
-err_kfree_flow:
- ovs_flow_free(new_flow, false);
err_kfree_key:
kfree(key);
+err_kfree_flow:
+ ovs_flow_free(new_flow, false);
error:
return error;
}
diff --git a/net/rds/message.c b/net/rds/message.c
index 4b00b1152a5f..309b54cc62ae 100644
--- a/net/rds/message.c
+++ b/net/rds/message.c
@@ -104,9 +104,9 @@ static void rds_rm_zerocopy_callback(struct rds_sock *rs,
spin_lock_irqsave(&q->lock, flags);
head = &q->zcookie_head;
if (!list_empty(head)) {
- info = list_entry(head, struct rds_msg_zcopy_info,
- rs_zcookie_next);
- if (info && rds_zcookie_add(info, cookie)) {
+ info = list_first_entry(head, struct rds_msg_zcopy_info,
+ rs_zcookie_next);
+ if (rds_zcookie_add(info, cookie)) {
spin_unlock_irqrestore(&q->lock, flags);
kfree(rds_info_from_znotifier(znotif));
/* caller invokes rds_wake_sk_sleep() */
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 03a1ee221112..4edd127bb892 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -490,6 +490,12 @@ static int rose_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
+ lock_sock(sk);
+ if (sock->state != SS_UNCONNECTED) {
+ release_sock(sk);
+ return -EINVAL;
+ }
+
if (sk->sk_state != TCP_LISTEN) {
struct rose_sock *rose = rose_sk(sk);
@@ -499,8 +505,10 @@ static int rose_listen(struct socket *sock, int backlog)
memset(rose->dest_digis, 0, AX25_ADDR_LEN * ROSE_MAX_DIGIS);
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;
+ release_sock(sk);
return 0;
}
+ release_sock(sk);
return -EOPNOTSUPP;
}
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 77d8adb27ec7..9d0328bb30ca 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -497,6 +497,12 @@ static int x25_listen(struct socket *sock, int backlog)
int rc = -EOPNOTSUPP;
lock_sock(sk);
+ if (sock->state != SS_UNCONNECTED) {
+ rc = -EINVAL;
+ release_sock(sk);
+ return rc;
+ }
+
if (sk->sk_state != TCP_LISTEN) {
memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
sk->sk_max_ack_backlog = backlog;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index b1a8ee8cf17e..69f88d3abf50 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -1106,6 +1106,7 @@ static const struct hda_device_id snd_hda_id_conexant[] = {
HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f120d0, "CX11970", patch_conexant_auto),
+ HDA_CODEC_ENTRY(0x14f120d1, "SN6180", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto),
HDA_CODEC_ENTRY(0x14f15051, "CX20561 (Hermosa)", patch_conexant_auto),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 9670db6ad1e1..9cedb78bffe7 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -771,7 +771,7 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
alc_setup_gpio(codec, 0x02);
break;
case 7:
- alc_setup_gpio(codec, 0x03);
+ alc_setup_gpio(codec, 0x04);
break;
case 5:
default:
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 937155b1fae0..9e2252eee626 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -834,6 +834,9 @@ static int add_secret_dac_path(struct hda_codec *codec)
return 0;
nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
ARRAY_SIZE(conn) - 1);
+ if (nums < 0)
+ return nums;
+
for (i = 0; i < nums; i++) {
if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
return 0;
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c
index a80684bdc30d..46f536209671 100644
--- a/sound/pci/lx6464es/lx_core.c
+++ b/sound/pci/lx6464es/lx_core.c
@@ -508,12 +508,11 @@ int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture,
dev_dbg(chip->card->dev,
"CMD_08_ASK_BUFFERS: needed %d, freed %d\n",
*r_needed, *r_freed);
- for (i = 0; i < MAX_STREAM_BUFFER; ++i) {
- for (i = 0; i != chip->rmh.stat_len; ++i)
- dev_dbg(chip->card->dev,
- " stat[%d]: %x, %x\n", i,
- chip->rmh.stat[i],
- chip->rmh.stat[i] & MASK_DATA_SIZE);
+ for (i = 0; i < MAX_STREAM_BUFFER && i < chip->rmh.stat_len;
+ ++i) {
+ dev_dbg(chip->card->dev, " stat[%d]: %x, %x\n", i,
+ chip->rmh.stat[i],
+ chip->rmh.stat[i] & MASK_DATA_SIZE);
}
}
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index deaad703a7db..a4826a7d0a98 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -1204,18 +1204,12 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
if (pdata) {
cs42l56->pdata = *pdata;
} else {
- pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata),
- GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
-
if (i2c_client->dev.of_node) {
ret = cs42l56_handle_of_data(i2c_client,
&cs42l56->pdata);
if (ret != 0)
return ret;
}
- cs42l56->pdata = *pdata;
}
if (cs42l56->pdata.gpio_nreset) {
diff --git a/sound/synth/emux/emux_nrpn.c b/sound/synth/emux/emux_nrpn.c
index 9729a15b6ae6..f4aa2706aeb6 100644
--- a/sound/synth/emux/emux_nrpn.c
+++ b/sound/synth/emux/emux_nrpn.c
@@ -363,6 +363,9 @@ int
snd_emux_xg_control(struct snd_emux_port *port, struct snd_midi_channel *chan,
int param)
{
+ if (param >= ARRAY_SIZE(chan->control))
+ return -EINVAL;
+
return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects),
port, chan, param,
chan->control[param],
diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
index ee03552b4116..7ead9d2aa6b8 100644
--- a/tools/testing/selftests/net/forwarding/lib.sh
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -519,14 +519,14 @@ sysctl_set()
local value=$1; shift
SYSCTL_ORIG[$key]=$(sysctl -n $key)
- sysctl -qw $key=$value
+ sysctl -qw $key="$value"
}
sysctl_restore()
{
local key=$1; shift
- sysctl -qw $key=${SYSCTL_ORIG["$key"]}
+ sysctl -qw $key="${SYSCTL_ORIG[$key]}"
}
forwarding_enable()
diff --git a/tools/virtio/linux/bug.h b/tools/virtio/linux/bug.h
index b14c2c3b6b85..74aef964f509 100644
--- a/tools/virtio/linux/bug.h
+++ b/tools/virtio/linux/bug.h
@@ -1,11 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef BUG_H
-#define BUG_H
+#ifndef _LINUX_BUG_H
+#define _LINUX_BUG_H
#define BUG_ON(__BUG_ON_cond) assert(!(__BUG_ON_cond))
-#define BUILD_BUG_ON(x)
-
#define BUG() abort()
-#endif /* BUG_H */
+#endif /* _LINUX_BUG_H */
diff --git a/tools/virtio/linux/build_bug.h b/tools/virtio/linux/build_bug.h
new file mode 100644
index 000000000000..cdbb75e28a60
--- /dev/null
+++ b/tools/virtio/linux/build_bug.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_BUILD_BUG_H
+#define _LINUX_BUILD_BUG_H
+
+#define BUILD_BUG_ON(x)
+
+#endif /* _LINUX_BUILD_BUG_H */
diff --git a/tools/virtio/linux/cpumask.h b/tools/virtio/linux/cpumask.h
new file mode 100644
index 000000000000..307da69d6b26
--- /dev/null
+++ b/tools/virtio/linux/cpumask.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_CPUMASK_H
+#define _LINUX_CPUMASK_H
+
+#include <linux/kernel.h>
+
+#endif /* _LINUX_CPUMASK_H */
diff --git a/tools/virtio/linux/gfp.h b/tools/virtio/linux/gfp.h
new file mode 100644
index 000000000000..43d146f236f1
--- /dev/null
+++ b/tools/virtio/linux/gfp.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_GFP_H
+#define __LINUX_GFP_H
+
+#include <linux/topology.h>
+
+#endif
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h
index 7ef45a4a3cba..0dc38fe2a4f1 100644
--- a/tools/virtio/linux/kernel.h
+++ b/tools/virtio/linux/kernel.h
@@ -10,6 +10,7 @@
#include <stdarg.h>
#include <linux/compiler.h>
+#include <linux/log2.h>
#include <linux/types.h>
#include <linux/printk.h>
#include <linux/bug.h>
diff --git a/tools/virtio/linux/kmsan.h b/tools/virtio/linux/kmsan.h
new file mode 100644
index 000000000000..272b5aa285d5
--- /dev/null
+++ b/tools/virtio/linux/kmsan.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_KMSAN_H
+#define _LINUX_KMSAN_H
+
+#include <linux/gfp.h>
+
+inline void kmsan_handle_dma(struct page *page, size_t offset, size_t size,
+ enum dma_data_direction dir)
+{
+}
+
+#endif /* _LINUX_KMSAN_H */
diff --git a/tools/virtio/linux/scatterlist.h b/tools/virtio/linux/scatterlist.h
index 369ee308b668..74d9e1825748 100644
--- a/tools/virtio/linux/scatterlist.h
+++ b/tools/virtio/linux/scatterlist.h
@@ -2,6 +2,7 @@
#ifndef SCATTERLIST_H
#define SCATTERLIST_H
#include <linux/kernel.h>
+#include <linux/bug.h>
struct scatterlist {
unsigned long page_link;
diff --git a/tools/virtio/linux/topology.h b/tools/virtio/linux/topology.h
new file mode 100644
index 000000000000..910794afb993
--- /dev/null
+++ b/tools/virtio/linux/topology.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_TOPOLOGY_H
+#define _LINUX_TOPOLOGY_H
+
+#include <linux/cpumask.h>
+
+#endif /* _LINUX_TOPOLOGY_H */
^ permalink raw reply related [relevance 1%]
* Re: [PATCH v7 01/22] drm/edid: fix AVI infoframe aspect ratio handling
2023-01-04 10:05 5% ` [PATCH v7 01/22] drm/edid: fix AVI infoframe aspect ratio handling Jani Nikula
@ 2023-01-18 14:56 0% ` Ville Syrjälä
0 siblings, 0 replies; 200+ results
From: Ville Syrjälä @ 2023-01-18 14:56 UTC (permalink / raw)
To: Jani Nikula; +Cc: dri-devel, intel-gfx, William Tseng, stable
On Wed, Jan 04, 2023 at 12:05:16PM +0200, Jani Nikula wrote:
> We try to avoid sending VICs defined in the later specs in AVI
> infoframes to sinks that conform to the earlier specs, to not upset
> them, and use 0 for the VIC instead. However, we do this detection and
> conversion to 0 too early, as we'll need the actual VIC to figure out
> the aspect ratio.
>
> In particular, for a mode with 64:27 aspect ratio, 0 for VIC fails the
> AVI infoframe generation altogether with -EINVAL.
>
> Separate the VIC lookup from the "filtering", and postpone the
> filtering, to use the proper VIC for aspect ratio handling, and the 0
> VIC for the infoframe video code as needed.
>
> Reported-by: William Tseng <william.tseng@intel.com>
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6153
> References: https://lore.kernel.org/r/20220920062316.43162-1-william.tseng@intel.com
> Cc: <stable@vger.kernel.org>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
> drivers/gpu/drm/drm_edid.c | 21 ++++++++++++---------
> 1 file changed, 12 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 3841aba17abd..23f7146e6a9b 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -6885,8 +6885,6 @@ static u8 drm_mode_hdmi_vic(const struct drm_connector *connector,
> static u8 drm_mode_cea_vic(const struct drm_connector *connector,
> const struct drm_display_mode *mode)
> {
> - u8 vic;
> -
> /*
> * HDMI spec says if a mode is found in HDMI 1.4b 4K modes
> * we should send its VIC in vendor infoframes, else send the
> @@ -6896,13 +6894,18 @@ static u8 drm_mode_cea_vic(const struct drm_connector *connector,
> if (drm_mode_hdmi_vic(connector, mode))
> return 0;
>
> - vic = drm_match_cea_mode(mode);
> + return drm_match_cea_mode(mode);
> +}
>
> - /*
> - * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
> - * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
> - * have to make sure we dont break HDMI 1.4 sinks.
> - */
> +/*
> + * Avoid sending VICs defined in HDMI 2.0 in AVI infoframes to sinks that
> + * conform to HDMI 1.4.
> + *
> + * HDMI 1.4 (CTA-861-D) VIC range: [1..64]
> + * HDMI 2.0 (CTA-861-F) VIC range: [1..107]
> + */
> +static u8 vic_for_avi_infoframe(const struct drm_connector *connector, u8 vic)
> +{
> if (!is_hdmi2_sink(connector) && vic > 64)
> return 0;
>
> @@ -6978,7 +6981,7 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
> picture_aspect = HDMI_PICTURE_ASPECT_NONE;
> }
>
> - frame->video_code = vic;
> + frame->video_code = vic_for_avi_infoframe(connector, vic);
> frame->picture_aspect = picture_aspect;
> frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
> frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
> --
> 2.34.1
--
Ville Syrjälä
Intel
^ permalink raw reply [relevance 0%]
* [PATCH v7 01/22] drm/edid: fix AVI infoframe aspect ratio handling
[not found] <cover.1672826282.git.jani.nikula@intel.com>
@ 2023-01-04 10:05 5% ` Jani Nikula
2023-01-18 14:56 0% ` Ville Syrjälä
0 siblings, 1 reply; 200+ results
From: Jani Nikula @ 2023-01-04 10:05 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, ville.syrjala, jani.nikula, William Tseng, stable
We try to avoid sending VICs defined in the later specs in AVI
infoframes to sinks that conform to the earlier specs, to not upset
them, and use 0 for the VIC instead. However, we do this detection and
conversion to 0 too early, as we'll need the actual VIC to figure out
the aspect ratio.
In particular, for a mode with 64:27 aspect ratio, 0 for VIC fails the
AVI infoframe generation altogether with -EINVAL.
Separate the VIC lookup from the "filtering", and postpone the
filtering, to use the proper VIC for aspect ratio handling, and the 0
VIC for the infoframe video code as needed.
Reported-by: William Tseng <william.tseng@intel.com>
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6153
References: https://lore.kernel.org/r/20220920062316.43162-1-william.tseng@intel.com
Cc: <stable@vger.kernel.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
drivers/gpu/drm/drm_edid.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 3841aba17abd..23f7146e6a9b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6885,8 +6885,6 @@ static u8 drm_mode_hdmi_vic(const struct drm_connector *connector,
static u8 drm_mode_cea_vic(const struct drm_connector *connector,
const struct drm_display_mode *mode)
{
- u8 vic;
-
/*
* HDMI spec says if a mode is found in HDMI 1.4b 4K modes
* we should send its VIC in vendor infoframes, else send the
@@ -6896,13 +6894,18 @@ static u8 drm_mode_cea_vic(const struct drm_connector *connector,
if (drm_mode_hdmi_vic(connector, mode))
return 0;
- vic = drm_match_cea_mode(mode);
+ return drm_match_cea_mode(mode);
+}
- /*
- * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
- * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
- * have to make sure we dont break HDMI 1.4 sinks.
- */
+/*
+ * Avoid sending VICs defined in HDMI 2.0 in AVI infoframes to sinks that
+ * conform to HDMI 1.4.
+ *
+ * HDMI 1.4 (CTA-861-D) VIC range: [1..64]
+ * HDMI 2.0 (CTA-861-F) VIC range: [1..107]
+ */
+static u8 vic_for_avi_infoframe(const struct drm_connector *connector, u8 vic)
+{
if (!is_hdmi2_sink(connector) && vic > 64)
return 0;
@@ -6978,7 +6981,7 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
picture_aspect = HDMI_PICTURE_ASPECT_NONE;
}
- frame->video_code = vic;
+ frame->video_code = vic_for_avi_infoframe(connector, vic);
frame->picture_aspect = picture_aspect;
frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
--
2.34.1
^ permalink raw reply related [relevance 5%]
* [PATCH 6.0 031/197] netfilter: nf_tables: release flow rule object from commit path
@ 2022-11-08 13:37 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-11-08 13:37 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+8f747f62763bc6c32916,
Pablo Neira Ayuso, Sasha Levin
From: Pablo Neira Ayuso <pablo@netfilter.org>
[ Upstream commit 26b5934ff4194e13196bedcba373cd4915071d0e ]
No need to postpone this to the commit release path, since no packets
are walking over this object, this is accessed from control plane only.
This helped uncovered UAF triggered by races with the netlink notifier.
Fixes: 9dd732e0bdf5 ("netfilter: nf_tables: memleak flow rule from commit path")
Reported-by: syzbot+8f747f62763bc6c32916@syzkaller.appspotmail.com
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/nf_tables_api.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index cc598504bc10..879f4a1a27d5 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -8465,9 +8465,6 @@ static void nft_commit_release(struct nft_trans *trans)
nf_tables_chain_destroy(&trans->ctx);
break;
case NFT_MSG_DELRULE:
- if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
- nft_flow_rule_destroy(nft_trans_flow_rule(trans));
-
nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
break;
case NFT_MSG_DELSET:
@@ -8973,6 +8970,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
nft_rule_expr_deactivate(&trans->ctx,
nft_trans_rule(trans),
NFT_TRANS_COMMIT);
+
+ if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
+ nft_flow_rule_destroy(nft_trans_flow_rule(trans));
break;
case NFT_MSG_NEWSET:
nft_clear(net, nft_trans_set(trans));
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH 5.15 037/144] netfilter: nf_tables: release flow rule object from commit path
@ 2022-11-08 13:38 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-11-08 13:38 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+8f747f62763bc6c32916,
Pablo Neira Ayuso, Sasha Levin
From: Pablo Neira Ayuso <pablo@netfilter.org>
[ Upstream commit 26b5934ff4194e13196bedcba373cd4915071d0e ]
No need to postpone this to the commit release path, since no packets
are walking over this object, this is accessed from control plane only.
This helped uncovered UAF triggered by races with the netlink notifier.
Fixes: 9dd732e0bdf5 ("netfilter: nf_tables: memleak flow rule from commit path")
Reported-by: syzbot+8f747f62763bc6c32916@syzkaller.appspotmail.com
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/nf_tables_api.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 8cd11a7e5a3e..899f01c6c26c 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -8308,9 +8308,6 @@ static void nft_commit_release(struct nft_trans *trans)
nf_tables_chain_destroy(&trans->ctx);
break;
case NFT_MSG_DELRULE:
- if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
- nft_flow_rule_destroy(nft_trans_flow_rule(trans));
-
nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
break;
case NFT_MSG_DELSET:
@@ -8767,6 +8764,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
nft_rule_expr_deactivate(&trans->ctx,
nft_trans_rule(trans),
NFT_TRANS_COMMIT);
+
+ if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
+ nft_flow_rule_destroy(nft_trans_flow_rule(trans));
break;
case NFT_MSG_NEWSET:
nft_clear(net, nft_trans_set(trans));
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH 5.10 032/118] netfilter: nf_tables: release flow rule object from commit path
@ 2022-11-08 13:38 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-11-08 13:38 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+8f747f62763bc6c32916,
Pablo Neira Ayuso, Sasha Levin
From: Pablo Neira Ayuso <pablo@netfilter.org>
[ Upstream commit 26b5934ff4194e13196bedcba373cd4915071d0e ]
No need to postpone this to the commit release path, since no packets
are walking over this object, this is accessed from control plane only.
This helped uncovered UAF triggered by races with the netlink notifier.
Fixes: 9dd732e0bdf5 ("netfilter: nf_tables: memleak flow rule from commit path")
Reported-by: syzbot+8f747f62763bc6c32916@syzkaller.appspotmail.com
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/nf_tables_api.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 810995d712ac..2143edafba77 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -7527,9 +7527,6 @@ static void nft_commit_release(struct nft_trans *trans)
nf_tables_chain_destroy(&trans->ctx);
break;
case NFT_MSG_DELRULE:
- if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
- nft_flow_rule_destroy(nft_trans_flow_rule(trans));
-
nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
break;
case NFT_MSG_DELSET:
@@ -7973,6 +7970,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
nft_rule_expr_deactivate(&trans->ctx,
nft_trans_rule(trans),
NFT_TRANS_COMMIT);
+
+ if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
+ nft_flow_rule_destroy(nft_trans_flow_rule(trans));
break;
case NFT_MSG_NEWSET:
nft_clear(net, nft_trans_set(trans));
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH 5.4 15/74] netfilter: nf_tables: release flow rule object from commit path
@ 2022-11-08 13:38 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-11-08 13:38 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+8f747f62763bc6c32916,
Pablo Neira Ayuso, Sasha Levin
From: Pablo Neira Ayuso <pablo@netfilter.org>
[ Upstream commit 26b5934ff4194e13196bedcba373cd4915071d0e ]
No need to postpone this to the commit release path, since no packets
are walking over this object, this is accessed from control plane only.
This helped uncovered UAF triggered by races with the netlink notifier.
Fixes: 9dd732e0bdf5 ("netfilter: nf_tables: memleak flow rule from commit path")
Reported-by: syzbot+8f747f62763bc6c32916@syzkaller.appspotmail.com
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/nf_tables_api.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index f9cecd30f1ba..140c24f1b6c6 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -6576,9 +6576,6 @@ static void nft_commit_release(struct nft_trans *trans)
nf_tables_chain_destroy(&trans->ctx);
break;
case NFT_MSG_DELRULE:
- if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
- nft_flow_rule_destroy(nft_trans_flow_rule(trans));
-
nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
break;
case NFT_MSG_DELSET:
@@ -6913,6 +6910,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
nft_rule_expr_deactivate(&trans->ctx,
nft_trans_rule(trans),
NFT_TRANS_COMMIT);
+
+ if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
+ nft_flow_rule_destroy(nft_trans_flow_rule(trans));
break;
case NFT_MSG_NEWSET:
nft_clear(net, nft_trans_set(trans));
--
2.35.1
^ permalink raw reply related [relevance 5%]
* Re: [PATCH 5.18 00/61] 5.18.12-rc1 review
@ 2022-07-15 11:27 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-07-15 11:27 UTC (permalink / raw)
To: linux-kernel
Cc: stable, torvalds, akpm, linux, shuah, patches, lkft-triage,
pavel, jonathanh, f.fainelli, sudipm.mukherjee, slade
On Tue, Jul 12, 2022 at 08:38:57PM +0200, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 5.18.12 release.
> There are 61 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu, 14 Jul 2022 18:32:19 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.18.12-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.18.y
> and the diffstat can be found below.
With all the problems that this, and the 5.15.y and 5.10.y trees are
having right now, I'm going to postpone this whole set of -rc releases
and get to them next week, when all of the needed fixup patches have hit
Linus's tree.
Sorry for the delay all, and thank you to everyone for all of the
testing. The problems are purely due to the fact that we were forced to
do this type of work "in private" with very limited ability for testing
by the normal larger kernel community like we rely on. We don't have
fancy or huge private testing labs where we can do all of this work as
we are an open source project, and we rely on open testing in public.
So thanks all for your understanding with the delay. If you _really_
need protection from RETBLEED, you can grab these patches now, as maybe
the corner cases we have hit so far don't affect you. Otherwise they
should be ready next week, and I'll do a whole new round of -rc1 with
them.
greg k-h
^ permalink raw reply [relevance 5%]
* Re: Linux 5.18.10
@ 2022-07-07 16:08 1% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-07-07 16:08 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/Makefile b/Makefile
index 751cfd786c8c..088b84f99203 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 18
-SUBLEVEL = 9
+SUBLEVEL = 10
EXTRAVERSION =
NAME = Superb Owl
diff --git a/arch/arm/xen/p2m.c b/arch/arm/xen/p2m.c
index 84a1cea1f43b..309648c17f48 100644
--- a/arch/arm/xen/p2m.c
+++ b/arch/arm/xen/p2m.c
@@ -63,11 +63,12 @@ static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
unsigned long __pfn_to_mfn(unsigned long pfn)
{
- struct rb_node *n = phys_to_mach.rb_node;
+ struct rb_node *n;
struct xen_p2m_entry *entry;
unsigned long irqflags;
read_lock_irqsave(&p2m_lock, irqflags);
+ n = phys_to_mach.rb_node;
while (n) {
entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
if (entry->pfn <= pfn &&
@@ -152,10 +153,11 @@ bool __set_phys_to_machine_multi(unsigned long pfn,
int rc;
unsigned long irqflags;
struct xen_p2m_entry *p2m_entry;
- struct rb_node *n = phys_to_mach.rb_node;
+ struct rb_node *n;
if (mfn == INVALID_P2M_ENTRY) {
write_lock_irqsave(&p2m_lock, irqflags);
+ n = phys_to_mach.rb_node;
while (n) {
p2m_entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
if (p2m_entry->pfn <= pfn &&
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index 2673d57eeb00..94652e13c260 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -224,8 +224,13 @@ int main(void)
BLANK();
DEFINE(ASM_SIGFRAME_SIZE, PARISC_RT_SIGFRAME_SIZE);
DEFINE(SIGFRAME_CONTEXT_REGS, offsetof(struct rt_sigframe, uc.uc_mcontext) - PARISC_RT_SIGFRAME_SIZE);
+#ifdef CONFIG_64BIT
DEFINE(ASM_SIGFRAME_SIZE32, PARISC_RT_SIGFRAME_SIZE32);
DEFINE(SIGFRAME_CONTEXT_REGS32, offsetof(struct compat_rt_sigframe, uc.uc_mcontext) - PARISC_RT_SIGFRAME_SIZE32);
+#else
+ DEFINE(ASM_SIGFRAME_SIZE32, PARISC_RT_SIGFRAME_SIZE);
+ DEFINE(SIGFRAME_CONTEXT_REGS32, offsetof(struct rt_sigframe, uc.uc_mcontext) - PARISC_RT_SIGFRAME_SIZE);
+#endif
BLANK();
DEFINE(ICACHE_BASE, offsetof(struct pdc_cache_info, ic_base));
DEFINE(ICACHE_STRIDE, offsetof(struct pdc_cache_info, ic_stride));
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index ed1e88a74dc4..bac581b5ecfc 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -146,7 +146,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
" depw %%r0,31,2,%4\n"
"1: ldw 0(%%sr1,%4),%0\n"
"2: ldw 4(%%sr1,%4),%3\n"
-" subi 32,%4,%2\n"
+" subi 32,%2,%2\n"
" mtctl %2,11\n"
" vshd %0,%3,%0\n"
"3: \n"
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 500f2a0831ef..45e471516c3c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -358,6 +358,10 @@ config ARCH_SUSPEND_NONZERO_CPU
def_bool y
depends on PPC_POWERNV || PPC_PSERIES
+config ARCH_HAS_ADD_PAGES
+ def_bool y
+ depends on ARCH_ENABLE_MEMORY_HOTPLUG
+
config PPC_DCR_NATIVE
bool
diff --git a/arch/powerpc/include/asm/bpf_perf_event.h b/arch/powerpc/include/asm/bpf_perf_event.h
new file mode 100644
index 000000000000..e8a7b4ffb58c
--- /dev/null
+++ b/arch/powerpc/include/asm/bpf_perf_event.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_BPF_PERF_EVENT_H
+#define _ASM_POWERPC_BPF_PERF_EVENT_H
+
+#include <asm/ptrace.h>
+
+typedef struct user_pt_regs bpf_user_pt_regs_t;
+
+#endif /* _ASM_POWERPC_BPF_PERF_EVENT_H */
diff --git a/arch/powerpc/include/uapi/asm/bpf_perf_event.h b/arch/powerpc/include/uapi/asm/bpf_perf_event.h
deleted file mode 100644
index 5e1e648aeec4..000000000000
--- a/arch/powerpc/include/uapi/asm/bpf_perf_event.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
-#define _UAPI__ASM_BPF_PERF_EVENT_H__
-
-#include <asm/ptrace.h>
-
-typedef struct user_pt_regs bpf_user_pt_regs_t;
-
-#endif /* _UAPI__ASM_BPF_PERF_EVENT_H__ */
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
index b183ab9c5107..dfa5f729f774 100644
--- a/arch/powerpc/kernel/prom_init_check.sh
+++ b/arch/powerpc/kernel/prom_init_check.sh
@@ -13,7 +13,7 @@
# If you really need to reference something from prom_init.o add
# it to the list below:
-grep "^CONFIG_KASAN=y$" .config >/dev/null
+grep "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} >/dev/null
if [ $? -eq 0 ]
then
MEM_FUNCS="__memcpy __memset"
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 149635e5c165..5dd434d80f44 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -103,6 +103,37 @@ void __ref arch_remove_linear_mapping(u64 start, u64 size)
vm_unmap_aliases();
}
+/*
+ * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need
+ * updating.
+ */
+static void update_end_of_memory_vars(u64 start, u64 size)
+{
+ unsigned long end_pfn = PFN_UP(start + size);
+
+ if (end_pfn > max_pfn) {
+ max_pfn = end_pfn;
+ max_low_pfn = end_pfn;
+ high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+ }
+}
+
+int __ref add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
+ struct mhp_params *params)
+{
+ int ret;
+
+ ret = __add_pages(nid, start_pfn, nr_pages, params);
+ if (ret)
+ return ret;
+
+ /* update max_pfn, max_low_pfn and high_memory */
+ update_end_of_memory_vars(start_pfn << PAGE_SHIFT,
+ nr_pages << PAGE_SHIFT);
+
+ return ret;
+}
+
int __ref arch_add_memory(int nid, u64 start, u64 size,
struct mhp_params *params)
{
@@ -113,7 +144,7 @@ int __ref arch_add_memory(int nid, u64 start, u64 size,
rc = arch_create_linear_mapping(nid, start, size, params);
if (rc)
return rc;
- rc = __add_pages(nid, start_pfn, nr_pages, params);
+ rc = add_pages(nid, start_pfn, nr_pages, params);
if (rc)
arch_remove_linear_mapping(start, size);
return rc;
diff --git a/arch/powerpc/mm/nohash/book3e_pgtable.c b/arch/powerpc/mm/nohash/book3e_pgtable.c
index 7d4368d055a6..b80fc4a91a53 100644
--- a/arch/powerpc/mm/nohash/book3e_pgtable.c
+++ b/arch/powerpc/mm/nohash/book3e_pgtable.c
@@ -96,8 +96,8 @@ int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
pgdp = pgd_offset_k(ea);
p4dp = p4d_offset(pgdp, ea);
if (p4d_none(*p4dp)) {
- pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
- p4d_populate(&init_mm, p4dp, pmdp);
+ pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
+ p4d_populate(&init_mm, p4dp, pudp);
}
pudp = pud_offset(p4dp, ea);
if (pud_none(*pudp)) {
@@ -106,7 +106,7 @@ int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
}
pmdp = pmd_offset(pudp, ea);
if (!pmd_present(*pmdp)) {
- ptep = early_alloc_pgtable(PAGE_SIZE);
+ ptep = early_alloc_pgtable(PTE_TABLE_SIZE);
pmd_populate_kernel(&init_mm, pmdp, ptep);
}
ptep = pte_offset_kernel(pmdp, ea);
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 359b0cc0dc35..d7dcad901146 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -487,7 +487,6 @@ config KEXEC
config KEXEC_FILE
bool "kexec file based system call"
select KEXEC_CORE
- select BUILD_BIN2C
depends on CRYPTO
depends on CRYPTO_SHA256
depends on CRYPTO_SHA256_S390
diff --git a/arch/s390/crypto/arch_random.c b/arch/s390/crypto/arch_random.c
index 56007c763902..1f2d40993c4d 100644
--- a/arch/s390/crypto/arch_random.c
+++ b/arch/s390/crypto/arch_random.c
@@ -4,232 +4,15 @@
*
* Copyright IBM Corp. 2017, 2020
* Author(s): Harald Freudenberger
- *
- * The s390_arch_random_generate() function may be called from random.c
- * in interrupt context. So this implementation does the best to be very
- * fast. There is a buffer of random data which is asynchronously checked
- * and filled by a workqueue thread.
- * If there are enough bytes in the buffer the s390_arch_random_generate()
- * just delivers these bytes. Otherwise false is returned until the
- * worker thread refills the buffer.
- * The worker fills the rng buffer by pulling fresh entropy from the
- * high quality (but slow) true hardware random generator. This entropy
- * is then spread over the buffer with an pseudo random generator PRNG.
- * As the arch_get_random_seed_long() fetches 8 bytes and the calling
- * function add_interrupt_randomness() counts this as 1 bit entropy the
- * distribution needs to make sure there is in fact 1 bit entropy contained
- * in 8 bytes of the buffer. The current values pull 32 byte entropy
- * and scatter this into a 2048 byte buffer. So 8 byte in the buffer
- * will contain 1 bit of entropy.
- * The worker thread is rescheduled based on the charge level of the
- * buffer but at least with 500 ms delay to avoid too much CPU consumption.
- * So the max. amount of rng data delivered via arch_get_random_seed is
- * limited to 4k bytes per second.
*/
#include <linux/kernel.h>
#include <linux/atomic.h>
#include <linux/random.h>
-#include <linux/slab.h>
#include <linux/static_key.h>
-#include <linux/workqueue.h>
-#include <linux/moduleparam.h>
#include <asm/cpacf.h>
DEFINE_STATIC_KEY_FALSE(s390_arch_random_available);
atomic64_t s390_arch_random_counter = ATOMIC64_INIT(0);
EXPORT_SYMBOL(s390_arch_random_counter);
-
-#define ARCH_REFILL_TICKS (HZ/2)
-#define ARCH_PRNG_SEED_SIZE 32
-#define ARCH_RNG_BUF_SIZE 2048
-
-static DEFINE_SPINLOCK(arch_rng_lock);
-static u8 *arch_rng_buf;
-static unsigned int arch_rng_buf_idx;
-
-static void arch_rng_refill_buffer(struct work_struct *);
-static DECLARE_DELAYED_WORK(arch_rng_work, arch_rng_refill_buffer);
-
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes)
-{
- /* max hunk is ARCH_RNG_BUF_SIZE */
- if (nbytes > ARCH_RNG_BUF_SIZE)
- return false;
-
- /* lock rng buffer */
- if (!spin_trylock(&arch_rng_lock))
- return false;
-
- /* try to resolve the requested amount of bytes from the buffer */
- arch_rng_buf_idx -= nbytes;
- if (arch_rng_buf_idx < ARCH_RNG_BUF_SIZE) {
- memcpy(buf, arch_rng_buf + arch_rng_buf_idx, nbytes);
- atomic64_add(nbytes, &s390_arch_random_counter);
- spin_unlock(&arch_rng_lock);
- return true;
- }
-
- /* not enough bytes in rng buffer, refill is done asynchronously */
- spin_unlock(&arch_rng_lock);
-
- return false;
-}
-EXPORT_SYMBOL(s390_arch_random_generate);
-
-static void arch_rng_refill_buffer(struct work_struct *unused)
-{
- unsigned int delay = ARCH_REFILL_TICKS;
-
- spin_lock(&arch_rng_lock);
- if (arch_rng_buf_idx > ARCH_RNG_BUF_SIZE) {
- /* buffer is exhausted and needs refill */
- u8 seed[ARCH_PRNG_SEED_SIZE];
- u8 prng_wa[240];
- /* fetch ARCH_PRNG_SEED_SIZE bytes of entropy */
- cpacf_trng(NULL, 0, seed, sizeof(seed));
- /* blow this entropy up to ARCH_RNG_BUF_SIZE with PRNG */
- memset(prng_wa, 0, sizeof(prng_wa));
- cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
- &prng_wa, NULL, 0, seed, sizeof(seed));
- cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
- &prng_wa, arch_rng_buf, ARCH_RNG_BUF_SIZE, NULL, 0);
- arch_rng_buf_idx = ARCH_RNG_BUF_SIZE;
- }
- delay += (ARCH_REFILL_TICKS * arch_rng_buf_idx) / ARCH_RNG_BUF_SIZE;
- spin_unlock(&arch_rng_lock);
-
- /* kick next check */
- queue_delayed_work(system_long_wq, &arch_rng_work, delay);
-}
-
-/*
- * Here follows the implementation of s390_arch_get_random_long().
- *
- * The random longs to be pulled by arch_get_random_long() are
- * prepared in an 4K buffer which is filled from the NIST 800-90
- * compliant s390 drbg. By default the random long buffer is refilled
- * 256 times before the drbg itself needs a reseed. The reseed of the
- * drbg is done with 32 bytes fetched from the high quality (but slow)
- * trng which is assumed to deliver 100% entropy. So the 32 * 8 = 256
- * bits of entropy are spread over 256 * 4KB = 1MB serving 131072
- * arch_get_random_long() invocations before reseeded.
- *
- * How often the 4K random long buffer is refilled with the drbg
- * before the drbg is reseeded can be adjusted. There is a module
- * parameter 's390_arch_rnd_long_drbg_reseed' accessible via
- * /sys/module/arch_random/parameters/rndlong_drbg_reseed
- * or as kernel command line parameter
- * arch_random.rndlong_drbg_reseed=<value>
- * This parameter tells how often the drbg fills the 4K buffer before
- * it is re-seeded by fresh entropy from the trng.
- * A value of 16 results in reseeding the drbg at every 16 * 4 KB = 64
- * KB with 32 bytes of fresh entropy pulled from the trng. So a value
- * of 16 would result in 256 bits entropy per 64 KB.
- * A value of 256 results in 1MB of drbg output before a reseed of the
- * drbg is done. So this would spread the 256 bits of entropy among 1MB.
- * Setting this parameter to 0 forces the reseed to take place every
- * time the 4K buffer is depleted, so the entropy rises to 256 bits
- * entropy per 4K or 0.5 bit entropy per arch_get_random_long(). With
- * setting this parameter to negative values all this effort is
- * disabled, arch_get_random long() returns false and thus indicating
- * that the arch_get_random_long() feature is disabled at all.
- */
-
-static unsigned long rndlong_buf[512];
-static DEFINE_SPINLOCK(rndlong_lock);
-static int rndlong_buf_index;
-
-static int rndlong_drbg_reseed = 256;
-module_param_named(rndlong_drbg_reseed, rndlong_drbg_reseed, int, 0600);
-MODULE_PARM_DESC(rndlong_drbg_reseed, "s390 arch_get_random_long() drbg reseed");
-
-static inline void refill_rndlong_buf(void)
-{
- static u8 prng_ws[240];
- static int drbg_counter;
-
- if (--drbg_counter < 0) {
- /* need to re-seed the drbg */
- u8 seed[32];
-
- /* fetch seed from trng */
- cpacf_trng(NULL, 0, seed, sizeof(seed));
- /* seed drbg */
- memset(prng_ws, 0, sizeof(prng_ws));
- cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
- &prng_ws, NULL, 0, seed, sizeof(seed));
- /* re-init counter for drbg */
- drbg_counter = rndlong_drbg_reseed;
- }
-
- /* fill the arch_get_random_long buffer from drbg */
- cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &prng_ws,
- (u8 *) rndlong_buf, sizeof(rndlong_buf),
- NULL, 0);
-}
-
-bool s390_arch_get_random_long(unsigned long *v)
-{
- bool rc = false;
- unsigned long flags;
-
- /* arch_get_random_long() disabled ? */
- if (rndlong_drbg_reseed < 0)
- return false;
-
- /* try to lock the random long lock */
- if (!spin_trylock_irqsave(&rndlong_lock, flags))
- return false;
-
- if (--rndlong_buf_index >= 0) {
- /* deliver next long value from the buffer */
- *v = rndlong_buf[rndlong_buf_index];
- rc = true;
- goto out;
- }
-
- /* buffer is depleted and needs refill */
- if (in_interrupt()) {
- /* delay refill in interrupt context to next caller */
- rndlong_buf_index = 0;
- goto out;
- }
-
- /* refill random long buffer */
- refill_rndlong_buf();
- rndlong_buf_index = ARRAY_SIZE(rndlong_buf);
-
- /* and provide one random long */
- *v = rndlong_buf[--rndlong_buf_index];
- rc = true;
-
-out:
- spin_unlock_irqrestore(&rndlong_lock, flags);
- return rc;
-}
-EXPORT_SYMBOL(s390_arch_get_random_long);
-
-static int __init s390_arch_random_init(void)
-{
- /* all the needed PRNO subfunctions available ? */
- if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG) &&
- cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) {
-
- /* alloc arch random working buffer */
- arch_rng_buf = kmalloc(ARCH_RNG_BUF_SIZE, GFP_KERNEL);
- if (!arch_rng_buf)
- return -ENOMEM;
-
- /* kick worker queue job to fill the random buffer */
- queue_delayed_work(system_long_wq,
- &arch_rng_work, ARCH_REFILL_TICKS);
-
- /* enable arch random to the outside world */
- static_branch_enable(&s390_arch_random_available);
- }
-
- return 0;
-}
-arch_initcall(s390_arch_random_init);
diff --git a/arch/s390/include/asm/archrandom.h b/arch/s390/include/asm/archrandom.h
index 5dc712fde3c7..2c6e1c6ecbe7 100644
--- a/arch/s390/include/asm/archrandom.h
+++ b/arch/s390/include/asm/archrandom.h
@@ -15,17 +15,13 @@
#include <linux/static_key.h>
#include <linux/atomic.h>
+#include <asm/cpacf.h>
DECLARE_STATIC_KEY_FALSE(s390_arch_random_available);
extern atomic64_t s390_arch_random_counter;
-bool s390_arch_get_random_long(unsigned long *v);
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes);
-
static inline bool __must_check arch_get_random_long(unsigned long *v)
{
- if (static_branch_likely(&s390_arch_random_available))
- return s390_arch_get_random_long(v);
return false;
}
@@ -37,7 +33,9 @@ static inline bool __must_check arch_get_random_int(unsigned int *v)
static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
{
if (static_branch_likely(&s390_arch_random_available)) {
- return s390_arch_random_generate((u8 *)v, sizeof(*v));
+ cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+ atomic64_add(sizeof(*v), &s390_arch_random_counter);
+ return true;
}
return false;
}
@@ -45,7 +43,9 @@ static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
{
if (static_branch_likely(&s390_arch_random_available)) {
- return s390_arch_random_generate((u8 *)v, sizeof(*v));
+ cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+ atomic64_add(sizeof(*v), &s390_arch_random_counter);
+ return true;
}
return false;
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index d860ac300919..2cef49983e9e 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -875,6 +875,11 @@ static void __init setup_randomness(void)
if (stsi(vmms, 3, 2, 2) == 0 && vmms->count)
add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count);
memblock_free(vmms, PAGE_SIZE);
+
+#ifdef CONFIG_ARCH_RANDOM
+ if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
+ static_branch_enable(&s390_arch_random_available);
+#endif
}
/*
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index 990ff5b0aeb8..e4ea42b83b51 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -73,6 +73,7 @@ module_param(device_id_scheme, bool, 0444);
static int only_lcd = -1;
module_param(only_lcd, int, 0444);
+static bool has_backlight;
static int register_count;
static DEFINE_MUTEX(register_count_mutex);
static DEFINE_MUTEX(video_list_lock);
@@ -1222,6 +1223,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
acpi_video_device_bind(video, data);
acpi_video_device_find_cap(data);
+ if (data->cap._BCM && data->cap._BCL)
+ has_backlight = true;
+
mutex_lock(&video->device_list_lock);
list_add_tail(&data->entry, &video->video_device_list);
mutex_unlock(&video->device_list_lock);
@@ -2250,6 +2254,7 @@ void acpi_video_unregister(void)
if (register_count) {
acpi_bus_unregister_driver(&acpi_video_bus);
register_count = 0;
+ has_backlight = false;
}
mutex_unlock(®ister_count_mutex);
}
@@ -2271,13 +2276,7 @@ void acpi_video_unregister_backlight(void)
bool acpi_video_handles_brightness_key_presses(void)
{
- bool have_video_busses;
-
- mutex_lock(&video_list_lock);
- have_video_busses = !list_empty(&video_bus_head);
- mutex_unlock(&video_list_lock);
-
- return have_video_busses &&
+ return has_backlight &&
(report_key_events & REPORT_BRIGHTNESS_KEY_EVENTS);
}
EXPORT_SYMBOL(acpi_video_handles_brightness_key_presses);
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 966a6bf4c162..cf9cfc40a028 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -152,6 +152,10 @@ static unsigned int xen_blkif_max_ring_order;
module_param_named(max_ring_page_order, xen_blkif_max_ring_order, int, 0444);
MODULE_PARM_DESC(max_ring_page_order, "Maximum order of pages to be used for the shared ring");
+static bool __read_mostly xen_blkif_trusted = true;
+module_param_named(trusted, xen_blkif_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
#define BLK_RING_SIZE(info) \
__CONST_RING_SIZE(blkif, XEN_PAGE_SIZE * (info)->nr_ring_pages)
@@ -210,6 +214,7 @@ struct blkfront_info
unsigned int feature_discard:1;
unsigned int feature_secdiscard:1;
unsigned int feature_persistent:1;
+ unsigned int bounce:1;
unsigned int discard_granularity;
unsigned int discard_alignment;
/* Number of 4KB segments handled */
@@ -312,8 +317,8 @@ static int fill_grant_buffer(struct blkfront_ring_info *rinfo, int num)
if (!gnt_list_entry)
goto out_of_memory;
- if (info->feature_persistent) {
- granted_page = alloc_page(GFP_NOIO);
+ if (info->bounce) {
+ granted_page = alloc_page(GFP_NOIO | __GFP_ZERO);
if (!granted_page) {
kfree(gnt_list_entry);
goto out_of_memory;
@@ -332,7 +337,7 @@ static int fill_grant_buffer(struct blkfront_ring_info *rinfo, int num)
list_for_each_entry_safe(gnt_list_entry, n,
&rinfo->grants, node) {
list_del(&gnt_list_entry->node);
- if (info->feature_persistent)
+ if (info->bounce)
__free_page(gnt_list_entry->page);
kfree(gnt_list_entry);
i--;
@@ -378,7 +383,7 @@ static struct grant *get_grant(grant_ref_t *gref_head,
/* Assign a gref to this page */
gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
BUG_ON(gnt_list_entry->gref == -ENOSPC);
- if (info->feature_persistent)
+ if (info->bounce)
grant_foreign_access(gnt_list_entry, info);
else {
/* Grant access to the GFN passed by the caller */
@@ -402,7 +407,7 @@ static struct grant *get_indirect_grant(grant_ref_t *gref_head,
/* Assign a gref to this page */
gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
BUG_ON(gnt_list_entry->gref == -ENOSPC);
- if (!info->feature_persistent) {
+ if (!info->bounce) {
struct page *indirect_page;
/* Fetch a pre-allocated page to use for indirect grefs */
@@ -705,7 +710,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
.grant_idx = 0,
.segments = NULL,
.rinfo = rinfo,
- .need_copy = rq_data_dir(req) && info->feature_persistent,
+ .need_copy = rq_data_dir(req) && info->bounce,
};
/*
@@ -983,11 +988,12 @@ static void xlvbd_flush(struct blkfront_info *info)
{
blk_queue_write_cache(info->rq, info->feature_flush ? true : false,
info->feature_fua ? true : false);
- pr_info("blkfront: %s: %s %s %s %s %s\n",
+ pr_info("blkfront: %s: %s %s %s %s %s %s %s\n",
info->gd->disk_name, flush_info(info),
"persistent grants:", info->feature_persistent ?
"enabled;" : "disabled;", "indirect descriptors:",
- info->max_indirect_segments ? "enabled;" : "disabled;");
+ info->max_indirect_segments ? "enabled;" : "disabled;",
+ "bounce buffer:", info->bounce ? "enabled" : "disabled;");
}
static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset)
@@ -1209,7 +1215,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
if (!list_empty(&rinfo->indirect_pages)) {
struct page *indirect_page, *n;
- BUG_ON(info->feature_persistent);
+ BUG_ON(info->bounce);
list_for_each_entry_safe(indirect_page, n, &rinfo->indirect_pages, lru) {
list_del(&indirect_page->lru);
__free_page(indirect_page);
@@ -1226,7 +1232,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
0UL);
rinfo->persistent_gnts_c--;
}
- if (info->feature_persistent)
+ if (info->bounce)
__free_page(persistent_gnt->page);
kfree(persistent_gnt);
}
@@ -1247,7 +1253,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
for (j = 0; j < segs; j++) {
persistent_gnt = rinfo->shadow[i].grants_used[j];
gnttab_end_foreign_access(persistent_gnt->gref, 0UL);
- if (info->feature_persistent)
+ if (info->bounce)
__free_page(persistent_gnt->page);
kfree(persistent_gnt);
}
@@ -1437,7 +1443,7 @@ static int blkif_completion(unsigned long *id,
data.s = s;
num_sg = s->num_sg;
- if (bret->operation == BLKIF_OP_READ && info->feature_persistent) {
+ if (bret->operation == BLKIF_OP_READ && info->bounce) {
for_each_sg(s->sg, sg, num_sg, i) {
BUG_ON(sg->offset + sg->length > PAGE_SIZE);
@@ -1496,7 +1502,7 @@ static int blkif_completion(unsigned long *id,
* Add the used indirect page back to the list of
* available pages for indirect grefs.
*/
- if (!info->feature_persistent) {
+ if (!info->bounce) {
indirect_page = s->indirect_grants[i]->page;
list_add(&indirect_page->lru, &rinfo->indirect_pages);
}
@@ -1689,7 +1695,7 @@ static int setup_blkring(struct xenbus_device *dev,
for (i = 0; i < info->nr_ring_pages; i++)
rinfo->ring_ref[i] = GRANT_INVALID_REF;
- sring = alloc_pages_exact(ring_size, GFP_NOIO);
+ sring = alloc_pages_exact(ring_size, GFP_NOIO | __GFP_ZERO);
if (!sring) {
xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
return -ENOMEM;
@@ -1787,6 +1793,10 @@ static int talk_to_blkback(struct xenbus_device *dev,
if (!info)
return -ENODEV;
+ /* Check if backend is trusted. */
+ info->bounce = !xen_blkif_trusted ||
+ !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
max_page_order = xenbus_read_unsigned(info->xbdev->otherend,
"max-ring-page-order", 0);
ring_page_order = min(xen_blkif_max_ring_order, max_page_order);
@@ -2196,17 +2206,18 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
if (err)
goto out_of_memory;
- if (!info->feature_persistent && info->max_indirect_segments) {
+ if (!info->bounce && info->max_indirect_segments) {
/*
- * We are using indirect descriptors but not persistent
- * grants, we need to allocate a set of pages that can be
+ * We are using indirect descriptors but don't have a bounce
+ * buffer, we need to allocate a set of pages that can be
* used for mapping indirect grefs
*/
int num = INDIRECT_GREFS(grants) * BLK_RING_SIZE(info);
BUG_ON(!list_empty(&rinfo->indirect_pages));
for (i = 0; i < num; i++) {
- struct page *indirect_page = alloc_page(GFP_KERNEL);
+ struct page *indirect_page = alloc_page(GFP_KERNEL |
+ __GFP_ZERO);
if (!indirect_page)
goto out_of_memory;
list_add(&indirect_page->lru, &rinfo->indirect_pages);
@@ -2299,6 +2310,8 @@ static void blkfront_gather_backend_features(struct blkfront_info *info)
info->feature_persistent =
!!xenbus_read_unsigned(info->xbdev->otherend,
"feature-persistent", 0);
+ if (info->feature_persistent)
+ info->bounce = true;
indirect_segments = xenbus_read_unsigned(info->xbdev->otherend,
"feature-max-indirect-segments", 0);
@@ -2570,6 +2583,13 @@ static void blkfront_delay_work(struct work_struct *work)
struct blkfront_info *info;
bool need_schedule_work = false;
+ /*
+ * Note that when using bounce buffers but not persistent grants
+ * there's no need to run blkfront_delay_work because grants are
+ * revoked in blkif_completion or else an error is reported and the
+ * connection is closed.
+ */
+
mutex_lock(&blkfront_mutex);
list_for_each_entry(info, &info_list, info_list) {
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 7be38bc6a673..9ac75c1cde9c 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -566,6 +566,28 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
+static int amd_pstate_cpu_resume(struct cpufreq_policy *policy)
+{
+ int ret;
+
+ ret = amd_pstate_enable(true);
+ if (ret)
+ pr_err("failed to enable amd-pstate during resume, return %d\n", ret);
+
+ return ret;
+}
+
+static int amd_pstate_cpu_suspend(struct cpufreq_policy *policy)
+{
+ int ret;
+
+ ret = amd_pstate_enable(false);
+ if (ret)
+ pr_err("failed to disable amd-pstate during suspend, return %d\n", ret);
+
+ return ret;
+}
+
/* Sysfs attributes */
/*
@@ -636,6 +658,8 @@ static struct cpufreq_driver amd_pstate_driver = {
.target = amd_pstate_target,
.init = amd_pstate_cpu_init,
.exit = amd_pstate_cpu_exit,
+ .suspend = amd_pstate_cpu_suspend,
+ .resume = amd_pstate_cpu_resume,
.set_boost = amd_pstate_set_boost,
.name = "amd-pstate",
.attr = amd_pstate_attr,
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index 0253731d6d25..36c79580fba2 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -442,6 +442,9 @@ static int qcom_cpufreq_hw_cpu_online(struct cpufreq_policy *policy)
struct platform_device *pdev = cpufreq_get_driver_data();
int ret;
+ if (data->throttle_irq <= 0)
+ return 0;
+
ret = irq_set_affinity_hint(data->throttle_irq, policy->cpus);
if (ret)
dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n",
@@ -469,6 +472,9 @@ static int qcom_cpufreq_hw_cpu_offline(struct cpufreq_policy *policy)
static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data)
{
+ if (data->throttle_irq <= 0)
+ return;
+
free_irq(data->throttle_irq, data);
}
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 6b6b20da2bcf..573b417e1483 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -275,6 +275,7 @@ static int qoriq_cpufreq_probe(struct platform_device *pdev)
np = of_find_matching_node(NULL, qoriq_cpufreq_blacklist);
if (np) {
+ of_node_put(np);
dev_info(&pdev->dev, "Disabling due to erratum A-008083");
return -ENODEV;
}
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index 9b849d781116..a443e7c42daf 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -519,15 +519,19 @@ static int of_get_devfreq_events(struct device_node *np,
count = of_get_child_count(events_np);
desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
- if (!desc)
+ if (!desc) {
+ of_node_put(events_np);
return -ENOMEM;
+ }
info->num_events = count;
of_id = of_match_device(exynos_ppmu_id_match, dev);
if (of_id)
info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
- else
+ else {
+ of_node_put(events_np);
return -EINVAL;
+ }
j = 0;
for_each_child_of_node(events_np, node) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 6ca1db3c243f..3610bcd29ad9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -703,7 +703,8 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
{
bool all_hub = false;
- if (adev->family == AMDGPU_FAMILY_AI)
+ if (adev->family == AMDGPU_FAMILY_AI ||
+ adev->family == AMDGPU_FAMILY_RV)
all_hub = true;
return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 49f734137f15..66e40cac5eb3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5140,7 +5140,7 @@ int amdgpu_device_gpu_recover_imp(struct amdgpu_device *adev,
*/
amdgpu_unregister_gpu_instance(tmp_adev);
- drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
+ drm_fb_helper_set_suspend_unlocked(adev_to_drm(tmp_adev)->fb_helper, true);
/* disable ras on ALL IPs */
if (!need_emergency_restart &&
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index ea3e8c66211f..ebd53dacfac4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -333,6 +333,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
if (!amdgpu_device_has_dc_support(adev)) {
if (!adev->enable_virtual_display)
/* Disable vblank IRQs aggressively for power-saving */
+ /* XXX: can this be enabled for DC? */
adev_to_drm(adev)->vblank_disable_immediate = true;
r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 78a38c3b7d66..6dc9808760fc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4286,9 +4286,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
}
#endif
- /* Disable vblank IRQs aggressively for power-saving. */
- adev_to_drm(adev)->vblank_disable_immediate = true;
-
/* loops over all connectors on the board */
for (i = 0; i < link_cnt; i++) {
struct dc_link *link = NULL;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 9ae294eb7fb4..12b7d4d39216 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -932,8 +932,9 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv,
case I915_CONTEXT_PARAM_PERSISTENCE:
if (args->size)
ret = -EINVAL;
- ret = proto_context_set_persistence(fpriv->dev_priv, pc,
- args->value);
+ else
+ ret = proto_context_set_persistence(fpriv->dev_priv, pc,
+ args->value);
break;
case I915_CONTEXT_PARAM_PROTECTED_CONTENT:
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index 62b3f332bbf5..0478fa6259eb 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -538,6 +538,7 @@ static int i915_set_dma_info(struct drm_i915_private *i915)
static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
+ struct pci_dev *root_pdev;
int ret;
if (i915_inject_probe_failure(dev_priv))
@@ -651,6 +652,15 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
intel_bw_init_hw(dev_priv);
+ /*
+ * FIXME: Temporary hammer to avoid freezing the machine on our DGFX
+ * This should be totally removed when we handle the pci states properly
+ * on runtime PM and on s2idle cases.
+ */
+ root_pdev = pcie_find_root_port(pdev);
+ if (root_pdev)
+ pci_d3cold_disable(root_pdev);
+
return 0;
err_msi:
@@ -674,11 +684,16 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
static void i915_driver_hw_remove(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
+ struct pci_dev *root_pdev;
i915_perf_fini(dev_priv);
if (pdev->msi_enabled)
pci_disable_msi(pdev);
+
+ root_pdev = pcie_find_root_port(pdev);
+ if (root_pdev)
+ pci_d3cold_enable(root_pdev);
}
/**
@@ -1195,14 +1210,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
goto out;
}
- /*
- * FIXME: Temporary hammer to avoid freezing the machine on our DGFX
- * This should be totally removed when we handle the pci states properly
- * on runtime PM and on s2idle cases.
- */
- if (suspend_to_idle(dev_priv))
- pci_d3cold_disable(pdev);
-
pci_disable_device(pdev);
/*
* During hibernation on some platforms the BIOS may try to access
@@ -1367,8 +1374,6 @@ static int i915_drm_resume_early(struct drm_device *dev)
pci_set_master(pdev);
- pci_d3cold_enable(pdev);
-
disable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
ret = vlv_resume_prepare(dev_priv, false);
@@ -1545,7 +1550,6 @@ static int intel_runtime_suspend(struct device *kdev)
{
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
- struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
int ret;
if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_RUNTIME_PM(dev_priv)))
@@ -1591,12 +1595,6 @@ static int intel_runtime_suspend(struct device *kdev)
drm_err(&dev_priv->drm,
"Unclaimed access detected prior to suspending\n");
- /*
- * FIXME: Temporary hammer to avoid freezing the machine on our DGFX
- * This should be totally removed when we handle the pci states properly
- * on runtime PM and on s2idle cases.
- */
- pci_d3cold_disable(pdev);
rpm->suspended = true;
/*
@@ -1635,7 +1633,6 @@ static int intel_runtime_resume(struct device *kdev)
{
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
- struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
int ret;
if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_RUNTIME_PM(dev_priv)))
@@ -1648,7 +1645,6 @@ static int intel_runtime_resume(struct device *kdev)
intel_opregion_notify_adapter(dev_priv, PCI_D0);
rpm->suspended = false;
- pci_d3cold_enable(pdev);
if (intel_uncore_unclaimed_mmio(&dev_priv->uncore))
drm_dbg(&dev_priv->drm,
"Unclaimed access during suspend, bios?\n");
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 3940b9c6323b..fffd2ef897a0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1187,12 +1187,13 @@ static void dpu_encoder_vblank_callback(struct drm_encoder *drm_enc,
DPU_ATRACE_BEGIN("encoder_vblank_callback");
dpu_enc = to_dpu_encoder_virt(drm_enc);
+ atomic_inc(&phy_enc->vsync_cnt);
+
spin_lock_irqsave(&dpu_enc->enc_spinlock, lock_flags);
if (dpu_enc->crtc)
dpu_crtc_vblank_callback(dpu_enc->crtc);
spin_unlock_irqrestore(&dpu_enc->enc_spinlock, lock_flags);
- atomic_inc(&phy_enc->vsync_cnt);
DPU_ATRACE_END("encoder_vblank_callback");
}
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index c6d60c8d286d..fec4e3973287 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -913,7 +913,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
INT_MAX, GFP_KERNEL);
}
if (submit->fence_id < 0) {
- ret = submit->fence_id = 0;
+ ret = submit->fence_id;
submit->fence_id = 0;
}
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index de6baf6ca3d1..dab4908b78a8 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -550,7 +550,7 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
res = platform_device_add(data->pdev);
if (res)
- goto ipmi_err;
+ goto dev_add_err;
platform_set_drvdata(data->pdev, data);
@@ -598,7 +598,9 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
ipmi_destroy_user(data->ipmi.user);
ipmi_err:
platform_set_drvdata(data->pdev, NULL);
- platform_device_unregister(data->pdev);
+ platform_device_del(data->pdev);
+dev_add_err:
+ platform_device_put(data->pdev);
dev_err:
ida_simple_remove(&aem_ida, data->id);
id_err:
@@ -690,7 +692,7 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
res = platform_device_add(data->pdev);
if (res)
- goto ipmi_err;
+ goto dev_add_err;
platform_set_drvdata(data->pdev, data);
@@ -738,7 +740,9 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
ipmi_destroy_user(data->ipmi.user);
ipmi_err:
platform_set_drvdata(data->pdev, NULL);
- platform_device_unregister(data->pdev);
+ platform_device_del(data->pdev);
+dev_add_err:
+ platform_device_put(data->pdev);
dev_err:
ida_simple_remove(&aem_ida, data->id);
id_err:
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index f00cd59f1d19..1757f3ab842e 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -145,7 +145,7 @@ static int occ_poll(struct occ *occ)
cmd[6] = 0; /* checksum lsb */
/* mutex should already be locked if necessary */
- rc = occ->send_cmd(occ, cmd, sizeof(cmd));
+ rc = occ->send_cmd(occ, cmd, sizeof(cmd), &occ->resp, sizeof(occ->resp));
if (rc) {
occ->last_error = rc;
if (occ->error_count++ > OCC_ERROR_COUNT_THRESHOLD)
@@ -182,6 +182,7 @@ static int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
{
int rc;
u8 cmd[8];
+ u8 resp[8];
__be16 user_power_cap_be = cpu_to_be16(user_power_cap);
cmd[0] = 0; /* sequence number */
@@ -198,7 +199,7 @@ static int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
if (rc)
return rc;
- rc = occ->send_cmd(occ, cmd, sizeof(cmd));
+ rc = occ->send_cmd(occ, cmd, sizeof(cmd), resp, sizeof(resp));
mutex_unlock(&occ->lock);
diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h
index 2dd4a4d240c0..726943af9a07 100644
--- a/drivers/hwmon/occ/common.h
+++ b/drivers/hwmon/occ/common.h
@@ -96,7 +96,8 @@ struct occ {
int powr_sample_time_us; /* average power sample time */
u8 poll_cmd_data; /* to perform OCC poll command */
- int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len);
+ int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len, void *resp,
+ size_t resp_len);
unsigned long next_update;
struct mutex lock; /* lock OCC access */
diff --git a/drivers/hwmon/occ/p8_i2c.c b/drivers/hwmon/occ/p8_i2c.c
index 9e61e1fb5142..c35c07964d85 100644
--- a/drivers/hwmon/occ/p8_i2c.c
+++ b/drivers/hwmon/occ/p8_i2c.c
@@ -111,7 +111,8 @@ static int p8_i2c_occ_putscom_be(struct i2c_client *client, u32 address,
be32_to_cpu(data1));
}
-static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
+static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
+ void *resp, size_t resp_len)
{
int i, rc;
unsigned long start;
@@ -120,7 +121,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
const long wait_time = msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS);
struct p8_i2c_occ *ctx = to_p8_i2c_occ(occ);
struct i2c_client *client = ctx->client;
- struct occ_response *resp = &occ->resp;
+ struct occ_response *or = (struct occ_response *)resp;
start = jiffies;
@@ -151,7 +152,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
return rc;
/* wait for OCC */
- if (resp->return_status == OCC_RESP_CMD_IN_PRG) {
+ if (or->return_status == OCC_RESP_CMD_IN_PRG) {
rc = -EALREADY;
if (time_after(jiffies, start + timeout))
@@ -163,7 +164,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
} while (rc);
/* check the OCC response */
- switch (resp->return_status) {
+ switch (or->return_status) {
case OCC_RESP_CMD_IN_PRG:
rc = -ETIMEDOUT;
break;
@@ -192,8 +193,8 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
if (rc < 0)
return rc;
- data_length = get_unaligned_be16(&resp->data_length);
- if (data_length > OCC_RESP_DATA_BYTES)
+ data_length = get_unaligned_be16(&or->data_length);
+ if ((data_length + 7) > resp_len)
return -EMSGSIZE;
/* fetch the rest of the response data */
diff --git a/drivers/hwmon/occ/p9_sbe.c b/drivers/hwmon/occ/p9_sbe.c
index 49b13cc01073..bad349bf9f33 100644
--- a/drivers/hwmon/occ/p9_sbe.c
+++ b/drivers/hwmon/occ/p9_sbe.c
@@ -78,11 +78,10 @@ static bool p9_sbe_occ_save_ffdc(struct p9_sbe_occ *ctx, const void *resp,
return notify;
}
-static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
+static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
+ void *resp, size_t resp_len)
{
- struct occ_response *resp = &occ->resp;
struct p9_sbe_occ *ctx = to_p9_sbe_occ(occ);
- size_t resp_len = sizeof(*resp);
int rc;
rc = fsi_occ_submit(ctx->sbe, cmd, len, resp, &resp_len);
@@ -96,7 +95,7 @@ static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len)
return rc;
}
- switch (resp->return_status) {
+ switch (((struct occ_response *)resp)->return_status) {
case OCC_RESP_CMD_IN_PRG:
rc = -ETIMEDOUT;
break;
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 1c107d6d03b9..b985e0d9bc05 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -1252,8 +1252,10 @@ struct ib_cm_id *ib_cm_insert_listen(struct ib_device *device,
return ERR_CAST(cm_id_priv);
err = cm_init_listen(cm_id_priv, service_id, 0);
- if (err)
+ if (err) {
+ ib_destroy_cm_id(&cm_id_priv->id);
return ERR_PTR(err);
+ }
spin_lock_irq(&cm_id_priv->lock);
listen_id_priv = cm_insert_listen(cm_id_priv, cm_handler);
diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h
index 8def88cfa300..db9ef3e1eb97 100644
--- a/drivers/infiniband/hw/qedr/qedr.h
+++ b/drivers/infiniband/hw/qedr/qedr.h
@@ -418,6 +418,7 @@ struct qedr_qp {
u32 sq_psn;
u32 qkey;
u32 dest_qp_num;
+ u8 timeout;
/* Relevant to qps created from kernel space only (ULPs) */
u8 prev_wqe_size;
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index a53476653b0d..df4d7970c1ad 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -2612,6 +2612,8 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
1 << max_t(int, attr->timeout - 8, 0);
else
qp_params.ack_timeout = 0;
+
+ qp->timeout = attr->timeout;
}
if (attr_mask & IB_QP_RETRY_CNT) {
@@ -2771,7 +2773,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
rdma_ah_set_dgid_raw(&qp_attr->ah_attr, ¶ms.dgid.bytes[0]);
rdma_ah_set_port_num(&qp_attr->ah_attr, 1);
rdma_ah_set_sl(&qp_attr->ah_attr, 0);
- qp_attr->timeout = params.timeout;
+ qp_attr->timeout = qp->timeout;
qp_attr->rnr_retry = params.rnr_retry;
qp_attr->retry_cnt = params.retry_cnt;
qp_attr->min_rnr_timer = params.min_rnr_nak_timer;
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 2b26435a6946..e362a7471512 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1001,12 +1001,13 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
static int validate_raid_redundancy(struct raid_set *rs)
{
unsigned int i, rebuild_cnt = 0;
- unsigned int rebuilds_per_group = 0, copies;
+ unsigned int rebuilds_per_group = 0, copies, raid_disks;
unsigned int group_size, last_group_start;
- for (i = 0; i < rs->md.raid_disks; i++)
- if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
- !rs->dev[i].rdev.sb_page)
+ for (i = 0; i < rs->raid_disks; i++)
+ if (!test_bit(FirstUse, &rs->dev[i].rdev.flags) &&
+ ((!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
+ !rs->dev[i].rdev.sb_page)))
rebuild_cnt++;
switch (rs->md.level) {
@@ -1046,8 +1047,9 @@ static int validate_raid_redundancy(struct raid_set *rs)
* A A B B C
* C D D E E
*/
+ raid_disks = min(rs->raid_disks, rs->md.raid_disks);
if (__is_raid10_near(rs->md.new_layout)) {
- for (i = 0; i < rs->md.raid_disks; i++) {
+ for (i = 0; i < raid_disks; i++) {
if (!(i % copies))
rebuilds_per_group = 0;
if ((!rs->dev[i].rdev.sb_page ||
@@ -1070,10 +1072,10 @@ static int validate_raid_redundancy(struct raid_set *rs)
* results in the need to treat the last (potentially larger)
* set differently.
*/
- group_size = (rs->md.raid_disks / copies);
- last_group_start = (rs->md.raid_disks / group_size) - 1;
+ group_size = (raid_disks / copies);
+ last_group_start = (raid_disks / group_size) - 1;
last_group_start *= group_size;
- for (i = 0; i < rs->md.raid_disks; i++) {
+ for (i = 0; i < raid_disks; i++) {
if (!(i % copies) && !(i > last_group_start))
rebuilds_per_group = 0;
if ((!rs->dev[i].rdev.sb_page ||
@@ -1588,7 +1590,7 @@ static sector_t __rdev_sectors(struct raid_set *rs)
{
int i;
- for (i = 0; i < rs->md.raid_disks; i++) {
+ for (i = 0; i < rs->raid_disks; i++) {
struct md_rdev *rdev = &rs->dev[i].rdev;
if (!test_bit(Journal, &rdev->flags) &&
@@ -3771,13 +3773,13 @@ static int raid_iterate_devices(struct dm_target *ti,
unsigned int i;
int r = 0;
- for (i = 0; !r && i < rs->md.raid_disks; i++)
- if (rs->dev[i].data_dev)
- r = fn(ti,
- rs->dev[i].data_dev,
- 0, /* No offset on data devs */
- rs->md.dev_sectors,
- data);
+ for (i = 0; !r && i < rs->raid_disks; i++) {
+ if (rs->dev[i].data_dev) {
+ r = fn(ti, rs->dev[i].data_dev,
+ 0, /* No offset on data devs */
+ rs->md.dev_sectors, data);
+ }
+ }
return r;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index d6ce5a09fd35..0dd4679deb61 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -8023,6 +8023,7 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
*/
if (rdev->saved_raid_disk >= 0 &&
rdev->saved_raid_disk >= first &&
+ rdev->saved_raid_disk <= last &&
conf->disks[rdev->saved_raid_disk].rdev == NULL)
first = rdev->saved_raid_disk;
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index a86b1f71762e..d7fb33c078e8 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2228,7 +2228,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
temp_aggregator->num_of_ports--;
if (__agg_active_ports(temp_aggregator) == 0) {
select_new_active_agg = temp_aggregator->is_active;
- ad_clear_agg(temp_aggregator);
+ if (temp_aggregator->num_of_ports == 0)
+ ad_clear_agg(temp_aggregator);
if (select_new_active_agg) {
slave_info(bond->dev, slave->dev, "Removing an active aggregator\n");
/* select new active aggregator */
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 303c8d32d451..007d43e46dcb 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1302,12 +1302,12 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
return res;
if (rlb_enabled) {
- bond->alb_info.rlb_enabled = 1;
res = rlb_initialize(bond);
if (res) {
tlb_deinitialize(bond);
return res;
}
+ bond->alb_info.rlb_enabled = 1;
} else {
bond->alb_info.rlb_enabled = 0;
}
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
index 444ef6a342f6..14c5b2db65f4 100644
--- a/drivers/net/caif/caif_virtio.c
+++ b/drivers/net/caif/caif_virtio.c
@@ -721,13 +721,21 @@ static int cfv_probe(struct virtio_device *vdev)
/* Carrier is off until netdevice is opened */
netif_carrier_off(netdev);
+ /* serialize netdev register + virtio_device_ready() with ndo_open() */
+ rtnl_lock();
+
/* register Netdev */
- err = register_netdev(netdev);
+ err = register_netdevice(netdev);
if (err) {
+ rtnl_unlock();
dev_err(&vdev->dev, "Unable to register netdev (%d)\n", err);
goto err;
}
+ virtio_device_ready(vdev);
+
+ rtnl_unlock();
+
debugfs_init(cfv);
return 0;
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 87e81c636339..be0edfa093d0 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -878,6 +878,11 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port,
if (duplex == DUPLEX_FULL)
reg |= DUPLX_MODE;
+ if (tx_pause)
+ reg |= TXFLOW_CNTL;
+ if (rx_pause)
+ reg |= RXFLOW_CNTL;
+
core_writel(priv, reg, offset);
}
diff --git a/drivers/net/dsa/hirschmann/hellcreek_ptp.c b/drivers/net/dsa/hirschmann/hellcreek_ptp.c
index 2572c6087bb5..b28baab6d56a 100644
--- a/drivers/net/dsa/hirschmann/hellcreek_ptp.c
+++ b/drivers/net/dsa/hirschmann/hellcreek_ptp.c
@@ -300,6 +300,7 @@ static int hellcreek_led_setup(struct hellcreek *hellcreek)
const char *label, *state;
int ret = -EINVAL;
+ of_node_get(hellcreek->dev->of_node);
leds = of_find_node_by_name(hellcreek->dev->of_node, "leds");
if (!leds) {
dev_err(hellcreek->dev, "No LEDs specified in device tree!\n");
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 52a8566071ed..4a071f96ea28 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1883,6 +1883,8 @@ static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot,
static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
struct felix_stream_filter_counters *counters)
{
+ mutex_lock(&ocelot->stats_lock);
+
ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index),
SYS_STAT_CFG_STAT_VIEW_M,
SYS_STAT_CFG);
@@ -1897,6 +1899,8 @@ static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
SYS_STAT_CFG_STAT_VIEW(index) |
SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10),
SYS_STAT_CFG);
+
+ mutex_unlock(&ocelot->stats_lock);
}
static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 79deb19e3a19..7ad663c5b1ab 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -4418,6 +4418,8 @@ static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
return 0;
err_nexthop_neigh_init:
+ list_del(&nh->router_list_node);
+ mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
return err;
}
@@ -6743,6 +6745,7 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
const struct fib6_info *rt)
{
struct net_device *dev = rt->fib6_nh->fib_nh_dev;
+ int err;
nh->nhgi = nh_grp->nhgi;
nh->nh_weight = rt->fib6_nh->fib_nh_weight;
@@ -6758,7 +6761,16 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
return 0;
nh->ifindex = dev->ifindex;
- return mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
+ err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
+ if (err)
+ goto err_nexthop_type_init;
+
+ return 0;
+
+err_nexthop_type_init:
+ list_del(&nh->router_list_node);
+ mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
+ return err;
}
static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c
index 5389fffc694a..5edc8b7176c8 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c
@@ -396,6 +396,14 @@ static int sparx5_handle_port_mdb_add(struct net_device *dev,
u32 mact_entry;
int res, err;
+ if (!sparx5_netdevice_check(dev))
+ return -EOPNOTSUPP;
+
+ if (netif_is_bridge_master(v->obj.orig_dev)) {
+ sparx5_mact_learn(spx5, PGID_CPU, v->addr, v->vid);
+ return 0;
+ }
+
/* When VLAN unaware the vlan value is not parsed and we receive vid 0.
* Fall back to bridge vid 1.
*/
@@ -461,6 +469,14 @@ static int sparx5_handle_port_mdb_del(struct net_device *dev,
u32 mact_entry, res, pgid_entry[3];
int err;
+ if (!sparx5_netdevice_check(dev))
+ return -EOPNOTSUPP;
+
+ if (netif_is_bridge_master(v->obj.orig_dev)) {
+ sparx5_mact_forget(spx5, v->addr, v->vid);
+ return 0;
+ }
+
if (!br_vlan_enabled(spx5->hw_bridge_dev))
vid = 1;
else
@@ -500,6 +516,7 @@ static int sparx5_handle_port_obj_add(struct net_device *dev,
SWITCHDEV_OBJ_PORT_VLAN(obj));
break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
+ case SWITCHDEV_OBJ_ID_HOST_MDB:
err = sparx5_handle_port_mdb_add(dev, nb,
SWITCHDEV_OBJ_PORT_MDB(obj));
break;
@@ -552,6 +569,7 @@ static int sparx5_handle_port_obj_del(struct net_device *dev,
SWITCHDEV_OBJ_PORT_VLAN(obj)->vid);
break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
+ case SWITCHDEV_OBJ_ID_HOST_MDB:
err = sparx5_handle_port_mdb_del(dev, nb,
SWITCHDEV_OBJ_PORT_MDB(obj));
break;
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
index a0654e88444c..0329caf63279 100644
--- a/drivers/net/ethernet/smsc/epic100.c
+++ b/drivers/net/ethernet/smsc/epic100.c
@@ -1515,14 +1515,14 @@ static void epic_remove_one(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct epic_private *ep = netdev_priv(dev);
+ unregister_netdev(dev);
dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, ep->tx_ring,
ep->tx_ring_dma);
dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, ep->rx_ring,
ep->rx_ring_dma);
- unregister_netdev(dev);
pci_iounmap(pdev, ep->ioaddr);
- pci_release_regions(pdev);
free_netdev(dev);
+ pci_release_regions(pdev);
pci_disable_device(pdev);
/* pci_power_off(pdev, -1); */
}
diff --git a/drivers/net/phy/ax88796b.c b/drivers/net/phy/ax88796b.c
index 457896337505..0f1e617a26c9 100644
--- a/drivers/net/phy/ax88796b.c
+++ b/drivers/net/phy/ax88796b.c
@@ -88,8 +88,10 @@ static void asix_ax88772a_link_change_notify(struct phy_device *phydev)
/* Reset PHY, otherwise MII_LPA will provide outdated information.
* This issue is reproducible only with some link partner PHYs
*/
- if (phydev->state == PHY_NOLINK && phydev->drv->soft_reset)
- phydev->drv->soft_reset(phydev);
+ if (phydev->state == PHY_NOLINK) {
+ phy_init_hw(phydev);
+ phy_start_aneg(phydev);
+ }
}
static struct phy_driver asix_driver[] = {
diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c
index ce17b2af3218..a792dd6d2ec3 100644
--- a/drivers/net/phy/dp83822.c
+++ b/drivers/net/phy/dp83822.c
@@ -228,9 +228,7 @@ static int dp83822_config_intr(struct phy_device *phydev)
if (misr_status < 0)
return misr_status;
- misr_status |= (DP83822_RX_ERR_HF_INT_EN |
- DP83822_FALSE_CARRIER_HF_INT_EN |
- DP83822_LINK_STAT_INT_EN |
+ misr_status |= (DP83822_LINK_STAT_INT_EN |
DP83822_ENERGY_DET_INT_EN |
DP83822_LINK_QUAL_INT_EN);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index f122026c4682..2fc851082e7b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -972,6 +973,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 8406ac739def..2a53ae38a962 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -277,6 +277,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -314,6 +323,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index dbe4c0a4be2c..4ebf83bb9888 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -274,6 +274,12 @@ static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile,
}
}
+static void tun_napi_enable(struct tun_file *tfile)
+{
+ if (tfile->napi_enabled)
+ napi_enable(&tfile->napi);
+}
+
static void tun_napi_disable(struct tun_file *tfile)
{
if (tfile->napi_enabled)
@@ -635,7 +641,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
tun = rtnl_dereference(tfile->tun);
if (tun && clean) {
- tun_napi_disable(tfile);
+ if (!tfile->detached)
+ tun_napi_disable(tfile);
tun_napi_del(tfile);
}
@@ -654,8 +661,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
if (clean) {
RCU_INIT_POINTER(tfile->tun, NULL);
sock_put(&tfile->sk);
- } else
+ } else {
tun_disable_queue(tun, tfile);
+ tun_napi_disable(tfile);
+ }
synchronize_net();
tun_flow_delete_by_queue(tun, tun->numqueues + 1);
@@ -728,6 +737,7 @@ static void tun_detach_all(struct net_device *dev)
sock_put(&tfile->sk);
}
list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) {
+ tun_napi_del(tfile);
tun_enable_queue(tfile);
tun_queue_purge(tfile);
xdp_rxq_info_unreg(&tfile->xdp_rxq);
@@ -808,6 +818,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
if (tfile->detached) {
tun_enable_queue(tfile);
+ tun_napi_enable(tfile);
} else {
sock_hold(&tfile->sk);
tun_napi_init(tun, tfile, napi, napi_frags);
diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
index 2c81236c6c7c..45d3cc5cc355 100644
--- a/drivers/net/usb/asix.h
+++ b/drivers/net/usb/asix.h
@@ -126,8 +126,7 @@
AX_MEDIUM_RE)
#define AX88772_MEDIUM_DEFAULT \
- (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
- AX_MEDIUM_TFC | AX_MEDIUM_PS | \
+ (AX_MEDIUM_FD | AX_MEDIUM_PS | \
AX_MEDIUM_AC | AX_MEDIUM_RE)
/* AX88772 & AX88178 RX_CTL values */
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 632fa6c1d5e3..b4a1b7abcfc9 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -431,6 +431,7 @@ void asix_adjust_link(struct net_device *netdev)
asix_write_medium_mode(dev, mode, 0);
phy_print_status(phydev);
+ usbnet_link_change(dev, phydev->link, 0);
}
int asix_write_gpio(struct usbnet *dev, u16 value, int sleep, int in_pm)
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index e2fa56b92685..873f6deabbd1 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1472,6 +1472,42 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
* are bundled into this buffer and where we can find an array of
* per-packet metadata (which contains elements encoded into u16).
*/
+
+ /* SKB contents for current firmware:
+ * <packet 1> <padding>
+ * ...
+ * <packet N> <padding>
+ * <per-packet metadata entry 1> <dummy header>
+ * ...
+ * <per-packet metadata entry N> <dummy header>
+ * <padding2> <rx_hdr>
+ *
+ * where:
+ * <packet N> contains pkt_len bytes:
+ * 2 bytes of IP alignment pseudo header
+ * packet received
+ * <per-packet metadata entry N> contains 4 bytes:
+ * pkt_len and fields AX_RXHDR_*
+ * <padding> 0-7 bytes to terminate at
+ * 8 bytes boundary (64-bit).
+ * <padding2> 4 bytes to make rx_hdr terminate at
+ * 8 bytes boundary (64-bit)
+ * <dummy-header> contains 4 bytes:
+ * pkt_len=0 and AX_RXHDR_DROP_ERR
+ * <rx-hdr> contains 4 bytes:
+ * pkt_cnt and hdr_off (offset of
+ * <per-packet metadata entry 1>)
+ *
+ * pkt_cnt is number of entrys in the per-packet metadata.
+ * In current firmware there is 2 entrys per packet.
+ * The first points to the packet and the
+ * second is a dummy header.
+ * This was done probably to align fields in 64-bit and
+ * maintain compatibility with old firmware.
+ * This code assumes that <dummy header> and <padding2> are
+ * optional.
+ */
+
if (skb->len < 4)
return 0;
skb_trim(skb, skb->len - 4);
@@ -1485,51 +1521,66 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
/* Make sure that the bounds of the metadata array are inside the SKB
* (and in front of the counter at the end).
*/
- if (pkt_cnt * 2 + hdr_off > skb->len)
+ if (pkt_cnt * 4 + hdr_off > skb->len)
return 0;
pkt_hdr = (u32 *)(skb->data + hdr_off);
/* Packets must not overlap the metadata array */
skb_trim(skb, hdr_off);
- for (; ; pkt_cnt--, pkt_hdr++) {
+ for (; pkt_cnt > 0; pkt_cnt--, pkt_hdr++) {
+ u16 pkt_len_plus_padd;
u16 pkt_len;
le32_to_cpus(pkt_hdr);
pkt_len = (*pkt_hdr >> 16) & 0x1fff;
+ pkt_len_plus_padd = (pkt_len + 7) & 0xfff8;
- if (pkt_len > skb->len)
+ /* Skip dummy header used for alignment
+ */
+ if (pkt_len == 0)
+ continue;
+
+ if (pkt_len_plus_padd > skb->len)
return 0;
/* Check CRC or runt packet */
- if (((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) == 0) &&
- pkt_len >= 2 + ETH_HLEN) {
- bool last = (pkt_cnt == 0);
-
- if (last) {
- ax_skb = skb;
- } else {
- ax_skb = skb_clone(skb, GFP_ATOMIC);
- if (!ax_skb)
- return 0;
- }
- ax_skb->len = pkt_len;
- /* Skip IP alignment pseudo header */
- skb_pull(ax_skb, 2);
- skb_set_tail_pointer(ax_skb, ax_skb->len);
- ax_skb->truesize = pkt_len + sizeof(struct sk_buff);
- ax88179_rx_checksum(ax_skb, pkt_hdr);
+ if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) ||
+ pkt_len < 2 + ETH_HLEN) {
+ dev->net->stats.rx_errors++;
+ skb_pull(skb, pkt_len_plus_padd);
+ continue;
+ }
- if (last)
- return 1;
+ /* last packet */
+ if (pkt_len_plus_padd == skb->len) {
+ skb_trim(skb, pkt_len);
- usbnet_skb_return(dev, ax_skb);
+ /* Skip IP alignment pseudo header */
+ skb_pull(skb, 2);
+
+ skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd);
+ ax88179_rx_checksum(skb, pkt_hdr);
+ return 1;
}
- /* Trim this packet away from the SKB */
- if (!skb_pull(skb, (pkt_len + 7) & 0xFFF8))
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
+ if (!ax_skb)
return 0;
+ skb_trim(ax_skb, pkt_len);
+
+ /* Skip IP alignment pseudo header */
+ skb_pull(ax_skb, 2);
+
+ skb->truesize = pkt_len_plus_padd +
+ SKB_DATA_ALIGN(sizeof(struct sk_buff));
+ ax88179_rx_checksum(ax_skb, pkt_hdr);
+ usbnet_skb_return(dev, ax_skb);
+
+ skb_pull(skb, pkt_len_plus_padd);
}
+
+ return 0;
}
static struct sk_buff *
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 36b24ec11650..2ea81931543c 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -2004,7 +2004,7 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
cmd, reqtype, value, index, size);
if (size) {
- buf = kmalloc(size, GFP_KERNEL);
+ buf = kmalloc(size, GFP_NOIO);
if (!buf)
goto out;
}
@@ -2036,7 +2036,7 @@ static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
cmd, reqtype, value, index, size);
if (data) {
- buf = kmemdup(data, size, GFP_KERNEL);
+ buf = kmemdup(data, size, GFP_NOIO);
if (!buf)
goto out;
} else {
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 10d548b07b9c..c7804fce204c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3641,14 +3641,20 @@ static int virtnet_probe(struct virtio_device *vdev)
if (vi->has_rss || vi->has_rss_hash_report)
virtnet_init_default_rss(vi);
- err = register_netdev(dev);
+ /* serialize netdev register + virtio_device_ready() with ndo_open() */
+ rtnl_lock();
+
+ err = register_netdevice(dev);
if (err) {
pr_debug("virtio_net: registering device failed\n");
+ rtnl_unlock();
goto free_failover;
}
virtio_device_ready(vdev);
+ rtnl_unlock();
+
err = virtnet_cpu_notif_add(vi);
if (err) {
pr_debug("virtio_net: registering cpu notifier failed\n");
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index e2b4a1893a13..97c7633070a3 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -66,6 +66,10 @@ module_param_named(max_queues, xennet_max_queues, uint, 0644);
MODULE_PARM_DESC(max_queues,
"Maximum number of queues per virtual interface");
+static bool __read_mostly xennet_trusted = true;
+module_param_named(trusted, xennet_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
#define XENNET_TIMEOUT (5 * HZ)
static const struct ethtool_ops xennet_ethtool_ops;
@@ -175,6 +179,9 @@ struct netfront_info {
/* Is device behaving sane? */
bool broken;
+ /* Should skbs be bounced into a zeroed buffer? */
+ bool bounce;
+
atomic_t rx_gso_checksum_fixup;
};
@@ -273,7 +280,8 @@ static struct sk_buff *xennet_alloc_one_rx_buffer(struct netfront_queue *queue)
if (unlikely(!skb))
return NULL;
- page = page_pool_dev_alloc_pages(queue->page_pool);
+ page = page_pool_alloc_pages(queue->page_pool,
+ GFP_ATOMIC | __GFP_NOWARN | __GFP_ZERO);
if (unlikely(!page)) {
kfree_skb(skb);
return NULL;
@@ -667,6 +675,33 @@ static int xennet_xdp_xmit(struct net_device *dev, int n,
return nxmit;
}
+struct sk_buff *bounce_skb(const struct sk_buff *skb)
+{
+ unsigned int headerlen = skb_headroom(skb);
+ /* Align size to allocate full pages and avoid contiguous data leaks */
+ unsigned int size = ALIGN(skb_end_offset(skb) + skb->data_len,
+ XEN_PAGE_SIZE);
+ struct sk_buff *n = alloc_skb(size, GFP_ATOMIC | __GFP_ZERO);
+
+ if (!n)
+ return NULL;
+
+ if (!IS_ALIGNED((uintptr_t)n->head, XEN_PAGE_SIZE)) {
+ WARN_ONCE(1, "misaligned skb allocated\n");
+ kfree_skb(n);
+ return NULL;
+ }
+
+ /* Set the data pointer */
+ skb_reserve(n, headerlen);
+ /* Set the tail pointer and length */
+ skb_put(n, skb->len);
+
+ BUG_ON(skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len));
+
+ skb_copy_header(n, skb);
+ return n;
+}
#define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)
@@ -720,9 +755,13 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
/* The first req should be at least ETH_HLEN size or the packet will be
* dropped by netback.
+ *
+ * If the backend is not trusted bounce all data to zeroed pages to
+ * avoid exposing contiguous data on the granted page not belonging to
+ * the skb.
*/
- if (unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
- nskb = skb_copy(skb, GFP_ATOMIC);
+ if (np->bounce || unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
+ nskb = bounce_skb(skb);
if (!nskb)
goto drop;
dev_consume_skb_any(skb);
@@ -1055,8 +1094,10 @@ static int xennet_get_responses(struct netfront_queue *queue,
}
}
rcu_read_unlock();
-next:
+
__skb_queue_tail(list, skb);
+
+next:
if (!(rx->flags & XEN_NETRXF_more_data))
break;
@@ -2246,6 +2287,10 @@ static int talk_to_netback(struct xenbus_device *dev,
info->netdev->irq = 0;
+ /* Check if backend is trusted. */
+ info->bounce = !xennet_trusted ||
+ !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
/* Check if backend supports multiple queues */
max_queues = xenbus_read_unsigned(info->xbdev->otherend,
"multi-queue-max-queues", 1);
@@ -2413,6 +2458,9 @@ static int xennet_connect(struct net_device *dev)
return err;
if (np->netback_has_xdp_headroom)
pr_info("backend supports XDP headroom\n");
+ if (np->bounce)
+ dev_info(&np->xbdev->dev,
+ "bouncing transmitted data to zeroed pages\n");
/* talk_to_netback() sets the correct number of queues */
num_queues = dev->real_num_tx_queues;
diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c
index ceef81d93ac9..01329b91d59d 100644
--- a/drivers/nfc/nfcmrvl/i2c.c
+++ b/drivers/nfc/nfcmrvl/i2c.c
@@ -167,9 +167,9 @@ static int nfcmrvl_i2c_parse_dt(struct device_node *node,
pdata->irq_polarity = IRQF_TRIGGER_RISING;
ret = irq_of_parse_and_map(node, 0);
- if (ret < 0) {
- pr_err("Unable to get irq, error: %d\n", ret);
- return ret;
+ if (!ret) {
+ pr_err("Unable to get irq\n");
+ return -EINVAL;
}
pdata->irq = ret;
diff --git a/drivers/nfc/nfcmrvl/spi.c b/drivers/nfc/nfcmrvl/spi.c
index a38e2fcdfd39..ad3359a4942c 100644
--- a/drivers/nfc/nfcmrvl/spi.c
+++ b/drivers/nfc/nfcmrvl/spi.c
@@ -115,9 +115,9 @@ static int nfcmrvl_spi_parse_dt(struct device_node *node,
}
ret = irq_of_parse_and_map(node, 0);
- if (ret < 0) {
- pr_err("Unable to get irq, error: %d\n", ret);
- return ret;
+ if (!ret) {
+ pr_err("Unable to get irq\n");
+ return -EINVAL;
}
pdata->irq = ret;
diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
index 7e451c10985d..e8f3b35afbee 100644
--- a/drivers/nfc/nxp-nci/i2c.c
+++ b/drivers/nfc/nxp-nci/i2c.c
@@ -162,6 +162,9 @@ static int nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy *phy,
skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE);
+ if (!header.plen)
+ return 0;
+
r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen);
if (r != header.plen) {
nfc_err(&client->dev,
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 7b0d1443217a..5db16857b80e 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -182,8 +182,8 @@ static int nvdimm_clear_badblocks_region(struct device *dev, void *data)
ndr_end = nd_region->ndr_start + nd_region->ndr_size - 1;
/* make sure we are in the region */
- if (ctx->phys < nd_region->ndr_start
- || (ctx->phys + ctx->cleared) > ndr_end)
+ if (ctx->phys < nd_region->ndr_start ||
+ (ctx->phys + ctx->cleared - 1) > ndr_end)
return 0;
sector = (ctx->phys - nd_region->ndr_start) / 512;
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index ddea0fb90c28..fe829377c7c2 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -3436,8 +3436,11 @@ static const struct pci_device_id nvme_id_table[] = {
{ PCI_DEVICE(0x1b4b, 0x1092), /* Lexar 256 GB SSD */
.driver_data = NVME_QUIRK_NO_NS_DESC_LIST |
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+ { PCI_DEVICE(0x1cc1, 0x33f8), /* ADATA IM2P33F8ABR1 1 TB */
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
{ PCI_DEVICE(0x10ec, 0x5762), /* ADATA SX6000LNP */
- .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+ .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN |
+ NVME_QUIRK_BOGUS_NID, },
{ PCI_DEVICE(0x1cc1, 0x8201), /* ADATA SX8200PNP 512GB */
.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index e44b2988759e..ff77c3d2354f 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -773,11 +773,31 @@ static ssize_t nvmet_passthru_io_timeout_store(struct config_item *item,
}
CONFIGFS_ATTR(nvmet_passthru_, io_timeout);
+static ssize_t nvmet_passthru_clear_ids_show(struct config_item *item,
+ char *page)
+{
+ return sprintf(page, "%u\n", to_subsys(item->ci_parent)->clear_ids);
+}
+
+static ssize_t nvmet_passthru_clear_ids_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct nvmet_subsys *subsys = to_subsys(item->ci_parent);
+ unsigned int clear_ids;
+
+ if (kstrtouint(page, 0, &clear_ids))
+ return -EINVAL;
+ subsys->clear_ids = clear_ids;
+ return count;
+}
+CONFIGFS_ATTR(nvmet_passthru_, clear_ids);
+
static struct configfs_attribute *nvmet_passthru_attrs[] = {
&nvmet_passthru_attr_device_path,
&nvmet_passthru_attr_enable,
&nvmet_passthru_attr_admin_timeout,
&nvmet_passthru_attr_io_timeout,
+ &nvmet_passthru_attr_clear_ids,
NULL,
};
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 90e75324dae0..c27660a660d9 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -1374,6 +1374,12 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
ctrl->port = req->port;
ctrl->ops = req->ops;
+#ifdef CONFIG_NVME_TARGET_PASSTHRU
+ /* By default, set loop targets to clear IDS by default */
+ if (ctrl->port->disc_addr.trtype == NVMF_TRTYPE_LOOP)
+ subsys->clear_ids = 1;
+#endif
+
INIT_WORK(&ctrl->async_event_work, nvmet_async_event_work);
INIT_LIST_HEAD(&ctrl->async_events);
INIT_RADIX_TREE(&ctrl->p2p_ns_map, GFP_KERNEL);
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 69818752a33a..2b3e5719f24e 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -249,6 +249,7 @@ struct nvmet_subsys {
struct config_group passthru_group;
unsigned int admin_timeout;
unsigned int io_timeout;
+ unsigned int clear_ids;
#endif /* CONFIG_NVME_TARGET_PASSTHRU */
#ifdef CONFIG_BLK_DEV_ZONED
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 5247c24538eb..6506831cb012 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -30,6 +30,53 @@ void nvmet_passthrough_override_cap(struct nvmet_ctrl *ctrl)
ctrl->cap &= ~(1ULL << 43);
}
+static u16 nvmet_passthru_override_id_descs(struct nvmet_req *req)
+{
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ u16 status = NVME_SC_SUCCESS;
+ int pos, len;
+ bool csi_seen = false;
+ void *data;
+ u8 csi;
+
+ if (!ctrl->subsys->clear_ids)
+ return status;
+
+ data = kzalloc(NVME_IDENTIFY_DATA_SIZE, GFP_KERNEL);
+ if (!data)
+ return NVME_SC_INTERNAL;
+
+ status = nvmet_copy_from_sgl(req, 0, data, NVME_IDENTIFY_DATA_SIZE);
+ if (status)
+ goto out_free;
+
+ for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) {
+ struct nvme_ns_id_desc *cur = data + pos;
+
+ if (cur->nidl == 0)
+ break;
+ if (cur->nidt == NVME_NIDT_CSI) {
+ memcpy(&csi, cur + 1, NVME_NIDT_CSI_LEN);
+ csi_seen = true;
+ break;
+ }
+ len = sizeof(struct nvme_ns_id_desc) + cur->nidl;
+ }
+
+ memset(data, 0, NVME_IDENTIFY_DATA_SIZE);
+ if (csi_seen) {
+ struct nvme_ns_id_desc *cur = data;
+
+ cur->nidt = NVME_NIDT_CSI;
+ cur->nidl = NVME_NIDT_CSI_LEN;
+ memcpy(cur + 1, &csi, NVME_NIDT_CSI_LEN);
+ }
+ status = nvmet_copy_to_sgl(req, 0, data, NVME_IDENTIFY_DATA_SIZE);
+out_free:
+ kfree(data);
+ return status;
+}
+
static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
{
struct nvmet_ctrl *ctrl = req->sq->ctrl;
@@ -152,6 +199,11 @@ static u16 nvmet_passthru_override_id_ns(struct nvmet_req *req)
*/
id->mc = 0;
+ if (req->sq->ctrl->subsys->clear_ids) {
+ memset(id->nguid, 0, NVME_NIDT_NGUID_LEN);
+ memset(id->eui64, 0, NVME_NIDT_EUI64_LEN);
+ }
+
status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
out_free:
@@ -176,6 +228,9 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
case NVME_ID_CNS_NS:
nvmet_passthru_override_id_ns(req);
break;
+ case NVME_ID_CNS_NS_DESC_LIST:
+ nvmet_passthru_override_id_descs(req);
+ break;
}
} else if (status < 0)
status = NVME_SC_INTERNAL;
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 2793554e622e..0a9542599ad1 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -405,7 +405,7 @@ static int nvmet_tcp_map_data(struct nvmet_tcp_cmd *cmd)
return NVME_SC_INTERNAL;
}
-static void nvmet_tcp_send_ddgst(struct ahash_request *hash,
+static void nvmet_tcp_calc_ddgst(struct ahash_request *hash,
struct nvmet_tcp_cmd *cmd)
{
ahash_request_set_crypt(hash, cmd->req.sg,
@@ -413,23 +413,6 @@ static void nvmet_tcp_send_ddgst(struct ahash_request *hash,
crypto_ahash_digest(hash);
}
-static void nvmet_tcp_recv_ddgst(struct ahash_request *hash,
- struct nvmet_tcp_cmd *cmd)
-{
- struct scatterlist sg;
- struct kvec *iov;
- int i;
-
- crypto_ahash_init(hash);
- for (i = 0, iov = cmd->iov; i < cmd->nr_mapped; i++, iov++) {
- sg_init_one(&sg, iov->iov_base, iov->iov_len);
- ahash_request_set_crypt(hash, &sg, NULL, iov->iov_len);
- crypto_ahash_update(hash);
- }
- ahash_request_set_crypt(hash, NULL, (void *)&cmd->exp_ddgst, 0);
- crypto_ahash_final(hash);
-}
-
static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
{
struct nvme_tcp_data_pdu *pdu = cmd->data_pdu;
@@ -454,7 +437,7 @@ static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
if (queue->data_digest) {
pdu->hdr.flags |= NVME_TCP_F_DDGST;
- nvmet_tcp_send_ddgst(queue->snd_hash, cmd);
+ nvmet_tcp_calc_ddgst(queue->snd_hash, cmd);
}
if (cmd->queue->hdr_digest) {
@@ -1137,7 +1120,7 @@ static void nvmet_tcp_prep_recv_ddgst(struct nvmet_tcp_cmd *cmd)
{
struct nvmet_tcp_queue *queue = cmd->queue;
- nvmet_tcp_recv_ddgst(queue->rcv_hash, cmd);
+ nvmet_tcp_calc_ddgst(queue->rcv_hash, cmd);
queue->offset = 0;
queue->left = NVME_TCP_DIGEST_LENGTH;
queue->rcv_state = NVMET_TCP_RECV_DDGST;
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 5d9dd70e4e0f..ddb8f14247c0 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -945,6 +945,8 @@ config PANASONIC_LAPTOP
tristate "Panasonic Laptop Extras"
depends on INPUT && ACPI
depends on BACKLIGHT_CLASS_DEVICE
+ depends on ACPI_VIDEO=n || ACPI_VIDEO
+ depends on SERIO_I8042 || SERIO_I8042 = n
select INPUT_SPARSEKMAP
help
This driver adds support for access to backlight control and hotkeys
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 3ccb7b71dfb1..abd0c81d62c4 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -152,6 +152,10 @@ static bool no_bt_rfkill;
module_param(no_bt_rfkill, bool, 0444);
MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
+static bool allow_v4_dytc;
+module_param(allow_v4_dytc, bool, 0444);
+MODULE_PARM_DESC(allow_v4_dytc, "Enable DYTC version 4 platform-profile support.");
+
/*
* ACPI Helpers
*/
@@ -871,12 +875,18 @@ static void dytc_profile_refresh(struct ideapad_private *priv)
static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
{
/* Ideapad 5 Pro 16ACH6 */
- .ident = "LENOVO 82L5",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "82L5")
}
},
+ {
+ /* Ideapad 5 15ITL05 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad 5 15ITL05")
+ }
+ },
{}
};
@@ -901,13 +911,16 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
- if (dytc_version < 5) {
- if (dytc_version < 4 || !dmi_check_system(ideapad_dytc_v4_allow_table)) {
- dev_info(&priv->platform_device->dev,
- "DYTC_VERSION is less than 4 or is not allowed: %d\n",
- dytc_version);
- return -ENODEV;
- }
+ if (dytc_version < 4) {
+ dev_info(&priv->platform_device->dev, "DYTC_VERSION < 4 is not supported\n");
+ return -ENODEV;
+ }
+
+ if (dytc_version < 5 &&
+ !(allow_v4_dytc || dmi_check_system(ideapad_dytc_v4_allow_table))) {
+ dev_info(&priv->platform_device->dev,
+ "DYTC_VERSION 4 support may not work. Pass ideapad_laptop.allow_v4_dytc=Y on the kernel commandline to enable\n");
+ return -ENODEV;
}
priv->dytc = kzalloc(sizeof(*priv->dytc), GFP_KERNEL);
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 37850d07987d..615e39cbbbf1 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -119,20 +119,22 @@
* - v0.1 start from toshiba_acpi driver written by John Belmonte
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
+#include <linux/acpi.h>
#include <linux/backlight.h>
#include <linux/ctype.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/acpi.h>
+#include <linux/i8042.h>
+#include <linux/init.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
-
+#include <linux/seq_file.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <acpi/video.h>
MODULE_AUTHOR("Hiroshi Miura <miura@da-cha.org>");
MODULE_AUTHOR("David Bronaugh <dbronaugh@linuxboxen.org>");
@@ -241,6 +243,42 @@ struct pcc_acpi {
struct platform_device *platform;
};
+/*
+ * On some Panasonic models the volume up / down / mute keys send duplicate
+ * keypress events over the PS/2 kbd interface, filter these out.
+ */
+static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
+ struct serio *port)
+{
+ static bool extended;
+
+ if (str & I8042_STR_AUXDATA)
+ return false;
+
+ if (data == 0xe0) {
+ extended = true;
+ return true;
+ } else if (extended) {
+ extended = false;
+
+ switch (data & 0x7f) {
+ case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */
+ case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
+ case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
+ return true;
+ default:
+ /*
+ * Report the previously filtered e0 before continuing
+ * with the next non-filtered byte.
+ */
+ serio_interrupt(port, 0xe0, 0);
+ return false;
+ }
+ }
+
+ return false;
+}
+
/* method access functions */
static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
{
@@ -762,6 +800,8 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
struct input_dev *hotk_input_dev = pcc->input_dev;
int rc;
unsigned long long result;
+ unsigned int key;
+ unsigned int updown;
rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
NULL, &result);
@@ -770,20 +810,27 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
return;
}
+ key = result & 0xf;
+ updown = result & 0x80; /* 0x80 == key down; 0x00 = key up */
+
/* hack: some firmware sends no key down for sleep / hibernate */
- if ((result & 0xf) == 0x7 || (result & 0xf) == 0xa) {
- if (result & 0x80)
+ if (key == 7 || key == 10) {
+ if (updown)
sleep_keydown_seen = 1;
if (!sleep_keydown_seen)
sparse_keymap_report_event(hotk_input_dev,
- result & 0xf, 0x80, false);
+ key, 0x80, false);
}
- if ((result & 0xf) == 0x7 || (result & 0xf) == 0x9 || (result & 0xf) == 0xa) {
- if (!sparse_keymap_report_event(hotk_input_dev,
- result & 0xf, result & 0x80, false))
- pr_err("Unknown hotkey event: 0x%04llx\n", result);
- }
+ /*
+ * Don't report brightness key-presses if they are also reported
+ * by the ACPI video bus.
+ */
+ if ((key == 1 || key == 2) && acpi_video_handles_brightness_key_presses())
+ return;
+
+ if (!sparse_keymap_report_event(hotk_input_dev, key, updown, false))
+ pr_err("Unknown hotkey event: 0x%04llx\n", result);
}
static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
@@ -997,6 +1044,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
pcc->platform = NULL;
}
+ i8042_install_filter(panasonic_i8042_filter);
return 0;
out_platform:
@@ -1020,6 +1068,8 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device)
if (!device || !pcc)
return -EINVAL;
+ i8042_remove_filter(panasonic_i8042_filter);
+
if (pcc->platform) {
device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
platform_device_unregister(pcc->platform);
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index e6cb4a14cdd4..aa6ffeaa3932 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -4529,6 +4529,7 @@ static void thinkpad_acpi_amd_s2idle_restore(void)
iounmap(addr);
cleanup_resource:
release_resource(res);
+ kfree(res);
}
static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = {
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index e0de44000d92..c290386aa2f3 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -1757,6 +1757,8 @@ static void mlx5_vdpa_set_vq_cb(struct vdpa_device *vdev, u16 idx, struct vdpa_c
struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
ndev->event_cbs[idx] = *cb;
+ if (is_ctrl_vq_idx(mvdev, idx))
+ mvdev->cvq.event_cb = *cb;
}
static void mlx5_cvq_notify(struct vringh *vring)
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index a0467bca39fa..263d1cd3af76 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -4358,6 +4358,7 @@ static void flush_dirty_session_caps(struct ceph_mds_session *s)
ihold(inode);
dout("flush_dirty_caps %llx.%llx\n", ceph_vinop(inode));
spin_unlock(&mdsc->cap_dirty_lock);
+ ceph_wait_on_async_create(inode);
ceph_check_caps(ci, CHECK_CAPS_FLUSH, NULL);
iput(inode);
spin_lock(&mdsc->cap_dirty_lock);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 98e4a1aa898e..409cad848ae6 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3423,7 +3423,9 @@ static int is_path_remote(struct mount_ctx *mnt_ctx)
struct cifs_tcon *tcon = mnt_ctx->tcon;
struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
char *full_path;
+#ifdef CONFIG_CIFS_DFS_UPCALL
bool nodfs = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS;
+#endif
if (!server->ops->is_path_accessible)
return -EOPNOTSUPP;
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 7c190e885340..7e8c715052c0 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -5254,7 +5254,7 @@ static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
return -EINVAL;
- if (unlikely(sqe->addr2 || sqe->file_index))
+ if (unlikely(sqe->addr2 || sqe->file_index || sqe->ioprio))
return -EINVAL;
sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
@@ -5467,7 +5467,7 @@ static int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
return -EINVAL;
- if (unlikely(sqe->addr2 || sqe->file_index))
+ if (unlikely(sqe->addr2 || sqe->file_index || sqe->ioprio))
return -EINVAL;
sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 16c803a9d996..31138e9be1dc 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -7705,7 +7705,7 @@ int smb2_ioctl(struct ksmbd_work *work)
{
struct file_zero_data_information *zero_data;
struct ksmbd_file *fp;
- loff_t off, len;
+ loff_t off, len, bfz;
if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
ksmbd_debug(SMB,
@@ -7722,19 +7722,26 @@ int smb2_ioctl(struct ksmbd_work *work)
zero_data =
(struct file_zero_data_information *)&req->Buffer[0];
- fp = ksmbd_lookup_fd_fast(work, id);
- if (!fp) {
- ret = -ENOENT;
+ off = le64_to_cpu(zero_data->FileOffset);
+ bfz = le64_to_cpu(zero_data->BeyondFinalZero);
+ if (off > bfz) {
+ ret = -EINVAL;
goto out;
}
- off = le64_to_cpu(zero_data->FileOffset);
- len = le64_to_cpu(zero_data->BeyondFinalZero) - off;
+ len = bfz - off;
+ if (len) {
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp) {
+ ret = -ENOENT;
+ goto out;
+ }
- ret = ksmbd_vfs_zero_data(work, fp, off, len);
- ksmbd_fd_put(work, fp);
- if (ret < 0)
- goto out;
+ ret = ksmbd_vfs_zero_data(work, fp, off, len);
+ ksmbd_fd_put(work, fp);
+ if (ret < 0)
+ goto out;
+ }
break;
}
case FSCTL_QUERY_ALLOCATED_RANGES:
@@ -7808,14 +7815,24 @@ int smb2_ioctl(struct ksmbd_work *work)
src_off = le64_to_cpu(dup_ext->SourceFileOffset);
dst_off = le64_to_cpu(dup_ext->TargetFileOffset);
length = le64_to_cpu(dup_ext->ByteCount);
- cloned = vfs_clone_file_range(fp_in->filp, src_off, fp_out->filp,
- dst_off, length, 0);
+ /*
+ * XXX: It is not clear if FSCTL_DUPLICATE_EXTENTS_TO_FILE
+ * should fall back to vfs_copy_file_range(). This could be
+ * beneficial when re-exporting nfs/smb mount, but note that
+ * this can result in partial copy that returns an error status.
+ * If/when FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX is implemented,
+ * fall back to vfs_copy_file_range(), should be avoided when
+ * the flag DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC is set.
+ */
+ cloned = vfs_clone_file_range(fp_in->filp, src_off,
+ fp_out->filp, dst_off, length, 0);
if (cloned == -EXDEV || cloned == -EOPNOTSUPP) {
ret = -EOPNOTSUPP;
goto dup_ext_out;
} else if (cloned != length) {
cloned = vfs_copy_file_range(fp_in->filp, src_off,
- fp_out->filp, dst_off, length, 0);
+ fp_out->filp, dst_off,
+ length, 0);
if (cloned != length) {
if (cloned < 0)
ret = cloned;
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index dcdd07c6efff..05efcdf7a4a7 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -1015,7 +1015,9 @@ int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
off, len);
- return vfs_fallocate(fp->filp, FALLOC_FL_ZERO_RANGE, off, len);
+ return vfs_fallocate(fp->filp,
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
+ off, len);
}
int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
@@ -1046,7 +1048,7 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
*out_count = 0;
end = start + length;
while (start < end && *out_count < in_count) {
- extent_start = f->f_op->llseek(f, start, SEEK_DATA);
+ extent_start = vfs_llseek(f, start, SEEK_DATA);
if (extent_start < 0) {
if (extent_start != -ENXIO)
ret = (int)extent_start;
@@ -1056,7 +1058,7 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
if (extent_start >= end)
break;
- extent_end = f->f_op->llseek(f, extent_start, SEEK_HOLE);
+ extent_end = vfs_llseek(f, extent_start, SEEK_HOLE);
if (extent_end < 0) {
if (extent_end != -ENXIO)
ret = (int)extent_end;
@@ -1777,6 +1779,10 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
ret = vfs_copy_file_range(src_fp->filp, src_off,
dst_fp->filp, dst_off, len, 0);
+ if (ret == -EOPNOTSUPP || ret == -EXDEV)
+ ret = generic_copy_file_range(src_fp->filp, src_off,
+ dst_fp->filp, dst_off,
+ len, 0);
if (ret < 0)
return ret;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d1eaaeb7f713..f0069395f02c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4012,22 +4012,29 @@ static int _nfs4_discover_trunking(struct nfs_server *server,
}
page = alloc_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
- if (page == NULL || locations == NULL)
- goto out;
+ if (!locations)
+ goto out_free;
+ locations->fattr = nfs_alloc_fattr();
+ if (!locations->fattr)
+ goto out_free_2;
status = nfs4_proc_get_locations(server, fhandle, locations, page,
cred);
if (status)
- goto out;
+ goto out_free_3;
for (i = 0; i < locations->nlocations; i++)
test_fs_location_for_trunking(&locations->locations[i], clp,
server);
-out:
- if (page)
- __free_page(page);
+out_free_3:
+ kfree(locations->fattr);
+out_free_2:
kfree(locations);
+out_free:
+ __free_page(page);
return status;
}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 9656d40bb488..673af2d4b5a2 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -2743,5 +2743,6 @@ static int nfs4_run_state_manager(void *ptr)
goto again;
nfs_put_client(clp);
+ module_put_and_kthread_exit(0);
return 0;
}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c22ad0532e8e..67c851f02b24 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -577,6 +577,7 @@ __be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
u64 dst_pos, u64 count)
{
+ ssize_t ret;
/*
* Limit copy to 4MB to prevent indefinitely blocking an nfsd
@@ -587,7 +588,12 @@ ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
* limit like this and pipeline multiple COPY requests.
*/
count = min_t(u64, count, 1 << 22);
- return vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
+ ret = vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
+
+ if (ret == -EOPNOTSUPP || ret == -EXDEV)
+ ret = generic_copy_file_range(src, src_pos, dst, dst_pos,
+ count, 0);
+ return ret;
}
__be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp,
@@ -1170,6 +1176,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
nfsd_copy_write_verifier(verf, nn);
err2 = filemap_check_wb_err(nf->nf_file->f_mapping,
since);
+ err = nfserrno(err2);
break;
case -EINVAL:
err = nfserr_notsupp;
@@ -1177,8 +1184,8 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
default:
nfsd_reset_write_verifier(nn);
trace_nfsd_writeverf_reset(nn, rqstp, err2);
+ err = nfserrno(err2);
}
- err = nfserrno(err2);
} else
nfsd_copy_write_verifier(verf, nn);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 16d8fc84713a..a12391d06fe5 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -1483,8 +1483,15 @@ static int fanotify_test_fid(struct dentry *dentry)
return 0;
}
-static int fanotify_events_supported(struct path *path, __u64 mask)
+static int fanotify_events_supported(struct fsnotify_group *group,
+ struct path *path, __u64 mask,
+ unsigned int flags)
{
+ unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
+ /* Strict validation of events in non-dir inode mask with v5.17+ APIs */
+ bool strict_dir_events = FAN_GROUP_FLAG(group, FAN_REPORT_TARGET_FID) ||
+ (mask & FAN_RENAME);
+
/*
* Some filesystems such as 'proc' acquire unusual locks when opening
* files. For them fanotify permission events have high chances of
@@ -1496,6 +1503,16 @@ static int fanotify_events_supported(struct path *path, __u64 mask)
if (mask & FANOTIFY_PERM_EVENTS &&
path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM)
return -EINVAL;
+
+ /*
+ * We shouldn't have allowed setting dirent events and the directory
+ * flags FAN_ONDIR and FAN_EVENT_ON_CHILD in mask of non-dir inode,
+ * but because we always allowed it, error only when using new APIs.
+ */
+ if (strict_dir_events && mark_type == FAN_MARK_INODE &&
+ !d_is_dir(path->dentry) && (mask & FANOTIFY_DIRONLY_EVENT_BITS))
+ return -ENOTDIR;
+
return 0;
}
@@ -1634,7 +1651,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
goto fput_and_out;
if (flags & FAN_MARK_ADD) {
- ret = fanotify_events_supported(&path, mask);
+ ret = fanotify_events_supported(group, &path, mask, flags);
if (ret)
goto path_put_and_out;
}
@@ -1657,19 +1674,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
else
mnt = path.mnt;
- /*
- * FAN_RENAME is not allowed on non-dir (for now).
- * We shouldn't have allowed setting any dirent events in mask of
- * non-dir, but because we always allowed it, error only if group
- * was initialized with the new flag FAN_REPORT_TARGET_FID.
- */
- ret = -ENOTDIR;
- if (inode && !S_ISDIR(inode->i_mode) &&
- ((mask & FAN_RENAME) ||
- ((mask & FANOTIFY_DIRENT_EVENTS) &&
- FAN_GROUP_FLAG(group, FAN_REPORT_TARGET_FID))))
- goto path_put_and_out;
-
/* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */
if (mnt || !S_ISDIR(inode->i_mode)) {
mask &= ~FAN_EVENT_ON_CHILD;
diff --git a/fs/read_write.c b/fs/read_write.c
index e643aec2b0ef..671f47d5984c 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1381,28 +1381,6 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
}
EXPORT_SYMBOL(generic_copy_file_range);
-static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in,
- struct file *file_out, loff_t pos_out,
- size_t len, unsigned int flags)
-{
- /*
- * Although we now allow filesystems to handle cross sb copy, passing
- * a file of the wrong filesystem type to filesystem driver can result
- * in an attempt to dereference the wrong type of ->private_data, so
- * avoid doing that until we really have a good reason. NFS defines
- * several different file_system_type structures, but they all end up
- * using the same ->copy_file_range() function pointer.
- */
- if (file_out->f_op->copy_file_range &&
- file_out->f_op->copy_file_range == file_in->f_op->copy_file_range)
- return file_out->f_op->copy_file_range(file_in, pos_in,
- file_out, pos_out,
- len, flags);
-
- return generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
- flags);
-}
-
/*
* Performs necessary checks before doing a file copy
*
@@ -1424,6 +1402,24 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
if (ret)
return ret;
+ /*
+ * We allow some filesystems to handle cross sb copy, but passing
+ * a file of the wrong filesystem type to filesystem driver can result
+ * in an attempt to dereference the wrong type of ->private_data, so
+ * avoid doing that until we really have a good reason.
+ *
+ * nfs and cifs define several different file_system_type structures
+ * and several different sets of file_operations, but they all end up
+ * using the same ->copy_file_range() function pointer.
+ */
+ if (file_out->f_op->copy_file_range) {
+ if (file_in->f_op->copy_file_range !=
+ file_out->f_op->copy_file_range)
+ return -EXDEV;
+ } else if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) {
+ return -EXDEV;
+ }
+
/* Don't touch certain kinds of inodes */
if (IS_IMMUTABLE(inode_out))
return -EPERM;
@@ -1489,26 +1485,41 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
file_start_write(file_out);
/*
- * Try cloning first, this is supported by more file systems, and
- * more efficient if both clone and copy are supported (e.g. NFS).
+ * Cloning is supported by more file systems, so we implement copy on
+ * same sb using clone, but for filesystems where both clone and copy
+ * are supported (e.g. nfs,cifs), we only call the copy method.
*/
+ if (file_out->f_op->copy_file_range) {
+ ret = file_out->f_op->copy_file_range(file_in, pos_in,
+ file_out, pos_out,
+ len, flags);
+ goto done;
+ }
+
if (file_in->f_op->remap_file_range &&
file_inode(file_in)->i_sb == file_inode(file_out)->i_sb) {
- loff_t cloned;
-
- cloned = file_in->f_op->remap_file_range(file_in, pos_in,
+ ret = file_in->f_op->remap_file_range(file_in, pos_in,
file_out, pos_out,
min_t(loff_t, MAX_RW_COUNT, len),
REMAP_FILE_CAN_SHORTEN);
- if (cloned > 0) {
- ret = cloned;
+ if (ret > 0)
goto done;
- }
}
- ret = do_copy_file_range(file_in, pos_in, file_out, pos_out, len,
- flags);
- WARN_ON_ONCE(ret == -EOPNOTSUPP);
+ /*
+ * We can get here for same sb copy of filesystems that do not implement
+ * ->copy_file_range() in case filesystem does not support clone or in
+ * case filesystem supports clone but rejected the clone request (e.g.
+ * because it was not block aligned).
+ *
+ * In both cases, fall back to kernel copy so we are able to maintain a
+ * consistent story about which filesystems support copy_file_range()
+ * and which filesystems do not, that will allow userspace tools to
+ * make consistent desicions w.r.t using copy_file_range().
+ */
+ ret = generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
+ flags);
+
done:
if (ret > 0) {
fsnotify_access(file_in);
diff --git a/include/linux/dim.h b/include/linux/dim.h
index b698266d0035..6c5733981563 100644
--- a/include/linux/dim.h
+++ b/include/linux/dim.h
@@ -21,7 +21,7 @@
* We consider 10% difference as significant.
*/
#define IS_SIGNIFICANT_DIFF(val, ref) \
- (((100UL * abs((val) - (ref))) / (ref)) > 10)
+ ((ref) && (((100UL * abs((val) - (ref))) / (ref)) > 10))
/*
* Calculate the gap between two values.
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index 419cadcd7ff5..2f0e41888854 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -110,6 +110,10 @@
FANOTIFY_PERM_EVENTS | \
FAN_Q_OVERFLOW | FAN_ONDIR)
+/* Events and flags relevant only for directories */
+#define FANOTIFY_DIRONLY_EVENT_BITS (FANOTIFY_DIRENT_EVENTS | \
+ FAN_EVENT_ON_CHILD | FAN_ONDIR)
+
#define ALL_FANOTIFY_EVENT_BITS (FANOTIFY_OUTGOING_EVENTS | \
FANOTIFY_EVENT_FLAGS)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f736c020cde2..bfa27972f860 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1653,7 +1653,7 @@ enum netdev_priv_flags {
IFF_FAILOVER_SLAVE = 1<<28,
IFF_L3MDEV_RX_HANDLER = 1<<29,
IFF_LIVE_RENAME_OK = 1<<30,
- IFF_TX_SKB_NO_LINEAR = 1<<31,
+ IFF_TX_SKB_NO_LINEAR = BIT_ULL(31),
IFF_CHANGE_PROTO_DOWN = BIT_ULL(32),
};
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 36ca2b5c2253..b2b76dc2e5e2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -571,6 +571,10 @@ struct macsec_ops;
* @mdix: Current crossover
* @mdix_ctrl: User setting of crossover
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -625,6 +629,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index fc0c1454d275..7b9e3f9a0f00 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -1375,11 +1375,11 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
#define AMD_FMT_MOD_PIPE_MASK 0x7
#define AMD_FMT_MOD_SET(field, value) \
- ((uint64_t)(value) << AMD_FMT_MOD_##field##_SHIFT)
+ ((__u64)(value) << AMD_FMT_MOD_##field##_SHIFT)
#define AMD_FMT_MOD_GET(field, value) \
(((value) >> AMD_FMT_MOD_##field##_SHIFT) & AMD_FMT_MOD_##field##_MASK)
#define AMD_FMT_MOD_CLEAR(field) \
- (~((uint64_t)AMD_FMT_MOD_##field##_MASK << AMD_FMT_MOD_##field##_SHIFT))
+ (~((__u64)AMD_FMT_MOD_##field##_MASK << AMD_FMT_MOD_##field##_SHIFT))
#if defined(__cplusplus)
}
diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h
index 9690efedb5fa..3e085b6c05a6 100644
--- a/include/uapi/linux/mptcp.h
+++ b/include/uapi/linux/mptcp.h
@@ -2,16 +2,17 @@
#ifndef _UAPI_MPTCP_H
#define _UAPI_MPTCP_H
+#ifndef __KERNEL__
+#include <netinet/in.h> /* for sockaddr_in and sockaddr_in6 */
+#include <sys/socket.h> /* for struct sockaddr */
+#endif
+
#include <linux/const.h>
#include <linux/types.h>
#include <linux/in.h> /* for sockaddr_in */
#include <linux/in6.h> /* for sockaddr_in6 */
#include <linux/socket.h> /* for sockaddr_storage and sa_family */
-#ifndef __KERNEL__
-#include <sys/socket.h> /* for struct sockaddr */
-#endif
-
#define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0)
#define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1)
#define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2)
diff --git a/lib/sbitmap.c b/lib/sbitmap.c
index ae4fd4de9ebe..29eb0484215a 100644
--- a/lib/sbitmap.c
+++ b/lib/sbitmap.c
@@ -528,7 +528,7 @@ unsigned long __sbitmap_queue_get_batch(struct sbitmap_queue *sbq, int nr_tags,
sbitmap_deferred_clear(map);
if (map->word == (1UL << (map_depth - 1)) - 1)
- continue;
+ goto next;
nr = find_first_zero_bit(&map->word, map_depth);
if (nr + nr_tags <= map_depth) {
@@ -539,6 +539,8 @@ unsigned long __sbitmap_queue_get_batch(struct sbitmap_queue *sbq, int nr_tags,
get_mask = ((1UL << map_tags) - 1) << nr;
do {
val = READ_ONCE(map->word);
+ if ((val & ~get_mask) != val)
+ goto next;
ret = atomic_long_cmpxchg(ptr, val, get_mask | val);
} while (ret != val);
get_mask = (get_mask & ~ret) >> nr;
@@ -549,6 +551,7 @@ unsigned long __sbitmap_queue_get_batch(struct sbitmap_queue *sbq, int nr_tags,
return get_mask;
}
}
+next:
/* Jump to next index. */
if (++index >= sb->map_nr)
index = 0;
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 6b2dc7b2b612..cc1caab4a654 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -410,7 +410,7 @@ int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst,
u32 mtu = dst_mtu(encap_dst) - headroom;
if ((skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu)) ||
- (!skb_is_gso(skb) && (skb->len - skb_mac_header_len(skb)) <= mtu))
+ (!skb_is_gso(skb) && (skb->len - skb_network_offset(skb)) <= mtu))
return 0;
skb_dst_update_pmtu_no_confirm(skb, mtu);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 30a74e4eeab4..cd78b4fc334f 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1965,7 +1965,10 @@ int tcp_v4_rcv(struct sk_buff *skb)
struct sock *nsk;
sk = req->rsk_listener;
- drop_reason = tcp_inbound_md5_hash(sk, skb,
+ if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
+ drop_reason = SKB_DROP_REASON_XFRM_POLICY;
+ else
+ drop_reason = tcp_inbound_md5_hash(sk, skb,
&iph->saddr, &iph->daddr,
AF_INET, dif, sdif);
if (unlikely(drop_reason)) {
@@ -2017,6 +2020,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
}
goto discard_and_relse;
}
+ nf_reset_ct(skb);
if (nsk == sk) {
reqsk_put(req);
tcp_v4_restore_cb(skb);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 51e77dc6571a..3b47c901c832 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1109,10 +1109,6 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
goto out;
}
- if (net->ipv6.devconf_all->disable_policy ||
- idev->cnf.disable_policy)
- f6i->dst_nopolicy = true;
-
neigh_parms_data_state_setall(idev->nd_parms);
ifa->addr = *cfg->pfx;
@@ -5174,9 +5170,9 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
fillargs->event = RTM_GETMULTICAST;
/* multicast address */
- for (ifmca = rcu_dereference(idev->mc_list);
+ for (ifmca = rtnl_dereference(idev->mc_list);
ifmca;
- ifmca = rcu_dereference(ifmca->next), ip_idx++) {
+ ifmca = rtnl_dereference(ifmca->next), ip_idx++) {
if (ip_idx < s_ip_idx)
continue;
err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c4b6ce017d5e..83786de847ab 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -4565,8 +4565,15 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
}
f6i = ip6_route_info_create(&cfg, gfp_flags, NULL);
- if (!IS_ERR(f6i))
+ if (!IS_ERR(f6i)) {
f6i->dst_nocount = true;
+
+ if (!anycast &&
+ (net->ipv6.devconf_all->disable_policy ||
+ idev->cnf.disable_policy))
+ f6i->dst_nopolicy = true;
+ }
+
return f6i;
}
diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c
index 6de01185cc68..d43c50a7310d 100644
--- a/net/ipv6/seg6_hmac.c
+++ b/net/ipv6/seg6_hmac.c
@@ -406,7 +406,6 @@ int __net_init seg6_hmac_net_init(struct net *net)
return rhashtable_init(&sdata->hmac_infos, &rht_params);
}
-EXPORT_SYMBOL(seg6_hmac_net_init);
void seg6_hmac_exit(void)
{
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index c0b138c20992..6bcd5e419a08 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -323,8 +323,6 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
kcalloc(cmax, sizeof(*kp), GFP_KERNEL_ACCOUNT | __GFP_NOWARN) :
NULL;
- rcu_read_lock();
-
ca = min(t->prl_count, cmax);
if (!kp) {
@@ -341,7 +339,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
}
}
- c = 0;
+ rcu_read_lock();
for_each_prl_rcu(t->prl) {
if (c >= cmax)
break;
@@ -353,7 +351,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
if (kprl.addr != htonl(INADDR_ANY))
break;
}
-out:
+
rcu_read_unlock();
len = sizeof(*kp) * c;
@@ -362,7 +360,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
ret = -EFAULT;
kfree(kp);
-
+out:
return ret;
}
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 8f54293c1d88..713077eef04a 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -2305,6 +2305,11 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
kfree_rcu(subflow, rcu);
} else {
/* otherwise tcp will dispose of the ssk and subflow ctx */
+ if (ssk->sk_state == TCP_LISTEN) {
+ tcp_set_state(ssk, TCP_CLOSE);
+ mptcp_subflow_queue_clean(ssk);
+ inet_csk_listen_stop(ssk);
+ }
__tcp_close(ssk, 0);
/* close acquired an extra ref */
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 9ac63fa4866e..2aab5aff6bcd 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -286,6 +286,7 @@ struct mptcp_sock {
u32 setsockopt_seq;
char ca_name[TCP_CA_NAME_MAX];
+ struct mptcp_sock *dl_next;
};
#define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock)
@@ -585,6 +586,7 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
struct mptcp_subflow_context *subflow);
void mptcp_subflow_send_ack(struct sock *ssk);
void mptcp_subflow_reset(struct sock *ssk);
+void mptcp_subflow_queue_clean(struct sock *ssk);
void mptcp_sock_graft(struct sock *sk, struct socket *parent);
struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index be76ada89d96..7919e259175d 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1688,6 +1688,58 @@ static void subflow_state_change(struct sock *sk)
}
}
+void mptcp_subflow_queue_clean(struct sock *listener_ssk)
+{
+ struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue;
+ struct mptcp_sock *msk, *next, *head = NULL;
+ struct request_sock *req;
+
+ /* build a list of all unaccepted mptcp sockets */
+ spin_lock_bh(&queue->rskq_lock);
+ for (req = queue->rskq_accept_head; req; req = req->dl_next) {
+ struct mptcp_subflow_context *subflow;
+ struct sock *ssk = req->sk;
+ struct mptcp_sock *msk;
+
+ if (!sk_is_mptcp(ssk))
+ continue;
+
+ subflow = mptcp_subflow_ctx(ssk);
+ if (!subflow || !subflow->conn)
+ continue;
+
+ /* skip if already in list */
+ msk = mptcp_sk(subflow->conn);
+ if (msk->dl_next || msk == head)
+ continue;
+
+ msk->dl_next = head;
+ head = msk;
+ }
+ spin_unlock_bh(&queue->rskq_lock);
+ if (!head)
+ return;
+
+ /* can't acquire the msk socket lock under the subflow one,
+ * or will cause ABBA deadlock
+ */
+ release_sock(listener_ssk);
+
+ for (msk = head; msk; msk = next) {
+ struct sock *sk = (struct sock *)msk;
+ bool slow;
+
+ slow = lock_sock_fast_nested(sk);
+ next = msk->dl_next;
+ msk->first = NULL;
+ msk->dl_next = NULL;
+ unlock_sock_fast(sk, slow);
+ }
+
+ /* we are still under the listener msk socket lock */
+ lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING);
+}
+
static int subflow_ulp_init(struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk);
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
index df40314de21f..76de6c8d9865 100644
--- a/net/netfilter/nft_set_hash.c
+++ b/net/netfilter/nft_set_hash.c
@@ -143,6 +143,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key,
/* Another cpu may race to insert the element with the same key */
if (prev) {
nft_set_elem_destroy(set, he, true);
+ atomic_dec(&set->nelems);
he = prev;
}
@@ -152,6 +153,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key,
err2:
nft_set_elem_destroy(set, he, true);
+ atomic_dec(&set->nelems);
err1:
return false;
}
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index b3138fc2e552..f06ddbed3fed 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -31,89 +31,89 @@ static void rose_idletimer_expiry(struct timer_list *);
void rose_start_heartbeat(struct sock *sk)
{
- del_timer(&sk->sk_timer);
+ sk_stop_timer(sk, &sk->sk_timer);
sk->sk_timer.function = rose_heartbeat_expiry;
sk->sk_timer.expires = jiffies + 5 * HZ;
- add_timer(&sk->sk_timer);
+ sk_reset_timer(sk, &sk->sk_timer, sk->sk_timer.expires);
}
void rose_start_t1timer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->timer);
+ sk_stop_timer(sk, &rose->timer);
rose->timer.function = rose_timer_expiry;
rose->timer.expires = jiffies + rose->t1;
- add_timer(&rose->timer);
+ sk_reset_timer(sk, &rose->timer, rose->timer.expires);
}
void rose_start_t2timer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->timer);
+ sk_stop_timer(sk, &rose->timer);
rose->timer.function = rose_timer_expiry;
rose->timer.expires = jiffies + rose->t2;
- add_timer(&rose->timer);
+ sk_reset_timer(sk, &rose->timer, rose->timer.expires);
}
void rose_start_t3timer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->timer);
+ sk_stop_timer(sk, &rose->timer);
rose->timer.function = rose_timer_expiry;
rose->timer.expires = jiffies + rose->t3;
- add_timer(&rose->timer);
+ sk_reset_timer(sk, &rose->timer, rose->timer.expires);
}
void rose_start_hbtimer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->timer);
+ sk_stop_timer(sk, &rose->timer);
rose->timer.function = rose_timer_expiry;
rose->timer.expires = jiffies + rose->hb;
- add_timer(&rose->timer);
+ sk_reset_timer(sk, &rose->timer, rose->timer.expires);
}
void rose_start_idletimer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->idletimer);
+ sk_stop_timer(sk, &rose->idletimer);
if (rose->idle > 0) {
rose->idletimer.function = rose_idletimer_expiry;
rose->idletimer.expires = jiffies + rose->idle;
- add_timer(&rose->idletimer);
+ sk_reset_timer(sk, &rose->idletimer, rose->idletimer.expires);
}
}
void rose_stop_heartbeat(struct sock *sk)
{
- del_timer(&sk->sk_timer);
+ sk_stop_timer(sk, &sk->sk_timer);
}
void rose_stop_timer(struct sock *sk)
{
- del_timer(&rose_sk(sk)->timer);
+ sk_stop_timer(sk, &rose_sk(sk)->timer);
}
void rose_stop_idletimer(struct sock *sk)
{
- del_timer(&rose_sk(sk)->idletimer);
+ sk_stop_timer(sk, &rose_sk(sk)->idletimer);
}
static void rose_heartbeat_expiry(struct timer_list *t)
@@ -130,6 +130,7 @@ static void rose_heartbeat_expiry(struct timer_list *t)
(sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
bh_unlock_sock(sk);
rose_destroy_socket(sk);
+ sock_put(sk);
return;
}
break;
@@ -152,6 +153,7 @@ static void rose_heartbeat_expiry(struct timer_list *t)
rose_start_heartbeat(sk);
bh_unlock_sock(sk);
+ sock_put(sk);
}
static void rose_timer_expiry(struct timer_list *t)
@@ -181,6 +183,7 @@ static void rose_timer_expiry(struct timer_list *t)
break;
}
bh_unlock_sock(sk);
+ sock_put(sk);
}
static void rose_idletimer_expiry(struct timer_list *t)
@@ -205,4 +208,5 @@ static void rose_idletimer_expiry(struct timer_list *t)
sock_set_flag(sk, SOCK_DEAD);
}
bh_unlock_sock(sk);
+ sock_put(sk);
}
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 4f51094da9da..6fa9e7b1406a 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -588,7 +588,8 @@ static int tcf_idr_release_unsafe(struct tc_action *p)
}
static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
- const struct tc_action_ops *ops)
+ const struct tc_action_ops *ops,
+ struct netlink_ext_ack *extack)
{
struct nlattr *nest;
int n_i = 0;
@@ -604,20 +605,25 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
if (nla_put_string(skb, TCA_KIND, ops->kind))
goto nla_put_failure;
+ ret = 0;
mutex_lock(&idrinfo->lock);
idr_for_each_entry_ul(idr, p, tmp, id) {
if (IS_ERR(p))
continue;
ret = tcf_idr_release_unsafe(p);
- if (ret == ACT_P_DELETED) {
+ if (ret == ACT_P_DELETED)
module_put(ops->owner);
- n_i++;
- } else if (ret < 0) {
- mutex_unlock(&idrinfo->lock);
- goto nla_put_failure;
- }
+ else if (ret < 0)
+ break;
+ n_i++;
}
mutex_unlock(&idrinfo->lock);
+ if (ret < 0) {
+ if (n_i)
+ NL_SET_ERR_MSG(extack, "Unable to flush all TC actions");
+ else
+ goto nla_put_failure;
+ }
ret = nla_put_u32(skb, TCA_FCNT, n_i);
if (ret)
@@ -638,7 +644,7 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct tcf_idrinfo *idrinfo = tn->idrinfo;
if (type == RTM_DELACTION) {
- return tcf_del_walker(idrinfo, skb, ops);
+ return tcf_del_walker(idrinfo, skb, ops, extack);
} else if (type == RTM_GETACTION) {
return tcf_dump_walker(idrinfo, skb, cb);
} else {
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index b57cf9df4de8..8272427d29ca 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -979,7 +979,7 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr,
*/
xdr->p = (void *)p + frag2bytes;
space_left = xdr->buf->buflen - xdr->buf->len;
- if (space_left - nbytes >= PAGE_SIZE)
+ if (space_left - frag1bytes >= PAGE_SIZE)
xdr->end = (void *)p + PAGE_SIZE;
else
xdr->end = (void *)p + space_left - frag1bytes;
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 6ef95ce565bd..b48d97cbbe29 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -472,8 +472,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
bool preliminary)
{
struct tipc_net *tn = net_generic(net, tipc_net_id);
+ struct tipc_link *l, *snd_l = tipc_bc_sndlink(net);
struct tipc_node *n, *temp_node;
- struct tipc_link *l;
unsigned long intv;
int bearer_id;
int i;
@@ -488,6 +488,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
goto exit;
/* A preliminary node becomes "real" now, refresh its data */
tipc_node_write_lock(n);
+ if (!tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX,
+ tipc_link_min_win(snd_l), tipc_link_max_win(snd_l),
+ n->capabilities, &n->bc_entry.inputq1,
+ &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
+ pr_warn("Broadcast rcv link refresh failed, no memory\n");
+ tipc_node_write_unlock_fast(n);
+ tipc_node_put(n);
+ n = NULL;
+ goto exit;
+ }
n->preliminary = false;
n->addr = addr;
hlist_del_rcu(&n->hash);
@@ -567,7 +577,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
n->signature = INVALID_NODE_SIG;
n->active_links[0] = INVALID_BEARER_ID;
n->active_links[1] = INVALID_BEARER_ID;
- n->bc_entry.link = NULL;
+ if (!preliminary &&
+ !tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX,
+ tipc_link_min_win(snd_l), tipc_link_max_win(snd_l),
+ n->capabilities, &n->bc_entry.inputq1,
+ &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
+ pr_warn("Broadcast rcv link creation failed, no memory\n");
+ kfree(n);
+ n = NULL;
+ goto exit;
+ }
tipc_node_get(n);
timer_setup(&n->timer, tipc_node_timeout, 0);
/* Start a slow timer anyway, crypto needs it */
@@ -1155,7 +1174,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
bool *respond, bool *dupl_addr)
{
struct tipc_node *n;
- struct tipc_link *l, *snd_l;
+ struct tipc_link *l;
struct tipc_link_entry *le;
bool addr_match = false;
bool sign_match = false;
@@ -1175,22 +1194,6 @@ void tipc_node_check_dest(struct net *net, u32 addr,
return;
tipc_node_write_lock(n);
- if (unlikely(!n->bc_entry.link)) {
- snd_l = tipc_bc_sndlink(net);
- if (!tipc_link_bc_create(net, tipc_own_addr(net),
- addr, peer_id, U16_MAX,
- tipc_link_min_win(snd_l),
- tipc_link_max_win(snd_l),
- n->capabilities,
- &n->bc_entry.inputq1,
- &n->bc_entry.namedq, snd_l,
- &n->bc_entry.link)) {
- pr_warn("Broadcast rcv link creation failed, no mem\n");
- tipc_node_write_unlock_fast(n);
- tipc_node_put(n);
- return;
- }
- }
le = &n->links[b->identity];
diff --git a/tools/testing/selftests/net/bpf/Makefile b/tools/testing/selftests/net/bpf/Makefile
index 8a69c91fcca0..8ccaf8732eb2 100644
--- a/tools/testing/selftests/net/bpf/Makefile
+++ b/tools/testing/selftests/net/bpf/Makefile
@@ -2,7 +2,7 @@
CLANG ?= clang
CCINCLUDE += -I../../bpf
-CCINCLUDE += -I../../../lib
+CCINCLUDE += -I../../../../lib
CCINCLUDE += -I../../../../../usr/include/
TEST_CUSTOM_PROGS = $(OUTPUT)/bpf/nat6to4.o
diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh
index ff821025d309..49dfabded1d4 100755
--- a/tools/testing/selftests/net/mptcp/diag.sh
+++ b/tools/testing/selftests/net/mptcp/diag.sh
@@ -61,6 +61,39 @@ chk_msk_nr()
__chk_nr "grep -c token:" $*
}
+wait_msk_nr()
+{
+ local condition="grep -c token:"
+ local expected=$1
+ local timeout=20
+ local msg nr
+ local max=0
+ local i=0
+
+ shift 1
+ msg=$*
+
+ while [ $i -lt $timeout ]; do
+ nr=$(ss -inmHMN $ns | $condition)
+ [ $nr == $expected ] && break;
+ [ $nr -gt $max ] && max=$nr
+ i=$((i + 1))
+ sleep 1
+ done
+
+ printf "%-50s" "$msg"
+ if [ $i -ge $timeout ]; then
+ echo "[ fail ] timeout while expecting $expected max $max last $nr"
+ ret=$test_cnt
+ elif [ $nr != $expected ]; then
+ echo "[ fail ] expected $expected found $nr"
+ ret=$test_cnt
+ else
+ echo "[ ok ]"
+ fi
+ test_cnt=$((test_cnt+1))
+}
+
chk_msk_fallback_nr()
{
__chk_nr "grep -c fallback" $*
@@ -109,7 +142,7 @@ ip -n $ns link set dev lo up
echo "a" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10000 -l -t ${timeout_poll} \
+ ./mptcp_connect -p 10000 -l -t ${timeout_poll} -w 20 \
0.0.0.0 >/dev/null &
wait_local_port_listen $ns 10000
chk_msk_nr 0 "no msk on netns creation"
@@ -117,7 +150,7 @@ chk_msk_nr 0 "no msk on netns creation"
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} \
+ ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} -w 20 \
127.0.0.1 >/dev/null &
wait_connected $ns 10000
chk_msk_nr 2 "after MPC handshake "
@@ -129,13 +162,13 @@ flush_pids
echo "a" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} \
+ ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} -w 20 \
0.0.0.0 >/dev/null &
wait_local_port_listen $ns 10001
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} \
+ ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} -w 20 \
127.0.0.1 >/dev/null &
wait_connected $ns 10001
chk_msk_fallback_nr 1 "check fallback"
@@ -146,7 +179,7 @@ for I in `seq 1 $NR_CLIENTS`; do
echo "a" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p $((I+10001)) -l -w 10 \
+ ./mptcp_connect -p $((I+10001)) -l -w 20 \
-t ${timeout_poll} 0.0.0.0 >/dev/null &
done
wait_local_port_listen $ns $((NR_CLIENTS + 10001))
@@ -155,12 +188,11 @@ for I in `seq 1 $NR_CLIENTS`; do
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p $((I+10001)) -w 10 \
+ ./mptcp_connect -p $((I+10001)) -w 20 \
-t ${timeout_poll} 127.0.0.1 >/dev/null &
done
-sleep 1.5
-chk_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
+wait_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
flush_pids
exit $ret
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index 8628aa61b763..e2ea6c126c99 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -265,7 +265,7 @@ static void sock_test_tcpulp(int sock, int proto, unsigned int line)
static int sock_listen_mptcp(const char * const listenaddr,
const char * const port)
{
- int sock;
+ int sock = -1;
struct addrinfo hints = {
.ai_protocol = IPPROTO_TCP,
.ai_socktype = SOCK_STREAM,
diff --git a/tools/testing/selftests/net/mptcp/mptcp_inq.c b/tools/testing/selftests/net/mptcp/mptcp_inq.c
index 29f75e2a1116..8672d898f8cd 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_inq.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_inq.c
@@ -88,7 +88,7 @@ static void xgetaddrinfo(const char *node, const char *service,
static int sock_listen_mptcp(const char * const listenaddr,
const char * const port)
{
- int sock;
+ int sock = -1;
struct addrinfo hints = {
.ai_protocol = IPPROTO_TCP,
.ai_socktype = SOCK_STREAM,
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index ac9a4d9c1764..ae61f39556ca 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -136,7 +136,7 @@ static void xgetaddrinfo(const char *node, const char *service,
static int sock_listen_mptcp(const char * const listenaddr,
const char * const port)
{
- int sock;
+ int sock = -1;
struct addrinfo hints = {
.ai_protocol = IPPROTO_TCP,
.ai_socktype = SOCK_STREAM,
diff --git a/tools/testing/selftests/net/udpgso_bench.sh b/tools/testing/selftests/net/udpgso_bench.sh
index 80b5d352702e..dc932fd65363 100755
--- a/tools/testing/selftests/net/udpgso_bench.sh
+++ b/tools/testing/selftests/net/udpgso_bench.sh
@@ -120,7 +120,7 @@ run_all() {
run_udp "${ipv4_args}"
echo "ipv6"
- run_tcp "${ipv4_args}"
+ run_tcp "${ipv6_args}"
run_udp "${ipv6_args}"
}
^ permalink raw reply related [relevance 1%]
* Re: Linux 5.15.53
@ 2022-07-07 16:08 1% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-07-07 16:08 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/MAINTAINERS b/MAINTAINERS
index 393706e85ba2..a60d7e0466af 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20579,6 +20579,7 @@ F: drivers/xen/*swiotlb*
XFS FILESYSTEM
C: irc://irc.oftc.net/xfs
+M: Leah Rumancik <leah.rumancik@gmail.com>
M: Darrick J. Wong <djwong@kernel.org>
M: linux-xfs@vger.kernel.org
L: linux-xfs@vger.kernel.org
diff --git a/Makefile b/Makefile
index 777e0a0eeccd..c7750d260a55 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 15
-SUBLEVEL = 52
+SUBLEVEL = 53
EXTRAVERSION =
NAME = Trick or Treat
diff --git a/arch/arm/xen/p2m.c b/arch/arm/xen/p2m.c
index 84a1cea1f43b..309648c17f48 100644
--- a/arch/arm/xen/p2m.c
+++ b/arch/arm/xen/p2m.c
@@ -63,11 +63,12 @@ static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
unsigned long __pfn_to_mfn(unsigned long pfn)
{
- struct rb_node *n = phys_to_mach.rb_node;
+ struct rb_node *n;
struct xen_p2m_entry *entry;
unsigned long irqflags;
read_lock_irqsave(&p2m_lock, irqflags);
+ n = phys_to_mach.rb_node;
while (n) {
entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
if (entry->pfn <= pfn &&
@@ -152,10 +153,11 @@ bool __set_phys_to_machine_multi(unsigned long pfn,
int rc;
unsigned long irqflags;
struct xen_p2m_entry *p2m_entry;
- struct rb_node *n = phys_to_mach.rb_node;
+ struct rb_node *n;
if (mfn == INVALID_P2M_ENTRY) {
write_lock_irqsave(&p2m_lock, irqflags);
+ n = phys_to_mach.rb_node;
while (n) {
p2m_entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
if (p2m_entry->pfn <= pfn &&
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 941618a7f7ff..27222b75d2a4 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -353,6 +353,10 @@ config ARCH_SUSPEND_NONZERO_CPU
def_bool y
depends on PPC_POWERNV || PPC_PSERIES
+config ARCH_HAS_ADD_PAGES
+ def_bool y
+ depends on ARCH_ENABLE_MEMORY_HOTPLUG
+
config PPC_DCR_NATIVE
bool
diff --git a/arch/powerpc/include/asm/bpf_perf_event.h b/arch/powerpc/include/asm/bpf_perf_event.h
new file mode 100644
index 000000000000..e8a7b4ffb58c
--- /dev/null
+++ b/arch/powerpc/include/asm/bpf_perf_event.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_BPF_PERF_EVENT_H
+#define _ASM_POWERPC_BPF_PERF_EVENT_H
+
+#include <asm/ptrace.h>
+
+typedef struct user_pt_regs bpf_user_pt_regs_t;
+
+#endif /* _ASM_POWERPC_BPF_PERF_EVENT_H */
diff --git a/arch/powerpc/include/uapi/asm/bpf_perf_event.h b/arch/powerpc/include/uapi/asm/bpf_perf_event.h
deleted file mode 100644
index 5e1e648aeec4..000000000000
--- a/arch/powerpc/include/uapi/asm/bpf_perf_event.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
-#define _UAPI__ASM_BPF_PERF_EVENT_H__
-
-#include <asm/ptrace.h>
-
-typedef struct user_pt_regs bpf_user_pt_regs_t;
-
-#endif /* _UAPI__ASM_BPF_PERF_EVENT_H__ */
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
index b183ab9c5107..dfa5f729f774 100644
--- a/arch/powerpc/kernel/prom_init_check.sh
+++ b/arch/powerpc/kernel/prom_init_check.sh
@@ -13,7 +13,7 @@
# If you really need to reference something from prom_init.o add
# it to the list below:
-grep "^CONFIG_KASAN=y$" .config >/dev/null
+grep "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} >/dev/null
if [ $? -eq 0 ]
then
MEM_FUNCS="__memcpy __memset"
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 543a044560e9..6902f453c745 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -104,6 +104,37 @@ void __ref arch_remove_linear_mapping(u64 start, u64 size)
vm_unmap_aliases();
}
+/*
+ * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need
+ * updating.
+ */
+static void update_end_of_memory_vars(u64 start, u64 size)
+{
+ unsigned long end_pfn = PFN_UP(start + size);
+
+ if (end_pfn > max_pfn) {
+ max_pfn = end_pfn;
+ max_low_pfn = end_pfn;
+ high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+ }
+}
+
+int __ref add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
+ struct mhp_params *params)
+{
+ int ret;
+
+ ret = __add_pages(nid, start_pfn, nr_pages, params);
+ if (ret)
+ return ret;
+
+ /* update max_pfn, max_low_pfn and high_memory */
+ update_end_of_memory_vars(start_pfn << PAGE_SHIFT,
+ nr_pages << PAGE_SHIFT);
+
+ return ret;
+}
+
int __ref arch_add_memory(int nid, u64 start, u64 size,
struct mhp_params *params)
{
@@ -114,7 +145,7 @@ int __ref arch_add_memory(int nid, u64 start, u64 size,
rc = arch_create_linear_mapping(nid, start, size, params);
if (rc)
return rc;
- rc = __add_pages(nid, start_pfn, nr_pages, params);
+ rc = add_pages(nid, start_pfn, nr_pages, params);
if (rc)
arch_remove_linear_mapping(start, size);
return rc;
diff --git a/arch/powerpc/mm/nohash/book3e_pgtable.c b/arch/powerpc/mm/nohash/book3e_pgtable.c
index 77884e24281d..3d845e001c87 100644
--- a/arch/powerpc/mm/nohash/book3e_pgtable.c
+++ b/arch/powerpc/mm/nohash/book3e_pgtable.c
@@ -95,8 +95,8 @@ int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
pgdp = pgd_offset_k(ea);
p4dp = p4d_offset(pgdp, ea);
if (p4d_none(*p4dp)) {
- pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
- p4d_populate(&init_mm, p4dp, pmdp);
+ pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
+ p4d_populate(&init_mm, p4dp, pudp);
}
pudp = pud_offset(p4dp, ea);
if (pud_none(*pudp)) {
@@ -105,7 +105,7 @@ int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
}
pmdp = pmd_offset(pudp, ea);
if (!pmd_present(*pmdp)) {
- ptep = early_alloc_pgtable(PAGE_SIZE);
+ ptep = early_alloc_pgtable(PTE_TABLE_SIZE);
pmd_populate_kernel(&init_mm, pmdp, ptep);
}
ptep = pte_offset_kernel(pmdp, ea);
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 797041b5109a..e402fa964f23 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -516,7 +516,6 @@ config KEXEC
config KEXEC_FILE
bool "kexec file based system call"
select KEXEC_CORE
- select BUILD_BIN2C
depends on CRYPTO
depends on CRYPTO_SHA256
depends on CRYPTO_SHA256_S390
diff --git a/arch/s390/crypto/arch_random.c b/arch/s390/crypto/arch_random.c
index 56007c763902..1f2d40993c4d 100644
--- a/arch/s390/crypto/arch_random.c
+++ b/arch/s390/crypto/arch_random.c
@@ -4,232 +4,15 @@
*
* Copyright IBM Corp. 2017, 2020
* Author(s): Harald Freudenberger
- *
- * The s390_arch_random_generate() function may be called from random.c
- * in interrupt context. So this implementation does the best to be very
- * fast. There is a buffer of random data which is asynchronously checked
- * and filled by a workqueue thread.
- * If there are enough bytes in the buffer the s390_arch_random_generate()
- * just delivers these bytes. Otherwise false is returned until the
- * worker thread refills the buffer.
- * The worker fills the rng buffer by pulling fresh entropy from the
- * high quality (but slow) true hardware random generator. This entropy
- * is then spread over the buffer with an pseudo random generator PRNG.
- * As the arch_get_random_seed_long() fetches 8 bytes and the calling
- * function add_interrupt_randomness() counts this as 1 bit entropy the
- * distribution needs to make sure there is in fact 1 bit entropy contained
- * in 8 bytes of the buffer. The current values pull 32 byte entropy
- * and scatter this into a 2048 byte buffer. So 8 byte in the buffer
- * will contain 1 bit of entropy.
- * The worker thread is rescheduled based on the charge level of the
- * buffer but at least with 500 ms delay to avoid too much CPU consumption.
- * So the max. amount of rng data delivered via arch_get_random_seed is
- * limited to 4k bytes per second.
*/
#include <linux/kernel.h>
#include <linux/atomic.h>
#include <linux/random.h>
-#include <linux/slab.h>
#include <linux/static_key.h>
-#include <linux/workqueue.h>
-#include <linux/moduleparam.h>
#include <asm/cpacf.h>
DEFINE_STATIC_KEY_FALSE(s390_arch_random_available);
atomic64_t s390_arch_random_counter = ATOMIC64_INIT(0);
EXPORT_SYMBOL(s390_arch_random_counter);
-
-#define ARCH_REFILL_TICKS (HZ/2)
-#define ARCH_PRNG_SEED_SIZE 32
-#define ARCH_RNG_BUF_SIZE 2048
-
-static DEFINE_SPINLOCK(arch_rng_lock);
-static u8 *arch_rng_buf;
-static unsigned int arch_rng_buf_idx;
-
-static void arch_rng_refill_buffer(struct work_struct *);
-static DECLARE_DELAYED_WORK(arch_rng_work, arch_rng_refill_buffer);
-
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes)
-{
- /* max hunk is ARCH_RNG_BUF_SIZE */
- if (nbytes > ARCH_RNG_BUF_SIZE)
- return false;
-
- /* lock rng buffer */
- if (!spin_trylock(&arch_rng_lock))
- return false;
-
- /* try to resolve the requested amount of bytes from the buffer */
- arch_rng_buf_idx -= nbytes;
- if (arch_rng_buf_idx < ARCH_RNG_BUF_SIZE) {
- memcpy(buf, arch_rng_buf + arch_rng_buf_idx, nbytes);
- atomic64_add(nbytes, &s390_arch_random_counter);
- spin_unlock(&arch_rng_lock);
- return true;
- }
-
- /* not enough bytes in rng buffer, refill is done asynchronously */
- spin_unlock(&arch_rng_lock);
-
- return false;
-}
-EXPORT_SYMBOL(s390_arch_random_generate);
-
-static void arch_rng_refill_buffer(struct work_struct *unused)
-{
- unsigned int delay = ARCH_REFILL_TICKS;
-
- spin_lock(&arch_rng_lock);
- if (arch_rng_buf_idx > ARCH_RNG_BUF_SIZE) {
- /* buffer is exhausted and needs refill */
- u8 seed[ARCH_PRNG_SEED_SIZE];
- u8 prng_wa[240];
- /* fetch ARCH_PRNG_SEED_SIZE bytes of entropy */
- cpacf_trng(NULL, 0, seed, sizeof(seed));
- /* blow this entropy up to ARCH_RNG_BUF_SIZE with PRNG */
- memset(prng_wa, 0, sizeof(prng_wa));
- cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
- &prng_wa, NULL, 0, seed, sizeof(seed));
- cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
- &prng_wa, arch_rng_buf, ARCH_RNG_BUF_SIZE, NULL, 0);
- arch_rng_buf_idx = ARCH_RNG_BUF_SIZE;
- }
- delay += (ARCH_REFILL_TICKS * arch_rng_buf_idx) / ARCH_RNG_BUF_SIZE;
- spin_unlock(&arch_rng_lock);
-
- /* kick next check */
- queue_delayed_work(system_long_wq, &arch_rng_work, delay);
-}
-
-/*
- * Here follows the implementation of s390_arch_get_random_long().
- *
- * The random longs to be pulled by arch_get_random_long() are
- * prepared in an 4K buffer which is filled from the NIST 800-90
- * compliant s390 drbg. By default the random long buffer is refilled
- * 256 times before the drbg itself needs a reseed. The reseed of the
- * drbg is done with 32 bytes fetched from the high quality (but slow)
- * trng which is assumed to deliver 100% entropy. So the 32 * 8 = 256
- * bits of entropy are spread over 256 * 4KB = 1MB serving 131072
- * arch_get_random_long() invocations before reseeded.
- *
- * How often the 4K random long buffer is refilled with the drbg
- * before the drbg is reseeded can be adjusted. There is a module
- * parameter 's390_arch_rnd_long_drbg_reseed' accessible via
- * /sys/module/arch_random/parameters/rndlong_drbg_reseed
- * or as kernel command line parameter
- * arch_random.rndlong_drbg_reseed=<value>
- * This parameter tells how often the drbg fills the 4K buffer before
- * it is re-seeded by fresh entropy from the trng.
- * A value of 16 results in reseeding the drbg at every 16 * 4 KB = 64
- * KB with 32 bytes of fresh entropy pulled from the trng. So a value
- * of 16 would result in 256 bits entropy per 64 KB.
- * A value of 256 results in 1MB of drbg output before a reseed of the
- * drbg is done. So this would spread the 256 bits of entropy among 1MB.
- * Setting this parameter to 0 forces the reseed to take place every
- * time the 4K buffer is depleted, so the entropy rises to 256 bits
- * entropy per 4K or 0.5 bit entropy per arch_get_random_long(). With
- * setting this parameter to negative values all this effort is
- * disabled, arch_get_random long() returns false and thus indicating
- * that the arch_get_random_long() feature is disabled at all.
- */
-
-static unsigned long rndlong_buf[512];
-static DEFINE_SPINLOCK(rndlong_lock);
-static int rndlong_buf_index;
-
-static int rndlong_drbg_reseed = 256;
-module_param_named(rndlong_drbg_reseed, rndlong_drbg_reseed, int, 0600);
-MODULE_PARM_DESC(rndlong_drbg_reseed, "s390 arch_get_random_long() drbg reseed");
-
-static inline void refill_rndlong_buf(void)
-{
- static u8 prng_ws[240];
- static int drbg_counter;
-
- if (--drbg_counter < 0) {
- /* need to re-seed the drbg */
- u8 seed[32];
-
- /* fetch seed from trng */
- cpacf_trng(NULL, 0, seed, sizeof(seed));
- /* seed drbg */
- memset(prng_ws, 0, sizeof(prng_ws));
- cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
- &prng_ws, NULL, 0, seed, sizeof(seed));
- /* re-init counter for drbg */
- drbg_counter = rndlong_drbg_reseed;
- }
-
- /* fill the arch_get_random_long buffer from drbg */
- cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &prng_ws,
- (u8 *) rndlong_buf, sizeof(rndlong_buf),
- NULL, 0);
-}
-
-bool s390_arch_get_random_long(unsigned long *v)
-{
- bool rc = false;
- unsigned long flags;
-
- /* arch_get_random_long() disabled ? */
- if (rndlong_drbg_reseed < 0)
- return false;
-
- /* try to lock the random long lock */
- if (!spin_trylock_irqsave(&rndlong_lock, flags))
- return false;
-
- if (--rndlong_buf_index >= 0) {
- /* deliver next long value from the buffer */
- *v = rndlong_buf[rndlong_buf_index];
- rc = true;
- goto out;
- }
-
- /* buffer is depleted and needs refill */
- if (in_interrupt()) {
- /* delay refill in interrupt context to next caller */
- rndlong_buf_index = 0;
- goto out;
- }
-
- /* refill random long buffer */
- refill_rndlong_buf();
- rndlong_buf_index = ARRAY_SIZE(rndlong_buf);
-
- /* and provide one random long */
- *v = rndlong_buf[--rndlong_buf_index];
- rc = true;
-
-out:
- spin_unlock_irqrestore(&rndlong_lock, flags);
- return rc;
-}
-EXPORT_SYMBOL(s390_arch_get_random_long);
-
-static int __init s390_arch_random_init(void)
-{
- /* all the needed PRNO subfunctions available ? */
- if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG) &&
- cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) {
-
- /* alloc arch random working buffer */
- arch_rng_buf = kmalloc(ARCH_RNG_BUF_SIZE, GFP_KERNEL);
- if (!arch_rng_buf)
- return -ENOMEM;
-
- /* kick worker queue job to fill the random buffer */
- queue_delayed_work(system_long_wq,
- &arch_rng_work, ARCH_REFILL_TICKS);
-
- /* enable arch random to the outside world */
- static_branch_enable(&s390_arch_random_available);
- }
-
- return 0;
-}
-arch_initcall(s390_arch_random_init);
diff --git a/arch/s390/include/asm/archrandom.h b/arch/s390/include/asm/archrandom.h
index 5dc712fde3c7..2c6e1c6ecbe7 100644
--- a/arch/s390/include/asm/archrandom.h
+++ b/arch/s390/include/asm/archrandom.h
@@ -15,17 +15,13 @@
#include <linux/static_key.h>
#include <linux/atomic.h>
+#include <asm/cpacf.h>
DECLARE_STATIC_KEY_FALSE(s390_arch_random_available);
extern atomic64_t s390_arch_random_counter;
-bool s390_arch_get_random_long(unsigned long *v);
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes);
-
static inline bool __must_check arch_get_random_long(unsigned long *v)
{
- if (static_branch_likely(&s390_arch_random_available))
- return s390_arch_get_random_long(v);
return false;
}
@@ -37,7 +33,9 @@ static inline bool __must_check arch_get_random_int(unsigned int *v)
static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
{
if (static_branch_likely(&s390_arch_random_available)) {
- return s390_arch_random_generate((u8 *)v, sizeof(*v));
+ cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+ atomic64_add(sizeof(*v), &s390_arch_random_counter);
+ return true;
}
return false;
}
@@ -45,7 +43,9 @@ static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
{
if (static_branch_likely(&s390_arch_random_available)) {
- return s390_arch_random_generate((u8 *)v, sizeof(*v));
+ cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+ atomic64_add(sizeof(*v), &s390_arch_random_counter);
+ return true;
}
return false;
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index ee67215a678a..8ede12c4ba6b 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -880,6 +880,11 @@ static void __init setup_randomness(void)
if (stsi(vmms, 3, 2, 2) == 0 && vmms->count)
add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count);
memblock_free((unsigned long) vmms, PAGE_SIZE);
+
+#ifdef CONFIG_ARCH_RANDOM
+ if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
+ static_branch_enable(&s390_arch_random_available);
+#endif
}
/*
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index 42ede059728c..007deb3a8ea3 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -73,6 +73,7 @@ module_param(device_id_scheme, bool, 0444);
static int only_lcd = -1;
module_param(only_lcd, int, 0444);
+static bool has_backlight;
static int register_count;
static DEFINE_MUTEX(register_count_mutex);
static DEFINE_MUTEX(video_list_lock);
@@ -1222,6 +1223,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
acpi_video_device_bind(video, data);
acpi_video_device_find_cap(data);
+ if (data->cap._BCM && data->cap._BCL)
+ has_backlight = true;
+
mutex_lock(&video->device_list_lock);
list_add_tail(&data->entry, &video->video_device_list);
mutex_unlock(&video->device_list_lock);
@@ -2251,6 +2255,7 @@ void acpi_video_unregister(void)
if (register_count) {
acpi_bus_unregister_driver(&acpi_video_bus);
register_count = 0;
+ has_backlight = false;
}
mutex_unlock(®ister_count_mutex);
}
@@ -2272,13 +2277,7 @@ void acpi_video_unregister_backlight(void)
bool acpi_video_handles_brightness_key_presses(void)
{
- bool have_video_busses;
-
- mutex_lock(&video_list_lock);
- have_video_busses = !list_empty(&video_bus_head);
- mutex_unlock(&video_list_lock);
-
- return have_video_busses &&
+ return has_backlight &&
(report_key_events & REPORT_BRIGHTNESS_KEY_EVENTS);
}
EXPORT_SYMBOL(acpi_video_handles_brightness_key_presses);
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index d7a9bf43fb32..f6f679702b83 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -152,6 +152,10 @@ static unsigned int xen_blkif_max_ring_order;
module_param_named(max_ring_page_order, xen_blkif_max_ring_order, int, 0444);
MODULE_PARM_DESC(max_ring_page_order, "Maximum order of pages to be used for the shared ring");
+static bool __read_mostly xen_blkif_trusted = true;
+module_param_named(trusted, xen_blkif_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
#define BLK_RING_SIZE(info) \
__CONST_RING_SIZE(blkif, XEN_PAGE_SIZE * (info)->nr_ring_pages)
@@ -209,6 +213,7 @@ struct blkfront_info
unsigned int feature_discard:1;
unsigned int feature_secdiscard:1;
unsigned int feature_persistent:1;
+ unsigned int bounce:1;
unsigned int discard_granularity;
unsigned int discard_alignment;
/* Number of 4KB segments handled */
@@ -311,8 +316,8 @@ static int fill_grant_buffer(struct blkfront_ring_info *rinfo, int num)
if (!gnt_list_entry)
goto out_of_memory;
- if (info->feature_persistent) {
- granted_page = alloc_page(GFP_NOIO);
+ if (info->bounce) {
+ granted_page = alloc_page(GFP_NOIO | __GFP_ZERO);
if (!granted_page) {
kfree(gnt_list_entry);
goto out_of_memory;
@@ -331,7 +336,7 @@ static int fill_grant_buffer(struct blkfront_ring_info *rinfo, int num)
list_for_each_entry_safe(gnt_list_entry, n,
&rinfo->grants, node) {
list_del(&gnt_list_entry->node);
- if (info->feature_persistent)
+ if (info->bounce)
__free_page(gnt_list_entry->page);
kfree(gnt_list_entry);
i--;
@@ -377,7 +382,7 @@ static struct grant *get_grant(grant_ref_t *gref_head,
/* Assign a gref to this page */
gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
BUG_ON(gnt_list_entry->gref == -ENOSPC);
- if (info->feature_persistent)
+ if (info->bounce)
grant_foreign_access(gnt_list_entry, info);
else {
/* Grant access to the GFN passed by the caller */
@@ -401,7 +406,7 @@ static struct grant *get_indirect_grant(grant_ref_t *gref_head,
/* Assign a gref to this page */
gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
BUG_ON(gnt_list_entry->gref == -ENOSPC);
- if (!info->feature_persistent) {
+ if (!info->bounce) {
struct page *indirect_page;
/* Fetch a pre-allocated page to use for indirect grefs */
@@ -703,7 +708,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
.grant_idx = 0,
.segments = NULL,
.rinfo = rinfo,
- .need_copy = rq_data_dir(req) && info->feature_persistent,
+ .need_copy = rq_data_dir(req) && info->bounce,
};
/*
@@ -981,11 +986,12 @@ static void xlvbd_flush(struct blkfront_info *info)
{
blk_queue_write_cache(info->rq, info->feature_flush ? true : false,
info->feature_fua ? true : false);
- pr_info("blkfront: %s: %s %s %s %s %s\n",
+ pr_info("blkfront: %s: %s %s %s %s %s %s %s\n",
info->gd->disk_name, flush_info(info),
"persistent grants:", info->feature_persistent ?
"enabled;" : "disabled;", "indirect descriptors:",
- info->max_indirect_segments ? "enabled;" : "disabled;");
+ info->max_indirect_segments ? "enabled;" : "disabled;",
+ "bounce buffer:", info->bounce ? "enabled" : "disabled;");
}
static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset)
@@ -1212,7 +1218,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
if (!list_empty(&rinfo->indirect_pages)) {
struct page *indirect_page, *n;
- BUG_ON(info->feature_persistent);
+ BUG_ON(info->bounce);
list_for_each_entry_safe(indirect_page, n, &rinfo->indirect_pages, lru) {
list_del(&indirect_page->lru);
__free_page(indirect_page);
@@ -1229,7 +1235,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
0, 0UL);
rinfo->persistent_gnts_c--;
}
- if (info->feature_persistent)
+ if (info->bounce)
__free_page(persistent_gnt->page);
kfree(persistent_gnt);
}
@@ -1250,7 +1256,7 @@ static void blkif_free_ring(struct blkfront_ring_info *rinfo)
for (j = 0; j < segs; j++) {
persistent_gnt = rinfo->shadow[i].grants_used[j];
gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
- if (info->feature_persistent)
+ if (info->bounce)
__free_page(persistent_gnt->page);
kfree(persistent_gnt);
}
@@ -1440,7 +1446,7 @@ static int blkif_completion(unsigned long *id,
data.s = s;
num_sg = s->num_sg;
- if (bret->operation == BLKIF_OP_READ && info->feature_persistent) {
+ if (bret->operation == BLKIF_OP_READ && info->bounce) {
for_each_sg(s->sg, sg, num_sg, i) {
BUG_ON(sg->offset + sg->length > PAGE_SIZE);
@@ -1499,7 +1505,7 @@ static int blkif_completion(unsigned long *id,
* Add the used indirect page back to the list of
* available pages for indirect grefs.
*/
- if (!info->feature_persistent) {
+ if (!info->bounce) {
indirect_page = s->indirect_grants[i]->page;
list_add(&indirect_page->lru, &rinfo->indirect_pages);
}
@@ -1692,7 +1698,7 @@ static int setup_blkring(struct xenbus_device *dev,
for (i = 0; i < info->nr_ring_pages; i++)
rinfo->ring_ref[i] = GRANT_INVALID_REF;
- sring = alloc_pages_exact(ring_size, GFP_NOIO);
+ sring = alloc_pages_exact(ring_size, GFP_NOIO | __GFP_ZERO);
if (!sring) {
xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
return -ENOMEM;
@@ -1790,6 +1796,10 @@ static int talk_to_blkback(struct xenbus_device *dev,
if (!info)
return -ENODEV;
+ /* Check if backend is trusted. */
+ info->bounce = !xen_blkif_trusted ||
+ !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
max_page_order = xenbus_read_unsigned(info->xbdev->otherend,
"max-ring-page-order", 0);
ring_page_order = min(xen_blkif_max_ring_order, max_page_order);
@@ -2199,17 +2209,18 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
if (err)
goto out_of_memory;
- if (!info->feature_persistent && info->max_indirect_segments) {
+ if (!info->bounce && info->max_indirect_segments) {
/*
- * We are using indirect descriptors but not persistent
- * grants, we need to allocate a set of pages that can be
+ * We are using indirect descriptors but don't have a bounce
+ * buffer, we need to allocate a set of pages that can be
* used for mapping indirect grefs
*/
int num = INDIRECT_GREFS(grants) * BLK_RING_SIZE(info);
BUG_ON(!list_empty(&rinfo->indirect_pages));
for (i = 0; i < num; i++) {
- struct page *indirect_page = alloc_page(GFP_KERNEL);
+ struct page *indirect_page = alloc_page(GFP_KERNEL |
+ __GFP_ZERO);
if (!indirect_page)
goto out_of_memory;
list_add(&indirect_page->lru, &rinfo->indirect_pages);
@@ -2302,6 +2313,8 @@ static void blkfront_gather_backend_features(struct blkfront_info *info)
info->feature_persistent =
!!xenbus_read_unsigned(info->xbdev->otherend,
"feature-persistent", 0);
+ if (info->feature_persistent)
+ info->bounce = true;
indirect_segments = xenbus_read_unsigned(info->xbdev->otherend,
"feature-max-indirect-segments", 0);
@@ -2565,6 +2578,13 @@ static void blkfront_delay_work(struct work_struct *work)
struct blkfront_info *info;
bool need_schedule_work = false;
+ /*
+ * Note that when using bounce buffers but not persistent grants
+ * there's no need to run blkfront_delay_work because grants are
+ * revoked in blkif_completion or else an error is reported and the
+ * connection is closed.
+ */
+
mutex_lock(&blkfront_mutex);
list_for_each_entry(info, &info_list, info_list) {
diff --git a/drivers/clocksource/timer-ixp4xx.c b/drivers/clocksource/timer-ixp4xx.c
index cbb184953510..b8e92991c471 100644
--- a/drivers/clocksource/timer-ixp4xx.c
+++ b/drivers/clocksource/timer-ixp4xx.c
@@ -282,7 +282,6 @@ void __init ixp4xx_timer_setup(resource_size_t timerbase,
}
ixp4xx_timer_register(base, timer_irq, timer_freq);
}
-EXPORT_SYMBOL_GPL(ixp4xx_timer_setup);
#ifdef CONFIG_OF
static __init int ixp4xx_of_timer_init(struct device_node *np)
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 6b6b20da2bcf..573b417e1483 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -275,6 +275,7 @@ static int qoriq_cpufreq_probe(struct platform_device *pdev)
np = of_find_matching_node(NULL, qoriq_cpufreq_blacklist);
if (np) {
+ of_node_put(np);
dev_info(&pdev->dev, "Disabling due to erratum A-008083");
return -ENODEV;
}
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index 17ed980d9099..d6da9c3e3106 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -514,15 +514,19 @@ static int of_get_devfreq_events(struct device_node *np,
count = of_get_child_count(events_np);
desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
- if (!desc)
+ if (!desc) {
+ of_node_put(events_np);
return -ENOMEM;
+ }
info->num_events = count;
of_id = of_match_device(exynos_ppmu_id_match, dev);
if (of_id)
info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
- else
+ else {
+ of_node_put(events_np);
return -EINVAL;
+ }
j = 0;
for_each_child_of_node(events_np, node) {
diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c
index b223f0ef337b..ecf738411fe2 100644
--- a/drivers/fsi/fsi-occ.c
+++ b/drivers/fsi/fsi-occ.c
@@ -50,6 +50,7 @@ struct occ {
struct device *sbefifo;
char name[32];
int idx;
+ u8 sequence_number;
enum versions version;
struct miscdevice mdev;
struct mutex occ_lock;
@@ -141,8 +142,7 @@ static ssize_t occ_write(struct file *file, const char __user *buf,
{
struct occ_client *client = file->private_data;
size_t rlen, data_length;
- u16 checksum = 0;
- ssize_t rc, i;
+ ssize_t rc;
u8 *cmd;
if (!client)
@@ -156,9 +156,6 @@ static ssize_t occ_write(struct file *file, const char __user *buf,
/* Construct the command */
cmd = client->buffer;
- /* Sequence number (we could increment and compare with response) */
- cmd[0] = 1;
-
/*
* Copy the user command (assume user data follows the occ command
* format)
@@ -178,14 +175,7 @@ static ssize_t occ_write(struct file *file, const char __user *buf,
goto done;
}
- /* Calculate checksum */
- for (i = 0; i < data_length + 4; ++i)
- checksum += cmd[i];
-
- cmd[data_length + 4] = checksum >> 8;
- cmd[data_length + 5] = checksum & 0xFF;
-
- /* Submit command */
+ /* Submit command; 4 bytes before the data and 2 bytes after */
rlen = PAGE_SIZE;
rc = fsi_occ_submit(client->occ->dev, cmd, data_length + 6, cmd,
&rlen);
@@ -314,11 +304,13 @@ static int occ_getsram(struct occ *occ, u32 offset, void *data, ssize_t len)
return rc;
}
-static int occ_putsram(struct occ *occ, const void *data, ssize_t len)
+static int occ_putsram(struct occ *occ, const void *data, ssize_t len,
+ u8 seq_no, u16 checksum)
{
size_t cmd_len, buf_len, resp_len, resp_data_len;
u32 data_len = ((len + 7) / 8) * 8; /* must be multiples of 8 B */
__be32 *buf;
+ u8 *byte_buf;
int idx = 0, rc;
cmd_len = (occ->version == occ_p10) ? 6 : 5;
@@ -358,6 +350,15 @@ static int occ_putsram(struct occ *occ, const void *data, ssize_t len)
buf[4 + idx] = cpu_to_be32(data_len);
memcpy(&buf[5 + idx], data, len);
+ byte_buf = (u8 *)&buf[5 + idx];
+ /*
+ * Overwrite the first byte with our sequence number and the last two
+ * bytes with the checksum.
+ */
+ byte_buf[0] = seq_no;
+ byte_buf[len - 2] = checksum >> 8;
+ byte_buf[len - 1] = checksum & 0xff;
+
rc = sbefifo_submit(occ->sbefifo, buf, cmd_len, buf, &resp_len);
if (rc)
goto free;
@@ -467,9 +468,12 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
struct occ *occ = dev_get_drvdata(dev);
struct occ_response *resp = response;
u8 seq_no;
+ u16 checksum = 0;
u16 resp_data_length;
+ const u8 *byte_request = (const u8 *)request;
unsigned long start;
int rc;
+ size_t i;
if (!occ)
return -ENODEV;
@@ -479,11 +483,26 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
return -EINVAL;
}
+ /* Checksum the request, ignoring first byte (sequence number). */
+ for (i = 1; i < req_len - 2; ++i)
+ checksum += byte_request[i];
+
mutex_lock(&occ->occ_lock);
- /* Extract the seq_no from the command (first byte) */
- seq_no = *(const u8 *)request;
- rc = occ_putsram(occ, request, req_len);
+ /*
+ * Get a sequence number and update the counter. Avoid a sequence
+ * number of 0 which would pass the response check below even if the
+ * OCC response is uninitialized. Any sequence number the user is
+ * trying to send is overwritten since this function is the only common
+ * interface to the OCC and therefore the only place we can guarantee
+ * unique sequence numbers.
+ */
+ seq_no = occ->sequence_number++;
+ if (!occ->sequence_number)
+ occ->sequence_number = 1;
+ checksum += seq_no;
+
+ rc = occ_putsram(occ, request, req_len, seq_no, checksum);
if (rc)
goto done;
@@ -574,6 +593,7 @@ static int occ_probe(struct platform_device *pdev)
occ->version = (uintptr_t)of_device_get_match_data(dev);
occ->dev = dev;
occ->sbefifo = dev->parent;
+ occ->sequence_number = 1;
mutex_init(&occ->occ_lock);
if (dev->of_node) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 1d41c2c00623..5690cb6d27fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -768,7 +768,8 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid,
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
bool all_hub = false;
- if (adev->family == AMDGPU_FAMILY_AI)
+ if (adev->family == AMDGPU_FAMILY_AI ||
+ adev->family == AMDGPU_FAMILY_RV)
all_hub = true;
return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index 4f3c62adccbd..cc2e0c9cfe0a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -333,6 +333,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
if (!amdgpu_device_has_dc_support(adev)) {
if (!adev->enable_virtual_display)
/* Disable vblank IRQs aggressively for power-saving */
+ /* XXX: can this be enabled for DC? */
adev_to_drm(adev)->vblank_disable_immediate = true;
r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d2aecf7bf66b..d35a6f6d158e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3838,9 +3838,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
}
#endif
- /* Disable vblank IRQs aggressively for power-saving. */
- adev_to_drm(adev)->vblank_disable_immediate = true;
-
/* loops over all connectors on the board */
for (i = 0; i < link_cnt; i++) {
struct dc_link *link = NULL;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 166bb46408a9..ee0c0b712522 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -720,8 +720,9 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv,
case I915_CONTEXT_PARAM_PERSISTENCE:
if (args->size)
ret = -EINVAL;
- ret = proto_context_set_persistence(fpriv->dev_priv, pc,
- args->value);
+ else
+ ret = proto_context_set_persistence(fpriv->dev_priv, pc,
+ args->value);
break;
case I915_CONTEXT_PARAM_NO_ZEROMAP:
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 7fb7ff043bcd..1f74bab9e231 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -889,7 +889,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
submit->fence_id = idr_alloc_cyclic(&queue->fence_idr,
submit->user_fence, 1, INT_MAX, GFP_KERNEL);
if (submit->fence_id < 0) {
- ret = submit->fence_id = 0;
+ ret = submit->fence_id;
submit->fence_id = 0;
goto out;
}
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index a4ec85207782..2e6d6a5cffa1 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -550,7 +550,7 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
res = platform_device_add(data->pdev);
if (res)
- goto ipmi_err;
+ goto dev_add_err;
platform_set_drvdata(data->pdev, data);
@@ -598,7 +598,9 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
ipmi_destroy_user(data->ipmi.user);
ipmi_err:
platform_set_drvdata(data->pdev, NULL);
- platform_device_unregister(data->pdev);
+ platform_device_del(data->pdev);
+dev_add_err:
+ platform_device_put(data->pdev);
dev_err:
ida_simple_remove(&aem_ida, data->id);
id_err:
@@ -690,7 +692,7 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
res = platform_device_add(data->pdev);
if (res)
- goto ipmi_err;
+ goto dev_add_err;
platform_set_drvdata(data->pdev, data);
@@ -738,7 +740,9 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
ipmi_destroy_user(data->ipmi.user);
ipmi_err:
platform_set_drvdata(data->pdev, NULL);
- platform_device_unregister(data->pdev);
+ platform_device_del(data->pdev);
+dev_add_err:
+ platform_device_put(data->pdev);
dev_err:
ida_simple_remove(&aem_ida, data->id);
id_err:
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index ae664613289c..bbe5e4ef4113 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -132,22 +132,20 @@ struct extended_sensor {
static int occ_poll(struct occ *occ)
{
int rc;
- u16 checksum = occ->poll_cmd_data + occ->seq_no + 1;
- u8 cmd[8];
+ u8 cmd[7];
struct occ_poll_response_header *header;
/* big endian */
- cmd[0] = occ->seq_no++; /* sequence number */
+ cmd[0] = 0; /* sequence number */
cmd[1] = 0; /* cmd type */
cmd[2] = 0; /* data length msb */
cmd[3] = 1; /* data length lsb */
cmd[4] = occ->poll_cmd_data; /* data */
- cmd[5] = checksum >> 8; /* checksum msb */
- cmd[6] = checksum & 0xFF; /* checksum lsb */
- cmd[7] = 0;
+ cmd[5] = 0; /* checksum msb */
+ cmd[6] = 0; /* checksum lsb */
/* mutex should already be locked if necessary */
- rc = occ->send_cmd(occ, cmd);
+ rc = occ->send_cmd(occ, cmd, sizeof(cmd), &occ->resp, sizeof(occ->resp));
if (rc) {
occ->last_error = rc;
if (occ->error_count++ > OCC_ERROR_COUNT_THRESHOLD)
@@ -184,25 +182,24 @@ static int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
{
int rc;
u8 cmd[8];
- u16 checksum = 0x24;
+ u8 resp[8];
__be16 user_power_cap_be = cpu_to_be16(user_power_cap);
- cmd[0] = 0;
- cmd[1] = 0x22;
- cmd[2] = 0;
- cmd[3] = 2;
+ cmd[0] = 0; /* sequence number */
+ cmd[1] = 0x22; /* cmd type */
+ cmd[2] = 0; /* data length msb */
+ cmd[3] = 2; /* data length lsb */
memcpy(&cmd[4], &user_power_cap_be, 2);
- checksum += cmd[4] + cmd[5];
- cmd[6] = checksum >> 8;
- cmd[7] = checksum & 0xFF;
+ cmd[6] = 0; /* checksum msb */
+ cmd[7] = 0; /* checksum lsb */
rc = mutex_lock_interruptible(&occ->lock);
if (rc)
return rc;
- rc = occ->send_cmd(occ, cmd);
+ rc = occ->send_cmd(occ, cmd, sizeof(cmd), resp, sizeof(resp));
mutex_unlock(&occ->lock);
@@ -1144,8 +1141,6 @@ int occ_setup(struct occ *occ, const char *name)
{
int rc;
- /* start with 1 to avoid false match with zero-initialized SRAM buffer */
- occ->seq_no = 1;
mutex_init(&occ->lock);
occ->groups[0] = &occ->group;
diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h
index e6df719770e8..7abf19102062 100644
--- a/drivers/hwmon/occ/common.h
+++ b/drivers/hwmon/occ/common.h
@@ -95,9 +95,9 @@ struct occ {
struct occ_sensors sensors;
int powr_sample_time_us; /* average power sample time */
- u8 seq_no;
u8 poll_cmd_data; /* to perform OCC poll command */
- int (*send_cmd)(struct occ *occ, u8 *cmd);
+ int (*send_cmd)(struct occ *occ, u8 *cmd, size_t len, void *resp,
+ size_t resp_len);
unsigned long next_update;
struct mutex lock; /* lock OCC access */
diff --git a/drivers/hwmon/occ/p8_i2c.c b/drivers/hwmon/occ/p8_i2c.c
index 0cf8588be35a..c35c07964d85 100644
--- a/drivers/hwmon/occ/p8_i2c.c
+++ b/drivers/hwmon/occ/p8_i2c.c
@@ -97,18 +97,22 @@ static int p8_i2c_occ_putscom_u32(struct i2c_client *client, u32 address,
}
static int p8_i2c_occ_putscom_be(struct i2c_client *client, u32 address,
- u8 *data)
+ u8 *data, size_t len)
{
- __be32 data0, data1;
+ __be32 data0 = 0, data1 = 0;
- memcpy(&data0, data, 4);
- memcpy(&data1, data + 4, 4);
+ memcpy(&data0, data, min_t(size_t, len, 4));
+ if (len > 4) {
+ len -= 4;
+ memcpy(&data1, data + 4, min_t(size_t, len, 4));
+ }
return p8_i2c_occ_putscom_u32(client, address, be32_to_cpu(data0),
be32_to_cpu(data1));
}
-static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd)
+static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
+ void *resp, size_t resp_len)
{
int i, rc;
unsigned long start;
@@ -117,7 +121,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd)
const long wait_time = msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS);
struct p8_i2c_occ *ctx = to_p8_i2c_occ(occ);
struct i2c_client *client = ctx->client;
- struct occ_response *resp = &occ->resp;
+ struct occ_response *or = (struct occ_response *)resp;
start = jiffies;
@@ -127,7 +131,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd)
return rc;
/* write command (expected to already be BE), we need bus-endian... */
- rc = p8_i2c_occ_putscom_be(client, OCB_DATA3, cmd);
+ rc = p8_i2c_occ_putscom_be(client, OCB_DATA3, cmd, len);
if (rc)
return rc;
@@ -148,7 +152,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd)
return rc;
/* wait for OCC */
- if (resp->return_status == OCC_RESP_CMD_IN_PRG) {
+ if (or->return_status == OCC_RESP_CMD_IN_PRG) {
rc = -EALREADY;
if (time_after(jiffies, start + timeout))
@@ -160,7 +164,7 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd)
} while (rc);
/* check the OCC response */
- switch (resp->return_status) {
+ switch (or->return_status) {
case OCC_RESP_CMD_IN_PRG:
rc = -ETIMEDOUT;
break;
@@ -189,8 +193,8 @@ static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd)
if (rc < 0)
return rc;
- data_length = get_unaligned_be16(&resp->data_length);
- if (data_length > OCC_RESP_DATA_BYTES)
+ data_length = get_unaligned_be16(&or->data_length);
+ if ((data_length + 7) > resp_len)
return -EMSGSIZE;
/* fetch the rest of the response data */
diff --git a/drivers/hwmon/occ/p9_sbe.c b/drivers/hwmon/occ/p9_sbe.c
index f6387cc0b754..14923e78e1f3 100644
--- a/drivers/hwmon/occ/p9_sbe.c
+++ b/drivers/hwmon/occ/p9_sbe.c
@@ -16,18 +16,17 @@ struct p9_sbe_occ {
#define to_p9_sbe_occ(x) container_of((x), struct p9_sbe_occ, occ)
-static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd)
+static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len,
+ void *resp, size_t resp_len)
{
- struct occ_response *resp = &occ->resp;
struct p9_sbe_occ *ctx = to_p9_sbe_occ(occ);
- size_t resp_len = sizeof(*resp);
int rc;
- rc = fsi_occ_submit(ctx->sbe, cmd, 8, resp, &resp_len);
+ rc = fsi_occ_submit(ctx->sbe, cmd, len, resp, &resp_len);
if (rc < 0)
return rc;
- switch (resp->return_status) {
+ switch (((struct occ_response *)resp)->return_status) {
case OCC_RESP_CMD_IN_PRG:
rc = -ETIMEDOUT;
break;
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 1c107d6d03b9..b985e0d9bc05 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -1252,8 +1252,10 @@ struct ib_cm_id *ib_cm_insert_listen(struct ib_device *device,
return ERR_CAST(cm_id_priv);
err = cm_init_listen(cm_id_priv, service_id, 0);
- if (err)
+ if (err) {
+ ib_destroy_cm_id(&cm_id_priv->id);
return ERR_PTR(err);
+ }
spin_lock_irq(&cm_id_priv->lock);
listen_id_priv = cm_insert_listen(cm_id_priv, cm_handler);
diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h
index 8def88cfa300..db9ef3e1eb97 100644
--- a/drivers/infiniband/hw/qedr/qedr.h
+++ b/drivers/infiniband/hw/qedr/qedr.h
@@ -418,6 +418,7 @@ struct qedr_qp {
u32 sq_psn;
u32 qkey;
u32 dest_qp_num;
+ u8 timeout;
/* Relevant to qps created from kernel space only (ULPs) */
u8 prev_wqe_size;
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index f652d083ff20..49dfedbc5665 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -2622,6 +2622,8 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
1 << max_t(int, attr->timeout - 8, 0);
else
qp_params.ack_timeout = 0;
+
+ qp->timeout = attr->timeout;
}
if (attr_mask & IB_QP_RETRY_CNT) {
@@ -2781,7 +2783,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
rdma_ah_set_dgid_raw(&qp_attr->ah_attr, ¶ms.dgid.bytes[0]);
rdma_ah_set_port_num(&qp_attr->ah_attr, 1);
rdma_ah_set_sl(&qp_attr->ah_attr, 0);
- qp_attr->timeout = params.timeout;
+ qp_attr->timeout = qp->timeout;
qp_attr->rnr_retry = params.rnr_retry;
qp_attr->retry_cnt = params.retry_cnt;
qp_attr->min_rnr_timer = params.min_rnr_nak_timer;
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index d9ef52159a22..b0566aabc186 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1001,12 +1001,13 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
static int validate_raid_redundancy(struct raid_set *rs)
{
unsigned int i, rebuild_cnt = 0;
- unsigned int rebuilds_per_group = 0, copies;
+ unsigned int rebuilds_per_group = 0, copies, raid_disks;
unsigned int group_size, last_group_start;
- for (i = 0; i < rs->md.raid_disks; i++)
- if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
- !rs->dev[i].rdev.sb_page)
+ for (i = 0; i < rs->raid_disks; i++)
+ if (!test_bit(FirstUse, &rs->dev[i].rdev.flags) &&
+ ((!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
+ !rs->dev[i].rdev.sb_page)))
rebuild_cnt++;
switch (rs->md.level) {
@@ -1046,8 +1047,9 @@ static int validate_raid_redundancy(struct raid_set *rs)
* A A B B C
* C D D E E
*/
+ raid_disks = min(rs->raid_disks, rs->md.raid_disks);
if (__is_raid10_near(rs->md.new_layout)) {
- for (i = 0; i < rs->md.raid_disks; i++) {
+ for (i = 0; i < raid_disks; i++) {
if (!(i % copies))
rebuilds_per_group = 0;
if ((!rs->dev[i].rdev.sb_page ||
@@ -1070,10 +1072,10 @@ static int validate_raid_redundancy(struct raid_set *rs)
* results in the need to treat the last (potentially larger)
* set differently.
*/
- group_size = (rs->md.raid_disks / copies);
- last_group_start = (rs->md.raid_disks / group_size) - 1;
+ group_size = (raid_disks / copies);
+ last_group_start = (raid_disks / group_size) - 1;
last_group_start *= group_size;
- for (i = 0; i < rs->md.raid_disks; i++) {
+ for (i = 0; i < raid_disks; i++) {
if (!(i % copies) && !(i > last_group_start))
rebuilds_per_group = 0;
if ((!rs->dev[i].rdev.sb_page ||
@@ -1588,7 +1590,7 @@ static sector_t __rdev_sectors(struct raid_set *rs)
{
int i;
- for (i = 0; i < rs->md.raid_disks; i++) {
+ for (i = 0; i < rs->raid_disks; i++) {
struct md_rdev *rdev = &rs->dev[i].rdev;
if (!test_bit(Journal, &rdev->flags) &&
@@ -3771,13 +3773,13 @@ static int raid_iterate_devices(struct dm_target *ti,
unsigned int i;
int r = 0;
- for (i = 0; !r && i < rs->md.raid_disks; i++)
- if (rs->dev[i].data_dev)
- r = fn(ti,
- rs->dev[i].data_dev,
- 0, /* No offset on data devs */
- rs->md.dev_sectors,
- data);
+ for (i = 0; !r && i < rs->raid_disks; i++) {
+ if (rs->dev[i].data_dev) {
+ r = fn(ti, rs->dev[i].data_dev,
+ 0, /* No offset on data devs */
+ rs->md.dev_sectors, data);
+ }
+ }
return r;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e54d802ee0bb..b58984ddca13 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -8026,6 +8026,7 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev)
*/
if (rdev->saved_raid_disk >= 0 &&
rdev->saved_raid_disk >= first &&
+ rdev->saved_raid_disk <= last &&
conf->disks[rdev->saved_raid_disk].rdev == NULL)
first = rdev->saved_raid_disk;
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index a86b1f71762e..d7fb33c078e8 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2228,7 +2228,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
temp_aggregator->num_of_ports--;
if (__agg_active_ports(temp_aggregator) == 0) {
select_new_active_agg = temp_aggregator->is_active;
- ad_clear_agg(temp_aggregator);
+ if (temp_aggregator->num_of_ports == 0)
+ ad_clear_agg(temp_aggregator);
if (select_new_active_agg) {
slave_info(bond->dev, slave->dev, "Removing an active aggregator\n");
/* select new active aggregator */
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index bca36be884b8..a6a70b872ac4 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1281,12 +1281,12 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
return res;
if (rlb_enabled) {
- bond->alb_info.rlb_enabled = 1;
res = rlb_initialize(bond);
if (res) {
tlb_deinitialize(bond);
return res;
}
+ bond->alb_info.rlb_enabled = 1;
} else {
bond->alb_info.rlb_enabled = 0;
}
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
index 91230894692d..da87de02b2fc 100644
--- a/drivers/net/caif/caif_virtio.c
+++ b/drivers/net/caif/caif_virtio.c
@@ -721,13 +721,21 @@ static int cfv_probe(struct virtio_device *vdev)
/* Carrier is off until netdevice is opened */
netif_carrier_off(netdev);
+ /* serialize netdev register + virtio_device_ready() with ndo_open() */
+ rtnl_lock();
+
/* register Netdev */
- err = register_netdev(netdev);
+ err = register_netdevice(netdev);
if (err) {
+ rtnl_unlock();
dev_err(&vdev->dev, "Unable to register netdev (%d)\n", err);
goto err;
}
+ virtio_device_ready(vdev);
+
+ rtnl_unlock();
+
debugfs_init(cfv);
return 0;
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index b3a43a3d90e4..d76b2377d66e 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -865,6 +865,11 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port,
if (duplex == DUPLEX_FULL)
reg |= DUPLX_MODE;
+ if (tx_pause)
+ reg |= TXFLOW_CNTL;
+ if (rx_pause)
+ reg |= RXFLOW_CNTL;
+
core_writel(priv, reg, offset);
}
diff --git a/drivers/net/dsa/hirschmann/hellcreek_ptp.c b/drivers/net/dsa/hirschmann/hellcreek_ptp.c
index 2572c6087bb5..b28baab6d56a 100644
--- a/drivers/net/dsa/hirschmann/hellcreek_ptp.c
+++ b/drivers/net/dsa/hirschmann/hellcreek_ptp.c
@@ -300,6 +300,7 @@ static int hellcreek_led_setup(struct hellcreek *hellcreek)
const char *label, *state;
int ret = -EINVAL;
+ of_node_get(hellcreek->dev->of_node);
leds = of_find_node_by_name(hellcreek->dev->of_node, "leds");
if (!leds) {
dev_err(hellcreek->dev, "No LEDs specified in device tree!\n");
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 19bb3ca0515e..d7d90cdce4f6 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -4293,6 +4293,8 @@ static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
return 0;
err_nexthop_neigh_init:
+ list_del(&nh->router_list_node);
+ mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
return err;
}
@@ -6578,6 +6580,7 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
const struct fib6_info *rt)
{
struct net_device *dev = rt->fib6_nh->fib_nh_dev;
+ int err;
nh->nhgi = nh_grp->nhgi;
nh->nh_weight = rt->fib6_nh->fib_nh_weight;
@@ -6593,7 +6596,16 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
return 0;
nh->ifindex = dev->ifindex;
- return mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
+ err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
+ if (err)
+ goto err_nexthop_type_init;
+
+ return 0;
+
+err_nexthop_type_init:
+ list_del(&nh->router_list_node);
+ mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
+ return err;
}
static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
index 44daf79a8f97..f3b1af9a59e8 100644
--- a/drivers/net/ethernet/smsc/epic100.c
+++ b/drivers/net/ethernet/smsc/epic100.c
@@ -1513,14 +1513,14 @@ static void epic_remove_one(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct epic_private *ep = netdev_priv(dev);
+ unregister_netdev(dev);
dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, ep->tx_ring,
ep->tx_ring_dma);
dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, ep->rx_ring,
ep->rx_ring_dma);
- unregister_netdev(dev);
pci_iounmap(pdev, ep->ioaddr);
- pci_release_regions(pdev);
free_netdev(dev);
+ pci_release_regions(pdev);
pci_disable_device(pdev);
/* pci_power_off(pdev, -1); */
}
diff --git a/drivers/net/phy/ax88796b.c b/drivers/net/phy/ax88796b.c
index 457896337505..0f1e617a26c9 100644
--- a/drivers/net/phy/ax88796b.c
+++ b/drivers/net/phy/ax88796b.c
@@ -88,8 +88,10 @@ static void asix_ax88772a_link_change_notify(struct phy_device *phydev)
/* Reset PHY, otherwise MII_LPA will provide outdated information.
* This issue is reproducible only with some link partner PHYs
*/
- if (phydev->state == PHY_NOLINK && phydev->drv->soft_reset)
- phydev->drv->soft_reset(phydev);
+ if (phydev->state == PHY_NOLINK) {
+ phy_init_hw(phydev);
+ phy_start_aneg(phydev);
+ }
}
static struct phy_driver asix_driver[] = {
diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c
index ce17b2af3218..a792dd6d2ec3 100644
--- a/drivers/net/phy/dp83822.c
+++ b/drivers/net/phy/dp83822.c
@@ -228,9 +228,7 @@ static int dp83822_config_intr(struct phy_device *phydev)
if (misr_status < 0)
return misr_status;
- misr_status |= (DP83822_RX_ERR_HF_INT_EN |
- DP83822_FALSE_CARRIER_HF_INT_EN |
- DP83822_LINK_STAT_INT_EN |
+ misr_status |= (DP83822_LINK_STAT_INT_EN |
DP83822_ENERGY_DET_INT_EN |
DP83822_LINK_QUAL_INT_EN);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index f122026c4682..2fc851082e7b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -972,6 +973,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 28f4a383aba7..0d3f8fe8e42c 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -277,6 +277,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -314,6 +323,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 02de8d998bfa..ea60453fe69a 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -274,6 +274,12 @@ static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile,
}
}
+static void tun_napi_enable(struct tun_file *tfile)
+{
+ if (tfile->napi_enabled)
+ napi_enable(&tfile->napi);
+}
+
static void tun_napi_disable(struct tun_file *tfile)
{
if (tfile->napi_enabled)
@@ -635,7 +641,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
tun = rtnl_dereference(tfile->tun);
if (tun && clean) {
- tun_napi_disable(tfile);
+ if (!tfile->detached)
+ tun_napi_disable(tfile);
tun_napi_del(tfile);
}
@@ -654,8 +661,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
if (clean) {
RCU_INIT_POINTER(tfile->tun, NULL);
sock_put(&tfile->sk);
- } else
+ } else {
tun_disable_queue(tun, tfile);
+ tun_napi_disable(tfile);
+ }
synchronize_net();
tun_flow_delete_by_queue(tun, tun->numqueues + 1);
@@ -728,6 +737,7 @@ static void tun_detach_all(struct net_device *dev)
sock_put(&tfile->sk);
}
list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) {
+ tun_napi_del(tfile);
tun_enable_queue(tfile);
tun_queue_purge(tfile);
xdp_rxq_info_unreg(&tfile->xdp_rxq);
@@ -808,6 +818,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
if (tfile->detached) {
tun_enable_queue(tfile);
+ tun_napi_enable(tfile);
} else {
sock_hold(&tfile->sk);
tun_napi_init(tun, tfile, napi, napi_frags);
diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
index 4334aafab59a..c126df1c13ee 100644
--- a/drivers/net/usb/asix.h
+++ b/drivers/net/usb/asix.h
@@ -126,8 +126,7 @@
AX_MEDIUM_RE)
#define AX88772_MEDIUM_DEFAULT \
- (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
- AX_MEDIUM_TFC | AX_MEDIUM_PS | \
+ (AX_MEDIUM_FD | AX_MEDIUM_PS | \
AX_MEDIUM_AC | AX_MEDIUM_RE)
/* AX88772 & AX88178 RX_CTL values */
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index f39188b7717a..00c23f1d1c94 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -431,6 +431,7 @@ void asix_adjust_link(struct net_device *netdev)
asix_write_medium_mode(dev, mode, 0);
phy_print_status(phydev);
+ usbnet_link_change(dev, phydev->link, 0);
}
int asix_write_gpio(struct usbnet *dev, u16 value, int sleep, int in_pm)
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index d5ce642200e8..0a2c3860179e 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1471,6 +1471,42 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
* are bundled into this buffer and where we can find an array of
* per-packet metadata (which contains elements encoded into u16).
*/
+
+ /* SKB contents for current firmware:
+ * <packet 1> <padding>
+ * ...
+ * <packet N> <padding>
+ * <per-packet metadata entry 1> <dummy header>
+ * ...
+ * <per-packet metadata entry N> <dummy header>
+ * <padding2> <rx_hdr>
+ *
+ * where:
+ * <packet N> contains pkt_len bytes:
+ * 2 bytes of IP alignment pseudo header
+ * packet received
+ * <per-packet metadata entry N> contains 4 bytes:
+ * pkt_len and fields AX_RXHDR_*
+ * <padding> 0-7 bytes to terminate at
+ * 8 bytes boundary (64-bit).
+ * <padding2> 4 bytes to make rx_hdr terminate at
+ * 8 bytes boundary (64-bit)
+ * <dummy-header> contains 4 bytes:
+ * pkt_len=0 and AX_RXHDR_DROP_ERR
+ * <rx-hdr> contains 4 bytes:
+ * pkt_cnt and hdr_off (offset of
+ * <per-packet metadata entry 1>)
+ *
+ * pkt_cnt is number of entrys in the per-packet metadata.
+ * In current firmware there is 2 entrys per packet.
+ * The first points to the packet and the
+ * second is a dummy header.
+ * This was done probably to align fields in 64-bit and
+ * maintain compatibility with old firmware.
+ * This code assumes that <dummy header> and <padding2> are
+ * optional.
+ */
+
if (skb->len < 4)
return 0;
skb_trim(skb, skb->len - 4);
@@ -1484,51 +1520,66 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
/* Make sure that the bounds of the metadata array are inside the SKB
* (and in front of the counter at the end).
*/
- if (pkt_cnt * 2 + hdr_off > skb->len)
+ if (pkt_cnt * 4 + hdr_off > skb->len)
return 0;
pkt_hdr = (u32 *)(skb->data + hdr_off);
/* Packets must not overlap the metadata array */
skb_trim(skb, hdr_off);
- for (; ; pkt_cnt--, pkt_hdr++) {
+ for (; pkt_cnt > 0; pkt_cnt--, pkt_hdr++) {
+ u16 pkt_len_plus_padd;
u16 pkt_len;
le32_to_cpus(pkt_hdr);
pkt_len = (*pkt_hdr >> 16) & 0x1fff;
+ pkt_len_plus_padd = (pkt_len + 7) & 0xfff8;
- if (pkt_len > skb->len)
+ /* Skip dummy header used for alignment
+ */
+ if (pkt_len == 0)
+ continue;
+
+ if (pkt_len_plus_padd > skb->len)
return 0;
/* Check CRC or runt packet */
- if (((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) == 0) &&
- pkt_len >= 2 + ETH_HLEN) {
- bool last = (pkt_cnt == 0);
-
- if (last) {
- ax_skb = skb;
- } else {
- ax_skb = skb_clone(skb, GFP_ATOMIC);
- if (!ax_skb)
- return 0;
- }
- ax_skb->len = pkt_len;
- /* Skip IP alignment pseudo header */
- skb_pull(ax_skb, 2);
- skb_set_tail_pointer(ax_skb, ax_skb->len);
- ax_skb->truesize = pkt_len + sizeof(struct sk_buff);
- ax88179_rx_checksum(ax_skb, pkt_hdr);
+ if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) ||
+ pkt_len < 2 + ETH_HLEN) {
+ dev->net->stats.rx_errors++;
+ skb_pull(skb, pkt_len_plus_padd);
+ continue;
+ }
- if (last)
- return 1;
+ /* last packet */
+ if (pkt_len_plus_padd == skb->len) {
+ skb_trim(skb, pkt_len);
- usbnet_skb_return(dev, ax_skb);
+ /* Skip IP alignment pseudo header */
+ skb_pull(skb, 2);
+
+ skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd);
+ ax88179_rx_checksum(skb, pkt_hdr);
+ return 1;
}
- /* Trim this packet away from the SKB */
- if (!skb_pull(skb, (pkt_len + 7) & 0xFFF8))
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
+ if (!ax_skb)
return 0;
+ skb_trim(ax_skb, pkt_len);
+
+ /* Skip IP alignment pseudo header */
+ skb_pull(ax_skb, 2);
+
+ skb->truesize = pkt_len_plus_padd +
+ SKB_DATA_ALIGN(sizeof(struct sk_buff));
+ ax88179_rx_checksum(ax_skb, pkt_hdr);
+ usbnet_skb_return(dev, ax_skb);
+
+ skb_pull(skb, pkt_len_plus_padd);
}
+
+ return 0;
}
static struct sk_buff *
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 0c7f02ca6822..3e1aab1e894e 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1355,6 +1355,7 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1050, 2)}, /* Telit FN980 */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990 */
{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */
{QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */
{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index af2bbaff2478..a0ea236ac60e 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -2002,7 +2002,7 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
cmd, reqtype, value, index, size);
if (size) {
- buf = kmalloc(size, GFP_KERNEL);
+ buf = kmalloc(size, GFP_NOIO);
if (!buf)
goto out;
}
@@ -2034,7 +2034,7 @@ static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
cmd, reqtype, value, index, size);
if (data) {
- buf = kmemdup(data, size, GFP_KERNEL);
+ buf = kmemdup(data, size, GFP_NOIO);
if (!buf)
goto out;
} else {
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 468d0ffc266b..318c681ad63e 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3241,14 +3241,20 @@ static int virtnet_probe(struct virtio_device *vdev)
}
}
- err = register_netdev(dev);
+ /* serialize netdev register + virtio_device_ready() with ndo_open() */
+ rtnl_lock();
+
+ err = register_netdevice(dev);
if (err) {
pr_debug("virtio_net: registering device failed\n");
+ rtnl_unlock();
goto free_failover;
}
virtio_device_ready(vdev);
+ rtnl_unlock();
+
err = virtnet_cpu_notif_add(vi);
if (err) {
pr_debug("virtio_net: registering cpu notifier failed\n");
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 2492a27467b4..074dceb1930b 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -66,6 +66,10 @@ module_param_named(max_queues, xennet_max_queues, uint, 0644);
MODULE_PARM_DESC(max_queues,
"Maximum number of queues per virtual interface");
+static bool __read_mostly xennet_trusted = true;
+module_param_named(trusted, xennet_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
#define XENNET_TIMEOUT (5 * HZ)
static const struct ethtool_ops xennet_ethtool_ops;
@@ -175,6 +179,9 @@ struct netfront_info {
/* Is device behaving sane? */
bool broken;
+ /* Should skbs be bounced into a zeroed buffer? */
+ bool bounce;
+
atomic_t rx_gso_checksum_fixup;
};
@@ -273,7 +280,8 @@ static struct sk_buff *xennet_alloc_one_rx_buffer(struct netfront_queue *queue)
if (unlikely(!skb))
return NULL;
- page = page_pool_dev_alloc_pages(queue->page_pool);
+ page = page_pool_alloc_pages(queue->page_pool,
+ GFP_ATOMIC | __GFP_NOWARN | __GFP_ZERO);
if (unlikely(!page)) {
kfree_skb(skb);
return NULL;
@@ -667,6 +675,33 @@ static int xennet_xdp_xmit(struct net_device *dev, int n,
return nxmit;
}
+struct sk_buff *bounce_skb(const struct sk_buff *skb)
+{
+ unsigned int headerlen = skb_headroom(skb);
+ /* Align size to allocate full pages and avoid contiguous data leaks */
+ unsigned int size = ALIGN(skb_end_offset(skb) + skb->data_len,
+ XEN_PAGE_SIZE);
+ struct sk_buff *n = alloc_skb(size, GFP_ATOMIC | __GFP_ZERO);
+
+ if (!n)
+ return NULL;
+
+ if (!IS_ALIGNED((uintptr_t)n->head, XEN_PAGE_SIZE)) {
+ WARN_ONCE(1, "misaligned skb allocated\n");
+ kfree_skb(n);
+ return NULL;
+ }
+
+ /* Set the data pointer */
+ skb_reserve(n, headerlen);
+ /* Set the tail pointer and length */
+ skb_put(n, skb->len);
+
+ BUG_ON(skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len));
+
+ skb_copy_header(n, skb);
+ return n;
+}
#define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)
@@ -720,9 +755,13 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
/* The first req should be at least ETH_HLEN size or the packet will be
* dropped by netback.
+ *
+ * If the backend is not trusted bounce all data to zeroed pages to
+ * avoid exposing contiguous data on the granted page not belonging to
+ * the skb.
*/
- if (unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
- nskb = skb_copy(skb, GFP_ATOMIC);
+ if (np->bounce || unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
+ nskb = bounce_skb(skb);
if (!nskb)
goto drop;
dev_consume_skb_any(skb);
@@ -1055,8 +1094,10 @@ static int xennet_get_responses(struct netfront_queue *queue,
}
}
rcu_read_unlock();
-next:
+
__skb_queue_tail(list, skb);
+
+next:
if (!(rx->flags & XEN_NETRXF_more_data))
break;
@@ -2246,6 +2287,10 @@ static int talk_to_netback(struct xenbus_device *dev,
info->netdev->irq = 0;
+ /* Check if backend is trusted. */
+ info->bounce = !xennet_trusted ||
+ !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
/* Check if backend supports multiple queues */
max_queues = xenbus_read_unsigned(info->xbdev->otherend,
"multi-queue-max-queues", 1);
@@ -2412,6 +2457,9 @@ static int xennet_connect(struct net_device *dev)
return err;
if (np->netback_has_xdp_headroom)
pr_info("backend supports XDP headroom\n");
+ if (np->bounce)
+ dev_info(&np->xbdev->dev,
+ "bouncing transmitted data to zeroed pages\n");
/* talk_to_netback() sets the correct number of queues */
num_queues = dev->real_num_tx_queues;
diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c
index ceef81d93ac9..01329b91d59d 100644
--- a/drivers/nfc/nfcmrvl/i2c.c
+++ b/drivers/nfc/nfcmrvl/i2c.c
@@ -167,9 +167,9 @@ static int nfcmrvl_i2c_parse_dt(struct device_node *node,
pdata->irq_polarity = IRQF_TRIGGER_RISING;
ret = irq_of_parse_and_map(node, 0);
- if (ret < 0) {
- pr_err("Unable to get irq, error: %d\n", ret);
- return ret;
+ if (!ret) {
+ pr_err("Unable to get irq\n");
+ return -EINVAL;
}
pdata->irq = ret;
diff --git a/drivers/nfc/nfcmrvl/spi.c b/drivers/nfc/nfcmrvl/spi.c
index 5b833a9a83f8..abd75779194c 100644
--- a/drivers/nfc/nfcmrvl/spi.c
+++ b/drivers/nfc/nfcmrvl/spi.c
@@ -115,9 +115,9 @@ static int nfcmrvl_spi_parse_dt(struct device_node *node,
}
ret = irq_of_parse_and_map(node, 0);
- if (ret < 0) {
- pr_err("Unable to get irq, error: %d\n", ret);
- return ret;
+ if (!ret) {
+ pr_err("Unable to get irq\n");
+ return -EINVAL;
}
pdata->irq = ret;
diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
index 7e451c10985d..e8f3b35afbee 100644
--- a/drivers/nfc/nxp-nci/i2c.c
+++ b/drivers/nfc/nxp-nci/i2c.c
@@ -162,6 +162,9 @@ static int nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy *phy,
skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE);
+ if (!header.plen)
+ return 0;
+
r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen);
if (r != header.plen) {
nfc_err(&client->dev,
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 9dc7f3edd42b..84d197cc09f8 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -185,8 +185,8 @@ static int nvdimm_clear_badblocks_region(struct device *dev, void *data)
ndr_end = nd_region->ndr_start + nd_region->ndr_size - 1;
/* make sure we are in the region */
- if (ctx->phys < nd_region->ndr_start
- || (ctx->phys + ctx->cleared) > ndr_end)
+ if (ctx->phys < nd_region->ndr_start ||
+ (ctx->phys + ctx->cleared - 1) > ndr_end)
return 0;
sector = (ctx->phys - nd_region->ndr_start) / 512;
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 58b8461b2b0f..c3db9f12dac3 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -3341,8 +3341,11 @@ static const struct pci_device_id nvme_id_table[] = {
{ PCI_DEVICE(0x1b4b, 0x1092), /* Lexar 256 GB SSD */
.driver_data = NVME_QUIRK_NO_NS_DESC_LIST |
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+ { PCI_DEVICE(0x1cc1, 0x33f8), /* ADATA IM2P33F8ABR1 1 TB */
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
{ PCI_DEVICE(0x10ec, 0x5762), /* ADATA SX6000LNP */
- .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+ .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN |
+ NVME_QUIRK_BOGUS_NID, },
{ PCI_DEVICE(0x1cc1, 0x8201), /* ADATA SX8200PNP 512GB */
.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index e21ea3d23e6f..f1ff003bb14b 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -871,6 +871,8 @@ config PANASONIC_LAPTOP
tristate "Panasonic Laptop Extras"
depends on INPUT && ACPI
depends on BACKLIGHT_CLASS_DEVICE
+ depends on ACPI_VIDEO=n || ACPI_VIDEO
+ depends on SERIO_I8042 || SERIO_I8042 = n
select INPUT_SPARSEKMAP
help
This driver adds support for access to backlight control and hotkeys
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index d4f444401496..7ca49b3fc6c2 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -119,20 +119,22 @@
* - v0.1 start from toshiba_acpi driver written by John Belmonte
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
+#include <linux/acpi.h>
#include <linux/backlight.h>
#include <linux/ctype.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/acpi.h>
+#include <linux/i8042.h>
+#include <linux/init.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
-
+#include <linux/seq_file.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <acpi/video.h>
MODULE_AUTHOR("Hiroshi Miura <miura@da-cha.org>");
MODULE_AUTHOR("David Bronaugh <dbronaugh@linuxboxen.org>");
@@ -241,6 +243,42 @@ struct pcc_acpi {
struct platform_device *platform;
};
+/*
+ * On some Panasonic models the volume up / down / mute keys send duplicate
+ * keypress events over the PS/2 kbd interface, filter these out.
+ */
+static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
+ struct serio *port)
+{
+ static bool extended;
+
+ if (str & I8042_STR_AUXDATA)
+ return false;
+
+ if (data == 0xe0) {
+ extended = true;
+ return true;
+ } else if (extended) {
+ extended = false;
+
+ switch (data & 0x7f) {
+ case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */
+ case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
+ case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
+ return true;
+ default:
+ /*
+ * Report the previously filtered e0 before continuing
+ * with the next non-filtered byte.
+ */
+ serio_interrupt(port, 0xe0, 0);
+ return false;
+ }
+ }
+
+ return false;
+}
+
/* method access functions */
static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
{
@@ -762,6 +800,8 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
struct input_dev *hotk_input_dev = pcc->input_dev;
int rc;
unsigned long long result;
+ unsigned int key;
+ unsigned int updown;
rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
NULL, &result);
@@ -770,20 +810,27 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
return;
}
+ key = result & 0xf;
+ updown = result & 0x80; /* 0x80 == key down; 0x00 = key up */
+
/* hack: some firmware sends no key down for sleep / hibernate */
- if ((result & 0xf) == 0x7 || (result & 0xf) == 0xa) {
- if (result & 0x80)
+ if (key == 7 || key == 10) {
+ if (updown)
sleep_keydown_seen = 1;
if (!sleep_keydown_seen)
sparse_keymap_report_event(hotk_input_dev,
- result & 0xf, 0x80, false);
+ key, 0x80, false);
}
- if ((result & 0xf) == 0x7 || (result & 0xf) == 0x9 || (result & 0xf) == 0xa) {
- if (!sparse_keymap_report_event(hotk_input_dev,
- result & 0xf, result & 0x80, false))
- pr_err("Unknown hotkey event: 0x%04llx\n", result);
- }
+ /*
+ * Don't report brightness key-presses if they are also reported
+ * by the ACPI video bus.
+ */
+ if ((key == 1 || key == 2) && acpi_video_handles_brightness_key_presses())
+ return;
+
+ if (!sparse_keymap_report_event(hotk_input_dev, key, updown, false))
+ pr_err("Unknown hotkey event: 0x%04llx\n", result);
}
static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
@@ -997,6 +1044,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
pcc->platform = NULL;
}
+ i8042_install_filter(panasonic_i8042_filter);
return 0;
out_platform:
@@ -1020,6 +1068,8 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device)
if (!device || !pcc)
return -EINVAL;
+ i8042_remove_filter(panasonic_i8042_filter);
+
if (pcc->platform) {
device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
platform_device_unregister(pcc->platform);
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index e4258f40dcd7..174895372e7f 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -1698,6 +1698,8 @@ static void mlx5_vdpa_set_vq_cb(struct vdpa_device *vdev, u16 idx, struct vdpa_c
struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
ndev->event_cbs[idx] = *cb;
+ if (is_ctrl_vq_idx(mvdev, idx))
+ mvdev->cvq.event_cb = *cb;
}
static void mlx5_cvq_notify(struct vringh *vring)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index a8470a98f84d..189323740324 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -4788,6 +4788,8 @@ static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
return -EINVAL;
if (unlikely(sqe->addr2 || sqe->file_index))
return -EINVAL;
+ if (unlikely(sqe->addr2 || sqe->file_index || sqe->ioprio))
+ return -EINVAL;
sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
sr->len = READ_ONCE(sqe->len);
@@ -5011,6 +5013,8 @@ static int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
return -EINVAL;
if (unlikely(sqe->addr2 || sqe->file_index))
return -EINVAL;
+ if (unlikely(sqe->addr2 || sqe->file_index || sqe->ioprio))
+ return -EINVAL;
sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
sr->len = READ_ONCE(sqe->len);
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 1ed3046dd5b3..876afde0ea66 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -7684,7 +7684,7 @@ int smb2_ioctl(struct ksmbd_work *work)
{
struct file_zero_data_information *zero_data;
struct ksmbd_file *fp;
- loff_t off, len;
+ loff_t off, len, bfz;
if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
ksmbd_debug(SMB,
@@ -7701,19 +7701,26 @@ int smb2_ioctl(struct ksmbd_work *work)
zero_data =
(struct file_zero_data_information *)&req->Buffer[0];
- fp = ksmbd_lookup_fd_fast(work, id);
- if (!fp) {
- ret = -ENOENT;
+ off = le64_to_cpu(zero_data->FileOffset);
+ bfz = le64_to_cpu(zero_data->BeyondFinalZero);
+ if (off > bfz) {
+ ret = -EINVAL;
goto out;
}
- off = le64_to_cpu(zero_data->FileOffset);
- len = le64_to_cpu(zero_data->BeyondFinalZero) - off;
+ len = bfz - off;
+ if (len) {
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp) {
+ ret = -ENOENT;
+ goto out;
+ }
- ret = ksmbd_vfs_zero_data(work, fp, off, len);
- ksmbd_fd_put(work, fp);
- if (ret < 0)
- goto out;
+ ret = ksmbd_vfs_zero_data(work, fp, off, len);
+ ksmbd_fd_put(work, fp);
+ if (ret < 0)
+ goto out;
+ }
break;
}
case FSCTL_QUERY_ALLOCATED_RANGES:
@@ -7787,14 +7794,24 @@ int smb2_ioctl(struct ksmbd_work *work)
src_off = le64_to_cpu(dup_ext->SourceFileOffset);
dst_off = le64_to_cpu(dup_ext->TargetFileOffset);
length = le64_to_cpu(dup_ext->ByteCount);
- cloned = vfs_clone_file_range(fp_in->filp, src_off, fp_out->filp,
- dst_off, length, 0);
+ /*
+ * XXX: It is not clear if FSCTL_DUPLICATE_EXTENTS_TO_FILE
+ * should fall back to vfs_copy_file_range(). This could be
+ * beneficial when re-exporting nfs/smb mount, but note that
+ * this can result in partial copy that returns an error status.
+ * If/when FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX is implemented,
+ * fall back to vfs_copy_file_range(), should be avoided when
+ * the flag DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC is set.
+ */
+ cloned = vfs_clone_file_range(fp_in->filp, src_off,
+ fp_out->filp, dst_off, length, 0);
if (cloned == -EXDEV || cloned == -EOPNOTSUPP) {
ret = -EOPNOTSUPP;
goto dup_ext_out;
} else if (cloned != length) {
cloned = vfs_copy_file_range(fp_in->filp, src_off,
- fp_out->filp, dst_off, length, 0);
+ fp_out->filp, dst_off,
+ length, 0);
if (cloned != length) {
if (cloned < 0)
ret = cloned;
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 835b384b0895..2139aa042c79 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -1018,7 +1018,9 @@ int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
off, len);
- return vfs_fallocate(fp->filp, FALLOC_FL_ZERO_RANGE, off, len);
+ return vfs_fallocate(fp->filp,
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
+ off, len);
}
int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
@@ -1049,7 +1051,7 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
*out_count = 0;
end = start + length;
while (start < end && *out_count < in_count) {
- extent_start = f->f_op->llseek(f, start, SEEK_DATA);
+ extent_start = vfs_llseek(f, start, SEEK_DATA);
if (extent_start < 0) {
if (extent_start != -ENXIO)
ret = (int)extent_start;
@@ -1059,7 +1061,7 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
if (extent_start >= end)
break;
- extent_end = f->f_op->llseek(f, extent_start, SEEK_HOLE);
+ extent_end = vfs_llseek(f, extent_start, SEEK_HOLE);
if (extent_end < 0) {
if (extent_end != -ENXIO)
ret = (int)extent_end;
@@ -1780,6 +1782,10 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
ret = vfs_copy_file_range(src_fp->filp, src_off,
dst_fp->filp, dst_off, len, 0);
+ if (ret == -EOPNOTSUPP || ret == -EXDEV)
+ ret = generic_copy_file_range(src_fp->filp, src_off,
+ dst_fp->filp, dst_off,
+ len, 0);
if (ret < 0)
return ret;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7bfb68583154..5f62fa0963ce 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -560,6 +560,7 @@ __be32 nfsd4_clone_file_range(struct nfsd_file *nf_src, u64 src_pos,
ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
u64 dst_pos, u64 count)
{
+ ssize_t ret;
/*
* Limit copy to 4MB to prevent indefinitely blocking an nfsd
@@ -570,7 +571,12 @@ ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
* limit like this and pipeline multiple COPY requests.
*/
count = min_t(u64, count, 1 << 22);
- return vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
+ ret = vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
+
+ if (ret == -EOPNOTSUPP || ret == -EXDEV)
+ ret = generic_copy_file_range(src, src_pos, dst, dst_pos,
+ count, 0);
+ return ret;
}
__be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp,
@@ -1142,6 +1148,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
nfsd_net_id));
err2 = filemap_check_wb_err(nf->nf_file->f_mapping,
since);
+ err = nfserrno(err2);
break;
case -EINVAL:
err = nfserr_notsupp;
@@ -1149,8 +1156,8 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
default:
nfsd_reset_boot_verifier(net_generic(nf->nf_net,
nfsd_net_id));
+ err = nfserrno(err2);
}
- err = nfserrno(err2);
} else
nfsd_copy_boot_verifier(verf, net_generic(nf->nf_net,
nfsd_net_id));
diff --git a/fs/read_write.c b/fs/read_write.c
index af057c57bdc6..c6db1a0762fa 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1384,28 +1384,6 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in,
}
EXPORT_SYMBOL(generic_copy_file_range);
-static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in,
- struct file *file_out, loff_t pos_out,
- size_t len, unsigned int flags)
-{
- /*
- * Although we now allow filesystems to handle cross sb copy, passing
- * a file of the wrong filesystem type to filesystem driver can result
- * in an attempt to dereference the wrong type of ->private_data, so
- * avoid doing that until we really have a good reason. NFS defines
- * several different file_system_type structures, but they all end up
- * using the same ->copy_file_range() function pointer.
- */
- if (file_out->f_op->copy_file_range &&
- file_out->f_op->copy_file_range == file_in->f_op->copy_file_range)
- return file_out->f_op->copy_file_range(file_in, pos_in,
- file_out, pos_out,
- len, flags);
-
- return generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
- flags);
-}
-
/*
* Performs necessary checks before doing a file copy
*
@@ -1427,6 +1405,24 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,
if (ret)
return ret;
+ /*
+ * We allow some filesystems to handle cross sb copy, but passing
+ * a file of the wrong filesystem type to filesystem driver can result
+ * in an attempt to dereference the wrong type of ->private_data, so
+ * avoid doing that until we really have a good reason.
+ *
+ * nfs and cifs define several different file_system_type structures
+ * and several different sets of file_operations, but they all end up
+ * using the same ->copy_file_range() function pointer.
+ */
+ if (file_out->f_op->copy_file_range) {
+ if (file_in->f_op->copy_file_range !=
+ file_out->f_op->copy_file_range)
+ return -EXDEV;
+ } else if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) {
+ return -EXDEV;
+ }
+
/* Don't touch certain kinds of inodes */
if (IS_IMMUTABLE(inode_out))
return -EPERM;
@@ -1492,26 +1488,41 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
file_start_write(file_out);
/*
- * Try cloning first, this is supported by more file systems, and
- * more efficient if both clone and copy are supported (e.g. NFS).
+ * Cloning is supported by more file systems, so we implement copy on
+ * same sb using clone, but for filesystems where both clone and copy
+ * are supported (e.g. nfs,cifs), we only call the copy method.
*/
+ if (file_out->f_op->copy_file_range) {
+ ret = file_out->f_op->copy_file_range(file_in, pos_in,
+ file_out, pos_out,
+ len, flags);
+ goto done;
+ }
+
if (file_in->f_op->remap_file_range &&
file_inode(file_in)->i_sb == file_inode(file_out)->i_sb) {
- loff_t cloned;
-
- cloned = file_in->f_op->remap_file_range(file_in, pos_in,
+ ret = file_in->f_op->remap_file_range(file_in, pos_in,
file_out, pos_out,
min_t(loff_t, MAX_RW_COUNT, len),
REMAP_FILE_CAN_SHORTEN);
- if (cloned > 0) {
- ret = cloned;
+ if (ret > 0)
goto done;
- }
}
- ret = do_copy_file_range(file_in, pos_in, file_out, pos_out, len,
- flags);
- WARN_ON_ONCE(ret == -EOPNOTSUPP);
+ /*
+ * We can get here for same sb copy of filesystems that do not implement
+ * ->copy_file_range() in case filesystem does not support clone or in
+ * case filesystem supports clone but rejected the clone request (e.g.
+ * because it was not block aligned).
+ *
+ * In both cases, fall back to kernel copy so we are able to maintain a
+ * consistent story about which filesystems support copy_file_range()
+ * and which filesystems do not, that will allow userspace tools to
+ * make consistent desicions w.r.t using copy_file_range().
+ */
+ ret = generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
+ flags);
+
done:
if (ret > 0) {
fsnotify_access(file_in);
diff --git a/include/linux/dim.h b/include/linux/dim.h
index b698266d0035..6c5733981563 100644
--- a/include/linux/dim.h
+++ b/include/linux/dim.h
@@ -21,7 +21,7 @@
* We consider 10% difference as significant.
*/
#define IS_SIGNIFICANT_DIFF(val, ref) \
- (((100UL * abs((val) - (ref))) / (ref)) > 10)
+ ((ref) && (((100UL * abs((val) - (ref))) / (ref)) > 10))
/*
* Calculate the gap between two values.
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 39f1893ecac0..f8d46dc62d65 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1645,7 +1645,7 @@ enum netdev_priv_flags {
IFF_FAILOVER_SLAVE = 1<<28,
IFF_L3MDEV_RX_HANDLER = 1<<29,
IFF_LIVE_RENAME_OK = 1<<30,
- IFF_TX_SKB_NO_LINEAR = 1<<31,
+ IFF_TX_SKB_NO_LINEAR = BIT_ULL(31),
};
#define IFF_802_1Q_VLAN IFF_802_1Q_VLAN
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 736e1d1a47c4..946ccec17858 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -536,6 +536,10 @@ struct macsec_ops;
* @mdix: Current crossover
* @mdix_ctrl: User setting of crossover
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -590,6 +594,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 9f4bb4a6f358..808c73c52820 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -1352,11 +1352,11 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
#define AMD_FMT_MOD_PIPE_MASK 0x7
#define AMD_FMT_MOD_SET(field, value) \
- ((uint64_t)(value) << AMD_FMT_MOD_##field##_SHIFT)
+ ((__u64)(value) << AMD_FMT_MOD_##field##_SHIFT)
#define AMD_FMT_MOD_GET(field, value) \
(((value) >> AMD_FMT_MOD_##field##_SHIFT) & AMD_FMT_MOD_##field##_MASK)
#define AMD_FMT_MOD_CLEAR(field) \
- (~((uint64_t)AMD_FMT_MOD_##field##_MASK << AMD_FMT_MOD_##field##_SHIFT))
+ (~((__u64)AMD_FMT_MOD_##field##_MASK << AMD_FMT_MOD_##field##_SHIFT))
#if defined(__cplusplus)
}
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 6b2dc7b2b612..cc1caab4a654 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -410,7 +410,7 @@ int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst,
u32 mtu = dst_mtu(encap_dst) - headroom;
if ((skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu)) ||
- (!skb_is_gso(skb) && (skb->len - skb_mac_header_len(skb)) <= mtu))
+ (!skb_is_gso(skb) && (skb->len - skb_network_offset(skb)) <= mtu))
return 0;
skb_dst_update_pmtu_no_confirm(skb, mtu);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a189625098ba..5d94822fd506 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2014,7 +2014,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
struct sock *nsk;
sk = req->rsk_listener;
- if (unlikely(tcp_v4_inbound_md5_hash(sk, skb, dif, sdif))) {
+ if (unlikely(!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb) ||
+ tcp_v4_inbound_md5_hash(sk, skb, dif, sdif))) {
sk_drops_add(sk, skb);
reqsk_put(req);
goto discard_it;
@@ -2061,6 +2062,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
}
goto discard_and_relse;
}
+ nf_reset_ct(skb);
if (nsk == sk) {
reqsk_put(req);
tcp_v4_restore_cb(skb);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 07b868c002a3..6dcf034835ec 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1111,10 +1111,6 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
goto out;
}
- if (net->ipv6.devconf_all->disable_policy ||
- idev->cnf.disable_policy)
- f6i->dst_nopolicy = true;
-
neigh_parms_data_state_setall(idev->nd_parms);
ifa->addr = *cfg->pfx;
@@ -5170,9 +5166,9 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
fillargs->event = RTM_GETMULTICAST;
/* multicast address */
- for (ifmca = rcu_dereference(idev->mc_list);
+ for (ifmca = rtnl_dereference(idev->mc_list);
ifmca;
- ifmca = rcu_dereference(ifmca->next), ip_idx++) {
+ ifmca = rtnl_dereference(ifmca->next), ip_idx++) {
if (ip_idx < s_ip_idx)
continue;
err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0ca7c780d97a..4ca754c360a3 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -4590,8 +4590,15 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
}
f6i = ip6_route_info_create(&cfg, gfp_flags, NULL);
- if (!IS_ERR(f6i))
+ if (!IS_ERR(f6i)) {
f6i->dst_nocount = true;
+
+ if (!anycast &&
+ (net->ipv6.devconf_all->disable_policy ||
+ idev->cnf.disable_policy))
+ f6i->dst_nopolicy = true;
+ }
+
return f6i;
}
diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c
index 5b2c9ce53395..b7d6b64cc532 100644
--- a/net/ipv6/seg6_hmac.c
+++ b/net/ipv6/seg6_hmac.c
@@ -408,7 +408,6 @@ int __net_init seg6_hmac_net_init(struct net *net)
return 0;
}
-EXPORT_SYMBOL(seg6_hmac_net_init);
void seg6_hmac_exit(void)
{
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 626cb53aa57a..637cd99bd7a6 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -323,8 +323,6 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
kcalloc(cmax, sizeof(*kp), GFP_KERNEL_ACCOUNT | __GFP_NOWARN) :
NULL;
- rcu_read_lock();
-
ca = min(t->prl_count, cmax);
if (!kp) {
@@ -341,7 +339,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
}
}
- c = 0;
+ rcu_read_lock();
for_each_prl_rcu(t->prl) {
if (c >= cmax)
break;
@@ -353,7 +351,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
if (kprl.addr != htonl(INADDR_ANY))
break;
}
-out:
+
rcu_read_unlock();
len = sizeof(*kp) * c;
@@ -362,7 +360,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u
ret = -EFAULT;
kfree(kp);
-
+out:
return ret;
}
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
index df40314de21f..76de6c8d9865 100644
--- a/net/netfilter/nft_set_hash.c
+++ b/net/netfilter/nft_set_hash.c
@@ -143,6 +143,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key,
/* Another cpu may race to insert the element with the same key */
if (prev) {
nft_set_elem_destroy(set, he, true);
+ atomic_dec(&set->nelems);
he = prev;
}
@@ -152,6 +153,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key,
err2:
nft_set_elem_destroy(set, he, true);
+ atomic_dec(&set->nelems);
err1:
return false;
}
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index b3138fc2e552..f06ddbed3fed 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -31,89 +31,89 @@ static void rose_idletimer_expiry(struct timer_list *);
void rose_start_heartbeat(struct sock *sk)
{
- del_timer(&sk->sk_timer);
+ sk_stop_timer(sk, &sk->sk_timer);
sk->sk_timer.function = rose_heartbeat_expiry;
sk->sk_timer.expires = jiffies + 5 * HZ;
- add_timer(&sk->sk_timer);
+ sk_reset_timer(sk, &sk->sk_timer, sk->sk_timer.expires);
}
void rose_start_t1timer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->timer);
+ sk_stop_timer(sk, &rose->timer);
rose->timer.function = rose_timer_expiry;
rose->timer.expires = jiffies + rose->t1;
- add_timer(&rose->timer);
+ sk_reset_timer(sk, &rose->timer, rose->timer.expires);
}
void rose_start_t2timer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->timer);
+ sk_stop_timer(sk, &rose->timer);
rose->timer.function = rose_timer_expiry;
rose->timer.expires = jiffies + rose->t2;
- add_timer(&rose->timer);
+ sk_reset_timer(sk, &rose->timer, rose->timer.expires);
}
void rose_start_t3timer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->timer);
+ sk_stop_timer(sk, &rose->timer);
rose->timer.function = rose_timer_expiry;
rose->timer.expires = jiffies + rose->t3;
- add_timer(&rose->timer);
+ sk_reset_timer(sk, &rose->timer, rose->timer.expires);
}
void rose_start_hbtimer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->timer);
+ sk_stop_timer(sk, &rose->timer);
rose->timer.function = rose_timer_expiry;
rose->timer.expires = jiffies + rose->hb;
- add_timer(&rose->timer);
+ sk_reset_timer(sk, &rose->timer, rose->timer.expires);
}
void rose_start_idletimer(struct sock *sk)
{
struct rose_sock *rose = rose_sk(sk);
- del_timer(&rose->idletimer);
+ sk_stop_timer(sk, &rose->idletimer);
if (rose->idle > 0) {
rose->idletimer.function = rose_idletimer_expiry;
rose->idletimer.expires = jiffies + rose->idle;
- add_timer(&rose->idletimer);
+ sk_reset_timer(sk, &rose->idletimer, rose->idletimer.expires);
}
}
void rose_stop_heartbeat(struct sock *sk)
{
- del_timer(&sk->sk_timer);
+ sk_stop_timer(sk, &sk->sk_timer);
}
void rose_stop_timer(struct sock *sk)
{
- del_timer(&rose_sk(sk)->timer);
+ sk_stop_timer(sk, &rose_sk(sk)->timer);
}
void rose_stop_idletimer(struct sock *sk)
{
- del_timer(&rose_sk(sk)->idletimer);
+ sk_stop_timer(sk, &rose_sk(sk)->idletimer);
}
static void rose_heartbeat_expiry(struct timer_list *t)
@@ -130,6 +130,7 @@ static void rose_heartbeat_expiry(struct timer_list *t)
(sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
bh_unlock_sock(sk);
rose_destroy_socket(sk);
+ sock_put(sk);
return;
}
break;
@@ -152,6 +153,7 @@ static void rose_heartbeat_expiry(struct timer_list *t)
rose_start_heartbeat(sk);
bh_unlock_sock(sk);
+ sock_put(sk);
}
static void rose_timer_expiry(struct timer_list *t)
@@ -181,6 +183,7 @@ static void rose_timer_expiry(struct timer_list *t)
break;
}
bh_unlock_sock(sk);
+ sock_put(sk);
}
static void rose_idletimer_expiry(struct timer_list *t)
@@ -205,4 +208,5 @@ static void rose_idletimer_expiry(struct timer_list *t)
sock_set_flag(sk, SOCK_DEAD);
}
bh_unlock_sock(sk);
+ sock_put(sk);
}
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 7d53272727bf..d775676956bf 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -350,7 +350,8 @@ static int tcf_idr_release_unsafe(struct tc_action *p)
}
static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
- const struct tc_action_ops *ops)
+ const struct tc_action_ops *ops,
+ struct netlink_ext_ack *extack)
{
struct nlattr *nest;
int n_i = 0;
@@ -366,20 +367,25 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
if (nla_put_string(skb, TCA_KIND, ops->kind))
goto nla_put_failure;
+ ret = 0;
mutex_lock(&idrinfo->lock);
idr_for_each_entry_ul(idr, p, tmp, id) {
if (IS_ERR(p))
continue;
ret = tcf_idr_release_unsafe(p);
- if (ret == ACT_P_DELETED) {
+ if (ret == ACT_P_DELETED)
module_put(ops->owner);
- n_i++;
- } else if (ret < 0) {
- mutex_unlock(&idrinfo->lock);
- goto nla_put_failure;
- }
+ else if (ret < 0)
+ break;
+ n_i++;
}
mutex_unlock(&idrinfo->lock);
+ if (ret < 0) {
+ if (n_i)
+ NL_SET_ERR_MSG(extack, "Unable to flush all TC actions");
+ else
+ goto nla_put_failure;
+ }
ret = nla_put_u32(skb, TCA_FCNT, n_i);
if (ret)
@@ -400,7 +406,7 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct tcf_idrinfo *idrinfo = tn->idrinfo;
if (type == RTM_DELACTION) {
- return tcf_del_walker(idrinfo, skb, ops);
+ return tcf_del_walker(idrinfo, skb, ops, extack);
} else if (type == RTM_GETACTION) {
return tcf_dump_walker(idrinfo, skb, cb);
} else {
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 85473264cccf..f0a0a4ad6d52 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -979,7 +979,7 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr,
*/
xdr->p = (void *)p + frag2bytes;
space_left = xdr->buf->buflen - xdr->buf->len;
- if (space_left - nbytes >= PAGE_SIZE)
+ if (space_left - frag1bytes >= PAGE_SIZE)
xdr->end = (void *)p + PAGE_SIZE;
else
xdr->end = (void *)p + space_left - frag1bytes;
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 6ef95ce565bd..b48d97cbbe29 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -472,8 +472,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
bool preliminary)
{
struct tipc_net *tn = net_generic(net, tipc_net_id);
+ struct tipc_link *l, *snd_l = tipc_bc_sndlink(net);
struct tipc_node *n, *temp_node;
- struct tipc_link *l;
unsigned long intv;
int bearer_id;
int i;
@@ -488,6 +488,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
goto exit;
/* A preliminary node becomes "real" now, refresh its data */
tipc_node_write_lock(n);
+ if (!tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX,
+ tipc_link_min_win(snd_l), tipc_link_max_win(snd_l),
+ n->capabilities, &n->bc_entry.inputq1,
+ &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
+ pr_warn("Broadcast rcv link refresh failed, no memory\n");
+ tipc_node_write_unlock_fast(n);
+ tipc_node_put(n);
+ n = NULL;
+ goto exit;
+ }
n->preliminary = false;
n->addr = addr;
hlist_del_rcu(&n->hash);
@@ -567,7 +577,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id,
n->signature = INVALID_NODE_SIG;
n->active_links[0] = INVALID_BEARER_ID;
n->active_links[1] = INVALID_BEARER_ID;
- n->bc_entry.link = NULL;
+ if (!preliminary &&
+ !tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX,
+ tipc_link_min_win(snd_l), tipc_link_max_win(snd_l),
+ n->capabilities, &n->bc_entry.inputq1,
+ &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
+ pr_warn("Broadcast rcv link creation failed, no memory\n");
+ kfree(n);
+ n = NULL;
+ goto exit;
+ }
tipc_node_get(n);
timer_setup(&n->timer, tipc_node_timeout, 0);
/* Start a slow timer anyway, crypto needs it */
@@ -1155,7 +1174,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
bool *respond, bool *dupl_addr)
{
struct tipc_node *n;
- struct tipc_link *l, *snd_l;
+ struct tipc_link *l;
struct tipc_link_entry *le;
bool addr_match = false;
bool sign_match = false;
@@ -1175,22 +1194,6 @@ void tipc_node_check_dest(struct net *net, u32 addr,
return;
tipc_node_write_lock(n);
- if (unlikely(!n->bc_entry.link)) {
- snd_l = tipc_bc_sndlink(net);
- if (!tipc_link_bc_create(net, tipc_own_addr(net),
- addr, peer_id, U16_MAX,
- tipc_link_min_win(snd_l),
- tipc_link_max_win(snd_l),
- n->capabilities,
- &n->bc_entry.inputq1,
- &n->bc_entry.namedq, snd_l,
- &n->bc_entry.link)) {
- pr_warn("Broadcast rcv link creation failed, no mem\n");
- tipc_node_write_unlock_fast(n);
- tipc_node_put(n);
- return;
- }
- }
le = &n->links[b->identity];
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 3a9e332c5e36..68a9a897185c 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -31,6 +31,7 @@
#include <linux/if_ether.h>
#include <linux/btf.h>
+#include <bpf/btf.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
@@ -63,6 +64,11 @@ static bool unpriv_disabled = false;
static int skips;
static bool verbose = false;
+struct kfunc_btf_id_pair {
+ const char *kfunc;
+ int insn_idx;
+};
+
struct bpf_test {
const char *descr;
struct bpf_insn insns[MAX_INSNS];
@@ -88,6 +94,7 @@ struct bpf_test {
int fixup_map_event_output[MAX_FIXUPS];
int fixup_map_reuseport_array[MAX_FIXUPS];
int fixup_map_ringbuf[MAX_FIXUPS];
+ struct kfunc_btf_id_pair fixup_kfunc_btf_id[MAX_FIXUPS];
/* Expected verifier log output for result REJECT or VERBOSE_ACCEPT.
* Can be a tab-separated sequence of expected strings. An empty string
* means no log verification.
@@ -718,6 +725,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
int *fixup_map_event_output = test->fixup_map_event_output;
int *fixup_map_reuseport_array = test->fixup_map_reuseport_array;
int *fixup_map_ringbuf = test->fixup_map_ringbuf;
+ struct kfunc_btf_id_pair *fixup_kfunc_btf_id = test->fixup_kfunc_btf_id;
if (test->fill_helper) {
test->fill_insns = calloc(MAX_TEST_INSNS, sizeof(struct bpf_insn));
@@ -903,6 +911,26 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
fixup_map_ringbuf++;
} while (*fixup_map_ringbuf);
}
+
+ /* Patch in kfunc BTF IDs */
+ if (fixup_kfunc_btf_id->kfunc) {
+ struct btf *btf;
+ int btf_id;
+
+ do {
+ btf_id = 0;
+ btf = btf__load_vmlinux_btf();
+ if (btf) {
+ btf_id = btf__find_by_name_kind(btf,
+ fixup_kfunc_btf_id->kfunc,
+ BTF_KIND_FUNC);
+ btf_id = btf_id < 0 ? 0 : btf_id;
+ }
+ btf__free(btf);
+ prog[fixup_kfunc_btf_id->insn_idx].imm = btf_id;
+ fixup_kfunc_btf_id++;
+ } while (fixup_kfunc_btf_id->kfunc);
+ }
}
struct libcap {
diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh
index ff821025d309..49dfabded1d4 100755
--- a/tools/testing/selftests/net/mptcp/diag.sh
+++ b/tools/testing/selftests/net/mptcp/diag.sh
@@ -61,6 +61,39 @@ chk_msk_nr()
__chk_nr "grep -c token:" $*
}
+wait_msk_nr()
+{
+ local condition="grep -c token:"
+ local expected=$1
+ local timeout=20
+ local msg nr
+ local max=0
+ local i=0
+
+ shift 1
+ msg=$*
+
+ while [ $i -lt $timeout ]; do
+ nr=$(ss -inmHMN $ns | $condition)
+ [ $nr == $expected ] && break;
+ [ $nr -gt $max ] && max=$nr
+ i=$((i + 1))
+ sleep 1
+ done
+
+ printf "%-50s" "$msg"
+ if [ $i -ge $timeout ]; then
+ echo "[ fail ] timeout while expecting $expected max $max last $nr"
+ ret=$test_cnt
+ elif [ $nr != $expected ]; then
+ echo "[ fail ] expected $expected found $nr"
+ ret=$test_cnt
+ else
+ echo "[ ok ]"
+ fi
+ test_cnt=$((test_cnt+1))
+}
+
chk_msk_fallback_nr()
{
__chk_nr "grep -c fallback" $*
@@ -109,7 +142,7 @@ ip -n $ns link set dev lo up
echo "a" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10000 -l -t ${timeout_poll} \
+ ./mptcp_connect -p 10000 -l -t ${timeout_poll} -w 20 \
0.0.0.0 >/dev/null &
wait_local_port_listen $ns 10000
chk_msk_nr 0 "no msk on netns creation"
@@ -117,7 +150,7 @@ chk_msk_nr 0 "no msk on netns creation"
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} \
+ ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} -w 20 \
127.0.0.1 >/dev/null &
wait_connected $ns 10000
chk_msk_nr 2 "after MPC handshake "
@@ -129,13 +162,13 @@ flush_pids
echo "a" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} \
+ ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} -w 20 \
0.0.0.0 >/dev/null &
wait_local_port_listen $ns 10001
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} \
+ ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} -w 20 \
127.0.0.1 >/dev/null &
wait_connected $ns 10001
chk_msk_fallback_nr 1 "check fallback"
@@ -146,7 +179,7 @@ for I in `seq 1 $NR_CLIENTS`; do
echo "a" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p $((I+10001)) -l -w 10 \
+ ./mptcp_connect -p $((I+10001)) -l -w 20 \
-t ${timeout_poll} 0.0.0.0 >/dev/null &
done
wait_local_port_listen $ns $((NR_CLIENTS + 10001))
@@ -155,12 +188,11 @@ for I in `seq 1 $NR_CLIENTS`; do
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p $((I+10001)) -w 10 \
+ ./mptcp_connect -p $((I+10001)) -w 20 \
-t ${timeout_poll} 127.0.0.1 >/dev/null &
done
-sleep 1.5
-chk_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
+wait_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
flush_pids
exit $ret
diff --git a/tools/testing/selftests/net/udpgso_bench.sh b/tools/testing/selftests/net/udpgso_bench.sh
index 80b5d352702e..dc932fd65363 100755
--- a/tools/testing/selftests/net/udpgso_bench.sh
+++ b/tools/testing/selftests/net/udpgso_bench.sh
@@ -120,7 +120,7 @@ run_all() {
run_udp "${ipv4_args}"
echo "ipv6"
- run_tcp "${ipv4_args}"
+ run_tcp "${ipv6_args}"
run_udp "${ipv6_args}"
}
diff --git a/tools/testing/selftests/rseq/Makefile b/tools/testing/selftests/rseq/Makefile
index 2af9d39a9716..215e1067f037 100644
--- a/tools/testing/selftests/rseq/Makefile
+++ b/tools/testing/selftests/rseq/Makefile
@@ -6,7 +6,7 @@ endif
CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L$(OUTPUT) -Wl,-rpath=./ \
$(CLANG_FLAGS)
-LDLIBS += -lpthread
+LDLIBS += -lpthread -ldl
# Own dependencies because we only want to build against 1st prerequisite, but
# still track changes to header files and depend on shared object.
diff --git a/tools/testing/selftests/rseq/basic_percpu_ops_test.c b/tools/testing/selftests/rseq/basic_percpu_ops_test.c
index eb3f6db36d36..517756afc2a4 100644
--- a/tools/testing/selftests/rseq/basic_percpu_ops_test.c
+++ b/tools/testing/selftests/rseq/basic_percpu_ops_test.c
@@ -9,10 +9,9 @@
#include <string.h>
#include <stddef.h>
+#include "../kselftest.h"
#include "rseq.h"
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
struct percpu_lock_entry {
intptr_t v;
} __attribute__((aligned(128)));
@@ -168,7 +167,7 @@ struct percpu_list_node *this_cpu_list_pop(struct percpu_list *list,
for (;;) {
struct percpu_list_node *head;
intptr_t *targetptr, expectnot, *load;
- off_t offset;
+ long offset;
int ret, cpu;
cpu = rseq_cpu_start();
diff --git a/tools/testing/selftests/rseq/compiler.h b/tools/testing/selftests/rseq/compiler.h
new file mode 100644
index 000000000000..876eb6a7f75b
--- /dev/null
+++ b/tools/testing/selftests/rseq/compiler.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/*
+ * rseq/compiler.h
+ *
+ * Work-around asm goto compiler bugs.
+ *
+ * (C) Copyright 2021 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#ifndef RSEQ_COMPILER_H
+#define RSEQ_COMPILER_H
+
+/*
+ * gcc prior to 4.8.2 miscompiles asm goto.
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
+ *
+ * gcc prior to 8.1.0 miscompiles asm goto at O1.
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103908
+ *
+ * clang prior to version 13.0.1 miscompiles asm goto at O2.
+ * https://github.com/llvm/llvm-project/issues/52735
+ *
+ * Work around these issues by adding a volatile inline asm with
+ * memory clobber in the fallthrough after the asm goto and at each
+ * label target. Emit this for all compilers in case other similar
+ * issues are found in the future.
+ */
+#define rseq_after_asm_goto() asm volatile ("" : : : "memory")
+
+#endif /* RSEQ_COMPILER_H_ */
diff --git a/tools/testing/selftests/rseq/param_test.c b/tools/testing/selftests/rseq/param_test.c
index 699ad5f93c34..da23c22d5882 100644
--- a/tools/testing/selftests/rseq/param_test.c
+++ b/tools/testing/selftests/rseq/param_test.c
@@ -161,7 +161,7 @@ unsigned int yield_mod_cnt, nr_abort;
" cbnz " INJECT_ASM_REG ", 222b\n" \
"333:\n"
-#elif __PPC__
+#elif defined(__PPC__)
#define RSEQ_INJECT_INPUT \
, [loop_cnt_1]"m"(loop_cnt[1]) \
@@ -368,9 +368,7 @@ void *test_percpu_spinlock_thread(void *arg)
abort();
reps = thread_data->reps;
for (i = 0; i < reps; i++) {
- int cpu = rseq_cpu_start();
-
- cpu = rseq_this_cpu_lock(&data->lock);
+ int cpu = rseq_this_cpu_lock(&data->lock);
data->c[cpu].count++;
rseq_percpu_unlock(&data->lock, cpu);
#ifndef BENCHMARK
@@ -551,7 +549,7 @@ struct percpu_list_node *this_cpu_list_pop(struct percpu_list *list,
for (;;) {
struct percpu_list_node *head;
intptr_t *targetptr, expectnot, *load;
- off_t offset;
+ long offset;
int ret;
cpu = rseq_cpu_start();
diff --git a/tools/testing/selftests/rseq/rseq-abi.h b/tools/testing/selftests/rseq/rseq-abi.h
new file mode 100644
index 000000000000..a8c44d9af71f
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-abi.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+#ifndef _RSEQ_ABI_H
+#define _RSEQ_ABI_H
+
+/*
+ * rseq-abi.h
+ *
+ * Restartable sequences system call API
+ *
+ * Copyright (c) 2015-2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+enum rseq_abi_cpu_id_state {
+ RSEQ_ABI_CPU_ID_UNINITIALIZED = -1,
+ RSEQ_ABI_CPU_ID_REGISTRATION_FAILED = -2,
+};
+
+enum rseq_abi_flags {
+ RSEQ_ABI_FLAG_UNREGISTER = (1 << 0),
+};
+
+enum rseq_abi_cs_flags_bit {
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
+};
+
+enum rseq_abi_cs_flags {
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT =
+ (1U << RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL =
+ (1U << RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE =
+ (1U << RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
+};
+
+/*
+ * struct rseq_abi_cs is aligned on 4 * 8 bytes to ensure it is always
+ * contained within a single cache-line. It is usually declared as
+ * link-time constant data.
+ */
+struct rseq_abi_cs {
+ /* Version of this structure. */
+ __u32 version;
+ /* enum rseq_abi_cs_flags */
+ __u32 flags;
+ __u64 start_ip;
+ /* Offset from start_ip. */
+ __u64 post_commit_offset;
+ __u64 abort_ip;
+} __attribute__((aligned(4 * sizeof(__u64))));
+
+/*
+ * struct rseq_abi is aligned on 4 * 8 bytes to ensure it is always
+ * contained within a single cache-line.
+ *
+ * A single struct rseq_abi per thread is allowed.
+ */
+struct rseq_abi {
+ /*
+ * Restartable sequences cpu_id_start field. Updated by the
+ * kernel. Read by user-space with single-copy atomicity
+ * semantics. This field should only be read by the thread which
+ * registered this data structure. Aligned on 32-bit. Always
+ * contains a value in the range of possible CPUs, although the
+ * value may not be the actual current CPU (e.g. if rseq is not
+ * initialized). This CPU number value should always be compared
+ * against the value of the cpu_id field before performing a rseq
+ * commit or returning a value read from a data structure indexed
+ * using the cpu_id_start value.
+ */
+ __u32 cpu_id_start;
+ /*
+ * Restartable sequences cpu_id field. Updated by the kernel.
+ * Read by user-space with single-copy atomicity semantics. This
+ * field should only be read by the thread which registered this
+ * data structure. Aligned on 32-bit. Values
+ * RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED
+ * have a special semantic: the former means "rseq uninitialized",
+ * and latter means "rseq initialization failed". This value is
+ * meant to be read within rseq critical sections and compared
+ * with the cpu_id_start value previously read, before performing
+ * the commit instruction, or read and compared with the
+ * cpu_id_start value before returning a value loaded from a data
+ * structure indexed using the cpu_id_start value.
+ */
+ __u32 cpu_id;
+ /*
+ * Restartable sequences rseq_cs field.
+ *
+ * Contains NULL when no critical section is active for the current
+ * thread, or holds a pointer to the currently active struct rseq_cs.
+ *
+ * Updated by user-space, which sets the address of the currently
+ * active rseq_cs at the beginning of assembly instruction sequence
+ * block, and set to NULL by the kernel when it restarts an assembly
+ * instruction sequence block, as well as when the kernel detects that
+ * it is preempting or delivering a signal outside of the range
+ * targeted by the rseq_cs. Also needs to be set to NULL by user-space
+ * before reclaiming memory that contains the targeted struct rseq_cs.
+ *
+ * Read and set by the kernel. Set by user-space with single-copy
+ * atomicity semantics. This field should only be updated by the
+ * thread which registered this data structure. Aligned on 64-bit.
+ */
+ union {
+ __u64 ptr64;
+
+ /*
+ * The "arch" field provides architecture accessor for
+ * the ptr field based on architecture pointer size and
+ * endianness.
+ */
+ struct {
+#ifdef __LP64__
+ __u64 ptr;
+#elif defined(__BYTE_ORDER) ? (__BYTE_ORDER == __BIG_ENDIAN) : defined(__BIG_ENDIAN)
+ __u32 padding; /* Initialized to zero. */
+ __u32 ptr;
+#else
+ __u32 ptr;
+ __u32 padding; /* Initialized to zero. */
+#endif
+ } arch;
+ } rseq_cs;
+
+ /*
+ * Restartable sequences flags field.
+ *
+ * This field should only be updated by the thread which
+ * registered this data structure. Read by the kernel.
+ * Mainly used for single-stepping through rseq critical sections
+ * with debuggers.
+ *
+ * - RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT
+ * Inhibit instruction sequence block restart on preemption
+ * for this thread.
+ * - RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL
+ * Inhibit instruction sequence block restart on signal
+ * delivery for this thread.
+ * - RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE
+ * Inhibit instruction sequence block restart on migration for
+ * this thread.
+ */
+ __u32 flags;
+} __attribute__((aligned(4 * sizeof(__u64))));
+
+#endif /* _RSEQ_ABI_H */
diff --git a/tools/testing/selftests/rseq/rseq-arm.h b/tools/testing/selftests/rseq/rseq-arm.h
index 5943c816c07c..893a11eca9d5 100644
--- a/tools/testing/selftests/rseq/rseq-arm.h
+++ b/tools/testing/selftests/rseq/rseq-arm.h
@@ -147,14 +147,11 @@ do { \
teardown \
"b %l[" __rseq_str(cmpfail_label) "]\n\t"
-#define rseq_workaround_gcc_asm_size_guess() __asm__ __volatile__("")
-
static inline __attribute__((always_inline))
int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -185,8 +182,8 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "m" (*v),
[expect] "r" (expect),
[newv] "r" (newv)
@@ -198,30 +195,31 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
- off_t voffp, intptr_t *load, int cpu)
+ long voffp, intptr_t *load, int cpu)
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -255,8 +253,8 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expectnot] "r" (expectnot),
@@ -270,19 +268,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -292,7 +292,6 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
#ifdef RSEQ_COMPARE_TWICE
@@ -316,8 +315,8 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "m" (*v),
[count] "Ir" (count)
RSEQ_INJECT_INPUT
@@ -328,14 +327,15 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
, error1
#endif
);
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
#endif
}
@@ -347,7 +347,6 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -381,8 +380,8 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -398,19 +397,21 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -422,7 +423,6 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -457,8 +457,8 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -474,19 +474,21 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -498,7 +500,6 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -537,8 +538,8 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* cmp2 input */
[v2] "m" (*v2),
[expect2] "r" (expect2),
@@ -554,21 +555,24 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
, error1, error2, error3
#endif
);
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("1st expected value comparison failed");
error3:
+ rseq_after_asm_goto();
rseq_bug("2nd expected value comparison failed");
#endif
}
@@ -582,7 +586,6 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -657,8 +660,8 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
"8:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expect] "r" (expect),
@@ -678,21 +681,21 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -706,7 +709,6 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -782,8 +784,8 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
"8:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expect] "r" (expect),
@@ -803,21 +805,21 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
- rseq_workaround_gcc_asm_size_guess();
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
diff --git a/tools/testing/selftests/rseq/rseq-arm64.h b/tools/testing/selftests/rseq/rseq-arm64.h
index 200dae9e4208..cbe190a4d005 100644
--- a/tools/testing/selftests/rseq/rseq-arm64.h
+++ b/tools/testing/selftests/rseq/rseq-arm64.h
@@ -230,8 +230,8 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "Qo" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "Qo" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "Qo" (*v),
[expect] "r" (expect),
[newv] "r" (newv)
@@ -242,24 +242,28 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
, error1, error2
#endif
);
-
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
- off_t voffp, intptr_t *load, int cpu)
+ long voffp, intptr_t *load, int cpu)
{
RSEQ_INJECT_C(9)
@@ -287,8 +291,8 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "Qo" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "Qo" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "Qo" (*v),
[expectnot] "r" (expectnot),
[load] "Qo" (*load),
@@ -300,16 +304,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -337,8 +346,8 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "Qo" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "Qo" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "Qo" (*v),
[count] "r" (count)
RSEQ_INJECT_INPUT
@@ -348,12 +357,15 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
, error1
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
#endif
}
@@ -388,8 +400,8 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "Qo" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "Qo" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[expect] "r" (expect),
[v] "Qo" (*v),
[newv] "r" (newv),
@@ -402,17 +414,21 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
-
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -447,8 +463,8 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "Qo" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "Qo" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[expect] "r" (expect),
[v] "Qo" (*v),
[newv] "r" (newv),
@@ -461,17 +477,21 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
-
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -508,8 +528,8 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "Qo" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "Qo" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "Qo" (*v),
[expect] "r" (expect),
[v2] "Qo" (*v2),
@@ -522,19 +542,24 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
, error1, error2, error3
#endif
);
-
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
error3:
+ rseq_after_asm_goto();
rseq_bug("2nd expected value comparison failed");
#endif
}
@@ -569,8 +594,8 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "Qo" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "Qo" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[expect] "r" (expect),
[v] "Qo" (*v),
[newv] "r" (newv),
@@ -584,17 +609,21 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
-
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -629,8 +658,8 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "Qo" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "Qo" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[expect] "r" (expect),
[v] "Qo" (*v),
[newv] "r" (newv),
@@ -644,17 +673,21 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
-
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
diff --git a/tools/testing/selftests/rseq/rseq-generic-thread-pointer.h b/tools/testing/selftests/rseq/rseq-generic-thread-pointer.h
new file mode 100644
index 000000000000..38c584661571
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-generic-thread-pointer.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/*
+ * rseq-generic-thread-pointer.h
+ *
+ * (C) Copyright 2021 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#ifndef _RSEQ_GENERIC_THREAD_POINTER
+#define _RSEQ_GENERIC_THREAD_POINTER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Use gcc builtin thread pointer. */
+static inline void *rseq_thread_pointer(void)
+{
+ return __builtin_thread_pointer();
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tools/testing/selftests/rseq/rseq-mips.h b/tools/testing/selftests/rseq/rseq-mips.h
index e989e7c14b09..878739fae2fd 100644
--- a/tools/testing/selftests/rseq/rseq-mips.h
+++ b/tools/testing/selftests/rseq/rseq-mips.h
@@ -154,14 +154,11 @@ do { \
teardown \
"b %l[" __rseq_str(cmpfail_label) "]\n\t"
-#define rseq_workaround_gcc_asm_size_guess() __asm__ __volatile__("")
-
static inline __attribute__((always_inline))
int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -190,8 +187,8 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "m" (*v),
[expect] "r" (expect),
[newv] "r" (newv)
@@ -203,14 +200,11 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -222,11 +216,10 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
- off_t voffp, intptr_t *load, int cpu)
+ long voffp, intptr_t *load, int cpu)
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -258,8 +251,8 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expectnot] "r" (expectnot),
@@ -273,14 +266,11 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -295,7 +285,6 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
#ifdef RSEQ_COMPARE_TWICE
@@ -319,8 +308,8 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "m" (*v),
[count] "Ir" (count)
RSEQ_INJECT_INPUT
@@ -331,10 +320,8 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
, error1
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
#ifdef RSEQ_COMPARE_TWICE
@@ -350,7 +337,6 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -382,8 +368,8 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -399,14 +385,11 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -423,7 +406,6 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -456,8 +438,8 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -473,14 +455,11 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -497,7 +476,6 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
{
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -532,8 +510,8 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
"5:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* cmp2 input */
[v2] "m" (*v2),
[expect2] "r" (expect2),
@@ -549,14 +527,11 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
, error1, error2, error3
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -577,7 +552,6 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -649,8 +623,8 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
"8:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expect] "r" (expect),
@@ -670,21 +644,16 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("cpu_id comparison failed");
error2:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("expected value comparison failed");
#endif
}
@@ -698,7 +667,6 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
RSEQ_INJECT_C(9)
- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -771,8 +739,8 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
"8:\n\t"
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expect] "r" (expect),
@@ -792,21 +760,16 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("cpu_id comparison failed");
error2:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("expected value comparison failed");
#endif
}
diff --git a/tools/testing/selftests/rseq/rseq-ppc-thread-pointer.h b/tools/testing/selftests/rseq/rseq-ppc-thread-pointer.h
new file mode 100644
index 000000000000..263eee84fb76
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-ppc-thread-pointer.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/*
+ * rseq-ppc-thread-pointer.h
+ *
+ * (C) Copyright 2021 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#ifndef _RSEQ_PPC_THREAD_POINTER
+#define _RSEQ_PPC_THREAD_POINTER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline void *rseq_thread_pointer(void)
+{
+#ifdef __powerpc64__
+ register void *__result asm ("r13");
+#else
+ register void *__result asm ("r2");
+#endif
+ asm ("" : "=r" (__result));
+ return __result;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tools/testing/selftests/rseq/rseq-ppc.h b/tools/testing/selftests/rseq/rseq-ppc.h
index 76be90196fe4..bab8e0b9fb11 100644
--- a/tools/testing/selftests/rseq/rseq-ppc.h
+++ b/tools/testing/selftests/rseq/rseq-ppc.h
@@ -47,10 +47,13 @@ do { \
#ifdef __PPC64__
-#define STORE_WORD "std "
-#define LOAD_WORD "ld "
-#define LOADX_WORD "ldx "
-#define CMP_WORD "cmpd "
+#define RSEQ_STORE_LONG(arg) "std%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* To memory ("m" constraint) */
+#define RSEQ_STORE_INT(arg) "stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* To memory ("m" constraint) */
+#define RSEQ_LOAD_LONG(arg) "ld%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* From memory ("m" constraint) */
+#define RSEQ_LOAD_INT(arg) "lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* From memory ("m" constraint) */
+#define RSEQ_LOADX_LONG "ldx " /* From base register ("b" constraint) */
+#define RSEQ_CMP_LONG "cmpd "
+#define RSEQ_CMP_LONG_INT "cmpdi "
#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \
start_ip, post_commit_offset, abort_ip) \
@@ -89,10 +92,13 @@ do { \
#else /* #ifdef __PPC64__ */
-#define STORE_WORD "stw "
-#define LOAD_WORD "lwz "
-#define LOADX_WORD "lwzx "
-#define CMP_WORD "cmpw "
+#define RSEQ_STORE_LONG(arg) "stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* To memory ("m" constraint) */
+#define RSEQ_STORE_INT(arg) RSEQ_STORE_LONG(arg) /* To memory ("m" constraint) */
+#define RSEQ_LOAD_LONG(arg) "lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* From memory ("m" constraint) */
+#define RSEQ_LOAD_INT(arg) RSEQ_LOAD_LONG(arg) /* From memory ("m" constraint) */
+#define RSEQ_LOADX_LONG "lwzx " /* From base register ("b" constraint) */
+#define RSEQ_CMP_LONG "cmpw "
+#define RSEQ_CMP_LONG_INT "cmpwi "
#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \
start_ip, post_commit_offset, abort_ip) \
@@ -125,7 +131,7 @@ do { \
RSEQ_INJECT_ASM(1) \
"lis %%r17, (" __rseq_str(cs_label) ")@ha\n\t" \
"addi %%r17, %%r17, (" __rseq_str(cs_label) ")@l\n\t" \
- "stw %%r17, %[" __rseq_str(rseq_cs) "]\n\t" \
+ RSEQ_STORE_INT(rseq_cs) "%%r17, %[" __rseq_str(rseq_cs) "]\n\t" \
__rseq_str(label) ":\n\t"
#endif /* #ifdef __PPC64__ */
@@ -136,7 +142,7 @@ do { \
#define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \
RSEQ_INJECT_ASM(2) \
- "lwz %%r17, %[" __rseq_str(current_cpu_id) "]\n\t" \
+ RSEQ_LOAD_INT(current_cpu_id) "%%r17, %[" __rseq_str(current_cpu_id) "]\n\t" \
"cmpw cr7, %[" __rseq_str(cpu_id) "], %%r17\n\t" \
"bne- cr7, " __rseq_str(label) "\n\t"
@@ -153,25 +159,25 @@ do { \
* RSEQ_ASM_OP_* (else): doesn't have hard-code registers(unless cr7)
*/
#define RSEQ_ASM_OP_CMPEQ(var, expect, label) \
- LOAD_WORD "%%r17, %[" __rseq_str(var) "]\n\t" \
- CMP_WORD "cr7, %%r17, %[" __rseq_str(expect) "]\n\t" \
+ RSEQ_LOAD_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t" \
+ RSEQ_CMP_LONG "cr7, %%r17, %[" __rseq_str(expect) "]\n\t" \
"bne- cr7, " __rseq_str(label) "\n\t"
#define RSEQ_ASM_OP_CMPNE(var, expectnot, label) \
- LOAD_WORD "%%r17, %[" __rseq_str(var) "]\n\t" \
- CMP_WORD "cr7, %%r17, %[" __rseq_str(expectnot) "]\n\t" \
+ RSEQ_LOAD_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t" \
+ RSEQ_CMP_LONG "cr7, %%r17, %[" __rseq_str(expectnot) "]\n\t" \
"beq- cr7, " __rseq_str(label) "\n\t"
#define RSEQ_ASM_OP_STORE(value, var) \
- STORE_WORD "%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n\t"
+ RSEQ_STORE_LONG(var) "%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n\t"
/* Load @var to r17 */
#define RSEQ_ASM_OP_R_LOAD(var) \
- LOAD_WORD "%%r17, %[" __rseq_str(var) "]\n\t"
+ RSEQ_LOAD_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t"
/* Store r17 to @var */
#define RSEQ_ASM_OP_R_STORE(var) \
- STORE_WORD "%%r17, %[" __rseq_str(var) "]\n\t"
+ RSEQ_STORE_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t"
/* Add @count to r17 */
#define RSEQ_ASM_OP_R_ADD(count) \
@@ -179,11 +185,11 @@ do { \
/* Load (r17 + voffp) to r17 */
#define RSEQ_ASM_OP_R_LOADX(voffp) \
- LOADX_WORD "%%r17, %[" __rseq_str(voffp) "], %%r17\n\t"
+ RSEQ_LOADX_LONG "%%r17, %[" __rseq_str(voffp) "], %%r17\n\t"
/* TODO: implement a faster memcpy. */
#define RSEQ_ASM_OP_R_MEMCPY() \
- "cmpdi %%r19, 0\n\t" \
+ RSEQ_CMP_LONG_INT "%%r19, 0\n\t" \
"beq 333f\n\t" \
"addi %%r20, %%r20, -1\n\t" \
"addi %%r21, %%r21, -1\n\t" \
@@ -191,16 +197,16 @@ do { \
"lbzu %%r18, 1(%%r20)\n\t" \
"stbu %%r18, 1(%%r21)\n\t" \
"addi %%r19, %%r19, -1\n\t" \
- "cmpdi %%r19, 0\n\t" \
+ RSEQ_CMP_LONG_INT "%%r19, 0\n\t" \
"bne 222b\n\t" \
"333:\n\t" \
#define RSEQ_ASM_OP_R_FINAL_STORE(var, post_commit_label) \
- STORE_WORD "%%r17, %[" __rseq_str(var) "]\n\t" \
+ RSEQ_STORE_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t" \
__rseq_str(post_commit_label) ":\n\t"
#define RSEQ_ASM_OP_FINAL_STORE(value, var, post_commit_label) \
- STORE_WORD "%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n\t" \
+ RSEQ_STORE_LONG(var) "%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n\t" \
__rseq_str(post_commit_label) ":\n\t"
static inline __attribute__((always_inline))
@@ -235,8 +241,8 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "m" (*v),
[expect] "r" (expect),
[newv] "r" (newv)
@@ -248,23 +254,28 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
- off_t voffp, intptr_t *load, int cpu)
+ long voffp, intptr_t *load, int cpu)
{
RSEQ_INJECT_C(9)
@@ -301,8 +312,8 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expectnot] "r" (expectnot),
@@ -316,16 +327,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -359,8 +375,8 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[count] "r" (count)
@@ -372,12 +388,15 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
, error1
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
#endif
}
@@ -419,8 +438,8 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -436,16 +455,21 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -489,8 +513,8 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -506,16 +530,21 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -560,8 +589,8 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* cmp2 input */
[v2] "m" (*v2),
[expect2] "r" (expect2),
@@ -577,18 +606,24 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
, error1, error2, error3
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("1st expected value comparison failed");
error3:
+ rseq_after_asm_goto();
rseq_bug("2nd expected value comparison failed");
#endif
}
@@ -635,8 +670,8 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expect] "r" (expect),
@@ -653,16 +688,21 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -711,8 +751,8 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expect] "r" (expect),
@@ -729,23 +769,23 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
-#undef STORE_WORD
-#undef LOAD_WORD
-#undef LOADX_WORD
-#undef CMP_WORD
-
#endif /* !RSEQ_SKIP_FASTPATH */
diff --git a/tools/testing/selftests/rseq/rseq-s390.h b/tools/testing/selftests/rseq/rseq-s390.h
index 8ef94ad1cbb4..4e6dc5f0cb42 100644
--- a/tools/testing/selftests/rseq/rseq-s390.h
+++ b/tools/testing/selftests/rseq/rseq-s390.h
@@ -165,8 +165,8 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
[v] "m" (*v),
[expect] "r" (expect),
[newv] "r" (newv)
@@ -178,16 +178,21 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -198,7 +203,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
*/
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
- off_t voffp, intptr_t *load, int cpu)
+ long voffp, intptr_t *load, int cpu)
{
RSEQ_INJECT_C(9)
@@ -233,8 +238,8 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expectnot] "r" (expectnot),
@@ -248,16 +253,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -288,8 +298,8 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[count] "r" (count)
@@ -301,12 +311,15 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
, error1
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
#endif
}
@@ -347,8 +360,8 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -364,16 +377,21 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -426,8 +444,8 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* cmp2 input */
[v2] "m" (*v2),
[expect2] "r" (expect2),
@@ -443,18 +461,24 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
, error1, error2, error3
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("1st expected value comparison failed");
error3:
+ rseq_after_asm_goto();
rseq_bug("2nd expected value comparison failed");
#endif
}
@@ -534,8 +558,8 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
#endif
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [current_cpu_id] "m" (__rseq_abi.cpu_id),
- [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
+ [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
/* final store input */
[v] "m" (*v),
[expect] "r" (expect),
@@ -555,16 +579,21 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
diff --git a/tools/testing/selftests/rseq/rseq-skip.h b/tools/testing/selftests/rseq/rseq-skip.h
index 72750b5905a9..7b53dac1fcdd 100644
--- a/tools/testing/selftests/rseq/rseq-skip.h
+++ b/tools/testing/selftests/rseq/rseq-skip.h
@@ -13,7 +13,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
- off_t voffp, intptr_t *load, int cpu)
+ long voffp, intptr_t *load, int cpu)
{
return -1;
}
diff --git a/tools/testing/selftests/rseq/rseq-thread-pointer.h b/tools/testing/selftests/rseq/rseq-thread-pointer.h
new file mode 100644
index 000000000000..977c25d758b2
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-thread-pointer.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/*
+ * rseq-thread-pointer.h
+ *
+ * (C) Copyright 2021 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#ifndef _RSEQ_THREAD_POINTER
+#define _RSEQ_THREAD_POINTER
+
+#if defined(__x86_64__) || defined(__i386__)
+#include "rseq-x86-thread-pointer.h"
+#elif defined(__PPC__)
+#include "rseq-ppc-thread-pointer.h"
+#else
+#include "rseq-generic-thread-pointer.h"
+#endif
+
+#endif
diff --git a/tools/testing/selftests/rseq/rseq-x86-thread-pointer.h b/tools/testing/selftests/rseq/rseq-x86-thread-pointer.h
new file mode 100644
index 000000000000..d3133587d996
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-x86-thread-pointer.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/*
+ * rseq-x86-thread-pointer.h
+ *
+ * (C) Copyright 2021 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#ifndef _RSEQ_X86_THREAD_POINTER
+#define _RSEQ_X86_THREAD_POINTER
+
+#include <features.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __GNUC_PREREQ (11, 1)
+static inline void *rseq_thread_pointer(void)
+{
+ return __builtin_thread_pointer();
+}
+#else
+static inline void *rseq_thread_pointer(void)
+{
+ void *__result;
+
+# ifdef __x86_64__
+ __asm__ ("mov %%fs:0, %0" : "=r" (__result));
+# else
+ __asm__ ("mov %%gs:0, %0" : "=r" (__result));
+# endif
+ return __result;
+}
+#endif /* !GCC 11 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tools/testing/selftests/rseq/rseq-x86.h b/tools/testing/selftests/rseq/rseq-x86.h
index 640411518e46..bd01dc41ca13 100644
--- a/tools/testing/selftests/rseq/rseq-x86.h
+++ b/tools/testing/selftests/rseq/rseq-x86.h
@@ -28,6 +28,8 @@
#ifdef __x86_64__
+#define RSEQ_ASM_TP_SEGMENT %%fs
+
#define rseq_smp_mb() \
__asm__ __volatile__ ("lock; addl $0,-128(%%rsp)" ::: "memory", "cc")
#define rseq_smp_rmb() rseq_barrier()
@@ -123,14 +125,14 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpq %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpq %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
#endif
@@ -141,7 +143,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
[v] "m" (*v),
[expect] "r" (expect),
[newv] "r" (newv)
@@ -152,16 +154,21 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -172,7 +179,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
*/
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
- off_t voffp, intptr_t *load, int cpu)
+ long voffp, intptr_t *load, int cpu)
{
RSEQ_INJECT_C(9)
@@ -184,15 +191,15 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movq %[v], %%rbx\n\t"
"cmpq %%rbx, %[expectnot]\n\t"
"je %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"movq %[v], %%rbx\n\t"
"cmpq %%rbx, %[expectnot]\n\t"
"je %l[error2]\n\t"
@@ -207,7 +214,7 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[expectnot] "r" (expectnot),
@@ -220,16 +227,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -245,11 +257,11 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
#endif
/* final store */
"addq %[count], %[v]\n\t"
@@ -258,7 +270,7 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[count] "er" (count)
@@ -269,12 +281,15 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
, error1
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
#endif
}
@@ -286,7 +301,7 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
* *pval += inc;
*/
static inline __attribute__((always_inline))
-int rseq_offset_deref_addv(intptr_t *ptr, off_t off, intptr_t inc, int cpu)
+int rseq_offset_deref_addv(intptr_t *ptr, long off, intptr_t inc, int cpu)
{
RSEQ_INJECT_C(9)
@@ -296,11 +311,11 @@ int rseq_offset_deref_addv(intptr_t *ptr, off_t off, intptr_t inc, int cpu)
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
#endif
/* get p+v */
"movq %[ptr], %%rbx\n\t"
@@ -314,7 +329,7 @@ int rseq_offset_deref_addv(intptr_t *ptr, off_t off, intptr_t inc, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[ptr] "m" (*ptr),
[off] "er" (off),
@@ -351,14 +366,14 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpq %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpq %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
#endif
@@ -372,7 +387,7 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -387,16 +402,21 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -426,8 +446,8 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpq %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
@@ -436,7 +456,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(5)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpq %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
"cmpq %[v2], %[expect2]\n\t"
@@ -449,7 +469,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* cmp2 input */
[v2] "m" (*v2),
[expect2] "r" (expect2),
@@ -464,18 +484,24 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
, error1, error2, error3
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("1st expected value comparison failed");
error3:
+ rseq_after_asm_goto();
rseq_bug("2nd expected value comparison failed");
#endif
}
@@ -500,14 +526,14 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
"movq %[dst], %[rseq_scratch1]\n\t"
"movq %[len], %[rseq_scratch2]\n\t"
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpq %[v], %[expect]\n\t"
"jnz 5f\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 6f)
"cmpq %[v], %[expect]\n\t"
"jnz 7f\n\t"
#endif
@@ -555,7 +581,7 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
#endif
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[expect] "r" (expect),
@@ -574,16 +600,21 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -600,7 +631,9 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
#endif /* !RSEQ_SKIP_FASTPATH */
-#elif __i386__
+#elif defined(__i386__)
+
+#define RSEQ_ASM_TP_SEGMENT %%gs
#define rseq_smp_mb() \
__asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")
@@ -701,14 +734,14 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpl %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpl %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
#endif
@@ -719,7 +752,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
[v] "m" (*v),
[expect] "r" (expect),
[newv] "r" (newv)
@@ -730,16 +763,21 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -750,7 +788,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
*/
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
- off_t voffp, intptr_t *load, int cpu)
+ long voffp, intptr_t *load, int cpu)
{
RSEQ_INJECT_C(9)
@@ -762,15 +800,15 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movl %[v], %%ebx\n\t"
"cmpl %%ebx, %[expectnot]\n\t"
"je %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"movl %[v], %%ebx\n\t"
"cmpl %%ebx, %[expectnot]\n\t"
"je %l[error2]\n\t"
@@ -785,7 +823,7 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[expectnot] "r" (expectnot),
@@ -798,16 +836,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -823,11 +866,11 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
#endif
/* final store */
"addl %[count], %[v]\n\t"
@@ -836,7 +879,7 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[count] "ir" (count)
@@ -847,12 +890,15 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
, error1
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
#endif
}
@@ -872,14 +918,14 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpl %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpl %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
#endif
@@ -894,7 +940,7 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* try store input */
[v2] "m" (*v2),
[newv2] "m" (newv2),
@@ -909,16 +955,21 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -938,15 +989,15 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movl %[expect], %%eax\n\t"
"cmpl %[v], %%eax\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"movl %[expect], %%eax\n\t"
"cmpl %[v], %%eax\n\t"
"jnz %l[error2]\n\t"
@@ -962,7 +1013,7 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -977,16 +1028,21 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
@@ -1008,8 +1064,8 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpl %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
@@ -1018,7 +1074,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(5)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpl %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
"cmpl %[expect2], %[v2]\n\t"
@@ -1032,7 +1088,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* cmp2 input */
[v2] "m" (*v2),
[expect2] "r" (expect2),
@@ -1047,18 +1103,24 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
, error1, error2, error3
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("1st expected value comparison failed");
error3:
+ rseq_after_asm_goto();
rseq_bug("2nd expected value comparison failed");
#endif
}
@@ -1084,15 +1146,15 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
"movl %[dst], %[rseq_scratch1]\n\t"
"movl %[len], %[rseq_scratch2]\n\t"
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movl %[expect], %%eax\n\t"
"cmpl %%eax, %[v]\n\t"
"jnz 5f\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 6f)
"movl %[expect], %%eax\n\t"
"cmpl %%eax, %[v]\n\t"
"jnz 7f\n\t"
@@ -1142,7 +1204,7 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
#endif
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[expect] "m" (expect),
@@ -1161,16 +1223,21 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
@@ -1196,15 +1263,15 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
"movl %[dst], %[rseq_scratch1]\n\t"
"movl %[len], %[rseq_scratch2]\n\t"
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movl %[expect], %%eax\n\t"
"cmpl %%eax, %[v]\n\t"
"jnz 5f\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 6f)
"movl %[expect], %%eax\n\t"
"cmpl %%eax, %[v]\n\t"
"jnz 7f\n\t"
@@ -1255,7 +1322,7 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
#endif
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (&__rseq_abi),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[expect] "m" (expect),
@@ -1274,16 +1341,21 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
, error1, error2
#endif
);
+ rseq_after_asm_goto();
return 0;
abort:
+ rseq_after_asm_goto();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
+ rseq_after_asm_goto();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
+ rseq_after_asm_goto();
rseq_bug("cpu_id comparison failed");
error2:
+ rseq_after_asm_goto();
rseq_bug("expected value comparison failed");
#endif
}
diff --git a/tools/testing/selftests/rseq/rseq.c b/tools/testing/selftests/rseq/rseq.c
index 7159eb777fd3..986b9458efb2 100644
--- a/tools/testing/selftests/rseq/rseq.c
+++ b/tools/testing/selftests/rseq/rseq.c
@@ -26,131 +26,124 @@
#include <assert.h>
#include <signal.h>
#include <limits.h>
+#include <dlfcn.h>
+#include <stddef.h>
+#include "../kselftest.h"
#include "rseq.h"
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+static const ptrdiff_t *libc_rseq_offset_p;
+static const unsigned int *libc_rseq_size_p;
+static const unsigned int *libc_rseq_flags_p;
-__thread volatile struct rseq __rseq_abi = {
- .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
-};
+/* Offset from the thread pointer to the rseq area. */
+ptrdiff_t rseq_offset;
-/*
- * Shared with other libraries. This library may take rseq ownership if it is
- * still 0 when executing the library constructor. Set to 1 by library
- * constructor when handling rseq. Set to 0 in destructor if handling rseq.
- */
-int __rseq_handled;
+/* Size of the registered rseq area. 0 if the registration was
+ unsuccessful. */
+unsigned int rseq_size = -1U;
+
+/* Flags used during rseq registration. */
+unsigned int rseq_flags;
-/* Whether this library have ownership of rseq registration. */
static int rseq_ownership;
-static __thread volatile uint32_t __rseq_refcount;
+static
+__thread struct rseq_abi __rseq_abi __attribute__((tls_model("initial-exec"))) = {
+ .cpu_id = RSEQ_ABI_CPU_ID_UNINITIALIZED,
+};
-static void signal_off_save(sigset_t *oldset)
+static int sys_rseq(struct rseq_abi *rseq_abi, uint32_t rseq_len,
+ int flags, uint32_t sig)
{
- sigset_t set;
- int ret;
-
- sigfillset(&set);
- ret = pthread_sigmask(SIG_BLOCK, &set, oldset);
- if (ret)
- abort();
+ return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
}
-static void signal_restore(sigset_t oldset)
+int rseq_available(void)
{
- int ret;
+ int rc;
- ret = pthread_sigmask(SIG_SETMASK, &oldset, NULL);
- if (ret)
+ rc = sys_rseq(NULL, 0, 0, 0);
+ if (rc != -1)
abort();
-}
-
-static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len,
- int flags, uint32_t sig)
-{
- return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
+ switch (errno) {
+ case ENOSYS:
+ return 0;
+ case EINVAL:
+ return 1;
+ default:
+ abort();
+ }
}
int rseq_register_current_thread(void)
{
- int rc, ret = 0;
- sigset_t oldset;
+ int rc;
- if (!rseq_ownership)
+ if (!rseq_ownership) {
+ /* Treat libc's ownership as a successful registration. */
return 0;
- signal_off_save(&oldset);
- if (__rseq_refcount == UINT_MAX) {
- ret = -1;
- goto end;
- }
- if (__rseq_refcount++)
- goto end;
- rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG);
- if (!rc) {
- assert(rseq_current_cpu_raw() >= 0);
- goto end;
}
- if (errno != EBUSY)
- __rseq_abi.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
- ret = -1;
- __rseq_refcount--;
-end:
- signal_restore(oldset);
- return ret;
+ rc = sys_rseq(&__rseq_abi, sizeof(struct rseq_abi), 0, RSEQ_SIG);
+ if (rc)
+ return -1;
+ assert(rseq_current_cpu_raw() >= 0);
+ return 0;
}
int rseq_unregister_current_thread(void)
{
- int rc, ret = 0;
- sigset_t oldset;
+ int rc;
- if (!rseq_ownership)
+ if (!rseq_ownership) {
+ /* Treat libc's ownership as a successful unregistration. */
return 0;
- signal_off_save(&oldset);
- if (!__rseq_refcount) {
- ret = -1;
- goto end;
}
- if (--__rseq_refcount)
- goto end;
- rc = sys_rseq(&__rseq_abi, sizeof(struct rseq),
- RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
- if (!rc)
- goto end;
- __rseq_refcount = 1;
- ret = -1;
-end:
- signal_restore(oldset);
- return ret;
+ rc = sys_rseq(&__rseq_abi, sizeof(struct rseq_abi), RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
+ if (rc)
+ return -1;
+ return 0;
}
-int32_t rseq_fallback_current_cpu(void)
+static __attribute__((constructor))
+void rseq_init(void)
{
- int32_t cpu;
-
- cpu = sched_getcpu();
- if (cpu < 0) {
- perror("sched_getcpu()");
- abort();
+ libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
+ libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
+ libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
+ if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p) {
+ /* rseq registration owned by glibc */
+ rseq_offset = *libc_rseq_offset_p;
+ rseq_size = *libc_rseq_size_p;
+ rseq_flags = *libc_rseq_flags_p;
+ return;
}
- return cpu;
-}
-
-void __attribute__((constructor)) rseq_init(void)
-{
- /* Check whether rseq is handled by another library. */
- if (__rseq_handled)
+ if (!rseq_available())
return;
- __rseq_handled = 1;
rseq_ownership = 1;
+ rseq_offset = (void *)&__rseq_abi - rseq_thread_pointer();
+ rseq_size = sizeof(struct rseq_abi);
+ rseq_flags = 0;
}
-void __attribute__((destructor)) rseq_fini(void)
+static __attribute__((destructor))
+void rseq_exit(void)
{
if (!rseq_ownership)
return;
- __rseq_handled = 0;
+ rseq_offset = 0;
+ rseq_size = -1U;
rseq_ownership = 0;
}
+
+int32_t rseq_fallback_current_cpu(void)
+{
+ int32_t cpu;
+
+ cpu = sched_getcpu();
+ if (cpu < 0) {
+ perror("sched_getcpu()");
+ abort();
+ }
+ return cpu;
+}
diff --git a/tools/testing/selftests/rseq/rseq.h b/tools/testing/selftests/rseq/rseq.h
index 3f63eb362b92..9d850b290c2e 100644
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -16,7 +16,9 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <linux/rseq.h>
+#include <stddef.h>
+#include "rseq-abi.h"
+#include "compiler.h"
/*
* Empty code injection macros, override when testing.
@@ -43,8 +45,20 @@
#define RSEQ_INJECT_FAILED
#endif
-extern __thread volatile struct rseq __rseq_abi;
-extern int __rseq_handled;
+#include "rseq-thread-pointer.h"
+
+/* Offset from the thread pointer to the rseq area. */
+extern ptrdiff_t rseq_offset;
+/* Size of the registered rseq area. 0 if the registration was
+ unsuccessful. */
+extern unsigned int rseq_size;
+/* Flags used during rseq registration. */
+extern unsigned int rseq_flags;
+
+static inline struct rseq_abi *rseq_get_abi(void)
+{
+ return (struct rseq_abi *) ((uintptr_t) rseq_thread_pointer() + rseq_offset);
+}
#define rseq_likely(x) __builtin_expect(!!(x), 1)
#define rseq_unlikely(x) __builtin_expect(!!(x), 0)
@@ -108,7 +122,7 @@ int32_t rseq_fallback_current_cpu(void);
*/
static inline int32_t rseq_current_cpu_raw(void)
{
- return RSEQ_ACCESS_ONCE(__rseq_abi.cpu_id);
+ return RSEQ_ACCESS_ONCE(rseq_get_abi()->cpu_id);
}
/*
@@ -124,7 +138,7 @@ static inline int32_t rseq_current_cpu_raw(void)
*/
static inline uint32_t rseq_cpu_start(void)
{
- return RSEQ_ACCESS_ONCE(__rseq_abi.cpu_id_start);
+ return RSEQ_ACCESS_ONCE(rseq_get_abi()->cpu_id_start);
}
static inline uint32_t rseq_current_cpu(void)
@@ -139,11 +153,7 @@ static inline uint32_t rseq_current_cpu(void)
static inline void rseq_clear_rseq_cs(void)
{
-#ifdef __LP64__
- __rseq_abi.rseq_cs.ptr = 0;
-#else
- __rseq_abi.rseq_cs.ptr.ptr32 = 0;
-#endif
+ RSEQ_WRITE_ONCE(rseq_get_abi()->rseq_cs.arch.ptr, 0);
}
/*
^ permalink raw reply related [relevance 1%]
* [PATCH 5.18 008/102] net: phy: Dont trigger state machine while in suspend
@ 2022-07-05 11:57 11% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-07-05 11:57 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Marek Szyprowski, Lukas Wunner,
Rafael J. Wysocki, Andrew Lunn, Jakub Kicinski
From: Lukas Wunner <lukas@wunner.de>
commit 1758bde2e4aa5ff188d53e7d9d388bbb7e12eebb upstream.
Upon system sleep, mdio_bus_phy_suspend() stops the phy_state_machine(),
but subsequent interrupts may retrigger it:
They may have been left enabled to facilitate wakeup and are not
quiesced until the ->suspend_noirq() phase. Unwanted interrupts may
hence occur between mdio_bus_phy_suspend() and dpm_suspend_noirq(),
as well as between dpm_resume_noirq() and mdio_bus_phy_resume().
Retriggering the phy_state_machine() through an interrupt is not only
undesirable for the reason given in mdio_bus_phy_suspend() (freezing it
midway with phydev->lock held), but also because the PHY may be
inaccessible after it's suspended: Accesses to USB-attached PHYs are
blocked once usb_suspend_both() clears the can_submit flag and PHYs on
PCI network cards may become inaccessible upon suspend as well.
Amend phy_interrupt() to avoid triggering the state machine if the PHY
is suspended. Signal wakeup instead if the attached net_device or its
parent has been configured as a wakeup source. (Those conditions are
identical to mdio_bus_phy_may_suspend().) Postpone handling of the
interrupt until the PHY has resumed.
Before stopping the phy_state_machine() in mdio_bus_phy_suspend(),
wait for a concurrent phy_interrupt() to run to completion. That is
necessary because phy_interrupt() may have checked the PHY's suspend
status before the system sleep transition commenced and it may thus
retrigger the state machine after it was stopped.
Likewise, after re-enabling interrupt handling in mdio_bus_phy_resume(),
wait for a concurrent phy_interrupt() to complete to ensure that
interrupts which it postponed are properly rerun.
The issue was exposed by commit 1ce8b37241ed ("usbnet: smsc95xx: Forward
PHY interrupts to PHY driver to avoid polling"), but has existed since
forever.
Fixes: 541cd3ee00a4 ("phylib: Fix deadlock on resume")
Link: https://lore.kernel.org/netdev/a5315a8a-32c2-962f-f696-de9a26d30091@samsung.com/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: stable@vger.kernel.org # v2.6.33+
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/b7f386d04e9b5b0e2738f0125743e30676f309ef.1656410895.git.lukas@wunner.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/phy/phy.c | 23 +++++++++++++++++++++++
drivers/net/phy/phy_device.c | 23 +++++++++++++++++++++++
include/linux/phy.h | 6 ++++++
3 files changed, 52 insertions(+)
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -972,6 +973,28 @@ static irqreturn_t phy_interrupt(int irq
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -277,6 +277,15 @@ static __maybe_unused int mdio_bus_phy_s
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -314,6 +323,20 @@ static __maybe_unused int mdio_bus_phy_r
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -571,6 +571,10 @@ struct macsec_ops;
* @mdix: Current crossover
* @mdix_ctrl: User setting of crossover
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -625,6 +629,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
^ permalink raw reply [relevance 11%]
* [PATCH 5.15 07/98] net: phy: Dont trigger state machine while in suspend
@ 2022-07-05 11:57 11% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-07-05 11:57 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Marek Szyprowski, Lukas Wunner,
Rafael J. Wysocki, Andrew Lunn, Jakub Kicinski
From: Lukas Wunner <lukas@wunner.de>
commit 1758bde2e4aa5ff188d53e7d9d388bbb7e12eebb upstream.
Upon system sleep, mdio_bus_phy_suspend() stops the phy_state_machine(),
but subsequent interrupts may retrigger it:
They may have been left enabled to facilitate wakeup and are not
quiesced until the ->suspend_noirq() phase. Unwanted interrupts may
hence occur between mdio_bus_phy_suspend() and dpm_suspend_noirq(),
as well as between dpm_resume_noirq() and mdio_bus_phy_resume().
Retriggering the phy_state_machine() through an interrupt is not only
undesirable for the reason given in mdio_bus_phy_suspend() (freezing it
midway with phydev->lock held), but also because the PHY may be
inaccessible after it's suspended: Accesses to USB-attached PHYs are
blocked once usb_suspend_both() clears the can_submit flag and PHYs on
PCI network cards may become inaccessible upon suspend as well.
Amend phy_interrupt() to avoid triggering the state machine if the PHY
is suspended. Signal wakeup instead if the attached net_device or its
parent has been configured as a wakeup source. (Those conditions are
identical to mdio_bus_phy_may_suspend().) Postpone handling of the
interrupt until the PHY has resumed.
Before stopping the phy_state_machine() in mdio_bus_phy_suspend(),
wait for a concurrent phy_interrupt() to run to completion. That is
necessary because phy_interrupt() may have checked the PHY's suspend
status before the system sleep transition commenced and it may thus
retrigger the state machine after it was stopped.
Likewise, after re-enabling interrupt handling in mdio_bus_phy_resume(),
wait for a concurrent phy_interrupt() to complete to ensure that
interrupts which it postponed are properly rerun.
The issue was exposed by commit 1ce8b37241ed ("usbnet: smsc95xx: Forward
PHY interrupts to PHY driver to avoid polling"), but has existed since
forever.
Fixes: 541cd3ee00a4 ("phylib: Fix deadlock on resume")
Link: https://lore.kernel.org/netdev/a5315a8a-32c2-962f-f696-de9a26d30091@samsung.com/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: stable@vger.kernel.org # v2.6.33+
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/b7f386d04e9b5b0e2738f0125743e30676f309ef.1656410895.git.lukas@wunner.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/phy/phy.c | 23 +++++++++++++++++++++++
drivers/net/phy/phy_device.c | 23 +++++++++++++++++++++++
include/linux/phy.h | 6 ++++++
3 files changed, 52 insertions(+)
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -972,6 +973,28 @@ static irqreturn_t phy_interrupt(int irq
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -277,6 +277,15 @@ static __maybe_unused int mdio_bus_phy_s
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -314,6 +323,20 @@ static __maybe_unused int mdio_bus_phy_r
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -536,6 +536,10 @@ struct macsec_ops;
* @mdix: Current crossover
* @mdix_ctrl: User setting of crossover
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -590,6 +594,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
^ permalink raw reply [relevance 11%]
* FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 5.4-stable tree
@ 2022-07-04 7:44 11% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2022-07-04 7:44 UTC (permalink / raw)
To: lukas, andrew, kuba, m.szyprowski, rafael.j.wysocki; +Cc: stable
The patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1758bde2e4aa5ff188d53e7d9d388bbb7e12eebb Mon Sep 17 00:00:00 2001
From: Lukas Wunner <lukas@wunner.de>
Date: Tue, 28 Jun 2022 12:15:08 +0200
Subject: [PATCH] net: phy: Don't trigger state machine while in suspend
Upon system sleep, mdio_bus_phy_suspend() stops the phy_state_machine(),
but subsequent interrupts may retrigger it:
They may have been left enabled to facilitate wakeup and are not
quiesced until the ->suspend_noirq() phase. Unwanted interrupts may
hence occur between mdio_bus_phy_suspend() and dpm_suspend_noirq(),
as well as between dpm_resume_noirq() and mdio_bus_phy_resume().
Retriggering the phy_state_machine() through an interrupt is not only
undesirable for the reason given in mdio_bus_phy_suspend() (freezing it
midway with phydev->lock held), but also because the PHY may be
inaccessible after it's suspended: Accesses to USB-attached PHYs are
blocked once usb_suspend_both() clears the can_submit flag and PHYs on
PCI network cards may become inaccessible upon suspend as well.
Amend phy_interrupt() to avoid triggering the state machine if the PHY
is suspended. Signal wakeup instead if the attached net_device or its
parent has been configured as a wakeup source. (Those conditions are
identical to mdio_bus_phy_may_suspend().) Postpone handling of the
interrupt until the PHY has resumed.
Before stopping the phy_state_machine() in mdio_bus_phy_suspend(),
wait for a concurrent phy_interrupt() to run to completion. That is
necessary because phy_interrupt() may have checked the PHY's suspend
status before the system sleep transition commenced and it may thus
retrigger the state machine after it was stopped.
Likewise, after re-enabling interrupt handling in mdio_bus_phy_resume(),
wait for a concurrent phy_interrupt() to complete to ensure that
interrupts which it postponed are properly rerun.
The issue was exposed by commit 1ce8b37241ed ("usbnet: smsc95xx: Forward
PHY interrupts to PHY driver to avoid polling"), but has existed since
forever.
Fixes: 541cd3ee00a4 ("phylib: Fix deadlock on resume")
Link: https://lore.kernel.org/netdev/a5315a8a-32c2-962f-f696-de9a26d30091@samsung.com/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: stable@vger.kernel.org # v2.6.33+
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/b7f386d04e9b5b0e2738f0125743e30676f309ef.1656410895.git.lukas@wunner.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef62f357b76d..8d3ee3a6495b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 431a8719c635..46acddd865a7 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -315,6 +324,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 508f1149665b..b09f7d36cff2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -572,6 +572,10 @@ struct macsec_ops;
* @mdix_ctrl: User setting of crossover
* @pma_extable: Cached value of PMA/PMD Extended Abilities Register
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -626,6 +630,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
^ permalink raw reply related [relevance 11%]
* FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 5.10-stable tree
@ 2022-07-04 7:44 11% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2022-07-04 7:44 UTC (permalink / raw)
To: lukas, andrew, kuba, m.szyprowski, rafael.j.wysocki; +Cc: stable
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1758bde2e4aa5ff188d53e7d9d388bbb7e12eebb Mon Sep 17 00:00:00 2001
From: Lukas Wunner <lukas@wunner.de>
Date: Tue, 28 Jun 2022 12:15:08 +0200
Subject: [PATCH] net: phy: Don't trigger state machine while in suspend
Upon system sleep, mdio_bus_phy_suspend() stops the phy_state_machine(),
but subsequent interrupts may retrigger it:
They may have been left enabled to facilitate wakeup and are not
quiesced until the ->suspend_noirq() phase. Unwanted interrupts may
hence occur between mdio_bus_phy_suspend() and dpm_suspend_noirq(),
as well as between dpm_resume_noirq() and mdio_bus_phy_resume().
Retriggering the phy_state_machine() through an interrupt is not only
undesirable for the reason given in mdio_bus_phy_suspend() (freezing it
midway with phydev->lock held), but also because the PHY may be
inaccessible after it's suspended: Accesses to USB-attached PHYs are
blocked once usb_suspend_both() clears the can_submit flag and PHYs on
PCI network cards may become inaccessible upon suspend as well.
Amend phy_interrupt() to avoid triggering the state machine if the PHY
is suspended. Signal wakeup instead if the attached net_device or its
parent has been configured as a wakeup source. (Those conditions are
identical to mdio_bus_phy_may_suspend().) Postpone handling of the
interrupt until the PHY has resumed.
Before stopping the phy_state_machine() in mdio_bus_phy_suspend(),
wait for a concurrent phy_interrupt() to run to completion. That is
necessary because phy_interrupt() may have checked the PHY's suspend
status before the system sleep transition commenced and it may thus
retrigger the state machine after it was stopped.
Likewise, after re-enabling interrupt handling in mdio_bus_phy_resume(),
wait for a concurrent phy_interrupt() to complete to ensure that
interrupts which it postponed are properly rerun.
The issue was exposed by commit 1ce8b37241ed ("usbnet: smsc95xx: Forward
PHY interrupts to PHY driver to avoid polling"), but has existed since
forever.
Fixes: 541cd3ee00a4 ("phylib: Fix deadlock on resume")
Link: https://lore.kernel.org/netdev/a5315a8a-32c2-962f-f696-de9a26d30091@samsung.com/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: stable@vger.kernel.org # v2.6.33+
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/b7f386d04e9b5b0e2738f0125743e30676f309ef.1656410895.git.lukas@wunner.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef62f357b76d..8d3ee3a6495b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 431a8719c635..46acddd865a7 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -315,6 +324,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 508f1149665b..b09f7d36cff2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -572,6 +572,10 @@ struct macsec_ops;
* @mdix_ctrl: User setting of crossover
* @pma_extable: Cached value of PMA/PMD Extended Abilities Register
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -626,6 +630,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
^ permalink raw reply related [relevance 11%]
* FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 5.4-stable tree
@ 2022-07-04 7:36 11% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2022-07-04 7:36 UTC (permalink / raw)
To: lukas, andrew, kuba, m.szyprowski, rafael.j.wysocki; +Cc: stable
The patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1758bde2e4aa5ff188d53e7d9d388bbb7e12eebb Mon Sep 17 00:00:00 2001
From: Lukas Wunner <lukas@wunner.de>
Date: Tue, 28 Jun 2022 12:15:08 +0200
Subject: [PATCH] net: phy: Don't trigger state machine while in suspend
Upon system sleep, mdio_bus_phy_suspend() stops the phy_state_machine(),
but subsequent interrupts may retrigger it:
They may have been left enabled to facilitate wakeup and are not
quiesced until the ->suspend_noirq() phase. Unwanted interrupts may
hence occur between mdio_bus_phy_suspend() and dpm_suspend_noirq(),
as well as between dpm_resume_noirq() and mdio_bus_phy_resume().
Retriggering the phy_state_machine() through an interrupt is not only
undesirable for the reason given in mdio_bus_phy_suspend() (freezing it
midway with phydev->lock held), but also because the PHY may be
inaccessible after it's suspended: Accesses to USB-attached PHYs are
blocked once usb_suspend_both() clears the can_submit flag and PHYs on
PCI network cards may become inaccessible upon suspend as well.
Amend phy_interrupt() to avoid triggering the state machine if the PHY
is suspended. Signal wakeup instead if the attached net_device or its
parent has been configured as a wakeup source. (Those conditions are
identical to mdio_bus_phy_may_suspend().) Postpone handling of the
interrupt until the PHY has resumed.
Before stopping the phy_state_machine() in mdio_bus_phy_suspend(),
wait for a concurrent phy_interrupt() to run to completion. That is
necessary because phy_interrupt() may have checked the PHY's suspend
status before the system sleep transition commenced and it may thus
retrigger the state machine after it was stopped.
Likewise, after re-enabling interrupt handling in mdio_bus_phy_resume(),
wait for a concurrent phy_interrupt() to complete to ensure that
interrupts which it postponed are properly rerun.
The issue was exposed by commit 1ce8b37241ed ("usbnet: smsc95xx: Forward
PHY interrupts to PHY driver to avoid polling"), but has existed since
forever.
Fixes: 541cd3ee00a4 ("phylib: Fix deadlock on resume")
Link: https://lore.kernel.org/netdev/a5315a8a-32c2-962f-f696-de9a26d30091@samsung.com/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: stable@vger.kernel.org # v2.6.33+
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/b7f386d04e9b5b0e2738f0125743e30676f309ef.1656410895.git.lukas@wunner.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef62f357b76d..8d3ee3a6495b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 431a8719c635..46acddd865a7 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -315,6 +324,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 508f1149665b..b09f7d36cff2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -572,6 +572,10 @@ struct macsec_ops;
* @mdix_ctrl: User setting of crossover
* @pma_extable: Cached value of PMA/PMD Extended Abilities Register
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -626,6 +630,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
^ permalink raw reply related [relevance 11%]
* FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 4.19-stable tree
@ 2022-07-04 7:36 11% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2022-07-04 7:36 UTC (permalink / raw)
To: lukas, andrew, kuba, m.szyprowski, rafael.j.wysocki; +Cc: stable
The patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1758bde2e4aa5ff188d53e7d9d388bbb7e12eebb Mon Sep 17 00:00:00 2001
From: Lukas Wunner <lukas@wunner.de>
Date: Tue, 28 Jun 2022 12:15:08 +0200
Subject: [PATCH] net: phy: Don't trigger state machine while in suspend
Upon system sleep, mdio_bus_phy_suspend() stops the phy_state_machine(),
but subsequent interrupts may retrigger it:
They may have been left enabled to facilitate wakeup and are not
quiesced until the ->suspend_noirq() phase. Unwanted interrupts may
hence occur between mdio_bus_phy_suspend() and dpm_suspend_noirq(),
as well as between dpm_resume_noirq() and mdio_bus_phy_resume().
Retriggering the phy_state_machine() through an interrupt is not only
undesirable for the reason given in mdio_bus_phy_suspend() (freezing it
midway with phydev->lock held), but also because the PHY may be
inaccessible after it's suspended: Accesses to USB-attached PHYs are
blocked once usb_suspend_both() clears the can_submit flag and PHYs on
PCI network cards may become inaccessible upon suspend as well.
Amend phy_interrupt() to avoid triggering the state machine if the PHY
is suspended. Signal wakeup instead if the attached net_device or its
parent has been configured as a wakeup source. (Those conditions are
identical to mdio_bus_phy_may_suspend().) Postpone handling of the
interrupt until the PHY has resumed.
Before stopping the phy_state_machine() in mdio_bus_phy_suspend(),
wait for a concurrent phy_interrupt() to run to completion. That is
necessary because phy_interrupt() may have checked the PHY's suspend
status before the system sleep transition commenced and it may thus
retrigger the state machine after it was stopped.
Likewise, after re-enabling interrupt handling in mdio_bus_phy_resume(),
wait for a concurrent phy_interrupt() to complete to ensure that
interrupts which it postponed are properly rerun.
The issue was exposed by commit 1ce8b37241ed ("usbnet: smsc95xx: Forward
PHY interrupts to PHY driver to avoid polling"), but has existed since
forever.
Fixes: 541cd3ee00a4 ("phylib: Fix deadlock on resume")
Link: https://lore.kernel.org/netdev/a5315a8a-32c2-962f-f696-de9a26d30091@samsung.com/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: stable@vger.kernel.org # v2.6.33+
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/b7f386d04e9b5b0e2738f0125743e30676f309ef.1656410895.git.lukas@wunner.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef62f357b76d..8d3ee3a6495b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 431a8719c635..46acddd865a7 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -315,6 +324,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 508f1149665b..b09f7d36cff2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -572,6 +572,10 @@ struct macsec_ops;
* @mdix_ctrl: User setting of crossover
* @pma_extable: Cached value of PMA/PMD Extended Abilities Register
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -626,6 +630,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
^ permalink raw reply related [relevance 11%]
* FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 4.14-stable tree
@ 2022-07-04 7:36 11% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2022-07-04 7:36 UTC (permalink / raw)
To: lukas, andrew, kuba, m.szyprowski, rafael.j.wysocki; +Cc: stable
The patch below does not apply to the 4.14-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1758bde2e4aa5ff188d53e7d9d388bbb7e12eebb Mon Sep 17 00:00:00 2001
From: Lukas Wunner <lukas@wunner.de>
Date: Tue, 28 Jun 2022 12:15:08 +0200
Subject: [PATCH] net: phy: Don't trigger state machine while in suspend
Upon system sleep, mdio_bus_phy_suspend() stops the phy_state_machine(),
but subsequent interrupts may retrigger it:
They may have been left enabled to facilitate wakeup and are not
quiesced until the ->suspend_noirq() phase. Unwanted interrupts may
hence occur between mdio_bus_phy_suspend() and dpm_suspend_noirq(),
as well as between dpm_resume_noirq() and mdio_bus_phy_resume().
Retriggering the phy_state_machine() through an interrupt is not only
undesirable for the reason given in mdio_bus_phy_suspend() (freezing it
midway with phydev->lock held), but also because the PHY may be
inaccessible after it's suspended: Accesses to USB-attached PHYs are
blocked once usb_suspend_both() clears the can_submit flag and PHYs on
PCI network cards may become inaccessible upon suspend as well.
Amend phy_interrupt() to avoid triggering the state machine if the PHY
is suspended. Signal wakeup instead if the attached net_device or its
parent has been configured as a wakeup source. (Those conditions are
identical to mdio_bus_phy_may_suspend().) Postpone handling of the
interrupt until the PHY has resumed.
Before stopping the phy_state_machine() in mdio_bus_phy_suspend(),
wait for a concurrent phy_interrupt() to run to completion. That is
necessary because phy_interrupt() may have checked the PHY's suspend
status before the system sleep transition commenced and it may thus
retrigger the state machine after it was stopped.
Likewise, after re-enabling interrupt handling in mdio_bus_phy_resume(),
wait for a concurrent phy_interrupt() to complete to ensure that
interrupts which it postponed are properly rerun.
The issue was exposed by commit 1ce8b37241ed ("usbnet: smsc95xx: Forward
PHY interrupts to PHY driver to avoid polling"), but has existed since
forever.
Fixes: 541cd3ee00a4 ("phylib: Fix deadlock on resume")
Link: https://lore.kernel.org/netdev/a5315a8a-32c2-962f-f696-de9a26d30091@samsung.com/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: stable@vger.kernel.org # v2.6.33+
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/b7f386d04e9b5b0e2738f0125743e30676f309ef.1656410895.git.lukas@wunner.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef62f357b76d..8d3ee3a6495b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 431a8719c635..46acddd865a7 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -315,6 +324,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 508f1149665b..b09f7d36cff2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -572,6 +572,10 @@ struct macsec_ops;
* @mdix_ctrl: User setting of crossover
* @pma_extable: Cached value of PMA/PMD Extended Abilities Register
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -626,6 +630,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
^ permalink raw reply related [relevance 11%]
* FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 4.9-stable tree
@ 2022-07-04 7:36 11% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2022-07-04 7:36 UTC (permalink / raw)
To: lukas, andrew, kuba, m.szyprowski, rafael.j.wysocki; +Cc: stable
The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1758bde2e4aa5ff188d53e7d9d388bbb7e12eebb Mon Sep 17 00:00:00 2001
From: Lukas Wunner <lukas@wunner.de>
Date: Tue, 28 Jun 2022 12:15:08 +0200
Subject: [PATCH] net: phy: Don't trigger state machine while in suspend
Upon system sleep, mdio_bus_phy_suspend() stops the phy_state_machine(),
but subsequent interrupts may retrigger it:
They may have been left enabled to facilitate wakeup and are not
quiesced until the ->suspend_noirq() phase. Unwanted interrupts may
hence occur between mdio_bus_phy_suspend() and dpm_suspend_noirq(),
as well as between dpm_resume_noirq() and mdio_bus_phy_resume().
Retriggering the phy_state_machine() through an interrupt is not only
undesirable for the reason given in mdio_bus_phy_suspend() (freezing it
midway with phydev->lock held), but also because the PHY may be
inaccessible after it's suspended: Accesses to USB-attached PHYs are
blocked once usb_suspend_both() clears the can_submit flag and PHYs on
PCI network cards may become inaccessible upon suspend as well.
Amend phy_interrupt() to avoid triggering the state machine if the PHY
is suspended. Signal wakeup instead if the attached net_device or its
parent has been configured as a wakeup source. (Those conditions are
identical to mdio_bus_phy_may_suspend().) Postpone handling of the
interrupt until the PHY has resumed.
Before stopping the phy_state_machine() in mdio_bus_phy_suspend(),
wait for a concurrent phy_interrupt() to run to completion. That is
necessary because phy_interrupt() may have checked the PHY's suspend
status before the system sleep transition commenced and it may thus
retrigger the state machine after it was stopped.
Likewise, after re-enabling interrupt handling in mdio_bus_phy_resume(),
wait for a concurrent phy_interrupt() to complete to ensure that
interrupts which it postponed are properly rerun.
The issue was exposed by commit 1ce8b37241ed ("usbnet: smsc95xx: Forward
PHY interrupts to PHY driver to avoid polling"), but has existed since
forever.
Fixes: 541cd3ee00a4 ("phylib: Fix deadlock on resume")
Link: https://lore.kernel.org/netdev/a5315a8a-32c2-962f-f696-de9a26d30091@samsung.com/
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: stable@vger.kernel.org # v2.6.33+
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/b7f386d04e9b5b0e2738f0125743e30676f309ef.1656410895.git.lukas@wunner.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef62f357b76d..8d3ee3a6495b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
+#include <linux/suspend.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
@@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
struct phy_driver *drv = phydev->drv;
irqreturn_t ret;
+ /* Wakeup interrupts may occur during a system sleep transition.
+ * Postpone handling until the PHY has resumed.
+ */
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ struct net_device *netdev = phydev->attached_dev;
+
+ if (netdev) {
+ struct device *parent = netdev->dev.parent;
+
+ if (netdev->wol_enabled)
+ pm_system_wakeup();
+ else if (device_may_wakeup(&netdev->dev))
+ pm_wakeup_dev_event(&netdev->dev, 0, true);
+ else if (parent && device_may_wakeup(parent))
+ pm_wakeup_dev_event(parent, 0, true);
+ }
+
+ phydev->irq_rerun = 1;
+ disable_irq_nosync(irq);
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&phydev->lock);
ret = drv->handle_interrupt(phydev);
mutex_unlock(&phydev->lock);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 431a8719c635..46acddd865a7 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (phydev->mac_managed_pm)
return 0;
+ /* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 1;
+ synchronize_irq(phydev->irq);
+ }
+
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -315,6 +324,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
if (ret < 0)
return ret;
no_resume:
+ if (phy_interrupt_is_valid(phydev)) {
+ phydev->irq_suspended = 0;
+ synchronize_irq(phydev->irq);
+
+ /* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = 0;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ }
+
if (phydev->attached_dev && phydev->adjust_link)
phy_start_machine(phydev);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 508f1149665b..b09f7d36cff2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -572,6 +572,10 @@ struct macsec_ops;
* @mdix_ctrl: User setting of crossover
* @pma_extable: Cached value of PMA/PMD Extended Abilities Register
* @interrupts: Flag interrupts have been enabled
+ * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
+ * handling shall be postponed until PHY has resumed
+ * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
+ * requiring a rerun of the interrupt handler after resume
* @interface: enum phy_interface_t value
* @skb: Netlink message for cable diagnostics
* @nest: Netlink nest used for cable diagnostics
@@ -626,6 +630,8 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
+ unsigned irq_suspended:1;
+ unsigned irq_rerun:1;
enum phy_state state;
^ permalink raw reply related [relevance 11%]
* [PATCH 5.15 040/106] gpio: dwapb: Dont print error on -EPROBE_DEFER
@ 2022-06-20 12:50 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-20 12:50 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Serge Semin, Andy Shevchenko,
Bartosz Golaszewski, Sasha Levin
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
[ Upstream commit 77006f6edc0e0f58617eb25e53731f78641e820d ]
Currently if the APB or Debounce clocks aren't yet ready to be requested
the DW GPIO driver will correctly handle that by deferring the probe
procedure, but the error is still printed to the system log. It needlessly
pollutes the log since there was no real error but a request to postpone
the clock request procedure since the clocks subsystem hasn't been fully
initialized yet. Let's fix that by using the dev_err_probe method to print
the APB/clock request error status. It will correctly handle the deferred
probe situation and print the error if it actually happens.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpio/gpio-dwapb.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index f98fa33e1679..e981e7a46fc1 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -653,10 +653,9 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
gpio->clks[1].id = "db";
err = devm_clk_bulk_get_optional(gpio->dev, DWAPB_NR_CLOCKS,
gpio->clks);
- if (err) {
- dev_err(gpio->dev, "Cannot get APB/Debounce clocks\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(gpio->dev, err,
+ "Cannot get APB/Debounce clocks\n");
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
if (err) {
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH 5.10 33/84] gpio: dwapb: Dont print error on -EPROBE_DEFER
@ 2022-06-20 12:50 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-20 12:50 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Serge Semin, Andy Shevchenko,
Bartosz Golaszewski, Sasha Levin
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
[ Upstream commit 77006f6edc0e0f58617eb25e53731f78641e820d ]
Currently if the APB or Debounce clocks aren't yet ready to be requested
the DW GPIO driver will correctly handle that by deferring the probe
procedure, but the error is still printed to the system log. It needlessly
pollutes the log since there was no real error but a request to postpone
the clock request procedure since the clocks subsystem hasn't been fully
initialized yet. Let's fix that by using the dev_err_probe method to print
the APB/clock request error status. It will correctly handle the deferred
probe situation and print the error if it actually happens.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpio/gpio-dwapb.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 4275c18a097a..ea2e2618b794 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -646,10 +646,9 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
gpio->clks[1].id = "db";
err = devm_clk_bulk_get_optional(gpio->dev, DWAPB_NR_CLOCKS,
gpio->clks);
- if (err) {
- dev_err(gpio->dev, "Cannot get APB/Debounce clocks\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(gpio->dev, err,
+ "Cannot get APB/Debounce clocks\n");
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
if (err) {
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH 5.18 046/141] gpio: dwapb: Dont print error on -EPROBE_DEFER
@ 2022-06-20 12:49 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-20 12:49 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Serge Semin, Andy Shevchenko,
Bartosz Golaszewski, Sasha Levin
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
[ Upstream commit 77006f6edc0e0f58617eb25e53731f78641e820d ]
Currently if the APB or Debounce clocks aren't yet ready to be requested
the DW GPIO driver will correctly handle that by deferring the probe
procedure, but the error is still printed to the system log. It needlessly
pollutes the log since there was no real error but a request to postpone
the clock request procedure since the clocks subsystem hasn't been fully
initialized yet. Let's fix that by using the dev_err_probe method to print
the APB/clock request error status. It will correctly handle the deferred
probe situation and print the error if it actually happens.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpio/gpio-dwapb.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index b0f3aca61974..9467d695a33e 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -652,10 +652,9 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
gpio->clks[1].id = "db";
err = devm_clk_bulk_get_optional(gpio->dev, DWAPB_NR_CLOCKS,
gpio->clks);
- if (err) {
- dev_err(gpio->dev, "Cannot get APB/Debounce clocks\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(gpio->dev, err,
+ "Cannot get APB/Debounce clocks\n");
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
if (err) {
--
2.35.1
^ permalink raw reply related [relevance 5%]
* Linux 5.4.198
@ 2022-06-14 16:49 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-14 16:49 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.4.198 kernel.
All users of the 5.4 kernel series must upgrade.
The updated 5.4.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.4.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/ABI/testing/sysfs-ata | 11
Documentation/conf.py | 2
Documentation/devicetree/bindings/gpio/gpio-altera.txt | 5
Documentation/hwmon/hwmon-kernel-api.rst | 2
Makefile | 2
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22 -
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4
arch/arm/boot/dts/ox820.dtsi | 2
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4
arch/arm/mach-hisi/platsmp.c | 4
arch/arm/mach-mediatek/Kconfig | 1
arch/arm/mach-omap1/clock.c | 2
arch/arm/mach-pxa/cm-x300.c | 8
arch/arm/mach-pxa/magician.c | 2
arch/arm/mach-pxa/tosa.c | 4
arch/arm/mach-vexpress/dcscb.c | 1
arch/arm64/Kconfig.platforms | 1
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2
arch/arm64/kernel/sys_compat.c | 2
arch/arm64/net/bpf_jit_comp.c | 1
arch/m68k/Kconfig.cpu | 2
arch/m68k/Kconfig.machine | 1
arch/m68k/include/asm/pgtable_no.h | 3
arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h | 1
arch/mips/kernel/mips-cpc.c | 1
arch/openrisc/include/asm/timex.h | 1
arch/openrisc/kernel/head.S | 9
arch/powerpc/include/asm/page.h | 7
arch/powerpc/kernel/fadump.c | 8
arch/powerpc/kernel/idle.c | 2
arch/powerpc/kernel/ptrace.c | 21 +
arch/powerpc/perf/isa207-common.c | 3
arch/powerpc/platforms/4xx/cpm.c | 2
arch/powerpc/platforms/8xx/cpm1.c | 1
arch/powerpc/platforms/powernv/opal-fadump.c | 94 +++---
arch/powerpc/platforms/powernv/opal-fadump.h | 10
arch/powerpc/platforms/powernv/ultravisor.c | 1
arch/powerpc/sysdev/dart_iommu.c | 6
arch/powerpc/sysdev/fsl_rio.c | 2
arch/powerpc/sysdev/xics/icp-opal.c | 1
arch/s390/crypto/aes_s390.c | 4
arch/s390/include/asm/preempt.h | 15 -
arch/s390/mm/gmap.c | 14
arch/um/drivers/chan_user.c | 9
arch/um/include/asm/thread_info.h | 2
arch/um/kernel/exec.c | 2
arch/um/kernel/process.c | 2
arch/um/kernel/ptrace.c | 8
arch/um/kernel/signal.c | 4
arch/x86/entry/vdso/vma.c | 2
arch/x86/events/amd/ibs.c | 18 +
arch/x86/events/intel/core.c | 2
arch/x86/include/asm/acenv.h | 14
arch/x86/include/asm/cpufeature.h | 2
arch/x86/include/asm/suspend_32.h | 2
arch/x86/include/asm/suspend_64.h | 12
arch/x86/kernel/apic/apic.c | 2
arch/x86/kernel/cpu/intel.c | 2
arch/x86/kernel/step.c | 3
arch/x86/kernel/sys_x86_64.c | 7
arch/x86/kvm/vmx/nested.c | 15 -
arch/x86/lib/delay.c | 4
arch/x86/mm/pat.c | 2
arch/x86/um/ldt.c | 6
arch/xtensa/kernel/ptrace.c | 4
arch/xtensa/kernel/signal.c | 4
block/bfq-cgroup.c | 111 ++++---
block/bfq-iosched.c | 46 +--
block/bfq-iosched.h | 6
block/bio.c | 2
block/blk-iolatency.c | 122 ++++----
crypto/cryptd.c | 23 -
drivers/acpi/property.c | 18 -
drivers/acpi/sleep.c | 12
drivers/ata/libata-transport.c | 2
drivers/ata/pata_octeon_cf.c | 3
drivers/base/bus.c | 4
drivers/base/dd.c | 5
drivers/base/node.c | 1
drivers/block/drbd/drbd_main.c | 11
drivers/block/nbd.c | 50 ++-
drivers/block/virtio_blk.c | 7
drivers/bus/ti-sysc.c | 4
drivers/char/ipmi/ipmi_msghandler.c | 4
drivers/char/ipmi/ipmi_ssif.c | 23 +
drivers/clocksource/timer-oxnas-rps.c | 2
drivers/clocksource/timer-riscv.c | 2
drivers/clocksource/timer-sp804.c | 10
drivers/crypto/marvell/cipher.c | 1
drivers/devfreq/rk3399_dmc.c | 2
drivers/dma/stm32-mdma.c | 21 -
drivers/dma/xilinx/zynqmp_dma.c | 5
drivers/extcon/extcon.c | 29 +
drivers/firmware/arm_scmi/base.c | 2
drivers/firmware/dmi-sysfs.c | 2
drivers/firmware/stratix10-svc.c | 12
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3
drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 14
drivers/gpu/drm/amd/amdgpu/si_dpm.c | 8
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10
drivers/gpu/drm/arm/malidp_crtc.c | 5
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31 +-
drivers/gpu/drm/drm_edid.c | 6
drivers/gpu/drm/drm_plane.c | 14
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6
drivers/gpu/drm/gma500/psb_intel_display.c | 7
drivers/gpu/drm/imx/ipuv3-crtc.c | 2
drivers/gpu/drm/mediatek/mtk_cec.c | 2
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 1
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15 -
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15 -
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20 +
drivers/gpu/drm/msm/dsi/dsi_host.c | 21 -
drivers/gpu/drm/msm/hdmi/hdmi.c | 10
drivers/gpu/drm/msm/msm_gem_prime.c | 2
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6
drivers/gpu/drm/radeon/radeon_connectors.c | 4
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8
drivers/gpu/drm/vc4/vc4_txp.c | 8
drivers/gpu/drm/virtio/virtgpu_display.c | 2
drivers/hid/hid-bigbenff.c | 6
drivers/hid/hid-elan.c | 2
drivers/hid/hid-led.c | 2
drivers/hwmon/hwmon.c | 16 -
drivers/hwtracing/coresight/coresight-cpu-debug.c | 7
drivers/i2c/busses/i2c-at91-master.c | 11
drivers/i2c/busses/i2c-cadence.c | 12
drivers/iio/adc/ad7124.c | 1
drivers/iio/adc/sc27xx_adc.c | 20 -
drivers/iio/adc/stmpe-adc.c | 8
drivers/iio/common/st_sensors/st_sensors_core.c | 24 +
drivers/iio/dummy/iio_simple_dummy.c | 20 -
drivers/infiniband/hw/hfi1/file_ops.c | 2
drivers/infiniband/hw/hfi1/init.c | 2
drivers/infiniband/hw/hfi1/sdma.c | 12
drivers/infiniband/sw/rdmavt/qp.c | 6
drivers/infiniband/sw/rxe/rxe_req.c | 2
drivers/input/misc/sparcspkr.c | 1
drivers/input/mouse/bcm5974.c | 7
drivers/input/touchscreen/stmfts.c | 16 -
drivers/iommu/amd_iommu_init.c | 2
drivers/iommu/msm_iommu.c | 11
drivers/iommu/mtk_iommu.c | 3
drivers/irqchip/irq-armada-370-xp.c | 11
drivers/irqchip/irq-aspeed-i2c-ic.c | 4
drivers/irqchip/irq-sni-exiu.c | 25 +
drivers/irqchip/irq-xtensa-mx.c | 18 -
drivers/macintosh/Kconfig | 6
drivers/macintosh/Makefile | 3
drivers/macintosh/via-pmu.c | 2
drivers/mailbox/mailbox.c | 19 -
drivers/md/bcache/request.c | 6
drivers/md/md-bitmap.c | 44 +-
drivers/md/md.c | 33 +-
drivers/md/raid0.c | 31 +-
drivers/media/cec/cec-adap.c | 6
drivers/media/i2c/ov7670.c | 1
drivers/media/pci/cx23885/cx23885-core.c | 6
drivers/media/pci/cx25821/cx25821-core.c | 2
drivers/media/platform/aspeed-video.c | 4
drivers/media/platform/coda/coda-common.c | 35 +-
drivers/media/platform/exynos4-is/fimc-is.c | 2
drivers/media/platform/exynos4-is/fimc-isp-video.h | 2
drivers/media/platform/qcom/venus/hfi.c | 3
drivers/media/platform/sti/delta/delta-v4l2.c | 6
drivers/media/platform/vsp1/vsp1_rpf.c | 6
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7
drivers/media/usb/uvc/uvc_v4l2.c | 20 -
drivers/mfd/davinci_voicecodec.c | 6
drivers/mfd/ipaq-micro.c | 2
drivers/misc/cardreader/rtsx_usb.c | 1
drivers/misc/lkdtm/usercopy.c | 17 -
drivers/misc/ocxl/file.c | 2
drivers/mmc/core/block.c | 3
drivers/mmc/host/jz4740_mmc.c | 20 +
drivers/mtd/chips/cfi_cmdset_0002.c | 103 +++---
drivers/mtd/ubi/vmt.c | 1
drivers/net/can/xilinx_can.c | 4
drivers/net/dsa/lantiq_gswip.c | 4
drivers/net/dsa/mv88e6xxx/chip.c | 1
drivers/net/ethernet/altera/altera_tse_main.c | 6
drivers/net/ethernet/broadcom/Makefile | 5
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 8
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 2
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 7
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 5
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 45 ++-
drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c | 9
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 4
drivers/net/phy/mdio_bus.c | 1
drivers/net/phy/micrel.c | 11
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8
drivers/net/wireless/ath/carl9170/tx.c | 3
drivers/net/wireless/broadcom/b43/phy_n.c | 2
drivers/net/wireless/broadcom/b43legacy/phy.c | 2
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3
drivers/net/wireless/marvell/mwifiex/11h.c | 2
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8
drivers/net/wireless/realtek/rtlwifi/usb.c | 2
drivers/nfc/st21nfca/se.c | 32 +-
drivers/nfc/st21nfca/st21nfca.h | 1
drivers/nvdimm/security.c | 5
drivers/nvme/host/pci.c | 1
drivers/of/overlay.c | 4
drivers/pci/controller/dwc/pci-imx6.c | 23 -
drivers/pci/controller/dwc/pcie-qcom.c | 9
drivers/pci/controller/pcie-cadence-ep.c | 3
drivers/pci/controller/pcie-rockchip-ep.c | 3
drivers/pci/pci.c | 12
drivers/pcmcia/Kconfig | 2
drivers/phy/qualcomm/phy-qcom-qmp.c | 13
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2
drivers/pwm/pwm-lp3943.c | 1
drivers/regulator/core.c | 7
drivers/regulator/pfuze100-regulator.c | 2
drivers/rpmsg/qcom_smd.c | 4
drivers/rtc/rtc-mt6397.c | 2
drivers/scsi/dc395x.c | 15 -
drivers/scsi/fcoe/fcoe_ctlr.c | 2
drivers/scsi/megaraid.c | 2
drivers/scsi/myrb.c | 11
drivers/scsi/ufs/ufs-qcom.c | 7
drivers/scsi/ufs/ufshcd.c | 7
drivers/soc/qcom/smp2p.c | 1
drivers/soc/qcom/smsm.c | 1
drivers/soc/rockchip/grf.c | 2
drivers/spi/spi-img-spfi.c | 2
drivers/spi/spi-rspi.c | 15 -
drivers/spi/spi-stm32-qspi.c | 3
drivers/spi/spi-ti-qspi.c | 5
drivers/staging/fieldbus/anybuss/host.c | 2
drivers/staging/greybus/audio_codec.c | 4
drivers/staging/rtl8192e/rtllib_softmac.c | 2
drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c | 2
drivers/staging/rtl8712/usb_intf.c | 6
drivers/staging/rtl8712/usb_ops.c | 27 +
drivers/thermal/broadcom/sr-thermal.c | 3
drivers/tty/goldfish.c | 2
drivers/tty/serial/8250/8250_fintek.c | 8
drivers/tty/serial/digicolor-usart.c | 2
drivers/tty/serial/fsl_lpuart.c | 24 -
drivers/tty/serial/icom.c | 2
drivers/tty/serial/meson_uart.c | 13
drivers/tty/serial/msm_serial.c | 5
drivers/tty/serial/owl-uart.c | 1
drivers/tty/serial/pch_uart.c | 27 -
drivers/tty/serial/rda-uart.c | 2
drivers/tty/serial/sa1100.c | 4
drivers/tty/serial/serial_txx9.c | 2
drivers/tty/serial/sh-sci.c | 6
drivers/tty/serial/sifive.c | 8
drivers/tty/serial/st-asc.c | 4
drivers/tty/serial/stm32-usart.c | 15 -
drivers/tty/synclink_gt.c | 2
drivers/tty/tty_buffer.c | 3
drivers/usb/core/hcd-pci.c | 4
drivers/usb/core/hcd.c | 29 +
drivers/usb/core/quirks.c | 3
drivers/usb/dwc2/gadget.c | 1
drivers/usb/dwc3/dwc3-pci.c | 2
drivers/usb/host/isp116x-hcd.c | 6
drivers/usb/host/oxu210hp-hcd.c | 2
drivers/usb/musb/omap2430.c | 1
drivers/usb/serial/option.c | 2
drivers/usb/storage/karma.c | 15 -
drivers/usb/usbip/stub_dev.c | 2
drivers/usb/usbip/stub_rx.c | 2
drivers/vhost/vringh.c | 10
drivers/video/fbdev/amba-clcd.c | 5
drivers/video/fbdev/core/fbcon.c | 5
drivers/video/fbdev/pxa3xx-gcu.c | 12
drivers/watchdog/ts4800_wdt.c | 5
drivers/watchdog/wdat_wdt.c | 1
drivers/xen/xlate_mmu.c | 1
fs/afs/dir.c | 5
fs/binfmt_flat.c | 27 +
fs/btrfs/disk-io.c | 4
fs/btrfs/volumes.c | 8
fs/ceph/xattr.c | 10
fs/cifs/cifsglob.h | 4
fs/cifs/smb2ops.c | 7
fs/cifs/smb2pdu.c | 3
fs/dax.c | 3
fs/dlm/lock.c | 11
fs/dlm/plock.c | 12
fs/ext4/inline.c | 12
fs/ext4/inode.c | 4
fs/ext4/namei.c | 84 ++++-
fs/ext4/super.c | 1
fs/f2fs/checkpoint.c | 4
fs/f2fs/f2fs.h | 14
fs/f2fs/file.c | 20 +
fs/f2fs/inode.c | 16 +
fs/f2fs/segment.c | 9
fs/f2fs/segment.h | 32 +-
fs/f2fs/super.c | 6
fs/fat/fatent.c | 7
fs/fs-writeback.c | 13
fs/iomap/buffered-io.c | 3
fs/jffs2/fs.c | 1
fs/jfs/jfs_dmap.c | 3
fs/kernfs/dir.c | 31 +-
fs/nfs/file.c | 7
fs/nfs/nfs4proc.c | 4
fs/nfs/pnfs.c | 2
fs/nfs/write.c | 11
fs/notify/fdinfo.c | 11
fs/notify/inotify/inotify.h | 12
fs/notify/inotify/inotify_user.c | 2
fs/notify/mark.c | 6
fs/ocfs2/dlmfs/userdlm.c | 16 +
fs/proc/generic.c | 3
fs/proc/proc_net.c | 3
include/drm/drm_edid.h | 6
include/linux/bpf.h | 2
include/linux/efi.h | 2
include/linux/iio/common/st_sensors.h | 3
include/linux/mailbox_controller.h | 1
include/linux/mtd/cfi.h | 1
include/linux/nodemask.h | 51 +--
include/linux/ptrace.h | 7
include/linux/usb/hcd.h | 2
include/net/if_inet6.h | 8
include/net/sch_generic.h | 42 --
include/scsi/libfcoe.h | 3
include/sound/jack.h | 1
include/trace/events/rxrpc.h | 2
include/trace/events/vmscan.h | 4
init/Kconfig | 9
ipc/mqueue.c | 14
kernel/bpf/stackmap.c | 1
kernel/dma/debug.c | 2
kernel/ptrace.c | 5
kernel/sched/fair.c | 8
kernel/sched/pelt.h | 4
kernel/sched/sched.h | 4
kernel/trace/trace.c | 13
kernel/trace/trace_events_hist.c | 3
lib/nodemask.c | 4
mm/compaction.c | 2
mm/hugetlb.c | 9
net/bluetooth/sco.c | 21 -
net/ipv4/ip_gre.c | 11
net/ipv4/tcp_input.c | 11
net/ipv4/tcp_output.c | 4
net/ipv4/xfrm4_protocol.c | 1
net/ipv6/addrconf.c | 33 +-
net/ipv6/seg6_hmac.c | 1
net/key/af_key.c | 10
net/mac80211/chan.c | 7
net/mac80211/ieee80211_i.h | 5
net/mac80211/scan.c | 20 +
net/netfilter/nf_tables_api.c | 22 +
net/netfilter/nft_dynset.c | 3
net/netfilter/nft_nat.c | 3
net/nfc/core.c | 1
net/rxrpc/ar-internal.h | 13
net/rxrpc/call_event.c | 3
net/rxrpc/input.c | 31 +-
net/rxrpc/output.c | 20 -
net/rxrpc/recvmsg.c | 8
net/rxrpc/sendmsg.c | 6
net/rxrpc/sysctl.c | 4
net/sctp/input.c | 4
net/smc/af_smc.c | 2
net/sunrpc/xdr.c | 6
net/sunrpc/xprtrdma/rpc_rdma.c | 5
net/tipc/bearer.c | 3
net/unix/af_unix.c | 2
net/wireless/nl80211.c | 1
scripts/faddr2line | 150 ++++++----
scripts/gdb/linux/config.py | 6
scripts/mod/modpost.c | 5
security/integrity/platform_certs/keyring_handler.h | 8
security/integrity/platform_certs/load_uefi.c | 33 ++
sound/core/jack.c | 34 +-
sound/pci/hda/patch_conexant.c | 7
sound/pci/hda/patch_realtek.c | 10
sound/soc/codecs/Kconfig | 1
sound/soc/codecs/rk3328_codec.c | 2
sound/soc/codecs/rt5514.c | 2
sound/soc/codecs/rt5645.c | 7
sound/soc/codecs/tscs454.c | 12
sound/soc/codecs/wm2000.c | 6
sound/soc/fsl/fsl_sai.h | 4
sound/soc/fsl/imx-sgtl5000.c | 14
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5
sound/soc/mxs/mxs-saif.c | 1
sound/soc/soc-dapm.c | 2
tools/perf/builtin-c2c.c | 10
tools/perf/pmu-events/jevents.c | 2
tools/perf/util/data.h | 1
tools/power/x86/turbostat/turbostat.c | 1
tools/testing/selftests/bpf/progs/btf_dump_test_case_syntax.c | 2
tools/testing/selftests/netfilter/nft_nat.sh | 43 ++
413 files changed, 2500 insertions(+), 1316 deletions(-)
Aditya Garg (1):
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Adrian Hunter (1):
mmc: block: Fix CQE recovery reset success
Aidan MacDonald (1):
mmc: jz4740: Apply DMA engine limits to maximum segment size
Akira Yokosawa (1):
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Alexander Aring (2):
dlm: fix plock invalid read
dlm: fix missing lkb refcount handling
Alexander Lobakin (1):
modpost: fix removing numeric suffixes
Alexander Wetzel (1):
rtl818x: Prevent using not initialized queues
Alexandru Elisei (1):
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Alexandru Tachici (1):
iio: adc: ad7124: Remove shift from scan_type
Alexey Dobriyan (1):
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
Alice Wong (1):
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Amadeusz Sławiński (1):
ALSA: jack: Access input_dev under mutex
Amelie Delaunay (1):
dmaengine: stm32-mdma: remove GISR1 register
Amir Goldstein (2):
inotify: show inotify mask flags in proc fdinfo
fsnotify: fix wrong lockdep annotations
Ammar Faizi (1):
x86/delay: Fix the wrong asm constraint in delay_loop()
Andre Przywara (2):
ARM: dts: suniv: F1C100: fix watchdog compatible
clocksource/drivers/sp804: Avoid error on multiple instances
Andreas Gruenbacher (1):
iomap: iomap_write_failed fix
Arnd Bergmann (2):
drbd: fix duplicate array initializer
ARM: pxa: maybe fix gpio lookup tables
Baokun Li (1):
jffs2: fix memory leak in jffs2_do_fill_super
Biju Das (1):
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Bjorn Helgaas (1):
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Björn Ardö (1):
mailbox: forward the hrtimer if not queued and under a lock
Brian Norris (2):
PM / devfreq: rk3399_dmc: Disable edev on remove()
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Carl Yin(殷张成) (1):
USB: serial: option: add Quectel BG95 modem
Chao Yu (5):
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
f2fs: fix to clear dirty inode in f2fs_evict_inode()
f2fs: fix deadloop in foreground GC
f2fs: fix fallocate to use file_modified to update permissions consistently
Charles Keepax (1):
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
Chengming Zhou (1):
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
Christian Borntraeger (1):
s390/gmap: voluntarily schedule during key setting
Christoph Hellwig (1):
virtio_blk: fix the discard_granularity and discard_alignment queue limits
Christophe JAILLET (2):
media: aspeed: Fix an error handling path in aspeed_video_probe()
staging: fieldbus: Fix the error handling path in anybuss_host_common_probe()
Christophe de Dinechin (1):
nodemask.h: fix compilation error with GCC12
Chuanhong Guo (1):
arm: mediatek: select arch timer for mt7629
Chuck Lever (1):
SUNRPC: Fix the calculation of xdr->end in xdr_get_next_encode_buffer()
Cixi Geng (2):
iio: adc: sc27xx: fix read big scale voltage not right
iio: adc: sc27xx: Fine tune the scale calibration values
Corentin Labbe (1):
crypto: marvell/cesa - ECB does not IV
Corey Minyard (2):
ipmi:ssif: Check for NULL msg when handling events and messages
ipmi: Fix pr_fmt to avoid compilation issues
Cristian Marussi (1):
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Dan Carpenter (5):
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
PCI: cadence: Fix find_first_zero_bit() limit
PCI: rockchip: Fix find_first_zero_bit() limit
net: ethernet: mtk_eth_soc: out of bounds read in mtk_hwlro_get_fdir_entry()
Dan Williams (1):
nvdimm: Allow overwrite in the presence of disabled dimms
Daniel Thompson (1):
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Daniel Vetter (1):
fbcon: Consistently protect deferred_takeover with console_lock()
Dave Airlie (1):
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
David Howells (7):
rxrpc: Return an error to sendmsg if call failed
rxrpc: Fix listen() setting the bar too high for the prealloc rings
rxrpc: Don't try to resend the request if we're receiving the reply
rxrpc: Fix overlapping ACK accounting
rxrpc: Don't let ack.previousPacket regress
rxrpc: Fix decision on when to generate an IDLE ACK
afs: Fix infinite loop found by xfstest generic/676
Dennis Dalessandro (1):
RDMA/hfi1: Fix potential integer multiplication overflow errors
Dinh Nguyen (1):
dt-bindings: gpio: altera: correct interrupt-cells
Dmitry Baryshkov (1):
drm/msm/dsi: fix error checks and return values for DSI xmit functions
Dmitry Torokhov (1):
Input: stmfts - do not leave device disabled in stmfts_input_open
Dongliang Mu (4):
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
rtlwifi: Use pr_warn instead of WARN_ONCE
media: ov7670: remove ov7670_power_off from ov7670_remove
f2fs: remove WARN_ON in f2fs_is_valid_blkaddr
Douglas Miller (2):
RDMA/hfi1: Prevent panic when SDMA is disabled
RDMA/hfi1: Prevent use of lock before it is initialized
Duoming Zhou (5):
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
drivers: staging: rtl8192u: Fix deadlock in ieee80211_beacons_stop()
drivers: staging: rtl8192e: Fix deadlock in rtllib_beacons_stop()
drivers: tty: serial: Fix deadlock in sa1100_set_termios()
drivers: usb: host: Fix deadlock in oxu_bus_suspend()
Emmanuel Grumbach (1):
iwlwifi: mvm: fix assert 1F04 upon reconfig
Eric Biggers (1):
ext4: reject the 'commit' option on ext2 filesystems
Eric Dumazet (4):
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
tcp: tcp_rtx_synack() can be called from process context
bpf, arm64: Clear prog->jited_len along prog->jited
tcp: fix tcp_mtup_probe_success vs wrong snd_cwnd
Eric W. Biederman (3):
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Evan Green (1):
USB: hcd-pci: Fully suspend across freeze/thaw cycle
Evan Quan (1):
drm/amd/pm: fix the compile warning
Fabio Estevam (1):
net: phy: micrel: Allow probing without .driver_data
Felix Fietkau (1):
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Feras Daoud (1):
net/mlx5: Rearm the FW tracer after each tracer event
Finn Thain (1):
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Florian Westphal (1):
netfilter: nat: really support inet nat without l3 address
Francesco Dolcini (1):
PCI: imx6: Fix PERST# start-up sequence
Gal Pressman (1):
net/mlx4_en: Fix wrong return value on ioctl EEPROM query failure
Geert Uytterhoeven (1):
m68k: math-emu: Fix dependencies of math emulation support
Gong Yuanjun (2):
mips: cpc: Fix refcount leak in mips_cpc_default_phys_base
drm/radeon: fix a possible null pointer dereference
Greg Kroah-Hartman (1):
Linux 5.4.198
Greg Ungerer (2):
m68knommu: set ZERO_PAGE() to the allocated zeroed page
m68knommu: fix undefined reference to `_init_sp'
Guenter Roeck (1):
hwmon: Make chip parameter for with_info API mandatory
Guilherme G. Piccoli (1):
coresight: cpu-debug: Replace mutex with mutex_trylock on panic notifier
Guoju Fang (1):
net: sched: add barrier to fix packet stuck problem for lockless qdisc
Guoqing Jiang (1):
md: protect md_unregister_thread from reentrancy
Gustavo A. R. Silva (1):
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
Hangyu Hua (3):
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
misc: ocxl: fix possible double free in ocxl_file_register_afu
usb: usbip: fix a refcount leak in stub_probe()
Hannes Reinecke (1):
scsi: myrb: Fix up null pointer access on myrb_cleanup()
Hans Verkuil (1):
media: cec-adap.c: fix is_configuring state
Hao Luo (1):
kernfs: Separate kernfs_pr_cont_buf and rename_lock.
Haowen Bai (3):
b43legacy: Fix assigning negative value to unsigned variable
b43: Fix assigning negative value to unsigned variable
ipw2x00: Fix potential NULL dereference in libipw_xmit()
Hari Bathini (2):
powerpc/fadump: Fix fadump to work with a different endian capture kernel
powerpc/fadump: fix PT_LOAD segment for boot memory area
Heiko Carstens (1):
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Heming Zhao (1):
md/bitmap: don't set sb values if can't pass sanity check
Hoang Le (1):
tipc: check attribute length for bearer name
Huang Guobin (1):
tty: Fix a possible resource leak in icom_probe
Ilpo Järvinen (8):
serial: 8250_fintek: Check SER_RS485_RTS_* only with RS485
serial: digicolor-usart: Don't allow CS5-6
serial: rda-uart: Don't allow CS5-6
serial: txx9: Don't allow CS5-6
serial: sh-sci: Don't allow CS5-6
serial: sifive: Sanitize CSIZE and c_iflag
serial: st-asc: Sanitize CSIZE and correct PARENB for CS7
serial: stm32-usart: Correct CSIZE, bits, and parity
Jaegeuk Kim (1):
f2fs: don't need inode lock for system hidden quota
Jakob Koschel (2):
f2fs: fix dereference of stale list iterator after loop body
staging: greybus: codecs: fix type confusion of list iterator variable
Jakub Kicinski (1):
eth: tg3: silence the GCC 12 array-bounds warning
Jan Kara (11):
bfq: Split shared queues on move between cgroups
bfq: Update cgroup information before merging bio
bfq: Track whether bfq_group is still online
ext4: verify dir block before splitting it
ext4: avoid cycles in directory h-tree
bfq: Avoid merging queues with different parents
bfq: Drop pointless unlock-lock pair
bfq: Remove pointless bfq_init_rq() calls
bfq: Get rid of __bio_blkcg() usage
bfq: Make sure bfqg for which we are queueing requests is online
block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
Jan Kiszka (1):
efi: Add missing prototype for efi_capsule_setup_info
Jani Nikula (1):
drm/edid: fix invalid EDID extension block filtering
Jann Horn (1):
s390/crypto: fix scatterwalk_unmap() callers in AES-GCM
Janusz Krzysztofik (1):
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Jason A. Donenfeld (1):
openrisc: start CPU timer early in boot
Jessica Zhang (2):
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jia-Ju Bai (1):
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Jiasheng Jiang (1):
drm: mali-dp: potential dereference of null pointer
Jiri Slaby (1):
serial: pch: don't overwrite xmit->buf[0] by x_char
Joerg Roedel (1):
iommu/amd: Increase timeout waiting for GA log enablement
Johan Hovold (5):
PCI: qcom: Fix runtime PM imbalance on probe errors
PCI: qcom: Fix unbalanced PHY init on probe errors
phy: qcom-qmp: fix struct clk leak on probe errors
phy: qcom-qmp: fix reset-controller leak on probe errors
phy: qcom-qmp: fix pipe-clock imbalance on power-on failure
Johannes Berg (3):
nl80211: show SSID for P2P_GO interfaces
wifi: mac80211: fix use-after-free in chanctx code
um: chan_user: Fix winch_tramp() return value
John Ogness (2):
serial: meson: acquire port->lock in startup()
serial: msm_serial: disable interrupts in __msm_console_write()
Jonathan Teh (1):
HID: hid-led: fix maximum brightness for Dream Cheeky
Josh Poimboeuf (2):
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
scripts/faddr2line: Fix overlapping text section failures
Jun Miao (1):
tracing: Fix sleeping function called from invalid context on RT kernel
Junxiao Bi via Ocfs2-devel (1):
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Kajol Jain (1):
powerpc/perf: Fix the threshold compare group constraint for power9
Kan Liang (1):
perf/x86/intel: Fix event constraints for ICL
Kathiravan T (1):
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Kees Cook (2):
lkdtm/usercopy: Expand size of "out of frame" object
nodemask: Fix return values to be unsigned
Keita Suzuki (2):
drm/amd/pm: fix double free in si_parse_power_table()
tracing: Fix potential double free in create_var_ref()
Kinglong Mee (1):
xprtrdma: treat all calls not a bcall when bc_serv is NULL
Kirill A. Shutemov (1):
ACPICA: Avoid cache flush inside virtual machines
Kishon Vijay Abraham I (1):
usb: core: hcd: Add support for deferring roothub registration
Kiwoong Kim (1):
scsi: ufs: core: Exclude UECxx from SFR dump list
Krzysztof Kozlowski (7):
ARM: dts: ox820: align interrupt controller node name with dtschema
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
rpmsg: qcom_smd: Fix irq_of_parse_and_map() return value
rpmsg: qcom_smd: Fix returning 0 if irq_of_parse_and_map() fails
clocksource/drivers/oxnas-rps: Fix irq_of_parse_and_map() return value
Kuan-Ying Lee (1):
scripts/gdb: change kernel config dumping method
Kuniyuki Iwashima (1):
af_unix: Fix a data-race in unix_dgram_peer_wake_me().
Kwanghoon Son (1):
media: exynos4-is: Fix compile warning
Len Brown (1):
tools/power turbostat: fix ICX DRAM power numbers
Leo Yan (2):
perf c2c: Use stdio interface if slang is not supported
perf c2c: Fix sorting in percent_rmt_hitm_cmp()
Leon Romanovsky (1):
net/mlx5: Don't use already freed action pointer
Lin Ma (3):
ASoC: rt5645: Fix errorenous cleanup order
NFC: NULL out the dev->rfkill to prevent UAF
USB: storage: karma: fix rio_karma_init return
Linus Torvalds (2):
drm: fix EDID struct for old ARM OABI format
drm: imx: fix compiler warning with gcc-12
Liu Xinpeng (1):
watchdog: wdat_wdt: Stop watchdog when rebooting the system
Liu Zixian (1):
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Liviu Dudau (1):
drm/komeda: return early if drm_universal_plane_init() fails.
Luca Weiss (1):
media: venus: hfi: avoid null dereference in deinit
Lucas Stach (2):
drm/bridge: adv7511: clean up CEC adapter when probe fails
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Lucas Tanure (1):
i2c: cadence: Increase timeout per message if necessary
Lv Ruyi (6):
scsi: megaraid: Fix error check return value of register_chrdev()
drm: msm: fix error check return value of irq_of_parse_and_map()
powerpc/xics: fix refcount leak in icp_opal_init()
powerpc/powernv: fix missing of_node_put in uv_init()
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
Maciej W. Rozycki (2):
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
serial: sifive: Report actual baud base rather than fixed 115200
Manivannan Sadhasivam (1):
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Marc Kleine-Budde (1):
can: xilinx_can: mark bit timing constants as const
Marek Szyprowski (1):
usb: dwc2: gadget: don't reset gadget's driver->bus
Mario Limonciello (1):
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
Marios Levogiannis (1):
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Mark Bloch (2):
net/mlx5: fs, delete the FTE when there are no rules attached to it
net/mlx5: fs, fail conflicting actions
Mark Brown (2):
ASoC: dapm: Don't fold register value changes into notifications
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Mark-PK Tsai (1):
tracing: Avoid adding tracer option before update_tracer_options
Martin Faltesek (2):
nfc: st21nfca: fix incorrect validating logic in EVT_TRANSACTION
nfc: st21nfca: fix memory leaks in EVT_TRANSACTION handling
Masahiro Yamada (5):
xen: unexport __init-annotated xen_xlate_map_ballooned_pages()
net: mdio: unexport __init-annotated mdio_bus_init()
net: xfrm: unexport __init-annotated xfrm4_protocol_init()
net: ipv6: unexport __init-annotated seg6_hmac_init()
modpost: fix undefined behavior of is_arm_mapping_symbol()
Mathias Nyman (1):
Input: bcm5974 - set missing URB_NO_TRANSFER_DMA_MAP urb flag
Matthieu Baerts (1):
x86/pm: Fix false positive kmemleak report in msr_build_context()
Max Filippov (1):
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Maxim Mikityanskiy (1):
net/mlx5e: Update netdev features after changing XDP state
Maxime Ripard (2):
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Miaohe Lin (1):
drivers/base/node.c: fix compaction sysfs file leak
Miaoqian Lin (26):
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
HID: elan: Fix potential double free in elan_input_configured
drm/bridge: Fix error handling in analogix_dp_probe
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
media: st-delta: Fix PM disable depth imbalance in delta_probe
media: exynos4-is: Change clk_disable to clk_disable_unprepare
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
Input: sparcspkr - fix refcount leak in bbc_beep_probe
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
tty: serial: owl: Fix missing clk_disable_unprepare() in owl_uart_probe
usb: musb: Fix missing of_node_put() in omap2430_probe
iio: adc: stmpe-adc: Fix wait_for_completion_timeout return value check
soc: rockchip: Fix refcount leak in rockchip_grf_init
firmware: dmi-sysfs: Fix memory leak in dmi_sysfs_register_handle
watchdog: ts4800_wdt: Fix refcount leak in ts4800_wdt_probe
net: dsa: mv88e6xxx: Fix refcount leak in mv88e6xxx_mdios_register
ata: pata_octeon_cf: Fix refcount leak in octeon_cf_probe
net: dsa: lantiq_gswip: Fix refcount leak in gswip_gphy_fw_list
net: altera: Fix refcount leak in altera_tse_mdio_create
Michael Ellerman (2):
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
powerpc/32: Fix overread/overwrite of thread_struct via ptrace
Michael Rodin (1):
media: vsp1: Fix offset calculation for plane cropping
Michael Walle (1):
i2c: at91: use dma safe buffers
Michal Kubecek (1):
Revert "net: af_key: add check for pfkey_broadcast in function pfkey_process"
Mike Kravetz (1):
hugetlb: fix huge_pmd_unshare address update
Mikulas Patocka (1):
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
Miles Chen (1):
drm/mediatek: Fix mtk_cec_mask()
Miquel Raynal (1):
iio: st_sensors: Add a local lock for protecting odr
Monish Kumar R (1):
USB: new quirk for Dell Gen 2 devices
Muchun Song (1):
dax: fix cache flush on PMD-mapped pages
Nathan Chancellor (1):
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Nick Desaulniers (1):
Kconfig: add config option for asm goto w/ outputs
Nicolas Dufresne (2):
media: coda: Fix reported H264 profile
media: coda: Add more H264 levels for CODA960
Nicolas Frattaroli (1):
ASoC: rk3328: fix disabling mclk on pclk probe failure
Niels Dossche (4):
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
ipv6: fix locking issues with loops over idev->addr_list
IB/rdmavt: add missing locks in rvt_ruc_loopback
usb: usbip: add missing device lock on tweak configuration cmd
Niklas Cassel (1):
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
Nuno Sá (1):
of: overlay: do not break notify on NOTIFY_{OK|STOP}
OGAWA Hirofumi (1):
fat: add ratelimit to fat*_ent_bread()
Olivier Matz (2):
ixgbe: fix bcast packets Rx on VF after promisc removal
ixgbe: fix unexpected VLAN Rx in promisc mode on VF
Pablo Neira Ayuso (2):
netfilter: nf_tables: disallow non-stateful expression in sets earlier
netfilter: nf_tables: memleak flow rule from commit path
Pali Rohár (1):
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Pascal Hambourg (1):
md/raid0: Ignore RAID0 layout if the second zone has only one device
Patrice Chotard (1):
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Pavel Skripkin (1):
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Peng Wu (3):
ARM: versatile: Add missing of_node_put in dcscb_init
ARM: hisi: Add missing of_node_put after of_find_compatible_node
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Peter Zijlstra (1):
x86/cpu: Elide KCSAN for cpu_has() and friends
Petr Machata (1):
mlxsw: spectrum_dcb: Do not warn about priority changes
Phil Elwell (3):
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Philipp Zabel (1):
media: coda: limit frame interval enumeration to supported encoder frame sizes
Pierre-Louis Bossart (1):
ASoC: max98357a: remove dependency on GPIOLIB
Qi Zheng (1):
tty: fix deadlock caused by calling printk() under tty_port->lock
Qu Wenruo (2):
btrfs: add "0x" prefix for unsupported optional features
btrfs: repair super block num_devices automatically
Radhey Shyam Pandey (1):
dmaengine: zynqmp_dma: In struct zynqmp_dma_chan fix desc_size data type
Randy Dunlap (7):
x86: Fix return value of __setup handlers
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
powerpc/8xx: export 'cpm_setbrg' for modules
powerpc/idle: Fix return value of __setup() handler
powerpc/4xx/cpm: Fix return value of __setup() handler
macintosh: via-pmu and via-cuda need RTC_LIB
pcmcia: db1xxx_ss: restrict to MIPS_DB1XXX boards
Ravi Bangoria (1):
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Rei Yamamoto (1):
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Sakari Ailus (1):
ACPI: property: Release subnode properties with data nodes
Samuel Holland (1):
clocksource/drivers/riscv: Events are stopped during CPU suspend
Schspa Shi (2):
cpufreq: Fix possible race in cpufreq online error path
driver: base: fix UAF when driver_attach failed
Sean Christopherson (2):
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
Sebastian Andrzej Siewior (1):
crypto: cryptd - Protect per-CPU resource by disabling BH.
Sergey Shtylyov (1):
ata: libata-transport: fix {dma|pio|xfer}_mode sysfs files
Shawn Lin (1):
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
Shengjiu Wang (1):
ASoC: fsl_sai: Fix FSL_SAI_xDR/xFR definition
Sherry Sun (1):
tty: serial: fsl_lpuart: fix potential bug when using both of_alias_get_id and ida_simple_get
Shuah Khan (1):
misc: rtsx: set NULL intfdata when probe fails
Shyam Prasad N (1):
cifs: return errors during session setup during reconnects
Smith, Kyle Miller (Nimble Kernel) (1):
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Stefan Wahren (1):
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
Steve French (1):
cifs: version operations for smb20 unneeded when legacy support disabled
Steven Price (1):
drm/plane: Move range check for format_count earlier
Tejun Heo (1):
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Thibaut VARÈNE (1):
ath9k: fix QCA9561 PA bias level
Tokunori Ikegami (2):
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Tony Lindgren (1):
bus: ti-sysc: Fix warnings for unbind for serial
Trond Myklebust (5):
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
NFS: Do not report flush errors in nfs_write_end()
NFS: Don't report errors from nfs_pageio_complete() more than once
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
NFSv4: Don't hold the layoutget locks across multiple RPC calls
Uwe Kleine-König (1):
pwm: lp3943: Fix duty calculation in case period was clamped
Vasily Averin (1):
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
Venky Shankar (1):
ceph: allow ceph.dir.rctime xattr to be updatable
Vincent Ray (1):
net: sched: fixed barrier to prevent skbuff sticking in qdisc backlog
Vincent Whitchurch (1):
um: Fix out-of-bounds read in LDT setup
Vinod Polimera (1):
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
Viresh Kumar (1):
Revert "cpufreq: Fix possible race in cpufreq online error path"
Waiman Long (1):
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
Wang Cheng (2):
staging: rtl8712: fix uninit-value in usb_read8() and friends
staging: rtl8712: fix uninit-value in r871xu_drv_init()
Wang Weiyang (1):
tty: goldfish: Use tty_port_destroy() to destroy port
Wenli Looi (1):
ath9k: fix ar9003_get_eepmisc
Willem de Bruijn (1):
ip_gre: test csum_start instead of transport header
Xiao Yang (1):
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Xiaoke Wang (1):
iio: dummy: iio_simple_dummy: check the return value of kstrdup()
Xiaomeng Tong (10):
media: uvcvideo: Fix missing check to determine if element is found in list
scsi: dc395x: Fix a missing check on list iterator
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
md: fix an incorrect NULL check in does_sb_need_changing
md: fix an incorrect NULL check in md_reload_sb
iommu/msm: Fix an incorrect NULL check on list iterator
carl9170: tx: fix an incorrect use of list iterator
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
gma500: fix an incorrect NULL check on list iterator
firmware: stratix10-svc: fix a missing check on list iterator
Xie Yongji (2):
nbd: Fix hung on disconnect request if socket is closed before
vringh: Fix loop descriptors check in the indirect cases
Yang Jihong (1):
perf tools: Add missing headers needed by util/data.h
Yang Yingliang (6):
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
rtc: mt6397: check return value after calling platform_get_resource()
video: fbdev: pxa3xx-gcu: release the resources correctly in pxa3xx_gcu_probe/remove()
Ye Bin (3):
ext4: fix use-after-free in ext4_rename_dir_prepare
ext4: fix warning in ext4_handle_inode_extension
ext4: fix bug_on in ext4_writepages
Yicong Yang (1):
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Ying Hsu (1):
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Yong Wu (1):
iommu/mediatek: Add list_del in mtk_iommu_remove
Yonghong Song (1):
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Yu Kuai (3):
nbd: call genl_unregister_family() first in nbd_cleanup()
nbd: fix race between nbd_alloc_config() and module removal
nbd: fix io hung while disconnecting device
Yu Xiao (1):
nfp: only report pause frame configuration for physical device
Yuntao Wang (1):
bpf: Fix excessive memory allocation in stack_map_alloc()
Zev Weiss (1):
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Zhang Wensheng (1):
driver core: fix deadlock in __device_attach
Zhen Ni (1):
USB: host: isp116x: check return value after calling platform_get_resource()
Zheng Yongjun (3):
spi: img-spfi: Fix pm_runtime_get_sync() error checking
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
usb: dwc3: pci: Fix pm_runtime_get_sync() error checking
Zhengjun Xing (1):
perf jevents: Fix event syntax error caused by ExtSel
Zheyu Ma (3):
media: pci: cx23885: Fix the error handling in cx23885_initdev()
media: cx25821: Fix the warning when removing the module
tty: synclink_gt: Fix null-pointer-dereference in slgt_clean()
Zhihao Cheng (2):
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
ubi: ubi_create_volume: Fix use-after-free when volume creation failed
Zhou Qingyang (1):
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Zixuan Fu (1):
fs: jfs: fix possible NULL pointer dereference in dbFree()
bumwoo lee (1):
extcon: Modify extcon device to be created after driver data is set
huangwenhui (1):
ALSA: hda/conexant - Fix loopback issue with CX20632
jianghaoran (1):
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
liuyacan (1):
net/smc: postpone sk_refcnt increment in connect()
^ permalink raw reply [relevance 1%]
* [PATCH AUTOSEL 5.10 29/29] gpio: dwapb: Don't print error on -EPROBE_DEFER
@ 2022-06-14 2:08 5% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2022-06-14 2:08 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Serge Semin, Andy Shevchenko, Bartosz Golaszewski, Sasha Levin,
linus.walleij, gnurou, linux-gpio
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
[ Upstream commit 77006f6edc0e0f58617eb25e53731f78641e820d ]
Currently if the APB or Debounce clocks aren't yet ready to be requested
the DW GPIO driver will correctly handle that by deferring the probe
procedure, but the error is still printed to the system log. It needlessly
pollutes the log since there was no real error but a request to postpone
the clock request procedure since the clocks subsystem hasn't been fully
initialized yet. Let's fix that by using the dev_err_probe method to print
the APB/clock request error status. It will correctly handle the deferred
probe situation and print the error if it actually happens.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpio/gpio-dwapb.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 4275c18a097a..ea2e2618b794 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -646,10 +646,9 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
gpio->clks[1].id = "db";
err = devm_clk_bulk_get_optional(gpio->dev, DWAPB_NR_CLOCKS,
gpio->clks);
- if (err) {
- dev_err(gpio->dev, "Cannot get APB/Debounce clocks\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(gpio->dev, err,
+ "Cannot get APB/Debounce clocks\n");
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
if (err) {
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH AUTOSEL 5.15 37/41] gpio: dwapb: Don't print error on -EPROBE_DEFER
@ 2022-06-14 2:07 5% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2022-06-14 2:07 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Serge Semin, Andy Shevchenko, Bartosz Golaszewski, Sasha Levin,
linus.walleij, gnurou, linux-gpio
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
[ Upstream commit 77006f6edc0e0f58617eb25e53731f78641e820d ]
Currently if the APB or Debounce clocks aren't yet ready to be requested
the DW GPIO driver will correctly handle that by deferring the probe
procedure, but the error is still printed to the system log. It needlessly
pollutes the log since there was no real error but a request to postpone
the clock request procedure since the clocks subsystem hasn't been fully
initialized yet. Let's fix that by using the dev_err_probe method to print
the APB/clock request error status. It will correctly handle the deferred
probe situation and print the error if it actually happens.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpio/gpio-dwapb.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index f98fa33e1679..e981e7a46fc1 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -653,10 +653,9 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
gpio->clks[1].id = "db";
err = devm_clk_bulk_get_optional(gpio->dev, DWAPB_NR_CLOCKS,
gpio->clks);
- if (err) {
- dev_err(gpio->dev, "Cannot get APB/Debounce clocks\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(gpio->dev, err,
+ "Cannot get APB/Debounce clocks\n");
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
if (err) {
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH AUTOSEL 5.17 38/43] gpio: dwapb: Don't print error on -EPROBE_DEFER
@ 2022-06-14 2:05 5% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2022-06-14 2:05 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Serge Semin, Andy Shevchenko, Bartosz Golaszewski, Sasha Levin,
linus.walleij, gnurou, linux-gpio
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
[ Upstream commit 77006f6edc0e0f58617eb25e53731f78641e820d ]
Currently if the APB or Debounce clocks aren't yet ready to be requested
the DW GPIO driver will correctly handle that by deferring the probe
procedure, but the error is still printed to the system log. It needlessly
pollutes the log since there was no real error but a request to postpone
the clock request procedure since the clocks subsystem hasn't been fully
initialized yet. Let's fix that by using the dev_err_probe method to print
the APB/clock request error status. It will correctly handle the deferred
probe situation and print the error if it actually happens.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpio/gpio-dwapb.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index b0f3aca61974..9467d695a33e 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -652,10 +652,9 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
gpio->clks[1].id = "db";
err = devm_clk_bulk_get_optional(gpio->dev, DWAPB_NR_CLOCKS,
gpio->clks);
- if (err) {
- dev_err(gpio->dev, "Cannot get APB/Debounce clocks\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(gpio->dev, err,
+ "Cannot get APB/Debounce clocks\n");
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
if (err) {
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH AUTOSEL 5.18 42/47] gpio: dwapb: Don't print error on -EPROBE_DEFER
@ 2022-06-14 2:04 5% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2022-06-14 2:04 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Serge Semin, Andy Shevchenko, Bartosz Golaszewski, Sasha Levin,
linus.walleij, gnurou, linux-gpio
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
[ Upstream commit 77006f6edc0e0f58617eb25e53731f78641e820d ]
Currently if the APB or Debounce clocks aren't yet ready to be requested
the DW GPIO driver will correctly handle that by deferring the probe
procedure, but the error is still printed to the system log. It needlessly
pollutes the log since there was no real error but a request to postpone
the clock request procedure since the clocks subsystem hasn't been fully
initialized yet. Let's fix that by using the dev_err_probe method to print
the APB/clock request error status. It will correctly handle the deferred
probe situation and print the error if it actually happens.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpio/gpio-dwapb.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index b0f3aca61974..9467d695a33e 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -652,10 +652,9 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
gpio->clks[1].id = "db";
err = devm_clk_bulk_get_optional(gpio->dev, DWAPB_NR_CLOCKS,
gpio->clks);
- if (err) {
- dev_err(gpio->dev, "Cannot get APB/Debounce clocks\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(gpio->dev, err,
+ "Cannot get APB/Debounce clocks\n");
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
if (err) {
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH 5.4 155/411] net/smc: postpone sk_refcnt increment in connect()
2022-06-13 10:04 1% [PATCH 5.4 000/411] 5.4.198-rc1 review Greg Kroah-Hartman
@ 2022-06-13 10:07 7% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-13 10:07 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, liuyacan, David S. Miller, Sasha Levin
From: liuyacan <liuyacan@corp.netease.com>
[ Upstream commit 75c1edf23b95a9c66923d9269d8e86e4dbde151f ]
Same trigger condition as commit 86434744. When setsockopt runs
in parallel to a connect(), and switch the socket into fallback
mode. Then the sk_refcnt is incremented in smc_connect(), but
its state stay in SMC_INIT (NOT SMC_ACTIVE). This cause the
corresponding sk_refcnt decrement in __smc_release() will not be
performed.
Fixes: 86434744fedf ("net/smc: add fallback check to connect()")
Signed-off-by: liuyacan <liuyacan@corp.netease.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/smc/af_smc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index a5a8cca46bd5..394491692a07 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -877,9 +877,9 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
if (rc && rc != -EINPROGRESS)
goto out;
- sock_hold(&smc->sk); /* sock put in passive closing */
if (smc->use_fallback)
goto out;
+ sock_hold(&smc->sk); /* sock put in passive closing */
if (flags & O_NONBLOCK) {
if (schedule_work(&smc->connect_work))
smc->connect_nonblock = 1;
--
2.35.1
^ permalink raw reply related [relevance 7%]
* [PATCH 5.4 000/411] 5.4.198-rc1 review
@ 2022-06-13 10:04 1% Greg Kroah-Hartman
2022-06-13 10:07 7% ` [PATCH 5.4 155/411] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2022-06-13 10:04 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, torvalds, akpm, linux, shuah,
patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, slade
This is the start of the stable review cycle for the 5.4.198 release.
There are 411 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 15 Jun 2022 09:47:08 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.198-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.4.198-rc1
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Pascal Hambourg <pascal@plouf.fr.eu.org>
md/raid0: Ignore RAID0 layout if the second zone has only one device
Michael Ellerman <mpe@ellerman.id.au>
powerpc/32: Fix overread/overwrite of thread_struct via ptrace
Mathias Nyman <mathias.nyman@linux.intel.com>
Input: bcm5974 - set missing URB_NO_TRANSFER_DMA_MAP urb flag
Olivier Matz <olivier.matz@6wind.com>
ixgbe: fix unexpected VLAN Rx in promisc mode on VF
Olivier Matz <olivier.matz@6wind.com>
ixgbe: fix bcast packets Rx on VF after promisc removal
Martin Faltesek <mfaltesek@google.com>
nfc: st21nfca: fix memory leaks in EVT_TRANSACTION handling
Martin Faltesek <mfaltesek@google.com>
nfc: st21nfca: fix incorrect validating logic in EVT_TRANSACTION
Adrian Hunter <adrian.hunter@intel.com>
mmc: block: Fix CQE recovery reset success
Sergey Shtylyov <s.shtylyov@omp.ru>
ata: libata-transport: fix {dma|pio|xfer}_mode sysfs files
Shyam Prasad N <sprasad@microsoft.com>
cifs: return errors during session setup during reconnects
huangwenhui <huangwenhuia@uniontech.com>
ALSA: hda/conexant - Fix loopback issue with CX20632
Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com>
scripts/gdb: change kernel config dumping method
Xie Yongji <xieyongji@bytedance.com>
vringh: Fix loop descriptors check in the indirect cases
Kees Cook <keescook@chromium.org>
nodemask: Fix return values to be unsigned
Steve French <stfrench@microsoft.com>
cifs: version operations for smb20 unneeded when legacy support disabled
Christian Borntraeger <borntraeger@linux.ibm.com>
s390/gmap: voluntarily schedule during key setting
Yu Kuai <yukuai3@huawei.com>
nbd: fix io hung while disconnecting device
Yu Kuai <yukuai3@huawei.com>
nbd: fix race between nbd_alloc_config() and module removal
Yu Kuai <yukuai3@huawei.com>
nbd: call genl_unregister_family() first in nbd_cleanup()
Peter Zijlstra <peterz@infradead.org>
x86/cpu: Elide KCSAN for cpu_has() and friends
Masahiro Yamada <masahiroy@kernel.org>
modpost: fix undefined behavior of is_arm_mapping_symbol()
Gong Yuanjun <ruc_gongyuanjun@163.com>
drm/radeon: fix a possible null pointer dereference
Venky Shankar <vshankar@redhat.com>
ceph: allow ceph.dir.rctime xattr to be updatable
Michal Kubecek <mkubecek@suse.cz>
Revert "net: af_key: add check for pfkey_broadcast in function pfkey_process"
Hannes Reinecke <hare@suse.de>
scsi: myrb: Fix up null pointer access on myrb_cleanup()
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
md: protect md_unregister_thread from reentrancy
Liu Xinpeng <liuxp11@chinatelecom.cn>
watchdog: wdat_wdt: Stop watchdog when rebooting the system
Hao Luo <haoluo@google.com>
kernfs: Separate kernfs_pr_cont_buf and rename_lock.
John Ogness <john.ogness@linutronix.de>
serial: msm_serial: disable interrupts in __msm_console_write()
Wang Cheng <wanngchenng@gmail.com>
staging: rtl8712: fix uninit-value in r871xu_drv_init()
Wang Cheng <wanngchenng@gmail.com>
staging: rtl8712: fix uninit-value in usb_read8() and friends
Andre Przywara <andre.przywara@arm.com>
clocksource/drivers/sp804: Avoid error on multiple instances
bumwoo lee <bw365.lee@samsung.com>
extcon: Modify extcon device to be created after driver data is set
Shuah Khan <skhan@linuxfoundation.org>
misc: rtsx: set NULL intfdata when probe fails
Marek Szyprowski <m.szyprowski@samsung.com>
usb: dwc2: gadget: don't reset gadget's driver->bus
Evan Green <evgreen@chromium.org>
USB: hcd-pci: Fully suspend across freeze/thaw cycle
Duoming Zhou <duoming@zju.edu.cn>
drivers: usb: host: Fix deadlock in oxu_bus_suspend()
Duoming Zhou <duoming@zju.edu.cn>
drivers: tty: serial: Fix deadlock in sa1100_set_termios()
Zhen Ni <nizhen@uniontech.com>
USB: host: isp116x: check return value after calling platform_get_resource()
Duoming Zhou <duoming@zju.edu.cn>
drivers: staging: rtl8192e: Fix deadlock in rtllib_beacons_stop()
Duoming Zhou <duoming@zju.edu.cn>
drivers: staging: rtl8192u: Fix deadlock in ieee80211_beacons_stop()
Huang Guobin <huangguobin4@huawei.com>
tty: Fix a possible resource leak in icom_probe
Zheyu Ma <zheyuma97@gmail.com>
tty: synclink_gt: Fix null-pointer-dereference in slgt_clean()
Kees Cook <keescook@chromium.org>
lkdtm/usercopy: Expand size of "out of frame" object
Miquel Raynal <miquel.raynal@bootlin.com>
iio: st_sensors: Add a local lock for protecting odr
Xiaoke Wang <xkernel.wang@foxmail.com>
iio: dummy: iio_simple_dummy: check the return value of kstrdup()
Linus Torvalds <torvalds@linux-foundation.org>
drm: imx: fix compiler warning with gcc-12
Miaoqian Lin <linmq006@gmail.com>
net: altera: Fix refcount leak in altera_tse_mdio_create
Willem de Bruijn <willemb@google.com>
ip_gre: test csum_start instead of transport header
Mark Bloch <mbloch@nvidia.com>
net/mlx5: fs, fail conflicting actions
Feras Daoud <ferasda@nvidia.com>
net/mlx5: Rearm the FW tracer after each tracer event
Masahiro Yamada <masahiroy@kernel.org>
net: ipv6: unexport __init-annotated seg6_hmac_init()
Masahiro Yamada <masahiroy@kernel.org>
net: xfrm: unexport __init-annotated xfrm4_protocol_init()
Masahiro Yamada <masahiroy@kernel.org>
net: mdio: unexport __init-annotated mdio_bus_init()
Chuck Lever <chuck.lever@oracle.com>
SUNRPC: Fix the calculation of xdr->end in xdr_get_next_encode_buffer()
Gal Pressman <gal@nvidia.com>
net/mlx4_en: Fix wrong return value on ioctl EEPROM query failure
Miaoqian Lin <linmq006@gmail.com>
net: dsa: lantiq_gswip: Fix refcount leak in gswip_gphy_fw_list
Eric Dumazet <edumazet@google.com>
bpf, arm64: Clear prog->jited_len along prog->jited
Kuniyuki Iwashima <kuniyu@amazon.com>
af_unix: Fix a data-race in unix_dgram_peer_wake_me().
Masahiro Yamada <masahiroy@kernel.org>
xen: unexport __init-annotated xen_xlate_map_ballooned_pages()
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: memleak flow rule from commit path
Miaoqian Lin <linmq006@gmail.com>
ata: pata_octeon_cf: Fix refcount leak in octeon_cf_probe
Florian Westphal <fw@strlen.de>
netfilter: nat: really support inet nat without l3 address
Kinglong Mee <kinglongmee@gmail.com>
xprtrdma: treat all calls not a bcall when bc_serv is NULL
Yang Yingliang <yangyingliang@huawei.com>
video: fbdev: pxa3xx-gcu: release the resources correctly in pxa3xx_gcu_probe/remove()
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4: Don't hold the layoutget locks across multiple RPC calls
Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
dmaengine: zynqmp_dma: In struct zynqmp_dma_chan fix desc_size data type
Greg Ungerer <gerg@linux-m68k.org>
m68knommu: fix undefined reference to `_init_sp'
Greg Ungerer <gerg@linux-m68k.org>
m68knommu: set ZERO_PAGE() to the allocated zeroed page
Lucas Tanure <tanureal@opensource.cirrus.com>
i2c: cadence: Increase timeout per message if necessary
Dongliang Mu <mudongliangabcd@gmail.com>
f2fs: remove WARN_ON in f2fs_is_valid_blkaddr
Mark-PK Tsai <mark-pk.tsai@mediatek.com>
tracing: Avoid adding tracer option before update_tracer_options
Jun Miao <jun.miao@intel.com>
tracing: Fix sleeping function called from invalid context on RT kernel
Gong Yuanjun <ruc_gongyuanjun@163.com>
mips: cpc: Fix refcount leak in mips_cpc_default_phys_base
Leo Yan <leo.yan@linaro.org>
perf c2c: Fix sorting in percent_rmt_hitm_cmp()
Hoang Le <hoang.h.le@dektech.com.au>
tipc: check attribute length for bearer name
David Howells <dhowells@redhat.com>
afs: Fix infinite loop found by xfstest generic/676
Eric Dumazet <edumazet@google.com>
tcp: tcp_rtx_synack() can be called from process context
Guoju Fang <gjfang@linux.alibaba.com>
net: sched: add barrier to fix packet stuck problem for lockless qdisc
Maxim Mikityanskiy <maximmi@nvidia.com>
net/mlx5e: Update netdev features after changing XDP state
Leon Romanovsky <leonro@nvidia.com>
net/mlx5: Don't use already freed action pointer
Yu Xiao <yu.xiao@corigine.com>
nfp: only report pause frame configuration for physical device
Zhihao Cheng <chengzhihao1@huawei.com>
ubi: ubi_create_volume: Fix use-after-free when volume creation failed
Baokun Li <libaokun1@huawei.com>
jffs2: fix memory leak in jffs2_do_fill_super
Alexander Lobakin <alexandr.lobakin@intel.com>
modpost: fix removing numeric suffixes
Miaoqian Lin <linmq006@gmail.com>
net: dsa: mv88e6xxx: Fix refcount leak in mv88e6xxx_mdios_register
Dan Carpenter <dan.carpenter@oracle.com>
net: ethernet: mtk_eth_soc: out of bounds read in mtk_hwlro_get_fdir_entry()
Vincent Ray <vray@kalrayinc.com>
net: sched: fixed barrier to prevent skbuff sticking in qdisc backlog
Jann Horn <jannh@google.com>
s390/crypto: fix scatterwalk_unmap() callers in AES-GCM
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
clocksource/drivers/oxnas-rps: Fix irq_of_parse_and_map() return value
Shengjiu Wang <shengjiu.wang@nxp.com>
ASoC: fsl_sai: Fix FSL_SAI_xDR/xFR definition
Miaoqian Lin <linmq006@gmail.com>
watchdog: ts4800_wdt: Fix refcount leak in ts4800_wdt_probe
Zhang Wensheng <zhangwensheng5@huawei.com>
driver core: fix deadlock in __device_attach
Schspa Shi <schspa@gmail.com>
driver: base: fix UAF when driver_attach failed
Tony Lindgren <tony@atomide.com>
bus: ti-sysc: Fix warnings for unbind for serial
Miaoqian Lin <linmq006@gmail.com>
firmware: dmi-sysfs: Fix memory leak in dmi_sysfs_register_handle
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
serial: stm32-usart: Correct CSIZE, bits, and parity
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
serial: st-asc: Sanitize CSIZE and correct PARENB for CS7
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
serial: sifive: Sanitize CSIZE and c_iflag
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
serial: sh-sci: Don't allow CS5-6
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
serial: txx9: Don't allow CS5-6
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
serial: rda-uart: Don't allow CS5-6
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
serial: digicolor-usart: Don't allow CS5-6
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
serial: 8250_fintek: Check SER_RS485_RTS_* only with RS485
John Ogness <john.ogness@linutronix.de>
serial: meson: acquire port->lock in startup()
Yang Yingliang <yangyingliang@huawei.com>
rtc: mt6397: check return value after calling platform_get_resource()
Samuel Holland <samuel@sholland.org>
clocksource/drivers/riscv: Events are stopped during CPU suspend
Miaoqian Lin <linmq006@gmail.com>
soc: rockchip: Fix refcount leak in rockchip_grf_init
Guilherme G. Piccoli <gpiccoli@igalia.com>
coresight: cpu-debug: Replace mutex with mutex_trylock on panic notifier
Maciej W. Rozycki <macro@orcam.me.uk>
serial: sifive: Report actual baud base rather than fixed 115200
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix pipe-clock imbalance on power-on failure
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
rpmsg: qcom_smd: Fix returning 0 if irq_of_parse_and_map() fails
Cixi Geng <cixi.geng1@unisoc.com>
iio: adc: sc27xx: Fine tune the scale calibration values
Cixi Geng <cixi.geng1@unisoc.com>
iio: adc: sc27xx: fix read big scale voltage not right
Miaoqian Lin <linmq006@gmail.com>
iio: adc: stmpe-adc: Fix wait_for_completion_timeout return value check
Xiaomeng Tong <xiam0nd.tong@gmail.com>
firmware: stratix10-svc: fix a missing check on list iterator
Zheng Yongjun <zhengyongjun3@huawei.com>
usb: dwc3: pci: Fix pm_runtime_get_sync() error checking
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
rpmsg: qcom_smd: Fix irq_of_parse_and_map() return value
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
pwm: lp3943: Fix duty calculation in case period was clamped
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
staging: fieldbus: Fix the error handling path in anybuss_host_common_probe()
Miaoqian Lin <linmq006@gmail.com>
usb: musb: Fix missing of_node_put() in omap2430_probe
Lin Ma <linma@zju.edu.cn>
USB: storage: karma: fix rio_karma_init return
Niels Dossche <dossche.niels@gmail.com>
usb: usbip: add missing device lock on tweak configuration cmd
Hangyu Hua <hbh25y@gmail.com>
usb: usbip: fix a refcount leak in stub_probe()
Sherry Sun <sherry.sun@nxp.com>
tty: serial: fsl_lpuart: fix potential bug when using both of_alias_get_id and ida_simple_get
Miaoqian Lin <linmq006@gmail.com>
tty: serial: owl: Fix missing clk_disable_unprepare() in owl_uart_probe
Wang Weiyang <wangweiyang2@huawei.com>
tty: goldfish: Use tty_port_destroy() to destroy port
Alexandru Tachici <alexandru.tachici@analog.com>
iio: adc: ad7124: Remove shift from scan_type
Jakob Koschel <jakobkoschel@gmail.com>
staging: greybus: codecs: fix type confusion of list iterator variable
Randy Dunlap <rdunlap@infradead.org>
pcmcia: db1xxx_ss: restrict to MIPS_DB1XXX boards
Jia-Ju Bai <baijiaju1990@gmail.com>
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Jan Kara <jack@suse.cz>
block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
Jan Kara <jack@suse.cz>
bfq: Make sure bfqg for which we are queueing requests is online
Jan Kara <jack@suse.cz>
bfq: Get rid of __bio_blkcg() usage
Jan Kara <jack@suse.cz>
bfq: Remove pointless bfq_init_rq() calls
Jan Kara <jack@suse.cz>
bfq: Drop pointless unlock-lock pair
Jan Kara <jack@suse.cz>
bfq: Avoid merging queues with different parents
Maciej W. Rozycki <macro@orcam.me.uk>
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
Xiao Yang <yangx.jy@fujitsu.com>
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Nick Desaulniers <ndesaulniers@google.com>
Kconfig: add config option for asm goto w/ outputs
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix reset-controller leak on probe errors
Tejun Heo <tj@kernel.org>
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Dinh Nguyen <dinguyen@kernel.org>
dt-bindings: gpio: altera: correct interrupt-cells
Akira Yokosawa <akiyks@gmail.com>
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Arnd Bergmann <arnd@arndb.de>
ARM: pxa: maybe fix gpio lookup tables
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix struct clk leak on probe errors
Kathiravan T <quic_kathirav@quicinc.com>
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Xiaomeng Tong <xiam0nd.tong@gmail.com>
gma500: fix an incorrect NULL check on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
Jiri Slaby <jslaby@suse.cz>
serial: pch: don't overwrite xmit->buf[0] by x_char
Xiaomeng Tong <xiam0nd.tong@gmail.com>
carl9170: tx: fix an incorrect use of list iterator
Mark Brown <broonie@kernel.org>
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Alexander Wetzel <alexander@wetzel-home.de>
rtl818x: Prevent using not initialized queues
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix huge_pmd_unshare address update
Christophe de Dinechin <dinechin@redhat.com>
nodemask.h: fix compilation error with GCC12
Xiaomeng Tong <xiam0nd.tong@gmail.com>
iommu/msm: Fix an incorrect NULL check on list iterator
Vincent Whitchurch <vincent.whitchurch@axis.com>
um: Fix out-of-bounds read in LDT setup
Johannes Berg <johannes.berg@intel.com>
um: chan_user: Fix winch_tramp() return value
Felix Fietkau <nbd@nbd.name>
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Max Filippov <jcmvbkbc@gmail.com>
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Pali Rohár <pali@kernel.org>
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
RDMA/hfi1: Fix potential integer multiplication overflow errors
Sean Christopherson <seanjc@google.com>
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Add more H264 levels for CODA960
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Fix reported H264 profile
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in md_reload_sb
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in does_sb_need_changing
Brian Norris <briannorris@chromium.org>
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Xiaomeng Tong <xiam0nd.tong@gmail.com>
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
Lucas Stach <l.stach@pengutronix.de>
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Dave Airlie <airlied@redhat.com>
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Xiaomeng Tong <xiam0nd.tong@gmail.com>
scsi: dc395x: Fix a missing check on list iterator
Junxiao Bi via Ocfs2-devel <ocfs2-devel@oss.oracle.com>
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Alexander Aring <aahringo@redhat.com>
dlm: fix missing lkb refcount handling
Alexander Aring <aahringo@redhat.com>
dlm: fix plock invalid read
Rei Yamamoto <yamamoto.rei@jp.fujitsu.com>
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix unbalanced PHY init on probe errors
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix runtime PM imbalance on probe errors
Bjorn Helgaas <bhelgaas@google.com>
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
tracing: Fix potential double free in create_var_ref()
Sakari Ailus <sakari.ailus@linux.intel.com>
ACPI: property: Release subnode properties with data nodes
Jan Kara <jack@suse.cz>
ext4: avoid cycles in directory h-tree
Jan Kara <jack@suse.cz>
ext4: verify dir block before splitting it
Ye Bin <yebin10@huawei.com>
ext4: fix bug_on in ext4_writepages
Ye Bin <yebin10@huawei.com>
ext4: fix warning in ext4_handle_inode_extension
Ye Bin <yebin10@huawei.com>
ext4: fix use-after-free in ext4_rename_dir_prepare
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_tables: disallow non-stateful expression in sets earlier
Jan Kara <jack@suse.cz>
bfq: Track whether bfq_group is still online
Jan Kara <jack@suse.cz>
bfq: Update cgroup information before merging bio
Jan Kara <jack@suse.cz>
bfq: Split shared queues on move between cgroups
Aditya Garg <gargaditya08@live.com>
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Zhihao Cheng <chengzhihao1@huawei.com>
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
Emmanuel Grumbach <emmanuel.grumbach@intel.com>
iwlwifi: mvm: fix assert 1F04 upon reconfig
Johannes Berg <johannes.berg@intel.com>
wifi: mac80211: fix use-after-free in chanctx code
Chao Yu <chao@kernel.org>
f2fs: fix fallocate to use file_modified to update permissions consistently
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: don't need inode lock for system hidden quota
Chao Yu <chao@kernel.org>
f2fs: fix deadloop in foreground GC
Chao Yu <chao@kernel.org>
f2fs: fix to clear dirty inode in f2fs_evict_inode()
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
Chao Yu <chao@kernel.org>
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
Zhengjun Xing <zhengjun.xing@linux.intel.com>
perf jevents: Fix event syntax error caused by ExtSel
Leo Yan <leo.yan@linaro.org>
perf c2c: Use stdio interface if slang is not supported
Joerg Roedel <jroedel@suse.de>
iommu/amd: Increase timeout waiting for GA log enablement
Amelie Delaunay <amelie.delaunay@foss.st.com>
dmaengine: stm32-mdma: remove GISR1 register
Miaoqian Lin <linmq006@gmail.com>
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Don't report errors from nfs_pageio_complete() more than once
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report flush errors in nfs_write_end()
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
Nathan Chancellor <nathan@kernel.org>
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Michael Walle <michael@walle.cc>
i2c: at91: use dma safe buffers
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Add list_del in mtk_iommu_remove
Jakob Koschel <jakobkoschel@gmail.com>
f2fs: fix dereference of stale list iterator after loop body
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: stmfts - do not leave device disabled in stmfts_input_open
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent use of lock before it is initialized
Björn Ardö <bjorn.ardo@axis.com>
mailbox: forward the hrtimer if not queued and under a lock
Yang Yingliang <yangyingliang@huawei.com>
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
Miaoqian Lin <linmq006@gmail.com>
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
Randy Dunlap <rdunlap@infradead.org>
macintosh: via-pmu and via-cuda need RTC_LIB
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf: Fix the threshold compare group constraint for power9
Michael Ellerman <mpe@ellerman.id.au>
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
Miaoqian Lin <linmq006@gmail.com>
Input: sparcspkr - fix refcount leak in bbc_beep_probe
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
crypto: cryptd - Protect per-CPU resource by disabling BH.
Qi Zheng <zhengqi.arch@bytedance.com>
tty: fix deadlock caused by calling printk() under tty_port->lock
Francesco Dolcini <francesco.dolcini@toradex.com>
PCI: imx6: Fix PERST# start-up sequence
Waiman Long <longman@redhat.com>
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
Alexey Dobriyan <adobriyan@gmail.com>
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
Randy Dunlap <rdunlap@infradead.org>
powerpc/4xx/cpm: Fix return value of __setup() handler
Randy Dunlap <rdunlap@infradead.org>
powerpc/idle: Fix return value of __setup() handler
Randy Dunlap <rdunlap@infradead.org>
powerpc/8xx: export 'cpm_setbrg' for modules
Muchun Song <songmuchun@bytedance.com>
dax: fix cache flush on PMD-mapped pages
Miaohe Lin <linmiaohe@huawei.com>
drivers/base/node.c: fix compaction sysfs file leak
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
Dan Williams <dan.j.williams@intel.com>
nvdimm: Allow overwrite in the presence of disabled dimms
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Gustavo A. R. Silva <gustavoars@kernel.org>
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
Lv Ruyi <lv.ruyi@zte.com.cn>
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: fix PT_LOAD segment for boot memory area
Chuanhong Guo <gch981213@gmail.com>
arm: mediatek: select arch timer for mt7629
Corentin Labbe <clabbe@baylibre.com>
crypto: marvell/cesa - ECB does not IV
Hangyu Hua <hbh25y@gmail.com>
misc: ocxl: fix possible double free in ocxl_file_register_afu
Stefan Wahren <stefan.wahren@i2se.com>
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
Marc Kleine-Budde <mkl@pengutronix.de>
can: xilinx_can: mark bit timing constants as const
Sean Christopherson <seanjc@google.com>
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
Dan Carpenter <dan.carpenter@oracle.com>
PCI: rockchip: Fix find_first_zero_bit() limit
Dan Carpenter <dan.carpenter@oracle.com>
PCI: cadence: Fix find_first_zero_bit() limit
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
Andre Przywara <andre.przywara@arm.com>
ARM: dts: suniv: F1C100: fix watchdog compatible
Shawn Lin <shawn.lin@rock-chips.com>
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
liuyacan <liuyacan@corp.netease.com>
net/smc: postpone sk_refcnt increment in connect()
David Howells <dhowells@redhat.com>
rxrpc: Fix decision on when to generate an IDLE ACK
David Howells <dhowells@redhat.com>
rxrpc: Don't let ack.previousPacket regress
David Howells <dhowells@redhat.com>
rxrpc: Fix overlapping ACK accounting
David Howells <dhowells@redhat.com>
rxrpc: Don't try to resend the request if we're receiving the reply
David Howells <dhowells@redhat.com>
rxrpc: Fix listen() setting the bar too high for the prealloc rings
Duoming Zhou <duoming@zju.edu.cn>
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
Yang Yingliang <yangyingliang@huawei.com>
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
Zheng Yongjun <zhengyongjun3@huawei.com>
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
Hangyu Hua <hbh25y@gmail.com>
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
Miaoqian Lin <linmq006@gmail.com>
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
Eric Biggers <ebiggers@google.com>
ext4: reject the 'commit' option on ext2 filesystems
Dongliang Mu <mudongliangabcd@gmail.com>
media: ov7670: remove ov7670_power_off from ov7670_remove
Eric Dumazet <edumazet@google.com>
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
Geert Uytterhoeven <geert@linux-m68k.org>
m68k: math-emu: Fix dependencies of math emulation support
Ying Hsu <yinghsu@chromium.org>
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Michael Rodin <mrodin@de.adit-jv.com>
media: vsp1: Fix offset calculation for plane cropping
Pavel Skripkin <paskripkin@gmail.com>
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Miaoqian Lin <linmq006@gmail.com>
media: exynos4-is: Change clk_disable to clk_disable_unprepare
Miaoqian Lin <linmq006@gmail.com>
media: st-delta: Fix PM disable depth imbalance in delta_probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: aspeed: Fix an error handling path in aspeed_video_probe()
Josh Poimboeuf <jpoimboe@kernel.org>
scripts/faddr2line: Fix overlapping text section failures
Miaoqian Lin <linmq006@gmail.com>
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
Miaoqian Lin <linmq006@gmail.com>
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
Ravi Bangoria <ravi.bangoria@amd.com>
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Viresh Kumar <viresh.kumar@linaro.org>
Revert "cpufreq: Fix possible race in cpufreq online error path"
Andreas Gruenbacher <agruenba@redhat.com>
iomap: iomap_write_failed fix
Xiaomeng Tong <xiam0nd.tong@gmail.com>
media: uvcvideo: Fix missing check to determine if element is found in list
Dan Carpenter <dan.carpenter@oracle.com>
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
Zev Weiss <zev@bewilderbeest.net>
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Randy Dunlap <rdunlap@infradead.org>
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
Daniel Thompson <daniel.thompson@linaro.org>
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Randy Dunlap <rdunlap@infradead.org>
x86: Fix return value of __setup handlers
Christoph Hellwig <hch@lst.de>
virtio_blk: fix the discard_granularity and discard_alignment queue limits
Yang Yingliang <yangyingliang@huawei.com>
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
Yang Yingliang <yangyingliang@huawei.com>
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix error checks and return values for DSI xmit functions
Vinod Polimera <quic_vpolimer@quicinc.com>
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
Yang Jihong <yangjihong1@huawei.com>
perf tools: Add missing headers needed by util/data.h
Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
ASoC: rk3328: fix disabling mclk on pclk probe failure
Josh Poimboeuf <jpoimboe@redhat.com>
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
Matthieu Baerts <matthieu.baerts@tessares.net>
x86/pm: Fix false positive kmemleak report in msr_build_context()
Kiwoong Kim <kwmad.kim@samsung.com>
scsi: ufs: core: Exclude UECxx from SFR dump list
Nuno Sá <nuno.sa@analog.com>
of: overlay: do not break notify on NOTIFY_{OK|STOP}
Amir Goldstein <amir73il@gmail.com>
fsnotify: fix wrong lockdep annotations
Amir Goldstein <amir73il@gmail.com>
inotify: show inotify mask flags in proc fdinfo
Dan Carpenter <dan.carpenter@oracle.com>
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
Schspa Shi <schspa@gmail.com>
cpufreq: Fix possible race in cpufreq online error path
Zheng Yongjun <zhengyongjun3@huawei.com>
spi: img-spfi: Fix pm_runtime_get_sync() error checking
Chengming Zhou <zhouchengming@bytedance.com>
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
Miaoqian Lin <linmq006@gmail.com>
drm/bridge: Fix error handling in analogix_dp_probe
Miaoqian Lin <linmq006@gmail.com>
HID: elan: Fix potential double free in elan_input_configured
Jonathan Teh <jonathan.teh@outlook.com>
HID: hid-led: fix maximum brightness for Dream Cheeky
Arnd Bergmann <arnd@arndb.de>
drbd: fix duplicate array initializer
Jan Kiszka <jan.kiszka@siemens.com>
efi: Add missing prototype for efi_capsule_setup_info
Lin Ma <linma@zju.edu.cn>
NFC: NULL out the dev->rfkill to prevent UAF
Miaoqian Lin <linmq006@gmail.com>
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
Jiasheng Jiang <jiasheng@iscas.ac.cn>
drm: mali-dp: potential dereference of null pointer
Zhou Qingyang <zhou1615@umn.edu>
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Johannes Berg <johannes.berg@intel.com>
nl80211: show SSID for P2P_GO interfaces
Yuntao Wang <ytcoode@gmail.com>
bpf: Fix excessive memory allocation in stack_map_alloc()
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
Miles Chen <miles.chen@mediatek.com>
drm/mediatek: Fix mtk_cec_mask()
Ammar Faizi <ammarfaizi2@gnuweeb.org>
x86/delay: Fix the wrong asm constraint in delay_loop()
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
Lucas Stach <l.stach@pengutronix.de>
drm/bridge: adv7511: clean up CEC adapter when probe fails
Jani Nikula <jani.nikula@intel.com>
drm/edid: fix invalid EDID extension block filtering
Wenli Looi <wlooi@ucalgary.ca>
ath9k: fix ar9003_get_eepmisc
Linus Torvalds <torvalds@linux-foundation.org>
drm: fix EDID struct for old ARM OABI format
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent panic when SDMA is disabled
Peng Wu <wupeng58@huawei.com>
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Finn Thain <fthain@linux-m68k.org>
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/powernv: fix missing of_node_put in uv_init()
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/xics: fix refcount leak in icp_opal_init()
Vasily Averin <vvs@openvz.org>
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
Yicong Yang <yangyicong@hisilicon.com>
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Peng Wu <wupeng58@huawei.com>
ARM: hisi: Add missing of_node_put after of_find_compatible_node
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
Peng Wu <wupeng58@huawei.com>
ARM: versatile: Add missing of_node_put in dcscb_init
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
fat: add ratelimit to fat*_ent_bread()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: Fix fadump to work with a different endian capture kernel
Janusz Krzysztofik <jmkrzyszt@gmail.com>
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Zixuan Fu <r33s3n6@gmail.com>
fs: jfs: fix possible NULL pointer dereference in dbFree()
Brian Norris <briannorris@chromium.org>
PM / devfreq: rk3399_dmc: Disable edev on remove()
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: ox820: align interrupt controller node name with dtschema
Niels Dossche <dossche.niels@gmail.com>
IB/rdmavt: add missing locks in rvt_ruc_loopback
Yonghong Song <yhs@fb.com>
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Jakub Kicinski <kuba@kernel.org>
eth: tg3: silence the GCC 12 array-bounds warning
David Howells <dhowells@redhat.com>
rxrpc: Return an error to sendmsg if call failed
Guenter Roeck <linux@roeck-us.net>
hwmon: Make chip parameter for with_info API mandatory
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: max98357a: remove dependency on GPIOLIB
Kwanghoon Son <k.son@samsung.com>
media: exynos4-is: Fix compile warning
Fabio Estevam <festevam@denx.de>
net: phy: micrel: Allow probing without .driver_data
Xie Yongji <xieyongji@bytedance.com>
nbd: Fix hung on disconnect request if socket is closed before
Lin Ma <linma@zju.edu.cn>
ASoC: rt5645: Fix errorenous cleanup order
Smith, Kyle Miller (Nimble Kernel) <kyles@hpe.com>
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Jason A. Donenfeld <Jason@zx2c4.com>
openrisc: start CPU timer early in boot
Hans Verkuil <hverkuil-cisco@xs4all.nl>
media: cec-adap.c: fix is_configuring state
Philipp Zabel <p.zabel@pengutronix.de>
media: coda: limit frame interval enumeration to supported encoder frame sizes
Dongliang Mu <mudongliangabcd@gmail.com>
rtlwifi: Use pr_warn instead of WARN_ONCE
Corey Minyard <cminyard@mvista.com>
ipmi: Fix pr_fmt to avoid compilation issues
Corey Minyard <cminyard@mvista.com>
ipmi:ssif: Check for NULL msg when handling events and messages
Mario Limonciello <mario.limonciello@amd.com>
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
Mikulas Patocka <mpatocka@redhat.com>
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
Patrice Chotard <patrice.chotard@foss.st.com>
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Heiko Carstens <hca@linux.ibm.com>
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
Dongliang Mu <mudongliangabcd@gmail.com>
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
Alice Wong <shiwei.wong@amd.com>
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Petr Machata <petrm@nvidia.com>
mlxsw: spectrum_dcb: Do not warn about priority changes
Mark Brown <broonie@kernel.org>
ASoC: dapm: Don't fold register value changes into notifications
Mark Bloch <mbloch@nvidia.com>
net/mlx5: fs, delete the FTE when there are no rules attached to it
jianghaoran <jianghaoran@kylinos.cn>
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
Lv Ruyi <lv.ruyi@zte.com.cn>
drm: msm: fix error check return value of irq_of_parse_and_map()
Alexandru Elisei <alexandru.elisei@arm.com>
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Evan Quan <evan.quan@amd.com>
drm/amd/pm: fix the compile warning
Steven Price <steven.price@arm.com>
drm/plane: Move range check for format_count earlier
Lv Ruyi <lv.ruyi@zte.com.cn>
scsi: megaraid: Fix error check return value of register_chrdev()
Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
mmc: jz4740: Apply DMA engine limits to maximum segment size
Heming Zhao <heming.zhao@suse.com>
md/bitmap: don't set sb values if can't pass sanity check
Zheyu Ma <zheyuma97@gmail.com>
media: cx25821: Fix the warning when removing the module
Zheyu Ma <zheyuma97@gmail.com>
media: pci: cx23885: Fix the error handling in cx23885_initdev()
Luca Weiss <luca.weiss@fairphone.com>
media: venus: hfi: avoid null dereference in deinit
Thibaut VARÈNE <hacks+kernel@slashdirt.org>
ath9k: fix QCA9561 PA bias level
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
drm/amd/pm: fix double free in si_parse_power_table()
Len Brown <len.brown@intel.com>
tools/power turbostat: fix ICX DRAM power numbers
Biju Das <biju.das.jz@bp.renesas.com>
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
ALSA: jack: Access input_dev under mutex
Liviu Dudau <liviu.dudau@arm.com>
drm/komeda: return early if drm_universal_plane_init() fails.
Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
ACPICA: Avoid cache flush inside virtual machines
Daniel Vetter <daniel.vetter@ffwll.ch>
fbcon: Consistently protect deferred_takeover with console_lock()
Niels Dossche <dossche.niels@gmail.com>
ipv6: fix locking issues with loops over idev->addr_list
Haowen Bai <baihaowen@meizu.com>
ipw2x00: Fix potential NULL dereference in libipw_xmit()
Haowen Bai <baihaowen@meizu.com>
b43: Fix assigning negative value to unsigned variable
Haowen Bai <baihaowen@meizu.com>
b43legacy: Fix assigning negative value to unsigned variable
Niels Dossche <dossche.niels@gmail.com>
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
Liu Zixian <liuzixian4@huawei.com>
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Qu Wenruo <wqu@suse.com>
btrfs: repair super block num_devices automatically
Qu Wenruo <wqu@suse.com>
btrfs: add "0x" prefix for unsupported optional features
Eric W. Biederman <ebiederm@xmission.com>
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Eric W. Biederman <ebiederm@xmission.com>
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
Eric W. Biederman <ebiederm@xmission.com>
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
Kan Liang <kan.liang@linux.intel.com>
perf/x86/intel: Fix event constraints for ICL
Kishon Vijay Abraham I <kishon@ti.com>
usb: core: hcd: Add support for deferring roothub registration
Monish Kumar R <monish.kumar.r@intel.com>
USB: new quirk for Dell Gen 2 devices
Carl Yin(殷张成) <carl.yin@quectel.com>
USB: serial: option: add Quectel BG95 modem
Marios Levogiannis <marios.levogiannis@gmail.com>
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Niklas Cassel <niklas.cassel@wdc.com>
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
-------------
Diffstat:
Documentation/ABI/testing/sysfs-ata | 11 +-
Documentation/conf.py | 2 +-
.../devicetree/bindings/gpio/gpio-altera.txt | 5 +-
Documentation/hwmon/hwmon-kernel-api.rst | 2 +-
Makefile | 4 +-
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13 +-
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22 +--
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4 +-
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4 +-
arch/arm/boot/dts/ox820.dtsi | 2 +-
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4 +-
arch/arm/mach-hisi/platsmp.c | 4 +
arch/arm/mach-mediatek/Kconfig | 1 +
arch/arm/mach-omap1/clock.c | 2 +-
arch/arm/mach-pxa/cm-x300.c | 8 +-
arch/arm/mach-pxa/magician.c | 2 +-
arch/arm/mach-pxa/tosa.c | 4 +-
arch/arm/mach-vexpress/dcscb.c | 1 +
arch/arm64/Kconfig.platforms | 1 +
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +-
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
arch/arm64/kernel/sys_compat.c | 2 +-
arch/arm64/net/bpf_jit_comp.c | 1 +
arch/m68k/Kconfig.cpu | 2 +-
arch/m68k/Kconfig.machine | 1 +
arch/m68k/include/asm/pgtable_no.h | 3 +-
.../include/asm/mach-ip27/cpu-feature-overrides.h | 1 -
arch/mips/kernel/mips-cpc.c | 1 +
arch/openrisc/include/asm/timex.h | 1 +
arch/openrisc/kernel/head.S | 9 ++
arch/powerpc/include/asm/page.h | 7 +-
arch/powerpc/kernel/fadump.c | 8 +-
arch/powerpc/kernel/idle.c | 2 +-
arch/powerpc/kernel/ptrace.c | 21 ++-
arch/powerpc/perf/isa207-common.c | 3 +-
arch/powerpc/platforms/4xx/cpm.c | 2 +-
arch/powerpc/platforms/8xx/cpm1.c | 1 +
arch/powerpc/platforms/powernv/opal-fadump.c | 94 +++++++------
arch/powerpc/platforms/powernv/opal-fadump.h | 10 +-
arch/powerpc/platforms/powernv/ultravisor.c | 1 +
arch/powerpc/sysdev/dart_iommu.c | 6 +-
arch/powerpc/sysdev/fsl_rio.c | 2 +
arch/powerpc/sysdev/xics/icp-opal.c | 1 +
arch/s390/crypto/aes_s390.c | 4 +-
arch/s390/include/asm/preempt.h | 15 ++-
arch/s390/mm/gmap.c | 14 ++
arch/um/drivers/chan_user.c | 9 +-
arch/um/include/asm/thread_info.h | 2 +
arch/um/kernel/exec.c | 2 +-
arch/um/kernel/process.c | 2 +-
arch/um/kernel/ptrace.c | 8 +-
arch/um/kernel/signal.c | 4 +-
arch/x86/entry/vdso/vma.c | 2 +-
arch/x86/events/amd/ibs.c | 18 +++
arch/x86/events/intel/core.c | 2 +-
arch/x86/include/asm/acenv.h | 14 +-
arch/x86/include/asm/cpufeature.h | 2 +-
arch/x86/include/asm/suspend_32.h | 2 +-
arch/x86/include/asm/suspend_64.h | 12 +-
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/cpu/intel.c | 2 +-
arch/x86/kernel/step.c | 3 +-
arch/x86/kernel/sys_x86_64.c | 7 +-
arch/x86/kvm/vmx/nested.c | 15 ++-
arch/x86/lib/delay.c | 4 +-
arch/x86/mm/pat.c | 2 +-
arch/x86/um/ldt.c | 6 +-
arch/xtensa/kernel/ptrace.c | 4 +-
arch/xtensa/kernel/signal.c | 4 +-
block/bfq-cgroup.c | 111 +++++++++------
block/bfq-iosched.c | 46 ++++---
block/bfq-iosched.h | 6 +-
block/bio.c | 2 +-
block/blk-iolatency.c | 122 +++++++++--------
crypto/cryptd.c | 23 ++--
drivers/acpi/property.c | 18 ++-
drivers/acpi/sleep.c | 12 ++
drivers/ata/libata-transport.c | 2 +-
drivers/ata/pata_octeon_cf.c | 3 +
drivers/base/bus.c | 4 +-
drivers/base/dd.c | 5 +-
drivers/base/node.c | 1 +
drivers/block/drbd/drbd_main.c | 11 +-
drivers/block/nbd.c | 50 ++++---
drivers/block/virtio_blk.c | 7 +-
drivers/bus/ti-sysc.c | 4 +-
drivers/char/ipmi/ipmi_msghandler.c | 4 +-
drivers/char/ipmi/ipmi_ssif.c | 23 ++++
drivers/clocksource/timer-oxnas-rps.c | 2 +-
drivers/clocksource/timer-riscv.c | 2 +-
drivers/clocksource/timer-sp804.c | 10 +-
drivers/crypto/marvell/cipher.c | 1 -
drivers/devfreq/rk3399_dmc.c | 2 +
drivers/dma/stm32-mdma.c | 21 +--
drivers/dma/xilinx/zynqmp_dma.c | 5 +-
drivers/extcon/extcon.c | 29 ++--
drivers/firmware/arm_scmi/base.c | 2 +-
drivers/firmware/dmi-sysfs.c | 2 +-
drivers/firmware/stratix10-svc.c | 12 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 +-
drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 14 +-
drivers/gpu/drm/amd/amdgpu/si_dpm.c | 8 +-
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10 +-
drivers/gpu/drm/arm/malidp_crtc.c | 5 +-
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1 +
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31 ++++-
drivers/gpu/drm/drm_edid.c | 6 +-
drivers/gpu/drm/drm_plane.c | 14 +-
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6 +
drivers/gpu/drm/gma500/psb_intel_display.c | 7 +-
drivers/gpu/drm/imx/ipuv3-crtc.c | 2 +-
drivers/gpu/drm/mediatek/mtk_cec.c | 2 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15 ++-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15 ++-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20 ++-
drivers/gpu/drm/msm/dsi/dsi_host.c | 21 ++-
drivers/gpu/drm/msm/hdmi/hdmi.c | 10 +-
drivers/gpu/drm/msm/msm_gem_prime.c | 2 +-
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6 +-
drivers/gpu/drm/radeon/radeon_connectors.c | 4 +
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 +-
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8 +-
drivers/gpu/drm/vc4/vc4_txp.c | 8 +-
drivers/gpu/drm/virtio/virtgpu_display.c | 2 +
drivers/hid/hid-bigbenff.c | 6 +
drivers/hid/hid-elan.c | 2 -
drivers/hid/hid-led.c | 2 +-
drivers/hwmon/hwmon.c | 16 +--
drivers/hwtracing/coresight/coresight-cpu-debug.c | 7 +-
drivers/i2c/busses/i2c-at91-master.c | 11 ++
drivers/i2c/busses/i2c-cadence.c | 12 +-
drivers/iio/adc/ad7124.c | 1 -
drivers/iio/adc/sc27xx_adc.c | 20 +--
drivers/iio/adc/stmpe-adc.c | 8 +-
drivers/iio/common/st_sensors/st_sensors_core.c | 24 +++-
drivers/iio/dummy/iio_simple_dummy.c | 20 +--
drivers/infiniband/hw/hfi1/file_ops.c | 2 +
drivers/infiniband/hw/hfi1/init.c | 2 +-
drivers/infiniband/hw/hfi1/sdma.c | 12 +-
drivers/infiniband/sw/rdmavt/qp.c | 6 +-
drivers/infiniband/sw/rxe/rxe_req.c | 2 +-
drivers/input/misc/sparcspkr.c | 1 +
drivers/input/mouse/bcm5974.c | 7 +-
drivers/input/touchscreen/stmfts.c | 16 +--
drivers/iommu/amd_iommu_init.c | 2 +-
drivers/iommu/msm_iommu.c | 11 +-
drivers/iommu/mtk_iommu.c | 3 +-
drivers/irqchip/irq-armada-370-xp.c | 11 +-
drivers/irqchip/irq-aspeed-i2c-ic.c | 4 +-
drivers/irqchip/irq-sni-exiu.c | 25 +++-
drivers/irqchip/irq-xtensa-mx.c | 18 ++-
drivers/macintosh/Kconfig | 6 +
drivers/macintosh/Makefile | 3 +-
drivers/macintosh/via-pmu.c | 2 +-
drivers/mailbox/mailbox.c | 19 ++-
drivers/md/bcache/request.c | 6 +
drivers/md/md-bitmap.c | 44 +++---
drivers/md/md.c | 33 +++--
drivers/md/raid0.c | 31 ++---
drivers/media/cec/cec-adap.c | 6 +-
drivers/media/i2c/ov7670.c | 1 -
drivers/media/pci/cx23885/cx23885-core.c | 6 +-
drivers/media/pci/cx25821/cx25821-core.c | 2 +-
drivers/media/platform/aspeed-video.c | 4 +-
drivers/media/platform/coda/coda-common.c | 35 +++--
drivers/media/platform/exynos4-is/fimc-is.c | 2 +-
drivers/media/platform/exynos4-is/fimc-isp-video.h | 2 +-
drivers/media/platform/qcom/venus/hfi.c | 3 +
drivers/media/platform/sti/delta/delta-v4l2.c | 6 +-
drivers/media/platform/vsp1/vsp1_rpf.c | 6 +-
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7 +-
drivers/media/usb/uvc/uvc_v4l2.c | 20 +--
drivers/mfd/davinci_voicecodec.c | 6 +-
drivers/mfd/ipaq-micro.c | 2 +-
drivers/misc/cardreader/rtsx_usb.c | 1 +
drivers/misc/lkdtm/usercopy.c | 17 ++-
drivers/misc/ocxl/file.c | 2 +
drivers/mmc/core/block.c | 3 +-
drivers/mmc/host/jz4740_mmc.c | 20 +++
drivers/mtd/chips/cfi_cmdset_0002.c | 103 +++++++-------
drivers/mtd/ubi/vmt.c | 1 -
drivers/net/can/xilinx_can.c | 4 +-
drivers/net/dsa/lantiq_gswip.c | 4 +-
drivers/net/dsa/mv88e6xxx/chip.c | 1 +
drivers/net/ethernet/altera/altera_tse_main.c | 6 +-
drivers/net/ethernet/broadcom/Makefile | 5 +
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 8 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 2 +-
.../ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 7 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 5 +
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 45 +++++--
.../ethernet/mellanox/mlx5/core/steering/fs_dr.c | 9 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13 --
.../net/ethernet/netronome/nfp/nfp_net_ethtool.c | 4 +-
drivers/net/phy/mdio_bus.c | 1 -
drivers/net/phy/micrel.c | 11 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8 ++
drivers/net/wireless/ath/carl9170/tx.c | 3 +
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/broadcom/b43legacy/phy.c | 2 +-
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3 +
drivers/net/wireless/marvell/mwifiex/11h.c | 2 +
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8 +-
drivers/net/wireless/realtek/rtlwifi/usb.c | 2 +-
drivers/nfc/st21nfca/se.c | 32 ++++-
drivers/nfc/st21nfca/st21nfca.h | 1 +
drivers/nvdimm/security.c | 5 -
drivers/nvme/host/pci.c | 1 +
drivers/of/overlay.c | 4 +-
drivers/pci/controller/dwc/pci-imx6.c | 23 ++--
drivers/pci/controller/dwc/pcie-qcom.c | 9 +-
drivers/pci/controller/pcie-cadence-ep.c | 3 +-
drivers/pci/controller/pcie-rockchip-ep.c | 3 +-
drivers/pci/pci.c | 12 +-
drivers/pcmcia/Kconfig | 2 +-
drivers/phy/qualcomm/phy-qcom-qmp.c | 13 +-
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2 +-
drivers/pwm/pwm-lp3943.c | 1 +
drivers/regulator/core.c | 7 +-
drivers/regulator/pfuze100-regulator.c | 2 +
drivers/rpmsg/qcom_smd.c | 4 +-
drivers/rtc/rtc-mt6397.c | 2 +
drivers/scsi/dc395x.c | 15 ++-
drivers/scsi/fcoe/fcoe_ctlr.c | 2 +-
drivers/scsi/megaraid.c | 2 +-
drivers/scsi/myrb.c | 11 +-
drivers/scsi/ufs/ufs-qcom.c | 7 +-
drivers/scsi/ufs/ufshcd.c | 7 +-
drivers/soc/qcom/smp2p.c | 1 +
drivers/soc/qcom/smsm.c | 1 +
drivers/soc/rockchip/grf.c | 2 +
drivers/spi/spi-img-spfi.c | 2 +-
drivers/spi/spi-rspi.c | 15 +--
drivers/spi/spi-stm32-qspi.c | 3 +-
drivers/spi/spi-ti-qspi.c | 5 +-
drivers/staging/fieldbus/anybuss/host.c | 2 +-
drivers/staging/greybus/audio_codec.c | 4 +-
drivers/staging/rtl8192e/rtllib_softmac.c | 2 +-
.../staging/rtl8192u/ieee80211/ieee80211_softmac.c | 2 +-
drivers/staging/rtl8712/usb_intf.c | 6 +-
drivers/staging/rtl8712/usb_ops.c | 27 ++--
drivers/thermal/broadcom/sr-thermal.c | 3 +
drivers/tty/goldfish.c | 2 +
drivers/tty/serial/8250/8250_fintek.c | 8 +-
drivers/tty/serial/digicolor-usart.c | 2 +
drivers/tty/serial/fsl_lpuart.c | 24 +---
drivers/tty/serial/icom.c | 2 +-
drivers/tty/serial/meson_uart.c | 13 ++
drivers/tty/serial/msm_serial.c | 5 +
drivers/tty/serial/owl-uart.c | 1 +
drivers/tty/serial/pch_uart.c | 27 +---
drivers/tty/serial/rda-uart.c | 2 +
drivers/tty/serial/sa1100.c | 4 +-
drivers/tty/serial/serial_txx9.c | 2 +
drivers/tty/serial/sh-sci.c | 6 +-
drivers/tty/serial/sifive.c | 8 +-
drivers/tty/serial/st-asc.c | 4 +
drivers/tty/serial/stm32-usart.c | 15 ++-
drivers/tty/synclink_gt.c | 2 +
drivers/tty/tty_buffer.c | 3 +-
drivers/usb/core/hcd-pci.c | 4 +-
drivers/usb/core/hcd.c | 29 +++-
drivers/usb/core/quirks.c | 3 +
drivers/usb/dwc2/gadget.c | 1 -
drivers/usb/dwc3/dwc3-pci.c | 2 +-
drivers/usb/host/isp116x-hcd.c | 6 +-
drivers/usb/host/oxu210hp-hcd.c | 2 +
drivers/usb/musb/omap2430.c | 1 +
drivers/usb/serial/option.c | 2 +
drivers/usb/storage/karma.c | 15 ++-
drivers/usb/usbip/stub_dev.c | 2 +-
drivers/usb/usbip/stub_rx.c | 2 +
drivers/vhost/vringh.c | 10 +-
drivers/video/fbdev/amba-clcd.c | 5 +-
drivers/video/fbdev/core/fbcon.c | 5 +-
drivers/video/fbdev/pxa3xx-gcu.c | 12 +-
drivers/watchdog/ts4800_wdt.c | 5 +-
drivers/watchdog/wdat_wdt.c | 1 +
drivers/xen/xlate_mmu.c | 1 -
fs/afs/dir.c | 5 +-
fs/binfmt_flat.c | 27 +++-
fs/btrfs/disk-io.c | 4 +-
fs/btrfs/volumes.c | 8 +-
fs/ceph/xattr.c | 10 +-
fs/cifs/cifsglob.h | 4 +-
fs/cifs/smb2ops.c | 7 +-
fs/cifs/smb2pdu.c | 3 +
fs/dax.c | 3 +-
fs/dlm/lock.c | 11 +-
fs/dlm/plock.c | 12 +-
fs/ext4/inline.c | 12 ++
fs/ext4/inode.c | 4 +
fs/ext4/namei.c | 84 +++++++++---
fs/ext4/super.c | 1 +
fs/f2fs/checkpoint.c | 4 +-
fs/f2fs/f2fs.h | 14 +-
fs/f2fs/file.c | 20 ++-
fs/f2fs/inode.c | 16 ++-
fs/f2fs/segment.c | 9 +-
fs/f2fs/segment.h | 32 +++--
fs/f2fs/super.c | 6 +-
fs/fat/fatent.c | 7 +-
fs/fs-writeback.c | 13 +-
fs/iomap/buffered-io.c | 3 +-
fs/jffs2/fs.c | 1 +
fs/jfs/jfs_dmap.c | 3 +-
fs/kernfs/dir.c | 31 +++--
fs/nfs/file.c | 7 +-
fs/nfs/nfs4proc.c | 4 +
fs/nfs/pnfs.c | 2 +
fs/nfs/write.c | 11 +-
fs/notify/fdinfo.c | 11 +-
fs/notify/inotify/inotify.h | 12 ++
fs/notify/inotify/inotify_user.c | 2 +-
fs/notify/mark.c | 6 +-
fs/ocfs2/dlmfs/userdlm.c | 16 ++-
fs/proc/generic.c | 3 +
fs/proc/proc_net.c | 3 +
include/drm/drm_edid.h | 6 +-
include/linux/bpf.h | 2 +
include/linux/efi.h | 2 +
include/linux/iio/common/st_sensors.h | 3 +
include/linux/mailbox_controller.h | 1 +
include/linux/mtd/cfi.h | 1 +
include/linux/nodemask.h | 51 ++++---
include/linux/ptrace.h | 7 -
include/linux/usb/hcd.h | 2 +
include/net/if_inet6.h | 8 ++
include/net/sch_generic.h | 42 ++----
include/scsi/libfcoe.h | 3 +-
include/sound/jack.h | 1 +
include/trace/events/rxrpc.h | 2 +-
include/trace/events/vmscan.h | 4 +-
init/Kconfig | 9 ++
ipc/mqueue.c | 14 ++
kernel/bpf/stackmap.c | 1 -
kernel/dma/debug.c | 2 +-
kernel/ptrace.c | 5 +-
kernel/sched/fair.c | 8 +-
kernel/sched/pelt.h | 4 +-
kernel/sched/sched.h | 4 +-
kernel/trace/trace.c | 13 +-
kernel/trace/trace_events_hist.c | 3 +
lib/nodemask.c | 4 +-
mm/compaction.c | 2 +
mm/hugetlb.c | 9 +-
net/bluetooth/sco.c | 21 +--
net/ipv4/ip_gre.c | 11 +-
net/ipv4/tcp_output.c | 4 +-
net/ipv4/xfrm4_protocol.c | 1 -
net/ipv6/addrconf.c | 33 ++++-
net/ipv6/seg6_hmac.c | 1 -
net/key/af_key.c | 10 +-
net/mac80211/chan.c | 7 +-
net/mac80211/ieee80211_i.h | 5 +
net/mac80211/scan.c | 20 +++
net/netfilter/nf_tables_api.c | 22 ++-
net/netfilter/nft_dynset.c | 3 -
net/netfilter/nft_nat.c | 3 +-
net/nfc/core.c | 1 +
net/rxrpc/ar-internal.h | 13 +-
net/rxrpc/call_event.c | 3 +-
net/rxrpc/input.c | 31 +++--
net/rxrpc/output.c | 20 +--
net/rxrpc/recvmsg.c | 8 +-
net/rxrpc/sendmsg.c | 6 +
net/rxrpc/sysctl.c | 4 +-
net/sctp/input.c | 4 +-
net/smc/af_smc.c | 2 +-
net/sunrpc/xdr.c | 6 +-
net/sunrpc/xprtrdma/rpc_rdma.c | 5 +
net/tipc/bearer.c | 3 +-
net/unix/af_unix.c | 2 +-
net/wireless/nl80211.c | 1 +
scripts/faddr2line | 150 +++++++++++++--------
scripts/gdb/linux/config.py | 6 +-
scripts/mod/modpost.c | 5 +-
.../integrity/platform_certs/keyring_handler.h | 8 ++
security/integrity/platform_certs/load_uefi.c | 33 +++++
sound/core/jack.c | 34 ++++-
sound/pci/hda/patch_conexant.c | 7 +
sound/pci/hda/patch_realtek.c | 10 ++
sound/soc/codecs/Kconfig | 1 -
sound/soc/codecs/rk3328_codec.c | 2 +-
sound/soc/codecs/rt5514.c | 2 +-
sound/soc/codecs/rt5645.c | 7 +-
sound/soc/codecs/tscs454.c | 12 +-
sound/soc/codecs/wm2000.c | 6 +-
sound/soc/fsl/fsl_sai.h | 4 +-
sound/soc/fsl/imx-sgtl5000.c | 14 +-
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9 +-
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5 +-
sound/soc/mxs/mxs-saif.c | 1 +
sound/soc/soc-dapm.c | 2 -
tools/perf/builtin-c2c.c | 10 +-
tools/perf/pmu-events/jevents.c | 2 +-
tools/perf/util/data.h | 1 +
tools/power/x86/turbostat/turbostat.c | 1 +
.../bpf/progs/btf_dump_test_case_syntax.c | 2 +-
tools/testing/selftests/netfilter/nft_nat.sh | 43 ++++++
412 files changed, 2494 insertions(+), 1313 deletions(-)
^ permalink raw reply [relevance 1%]
* Linux 5.18.3
@ 2022-06-09 8:39 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-09 8:39 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.18.3 kernel.
All users of the 5.18 kernel series must upgrade.
The updated 5.18.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.18.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/accounting/psi.rst | 9
Documentation/conf.py | 2
Documentation/devicetree/bindings/display/sitronix,st7735r.yaml | 1
Documentation/devicetree/bindings/gpio/gpio-altera.txt | 5
Documentation/devicetree/bindings/regulator/mt6315-regulator.yaml | 2
Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml | 1
Documentation/devicetree/bindings/spi/qcom,spi-qcom-qspi.yaml | 1
Documentation/driver-api/thermal/intel_dptf.rst | 2
Documentation/sound/alsa-configuration.rst | 4
Documentation/userspace-api/landlock.rst | 4
Documentation/userspace-api/media/lirc.h.rst.exceptions | 2
Makefile | 2
arch/alpha/include/asm/page.h | 2
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4
arch/arm/boot/dts/bcm5301x.dtsi | 2
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 6
arch/arm/boot/dts/imx6qdl-colibri.dtsi | 6
arch/arm/boot/dts/lan966x.dtsi | 6
arch/arm/boot/dts/ox820.dtsi | 2
arch/arm/boot/dts/qcom-sdx65.dtsi | 2
arch/arm/boot/dts/s5pv210-aries.dtsi | 3
arch/arm/boot/dts/s5pv210.dtsi | 12
arch/arm/boot/dts/sama7g5.dtsi | 1
arch/arm/boot/dts/socfpga.dtsi | 2
arch/arm/boot/dts/socfpga_arria10.dtsi | 2
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 1
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4
arch/arm/include/asm/arch_gicv3.h | 7
arch/arm/kernel/signal.c | 1
arch/arm/mach-hisi/platsmp.c | 4
arch/arm/mach-mediatek/Kconfig | 1
arch/arm/mach-omap1/clock.c | 2
arch/arm/mach-pxa/cm-x300.c | 8
arch/arm/mach-pxa/magician.c | 2
arch/arm/mach-pxa/tosa.c | 4
arch/arm/mach-vexpress/dcscb.c | 1
arch/arm64/Kconfig.platforms | 1
arch/arm64/boot/dts/arm/juno-r1-scmi.dts | 4
arch/arm64/boot/dts/arm/juno-r2-scmi.dts | 4
arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts | 5
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 2
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 5
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2
arch/arm64/boot/dts/qcom/msm8994.dtsi | 8
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 2
arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi | 4
arch/arm64/boot/dts/qcom/sc7280-idp.dtsi | 18
arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi | 19
arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium.dts | 2
arch/arm64/boot/dts/qcom/sm8450.dtsi | 6
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2
arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi | 2
arch/arm64/configs/defconfig | 1
arch/arm64/include/asm/arch_gicv3.h | 6
arch/arm64/include/asm/processor.h | 10
arch/arm64/kernel/signal.c | 1
arch/arm64/kernel/signal32.c | 1
arch/arm64/kernel/sys_compat.c | 2
arch/arm64/mm/copypage.c | 4
arch/csky/kernel/probes/kprobes.c | 2
arch/m68k/Kconfig.cpu | 2
arch/m68k/include/asm/raw_io.h | 6
arch/m68k/kernel/signal.c | 1
arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h | 1
arch/mips/include/asm/mach-ip30/cpu-feature-overrides.h | 1
arch/mips/include/asm/mach-ralink/spaces.h | 2
arch/openrisc/include/asm/timex.h | 1
arch/openrisc/kernel/head.S | 9
arch/parisc/include/asm/fb.h | 4
arch/parisc/kernel/processor.c | 2
arch/parisc/kernel/topology.c | 16
arch/powerpc/include/asm/page.h | 7
arch/powerpc/include/asm/vas.h | 2
arch/powerpc/kernel/entry_64.S | 24
arch/powerpc/kernel/fadump.c | 8
arch/powerpc/kernel/idle.c | 2
arch/powerpc/kernel/rtas.c | 9
arch/powerpc/kvm/book3s_hv.c | 12
arch/powerpc/kvm/book3s_hv_nested.c | 3
arch/powerpc/kvm/trace_hv.h | 8
arch/powerpc/mm/nohash/fsl_book3e.c | 15
arch/powerpc/perf/isa207-common.c | 12
arch/powerpc/platforms/4xx/cpm.c | 2
arch/powerpc/platforms/8xx/cpm1.c | 1
arch/powerpc/platforms/powernv/opal-fadump.c | 94 -
arch/powerpc/platforms/powernv/opal-fadump.h | 10
arch/powerpc/platforms/powernv/setup.c | 9
arch/powerpc/platforms/powernv/ultravisor.c | 1
arch/powerpc/platforms/powernv/vas-fault.c | 2
arch/powerpc/platforms/powernv/vas-window.c | 4
arch/powerpc/platforms/powernv/vas.h | 2
arch/powerpc/platforms/pseries/papr_scm.c | 54
arch/powerpc/sysdev/dart_iommu.c | 6
arch/powerpc/sysdev/fsl_rio.c | 2
arch/powerpc/sysdev/xics/icp-opal.c | 1
arch/powerpc/sysdev/xive/spapr.c | 7
arch/riscv/Makefile | 4
arch/riscv/include/asm/alternative-macros.h | 4
arch/riscv/include/asm/asm.h | 26
arch/riscv/include/asm/irq_work.h | 2
arch/riscv/include/asm/unistd.h | 1
arch/riscv/include/asm/xip_fixup.h | 31
arch/riscv/include/uapi/asm/unistd.h | 1
arch/riscv/kernel/head.S | 2
arch/riscv/kernel/setup.c | 4
arch/riscv/kernel/suspend_entry.S | 1
arch/riscv/mm/init.c | 2
arch/s390/include/asm/cio.h | 2
arch/s390/include/asm/kexec.h | 10
arch/s390/include/asm/preempt.h | 15
arch/s390/kernel/perf_event.c | 2
arch/s390/kernel/time.c | 8
arch/sparc/kernel/signal32.c | 1
arch/sparc/kernel/signal_64.c | 1
arch/um/drivers/chan_user.c | 9
arch/um/drivers/virtio_uml.c | 33
arch/um/include/asm/Kbuild | 1
arch/um/include/asm/thread_info.h | 2
arch/um/kernel/exec.c | 2
arch/um/kernel/process.c | 2
arch/um/kernel/ptrace.c | 8
arch/um/kernel/signal.c | 4
arch/x86/Kconfig | 4
arch/x86/entry/entry_64.S | 1
arch/x86/entry/vdso/vma.c | 2
arch/x86/events/amd/ibs.c | 55
arch/x86/events/intel/core.c | 2
arch/x86/include/asm/acenv.h | 14
arch/x86/include/asm/kexec.h | 8
arch/x86/include/asm/set_memory.h | 52
arch/x86/include/asm/suspend_32.h | 2
arch/x86/include/asm/suspend_64.h | 12
arch/x86/kernel/apic/apic.c | 2
arch/x86/kernel/apic/x2apic_uv_x.c | 8
arch/x86/kernel/cpu/intel.c | 2
arch/x86/kernel/cpu/mce/amd.c | 32
arch/x86/kernel/cpu/mce/core.c | 6
arch/x86/kernel/cpu/sgx/encl.c | 105 +
arch/x86/kernel/cpu/sgx/encl.h | 7
arch/x86/kernel/cpu/sgx/main.c | 9
arch/x86/kernel/machine_kexec_64.c | 12
arch/x86/kernel/signal_compat.c | 2
arch/x86/kernel/step.c | 3
arch/x86/kernel/sys_x86_64.c | 7
arch/x86/kvm/lapic.c | 1
arch/x86/kvm/vmx/nested.c | 45
arch/x86/kvm/vmx/vmcs.h | 5
arch/x86/lib/delay.c | 4
arch/x86/mm/pat/memtype.c | 2
arch/x86/mm/pat/set_memory.c | 49
arch/x86/pci/irq.c | 19
arch/x86/um/ldt.c | 6
arch/xtensa/kernel/entry.S | 19
arch/xtensa/kernel/ptrace.c | 4
arch/xtensa/kernel/signal.c | 4
arch/xtensa/kernel/traps.c | 11
arch/xtensa/platforms/iss/simdisk.c | 18
block/bfq-cgroup.c | 111 -
block/bfq-iosched.c | 64
block/bfq-iosched.h | 7
block/blk-cgroup.c | 17
block/blk-cgroup.h | 2
block/blk-ia-ranges.c | 7
block/blk-iocost.c | 5
block/blk-iolatency.c | 130 -
block/blk-throttle.c | 3
crypto/cryptd.c | 23
drivers/acpi/arm64/agdi.c | 1
drivers/acpi/cppc_acpi.c | 17
drivers/acpi/property.c | 18
drivers/acpi/sleep.c | 12
drivers/base/memory.c | 5
drivers/base/node.c | 1
drivers/base/power/domain.c | 1
drivers/base/property.c | 89 -
drivers/block/drbd/drbd_main.c | 62
drivers/block/loop.c | 16
drivers/block/nbd.c | 13
drivers/block/virtio_blk.c | 7
drivers/bluetooth/btmtksdio.c | 26
drivers/bluetooth/btusb.c | 6
drivers/char/hw_random/cn10k-rng.c | 31
drivers/char/hw_random/omap3-rom-rng.c | 2
drivers/char/ipmi/ipmi_ipmb.c | 1
drivers/char/ipmi/ipmi_msghandler.c | 4
drivers/char/ipmi/ipmi_poweroff.c | 4
drivers/char/ipmi/ipmi_ssif.c | 23
drivers/char/ipmi/ipmi_watchdog.c | 14
drivers/char/random.c | 12
drivers/char/tpm/tpm_tis_i2c_cr50.c | 4
drivers/clk/tegra/clk-dfll.c | 12
drivers/cpufreq/cpufreq.c | 11
drivers/cpufreq/cpufreq_governor.c | 20
drivers/cpufreq/cpufreq_governor.h | 1
drivers/cpufreq/mediatek-cpufreq.c | 18
drivers/cpuidle/cpuidle-psci-domain.c | 4
drivers/cpuidle/cpuidle-psci.c | 46
drivers/cpuidle/cpuidle-riscv-sbi.c | 4
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c | 115 +
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 30
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c | 10
drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 14
drivers/crypto/ccp/sev-dev.c | 30
drivers/crypto/ccree/cc_buffer_mgr.c | 27
drivers/crypto/marvell/cesa/cipher.c | 1
drivers/crypto/nx/nx-common-powernv.c | 2
drivers/crypto/qat/qat_common/adf_pfvf_pf_proto.c | 2
drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 13
drivers/cxl/mem.c | 4
drivers/cxl/pci.c | 40
drivers/devfreq/rk3399_dmc.c | 2
drivers/dma/idxd/cdev.c | 8
drivers/dma/stm32-mdma.c | 23
drivers/dma/ti/k3-psil-am62.c | 8
drivers/edac/dmc520_edac.c | 2
drivers/firmware/arm_ffa/driver.c | 4
drivers/firmware/arm_scmi/base.c | 2
drivers/firmware/efi/Kconfig | 15
drivers/firmware/efi/efi.c | 2
drivers/gpio/gpio-rockchip.c | 24
drivers/gpio/gpio-sim.c | 4
drivers/gpio/gpiolib-of.c | 5
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 13
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 95 -
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 10
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 8
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 8
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 7
drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 2
drivers/gpu/drm/amd/amdkfd/kfd_device.c | 2
drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1
drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 7
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 1
drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 2
drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c | 14
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 8
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 4
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 60
drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 62
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10
drivers/gpu/drm/arm/malidp_crtc.c | 5
drivers/gpu/drm/bridge/Kconfig | 2
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31
drivers/gpu/drm/bridge/analogix/anx7625.c | 21
drivers/gpu/drm/bridge/analogix/anx7625.h | 4
drivers/gpu/drm/bridge/chipone-icn6211.c | 155 +-
drivers/gpu/drm/bridge/ite-it6505.c | 29
drivers/gpu/drm/bridge/ite-it66121.c | 2
drivers/gpu/drm/drm_bridge_connector.c | 4
drivers/gpu/drm/drm_edid.c | 6
drivers/gpu/drm/drm_format_helper.c | 74
drivers/gpu/drm/drm_plane.c | 14
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6
drivers/gpu/drm/gma500/psb_intel_display.c | 7
drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 33
drivers/gpu/drm/i915/i915_perf.c | 4
drivers/gpu/drm/i915/i915_perf_types.h | 2
drivers/gpu/drm/mediatek/mtk_cec.c | 2
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 16
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 22
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 20
drivers/gpu/drm/mediatek/mtk_dpi.c | 4
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 14
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 29
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 19
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 16
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 5
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 3
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 3
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 2
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20
drivers/gpu/drm/msm/dp/dp_ctrl.c | 16
drivers/gpu/drm/msm/dp/dp_display.c | 55
drivers/gpu/drm/msm/dp/dp_drm.c | 4
drivers/gpu/drm/msm/dsi/dsi_host.c | 21
drivers/gpu/drm/msm/dsi/dsi_manager.c | 35
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 2
drivers/gpu/drm/msm/hdmi/hdmi.c | 10
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 3
drivers/gpu/drm/msm/msm_drv.c | 11
drivers/gpu/drm/msm/msm_gem_prime.c | 2
drivers/gpu/drm/msm/msm_gpu.c | 3
drivers/gpu/drm/msm/msm_gpu.h | 12
drivers/gpu/drm/msm/msm_gpu_devfreq.c | 90 +
drivers/gpu/drm/msm/msm_kms.h | 1
drivers/gpu/drm/nouveau/dispnv50/atom.h | 6
drivers/gpu/drm/nouveau/dispnv50/crc.c | 27
drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 2
drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c | 14
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c | 6
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c | 6
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6
drivers/gpu/drm/omapdrm/omap_overlay.c | 2
drivers/gpu/drm/panel/panel-simple.c | 3
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2
drivers/gpu/drm/selftests/test-drm_buddy.c | 10
drivers/gpu/drm/solomon/Kconfig | 2
drivers/gpu/drm/solomon/ssd130x.c | 42
drivers/gpu/drm/stm/ltdc.c | 16
drivers/gpu/drm/tegra/gem.c | 1
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8
drivers/gpu/drm/tiny/repaper.c | 2
drivers/gpu/drm/v3d/v3d_perfmon.c | 3
drivers/gpu/drm/vc4/vc4_crtc.c | 2
drivers/gpu/drm/vc4/vc4_drv.h | 1
drivers/gpu/drm/vc4/vc4_hvs.c | 49
drivers/gpu/drm/vc4/vc4_kms.c | 5
drivers/gpu/drm/vc4/vc4_regs.h | 12
drivers/gpu/drm/vc4/vc4_txp.c | 8
drivers/gpu/drm/virtio/virtgpu_display.c | 2
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 30
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 14
drivers/hid/amd-sfh-hid/amd_sfh_hid.c | 4
drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2
drivers/hid/hid-bigbenff.c | 6
drivers/hid/hid-elan.c | 2
drivers/hid/hid-led.c | 2
drivers/hv/channel.c | 6
drivers/hwmon/peci/dimmtemp.c | 6
drivers/hwmon/pmbus/pmbus_core.c | 95 +
drivers/hwtracing/coresight/coresight-core.c | 33
drivers/i2c/busses/i2c-at91-master.c | 11
drivers/i2c/busses/i2c-npcm7xx.c | 103 -
drivers/i2c/busses/i2c-rcar.c | 15
drivers/infiniband/hw/hfi1/file_ops.c | 2
drivers/infiniband/hw/hfi1/init.c | 2
drivers/infiniband/hw/hfi1/sdma.c | 12
drivers/infiniband/hw/hns/hns_roce_device.h | 7
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 24
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2
drivers/infiniband/hw/hns/hns_roce_main.c | 2
drivers/infiniband/sw/rdmavt/qp.c | 6
drivers/infiniband/sw/rxe/rxe_mcast.c | 6
drivers/infiniband/sw/rxe/rxe_req.c | 2
drivers/input/keyboard/gpio_keys.c | 2
drivers/input/misc/sparcspkr.c | 1
drivers/input/touchscreen/stmfts.c | 16
drivers/iommu/amd/init.c | 2
drivers/iommu/amd/iommu.c | 7
drivers/iommu/amd/iommu_v2.c | 12
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 13
drivers/iommu/dma-iommu.c | 7
drivers/iommu/intel/iommu.c | 2
drivers/iommu/msm_iommu.c | 11
drivers/iommu/mtk_iommu.c | 30
drivers/iommu/mtk_iommu.h | 2
drivers/iommu/mtk_iommu_v1.c | 7
drivers/irqchip/irq-armada-370-xp.c | 11
drivers/irqchip/irq-aspeed-i2c-ic.c | 4
drivers/irqchip/irq-aspeed-scu-ic.c | 4
drivers/irqchip/irq-gic-v3.c | 183 +-
drivers/irqchip/irq-sni-exiu.c | 25
drivers/irqchip/irq-xtensa-mx.c | 18
drivers/macintosh/Kconfig | 6
drivers/macintosh/Makefile | 3
drivers/macintosh/via-pmu.c | 2
drivers/mailbox/mailbox.c | 19
drivers/mailbox/pcc.c | 2
drivers/md/bcache/btree.c | 58
drivers/md/bcache/btree.h | 2
drivers/md/bcache/journal.c | 31
drivers/md/bcache/journal.h | 2
drivers/md/bcache/request.c | 6
drivers/md/bcache/super.c | 1
drivers/md/bcache/writeback.c | 101 -
drivers/md/bcache/writeback.h | 2
drivers/md/md-bitmap.c | 44
drivers/md/md.c | 22
drivers/md/raid0.c | 1
drivers/media/cec/core/cec-adap.c | 6
drivers/media/i2c/Kconfig | 1
drivers/media/i2c/ccs/ccs-core.c | 7
drivers/media/i2c/dw9714.c | 1
drivers/media/i2c/dw9768.c | 6
drivers/media/i2c/max9286.c | 19
drivers/media/i2c/ov5648.c | 4
drivers/media/i2c/ov7670.c | 1
drivers/media/i2c/rdacm20.c | 2
drivers/media/i2c/rdacm21.c | 2
drivers/media/pci/cx23885/cx23885-core.c | 6
drivers/media/pci/cx25821/cx25821-core.c | 2
drivers/media/platform/amphion/vdec.c | 2
drivers/media/platform/aspeed/aspeed-video.c | 4
drivers/media/platform/atmel/atmel-sama5d2-isc.c | 7
drivers/media/platform/chips-media/coda-common.c | 35
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c | 13
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c | 6
drivers/media/platform/nxp/imx-mipi-csis.c | 561 +++----
drivers/media/platform/qcom/venus/helpers.c | 34
drivers/media/platform/qcom/venus/hfi.c | 3
drivers/media/platform/renesas/vsp1/vsp1_rpf.c | 6
drivers/media/platform/rockchip/rga/rga.c | 6
drivers/media/platform/samsung/exynos4-is/fimc-is.c | 6
drivers/media/platform/samsung/exynos4-is/fimc-isp-video.h | 2
drivers/media/platform/st/sti/delta/delta-v4l2.c | 6
drivers/media/radio/Kconfig | 4
drivers/media/rc/bpf-lirc.c | 8
drivers/media/rc/imon.c | 99 -
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7
drivers/media/usb/uvc/uvc_v4l2.c | 20
drivers/memory/samsung/exynos5422-dmc.c | 5
drivers/mfd/davinci_voicecodec.c | 6
drivers/mfd/ipaq-micro.c | 2
drivers/misc/fastrpc.c | 9
drivers/misc/ocxl/file.c | 2
drivers/mmc/core/block.c | 8
drivers/mmc/host/jz4740_mmc.c | 20
drivers/mmc/host/sdhci_am654.c | 23
drivers/mtd/chips/cfi_cmdset_0002.c | 103 -
drivers/mtd/mtdblock.c | 8
drivers/mtd/nand/raw/cadence-nand-controller.c | 5
drivers/mtd/nand/raw/denali_pci.c | 15
drivers/mtd/nand/raw/intel-nand-controller.c | 2
drivers/mtd/nand/spi/gigadevice.c | 10
drivers/mtd/spi-nor/core.c | 9
drivers/net/amt.c | 11
drivers/net/bonding/bond_main.c | 15
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 2
drivers/net/can/xilinx_can.c | 4
drivers/net/dsa/Kconfig | 3
drivers/net/dsa/mt7530.c | 14
drivers/net/dsa/qca8k.c | 7
drivers/net/ethernet/broadcom/Makefile | 5
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 1
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 56
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h | 2
drivers/net/ethernet/cadence/macb_main.c | 42
drivers/net/ethernet/cadence/macb_ptp.c | 4
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 12
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 2
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 2
drivers/net/ethernet/intel/ice/ice_devlink.c | 5
drivers/net/ethernet/intel/ice/ice_repr.c | 7
drivers/net/ethernet/intel/ice/ice_sriov.c | 32
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 28
drivers/net/ethernet/intel/ice/ice_virtchnl.c | 5
drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c | 7
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 4
drivers/net/ethernet/mellanox/mlx5/core/en.h | 1
drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c | 2
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 9
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 10
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10
drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 2
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c | 1
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h | 1
drivers/net/ethernet/mellanox/mlx5/core/main.c | 23
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h | 2
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13
drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c | 2
drivers/net/ethernet/sfc/ef10.c | 2
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | 13
drivers/net/ethernet/ti/Kconfig | 1
drivers/net/ethernet/xscale/ptp_ixp46x.c | 2
drivers/net/hyperv/netvsc_drv.c | 5
drivers/net/ipa/ipa_endpoint.c | 41
drivers/net/macsec.c | 7
drivers/net/phy/micrel.c | 11
drivers/net/usb/asix_devices.c | 6
drivers/net/usb/smsc95xx.c | 3
drivers/net/usb/usbnet.c | 6
drivers/net/wireless/ath/ath10k/mac.c | 20
drivers/net/wireless/ath/ath11k/mac.c | 16
drivers/net/wireless/ath/ath11k/pci.c | 12
drivers/net/wireless/ath/ath11k/spectral.c | 17
drivers/net/wireless/ath/ath11k/wmi.c | 11
drivers/net/wireless/ath/ath11k/wmi.h | 12
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8
drivers/net/wireless/ath/carl9170/tx.c | 3
drivers/net/wireless/broadcom/b43/phy_n.c | 2
drivers/net/wireless/broadcom/b43legacy/phy.c | 2
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2
drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 3
drivers/net/wireless/intel/iwlwifi/mei/main.c | 3
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3
drivers/net/wireless/marvell/mwifiex/11h.c | 2
drivers/net/wireless/mediatek/mt76/agg-rx.c | 5
drivers/net/wireless/mediatek/mt76/mac80211.c | 8
drivers/net/wireless/mediatek/mt76/mt76.h | 2
drivers/net/wireless/mediatek/mt76/mt7603/main.c | 2
drivers/net/wireless/mediatek/mt76/mt7615/main.c | 2
drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c | 2
drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 2
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 35
drivers/net/wireless/mediatek/mt76/mt7915/main.c | 2
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 20
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 2
drivers/net/wireless/mediatek/mt76/mt7915/soc.c | 2
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6
drivers/net/wireless/mediatek/mt76/mt7921/main.c | 6
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 10
drivers/net/wireless/mediatek/mt76/tx.c | 11
drivers/net/wireless/microchip/wilc1000/mon.c | 4
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8
drivers/net/wireless/realtek/rtlwifi/usb.c | 2
drivers/net/wireless/realtek/rtw88/rtw8821c.c | 4
drivers/net/wireless/realtek/rtw88/rx.c | 3
drivers/net/wireless/realtek/rtw89/cam.c | 14
drivers/net/wireless/realtek/rtw89/fw.c | 2
drivers/net/wireless/realtek/rtw89/phy.c | 5
drivers/net/wireless/realtek/rtw89/ser.c | 21
drivers/net/wireless/ti/wl1251/event.c | 22
drivers/net/wireless/ti/wl1251/io.c | 20
drivers/net/wireless/ti/wl1251/tx.c | 15
drivers/nfc/st21nfca/se.c | 17
drivers/nfc/st21nfca/st21nfca.h | 1
drivers/nvdimm/core.c | 9
drivers/nvdimm/pmem.c | 30
drivers/nvdimm/security.c | 5
drivers/nvme/host/core.c | 21
drivers/nvme/host/pci.c | 1
drivers/of/fdt.c | 3
drivers/of/kexec.c | 9
drivers/of/overlay.c | 4
drivers/opp/of.c | 2
drivers/pci/controller/cadence/pci-j721e.c | 3
drivers/pci/controller/cadence/pcie-cadence-ep.c | 21
drivers/pci/controller/cadence/pcie-cadence.h | 3
drivers/pci/controller/dwc/pci-imx6.c | 23
drivers/pci/controller/dwc/pcie-designware-host.c | 3
drivers/pci/controller/dwc/pcie-qcom.c | 15
drivers/pci/controller/pcie-mediatek-gen3.c | 8
drivers/pci/controller/pcie-mediatek.c | 1
drivers/pci/controller/pcie-microchip-host.c | 16
drivers/pci/controller/pcie-rockchip-ep.c | 3
drivers/pci/pci-acpi.c | 41
drivers/pci/pci.c | 12
drivers/pci/pcie/aer.c | 7
drivers/pci/quirks.c | 47
drivers/phy/qualcomm/phy-qcom-qmp.c | 11
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 18
drivers/pinctrl/mediatek/Kconfig | 1
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2
drivers/pinctrl/pinctrl-apple-gpio.c | 1
drivers/pinctrl/pinctrl-rockchip.c | 64
drivers/pinctrl/pinctrl-rockchip.h | 7
drivers/pinctrl/renesas/core.c | 7
drivers/pinctrl/renesas/pfc-r8a779a0.c | 29
drivers/pinctrl/renesas/pfc-r8a779f0.c | 21
drivers/pinctrl/renesas/pinctrl-rzn1.c | 10
drivers/platform/chrome/cros_ec.c | 16
drivers/platform/chrome/cros_ec_chardev.c | 2
drivers/platform/chrome/cros_ec_proto.c | 50
drivers/platform/mips/cpu_hwmon.c | 127 -
drivers/platform/x86/intel/chtwc_int33fe.c | 2
drivers/platform/x86/intel/hid.c | 2
drivers/regulator/core.c | 7
drivers/regulator/da9121-regulator.c | 2
drivers/regulator/pfuze100-regulator.c | 2
drivers/regulator/qcom_smd-regulator.c | 35
drivers/regulator/scmi-regulator.c | 2
drivers/s390/cio/chsc.c | 4
drivers/scsi/dc395x.c | 15
drivers/scsi/fcoe/fcoe_ctlr.c | 2
drivers/scsi/hisi_sas/hisi_sas_main.c | 49
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10
drivers/scsi/lpfc/lpfc.h | 1
drivers/scsi/lpfc/lpfc_els.c | 112 -
drivers/scsi/lpfc/lpfc_hbadisc.c | 3
drivers/scsi/lpfc/lpfc_init.c | 51
drivers/scsi/lpfc/lpfc_logmsg.h | 6
drivers/scsi/lpfc/lpfc_nportdisc.c | 10
drivers/scsi/lpfc/lpfc_scsi.c | 37
drivers/scsi/lpfc/lpfc_sli.c | 48
drivers/scsi/megaraid.c | 2
drivers/scsi/ufs/ti-j721e-ufs.c | 6
drivers/scsi/ufs/ufs-qcom.c | 14
drivers/scsi/ufs/ufshcd.c | 7
drivers/soc/bcm/bcm63xx/bcm-pmb.c | 3
drivers/soc/qcom/llcc-qcom.c | 1
drivers/soc/qcom/smp2p.c | 1
drivers/soc/qcom/smsm.c | 1
drivers/soc/ti/ti_sci_pm_domains.c | 2
drivers/spi/spi-cadence-quadspi.c | 2
drivers/spi/spi-fsl-qspi.c | 4
drivers/spi/spi-img-spfi.c | 2
drivers/spi/spi-rockchip.c | 8
drivers/spi/spi-rspi.c | 15
drivers/spi/spi-stm32-qspi.c | 3
drivers/spi/spi-ti-qspi.c | 5
drivers/staging/media/hantro/hantro_drv.c | 17
drivers/staging/media/hantro/hantro_g2_hevc_dec.c | 11
drivers/staging/media/hantro/hantro_h264.c | 2
drivers/staging/media/hantro/hantro_v4l2.c | 67
drivers/staging/media/rkvdec/rkvdec-h264.c | 37
drivers/staging/r8188eu/os_dep/ioctl_linux.c | 92 -
drivers/target/target_core_device.c | 1
drivers/target/target_core_user.c | 50
drivers/thermal/broadcom/bcm2711_thermal.c | 5
drivers/thermal/broadcom/sr-thermal.c | 3
drivers/thermal/devfreq_cooling.c | 25
drivers/thermal/imx_sc_thermal.c | 6
drivers/thermal/thermal_core.c | 1
drivers/tty/goldfish.c | 20
drivers/tty/n_gsm.c | 31
drivers/tty/serial/pch_uart.c | 27
drivers/tty/tty_buffer.c | 3
drivers/usb/core/hcd.c | 29
drivers/usb/core/quirks.c | 3
drivers/usb/dwc3/gadget.c | 6
drivers/usb/host/xhci-pci.c | 2
drivers/usb/host/xhci.c | 2
drivers/usb/isp1760/isp1760-core.c | 8
drivers/usb/serial/option.c | 2
drivers/usb/serial/pl2303.c | 3
drivers/vdpa/vdpa_sim/vdpa_sim.c | 5
drivers/video/console/sticon.c | 5
drivers/video/console/sticore.c | 32
drivers/video/fbdev/amba-clcd.c | 5
drivers/video/fbdev/core/fb_defio.c | 9
drivers/video/fbdev/core/fbcon.c | 5
drivers/video/fbdev/sticore.h | 3
drivers/video/fbdev/stifb.c | 4
drivers/video/fbdev/vesafb.c | 5
fs/afs/misc.c | 5
fs/afs/rotate.c | 4
fs/afs/rxrpc.c | 8
fs/afs/write.c | 1
fs/binfmt_flat.c | 27
fs/btrfs/block-group.c | 8
fs/btrfs/block-group.h | 2
fs/btrfs/disk-io.c | 4
fs/btrfs/extent_io.c | 27
fs/btrfs/extent_io.h | 1
fs/btrfs/inode.c | 81 -
fs/btrfs/ioctl.c | 49
fs/btrfs/volumes.c | 8
fs/btrfs/zoned.c | 44
fs/btrfs/zoned.h | 5
fs/ceph/mds_client.c | 14
fs/cifs/cifsfs.c | 10
fs/cifs/cifsglob.h | 15
fs/cifs/connect.c | 67
fs/cifs/dfs_cache.c | 6
fs/cifs/fs_context.c | 29
fs/cifs/fs_context.h | 2
fs/cifs/misc.c | 7
fs/cifs/sess.c | 6
fs/cifs/smb2inode.c | 2
fs/cifs/smb2ops.c | 9
fs/cifs/smb2pdu.c | 3
fs/cifs/smb2transport.c | 3
fs/dax.c | 3
fs/dlm/lock.c | 15
fs/dlm/lowcomms.c | 2
fs/dlm/plock.c | 12
fs/erofs/decompressor.c | 5
fs/exec.c | 6
fs/exportfs/expfs.c | 5
fs/ext4/ext4.h | 6
fs/ext4/extents.c | 20
fs/ext4/inline.c | 12
fs/ext4/inode.c | 13
fs/ext4/mballoc.c | 18
fs/ext4/namei.c | 84 -
fs/ext4/super.c | 87 -
fs/f2fs/dir.c | 3
fs/f2fs/f2fs.h | 29
fs/f2fs/file.c | 20
fs/f2fs/hash.c | 11
fs/f2fs/inline.c | 29
fs/f2fs/inode.c | 19
fs/f2fs/namei.c | 7
fs/f2fs/segment.c | 42
fs/f2fs/segment.h | 33
fs/f2fs/super.c | 6
fs/fat/fatent.c | 7
fs/fs-writeback.c | 13
fs/gfs2/quota.c | 32
fs/hugetlbfs/inode.c | 4
fs/io_uring.c | 7
fs/iomap/buffered-io.c | 3
fs/jfs/jfs_dmap.c | 3
fs/ksmbd/connection.c | 2
fs/ksmbd/smb2misc.c | 2
fs/ksmbd/smb_common.c | 4
fs/namei.c | 70
fs/namespace.c | 5
fs/nfs/file.c | 50
fs/nfs/fscache.c | 7
fs/nfs/nfs4namespace.c | 9
fs/nfs/nfs4proc.c | 41
fs/nfs/nfs4state.c | 9
fs/nfs/nfs4xdr.c | 4
fs/nfs/pagelist.c | 3
fs/nfs/pnfs.c | 2
fs/nfs/unlink.c | 8
fs/nfs/write.c | 54
fs/nfsd/nfscache.c | 2
fs/notify/fanotify/fanotify_user.c | 4
fs/notify/fdinfo.c | 11
fs/notify/inotify/inotify.h | 12
fs/notify/inotify/inotify_user.c | 2
fs/notify/mark.c | 6
fs/ntfs3/file.c | 12
fs/ntfs3/frecord.c | 10
fs/ntfs3/fslog.c | 12
fs/ntfs3/inode.c | 9
fs/ntfs3/xattr.c | 112 +
fs/ocfs2/dlmfs/userdlm.c | 16
fs/ocfs2/inode.c | 4
fs/ocfs2/journal.c | 33
fs/ocfs2/journal.h | 2
fs/ocfs2/super.c | 15
fs/proc/generic.c | 3
fs/proc/proc_net.c | 3
fs/seq_file.c | 32
include/drm/drm_edid.h | 6
include/drm/drm_format_helper.h | 5
include/linux/blk_types.h | 5
include/linux/bpf.h | 119 -
include/linux/compat.h | 1
include/linux/efi.h | 2
include/linux/fwnode.h | 10
include/linux/goldfish.h | 15
include/linux/gpio/driver.h | 12
include/linux/ipmi_smi.h | 6
include/linux/kexec.h | 46
include/linux/kprobes.h | 2
include/linux/linkage.h | 15
include/linux/list.h | 16
include/linux/mailbox_controller.h | 1
include/linux/module.h | 3
include/linux/mtd/cfi.h | 1
include/linux/namei.h | 6
include/linux/nfs_fs_sb.h | 1
include/linux/nfs_xdr.h | 2
include/linux/nodemask.h | 13
include/linux/platform_data/cros_ec_proto.h | 3
include/linux/ptp_classify.h | 3
include/linux/ptrace.h | 7
include/linux/sched/signal.h | 2
include/linux/sched/task.h | 2
include/linux/seq_file.h | 4
include/linux/set_memory.h | 10
include/linux/usb/hcd.h | 2
include/net/bluetooth/hci.h | 9
include/net/bluetooth/hci_core.h | 8
include/net/if_inet6.h | 8
include/net/ip.h | 2
include/net/sock.h | 5
include/scsi/libfcoe.h | 3
include/scsi/libiscsi.h | 6
include/sound/cs35l41.h | 1
include/sound/jack.h | 1
include/trace/events/rxrpc.h | 2
include/trace/events/vmscan.h | 4
include/uapi/asm-generic/siginfo.h | 7
include/uapi/linux/android/binder.h | 2
include/uapi/linux/landlock.h | 9
include/uapi/linux/lirc.h | 7
include/uapi/linux/types.h | 3
init/Kconfig | 5
init/main.c | 2
ipc/mqueue.c | 14
kernel/bpf/cgroup.c | 124 +
kernel/dma/debug.c | 2
kernel/dma/direct.c | 31
kernel/events/core.c | 4
kernel/fork.c | 22
kernel/kexec_file.c | 34
kernel/kprobes.c | 144 -
kernel/module.c | 4
kernel/power/energy_model.c | 2
kernel/printk/printk.c | 61
kernel/ptrace.c | 5
kernel/rcu/Kconfig | 1
kernel/rcu/tasks.h | 5
kernel/scftorture.c | 5
kernel/sched/core.c | 6
kernel/sched/deadline.c | 5
kernel/sched/fair.c | 8
kernel/sched/pelt.h | 4
kernel/sched/psi.c | 15
kernel/sched/rt.c | 5
kernel/sched/sched.h | 32
kernel/signal.c | 18
kernel/trace/bpf_trace.c | 5
kernel/trace/ftrace.c | 5
kernel/trace/trace.c | 6
kernel/trace/trace_boot.c | 2
kernel/trace/trace_events.c | 13
kernel/trace/trace_events_hist.c | 3
kernel/trace/trace_osnoise.c | 9
kernel/trace/trace_selftest.c | 3
kernel/umh.c | 6
lib/kunit/debugfs.c | 2
lib/kunit/executor.c | 32
lib/kunit/executor_test.c | 4
lib/string_helpers.c | 3
mm/cma.c | 4
mm/compaction.c | 2
mm/hugetlb.c | 9
mm/memremap.c | 2
mm/page_alloc.c | 4
mm/page_owner.c | 2
net/bluetooth/hci_conn.c | 7
net/bluetooth/hci_event.c | 35
net/bluetooth/hci_request.c | 2
net/bluetooth/sco.c | 23
net/core/dev.c | 8
net/ipv4/tcp_input.c | 28
net/ipv6/addrconf.c | 33
net/ipv6/datagram.c | 6
net/ipv6/udp.c | 11
net/mac80211/chan.c | 7
net/mac80211/ieee80211_i.h | 5
net/mac80211/rc80211_minstrel_ht.c | 3
net/mac80211/scan.c | 20
net/mptcp/pm.c | 19
net/mptcp/pm_netlink.c | 2
net/mptcp/protocol.c | 18
net/mptcp/protocol.h | 1
net/nfc/core.c | 1
net/rxrpc/ar-internal.h | 15
net/rxrpc/call_accept.c | 6
net/rxrpc/call_event.c | 7
net/rxrpc/call_object.c | 18
net/rxrpc/conn_object.c | 2
net/rxrpc/input.c | 58
net/rxrpc/net_ns.c | 2
net/rxrpc/output.c | 20
net/rxrpc/proc.c | 10
net/rxrpc/recvmsg.c | 8
net/rxrpc/sendmsg.c | 6
net/rxrpc/sysctl.c | 4
net/sctp/input.c | 4
net/smc/af_smc.c | 2
net/wireless/nl80211.c | 4
net/wireless/reg.c | 4
samples/bpf/Makefile | 9
samples/landlock/sandboxer.c | 104 -
scripts/faddr2line | 150 +
security/integrity/ima/Kconfig | 14
security/integrity/platform_certs/keyring_handler.h | 8
security/integrity/platform_certs/load_uefi.c | 33
security/landlock/cred.c | 4
security/landlock/cred.h | 8
security/landlock/fs.c | 191 +-
security/landlock/fs.h | 11
security/landlock/limits.h | 8
security/landlock/object.c | 6
security/landlock/object.h | 6
security/landlock/ptrace.c | 10
security/landlock/ruleset.c | 84 -
security/landlock/ruleset.h | 35
security/landlock/syscalls.c | 95 -
sound/core/jack.c | 34
sound/core/pcm_memory.c | 3
sound/pci/hda/patch_realtek.c | 21
sound/soc/amd/yc/acp6x-mach.c | 29
sound/soc/atmel/atmel-classd.c | 1
sound/soc/atmel/atmel-pdmic.c | 1
sound/soc/codecs/Kconfig | 2
sound/soc/codecs/cs35l41-lib.c | 14
sound/soc/codecs/lpass-macro-common.c | 35
sound/soc/codecs/max98090.c | 6
sound/soc/codecs/rk3328_codec.c | 2
sound/soc/codecs/rt5514.c | 2
sound/soc/codecs/rt5645.c | 7
sound/soc/codecs/tscs454.c | 12
sound/soc/codecs/wm2000.c | 6
sound/soc/fsl/imx-hdmi.c | 1
sound/soc/fsl/imx-sgtl5000.c | 14
sound/soc/intel/boards/bytcr_rt5640.c | 12
sound/soc/intel/boards/sof_ssp_amp.c | 16
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5
sound/soc/mxs/mxs-saif.c | 1
sound/soc/samsung/aries_wm8994.c | 2
sound/soc/sh/rcar/core.c | 15
sound/soc/sh/rcar/dma.c | 9
sound/soc/sh/rcar/rsnd.h | 2
sound/soc/sh/rcar/src.c | 7
sound/soc/sh/rcar/ssi.c | 14
sound/soc/sh/rcar/ssiu.c | 11
sound/soc/sh/rz-ssi.c | 22
sound/soc/soc-dapm.c | 2
sound/soc/sof/amd/pci-rn.c | 1
sound/soc/sof/ipc3-topology.c | 40
sound/soc/ti/j721e-evm.c | 44
sound/usb/implicit.c | 10
sound/usb/midi.c | 3
sound/usb/quirks.c | 6
sound/usb/usbaudio.h | 6
tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c | 5
tools/lib/bpf/libbpf.c | 22
tools/objtool/check.c | 9
tools/objtool/elf.c | 200 +-
tools/objtool/include/objtool/elf.h | 4
tools/perf/Makefile.config | 39
tools/perf/arch/x86/util/evlist.c | 2
tools/perf/arch/x86/util/evsel.c | 12
tools/perf/builtin-c2c.c | 6
tools/perf/builtin-stat.c | 7
tools/perf/pmu-events/jevents.c | 2
tools/perf/util/data.h | 1
tools/perf/util/evlist.c | 12
tools/perf/util/evsel.c | 19
tools/perf/util/evsel.h | 3
tools/power/x86/turbostat/turbostat.c | 1
tools/testing/kunit/kunit_parser.py | 7
tools/testing/kunit/test_data/test_is_test_passed-no_tests_no_plan.log | 2
tools/testing/selftests/Makefile | 1
tools/testing/selftests/arm64/bti/Makefile | 4
tools/testing/selftests/bpf/Makefile | 12
tools/testing/selftests/bpf/prog_tests/trampoline_count.c | 134 -
tools/testing/selftests/bpf/progs/btf_dump_test_case_syntax.c | 2
tools/testing/selftests/bpf/progs/profiler.inc.h | 5
tools/testing/selftests/bpf/progs/test_trampoline_count.c | 16
tools/testing/selftests/bpf/test_bpftool_synctypes.py | 2
tools/testing/selftests/bpf/trace_helpers.c | 9
tools/testing/selftests/cgroup/test_stress.sh | 2
tools/testing/selftests/landlock/base_test.c | 177 +-
tools/testing/selftests/landlock/common.h | 66
tools/testing/selftests/landlock/fs_test.c | 753 ++++++----
tools/testing/selftests/landlock/ptrace_test.c | 40
tools/testing/selftests/resctrl/fill_buf.c | 4
tools/tracing/rtla/Makefile | 5
tools/tracing/rtla/README.txt | 13
tools/tracing/rtla/src/osnoise_hist.c | 5
tools/tracing/rtla/src/osnoise_top.c | 9
tools/tracing/rtla/src/timerlat_hist.c | 11
tools/tracing/rtla/src/timerlat_top.c | 11
tools/tracing/rtla/src/utils.c | 108 +
tools/tracing/rtla/src/utils.h | 3
949 files changed, 9403 insertions(+), 5275 deletions(-)
Abhinav Kumar (1):
drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path
Abhishek Kumar (1):
ath10k: skip ath10k_halt during suspend for driver state RESTARTING
Adam Wujek (1):
hwmon: (pmbus) Check PEC support before reading other registers
Aditya Garg (1):
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Aidan MacDonald (1):
mmc: jz4740: Apply DMA engine limits to maximum segment size
Ajay Singh (1):
wilc1000: fix crash observed in AP mode with cfg80211_register_netdevice()
Akira Yokosawa (2):
docs: driver-api/thermal/intel_dptf: Use copyright symbol
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Albert Wang (1):
usb: dwc3: gadget: Move null pinter check to proper place
Alex Deucher (2):
drm/amdgpu/psp: move PSP memory alloc from hw_init to sw_init
drm/amdgpu: add beige goby PCI ID
Alex Elder (3):
net: ipa: ignore endianness if there is no header
net: ipa: fix page free in ipa_endpoint_trans_release()
net: ipa: fix page free in ipa_endpoint_replenish_one()
Alexander Aring (3):
dlm: fix plock invalid read
dlm: fix wake_up() calls for pending remove
dlm: fix missing lkb refcount handling
Alexander Wetzel (1):
rtl818x: Prevent using not initialized queues
Alexandre Ghiti (1):
riscv: Initialize thread pointer before calling C functions
Alexandru Elisei (1):
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Alexey Dobriyan (2):
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
module: fix [e_shstrndx].sh_size=0 OOB access
Alexey Khoroshilov (1):
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
Alice Wong (1):
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Allen-KH Cheng (1):
arm64: dts: mt8192: Fix nor_flash status disable typo
Amadeusz Sławiński (1):
ALSA: jack: Access input_dev under mutex
Amelie Delaunay (2):
dmaengine: stm32-mdma: remove GISR1 register
dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler()
Amir Goldstein (2):
inotify: show inotify mask flags in proc fdinfo
fsnotify: fix wrong lockdep annotations
Ammar Faizi (2):
x86/MCE/AMD: Fix memory leak when threshold_create_bank() fails
x86/delay: Fix the wrong asm constraint in delay_loop()
Andre Przywara (3):
of/fdt: Ignore disabled memory nodes
kselftest/arm64: bti: force static linking
ARM: dts: suniv: F1C100: fix watchdog compatible
Andrea Parri (Microsoft) (1):
Drivers: hv: vmbus: Fix handling of messages with transaction ID of zero
Andreas Gruenbacher (1):
iomap: iomap_write_failed fix
Andrii Nakryiko (3):
libbpf: Don't error out on CO-RE relos for overriden weak subprogs
libbpf: Fix logic for finding matching program for CO-RE relocation
selftests/bpf: Prevent skeleton generation race
Andy Shevchenko (1):
device property: Allow error pointer to be passed to fwnode APIs
AngeloGioacchino Del Regno (1):
PCI: mediatek-gen3: Assert resets to ensure expected init state
Ansuel Smith (1):
net: dsa: qca8k: correctly handle mdio read error
Arnd Bergmann (2):
drbd: fix duplicate array initializer
ARM: pxa: maybe fix gpio lookup tables
Arunpravin (1):
drm/selftests: fix a shift-out-of-bounds bug
Avraham Stern (1):
iwlwifi: mei: clear the sap data header before sending
Baochen Qiang (1):
ath11k: Don't check arvif->is_started before sending management frames
Baokun Li (2):
ext4: fix race condition between ext4_write and ext4_convert_inline_data
ext4: fix bug_on in __es_tree_search
Baoquan He (1):
x86/kexec: fix memory leak of elf header buffer
Bart Van Assche (2):
scsi: ufs: qcom: Fix ufs_qcom_resume()
block: Fix the bio.bi_opf comment
Basavaraj Natikar (2):
HID: amd_sfh: Modify the bus name
HID: amd_sfh: Modify the hid name
Bean Huo (1):
mmc: core: Allows to override the timeout value for ioctl() path
Benjamin Coddington (1):
NFSv4: Fix free of uninitialized nfs4_label on referral lookup.
Benjamin Gaignard (2):
media: hantro: HEVC: unconditionnaly set pps_{cb/cr}_qp_offset values
media: hantro: HEVC: Fix tile info buffer value computation
Biju Das (1):
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Bjorn Andersson (1):
soc: qcom: llcc: Add MODULE_DEVICE_TABLE()
Bjorn Helgaas (1):
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Björn Ardö (1):
mailbox: forward the hrtimer if not queued and under a lock
Bjørn Mork (1):
mtdblock: warn if opened on NAND
Bob Peterson (1):
gfs2: use i_lock spin_lock for inode qadata
Bodo Stroesser (1):
scsi: target: tcmu: Avoid holding XArray lock when calling lock_page
Borislav Petkov (1):
x86/microcode: Add explicit CPU vendor dependency
Brent Lu (1):
ASoC: Intel: sof_ssp_amp: fix no DMIC BE Link on Chromebooks
Brian Norris (2):
PM / devfreq: rk3399_dmc: Disable edev on remove()
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Bryan O'Donoghue (1):
dt-bindings: soc: qcom: smd-rpm: Fix missing MSM8936 compatible
Caleb Connolly (2):
pinctrl/rockchip: support deferring other gpio params
pinctrl/rockchip: support setting input-enable param
Carl Yin(殷张成) (1):
USB: serial: option: add Quectel BG95 modem
Carlos Llamas (1):
binder: fix sender_euid type in uapi header
Chaitanya Kulkarni (1):
nvme: set non-mdts limits in nvme_scan_work
Chao Yu (8):
f2fs: fix to do sanity check on inline_dots inode
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
f2fs: fix to clear dirty inode in f2fs_evict_inode()
f2fs: fix deadloop in foreground GC
f2fs: fix to do sanity check on total_data_blocks
f2fs: fix fallocate to use file_modified to update permissions consistently
f2fs: fix to do sanity check for inline inode
Charles Keepax (3):
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
ASoC: atmel-pdmic: Remove endianness flag on pdmic component
ASoC: atmel-classd: Remove endianness flag on class d component
Chen-Tsung Hsieh (1):
mtd: spi-nor: core: Check written SR value in spi_nor_write_16bit_sr_and_check()
Chen-Yu Tsai (5):
drm: ssd130x: Fix COM scan direction register mask
drm: ssd130x: Always apply segment remap setting
drm/mediatek: Fix DPI component detection for MT8192
media: hantro: Implement support for encoder commands
media: hantro: Empty encoder capture buffers by default
Chengming Zhou (2):
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
sched/psi: report zeroes for CPU full at the system level
Chia-I Wu (2):
drm/msm: simplify gpu_busy callback
drm/msm: return the average load over the polling period
Christian Brauner (3):
fs: hold writers when changing mount's idmapping
fs: add two trivial lookup helpers
exportfs: support idmapped mounts
Christoph Hellwig (7):
loop: implement ->free_disk
target: remove an incorrect unmap zeroes data deduction
drbd: remove assign_p_sizes_qlim
drbd: use bdev based limit helpers in drbd_send_sizes
drbd: use bdev_alignment_offset instead of queue_alignment_offset
virtio_blk: fix the discard_granularity and discard_alignment queue limits
dma-direct: don't fail on highmem CMA pages in dma_direct_alloc_pages
Christophe JAILLET (9):
fs/ntfs3: Fix some memory leaks in an error handling path of 'log_replay()'
media: aspeed: Fix an error handling path in aspeed_video_probe()
mt76: mt7921: Fix the error handling path of mt7921_pci_probe()
hinic: Avoid some over memory allocation
memory: samsung: exynos5422-dmc: Avoid some over memory allocation
drivers/base/memory: fix an unlikely reference counting issue in __add_memory_block()
gpio: sim: Use correct order for the parameters of devm_kcalloc()
RDMA/rxe: Fix an error handling path in rxe_get_mcg()
dmaengine: idxd: Fix the error handling path in idxd_cdev_register()
Christophe Leroy (1):
powerpc/fsl_book3e: Don't set rodata RO too early
Christophe de Dinechin (1):
nodemask.h: fix compilation error with GCC12
Chuanhong Guo (2):
mtd: spinand: gigadevice: fix Quad IO for GD5F1GQ5UExxG
arm: mediatek: select arch timer for mt7629
Chuansheng Liu (1):
fbdev: defio: fix the pagelist corruption
Colin Ian King (3):
ALSA: pcm: Check for null pointer of pointer substream before dereferencing it
drm/v3d: Fix null pointer dereference of pointer perfmon
selftests/resctrl: Fix null pointer dereference on open failed
Coly Li (4):
bcache: improve multithreaded bch_btree_check()
bcache: improve multithreaded bch_sectors_dirty_init()
bcache: remove incremental dirty sector counting for bch_sectors_dirty_init()
bcache: avoid journal no-space deadlock by reserving 1 journal bucket
Conor Dooley (1):
PCI: microchip: Add missing chained_irq_enter()/exit() calls
Corentin Labbe (3):
crypto: marvell/cesa - ECB does not IV
crypto: sun8i-ss - rework handling of IV
crypto: sun8i-ss - handle zero sized sg
Corey Minyard (3):
ipmi:ssif: Check for NULL msg when handling events and messages
ipmi: Add an intializer for ipmi_smi_msg struct
ipmi: Fix pr_fmt to avoid compilation issues
Cristian Marussi (1):
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Daire McNamara (1):
PCI: microchip: Fix potential race in interrupt handling
Damien Le Moal (1):
block: Fix potential deadlock in blk_ia_range_sysfs_show()
Dan Carpenter (9):
drm/selftests: missing error code in igt_buddy_alloc_smoke()
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
scsi: iscsi: Fix harmless double shift bug
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
PCI: cadence: Fix find_first_zero_bit() limit
PCI: rockchip: Fix find_first_zero_bit() limit
OPP: call of_node_put() on error path in _bandwidth_supported()
dlm: uninitialized variable on error in dlm_listen_for_all()
staging: r8188eu: delete rtw_wx_read/write32()
Dan Williams (5):
cxl/pci: Add debug for DVSEC range init failures
cxl/pci: Make cxl_dvsec_ranges() failure not fatal to cxl_pci
nvdimm: Fix firmware activation deadlock scenarios
nvdimm: Allow overwrite in the presence of disabled dimms
cxl/mem: Drop mem_enabled check from wait_for_media()
Daniel Bristot de Oliveira (3):
rtla: Fix __set_sched_attr error message
rtla: Remove procps-ng dependency
tracing/timerlat: Notify IRQ new max latency only if stop tracing is set
Daniel Latypov (4):
kunit: bail out of test filtering logic quicker if OOM
kunit: tool: make parser stop overwriting status of suites w/ no_tests
kunit: fix executor OOM error handling logic on non-UML
kunit: fix debugfs code to use enum kunit_status, not bool
Daniel Thompson (1):
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Daniel Vetter (1):
fbcon: Consistently protect deferred_takeover with console_lock()
Dave Airlie (1):
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
Dave Wysochanski (1):
NFS: Pass i_size to fscache_unuse_cookie() when a file is released
David Howells (9):
rxrpc: Return an error to sendmsg if call failed
rxrpc, afs: Fix selection of abort codes
afs: Adjust ACK interpretation to try and cope with NAT
rxrpc: Fix locking issue
rxrpc: Fix listen() setting the bar too high for the prealloc rings
rxrpc: Don't try to resend the request if we're receiving the reply
rxrpc: Fix overlapping ACK accounting
rxrpc: Don't let ack.previousPacket regress
rxrpc: Fix decision on when to generate an IDLE ACK
Denis Efremov (1):
staging: r8188eu: prevent ->Ssid overflow in rtw_wx_set_scan()
Dennis Dalessandro (1):
RDMA/hfi1: Fix potential integer multiplication overflow errors
Deren Wu (1):
mt76: fix antenna config missing in 6G cap
Dimitri John Ledkov (1):
cfg80211: declare MODULE_FIRMWARE for regulatory.db
Dinh Nguyen (1):
dt-bindings: gpio: altera: correct interrupt-cells
Diogo Ivo (2):
arm64: tegra: Add missing DFLL reset on Tegra210
clk: tegra: Add missing reset deassertion
Dmitry Baryshkov (6):
drm/msm: properly add and remove internal bridges
drm/msm/dsi: fix error checks and return values for DSI xmit functions
drm/msm: add missing include to msm_drv.c
drm/msm/dsi: fix address for second DSI PHY on SDM660
drm/msm: don't free the IRQ if it was not requested
arm64: defconfig: reenable SM_DISPCC_8250
Dmitry Monakhov (1):
ext4: mark group as trimmed only if it was fully scanned
Dmitry Torokhov (1):
Input: stmfts - do not leave device disabled in stmfts_input_open
Dong Aisheng (1):
Revert "mm/cma.c: remove redundant cma_mutex lock"
Dongliang Mu (3):
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
rtlwifi: Use pr_warn instead of WARN_ONCE
media: ov7670: remove ov7670_power_off from ov7670_remove
Douglas Anderson (1):
drm/msm/dsi: don't powerup at modeset time for parade-ps8640
Douglas Miller (2):
RDMA/hfi1: Prevent panic when SDMA is disabled
RDMA/hfi1: Prevent use of lock before it is initialized
Duoming Zhou (1):
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
Dylan Yudaken (1):
io_uring: only wake when the correct events are set
Emmanuel Grumbach (1):
iwlwifi: mvm: fix assert 1F04 upon reconfig
Enzo Matsumiya (2):
cifs: don't call cifs_dfs_query_info_nonascii_quirk() if nodfs was set
cifs: return ENOENT for DFS lookup_cache_entry()
Eric Biggers (4):
ext4: reject the 'commit' option on ext2 filesystems
f2fs: don't use casefolded comparison for "." and ".."
ext4: fix memory leak in parse_apply_sb_mount_options()
ext4: only allow test_dummy_encryption when supported
Eric Dumazet (5):
tcp: consume incoming skb leading to a reset
net: remove two BUG() from skb_checksum_help()
net: annotate races around sk->sk_bound_dev_if
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
mm/page_owner: use strscpy() instead of strlcpy()
Eric W. Biederman (4):
kthread: Don't allocate kthread_struct for init and umh
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Eugen Hristev (2):
media: atmel: atmel-sama5d2-isc: fix wrong mask in YUYV format check
ARM: dts: at91: sama7g5: remove interrupt-parent from gic node
Eugenio Pérez (1):
vdpasim: allow to enable a vq repeatedly
Evan Quan (1):
drm/amd/pm: fix the compile warning
Fabiano Rosas (1):
KVM: PPC: Book3S HV: Fix vcore_blocked tracepoint
Fabien Parent (1):
pinctrl: mediatek: mt8195: enable driver on mtk platforms
Fabio Estevam (1):
net: phy: micrel: Allow probing without .driver_data
Felix Fietkau (8):
mt76: mt7915: accept rx frames with non-standard VHT MCS10-11
mt76: mt7921: accept rx frames with non-standard VHT MCS10-11
mt76: fix encap offload ethernet type check
mt76: mt7915: fix DBDC default band selection on MT7915D
mt76: do not attempt to reorder received 802.3 packets without agg session
mt76: fix tx status related use-after-free race on station removal
mt76: fix use-after-free by removing a non-RCU wcid pointer
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Filipe Manana (1):
btrfs: fix deadlock between concurrent dio writes when low on free data space
Finn Thain (1):
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Francesco Dolcini (1):
PCI: imx6: Fix PERST# start-up sequence
GUO Zihua (1):
ima: remove the IMA_TEMPLATE Kconfig option
Gao Xiang (1):
erofs: fix buffer copy overflow of ztailpacking feature
Gautam Menghani (1):
tracing: Initialize integer variable to prevent garbage return value
Gavin Li (1):
net/mlx5: Increase FW pre-init timeout for health recovery
Gavin Wan (1):
drm/amd/amdgpu: Remove static from variable in RLCG Reg RW
Geert Uytterhoeven (8):
m68k: atari: Make Atari ROM port I/O write macros return void
drm/format-helper: Rename drm_fb_xrgb8888_to_mono_reversed()
drm/format-helper: Fix XRGB888 to monochrome conversion
drm/ssd130x: Fix rectangle updates
drm/ssd130x: Reduce temporary buffer sizes
m68k: math-emu: Fix dependencies of math emulation support
pinctrl: renesas: r8a779a0: Fix GPIO function on I2C-capable pins
pinctrl: renesas: r8a779f0: Fix GPIO function on I2C-capable pins
Gilad Ben-Yossef (1):
crypto: ccree - use fine grained DMA mapping dir
Giovanni Cabiddu (2):
crypto: qat - set CIPHER capability for DH895XCC
crypto: qat - set COMPRESSION capability for DH895XCC
Greg Kroah-Hartman (2):
module.h: simplify MODULE_IMPORT_NS
Linux 5.18.3
Guenter Roeck (3):
hwmon: (dimmtemp) Fix bitmap handling
platform/chrome: Re-introduce cros_ec_cmd_xfer and use it for ioctls
MIPS: Loongson: Use hwmon_device_register_with_groups() to register hwmon
Guo Ren (2):
riscv: Fixup difference with defconfig
csky: patch_text: Fixup last cpu should be master
Gustavo A. R. Silva (1):
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
H. Nikolaus Schaller (1):
wl1251: dynamically allocate memory used for DMA
Hangbin Liu (2):
selftests/bpf: Add missed ima_setup.sh in Makefile
bonding: fix missed rcu protection
Hangyu Hua (3):
media: rga: fix possible memory leak in rga_probe
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
misc: ocxl: fix possible double free in ocxl_file_register_afu
Hans Verkuil (2):
media: ccs-core.c: fix failure to call clk_disable_unprepare
media: cec-adap.c: fix is_configuring state
Hans de Goede (2):
ASoC: Intel: bytcr_rt5640: Add quirk for the HP Pro Tablet 408
drm/amdgpu: Move mutex_init(&smu->message_lock) to smu_early_init()
Hao Jia (1):
sched/core: Avoid obvious double update_rq_clock warning
Haohui Mai (1):
drm/amdgpu/sdma: Fix incorrect calculations of the wptr of the doorbells
Haowen Bai (4):
b43legacy: Fix assigning negative value to unsigned variable
b43: Fix assigning negative value to unsigned variable
ipw2x00: Fix potential NULL dereference in libipw_xmit()
sfc: ef10: Fix assigning negative value to unsigned variable
Haren Myneni (1):
powerpc/powernv/vas: Assign real address to rx_fifo in vas_rx_win_attr
Hari Bathini (2):
powerpc/fadump: Fix fadump to work with a different endian capture kernel
powerpc/fadump: fix PT_LOAD segment for boot memory area
Hari Chandrakanthan (1):
ath11k: disable spectral scan during spectral deinit
Harini Katakam (1):
net: macb: Fix PTP one step sync support
Hector Martin (1):
pinctrl: apple: Use a raw spinlock for the regmap
Heikki Krogerus (1):
platform/x86: intel_cht_int33fe: Set driver data
Heiko Carstens (1):
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Helge Deller (2):
parisc/stifb: Implement fb_is_primary_device()
parisc/stifb: Keep track of hardware path of graphics card
Heming Zhao (1):
md/bitmap: don't set sb values if can't pass sanity check
Heming Zhao via Ocfs2-devel (1):
ocfs2: fix mounting crash if journal is not alloced
Huang Rui (1):
drm/amdgpu/pm: fix the null pointer while the smu is disabled
Hui Wang (1):
ASoC: cs35l41: Fix an out-of-bounds access in otp_packed_element_t
Hyunchul Lee (1):
ksmbd: fix outstanding credits related bugs
Ian Abbott (1):
spi: cadence-quadspi: fix Direct Access Mode disable for SoCFPGA
Ian Rogers (1):
perf evlist: Keep topdown counters in weak group
Ilkka Koskinen (1):
ACPI: AGDI: Fix missing prototype warning for acpi_agdi_init()
Ioana Ciornei (3):
dpaa2-eth: retrieve the virtual address before dma_unmap
dpaa2-eth: use the correct software annotation field
dpaa2-eth: unmap the SGT buffer before accessing its contents
Jacky Li (1):
crypto: ccp - Fix the INIT_EX data file open failure
Jacob Keller (1):
ice: always check VF VSI pointer values
Jaegeuk Kim (1):
f2fs: don't need inode lock for system hidden quota
Jagan Teki (1):
drm/panel: panel-simple: Fix proper bpc for AM-1280800N3TZQW-T00H
Jakob Koschel (1):
f2fs: fix dereference of stale list iterator after loop body
Jakub Kicinski (2):
eth: tg3: silence the GCC 12 array-bounds warning
net: stmmac: fix out-of-bounds access in a selftest
James Clark (1):
perf tools: Use Python devtools for version autodetection rather than runtime
James Smart (10):
scsi: lpfc: Move cfg_log_verbose check before calling lpfc_dmp_dbg()
scsi: lpfc: Fix SCSI I/O completion and abort handler deadlock
scsi: lpfc: Fix null pointer dereference after failing to issue FLOGI and PLOGI
scsi: lpfc: Protect memory leak for NPIV ports sending PLOGI_RJT
scsi: lpfc: Fix call trace observed during I/O with CMF enabled
scsi: lpfc: Fix resource leak in lpfc_sli4_send_seq_to_ulp()
scsi: lpfc: Inhibit aborts if external loopback plug is inserted
scsi: lpfc: Alter FPIN stat accounting logic
scsi: lpfc: Fix element offset in __lpfc_sli_release_iocbq_s4()
scsi: lpfc: Fix dmabuf ptr assignment in lpfc_ct_reject_event()
Jan Kara (14):
bfq: Relax waker detection for shared queues
bfq: Allow current waker to defend against a tentative one
bfq: Avoid false marking of bic as stably merged
bfq: Avoid merging queues with different parents
bfq: Split shared queues on move between cgroups
bfq: Update cgroup information before merging bio
bfq: Drop pointless unlock-lock pair
bfq: Remove pointless bfq_init_rq() calls
bfq: Track whether bfq_group is still online
bfq: Get rid of __bio_blkcg() usage
bfq: Make sure bfqg for which we are queueing requests is online
ext4: verify dir block before splitting it
ext4: avoid cycles in directory h-tree
block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
Jan Kiszka (1):
efi: Add missing prototype for efi_capsule_setup_info
Jane Chu (2):
x86/mce: relocate set{clear}_mce_nospec() functions
mce: fix set_mce_nospec to always unmap the whole page
Jani Nikula (2):
drm/edid: fix invalid EDID extension block filtering
drm/i915/dsi: fix VBT send packet port selection for ICL+
Janusz Krzysztofik (1):
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Jason A. Donenfeld (2):
openrisc: start CPU timer early in boot
Revert "random: use static branch for crng_ready()"
Javier Martinez Canillas (2):
efi: Allow to enable EFI runtime services by default on RT
video: fbdev: vesafb: Fix a use-after-free due early fb_info cleanup
Jayesh Choudhary (1):
dmaengine: ti: k3-psil-am62: Update PSIL thread for saul.
Jean-Philippe Brucker (1):
iommu/arm-smmu-v3-sva: Fix mm use-after-free
Jerome Marchand (1):
samples: bpf: Don't fail for a missing VMLINUX_BTF when VMLINUX_H is provided
Jessica Zhang (3):
drm/msm/dpu: Clean up CRC debug logs
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jia-Ju Bai (1):
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Jia-Wei Chang (1):
cpufreq: mediatek: Use module_init and add module_exit
Jiantao Zhang (1):
PCI: dwc: Fix setting error return on MSI DMA mapping failure
Jiasheng Jiang (1):
drm: mali-dp: potential dereference of null pointer
Jiri Olsa (1):
perf build: Fix btf__load_from_kernel_by_id() feature check
Jiri Slaby (1):
serial: pch: don't overwrite xmit->buf[0] by x_char
Joel Selvaraj (1):
arm64: dts: qcom: sdm845-xiaomi-beryllium: fix typo in panel's vddio-supply property
Joerg Roedel (1):
iommu/amd: Increase timeout waiting for GA log enablement
Johan Hovold (6):
USB: serial: pl2303: fix type detection for odd device
PCI: qcom: Fix pipe clock imbalance
PCI: qcom: Fix runtime PM imbalance on probe errors
PCI: qcom: Fix unbalanced PHY init on probe errors
phy: qcom-qmp: fix struct clk leak on probe errors
phy: qcom-qmp: fix reset-controller leak on probe errors
Johannes Berg (8):
nl80211: show SSID for P2P_GO interfaces
nl80211: don't hold RTNL in color change request
wifi: mac80211: fix use-after-free in chanctx code
iwlwifi: fw: init SAR GEO table only if data is present
iwlwifi: mei: fix potential NULL-ptr deref
um: virtio_uml: Fix broken device handling in time-travel
um: Use asm-generic/dma-mapping.h
um: chan_user: Fix winch_tramp() return value
John Garry (2):
scsi: hisi_sas: Fix rescan after deleting a disk
scsi: hisi_sas: Fix memory ordering in hisi_sas_task_deliver()
John Kacur (2):
rtla: Don't overwrite existing directory mode
rtla: Minor grammar fix for rtla README
John Ogness (2):
printk: add missing memory barrier to wake_up_klogd()
printk: wake waiters for safe and NMI contexts
Jonas Karlman (1):
media: rkvdec: h264: Fix bit depth wrap in pps packet
Jonathan Bakker (1):
ARM: dts: s5pv210: Remove spi-cs-high on panel in Aries
Jonathan Teh (1):
HID: hid-led: fix maximum brightness for Dream Cheeky
Josh Poimboeuf (2):
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
scripts/faddr2line: Fix overlapping text section failures
Julian Schroeder (1):
nfsd: destroy percpu stats counters after reply cache shutdown
Junxiao Bi via Ocfs2-devel (1):
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Kailang Yang (1):
ALSA: hda/realtek - Add new type for ALC245
Kajol Jain (2):
powerpc/perf: Fix the threshold compare group constraint for power10
powerpc/perf: Fix the threshold compare group constraint for power9
Kan Liang (3):
perf/x86/intel: Fix event constraints for ICL
perf parse-events: Support different format of the topdown event name
perf stat: Always keep perf metrics topdown events in a group
Kant Fan (1):
thermal: devfreq_cooling: use local ops instead of global ops
Karthikeyan Kathirvel (1):
ath11k: Change max no of active probe SSID and BSSID to fw capability
Kathiravan T (1):
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Keita Suzuki (2):
drm/amd/pm: fix double free in si_parse_power_table()
tracing: Fix potential double free in create_var_ref()
Keith Busch (1):
nvme: set dma alignment to dword
Kevin Hao (1):
cpufreq: governor: Use kobject release() method to free dbs_data
Kirill A. Shutemov (1):
ACPICA: Avoid cache flush inside virtual machines
Kishon Vijay Abraham I (2):
usb: core: hcd: Add support for deferring roothub registration
xhci: Set HCD flag to defer primary roothub registration
Kiwoong Kim (1):
scsi: ufs: core: Exclude UECxx from SFR dump list
Konrad Dybcio (3):
arm64: dts: qcom: msm8994: Fix the cont_splash_mem address
arm64: dts: qcom: msm8994: Fix BLSP[12]_DMA channels count
regulator: qcom_smd: Fix up PM8950 regulator configuration
Konstantin Komarov (7):
fs/ntfs3: Update valid size if -EIOCBQUEUED
fs/ntfs3: Fix fiemap + fix shrink file size (to remove preallocated space)
fs/ntfs3: Keep preallocated only if option prealloc enabled
fs/ntfs3: Check new size for limits
fs/ntfs3: In function ntfs_set_acl_ex do not change inode->i_mode if called from function ntfs_init_acl
fs/ntfs3: Update i_ctime when xattr is added
fs/ntfs3: Restore ntfs_xattr_get_acl and ntfs_xattr_set_acl functions
Kristen Carlson Accardi (1):
x86/sgx: Set active memcg prior to shmem allocation
Krzysztof Kozlowski (8):
ARM: dts: ox820: align interrupt controller node name with dtschema
ARM: dts: socfpga: align interrupt controller node name with dtschema
ARM: dts: s5pv210: align DMA channels with dtschema
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
irqchip/aspeed-scu-ic: Fix irq_of_parse_and_map() return value
ARM: dts: qcom: sdx55: remove wrong unit address from RPMH RSC clocks
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
Kuldeep Singh (1):
spi: qcom-qspi: Add minItems to interconnect-names
Kuninori Morimoto (3):
ASoC: rsnd: care default case on rsnd_ssiu_busif_err_status_clear()
ASoC: rsnd: care return value from rsnd_node_fixed_index()
i2c: rcar: fix PM ref counts in probe error paths
Kuniyuki Iwashima (1):
list: fix a data-race around ep->rdllist
Kuogee Hsieh (5):
drm/msm/dpu: adjust display_v_end for eDP and DP
drm/msm/dp: stop event kernel thread when DP unbind
drm/msm/dp: reset DP controller before transmit phy test pattern
drm/msm/dp: do not stop transmitting phy test pattern during DP phy compliance test
drm/msm/dp: fix event thread stuck in wait_event after kthread_stop()
Kuppuswamy Sathyanarayanan (1):
PCI/AER: Clear MULTI_ERR_COR/UNCOR_RCV bits
Kwanghoon Son (1):
media: exynos4-is: Fix compile warning
Lad Prabhakar (3):
Input: gpio-keys - cancel delayed work only in case of GPIO
ASoC: sh: rz-ssi: Propagate error codes returned from platform_get_irq_byname()
ASoC: sh: rz-ssi: Release the DMA channels in rz_ssi_probe() error path
Lai Jiangshan (1):
x86/sev: Annotate stack change in the #VC handler
Laibin Qiu (1):
blk-throttle: Set BIO_THROTTLED when bio has been throttled
Laurent Dufour (1):
powerpc/rtas: Keep MSR[RI] set when calling RTAS
Laurent Pinchart (2):
media: imx: imx-mipi-csis: Rename csi_state to mipi_csis_device
media: imx: imx-mipi-csis: Fix active format initialization on source pad
Laurent Vivier (1):
tty: goldfish: Introduce gf_ioread32()/gf_iowrite32()
Laurentiu Palcu (2):
media: i2c: max9286: fix kernel oops when removing module
media: i2c: rdacm2x: properly set subdev entity function
Len Brown (1):
tools/power turbostat: fix ICX DRAM power numbers
Leo Yan (1):
perf c2c: Use stdio interface if slang is not supported
Li Huafei (1):
tracing: Reset the function filter after completing trampoline/graph selftest
Lin Ma (2):
ASoC: rt5645: Fix errorenous cleanup order
NFC: NULL out the dev->rfkill to prevent UAF
Linus Torvalds (2):
linux/types.h: reinstate "__bitwise__" macro for user space use
drm: fix EDID struct for old ARM OABI format
Linus Walleij (1):
usb: isp1760: Fix out-of-bounds array access
Liu Zixian (1):
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Liviu Dudau (1):
drm/komeda: return early if drm_universal_plane_init() fails.
Lorenzo Bianconi (6):
mt76: mt7921: honor pm user configuration in mt7921_sniffer_interface_iter
mt76: mt7915: fix unbounded shift in mt7915_mcu_beacon_mbss
mt76: mt7915: fix possible uninitialized pointer dereference in mt7986_wmac_gpio_setup
mt76: mt7915: fix possible NULL pointer dereference in mt7915_mac_fill_rx_vector
mt76: mt7915: do not pass data pointer to mt7915_mcu_muru_debug_set
mt76: mt7915: report rx mode value in mt7915_mac_fill_rx_rate
Luca Ceresoli (1):
spi: rockchip: fix missing error on unsupported SPI_CS_HIGH
Luca Weiss (2):
media: venus: hfi: avoid null dereference in deinit
drm/msm: Fix null pointer dereferences without iommu
Lucas Stach (2):
drm/bridge: adv7511: clean up CEC adapter when probe fails
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Luiz Augusto von Dentz (3):
Bluetooth: HCI: Add HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN quirk
Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN for QCA
Bluetooth: hci_conn: Fix hci_connect_le_sync
Lukas Wunner (1):
usbnet: Run unregister_netdev() before unbind() again
Luís Henriques (1):
ceph: fix decoding of client session messages flags
Lv Ruyi (9):
scsi: megaraid: Fix error check return value of register_chrdev()
drm: msm: fix error check return value of irq_of_parse_and_map()
powerpc/xics: fix refcount leak in icp_opal_init()
powerpc/powernv: fix missing of_node_put in uv_init()
ixp4xx_eth: fix error check return value of platform_get_irq()
drm/msm/dp: fix error check return value of irq_of_parse_and_map()
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
drm/msm/dpu: fix error check return value of irq_of_parse_and_map()
Lyude Paul (1):
drm/nouveau/subdev/bus: Ratelimit logging for fault errors
Maciej W. Rozycki (3):
x86/PCI: Fix ALi M1487 (IBC) PIRQ router link value interpretation
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
MIPS: IP30: Remove incorrect `cpu_has_fpu' override
Manivannan Sadhasivam (1):
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Mao Jinlong (1):
coresight: core: Fix coresight device probe failure issue
Marc Kleine-Budde (1):
can: xilinx_can: mark bit timing constants as const
Marco Chiappero (1):
crypto: qat - fix off-by-one error in PFVF debug print
Marco Elver (1):
signal: Deliver SIGTRAP on perf event asynchronously if blocked
Marek Vasut (4):
drm: bridge: icn6211: Fix register layout
drm: bridge: icn6211: Fix HFP_HSW_HBP_HI and HFP_MIN handling
drm/panel: simple: Add missing bus flags for Innolux G070Y2-L01
ARM: dts: stm32: Fix PHY post-reset delay on Avenger96
Mario Limonciello (5):
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
ASoC: amd: Add driver data to acp6x machine driver
PCI/ACPI: Allow D3 only if Root Port can signal and wake from D3
mailbox: pcc: Fix an invalid-load caught by the address sanitizer
iommu/amd: Enable swiotlb in all cases
Marios Levogiannis (1):
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Mark Bloch (1):
net/mlx5: fs, delete the FTE when there are no rules attached to it
Mark Brown (2):
ASoC: dapm: Don't fold register value changes into notifications
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Mark Rutland (4):
arm64: stackleak: fix current_top_of_stack()
irqchip/gic-v3: Ensure pseudo-NMIs have an ISB between ack and handling
irqchip/gic-v3: Refactor ISB + EOIR at ack time
irqchip/gic-v3: Fix priority mask handling
Masami Hiramatsu (1):
kprobes: Fix build errors with CONFIG_KRETPROBES=n
Mathias Nyman (1):
xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI
Matthew Wilcox (Oracle) (1):
alpha: fix alloc_zeroed_user_highpage_movable()
Matthias Schiffer (1):
arm64: dts: ti: k3-am64-mcu: remove incorrect UART base clock rates
Matthieu Baerts (1):
x86/pm: Fix false positive kmemleak report in msr_build_context()
Max Filippov (2):
xtensa: move trace_hardirqs_off call back to entry.S
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Max Krummenacher (1):
ARM: dts: imx6dl-colibri: Fix I2C pinmuxing
Maxime Ripard (5):
drm/vc4: kms: Take old state core clock rate into account
drm/vc4: hvs: Fix frame count register readout
drm/vc4: hvs: Reset muxes at probe time
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Mel Gorman (1):
mm/page_alloc: always attempt to allocate at least one page during bulk allocation
Miaohe Lin (2):
drivers/base/node.c: fix compaction sysfs file leak
mm/memremap: fix missing call to untrack_pfn() in pagemap_range()
Miaoqian Lin (26):
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
HID: elan: Fix potential double free in elan_input_configured
drm/bridge: Fix error handling in analogix_dp_probe
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
ASoC: imx-hdmi: Fix refcount leak in imx_hdmi_probe
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
ASoC: samsung: Fix refcount leak in aries_audio_probe
media: exynos4-is: Fix PM disable depth imbalance in fimc_is_probe
media: st-delta: Fix PM disable depth imbalance in delta_probe
media: atmel: atmel-isc: Fix PM disable depth imbalance in atmel_isc_probe
media: exynos4-is: Change clk_disable to clk_disable_unprepare
ASoC: ti: j721e-evm: Fix refcount leak in j721e_soc_probe_*
regulator: scmi: Fix refcount leak in scmi_regulator_probe
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
thermal/drivers/imx_sc_thermal: Fix refcount leak in imx_sc_thermal_probe
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
PCI: mediatek: Fix refcount leak in mtk_pcie_subsys_powerup()
Input: sparcspkr - fix refcount leak in bbc_beep_probe
powerpc/xive: Fix refcount leak in xive_spapr_init
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
ipmi:ipmb: Fix refcount leak in ipmi_ipmb_probe
Michael Ellerman (1):
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
Michael Niewöhner (1):
platform/x86: intel-hid: fix _DSM function index handling
Michael Rodin (1):
media: vsp1: Fix offset calculation for plane cropping
Michael Walle (2):
ARM: dts: lan966x: swap dma channels for crypto node
i2c: at91: use dma safe buffers
Mickaël Salaün (21):
landlock: Add clang-format exceptions
landlock: Format with clang-format
selftests/landlock: Add clang-format exceptions
selftests/landlock: Normalize array assignment
selftests/landlock: Format with clang-format
samples/landlock: Add clang-format exceptions
samples/landlock: Format with clang-format
landlock: Fix landlock_add_rule(2) documentation
selftests/landlock: Make tests build with old libc
selftests/landlock: Extend tests for minimal valid attribute size
selftests/landlock: Add tests for unknown access rights
selftests/landlock: Extend access right tests to directories
selftests/landlock: Fully test file rename with "remove" access
selftests/landlock: Add tests for O_PATH
landlock: Change landlock_add_rule(2) argument check ordering
landlock: Change landlock_restrict_self(2) check ordering
selftests/landlock: Test landlock_create_ruleset(2) argument check ordering
landlock: Define access_mask_t to enforce a consistent access mask size
landlock: Reduce the maximum number of layers to 16
landlock: Create find_rule() from unmask_layers()
landlock: Fix same-layer rule unions
Mika Westerberg (1):
PCI/ASPM: Make Intel DG2 L1 acceptable latency unlimited
Mike Kravetz (1):
hugetlb: fix huge_pmd_unshare address update
Mike Pagano (1):
media: i2c: ov2640: Depend on V4L2_ASYNC
Mike Travis (1):
x86/platform/uv: Update TSC sync state for UV5
Mikulas Patocka (4):
parisc: fix a crash with multicore scheduler
fs/ntfs3: provide block_invalidate_folio to fix memory leak
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
objtool: Fix objtool regression on x32 systems
Miles Chen (2):
drm/mediatek: Fix mtk_cec_mask()
iommu/mediatek: Fix NULL pointer dereference when printing dev_name
Mina Almasry (1):
hugetlbfs: fix hugetlbfs_statfs() locking
Ming Qian (1):
media: amphion: fix decoder's interlaced field
Minghao Chi (1):
scsi: ufs: Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
Monish Kumar R (1):
USB: new quirk for Dell Gen 2 devices
Moshe Tal (1):
net/mlx5e: Correct the calculation of max channels for rep
Muchun Song (1):
dax: fix cache flush on PMD-mapped pages
Mukul Joshi (1):
drm/amdkfd: Fix circular lock dependency warning
Mårten Lindahl (1):
hwmon: (pmbus) Add get_voltage/set_voltage ops
Namjae Jeon (1):
fs/ntfs3: Fix invalid free in log_replay
Naohiro Aota (4):
btrfs: zoned: properly finish block group on metadata write
btrfs: zoned: zone finish unused block group
btrfs: zoned: finish block group when there are no more allocatable bytes left
btrfs: zoned: fix comparison of alloc_offset vs meta_write_pointer
Nathan Chancellor (3):
riscv: Move alternative length validation into subsection
drm/i915: Fix CFI violation with show_dynamic_id()
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Naveen N. Rao (1):
kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
Nicholas Piggin (1):
KVM: PPC: Book3S HV Nested: L2 LPCR should inherit L1 LPES setting
Nico Boehr (1):
s390/perf: obtain sie_block from the right address
Nicolas Belin (1):
drm: bridge: it66121: Fix the register page length
Nicolas Dufresne (4):
media: hantro: Stop using H.264 parameter pic_num
media: rkvdec: h264: Fix dpb_valid implementation
media: coda: Fix reported H264 profile
media: coda: Add more H264 levels for CODA960
Nicolas Frattaroli (1):
ASoC: rk3328: fix disabling mclk on pclk probe failure
Niels Dossche (7):
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
ipv6: fix locking issues with loops over idev->addr_list
IB/rdmavt: add missing locks in rvt_ruc_loopback
ath11k: acquire ab->base_lock in unassign when finding the peer by addr
Bluetooth: use hdev lock in activate_scan for hci_is_adv_monitoring
Bluetooth: use hdev lock for accept_list and reject_list in conn req
Bluetooth: protect le accept and resolv lists with hdev->lock
Nikita Yushchenko (1):
drm/bridge_connector: enable HPD by default if supported
Niklas Cassel (1):
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
Nikolay Borisov (1):
selftests/bpf: Fix vfs_link kprobe definition
Noralf Trønnes (1):
dt-bindings: display: sitronix, st7735r: Fix backlight in example
Nuno Sá (1):
of: overlay: do not break notify on NOTIFY_{OK|STOP}
Nícolas F. R. A. Prado (3):
regulator: mt6315: Enforce regulator-compatible, not name
drm/bridge: anx7625: Use uint8 for lane-swing arrays
drm/mediatek: dpi: Use mt8183 output formats for mt8192
OGAWA Hirofumi (1):
fat: add ratelimit to fat*_ent_bread()
Ojaswin Mujoo (1):
ext4: fix journal_ioprio mount option handling
Olga Kornievskaia (1):
NFSv4.1 mark qualified async operations as MOVEABLE tasks
Omar Sandoval (1):
btrfs: fix anon_dev leak in create_subvol()
Padmanabha Srinivasaiah (1):
rcu-tasks: Fix race in schedule and flush work
Pali Rohár (1):
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Palmer Dabbelt (2):
RISC-V: Split out the XIP fixups into their own file
RISC-V: Fix the XIP build
Paolo Abeni (3):
mptcp: optimize release_cb for the common case
mptcp: reset the packet scheduler on incoming MP_PRIO
mptcp: reset the packet scheduler on PRIO change
Parshuram Thombare (1):
PCI: cadence: Clear FLR in device capabilities register
Patrice Chotard (1):
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Paul E. McKenney (3):
rcu-tasks: Handle sparse cpu_possible_mask in rcu_tasks_invoke_cbs()
rcu: Make TASKS_RUDE_RCU select IRQ_WORK
scftorture: Fix distribution of short handler delays
Paulo Alcantara (1):
cifs: fix ntlmssp on old servers
Pavan Chebbi (1):
bnxt_en: Configure ptp filters during bnxt open
Pavel Begunkov (1):
io_uring: avoid io-wq -EAGAIN looping for !IOPOLL
Pavel Skripkin (1):
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Peng Wu (3):
ARM: versatile: Add missing of_node_put in dcscb_init
ARM: hisi: Add missing of_node_put after of_find_compatible_node
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Peter Chiu (1):
mt76: mt7915: fix twt table_mask to u16 in mt7915_dev
Peter Seiderer (1):
mac80211: minstrel_ht: fix where rate stats are stored (fixes debugfs output)
Peter Ujfalusi (2):
ASoC: SOF: ipc3-topology: Correct get_control_data for non bytes payload
ASoC: SOF: ipc3-topology: Set scontrol->priv to NULL after freeing it
Peter Zijlstra (2):
linkage: Fix issue with missing symbol size
objtool: Fix symbol creation
Petr Machata (2):
mlxsw: spectrum_dcb: Do not warn about priority changes
mlxsw: Treat LLDP packets as control
Phil Auld (1):
kselftest/cgroup: fix test_stress.sh to use OUTPUT dir
Phil Elwell (3):
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Philipp Zabel (1):
media: coda: limit frame interval enumeration to supported encoder frame sizes
Pierre Gondois (2):
ACPI: CPPC: Assume no transition latency if no PCCT
PM: EM: Decrement policy counter
Pierre-Louis Bossart (2):
ASoC: max98357a: remove dependency on GPIOLIB
ASoC: rt1015p: remove dependency on GPIOLIB
Pin-Yen Lin (1):
drm/bridge: it6505: Send DPCD SET_POWER to downstream
Ping-Ke Shih (1):
rtw89: cfo: check mac_id to avoid out-of-bounds
Po Hao Huang (1):
rtw89: fix misconfiguration on hw_scan channel time
Po-Hao Huang (2):
rtw88: fix incorrect frequency reported
rtw88: 8821c: fix debugfs rssi value
Puyou Lu (1):
lib/string_helpers: fix not adding strarray to device's resource list
Qi Zheng (1):
tty: fix deadlock caused by calling printk() under tty_port->lock
QintaoShen (2):
soc: ti: ti_sci_pm_domains: Check for null return of devm_kcalloc
soc: bcm: Check for NULL return of devm_kzalloc()
Qu Wenruo (4):
btrfs: add "0x" prefix for unsupported optional features
btrfs: return correct error number for __extent_writepage_io()
btrfs: repair super block num_devices automatically
btrfs: fix the error handling for submit_extent_page() for btrfs_do_readpage()
Quentin Monnet (1):
selftests/bpf: Fix parsing of prog types in UAPI hdr for bpftool sync
Radhey Shyam Pandey (1):
net: macb: In ZynqMP initialization make SGMII phy configuration optional
Rafał Miłecki (1):
ARM: dts: BCM5301X: Update pin controller node name
Randy Dunlap (8):
x86: Fix return value of __setup handlers
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
media: make RADIO_ADAPTERS tristate
net: dsa: restrict SMSC_LAN9303_I2C kconfig
powerpc/8xx: export 'cpm_setbrg' for modules
powerpc/idle: Fix return value of __setup() handler
powerpc/4xx/cpm: Fix return value of __setup() handler
macintosh: via-pmu and via-cuda need RTC_LIB
Ravi Bangoria (2):
perf/amd/ibs: Cascade pmu init functions' return value
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Rei Yamamoto (1):
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Rex-BC Chen (2):
drm/mediatek: Add vblank register/unregister callback functions
cpufreq: mediatek: Unregister platform device on exit
Rik van der Kemp (1):
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9520 laptop
Robert Foss (1):
drm/bridge: Fix it6505 Kconfig DRM_DP_AUX_BUS dependency
Robert Marko (2):
arm64: dts: marvell: espressobin-ultra: fix SPI-NOR config
arm64: dts: marvell: espressobin-ultra: enable front USB3 port
Robin Murphy (1):
dma-direct: don't over-decrypt memory
Ronnie Sahlberg (2):
cifs: fix potential double free during failed mount
cifs: when extending a file with falloc we should make files not-sparse
Runqing Yang (1):
libbpf: Fix a bug with checking bpf_probe_read_kernel() support in old kernels
Russell Currey (2):
powerpc/powernv: Get L1D flush requirements from device-tree
powerpc/powernv: Get STF barrier requirements from device-tree
Russell King (Oracle) (1):
net: dsa: mt7530: 1G can also support 1000BASE-X link mode
Saaem Rizvi (1):
drm/amd/display: Disabling Z10 on DCN31
Sakari Ailus (2):
media: Revert "media: dw9768: activate runtime PM and turn off device"
ACPI: property: Release subnode properties with data nodes
Samuel Holland (1):
riscv: Fix irq_work when SMP is disabled
Sathishkumar S (2):
drm/amd/pm: update smartshift powerboost calc for smu12
drm/amd/pm: update smartshift powerboost calc for smu13
Schspa Shi (1):
cpufreq: Fix possible race in cpufreq online error path
Sean Christopherson (3):
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
KVM: nVMX: Clear IDT vectoring on nested VM-Exit for double/triple fault
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
Sean Wang (5):
mt76: mt7921: fix kernel crash at mt7921_pci_remove
Bluetooth: mt7921s: Fix the incorrect pointer check
Bluetooth: btmtksdio: fix use-after-free at btmtksdio_recv_event
Bluetooth: btmtksdio: fix possible FW initialization failure
Bluetooth: btmtksdio: fix the reset takes too long
Sean Young (2):
media: lirc: revert removal of unused feature flags
media: lirc: add missing exceptions for lirc uapi header file
Sebastian Andrzej Siewior (1):
crypto: cryptd - Protect per-CPU resource by disabling BH.
Shawn Lin (1):
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
Shyam Prasad N (1):
cifs: do not use tcpStatus after negotiate completes
Smith, Kyle Miller (Nimble Kernel) (1):
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Song Liu (1):
ftrace: Clean up hash direct_functions on register failures
Srinivas Kandagatla (1):
misc: fastrpc: fix list iterator in fastrpc_req_mem_unmap_impl
Srinivasa Rao Mandadapu (1):
ASoC: codecs: Fix error handling in power domain init and exit handlers
Stanislav Fomichev (1):
bpf: Move rcu lock management out of BPF_PROG_RUN routines
Stefan Wahren (4):
thermal/drivers/bcm2711: Don't clamp temperature at zero
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
gpiolib: of: Introduce hook for missing gpio-ranges
pinctrl: bcm2835: implement hook for missing gpio-ranges
Stephen Boyd (2):
arm64: dts: qcom: sc7280: Fix sar1_irq_odl node name
arm64: dts: qcom: sc7280-herobrine: Drop outputs on fpmcu pins
Steve French (2):
smb3: check for null tcon
SMB3: EBADF/EIO errors in rename/open caused by race condition in smb2_compound_op
Steven Price (1):
drm/plane: Move range check for format_count earlier
Steven Rostedt (Google) (1):
tracing: Have event format check not flag %p* on __get_dynamic_array()
Sudeep Holla (3):
arm64: dts: juno: Fix SCMI power domain IDs for ETF and CS funnel
firmware: arm_ffa: Fix uuid parameter to ffa_partition_probe
firmware: arm_ffa: Remove incorrect assignment of driver_data
Suravee Suthikulpanit (1):
iommu/amd: Do not call sleep while holding spinlock
Sven Schnelle (1):
s390/stp: clock_delta should be signed
Taehee Yoo (2):
amt: fix gateway mode stuck
amt: fix memory leak for advertisement message
Takashi Iwai (3):
ALSA: usb-audio: Cancel pending work at closing a MIDI substream
ALSA: usb-audio: Add quirk bits for enabling/disabling generic implicit fb
ALSA: usb-audio: Move generic implicit fb quirk entries into quirks.c
Tali Perry (2):
i2c: npcm: Fix timeout calculation
i2c: npcm: Handle spurious interrupts
Tejas Upadhyay (1):
iommu/vt-d: Add RPLS to quirk list to skip TE disabling
Tejun Heo (1):
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Tetsuo Handa (1):
media: imon: reorganize serialization
Theodore Ts'o (1):
ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state
Thibaut VARÈNE (1):
ath9k: fix QCA9561 PA bias level
Thierry Reding (1):
drm/tegra: gem: Do not try to dereference ERR_PTR()
Thorsten Scherer (1):
ARM: dts: ci4x10: Adapt to changes in imx6qdl.dtsi regarding fec clocks
Tiezhu Yang (1):
MIPS: RALINK: Define pci_remap_iospace under CONFIG_PCI_DRIVERS_GENERIC
Tobias Klauser (1):
riscv: Wire up memfd_secret in UAPI header
Tokunori Ikegami (2):
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Tom Rix (1):
drm/bridge: anx7625: check the return on anx7625_aux_trans
Tong Tiangen (1):
arm64: fix types in copy_highpage()
Tony Lindgren (1):
tty: n_gsm: Fix packet data hex dump output
Trond Myklebust (7):
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
NFS: fsync() should report filesystem errors over EINTR/ERESTARTSYS
NFS: Don't report ENOSPC write errors twice
NFS: Do not report flush errors in nfs_write_end()
NFS: Don't report errors from nfs_pageio_complete() more than once
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
NFS: Further fixes to the writeback error handling
Tyler Hicks (1):
EDAC/dmc520: Don't print an error for each unconfigured interrupt line
Tyrone Ting (1):
i2c: npcm: Correct register access width
Tzung-Bi Shih (1):
platform/chrome: cros_ec: fix error handling in cros_ec_register()
Ulf Hansson (4):
cpuidle: PSCI: Improve support for suspend-to-RAM for PSCI OSI mode
cpuidle: psci: Fix regression leading to no genpd governor
cpuidle: riscv-sbi: Fix code to allow a genpd governor to be used
PM: domains: Fix initialization of genpd's next_wakeup
Uwe Kleine-König (1):
char: tpm: cr50_i2c: Suppress duplicated error message in .remove()
Vaibhav Jain (1):
powerpc/papr_scm: Fix leaking nvdimm_events_map elements
Vasily Averin (2):
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
fanotify: fix incorrect fmode_t casts
Vignesh Raghavendra (1):
drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit
Vijaya Krishna Nivarthi (2):
arm64: dts: qcom: sc7280-idp: Configure CTS pin to bias-bus-hold for bluetooth
arm64: dts: qcom: sc7280-qcard: Configure CTS pin to bias-bus-hold for bluetooth
Vikash Garodia (1):
media: venus: do not queue internal buffers from previous sequence
Vincent Mailhol (1):
can: mcp251xfd: silence clang's -Wunaligned-access warning
Vincent Whitchurch (1):
um: Fix out-of-bounds read in LDT setup
Vinod Koul (3):
arm64: dts: qcom: sm8450: Fix missing iommus for qup
arm64: dts: qcom: sm8450: Fix missing iommus for qup1
arm64: dts: qcom: qrb5165-rb5: Fix can-clock node name
Vinod Polimera (2):
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
drm/msm/disp/dpu1: avoid clearing hw interrupts if hw_intr is null during drm uninit
Viresh Kumar (2):
cpufreq: Avoid unnecessary frequency updates due to mismatch
Revert "cpufreq: Fix possible race in cpufreq online error path"
Vladis Dronov (2):
hwrng: cn10k - Optimize cn10k_rng_read()
hwrng: cn10k - Make check_rng_health() return an error code
Waiman Long (2):
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
kseltest/cgroup: Make test_stress.sh work if run interactively
Wan Jiabing (2):
drm/omap: fix NULL but dereferenced coccicheck error
rtla: Avoid record NULL pointer dereference
Wanpeng Li (1):
KVM: LAPIC: Drop pending LAPIC timer injection when canceling the timer
Wei Yongjun (1):
regulator: da9121: Fix uninit-value in da9121_assign_chip_model()
Wen Gong (2):
ath11k: fix the warning of dev_wake in mhi_pm_disable_transition()
ath11k: fix warning of not found station for bssid in message
Wenli Looi (1):
ath9k: fix ar9003_get_eepmisc
Wolfgang Bumiller (1):
blk-cgroup: always terminate io.stat lines
Wonhyuk Yang (1):
tracing: Fix return value of trace_pid_write()
Xiang Chen (1):
scsi: hisi_sas: Undo RPM resume for failed notify phy event for v3 HW
Xianting Tian (1):
RISC-V: Mark IORESOURCE_EXCLUSIVE for reserved mem instead of IORESOURCE_BUSY
Xiao Ni (2):
md: Don't set mddev private to NULL in raid0 pers->free
md: fix double free of io_acct_set bioset
Xiao Yang (1):
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Xiaoguang Wang (1):
scsi: target: tcmu: Fix possible data corruption
Xiaomeng Tong (11):
media: uvcvideo: Fix missing check to determine if element is found in list
scsi: dc395x: Fix a missing check on list iterator
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator
md: fix an incorrect NULL check in does_sb_need_changing
md: fix an incorrect NULL check in md_reload_sb
iommu/msm: Fix an incorrect NULL check on list iterator
carl9170: tx: fix an incorrect use of list iterator
stm: ltdc: fix two incorrect NULL checks on list iterator
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
gma500: fix an incorrect NULL check on list iterator
Xie Yongji (1):
nbd: Fix hung on disconnect request if socket is closed before
Yang Jihong (1):
perf tools: Add missing headers needed by util/data.h
Yang Yingliang (13):
pinctrl: renesas: rzn1: Fix possible null-ptr-deref in sh_pfc_map_resources()
drm/bridge: anx7625: add missing destroy_workqueue() in anx7625_i2c_probe()
mtd: rawnand: cadence: fix possible null-ptr-deref in cadence_nand_dt_probe()
mtd: rawnand: intel: fix possible null-ptr-deref in ebu_nand_probe()
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
spi: spi-fsl-qspi: check return value after calling platform_get_resource_byname()
media: i2c: ov5648: fix wrong pointer passed to IS_ERR() and PTR_ERR()
thermal/core: Fix memory leak in __thermal_cooling_device_register()
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
pinctrl: renesas: core: Fix possible null-ptr-deref in sh_pfc_map_resources()
hwrng: omap3-rom - fix using wrong clk_disable() in omap_rom_rng_runtime_resume()
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
Yangyang Li (1):
RDMA/hns: Add the detection for CMDQ status in the device initialization process
Ye Bin (3):
ext4: fix use-after-free in ext4_rename_dir_prepare
ext4: fix warning in ext4_handle_inode_extension
ext4: fix bug_on in ext4_writepages
Yi Yang (1):
xtensa/simdisk: fix proc_read_simdisk()
Yicong Yang (1):
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Ying Hsu (1):
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Yixing Liu (1):
RDMA/hns: Remove the num_cqc_timer variable
Yong Wu (4):
iommu/mediatek: Fix 2 HW sharing pgtable issue
iommu/mediatek: Add list_del in mtk_iommu_remove
iommu/mediatek: Remove clk_disable in mtk_iommu_remove
iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
Yonghong Song (1):
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Yongqiang Sun (2):
drm/amd/amdgpu: Only reserve vram for firmware with vega9 MS_HYPERV host.
drm/amd/amdgpu: Fix asm/hypervisor.h build error.
Yongzhi Liu (1):
hv_netvsc: Fix potential dereference of NULL pointer
Yuanchu Xie (1):
selftests/damon: add damon to selftests root Makefile
YueHaibing (4):
drm/solomon: Make DRM_SSD130X depends on MMU
drm/bridge: it6505: Fix build error
net: ethernet: ti: am65-cpsw: Fix build error without PHYLINK
ASoC: codecs: lpass: Fix passing zero to 'PTR_ERR'
Yunfei Dong (2):
media: mediatek: vcodec: prevent kernel crash when rmmod mtk-vcodec-dec.ko
media: mediatek: vcodec: Fix v4l2 compliance decoder cmd test fail
Yunfei Wang (1):
iommu/dma: Fix iova map result check bug
Yuntao Wang (2):
selftests/bpf: Fix file descriptor leak in load_kallsyms()
selftests/bpf: Add missing trampoline program type to trampoline_count test
Zack Rusin (2):
drm/vmwgfx: validate the screen formats
drm/vmwgfx: Fix an invalid read
Zev Weiss (1):
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Zhen Lei (1):
of: Support more than one crash kernel regions for kexec -s
Zheng Bin (2):
ASoC: SOF: amd: add missing platform_device_unregister in acp_pci_rn_probe
net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init
Zheng Yongjun (2):
spi: img-spfi: Fix pm_runtime_get_sync() error checking
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
Zhengjun Xing (2):
perf jevents: Fix event syntax error caused by ExtSel
perf evlist: Extend arch_evsel__must_be_in_group to support hybrid systems
Zheyu Ma (4):
media: i2c: dw9714: Disable the regulator when the driver fails to probe
media: pci: cx23885: Fix the error handling in cx23885_initdev()
media: cx25821: Fix the warning when removing the module
mtd: rawnand: denali: Use managed device resources
Zhihao Cheng (1):
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
Zhou Qingyang (1):
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Zijun Hu (1):
Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ERR_DATA_REPORTING for QCA
Zixuan Fu (1):
fs: jfs: fix possible NULL pointer dereference in dbFree()
Ziyang Xuan (2):
net/mlx5: use kvfree() for kvzalloc() in mlx5_ct_fs_smfs_matcher_create
macsec: fix UAF bug for real_dev
Zong-Zhe Yang (1):
rtw89: ser: fix CAM leaks occurring in L2 reset
jianghaoran (1):
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
liuyacan (3):
net/smc: postpone sk_refcnt increment in connect()
net/smc: fix listen processing for SMC-Rv2
Revert "net/smc: fix listen processing for SMC-Rv2"
^ permalink raw reply [relevance 1%]
* Linux 5.17.14
@ 2022-06-09 8:39 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-09 8:39 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.17.14 kernel.
All users of the 5.17 kernel series must upgrade.
The updated 5.17.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.17.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/accounting/psi.rst | 9
Documentation/conf.py | 2
Documentation/devicetree/bindings/display/sitronix,st7735r.yaml | 1
Documentation/devicetree/bindings/gpio/gpio-altera.txt | 5
Documentation/devicetree/bindings/regulator/mt6315-regulator.yaml | 2
Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml | 1
Documentation/devicetree/bindings/spi/qcom,spi-qcom-qspi.yaml | 1
Documentation/sound/alsa-configuration.rst | 4
Documentation/userspace-api/landlock.rst | 4
Makefile | 2
arch/alpha/include/asm/page.h | 2
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4
arch/arm/boot/dts/bcm5301x.dtsi | 2
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 6
arch/arm/boot/dts/imx6qdl-colibri.dtsi | 6
arch/arm/boot/dts/ox820.dtsi | 2
arch/arm/boot/dts/qcom-sdx65.dtsi | 2
arch/arm/boot/dts/s5pv210-aries.dtsi | 3
arch/arm/boot/dts/s5pv210.dtsi | 12
arch/arm/boot/dts/sama7g5.dtsi | 1
arch/arm/boot/dts/socfpga.dtsi | 2
arch/arm/boot/dts/socfpga_arria10.dtsi | 2
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 1
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4
arch/arm/include/asm/arch_gicv3.h | 7
arch/arm/kernel/signal.c | 1
arch/arm/mach-hisi/platsmp.c | 4
arch/arm/mach-mediatek/Kconfig | 1
arch/arm/mach-omap1/clock.c | 2
arch/arm/mach-pxa/cm-x300.c | 8
arch/arm/mach-pxa/magician.c | 2
arch/arm/mach-pxa/tosa.c | 4
arch/arm/mach-vexpress/dcscb.c | 1
arch/arm64/Kconfig.platforms | 1
arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts | 5
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 2
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 5
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2
arch/arm64/boot/dts/qcom/msm8994.dtsi | 8
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 2
arch/arm64/boot/dts/qcom/sc7280-idp.dtsi | 18
arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium.dts | 2
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2
arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi | 2
arch/arm64/include/asm/arch_gicv3.h | 6
arch/arm64/include/asm/processor.h | 10
arch/arm64/kernel/signal.c | 1
arch/arm64/kernel/signal32.c | 1
arch/arm64/kernel/sys_compat.c | 2
arch/arm64/mm/copypage.c | 4
arch/csky/kernel/probes/kprobes.c | 2
arch/m68k/Kconfig.cpu | 2
arch/m68k/include/asm/raw_io.h | 6
arch/m68k/kernel/signal.c | 1
arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h | 1
arch/mips/include/asm/mach-ip30/cpu-feature-overrides.h | 1
arch/mips/include/asm/mach-ralink/spaces.h | 2
arch/openrisc/include/asm/timex.h | 1
arch/openrisc/kernel/head.S | 9
arch/parisc/include/asm/fb.h | 4
arch/powerpc/include/asm/page.h | 7
arch/powerpc/include/asm/vas.h | 2
arch/powerpc/kernel/entry_64.S | 24
arch/powerpc/kernel/fadump.c | 8
arch/powerpc/kernel/idle.c | 2
arch/powerpc/kernel/rtas.c | 9
arch/powerpc/kvm/book3s_hv.c | 12
arch/powerpc/kvm/book3s_hv_nested.c | 3
arch/powerpc/kvm/trace_hv.h | 8
arch/powerpc/mm/nohash/fsl_book3e.c | 15
arch/powerpc/perf/isa207-common.c | 12
arch/powerpc/platforms/4xx/cpm.c | 2
arch/powerpc/platforms/8xx/cpm1.c | 1
arch/powerpc/platforms/powernv/opal-fadump.c | 94 -
arch/powerpc/platforms/powernv/opal-fadump.h | 10
arch/powerpc/platforms/powernv/setup.c | 9
arch/powerpc/platforms/powernv/ultravisor.c | 1
arch/powerpc/platforms/powernv/vas-fault.c | 2
arch/powerpc/platforms/powernv/vas-window.c | 4
arch/powerpc/platforms/powernv/vas.h | 2
arch/powerpc/sysdev/dart_iommu.c | 6
arch/powerpc/sysdev/fsl_rio.c | 2
arch/powerpc/sysdev/xics/icp-opal.c | 1
arch/powerpc/sysdev/xive/spapr.c | 43
arch/riscv/Makefile | 4
arch/riscv/include/asm/alternative-macros.h | 4
arch/riscv/include/asm/irq_work.h | 2
arch/riscv/include/asm/unistd.h | 1
arch/riscv/include/uapi/asm/unistd.h | 1
arch/riscv/kernel/head.S | 1
arch/riscv/kernel/setup.c | 4
arch/riscv/mm/init.c | 2
arch/s390/include/asm/cio.h | 2
arch/s390/include/asm/kexec.h | 10
arch/s390/include/asm/preempt.h | 15
arch/s390/kernel/perf_event.c | 2
arch/s390/kernel/time.c | 8
arch/sparc/kernel/signal32.c | 1
arch/sparc/kernel/signal_64.c | 1
arch/um/drivers/chan_user.c | 9
arch/um/drivers/virtio_uml.c | 33
arch/um/include/asm/Kbuild | 1
arch/um/include/asm/thread_info.h | 2
arch/um/kernel/exec.c | 2
arch/um/kernel/process.c | 2
arch/um/kernel/ptrace.c | 8
arch/um/kernel/signal.c | 4
arch/x86/Kconfig | 4
arch/x86/entry/entry_64.S | 1
arch/x86/entry/vdso/vma.c | 2
arch/x86/events/amd/ibs.c | 55
arch/x86/events/intel/core.c | 2
arch/x86/include/asm/acenv.h | 14
arch/x86/include/asm/kexec.h | 8
arch/x86/include/asm/set_memory.h | 52
arch/x86/include/asm/suspend_32.h | 2
arch/x86/include/asm/suspend_64.h | 12
arch/x86/kernel/apic/apic.c | 2
arch/x86/kernel/apic/x2apic_uv_x.c | 8
arch/x86/kernel/cpu/intel.c | 2
arch/x86/kernel/cpu/mce/amd.c | 32
arch/x86/kernel/cpu/mce/core.c | 6
arch/x86/kernel/cpu/sgx/encl.c | 105 +
arch/x86/kernel/cpu/sgx/encl.h | 7
arch/x86/kernel/cpu/sgx/main.c | 9
arch/x86/kernel/machine_kexec_64.c | 12
arch/x86/kernel/signal_compat.c | 2
arch/x86/kernel/step.c | 3
arch/x86/kernel/sys_x86_64.c | 7
arch/x86/kvm/lapic.c | 1
arch/x86/kvm/vmx/nested.c | 45
arch/x86/kvm/vmx/vmcs.h | 5
arch/x86/lib/delay.c | 4
arch/x86/mm/pat/memtype.c | 2
arch/x86/mm/pat/set_memory.c | 49
arch/x86/pci/irq.c | 19
arch/x86/um/ldt.c | 6
arch/xtensa/kernel/entry.S | 19
arch/xtensa/kernel/ptrace.c | 4
arch/xtensa/kernel/signal.c | 4
arch/xtensa/kernel/traps.c | 11
arch/xtensa/platforms/iss/simdisk.c | 18
block/bfq-cgroup.c | 111 -
block/bfq-iosched.c | 64
block/bfq-iosched.h | 7
block/blk-cgroup.c | 8
block/blk-ia-ranges.c | 7
block/blk-iolatency.c | 122 -
block/blk-throttle.c | 3
crypto/cryptd.c | 23
drivers/acpi/cppc_acpi.c | 17
drivers/acpi/property.c | 18
drivers/acpi/sleep.c | 12
drivers/base/memory.c | 5
drivers/base/node.c | 1
drivers/base/power/domain.c | 1
drivers/base/property.c | 89 -
drivers/block/drbd/drbd_main.c | 11
drivers/block/nbd.c | 13
drivers/block/virtio_blk.c | 7
drivers/bluetooth/btmtksdio.c | 3
drivers/bluetooth/btusb.c | 6
drivers/char/hw_random/cn10k-rng.c | 31
drivers/char/hw_random/omap3-rom-rng.c | 2
drivers/char/ipmi/ipmi_msghandler.c | 4
drivers/char/ipmi/ipmi_poweroff.c | 4
drivers/char/ipmi/ipmi_ssif.c | 23
drivers/char/ipmi/ipmi_watchdog.c | 14
drivers/char/random.c | 12
drivers/char/tpm/tpm_tis_i2c_cr50.c | 4
drivers/clk/tegra/clk-dfll.c | 12
drivers/cpufreq/cpufreq.c | 11
drivers/cpufreq/mediatek-cpufreq.c | 18
drivers/cpuidle/cpuidle-psci.c | 46
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c | 115 +
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 30
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c | 10
drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 14
drivers/crypto/ccp/sev-dev.c | 30
drivers/crypto/ccree/cc_buffer_mgr.c | 27
drivers/crypto/marvell/cesa/cipher.c | 1
drivers/crypto/nx/nx-common-powernv.c | 2
drivers/crypto/qat/qat_common/adf_pfvf_pf_proto.c | 2
drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 13
drivers/devfreq/rk3399_dmc.c | 2
drivers/dma/idxd/cdev.c | 8
drivers/dma/stm32-mdma.c | 23
drivers/edac/dmc520_edac.c | 2
drivers/firmware/arm_ffa/driver.c | 4
drivers/firmware/arm_scmi/base.c | 2
drivers/firmware/efi/Kconfig | 15
drivers/firmware/efi/efi.c | 2
drivers/gpio/gpio-rockchip.c | 24
drivers/gpio/gpio-sim.c | 4
drivers/gpio/gpiolib-of.c | 5
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 95 -
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 8
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 8
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 1
drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 14
drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 8
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 60
drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 62
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10
drivers/gpu/drm/arm/malidp_crtc.c | 5
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31
drivers/gpu/drm/bridge/analogix/anx7625.c | 12
drivers/gpu/drm/bridge/analogix/anx7625.h | 4
drivers/gpu/drm/bridge/chipone-icn6211.c | 155 +-
drivers/gpu/drm/bridge/ite-it66121.c | 2
drivers/gpu/drm/drm_bridge_connector.c | 4
drivers/gpu/drm/drm_edid.c | 6
drivers/gpu/drm/drm_plane.c | 14
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6
drivers/gpu/drm/gma500/psb_intel_display.c | 7
drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 33
drivers/gpu/drm/i915/i915_perf.c | 4
drivers/gpu/drm/i915/i915_perf_types.h | 2
drivers/gpu/drm/mediatek/mtk_cec.c | 2
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 16
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 22
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 20
drivers/gpu/drm/mediatek/mtk_dpi.c | 4
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 14
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 29
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 19
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 16
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 3
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 3
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 2
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20
drivers/gpu/drm/msm/dp/dp_ctrl.c | 16
drivers/gpu/drm/msm/dp/dp_display.c | 55
drivers/gpu/drm/msm/dp/dp_drm.c | 4
drivers/gpu/drm/msm/dsi/dsi_host.c | 21
drivers/gpu/drm/msm/dsi/dsi_manager.c | 3
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 2
drivers/gpu/drm/msm/hdmi/hdmi.c | 10
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 3
drivers/gpu/drm/msm/msm_drv.c | 11
drivers/gpu/drm/msm/msm_gem_prime.c | 2
drivers/gpu/drm/msm/msm_gpu.h | 12
drivers/gpu/drm/msm/msm_gpu_devfreq.c | 90 +
drivers/gpu/drm/msm/msm_kms.h | 1
drivers/gpu/drm/nouveau/dispnv50/atom.h | 6
drivers/gpu/drm/nouveau/dispnv50/crc.c | 27
drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 2
drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c | 14
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c | 6
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c | 6
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6
drivers/gpu/drm/omapdrm/omap_overlay.c | 2
drivers/gpu/drm/panel/panel-simple.c | 3
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2
drivers/gpu/drm/stm/ltdc.c | 16
drivers/gpu/drm/tegra/gem.c | 1
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8
drivers/gpu/drm/v3d/v3d_perfmon.c | 3
drivers/gpu/drm/vc4/vc4_crtc.c | 2
drivers/gpu/drm/vc4/vc4_drv.h | 1
drivers/gpu/drm/vc4/vc4_hvs.c | 49
drivers/gpu/drm/vc4/vc4_kms.c | 5
drivers/gpu/drm/vc4/vc4_regs.h | 12
drivers/gpu/drm/vc4/vc4_txp.c | 8
drivers/gpu/drm/virtio/virtgpu_display.c | 2
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 30
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 14
drivers/hid/amd-sfh-hid/amd_sfh_hid.c | 4
drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2
drivers/hid/hid-bigbenff.c | 6
drivers/hid/hid-elan.c | 2
drivers/hid/hid-led.c | 2
drivers/hv/channel.c | 6
drivers/hwmon/pmbus/pmbus_core.c | 28
drivers/hwtracing/coresight/coresight-core.c | 33
drivers/i2c/busses/i2c-at91-master.c | 11
drivers/i2c/busses/i2c-npcm7xx.c | 103 -
drivers/i2c/busses/i2c-rcar.c | 15
drivers/infiniband/hw/hfi1/file_ops.c | 2
drivers/infiniband/hw/hfi1/init.c | 2
drivers/infiniband/hw/hfi1/sdma.c | 12
drivers/infiniband/hw/hns/hns_roce_device.h | 7
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 24
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2
drivers/infiniband/hw/hns/hns_roce_main.c | 2
drivers/infiniband/sw/rdmavt/qp.c | 6
drivers/infiniband/sw/rxe/rxe_req.c | 2
drivers/input/keyboard/gpio_keys.c | 2
drivers/input/misc/sparcspkr.c | 1
drivers/input/touchscreen/stmfts.c | 16
drivers/iommu/amd/init.c | 2
drivers/iommu/amd/iommu.c | 7
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 13
drivers/iommu/dma-iommu.c | 7
drivers/iommu/intel/iommu.c | 2
drivers/iommu/msm_iommu.c | 11
drivers/iommu/mtk_iommu.c | 30
drivers/iommu/mtk_iommu.h | 2
drivers/iommu/mtk_iommu_v1.c | 7
drivers/irqchip/irq-armada-370-xp.c | 11
drivers/irqchip/irq-aspeed-i2c-ic.c | 4
drivers/irqchip/irq-aspeed-scu-ic.c | 4
drivers/irqchip/irq-gic-v3.c | 183 +-
drivers/irqchip/irq-sni-exiu.c | 25
drivers/irqchip/irq-xtensa-mx.c | 18
drivers/macintosh/Kconfig | 6
drivers/macintosh/Makefile | 3
drivers/macintosh/via-pmu.c | 2
drivers/mailbox/mailbox.c | 19
drivers/mailbox/pcc.c | 2
drivers/md/bcache/btree.c | 58
drivers/md/bcache/btree.h | 2
drivers/md/bcache/journal.c | 31
drivers/md/bcache/journal.h | 2
drivers/md/bcache/request.c | 6
drivers/md/bcache/super.c | 1
drivers/md/bcache/writeback.c | 101 -
drivers/md/bcache/writeback.h | 2
drivers/md/md-bitmap.c | 44
drivers/md/md.c | 22
drivers/md/raid0.c | 1
drivers/media/cec/core/cec-adap.c | 6
drivers/media/i2c/ccs/ccs-core.c | 7
drivers/media/i2c/dw9768.c | 6
drivers/media/i2c/max9286.c | 137 +
drivers/media/i2c/ov5648.c | 4
drivers/media/i2c/ov7670.c | 1
drivers/media/i2c/rdacm20.c | 2
drivers/media/i2c/rdacm21.c | 2
drivers/media/pci/cx23885/cx23885-core.c | 6
drivers/media/pci/cx25821/cx25821-core.c | 2
drivers/media/platform/aspeed-video.c | 4
drivers/media/platform/atmel/atmel-sama5d2-isc.c | 7
drivers/media/platform/coda/coda-common.c | 35
drivers/media/platform/exynos4-is/fimc-is.c | 6
drivers/media/platform/exynos4-is/fimc-isp-video.h | 2
drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 13
drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 3
drivers/media/platform/qcom/venus/helpers.c | 34
drivers/media/platform/qcom/venus/hfi.c | 3
drivers/media/platform/rockchip/rga/rga.c | 6
drivers/media/platform/sti/delta/delta-v4l2.c | 6
drivers/media/platform/vsp1/vsp1_rpf.c | 6
drivers/media/rc/imon.c | 99 -
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7
drivers/media/usb/uvc/uvc_v4l2.c | 20
drivers/memory/samsung/exynos5422-dmc.c | 5
drivers/mfd/davinci_voicecodec.c | 6
drivers/mfd/ipaq-micro.c | 2
drivers/misc/ocxl/file.c | 2
drivers/mmc/core/block.c | 8
drivers/mmc/host/jz4740_mmc.c | 20
drivers/mmc/host/sdhci_am654.c | 23
drivers/mtd/chips/cfi_cmdset_0002.c | 103 -
drivers/mtd/mtdblock.c | 8
drivers/mtd/nand/raw/cadence-nand-controller.c | 5
drivers/mtd/nand/raw/denali_pci.c | 15
drivers/mtd/nand/raw/intel-nand-controller.c | 2
drivers/mtd/nand/spi/gigadevice.c | 10
drivers/mtd/spi-nor/core.c | 9
drivers/net/amt.c | 11
drivers/net/bonding/bond_main.c | 15
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 2
drivers/net/can/xilinx_can.c | 4
drivers/net/dsa/Kconfig | 3
drivers/net/dsa/mt7530.c | 14
drivers/net/ethernet/broadcom/Makefile | 5
drivers/net/ethernet/cadence/macb_main.c | 40
drivers/net/ethernet/cadence/macb_ptp.c | 4
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 2
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 2
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 4
drivers/net/ethernet/mellanox/mlx5/core/en.h | 1
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 9
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 10
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10
drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 2
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c | 1
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h | 1
drivers/net/ethernet/mellanox/mlx5/core/main.c | 23
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h | 2
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13
drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c | 2
drivers/net/ethernet/sfc/ef10.c | 2
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | 13
drivers/net/ethernet/xscale/ptp_ixp46x.c | 2
drivers/net/hyperv/netvsc_drv.c | 5
drivers/net/ipa/ipa_endpoint.c | 36
drivers/net/phy/micrel.c | 11
drivers/net/usb/asix_devices.c | 6
drivers/net/usb/smsc95xx.c | 3
drivers/net/usb/usbnet.c | 6
drivers/net/wireless/ath/ath10k/mac.c | 20
drivers/net/wireless/ath/ath11k/mac.c | 16
drivers/net/wireless/ath/ath11k/pci.c | 12
drivers/net/wireless/ath/ath11k/spectral.c | 17
drivers/net/wireless/ath/ath11k/wmi.c | 11
drivers/net/wireless/ath/ath11k/wmi.h | 12
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8
drivers/net/wireless/ath/carl9170/tx.c | 3
drivers/net/wireless/broadcom/b43/phy_n.c | 2
drivers/net/wireless/broadcom/b43legacy/phy.c | 2
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2
drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 3
drivers/net/wireless/intel/iwlwifi/mei/main.c | 3
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3
drivers/net/wireless/marvell/mwifiex/11h.c | 2
drivers/net/wireless/mediatek/mt76/agg-rx.c | 5
drivers/net/wireless/mediatek/mt76/mac80211.c | 8
drivers/net/wireless/mediatek/mt76/mt76.h | 2
drivers/net/wireless/mediatek/mt76/mt7603/main.c | 2
drivers/net/wireless/mediatek/mt76/mt7615/main.c | 2
drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c | 2
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4
drivers/net/wireless/mediatek/mt76/mt7915/main.c | 2
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 2
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6
drivers/net/wireless/mediatek/mt76/mt7921/main.c | 2
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 10
drivers/net/wireless/mediatek/mt76/tx.c | 11
drivers/net/wireless/microchip/wilc1000/mon.c | 4
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8
drivers/net/wireless/realtek/rtlwifi/usb.c | 2
drivers/net/wireless/realtek/rtw88/rtw8821c.c | 4
drivers/net/wireless/realtek/rtw88/rx.c | 3
drivers/net/wireless/realtek/rtw89/phy.c | 5
drivers/nfc/st21nfca/se.c | 17
drivers/nfc/st21nfca/st21nfca.h | 1
drivers/nvdimm/core.c | 9
drivers/nvdimm/pmem.c | 30
drivers/nvdimm/security.c | 5
drivers/nvme/host/core.c | 21
drivers/nvme/host/pci.c | 1
drivers/of/fdt.c | 3
drivers/of/kexec.c | 9
drivers/of/overlay.c | 4
drivers/opp/of.c | 2
drivers/pci/controller/cadence/pci-j721e.c | 3
drivers/pci/controller/cadence/pcie-cadence-ep.c | 21
drivers/pci/controller/cadence/pcie-cadence.h | 3
drivers/pci/controller/dwc/pci-imx6.c | 23
drivers/pci/controller/dwc/pcie-designware-host.c | 3
drivers/pci/controller/dwc/pcie-qcom.c | 9
drivers/pci/controller/pcie-mediatek-gen3.c | 8
drivers/pci/controller/pcie-mediatek.c | 1
drivers/pci/controller/pcie-microchip-host.c | 16
drivers/pci/controller/pcie-rockchip-ep.c | 3
drivers/pci/pci-acpi.c | 41
drivers/pci/pci.c | 12
drivers/pci/pcie/aer.c | 7
drivers/pci/quirks.c | 47
drivers/phy/qualcomm/phy-qcom-qmp.c | 11
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 18
drivers/pinctrl/mediatek/Kconfig | 1
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2
drivers/pinctrl/pinctrl-apple-gpio.c | 1
drivers/pinctrl/pinctrl-rockchip.c | 64
drivers/pinctrl/pinctrl-rockchip.h | 7
drivers/pinctrl/renesas/core.c | 7
drivers/pinctrl/renesas/pfc-r8a779a0.c | 29
drivers/pinctrl/renesas/pinctrl-rzn1.c | 10
drivers/platform/chrome/cros_ec.c | 16
drivers/platform/chrome/cros_ec_chardev.c | 2
drivers/platform/chrome/cros_ec_proto.c | 50
drivers/platform/mips/cpu_hwmon.c | 127 -
drivers/platform/x86/intel/hid.c | 2
drivers/regulator/core.c | 7
drivers/regulator/da9121-regulator.c | 2
drivers/regulator/pfuze100-regulator.c | 2
drivers/regulator/qcom_smd-regulator.c | 35
drivers/regulator/scmi-regulator.c | 2
drivers/s390/cio/chsc.c | 4
drivers/scsi/dc395x.c | 15
drivers/scsi/fcoe/fcoe_ctlr.c | 2
drivers/scsi/hisi_sas/hisi_sas_main.c | 47
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10
drivers/scsi/lpfc/lpfc_els.c | 49
drivers/scsi/lpfc/lpfc_init.c | 51
drivers/scsi/lpfc/lpfc_logmsg.h | 6
drivers/scsi/lpfc/lpfc_scsi.c | 37
drivers/scsi/lpfc/lpfc_sli.c | 6
drivers/scsi/megaraid.c | 2
drivers/scsi/ufs/ti-j721e-ufs.c | 6
drivers/scsi/ufs/ufs-qcom.c | 14
drivers/scsi/ufs/ufshcd.c | 7
drivers/soc/bcm/bcm63xx/bcm-pmb.c | 3
drivers/soc/qcom/llcc-qcom.c | 1
drivers/soc/qcom/smp2p.c | 1
drivers/soc/qcom/smsm.c | 1
drivers/soc/ti/ti_sci_pm_domains.c | 2
drivers/spi/spi-cadence-quadspi.c | 2
drivers/spi/spi-fsl-qspi.c | 4
drivers/spi/spi-img-spfi.c | 2
drivers/spi/spi-rockchip.c | 113 +
drivers/spi/spi-rspi.c | 15
drivers/spi/spi-stm32-qspi.c | 3
drivers/spi/spi-ti-qspi.c | 5
drivers/staging/media/hantro/hantro_g2_hevc_dec.c | 11
drivers/staging/media/hantro/hantro_h264.c | 2
drivers/staging/media/hantro/hantro_v4l2.c | 8
drivers/staging/media/rkvdec/rkvdec-h264.c | 37
drivers/staging/r8188eu/os_dep/ioctl_linux.c | 98 -
drivers/target/target_core_device.c | 1
drivers/target/target_core_user.c | 50
drivers/thermal/broadcom/bcm2711_thermal.c | 5
drivers/thermal/broadcom/sr-thermal.c | 3
drivers/thermal/devfreq_cooling.c | 25
drivers/thermal/imx_sc_thermal.c | 6
drivers/thermal/thermal_core.c | 1
drivers/tty/goldfish.c | 20
drivers/tty/n_gsm.c | 31
drivers/tty/serial/pch_uart.c | 27
drivers/tty/tty_buffer.c | 3
drivers/usb/core/hcd.c | 29
drivers/usb/core/quirks.c | 3
drivers/usb/dwc3/gadget.c | 6
drivers/usb/host/xhci-pci.c | 2
drivers/usb/isp1760/isp1760-core.c | 8
drivers/usb/serial/option.c | 2
drivers/usb/serial/pl2303.c | 3
drivers/vdpa/vdpa_sim/vdpa_sim.c | 5
drivers/video/console/sticon.c | 5
drivers/video/console/sticore.c | 32
drivers/video/fbdev/amba-clcd.c | 5
drivers/video/fbdev/core/fbcon.c | 5
drivers/video/fbdev/sticore.h | 3
drivers/video/fbdev/stifb.c | 4
drivers/video/fbdev/vesafb.c | 5
fs/afs/misc.c | 5
fs/afs/rotate.c | 4
fs/afs/rxrpc.c | 8
fs/afs/write.c | 1
fs/binfmt_flat.c | 27
fs/btrfs/block-group.c | 8
fs/btrfs/block-group.h | 2
fs/btrfs/disk-io.c | 4
fs/btrfs/extent_io.c | 27
fs/btrfs/extent_io.h | 1
fs/btrfs/ioctl.c | 49
fs/btrfs/volumes.c | 8
fs/btrfs/zoned.c | 44
fs/btrfs/zoned.h | 5
fs/ceph/mds_client.c | 14
fs/cifs/cifsfs.c | 10
fs/cifs/cifsglob.h | 15
fs/cifs/connect.c | 67
fs/cifs/dfs_cache.c | 6
fs/cifs/fs_context.c | 29
fs/cifs/fs_context.h | 2
fs/cifs/misc.c | 7
fs/cifs/sess.c | 6
fs/cifs/smb2inode.c | 2
fs/cifs/smb2ops.c | 9
fs/cifs/smb2pdu.c | 3
fs/cifs/smb2transport.c | 3
fs/dax.c | 3
fs/dlm/lock.c | 15
fs/dlm/lowcomms.c | 2
fs/dlm/plock.c | 12
fs/erofs/decompressor.c | 5
fs/exec.c | 6
fs/exportfs/expfs.c | 5
fs/ext4/ext4.h | 6
fs/ext4/extents.c | 20
fs/ext4/inline.c | 12
fs/ext4/inode.c | 13
fs/ext4/mballoc.c | 18
fs/ext4/namei.c | 84 -
fs/ext4/super.c | 87 -
fs/f2fs/dir.c | 3
fs/f2fs/f2fs.h | 29
fs/f2fs/file.c | 20
fs/f2fs/hash.c | 11
fs/f2fs/inline.c | 29
fs/f2fs/inode.c | 19
fs/f2fs/namei.c | 7
fs/f2fs/segment.c | 42
fs/f2fs/segment.h | 33
fs/f2fs/super.c | 6
fs/fat/fatent.c | 7
fs/fs-writeback.c | 13
fs/gfs2/quota.c | 32
fs/hugetlbfs/inode.c | 4
fs/io_uring.c | 45
fs/iomap/buffered-io.c | 3
fs/jfs/jfs_dmap.c | 3
fs/ksmbd/connection.c | 2
fs/ksmbd/smb2misc.c | 2
fs/ksmbd/smb_common.c | 4
fs/namei.c | 70
fs/nfs/file.c | 50
fs/nfs/inode.c | 6
fs/nfs/nfs4proc.c | 41
fs/nfs/nfs4state.c | 2
fs/nfs/pagelist.c | 3
fs/nfs/pnfs.c | 6
fs/nfs/unlink.c | 8
fs/nfs/write.c | 54
fs/nfsd/nfscache.c | 2
fs/notify/fanotify/fanotify_user.c | 4
fs/notify/fdinfo.c | 11
fs/notify/inotify/inotify.h | 12
fs/notify/inotify/inotify_user.c | 2
fs/notify/mark.c | 6
fs/ntfs3/file.c | 12
fs/ntfs3/frecord.c | 10
fs/ntfs3/fslog.c | 12
fs/ntfs3/inode.c | 8
fs/ntfs3/xattr.c | 112 +
fs/ocfs2/dlmfs/userdlm.c | 16
fs/ocfs2/inode.c | 4
fs/ocfs2/journal.c | 33
fs/ocfs2/journal.h | 2
fs/ocfs2/super.c | 15
fs/proc/generic.c | 3
fs/proc/proc_net.c | 3
fs/seq_file.c | 32
include/drm/drm_edid.h | 6
include/linux/blk_types.h | 5
include/linux/bpf.h | 4
include/linux/compat.h | 1
include/linux/efi.h | 2
include/linux/fwnode.h | 10
include/linux/goldfish.h | 15
include/linux/gpio/driver.h | 12
include/linux/ipmi_smi.h | 6
include/linux/kexec.h | 46
include/linux/list.h | 16
include/linux/mailbox_controller.h | 1
include/linux/module.h | 3
include/linux/mtd/cfi.h | 1
include/linux/namei.h | 6
include/linux/nfs_fs_sb.h | 1
include/linux/nodemask.h | 13
include/linux/platform_data/cros_ec_proto.h | 3
include/linux/ptp_classify.h | 3
include/linux/ptrace.h | 7
include/linux/sched/signal.h | 2
include/linux/sched/task.h | 2
include/linux/seq_file.h | 4
include/linux/set_memory.h | 10
include/linux/usb/hcd.h | 2
include/net/bluetooth/hci.h | 9
include/net/bluetooth/hci_core.h | 10
include/net/if_inet6.h | 8
include/scsi/libfcoe.h | 3
include/scsi/libiscsi.h | 6
include/sound/cs35l41.h | 1
include/sound/jack.h | 1
include/trace/events/rxrpc.h | 2
include/trace/events/vmscan.h | 4
include/uapi/asm-generic/siginfo.h | 7
include/uapi/linux/landlock.h | 9
init/Kconfig | 5
init/main.c | 2
ipc/mqueue.c | 14
kernel/dma/debug.c | 2
kernel/dma/direct.c | 31
kernel/events/core.c | 4
kernel/fork.c | 22
kernel/kexec_file.c | 34
kernel/module.c | 4
kernel/power/energy_model.c | 2
kernel/printk/printk.c | 63
kernel/ptrace.c | 5
kernel/rcu/Kconfig | 1
kernel/rcu/tasks.h | 5
kernel/scftorture.c | 5
kernel/sched/core.c | 6
kernel/sched/deadline.c | 5
kernel/sched/fair.c | 8
kernel/sched/pelt.h | 4
kernel/sched/psi.c | 15
kernel/sched/rt.c | 5
kernel/sched/sched.h | 32
kernel/signal.c | 18
kernel/trace/ftrace.c | 5
kernel/trace/trace.c | 6
kernel/trace/trace_boot.c | 2
kernel/trace/trace_events_hist.c | 3
kernel/trace/trace_osnoise.c | 9
kernel/trace/trace_selftest.c | 3
kernel/umh.c | 6
lib/kunit/debugfs.c | 2
lib/kunit/executor.c | 32
lib/kunit/executor_test.c | 4
lib/list-test.c | 19
lib/string_helpers.c | 3
mm/cma.c | 4
mm/compaction.c | 2
mm/hugetlb.c | 9
mm/memremap.c | 2
mm/page_alloc.c | 4
net/bluetooth/hci_conn.c | 39
net/bluetooth/hci_event.c | 46
net/bluetooth/hci_request.c | 2
net/bluetooth/hci_sync.c | 11
net/bluetooth/sco.c | 23
net/core/dev.c | 8
net/ipv4/tcp_input.c | 28
net/ipv6/addrconf.c | 33
net/mac80211/chan.c | 7
net/mac80211/ieee80211_i.h | 5
net/mac80211/rc80211_minstrel_ht.c | 3
net/mac80211/scan.c | 20
net/mptcp/pm.c | 19
net/mptcp/pm_netlink.c | 2
net/mptcp/protocol.c | 18
net/mptcp/protocol.h | 1
net/nfc/core.c | 1
net/rxrpc/ar-internal.h | 15
net/rxrpc/call_accept.c | 6
net/rxrpc/call_event.c | 7
net/rxrpc/call_object.c | 18
net/rxrpc/conn_object.c | 2
net/rxrpc/input.c | 58
net/rxrpc/net_ns.c | 2
net/rxrpc/output.c | 20
net/rxrpc/proc.c | 10
net/rxrpc/recvmsg.c | 8
net/rxrpc/sendmsg.c | 6
net/rxrpc/sysctl.c | 4
net/sctp/input.c | 4
net/smc/af_smc.c | 2
net/wireless/nl80211.c | 4
net/wireless/reg.c | 4
samples/bpf/Makefile | 9
samples/landlock/sandboxer.c | 104 -
scripts/faddr2line | 150 +
security/integrity/ima/Kconfig | 14
security/integrity/platform_certs/keyring_handler.h | 8
security/integrity/platform_certs/load_uefi.c | 33
security/landlock/cred.c | 4
security/landlock/cred.h | 8
security/landlock/fs.c | 191 +-
security/landlock/fs.h | 11
security/landlock/limits.h | 8
security/landlock/object.c | 6
security/landlock/object.h | 6
security/landlock/ptrace.c | 10
security/landlock/ruleset.c | 84 -
security/landlock/ruleset.h | 35
security/landlock/syscalls.c | 95 -
sound/core/jack.c | 34
sound/core/pcm_memory.c | 3
sound/pci/hda/patch_realtek.c | 21
sound/soc/amd/yc/acp6x-mach.c | 29
sound/soc/atmel/atmel-classd.c | 1
sound/soc/atmel/atmel-pdmic.c | 1
sound/soc/codecs/Kconfig | 2
sound/soc/codecs/cs35l41-lib.c | 14
sound/soc/codecs/max98090.c | 6
sound/soc/codecs/rk3328_codec.c | 2
sound/soc/codecs/rt5514.c | 2
sound/soc/codecs/rt5645.c | 7
sound/soc/codecs/tscs454.c | 12
sound/soc/codecs/wm2000.c | 6
sound/soc/fsl/imx-hdmi.c | 1
sound/soc/fsl/imx-sgtl5000.c | 14
sound/soc/intel/boards/bytcr_rt5640.c | 12
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5
sound/soc/mxs/mxs-saif.c | 1
sound/soc/samsung/aries_wm8994.c | 2
sound/soc/sh/rcar/core.c | 15
sound/soc/sh/rcar/dma.c | 9
sound/soc/sh/rcar/rsnd.h | 2
sound/soc/sh/rcar/src.c | 7
sound/soc/sh/rcar/ssi.c | 14
sound/soc/sh/rcar/ssiu.c | 11
sound/soc/sh/rz-ssi.c | 22
sound/soc/soc-dapm.c | 2
sound/soc/sof/amd/pci-rn.c | 1
sound/soc/ti/j721e-evm.c | 44
sound/usb/implicit.c | 10
sound/usb/midi.c | 3
sound/usb/quirks.c | 6
sound/usb/usbaudio.h | 6
tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c | 5
tools/lib/bpf/libbpf.c | 22
tools/objtool/check.c | 9
tools/objtool/elf.c | 200 +-
tools/objtool/include/objtool/elf.h | 4
tools/perf/Makefile.config | 39
tools/perf/arch/x86/util/evlist.c | 2
tools/perf/arch/x86/util/evsel.c | 12
tools/perf/builtin-c2c.c | 6
tools/perf/builtin-stat.c | 7
tools/perf/pmu-events/jevents.c | 2
tools/perf/util/data.h | 1
tools/perf/util/evlist.c | 12
tools/perf/util/evsel.c | 19
tools/perf/util/evsel.h | 3
tools/power/x86/turbostat/turbostat.c | 1
tools/testing/kunit/kunit_parser.py | 7
tools/testing/kunit/test_data/test_is_test_passed-no_tests_no_plan.log | 2
tools/testing/selftests/Makefile | 1
tools/testing/selftests/arm64/bti/Makefile | 4
tools/testing/selftests/bpf/Makefile | 12
tools/testing/selftests/bpf/prog_tests/trampoline_count.c | 134 -
tools/testing/selftests/bpf/progs/btf_dump_test_case_syntax.c | 2
tools/testing/selftests/bpf/progs/profiler.inc.h | 5
tools/testing/selftests/bpf/progs/test_trampoline_count.c | 16
tools/testing/selftests/bpf/test_bpftool_synctypes.py | 2
tools/testing/selftests/cgroup/test_stress.sh | 2
tools/testing/selftests/landlock/base_test.c | 177 +-
tools/testing/selftests/landlock/common.h | 66
tools/testing/selftests/landlock/fs_test.c | 753 ++++++----
tools/testing/selftests/landlock/ptrace_test.c | 40
tools/testing/selftests/resctrl/fill_buf.c | 4
tools/tracing/rtla/Makefile | 3
tools/tracing/rtla/README.txt | 12
tools/tracing/rtla/src/utils.c | 2
836 files changed, 8040 insertions(+), 4320 deletions(-)
Abhinav Kumar (1):
drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path
Abhishek Kumar (1):
ath10k: skip ath10k_halt during suspend for driver state RESTARTING
Adam Wujek (1):
hwmon: (pmbus) Check PEC support before reading other registers
Aditya Garg (1):
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Aidan MacDonald (1):
mmc: jz4740: Apply DMA engine limits to maximum segment size
Ajay Singh (1):
wilc1000: fix crash observed in AP mode with cfg80211_register_netdevice()
Akira Yokosawa (1):
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Albert Wang (1):
usb: dwc3: gadget: Move null pinter check to proper place
Alex Deucher (2):
drm/amdgpu/psp: move PSP memory alloc from hw_init to sw_init
drm/amdgpu: add beige goby PCI ID
Alex Elder (3):
net: ipa: ignore endianness if there is no header
net: ipa: fix page free in ipa_endpoint_trans_release()
net: ipa: fix page free in ipa_endpoint_replenish_one()
Alexander Aring (3):
dlm: fix plock invalid read
dlm: fix wake_up() calls for pending remove
dlm: fix missing lkb refcount handling
Alexander Wetzel (1):
rtl818x: Prevent using not initialized queues
Alexandre Ghiti (1):
riscv: Initialize thread pointer before calling C functions
Alexandru Elisei (1):
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Alexey Dobriyan (2):
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
module: fix [e_shstrndx].sh_size=0 OOB access
Alexey Khoroshilov (1):
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
Alice Wong (1):
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Allen-KH Cheng (1):
arm64: dts: mt8192: Fix nor_flash status disable typo
Amadeusz Sławiński (1):
ALSA: jack: Access input_dev under mutex
Amelie Delaunay (2):
dmaengine: stm32-mdma: remove GISR1 register
dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler()
Amir Goldstein (2):
inotify: show inotify mask flags in proc fdinfo
fsnotify: fix wrong lockdep annotations
Ammar Faizi (2):
x86/MCE/AMD: Fix memory leak when threshold_create_bank() fails
x86/delay: Fix the wrong asm constraint in delay_loop()
Andre Przywara (3):
of/fdt: Ignore disabled memory nodes
kselftest/arm64: bti: force static linking
ARM: dts: suniv: F1C100: fix watchdog compatible
Andrea Parri (Microsoft) (1):
Drivers: hv: vmbus: Fix handling of messages with transaction ID of zero
Andreas Gruenbacher (1):
iomap: iomap_write_failed fix
Andrii Nakryiko (3):
libbpf: Don't error out on CO-RE relos for overriden weak subprogs
libbpf: Fix logic for finding matching program for CO-RE relocation
selftests/bpf: Prevent skeleton generation race
Andy Shevchenko (1):
device property: Allow error pointer to be passed to fwnode APIs
AngeloGioacchino Del Regno (1):
PCI: mediatek-gen3: Assert resets to ensure expected init state
Arnd Bergmann (2):
drbd: fix duplicate array initializer
ARM: pxa: maybe fix gpio lookup tables
Avraham Stern (1):
iwlwifi: mei: clear the sap data header before sending
Baochen Qiang (1):
ath11k: Don't check arvif->is_started before sending management frames
Baokun Li (2):
ext4: fix race condition between ext4_write and ext4_convert_inline_data
ext4: fix bug_on in __es_tree_search
Baoquan He (1):
x86/kexec: fix memory leak of elf header buffer
Bart Van Assche (2):
scsi: ufs: qcom: Fix ufs_qcom_resume()
block: Fix the bio.bi_opf comment
Basavaraj Natikar (2):
HID: amd_sfh: Modify the bus name
HID: amd_sfh: Modify the hid name
Bean Huo (1):
mmc: core: Allows to override the timeout value for ioctl() path
Benjamin Gaignard (2):
media: hantro: HEVC: unconditionnaly set pps_{cb/cr}_qp_offset values
media: hantro: HEVC: Fix tile info buffer value computation
Biju Das (1):
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Bjorn Andersson (1):
soc: qcom: llcc: Add MODULE_DEVICE_TABLE()
Bjorn Helgaas (1):
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Björn Ardö (1):
mailbox: forward the hrtimer if not queued and under a lock
Bjørn Mork (1):
mtdblock: warn if opened on NAND
Bob Peterson (1):
gfs2: use i_lock spin_lock for inode qadata
Bodo Stroesser (1):
scsi: target: tcmu: Avoid holding XArray lock when calling lock_page
Borislav Petkov (1):
x86/microcode: Add explicit CPU vendor dependency
Brian Norris (2):
PM / devfreq: rk3399_dmc: Disable edev on remove()
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Bryan O'Donoghue (1):
dt-bindings: soc: qcom: smd-rpm: Fix missing MSM8936 compatible
Caleb Connolly (2):
pinctrl/rockchip: support deferring other gpio params
pinctrl/rockchip: support setting input-enable param
Carl Yin(殷张成) (1):
USB: serial: option: add Quectel BG95 modem
Chaitanya Kulkarni (1):
nvme: set non-mdts limits in nvme_scan_work
Chao Yu (8):
f2fs: fix to do sanity check on inline_dots inode
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
f2fs: fix to clear dirty inode in f2fs_evict_inode()
f2fs: fix deadloop in foreground GC
f2fs: fix to do sanity check on total_data_blocks
f2fs: fix fallocate to use file_modified to update permissions consistently
f2fs: fix to do sanity check for inline inode
Charles Keepax (3):
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
ASoC: atmel-pdmic: Remove endianness flag on pdmic component
ASoC: atmel-classd: Remove endianness flag on class d component
Chen-Tsung Hsieh (1):
mtd: spi-nor: core: Check written SR value in spi_nor_write_16bit_sr_and_check()
Chen-Yu Tsai (2):
drm/mediatek: Fix DPI component detection for MT8192
media: hantro: Empty encoder capture buffers by default
Chengming Zhou (2):
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
sched/psi: report zeroes for CPU full at the system level
Chia-I Wu (2):
drm/msm: simplify gpu_busy callback
drm/msm: return the average load over the polling period
Christian Brauner (2):
fs: add two trivial lookup helpers
exportfs: support idmapped mounts
Christoph Hellwig (3):
target: remove an incorrect unmap zeroes data deduction
virtio_blk: fix the discard_granularity and discard_alignment queue limits
dma-direct: don't fail on highmem CMA pages in dma_direct_alloc_pages
Christophe JAILLET (9):
fs/ntfs3: Fix some memory leaks in an error handling path of 'log_replay()'
media: aspeed: Fix an error handling path in aspeed_video_probe()
mt76: mt7921: Fix the error handling path of mt7921_pci_probe()
hinic: Avoid some over memory allocation
memory: samsung: exynos5422-dmc: Avoid some over memory allocation
drivers/base/memory: fix an unlikely reference counting issue in __add_memory_block()
powerpc/xive: Add some error handling code to 'xive_spapr_init()'
gpio: sim: Use correct order for the parameters of devm_kcalloc()
dmaengine: idxd: Fix the error handling path in idxd_cdev_register()
Christophe Leroy (1):
powerpc/fsl_book3e: Don't set rodata RO too early
Christophe de Dinechin (1):
nodemask.h: fix compilation error with GCC12
Chuanhong Guo (2):
mtd: spinand: gigadevice: fix Quad IO for GD5F1GQ5UExxG
arm: mediatek: select arch timer for mt7629
Colin Ian King (3):
ALSA: pcm: Check for null pointer of pointer substream before dereferencing it
drm/v3d: Fix null pointer dereference of pointer perfmon
selftests/resctrl: Fix null pointer dereference on open failed
Coly Li (4):
bcache: improve multithreaded bch_btree_check()
bcache: improve multithreaded bch_sectors_dirty_init()
bcache: remove incremental dirty sector counting for bch_sectors_dirty_init()
bcache: avoid journal no-space deadlock by reserving 1 journal bucket
Conor Dooley (1):
PCI: microchip: Add missing chained_irq_enter()/exit() calls
Corentin Labbe (3):
crypto: marvell/cesa - ECB does not IV
crypto: sun8i-ss - rework handling of IV
crypto: sun8i-ss - handle zero sized sg
Corey Minyard (3):
ipmi:ssif: Check for NULL msg when handling events and messages
ipmi: Add an intializer for ipmi_smi_msg struct
ipmi: Fix pr_fmt to avoid compilation issues
Cristian Marussi (1):
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Daire McNamara (1):
PCI: microchip: Fix potential race in interrupt handling
Damien Le Moal (1):
block: Fix potential deadlock in blk_ia_range_sysfs_show()
Dan Carpenter (8):
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
scsi: iscsi: Fix harmless double shift bug
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
PCI: cadence: Fix find_first_zero_bit() limit
PCI: rockchip: Fix find_first_zero_bit() limit
OPP: call of_node_put() on error path in _bandwidth_supported()
dlm: uninitialized variable on error in dlm_listen_for_all()
staging: r8188eu: delete rtw_wx_read/write32()
Dan Williams (2):
nvdimm: Fix firmware activation deadlock scenarios
nvdimm: Allow overwrite in the presence of disabled dimms
Daniel Bristot de Oliveira (2):
rtla: Fix __set_sched_attr error message
tracing/timerlat: Notify IRQ new max latency only if stop tracing is set
Daniel Latypov (4):
kunit: bail out of test filtering logic quicker if OOM
kunit: tool: make parser stop overwriting status of suites w/ no_tests
kunit: fix executor OOM error handling logic on non-UML
kunit: fix debugfs code to use enum kunit_status, not bool
Daniel Thompson (1):
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Daniel Vetter (1):
fbcon: Consistently protect deferred_takeover with console_lock()
Dave Airlie (1):
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
David Gow (1):
list: test: Add a test for list_is_head()
David Howells (9):
rxrpc: Return an error to sendmsg if call failed
rxrpc, afs: Fix selection of abort codes
afs: Adjust ACK interpretation to try and cope with NAT
rxrpc: Fix locking issue
rxrpc: Fix listen() setting the bar too high for the prealloc rings
rxrpc: Don't try to resend the request if we're receiving the reply
rxrpc: Fix overlapping ACK accounting
rxrpc: Don't let ack.previousPacket regress
rxrpc: Fix decision on when to generate an IDLE ACK
Denis Efremov (1):
staging: r8188eu: prevent ->Ssid overflow in rtw_wx_set_scan()
Dennis Dalessandro (1):
RDMA/hfi1: Fix potential integer multiplication overflow errors
Deren Wu (1):
mt76: fix antenna config missing in 6G cap
Dimitri John Ledkov (1):
cfg80211: declare MODULE_FIRMWARE for regulatory.db
Dinh Nguyen (1):
dt-bindings: gpio: altera: correct interrupt-cells
Diogo Ivo (2):
arm64: tegra: Add missing DFLL reset on Tegra210
clk: tegra: Add missing reset deassertion
Dmitry Baryshkov (5):
drm/msm: properly add and remove internal bridges
drm/msm/dsi: fix error checks and return values for DSI xmit functions
drm/msm: add missing include to msm_drv.c
drm/msm/dsi: fix address for second DSI PHY on SDM660
drm/msm: don't free the IRQ if it was not requested
Dmitry Monakhov (1):
ext4: mark group as trimmed only if it was fully scanned
Dmitry Torokhov (1):
Input: stmfts - do not leave device disabled in stmfts_input_open
Dong Aisheng (1):
Revert "mm/cma.c: remove redundant cma_mutex lock"
Dongliang Mu (3):
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
rtlwifi: Use pr_warn instead of WARN_ONCE
media: ov7670: remove ov7670_power_off from ov7670_remove
Douglas Miller (2):
RDMA/hfi1: Prevent panic when SDMA is disabled
RDMA/hfi1: Prevent use of lock before it is initialized
Duoming Zhou (1):
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
Dylan Yudaken (1):
io_uring: only wake when the correct events are set
Emmanuel Grumbach (1):
iwlwifi: mvm: fix assert 1F04 upon reconfig
Enzo Matsumiya (2):
cifs: don't call cifs_dfs_query_info_nonascii_quirk() if nodfs was set
cifs: return ENOENT for DFS lookup_cache_entry()
Eric Biggers (4):
ext4: reject the 'commit' option on ext2 filesystems
f2fs: don't use casefolded comparison for "." and ".."
ext4: fix memory leak in parse_apply_sb_mount_options()
ext4: only allow test_dummy_encryption when supported
Eric Dumazet (3):
tcp: consume incoming skb leading to a reset
net: remove two BUG() from skb_checksum_help()
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
Eric W. Biederman (4):
kthread: Don't allocate kthread_struct for init and umh
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Eugen Hristev (2):
media: atmel: atmel-sama5d2-isc: fix wrong mask in YUYV format check
ARM: dts: at91: sama7g5: remove interrupt-parent from gic node
Eugenio Pérez (1):
vdpasim: allow to enable a vq repeatedly
Evan Quan (1):
drm/amd/pm: fix the compile warning
Fabiano Rosas (1):
KVM: PPC: Book3S HV: Fix vcore_blocked tracepoint
Fabien Parent (1):
pinctrl: mediatek: mt8195: enable driver on mtk platforms
Fabio Estevam (1):
net: phy: micrel: Allow probing without .driver_data
Felix Fietkau (6):
mt76: mt7921: accept rx frames with non-standard VHT MCS10-11
mt76: fix encap offload ethernet type check
mt76: do not attempt to reorder received 802.3 packets without agg session
mt76: fix tx status related use-after-free race on station removal
mt76: fix use-after-free by removing a non-RCU wcid pointer
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Finn Thain (1):
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Francesco Dolcini (1):
PCI: imx6: Fix PERST# start-up sequence
GUO Zihua (1):
ima: remove the IMA_TEMPLATE Kconfig option
Gao Xiang (1):
erofs: fix buffer copy overflow of ztailpacking feature
Gautam Menghani (1):
tracing: Initialize integer variable to prevent garbage return value
Gavin Li (1):
net/mlx5: Increase FW pre-init timeout for health recovery
Geert Uytterhoeven (3):
m68k: atari: Make Atari ROM port I/O write macros return void
m68k: math-emu: Fix dependencies of math emulation support
pinctrl: renesas: r8a779a0: Fix GPIO function on I2C-capable pins
Gilad Ben-Yossef (1):
crypto: ccree - use fine grained DMA mapping dir
Giovanni Cabiddu (2):
crypto: qat - set CIPHER capability for DH895XCC
crypto: qat - set COMPRESSION capability for DH895XCC
Greg Kroah-Hartman (2):
module.h: simplify MODULE_IMPORT_NS
Linux 5.17.14
Guenter Roeck (2):
platform/chrome: Re-introduce cros_ec_cmd_xfer and use it for ioctls
MIPS: Loongson: Use hwmon_device_register_with_groups() to register hwmon
Guo Ren (2):
riscv: Fixup difference with defconfig
csky: patch_text: Fixup last cpu should be master
Gustavo A. R. Silva (1):
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
Hangbin Liu (2):
selftests/bpf: Add missed ima_setup.sh in Makefile
bonding: fix missed rcu protection
Hangyu Hua (3):
media: rga: fix possible memory leak in rga_probe
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
misc: ocxl: fix possible double free in ocxl_file_register_afu
Hans Verkuil (2):
media: ccs-core.c: fix failure to call clk_disable_unprepare
media: cec-adap.c: fix is_configuring state
Hans de Goede (1):
ASoC: Intel: bytcr_rt5640: Add quirk for the HP Pro Tablet 408
Hao Jia (1):
sched/core: Avoid obvious double update_rq_clock warning
Haohui Mai (1):
drm/amdgpu/sdma: Fix incorrect calculations of the wptr of the doorbells
Haowen Bai (4):
b43legacy: Fix assigning negative value to unsigned variable
b43: Fix assigning negative value to unsigned variable
ipw2x00: Fix potential NULL dereference in libipw_xmit()
sfc: ef10: Fix assigning negative value to unsigned variable
Haren Myneni (1):
powerpc/powernv/vas: Assign real address to rx_fifo in vas_rx_win_attr
Hari Bathini (2):
powerpc/fadump: Fix fadump to work with a different endian capture kernel
powerpc/fadump: fix PT_LOAD segment for boot memory area
Hari Chandrakanthan (1):
ath11k: disable spectral scan during spectral deinit
Harini Katakam (1):
net: macb: Fix PTP one step sync support
Hector Martin (1):
pinctrl: apple: Use a raw spinlock for the regmap
Heiko Carstens (1):
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Helge Deller (2):
parisc/stifb: Implement fb_is_primary_device()
parisc/stifb: Keep track of hardware path of graphics card
Heming Zhao (1):
md/bitmap: don't set sb values if can't pass sanity check
Heming Zhao via Ocfs2-devel (1):
ocfs2: fix mounting crash if journal is not alloced
Hui Wang (1):
ASoC: cs35l41: Fix an out-of-bounds access in otp_packed_element_t
Hyunchul Lee (1):
ksmbd: fix outstanding credits related bugs
Ian Abbott (1):
spi: cadence-quadspi: fix Direct Access Mode disable for SoCFPGA
Ian Rogers (1):
perf evlist: Keep topdown counters in weak group
Jacky Li (1):
crypto: ccp - Fix the INIT_EX data file open failure
Jacopo Mondi (1):
media: i2c: max9286: Use "maxim,gpio-poc" property
Jaegeuk Kim (1):
f2fs: don't need inode lock for system hidden quota
Jagan Teki (1):
drm/panel: panel-simple: Fix proper bpc for AM-1280800N3TZQW-T00H
Jakob Koschel (1):
f2fs: fix dereference of stale list iterator after loop body
Jakub Kicinski (2):
eth: tg3: silence the GCC 12 array-bounds warning
net: stmmac: fix out-of-bounds access in a selftest
James Clark (1):
perf tools: Use Python devtools for version autodetection rather than runtime
James Smart (5):
scsi: lpfc: Move cfg_log_verbose check before calling lpfc_dmp_dbg()
scsi: lpfc: Fix SCSI I/O completion and abort handler deadlock
scsi: lpfc: Fix call trace observed during I/O with CMF enabled
scsi: lpfc: Fix resource leak in lpfc_sli4_send_seq_to_ulp()
scsi: lpfc: Alter FPIN stat accounting logic
Jan Kara (14):
bfq: Relax waker detection for shared queues
bfq: Allow current waker to defend against a tentative one
bfq: Avoid false marking of bic as stably merged
bfq: Avoid merging queues with different parents
bfq: Split shared queues on move between cgroups
bfq: Update cgroup information before merging bio
bfq: Drop pointless unlock-lock pair
bfq: Remove pointless bfq_init_rq() calls
bfq: Track whether bfq_group is still online
bfq: Get rid of __bio_blkcg() usage
bfq: Make sure bfqg for which we are queueing requests is online
ext4: verify dir block before splitting it
ext4: avoid cycles in directory h-tree
block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
Jan Kiszka (1):
efi: Add missing prototype for efi_capsule_setup_info
Jane Chu (2):
x86/mce: relocate set{clear}_mce_nospec() functions
mce: fix set_mce_nospec to always unmap the whole page
Jani Nikula (2):
drm/edid: fix invalid EDID extension block filtering
drm/i915/dsi: fix VBT send packet port selection for ICL+
Janusz Krzysztofik (1):
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Jason A. Donenfeld (2):
openrisc: start CPU timer early in boot
Revert "random: use static branch for crng_ready()"
Javier Martinez Canillas (2):
efi: Allow to enable EFI runtime services by default on RT
video: fbdev: vesafb: Fix a use-after-free due early fb_info cleanup
Jean-Philippe Brucker (1):
iommu/arm-smmu-v3-sva: Fix mm use-after-free
Jens Axboe (2):
io_uring: cache poll/double-poll state with a request flag
io_uring: fix assuming triggered poll waitqueue is the single poll
Jerome Marchand (1):
samples: bpf: Don't fail for a missing VMLINUX_BTF when VMLINUX_H is provided
Jessica Zhang (3):
drm/msm/dpu: Clean up CRC debug logs
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jia-Ju Bai (1):
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Jia-Wei Chang (1):
cpufreq: mediatek: Use module_init and add module_exit
Jiantao Zhang (1):
PCI: dwc: Fix setting error return on MSI DMA mapping failure
Jiasheng Jiang (1):
drm: mali-dp: potential dereference of null pointer
Jiri Olsa (1):
perf build: Fix btf__load_from_kernel_by_id() feature check
Jiri Slaby (1):
serial: pch: don't overwrite xmit->buf[0] by x_char
Joel Selvaraj (1):
arm64: dts: qcom: sdm845-xiaomi-beryllium: fix typo in panel's vddio-supply property
Joerg Roedel (1):
iommu/amd: Increase timeout waiting for GA log enablement
Johan Hovold (5):
USB: serial: pl2303: fix type detection for odd device
PCI: qcom: Fix runtime PM imbalance on probe errors
PCI: qcom: Fix unbalanced PHY init on probe errors
phy: qcom-qmp: fix struct clk leak on probe errors
phy: qcom-qmp: fix reset-controller leak on probe errors
Johannes Berg (8):
nl80211: show SSID for P2P_GO interfaces
nl80211: don't hold RTNL in color change request
wifi: mac80211: fix use-after-free in chanctx code
iwlwifi: fw: init SAR GEO table only if data is present
iwlwifi: mei: fix potential NULL-ptr deref
um: virtio_uml: Fix broken device handling in time-travel
um: Use asm-generic/dma-mapping.h
um: chan_user: Fix winch_tramp() return value
John Garry (1):
scsi: hisi_sas: Fix rescan after deleting a disk
John Kacur (2):
rtla: Don't overwrite existing directory mode
rtla: Minor grammar fix for rtla README
John Ogness (3):
printk: use atomic updates for klogd work
printk: add missing memory barrier to wake_up_klogd()
printk: wake waiters for safe and NMI contexts
Jon Lin (2):
spi: rockchip: Stop spi slave dma receiver when cs inactive
spi: rockchip: Preset cs-high and clk polarity in setup progress
Jonas Karlman (1):
media: rkvdec: h264: Fix bit depth wrap in pps packet
Jonathan Bakker (1):
ARM: dts: s5pv210: Remove spi-cs-high on panel in Aries
Jonathan Teh (1):
HID: hid-led: fix maximum brightness for Dream Cheeky
Josh Poimboeuf (2):
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
scripts/faddr2line: Fix overlapping text section failures
Julian Schroeder (1):
nfsd: destroy percpu stats counters after reply cache shutdown
Junxiao Bi via Ocfs2-devel (1):
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Kailang Yang (1):
ALSA: hda/realtek - Add new type for ALC245
Kajol Jain (2):
powerpc/perf: Fix the threshold compare group constraint for power10
powerpc/perf: Fix the threshold compare group constraint for power9
Kan Liang (3):
perf/x86/intel: Fix event constraints for ICL
perf parse-events: Support different format of the topdown event name
perf stat: Always keep perf metrics topdown events in a group
Kant Fan (1):
thermal: devfreq_cooling: use local ops instead of global ops
Karthikeyan Kathirvel (1):
ath11k: Change max no of active probe SSID and BSSID to fw capability
Kathiravan T (1):
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Keita Suzuki (2):
drm/amd/pm: fix double free in si_parse_power_table()
tracing: Fix potential double free in create_var_ref()
Keith Busch (1):
nvme: set dma alignment to dword
Kirill A. Shutemov (1):
ACPICA: Avoid cache flush inside virtual machines
Kishon Vijay Abraham I (1):
usb: core: hcd: Add support for deferring roothub registration
Kiwoong Kim (1):
scsi: ufs: core: Exclude UECxx from SFR dump list
Konrad Dybcio (3):
arm64: dts: qcom: msm8994: Fix the cont_splash_mem address
arm64: dts: qcom: msm8994: Fix BLSP[12]_DMA channels count
regulator: qcom_smd: Fix up PM8950 regulator configuration
Konstantin Komarov (7):
fs/ntfs3: Update valid size if -EIOCBQUEUED
fs/ntfs3: Fix fiemap + fix shrink file size (to remove preallocated space)
fs/ntfs3: Keep preallocated only if option prealloc enabled
fs/ntfs3: Check new size for limits
fs/ntfs3: In function ntfs_set_acl_ex do not change inode->i_mode if called from function ntfs_init_acl
fs/ntfs3: Update i_ctime when xattr is added
fs/ntfs3: Restore ntfs_xattr_get_acl and ntfs_xattr_set_acl functions
Kristen Carlson Accardi (1):
x86/sgx: Set active memcg prior to shmem allocation
Krzysztof Kozlowski (8):
ARM: dts: ox820: align interrupt controller node name with dtschema
ARM: dts: socfpga: align interrupt controller node name with dtschema
ARM: dts: s5pv210: align DMA channels with dtschema
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
irqchip/aspeed-scu-ic: Fix irq_of_parse_and_map() return value
ARM: dts: qcom: sdx55: remove wrong unit address from RPMH RSC clocks
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
Kuldeep Singh (1):
spi: qcom-qspi: Add minItems to interconnect-names
Kuninori Morimoto (3):
ASoC: rsnd: care default case on rsnd_ssiu_busif_err_status_clear()
ASoC: rsnd: care return value from rsnd_node_fixed_index()
i2c: rcar: fix PM ref counts in probe error paths
Kuniyuki Iwashima (1):
list: fix a data-race around ep->rdllist
Kuogee Hsieh (5):
drm/msm/dpu: adjust display_v_end for eDP and DP
drm/msm/dp: stop event kernel thread when DP unbind
drm/msm/dp: reset DP controller before transmit phy test pattern
drm/msm/dp: do not stop transmitting phy test pattern during DP phy compliance test
drm/msm/dp: fix event thread stuck in wait_event after kthread_stop()
Kuppuswamy Sathyanarayanan (1):
PCI/AER: Clear MULTI_ERR_COR/UNCOR_RCV bits
Kwanghoon Son (1):
media: exynos4-is: Fix compile warning
Lad Prabhakar (3):
Input: gpio-keys - cancel delayed work only in case of GPIO
ASoC: sh: rz-ssi: Propagate error codes returned from platform_get_irq_byname()
ASoC: sh: rz-ssi: Release the DMA channels in rz_ssi_probe() error path
Lai Jiangshan (1):
x86/sev: Annotate stack change in the #VC handler
Laibin Qiu (1):
blk-throttle: Set BIO_THROTTLED when bio has been throttled
Laurent Dufour (1):
powerpc/rtas: Keep MSR[RI] set when calling RTAS
Laurent Vivier (1):
tty: goldfish: Introduce gf_ioread32()/gf_iowrite32()
Laurentiu Palcu (2):
media: i2c: max9286: fix kernel oops when removing module
media: i2c: rdacm2x: properly set subdev entity function
Len Brown (1):
tools/power turbostat: fix ICX DRAM power numbers
Leo Yan (1):
perf c2c: Use stdio interface if slang is not supported
Li Huafei (1):
tracing: Reset the function filter after completing trampoline/graph selftest
Lin Ma (2):
ASoC: rt5645: Fix errorenous cleanup order
NFC: NULL out the dev->rfkill to prevent UAF
Linus Torvalds (1):
drm: fix EDID struct for old ARM OABI format
Linus Walleij (1):
usb: isp1760: Fix out-of-bounds array access
Liu Zixian (1):
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Liviu Dudau (1):
drm/komeda: return early if drm_universal_plane_init() fails.
Lorenzo Bianconi (1):
mt76: mt7915: do not pass data pointer to mt7915_mcu_muru_debug_set
Luca Ceresoli (1):
spi: rockchip: fix missing error on unsupported SPI_CS_HIGH
Luca Weiss (1):
media: venus: hfi: avoid null dereference in deinit
Lucas Stach (2):
drm/bridge: adv7511: clean up CEC adapter when probe fails
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Luiz Augusto von Dentz (4):
Bluetooth: HCI: Add HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN quirk
Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN for QCA
Bluetooth: hci_sync: Cleanup hci_conn if it cannot be aborted
Bluetooth: hci_conn: Fix hci_connect_le_sync
Lukas Wunner (1):
usbnet: Run unregister_netdev() before unbind() again
Luís Henriques (1):
ceph: fix decoding of client session messages flags
Lv Ruyi (9):
scsi: megaraid: Fix error check return value of register_chrdev()
drm: msm: fix error check return value of irq_of_parse_and_map()
powerpc/xics: fix refcount leak in icp_opal_init()
powerpc/powernv: fix missing of_node_put in uv_init()
ixp4xx_eth: fix error check return value of platform_get_irq()
drm/msm/dp: fix error check return value of irq_of_parse_and_map()
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
drm/msm/dpu: fix error check return value of irq_of_parse_and_map()
Lyude Paul (1):
drm/nouveau/subdev/bus: Ratelimit logging for fault errors
Maciej W. Rozycki (3):
x86/PCI: Fix ALi M1487 (IBC) PIRQ router link value interpretation
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
MIPS: IP30: Remove incorrect `cpu_has_fpu' override
Manivannan Sadhasivam (1):
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Mao Jinlong (1):
coresight: core: Fix coresight device probe failure issue
Marc Kleine-Budde (1):
can: xilinx_can: mark bit timing constants as const
Marco Chiappero (1):
crypto: qat - fix off-by-one error in PFVF debug print
Marco Elver (1):
signal: Deliver SIGTRAP on perf event asynchronously if blocked
Marek Vasut (4):
drm: bridge: icn6211: Fix register layout
drm: bridge: icn6211: Fix HFP_HSW_HBP_HI and HFP_MIN handling
drm/panel: simple: Add missing bus flags for Innolux G070Y2-L01
ARM: dts: stm32: Fix PHY post-reset delay on Avenger96
Mario Limonciello (5):
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
ASoC: amd: Add driver data to acp6x machine driver
PCI/ACPI: Allow D3 only if Root Port can signal and wake from D3
mailbox: pcc: Fix an invalid-load caught by the address sanitizer
iommu/amd: Enable swiotlb in all cases
Marios Levogiannis (1):
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Mark Bloch (1):
net/mlx5: fs, delete the FTE when there are no rules attached to it
Mark Brown (2):
ASoC: dapm: Don't fold register value changes into notifications
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Mark Rutland (4):
arm64: stackleak: fix current_top_of_stack()
irqchip/gic-v3: Ensure pseudo-NMIs have an ISB between ack and handling
irqchip/gic-v3: Refactor ISB + EOIR at ack time
irqchip/gic-v3: Fix priority mask handling
Mathias Nyman (1):
xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI
Matthew Wilcox (Oracle) (1):
alpha: fix alloc_zeroed_user_highpage_movable()
Matthias Schiffer (1):
arm64: dts: ti: k3-am64-mcu: remove incorrect UART base clock rates
Matthieu Baerts (1):
x86/pm: Fix false positive kmemleak report in msr_build_context()
Max Filippov (2):
xtensa: move trace_hardirqs_off call back to entry.S
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Max Krummenacher (1):
ARM: dts: imx6dl-colibri: Fix I2C pinmuxing
Maxime Ripard (5):
drm/vc4: kms: Take old state core clock rate into account
drm/vc4: hvs: Fix frame count register readout
drm/vc4: hvs: Reset muxes at probe time
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Mel Gorman (1):
mm/page_alloc: always attempt to allocate at least one page during bulk allocation
Miaohe Lin (2):
drivers/base/node.c: fix compaction sysfs file leak
mm/memremap: fix missing call to untrack_pfn() in pagemap_range()
Miaoqian Lin (25):
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
HID: elan: Fix potential double free in elan_input_configured
drm/bridge: Fix error handling in analogix_dp_probe
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
ASoC: imx-hdmi: Fix refcount leak in imx_hdmi_probe
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
ASoC: samsung: Fix refcount leak in aries_audio_probe
media: exynos4-is: Fix PM disable depth imbalance in fimc_is_probe
media: st-delta: Fix PM disable depth imbalance in delta_probe
media: atmel: atmel-isc: Fix PM disable depth imbalance in atmel_isc_probe
media: exynos4-is: Change clk_disable to clk_disable_unprepare
ASoC: ti: j721e-evm: Fix refcount leak in j721e_soc_probe_*
regulator: scmi: Fix refcount leak in scmi_regulator_probe
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
thermal/drivers/imx_sc_thermal: Fix refcount leak in imx_sc_thermal_probe
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
PCI: mediatek: Fix refcount leak in mtk_pcie_subsys_powerup()
Input: sparcspkr - fix refcount leak in bbc_beep_probe
powerpc/xive: Fix refcount leak in xive_spapr_init
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
Michael Ellerman (1):
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
Michael Niewöhner (1):
platform/x86: intel-hid: fix _DSM function index handling
Michael Rodin (1):
media: vsp1: Fix offset calculation for plane cropping
Michael Walle (1):
i2c: at91: use dma safe buffers
Mickaël Salaün (21):
landlock: Add clang-format exceptions
landlock: Format with clang-format
selftests/landlock: Add clang-format exceptions
selftests/landlock: Normalize array assignment
selftests/landlock: Format with clang-format
samples/landlock: Add clang-format exceptions
samples/landlock: Format with clang-format
landlock: Fix landlock_add_rule(2) documentation
selftests/landlock: Make tests build with old libc
selftests/landlock: Extend tests for minimal valid attribute size
selftests/landlock: Add tests for unknown access rights
selftests/landlock: Extend access right tests to directories
selftests/landlock: Fully test file rename with "remove" access
selftests/landlock: Add tests for O_PATH
landlock: Change landlock_add_rule(2) argument check ordering
landlock: Change landlock_restrict_self(2) check ordering
selftests/landlock: Test landlock_create_ruleset(2) argument check ordering
landlock: Define access_mask_t to enforce a consistent access mask size
landlock: Reduce the maximum number of layers to 16
landlock: Create find_rule() from unmask_layers()
landlock: Fix same-layer rule unions
Mika Westerberg (1):
PCI/ASPM: Make Intel DG2 L1 acceptable latency unlimited
Mike Kravetz (1):
hugetlb: fix huge_pmd_unshare address update
Mike Travis (1):
x86/platform/uv: Update TSC sync state for UV5
Mikulas Patocka (2):
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
objtool: Fix objtool regression on x32 systems
Miles Chen (2):
drm/mediatek: Fix mtk_cec_mask()
iommu/mediatek: Fix NULL pointer dereference when printing dev_name
Mina Almasry (1):
hugetlbfs: fix hugetlbfs_statfs() locking
Minghao Chi (1):
scsi: ufs: Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
Monish Kumar R (1):
USB: new quirk for Dell Gen 2 devices
Moshe Tal (1):
net/mlx5e: Correct the calculation of max channels for rep
Muchun Song (1):
dax: fix cache flush on PMD-mapped pages
Namjae Jeon (1):
fs/ntfs3: Fix invalid free in log_replay
Naohiro Aota (4):
btrfs: zoned: properly finish block group on metadata write
btrfs: zoned: zone finish unused block group
btrfs: zoned: finish block group when there are no more allocatable bytes left
btrfs: zoned: fix comparison of alloc_offset vs meta_write_pointer
Nathan Chancellor (3):
riscv: Move alternative length validation into subsection
drm/i915: Fix CFI violation with show_dynamic_id()
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Naveen N. Rao (1):
kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
Nicholas Piggin (1):
KVM: PPC: Book3S HV Nested: L2 LPCR should inherit L1 LPES setting
Nico Boehr (1):
s390/perf: obtain sie_block from the right address
Nicolas Belin (1):
drm: bridge: it66121: Fix the register page length
Nicolas Dufresne (4):
media: hantro: Stop using H.264 parameter pic_num
media: rkvdec: h264: Fix dpb_valid implementation
media: coda: Fix reported H264 profile
media: coda: Add more H264 levels for CODA960
Nicolas Frattaroli (1):
ASoC: rk3328: fix disabling mclk on pclk probe failure
Niels Dossche (7):
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
ipv6: fix locking issues with loops over idev->addr_list
IB/rdmavt: add missing locks in rvt_ruc_loopback
ath11k: acquire ab->base_lock in unassign when finding the peer by addr
Bluetooth: use hdev lock in activate_scan for hci_is_adv_monitoring
Bluetooth: use hdev lock for accept_list and reject_list in conn req
Bluetooth: protect le accept and resolv lists with hdev->lock
Nikita Yushchenko (1):
drm/bridge_connector: enable HPD by default if supported
Niklas Cassel (1):
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
Nikolay Borisov (1):
selftests/bpf: Fix vfs_link kprobe definition
Noralf Trønnes (1):
dt-bindings: display: sitronix, st7735r: Fix backlight in example
Nuno Sá (1):
of: overlay: do not break notify on NOTIFY_{OK|STOP}
Nícolas F. R. A. Prado (3):
regulator: mt6315: Enforce regulator-compatible, not name
drm/bridge: anx7625: Use uint8 for lane-swing arrays
drm/mediatek: dpi: Use mt8183 output formats for mt8192
OGAWA Hirofumi (1):
fat: add ratelimit to fat*_ent_bread()
Ojaswin Mujoo (1):
ext4: fix journal_ioprio mount option handling
Olga Kornievskaia (1):
NFSv4.1 mark qualified async operations as MOVEABLE tasks
Omar Sandoval (1):
btrfs: fix anon_dev leak in create_subvol()
Padmanabha Srinivasaiah (1):
rcu-tasks: Fix race in schedule and flush work
Pali Rohár (1):
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Palmer Dabbelt (1):
RISC-V: Fix the XIP build
Paolo Abeni (3):
mptcp: optimize release_cb for the common case
mptcp: reset the packet scheduler on incoming MP_PRIO
mptcp: reset the packet scheduler on PRIO change
Parshuram Thombare (1):
PCI: cadence: Clear FLR in device capabilities register
Patrice Chotard (1):
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Paul E. McKenney (3):
rcu-tasks: Handle sparse cpu_possible_mask in rcu_tasks_invoke_cbs()
rcu: Make TASKS_RUDE_RCU select IRQ_WORK
scftorture: Fix distribution of short handler delays
Paulo Alcantara (1):
cifs: fix ntlmssp on old servers
Pavel Begunkov (1):
io_uring: avoid io-wq -EAGAIN looping for !IOPOLL
Pavel Skripkin (1):
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Peng Wu (3):
ARM: versatile: Add missing of_node_put in dcscb_init
ARM: hisi: Add missing of_node_put after of_find_compatible_node
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Peter Chiu (1):
mt76: mt7915: fix twt table_mask to u16 in mt7915_dev
Peter Seiderer (1):
mac80211: minstrel_ht: fix where rate stats are stored (fixes debugfs output)
Peter Zijlstra (1):
objtool: Fix symbol creation
Petr Machata (2):
mlxsw: spectrum_dcb: Do not warn about priority changes
mlxsw: Treat LLDP packets as control
Phil Auld (1):
kselftest/cgroup: fix test_stress.sh to use OUTPUT dir
Phil Elwell (3):
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Philipp Zabel (1):
media: coda: limit frame interval enumeration to supported encoder frame sizes
Pierre Gondois (2):
ACPI: CPPC: Assume no transition latency if no PCCT
PM: EM: Decrement policy counter
Pierre-Louis Bossart (2):
ASoC: max98357a: remove dependency on GPIOLIB
ASoC: rt1015p: remove dependency on GPIOLIB
Ping-Ke Shih (1):
rtw89: cfo: check mac_id to avoid out-of-bounds
Po-Hao Huang (2):
rtw88: fix incorrect frequency reported
rtw88: 8821c: fix debugfs rssi value
Puyou Lu (1):
lib/string_helpers: fix not adding strarray to device's resource list
Qi Zheng (1):
tty: fix deadlock caused by calling printk() under tty_port->lock
QintaoShen (2):
soc: ti: ti_sci_pm_domains: Check for null return of devm_kcalloc
soc: bcm: Check for NULL return of devm_kzalloc()
Qu Wenruo (4):
btrfs: add "0x" prefix for unsupported optional features
btrfs: return correct error number for __extent_writepage_io()
btrfs: repair super block num_devices automatically
btrfs: fix the error handling for submit_extent_page() for btrfs_do_readpage()
Quentin Monnet (1):
selftests/bpf: Fix parsing of prog types in UAPI hdr for bpftool sync
Rafał Miłecki (1):
ARM: dts: BCM5301X: Update pin controller node name
Randy Dunlap (7):
x86: Fix return value of __setup handlers
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
net: dsa: restrict SMSC_LAN9303_I2C kconfig
powerpc/8xx: export 'cpm_setbrg' for modules
powerpc/idle: Fix return value of __setup() handler
powerpc/4xx/cpm: Fix return value of __setup() handler
macintosh: via-pmu and via-cuda need RTC_LIB
Ravi Bangoria (2):
perf/amd/ibs: Cascade pmu init functions' return value
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Rei Yamamoto (1):
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Rex-BC Chen (2):
drm/mediatek: Add vblank register/unregister callback functions
cpufreq: mediatek: Unregister platform device on exit
Rik van der Kemp (1):
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9520 laptop
Robert Marko (2):
arm64: dts: marvell: espressobin-ultra: fix SPI-NOR config
arm64: dts: marvell: espressobin-ultra: enable front USB3 port
Robin Murphy (1):
dma-direct: don't over-decrypt memory
Ronnie Sahlberg (2):
cifs: fix potential double free during failed mount
cifs: when extending a file with falloc we should make files not-sparse
Runqing Yang (1):
libbpf: Fix a bug with checking bpf_probe_read_kernel() support in old kernels
Russell Currey (2):
powerpc/powernv: Get L1D flush requirements from device-tree
powerpc/powernv: Get STF barrier requirements from device-tree
Russell King (Oracle) (1):
net: dsa: mt7530: 1G can also support 1000BASE-X link mode
Saaem Rizvi (1):
drm/amd/display: Disabling Z10 on DCN31
Sakari Ailus (2):
media: Revert "media: dw9768: activate runtime PM and turn off device"
ACPI: property: Release subnode properties with data nodes
Samuel Holland (1):
riscv: Fix irq_work when SMP is disabled
Sathishkumar S (2):
drm/amd/pm: update smartshift powerboost calc for smu12
drm/amd/pm: update smartshift powerboost calc for smu13
Schspa Shi (1):
cpufreq: Fix possible race in cpufreq online error path
Sean Christopherson (3):
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
KVM: nVMX: Clear IDT vectoring on nested VM-Exit for double/triple fault
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
Sean Wang (2):
mt76: mt7921: fix kernel crash at mt7921_pci_remove
Bluetooth: btmtksdio: fix use-after-free at btmtksdio_recv_event
Sebastian Andrzej Siewior (1):
crypto: cryptd - Protect per-CPU resource by disabling BH.
Shawn Lin (1):
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
Shyam Prasad N (1):
cifs: do not use tcpStatus after negotiate completes
Smith, Kyle Miller (Nimble Kernel) (1):
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Song Liu (1):
ftrace: Clean up hash direct_functions on register failures
Stefan Wahren (4):
thermal/drivers/bcm2711: Don't clamp temperature at zero
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
gpiolib: of: Introduce hook for missing gpio-ranges
pinctrl: bcm2835: implement hook for missing gpio-ranges
Steve French (2):
smb3: check for null tcon
SMB3: EBADF/EIO errors in rename/open caused by race condition in smb2_compound_op
Steven Price (1):
drm/plane: Move range check for format_count earlier
Sudeep Holla (2):
firmware: arm_ffa: Fix uuid parameter to ffa_partition_probe
firmware: arm_ffa: Remove incorrect assignment of driver_data
Sven Schnelle (1):
s390/stp: clock_delta should be signed
Taehee Yoo (2):
amt: fix gateway mode stuck
amt: fix memory leak for advertisement message
Takashi Iwai (3):
ALSA: usb-audio: Cancel pending work at closing a MIDI substream
ALSA: usb-audio: Add quirk bits for enabling/disabling generic implicit fb
ALSA: usb-audio: Move generic implicit fb quirk entries into quirks.c
Tali Perry (2):
i2c: npcm: Fix timeout calculation
i2c: npcm: Handle spurious interrupts
Tejas Upadhyay (1):
iommu/vt-d: Add RPLS to quirk list to skip TE disabling
Tejun Heo (1):
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Tetsuo Handa (1):
media: imon: reorganize serialization
Theodore Ts'o (1):
ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state
Thibaut VARÈNE (1):
ath9k: fix QCA9561 PA bias level
Thierry Reding (1):
drm/tegra: gem: Do not try to dereference ERR_PTR()
Thorsten Scherer (1):
ARM: dts: ci4x10: Adapt to changes in imx6qdl.dtsi regarding fec clocks
Tiezhu Yang (1):
MIPS: RALINK: Define pci_remap_iospace under CONFIG_PCI_DRIVERS_GENERIC
Tobias Klauser (1):
riscv: Wire up memfd_secret in UAPI header
Tokunori Ikegami (2):
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Tong Tiangen (1):
arm64: fix types in copy_highpage()
Tony Lindgren (1):
tty: n_gsm: Fix packet data hex dump output
Trond Myklebust (8):
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
NFS: fsync() should report filesystem errors over EINTR/ERESTARTSYS
NFS: Don't report ENOSPC write errors twice
NFS: Do not report flush errors in nfs_write_end()
NFS: Don't report errors from nfs_pageio_complete() more than once
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
NFS: Further fixes to the writeback error handling
NFS: Convert GFP_NOFS to GFP_KERNEL
Tyler Hicks (1):
EDAC/dmc520: Don't print an error for each unconfigured interrupt line
Tyrone Ting (1):
i2c: npcm: Correct register access width
Tzung-Bi Shih (1):
platform/chrome: cros_ec: fix error handling in cros_ec_register()
Ulf Hansson (2):
cpuidle: PSCI: Improve support for suspend-to-RAM for PSCI OSI mode
PM: domains: Fix initialization of genpd's next_wakeup
Uwe Kleine-König (1):
char: tpm: cr50_i2c: Suppress duplicated error message in .remove()
Vasily Averin (2):
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
fanotify: fix incorrect fmode_t casts
Vignesh Raghavendra (1):
drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit
Vijaya Krishna Nivarthi (1):
arm64: dts: qcom: sc7280-idp: Configure CTS pin to bias-bus-hold for bluetooth
Vikash Garodia (1):
media: venus: do not queue internal buffers from previous sequence
Vincent Mailhol (1):
can: mcp251xfd: silence clang's -Wunaligned-access warning
Vincent Whitchurch (1):
um: Fix out-of-bounds read in LDT setup
Vinod Koul (1):
arm64: dts: qcom: qrb5165-rb5: Fix can-clock node name
Vinod Polimera (2):
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
drm/msm/disp/dpu1: avoid clearing hw interrupts if hw_intr is null during drm uninit
Viresh Kumar (2):
cpufreq: Avoid unnecessary frequency updates due to mismatch
Revert "cpufreq: Fix possible race in cpufreq online error path"
Vladis Dronov (2):
hwrng: cn10k - Optimize cn10k_rng_read()
hwrng: cn10k - Make check_rng_health() return an error code
Waiman Long (2):
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
kseltest/cgroup: Make test_stress.sh work if run interactively
Wan Jiabing (1):
drm/omap: fix NULL but dereferenced coccicheck error
Wanpeng Li (1):
KVM: LAPIC: Drop pending LAPIC timer injection when canceling the timer
Wei Yongjun (1):
regulator: da9121: Fix uninit-value in da9121_assign_chip_model()
Wen Gong (2):
ath11k: fix the warning of dev_wake in mhi_pm_disable_transition()
ath11k: fix warning of not found station for bssid in message
Wenli Looi (1):
ath9k: fix ar9003_get_eepmisc
Wonhyuk Yang (1):
tracing: Fix return value of trace_pid_write()
Xiang Chen (1):
scsi: hisi_sas: Undo RPM resume for failed notify phy event for v3 HW
Xianting Tian (1):
RISC-V: Mark IORESOURCE_EXCLUSIVE for reserved mem instead of IORESOURCE_BUSY
Xiao Ni (2):
md: Don't set mddev private to NULL in raid0 pers->free
md: fix double free of io_acct_set bioset
Xiao Yang (1):
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Xiaoguang Wang (1):
scsi: target: tcmu: Fix possible data corruption
Xiaomeng Tong (11):
media: uvcvideo: Fix missing check to determine if element is found in list
scsi: dc395x: Fix a missing check on list iterator
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator
md: fix an incorrect NULL check in does_sb_need_changing
md: fix an incorrect NULL check in md_reload_sb
iommu/msm: Fix an incorrect NULL check on list iterator
carl9170: tx: fix an incorrect use of list iterator
stm: ltdc: fix two incorrect NULL checks on list iterator
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
gma500: fix an incorrect NULL check on list iterator
Xie Yongji (1):
nbd: Fix hung on disconnect request if socket is closed before
Yang Jihong (1):
perf tools: Add missing headers needed by util/data.h
Yang Yingliang (12):
pinctrl: renesas: rzn1: Fix possible null-ptr-deref in sh_pfc_map_resources()
mtd: rawnand: cadence: fix possible null-ptr-deref in cadence_nand_dt_probe()
mtd: rawnand: intel: fix possible null-ptr-deref in ebu_nand_probe()
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
spi: spi-fsl-qspi: check return value after calling platform_get_resource_byname()
media: i2c: ov5648: fix wrong pointer passed to IS_ERR() and PTR_ERR()
thermal/core: Fix memory leak in __thermal_cooling_device_register()
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
pinctrl: renesas: core: Fix possible null-ptr-deref in sh_pfc_map_resources()
hwrng: omap3-rom - fix using wrong clk_disable() in omap_rom_rng_runtime_resume()
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
Yangyang Li (1):
RDMA/hns: Add the detection for CMDQ status in the device initialization process
Ye Bin (3):
ext4: fix use-after-free in ext4_rename_dir_prepare
ext4: fix warning in ext4_handle_inode_extension
ext4: fix bug_on in ext4_writepages
Yi Yang (1):
xtensa/simdisk: fix proc_read_simdisk()
Yicong Yang (1):
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Ying Hsu (1):
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Yixing Liu (1):
RDMA/hns: Remove the num_cqc_timer variable
Yong Wu (4):
iommu/mediatek: Fix 2 HW sharing pgtable issue
iommu/mediatek: Add list_del in mtk_iommu_remove
iommu/mediatek: Remove clk_disable in mtk_iommu_remove
iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
Yonghong Song (1):
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Yongzhi Liu (1):
hv_netvsc: Fix potential dereference of NULL pointer
Yuanchu Xie (1):
selftests/damon: add damon to selftests root Makefile
Yunfei Dong (1):
media: mediatek: vcodec: Fix v4l2 compliance decoder cmd test fail
Yunfei Wang (1):
iommu/dma: Fix iova map result check bug
Yuntao Wang (1):
selftests/bpf: Add missing trampoline program type to trampoline_count test
Zack Rusin (2):
drm/vmwgfx: validate the screen formats
drm/vmwgfx: Fix an invalid read
Zev Weiss (1):
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Zhen Lei (1):
of: Support more than one crash kernel regions for kexec -s
Zheng Bin (2):
ASoC: SOF: amd: add missing platform_device_unregister in acp_pci_rn_probe
net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init
Zheng Yongjun (2):
spi: img-spfi: Fix pm_runtime_get_sync() error checking
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
Zhengjun Xing (2):
perf jevents: Fix event syntax error caused by ExtSel
perf evlist: Extend arch_evsel__must_be_in_group to support hybrid systems
Zheyu Ma (3):
media: pci: cx23885: Fix the error handling in cx23885_initdev()
media: cx25821: Fix the warning when removing the module
mtd: rawnand: denali: Use managed device resources
Zhihao Cheng (1):
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
Zhou Qingyang (1):
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Zijun Hu (1):
Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ERR_DATA_REPORTING for QCA
Zixuan Fu (1):
fs: jfs: fix possible NULL pointer dereference in dbFree()
jianghaoran (1):
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
liuyacan (3):
net/smc: postpone sk_refcnt increment in connect()
net/smc: fix listen processing for SMC-Rv2
Revert "net/smc: fix listen processing for SMC-Rv2"
^ permalink raw reply [relevance 1%]
* Linux 5.15.46
@ 2022-06-09 8:39 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-09 8:39 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.15.46 kernel.
All users of the 5.15 kernel series must upgrade.
The updated 5.15.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.15.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/accounting/psi.rst | 9
Documentation/conf.py | 2
Documentation/devicetree/bindings/display/sitronix,st7735r.yaml | 1
Documentation/devicetree/bindings/gpio/gpio-altera.txt | 5
Documentation/devicetree/bindings/regulator/mt6315-regulator.yaml | 2
Documentation/devicetree/bindings/spi/qcom,spi-qcom-qspi.yaml | 1
Documentation/filesystems/f2fs.rst | 1
Documentation/sound/alsa-configuration.rst | 4
Documentation/userspace-api/landlock.rst | 4
Makefile | 2
arch/alpha/include/asm/page.h | 2
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4
arch/arm/boot/dts/bcm5301x.dtsi | 15
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 6
arch/arm/boot/dts/imx6qdl-colibri.dtsi | 6
arch/arm/boot/dts/ox820.dtsi | 2
arch/arm/boot/dts/s5pv210-aries.dtsi | 3
arch/arm/boot/dts/s5pv210.dtsi | 12
arch/arm/boot/dts/sama7g5.dtsi | 1
arch/arm/boot/dts/socfpga.dtsi | 2
arch/arm/boot/dts/socfpga_arria10.dtsi | 2
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 1
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4
arch/arm/kernel/signal.c | 1
arch/arm/mach-hisi/platsmp.c | 4
arch/arm/mach-mediatek/Kconfig | 1
arch/arm/mach-omap1/clock.c | 2
arch/arm/mach-pxa/cm-x300.c | 8
arch/arm/mach-pxa/magician.c | 2
arch/arm/mach-pxa/tosa.c | 4
arch/arm/mach-vexpress/dcscb.c | 1
arch/arm64/Kconfig.platforms | 1
arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts | 5
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 2
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 5
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2
arch/arm64/boot/dts/qcom/msm8994.dtsi | 8
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 2
arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium.dts | 2
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2
arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi | 2
arch/arm64/include/asm/processor.h | 10
arch/arm64/kernel/signal.c | 1
arch/arm64/kernel/signal32.c | 1
arch/arm64/kernel/sys_compat.c | 2
arch/arm64/mm/copypage.c | 4
arch/csky/kernel/probes/kprobes.c | 2
arch/m68k/Kconfig.cpu | 2
arch/m68k/include/asm/raw_io.h | 6
arch/m68k/kernel/signal.c | 1
arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h | 1
arch/mips/include/asm/mach-ip30/cpu-feature-overrides.h | 1
arch/openrisc/include/asm/timex.h | 1
arch/openrisc/kernel/head.S | 9
arch/parisc/include/asm/fb.h | 4
arch/powerpc/include/asm/page.h | 7
arch/powerpc/include/asm/vas.h | 2
arch/powerpc/kernel/entry_64.S | 24
arch/powerpc/kernel/fadump.c | 8
arch/powerpc/kernel/idle.c | 2
arch/powerpc/kernel/rtas.c | 9
arch/powerpc/kvm/book3s_hv.c | 4
arch/powerpc/kvm/book3s_hv_nested.c | 3
arch/powerpc/perf/isa207-common.c | 12
arch/powerpc/platforms/4xx/cpm.c | 2
arch/powerpc/platforms/8xx/cpm1.c | 1
arch/powerpc/platforms/powernv/opal-fadump.c | 94 -
arch/powerpc/platforms/powernv/opal-fadump.h | 10
arch/powerpc/platforms/powernv/ultravisor.c | 1
arch/powerpc/platforms/powernv/vas-fault.c | 2
arch/powerpc/platforms/powernv/vas-window.c | 4
arch/powerpc/platforms/powernv/vas.h | 2
arch/powerpc/sysdev/dart_iommu.c | 6
arch/powerpc/sysdev/fsl_rio.c | 2
arch/powerpc/sysdev/xics/icp-opal.c | 1
arch/powerpc/sysdev/xive/spapr.c | 43
arch/riscv/include/asm/alternative-macros.h | 4
arch/riscv/include/asm/irq_work.h | 2
arch/riscv/include/asm/unistd.h | 1
arch/riscv/include/uapi/asm/unistd.h | 1
arch/riscv/kernel/head.S | 1
arch/riscv/kernel/setup.c | 4
arch/s390/include/asm/cio.h | 2
arch/s390/include/asm/kexec.h | 10
arch/s390/include/asm/preempt.h | 15
arch/s390/kernel/perf_event.c | 2
arch/s390/kernel/time.c | 8
arch/sparc/kernel/signal32.c | 1
arch/sparc/kernel/signal_64.c | 1
arch/um/drivers/chan_user.c | 9
arch/um/include/asm/Kbuild | 1
arch/um/include/asm/thread_info.h | 2
arch/um/kernel/exec.c | 2
arch/um/kernel/process.c | 2
arch/um/kernel/ptrace.c | 8
arch/um/kernel/signal.c | 4
arch/x86/Kconfig | 4
arch/x86/entry/entry_64.S | 1
arch/x86/entry/vdso/vma.c | 2
arch/x86/events/amd/ibs.c | 55
arch/x86/events/intel/core.c | 2
arch/x86/include/asm/acenv.h | 14
arch/x86/include/asm/kexec.h | 8
arch/x86/include/asm/suspend_32.h | 2
arch/x86/include/asm/suspend_64.h | 12
arch/x86/kernel/apic/apic.c | 2
arch/x86/kernel/apic/x2apic_uv_x.c | 8
arch/x86/kernel/cpu/intel.c | 2
arch/x86/kernel/cpu/mce/amd.c | 32
arch/x86/kernel/cpu/sgx/encl.c | 105 +
arch/x86/kernel/cpu/sgx/encl.h | 7
arch/x86/kernel/cpu/sgx/main.c | 9
arch/x86/kernel/machine_kexec_64.c | 12
arch/x86/kernel/signal_compat.c | 2
arch/x86/kernel/step.c | 3
arch/x86/kernel/sys_x86_64.c | 7
arch/x86/kvm/lapic.c | 1
arch/x86/kvm/vmx/nested.c | 45
arch/x86/kvm/vmx/vmcs.h | 5
arch/x86/lib/delay.c | 4
arch/x86/mm/pat/memtype.c | 2
arch/x86/pci/irq.c | 19
arch/x86/um/ldt.c | 6
arch/xtensa/kernel/ptrace.c | 4
arch/xtensa/kernel/signal.c | 4
arch/xtensa/platforms/iss/simdisk.c | 18
block/bfq-cgroup.c | 111 -
block/bfq-iosched.c | 64
block/bfq-iosched.h | 7
block/blk-cgroup.c | 8
block/blk-iolatency.c | 122 -
crypto/cryptd.c | 23
drivers/acpi/cppc_acpi.c | 17
drivers/acpi/property.c | 18
drivers/acpi/sleep.c | 12
drivers/base/memory.c | 5
drivers/base/node.c | 1
drivers/base/power/domain.c | 1
drivers/base/property.c | 90 -
drivers/block/drbd/drbd_main.c | 11
drivers/block/nbd.c | 13
drivers/block/virtio_blk.c | 7
drivers/char/hw_random/omap3-rom-rng.c | 2
drivers/char/ipmi/ipmi_msghandler.c | 4
drivers/char/ipmi/ipmi_ssif.c | 23
drivers/char/random.c | 12
drivers/char/tpm/tpm_tis_i2c_cr50.c | 4
drivers/clk/tegra/clk-dfll.c | 12
drivers/cpufreq/cpufreq.c | 11
drivers/cpufreq/mediatek-cpufreq.c | 18
drivers/cpuidle/cpuidle-psci.c | 46
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c | 115 +
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 30
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c | 10
drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 14
drivers/crypto/ccree/cc_buffer_mgr.c | 27
drivers/crypto/marvell/cesa/cipher.c | 1
drivers/crypto/nx/nx-common-powernv.c | 2
drivers/crypto/qat/qat_common/adf_gen2_hw_data.c | 18
drivers/crypto/qat/qat_common/adf_gen2_hw_data.h | 1
drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 15
drivers/devfreq/rk3399_dmc.c | 2
drivers/dma/idxd/cdev.c | 8
drivers/dma/stm32-mdma.c | 23
drivers/edac/dmc520_edac.c | 2
drivers/firmware/arm_ffa/driver.c | 4
drivers/firmware/arm_scmi/base.c | 2
drivers/gpio/gpio-rockchip.c | 24
drivers/gpio/gpiolib-of.c | 5
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 95 -
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 8
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 8
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 1
drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 14
drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 8
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 60
drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 62
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10
drivers/gpu/drm/arm/malidp_crtc.c | 5
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31
drivers/gpu/drm/bridge/chipone-icn6211.c | 155 +-
drivers/gpu/drm/bridge/ite-it66121.c | 2
drivers/gpu/drm/drm_bridge_connector.c | 4
drivers/gpu/drm/drm_edid.c | 6
drivers/gpu/drm/drm_plane.c | 14
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6
drivers/gpu/drm/gma500/psb_intel_display.c | 7
drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 33
drivers/gpu/drm/i915/i915_perf.c | 4
drivers/gpu/drm/i915/i915_perf_types.h | 2
drivers/gpu/drm/mediatek/mtk_cec.c | 2
drivers/gpu/drm/mediatek/mtk_dpi.c | 4
drivers/gpu/drm/msm/Makefile | 2
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 1
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 23
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 1
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20
drivers/gpu/drm/msm/dp/dp_ctrl.c | 16
drivers/gpu/drm/msm/dp/dp_display.c | 55
drivers/gpu/drm/msm/dsi/dsi_host.c | 21
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 2
drivers/gpu/drm/msm/hdmi/hdmi.c | 22
drivers/gpu/drm/msm/hdmi/hdmi.h | 19
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 81 -
drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 451 -----
drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 323 ++++
drivers/gpu/drm/msm/msm_drv.c | 8
drivers/gpu/drm/msm/msm_gem_prime.c | 2
drivers/gpu/drm/msm/msm_kms.h | 1
drivers/gpu/drm/nouveau/dispnv50/atom.h | 6
drivers/gpu/drm/nouveau/dispnv50/crc.c | 27
drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 2
drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c | 14
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c | 6
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c | 6
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6
drivers/gpu/drm/panel/panel-simple.c | 3
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2
drivers/gpu/drm/stm/ltdc.c | 16
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8
drivers/gpu/drm/v3d/v3d_perfmon.c | 3
drivers/gpu/drm/vc4/vc4_crtc.c | 2
drivers/gpu/drm/vc4/vc4_drv.h | 1
drivers/gpu/drm/vc4/vc4_hvs.c | 49
drivers/gpu/drm/vc4/vc4_regs.h | 12
drivers/gpu/drm/vc4/vc4_txp.c | 8
drivers/gpu/drm/virtio/virtgpu_display.c | 2
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 30
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 14
drivers/hid/amd-sfh-hid/amd_sfh_hid.c | 4
drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2
drivers/hid/hid-bigbenff.c | 6
drivers/hid/hid-elan.c | 2
drivers/hid/hid-led.c | 2
drivers/hv/channel.c | 6
drivers/hwmon/pmbus/pmbus_core.c | 28
drivers/hwtracing/coresight/coresight-core.c | 33
drivers/i2c/busses/i2c-at91-master.c | 11
drivers/i2c/busses/i2c-npcm7xx.c | 103 -
drivers/i2c/busses/i2c-rcar.c | 15
drivers/infiniband/hw/hfi1/file_ops.c | 2
drivers/infiniband/hw/hfi1/init.c | 2
drivers/infiniband/hw/hfi1/sdma.c | 12
drivers/infiniband/hw/hns/hns_roce_device.h | 7
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 24
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2
drivers/infiniband/hw/hns/hns_roce_main.c | 2
drivers/infiniband/sw/rdmavt/qp.c | 6
drivers/infiniband/sw/rxe/rxe_req.c | 2
drivers/input/keyboard/gpio_keys.c | 2
drivers/input/misc/sparcspkr.c | 1
drivers/input/touchscreen/stmfts.c | 16
drivers/interconnect/qcom/icc-rpmh.c | 10
drivers/interconnect/qcom/sc7180.c | 21
drivers/interconnect/qcom/sm8150.c | 1
drivers/interconnect/qcom/sm8250.c | 1
drivers/interconnect/qcom/sm8350.c | 1
drivers/iommu/amd/init.c | 2
drivers/iommu/amd/iommu.c | 7
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 13
drivers/iommu/dma-iommu.c | 7
drivers/iommu/intel/iommu.c | 2
drivers/iommu/msm_iommu.c | 11
drivers/iommu/mtk_iommu.c | 30
drivers/iommu/mtk_iommu.h | 2
drivers/iommu/mtk_iommu_v1.c | 7
drivers/irqchip/irq-armada-370-xp.c | 11
drivers/irqchip/irq-aspeed-i2c-ic.c | 4
drivers/irqchip/irq-aspeed-scu-ic.c | 4
drivers/irqchip/irq-sni-exiu.c | 25
drivers/irqchip/irq-xtensa-mx.c | 18
drivers/macintosh/Kconfig | 6
drivers/macintosh/Makefile | 3
drivers/macintosh/via-pmu.c | 2
drivers/mailbox/mailbox.c | 19
drivers/md/bcache/btree.c | 58
drivers/md/bcache/btree.h | 2
drivers/md/bcache/journal.c | 31
drivers/md/bcache/journal.h | 2
drivers/md/bcache/request.c | 6
drivers/md/bcache/super.c | 1
drivers/md/bcache/writeback.c | 101 -
drivers/md/bcache/writeback.h | 2
drivers/md/md-bitmap.c | 44
drivers/md/md.c | 22
drivers/md/raid0.c | 1
drivers/media/cec/core/cec-adap.c | 6
drivers/media/i2c/ccs/ccs-core.c | 7
drivers/media/i2c/max9286.c | 139 +
drivers/media/i2c/ov5648.c | 4
drivers/media/i2c/ov7670.c | 1
drivers/media/i2c/rdacm20.c | 2
drivers/media/i2c/rdacm21.c | 2
drivers/media/pci/cx23885/cx23885-core.c | 6
drivers/media/pci/cx25821/cx25821-core.c | 2
drivers/media/platform/aspeed-video.c | 4
drivers/media/platform/atmel/atmel-sama5d2-isc.c | 7
drivers/media/platform/coda/coda-common.c | 35
drivers/media/platform/exynos4-is/fimc-is.c | 6
drivers/media/platform/exynos4-is/fimc-isp-video.h | 2
drivers/media/platform/qcom/venus/hfi.c | 3
drivers/media/platform/rockchip/rga/rga.c | 6
drivers/media/platform/sti/delta/delta-v4l2.c | 6
drivers/media/platform/vsp1/vsp1_rpf.c | 6
drivers/media/rc/imon.c | 99 -
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7
drivers/media/usb/uvc/uvc_v4l2.c | 20
drivers/memory/samsung/exynos5422-dmc.c | 5
drivers/mfd/davinci_voicecodec.c | 6
drivers/mfd/ipaq-micro.c | 2
drivers/misc/ocxl/file.c | 2
drivers/mmc/core/block.c | 8
drivers/mmc/host/jz4740_mmc.c | 20
drivers/mmc/host/sdhci_am654.c | 23
drivers/mtd/chips/cfi_cmdset_0002.c | 103 -
drivers/mtd/mtdblock.c | 8
drivers/mtd/nand/raw/cadence-nand-controller.c | 5
drivers/mtd/nand/raw/denali_pci.c | 15
drivers/mtd/nand/raw/intel-nand-controller.c | 2
drivers/mtd/nand/spi/gigadevice.c | 10
drivers/mtd/spi-nor/core.c | 9
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 2
drivers/net/can/xilinx_can.c | 4
drivers/net/dsa/Kconfig | 3
drivers/net/dsa/mt7530.c | 14
drivers/net/ethernet/broadcom/Makefile | 5
drivers/net/ethernet/cadence/macb_main.c | 40
drivers/net/ethernet/cadence/macb_ptp.c | 4
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 5
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 10
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 5
drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 9
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 2
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 23
drivers/net/ethernet/huawei/hinic/hinic_main.c | 10
drivers/net/ethernet/huawei/hinic/hinic_tx.c | 9
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13
drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c | 2
drivers/net/ethernet/sfc/ef10.c | 2
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | 15
drivers/net/ethernet/xscale/ptp_ixp46x.c | 2
drivers/net/hyperv/netvsc_drv.c | 5
drivers/net/ipa/ipa_endpoint.c | 36
drivers/net/phy/micrel.c | 11
drivers/net/usb/asix_devices.c | 6
drivers/net/usb/smsc95xx.c | 3
drivers/net/usb/usbnet.c | 6
drivers/net/wireless/ath/ath10k/mac.c | 20
drivers/net/wireless/ath/ath11k/mac.c | 16
drivers/net/wireless/ath/ath11k/spectral.c | 17
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8
drivers/net/wireless/ath/carl9170/tx.c | 3
drivers/net/wireless/broadcom/b43/phy_n.c | 2
drivers/net/wireless/broadcom/b43legacy/phy.c | 2
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3
drivers/net/wireless/marvell/mwifiex/11h.c | 2
drivers/net/wireless/mediatek/mt76/agg-rx.c | 5
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 8
drivers/net/wireless/microchip/wilc1000/mon.c | 4
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8
drivers/net/wireless/realtek/rtlwifi/usb.c | 2
drivers/net/wireless/realtek/rtw88/rtw8821c.c | 4
drivers/nfc/st21nfca/se.c | 17
drivers/nfc/st21nfca/st21nfca.h | 1
drivers/nvdimm/core.c | 9
drivers/nvdimm/security.c | 5
drivers/nvme/host/core.c | 21
drivers/nvme/host/pci.c | 1
drivers/of/kexec.c | 9
drivers/of/overlay.c | 4
drivers/opp/of.c | 2
drivers/pci/controller/cadence/pcie-cadence-ep.c | 3
drivers/pci/controller/dwc/pci-imx6.c | 23
drivers/pci/controller/dwc/pcie-designware-host.c | 3
drivers/pci/controller/dwc/pcie-qcom.c | 9
drivers/pci/controller/pcie-mediatek.c | 1
drivers/pci/controller/pcie-microchip-host.c | 6
drivers/pci/controller/pcie-rockchip-ep.c | 3
drivers/pci/pci-acpi.c | 41
drivers/pci/pci.c | 12
drivers/pci/pcie/aer.c | 7
drivers/phy/qualcomm/phy-qcom-qmp.c | 11
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 18
drivers/pinctrl/mediatek/Kconfig | 1
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2
drivers/pinctrl/pinctrl-rockchip.c | 64
drivers/pinctrl/pinctrl-rockchip.h | 7
drivers/pinctrl/renesas/core.c | 7
drivers/pinctrl/renesas/pfc-r8a779a0.c | 29
drivers/pinctrl/renesas/pinctrl-rzn1.c | 10
drivers/platform/chrome/cros_ec.c | 16
drivers/platform/chrome/cros_ec_chardev.c | 2
drivers/platform/chrome/cros_ec_proto.c | 50
drivers/platform/mips/cpu_hwmon.c | 127 -
drivers/platform/x86/intel/hid.c | 2
drivers/regulator/core.c | 7
drivers/regulator/da9121-regulator.c | 2
drivers/regulator/pfuze100-regulator.c | 2
drivers/regulator/qcom_smd-regulator.c | 35
drivers/regulator/scmi-regulator.c | 2
drivers/s390/cio/chsc.c | 4
drivers/scsi/dc395x.c | 15
drivers/scsi/fcoe/fcoe_ctlr.c | 2
drivers/scsi/lpfc/lpfc_els.c | 49
drivers/scsi/lpfc/lpfc_init.c | 51
drivers/scsi/lpfc/lpfc_logmsg.h | 6
drivers/scsi/lpfc/lpfc_scsi.c | 37
drivers/scsi/lpfc/lpfc_sli.c | 6
drivers/scsi/megaraid.c | 2
drivers/scsi/ufs/ti-j721e-ufs.c | 6
drivers/scsi/ufs/ufs-qcom.c | 14
drivers/scsi/ufs/ufshcd.c | 7
drivers/soc/bcm/bcm63xx/bcm-pmb.c | 3
drivers/soc/qcom/llcc-qcom.c | 1
drivers/soc/qcom/smp2p.c | 1
drivers/soc/qcom/smsm.c | 1
drivers/soc/ti/ti_sci_pm_domains.c | 2
drivers/spi/spi-cadence-quadspi.c | 2
drivers/spi/spi-fsl-qspi.c | 4
drivers/spi/spi-img-spfi.c | 2
drivers/spi/spi-rockchip.c | 113 +
drivers/spi/spi-rspi.c | 15
drivers/spi/spi-stm32-qspi.c | 3
drivers/spi/spi-ti-qspi.c | 5
drivers/staging/media/hantro/hantro_g2_hevc_dec.c | 11
drivers/staging/media/hantro/hantro_h264.c | 2
drivers/staging/media/hantro/hantro_v4l2.c | 8
drivers/staging/media/rkvdec/rkvdec-h264.c | 37
drivers/staging/media/rkvdec/rkvdec.c | 4
drivers/staging/r8188eu/os_dep/ioctl_linux.c | 103 -
drivers/target/target_core_device.c | 1
drivers/target/target_core_user.c | 50
drivers/thermal/broadcom/bcm2711_thermal.c | 5
drivers/thermal/broadcom/sr-thermal.c | 3
drivers/thermal/devfreq_cooling.c | 25
drivers/thermal/imx_sc_thermal.c | 6
drivers/thermal/thermal_core.c | 1
drivers/tty/goldfish.c | 20
drivers/tty/serial/pch_uart.c | 27
drivers/tty/tty_buffer.c | 3
drivers/usb/core/hcd.c | 29
drivers/usb/core/quirks.c | 3
drivers/usb/dwc3/gadget.c | 6
drivers/usb/host/xhci-pci.c | 2
drivers/usb/isp1760/isp1760-core.c | 8
drivers/usb/serial/option.c | 2
drivers/usb/serial/pl2303.c | 3
drivers/vdpa/vdpa_sim/vdpa_sim.c | 5
drivers/video/console/sticon.c | 5
drivers/video/console/sticore.c | 32
drivers/video/fbdev/amba-clcd.c | 5
drivers/video/fbdev/core/fbcon.c | 5
drivers/video/fbdev/sticore.h | 3
drivers/video/fbdev/stifb.c | 4
drivers/video/fbdev/vesafb.c | 5
fs/afs/misc.c | 5
fs/afs/rotate.c | 4
fs/afs/rxrpc.c | 8
fs/afs/write.c | 1
fs/binfmt_flat.c | 27
fs/btrfs/disk-io.c | 4
fs/btrfs/extent_io.c | 21
fs/btrfs/volumes.c | 8
fs/cifs/cifsfs.c | 10
fs/cifs/smb2inode.c | 2
fs/cifs/smb2ops.c | 9
fs/dax.c | 3
fs/dlm/lock.c | 11
fs/dlm/lowcomms.c | 2
fs/dlm/plock.c | 12
fs/exportfs/expfs.c | 5
fs/ext4/ext4.h | 6
fs/ext4/extents.c | 20
fs/ext4/inline.c | 12
fs/ext4/inode.c | 13
fs/ext4/mballoc.c | 18
fs/ext4/namei.c | 84 -
fs/ext4/super.c | 24
fs/f2fs/checkpoint.c | 2
fs/f2fs/dir.c | 3
fs/f2fs/f2fs.h | 31
fs/f2fs/file.c | 26
fs/f2fs/hash.c | 11
fs/f2fs/inline.c | 31
fs/f2fs/inode.c | 21
fs/f2fs/namei.c | 37
fs/f2fs/recovery.c | 6
fs/f2fs/segment.c | 42
fs/f2fs/segment.h | 33
fs/f2fs/super.c | 22
fs/f2fs/verity.c | 2
fs/f2fs/xattr.c | 2
fs/fat/fatent.c | 7
fs/fs-writeback.c | 13
fs/gfs2/quota.c | 32
fs/hugetlbfs/inode.c | 4
fs/iomap/buffered-io.c | 3
fs/jfs/jfs_dmap.c | 3
fs/ksmbd/connection.c | 2
fs/ksmbd/smb2misc.c | 2
fs/ksmbd/smb_common.c | 4
fs/namei.c | 70
fs/nfs/file.c | 50
fs/nfs/getroot.c | 17
fs/nfs/inode.c | 25
fs/nfs/internal.h | 9
fs/nfs/nfs4proc.c | 41
fs/nfs/nfs4state.c | 2
fs/nfs/pagelist.c | 3
fs/nfs/pnfs.c | 6
fs/nfs/unlink.c | 8
fs/nfs/write.c | 54
fs/nfsd/nfscache.c | 2
fs/notify/fdinfo.c | 11
fs/notify/inotify/inotify.h | 12
fs/notify/inotify/inotify_user.c | 2
fs/notify/mark.c | 6
fs/ntfs3/file.c | 12
fs/ntfs3/frecord.c | 10
fs/ntfs3/fslog.c | 12
fs/ntfs3/inode.c | 8
fs/ntfs3/xattr.c | 112 +
fs/ocfs2/dlmfs/userdlm.c | 16
fs/proc/generic.c | 3
fs/proc/proc_net.c | 3
include/drm/drm_edid.h | 6
include/linux/blk_types.h | 5
include/linux/bpf.h | 2
include/linux/compat.h | 1
include/linux/efi.h | 2
include/linux/fwnode.h | 10
include/linux/goldfish.h | 15
include/linux/gpio/driver.h | 12
include/linux/kexec.h | 46
include/linux/list.h | 40
include/linux/mailbox_controller.h | 1
include/linux/mtd/cfi.h | 1
include/linux/namei.h | 6
include/linux/nfs_fs.h | 13
include/linux/nfs_fs_sb.h | 1
include/linux/nodemask.h | 13
include/linux/platform_data/cros_ec_proto.h | 3
include/linux/ptp_classify.h | 3
include/linux/ptrace.h | 7
include/linux/sched/signal.h | 2
include/linux/usb/hcd.h | 2
include/net/if_inet6.h | 8
include/scsi/libfcoe.h | 3
include/scsi/libiscsi.h | 6
include/sound/jack.h | 1
include/trace/events/rxrpc.h | 2
include/trace/events/vmscan.h | 4
include/uapi/asm-generic/siginfo.h | 7
include/uapi/linux/landlock.h | 9
init/Kconfig | 5
ipc/mqueue.c | 14
kernel/dma/debug.c | 2
kernel/dma/direct.c | 125 -
kernel/events/core.c | 4
kernel/kexec_file.c | 34
kernel/printk/printk.c | 63
kernel/ptrace.c | 5
kernel/rcu/Kconfig | 1
kernel/rcu/tasks.h | 3
kernel/scftorture.c | 5
kernel/sched/core.c | 6
kernel/sched/deadline.c | 5
kernel/sched/fair.c | 8
kernel/sched/pelt.h | 4
kernel/sched/psi.c | 15
kernel/sched/rt.c | 5
kernel/sched/sched.h | 32
kernel/signal.c | 18
kernel/trace/ftrace.c | 5
kernel/trace/trace_boot.c | 2
kernel/trace/trace_events_hist.c | 3
lib/kunit/debugfs.c | 2
lib/list-test.c | 19
mm/cma.c | 4
mm/compaction.c | 2
mm/hugetlb.c | 9
mm/memremap.c | 2
mm/page_alloc.c | 4
net/bluetooth/hci_event.c | 15
net/bluetooth/hci_request.c | 2
net/bluetooth/sco.c | 21
net/core/dev.c | 8
net/ipv6/addrconf.c | 33
net/mac80211/chan.c | 7
net/mac80211/ieee80211_i.h | 5
net/mac80211/rc80211_minstrel_ht.c | 3
net/mac80211/scan.c | 20
net/mptcp/pm_netlink.c | 2
net/nfc/core.c | 1
net/rxrpc/ar-internal.h | 13
net/rxrpc/call_event.c | 7
net/rxrpc/conn_object.c | 2
net/rxrpc/input.c | 58
net/rxrpc/output.c | 20
net/rxrpc/recvmsg.c | 8
net/rxrpc/sendmsg.c | 6
net/rxrpc/sysctl.c | 4
net/sctp/input.c | 4
net/smc/af_smc.c | 2
net/wireless/nl80211.c | 4
net/wireless/reg.c | 4
samples/bpf/Makefile | 9
samples/landlock/sandboxer.c | 104 -
scripts/faddr2line | 150 +
security/integrity/ima/Kconfig | 14
security/integrity/platform_certs/keyring_handler.h | 8
security/integrity/platform_certs/load_uefi.c | 33
security/landlock/cred.c | 4
security/landlock/cred.h | 8
security/landlock/fs.c | 191 +-
security/landlock/fs.h | 11
security/landlock/limits.h | 8
security/landlock/object.c | 6
security/landlock/object.h | 6
security/landlock/ptrace.c | 10
security/landlock/ruleset.c | 84 -
security/landlock/ruleset.h | 35
security/landlock/syscalls.c | 95 -
sound/core/jack.c | 34
sound/core/pcm_memory.c | 3
sound/pci/hda/patch_realtek.c | 21
sound/soc/atmel/atmel-classd.c | 1
sound/soc/atmel/atmel-pdmic.c | 1
sound/soc/codecs/Kconfig | 2
sound/soc/codecs/max98090.c | 6
sound/soc/codecs/rk3328_codec.c | 2
sound/soc/codecs/rt5514.c | 2
sound/soc/codecs/rt5645.c | 7
sound/soc/codecs/tscs454.c | 12
sound/soc/codecs/wm2000.c | 6
sound/soc/fsl/fsl-asoc-card.c | 3
sound/soc/fsl/imx-card.c | 17
sound/soc/fsl/imx-hdmi.c | 1
sound/soc/fsl/imx-sgtl5000.c | 18
sound/soc/fsl/imx-spdif.c | 4
sound/soc/intel/boards/bytcr_rt5640.c | 12
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5
sound/soc/mxs/mxs-saif.c | 1
sound/soc/samsung/aries_wm8994.c | 17
sound/soc/samsung/arndale.c | 5
sound/soc/samsung/littlemill.c | 5
sound/soc/samsung/lowland.c | 5
sound/soc/samsung/odroid.c | 4
sound/soc/samsung/smdk_wm8994.c | 4
sound/soc/samsung/smdk_wm8994pcm.c | 4
sound/soc/samsung/snow.c | 9
sound/soc/samsung/speyside.c | 5
sound/soc/samsung/tm2_wm5110.c | 3
sound/soc/samsung/tobermory.c | 5
sound/soc/sh/rcar/core.c | 15
sound/soc/sh/rcar/dma.c | 9
sound/soc/sh/rcar/rsnd.h | 2
sound/soc/sh/rcar/src.c | 7
sound/soc/sh/rcar/ssi.c | 14
sound/soc/sh/rcar/ssiu.c | 11
sound/soc/sh/rz-ssi.c | 29
sound/soc/soc-dapm.c | 2
sound/soc/ti/j721e-evm.c | 44
sound/usb/implicit.c | 10
sound/usb/midi.c | 3
sound/usb/quirks.c | 6
sound/usb/usbaudio.h | 6
tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c | 5
tools/lib/bpf/libbpf.c | 20
tools/objtool/check.c | 9
tools/objtool/elf.c | 198 +-
tools/objtool/include/objtool/elf.h | 4
tools/perf/Makefile.config | 39
tools/perf/builtin-c2c.c | 6
tools/perf/pmu-events/jevents.c | 2
tools/perf/util/data.h | 1
tools/power/x86/turbostat/turbostat.c | 1
tools/testing/selftests/Makefile | 1
tools/testing/selftests/arm64/bti/Makefile | 4
tools/testing/selftests/bpf/Makefile | 2
tools/testing/selftests/bpf/progs/btf_dump_test_case_syntax.c | 2
tools/testing/selftests/bpf/progs/profiler.inc.h | 5
tools/testing/selftests/bpf/test_bpftool_synctypes.py | 2
tools/testing/selftests/cgroup/test_stress.sh | 2
tools/testing/selftests/landlock/base_test.c | 177 +-
tools/testing/selftests/landlock/common.h | 66
tools/testing/selftests/landlock/fs_test.c | 753 ++++++----
tools/testing/selftests/landlock/ptrace_test.c | 40
tools/testing/selftests/resctrl/fill_buf.c | 4
713 files changed, 7192 insertions(+), 4198 deletions(-)
Abhinav Kumar (1):
drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path
Abhishek Kumar (1):
ath10k: skip ath10k_halt during suspend for driver state RESTARTING
Adam Wujek (1):
hwmon: (pmbus) Check PEC support before reading other registers
Aditya Garg (1):
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Aidan MacDonald (1):
mmc: jz4740: Apply DMA engine limits to maximum segment size
Ajay Singh (1):
wilc1000: fix crash observed in AP mode with cfg80211_register_netdevice()
Akira Yokosawa (1):
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Albert Wang (1):
usb: dwc3: gadget: Move null pinter check to proper place
Alex Deucher (2):
drm/amdgpu/psp: move PSP memory alloc from hw_init to sw_init
drm/amdgpu: add beige goby PCI ID
Alex Elder (3):
net: ipa: ignore endianness if there is no header
net: ipa: fix page free in ipa_endpoint_trans_release()
net: ipa: fix page free in ipa_endpoint_replenish_one()
Alexander Aring (2):
dlm: fix plock invalid read
dlm: fix missing lkb refcount handling
Alexander Wetzel (1):
rtl818x: Prevent using not initialized queues
Alexandre Ghiti (1):
riscv: Initialize thread pointer before calling C functions
Alexandru Elisei (1):
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Alexey Dobriyan (1):
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
Alexey Khoroshilov (1):
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
Alice Wong (1):
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Allen-KH Cheng (1):
arm64: dts: mt8192: Fix nor_flash status disable typo
Amadeusz Sławiński (1):
ALSA: jack: Access input_dev under mutex
Amelie Delaunay (2):
dmaengine: stm32-mdma: remove GISR1 register
dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler()
Amir Goldstein (2):
inotify: show inotify mask flags in proc fdinfo
fsnotify: fix wrong lockdep annotations
Ammar Faizi (2):
x86/MCE/AMD: Fix memory leak when threshold_create_bank() fails
x86/delay: Fix the wrong asm constraint in delay_loop()
Andre Przywara (2):
kselftest/arm64: bti: force static linking
ARM: dts: suniv: F1C100: fix watchdog compatible
Andrea Parri (Microsoft) (1):
Drivers: hv: vmbus: Fix handling of messages with transaction ID of zero
Andreas Gruenbacher (1):
iomap: iomap_write_failed fix
Andrii Nakryiko (2):
libbpf: Don't error out on CO-RE relos for overriden weak subprogs
libbpf: Fix logic for finding matching program for CO-RE relocation
Andy Shevchenko (2):
device property: Allow error pointer to be passed to fwnode APIs
list: introduce list_is_head() helper and re-use it in list.h
Anna Schumaker (1):
NFS: Create a new nfs_alloc_fattr_with_label() function
Arnd Bergmann (2):
drbd: fix duplicate array initializer
ARM: pxa: maybe fix gpio lookup tables
Baochen Qiang (1):
ath11k: Don't check arvif->is_started before sending management frames
Baokun Li (2):
ext4: fix race condition between ext4_write and ext4_convert_inline_data
ext4: fix bug_on in __es_tree_search
Baoquan He (1):
x86/kexec: fix memory leak of elf header buffer
Bart Van Assche (2):
scsi: ufs: qcom: Fix ufs_qcom_resume()
block: Fix the bio.bi_opf comment
Basavaraj Natikar (2):
HID: amd_sfh: Modify the bus name
HID: amd_sfh: Modify the hid name
Bean Huo (1):
mmc: core: Allows to override the timeout value for ioctl() path
Benjamin Gaignard (2):
media: hantro: HEVC: unconditionnaly set pps_{cb/cr}_qp_offset values
media: hantro: HEVC: Fix tile info buffer value computation
Biju Das (1):
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Bjorn Andersson (2):
drm/msm/dp: Modify prototype of encoder based API
soc: qcom: llcc: Add MODULE_DEVICE_TABLE()
Bjorn Helgaas (1):
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Björn Ardö (1):
mailbox: forward the hrtimer if not queued and under a lock
Bjørn Mork (1):
mtdblock: warn if opened on NAND
Bob Peterson (1):
gfs2: use i_lock spin_lock for inode qadata
Bodo Stroesser (1):
scsi: target: tcmu: Avoid holding XArray lock when calling lock_page
Borislav Petkov (1):
x86/microcode: Add explicit CPU vendor dependency
Brian Norris (2):
PM / devfreq: rk3399_dmc: Disable edev on remove()
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Cai Huoqing (1):
media: staging: media: rkvdec: Make use of the helper function devm_platform_ioremap_resource()
Caleb Connolly (2):
pinctrl/rockchip: support deferring other gpio params
pinctrl/rockchip: support setting input-enable param
Carl Yin(殷张成) (1):
USB: serial: option: add Quectel BG95 modem
Chaitanya Kulkarni (1):
nvme: set non-mdts limits in nvme_scan_work
Chao Yu (9):
f2fs: support fault injection for dquot_initialize()
f2fs: fix to do sanity check on inline_dots inode
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
f2fs: fix to clear dirty inode in f2fs_evict_inode()
f2fs: fix deadloop in foreground GC
f2fs: fix to do sanity check on total_data_blocks
f2fs: fix fallocate to use file_modified to update permissions consistently
f2fs: fix to do sanity check for inline inode
Charles Keepax (3):
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
ASoC: atmel-pdmic: Remove endianness flag on pdmic component
ASoC: atmel-classd: Remove endianness flag on class d component
Chen-Tsung Hsieh (1):
mtd: spi-nor: core: Check written SR value in spi_nor_write_16bit_sr_and_check()
Chen-Yu Tsai (1):
media: hantro: Empty encoder capture buffers by default
Chengming Zhou (2):
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
sched/psi: report zeroes for CPU full at the system level
Christian Brauner (2):
fs: add two trivial lookup helpers
exportfs: support idmapped mounts
Christoph Hellwig (7):
target: remove an incorrect unmap zeroes data deduction
virtio_blk: fix the discard_granularity and discard_alignment queue limits
dma-direct: factor out a helper for DMA_ATTR_NO_KERNEL_MAPPING allocations
dma-direct: don't fail on highmem CMA pages in dma_direct_alloc_pages
dma-direct: factor out dma_set_{de,en}crypted helpers
dma-direct: don't call dma_set_decrypted for remapped allocations
dma-direct: always leak memory that can't be re-encrypted
Christophe JAILLET (8):
fs/ntfs3: Fix some memory leaks in an error handling path of 'log_replay()'
media: aspeed: Fix an error handling path in aspeed_video_probe()
mt76: mt7921: Fix the error handling path of mt7921_pci_probe()
hinic: Avoid some over memory allocation
memory: samsung: exynos5422-dmc: Avoid some over memory allocation
drivers/base/memory: fix an unlikely reference counting issue in __add_memory_block()
powerpc/xive: Add some error handling code to 'xive_spapr_init()'
dmaengine: idxd: Fix the error handling path in idxd_cdev_register()
Christophe de Dinechin (1):
nodemask.h: fix compilation error with GCC12
Chuanhong Guo (2):
mtd: spinand: gigadevice: fix Quad IO for GD5F1GQ5UExxG
arm: mediatek: select arch timer for mt7629
Colin Ian King (3):
ALSA: pcm: Check for null pointer of pointer substream before dereferencing it
drm/v3d: Fix null pointer dereference of pointer perfmon
selftests/resctrl: Fix null pointer dereference on open failed
Coly Li (4):
bcache: improve multithreaded bch_btree_check()
bcache: improve multithreaded bch_sectors_dirty_init()
bcache: remove incremental dirty sector counting for bch_sectors_dirty_init()
bcache: avoid journal no-space deadlock by reserving 1 journal bucket
Corentin Labbe (3):
crypto: marvell/cesa - ECB does not IV
crypto: sun8i-ss - rework handling of IV
crypto: sun8i-ss - handle zero sized sg
Corey Minyard (2):
ipmi:ssif: Check for NULL msg when handling events and messages
ipmi: Fix pr_fmt to avoid compilation issues
Cristian Marussi (1):
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Daire McNamara (1):
PCI: microchip: Fix potential race in interrupt handling
Dan Carpenter (8):
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
scsi: iscsi: Fix harmless double shift bug
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
PCI: cadence: Fix find_first_zero_bit() limit
PCI: rockchip: Fix find_first_zero_bit() limit
OPP: call of_node_put() on error path in _bandwidth_supported()
dlm: uninitialized variable on error in dlm_listen_for_all()
staging: r8188eu: delete rtw_wx_read/write32()
Dan Williams (2):
nvdimm: Fix firmware activation deadlock scenarios
nvdimm: Allow overwrite in the presence of disabled dimms
Daniel Latypov (1):
kunit: fix debugfs code to use enum kunit_status, not bool
Daniel Scally (1):
device property: Check fwnode->secondary when finding properties
Daniel Thompson (1):
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Daniel Vetter (1):
fbcon: Consistently protect deferred_takeover with console_lock()
Dave Airlie (1):
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
David Gow (1):
list: test: Add a test for list_is_head()
David Howells (8):
rxrpc: Return an error to sendmsg if call failed
rxrpc, afs: Fix selection of abort codes
afs: Adjust ACK interpretation to try and cope with NAT
rxrpc: Fix listen() setting the bar too high for the prealloc rings
rxrpc: Don't try to resend the request if we're receiving the reply
rxrpc: Fix overlapping ACK accounting
rxrpc: Don't let ack.previousPacket regress
rxrpc: Fix decision on when to generate an IDLE ACK
Denis Efremov (1):
staging: r8188eu: prevent ->Ssid overflow in rtw_wx_set_scan()
Dennis Dalessandro (1):
RDMA/hfi1: Fix potential integer multiplication overflow errors
Dimitri John Ledkov (1):
cfg80211: declare MODULE_FIRMWARE for regulatory.db
Dinh Nguyen (1):
dt-bindings: gpio: altera: correct interrupt-cells
Diogo Ivo (2):
arm64: tegra: Add missing DFLL reset on Tegra210
clk: tegra: Add missing reset deassertion
Dmitry Baryshkov (5):
drm/msm/hdmi: switch to drm_bridge_connector
drm/msm/dsi: fix error checks and return values for DSI xmit functions
drm/msm: add missing include to msm_drv.c
drm/msm/dsi: fix address for second DSI PHY on SDM660
drm/msm: don't free the IRQ if it was not requested
Dmitry Monakhov (1):
ext4: mark group as trimmed only if it was fully scanned
Dmitry Torokhov (1):
Input: stmfts - do not leave device disabled in stmfts_input_open
Dong Aisheng (1):
Revert "mm/cma.c: remove redundant cma_mutex lock"
Dongliang Mu (3):
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
rtlwifi: Use pr_warn instead of WARN_ONCE
media: ov7670: remove ov7670_power_off from ov7670_remove
Douglas Miller (2):
RDMA/hfi1: Prevent panic when SDMA is disabled
RDMA/hfi1: Prevent use of lock before it is initialized
Duoming Zhou (1):
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
Emmanuel Grumbach (1):
iwlwifi: mvm: fix assert 1F04 upon reconfig
Eric Biggers (3):
ext4: reject the 'commit' option on ext2 filesystems
f2fs: don't use casefolded comparison for "." and ".."
ext4: only allow test_dummy_encryption when supported
Eric Dumazet (2):
net: remove two BUG() from skb_checksum_help()
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
Eric W. Biederman (3):
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Eugen Hristev (2):
media: atmel: atmel-sama5d2-isc: fix wrong mask in YUYV format check
ARM: dts: at91: sama7g5: remove interrupt-parent from gic node
Eugenio Pérez (1):
vdpasim: allow to enable a vq repeatedly
Evan Quan (1):
drm/amd/pm: fix the compile warning
Fabien Parent (1):
pinctrl: mediatek: mt8195: enable driver on mtk platforms
Fabio Estevam (1):
net: phy: micrel: Allow probing without .driver_data
Felix Fietkau (4):
mt76: mt7921: accept rx frames with non-standard VHT MCS10-11
mt76: fix encap offload ethernet type check
mt76: do not attempt to reorder received 802.3 packets without agg session
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Finn Thain (1):
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Francesco Dolcini (1):
PCI: imx6: Fix PERST# start-up sequence
GUO Zihua (1):
ima: remove the IMA_TEMPLATE Kconfig option
Gautam Menghani (1):
tracing: Initialize integer variable to prevent garbage return value
Geert Uytterhoeven (3):
m68k: atari: Make Atari ROM port I/O write macros return void
m68k: math-emu: Fix dependencies of math emulation support
pinctrl: renesas: r8a779a0: Fix GPIO function on I2C-capable pins
Gilad Ben-Yossef (1):
crypto: ccree - use fine grained DMA mapping dir
Giovanni Cabiddu (4):
crypto: qat - set CIPHER capability for QAT GEN2
crypto: qat - set COMPRESSION capability for QAT GEN2
crypto: qat - set CIPHER capability for DH895XCC
crypto: qat - set COMPRESSION capability for DH895XCC
Greg Kroah-Hartman (1):
Linux 5.15.46
Guenter Roeck (2):
platform/chrome: Re-introduce cros_ec_cmd_xfer and use it for ioctls
MIPS: Loongson: Use hwmon_device_register_with_groups() to register hwmon
Guo Ren (1):
csky: patch_text: Fixup last cpu should be master
Gustavo A. R. Silva (3):
net: stmmac: selftests: Use kcalloc() instead of kzalloc()
net: huawei: hinic: Use devm_kcalloc() instead of devm_kzalloc()
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
Hangbin Liu (1):
selftests/bpf: Add missed ima_setup.sh in Makefile
Hangyu Hua (3):
media: rga: fix possible memory leak in rga_probe
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
misc: ocxl: fix possible double free in ocxl_file_register_afu
Hans Verkuil (2):
media: ccs-core.c: fix failure to call clk_disable_unprepare
media: cec-adap.c: fix is_configuring state
Hans de Goede (1):
ASoC: Intel: bytcr_rt5640: Add quirk for the HP Pro Tablet 408
Hao Jia (1):
sched/core: Avoid obvious double update_rq_clock warning
Haohui Mai (1):
drm/amdgpu/sdma: Fix incorrect calculations of the wptr of the doorbells
Haowen Bai (4):
b43legacy: Fix assigning negative value to unsigned variable
b43: Fix assigning negative value to unsigned variable
ipw2x00: Fix potential NULL dereference in libipw_xmit()
sfc: ef10: Fix assigning negative value to unsigned variable
Haren Myneni (1):
powerpc/powernv/vas: Assign real address to rx_fifo in vas_rx_win_attr
Hari Bathini (2):
powerpc/fadump: Fix fadump to work with a different endian capture kernel
powerpc/fadump: fix PT_LOAD segment for boot memory area
Hari Chandrakanthan (1):
ath11k: disable spectral scan during spectral deinit
Harini Katakam (1):
net: macb: Fix PTP one step sync support
Heiko Carstens (1):
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Heiner Kallweit (1):
ASoC: sh: rz-ssi: Check return value of pm_runtime_resume_and_get()
Helge Deller (2):
parisc/stifb: Implement fb_is_primary_device()
parisc/stifb: Keep track of hardware path of graphics card
Heming Zhao (1):
md/bitmap: don't set sb values if can't pass sanity check
Hyunchul Lee (1):
ksmbd: fix outstanding credits related bugs
Ian Abbott (1):
spi: cadence-quadspi: fix Direct Access Mode disable for SoCFPGA
Jacopo Mondi (1):
media: i2c: max9286: Use "maxim,gpio-poc" property
Jaegeuk Kim (1):
f2fs: don't need inode lock for system hidden quota
Jagan Teki (1):
drm/panel: panel-simple: Fix proper bpc for AM-1280800N3TZQW-T00H
Jakob Koschel (1):
f2fs: fix dereference of stale list iterator after loop body
Jakub Kicinski (2):
eth: tg3: silence the GCC 12 array-bounds warning
net: stmmac: fix out-of-bounds access in a selftest
James Clark (1):
perf tools: Use Python devtools for version autodetection rather than runtime
James Smart (5):
scsi: lpfc: Move cfg_log_verbose check before calling lpfc_dmp_dbg()
scsi: lpfc: Fix SCSI I/O completion and abort handler deadlock
scsi: lpfc: Fix call trace observed during I/O with CMF enabled
scsi: lpfc: Fix resource leak in lpfc_sli4_send_seq_to_ulp()
scsi: lpfc: Alter FPIN stat accounting logic
Jan Kara (14):
bfq: Relax waker detection for shared queues
bfq: Allow current waker to defend against a tentative one
bfq: Avoid false marking of bic as stably merged
bfq: Avoid merging queues with different parents
bfq: Split shared queues on move between cgroups
bfq: Update cgroup information before merging bio
bfq: Drop pointless unlock-lock pair
bfq: Remove pointless bfq_init_rq() calls
bfq: Track whether bfq_group is still online
bfq: Get rid of __bio_blkcg() usage
bfq: Make sure bfqg for which we are queueing requests is online
ext4: verify dir block before splitting it
ext4: avoid cycles in directory h-tree
block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
Jan Kiszka (1):
efi: Add missing prototype for efi_capsule_setup_info
Jani Nikula (2):
drm/edid: fix invalid EDID extension block filtering
drm/i915/dsi: fix VBT send packet port selection for ICL+
Janusz Krzysztofik (1):
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Jason A. Donenfeld (2):
openrisc: start CPU timer early in boot
Revert "random: use static branch for crng_ready()"
Javier Martinez Canillas (1):
video: fbdev: vesafb: Fix a use-after-free due early fb_info cleanup
Jean-Philippe Brucker (1):
iommu/arm-smmu-v3-sva: Fix mm use-after-free
Jerome Marchand (1):
samples: bpf: Don't fail for a missing VMLINUX_BTF when VMLINUX_H is provided
Jessica Zhang (2):
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jia-Ju Bai (1):
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Jia-Wei Chang (1):
cpufreq: mediatek: Use module_init and add module_exit
Jiantao Zhang (1):
PCI: dwc: Fix setting error return on MSI DMA mapping failure
Jiasheng Jiang (1):
drm: mali-dp: potential dereference of null pointer
Jiri Olsa (1):
perf build: Fix btf__load_from_kernel_by_id() feature check
Jiri Slaby (1):
serial: pch: don't overwrite xmit->buf[0] by x_char
Joel Selvaraj (1):
arm64: dts: qcom: sdm845-xiaomi-beryllium: fix typo in panel's vddio-supply property
Joerg Roedel (1):
iommu/amd: Increase timeout waiting for GA log enablement
Johan Hovold (5):
USB: serial: pl2303: fix type detection for odd device
PCI: qcom: Fix runtime PM imbalance on probe errors
PCI: qcom: Fix unbalanced PHY init on probe errors
phy: qcom-qmp: fix struct clk leak on probe errors
phy: qcom-qmp: fix reset-controller leak on probe errors
Johannes Berg (5):
nl80211: show SSID for P2P_GO interfaces
nl80211: don't hold RTNL in color change request
wifi: mac80211: fix use-after-free in chanctx code
um: Use asm-generic/dma-mapping.h
um: chan_user: Fix winch_tramp() return value
John Ogness (3):
printk: use atomic updates for klogd work
printk: add missing memory barrier to wake_up_klogd()
printk: wake waiters for safe and NMI contexts
Jon Lin (2):
spi: rockchip: Stop spi slave dma receiver when cs inactive
spi: rockchip: Preset cs-high and clk polarity in setup progress
Jonas Karlman (1):
media: rkvdec: h264: Fix bit depth wrap in pps packet
Jonathan Bakker (1):
ARM: dts: s5pv210: Remove spi-cs-high on panel in Aries
Jonathan Teh (1):
HID: hid-led: fix maximum brightness for Dream Cheeky
Josh Poimboeuf (2):
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
scripts/faddr2line: Fix overlapping text section failures
Julian Schroeder (1):
nfsd: destroy percpu stats counters after reply cache shutdown
Junxiao Bi via Ocfs2-devel (1):
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Kailang Yang (1):
ALSA: hda/realtek - Add new type for ALC245
Kajol Jain (2):
powerpc/perf: Fix the threshold compare group constraint for power10
powerpc/perf: Fix the threshold compare group constraint for power9
Kan Liang (1):
perf/x86/intel: Fix event constraints for ICL
Kant Fan (1):
thermal: devfreq_cooling: use local ops instead of global ops
Kathiravan T (1):
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Keita Suzuki (2):
drm/amd/pm: fix double free in si_parse_power_table()
tracing: Fix potential double free in create_var_ref()
Keith Busch (1):
nvme: set dma alignment to dword
Kirill A. Shutemov (1):
ACPICA: Avoid cache flush inside virtual machines
Kishon Vijay Abraham I (1):
usb: core: hcd: Add support for deferring roothub registration
Kiwoong Kim (1):
scsi: ufs: core: Exclude UECxx from SFR dump list
Konrad Dybcio (3):
arm64: dts: qcom: msm8994: Fix the cont_splash_mem address
arm64: dts: qcom: msm8994: Fix BLSP[12]_DMA channels count
regulator: qcom_smd: Fix up PM8950 regulator configuration
Konstantin Komarov (7):
fs/ntfs3: Update valid size if -EIOCBQUEUED
fs/ntfs3: Fix fiemap + fix shrink file size (to remove preallocated space)
fs/ntfs3: Keep preallocated only if option prealloc enabled
fs/ntfs3: Check new size for limits
fs/ntfs3: In function ntfs_set_acl_ex do not change inode->i_mode if called from function ntfs_init_acl
fs/ntfs3: Update i_ctime when xattr is added
fs/ntfs3: Restore ntfs_xattr_get_acl and ntfs_xattr_set_acl functions
Kristen Carlson Accardi (1):
x86/sgx: Set active memcg prior to shmem allocation
Krzysztof Kozlowski (7):
ARM: dts: ox820: align interrupt controller node name with dtschema
ARM: dts: socfpga: align interrupt controller node name with dtschema
ARM: dts: s5pv210: align DMA channels with dtschema
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
irqchip/aspeed-scu-ic: Fix irq_of_parse_and_map() return value
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
Kuldeep Singh (1):
spi: qcom-qspi: Add minItems to interconnect-names
Kuninori Morimoto (5):
ASoC: rsnd: care default case on rsnd_ssiu_busif_err_status_clear()
ASoC: rsnd: care return value from rsnd_node_fixed_index()
ASoC: fsl: Use dev_err_probe() helper
ASoC: samsung: Use dev_err_probe() helper
i2c: rcar: fix PM ref counts in probe error paths
Kuniyuki Iwashima (1):
list: fix a data-race around ep->rdllist
Kuogee Hsieh (5):
drm/msm/dpu: adjust display_v_end for eDP and DP
drm/msm/dp: stop event kernel thread when DP unbind
drm/msm/dp: reset DP controller before transmit phy test pattern
drm/msm/dp: do not stop transmitting phy test pattern during DP phy compliance test
drm/msm/dp: fix event thread stuck in wait_event after kthread_stop()
Kuppuswamy Sathyanarayanan (1):
PCI/AER: Clear MULTI_ERR_COR/UNCOR_RCV bits
Kwanghoon Son (1):
media: exynos4-is: Fix compile warning
Lad Prabhakar (3):
Input: gpio-keys - cancel delayed work only in case of GPIO
ASoC: sh: rz-ssi: Propagate error codes returned from platform_get_irq_byname()
ASoC: sh: rz-ssi: Release the DMA channels in rz_ssi_probe() error path
Lai Jiangshan (1):
x86/sev: Annotate stack change in the #VC handler
Laurent Dufour (1):
powerpc/rtas: Keep MSR[RI] set when calling RTAS
Laurent Vivier (1):
tty: goldfish: Introduce gf_ioread32()/gf_iowrite32()
Laurentiu Palcu (2):
media: i2c: max9286: fix kernel oops when removing module
media: i2c: rdacm2x: properly set subdev entity function
Len Brown (1):
tools/power turbostat: fix ICX DRAM power numbers
Leo Yan (1):
perf c2c: Use stdio interface if slang is not supported
Lin Ma (2):
ASoC: rt5645: Fix errorenous cleanup order
NFC: NULL out the dev->rfkill to prevent UAF
Linus Torvalds (1):
drm: fix EDID struct for old ARM OABI format
Linus Walleij (1):
usb: isp1760: Fix out-of-bounds array access
Liu Zixian (1):
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Liviu Dudau (1):
drm/komeda: return early if drm_universal_plane_init() fails.
Luca Ceresoli (1):
spi: rockchip: fix missing error on unsupported SPI_CS_HIGH
Luca Weiss (1):
media: venus: hfi: avoid null dereference in deinit
Lucas Stach (2):
drm/bridge: adv7511: clean up CEC adapter when probe fails
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Lukas Wunner (1):
usbnet: Run unregister_netdev() before unbind() again
Lv Ruyi (9):
scsi: megaraid: Fix error check return value of register_chrdev()
drm: msm: fix error check return value of irq_of_parse_and_map()
powerpc/xics: fix refcount leak in icp_opal_init()
powerpc/powernv: fix missing of_node_put in uv_init()
ixp4xx_eth: fix error check return value of platform_get_irq()
drm/msm/dp: fix error check return value of irq_of_parse_and_map()
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
drm/msm/dpu: fix error check return value of irq_of_parse_and_map()
Lyude Paul (1):
drm/nouveau/subdev/bus: Ratelimit logging for fault errors
Maciej W. Rozycki (3):
x86/PCI: Fix ALi M1487 (IBC) PIRQ router link value interpretation
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
MIPS: IP30: Remove incorrect `cpu_has_fpu' override
Manivannan Sadhasivam (1):
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Mao Jinlong (1):
coresight: core: Fix coresight device probe failure issue
Marc Kleine-Budde (1):
can: xilinx_can: mark bit timing constants as const
Marco Elver (1):
signal: Deliver SIGTRAP on perf event asynchronously if blocked
Marek Vasut (4):
drm: bridge: icn6211: Fix register layout
drm: bridge: icn6211: Fix HFP_HSW_HBP_HI and HFP_MIN handling
drm/panel: simple: Add missing bus flags for Innolux G070Y2-L01
ARM: dts: stm32: Fix PHY post-reset delay on Avenger96
Mario Limonciello (3):
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
PCI/ACPI: Allow D3 only if Root Port can signal and wake from D3
iommu/amd: Enable swiotlb in all cases
Marios Levogiannis (1):
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Mark Bloch (1):
net/mlx5: fs, delete the FTE when there are no rules attached to it
Mark Brown (2):
ASoC: dapm: Don't fold register value changes into notifications
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Mark Rutland (1):
arm64: stackleak: fix current_top_of_stack()
Mathias Nyman (1):
xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI
Matthew Wilcox (Oracle) (1):
alpha: fix alloc_zeroed_user_highpage_movable()
Matthias Schiffer (1):
arm64: dts: ti: k3-am64-mcu: remove incorrect UART base clock rates
Matthieu Baerts (1):
x86/pm: Fix false positive kmemleak report in msr_build_context()
Max Filippov (1):
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Max Krummenacher (1):
ARM: dts: imx6dl-colibri: Fix I2C pinmuxing
Maxime Ripard (4):
drm/vc4: hvs: Fix frame count register readout
drm/vc4: hvs: Reset muxes at probe time
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Mel Gorman (1):
mm/page_alloc: always attempt to allocate at least one page during bulk allocation
Miaohe Lin (2):
drivers/base/node.c: fix compaction sysfs file leak
mm/memremap: fix missing call to untrack_pfn() in pagemap_range()
Miaoqian Lin (25):
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
HID: elan: Fix potential double free in elan_input_configured
drm/bridge: Fix error handling in analogix_dp_probe
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
ASoC: imx-hdmi: Fix refcount leak in imx_hdmi_probe
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
ASoC: samsung: Fix refcount leak in aries_audio_probe
media: exynos4-is: Fix PM disable depth imbalance in fimc_is_probe
media: st-delta: Fix PM disable depth imbalance in delta_probe
media: atmel: atmel-isc: Fix PM disable depth imbalance in atmel_isc_probe
media: exynos4-is: Change clk_disable to clk_disable_unprepare
ASoC: ti: j721e-evm: Fix refcount leak in j721e_soc_probe_*
regulator: scmi: Fix refcount leak in scmi_regulator_probe
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
thermal/drivers/imx_sc_thermal: Fix refcount leak in imx_sc_thermal_probe
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
PCI: mediatek: Fix refcount leak in mtk_pcie_subsys_powerup()
Input: sparcspkr - fix refcount leak in bbc_beep_probe
powerpc/xive: Fix refcount leak in xive_spapr_init
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
Michael Ellerman (1):
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
Michael Niewöhner (1):
platform/x86: intel-hid: fix _DSM function index handling
Michael Rodin (1):
media: vsp1: Fix offset calculation for plane cropping
Michael Walle (1):
i2c: at91: use dma safe buffers
Mickaël Salaün (21):
landlock: Add clang-format exceptions
landlock: Format with clang-format
selftests/landlock: Add clang-format exceptions
selftests/landlock: Normalize array assignment
selftests/landlock: Format with clang-format
samples/landlock: Add clang-format exceptions
samples/landlock: Format with clang-format
landlock: Fix landlock_add_rule(2) documentation
selftests/landlock: Make tests build with old libc
selftests/landlock: Extend tests for minimal valid attribute size
selftests/landlock: Add tests for unknown access rights
selftests/landlock: Extend access right tests to directories
selftests/landlock: Fully test file rename with "remove" access
selftests/landlock: Add tests for O_PATH
landlock: Change landlock_add_rule(2) argument check ordering
landlock: Change landlock_restrict_self(2) check ordering
selftests/landlock: Test landlock_create_ruleset(2) argument check ordering
landlock: Define access_mask_t to enforce a consistent access mask size
landlock: Reduce the maximum number of layers to 16
landlock: Create find_rule() from unmask_layers()
landlock: Fix same-layer rule unions
Mike Kravetz (1):
hugetlb: fix huge_pmd_unshare address update
Mike Tipton (1):
interconnect: qcom: icc-rpmh: Add BCMs to commit list in pre_aggregate
Mike Travis (1):
x86/platform/uv: Update TSC sync state for UV5
Mikulas Patocka (2):
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
objtool: Fix objtool regression on x32 systems
Miles Chen (2):
drm/mediatek: Fix mtk_cec_mask()
iommu/mediatek: Fix NULL pointer dereference when printing dev_name
Mina Almasry (1):
hugetlbfs: fix hugetlbfs_statfs() locking
Minghao Chi (1):
scsi: ufs: Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
Monish Kumar R (1):
USB: new quirk for Dell Gen 2 devices
Muchun Song (1):
dax: fix cache flush on PMD-mapped pages
Namjae Jeon (1):
fs/ntfs3: Fix invalid free in log_replay
Nathan Chancellor (3):
riscv: Move alternative length validation into subsection
drm/i915: Fix CFI violation with show_dynamic_id()
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Naveen N. Rao (1):
kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
Nicholas Piggin (1):
KVM: PPC: Book3S HV Nested: L2 LPCR should inherit L1 LPES setting
Nico Boehr (1):
s390/perf: obtain sie_block from the right address
Nicolas Belin (1):
drm: bridge: it66121: Fix the register page length
Nicolas Dufresne (4):
media: hantro: Stop using H.264 parameter pic_num
media: rkvdec: h264: Fix dpb_valid implementation
media: coda: Fix reported H264 profile
media: coda: Add more H264 levels for CODA960
Nicolas Frattaroli (1):
ASoC: rk3328: fix disabling mclk on pclk probe failure
Niels Dossche (6):
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
ipv6: fix locking issues with loops over idev->addr_list
IB/rdmavt: add missing locks in rvt_ruc_loopback
ath11k: acquire ab->base_lock in unassign when finding the peer by addr
Bluetooth: use hdev lock in activate_scan for hci_is_adv_monitoring
Bluetooth: use hdev lock for accept_list and reject_list in conn req
Nikita Yushchenko (1):
drm/bridge_connector: enable HPD by default if supported
Niklas Cassel (1):
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
Niklas Söderlund (1):
media: i2c: max9286: Use dev_err_probe() helper
Nikolay Borisov (1):
selftests/bpf: Fix vfs_link kprobe definition
Noralf Trønnes (1):
dt-bindings: display: sitronix, st7735r: Fix backlight in example
Nuno Sá (1):
of: overlay: do not break notify on NOTIFY_{OK|STOP}
Nícolas F. R. A. Prado (2):
regulator: mt6315: Enforce regulator-compatible, not name
drm/mediatek: dpi: Use mt8183 output formats for mt8192
OGAWA Hirofumi (1):
fat: add ratelimit to fat*_ent_bread()
Olga Kornievskaia (1):
NFSv4.1 mark qualified async operations as MOVEABLE tasks
Padmanabha Srinivasaiah (1):
rcu-tasks: Fix race in schedule and flush work
Pali Rohár (1):
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Paolo Abeni (1):
mptcp: reset the packet scheduler on PRIO change
Patrice Chotard (1):
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Paul E. McKenney (2):
rcu: Make TASKS_RUDE_RCU select IRQ_WORK
scftorture: Fix distribution of short handler delays
Pavel Skripkin (1):
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Peng Wu (3):
ARM: versatile: Add missing of_node_put in dcscb_init
ARM: hisi: Add missing of_node_put after of_find_compatible_node
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Peter Seiderer (1):
mac80211: minstrel_ht: fix where rate stats are stored (fixes debugfs output)
Peter Zijlstra (1):
objtool: Fix symbol creation
Petr Machata (2):
mlxsw: spectrum_dcb: Do not warn about priority changes
mlxsw: Treat LLDP packets as control
Phil Auld (1):
kselftest/cgroup: fix test_stress.sh to use OUTPUT dir
Phil Elwell (3):
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Philipp Zabel (1):
media: coda: limit frame interval enumeration to supported encoder frame sizes
Pierre Gondois (1):
ACPI: CPPC: Assume no transition latency if no PCCT
Pierre-Louis Bossart (2):
ASoC: max98357a: remove dependency on GPIOLIB
ASoC: rt1015p: remove dependency on GPIOLIB
Po-Hao Huang (1):
rtw88: 8821c: fix debugfs rssi value
Qi Zheng (1):
tty: fix deadlock caused by calling printk() under tty_port->lock
QintaoShen (2):
soc: ti: ti_sci_pm_domains: Check for null return of devm_kcalloc
soc: bcm: Check for NULL return of devm_kzalloc()
Qu Wenruo (4):
btrfs: add "0x" prefix for unsupported optional features
btrfs: return correct error number for __extent_writepage_io()
btrfs: repair super block num_devices automatically
btrfs: fix the error handling for submit_extent_page() for btrfs_do_readpage()
Quentin Monnet (1):
selftests/bpf: Fix parsing of prog types in UAPI hdr for bpftool sync
Rafał Miłecki (2):
ARM: dts: BCM5301X: update CRU block description
ARM: dts: BCM5301X: Update pin controller node name
Randy Dunlap (7):
x86: Fix return value of __setup handlers
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
net: dsa: restrict SMSC_LAN9303_I2C kconfig
powerpc/8xx: export 'cpm_setbrg' for modules
powerpc/idle: Fix return value of __setup() handler
powerpc/4xx/cpm: Fix return value of __setup() handler
macintosh: via-pmu and via-cuda need RTC_LIB
Ravi Bangoria (2):
perf/amd/ibs: Cascade pmu init functions' return value
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Rei Yamamoto (1):
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Rex-BC Chen (1):
cpufreq: mediatek: Unregister platform device on exit
Rik van der Kemp (1):
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9520 laptop
Robert Marko (2):
arm64: dts: marvell: espressobin-ultra: fix SPI-NOR config
arm64: dts: marvell: espressobin-ultra: enable front USB3 port
Robin Murphy (1):
dma-direct: don't over-decrypt memory
Ronnie Sahlberg (2):
cifs: fix potential double free during failed mount
cifs: when extending a file with falloc we should make files not-sparse
Russell King (Oracle) (1):
net: dsa: mt7530: 1G can also support 1000BASE-X link mode
Saaem Rizvi (1):
drm/amd/display: Disabling Z10 on DCN31
Sakari Ailus (1):
ACPI: property: Release subnode properties with data nodes
Samuel Holland (1):
riscv: Fix irq_work when SMP is disabled
Sathishkumar S (2):
drm/amd/pm: update smartshift powerboost calc for smu12
drm/amd/pm: update smartshift powerboost calc for smu13
Schspa Shi (1):
cpufreq: Fix possible race in cpufreq online error path
Sean Christopherson (3):
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
KVM: nVMX: Clear IDT vectoring on nested VM-Exit for double/triple fault
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
Sebastian Andrzej Siewior (1):
crypto: cryptd - Protect per-CPU resource by disabling BH.
Shawn Lin (1):
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
Smith, Kyle Miller (Nimble Kernel) (1):
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Song Liu (1):
ftrace: Clean up hash direct_functions on register failures
Stefan Wahren (4):
thermal/drivers/bcm2711: Don't clamp temperature at zero
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
gpiolib: of: Introduce hook for missing gpio-ranges
pinctrl: bcm2835: implement hook for missing gpio-ranges
Stephen Boyd (1):
interconnect: qcom: sc7180: Drop IP0 interconnects
Steve French (2):
smb3: check for null tcon
SMB3: EBADF/EIO errors in rename/open caused by race condition in smb2_compound_op
Steven Price (1):
drm/plane: Move range check for format_count earlier
Sudeep Holla (2):
firmware: arm_ffa: Fix uuid parameter to ffa_partition_probe
firmware: arm_ffa: Remove incorrect assignment of driver_data
Sven Schnelle (1):
s390/stp: clock_delta should be signed
Takashi Iwai (3):
ALSA: usb-audio: Cancel pending work at closing a MIDI substream
ALSA: usb-audio: Add quirk bits for enabling/disabling generic implicit fb
ALSA: usb-audio: Move generic implicit fb quirk entries into quirks.c
Tali Perry (2):
i2c: npcm: Fix timeout calculation
i2c: npcm: Handle spurious interrupts
Tejas Upadhyay (1):
iommu/vt-d: Add RPLS to quirk list to skip TE disabling
Tejun Heo (1):
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Tetsuo Handa (1):
media: imon: reorganize serialization
Theodore Ts'o (1):
ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state
Thibaut VARÈNE (1):
ath9k: fix QCA9561 PA bias level
Thorsten Scherer (1):
ARM: dts: ci4x10: Adapt to changes in imx6qdl.dtsi regarding fec clocks
Tobias Klauser (1):
riscv: Wire up memfd_secret in UAPI header
Tokunori Ikegami (2):
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Tong Tiangen (1):
arm64: fix types in copy_highpage()
Trond Myklebust (9):
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
NFS: fsync() should report filesystem errors over EINTR/ERESTARTSYS
NFS: Don't report ENOSPC write errors twice
NFS: Do not report flush errors in nfs_write_end()
NFS: Don't report errors from nfs_pageio_complete() more than once
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
NFS: Further fixes to the writeback error handling
NFS: Always initialise fattr->label in nfs_fattr_alloc()
NFS: Convert GFP_NOFS to GFP_KERNEL
Tyler Hicks (1):
EDAC/dmc520: Don't print an error for each unconfigured interrupt line
Tyrone Ting (1):
i2c: npcm: Correct register access width
Tzung-Bi Shih (1):
platform/chrome: cros_ec: fix error handling in cros_ec_register()
Ulf Hansson (2):
cpuidle: PSCI: Improve support for suspend-to-RAM for PSCI OSI mode
PM: domains: Fix initialization of genpd's next_wakeup
Uwe Kleine-König (1):
char: tpm: cr50_i2c: Suppress duplicated error message in .remove()
Vasily Averin (1):
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
Vignesh Raghavendra (1):
drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit
Vincent Mailhol (1):
can: mcp251xfd: silence clang's -Wunaligned-access warning
Vincent Whitchurch (1):
um: Fix out-of-bounds read in LDT setup
Vinod Koul (1):
arm64: dts: qcom: qrb5165-rb5: Fix can-clock node name
Vinod Polimera (1):
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
Viresh Kumar (2):
cpufreq: Avoid unnecessary frequency updates due to mismatch
Revert "cpufreq: Fix possible race in cpufreq online error path"
Waiman Long (2):
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
kseltest/cgroup: Make test_stress.sh work if run interactively
Wanpeng Li (1):
KVM: LAPIC: Drop pending LAPIC timer injection when canceling the timer
Wei Yongjun (1):
regulator: da9121: Fix uninit-value in da9121_assign_chip_model()
Wenli Looi (1):
ath9k: fix ar9003_get_eepmisc
Xianting Tian (1):
RISC-V: Mark IORESOURCE_EXCLUSIVE for reserved mem instead of IORESOURCE_BUSY
Xiao Ni (2):
md: Don't set mddev private to NULL in raid0 pers->free
md: fix double free of io_acct_set bioset
Xiao Yang (1):
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Xiaoguang Wang (1):
scsi: target: tcmu: Fix possible data corruption
Xiaomeng Tong (11):
media: uvcvideo: Fix missing check to determine if element is found in list
scsi: dc395x: Fix a missing check on list iterator
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator
md: fix an incorrect NULL check in does_sb_need_changing
md: fix an incorrect NULL check in md_reload_sb
iommu/msm: Fix an incorrect NULL check on list iterator
carl9170: tx: fix an incorrect use of list iterator
stm: ltdc: fix two incorrect NULL checks on list iterator
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
gma500: fix an incorrect NULL check on list iterator
Xie Yongji (1):
nbd: Fix hung on disconnect request if socket is closed before
Yang Jihong (1):
perf tools: Add missing headers needed by util/data.h
Yang Yingliang (12):
pinctrl: renesas: rzn1: Fix possible null-ptr-deref in sh_pfc_map_resources()
mtd: rawnand: cadence: fix possible null-ptr-deref in cadence_nand_dt_probe()
mtd: rawnand: intel: fix possible null-ptr-deref in ebu_nand_probe()
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
spi: spi-fsl-qspi: check return value after calling platform_get_resource_byname()
media: i2c: ov5648: fix wrong pointer passed to IS_ERR() and PTR_ERR()
thermal/core: Fix memory leak in __thermal_cooling_device_register()
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
pinctrl: renesas: core: Fix possible null-ptr-deref in sh_pfc_map_resources()
hwrng: omap3-rom - fix using wrong clk_disable() in omap_rom_rng_runtime_resume()
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
Yangyang Li (1):
RDMA/hns: Add the detection for CMDQ status in the device initialization process
Ye Bin (3):
ext4: fix use-after-free in ext4_rename_dir_prepare
ext4: fix warning in ext4_handle_inode_extension
ext4: fix bug_on in ext4_writepages
Yi Yang (1):
xtensa/simdisk: fix proc_read_simdisk()
Yicong Yang (1):
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Ying Hsu (1):
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Yixing Liu (1):
RDMA/hns: Remove the num_cqc_timer variable
Yong Wu (4):
iommu/mediatek: Fix 2 HW sharing pgtable issue
iommu/mediatek: Add list_del in mtk_iommu_remove
iommu/mediatek: Remove clk_disable in mtk_iommu_remove
iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
Yonghong Song (1):
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Yongzhi Liu (1):
hv_netvsc: Fix potential dereference of NULL pointer
Yuanchu Xie (1):
selftests/damon: add damon to selftests root Makefile
Yunfei Wang (1):
iommu/dma: Fix iova map result check bug
Zack Rusin (2):
drm/vmwgfx: validate the screen formats
drm/vmwgfx: Fix an invalid read
Zev Weiss (1):
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Zhen Lei (1):
of: Support more than one crash kernel regions for kexec -s
Zheng Bin (1):
net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init
Zheng Yongjun (2):
spi: img-spfi: Fix pm_runtime_get_sync() error checking
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
Zhengjun Xing (1):
perf jevents: Fix event syntax error caused by ExtSel
Zheyu Ma (3):
media: pci: cx23885: Fix the error handling in cx23885_initdev()
media: cx25821: Fix the warning when removing the module
mtd: rawnand: denali: Use managed device resources
Zhihao Cheng (1):
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
Zhou Qingyang (1):
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Zixuan Fu (1):
fs: jfs: fix possible NULL pointer dereference in dbFree()
jianghaoran (1):
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
liuyacan (1):
net/smc: postpone sk_refcnt increment in connect()
^ permalink raw reply [relevance 1%]
* Linux 5.10.121
@ 2022-06-09 8:38 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-09 8:38 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.10.121 kernel.
All users of the 5.10 kernel series must upgrade.
The updated 5.10.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.10.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/conf.py | 2
Documentation/devicetree/bindings/display/sitronix,st7735r.yaml | 1
Documentation/devicetree/bindings/gpio/gpio-altera.txt | 5
Documentation/devicetree/bindings/spi/qcom,spi-qcom-qspi.yaml | 1
Makefile | 2
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 6
arch/arm/boot/dts/imx6qdl-colibri.dtsi | 6
arch/arm/boot/dts/ox820.dtsi | 2
arch/arm/boot/dts/s5pv210-aries.dtsi | 3
arch/arm/boot/dts/s5pv210.dtsi | 12
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 1
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4
arch/arm/mach-hisi/platsmp.c | 4
arch/arm/mach-mediatek/Kconfig | 1
arch/arm/mach-omap1/clock.c | 2
arch/arm/mach-pxa/cm-x300.c | 8
arch/arm/mach-pxa/magician.c | 2
arch/arm/mach-pxa/tosa.c | 4
arch/arm/mach-vexpress/dcscb.c | 1
arch/arm64/Kconfig.platforms | 1
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2
arch/arm64/boot/dts/qcom/msm8994.dtsi | 4
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2
arch/arm64/kernel/sys_compat.c | 2
arch/arm64/mm/copypage.c | 4
arch/csky/kernel/probes/kprobes.c | 2
arch/m68k/Kconfig.cpu | 2
arch/m68k/include/asm/raw_io.h | 6
arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h | 1
arch/mips/include/asm/mach-ip30/cpu-feature-overrides.h | 1
arch/openrisc/include/asm/timex.h | 1
arch/openrisc/kernel/head.S | 9
arch/parisc/include/asm/fb.h | 4
arch/powerpc/include/asm/page.h | 7
arch/powerpc/include/asm/vas.h | 2
arch/powerpc/kernel/fadump.c | 8
arch/powerpc/kernel/idle.c | 2
arch/powerpc/perf/isa207-common.c | 3
arch/powerpc/platforms/4xx/cpm.c | 2
arch/powerpc/platforms/8xx/cpm1.c | 1
arch/powerpc/platforms/powernv/opal-fadump.c | 94 ++--
arch/powerpc/platforms/powernv/opal-fadump.h | 10
arch/powerpc/platforms/powernv/ultravisor.c | 1
arch/powerpc/platforms/powernv/vas-fault.c | 2
arch/powerpc/platforms/powernv/vas-window.c | 4
arch/powerpc/platforms/powernv/vas.h | 2
arch/powerpc/sysdev/dart_iommu.c | 6
arch/powerpc/sysdev/fsl_rio.c | 2
arch/powerpc/sysdev/xics/icp-opal.c | 1
arch/riscv/include/asm/irq_work.h | 2
arch/riscv/kernel/head.S | 1
arch/s390/include/asm/kexec.h | 10
arch/s390/include/asm/preempt.h | 15
arch/s390/kernel/perf_event.c | 2
arch/um/drivers/chan_user.c | 9
arch/um/include/asm/thread_info.h | 2
arch/um/kernel/exec.c | 2
arch/um/kernel/process.c | 2
arch/um/kernel/ptrace.c | 8
arch/um/kernel/signal.c | 4
arch/x86/Kconfig | 4
arch/x86/entry/entry_64.S | 1
arch/x86/entry/vdso/vma.c | 2
arch/x86/events/amd/ibs.c | 55 ++
arch/x86/events/intel/core.c | 2
arch/x86/include/asm/acenv.h | 14
arch/x86/include/asm/kexec.h | 8
arch/x86/include/asm/suspend_32.h | 2
arch/x86/include/asm/suspend_64.h | 12
arch/x86/kernel/apic/apic.c | 2
arch/x86/kernel/apic/x2apic_uv_x.c | 8
arch/x86/kernel/cpu/intel.c | 2
arch/x86/kernel/cpu/mce/amd.c | 32 -
arch/x86/kernel/step.c | 3
arch/x86/kernel/sys_x86_64.c | 7
arch/x86/kvm/vmx/nested.c | 45 +-
arch/x86/kvm/vmx/vmcs.h | 5
arch/x86/lib/delay.c | 4
arch/x86/mm/pat/memtype.c | 2
arch/x86/um/ldt.c | 6
arch/xtensa/kernel/ptrace.c | 4
arch/xtensa/kernel/signal.c | 4
arch/xtensa/platforms/iss/simdisk.c | 18
block/bfq-cgroup.c | 111 +++--
block/bfq-iosched.c | 46 +-
block/bfq-iosched.h | 6
block/blk-cgroup.c | 8
block/blk-iolatency.c | 122 ++---
crypto/cryptd.c | 23 -
drivers/acpi/property.c | 18
drivers/acpi/sleep.c | 12
drivers/base/memory.c | 5
drivers/base/node.c | 1
drivers/block/drbd/drbd_main.c | 11
drivers/block/nbd.c | 13
drivers/block/virtio_blk.c | 7
drivers/char/hw_random/omap3-rom-rng.c | 2
drivers/char/ipmi/ipmi_msghandler.c | 4
drivers/char/ipmi/ipmi_ssif.c | 23 +
drivers/char/random.c | 12
drivers/cpufreq/mediatek-cpufreq.c | 19
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c | 115 +++--
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 30 -
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c | 10
drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 14
drivers/crypto/ccree/cc_buffer_mgr.c | 27 -
drivers/crypto/marvell/cesa/cipher.c | 1
drivers/crypto/nx/nx-common-powernv.c | 2
drivers/devfreq/rk3399_dmc.c | 2
drivers/dma/idxd/cdev.c | 8
drivers/dma/stm32-mdma.c | 87 +--
drivers/edac/dmc520_edac.c | 2
drivers/firmware/arm_scmi/base.c | 2
drivers/gpio/gpiolib-of.c | 5
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3
drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 14
drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 8
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10
drivers/gpu/drm/arm/malidp_crtc.c | 5
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31 +
drivers/gpu/drm/drm_edid.c | 6
drivers/gpu/drm/drm_plane.c | 14
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6
drivers/gpu/drm/gma500/psb_intel_display.c | 7
drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 33 -
drivers/gpu/drm/i915/i915_perf.c | 4
drivers/gpu/drm/i915/i915_perf_types.h | 2
drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 61 ++
drivers/gpu/drm/mediatek/mtk_cec.c | 2
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 1
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20
drivers/gpu/drm/msm/dp/dp_display.c | 55 +-
drivers/gpu/drm/msm/dsi/dsi_host.c | 21
drivers/gpu/drm/msm/hdmi/hdmi.c | 10
drivers/gpu/drm/msm/msm_drv.c | 1
drivers/gpu/drm/msm/msm_gem_prime.c | 2
drivers/gpu/drm/nouveau/dispnv50/atom.h | 6
drivers/gpu/drm/nouveau/dispnv50/crc.c | 27 -
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6
drivers/gpu/drm/panel/panel-simple.c | 3
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2
drivers/gpu/drm/stm/ltdc.c | 16
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8
drivers/gpu/drm/vc4/vc4_hvs.c | 26 -
drivers/gpu/drm/vc4/vc4_txp.c | 8
drivers/gpu/drm/virtio/virtgpu_display.c | 2
drivers/hid/hid-bigbenff.c | 6
drivers/hid/hid-elan.c | 2
drivers/hid/hid-led.c | 2
drivers/hwtracing/coresight/coresight-core.c | 33 -
drivers/i2c/busses/i2c-at91-master.c | 11
drivers/i2c/busses/i2c-npcm7xx.c | 103 +++-
drivers/i2c/busses/i2c-rcar.c | 15
drivers/infiniband/hw/hfi1/file_ops.c | 2
drivers/infiniband/hw/hfi1/init.c | 2
drivers/infiniband/hw/hfi1/sdma.c | 12
drivers/infiniband/sw/rdmavt/qp.c | 6
drivers/infiniband/sw/rxe/rxe_req.c | 2
drivers/input/misc/sparcspkr.c | 1
drivers/input/touchscreen/stmfts.c | 16
drivers/iommu/amd/init.c | 2
drivers/iommu/intel/iommu.c | 2
drivers/iommu/msm_iommu.c | 11
drivers/iommu/mtk_iommu.c | 3
drivers/irqchip/irq-armada-370-xp.c | 11
drivers/irqchip/irq-aspeed-i2c-ic.c | 4
drivers/irqchip/irq-aspeed-scu-ic.c | 4
drivers/irqchip/irq-sni-exiu.c | 25 -
drivers/irqchip/irq-xtensa-mx.c | 18
drivers/macintosh/Kconfig | 6
drivers/macintosh/Makefile | 3
drivers/macintosh/via-pmu.c | 2
drivers/mailbox/mailbox.c | 19
drivers/md/bcache/btree.c | 58 +-
drivers/md/bcache/btree.h | 2
drivers/md/bcache/journal.c | 31 +
drivers/md/bcache/journal.h | 2
drivers/md/bcache/request.c | 6
drivers/md/bcache/super.c | 1
drivers/md/bcache/writeback.c | 101 +---
drivers/md/bcache/writeback.h | 2
drivers/md/md-bitmap.c | 44 +
drivers/md/md.c | 18
drivers/media/cec/core/cec-adap.c | 6
drivers/media/i2c/ov7670.c | 1
drivers/media/pci/cx23885/cx23885-core.c | 6
drivers/media/pci/cx25821/cx25821-core.c | 2
drivers/media/platform/aspeed-video.c | 4
drivers/media/platform/coda/coda-common.c | 35 +
drivers/media/platform/exynos4-is/fimc-is.c | 6
drivers/media/platform/exynos4-is/fimc-isp-video.h | 2
drivers/media/platform/qcom/venus/hfi.c | 3
drivers/media/platform/rockchip/rga/rga.c | 6
drivers/media/platform/sti/delta/delta-v4l2.c | 6
drivers/media/platform/vsp1/vsp1_rpf.c | 6
drivers/media/rc/imon.c | 99 ++--
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7
drivers/media/usb/uvc/uvc_v4l2.c | 20
drivers/memory/samsung/exynos5422-dmc.c | 5
drivers/mfd/davinci_voicecodec.c | 6
drivers/mfd/ipaq-micro.c | 2
drivers/misc/ocxl/file.c | 2
drivers/mmc/host/jz4740_mmc.c | 20
drivers/mmc/host/sdhci_am654.c | 23 -
drivers/mtd/chips/cfi_cmdset_0002.c | 103 ++--
drivers/mtd/nand/raw/cadence-nand-controller.c | 5
drivers/mtd/nand/raw/denali_pci.c | 15
drivers/mtd/spi-nor/core.c | 9
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 2
drivers/net/can/xilinx_can.c | 4
drivers/net/dsa/mt7530.c | 14
drivers/net/ethernet/broadcom/Makefile | 5
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c | 2
drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 5
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 10
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 5
drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 9
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 2
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 23 -
drivers/net/ethernet/huawei/hinic/hinic_main.c | 10
drivers/net/ethernet/huawei/hinic/hinic_tx.c | 9
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 2
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13
drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c | 2
drivers/net/ethernet/sfc/ef10.c | 2
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | 15
drivers/net/hyperv/netvsc_drv.c | 5
drivers/net/ipa/ipa_endpoint.c | 4
drivers/net/phy/micrel.c | 11
drivers/net/wireguard/socket.c | 4
drivers/net/wireless/ath/ath10k/mac.c | 20
drivers/net/wireless/ath/ath11k/mac.c | 16
drivers/net/wireless/ath/ath11k/spectral.c | 17
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8
drivers/net/wireless/ath/carl9170/tx.c | 3
drivers/net/wireless/broadcom/b43/phy_n.c | 2
drivers/net/wireless/broadcom/b43legacy/phy.c | 2
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3
drivers/net/wireless/marvell/mwifiex/11h.c | 2
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8
drivers/net/wireless/realtek/rtlwifi/usb.c | 2
drivers/nfc/st21nfca/se.c | 17
drivers/nfc/st21nfca/st21nfca.h | 1
drivers/nvdimm/core.c | 9
drivers/nvdimm/security.c | 5
drivers/nvme/host/core.c | 2
drivers/nvme/host/pci.c | 1
drivers/of/overlay.c | 4
drivers/opp/of.c | 2
drivers/pci/controller/cadence/pcie-cadence-ep.c | 3
drivers/pci/controller/dwc/pci-imx6.c | 23 -
drivers/pci/controller/dwc/pcie-designware-host.c | 3
drivers/pci/controller/dwc/pcie-qcom.c | 9
drivers/pci/controller/pcie-rockchip-ep.c | 3
drivers/pci/pci.c | 12
drivers/pci/pcie/aer.c | 7
drivers/phy/qualcomm/phy-qcom-qmp.c | 11
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 18
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2
drivers/pinctrl/renesas/core.c | 7
drivers/pinctrl/renesas/pinctrl-rzn1.c | 10
drivers/platform/chrome/cros_ec.c | 16
drivers/platform/chrome/cros_ec_chardev.c | 2
drivers/platform/chrome/cros_ec_proto.c | 50 +-
drivers/platform/mips/cpu_hwmon.c | 127 +----
drivers/regulator/core.c | 7
drivers/regulator/pfuze100-regulator.c | 2
drivers/regulator/qcom_smd-regulator.c | 35 -
drivers/scsi/dc395x.c | 15
drivers/scsi/fcoe/fcoe_ctlr.c | 2
drivers/scsi/lpfc/lpfc_sli.c | 6
drivers/scsi/megaraid.c | 2
drivers/scsi/ufs/ti-j721e-ufs.c | 6
drivers/scsi/ufs/ufs-qcom.c | 14
drivers/scsi/ufs/ufshcd.c | 7
drivers/soc/qcom/llcc-qcom.c | 1
drivers/soc/qcom/smp2p.c | 1
drivers/soc/qcom/smsm.c | 1
drivers/soc/ti/ti_sci_pm_domains.c | 2
drivers/spi/spi-fsl-qspi.c | 4
drivers/spi/spi-img-spfi.c | 2
drivers/spi/spi-rspi.c | 15
drivers/spi/spi-stm32-qspi.c | 3
drivers/spi/spi-ti-qspi.c | 5
drivers/staging/media/hantro/hantro_v4l2.c | 8
drivers/staging/media/rkvdec/rkvdec-h264.c | 37 +
drivers/staging/media/rkvdec/rkvdec.c | 4
drivers/target/target_core_device.c | 1
drivers/thermal/broadcom/bcm2711_thermal.c | 5
drivers/thermal/broadcom/sr-thermal.c | 3
drivers/thermal/imx_sc_thermal.c | 6
drivers/thermal/thermal_core.c | 42 +
drivers/tty/serial/pch_uart.c | 27 -
drivers/tty/tty_buffer.c | 3
drivers/usb/core/hcd.c | 29 +
drivers/usb/core/quirks.c | 3
drivers/usb/dwc3/gadget.c | 6
drivers/usb/host/xhci-pci.c | 2
drivers/usb/serial/option.c | 2
drivers/vdpa/vdpa_sim/vdpa_sim.c | 5
drivers/video/console/sticon.c | 5
drivers/video/console/sticore.c | 32 +
drivers/video/fbdev/amba-clcd.c | 5
drivers/video/fbdev/core/fbcon.c | 5
drivers/video/fbdev/sticore.h | 3
drivers/video/fbdev/stifb.c | 4
fs/afs/rxrpc.c | 8
fs/binfmt_flat.c | 27 +
fs/btrfs/disk-io.c | 4
fs/btrfs/volumes.c | 8
fs/cifs/smb2inode.c | 2
fs/cifs/smb2ops.c | 2
fs/dax.c | 3
fs/dlm/lock.c | 11
fs/dlm/plock.c | 12
fs/ext4/ext4.h | 6
fs/ext4/extents.c | 10
fs/ext4/inline.c | 12
fs/ext4/inode.c | 4
fs/ext4/namei.c | 84 +++
fs/ext4/super.c | 24 -
fs/f2fs/f2fs.h | 19
fs/f2fs/file.c | 20
fs/f2fs/inline.c | 29 +
fs/f2fs/inode.c | 19
fs/f2fs/segment.c | 42 +
fs/f2fs/segment.h | 33 -
fs/f2fs/super.c | 6
fs/fat/fatent.c | 7
fs/fs-writeback.c | 13
fs/gfs2/quota.c | 32 -
fs/iomap/buffered-io.c | 3
fs/jfs/jfs_dmap.c | 3
fs/nfs/file.c | 16
fs/nfs/pnfs.c | 2
fs/nfs/write.c | 11
fs/notify/fdinfo.c | 11
fs/notify/inotify/inotify.h | 12
fs/notify/inotify/inotify_user.c | 2
fs/notify/mark.c | 6
fs/ocfs2/dlmfs/userdlm.c | 16
fs/proc/generic.c | 3
fs/proc/proc_net.c | 3
fs/xfs/libxfs/xfs_btree.c | 35 -
fs/xfs/xfs_dquot.c | 39 +
fs/xfs/xfs_iomap.c | 3
fs/xfs/xfs_log.c | 28 -
fs/xfs/xfs_log.h | 1
fs/xfs/xfs_mount.c | 93 ++--
fs/xfs/xfs_qm.c | 92 +---
fs/xfs/xfs_symlink.c | 1
include/drm/drm_edid.h | 6
include/linux/bpf.h | 2
include/linux/efi.h | 2
include/linux/font.h | 2
include/linux/gpio/driver.h | 12
include/linux/kexec.h | 46 +-
include/linux/lsm_hook_defs.h | 4
include/linux/lsm_hooks.h | 2
include/linux/mailbox_controller.h | 1
include/linux/mtd/cfi.h | 1
include/linux/nodemask.h | 13
include/linux/platform_data/cros_ec_proto.h | 3
include/linux/ptrace.h | 7
include/linux/security.h | 23 -
include/linux/thermal.h | 2
include/linux/usb/hcd.h | 2
include/net/bluetooth/hci.h | 16
include/net/bluetooth/hci_core.h | 18
include/net/flow.h | 10
include/net/if_inet6.h | 8
include/net/route.h | 6
include/scsi/libfcoe.h | 3
include/sound/jack.h | 1
include/trace/events/rxrpc.h | 2
include/trace/events/vmscan.h | 4
init/Kconfig | 5
ipc/mqueue.c | 14
kernel/bpf/stackmap.c | 1
kernel/dma/debug.c | 2
kernel/kexec_file.c | 34 -
kernel/ptrace.c | 5
kernel/rcu/Kconfig | 1
kernel/rcu/tasks.h | 3
kernel/scftorture.c | 5
kernel/sched/fair.c | 8
kernel/sched/pelt.h | 4
kernel/sched/sched.h | 4
kernel/trace/ftrace.c | 5
kernel/trace/trace_events_hist.c | 3
mm/compaction.c | 2
mm/hugetlb.c | 9
net/bluetooth/hci_conn.c | 8
net/bluetooth/hci_core.c | 27 -
net/bluetooth/hci_debugfs.c | 8
net/bluetooth/hci_event.c | 91 ++--
net/bluetooth/hci_request.c | 221 +++++++---
net/bluetooth/hci_sock.c | 12
net/bluetooth/l2cap_core.c | 10
net/bluetooth/mgmt.c | 14
net/bluetooth/mgmt_config.c | 10
net/bluetooth/sco.c | 21
net/bluetooth/smp.c | 6
net/core/dev.c | 8
net/dccp/ipv4.c | 2
net/dccp/ipv6.c | 6
net/ipv4/icmp.c | 4
net/ipv4/inet_connection_sock.c | 4
net/ipv4/ip_output.c | 2
net/ipv4/ping.c | 2
net/ipv4/raw.c | 2
net/ipv4/syncookies.c | 2
net/ipv4/udp.c | 2
net/ipv6/addrconf.c | 33 +
net/ipv6/af_inet6.c | 2
net/ipv6/datagram.c | 2
net/ipv6/icmp.c | 6
net/ipv6/inet6_connection_sock.c | 4
net/ipv6/netfilter/nf_reject_ipv6.c | 2
net/ipv6/ping.c | 2
net/ipv6/raw.c | 2
net/ipv6/syncookies.c | 2
net/ipv6/tcp_ipv6.c | 4
net/ipv6/udp.c | 2
net/l2tp/l2tp_ip6.c | 2
net/mac80211/chan.c | 7
net/mac80211/ieee80211_i.h | 5
net/mac80211/scan.c | 20
net/netfilter/nf_synproxy_core.c | 2
net/nfc/core.c | 1
net/rxrpc/ar-internal.h | 13
net/rxrpc/call_event.c | 7
net/rxrpc/conn_object.c | 2
net/rxrpc/input.c | 31 -
net/rxrpc/output.c | 20
net/rxrpc/recvmsg.c | 8
net/rxrpc/sendmsg.c | 6
net/rxrpc/sysctl.c | 4
net/sctp/input.c | 4
net/smc/af_smc.c | 2
net/wireless/nl80211.c | 1
net/wireless/reg.c | 4
net/xfrm/xfrm_state.c | 6
scripts/faddr2line | 150 ++++--
security/integrity/ima/Kconfig | 14
security/integrity/platform_certs/keyring_handler.h | 8
security/integrity/platform_certs/load_uefi.c | 33 +
security/security.c | 17
security/selinux/hooks.c | 4
security/selinux/include/xfrm.h | 2
security/selinux/xfrm.c | 13
sound/core/jack.c | 34 +
sound/core/pcm_memory.c | 3
sound/pci/hda/patch_realtek.c | 11
sound/soc/atmel/atmel-classd.c | 1
sound/soc/atmel/atmel-pdmic.c | 1
sound/soc/codecs/Kconfig | 2
sound/soc/codecs/max98090.c | 6
sound/soc/codecs/rk3328_codec.c | 2
sound/soc/codecs/rt5514.c | 2
sound/soc/codecs/rt5645.c | 7
sound/soc/codecs/tscs454.c | 12
sound/soc/codecs/wm2000.c | 6
sound/soc/fsl/imx-sgtl5000.c | 14
sound/soc/intel/boards/bytcr_rt5640.c | 12
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5
sound/soc/mxs/mxs-saif.c | 1
sound/soc/samsung/aries_wm8994.c | 17
sound/soc/samsung/arndale.c | 5
sound/soc/samsung/littlemill.c | 5
sound/soc/samsung/lowland.c | 5
sound/soc/samsung/odroid.c | 4
sound/soc/samsung/smdk_wm8994.c | 4
sound/soc/samsung/smdk_wm8994pcm.c | 4
sound/soc/samsung/snow.c | 9
sound/soc/samsung/speyside.c | 5
sound/soc/samsung/tm2_wm5110.c | 3
sound/soc/samsung/tobermory.c | 5
sound/soc/soc-dapm.c | 2
sound/soc/ti/j721e-evm.c | 44 +
sound/usb/midi.c | 3
tools/lib/bpf/libbpf.c | 20
tools/perf/Makefile.config | 39 +
tools/perf/builtin-c2c.c | 6
tools/perf/pmu-events/jevents.c | 2
tools/perf/util/data.h | 1
tools/power/x86/turbostat/turbostat.c | 1
tools/testing/selftests/bpf/progs/btf_dump_test_case_syntax.c | 2
tools/testing/selftests/cgroup/test_stress.sh | 2
tools/testing/selftests/resctrl/fill_buf.c | 4
510 files changed, 3860 insertions(+), 2277 deletions(-)
Abhinav Kumar (1):
drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path
Abhishek Kumar (1):
ath10k: skip ath10k_halt during suspend for driver state RESTARTING
Aditya Garg (1):
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Aidan MacDonald (1):
mmc: jz4740: Apply DMA engine limits to maximum segment size
Akira Yokosawa (1):
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Albert Wang (1):
usb: dwc3: gadget: Move null pinter check to proper place
Alex Elder (2):
net: ipa: fix page free in ipa_endpoint_trans_release()
net: ipa: fix page free in ipa_endpoint_replenish_one()
Alexander Aring (2):
dlm: fix plock invalid read
dlm: fix missing lkb refcount handling
Alexander Wetzel (1):
rtl818x: Prevent using not initialized queues
Alexandre Ghiti (1):
riscv: Initialize thread pointer before calling C functions
Alexandru Elisei (1):
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Alexey Dobriyan (1):
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
Alexey Khoroshilov (1):
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
Alice Wong (1):
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Amadeusz Sławiński (1):
ALSA: jack: Access input_dev under mutex
Amelie Delaunay (3):
dmaengine: stm32-mdma: remove GISR1 register
dmaengine: stm32-mdma: rework interrupt handler
dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler()
Amir Goldstein (2):
inotify: show inotify mask flags in proc fdinfo
fsnotify: fix wrong lockdep annotations
Ammar Faizi (2):
x86/MCE/AMD: Fix memory leak when threshold_create_bank() fails
x86/delay: Fix the wrong asm constraint in delay_loop()
Andre Przywara (1):
ARM: dts: suniv: F1C100: fix watchdog compatible
Andreas Gruenbacher (1):
iomap: iomap_write_failed fix
Andrii Nakryiko (2):
libbpf: Don't error out on CO-RE relos for overriden weak subprogs
libbpf: Fix logic for finding matching program for CO-RE relocation
Archie Pusaka (2):
Bluetooth: use inclusive language in HCI role comments
Bluetooth: use inclusive language when filtering devices
Arnd Bergmann (2):
drbd: fix duplicate array initializer
ARM: pxa: maybe fix gpio lookup tables
Baochen Qiang (1):
ath11k: Don't check arvif->is_started before sending management frames
Baokun Li (1):
ext4: fix bug_on in __es_tree_search
Bart Van Assche (1):
scsi: ufs: qcom: Fix ufs_qcom_resume()
Bhaskar Chowdhury (1):
Bluetooth: L2CAP: Rudimentary typo fixes
Biju Das (1):
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Bjorn Andersson (1):
soc: qcom: llcc: Add MODULE_DEVICE_TABLE()
Bjorn Helgaas (1):
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Björn Ardö (1):
mailbox: forward the hrtimer if not queued and under a lock
Bob Peterson (1):
gfs2: use i_lock spin_lock for inode qadata
Borislav Petkov (1):
x86/microcode: Add explicit CPU vendor dependency
Brian Foster (3):
xfs: sync lazy sb accounting on quiesce of read-only mounts
xfs: restore shutdown check in mapped write fault path
xfs: consider shutdown in bmapbt cursor delete assert
Brian Norris (2):
PM / devfreq: rk3399_dmc: Disable edev on remove()
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Cai Huoqing (1):
media: staging: media: rkvdec: Make use of the helper function devm_platform_ioremap_resource()
Carl Yin(殷张成) (1):
USB: serial: option: add Quectel BG95 modem
Chao Yu (7):
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
f2fs: fix to clear dirty inode in f2fs_evict_inode()
f2fs: fix deadloop in foreground GC
f2fs: fix to do sanity check on total_data_blocks
f2fs: fix fallocate to use file_modified to update permissions consistently
f2fs: fix to do sanity check for inline inode
Charles Keepax (3):
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
ASoC: atmel-pdmic: Remove endianness flag on pdmic component
ASoC: atmel-classd: Remove endianness flag on class d component
Chen-Tsung Hsieh (1):
mtd: spi-nor: core: Check written SR value in spi_nor_write_16bit_sr_and_check()
Chen-Yu Tsai (1):
media: hantro: Empty encoder capture buffers by default
Chengming Zhou (1):
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
Christoph Hellwig (2):
target: remove an incorrect unmap zeroes data deduction
virtio_blk: fix the discard_granularity and discard_alignment queue limits
Christophe JAILLET (5):
media: aspeed: Fix an error handling path in aspeed_video_probe()
hinic: Avoid some over memory allocation
memory: samsung: exynos5422-dmc: Avoid some over memory allocation
drivers/base/memory: fix an unlikely reference counting issue in __add_memory_block()
dmaengine: idxd: Fix the error handling path in idxd_cdev_register()
Christophe de Dinechin (1):
nodemask.h: fix compilation error with GCC12
Chuanhong Guo (1):
arm: mediatek: select arch timer for mt7629
Colin Ian King (2):
ALSA: pcm: Check for null pointer of pointer substream before dereferencing it
selftests/resctrl: Fix null pointer dereference on open failed
Coly Li (4):
bcache: improve multithreaded bch_btree_check()
bcache: improve multithreaded bch_sectors_dirty_init()
bcache: remove incremental dirty sector counting for bch_sectors_dirty_init()
bcache: avoid journal no-space deadlock by reserving 1 journal bucket
Corentin Labbe (3):
crypto: marvell/cesa - ECB does not IV
crypto: sun8i-ss - rework handling of IV
crypto: sun8i-ss - handle zero sized sg
Corey Minyard (2):
ipmi:ssif: Check for NULL msg when handling events and messages
ipmi: Fix pr_fmt to avoid compilation issues
Cristian Marussi (1):
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Dan Carpenter (5):
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
PCI: cadence: Fix find_first_zero_bit() limit
PCI: rockchip: Fix find_first_zero_bit() limit
OPP: call of_node_put() on error path in _bandwidth_supported()
Dan Williams (2):
nvdimm: Fix firmware activation deadlock scenarios
nvdimm: Allow overwrite in the presence of disabled dimms
Daniel Lezcano (2):
thermal/drivers/core: Use a char pointer for the cooling device name
thermal/core: Fix memory leak in the error path
Daniel Thompson (1):
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Daniel Vetter (1):
fbcon: Consistently protect deferred_takeover with console_lock()
Darrick J. Wong (3):
xfs: fix chown leaking delalloc quota blocks when fssetxattr fails
xfs: fix incorrect root dquot corruption error when switching group/project quota types
xfs: force log and push AIL to clear pinned inodes when aborting mount
Dave Airlie (1):
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
Dave Chinner (1):
xfs: assert in xfs_btree_del_cursor should take into account error
David Howells (7):
rxrpc: Return an error to sendmsg if call failed
rxrpc, afs: Fix selection of abort codes
rxrpc: Fix listen() setting the bar too high for the prealloc rings
rxrpc: Don't try to resend the request if we're receiving the reply
rxrpc: Fix overlapping ACK accounting
rxrpc: Don't let ack.previousPacket regress
rxrpc: Fix decision on when to generate an IDLE ACK
Dennis Dalessandro (1):
RDMA/hfi1: Fix potential integer multiplication overflow errors
Dimitri John Ledkov (1):
cfg80211: declare MODULE_FIRMWARE for regulatory.db
Dinh Nguyen (1):
dt-bindings: gpio: altera: correct interrupt-cells
Dmitry Baryshkov (2):
drm/msm/dsi: fix error checks and return values for DSI xmit functions
drm/msm: add missing include to msm_drv.c
Dmitry Torokhov (1):
Input: stmfts - do not leave device disabled in stmfts_input_open
Dongliang Mu (3):
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
rtlwifi: Use pr_warn instead of WARN_ONCE
media: ov7670: remove ov7670_power_off from ov7670_remove
Douglas Miller (2):
RDMA/hfi1: Prevent panic when SDMA is disabled
RDMA/hfi1: Prevent use of lock before it is initialized
Duoming Zhou (1):
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
Emmanuel Grumbach (1):
iwlwifi: mvm: fix assert 1F04 upon reconfig
Eric Biggers (2):
ext4: reject the 'commit' option on ext2 filesystems
ext4: only allow test_dummy_encryption when supported
Eric Dumazet (2):
net: remove two BUG() from skb_checksum_help()
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
Eric W. Biederman (3):
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Eugenio Pérez (1):
vdpasim: allow to enable a vq repeatedly
Evan Quan (1):
drm/amd/pm: fix the compile warning
Fabio Estevam (1):
net: phy: micrel: Allow probing without .driver_data
Felix Fietkau (1):
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Finn Thain (1):
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Francesco Dolcini (1):
PCI: imx6: Fix PERST# start-up sequence
GUO Zihua (1):
ima: remove the IMA_TEMPLATE Kconfig option
Geert Uytterhoeven (2):
m68k: atari: Make Atari ROM port I/O write macros return void
m68k: math-emu: Fix dependencies of math emulation support
Gilad Ben-Yossef (1):
crypto: ccree - use fine grained DMA mapping dir
Greg Kroah-Hartman (1):
Linux 5.10.121
Guenter Roeck (2):
platform/chrome: Re-introduce cros_ec_cmd_xfer and use it for ioctls
MIPS: Loongson: Use hwmon_device_register_with_groups() to register hwmon
Guo Ren (1):
csky: patch_text: Fixup last cpu should be master
Gustavo A. R. Silva (3):
net: stmmac: selftests: Use kcalloc() instead of kzalloc()
net: huawei: hinic: Use devm_kcalloc() instead of devm_kzalloc()
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
Hangyu Hua (3):
media: rga: fix possible memory leak in rga_probe
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
misc: ocxl: fix possible double free in ocxl_file_register_afu
Hans Verkuil (1):
media: cec-adap.c: fix is_configuring state
Hans de Goede (1):
ASoC: Intel: bytcr_rt5640: Add quirk for the HP Pro Tablet 408
Haowen Bai (4):
b43legacy: Fix assigning negative value to unsigned variable
b43: Fix assigning negative value to unsigned variable
ipw2x00: Fix potential NULL dereference in libipw_xmit()
sfc: ef10: Fix assigning negative value to unsigned variable
Haren Myneni (1):
powerpc/powernv/vas: Assign real address to rx_fifo in vas_rx_win_attr
Hari Bathini (2):
powerpc/fadump: Fix fadump to work with a different endian capture kernel
powerpc/fadump: fix PT_LOAD segment for boot memory area
Hari Chandrakanthan (1):
ath11k: disable spectral scan during spectral deinit
Heiko Carstens (1):
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Helge Deller (2):
parisc/stifb: Implement fb_is_primary_device()
parisc/stifb: Keep track of hardware path of graphics card
Heming Zhao (1):
md/bitmap: don't set sb values if can't pass sanity check
Howard Chung (1):
Bluetooth: Interleave with allowlist scan
Jaegeuk Kim (1):
f2fs: don't need inode lock for system hidden quota
Jagan Teki (1):
drm/panel: panel-simple: Fix proper bpc for AM-1280800N3TZQW-T00H
Jakob Koschel (1):
f2fs: fix dereference of stale list iterator after loop body
Jakub Kicinski (2):
eth: tg3: silence the GCC 12 array-bounds warning
net: stmmac: fix out-of-bounds access in a selftest
James Clark (1):
perf tools: Use Python devtools for version autodetection rather than runtime
James Smart (1):
scsi: lpfc: Fix resource leak in lpfc_sli4_send_seq_to_ulp()
Jan Kara (11):
bfq: Split shared queues on move between cgroups
bfq: Update cgroup information before merging bio
bfq: Track whether bfq_group is still online
ext4: verify dir block before splitting it
ext4: avoid cycles in directory h-tree
bfq: Avoid merging queues with different parents
bfq: Drop pointless unlock-lock pair
bfq: Remove pointless bfq_init_rq() calls
bfq: Get rid of __bio_blkcg() usage
bfq: Make sure bfqg for which we are queueing requests is online
block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
Jan Kiszka (1):
efi: Add missing prototype for efi_capsule_setup_info
Jani Nikula (2):
drm/edid: fix invalid EDID extension block filtering
drm/i915/dsi: fix VBT send packet port selection for ICL+
Janusz Krzysztofik (1):
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Jason A. Donenfeld (2):
openrisc: start CPU timer early in boot
Revert "random: use static branch for crng_ready()"
Jeffrey Mitchell (1):
xfs: set inode size after creating symlink
Jessica Zhang (2):
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jia-Ju Bai (1):
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Jia-Wei Chang (1):
cpufreq: mediatek: Use module_init and add module_exit
Jiantao Zhang (1):
PCI: dwc: Fix setting error return on MSI DMA mapping failure
Jiasheng Jiang (1):
drm: mali-dp: potential dereference of null pointer
Jiri Slaby (1):
serial: pch: don't overwrite xmit->buf[0] by x_char
Joerg Roedel (1):
iommu/amd: Increase timeout waiting for GA log enablement
Johan Hovold (4):
PCI: qcom: Fix runtime PM imbalance on probe errors
PCI: qcom: Fix unbalanced PHY init on probe errors
phy: qcom-qmp: fix struct clk leak on probe errors
phy: qcom-qmp: fix reset-controller leak on probe errors
Johannes Berg (3):
nl80211: show SSID for P2P_GO interfaces
wifi: mac80211: fix use-after-free in chanctx code
um: chan_user: Fix winch_tramp() return value
Jonas Karlman (1):
media: rkvdec: h264: Fix bit depth wrap in pps packet
Jonathan Bakker (1):
ARM: dts: s5pv210: Remove spi-cs-high on panel in Aries
Jonathan Teh (1):
HID: hid-led: fix maximum brightness for Dream Cheeky
Josh Poimboeuf (2):
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
scripts/faddr2line: Fix overlapping text section failures
Junxiao Bi via Ocfs2-devel (1):
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Kajol Jain (1):
powerpc/perf: Fix the threshold compare group constraint for power9
Kan Liang (1):
perf/x86/intel: Fix event constraints for ICL
Kathiravan T (1):
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Keita Suzuki (2):
drm/amd/pm: fix double free in si_parse_power_table()
tracing: Fix potential double free in create_var_ref()
Keith Busch (1):
nvme: set dma alignment to dword
Kirill A. Shutemov (1):
ACPICA: Avoid cache flush inside virtual machines
Kishon Vijay Abraham I (1):
usb: core: hcd: Add support for deferring roothub registration
Kiwoong Kim (1):
scsi: ufs: core: Exclude UECxx from SFR dump list
Konrad Dybcio (2):
arm64: dts: qcom: msm8994: Fix BLSP[12]_DMA channels count
regulator: qcom_smd: Fix up PM8950 regulator configuration
Krzysztof Kozlowski (6):
ARM: dts: ox820: align interrupt controller node name with dtschema
ARM: dts: s5pv210: align DMA channels with dtschema
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
irqchip/aspeed-scu-ic: Fix irq_of_parse_and_map() return value
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
Kuldeep Singh (1):
spi: qcom-qspi: Add minItems to interconnect-names
Kuninori Morimoto (2):
ASoC: samsung: Use dev_err_probe() helper
i2c: rcar: fix PM ref counts in probe error paths
Kuogee Hsieh (3):
drm/msm/dpu: adjust display_v_end for eDP and DP
drm/msm/dp: stop event kernel thread when DP unbind
drm/msm/dp: fix event thread stuck in wait_event after kthread_stop()
Kuppuswamy Sathyanarayanan (1):
PCI/AER: Clear MULTI_ERR_COR/UNCOR_RCV bits
Kwanghoon Son (1):
media: exynos4-is: Fix compile warning
Lai Jiangshan (1):
x86/sev: Annotate stack change in the #VC handler
Len Brown (1):
tools/power turbostat: fix ICX DRAM power numbers
Leo Yan (1):
perf c2c: Use stdio interface if slang is not supported
Lin Ma (2):
ASoC: rt5645: Fix errorenous cleanup order
NFC: NULL out the dev->rfkill to prevent UAF
Linus Torvalds (1):
drm: fix EDID struct for old ARM OABI format
Liu Zixian (1):
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Liviu Dudau (1):
drm/komeda: return early if drm_universal_plane_init() fails.
Luca Weiss (1):
media: venus: hfi: avoid null dereference in deinit
Lucas Stach (2):
drm/bridge: adv7511: clean up CEC adapter when probe fails
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Lv Ruyi (7):
scsi: megaraid: Fix error check return value of register_chrdev()
drm: msm: fix error check return value of irq_of_parse_and_map()
powerpc/xics: fix refcount leak in icp_opal_init()
powerpc/powernv: fix missing of_node_put in uv_init()
drm/msm/dp: fix error check return value of irq_of_parse_and_map()
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
Maciej W. Rozycki (2):
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
MIPS: IP30: Remove incorrect `cpu_has_fpu' override
Manivannan Sadhasivam (1):
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Mao Jinlong (1):
coresight: core: Fix coresight device probe failure issue
Marc Kleine-Budde (1):
can: xilinx_can: mark bit timing constants as const
Marek Vasut (2):
drm/panel: simple: Add missing bus flags for Innolux G070Y2-L01
ARM: dts: stm32: Fix PHY post-reset delay on Avenger96
Mario Limonciello (1):
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
Marios Levogiannis (1):
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Mark Bloch (1):
net/mlx5: fs, delete the FTE when there are no rules attached to it
Mark Brown (2):
ASoC: dapm: Don't fold register value changes into notifications
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Mathias Nyman (1):
xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI
Matthieu Baerts (1):
x86/pm: Fix false positive kmemleak report in msr_build_context()
Max Filippov (1):
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Max Krummenacher (1):
ARM: dts: imx6dl-colibri: Fix I2C pinmuxing
Maxime Ripard (3):
drm/vc4: hvs: Reset muxes at probe time
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Miaohe Lin (1):
drivers/base/node.c: fix compaction sysfs file leak
Miaoqian Lin (20):
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
HID: elan: Fix potential double free in elan_input_configured
drm/bridge: Fix error handling in analogix_dp_probe
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
ASoC: samsung: Fix refcount leak in aries_audio_probe
media: exynos4-is: Fix PM disable depth imbalance in fimc_is_probe
media: st-delta: Fix PM disable depth imbalance in delta_probe
media: exynos4-is: Change clk_disable to clk_disable_unprepare
ASoC: ti: j721e-evm: Fix refcount leak in j721e_soc_probe_*
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
thermal/drivers/imx_sc_thermal: Fix refcount leak in imx_sc_thermal_probe
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
Input: sparcspkr - fix refcount leak in bbc_beep_probe
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
Michael Ellerman (1):
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
Michael Rodin (1):
media: vsp1: Fix offset calculation for plane cropping
Michael Walle (1):
i2c: at91: use dma safe buffers
Mike Kravetz (1):
hugetlb: fix huge_pmd_unshare address update
Mike Travis (1):
x86/platform/uv: Update TSC sync state for UV5
Mikulas Patocka (1):
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
Miles Chen (1):
drm/mediatek: Fix mtk_cec_mask()
Minghao Chi (1):
scsi: ufs: Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
Monish Kumar R (1):
USB: new quirk for Dell Gen 2 devices
Muchun Song (1):
dax: fix cache flush on PMD-mapped pages
Nathan Chancellor (2):
drm/i915: Fix CFI violation with show_dynamic_id()
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Naveen N. Rao (1):
kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
Nico Boehr (1):
s390/perf: obtain sie_block from the right address
Nicolas Dufresne (3):
media: rkvdec: h264: Fix dpb_valid implementation
media: coda: Fix reported H264 profile
media: coda: Add more H264 levels for CODA960
Nicolas Frattaroli (1):
ASoC: rk3328: fix disabling mclk on pclk probe failure
Niels Dossche (5):
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
ipv6: fix locking issues with loops over idev->addr_list
IB/rdmavt: add missing locks in rvt_ruc_loopback
ath11k: acquire ab->base_lock in unassign when finding the peer by addr
Bluetooth: use hdev lock for accept_list and reject_list in conn req
Niklas Cassel (1):
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
Noralf Trønnes (1):
dt-bindings: display: sitronix, st7735r: Fix backlight in example
Nuno Sá (1):
of: overlay: do not break notify on NOTIFY_{OK|STOP}
OGAWA Hirofumi (1):
fat: add ratelimit to fat*_ent_bread()
Padmanabha Srinivasaiah (1):
rcu-tasks: Fix race in schedule and flush work
Pali Rohár (1):
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Patrice Chotard (1):
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Paul Cercueil (1):
drm/ingenic: Reset pixclock rate when parent clock rate changes
Paul E. McKenney (2):
rcu: Make TASKS_RUDE_RCU select IRQ_WORK
scftorture: Fix distribution of short handler delays
Paul Moore (1):
lsm,selinux: pass flowi_common instead of flowi to the LSM hooks
Pavel Skripkin (1):
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Peilin Ye (1):
Fonts: Make font size unsigned in font_desc
Peng Wu (3):
ARM: versatile: Add missing of_node_put in dcscb_init
ARM: hisi: Add missing of_node_put after of_find_compatible_node
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Petr Machata (2):
mlxsw: spectrum_dcb: Do not warn about priority changes
mlxsw: Treat LLDP packets as control
Phil Auld (1):
kselftest/cgroup: fix test_stress.sh to use OUTPUT dir
Phil Elwell (3):
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Philipp Zabel (1):
media: coda: limit frame interval enumeration to supported encoder frame sizes
Pierre-Louis Bossart (2):
ASoC: max98357a: remove dependency on GPIOLIB
ASoC: rt1015p: remove dependency on GPIOLIB
Qi Zheng (1):
tty: fix deadlock caused by calling printk() under tty_port->lock
Qinglang Miao (1):
cpufreq: mediatek: add missing platform_driver_unregister() on error in mtk_cpufreq_driver_init
QintaoShen (1):
soc: ti: ti_sci_pm_domains: Check for null return of devm_kcalloc
Qu Wenruo (2):
btrfs: add "0x" prefix for unsupported optional features
btrfs: repair super block num_devices automatically
Randy Dunlap (6):
x86: Fix return value of __setup handlers
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
powerpc/8xx: export 'cpm_setbrg' for modules
powerpc/idle: Fix return value of __setup() handler
powerpc/4xx/cpm: Fix return value of __setup() handler
macintosh: via-pmu and via-cuda need RTC_LIB
Ravi Bangoria (2):
perf/amd/ibs: Cascade pmu init functions' return value
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Rei Yamamoto (1):
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Rex-BC Chen (1):
cpufreq: mediatek: Unregister platform device on exit
Rik van der Kemp (1):
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9520 laptop
Ronnie Sahlberg (1):
cifs: when extending a file with falloc we should make files not-sparse
Russell King (Oracle) (1):
net: dsa: mt7530: 1G can also support 1000BASE-X link mode
Sakari Ailus (1):
ACPI: property: Release subnode properties with data nodes
Samuel Holland (1):
riscv: Fix irq_work when SMP is disabled
Sathish Narasimman (1):
Bluetooth: LL privacy allow RPA
Schspa Shi (1):
cpufreq: Fix possible race in cpufreq online error path
Sean Christopherson (3):
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
KVM: nVMX: Clear IDT vectoring on nested VM-Exit for double/triple fault
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
Sebastian Andrzej Siewior (1):
crypto: cryptd - Protect per-CPU resource by disabling BH.
Shawn Lin (1):
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
Smith, Kyle Miller (Nimble Kernel) (1):
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Song Liu (1):
ftrace: Clean up hash direct_functions on register failures
Stefan Wahren (4):
thermal/drivers/bcm2711: Don't clamp temperature at zero
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
gpiolib: of: Introduce hook for missing gpio-ranges
pinctrl: bcm2835: implement hook for missing gpio-ranges
Steve French (1):
SMB3: EBADF/EIO errors in rename/open caused by race condition in smb2_compound_op
Steven Price (1):
drm/plane: Move range check for format_count earlier
Takashi Iwai (1):
ALSA: usb-audio: Cancel pending work at closing a MIDI substream
Tali Perry (2):
i2c: npcm: Fix timeout calculation
i2c: npcm: Handle spurious interrupts
Tejas Upadhyay (1):
iommu/vt-d: Add RPLS to quirk list to skip TE disabling
Tejun Heo (1):
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Tetsuo Handa (1):
media: imon: reorganize serialization
Theodore Ts'o (1):
ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state
Thibaut VARÈNE (1):
ath9k: fix QCA9561 PA bias level
Thorsten Scherer (1):
ARM: dts: ci4x10: Adapt to changes in imx6qdl.dtsi regarding fec clocks
Tokunori Ikegami (2):
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Tong Tiangen (1):
arm64: fix types in copy_highpage()
Trond Myklebust (5):
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
NFS: fsync() should report filesystem errors over EINTR/ERESTARTSYS
NFS: Do not report flush errors in nfs_write_end()
NFS: Don't report errors from nfs_pageio_complete() more than once
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
Tyler Hicks (1):
EDAC/dmc520: Don't print an error for each unconfigured interrupt line
Tyrone Ting (1):
i2c: npcm: Correct register access width
Tzung-Bi Shih (1):
platform/chrome: cros_ec: fix error handling in cros_ec_register()
Vasily Averin (1):
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
Vignesh Raghavendra (1):
drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit
Vincent Mailhol (1):
can: mcp251xfd: silence clang's -Wunaligned-access warning
Vincent Whitchurch (1):
um: Fix out-of-bounds read in LDT setup
Vinod Polimera (1):
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
Viresh Kumar (1):
Revert "cpufreq: Fix possible race in cpufreq online error path"
Waiman Long (2):
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
kseltest/cgroup: Make test_stress.sh work if run interactively
Wenli Looi (1):
ath9k: fix ar9003_get_eepmisc
Xiao Yang (1):
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Xiaomeng Tong (11):
media: uvcvideo: Fix missing check to determine if element is found in list
scsi: dc395x: Fix a missing check on list iterator
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator
md: fix an incorrect NULL check in does_sb_need_changing
md: fix an incorrect NULL check in md_reload_sb
iommu/msm: Fix an incorrect NULL check on list iterator
carl9170: tx: fix an incorrect use of list iterator
stm: ltdc: fix two incorrect NULL checks on list iterator
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
gma500: fix an incorrect NULL check on list iterator
Xie Yongji (1):
nbd: Fix hung on disconnect request if socket is closed before
Yang Jihong (1):
perf tools: Add missing headers needed by util/data.h
Yang Yingliang (10):
pinctrl: renesas: rzn1: Fix possible null-ptr-deref in sh_pfc_map_resources()
mtd: rawnand: cadence: fix possible null-ptr-deref in cadence_nand_dt_probe()
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
spi: spi-fsl-qspi: check return value after calling platform_get_resource_byname()
thermal/core: Fix memory leak in __thermal_cooling_device_register()
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
pinctrl: renesas: core: Fix possible null-ptr-deref in sh_pfc_map_resources()
hwrng: omap3-rom - fix using wrong clk_disable() in omap_rom_rng_runtime_resume()
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
Ye Bin (3):
ext4: fix use-after-free in ext4_rename_dir_prepare
ext4: fix warning in ext4_handle_inode_extension
ext4: fix bug_on in ext4_writepages
Yi Yang (1):
xtensa/simdisk: fix proc_read_simdisk()
Yicong Yang (1):
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Ying Hsu (1):
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Yong Wu (1):
iommu/mediatek: Add list_del in mtk_iommu_remove
Yonghong Song (1):
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Yongzhi Liu (1):
hv_netvsc: Fix potential dereference of NULL pointer
Yuntao Wang (1):
bpf: Fix excessive memory allocation in stack_map_alloc()
Zev Weiss (1):
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Zheng Bin (1):
net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init
Zheng Yongjun (2):
spi: img-spfi: Fix pm_runtime_get_sync() error checking
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
Zhengjun Xing (1):
perf jevents: Fix event syntax error caused by ExtSel
Zheyu Ma (3):
media: pci: cx23885: Fix the error handling in cx23885_initdev()
media: cx25821: Fix the warning when removing the module
mtd: rawnand: denali: Use managed device resources
Zhihao Cheng (1):
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
Zhou Qingyang (1):
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Zixuan Fu (1):
fs: jfs: fix possible NULL pointer dereference in dbFree()
Ziyang Xuan (1):
thermal/core: fix a UAF bug in __thermal_cooling_device_register()
jianghaoran (1):
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
liuyacan (1):
net/smc: postpone sk_refcnt increment in connect()
^ permalink raw reply [relevance 1%]
* [PATCH 5.18 527/879] net/smc: postpone sk_refcnt increment in connect()
2022-06-07 16:51 1% [PATCH 5.18 000/879] 5.18.3-rc1 review Greg Kroah-Hartman
@ 2022-06-07 17:00 7% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-07 17:00 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, liuyacan, David S. Miller, Sasha Levin
From: liuyacan <liuyacan@corp.netease.com>
[ Upstream commit 75c1edf23b95a9c66923d9269d8e86e4dbde151f ]
Same trigger condition as commit 86434744. When setsockopt runs
in parallel to a connect(), and switch the socket into fallback
mode. Then the sk_refcnt is incremented in smc_connect(), but
its state stay in SMC_INIT (NOT SMC_ACTIVE). This cause the
corresponding sk_refcnt decrement in __smc_release() will not be
performed.
Fixes: 86434744fedf ("net/smc: add fallback check to connect()")
Signed-off-by: liuyacan <liuyacan@corp.netease.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/smc/af_smc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index fce16b9d6e1a..45a24d24210f 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1564,9 +1564,9 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
if (rc && rc != -EINPROGRESS)
goto out;
- sock_hold(&smc->sk); /* sock put in passive closing */
if (smc->use_fallback)
goto out;
+ sock_hold(&smc->sk); /* sock put in passive closing */
if (flags & O_NONBLOCK) {
if (queue_work(smc_hs_wq, &smc->connect_work))
smc->connect_nonblock = 1;
--
2.35.1
^ permalink raw reply related [relevance 7%]
* [PATCH 5.18 000/879] 5.18.3-rc1 review
@ 2022-06-07 16:51 1% Greg Kroah-Hartman
2022-06-07 17:00 7% ` [PATCH 5.18 527/879] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2022-06-07 16:51 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, torvalds, akpm, linux, shuah,
patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, slade
This is the start of the stable review cycle for the 5.18.3 release.
There are 879 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 09 Jun 2022 16:48:02 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.18.3-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.18.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.18.3-rc1
Tony Lindgren <tony@atomide.com>
tty: n_gsm: Fix packet data hex dump output
Ziyang Xuan <william.xuanziyang@huawei.com>
macsec: fix UAF bug for real_dev
Jia-Ju Bai <baijiaju1990@gmail.com>
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Xiao Ni <xni@redhat.com>
md: fix double free of io_acct_set bioset
Xiao Ni <xni@redhat.com>
md: Don't set mddev private to NULL in raid0 pers->free
Namjae Jeon <linkinjeon@kernel.org>
fs/ntfs3: Fix invalid free in log_replay
Christian Brauner <brauner@kernel.org>
exportfs: support idmapped mounts
Christian Brauner <brauner@kernel.org>
fs: add two trivial lookup helpers
Eric Biggers <ebiggers@google.com>
ext4: only allow test_dummy_encryption when supported
Xiao Yang <yangx.jy@fujitsu.com>
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Yixing Liu <liuyixing1@huawei.com>
RDMA/hns: Remove the num_cqc_timer variable
Carlos Llamas <cmllamas@google.com>
binder: fix sender_euid type in uapi header
Dan Carpenter <dan.carpenter@oracle.com>
staging: r8188eu: delete rtw_wx_read/write32()
Jason A. Donenfeld <Jason@zx2c4.com>
Revert "random: use static branch for crng_ready()"
Zhengjun Xing <zhengjun.xing@linux.intel.com>
perf evlist: Extend arch_evsel__must_be_in_group to support hybrid systems
Waiman Long <longman@redhat.com>
kseltest/cgroup: Make test_stress.sh work if run interactively
Sean Young <sean@mess.org>
media: lirc: add missing exceptions for lirc uapi header file
Alex Elder <elder@linaro.org>
net: ipa: fix page free in ipa_endpoint_replenish_one()
Alex Elder <elder@linaro.org>
net: ipa: fix page free in ipa_endpoint_trans_release()
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix reset-controller leak on probe errors
Mao Jinlong <quic_jinlmao@quicinc.com>
coresight: core: Fix coresight device probe failure issue
Tejun Heo <tj@kernel.org>
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Eugenio Pérez <eperezma@redhat.com>
vdpasim: allow to enable a vq repeatedly
Dinh Nguyen <dinguyen@kernel.org>
dt-bindings: gpio: altera: correct interrupt-cells
Akira Yokosawa <akiyks@gmail.com>
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Steve French <stfrench@microsoft.com>
SMB3: EBADF/EIO errors in rename/open caused by race condition in smb2_compound_op
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
misc: fastrpc: fix list iterator in fastrpc_req_mem_unmap_impl
Luís Henriques <lhenriques@suse.de>
ceph: fix decoding of client session messages flags
Arnd Bergmann <arnd@arndb.de>
ARM: pxa: maybe fix gpio lookup tables
Jonathan Bakker <xc-racer2@live.ca>
ARM: dts: s5pv210: Remove spi-cs-high on panel in Aries
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix struct clk leak on probe errors
Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
clk: tegra: Add missing reset deassertion
Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
arm64: tegra: Add missing DFLL reset on Tegra210
Kathiravan T <quic_kathirav@quicinc.com>
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Xiaomeng Tong <xiam0nd.tong@gmail.com>
gma500: fix an incorrect NULL check on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
Jiri Slaby <jirislaby@kernel.org>
serial: pch: don't overwrite xmit->buf[0] by x_char
Coly Li <colyli@suse.de>
bcache: avoid journal no-space deadlock by reserving 1 journal bucket
Coly Li <colyli@suse.de>
bcache: remove incremental dirty sector counting for bch_sectors_dirty_init()
Coly Li <colyli@suse.de>
bcache: improve multithreaded bch_sectors_dirty_init()
Coly Li <colyli@suse.de>
bcache: improve multithreaded bch_btree_check()
Xiaomeng Tong <xiam0nd.tong@gmail.com>
stm: ltdc: fix two incorrect NULL checks on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
carl9170: tx: fix an incorrect use of list iterator
Mark Brown <broonie@kernel.org>
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Alexander Wetzel <alexander@wetzel-home.de>
rtl818x: Prevent using not initialized queues
Yi Yang <yiyang13@huawei.com>
xtensa/simdisk: fix proc_read_simdisk()
Miaohe Lin <linmiaohe@huawei.com>
mm/memremap: fix missing call to untrack_pfn() in pagemap_range()
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix huge_pmd_unshare address update
Christophe de Dinechin <dinechin@redhat.com>
nodemask.h: fix compilation error with GCC12
Mel Gorman <mgorman@techsingularity.net>
mm/page_alloc: always attempt to allocate at least one page during bulk allocation
Eric Dumazet <edumazet@google.com>
mm/page_owner: use strscpy() instead of strlcpy()
Dong Aisheng <aisheng.dong@nxp.com>
Revert "mm/cma.c: remove redundant cma_mutex lock"
Masami Hiramatsu <mhiramat@kernel.org>
kprobes: Fix build errors with CONFIG_KRETPROBES=n
Yunfei Wang <yf.wang@mediatek.com>
iommu/dma: Fix iova map result check bug
Xiaomeng Tong <xiam0nd.tong@gmail.com>
iommu/msm: Fix an incorrect NULL check on list iterator
Hyunchul Lee <hyc.lee@gmail.com>
ksmbd: fix outstanding credits related bugs
Song Liu <song@kernel.org>
ftrace: Clean up hash direct_functions on register failures
Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
Maciej W. Rozycki <macro@orcam.me.uk>
MIPS: IP30: Remove incorrect `cpu_has_fpu' override
Maciej W. Rozycki <macro@orcam.me.uk>
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
Vincent Whitchurch <vincent.whitchurch@axis.com>
um: Fix out-of-bounds read in LDT setup
Johannes Berg <johannes.berg@intel.com>
um: chan_user: Fix winch_tramp() return value
Johannes Berg <johannes.berg@intel.com>
um: Use asm-generic/dma-mapping.h
Johannes Berg <johannes.berg@intel.com>
um: virtio_uml: Fix broken device handling in time-travel
Felix Fietkau <nbd@nbd.name>
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Dimitri John Ledkov <dimitri.ledkov@canonical.com>
cfg80211: declare MODULE_FIRMWARE for regulatory.db
Felix Fietkau <nbd@nbd.name>
mt76: fix use-after-free by removing a non-RCU wcid pointer
Kant Fan <kant@allwinnertech.com>
thermal: devfreq_cooling: use local ops instead of global ops
Max Filippov <jcmvbkbc@gmail.com>
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Pali Rohár <pali@kernel.org>
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Guo Ren <guoren@kernel.org>
csky: patch_text: Fixup last cpu should be master
Bean Huo <beanhuo@micron.com>
mmc: core: Allows to override the timeout value for ioctl() path
Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
RDMA/hfi1: Fix potential integer multiplication overflow errors
Puyou Lu <puyou.lu@gmail.com>
lib/string_helpers: fix not adding strarray to device's resource list
Sean Christopherson <seanjc@google.com>
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
GUO Zihua <guozihua@huawei.com>
ima: remove the IMA_TEMPLATE Kconfig option
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Add more H264 levels for CODA960
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Fix reported H264 profile
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in md_reload_sb
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in does_sb_need_changing
Jani Nikula <jani.nikula@intel.com>
drm/i915/dsi: fix VBT send packet port selection for ICL+
Brian Norris <briannorris@chromium.org>
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Xiaomeng Tong <xiam0nd.tong@gmail.com>
drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
Lucas Stach <l.stach@pengutronix.de>
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Lyude Paul <lyude@redhat.com>
drm/nouveau/subdev/bus: Ratelimit logging for fault errors
Dave Airlie <airlied@redhat.com>
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
Mickaël Salaün <mic@digikod.net>
landlock: Fix same-layer rule unions
Mickaël Salaün <mic@digikod.net>
landlock: Create find_rule() from unmask_layers()
Mickaël Salaün <mic@digikod.net>
landlock: Reduce the maximum number of layers to 16
Mickaël Salaün <mic@digikod.net>
landlock: Define access_mask_t to enforce a consistent access mask size
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Test landlock_create_ruleset(2) argument check ordering
Mickaël Salaün <mic@digikod.net>
landlock: Change landlock_restrict_self(2) check ordering
Mickaël Salaün <mic@digikod.net>
landlock: Change landlock_add_rule(2) argument check ordering
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Add tests for O_PATH
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Fully test file rename with "remove" access
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Extend access right tests to directories
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Add tests for unknown access rights
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Extend tests for minimal valid attribute size
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Make tests build with old libc
Mickaël Salaün <mic@digikod.net>
landlock: Fix landlock_add_rule(2) documentation
Mickaël Salaün <mic@digikod.net>
samples/landlock: Format with clang-format
Mickaël Salaün <mic@digikod.net>
samples/landlock: Add clang-format exceptions
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Format with clang-format
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Normalize array assignment
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Add clang-format exceptions
Mickaël Salaün <mic@digikod.net>
landlock: Format with clang-format
Mickaël Salaün <mic@digikod.net>
landlock: Add clang-format exceptions
Manivannan Sadhasivam <mani@kernel.org>
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Xiaomeng Tong <xiam0nd.tong@gmail.com>
scsi: dc395x: Fix a missing check on list iterator
Junxiao Bi via Ocfs2-devel <ocfs2-devel@oss.oracle.com>
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Alexander Aring <aahringo@redhat.com>
dlm: fix missing lkb refcount handling
Alexander Aring <aahringo@redhat.com>
dlm: fix wake_up() calls for pending remove
Dan Carpenter <dan.carpenter@oracle.com>
dlm: uninitialized variable on error in dlm_listen_for_all()
Alexander Aring <aahringo@redhat.com>
dlm: fix plock invalid read
Sven Schnelle <svens@linux.ibm.com>
s390/stp: clock_delta should be signed
Nico Boehr <nrb@linux.ibm.com>
s390/perf: obtain sie_block from the right address
Rei Yamamoto <yamamoto.rei@jp.fujitsu.com>
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Damien Le Moal <damien.lemoal@opensource.wdc.com>
block: Fix potential deadlock in blk_ia_range_sysfs_show()
Denis Efremov <denis.e.efremov@oracle.com>
staging: r8188eu: prevent ->Ssid overflow in rtw_wx_set_scan()
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix unbalanced PHY init on probe errors
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix runtime PM imbalance on probe errors
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix pipe clock imbalance
Bjorn Helgaas <bhelgaas@google.com>
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: add beige goby PCI ID
Gautam Menghani <gautammenghani201@gmail.com>
tracing: Initialize integer variable to prevent garbage return value
Wonhyuk Yang <vvghjk1234@gmail.com>
tracing: Fix return value of trace_pid_write()
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
tracing: Fix potential double free in create_var_ref()
Steven Rostedt (Google) <rostedt@goodmis.org>
tracing: Have event format check not flag %p* on __get_dynamic_array()
Laurent Vivier <laurent@vivier.eu>
tty: goldfish: Introduce gf_ioread32()/gf_iowrite32()
Sakari Ailus <sakari.ailus@linux.intel.com>
ACPI: property: Release subnode properties with data nodes
Jan Kara <jack@suse.cz>
ext4: avoid cycles in directory h-tree
Jan Kara <jack@suse.cz>
ext4: verify dir block before splitting it
Baokun Li <libaokun1@huawei.com>
ext4: fix bug_on in __es_tree_search
Theodore Ts'o <tytso@mit.edu>
ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state
Ye Bin <yebin10@huawei.com>
ext4: fix bug_on in ext4_writepages
Eric Biggers <ebiggers@google.com>
ext4: fix memory leak in parse_apply_sb_mount_options()
Ye Bin <yebin10@huawei.com>
ext4: fix warning in ext4_handle_inode_extension
Baokun Li <libaokun1@huawei.com>
ext4: fix race condition between ext4_write and ext4_convert_inline_data
Ojaswin Mujoo <ojaswin@linux.ibm.com>
ext4: fix journal_ioprio mount option handling
Ye Bin <yebin10@huawei.com>
ext4: fix use-after-free in ext4_rename_dir_prepare
Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
ext4: mark group as trimmed only if it was fully scanned
Jan Kara <jack@suse.cz>
bfq: Make sure bfqg for which we are queueing requests is online
Jan Kara <jack@suse.cz>
bfq: Get rid of __bio_blkcg() usage
Jan Kara <jack@suse.cz>
bfq: Track whether bfq_group is still online
Jan Kara <jack@suse.cz>
bfq: Remove pointless bfq_init_rq() calls
Jan Kara <jack@suse.cz>
bfq: Drop pointless unlock-lock pair
Jan Kara <jack@suse.cz>
bfq: Update cgroup information before merging bio
Jan Kara <jack@suse.cz>
bfq: Split shared queues on move between cgroups
Jan Kara <jack@suse.cz>
bfq: Avoid merging queues with different parents
Jan Kara <jack@suse.cz>
bfq: Avoid false marking of bic as stably merged
Aditya Garg <gargaditya08@live.com>
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Zhihao Cheng <chengzhihao1@huawei.com>
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
Miaoqian Lin <linmq006@gmail.com>
ipmi:ipmb: Fix refcount leak in ipmi_ipmb_probe
Johannes Berg <johannes.berg@intel.com>
iwlwifi: mei: fix potential NULL-ptr deref
Avraham Stern <avraham.stern@intel.com>
iwlwifi: mei: clear the sap data header before sending
Emmanuel Grumbach <emmanuel.grumbach@intel.com>
iwlwifi: mvm: fix assert 1F04 upon reconfig
Johannes Berg <johannes.berg@intel.com>
iwlwifi: fw: init SAR GEO table only if data is present
Johannes Berg <johannes.berg@intel.com>
wifi: mac80211: fix use-after-free in chanctx code
Peter Zijlstra <peterz@infradead.org>
objtool: Fix symbol creation
Mikulas Patocka <mpatocka@redhat.com>
objtool: Fix objtool regression on x32 systems
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check for inline inode
Chao Yu <chao@kernel.org>
f2fs: fix fallocate to use file_modified to update permissions consistently
Eric Biggers <ebiggers@google.com>
f2fs: don't use casefolded comparison for "." and ".."
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on total_data_blocks
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: don't need inode lock for system hidden quota
Chao Yu <chao@kernel.org>
f2fs: fix deadloop in foreground GC
Chao Yu <chao@kernel.org>
f2fs: fix to clear dirty inode in f2fs_evict_inode()
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
Chao Yu <chao@kernel.org>
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
Olga Kornievskaia <kolga@netapp.com>
NFSv4.1 mark qualified async operations as MOVEABLE tasks
Benjamin Coddington <bcodding@redhat.com>
NFSv4: Fix free of uninitialized nfs4_label on referral lookup.
Javier Martinez Canillas <javierm@redhat.com>
video: fbdev: vesafb: Fix a use-after-free due early fb_info cleanup
Zhengjun Xing <zhengjun.xing@linux.intel.com>
perf jevents: Fix event syntax error caused by ExtSel
Daniel Bristot de Oliveira <bristot@kernel.org>
tracing/timerlat: Notify IRQ new max latency only if stop tracing is set
Daniel Bristot de Oliveira <bristot@kernel.org>
rtla: Remove procps-ng dependency
Daniel Bristot de Oliveira <bristot@kernel.org>
rtla: Fix __set_sched_attr error message
John Kacur <jkacur@redhat.com>
rtla: Minor grammar fix for rtla README
John Kacur <jkacur@redhat.com>
rtla: Don't overwrite existing directory mode
Wan Jiabing <wanjiabing@vivo.com>
rtla: Avoid record NULL pointer dereference
Leo Yan <leo.yan@linaro.org>
perf c2c: Use stdio interface if slang is not supported
Jiri Olsa <jolsa@kernel.org>
perf build: Fix btf__load_from_kernel_by_id() feature check
Tiezhu Yang <yangtiezhu@loongson.cn>
MIPS: RALINK: Define pci_remap_iospace under CONFIG_PCI_DRIVERS_GENERIC
Palmer Dabbelt <palmer@rivosinc.com>
RISC-V: Fix the XIP build
Palmer Dabbelt <palmer@rivosinc.com>
RISC-V: Split out the XIP fixups into their own file
Li Huafei <lihuafei1@huawei.com>
tracing: Reset the function filter after completing trampoline/graph selftest
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
i2c: rcar: fix PM ref counts in probe error paths
Tali Perry <tali.perry1@gmail.com>
i2c: npcm: Handle spurious interrupts
Tyrone Ting <kfting@nuvoton.com>
i2c: npcm: Correct register access width
Tali Perry <tali.perry1@gmail.com>
i2c: npcm: Fix timeout calculation
Joerg Roedel <jroedel@suse.de>
iommu/amd: Increase timeout waiting for GA log enablement
Amelie Delaunay <amelie.delaunay@foss.st.com>
dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler()
Amelie Delaunay <amelie.delaunay@foss.st.com>
dmaengine: stm32-mdma: remove GISR1 register
Miaoqian Lin <linmq006@gmail.com>
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
Dave Wysochanski <dwysocha@redhat.com>
NFS: Pass i_size to fscache_unuse_cookie() when a file is released
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Further fixes to the writeback error handling
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Don't report errors from nfs_pageio_complete() more than once
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report flush errors in nfs_write_end()
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Don't report ENOSPC write errors twice
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: fsync() should report filesystem errors over EINTR/ERESTARTSYS
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: idxd: Fix the error handling path in idxd_cdev_register()
Nathan Chancellor <nathan@kernel.org>
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Miles Chen <miles.chen@mediatek.com>
iommu/mediatek: Fix NULL pointer dereference when printing dev_name
Guenter Roeck <linux@roeck-us.net>
MIPS: Loongson: Use hwmon_device_register_with_groups() to register hwmon
Jean-Philippe Brucker <jean-philippe@linaro.org>
iommu/arm-smmu-v3-sva: Fix mm use-after-free
Rex-BC Chen <rex-bc.chen@mediatek.com>
cpufreq: mediatek: Unregister platform device on exit
Jia-Wei Chang <jia-wei.chang@mediatek.com>
cpufreq: mediatek: Use module_init and add module_exit
Michael Walle <michael@walle.cc>
i2c: at91: use dma safe buffers
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Remove clk_disable in mtk_iommu_remove
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Add list_del in mtk_iommu_remove
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Fix 2 HW sharing pgtable issue
Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
iommu/amd: Do not call sleep while holding spinlock
Mario Limonciello <mario.limonciello@amd.com>
iommu/amd: Enable swiotlb in all cases
Guo Ren <guoren@kernel.org>
riscv: Fixup difference with defconfig
Jakob Koschel <jakobkoschel@gmail.com>
f2fs: fix dereference of stale list iterator after loop body
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on inline_dots inode
Jayesh Choudhary <j-choudhary@ti.com>
dmaengine: ti: k3-psil-am62: Update PSIL thread for saul.
Dan Carpenter <dan.carpenter@oracle.com>
OPP: call of_node_put() on error path in _bandwidth_supported()
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: stmfts - do not leave device disabled in stmfts_input_open
Wanpeng Li <wanpengli@tencent.com>
KVM: LAPIC: Drop pending LAPIC timer injection when canceling the timer
Hector Martin <marcan@marcan.st>
pinctrl: apple: Use a raw spinlock for the regmap
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent use of lock before it is initialized
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
RDMA/rxe: Fix an error handling path in rxe_get_mcg()
Björn Ardö <bjorn.ardo@axis.com>
mailbox: forward the hrtimer if not queued and under a lock
Julian Schroeder <jumaco@amazon.com>
nfsd: destroy percpu stats counters after reply cache shutdown
Yang Yingliang <yangyingliang@huawei.com>
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
gpio: sim: Use correct order for the parameters of devm_kcalloc()
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/fsl_book3e: Don't set rodata RO too early
Vaibhav Jain <vaibhav@linux.ibm.com>
powerpc/papr_scm: Fix leaking nvdimm_events_map elements
Miaoqian Lin <linmq006@gmail.com>
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
Miaoqian Lin <linmq006@gmail.com>
powerpc/xive: Fix refcount leak in xive_spapr_init
Randy Dunlap <rdunlap@infradead.org>
macintosh: via-pmu and via-cuda need RTC_LIB
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf: Fix the threshold compare group constraint for power9
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf: Fix the threshold compare group constraint for power10
Russell Currey <ruscur@russell.cc>
powerpc/powernv: Get STF barrier requirements from device-tree
Russell Currey <ruscur@russell.cc>
powerpc/powernv: Get L1D flush requirements from device-tree
Michael Ellerman <mpe@ellerman.id.au>
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
Mario Limonciello <mario.limonciello@amd.com>
mailbox: pcc: Fix an invalid-load caught by the address sanitizer
Kan Liang <kan.liang@linux.intel.com>
perf stat: Always keep perf metrics topdown events in a group
Ian Rogers <irogers@google.com>
perf evlist: Keep topdown counters in weak group
Yang Yingliang <yangyingliang@huawei.com>
hwrng: omap3-rom - fix using wrong clk_disable() in omap_rom_rng_runtime_resume()
Dan Williams <dan.j.williams@intel.com>
cxl/mem: Drop mem_enabled check from wait_for_media()
Daire McNamara <daire.mcnamara@microchip.com>
PCI: microchip: Fix potential race in interrupt handling
Fabiano Rosas <farosas@linux.ibm.com>
KVM: PPC: Book3S HV: Fix vcore_blocked tracepoint
Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
PCI/AER: Clear MULTI_ERR_COR/UNCOR_RCV bits
Miaoqian Lin <linmq006@gmail.com>
Input: sparcspkr - fix refcount leak in bbc_beep_probe
Jane Chu <jane.chu@oracle.com>
mce: fix set_mce_nospec to always unmap the whole page
Jane Chu <jane.chu@oracle.com>
x86/mce: relocate set{clear}_mce_nospec() functions
Mina Almasry <almasrymina@google.com>
hugetlbfs: fix hugetlbfs_statfs() locking
Michael Walle <michael@walle.cc>
ARM: dts: lan966x: swap dma channels for crypto node
Eugen Hristev <eugen.hristev@microchip.com>
ARM: dts: at91: sama7g5: remove interrupt-parent from gic node
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
crypto: cryptd - Protect per-CPU resource by disabling BH.
Corentin Labbe <clabbe@baylibre.com>
crypto: sun8i-ss - handle zero sized sg
Corentin Labbe <clabbe@baylibre.com>
crypto: sun8i-ss - rework handling of IV
Qi Zheng <zhengqi.arch@bytedance.com>
tty: fix deadlock caused by calling printk() under tty_port->lock
Alexey Dobriyan <adobriyan@gmail.com>
module: fix [e_shstrndx].sh_size=0 OOB access
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
module.h: simplify MODULE_IMPORT_NS
AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
PCI: mediatek-gen3: Assert resets to ensure expected init state
Francesco Dolcini <francesco.dolcini@toradex.com>
PCI: imx6: Fix PERST# start-up sequence
Waiman Long <longman@redhat.com>
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
Alexey Dobriyan <adobriyan@gmail.com>
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: atmel-classd: Remove endianness flag on class d component
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: atmel-pdmic: Remove endianness flag on pdmic component
Robert Marko <robert.marko@sartura.hr>
arm64: dts: marvell: espressobin-ultra: enable front USB3 port
Robert Marko <robert.marko@sartura.hr>
arm64: dts: marvell: espressobin-ultra: fix SPI-NOR config
Yangyang Li <liyangyang20@huawei.com>
RDMA/hns: Add the detection for CMDQ status in the device initialization process
Randy Dunlap <rdunlap@infradead.org>
powerpc/4xx/cpm: Fix return value of __setup() handler
Randy Dunlap <rdunlap@infradead.org>
powerpc/idle: Fix return value of __setup() handler
Yang Yingliang <yangyingliang@huawei.com>
pinctrl: renesas: core: Fix possible null-ptr-deref in sh_pfc_map_resources()
Geert Uytterhoeven <geert+renesas@glider.be>
pinctrl: renesas: r8a779f0: Fix GPIO function on I2C-capable pins
Geert Uytterhoeven <geert+renesas@glider.be>
pinctrl: renesas: r8a779a0: Fix GPIO function on I2C-capable pins
Randy Dunlap <rdunlap@infradead.org>
powerpc/8xx: export 'cpm_setbrg' for modules
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/dpu: fix error check return value of irq_of_parse_and_map()
Kuniyuki Iwashima <kuniyu@amazon.co.jp>
list: fix a data-race around ep->rdllist
Heming Zhao via Ocfs2-devel <ocfs2-devel@oss.oracle.com>
ocfs2: fix mounting crash if journal is not alloced
Sudeep Holla <sudeep.holla@arm.com>
firmware: arm_ffa: Remove incorrect assignment of driver_data
Sudeep Holla <sudeep.holla@arm.com>
firmware: arm_ffa: Fix uuid parameter to ffa_partition_probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
drivers/base/memory: fix an unlikely reference counting issue in __add_memory_block()
Muchun Song <songmuchun@bytedance.com>
dax: fix cache flush on PMD-mapped pages
Miaohe Lin <linmiaohe@huawei.com>
drivers/base/node.c: fix compaction sysfs file leak
Jacky Li <jackyli@google.com>
crypto: ccp - Fix the INIT_EX data file open failure
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
Dan Williams <dan.j.williams@intel.com>
nvdimm: Allow overwrite in the presence of disabled dimms
Dan Williams <dan.j.williams@intel.com>
nvdimm: Fix firmware activation deadlock scenarios
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
ASoC: sh: rz-ssi: Release the DMA channels in rz_ssi_probe() error path
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
ASoC: sh: rz-ssi: Propagate error codes returned from platform_get_irq_byname()
Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
arm64: dts: ti: k3-am64-mcu: remove incorrect UART base clock rates
QintaoShen <unSimple1993@163.com>
soc: bcm: Check for NULL return of devm_kzalloc()
Gustavo A. R. Silva <gustavoars@kernel.org>
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
Lv Ruyi <lv.ruyi@zte.com.cn>
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: fix PT_LOAD segment for boot memory area
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Fix handling of messages with transaction ID of zero
Vinod Koul <vkoul@kernel.org>
arm64: dts: qcom: qrb5165-rb5: Fix can-clock node name
Fabien Parent <fparent@baylibre.com>
pinctrl: mediatek: mt8195: enable driver on mtk platforms
Caleb Connolly <kc@postmarketos.org>
pinctrl/rockchip: support deferring other gpio params
Chuanhong Guo <gch981213@gmail.com>
arm: mediatek: select arch timer for mt7629
Chia-I Wu <olvaffe@gmail.com>
drm/msm: return the average load over the polling period
Chia-I Wu <olvaffe@gmail.com>
drm/msm: simplify gpu_busy callback
Stefan Wahren <stefan.wahren@i2se.com>
pinctrl: bcm2835: implement hook for missing gpio-ranges
Stefan Wahren <stefan.wahren@i2se.com>
gpiolib: of: Introduce hook for missing gpio-ranges
Corentin Labbe <clabbe@baylibre.com>
crypto: marvell/cesa - ECB does not IV
Vladis Dronov <vdronov@redhat.com>
hwrng: cn10k - Make check_rng_health() return an error code
Vladis Dronov <vdronov@redhat.com>
hwrng: cn10k - Optimize cn10k_rng_read()
Hangyu Hua <hbh25y@gmail.com>
misc: ocxl: fix possible double free in ocxl_file_register_afu
Stefan Wahren <stefan.wahren@i2se.com>
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
Vinod Koul <vkoul@kernel.org>
arm64: dts: qcom: sm8450: Fix missing iommus for qup1
Vinod Koul <vkoul@kernel.org>
arm64: dts: qcom: sm8450: Fix missing iommus for qup
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: qcom: sdx55: remove wrong unit address from RPMH RSC clocks
Bryan O'Donoghue <bryan.odonoghue@linaro.org>
dt-bindings: soc: qcom: smd-rpm: Fix missing MSM8936 compatible
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Fix PHY post-reset delay on Avenger96
Marc Kleine-Budde <mkl@pengutronix.de>
can: xilinx_can: mark bit timing constants as const
Guenter Roeck <linux@roeck-us.net>
platform/chrome: Re-introduce cros_ec_cmd_xfer and use it for ioctls
Max Krummenacher <max.krummenacher@toradex.com>
ARM: dts: imx6dl-colibri: Fix I2C pinmuxing
Tzung-Bi Shih <tzungbi@kernel.org>
platform/chrome: cros_ec: fix error handling in cros_ec_register()
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - set COMPRESSION capability for DH895XCC
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - set CIPHER capability for DH895XCC
Sudeep Holla <sudeep.holla@arm.com>
arm64: dts: juno: Fix SCMI power domain IDs for ETF and CS funnel
Sean Christopherson <seanjc@google.com>
KVM: nVMX: Clear IDT vectoring on nested VM-Exit for double/triple fault
Sean Christopherson <seanjc@google.com>
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
Dan Williams <dan.j.williams@intel.com>
cxl/pci: Make cxl_dvsec_ranges() failure not fatal to cxl_pci
Dan Williams <dan.j.williams@intel.com>
cxl/pci: Add debug for DVSEC range init failures
Bjorn Andersson <bjorn.andersson@linaro.org>
soc: qcom: llcc: Add MODULE_DEVICE_TABLE()
Stephen Boyd <swboyd@chromium.org>
arm64: dts: qcom: sc7280-herobrine: Drop outputs on fpmcu pins
Stephen Boyd <swboyd@chromium.org>
arm64: dts: qcom: sc7280: Fix sar1_irq_odl node name
Thorsten Scherer <t.scherer@eckelmann.de>
ARM: dts: ci4x10: Adapt to changes in imx6qdl.dtsi regarding fec clocks
Jiantao Zhang <water.zhangjiantao@huawei.com>
PCI: dwc: Fix setting error return on MSI DMA mapping failure
Miaoqian Lin <linmq006@gmail.com>
PCI: mediatek: Fix refcount leak in mtk_pcie_subsys_powerup()
Dan Carpenter <dan.carpenter@oracle.com>
PCI: rockchip: Fix find_first_zero_bit() limit
Dan Carpenter <dan.carpenter@oracle.com>
PCI: cadence: Fix find_first_zero_bit() limit
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: defconfig: reenable SM_DISPCC_8250
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
Andre Przywara <andre.przywara@arm.com>
ARM: dts: suniv: F1C100: fix watchdog compatible
Rafał Miłecki <rafal@milecki.pl>
ARM: dts: BCM5301X: Update pin controller node name
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
memory: samsung: exynos5422-dmc: Avoid some over memory allocation
Mario Limonciello <mario.limonciello@amd.com>
PCI/ACPI: Allow D3 only if Root Port can signal and wake from D3
Allen-KH Cheng <allen-kh.cheng@mediatek.com>
arm64: dts: mt8192: Fix nor_flash status disable typo
Shawn Lin <shawn.lin@rock-chips.com>
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
Sean Young <sean@mess.org>
media: lirc: revert removal of unused feature flags
liuyacan <liuyacan@corp.netease.com>
Revert "net/smc: fix listen processing for SMC-Rv2"
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: hci_conn: Fix hci_connect_le_sync
Robin Murphy <robin.murphy@arm.com>
dma-direct: don't over-decrypt memory
liuyacan <liuyacan@corp.netease.com>
net/smc: fix listen processing for SMC-Rv2
liuyacan <liuyacan@corp.netease.com>
net/smc: postpone sk_refcnt increment in connect()
Randy Dunlap <rdunlap@infradead.org>
net: dsa: restrict SMSC_LAN9303_I2C kconfig
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: unmap the SGT buffer before accessing its contents
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: use the correct software annotation field
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: retrieve the virtual address before dma_unmap
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hinic: Avoid some over memory allocation
David Howells <dhowells@redhat.com>
rxrpc: Fix decision on when to generate an IDLE ACK
David Howells <dhowells@redhat.com>
rxrpc: Don't let ack.previousPacket regress
David Howells <dhowells@redhat.com>
rxrpc: Fix overlapping ACK accounting
David Howells <dhowells@redhat.com>
rxrpc: Don't try to resend the request if we're receiving the reply
David Howells <dhowells@redhat.com>
rxrpc: Fix listen() setting the bar too high for the prealloc rings
David Howells <dhowells@redhat.com>
rxrpc: Fix locking issue
Adam Wujek <dev_public@wujek.eu>
hwmon: (pmbus) Check PEC support before reading other registers
Guenter Roeck <linux@roeck-us.net>
hwmon: (dimmtemp) Fix bitmap handling
Yongzhi Liu <lyz_cs@pku.edu.cn>
hv_netvsc: Fix potential dereference of NULL pointer
Taehee Yoo <ap420073@gmail.com>
amt: fix memory leak for advertisement message
Taehee Yoo <ap420073@gmail.com>
amt: fix gateway mode stuck
Jakub Kicinski <kuba@kernel.org>
net: stmmac: fix out-of-bounds access in a selftest
Kan Liang <kan.liang@linux.intel.com>
perf parse-events: Support different format of the topdown event name
Alexey Khoroshilov <khoroshilov@ispras.ru>
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
Hangbin Liu <liuhangbin@gmail.com>
bonding: fix missed rcu protection
Duoming Zhou <duoming@zju.edu.cn>
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
John Garry <john.garry@huawei.com>
scsi: hisi_sas: Fix memory ordering in hisi_sas_task_deliver()
John Garry <john.garry@huawei.com>
scsi: hisi_sas: Fix rescan after deleting a disk
Harini Katakam <harini.katakam@xilinx.com>
net: macb: Fix PTP one step sync support
Ulf Hansson <ulf.hansson@linaro.org>
PM: domains: Fix initialization of genpd's next_wakeup
Heikki Krogerus <heikki.krogerus@linux.intel.com>
platform/x86: intel_cht_int33fe: Set driver data
Ulf Hansson <ulf.hansson@linaro.org>
cpuidle: riscv-sbi: Fix code to allow a genpd governor to be used
Ulf Hansson <ulf.hansson@linaro.org>
cpuidle: psci: Fix regression leading to no genpd governor
Yang Yingliang <yangyingliang@huawei.com>
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
YueHaibing <yuehaibing@huawei.com>
ASoC: codecs: lpass: Fix passing zero to 'PTR_ERR'
Jan Kara <jack@suse.cz>
bfq: Allow current waker to defend against a tentative one
Jan Kara <jack@suse.cz>
bfq: Relax waker detection for shared queues
Miaoqian Lin <linmq006@gmail.com>
thermal/drivers/imx_sc_thermal: Fix refcount leak in imx_sc_thermal_probe
Yang Yingliang <yangyingliang@huawei.com>
thermal/core: Fix memory leak in __thermal_cooling_device_register()
Zheng Yongjun <zhengyongjun3@huawei.com>
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
Stefan Wahren <stefan.wahren@i2se.com>
thermal/drivers/bcm2711: Don't clamp temperature at zero
Nathan Chancellor <nathan@kernel.org>
drm/i915: Fix CFI violation with show_dynamic_id()
Abhinav Kumar <quic_abhinavk@quicinc.com>
drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path
Hangbin Liu <liuhangbin@gmail.com>
selftests/bpf: Add missed ima_setup.sh in Makefile
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: don't free the IRQ if it was not requested
Lai Jiangshan <jiangshan.ljs@antgroup.com>
x86/sev: Annotate stack change in the #VC handler
Hangyu Hua <hbh25y@gmail.com>
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
Miaoqian Lin <linmq006@gmail.com>
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
Douglas Anderson <dianders@chromium.org>
drm/msm/dsi: don't powerup at modeset time for parade-ps8640
Eric Biggers <ebiggers@google.com>
ext4: reject the 'commit' option on ext2 filesystems
Moshe Tal <moshet@nvidia.com>
net/mlx5e: Correct the calculation of max channels for rep
Gao Xiang <hsiangkao@linux.alibaba.com>
erofs: fix buffer copy overflow of ztailpacking feature
Wolfgang Bumiller <w.bumiller@proxmox.com>
blk-cgroup: always terminate io.stat lines
Miaoqian Lin <linmq006@gmail.com>
regulator: scmi: Fix refcount leak in scmi_regulator_probe
Jonas Karlman <jonas@kwiboo.se>
media: rkvdec: h264: Fix bit depth wrap in pps packet
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: rkvdec: h264: Fix dpb_valid implementation
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: rkvdec: Stop overclocking the decoder
Yang Yingliang <yangyingliang@huawei.com>
media: i2c: ov5648: fix wrong pointer passed to IS_ERR() and PTR_ERR()
Mike Pagano <mpagano@gentoo.org>
media: i2c: ov2640: Depend on V4L2_ASYNC
Dongliang Mu <mudongliangabcd@gmail.com>
media: ov7670: remove ov7670_power_off from ov7670_remove
Andre Przywara <andre.przywara@arm.com>
kselftest/arm64: bti: force static linking
Miaoqian Lin <linmq006@gmail.com>
ASoC: ti: j721e-evm: Fix refcount leak in j721e_soc_probe_*
Zheng Bin <zhengbin13@huawei.com>
net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init
Eric Dumazet <edumazet@google.com>
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
Eric Dumazet <edumazet@google.com>
net: annotate races around sk->sk_bound_dev_if
Geert Uytterhoeven <geert@linux-m68k.org>
m68k: math-emu: Fix dependencies of math emulation support
Keith Busch <kbusch@kernel.org>
nvme: set dma alignment to dword
Mark Rutland <mark.rutland@arm.com>
irqchip/gic-v3: Fix priority mask handling
Mark Rutland <mark.rutland@arm.com>
irqchip/gic-v3: Refactor ISB + EOIR at ack time
Mark Rutland <mark.rutland@arm.com>
irqchip/gic-v3: Ensure pseudo-NMIs have an ISB between ack and handling
Dylan Yudaken <dylany@fb.com>
io_uring: only wake when the correct events are set
Pavel Begunkov <asml.silence@gmail.com>
io_uring: avoid io-wq -EAGAIN looping for !IOPOLL
Yunfei Dong <yunfei.dong@mediatek.com>
media: mediatek: vcodec: Fix v4l2 compliance decoder cmd test fail
Sean Wang <sean.wang@mediatek.com>
Bluetooth: btmtksdio: fix the reset takes too long
Sean Wang <sean.wang@mediatek.com>
Bluetooth: btmtksdio: fix possible FW initialization failure
Sean Wang <sean.wang@mediatek.com>
Bluetooth: btmtksdio: fix use-after-free at btmtksdio_recv_event
Niels Dossche <dossche.niels@gmail.com>
Bluetooth: protect le accept and resolv lists with hdev->lock
Niels Dossche <dossche.niels@gmail.com>
Bluetooth: use hdev lock for accept_list and reject_list in conn req
Niels Dossche <dossche.niels@gmail.com>
Bluetooth: use hdev lock in activate_scan for hci_is_adv_monitoring
Ying Hsu <yinghsu@chromium.org>
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Sean Wang <sean.wang@mediatek.com>
Bluetooth: mt7921s: Fix the incorrect pointer check
Benjamin Gaignard <benjamin.gaignard@collabora.com>
media: hantro: HEVC: Fix tile info buffer value computation
Eugen Hristev <eugen.hristev@microchip.com>
media: atmel: atmel-sama5d2-isc: fix wrong mask in YUYV format check
Michael Rodin <mrodin@de.adit-jv.com>
media: vsp1: Fix offset calculation for plane cropping
Randy Dunlap <rdunlap@infradead.org>
media: make RADIO_ADAPTERS tristate
Pavel Skripkin <paskripkin@gmail.com>
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Miaoqian Lin <linmq006@gmail.com>
media: exynos4-is: Change clk_disable to clk_disable_unprepare
Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
media: i2c: rdacm2x: properly set subdev entity function
Miaoqian Lin <linmq006@gmail.com>
media: atmel: atmel-isc: Fix PM disable depth imbalance in atmel_isc_probe
Miaoqian Lin <linmq006@gmail.com>
media: st-delta: Fix PM disable depth imbalance in delta_probe
Peter Chiu <chui-hao.chiu@mediatek.com>
mt76: mt7915: fix twt table_mask to u16 in mt7915_dev
Felix Fietkau <nbd@nbd.name>
mt76: fix tx status related use-after-free race on station removal
Felix Fietkau <nbd@nbd.name>
mt76: do not attempt to reorder received 802.3 packets without agg session
Sean Wang <sean.wang@mediatek.com>
mt76: mt7921: fix kernel crash at mt7921_pci_remove
Deren Wu <deren.wu@mediatek.com>
mt76: fix antenna config missing in 6G cap
Lorenzo Bianconi <lorenzo@kernel.org>
mt76: mt7915: report rx mode value in mt7915_mac_fill_rx_rate
Lorenzo Bianconi <lorenzo@kernel.org>
mt76: mt7915: do not pass data pointer to mt7915_mcu_muru_debug_set
Lorenzo Bianconi <lorenzo@kernel.org>
mt76: mt7915: fix possible NULL pointer dereference in mt7915_mac_fill_rx_vector
Lorenzo Bianconi <lorenzo@kernel.org>
mt76: mt7915: fix possible uninitialized pointer dereference in mt7986_wmac_gpio_setup
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mt76: mt7921: Fix the error handling path of mt7921_pci_probe()
Lorenzo Bianconi <lorenzo@kernel.org>
mt76: mt7915: fix unbounded shift in mt7915_mcu_beacon_mbss
Lorenzo Bianconi <lorenzo@kernel.org>
mt76: mt7921: honor pm user configuration in mt7921_sniffer_interface_iter
Felix Fietkau <nbd@nbd.name>
mt76: mt7915: fix DBDC default band selection on MT7915D
Miaoqian Lin <linmq006@gmail.com>
media: exynos4-is: Fix PM disable depth imbalance in fimc_is_probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: aspeed: Fix an error handling path in aspeed_video_probe()
Josh Poimboeuf <jpoimboe@kernel.org>
scripts/faddr2line: Fix overlapping text section failures
Phil Auld <pauld@redhat.com>
kselftest/cgroup: fix test_stress.sh to use OUTPUT dir
Bart Van Assche <bvanassche@acm.org>
block: Fix the bio.bi_opf comment
Miaoqian Lin <linmq006@gmail.com>
ASoC: samsung: Fix refcount leak in aries_audio_probe
Christoph Hellwig <hch@lst.de>
dma-direct: don't fail on highmem CMA pages in dma_direct_alloc_pages
Pierre Gondois <Pierre.Gondois@arm.com>
PM: EM: Decrement policy counter
Miaoqian Lin <linmq006@gmail.com>
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
Miaoqian Lin <linmq006@gmail.com>
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: imx-hdmi: Fix refcount leak in imx_hdmi_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Modify the hid name
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Modify the bus name
Ajay Singh <ajay.kathat@microchip.com>
wilc1000: fix crash observed in AP mode with cfg80211_register_netdevice()
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix dmabuf ptr assignment in lpfc_ct_reject_event()
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix element offset in __lpfc_sli_release_iocbq_s4()
Baochen Qiang <quic_bqiang@quicinc.com>
ath11k: Don't check arvif->is_started before sending management frames
Ravi Bangoria <ravi.bangoria@amd.com>
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Jerome Marchand <jmarchan@redhat.com>
samples: bpf: Don't fail for a missing VMLINUX_BTF when VMLINUX_H is provided
Konrad Dybcio <konrad.dybcio@somainline.org>
regulator: qcom_smd: Fix up PM8950 regulator configuration
Viresh Kumar <viresh.kumar@linaro.org>
Revert "cpufreq: Fix possible race in cpufreq online error path"
Andrii Nakryiko <andrii@kernel.org>
selftests/bpf: Prevent skeleton generation race
Yang Yingliang <yangyingliang@huawei.com>
spi: spi-fsl-qspi: check return value after calling platform_get_resource_byname()
Andreas Gruenbacher <agruenba@redhat.com>
iomap: iomap_write_failed fix
Mark Rutland <mark.rutland@arm.com>
arm64: stackleak: fix current_top_of_stack()
Xiaomeng Tong <xiam0nd.tong@gmail.com>
media: uvcvideo: Fix missing check to determine if element is found in list
Dan Carpenter <dan.carpenter@oracle.com>
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: fix event thread stuck in wait_event after kthread_stop()
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix address for second DSI PHY on SDM660
Vinod Polimera <quic_vpolimer@quicinc.com>
drm/msm/disp/dpu1: avoid clearing hw interrupts if hw_intr is null during drm uninit
Ilkka Koskinen <ilkka@os.amperecomputing.com>
ACPI: AGDI: Fix missing prototype warning for acpi_agdi_init()
Peter Zijlstra <peterz@infradead.org>
linkage: Fix issue with missing symbol size
H. Nikolaus Schaller <hns@goldelico.com>
wl1251: dynamically allocate memory used for DMA
Zev Weiss <zev@bewilderbeest.net>
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Tong Tiangen <tongtiangen@huawei.com>
arm64: fix types in copy_highpage()
Randy Dunlap <rdunlap@infradead.org>
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
irqchip/aspeed-scu-ic: Fix irq_of_parse_and_map() return value
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
Daniel Thompson <daniel.thompson@linaro.org>
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Randy Dunlap <rdunlap@infradead.org>
x86: Fix return value of __setup handlers
Johannes Berg <johannes.berg@intel.com>
nl80211: don't hold RTNL in color change request
Christoph Hellwig <hch@lst.de>
virtio_blk: fix the discard_granularity and discard_alignment queue limits
James Clark <james.clark@arm.com>
perf tools: Use Python devtools for version autodetection rather than runtime
Ian Abbott <abbotti@mev.co.uk>
spi: cadence-quadspi: fix Direct Access Mode disable for SoCFPGA
Yang Yingliang <yangyingliang@huawei.com>
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
Daniel Latypov <dlatypov@google.com>
kunit: fix debugfs code to use enum kunit_status, not bool
Luca Weiss <luca@z3ntu.xyz>
drm/msm: Fix null pointer dereferences without iommu
Pin-Yen Lin <treapking@chromium.org>
drm/bridge: it6505: Send DPCD SET_POWER to downstream
Jagan Teki <jagan@amarulasolutions.com>
drm/panel: panel-simple: Fix proper bpc for AM-1280800N3TZQW-T00H
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: add missing include to msm_drv.c
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
Yang Yingliang <yangyingliang@huawei.com>
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix error checks and return values for DSI xmit functions
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: do not stop transmitting phy test pattern during DP phy compliance test
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: reset DP controller before transmit phy test pattern
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/dp: fix error check return value of irq_of_parse_and_map()
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: stop event kernel thread when DP unbind
Vinod Polimera <quic_vpolimer@quicinc.com>
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
Yang Jihong <yangjihong1@huawei.com>
perf tools: Add missing headers needed by util/data.h
Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
ASoC: rk3328: fix disabling mclk on pclk probe failure
Josh Poimboeuf <jpoimboe@redhat.com>
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
Yang Yingliang <yangyingliang@huawei.com>
mtd: rawnand: intel: fix possible null-ptr-deref in ebu_nand_probe()
Yang Yingliang <yangyingliang@huawei.com>
mtd: rawnand: cadence: fix possible null-ptr-deref in cadence_nand_dt_probe()
Matthieu Baerts <matthieu.baerts@tessares.net>
x86/pm: Fix false positive kmemleak report in msr_build_context()
Chen-Tsung Hsieh <chentsung@chromium.org>
mtd: spi-nor: core: Check written SR value in spi_nor_write_16bit_sr_and_check()
Andrii Nakryiko <andrii@kernel.org>
libbpf: Fix logic for finding matching program for CO-RE relocation
Colin Ian King <colin.king@intel.com>
selftests/resctrl: Fix null pointer dereference on open failed
Colin Ian King <colin.king@intel.com>
drm/v3d: Fix null pointer dereference of pointer perfmon
Kiwoong Kim <kwmad.kim@samsung.com>
scsi: ufs: core: Exclude UECxx from SFR dump list
Bart Van Assche <bvanassche@acm.org>
scsi: ufs: qcom: Fix ufs_qcom_resume()
Dan Carpenter <dan.carpenter@oracle.com>
scsi: iscsi: Fix harmless double shift bug
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dpu: adjust display_v_end for eDP and DP
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: properly add and remove internal bridges
Yuanchu Xie <yuanchu@google.com>
selftests/damon: add damon to selftests root Makefile
Nuno Sá <nuno.sa@analog.com>
of: overlay: do not break notify on NOTIFY_{OK|STOP}
Luca Ceresoli <luca.ceresoli@bootlin.com>
spi: rockchip: fix missing error on unsupported SPI_CS_HIGH
Amir Goldstein <amir73il@gmail.com>
fsnotify: fix wrong lockdep annotations
Amir Goldstein <amir73il@gmail.com>
inotify: show inotify mask flags in proc fdinfo
Bjørn Mork <bjorn@mork.no>
mtdblock: warn if opened on NAND
Colin Ian King <colin.king@intel.com>
ALSA: pcm: Check for null pointer of pointer substream before dereferencing it
Marek Vasut <marex@denx.de>
drm/panel: simple: Add missing bus flags for Innolux G070Y2-L01
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: imx: imx-mipi-csis: Fix active format initialization on source pad
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: imx: imx-mipi-csis: Rename csi_state to mipi_csis_device
Chen-Yu Tsai <wenst@chromium.org>
media: hantro: Empty encoder capture buffers by default
Chen-Yu Tsai <wenst@chromium.org>
media: hantro: Implement support for encoder commands
Ming Qian <ming.qian@nxp.com>
media: amphion: fix decoder's interlaced field
Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
media: i2c: max9286: fix kernel oops when removing module
Dan Carpenter <dan.carpenter@oracle.com>
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
John Ogness <john.ogness@linutronix.de>
printk: wake waiters for safe and NMI contexts
John Ogness <john.ogness@linutronix.de>
printk: add missing memory barrier to wake_up_klogd()
Schspa Shi <schspa@gmail.com>
cpufreq: Fix possible race in cpufreq online error path
Robert Foss <robert.foss@linaro.org>
drm/bridge: Fix it6505 Kconfig DRM_DP_AUX_BUS dependency
Zheng Yongjun <zhengyongjun3@huawei.com>
spi: img-spfi: Fix pm_runtime_get_sync() error checking
Chengming Zhou <zhouchengming@bytedance.com>
sched/psi: report zeroes for CPU full at the system level
Chengming Zhou <zhouchengming@bytedance.com>
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
Marco Elver <elver@google.com>
signal: Deliver SIGTRAP on perf event asynchronously if blocked
Nícolas F. R. A. Prado <nfraprado@collabora.com>
drm/mediatek: dpi: Use mt8183 output formats for mt8192
Wei Yongjun <weiyongjun1@huawei.com>
regulator: da9121: Fix uninit-value in da9121_assign_chip_model()
Miaoqian Lin <linmq006@gmail.com>
drm/bridge: Fix error handling in analogix_dp_probe
Miaoqian Lin <linmq006@gmail.com>
HID: elan: Fix potential double free in elan_input_configured
Jonathan Teh <jonathan.teh@outlook.com>
HID: hid-led: fix maximum brightness for Dream Cheeky
Zheyu Ma <zheyuma97@gmail.com>
mtd: rawnand: denali: Use managed device resources
Nícolas F. R. A. Prado <nfraprado@collabora.com>
drm/bridge: anx7625: Use uint8 for lane-swing arrays
Stanislav Fomichev <sdf@google.com>
bpf: Move rcu lock management out of BPF_PROG_RUN routines
Tyler Hicks <tyhicks@linux.microsoft.com>
EDAC/dmc520: Don't print an error for each unconfigured interrupt line
Arnd Bergmann <arnd@arndb.de>
drbd: fix duplicate array initializer
Christoph Hellwig <hch@lst.de>
drbd: use bdev_alignment_offset instead of queue_alignment_offset
Christoph Hellwig <hch@lst.de>
drbd: use bdev based limit helpers in drbd_send_sizes
Christoph Hellwig <hch@lst.de>
drbd: remove assign_p_sizes_qlim
Christoph Hellwig <hch@lst.de>
target: remove an incorrect unmap zeroes data deduction
Ansuel Smith <ansuelsmth@gmail.com>
net: dsa: qca8k: correctly handle mdio read error
Gavin Wan <Gavin.Wan@amd.com>
drm/amd/amdgpu: Remove static from variable in RLCG Reg RW
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
device property: Allow error pointer to be passed to fwnode APIs
Jan Kiszka <jan.kiszka@siemens.com>
efi: Add missing prototype for efi_capsule_setup_info
Javier Martinez Canillas <javierm@redhat.com>
efi: Allow to enable EFI runtime services by default on RT
Kevin Hao <haokexin@gmail.com>
cpufreq: governor: Use kobject release() method to free dbs_data
Lin Ma <linma@zju.edu.cn>
NFC: NULL out the dev->rfkill to prevent UAF
Lv Ruyi <lv.ruyi@zte.com.cn>
ixp4xx_eth: fix error check return value of platform_get_irq()
Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
net: dsa: mt7530: 1G can also support 1000BASE-X link mode
YueHaibing <yuehaibing@huawei.com>
net: ethernet: ti: am65-cpsw: Fix build error without PHYLINK
Paul E. McKenney <paulmck@kernel.org>
scftorture: Fix distribution of short handler delays
Miaoqian Lin <linmq006@gmail.com>
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
Yongqiang Sun <yongqiang.sun@amd.com>
drm/amd/amdgpu: Fix asm/hypervisor.h build error.
Jiasheng Jiang <jiasheng@iscas.ac.cn>
drm: mali-dp: potential dereference of null pointer
Zhou Qingyang <zhou1615@umn.edu>
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Johannes Berg <johannes.berg@intel.com>
nl80211: show SSID for P2P_GO interfaces
Paolo Abeni <pabeni@redhat.com>
mptcp: reset the packet scheduler on PRIO change
Paolo Abeni <pabeni@redhat.com>
mptcp: reset the packet scheduler on incoming MP_PRIO
Paolo Abeni <pabeni@redhat.com>
mptcp: optimize release_cb for the common case
Maciej W. Rozycki <macro@orcam.me.uk>
x86/PCI: Fix ALi M1487 (IBC) PIRQ router link value interpretation
Andrii Nakryiko <andrii@kernel.org>
libbpf: Don't error out on CO-RE relos for overriden weak subprogs
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hvs: Reset muxes at probe time
Yongqiang Sun <yongqiang.sun@amd.com>
drm/amd/amdgpu: Only reserve vram for firmware with vega9 MS_HYPERV host.
Miles Chen <miles.chen@mediatek.com>
drm/mediatek: Fix mtk_cec_mask()
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hvs: Fix frame count register readout
Maxime Ripard <maxime@cerno.tech>
drm/vc4: kms: Take old state core clock rate into account
Chen-Yu Tsai <wenst@chromium.org>
drm/mediatek: Fix DPI component detection for MT8192
Rex-BC Chen <rex-bc.chen@mediatek.com>
drm/mediatek: Add vblank register/unregister callback functions
Ammar Faizi <ammarfaizi2@gnuweeb.org>
x86/delay: Fix the wrong asm constraint in delay_loop()
Akira Yokosawa <akiyks@gmail.com>
docs: driver-api/thermal/intel_dptf: Use copyright symbol
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
ASoC: SOF: ipc3-topology: Set scontrol->priv to NULL after freeing it
Hui Wang <hui.wang@canonical.com>
ASoC: cs35l41: Fix an out-of-bounds access in otp_packed_element_t
Srinivasa Rao Mandadapu <quic_srivasam@quicinc.com>
ASoC: codecs: Fix error handling in power domain init and exit handlers
Kuldeep Singh <singh.kuldeep87k@gmail.com>
spi: qcom-qspi: Add minItems to interconnect-names
Chuanhong Guo <gch981213@gmail.com>
mtd: spinand: gigadevice: fix Quad IO for GD5F1GQ5UExxG
Marek Vasut <marex@denx.de>
drm: bridge: icn6211: Fix HFP_HSW_HBP_HI and HFP_MIN handling
Marek Vasut <marex@denx.de>
drm: bridge: icn6211: Fix register layout
Lucas Stach <l.stach@pengutronix.de>
drm/bridge: adv7511: clean up CEC adapter when probe fails
Yang Yingliang <yangyingliang@huawei.com>
drm/bridge: anx7625: add missing destroy_workqueue() in anx7625_i2c_probe()
Jani Nikula <jani.nikula@intel.com>
drm/edid: fix invalid EDID extension block filtering
Wenli Looi <wlooi@ucalgary.ca>
ath9k: fix ar9003_get_eepmisc
YueHaibing <yuehaibing@huawei.com>
drm/bridge: it6505: Fix build error
Nicolas Belin <nbelin@baylibre.com>
drm: bridge: it66121: Fix the register page length
Niels Dossche <dossche.niels@gmail.com>
ath11k: acquire ab->base_lock in unassign when finding the peer by addr
Zack Rusin <zackr@vmware.com>
drm/vmwgfx: Fix an invalid read
Chuansheng Liu <chuansheng.liu@intel.com>
fbdev: defio: fix the pagelist corruption
Geert Uytterhoeven <geert@linux-m68k.org>
drm/ssd130x: Reduce temporary buffer sizes
Geert Uytterhoeven <geert@linux-m68k.org>
drm/ssd130x: Fix rectangle updates
Geert Uytterhoeven <geert@linux-m68k.org>
drm/format-helper: Fix XRGB888 to monochrome conversion
Geert Uytterhoeven <geert@linux-m68k.org>
drm/format-helper: Rename drm_fb_xrgb8888_to_mono_reversed()
YueHaibing <yuehaibing@huawei.com>
drm/solomon: Make DRM_SSD130X depends on MMU
Chen-Yu Tsai <wens@csie.org>
drm: ssd130x: Always apply segment remap setting
Chen-Yu Tsai <wens@csie.org>
drm: ssd130x: Fix COM scan direction register mask
Tom Rix <trix@redhat.com>
drm/bridge: anx7625: check the return on anx7625_aux_trans
Noralf Trønnes <noralf@tronnes.org>
dt-bindings: display: sitronix, st7735r: Fix backlight in example
Wan Jiabing <wanjiabing@vivo.com>
drm/omap: fix NULL but dereferenced coccicheck error
Dan Carpenter <dan.carpenter@oracle.com>
drm/selftests: missing error code in igt_buddy_alloc_smoke()
Nikita Yushchenko <nikita.yoush@cogentembedded.com>
drm/bridge_connector: enable HPD by default if supported
Linus Torvalds <torvalds@linux-foundation.org>
drm: fix EDID struct for old ARM OABI format
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Input: gpio-keys - cancel delayed work only in case of GPIO
Shyam Prasad N <sprasad@microsoft.com>
cifs: do not use tcpStatus after negotiate completes
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent panic when SDMA is disabled
Steve French <stfrench@microsoft.com>
smb3: check for null tcon
Vasily Averin <vasily.averin@linux.dev>
fanotify: fix incorrect fmode_t casts
Peng Wu <wupeng58@huawei.com>
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Finn Thain <fthain@linux-m68k.org>
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/powernv: fix missing of_node_put in uv_init()
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/xics: fix refcount leak in icp_opal_init()
Haren Myneni <haren@linux.ibm.com>
powerpc/powernv/vas: Assign real address to rx_fifo in vas_rx_win_attr
Enzo Matsumiya <ematsumiya@suse.de>
cifs: return ENOENT for DFS lookup_cache_entry()
Vasily Averin <vasily.averin@linux.dev>
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
Matthew Wilcox (Oracle) <willy@infradead.org>
alpha: fix alloc_zeroed_user_highpage_movable()
Nicholas Piggin <npiggin@gmail.com>
KVM: PPC: Book3S HV Nested: L2 LPCR should inherit L1 LPES setting
Parshuram Thombare <pthombar@cadence.com>
PCI: cadence: Clear FLR in device capabilities register
Yicong Yang <yangyicong@hisilicon.com>
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Laurent Dufour <ldufour@linux.ibm.com>
powerpc/rtas: Keep MSR[RI] set when calling RTAS
Conor Dooley <conor.dooley@microchip.com>
PCI: microchip: Add missing chained_irq_enter()/exit() calls
Viresh Kumar <viresh.kumar@linaro.org>
cpufreq: Avoid unnecessary frequency updates due to mismatch
Peng Wu <wupeng58@huawei.com>
ARM: hisi: Add missing of_node_put after of_find_compatible_node
Vijaya Krishna Nivarthi <quic_vnivarth@quicinc.com>
arm64: dts: qcom: sc7280-qcard: Configure CTS pin to bias-bus-hold for bluetooth
Vijaya Krishna Nivarthi <quic_vnivarth@quicinc.com>
arm64: dts: qcom: sc7280-idp: Configure CTS pin to bias-bus-hold for bluetooth
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
Peng Wu <wupeng58@huawei.com>
ARM: versatile: Add missing of_node_put in dcscb_init
Yang Yingliang <yangyingliang@huawei.com>
pinctrl: renesas: rzn1: Fix possible null-ptr-deref in sh_pfc_map_resources()
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
fat: add ratelimit to fat*_ent_bread()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: Fix fadump to work with a different endian capture kernel
Janusz Krzysztofik <jmkrzyszt@gmail.com>
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Move generic implicit fb quirk entries into quirks.c
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Add quirk bits for enabling/disabling generic implicit fb
Joel Selvaraj <jo@jsfamily.in>
arm64: dts: qcom: sdm845-xiaomi-beryllium: fix typo in panel's vddio-supply property
Zixuan Fu <r33s3n6@gmail.com>
fs: jfs: fix possible NULL pointer dereference in dbFree()
QintaoShen <unSimple1993@163.com>
soc: ti: ti_sci_pm_domains: Check for null return of devm_kcalloc
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - fix off-by-one error in PFVF debug print
Gilad Ben-Yossef <gilad@benyossef.com>
crypto: ccree - use fine grained DMA mapping dir
Brian Norris <briannorris@chromium.org>
PM / devfreq: rk3399_dmc: Disable edev on remove()
Konrad Dybcio <konrad.dybcio@somainline.org>
arm64: dts: qcom: msm8994: Fix BLSP[12]_DMA channels count
Konrad Dybcio <konrad.dybcio@somainline.org>
arm64: dts: qcom: msm8994: Fix the cont_splash_mem address
Mario Limonciello <mario.limonciello@amd.com>
ASoC: amd: Add driver data to acp6x machine driver
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: s5pv210: align DMA channels with dtschema
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: socfpga: align interrupt controller node name with dtschema
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: ox820: align interrupt controller node name with dtschema
Mika Westerberg <mika.westerberg@linux.intel.com>
PCI/ASPM: Make Intel DG2 L1 acceptable latency unlimited
Niels Dossche <dossche.niels@gmail.com>
IB/rdmavt: add missing locks in rvt_ruc_loopback
Daniel Latypov <dlatypov@google.com>
kunit: fix executor OOM error handling logic on non-UML
Bodo Stroesser <bostroesser@gmail.com>
scsi: target: tcmu: Avoid holding XArray lock when calling lock_page
Linus Torvalds <torvalds@linux-foundation.org>
linux/types.h: reinstate "__bitwise__" macro for user space use
Bob Peterson <rpeterso@redhat.com>
gfs2: use i_lock spin_lock for inode qadata
Yonghong Song <yhs@fb.com>
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
char: tpm: cr50_i2c: Suppress duplicated error message in .remove()
Jakub Kicinski <kuba@kernel.org>
eth: tg3: silence the GCC 12 array-bounds warning
David Howells <dhowells@redhat.com>
afs: Adjust ACK interpretation to try and cope with NAT
David Howells <dhowells@redhat.com>
rxrpc, afs: Fix selection of abort codes
David Howells <dhowells@redhat.com>
rxrpc: Return an error to sendmsg if call failed
Mårten Lindahl <marten.lindahl@axis.com>
hwmon: (pmbus) Add get_voltage/set_voltage ops
Geert Uytterhoeven <geert@linux-m68k.org>
m68k: atari: Make Atari ROM port I/O write macros return void
Yuntao Wang <ytcoode@gmail.com>
selftests/bpf: Add missing trampoline program type to trampoline_count test
Alex Elder <elder@linaro.org>
net: ipa: ignore endianness if there is no header
Borislav Petkov <bp@suse.de>
x86/microcode: Add explicit CPU vendor dependency
Vincent Mailhol <mailhol.vincent@wanadoo.fr>
can: mcp251xfd: silence clang's -Wunaligned-access warning
Chaitanya Kulkarni <kch@nvidia.com>
nvme: set non-mdts limits in nvme_scan_work
Pierre Gondois <Pierre.Gondois@arm.com>
ACPI: CPPC: Assume no transition latency if no PCCT
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: rt1015p: remove dependency on GPIOLIB
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: max98357a: remove dependency on GPIOLIB
Laibin Qiu <qiulaibin@huawei.com>
blk-throttle: Set BIO_THROTTLED when bio has been throttled
Andre Przywara <andre.przywara@arm.com>
of/fdt: Ignore disabled memory nodes
Ping-Ke Shih <pkshih@realtek.com>
rtw89: cfo: check mac_id to avoid out-of-bounds
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: hantro: Stop using H.264 parameter pic_num
Kwanghoon Son <k.son@samsung.com>
media: exynos4-is: Fix compile warning
Fabio Estevam <festevam@denx.de>
net: phy: micrel: Allow probing without .driver_data
Daniel Latypov <dlatypov@google.com>
kunit: tool: make parser stop overwriting status of suites w/ no_tests
Omar Sandoval <osandov@fb.com>
btrfs: fix anon_dev leak in create_subvol()
Hans de Goede <hdegoede@redhat.com>
drm/amdgpu: Move mutex_init(&smu->message_lock) to smu_early_init()
Sathishkumar S <sathishkumar.sundararaju@amd.com>
drm/amd/pm: update smartshift powerboost calc for smu13
Sathishkumar S <sathishkumar.sundararaju@amd.com>
drm/amd/pm: update smartshift powerboost calc for smu12
Xie Yongji <xieyongji@bytedance.com>
nbd: Fix hung on disconnect request if socket is closed before
Lin Ma <linma@zju.edu.cn>
ASoC: rt5645: Fix errorenous cleanup order
Smith, Kyle Miller (Nimble Kernel) <kyles@hpe.com>
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Jason A. Donenfeld <Jason@zx2c4.com>
openrisc: start CPU timer early in boot
Yunfei Dong <yunfei.dong@mediatek.com>
media: mediatek: vcodec: prevent kernel crash when rmmod mtk-vcodec-dec.ko
Pavan Chebbi <pavan.chebbi@broadcom.com>
bnxt_en: Configure ptp filters during bnxt open
Zijun Hu <quic_zijuhu@quicinc.com>
Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ERR_DATA_REPORTING for QCA
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN for QCA
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: HCI: Add HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN quirk
Lukas Wunner <lukas@wunner.de>
usbnet: Run unregister_netdev() before unbind() again
Hans Verkuil <hverkuil-cisco@xs4all.nl>
media: cec-adap.c: fix is_configuring state
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
media: imon: reorganize serialization
Hans Verkuil <hverkuil-cisco@xs4all.nl>
media: ccs-core.c: fix failure to call clk_disable_unprepare
Benjamin Gaignard <benjamin.gaignard@collabora.com>
media: hantro: HEVC: unconditionnaly set pps_{cb/cr}_qp_offset values
Philipp Zabel <p.zabel@pengutronix.de>
media: coda: limit frame interval enumeration to supported encoder frame sizes
Hangyu Hua <hbh25y@gmail.com>
media: rga: fix possible memory leak in rga_probe
Felix Fietkau <nbd@nbd.name>
mt76: fix encap offload ethernet type check
Felix Fietkau <nbd@nbd.name>
mt76: mt7921: accept rx frames with non-standard VHT MCS10-11
Felix Fietkau <nbd@nbd.name>
mt76: mt7915: accept rx frames with non-standard VHT MCS10-11
Dongliang Mu <mudongliangabcd@gmail.com>
rtlwifi: Use pr_warn instead of WARN_ONCE
Daniel Latypov <dlatypov@google.com>
kunit: bail out of test filtering logic quicker if OOM
Corey Minyard <cminyard@mvista.com>
ipmi: Fix pr_fmt to avoid compilation issues
Corey Minyard <cminyard@mvista.com>
ipmi: Add an intializer for ipmi_smi_msg struct
Corey Minyard <cminyard@mvista.com>
ipmi:ssif: Check for NULL msg when handling events and messages
Mario Limonciello <mario.limonciello@amd.com>
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
Zheng Bin <zhengbin13@huawei.com>
ASoC: SOF: amd: add missing platform_device_unregister in acp_pci_rn_probe
Christian Brauner <brauner@kernel.org>
fs: hold writers when changing mount's idmapping
Mikulas Patocka <mpatocka@redhat.com>
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
Patrice Chotard <patrice.chotard@foss.st.com>
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Hao Jia <jiahao.os@bytedance.com>
sched/core: Avoid obvious double update_rq_clock warning
Ravi Bangoria <ravi.bangoria@amd.com>
perf/amd/ibs: Cascade pmu init functions' return value
Heiko Carstens <hca@linux.ibm.com>
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Eric Dumazet <edumazet@google.com>
net: remove two BUG() from skb_checksum_help()
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Alter FPIN stat accounting logic
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Inhibit aborts if external loopback plug is inserted
Xiang Chen <chenxiang66@hisilicon.com>
scsi: hisi_sas: Undo RPM resume for failed notify phy event for v3 HW
Brent Lu <brent.lu@intel.com>
ASoC: Intel: sof_ssp_amp: fix no DMIC BE Link on Chromebooks
Gavin Li <gavinl@nvidia.com>
net/mlx5: Increase FW pre-init timeout for health recovery
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
Zhen Lei <thunder.leizhen@huawei.com>
of: Support more than one crash kernel regions for kexec -s
Thierry Reding <treding@nvidia.com>
drm/tegra: gem: Do not try to dereference ERR_PTR()
Dongliang Mu <mudongliangabcd@gmail.com>
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
Jacob Keller <jacob.e.keller@intel.com>
ice: always check VF VSI pointer values
Nícolas F. R. A. Prado <nfraprado@collabora.com>
regulator: mt6315: Enforce regulator-compatible, not name
Alice Wong <shiwei.wong@amd.com>
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/psp: move PSP memory alloc from hw_init to sw_init
Petr Machata <petrm@nvidia.com>
mlxsw: Treat LLDP packets as control
Petr Machata <petrm@nvidia.com>
mlxsw: spectrum_dcb: Do not warn about priority changes
Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
ASoC: SOF: ipc3-topology: Correct get_control_data for non bytes payload
Mark Brown <broonie@kernel.org>
ASoC: dapm: Don't fold register value changes into notifications
Mark Bloch <mbloch@nvidia.com>
net/mlx5: fs, delete the FTE when there are no rules attached to it
Ziyang Xuan <william.xuanziyang@huawei.com>
net/mlx5: use kvfree() for kvzalloc() in mlx5_ct_fs_smfs_matcher_create
jianghaoran <jianghaoran@kylinos.cn>
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
Xiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
scsi: target: tcmu: Fix possible data corruption
Wen Gong <quic_wgong@quicinc.com>
ath11k: fix warning of not found station for bssid in message
Max Filippov <jcmvbkbc@gmail.com>
xtensa: move trace_hardirqs_off call back to entry.S
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/dpu: Clean up CRC debug logs
Lv Ruyi <lv.ruyi@zte.com.cn>
drm: msm: fix error check return value of irq_of_parse_and_map()
Alexandru Elisei <alexandru.elisei@arm.com>
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Abhishek Kumar <kuabhs@chromium.org>
ath10k: skip ath10k_halt during suspend for driver state RESTARTING
Evan Quan <evan.quan@amd.com>
drm/amd/pm: fix the compile warning
Mukul Joshi <mukul.joshi@amd.com>
drm/amdkfd: Fix circular lock dependency warning
Steven Price <steven.price@arm.com>
drm/plane: Move range check for format_count earlier
Hans de Goede <hdegoede@redhat.com>
ASoC: Intel: bytcr_rt5640: Add quirk for the HP Pro Tablet 408
Hari Chandrakanthan <quic_haric@quicinc.com>
ath11k: disable spectral scan during spectral deinit
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix resource leak in lpfc_sli4_send_seq_to_ulp()
Minghao Chi <chi.minghao@zte.com.cn>
scsi: ufs: Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
Haohui Mai <ricetons@gmail.com>
drm/amdgpu/sdma: Fix incorrect calculations of the wptr of the doorbells
Lv Ruyi <lv.ruyi@zte.com.cn>
scsi: megaraid: Fix error check return value of register_chrdev()
Vignesh Raghavendra <vigneshr@ti.com>
drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit
Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
mmc: jz4740: Apply DMA engine limits to maximum segment size
Heming Zhao <heming.zhao@suse.com>
md/bitmap: don't set sb values if can't pass sanity check
Zheyu Ma <zheyuma97@gmail.com>
media: cx25821: Fix the warning when removing the module
Zheyu Ma <zheyuma97@gmail.com>
media: pci: cx23885: Fix the error handling in cx23885_initdev()
Vikash Garodia <quic_vgarodia@quicinc.com>
media: venus: do not queue internal buffers from previous sequence
Luca Weiss <luca.weiss@fairphone.com>
media: venus: hfi: avoid null dereference in deinit
Zheyu Ma <zheyuma97@gmail.com>
media: i2c: dw9714: Disable the regulator when the driver fails to probe
Sakari Ailus <sakari.ailus@linux.intel.com>
media: Revert "media: dw9768: activate runtime PM and turn off device"
Thibaut VARÈNE <hacks+kernel@slashdirt.org>
ath9k: fix QCA9561 PA bias level
Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
net: macb: In ZynqMP initialization make SGMII phy configuration optional
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: rsnd: care return value from rsnd_node_fixed_index()
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: rsnd: care default case on rsnd_ssiu_busif_err_status_clear()
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
drm/amd/pm: fix double free in si_parse_power_table()
Huang Rui <ray.huang@amd.com>
drm/amdgpu/pm: fix the null pointer while the smu is disabled
Ulf Hansson <ulf.hansson@linaro.org>
cpuidle: PSCI: Improve support for suspend-to-RAM for PSCI OSI mode
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix call trace observed during I/O with CMF enabled
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Protect memory leak for NPIV ports sending PLOGI_RJT
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix null pointer dereference after failing to issue FLOGI and PLOGI
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix SCSI I/O completion and abort handler deadlock
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Move cfg_log_verbose check before calling lpfc_dmp_dbg()
Christoph Hellwig <hch@lst.de>
loop: implement ->free_disk
Eric Dumazet <edumazet@google.com>
tcp: consume incoming skb leading to a reset
Len Brown <len.brown@intel.com>
tools/power turbostat: fix ICX DRAM power numbers
Biju Das <biju.das.jz@bp.renesas.com>
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Po-Hao Huang <phhuang@realtek.com>
rtw88: 8821c: fix debugfs rssi value
Po-Hao Huang <phhuang@realtek.com>
rtw88: fix incorrect frequency reported
Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
ALSA: jack: Access input_dev under mutex
Haowen Bai <baihaowen@meizu.com>
sfc: ef10: Fix assigning negative value to unsigned variable
Paul E. McKenney <paulmck@kernel.org>
rcu: Make TASKS_RUDE_RCU select IRQ_WORK
Paul E. McKenney <paulmck@kernel.org>
rcu-tasks: Handle sparse cpu_possible_mask in rcu_tasks_invoke_cbs()
Padmanabha Srinivasaiah <treasure4paddy@gmail.com>
rcu-tasks: Fix race in schedule and flush work
Saaem Rizvi <syerizvi@amd.com>
drm/amd/display: Disabling Z10 on DCN31
Liviu Dudau <liviu.dudau@arm.com>
drm/komeda: return early if drm_universal_plane_init() fails.
Peter Seiderer <ps.report@gmx.net>
mac80211: minstrel_ht: fix where rate stats are stored (fixes debugfs output)
Runqing Yang <rainkin1993@gmail.com>
libbpf: Fix a bug with checking bpf_probe_read_kernel() support in old kernels
Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
ACPICA: Avoid cache flush inside virtual machines
Mike Travis <mike.travis@hpe.com>
x86/platform/uv: Update TSC sync state for UV5
Daniel Vetter <daniel.vetter@ffwll.ch>
fbcon: Consistently protect deferred_takeover with console_lock()
Niels Dossche <dossche.niels@gmail.com>
ipv6: fix locking issues with loops over idev->addr_list
Haowen Bai <baihaowen@meizu.com>
ipw2x00: Fix potential NULL dereference in libipw_xmit()
Haowen Bai <baihaowen@meizu.com>
b43: Fix assigning negative value to unsigned variable
Haowen Bai <baihaowen@meizu.com>
b43legacy: Fix assigning negative value to unsigned variable
Niels Dossche <dossche.niels@gmail.com>
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
Po Hao Huang <phhuang@realtek.com>
rtw89: fix misconfiguration on hw_scan channel time
Zong-Zhe Yang <kevin_yang@realtek.com>
rtw89: ser: fix CAM leaks occurring in L2 reset
Yuntao Wang <ytcoode@gmail.com>
selftests/bpf: Fix file descriptor leak in load_kallsyms()
Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
ath11k: Change max no of active probe SSID and BSSID to fw capability
Quentin Monnet <quentin@isovalent.com>
selftests/bpf: Fix parsing of prog types in UAPI hdr for bpftool sync
Nikolay Borisov <nborisov@suse.com>
selftests/bpf: Fix vfs_link kprobe definition
Liu Zixian <liuzixian4@huawei.com>
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Wen Gong <quic_wgong@quicinc.com>
ath11k: fix the warning of dev_wake in mhi_pm_disable_transition()
Zack Rusin <zackr@vmware.com>
drm/vmwgfx: validate the screen formats
Arunpravin <Arunpravin.PaneerSelvam@amd.com>
drm/selftests: fix a shift-out-of-bounds bug
Tejas Upadhyay <tejaskumarx.surendrakumar.upadhyay@intel.com>
iommu/vt-d: Add RPLS to quirk list to skip TE disabling
Naohiro Aota <naohiro.aota@wdc.com>
btrfs: zoned: fix comparison of alloc_offset vs meta_write_pointer
Naohiro Aota <naohiro.aota@wdc.com>
btrfs: zoned: finish block group when there are no more allocatable bytes left
Naohiro Aota <naohiro.aota@wdc.com>
btrfs: zoned: zone finish unused block group
Naohiro Aota <naohiro.aota@wdc.com>
btrfs: zoned: properly finish block group on metadata write
Filipe Manana <fdmanana@suse.com>
btrfs: fix deadlock between concurrent dio writes when low on free data space
Qu Wenruo <wqu@suse.com>
btrfs: fix the error handling for submit_extent_page() for btrfs_do_readpage()
Qu Wenruo <wqu@suse.com>
btrfs: repair super block num_devices automatically
Qu Wenruo <wqu@suse.com>
btrfs: return correct error number for __extent_writepage_io()
Qu Wenruo <wqu@suse.com>
btrfs: add "0x" prefix for unsupported optional features
Eric W. Biederman <ebiederm@xmission.com>
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Eric W. Biederman <ebiederm@xmission.com>
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
Eric W. Biederman <ebiederm@xmission.com>
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
Eric W. Biederman <ebiederm@xmission.com>
kthread: Don't allocate kthread_struct for init and umh
Kristen Carlson Accardi <kristen@linux.intel.com>
x86/sgx: Set active memcg prior to shmem allocation
Baoquan He <bhe@redhat.com>
x86/kexec: fix memory leak of elf header buffer
Kan Liang <kan.liang@linux.intel.com>
perf/x86/intel: Fix event constraints for ICL
Ammar Faizi <ammarfaizi2@gnuweeb.org>
x86/MCE/AMD: Fix memory leak when threshold_create_bank() fails
Michael Niewöhner <linux@mniewoehner.de>
platform/x86: intel-hid: fix _DSM function index handling
Mathias Nyman <mathias.nyman@linux.intel.com>
xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI
Kishon Vijay Abraham I <kishon@ti.com>
xhci: Set HCD flag to defer primary roothub registration
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: when extending a file with falloc we should make files not-sparse
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: fix potential double free during failed mount
Paulo Alcantara <pc@cjr.nz>
cifs: fix ntlmssp on old servers
Enzo Matsumiya <ematsumiya@suse.de>
cifs: don't call cifs_dfs_query_info_nonascii_quirk() if nodfs was set
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Restore ntfs_xattr_get_acl and ntfs_xattr_set_acl functions
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Update i_ctime when xattr is added
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
fs/ntfs3: Fix some memory leaks in an error handling path of 'log_replay()'
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: In function ntfs_set_acl_ex do not change inode->i_mode if called from function ntfs_init_acl
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Check new size for limits
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Keep preallocated only if option prealloc enabled
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Fix fiemap + fix shrink file size (to remove preallocated space)
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Update valid size if -EIOCBQUEUED
Mikulas Patocka <mpatocka@redhat.com>
fs/ntfs3: provide block_invalidate_folio to fix memory leak
Kishon Vijay Abraham I <kishon@ti.com>
usb: core: hcd: Add support for deferring roothub registration
Albert Wang <albertccwang@google.com>
usb: dwc3: gadget: Move null pinter check to proper place
Linus Walleij <linus.walleij@linaro.org>
usb: isp1760: Fix out-of-bounds array access
Monish Kumar R <monish.kumar.r@intel.com>
USB: new quirk for Dell Gen 2 devices
Carl Yin(殷张成) <carl.yin@quectel.com>
USB: serial: option: add Quectel BG95 modem
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix type detection for odd device
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Cancel pending work at closing a MIDI substream
Marios Levogiannis <marios.levogiannis@gmail.com>
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Rik van der Kemp <rik@upto11.nl>
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9520 laptop
Kailang Yang <kailang@realtek.com>
ALSA: hda/realtek - Add new type for ALC245
Nathan Chancellor <nathan@kernel.org>
riscv: Move alternative length validation into subsection
Tobias Klauser <tklauser@distanz.ch>
riscv: Wire up memfd_secret in UAPI header
Samuel Holland <samuel@sholland.org>
riscv: Fix irq_work when SMP is disabled
Alexandre Ghiti <alexandre.ghiti@canonical.com>
riscv: Initialize thread pointer before calling C functions
Xianting Tian <xianting.tian@linux.alibaba.com>
RISC-V: Mark IORESOURCE_EXCLUSIVE for reserved mem instead of IORESOURCE_BUSY
Helge Deller <deller@gmx.de>
parisc/stifb: Keep track of hardware path of graphics card
Helge Deller <deller@gmx.de>
parisc/stifb: Implement fb_is_primary_device()
Mikulas Patocka <mpatocka@redhat.com>
parisc: fix a crash with multicore scheduler
Niklas Cassel <niklas.cassel@wdc.com>
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
Stephen Boyd <swboyd@chromium.org>
arm64: Initialize jump labels before setup_machine_fdt()
-------------
Diffstat:
Documentation/accounting/psi.rst | 9 +-
Documentation/conf.py | 2 +-
.../bindings/display/sitronix,st7735r.yaml | 1 +
.../devicetree/bindings/gpio/gpio-altera.txt | 5 +-
.../bindings/regulator/mt6315-regulator.yaml | 2 +-
.../devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml | 1 +
.../bindings/spi/qcom,spi-qcom-qspi.yaml | 1 +
Documentation/driver-api/thermal/intel_dptf.rst | 2 +-
Documentation/sound/alsa-configuration.rst | 4 +-
Documentation/userspace-api/landlock.rst | 4 +-
.../userspace-api/media/lirc.h.rst.exceptions | 2 +
Makefile | 4 +-
arch/alpha/include/asm/page.h | 2 +-
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13 +-
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22 +-
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4 +-
arch/arm/boot/dts/bcm5301x.dtsi | 2 +-
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4 +-
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 6 +-
arch/arm/boot/dts/imx6qdl-colibri.dtsi | 6 +-
arch/arm/boot/dts/lan966x.dtsi | 6 +-
arch/arm/boot/dts/ox820.dtsi | 2 +-
arch/arm/boot/dts/qcom-sdx65.dtsi | 2 +-
arch/arm/boot/dts/s5pv210-aries.dtsi | 3 +-
arch/arm/boot/dts/s5pv210.dtsi | 12 +-
arch/arm/boot/dts/sama7g5.dtsi | 1 -
arch/arm/boot/dts/socfpga.dtsi | 2 +-
arch/arm/boot/dts/socfpga_arria10.dtsi | 2 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 1 +
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4 +-
arch/arm/include/asm/arch_gicv3.h | 7 +-
arch/arm/kernel/signal.c | 1 +
arch/arm/mach-hisi/platsmp.c | 4 +
arch/arm/mach-mediatek/Kconfig | 1 +
arch/arm/mach-omap1/clock.c | 2 +-
arch/arm/mach-pxa/cm-x300.c | 8 +-
arch/arm/mach-pxa/magician.c | 2 +-
arch/arm/mach-pxa/tosa.c | 4 +-
arch/arm/mach-vexpress/dcscb.c | 1 +
arch/arm64/Kconfig.platforms | 1 +
arch/arm64/boot/dts/arm/juno-r1-scmi.dts | 4 +-
arch/arm64/boot/dts/arm/juno-r2-scmi.dts | 4 +-
.../dts/marvell/armada-3720-espressobin-ultra.dts | 5 -
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 2 +-
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 5 +-
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8994.dtsi | 8 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 2 +-
arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi | 4 +-
arch/arm64/boot/dts/qcom/sc7280-idp.dtsi | 18 +-
arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi | 19 +-
.../boot/dts/qcom/sdm845-xiaomi-beryllium.dts | 2 +-
arch/arm64/boot/dts/qcom/sm8450.dtsi | 6 +
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi | 2 -
arch/arm64/configs/defconfig | 1 +
arch/arm64/include/asm/arch_gicv3.h | 6 -
arch/arm64/include/asm/processor.h | 10 +-
arch/arm64/kernel/setup.c | 7 +-
arch/arm64/kernel/signal.c | 1 +
arch/arm64/kernel/signal32.c | 1 +
arch/arm64/kernel/sys_compat.c | 2 +-
arch/arm64/mm/copypage.c | 4 +-
arch/csky/kernel/probes/kprobes.c | 2 +-
arch/m68k/Kconfig.cpu | 2 +-
arch/m68k/include/asm/raw_io.h | 6 +-
arch/m68k/kernel/signal.c | 1 +
.../include/asm/mach-ip27/cpu-feature-overrides.h | 1 -
.../include/asm/mach-ip30/cpu-feature-overrides.h | 1 -
arch/mips/include/asm/mach-ralink/spaces.h | 2 +
arch/openrisc/include/asm/timex.h | 1 +
arch/openrisc/kernel/head.S | 9 +
arch/parisc/include/asm/fb.h | 4 +
arch/parisc/kernel/processor.c | 2 -
arch/parisc/kernel/topology.c | 16 +-
arch/powerpc/include/asm/page.h | 7 +-
arch/powerpc/include/asm/vas.h | 2 +-
arch/powerpc/kernel/entry_64.S | 24 +-
arch/powerpc/kernel/fadump.c | 8 +-
arch/powerpc/kernel/idle.c | 2 +-
arch/powerpc/kernel/rtas.c | 9 +
arch/powerpc/kvm/book3s_hv.c | 12 +-
arch/powerpc/kvm/book3s_hv_nested.c | 3 +-
arch/powerpc/kvm/trace_hv.h | 8 +-
arch/powerpc/mm/nohash/fsl_book3e.c | 15 +-
arch/powerpc/perf/isa207-common.c | 12 +-
arch/powerpc/platforms/4xx/cpm.c | 2 +-
arch/powerpc/platforms/8xx/cpm1.c | 1 +
arch/powerpc/platforms/powernv/opal-fadump.c | 94 +--
arch/powerpc/platforms/powernv/opal-fadump.h | 10 +-
arch/powerpc/platforms/powernv/setup.c | 9 +
arch/powerpc/platforms/powernv/ultravisor.c | 1 +
arch/powerpc/platforms/powernv/vas-fault.c | 2 +-
arch/powerpc/platforms/powernv/vas-window.c | 4 +-
arch/powerpc/platforms/powernv/vas.h | 2 +-
arch/powerpc/platforms/pseries/papr_scm.c | 54 +-
arch/powerpc/sysdev/dart_iommu.c | 6 +-
arch/powerpc/sysdev/fsl_rio.c | 2 +
arch/powerpc/sysdev/xics/icp-opal.c | 1 +
arch/powerpc/sysdev/xive/spapr.c | 7 +-
arch/riscv/Makefile | 4 +
arch/riscv/include/asm/alternative-macros.h | 4 +-
arch/riscv/include/asm/asm.h | 26 -
arch/riscv/include/asm/irq_work.h | 2 +-
arch/riscv/include/asm/unistd.h | 1 -
arch/riscv/include/asm/xip_fixup.h | 31 +
arch/riscv/include/uapi/asm/unistd.h | 1 +
arch/riscv/kernel/head.S | 2 +
arch/riscv/kernel/setup.c | 4 +-
arch/riscv/kernel/suspend_entry.S | 1 +
arch/riscv/mm/init.c | 2 +-
arch/s390/include/asm/cio.h | 2 +-
arch/s390/include/asm/kexec.h | 10 +
arch/s390/include/asm/preempt.h | 15 +-
arch/s390/kernel/perf_event.c | 2 +-
arch/s390/kernel/time.c | 8 +-
arch/sparc/kernel/signal32.c | 1 +
arch/sparc/kernel/signal_64.c | 1 +
arch/um/drivers/chan_user.c | 9 +-
arch/um/drivers/virtio_uml.c | 33 +-
arch/um/include/asm/Kbuild | 1 +
arch/um/include/asm/thread_info.h | 2 +
arch/um/kernel/exec.c | 2 +-
arch/um/kernel/process.c | 2 +-
arch/um/kernel/ptrace.c | 8 +-
arch/um/kernel/signal.c | 4 +-
arch/x86/Kconfig | 4 +-
arch/x86/entry/entry_64.S | 1 +
arch/x86/entry/vdso/vma.c | 2 +-
arch/x86/events/amd/ibs.c | 55 +-
arch/x86/events/intel/core.c | 2 +-
arch/x86/include/asm/acenv.h | 14 +-
arch/x86/include/asm/kexec.h | 8 +
arch/x86/include/asm/set_memory.h | 52 --
arch/x86/include/asm/suspend_32.h | 2 +-
arch/x86/include/asm/suspend_64.h | 12 +-
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/apic/x2apic_uv_x.c | 8 +-
arch/x86/kernel/cpu/intel.c | 2 +-
arch/x86/kernel/cpu/mce/amd.c | 32 +-
arch/x86/kernel/cpu/mce/core.c | 6 +-
arch/x86/kernel/cpu/sgx/encl.c | 105 ++-
arch/x86/kernel/cpu/sgx/encl.h | 7 +-
arch/x86/kernel/cpu/sgx/main.c | 9 +-
arch/x86/kernel/machine_kexec_64.c | 12 +-
arch/x86/kernel/signal_compat.c | 2 +
arch/x86/kernel/step.c | 3 +-
arch/x86/kernel/sys_x86_64.c | 7 +-
arch/x86/kvm/lapic.c | 1 +
arch/x86/kvm/vmx/nested.c | 45 +-
arch/x86/kvm/vmx/vmcs.h | 5 +
arch/x86/lib/delay.c | 4 +-
arch/x86/mm/pat/memtype.c | 2 +-
arch/x86/mm/pat/set_memory.c | 49 +-
arch/x86/pci/irq.c | 19 +-
arch/x86/um/ldt.c | 6 +-
arch/xtensa/kernel/entry.S | 19 +-
arch/xtensa/kernel/ptrace.c | 4 +-
arch/xtensa/kernel/signal.c | 4 +-
arch/xtensa/kernel/traps.c | 11 +-
arch/xtensa/platforms/iss/simdisk.c | 18 +-
block/bfq-cgroup.c | 111 +--
block/bfq-iosched.c | 64 +-
block/bfq-iosched.h | 7 +-
block/blk-cgroup.c | 9 +-
block/blk-cgroup.h | 2 +-
block/blk-ia-ranges.c | 7 +-
block/blk-iocost.c | 5 +-
block/blk-iolatency.c | 130 ++--
block/blk-throttle.c | 3 +-
crypto/cryptd.c | 23 +-
drivers/acpi/arm64/agdi.c | 1 +
drivers/acpi/cppc_acpi.c | 17 +-
drivers/acpi/property.c | 18 +-
drivers/acpi/sleep.c | 12 +
drivers/base/memory.c | 5 +-
drivers/base/node.c | 1 +
drivers/base/power/domain.c | 1 +
drivers/base/property.c | 89 +--
drivers/block/drbd/drbd_main.c | 62 +-
drivers/block/loop.c | 16 +-
drivers/block/nbd.c | 13 +-
drivers/block/virtio_blk.c | 7 +-
drivers/bluetooth/btmtksdio.c | 26 +-
drivers/bluetooth/btusb.c | 6 +
drivers/char/hw_random/cn10k-rng.c | 31 +-
drivers/char/hw_random/omap3-rom-rng.c | 2 +-
drivers/char/ipmi/ipmi_ipmb.c | 1 +
drivers/char/ipmi/ipmi_msghandler.c | 4 +-
drivers/char/ipmi/ipmi_poweroff.c | 4 +-
drivers/char/ipmi/ipmi_ssif.c | 23 +
drivers/char/ipmi/ipmi_watchdog.c | 14 +-
drivers/char/random.c | 12 +-
drivers/char/tpm/tpm_tis_i2c_cr50.c | 4 +-
drivers/clk/tegra/clk-dfll.c | 12 +
drivers/cpufreq/cpufreq.c | 11 +
drivers/cpufreq/cpufreq_governor.c | 20 +-
drivers/cpufreq/cpufreq_governor.h | 1 +
drivers/cpufreq/mediatek-cpufreq.c | 18 +-
drivers/cpuidle/cpuidle-psci-domain.c | 4 +-
drivers/cpuidle/cpuidle-psci.c | 46 ++
drivers/cpuidle/cpuidle-riscv-sbi.c | 4 +-
.../crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c | 115 ++--
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 30 +-
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c | 10 +-
drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 14 +-
drivers/crypto/ccp/sev-dev.c | 30 +-
drivers/crypto/ccree/cc_buffer_mgr.c | 27 +-
drivers/crypto/marvell/cesa/cipher.c | 1 -
drivers/crypto/nx/nx-common-powernv.c | 2 +-
drivers/crypto/qat/qat_common/adf_pfvf_pf_proto.c | 2 +-
.../crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 13 +-
drivers/cxl/mem.c | 4 -
drivers/cxl/pci.c | 40 +-
drivers/devfreq/rk3399_dmc.c | 2 +
drivers/dma/idxd/cdev.c | 8 +-
drivers/dma/stm32-mdma.c | 23 +-
drivers/dma/ti/k3-psil-am62.c | 8 +-
drivers/edac/dmc520_edac.c | 2 +-
drivers/firmware/arm_ffa/driver.c | 4 +-
drivers/firmware/arm_scmi/base.c | 2 +-
drivers/firmware/efi/Kconfig | 15 +
drivers/firmware/efi/efi.c | 2 +-
drivers/gpio/gpio-rockchip.c | 24 +-
drivers/gpio/gpio-sim.c | 4 +-
drivers/gpio/gpiolib-of.c | 5 +
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 13 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 95 ++-
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 10 +-
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4 +-
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 8 +-
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 8 +-
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 7 +-
drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 2 +-
drivers/gpu/drm/amd/amdkfd/kfd_device.c | 2 +
drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 +
drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 7 +-
.../gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 1 +
drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 2 +-
drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c | 14 +-
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 8 +-
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 4 +-
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 60 +-
.../gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 62 +-
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10 +-
drivers/gpu/drm/arm/malidp_crtc.c | 5 +-
drivers/gpu/drm/bridge/Kconfig | 2 +
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1 +
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31 +-
drivers/gpu/drm/bridge/analogix/anx7625.c | 21 +-
drivers/gpu/drm/bridge/analogix/anx7625.h | 4 +-
drivers/gpu/drm/bridge/chipone-icn6211.c | 155 ++++-
drivers/gpu/drm/bridge/ite-it6505.c | 29 +-
drivers/gpu/drm/bridge/ite-it66121.c | 2 +-
drivers/gpu/drm/drm_bridge_connector.c | 4 +-
drivers/gpu/drm/drm_edid.c | 6 +-
drivers/gpu/drm/drm_format_helper.c | 74 +-
drivers/gpu/drm/drm_plane.c | 14 +-
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6 +
drivers/gpu/drm/gma500/psb_intel_display.c | 7 +-
drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 33 +-
drivers/gpu/drm/i915/i915_perf.c | 4 +-
drivers/gpu/drm/i915/i915_perf_types.h | 2 +-
drivers/gpu/drm/mediatek/mtk_cec.c | 2 +-
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 16 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 22 +-
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 20 +-
drivers/gpu/drm/mediatek/mtk_dpi.c | 4 +-
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 14 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 29 +-
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 +
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 19 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 16 +-
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 5 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 3 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 3 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 2 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20 +-
drivers/gpu/drm/msm/dp/dp_ctrl.c | 16 +-
drivers/gpu/drm/msm/dp/dp_display.c | 55 +-
drivers/gpu/drm/msm/dp/dp_drm.c | 4 +
drivers/gpu/drm/msm/dsi/dsi_host.c | 21 +-
drivers/gpu/drm/msm/dsi/dsi_manager.c | 35 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 2 +-
drivers/gpu/drm/msm/hdmi/hdmi.c | 10 +-
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 3 +
drivers/gpu/drm/msm/msm_drv.c | 11 +-
drivers/gpu/drm/msm/msm_gem_prime.c | 2 +-
drivers/gpu/drm/msm/msm_gpu.c | 3 +-
drivers/gpu/drm/msm/msm_gpu.h | 12 +-
drivers/gpu/drm/msm/msm_gpu_devfreq.c | 90 ++-
drivers/gpu/drm/msm/msm_kms.h | 1 +
drivers/gpu/drm/nouveau/dispnv50/atom.h | 6 +-
drivers/gpu/drm/nouveau/dispnv50/crc.c | 27 +-
drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 2 +
drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c | 14 +-
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c | 6 +-
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c | 6 +-
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6 +-
drivers/gpu/drm/omapdrm/omap_overlay.c | 2 +-
drivers/gpu/drm/panel/panel-simple.c | 3 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 +-
drivers/gpu/drm/selftests/test-drm_buddy.c | 10 +-
drivers/gpu/drm/solomon/Kconfig | 2 +-
drivers/gpu/drm/solomon/ssd130x.c | 42 +-
drivers/gpu/drm/stm/ltdc.c | 16 +-
drivers/gpu/drm/tegra/gem.c | 1 +
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8 +-
drivers/gpu/drm/tiny/repaper.c | 2 +-
drivers/gpu/drm/v3d/v3d_perfmon.c | 3 +-
drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
drivers/gpu/drm/vc4/vc4_drv.h | 1 +
drivers/gpu/drm/vc4/vc4_hvs.c | 49 +-
drivers/gpu/drm/vc4/vc4_kms.c | 5 +-
drivers/gpu/drm/vc4/vc4_regs.h | 12 +-
drivers/gpu/drm/vc4/vc4_txp.c | 8 +-
drivers/gpu/drm/virtio/virtgpu_display.c | 2 +
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 30 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1 -
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 14 +-
drivers/hid/amd-sfh-hid/amd_sfh_hid.c | 4 +-
drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2 +-
drivers/hid/hid-bigbenff.c | 6 +
drivers/hid/hid-elan.c | 2 -
drivers/hid/hid-led.c | 2 +-
drivers/hv/channel.c | 6 +-
drivers/hwmon/peci/dimmtemp.c | 6 +-
drivers/hwmon/pmbus/pmbus_core.c | 95 ++-
drivers/hwtracing/coresight/coresight-core.c | 33 +-
drivers/i2c/busses/i2c-at91-master.c | 11 +
drivers/i2c/busses/i2c-npcm7xx.c | 103 ++-
drivers/i2c/busses/i2c-rcar.c | 15 +-
drivers/infiniband/hw/hfi1/file_ops.c | 2 +
drivers/infiniband/hw/hfi1/init.c | 2 +-
drivers/infiniband/hw/hfi1/sdma.c | 12 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 7 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 24 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 2 +-
drivers/infiniband/sw/rdmavt/qp.c | 6 +-
drivers/infiniband/sw/rxe/rxe_mcast.c | 6 +-
drivers/infiniband/sw/rxe/rxe_req.c | 2 +-
drivers/input/keyboard/gpio_keys.c | 2 +-
drivers/input/misc/sparcspkr.c | 1 +
drivers/input/touchscreen/stmfts.c | 16 +-
drivers/iommu/amd/init.c | 2 +-
drivers/iommu/amd/iommu.c | 7 -
drivers/iommu/amd/iommu_v2.c | 12 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 13 +-
drivers/iommu/dma-iommu.c | 7 +-
drivers/iommu/intel/iommu.c | 2 +-
drivers/iommu/msm_iommu.c | 11 +-
drivers/iommu/mtk_iommu.c | 30 +-
drivers/iommu/mtk_iommu.h | 2 +
drivers/iommu/mtk_iommu_v1.c | 7 +
drivers/irqchip/irq-armada-370-xp.c | 11 +-
drivers/irqchip/irq-aspeed-i2c-ic.c | 4 +-
drivers/irqchip/irq-aspeed-scu-ic.c | 4 +-
drivers/irqchip/irq-gic-v3.c | 183 +++--
drivers/irqchip/irq-sni-exiu.c | 25 +-
drivers/irqchip/irq-xtensa-mx.c | 18 +-
drivers/macintosh/Kconfig | 6 +
drivers/macintosh/Makefile | 3 +-
drivers/macintosh/via-pmu.c | 2 +-
drivers/mailbox/mailbox.c | 19 +-
drivers/mailbox/pcc.c | 2 +-
drivers/md/bcache/btree.c | 58 +-
drivers/md/bcache/btree.h | 2 +-
drivers/md/bcache/journal.c | 31 +-
drivers/md/bcache/journal.h | 2 +
drivers/md/bcache/request.c | 6 +
drivers/md/bcache/super.c | 1 +
drivers/md/bcache/writeback.c | 101 +--
drivers/md/bcache/writeback.h | 2 +-
drivers/md/md-bitmap.c | 44 +-
drivers/md/md.c | 22 +-
drivers/md/raid0.c | 1 -
drivers/media/cec/core/cec-adap.c | 6 +-
drivers/media/i2c/Kconfig | 1 +
drivers/media/i2c/ccs/ccs-core.c | 7 +-
drivers/media/i2c/dw9714.c | 1 +
drivers/media/i2c/dw9768.c | 6 -
drivers/media/i2c/max9286.c | 19 +-
drivers/media/i2c/ov5648.c | 4 +-
drivers/media/i2c/ov7670.c | 1 -
drivers/media/i2c/rdacm20.c | 2 +-
drivers/media/i2c/rdacm21.c | 2 +-
drivers/media/pci/cx23885/cx23885-core.c | 6 +-
drivers/media/pci/cx25821/cx25821-core.c | 2 +-
drivers/media/platform/amphion/vdec.c | 2 +-
drivers/media/platform/aspeed/aspeed-video.c | 4 +-
drivers/media/platform/atmel/atmel-sama5d2-isc.c | 7 +-
drivers/media/platform/chips-media/coda-common.c | 35 +-
.../platform/mediatek/vcodec/mtk_vcodec_dec.c | 13 +-
.../platform/mediatek/vcodec/mtk_vcodec_dec_drv.c | 6 +-
drivers/media/platform/nxp/imx-mipi-csis.c | 561 ++++++++-------
drivers/media/platform/qcom/venus/helpers.c | 34 +-
drivers/media/platform/qcom/venus/hfi.c | 3 +
drivers/media/platform/renesas/vsp1/vsp1_rpf.c | 6 +-
drivers/media/platform/rockchip/rga/rga.c | 6 +-
.../media/platform/samsung/exynos4-is/fimc-is.c | 6 +-
.../platform/samsung/exynos4-is/fimc-isp-video.h | 2 +-
drivers/media/platform/st/sti/delta/delta-v4l2.c | 6 +-
drivers/media/radio/Kconfig | 4 +-
drivers/media/rc/bpf-lirc.c | 8 +-
drivers/media/rc/imon.c | 99 ++-
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7 +-
drivers/media/usb/uvc/uvc_v4l2.c | 20 +-
drivers/memory/samsung/exynos5422-dmc.c | 5 +-
drivers/mfd/davinci_voicecodec.c | 6 +-
drivers/mfd/ipaq-micro.c | 2 +-
drivers/misc/fastrpc.c | 9 +-
drivers/misc/ocxl/file.c | 2 +
drivers/mmc/core/block.c | 8 +-
drivers/mmc/host/jz4740_mmc.c | 20 +
drivers/mmc/host/sdhci_am654.c | 23 +-
drivers/mtd/chips/cfi_cmdset_0002.c | 103 ++-
drivers/mtd/mtdblock.c | 8 +-
drivers/mtd/nand/raw/cadence-nand-controller.c | 5 +-
drivers/mtd/nand/raw/denali_pci.c | 15 +-
drivers/mtd/nand/raw/intel-nand-controller.c | 2 +-
drivers/mtd/nand/spi/gigadevice.c | 10 +-
drivers/mtd/spi-nor/core.c | 9 +
drivers/net/amt.c | 11 +-
drivers/net/bonding/bond_main.c | 15 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 2 +-
drivers/net/can/xilinx_can.c | 4 +-
drivers/net/dsa/Kconfig | 3 +-
drivers/net/dsa/mt7530.c | 14 +-
drivers/net/dsa/qca8k.c | 7 +-
drivers/net/ethernet/broadcom/Makefile | 5 +
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 1 +
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 56 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h | 2 +
drivers/net/ethernet/cadence/macb_main.c | 42 +-
drivers/net/ethernet/cadence/macb_ptp.c | 4 +-
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 12 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 2 +
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 2 +-
drivers/net/ethernet/intel/ice/ice_devlink.c | 5 +-
drivers/net/ethernet/intel/ice/ice_repr.c | 7 +-
drivers/net/ethernet/intel/ice/ice_sriov.c | 32 +-
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 28 +-
drivers/net/ethernet/intel/ice/ice_virtchnl.c | 5 +
drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c | 7 +-
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 +
.../ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 9 +
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 10 +-
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10 +-
drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h | 1 +
drivers/net/ethernet/mellanox/mlx5/core/main.c | 23 +-
.../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13 -
.../net/ethernet/mellanox/mlxsw/spectrum_trap.c | 2 +-
drivers/net/ethernet/sfc/ef10.c | 2 +-
.../net/ethernet/stmicro/stmmac/stmmac_selftests.c | 13 +-
drivers/net/ethernet/ti/Kconfig | 1 +
drivers/net/ethernet/xscale/ptp_ixp46x.c | 2 +-
drivers/net/hyperv/netvsc_drv.c | 5 +-
drivers/net/ipa/ipa_endpoint.c | 41 +-
drivers/net/macsec.c | 7 +
drivers/net/phy/micrel.c | 11 +-
drivers/net/usb/asix_devices.c | 6 +-
drivers/net/usb/smsc95xx.c | 3 +-
drivers/net/usb/usbnet.c | 6 +-
drivers/net/wireless/ath/ath10k/mac.c | 20 +-
drivers/net/wireless/ath/ath11k/mac.c | 16 +-
drivers/net/wireless/ath/ath11k/pci.c | 12 +-
drivers/net/wireless/ath/ath11k/spectral.c | 17 +-
drivers/net/wireless/ath/ath11k/wmi.c | 11 +-
drivers/net/wireless/ath/ath11k/wmi.h | 12 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8 +
drivers/net/wireless/ath/carl9170/tx.c | 3 +
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/broadcom/b43legacy/phy.c | 2 +-
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 3 +
drivers/net/wireless/intel/iwlwifi/mei/main.c | 3 +
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3 +
drivers/net/wireless/marvell/mwifiex/11h.c | 2 +
drivers/net/wireless/mediatek/mt76/agg-rx.c | 5 +-
drivers/net/wireless/mediatek/mt76/mac80211.c | 8 +-
drivers/net/wireless/mediatek/mt76/mt76.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt7603/main.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7615/main.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 +-
.../net/wireless/mediatek/mt76/mt7915/debugfs.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c | 2 +
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 35 +-
drivers/net/wireless/mediatek/mt76/mt7915/main.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 20 +-
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt7915/soc.c | 2 +
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6 +-
drivers/net/wireless/mediatek/mt76/mt7921/main.c | 6 +-
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 10 +-
drivers/net/wireless/mediatek/mt76/tx.c | 11 +-
drivers/net/wireless/microchip/wilc1000/mon.c | 4 +-
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8 +-
drivers/net/wireless/realtek/rtlwifi/usb.c | 2 +-
drivers/net/wireless/realtek/rtw88/rtw8821c.c | 4 +
drivers/net/wireless/realtek/rtw88/rx.c | 3 +-
drivers/net/wireless/realtek/rtw89/cam.c | 14 +-
drivers/net/wireless/realtek/rtw89/fw.c | 2 +-
drivers/net/wireless/realtek/rtw89/phy.c | 5 +
drivers/net/wireless/realtek/rtw89/ser.c | 21 +
drivers/net/wireless/ti/wl1251/event.c | 22 +-
drivers/net/wireless/ti/wl1251/io.c | 20 +-
drivers/net/wireless/ti/wl1251/tx.c | 15 +-
drivers/nfc/st21nfca/se.c | 17 +-
drivers/nfc/st21nfca/st21nfca.h | 1 +
drivers/nvdimm/core.c | 9 -
drivers/nvdimm/pmem.c | 30 +-
drivers/nvdimm/security.c | 5 -
drivers/nvme/host/core.c | 21 +-
drivers/nvme/host/pci.c | 1 +
drivers/of/fdt.c | 3 +
drivers/of/kexec.c | 9 +
drivers/of/overlay.c | 4 +-
drivers/opp/of.c | 2 +-
drivers/pci/controller/cadence/pci-j721e.c | 3 +
drivers/pci/controller/cadence/pcie-cadence-ep.c | 21 +-
drivers/pci/controller/cadence/pcie-cadence.h | 3 +
drivers/pci/controller/dwc/pci-imx6.c | 23 +-
drivers/pci/controller/dwc/pcie-designware-host.c | 3 +-
drivers/pci/controller/dwc/pcie-qcom.c | 15 +-
drivers/pci/controller/pcie-mediatek-gen3.c | 8 +
drivers/pci/controller/pcie-mediatek.c | 1 +
drivers/pci/controller/pcie-microchip-host.c | 16 +-
drivers/pci/controller/pcie-rockchip-ep.c | 3 +-
drivers/pci/pci-acpi.c | 41 +-
drivers/pci/pci.c | 12 +-
drivers/pci/pcie/aer.c | 7 +-
drivers/pci/quirks.c | 47 ++
drivers/phy/qualcomm/phy-qcom-qmp.c | 11 +-
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 18 +
drivers/pinctrl/mediatek/Kconfig | 1 +
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2 +-
drivers/pinctrl/pinctrl-apple-gpio.c | 1 +
drivers/pinctrl/pinctrl-rockchip.c | 54 +-
drivers/pinctrl/pinctrl-rockchip.h | 7 +-
drivers/pinctrl/renesas/core.c | 7 +-
drivers/pinctrl/renesas/pfc-r8a779a0.c | 29 +
drivers/pinctrl/renesas/pfc-r8a779f0.c | 21 +
drivers/pinctrl/renesas/pinctrl-rzn1.c | 10 +-
drivers/platform/chrome/cros_ec.c | 16 +-
drivers/platform/chrome/cros_ec_chardev.c | 2 +-
drivers/platform/chrome/cros_ec_proto.c | 50 +-
drivers/platform/mips/cpu_hwmon.c | 127 ++--
drivers/platform/x86/intel/chtwc_int33fe.c | 2 +
drivers/platform/x86/intel/hid.c | 2 +-
drivers/regulator/core.c | 7 +-
drivers/regulator/da9121-regulator.c | 2 +
drivers/regulator/pfuze100-regulator.c | 2 +
drivers/regulator/qcom_smd-regulator.c | 35 +-
drivers/regulator/scmi-regulator.c | 2 +-
drivers/s390/cio/chsc.c | 4 +-
drivers/scsi/dc395x.c | 15 +-
drivers/scsi/fcoe/fcoe_ctlr.c | 2 +-
drivers/scsi/hisi_sas/hisi_sas_main.c | 49 +-
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 +-
drivers/scsi/lpfc/lpfc.h | 1 +
drivers/scsi/lpfc/lpfc_els.c | 112 +--
drivers/scsi/lpfc/lpfc_hbadisc.c | 3 +
drivers/scsi/lpfc/lpfc_init.c | 51 +-
drivers/scsi/lpfc/lpfc_logmsg.h | 6 +-
drivers/scsi/lpfc/lpfc_nportdisc.c | 10 +-
drivers/scsi/lpfc/lpfc_scsi.c | 37 +-
drivers/scsi/lpfc/lpfc_sli.c | 48 +-
drivers/scsi/megaraid.c | 2 +-
drivers/scsi/ufs/ti-j721e-ufs.c | 6 +-
drivers/scsi/ufs/ufs-qcom.c | 14 +-
drivers/scsi/ufs/ufshcd.c | 7 +-
drivers/soc/bcm/bcm63xx/bcm-pmb.c | 3 +
drivers/soc/qcom/llcc-qcom.c | 1 +
drivers/soc/qcom/smp2p.c | 1 +
drivers/soc/qcom/smsm.c | 1 +
drivers/soc/ti/ti_sci_pm_domains.c | 2 +
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-fsl-qspi.c | 4 +
drivers/spi/spi-img-spfi.c | 2 +-
drivers/spi/spi-rockchip.c | 8 +
drivers/spi/spi-rspi.c | 15 +-
drivers/spi/spi-stm32-qspi.c | 3 +-
drivers/spi/spi-ti-qspi.c | 5 +-
drivers/staging/media/hantro/hantro_drv.c | 17 +-
drivers/staging/media/hantro/hantro_g2_hevc_dec.c | 11 +-
drivers/staging/media/hantro/hantro_h264.c | 2 -
drivers/staging/media/hantro/hantro_v4l2.c | 67 +-
drivers/staging/media/rkvdec/rkvdec-h264.c | 37 +-
drivers/staging/media/rkvdec/rkvdec.c | 6 -
drivers/staging/r8188eu/os_dep/ioctl_linux.c | 92 +--
drivers/target/target_core_device.c | 1 -
drivers/target/target_core_user.c | 50 +-
drivers/thermal/broadcom/bcm2711_thermal.c | 5 +-
drivers/thermal/broadcom/sr-thermal.c | 3 +
drivers/thermal/devfreq_cooling.c | 25 +-
drivers/thermal/imx_sc_thermal.c | 6 +-
drivers/thermal/thermal_core.c | 1 +
drivers/tty/goldfish.c | 20 +-
drivers/tty/n_gsm.c | 31 +-
drivers/tty/serial/pch_uart.c | 27 +-
drivers/tty/tty_buffer.c | 3 +-
drivers/usb/core/hcd.c | 29 +-
drivers/usb/core/quirks.c | 3 +
drivers/usb/dwc3/gadget.c | 6 +-
drivers/usb/host/xhci-pci.c | 2 +
drivers/usb/host/xhci.c | 2 +
drivers/usb/isp1760/isp1760-core.c | 8 +
drivers/usb/serial/option.c | 2 +
drivers/usb/serial/pl2303.c | 3 +
drivers/vdpa/vdpa_sim/vdpa_sim.c | 5 +-
drivers/video/console/sticon.c | 5 +-
drivers/video/console/sticore.c | 32 +-
drivers/video/fbdev/amba-clcd.c | 5 +-
drivers/video/fbdev/core/fb_defio.c | 9 +-
drivers/video/fbdev/core/fbcon.c | 5 +-
drivers/video/fbdev/sticore.h | 3 +
drivers/video/fbdev/stifb.c | 4 +-
drivers/video/fbdev/vesafb.c | 5 +-
fs/afs/misc.c | 5 +-
fs/afs/rotate.c | 4 +
fs/afs/rxrpc.c | 8 +-
fs/afs/write.c | 1 +
fs/binfmt_flat.c | 27 +-
fs/btrfs/block-group.c | 8 +
fs/btrfs/block-group.h | 2 +
fs/btrfs/disk-io.c | 4 +-
fs/btrfs/extent_io.c | 27 +-
fs/btrfs/extent_io.h | 1 -
fs/btrfs/inode.c | 81 ++-
fs/btrfs/ioctl.c | 49 +-
fs/btrfs/volumes.c | 8 +-
fs/btrfs/zoned.c | 44 +-
fs/btrfs/zoned.h | 5 +
fs/ceph/mds_client.c | 14 +-
fs/cifs/cifsfs.c | 10 +-
fs/cifs/cifsglob.h | 15 +-
fs/cifs/connect.c | 67 +-
fs/cifs/dfs_cache.c | 6 +-
fs/cifs/fs_context.c | 29 +-
fs/cifs/fs_context.h | 2 +-
fs/cifs/misc.c | 7 +-
fs/cifs/sess.c | 6 +-
fs/cifs/smb2inode.c | 2 -
fs/cifs/smb2ops.c | 9 +-
fs/cifs/smb2pdu.c | 3 +-
fs/cifs/smb2transport.c | 3 +-
fs/dax.c | 3 +-
fs/dlm/lock.c | 15 +-
fs/dlm/lowcomms.c | 2 +-
fs/dlm/plock.c | 12 +-
fs/erofs/decompressor.c | 5 +-
fs/exec.c | 6 +-
fs/exportfs/expfs.c | 5 +-
fs/ext4/ext4.h | 6 -
fs/ext4/extents.c | 20 +-
fs/ext4/inline.c | 12 +
fs/ext4/inode.c | 13 +-
fs/ext4/mballoc.c | 18 +-
fs/ext4/namei.c | 84 ++-
fs/ext4/super.c | 87 ++-
fs/f2fs/dir.c | 3 +-
fs/f2fs/f2fs.h | 29 +-
fs/f2fs/file.c | 20 +-
fs/f2fs/hash.c | 11 +-
fs/f2fs/inline.c | 29 +-
fs/f2fs/inode.c | 19 +-
fs/f2fs/namei.c | 7 +
fs/f2fs/segment.c | 42 +-
fs/f2fs/segment.h | 33 +-
fs/f2fs/super.c | 6 +-
fs/fat/fatent.c | 7 +-
fs/fs-writeback.c | 13 +-
fs/gfs2/quota.c | 32 +-
fs/hugetlbfs/inode.c | 4 +-
fs/io_uring.c | 7 +-
fs/iomap/buffered-io.c | 3 +-
fs/jfs/jfs_dmap.c | 3 +-
fs/ksmbd/connection.c | 2 +-
fs/ksmbd/smb2misc.c | 2 +-
fs/ksmbd/smb_common.c | 4 +-
fs/namei.c | 70 +-
fs/namespace.c | 5 +-
fs/nfs/file.c | 50 +-
fs/nfs/fscache.c | 7 +-
fs/nfs/nfs4namespace.c | 9 +-
fs/nfs/nfs4proc.c | 41 +-
fs/nfs/nfs4state.c | 9 +-
fs/nfs/nfs4xdr.c | 4 +-
fs/nfs/pagelist.c | 3 +
fs/nfs/pnfs.c | 2 +
fs/nfs/unlink.c | 8 +
fs/nfs/write.c | 54 +-
fs/nfsd/nfscache.c | 2 +-
fs/notify/fanotify/fanotify_user.c | 4 +-
fs/notify/fdinfo.c | 11 +-
fs/notify/inotify/inotify.h | 12 +
fs/notify/inotify/inotify_user.c | 2 +-
fs/notify/mark.c | 6 +-
fs/ntfs3/file.c | 12 +-
fs/ntfs3/frecord.c | 10 +-
fs/ntfs3/fslog.c | 12 +-
fs/ntfs3/inode.c | 9 +-
fs/ntfs3/xattr.c | 112 ++-
fs/ocfs2/dlmfs/userdlm.c | 16 +-
fs/ocfs2/inode.c | 4 +-
fs/ocfs2/journal.c | 33 +-
fs/ocfs2/journal.h | 2 +
fs/ocfs2/super.c | 15 +
fs/proc/generic.c | 3 +
fs/proc/proc_net.c | 3 +
fs/seq_file.c | 32 +
include/drm/drm_edid.h | 6 +-
include/drm/drm_format_helper.h | 5 +-
include/linux/blk_types.h | 5 +-
include/linux/bpf.h | 119 +---
include/linux/compat.h | 1 +
include/linux/efi.h | 2 +
include/linux/fwnode.h | 10 +-
include/linux/goldfish.h | 15 +-
include/linux/gpio/driver.h | 12 +
include/linux/ipmi_smi.h | 6 +
include/linux/kexec.h | 46 +-
include/linux/kprobes.h | 2 +-
include/linux/linkage.h | 15 +-
include/linux/list.h | 16 +-
include/linux/mailbox_controller.h | 1 +
include/linux/module.h | 3 +-
include/linux/mtd/cfi.h | 1 +
include/linux/namei.h | 6 +
include/linux/nfs_fs_sb.h | 1 +
include/linux/nfs_xdr.h | 2 +-
include/linux/nodemask.h | 13 +-
include/linux/platform_data/cros_ec_proto.h | 3 +
include/linux/ptp_classify.h | 3 +
include/linux/ptrace.h | 7 -
include/linux/sched/signal.h | 2 +-
include/linux/sched/task.h | 2 +
include/linux/seq_file.h | 4 +
include/linux/set_memory.h | 10 +-
include/linux/usb/hcd.h | 2 +
include/net/bluetooth/hci.h | 9 +
include/net/bluetooth/hci_core.h | 8 +-
include/net/if_inet6.h | 8 +
include/net/ip.h | 2 +-
include/net/sock.h | 5 +-
include/scsi/libfcoe.h | 3 +-
include/scsi/libiscsi.h | 6 +-
include/sound/cs35l41.h | 1 -
include/sound/jack.h | 1 +
include/trace/events/rxrpc.h | 2 +-
include/trace/events/vmscan.h | 4 +-
include/uapi/asm-generic/siginfo.h | 7 +
include/uapi/linux/android/binder.h | 2 +-
include/uapi/linux/landlock.h | 9 +-
include/uapi/linux/lirc.h | 7 +
include/uapi/linux/types.h | 3 +
init/Kconfig | 5 +
init/main.c | 2 +-
ipc/mqueue.c | 14 +
kernel/bpf/cgroup.c | 124 +++-
kernel/dma/debug.c | 2 +-
kernel/dma/direct.c | 31 +-
kernel/events/core.c | 4 +-
kernel/fork.c | 22 +-
kernel/kexec_file.c | 34 -
kernel/kprobes.c | 144 ++--
kernel/module.c | 4 +
kernel/power/energy_model.c | 2 +
kernel/printk/printk.c | 61 +-
kernel/ptrace.c | 5 +-
kernel/rcu/Kconfig | 1 +
kernel/rcu/tasks.h | 5 +-
kernel/scftorture.c | 5 +-
kernel/sched/core.c | 6 +-
kernel/sched/deadline.c | 5 +-
kernel/sched/fair.c | 8 +-
kernel/sched/pelt.h | 4 +-
kernel/sched/psi.c | 15 +-
kernel/sched/rt.c | 5 +-
kernel/sched/sched.h | 32 +-
kernel/signal.c | 18 +-
kernel/trace/bpf_trace.c | 5 +-
kernel/trace/ftrace.c | 5 +-
kernel/trace/trace.c | 6 +-
kernel/trace/trace_boot.c | 2 +-
kernel/trace/trace_events.c | 13 +-
kernel/trace/trace_events_hist.c | 3 +
kernel/trace/trace_osnoise.c | 9 +-
kernel/trace/trace_selftest.c | 3 +
kernel/umh.c | 6 +-
lib/kunit/debugfs.c | 2 +-
lib/kunit/executor.c | 32 +-
lib/kunit/executor_test.c | 4 +-
lib/string_helpers.c | 3 +
mm/cma.c | 4 +-
mm/compaction.c | 2 +
mm/hugetlb.c | 9 +-
mm/memremap.c | 2 +-
mm/page_alloc.c | 4 +-
mm/page_owner.c | 2 +-
net/bluetooth/hci_conn.c | 7 +-
net/bluetooth/hci_event.c | 35 +-
net/bluetooth/hci_request.c | 2 +
net/bluetooth/sco.c | 23 +-
net/core/dev.c | 8 +-
net/ipv4/tcp_input.c | 28 +-
net/ipv6/addrconf.c | 33 +-
net/ipv6/datagram.c | 6 +-
net/ipv6/udp.c | 11 +-
net/mac80211/chan.c | 7 +-
net/mac80211/ieee80211_i.h | 5 +
net/mac80211/rc80211_minstrel_ht.c | 3 +
net/mac80211/scan.c | 20 +
net/mptcp/pm.c | 19 +-
net/mptcp/pm_netlink.c | 2 +
net/mptcp/protocol.c | 18 +-
net/mptcp/protocol.h | 1 +
net/nfc/core.c | 1 +
net/rxrpc/ar-internal.h | 15 +-
net/rxrpc/call_accept.c | 6 +-
net/rxrpc/call_event.c | 7 +-
net/rxrpc/call_object.c | 18 +-
net/rxrpc/conn_object.c | 2 +-
net/rxrpc/input.c | 58 +-
net/rxrpc/net_ns.c | 2 +-
net/rxrpc/output.c | 20 +-
net/rxrpc/proc.c | 10 +-
net/rxrpc/recvmsg.c | 8 +-
net/rxrpc/sendmsg.c | 6 +
net/rxrpc/sysctl.c | 4 +-
net/sctp/input.c | 4 +-
net/smc/af_smc.c | 2 +-
net/wireless/nl80211.c | 4 +-
net/wireless/reg.c | 4 +
samples/bpf/Makefile | 9 +-
samples/landlock/sandboxer.c | 104 +--
scripts/faddr2line | 150 ++--
security/integrity/ima/Kconfig | 14 +-
.../integrity/platform_certs/keyring_handler.h | 8 +
security/integrity/platform_certs/load_uefi.c | 33 +
security/landlock/cred.c | 4 +-
security/landlock/cred.h | 8 +-
security/landlock/fs.c | 191 ++++--
security/landlock/fs.h | 11 +-
security/landlock/limits.h | 8 +-
security/landlock/object.c | 6 +-
security/landlock/object.h | 6 +-
security/landlock/ptrace.c | 10 +-
security/landlock/ruleset.c | 84 +--
security/landlock/ruleset.h | 35 +-
security/landlock/syscalls.c | 95 +--
sound/core/jack.c | 34 +-
sound/core/pcm_memory.c | 3 +-
sound/pci/hda/patch_realtek.c | 21 +-
sound/soc/amd/yc/acp6x-mach.c | 29 +-
sound/soc/atmel/atmel-classd.c | 1 -
sound/soc/atmel/atmel-pdmic.c | 1 -
sound/soc/codecs/Kconfig | 2 -
sound/soc/codecs/cs35l41-lib.c | 14 +-
sound/soc/codecs/lpass-macro-common.c | 35 +-
sound/soc/codecs/max98090.c | 6 +-
sound/soc/codecs/rk3328_codec.c | 2 +-
sound/soc/codecs/rt5514.c | 2 +-
sound/soc/codecs/rt5645.c | 7 +-
sound/soc/codecs/tscs454.c | 12 +-
sound/soc/codecs/wm2000.c | 6 +-
sound/soc/fsl/imx-hdmi.c | 1 +
sound/soc/fsl/imx-sgtl5000.c | 14 +-
sound/soc/intel/boards/bytcr_rt5640.c | 12 +
sound/soc/intel/boards/sof_ssp_amp.c | 16 +-
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9 +-
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5 +-
sound/soc/mxs/mxs-saif.c | 1 +
sound/soc/samsung/aries_wm8994.c | 2 +-
sound/soc/sh/rcar/core.c | 15 +-
sound/soc/sh/rcar/dma.c | 9 +-
sound/soc/sh/rcar/rsnd.h | 2 +-
sound/soc/sh/rcar/src.c | 7 +-
sound/soc/sh/rcar/ssi.c | 14 +-
sound/soc/sh/rcar/ssiu.c | 11 +-
sound/soc/sh/rz-ssi.c | 22 +-
sound/soc/soc-dapm.c | 2 -
sound/soc/sof/amd/pci-rn.c | 1 +
sound/soc/sof/ipc3-topology.c | 40 +-
sound/soc/ti/j721e-evm.c | 44 +-
sound/usb/implicit.c | 10 +-
sound/usb/midi.c | 3 +
sound/usb/quirks.c | 6 +
sound/usb/usbaudio.h | 6 +
.../test-libbpf-btf__load_from_kernel_by_id.c | 5 +-
tools/lib/bpf/libbpf.c | 22 +-
tools/objtool/check.c | 9 +-
tools/objtool/elf.c | 200 ++++--
tools/objtool/include/objtool/elf.h | 4 +-
tools/perf/Makefile.config | 39 +-
tools/perf/arch/x86/util/evlist.c | 2 +-
tools/perf/arch/x86/util/evsel.c | 12 +
tools/perf/builtin-c2c.c | 6 +-
tools/perf/builtin-stat.c | 7 +-
tools/perf/pmu-events/jevents.c | 2 +-
tools/perf/util/data.h | 1 +
tools/perf/util/evlist.c | 12 +-
tools/perf/util/evsel.c | 19 +
tools/perf/util/evsel.h | 3 +
tools/power/x86/turbostat/turbostat.c | 1 +
tools/testing/kunit/kunit_parser.py | 7 +-
.../test_is_test_passed-no_tests_no_plan.log | 2 +-
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/arm64/bti/Makefile | 4 +-
tools/testing/selftests/bpf/Makefile | 12 +-
.../selftests/bpf/prog_tests/trampoline_count.c | 134 ++--
.../bpf/progs/btf_dump_test_case_syntax.c | 2 +-
tools/testing/selftests/bpf/progs/profiler.inc.h | 5 +-
.../selftests/bpf/progs/test_trampoline_count.c | 16 +-
.../selftests/bpf/test_bpftool_synctypes.py | 2 +-
tools/testing/selftests/bpf/trace_helpers.c | 9 +-
tools/testing/selftests/cgroup/test_stress.sh | 2 +-
tools/testing/selftests/landlock/base_test.c | 177 +++--
tools/testing/selftests/landlock/common.h | 66 +-
tools/testing/selftests/landlock/fs_test.c | 753 ++++++++++++++-------
tools/testing/selftests/landlock/ptrace_test.c | 40 +-
tools/testing/selftests/resctrl/fill_buf.c | 4 +-
tools/tracing/rtla/Makefile | 5 +-
tools/tracing/rtla/README.txt | 13 +-
tools/tracing/rtla/src/osnoise_hist.c | 5 +-
tools/tracing/rtla/src/osnoise_top.c | 9 +-
tools/tracing/rtla/src/timerlat_hist.c | 11 +-
tools/tracing/rtla/src/timerlat_top.c | 11 +-
tools/tracing/rtla/src/utils.c | 108 ++-
tools/tracing/rtla/src/utils.h | 3 +-
951 files changed, 9396 insertions(+), 5279 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.17 445/772] net/smc: postpone sk_refcnt increment in connect()
2022-06-07 16:53 1% [PATCH 5.17 000/772] 5.17.14-rc1 review Greg Kroah-Hartman
@ 2022-06-07 17:00 7% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-07 17:00 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, liuyacan, David S. Miller, Sasha Levin
From: liuyacan <liuyacan@corp.netease.com>
[ Upstream commit 75c1edf23b95a9c66923d9269d8e86e4dbde151f ]
Same trigger condition as commit 86434744. When setsockopt runs
in parallel to a connect(), and switch the socket into fallback
mode. Then the sk_refcnt is incremented in smc_connect(), but
its state stay in SMC_INIT (NOT SMC_ACTIVE). This cause the
corresponding sk_refcnt decrement in __smc_release() will not be
performed.
Fixes: 86434744fedf ("net/smc: add fallback check to connect()")
Signed-off-by: liuyacan <liuyacan@corp.netease.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/smc/af_smc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index fd9d9cfd0f3d..b9fe31834354 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1417,9 +1417,9 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
if (rc && rc != -EINPROGRESS)
goto out;
- sock_hold(&smc->sk); /* sock put in passive closing */
if (smc->use_fallback)
goto out;
+ sock_hold(&smc->sk); /* sock put in passive closing */
if (flags & O_NONBLOCK) {
if (queue_work(smc_hs_wq, &smc->connect_work))
smc->connect_nonblock = 1;
--
2.35.1
^ permalink raw reply related [relevance 7%]
* [PATCH 5.17 000/772] 5.17.14-rc1 review
@ 2022-06-07 16:53 1% Greg Kroah-Hartman
2022-06-07 17:00 7% ` [PATCH 5.17 445/772] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2022-06-07 16:53 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, torvalds, akpm, linux, shuah,
patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, slade
This is the start of the stable review cycle for the 5.17.14 release.
There are 772 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 09 Jun 2022 16:48:02 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.17.14-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.17.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.17.14-rc1
Tony Lindgren <tony@atomide.com>
tty: n_gsm: Fix packet data hex dump output
Jia-Ju Bai <baijiaju1990@gmail.com>
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Xiao Ni <xni@redhat.com>
md: fix double free of io_acct_set bioset
Xiao Ni <xni@redhat.com>
md: Don't set mddev private to NULL in raid0 pers->free
Namjae Jeon <linkinjeon@kernel.org>
fs/ntfs3: Fix invalid free in log_replay
Christian Brauner <brauner@kernel.org>
exportfs: support idmapped mounts
Christian Brauner <brauner@kernel.org>
fs: add two trivial lookup helpers
Eric Biggers <ebiggers@google.com>
ext4: only allow test_dummy_encryption when supported
Maciej W. Rozycki <macro@orcam.me.uk>
MIPS: IP30: Remove incorrect `cpu_has_fpu' override
Maciej W. Rozycki <macro@orcam.me.uk>
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
Xiao Yang <yangx.jy@fujitsu.com>
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Yixing Liu <liuyixing1@huawei.com>
RDMA/hns: Remove the num_cqc_timer variable
Dan Carpenter <dan.carpenter@oracle.com>
staging: r8188eu: delete rtw_wx_read/write32()
Jason A. Donenfeld <Jason@zx2c4.com>
Revert "random: use static branch for crng_ready()"
David Gow <davidgow@google.com>
list: test: Add a test for list_is_head()
Zhengjun Xing <zhengjun.xing@linux.intel.com>
perf evlist: Extend arch_evsel__must_be_in_group to support hybrid systems
Waiman Long <longman@redhat.com>
kseltest/cgroup: Make test_stress.sh work if run interactively
Alex Elder <elder@linaro.org>
net: ipa: fix page free in ipa_endpoint_replenish_one()
Alex Elder <elder@linaro.org>
net: ipa: fix page free in ipa_endpoint_trans_release()
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix reset-controller leak on probe errors
Mao Jinlong <quic_jinlmao@quicinc.com>
coresight: core: Fix coresight device probe failure issue
Tejun Heo <tj@kernel.org>
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Eugenio Pérez <eperezma@redhat.com>
vdpasim: allow to enable a vq repeatedly
Dinh Nguyen <dinguyen@kernel.org>
dt-bindings: gpio: altera: correct interrupt-cells
Akira Yokosawa <akiyks@gmail.com>
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Steve French <stfrench@microsoft.com>
SMB3: EBADF/EIO errors in rename/open caused by race condition in smb2_compound_op
Luís Henriques <lhenriques@suse.de>
ceph: fix decoding of client session messages flags
Arnd Bergmann <arnd@arndb.de>
ARM: pxa: maybe fix gpio lookup tables
Jonathan Bakker <xc-racer2@live.ca>
ARM: dts: s5pv210: Remove spi-cs-high on panel in Aries
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix struct clk leak on probe errors
Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
clk: tegra: Add missing reset deassertion
Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
arm64: tegra: Add missing DFLL reset on Tegra210
Kathiravan T <quic_kathirav@quicinc.com>
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Xiaomeng Tong <xiam0nd.tong@gmail.com>
gma500: fix an incorrect NULL check on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
Jiri Slaby <jirislaby@kernel.org>
serial: pch: don't overwrite xmit->buf[0] by x_char
Coly Li <colyli@suse.de>
bcache: avoid journal no-space deadlock by reserving 1 journal bucket
Coly Li <colyli@suse.de>
bcache: remove incremental dirty sector counting for bch_sectors_dirty_init()
Coly Li <colyli@suse.de>
bcache: improve multithreaded bch_sectors_dirty_init()
Coly Li <colyli@suse.de>
bcache: improve multithreaded bch_btree_check()
Xiaomeng Tong <xiam0nd.tong@gmail.com>
stm: ltdc: fix two incorrect NULL checks on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
carl9170: tx: fix an incorrect use of list iterator
Mark Brown <broonie@kernel.org>
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Alexander Wetzel <alexander@wetzel-home.de>
rtl818x: Prevent using not initialized queues
Yi Yang <yiyang13@huawei.com>
xtensa/simdisk: fix proc_read_simdisk()
Miaohe Lin <linmiaohe@huawei.com>
mm/memremap: fix missing call to untrack_pfn() in pagemap_range()
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix huge_pmd_unshare address update
Christophe de Dinechin <dinechin@redhat.com>
nodemask.h: fix compilation error with GCC12
Mel Gorman <mgorman@techsingularity.net>
mm/page_alloc: always attempt to allocate at least one page during bulk allocation
Dong Aisheng <aisheng.dong@nxp.com>
Revert "mm/cma.c: remove redundant cma_mutex lock"
Yunfei Wang <yf.wang@mediatek.com>
iommu/dma: Fix iova map result check bug
Xiaomeng Tong <xiam0nd.tong@gmail.com>
iommu/msm: Fix an incorrect NULL check on list iterator
Hyunchul Lee <hyc.lee@gmail.com>
ksmbd: fix outstanding credits related bugs
Song Liu <song@kernel.org>
ftrace: Clean up hash direct_functions on register failures
Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
Vincent Whitchurch <vincent.whitchurch@axis.com>
um: Fix out-of-bounds read in LDT setup
Johannes Berg <johannes.berg@intel.com>
um: chan_user: Fix winch_tramp() return value
Johannes Berg <johannes.berg@intel.com>
um: Use asm-generic/dma-mapping.h
Johannes Berg <johannes.berg@intel.com>
um: virtio_uml: Fix broken device handling in time-travel
Felix Fietkau <nbd@nbd.name>
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Dimitri John Ledkov <dimitri.ledkov@canonical.com>
cfg80211: declare MODULE_FIRMWARE for regulatory.db
Felix Fietkau <nbd@nbd.name>
mt76: fix use-after-free by removing a non-RCU wcid pointer
Kant Fan <kant@allwinnertech.com>
thermal: devfreq_cooling: use local ops instead of global ops
Max Filippov <jcmvbkbc@gmail.com>
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Pali Rohár <pali@kernel.org>
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Guo Ren <guoren@kernel.org>
csky: patch_text: Fixup last cpu should be master
Bean Huo <beanhuo@micron.com>
mmc: core: Allows to override the timeout value for ioctl() path
Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
RDMA/hfi1: Fix potential integer multiplication overflow errors
Puyou Lu <puyou.lu@gmail.com>
lib/string_helpers: fix not adding strarray to device's resource list
Sean Christopherson <seanjc@google.com>
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
GUO Zihua <guozihua@huawei.com>
ima: remove the IMA_TEMPLATE Kconfig option
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Add more H264 levels for CODA960
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Fix reported H264 profile
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in md_reload_sb
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in does_sb_need_changing
Jani Nikula <jani.nikula@intel.com>
drm/i915/dsi: fix VBT send packet port selection for ICL+
Brian Norris <briannorris@chromium.org>
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Xiaomeng Tong <xiam0nd.tong@gmail.com>
drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
Lucas Stach <l.stach@pengutronix.de>
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Lyude Paul <lyude@redhat.com>
drm/nouveau/subdev/bus: Ratelimit logging for fault errors
Dave Airlie <airlied@redhat.com>
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
Mickaël Salaün <mic@digikod.net>
landlock: Fix same-layer rule unions
Mickaël Salaün <mic@digikod.net>
landlock: Create find_rule() from unmask_layers()
Mickaël Salaün <mic@digikod.net>
landlock: Reduce the maximum number of layers to 16
Mickaël Salaün <mic@digikod.net>
landlock: Define access_mask_t to enforce a consistent access mask size
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Test landlock_create_ruleset(2) argument check ordering
Mickaël Salaün <mic@digikod.net>
landlock: Change landlock_restrict_self(2) check ordering
Mickaël Salaün <mic@digikod.net>
landlock: Change landlock_add_rule(2) argument check ordering
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Add tests for O_PATH
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Fully test file rename with "remove" access
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Extend access right tests to directories
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Add tests for unknown access rights
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Extend tests for minimal valid attribute size
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Make tests build with old libc
Mickaël Salaün <mic@digikod.net>
landlock: Fix landlock_add_rule(2) documentation
Mickaël Salaün <mic@digikod.net>
samples/landlock: Format with clang-format
Mickaël Salaün <mic@digikod.net>
samples/landlock: Add clang-format exceptions
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Format with clang-format
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Normalize array assignment
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Add clang-format exceptions
Mickaël Salaün <mic@digikod.net>
landlock: Format with clang-format
Mickaël Salaün <mic@digikod.net>
landlock: Add clang-format exceptions
Manivannan Sadhasivam <mani@kernel.org>
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Xiaomeng Tong <xiam0nd.tong@gmail.com>
scsi: dc395x: Fix a missing check on list iterator
Junxiao Bi via Ocfs2-devel <ocfs2-devel@oss.oracle.com>
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Alexander Aring <aahringo@redhat.com>
dlm: fix missing lkb refcount handling
Alexander Aring <aahringo@redhat.com>
dlm: fix wake_up() calls for pending remove
Dan Carpenter <dan.carpenter@oracle.com>
dlm: uninitialized variable on error in dlm_listen_for_all()
Alexander Aring <aahringo@redhat.com>
dlm: fix plock invalid read
Sven Schnelle <svens@linux.ibm.com>
s390/stp: clock_delta should be signed
Nico Boehr <nrb@linux.ibm.com>
s390/perf: obtain sie_block from the right address
Rei Yamamoto <yamamoto.rei@jp.fujitsu.com>
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Damien Le Moal <damien.lemoal@opensource.wdc.com>
block: Fix potential deadlock in blk_ia_range_sysfs_show()
Denis Efremov <denis.e.efremov@oracle.com>
staging: r8188eu: prevent ->Ssid overflow in rtw_wx_set_scan()
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix unbalanced PHY init on probe errors
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix runtime PM imbalance on probe errors
Bjorn Helgaas <bhelgaas@google.com>
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: add beige goby PCI ID
Gautam Menghani <gautammenghani201@gmail.com>
tracing: Initialize integer variable to prevent garbage return value
Wonhyuk Yang <vvghjk1234@gmail.com>
tracing: Fix return value of trace_pid_write()
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
tracing: Fix potential double free in create_var_ref()
Laurent Vivier <laurent@vivier.eu>
tty: goldfish: Introduce gf_ioread32()/gf_iowrite32()
Sakari Ailus <sakari.ailus@linux.intel.com>
ACPI: property: Release subnode properties with data nodes
Jan Kara <jack@suse.cz>
ext4: avoid cycles in directory h-tree
Jan Kara <jack@suse.cz>
ext4: verify dir block before splitting it
Baokun Li <libaokun1@huawei.com>
ext4: fix bug_on in __es_tree_search
Theodore Ts'o <tytso@mit.edu>
ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state
Ye Bin <yebin10@huawei.com>
ext4: fix bug_on in ext4_writepages
Eric Biggers <ebiggers@google.com>
ext4: fix memory leak in parse_apply_sb_mount_options()
Ye Bin <yebin10@huawei.com>
ext4: fix warning in ext4_handle_inode_extension
Baokun Li <libaokun1@huawei.com>
ext4: fix race condition between ext4_write and ext4_convert_inline_data
Ojaswin Mujoo <ojaswin@linux.ibm.com>
ext4: fix journal_ioprio mount option handling
Ye Bin <yebin10@huawei.com>
ext4: fix use-after-free in ext4_rename_dir_prepare
Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
ext4: mark group as trimmed only if it was fully scanned
Jan Kara <jack@suse.cz>
bfq: Make sure bfqg for which we are queueing requests is online
Jan Kara <jack@suse.cz>
bfq: Get rid of __bio_blkcg() usage
Jan Kara <jack@suse.cz>
bfq: Track whether bfq_group is still online
Jan Kara <jack@suse.cz>
bfq: Remove pointless bfq_init_rq() calls
Jan Kara <jack@suse.cz>
bfq: Drop pointless unlock-lock pair
Jan Kara <jack@suse.cz>
bfq: Update cgroup information before merging bio
Jan Kara <jack@suse.cz>
bfq: Split shared queues on move between cgroups
Jan Kara <jack@suse.cz>
bfq: Avoid merging queues with different parents
Jan Kara <jack@suse.cz>
bfq: Avoid false marking of bic as stably merged
Aditya Garg <gargaditya08@live.com>
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Zhihao Cheng <chengzhihao1@huawei.com>
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
Johannes Berg <johannes.berg@intel.com>
iwlwifi: mei: fix potential NULL-ptr deref
Avraham Stern <avraham.stern@intel.com>
iwlwifi: mei: clear the sap data header before sending
Emmanuel Grumbach <emmanuel.grumbach@intel.com>
iwlwifi: mvm: fix assert 1F04 upon reconfig
Johannes Berg <johannes.berg@intel.com>
iwlwifi: fw: init SAR GEO table only if data is present
Johannes Berg <johannes.berg@intel.com>
wifi: mac80211: fix use-after-free in chanctx code
Peter Zijlstra <peterz@infradead.org>
objtool: Fix symbol creation
Mikulas Patocka <mpatocka@redhat.com>
objtool: Fix objtool regression on x32 systems
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check for inline inode
Chao Yu <chao@kernel.org>
f2fs: fix fallocate to use file_modified to update permissions consistently
Eric Biggers <ebiggers@google.com>
f2fs: don't use casefolded comparison for "." and ".."
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on total_data_blocks
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: don't need inode lock for system hidden quota
Chao Yu <chao@kernel.org>
f2fs: fix deadloop in foreground GC
Chao Yu <chao@kernel.org>
f2fs: fix to clear dirty inode in f2fs_evict_inode()
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
Chao Yu <chao@kernel.org>
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
Olga Kornievskaia <kolga@netapp.com>
NFSv4.1 mark qualified async operations as MOVEABLE tasks
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Convert GFP_NOFS to GFP_KERNEL
Benjamin Coddington <bcodding@redhat.com>
NFSv4: Fix free of uninitialized nfs4_label on referral lookup.
Javier Martinez Canillas <javierm@redhat.com>
video: fbdev: vesafb: Fix a use-after-free due early fb_info cleanup
Zhengjun Xing <zhengjun.xing@linux.intel.com>
perf jevents: Fix event syntax error caused by ExtSel
Daniel Bristot de Oliveira <bristot@kernel.org>
tracing/timerlat: Notify IRQ new max latency only if stop tracing is set
Daniel Bristot de Oliveira <bristot@kernel.org>
rtla: Fix __set_sched_attr error message
John Kacur <jkacur@redhat.com>
rtla: Minor grammar fix for rtla README
John Kacur <jkacur@redhat.com>
rtla: Don't overwrite existing directory mode
Leo Yan <leo.yan@linaro.org>
perf c2c: Use stdio interface if slang is not supported
Jiri Olsa <jolsa@kernel.org>
perf build: Fix btf__load_from_kernel_by_id() feature check
Tiezhu Yang <yangtiezhu@loongson.cn>
MIPS: RALINK: Define pci_remap_iospace under CONFIG_PCI_DRIVERS_GENERIC
Palmer Dabbelt <palmer@rivosinc.com>
RISC-V: Fix the XIP build
Li Huafei <lihuafei1@huawei.com>
tracing: Reset the function filter after completing trampoline/graph selftest
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
i2c: rcar: fix PM ref counts in probe error paths
Tali Perry <tali.perry1@gmail.com>
i2c: npcm: Handle spurious interrupts
Tyrone Ting <kfting@nuvoton.com>
i2c: npcm: Correct register access width
Tali Perry <tali.perry1@gmail.com>
i2c: npcm: Fix timeout calculation
Joerg Roedel <jroedel@suse.de>
iommu/amd: Increase timeout waiting for GA log enablement
Amelie Delaunay <amelie.delaunay@foss.st.com>
dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler()
Amelie Delaunay <amelie.delaunay@foss.st.com>
dmaengine: stm32-mdma: remove GISR1 register
Miaoqian Lin <linmq006@gmail.com>
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Further fixes to the writeback error handling
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Don't report errors from nfs_pageio_complete() more than once
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report flush errors in nfs_write_end()
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Don't report ENOSPC write errors twice
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: fsync() should report filesystem errors over EINTR/ERESTARTSYS
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: idxd: Fix the error handling path in idxd_cdev_register()
Nathan Chancellor <nathan@kernel.org>
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Miles Chen <miles.chen@mediatek.com>
iommu/mediatek: Fix NULL pointer dereference when printing dev_name
Guenter Roeck <linux@roeck-us.net>
MIPS: Loongson: Use hwmon_device_register_with_groups() to register hwmon
Jean-Philippe Brucker <jean-philippe@linaro.org>
iommu/arm-smmu-v3-sva: Fix mm use-after-free
Rex-BC Chen <rex-bc.chen@mediatek.com>
cpufreq: mediatek: Unregister platform device on exit
Jia-Wei Chang <jia-wei.chang@mediatek.com>
cpufreq: mediatek: Use module_init and add module_exit
Michael Walle <michael@walle.cc>
i2c: at91: use dma safe buffers
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Remove clk_disable in mtk_iommu_remove
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Add list_del in mtk_iommu_remove
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Fix 2 HW sharing pgtable issue
Mario Limonciello <mario.limonciello@amd.com>
iommu/amd: Enable swiotlb in all cases
Guo Ren <guoren@kernel.org>
riscv: Fixup difference with defconfig
Jakob Koschel <jakobkoschel@gmail.com>
f2fs: fix dereference of stale list iterator after loop body
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on inline_dots inode
Dan Carpenter <dan.carpenter@oracle.com>
OPP: call of_node_put() on error path in _bandwidth_supported()
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: stmfts - do not leave device disabled in stmfts_input_open
Wanpeng Li <wanpengli@tencent.com>
KVM: LAPIC: Drop pending LAPIC timer injection when canceling the timer
Hector Martin <marcan@marcan.st>
pinctrl: apple: Use a raw spinlock for the regmap
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent use of lock before it is initialized
Björn Ardö <bjorn.ardo@axis.com>
mailbox: forward the hrtimer if not queued and under a lock
Julian Schroeder <jumaco@amazon.com>
nfsd: destroy percpu stats counters after reply cache shutdown
Yang Yingliang <yangyingliang@huawei.com>
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
gpio: sim: Use correct order for the parameters of devm_kcalloc()
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/fsl_book3e: Don't set rodata RO too early
Miaoqian Lin <linmq006@gmail.com>
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
Miaoqian Lin <linmq006@gmail.com>
powerpc/xive: Fix refcount leak in xive_spapr_init
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
powerpc/xive: Add some error handling code to 'xive_spapr_init()'
Randy Dunlap <rdunlap@infradead.org>
macintosh: via-pmu and via-cuda need RTC_LIB
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf: Fix the threshold compare group constraint for power9
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf: Fix the threshold compare group constraint for power10
Russell Currey <ruscur@russell.cc>
powerpc/powernv: Get STF barrier requirements from device-tree
Russell Currey <ruscur@russell.cc>
powerpc/powernv: Get L1D flush requirements from device-tree
Michael Ellerman <mpe@ellerman.id.au>
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
Mario Limonciello <mario.limonciello@amd.com>
mailbox: pcc: Fix an invalid-load caught by the address sanitizer
Kan Liang <kan.liang@linux.intel.com>
perf stat: Always keep perf metrics topdown events in a group
Ian Rogers <irogers@google.com>
perf evlist: Keep topdown counters in weak group
Yang Yingliang <yangyingliang@huawei.com>
hwrng: omap3-rom - fix using wrong clk_disable() in omap_rom_rng_runtime_resume()
Daire McNamara <daire.mcnamara@microchip.com>
PCI: microchip: Fix potential race in interrupt handling
Fabiano Rosas <farosas@linux.ibm.com>
KVM: PPC: Book3S HV: Fix vcore_blocked tracepoint
Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
PCI/AER: Clear MULTI_ERR_COR/UNCOR_RCV bits
Miaoqian Lin <linmq006@gmail.com>
Input: sparcspkr - fix refcount leak in bbc_beep_probe
Jane Chu <jane.chu@oracle.com>
mce: fix set_mce_nospec to always unmap the whole page
Jane Chu <jane.chu@oracle.com>
x86/mce: relocate set{clear}_mce_nospec() functions
Mina Almasry <almasrymina@google.com>
hugetlbfs: fix hugetlbfs_statfs() locking
Eugen Hristev <eugen.hristev@microchip.com>
ARM: dts: at91: sama7g5: remove interrupt-parent from gic node
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
crypto: cryptd - Protect per-CPU resource by disabling BH.
Corentin Labbe <clabbe@baylibre.com>
crypto: sun8i-ss - handle zero sized sg
Corentin Labbe <clabbe@baylibre.com>
crypto: sun8i-ss - rework handling of IV
Qi Zheng <zhengqi.arch@bytedance.com>
tty: fix deadlock caused by calling printk() under tty_port->lock
Alexey Dobriyan <adobriyan@gmail.com>
module: fix [e_shstrndx].sh_size=0 OOB access
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
module.h: simplify MODULE_IMPORT_NS
AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
PCI: mediatek-gen3: Assert resets to ensure expected init state
Francesco Dolcini <francesco.dolcini@toradex.com>
PCI: imx6: Fix PERST# start-up sequence
Waiman Long <longman@redhat.com>
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
Alexey Dobriyan <adobriyan@gmail.com>
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: atmel-classd: Remove endianness flag on class d component
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: atmel-pdmic: Remove endianness flag on pdmic component
Robert Marko <robert.marko@sartura.hr>
arm64: dts: marvell: espressobin-ultra: enable front USB3 port
Robert Marko <robert.marko@sartura.hr>
arm64: dts: marvell: espressobin-ultra: fix SPI-NOR config
Yangyang Li <liyangyang20@huawei.com>
RDMA/hns: Add the detection for CMDQ status in the device initialization process
Randy Dunlap <rdunlap@infradead.org>
powerpc/4xx/cpm: Fix return value of __setup() handler
Randy Dunlap <rdunlap@infradead.org>
powerpc/idle: Fix return value of __setup() handler
Yang Yingliang <yangyingliang@huawei.com>
pinctrl: renesas: core: Fix possible null-ptr-deref in sh_pfc_map_resources()
Geert Uytterhoeven <geert+renesas@glider.be>
pinctrl: renesas: r8a779a0: Fix GPIO function on I2C-capable pins
Randy Dunlap <rdunlap@infradead.org>
powerpc/8xx: export 'cpm_setbrg' for modules
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/dpu: fix error check return value of irq_of_parse_and_map()
Kuniyuki Iwashima <kuniyu@amazon.co.jp>
list: fix a data-race around ep->rdllist
Heming Zhao via Ocfs2-devel <ocfs2-devel@oss.oracle.com>
ocfs2: fix mounting crash if journal is not alloced
Sudeep Holla <sudeep.holla@arm.com>
firmware: arm_ffa: Remove incorrect assignment of driver_data
Sudeep Holla <sudeep.holla@arm.com>
firmware: arm_ffa: Fix uuid parameter to ffa_partition_probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
drivers/base/memory: fix an unlikely reference counting issue in __add_memory_block()
Muchun Song <songmuchun@bytedance.com>
dax: fix cache flush on PMD-mapped pages
Miaohe Lin <linmiaohe@huawei.com>
drivers/base/node.c: fix compaction sysfs file leak
Jacky Li <jackyli@google.com>
crypto: ccp - Fix the INIT_EX data file open failure
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
Dan Williams <dan.j.williams@intel.com>
nvdimm: Allow overwrite in the presence of disabled dimms
Dan Williams <dan.j.williams@intel.com>
nvdimm: Fix firmware activation deadlock scenarios
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
ASoC: sh: rz-ssi: Release the DMA channels in rz_ssi_probe() error path
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
ASoC: sh: rz-ssi: Propagate error codes returned from platform_get_irq_byname()
Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
arm64: dts: ti: k3-am64-mcu: remove incorrect UART base clock rates
QintaoShen <unSimple1993@163.com>
soc: bcm: Check for NULL return of devm_kzalloc()
Gustavo A. R. Silva <gustavoars@kernel.org>
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
Lv Ruyi <lv.ruyi@zte.com.cn>
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: fix PT_LOAD segment for boot memory area
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Fix handling of messages with transaction ID of zero
Vinod Koul <vkoul@kernel.org>
arm64: dts: qcom: qrb5165-rb5: Fix can-clock node name
Fabien Parent <fparent@baylibre.com>
pinctrl: mediatek: mt8195: enable driver on mtk platforms
Caleb Connolly <kc@postmarketos.org>
pinctrl/rockchip: support deferring other gpio params
Chuanhong Guo <gch981213@gmail.com>
arm: mediatek: select arch timer for mt7629
Chia-I Wu <olvaffe@gmail.com>
drm/msm: return the average load over the polling period
Chia-I Wu <olvaffe@gmail.com>
drm/msm: simplify gpu_busy callback
Stefan Wahren <stefan.wahren@i2se.com>
pinctrl: bcm2835: implement hook for missing gpio-ranges
Stefan Wahren <stefan.wahren@i2se.com>
gpiolib: of: Introduce hook for missing gpio-ranges
Corentin Labbe <clabbe@baylibre.com>
crypto: marvell/cesa - ECB does not IV
Vladis Dronov <vdronov@redhat.com>
hwrng: cn10k - Make check_rng_health() return an error code
Vladis Dronov <vdronov@redhat.com>
hwrng: cn10k - Optimize cn10k_rng_read()
Hangyu Hua <hbh25y@gmail.com>
misc: ocxl: fix possible double free in ocxl_file_register_afu
Stefan Wahren <stefan.wahren@i2se.com>
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: qcom: sdx55: remove wrong unit address from RPMH RSC clocks
Bryan O'Donoghue <bryan.odonoghue@linaro.org>
dt-bindings: soc: qcom: smd-rpm: Fix missing MSM8936 compatible
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Fix PHY post-reset delay on Avenger96
Marc Kleine-Budde <mkl@pengutronix.de>
can: xilinx_can: mark bit timing constants as const
Guenter Roeck <linux@roeck-us.net>
platform/chrome: Re-introduce cros_ec_cmd_xfer and use it for ioctls
Max Krummenacher <max.krummenacher@toradex.com>
ARM: dts: imx6dl-colibri: Fix I2C pinmuxing
Tzung-Bi Shih <tzungbi@kernel.org>
platform/chrome: cros_ec: fix error handling in cros_ec_register()
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - set COMPRESSION capability for DH895XCC
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - set CIPHER capability for DH895XCC
Sean Christopherson <seanjc@google.com>
KVM: nVMX: Clear IDT vectoring on nested VM-Exit for double/triple fault
Sean Christopherson <seanjc@google.com>
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
Bjorn Andersson <bjorn.andersson@linaro.org>
soc: qcom: llcc: Add MODULE_DEVICE_TABLE()
Thorsten Scherer <t.scherer@eckelmann.de>
ARM: dts: ci4x10: Adapt to changes in imx6qdl.dtsi regarding fec clocks
Jiantao Zhang <water.zhangjiantao@huawei.com>
PCI: dwc: Fix setting error return on MSI DMA mapping failure
Miaoqian Lin <linmq006@gmail.com>
PCI: mediatek: Fix refcount leak in mtk_pcie_subsys_powerup()
Dan Carpenter <dan.carpenter@oracle.com>
PCI: rockchip: Fix find_first_zero_bit() limit
Dan Carpenter <dan.carpenter@oracle.com>
PCI: cadence: Fix find_first_zero_bit() limit
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
Andre Przywara <andre.przywara@arm.com>
ARM: dts: suniv: F1C100: fix watchdog compatible
Rafał Miłecki <rafal@milecki.pl>
ARM: dts: BCM5301X: Update pin controller node name
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
memory: samsung: exynos5422-dmc: Avoid some over memory allocation
Mario Limonciello <mario.limonciello@amd.com>
PCI/ACPI: Allow D3 only if Root Port can signal and wake from D3
Allen-KH Cheng <allen-kh.cheng@mediatek.com>
arm64: dts: mt8192: Fix nor_flash status disable typo
Shawn Lin <shawn.lin@rock-chips.com>
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
liuyacan <liuyacan@corp.netease.com>
Revert "net/smc: fix listen processing for SMC-Rv2"
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: hci_conn: Fix hci_connect_le_sync
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: hci_sync: Cleanup hci_conn if it cannot be aborted
Robin Murphy <robin.murphy@arm.com>
dma-direct: don't over-decrypt memory
liuyacan <liuyacan@corp.netease.com>
net/smc: fix listen processing for SMC-Rv2
liuyacan <liuyacan@corp.netease.com>
net/smc: postpone sk_refcnt increment in connect()
Randy Dunlap <rdunlap@infradead.org>
net: dsa: restrict SMSC_LAN9303_I2C kconfig
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hinic: Avoid some over memory allocation
David Howells <dhowells@redhat.com>
rxrpc: Fix decision on when to generate an IDLE ACK
David Howells <dhowells@redhat.com>
rxrpc: Don't let ack.previousPacket regress
David Howells <dhowells@redhat.com>
rxrpc: Fix overlapping ACK accounting
David Howells <dhowells@redhat.com>
rxrpc: Don't try to resend the request if we're receiving the reply
David Howells <dhowells@redhat.com>
rxrpc: Fix listen() setting the bar too high for the prealloc rings
David Howells <dhowells@redhat.com>
rxrpc: Fix locking issue
Adam Wujek <dev_public@wujek.eu>
hwmon: (pmbus) Check PEC support before reading other registers
Yongzhi Liu <lyz_cs@pku.edu.cn>
hv_netvsc: Fix potential dereference of NULL pointer
Taehee Yoo <ap420073@gmail.com>
amt: fix memory leak for advertisement message
Taehee Yoo <ap420073@gmail.com>
amt: fix gateway mode stuck
Jakub Kicinski <kuba@kernel.org>
net: stmmac: fix out-of-bounds access in a selftest
Kan Liang <kan.liang@linux.intel.com>
perf parse-events: Support different format of the topdown event name
Alexey Khoroshilov <khoroshilov@ispras.ru>
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
Hangbin Liu <liuhangbin@gmail.com>
bonding: fix missed rcu protection
Duoming Zhou <duoming@zju.edu.cn>
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
John Garry <john.garry@huawei.com>
scsi: hisi_sas: Fix rescan after deleting a disk
Harini Katakam <harini.katakam@xilinx.com>
net: macb: Fix PTP one step sync support
Ulf Hansson <ulf.hansson@linaro.org>
PM: domains: Fix initialization of genpd's next_wakeup
Yang Yingliang <yangyingliang@huawei.com>
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
Jan Kara <jack@suse.cz>
bfq: Allow current waker to defend against a tentative one
Jan Kara <jack@suse.cz>
bfq: Relax waker detection for shared queues
Miaoqian Lin <linmq006@gmail.com>
thermal/drivers/imx_sc_thermal: Fix refcount leak in imx_sc_thermal_probe
Yang Yingliang <yangyingliang@huawei.com>
thermal/core: Fix memory leak in __thermal_cooling_device_register()
Zheng Yongjun <zhengyongjun3@huawei.com>
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
Stefan Wahren <stefan.wahren@i2se.com>
thermal/drivers/bcm2711: Don't clamp temperature at zero
Nathan Chancellor <nathan@kernel.org>
drm/i915: Fix CFI violation with show_dynamic_id()
Abhinav Kumar <quic_abhinavk@quicinc.com>
drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path
Hangbin Liu <liuhangbin@gmail.com>
selftests/bpf: Add missed ima_setup.sh in Makefile
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: don't free the IRQ if it was not requested
Lai Jiangshan <jiangshan.ljs@antgroup.com>
x86/sev: Annotate stack change in the #VC handler
Hangyu Hua <hbh25y@gmail.com>
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
Miaoqian Lin <linmq006@gmail.com>
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
Eric Biggers <ebiggers@google.com>
ext4: reject the 'commit' option on ext2 filesystems
Moshe Tal <moshet@nvidia.com>
net/mlx5e: Correct the calculation of max channels for rep
Gao Xiang <hsiangkao@linux.alibaba.com>
erofs: fix buffer copy overflow of ztailpacking feature
Miaoqian Lin <linmq006@gmail.com>
regulator: scmi: Fix refcount leak in scmi_regulator_probe
Jonas Karlman <jonas@kwiboo.se>
media: rkvdec: h264: Fix bit depth wrap in pps packet
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: rkvdec: h264: Fix dpb_valid implementation
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: rkvdec: Stop overclocking the decoder
Yang Yingliang <yangyingliang@huawei.com>
media: i2c: ov5648: fix wrong pointer passed to IS_ERR() and PTR_ERR()
Dongliang Mu <mudongliangabcd@gmail.com>
media: ov7670: remove ov7670_power_off from ov7670_remove
Andre Przywara <andre.przywara@arm.com>
kselftest/arm64: bti: force static linking
Miaoqian Lin <linmq006@gmail.com>
ASoC: ti: j721e-evm: Fix refcount leak in j721e_soc_probe_*
Zheng Bin <zhengbin13@huawei.com>
net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init
Eric Dumazet <edumazet@google.com>
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
Geert Uytterhoeven <geert@linux-m68k.org>
m68k: math-emu: Fix dependencies of math emulation support
Keith Busch <kbusch@kernel.org>
nvme: set dma alignment to dword
Mark Rutland <mark.rutland@arm.com>
irqchip/gic-v3: Fix priority mask handling
Mark Rutland <mark.rutland@arm.com>
irqchip/gic-v3: Refactor ISB + EOIR at ack time
Mark Rutland <mark.rutland@arm.com>
irqchip/gic-v3: Ensure pseudo-NMIs have an ISB between ack and handling
Dylan Yudaken <dylany@fb.com>
io_uring: only wake when the correct events are set
Jens Axboe <axboe@kernel.dk>
io_uring: fix assuming triggered poll waitqueue is the single poll
Jens Axboe <axboe@kernel.dk>
io_uring: cache poll/double-poll state with a request flag
Pavel Begunkov <asml.silence@gmail.com>
io_uring: avoid io-wq -EAGAIN looping for !IOPOLL
Yunfei Dong <yunfei.dong@mediatek.com>
media: mediatek: vcodec: Fix v4l2 compliance decoder cmd test fail
Sean Wang <sean.wang@mediatek.com>
Bluetooth: btmtksdio: fix use-after-free at btmtksdio_recv_event
Niels Dossche <dossche.niels@gmail.com>
Bluetooth: protect le accept and resolv lists with hdev->lock
Niels Dossche <dossche.niels@gmail.com>
Bluetooth: use hdev lock for accept_list and reject_list in conn req
Niels Dossche <dossche.niels@gmail.com>
Bluetooth: use hdev lock in activate_scan for hci_is_adv_monitoring
Ying Hsu <yinghsu@chromium.org>
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Benjamin Gaignard <benjamin.gaignard@collabora.com>
media: hantro: HEVC: Fix tile info buffer value computation
Eugen Hristev <eugen.hristev@microchip.com>
media: atmel: atmel-sama5d2-isc: fix wrong mask in YUYV format check
Michael Rodin <mrodin@de.adit-jv.com>
media: vsp1: Fix offset calculation for plane cropping
Pavel Skripkin <paskripkin@gmail.com>
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Miaoqian Lin <linmq006@gmail.com>
media: exynos4-is: Change clk_disable to clk_disable_unprepare
Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
media: i2c: rdacm2x: properly set subdev entity function
Miaoqian Lin <linmq006@gmail.com>
media: atmel: atmel-isc: Fix PM disable depth imbalance in atmel_isc_probe
Miaoqian Lin <linmq006@gmail.com>
media: st-delta: Fix PM disable depth imbalance in delta_probe
Peter Chiu <chui-hao.chiu@mediatek.com>
mt76: mt7915: fix twt table_mask to u16 in mt7915_dev
Felix Fietkau <nbd@nbd.name>
mt76: fix tx status related use-after-free race on station removal
Felix Fietkau <nbd@nbd.name>
mt76: do not attempt to reorder received 802.3 packets without agg session
Sean Wang <sean.wang@mediatek.com>
mt76: mt7921: fix kernel crash at mt7921_pci_remove
Deren Wu <deren.wu@mediatek.com>
mt76: fix antenna config missing in 6G cap
Lorenzo Bianconi <lorenzo@kernel.org>
mt76: mt7915: do not pass data pointer to mt7915_mcu_muru_debug_set
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mt76: mt7921: Fix the error handling path of mt7921_pci_probe()
Miaoqian Lin <linmq006@gmail.com>
media: exynos4-is: Fix PM disable depth imbalance in fimc_is_probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: aspeed: Fix an error handling path in aspeed_video_probe()
Josh Poimboeuf <jpoimboe@kernel.org>
scripts/faddr2line: Fix overlapping text section failures
Phil Auld <pauld@redhat.com>
kselftest/cgroup: fix test_stress.sh to use OUTPUT dir
Bart Van Assche <bvanassche@acm.org>
block: Fix the bio.bi_opf comment
Miaoqian Lin <linmq006@gmail.com>
ASoC: samsung: Fix refcount leak in aries_audio_probe
Christoph Hellwig <hch@lst.de>
dma-direct: don't fail on highmem CMA pages in dma_direct_alloc_pages
Pierre Gondois <Pierre.Gondois@arm.com>
PM: EM: Decrement policy counter
Miaoqian Lin <linmq006@gmail.com>
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
Miaoqian Lin <linmq006@gmail.com>
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: imx-hdmi: Fix refcount leak in imx_hdmi_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Modify the hid name
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Modify the bus name
Ajay Singh <ajay.kathat@microchip.com>
wilc1000: fix crash observed in AP mode with cfg80211_register_netdevice()
Baochen Qiang <quic_bqiang@quicinc.com>
ath11k: Don't check arvif->is_started before sending management frames
Ravi Bangoria <ravi.bangoria@amd.com>
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Jerome Marchand <jmarchan@redhat.com>
samples: bpf: Don't fail for a missing VMLINUX_BTF when VMLINUX_H is provided
Konrad Dybcio <konrad.dybcio@somainline.org>
regulator: qcom_smd: Fix up PM8950 regulator configuration
Viresh Kumar <viresh.kumar@linaro.org>
Revert "cpufreq: Fix possible race in cpufreq online error path"
Andrii Nakryiko <andrii@kernel.org>
selftests/bpf: Prevent skeleton generation race
Yang Yingliang <yangyingliang@huawei.com>
spi: spi-fsl-qspi: check return value after calling platform_get_resource_byname()
Andreas Gruenbacher <agruenba@redhat.com>
iomap: iomap_write_failed fix
Mark Rutland <mark.rutland@arm.com>
arm64: stackleak: fix current_top_of_stack()
Xiaomeng Tong <xiam0nd.tong@gmail.com>
media: uvcvideo: Fix missing check to determine if element is found in list
Dan Carpenter <dan.carpenter@oracle.com>
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: fix event thread stuck in wait_event after kthread_stop()
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix address for second DSI PHY on SDM660
Vinod Polimera <quic_vpolimer@quicinc.com>
drm/msm/disp/dpu1: avoid clearing hw interrupts if hw_intr is null during drm uninit
Zev Weiss <zev@bewilderbeest.net>
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Tong Tiangen <tongtiangen@huawei.com>
arm64: fix types in copy_highpage()
Randy Dunlap <rdunlap@infradead.org>
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
irqchip/aspeed-scu-ic: Fix irq_of_parse_and_map() return value
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
Daniel Thompson <daniel.thompson@linaro.org>
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Randy Dunlap <rdunlap@infradead.org>
x86: Fix return value of __setup handlers
Johannes Berg <johannes.berg@intel.com>
nl80211: don't hold RTNL in color change request
Christoph Hellwig <hch@lst.de>
virtio_blk: fix the discard_granularity and discard_alignment queue limits
James Clark <james.clark@arm.com>
perf tools: Use Python devtools for version autodetection rather than runtime
Ian Abbott <abbotti@mev.co.uk>
spi: cadence-quadspi: fix Direct Access Mode disable for SoCFPGA
Yang Yingliang <yangyingliang@huawei.com>
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
Daniel Latypov <dlatypov@google.com>
kunit: fix debugfs code to use enum kunit_status, not bool
Jagan Teki <jagan@amarulasolutions.com>
drm/panel: panel-simple: Fix proper bpc for AM-1280800N3TZQW-T00H
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: add missing include to msm_drv.c
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
Yang Yingliang <yangyingliang@huawei.com>
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix error checks and return values for DSI xmit functions
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: do not stop transmitting phy test pattern during DP phy compliance test
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: reset DP controller before transmit phy test pattern
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/dp: fix error check return value of irq_of_parse_and_map()
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: stop event kernel thread when DP unbind
Vinod Polimera <quic_vpolimer@quicinc.com>
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
Yang Jihong <yangjihong1@huawei.com>
perf tools: Add missing headers needed by util/data.h
Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
ASoC: rk3328: fix disabling mclk on pclk probe failure
Josh Poimboeuf <jpoimboe@redhat.com>
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
Yang Yingliang <yangyingliang@huawei.com>
mtd: rawnand: intel: fix possible null-ptr-deref in ebu_nand_probe()
Yang Yingliang <yangyingliang@huawei.com>
mtd: rawnand: cadence: fix possible null-ptr-deref in cadence_nand_dt_probe()
Matthieu Baerts <matthieu.baerts@tessares.net>
x86/pm: Fix false positive kmemleak report in msr_build_context()
Chen-Tsung Hsieh <chentsung@chromium.org>
mtd: spi-nor: core: Check written SR value in spi_nor_write_16bit_sr_and_check()
Andrii Nakryiko <andrii@kernel.org>
libbpf: Fix logic for finding matching program for CO-RE relocation
Colin Ian King <colin.king@intel.com>
selftests/resctrl: Fix null pointer dereference on open failed
Colin Ian King <colin.king@intel.com>
drm/v3d: Fix null pointer dereference of pointer perfmon
Kiwoong Kim <kwmad.kim@samsung.com>
scsi: ufs: core: Exclude UECxx from SFR dump list
Bart Van Assche <bvanassche@acm.org>
scsi: ufs: qcom: Fix ufs_qcom_resume()
Dan Carpenter <dan.carpenter@oracle.com>
scsi: iscsi: Fix harmless double shift bug
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dpu: adjust display_v_end for eDP and DP
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: properly add and remove internal bridges
Yuanchu Xie <yuanchu@google.com>
selftests/damon: add damon to selftests root Makefile
Nuno Sá <nuno.sa@analog.com>
of: overlay: do not break notify on NOTIFY_{OK|STOP}
Luca Ceresoli <luca.ceresoli@bootlin.com>
spi: rockchip: fix missing error on unsupported SPI_CS_HIGH
Jon Lin <jon.lin@rock-chips.com>
spi: rockchip: Preset cs-high and clk polarity in setup progress
Jon Lin <jon.lin@rock-chips.com>
spi: rockchip: Stop spi slave dma receiver when cs inactive
Amir Goldstein <amir73il@gmail.com>
fsnotify: fix wrong lockdep annotations
Amir Goldstein <amir73il@gmail.com>
inotify: show inotify mask flags in proc fdinfo
Bjørn Mork <bjorn@mork.no>
mtdblock: warn if opened on NAND
Colin Ian King <colin.king@intel.com>
ALSA: pcm: Check for null pointer of pointer substream before dereferencing it
Marek Vasut <marex@denx.de>
drm/panel: simple: Add missing bus flags for Innolux G070Y2-L01
Chen-Yu Tsai <wenst@chromium.org>
media: hantro: Empty encoder capture buffers by default
Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
media: i2c: max9286: fix kernel oops when removing module
Jacopo Mondi <jacopo+renesas@jmondi.org>
media: i2c: max9286: Use "maxim,gpio-poc" property
Dan Carpenter <dan.carpenter@oracle.com>
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
John Ogness <john.ogness@linutronix.de>
printk: wake waiters for safe and NMI contexts
John Ogness <john.ogness@linutronix.de>
printk: add missing memory barrier to wake_up_klogd()
John Ogness <john.ogness@linutronix.de>
printk: use atomic updates for klogd work
Schspa Shi <schspa@gmail.com>
cpufreq: Fix possible race in cpufreq online error path
Zheng Yongjun <zhengyongjun3@huawei.com>
spi: img-spfi: Fix pm_runtime_get_sync() error checking
Chengming Zhou <zhouchengming@bytedance.com>
sched/psi: report zeroes for CPU full at the system level
Chengming Zhou <zhouchengming@bytedance.com>
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
Marco Elver <elver@google.com>
signal: Deliver SIGTRAP on perf event asynchronously if blocked
Nícolas F. R. A. Prado <nfraprado@collabora.com>
drm/mediatek: dpi: Use mt8183 output formats for mt8192
Wei Yongjun <weiyongjun1@huawei.com>
regulator: da9121: Fix uninit-value in da9121_assign_chip_model()
Miaoqian Lin <linmq006@gmail.com>
drm/bridge: Fix error handling in analogix_dp_probe
Miaoqian Lin <linmq006@gmail.com>
HID: elan: Fix potential double free in elan_input_configured
Jonathan Teh <jonathan.teh@outlook.com>
HID: hid-led: fix maximum brightness for Dream Cheeky
Zheyu Ma <zheyuma97@gmail.com>
mtd: rawnand: denali: Use managed device resources
Nícolas F. R. A. Prado <nfraprado@collabora.com>
drm/bridge: anx7625: Use uint8 for lane-swing arrays
Tyler Hicks <tyhicks@linux.microsoft.com>
EDAC/dmc520: Don't print an error for each unconfigured interrupt line
Arnd Bergmann <arnd@arndb.de>
drbd: fix duplicate array initializer
Christoph Hellwig <hch@lst.de>
target: remove an incorrect unmap zeroes data deduction
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
device property: Allow error pointer to be passed to fwnode APIs
Jan Kiszka <jan.kiszka@siemens.com>
efi: Add missing prototype for efi_capsule_setup_info
Javier Martinez Canillas <javierm@redhat.com>
efi: Allow to enable EFI runtime services by default on RT
Lin Ma <linma@zju.edu.cn>
NFC: NULL out the dev->rfkill to prevent UAF
Lv Ruyi <lv.ruyi@zte.com.cn>
ixp4xx_eth: fix error check return value of platform_get_irq()
Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
net: dsa: mt7530: 1G can also support 1000BASE-X link mode
Paul E. McKenney <paulmck@kernel.org>
scftorture: Fix distribution of short handler delays
Miaoqian Lin <linmq006@gmail.com>
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
Jiasheng Jiang <jiasheng@iscas.ac.cn>
drm: mali-dp: potential dereference of null pointer
Zhou Qingyang <zhou1615@umn.edu>
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Johannes Berg <johannes.berg@intel.com>
nl80211: show SSID for P2P_GO interfaces
Paolo Abeni <pabeni@redhat.com>
mptcp: reset the packet scheduler on PRIO change
Paolo Abeni <pabeni@redhat.com>
mptcp: reset the packet scheduler on incoming MP_PRIO
Paolo Abeni <pabeni@redhat.com>
mptcp: optimize release_cb for the common case
Maciej W. Rozycki <macro@orcam.me.uk>
x86/PCI: Fix ALi M1487 (IBC) PIRQ router link value interpretation
Andrii Nakryiko <andrii@kernel.org>
libbpf: Don't error out on CO-RE relos for overriden weak subprogs
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hvs: Reset muxes at probe time
Miles Chen <miles.chen@mediatek.com>
drm/mediatek: Fix mtk_cec_mask()
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hvs: Fix frame count register readout
Maxime Ripard <maxime@cerno.tech>
drm/vc4: kms: Take old state core clock rate into account
Chen-Yu Tsai <wenst@chromium.org>
drm/mediatek: Fix DPI component detection for MT8192
Rex-BC Chen <rex-bc.chen@mediatek.com>
drm/mediatek: Add vblank register/unregister callback functions
Ammar Faizi <ammarfaizi2@gnuweeb.org>
x86/delay: Fix the wrong asm constraint in delay_loop()
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
Hui Wang <hui.wang@canonical.com>
ASoC: cs35l41: Fix an out-of-bounds access in otp_packed_element_t
Kuldeep Singh <singh.kuldeep87k@gmail.com>
spi: qcom-qspi: Add minItems to interconnect-names
Chuanhong Guo <gch981213@gmail.com>
mtd: spinand: gigadevice: fix Quad IO for GD5F1GQ5UExxG
Marek Vasut <marex@denx.de>
drm: bridge: icn6211: Fix HFP_HSW_HBP_HI and HFP_MIN handling
Marek Vasut <marex@denx.de>
drm: bridge: icn6211: Fix register layout
Lucas Stach <l.stach@pengutronix.de>
drm/bridge: adv7511: clean up CEC adapter when probe fails
Jani Nikula <jani.nikula@intel.com>
drm/edid: fix invalid EDID extension block filtering
Wenli Looi <wlooi@ucalgary.ca>
ath9k: fix ar9003_get_eepmisc
Nicolas Belin <nbelin@baylibre.com>
drm: bridge: it66121: Fix the register page length
Niels Dossche <dossche.niels@gmail.com>
ath11k: acquire ab->base_lock in unassign when finding the peer by addr
Zack Rusin <zackr@vmware.com>
drm/vmwgfx: Fix an invalid read
Noralf Trønnes <noralf@tronnes.org>
dt-bindings: display: sitronix, st7735r: Fix backlight in example
Wan Jiabing <wanjiabing@vivo.com>
drm/omap: fix NULL but dereferenced coccicheck error
Nikita Yushchenko <nikita.yoush@cogentembedded.com>
drm/bridge_connector: enable HPD by default if supported
Linus Torvalds <torvalds@linux-foundation.org>
drm: fix EDID struct for old ARM OABI format
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Input: gpio-keys - cancel delayed work only in case of GPIO
Shyam Prasad N <sprasad@microsoft.com>
cifs: do not use tcpStatus after negotiate completes
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent panic when SDMA is disabled
Steve French <stfrench@microsoft.com>
smb3: check for null tcon
Vasily Averin <vvs@openvz.org>
fanotify: fix incorrect fmode_t casts
Peng Wu <wupeng58@huawei.com>
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Finn Thain <fthain@linux-m68k.org>
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/powernv: fix missing of_node_put in uv_init()
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/xics: fix refcount leak in icp_opal_init()
Haren Myneni <haren@linux.ibm.com>
powerpc/powernv/vas: Assign real address to rx_fifo in vas_rx_win_attr
Enzo Matsumiya <ematsumiya@suse.de>
cifs: return ENOENT for DFS lookup_cache_entry()
Vasily Averin <vvs@openvz.org>
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
Matthew Wilcox (Oracle) <willy@infradead.org>
alpha: fix alloc_zeroed_user_highpage_movable()
Nicholas Piggin <npiggin@gmail.com>
KVM: PPC: Book3S HV Nested: L2 LPCR should inherit L1 LPES setting
Parshuram Thombare <pthombar@cadence.com>
PCI: cadence: Clear FLR in device capabilities register
Yicong Yang <yangyicong@hisilicon.com>
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Laurent Dufour <ldufour@linux.ibm.com>
powerpc/rtas: Keep MSR[RI] set when calling RTAS
Conor Dooley <conor.dooley@microchip.com>
PCI: microchip: Add missing chained_irq_enter()/exit() calls
Viresh Kumar <viresh.kumar@linaro.org>
cpufreq: Avoid unnecessary frequency updates due to mismatch
Peng Wu <wupeng58@huawei.com>
ARM: hisi: Add missing of_node_put after of_find_compatible_node
Vijaya Krishna Nivarthi <quic_vnivarth@quicinc.com>
arm64: dts: qcom: sc7280-idp: Configure CTS pin to bias-bus-hold for bluetooth
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
Peng Wu <wupeng58@huawei.com>
ARM: versatile: Add missing of_node_put in dcscb_init
Yang Yingliang <yangyingliang@huawei.com>
pinctrl: renesas: rzn1: Fix possible null-ptr-deref in sh_pfc_map_resources()
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
fat: add ratelimit to fat*_ent_bread()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: Fix fadump to work with a different endian capture kernel
Janusz Krzysztofik <jmkrzyszt@gmail.com>
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Move generic implicit fb quirk entries into quirks.c
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Add quirk bits for enabling/disabling generic implicit fb
Joel Selvaraj <jo@jsfamily.in>
arm64: dts: qcom: sdm845-xiaomi-beryllium: fix typo in panel's vddio-supply property
Zixuan Fu <r33s3n6@gmail.com>
fs: jfs: fix possible NULL pointer dereference in dbFree()
QintaoShen <unSimple1993@163.com>
soc: ti: ti_sci_pm_domains: Check for null return of devm_kcalloc
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - fix off-by-one error in PFVF debug print
Gilad Ben-Yossef <gilad@benyossef.com>
crypto: ccree - use fine grained DMA mapping dir
Brian Norris <briannorris@chromium.org>
PM / devfreq: rk3399_dmc: Disable edev on remove()
Konrad Dybcio <konrad.dybcio@somainline.org>
arm64: dts: qcom: msm8994: Fix BLSP[12]_DMA channels count
Konrad Dybcio <konrad.dybcio@somainline.org>
arm64: dts: qcom: msm8994: Fix the cont_splash_mem address
Mario Limonciello <mario.limonciello@amd.com>
ASoC: amd: Add driver data to acp6x machine driver
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: s5pv210: align DMA channels with dtschema
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: socfpga: align interrupt controller node name with dtschema
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: ox820: align interrupt controller node name with dtschema
Mika Westerberg <mika.westerberg@linux.intel.com>
PCI/ASPM: Make Intel DG2 L1 acceptable latency unlimited
Niels Dossche <dossche.niels@gmail.com>
IB/rdmavt: add missing locks in rvt_ruc_loopback
Daniel Latypov <dlatypov@google.com>
kunit: fix executor OOM error handling logic on non-UML
Bodo Stroesser <bostroesser@gmail.com>
scsi: target: tcmu: Avoid holding XArray lock when calling lock_page
Bob Peterson <rpeterso@redhat.com>
gfs2: use i_lock spin_lock for inode qadata
Yonghong Song <yhs@fb.com>
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
char: tpm: cr50_i2c: Suppress duplicated error message in .remove()
Jakub Kicinski <kuba@kernel.org>
eth: tg3: silence the GCC 12 array-bounds warning
David Howells <dhowells@redhat.com>
afs: Adjust ACK interpretation to try and cope with NAT
David Howells <dhowells@redhat.com>
rxrpc, afs: Fix selection of abort codes
David Howells <dhowells@redhat.com>
rxrpc: Return an error to sendmsg if call failed
Geert Uytterhoeven <geert@linux-m68k.org>
m68k: atari: Make Atari ROM port I/O write macros return void
Yuntao Wang <ytcoode@gmail.com>
selftests/bpf: Add missing trampoline program type to trampoline_count test
Alex Elder <elder@linaro.org>
net: ipa: ignore endianness if there is no header
Borislav Petkov <bp@suse.de>
x86/microcode: Add explicit CPU vendor dependency
Vincent Mailhol <mailhol.vincent@wanadoo.fr>
can: mcp251xfd: silence clang's -Wunaligned-access warning
Chaitanya Kulkarni <kch@nvidia.com>
nvme: set non-mdts limits in nvme_scan_work
Pierre Gondois <Pierre.Gondois@arm.com>
ACPI: CPPC: Assume no transition latency if no PCCT
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: rt1015p: remove dependency on GPIOLIB
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: max98357a: remove dependency on GPIOLIB
Laibin Qiu <qiulaibin@huawei.com>
blk-throttle: Set BIO_THROTTLED when bio has been throttled
Andre Przywara <andre.przywara@arm.com>
of/fdt: Ignore disabled memory nodes
Ping-Ke Shih <pkshih@realtek.com>
rtw89: cfo: check mac_id to avoid out-of-bounds
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: hantro: Stop using H.264 parameter pic_num
Kwanghoon Son <k.son@samsung.com>
media: exynos4-is: Fix compile warning
Fabio Estevam <festevam@denx.de>
net: phy: micrel: Allow probing without .driver_data
Daniel Latypov <dlatypov@google.com>
kunit: tool: make parser stop overwriting status of suites w/ no_tests
Omar Sandoval <osandov@fb.com>
btrfs: fix anon_dev leak in create_subvol()
Sathishkumar S <sathishkumar.sundararaju@amd.com>
drm/amd/pm: update smartshift powerboost calc for smu13
Sathishkumar S <sathishkumar.sundararaju@amd.com>
drm/amd/pm: update smartshift powerboost calc for smu12
Xie Yongji <xieyongji@bytedance.com>
nbd: Fix hung on disconnect request if socket is closed before
Lin Ma <linma@zju.edu.cn>
ASoC: rt5645: Fix errorenous cleanup order
Smith, Kyle Miller (Nimble Kernel) <kyles@hpe.com>
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Jason A. Donenfeld <Jason@zx2c4.com>
openrisc: start CPU timer early in boot
Zijun Hu <quic_zijuhu@quicinc.com>
Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ERR_DATA_REPORTING for QCA
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN for QCA
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: HCI: Add HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN quirk
Lukas Wunner <lukas@wunner.de>
usbnet: Run unregister_netdev() before unbind() again
Hans Verkuil <hverkuil-cisco@xs4all.nl>
media: cec-adap.c: fix is_configuring state
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
media: imon: reorganize serialization
Hans Verkuil <hverkuil-cisco@xs4all.nl>
media: ccs-core.c: fix failure to call clk_disable_unprepare
Benjamin Gaignard <benjamin.gaignard@collabora.com>
media: hantro: HEVC: unconditionnaly set pps_{cb/cr}_qp_offset values
Philipp Zabel <p.zabel@pengutronix.de>
media: coda: limit frame interval enumeration to supported encoder frame sizes
Hangyu Hua <hbh25y@gmail.com>
media: rga: fix possible memory leak in rga_probe
Felix Fietkau <nbd@nbd.name>
mt76: fix encap offload ethernet type check
Felix Fietkau <nbd@nbd.name>
mt76: mt7921: accept rx frames with non-standard VHT MCS10-11
Dongliang Mu <mudongliangabcd@gmail.com>
rtlwifi: Use pr_warn instead of WARN_ONCE
Daniel Latypov <dlatypov@google.com>
kunit: bail out of test filtering logic quicker if OOM
Corey Minyard <cminyard@mvista.com>
ipmi: Fix pr_fmt to avoid compilation issues
Corey Minyard <cminyard@mvista.com>
ipmi: Add an intializer for ipmi_smi_msg struct
Corey Minyard <cminyard@mvista.com>
ipmi:ssif: Check for NULL msg when handling events and messages
Mario Limonciello <mario.limonciello@amd.com>
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
Zheng Bin <zhengbin13@huawei.com>
ASoC: SOF: amd: add missing platform_device_unregister in acp_pci_rn_probe
Mikulas Patocka <mpatocka@redhat.com>
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
Patrice Chotard <patrice.chotard@foss.st.com>
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Hao Jia <jiahao.os@bytedance.com>
sched/core: Avoid obvious double update_rq_clock warning
Ravi Bangoria <ravi.bangoria@amd.com>
perf/amd/ibs: Cascade pmu init functions' return value
Heiko Carstens <hca@linux.ibm.com>
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Eric Dumazet <edumazet@google.com>
net: remove two BUG() from skb_checksum_help()
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Alter FPIN stat accounting logic
Xiang Chen <chenxiang66@hisilicon.com>
scsi: hisi_sas: Undo RPM resume for failed notify phy event for v3 HW
Gavin Li <gavinl@nvidia.com>
net/mlx5: Increase FW pre-init timeout for health recovery
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
Zhen Lei <thunder.leizhen@huawei.com>
of: Support more than one crash kernel regions for kexec -s
Thierry Reding <treding@nvidia.com>
drm/tegra: gem: Do not try to dereference ERR_PTR()
Dongliang Mu <mudongliangabcd@gmail.com>
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
Nícolas F. R. A. Prado <nfraprado@collabora.com>
regulator: mt6315: Enforce regulator-compatible, not name
Alice Wong <shiwei.wong@amd.com>
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/psp: move PSP memory alloc from hw_init to sw_init
Petr Machata <petrm@nvidia.com>
mlxsw: Treat LLDP packets as control
Petr Machata <petrm@nvidia.com>
mlxsw: spectrum_dcb: Do not warn about priority changes
Mark Brown <broonie@kernel.org>
ASoC: dapm: Don't fold register value changes into notifications
Mark Bloch <mbloch@nvidia.com>
net/mlx5: fs, delete the FTE when there are no rules attached to it
jianghaoran <jianghaoran@kylinos.cn>
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
Xiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
scsi: target: tcmu: Fix possible data corruption
Wen Gong <quic_wgong@quicinc.com>
ath11k: fix warning of not found station for bssid in message
Max Filippov <jcmvbkbc@gmail.com>
xtensa: move trace_hardirqs_off call back to entry.S
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/dpu: Clean up CRC debug logs
Lv Ruyi <lv.ruyi@zte.com.cn>
drm: msm: fix error check return value of irq_of_parse_and_map()
Alexandru Elisei <alexandru.elisei@arm.com>
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Abhishek Kumar <kuabhs@chromium.org>
ath10k: skip ath10k_halt during suspend for driver state RESTARTING
Evan Quan <evan.quan@amd.com>
drm/amd/pm: fix the compile warning
Steven Price <steven.price@arm.com>
drm/plane: Move range check for format_count earlier
Hans de Goede <hdegoede@redhat.com>
ASoC: Intel: bytcr_rt5640: Add quirk for the HP Pro Tablet 408
Hari Chandrakanthan <quic_haric@quicinc.com>
ath11k: disable spectral scan during spectral deinit
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix resource leak in lpfc_sli4_send_seq_to_ulp()
Minghao Chi <chi.minghao@zte.com.cn>
scsi: ufs: Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
Haohui Mai <ricetons@gmail.com>
drm/amdgpu/sdma: Fix incorrect calculations of the wptr of the doorbells
Lv Ruyi <lv.ruyi@zte.com.cn>
scsi: megaraid: Fix error check return value of register_chrdev()
Vignesh Raghavendra <vigneshr@ti.com>
drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit
Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
mmc: jz4740: Apply DMA engine limits to maximum segment size
Heming Zhao <heming.zhao@suse.com>
md/bitmap: don't set sb values if can't pass sanity check
Zheyu Ma <zheyuma97@gmail.com>
media: cx25821: Fix the warning when removing the module
Zheyu Ma <zheyuma97@gmail.com>
media: pci: cx23885: Fix the error handling in cx23885_initdev()
Vikash Garodia <quic_vgarodia@quicinc.com>
media: venus: do not queue internal buffers from previous sequence
Luca Weiss <luca.weiss@fairphone.com>
media: venus: hfi: avoid null dereference in deinit
Sakari Ailus <sakari.ailus@linux.intel.com>
media: Revert "media: dw9768: activate runtime PM and turn off device"
Thibaut VARÈNE <hacks+kernel@slashdirt.org>
ath9k: fix QCA9561 PA bias level
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: rsnd: care return value from rsnd_node_fixed_index()
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: rsnd: care default case on rsnd_ssiu_busif_err_status_clear()
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
drm/amd/pm: fix double free in si_parse_power_table()
Ulf Hansson <ulf.hansson@linaro.org>
cpuidle: PSCI: Improve support for suspend-to-RAM for PSCI OSI mode
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix call trace observed during I/O with CMF enabled
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix SCSI I/O completion and abort handler deadlock
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Move cfg_log_verbose check before calling lpfc_dmp_dbg()
Eric Dumazet <edumazet@google.com>
tcp: consume incoming skb leading to a reset
Len Brown <len.brown@intel.com>
tools/power turbostat: fix ICX DRAM power numbers
Biju Das <biju.das.jz@bp.renesas.com>
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Po-Hao Huang <phhuang@realtek.com>
rtw88: 8821c: fix debugfs rssi value
Po-Hao Huang <phhuang@realtek.com>
rtw88: fix incorrect frequency reported
Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
ALSA: jack: Access input_dev under mutex
Haowen Bai <baihaowen@meizu.com>
sfc: ef10: Fix assigning negative value to unsigned variable
Paul E. McKenney <paulmck@kernel.org>
rcu: Make TASKS_RUDE_RCU select IRQ_WORK
Paul E. McKenney <paulmck@kernel.org>
rcu-tasks: Handle sparse cpu_possible_mask in rcu_tasks_invoke_cbs()
Padmanabha Srinivasaiah <treasure4paddy@gmail.com>
rcu-tasks: Fix race in schedule and flush work
Saaem Rizvi <syerizvi@amd.com>
drm/amd/display: Disabling Z10 on DCN31
Liviu Dudau <liviu.dudau@arm.com>
drm/komeda: return early if drm_universal_plane_init() fails.
Peter Seiderer <ps.report@gmx.net>
mac80211: minstrel_ht: fix where rate stats are stored (fixes debugfs output)
Runqing Yang <rainkin1993@gmail.com>
libbpf: Fix a bug with checking bpf_probe_read_kernel() support in old kernels
Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
ACPICA: Avoid cache flush inside virtual machines
Mike Travis <mike.travis@hpe.com>
x86/platform/uv: Update TSC sync state for UV5
Daniel Vetter <daniel.vetter@ffwll.ch>
fbcon: Consistently protect deferred_takeover with console_lock()
Niels Dossche <dossche.niels@gmail.com>
ipv6: fix locking issues with loops over idev->addr_list
Haowen Bai <baihaowen@meizu.com>
ipw2x00: Fix potential NULL dereference in libipw_xmit()
Haowen Bai <baihaowen@meizu.com>
b43: Fix assigning negative value to unsigned variable
Haowen Bai <baihaowen@meizu.com>
b43legacy: Fix assigning negative value to unsigned variable
Niels Dossche <dossche.niels@gmail.com>
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
ath11k: Change max no of active probe SSID and BSSID to fw capability
Quentin Monnet <quentin@isovalent.com>
selftests/bpf: Fix parsing of prog types in UAPI hdr for bpftool sync
Nikolay Borisov <nborisov@suse.com>
selftests/bpf: Fix vfs_link kprobe definition
Liu Zixian <liuzixian4@huawei.com>
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Wen Gong <quic_wgong@quicinc.com>
ath11k: fix the warning of dev_wake in mhi_pm_disable_transition()
Zack Rusin <zackr@vmware.com>
drm/vmwgfx: validate the screen formats
Tejas Upadhyay <tejaskumarx.surendrakumar.upadhyay@intel.com>
iommu/vt-d: Add RPLS to quirk list to skip TE disabling
Naohiro Aota <naohiro.aota@wdc.com>
btrfs: zoned: fix comparison of alloc_offset vs meta_write_pointer
Naohiro Aota <naohiro.aota@wdc.com>
btrfs: zoned: finish block group when there are no more allocatable bytes left
Naohiro Aota <naohiro.aota@wdc.com>
btrfs: zoned: zone finish unused block group
Naohiro Aota <naohiro.aota@wdc.com>
btrfs: zoned: properly finish block group on metadata write
Qu Wenruo <wqu@suse.com>
btrfs: fix the error handling for submit_extent_page() for btrfs_do_readpage()
Qu Wenruo <wqu@suse.com>
btrfs: repair super block num_devices automatically
Qu Wenruo <wqu@suse.com>
btrfs: return correct error number for __extent_writepage_io()
Qu Wenruo <wqu@suse.com>
btrfs: add "0x" prefix for unsupported optional features
Eric W. Biederman <ebiederm@xmission.com>
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Eric W. Biederman <ebiederm@xmission.com>
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
Eric W. Biederman <ebiederm@xmission.com>
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
Eric W. Biederman <ebiederm@xmission.com>
kthread: Don't allocate kthread_struct for init and umh
Kristen Carlson Accardi <kristen@linux.intel.com>
x86/sgx: Set active memcg prior to shmem allocation
Baoquan He <bhe@redhat.com>
x86/kexec: fix memory leak of elf header buffer
Kan Liang <kan.liang@linux.intel.com>
perf/x86/intel: Fix event constraints for ICL
Ammar Faizi <ammarfaizi2@gnuweeb.org>
x86/MCE/AMD: Fix memory leak when threshold_create_bank() fails
Michael Niewöhner <linux@mniewoehner.de>
platform/x86: intel-hid: fix _DSM function index handling
Mathias Nyman <mathias.nyman@linux.intel.com>
xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: when extending a file with falloc we should make files not-sparse
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: fix potential double free during failed mount
Paulo Alcantara <pc@cjr.nz>
cifs: fix ntlmssp on old servers
Enzo Matsumiya <ematsumiya@suse.de>
cifs: don't call cifs_dfs_query_info_nonascii_quirk() if nodfs was set
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Restore ntfs_xattr_get_acl and ntfs_xattr_set_acl functions
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Update i_ctime when xattr is added
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
fs/ntfs3: Fix some memory leaks in an error handling path of 'log_replay()'
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: In function ntfs_set_acl_ex do not change inode->i_mode if called from function ntfs_init_acl
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Check new size for limits
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Keep preallocated only if option prealloc enabled
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Fix fiemap + fix shrink file size (to remove preallocated space)
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Update valid size if -EIOCBQUEUED
Kishon Vijay Abraham I <kishon@ti.com>
usb: core: hcd: Add support for deferring roothub registration
Albert Wang <albertccwang@google.com>
usb: dwc3: gadget: Move null pinter check to proper place
Linus Walleij <linus.walleij@linaro.org>
usb: isp1760: Fix out-of-bounds array access
Monish Kumar R <monish.kumar.r@intel.com>
USB: new quirk for Dell Gen 2 devices
Carl Yin(殷张成) <carl.yin@quectel.com>
USB: serial: option: add Quectel BG95 modem
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix type detection for odd device
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Cancel pending work at closing a MIDI substream
Marios Levogiannis <marios.levogiannis@gmail.com>
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Rik van der Kemp <rik@upto11.nl>
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9520 laptop
Kailang Yang <kailang@realtek.com>
ALSA: hda/realtek - Add new type for ALC245
Nathan Chancellor <nathan@kernel.org>
riscv: Move alternative length validation into subsection
Tobias Klauser <tklauser@distanz.ch>
riscv: Wire up memfd_secret in UAPI header
Samuel Holland <samuel@sholland.org>
riscv: Fix irq_work when SMP is disabled
Alexandre Ghiti <alexandre.ghiti@canonical.com>
riscv: Initialize thread pointer before calling C functions
Xianting Tian <xianting.tian@linux.alibaba.com>
RISC-V: Mark IORESOURCE_EXCLUSIVE for reserved mem instead of IORESOURCE_BUSY
Helge Deller <deller@gmx.de>
parisc/stifb: Keep track of hardware path of graphics card
Helge Deller <deller@gmx.de>
parisc/stifb: Implement fb_is_primary_device()
Niklas Cassel <niklas.cassel@wdc.com>
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
Stephen Boyd <swboyd@chromium.org>
arm64: Initialize jump labels before setup_machine_fdt()
-------------
Diffstat:
Documentation/accounting/psi.rst | 9 +-
Documentation/conf.py | 2 +-
.../bindings/display/sitronix,st7735r.yaml | 1 +
.../devicetree/bindings/gpio/gpio-altera.txt | 5 +-
.../bindings/regulator/mt6315-regulator.yaml | 2 +-
.../devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml | 1 +
.../bindings/spi/qcom,spi-qcom-qspi.yaml | 1 +
Documentation/sound/alsa-configuration.rst | 4 +-
Documentation/userspace-api/landlock.rst | 4 +-
Makefile | 4 +-
arch/alpha/include/asm/page.h | 2 +-
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13 +-
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22 +-
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4 +-
arch/arm/boot/dts/bcm5301x.dtsi | 2 +-
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4 +-
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 6 +-
arch/arm/boot/dts/imx6qdl-colibri.dtsi | 6 +-
arch/arm/boot/dts/ox820.dtsi | 2 +-
arch/arm/boot/dts/qcom-sdx65.dtsi | 2 +-
arch/arm/boot/dts/s5pv210-aries.dtsi | 3 +-
arch/arm/boot/dts/s5pv210.dtsi | 12 +-
arch/arm/boot/dts/sama7g5.dtsi | 1 -
arch/arm/boot/dts/socfpga.dtsi | 2 +-
arch/arm/boot/dts/socfpga_arria10.dtsi | 2 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 1 +
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4 +-
arch/arm/include/asm/arch_gicv3.h | 7 +-
arch/arm/kernel/signal.c | 1 +
arch/arm/mach-hisi/platsmp.c | 4 +
arch/arm/mach-mediatek/Kconfig | 1 +
arch/arm/mach-omap1/clock.c | 2 +-
arch/arm/mach-pxa/cm-x300.c | 8 +-
arch/arm/mach-pxa/magician.c | 2 +-
arch/arm/mach-pxa/tosa.c | 4 +-
arch/arm/mach-vexpress/dcscb.c | 1 +
arch/arm64/Kconfig.platforms | 1 +
.../dts/marvell/armada-3720-espressobin-ultra.dts | 5 -
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 2 +-
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 5 +-
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8994.dtsi | 8 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 2 +-
arch/arm64/boot/dts/qcom/sc7280-idp.dtsi | 18 +-
.../boot/dts/qcom/sdm845-xiaomi-beryllium.dts | 2 +-
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi | 2 -
arch/arm64/include/asm/arch_gicv3.h | 6 -
arch/arm64/include/asm/processor.h | 10 +-
arch/arm64/kernel/setup.c | 7 +-
arch/arm64/kernel/signal.c | 1 +
arch/arm64/kernel/signal32.c | 1 +
arch/arm64/kernel/sys_compat.c | 2 +-
arch/arm64/mm/copypage.c | 4 +-
arch/csky/kernel/probes/kprobes.c | 2 +-
arch/m68k/Kconfig.cpu | 2 +-
arch/m68k/include/asm/raw_io.h | 6 +-
arch/m68k/kernel/signal.c | 1 +
.../include/asm/mach-ip27/cpu-feature-overrides.h | 1 -
.../include/asm/mach-ip30/cpu-feature-overrides.h | 1 -
arch/mips/include/asm/mach-ralink/spaces.h | 2 +
arch/openrisc/include/asm/timex.h | 1 +
arch/openrisc/kernel/head.S | 9 +
arch/parisc/include/asm/fb.h | 4 +
arch/powerpc/include/asm/page.h | 7 +-
arch/powerpc/include/asm/vas.h | 2 +-
arch/powerpc/kernel/entry_64.S | 24 +-
arch/powerpc/kernel/fadump.c | 8 +-
arch/powerpc/kernel/idle.c | 2 +-
arch/powerpc/kernel/rtas.c | 9 +
arch/powerpc/kvm/book3s_hv.c | 12 +-
arch/powerpc/kvm/book3s_hv_nested.c | 3 +-
arch/powerpc/kvm/trace_hv.h | 8 +-
arch/powerpc/mm/nohash/fsl_book3e.c | 15 +-
arch/powerpc/perf/isa207-common.c | 12 +-
arch/powerpc/platforms/4xx/cpm.c | 2 +-
arch/powerpc/platforms/8xx/cpm1.c | 1 +
arch/powerpc/platforms/powernv/opal-fadump.c | 94 +--
arch/powerpc/platforms/powernv/opal-fadump.h | 10 +-
arch/powerpc/platforms/powernv/setup.c | 9 +
arch/powerpc/platforms/powernv/ultravisor.c | 1 +
arch/powerpc/platforms/powernv/vas-fault.c | 2 +-
arch/powerpc/platforms/powernv/vas-window.c | 4 +-
arch/powerpc/platforms/powernv/vas.h | 2 +-
arch/powerpc/sysdev/dart_iommu.c | 6 +-
arch/powerpc/sysdev/fsl_rio.c | 2 +
arch/powerpc/sysdev/xics/icp-opal.c | 1 +
arch/powerpc/sysdev/xive/spapr.c | 43 +-
arch/riscv/Makefile | 4 +
arch/riscv/include/asm/alternative-macros.h | 4 +-
arch/riscv/include/asm/irq_work.h | 2 +-
arch/riscv/include/asm/unistd.h | 1 -
arch/riscv/include/uapi/asm/unistd.h | 1 +
arch/riscv/kernel/head.S | 1 +
arch/riscv/kernel/setup.c | 4 +-
arch/riscv/mm/init.c | 2 +-
arch/s390/include/asm/cio.h | 2 +-
arch/s390/include/asm/kexec.h | 10 +
arch/s390/include/asm/preempt.h | 15 +-
arch/s390/kernel/perf_event.c | 2 +-
arch/s390/kernel/time.c | 8 +-
arch/sparc/kernel/signal32.c | 1 +
arch/sparc/kernel/signal_64.c | 1 +
arch/um/drivers/chan_user.c | 9 +-
arch/um/drivers/virtio_uml.c | 33 +-
arch/um/include/asm/Kbuild | 1 +
arch/um/include/asm/thread_info.h | 2 +
arch/um/kernel/exec.c | 2 +-
arch/um/kernel/process.c | 2 +-
arch/um/kernel/ptrace.c | 8 +-
arch/um/kernel/signal.c | 4 +-
arch/x86/Kconfig | 4 +-
arch/x86/entry/entry_64.S | 1 +
arch/x86/entry/vdso/vma.c | 2 +-
arch/x86/events/amd/ibs.c | 55 +-
arch/x86/events/intel/core.c | 2 +-
arch/x86/include/asm/acenv.h | 14 +-
arch/x86/include/asm/kexec.h | 8 +
arch/x86/include/asm/set_memory.h | 52 --
arch/x86/include/asm/suspend_32.h | 2 +-
arch/x86/include/asm/suspend_64.h | 12 +-
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/apic/x2apic_uv_x.c | 8 +-
arch/x86/kernel/cpu/intel.c | 2 +-
arch/x86/kernel/cpu/mce/amd.c | 32 +-
arch/x86/kernel/cpu/mce/core.c | 6 +-
arch/x86/kernel/cpu/sgx/encl.c | 105 ++-
arch/x86/kernel/cpu/sgx/encl.h | 7 +-
arch/x86/kernel/cpu/sgx/main.c | 9 +-
arch/x86/kernel/machine_kexec_64.c | 12 +-
arch/x86/kernel/signal_compat.c | 2 +
arch/x86/kernel/step.c | 3 +-
arch/x86/kernel/sys_x86_64.c | 7 +-
arch/x86/kvm/lapic.c | 1 +
arch/x86/kvm/vmx/nested.c | 45 +-
arch/x86/kvm/vmx/vmcs.h | 5 +
arch/x86/lib/delay.c | 4 +-
arch/x86/mm/pat/memtype.c | 2 +-
arch/x86/mm/pat/set_memory.c | 49 +-
arch/x86/pci/irq.c | 19 +-
arch/x86/um/ldt.c | 6 +-
arch/xtensa/kernel/entry.S | 19 +-
arch/xtensa/kernel/ptrace.c | 4 +-
arch/xtensa/kernel/signal.c | 4 +-
arch/xtensa/kernel/traps.c | 11 +-
arch/xtensa/platforms/iss/simdisk.c | 18 +-
block/bfq-cgroup.c | 111 +--
block/bfq-iosched.c | 64 +-
block/bfq-iosched.h | 7 +-
block/blk-ia-ranges.c | 7 +-
block/blk-iolatency.c | 122 ++--
block/blk-throttle.c | 3 +-
crypto/cryptd.c | 23 +-
drivers/acpi/cppc_acpi.c | 17 +-
drivers/acpi/property.c | 18 +-
drivers/acpi/sleep.c | 12 +
drivers/base/memory.c | 5 +-
drivers/base/node.c | 1 +
drivers/base/power/domain.c | 1 +
drivers/base/property.c | 89 +--
drivers/block/drbd/drbd_main.c | 11 +-
drivers/block/nbd.c | 13 +-
drivers/block/virtio_blk.c | 7 +-
drivers/bluetooth/btmtksdio.c | 3 +-
drivers/bluetooth/btusb.c | 6 +
drivers/char/hw_random/cn10k-rng.c | 31 +-
drivers/char/hw_random/omap3-rom-rng.c | 2 +-
drivers/char/ipmi/ipmi_msghandler.c | 4 +-
drivers/char/ipmi/ipmi_poweroff.c | 4 +-
drivers/char/ipmi/ipmi_ssif.c | 23 +
drivers/char/ipmi/ipmi_watchdog.c | 14 +-
drivers/char/random.c | 12 +-
drivers/char/tpm/tpm_tis_i2c_cr50.c | 4 +-
drivers/clk/tegra/clk-dfll.c | 12 +
drivers/cpufreq/cpufreq.c | 11 +
drivers/cpufreq/mediatek-cpufreq.c | 18 +-
drivers/cpuidle/cpuidle-psci.c | 46 ++
.../crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c | 115 ++--
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 30 +-
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c | 10 +-
drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 14 +-
drivers/crypto/ccp/sev-dev.c | 30 +-
drivers/crypto/ccree/cc_buffer_mgr.c | 27 +-
drivers/crypto/marvell/cesa/cipher.c | 1 -
drivers/crypto/nx/nx-common-powernv.c | 2 +-
drivers/crypto/qat/qat_common/adf_pfvf_pf_proto.c | 2 +-
.../crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 13 +-
drivers/devfreq/rk3399_dmc.c | 2 +
drivers/dma/idxd/cdev.c | 8 +-
drivers/dma/stm32-mdma.c | 23 +-
drivers/edac/dmc520_edac.c | 2 +-
drivers/firmware/arm_ffa/driver.c | 4 +-
drivers/firmware/arm_scmi/base.c | 2 +-
drivers/firmware/efi/Kconfig | 15 +
drivers/firmware/efi/efi.c | 2 +-
drivers/gpio/gpio-rockchip.c | 24 +-
drivers/gpio/gpio-sim.c | 4 +-
drivers/gpio/gpiolib-of.c | 5 +
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 95 ++-
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 +-
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4 +-
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 8 +-
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 8 +-
.../gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 1 +
drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 14 +-
drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 8 +-
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 60 +-
.../gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 62 +-
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10 +-
drivers/gpu/drm/arm/malidp_crtc.c | 5 +-
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1 +
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31 +-
drivers/gpu/drm/bridge/analogix/anx7625.c | 12 +-
drivers/gpu/drm/bridge/analogix/anx7625.h | 4 +-
drivers/gpu/drm/bridge/chipone-icn6211.c | 155 ++++-
drivers/gpu/drm/bridge/ite-it66121.c | 2 +-
drivers/gpu/drm/drm_bridge_connector.c | 4 +-
drivers/gpu/drm/drm_edid.c | 6 +-
drivers/gpu/drm/drm_plane.c | 14 +-
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6 +
drivers/gpu/drm/gma500/psb_intel_display.c | 7 +-
drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 33 +-
drivers/gpu/drm/i915/i915_perf.c | 4 +-
drivers/gpu/drm/i915/i915_perf_types.h | 2 +-
drivers/gpu/drm/mediatek/mtk_cec.c | 2 +-
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 16 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 22 +-
drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 20 +-
drivers/gpu/drm/mediatek/mtk_dpi.c | 4 +-
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 14 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 29 +-
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 +
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 19 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 16 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 3 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 3 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 2 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20 +-
drivers/gpu/drm/msm/dp/dp_ctrl.c | 16 +-
drivers/gpu/drm/msm/dp/dp_display.c | 55 +-
drivers/gpu/drm/msm/dp/dp_drm.c | 4 +
drivers/gpu/drm/msm/dsi/dsi_host.c | 21 +-
drivers/gpu/drm/msm/dsi/dsi_manager.c | 3 +
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 2 +-
drivers/gpu/drm/msm/hdmi/hdmi.c | 10 +-
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 3 +
drivers/gpu/drm/msm/msm_drv.c | 11 +-
drivers/gpu/drm/msm/msm_gem_prime.c | 2 +-
drivers/gpu/drm/msm/msm_gpu.h | 12 +-
drivers/gpu/drm/msm/msm_gpu_devfreq.c | 90 ++-
drivers/gpu/drm/msm/msm_kms.h | 1 +
drivers/gpu/drm/nouveau/dispnv50/atom.h | 6 +-
drivers/gpu/drm/nouveau/dispnv50/crc.c | 27 +-
drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 2 +
drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c | 14 +-
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c | 6 +-
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c | 6 +-
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6 +-
drivers/gpu/drm/omapdrm/omap_overlay.c | 2 +-
drivers/gpu/drm/panel/panel-simple.c | 3 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 +-
drivers/gpu/drm/stm/ltdc.c | 16 +-
drivers/gpu/drm/tegra/gem.c | 1 +
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8 +-
drivers/gpu/drm/v3d/v3d_perfmon.c | 3 +-
drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
drivers/gpu/drm/vc4/vc4_drv.h | 1 +
drivers/gpu/drm/vc4/vc4_hvs.c | 49 +-
drivers/gpu/drm/vc4/vc4_kms.c | 5 +-
drivers/gpu/drm/vc4/vc4_regs.h | 12 +-
drivers/gpu/drm/vc4/vc4_txp.c | 8 +-
drivers/gpu/drm/virtio/virtgpu_display.c | 2 +
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 30 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1 -
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 14 +-
drivers/hid/amd-sfh-hid/amd_sfh_hid.c | 4 +-
drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2 +-
drivers/hid/hid-bigbenff.c | 6 +
drivers/hid/hid-elan.c | 2 -
drivers/hid/hid-led.c | 2 +-
drivers/hv/channel.c | 6 +-
drivers/hwmon/pmbus/pmbus_core.c | 28 +-
drivers/hwtracing/coresight/coresight-core.c | 33 +-
drivers/i2c/busses/i2c-at91-master.c | 11 +
drivers/i2c/busses/i2c-npcm7xx.c | 103 ++-
drivers/i2c/busses/i2c-rcar.c | 15 +-
drivers/infiniband/hw/hfi1/file_ops.c | 2 +
drivers/infiniband/hw/hfi1/init.c | 2 +-
drivers/infiniband/hw/hfi1/sdma.c | 12 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 7 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 24 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 2 +-
drivers/infiniband/sw/rdmavt/qp.c | 6 +-
drivers/infiniband/sw/rxe/rxe_req.c | 2 +-
drivers/input/keyboard/gpio_keys.c | 2 +-
drivers/input/misc/sparcspkr.c | 1 +
drivers/input/touchscreen/stmfts.c | 16 +-
drivers/iommu/amd/init.c | 2 +-
drivers/iommu/amd/iommu.c | 7 -
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 13 +-
drivers/iommu/dma-iommu.c | 7 +-
drivers/iommu/intel/iommu.c | 2 +-
drivers/iommu/msm_iommu.c | 11 +-
drivers/iommu/mtk_iommu.c | 30 +-
drivers/iommu/mtk_iommu.h | 2 +
drivers/iommu/mtk_iommu_v1.c | 7 +
drivers/irqchip/irq-armada-370-xp.c | 11 +-
drivers/irqchip/irq-aspeed-i2c-ic.c | 4 +-
drivers/irqchip/irq-aspeed-scu-ic.c | 4 +-
drivers/irqchip/irq-gic-v3.c | 183 +++--
drivers/irqchip/irq-sni-exiu.c | 25 +-
drivers/irqchip/irq-xtensa-mx.c | 18 +-
drivers/macintosh/Kconfig | 6 +
drivers/macintosh/Makefile | 3 +-
drivers/macintosh/via-pmu.c | 2 +-
drivers/mailbox/mailbox.c | 19 +-
drivers/mailbox/pcc.c | 2 +-
drivers/md/bcache/btree.c | 58 +-
drivers/md/bcache/btree.h | 2 +-
drivers/md/bcache/journal.c | 31 +-
drivers/md/bcache/journal.h | 2 +
drivers/md/bcache/request.c | 6 +
drivers/md/bcache/super.c | 1 +
drivers/md/bcache/writeback.c | 101 +--
drivers/md/bcache/writeback.h | 2 +-
drivers/md/md-bitmap.c | 44 +-
drivers/md/md.c | 22 +-
drivers/md/raid0.c | 1 -
drivers/media/cec/core/cec-adap.c | 6 +-
drivers/media/i2c/ccs/ccs-core.c | 7 +-
drivers/media/i2c/dw9768.c | 6 -
drivers/media/i2c/max9286.c | 137 ++--
drivers/media/i2c/ov5648.c | 4 +-
drivers/media/i2c/ov7670.c | 1 -
drivers/media/i2c/rdacm20.c | 2 +-
drivers/media/i2c/rdacm21.c | 2 +-
drivers/media/pci/cx23885/cx23885-core.c | 6 +-
drivers/media/pci/cx25821/cx25821-core.c | 2 +-
drivers/media/platform/aspeed-video.c | 4 +-
drivers/media/platform/atmel/atmel-sama5d2-isc.c | 7 +-
drivers/media/platform/coda/coda-common.c | 35 +-
drivers/media/platform/exynos4-is/fimc-is.c | 6 +-
drivers/media/platform/exynos4-is/fimc-isp-video.h | 2 +-
drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 13 +-
.../media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 3 +
drivers/media/platform/qcom/venus/helpers.c | 34 +-
drivers/media/platform/qcom/venus/hfi.c | 3 +
drivers/media/platform/rockchip/rga/rga.c | 6 +-
drivers/media/platform/sti/delta/delta-v4l2.c | 6 +-
drivers/media/platform/vsp1/vsp1_rpf.c | 6 +-
drivers/media/rc/imon.c | 99 ++-
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7 +-
drivers/media/usb/uvc/uvc_v4l2.c | 20 +-
drivers/memory/samsung/exynos5422-dmc.c | 5 +-
drivers/mfd/davinci_voicecodec.c | 6 +-
drivers/mfd/ipaq-micro.c | 2 +-
drivers/misc/ocxl/file.c | 2 +
drivers/mmc/core/block.c | 8 +-
drivers/mmc/host/jz4740_mmc.c | 20 +
drivers/mmc/host/sdhci_am654.c | 23 +-
drivers/mtd/chips/cfi_cmdset_0002.c | 103 ++-
drivers/mtd/mtdblock.c | 8 +-
drivers/mtd/nand/raw/cadence-nand-controller.c | 5 +-
drivers/mtd/nand/raw/denali_pci.c | 15 +-
drivers/mtd/nand/raw/intel-nand-controller.c | 2 +-
drivers/mtd/nand/spi/gigadevice.c | 10 +-
drivers/mtd/spi-nor/core.c | 9 +
drivers/net/amt.c | 11 +-
drivers/net/bonding/bond_main.c | 15 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 2 +-
drivers/net/can/xilinx_can.c | 4 +-
drivers/net/dsa/Kconfig | 3 +-
drivers/net/dsa/mt7530.c | 14 +-
drivers/net/ethernet/broadcom/Makefile | 5 +
drivers/net/ethernet/cadence/macb_main.c | 40 +-
drivers/net/ethernet/cadence/macb_ptp.c | 4 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 2 +
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 +
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 9 +
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 10 +-
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10 +-
drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h | 1 +
drivers/net/ethernet/mellanox/mlx5/core/main.c | 23 +-
.../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13 -
.../net/ethernet/mellanox/mlxsw/spectrum_trap.c | 2 +-
drivers/net/ethernet/sfc/ef10.c | 2 +-
.../net/ethernet/stmicro/stmmac/stmmac_selftests.c | 13 +-
drivers/net/ethernet/xscale/ptp_ixp46x.c | 2 +-
drivers/net/hyperv/netvsc_drv.c | 5 +-
drivers/net/ipa/ipa_endpoint.c | 36 +-
drivers/net/phy/micrel.c | 11 +-
drivers/net/usb/asix_devices.c | 6 +-
drivers/net/usb/smsc95xx.c | 3 +-
drivers/net/usb/usbnet.c | 6 +-
drivers/net/wireless/ath/ath10k/mac.c | 20 +-
drivers/net/wireless/ath/ath11k/mac.c | 16 +-
drivers/net/wireless/ath/ath11k/pci.c | 12 +-
drivers/net/wireless/ath/ath11k/spectral.c | 17 +-
drivers/net/wireless/ath/ath11k/wmi.c | 11 +-
drivers/net/wireless/ath/ath11k/wmi.h | 12 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8 +
drivers/net/wireless/ath/carl9170/tx.c | 3 +
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/broadcom/b43legacy/phy.c | 2 +-
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 3 +
drivers/net/wireless/intel/iwlwifi/mei/main.c | 3 +
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3 +
drivers/net/wireless/marvell/mwifiex/11h.c | 2 +
drivers/net/wireless/mediatek/mt76/agg-rx.c | 5 +-
drivers/net/wireless/mediatek/mt76/mac80211.c | 8 +-
drivers/net/wireless/mediatek/mt76/mt76.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt7603/main.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7615/main.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 +-
.../net/wireless/mediatek/mt76/mt7915/debugfs.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4 +-
drivers/net/wireless/mediatek/mt76/mt7915/main.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6 +-
drivers/net/wireless/mediatek/mt76/mt7921/main.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 10 +-
drivers/net/wireless/mediatek/mt76/tx.c | 11 +-
drivers/net/wireless/microchip/wilc1000/mon.c | 4 +-
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8 +-
drivers/net/wireless/realtek/rtlwifi/usb.c | 2 +-
drivers/net/wireless/realtek/rtw88/rtw8821c.c | 4 +
drivers/net/wireless/realtek/rtw88/rx.c | 3 +-
drivers/net/wireless/realtek/rtw89/phy.c | 5 +
drivers/nfc/st21nfca/se.c | 17 +-
drivers/nfc/st21nfca/st21nfca.h | 1 +
drivers/nvdimm/core.c | 9 -
drivers/nvdimm/pmem.c | 30 +-
drivers/nvdimm/security.c | 5 -
drivers/nvme/host/core.c | 21 +-
drivers/nvme/host/pci.c | 1 +
drivers/of/fdt.c | 3 +
drivers/of/kexec.c | 9 +
drivers/of/overlay.c | 4 +-
drivers/opp/of.c | 2 +-
drivers/pci/controller/cadence/pci-j721e.c | 3 +
drivers/pci/controller/cadence/pcie-cadence-ep.c | 21 +-
drivers/pci/controller/cadence/pcie-cadence.h | 3 +
drivers/pci/controller/dwc/pci-imx6.c | 23 +-
drivers/pci/controller/dwc/pcie-designware-host.c | 3 +-
drivers/pci/controller/dwc/pcie-qcom.c | 9 +-
drivers/pci/controller/pcie-mediatek-gen3.c | 8 +
drivers/pci/controller/pcie-mediatek.c | 1 +
drivers/pci/controller/pcie-microchip-host.c | 16 +-
drivers/pci/controller/pcie-rockchip-ep.c | 3 +-
drivers/pci/pci-acpi.c | 41 +-
drivers/pci/pci.c | 12 +-
drivers/pci/pcie/aer.c | 7 +-
drivers/pci/quirks.c | 47 ++
drivers/phy/qualcomm/phy-qcom-qmp.c | 11 +-
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 18 +
drivers/pinctrl/mediatek/Kconfig | 1 +
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2 +-
drivers/pinctrl/pinctrl-apple-gpio.c | 1 +
drivers/pinctrl/pinctrl-rockchip.c | 54 +-
drivers/pinctrl/pinctrl-rockchip.h | 7 +-
drivers/pinctrl/renesas/core.c | 7 +-
drivers/pinctrl/renesas/pfc-r8a779a0.c | 29 +
drivers/pinctrl/renesas/pinctrl-rzn1.c | 10 +-
drivers/platform/chrome/cros_ec.c | 16 +-
drivers/platform/chrome/cros_ec_chardev.c | 2 +-
drivers/platform/chrome/cros_ec_proto.c | 50 +-
drivers/platform/mips/cpu_hwmon.c | 127 ++--
drivers/platform/x86/intel/hid.c | 2 +-
drivers/regulator/core.c | 7 +-
drivers/regulator/da9121-regulator.c | 2 +
drivers/regulator/pfuze100-regulator.c | 2 +
drivers/regulator/qcom_smd-regulator.c | 35 +-
drivers/regulator/scmi-regulator.c | 2 +-
drivers/s390/cio/chsc.c | 4 +-
drivers/scsi/dc395x.c | 15 +-
drivers/scsi/fcoe/fcoe_ctlr.c | 2 +-
drivers/scsi/hisi_sas/hisi_sas_main.c | 47 +-
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 +-
drivers/scsi/lpfc/lpfc_els.c | 49 +-
drivers/scsi/lpfc/lpfc_init.c | 51 +-
drivers/scsi/lpfc/lpfc_logmsg.h | 6 +-
drivers/scsi/lpfc/lpfc_scsi.c | 37 +-
drivers/scsi/lpfc/lpfc_sli.c | 6 +-
drivers/scsi/megaraid.c | 2 +-
drivers/scsi/ufs/ti-j721e-ufs.c | 6 +-
drivers/scsi/ufs/ufs-qcom.c | 14 +-
drivers/scsi/ufs/ufshcd.c | 7 +-
drivers/soc/bcm/bcm63xx/bcm-pmb.c | 3 +
drivers/soc/qcom/llcc-qcom.c | 1 +
drivers/soc/qcom/smp2p.c | 1 +
drivers/soc/qcom/smsm.c | 1 +
drivers/soc/ti/ti_sci_pm_domains.c | 2 +
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-fsl-qspi.c | 4 +
drivers/spi/spi-img-spfi.c | 2 +-
drivers/spi/spi-rockchip.c | 113 +++-
drivers/spi/spi-rspi.c | 15 +-
drivers/spi/spi-stm32-qspi.c | 3 +-
drivers/spi/spi-ti-qspi.c | 5 +-
drivers/staging/media/hantro/hantro_g2_hevc_dec.c | 11 +-
drivers/staging/media/hantro/hantro_h264.c | 2 -
drivers/staging/media/hantro/hantro_v4l2.c | 8 +-
drivers/staging/media/rkvdec/rkvdec-h264.c | 37 +-
drivers/staging/media/rkvdec/rkvdec.c | 6 -
drivers/staging/r8188eu/os_dep/ioctl_linux.c | 98 +--
drivers/target/target_core_device.c | 1 -
drivers/target/target_core_user.c | 50 +-
drivers/thermal/broadcom/bcm2711_thermal.c | 5 +-
drivers/thermal/broadcom/sr-thermal.c | 3 +
drivers/thermal/devfreq_cooling.c | 25 +-
drivers/thermal/imx_sc_thermal.c | 6 +-
drivers/thermal/thermal_core.c | 1 +
drivers/tty/goldfish.c | 20 +-
drivers/tty/n_gsm.c | 31 +-
drivers/tty/serial/pch_uart.c | 27 +-
drivers/tty/tty_buffer.c | 3 +-
drivers/usb/core/hcd.c | 29 +-
drivers/usb/core/quirks.c | 3 +
drivers/usb/dwc3/gadget.c | 6 +-
drivers/usb/host/xhci-pci.c | 2 +
drivers/usb/isp1760/isp1760-core.c | 8 +
drivers/usb/serial/option.c | 2 +
drivers/usb/serial/pl2303.c | 3 +
drivers/vdpa/vdpa_sim/vdpa_sim.c | 5 +-
drivers/video/console/sticon.c | 5 +-
drivers/video/console/sticore.c | 32 +-
drivers/video/fbdev/amba-clcd.c | 5 +-
drivers/video/fbdev/core/fbcon.c | 5 +-
drivers/video/fbdev/sticore.h | 3 +
drivers/video/fbdev/stifb.c | 4 +-
drivers/video/fbdev/vesafb.c | 5 +-
fs/afs/misc.c | 5 +-
fs/afs/rotate.c | 4 +
fs/afs/rxrpc.c | 8 +-
fs/afs/write.c | 1 +
fs/binfmt_flat.c | 27 +-
fs/btrfs/block-group.c | 8 +
fs/btrfs/block-group.h | 2 +
fs/btrfs/disk-io.c | 4 +-
fs/btrfs/extent_io.c | 27 +-
fs/btrfs/extent_io.h | 1 -
fs/btrfs/ioctl.c | 49 +-
fs/btrfs/volumes.c | 8 +-
fs/btrfs/zoned.c | 44 +-
fs/btrfs/zoned.h | 5 +
fs/ceph/mds_client.c | 14 +-
fs/cifs/cifsfs.c | 10 +-
fs/cifs/cifsglob.h | 15 +-
fs/cifs/connect.c | 67 +-
fs/cifs/dfs_cache.c | 6 +-
fs/cifs/fs_context.c | 29 +-
fs/cifs/fs_context.h | 2 +-
fs/cifs/misc.c | 7 +-
fs/cifs/sess.c | 6 +-
fs/cifs/smb2inode.c | 2 -
fs/cifs/smb2ops.c | 9 +-
fs/cifs/smb2pdu.c | 3 +-
fs/cifs/smb2transport.c | 3 +-
fs/dax.c | 3 +-
fs/dlm/lock.c | 15 +-
fs/dlm/lowcomms.c | 2 +-
fs/dlm/plock.c | 12 +-
fs/erofs/decompressor.c | 5 +-
fs/exec.c | 6 +-
fs/exportfs/expfs.c | 5 +-
fs/ext4/ext4.h | 6 -
fs/ext4/extents.c | 20 +-
fs/ext4/inline.c | 12 +
fs/ext4/inode.c | 13 +-
fs/ext4/mballoc.c | 18 +-
fs/ext4/namei.c | 84 ++-
fs/ext4/super.c | 87 ++-
fs/f2fs/dir.c | 3 +-
fs/f2fs/f2fs.h | 29 +-
fs/f2fs/file.c | 20 +-
fs/f2fs/hash.c | 11 +-
fs/f2fs/inline.c | 29 +-
fs/f2fs/inode.c | 19 +-
fs/f2fs/namei.c | 7 +
fs/f2fs/segment.c | 42 +-
fs/f2fs/segment.h | 33 +-
fs/f2fs/super.c | 6 +-
fs/fat/fatent.c | 7 +-
fs/fs-writeback.c | 13 +-
fs/gfs2/quota.c | 32 +-
fs/hugetlbfs/inode.c | 4 +-
fs/io_uring.c | 45 +-
fs/iomap/buffered-io.c | 3 +-
fs/jfs/jfs_dmap.c | 3 +-
fs/ksmbd/connection.c | 2 +-
fs/ksmbd/smb2misc.c | 2 +-
fs/ksmbd/smb_common.c | 4 +-
fs/namei.c | 70 +-
fs/nfs/file.c | 50 +-
fs/nfs/inode.c | 6 +-
fs/nfs/nfs4namespace.c | 9 +-
fs/nfs/nfs4proc.c | 56 +-
fs/nfs/nfs4state.c | 11 +-
fs/nfs/nfs4xdr.c | 4 +-
fs/nfs/pagelist.c | 3 +
fs/nfs/pnfs.c | 6 +-
fs/nfs/unlink.c | 8 +
fs/nfs/write.c | 54 +-
fs/nfsd/nfscache.c | 2 +-
fs/notify/fanotify/fanotify_user.c | 4 +-
fs/notify/fdinfo.c | 11 +-
fs/notify/inotify/inotify.h | 12 +
fs/notify/inotify/inotify_user.c | 2 +-
fs/notify/mark.c | 6 +-
fs/ntfs3/file.c | 12 +-
fs/ntfs3/frecord.c | 10 +-
fs/ntfs3/fslog.c | 12 +-
fs/ntfs3/inode.c | 8 +-
fs/ntfs3/xattr.c | 112 ++-
fs/ocfs2/dlmfs/userdlm.c | 16 +-
fs/ocfs2/inode.c | 4 +-
fs/ocfs2/journal.c | 33 +-
fs/ocfs2/journal.h | 2 +
fs/ocfs2/super.c | 15 +
fs/proc/generic.c | 3 +
fs/proc/proc_net.c | 3 +
fs/seq_file.c | 32 +
include/drm/drm_edid.h | 6 +-
include/linux/blk_types.h | 5 +-
include/linux/bpf.h | 4 +-
include/linux/compat.h | 1 +
include/linux/efi.h | 2 +
include/linux/fwnode.h | 10 +-
include/linux/goldfish.h | 15 +-
include/linux/gpio/driver.h | 12 +
include/linux/ipmi_smi.h | 6 +
include/linux/kexec.h | 46 +-
include/linux/list.h | 16 +-
include/linux/mailbox_controller.h | 1 +
include/linux/module.h | 3 +-
include/linux/mtd/cfi.h | 1 +
include/linux/namei.h | 6 +
include/linux/nfs_fs_sb.h | 1 +
include/linux/nfs_xdr.h | 2 +-
include/linux/nodemask.h | 13 +-
include/linux/platform_data/cros_ec_proto.h | 3 +
include/linux/ptp_classify.h | 3 +
include/linux/ptrace.h | 7 -
include/linux/sched/signal.h | 2 +-
include/linux/sched/task.h | 2 +
include/linux/seq_file.h | 4 +
include/linux/set_memory.h | 10 +-
include/linux/usb/hcd.h | 2 +
include/net/bluetooth/hci.h | 9 +
include/net/bluetooth/hci_core.h | 10 +-
include/net/if_inet6.h | 8 +
include/scsi/libfcoe.h | 3 +-
include/scsi/libiscsi.h | 6 +-
include/sound/cs35l41.h | 1 -
include/sound/jack.h | 1 +
include/trace/events/rxrpc.h | 2 +-
include/trace/events/vmscan.h | 4 +-
include/uapi/asm-generic/siginfo.h | 7 +
include/uapi/linux/landlock.h | 9 +-
init/Kconfig | 5 +
init/main.c | 2 +-
ipc/mqueue.c | 14 +
kernel/dma/debug.c | 2 +-
kernel/dma/direct.c | 31 +-
kernel/events/core.c | 4 +-
kernel/fork.c | 22 +-
kernel/kexec_file.c | 34 -
kernel/module.c | 4 +
kernel/power/energy_model.c | 2 +
kernel/printk/printk.c | 63 +-
kernel/ptrace.c | 5 +-
kernel/rcu/Kconfig | 1 +
kernel/rcu/tasks.h | 5 +-
kernel/scftorture.c | 5 +-
kernel/sched/core.c | 6 +-
kernel/sched/deadline.c | 5 +-
kernel/sched/fair.c | 8 +-
kernel/sched/pelt.h | 4 +-
kernel/sched/psi.c | 15 +-
kernel/sched/rt.c | 5 +-
kernel/sched/sched.h | 32 +-
kernel/signal.c | 18 +-
kernel/trace/ftrace.c | 5 +-
kernel/trace/trace.c | 6 +-
kernel/trace/trace_boot.c | 2 +-
kernel/trace/trace_events_hist.c | 3 +
kernel/trace/trace_osnoise.c | 9 +-
kernel/trace/trace_selftest.c | 3 +
kernel/umh.c | 6 +-
lib/kunit/debugfs.c | 2 +-
lib/kunit/executor.c | 32 +-
lib/kunit/executor_test.c | 4 +-
lib/list-test.c | 19 +
lib/string_helpers.c | 3 +
mm/cma.c | 4 +-
mm/compaction.c | 2 +
mm/hugetlb.c | 9 +-
mm/memremap.c | 2 +-
mm/page_alloc.c | 4 +-
net/bluetooth/hci_conn.c | 39 +-
net/bluetooth/hci_event.c | 46 +-
net/bluetooth/hci_request.c | 2 +
net/bluetooth/hci_sync.c | 11 +-
net/bluetooth/sco.c | 23 +-
net/core/dev.c | 8 +-
net/ipv4/tcp_input.c | 28 +-
net/ipv6/addrconf.c | 33 +-
net/mac80211/chan.c | 7 +-
net/mac80211/ieee80211_i.h | 5 +
net/mac80211/rc80211_minstrel_ht.c | 3 +
net/mac80211/scan.c | 20 +
net/mptcp/pm.c | 19 +-
net/mptcp/pm_netlink.c | 2 +
net/mptcp/protocol.c | 18 +-
net/mptcp/protocol.h | 1 +
net/nfc/core.c | 1 +
net/rxrpc/ar-internal.h | 15 +-
net/rxrpc/call_accept.c | 6 +-
net/rxrpc/call_event.c | 7 +-
net/rxrpc/call_object.c | 18 +-
net/rxrpc/conn_object.c | 2 +-
net/rxrpc/input.c | 58 +-
net/rxrpc/net_ns.c | 2 +-
net/rxrpc/output.c | 20 +-
net/rxrpc/proc.c | 10 +-
net/rxrpc/recvmsg.c | 8 +-
net/rxrpc/sendmsg.c | 6 +
net/rxrpc/sysctl.c | 4 +-
net/sctp/input.c | 4 +-
net/smc/af_smc.c | 2 +-
net/wireless/nl80211.c | 4 +-
net/wireless/reg.c | 4 +
samples/bpf/Makefile | 9 +-
samples/landlock/sandboxer.c | 104 +--
scripts/faddr2line | 150 ++--
security/integrity/ima/Kconfig | 14 +-
.../integrity/platform_certs/keyring_handler.h | 8 +
security/integrity/platform_certs/load_uefi.c | 33 +
security/landlock/cred.c | 4 +-
security/landlock/cred.h | 8 +-
security/landlock/fs.c | 191 ++++--
security/landlock/fs.h | 11 +-
security/landlock/limits.h | 8 +-
security/landlock/object.c | 6 +-
security/landlock/object.h | 6 +-
security/landlock/ptrace.c | 10 +-
security/landlock/ruleset.c | 84 +--
security/landlock/ruleset.h | 35 +-
security/landlock/syscalls.c | 95 +--
sound/core/jack.c | 34 +-
sound/core/pcm_memory.c | 3 +-
sound/pci/hda/patch_realtek.c | 21 +-
sound/soc/amd/yc/acp6x-mach.c | 29 +-
sound/soc/atmel/atmel-classd.c | 1 -
sound/soc/atmel/atmel-pdmic.c | 1 -
sound/soc/codecs/Kconfig | 2 -
sound/soc/codecs/cs35l41-lib.c | 14 +-
sound/soc/codecs/max98090.c | 6 +-
sound/soc/codecs/rk3328_codec.c | 2 +-
sound/soc/codecs/rt5514.c | 2 +-
sound/soc/codecs/rt5645.c | 7 +-
sound/soc/codecs/tscs454.c | 12 +-
sound/soc/codecs/wm2000.c | 6 +-
sound/soc/fsl/imx-hdmi.c | 1 +
sound/soc/fsl/imx-sgtl5000.c | 14 +-
sound/soc/intel/boards/bytcr_rt5640.c | 12 +
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9 +-
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5 +-
sound/soc/mxs/mxs-saif.c | 1 +
sound/soc/samsung/aries_wm8994.c | 2 +-
sound/soc/sh/rcar/core.c | 15 +-
sound/soc/sh/rcar/dma.c | 9 +-
sound/soc/sh/rcar/rsnd.h | 2 +-
sound/soc/sh/rcar/src.c | 7 +-
sound/soc/sh/rcar/ssi.c | 14 +-
sound/soc/sh/rcar/ssiu.c | 11 +-
sound/soc/sh/rz-ssi.c | 22 +-
sound/soc/soc-dapm.c | 2 -
sound/soc/sof/amd/pci-rn.c | 1 +
sound/soc/ti/j721e-evm.c | 44 +-
sound/usb/implicit.c | 10 +-
sound/usb/midi.c | 3 +
sound/usb/quirks.c | 6 +
sound/usb/usbaudio.h | 6 +
.../test-libbpf-btf__load_from_kernel_by_id.c | 5 +-
tools/lib/bpf/libbpf.c | 22 +-
tools/objtool/check.c | 9 +-
tools/objtool/elf.c | 200 ++++--
tools/objtool/include/objtool/elf.h | 4 +-
tools/perf/Makefile.config | 39 +-
tools/perf/arch/x86/util/evlist.c | 2 +-
tools/perf/arch/x86/util/evsel.c | 12 +
tools/perf/builtin-c2c.c | 6 +-
tools/perf/builtin-stat.c | 7 +-
tools/perf/pmu-events/jevents.c | 2 +-
tools/perf/util/data.h | 1 +
tools/perf/util/evlist.c | 12 +-
tools/perf/util/evsel.c | 19 +
tools/perf/util/evsel.h | 3 +
tools/power/x86/turbostat/turbostat.c | 1 +
tools/testing/kunit/kunit_parser.py | 7 +-
.../test_is_test_passed-no_tests_no_plan.log | 2 +-
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/arm64/bti/Makefile | 4 +-
tools/testing/selftests/bpf/Makefile | 12 +-
.../selftests/bpf/prog_tests/trampoline_count.c | 134 ++--
.../bpf/progs/btf_dump_test_case_syntax.c | 2 +-
tools/testing/selftests/bpf/progs/profiler.inc.h | 5 +-
.../selftests/bpf/progs/test_trampoline_count.c | 16 +-
.../selftests/bpf/test_bpftool_synctypes.py | 2 +-
tools/testing/selftests/cgroup/test_stress.sh | 2 +-
tools/testing/selftests/landlock/base_test.c | 177 +++--
tools/testing/selftests/landlock/common.h | 66 +-
tools/testing/selftests/landlock/fs_test.c | 753 ++++++++++++++-------
tools/testing/selftests/landlock/ptrace_test.c | 40 +-
tools/testing/selftests/resctrl/fill_buf.c | 4 +-
tools/tracing/rtla/Makefile | 3 +-
tools/tracing/rtla/README.txt | 12 +-
tools/tracing/rtla/src/utils.c | 2 +-
840 files changed, 8058 insertions(+), 4338 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.15 376/667] net/smc: postpone sk_refcnt increment in connect()
2022-06-07 16:54 1% [PATCH 5.15 000/667] 5.15.46-rc1 review Greg Kroah-Hartman
@ 2022-06-07 17:00 7% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-07 17:00 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, liuyacan, David S. Miller, Sasha Levin
From: liuyacan <liuyacan@corp.netease.com>
[ Upstream commit 75c1edf23b95a9c66923d9269d8e86e4dbde151f ]
Same trigger condition as commit 86434744. When setsockopt runs
in parallel to a connect(), and switch the socket into fallback
mode. Then the sk_refcnt is incremented in smc_connect(), but
its state stay in SMC_INIT (NOT SMC_ACTIVE). This cause the
corresponding sk_refcnt decrement in __smc_release() will not be
performed.
Fixes: 86434744fedf ("net/smc: add fallback check to connect()")
Signed-off-by: liuyacan <liuyacan@corp.netease.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/smc/af_smc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index fb801c249d92..2ddd7b34b4ce 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1283,9 +1283,9 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
if (rc && rc != -EINPROGRESS)
goto out;
- sock_hold(&smc->sk); /* sock put in passive closing */
if (smc->use_fallback)
goto out;
+ sock_hold(&smc->sk); /* sock put in passive closing */
if (flags & O_NONBLOCK) {
if (queue_work(smc_hs_wq, &smc->connect_work))
smc->connect_nonblock = 1;
--
2.35.1
^ permalink raw reply related [relevance 7%]
* [PATCH 5.15 000/667] 5.15.46-rc1 review
@ 2022-06-07 16:54 1% Greg Kroah-Hartman
2022-06-07 17:00 7% ` [PATCH 5.15 376/667] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2022-06-07 16:54 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, torvalds, akpm, linux, shuah,
patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, slade
This is the start of the stable review cycle for the 5.15.46 release.
There are 667 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 09 Jun 2022 16:48:02 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.46-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.15.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.15.46-rc1
Jia-Ju Bai <baijiaju1990@gmail.com>
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Xiao Ni <xni@redhat.com>
md: fix double free of io_acct_set bioset
Xiao Ni <xni@redhat.com>
md: Don't set mddev private to NULL in raid0 pers->free
Namjae Jeon <linkinjeon@kernel.org>
fs/ntfs3: Fix invalid free in log_replay
Christian Brauner <brauner@kernel.org>
exportfs: support idmapped mounts
Christian Brauner <brauner@kernel.org>
fs: add two trivial lookup helpers
Mike Tipton <mdtipton@codeaurora.org>
interconnect: qcom: icc-rpmh: Add BCMs to commit list in pre_aggregate
Stephen Boyd <swboyd@chromium.org>
interconnect: qcom: sc7180: Drop IP0 interconnects
Eric Biggers <ebiggers@google.com>
ext4: only allow test_dummy_encryption when supported
Maciej W. Rozycki <macro@orcam.me.uk>
MIPS: IP30: Remove incorrect `cpu_has_fpu' override
Maciej W. Rozycki <macro@orcam.me.uk>
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
Xiao Yang <yangx.jy@fujitsu.com>
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Yixing Liu <liuyixing1@huawei.com>
RDMA/hns: Remove the num_cqc_timer variable
Dan Carpenter <dan.carpenter@oracle.com>
staging: r8188eu: delete rtw_wx_read/write32()
Jason A. Donenfeld <Jason@zx2c4.com>
Revert "random: use static branch for crng_ready()"
David Gow <davidgow@google.com>
list: test: Add a test for list_is_head()
Waiman Long <longman@redhat.com>
kseltest/cgroup: Make test_stress.sh work if run interactively
Alex Elder <elder@linaro.org>
net: ipa: fix page free in ipa_endpoint_replenish_one()
Alex Elder <elder@linaro.org>
net: ipa: fix page free in ipa_endpoint_trans_release()
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix reset-controller leak on probe errors
Mao Jinlong <quic_jinlmao@quicinc.com>
coresight: core: Fix coresight device probe failure issue
Tejun Heo <tj@kernel.org>
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Eugenio Pérez <eperezma@redhat.com>
vdpasim: allow to enable a vq repeatedly
Dinh Nguyen <dinguyen@kernel.org>
dt-bindings: gpio: altera: correct interrupt-cells
Akira Yokosawa <akiyks@gmail.com>
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Steve French <stfrench@microsoft.com>
SMB3: EBADF/EIO errors in rename/open caused by race condition in smb2_compound_op
Arnd Bergmann <arnd@arndb.de>
ARM: pxa: maybe fix gpio lookup tables
Jonathan Bakker <xc-racer2@live.ca>
ARM: dts: s5pv210: Remove spi-cs-high on panel in Aries
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix struct clk leak on probe errors
Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
clk: tegra: Add missing reset deassertion
Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt>
arm64: tegra: Add missing DFLL reset on Tegra210
Kathiravan T <quic_kathirav@quicinc.com>
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Xiaomeng Tong <xiam0nd.tong@gmail.com>
gma500: fix an incorrect NULL check on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
Jiri Slaby <jirislaby@kernel.org>
serial: pch: don't overwrite xmit->buf[0] by x_char
Coly Li <colyli@suse.de>
bcache: avoid journal no-space deadlock by reserving 1 journal bucket
Coly Li <colyli@suse.de>
bcache: remove incremental dirty sector counting for bch_sectors_dirty_init()
Coly Li <colyli@suse.de>
bcache: improve multithreaded bch_sectors_dirty_init()
Coly Li <colyli@suse.de>
bcache: improve multithreaded bch_btree_check()
Xiaomeng Tong <xiam0nd.tong@gmail.com>
stm: ltdc: fix two incorrect NULL checks on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
carl9170: tx: fix an incorrect use of list iterator
Mark Brown <broonie@kernel.org>
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Alexander Wetzel <alexander@wetzel-home.de>
rtl818x: Prevent using not initialized queues
Yi Yang <yiyang13@huawei.com>
xtensa/simdisk: fix proc_read_simdisk()
Miaohe Lin <linmiaohe@huawei.com>
mm/memremap: fix missing call to untrack_pfn() in pagemap_range()
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix huge_pmd_unshare address update
Christophe de Dinechin <dinechin@redhat.com>
nodemask.h: fix compilation error with GCC12
Mel Gorman <mgorman@techsingularity.net>
mm/page_alloc: always attempt to allocate at least one page during bulk allocation
Dong Aisheng <aisheng.dong@nxp.com>
Revert "mm/cma.c: remove redundant cma_mutex lock"
Yunfei Wang <yf.wang@mediatek.com>
iommu/dma: Fix iova map result check bug
Xiaomeng Tong <xiam0nd.tong@gmail.com>
iommu/msm: Fix an incorrect NULL check on list iterator
Hyunchul Lee <hyc.lee@gmail.com>
ksmbd: fix outstanding credits related bugs
Song Liu <song@kernel.org>
ftrace: Clean up hash direct_functions on register failures
Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
Vincent Whitchurch <vincent.whitchurch@axis.com>
um: Fix out-of-bounds read in LDT setup
Johannes Berg <johannes.berg@intel.com>
um: chan_user: Fix winch_tramp() return value
Johannes Berg <johannes.berg@intel.com>
um: Use asm-generic/dma-mapping.h
Felix Fietkau <nbd@nbd.name>
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Dimitri John Ledkov <dimitri.ledkov@canonical.com>
cfg80211: declare MODULE_FIRMWARE for regulatory.db
Kant Fan <kant@allwinnertech.com>
thermal: devfreq_cooling: use local ops instead of global ops
Max Filippov <jcmvbkbc@gmail.com>
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Pali Rohár <pali@kernel.org>
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Guo Ren <guoren@linux.alibaba.com>
csky: patch_text: Fixup last cpu should be master
Bean Huo <beanhuo@micron.com>
mmc: core: Allows to override the timeout value for ioctl() path
Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
RDMA/hfi1: Fix potential integer multiplication overflow errors
Sean Christopherson <seanjc@google.com>
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
GUO Zihua <guozihua@huawei.com>
ima: remove the IMA_TEMPLATE Kconfig option
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Add more H264 levels for CODA960
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Fix reported H264 profile
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in md_reload_sb
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in does_sb_need_changing
Jani Nikula <jani.nikula@intel.com>
drm/i915/dsi: fix VBT send packet port selection for ICL+
Brian Norris <briannorris@chromium.org>
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Xiaomeng Tong <xiam0nd.tong@gmail.com>
drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
Lucas Stach <l.stach@pengutronix.de>
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Lyude Paul <lyude@redhat.com>
drm/nouveau/subdev/bus: Ratelimit logging for fault errors
Dave Airlie <airlied@redhat.com>
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
Mickaël Salaün <mic@digikod.net>
landlock: Fix same-layer rule unions
Mickaël Salaün <mic@digikod.net>
landlock: Create find_rule() from unmask_layers()
Mickaël Salaün <mic@digikod.net>
landlock: Reduce the maximum number of layers to 16
Mickaël Salaün <mic@digikod.net>
landlock: Define access_mask_t to enforce a consistent access mask size
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Test landlock_create_ruleset(2) argument check ordering
Mickaël Salaün <mic@digikod.net>
landlock: Change landlock_restrict_self(2) check ordering
Mickaël Salaün <mic@digikod.net>
landlock: Change landlock_add_rule(2) argument check ordering
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Add tests for O_PATH
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Fully test file rename with "remove" access
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Extend access right tests to directories
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Add tests for unknown access rights
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Extend tests for minimal valid attribute size
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Make tests build with old libc
Mickaël Salaün <mic@digikod.net>
landlock: Fix landlock_add_rule(2) documentation
Mickaël Salaün <mic@digikod.net>
samples/landlock: Format with clang-format
Mickaël Salaün <mic@digikod.net>
samples/landlock: Add clang-format exceptions
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Format with clang-format
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Normalize array assignment
Mickaël Salaün <mic@digikod.net>
selftests/landlock: Add clang-format exceptions
Mickaël Salaün <mic@digikod.net>
landlock: Format with clang-format
Mickaël Salaün <mic@digikod.net>
landlock: Add clang-format exceptions
Manivannan Sadhasivam <mani@kernel.org>
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Xiaomeng Tong <xiam0nd.tong@gmail.com>
scsi: dc395x: Fix a missing check on list iterator
Junxiao Bi via Ocfs2-devel <ocfs2-devel@oss.oracle.com>
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Alexander Aring <aahringo@redhat.com>
dlm: fix missing lkb refcount handling
Dan Carpenter <dan.carpenter@oracle.com>
dlm: uninitialized variable on error in dlm_listen_for_all()
Alexander Aring <aahringo@redhat.com>
dlm: fix plock invalid read
Sven Schnelle <svens@linux.ibm.com>
s390/stp: clock_delta should be signed
Nico Boehr <nrb@linux.ibm.com>
s390/perf: obtain sie_block from the right address
Rei Yamamoto <yamamoto.rei@jp.fujitsu.com>
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Denis Efremov <denis.e.efremov@oracle.com>
staging: r8188eu: prevent ->Ssid overflow in rtw_wx_set_scan()
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix unbalanced PHY init on probe errors
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix runtime PM imbalance on probe errors
Bjorn Helgaas <bhelgaas@google.com>
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: add beige goby PCI ID
Gautam Menghani <gautammenghani201@gmail.com>
tracing: Initialize integer variable to prevent garbage return value
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
tracing: Fix potential double free in create_var_ref()
Laurent Vivier <laurent@vivier.eu>
tty: goldfish: Introduce gf_ioread32()/gf_iowrite32()
Sakari Ailus <sakari.ailus@linux.intel.com>
ACPI: property: Release subnode properties with data nodes
Jan Kara <jack@suse.cz>
ext4: avoid cycles in directory h-tree
Jan Kara <jack@suse.cz>
ext4: verify dir block before splitting it
Baokun Li <libaokun1@huawei.com>
ext4: fix bug_on in __es_tree_search
Theodore Ts'o <tytso@mit.edu>
ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state
Ye Bin <yebin10@huawei.com>
ext4: fix bug_on in ext4_writepages
Ye Bin <yebin10@huawei.com>
ext4: fix warning in ext4_handle_inode_extension
Baokun Li <libaokun1@huawei.com>
ext4: fix race condition between ext4_write and ext4_convert_inline_data
Ye Bin <yebin10@huawei.com>
ext4: fix use-after-free in ext4_rename_dir_prepare
Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
ext4: mark group as trimmed only if it was fully scanned
Jan Kara <jack@suse.cz>
bfq: Make sure bfqg for which we are queueing requests is online
Jan Kara <jack@suse.cz>
bfq: Get rid of __bio_blkcg() usage
Jan Kara <jack@suse.cz>
bfq: Track whether bfq_group is still online
Jan Kara <jack@suse.cz>
bfq: Remove pointless bfq_init_rq() calls
Jan Kara <jack@suse.cz>
bfq: Drop pointless unlock-lock pair
Jan Kara <jack@suse.cz>
bfq: Update cgroup information before merging bio
Jan Kara <jack@suse.cz>
bfq: Split shared queues on move between cgroups
Jan Kara <jack@suse.cz>
bfq: Avoid merging queues with different parents
Jan Kara <jack@suse.cz>
bfq: Avoid false marking of bic as stably merged
Aditya Garg <gargaditya08@live.com>
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Zhihao Cheng <chengzhihao1@huawei.com>
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
Emmanuel Grumbach <emmanuel.grumbach@intel.com>
iwlwifi: mvm: fix assert 1F04 upon reconfig
Johannes Berg <johannes.berg@intel.com>
wifi: mac80211: fix use-after-free in chanctx code
Peter Zijlstra <peterz@infradead.org>
objtool: Fix symbol creation
Mikulas Patocka <mpatocka@redhat.com>
objtool: Fix objtool regression on x32 systems
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check for inline inode
Chao Yu <chao@kernel.org>
f2fs: fix fallocate to use file_modified to update permissions consistently
Eric Biggers <ebiggers@google.com>
f2fs: don't use casefolded comparison for "." and ".."
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on total_data_blocks
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: don't need inode lock for system hidden quota
Chao Yu <chao@kernel.org>
f2fs: fix deadloop in foreground GC
Chao Yu <chao@kernel.org>
f2fs: fix to clear dirty inode in f2fs_evict_inode()
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
Chao Yu <chao@kernel.org>
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
Olga Kornievskaia <kolga@netapp.com>
NFSv4.1 mark qualified async operations as MOVEABLE tasks
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Convert GFP_NOFS to GFP_KERNEL
Anna Schumaker <Anna.Schumaker@Netapp.com>
NFS: Create a new nfs_alloc_fattr_with_label() function
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Always initialise fattr->label in nfs_fattr_alloc()
Javier Martinez Canillas <javierm@redhat.com>
video: fbdev: vesafb: Fix a use-after-free due early fb_info cleanup
Zhengjun Xing <zhengjun.xing@linux.intel.com>
perf jevents: Fix event syntax error caused by ExtSel
Leo Yan <leo.yan@linaro.org>
perf c2c: Use stdio interface if slang is not supported
Jiri Olsa <jolsa@kernel.org>
perf build: Fix btf__load_from_kernel_by_id() feature check
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
i2c: rcar: fix PM ref counts in probe error paths
Tali Perry <tali.perry1@gmail.com>
i2c: npcm: Handle spurious interrupts
Tyrone Ting <kfting@nuvoton.com>
i2c: npcm: Correct register access width
Tali Perry <tali.perry1@gmail.com>
i2c: npcm: Fix timeout calculation
Joerg Roedel <jroedel@suse.de>
iommu/amd: Increase timeout waiting for GA log enablement
Amelie Delaunay <amelie.delaunay@foss.st.com>
dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler()
Amelie Delaunay <amelie.delaunay@foss.st.com>
dmaengine: stm32-mdma: remove GISR1 register
Miaoqian Lin <linmq006@gmail.com>
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Further fixes to the writeback error handling
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Don't report errors from nfs_pageio_complete() more than once
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report flush errors in nfs_write_end()
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Don't report ENOSPC write errors twice
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: fsync() should report filesystem errors over EINTR/ERESTARTSYS
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: idxd: Fix the error handling path in idxd_cdev_register()
Nathan Chancellor <nathan@kernel.org>
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Miles Chen <miles.chen@mediatek.com>
iommu/mediatek: Fix NULL pointer dereference when printing dev_name
Guenter Roeck <linux@roeck-us.net>
MIPS: Loongson: Use hwmon_device_register_with_groups() to register hwmon
Jean-Philippe Brucker <jean-philippe@linaro.org>
iommu/arm-smmu-v3-sva: Fix mm use-after-free
Rex-BC Chen <rex-bc.chen@mediatek.com>
cpufreq: mediatek: Unregister platform device on exit
Jia-Wei Chang <jia-wei.chang@mediatek.com>
cpufreq: mediatek: Use module_init and add module_exit
Michael Walle <michael@walle.cc>
i2c: at91: use dma safe buffers
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Remove clk_disable in mtk_iommu_remove
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Add list_del in mtk_iommu_remove
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Fix 2 HW sharing pgtable issue
Mario Limonciello <mario.limonciello@amd.com>
iommu/amd: Enable swiotlb in all cases
Jakob Koschel <jakobkoschel@gmail.com>
f2fs: fix dereference of stale list iterator after loop body
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on inline_dots inode
Chao Yu <chao@kernel.org>
f2fs: support fault injection for dquot_initialize()
Dan Carpenter <dan.carpenter@oracle.com>
OPP: call of_node_put() on error path in _bandwidth_supported()
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: stmfts - do not leave device disabled in stmfts_input_open
Wanpeng Li <wanpengli@tencent.com>
KVM: LAPIC: Drop pending LAPIC timer injection when canceling the timer
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent use of lock before it is initialized
Björn Ardö <bjorn.ardo@axis.com>
mailbox: forward the hrtimer if not queued and under a lock
Julian Schroeder <jumaco@amazon.com>
nfsd: destroy percpu stats counters after reply cache shutdown
Yang Yingliang <yangyingliang@huawei.com>
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
Miaoqian Lin <linmq006@gmail.com>
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
Miaoqian Lin <linmq006@gmail.com>
powerpc/xive: Fix refcount leak in xive_spapr_init
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
powerpc/xive: Add some error handling code to 'xive_spapr_init()'
Randy Dunlap <rdunlap@infradead.org>
macintosh: via-pmu and via-cuda need RTC_LIB
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf: Fix the threshold compare group constraint for power9
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf: Fix the threshold compare group constraint for power10
Michael Ellerman <mpe@ellerman.id.au>
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
Yang Yingliang <yangyingliang@huawei.com>
hwrng: omap3-rom - fix using wrong clk_disable() in omap_rom_rng_runtime_resume()
Daire McNamara <daire.mcnamara@microchip.com>
PCI: microchip: Fix potential race in interrupt handling
Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
PCI/AER: Clear MULTI_ERR_COR/UNCOR_RCV bits
Miaoqian Lin <linmq006@gmail.com>
Input: sparcspkr - fix refcount leak in bbc_beep_probe
Mina Almasry <almasrymina@google.com>
hugetlbfs: fix hugetlbfs_statfs() locking
Eugen Hristev <eugen.hristev@microchip.com>
ARM: dts: at91: sama7g5: remove interrupt-parent from gic node
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
crypto: cryptd - Protect per-CPU resource by disabling BH.
Corentin Labbe <clabbe@baylibre.com>
crypto: sun8i-ss - handle zero sized sg
Corentin Labbe <clabbe@baylibre.com>
crypto: sun8i-ss - rework handling of IV
Qi Zheng <zhengqi.arch@bytedance.com>
tty: fix deadlock caused by calling printk() under tty_port->lock
Francesco Dolcini <francesco.dolcini@toradex.com>
PCI: imx6: Fix PERST# start-up sequence
Waiman Long <longman@redhat.com>
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
Alexey Dobriyan <adobriyan@gmail.com>
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: atmel-classd: Remove endianness flag on class d component
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: atmel-pdmic: Remove endianness flag on pdmic component
Robert Marko <robert.marko@sartura.hr>
arm64: dts: marvell: espressobin-ultra: enable front USB3 port
Robert Marko <robert.marko@sartura.hr>
arm64: dts: marvell: espressobin-ultra: fix SPI-NOR config
Yangyang Li <liyangyang20@huawei.com>
RDMA/hns: Add the detection for CMDQ status in the device initialization process
Randy Dunlap <rdunlap@infradead.org>
powerpc/4xx/cpm: Fix return value of __setup() handler
Randy Dunlap <rdunlap@infradead.org>
powerpc/idle: Fix return value of __setup() handler
Yang Yingliang <yangyingliang@huawei.com>
pinctrl: renesas: core: Fix possible null-ptr-deref in sh_pfc_map_resources()
Geert Uytterhoeven <geert+renesas@glider.be>
pinctrl: renesas: r8a779a0: Fix GPIO function on I2C-capable pins
Randy Dunlap <rdunlap@infradead.org>
powerpc/8xx: export 'cpm_setbrg' for modules
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/dpu: fix error check return value of irq_of_parse_and_map()
Kuniyuki Iwashima <kuniyu@amazon.co.jp>
list: fix a data-race around ep->rdllist
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
list: introduce list_is_head() helper and re-use it in list.h
Sudeep Holla <sudeep.holla@arm.com>
firmware: arm_ffa: Remove incorrect assignment of driver_data
Sudeep Holla <sudeep.holla@arm.com>
firmware: arm_ffa: Fix uuid parameter to ffa_partition_probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
drivers/base/memory: fix an unlikely reference counting issue in __add_memory_block()
Muchun Song <songmuchun@bytedance.com>
dax: fix cache flush on PMD-mapped pages
Miaohe Lin <linmiaohe@huawei.com>
drivers/base/node.c: fix compaction sysfs file leak
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
Dan Williams <dan.j.williams@intel.com>
nvdimm: Allow overwrite in the presence of disabled dimms
Dan Williams <dan.j.williams@intel.com>
nvdimm: Fix firmware activation deadlock scenarios
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
ASoC: sh: rz-ssi: Release the DMA channels in rz_ssi_probe() error path
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
ASoC: sh: rz-ssi: Propagate error codes returned from platform_get_irq_byname()
Heiner Kallweit <hkallweit1@gmail.com>
ASoC: sh: rz-ssi: Check return value of pm_runtime_resume_and_get()
Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
arm64: dts: ti: k3-am64-mcu: remove incorrect UART base clock rates
QintaoShen <unSimple1993@163.com>
soc: bcm: Check for NULL return of devm_kzalloc()
Gustavo A. R. Silva <gustavoars@kernel.org>
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
Lv Ruyi <lv.ruyi@zte.com.cn>
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: fix PT_LOAD segment for boot memory area
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Fix handling of messages with transaction ID of zero
Vinod Koul <vkoul@kernel.org>
arm64: dts: qcom: qrb5165-rb5: Fix can-clock node name
Fabien Parent <fparent@baylibre.com>
pinctrl: mediatek: mt8195: enable driver on mtk platforms
Caleb Connolly <kc@postmarketos.org>
pinctrl/rockchip: support deferring other gpio params
Chuanhong Guo <gch981213@gmail.com>
arm: mediatek: select arch timer for mt7629
Stefan Wahren <stefan.wahren@i2se.com>
pinctrl: bcm2835: implement hook for missing gpio-ranges
Stefan Wahren <stefan.wahren@i2se.com>
gpiolib: of: Introduce hook for missing gpio-ranges
Corentin Labbe <clabbe@baylibre.com>
crypto: marvell/cesa - ECB does not IV
Hangyu Hua <hbh25y@gmail.com>
misc: ocxl: fix possible double free in ocxl_file_register_afu
Stefan Wahren <stefan.wahren@i2se.com>
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Fix PHY post-reset delay on Avenger96
Marc Kleine-Budde <mkl@pengutronix.de>
can: xilinx_can: mark bit timing constants as const
Guenter Roeck <linux@roeck-us.net>
platform/chrome: Re-introduce cros_ec_cmd_xfer and use it for ioctls
Max Krummenacher <max.krummenacher@toradex.com>
ARM: dts: imx6dl-colibri: Fix I2C pinmuxing
Tzung-Bi Shih <tzungbi@kernel.org>
platform/chrome: cros_ec: fix error handling in cros_ec_register()
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - set COMPRESSION capability for DH895XCC
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - set CIPHER capability for DH895XCC
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - set COMPRESSION capability for QAT GEN2
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - set CIPHER capability for QAT GEN2
Sean Christopherson <seanjc@google.com>
KVM: nVMX: Clear IDT vectoring on nested VM-Exit for double/triple fault
Sean Christopherson <seanjc@google.com>
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
Bjorn Andersson <bjorn.andersson@linaro.org>
soc: qcom: llcc: Add MODULE_DEVICE_TABLE()
Thorsten Scherer <t.scherer@eckelmann.de>
ARM: dts: ci4x10: Adapt to changes in imx6qdl.dtsi regarding fec clocks
Jiantao Zhang <water.zhangjiantao@huawei.com>
PCI: dwc: Fix setting error return on MSI DMA mapping failure
Miaoqian Lin <linmq006@gmail.com>
PCI: mediatek: Fix refcount leak in mtk_pcie_subsys_powerup()
Dan Carpenter <dan.carpenter@oracle.com>
PCI: rockchip: Fix find_first_zero_bit() limit
Dan Carpenter <dan.carpenter@oracle.com>
PCI: cadence: Fix find_first_zero_bit() limit
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
Andre Przywara <andre.przywara@arm.com>
ARM: dts: suniv: F1C100: fix watchdog compatible
Rafał Miłecki <rafal@milecki.pl>
ARM: dts: BCM5301X: Update pin controller node name
Rafał Miłecki <rafal@milecki.pl>
ARM: dts: BCM5301X: update CRU block description
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
memory: samsung: exynos5422-dmc: Avoid some over memory allocation
Mario Limonciello <mario.limonciello@amd.com>
PCI/ACPI: Allow D3 only if Root Port can signal and wake from D3
Allen-KH Cheng <allen-kh.cheng@mediatek.com>
arm64: dts: mt8192: Fix nor_flash status disable typo
Shawn Lin <shawn.lin@rock-chips.com>
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
Robin Murphy <robin.murphy@arm.com>
dma-direct: don't over-decrypt memory
Christoph Hellwig <hch@lst.de>
dma-direct: always leak memory that can't be re-encrypted
Christoph Hellwig <hch@lst.de>
dma-direct: don't call dma_set_decrypted for remapped allocations
Christoph Hellwig <hch@lst.de>
dma-direct: factor out dma_set_{de,en}crypted helpers
liuyacan <liuyacan@corp.netease.com>
net/smc: postpone sk_refcnt increment in connect()
Randy Dunlap <rdunlap@infradead.org>
net: dsa: restrict SMSC_LAN9303_I2C kconfig
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hinic: Avoid some over memory allocation
Gustavo A. R. Silva <gustavoars@kernel.org>
net: huawei: hinic: Use devm_kcalloc() instead of devm_kzalloc()
David Howells <dhowells@redhat.com>
rxrpc: Fix decision on when to generate an IDLE ACK
David Howells <dhowells@redhat.com>
rxrpc: Don't let ack.previousPacket regress
David Howells <dhowells@redhat.com>
rxrpc: Fix overlapping ACK accounting
David Howells <dhowells@redhat.com>
rxrpc: Don't try to resend the request if we're receiving the reply
David Howells <dhowells@redhat.com>
rxrpc: Fix listen() setting the bar too high for the prealloc rings
Adam Wujek <dev_public@wujek.eu>
hwmon: (pmbus) Check PEC support before reading other registers
Yongzhi Liu <lyz_cs@pku.edu.cn>
hv_netvsc: Fix potential dereference of NULL pointer
Jakub Kicinski <kuba@kernel.org>
net: stmmac: fix out-of-bounds access in a selftest
Gustavo A. R. Silva <gustavoars@kernel.org>
net: stmmac: selftests: Use kcalloc() instead of kzalloc()
Alexey Khoroshilov <khoroshilov@ispras.ru>
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
Duoming Zhou <duoming@zju.edu.cn>
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
Harini Katakam <harini.katakam@xilinx.com>
net: macb: Fix PTP one step sync support
Ulf Hansson <ulf.hansson@linaro.org>
PM: domains: Fix initialization of genpd's next_wakeup
Yang Yingliang <yangyingliang@huawei.com>
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
Jan Kara <jack@suse.cz>
bfq: Allow current waker to defend against a tentative one
Jan Kara <jack@suse.cz>
bfq: Relax waker detection for shared queues
Miaoqian Lin <linmq006@gmail.com>
thermal/drivers/imx_sc_thermal: Fix refcount leak in imx_sc_thermal_probe
Yang Yingliang <yangyingliang@huawei.com>
thermal/core: Fix memory leak in __thermal_cooling_device_register()
Zheng Yongjun <zhengyongjun3@huawei.com>
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
Stefan Wahren <stefan.wahren@i2se.com>
thermal/drivers/bcm2711: Don't clamp temperature at zero
Nathan Chancellor <nathan@kernel.org>
drm/i915: Fix CFI violation with show_dynamic_id()
Abhinav Kumar <quic_abhinavk@quicinc.com>
drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path
Hangbin Liu <liuhangbin@gmail.com>
selftests/bpf: Add missed ima_setup.sh in Makefile
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: don't free the IRQ if it was not requested
Lai Jiangshan <jiangshan.ljs@antgroup.com>
x86/sev: Annotate stack change in the #VC handler
Hangyu Hua <hbh25y@gmail.com>
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
Miaoqian Lin <linmq006@gmail.com>
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
Eric Biggers <ebiggers@google.com>
ext4: reject the 'commit' option on ext2 filesystems
Miaoqian Lin <linmq006@gmail.com>
regulator: scmi: Fix refcount leak in scmi_regulator_probe
Jonas Karlman <jonas@kwiboo.se>
media: rkvdec: h264: Fix bit depth wrap in pps packet
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: rkvdec: h264: Fix dpb_valid implementation
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: rkvdec: Stop overclocking the decoder
Cai Huoqing <caihuoqing@baidu.com>
media: staging: media: rkvdec: Make use of the helper function devm_platform_ioremap_resource()
Yang Yingliang <yangyingliang@huawei.com>
media: i2c: ov5648: fix wrong pointer passed to IS_ERR() and PTR_ERR()
Dongliang Mu <mudongliangabcd@gmail.com>
media: ov7670: remove ov7670_power_off from ov7670_remove
Andre Przywara <andre.przywara@arm.com>
kselftest/arm64: bti: force static linking
Miaoqian Lin <linmq006@gmail.com>
ASoC: ti: j721e-evm: Fix refcount leak in j721e_soc_probe_*
Zheng Bin <zhengbin13@huawei.com>
net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init
Eric Dumazet <edumazet@google.com>
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
Geert Uytterhoeven <geert@linux-m68k.org>
m68k: math-emu: Fix dependencies of math emulation support
Keith Busch <kbusch@kernel.org>
nvme: set dma alignment to dword
Niels Dossche <dossche.niels@gmail.com>
Bluetooth: use hdev lock for accept_list and reject_list in conn req
Niels Dossche <dossche.niels@gmail.com>
Bluetooth: use hdev lock in activate_scan for hci_is_adv_monitoring
Ying Hsu <yinghsu@chromium.org>
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Benjamin Gaignard <benjamin.gaignard@collabora.com>
media: hantro: HEVC: Fix tile info buffer value computation
Eugen Hristev <eugen.hristev@microchip.com>
media: atmel: atmel-sama5d2-isc: fix wrong mask in YUYV format check
Michael Rodin <mrodin@de.adit-jv.com>
media: vsp1: Fix offset calculation for plane cropping
Pavel Skripkin <paskripkin@gmail.com>
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Miaoqian Lin <linmq006@gmail.com>
media: exynos4-is: Change clk_disable to clk_disable_unprepare
Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
media: i2c: rdacm2x: properly set subdev entity function
Miaoqian Lin <linmq006@gmail.com>
media: atmel: atmel-isc: Fix PM disable depth imbalance in atmel_isc_probe
Miaoqian Lin <linmq006@gmail.com>
media: st-delta: Fix PM disable depth imbalance in delta_probe
Felix Fietkau <nbd@nbd.name>
mt76: do not attempt to reorder received 802.3 packets without agg session
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mt76: mt7921: Fix the error handling path of mt7921_pci_probe()
Miaoqian Lin <linmq006@gmail.com>
media: exynos4-is: Fix PM disable depth imbalance in fimc_is_probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: aspeed: Fix an error handling path in aspeed_video_probe()
Josh Poimboeuf <jpoimboe@kernel.org>
scripts/faddr2line: Fix overlapping text section failures
Phil Auld <pauld@redhat.com>
kselftest/cgroup: fix test_stress.sh to use OUTPUT dir
Bart Van Assche <bvanassche@acm.org>
block: Fix the bio.bi_opf comment
Miaoqian Lin <linmq006@gmail.com>
ASoC: samsung: Fix refcount leak in aries_audio_probe
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: samsung: Use dev_err_probe() helper
Christoph Hellwig <hch@lst.de>
dma-direct: don't fail on highmem CMA pages in dma_direct_alloc_pages
Christoph Hellwig <hch@lst.de>
dma-direct: factor out a helper for DMA_ATTR_NO_KERNEL_MAPPING allocations
Miaoqian Lin <linmq006@gmail.com>
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
Miaoqian Lin <linmq006@gmail.com>
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: imx-hdmi: Fix refcount leak in imx_hdmi_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: fsl: Use dev_err_probe() helper
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Modify the hid name
Basavaraj Natikar <Basavaraj.Natikar@amd.com>
HID: amd_sfh: Modify the bus name
Ajay Singh <ajay.kathat@microchip.com>
wilc1000: fix crash observed in AP mode with cfg80211_register_netdevice()
Baochen Qiang <quic_bqiang@quicinc.com>
ath11k: Don't check arvif->is_started before sending management frames
Ravi Bangoria <ravi.bangoria@amd.com>
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Jerome Marchand <jmarchan@redhat.com>
samples: bpf: Don't fail for a missing VMLINUX_BTF when VMLINUX_H is provided
Konrad Dybcio <konrad.dybcio@somainline.org>
regulator: qcom_smd: Fix up PM8950 regulator configuration
Viresh Kumar <viresh.kumar@linaro.org>
Revert "cpufreq: Fix possible race in cpufreq online error path"
Yang Yingliang <yangyingliang@huawei.com>
spi: spi-fsl-qspi: check return value after calling platform_get_resource_byname()
Andreas Gruenbacher <agruenba@redhat.com>
iomap: iomap_write_failed fix
Mark Rutland <mark.rutland@arm.com>
arm64: stackleak: fix current_top_of_stack()
Xiaomeng Tong <xiam0nd.tong@gmail.com>
media: uvcvideo: Fix missing check to determine if element is found in list
Dan Carpenter <dan.carpenter@oracle.com>
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: fix event thread stuck in wait_event after kthread_stop()
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix address for second DSI PHY on SDM660
Zev Weiss <zev@bewilderbeest.net>
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Tong Tiangen <tongtiangen@huawei.com>
arm64: fix types in copy_highpage()
Randy Dunlap <rdunlap@infradead.org>
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
irqchip/aspeed-scu-ic: Fix irq_of_parse_and_map() return value
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
Daniel Thompson <daniel.thompson@linaro.org>
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Randy Dunlap <rdunlap@infradead.org>
x86: Fix return value of __setup handlers
Johannes Berg <johannes.berg@intel.com>
nl80211: don't hold RTNL in color change request
Christoph Hellwig <hch@lst.de>
virtio_blk: fix the discard_granularity and discard_alignment queue limits
James Clark <james.clark@arm.com>
perf tools: Use Python devtools for version autodetection rather than runtime
Ian Abbott <abbotti@mev.co.uk>
spi: cadence-quadspi: fix Direct Access Mode disable for SoCFPGA
Yang Yingliang <yangyingliang@huawei.com>
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
Daniel Latypov <dlatypov@google.com>
kunit: fix debugfs code to use enum kunit_status, not bool
Jagan Teki <jagan@amarulasolutions.com>
drm/panel: panel-simple: Fix proper bpc for AM-1280800N3TZQW-T00H
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: add missing include to msm_drv.c
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
Yang Yingliang <yangyingliang@huawei.com>
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix error checks and return values for DSI xmit functions
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: do not stop transmitting phy test pattern during DP phy compliance test
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: reset DP controller before transmit phy test pattern
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/dp: fix error check return value of irq_of_parse_and_map()
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: stop event kernel thread when DP unbind
Vinod Polimera <quic_vpolimer@quicinc.com>
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
Yang Jihong <yangjihong1@huawei.com>
perf tools: Add missing headers needed by util/data.h
Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
ASoC: rk3328: fix disabling mclk on pclk probe failure
Josh Poimboeuf <jpoimboe@redhat.com>
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
Yang Yingliang <yangyingliang@huawei.com>
mtd: rawnand: intel: fix possible null-ptr-deref in ebu_nand_probe()
Yang Yingliang <yangyingliang@huawei.com>
mtd: rawnand: cadence: fix possible null-ptr-deref in cadence_nand_dt_probe()
Matthieu Baerts <matthieu.baerts@tessares.net>
x86/pm: Fix false positive kmemleak report in msr_build_context()
Chen-Tsung Hsieh <chentsung@chromium.org>
mtd: spi-nor: core: Check written SR value in spi_nor_write_16bit_sr_and_check()
Andrii Nakryiko <andrii@kernel.org>
libbpf: Fix logic for finding matching program for CO-RE relocation
Colin Ian King <colin.i.king@gmail.com>
selftests/resctrl: Fix null pointer dereference on open failed
Colin Ian King <colin.i.king@gmail.com>
drm/v3d: Fix null pointer dereference of pointer perfmon
Kiwoong Kim <kwmad.kim@samsung.com>
scsi: ufs: core: Exclude UECxx from SFR dump list
Bart Van Assche <bvanassche@acm.org>
scsi: ufs: qcom: Fix ufs_qcom_resume()
Dan Carpenter <dan.carpenter@oracle.com>
scsi: iscsi: Fix harmless double shift bug
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dpu: adjust display_v_end for eDP and DP
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/hdmi: switch to drm_bridge_connector
Bjorn Andersson <bjorn.andersson@linaro.org>
drm/msm/dp: Modify prototype of encoder based API
Yuanchu Xie <yuanchu@google.com>
selftests/damon: add damon to selftests root Makefile
Nuno Sá <nuno.sa@analog.com>
of: overlay: do not break notify on NOTIFY_{OK|STOP}
Luca Ceresoli <luca.ceresoli@bootlin.com>
spi: rockchip: fix missing error on unsupported SPI_CS_HIGH
Jon Lin <jon.lin@rock-chips.com>
spi: rockchip: Preset cs-high and clk polarity in setup progress
Jon Lin <jon.lin@rock-chips.com>
spi: rockchip: Stop spi slave dma receiver when cs inactive
Amir Goldstein <amir73il@gmail.com>
fsnotify: fix wrong lockdep annotations
Amir Goldstein <amir73il@gmail.com>
inotify: show inotify mask flags in proc fdinfo
Bjørn Mork <bjorn@mork.no>
mtdblock: warn if opened on NAND
Colin Ian King <colin.i.king@gmail.com>
ALSA: pcm: Check for null pointer of pointer substream before dereferencing it
Marek Vasut <marex@denx.de>
drm/panel: simple: Add missing bus flags for Innolux G070Y2-L01
Chen-Yu Tsai <wenst@chromium.org>
media: hantro: Empty encoder capture buffers by default
Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
media: i2c: max9286: fix kernel oops when removing module
Jacopo Mondi <jacopo+renesas@jmondi.org>
media: i2c: max9286: Use "maxim,gpio-poc" property
Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
media: i2c: max9286: Use dev_err_probe() helper
Dan Carpenter <dan.carpenter@oracle.com>
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
John Ogness <john.ogness@linutronix.de>
printk: wake waiters for safe and NMI contexts
John Ogness <john.ogness@linutronix.de>
printk: add missing memory barrier to wake_up_klogd()
John Ogness <john.ogness@linutronix.de>
printk: use atomic updates for klogd work
Schspa Shi <schspa@gmail.com>
cpufreq: Fix possible race in cpufreq online error path
Zheng Yongjun <zhengyongjun3@huawei.com>
spi: img-spfi: Fix pm_runtime_get_sync() error checking
Chengming Zhou <zhouchengming@bytedance.com>
sched/psi: report zeroes for CPU full at the system level
Chengming Zhou <zhouchengming@bytedance.com>
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
Marco Elver <elver@google.com>
signal: Deliver SIGTRAP on perf event asynchronously if blocked
Nícolas F. R. A. Prado <nfraprado@collabora.com>
drm/mediatek: dpi: Use mt8183 output formats for mt8192
Wei Yongjun <weiyongjun1@huawei.com>
regulator: da9121: Fix uninit-value in da9121_assign_chip_model()
Miaoqian Lin <linmq006@gmail.com>
drm/bridge: Fix error handling in analogix_dp_probe
Miaoqian Lin <linmq006@gmail.com>
HID: elan: Fix potential double free in elan_input_configured
Jonathan Teh <jonathan.teh@outlook.com>
HID: hid-led: fix maximum brightness for Dream Cheeky
Zheyu Ma <zheyuma97@gmail.com>
mtd: rawnand: denali: Use managed device resources
Tyler Hicks <tyhicks@linux.microsoft.com>
EDAC/dmc520: Don't print an error for each unconfigured interrupt line
Arnd Bergmann <arnd@arndb.de>
drbd: fix duplicate array initializer
Christoph Hellwig <hch@lst.de>
target: remove an incorrect unmap zeroes data deduction
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
device property: Allow error pointer to be passed to fwnode APIs
Daniel Scally <djrscally@gmail.com>
device property: Check fwnode->secondary when finding properties
Jan Kiszka <jan.kiszka@siemens.com>
efi: Add missing prototype for efi_capsule_setup_info
Lin Ma <linma@zju.edu.cn>
NFC: NULL out the dev->rfkill to prevent UAF
Lv Ruyi <lv.ruyi@zte.com.cn>
ixp4xx_eth: fix error check return value of platform_get_irq()
Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
net: dsa: mt7530: 1G can also support 1000BASE-X link mode
Paul E. McKenney <paulmck@kernel.org>
scftorture: Fix distribution of short handler delays
Miaoqian Lin <linmq006@gmail.com>
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
Jiasheng Jiang <jiasheng@iscas.ac.cn>
drm: mali-dp: potential dereference of null pointer
Zhou Qingyang <zhou1615@umn.edu>
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Johannes Berg <johannes.berg@intel.com>
nl80211: show SSID for P2P_GO interfaces
Paolo Abeni <pabeni@redhat.com>
mptcp: reset the packet scheduler on PRIO change
Maciej W. Rozycki <macro@orcam.me.uk>
x86/PCI: Fix ALi M1487 (IBC) PIRQ router link value interpretation
Andrii Nakryiko <andrii@kernel.org>
libbpf: Don't error out on CO-RE relos for overriden weak subprogs
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hvs: Reset muxes at probe time
Miles Chen <miles.chen@mediatek.com>
drm/mediatek: Fix mtk_cec_mask()
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hvs: Fix frame count register readout
Ammar Faizi <ammarfaizi2@gnuweeb.org>
x86/delay: Fix the wrong asm constraint in delay_loop()
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
Kuldeep Singh <singh.kuldeep87k@gmail.com>
spi: qcom-qspi: Add minItems to interconnect-names
Chuanhong Guo <gch981213@gmail.com>
mtd: spinand: gigadevice: fix Quad IO for GD5F1GQ5UExxG
Marek Vasut <marex@denx.de>
drm: bridge: icn6211: Fix HFP_HSW_HBP_HI and HFP_MIN handling
Marek Vasut <marex@denx.de>
drm: bridge: icn6211: Fix register layout
Lucas Stach <l.stach@pengutronix.de>
drm/bridge: adv7511: clean up CEC adapter when probe fails
Jani Nikula <jani.nikula@intel.com>
drm/edid: fix invalid EDID extension block filtering
Wenli Looi <wlooi@ucalgary.ca>
ath9k: fix ar9003_get_eepmisc
Nicolas Belin <nbelin@baylibre.com>
drm: bridge: it66121: Fix the register page length
Niels Dossche <dossche.niels@gmail.com>
ath11k: acquire ab->base_lock in unassign when finding the peer by addr
Zack Rusin <zackr@vmware.com>
drm/vmwgfx: Fix an invalid read
Noralf Trønnes <noralf@tronnes.org>
dt-bindings: display: sitronix, st7735r: Fix backlight in example
Nikita Yushchenko <nikita.yoush@cogentembedded.com>
drm/bridge_connector: enable HPD by default if supported
Linus Torvalds <torvalds@linux-foundation.org>
drm: fix EDID struct for old ARM OABI format
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Input: gpio-keys - cancel delayed work only in case of GPIO
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent panic when SDMA is disabled
Steve French <stfrench@microsoft.com>
smb3: check for null tcon
Peng Wu <wupeng58@huawei.com>
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Finn Thain <fthain@linux-m68k.org>
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/powernv: fix missing of_node_put in uv_init()
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/xics: fix refcount leak in icp_opal_init()
Haren Myneni <haren@linux.ibm.com>
powerpc/powernv/vas: Assign real address to rx_fifo in vas_rx_win_attr
Vasily Averin <vvs@openvz.org>
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
Matthew Wilcox (Oracle) <willy@infradead.org>
alpha: fix alloc_zeroed_user_highpage_movable()
Nicholas Piggin <npiggin@gmail.com>
KVM: PPC: Book3S HV Nested: L2 LPCR should inherit L1 LPES setting
Yicong Yang <yangyicong@hisilicon.com>
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Laurent Dufour <ldufour@linux.ibm.com>
powerpc/rtas: Keep MSR[RI] set when calling RTAS
Viresh Kumar <viresh.kumar@linaro.org>
cpufreq: Avoid unnecessary frequency updates due to mismatch
Peng Wu <wupeng58@huawei.com>
ARM: hisi: Add missing of_node_put after of_find_compatible_node
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
Peng Wu <wupeng58@huawei.com>
ARM: versatile: Add missing of_node_put in dcscb_init
Yang Yingliang <yangyingliang@huawei.com>
pinctrl: renesas: rzn1: Fix possible null-ptr-deref in sh_pfc_map_resources()
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
fat: add ratelimit to fat*_ent_bread()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: Fix fadump to work with a different endian capture kernel
Janusz Krzysztofik <jmkrzyszt@gmail.com>
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Move generic implicit fb quirk entries into quirks.c
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Add quirk bits for enabling/disabling generic implicit fb
Joel Selvaraj <jo@jsfamily.in>
arm64: dts: qcom: sdm845-xiaomi-beryllium: fix typo in panel's vddio-supply property
Zixuan Fu <r33s3n6@gmail.com>
fs: jfs: fix possible NULL pointer dereference in dbFree()
QintaoShen <unSimple1993@163.com>
soc: ti: ti_sci_pm_domains: Check for null return of devm_kcalloc
Gilad Ben-Yossef <gilad@benyossef.com>
crypto: ccree - use fine grained DMA mapping dir
Brian Norris <briannorris@chromium.org>
PM / devfreq: rk3399_dmc: Disable edev on remove()
Konrad Dybcio <konrad.dybcio@somainline.org>
arm64: dts: qcom: msm8994: Fix BLSP[12]_DMA channels count
Konrad Dybcio <konrad.dybcio@somainline.org>
arm64: dts: qcom: msm8994: Fix the cont_splash_mem address
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: s5pv210: align DMA channels with dtschema
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: socfpga: align interrupt controller node name with dtschema
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: ox820: align interrupt controller node name with dtschema
Niels Dossche <dossche.niels@gmail.com>
IB/rdmavt: add missing locks in rvt_ruc_loopback
Bodo Stroesser <bostroesser@gmail.com>
scsi: target: tcmu: Avoid holding XArray lock when calling lock_page
Bob Peterson <rpeterso@redhat.com>
gfs2: use i_lock spin_lock for inode qadata
Yonghong Song <yhs@fb.com>
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
char: tpm: cr50_i2c: Suppress duplicated error message in .remove()
Jakub Kicinski <kuba@kernel.org>
eth: tg3: silence the GCC 12 array-bounds warning
David Howells <dhowells@redhat.com>
afs: Adjust ACK interpretation to try and cope with NAT
David Howells <dhowells@redhat.com>
rxrpc, afs: Fix selection of abort codes
David Howells <dhowells@redhat.com>
rxrpc: Return an error to sendmsg if call failed
Geert Uytterhoeven <geert@linux-m68k.org>
m68k: atari: Make Atari ROM port I/O write macros return void
Alex Elder <elder@linaro.org>
net: ipa: ignore endianness if there is no header
Borislav Petkov <bp@suse.de>
x86/microcode: Add explicit CPU vendor dependency
Vincent Mailhol <mailhol.vincent@wanadoo.fr>
can: mcp251xfd: silence clang's -Wunaligned-access warning
Chaitanya Kulkarni <kch@nvidia.com>
nvme: set non-mdts limits in nvme_scan_work
Pierre Gondois <Pierre.Gondois@arm.com>
ACPI: CPPC: Assume no transition latency if no PCCT
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: rt1015p: remove dependency on GPIOLIB
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: max98357a: remove dependency on GPIOLIB
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: hantro: Stop using H.264 parameter pic_num
Kwanghoon Son <k.son@samsung.com>
media: exynos4-is: Fix compile warning
Fabio Estevam <festevam@denx.de>
net: phy: micrel: Allow probing without .driver_data
Sathishkumar S <sathishkumar.sundararaju@amd.com>
drm/amd/pm: update smartshift powerboost calc for smu13
Sathishkumar S <sathishkumar.sundararaju@amd.com>
drm/amd/pm: update smartshift powerboost calc for smu12
Xie Yongji <xieyongji@bytedance.com>
nbd: Fix hung on disconnect request if socket is closed before
Lin Ma <linma@zju.edu.cn>
ASoC: rt5645: Fix errorenous cleanup order
Smith, Kyle Miller (Nimble Kernel) <kyles@hpe.com>
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Jason A. Donenfeld <Jason@zx2c4.com>
openrisc: start CPU timer early in boot
Lukas Wunner <lukas@wunner.de>
usbnet: Run unregister_netdev() before unbind() again
Hans Verkuil <hverkuil-cisco@xs4all.nl>
media: cec-adap.c: fix is_configuring state
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
media: imon: reorganize serialization
Hans Verkuil <hverkuil-cisco@xs4all.nl>
media: ccs-core.c: fix failure to call clk_disable_unprepare
Benjamin Gaignard <benjamin.gaignard@collabora.com>
media: hantro: HEVC: unconditionnaly set pps_{cb/cr}_qp_offset values
Philipp Zabel <p.zabel@pengutronix.de>
media: coda: limit frame interval enumeration to supported encoder frame sizes
Hangyu Hua <hbh25y@gmail.com>
media: rga: fix possible memory leak in rga_probe
Felix Fietkau <nbd@nbd.name>
mt76: fix encap offload ethernet type check
Felix Fietkau <nbd@nbd.name>
mt76: mt7921: accept rx frames with non-standard VHT MCS10-11
Dongliang Mu <mudongliangabcd@gmail.com>
rtlwifi: Use pr_warn instead of WARN_ONCE
Corey Minyard <cminyard@mvista.com>
ipmi: Fix pr_fmt to avoid compilation issues
Corey Minyard <cminyard@mvista.com>
ipmi:ssif: Check for NULL msg when handling events and messages
Mario Limonciello <mario.limonciello@amd.com>
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
Mikulas Patocka <mpatocka@redhat.com>
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
Patrice Chotard <patrice.chotard@foss.st.com>
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Hao Jia <jiahao.os@bytedance.com>
sched/core: Avoid obvious double update_rq_clock warning
Ravi Bangoria <ravi.bangoria@amd.com>
perf/amd/ibs: Cascade pmu init functions' return value
Heiko Carstens <hca@linux.ibm.com>
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Eric Dumazet <edumazet@google.com>
net: remove two BUG() from skb_checksum_help()
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Alter FPIN stat accounting logic
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
Zhen Lei <thunder.leizhen@huawei.com>
of: Support more than one crash kernel regions for kexec -s
Dongliang Mu <mudongliangabcd@gmail.com>
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
Nícolas F. R. A. Prado <nfraprado@collabora.com>
regulator: mt6315: Enforce regulator-compatible, not name
Alice Wong <shiwei.wong@amd.com>
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/psp: move PSP memory alloc from hw_init to sw_init
Petr Machata <petrm@nvidia.com>
mlxsw: Treat LLDP packets as control
Petr Machata <petrm@nvidia.com>
mlxsw: spectrum_dcb: Do not warn about priority changes
Mark Brown <broonie@kernel.org>
ASoC: dapm: Don't fold register value changes into notifications
Mark Bloch <mbloch@nvidia.com>
net/mlx5: fs, delete the FTE when there are no rules attached to it
jianghaoran <jianghaoran@kylinos.cn>
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
Xiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
scsi: target: tcmu: Fix possible data corruption
Lv Ruyi <lv.ruyi@zte.com.cn>
drm: msm: fix error check return value of irq_of_parse_and_map()
Alexandru Elisei <alexandru.elisei@arm.com>
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Abhishek Kumar <kuabhs@chromium.org>
ath10k: skip ath10k_halt during suspend for driver state RESTARTING
Evan Quan <evan.quan@amd.com>
drm/amd/pm: fix the compile warning
Steven Price <steven.price@arm.com>
drm/plane: Move range check for format_count earlier
Hans de Goede <hdegoede@redhat.com>
ASoC: Intel: bytcr_rt5640: Add quirk for the HP Pro Tablet 408
Hari Chandrakanthan <quic_haric@quicinc.com>
ath11k: disable spectral scan during spectral deinit
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix resource leak in lpfc_sli4_send_seq_to_ulp()
Minghao Chi <chi.minghao@zte.com.cn>
scsi: ufs: Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
Haohui Mai <ricetons@gmail.com>
drm/amdgpu/sdma: Fix incorrect calculations of the wptr of the doorbells
Lv Ruyi <lv.ruyi@zte.com.cn>
scsi: megaraid: Fix error check return value of register_chrdev()
Vignesh Raghavendra <vigneshr@ti.com>
drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit
Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
mmc: jz4740: Apply DMA engine limits to maximum segment size
Heming Zhao <heming.zhao@suse.com>
md/bitmap: don't set sb values if can't pass sanity check
Zheyu Ma <zheyuma97@gmail.com>
media: cx25821: Fix the warning when removing the module
Zheyu Ma <zheyuma97@gmail.com>
media: pci: cx23885: Fix the error handling in cx23885_initdev()
Luca Weiss <luca.weiss@fairphone.com>
media: venus: hfi: avoid null dereference in deinit
Thibaut VARÈNE <hacks+kernel@slashdirt.org>
ath9k: fix QCA9561 PA bias level
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: rsnd: care return value from rsnd_node_fixed_index()
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: rsnd: care default case on rsnd_ssiu_busif_err_status_clear()
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
drm/amd/pm: fix double free in si_parse_power_table()
Ulf Hansson <ulf.hansson@linaro.org>
cpuidle: PSCI: Improve support for suspend-to-RAM for PSCI OSI mode
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix call trace observed during I/O with CMF enabled
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix SCSI I/O completion and abort handler deadlock
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Move cfg_log_verbose check before calling lpfc_dmp_dbg()
Len Brown <len.brown@intel.com>
tools/power turbostat: fix ICX DRAM power numbers
Biju Das <biju.das.jz@bp.renesas.com>
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Po-Hao Huang <phhuang@realtek.com>
rtw88: 8821c: fix debugfs rssi value
Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
ALSA: jack: Access input_dev under mutex
Haowen Bai <baihaowen@meizu.com>
sfc: ef10: Fix assigning negative value to unsigned variable
Paul E. McKenney <paulmck@kernel.org>
rcu: Make TASKS_RUDE_RCU select IRQ_WORK
Padmanabha Srinivasaiah <treasure4paddy@gmail.com>
rcu-tasks: Fix race in schedule and flush work
Saaem Rizvi <syerizvi@amd.com>
drm/amd/display: Disabling Z10 on DCN31
Liviu Dudau <liviu.dudau@arm.com>
drm/komeda: return early if drm_universal_plane_init() fails.
Peter Seiderer <ps.report@gmx.net>
mac80211: minstrel_ht: fix where rate stats are stored (fixes debugfs output)
Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
ACPICA: Avoid cache flush inside virtual machines
Mike Travis <mike.travis@hpe.com>
x86/platform/uv: Update TSC sync state for UV5
Daniel Vetter <daniel.vetter@ffwll.ch>
fbcon: Consistently protect deferred_takeover with console_lock()
Niels Dossche <dossche.niels@gmail.com>
ipv6: fix locking issues with loops over idev->addr_list
Haowen Bai <baihaowen@meizu.com>
ipw2x00: Fix potential NULL dereference in libipw_xmit()
Haowen Bai <baihaowen@meizu.com>
b43: Fix assigning negative value to unsigned variable
Haowen Bai <baihaowen@meizu.com>
b43legacy: Fix assigning negative value to unsigned variable
Niels Dossche <dossche.niels@gmail.com>
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
Quentin Monnet <quentin@isovalent.com>
selftests/bpf: Fix parsing of prog types in UAPI hdr for bpftool sync
Nikolay Borisov <nborisov@suse.com>
selftests/bpf: Fix vfs_link kprobe definition
Liu Zixian <liuzixian4@huawei.com>
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Zack Rusin <zackr@vmware.com>
drm/vmwgfx: validate the screen formats
Tejas Upadhyay <tejaskumarx.surendrakumar.upadhyay@intel.com>
iommu/vt-d: Add RPLS to quirk list to skip TE disabling
Qu Wenruo <wqu@suse.com>
btrfs: fix the error handling for submit_extent_page() for btrfs_do_readpage()
Qu Wenruo <wqu@suse.com>
btrfs: repair super block num_devices automatically
Qu Wenruo <wqu@suse.com>
btrfs: return correct error number for __extent_writepage_io()
Qu Wenruo <wqu@suse.com>
btrfs: add "0x" prefix for unsupported optional features
Eric W. Biederman <ebiederm@xmission.com>
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Eric W. Biederman <ebiederm@xmission.com>
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
Eric W. Biederman <ebiederm@xmission.com>
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
Kristen Carlson Accardi <kristen@linux.intel.com>
x86/sgx: Set active memcg prior to shmem allocation
Baoquan He <bhe@redhat.com>
x86/kexec: fix memory leak of elf header buffer
Kan Liang <kan.liang@linux.intel.com>
perf/x86/intel: Fix event constraints for ICL
Ammar Faizi <ammarfaizi2@gnuweeb.org>
x86/MCE/AMD: Fix memory leak when threshold_create_bank() fails
Michael Niewöhner <linux@mniewoehner.de>
platform/x86: intel-hid: fix _DSM function index handling
Mathias Nyman <mathias.nyman@linux.intel.com>
xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: when extending a file with falloc we should make files not-sparse
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: fix potential double free during failed mount
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Restore ntfs_xattr_get_acl and ntfs_xattr_set_acl functions
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Update i_ctime when xattr is added
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
fs/ntfs3: Fix some memory leaks in an error handling path of 'log_replay()'
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: In function ntfs_set_acl_ex do not change inode->i_mode if called from function ntfs_init_acl
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Check new size for limits
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Keep preallocated only if option prealloc enabled
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Fix fiemap + fix shrink file size (to remove preallocated space)
Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3: Update valid size if -EIOCBQUEUED
Kishon Vijay Abraham I <kishon@ti.com>
usb: core: hcd: Add support for deferring roothub registration
Albert Wang <albertccwang@google.com>
usb: dwc3: gadget: Move null pinter check to proper place
Linus Walleij <linus.walleij@linaro.org>
usb: isp1760: Fix out-of-bounds array access
Monish Kumar R <monish.kumar.r@intel.com>
USB: new quirk for Dell Gen 2 devices
Carl Yin(殷张成) <carl.yin@quectel.com>
USB: serial: option: add Quectel BG95 modem
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix type detection for odd device
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Cancel pending work at closing a MIDI substream
Marios Levogiannis <marios.levogiannis@gmail.com>
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Rik van der Kemp <rik@upto11.nl>
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9520 laptop
Kailang Yang <kailang@realtek.com>
ALSA: hda/realtek - Add new type for ALC245
Nathan Chancellor <nathan@kernel.org>
riscv: Move alternative length validation into subsection
Tobias Klauser <tklauser@distanz.ch>
riscv: Wire up memfd_secret in UAPI header
Samuel Holland <samuel@sholland.org>
riscv: Fix irq_work when SMP is disabled
Alexandre Ghiti <alexandre.ghiti@canonical.com>
riscv: Initialize thread pointer before calling C functions
Xianting Tian <xianting.tian@linux.alibaba.com>
RISC-V: Mark IORESOURCE_EXCLUSIVE for reserved mem instead of IORESOURCE_BUSY
Helge Deller <deller@gmx.de>
parisc/stifb: Keep track of hardware path of graphics card
Helge Deller <deller@gmx.de>
parisc/stifb: Implement fb_is_primary_device()
Niklas Cassel <niklas.cassel@wdc.com>
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
Stephen Boyd <swboyd@chromium.org>
arm64: Initialize jump labels before setup_machine_fdt()
-------------
Diffstat:
Documentation/accounting/psi.rst | 9 +-
Documentation/conf.py | 2 +-
.../bindings/display/sitronix,st7735r.yaml | 1 +
.../devicetree/bindings/gpio/gpio-altera.txt | 5 +-
.../bindings/regulator/mt6315-regulator.yaml | 2 +-
.../bindings/spi/qcom,spi-qcom-qspi.yaml | 1 +
Documentation/filesystems/f2fs.rst | 1 +
Documentation/sound/alsa-configuration.rst | 4 +-
Documentation/userspace-api/landlock.rst | 4 +-
Makefile | 4 +-
arch/alpha/include/asm/page.h | 2 +-
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13 +-
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22 +-
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4 +-
arch/arm/boot/dts/bcm5301x.dtsi | 15 +-
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4 +-
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 6 +-
arch/arm/boot/dts/imx6qdl-colibri.dtsi | 6 +-
arch/arm/boot/dts/ox820.dtsi | 2 +-
arch/arm/boot/dts/s5pv210-aries.dtsi | 3 +-
arch/arm/boot/dts/s5pv210.dtsi | 12 +-
arch/arm/boot/dts/sama7g5.dtsi | 1 -
arch/arm/boot/dts/socfpga.dtsi | 2 +-
arch/arm/boot/dts/socfpga_arria10.dtsi | 2 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 1 +
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4 +-
arch/arm/kernel/signal.c | 1 +
arch/arm/mach-hisi/platsmp.c | 4 +
arch/arm/mach-mediatek/Kconfig | 1 +
arch/arm/mach-omap1/clock.c | 2 +-
arch/arm/mach-pxa/cm-x300.c | 8 +-
arch/arm/mach-pxa/magician.c | 2 +-
arch/arm/mach-pxa/tosa.c | 4 +-
arch/arm/mach-vexpress/dcscb.c | 1 +
arch/arm64/Kconfig.platforms | 1 +
.../dts/marvell/armada-3720-espressobin-ultra.dts | 5 -
arch/arm64/boot/dts/mediatek/mt8192.dtsi | 2 +-
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 5 +-
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8994.dtsi | 8 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 2 +-
.../boot/dts/qcom/sdm845-xiaomi-beryllium.dts | 2 +-
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi | 2 -
arch/arm64/include/asm/processor.h | 10 +-
arch/arm64/kernel/setup.c | 7 +-
arch/arm64/kernel/signal.c | 1 +
arch/arm64/kernel/signal32.c | 1 +
arch/arm64/kernel/sys_compat.c | 2 +-
arch/arm64/mm/copypage.c | 4 +-
arch/csky/kernel/probes/kprobes.c | 2 +-
arch/m68k/Kconfig.cpu | 2 +-
arch/m68k/include/asm/raw_io.h | 6 +-
arch/m68k/kernel/signal.c | 1 +
.../include/asm/mach-ip27/cpu-feature-overrides.h | 1 -
.../include/asm/mach-ip30/cpu-feature-overrides.h | 1 -
arch/openrisc/include/asm/timex.h | 1 +
arch/openrisc/kernel/head.S | 9 +
arch/parisc/include/asm/fb.h | 4 +
arch/powerpc/include/asm/page.h | 7 +-
arch/powerpc/include/asm/vas.h | 2 +-
arch/powerpc/kernel/entry_64.S | 24 +-
arch/powerpc/kernel/fadump.c | 8 +-
arch/powerpc/kernel/idle.c | 2 +-
arch/powerpc/kernel/rtas.c | 9 +
arch/powerpc/kvm/book3s_hv.c | 4 +
arch/powerpc/kvm/book3s_hv_nested.c | 3 +-
arch/powerpc/perf/isa207-common.c | 12 +-
arch/powerpc/platforms/4xx/cpm.c | 2 +-
arch/powerpc/platforms/8xx/cpm1.c | 1 +
arch/powerpc/platforms/powernv/opal-fadump.c | 94 +--
arch/powerpc/platforms/powernv/opal-fadump.h | 10 +-
arch/powerpc/platforms/powernv/ultravisor.c | 1 +
arch/powerpc/platforms/powernv/vas-fault.c | 2 +-
arch/powerpc/platforms/powernv/vas-window.c | 4 +-
arch/powerpc/platforms/powernv/vas.h | 2 +-
arch/powerpc/sysdev/dart_iommu.c | 6 +-
arch/powerpc/sysdev/fsl_rio.c | 2 +
arch/powerpc/sysdev/xics/icp-opal.c | 1 +
arch/powerpc/sysdev/xive/spapr.c | 43 +-
arch/riscv/include/asm/alternative-macros.h | 4 +-
arch/riscv/include/asm/irq_work.h | 2 +-
arch/riscv/include/asm/unistd.h | 1 -
arch/riscv/include/uapi/asm/unistd.h | 1 +
arch/riscv/kernel/head.S | 1 +
arch/riscv/kernel/setup.c | 4 +-
arch/s390/include/asm/cio.h | 2 +-
arch/s390/include/asm/kexec.h | 10 +
arch/s390/include/asm/preempt.h | 15 +-
arch/s390/kernel/perf_event.c | 2 +-
arch/s390/kernel/time.c | 8 +-
arch/sparc/kernel/signal32.c | 1 +
arch/sparc/kernel/signal_64.c | 1 +
arch/um/drivers/chan_user.c | 9 +-
arch/um/include/asm/Kbuild | 1 +
arch/um/include/asm/thread_info.h | 2 +
arch/um/kernel/exec.c | 2 +-
arch/um/kernel/process.c | 2 +-
arch/um/kernel/ptrace.c | 8 +-
arch/um/kernel/signal.c | 4 +-
arch/x86/Kconfig | 4 +-
arch/x86/entry/entry_64.S | 1 +
arch/x86/entry/vdso/vma.c | 2 +-
arch/x86/events/amd/ibs.c | 55 +-
arch/x86/events/intel/core.c | 2 +-
arch/x86/include/asm/acenv.h | 14 +-
arch/x86/include/asm/kexec.h | 8 +
arch/x86/include/asm/suspend_32.h | 2 +-
arch/x86/include/asm/suspend_64.h | 12 +-
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/apic/x2apic_uv_x.c | 8 +-
arch/x86/kernel/cpu/intel.c | 2 +-
arch/x86/kernel/cpu/mce/amd.c | 32 +-
arch/x86/kernel/cpu/sgx/encl.c | 105 ++-
arch/x86/kernel/cpu/sgx/encl.h | 7 +-
arch/x86/kernel/cpu/sgx/main.c | 9 +-
arch/x86/kernel/machine_kexec_64.c | 12 +-
arch/x86/kernel/signal_compat.c | 2 +
arch/x86/kernel/step.c | 3 +-
arch/x86/kernel/sys_x86_64.c | 7 +-
arch/x86/kvm/lapic.c | 1 +
arch/x86/kvm/vmx/nested.c | 45 +-
arch/x86/kvm/vmx/vmcs.h | 5 +
arch/x86/lib/delay.c | 4 +-
arch/x86/mm/pat/memtype.c | 2 +-
arch/x86/pci/irq.c | 19 +-
arch/x86/um/ldt.c | 6 +-
arch/xtensa/kernel/ptrace.c | 4 +-
arch/xtensa/kernel/signal.c | 4 +-
arch/xtensa/platforms/iss/simdisk.c | 18 +-
block/bfq-cgroup.c | 111 +--
block/bfq-iosched.c | 64 +-
block/bfq-iosched.h | 7 +-
block/blk-iolatency.c | 122 ++--
crypto/cryptd.c | 23 +-
drivers/acpi/cppc_acpi.c | 17 +-
drivers/acpi/property.c | 18 +-
drivers/acpi/sleep.c | 12 +
drivers/base/memory.c | 5 +-
drivers/base/node.c | 1 +
drivers/base/power/domain.c | 1 +
drivers/base/property.c | 90 ++-
drivers/block/drbd/drbd_main.c | 11 +-
drivers/block/nbd.c | 13 +-
drivers/block/virtio_blk.c | 7 +-
drivers/char/hw_random/omap3-rom-rng.c | 2 +-
drivers/char/ipmi/ipmi_msghandler.c | 4 +-
drivers/char/ipmi/ipmi_ssif.c | 23 +
drivers/char/random.c | 12 +-
drivers/char/tpm/tpm_tis_i2c_cr50.c | 4 +-
drivers/clk/tegra/clk-dfll.c | 12 +
drivers/cpufreq/cpufreq.c | 11 +
drivers/cpufreq/mediatek-cpufreq.c | 18 +-
drivers/cpuidle/cpuidle-psci.c | 46 ++
.../crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c | 115 ++--
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 30 +-
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c | 10 +-
drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 14 +-
drivers/crypto/ccree/cc_buffer_mgr.c | 27 +-
drivers/crypto/marvell/cesa/cipher.c | 1 -
drivers/crypto/nx/nx-common-powernv.c | 2 +-
drivers/crypto/qat/qat_common/adf_gen2_hw_data.c | 18 +-
drivers/crypto/qat/qat_common/adf_gen2_hw_data.h | 1 +
.../crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c | 15 +-
drivers/devfreq/rk3399_dmc.c | 2 +
drivers/dma/idxd/cdev.c | 8 +-
drivers/dma/stm32-mdma.c | 23 +-
drivers/edac/dmc520_edac.c | 2 +-
drivers/firmware/arm_ffa/driver.c | 4 +-
drivers/firmware/arm_scmi/base.c | 2 +-
drivers/gpio/gpio-rockchip.c | 24 +-
drivers/gpio/gpiolib-of.c | 5 +
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 95 ++-
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 +-
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4 +-
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 8 +-
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 8 +-
.../gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 1 +
drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 14 +-
drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 8 +-
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 60 +-
.../gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 62 +-
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10 +-
drivers/gpu/drm/arm/malidp_crtc.c | 5 +-
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1 +
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31 +-
drivers/gpu/drm/bridge/chipone-icn6211.c | 155 ++++-
drivers/gpu/drm/bridge/ite-it66121.c | 2 +-
drivers/gpu/drm/drm_bridge_connector.c | 4 +-
drivers/gpu/drm/drm_edid.c | 6 +-
drivers/gpu/drm/drm_plane.c | 14 +-
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6 +
drivers/gpu/drm/gma500/psb_intel_display.c | 7 +-
drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 33 +-
drivers/gpu/drm/i915/i915_perf.c | 4 +-
drivers/gpu/drm/i915/i915_perf_types.h | 2 +-
drivers/gpu/drm/mediatek/mtk_cec.c | 2 +-
drivers/gpu/drm/mediatek/mtk_dpi.c | 4 +-
drivers/gpu/drm/msm/Makefile | 2 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 23 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20 +-
drivers/gpu/drm/msm/dp/dp_ctrl.c | 16 +-
drivers/gpu/drm/msm/dp/dp_display.c | 55 +-
drivers/gpu/drm/msm/dsi/dsi_host.c | 21 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 2 +-
drivers/gpu/drm/msm/hdmi/hdmi.c | 22 +-
drivers/gpu/drm/msm/hdmi/hdmi.h | 19 +-
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 81 ++-
.../drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154 +----
drivers/gpu/drm/msm/msm_drv.c | 8 +-
drivers/gpu/drm/msm/msm_gem_prime.c | 2 +-
drivers/gpu/drm/msm/msm_kms.h | 1 +
drivers/gpu/drm/nouveau/dispnv50/atom.h | 6 +-
drivers/gpu/drm/nouveau/dispnv50/crc.c | 27 +-
drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 2 +
drivers/gpu/drm/nouveau/nvkm/subdev/bus/gf100.c | 14 +-
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv31.c | 6 +-
drivers/gpu/drm/nouveau/nvkm/subdev/bus/nv50.c | 6 +-
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6 +-
drivers/gpu/drm/panel/panel-simple.c | 3 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 +-
drivers/gpu/drm/stm/ltdc.c | 16 +-
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8 +-
drivers/gpu/drm/v3d/v3d_perfmon.c | 3 +-
drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
drivers/gpu/drm/vc4/vc4_drv.h | 1 +
drivers/gpu/drm/vc4/vc4_hvs.c | 49 +-
drivers/gpu/drm/vc4/vc4_regs.h | 12 +-
drivers/gpu/drm/vc4/vc4_txp.c | 8 +-
drivers/gpu/drm/virtio/virtgpu_display.c | 2 +
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 30 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1 -
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 14 +-
drivers/hid/amd-sfh-hid/amd_sfh_hid.c | 4 +-
drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2 +-
drivers/hid/hid-bigbenff.c | 6 +
drivers/hid/hid-elan.c | 2 -
drivers/hid/hid-led.c | 2 +-
drivers/hv/channel.c | 6 +-
drivers/hwmon/pmbus/pmbus_core.c | 28 +-
drivers/hwtracing/coresight/coresight-core.c | 33 +-
drivers/i2c/busses/i2c-at91-master.c | 11 +
drivers/i2c/busses/i2c-npcm7xx.c | 103 ++-
drivers/i2c/busses/i2c-rcar.c | 15 +-
drivers/infiniband/hw/hfi1/file_ops.c | 2 +
drivers/infiniband/hw/hfi1/init.c | 2 +-
drivers/infiniband/hw/hfi1/sdma.c | 12 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 7 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 24 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 2 +-
drivers/infiniband/sw/rdmavt/qp.c | 6 +-
drivers/infiniband/sw/rxe/rxe_req.c | 2 +-
drivers/input/keyboard/gpio_keys.c | 2 +-
drivers/input/misc/sparcspkr.c | 1 +
drivers/input/touchscreen/stmfts.c | 16 +-
drivers/interconnect/qcom/icc-rpmh.c | 10 +-
drivers/interconnect/qcom/sc7180.c | 21 -
drivers/interconnect/qcom/sm8150.c | 1 -
drivers/interconnect/qcom/sm8250.c | 1 -
drivers/interconnect/qcom/sm8350.c | 1 -
drivers/iommu/amd/init.c | 2 +-
drivers/iommu/amd/iommu.c | 7 -
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 13 +-
drivers/iommu/dma-iommu.c | 7 +-
drivers/iommu/intel/iommu.c | 2 +-
drivers/iommu/msm_iommu.c | 11 +-
drivers/iommu/mtk_iommu.c | 30 +-
drivers/iommu/mtk_iommu.h | 2 +
drivers/iommu/mtk_iommu_v1.c | 7 +
drivers/irqchip/irq-armada-370-xp.c | 11 +-
drivers/irqchip/irq-aspeed-i2c-ic.c | 4 +-
drivers/irqchip/irq-aspeed-scu-ic.c | 4 +-
drivers/irqchip/irq-sni-exiu.c | 25 +-
drivers/irqchip/irq-xtensa-mx.c | 18 +-
drivers/macintosh/Kconfig | 6 +
drivers/macintosh/Makefile | 3 +-
drivers/macintosh/via-pmu.c | 2 +-
drivers/mailbox/mailbox.c | 19 +-
drivers/md/bcache/btree.c | 58 +-
drivers/md/bcache/btree.h | 2 +-
drivers/md/bcache/journal.c | 31 +-
drivers/md/bcache/journal.h | 2 +
drivers/md/bcache/request.c | 6 +
drivers/md/bcache/super.c | 1 +
drivers/md/bcache/writeback.c | 101 +--
drivers/md/bcache/writeback.h | 2 +-
drivers/md/md-bitmap.c | 44 +-
drivers/md/md.c | 22 +-
drivers/md/raid0.c | 1 -
drivers/media/cec/core/cec-adap.c | 6 +-
drivers/media/i2c/ccs/ccs-core.c | 7 +-
drivers/media/i2c/max9286.c | 139 ++--
drivers/media/i2c/ov5648.c | 4 +-
drivers/media/i2c/ov7670.c | 1 -
drivers/media/i2c/rdacm20.c | 2 +-
drivers/media/i2c/rdacm21.c | 2 +-
drivers/media/pci/cx23885/cx23885-core.c | 6 +-
drivers/media/pci/cx25821/cx25821-core.c | 2 +-
drivers/media/platform/aspeed-video.c | 4 +-
drivers/media/platform/atmel/atmel-sama5d2-isc.c | 7 +-
drivers/media/platform/coda/coda-common.c | 35 +-
drivers/media/platform/exynos4-is/fimc-is.c | 6 +-
drivers/media/platform/exynos4-is/fimc-isp-video.h | 2 +-
drivers/media/platform/qcom/venus/hfi.c | 3 +
drivers/media/platform/rockchip/rga/rga.c | 6 +-
drivers/media/platform/sti/delta/delta-v4l2.c | 6 +-
drivers/media/platform/vsp1/vsp1_rpf.c | 6 +-
drivers/media/rc/imon.c | 99 ++-
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7 +-
drivers/media/usb/uvc/uvc_v4l2.c | 20 +-
drivers/memory/samsung/exynos5422-dmc.c | 5 +-
drivers/mfd/davinci_voicecodec.c | 6 +-
drivers/mfd/ipaq-micro.c | 2 +-
drivers/misc/ocxl/file.c | 2 +
drivers/mmc/core/block.c | 8 +-
drivers/mmc/host/jz4740_mmc.c | 20 +
drivers/mmc/host/sdhci_am654.c | 23 +-
drivers/mtd/chips/cfi_cmdset_0002.c | 103 ++-
drivers/mtd/mtdblock.c | 8 +-
drivers/mtd/nand/raw/cadence-nand-controller.c | 5 +-
drivers/mtd/nand/raw/denali_pci.c | 15 +-
drivers/mtd/nand/raw/intel-nand-controller.c | 2 +-
drivers/mtd/nand/spi/gigadevice.c | 10 +-
drivers/mtd/spi-nor/core.c | 9 +
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 2 +-
drivers/net/can/xilinx_can.c | 4 +-
drivers/net/dsa/Kconfig | 3 +-
drivers/net/dsa/mt7530.c | 14 +-
drivers/net/ethernet/broadcom/Makefile | 5 +
drivers/net/ethernet/cadence/macb_main.c | 40 +-
drivers/net/ethernet/cadence/macb_ptp.c | 4 +-
.../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 5 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 10 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 5 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 9 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 2 +
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 23 +-
drivers/net/ethernet/huawei/hinic/hinic_main.c | 10 +-
drivers/net/ethernet/huawei/hinic/hinic_tx.c | 9 +-
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13 -
.../net/ethernet/mellanox/mlxsw/spectrum_trap.c | 2 +-
drivers/net/ethernet/sfc/ef10.c | 2 +-
.../net/ethernet/stmicro/stmmac/stmmac_selftests.c | 15 +-
drivers/net/ethernet/xscale/ptp_ixp46x.c | 2 +-
drivers/net/hyperv/netvsc_drv.c | 5 +-
drivers/net/ipa/ipa_endpoint.c | 36 +-
drivers/net/phy/micrel.c | 11 +-
drivers/net/usb/asix_devices.c | 6 +-
drivers/net/usb/smsc95xx.c | 3 +-
drivers/net/usb/usbnet.c | 6 +-
drivers/net/wireless/ath/ath10k/mac.c | 20 +-
drivers/net/wireless/ath/ath11k/mac.c | 16 +-
drivers/net/wireless/ath/ath11k/spectral.c | 17 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8 +
drivers/net/wireless/ath/carl9170/tx.c | 3 +
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/broadcom/b43legacy/phy.c | 2 +-
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3 +
drivers/net/wireless/marvell/mwifiex/11h.c | 2 +
drivers/net/wireless/mediatek/mt76/agg-rx.c | 5 +-
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4 +-
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 6 +-
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 8 +-
drivers/net/wireless/microchip/wilc1000/mon.c | 4 +-
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8 +-
drivers/net/wireless/realtek/rtlwifi/usb.c | 2 +-
drivers/net/wireless/realtek/rtw88/rtw8821c.c | 4 +
drivers/nfc/st21nfca/se.c | 17 +-
drivers/nfc/st21nfca/st21nfca.h | 1 +
drivers/nvdimm/core.c | 9 -
drivers/nvdimm/security.c | 5 -
drivers/nvme/host/core.c | 21 +-
drivers/nvme/host/pci.c | 1 +
drivers/of/kexec.c | 9 +
drivers/of/overlay.c | 4 +-
drivers/opp/of.c | 2 +-
drivers/pci/controller/cadence/pcie-cadence-ep.c | 3 +-
drivers/pci/controller/dwc/pci-imx6.c | 23 +-
drivers/pci/controller/dwc/pcie-designware-host.c | 3 +-
drivers/pci/controller/dwc/pcie-qcom.c | 9 +-
drivers/pci/controller/pcie-mediatek.c | 1 +
drivers/pci/controller/pcie-microchip-host.c | 6 +-
drivers/pci/controller/pcie-rockchip-ep.c | 3 +-
drivers/pci/pci-acpi.c | 41 +-
drivers/pci/pci.c | 12 +-
drivers/pci/pcie/aer.c | 7 +-
drivers/phy/qualcomm/phy-qcom-qmp.c | 11 +-
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 18 +
drivers/pinctrl/mediatek/Kconfig | 1 +
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2 +-
drivers/pinctrl/pinctrl-rockchip.c | 54 +-
drivers/pinctrl/pinctrl-rockchip.h | 7 +-
drivers/pinctrl/renesas/core.c | 7 +-
drivers/pinctrl/renesas/pfc-r8a779a0.c | 29 +
drivers/pinctrl/renesas/pinctrl-rzn1.c | 10 +-
drivers/platform/chrome/cros_ec.c | 16 +-
drivers/platform/chrome/cros_ec_chardev.c | 2 +-
drivers/platform/chrome/cros_ec_proto.c | 50 +-
drivers/platform/mips/cpu_hwmon.c | 127 ++--
drivers/platform/x86/intel/hid.c | 2 +-
drivers/regulator/core.c | 7 +-
drivers/regulator/da9121-regulator.c | 2 +
drivers/regulator/pfuze100-regulator.c | 2 +
drivers/regulator/qcom_smd-regulator.c | 35 +-
drivers/regulator/scmi-regulator.c | 2 +-
drivers/s390/cio/chsc.c | 4 +-
drivers/scsi/dc395x.c | 15 +-
drivers/scsi/fcoe/fcoe_ctlr.c | 2 +-
drivers/scsi/lpfc/lpfc_els.c | 49 +-
drivers/scsi/lpfc/lpfc_init.c | 51 +-
drivers/scsi/lpfc/lpfc_logmsg.h | 6 +-
drivers/scsi/lpfc/lpfc_scsi.c | 37 +-
drivers/scsi/lpfc/lpfc_sli.c | 6 +-
drivers/scsi/megaraid.c | 2 +-
drivers/scsi/ufs/ti-j721e-ufs.c | 6 +-
drivers/scsi/ufs/ufs-qcom.c | 14 +-
drivers/scsi/ufs/ufshcd.c | 7 +-
drivers/soc/bcm/bcm63xx/bcm-pmb.c | 3 +
drivers/soc/qcom/llcc-qcom.c | 1 +
drivers/soc/qcom/smp2p.c | 1 +
drivers/soc/qcom/smsm.c | 1 +
drivers/soc/ti/ti_sci_pm_domains.c | 2 +
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-fsl-qspi.c | 4 +
drivers/spi/spi-img-spfi.c | 2 +-
drivers/spi/spi-rockchip.c | 113 +++-
drivers/spi/spi-rspi.c | 15 +-
drivers/spi/spi-stm32-qspi.c | 3 +-
drivers/spi/spi-ti-qspi.c | 5 +-
drivers/staging/media/hantro/hantro_g2_hevc_dec.c | 11 +-
drivers/staging/media/hantro/hantro_h264.c | 2 -
drivers/staging/media/hantro/hantro_v4l2.c | 8 +-
drivers/staging/media/rkvdec/rkvdec-h264.c | 37 +-
drivers/staging/media/rkvdec/rkvdec.c | 10 +-
drivers/staging/r8188eu/os_dep/ioctl_linux.c | 103 +--
drivers/target/target_core_device.c | 1 -
drivers/target/target_core_user.c | 50 +-
drivers/thermal/broadcom/bcm2711_thermal.c | 5 +-
drivers/thermal/broadcom/sr-thermal.c | 3 +
drivers/thermal/devfreq_cooling.c | 25 +-
drivers/thermal/imx_sc_thermal.c | 6 +-
drivers/thermal/thermal_core.c | 1 +
drivers/tty/goldfish.c | 20 +-
drivers/tty/serial/pch_uart.c | 27 +-
drivers/tty/tty_buffer.c | 3 +-
drivers/usb/core/hcd.c | 29 +-
drivers/usb/core/quirks.c | 3 +
drivers/usb/dwc3/gadget.c | 6 +-
drivers/usb/host/xhci-pci.c | 2 +
drivers/usb/isp1760/isp1760-core.c | 8 +
drivers/usb/serial/option.c | 2 +
drivers/usb/serial/pl2303.c | 3 +
drivers/vdpa/vdpa_sim/vdpa_sim.c | 5 +-
drivers/video/console/sticon.c | 5 +-
drivers/video/console/sticore.c | 32 +-
drivers/video/fbdev/amba-clcd.c | 5 +-
drivers/video/fbdev/core/fbcon.c | 5 +-
drivers/video/fbdev/sticore.h | 3 +
drivers/video/fbdev/stifb.c | 4 +-
drivers/video/fbdev/vesafb.c | 5 +-
fs/afs/misc.c | 5 +-
fs/afs/rotate.c | 4 +
fs/afs/rxrpc.c | 8 +-
fs/afs/write.c | 1 +
fs/binfmt_flat.c | 27 +-
fs/btrfs/disk-io.c | 4 +-
fs/btrfs/extent_io.c | 21 +-
fs/btrfs/volumes.c | 8 +-
fs/cifs/cifsfs.c | 10 +-
fs/cifs/smb2inode.c | 2 -
fs/cifs/smb2ops.c | 9 +-
fs/dax.c | 3 +-
fs/dlm/lock.c | 11 +-
fs/dlm/lowcomms.c | 2 +-
fs/dlm/plock.c | 12 +-
fs/exportfs/expfs.c | 5 +-
fs/ext4/ext4.h | 6 -
fs/ext4/extents.c | 20 +-
fs/ext4/inline.c | 12 +
fs/ext4/inode.c | 13 +-
fs/ext4/mballoc.c | 18 +-
fs/ext4/namei.c | 84 ++-
fs/ext4/super.c | 24 +-
fs/f2fs/checkpoint.c | 2 +-
fs/f2fs/dir.c | 3 +-
fs/f2fs/f2fs.h | 31 +-
fs/f2fs/file.c | 26 +-
fs/f2fs/hash.c | 11 +-
fs/f2fs/inline.c | 31 +-
fs/f2fs/inode.c | 21 +-
fs/f2fs/namei.c | 37 +-
fs/f2fs/recovery.c | 6 +-
fs/f2fs/segment.c | 42 +-
fs/f2fs/segment.h | 33 +-
fs/f2fs/super.c | 22 +-
fs/f2fs/verity.c | 2 +-
fs/f2fs/xattr.c | 2 +-
fs/fat/fatent.c | 7 +-
fs/fs-writeback.c | 13 +-
fs/gfs2/quota.c | 32 +-
fs/hugetlbfs/inode.c | 4 +-
fs/iomap/buffered-io.c | 3 +-
fs/jfs/jfs_dmap.c | 3 +-
fs/ksmbd/connection.c | 2 +-
fs/ksmbd/smb2misc.c | 2 +-
fs/ksmbd/smb_common.c | 4 +-
fs/namei.c | 70 +-
fs/nfs/file.c | 50 +-
fs/nfs/getroot.c | 17 +-
fs/nfs/inode.c | 25 +-
fs/nfs/internal.h | 9 -
fs/nfs/nfs4proc.c | 41 +-
fs/nfs/nfs4state.c | 2 +-
fs/nfs/pagelist.c | 3 +
fs/nfs/pnfs.c | 6 +-
fs/nfs/unlink.c | 8 +
fs/nfs/write.c | 54 +-
fs/nfsd/nfscache.c | 2 +-
fs/notify/fdinfo.c | 11 +-
fs/notify/inotify/inotify.h | 12 +
fs/notify/inotify/inotify_user.c | 2 +-
fs/notify/mark.c | 6 +-
fs/ntfs3/file.c | 12 +-
fs/ntfs3/frecord.c | 10 +-
fs/ntfs3/fslog.c | 12 +-
fs/ntfs3/inode.c | 8 +-
fs/ntfs3/xattr.c | 112 ++-
fs/ocfs2/dlmfs/userdlm.c | 16 +-
fs/proc/generic.c | 3 +
fs/proc/proc_net.c | 3 +
include/drm/drm_edid.h | 6 +-
include/linux/blk_types.h | 5 +-
include/linux/bpf.h | 2 +
include/linux/compat.h | 1 +
include/linux/efi.h | 2 +
include/linux/fwnode.h | 10 +-
include/linux/goldfish.h | 15 +-
include/linux/gpio/driver.h | 12 +
include/linux/kexec.h | 46 +-
include/linux/list.h | 40 +-
include/linux/mailbox_controller.h | 1 +
include/linux/mtd/cfi.h | 1 +
include/linux/namei.h | 6 +
include/linux/nfs_fs.h | 13 +
include/linux/nfs_fs_sb.h | 1 +
include/linux/nodemask.h | 13 +-
include/linux/platform_data/cros_ec_proto.h | 3 +
include/linux/ptp_classify.h | 3 +
include/linux/ptrace.h | 7 -
include/linux/sched/signal.h | 2 +-
include/linux/usb/hcd.h | 2 +
include/net/if_inet6.h | 8 +
include/scsi/libfcoe.h | 3 +-
include/scsi/libiscsi.h | 6 +-
include/sound/jack.h | 1 +
include/trace/events/rxrpc.h | 2 +-
include/trace/events/vmscan.h | 4 +-
include/uapi/asm-generic/siginfo.h | 7 +
include/uapi/linux/landlock.h | 9 +-
init/Kconfig | 5 +
ipc/mqueue.c | 14 +
kernel/dma/debug.c | 2 +-
kernel/dma/direct.c | 125 ++--
kernel/events/core.c | 4 +-
kernel/kexec_file.c | 34 -
kernel/printk/printk.c | 63 +-
kernel/ptrace.c | 5 +-
kernel/rcu/Kconfig | 1 +
kernel/rcu/tasks.h | 3 +
kernel/scftorture.c | 5 +-
kernel/sched/core.c | 6 +-
kernel/sched/deadline.c | 5 +-
kernel/sched/fair.c | 8 +-
kernel/sched/pelt.h | 4 +-
kernel/sched/psi.c | 15 +-
kernel/sched/rt.c | 5 +-
kernel/sched/sched.h | 32 +-
kernel/signal.c | 18 +-
kernel/trace/ftrace.c | 5 +-
kernel/trace/trace_boot.c | 2 +-
kernel/trace/trace_events_hist.c | 3 +
lib/kunit/debugfs.c | 2 +-
lib/list-test.c | 19 +
mm/cma.c | 4 +-
mm/compaction.c | 2 +
mm/hugetlb.c | 9 +-
mm/memremap.c | 2 +-
mm/page_alloc.c | 4 +-
net/bluetooth/hci_event.c | 15 +-
net/bluetooth/hci_request.c | 2 +
net/bluetooth/sco.c | 21 +-
net/core/dev.c | 8 +-
net/ipv6/addrconf.c | 33 +-
net/mac80211/chan.c | 7 +-
net/mac80211/ieee80211_i.h | 5 +
net/mac80211/rc80211_minstrel_ht.c | 3 +
net/mac80211/scan.c | 20 +
net/mptcp/pm_netlink.c | 2 +
net/nfc/core.c | 1 +
net/rxrpc/ar-internal.h | 13 +-
net/rxrpc/call_event.c | 7 +-
net/rxrpc/conn_object.c | 2 +-
net/rxrpc/input.c | 58 +-
net/rxrpc/output.c | 20 +-
net/rxrpc/recvmsg.c | 8 +-
net/rxrpc/sendmsg.c | 6 +
net/rxrpc/sysctl.c | 4 +-
net/sctp/input.c | 4 +-
net/smc/af_smc.c | 2 +-
net/wireless/nl80211.c | 4 +-
net/wireless/reg.c | 4 +
samples/bpf/Makefile | 9 +-
samples/landlock/sandboxer.c | 104 +--
scripts/faddr2line | 150 ++--
security/integrity/ima/Kconfig | 14 +-
.../integrity/platform_certs/keyring_handler.h | 8 +
security/integrity/platform_certs/load_uefi.c | 33 +
security/landlock/cred.c | 4 +-
security/landlock/cred.h | 8 +-
security/landlock/fs.c | 191 ++++--
security/landlock/fs.h | 11 +-
security/landlock/limits.h | 8 +-
security/landlock/object.c | 6 +-
security/landlock/object.h | 6 +-
security/landlock/ptrace.c | 10 +-
security/landlock/ruleset.c | 84 +--
security/landlock/ruleset.h | 35 +-
security/landlock/syscalls.c | 95 +--
sound/core/jack.c | 34 +-
sound/core/pcm_memory.c | 3 +-
sound/pci/hda/patch_realtek.c | 21 +-
sound/soc/atmel/atmel-classd.c | 1 -
sound/soc/atmel/atmel-pdmic.c | 1 -
sound/soc/codecs/Kconfig | 2 -
sound/soc/codecs/max98090.c | 6 +-
sound/soc/codecs/rk3328_codec.c | 2 +-
sound/soc/codecs/rt5514.c | 2 +-
sound/soc/codecs/rt5645.c | 7 +-
sound/soc/codecs/tscs454.c | 12 +-
sound/soc/codecs/wm2000.c | 6 +-
sound/soc/fsl/fsl-asoc-card.c | 3 +-
sound/soc/fsl/imx-card.c | 17 +-
sound/soc/fsl/imx-hdmi.c | 1 +
sound/soc/fsl/imx-sgtl5000.c | 18 +-
sound/soc/fsl/imx-spdif.c | 4 +-
sound/soc/intel/boards/bytcr_rt5640.c | 12 +
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9 +-
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5 +-
sound/soc/mxs/mxs-saif.c | 1 +
sound/soc/samsung/aries_wm8994.c | 17 +-
sound/soc/samsung/arndale.c | 5 +-
sound/soc/samsung/littlemill.c | 5 +-
sound/soc/samsung/lowland.c | 5 +-
sound/soc/samsung/odroid.c | 4 +-
sound/soc/samsung/smdk_wm8994.c | 4 +-
sound/soc/samsung/smdk_wm8994pcm.c | 4 +-
sound/soc/samsung/snow.c | 9 +-
sound/soc/samsung/speyside.c | 5 +-
sound/soc/samsung/tm2_wm5110.c | 3 +-
sound/soc/samsung/tobermory.c | 5 +-
sound/soc/sh/rcar/core.c | 15 +-
sound/soc/sh/rcar/dma.c | 9 +-
sound/soc/sh/rcar/rsnd.h | 2 +-
sound/soc/sh/rcar/src.c | 7 +-
sound/soc/sh/rcar/ssi.c | 14 +-
sound/soc/sh/rcar/ssiu.c | 11 +-
sound/soc/sh/rz-ssi.c | 29 +-
sound/soc/soc-dapm.c | 2 -
sound/soc/ti/j721e-evm.c | 44 +-
sound/usb/implicit.c | 10 +-
sound/usb/midi.c | 3 +
sound/usb/quirks.c | 6 +
sound/usb/usbaudio.h | 6 +
.../test-libbpf-btf__load_from_kernel_by_id.c | 5 +-
tools/lib/bpf/libbpf.c | 20 +-
tools/objtool/check.c | 9 +-
tools/objtool/elf.c | 198 ++++--
tools/objtool/include/objtool/elf.h | 4 +-
tools/perf/Makefile.config | 39 +-
tools/perf/builtin-c2c.c | 6 +-
tools/perf/pmu-events/jevents.c | 2 +-
tools/perf/util/data.h | 1 +
tools/power/x86/turbostat/turbostat.c | 1 +
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/arm64/bti/Makefile | 4 +-
tools/testing/selftests/bpf/Makefile | 2 +-
.../bpf/progs/btf_dump_test_case_syntax.c | 2 +-
tools/testing/selftests/bpf/progs/profiler.inc.h | 5 +-
.../selftests/bpf/test_bpftool_synctypes.py | 2 +-
tools/testing/selftests/cgroup/test_stress.sh | 2 +-
tools/testing/selftests/landlock/base_test.c | 177 +++--
tools/testing/selftests/landlock/common.h | 66 +-
tools/testing/selftests/landlock/fs_test.c | 753 ++++++++++++++-------
tools/testing/selftests/landlock/ptrace_test.c | 40 +-
tools/testing/selftests/resctrl/fill_buf.c | 4 +-
712 files changed, 6875 insertions(+), 3892 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.10 257/452] net/smc: postpone sk_refcnt increment in connect()
2022-06-07 16:57 1% [PATCH 5.10 000/452] 5.10.121-rc1 review Greg Kroah-Hartman
@ 2022-06-07 17:01 7% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-06-07 17:01 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, liuyacan, David S. Miller, Sasha Levin
From: liuyacan <liuyacan@corp.netease.com>
[ Upstream commit 75c1edf23b95a9c66923d9269d8e86e4dbde151f ]
Same trigger condition as commit 86434744. When setsockopt runs
in parallel to a connect(), and switch the socket into fallback
mode. Then the sk_refcnt is incremented in smc_connect(), but
its state stay in SMC_INIT (NOT SMC_ACTIVE). This cause the
corresponding sk_refcnt decrement in __smc_release() will not be
performed.
Fixes: 86434744fedf ("net/smc: add fallback check to connect()")
Signed-off-by: liuyacan <liuyacan@corp.netease.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/smc/af_smc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 35db3260e8d5..5d7710dd9514 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1118,9 +1118,9 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
if (rc && rc != -EINPROGRESS)
goto out;
- sock_hold(&smc->sk); /* sock put in passive closing */
if (smc->use_fallback)
goto out;
+ sock_hold(&smc->sk); /* sock put in passive closing */
if (flags & O_NONBLOCK) {
if (queue_work(smc_hs_wq, &smc->connect_work))
smc->connect_nonblock = 1;
--
2.35.1
^ permalink raw reply related [relevance 7%]
* [PATCH 5.10 000/452] 5.10.121-rc1 review
@ 2022-06-07 16:57 1% Greg Kroah-Hartman
2022-06-07 17:01 7% ` [PATCH 5.10 257/452] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2022-06-07 16:57 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, torvalds, akpm, linux, shuah,
patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, slade
This is the start of the stable review cycle for the 5.10.121 release.
There are 452 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 09 Jun 2022 16:48:02 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.121-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.121-rc1
Jia-Ju Bai <baijiaju1990@gmail.com>
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
Eric Biggers <ebiggers@google.com>
ext4: only allow test_dummy_encryption when supported
Maciej W. Rozycki <macro@orcam.me.uk>
MIPS: IP30: Remove incorrect `cpu_has_fpu' override
Maciej W. Rozycki <macro@orcam.me.uk>
MIPS: IP27: Remove incorrect `cpu_has_fpu' override
Xiao Yang <yangx.jy@fujitsu.com>
RDMA/rxe: Generate a completion for unsupported/invalid opcode
Jason A. Donenfeld <Jason@zx2c4.com>
Revert "random: use static branch for crng_ready()"
Jan Kara <jack@suse.cz>
block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
Jan Kara <jack@suse.cz>
bfq: Make sure bfqg for which we are queueing requests is online
Jan Kara <jack@suse.cz>
bfq: Get rid of __bio_blkcg() usage
Jan Kara <jack@suse.cz>
bfq: Remove pointless bfq_init_rq() calls
Jan Kara <jack@suse.cz>
bfq: Drop pointless unlock-lock pair
Jan Kara <jack@suse.cz>
bfq: Avoid merging queues with different parents
Daniel Lezcano <daniel.lezcano@linaro.org>
thermal/core: Fix memory leak in the error path
Ziyang Xuan <william.xuanziyang@huawei.com>
thermal/core: fix a UAF bug in __thermal_cooling_device_register()
Waiman Long <longman@redhat.com>
kseltest/cgroup: Make test_stress.sh work if run interactively
Dave Chinner <dchinner@redhat.com>
xfs: assert in xfs_btree_del_cursor should take into account error
Brian Foster <bfoster@redhat.com>
xfs: consider shutdown in bmapbt cursor delete assert
Darrick J. Wong <djwong@kernel.org>
xfs: force log and push AIL to clear pinned inodes when aborting mount
Brian Foster <bfoster@redhat.com>
xfs: restore shutdown check in mapped write fault path
Darrick J. Wong <djwong@kernel.org>
xfs: fix incorrect root dquot corruption error when switching group/project quota types
Darrick J. Wong <djwong@kernel.org>
xfs: fix chown leaking delalloc quota blocks when fssetxattr fails
Brian Foster <bfoster@redhat.com>
xfs: sync lazy sb accounting on quiesce of read-only mounts
Jeffrey Mitchell <jeffrey.mitchell@starlab.io>
xfs: set inode size after creating symlink
Alex Elder <elder@linaro.org>
net: ipa: fix page free in ipa_endpoint_replenish_one()
Alex Elder <elder@linaro.org>
net: ipa: fix page free in ipa_endpoint_trans_release()
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix reset-controller leak on probe errors
Mao Jinlong <quic_jinlmao@quicinc.com>
coresight: core: Fix coresight device probe failure issue
Tejun Heo <tj@kernel.org>
blk-iolatency: Fix inflight count imbalances and IO hangs on offline
Eugenio Pérez <eperezma@redhat.com>
vdpasim: allow to enable a vq repeatedly
Dinh Nguyen <dinguyen@kernel.org>
dt-bindings: gpio: altera: correct interrupt-cells
Akira Yokosawa <akiyks@gmail.com>
docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
Steve French <stfrench@microsoft.com>
SMB3: EBADF/EIO errors in rename/open caused by race condition in smb2_compound_op
Arnd Bergmann <arnd@arndb.de>
ARM: pxa: maybe fix gpio lookup tables
Jonathan Bakker <xc-racer2@live.ca>
ARM: dts: s5pv210: Remove spi-cs-high on panel in Aries
Johan Hovold <johan+linaro@kernel.org>
phy: qcom-qmp: fix struct clk leak on probe errors
Kathiravan T <quic_kathirav@quicinc.com>
arm64: dts: qcom: ipq8074: fix the sleep clock frequency
Xiaomeng Tong <xiam0nd.tong@gmail.com>
gma500: fix an incorrect NULL check on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
Jiri Slaby <jirislaby@kernel.org>
serial: pch: don't overwrite xmit->buf[0] by x_char
Coly Li <colyli@suse.de>
bcache: avoid journal no-space deadlock by reserving 1 journal bucket
Coly Li <colyli@suse.de>
bcache: remove incremental dirty sector counting for bch_sectors_dirty_init()
Coly Li <colyli@suse.de>
bcache: improve multithreaded bch_sectors_dirty_init()
Coly Li <colyli@suse.de>
bcache: improve multithreaded bch_btree_check()
Xiaomeng Tong <xiam0nd.tong@gmail.com>
stm: ltdc: fix two incorrect NULL checks on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
carl9170: tx: fix an incorrect use of list iterator
Mark Brown <broonie@kernel.org>
ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
Alexander Wetzel <alexander@wetzel-home.de>
rtl818x: Prevent using not initialized queues
Yi Yang <yiyang13@huawei.com>
xtensa/simdisk: fix proc_read_simdisk()
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix huge_pmd_unshare address update
Christophe de Dinechin <dinechin@redhat.com>
nodemask.h: fix compilation error with GCC12
Xiaomeng Tong <xiam0nd.tong@gmail.com>
iommu/msm: Fix an incorrect NULL check on list iterator
Song Liu <song@kernel.org>
ftrace: Clean up hash direct_functions on register failures
Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
Vincent Whitchurch <vincent.whitchurch@axis.com>
um: Fix out-of-bounds read in LDT setup
Johannes Berg <johannes.berg@intel.com>
um: chan_user: Fix winch_tramp() return value
Felix Fietkau <nbd@nbd.name>
mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
Dimitri John Ledkov <dimitri.ledkov@canonical.com>
cfg80211: declare MODULE_FIRMWARE for regulatory.db
Max Filippov <jcmvbkbc@gmail.com>
irqchip: irq-xtensa-mx: fix initial IRQ affinity
Pali Rohár <pali@kernel.org>
irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x
Guo Ren <guoren@linux.alibaba.com>
csky: patch_text: Fixup last cpu should be master
Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
RDMA/hfi1: Fix potential integer multiplication overflow errors
Sean Christopherson <seanjc@google.com>
Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
GUO Zihua <guozihua@huawei.com>
ima: remove the IMA_TEMPLATE Kconfig option
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Add more H264 levels for CODA960
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: coda: Fix reported H264 profile
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
Tokunori Ikegami <ikegami.t@gmail.com>
mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in md_reload_sb
Xiaomeng Tong <xiam0nd.tong@gmail.com>
md: fix an incorrect NULL check in does_sb_need_changing
Jani Nikula <jani.nikula@intel.com>
drm/i915/dsi: fix VBT send packet port selection for ICL+
Brian Norris <briannorris@chromium.org>
drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
Xiaomeng Tong <xiam0nd.tong@gmail.com>
drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator
Xiaomeng Tong <xiam0nd.tong@gmail.com>
drm/nouveau/clk: Fix an incorrect NULL check on list iterator
Lucas Stach <l.stach@pengutronix.de>
drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
Dave Airlie <airlied@redhat.com>
drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
Xiaomeng Tong <xiam0nd.tong@gmail.com>
scsi: dc395x: Fix a missing check on list iterator
Junxiao Bi via Ocfs2-devel <ocfs2-devel@oss.oracle.com>
ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
Alexander Aring <aahringo@redhat.com>
dlm: fix missing lkb refcount handling
Alexander Aring <aahringo@redhat.com>
dlm: fix plock invalid read
Nico Boehr <nrb@linux.ibm.com>
s390/perf: obtain sie_block from the right address
Rei Yamamoto <yamamoto.rei@jp.fujitsu.com>
mm, compaction: fast_find_migrateblock() should return pfn in the target zone
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix unbalanced PHY init on probe errors
Johan Hovold <johan+linaro@kernel.org>
PCI: qcom: Fix runtime PM imbalance on probe errors
Bjorn Helgaas <bhelgaas@google.com>
PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
tracing: Fix potential double free in create_var_ref()
Sakari Ailus <sakari.ailus@linux.intel.com>
ACPI: property: Release subnode properties with data nodes
Jan Kara <jack@suse.cz>
ext4: avoid cycles in directory h-tree
Jan Kara <jack@suse.cz>
ext4: verify dir block before splitting it
Baokun Li <libaokun1@huawei.com>
ext4: fix bug_on in __es_tree_search
Theodore Ts'o <tytso@mit.edu>
ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state
Ye Bin <yebin10@huawei.com>
ext4: fix bug_on in ext4_writepages
Ye Bin <yebin10@huawei.com>
ext4: fix warning in ext4_handle_inode_extension
Ye Bin <yebin10@huawei.com>
ext4: fix use-after-free in ext4_rename_dir_prepare
Jan Kara <jack@suse.cz>
bfq: Track whether bfq_group is still online
Jan Kara <jack@suse.cz>
bfq: Update cgroup information before merging bio
Jan Kara <jack@suse.cz>
bfq: Split shared queues on move between cgroups
Aditya Garg <gargaditya08@live.com>
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
Zhihao Cheng <chengzhihao1@huawei.com>
fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages
Emmanuel Grumbach <emmanuel.grumbach@intel.com>
iwlwifi: mvm: fix assert 1F04 upon reconfig
Johannes Berg <johannes.berg@intel.com>
wifi: mac80211: fix use-after-free in chanctx code
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check for inline inode
Chao Yu <chao@kernel.org>
f2fs: fix fallocate to use file_modified to update permissions consistently
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on total_data_blocks
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: don't need inode lock for system hidden quota
Chao Yu <chao@kernel.org>
f2fs: fix deadloop in foreground GC
Chao Yu <chao@kernel.org>
f2fs: fix to clear dirty inode in f2fs_evict_inode()
Chao Yu <chao@kernel.org>
f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
Chao Yu <chao@kernel.org>
f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
Zhengjun Xing <zhengjun.xing@linux.intel.com>
perf jevents: Fix event syntax error caused by ExtSel
Leo Yan <leo.yan@linaro.org>
perf c2c: Use stdio interface if slang is not supported
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
i2c: rcar: fix PM ref counts in probe error paths
Tali Perry <tali.perry1@gmail.com>
i2c: npcm: Handle spurious interrupts
Tyrone Ting <kfting@nuvoton.com>
i2c: npcm: Correct register access width
Tali Perry <tali.perry1@gmail.com>
i2c: npcm: Fix timeout calculation
Joerg Roedel <jroedel@suse.de>
iommu/amd: Increase timeout waiting for GA log enablement
Amelie Delaunay <amelie.delaunay@foss.st.com>
dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler()
Amelie Delaunay <amelie.delaunay@st.com>
dmaengine: stm32-mdma: rework interrupt handler
Amelie Delaunay <amelie.delaunay@foss.st.com>
dmaengine: stm32-mdma: remove GISR1 register
Miaoqian Lin <linmq006@gmail.com>
video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Don't report errors from nfs_pageio_complete() more than once
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report flush errors in nfs_write_end()
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: fsync() should report filesystem errors over EINTR/ERESTARTSYS
Trond Myklebust <trond.myklebust@hammerspace.com>
NFS: Do not report EINTR/ERESTARTSYS as mapping errors
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: idxd: Fix the error handling path in idxd_cdev_register()
Nathan Chancellor <nathan@kernel.org>
i2c: at91: Initialize dma_buf in at91_twi_xfer()
Guenter Roeck <linux@roeck-us.net>
MIPS: Loongson: Use hwmon_device_register_with_groups() to register hwmon
Rex-BC Chen <rex-bc.chen@mediatek.com>
cpufreq: mediatek: Unregister platform device on exit
Jia-Wei Chang <jia-wei.chang@mediatek.com>
cpufreq: mediatek: Use module_init and add module_exit
Qinglang Miao <miaoqinglang@huawei.com>
cpufreq: mediatek: add missing platform_driver_unregister() on error in mtk_cpufreq_driver_init
Michael Walle <michael@walle.cc>
i2c: at91: use dma safe buffers
Yong Wu <yong.wu@mediatek.com>
iommu/mediatek: Add list_del in mtk_iommu_remove
Jakob Koschel <jakobkoschel@gmail.com>
f2fs: fix dereference of stale list iterator after loop body
Dan Carpenter <dan.carpenter@oracle.com>
OPP: call of_node_put() on error path in _bandwidth_supported()
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: stmfts - do not leave device disabled in stmfts_input_open
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent use of lock before it is initialized
Björn Ardö <bjorn.ardo@axis.com>
mailbox: forward the hrtimer if not queued and under a lock
Yang Yingliang <yangyingliang@huawei.com>
mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
Miaoqian Lin <linmq006@gmail.com>
powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
Randy Dunlap <rdunlap@infradead.org>
macintosh: via-pmu and via-cuda need RTC_LIB
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf: Fix the threshold compare group constraint for power9
Michael Ellerman <mpe@ellerman.id.au>
powerpc/64: Only WARN if __pa()/__va() called with bad addresses
Yang Yingliang <yangyingliang@huawei.com>
hwrng: omap3-rom - fix using wrong clk_disable() in omap_rom_rng_runtime_resume()
Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
PCI/AER: Clear MULTI_ERR_COR/UNCOR_RCV bits
Miaoqian Lin <linmq006@gmail.com>
Input: sparcspkr - fix refcount leak in bbc_beep_probe
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
crypto: cryptd - Protect per-CPU resource by disabling BH.
Corentin Labbe <clabbe@baylibre.com>
crypto: sun8i-ss - handle zero sized sg
Corentin Labbe <clabbe@baylibre.com>
crypto: sun8i-ss - rework handling of IV
Qi Zheng <zhengqi.arch@bytedance.com>
tty: fix deadlock caused by calling printk() under tty_port->lock
Francesco Dolcini <francesco.dolcini@toradex.com>
PCI: imx6: Fix PERST# start-up sequence
Waiman Long <longman@redhat.com>
ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
Alexey Dobriyan <adobriyan@gmail.com>
proc: fix dentry/inode overinstantiating under /proc/${pid}/net
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: atmel-classd: Remove endianness flag on class d component
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: atmel-pdmic: Remove endianness flag on pdmic component
Randy Dunlap <rdunlap@infradead.org>
powerpc/4xx/cpm: Fix return value of __setup() handler
Randy Dunlap <rdunlap@infradead.org>
powerpc/idle: Fix return value of __setup() handler
Yang Yingliang <yangyingliang@huawei.com>
pinctrl: renesas: core: Fix possible null-ptr-deref in sh_pfc_map_resources()
Randy Dunlap <rdunlap@infradead.org>
powerpc/8xx: export 'cpm_setbrg' for modules
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
drivers/base/memory: fix an unlikely reference counting issue in __add_memory_block()
Muchun Song <songmuchun@bytedance.com>
dax: fix cache flush on PMD-mapped pages
Miaohe Lin <linmiaohe@huawei.com>
drivers/base/node.c: fix compaction sysfs file leak
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
pinctrl: mvebu: Fix irq_of_parse_and_map() return value
Dan Williams <dan.j.williams@intel.com>
nvdimm: Allow overwrite in the presence of disabled dimms
Dan Williams <dan.j.williams@intel.com>
nvdimm: Fix firmware activation deadlock scenarios
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix list protocols enumeration in the base protocol
Gustavo A. R. Silva <gustavoars@kernel.org>
scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
Lv Ruyi <lv.ruyi@zte.com.cn>
mfd: ipaq-micro: Fix error check return value of platform_get_irq()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: fix PT_LOAD segment for boot memory area
Chuanhong Guo <gch981213@gmail.com>
arm: mediatek: select arch timer for mt7629
Stefan Wahren <stefan.wahren@i2se.com>
pinctrl: bcm2835: implement hook for missing gpio-ranges
Stefan Wahren <stefan.wahren@i2se.com>
gpiolib: of: Introduce hook for missing gpio-ranges
Corentin Labbe <clabbe@baylibre.com>
crypto: marvell/cesa - ECB does not IV
Hangyu Hua <hbh25y@gmail.com>
misc: ocxl: fix possible double free in ocxl_file_register_afu
Stefan Wahren <stefan.wahren@i2se.com>
ARM: dts: bcm2835-rpi-b: Fix GPIO line names
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
Phil Elwell <phil@raspberrypi.com>
ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
Marek Vasut <marex@denx.de>
ARM: dts: stm32: Fix PHY post-reset delay on Avenger96
Marc Kleine-Budde <mkl@pengutronix.de>
can: xilinx_can: mark bit timing constants as const
Guenter Roeck <linux@roeck-us.net>
platform/chrome: Re-introduce cros_ec_cmd_xfer and use it for ioctls
Max Krummenacher <max.krummenacher@toradex.com>
ARM: dts: imx6dl-colibri: Fix I2C pinmuxing
Tzung-Bi Shih <tzungbi@kernel.org>
platform/chrome: cros_ec: fix error handling in cros_ec_register()
Sean Christopherson <seanjc@google.com>
KVM: nVMX: Clear IDT vectoring on nested VM-Exit for double/triple fault
Sean Christopherson <seanjc@google.com>
KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
Bjorn Andersson <bjorn.andersson@linaro.org>
soc: qcom: llcc: Add MODULE_DEVICE_TABLE()
Thorsten Scherer <t.scherer@eckelmann.de>
ARM: dts: ci4x10: Adapt to changes in imx6qdl.dtsi regarding fec clocks
Jiantao Zhang <water.zhangjiantao@huawei.com>
PCI: dwc: Fix setting error return on MSI DMA mapping failure
Dan Carpenter <dan.carpenter@oracle.com>
PCI: rockchip: Fix find_first_zero_bit() limit
Dan Carpenter <dan.carpenter@oracle.com>
PCI: cadence: Fix find_first_zero_bit() limit
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
Miaoqian Lin <linmq006@gmail.com>
soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
Andre Przywara <andre.przywara@arm.com>
ARM: dts: suniv: F1C100: fix watchdog compatible
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
memory: samsung: exynos5422-dmc: Avoid some over memory allocation
Shawn Lin <shawn.lin@rock-chips.com>
arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
liuyacan <liuyacan@corp.netease.com>
net/smc: postpone sk_refcnt increment in connect()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hinic: Avoid some over memory allocation
Gustavo A. R. Silva <gustavoars@kernel.org>
net: huawei: hinic: Use devm_kcalloc() instead of devm_kzalloc()
David Howells <dhowells@redhat.com>
rxrpc: Fix decision on when to generate an IDLE ACK
David Howells <dhowells@redhat.com>
rxrpc: Don't let ack.previousPacket regress
David Howells <dhowells@redhat.com>
rxrpc: Fix overlapping ACK accounting
David Howells <dhowells@redhat.com>
rxrpc: Don't try to resend the request if we're receiving the reply
David Howells <dhowells@redhat.com>
rxrpc: Fix listen() setting the bar too high for the prealloc rings
Yongzhi Liu <lyz_cs@pku.edu.cn>
hv_netvsc: Fix potential dereference of NULL pointer
Jakub Kicinski <kuba@kernel.org>
net: stmmac: fix out-of-bounds access in a selftest
Gustavo A. R. Silva <gustavoars@kernel.org>
net: stmmac: selftests: Use kcalloc() instead of kzalloc()
Alexey Khoroshilov <khoroshilov@ispras.ru>
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
Duoming Zhou <duoming@zju.edu.cn>
NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
Yang Yingliang <yangyingliang@huawei.com>
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
Miaoqian Lin <linmq006@gmail.com>
thermal/drivers/imx_sc_thermal: Fix refcount leak in imx_sc_thermal_probe
Yang Yingliang <yangyingliang@huawei.com>
thermal/core: Fix memory leak in __thermal_cooling_device_register()
Daniel Lezcano <daniel.lezcano@linaro.org>
thermal/drivers/core: Use a char pointer for the cooling device name
Zheng Yongjun <zhengyongjun3@huawei.com>
thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
Stefan Wahren <stefan.wahren@i2se.com>
thermal/drivers/bcm2711: Don't clamp temperature at zero
Nathan Chancellor <nathan@kernel.org>
drm/i915: Fix CFI violation with show_dynamic_id()
Abhinav Kumar <quic_abhinavk@quicinc.com>
drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path
Lai Jiangshan <jiangshan.ljs@antgroup.com>
x86/sev: Annotate stack change in the #VC handler
Hangyu Hua <hbh25y@gmail.com>
drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
Miaoqian Lin <linmq006@gmail.com>
drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
Eric Biggers <ebiggers@google.com>
ext4: reject the 'commit' option on ext2 filesystems
Jonas Karlman <jonas@kwiboo.se>
media: rkvdec: h264: Fix bit depth wrap in pps packet
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: rkvdec: h264: Fix dpb_valid implementation
Nicolas Dufresne <nicolas.dufresne@collabora.com>
media: rkvdec: Stop overclocking the decoder
Cai Huoqing <caihuoqing@baidu.com>
media: staging: media: rkvdec: Make use of the helper function devm_platform_ioremap_resource()
Dongliang Mu <mudongliangabcd@gmail.com>
media: ov7670: remove ov7670_power_off from ov7670_remove
Miaoqian Lin <linmq006@gmail.com>
ASoC: ti: j721e-evm: Fix refcount leak in j721e_soc_probe_*
Zheng Bin <zhengbin13@huawei.com>
net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init
Eric Dumazet <edumazet@google.com>
sctp: read sk->sk_bound_dev_if once in sctp_rcv()
Paul Moore <paul@paul-moore.com>
lsm,selinux: pass flowi_common instead of flowi to the LSM hooks
Geert Uytterhoeven <geert@linux-m68k.org>
m68k: math-emu: Fix dependencies of math emulation support
Keith Busch <kbusch@kernel.org>
nvme: set dma alignment to dword
Niels Dossche <dossche.niels@gmail.com>
Bluetooth: use hdev lock for accept_list and reject_list in conn req
Archie Pusaka <apusaka@chromium.org>
Bluetooth: use inclusive language when filtering devices
Archie Pusaka <apusaka@chromium.org>
Bluetooth: use inclusive language in HCI role comments
Sathish Narasimman <sathish.narasimman@intel.com>
Bluetooth: LL privacy allow RPA
Bhaskar Chowdhury <unixbhaskar@gmail.com>
Bluetooth: L2CAP: Rudimentary typo fixes
Howard Chung <howardchung@google.com>
Bluetooth: Interleave with allowlist scan
Ying Hsu <yinghsu@chromium.org>
Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
Michael Rodin <mrodin@de.adit-jv.com>
media: vsp1: Fix offset calculation for plane cropping
Pavel Skripkin <paskripkin@gmail.com>
media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
Miaoqian Lin <linmq006@gmail.com>
media: exynos4-is: Change clk_disable to clk_disable_unprepare
Miaoqian Lin <linmq006@gmail.com>
media: st-delta: Fix PM disable depth imbalance in delta_probe
Miaoqian Lin <linmq006@gmail.com>
media: exynos4-is: Fix PM disable depth imbalance in fimc_is_probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: aspeed: Fix an error handling path in aspeed_video_probe()
Josh Poimboeuf <jpoimboe@kernel.org>
scripts/faddr2line: Fix overlapping text section failures
Phil Auld <pauld@redhat.com>
kselftest/cgroup: fix test_stress.sh to use OUTPUT dir
Miaoqian Lin <linmq006@gmail.com>
ASoC: samsung: Fix refcount leak in aries_audio_probe
Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
ASoC: samsung: Use dev_err_probe() helper
Miaoqian Lin <linmq006@gmail.com>
regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
Miaoqian Lin <linmq006@gmail.com>
ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
Baochen Qiang <quic_bqiang@quicinc.com>
ath11k: Don't check arvif->is_started before sending management frames
Ravi Bangoria <ravi.bangoria@amd.com>
perf/amd/ibs: Use interrupt regs ip for stack unwinding
Konrad Dybcio <konrad.dybcio@somainline.org>
regulator: qcom_smd: Fix up PM8950 regulator configuration
Viresh Kumar <viresh.kumar@linaro.org>
Revert "cpufreq: Fix possible race in cpufreq online error path"
Yang Yingliang <yangyingliang@huawei.com>
spi: spi-fsl-qspi: check return value after calling platform_get_resource_byname()
Andreas Gruenbacher <agruenba@redhat.com>
iomap: iomap_write_failed fix
Xiaomeng Tong <xiam0nd.tong@gmail.com>
media: uvcvideo: Fix missing check to determine if element is found in list
Dan Carpenter <dan.carpenter@oracle.com>
drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected
Jessica Zhang <quic_jesszhan@quicinc.com>
drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: fix event thread stuck in wait_event after kthread_stop()
Zev Weiss <zev@bewilderbeest.net>
regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
Tong Tiangen <tongtiangen@huawei.com>
arm64: fix types in copy_highpage()
Randy Dunlap <rdunlap@infradead.org>
x86/mm: Cleanup the control_va_addr_alignment() __setup handler
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
irqchip/aspeed-scu-ic: Fix irq_of_parse_and_map() return value
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
Daniel Thompson <daniel.thompson@linaro.org>
irqchip/exiu: Fix acknowledgment of edge triggered interrupts
Randy Dunlap <rdunlap@infradead.org>
x86: Fix return value of __setup handlers
Christoph Hellwig <hch@lst.de>
virtio_blk: fix the discard_granularity and discard_alignment queue limits
James Clark <james.clark@arm.com>
perf tools: Use Python devtools for version autodetection rather than runtime
Yang Yingliang <yangyingliang@huawei.com>
drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
Jagan Teki <jagan@amarulasolutions.com>
drm/panel: panel-simple: Fix proper bpc for AM-1280800N3TZQW-T00H
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: add missing include to msm_drv.c
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
Yang Yingliang <yangyingliang@huawei.com>
drm/msm/hdmi: check return value after calling platform_get_resource_byname()
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix error checks and return values for DSI xmit functions
Lv Ruyi <lv.ruyi@zte.com.cn>
drm/msm/dp: fix error check return value of irq_of_parse_and_map()
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dp: stop event kernel thread when DP unbind
Vinod Polimera <quic_vpolimer@quicinc.com>
drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume
Yang Jihong <yangjihong1@huawei.com>
perf tools: Add missing headers needed by util/data.h
Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
ASoC: rk3328: fix disabling mclk on pclk probe failure
Josh Poimboeuf <jpoimboe@redhat.com>
x86/speculation: Add missing prototype for unpriv_ebpf_notify()
Yang Yingliang <yangyingliang@huawei.com>
mtd: rawnand: cadence: fix possible null-ptr-deref in cadence_nand_dt_probe()
Matthieu Baerts <matthieu.baerts@tessares.net>
x86/pm: Fix false positive kmemleak report in msr_build_context()
Chen-Tsung Hsieh <chentsung@chromium.org>
mtd: spi-nor: core: Check written SR value in spi_nor_write_16bit_sr_and_check()
Andrii Nakryiko <andrii@kernel.org>
libbpf: Fix logic for finding matching program for CO-RE relocation
Colin Ian King <colin.i.king@gmail.com>
selftests/resctrl: Fix null pointer dereference on open failed
Kiwoong Kim <kwmad.kim@samsung.com>
scsi: ufs: core: Exclude UECxx from SFR dump list
Bart Van Assche <bvanassche@acm.org>
scsi: ufs: qcom: Fix ufs_qcom_resume()
Kuogee Hsieh <quic_khsieh@quicinc.com>
drm/msm/dpu: adjust display_v_end for eDP and DP
Nuno Sá <nuno.sa@analog.com>
of: overlay: do not break notify on NOTIFY_{OK|STOP}
Amir Goldstein <amir73il@gmail.com>
fsnotify: fix wrong lockdep annotations
Amir Goldstein <amir73il@gmail.com>
inotify: show inotify mask flags in proc fdinfo
Colin Ian King <colin.i.king@gmail.com>
ALSA: pcm: Check for null pointer of pointer substream before dereferencing it
Marek Vasut <marex@denx.de>
drm/panel: simple: Add missing bus flags for Innolux G070Y2-L01
Chen-Yu Tsai <wenst@chromium.org>
media: hantro: Empty encoder capture buffers by default
Dan Carpenter <dan.carpenter@oracle.com>
ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
Schspa Shi <schspa@gmail.com>
cpufreq: Fix possible race in cpufreq online error path
Zheng Yongjun <zhengyongjun3@huawei.com>
spi: img-spfi: Fix pm_runtime_get_sync() error checking
Chengming Zhou <zhouchengming@bytedance.com>
sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
Miaoqian Lin <linmq006@gmail.com>
drm/bridge: Fix error handling in analogix_dp_probe
Miaoqian Lin <linmq006@gmail.com>
HID: elan: Fix potential double free in elan_input_configured
Jonathan Teh <jonathan.teh@outlook.com>
HID: hid-led: fix maximum brightness for Dream Cheeky
Zheyu Ma <zheyuma97@gmail.com>
mtd: rawnand: denali: Use managed device resources
Tyler Hicks <tyhicks@linux.microsoft.com>
EDAC/dmc520: Don't print an error for each unconfigured interrupt line
Arnd Bergmann <arnd@arndb.de>
drbd: fix duplicate array initializer
Christoph Hellwig <hch@lst.de>
target: remove an incorrect unmap zeroes data deduction
Jan Kiszka <jan.kiszka@siemens.com>
efi: Add missing prototype for efi_capsule_setup_info
Lin Ma <linma@zju.edu.cn>
NFC: NULL out the dev->rfkill to prevent UAF
Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
net: dsa: mt7530: 1G can also support 1000BASE-X link mode
Paul E. McKenney <paulmck@kernel.org>
scftorture: Fix distribution of short handler delays
Miaoqian Lin <linmq006@gmail.com>
spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
Jiasheng Jiang <jiasheng@iscas.ac.cn>
drm: mali-dp: potential dereference of null pointer
Zhou Qingyang <zhou1615@umn.edu>
drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
Johannes Berg <johannes.berg@intel.com>
nl80211: show SSID for P2P_GO interfaces
Yuntao Wang <ytcoode@gmail.com>
bpf: Fix excessive memory allocation in stack_map_alloc()
Andrii Nakryiko <andrii@kernel.org>
libbpf: Don't error out on CO-RE relos for overriden weak subprogs
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Force alpha to be 0xff if it's disabled
Maxime Ripard <maxime@cerno.tech>
drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hvs: Reset muxes at probe time
Miles Chen <miles.chen@mediatek.com>
drm/mediatek: Fix mtk_cec_mask()
Paul Cercueil <paul@crapouillou.net>
drm/ingenic: Reset pixclock rate when parent clock rate changes
Ammar Faizi <ammarfaizi2@gnuweeb.org>
x86/delay: Fix the wrong asm constraint in delay_loop()
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
Miaoqian Lin <linmq006@gmail.com>
ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
Kuldeep Singh <singh.kuldeep87k@gmail.com>
spi: qcom-qspi: Add minItems to interconnect-names
Lucas Stach <l.stach@pengutronix.de>
drm/bridge: adv7511: clean up CEC adapter when probe fails
Jani Nikula <jani.nikula@intel.com>
drm/edid: fix invalid EDID extension block filtering
Wenli Looi <wlooi@ucalgary.ca>
ath9k: fix ar9003_get_eepmisc
Niels Dossche <dossche.niels@gmail.com>
ath11k: acquire ab->base_lock in unassign when finding the peer by addr
Noralf Trønnes <noralf@tronnes.org>
dt-bindings: display: sitronix, st7735r: Fix backlight in example
Linus Torvalds <torvalds@linux-foundation.org>
drm: fix EDID struct for old ARM OABI format
Douglas Miller <doug.miller@cornelisnetworks.com>
RDMA/hfi1: Prevent panic when SDMA is disabled
Peng Wu <wupeng58@huawei.com>
powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
Finn Thain <fthain@linux-m68k.org>
macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/powernv: fix missing of_node_put in uv_init()
Lv Ruyi <lv.ruyi@zte.com.cn>
powerpc/xics: fix refcount leak in icp_opal_init()
Haren Myneni <haren@linux.ibm.com>
powerpc/powernv/vas: Assign real address to rx_fifo in vas_rx_win_attr
Vasily Averin <vvs@openvz.org>
tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
Yicong Yang <yangyicong@hisilicon.com>
PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
Peng Wu <wupeng58@huawei.com>
ARM: hisi: Add missing of_node_put after of_find_compatible_node
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
Peng Wu <wupeng58@huawei.com>
ARM: versatile: Add missing of_node_put in dcscb_init
Yang Yingliang <yangyingliang@huawei.com>
pinctrl: renesas: rzn1: Fix possible null-ptr-deref in sh_pfc_map_resources()
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
fat: add ratelimit to fat*_ent_bread()
Hari Bathini <hbathini@linux.ibm.com>
powerpc/fadump: Fix fadump to work with a different endian capture kernel
Janusz Krzysztofik <jmkrzyszt@gmail.com>
ARM: OMAP1: clock: Fix UART rate reporting algorithm
Zixuan Fu <r33s3n6@gmail.com>
fs: jfs: fix possible NULL pointer dereference in dbFree()
QintaoShen <unSimple1993@163.com>
soc: ti: ti_sci_pm_domains: Check for null return of devm_kcalloc
Gilad Ben-Yossef <gilad@benyossef.com>
crypto: ccree - use fine grained DMA mapping dir
Brian Norris <briannorris@chromium.org>
PM / devfreq: rk3399_dmc: Disable edev on remove()
Konrad Dybcio <konrad.dybcio@somainline.org>
arm64: dts: qcom: msm8994: Fix BLSP[12]_DMA channels count
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: s5pv210: align DMA channels with dtschema
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
ARM: dts: ox820: align interrupt controller node name with dtschema
Niels Dossche <dossche.niels@gmail.com>
IB/rdmavt: add missing locks in rvt_ruc_loopback
Bob Peterson <rpeterso@redhat.com>
gfs2: use i_lock spin_lock for inode qadata
Yonghong Song <yhs@fb.com>
selftests/bpf: fix btf_dump/btf_dump due to recent clang change
Jakub Kicinski <kuba@kernel.org>
eth: tg3: silence the GCC 12 array-bounds warning
David Howells <dhowells@redhat.com>
rxrpc, afs: Fix selection of abort codes
David Howells <dhowells@redhat.com>
rxrpc: Return an error to sendmsg if call failed
Geert Uytterhoeven <geert@linux-m68k.org>
m68k: atari: Make Atari ROM port I/O write macros return void
Borislav Petkov <bp@suse.de>
x86/microcode: Add explicit CPU vendor dependency
Vincent Mailhol <mailhol.vincent@wanadoo.fr>
can: mcp251xfd: silence clang's -Wunaligned-access warning
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: rt1015p: remove dependency on GPIOLIB
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: max98357a: remove dependency on GPIOLIB
Kwanghoon Son <k.son@samsung.com>
media: exynos4-is: Fix compile warning
Fabio Estevam <festevam@denx.de>
net: phy: micrel: Allow probing without .driver_data
Xie Yongji <xieyongji@bytedance.com>
nbd: Fix hung on disconnect request if socket is closed before
Lin Ma <linma@zju.edu.cn>
ASoC: rt5645: Fix errorenous cleanup order
Smith, Kyle Miller (Nimble Kernel) <kyles@hpe.com>
nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
Jason A. Donenfeld <Jason@zx2c4.com>
openrisc: start CPU timer early in boot
Hans Verkuil <hverkuil-cisco@xs4all.nl>
media: cec-adap.c: fix is_configuring state
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
media: imon: reorganize serialization
Philipp Zabel <p.zabel@pengutronix.de>
media: coda: limit frame interval enumeration to supported encoder frame sizes
Hangyu Hua <hbh25y@gmail.com>
media: rga: fix possible memory leak in rga_probe
Dongliang Mu <mudongliangabcd@gmail.com>
rtlwifi: Use pr_warn instead of WARN_ONCE
Corey Minyard <cminyard@mvista.com>
ipmi: Fix pr_fmt to avoid compilation issues
Corey Minyard <cminyard@mvista.com>
ipmi:ssif: Check for NULL msg when handling events and messages
Mario Limonciello <mario.limonciello@amd.com>
ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
Mikulas Patocka <mpatocka@redhat.com>
dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
Patrice Chotard <patrice.chotard@foss.st.com>
spi: stm32-qspi: Fix wait_cmd timeout in APM mode
Ravi Bangoria <ravi.bangoria@amd.com>
perf/amd/ibs: Cascade pmu init functions' return value
Heiko Carstens <hca@linux.ibm.com>
s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES
Eric Dumazet <edumazet@google.com>
net: remove two BUG() from skb_checksum_help()
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: tscs454: Add endianness flag in snd_soc_component_driver
Dongliang Mu <mudongliangabcd@gmail.com>
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
Alice Wong <shiwei.wong@amd.com>
drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
Petr Machata <petrm@nvidia.com>
mlxsw: Treat LLDP packets as control
Petr Machata <petrm@nvidia.com>
mlxsw: spectrum_dcb: Do not warn about priority changes
Mark Brown <broonie@kernel.org>
ASoC: dapm: Don't fold register value changes into notifications
Mark Bloch <mbloch@nvidia.com>
net/mlx5: fs, delete the FTE when there are no rules attached to it
jianghaoran <jianghaoran@kylinos.cn>
ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
Lv Ruyi <lv.ruyi@zte.com.cn>
drm: msm: fix error check return value of irq_of_parse_and_map()
Alexandru Elisei <alexandru.elisei@arm.com>
arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
Abhishek Kumar <kuabhs@chromium.org>
ath10k: skip ath10k_halt during suspend for driver state RESTARTING
Evan Quan <evan.quan@amd.com>
drm/amd/pm: fix the compile warning
Steven Price <steven.price@arm.com>
drm/plane: Move range check for format_count earlier
Hans de Goede <hdegoede@redhat.com>
ASoC: Intel: bytcr_rt5640: Add quirk for the HP Pro Tablet 408
Hari Chandrakanthan <quic_haric@quicinc.com>
ath11k: disable spectral scan during spectral deinit
James Smart <jsmart2021@gmail.com>
scsi: lpfc: Fix resource leak in lpfc_sli4_send_seq_to_ulp()
Minghao Chi <chi.minghao@zte.com.cn>
scsi: ufs: Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
Lv Ruyi <lv.ruyi@zte.com.cn>
scsi: megaraid: Fix error check return value of register_chrdev()
Vignesh Raghavendra <vigneshr@ti.com>
drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit
Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
mmc: jz4740: Apply DMA engine limits to maximum segment size
Heming Zhao <heming.zhao@suse.com>
md/bitmap: don't set sb values if can't pass sanity check
Zheyu Ma <zheyuma97@gmail.com>
media: cx25821: Fix the warning when removing the module
Zheyu Ma <zheyuma97@gmail.com>
media: pci: cx23885: Fix the error handling in cx23885_initdev()
Luca Weiss <luca.weiss@fairphone.com>
media: venus: hfi: avoid null dereference in deinit
Thibaut VARÈNE <hacks+kernel@slashdirt.org>
ath9k: fix QCA9561 PA bias level
Keita Suzuki <keitasuzuki.park@sslab.ics.keio.ac.jp>
drm/amd/pm: fix double free in si_parse_power_table()
Len Brown <len.brown@intel.com>
tools/power turbostat: fix ICX DRAM power numbers
Biju Das <biju.das.jz@bp.renesas.com>
spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction
Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
ALSA: jack: Access input_dev under mutex
Haowen Bai <baihaowen@meizu.com>
sfc: ef10: Fix assigning negative value to unsigned variable
Paul E. McKenney <paulmck@kernel.org>
rcu: Make TASKS_RUDE_RCU select IRQ_WORK
Padmanabha Srinivasaiah <treasure4paddy@gmail.com>
rcu-tasks: Fix race in schedule and flush work
Liviu Dudau <liviu.dudau@arm.com>
drm/komeda: return early if drm_universal_plane_init() fails.
Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
ACPICA: Avoid cache flush inside virtual machines
Mike Travis <mike.travis@hpe.com>
x86/platform/uv: Update TSC sync state for UV5
Daniel Vetter <daniel.vetter@ffwll.ch>
fbcon: Consistently protect deferred_takeover with console_lock()
Niels Dossche <dossche.niels@gmail.com>
ipv6: fix locking issues with loops over idev->addr_list
Haowen Bai <baihaowen@meizu.com>
ipw2x00: Fix potential NULL dereference in libipw_xmit()
Haowen Bai <baihaowen@meizu.com>
b43: Fix assigning negative value to unsigned variable
Haowen Bai <baihaowen@meizu.com>
b43legacy: Fix assigning negative value to unsigned variable
Niels Dossche <dossche.niels@gmail.com>
mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
Nikolay Borisov <nborisov@suse.com>
selftests/bpf: Fix vfs_link kprobe definition
Liu Zixian <liuzixian4@huawei.com>
drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
Tejas Upadhyay <tejaskumarx.surendrakumar.upadhyay@intel.com>
iommu/vt-d: Add RPLS to quirk list to skip TE disabling
Qu Wenruo <wqu@suse.com>
btrfs: repair super block num_devices automatically
Qu Wenruo <wqu@suse.com>
btrfs: add "0x" prefix for unsupported optional features
Eric W. Biederman <ebiederm@xmission.com>
ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
Eric W. Biederman <ebiederm@xmission.com>
ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
Eric W. Biederman <ebiederm@xmission.com>
ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
Kan Liang <kan.liang@linux.intel.com>
perf/x86/intel: Fix event constraints for ICL
Ammar Faizi <ammarfaizi2@gnuweeb.org>
x86/MCE/AMD: Fix memory leak when threshold_create_bank() fails
Helge Deller <deller@gmx.de>
parisc/stifb: Keep track of hardware path of graphics card
Peilin Ye <yepeilin.cs@gmail.com>
Fonts: Make font size unsigned in font_desc
Mathias Nyman <mathias.nyman@linux.intel.com>
xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: when extending a file with falloc we should make files not-sparse
Kishon Vijay Abraham I <kishon@ti.com>
usb: core: hcd: Add support for deferring roothub registration
Albert Wang <albertccwang@google.com>
usb: dwc3: gadget: Move null pinter check to proper place
Monish Kumar R <monish.kumar.r@intel.com>
USB: new quirk for Dell Gen 2 devices
Carl Yin(殷张成) <carl.yin@quectel.com>
USB: serial: option: add Quectel BG95 modem
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Cancel pending work at closing a MIDI substream
Marios Levogiannis <marios.levogiannis@gmail.com>
ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
Rik van der Kemp <rik@upto11.nl>
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9520 laptop
Samuel Holland <samuel@sholland.org>
riscv: Fix irq_work when SMP is disabled
Alexandre Ghiti <alexandre.ghiti@canonical.com>
riscv: Initialize thread pointer before calling C functions
Helge Deller <deller@gmx.de>
parisc/stifb: Implement fb_is_primary_device()
Niklas Cassel <niklas.cassel@wdc.com>
binfmt_flat: do not stop relocating GOT entries prematurely on riscv
Stephen Boyd <swboyd@chromium.org>
arm64: Initialize jump labels before setup_machine_fdt()
-------------
Diffstat:
Documentation/conf.py | 2 +-
.../bindings/display/sitronix,st7735r.yaml | 1 +
.../devicetree/bindings/gpio/gpio-altera.txt | 5 +-
.../bindings/spi/qcom,spi-qcom-qspi.yaml | 1 +
Makefile | 4 +-
arch/arm/boot/dts/bcm2835-rpi-b.dts | 13 +-
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts | 22 +-
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 2 +-
arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts | 4 +-
arch/arm/boot/dts/exynos5250-smdk5250.dts | 4 +-
arch/arm/boot/dts/imx6dl-eckelmann-ci4x10.dts | 6 +-
arch/arm/boot/dts/imx6qdl-colibri.dtsi | 6 +-
arch/arm/boot/dts/ox820.dtsi | 2 +-
arch/arm/boot/dts/s5pv210-aries.dtsi | 3 +-
arch/arm/boot/dts/s5pv210.dtsi | 12 +-
arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 1 +
arch/arm/boot/dts/suniv-f1c100s.dtsi | 4 +-
arch/arm/mach-hisi/platsmp.c | 4 +
arch/arm/mach-mediatek/Kconfig | 1 +
arch/arm/mach-omap1/clock.c | 2 +-
arch/arm/mach-pxa/cm-x300.c | 8 +-
arch/arm/mach-pxa/magician.c | 2 +-
arch/arm/mach-pxa/tosa.c | 4 +-
arch/arm/mach-vexpress/dcscb.c | 1 +
arch/arm64/Kconfig.platforms | 1 +
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8994.dtsi | 4 +-
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
arch/arm64/kernel/setup.c | 7 +-
arch/arm64/kernel/sys_compat.c | 2 +-
arch/arm64/mm/copypage.c | 4 +-
arch/csky/kernel/probes/kprobes.c | 2 +-
arch/m68k/Kconfig.cpu | 2 +-
arch/m68k/include/asm/raw_io.h | 6 +-
.../include/asm/mach-ip27/cpu-feature-overrides.h | 1 -
.../include/asm/mach-ip30/cpu-feature-overrides.h | 1 -
arch/openrisc/include/asm/timex.h | 1 +
arch/openrisc/kernel/head.S | 9 +
arch/parisc/include/asm/fb.h | 4 +
arch/powerpc/include/asm/page.h | 7 +-
arch/powerpc/include/asm/vas.h | 2 +-
arch/powerpc/kernel/fadump.c | 8 +-
arch/powerpc/kernel/idle.c | 2 +-
arch/powerpc/perf/isa207-common.c | 3 +-
arch/powerpc/platforms/4xx/cpm.c | 2 +-
arch/powerpc/platforms/8xx/cpm1.c | 1 +
arch/powerpc/platforms/powernv/opal-fadump.c | 94 +++++----
arch/powerpc/platforms/powernv/opal-fadump.h | 10 +-
arch/powerpc/platforms/powernv/ultravisor.c | 1 +
arch/powerpc/platforms/powernv/vas-fault.c | 2 +-
arch/powerpc/platforms/powernv/vas-window.c | 4 +-
arch/powerpc/platforms/powernv/vas.h | 2 +-
arch/powerpc/sysdev/dart_iommu.c | 6 +-
arch/powerpc/sysdev/fsl_rio.c | 2 +
arch/powerpc/sysdev/xics/icp-opal.c | 1 +
arch/riscv/include/asm/irq_work.h | 2 +-
arch/riscv/kernel/head.S | 1 +
arch/s390/include/asm/kexec.h | 10 +
arch/s390/include/asm/preempt.h | 15 +-
arch/s390/kernel/perf_event.c | 2 +-
arch/um/drivers/chan_user.c | 9 +-
arch/um/include/asm/thread_info.h | 2 +
arch/um/kernel/exec.c | 2 +-
arch/um/kernel/process.c | 2 +-
arch/um/kernel/ptrace.c | 8 +-
arch/um/kernel/signal.c | 4 +-
arch/x86/Kconfig | 4 +-
arch/x86/entry/entry_64.S | 1 +
arch/x86/entry/vdso/vma.c | 2 +-
arch/x86/events/amd/ibs.c | 55 ++++-
arch/x86/events/intel/core.c | 2 +-
arch/x86/include/asm/acenv.h | 14 +-
arch/x86/include/asm/kexec.h | 8 +
arch/x86/include/asm/suspend_32.h | 2 +-
arch/x86/include/asm/suspend_64.h | 12 +-
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/apic/x2apic_uv_x.c | 8 +-
arch/x86/kernel/cpu/intel.c | 2 +-
arch/x86/kernel/cpu/mce/amd.c | 32 +--
arch/x86/kernel/step.c | 3 +-
arch/x86/kernel/sys_x86_64.c | 7 +-
arch/x86/kvm/vmx/nested.c | 45 ++++-
arch/x86/kvm/vmx/vmcs.h | 5 +
arch/x86/lib/delay.c | 4 +-
arch/x86/mm/pat/memtype.c | 2 +-
arch/x86/um/ldt.c | 6 +-
arch/xtensa/kernel/ptrace.c | 4 +-
arch/xtensa/kernel/signal.c | 4 +-
arch/xtensa/platforms/iss/simdisk.c | 18 +-
block/bfq-cgroup.c | 111 +++++++----
block/bfq-iosched.c | 46 +++--
block/bfq-iosched.h | 6 +-
block/blk-cgroup.c | 8 +-
block/blk-iolatency.c | 122 ++++++------
crypto/cryptd.c | 23 +--
drivers/acpi/property.c | 18 +-
drivers/acpi/sleep.c | 12 ++
drivers/base/memory.c | 5 +-
drivers/base/node.c | 1 +
drivers/block/drbd/drbd_main.c | 11 +-
drivers/block/nbd.c | 13 +-
drivers/block/virtio_blk.c | 7 +-
drivers/char/hw_random/omap3-rom-rng.c | 2 +-
drivers/char/ipmi/ipmi_msghandler.c | 4 +-
drivers/char/ipmi/ipmi_ssif.c | 23 +++
drivers/char/random.c | 12 +-
drivers/cpufreq/mediatek-cpufreq.c | 19 +-
.../crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c | 115 +++++++----
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 30 ++-
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c | 10 +-
drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 14 +-
drivers/crypto/ccree/cc_buffer_mgr.c | 27 +--
drivers/crypto/marvell/cesa/cipher.c | 1 -
drivers/crypto/nx/nx-common-powernv.c | 2 +-
drivers/devfreq/rk3399_dmc.c | 2 +
drivers/dma/idxd/cdev.c | 8 +-
drivers/dma/stm32-mdma.c | 87 ++++----
drivers/edac/dmc520_edac.c | 2 +-
drivers/firmware/arm_scmi/base.c | 2 +-
drivers/gpio/gpiolib-of.c | 5 +
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 +-
drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 14 +-
drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 8 +-
drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 10 +-
drivers/gpu/drm/arm/malidp_crtc.c | 5 +-
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1 +
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 31 ++-
drivers/gpu/drm/drm_edid.c | 6 +-
drivers/gpu/drm/drm_plane.c | 14 +-
drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6 +
drivers/gpu/drm/gma500/psb_intel_display.c | 7 +-
drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 33 ++-
drivers/gpu/drm/i915/i915_perf.c | 4 +-
drivers/gpu/drm/i915/i915_perf_types.h | 2 +-
drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 61 +++++-
drivers/gpu/drm/mediatek/mtk_cec.c | 2 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 14 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 6 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 15 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h | 4 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 15 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h | 2 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 20 +-
drivers/gpu/drm/msm/dp/dp_display.c | 55 +++--
drivers/gpu/drm/msm/dsi/dsi_host.c | 21 +-
drivers/gpu/drm/msm/hdmi/hdmi.c | 10 +-
drivers/gpu/drm/msm/msm_drv.c | 1 +
drivers/gpu/drm/msm/msm_gem_prime.c | 2 +-
drivers/gpu/drm/nouveau/dispnv50/atom.h | 6 +-
drivers/gpu/drm/nouveau/dispnv50/crc.c | 27 ++-
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c | 6 +-
drivers/gpu/drm/panel/panel-simple.c | 3 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 +-
drivers/gpu/drm/stm/ltdc.c | 16 +-
drivers/gpu/drm/tilcdc/tilcdc_external.c | 8 +-
drivers/gpu/drm/vc4/vc4_hvs.c | 26 ++-
drivers/gpu/drm/vc4/vc4_txp.c | 8 +-
drivers/gpu/drm/virtio/virtgpu_display.c | 2 +
drivers/hid/hid-bigbenff.c | 6 +
drivers/hid/hid-elan.c | 2 -
drivers/hid/hid-led.c | 2 +-
drivers/hwtracing/coresight/coresight-core.c | 33 ++-
drivers/i2c/busses/i2c-at91-master.c | 11 +
drivers/i2c/busses/i2c-npcm7xx.c | 103 ++++++----
drivers/i2c/busses/i2c-rcar.c | 15 +-
drivers/infiniband/hw/hfi1/file_ops.c | 2 +
drivers/infiniband/hw/hfi1/init.c | 2 +-
drivers/infiniband/hw/hfi1/sdma.c | 12 +-
drivers/infiniband/sw/rdmavt/qp.c | 6 +-
drivers/infiniband/sw/rxe/rxe_req.c | 2 +-
drivers/input/misc/sparcspkr.c | 1 +
drivers/input/touchscreen/stmfts.c | 16 +-
drivers/iommu/amd/init.c | 2 +-
drivers/iommu/intel/iommu.c | 2 +-
drivers/iommu/msm_iommu.c | 11 +-
drivers/iommu/mtk_iommu.c | 3 +-
drivers/irqchip/irq-armada-370-xp.c | 11 +-
drivers/irqchip/irq-aspeed-i2c-ic.c | 4 +-
drivers/irqchip/irq-aspeed-scu-ic.c | 4 +-
drivers/irqchip/irq-sni-exiu.c | 25 ++-
drivers/irqchip/irq-xtensa-mx.c | 18 +-
drivers/macintosh/Kconfig | 6 +
drivers/macintosh/Makefile | 3 +-
drivers/macintosh/via-pmu.c | 2 +-
drivers/mailbox/mailbox.c | 19 +-
drivers/md/bcache/btree.c | 58 +++---
drivers/md/bcache/btree.h | 2 +-
drivers/md/bcache/journal.c | 31 ++-
drivers/md/bcache/journal.h | 2 +
drivers/md/bcache/request.c | 6 +
drivers/md/bcache/super.c | 1 +
drivers/md/bcache/writeback.c | 101 ++++------
drivers/md/bcache/writeback.h | 2 +-
drivers/md/md-bitmap.c | 44 ++--
drivers/md/md.c | 18 +-
drivers/media/cec/core/cec-adap.c | 6 +-
drivers/media/i2c/ov7670.c | 1 -
drivers/media/pci/cx23885/cx23885-core.c | 6 +-
drivers/media/pci/cx25821/cx25821-core.c | 2 +-
drivers/media/platform/aspeed-video.c | 4 +-
drivers/media/platform/coda/coda-common.c | 35 ++--
drivers/media/platform/exynos4-is/fimc-is.c | 6 +-
drivers/media/platform/exynos4-is/fimc-isp-video.h | 2 +-
drivers/media/platform/qcom/venus/hfi.c | 3 +
drivers/media/platform/rockchip/rga/rga.c | 6 +-
drivers/media/platform/sti/delta/delta-v4l2.c | 6 +-
drivers/media/platform/vsp1/vsp1_rpf.c | 6 +-
drivers/media/rc/imon.c | 99 +++++----
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 7 +-
drivers/media/usb/uvc/uvc_v4l2.c | 20 +-
drivers/memory/samsung/exynos5422-dmc.c | 5 +-
drivers/mfd/davinci_voicecodec.c | 6 +-
drivers/mfd/ipaq-micro.c | 2 +-
drivers/misc/ocxl/file.c | 2 +
drivers/mmc/host/jz4740_mmc.c | 20 ++
drivers/mmc/host/sdhci_am654.c | 23 ++-
drivers/mtd/chips/cfi_cmdset_0002.c | 103 +++++-----
drivers/mtd/nand/raw/cadence-nand-controller.c | 5 +-
drivers/mtd/nand/raw/denali_pci.c | 15 +-
drivers/mtd/spi-nor/core.c | 9 +
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 2 +-
drivers/net/can/xilinx_can.c | 4 +-
drivers/net/dsa/mt7530.c | 14 +-
drivers/net/ethernet/broadcom/Makefile | 5 +
.../chelsio/inline_crypto/chtls/chtls_cm.c | 2 +-
.../net/ethernet/huawei/hinic/hinic_hw_api_cmd.c | 5 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 10 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 5 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c | 9 +-
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 2 +
drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c | 23 +--
drivers/net/ethernet/huawei/hinic/hinic_main.c | 10 +-
drivers/net/ethernet/huawei/hinic/hinic_tx.c | 9 +-
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 10 +-
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c | 13 --
.../net/ethernet/mellanox/mlxsw/spectrum_trap.c | 2 +-
drivers/net/ethernet/sfc/ef10.c | 2 +-
.../net/ethernet/stmicro/stmmac/stmmac_selftests.c | 15 +-
drivers/net/hyperv/netvsc_drv.c | 5 +-
drivers/net/ipa/ipa_endpoint.c | 4 +-
drivers/net/phy/micrel.c | 11 +-
drivers/net/wireguard/socket.c | 4 +-
drivers/net/wireless/ath/ath10k/mac.c | 20 +-
drivers/net/wireless/ath/ath11k/mac.c | 16 +-
drivers/net/wireless/ath/ath11k/spectral.c | 17 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8 +
drivers/net/wireless/ath/carl9170/tx.c | 3 +
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/broadcom/b43legacy/phy.c | 2 +-
drivers/net/wireless/intel/ipw2x00/libipw_tx.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/power.c | 3 +
drivers/net/wireless/marvell/mwifiex/11h.c | 2 +
drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 8 +-
drivers/net/wireless/realtek/rtlwifi/usb.c | 2 +-
drivers/nfc/st21nfca/se.c | 17 +-
drivers/nfc/st21nfca/st21nfca.h | 1 +
drivers/nvdimm/core.c | 9 -
drivers/nvdimm/security.c | 5 -
drivers/nvme/host/core.c | 2 +-
drivers/nvme/host/pci.c | 1 +
drivers/of/overlay.c | 4 +-
drivers/opp/of.c | 2 +-
drivers/pci/controller/cadence/pcie-cadence-ep.c | 3 +-
drivers/pci/controller/dwc/pci-imx6.c | 23 ++-
drivers/pci/controller/dwc/pcie-designware-host.c | 3 +-
drivers/pci/controller/dwc/pcie-qcom.c | 9 +-
drivers/pci/controller/pcie-rockchip-ep.c | 3 +-
drivers/pci/pci.c | 12 +-
drivers/pci/pcie/aer.c | 7 +-
drivers/phy/qualcomm/phy-qcom-qmp.c | 11 +-
drivers/pinctrl/bcm/pinctrl-bcm2835.c | 18 ++
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 2 +-
drivers/pinctrl/renesas/core.c | 7 +-
drivers/pinctrl/renesas/pinctrl-rzn1.c | 10 +-
drivers/platform/chrome/cros_ec.c | 16 +-
drivers/platform/chrome/cros_ec_chardev.c | 2 +-
drivers/platform/chrome/cros_ec_proto.c | 50 ++++-
drivers/platform/mips/cpu_hwmon.c | 127 ++++--------
drivers/regulator/core.c | 7 +-
drivers/regulator/pfuze100-regulator.c | 2 +
drivers/regulator/qcom_smd-regulator.c | 35 ++--
drivers/scsi/dc395x.c | 15 +-
drivers/scsi/fcoe/fcoe_ctlr.c | 2 +-
drivers/scsi/lpfc/lpfc_sli.c | 6 +-
drivers/scsi/megaraid.c | 2 +-
drivers/scsi/ufs/ti-j721e-ufs.c | 6 +-
drivers/scsi/ufs/ufs-qcom.c | 14 +-
drivers/scsi/ufs/ufshcd.c | 7 +-
drivers/soc/qcom/llcc-qcom.c | 1 +
drivers/soc/qcom/smp2p.c | 1 +
drivers/soc/qcom/smsm.c | 1 +
drivers/soc/ti/ti_sci_pm_domains.c | 2 +
drivers/spi/spi-fsl-qspi.c | 4 +
drivers/spi/spi-img-spfi.c | 2 +-
drivers/spi/spi-rspi.c | 15 +-
drivers/spi/spi-stm32-qspi.c | 3 +-
drivers/spi/spi-ti-qspi.c | 5 +-
drivers/staging/media/hantro/hantro_v4l2.c | 8 +-
drivers/staging/media/rkvdec/rkvdec-h264.c | 37 +++-
drivers/staging/media/rkvdec/rkvdec.c | 10 +-
drivers/target/target_core_device.c | 1 -
drivers/thermal/broadcom/bcm2711_thermal.c | 5 +-
drivers/thermal/broadcom/sr-thermal.c | 3 +
drivers/thermal/imx_sc_thermal.c | 6 +-
drivers/thermal/thermal_core.c | 42 ++--
drivers/tty/serial/pch_uart.c | 27 +--
drivers/tty/tty_buffer.c | 3 +-
drivers/usb/core/hcd.c | 29 ++-
drivers/usb/core/quirks.c | 3 +
drivers/usb/dwc3/gadget.c | 6 +-
drivers/usb/host/xhci-pci.c | 2 +
drivers/usb/serial/option.c | 2 +
drivers/vdpa/vdpa_sim/vdpa_sim.c | 5 +-
drivers/video/console/sticon.c | 5 +-
drivers/video/console/sticore.c | 32 ++-
drivers/video/fbdev/amba-clcd.c | 5 +-
drivers/video/fbdev/core/fbcon.c | 5 +-
drivers/video/fbdev/sticore.h | 3 +
drivers/video/fbdev/stifb.c | 4 +-
fs/afs/rxrpc.c | 8 +-
fs/binfmt_flat.c | 27 ++-
fs/btrfs/disk-io.c | 4 +-
fs/btrfs/volumes.c | 8 +-
fs/cifs/smb2inode.c | 2 -
fs/cifs/smb2ops.c | 2 +-
fs/dax.c | 3 +-
fs/dlm/lock.c | 11 +-
fs/dlm/plock.c | 12 +-
fs/ext4/ext4.h | 6 -
fs/ext4/extents.c | 10 +-
fs/ext4/inline.c | 12 ++
fs/ext4/inode.c | 4 +
fs/ext4/namei.c | 84 ++++++--
fs/ext4/super.c | 24 ++-
fs/f2fs/f2fs.h | 19 +-
fs/f2fs/file.c | 20 +-
fs/f2fs/inline.c | 29 ++-
fs/f2fs/inode.c | 19 +-
fs/f2fs/segment.c | 42 ++--
fs/f2fs/segment.h | 33 +--
fs/f2fs/super.c | 6 +-
fs/fat/fatent.c | 7 +-
fs/fs-writeback.c | 13 +-
fs/gfs2/quota.c | 32 +--
fs/iomap/buffered-io.c | 3 +-
fs/jfs/jfs_dmap.c | 3 +-
fs/nfs/file.c | 16 +-
fs/nfs/pnfs.c | 2 +
fs/nfs/write.c | 11 +-
fs/notify/fdinfo.c | 11 +-
fs/notify/inotify/inotify.h | 12 ++
fs/notify/inotify/inotify_user.c | 2 +-
fs/notify/mark.c | 6 +-
fs/ocfs2/dlmfs/userdlm.c | 16 +-
fs/proc/generic.c | 3 +
fs/proc/proc_net.c | 3 +
fs/xfs/libxfs/xfs_btree.c | 35 ++--
fs/xfs/xfs_dquot.c | 39 +++-
fs/xfs/xfs_iomap.c | 3 +
fs/xfs/xfs_log.c | 28 ++-
fs/xfs/xfs_log.h | 1 +
fs/xfs/xfs_mount.c | 93 +++++----
fs/xfs/xfs_qm.c | 92 ++++-----
fs/xfs/xfs_symlink.c | 1 +
include/drm/drm_edid.h | 6 +-
include/linux/bpf.h | 2 +
include/linux/efi.h | 2 +
include/linux/font.h | 2 +-
include/linux/gpio/driver.h | 12 ++
include/linux/kexec.h | 46 ++++-
include/linux/lsm_hook_defs.h | 4 +-
include/linux/lsm_hooks.h | 2 +-
include/linux/mailbox_controller.h | 1 +
include/linux/mtd/cfi.h | 1 +
include/linux/nodemask.h | 13 +-
include/linux/platform_data/cros_ec_proto.h | 3 +
include/linux/ptrace.h | 7 -
include/linux/security.h | 23 ++-
include/linux/thermal.h | 2 +-
include/linux/usb/hcd.h | 2 +
include/net/bluetooth/hci.h | 16 +-
include/net/bluetooth/hci_core.h | 18 +-
include/net/flow.h | 10 +
include/net/if_inet6.h | 8 +
include/net/route.h | 6 +-
include/scsi/libfcoe.h | 3 +-
include/sound/jack.h | 1 +
include/trace/events/rxrpc.h | 2 +-
include/trace/events/vmscan.h | 4 +-
init/Kconfig | 5 +
ipc/mqueue.c | 14 ++
kernel/bpf/stackmap.c | 1 -
kernel/dma/debug.c | 2 +-
kernel/kexec_file.c | 34 ----
kernel/ptrace.c | 5 +-
kernel/rcu/Kconfig | 1 +
kernel/rcu/tasks.h | 3 +
kernel/scftorture.c | 5 +-
kernel/sched/fair.c | 8 +-
kernel/sched/pelt.h | 4 +-
kernel/sched/sched.h | 4 +-
kernel/trace/ftrace.c | 5 +-
kernel/trace/trace_events_hist.c | 3 +
mm/compaction.c | 2 +
mm/hugetlb.c | 9 +-
net/bluetooth/hci_conn.c | 8 +-
net/bluetooth/hci_core.c | 27 +--
net/bluetooth/hci_debugfs.c | 8 +-
net/bluetooth/hci_event.c | 91 +++++----
net/bluetooth/hci_request.c | 221 ++++++++++++++++-----
net/bluetooth/hci_sock.c | 12 +-
net/bluetooth/l2cap_core.c | 10 +-
net/bluetooth/mgmt.c | 14 +-
net/bluetooth/mgmt_config.c | 10 +
net/bluetooth/sco.c | 21 +-
net/bluetooth/smp.c | 6 +-
net/core/dev.c | 8 +-
net/dccp/ipv4.c | 2 +-
net/dccp/ipv6.c | 6 +-
net/ipv4/icmp.c | 4 +-
net/ipv4/inet_connection_sock.c | 4 +-
net/ipv4/ip_output.c | 2 +-
net/ipv4/ping.c | 2 +-
net/ipv4/raw.c | 2 +-
net/ipv4/syncookies.c | 2 +-
net/ipv4/udp.c | 2 +-
net/ipv6/addrconf.c | 33 ++-
net/ipv6/af_inet6.c | 2 +-
net/ipv6/datagram.c | 2 +-
net/ipv6/icmp.c | 6 +-
net/ipv6/inet6_connection_sock.c | 4 +-
net/ipv6/netfilter/nf_reject_ipv6.c | 2 +-
net/ipv6/ping.c | 2 +-
net/ipv6/raw.c | 2 +-
net/ipv6/syncookies.c | 2 +-
net/ipv6/tcp_ipv6.c | 4 +-
net/ipv6/udp.c | 2 +-
net/l2tp/l2tp_ip6.c | 2 +-
net/mac80211/chan.c | 7 +-
net/mac80211/ieee80211_i.h | 5 +
net/mac80211/scan.c | 20 ++
net/netfilter/nf_synproxy_core.c | 2 +-
net/nfc/core.c | 1 +
net/rxrpc/ar-internal.h | 13 +-
net/rxrpc/call_event.c | 7 +-
net/rxrpc/conn_object.c | 2 +-
net/rxrpc/input.c | 31 ++-
net/rxrpc/output.c | 20 +-
net/rxrpc/recvmsg.c | 8 +-
net/rxrpc/sendmsg.c | 6 +
net/rxrpc/sysctl.c | 4 +-
net/sctp/input.c | 4 +-
net/smc/af_smc.c | 2 +-
net/wireless/nl80211.c | 1 +
net/wireless/reg.c | 4 +
net/xfrm/xfrm_state.c | 6 +-
scripts/faddr2line | 150 +++++++++-----
security/integrity/ima/Kconfig | 14 +-
.../integrity/platform_certs/keyring_handler.h | 8 +
security/integrity/platform_certs/load_uefi.c | 33 +++
security/security.c | 17 +-
security/selinux/hooks.c | 4 +-
security/selinux/include/xfrm.h | 2 +-
security/selinux/xfrm.c | 13 +-
sound/core/jack.c | 34 +++-
sound/core/pcm_memory.c | 3 +-
sound/pci/hda/patch_realtek.c | 11 +
sound/soc/atmel/atmel-classd.c | 1 -
sound/soc/atmel/atmel-pdmic.c | 1 -
sound/soc/codecs/Kconfig | 2 -
sound/soc/codecs/max98090.c | 6 +-
sound/soc/codecs/rk3328_codec.c | 2 +-
sound/soc/codecs/rt5514.c | 2 +-
sound/soc/codecs/rt5645.c | 7 +-
sound/soc/codecs/tscs454.c | 12 +-
sound/soc/codecs/wm2000.c | 6 +-
sound/soc/fsl/imx-sgtl5000.c | 14 +-
sound/soc/intel/boards/bytcr_rt5640.c | 12 ++
sound/soc/mediatek/mt2701/mt2701-wm8960.c | 9 +-
sound/soc/mediatek/mt8173/mt8173-max98090.c | 5 +-
sound/soc/mxs/mxs-saif.c | 1 +
sound/soc/samsung/aries_wm8994.c | 17 +-
sound/soc/samsung/arndale.c | 5 +-
sound/soc/samsung/littlemill.c | 5 +-
sound/soc/samsung/lowland.c | 5 +-
sound/soc/samsung/odroid.c | 4 +-
sound/soc/samsung/smdk_wm8994.c | 4 +-
sound/soc/samsung/smdk_wm8994pcm.c | 4 +-
sound/soc/samsung/snow.c | 9 +-
sound/soc/samsung/speyside.c | 5 +-
sound/soc/samsung/tm2_wm5110.c | 3 +-
sound/soc/samsung/tobermory.c | 5 +-
sound/soc/soc-dapm.c | 2 -
sound/soc/ti/j721e-evm.c | 44 +++-
sound/usb/midi.c | 3 +
tools/lib/bpf/libbpf.c | 20 +-
tools/perf/Makefile.config | 39 ++--
tools/perf/builtin-c2c.c | 6 +-
tools/perf/pmu-events/jevents.c | 2 +-
tools/perf/util/data.h | 1 +
tools/power/x86/turbostat/turbostat.c | 1 +
.../bpf/progs/btf_dump_test_case_syntax.c | 2 +-
tools/testing/selftests/bpf/progs/profiler.inc.h | 5 +-
tools/testing/selftests/cgroup/test_stress.sh | 2 +-
tools/testing/selftests/resctrl/fill_buf.c | 4 +-
512 files changed, 3868 insertions(+), 2289 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.15 06/21] kbuild: move objtool_args back to scripts/Makefile.build
@ 2022-05-13 14:23 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-05-13 14:23 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Masahiro Yamada, Kees Cook,
Josh Poimboeuf, Sasha Levin
From: Masahiro Yamada <masahiroy@kernel.org>
[ Upstream commit 8f0c32c788fffa8e88f995372415864039347c8a ]
Commit b1a1a1a09b46 ("kbuild: lto: postpone objtool") moved objtool_args
to Makefile.lib, so the arguments can be used in Makefile.modfinal as
well as Makefile.build.
With commit 850ded46c642 ("kbuild: Fix TRIM_UNUSED_KSYMS with
LTO_CLANG"), module LTO linking came back to scripts/Makefile.build
again.
So, there is no more reason to keep objtool_args in a separate file.
Get it back to the original place, close to the objtool command.
Remove the stale comment too.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
scripts/Makefile.build | 10 ++++++++++
scripts/Makefile.lib | 11 -----------
2 files changed, 10 insertions(+), 11 deletions(-)
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -224,6 +224,16 @@ cmd_record_mcount = $(if $(findstring $(
endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
ifdef CONFIG_STACK_VALIDATION
+
+objtool_args = \
+ $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \
+ $(if $(part-of-module), --module) \
+ $(if $(CONFIG_FRAME_POINTER),, --no-fp) \
+ $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\
+ $(if $(CONFIG_RETPOLINE), --retpoline) \
+ $(if $(CONFIG_X86_SMAP), --uaccess) \
+ $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount)
+
ifndef CONFIG_LTO_CLANG
__objtool_obj := $(objtree)/tools/objtool/objtool
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -232,17 +232,6 @@ ifeq ($(CONFIG_LTO_CLANG),y)
mod-prelink-ext := .lto
endif
-# Objtool arguments are also needed for modfinal with LTO, so we define
-# then here to avoid duplication.
-objtool_args = \
- $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \
- $(if $(part-of-module), --module) \
- $(if $(CONFIG_FRAME_POINTER),, --no-fp) \
- $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\
- $(if $(CONFIG_RETPOLINE), --retpoline) \
- $(if $(CONFIG_X86_SMAP), --uaccess) \
- $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount)
-
# Useful for describing the dependency of composite objects
# Usage:
# $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add)
^ permalink raw reply [relevance 5%]
* Re: [PATCH net 1/1] net: stmmac: add fsleep() in HW Rx timestamp checking loop
@ 2022-04-20 12:54 5% ` Richard Cochran
0 siblings, 0 replies; 200+ results
From: Richard Cochran @ 2022-04-20 12:54 UTC (permalink / raw)
To: Tan Tee Min
Cc: Jakub Kicinski, Tan Tee Min, Giuseppe Cavallaro,
Alexandre Torgue, Jose Abreu, David S . Miller, Paolo Abeni,
Maxime Coquelin, Rayagond Kokatanur, netdev, linux-stm32,
linux-arm-kernel, linux-kernel, stable, Voon Wei Feng,
Wong Vee Khee, Song Yoong Siang, Alexandre Torgue
On Wed, Apr 20, 2022 at 01:15:08PM +0800, Tan Tee Min wrote:
> No. The context descriptor (frame) is possibly still owned by the
> DMA controller in this situation.
So that is a problem. The solution is to postpone this logic until
the driver owns the buffer. Doesn't the HW offer some means of
notification, like an interrupt for example?
Thanks,
Richard
^ permalink raw reply [relevance 5%]
* [PATCH 5.15 098/189] net: ftgmac100: access hardware register after clock ready
@ 2022-04-18 12:11 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-04-18 12:11 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Dylan Hung, David S. Miller, Sasha Levin
From: Dylan Hung <dylan_hung@aspeedtech.com>
[ Upstream commit 3d2504524531990b32a0629cc984db44f399d161 ]
AST2600 MAC register 0x58 is writable only when the MAC clock is
enabled. Usually, the MAC clock is enabled by the bootloader so
register 0x58 is set normally when the bootloader is involved. To make
ast2600 ftgmac100 work without the bootloader, postpone the register
write until the clock is ready.
Fixes: 137d23cea1c0 ("net: ftgmac100: Fix Aspeed ast2600 TX hang issue")
Signed-off-by: Dylan Hung <dylan_hung@aspeedtech.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/faraday/ftgmac100.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index ff76e401a014..e1df2dc810a2 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1817,11 +1817,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
priv->rxdes0_edorr_mask = BIT(30);
priv->txdes0_edotr_mask = BIT(30);
priv->is_aspeed = true;
- /* Disable ast2600 problematic HW arbitration */
- if (of_device_is_compatible(np, "aspeed,ast2600-mac")) {
- iowrite32(FTGMAC100_TM_DEFAULT,
- priv->base + FTGMAC100_OFFSET_TM);
- }
} else {
priv->rxdes0_edorr_mask = BIT(15);
priv->txdes0_edotr_mask = BIT(15);
@@ -1893,6 +1888,11 @@ static int ftgmac100_probe(struct platform_device *pdev)
err = ftgmac100_setup_clk(priv);
if (err)
goto err_phy_connect;
+
+ /* Disable ast2600 problematic HW arbitration */
+ if (of_device_is_compatible(np, "aspeed,ast2600-mac"))
+ iowrite32(FTGMAC100_TM_DEFAULT,
+ priv->base + FTGMAC100_OFFSET_TM);
}
/* Default ring sizes */
--
2.35.1
^ permalink raw reply related [relevance 5%]
* [PATCH 5.17 118/219] net: ftgmac100: access hardware register after clock ready
@ 2022-04-18 12:11 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2022-04-18 12:11 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Dylan Hung, David S. Miller, Sasha Levin
From: Dylan Hung <dylan_hung@aspeedtech.com>
[ Upstream commit 3d2504524531990b32a0629cc984db44f399d161 ]
AST2600 MAC register 0x58 is writable only when the MAC clock is
enabled. Usually, the MAC clock is enabled by the bootloader so
register 0x58 is set normally when the bootloader is involved. To make
ast2600 ftgmac100 work without the bootloader, postpone the register
write until the clock is ready.
Fixes: 137d23cea1c0 ("net: ftgmac100: Fix Aspeed ast2600 TX hang issue")
Signed-off-by: Dylan Hung <dylan_hung@aspeedtech.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/faraday/ftgmac100.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index d5356db7539a..caf48023f8ea 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1835,11 +1835,6 @@ static int ftgmac100_probe(struct platform_device *pdev)
priv->rxdes0_edorr_mask = BIT(30);
priv->txdes0_edotr_mask = BIT(30);
priv->is_aspeed = true;
- /* Disable ast2600 problematic HW arbitration */
- if (of_device_is_compatible(np, "aspeed,ast2600-mac")) {
- iowrite32(FTGMAC100_TM_DEFAULT,
- priv->base + FTGMAC100_OFFSET_TM);
- }
} else {
priv->rxdes0_edorr_mask = BIT(15);
priv->txdes0_edotr_mask = BIT(15);
@@ -1911,6 +1906,11 @@ static int ftgmac100_probe(struct platform_device *pdev)
err = ftgmac100_setup_clk(priv);
if (err)
goto err_phy_connect;
+
+ /* Disable ast2600 problematic HW arbitration */
+ if (of_device_is_compatible(np, "aspeed,ast2600-mac"))
+ iowrite32(FTGMAC100_TM_DEFAULT,
+ priv->base + FTGMAC100_OFFSET_TM);
}
/* Default ring sizes */
--
2.35.1
^ permalink raw reply related [relevance 5%]
* Re: [PATCH AUTOSEL 5.16 12/13] spi: Fix invalid sgs value
2022-03-16 16:07 5% ` Geert Uytterhoeven
@ 2022-03-16 16:40 0% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2022-03-16 16:40 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Linux Kernel Mailing List, stable, Biju Das, Lad Prabhakar,
Mark Brown, linux-spi
On Wed, Mar 16, 2022 at 05:07:28PM +0100, Geert Uytterhoeven wrote:
>Hi Sasha,
>
>On Wed, Mar 16, 2022 at 3:15 PM Sasha Levin <sashal@kernel.org> wrote:
>> From: Biju Das <biju.das.jz@bp.renesas.com>
>>
>> [ Upstream commit 1a4e53d2fc4f68aa654ad96d13ad042e1a8e8a7d ]
>
>This commit is not 100% correct, cfr.
>https://lore.kernel.org/lkml/CAHk-=wiZnS6n1ROQg3FHd=bcVTHi-sKutKT+toiViQEH47ZACg@mail.gmail.com
>Please postpone backporting until the issue has been resolved.
Will check back in a week, thanks!
--
Thanks,
Sasha
^ permalink raw reply [relevance 0%]
* Re: [PATCH AUTOSEL 5.16 12/13] spi: Fix invalid sgs value
@ 2022-03-16 16:07 5% ` Geert Uytterhoeven
2022-03-16 16:40 0% ` Sasha Levin
0 siblings, 1 reply; 200+ results
From: Geert Uytterhoeven @ 2022-03-16 16:07 UTC (permalink / raw)
To: Sasha Levin
Cc: Linux Kernel Mailing List, stable, Biju Das, Lad Prabhakar,
Mark Brown, linux-spi
Hi Sasha,
On Wed, Mar 16, 2022 at 3:15 PM Sasha Levin <sashal@kernel.org> wrote:
> From: Biju Das <biju.das.jz@bp.renesas.com>
>
> [ Upstream commit 1a4e53d2fc4f68aa654ad96d13ad042e1a8e8a7d ]
This commit is not 100% correct, cfr.
https://lore.kernel.org/lkml/CAHk-=wiZnS6n1ROQg3FHd=bcVTHi-sKutKT+toiViQEH47ZACg@mail.gmail.com
Please postpone backporting until the issue has been resolved.
>
> max_seg_size is unsigned int and it can have a value up to 2^32
> (for eg:-RZ_DMAC driver sets dma_set_max_seg_size as U32_MAX)
> When this value is used in min_t() as an integer type, it becomes
> -1 and the value of sgs becomes 0.
>
> Fix this issue by replacing the 'int' data type with 'unsigned int'
> in min_t().
>
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> Link: https://lore.kernel.org/r/20220307184843.9994-1-biju.das.jz@bp.renesas.com
> Signed-off-by: Mark Brown <broonie@kernel.org>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
> drivers/spi/spi.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> index 8ba87b7f8f1a..ed4e6983eda0 100644
> --- a/drivers/spi/spi.c
> +++ b/drivers/spi/spi.c
> @@ -1021,10 +1021,10 @@ int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
> int i, ret;
>
> if (vmalloced_buf || kmap_buf) {
> - desc_len = min_t(int, max_seg_size, PAGE_SIZE);
> + desc_len = min_t(unsigned int, max_seg_size, PAGE_SIZE);
> sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
> } else if (virt_addr_valid(buf)) {
> - desc_len = min_t(int, max_seg_size, ctlr->max_dma_len);
> + desc_len = min_t(unsigned int, max_seg_size, ctlr->max_dma_len);
> sgs = DIV_ROUND_UP(len, desc_len);
> } else {
> return -EINVAL;
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [relevance 5%]
* Re: [PATCH v3] mm: fix panic in __alloc_pages
@ 2021-12-07 13:23 7% ` Michal Hocko
0 siblings, 0 replies; 200+ results
From: Michal Hocko @ 2021-12-07 13:23 UTC (permalink / raw)
To: David Hildenbrand
Cc: Alexey Makhalov, Dennis Zhou, Eric Dumazet, linux-mm,
Andrew Morton, Oscar Salvador, Tejun Heo, Christoph Lameter,
linux-kernel, stable
On Tue 07-12-21 13:28:31, David Hildenbrand wrote:
[...]
> But maybe I am missing something important regarding online vs. offline
> nodes that your patch changes?
I am relying on alloc_node_data setting the node online. But if we are
to change the call to arch_alloc_node_data then the patch needs to be
more involved. Here is what I have right now. If this happens to be the
right way then there is some additional work to sync up with the hotplug
code.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c5952749ad40..a296e934ad2f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -8032,8 +8032,23 @@ void __init free_area_init(unsigned long *max_zone_pfn)
/* Initialise every node */
mminit_verify_pageflags_layout();
setup_nr_node_ids();
- for_each_online_node(nid) {
- pg_data_t *pgdat = NODE_DATA(nid);
+ for_each_node(nid) {
+ pg_data_t *pgdat;
+
+ if (!node_online(nid)) {
+ pr_warn("Node %d uninitialized by the platform. Please report with memory map.\n", nid);
+ pgdat = arch_alloc_nodedata(nid);
+ pgdat->per_cpu_nodestats = alloc_percpu(struct per_cpu_nodestat);
+ arch_refresh_nodedata(nid, pgdat);
+ node_set_online(nid);
+ /* TODO do we need register_one_node here or postpone to
+ * when any memory is onlined there
+ */
+ free_area_init_memoryless_node(nid);
+ continue;
+ }
+
+ pgdat = NODE_DATA(nid);
free_area_init_node(nid);
/* Any memory on that node */
--
Michal Hocko
SUSE Labs
^ permalink raw reply related [relevance 7%]
* [PATCH 5.10 066/121] net: stmmac: fix system hang caused by eee_ctrl_timer during suspend/resume
@ 2021-11-29 18:18 4% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-11-29 18:18 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Joakim Zhang, David S. Miller, Sasha Levin
From: Joakim Zhang <qiangqing.zhang@nxp.com>
[ Upstream commit 276aae377206d60b9b7b7df4586cd9f2a813f5d0 ]
commit 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after
napi disabled"), this patch tries to fix system hang caused by eee_ctrl_timer,
unfortunately, it only can resolve it for system reboot stress test. System
hang also can be reproduced easily during system suspend/resume stess test
when mount NFS on i.MX8MP EVK board.
In stmmac driver, eee feature is combined to phylink framework. When do
system suspend, phylink_stop() would queue delayed work, it invokes
stmmac_mac_link_down(), where to deactivate eee_ctrl_timer synchronizly.
In above commit, try to fix issue by deactivating eee_ctrl_timer obviously,
but it is not enough. Looking into eee_ctrl_timer expire callback
stmmac_eee_ctrl_timer(), it could enable hareware eee mode again. What is
unexpected is that LPI interrupt (MAC_Interrupt_Enable.LPIEN bit) is always
asserted. This interrupt has chance to be issued when LPI state entry/exit
from the MAC, and at that time, clock could have been already disabled.
The result is that system hang when driver try to touch register from
interrupt handler.
The reason why above commit can fix system hang issue in stmmac_release()
is that, deactivate eee_ctrl_timer not just after napi disabled, further
after irq freed.
In conclusion, hardware would generate LPI interrupt when clock has been
disabled during suspend or resume, since hardware is in eee mode and LPI
interrupt enabled.
Interrupts from MAC, MTL and DMA level are enabled and never been disabled
when system suspend, so postpone clocks management from suspend stage to
noirq suspend stage should be more safe.
Fixes: 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after napi disabled")
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 14 ------
.../ethernet/stmicro/stmmac/stmmac_platform.c | 44 +++++++++++++++++++
2 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 4a75e73f06bbd..b6a2bc020026a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5238,7 +5238,6 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan;
- int ret;
if (!ndev || !netif_running(ndev))
return 0;
@@ -5280,13 +5279,6 @@ int stmmac_suspend(struct device *dev)
stmmac_mac_set(priv, priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- clk_disable_unprepare(priv->plat->clk_ptp_ref);
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
}
mutex_unlock(&priv->lock);
@@ -5351,12 +5343,6 @@ int stmmac_resume(struct device *dev)
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
- /* enable the clk previously disabled */
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
- if (priv->plat->clk_ptp_ref)
- clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 035f9aef4308f..5c9d29c42bac8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,7 @@
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -778,9 +779,52 @@ static int __maybe_unused stmmac_runtime_resume(struct device *dev)
return stmmac_bus_clks_config(priv, true);
}
+static int stmmac_pltfr_noirq_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmmac_pltfr_noirq_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* enable the clk previously disabled */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ }
+
+ return 0;
+}
+
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
--
2.33.0
^ permalink raw reply related [relevance 4%]
* [PATCH 5.15 01/20] string: uninline memcpy_and_pad
@ 2021-11-19 17:39 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-11-19 17:39 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Linus Torvalds, Geert Uytterhoeven,
Andy Shevchenko, Guenter Roeck
From: Guenter Roeck <linux@roeck-us.net>
commit 5c4e0a21fae877a7ef89be6dcc6263ec672372b8 upstream.
When building m68k:allmodconfig, recent versions of gcc generate the
following error if the length of UTS_RELEASE is less than 8 bytes.
In function 'memcpy_and_pad',
inlined from 'nvmet_execute_disc_identify' at
drivers/nvme/target/discovery.c:268:2: arch/m68k/include/asm/string.h:72:25: error:
'__builtin_memcpy' reading 8 bytes from a region of size 7
Discussions around the problem suggest that this only happens if an
architecture does not provide strlen(), if -ffreestanding is provided as
compiler option, and if CONFIG_FORTIFY_SOURCE=n. All of this is the case
for m68k. The exact reasons are unknown, but seem to be related to the
ability of the compiler to evaluate the return value of strlen() and
the resulting execution flow in memcpy_and_pad(). It would be possible
to work around the problem by using sizeof(UTS_RELEASE) instead of
strlen(UTS_RELEASE), but that would only postpone the problem until the
function is called in a similar way. Uninline memcpy_and_pad() instead
to solve the problem for good.
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/string.h | 19 ++-----------------
lib/string_helpers.c | 20 ++++++++++++++++++++
2 files changed, 22 insertions(+), 17 deletions(-)
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -262,23 +262,8 @@ void __write_overflow(void) __compiletim
#include <linux/fortify-string.h>
#endif
-/**
- * memcpy_and_pad - Copy one buffer to another with padding
- * @dest: Where to copy to
- * @dest_len: The destination buffer size
- * @src: Where to copy from
- * @count: The number of bytes to copy
- * @pad: Character to use for padding if space is left in destination.
- */
-static inline void memcpy_and_pad(void *dest, size_t dest_len,
- const void *src, size_t count, int pad)
-{
- if (dest_len > count) {
- memcpy(dest, src, count);
- memset(dest + count, pad, dest_len - count);
- } else
- memcpy(dest, src, dest_len);
-}
+void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
+ int pad);
/**
* str_has_prefix - Test if a string has a given prefix
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -696,3 +696,23 @@ void kfree_strarray(char **array, size_t
kfree(array);
}
EXPORT_SYMBOL_GPL(kfree_strarray);
+
+/**
+ * memcpy_and_pad - Copy one buffer to another with padding
+ * @dest: Where to copy to
+ * @dest_len: The destination buffer size
+ * @src: Where to copy from
+ * @count: The number of bytes to copy
+ * @pad: Character to use for padding if space is left in destination.
+ */
+void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
+ int pad)
+{
+ if (dest_len > count) {
+ memcpy(dest, src, count);
+ memset(dest + count, pad, dest_len - count);
+ } else {
+ memcpy(dest, src, dest_len);
+ }
+}
+EXPORT_SYMBOL(memcpy_and_pad);
^ permalink raw reply [relevance 5%]
* [PATCH 5.14 037/100] init: move usermodehelper_enable() to populate_rootfs()
@ 2021-09-24 12:43 4% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-09-24 12:43 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Rasmus Villemoes,
Alexander Egorenkov, Bruno Goncalves, Heiner Kallweit,
Luis Chamberlain, Andrew Morton, Linus Torvalds, Sasha Levin
From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
[ Upstream commit b234ed6d629420827e2839c8c8935be85a0867fd ]
Currently, usermodehelper is enabled right before PID1 starts going
through the initcalls. However, any call of a usermodehelper from a
pure_, core_, postcore_, arch_, subsys_ or fs_ initcall is futile, as
there is no filesystem contents yet.
Up until commit e7cb072eb988 ("init/initramfs.c: do unpacking
asynchronously"), such calls, whether via some request_module(), a
legacy uevent "/sbin/hotplug" notification or something else, would
just fail silently with (presumably) -ENOENT from
kernel_execve(). However, that commit introduced the
wait_for_initramfs() synchronization hook which must be called from
the usermodehelper exec path right before the kernel_execve, in order
that request_module() et al done from *after* rootfs_initcall()
time (i.e. device_ and late_ initcalls) would continue to find a
populated initramfs as they used to.
Any call of wait_for_initramfs() done before the unpacking has been
scheduled (i.e. before rootfs_initcall time) must just return
immediately [and let the caller find an empty file system] in order
not to deadlock the machine. I mistakenly thought, and my limited
testing confirmed, that there were no such calls, so I added a
pr_warn_once() in wait_for_initramfs(). It turns out that one can
indeed hit request_module() as well as kobject_uevent_env() during
those early init calls, leading to a user-visible warning in the
kernel log emitted consistently for certain configurations.
We could just remove the pr_warn_once(), but I think it's better to
postpone enabling the usermodehelper framework until there is at least
some chance of finding the executable. That is also a little more
efficient in that a lot of work done in umh.c will be elided. However,
it does change the error seen by those early callers from -ENOENT to
-EBUSY, so there is a risk of a regression if any caller care about
the exact error value.
Link: https://lkml.kernel.org/r/20210728134638.329060-1-linux@rasmusvillemoes.dk
Fixes: e7cb072eb988 ("init/initramfs.c: do unpacking asynchronously")
Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Reported-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reported-by: Bruno Goncalves <bgoncalv@redhat.com>
Reported-by: Heiner Kallweit <hkallweit1@gmail.com>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
init/initramfs.c | 2 ++
init/main.c | 1 -
init/noinitramfs.c | 2 ++
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/init/initramfs.c b/init/initramfs.c
index af27abc59643..a842c0544745 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -15,6 +15,7 @@
#include <linux/mm.h>
#include <linux/namei.h>
#include <linux/init_syscalls.h>
+#include <linux/umh.h>
static ssize_t __init xwrite(struct file *file, const char *p, size_t count,
loff_t *pos)
@@ -727,6 +728,7 @@ static int __init populate_rootfs(void)
{
initramfs_cookie = async_schedule_domain(do_populate_rootfs, NULL,
&initramfs_domain);
+ usermodehelper_enable();
if (!initramfs_async)
wait_for_initramfs();
return 0;
diff --git a/init/main.c b/init/main.c
index 8d97aba78c3a..90733a916791 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1392,7 +1392,6 @@ static void __init do_basic_setup(void)
driver_init();
init_irq_proc();
do_ctors();
- usermodehelper_enable();
do_initcalls();
}
diff --git a/init/noinitramfs.c b/init/noinitramfs.c
index 3d62b07f3bb9..d1d26b93d25c 100644
--- a/init/noinitramfs.c
+++ b/init/noinitramfs.c
@@ -10,6 +10,7 @@
#include <linux/kdev_t.h>
#include <linux/syscalls.h>
#include <linux/init_syscalls.h>
+#include <linux/umh.h>
/*
* Create a simple rootfs that is similar to the default initramfs
@@ -18,6 +19,7 @@ static int __init default_rootfs(void)
{
int err;
+ usermodehelper_enable();
err = init_mkdir("/dev", 0755);
if (err < 0)
goto out;
--
2.33.0
^ permalink raw reply related [relevance 4%]
* Linux 4.9.283
@ 2021-09-22 11:12 2% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-09-22 11:12 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 4.9.283 kernel.
All users of the 4.9 kernel series must upgrade.
The updated 4.9.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-4.9.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/devicetree/bindings/mtd/gpmc-nand.txt | 2
Makefile | 2
arch/arc/mm/cache.c | 2
arch/arm/boot/compressed/Makefile | 2
arch/arm/boot/dts/tegra20-tamonten.dtsi | 14 -
arch/arm/kernel/Makefile | 6
arch/arm/kernel/return_address.c | 4
arch/arm64/boot/dts/exynos/exynos7.dtsi | 2
arch/m68k/emu/nfeth.c | 4
arch/mips/mti-malta/malta-dtshim.c | 2
arch/openrisc/kernel/entry.S | 2
arch/parisc/kernel/signal.c | 6
arch/powerpc/boot/crt0.S | 3
arch/powerpc/kernel/module_64.c | 2
arch/powerpc/perf/hv-gpci.c | 2
arch/s390/kernel/dis.c | 2
arch/s390/kernel/jump_label.c | 2
arch/s390/net/bpf_jit_comp.c | 9 -
arch/x86/events/amd/ibs.c | 8 +
arch/x86/kernel/reboot.c | 3
arch/x86/kvm/x86.c | 4
arch/x86/mm/init_64.c | 6
arch/x86/xen/enlighten.c | 7
arch/x86/xen/p2m.c | 4
arch/xtensa/Kconfig | 2
arch/xtensa/platforms/iss/console.c | 17 +-
certs/Makefile | 8 +
drivers/ata/libata-core.c | 6
drivers/ata/sata_dwc_460ex.c | 12 -
drivers/base/power/wakeirq.c | 12 +
drivers/base/regmap/regmap.c | 2
drivers/bcma/main.c | 6
drivers/block/Kconfig | 4
drivers/block/cryptoloop.c | 2
drivers/clk/mvebu/kirkwood.c | 1
drivers/crypto/mxs-dcp.c | 81 ++++++-----
drivers/crypto/omap-sham.c | 2
drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c | 4
drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c | 4
drivers/crypto/qat/qat_common/adf_common_drv.h | 8 -
drivers/crypto/qat/qat_common/adf_init.c | 5
drivers/crypto/qat/qat_common/adf_isr.c | 7
drivers/crypto/qat/qat_common/adf_pf2vf_msg.c | 3
drivers/crypto/qat/qat_common/adf_vf2pf_msg.c | 12 -
drivers/crypto/qat/qat_common/adf_vf_isr.c | 7
drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c | 4
drivers/crypto/talitos.c | 4
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 2
drivers/gpu/drm/msm/dsi/dsi.c | 6
drivers/i2c/busses/i2c-highlander.c | 2
drivers/i2c/busses/i2c-iop3xx.c | 6
drivers/i2c/busses/i2c-mt65xx.c | 2
drivers/i2c/busses/i2c-s3c2410.c | 2
drivers/iio/dac/ad5624r_spi.c | 18 ++
drivers/media/i2c/tc358743.c | 2
drivers/media/rc/rc-loopback.c | 2
drivers/media/usb/dvb-usb/nova-t-usb2.c | 6
drivers/media/usb/dvb-usb/vp702x.c | 12 +
drivers/media/usb/go7007/go7007-driver.c | 26 ---
drivers/media/usb/stkwebcam/stk-webcam.c | 6
drivers/media/usb/uvc/uvc_v4l2.c | 34 +++-
drivers/mfd/ab8500-core.c | 2
drivers/mfd/stmpe.c | 4
drivers/mfd/tc3589x.c | 2
drivers/mfd/wm8994-irq.c | 2
drivers/misc/vmw_vmci/vmci_queue_pair.c | 6
drivers/mmc/host/dw_mmc.c | 1
drivers/mmc/host/moxart-mmc.c | 1
drivers/mmc/host/rtsx_pci_sdmmc.c | 36 +++-
drivers/mtd/nand/atmel_nand.c | 1
drivers/mtd/nand/cafe_nand.c | 4
drivers/net/dsa/b53/b53_common.c | 3
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 2
drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 1
drivers/net/ethernet/qlogic/qed/qed_main.c | 7
drivers/net/ethernet/qlogic/qede/qede_main.c | 2
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 1
drivers/net/ethernet/rdc/r6040.c | 9 +
drivers/net/ethernet/renesas/sh_eth.c | 1
drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 18 +-
drivers/net/ethernet/wiznet/w5100.c | 2
drivers/net/ethernet/xilinx/ll_temac_main.c | 4
drivers/net/phy/dp83640_reg.h | 2
drivers/net/usb/cdc_mbim.c | 5
drivers/net/wireless/ath/ath.h | 3
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2
drivers/net/wireless/ath/ath6kl/wmi.c | 4
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 3
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2
drivers/net/wireless/ath/ath9k/hw.c | 12 -
drivers/net/wireless/ath/ath9k/hw.h | 1
drivers/net/wireless/ath/ath9k/main.c | 95 ++++++++++++-
drivers/net/wireless/ath/key.c | 41 +++--
drivers/nvme/host/pci.c | 7
drivers/parport/ieee1284_ops.c | 2
drivers/pci/msi.c | 3
drivers/pci/pci.c | 15 +-
drivers/pci/quirks.c | 13 -
drivers/pci/syscall.c | 4
drivers/pinctrl/pinctrl-single.c | 1
drivers/platform/chrome/cros_ec_proto.c | 9 +
drivers/power/supply/axp288_fuel_gauge.c | 4
drivers/power/supply/max17042_battery.c | 8 -
drivers/rtc/rtc-tps65910.c | 2
drivers/scsi/BusLogic.c | 4
drivers/soc/qcom/smsm.c | 11 +
drivers/spi/spi-pic32.c | 1
drivers/staging/board/board.c | 7
drivers/staging/ks7010/ks7010_sdio.c | 2
drivers/tty/hvc/hvsi.c | 19 ++
drivers/tty/serial/8250/8250_pci.c | 2
drivers/tty/serial/8250/8250_port.c | 3
drivers/tty/serial/jsm/jsm_neo.c | 2
drivers/tty/serial/jsm/jsm_tty.c | 3
drivers/tty/tty_io.c | 4
drivers/usb/gadget/composite.c | 8 -
drivers/usb/gadget/function/u_ether.c | 5
drivers/usb/gadget/udc/at91_udc.c | 4
drivers/usb/gadget/udc/mv_u3d_core.c | 19 +-
drivers/usb/host/ehci-orion.c | 8 -
drivers/usb/host/fotg210-hcd.c | 41 ++---
drivers/usb/host/fotg210.h | 5
drivers/usb/host/ohci-tmio.c | 3
drivers/usb/host/xhci.c | 24 +--
drivers/usb/phy/phy-fsl-usb.c | 2
drivers/usb/phy/phy-isp1301.c | 2
drivers/usb/phy/phy-tahvo.c | 4
drivers/usb/phy/phy-twl6030-usb.c | 5
drivers/usb/serial/mos7720.c | 4
drivers/usb/usbip/vhci_hcd.c | 24 +++
drivers/vfio/Kconfig | 2
drivers/video/fbdev/asiliantfb.c | 3
drivers/video/fbdev/core/fbmem.c | 7
drivers/video/fbdev/kyro/fbdev.c | 8 +
drivers/video/fbdev/riva/fbdev.c | 3
fs/btrfs/inode.c | 2
fs/cifs/cifs_unicode.c | 9 -
fs/cifs/sess.c | 2
fs/ext4/inline.c | 6
fs/gfs2/acl.c | 27 +--
fs/gfs2/lock_dlm.c | 5
fs/udf/misc.c | 13 +
fs/udf/super.c | 25 ++-
include/crypto/public_key.h | 4
include/linux/hugetlb.h | 9 +
include/linux/pci.h | 5
include/linux/power/max17042_battery.h | 2
include/linux/skbuff.h | 2
include/uapi/linux/serial_reg.h | 1
kernel/events/core.c | 2
kernel/fork.c | 1
kernel/pid_namespace.c | 2
lib/test_bpf.c | 13 +
mm/kmemleak.c | 2
mm/page_alloc.c | 8 -
net/bluetooth/cmtp/cmtp.h | 2
net/bluetooth/hci_core.c | 14 +
net/bluetooth/hci_event.c | 15 ++
net/bluetooth/sco.c | 50 +++---
net/caif/chnl_net.c | 19 --
net/core/flow_dissector.c | 12 +
net/dccp/minisocks.c | 2
net/ipv4/icmp.c | 23 ++-
net/ipv4/igmp.c | 2
net/ipv4/ip_output.c | 5
net/ipv4/route.c | 46 ++++--
net/ipv4/tcp_input.c | 2
net/ipv4/tcp_ipv4.c | 5
net/l2tp/l2tp_core.c | 4
net/netlabel/netlabel_cipso_v4.c | 12 -
net/netlink/af_netlink.c | 4
net/sched/cls_flower.c | 4
net/sunrpc/auth_gss/svcauth_gss.c | 2
net/tipc/socket.c | 2
net/unix/af_unix.c | 2
security/integrity/ima/ima_mok.c | 2
security/smack/smack_access.c | 17 +-
sound/core/pcm_lib.c | 2
sound/soc/intel/boards/bytcr_rt5640.c | 9 -
179 files changed, 933 insertions(+), 489 deletions(-)
Adrian Bunk (1):
bnx2x: Fix enabling network interfaces without VFs
Andreas Obergschwandtner (1):
ARM: tegra: tamonten: Fix UART pad setting
Andrew Morton (1):
mm/kmemleak.c: make cond_resched() rate-limiting more efficient
Andy Shevchenko (2):
ata: sata_dwc_460ex: No need to call phy_exit() befre phy_init()
PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
Anirudh Rayabharam (1):
usbip: give back URBs for unsent unlink requests during cleanup
Austin Kim (1):
IMA: remove -Wmissing-prototypes warning
Baptiste Lepers (1):
events: Reuse value read using READ_ONCE instead of re-reading it
Ben Dooks (1):
ARM: 8918/2: only build return_address() if needed
Bob Peterson (1):
gfs2: Don't call dlm after protocol is unmounted
Christoph Hellwig (1):
cryptoloop: add a deprecation warning
Christophe JAILLET (4):
nvme-pci: Fix an error handling path in 'nvme_probe()'
drm/msm/dsi: Fix some reference counted resource leaks
staging: ks7010: Fix the initialization of the 'sleep_status' structure
mtd: rawnand: cafe: Fix a resource leak in the error handling path of 'cafe_nand_probe()'
Christophe Leroy (1):
crypto: talitos - reduce max key size for SEC1
Colin Ian King (2):
Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow
parport: remove non-zero check on count
Damien Le Moal (1):
libata: fix ata_host_start()
Dan Carpenter (2):
Bluetooth: sco: prevent information leak in sco_conn_defer_accept()
ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point()
Daniele Palmas (1):
net: usb: cdc_mbim: avoid altsetting toggling for Telit LN920
David Heidelberg (1):
ARM: 9105/1: atags_to_fdt: don't warn about stack size
Desmond Cheong Zhi Xi (3):
Bluetooth: fix repeated calls to sco_sock_kill
Bluetooth: skip invalid hci_sync_conn_complete_evt
Bluetooth: avoid circular locks in sco_sock_connect
Ding Hui (1):
cifs: fix wrong release in sess_alloc_buffer() failed path
Dinghao Liu (1):
qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
Dmitry Osipenko (1):
rtc: tps65910: Correct driver module alias
Dongliang Mu (2):
media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init
media: dvb-usb: fix uninit-value in vp702x_read_mac_addr
Eric Dumazet (3):
ipv4: make exception cache less predictible
net-caif: avoid user-triggerable WARN_ON(1)
net/af_unix: fix a data-race in unix_dgram_poll
Esben Haabendal (1):
net: ll_temac: Remove left-over debug message
Evgeny Novikov (1):
usb: ehci-orion: Handle errors of clk_prepare_enable() in probe
Fangrui Song (1):
powerpc/boot: Delete unneeded .globl _zimage_start
Florian Fainelli (1):
r6040: Restore MDIO clock frequency after MAC reset
Geert Uytterhoeven (1):
staging: board: Fix uninitialized spinlock when attaching genpd
Giovanni Cabiddu (4):
crypto: qat - do not ignore errors from enable_vf2pf_comms()
crypto: qat - handle both source of interrupt in VF ISR
crypto: qat - do not export adf_iov_putmsg()
crypto: qat - use proper type for vf_mask
Greg Kroah-Hartman (3):
mtd: nand: atmel_nand: remove build warning in atmel_nand_remove()
serial: 8250_pci: make setup_port() parameters explicitly unsigned
Linux 4.9.283
Grygorii Strashko (1):
PM / wakeirq: Enable dedicated wakeirq for suspend
Gustavo A. R. Silva (2):
ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs()
flow_dissector: Fix out-of-bounds warnings
Hans de Goede (3):
power: supply: axp288_fuel_gauge: Report register-address on readb / writeb errors
libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs
ASoC: Intel: bytcr_rt5640: Move "Platform Clock" routes to the maps for the matching in-/output
Heiko Carstens (1):
s390/jump_label: print real address in a case of a jump label bug
Hoang Le (1):
tipc: increase timeout in tipc_sk_enqueue()
Ilya Leoshkevich (1):
s390/bpf: Fix 64-bit subtraction of the -0x80000000 constant
J. Bruce Fields (1):
rpc: fix gss_svc_init cleanup on failure
Jack Pham (1):
usb: gadget: composite: Allow bMaxPower=0 if self-powered
Jan Kara (2):
gfs2: Don't clear SGID when inheriting ACLs
udf: Check LVID earlier
Jason Gunthorpe (1):
vfio: Use config not menuconfig for VFIO_NOIOMMU
Javier Martinez Canillas (1):
usb: phy: isp1301: Fix build warning when CONFIG_OF is disabled
Jeongtae Park (1):
regmap: fix the offset of register error log
Jiri Slaby (2):
xtensa: ISS: don't panic in rs_init
hvsi: don't panic on tty_register_driver failure
Johan Almbladh (2):
bpf/tests: Fix copy-and-paste error in double word test
bpf/tests: Do not PASS tests without actually testing the result
Jonathan Cameron (1):
iio: dac: ad5624r: Fix incorrect handling of an optional regulator.
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Juergen Gross (2):
xen: fix setting of max_pfn in shared_info
xen: reset legacy rtc flag for PV domU
Kai-Heng Feng (1):
Bluetooth: Move shutdown callback before flushing tx and rx queue
Kajol Jain (1):
powerpc/perf/hv-gpci: Fix counter value parsing
Kelly Devilliv (2):
usb: host: fotg210: fix the endpoint's transactional opportunities calculation
usb: host: fotg210: fix the actual_length of an iso packet
Kim Phillips (1):
perf/x86/amd/ibs: Work around erratum #1197
Krzysztof Kozlowski (2):
arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7
power: supply: max17042: handle fails of reading status register
Krzysztof Wilczyński (1):
PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure
Len Baker (1):
CIFS: Fix a potencially linear read overflow
Lin, Zhenpeng (1):
dccp: don't duplicate ccid when cloning dccp sock
Linus Walleij (1):
clk: kirkwood: Fix a clocking boot regression
Liu Jian (1):
igmp: Add ip_mc_list lock in ip_check_mc_rcu
Liu Zixian (1):
mm/hugetlb: initialize hugetlb_usage in mm_init
Maciej W. Rozycki (2):
serial: 8250: Define RX trigger levels for OxSemi 950 devices
scsi: BusLogic: Fix missing pr_cont() use
Maciej Żenczykowski (1):
usb: gadget: u_ether: fix a potential null pointer dereference
Marc Zyngier (1):
mfd: Don't use irq_create_mapping() to resolve a mapping
Marco Chiappero (2):
crypto: qat - fix reuse of completion variable
crypto: qat - fix naming for init/shutdown VF to PF notifications
Marek Behún (2):
PCI: Call Max Payload Size-related fixup quirks early
PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported
Marek Marczykowski-Górecki (1):
PCI/MSI: Skip masking MSI-X on Xen PV
Martin KaFai Lau (1):
tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos
Mathias Nyman (1):
Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set"
Mathieu Desnoyers (1):
ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing table (v2)
Mauro Carvalho Chehab (1):
media: uvc: don't do DMA on stack
Miaoqing Pan (1):
ath9k: fix sleeping in atomic context
Michael Ellerman (1):
powerpc/module64: Fix comment in R_PPC64_ENTRY handling
Mike Rapoport (1):
x86/mm: Fix kern_addr_valid() to cope with existing but not present entries
Mikulas Patocka (1):
parisc: fix crash with signals and alloca
Miquel Raynal (1):
dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation
Muchun Song (1):
mm/page_alloc: speed up the iteration of max_order
Nadezda Lutovinova (1):
usb: gadget: mv_u3d: request_irq() after initializing UDC
Nathan Chancellor (1):
net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe()
Nguyen Dinh Phi (1):
tty: Fix data race between tiocsti() and flush_to_ldisc()
Oleksij Rempel (1):
MIPS: Malta: fix alignment of the devicetree buffer
Patryk Duda (1):
platform/chrome: cros_ec_proto: Send command again when timeout occurs
Paul Blakey (1):
net/sched: cls_flower: Use mask for addr_type
Paul Gortmaker (1):
x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions
Pavel Skripkin (5):
media: stkwebcam: fix memory leak in stk_camera_probe
m68k: emu: Fix invalid free in nfeth_cleanup()
media: go7007: remove redundant initialization
net: cipso: fix warnings in netlbl_cipsov4_add_std
Bluetooth: add timeout sanity check to hci_inquiry
Philipp Zabel (1):
tc358743: fix register i2c_rd/wr function fix
Qu Wenruo (1):
Revert "btrfs: compression: don't try to compress if we don't have enough pages"
Rafael J. Wysocki (2):
PCI: PM: Enable PME if it can be signaled from D3cold
PCI: Use pci_update_current_state() in pci_enable_device_flags()
Rafał Miłecki (1):
net: dsa: b53: Fix calculating number of switch ports
Randy Dunlap (4):
xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG
openrisc: don't printk() unconditionally
ptp: dp83640: don't define PAGE0
ARC: export clear_user_page() for modules
Sean Anderson (2):
crypto: mxs-dcp - Check for DMA mapping errors
crypto: mxs-dcp - Use sg_mapping_iter to copy data
Sean Young (1):
media: rc-loopback: return number of emitters rather than error
Sebastian Krzyszkowiak (1):
power: supply: max17042_battery: fix typo in MAx17042_TOFF
Sergey Shtylyov (9):
i2c: highlander: add IRQ check
usb: gadget: udc: at91: add IRQ check
usb: phy: fsl-usb: add IRQ check
usb: phy: twl6030: add IRQ checks
usb: host: ohci-tmio: add IRQ check
usb: phy: tahvo: add IRQ check
i2c: iop3xx: fix deferred probing
i2c: s3c2410: fix IRQ check
i2c: mt65xx: fix IRQ check
Shai Malin (2):
qed: Fix the VF msix vectors flow
qede: Fix memset corruption
Stefan Berger (1):
certs: Trigger creation of RSA module signing key if it's not an RSA key
Stephan Gerhold (1):
soc: qcom: smsm: Fix missed interrupts if state changes while masked
Stian Skjelstad (1):
udf_get_extendedattr() had no boundary checks.
Tetsuo Handa (1):
fbmem: don't allow too huge resolutions
Theodore Ts'o (1):
ext4: fix race writing to an inline_data file while its xattrs are changing
Thomas Hebb (1):
mmc: rtsx_pci: Fix long reads when clock is prescaled
Tianjia Zhang (1):
Smack: Fix wrong semantics in smk_access_entry()
Tom Rix (1):
USB: serial: mos7720: improve OOM-handling in read_mos_reg()
Tony Lindgren (4):
crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop()
spi: spi-pic32: Fix issue with uninitialized dma_slave_config
mmc: dw_mmc: Fix issue with uninitialized dma_slave_config
mmc: moxart: Fix issue with uninitialized dma_slave_config
Tuo Li (1):
gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable access in amdgpu_i2c_router_select_ddc_port()
Vasily Averin (1):
memcg: enable accounting for pids in nested pid namespaces
Vasily Gorbik (1):
s390/disassembler: correct disassembly lines alignment
Wang Hai (1):
VMCI: fix NULL pointer dereference when unmapping queue pair
Xiyu Yang (1):
net/l2tp: Fix reference count leak in l2tp_udp_recv_core
Yajun Deng (1):
netlink: Deal with ESRCH error in nlmsg_notify()
Yang Li (1):
ethtool: Fix an error code in cxgb2.c
Yang Yingliang (1):
net: w5100: check return value after calling platform_get_resource()
Yoshihiro Shimoda (1):
net: renesas: sh_eth: Fix freeing wrong tx descriptor
Zekun Shen (1):
ath9k: fix OOB read ar9300_eeprom_restore_internal
Zelin Deng (1):
KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is adjusted
Zenghui Yu (1):
bcma: Fix memory leak for internally-handled cores
Zhen Lei (1):
pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry()
Zheyu Ma (5):
video: fbdev: kyro: fix a DoS bug by restricting user input
tty: serial: jsm: hold port lock when reporting modem line changes
video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
video: fbdev: kyro: Error out if 'pixclock' equals zero
video: fbdev: riva: Error out if 'pixclock' equals zero
Zubin Mithra (1):
ALSA: pcm: fix divide error in snd_pcm_lib_ioctl
zhenggy (1):
tcp: fix tp->undo_retrans accounting in tcp_sacktag_one()
zhenwei pi (1):
crypto: public_key: fix overflow during implicit conversion
王贇 (1):
net: fix NULL pointer reference in cipso_v4_doi_free
^ permalink raw reply [relevance 2%]
* Linux 4.4.284
@ 2021-09-22 11:12 2% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-09-22 11:12 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 4.4.284 kernel.
All users of the 4.4 kernel series must upgrade.
The updated 4.4.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-4.4.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/devicetree/bindings/mtd/gpmc-nand.txt | 2
Makefile | 2
arch/arc/Kconfig | 2
arch/arc/mm/cache.c | 2
arch/arm/boot/compressed/Makefile | 2
arch/arm/boot/dts/tegra20-tamonten.dtsi | 14 +-
arch/arm/kernel/Makefile | 6 +
arch/arm/kernel/return_address.c | 4
arch/arm64/boot/dts/exynos/exynos7.dtsi | 2
arch/m68k/emu/nfeth.c | 4
arch/openrisc/kernel/entry.S | 2
arch/parisc/kernel/signal.c | 6 +
arch/powerpc/boot/crt0.S | 3
arch/powerpc/kernel/module_64.c | 2
arch/s390/kernel/dis.c | 2
arch/s390/kernel/jump_label.c | 2
arch/s390/net/bpf_jit_comp.c | 9 +
arch/x86/kernel/reboot.c | 3
arch/x86/kvm/x86.c | 4
arch/x86/mm/init_64.c | 6 -
arch/x86/xen/p2m.c | 4
arch/xtensa/Kconfig | 2
arch/xtensa/platforms/iss/console.c | 17 ++-
certs/Makefile | 8 +
drivers/ata/libata-core.c | 6 +
drivers/base/power/wakeirq.c | 12 ++
drivers/bcma/main.c | 6 -
drivers/block/Kconfig | 4
drivers/block/cryptoloop.c | 2
drivers/clk/mvebu/kirkwood.c | 1
drivers/crypto/mxs-dcp.c | 81 +++++++++--------
drivers/crypto/omap-sham.c | 2
drivers/crypto/qat/qat_common/adf_init.c | 5 -
drivers/crypto/qat/qat_common/adf_pf2vf_msg.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 2
drivers/gpu/drm/msm/dsi/dsi.c | 6 -
drivers/i2c/busses/i2c-highlander.c | 2
drivers/i2c/busses/i2c-iop3xx.c | 6 -
drivers/i2c/busses/i2c-mt65xx.c | 2
drivers/i2c/busses/i2c-s3c2410.c | 2
drivers/iio/dac/ad5624r_spi.c | 18 +++
drivers/media/i2c/tc358743.c | 2
drivers/media/rc/rc-loopback.c | 2
drivers/media/usb/dvb-usb/nova-t-usb2.c | 6 -
drivers/media/usb/dvb-usb/vp702x.c | 12 +-
drivers/media/usb/go7007/go7007-driver.c | 26 -----
drivers/media/usb/stkwebcam/stk-webcam.c | 6 -
drivers/media/usb/uvc/uvc_v4l2.c | 34 ++++---
drivers/misc/vmw_vmci/vmci_queue_pair.c | 6 -
drivers/mmc/host/dw_mmc.c | 1
drivers/mmc/host/moxart-mmc.c | 1
drivers/mmc/host/rtsx_pci_sdmmc.c | 36 ++++---
drivers/mtd/nand/cafe_nand.c | 4
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 2
drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 1
drivers/net/ethernet/qlogic/qede/qede_main.c | 2
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 1
drivers/net/ethernet/rdc/r6040.c | 9 +
drivers/net/ethernet/renesas/sh_eth.c | 1
drivers/net/ethernet/xilinx/ll_temac_main.c | 4
drivers/net/phy/dp83640_reg.h | 2
drivers/net/wireless/ath/ath.h | 3
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2
drivers/net/wireless/ath/ath6kl/wmi.c | 4
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 3
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2
drivers/net/wireless/ath/ath9k/hw.h | 1
drivers/net/wireless/ath/ath9k/main.c | 95 +++++++++++++++++++-
drivers/net/wireless/ath/key.c | 41 +++++---
drivers/parport/ieee1284_ops.c | 2
drivers/pci/msi.c | 3
drivers/pci/pci.c | 15 +--
drivers/pci/quirks.c | 13 +-
drivers/pci/syscall.c | 4
drivers/pinctrl/pinctrl-single.c | 1
drivers/platform/chrome/cros_ec_proto.c | 9 +
drivers/power/max17042_battery.c | 8 +
drivers/rtc/rtc-tps65910.c | 2
drivers/tty/hvc/hvsi.c | 19 +++-
drivers/tty/serial/8250/8250_pci.c | 2
drivers/tty/serial/8250/8250_port.c | 3
drivers/tty/serial/jsm/jsm_neo.c | 2
drivers/tty/serial/jsm/jsm_tty.c | 3
drivers/tty/tty_io.c | 4
drivers/usb/gadget/function/u_ether.c | 5 -
drivers/usb/gadget/udc/at91_udc.c | 4
drivers/usb/gadget/udc/mv_u3d_core.c | 19 ++--
drivers/usb/host/ehci-orion.c | 8 +
drivers/usb/host/fotg210-hcd.c | 5 -
drivers/usb/host/fotg210.h | 5 -
drivers/usb/host/ohci-tmio.c | 3
drivers/usb/host/xhci.c | 24 ++---
drivers/usb/phy/phy-fsl-usb.c | 2
drivers/usb/phy/phy-isp1301.c | 2
drivers/usb/phy/phy-tahvo.c | 4
drivers/usb/phy/phy-twl6030-usb.c | 5 +
drivers/usb/serial/mos7720.c | 4
drivers/video/fbdev/asiliantfb.c | 3
drivers/video/fbdev/core/fbmem.c | 7 +
drivers/video/fbdev/kyro/fbdev.c | 8 +
drivers/video/fbdev/riva/fbdev.c | 3
fs/btrfs/inode.c | 2
fs/cifs/cifs_unicode.c | 9 -
fs/cifs/sess.c | 2
fs/ext4/inline.c | 6 +
fs/gfs2/lock_dlm.c | 5 +
fs/udf/misc.c | 13 ++
include/linux/pci.h | 5 -
include/linux/power/max17042_battery.h | 2
include/linux/skbuff.h | 2
include/uapi/linux/serial_reg.h | 1
lib/test_bpf.c | 13 ++
mm/kmemleak.c | 2
mm/page_alloc.c | 8 -
net/bluetooth/cmtp/cmtp.h | 2
net/bluetooth/hci_core.c | 14 ++
net/bluetooth/hci_event.c | 15 +++
net/bluetooth/sco.c | 11 +-
net/caif/chnl_net.c | 19 ----
net/dccp/minisocks.c | 2
net/ipv4/icmp.c | 23 ++++
net/ipv4/igmp.c | 2
net/ipv4/ip_output.c | 5 -
net/ipv4/route.c | 46 ++++++---
net/ipv4/tcp_ipv4.c | 5 -
net/l2tp/l2tp_core.c | 4
net/netlabel/netlabel_cipso_v4.c | 12 +-
net/netlink/af_netlink.c | 4
net/sunrpc/auth_gss/svcauth_gss.c | 2
net/tipc/socket.c | 2
net/unix/af_unix.c | 2
security/smack/smack_access.c | 17 +--
sound/core/pcm_lib.c | 2
133 files changed, 698 insertions(+), 340 deletions(-)
Adrian Bunk (1):
bnx2x: Fix enabling network interfaces without VFs
Andreas Obergschwandtner (1):
ARM: tegra: tamonten: Fix UART pad setting
Andrew Morton (1):
mm/kmemleak.c: make cond_resched() rate-limiting more efficient
Andy Shevchenko (1):
PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
Ben Dooks (1):
ARM: 8918/2: only build return_address() if needed
Bob Peterson (1):
gfs2: Don't call dlm after protocol is unmounted
Christoph Hellwig (1):
cryptoloop: add a deprecation warning
Christophe JAILLET (2):
drm/msm/dsi: Fix some reference counted resource leaks
mtd: rawnand: cafe: Fix a resource leak in the error handling path of 'cafe_nand_probe()'
Colin Ian King (2):
Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow
parport: remove non-zero check on count
Damien Le Moal (1):
libata: fix ata_host_start()
Dan Carpenter (2):
Bluetooth: sco: prevent information leak in sco_conn_defer_accept()
ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point()
David Heidelberg (1):
ARM: 9105/1: atags_to_fdt: don't warn about stack size
Desmond Cheong Zhi Xi (2):
Bluetooth: fix repeated calls to sco_sock_kill
Bluetooth: skip invalid hci_sync_conn_complete_evt
Ding Hui (1):
cifs: fix wrong release in sess_alloc_buffer() failed path
Dinghao Liu (1):
qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
Dmitry Osipenko (1):
rtc: tps65910: Correct driver module alias
Dongliang Mu (2):
media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init
media: dvb-usb: fix uninit-value in vp702x_read_mac_addr
Eric Dumazet (3):
ipv4: make exception cache less predictible
net-caif: avoid user-triggerable WARN_ON(1)
net/af_unix: fix a data-race in unix_dgram_poll
Esben Haabendal (1):
net: ll_temac: Remove left-over debug message
Evgeny Novikov (1):
usb: ehci-orion: Handle errors of clk_prepare_enable() in probe
Fangrui Song (1):
powerpc/boot: Delete unneeded .globl _zimage_start
Florian Fainelli (1):
r6040: Restore MDIO clock frequency after MAC reset
Giovanni Cabiddu (1):
crypto: qat - do not ignore errors from enable_vf2pf_comms()
Greg Kroah-Hartman (2):
serial: 8250_pci: make setup_port() parameters explicitly unsigned
Linux 4.4.284
Grygorii Strashko (1):
PM / wakeirq: Enable dedicated wakeirq for suspend
Gustavo A. R. Silva (1):
ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs()
Hans de Goede (1):
libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs
Heiko Carstens (1):
s390/jump_label: print real address in a case of a jump label bug
Hoang Le (1):
tipc: increase timeout in tipc_sk_enqueue()
Ilya Leoshkevich (1):
s390/bpf: Fix 64-bit subtraction of the -0x80000000 constant
J. Bruce Fields (1):
rpc: fix gss_svc_init cleanup on failure
Javier Martinez Canillas (1):
usb: phy: isp1301: Fix build warning when CONFIG_OF is disabled
Jiri Slaby (2):
xtensa: ISS: don't panic in rs_init
hvsi: don't panic on tty_register_driver failure
Johan Almbladh (2):
bpf/tests: Fix copy-and-paste error in double word test
bpf/tests: Do not PASS tests without actually testing the result
Jonathan Cameron (1):
iio: dac: ad5624r: Fix incorrect handling of an optional regulator.
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Juergen Gross (1):
xen: fix setting of max_pfn in shared_info
Kai-Heng Feng (1):
Bluetooth: Move shutdown callback before flushing tx and rx queue
Kelly Devilliv (1):
usb: host: fotg210: fix the actual_length of an iso packet
Krzysztof Kozlowski (2):
arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7
power: supply: max17042: handle fails of reading status register
Krzysztof Wilczyński (1):
PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure
Len Baker (1):
CIFS: Fix a potencially linear read overflow
Lin, Zhenpeng (1):
dccp: don't duplicate ccid when cloning dccp sock
Linus Walleij (1):
clk: kirkwood: Fix a clocking boot regression
Liu Jian (1):
igmp: Add ip_mc_list lock in ip_check_mc_rcu
Maciej W. Rozycki (1):
serial: 8250: Define RX trigger levels for OxSemi 950 devices
Maciej Żenczykowski (1):
usb: gadget: u_ether: fix a potential null pointer dereference
Marco Chiappero (1):
crypto: qat - fix reuse of completion variable
Marek Behún (2):
PCI: Call Max Payload Size-related fixup quirks early
PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported
Marek Marczykowski-Górecki (1):
PCI/MSI: Skip masking MSI-X on Xen PV
Martin KaFai Lau (1):
tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos
Mathias Nyman (1):
Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set"
Mathieu Desnoyers (1):
ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing table (v2)
Mauro Carvalho Chehab (1):
media: uvc: don't do DMA on stack
Michael Ellerman (1):
powerpc/module64: Fix comment in R_PPC64_ENTRY handling
Mike Rapoport (1):
x86/mm: Fix kern_addr_valid() to cope with existing but not present entries
Mikulas Patocka (1):
parisc: fix crash with signals and alloca
Miquel Raynal (1):
dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation
Muchun Song (1):
mm/page_alloc: speed up the iteration of max_order
Nadezda Lutovinova (1):
usb: gadget: mv_u3d: request_irq() after initializing UDC
Nguyen Dinh Phi (1):
tty: Fix data race between tiocsti() and flush_to_ldisc()
Patryk Duda (1):
platform/chrome: cros_ec_proto: Send command again when timeout occurs
Paul Gortmaker (1):
x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions
Pavel Skripkin (5):
media: stkwebcam: fix memory leak in stk_camera_probe
m68k: emu: Fix invalid free in nfeth_cleanup()
media: go7007: remove redundant initialization
net: cipso: fix warnings in netlbl_cipsov4_add_std
Bluetooth: add timeout sanity check to hci_inquiry
Philipp Zabel (1):
tc358743: fix register i2c_rd/wr function fix
Qu Wenruo (1):
Revert "btrfs: compression: don't try to compress if we don't have enough pages"
Rafael J. Wysocki (2):
PCI: PM: Enable PME if it can be signaled from D3cold
PCI: Use pci_update_current_state() in pci_enable_device_flags()
Randy Dunlap (4):
xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG
openrisc: don't printk() unconditionally
ptp: dp83640: don't define PAGE0
ARC: export clear_user_page() for modules
Sean Anderson (2):
crypto: mxs-dcp - Check for DMA mapping errors
crypto: mxs-dcp - Use sg_mapping_iter to copy data
Sean Young (1):
media: rc-loopback: return number of emitters rather than error
Sebastian Krzyszkowiak (1):
power: supply: max17042_battery: fix typo in MAx17042_TOFF
Sergey Shtylyov (9):
i2c: highlander: add IRQ check
usb: gadget: udc: at91: add IRQ check
usb: phy: fsl-usb: add IRQ check
usb: phy: twl6030: add IRQ checks
usb: host: ohci-tmio: add IRQ check
usb: phy: tahvo: add IRQ check
i2c: iop3xx: fix deferred probing
i2c: s3c2410: fix IRQ check
i2c: mt65xx: fix IRQ check
Shai Malin (1):
qede: Fix memset corruption
Stefan Berger (1):
certs: Trigger creation of RSA module signing key if it's not an RSA key
Stian Skjelstad (1):
udf_get_extendedattr() had no boundary checks.
Tetsuo Handa (1):
fbmem: don't allow too huge resolutions
Theodore Ts'o (1):
ext4: fix race writing to an inline_data file while its xattrs are changing
Thomas Hebb (1):
mmc: rtsx_pci: Fix long reads when clock is prescaled
Tianjia Zhang (1):
Smack: Fix wrong semantics in smk_access_entry()
Tom Rix (1):
USB: serial: mos7720: improve OOM-handling in read_mos_reg()
Tony Lindgren (3):
crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop()
mmc: dw_mmc: Fix issue with uninitialized dma_slave_config
mmc: moxart: Fix issue with uninitialized dma_slave_config
Tuo Li (1):
gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable access in amdgpu_i2c_router_select_ddc_port()
Vasily Gorbik (1):
s390/disassembler: correct disassembly lines alignment
Vineet Gupta (1):
ARC: fix allnoconfig build warning
Wang Hai (1):
VMCI: fix NULL pointer dereference when unmapping queue pair
Xiyu Yang (1):
net/l2tp: Fix reference count leak in l2tp_udp_recv_core
Yajun Deng (1):
netlink: Deal with ESRCH error in nlmsg_notify()
Yang Li (1):
ethtool: Fix an error code in cxgb2.c
Yoshihiro Shimoda (1):
net: renesas: sh_eth: Fix freeing wrong tx descriptor
Zekun Shen (1):
ath9k: fix OOB read ar9300_eeprom_restore_internal
Zelin Deng (1):
KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is adjusted
Zenghui Yu (1):
bcma: Fix memory leak for internally-handled cores
Zhen Lei (1):
pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry()
Zheyu Ma (5):
video: fbdev: kyro: fix a DoS bug by restricting user input
tty: serial: jsm: hold port lock when reporting modem line changes
video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
video: fbdev: kyro: Error out if 'pixclock' equals zero
video: fbdev: riva: Error out if 'pixclock' equals zero
Zubin Mithra (1):
ALSA: pcm: fix divide error in snd_pcm_lib_ioctl
王贇 (1):
net: fix NULL pointer reference in cipso_v4_doi_free
^ permalink raw reply [relevance 2%]
* [PATCH 4.9 000/174] 4.9.283-rc2 review
@ 2021-09-21 12:48 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-09-21 12:48 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 4.9.283 release.
There are 174 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 23 Sep 2021 12:42:28 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.9.283-rc2.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.9.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 4.9.283-rc2
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
net: renesas: sh_eth: Fix freeing wrong tx descriptor
Dinghao Liu <dinghao.liu@zju.edu.cn>
qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
Rafał Miłecki <rafal@milecki.pl>
net: dsa: b53: Fix calculating number of switch ports
Randy Dunlap <rdunlap@infradead.org>
ARC: export clear_user_page() for modules
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mtd: rawnand: cafe: Fix a resource leak in the error handling path of 'cafe_nand_probe()'
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
Yang Li <yang.lee@linux.alibaba.com>
ethtool: Fix an error code in cxgb2.c
Daniele Palmas <dnlplm@gmail.com>
net: usb: cdc_mbim: avoid altsetting toggling for Telit LN920
Marc Zyngier <maz@kernel.org>
mfd: Don't use irq_create_mapping() to resolve a mapping
Miquel Raynal <miquel.raynal@bootlin.com>
dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation
Mike Rapoport <rppt@linux.ibm.com>
x86/mm: Fix kern_addr_valid() to cope with existing but not present entries
zhenggy <zhenggy@chinatelecom.cn>
tcp: fix tp->undo_retrans accounting in tcp_sacktag_one()
Eric Dumazet <edumazet@google.com>
net/af_unix: fix a data-race in unix_dgram_poll
Baptiste Lepers <baptiste.lepers@gmail.com>
events: Reuse value read using READ_ONCE instead of re-reading it
Hoang Le <hoang.h.le@dektech.com.au>
tipc: increase timeout in tipc_sk_enqueue()
Florian Fainelli <f.fainelli@gmail.com>
r6040: Restore MDIO clock frequency after MAC reset
Xiyu Yang <xiyuyang19@fudan.edu.cn>
net/l2tp: Fix reference count leak in l2tp_udp_recv_core
Lin, Zhenpeng <zplin@psu.edu>
dccp: don't duplicate ccid when cloning dccp sock
Randy Dunlap <rdunlap@infradead.org>
ptp: dp83640: don't define PAGE0
Eric Dumazet <edumazet@google.com>
net-caif: avoid user-triggerable WARN_ON(1)
Adrian Bunk <bunk@kernel.org>
bnx2x: Fix enabling network interfaces without VFs
Juergen Gross <jgross@suse.com>
xen: reset legacy rtc flag for PV domU
Patryk Duda <pdk@semihalf.com>
platform/chrome: cros_ec_proto: Send command again when timeout occurs
Vasily Averin <vvs@virtuozzo.com>
memcg: enable accounting for pids in nested pid namespaces
Liu Zixian <liuzixian4@huawei.com>
mm/hugetlb: initialize hugetlb_usage in mm_init
Maciej W. Rozycki <macro@orcam.me.uk>
scsi: BusLogic: Fix missing pr_cont() use
Mikulas Patocka <mpatocka@redhat.com>
parisc: fix crash with signals and alloca
Yang Yingliang <yangyingliang@huawei.com>
net: w5100: check return value after calling platform_get_resource()
王贇 <yun.wang@linux.alibaba.com>
net: fix NULL pointer reference in cipso_v4_doi_free
Miaoqing Pan <miaoqing@codeaurora.org>
ath9k: fix sleeping in atomic context
Zekun Shen <bruceshenzk@gmail.com>
ath9k: fix OOB read ar9300_eeprom_restore_internal
Colin Ian King <colin.king@canonical.com>
parport: remove non-zero check on count
Anirudh Rayabharam <mail@anirudhrb.com>
usbip: give back URBs for unsent unlink requests during cleanup
Mathias Nyman <mathias.nyman@linux.intel.com>
Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set"
Ding Hui <dinghui@sangfor.com.cn>
cifs: fix wrong release in sess_alloc_buffer() failed path
Thomas Hebb <tommyhebb@gmail.com>
mmc: rtsx_pci: Fix long reads when clock is prescaled
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't call dlm after protocol is unmounted
J. Bruce Fields <bfields@redhat.com>
rpc: fix gss_svc_init cleanup on failure
Andreas Obergschwandtner <andreas.obergschwandtner@gmail.com>
ARM: tegra: tamonten: Fix UART pad setting
Tuo Li <islituo@gmail.com>
gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable access in amdgpu_i2c_router_select_ddc_port()
Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
Bluetooth: avoid circular locks in sco_sock_connect
Nathan Chancellor <nathan@kernel.org>
net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe()
Hans de Goede <hdegoede@redhat.com>
ASoC: Intel: bytcr_rt5640: Move "Platform Clock" routes to the maps for the matching in-/output
Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
Bluetooth: skip invalid hci_sync_conn_complete_evt
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
ata: sata_dwc_460ex: No need to call phy_exit() befre phy_init()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
staging: ks7010: Fix the initialization of the 'sleep_status' structure
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
serial: 8250_pci: make setup_port() parameters explicitly unsigned
Jiri Slaby <jslaby@suse.cz>
hvsi: don't panic on tty_register_driver failure
Jiri Slaby <jslaby@suse.cz>
xtensa: ISS: don't panic in rs_init
Maciej W. Rozycki <macro@orcam.me.uk>
serial: 8250: Define RX trigger levels for OxSemi 950 devices
Heiko Carstens <hca@linux.ibm.com>
s390/jump_label: print real address in a case of a jump label bug
Gustavo A. R. Silva <gustavoars@kernel.org>
flow_dissector: Fix out-of-bounds warnings
Gustavo A. R. Silva <gustavoars@kernel.org>
ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs()
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: riva: Error out if 'pixclock' equals zero
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: kyro: Error out if 'pixclock' equals zero
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
Johan Almbladh <johan.almbladh@anyfinetworks.com>
bpf/tests: Do not PASS tests without actually testing the result
Johan Almbladh <johan.almbladh@anyfinetworks.com>
bpf/tests: Fix copy-and-paste error in double word test
Zheyu Ma <zheyuma97@gmail.com>
tty: serial: jsm: hold port lock when reporting modem line changes
Geert Uytterhoeven <geert+renesas@glider.be>
staging: board: Fix uninitialized spinlock when attaching genpd
Jack Pham <jackp@codeaurora.org>
usb: gadget: composite: Allow bMaxPower=0 if self-powered
Maciej Żenczykowski <maze@google.com>
usb: gadget: u_ether: fix a potential null pointer dereference
Kelly Devilliv <kelly.devilliv@gmail.com>
usb: host: fotg210: fix the actual_length of an iso packet
Kelly Devilliv <kelly.devilliv@gmail.com>
usb: host: fotg210: fix the endpoint's transactional opportunities calculation
Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
Smack: Fix wrong semantics in smk_access_entry()
Yajun Deng <yajun.deng@linux.dev>
netlink: Deal with ESRCH error in nlmsg_notify()
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: kyro: fix a DoS bug by restricting user input
Jonathan Cameron <Jonathan.Cameron@huawei.com>
iio: dac: ad5624r: Fix incorrect handling of an optional regulator.
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PCI: Use pci_update_current_state() in pci_enable_device_flags()
Sean Anderson <sean.anderson@seco.com>
crypto: mxs-dcp - Use sg_mapping_iter to copy data
Oleksij Rempel <o.rempel@pengutronix.de>
MIPS: Malta: fix alignment of the devicetree buffer
Zhen Lei <thunder.leizhen@huawei.com>
pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry()
Randy Dunlap <rdunlap@infradead.org>
openrisc: don't printk() unconditionally
Jason Gunthorpe <jgg@nvidia.com>
vfio: Use config not menuconfig for VFIO_NOIOMMU
Krzysztof Wilczyński <kw@linux.com>
PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure
Marek Behún <kabel@kernel.org>
PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported
David Heidelberg <david@ixit.cz>
ARM: 9105/1: atags_to_fdt: don't warn about stack size
Hans de Goede <hdegoede@redhat.com>
libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs
Sean Young <sean@mess.org>
media: rc-loopback: return number of emitters rather than error
Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
media: uvc: don't do DMA on stack
Wang Hai <wanghai38@huawei.com>
VMCI: fix NULL pointer dereference when unmapping queue pair
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
power: supply: max17042: handle fails of reading status register
zhenwei pi <pizhenwei@bytedance.com>
crypto: public_key: fix overflow during implicit conversion
Juergen Gross <jgross@suse.com>
xen: fix setting of max_pfn in shared_info
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf/hv-gpci: Fix counter value parsing
Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
PCI/MSI: Skip masking MSI-X on Xen PV
Dmitry Osipenko <digetx@gmail.com>
rtc: tps65910: Correct driver module alias
Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
fbmem: don't allow too huge resolutions
Linus Walleij <linus.walleij@linaro.org>
clk: kirkwood: Fix a clocking boot regression
Austin Kim <austin.kim@lge.com>
IMA: remove -Wmissing-prototypes warning
Zelin Deng <zelin.deng@linux.alibaba.com>
KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is adjusted
Nguyen Dinh Phi <phind.uet@gmail.com>
tty: Fix data race between tiocsti() and flush_to_ldisc()
Eric Dumazet <edumazet@google.com>
ipv4: make exception cache less predictible
Zenghui Yu <yuzenghui@huawei.com>
bcma: Fix memory leak for internally-handled cores
Dan Carpenter <dan.carpenter@oracle.com>
ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point()
Evgeny Novikov <novikov@ispras.ru>
usb: ehci-orion: Handle errors of clk_prepare_enable() in probe
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: mt65xx: fix IRQ check
Len Baker <len.baker@gmx.com>
CIFS: Fix a potencially linear read overflow
Tony Lindgren <tony@atomide.com>
mmc: moxart: Fix issue with uninitialized dma_slave_config
Tony Lindgren <tony@atomide.com>
mmc: dw_mmc: Fix issue with uninitialized dma_slave_config
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: s3c2410: fix IRQ check
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: iop3xx: fix deferred probing
Pavel Skripkin <paskripkin@gmail.com>
Bluetooth: add timeout sanity check to hci_inquiry
Nadezda Lutovinova <lutovinova@ispras.ru>
usb: gadget: mv_u3d: request_irq() after initializing UDC
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: phy: tahvo: add IRQ check
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: host: ohci-tmio: add IRQ check
Kai-Heng Feng <kai.heng.feng@canonical.com>
Bluetooth: Move shutdown callback before flushing tx and rx queue
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: phy: twl6030: add IRQ checks
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: phy: fsl-usb: add IRQ check
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: gadget: udc: at91: add IRQ check
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
drm/msm/dsi: Fix some reference counted resource leaks
Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
Bluetooth: fix repeated calls to sco_sock_kill
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7
Colin Ian King <colin.king@canonical.com>
Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow
Stephan Gerhold <stephan@gerhold.net>
soc: qcom: smsm: Fix missed interrupts if state changes while masked
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PCI: PM: Enable PME if it can be signaled from D3cold
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: highlander: add IRQ check
Pavel Skripkin <paskripkin@gmail.com>
net: cipso: fix warnings in netlbl_cipsov4_add_std
Martin KaFai Lau <kafai@fb.com>
tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos
Dan Carpenter <dan.carpenter@oracle.com>
Bluetooth: sco: prevent information leak in sco_conn_defer_accept()
Pavel Skripkin <paskripkin@gmail.com>
media: go7007: remove redundant initialization
Dongliang Mu <mudongliangabcd@gmail.com>
media: dvb-usb: fix uninit-value in vp702x_read_mac_addr
Dongliang Mu <mudongliangabcd@gmail.com>
media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init
Stefan Berger <stefanb@linux.ibm.com>
certs: Trigger creation of RSA module signing key if it's not an RSA key
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - use proper type for vf_mask
Tony Lindgren <tony@atomide.com>
spi: spi-pic32: Fix issue with uninitialized dma_slave_config
Pavel Skripkin <paskripkin@gmail.com>
m68k: emu: Fix invalid free in nfeth_cleanup()
Stian Skjelstad <stian.skjelstad@gmail.com>
udf_get_extendedattr() had no boundary checks.
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - do not export adf_iov_putmsg()
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - fix naming for init/shutdown VF to PF notifications
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - fix reuse of completion variable
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - handle both source of interrupt in VF ISR
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - do not ignore errors from enable_vf2pf_comms()
Damien Le Moal <damien.lemoal@wdc.com>
libata: fix ata_host_start()
Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
power: supply: max17042_battery: fix typo in MAx17042_TOFF
Jan Kara <jack@suse.cz>
udf: Check LVID earlier
Tony Lindgren <tony@atomide.com>
crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop()
Hans de Goede <hdegoede@redhat.com>
power: supply: axp288_fuel_gauge: Report register-address on readb / writeb errors
Sean Anderson <sean.anderson@seco.com>
crypto: mxs-dcp - Check for DMA mapping errors
Jeongtae Park <jeongtae.park@gmail.com>
regmap: fix the offset of register error log
Marek Behún <kabel@kernel.org>
PCI: Call Max Payload Size-related fixup quirks early
Paul Gortmaker <paul.gortmaker@windriver.com>
x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions
Qu Wenruo <wqu@suse.com>
Revert "btrfs: compression: don't try to compress if we don't have enough pages"
Muchun Song <songmuchun@bytedance.com>
mm/page_alloc: speed up the iteration of max_order
Esben Haabendal <esben@geanix.com>
net: ll_temac: Remove left-over debug message
Fangrui Song <maskray@google.com>
powerpc/boot: Delete unneeded .globl _zimage_start
Michael Ellerman <mpe@ellerman.id.au>
powerpc/module64: Fix comment in R_PPC64_ENTRY handling
Christophe Leroy <christophe.leroy@c-s.fr>
crypto: talitos - reduce max key size for SEC1
Andrew Morton <akpm@linux-foundation.org>
mm/kmemleak.c: make cond_resched() rate-limiting more efficient
Vasily Gorbik <gor@linux.vnet.ibm.com>
s390/disassembler: correct disassembly lines alignment
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing table (v2)
Jan Kara <jack@suse.cz>
gfs2: Don't clear SGID when inheriting ACLs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
nvme-pci: Fix an error handling path in 'nvme_probe()'
Philipp Zabel <p.zabel@pengutronix.de>
tc358743: fix register i2c_rd/wr function fix
Grygorii Strashko <grygorii.strashko@ti.com>
PM / wakeirq: Enable dedicated wakeirq for suspend
Paul Blakey <paulb@mellanox.com>
net/sched: cls_flower: Use mask for addr_type
Tom Rix <trix@redhat.com>
USB: serial: mos7720: improve OOM-handling in read_mos_reg()
Javier Martinez Canillas <javier@osg.samsung.com>
usb: phy: isp1301: Fix build warning when CONFIG_OF is disabled
Liu Jian <liujian56@huawei.com>
igmp: Add ip_mc_list lock in ip_check_mc_rcu
Pavel Skripkin <paskripkin@gmail.com>
media: stkwebcam: fix memory leak in stk_camera_probe
Jouni Malinen <jouni@codeaurora.org>
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Jouni Malinen <jouni@codeaurora.org>
ath: Modify ath_key_delete() to not need full key entry
Jouni Malinen <jouni@codeaurora.org>
ath: Export ath_hw_keysetmac()
Jouni Malinen <jouni@codeaurora.org>
ath9k: Clear key cache explicitly on disabling hardware
Jouni Malinen <jouni@codeaurora.org>
ath: Use safer key clearing with key cache entries
Zubin Mithra <zsm@chromium.org>
ALSA: pcm: fix divide error in snd_pcm_lib_ioctl
Ben Dooks <ben-linux@fluff.org>
ARM: 8918/2: only build return_address() if needed
Christoph Hellwig <hch@lst.de>
cryptoloop: add a deprecation warning
Kim Phillips <kim.phillips@amd.com>
perf/x86/amd/ibs: Work around erratum #1197
Shai Malin <smalin@marvell.com>
qede: Fix memset corruption
Shai Malin <smalin@marvell.com>
qed: Fix the VF msix vectors flow
Randy Dunlap <rdunlap@infradead.org>
xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
mtd: nand: atmel_nand: remove build warning in atmel_nand_remove()
Theodore Ts'o <tytso@mit.edu>
ext4: fix race writing to an inline_data file while its xattrs are changing
-------------
Diffstat:
.../devicetree/bindings/mtd/gpmc-nand.txt | 2 +-
Makefile | 4 +-
arch/arc/mm/cache.c | 2 +-
arch/arm/boot/compressed/Makefile | 2 +
arch/arm/boot/dts/tegra20-tamonten.dtsi | 14 ++--
arch/arm/kernel/Makefile | 6 +-
arch/arm/kernel/return_address.c | 4 -
arch/arm64/boot/dts/exynos/exynos7.dtsi | 2 +-
arch/m68k/emu/nfeth.c | 4 +-
arch/mips/mti-malta/malta-dtshim.c | 2 +-
arch/openrisc/kernel/entry.S | 2 +
arch/parisc/kernel/signal.c | 6 ++
arch/powerpc/boot/crt0.S | 3 -
arch/powerpc/kernel/module_64.c | 2 +-
arch/powerpc/perf/hv-gpci.c | 2 +-
arch/s390/kernel/dis.c | 2 +-
arch/s390/kernel/jump_label.c | 2 +-
arch/x86/events/amd/ibs.c | 8 ++
arch/x86/kernel/reboot.c | 3 +-
arch/x86/kvm/x86.c | 4 +
arch/x86/mm/init_64.c | 6 +-
arch/x86/xen/enlighten.c | 7 ++
arch/x86/xen/p2m.c | 4 +-
arch/xtensa/Kconfig | 2 +-
arch/xtensa/platforms/iss/console.c | 17 +++-
certs/Makefile | 8 ++
drivers/ata/libata-core.c | 6 +-
drivers/ata/sata_dwc_460ex.c | 12 +--
drivers/base/power/wakeirq.c | 12 ++-
drivers/base/regmap/regmap.c | 2 +-
drivers/bcma/main.c | 6 +-
drivers/block/Kconfig | 4 +-
drivers/block/cryptoloop.c | 2 +
drivers/clk/mvebu/kirkwood.c | 1 +
drivers/crypto/mxs-dcp.c | 81 +++++++++---------
drivers/crypto/omap-sham.c | 2 +-
.../crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c | 4 +-
drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c | 4 +-
drivers/crypto/qat/qat_common/adf_common_drv.h | 8 +-
drivers/crypto/qat/qat_common/adf_init.c | 5 +-
drivers/crypto/qat/qat_common/adf_isr.c | 7 +-
drivers/crypto/qat/qat_common/adf_pf2vf_msg.c | 3 +-
drivers/crypto/qat/qat_common/adf_vf2pf_msg.c | 12 +--
drivers/crypto/qat/qat_common/adf_vf_isr.c | 7 +-
.../qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c | 4 +-
drivers/crypto/talitos.c | 4 +
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 2 +-
drivers/gpu/drm/msm/dsi/dsi.c | 6 +-
drivers/i2c/busses/i2c-highlander.c | 2 +-
drivers/i2c/busses/i2c-iop3xx.c | 6 +-
drivers/i2c/busses/i2c-mt65xx.c | 2 +-
drivers/i2c/busses/i2c-s3c2410.c | 2 +-
drivers/iio/dac/ad5624r_spi.c | 18 +++-
drivers/media/i2c/tc358743.c | 2 +-
drivers/media/rc/rc-loopback.c | 2 +-
drivers/media/usb/dvb-usb/nova-t-usb2.c | 6 +-
drivers/media/usb/dvb-usb/vp702x.c | 12 ++-
drivers/media/usb/go7007/go7007-driver.c | 26 ------
drivers/media/usb/stkwebcam/stk-webcam.c | 6 +-
drivers/media/usb/uvc/uvc_v4l2.c | 34 +++++---
drivers/mfd/ab8500-core.c | 2 +-
drivers/mfd/stmpe.c | 4 +-
drivers/mfd/tc3589x.c | 2 +-
drivers/mfd/wm8994-irq.c | 2 +-
drivers/misc/vmw_vmci/vmci_queue_pair.c | 6 +-
drivers/mmc/host/dw_mmc.c | 1 +
drivers/mmc/host/moxart-mmc.c | 1 +
drivers/mmc/host/rtsx_pci_sdmmc.c | 36 +++++---
drivers/mtd/nand/atmel_nand.c | 1 -
drivers/mtd/nand/cafe_nand.c | 4 +-
drivers/net/dsa/b53/b53_common.c | 3 +-
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 2 +-
drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 1 +
drivers/net/ethernet/qlogic/qed/qed_main.c | 7 +-
drivers/net/ethernet/qlogic/qede/qede_main.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 1 -
drivers/net/ethernet/rdc/r6040.c | 9 +-
drivers/net/ethernet/renesas/sh_eth.c | 1 +
.../net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 18 ++--
drivers/net/ethernet/wiznet/w5100.c | 2 +
drivers/net/ethernet/xilinx/ll_temac_main.c | 4 +-
drivers/net/phy/dp83640_reg.h | 2 +-
drivers/net/usb/cdc_mbim.c | 5 ++
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath6kl/wmi.c | 4 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 3 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.c | 12 +--
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 +++++++++++++++++++++-
drivers/net/wireless/ath/key.c | 41 ++++++----
drivers/nvme/host/pci.c | 7 +-
drivers/parport/ieee1284_ops.c | 2 +-
drivers/pci/msi.c | 3 +
drivers/pci/pci.c | 15 ++--
drivers/pci/quirks.c | 13 +--
drivers/pci/syscall.c | 4 +-
drivers/pinctrl/pinctrl-single.c | 1 +
drivers/platform/chrome/cros_ec_proto.c | 9 ++
drivers/power/supply/axp288_fuel_gauge.c | 4 +-
drivers/power/supply/max17042_battery.c | 8 +-
drivers/rtc/rtc-tps65910.c | 2 +-
drivers/scsi/BusLogic.c | 4 +-
drivers/soc/qcom/smsm.c | 11 ++-
drivers/spi/spi-pic32.c | 1 +
drivers/staging/board/board.c | 7 +-
drivers/staging/ks7010/ks7010_sdio.c | 2 +-
drivers/tty/hvc/hvsi.c | 19 ++++-
drivers/tty/serial/8250/8250_pci.c | 2 +-
drivers/tty/serial/8250/8250_port.c | 3 +-
drivers/tty/serial/jsm/jsm_neo.c | 2 +
drivers/tty/serial/jsm/jsm_tty.c | 3 +
drivers/tty/tty_io.c | 4 +-
drivers/usb/gadget/composite.c | 8 +-
drivers/usb/gadget/function/u_ether.c | 5 +-
drivers/usb/gadget/udc/at91_udc.c | 4 +-
drivers/usb/gadget/udc/mv_u3d_core.c | 19 +++--
drivers/usb/host/ehci-orion.c | 8 +-
drivers/usb/host/fotg210-hcd.c | 41 +++++-----
drivers/usb/host/fotg210.h | 5 --
drivers/usb/host/ohci-tmio.c | 3 +
drivers/usb/host/xhci.c | 24 +++---
drivers/usb/phy/phy-fsl-usb.c | 2 +
drivers/usb/phy/phy-isp1301.c | 2 +-
drivers/usb/phy/phy-tahvo.c | 4 +-
drivers/usb/phy/phy-twl6030-usb.c | 5 ++
drivers/usb/serial/mos7720.c | 4 +-
drivers/usb/usbip/vhci_hcd.c | 24 ++++++
drivers/vfio/Kconfig | 2 +-
drivers/video/fbdev/asiliantfb.c | 3 +
drivers/video/fbdev/core/fbmem.c | 7 ++
drivers/video/fbdev/kyro/fbdev.c | 8 ++
drivers/video/fbdev/riva/fbdev.c | 3 +
fs/btrfs/inode.c | 2 +-
fs/cifs/cifs_unicode.c | 9 +-
fs/cifs/sess.c | 2 +-
fs/ext4/inline.c | 6 ++
fs/gfs2/acl.c | 27 +++---
fs/gfs2/lock_dlm.c | 5 ++
fs/udf/misc.c | 13 ++-
fs/udf/super.c | 25 ++++--
include/crypto/public_key.h | 4 +-
include/linux/hugetlb.h | 9 ++
include/linux/pci.h | 5 +-
include/linux/power/max17042_battery.h | 2 +-
include/linux/skbuff.h | 2 +-
include/uapi/linux/serial_reg.h | 1 +
kernel/events/core.c | 2 +-
kernel/fork.c | 1 +
kernel/pid_namespace.c | 2 +-
lib/test_bpf.c | 13 ++-
mm/kmemleak.c | 2 +-
mm/page_alloc.c | 8 +-
net/bluetooth/cmtp/cmtp.h | 2 +-
net/bluetooth/hci_core.c | 14 ++++
net/bluetooth/hci_event.c | 15 ++++
net/bluetooth/sco.c | 50 +++++-------
net/caif/chnl_net.c | 19 +----
net/core/flow_dissector.c | 12 ++-
net/dccp/minisocks.c | 2 +
net/ipv4/icmp.c | 23 +++++-
net/ipv4/igmp.c | 2 +
net/ipv4/ip_output.c | 5 +-
net/ipv4/route.c | 46 +++++++----
net/ipv4/tcp_input.c | 2 +-
net/ipv4/tcp_ipv4.c | 5 +-
net/l2tp/l2tp_core.c | 4 +-
net/netlabel/netlabel_cipso_v4.c | 12 +--
net/netlink/af_netlink.c | 4 +-
net/sched/cls_flower.c | 4 +
net/sunrpc/auth_gss/svcauth_gss.c | 2 +-
net/tipc/socket.c | 2 +-
net/unix/af_unix.c | 2 +-
security/integrity/ima/ima_mok.c | 2 +-
security/smack/smack_access.c | 17 ++--
sound/core/pcm_lib.c | 2 +-
sound/soc/intel/boards/bytcr_rt5640.c | 9 +-
178 files changed, 927 insertions(+), 488 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.14 053/168] net: stmmac: fix system hang caused by eee_ctrl_timer during suspend/resume
@ 2021-09-20 16:43 4% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-09-20 16:43 UTC (permalink / raw)
To: linux-kernel; +Cc: Greg Kroah-Hartman, stable, Joakim Zhang, David S. Miller
From: Joakim Zhang <qiangqing.zhang@nxp.com>
commit 276aae377206d60b9b7b7df4586cd9f2a813f5d0 upstream.
commit 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after
napi disabled"), this patch tries to fix system hang caused by eee_ctrl_timer,
unfortunately, it only can resolve it for system reboot stress test. System
hang also can be reproduced easily during system suspend/resume stess test
when mount NFS on i.MX8MP EVK board.
In stmmac driver, eee feature is combined to phylink framework. When do
system suspend, phylink_stop() would queue delayed work, it invokes
stmmac_mac_link_down(), where to deactivate eee_ctrl_timer synchronizly.
In above commit, try to fix issue by deactivating eee_ctrl_timer obviously,
but it is not enough. Looking into eee_ctrl_timer expire callback
stmmac_eee_ctrl_timer(), it could enable hareware eee mode again. What is
unexpected is that LPI interrupt (MAC_Interrupt_Enable.LPIEN bit) is always
asserted. This interrupt has chance to be issued when LPI state entry/exit
from the MAC, and at that time, clock could have been already disabled.
The result is that system hang when driver try to touch register from
interrupt handler.
The reason why above commit can fix system hang issue in stmmac_release()
is that, deactivate eee_ctrl_timer not just after napi disabled, further
after irq freed.
In conclusion, hardware would generate LPI interrupt when clock has been
disabled during suspend or resume, since hardware is in eee mode and LPI
interrupt enabled.
Interrupts from MAC, MTL and DMA level are enabled and never been disabled
when system suspend, so postpone clocks management from suspend stage to
noirq suspend stage should be more safe.
Fixes: 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after napi disabled")
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 14 -----
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 44 ++++++++++++++++++
2 files changed, 44 insertions(+), 14 deletions(-)
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7113,7 +7113,6 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan;
- int ret;
if (!ndev || !netif_running(ndev))
return 0;
@@ -7155,13 +7154,6 @@ int stmmac_suspend(struct device *dev)
stmmac_mac_set(priv, priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- clk_disable_unprepare(priv->plat->clk_ptp_ref);
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
}
mutex_unlock(&priv->lock);
@@ -7237,12 +7229,6 @@ int stmmac_resume(struct device *dev)
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
- /* enable the clk previously disabled */
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
- if (priv->plat->clk_ptp_ref)
- clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,7 @@
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -771,9 +772,52 @@ static int __maybe_unused stmmac_runtime
return stmmac_bus_clks_config(priv, true);
}
+static int stmmac_pltfr_noirq_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmmac_pltfr_noirq_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* enable the clk previously disabled */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ }
+
+ return 0;
+}
+
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
^ permalink raw reply [relevance 4%]
* [PATCH 4.9 000/175] 4.9.283-rc1 review
@ 2021-09-20 16:40 1% Greg Kroah-Hartman
2021-09-20 16:41 5% ` [PATCH 4.9 014/175] ath9k: Postpone key cache entry deletion for TXQ frames reference it Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2021-09-20 16:40 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 4.9.283 release.
There are 175 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 22 Sep 2021 16:38:49 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.9.283-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.9.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 4.9.283-rc1
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
net: renesas: sh_eth: Fix freeing wrong tx descriptor
Dinghao Liu <dinghao.liu@zju.edu.cn>
qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
Rafał Miłecki <rafal@milecki.pl>
net: dsa: b53: Fix calculating number of switch ports
Randy Dunlap <rdunlap@infradead.org>
ARC: export clear_user_page() for modules
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mtd: rawnand: cafe: Fix a resource leak in the error handling path of 'cafe_nand_probe()'
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
Yang Li <yang.lee@linux.alibaba.com>
ethtool: Fix an error code in cxgb2.c
Daniele Palmas <dnlplm@gmail.com>
net: usb: cdc_mbim: avoid altsetting toggling for Telit LN920
Marc Zyngier <maz@kernel.org>
mfd: Don't use irq_create_mapping() to resolve a mapping
Miquel Raynal <miquel.raynal@bootlin.com>
dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation
Mike Rapoport <rppt@linux.ibm.com>
x86/mm: Fix kern_addr_valid() to cope with existing but not present entries
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: check failover_pending in login response
zhenggy <zhenggy@chinatelecom.cn>
tcp: fix tp->undo_retrans accounting in tcp_sacktag_one()
Eric Dumazet <edumazet@google.com>
net/af_unix: fix a data-race in unix_dgram_poll
Baptiste Lepers <baptiste.lepers@gmail.com>
events: Reuse value read using READ_ONCE instead of re-reading it
Hoang Le <hoang.h.le@dektech.com.au>
tipc: increase timeout in tipc_sk_enqueue()
Florian Fainelli <f.fainelli@gmail.com>
r6040: Restore MDIO clock frequency after MAC reset
Xiyu Yang <xiyuyang19@fudan.edu.cn>
net/l2tp: Fix reference count leak in l2tp_udp_recv_core
Lin, Zhenpeng <zplin@psu.edu>
dccp: don't duplicate ccid when cloning dccp sock
Randy Dunlap <rdunlap@infradead.org>
ptp: dp83640: don't define PAGE0
Eric Dumazet <edumazet@google.com>
net-caif: avoid user-triggerable WARN_ON(1)
Adrian Bunk <bunk@kernel.org>
bnx2x: Fix enabling network interfaces without VFs
Juergen Gross <jgross@suse.com>
xen: reset legacy rtc flag for PV domU
Patryk Duda <pdk@semihalf.com>
platform/chrome: cros_ec_proto: Send command again when timeout occurs
Vasily Averin <vvs@virtuozzo.com>
memcg: enable accounting for pids in nested pid namespaces
Liu Zixian <liuzixian4@huawei.com>
mm/hugetlb: initialize hugetlb_usage in mm_init
Maciej W. Rozycki <macro@orcam.me.uk>
scsi: BusLogic: Fix missing pr_cont() use
Mikulas Patocka <mpatocka@redhat.com>
parisc: fix crash with signals and alloca
Yang Yingliang <yangyingliang@huawei.com>
net: w5100: check return value after calling platform_get_resource()
王贇 <yun.wang@linux.alibaba.com>
net: fix NULL pointer reference in cipso_v4_doi_free
Miaoqing Pan <miaoqing@codeaurora.org>
ath9k: fix sleeping in atomic context
Zekun Shen <bruceshenzk@gmail.com>
ath9k: fix OOB read ar9300_eeprom_restore_internal
Colin Ian King <colin.king@canonical.com>
parport: remove non-zero check on count
Anirudh Rayabharam <mail@anirudhrb.com>
usbip: give back URBs for unsent unlink requests during cleanup
Mathias Nyman <mathias.nyman@linux.intel.com>
Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set"
Ding Hui <dinghui@sangfor.com.cn>
cifs: fix wrong release in sess_alloc_buffer() failed path
Thomas Hebb <tommyhebb@gmail.com>
mmc: rtsx_pci: Fix long reads when clock is prescaled
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't call dlm after protocol is unmounted
J. Bruce Fields <bfields@redhat.com>
rpc: fix gss_svc_init cleanup on failure
Andreas Obergschwandtner <andreas.obergschwandtner@gmail.com>
ARM: tegra: tamonten: Fix UART pad setting
Tuo Li <islituo@gmail.com>
gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable access in amdgpu_i2c_router_select_ddc_port()
Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
Bluetooth: avoid circular locks in sco_sock_connect
Nathan Chancellor <nathan@kernel.org>
net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe()
Hans de Goede <hdegoede@redhat.com>
ASoC: Intel: bytcr_rt5640: Move "Platform Clock" routes to the maps for the matching in-/output
Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
Bluetooth: skip invalid hci_sync_conn_complete_evt
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
ata: sata_dwc_460ex: No need to call phy_exit() befre phy_init()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
staging: ks7010: Fix the initialization of the 'sleep_status' structure
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
serial: 8250_pci: make setup_port() parameters explicitly unsigned
Jiri Slaby <jslaby@suse.cz>
hvsi: don't panic on tty_register_driver failure
Jiri Slaby <jslaby@suse.cz>
xtensa: ISS: don't panic in rs_init
Maciej W. Rozycki <macro@orcam.me.uk>
serial: 8250: Define RX trigger levels for OxSemi 950 devices
Heiko Carstens <hca@linux.ibm.com>
s390/jump_label: print real address in a case of a jump label bug
Gustavo A. R. Silva <gustavoars@kernel.org>
flow_dissector: Fix out-of-bounds warnings
Gustavo A. R. Silva <gustavoars@kernel.org>
ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs()
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: riva: Error out if 'pixclock' equals zero
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: kyro: Error out if 'pixclock' equals zero
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
Johan Almbladh <johan.almbladh@anyfinetworks.com>
bpf/tests: Do not PASS tests without actually testing the result
Johan Almbladh <johan.almbladh@anyfinetworks.com>
bpf/tests: Fix copy-and-paste error in double word test
Zheyu Ma <zheyuma97@gmail.com>
tty: serial: jsm: hold port lock when reporting modem line changes
Geert Uytterhoeven <geert+renesas@glider.be>
staging: board: Fix uninitialized spinlock when attaching genpd
Jack Pham <jackp@codeaurora.org>
usb: gadget: composite: Allow bMaxPower=0 if self-powered
Maciej Żenczykowski <maze@google.com>
usb: gadget: u_ether: fix a potential null pointer dereference
Kelly Devilliv <kelly.devilliv@gmail.com>
usb: host: fotg210: fix the actual_length of an iso packet
Kelly Devilliv <kelly.devilliv@gmail.com>
usb: host: fotg210: fix the endpoint's transactional opportunities calculation
Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
Smack: Fix wrong semantics in smk_access_entry()
Yajun Deng <yajun.deng@linux.dev>
netlink: Deal with ESRCH error in nlmsg_notify()
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: kyro: fix a DoS bug by restricting user input
Jonathan Cameron <Jonathan.Cameron@huawei.com>
iio: dac: ad5624r: Fix incorrect handling of an optional regulator.
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PCI: Use pci_update_current_state() in pci_enable_device_flags()
Sean Anderson <sean.anderson@seco.com>
crypto: mxs-dcp - Use sg_mapping_iter to copy data
Oleksij Rempel <o.rempel@pengutronix.de>
MIPS: Malta: fix alignment of the devicetree buffer
Zhen Lei <thunder.leizhen@huawei.com>
pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry()
Randy Dunlap <rdunlap@infradead.org>
openrisc: don't printk() unconditionally
Jason Gunthorpe <jgg@nvidia.com>
vfio: Use config not menuconfig for VFIO_NOIOMMU
Krzysztof Wilczyński <kw@linux.com>
PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure
Marek Behún <kabel@kernel.org>
PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported
David Heidelberg <david@ixit.cz>
ARM: 9105/1: atags_to_fdt: don't warn about stack size
Hans de Goede <hdegoede@redhat.com>
libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs
Sean Young <sean@mess.org>
media: rc-loopback: return number of emitters rather than error
Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
media: uvc: don't do DMA on stack
Wang Hai <wanghai38@huawei.com>
VMCI: fix NULL pointer dereference when unmapping queue pair
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
power: supply: max17042: handle fails of reading status register
zhenwei pi <pizhenwei@bytedance.com>
crypto: public_key: fix overflow during implicit conversion
Juergen Gross <jgross@suse.com>
xen: fix setting of max_pfn in shared_info
Kajol Jain <kjain@linux.ibm.com>
powerpc/perf/hv-gpci: Fix counter value parsing
Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
PCI/MSI: Skip masking MSI-X on Xen PV
Dmitry Osipenko <digetx@gmail.com>
rtc: tps65910: Correct driver module alias
Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
fbmem: don't allow too huge resolutions
Linus Walleij <linus.walleij@linaro.org>
clk: kirkwood: Fix a clocking boot regression
Austin Kim <austin.kim@lge.com>
IMA: remove -Wmissing-prototypes warning
Zelin Deng <zelin.deng@linux.alibaba.com>
KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is adjusted
Nguyen Dinh Phi <phind.uet@gmail.com>
tty: Fix data race between tiocsti() and flush_to_ldisc()
Eric Dumazet <edumazet@google.com>
ipv4: make exception cache less predictible
Zenghui Yu <yuzenghui@huawei.com>
bcma: Fix memory leak for internally-handled cores
Dan Carpenter <dan.carpenter@oracle.com>
ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point()
Evgeny Novikov <novikov@ispras.ru>
usb: ehci-orion: Handle errors of clk_prepare_enable() in probe
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: mt65xx: fix IRQ check
Len Baker <len.baker@gmx.com>
CIFS: Fix a potencially linear read overflow
Tony Lindgren <tony@atomide.com>
mmc: moxart: Fix issue with uninitialized dma_slave_config
Tony Lindgren <tony@atomide.com>
mmc: dw_mmc: Fix issue with uninitialized dma_slave_config
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: s3c2410: fix IRQ check
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: iop3xx: fix deferred probing
Pavel Skripkin <paskripkin@gmail.com>
Bluetooth: add timeout sanity check to hci_inquiry
Nadezda Lutovinova <lutovinova@ispras.ru>
usb: gadget: mv_u3d: request_irq() after initializing UDC
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: phy: tahvo: add IRQ check
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: host: ohci-tmio: add IRQ check
Kai-Heng Feng <kai.heng.feng@canonical.com>
Bluetooth: Move shutdown callback before flushing tx and rx queue
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: phy: twl6030: add IRQ checks
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: phy: fsl-usb: add IRQ check
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: gadget: udc: at91: add IRQ check
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
drm/msm/dsi: Fix some reference counted resource leaks
Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
Bluetooth: fix repeated calls to sco_sock_kill
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7
Colin Ian King <colin.king@canonical.com>
Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow
Stephan Gerhold <stephan@gerhold.net>
soc: qcom: smsm: Fix missed interrupts if state changes while masked
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PCI: PM: Enable PME if it can be signaled from D3cold
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: highlander: add IRQ check
Pavel Skripkin <paskripkin@gmail.com>
net: cipso: fix warnings in netlbl_cipsov4_add_std
Martin KaFai Lau <kafai@fb.com>
tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos
Dan Carpenter <dan.carpenter@oracle.com>
Bluetooth: sco: prevent information leak in sco_conn_defer_accept()
Pavel Skripkin <paskripkin@gmail.com>
media: go7007: remove redundant initialization
Dongliang Mu <mudongliangabcd@gmail.com>
media: dvb-usb: fix uninit-value in vp702x_read_mac_addr
Dongliang Mu <mudongliangabcd@gmail.com>
media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init
Stefan Berger <stefanb@linux.ibm.com>
certs: Trigger creation of RSA module signing key if it's not an RSA key
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - use proper type for vf_mask
Tony Lindgren <tony@atomide.com>
spi: spi-pic32: Fix issue with uninitialized dma_slave_config
Pavel Skripkin <paskripkin@gmail.com>
m68k: emu: Fix invalid free in nfeth_cleanup()
Stian Skjelstad <stian.skjelstad@gmail.com>
udf_get_extendedattr() had no boundary checks.
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - do not export adf_iov_putmsg()
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - fix naming for init/shutdown VF to PF notifications
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - fix reuse of completion variable
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - handle both source of interrupt in VF ISR
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - do not ignore errors from enable_vf2pf_comms()
Damien Le Moal <damien.lemoal@wdc.com>
libata: fix ata_host_start()
Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
power: supply: max17042_battery: fix typo in MAx17042_TOFF
Jan Kara <jack@suse.cz>
udf: Check LVID earlier
Tony Lindgren <tony@atomide.com>
crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop()
Hans de Goede <hdegoede@redhat.com>
power: supply: axp288_fuel_gauge: Report register-address on readb / writeb errors
Sean Anderson <sean.anderson@seco.com>
crypto: mxs-dcp - Check for DMA mapping errors
Jeongtae Park <jeongtae.park@gmail.com>
regmap: fix the offset of register error log
Marek Behún <kabel@kernel.org>
PCI: Call Max Payload Size-related fixup quirks early
Paul Gortmaker <paul.gortmaker@windriver.com>
x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions
Qu Wenruo <wqu@suse.com>
Revert "btrfs: compression: don't try to compress if we don't have enough pages"
Muchun Song <songmuchun@bytedance.com>
mm/page_alloc: speed up the iteration of max_order
Esben Haabendal <esben@geanix.com>
net: ll_temac: Remove left-over debug message
Fangrui Song <maskray@google.com>
powerpc/boot: Delete unneeded .globl _zimage_start
Michael Ellerman <mpe@ellerman.id.au>
powerpc/module64: Fix comment in R_PPC64_ENTRY handling
Christophe Leroy <christophe.leroy@c-s.fr>
crypto: talitos - reduce max key size for SEC1
Andrew Morton <akpm@linux-foundation.org>
mm/kmemleak.c: make cond_resched() rate-limiting more efficient
Vasily Gorbik <gor@linux.vnet.ibm.com>
s390/disassembler: correct disassembly lines alignment
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing table (v2)
Jan Kara <jack@suse.cz>
gfs2: Don't clear SGID when inheriting ACLs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
nvme-pci: Fix an error handling path in 'nvme_probe()'
Philipp Zabel <p.zabel@pengutronix.de>
tc358743: fix register i2c_rd/wr function fix
Grygorii Strashko <grygorii.strashko@ti.com>
PM / wakeirq: Enable dedicated wakeirq for suspend
Paul Blakey <paulb@mellanox.com>
net/sched: cls_flower: Use mask for addr_type
Tom Rix <trix@redhat.com>
USB: serial: mos7720: improve OOM-handling in read_mos_reg()
Javier Martinez Canillas <javier@osg.samsung.com>
usb: phy: isp1301: Fix build warning when CONFIG_OF is disabled
Liu Jian <liujian56@huawei.com>
igmp: Add ip_mc_list lock in ip_check_mc_rcu
Pavel Skripkin <paskripkin@gmail.com>
media: stkwebcam: fix memory leak in stk_camera_probe
Jouni Malinen <jouni@codeaurora.org>
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Jouni Malinen <jouni@codeaurora.org>
ath: Modify ath_key_delete() to not need full key entry
Jouni Malinen <jouni@codeaurora.org>
ath: Export ath_hw_keysetmac()
Jouni Malinen <jouni@codeaurora.org>
ath9k: Clear key cache explicitly on disabling hardware
Jouni Malinen <jouni@codeaurora.org>
ath: Use safer key clearing with key cache entries
Zubin Mithra <zsm@chromium.org>
ALSA: pcm: fix divide error in snd_pcm_lib_ioctl
Ben Dooks <ben-linux@fluff.org>
ARM: 8918/2: only build return_address() if needed
Christoph Hellwig <hch@lst.de>
cryptoloop: add a deprecation warning
Kim Phillips <kim.phillips@amd.com>
perf/x86/amd/ibs: Work around erratum #1197
Shai Malin <smalin@marvell.com>
qede: Fix memset corruption
Shai Malin <smalin@marvell.com>
qed: Fix the VF msix vectors flow
Randy Dunlap <rdunlap@infradead.org>
xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
mtd: nand: atmel_nand: remove build warning in atmel_nand_remove()
Theodore Ts'o <tytso@mit.edu>
ext4: fix race writing to an inline_data file while its xattrs are changing
-------------
Diffstat:
.../devicetree/bindings/mtd/gpmc-nand.txt | 2 +-
Makefile | 4 +-
arch/arc/mm/cache.c | 2 +-
arch/arm/boot/compressed/Makefile | 2 +
arch/arm/boot/dts/tegra20-tamonten.dtsi | 14 ++--
arch/arm/kernel/Makefile | 6 +-
arch/arm/kernel/return_address.c | 4 -
arch/arm64/boot/dts/exynos/exynos7.dtsi | 2 +-
arch/m68k/emu/nfeth.c | 4 +-
arch/mips/mti-malta/malta-dtshim.c | 2 +-
arch/openrisc/kernel/entry.S | 2 +
arch/parisc/kernel/signal.c | 6 ++
arch/powerpc/boot/crt0.S | 3 -
arch/powerpc/kernel/module_64.c | 2 +-
arch/powerpc/perf/hv-gpci.c | 2 +-
arch/s390/kernel/dis.c | 2 +-
arch/s390/kernel/jump_label.c | 2 +-
arch/x86/events/amd/ibs.c | 8 ++
arch/x86/kernel/reboot.c | 3 +-
arch/x86/kvm/x86.c | 4 +
arch/x86/mm/init_64.c | 6 +-
arch/x86/xen/enlighten.c | 7 ++
arch/x86/xen/p2m.c | 4 +-
arch/xtensa/Kconfig | 2 +-
arch/xtensa/platforms/iss/console.c | 17 +++-
certs/Makefile | 8 ++
drivers/ata/libata-core.c | 6 +-
drivers/ata/sata_dwc_460ex.c | 12 +--
drivers/base/power/wakeirq.c | 12 ++-
drivers/base/regmap/regmap.c | 2 +-
drivers/bcma/main.c | 6 +-
drivers/block/Kconfig | 4 +-
drivers/block/cryptoloop.c | 2 +
drivers/clk/mvebu/kirkwood.c | 1 +
drivers/crypto/mxs-dcp.c | 81 +++++++++---------
drivers/crypto/omap-sham.c | 2 +-
.../crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c | 4 +-
drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c | 4 +-
drivers/crypto/qat/qat_common/adf_common_drv.h | 8 +-
drivers/crypto/qat/qat_common/adf_init.c | 5 +-
drivers/crypto/qat/qat_common/adf_isr.c | 7 +-
drivers/crypto/qat/qat_common/adf_pf2vf_msg.c | 3 +-
drivers/crypto/qat/qat_common/adf_vf2pf_msg.c | 12 +--
drivers/crypto/qat/qat_common/adf_vf_isr.c | 7 +-
.../qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c | 4 +-
drivers/crypto/talitos.c | 4 +
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 2 +-
drivers/gpu/drm/msm/dsi/dsi.c | 6 +-
drivers/i2c/busses/i2c-highlander.c | 2 +-
drivers/i2c/busses/i2c-iop3xx.c | 6 +-
drivers/i2c/busses/i2c-mt65xx.c | 2 +-
drivers/i2c/busses/i2c-s3c2410.c | 2 +-
drivers/iio/dac/ad5624r_spi.c | 18 +++-
drivers/media/i2c/tc358743.c | 2 +-
drivers/media/rc/rc-loopback.c | 2 +-
drivers/media/usb/dvb-usb/nova-t-usb2.c | 6 +-
drivers/media/usb/dvb-usb/vp702x.c | 12 ++-
drivers/media/usb/go7007/go7007-driver.c | 26 ------
drivers/media/usb/stkwebcam/stk-webcam.c | 6 +-
drivers/media/usb/uvc/uvc_v4l2.c | 34 +++++---
drivers/mfd/ab8500-core.c | 2 +-
drivers/mfd/stmpe.c | 4 +-
drivers/mfd/tc3589x.c | 2 +-
drivers/mfd/wm8994-irq.c | 2 +-
drivers/misc/vmw_vmci/vmci_queue_pair.c | 6 +-
drivers/mmc/host/dw_mmc.c | 1 +
drivers/mmc/host/moxart-mmc.c | 1 +
drivers/mmc/host/rtsx_pci_sdmmc.c | 36 +++++---
drivers/mtd/nand/atmel_nand.c | 1 -
drivers/mtd/nand/cafe_nand.c | 4 +-
drivers/net/dsa/b53/b53_common.c | 3 +-
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 2 +-
drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 1 +
drivers/net/ethernet/ibm/ibmvnic.c | 8 ++
drivers/net/ethernet/qlogic/qed/qed_main.c | 7 +-
drivers/net/ethernet/qlogic/qede/qede_main.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 1 -
drivers/net/ethernet/rdc/r6040.c | 9 +-
drivers/net/ethernet/renesas/sh_eth.c | 1 +
.../net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 18 ++--
drivers/net/ethernet/wiznet/w5100.c | 2 +
drivers/net/ethernet/xilinx/ll_temac_main.c | 4 +-
drivers/net/phy/dp83640_reg.h | 2 +-
drivers/net/usb/cdc_mbim.c | 5 ++
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath6kl/wmi.c | 4 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 3 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.c | 12 +--
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 +++++++++++++++++++++-
drivers/net/wireless/ath/key.c | 41 ++++++----
drivers/nvme/host/pci.c | 7 +-
drivers/parport/ieee1284_ops.c | 2 +-
drivers/pci/msi.c | 3 +
drivers/pci/pci.c | 15 ++--
drivers/pci/quirks.c | 13 +--
drivers/pci/syscall.c | 4 +-
drivers/pinctrl/pinctrl-single.c | 1 +
drivers/platform/chrome/cros_ec_proto.c | 9 ++
drivers/power/supply/axp288_fuel_gauge.c | 4 +-
drivers/power/supply/max17042_battery.c | 8 +-
drivers/rtc/rtc-tps65910.c | 2 +-
drivers/scsi/BusLogic.c | 4 +-
drivers/soc/qcom/smsm.c | 11 ++-
drivers/spi/spi-pic32.c | 1 +
drivers/staging/board/board.c | 7 +-
drivers/staging/ks7010/ks7010_sdio.c | 2 +-
drivers/tty/hvc/hvsi.c | 19 ++++-
drivers/tty/serial/8250/8250_pci.c | 2 +-
drivers/tty/serial/8250/8250_port.c | 3 +-
drivers/tty/serial/jsm/jsm_neo.c | 2 +
drivers/tty/serial/jsm/jsm_tty.c | 3 +
drivers/tty/tty_io.c | 4 +-
drivers/usb/gadget/composite.c | 8 +-
drivers/usb/gadget/function/u_ether.c | 5 +-
drivers/usb/gadget/udc/at91_udc.c | 4 +-
drivers/usb/gadget/udc/mv_u3d_core.c | 19 +++--
drivers/usb/host/ehci-orion.c | 8 +-
drivers/usb/host/fotg210-hcd.c | 41 +++++-----
drivers/usb/host/fotg210.h | 5 --
drivers/usb/host/ohci-tmio.c | 3 +
drivers/usb/host/xhci.c | 24 +++---
drivers/usb/phy/phy-fsl-usb.c | 2 +
drivers/usb/phy/phy-isp1301.c | 2 +-
drivers/usb/phy/phy-tahvo.c | 4 +-
drivers/usb/phy/phy-twl6030-usb.c | 5 ++
drivers/usb/serial/mos7720.c | 4 +-
drivers/usb/usbip/vhci_hcd.c | 24 ++++++
drivers/vfio/Kconfig | 2 +-
drivers/video/fbdev/asiliantfb.c | 3 +
drivers/video/fbdev/core/fbmem.c | 7 ++
drivers/video/fbdev/kyro/fbdev.c | 8 ++
drivers/video/fbdev/riva/fbdev.c | 3 +
fs/btrfs/inode.c | 2 +-
fs/cifs/cifs_unicode.c | 9 +-
fs/cifs/sess.c | 2 +-
fs/ext4/inline.c | 6 ++
fs/gfs2/acl.c | 27 +++---
fs/gfs2/lock_dlm.c | 5 ++
fs/udf/misc.c | 13 ++-
fs/udf/super.c | 25 ++++--
include/crypto/public_key.h | 4 +-
include/linux/hugetlb.h | 9 ++
include/linux/pci.h | 5 +-
include/linux/power/max17042_battery.h | 2 +-
include/linux/skbuff.h | 2 +-
include/uapi/linux/serial_reg.h | 1 +
kernel/events/core.c | 2 +-
kernel/fork.c | 1 +
kernel/pid_namespace.c | 2 +-
lib/test_bpf.c | 13 ++-
mm/kmemleak.c | 2 +-
mm/page_alloc.c | 8 +-
net/bluetooth/cmtp/cmtp.h | 2 +-
net/bluetooth/hci_core.c | 14 ++++
net/bluetooth/hci_event.c | 15 ++++
net/bluetooth/sco.c | 50 +++++-------
net/caif/chnl_net.c | 19 +----
net/core/flow_dissector.c | 12 ++-
net/dccp/minisocks.c | 2 +
net/ipv4/icmp.c | 23 +++++-
net/ipv4/igmp.c | 2 +
net/ipv4/ip_output.c | 5 +-
net/ipv4/route.c | 46 +++++++----
net/ipv4/tcp_input.c | 2 +-
net/ipv4/tcp_ipv4.c | 5 +-
net/l2tp/l2tp_core.c | 4 +-
net/netlabel/netlabel_cipso_v4.c | 12 +--
net/netlink/af_netlink.c | 4 +-
net/sched/cls_flower.c | 4 +
net/sunrpc/auth_gss/svcauth_gss.c | 2 +-
net/tipc/socket.c | 2 +-
net/unix/af_unix.c | 2 +-
security/integrity/ima/ima_mok.c | 2 +-
security/smack/smack_access.c | 17 ++--
sound/core/pcm_lib.c | 2 +-
sound/soc/intel/boards/bytcr_rt5640.c | 9 +-
179 files changed, 935 insertions(+), 488 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 4.9 014/175] ath9k: Postpone key cache entry deletion for TXQ frames reference it
2021-09-20 16:40 1% [PATCH 4.9 000/175] 4.9.283-rc1 review Greg Kroah-Hartman
@ 2021-09-20 16:41 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-09-20 16:41 UTC (permalink / raw)
To: linux-kernel; +Cc: Greg Kroah-Hartman, stable, Jouni Malinen, Kalle Valo
From: Jouni Malinen <jouni@codeaurora.org>
commit ca2848022c12789685d3fab3227df02b863f9696 upstream.
Do not delete a key cache entry that is still being referenced by
pending frames in TXQs. This avoids reuse of the key cache entry while a
frame might still be transmitted using it.
To avoid having to do any additional operations during the main TX path
operations, track pending key cache entries in a new bitmap and check
whether any pending entries can be deleted before every new key
add/remove operation. Also clear any remaining entries when stopping the
interface.
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20201214172118.18100-6-jouni@codeaurora.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/ath/ath9k/hw.h | 1
drivers/net/wireless/ath/ath9k/main.c | 87 +++++++++++++++++++++++++++++++++-
2 files changed, 87 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -815,6 +815,7 @@ struct ath_hw {
struct ath9k_pacal_info pacal_info;
struct ar5416Stats stats;
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+ DECLARE_BITMAP(pending_del_keymap, ATH_KEYMAX);
enum ath9k_int imask;
u32 imrs2_reg;
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -821,12 +821,80 @@ exit:
ieee80211_free_txskb(hw, skb);
}
+static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
+{
+ struct ath_buf *bf;
+ struct ieee80211_tx_info *txinfo;
+ struct ath_frame_info *fi;
+
+ list_for_each_entry(bf, txq_list, list) {
+ if (bf->bf_state.stale || !bf->bf_mpdu)
+ continue;
+
+ txinfo = IEEE80211_SKB_CB(bf->bf_mpdu);
+ fi = (struct ath_frame_info *)&txinfo->rate_driver_data[0];
+ if (fi->keyix == keyix)
+ return true;
+ }
+
+ return false;
+}
+
+static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ int i;
+ struct ath_txq *txq;
+ bool key_in_use = false;
+
+ for (i = 0; !key_in_use && i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+ txq = &sc->tx.txq[i];
+ if (!txq->axq_depth)
+ continue;
+ if (!ath9k_hw_numtxpending(ah, txq->axq_qnum))
+ continue;
+
+ ath_txq_lock(sc, txq);
+ key_in_use = ath9k_txq_list_has_key(&txq->axq_q, keyix);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ int idx = txq->txq_tailidx;
+
+ while (!key_in_use &&
+ !list_empty(&txq->txq_fifo[idx])) {
+ key_in_use = ath9k_txq_list_has_key(
+ &txq->txq_fifo[idx], keyix);
+ INCR(idx, ATH_TXFIFO_DEPTH);
+ }
+ }
+ ath_txq_unlock(sc, txq);
+ }
+
+ return key_in_use;
+}
+
+static void ath9k_pending_key_del(struct ath_softc *sc, u8 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!test_bit(keyix, ah->pending_del_keymap) ||
+ ath9k_txq_has_key(sc, keyix))
+ return;
+
+ /* No more TXQ frames point to this key cache entry, so delete it. */
+ clear_bit(keyix, ah->pending_del_keymap);
+ ath_key_delete(common, keyix);
+}
+
static void ath9k_stop(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
bool prev_idle;
+ int i;
ath9k_deinit_channel_context(sc);
@@ -894,6 +962,9 @@ static void ath9k_stop(struct ieee80211_
spin_unlock_bh(&sc->sc_pcu_lock);
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
/* Clear key cache entries explicitly to get rid of any potentially
* remaining keys.
*/
@@ -1710,6 +1781,12 @@ static int ath9k_set_key(struct ieee8021
if (sta)
an = (struct ath_node *)sta->drv_priv;
+ /* Delete pending key cache entries if no more frames are pointing to
+ * them in TXQs.
+ */
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
switch (cmd) {
case SET_KEY:
if (sta)
@@ -1739,7 +1816,15 @@ static int ath9k_set_key(struct ieee8021
}
break;
case DISABLE_KEY:
- ath_key_delete(common, key->hw_key_idx);
+ if (ath9k_txq_has_key(sc, key->hw_key_idx)) {
+ /* Delay key cache entry deletion until there are no
+ * remaining TXQ frames pointing to this entry.
+ */
+ set_bit(key->hw_key_idx, sc->sc_ah->pending_del_keymap);
+ ath_hw_keysetmac(common, key->hw_key_idx, NULL);
+ } else {
+ ath_key_delete(common, key->hw_key_idx);
+ }
if (an) {
for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
if (an->key_idx[i] != key->hw_key_idx)
^ permalink raw reply [relevance 5%]
* [PATCH 4.4 000/133] 4.4.284-rc1 review
@ 2021-09-20 16:41 2% Greg Kroah-Hartman
2021-09-20 16:41 5% ` [PATCH 4.4 012/133] ath9k: Postpone key cache entry deletion for TXQ frames reference it Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2021-09-20 16:41 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 4.4.284 release.
There are 133 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 22 Sep 2021 16:38:49 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.284-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.4.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 4.4.284-rc1
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
net: renesas: sh_eth: Fix freeing wrong tx descriptor
Dinghao Liu <dinghao.liu@zju.edu.cn>
qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
Randy Dunlap <rdunlap@infradead.org>
ARC: export clear_user_page() for modules
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mtd: rawnand: cafe: Fix a resource leak in the error handling path of 'cafe_nand_probe()'
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
Yang Li <yang.lee@linux.alibaba.com>
ethtool: Fix an error code in cxgb2.c
Miquel Raynal <miquel.raynal@bootlin.com>
dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation
Mike Rapoport <rppt@linux.ibm.com>
x86/mm: Fix kern_addr_valid() to cope with existing but not present entries
Eric Dumazet <edumazet@google.com>
net/af_unix: fix a data-race in unix_dgram_poll
Hoang Le <hoang.h.le@dektech.com.au>
tipc: increase timeout in tipc_sk_enqueue()
Florian Fainelli <f.fainelli@gmail.com>
r6040: Restore MDIO clock frequency after MAC reset
Xiyu Yang <xiyuyang19@fudan.edu.cn>
net/l2tp: Fix reference count leak in l2tp_udp_recv_core
Lin, Zhenpeng <zplin@psu.edu>
dccp: don't duplicate ccid when cloning dccp sock
Randy Dunlap <rdunlap@infradead.org>
ptp: dp83640: don't define PAGE0
Eric Dumazet <edumazet@google.com>
net-caif: avoid user-triggerable WARN_ON(1)
Adrian Bunk <bunk@kernel.org>
bnx2x: Fix enabling network interfaces without VFs
Patryk Duda <pdk@semihalf.com>
platform/chrome: cros_ec_proto: Send command again when timeout occurs
Mikulas Patocka <mpatocka@redhat.com>
parisc: fix crash with signals and alloca
王贇 <yun.wang@linux.alibaba.com>
net: fix NULL pointer reference in cipso_v4_doi_free
Zekun Shen <bruceshenzk@gmail.com>
ath9k: fix OOB read ar9300_eeprom_restore_internal
Colin Ian King <colin.king@canonical.com>
parport: remove non-zero check on count
Mathias Nyman <mathias.nyman@linux.intel.com>
Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set"
Ding Hui <dinghui@sangfor.com.cn>
cifs: fix wrong release in sess_alloc_buffer() failed path
Thomas Hebb <tommyhebb@gmail.com>
mmc: rtsx_pci: Fix long reads when clock is prescaled
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't call dlm after protocol is unmounted
J. Bruce Fields <bfields@redhat.com>
rpc: fix gss_svc_init cleanup on failure
Andreas Obergschwandtner <andreas.obergschwandtner@gmail.com>
ARM: tegra: tamonten: Fix UART pad setting
Tuo Li <islituo@gmail.com>
gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable access in amdgpu_i2c_router_select_ddc_port()
Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
Bluetooth: skip invalid hci_sync_conn_complete_evt
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
serial: 8250_pci: make setup_port() parameters explicitly unsigned
Jiri Slaby <jslaby@suse.cz>
hvsi: don't panic on tty_register_driver failure
Jiri Slaby <jslaby@suse.cz>
xtensa: ISS: don't panic in rs_init
Maciej W. Rozycki <macro@orcam.me.uk>
serial: 8250: Define RX trigger levels for OxSemi 950 devices
Heiko Carstens <hca@linux.ibm.com>
s390/jump_label: print real address in a case of a jump label bug
Gustavo A. R. Silva <gustavoars@kernel.org>
ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs()
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: riva: Error out if 'pixclock' equals zero
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: kyro: Error out if 'pixclock' equals zero
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
Johan Almbladh <johan.almbladh@anyfinetworks.com>
bpf/tests: Do not PASS tests without actually testing the result
Johan Almbladh <johan.almbladh@anyfinetworks.com>
bpf/tests: Fix copy-and-paste error in double word test
Zheyu Ma <zheyuma97@gmail.com>
tty: serial: jsm: hold port lock when reporting modem line changes
Maciej Żenczykowski <maze@google.com>
usb: gadget: u_ether: fix a potential null pointer dereference
Kelly Devilliv <kelly.devilliv@gmail.com>
usb: host: fotg210: fix the actual_length of an iso packet
Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
Smack: Fix wrong semantics in smk_access_entry()
Yajun Deng <yajun.deng@linux.dev>
netlink: Deal with ESRCH error in nlmsg_notify()
Zheyu Ma <zheyuma97@gmail.com>
video: fbdev: kyro: fix a DoS bug by restricting user input
Jonathan Cameron <Jonathan.Cameron@huawei.com>
iio: dac: ad5624r: Fix incorrect handling of an optional regulator.
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PCI: Use pci_update_current_state() in pci_enable_device_flags()
Sean Anderson <sean.anderson@seco.com>
crypto: mxs-dcp - Use sg_mapping_iter to copy data
Zhen Lei <thunder.leizhen@huawei.com>
pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry()
Randy Dunlap <rdunlap@infradead.org>
openrisc: don't printk() unconditionally
Krzysztof Wilczyński <kw@linux.com>
PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure
Marek Behún <kabel@kernel.org>
PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported
David Heidelberg <david@ixit.cz>
ARM: 9105/1: atags_to_fdt: don't warn about stack size
Hans de Goede <hdegoede@redhat.com>
libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs
Sean Young <sean@mess.org>
media: rc-loopback: return number of emitters rather than error
Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
media: uvc: don't do DMA on stack
Wang Hai <wanghai38@huawei.com>
VMCI: fix NULL pointer dereference when unmapping queue pair
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
power: supply: max17042: handle fails of reading status register
Juergen Gross <jgross@suse.com>
xen: fix setting of max_pfn in shared_info
Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
PCI/MSI: Skip masking MSI-X on Xen PV
Dmitry Osipenko <digetx@gmail.com>
rtc: tps65910: Correct driver module alias
Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
fbmem: don't allow too huge resolutions
Linus Walleij <linus.walleij@linaro.org>
clk: kirkwood: Fix a clocking boot regression
Zelin Deng <zelin.deng@linux.alibaba.com>
KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is adjusted
Nguyen Dinh Phi <phind.uet@gmail.com>
tty: Fix data race between tiocsti() and flush_to_ldisc()
Eric Dumazet <edumazet@google.com>
ipv4: make exception cache less predictible
Zenghui Yu <yuzenghui@huawei.com>
bcma: Fix memory leak for internally-handled cores
Dan Carpenter <dan.carpenter@oracle.com>
ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point()
Evgeny Novikov <novikov@ispras.ru>
usb: ehci-orion: Handle errors of clk_prepare_enable() in probe
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: mt65xx: fix IRQ check
Len Baker <len.baker@gmx.com>
CIFS: Fix a potencially linear read overflow
Tony Lindgren <tony@atomide.com>
mmc: moxart: Fix issue with uninitialized dma_slave_config
Tony Lindgren <tony@atomide.com>
mmc: dw_mmc: Fix issue with uninitialized dma_slave_config
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: s3c2410: fix IRQ check
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: iop3xx: fix deferred probing
Pavel Skripkin <paskripkin@gmail.com>
Bluetooth: add timeout sanity check to hci_inquiry
Nadezda Lutovinova <lutovinova@ispras.ru>
usb: gadget: mv_u3d: request_irq() after initializing UDC
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: phy: tahvo: add IRQ check
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: host: ohci-tmio: add IRQ check
Kai-Heng Feng <kai.heng.feng@canonical.com>
Bluetooth: Move shutdown callback before flushing tx and rx queue
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: phy: twl6030: add IRQ checks
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: phy: fsl-usb: add IRQ check
Sergey Shtylyov <s.shtylyov@omp.ru>
usb: gadget: udc: at91: add IRQ check
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
drm/msm/dsi: Fix some reference counted resource leaks
Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
Bluetooth: fix repeated calls to sco_sock_kill
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7
Colin Ian King <colin.king@canonical.com>
Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PCI: PM: Enable PME if it can be signaled from D3cold
Sergey Shtylyov <s.shtylyov@omp.ru>
i2c: highlander: add IRQ check
Pavel Skripkin <paskripkin@gmail.com>
net: cipso: fix warnings in netlbl_cipsov4_add_std
Martin KaFai Lau <kafai@fb.com>
tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos
Dan Carpenter <dan.carpenter@oracle.com>
Bluetooth: sco: prevent information leak in sco_conn_defer_accept()
Pavel Skripkin <paskripkin@gmail.com>
media: go7007: remove redundant initialization
Dongliang Mu <mudongliangabcd@gmail.com>
media: dvb-usb: fix uninit-value in vp702x_read_mac_addr
Dongliang Mu <mudongliangabcd@gmail.com>
media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init
Stefan Berger <stefanb@linux.ibm.com>
certs: Trigger creation of RSA module signing key if it's not an RSA key
Pavel Skripkin <paskripkin@gmail.com>
m68k: emu: Fix invalid free in nfeth_cleanup()
Stian Skjelstad <stian.skjelstad@gmail.com>
udf_get_extendedattr() had no boundary checks.
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - fix reuse of completion variable
Giovanni Cabiddu <giovanni.cabiddu@intel.com>
crypto: qat - do not ignore errors from enable_vf2pf_comms()
Damien Le Moal <damien.lemoal@wdc.com>
libata: fix ata_host_start()
Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
power: supply: max17042_battery: fix typo in MAx17042_TOFF
Tony Lindgren <tony@atomide.com>
crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop()
Sean Anderson <sean.anderson@seco.com>
crypto: mxs-dcp - Check for DMA mapping errors
Marek Behún <kabel@kernel.org>
PCI: Call Max Payload Size-related fixup quirks early
Paul Gortmaker <paul.gortmaker@windriver.com>
x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions
Qu Wenruo <wqu@suse.com>
Revert "btrfs: compression: don't try to compress if we don't have enough pages"
Muchun Song <songmuchun@bytedance.com>
mm/page_alloc: speed up the iteration of max_order
Esben Haabendal <esben@geanix.com>
net: ll_temac: Remove left-over debug message
Fangrui Song <maskray@google.com>
powerpc/boot: Delete unneeded .globl _zimage_start
Michael Ellerman <mpe@ellerman.id.au>
powerpc/module64: Fix comment in R_PPC64_ENTRY handling
Andrew Morton <akpm@linux-foundation.org>
mm/kmemleak.c: make cond_resched() rate-limiting more efficient
Vasily Gorbik <gor@linux.vnet.ibm.com>
s390/disassembler: correct disassembly lines alignment
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing table (v2)
Philipp Zabel <p.zabel@pengutronix.de>
tc358743: fix register i2c_rd/wr function fix
Grygorii Strashko <grygorii.strashko@ti.com>
PM / wakeirq: Enable dedicated wakeirq for suspend
Tom Rix <trix@redhat.com>
USB: serial: mos7720: improve OOM-handling in read_mos_reg()
Javier Martinez Canillas <javier@osg.samsung.com>
usb: phy: isp1301: Fix build warning when CONFIG_OF is disabled
Liu Jian <liujian56@huawei.com>
igmp: Add ip_mc_list lock in ip_check_mc_rcu
Pavel Skripkin <paskripkin@gmail.com>
media: stkwebcam: fix memory leak in stk_camera_probe
Jouni Malinen <jouni@codeaurora.org>
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Jouni Malinen <jouni@codeaurora.org>
ath: Modify ath_key_delete() to not need full key entry
Jouni Malinen <jouni@codeaurora.org>
ath: Export ath_hw_keysetmac()
Jouni Malinen <jouni@codeaurora.org>
ath9k: Clear key cache explicitly on disabling hardware
Jouni Malinen <jouni@codeaurora.org>
ath: Use safer key clearing with key cache entries
Zubin Mithra <zsm@chromium.org>
ALSA: pcm: fix divide error in snd_pcm_lib_ioctl
Ben Dooks <ben-linux@fluff.org>
ARM: 8918/2: only build return_address() if needed
Christoph Hellwig <hch@lst.de>
cryptoloop: add a deprecation warning
Shai Malin <smalin@marvell.com>
qede: Fix memset corruption
Vineet Gupta <vgupta@synopsys.com>
ARC: fix allnoconfig build warning
Randy Dunlap <rdunlap@infradead.org>
xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG
Theodore Ts'o <tytso@mit.edu>
ext4: fix race writing to an inline_data file while its xattrs are changing
-------------
Diffstat:
.../devicetree/bindings/mtd/gpmc-nand.txt | 2 +-
Makefile | 4 +-
arch/arc/Kconfig | 2 +-
arch/arc/mm/cache.c | 2 +-
arch/arm/boot/compressed/Makefile | 2 +
arch/arm/boot/dts/tegra20-tamonten.dtsi | 14 ++--
arch/arm/kernel/Makefile | 6 +-
arch/arm/kernel/return_address.c | 4 -
arch/arm64/boot/dts/exynos/exynos7.dtsi | 2 +-
arch/m68k/emu/nfeth.c | 4 +-
arch/openrisc/kernel/entry.S | 2 +
arch/parisc/kernel/signal.c | 6 ++
arch/powerpc/boot/crt0.S | 3 -
arch/powerpc/kernel/module_64.c | 2 +-
arch/s390/kernel/dis.c | 2 +-
arch/s390/kernel/jump_label.c | 2 +-
arch/x86/kernel/reboot.c | 3 +-
arch/x86/kvm/x86.c | 4 +
arch/x86/mm/init_64.c | 6 +-
arch/x86/xen/p2m.c | 4 +-
arch/xtensa/Kconfig | 2 +-
arch/xtensa/platforms/iss/console.c | 17 +++-
certs/Makefile | 8 ++
drivers/ata/libata-core.c | 6 +-
drivers/base/power/wakeirq.c | 12 ++-
drivers/bcma/main.c | 6 +-
drivers/block/Kconfig | 4 +-
drivers/block/cryptoloop.c | 2 +
drivers/clk/mvebu/kirkwood.c | 1 +
drivers/crypto/mxs-dcp.c | 81 +++++++++---------
drivers/crypto/omap-sham.c | 2 +-
drivers/crypto/qat/qat_common/adf_init.c | 5 +-
drivers/crypto/qat/qat_common/adf_pf2vf_msg.c | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 2 +-
drivers/gpu/drm/msm/dsi/dsi.c | 6 +-
drivers/i2c/busses/i2c-highlander.c | 2 +-
drivers/i2c/busses/i2c-iop3xx.c | 6 +-
drivers/i2c/busses/i2c-mt65xx.c | 2 +-
drivers/i2c/busses/i2c-s3c2410.c | 2 +-
drivers/iio/dac/ad5624r_spi.c | 18 +++-
drivers/media/i2c/tc358743.c | 2 +-
drivers/media/rc/rc-loopback.c | 2 +-
drivers/media/usb/dvb-usb/nova-t-usb2.c | 6 +-
drivers/media/usb/dvb-usb/vp702x.c | 12 ++-
drivers/media/usb/go7007/go7007-driver.c | 26 ------
drivers/media/usb/stkwebcam/stk-webcam.c | 6 +-
drivers/media/usb/uvc/uvc_v4l2.c | 34 +++++---
drivers/misc/vmw_vmci/vmci_queue_pair.c | 6 +-
drivers/mmc/host/dw_mmc.c | 1 +
drivers/mmc/host/moxart-mmc.c | 1 +
drivers/mmc/host/rtsx_pci_sdmmc.c | 36 +++++---
drivers/mtd/nand/cafe_nand.c | 4 +-
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 2 +-
drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 1 +
drivers/net/ethernet/qlogic/qede/qede_main.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 1 -
drivers/net/ethernet/rdc/r6040.c | 9 +-
drivers/net/ethernet/renesas/sh_eth.c | 1 +
drivers/net/ethernet/xilinx/ll_temac_main.c | 4 +-
drivers/net/phy/dp83640_reg.h | 2 +-
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath6kl/wmi.c | 4 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 3 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 +++++++++++++++++++++-
drivers/net/wireless/ath/key.c | 41 ++++++----
drivers/parport/ieee1284_ops.c | 2 +-
drivers/pci/msi.c | 3 +
drivers/pci/pci.c | 15 ++--
drivers/pci/quirks.c | 13 +--
drivers/pci/syscall.c | 4 +-
drivers/pinctrl/pinctrl-single.c | 1 +
drivers/platform/chrome/cros_ec_proto.c | 9 ++
drivers/power/max17042_battery.c | 8 +-
drivers/rtc/rtc-tps65910.c | 2 +-
drivers/tty/hvc/hvsi.c | 19 ++++-
drivers/tty/serial/8250/8250_pci.c | 2 +-
drivers/tty/serial/8250/8250_port.c | 3 +-
drivers/tty/serial/jsm/jsm_neo.c | 2 +
drivers/tty/serial/jsm/jsm_tty.c | 3 +
drivers/tty/tty_io.c | 4 +-
drivers/usb/gadget/function/u_ether.c | 5 +-
drivers/usb/gadget/udc/at91_udc.c | 4 +-
drivers/usb/gadget/udc/mv_u3d_core.c | 19 +++--
drivers/usb/host/ehci-orion.c | 8 +-
drivers/usb/host/fotg210-hcd.c | 5 +-
drivers/usb/host/fotg210.h | 5 --
drivers/usb/host/ohci-tmio.c | 3 +
drivers/usb/host/xhci.c | 24 +++---
drivers/usb/phy/phy-fsl-usb.c | 2 +
drivers/usb/phy/phy-isp1301.c | 2 +-
drivers/usb/phy/phy-tahvo.c | 4 +-
drivers/usb/phy/phy-twl6030-usb.c | 5 ++
drivers/usb/serial/mos7720.c | 4 +-
drivers/video/fbdev/asiliantfb.c | 3 +
drivers/video/fbdev/core/fbmem.c | 7 ++
drivers/video/fbdev/kyro/fbdev.c | 8 ++
drivers/video/fbdev/riva/fbdev.c | 3 +
fs/btrfs/inode.c | 2 +-
fs/cifs/cifs_unicode.c | 9 +-
fs/cifs/sess.c | 2 +-
fs/ext4/inline.c | 6 ++
fs/gfs2/lock_dlm.c | 5 ++
fs/udf/misc.c | 13 ++-
include/linux/pci.h | 5 +-
include/linux/power/max17042_battery.h | 2 +-
include/linux/skbuff.h | 2 +-
include/uapi/linux/serial_reg.h | 1 +
lib/test_bpf.c | 13 ++-
mm/kmemleak.c | 2 +-
mm/page_alloc.c | 8 +-
net/bluetooth/cmtp/cmtp.h | 2 +-
net/bluetooth/hci_core.c | 14 ++++
net/bluetooth/hci_event.c | 15 ++++
net/bluetooth/sco.c | 11 +--
net/caif/chnl_net.c | 19 +----
net/dccp/minisocks.c | 2 +
net/ipv4/icmp.c | 23 +++++-
net/ipv4/igmp.c | 2 +
net/ipv4/ip_output.c | 5 +-
net/ipv4/route.c | 46 +++++++----
net/ipv4/tcp_ipv4.c | 5 +-
net/l2tp/l2tp_core.c | 4 +-
net/netlabel/netlabel_cipso_v4.c | 12 +--
net/netlink/af_netlink.c | 4 +-
net/sunrpc/auth_gss/svcauth_gss.c | 2 +-
net/tipc/socket.c | 2 +-
net/unix/af_unix.c | 2 +-
security/smack/smack_access.c | 17 ++--
sound/core/pcm_lib.c | 2 +-
132 files changed, 692 insertions(+), 339 deletions(-)
^ permalink raw reply [relevance 2%]
* [PATCH 4.4 012/133] ath9k: Postpone key cache entry deletion for TXQ frames reference it
2021-09-20 16:41 2% [PATCH 4.4 000/133] 4.4.284-rc1 review Greg Kroah-Hartman
@ 2021-09-20 16:41 5% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-09-20 16:41 UTC (permalink / raw)
To: linux-kernel; +Cc: Greg Kroah-Hartman, stable, Jouni Malinen, Kalle Valo
From: Jouni Malinen <jouni@codeaurora.org>
commit ca2848022c12789685d3fab3227df02b863f9696 upstream.
Do not delete a key cache entry that is still being referenced by
pending frames in TXQs. This avoids reuse of the key cache entry while a
frame might still be transmitted using it.
To avoid having to do any additional operations during the main TX path
operations, track pending key cache entries in a new bitmap and check
whether any pending entries can be deleted before every new key
add/remove operation. Also clear any remaining entries when stopping the
interface.
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20201214172118.18100-6-jouni@codeaurora.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/ath/ath9k/hw.h | 1
drivers/net/wireless/ath/ath9k/main.c | 87 +++++++++++++++++++++++++++++++++-
2 files changed, 87 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -814,6 +814,7 @@ struct ath_hw {
struct ath9k_pacal_info pacal_info;
struct ar5416Stats stats;
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+ DECLARE_BITMAP(pending_del_keymap, ATH_KEYMAX);
enum ath9k_int imask;
u32 imrs2_reg;
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -819,12 +819,80 @@ exit:
ieee80211_free_txskb(hw, skb);
}
+static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
+{
+ struct ath_buf *bf;
+ struct ieee80211_tx_info *txinfo;
+ struct ath_frame_info *fi;
+
+ list_for_each_entry(bf, txq_list, list) {
+ if (bf->bf_state.stale || !bf->bf_mpdu)
+ continue;
+
+ txinfo = IEEE80211_SKB_CB(bf->bf_mpdu);
+ fi = (struct ath_frame_info *)&txinfo->rate_driver_data[0];
+ if (fi->keyix == keyix)
+ return true;
+ }
+
+ return false;
+}
+
+static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ int i;
+ struct ath_txq *txq;
+ bool key_in_use = false;
+
+ for (i = 0; !key_in_use && i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+ txq = &sc->tx.txq[i];
+ if (!txq->axq_depth)
+ continue;
+ if (!ath9k_hw_numtxpending(ah, txq->axq_qnum))
+ continue;
+
+ ath_txq_lock(sc, txq);
+ key_in_use = ath9k_txq_list_has_key(&txq->axq_q, keyix);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ int idx = txq->txq_tailidx;
+
+ while (!key_in_use &&
+ !list_empty(&txq->txq_fifo[idx])) {
+ key_in_use = ath9k_txq_list_has_key(
+ &txq->txq_fifo[idx], keyix);
+ INCR(idx, ATH_TXFIFO_DEPTH);
+ }
+ }
+ ath_txq_unlock(sc, txq);
+ }
+
+ return key_in_use;
+}
+
+static void ath9k_pending_key_del(struct ath_softc *sc, u8 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!test_bit(keyix, ah->pending_del_keymap) ||
+ ath9k_txq_has_key(sc, keyix))
+ return;
+
+ /* No more TXQ frames point to this key cache entry, so delete it. */
+ clear_bit(keyix, ah->pending_del_keymap);
+ ath_key_delete(common, keyix);
+}
+
static void ath9k_stop(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
bool prev_idle;
+ int i;
ath9k_deinit_channel_context(sc);
@@ -890,6 +958,9 @@ static void ath9k_stop(struct ieee80211_
spin_unlock_bh(&sc->sc_pcu_lock);
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
/* Clear key cache entries explicitly to get rid of any potentially
* remaining keys.
*/
@@ -1692,6 +1763,12 @@ static int ath9k_set_key(struct ieee8021
if (sta)
an = (struct ath_node *)sta->drv_priv;
+ /* Delete pending key cache entries if no more frames are pointing to
+ * them in TXQs.
+ */
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
switch (cmd) {
case SET_KEY:
if (sta)
@@ -1721,7 +1798,15 @@ static int ath9k_set_key(struct ieee8021
}
break;
case DISABLE_KEY:
- ath_key_delete(common, key->hw_key_idx);
+ if (ath9k_txq_has_key(sc, key->hw_key_idx)) {
+ /* Delay key cache entry deletion until there are no
+ * remaining TXQ frames pointing to this entry.
+ */
+ set_bit(key->hw_key_idx, sc->sc_ah->pending_del_keymap);
+ ath_hw_keysetmac(common, key->hw_key_idx, NULL);
+ } else {
+ ath_key_delete(common, key->hw_key_idx);
+ }
if (an) {
for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
if (an->key_idx[i] != key->hw_key_idx)
^ permalink raw reply [relevance 5%]
* FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 4.9-stable tree
@ 2021-09-20 8:01 4% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2021-09-20 8:01 UTC (permalink / raw)
To: qiangqing.zhang, davem; +Cc: stable
The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 276aae377206d60b9b7b7df4586cd9f2a813f5d0 Mon Sep 17 00:00:00 2001
From: Joakim Zhang <qiangqing.zhang@nxp.com>
Date: Wed, 8 Sep 2021 15:43:35 +0800
Subject: [PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during
suspend/resume
commit 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after
napi disabled"), this patch tries to fix system hang caused by eee_ctrl_timer,
unfortunately, it only can resolve it for system reboot stress test. System
hang also can be reproduced easily during system suspend/resume stess test
when mount NFS on i.MX8MP EVK board.
In stmmac driver, eee feature is combined to phylink framework. When do
system suspend, phylink_stop() would queue delayed work, it invokes
stmmac_mac_link_down(), where to deactivate eee_ctrl_timer synchronizly.
In above commit, try to fix issue by deactivating eee_ctrl_timer obviously,
but it is not enough. Looking into eee_ctrl_timer expire callback
stmmac_eee_ctrl_timer(), it could enable hareware eee mode again. What is
unexpected is that LPI interrupt (MAC_Interrupt_Enable.LPIEN bit) is always
asserted. This interrupt has chance to be issued when LPI state entry/exit
from the MAC, and at that time, clock could have been already disabled.
The result is that system hang when driver try to touch register from
interrupt handler.
The reason why above commit can fix system hang issue in stmmac_release()
is that, deactivate eee_ctrl_timer not just after napi disabled, further
after irq freed.
In conclusion, hardware would generate LPI interrupt when clock has been
disabled during suspend or resume, since hardware is in eee mode and LPI
interrupt enabled.
Interrupts from MAC, MTL and DMA level are enabled and never been disabled
when system suspend, so postpone clocks management from suspend stage to
noirq suspend stage should be more safe.
Fixes: 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after napi disabled")
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ece02b35a6ce..246f84fedbc8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7118,7 +7118,6 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan;
- int ret;
if (!ndev || !netif_running(ndev))
return 0;
@@ -7150,13 +7149,6 @@ int stmmac_suspend(struct device *dev)
} else {
stmmac_mac_set(priv, priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- clk_disable_unprepare(priv->plat->clk_ptp_ref);
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
}
mutex_unlock(&priv->lock);
@@ -7242,12 +7234,6 @@ int stmmac_resume(struct device *dev)
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
- /* enable the clk previously disabled */
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
- if (priv->plat->clk_ptp_ref)
- clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 5ca710844cc1..4885f9ad1b1e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,7 @@
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -771,9 +772,52 @@ static int __maybe_unused stmmac_runtime_resume(struct device *dev)
return stmmac_bus_clks_config(priv, true);
}
+static int stmmac_pltfr_noirq_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmmac_pltfr_noirq_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* enable the clk previously disabled */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ }
+
+ return 0;
+}
+
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
^ permalink raw reply related [relevance 4%]
* FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 4.14-stable tree
@ 2021-09-20 8:01 4% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2021-09-20 8:01 UTC (permalink / raw)
To: qiangqing.zhang, davem; +Cc: stable
The patch below does not apply to the 4.14-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 276aae377206d60b9b7b7df4586cd9f2a813f5d0 Mon Sep 17 00:00:00 2001
From: Joakim Zhang <qiangqing.zhang@nxp.com>
Date: Wed, 8 Sep 2021 15:43:35 +0800
Subject: [PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during
suspend/resume
commit 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after
napi disabled"), this patch tries to fix system hang caused by eee_ctrl_timer,
unfortunately, it only can resolve it for system reboot stress test. System
hang also can be reproduced easily during system suspend/resume stess test
when mount NFS on i.MX8MP EVK board.
In stmmac driver, eee feature is combined to phylink framework. When do
system suspend, phylink_stop() would queue delayed work, it invokes
stmmac_mac_link_down(), where to deactivate eee_ctrl_timer synchronizly.
In above commit, try to fix issue by deactivating eee_ctrl_timer obviously,
but it is not enough. Looking into eee_ctrl_timer expire callback
stmmac_eee_ctrl_timer(), it could enable hareware eee mode again. What is
unexpected is that LPI interrupt (MAC_Interrupt_Enable.LPIEN bit) is always
asserted. This interrupt has chance to be issued when LPI state entry/exit
from the MAC, and at that time, clock could have been already disabled.
The result is that system hang when driver try to touch register from
interrupt handler.
The reason why above commit can fix system hang issue in stmmac_release()
is that, deactivate eee_ctrl_timer not just after napi disabled, further
after irq freed.
In conclusion, hardware would generate LPI interrupt when clock has been
disabled during suspend or resume, since hardware is in eee mode and LPI
interrupt enabled.
Interrupts from MAC, MTL and DMA level are enabled and never been disabled
when system suspend, so postpone clocks management from suspend stage to
noirq suspend stage should be more safe.
Fixes: 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after napi disabled")
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ece02b35a6ce..246f84fedbc8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7118,7 +7118,6 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan;
- int ret;
if (!ndev || !netif_running(ndev))
return 0;
@@ -7150,13 +7149,6 @@ int stmmac_suspend(struct device *dev)
} else {
stmmac_mac_set(priv, priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- clk_disable_unprepare(priv->plat->clk_ptp_ref);
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
}
mutex_unlock(&priv->lock);
@@ -7242,12 +7234,6 @@ int stmmac_resume(struct device *dev)
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
- /* enable the clk previously disabled */
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
- if (priv->plat->clk_ptp_ref)
- clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 5ca710844cc1..4885f9ad1b1e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,7 @@
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -771,9 +772,52 @@ static int __maybe_unused stmmac_runtime_resume(struct device *dev)
return stmmac_bus_clks_config(priv, true);
}
+static int stmmac_pltfr_noirq_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmmac_pltfr_noirq_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* enable the clk previously disabled */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ }
+
+ return 0;
+}
+
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
^ permalink raw reply related [relevance 4%]
* FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 4.4-stable tree
@ 2021-09-20 8:01 4% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2021-09-20 8:01 UTC (permalink / raw)
To: qiangqing.zhang, davem; +Cc: stable
The patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 276aae377206d60b9b7b7df4586cd9f2a813f5d0 Mon Sep 17 00:00:00 2001
From: Joakim Zhang <qiangqing.zhang@nxp.com>
Date: Wed, 8 Sep 2021 15:43:35 +0800
Subject: [PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during
suspend/resume
commit 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after
napi disabled"), this patch tries to fix system hang caused by eee_ctrl_timer,
unfortunately, it only can resolve it for system reboot stress test. System
hang also can be reproduced easily during system suspend/resume stess test
when mount NFS on i.MX8MP EVK board.
In stmmac driver, eee feature is combined to phylink framework. When do
system suspend, phylink_stop() would queue delayed work, it invokes
stmmac_mac_link_down(), where to deactivate eee_ctrl_timer synchronizly.
In above commit, try to fix issue by deactivating eee_ctrl_timer obviously,
but it is not enough. Looking into eee_ctrl_timer expire callback
stmmac_eee_ctrl_timer(), it could enable hareware eee mode again. What is
unexpected is that LPI interrupt (MAC_Interrupt_Enable.LPIEN bit) is always
asserted. This interrupt has chance to be issued when LPI state entry/exit
from the MAC, and at that time, clock could have been already disabled.
The result is that system hang when driver try to touch register from
interrupt handler.
The reason why above commit can fix system hang issue in stmmac_release()
is that, deactivate eee_ctrl_timer not just after napi disabled, further
after irq freed.
In conclusion, hardware would generate LPI interrupt when clock has been
disabled during suspend or resume, since hardware is in eee mode and LPI
interrupt enabled.
Interrupts from MAC, MTL and DMA level are enabled and never been disabled
when system suspend, so postpone clocks management from suspend stage to
noirq suspend stage should be more safe.
Fixes: 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after napi disabled")
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ece02b35a6ce..246f84fedbc8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7118,7 +7118,6 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan;
- int ret;
if (!ndev || !netif_running(ndev))
return 0;
@@ -7150,13 +7149,6 @@ int stmmac_suspend(struct device *dev)
} else {
stmmac_mac_set(priv, priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- clk_disable_unprepare(priv->plat->clk_ptp_ref);
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
}
mutex_unlock(&priv->lock);
@@ -7242,12 +7234,6 @@ int stmmac_resume(struct device *dev)
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
- /* enable the clk previously disabled */
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
- if (priv->plat->clk_ptp_ref)
- clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 5ca710844cc1..4885f9ad1b1e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,7 @@
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -771,9 +772,52 @@ static int __maybe_unused stmmac_runtime_resume(struct device *dev)
return stmmac_bus_clks_config(priv, true);
}
+static int stmmac_pltfr_noirq_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmmac_pltfr_noirq_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* enable the clk previously disabled */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ }
+
+ return 0;
+}
+
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
^ permalink raw reply related [relevance 4%]
* FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 5.4-stable tree
@ 2021-09-20 8:01 4% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2021-09-20 8:01 UTC (permalink / raw)
To: qiangqing.zhang, davem; +Cc: stable
The patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 276aae377206d60b9b7b7df4586cd9f2a813f5d0 Mon Sep 17 00:00:00 2001
From: Joakim Zhang <qiangqing.zhang@nxp.com>
Date: Wed, 8 Sep 2021 15:43:35 +0800
Subject: [PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during
suspend/resume
commit 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after
napi disabled"), this patch tries to fix system hang caused by eee_ctrl_timer,
unfortunately, it only can resolve it for system reboot stress test. System
hang also can be reproduced easily during system suspend/resume stess test
when mount NFS on i.MX8MP EVK board.
In stmmac driver, eee feature is combined to phylink framework. When do
system suspend, phylink_stop() would queue delayed work, it invokes
stmmac_mac_link_down(), where to deactivate eee_ctrl_timer synchronizly.
In above commit, try to fix issue by deactivating eee_ctrl_timer obviously,
but it is not enough. Looking into eee_ctrl_timer expire callback
stmmac_eee_ctrl_timer(), it could enable hareware eee mode again. What is
unexpected is that LPI interrupt (MAC_Interrupt_Enable.LPIEN bit) is always
asserted. This interrupt has chance to be issued when LPI state entry/exit
from the MAC, and at that time, clock could have been already disabled.
The result is that system hang when driver try to touch register from
interrupt handler.
The reason why above commit can fix system hang issue in stmmac_release()
is that, deactivate eee_ctrl_timer not just after napi disabled, further
after irq freed.
In conclusion, hardware would generate LPI interrupt when clock has been
disabled during suspend or resume, since hardware is in eee mode and LPI
interrupt enabled.
Interrupts from MAC, MTL and DMA level are enabled and never been disabled
when system suspend, so postpone clocks management from suspend stage to
noirq suspend stage should be more safe.
Fixes: 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after napi disabled")
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ece02b35a6ce..246f84fedbc8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7118,7 +7118,6 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan;
- int ret;
if (!ndev || !netif_running(ndev))
return 0;
@@ -7150,13 +7149,6 @@ int stmmac_suspend(struct device *dev)
} else {
stmmac_mac_set(priv, priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- clk_disable_unprepare(priv->plat->clk_ptp_ref);
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
}
mutex_unlock(&priv->lock);
@@ -7242,12 +7234,6 @@ int stmmac_resume(struct device *dev)
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
- /* enable the clk previously disabled */
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
- if (priv->plat->clk_ptp_ref)
- clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 5ca710844cc1..4885f9ad1b1e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,7 @@
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -771,9 +772,52 @@ static int __maybe_unused stmmac_runtime_resume(struct device *dev)
return stmmac_bus_clks_config(priv, true);
}
+static int stmmac_pltfr_noirq_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmmac_pltfr_noirq_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* enable the clk previously disabled */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ }
+
+ return 0;
+}
+
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
^ permalink raw reply related [relevance 4%]
* FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 4.19-stable tree
@ 2021-09-20 8:01 4% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2021-09-20 8:01 UTC (permalink / raw)
To: qiangqing.zhang, davem; +Cc: stable
The patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 276aae377206d60b9b7b7df4586cd9f2a813f5d0 Mon Sep 17 00:00:00 2001
From: Joakim Zhang <qiangqing.zhang@nxp.com>
Date: Wed, 8 Sep 2021 15:43:35 +0800
Subject: [PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during
suspend/resume
commit 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after
napi disabled"), this patch tries to fix system hang caused by eee_ctrl_timer,
unfortunately, it only can resolve it for system reboot stress test. System
hang also can be reproduced easily during system suspend/resume stess test
when mount NFS on i.MX8MP EVK board.
In stmmac driver, eee feature is combined to phylink framework. When do
system suspend, phylink_stop() would queue delayed work, it invokes
stmmac_mac_link_down(), where to deactivate eee_ctrl_timer synchronizly.
In above commit, try to fix issue by deactivating eee_ctrl_timer obviously,
but it is not enough. Looking into eee_ctrl_timer expire callback
stmmac_eee_ctrl_timer(), it could enable hareware eee mode again. What is
unexpected is that LPI interrupt (MAC_Interrupt_Enable.LPIEN bit) is always
asserted. This interrupt has chance to be issued when LPI state entry/exit
from the MAC, and at that time, clock could have been already disabled.
The result is that system hang when driver try to touch register from
interrupt handler.
The reason why above commit can fix system hang issue in stmmac_release()
is that, deactivate eee_ctrl_timer not just after napi disabled, further
after irq freed.
In conclusion, hardware would generate LPI interrupt when clock has been
disabled during suspend or resume, since hardware is in eee mode and LPI
interrupt enabled.
Interrupts from MAC, MTL and DMA level are enabled and never been disabled
when system suspend, so postpone clocks management from suspend stage to
noirq suspend stage should be more safe.
Fixes: 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after napi disabled")
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ece02b35a6ce..246f84fedbc8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7118,7 +7118,6 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan;
- int ret;
if (!ndev || !netif_running(ndev))
return 0;
@@ -7150,13 +7149,6 @@ int stmmac_suspend(struct device *dev)
} else {
stmmac_mac_set(priv, priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- clk_disable_unprepare(priv->plat->clk_ptp_ref);
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
}
mutex_unlock(&priv->lock);
@@ -7242,12 +7234,6 @@ int stmmac_resume(struct device *dev)
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
- /* enable the clk previously disabled */
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
- if (priv->plat->clk_ptp_ref)
- clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 5ca710844cc1..4885f9ad1b1e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,7 @@
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -771,9 +772,52 @@ static int __maybe_unused stmmac_runtime_resume(struct device *dev)
return stmmac_bus_clks_config(priv, true);
}
+static int stmmac_pltfr_noirq_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmmac_pltfr_noirq_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* enable the clk previously disabled */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ }
+
+ return 0;
+}
+
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
^ permalink raw reply related [relevance 4%]
* FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 5.10-stable tree
@ 2021-09-20 8:01 4% gregkh
0 siblings, 0 replies; 200+ results
From: gregkh @ 2021-09-20 8:01 UTC (permalink / raw)
To: qiangqing.zhang, davem; +Cc: stable
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 276aae377206d60b9b7b7df4586cd9f2a813f5d0 Mon Sep 17 00:00:00 2001
From: Joakim Zhang <qiangqing.zhang@nxp.com>
Date: Wed, 8 Sep 2021 15:43:35 +0800
Subject: [PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during
suspend/resume
commit 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after
napi disabled"), this patch tries to fix system hang caused by eee_ctrl_timer,
unfortunately, it only can resolve it for system reboot stress test. System
hang also can be reproduced easily during system suspend/resume stess test
when mount NFS on i.MX8MP EVK board.
In stmmac driver, eee feature is combined to phylink framework. When do
system suspend, phylink_stop() would queue delayed work, it invokes
stmmac_mac_link_down(), where to deactivate eee_ctrl_timer synchronizly.
In above commit, try to fix issue by deactivating eee_ctrl_timer obviously,
but it is not enough. Looking into eee_ctrl_timer expire callback
stmmac_eee_ctrl_timer(), it could enable hareware eee mode again. What is
unexpected is that LPI interrupt (MAC_Interrupt_Enable.LPIEN bit) is always
asserted. This interrupt has chance to be issued when LPI state entry/exit
from the MAC, and at that time, clock could have been already disabled.
The result is that system hang when driver try to touch register from
interrupt handler.
The reason why above commit can fix system hang issue in stmmac_release()
is that, deactivate eee_ctrl_timer not just after napi disabled, further
after irq freed.
In conclusion, hardware would generate LPI interrupt when clock has been
disabled during suspend or resume, since hardware is in eee mode and LPI
interrupt enabled.
Interrupts from MAC, MTL and DMA level are enabled and never been disabled
when system suspend, so postpone clocks management from suspend stage to
noirq suspend stage should be more safe.
Fixes: 5f58591323bf ("net: stmmac: delete the eee_ctrl_timer after napi disabled")
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ece02b35a6ce..246f84fedbc8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7118,7 +7118,6 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan;
- int ret;
if (!ndev || !netif_running(ndev))
return 0;
@@ -7150,13 +7149,6 @@ int stmmac_suspend(struct device *dev)
} else {
stmmac_mac_set(priv, priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
- /* Disable clock in case of PWM is off */
- clk_disable_unprepare(priv->plat->clk_ptp_ref);
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- mutex_unlock(&priv->lock);
- return ret;
- }
}
mutex_unlock(&priv->lock);
@@ -7242,12 +7234,6 @@ int stmmac_resume(struct device *dev)
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
- /* enable the clk previously disabled */
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
- if (priv->plat->clk_ptp_ref)
- clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */
if (priv->mii)
stmmac_mdio_reset(priv->mii);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 5ca710844cc1..4885f9ad1b1e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -9,6 +9,7 @@
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -771,9 +772,52 @@ static int __maybe_unused stmmac_runtime_resume(struct device *dev)
return stmmac_bus_clks_config(priv, true);
}
+static int stmmac_pltfr_noirq_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->plat->clk_ptp_ref);
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmmac_pltfr_noirq_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
+ /* enable the clk previously disabled */
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ clk_prepare_enable(priv->plat->clk_ptp_ref);
+ }
+
+ return 0;
+}
+
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
^ permalink raw reply related [relevance 4%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-09-02 11:48 0% ` Pavel Machek
@ 2021-09-02 12:02 0% ` Greg KH
0 siblings, 0 replies; 200+ results
From: Greg KH @ 2021-09-02 12:02 UTC (permalink / raw)
To: Pavel Machek
Cc: nobuhiro1.iwamatsu, Pali Rohár, stable, Sasha Levin,
Kalle Valo, linux-wireless
On Thu, Sep 02, 2021 at 01:48:14PM +0200, Pavel Machek wrote:
> Hi!
>
> > > > > Hello! I would like to request for backporting following ath9k commits
> > > > > which are fixing CVE-2020-3702 issue.
> > > > >
> > > > > 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
> > > > > 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
> > > > > d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
> > > > > 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
> > > > > ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
> > > > >
> > > > > See also:
> > > > > https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
> ...
> > > > What stable tree(s) do you want to see these go into?
> > >
> > > Commits were introduced in 5.12, so it should go to all stable trees << 5.12
>
> ...
>
> > Great, all now queued up. Sad that qcom didn't want to do this
> > themselves :(
>
> Thanks for the fixes; I see them in 4.14 and newer stable trees.
>
> But I don't see them in 4.4 and 4.9, nor can I see reason why they
> were not applied.
>
> Can someone help?
Odd, I don't remember why I didn't even try to apply them to older
kernels. I'll do that after this next round is released in a few days,
sorry about that.
greg k-h
^ permalink raw reply [relevance 0%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-08-18 9:18 0% ` Greg KH
2021-08-20 11:35 0% ` Pali Rohár
@ 2021-09-02 11:48 0% ` Pavel Machek
2021-09-02 12:02 0% ` Greg KH
1 sibling, 1 reply; 200+ results
From: Pavel Machek @ 2021-09-02 11:48 UTC (permalink / raw)
To: Greg KH, nobuhiro1.iwamatsu
Cc: Pali Rohár, stable, Sasha Levin, Kalle Valo, linux-wireless
[-- Attachment #1: Type: text/plain, Size: 1243 bytes --]
Hi!
> > > > Hello! I would like to request for backporting following ath9k commits
> > > > which are fixing CVE-2020-3702 issue.
> > > >
> > > > 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
> > > > 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
> > > > d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
> > > > 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
> > > > ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
> > > >
> > > > See also:
> > > > https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
...
> > > What stable tree(s) do you want to see these go into?
> >
> > Commits were introduced in 5.12, so it should go to all stable trees << 5.12
...
> Great, all now queued up. Sad that qcom didn't want to do this
> themselves :(
Thanks for the fixes; I see them in 4.14 and newer stable trees.
But I don't see them in 4.4 and 4.9, nor can I see reason why they
were not applied.
Can someone help?
Thanks,
Pavel
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply [relevance 0%]
* Linux 4.14.245
@ 2021-08-26 13:26 3% Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2021-08-26 13:26 UTC (permalink / raw)
To: linux-kernel, stable, akpm, torvalds; +Cc: lwn, jslaby, gregkh
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
I'm announcing the release of the 4.14.245 kernel.
All users of the 4.14 kernel series must upgrade.
The updated 4.14.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-4.14.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
Thanks,
Sasha
- ------------
Documentation/filesystems/mandatory-locking.txt | 10 ++
Makefile | 2 +-
arch/arm/boot/dts/am43x-epos-evm.dts | 2 +-
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi | 4 +-
arch/powerpc/kernel/kprobes.c | 3 +-
arch/x86/include/asm/fpu/internal.h | 30 ++----
arch/x86/include/asm/svm.h | 2 +
arch/x86/kernel/cpu/intel_rdt_monitor.c | 27 +++--
arch/x86/kernel/fpu/xstate.c | 38 ++++++-
arch/x86/kvm/svm.c | 18 ++--
arch/x86/tools/chkobjdump.awk | 1 +
drivers/acpi/nfit/core.c | 3 +
drivers/base/core.c | 1 +
drivers/dma/of-dma.c | 9 +-
drivers/dma/sh/usb-dmac.c | 2 +-
drivers/i2c/i2c-dev.c | 5 +-
drivers/iio/adc/palmas_gpadc.c | 4 +-
drivers/iio/humidity/hdc100x.c | 6 +-
drivers/ipack/carriers/tpci200.c | 36 +++----
drivers/mmc/host/dw_mmc.c | 6 +-
drivers/net/dsa/mt7530.c | 1 +
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 54 ++++++----
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 +-
drivers/net/hamradio/6pack.c | 6 ++
drivers/net/phy/mdio-mux.c | 36 ++++---
drivers/net/ppp/ppp_generic.c | 2 +-
drivers/net/usb/lan78xx.c | 16 ++-
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 +++++++++++++++-
drivers/net/wireless/ath/key.c | 41 ++++---
drivers/pci/msi.c | 120 +++++++++++++--------
drivers/ptp/Kconfig | 3 +-
drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +-
drivers/scsi/megaraid/megaraid_mm.c | 21 ++--
drivers/scsi/scsi_scan.c | 3 +-
drivers/vhost/vhost.c | 10 +-
drivers/xen/events/events_base.c | 20 ++--
fs/btrfs/inode.c | 10 +-
fs/namespace.c | 15 ++-
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/device.h | 1 +
include/linux/msi.h | 2 +-
include/net/psample.h | 2 +
net/bluetooth/hidp/core.c | 2 +-
net/bridge/br_if.c | 2 +
net/dccp/dccp.h | 6 +-
net/ieee802154/socket.c | 7 +-
net/ipv4/tcp_bbr.c | 2 +-
net/mac80211/debugfs_sta.c | 1 +
net/mac80211/key.c | 1 +
net/mac80211/sta_info.h | 1 +
net/mac80211/tx.c | 12 ++-
net/netfilter/nft_exthdr.c | 8 +-
net/vmw_vsock/virtio_transport.c | 7 +-
sound/pci/hda/hda_generic.c | 10 +-
sound/soc/codecs/cs42l42.c | 18 +---
sound/soc/intel/atom/sst-mfld-platform-pcm.c | 3 +-
60 files changed, 519 insertions(+), 245 deletions(-)
Andy Shevchenko (1):
ptp_pch: Restore dependency on PCI
Babu Moger (1):
x86/resctrl: Fix default monitoring groups reporting
Chris Lesiak (1):
iio: humidity: hdc100x: Add margin to the conversion time
Colin Ian King (1):
iio: adc: Fix incorrect exit of for-loop
DENG Qingfang (1):
net: dsa: mt7530: add the missing RxUnicast MIB counter
Dan Williams (1):
ACPI: NFIT: Fix support for virtual SPA ranges
Dave Gerlach (1):
ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
Dinghao Liu (1):
net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
Dongliang Mu (1):
ipack: tpci200: fix many double free issues in tpci200_pci_probe
Greg Kroah-Hartman (1):
i2c: dev: zero out array used for i2c reads from userspace
Harshvardhan Jha (1):
scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
Ivan T. Ivanov (1):
net: usb: lan78xx: don't modify phy_device state concurrently
Jakub Kicinski (1):
bnxt: don't lock the tx queue from napi poll
Jaroslav Kysela (1):
ALSA: hda - fix the 'Capture Switch' value change notifications
Jeff Layton (2):
locks: print a warning when mount fails due to lack of "mand" support
fs: warn about impending deprecation of mandatory locks
Johannes Berg (1):
mac80211: drop data frames without key on encrypted links
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Longpeng(Mike) (1):
vsock/virtio: avoid potential deadlock when vsock device remove
Maxim Levitsky (2):
KVM: nSVM: always intercept VMLOAD/VMSAVE when nested (CVE-2021-3656)
KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl (CVE-2021-3653)
Maximilian Heyne (1):
xen/events: Fix race in set_evtchn_to_irq
Nathan Chancellor (1):
vmlinux.lds.h: Handle clang's module.{c,d}tor sections
Neal Cardwell (1):
tcp_bbr: fix u32 wrap bug in round logic if bbr_init() called after 2B packets
NeilBrown (1):
btrfs: prevent rename2 from exchanging a subvol with a directory from different parents
Ole Bjørn Midtbø (1):
Bluetooth: hidp: use correct wait queue when removing ctrl_wait
Pali Rohár (1):
ppp: Fix generating ifname when empty IFLA_IFNAME is specified
Pavel Skripkin (1):
net: 6pack: fix slab-out-of-bounds in decode_data
Peter Ujfalusi (1):
dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller is not yet available
Pu Lehui (1):
powerpc/kprobes: Fix kprobe Oops happens in booke
Randy Dunlap (2):
x86/tools: Fix objdump version check again
dccp: add do-while-0 stubs for dccp_pr_debug macros
Richard Fitzgerald (4):
ASoC: cs42l42: Correct definition of ADC Volume control
ASoC: cs42l42: Don't allow SND_SOC_DAIFMT_LEFT_J
ASoC: cs42l42: Fix inversion of ADC Notch Switch control
ASoC: cs42l42: Remove duplicate control for WNF filter frequency
Roi Dayan (1):
psample: Add a fwd declaration for skbuff
Saravana Kannan (2):
net: mdio-mux: Don't ignore memory allocation errors
net: mdio-mux: Handle -EPROBE_DEFER correctly
Sasha Levin (1):
Linux 4.14.245
Sergey Marinkevich (1):
netfilter: nft_exthdr: fix endianness of tcp option cast
Sreekanth Reddy (1):
scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
Sudeep Holla (1):
ARM: dts: nomadik: Fix up interrupt controller node names
Takashi Iwai (2):
ASoC: intel: atom: Fix reference to PCM buffer address
ASoC: intel: atom: Fix breakage for PCM buffer address setup
Takeshi Misawa (1):
net: Fix memory leak in ieee802154_raw_deliver
Thomas Gleixner (9):
PCI/MSI: Enable and mask MSI-X early
PCI/MSI: Do not set invalid bits in MSI mask
PCI/MSI: Correct misleading comments
PCI/MSI: Use msi_mask_irq() in pci_msi_shutdown()
PCI/MSI: Protect msi_desc::masked for multi-MSI
PCI/MSI: Mask all unused MSI-X entries
PCI/MSI: Enforce that MSI-X table entry is masked for update
PCI/MSI: Enforce MSI[X] entry updates to be visible
x86/fpu: Make init_fpstate correct with optimized XSAVE
Vincent Whitchurch (1):
mmc: dw_mmc: Fix hang on data CRC error
Xie Yongji (1):
vhost: Fix the calculation in vhost_overflow()
Yang Yingliang (1):
net: bridge: fix memleak in br_add_if()
Ye Bin (1):
scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
Yu Kuai (1):
dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEE4n5dijQDou9mhzu83qZv95d3LNwFAmEnlpMACgkQ3qZv95d3
LNwKAQ/9Gr0ysGptdWcNzvMYlATS3atpWiv3GO3JrCiwyJI2EeEc0TB0T5V7eCi2
zsWOtUtHo4D3mpOBOv6wYXqSre+4oMYG7PgcdETBBOm2elnkLODmhG9d0tkCWy3z
SbXfLSIW620gD8sFEHXqhmcI9jV3dEftmpVpyRTF+NhWW3SeaMnCYFAgqsYoJC0u
9zQ0iYME2+jt+eg+BYwxtpEpeN+B1QLTAunVDllOwG+0VcTfrDaSjabHQFjjPQgL
IDIkO/y+Ky6csz3CtIftuBadnwEu0aSNLP5LqeSfLds6w2ET20b6YcY03FSOINBA
dxDK7Z1A63ycMzwJf5Fz8dGBsU2ogHBpmAijx2Qh74vsMlDLDMX1PRKvOtvkBNny
SWRhnKbYr2KSeLzJIZXhy4y1t05gFd4n8CeJW/hNfPNKnfeZuHZWF/3QJq/pdRU0
g2n9khhOPmceOWxGVP9ydAPI70r9oVPXtNDoEbhzgn7/lC79qnPLSYLHxn0uzCuf
POBMLAbgC7gvvcdqT0KvKXZosXVTGJYXd10vcuN1Ks/zB4E0ijVuepoGRqBRQPvO
4m7AqE7WDkErLHQ03nHHTN2BNQ+FiIPi5EUrvTh9pqLRXMZ6JbBvIrYFIkJ0Wa6O
zKE0gTTY/epzoM6iZLNtnW3PI1iDTL6vVXM+fFJmKUU6CvU7Bwk=
=ZbMT
-----END PGP SIGNATURE-----
^ permalink raw reply [relevance 3%]
* Linux 4.19.205
@ 2021-08-26 13:26 3% Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2021-08-26 13:26 UTC (permalink / raw)
To: linux-kernel, stable, akpm, torvalds; +Cc: lwn, jslaby, gregkh
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
I'm announcing the release of the 4.19.205 kernel.
All users of the 4.19 kernel series must upgrade.
The updated 4.19.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-4.19.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
Thanks,
Sasha
- ------------
Documentation/filesystems/mandatory-locking.txt | 10 ++
Makefile | 2 +-
arch/arm/boot/dts/am43x-epos-evm.dts | 2 +-
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi | 4 +-
arch/powerpc/kernel/kprobes.c | 3 +-
arch/x86/include/asm/fpu/internal.h | 30 ++----
arch/x86/include/asm/svm.h | 2 +
arch/x86/kernel/apic/io_apic.c | 6 +-
arch/x86/kernel/apic/msi.c | 13 ++-
arch/x86/kernel/cpu/intel_rdt_monitor.c | 27 +++--
arch/x86/kernel/fpu/xstate.c | 38 ++++++-
arch/x86/kvm/svm.c | 18 ++--
arch/x86/tools/chkobjdump.awk | 1 +
drivers/acpi/nfit/core.c | 3 +
drivers/base/core.c | 1 +
drivers/cpufreq/armada-37xx-cpufreq.c | 6 +-
drivers/dma/of-dma.c | 9 +-
drivers/dma/sh/usb-dmac.c | 2 +-
drivers/dma/xilinx/xilinx_dma.c | 12 +++
drivers/i2c/i2c-dev.c | 5 +-
drivers/iio/adc/palmas_gpadc.c | 4 +-
drivers/iio/humidity/hdc100x.c | 6 +-
drivers/iommu/intel-iommu.c | 7 +-
drivers/ipack/carriers/tpci200.c | 60 ++++++-----
drivers/mmc/host/dw_mmc.c | 6 +-
drivers/net/dsa/lan9303-core.c | 34 +++---
drivers/net/dsa/mt7530.c | 1 +
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 57 +++++-----
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 +-
drivers/net/hamradio/6pack.c | 6 ++
drivers/net/ieee802154/mac802154_hwsim.c | 6 +-
drivers/net/phy/mdio-mux.c | 36 ++++---
drivers/net/ppp/ppp_generic.c | 2 +-
drivers/net/usb/lan78xx.c | 16 ++-
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 +++++++++++++++-
drivers/net/wireless/ath/key.c | 41 ++++---
drivers/pci/msi.c | 120 +++++++++++++--------
drivers/pci/quirks.c | 1 +
drivers/ptp/Kconfig | 3 +-
drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +-
drivers/scsi/megaraid/megaraid_mm.c | 21 ++--
drivers/scsi/scsi_scan.c | 3 +-
drivers/slimbus/messaging.c | 7 +-
drivers/slimbus/qcom-ngd-ctrl.c | 5 +-
drivers/vhost/vhost.c | 10 +-
drivers/xen/events/events_base.c | 20 ++--
fs/btrfs/inode.c | 10 +-
fs/namespace.c | 15 ++-
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/device.h | 1 +
include/linux/inetdevice.h | 2 +-
include/linux/irq.h | 2 +
include/linux/msi.h | 2 +-
include/net/psample.h | 2 +
kernel/irq/chip.c | 5 +-
kernel/irq/msi.c | 13 ++-
kernel/trace/trace_events_hist.c | 2 +
net/bluetooth/hidp/core.c | 2 +-
net/bridge/br_if.c | 2 +
net/dccp/dccp.h | 6 +-
net/ieee802154/socket.c | 7 +-
net/ipv4/igmp.c | 21 ++--
net/ipv4/tcp_bbr.c | 2 +-
net/mac80211/debugfs_sta.c | 1 +
net/mac80211/key.c | 1 +
net/mac80211/sta_info.h | 1 +
net/mac80211/tx.c | 12 ++-
net/netfilter/nft_exthdr.c | 8 +-
net/vmw_vsock/virtio_transport.c | 7 +-
sound/pci/hda/hda_generic.c | 10 +-
sound/soc/codecs/cs42l42.c | 39 +++----
sound/soc/intel/atom/sst-mfld-platform-pcm.c | 3 +-
76 files changed, 642 insertions(+), 312 deletions(-)
Adrian Larumbe (1):
dmaengine: xilinx_dma: Fix read-after-free bug when terminating transfers
Andy Shevchenko (1):
ptp_pch: Restore dependency on PCI
Babu Moger (1):
x86/resctrl: Fix default monitoring groups reporting
Bixuan Cui (1):
genirq/msi: Ensure deactivation on teardown
Chris Lesiak (1):
iio: humidity: hdc100x: Add margin to the conversion time
Colin Ian King (1):
iio: adc: Fix incorrect exit of for-loop
DENG Qingfang (1):
net: dsa: mt7530: add the missing RxUnicast MIB counter
Dan Williams (1):
ACPI: NFIT: Fix support for virtual SPA ranges
Dave Gerlach (1):
ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
Dinghao Liu (1):
net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
Dongliang Mu (4):
ieee802154: hwsim: fix GPF in hwsim_set_edge_lqi
ieee802154: hwsim: fix GPF in hwsim_new_edge_nl
ipack: tpci200: fix many double free issues in tpci200_pci_probe
ipack: tpci200: fix memory leak in the tpci200_register
Eric Dumazet (2):
net: igmp: fix data-race in igmp_ifc_timer_expire()
net: igmp: increase size of mr_ifc_count
Greg Kroah-Hartman (1):
i2c: dev: zero out array used for i2c reads from userspace
Harshvardhan Jha (1):
scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
Ivan T. Ivanov (1):
net: usb: lan78xx: don't modify phy_device state concurrently
Jakub Kicinski (2):
bnxt: don't lock the tx queue from napi poll
bnxt: disable napi before canceling DIM
Jaroslav Kysela (1):
ALSA: hda - fix the 'Capture Switch' value change notifications
Jeff Layton (2):
locks: print a warning when mount fails due to lack of "mand" support
fs: warn about impending deprecation of mandatory locks
Johannes Berg (1):
mac80211: drop data frames without key on encrypted links
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Longpeng(Mike) (1):
vsock/virtio: avoid potential deadlock when vsock device remove
Marcin Bachry (1):
PCI: Increase D3 delay for AMD Renoir/Cezanne XHCI
Marek Behún (1):
cpufreq: armada-37xx: forbid cpufreq for 1.2 GHz variant
Maxim Levitsky (2):
KVM: nSVM: always intercept VMLOAD/VMSAVE when nested (CVE-2021-3656)
KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl (CVE-2021-3653)
Maximilian Heyne (1):
xen/events: Fix race in set_evtchn_to_irq
Nathan Chancellor (1):
vmlinux.lds.h: Handle clang's module.{c,d}tor sections
Neal Cardwell (1):
tcp_bbr: fix u32 wrap bug in round logic if bbr_init() called after 2B packets
NeilBrown (1):
btrfs: prevent rename2 from exchanging a subvol with a directory from different parents
Ole Bjørn Midtbø (1):
Bluetooth: hidp: use correct wait queue when removing ctrl_wait
Pali Rohár (1):
ppp: Fix generating ifname when empty IFLA_IFNAME is specified
Pavel Skripkin (1):
net: 6pack: fix slab-out-of-bounds in decode_data
Peter Ujfalusi (1):
dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller is not yet available
Pu Lehui (1):
powerpc/kprobes: Fix kprobe Oops happens in booke
Randy Dunlap (2):
x86/tools: Fix objdump version check again
dccp: add do-while-0 stubs for dccp_pr_debug macros
Richard Fitzgerald (5):
ASoC: cs42l42: Correct definition of ADC Volume control
ASoC: cs42l42: Don't allow SND_SOC_DAIFMT_LEFT_J
ASoC: cs42l42: Fix inversion of ADC Notch Switch control
ASoC: cs42l42: Remove duplicate control for WNF filter frequency
ASoC: cs42l42: Fix LRCLK frame start edge
Roi Dayan (1):
psample: Add a fwd declaration for skbuff
Saeed Mirzamohammadi (1):
iommu/vt-d: Fix agaw for a supported 48 bit guest address width
Saravana Kannan (2):
net: mdio-mux: Don't ignore memory allocation errors
net: mdio-mux: Handle -EPROBE_DEFER correctly
Sasha Levin (1):
Linux 4.19.205
Sergey Marinkevich (1):
netfilter: nft_exthdr: fix endianness of tcp option cast
Sreekanth Reddy (1):
scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
Srinivas Kandagatla (3):
slimbus: messaging: start transaction ids from 1 instead of zero
slimbus: messaging: check for valid transaction id
slimbus: ngd: reset dma setup during runtime pm
Steven Rostedt (VMware) (1):
tracing / histogram: Fix NULL pointer dereference on strcmp() on NULL event name
Sudeep Holla (1):
ARM: dts: nomadik: Fix up interrupt controller node names
Takashi Iwai (2):
ASoC: intel: atom: Fix reference to PCM buffer address
ASoC: intel: atom: Fix breakage for PCM buffer address setup
Takeshi Misawa (1):
net: Fix memory leak in ieee802154_raw_deliver
Thomas Gleixner (12):
genirq: Provide IRQCHIP_AFFINITY_PRE_STARTUP
x86/msi: Force affinity setup before startup
x86/ioapic: Force affinity setup before startup
PCI/MSI: Enable and mask MSI-X early
PCI/MSI: Do not set invalid bits in MSI mask
PCI/MSI: Correct misleading comments
PCI/MSI: Use msi_mask_irq() in pci_msi_shutdown()
PCI/MSI: Protect msi_desc::masked for multi-MSI
PCI/MSI: Mask all unused MSI-X entries
PCI/MSI: Enforce that MSI-X table entry is masked for update
PCI/MSI: Enforce MSI[X] entry updates to be visible
x86/fpu: Make init_fpstate correct with optimized XSAVE
Vincent Whitchurch (1):
mmc: dw_mmc: Fix hang on data CRC error
Vladimir Oltean (1):
net: dsa: lan9303: fix broken backpressure in .port_fdb_dump
Xie Yongji (1):
vhost: Fix the calculation in vhost_overflow()
Yang Yingliang (1):
net: bridge: fix memleak in br_add_if()
Ye Bin (1):
scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
Yu Kuai (1):
dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEE4n5dijQDou9mhzu83qZv95d3LNwFAmEnln8ACgkQ3qZv95d3
LNw2vxAArASjjGco/gXLRE2d+dvDw6N0Rm+fASnqYxXEr1skS+PL769UbkN4LM+n
17oKT96lJH3BGdB3na0PO07JjTh1Tl0zmfLxU2E0kwSXn42ojhHyhbe1kT/n3xhq
aaGpSZkESop9rdnOYMtROHQ9kVPdYXpMZ7Fm1RQlINBSe3amz4dCPygujPlWlICO
kA0EDLn8uCxJ/u7xJFw0AYJKhCeKMJor0qgb1pDaBFDfZzFx0luGs8Gh2Dpen576
NhjWSsGCFfAo6OIuCi+LfNx4SHJt5CSx8quTEm0MA91GAAvfaWoHDiPsxWyu3oTh
RIMO7HVV8cr+vfihKG50MlmvnCbhtXstxaMo+JacH/pqhmCVwgbOJhiq76cMvONH
geBqN0r6Jqd0AAqES9oyxi35ynntwUMLrHqHHqCiNaebYIMgt9Xz8ftRP4ZKO8EB
vZsuWBfcTdc+kLMAkKRJTm7pWEC7P4STFy8n0pyUOHAAiMnjpL7JZ1m052mH5mkH
v+xVmzuAaFUYi3od5Y4RuKDbuP0PWOhd7B/U4bdCk05/FiYbpJoEJjKN3T9DHmQ8
0ilaZO16sPRUtVQOoPfLsF3uWFX3J5x2A80mdfrZgD69FUy+TEGvBETuTcdCXtcV
rD7RjzSgjZkG9DyfZbEw+4krg7nM1kCoCrhMKaZgm4jriZXVHZw=
=T5oG
-----END PGP SIGNATURE-----
^ permalink raw reply [relevance 3%]
* Linux 5.4.143
@ 2021-08-26 13:26 3% Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2021-08-26 13:26 UTC (permalink / raw)
To: linux-kernel, stable, akpm, torvalds; +Cc: lwn, jslaby, gregkh
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
I'm announcing the release of the 5.4.143 kernel.
All users of the 5.4 kernel series must upgrade.
The updated 5.4.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.4.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
Thanks,
Sasha
- ------------
Makefile | 2 +-
arch/arm/boot/dts/am43x-epos-evm.dts | 2 +-
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi | 4 +-
arch/x86/include/asm/fpu/internal.h | 30 ++-----
arch/x86/kernel/fpu/xstate.c | 38 ++++++++-
drivers/cpufreq/armada-37xx-cpufreq.c | 6 +-
drivers/dma/of-dma.c | 9 +-
drivers/dma/sh/usb-dmac.c | 2 +-
drivers/dma/xilinx/xilinx_dma.c | 12 +++
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 2 +-
drivers/iommu/iommu.c | 3 +
drivers/ipack/carriers/tpci200.c | 60 +++++++-------
drivers/media/usb/zr364xx/zr364xx.c | 77 ++++++++++++------
drivers/mmc/host/dw_mmc.c | 6 +-
drivers/mtd/chips/cfi_cmdset_0002.c | 2 +-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 69 ++++++++++------
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 +-
drivers/net/ethernet/intel/iavf/iavf.h | 1 +
drivers/net/ethernet/intel/iavf/iavf_main.c | 1 +
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 47 ++++++++++-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 +-
drivers/net/hamradio/6pack.c | 6 ++
drivers/net/phy/mdio-mux.c | 36 +++++---
drivers/net/usb/lan78xx.c | 16 +++-
drivers/net/virtio_net.c | 76 ++++++++++++-----
drivers/net/vrf.c | 4 +
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 +++++++++++++++++++++-
drivers/net/wireless/ath/key.c | 41 ++++++----
drivers/pci/quirks.c | 1 +
drivers/ptp/Kconfig | 3 +-
drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +-
drivers/scsi/megaraid/megaraid_mm.c | 21 +++--
drivers/scsi/scsi_scan.c | 3 +-
drivers/scsi/scsi_sysfs.c | 9 +-
drivers/slimbus/messaging.c | 7 +-
drivers/slimbus/qcom-ngd-ctrl.c | 5 +-
drivers/usb/core/message.c | 6 ++
drivers/vhost/vhost.c | 10 ++-
drivers/virtio/virtio.c | 1 +
drivers/virtio/virtio_ring.c | 8 ++
fs/btrfs/inode.c | 10 ++-
fs/ext4/ext4.h | 2 +-
fs/namespace.c | 6 +-
fs/overlayfs/file.c | 47 +++++++++++
include/linux/memcontrol.h | 59 +++++++++++---
include/linux/virtio.h | 1 +
kernel/bpf/verifier.c | 1 +
kernel/trace/trace_events_hist.c | 2 +
mm/memcontrol.c | 8 ++
mm/vmscan.c | 26 ++++--
net/bluetooth/hidp/core.c | 2 +-
net/dccp/dccp.h | 6 +-
net/netfilter/nft_exthdr.c | 8 +-
net/openvswitch/vport.c | 1 +
sound/pci/hda/hda_generic.c | 10 ++-
sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +-
60 files changed, 701 insertions(+), 230 deletions(-)
Adrian Larumbe (1):
dmaengine: xilinx_dma: Fix read-after-free bug when terminating transfers
Alan Stern (1):
USB: core: Avoid WARNings for 0-length descriptor requests
Andreas Persson (1):
mtd: cfi_cmdset_0002: fix crash when erasing/writing AMD cards
Andy Shevchenko (1):
ptp_pch: Restore dependency on PCI
Arkadiusz Kubalewski (1):
i40e: Fix ATR queue selection
Bing Guo (1):
drm/amd/display: Fix Dynamic bpp issue with 8K30 with Navi 1X
Dan Carpenter (1):
media: zr364xx: fix memory leaks in probe()
Dave Gerlach (1):
ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
Dinghao Liu (1):
net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
Dongliang Mu (2):
ipack: tpci200: fix many double free issues in tpci200_pci_probe
ipack: tpci200: fix memory leak in the tpci200_register
Evgeny Novikov (1):
media: zr364xx: propagate errors from zr364xx_start_readpipe()
Frank Wunderlich (1):
iommu: Check if group is NULL before remove device
Harshvardhan Jha (1):
scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
Ilya Leoshkevich (1):
bpf: Clear zext_dst of dead insns
Ivan T. Ivanov (1):
net: usb: lan78xx: don't modify phy_device state concurrently
Jakub Kicinski (2):
bnxt: don't lock the tx queue from napi poll
bnxt: disable napi before canceling DIM
Jaroslav Kysela (1):
ALSA: hda - fix the 'Capture Switch' value change notifications
Jason Wang (1):
virtio-net: use NETIF_F_GRO_HW instead of NETIF_F_LRO
Jeff Layton (1):
fs: warn about impending deprecation of mandatory locks
Johannes Weiner (1):
mm: memcontrol: fix occasional OOMs due to proportional memory.low reclaim
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Lahav Schlesinger (1):
vrf: Reset skb conntrack connection on VRF rcv
Marcin Bachry (1):
PCI: Increase D3 delay for AMD Renoir/Cezanne XHCI
Marek Behún (1):
cpufreq: armada-37xx: forbid cpufreq for 1.2 GHz variant
Michael Chan (1):
bnxt_en: Add missing DMA memory barriers
Murphy Zhou (1):
ovl: add splice file read write helper
NeilBrown (1):
btrfs: prevent rename2 from exchanging a subvol with a directory from different parents
Ole Bjørn Midtbø (1):
Bluetooth: hidp: use correct wait queue when removing ctrl_wait
Parav Pandit (1):
virtio: Protect vqs list access
Pavel Skripkin (2):
media: drivers/media/usb: fix memory leak in zr364xx_probe
net: 6pack: fix slab-out-of-bounds in decode_data
Peter Ujfalusi (1):
dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller is not yet available
Randy Dunlap (1):
dccp: add do-while-0 stubs for dccp_pr_debug macros
Ritesh Harjani (1):
ext4: fix EXT4_MAX_LOGICAL_BLOCK macro
Saravana Kannan (2):
net: mdio-mux: Don't ignore memory allocation errors
net: mdio-mux: Handle -EPROBE_DEFER correctly
Sasha Levin (1):
Linux 5.4.143
Sergey Marinkevich (1):
netfilter: nft_exthdr: fix endianness of tcp option cast
Sreekanth Reddy (1):
scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
Srinivas Kandagatla (3):
slimbus: messaging: start transaction ids from 1 instead of zero
slimbus: messaging: check for valid transaction id
slimbus: ngd: reset dma setup during runtime pm
Steven Rostedt (VMware) (1):
tracing / histogram: Fix NULL pointer dereference on strcmp() on NULL event name
Sudeep Holla (1):
ARM: dts: nomadik: Fix up interrupt controller node names
Sylwester Dziedziuch (1):
iavf: Fix ping is lost after untrusted VF had tried to change MAC
Takashi Iwai (1):
ASoC: intel: atom: Fix breakage for PCM buffer address setup
Thomas Gleixner (1):
x86/fpu: Make init_fpstate correct with optimized XSAVE
Vincent Whitchurch (1):
mmc: dw_mmc: Fix hang on data CRC error
Xie Yongji (1):
vhost: Fix the calculation in vhost_overflow()
Xuan Zhuo (1):
virtio-net: support XDP when not more queues
Yafang Shao (1):
mm, memcg: avoid stale protection values when cgroup is above protection
Ye Bin (1):
scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
Yu Kuai (1):
dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
kaixi.fan (1):
ovs: clear skb->tstamp in forwarding path
lijinlin (1):
scsi: core: Fix capacity set to zero after offlinining device
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEE4n5dijQDou9mhzu83qZv95d3LNwFAmEnlm8ACgkQ3qZv95d3
LNz7CBAAjeVaEg+B20WOCZbSHy5fdhoC9+mWf9SudyD7dypEqK22Kwn2VE/FZKYT
8U+yxhVQkFxsT0S7oPowBY0BENxm/R9TByp0UTLyaObVW+XcQ1AOugdmZdQOE+MW
pm0aZlzvCJq5c/W79f14MuzYzVBziLBMDkDCo4/OHE2/KgB0QUm/W4vEiwUXVGBz
dCEpRf2KN9iCuwGcWn7zqhwbyK1uMdnX38I1lA54TTrU7rN/y71hSr5hbqPWO7lL
IFBTxIBRS/Hl29OgiZeiMKuAFWcUeVd7M/w2AmLsIFArAysUX/Q1uJsvk6XFjb8d
IPejWpy6vAsrOF36QSUt2WxoNDvovjjZmoid3fq8D6YIocDnInBe47jmVNLsktrD
zgrBeQ5Cn8rSMe8c6+zco12wlDP7gj+7bQr5MR4rDxYi0V94l6Bgs35YrB4H6TZR
idc3DHw6CPApHcs+KT1jr/0uvmqQS3cIRw+r9ZK7skDVxFzZ7ERTLf+1K7TirRLK
AxVxY3XrdN/89zqL9bcQE3uEIPHXhbRr80nrlKyccUu4zjfEcEJH4DoNXSLnmRFP
qHVcx6xnWYugwWjVKUC6cYySHyuI2TrxwrbYW2UDGSAkY5O4gzyE7SS+0wduDLME
o2UyVyPfEVziEk3JtvxG3qJGDxPkPy33hH0ANsz3brIMZAPiVAA=
=g5fv
-----END PGP SIGNATURE-----
^ permalink raw reply [relevance 3%]
* Linux 5.10.61
@ 2021-08-26 13:25 3% Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2021-08-26 13:25 UTC (permalink / raw)
To: linux-kernel, stable, akpm, torvalds; +Cc: lwn, jslaby, gregkh
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
I'm announcing the release of the 5.10.61 kernel.
All users of the 5.10 kernel series must upgrade.
The updated 5.10.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.10.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
Thanks,
Sasha
- ------------
Makefile | 2 +-
arch/arm/boot/dts/am43x-epos-evm.dts | 2 +-
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi | 4 +-
.../boot/dts/qcom/msm8992-bullhead-rev-101.dts | 4 +
.../boot/dts/qcom/sdm850-lenovo-yoga-c630.dts | 4 +-
arch/s390/pci/pci.c | 6 ++
arch/s390/pci/pci_bus.h | 5 +
arch/x86/kvm/x86.c | 62 ++++++-----
arch/x86/kvm/x86.h | 2 +
drivers/bus/ti-sysc.c | 4 +-
drivers/clk/imx/clk-imx6q.c | 2 +-
drivers/clk/qcom/gdsc.c | 54 ++++++----
drivers/cpufreq/armada-37xx-cpufreq.c | 6 +-
drivers/dma/of-dma.c | 9 +-
drivers/dma/sh/usb-dmac.c | 2 +-
drivers/dma/xilinx/xilinx_dma.c | 12 +++
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 21 +++-
.../drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 4 +-
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 2 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 34 +------
drivers/iommu/intel/pasid.c | 26 ++---
drivers/iommu/intel/pasid.h | 6 ++
drivers/iommu/intel/svm.c | 55 ++--------
drivers/iommu/iommu.c | 3 +
drivers/ipack/carriers/tpci200.c | 60 ++++++-----
drivers/media/usb/zr364xx/zr364xx.c | 77 +++++++++-----
drivers/mmc/host/dw_mmc.c | 6 +-
drivers/mmc/host/mmci_stm32_sdmmc.c | 7 +-
drivers/mmc/host/sdhci-iproc.c | 21 +++-
drivers/mmc/host/sdhci-msm.c | 18 ++++
drivers/mtd/chips/cfi_cmdset_0002.c | 2 +-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 113 ++++++++++++++-------
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 +
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 +-
drivers/net/ethernet/intel/iavf/iavf.h | 1 +
drivers/net/ethernet/intel/iavf/iavf_main.c | 1 +
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 47 ++++++++-
drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c | 5 +-
drivers/net/ethernet/qlogic/qede/qede.h | 1 +
drivers/net/ethernet/qlogic/qede/qede_main.c | 8 ++
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 +-
drivers/net/hamradio/6pack.c | 6 ++
drivers/net/mdio/mdio-mux.c | 36 ++++---
drivers/net/usb/lan78xx.c | 16 ++-
drivers/net/usb/pegasus.c | 108 ++++++++++++++------
drivers/net/usb/r8152.c | 2 +-
drivers/net/virtio_net.c | 76 ++++++++++----
drivers/net/vrf.c | 4 +
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 ++++++++++++++++-
drivers/net/wireless/ath/key.c | 41 +++++---
drivers/pci/quirks.c | 1 +
drivers/ptp/Kconfig | 3 +-
drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +-
drivers/scsi/megaraid/megaraid_mm.c | 21 ++--
drivers/scsi/pm8001/pm8001_sas.c | 32 +++---
drivers/scsi/scsi_scan.c | 3 +-
drivers/scsi/scsi_sysfs.c | 9 +-
drivers/slimbus/messaging.c | 7 +-
drivers/slimbus/qcom-ngd-ctrl.c | 5 +-
drivers/soc/mediatek/mtk-mmsys.c | 4 +-
drivers/spi/spi-mux.c | 8 ++
drivers/usb/core/devio.c | 2 +-
drivers/usb/core/message.c | 6 ++
drivers/vdpa/mlx5/core/mr.c | 9 --
drivers/vhost/vdpa.c | 3 +-
drivers/vhost/vhost.c | 10 +-
drivers/virtio/virtio.c | 1 +
drivers/virtio/virtio_ring.c | 8 ++
fs/btrfs/inode.c | 10 +-
fs/io_uring.c | 16 +--
fs/namespace.c | 6 +-
include/linux/memcontrol.h | 29 +++---
include/linux/soc/mediatek/mtk-mmsys.h | 33 ++++++
include/linux/virtio.h | 1 +
include/net/flow_offload.h | 12 +--
kernel/bpf/verifier.c | 1 +
kernel/trace/trace_events_hist.c | 2 +
mm/vmscan.c | 27 +++--
net/bluetooth/hidp/core.c | 2 +-
net/dccp/dccp.h | 6 +-
net/openvswitch/vport.c | 1 +
net/sched/sch_cake.c | 2 +-
net/xfrm/xfrm_ipcomp.c | 2 +-
sound/pci/hda/hda_generic.c | 10 +-
sound/pci/hda/patch_realtek.c | 12 ++-
sound/pci/hda/patch_via.c | 1 +
sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +-
92 files changed, 965 insertions(+), 448 deletions(-)
Adrian Larumbe (1):
dmaengine: xilinx_dma: Fix read-after-free bug when terminating transfers
Alan Stern (2):
USB: core: Avoid WARNings for 0-length descriptor requests
USB: core: Fix incorrect pipe calculation in do_proc_control()
Andreas Persson (1):
mtd: cfi_cmdset_0002: fix crash when erasing/writing AMD cards
Andy Shevchenko (1):
ptp_pch: Restore dependency on PCI
Arkadiusz Kubalewski (1):
i40e: Fix ATR queue selection
Bing Guo (1):
drm/amd/display: Fix Dynamic bpp issue with 8K30 with Navi 1X
Bjorn Andersson (1):
clk: qcom: gdsc: Ensure regulator init state matches GDSC state
Christophe Kerello (1):
mmc: mmci: stm32: Check when the voltage switch procedure should be done
Dan Carpenter (1):
media: zr364xx: fix memory leaks in probe()
Dave Gerlach (1):
ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
Dinghao Liu (1):
net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
Dong Aisheng (1):
clk: imx6q: fix uart earlycon unwork
Dongliang Mu (2):
ipack: tpci200: fix many double free issues in tpci200_pci_probe
ipack: tpci200: fix memory leak in the tpci200_register
Eli Cohen (1):
vdpa/mlx5: Avoid destroying MR on empty iotlb
Evgeny Novikov (1):
media: zr364xx: propagate errors from zr364xx_start_readpipe()
Frank Wunderlich (1):
iommu: Check if group is NULL before remove device
Harshvardhan Jha (2):
net: xfrm: Fix end of loop tests for list_for_each_entry
scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
Hayes Wang (1):
r8152: fix writing USB_BP2_EN
Ido Schimmel (1):
Revert "flow_offload: action should not be NULL when it is referenced"
Igor Pylypiv (1):
scsi: pm80xx: Fix TMF task completion race condition
Ilya Leoshkevich (1):
bpf: Clear zext_dst of dead insns
Ivan T. Ivanov (1):
net: usb: lan78xx: don't modify phy_device state concurrently
Jakub Kicinski (4):
bnxt: don't lock the tx queue from napi poll
bnxt: disable napi before canceling DIM
bnxt: make sure xmit_more + errors does not miss doorbells
bnxt: count Tx drops
Jaroslav Kysela (1):
ALSA: hda - fix the 'Capture Switch' value change notifications
Jason Wang (1):
virtio-net: use NETIF_F_GRO_HW instead of NETIF_F_LRO
Jeff Layton (1):
fs: warn about impending deprecation of mandatory locks
Jens Axboe (2):
io_uring: fix xa_alloc_cycle() error return value check
io_uring: only assign io_uring_enter() SQPOLL error in actual error case
Johannes Weiner (1):
mm: memcontrol: fix occasional OOMs due to proportional memory.low reclaim
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Kai-Heng Feng (1):
ALSA: hda/realtek: Limit mic boost on HP ProBook 445 G8
Kristin Paget (1):
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9510 laptop
Lahav Schlesinger (1):
vrf: Reset skb conntrack connection on VRF rcv
Liu Yi L (1):
iommu/vt-d: Fix incomplete cache flush in intel_pasid_tear_down_entry()
Lu Baolu (1):
iommu/vt-d: Consolidate duplicate cache invaliation code
Marcin Bachry (1):
PCI: Increase D3 delay for AMD Renoir/Cezanne XHCI
Marek Behún (1):
cpufreq: armada-37xx: forbid cpufreq for 1.2 GHz variant
Michael Chan (2):
bnxt_en: Disable aRFS if running on 212 firmware
bnxt_en: Add missing DMA memory barriers
NeilBrown (1):
btrfs: prevent rename2 from exchanging a subvol with a directory from different parents
Nicolas Saenz Julienne (2):
mmc: sdhci-iproc: Cap min clock frequency on BCM2711
mmc: sdhci-iproc: Set SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN on BCM2711
Niklas Schnelle (1):
s390/pci: fix use after free of zpci_dev
Ole Bjørn Midtbø (1):
Bluetooth: hidp: use correct wait queue when removing ctrl_wait
Parav Pandit (1):
virtio: Protect vqs list access
Pavel Skripkin (2):
media: drivers/media/usb: fix memory leak in zr364xx_probe
net: 6pack: fix slab-out-of-bounds in decode_data
Peter Ujfalusi (1):
dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller is not yet available
Petko Manolov (1):
net: usb: pegasus: Check the return value of get_geristers() and friends;
Petr Vorel (1):
arm64: dts: qcom: msm8992-bullhead: Remove PSCI
Prabhakar Kushwaha (1):
qede: fix crash in rmmod qede while automatic debug collection
Qingqing Zhuo (1):
drm/amd/display: workaround for hard hang on HPD on native DP
Randy Dunlap (1):
dccp: add do-while-0 stubs for dccp_pr_debug macros
Saravana Kannan (2):
net: mdio-mux: Don't ignore memory allocation errors
net: mdio-mux: Handle -EPROBE_DEFER correctly
Sasha Levin (1):
Linux 5.10.61
Shaik Sajida Bhanu (1):
mmc: sdhci-msm: Update the software timeout value for sdhc
Sreekanth Reddy (1):
scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
Srinivas Kandagatla (4):
arm64: dts: qcom: c630: fix correct powerdown pin for WSA881x
slimbus: messaging: start transaction ids from 1 instead of zero
slimbus: messaging: check for valid transaction id
slimbus: ngd: reset dma setup during runtime pm
Steven Rostedt (VMware) (1):
tracing / histogram: Fix NULL pointer dereference on strcmp() on NULL event name
Sudeep Holla (1):
ARM: dts: nomadik: Fix up interrupt controller node names
Sylwester Dziedziuch (1):
iavf: Fix ping is lost after untrusted VF had tried to change MAC
Takashi Iwai (2):
ALSA: hda/via: Apply runtime PM workaround for ASUS B23E
ASoC: intel: atom: Fix breakage for PCM buffer address setup
Toke Høiland-Jørgensen (1):
sch_cake: fix srchost/dsthost hashing mode
Tony Lindgren (1):
bus: ti-sysc: Fix error handling for sysc_check_active_timer()
Uwe Kleine-König (1):
spi: spi-mux: Add module info needed for autoloading
Vincent Whitchurch (1):
mmc: dw_mmc: Fix hang on data CRC error
Wang Hai (1):
ixgbe, xsk: clean up the resources in ixgbe_xsk_pool_enable error path
Wanpeng Li (1):
KVM: X86: Fix warning caused by stale emulation context
Wei Huang (1):
KVM: x86: Factor out x86 instruction emulation with decoding
Xie Yongji (2):
vhost-vdpa: Fix integer overflow in vhost_vdpa_process_iotlb_update()
vhost: Fix the calculation in vhost_overflow()
Xuan Zhuo (1):
virtio-net: support XDP when not more queues
Ye Bin (1):
scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
Yifan Zhang (1):
drm/amdgpu: fix the doorbell missing when in CGPG issue for renoir.
Yongqiang Niu (2):
soc / drm: mediatek: Move DDP component defines into mtk-mmsys.h
drm/mediatek: Fix aal size config
Yu Kuai (1):
dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
jason-jh.lin (1):
drm/mediatek: Add AAL output size configuration
kaixi.fan (1):
ovs: clear skb->tstamp in forwarding path
lijinlin (1):
scsi: core: Fix capacity set to zero after offlinining device
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEE4n5dijQDou9mhzu83qZv95d3LNwFAmEnll0ACgkQ3qZv95d3
LNyAbg//QiFsXXCStPZdxLBlkSEYdBw7Wi5RhrhsRCWwkvkyLsQVHN6yt9hPMAj7
+Yee2H5WjCYK+Hm9g50JMv4p8LK17OqGhs208PlSM0IyFk4cdx01XzR07nJdTd9u
sTSURmN4e44n9kjcupJZaqyIIWWtsxX7yfXBacFUMBQK0LQ4CXuIk7jN09GB36CE
fnzr9maRJodPyoZMi0q6U/8rype12lnj+j/DpgZQLWFGf28gWrWrWtAKUcX62IpM
YnHyhhwslBXEQ7CI0E1OGPRobi5XlkjLJYEQk1xW7ojeBQ2yeFUUTZeVuC/Ahhuh
3AnxGcCNK7okFs9z+dWX+mxIxG9hagbU4/BNueVWnDAGhBhFQA17/EmsmH2lSRQV
Hp1FKwfoTZX6IijOhObSSLaQ5vekHcyv8OVdSxDeG5PnDM9/uJk1bSPvoSo2pPds
QutpI97Avj/7SZ3UhhwG6S6ftYdT73PBlBlXq5gAQrFQYrgboDNyS6RgBPcHPjvo
AiPzwbbpLXl9O82DU+M6JFX33aIITFbr5lnLRO9+qQEAF2pGqZW56MZyRKQiQ+sL
BhNzTyHCDHTxwHB0JuK0ruYH7G8va6YfI9+mZdMfVyDexzu8N+WuH2KbUtZS2xmc
woGJnBnljV1thrcyNWdCfspemPziI5i1zzfPNXsAofPiOR8JP5o=
=p96D
-----END PGP SIGNATURE-----
^ permalink raw reply [relevance 3%]
* [PATCH 4.14 38/64] ath9k: Postpone key cache entry deletion for TXQ frames reference it
2021-08-24 17:03 3% [PATCH 4.14 00/64] 4.14.245-rc1 review Sasha Levin
@ 2021-08-24 17:04 5% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2021-08-24 17:04 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Jouni Malinen, Kalle Valo, Pali Rohár, Greg Kroah-Hartman
From: Jouni Malinen <jouni@codeaurora.org>
commit ca2848022c12789685d3fab3227df02b863f9696 upstream.
Do not delete a key cache entry that is still being referenced by
pending frames in TXQs. This avoids reuse of the key cache entry while a
frame might still be transmitted using it.
To avoid having to do any additional operations during the main TX path
operations, track pending key cache entries in a new bitmap and check
whether any pending entries can be deleted before every new key
add/remove operation. Also clear any remaining entries when stopping the
interface.
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20201214172118.18100-6-jouni@codeaurora.org
Cc: Pali Rohár <pali@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 87 ++++++++++++++++++++++++++-
2 files changed, 87 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 4ac70827d142..ea008046c1f8 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -816,6 +816,7 @@ struct ath_hw {
struct ath9k_pacal_info pacal_info;
struct ar5416Stats stats;
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+ DECLARE_BITMAP(pending_del_keymap, ATH_KEYMAX);
enum ath9k_int imask;
u32 imrs2_reg;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6c635edc7596..173960682ea0 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -822,12 +822,80 @@ exit:
ieee80211_free_txskb(hw, skb);
}
+static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
+{
+ struct ath_buf *bf;
+ struct ieee80211_tx_info *txinfo;
+ struct ath_frame_info *fi;
+
+ list_for_each_entry(bf, txq_list, list) {
+ if (bf->bf_state.stale || !bf->bf_mpdu)
+ continue;
+
+ txinfo = IEEE80211_SKB_CB(bf->bf_mpdu);
+ fi = (struct ath_frame_info *)&txinfo->rate_driver_data[0];
+ if (fi->keyix == keyix)
+ return true;
+ }
+
+ return false;
+}
+
+static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ int i;
+ struct ath_txq *txq;
+ bool key_in_use = false;
+
+ for (i = 0; !key_in_use && i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+ txq = &sc->tx.txq[i];
+ if (!txq->axq_depth)
+ continue;
+ if (!ath9k_hw_numtxpending(ah, txq->axq_qnum))
+ continue;
+
+ ath_txq_lock(sc, txq);
+ key_in_use = ath9k_txq_list_has_key(&txq->axq_q, keyix);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ int idx = txq->txq_tailidx;
+
+ while (!key_in_use &&
+ !list_empty(&txq->txq_fifo[idx])) {
+ key_in_use = ath9k_txq_list_has_key(
+ &txq->txq_fifo[idx], keyix);
+ INCR(idx, ATH_TXFIFO_DEPTH);
+ }
+ }
+ ath_txq_unlock(sc, txq);
+ }
+
+ return key_in_use;
+}
+
+static void ath9k_pending_key_del(struct ath_softc *sc, u8 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!test_bit(keyix, ah->pending_del_keymap) ||
+ ath9k_txq_has_key(sc, keyix))
+ return;
+
+ /* No more TXQ frames point to this key cache entry, so delete it. */
+ clear_bit(keyix, ah->pending_del_keymap);
+ ath_key_delete(common, keyix);
+}
+
static void ath9k_stop(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
bool prev_idle;
+ int i;
ath9k_deinit_channel_context(sc);
@@ -895,6 +963,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
spin_unlock_bh(&sc->sc_pcu_lock);
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
/* Clear key cache entries explicitly to get rid of any potentially
* remaining keys.
*/
@@ -1711,6 +1782,12 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
if (sta)
an = (struct ath_node *)sta->drv_priv;
+ /* Delete pending key cache entries if no more frames are pointing to
+ * them in TXQs.
+ */
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
switch (cmd) {
case SET_KEY:
if (sta)
@@ -1740,7 +1817,15 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
}
break;
case DISABLE_KEY:
- ath_key_delete(common, key->hw_key_idx);
+ if (ath9k_txq_has_key(sc, key->hw_key_idx)) {
+ /* Delay key cache entry deletion until there are no
+ * remaining TXQ frames pointing to this entry.
+ */
+ set_bit(key->hw_key_idx, sc->sc_ah->pending_del_keymap);
+ ath_hw_keysetmac(common, key->hw_key_idx, NULL);
+ } else {
+ ath_key_delete(common, key->hw_key_idx);
+ }
if (an) {
for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
if (an->key_idx[i] != key->hw_key_idx)
--
2.30.2
^ permalink raw reply related [relevance 5%]
* [PATCH 4.14 00/64] 4.14.245-rc1 review
@ 2021-08-24 17:03 3% Sasha Levin
2021-08-24 17:04 5% ` [PATCH 4.14 38/64] ath9k: Postpone key cache entry deletion for TXQ frames reference it Sasha Levin
0 siblings, 1 reply; 200+ results
From: Sasha Levin @ 2021-08-24 17:03 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Sasha Levin, torvalds, akpm, linux, shuah, patches, lkft-triage, pavel
This is the start of the stable review cycle for the 4.14.245 release.
There are 64 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu 26 Aug 2021 05:04:55 PM UTC.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/patch/?id=linux-4.14.y&id2=v4.14.244
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.14.y
and the diffstat can be found below.
Thanks,
Sasha
-------------
Pseudo-Shortlog of commits:
Andy Shevchenko (1):
ptp_pch: Restore dependency on PCI
Babu Moger (1):
x86/resctrl: Fix default monitoring groups reporting
Chris Lesiak (1):
iio: humidity: hdc100x: Add margin to the conversion time
Colin Ian King (1):
iio: adc: Fix incorrect exit of for-loop
DENG Qingfang (1):
net: dsa: mt7530: add the missing RxUnicast MIB counter
Dan Williams (1):
ACPI: NFIT: Fix support for virtual SPA ranges
Dave Gerlach (1):
ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
Dinghao Liu (1):
net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
Dongliang Mu (1):
ipack: tpci200: fix many double free issues in tpci200_pci_probe
Greg Kroah-Hartman (1):
i2c: dev: zero out array used for i2c reads from userspace
Harshvardhan Jha (1):
scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
Ivan T. Ivanov (1):
net: usb: lan78xx: don't modify phy_device state concurrently
Jakub Kicinski (1):
bnxt: don't lock the tx queue from napi poll
Jaroslav Kysela (1):
ALSA: hda - fix the 'Capture Switch' value change notifications
Jeff Layton (2):
locks: print a warning when mount fails due to lack of "mand" support
fs: warn about impending deprecation of mandatory locks
Johannes Berg (1):
mac80211: drop data frames without key on encrypted links
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Longpeng(Mike) (1):
vsock/virtio: avoid potential deadlock when vsock device remove
Maxim Levitsky (2):
KVM: nSVM: always intercept VMLOAD/VMSAVE when nested (CVE-2021-3656)
KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl
(CVE-2021-3653)
Maximilian Heyne (1):
xen/events: Fix race in set_evtchn_to_irq
Nathan Chancellor (1):
vmlinux.lds.h: Handle clang's module.{c,d}tor sections
Neal Cardwell (1):
tcp_bbr: fix u32 wrap bug in round logic if bbr_init() called after 2B
packets
NeilBrown (1):
btrfs: prevent rename2 from exchanging a subvol with a directory from
different parents
Ole Bjørn Midtbø (1):
Bluetooth: hidp: use correct wait queue when removing ctrl_wait
Pali Rohár (1):
ppp: Fix generating ifname when empty IFLA_IFNAME is specified
Pavel Skripkin (1):
net: 6pack: fix slab-out-of-bounds in decode_data
Peter Ujfalusi (1):
dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller
is not yet available
Pu Lehui (1):
powerpc/kprobes: Fix kprobe Oops happens in booke
Randy Dunlap (2):
x86/tools: Fix objdump version check again
dccp: add do-while-0 stubs for dccp_pr_debug macros
Richard Fitzgerald (4):
ASoC: cs42l42: Correct definition of ADC Volume control
ASoC: cs42l42: Don't allow SND_SOC_DAIFMT_LEFT_J
ASoC: cs42l42: Fix inversion of ADC Notch Switch control
ASoC: cs42l42: Remove duplicate control for WNF filter frequency
Roi Dayan (1):
psample: Add a fwd declaration for skbuff
Saravana Kannan (2):
net: mdio-mux: Don't ignore memory allocation errors
net: mdio-mux: Handle -EPROBE_DEFER correctly
Sasha Levin (1):
Linux 4.14.245-rc1
Sergey Marinkevich (1):
netfilter: nft_exthdr: fix endianness of tcp option cast
Sreekanth Reddy (1):
scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
Sudeep Holla (1):
ARM: dts: nomadik: Fix up interrupt controller node names
Takashi Iwai (2):
ASoC: intel: atom: Fix reference to PCM buffer address
ASoC: intel: atom: Fix breakage for PCM buffer address setup
Takeshi Misawa (1):
net: Fix memory leak in ieee802154_raw_deliver
Thomas Gleixner (9):
PCI/MSI: Enable and mask MSI-X early
PCI/MSI: Do not set invalid bits in MSI mask
PCI/MSI: Correct misleading comments
PCI/MSI: Use msi_mask_irq() in pci_msi_shutdown()
PCI/MSI: Protect msi_desc::masked for multi-MSI
PCI/MSI: Mask all unused MSI-X entries
PCI/MSI: Enforce that MSI-X table entry is masked for update
PCI/MSI: Enforce MSI[X] entry updates to be visible
x86/fpu: Make init_fpstate correct with optimized XSAVE
Vincent Whitchurch (1):
mmc: dw_mmc: Fix hang on data CRC error
Xie Yongji (1):
vhost: Fix the calculation in vhost_overflow()
Yang Yingliang (1):
net: bridge: fix memleak in br_add_if()
Ye Bin (1):
scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
Yu Kuai (1):
dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
.../filesystems/mandatory-locking.txt | 10 ++
Makefile | 4 +-
arch/arm/boot/dts/am43x-epos-evm.dts | 2 +-
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi | 4 +-
arch/powerpc/kernel/kprobes.c | 3 +-
arch/x86/include/asm/fpu/internal.h | 30 ++---
arch/x86/include/asm/svm.h | 2 +
arch/x86/kernel/cpu/intel_rdt_monitor.c | 27 ++--
arch/x86/kernel/fpu/xstate.c | 38 +++++-
arch/x86/kvm/svm.c | 18 ++-
arch/x86/tools/chkobjdump.awk | 1 +
drivers/acpi/nfit/core.c | 3 +
drivers/base/core.c | 1 +
drivers/dma/of-dma.c | 9 +-
drivers/dma/sh/usb-dmac.c | 2 +-
drivers/i2c/i2c-dev.c | 5 +-
drivers/iio/adc/palmas_gpadc.c | 4 +-
drivers/iio/humidity/hdc100x.c | 6 +-
drivers/ipack/carriers/tpci200.c | 36 +++---
drivers/mmc/host/dw_mmc.c | 6 +-
drivers/net/dsa/mt7530.c | 1 +
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 54 ++++----
.../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 +-
drivers/net/hamradio/6pack.c | 6 +
drivers/net/phy/mdio-mux.c | 36 ++++--
drivers/net/ppp/ppp_generic.c | 2 +-
drivers/net/usb/lan78xx.c | 16 ++-
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 +++++++++++++-
drivers/net/wireless/ath/key.c | 41 +++---
drivers/pci/msi.c | 120 ++++++++++++------
drivers/ptp/Kconfig | 3 +-
drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +-
drivers/scsi/megaraid/megaraid_mm.c | 21 ++-
drivers/scsi/scsi_scan.c | 3 +-
drivers/vhost/vhost.c | 10 +-
drivers/xen/events/events_base.c | 20 ++-
fs/btrfs/inode.c | 10 +-
fs/namespace.c | 15 ++-
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/device.h | 1 +
include/linux/msi.h | 2 +-
include/net/psample.h | 2 +
net/bluetooth/hidp/core.c | 2 +-
net/bridge/br_if.c | 2 +
net/dccp/dccp.h | 6 +-
net/ieee802154/socket.c | 7 +-
net/ipv4/tcp_bbr.c | 2 +-
net/mac80211/debugfs_sta.c | 1 +
net/mac80211/key.c | 1 +
net/mac80211/sta_info.h | 1 +
net/mac80211/tx.c | 12 +-
net/netfilter/nft_exthdr.c | 8 +-
net/vmw_vsock/virtio_transport.c | 7 +-
sound/pci/hda/hda_generic.c | 10 +-
sound/soc/codecs/cs42l42.c | 18 +--
sound/soc/intel/atom/sst-mfld-platform-pcm.c | 3 +-
60 files changed, 520 insertions(+), 246 deletions(-)
--
2.30.2
^ permalink raw reply [relevance 3%]
* [PATCH 4.19 49/84] ath9k: Postpone key cache entry deletion for TXQ frames reference it
2021-08-24 17:01 3% [PATCH 4.19 00/84] 4.19.205-rc1 review Sasha Levin
@ 2021-08-24 17:02 5% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2021-08-24 17:02 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Jouni Malinen, Kalle Valo, Pali Rohár, Greg Kroah-Hartman
From: Jouni Malinen <jouni@codeaurora.org>
commit ca2848022c12789685d3fab3227df02b863f9696 upstream.
Do not delete a key cache entry that is still being referenced by
pending frames in TXQs. This avoids reuse of the key cache entry while a
frame might still be transmitted using it.
To avoid having to do any additional operations during the main TX path
operations, track pending key cache entries in a new bitmap and check
whether any pending entries can be deleted before every new key
add/remove operation. Also clear any remaining entries when stopping the
interface.
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20201214172118.18100-6-jouni@codeaurora.org
Cc: Pali Rohár <pali@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 87 ++++++++++++++++++++++++++-
2 files changed, 87 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 68956cdc8c9a..4b5687b6c0c9 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -818,6 +818,7 @@ struct ath_hw {
struct ath9k_pacal_info pacal_info;
struct ar5416Stats stats;
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+ DECLARE_BITMAP(pending_del_keymap, ATH_KEYMAX);
enum ath9k_int imask;
u32 imrs2_reg;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 95cc581e3761..a0097bebcba3 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -823,12 +823,80 @@ exit:
ieee80211_free_txskb(hw, skb);
}
+static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
+{
+ struct ath_buf *bf;
+ struct ieee80211_tx_info *txinfo;
+ struct ath_frame_info *fi;
+
+ list_for_each_entry(bf, txq_list, list) {
+ if (bf->bf_state.stale || !bf->bf_mpdu)
+ continue;
+
+ txinfo = IEEE80211_SKB_CB(bf->bf_mpdu);
+ fi = (struct ath_frame_info *)&txinfo->rate_driver_data[0];
+ if (fi->keyix == keyix)
+ return true;
+ }
+
+ return false;
+}
+
+static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ int i;
+ struct ath_txq *txq;
+ bool key_in_use = false;
+
+ for (i = 0; !key_in_use && i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+ txq = &sc->tx.txq[i];
+ if (!txq->axq_depth)
+ continue;
+ if (!ath9k_hw_numtxpending(ah, txq->axq_qnum))
+ continue;
+
+ ath_txq_lock(sc, txq);
+ key_in_use = ath9k_txq_list_has_key(&txq->axq_q, keyix);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ int idx = txq->txq_tailidx;
+
+ while (!key_in_use &&
+ !list_empty(&txq->txq_fifo[idx])) {
+ key_in_use = ath9k_txq_list_has_key(
+ &txq->txq_fifo[idx], keyix);
+ INCR(idx, ATH_TXFIFO_DEPTH);
+ }
+ }
+ ath_txq_unlock(sc, txq);
+ }
+
+ return key_in_use;
+}
+
+static void ath9k_pending_key_del(struct ath_softc *sc, u8 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!test_bit(keyix, ah->pending_del_keymap) ||
+ ath9k_txq_has_key(sc, keyix))
+ return;
+
+ /* No more TXQ frames point to this key cache entry, so delete it. */
+ clear_bit(keyix, ah->pending_del_keymap);
+ ath_key_delete(common, keyix);
+}
+
static void ath9k_stop(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
bool prev_idle;
+ int i;
ath9k_deinit_channel_context(sc);
@@ -896,6 +964,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
spin_unlock_bh(&sc->sc_pcu_lock);
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
/* Clear key cache entries explicitly to get rid of any potentially
* remaining keys.
*/
@@ -1712,6 +1783,12 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
if (sta)
an = (struct ath_node *)sta->drv_priv;
+ /* Delete pending key cache entries if no more frames are pointing to
+ * them in TXQs.
+ */
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
switch (cmd) {
case SET_KEY:
if (sta)
@@ -1741,7 +1818,15 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
}
break;
case DISABLE_KEY:
- ath_key_delete(common, key->hw_key_idx);
+ if (ath9k_txq_has_key(sc, key->hw_key_idx)) {
+ /* Delay key cache entry deletion until there are no
+ * remaining TXQ frames pointing to this entry.
+ */
+ set_bit(key->hw_key_idx, sc->sc_ah->pending_del_keymap);
+ ath_hw_keysetmac(common, key->hw_key_idx, NULL);
+ } else {
+ ath_key_delete(common, key->hw_key_idx);
+ }
if (an) {
for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
if (an->key_idx[i] != key->hw_key_idx)
--
2.30.2
^ permalink raw reply related [relevance 5%]
* [PATCH 4.19 00/84] 4.19.205-rc1 review
@ 2021-08-24 17:01 3% Sasha Levin
2021-08-24 17:02 5% ` [PATCH 4.19 49/84] ath9k: Postpone key cache entry deletion for TXQ frames reference it Sasha Levin
0 siblings, 1 reply; 200+ results
From: Sasha Levin @ 2021-08-24 17:01 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Sasha Levin, torvalds, akpm, linux, shuah, patches, lkft-triage, pavel
This is the start of the stable review cycle for the 4.19.205 release.
There are 84 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu 26 Aug 2021 05:02:47 PM UTC.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/patch/?id=linux-4.19.y&id2=v4.19.204
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.19.y
and the diffstat can be found below.
Thanks,
Sasha
-------------
Pseudo-Shortlog of commits:
Adrian Larumbe (1):
dmaengine: xilinx_dma: Fix read-after-free bug when terminating
transfers
Andy Shevchenko (1):
ptp_pch: Restore dependency on PCI
Babu Moger (1):
x86/resctrl: Fix default monitoring groups reporting
Bixuan Cui (1):
genirq/msi: Ensure deactivation on teardown
Chris Lesiak (1):
iio: humidity: hdc100x: Add margin to the conversion time
Colin Ian King (1):
iio: adc: Fix incorrect exit of for-loop
DENG Qingfang (1):
net: dsa: mt7530: add the missing RxUnicast MIB counter
Dan Williams (1):
ACPI: NFIT: Fix support for virtual SPA ranges
Dave Gerlach (1):
ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
Dinghao Liu (1):
net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
Dongliang Mu (4):
ieee802154: hwsim: fix GPF in hwsim_set_edge_lqi
ieee802154: hwsim: fix GPF in hwsim_new_edge_nl
ipack: tpci200: fix many double free issues in tpci200_pci_probe
ipack: tpci200: fix memory leak in the tpci200_register
Eric Dumazet (2):
net: igmp: fix data-race in igmp_ifc_timer_expire()
net: igmp: increase size of mr_ifc_count
Greg Kroah-Hartman (1):
i2c: dev: zero out array used for i2c reads from userspace
Harshvardhan Jha (1):
scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
Ivan T. Ivanov (1):
net: usb: lan78xx: don't modify phy_device state concurrently
Jakub Kicinski (2):
bnxt: don't lock the tx queue from napi poll
bnxt: disable napi before canceling DIM
Jaroslav Kysela (1):
ALSA: hda - fix the 'Capture Switch' value change notifications
Jeff Layton (2):
locks: print a warning when mount fails due to lack of "mand" support
fs: warn about impending deprecation of mandatory locks
Johannes Berg (1):
mac80211: drop data frames without key on encrypted links
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Longpeng(Mike) (1):
vsock/virtio: avoid potential deadlock when vsock device remove
Marcin Bachry (1):
PCI: Increase D3 delay for AMD Renoir/Cezanne XHCI
Marek Behún (1):
cpufreq: armada-37xx: forbid cpufreq for 1.2 GHz variant
Maxim Levitsky (2):
KVM: nSVM: always intercept VMLOAD/VMSAVE when nested (CVE-2021-3656)
KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl
(CVE-2021-3653)
Maximilian Heyne (1):
xen/events: Fix race in set_evtchn_to_irq
Nathan Chancellor (1):
vmlinux.lds.h: Handle clang's module.{c,d}tor sections
Neal Cardwell (1):
tcp_bbr: fix u32 wrap bug in round logic if bbr_init() called after 2B
packets
NeilBrown (1):
btrfs: prevent rename2 from exchanging a subvol with a directory from
different parents
Ole Bjørn Midtbø (1):
Bluetooth: hidp: use correct wait queue when removing ctrl_wait
Pali Rohár (1):
ppp: Fix generating ifname when empty IFLA_IFNAME is specified
Pavel Skripkin (1):
net: 6pack: fix slab-out-of-bounds in decode_data
Peter Ujfalusi (1):
dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller
is not yet available
Pu Lehui (1):
powerpc/kprobes: Fix kprobe Oops happens in booke
Randy Dunlap (2):
x86/tools: Fix objdump version check again
dccp: add do-while-0 stubs for dccp_pr_debug macros
Richard Fitzgerald (5):
ASoC: cs42l42: Correct definition of ADC Volume control
ASoC: cs42l42: Don't allow SND_SOC_DAIFMT_LEFT_J
ASoC: cs42l42: Fix inversion of ADC Notch Switch control
ASoC: cs42l42: Remove duplicate control for WNF filter frequency
ASoC: cs42l42: Fix LRCLK frame start edge
Roi Dayan (1):
psample: Add a fwd declaration for skbuff
Saeed Mirzamohammadi (1):
iommu/vt-d: Fix agaw for a supported 48 bit guest address width
Saravana Kannan (2):
net: mdio-mux: Don't ignore memory allocation errors
net: mdio-mux: Handle -EPROBE_DEFER correctly
Sasha Levin (1):
Linux 4.19.205-rc1
Sergey Marinkevich (1):
netfilter: nft_exthdr: fix endianness of tcp option cast
Sreekanth Reddy (1):
scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
Srinivas Kandagatla (3):
slimbus: messaging: start transaction ids from 1 instead of zero
slimbus: messaging: check for valid transaction id
slimbus: ngd: reset dma setup during runtime pm
Steven Rostedt (VMware) (1):
tracing / histogram: Fix NULL pointer dereference on strcmp() on NULL
event name
Sudeep Holla (1):
ARM: dts: nomadik: Fix up interrupt controller node names
Takashi Iwai (2):
ASoC: intel: atom: Fix reference to PCM buffer address
ASoC: intel: atom: Fix breakage for PCM buffer address setup
Takeshi Misawa (1):
net: Fix memory leak in ieee802154_raw_deliver
Thomas Gleixner (12):
genirq: Provide IRQCHIP_AFFINITY_PRE_STARTUP
x86/msi: Force affinity setup before startup
x86/ioapic: Force affinity setup before startup
PCI/MSI: Enable and mask MSI-X early
PCI/MSI: Do not set invalid bits in MSI mask
PCI/MSI: Correct misleading comments
PCI/MSI: Use msi_mask_irq() in pci_msi_shutdown()
PCI/MSI: Protect msi_desc::masked for multi-MSI
PCI/MSI: Mask all unused MSI-X entries
PCI/MSI: Enforce that MSI-X table entry is masked for update
PCI/MSI: Enforce MSI[X] entry updates to be visible
x86/fpu: Make init_fpstate correct with optimized XSAVE
Vincent Whitchurch (1):
mmc: dw_mmc: Fix hang on data CRC error
Vladimir Oltean (1):
net: dsa: lan9303: fix broken backpressure in .port_fdb_dump
Xie Yongji (1):
vhost: Fix the calculation in vhost_overflow()
Yang Yingliang (1):
net: bridge: fix memleak in br_add_if()
Ye Bin (1):
scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
Yu Kuai (1):
dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
.../filesystems/mandatory-locking.txt | 10 ++
Makefile | 4 +-
arch/arm/boot/dts/am43x-epos-evm.dts | 2 +-
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi | 4 +-
arch/powerpc/kernel/kprobes.c | 3 +-
arch/x86/include/asm/fpu/internal.h | 30 ++---
arch/x86/include/asm/svm.h | 2 +
arch/x86/kernel/apic/io_apic.c | 6 +-
arch/x86/kernel/apic/msi.c | 13 +-
arch/x86/kernel/cpu/intel_rdt_monitor.c | 27 ++--
arch/x86/kernel/fpu/xstate.c | 38 +++++-
arch/x86/kvm/svm.c | 18 ++-
arch/x86/tools/chkobjdump.awk | 1 +
drivers/acpi/nfit/core.c | 3 +
drivers/base/core.c | 1 +
drivers/cpufreq/armada-37xx-cpufreq.c | 6 +-
drivers/dma/of-dma.c | 9 +-
drivers/dma/sh/usb-dmac.c | 2 +-
drivers/dma/xilinx/xilinx_dma.c | 12 ++
drivers/i2c/i2c-dev.c | 5 +-
drivers/iio/adc/palmas_gpadc.c | 4 +-
drivers/iio/humidity/hdc100x.c | 6 +-
drivers/iommu/intel-iommu.c | 7 +-
drivers/ipack/carriers/tpci200.c | 60 +++++----
drivers/mmc/host/dw_mmc.c | 6 +-
drivers/net/dsa/lan9303-core.c | 34 ++---
drivers/net/dsa/mt7530.c | 1 +
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 57 +++++----
.../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 +-
drivers/net/hamradio/6pack.c | 6 +
drivers/net/ieee802154/mac802154_hwsim.c | 6 +-
drivers/net/phy/mdio-mux.c | 36 ++++--
drivers/net/ppp/ppp_generic.c | 2 +-
drivers/net/usb/lan78xx.c | 16 ++-
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 +++++++++++++-
drivers/net/wireless/ath/key.c | 41 +++---
drivers/pci/msi.c | 120 ++++++++++++------
drivers/pci/quirks.c | 1 +
drivers/ptp/Kconfig | 3 +-
drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +-
drivers/scsi/megaraid/megaraid_mm.c | 21 ++-
drivers/scsi/scsi_scan.c | 3 +-
drivers/slimbus/messaging.c | 7 +-
drivers/slimbus/qcom-ngd-ctrl.c | 5 +-
drivers/vhost/vhost.c | 10 +-
drivers/xen/events/events_base.c | 20 ++-
fs/btrfs/inode.c | 10 +-
fs/namespace.c | 15 ++-
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/device.h | 1 +
include/linux/inetdevice.h | 2 +-
include/linux/irq.h | 2 +
include/linux/msi.h | 2 +-
include/net/psample.h | 2 +
kernel/irq/chip.c | 5 +-
kernel/irq/msi.c | 13 +-
kernel/trace/trace_events_hist.c | 2 +
net/bluetooth/hidp/core.c | 2 +-
net/bridge/br_if.c | 2 +
net/dccp/dccp.h | 6 +-
net/ieee802154/socket.c | 7 +-
net/ipv4/igmp.c | 21 ++-
net/ipv4/tcp_bbr.c | 2 +-
net/mac80211/debugfs_sta.c | 1 +
net/mac80211/key.c | 1 +
net/mac80211/sta_info.h | 1 +
net/mac80211/tx.c | 12 +-
net/netfilter/nft_exthdr.c | 8 +-
net/vmw_vsock/virtio_transport.c | 7 +-
sound/pci/hda/hda_generic.c | 10 +-
sound/soc/codecs/cs42l42.c | 39 +++---
sound/soc/intel/atom/sst-mfld-platform-pcm.c | 3 +-
76 files changed, 643 insertions(+), 313 deletions(-)
--
2.30.2
^ permalink raw reply [relevance 3%]
* [PATCH 5.4 07/61] ath9k: Postpone key cache entry deletion for TXQ frames reference it
2021-08-24 17:00 3% [PATCH 5.4 00/61] 5.4.143-rc1 review Sasha Levin
@ 2021-08-24 17:00 5% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2021-08-24 17:00 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Jouni Malinen, Kalle Valo, Pali Rohár, Greg Kroah-Hartman
From: Jouni Malinen <jouni@codeaurora.org>
commit ca2848022c12789685d3fab3227df02b863f9696 upstream.
Do not delete a key cache entry that is still being referenced by
pending frames in TXQs. This avoids reuse of the key cache entry while a
frame might still be transmitted using it.
To avoid having to do any additional operations during the main TX path
operations, track pending key cache entries in a new bitmap and check
whether any pending entries can be deleted before every new key
add/remove operation. Also clear any remaining entries when stopping the
interface.
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20201214172118.18100-6-jouni@codeaurora.org
Cc: Pali Rohár <pali@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 87 ++++++++++++++++++++++++++-
2 files changed, 87 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 2e4489700a85..2842ca205a0a 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -819,6 +819,7 @@ struct ath_hw {
struct ath9k_pacal_info pacal_info;
struct ar5416Stats stats;
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+ DECLARE_BITMAP(pending_del_keymap, ATH_KEYMAX);
enum ath9k_int imask;
u32 imrs2_reg;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index c08a7202dca2..28ccdcb197de 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -823,12 +823,80 @@ exit:
ieee80211_free_txskb(hw, skb);
}
+static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
+{
+ struct ath_buf *bf;
+ struct ieee80211_tx_info *txinfo;
+ struct ath_frame_info *fi;
+
+ list_for_each_entry(bf, txq_list, list) {
+ if (bf->bf_state.stale || !bf->bf_mpdu)
+ continue;
+
+ txinfo = IEEE80211_SKB_CB(bf->bf_mpdu);
+ fi = (struct ath_frame_info *)&txinfo->rate_driver_data[0];
+ if (fi->keyix == keyix)
+ return true;
+ }
+
+ return false;
+}
+
+static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ int i;
+ struct ath_txq *txq;
+ bool key_in_use = false;
+
+ for (i = 0; !key_in_use && i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+ txq = &sc->tx.txq[i];
+ if (!txq->axq_depth)
+ continue;
+ if (!ath9k_hw_numtxpending(ah, txq->axq_qnum))
+ continue;
+
+ ath_txq_lock(sc, txq);
+ key_in_use = ath9k_txq_list_has_key(&txq->axq_q, keyix);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ int idx = txq->txq_tailidx;
+
+ while (!key_in_use &&
+ !list_empty(&txq->txq_fifo[idx])) {
+ key_in_use = ath9k_txq_list_has_key(
+ &txq->txq_fifo[idx], keyix);
+ INCR(idx, ATH_TXFIFO_DEPTH);
+ }
+ }
+ ath_txq_unlock(sc, txq);
+ }
+
+ return key_in_use;
+}
+
+static void ath9k_pending_key_del(struct ath_softc *sc, u8 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!test_bit(keyix, ah->pending_del_keymap) ||
+ ath9k_txq_has_key(sc, keyix))
+ return;
+
+ /* No more TXQ frames point to this key cache entry, so delete it. */
+ clear_bit(keyix, ah->pending_del_keymap);
+ ath_key_delete(common, keyix);
+}
+
static void ath9k_stop(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
bool prev_idle;
+ int i;
ath9k_deinit_channel_context(sc);
@@ -896,6 +964,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
spin_unlock_bh(&sc->sc_pcu_lock);
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
/* Clear key cache entries explicitly to get rid of any potentially
* remaining keys.
*/
@@ -1712,6 +1783,12 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
if (sta)
an = (struct ath_node *)sta->drv_priv;
+ /* Delete pending key cache entries if no more frames are pointing to
+ * them in TXQs.
+ */
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
switch (cmd) {
case SET_KEY:
if (sta)
@@ -1741,7 +1818,15 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
}
break;
case DISABLE_KEY:
- ath_key_delete(common, key->hw_key_idx);
+ if (ath9k_txq_has_key(sc, key->hw_key_idx)) {
+ /* Delay key cache entry deletion until there are no
+ * remaining TXQ frames pointing to this entry.
+ */
+ set_bit(key->hw_key_idx, sc->sc_ah->pending_del_keymap);
+ ath_hw_keysetmac(common, key->hw_key_idx, NULL);
+ } else {
+ ath_key_delete(common, key->hw_key_idx);
+ }
if (an) {
for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
if (an->key_idx[i] != key->hw_key_idx)
--
2.30.2
^ permalink raw reply related [relevance 5%]
* [PATCH 5.4 00/61] 5.4.143-rc1 review
@ 2021-08-24 17:00 3% Sasha Levin
2021-08-24 17:00 5% ` [PATCH 5.4 07/61] ath9k: Postpone key cache entry deletion for TXQ frames reference it Sasha Levin
0 siblings, 1 reply; 200+ results
From: Sasha Levin @ 2021-08-24 17:00 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Sasha Levin, torvalds, akpm, linux, shuah, patches, lkft-triage, pavel
This is the start of the stable review cycle for the 5.4.143 release.
There are 61 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu 26 Aug 2021 05:01:01 PM UTC.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/patch/?id=linux-5.4.y&id2=v5.4.142
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
and the diffstat can be found below.
Thanks,
Sasha
-------------
Pseudo-Shortlog of commits:
Adrian Larumbe (1):
dmaengine: xilinx_dma: Fix read-after-free bug when terminating
transfers
Alan Stern (1):
USB: core: Avoid WARNings for 0-length descriptor requests
Andreas Persson (1):
mtd: cfi_cmdset_0002: fix crash when erasing/writing AMD cards
Andy Shevchenko (1):
ptp_pch: Restore dependency on PCI
Arkadiusz Kubalewski (1):
i40e: Fix ATR queue selection
Bing Guo (1):
drm/amd/display: Fix Dynamic bpp issue with 8K30 with Navi 1X
Dan Carpenter (1):
media: zr364xx: fix memory leaks in probe()
Dave Gerlach (1):
ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
Dinghao Liu (1):
net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
Dongliang Mu (2):
ipack: tpci200: fix many double free issues in tpci200_pci_probe
ipack: tpci200: fix memory leak in the tpci200_register
Evgeny Novikov (1):
media: zr364xx: propagate errors from zr364xx_start_readpipe()
Frank Wunderlich (1):
iommu: Check if group is NULL before remove device
Harshvardhan Jha (1):
scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
Ilya Leoshkevich (1):
bpf: Clear zext_dst of dead insns
Ivan T. Ivanov (1):
net: usb: lan78xx: don't modify phy_device state concurrently
Jakub Kicinski (2):
bnxt: don't lock the tx queue from napi poll
bnxt: disable napi before canceling DIM
Jaroslav Kysela (1):
ALSA: hda - fix the 'Capture Switch' value change notifications
Jason Wang (1):
virtio-net: use NETIF_F_GRO_HW instead of NETIF_F_LRO
Jeff Layton (1):
fs: warn about impending deprecation of mandatory locks
Johannes Weiner (1):
mm: memcontrol: fix occasional OOMs due to proportional memory.low
reclaim
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Lahav Schlesinger (1):
vrf: Reset skb conntrack connection on VRF rcv
Marcin Bachry (1):
PCI: Increase D3 delay for AMD Renoir/Cezanne XHCI
Marek Behún (1):
cpufreq: armada-37xx: forbid cpufreq for 1.2 GHz variant
Michael Chan (1):
bnxt_en: Add missing DMA memory barriers
Murphy Zhou (1):
ovl: add splice file read write helper
NeilBrown (1):
btrfs: prevent rename2 from exchanging a subvol with a directory from
different parents
Ole Bjørn Midtbø (1):
Bluetooth: hidp: use correct wait queue when removing ctrl_wait
Parav Pandit (1):
virtio: Protect vqs list access
Pavel Skripkin (2):
media: drivers/media/usb: fix memory leak in zr364xx_probe
net: 6pack: fix slab-out-of-bounds in decode_data
Peter Ujfalusi (1):
dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller
is not yet available
Randy Dunlap (1):
dccp: add do-while-0 stubs for dccp_pr_debug macros
Ritesh Harjani (1):
ext4: fix EXT4_MAX_LOGICAL_BLOCK macro
Saravana Kannan (2):
net: mdio-mux: Don't ignore memory allocation errors
net: mdio-mux: Handle -EPROBE_DEFER correctly
Sasha Levin (1):
Linux 5.4.143-rc1
Sergey Marinkevich (1):
netfilter: nft_exthdr: fix endianness of tcp option cast
Sreekanth Reddy (1):
scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
Srinivas Kandagatla (3):
slimbus: messaging: start transaction ids from 1 instead of zero
slimbus: messaging: check for valid transaction id
slimbus: ngd: reset dma setup during runtime pm
Steven Rostedt (VMware) (1):
tracing / histogram: Fix NULL pointer dereference on strcmp() on NULL
event name
Sudeep Holla (1):
ARM: dts: nomadik: Fix up interrupt controller node names
Sylwester Dziedziuch (1):
iavf: Fix ping is lost after untrusted VF had tried to change MAC
Takashi Iwai (1):
ASoC: intel: atom: Fix breakage for PCM buffer address setup
Thomas Gleixner (1):
x86/fpu: Make init_fpstate correct with optimized XSAVE
Vincent Whitchurch (1):
mmc: dw_mmc: Fix hang on data CRC error
Xie Yongji (1):
vhost: Fix the calculation in vhost_overflow()
Xuan Zhuo (1):
virtio-net: support XDP when not more queues
Yafang Shao (1):
mm, memcg: avoid stale protection values when cgroup is above
protection
Ye Bin (1):
scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
Yu Kuai (1):
dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
kaixi.fan (1):
ovs: clear skb->tstamp in forwarding path
lijinlin (1):
scsi: core: Fix capacity set to zero after offlinining device
Makefile | 4 +-
arch/arm/boot/dts/am43x-epos-evm.dts | 2 +-
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi | 4 +-
arch/x86/include/asm/fpu/internal.h | 30 ++----
arch/x86/kernel/fpu/xstate.c | 38 +++++++-
drivers/cpufreq/armada-37xx-cpufreq.c | 6 +-
drivers/dma/of-dma.c | 9 +-
drivers/dma/sh/usb-dmac.c | 2 +-
drivers/dma/xilinx/xilinx_dma.c | 12 +++
.../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 2 +-
drivers/iommu/iommu.c | 3 +
drivers/ipack/carriers/tpci200.c | 60 ++++++------
drivers/media/usb/zr364xx/zr364xx.c | 77 ++++++++++-----
drivers/mmc/host/dw_mmc.c | 6 +-
drivers/mtd/chips/cfi_cmdset_0002.c | 2 +-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 69 +++++++++-----
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 +-
drivers/net/ethernet/intel/iavf/iavf.h | 1 +
drivers/net/ethernet/intel/iavf/iavf_main.c | 1 +
.../net/ethernet/intel/iavf/iavf_virtchnl.c | 47 ++++++++-
.../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 +-
drivers/net/hamradio/6pack.c | 6 ++
drivers/net/phy/mdio-mux.c | 36 ++++---
drivers/net/usb/lan78xx.c | 16 +++-
drivers/net/virtio_net.c | 76 +++++++++++----
drivers/net/vrf.c | 4 +
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 ++++++++++++++++++-
drivers/net/wireless/ath/key.c | 41 ++++----
drivers/pci/quirks.c | 1 +
drivers/ptp/Kconfig | 3 +-
drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +-
drivers/scsi/megaraid/megaraid_mm.c | 21 ++--
drivers/scsi/scsi_scan.c | 3 +-
drivers/scsi/scsi_sysfs.c | 9 +-
drivers/slimbus/messaging.c | 7 +-
drivers/slimbus/qcom-ngd-ctrl.c | 5 +-
drivers/usb/core/message.c | 6 ++
drivers/vhost/vhost.c | 10 +-
drivers/virtio/virtio.c | 1 +
drivers/virtio/virtio_ring.c | 8 ++
fs/btrfs/inode.c | 10 +-
fs/ext4/ext4.h | 2 +-
fs/namespace.c | 6 +-
fs/overlayfs/file.c | 47 +++++++++
include/linux/memcontrol.h | 59 ++++++++++--
include/linux/virtio.h | 1 +
kernel/bpf/verifier.c | 1 +
kernel/trace/trace_events_hist.c | 2 +
mm/memcontrol.c | 8 ++
mm/vmscan.c | 26 +++--
net/bluetooth/hidp/core.c | 2 +-
net/dccp/dccp.h | 6 +-
net/netfilter/nft_exthdr.c | 8 +-
net/openvswitch/vport.c | 1 +
sound/pci/hda/hda_generic.c | 10 +-
sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +-
60 files changed, 702 insertions(+), 231 deletions(-)
--
2.30.2
^ permalink raw reply [relevance 3%]
* [PATCH 5.10 00/98] 5.10.61-rc1 review
@ 2021-08-24 16:57 2% Sasha Levin
2021-08-24 16:57 5% ` [PATCH 5.10 05/98] ath9k: Postpone key cache entry deletion for TXQ frames reference it Sasha Levin
0 siblings, 1 reply; 200+ results
From: Sasha Levin @ 2021-08-24 16:57 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Sasha Levin, torvalds, akpm, linux, shuah, patches, lkft-triage, pavel
This is the start of the stable review cycle for the 5.10.61 release.
There are 98 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu 26 Aug 2021 04:58:25 PM UTC.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/patch/?id=linux-5.10.y&id2=v5.10.60
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
Thanks,
Sasha
-------------
Pseudo-Shortlog of commits:
Adrian Larumbe (1):
dmaengine: xilinx_dma: Fix read-after-free bug when terminating
transfers
Alan Stern (2):
USB: core: Avoid WARNings for 0-length descriptor requests
USB: core: Fix incorrect pipe calculation in do_proc_control()
Andreas Persson (1):
mtd: cfi_cmdset_0002: fix crash when erasing/writing AMD cards
Andy Shevchenko (1):
ptp_pch: Restore dependency on PCI
Arkadiusz Kubalewski (1):
i40e: Fix ATR queue selection
Bing Guo (1):
drm/amd/display: Fix Dynamic bpp issue with 8K30 with Navi 1X
Bjorn Andersson (1):
clk: qcom: gdsc: Ensure regulator init state matches GDSC state
Christophe Kerello (1):
mmc: mmci: stm32: Check when the voltage switch procedure should be
done
Dan Carpenter (1):
media: zr364xx: fix memory leaks in probe()
Dave Gerlach (1):
ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
Dinghao Liu (1):
net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
Dong Aisheng (1):
clk: imx6q: fix uart earlycon unwork
Dongliang Mu (2):
ipack: tpci200: fix many double free issues in tpci200_pci_probe
ipack: tpci200: fix memory leak in the tpci200_register
Eli Cohen (1):
vdpa/mlx5: Avoid destroying MR on empty iotlb
Evgeny Novikov (1):
media: zr364xx: propagate errors from zr364xx_start_readpipe()
Frank Wunderlich (1):
iommu: Check if group is NULL before remove device
Harshvardhan Jha (2):
net: xfrm: Fix end of loop tests for list_for_each_entry
scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
Hayes Wang (1):
r8152: fix writing USB_BP2_EN
Ido Schimmel (1):
Revert "flow_offload: action should not be NULL when it is referenced"
Igor Pylypiv (1):
scsi: pm80xx: Fix TMF task completion race condition
Ilya Leoshkevich (1):
bpf: Clear zext_dst of dead insns
Ivan T. Ivanov (1):
net: usb: lan78xx: don't modify phy_device state concurrently
Jakub Kicinski (4):
bnxt: don't lock the tx queue from napi poll
bnxt: disable napi before canceling DIM
bnxt: make sure xmit_more + errors does not miss doorbells
bnxt: count Tx drops
Jaroslav Kysela (1):
ALSA: hda - fix the 'Capture Switch' value change notifications
Jason Wang (1):
virtio-net: use NETIF_F_GRO_HW instead of NETIF_F_LRO
Jeff Layton (1):
fs: warn about impending deprecation of mandatory locks
Jens Axboe (2):
io_uring: fix xa_alloc_cycle() error return value check
io_uring: only assign io_uring_enter() SQPOLL error in actual error
case
Johannes Weiner (1):
mm: memcontrol: fix occasional OOMs due to proportional memory.low
reclaim
Jouni Malinen (5):
ath: Use safer key clearing with key cache entries
ath9k: Clear key cache explicitly on disabling hardware
ath: Export ath_hw_keysetmac()
ath: Modify ath_key_delete() to not need full key entry
ath9k: Postpone key cache entry deletion for TXQ frames reference it
Kai-Heng Feng (1):
ALSA: hda/realtek: Limit mic boost on HP ProBook 445 G8
Kristin Paget (1):
ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9510 laptop
Lahav Schlesinger (1):
vrf: Reset skb conntrack connection on VRF rcv
Linus Torvalds (1):
pipe: avoid unnecessary EPOLLET wakeups under normal loads
Liu Yi L (1):
iommu/vt-d: Fix incomplete cache flush in
intel_pasid_tear_down_entry()
Lu Baolu (1):
iommu/vt-d: Consolidate duplicate cache invaliation code
Marcin Bachry (1):
PCI: Increase D3 delay for AMD Renoir/Cezanne XHCI
Marek Behún (1):
cpufreq: armada-37xx: forbid cpufreq for 1.2 GHz variant
Michael Chan (2):
bnxt_en: Disable aRFS if running on 212 firmware
bnxt_en: Add missing DMA memory barriers
NeilBrown (1):
btrfs: prevent rename2 from exchanging a subvol with a directory from
different parents
Nicolas Saenz Julienne (2):
mmc: sdhci-iproc: Cap min clock frequency on BCM2711
mmc: sdhci-iproc: Set SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN on BCM2711
Niklas Schnelle (1):
s390/pci: fix use after free of zpci_dev
Ole Bjørn Midtbø (1):
Bluetooth: hidp: use correct wait queue when removing ctrl_wait
Parav Pandit (3):
vdpa: Extend routine to accept vdpa device name
vdpa: Define vdpa mgmt device, ops and a netlink interface
virtio: Protect vqs list access
Pavel Skripkin (2):
media: drivers/media/usb: fix memory leak in zr364xx_probe
net: 6pack: fix slab-out-of-bounds in decode_data
Peter Ujfalusi (1):
dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller
is not yet available
Petko Manolov (1):
net: usb: pegasus: Check the return value of get_geristers() and
friends;
Petr Vorel (1):
arm64: dts: qcom: msm8992-bullhead: Remove PSCI
Prabhakar Kushwaha (1):
qede: fix crash in rmmod qede while automatic debug collection
Qingqing Zhuo (1):
drm/amd/display: workaround for hard hang on HPD on native DP
Randy Dunlap (1):
dccp: add do-while-0 stubs for dccp_pr_debug macros
Saravana Kannan (2):
net: mdio-mux: Don't ignore memory allocation errors
net: mdio-mux: Handle -EPROBE_DEFER correctly
Sasha Levin (1):
Linux 5.10.61-rc1
Shaik Sajida Bhanu (1):
mmc: sdhci-msm: Update the software timeout value for sdhc
Sreekanth Reddy (1):
scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
Srinivas Kandagatla (4):
arm64: dts: qcom: c630: fix correct powerdown pin for WSA881x
slimbus: messaging: start transaction ids from 1 instead of zero
slimbus: messaging: check for valid transaction id
slimbus: ngd: reset dma setup during runtime pm
Steven Rostedt (VMware) (1):
tracing / histogram: Fix NULL pointer dereference on strcmp() on NULL
event name
Sudeep Holla (1):
ARM: dts: nomadik: Fix up interrupt controller node names
Sylwester Dziedziuch (1):
iavf: Fix ping is lost after untrusted VF had tried to change MAC
Takashi Iwai (2):
ALSA: hda/via: Apply runtime PM workaround for ASUS B23E
ASoC: intel: atom: Fix breakage for PCM buffer address setup
Toke Høiland-Jørgensen (1):
sch_cake: fix srchost/dsthost hashing mode
Tony Lindgren (1):
bus: ti-sysc: Fix error handling for sysc_check_active_timer()
Uwe Kleine-König (1):
spi: spi-mux: Add module info needed for autoloading
Vincent Whitchurch (1):
mmc: dw_mmc: Fix hang on data CRC error
Wang Hai (1):
ixgbe, xsk: clean up the resources in ixgbe_xsk_pool_enable error path
Wanpeng Li (1):
KVM: X86: Fix warning caused by stale emulation context
Wei Huang (1):
KVM: x86: Factor out x86 instruction emulation with decoding
Xie Yongji (2):
vhost-vdpa: Fix integer overflow in vhost_vdpa_process_iotlb_update()
vhost: Fix the calculation in vhost_overflow()
Xuan Zhuo (1):
virtio-net: support XDP when not more queues
Ye Bin (1):
scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
Yifan Zhang (1):
drm/amdgpu: fix the doorbell missing when in CGPG issue for renoir.
Yongqiang Niu (2):
soc / drm: mediatek: Move DDP component defines into mtk-mmsys.h
drm/mediatek: Fix aal size config
Yu Kuai (1):
dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
jason-jh.lin (1):
drm/mediatek: Add AAL output size configuration
kaixi.fan (1):
ovs: clear skb->tstamp in forwarding path
lijinlin (1):
scsi: core: Fix capacity set to zero after offlinining device
Makefile | 4 +-
arch/arm/boot/dts/am43x-epos-evm.dts | 2 +-
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi | 4 +-
.../dts/qcom/msm8992-bullhead-rev-101.dts | 4 +
.../boot/dts/qcom/sdm850-lenovo-yoga-c630.dts | 4 +-
arch/s390/pci/pci.c | 6 +
arch/s390/pci/pci_bus.h | 5 +
arch/x86/kvm/x86.c | 62 +++--
arch/x86/kvm/x86.h | 2 +
drivers/bus/ti-sysc.c | 4 +-
drivers/clk/imx/clk-imx6q.c | 2 +-
drivers/clk/qcom/gdsc.c | 54 ++--
drivers/cpufreq/armada-37xx-cpufreq.c | 6 +-
drivers/dma/of-dma.c | 9 +-
drivers/dma/sh/usb-dmac.c | 2 +-
drivers/dma/xilinx/xilinx_dma.c | 12 +
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 21 +-
.../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 4 +-
.../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 2 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 34 +--
drivers/iommu/intel/pasid.c | 26 +-
drivers/iommu/intel/pasid.h | 6 +
drivers/iommu/intel/svm.c | 55 +---
drivers/iommu/iommu.c | 3 +
drivers/ipack/carriers/tpci200.c | 60 +++--
drivers/media/usb/zr364xx/zr364xx.c | 77 ++++--
drivers/mmc/host/dw_mmc.c | 6 +-
drivers/mmc/host/mmci_stm32_sdmmc.c | 7 +-
drivers/mmc/host/sdhci-iproc.c | 21 +-
drivers/mmc/host/sdhci-msm.c | 18 ++
drivers/mtd/chips/cfi_cmdset_0002.c | 2 +-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 113 +++++---
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 +
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 +-
drivers/net/ethernet/intel/iavf/iavf.h | 1 +
drivers/net/ethernet/intel/iavf/iavf_main.c | 1 +
.../net/ethernet/intel/iavf/iavf_virtchnl.c | 47 +++-
drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c | 5 +-
drivers/net/ethernet/qlogic/qede/qede.h | 1 +
drivers/net/ethernet/qlogic/qede/qede_main.c | 8 +
.../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 +-
drivers/net/hamradio/6pack.c | 6 +
drivers/net/mdio/mdio-mux.c | 36 ++-
drivers/net/usb/lan78xx.c | 16 +-
drivers/net/usb/pegasus.c | 108 +++++---
drivers/net/usb/r8152.c | 2 +-
drivers/net/virtio_net.c | 76 ++++--
drivers/net/vrf.c | 4 +
drivers/net/wireless/ath/ath.h | 3 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +-
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 95 ++++++-
drivers/net/wireless/ath/key.c | 41 +--
drivers/pci/quirks.c | 1 +
drivers/ptp/Kconfig | 3 +-
drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +-
drivers/scsi/megaraid/megaraid_mm.c | 21 +-
drivers/scsi/pm8001/pm8001_sas.c | 32 ++-
drivers/scsi/scsi_scan.c | 3 +-
drivers/scsi/scsi_sysfs.c | 9 +-
drivers/slimbus/messaging.c | 7 +-
drivers/slimbus/qcom-ngd-ctrl.c | 5 +-
drivers/soc/mediatek/mtk-mmsys.c | 4 +-
drivers/spi/spi-mux.c | 8 +
drivers/usb/core/devio.c | 2 +-
drivers/usb/core/message.c | 6 +
drivers/vdpa/Kconfig | 1 +
drivers/vdpa/ifcvf/ifcvf_main.c | 2 +-
drivers/vdpa/mlx5/core/mr.c | 9 -
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
drivers/vdpa/vdpa.c | 249 +++++++++++++++++-
drivers/vdpa/vdpa_sim/vdpa_sim.c | 2 +-
drivers/vhost/vdpa.c | 3 +-
drivers/vhost/vhost.c | 10 +-
drivers/virtio/virtio.c | 1 +
drivers/virtio/virtio_ring.c | 8 +
fs/btrfs/inode.c | 10 +-
fs/io_uring.c | 16 +-
fs/namespace.c | 6 +-
fs/pipe.c | 15 +-
include/linux/memcontrol.h | 29 +-
include/linux/pipe_fs_i.h | 2 +
include/linux/soc/mediatek/mtk-mmsys.h | 33 +++
include/linux/vdpa.h | 38 ++-
include/linux/virtio.h | 1 +
include/net/flow_offload.h | 12 +-
include/uapi/linux/vdpa.h | 31 +++
kernel/bpf/verifier.c | 1 +
kernel/trace/trace_events_hist.c | 2 +
mm/vmscan.c | 27 +-
net/bluetooth/hidp/core.c | 2 +-
net/dccp/dccp.h | 6 +-
net/openvswitch/vport.c | 1 +
net/sched/sch_cake.c | 2 +-
net/xfrm/xfrm_ipcomp.c | 2 +-
sound/pci/hda/hda_generic.c | 10 +-
sound/pci/hda/patch_realtek.c | 12 +-
sound/pci/hda/patch_via.c | 1 +
sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +-
101 files changed, 1290 insertions(+), 467 deletions(-)
create mode 100644 include/uapi/linux/vdpa.h
--
2.30.2
^ permalink raw reply [relevance 2%]
* [PATCH 5.10 05/98] ath9k: Postpone key cache entry deletion for TXQ frames reference it
2021-08-24 16:57 2% [PATCH 5.10 00/98] 5.10.61-rc1 review Sasha Levin
@ 2021-08-24 16:57 5% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2021-08-24 16:57 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Jouni Malinen, Kalle Valo, Pali Rohár, Greg Kroah-Hartman
From: Jouni Malinen <jouni@codeaurora.org>
commit ca2848022c12789685d3fab3227df02b863f9696 upstream.
Do not delete a key cache entry that is still being referenced by
pending frames in TXQs. This avoids reuse of the key cache entry while a
frame might still be transmitted using it.
To avoid having to do any additional operations during the main TX path
operations, track pending key cache entries in a new bitmap and check
whether any pending entries can be deleted before every new key
add/remove operation. Also clear any remaining entries when stopping the
interface.
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20201214172118.18100-6-jouni@codeaurora.org
Cc: Pali Rohár <pali@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/main.c | 87 ++++++++++++++++++++++++++-
2 files changed, 87 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 023599e10dd5..b7b65b1c90e8 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -820,6 +820,7 @@ struct ath_hw {
struct ath9k_pacal_info pacal_info;
struct ar5416Stats stats;
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+ DECLARE_BITMAP(pending_del_keymap, ATH_KEYMAX);
enum ath9k_int imask;
u32 imrs2_reg;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 9fd3dc66d17a..5739c1dbf166 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -826,12 +826,80 @@ exit:
ieee80211_free_txskb(hw, skb);
}
+static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
+{
+ struct ath_buf *bf;
+ struct ieee80211_tx_info *txinfo;
+ struct ath_frame_info *fi;
+
+ list_for_each_entry(bf, txq_list, list) {
+ if (bf->bf_state.stale || !bf->bf_mpdu)
+ continue;
+
+ txinfo = IEEE80211_SKB_CB(bf->bf_mpdu);
+ fi = (struct ath_frame_info *)&txinfo->rate_driver_data[0];
+ if (fi->keyix == keyix)
+ return true;
+ }
+
+ return false;
+}
+
+static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ int i;
+ struct ath_txq *txq;
+ bool key_in_use = false;
+
+ for (i = 0; !key_in_use && i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+ txq = &sc->tx.txq[i];
+ if (!txq->axq_depth)
+ continue;
+ if (!ath9k_hw_numtxpending(ah, txq->axq_qnum))
+ continue;
+
+ ath_txq_lock(sc, txq);
+ key_in_use = ath9k_txq_list_has_key(&txq->axq_q, keyix);
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ int idx = txq->txq_tailidx;
+
+ while (!key_in_use &&
+ !list_empty(&txq->txq_fifo[idx])) {
+ key_in_use = ath9k_txq_list_has_key(
+ &txq->txq_fifo[idx], keyix);
+ INCR(idx, ATH_TXFIFO_DEPTH);
+ }
+ }
+ ath_txq_unlock(sc, txq);
+ }
+
+ return key_in_use;
+}
+
+static void ath9k_pending_key_del(struct ath_softc *sc, u8 keyix)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!test_bit(keyix, ah->pending_del_keymap) ||
+ ath9k_txq_has_key(sc, keyix))
+ return;
+
+ /* No more TXQ frames point to this key cache entry, so delete it. */
+ clear_bit(keyix, ah->pending_del_keymap);
+ ath_key_delete(common, keyix);
+}
+
static void ath9k_stop(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
bool prev_idle;
+ int i;
ath9k_deinit_channel_context(sc);
@@ -899,6 +967,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
spin_unlock_bh(&sc->sc_pcu_lock);
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
/* Clear key cache entries explicitly to get rid of any potentially
* remaining keys.
*/
@@ -1728,6 +1799,12 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
if (sta)
an = (struct ath_node *)sta->drv_priv;
+ /* Delete pending key cache entries if no more frames are pointing to
+ * them in TXQs.
+ */
+ for (i = 0; i < ATH_KEYMAX; i++)
+ ath9k_pending_key_del(sc, i);
+
switch (cmd) {
case SET_KEY:
if (sta)
@@ -1757,7 +1834,15 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
}
break;
case DISABLE_KEY:
- ath_key_delete(common, key->hw_key_idx);
+ if (ath9k_txq_has_key(sc, key->hw_key_idx)) {
+ /* Delay key cache entry deletion until there are no
+ * remaining TXQ frames pointing to this entry.
+ */
+ set_bit(key->hw_key_idx, sc->sc_ah->pending_del_keymap);
+ ath_hw_keysetmac(common, key->hw_key_idx, NULL);
+ } else {
+ ath_key_delete(common, key->hw_key_idx);
+ }
if (an) {
for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
if (an->key_idx[i] != key->hw_key_idx)
--
2.30.2
^ permalink raw reply related [relevance 5%]
* Re: Drivers for Qualcomm wifi chips (ath*k) and security issues
@ 2021-08-23 19:26 5% ` Sudip Mukherjee
0 siblings, 0 replies; 200+ results
From: Sudip Mukherjee @ 2021-08-23 19:26 UTC (permalink / raw)
To: Pali Rohár
Cc: Ben Greear, Sasha Levin, Greg KH, Stable, open list:TI WILINK WIRELES...
Hi Pali,
On Mon, Aug 23, 2021 at 3:58 PM Pali Rohár <pali@kernel.org> wrote:
>
> On Monday 23 August 2021 07:32:11 Ben Greear wrote:
> > On 8/23/21 7:08 AM, Pali Rohár wrote:
> > > Hello Sasha and Greg!
> > >
> > > Last week I sent request for backporting ath9k wifi fixes for security
> > > issue CVE-2020-3702 into stable LTS kernels because Qualcomm/maintainers
> > > did not it for more months... details are in email:
> > > https://lore.kernel.org/stable/20210818084859.vcs4vs3yd6zetmyt@pali/t/#u
> >
> > For one thing, almost everyone using these radios is using openwrt or
> > similar which has its own patch sets.
>
> AFAIK, latest stable released openwrt uses ath9k from 4.19 tree and
> AFAIK did not have above patch.
I think you asked for the following patches:
56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames
reference it")
And I can see they are already in the queue for next v4.19.y release,
so should be part of v4.19.205
--
Regards
Sudip
^ permalink raw reply [relevance 5%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-08-20 22:27 0% ` Toke Høiland-Jørgensen
@ 2021-08-20 23:07 0% ` Pali Rohár
0 siblings, 0 replies; 200+ results
From: Pali Rohár @ 2021-08-20 23:07 UTC (permalink / raw)
To: Toke Høiland-Jørgensen
Cc: Sasha Levin, Greg KH, stable, Kalle Valo, linux-wireless
On Saturday 21 August 2021 00:27:10 Toke Høiland-Jørgensen wrote:
> Sasha Levin <sashal@kernel.org> writes:
>
> > On Fri, Aug 20, 2021 at 01:35:05PM +0200, Pali Rohár wrote:
> >>On Wednesday 18 August 2021 11:18:29 Greg KH wrote:
> >>> On Wed, Aug 18, 2021 at 11:10:27AM +0200, Pali Rohár wrote:
> >>> > On Wednesday 18 August 2021 11:02:47 Greg KH wrote:
> >>> > > On Wed, Aug 18, 2021 at 10:48:59AM +0200, Pali Rohár wrote:
> >>> > > > Hello! I would like to request for backporting following ath9k commits
> >>> > > > which are fixing CVE-2020-3702 issue.
> >>> > > >
> >>> > > > 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
> >>> > > > 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
> >>> > > > d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
> >>> > > > 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
> >>> > > > ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
> >>> > > >
> >>> > > > See also:
> >>> > > > https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
> >>> > > >
> >>> > > > This CVE-2020-3702 issue affects ath9k driver in stable kernel versions.
> >>> > > > And due to this issue Qualcomm suggests to not use open source ath9k
> >>> > > > driver and instead to use their proprietary driver which do not have
> >>> > > > this issue.
> >>> > > >
> >>> > > > Details about CVE-2020-3702 are described on the ESET blog post:
> >>> > > > https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/
> >>> > > >
> >>> > > > Two months ago ESET tested above mentioned commits applied on top of
> >>> > > > 4.14 stable tree and confirmed that issue cannot be reproduced anymore
> >>> > > > with those patches. Commits were applied cleanly on top of 4.14 stable
> >>> > > > tree without need to do any modification.
> >>> > >
> >>> > > What stable tree(s) do you want to see these go into?
> >>> >
> >>> > Commits were introduced in 5.12, so it should go to all stable trees << 5.12
> >>> >
> >>> > > And what order are the above commits to be applied in, top-to-bottom or
> >>> > > bottom-to-top?
> >>> >
> >>> > Same order in which were applied in 5.12. So first commit to apply is
> >>> > 56c5485c9e44, then 73488cb2fa3b and so on... (from top of the email to
> >>> > the bottom of email).
> >>>
> >>> Great, all now queued up. Sad that qcom didn't want to do this
> >>> themselves :(
> >>>
> >>> greg k-h
> >>
> >>It is sad, but Qualcomm support said that they have fixed it in their
> >>proprietary driver in July 2020 (so more than year ago) and that open
> >>source drivers like ath9k are unsupported and customers should not use
> >>them :( And similar answer is from vendors who put these chips into
> >>their cards / products.
> >
> > Is there a public statement that says that? Right now the MAINTAINERS
> > file says it's "supported" and if it's not the case we should at least
> > fix that and consider deprecating it if it's really orphaned.
>
> FWIW there's still quite a few OpenWrt devices that are using ath9k and
> ticking away happily. And we are some that do still care about ath9k,
> even if QCA doesn't... As the email that started this thread also shows,
> I suppose?
For sure, there are lot of people who are using cards with this driver.
These cards are still popular for scenarios where 802.11N is enough as
these chips are relatively stable and have good hw design. In these
chips there is no CPU, no DSP, everything is done directly in HW or on
host CPU (in kernel driver or userspace). So therefore there is no
firmware/microcode like in new cards single point of failure or cause
instability. And card vendors are still putting these chips also into
new cards.
Simple issues (like kernel crash, API change, ... ) in ath9k driver can
be relatively easily fixed by (any) kernel developer. But issues like
fixing some cryptography part used in hw chip does not have to be simple
for people who do not have HW documentation or are not skilled in how
chip is working. (IIRC there is no public HW documentation)
So due to popularity basic maintenance is and would be still there (even
without Qualcomm support), but security related issues are problematic.
And I think that these older wifi cards would be still under attack by
security researchers. So we can expect that in future there can be
another attack which would need some driver modification for correct
mitigation...
^ permalink raw reply [relevance 0%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-08-20 21:23 0% ` Sasha Levin
2021-08-20 22:27 0% ` Toke Høiland-Jørgensen
@ 2021-08-20 22:41 0% ` Pali Rohár
1 sibling, 0 replies; 200+ results
From: Pali Rohár @ 2021-08-20 22:41 UTC (permalink / raw)
To: Sasha Levin; +Cc: Greg KH, stable, Kalle Valo, linux-wireless
On Friday 20 August 2021 17:23:08 Sasha Levin wrote:
> On Fri, Aug 20, 2021 at 01:35:05PM +0200, Pali Rohár wrote:
> > On Wednesday 18 August 2021 11:18:29 Greg KH wrote:
> > > On Wed, Aug 18, 2021 at 11:10:27AM +0200, Pali Rohár wrote:
> > > > On Wednesday 18 August 2021 11:02:47 Greg KH wrote:
> > > > > On Wed, Aug 18, 2021 at 10:48:59AM +0200, Pali Rohár wrote:
> > > > > > Hello! I would like to request for backporting following ath9k commits
> > > > > > which are fixing CVE-2020-3702 issue.
> > > > > >
> > > > > > 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
> > > > > > 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
> > > > > > d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
> > > > > > 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
> > > > > > ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
> > > > > >
> > > > > > See also:
> > > > > > https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
> > > > > >
> > > > > > This CVE-2020-3702 issue affects ath9k driver in stable kernel versions.
> > > > > > And due to this issue Qualcomm suggests to not use open source ath9k
> > > > > > driver and instead to use their proprietary driver which do not have
> > > > > > this issue.
> > > > > >
> > > > > > Details about CVE-2020-3702 are described on the ESET blog post:
> > > > > > https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/
> > > > > >
> > > > > > Two months ago ESET tested above mentioned commits applied on top of
> > > > > > 4.14 stable tree and confirmed that issue cannot be reproduced anymore
> > > > > > with those patches. Commits were applied cleanly on top of 4.14 stable
> > > > > > tree without need to do any modification.
> > > > >
> > > > > What stable tree(s) do you want to see these go into?
> > > >
> > > > Commits were introduced in 5.12, so it should go to all stable trees << 5.12
> > > >
> > > > > And what order are the above commits to be applied in, top-to-bottom or
> > > > > bottom-to-top?
> > > >
> > > > Same order in which were applied in 5.12. So first commit to apply is
> > > > 56c5485c9e44, then 73488cb2fa3b and so on... (from top of the email to
> > > > the bottom of email).
> > >
> > > Great, all now queued up. Sad that qcom didn't want to do this
> > > themselves :(
> > >
> > > greg k-h
> >
> > It is sad, but Qualcomm support said that they have fixed it in their
> > proprietary driver in July 2020 (so more than year ago) and that open
> > source drivers like ath9k are unsupported and customers should not use
> > them :( And similar answer is from vendors who put these chips into
> > their cards / products.
>
> Is there a public statement that says that? Right now the MAINTAINERS
> file says it's "supported" and if it's not the case we should at least
> fix that and consider deprecating it if it's really orphaned.
No, there is no public statement. This is just (private) response from
official Qualcomm support contact...
And from card vendors were similar replies, that they received only fix
from Qualcomm (for proprietary driver) and for open source ath9k support
I need to ask open source kernel community. They suggested me to wait
until open source kernel community fix it.
I really do not know what is the support state of ath9k, but the fact is
that this security issue was fixed in July 2020 (in Qualcomm driver) and
some vendors received fix even earlier.
So something is really wrong if in LTS kernels this issue was not fixed
for more than year and in vendor driver was it basically immediately.
I agree that some clarification or public statement about ath9k driver
support would be very useful...
> --
> Thanks,
> Sasha
^ permalink raw reply [relevance 0%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-08-20 21:23 0% ` Sasha Levin
@ 2021-08-20 22:27 0% ` Toke Høiland-Jørgensen
2021-08-20 23:07 0% ` Pali Rohár
2021-08-20 22:41 0% ` Pali Rohár
1 sibling, 1 reply; 200+ results
From: Toke Høiland-Jørgensen @ 2021-08-20 22:27 UTC (permalink / raw)
To: Sasha Levin, Pali Rohár; +Cc: Greg KH, stable, Kalle Valo, linux-wireless
Sasha Levin <sashal@kernel.org> writes:
> On Fri, Aug 20, 2021 at 01:35:05PM +0200, Pali Rohár wrote:
>>On Wednesday 18 August 2021 11:18:29 Greg KH wrote:
>>> On Wed, Aug 18, 2021 at 11:10:27AM +0200, Pali Rohár wrote:
>>> > On Wednesday 18 August 2021 11:02:47 Greg KH wrote:
>>> > > On Wed, Aug 18, 2021 at 10:48:59AM +0200, Pali Rohár wrote:
>>> > > > Hello! I would like to request for backporting following ath9k commits
>>> > > > which are fixing CVE-2020-3702 issue.
>>> > > >
>>> > > > 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
>>> > > > 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
>>> > > > d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
>>> > > > 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
>>> > > > ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
>>> > > >
>>> > > > See also:
>>> > > > https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
>>> > > >
>>> > > > This CVE-2020-3702 issue affects ath9k driver in stable kernel versions.
>>> > > > And due to this issue Qualcomm suggests to not use open source ath9k
>>> > > > driver and instead to use their proprietary driver which do not have
>>> > > > this issue.
>>> > > >
>>> > > > Details about CVE-2020-3702 are described on the ESET blog post:
>>> > > > https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/
>>> > > >
>>> > > > Two months ago ESET tested above mentioned commits applied on top of
>>> > > > 4.14 stable tree and confirmed that issue cannot be reproduced anymore
>>> > > > with those patches. Commits were applied cleanly on top of 4.14 stable
>>> > > > tree without need to do any modification.
>>> > >
>>> > > What stable tree(s) do you want to see these go into?
>>> >
>>> > Commits were introduced in 5.12, so it should go to all stable trees << 5.12
>>> >
>>> > > And what order are the above commits to be applied in, top-to-bottom or
>>> > > bottom-to-top?
>>> >
>>> > Same order in which were applied in 5.12. So first commit to apply is
>>> > 56c5485c9e44, then 73488cb2fa3b and so on... (from top of the email to
>>> > the bottom of email).
>>>
>>> Great, all now queued up. Sad that qcom didn't want to do this
>>> themselves :(
>>>
>>> greg k-h
>>
>>It is sad, but Qualcomm support said that they have fixed it in their
>>proprietary driver in July 2020 (so more than year ago) and that open
>>source drivers like ath9k are unsupported and customers should not use
>>them :( And similar answer is from vendors who put these chips into
>>their cards / products.
>
> Is there a public statement that says that? Right now the MAINTAINERS
> file says it's "supported" and if it's not the case we should at least
> fix that and consider deprecating it if it's really orphaned.
FWIW there's still quite a few OpenWrt devices that are using ath9k and
ticking away happily. And we are some that do still care about ath9k,
even if QCA doesn't... As the email that started this thread also shows,
I suppose?
-Toke
^ permalink raw reply [relevance 0%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-08-20 11:35 0% ` Pali Rohár
@ 2021-08-20 21:23 0% ` Sasha Levin
2021-08-20 22:27 0% ` Toke Høiland-Jørgensen
2021-08-20 22:41 0% ` Pali Rohár
0 siblings, 2 replies; 200+ results
From: Sasha Levin @ 2021-08-20 21:23 UTC (permalink / raw)
To: Pali Rohár; +Cc: Greg KH, stable, Kalle Valo, linux-wireless
On Fri, Aug 20, 2021 at 01:35:05PM +0200, Pali Rohár wrote:
>On Wednesday 18 August 2021 11:18:29 Greg KH wrote:
>> On Wed, Aug 18, 2021 at 11:10:27AM +0200, Pali Rohár wrote:
>> > On Wednesday 18 August 2021 11:02:47 Greg KH wrote:
>> > > On Wed, Aug 18, 2021 at 10:48:59AM +0200, Pali Rohár wrote:
>> > > > Hello! I would like to request for backporting following ath9k commits
>> > > > which are fixing CVE-2020-3702 issue.
>> > > >
>> > > > 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
>> > > > 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
>> > > > d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
>> > > > 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
>> > > > ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
>> > > >
>> > > > See also:
>> > > > https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
>> > > >
>> > > > This CVE-2020-3702 issue affects ath9k driver in stable kernel versions.
>> > > > And due to this issue Qualcomm suggests to not use open source ath9k
>> > > > driver and instead to use their proprietary driver which do not have
>> > > > this issue.
>> > > >
>> > > > Details about CVE-2020-3702 are described on the ESET blog post:
>> > > > https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/
>> > > >
>> > > > Two months ago ESET tested above mentioned commits applied on top of
>> > > > 4.14 stable tree and confirmed that issue cannot be reproduced anymore
>> > > > with those patches. Commits were applied cleanly on top of 4.14 stable
>> > > > tree without need to do any modification.
>> > >
>> > > What stable tree(s) do you want to see these go into?
>> >
>> > Commits were introduced in 5.12, so it should go to all stable trees << 5.12
>> >
>> > > And what order are the above commits to be applied in, top-to-bottom or
>> > > bottom-to-top?
>> >
>> > Same order in which were applied in 5.12. So first commit to apply is
>> > 56c5485c9e44, then 73488cb2fa3b and so on... (from top of the email to
>> > the bottom of email).
>>
>> Great, all now queued up. Sad that qcom didn't want to do this
>> themselves :(
>>
>> greg k-h
>
>It is sad, but Qualcomm support said that they have fixed it in their
>proprietary driver in July 2020 (so more than year ago) and that open
>source drivers like ath9k are unsupported and customers should not use
>them :( And similar answer is from vendors who put these chips into
>their cards / products.
Is there a public statement that says that? Right now the MAINTAINERS
file says it's "supported" and if it's not the case we should at least
fix that and consider deprecating it if it's really orphaned.
--
Thanks,
Sasha
^ permalink raw reply [relevance 0%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-08-18 9:18 0% ` Greg KH
@ 2021-08-20 11:35 0% ` Pali Rohár
2021-08-20 21:23 0% ` Sasha Levin
2021-09-02 11:48 0% ` Pavel Machek
1 sibling, 1 reply; 200+ results
From: Pali Rohár @ 2021-08-20 11:35 UTC (permalink / raw)
To: Greg KH; +Cc: stable, Sasha Levin, Kalle Valo, linux-wireless
On Wednesday 18 August 2021 11:18:29 Greg KH wrote:
> On Wed, Aug 18, 2021 at 11:10:27AM +0200, Pali Rohár wrote:
> > On Wednesday 18 August 2021 11:02:47 Greg KH wrote:
> > > On Wed, Aug 18, 2021 at 10:48:59AM +0200, Pali Rohár wrote:
> > > > Hello! I would like to request for backporting following ath9k commits
> > > > which are fixing CVE-2020-3702 issue.
> > > >
> > > > 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
> > > > 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
> > > > d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
> > > > 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
> > > > ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
> > > >
> > > > See also:
> > > > https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
> > > >
> > > > This CVE-2020-3702 issue affects ath9k driver in stable kernel versions.
> > > > And due to this issue Qualcomm suggests to not use open source ath9k
> > > > driver and instead to use their proprietary driver which do not have
> > > > this issue.
> > > >
> > > > Details about CVE-2020-3702 are described on the ESET blog post:
> > > > https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/
> > > >
> > > > Two months ago ESET tested above mentioned commits applied on top of
> > > > 4.14 stable tree and confirmed that issue cannot be reproduced anymore
> > > > with those patches. Commits were applied cleanly on top of 4.14 stable
> > > > tree without need to do any modification.
> > >
> > > What stable tree(s) do you want to see these go into?
> >
> > Commits were introduced in 5.12, so it should go to all stable trees << 5.12
> >
> > > And what order are the above commits to be applied in, top-to-bottom or
> > > bottom-to-top?
> >
> > Same order in which were applied in 5.12. So first commit to apply is
> > 56c5485c9e44, then 73488cb2fa3b and so on... (from top of the email to
> > the bottom of email).
>
> Great, all now queued up. Sad that qcom didn't want to do this
> themselves :(
>
> greg k-h
It is sad, but Qualcomm support said that they have fixed it in their
proprietary driver in July 2020 (so more than year ago) and that open
source drivers like ath9k are unsupported and customers should not use
them :( And similar answer is from vendors who put these chips into
their cards / products.
^ permalink raw reply [relevance 0%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-08-18 9:10 0% ` Pali Rohár
@ 2021-08-18 9:18 0% ` Greg KH
2021-08-20 11:35 0% ` Pali Rohár
2021-09-02 11:48 0% ` Pavel Machek
0 siblings, 2 replies; 200+ results
From: Greg KH @ 2021-08-18 9:18 UTC (permalink / raw)
To: Pali Rohár; +Cc: stable, Sasha Levin, Kalle Valo, linux-wireless
On Wed, Aug 18, 2021 at 11:10:27AM +0200, Pali Rohár wrote:
> On Wednesday 18 August 2021 11:02:47 Greg KH wrote:
> > On Wed, Aug 18, 2021 at 10:48:59AM +0200, Pali Rohár wrote:
> > > Hello! I would like to request for backporting following ath9k commits
> > > which are fixing CVE-2020-3702 issue.
> > >
> > > 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
> > > 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
> > > d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
> > > 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
> > > ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
> > >
> > > See also:
> > > https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
> > >
> > > This CVE-2020-3702 issue affects ath9k driver in stable kernel versions.
> > > And due to this issue Qualcomm suggests to not use open source ath9k
> > > driver and instead to use their proprietary driver which do not have
> > > this issue.
> > >
> > > Details about CVE-2020-3702 are described on the ESET blog post:
> > > https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/
> > >
> > > Two months ago ESET tested above mentioned commits applied on top of
> > > 4.14 stable tree and confirmed that issue cannot be reproduced anymore
> > > with those patches. Commits were applied cleanly on top of 4.14 stable
> > > tree without need to do any modification.
> >
> > What stable tree(s) do you want to see these go into?
>
> Commits were introduced in 5.12, so it should go to all stable trees << 5.12
>
> > And what order are the above commits to be applied in, top-to-bottom or
> > bottom-to-top?
>
> Same order in which were applied in 5.12. So first commit to apply is
> 56c5485c9e44, then 73488cb2fa3b and so on... (from top of the email to
> the bottom of email).
Great, all now queued up. Sad that qcom didn't want to do this
themselves :(
greg k-h
^ permalink raw reply [relevance 0%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-08-18 9:02 0% ` Greg KH
@ 2021-08-18 9:10 0% ` Pali Rohár
2021-08-18 9:18 0% ` Greg KH
0 siblings, 1 reply; 200+ results
From: Pali Rohár @ 2021-08-18 9:10 UTC (permalink / raw)
To: Greg KH; +Cc: stable, Sasha Levin, Kalle Valo, linux-wireless
On Wednesday 18 August 2021 11:02:47 Greg KH wrote:
> On Wed, Aug 18, 2021 at 10:48:59AM +0200, Pali Rohár wrote:
> > Hello! I would like to request for backporting following ath9k commits
> > which are fixing CVE-2020-3702 issue.
> >
> > 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
> > 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
> > d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
> > 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
> > ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
> >
> > See also:
> > https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
> >
> > This CVE-2020-3702 issue affects ath9k driver in stable kernel versions.
> > And due to this issue Qualcomm suggests to not use open source ath9k
> > driver and instead to use their proprietary driver which do not have
> > this issue.
> >
> > Details about CVE-2020-3702 are described on the ESET blog post:
> > https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/
> >
> > Two months ago ESET tested above mentioned commits applied on top of
> > 4.14 stable tree and confirmed that issue cannot be reproduced anymore
> > with those patches. Commits were applied cleanly on top of 4.14 stable
> > tree without need to do any modification.
>
> What stable tree(s) do you want to see these go into?
Commits were introduced in 5.12, so it should go to all stable trees << 5.12
> And what order are the above commits to be applied in, top-to-bottom or
> bottom-to-top?
Same order in which were applied in 5.12. So first commit to apply is
56c5485c9e44, then 73488cb2fa3b and so on... (from top of the email to
the bottom of email).
> thanks,
>
> greg k-h
^ permalink raw reply [relevance 0%]
* Re: Backporting CVE-2020-3702 ath9k patches to stable
2021-08-18 8:48 5% Backporting CVE-2020-3702 ath9k patches to stable Pali Rohár
@ 2021-08-18 9:02 0% ` Greg KH
2021-08-18 9:10 0% ` Pali Rohár
0 siblings, 1 reply; 200+ results
From: Greg KH @ 2021-08-18 9:02 UTC (permalink / raw)
To: Pali Rohár; +Cc: stable, Sasha Levin, Kalle Valo, linux-wireless
On Wed, Aug 18, 2021 at 10:48:59AM +0200, Pali Rohár wrote:
> Hello! I would like to request for backporting following ath9k commits
> which are fixing CVE-2020-3702 issue.
>
> 56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
> 73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
> d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
> 144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
> ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
>
> See also:
> https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
>
> This CVE-2020-3702 issue affects ath9k driver in stable kernel versions.
> And due to this issue Qualcomm suggests to not use open source ath9k
> driver and instead to use their proprietary driver which do not have
> this issue.
>
> Details about CVE-2020-3702 are described on the ESET blog post:
> https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/
>
> Two months ago ESET tested above mentioned commits applied on top of
> 4.14 stable tree and confirmed that issue cannot be reproduced anymore
> with those patches. Commits were applied cleanly on top of 4.14 stable
> tree without need to do any modification.
What stable tree(s) do you want to see these go into?
And what order are the above commits to be applied in, top-to-bottom or
bottom-to-top?
thanks,
greg k-h
^ permalink raw reply [relevance 0%]
* Backporting CVE-2020-3702 ath9k patches to stable
@ 2021-08-18 8:48 5% Pali Rohár
2021-08-18 9:02 0% ` Greg KH
0 siblings, 1 reply; 200+ results
From: Pali Rohár @ 2021-08-18 8:48 UTC (permalink / raw)
To: stable; +Cc: Greg KH, Sasha Levin, Kalle Valo, linux-wireless
Hello! I would like to request for backporting following ath9k commits
which are fixing CVE-2020-3702 issue.
56c5485c9e44 ("ath: Use safer key clearing with key cache entries")
73488cb2fa3b ("ath9k: Clear key cache explicitly on disabling hardware")
d2d3e36498dd ("ath: Export ath_hw_keysetmac()")
144cd24dbc36 ("ath: Modify ath_key_delete() to not need full key entry")
ca2848022c12 ("ath9k: Postpone key cache entry deletion for TXQ frames reference it")
See also:
https://lore.kernel.org/linux-wireless/87o8hvlx5g.fsf@codeaurora.org/
This CVE-2020-3702 issue affects ath9k driver in stable kernel versions.
And due to this issue Qualcomm suggests to not use open source ath9k
driver and instead to use their proprietary driver which do not have
this issue.
Details about CVE-2020-3702 are described on the ESET blog post:
https://www.welivesecurity.com/2020/08/06/beyond-kr00k-even-more-wifi-chips-vulnerable-eavesdropping/
Two months ago ESET tested above mentioned commits applied on top of
4.14 stable tree and confirmed that issue cannot be reproduced anymore
with those patches. Commits were applied cleanly on top of 4.14 stable
tree without need to do any modification.
^ permalink raw reply [relevance 5%]
* Linux 5.10.27
@ 2021-03-30 13:37 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-30 13:37 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.10.27 kernel.
All users of the 5.10 kernel series must upgrade.
The updated 5.10.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.10.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/virt/kvm/api.rst | 6
Makefile | 5
arch/arm/boot/dts/at91-sam9x60ek.dts | 8
arch/arm/boot/dts/at91-sama5d27_som1.dtsi | 4
arch/arm/boot/dts/imx6ull-myir-mys-6ulx-eval.dts | 1
arch/arm/boot/dts/sam9x60.dtsi | 9
arch/arm/mach-omap2/sr_device.c | 75 +++--
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 1
arch/arm64/kernel/crash_dump.c | 2
arch/arm64/kernel/stacktrace.c | 9
arch/ia64/include/asm/syscall.h | 2
arch/ia64/kernel/ptrace.c | 24 +
arch/powerpc/include/asm/dcr-native.h | 8
arch/sparc/kernel/traps_64.c | 13
arch/x86/include/asm/kvm_host.h | 14
arch/x86/include/asm/static_call.h | 7
arch/x86/include/asm/xen/page.h | 12
arch/x86/kvm/x86.c | 109 ++++---
arch/x86/mm/mem_encrypt.c | 2
arch/x86/xen/p2m.c | 7
arch/x86/xen/setup.c | 16 -
block/blk-cgroup-rwstat.c | 3
block/blk-merge.c | 8
block/blk-zoned.c | 2
block/genhd.c | 4
drivers/acpi/acpica/nsaccess.c | 3
drivers/acpi/internal.h | 6
drivers/acpi/scan.c | 88 +++--
drivers/acpi/video_detect.c | 1
drivers/atm/eni.c | 3
drivers/atm/idt77105.c | 4
drivers/atm/lanai.c | 5
drivers/atm/uPD98402.c | 2
drivers/base/power/runtime.c | 45 ++-
drivers/block/umem.c | 5
drivers/block/xen-blkback/blkback.c | 2
drivers/bus/omap_l3_noc.c | 4
drivers/clk/qcom/gcc-sc7180.c | 4
drivers/cpufreq/cpufreq-dt-platdev.c | 2
drivers/gpio/gpiolib-acpi.c | 2
drivers/gpu/drm/Kconfig | 1
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c | 3
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2
drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 54 +++
drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 74 ++++-
drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 24 +
drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 25 +
drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2
drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 13
drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +
drivers/gpu/drm/i915/intel_runtime_pm.h | 5
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 2
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 6
drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c | 5
drivers/gpu/drm/msm/msm_drv.c | 12
drivers/infiniband/hw/cxgb4/cm.c | 4
drivers/irqchip/irq-ingenic-tcu.c | 1
drivers/irqchip/irq-ingenic.c | 1
drivers/md/dm-ioctl.c | 2
drivers/md/dm-table.c | 33 +-
drivers/md/dm-verity-target.c | 2
drivers/md/dm-zoned-target.c | 2
drivers/misc/habanalabs/common/device.c | 2
drivers/net/bonding/bond_main.c | 8
drivers/net/can/c_can/c_can.c | 24 -
drivers/net/can/c_can/c_can_pci.c | 3
drivers/net/can/c_can/c_can_platform.c | 6
drivers/net/can/dev.c | 1
drivers/net/can/flexcan.c | 8
drivers/net/can/kvaser_pciefd.c | 4
drivers/net/can/m_can/m_can.c | 5
drivers/net/dsa/b53/b53_common.c | 14
drivers/net/dsa/bcm_sf2.c | 6
drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 2
drivers/net/ethernet/davicom/dm9000.c | 2
drivers/net/ethernet/faraday/ftgmac100.c | 1
drivers/net/ethernet/freescale/enetc/enetc_hw.h | 2
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6
drivers/net/ethernet/freescale/fec_ptp.c | 7
drivers/net/ethernet/freescale/gianfar.c | 15 +
drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4
drivers/net/ethernet/intel/e1000e/82571.c | 2
drivers/net/ethernet/intel/e1000e/netdev.c | 6
drivers/net/ethernet/intel/iavf/iavf_main.c | 3
drivers/net/ethernet/intel/igb/igb.h | 4
drivers/net/ethernet/intel/igb/igb_main.c | 33 +-
drivers/net/ethernet/intel/igb/igb_ptp.c | 31 +-
drivers/net/ethernet/intel/igc/igc.h | 2
drivers/net/ethernet/intel/igc/igc_ethtool.c | 7
drivers/net/ethernet/intel/igc/igc_main.c | 9
drivers/net/ethernet/intel/igc/igc_ptp.c | 72 ++--
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6
drivers/net/ethernet/marvell/octeontx2/af/npc.h | 31 ++
drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h | 97 +++++-
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 4
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c | 48 ++-
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c | 4
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5
drivers/net/ethernet/mellanox/mlx5/core/en.h | 7
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 3
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c | 4
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 6
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 17 -
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 54 ++-
drivers/net/ethernet/netronome/nfp/flower/metadata.c | 24 +
drivers/net/ethernet/netronome/nfp/flower/offload.c | 18 +
drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c | 15 -
drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 13
drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 3
drivers/net/ethernet/realtek/r8169_main.c | 6
drivers/net/ethernet/socionext/netsec.c | 9
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 50 ++-
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 9
drivers/net/ethernet/stmicro/stmmac/hwif.h | 3
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 9
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 57 ++-
drivers/net/ethernet/sun/niu.c | 2
drivers/net/ethernet/tehuti/tehuti.c | 1
drivers/net/ethernet/xilinx/xilinx_axienet.h | 3
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 125 ++++++--
drivers/net/ipa/ipa_qmi.c | 2
drivers/net/phy/broadcom.c | 147 +++++++---
drivers/net/phy/dp83822.c | 3
drivers/net/phy/dp83869.c | 4
drivers/net/phy/lxt.c | 1
drivers/net/phy/marvell.c | 1
drivers/net/phy/marvell10g.c | 2
drivers/net/phy/micrel.c | 14
drivers/net/phy/phy.c | 2
drivers/net/phy/phy_device.c | 9
drivers/net/phy/phylink.c | 2
drivers/net/usb/cdc-phonet.c | 2
drivers/net/usb/r8152.c | 40 --
drivers/net/veth.c | 3
drivers/net/wan/fsl_ucc_hdlc.c | 8
drivers/net/wan/hdlc_x25.c | 42 ++
drivers/net/wireless/mediatek/mt76/dma.c | 15 -
drivers/nvme/host/core.c | 15 -
drivers/nvme/host/fc.c | 3
drivers/nvme/host/pci.c | 1
drivers/nvme/target/rdma.c | 5
drivers/platform/x86/intel-vbtn.c | 12
drivers/regulator/qcom-rpmh-regulator.c | 4
drivers/scsi/mpt3sas/mpt3sas_base.c | 8
drivers/scsi/qedi/qedi_main.c | 1
drivers/scsi/qla2xxx/qla_target.c | 13
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4
drivers/scsi/ufs/ufs-qcom.c | 10
drivers/soc/ti/omap_prm.c | 6
drivers/staging/rtl8192e/Kconfig | 1
drivers/xen/Kconfig | 4
fs/btrfs/qgroup.c | 12
fs/cachefiles/rdwr.c | 7
fs/cifs/cifsglob.h | 4
fs/cifs/cifspdu.h | 5
fs/cifs/smb2glob.h | 1
fs/cifs/smb2ops.c | 27 +
fs/cifs/smb2pdu.c | 6
fs/cifs/smb2transport.c | 37 +-
fs/cifs/transport.c | 2
fs/ext4/mballoc.c | 11
fs/ext4/xattr.c | 4
fs/gfs2/log.c | 4
fs/gfs2/trans.c | 2
fs/io_uring.c | 4
fs/nfs/Kconfig | 2
fs/nfs/nfs3xdr.c | 3
fs/nfs/nfs4proc.c | 3
fs/squashfs/export.c | 8
fs/squashfs/id.c | 6
fs/squashfs/squashfs_fs.h | 1
fs/squashfs/xattr_id.c | 6
include/acpi/acpi_bus.h | 1
include/asm-generic/vmlinux.lds.h | 5
include/linux/bpf.h | 9
include/linux/brcmphy.h | 4
include/linux/device-mapper.h | 15 -
include/linux/hugetlb_cgroup.h | 15 -
include/linux/if_macvlan.h | 3
include/linux/memcontrol.h | 6
include/linux/mm.h | 15 -
include/linux/mm_types.h | 1
include/linux/mmu_notifier.h | 10
include/linux/mutex.h | 2
include/linux/netfilter/x_tables.h | 7
include/linux/pagemap.h | 1
include/linux/phy.h | 2
include/linux/static_call.h | 43 +-
include/linux/static_call_types.h | 50 +++
include/linux/u64_stats_sync.h | 7
include/linux/usermode_driver.h | 1
include/net/dst.h | 11
include/net/inet_connection_sock.h | 2
include/net/netfilter/nf_tables.h | 3
include/net/nexthop.h | 24 +
include/net/red.h | 10
include/net/rtnetlink.h | 2
include/uapi/linux/psample.h | 5
kernel/bpf/bpf_inode_storage.c | 2
kernel/bpf/preload/bpf_preload_kern.c | 19 +
kernel/fork.c | 8
kernel/gcov/clang.c | 69 ++++
kernel/power/energy_model.c | 2
kernel/static_call.c | 71 ++++
kernel/trace/ftrace.c | 43 ++
kernel/usermode_driver.c | 21 +
mm/huge_memory.c | 2
mm/hugetlb.c | 41 ++
mm/hugetlb_cgroup.c | 10
mm/memcontrol.c | 17 -
mm/mmu_notifier.c | 23 +
mm/page_alloc.c | 1
mm/z3fold.c | 16 +
net/bridge/br_switchdev.c | 2
net/can/isotp.c | 18 -
net/core/dev.c | 14
net/core/drop_monitor.c | 23 +
net/core/dst.c | 59 ++--
net/core/flow_dissector.c | 2
net/dccp/ipv6.c | 5
net/ipv4/inet_connection_sock.c | 7
net/ipv4/netfilter/arp_tables.c | 16 -
net/ipv4/netfilter/ip_tables.c | 16 -
net/ipv4/route.c | 45 ---
net/ipv4/tcp_minisocks.c | 7
net/ipv6/ip6_fib.c | 2
net/ipv6/ip6_input.c | 10
net/ipv6/netfilter/ip6_tables.c | 16 -
net/ipv6/route.c | 36 --
net/ipv6/tcp_ipv6.c | 5
net/mac80211/cfg.c | 4
net/mac80211/ibss.c | 2
net/mac80211/mlme.c | 2
net/mac80211/util.c | 2
net/mptcp/subflow.c | 5
net/netfilter/nf_conntrack_netlink.c | 1
net/netfilter/nf_flow_table_core.c | 2
net/netfilter/nf_tables_api.c | 19 +
net/netfilter/x_tables.c | 49 ++-
net/qrtr/qrtr.c | 5
net/sched/cls_flower.c | 2
net/sched/sch_choke.c | 7
net/sched/sch_gred.c | 2
net/sched/sch_red.c | 7
net/sched/sch_sfq.c | 2
net/tipc/node.c | 11
net/vmw_vsock/af_vsock.c | 1
scripts/dummy-tools/gcc | 5
security/integrity/iint.c | 8
security/selinux/include/security.h | 15 -
security/selinux/selinuxfs.c | 13
security/selinux/ss/services.c | 63 ++--
sound/hda/intel-nhlt.c | 5
tools/include/linux/static_call_types.h | 50 +++
tools/lib/bpf/Makefile | 2
tools/lib/bpf/btf_dump.c | 2
tools/lib/bpf/libbpf.c | 3
tools/lib/bpf/netlink.c | 2
tools/objtool/check.c | 17 +
tools/perf/util/auxtrace.c | 4
tools/perf/util/synthetic-events.c | 9
tools/testing/selftests/arm64/fp/sve-ptrace.c | 2
tools/testing/selftests/bpf/progs/test_tunnel_kern.c | 6
tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh | 2
tools/testing/selftests/net/reuseaddr_ports_exhausted.c | 32 +-
272 files changed, 2578 insertions(+), 970 deletions(-)
Adrian Hunter (1):
perf auxtrace: Fix auxtrace queue conflict
Alaa Hleihel (1):
net/mlx5e: Allow to match on MPLS parameters only for MPLS over UDP
Alex Deucher (2):
drm/amdgpu/display: restore AUX_DPHY_TX_CONTROL for DCN2.x
drm/amdgpu: Add additional Sienna Cichlid PCI ID
Alex Elder (1):
net: ipa: terminate message handler arrays
Alex Marginean (1):
net: enetc: set MAC RX FIFO to recommended value
Alexander Lobakin (1):
flow_dissector: fix byteorder of dissected ICMP ID
Alexander Ovechkin (1):
tcp: relookup sock for RST+ACK packets handled by obsolete req sock
Alexei Starovoitov (1):
ftrace: Fix modify_ftrace_direct.
Andre Guedes (1):
igc: Fix igc_ptp_rx_pktstamp()
Andrey Konovalov (1):
kasan: fix per-page tags for non-page_alloc pages
Andy Shevchenko (1):
ACPI: scan: Use unique number for instance_no
Angelo Dureghello (1):
can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
Arnd Bergmann (1):
ch_ktls: fix enum-conversion warning
Aurelien Aptel (1):
cifs: ask for more credit on async read/write code paths
Aya Levin (1):
net/mlx5e: Fix error path for ethtool set-priv-flag
Bart Van Assche (1):
scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
Bob Peterson (1):
gfs2: fix use-after-free in trans_drain
Brian Norris (1):
mac80211: Allow HE operation to be longer than expected.
Carlos Llamas (1):
selftests/net: fix warnings on reuseaddr_ports_exhausted
Chaitanya Kulkarni (1):
nvme-core: check ctrl css before setting up zns
Chris Chiu (1):
ACPI: video: Add missing callback back for Sony VPCEH3U1E
Christian König (1):
drm/radeon: fix AGP dependency
Christoph Hellwig (1):
nvme: fix the nsid value to print in nvme_validate_or_alloc_ns
Claudiu Beznea (1):
ARM: dts: at91-sama5d27_som1: fix phy address to 7
Colin Ian King (1):
octeontx2-af: Fix memory leak of object buf
Corentin Labbe (1):
net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
Damien Le Moal (1):
block: Fix REQ_OP_ZONE_RESET_ALL handling
Daniel Borkmann (2):
net: Consolidate common blackhole dst ops
net, bpf: Fix ip6ip6 crash with collect_md populated skbs
Daniel Vetter (1):
drm/etnaviv: Use FOLL_FORCE for userptr
Daniel Wagner (1):
block: Suppress uevent for hidden device when removed
David Brazdil (1):
selinux: vsock: Set SID for socket returned by accept()
David Jeffery (1):
block: recalculate segment count for multi-segment discards correctly
David S. Miller (1):
Revert "net: bonding: fix error return code of bond_neigh_init()"
Denis Efremov (1):
sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
Dima Chumak (1):
net/mlx5e: Offload tuple rewrite for non-CT flows
Dinghao Liu (2):
ixgbe: Fix memleak in ixgbe_configure_clsu32
e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
Dmitry Baryshkov (2):
drm/msm/dsi: fix check-before-set in the 7nm dsi_pll code
drm/msm: fix shutdown hook in case GPU components failed to bind
Dmitry Monakhov (1):
nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
Douglas Anderson (1):
clk: qcom: gcc-sc7180: Use floor ops for the correct sdcc1 clk
Dylan Hung (1):
ftgmac100: Restart MAC HW once
Eric Dumazet (4):
macvlan: macvlan_count_rx() needs to be aware of preemption
net: sched: validate stab values
net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
tipc: better validate user input in tipc_nl_retrieve_key()
Fabio Estevam (1):
drm/msm: Fix suspend/resume on i.MX5
Federico Pellegrin (1):
ARM: dts: at91: sam9x60: fix mux-mask for PA7 so it can be set to A, B and C
Felix Fietkau (1):
mt76: fix tx skb error handling in mt76_dma_tx_queue_skb
Fenghua Yu (1):
mm/fork: clear PASID for new mm
Filipe Manana (1):
btrfs: fix sleep while in non-sleep context during qgroup removal
Florian Fainelli (5):
net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
net: phy: broadcom: Add power down exit reset state delay
net: phy: broadcom: Avoid forward for bcm54xx_config_clock_delay()
net: phy: broadcom: Fix RGMII delays for BCM50160 and BCM50610M
net: dsa: b53: VLAN filtering is global to all users
Florian Westphal (1):
netfilter: ctnetlink: fix dump of the expect mask attribute
Frank Sorenson (1):
NFS: Correct size calculation for create reply length
Geetha sowjanya (2):
octeontx2-af: Fix irq free in rvu teardown
octeontx2-pf: Clear RSS enable flag on interace down
Georgi Valkov (1):
libbpf: Fix INSTALL flag order
Greg Kroah-Hartman (1):
Linux 5.10.27
Grygorii Strashko (1):
bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
Hangbin Liu (2):
selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
Hannes Reinecke (4):
nvme: simplify error logic in nvme_validate_ns()
nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
nvme-fc: set NVME_REQ_CANCELLED in nvme_fc_terminate_exchange()
nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
Hans de Goede (1):
platform/x86: intel-vbtn: Stop reporting SW_DOCK events
Hariprasad Kelam (1):
octeontx2-af: fix infinite loop in unmapping NPC counter
Hayes Wang (2):
Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
r8152: limit the RX buffer size of RTL8153A for USB 2.0
Heiko Thiery (1):
net: fec: ptp: avoid register access when ipg clock is disabled
Heiner Kallweit (1):
r8169: fix DMA being used after buffer free if WoL is enabled
Horia Geantă (3):
arm64: dts: ls1046a: mark crypto engine dma coherent
arm64: dts: ls1012a: mark crypto engine dma coherent
arm64: dts: ls1043a: mark crypto engine dma coherent
Hugh Dickins (1):
mm/memcg: fix 5.10 backport of splitting page memcg
Huy Nguyen (1):
net/mlx5: Add back multicast stats for uplink representor
Ian Rogers (1):
perf synthetic events: Avoid write of uninitialized memory when generating PERF_RECORD_MMAP* records
Ido Schimmel (2):
psample: Fix user API breakage
drop_monitor: Perform cleanup upon probe registration failure
Imre Deak (1):
drm/i915: Fix the GT fence revocation runtime PM logic
Isaku Yamahata (1):
x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
J. Bruce Fields (1):
nfs: we don't support removing system.nfs4_acl
Jakub Kicinski (1):
ipv6: weaken the v4mapped source check
Jan Beulich (1):
xen-blkback: don't leak persistent grants from xen_blkbk_map()
Jan Kara (1):
ext4: add reclaim checks to xattr code
Jean-Philippe Brucker (1):
libbpf: Fix BTF dump of pointer-to-array-of-struct
JeongHyeon Lee (1):
dm verity: fix DM_VERITY_OPTS_MAX value
Jesse Brandeburg (1):
igb: check timestamp validity
Jia-Ju Bai (6):
net: tehuti: fix error return code in bdx_probe()
net: intel: iavf: fix error return code of iavf_init_get_resources()
net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
net: wan: fix error return code of uhdlc_init()
scsi: qedi: Fix error return code of qedi_alloc_global_queues()
scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
Jimmy Assarsson (1):
can: kvaser_pciefd: Always disable bus load reporting
Jiri Bohac (1):
net: check all name nodes in __dev_alloc_name
Jiri Slaby (1):
kbuild: dummy-tools: fix inverted tests for gcc
Joakim Zhang (1):
net: stmmac: fix dma physical address of descriptor when display ring
Johan Hovold (1):
net: cdc-phonet: fix data-interface release on probe failure
Johannes Berg (1):
mac80211: fix rate mask reset
Josh Poimboeuf (1):
static_call: Allow module use without exposing static_call_key
Julian Braha (1):
staging: rtl8192e: fix kconfig dependency on CRYPTO
Kenneth Feng (1):
drm/amd/pm: workaround for audio noise issue
Kumar Kartikeya Dwivedi (1):
libbpf: Use SOCK_CLOEXEC when opening the netlink socket
Li RongQing (1):
igb: avoid premature Rx buffer reuse
Louis Peens (3):
nfp: flower: fix unsupported pre_tunnel flows
nfp: flower: add ipv6 bit to pre_tunnel control message
nfp: flower: fix pre_tun mask id allocation
Lukasz Luba (1):
PM: EM: postpone creating the debugfs dir till fs_initcall
Lv Yunlong (2):
nvme-rdma: Fix a use after free in nvmet_rdma_write_data_done
net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
Maciej Fijalkowski (1):
veth: Store queue_mapping independently of XDP prog presence
Maor Dickman (1):
net/mlx5e: Don't match on Geneve options in case option masks are all zero
Marc Kleine-Budde (3):
can: isotp: isotp_setsockopt(): only allow to set low level TX flags for CAN-FD
can: isotp: TX-path: ensure that CAN frame flags are initialized
can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
Mark Brown (1):
kselftest: arm64: Fix exit code of sve-ptrace
Mark Pearson (1):
ALSA: hda: ignore invalid NHLT table
Mark Rutland (1):
arm64: stacktrace: don't trace arch_stack_walk()
Mark Tomlinson (3):
Revert "netfilter: x_tables: Switch synchronization to RCU"
netfilter: x_tables: Use correct memory barriers.
Revert "netfilter: x_tables: Update remaining dereference to RCU"
Markus Theil (1):
mac80211: fix double free in ibss_leave
Martin Willi (1):
can: dev: Move device back to init netns on owning netns delete
Masahiro Yamada (1):
kbuild: add image_name to no-sync-config-targets
Matthew Wilcox (Oracle) (1):
fs/cachefiles: Remove wait_bit_key layout dependency
Maxim Mikityanskiy (1):
net/mlx5e: When changing XDP program without reset, take refs for XSK RQs
Mian Yousaf Kaukab (1):
netsec: restore phy power state after controller reset
Miaohe Lin (1):
hugetlb_cgroup: fix imbalanced css_get and css_put pair for shared mappings
Michael Braun (1):
gianfar: fix jumbo packets+napi+rx overrun crash
Michael Ellerman (1):
powerpc/4xx: Fix build errors from mfdcr()
Michael Walle (1):
net: phy: introduce phydev->port
Mikulas Patocka (1):
dm ioctl: fix out of bounds array access when no devices
Mimi Zohar (1):
integrity: double check iint_cache was initialized
Muhammad Husaini Zulkifli (2):
igc: Fix Pause Frame Advertising
igc: Fix Supported Pause Frame Link Setting
Namhyung Kim (1):
libbpf: Fix error path in bpf_object__elf_init()
Nick Desaulniers (1):
gcov: fix clang-11+ support
Nicolas Ferre (1):
ARM: dts: at91: sam9x60: fix mux-mask to match product's datasheet
Nirmoy Das (1):
drm/amdgpu: fb BO should be ttm_bo_type_device
Nitin Rawat (1):
scsi: ufs: ufs-qcom: Disable interrupt in reset path
Oliver Hartkopp (1):
can: isotp: tx-path: zero initialize outgoing CAN frames
Ondrej Mosnacek (2):
selinux: don't log MAC_POLICY_LOAD record on failed policy load
selinux: fix variable scope issue in live sidtab conversion
Ong Boon Leong (1):
net: phylink: Fix phylink_err() function name error in phylink_major_config
Pablo Neira Ayuso (2):
netfilter: nftables: report EOPNOTSUPP on unsupported flowtable flags
netfilter: nftables: allow to update flowtable flags
Paul Cercueil (2):
net: davicom: Use platform_get_irq_optional()
irqchip/ingenic: Add support for the JZ4760
Paulo Alcantara (1):
cifs: change noisy error message to FYI
Pavel Begunkov (1):
io_uring: fix provide_buffers sign extension
Pavel Tatashin (1):
arm64: kdump: update ppos when reading elfcorehdr
Peter Zijlstra (4):
u64_stats,lockdep: Fix u64_stats_init() vs lockdep
static_call: Pull some static_call declarations to the type headers
static_call: Fix the module key fixup
static_call: Fix static_call_set_init()
Phillip Lougher (1):
squashfs: fix xattr id and id lookup sanity checks
Potnuri Bharat Teja (1):
RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server
Rafael J. Wysocki (2):
PM: runtime: Defer suspending suppliers
ACPI: scan: Rearrange memory allocation in acpi_device_add()
Rakesh Babu (1):
octeontx2-af: Formatting debugfs entry rsrc_alloc.
Rob Gardner (1):
sparc64: Fix opcode filtering in handling of no fault loads
Robert Hancock (3):
net: axienet: Properly handle PCS/PMA PHY for 1000BaseX mode
net: axienet: Fix probe error cleanup
net: phy: broadcom: Set proper 1000BaseX/SGMII interface mode for BCM54616S
Roger Pau Monne (2):
xen/x86: make XEN_BALLOON_MEMORY_HOTPLUG_LIMIT depend on MEMORY_HOTPLUG
Revert "xen: fix p2m size in dom0 for disabled memory hotplug case"
Sabyrzhan Tasbolatov (1):
fs/ext4: fix integer overflow in s_log_groups_per_flex
Sasha Levin (1):
bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
Sasha Neftin (1):
igc: reinit_locked() should be called with rtnl_lock
Sean Christopherson (2):
KVM: x86: Protect userspace MSR filter with SRCU, and set atomically-ish
mm/mmu_notifiers: ensure range_end() is paired with range_start()
Sean Nyekjaer (1):
squashfs: fix inode lookup sanity checks
Sergei Trofimovich (2):
ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
Shannon Nelson (1):
ionic: linearize tso skb with too many frags
Shin'ichiro Kawasaki (1):
dm table: Fix zoned model check and zone sectors check
Shyam Prasad N (1):
cifs: Adjust key sizes and key generation routines for AES256 encryption
Stanislaw Kardach (1):
octeontx2-af: Modify default KEX profile to extract TX packet fields
Stephane Grosjean (1):
can: peak_usb: add forgotten supported devices
Steve French (1):
smb3: fix cached file size problems in duplicate extents (reflink)
Subbaraya Sundeep (1):
octeontx2-af: Remove TOS field from MKEX TX
Sudeep Holla (1):
cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
Sung Lee (1):
drm/amd/display: Revert dram_clock_change_latency for DCN2.1
Tal Lossos (1):
bpf: Change inode_storage's lookup_elem return value from NULL to -EBADF
Tariq Toukan (1):
net/mlx5e: RX, Mind the MPWQE gaps when calculating offsets
Thomas Gleixner (1):
locking/mutex: Fix non debug version of mutex_lock_io_nested()
Thomas Hebb (1):
z3fold: prevent reclaim/free race for headless pages
Timo Rothenpieler (1):
nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
Tomer Tayar (1):
habanalabs: Call put_pid() when releasing control device
Tong Zhang (6):
atm: eni: dont release is never initialized
atm: lanai: dont run lanai_dev_close if not open
atm: uPD98402: fix incorrect allocation
atm: idt77252: fix null-ptr-dereference
can: c_can_pci: c_can_pci_remove(): fix use-after-free
can: c_can: move runtime PM enable/disable to c_can_platform
Tony Lindgren (2):
ARM: OMAP2+: Fix smartreflex init regression after dropping legacy data
soc: ti: omap-prm: Fix occasional abort on reset deassert for dra7 iva
Torin Cooper-Bennun (2):
can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
Vegard Nossum (1):
ACPICA: Always create namespace nodes using acpi_ns_create_node()
Vitaly Lifshits (1):
e1000e: add rtnl_lock() to e1000_reset_task
Vladimir Oltean (1):
net: bridge: don't notify switchdev for local FDB addresses
Wei Wang (1):
ipv6: fix suspecious RCU usage warning
Wei Yongjun (1):
umem: fix error return code in mm_pci_probe()
Xie He (1):
net: hdlc_x25: Prevent racing between "x25_close" and "x25_xmit"/"x25_rx"
Xunlei Pang (1):
blk-cgroup: Fix the recursive blkg rwstat
Yang Li (1):
gpiolib: acpi: Add missing IRQF_ONESHOT
Yinjun Zhang (1):
netfilter: flowtable: Make sure GC works periodically in idle system
Zhou Guanghui (2):
mm/memcg: rename mem_cgroup_split_huge_fixup to split_page_memcg and add nr_pages argument
mm/memcg: set memcg when splitting page
Zqiang (1):
bpf: Fix umd memory leak in copy_process()
dillon min (1):
ARM: dts: imx6ull: fix ubi filesystem mount failed
satya priya (1):
regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
wenxu (1):
net/sched: cls_flower: fix only mask bit check in the validate_ct_state
^ permalink raw reply [relevance 1%]
* Linux 5.4.109
@ 2021-03-30 13:36 2% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-30 13:36 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.4.109 kernel.
All users of the 5.4 kernel series must upgrade.
The updated 5.4.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.4.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Makefile | 2
arch/arm/boot/dts/at91-sama5d27_som1.dtsi | 4
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 1
arch/arm64/kernel/crash_dump.c | 2
arch/ia64/include/asm/syscall.h | 2
arch/ia64/kernel/ptrace.c | 24 ++-
arch/powerpc/include/asm/dcr-native.h | 8 -
arch/sparc/kernel/traps_64.c | 13 -
arch/x86/mm/mem_encrypt.c | 2
block/blk-merge.c | 8 +
block/genhd.c | 4
drivers/acpi/internal.h | 6
drivers/acpi/scan.c | 88 +++++++------
drivers/acpi/video_detect.c | 1
drivers/atm/eni.c | 3
drivers/atm/idt77105.c | 4
drivers/atm/lanai.c | 5
drivers/atm/uPD98402.c | 2
drivers/base/power/runtime.c | 45 +++++-
drivers/block/xen-blkback/blkback.c | 2
drivers/bus/omap_l3_noc.c | 4
drivers/cpufreq/cpufreq-dt-platdev.c | 2
drivers/gpio/gpiolib-acpi.c | 2
drivers/gpu/drm/Kconfig | 1
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2
drivers/gpu/drm/msm/msm_drv.c | 4
drivers/infiniband/hw/cxgb4/cm.c | 4
drivers/irqchip/irq-ingenic-tcu.c | 1
drivers/irqchip/irq-ingenic.c | 1
drivers/md/dm-ioctl.c | 2
drivers/md/dm-verity-target.c | 2
drivers/misc/habanalabs/device.c | 2
drivers/net/can/c_can/c_can.c | 24 ---
drivers/net/can/c_can/c_can_pci.c | 3
drivers/net/can/c_can/c_can_platform.c | 6
drivers/net/can/dev.c | 1
drivers/net/can/flexcan.c | 8 +
drivers/net/can/kvaser_pciefd.c | 4
drivers/net/can/m_can/m_can.c | 5
drivers/net/dsa/b53/b53_common.c | 14 +-
drivers/net/dsa/bcm_sf2.c | 6
drivers/net/ethernet/davicom/dm9000.c | 2
drivers/net/ethernet/faraday/ftgmac100.c | 1
drivers/net/ethernet/freescale/fec_ptp.c | 7 +
drivers/net/ethernet/freescale/gianfar.c | 15 ++
drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4
drivers/net/ethernet/intel/e1000e/82571.c | 2
drivers/net/ethernet/intel/e1000e/netdev.c | 6
drivers/net/ethernet/intel/iavf/iavf_main.c | 3
drivers/net/ethernet/intel/igc/igc_ethtool.c | 7 -
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 4
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c | 4
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 6
drivers/net/ethernet/netronome/nfp/flower/metadata.c | 24 ++-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 3
drivers/net/ethernet/socionext/netsec.c | 9 -
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2
drivers/net/ethernet/sun/niu.c | 2
drivers/net/ethernet/tehuti/tehuti.c | 1
drivers/net/usb/cdc-phonet.c | 2
drivers/net/usb/r8152.c | 40 +----
drivers/net/veth.c | 3
drivers/net/wan/fsl_ucc_hdlc.c | 8 -
drivers/nvme/host/core.c | 1
drivers/nvme/host/fc.c | 2
drivers/nvme/host/pci.c | 1
drivers/platform/x86/intel-vbtn.c | 12 +
drivers/regulator/qcom-rpmh-regulator.c | 4
drivers/scsi/mpt3sas/mpt3sas_base.c | 8 -
drivers/scsi/qedi/qedi_main.c | 1
drivers/scsi/qla2xxx/qla_target.c | 13 -
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4
fs/cifs/smb2pdu.c | 6
fs/cifs/transport.c | 2
fs/ext4/xattr.c | 4
fs/hugetlbfs/inode.c | 4
fs/nfs/Kconfig | 2
fs/nfs/nfs3xdr.c | 3
fs/nfs/nfs4proc.c | 3
fs/squashfs/export.c | 8 -
fs/squashfs/id.c | 6
fs/squashfs/squashfs_fs.h | 1
fs/squashfs/xattr_id.c | 6
include/acpi/acpi_bus.h | 1
include/linux/bpf.h | 9 -
include/linux/hugetlb.h | 2
include/linux/if_macvlan.h | 3
include/linux/mm.h | 15 ++
include/linux/mutex.h | 2
include/linux/netfilter/x_tables.h | 7 -
include/linux/u64_stats_sync.h | 7 -
include/net/inet_connection_sock.h | 2
include/net/nexthop.h | 24 +++
include/net/red.h | 10 +
include/net/rtnetlink.h | 2
kernel/gcov/clang.c | 69 ++++++++++
kernel/power/energy_model.c | 2
mm/hugetlb.c | 10 -
mm/userfaultfd.c | 2
net/core/dev.c | 2
net/ipv4/inet_connection_sock.c | 7 -
net/ipv4/netfilter/arp_tables.c | 16 +-
net/ipv4/netfilter/ip_tables.c | 16 +-
net/ipv4/tcp_minisocks.c | 7 -
net/ipv6/ip6_fib.c | 2
net/ipv6/netfilter/ip6_tables.c | 16 +-
net/mac80211/cfg.c | 4
net/mac80211/ibss.c | 2
net/netfilter/nf_conntrack_netlink.c | 1
net/netfilter/x_tables.c | 49 +++++--
net/qrtr/qrtr.c | 5
net/sched/sch_choke.c | 7 -
net/sched/sch_gred.c | 2
net/sched/sch_red.c | 7 -
net/sched/sch_sfq.c | 2
security/integrity/iint.c | 8 +
sound/hda/intel-nhlt.c | 5
tools/lib/bpf/Makefile | 2
tools/lib/bpf/btf_dump.c | 2
tools/lib/bpf/netlink.c | 2
tools/perf/util/auxtrace.c | 4
tools/testing/selftests/bpf/progs/test_tunnel_kern.c | 6
tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh | 2
128 files changed, 621 insertions(+), 304 deletions(-)
Adrian Hunter (1):
perf auxtrace: Fix auxtrace queue conflict
Alexander Ovechkin (1):
tcp: relookup sock for RST+ACK packets handled by obsolete req sock
Andrey Konovalov (1):
kasan: fix per-page tags for non-page_alloc pages
Andy Shevchenko (1):
ACPI: scan: Use unique number for instance_no
Angelo Dureghello (1):
can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
Aurelien Aptel (1):
cifs: ask for more credit on async read/write code paths
Aya Levin (1):
net/mlx5e: Fix error path for ethtool set-priv-flag
Bart Van Assche (1):
scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
Chris Chiu (1):
ACPI: video: Add missing callback back for Sony VPCEH3U1E
Christian König (1):
drm/radeon: fix AGP dependency
Claudiu Beznea (1):
ARM: dts: at91-sama5d27_som1: fix phy address to 7
Corentin Labbe (1):
net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
Daniel Wagner (1):
block: Suppress uevent for hidden device when removed
David Jeffery (1):
block: recalculate segment count for multi-segment discards correctly
Denis Efremov (1):
sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
Dinghao Liu (2):
ixgbe: Fix memleak in ixgbe_configure_clsu32
e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
Dmitry Baryshkov (1):
drm/msm: fix shutdown hook in case GPU components failed to bind
Dmitry Monakhov (1):
nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
Dylan Hung (1):
ftgmac100: Restart MAC HW once
Eric Dumazet (3):
macvlan: macvlan_count_rx() needs to be aware of preemption
net: sched: validate stab values
net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
Florian Fainelli (2):
net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
net: dsa: b53: VLAN filtering is global to all users
Florian Westphal (1):
netfilter: ctnetlink: fix dump of the expect mask attribute
Frank Sorenson (1):
NFS: Correct size calculation for create reply length
Geetha sowjanya (1):
octeontx2-af: Fix irq free in rvu teardown
Georgi Valkov (1):
libbpf: Fix INSTALL flag order
Greg Kroah-Hartman (1):
Linux 5.4.109
Grygorii Strashko (1):
bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
Hangbin Liu (2):
selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
Hannes Reinecke (2):
nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
Hans de Goede (1):
platform/x86: intel-vbtn: Stop reporting SW_DOCK events
Hariprasad Kelam (1):
octeontx2-af: fix infinite loop in unmapping NPC counter
Hayes Wang (2):
Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
r8152: limit the RX buffer size of RTL8153A for USB 2.0
Heiko Thiery (1):
net: fec: ptp: avoid register access when ipg clock is disabled
Horia Geantă (3):
arm64: dts: ls1046a: mark crypto engine dma coherent
arm64: dts: ls1012a: mark crypto engine dma coherent
arm64: dts: ls1043a: mark crypto engine dma coherent
Isaku Yamahata (1):
x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
J. Bruce Fields (1):
nfs: we don't support removing system.nfs4_acl
Jan Beulich (1):
xen-blkback: don't leak persistent grants from xen_blkbk_map()
Jan Kara (1):
ext4: add reclaim checks to xattr code
Jean-Philippe Brucker (1):
libbpf: Fix BTF dump of pointer-to-array-of-struct
JeongHyeon Lee (1):
dm verity: fix DM_VERITY_OPTS_MAX value
Jia-Ju Bai (6):
net: tehuti: fix error return code in bdx_probe()
net: intel: iavf: fix error return code of iavf_init_get_resources()
net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
net: wan: fix error return code of uhdlc_init()
scsi: qedi: Fix error return code of qedi_alloc_global_queues()
scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
Jimmy Assarsson (1):
can: kvaser_pciefd: Always disable bus load reporting
Johan Hovold (1):
net: cdc-phonet: fix data-interface release on probe failure
Johannes Berg (1):
mac80211: fix rate mask reset
Kumar Kartikeya Dwivedi (1):
libbpf: Use SOCK_CLOEXEC when opening the netlink socket
Louis Peens (1):
nfp: flower: fix pre_tun mask id allocation
Lukasz Luba (1):
PM: EM: postpone creating the debugfs dir till fs_initcall
Lv Yunlong (1):
net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
Maciej Fijalkowski (1):
veth: Store queue_mapping independently of XDP prog presence
Maor Dickman (1):
net/mlx5e: Don't match on Geneve options in case option masks are all zero
Marc Kleine-Budde (1):
can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
Mark Pearson (1):
ALSA: hda: ignore invalid NHLT table
Mark Tomlinson (3):
Revert "netfilter: x_tables: Switch synchronization to RCU"
netfilter: x_tables: Use correct memory barriers.
Revert "netfilter: x_tables: Update remaining dereference to RCU"
Markus Theil (1):
mac80211: fix double free in ibss_leave
Martin Willi (1):
can: dev: Move device back to init netns on owning netns delete
Mian Yousaf Kaukab (1):
netsec: restore phy power state after controller reset
Michael Braun (1):
gianfar: fix jumbo packets+napi+rx overrun crash
Michael Ellerman (1):
powerpc/4xx: Fix build errors from mfdcr()
Mike Kravetz (1):
hugetlbfs: hugetlb_fault_mutex_hash() cleanup
Mikulas Patocka (1):
dm ioctl: fix out of bounds array access when no devices
Mimi Zohar (1):
integrity: double check iint_cache was initialized
Muhammad Husaini Zulkifli (2):
igc: Fix Pause Frame Advertising
igc: Fix Supported Pause Frame Link Setting
Nick Desaulniers (1):
gcov: fix clang-11+ support
Nirmoy Das (1):
drm/amdgpu: fb BO should be ttm_bo_type_device
Paul Cercueil (2):
net: davicom: Use platform_get_irq_optional()
irqchip/ingenic: Add support for the JZ4760
Paulo Alcantara (1):
cifs: change noisy error message to FYI
Pavel Tatashin (1):
arm64: kdump: update ppos when reading elfcorehdr
Peter Zijlstra (1):
u64_stats,lockdep: Fix u64_stats_init() vs lockdep
Phillip Lougher (1):
squashfs: fix xattr id and id lookup sanity checks
Potnuri Bharat Teja (1):
RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server
Rafael J. Wysocki (2):
PM: runtime: Defer suspending suppliers
ACPI: scan: Rearrange memory allocation in acpi_device_add()
Rob Gardner (1):
sparc64: Fix opcode filtering in handling of no fault loads
Sasha Levin (1):
bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
Sean Nyekjaer (1):
squashfs: fix inode lookup sanity checks
Sergei Trofimovich (2):
ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
Stephane Grosjean (1):
can: peak_usb: add forgotten supported devices
Sudeep Holla (1):
cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
Sung Lee (1):
drm/amd/display: Revert dram_clock_change_latency for DCN2.1
Thomas Gleixner (1):
locking/mutex: Fix non debug version of mutex_lock_io_nested()
Timo Rothenpieler (1):
nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
Tomer Tayar (1):
habanalabs: Call put_pid() when releasing control device
Tong Zhang (6):
atm: eni: dont release is never initialized
atm: lanai: dont run lanai_dev_close if not open
atm: uPD98402: fix incorrect allocation
atm: idt77252: fix null-ptr-dereference
can: c_can_pci: c_can_pci_remove(): fix use-after-free
can: c_can: move runtime PM enable/disable to c_can_platform
Torin Cooper-Bennun (2):
can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
Vitaly Lifshits (1):
e1000e: add rtnl_lock() to e1000_reset_task
Wei Wang (1):
ipv6: fix suspecious RCU usage warning
Yang Li (1):
gpiolib: acpi: Add missing IRQF_ONESHOT
satya priya (1):
regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
^ permalink raw reply [relevance 2%]
* Linux 5.11.11
@ 2021-03-30 13:36 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-30 13:36 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.11.11 kernel.
All users of the 5.11 kernel series must upgrade.
The updated 5.11.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.11.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/virt/kvm/api.rst | 6
Makefile | 5
arch/arm/boot/dts/at91-sam9x60ek.dts | 8
arch/arm/boot/dts/at91-sama5d27_som1.dtsi | 4
arch/arm/boot/dts/imx6ull-myir-mys-6ulx-eval.dts | 1
arch/arm/boot/dts/sam9x60.dtsi | 9
arch/arm/mach-omap2/sr_device.c | 75 ++-
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 1
arch/arm64/kernel/crash_dump.c | 2
arch/arm64/kernel/stacktrace.c | 9
arch/ia64/include/asm/syscall.h | 2
arch/ia64/kernel/ptrace.c | 24 -
arch/powerpc/include/asm/dcr-native.h | 8
arch/sparc/kernel/traps_64.c | 13
arch/x86/include/asm/kvm_host.h | 14
arch/x86/include/asm/static_call.h | 7
arch/x86/include/asm/xen/page.h | 12
arch/x86/kvm/x86.c | 109 ++---
arch/x86/mm/mem_encrypt.c | 2
arch/x86/net/bpf_jit_comp.c | 27 +
arch/x86/xen/p2m.c | 7
arch/x86/xen/setup.c | 16
block/blk-cgroup-rwstat.c | 3
block/blk-merge.c | 8
block/blk-zoned.c | 2
block/genhd.c | 4
drivers/acpi/acpica/nsaccess.c | 3
drivers/acpi/internal.h | 6
drivers/acpi/scan.c | 88 ++--
drivers/acpi/video_detect.c | 1
drivers/atm/eni.c | 3
drivers/atm/idt77105.c | 4
drivers/atm/lanai.c | 5
drivers/atm/uPD98402.c | 2
drivers/base/power/runtime.c | 45 +-
drivers/block/umem.c | 5
drivers/block/xen-blkback/blkback.c | 2
drivers/bus/omap_l3_noc.c | 4
drivers/clk/qcom/gcc-sc7180.c | 4
drivers/cpufreq/cpufreq-dt-platdev.c | 2
drivers/gpio/gpiolib-acpi.c | 2
drivers/gpu/drm/Kconfig | 1
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1
drivers/gpu/drm/amd/display/dc/dc.h | 1
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 11
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h | 6
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 7
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 1
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 6
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c | 3
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c | 1
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c | 1
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 31 +
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c | 96 ++++
drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 2
drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 54 ++
drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 74 ++-
drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 24 +
drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 25 +
drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2
drivers/gpu/drm/i915/display/intel_vdsc.c | 10
drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 13
drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +
drivers/gpu/drm/i915/intel_runtime_pm.h | 5
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 2
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 6
drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c | 5
drivers/gpu/drm/msm/msm_drv.c | 12
drivers/gpu/drm/nouveau/dispnv50/disp.c | 13
drivers/infiniband/hw/cxgb4/cm.c | 4
drivers/irqchip/irq-ingenic-tcu.c | 1
drivers/irqchip/irq-ingenic.c | 1
drivers/md/dm-ioctl.c | 2
drivers/md/dm-table.c | 33 +
drivers/md/dm-verity-target.c | 2
drivers/md/dm-zoned-target.c | 2
drivers/md/dm.c | 5
drivers/mfd/intel_quark_i2c_gpio.c | 6
drivers/misc/habanalabs/common/device.c | 40 +
drivers/misc/habanalabs/common/habanalabs_ioctl.c | 12
drivers/net/can/c_can/c_can.c | 24 -
drivers/net/can/c_can/c_can_pci.c | 3
drivers/net/can/c_can/c_can_platform.c | 6
drivers/net/can/dev.c | 1
drivers/net/can/flexcan.c | 8
drivers/net/can/kvaser_pciefd.c | 4
drivers/net/can/m_can/m_can.c | 5
drivers/net/dsa/b53/b53_common.c | 14
drivers/net/dsa/bcm_sf2.c | 6
drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 2
drivers/net/ethernet/davicom/dm9000.c | 2
drivers/net/ethernet/faraday/ftgmac100.c | 1
drivers/net/ethernet/freescale/enetc/enetc_hw.h | 2
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6
drivers/net/ethernet/freescale/fec_ptp.c | 7
drivers/net/ethernet/freescale/gianfar.c | 15
drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4
drivers/net/ethernet/intel/e1000e/82571.c | 2
drivers/net/ethernet/intel/e1000e/netdev.c | 6
drivers/net/ethernet/intel/iavf/iavf_main.c | 3
drivers/net/ethernet/intel/ice/ice_base.c | 6
drivers/net/ethernet/intel/ice/ice_xsk.c | 10
drivers/net/ethernet/intel/igb/igb.h | 4
drivers/net/ethernet/intel/igb/igb_main.c | 33 -
drivers/net/ethernet/intel/igb/igb_ptp.c | 31 +
drivers/net/ethernet/intel/igc/igc.h | 2
drivers/net/ethernet/intel/igc/igc_ethtool.c | 7
drivers/net/ethernet/intel/igc/igc_main.c | 9
drivers/net/ethernet/intel/igc/igc_ptp.c | 72 +--
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6
drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h | 2
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 6
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c | 48 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5
drivers/net/ethernet/mellanox/mlx5/core/en.h | 7
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 3
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c | 4
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 11
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 21
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 57 ++
drivers/net/ethernet/netronome/nfp/flower/metadata.c | 24 -
drivers/net/ethernet/netronome/nfp/flower/offload.c | 18
drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c | 15
drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 13
drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 3
drivers/net/ethernet/realtek/r8169_main.c | 6
drivers/net/ethernet/socionext/netsec.c | 9
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 50 +-
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 9
drivers/net/ethernet/stmicro/stmmac/hwif.h | 3
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 9
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 57 +-
drivers/net/ethernet/sun/niu.c | 2
drivers/net/ethernet/tehuti/tehuti.c | 1
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 35 +
drivers/net/ipa/ipa_qmi.c | 2
drivers/net/phy/broadcom.c | 147 ++++--
drivers/net/phy/dp83822.c | 3
drivers/net/phy/dp83869.c | 4
drivers/net/phy/lxt.c | 1
drivers/net/phy/marvell.c | 1
drivers/net/phy/marvell10g.c | 2
drivers/net/phy/micrel.c | 14
drivers/net/phy/phy.c | 2
drivers/net/phy/phy_device.c | 9
drivers/net/phy/phylink.c | 2
drivers/net/usb/cdc-phonet.c | 2
drivers/net/usb/r8152.c | 40 -
drivers/net/veth.c | 3
drivers/net/wan/fsl_ucc_hdlc.c | 8
drivers/net/wan/hdlc_x25.c | 42 +
drivers/net/wireless/mediatek/mt76/dma.c | 15
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 10
drivers/nvme/host/core.c | 15
drivers/nvme/host/fc.c | 3
drivers/nvme/host/pci.c | 1
drivers/nvme/target/rdma.c | 5
drivers/platform/x86/dell-wmi-sysman/enum-attributes.c | 3
drivers/platform/x86/dell-wmi-sysman/int-attributes.c | 3
drivers/platform/x86/dell-wmi-sysman/passobj-attributes.c | 3
drivers/platform/x86/dell-wmi-sysman/string-attributes.c | 3
drivers/platform/x86/dell-wmi-sysman/sysman.c | 84 +--
drivers/platform/x86/intel-vbtn.c | 12
drivers/platform/x86/intel_pmt_crashlog.c | 13
drivers/regulator/qcom-rpmh-regulator.c | 6
drivers/scsi/mpt3sas/mpt3sas_base.c | 8
drivers/scsi/qedi/qedi_main.c | 1
drivers/scsi/qla2xxx/qla_target.c | 13
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4
drivers/scsi/ufs/ufs-qcom.c | 10
drivers/soc/ti/omap_prm.c | 8
drivers/staging/rtl8192e/Kconfig | 1
drivers/xen/Kconfig | 4
fs/btrfs/dev-replace.c | 3
fs/btrfs/disk-io.c | 19
fs/btrfs/inode.c | 14
fs/btrfs/qgroup.c | 12
fs/btrfs/volumes.c | 3
fs/cachefiles/rdwr.c | 7
fs/cifs/cifsglob.h | 4
fs/cifs/cifspdu.h | 5
fs/cifs/smb2glob.h | 1
fs/cifs/smb2ops.c | 27 -
fs/cifs/smb2pdu.c | 6
fs/cifs/smb2transport.c | 37 +
fs/cifs/transport.c | 2
fs/ext4/mballoc.c | 11
fs/ext4/xattr.c | 4
fs/gfs2/log.c | 4
fs/gfs2/trans.c | 2
fs/io_uring.c | 14
fs/nfs/Kconfig | 2
fs/nfs/nfs3xdr.c | 3
fs/nfs/nfs4proc.c | 3
fs/squashfs/export.c | 8
fs/squashfs/id.c | 6
fs/squashfs/squashfs_fs.h | 1
fs/squashfs/xattr_id.c | 6
include/acpi/acpi_bus.h | 1
include/asm-generic/vmlinux.lds.h | 5
include/linux/bpf.h | 33 +
include/linux/brcmphy.h | 4
include/linux/device-mapper.h | 15
include/linux/hugetlb_cgroup.h | 15
include/linux/if_macvlan.h | 3
include/linux/memblock.h | 4
include/linux/mm.h | 18
include/linux/mm_types.h | 1
include/linux/mmu_notifier.h | 10
include/linux/mutex.h | 2
include/linux/netfilter/x_tables.h | 7
include/linux/pagemap.h | 1
include/linux/phy.h | 2
include/linux/static_call.h | 43 -
include/linux/static_call_types.h | 50 ++
include/linux/u64_stats_sync.h | 7
include/linux/usermode_driver.h | 1
include/net/dst.h | 11
include/net/inet_connection_sock.h | 2
include/net/netfilter/nf_tables.h | 3
include/net/nexthop.h | 24 +
include/net/red.h | 10
include/net/rtnetlink.h | 2
include/uapi/linux/psample.h | 5
kernel/bpf/bpf_inode_storage.c | 2
kernel/bpf/bpf_struct_ops.c | 2
kernel/bpf/core.c | 4
kernel/bpf/preload/bpf_preload_kern.c | 19
kernel/bpf/syscall.c | 5
kernel/bpf/trampoline.c | 218 +++++++---
kernel/bpf/verifier.c | 4
kernel/fork.c | 8
kernel/gcov/clang.c | 69 +++
kernel/power/energy_model.c | 2
kernel/static_call.c | 71 ++-
kernel/trace/ftrace.c | 43 +
kernel/usermode_driver.c | 21
mm/highmem.c | 4
mm/hugetlb.c | 41 +
mm/hugetlb_cgroup.c | 10
mm/mmu_notifier.c | 23 +
mm/z3fold.c | 16
net/bridge/br_switchdev.c | 2
net/can/isotp.c | 18
net/core/dev.c | 14
net/core/drop_monitor.c | 23 +
net/core/dst.c | 59 +-
net/core/flow_dissector.c | 2
net/dccp/ipv6.c | 5
net/ipv4/inet_connection_sock.c | 7
net/ipv4/netfilter/arp_tables.c | 16
net/ipv4/netfilter/ip_tables.c | 16
net/ipv4/route.c | 45 --
net/ipv4/tcp_minisocks.c | 7
net/ipv6/ip6_fib.c | 2
net/ipv6/ip6_input.c | 10
net/ipv6/netfilter/ip6_tables.c | 16
net/ipv6/route.c | 36 -
net/ipv6/tcp_ipv6.c | 5
net/mac80211/cfg.c | 4
net/mac80211/ibss.c | 2
net/mac80211/mlme.c | 2
net/mac80211/util.c | 2
net/mptcp/options.c | 24 -
net/mptcp/subflow.c | 5
net/netfilter/nf_conntrack_netlink.c | 1
net/netfilter/nf_flow_table_core.c | 2
net/netfilter/nf_tables_api.c | 19
net/netfilter/x_tables.c | 49 +-
net/qrtr/qrtr.c | 5
net/sched/cls_flower.c | 2
net/sched/sch_choke.c | 7
net/sched/sch_gred.c | 2
net/sched/sch_red.c | 7
net/sched/sch_sfq.c | 2
net/sctp/output.c | 7
net/sctp/outqueue.c | 7
net/tipc/node.c | 11
net/vmw_vsock/af_vsock.c | 1
scripts/dummy-tools/gcc | 5
security/integrity/iint.c | 8
security/selinux/include/security.h | 15
security/selinux/selinuxfs.c | 13
security/selinux/ss/services.c | 63 +-
sound/hda/intel-nhlt.c | 5
tools/include/linux/static_call_types.h | 50 ++
tools/lib/bpf/Makefile | 2
tools/lib/bpf/btf_dump.c | 2
tools/lib/bpf/libbpf.c | 3
tools/lib/bpf/netlink.c | 2
tools/objtool/check.c | 17
tools/perf/util/auxtrace.c | 4
tools/perf/util/synthetic-events.c | 9
tools/testing/kunit/configs/broken_on_uml.config | 2
tools/testing/selftests/arm64/fp/sve-ptrace.c | 2
tools/testing/selftests/bpf/prog_tests/fexit_sleep.c | 82 +++
tools/testing/selftests/bpf/progs/fexit_sleep.c | 31 +
tools/testing/selftests/bpf/progs/test_tunnel_kern.c | 6
tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh | 2
tools/testing/selftests/net/reuseaddr_ports_exhausted.c | 32 -
309 files changed, 3092 insertions(+), 1105 deletions(-)
Adrian Hunter (1):
perf auxtrace: Fix auxtrace queue conflict
Alaa Hleihel (1):
net/mlx5e: Allow to match on MPLS parameters only for MPLS over UDP
Alex Deucher (2):
drm/amdgpu/display: restore AUX_DPHY_TX_CONTROL for DCN2.x
drm/amdgpu: Add additional Sienna Cichlid PCI ID
Alex Elder (1):
net: ipa: terminate message handler arrays
Alex Marginean (1):
net: enetc: set MAC RX FIFO to recommended value
Alexander Lobakin (1):
flow_dissector: fix byteorder of dissected ICMP ID
Alexander Ovechkin (1):
tcp: relookup sock for RST+ACK packets handled by obsolete req sock
Alexei Starovoitov (4):
bpf: Dont allow vmlinux BTF to be used in map_create and prog_load.
ftrace: Fix modify_ftrace_direct.
bpf: Fix fexit trampoline.
selftest/bpf: Add a test to check trampoline freeing logic.
Andre Guedes (1):
igc: Fix igc_ptp_rx_pktstamp()
Andrey Konovalov (1):
kasan: fix per-page tags for non-page_alloc pages
Andy Shevchenko (2):
mfd: intel_quark_i2c_gpio: Revert "Constify static struct resources"
ACPI: scan: Use unique number for instance_no
Angelo Dureghello (1):
can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
Arnd Bergmann (1):
ch_ktls: fix enum-conversion warning
Aurelien Aptel (1):
cifs: ask for more credit on async read/write code paths
Aya Levin (2):
net/mlx5e: Set PTP channel pointer explicitly to NULL
net/mlx5e: Fix error path for ethtool set-priv-flag
Bart Van Assche (1):
scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
Bob Peterson (1):
gfs2: fix use-after-free in trans_drain
Brian Norris (1):
mac80211: Allow HE operation to be longer than expected.
Carlos Llamas (1):
selftests/net: fix warnings on reuseaddr_ports_exhausted
Chaitanya Kulkarni (1):
nvme-core: check ctrl css before setting up zns
Chris Chiu (1):
ACPI: video: Add missing callback back for Sony VPCEH3U1E
Christian König (1):
drm/radeon: fix AGP dependency
Christoph Hellwig (1):
nvme: fix the nsid value to print in nvme_validate_or_alloc_ns
Claudiu Beznea (1):
ARM: dts: at91-sama5d27_som1: fix phy address to 7
Colin Ian King (1):
octeontx2-af: Fix memory leak of object buf
Corentin Labbe (1):
net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
Damien Le Moal (1):
block: Fix REQ_OP_ZONE_RESET_ALL handling
Daniel Borkmann (2):
net: Consolidate common blackhole dst ops
net, bpf: Fix ip6ip6 crash with collect_md populated skbs
Daniel Vetter (1):
drm/etnaviv: Use FOLL_FORCE for userptr
Daniel Wagner (1):
block: Suppress uevent for hidden device when removed
David Brazdil (1):
selinux: vsock: Set SID for socket returned by accept()
David E. Box (1):
platform/x86: intel_pmt_crashlog: Fix incorrect macros
David Gow (1):
kunit: tool: Disable PAGE_POISONING under --alltests
David Jeffery (1):
block: recalculate segment count for multi-segment discards correctly
Davide Caratti (1):
mptcp: fix ADD_ADDR HMAC in case port is specified
Denis Efremov (1):
sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
Dillon Varone (1):
drm/amd/display: Enabled pipe harvesting in dcn30
Dima Chumak (1):
net/mlx5e: Offload tuple rewrite for non-CT flows
Dinghao Liu (2):
ixgbe: Fix memleak in ixgbe_configure_clsu32
e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
Dmitry Baryshkov (2):
drm/msm/dsi: fix check-before-set in the 7nm dsi_pll code
drm/msm: fix shutdown hook in case GPU components failed to bind
Dmitry Monakhov (1):
nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
Douglas Anderson (1):
clk: qcom: gcc-sc7180: Use floor ops for the correct sdcc1 clk
Dylan Hung (1):
ftgmac100: Restart MAC HW once
Eric Dumazet (4):
macvlan: macvlan_count_rx() needs to be aware of preemption
net: sched: validate stab values
net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
tipc: better validate user input in tipc_nl_retrieve_key()
Fabio Estevam (1):
drm/msm: Fix suspend/resume on i.MX5
Federico Pellegrin (1):
ARM: dts: at91: sam9x60: fix mux-mask for PA7 so it can be set to A, B and C
Felix Fietkau (2):
mt76: fix tx skb error handling in mt76_dma_tx_queue_skb
mt76: mt7915: only modify tx buffer list after allocating tx token id
Fenghua Yu (1):
mm/fork: clear PASID for new mm
Filipe Manana (2):
btrfs: fix sleep while in non-sleep context during qgroup removal
btrfs: fix subvolume/snapshot deletion not triggered on mount
Florian Fainelli (5):
net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
net: phy: broadcom: Add power down exit reset state delay
net: phy: broadcom: Avoid forward for bcm54xx_config_clock_delay()
net: phy: broadcom: Fix RGMII delays for BCM50160 and BCM50610M
net: dsa: b53: VLAN filtering is global to all users
Florian Westphal (1):
netfilter: ctnetlink: fix dump of the expect mask attribute
Frank Sorenson (1):
NFS: Correct size calculation for create reply length
Geetha sowjanya (2):
octeontx2-af: Fix irq free in rvu teardown
octeontx2-pf: Clear RSS enable flag on interace down
Georgi Valkov (1):
libbpf: Fix INSTALL flag order
Greg Kroah-Hartman (1):
Linux 5.11.11
Grygorii Strashko (1):
bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
Hangbin Liu (2):
selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
Hannes Reinecke (4):
nvme: simplify error logic in nvme_validate_ns()
nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
nvme-fc: set NVME_REQ_CANCELLED in nvme_fc_terminate_exchange()
nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
Hans de Goede (8):
platform/x86: intel-vbtn: Stop reporting SW_DOCK events
platform/x86: dell-wmi-sysman: Fix crash caused by calling kset_unregister twice
platform/x86: dell-wmi-sysman: Fix possible NULL pointer deref on exit
platform/x86: dell-wmi-sysman: Make it safe to call exit_foo_attributes() multiple times
platform/x86: dell-wmi-sysman: Fix release_attributes_data() getting called twice on init_bios_attributes() failure
platform/x86: dell-wmi-sysman: Cleanup sysman_init() error-exit handling
platform/x86: dell-wmi-sysman: Make sysman_init() return -ENODEV of the interfaces are not found
platform/x86: dell-wmi-sysman: Cleanup create_attributes_level_sysfs_files()
Hariprasad Kelam (1):
octeontx2-af: fix infinite loop in unmapping NPC counter
Hayes Wang (2):
Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
r8152: limit the RX buffer size of RTL8153A for USB 2.0
Heiko Thiery (1):
net: fec: ptp: avoid register access when ipg clock is disabled
Heiner Kallweit (1):
r8169: fix DMA being used after buffer free if WoL is enabled
Horia Geantă (3):
arm64: dts: ls1046a: mark crypto engine dma coherent
arm64: dts: ls1012a: mark crypto engine dma coherent
arm64: dts: ls1043a: mark crypto engine dma coherent
Huy Nguyen (1):
net/mlx5: Add back multicast stats for uplink representor
Ian Rogers (1):
perf synthetic events: Avoid write of uninitialized memory when generating PERF_RECORD_MMAP* records
Ido Schimmel (2):
psample: Fix user API breakage
drop_monitor: Perform cleanup upon probe registration failure
Imre Deak (1):
drm/i915: Fix the GT fence revocation runtime PM logic
Ira Weiny (1):
mm/highmem: fix CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP
Isaku Yamahata (1):
x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
J. Bruce Fields (1):
nfs: we don't support removing system.nfs4_acl
Jakub Kicinski (1):
ipv6: weaken the v4mapped source check
Jan Beulich (1):
xen-blkback: don't leak persistent grants from xen_blkbk_map()
Jan Kara (1):
ext4: add reclaim checks to xattr code
Jani Nikula (1):
drm/i915/dsc: fix DSS CTL register usage for ICL DSI transcoders
Jean-Philippe Brucker (1):
libbpf: Fix BTF dump of pointer-to-array-of-struct
JeongHyeon Lee (1):
dm verity: fix DM_VERITY_OPTS_MAX value
Jesse Brandeburg (1):
igb: check timestamp validity
Jia-Ju Bai (6):
net: tehuti: fix error return code in bdx_probe()
net: intel: iavf: fix error return code of iavf_init_get_resources()
net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
net: wan: fix error return code of uhdlc_init()
scsi: qedi: Fix error return code of qedi_alloc_global_queues()
scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
Jimmy Assarsson (1):
can: kvaser_pciefd: Always disable bus load reporting
Jiri Bohac (1):
net: check all name nodes in __dev_alloc_name
Jiri Slaby (1):
kbuild: dummy-tools: fix inverted tests for gcc
Joakim Zhang (1):
net: stmmac: fix dma physical address of descriptor when display ring
Johan Hovold (1):
net: cdc-phonet: fix data-interface release on probe failure
Johannes Berg (1):
mac80211: fix rate mask reset
Josef Bacik (3):
btrfs: do not initialize dev stats if we have no dev_root
btrfs: do not initialize dev replace for bad dev root
btrfs: initialize device::fs_info always
Josh Poimboeuf (1):
static_call: Allow module use without exposing static_call_key
Julian Braha (1):
staging: rtl8192e: fix kconfig dependency on CRYPTO
Kenneth Feng (1):
drm/amd/pm: workaround for audio noise issue
Kumar Kartikeya Dwivedi (1):
libbpf: Use SOCK_CLOEXEC when opening the netlink socket
Li RongQing (1):
igb: avoid premature Rx buffer reuse
Louis Peens (3):
nfp: flower: fix unsupported pre_tunnel flows
nfp: flower: add ipv6 bit to pre_tunnel control message
nfp: flower: fix pre_tun mask id allocation
Lukasz Luba (1):
PM: EM: postpone creating the debugfs dir till fs_initcall
Lv Yunlong (2):
nvme-rdma: Fix a use after free in nvmet_rdma_write_data_done
net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
Lyude Paul (1):
drm/nouveau/kms/nve4-nv108: Limit cursors to 128x128
Maciej Fijalkowski (1):
veth: Store queue_mapping independently of XDP prog presence
Magnus Karlsson (1):
ice: fix napi work done reporting in xsk path
Maor Dickman (1):
net/mlx5e: Don't match on Geneve options in case option masks are all zero
Marc Kleine-Budde (3):
can: isotp: isotp_setsockopt(): only allow to set low level TX flags for CAN-FD
can: isotp: TX-path: ensure that CAN frame flags are initialized
can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
Mark Brown (1):
kselftest: arm64: Fix exit code of sve-ptrace
Mark Pearson (1):
ALSA: hda: ignore invalid NHLT table
Mark Rutland (1):
arm64: stacktrace: don't trace arch_stack_walk()
Mark Tomlinson (3):
Revert "netfilter: x_tables: Switch synchronization to RCU"
netfilter: x_tables: Use correct memory barriers.
Revert "netfilter: x_tables: Update remaining dereference to RCU"
Markus Theil (1):
mac80211: fix double free in ibss_leave
Martin Willi (1):
can: dev: Move device back to init netns on owning netns delete
Masahiro Yamada (1):
kbuild: add image_name to no-sync-config-targets
Matthew Wilcox (Oracle) (1):
fs/cachefiles: Remove wait_bit_key layout dependency
Maxim Mikityanskiy (2):
net/mlx5e: When changing XDP program without reset, take refs for XSK RQs
net/mlx5e: Revert parameters on errors when changing PTP state without reset
Mian Yousaf Kaukab (1):
netsec: restore phy power state after controller reset
Miaohe Lin (1):
hugetlb_cgroup: fix imbalanced css_get and css_put pair for shared mappings
Michael Braun (1):
gianfar: fix jumbo packets+napi+rx overrun crash
Michael Ellerman (1):
powerpc/4xx: Fix build errors from mfdcr()
Michael Walle (1):
net: phy: introduce phydev->port
Mike Rapoport (1):
mm: memblock: fix section mismatch warning again
Mikulas Patocka (2):
dm: don't report "detected capacity change" on device creation
dm ioctl: fix out of bounds array access when no devices
Mimi Zohar (1):
integrity: double check iint_cache was initialized
Muhammad Husaini Zulkifli (2):
igc: Fix Pause Frame Advertising
igc: Fix Supported Pause Frame Link Setting
Namhyung Kim (1):
libbpf: Fix error path in bpf_object__elf_init()
Nick Desaulniers (1):
gcov: fix clang-11+ support
Nicolas Ferre (1):
ARM: dts: at91: sam9x60: fix mux-mask to match product's datasheet
Nirmoy Das (1):
drm/amdgpu: fb BO should be ttm_bo_type_device
Nitin Rawat (1):
scsi: ufs: ufs-qcom: Disable interrupt in reset path
Oliver Hartkopp (1):
can: isotp: tx-path: zero initialize outgoing CAN frames
Omar Sandoval (1):
btrfs: fix check_data_csum() error message for direct I/O
Ondrej Mosnacek (2):
selinux: don't log MAC_POLICY_LOAD record on failed policy load
selinux: fix variable scope issue in live sidtab conversion
Ong Boon Leong (1):
net: phylink: Fix phylink_err() function name error in phylink_major_config
Pablo Neira Ayuso (2):
netfilter: nftables: report EOPNOTSUPP on unsupported flowtable flags
netfilter: nftables: allow to update flowtable flags
Parav Pandit (1):
net/mlx5e: E-switch, Fix rate calculation division
Paul Cercueil (2):
net: davicom: Use platform_get_irq_optional()
irqchip/ingenic: Add support for the JZ4760
Paulo Alcantara (1):
cifs: change noisy error message to FYI
Pavel Begunkov (2):
io_uring: cancel deferred requests in try_cancel
io_uring: fix provide_buffers sign extension
Pavel Tatashin (1):
arm64: kdump: update ppos when reading elfcorehdr
Peter Zijlstra (4):
u64_stats,lockdep: Fix u64_stats_init() vs lockdep
static_call: Pull some static_call declarations to the type headers
static_call: Fix the module key fixup
static_call: Fix static_call_set_init()
Phillip Lougher (1):
squashfs: fix xattr id and id lookup sanity checks
Potnuri Bharat Teja (1):
RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server
Prike Liang (1):
drm/amdgpu: fix the hibernation suspend with s0ix
Qingqing Zhuo (1):
drm/amd/display: Enable pflip interrupt upon pipe enable
Rafael J. Wysocki (2):
PM: runtime: Defer suspending suppliers
ACPI: scan: Rearrange memory allocation in acpi_device_add()
Rakesh Babu (1):
octeontx2-af: Formatting debugfs entry rsrc_alloc.
Rob Gardner (1):
sparc64: Fix opcode filtering in handling of no fault loads
Robert Hancock (2):
net: axienet: Fix probe error cleanup
net: phy: broadcom: Set proper 1000BaseX/SGMII interface mode for BCM54616S
Roger Pau Monne (2):
xen/x86: make XEN_BALLOON_MEMORY_HOTPLUG_LIMIT depend on MEMORY_HOTPLUG
Revert "xen: fix p2m size in dom0 for disabled memory hotplug case"
Sabyrzhan Tasbolatov (1):
fs/ext4: fix integer overflow in s_log_groups_per_flex
Sasha Levin (1):
bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
Sasha Neftin (1):
igc: reinit_locked() should be called with rtnl_lock
Sean Christopherson (2):
KVM: x86: Protect userspace MSR filter with SRCU, and set atomically-ish
mm/mmu_notifiers: ensure range_end() is paired with range_start()
Sean Nyekjaer (1):
squashfs: fix inode lookup sanity checks
Sergei Trofimovich (2):
ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
Shannon Nelson (1):
ionic: linearize tso skb with too many frags
Shin'ichiro Kawasaki (1):
dm table: Fix zoned model check and zone sectors check
Shyam Prasad N (1):
cifs: Adjust key sizes and key generation routines for AES256 encryption
Stanislav Fomichev (1):
bpf: Use NOP_ATOMIC5 instead of emit_nops(&prog, 5) for BPF_TRAMP_F_CALL_ORIG
Stephane Grosjean (1):
can: peak_usb: add forgotten supported devices
Steve French (1):
smb3: fix cached file size problems in duplicate extents (reflink)
Subbaraya Sundeep (1):
octeontx2-af: Remove TOS field from MKEX TX
Sudeep Holla (1):
cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
Sung Lee (1):
drm/amd/display: Revert dram_clock_change_latency for DCN2.1
Tal Lossos (1):
bpf: Change inode_storage's lookup_elem return value from NULL to -EBADF
Tariq Toukan (1):
net/mlx5e: RX, Mind the MPWQE gaps when calculating offsets
Thomas Gleixner (1):
locking/mutex: Fix non debug version of mutex_lock_io_nested()
Thomas Hebb (1):
z3fold: prevent reclaim/free race for headless pages
Timo Rothenpieler (1):
nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
Tomer Tayar (2):
habanalabs: Call put_pid() when releasing control device
habanalabs: Disable file operations after device is removed
Tong Zhang (6):
atm: eni: dont release is never initialized
atm: lanai: dont run lanai_dev_close if not open
atm: uPD98402: fix incorrect allocation
atm: idt77252: fix null-ptr-dereference
can: c_can_pci: c_can_pci_remove(): fix use-after-free
can: c_can: move runtime PM enable/disable to c_can_platform
Tony Lindgren (3):
soc: ti: omap-prm: Fix reboot issue with invalid pcie reset map for dra7
ARM: OMAP2+: Fix smartreflex init regression after dropping legacy data
soc: ti: omap-prm: Fix occasional abort on reset deassert for dra7 iva
Torin Cooper-Bennun (2):
can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
Vegard Nossum (1):
ACPICA: Always create namespace nodes using acpi_ns_create_node()
Vitaly Lifshits (1):
e1000e: add rtnl_lock() to e1000_reset_task
Vladimir Oltean (1):
net: bridge: don't notify switchdev for local FDB addresses
Wei Wang (1):
ipv6: fix suspecious RCU usage warning
Wei Yongjun (1):
umem: fix error return code in mm_pci_probe()
Xie He (1):
net: hdlc_x25: Prevent racing between "x25_close" and "x25_xmit"/"x25_rx"
Xin Long (1):
sctp: move sk_route_caps check and set into sctp_outq_flush_transports
Xunlei Pang (1):
blk-cgroup: Fix the recursive blkg rwstat
Yang Li (1):
gpiolib: acpi: Add missing IRQF_ONESHOT
Yinjun Zhang (1):
netfilter: flowtable: Make sure GC works periodically in idle system
Zhan Liu (1):
drm/amdgpu/display: Use wm_table.entries for dcn301 calculate_wm
Zqiang (1):
bpf: Fix umd memory leak in copy_process()
dillon min (1):
ARM: dts: imx6ull: fix ubi filesystem mount failed
satya priya (2):
regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
regulator: qcom-rpmh: Use correct buck for S1C regulator
wenxu (1):
net/sched: cls_flower: fix only mask bit check in the validate_ct_state
^ permalink raw reply [relevance 1%]
* [PATCH 5.11 000/252] 5.11.11-rc2 review
@ 2021-03-29 10:14 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-29 10:14 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.11.11 release.
There are 252 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 31 Mar 2021 10:13:07 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.11-rc2.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.11.11-rc2
Alexei Starovoitov <ast@kernel.org>
selftest/bpf: Add a test to check trampoline freeing logic.
Marc Kleine-Budde <mkl@pengutronix.de>
can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
Christoph Hellwig <hch@lst.de>
nvme: fix the nsid value to print in nvme_validate_or_alloc_ns
Roger Pau Monne <roger.pau@citrix.com>
Revert "xen: fix p2m size in dom0 for disabled memory hotplug case"
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
fs/ext4: fix integer overflow in s_log_groups_per_flex
Jan Kara <jack@suse.cz>
ext4: add reclaim checks to xattr code
Markus Theil <markus.theil@tu-ilmenau.de>
mac80211: fix double free in ibss_leave
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: b53: VLAN filtering is global to all users
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix DMA being used after buffer free if WoL is enabled
Martin Willi <martin@strongswan.org>
can: dev: Move device back to init netns on owning netns delete
Arnd Bergmann <arnd@arndb.de>
ch_ktls: fix enum-conversion warning
Matthew Wilcox (Oracle) <willy@infradead.org>
fs/cachefiles: Remove wait_bit_key layout dependency
Isaku Yamahata <isaku.yamahata@intel.com>
x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
Thomas Gleixner <tglx@linutronix.de>
locking/mutex: Fix non debug version of mutex_lock_io_nested()
Shyam Prasad N <sprasad@microsoft.com>
cifs: Adjust key sizes and key generation routines for AES256 encryption
Steve French <stfrench@microsoft.com>
smb3: fix cached file size problems in duplicate extents (reflink)
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: qedi: Fix error return code of qedi_alloc_global_queues()
Bart Van Assche <bvanassche@acm.org>
scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
David Jeffery <djeffery@redhat.com>
block: recalculate segment count for multi-segment discards correctly
Pavel Begunkov <asml.silence@gmail.com>
io_uring: fix provide_buffers sign extension
Ian Rogers <irogers@google.com>
perf synthetic events: Avoid write of uninitialized memory when generating PERF_RECORD_MMAP* records
Adrian Hunter <adrian.hunter@intel.com>
perf auxtrace: Fix auxtrace queue conflict
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
ACPI: scan: Use unique number for instance_no
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: scan: Rearrange memory allocation in acpi_device_add()
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Update remaining dereference to RCU"
Sean Christopherson <seanjc@google.com>
mm/mmu_notifiers: ensure range_end() is paired with range_start()
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
dm table: Fix zoned model check and zone sectors check
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Cleanup create_attributes_level_sysfs_files()
Stanislav Fomichev <sdf@google.com>
bpf: Use NOP_ATOMIC5 instead of emit_nops(&prog, 5) for BPF_TRAMP_F_CALL_ORIG
Alexei Starovoitov <ast@kernel.org>
bpf: Fix fexit trampoline.
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
netfilter: x_tables: Use correct memory barriers.
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Switch synchronization to RCU"
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Fix RGMII delays for BCM50160 and BCM50610M
Robert Hancock <robert.hancock@calian.com>
net: phy: broadcom: Set proper 1000BaseX/SGMII interface mode for BCM54616S
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Avoid forward for bcm54xx_config_clock_delay()
Michael Walle <michael@walle.cc>
net: phy: introduce phydev->port
Robert Hancock <robert.hancock@calian.com>
net: axienet: Fix probe error cleanup
Li RongQing <lirongqing@baidu.com>
igb: avoid premature Rx buffer reuse
Daniel Borkmann <daniel@iogearbox.net>
net, bpf: Fix ip6ip6 crash with collect_md populated skbs
Daniel Borkmann <daniel@iogearbox.net>
net: Consolidate common blackhole dst ops
Sasha Levin <sashal@kernel.org>
bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
Mike Rapoport <rppt@kernel.org>
mm: memblock: fix section mismatch warning again
Potnuri Bharat Teja <bharat@chelsio.com>
RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server
Roger Pau Monne <roger.pau@citrix.com>
xen/x86: make XEN_BALLOON_MEMORY_HOTPLUG_LIMIT depend on MEMORY_HOTPLUG
Colin Ian King <colin.king@canonical.com>
octeontx2-af: Fix memory leak of object buf
Vladimir Oltean <vladimir.oltean@nxp.com>
net: bridge: don't notify switchdev for local FDB addresses
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt_crashlog: Fix incorrect macros
Lukasz Luba <lukasz.luba@arm.com>
PM: EM: postpone creating the debugfs dir till fs_initcall
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
mfd: intel_quark_i2c_gpio: Revert "Constify static struct resources"
Aya Levin <ayal@nvidia.com>
net/mlx5e: Fix error path for ethtool set-priv-flag
Dima Chumak <dchumak@nvidia.com>
net/mlx5e: Offload tuple rewrite for non-CT flows
Alaa Hleihel <alaa@nvidia.com>
net/mlx5e: Allow to match on MPLS parameters only for MPLS over UDP
Huy Nguyen <huyn@nvidia.com>
net/mlx5: Add back multicast stats for uplink representor
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PM: runtime: Defer suspending suppliers
Pavel Tatashin <pasha.tatashin@soleen.com>
arm64: kdump: update ppos when reading elfcorehdr
Fabio Estevam <festevam@gmail.com>
drm/msm: Fix suspend/resume on i.MX5
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: fix shutdown hook in case GPU components failed to bind
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Make sysman_init() return -ENODEV of the interfaces are not found
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Cleanup sysman_init() error-exit handling
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Fix release_attributes_data() getting called twice on init_bios_attributes() failure
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Make it safe to call exit_foo_attributes() multiple times
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Fix possible NULL pointer deref on exit
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Fix crash caused by calling kset_unregister twice
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: tx-path: zero initialize outgoing CAN frames
Zqiang <qiang.zhang@windriver.com>
bpf: Fix umd memory leak in copy_process()
Jean-Philippe Brucker <jean-philippe@linaro.org>
libbpf: Fix BTF dump of pointer-to-array-of-struct
Hangbin Liu <liuhangbin@gmail.com>
selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
David Brazdil <dbrazdil@google.com>
selinux: vsock: Set SID for socket returned by accept()
Corentin Labbe <clabbe@baylibre.com>
net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
Hayes Wang <hayeswang@realtek.com>
r8152: limit the RX buffer size of RTL8153A for USB 2.0
Xin Long <lucien.xin@gmail.com>
sctp: move sk_route_caps check and set into sctp_outq_flush_transports
Jesse Brandeburg <jesse.brandeburg@intel.com>
igb: check timestamp validity
Johan Hovold <johan@kernel.org>
net: cdc-phonet: fix data-interface release on probe failure
Jiri Bohac <jbohac@suse.cz>
net: check all name nodes in __dev_alloc_name
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-af: fix infinite loop in unmapping NPC counter
Geetha sowjanya <gakula@marvell.com>
octeontx2-pf: Clear RSS enable flag on interace down
Geetha sowjanya <gakula@marvell.com>
octeontx2-af: Fix irq free in rvu teardown
Subbaraya Sundeep <sbhatta@marvell.com>
octeontx2-af: Remove TOS field from MKEX TX
Rakesh Babu <rsaladi2@marvell.com>
octeontx2-af: Formatting debugfs entry rsrc_alloc.
Jakub Kicinski <kuba@kernel.org>
ipv6: weaken the v4mapped source check
dillon min <dillon.minfei@gmail.com>
ARM: dts: imx6ull: fix ubi filesystem mount failed
Kumar Kartikeya Dwivedi <memxor@gmail.com>
libbpf: Use SOCK_CLOEXEC when opening the netlink socket
Namhyung Kim <namhyung@kernel.org>
libbpf: Fix error path in bpf_object__elf_init()
Yinjun Zhang <yinjun.zhang@corigine.com>
netfilter: flowtable: Make sure GC works periodically in idle system
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: allow to update flowtable flags
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: report EOPNOTSUPP on unsupported flowtable flags
wenxu <wenxu@ucloud.cn>
net/sched: cls_flower: fix only mask bit check in the validate_ct_state
Shannon Nelson <snelson@pensando.io>
ionic: linearize tso skb with too many frags
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix check-before-set in the 7nm dsi_pll code
Alexei Starovoitov <ast@kernel.org>
ftrace: Fix modify_ftrace_direct.
Louis Peens <louis.peens@corigine.com>
nfp: flower: fix pre_tun mask id allocation
Louis Peens <louis.peens@corigine.com>
nfp: flower: add ipv6 bit to pre_tunnel control message
Louis Peens <louis.peens@corigine.com>
nfp: flower: fix unsupported pre_tunnel flows
Carlos Llamas <cmllamas@google.com>
selftests/net: fix warnings on reuseaddr_ports_exhausted
Brian Norris <briannorris@chromium.org>
mac80211: Allow HE operation to be longer than expected.
Johannes Berg <johannes.berg@intel.com>
mac80211: fix rate mask reset
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
Tong Zhang <ztong0001@gmail.com>
can: c_can: move runtime PM enable/disable to c_can_platform
Tong Zhang <ztong0001@gmail.com>
can: c_can_pci: c_can_pci_remove(): fix use-after-free
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Always disable bus load reporting
Angelo Dureghello <angelo@kernel-space.org>
can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
Stephane Grosjean <s.grosjean@peak-system.com>
can: peak_usb: add forgotten supported devices
Marc Kleine-Budde <mkl@pengutronix.de>
can: isotp: TX-path: ensure that CAN frame flags are initialized
Marc Kleine-Budde <mkl@pengutronix.de>
can: isotp: isotp_setsockopt(): only allow to set low level TX flags for CAN-FD
Davide Caratti <dcaratti@redhat.com>
mptcp: fix ADD_ADDR HMAC in case port is specified
Alexander Ovechkin <ovov@yandex-team.ru>
tcp: relookup sock for RST+ACK packets handled by obsolete req sock
Eric Dumazet <edumazet@google.com>
tipc: better validate user input in tipc_nl_retrieve_key()
Ong Boon Leong <boon.leong.ong@intel.com>
net: phylink: Fix phylink_err() function name error in phylink_major_config
Xie He <xie.he.0141@gmail.com>
net: hdlc_x25: Prevent racing between "x25_close" and "x25_xmit"/"x25_rx"
Florian Westphal <fw@strlen.de>
netfilter: ctnetlink: fix dump of the expect mask attribute
Hangbin Liu <liuhangbin@gmail.com>
selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
Alexander Lobakin <alobakin@pm.me>
flow_dissector: fix byteorder of dissected ICMP ID
Eric Dumazet <edumazet@google.com>
net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
Alex Elder <elder@linaro.org>
net: ipa: terminate message handler arrays
Douglas Anderson <dianders@chromium.org>
clk: qcom: gcc-sc7180: Use floor ops for the correct sdcc1 clk
Dylan Hung <dylan_hung@aspeedtech.com>
ftgmac100: Restart MAC HW once
Magnus Karlsson <magnus.karlsson@intel.com>
ice: fix napi work done reporting in xsk path
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Add power down exit reset state delay
Lv Yunlong <lyl2019@mail.ustc.edu.cn>
net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
David Gow <davidgow@google.com>
kunit: tool: Disable PAGE_POISONING under --alltests
Dinghao Liu <dinghao.liu@zju.edu.cn>
e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
Vitaly Lifshits <vitaly.lifshits@intel.com>
e1000e: add rtnl_lock() to e1000_reset_task
Andre Guedes <andre.guedes@intel.com>
igc: Fix igc_ptp_rx_pktstamp()
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Supported Pause Frame Link Setting
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Pause Frame Advertising
Sasha Neftin <sasha.neftin@intel.com>
igc: reinit_locked() should be called with rtnl_lock
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
Eric Dumazet <edumazet@google.com>
net: sched: validate stab values
Eric Dumazet <edumazet@google.com>
macvlan: macvlan_count_rx() needs to be aware of preemption
Ido Schimmel <idosch@nvidia.com>
drop_monitor: Perform cleanup upon probe registration failure
Wei Wang <weiwan@google.com>
ipv6: fix suspecious RCU usage warning
Parav Pandit <parav@nvidia.com>
net/mlx5e: E-switch, Fix rate calculation division
Maor Dickman <maord@nvidia.com>
net/mlx5e: Don't match on Geneve options in case option masks are all zero
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Revert parameters on errors when changing PTP state without reset
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: When changing XDP program without reset, take refs for XSK RQs
Aya Levin <ayal@nvidia.com>
net/mlx5e: Set PTP channel pointer explicitly to NULL
Tariq Toukan <tariqt@nvidia.com>
net/mlx5e: RX, Mind the MPWQE gaps when calculating offsets
Georgi Valkov <gvalkov@abv.bg>
libbpf: Fix INSTALL flag order
Tal Lossos <tallossos@gmail.com>
bpf: Change inode_storage's lookup_elem return value from NULL to -EBADF
Alexei Starovoitov <ast@kernel.org>
bpf: Dont allow vmlinux BTF to be used in map_create and prog_load.
Maciej Fijalkowski <maciej.fijalkowski@intel.com>
veth: Store queue_mapping independently of XDP prog presence
Tony Lindgren <tony@atomide.com>
soc: ti: omap-prm: Fix occasional abort on reset deassert for dra7 iva
Tony Lindgren <tony@atomide.com>
ARM: OMAP2+: Fix smartreflex init regression after dropping legacy data
Tony Lindgren <tony@atomide.com>
soc: ti: omap-prm: Fix reboot issue with invalid pcie reset map for dra7
Grygorii Strashko <grygorii.strashko@ti.com>
bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
Mikulas Patocka <mpatocka@redhat.com>
dm ioctl: fix out of bounds array access when no devices
Mikulas Patocka <mpatocka@redhat.com>
dm: don't report "detected capacity change" on device creation
JeongHyeon Lee <jhs2.lee@samsung.com>
dm verity: fix DM_VERITY_OPTS_MAX value
Imre Deak <imre.deak@intel.com>
drm/i915: Fix the GT fence revocation runtime PM logic
Jani Nikula <jani.nikula@intel.com>
drm/i915/dsc: fix DSS CTL register usage for ICL DSI transcoders
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Add additional Sienna Cichlid PCI ID
Prike Liang <Prike.Liang@amd.com>
drm/amdgpu: fix the hibernation suspend with s0ix
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/display: restore AUX_DPHY_TX_CONTROL for DCN2.x
Kenneth Feng <kenneth.feng@amd.com>
drm/amd/pm: workaround for audio noise issue
Daniel Vetter <daniel.vetter@ffwll.ch>
drm/etnaviv: Use FOLL_FORCE for userptr
Lyude Paul <lyude@redhat.com>
drm/nouveau/kms/nve4-nv108: Limit cursors to 128x128
Mimi Zohar <zohar@linux.ibm.com>
integrity: double check iint_cache was initialized
Claudiu Beznea <claudiu.beznea@microchip.com>
ARM: dts: at91-sama5d27_som1: fix phy address to 7
Nicolas Ferre <nicolas.ferre@microchip.com>
ARM: dts: at91: sam9x60: fix mux-mask to match product's datasheet
Federico Pellegrin <fede@evolware.org>
ARM: dts: at91: sam9x60: fix mux-mask for PA7 so it can be set to A, B and C
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1043a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1012a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1046a: mark crypto engine dma coherent
Mark Rutland <mark.rutland@arm.com>
arm64: stacktrace: don't trace arch_stack_walk()
Vegard Nossum <vegard.nossum@oracle.com>
ACPICA: Always create namespace nodes using acpi_ns_create_node()
Chris Chiu <chris.chiu@canonical.com>
ACPI: video: Add missing callback back for Sony VPCEH3U1E
Ira Weiny <ira.weiny@intel.com>
mm/highmem: fix CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP
Nick Desaulniers <ndesaulniers@google.com>
gcov: fix clang-11+ support
Andrey Konovalov <andreyknvl@google.com>
kasan: fix per-page tags for non-page_alloc pages
Miaohe Lin <linmiaohe@huawei.com>
hugetlb_cgroup: fix imbalanced css_get and css_put pair for shared mappings
Phillip Lougher <phillip@squashfs.org.uk>
squashfs: fix xattr id and id lookup sanity checks
Sean Nyekjaer <sean@geanix.com>
squashfs: fix inode lookup sanity checks
Thomas Hebb <tommyhebb@gmail.com>
z3fold: prevent reclaim/free race for headless pages
Ido Schimmel <idosch@nvidia.com>
psample: Fix user API breakage
Hans de Goede <hdegoede@redhat.com>
platform/x86: intel-vbtn: Stop reporting SW_DOCK events
Mian Yousaf Kaukab <ykaukab@suse.de>
netsec: restore phy power state after controller reset
Ondrej Mosnacek <omosnace@redhat.com>
selinux: fix variable scope issue in live sidtab conversion
Ondrej Mosnacek <omosnace@redhat.com>
selinux: don't log MAC_POLICY_LOAD record on failed policy load
Filipe Manana <fdmanana@suse.com>
btrfs: fix subvolume/snapshot deletion not triggered on mount
Filipe Manana <fdmanana@suse.com>
btrfs: fix sleep while in non-sleep context during qgroup removal
Josef Bacik <josef@toxicpanda.com>
btrfs: initialize device::fs_info always
Omar Sandoval <osandov@fb.com>
btrfs: fix check_data_csum() error message for direct I/O
Josef Bacik <josef@toxicpanda.com>
btrfs: do not initialize dev replace for bad dev root
Josef Bacik <josef@toxicpanda.com>
btrfs: do not initialize dev stats if we have no dev_root
Sean Christopherson <seanjc@google.com>
KVM: x86: Protect userspace MSR filter with SRCU, and set atomically-ish
Peter Zijlstra <peterz@infradead.org>
static_call: Fix static_call_set_init()
Peter Zijlstra <peterz@infradead.org>
static_call: Fix the module key fixup
Josh Poimboeuf <jpoimboe@redhat.com>
static_call: Allow module use without exposing static_call_key
Peter Zijlstra <peterz@infradead.org>
static_call: Pull some static_call declarations to the type headers
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
Fenghua Yu <fenghua.yu@intel.com>
mm/fork: clear PASID for new mm
Pavel Begunkov <asml.silence@gmail.com>
io_uring: cancel deferred requests in try_cancel
Daniel Wagner <dwagner@suse.de>
block: Suppress uevent for hidden device when removed
J. Bruce Fields <bfields@redhat.com>
nfs: we don't support removing system.nfs4_acl
Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
Lv Yunlong <lyl2019@mail.ustc.edu.cn>
nvme-rdma: Fix a use after free in nvmet_rdma_write_data_done
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvme-core: check ctrl css before setting up zns
Hannes Reinecke <hare@suse.de>
nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
Hannes Reinecke <hare@suse.de>
nvme-fc: set NVME_REQ_CANCELLED in nvme_fc_terminate_exchange()
Hannes Reinecke <hare@suse.de>
nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
Hannes Reinecke <hare@suse.de>
nvme: simplify error logic in nvme_validate_ns()
Christian König <christian.koenig@amd.com>
drm/radeon: fix AGP dependency
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu: fb BO should be ttm_bo_type_device
Zhan Liu <zhan.liu@amd.com>
drm/amdgpu/display: Use wm_table.entries for dcn301 calculate_wm
Dillon Varone <dillon.varone@amd.com>
drm/amd/display: Enabled pipe harvesting in dcn30
Sung Lee <sung.lee@amd.com>
drm/amd/display: Revert dram_clock_change_latency for DCN2.1
Qingqing Zhuo <qingqing.zhuo@amd.com>
drm/amd/display: Enable pflip interrupt upon pipe enable
Damien Le Moal <damien.lemoal@wdc.com>
block: Fix REQ_OP_ZONE_RESET_ALL handling
satya priya <skakit@codeaurora.org>
regulator: qcom-rpmh: Use correct buck for S1C regulator
satya priya <skakit@codeaurora.org>
regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
Mark Brown <broonie@kernel.org>
kselftest: arm64: Fix exit code of sve-ptrace
Peter Zijlstra <peterz@infradead.org>
u64_stats,lockdep: Fix u64_stats_init() vs lockdep
Julian Braha <julianbraha@gmail.com>
staging: rtl8192e: fix kconfig dependency on CRYPTO
Tomer Tayar <ttayar@habana.ai>
habanalabs: Disable file operations after device is removed
Tomer Tayar <ttayar@habana.ai>
habanalabs: Call put_pid() when releasing control device
Rob Gardner <rob.gardner@oracle.com>
sparc64: Fix opcode filtering in handling of no fault loads
Wei Yongjun <weiyongjun1@huawei.com>
umem: fix error return code in mm_pci_probe()
Jiri Slaby <jirislaby@kernel.org>
kbuild: dummy-tools: fix inverted tests for gcc
Masahiro Yamada <masahiroy@kernel.org>
kbuild: add image_name to no-sync-config-targets
Paul Cercueil <paul@crapouillou.net>
irqchip/ingenic: Add support for the JZ4760
Paulo Alcantara <pc@cjr.nz>
cifs: change noisy error message to FYI
Tong Zhang <ztong0001@gmail.com>
atm: idt77252: fix null-ptr-dereference
Tong Zhang <ztong0001@gmail.com>
atm: uPD98402: fix incorrect allocation
Alex Marginean <alexandru.marginean@nxp.com>
net: enetc: set MAC RX FIFO to recommended value
Paul Cercueil <paul@crapouillou.net>
net: davicom: Use platform_get_irq_optional()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: wan: fix error return code of uhdlc_init()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
Frank Sorenson <sorenson@redhat.com>
NFS: Correct size calculation for create reply length
Timo Rothenpieler <timo@rothenpieler.org>
nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
Yang Li <yang.lee@linux.alibaba.com>
gpiolib: acpi: Add missing IRQF_ONESHOT
Sudeep Holla <sudeep.holla@arm.com>
cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
Bob Peterson <rpeterso@redhat.com>
gfs2: fix use-after-free in trans_drain
Aurelien Aptel <aaptel@suse.com>
cifs: ask for more credit on async read/write code paths
Michael Braun <michael-dev@fami-braun.de>
gianfar: fix jumbo packets+napi+rx overrun crash
Denis Efremov <efremov@linux.com>
sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
Jia-Ju Bai <baijiaju1990@gmail.com>
net: intel: iavf: fix error return code of iavf_init_get_resources()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: tehuti: fix error return code in bdx_probe()
Xunlei Pang <xlpang@linux.alibaba.com>
blk-cgroup: Fix the recursive blkg rwstat
Nitin Rawat <nitirawa@codeaurora.org>
scsi: ufs: ufs-qcom: Disable interrupt in reset path
Dinghao Liu <dinghao.liu@zju.edu.cn>
ixgbe: Fix memleak in ixgbe_configure_clsu32
Mark Pearson <markpearson@lenovo.com>
ALSA: hda: ignore invalid NHLT table
Hayes Wang <hayeswang@realtek.com>
Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
Tong Zhang <ztong0001@gmail.com>
atm: lanai: dont run lanai_dev_close if not open
Tong Zhang <ztong0001@gmail.com>
atm: eni: dont release is never initialized
Michael Ellerman <mpe@ellerman.id.au>
powerpc/4xx: Fix build errors from mfdcr()
Heiko Thiery <heiko.thiery@gmail.com>
net: fec: ptp: avoid register access when ipg clock is disabled
Joakim Zhang <qiangqing.zhang@nxp.com>
net: stmmac: fix dma physical address of descriptor when display ring
Felix Fietkau <nbd@nbd.name>
mt76: mt7915: only modify tx buffer list after allocating tx token id
Felix Fietkau <nbd@nbd.name>
mt76: fix tx skb error handling in mt76_dma_tx_queue_skb
-------------
Diffstat:
Documentation/virt/kvm/api.rst | 6 +-
Makefile | 7 +-
arch/arm/boot/dts/at91-sam9x60ek.dts | 8 -
arch/arm/boot/dts/at91-sama5d27_som1.dtsi | 4 +-
arch/arm/boot/dts/imx6ull-myir-mys-6ulx-eval.dts | 1 +
arch/arm/boot/dts/sam9x60.dtsi | 9 +
arch/arm/mach-omap2/sr_device.c | 75 +++++--
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 1 +
arch/arm64/kernel/crash_dump.c | 2 +
arch/arm64/kernel/stacktrace.c | 9 +-
arch/ia64/include/asm/syscall.h | 2 +-
arch/ia64/kernel/ptrace.c | 24 ++-
arch/powerpc/include/asm/dcr-native.h | 8 +-
arch/sparc/kernel/traps_64.c | 13 +-
arch/x86/include/asm/kvm_host.h | 14 +-
arch/x86/include/asm/static_call.h | 7 +
arch/x86/include/asm/xen/page.h | 12 --
arch/x86/kvm/x86.c | 109 ++++++-----
arch/x86/mm/mem_encrypt.c | 2 +-
arch/x86/net/bpf_jit_comp.c | 27 ++-
arch/x86/xen/p2m.c | 7 +-
arch/x86/xen/setup.c | 16 +-
block/blk-cgroup-rwstat.c | 3 +-
block/blk-merge.c | 8 +
block/blk-zoned.c | 2 +-
block/genhd.c | 4 +-
drivers/acpi/acpica/nsaccess.c | 3 +-
drivers/acpi/internal.h | 6 +-
drivers/acpi/scan.c | 88 +++++----
drivers/acpi/video_detect.c | 1 +
drivers/atm/eni.c | 3 +-
drivers/atm/idt77105.c | 4 +-
drivers/atm/lanai.c | 5 +-
drivers/atm/uPD98402.c | 2 +-
drivers/base/power/runtime.c | 45 ++++-
drivers/block/umem.c | 5 +-
drivers/bus/omap_l3_noc.c | 4 +-
drivers/clk/qcom/gcc-sc7180.c | 4 +-
drivers/cpufreq/cpufreq-dt-platdev.c | 2 +
drivers/gpio/gpiolib-acpi.c | 2 +-
drivers/gpu/drm/Kconfig | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 +
drivers/gpu/drm/amd/display/dc/dc.h | 1 +
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 11 ++
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h | 6 +
.../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 7 +
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 1 +
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 6 +
.../drm/amd/display/dc/dcn20/dcn20_link_encoder.c | 3 +-
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c | 1 +
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c | 1 +
.../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 31 +++
.../drm/amd/display/dc/dcn301/dcn301_resource.c | 96 ++++++++-
drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 2 +
.../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 54 +++++
.../gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 74 +++++--
.../gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 24 +++
.../gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 25 +++
drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2 +-
drivers/gpu/drm/i915/display/intel_vdsc.c | 10 +-
drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 13 +-
drivers/gpu/drm/i915/intel_runtime_pm.c | 29 ++-
drivers/gpu/drm/i915/intel_runtime_pm.h | 5 +
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 2 +-
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 6 +-
drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c | 5 +-
drivers/gpu/drm/msm/msm_drv.c | 12 ++
drivers/gpu/drm/nouveau/dispnv50/disp.c | 13 +-
drivers/infiniband/hw/cxgb4/cm.c | 4 +-
drivers/irqchip/irq-ingenic-tcu.c | 1 +
drivers/irqchip/irq-ingenic.c | 1 +
drivers/md/dm-ioctl.c | 2 +-
drivers/md/dm-table.c | 33 +++-
drivers/md/dm-verity-target.c | 2 +-
drivers/md/dm-zoned-target.c | 2 +-
drivers/md/dm.c | 5 +-
drivers/mfd/intel_quark_i2c_gpio.c | 6 +-
drivers/misc/habanalabs/common/device.c | 40 +++-
drivers/misc/habanalabs/common/habanalabs_ioctl.c | 12 ++
drivers/net/can/c_can/c_can.c | 24 +--
drivers/net/can/c_can/c_can_pci.c | 3 +-
drivers/net/can/c_can/c_can_platform.c | 6 +-
drivers/net/can/dev.c | 1 +
drivers/net/can/flexcan.c | 8 +-
drivers/net/can/kvaser_pciefd.c | 4 +
drivers/net/can/m_can/m_can.c | 5 +-
drivers/net/dsa/b53/b53_common.c | 14 +-
drivers/net/dsa/bcm_sf2.c | 6 +-
.../chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 2 +-
drivers/net/ethernet/davicom/dm9000.c | 2 +-
drivers/net/ethernet/faraday/ftgmac100.c | 1 +
drivers/net/ethernet/freescale/enetc/enetc_hw.h | 2 +
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6 +
drivers/net/ethernet/freescale/fec_ptp.c | 7 +
drivers/net/ethernet/freescale/gianfar.c | 15 ++
drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4 +-
drivers/net/ethernet/intel/e1000e/82571.c | 2 +
drivers/net/ethernet/intel/e1000e/netdev.c | 6 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 3 +-
drivers/net/ethernet/intel/ice/ice_base.c | 6 +-
drivers/net/ethernet/intel/ice/ice_xsk.c | 10 +-
drivers/net/ethernet/intel/igb/igb.h | 4 +-
drivers/net/ethernet/intel/igb/igb_main.c | 33 ++--
drivers/net/ethernet/intel/igb/igb_ptp.c | 31 ++-
drivers/net/ethernet/intel/igc/igc.h | 2 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 7 +-
drivers/net/ethernet/intel/igc/igc_main.c | 9 +
drivers/net/ethernet/intel/igc/igc_ptp.c | 72 ++++---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +-
.../ethernet/marvell/octeontx2/af/npc_profile.h | 2 -
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 6 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 48 +++--
.../net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2 +-
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5 +
drivers/net/ethernet/mellanox/mlx5/core/en.h | 7 +-
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 3 +-
.../ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c | 4 +
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 11 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 21 +-
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 57 ++++--
.../net/ethernet/netronome/nfp/flower/metadata.c | 24 ++-
.../net/ethernet/netronome/nfp/flower/offload.c | 18 ++
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 15 +-
drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 13 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 3 +
drivers/net/ethernet/realtek/r8169_main.c | 6 +-
drivers/net/ethernet/socionext/netsec.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 50 ++++-
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 +-
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 57 ++++--
drivers/net/ethernet/sun/niu.c | 2 -
drivers/net/ethernet/tehuti/tehuti.c | 1 +
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 35 ++--
drivers/net/ipa/ipa_qmi.c | 2 +
drivers/net/phy/broadcom.c | 147 ++++++++++----
drivers/net/phy/dp83822.c | 3 +
drivers/net/phy/dp83869.c | 4 +
drivers/net/phy/lxt.c | 1 +
drivers/net/phy/marvell.c | 1 +
drivers/net/phy/marvell10g.c | 2 +
drivers/net/phy/micrel.c | 14 +-
drivers/net/phy/phy.c | 2 +-
drivers/net/phy/phy_device.c | 9 +
drivers/net/phy/phylink.c | 2 +-
drivers/net/usb/cdc-phonet.c | 2 +
drivers/net/usb/r8152.c | 40 +---
drivers/net/veth.c | 3 +-
drivers/net/wan/fsl_ucc_hdlc.c | 8 +-
drivers/net/wan/hdlc_x25.c | 42 +++-
drivers/net/wireless/mediatek/mt76/dma.c | 15 +-
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 10 +-
drivers/nvme/host/core.c | 15 +-
drivers/nvme/host/fc.c | 3 +-
drivers/nvme/host/pci.c | 1 +
drivers/nvme/target/rdma.c | 5 +-
.../platform/x86/dell-wmi-sysman/enum-attributes.c | 3 +
.../platform/x86/dell-wmi-sysman/int-attributes.c | 3 +
.../x86/dell-wmi-sysman/passobj-attributes.c | 3 +
.../x86/dell-wmi-sysman/string-attributes.c | 3 +
drivers/platform/x86/dell-wmi-sysman/sysman.c | 84 +++-----
drivers/platform/x86/intel-vbtn.c | 12 +-
drivers/platform/x86/intel_pmt_crashlog.c | 13 +-
drivers/regulator/qcom-rpmh-regulator.c | 6 +-
drivers/scsi/mpt3sas/mpt3sas_base.c | 8 +-
drivers/scsi/qedi/qedi_main.c | 1 +
drivers/scsi/qla2xxx/qla_target.c | 13 +-
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 -
drivers/scsi/ufs/ufs-qcom.c | 10 +
drivers/soc/ti/omap_prm.c | 8 +-
drivers/staging/rtl8192e/Kconfig | 1 +
drivers/xen/Kconfig | 4 +-
fs/btrfs/dev-replace.c | 3 +
fs/btrfs/disk-io.c | 19 +-
fs/btrfs/inode.c | 14 +-
fs/btrfs/qgroup.c | 12 +-
fs/btrfs/volumes.c | 3 +
fs/cachefiles/rdwr.c | 7 +-
fs/cifs/cifsglob.h | 4 +-
fs/cifs/cifspdu.h | 5 +
fs/cifs/smb2glob.h | 1 +
fs/cifs/smb2ops.c | 27 ++-
fs/cifs/smb2pdu.c | 6 +-
fs/cifs/smb2transport.c | 37 +++-
fs/cifs/transport.c | 2 +-
fs/ext4/mballoc.c | 11 +-
fs/ext4/xattr.c | 4 +
fs/gfs2/log.c | 4 +
fs/gfs2/trans.c | 2 +
fs/io_uring.c | 14 +-
fs/nfs/Kconfig | 2 +-
fs/nfs/nfs3xdr.c | 3 +-
fs/nfs/nfs4proc.c | 3 +
fs/squashfs/export.c | 8 +-
fs/squashfs/id.c | 6 +-
fs/squashfs/squashfs_fs.h | 1 +
fs/squashfs/xattr_id.c | 6 +-
include/acpi/acpi_bus.h | 1 +
include/asm-generic/vmlinux.lds.h | 5 +-
include/linux/bpf.h | 33 +++-
include/linux/brcmphy.h | 4 +
include/linux/device-mapper.h | 15 +-
include/linux/hugetlb_cgroup.h | 15 +-
include/linux/if_macvlan.h | 3 +-
include/linux/memblock.h | 4 +-
include/linux/mm.h | 18 +-
include/linux/mm_types.h | 1 +
include/linux/mmu_notifier.h | 10 +-
include/linux/mutex.h | 2 +-
include/linux/netfilter/x_tables.h | 7 +-
include/linux/pagemap.h | 1 -
include/linux/phy.h | 2 +
include/linux/static_call.h | 43 ++--
include/linux/static_call_types.h | 50 +++++
include/linux/u64_stats_sync.h | 7 +-
include/linux/usermode_driver.h | 1 +
include/net/dst.h | 11 ++
include/net/inet_connection_sock.h | 2 +-
include/net/netfilter/nf_tables.h | 3 +
include/net/nexthop.h | 24 +++
include/net/red.h | 10 +-
include/net/rtnetlink.h | 2 +
include/uapi/linux/psample.h | 5 +-
kernel/bpf/bpf_inode_storage.c | 2 +-
kernel/bpf/bpf_struct_ops.c | 2 +-
kernel/bpf/core.c | 4 +-
kernel/bpf/preload/bpf_preload_kern.c | 19 +-
kernel/bpf/syscall.c | 5 +
kernel/bpf/trampoline.c | 218 ++++++++++++++++-----
kernel/bpf/verifier.c | 4 +
kernel/fork.c | 8 +
kernel/gcov/clang.c | 69 +++++++
kernel/power/energy_model.c | 2 +-
kernel/static_call.c | 71 ++++++-
kernel/trace/ftrace.c | 43 +++-
kernel/usermode_driver.c | 21 +-
mm/highmem.c | 4 +-
mm/hugetlb.c | 41 +++-
mm/hugetlb_cgroup.c | 10 +-
mm/mmu_notifier.c | 23 +++
mm/z3fold.c | 16 +-
net/bridge/br_switchdev.c | 2 +
net/can/isotp.c | 18 +-
net/core/dev.c | 14 +-
net/core/drop_monitor.c | 23 +++
net/core/dst.c | 59 ++++--
net/core/flow_dissector.c | 2 +-
net/dccp/ipv6.c | 5 +
net/ipv4/inet_connection_sock.c | 7 +-
net/ipv4/netfilter/arp_tables.c | 16 +-
net/ipv4/netfilter/ip_tables.c | 16 +-
net/ipv4/route.c | 45 +----
net/ipv4/tcp_minisocks.c | 7 +-
net/ipv6/ip6_fib.c | 2 +-
net/ipv6/ip6_input.c | 10 -
net/ipv6/netfilter/ip6_tables.c | 16 +-
net/ipv6/route.c | 36 +---
net/ipv6/tcp_ipv6.c | 5 +
net/mac80211/cfg.c | 4 +-
net/mac80211/ibss.c | 2 +
net/mac80211/mlme.c | 2 +-
net/mac80211/util.c | 2 +-
net/mptcp/options.c | 24 ++-
net/mptcp/subflow.c | 5 +
net/netfilter/nf_conntrack_netlink.c | 1 +
net/netfilter/nf_flow_table_core.c | 2 +-
net/netfilter/nf_tables_api.c | 19 +-
net/netfilter/x_tables.c | 49 +++--
net/qrtr/qrtr.c | 5 +
net/sched/cls_flower.c | 2 +-
net/sched/sch_choke.c | 7 +-
net/sched/sch_gred.c | 2 +-
net/sched/sch_red.c | 7 +-
net/sched/sch_sfq.c | 2 +-
net/sctp/output.c | 7 -
net/sctp/outqueue.c | 7 +
net/tipc/node.c | 11 +-
net/vmw_vsock/af_vsock.c | 1 +
scripts/dummy-tools/gcc | 5 +
security/integrity/iint.c | 8 +
security/selinux/include/security.h | 15 +-
security/selinux/selinuxfs.c | 13 +-
security/selinux/ss/services.c | 63 +++---
sound/hda/intel-nhlt.c | 5 +
tools/include/linux/static_call_types.h | 50 +++++
tools/lib/bpf/Makefile | 2 +-
tools/lib/bpf/btf_dump.c | 2 +-
tools/lib/bpf/libbpf.c | 3 +-
tools/lib/bpf/netlink.c | 2 +-
tools/objtool/check.c | 17 +-
tools/perf/util/auxtrace.c | 4 -
tools/perf/util/synthetic-events.c | 9 +-
tools/testing/kunit/configs/broken_on_uml.config | 2 +
tools/testing/selftests/arm64/fp/sve-ptrace.c | 2 +-
.../testing/selftests/bpf/prog_tests/fexit_sleep.c | 82 ++++++++
tools/testing/selftests/bpf/progs/fexit_sleep.c | 31 +++
.../testing/selftests/bpf/progs/test_tunnel_kern.c | 6 +-
.../selftests/net/forwarding/vxlan_bridge_1d.sh | 2 +-
.../selftests/net/reuseaddr_ports_exhausted.c | 32 +--
308 files changed, 3092 insertions(+), 1105 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.10 000/219] 5.10.27-rc2 review
@ 2021-03-29 10:14 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-29 10:14 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.10.27 release.
There are 219 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 31 Mar 2021 10:13:09 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.27-rc2.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.27-rc2
Marc Kleine-Budde <mkl@pengutronix.de>
can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
Christoph Hellwig <hch@lst.de>
nvme: fix the nsid value to print in nvme_validate_or_alloc_ns
David S. Miller <davem@davemloft.net>
Revert "net: bonding: fix error return code of bond_neigh_init()"
Roger Pau Monne <roger.pau@citrix.com>
Revert "xen: fix p2m size in dom0 for disabled memory hotplug case"
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
fs/ext4: fix integer overflow in s_log_groups_per_flex
Jan Kara <jack@suse.cz>
ext4: add reclaim checks to xattr code
Markus Theil <markus.theil@tu-ilmenau.de>
mac80211: fix double free in ibss_leave
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: b53: VLAN filtering is global to all users
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix DMA being used after buffer free if WoL is enabled
Martin Willi <martin@strongswan.org>
can: dev: Move device back to init netns on owning netns delete
Arnd Bergmann <arnd@arndb.de>
ch_ktls: fix enum-conversion warning
Matthew Wilcox (Oracle) <willy@infradead.org>
fs/cachefiles: Remove wait_bit_key layout dependency
Hugh Dickins <hughd@google.com>
mm/memcg: fix 5.10 backport of splitting page memcg
Isaku Yamahata <isaku.yamahata@intel.com>
x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
Thomas Gleixner <tglx@linutronix.de>
locking/mutex: Fix non debug version of mutex_lock_io_nested()
Shyam Prasad N <sprasad@microsoft.com>
cifs: Adjust key sizes and key generation routines for AES256 encryption
Steve French <stfrench@microsoft.com>
smb3: fix cached file size problems in duplicate extents (reflink)
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: qedi: Fix error return code of qedi_alloc_global_queues()
Bart Van Assche <bvanassche@acm.org>
scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
David Jeffery <djeffery@redhat.com>
block: recalculate segment count for multi-segment discards correctly
Pavel Begunkov <asml.silence@gmail.com>
io_uring: fix provide_buffers sign extension
Ian Rogers <irogers@google.com>
perf synthetic events: Avoid write of uninitialized memory when generating PERF_RECORD_MMAP* records
Adrian Hunter <adrian.hunter@intel.com>
perf auxtrace: Fix auxtrace queue conflict
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
ACPI: scan: Use unique number for instance_no
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: scan: Rearrange memory allocation in acpi_device_add()
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Update remaining dereference to RCU"
Sean Christopherson <seanjc@google.com>
mm/mmu_notifiers: ensure range_end() is paired with range_start()
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
dm table: Fix zoned model check and zone sectors check
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
netfilter: x_tables: Use correct memory barriers.
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Switch synchronization to RCU"
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Fix RGMII delays for BCM50160 and BCM50610M
Robert Hancock <robert.hancock@calian.com>
net: phy: broadcom: Set proper 1000BaseX/SGMII interface mode for BCM54616S
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Avoid forward for bcm54xx_config_clock_delay()
Michael Walle <michael@walle.cc>
net: phy: introduce phydev->port
Robert Hancock <robert.hancock@calian.com>
net: axienet: Fix probe error cleanup
Robert Hancock <robert.hancock@calian.com>
net: axienet: Properly handle PCS/PMA PHY for 1000BaseX mode
Li RongQing <lirongqing@baidu.com>
igb: avoid premature Rx buffer reuse
Daniel Borkmann <daniel@iogearbox.net>
net, bpf: Fix ip6ip6 crash with collect_md populated skbs
Daniel Borkmann <daniel@iogearbox.net>
net: Consolidate common blackhole dst ops
Sasha Levin <sashal@kernel.org>
bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
Potnuri Bharat Teja <bharat@chelsio.com>
RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server
Roger Pau Monne <roger.pau@citrix.com>
xen/x86: make XEN_BALLOON_MEMORY_HOTPLUG_LIMIT depend on MEMORY_HOTPLUG
Colin Ian King <colin.king@canonical.com>
octeontx2-af: Fix memory leak of object buf
Vladimir Oltean <vladimir.oltean@nxp.com>
net: bridge: don't notify switchdev for local FDB addresses
Lukasz Luba <lukasz.luba@arm.com>
PM: EM: postpone creating the debugfs dir till fs_initcall
Aya Levin <ayal@nvidia.com>
net/mlx5e: Fix error path for ethtool set-priv-flag
Dima Chumak <dchumak@nvidia.com>
net/mlx5e: Offload tuple rewrite for non-CT flows
Alaa Hleihel <alaa@nvidia.com>
net/mlx5e: Allow to match on MPLS parameters only for MPLS over UDP
Huy Nguyen <huyn@nvidia.com>
net/mlx5: Add back multicast stats for uplink representor
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PM: runtime: Defer suspending suppliers
Pavel Tatashin <pasha.tatashin@soleen.com>
arm64: kdump: update ppos when reading elfcorehdr
Fabio Estevam <festevam@gmail.com>
drm/msm: Fix suspend/resume on i.MX5
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: fix shutdown hook in case GPU components failed to bind
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: tx-path: zero initialize outgoing CAN frames
Zqiang <qiang.zhang@windriver.com>
bpf: Fix umd memory leak in copy_process()
Jean-Philippe Brucker <jean-philippe@linaro.org>
libbpf: Fix BTF dump of pointer-to-array-of-struct
Hangbin Liu <liuhangbin@gmail.com>
selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
David Brazdil <dbrazdil@google.com>
selinux: vsock: Set SID for socket returned by accept()
Corentin Labbe <clabbe@baylibre.com>
net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
Hayes Wang <hayeswang@realtek.com>
r8152: limit the RX buffer size of RTL8153A for USB 2.0
Jesse Brandeburg <jesse.brandeburg@intel.com>
igb: check timestamp validity
Johan Hovold <johan@kernel.org>
net: cdc-phonet: fix data-interface release on probe failure
Jiri Bohac <jbohac@suse.cz>
net: check all name nodes in __dev_alloc_name
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-af: fix infinite loop in unmapping NPC counter
Geetha sowjanya <gakula@marvell.com>
octeontx2-pf: Clear RSS enable flag on interace down
Geetha sowjanya <gakula@marvell.com>
octeontx2-af: Fix irq free in rvu teardown
Subbaraya Sundeep <sbhatta@marvell.com>
octeontx2-af: Remove TOS field from MKEX TX
Stanislaw Kardach <skardach@marvell.com>
octeontx2-af: Modify default KEX profile to extract TX packet fields
Rakesh Babu <rsaladi2@marvell.com>
octeontx2-af: Formatting debugfs entry rsrc_alloc.
Jakub Kicinski <kuba@kernel.org>
ipv6: weaken the v4mapped source check
dillon min <dillon.minfei@gmail.com>
ARM: dts: imx6ull: fix ubi filesystem mount failed
Kumar Kartikeya Dwivedi <memxor@gmail.com>
libbpf: Use SOCK_CLOEXEC when opening the netlink socket
Namhyung Kim <namhyung@kernel.org>
libbpf: Fix error path in bpf_object__elf_init()
Yinjun Zhang <yinjun.zhang@corigine.com>
netfilter: flowtable: Make sure GC works periodically in idle system
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: allow to update flowtable flags
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: report EOPNOTSUPP on unsupported flowtable flags
wenxu <wenxu@ucloud.cn>
net/sched: cls_flower: fix only mask bit check in the validate_ct_state
Shannon Nelson <snelson@pensando.io>
ionic: linearize tso skb with too many frags
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix check-before-set in the 7nm dsi_pll code
Alexei Starovoitov <ast@kernel.org>
ftrace: Fix modify_ftrace_direct.
Louis Peens <louis.peens@corigine.com>
nfp: flower: fix pre_tun mask id allocation
Louis Peens <louis.peens@corigine.com>
nfp: flower: add ipv6 bit to pre_tunnel control message
Louis Peens <louis.peens@corigine.com>
nfp: flower: fix unsupported pre_tunnel flows
Carlos Llamas <cmllamas@google.com>
selftests/net: fix warnings on reuseaddr_ports_exhausted
Brian Norris <briannorris@chromium.org>
mac80211: Allow HE operation to be longer than expected.
Johannes Berg <johannes.berg@intel.com>
mac80211: fix rate mask reset
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
Tong Zhang <ztong0001@gmail.com>
can: c_can: move runtime PM enable/disable to c_can_platform
Tong Zhang <ztong0001@gmail.com>
can: c_can_pci: c_can_pci_remove(): fix use-after-free
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Always disable bus load reporting
Angelo Dureghello <angelo@kernel-space.org>
can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
Stephane Grosjean <s.grosjean@peak-system.com>
can: peak_usb: add forgotten supported devices
Marc Kleine-Budde <mkl@pengutronix.de>
can: isotp: TX-path: ensure that CAN frame flags are initialized
Marc Kleine-Budde <mkl@pengutronix.de>
can: isotp: isotp_setsockopt(): only allow to set low level TX flags for CAN-FD
Alexander Ovechkin <ovov@yandex-team.ru>
tcp: relookup sock for RST+ACK packets handled by obsolete req sock
Eric Dumazet <edumazet@google.com>
tipc: better validate user input in tipc_nl_retrieve_key()
Ong Boon Leong <boon.leong.ong@intel.com>
net: phylink: Fix phylink_err() function name error in phylink_major_config
Xie He <xie.he.0141@gmail.com>
net: hdlc_x25: Prevent racing between "x25_close" and "x25_xmit"/"x25_rx"
Florian Westphal <fw@strlen.de>
netfilter: ctnetlink: fix dump of the expect mask attribute
Hangbin Liu <liuhangbin@gmail.com>
selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
Alexander Lobakin <alobakin@pm.me>
flow_dissector: fix byteorder of dissected ICMP ID
Eric Dumazet <edumazet@google.com>
net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
Alex Elder <elder@linaro.org>
net: ipa: terminate message handler arrays
Douglas Anderson <dianders@chromium.org>
clk: qcom: gcc-sc7180: Use floor ops for the correct sdcc1 clk
Dylan Hung <dylan_hung@aspeedtech.com>
ftgmac100: Restart MAC HW once
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Add power down exit reset state delay
Lv Yunlong <lyl2019@mail.ustc.edu.cn>
net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
Dinghao Liu <dinghao.liu@zju.edu.cn>
e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
Vitaly Lifshits <vitaly.lifshits@intel.com>
e1000e: add rtnl_lock() to e1000_reset_task
Andre Guedes <andre.guedes@intel.com>
igc: Fix igc_ptp_rx_pktstamp()
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Supported Pause Frame Link Setting
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Pause Frame Advertising
Sasha Neftin <sasha.neftin@intel.com>
igc: reinit_locked() should be called with rtnl_lock
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
Eric Dumazet <edumazet@google.com>
net: sched: validate stab values
Eric Dumazet <edumazet@google.com>
macvlan: macvlan_count_rx() needs to be aware of preemption
Ido Schimmel <idosch@nvidia.com>
drop_monitor: Perform cleanup upon probe registration failure
Wei Wang <weiwan@google.com>
ipv6: fix suspecious RCU usage warning
Maor Dickman <maord@nvidia.com>
net/mlx5e: Don't match on Geneve options in case option masks are all zero
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: When changing XDP program without reset, take refs for XSK RQs
Tariq Toukan <tariqt@nvidia.com>
net/mlx5e: RX, Mind the MPWQE gaps when calculating offsets
Georgi Valkov <gvalkov@abv.bg>
libbpf: Fix INSTALL flag order
Tal Lossos <tallossos@gmail.com>
bpf: Change inode_storage's lookup_elem return value from NULL to -EBADF
Maciej Fijalkowski <maciej.fijalkowski@intel.com>
veth: Store queue_mapping independently of XDP prog presence
Tony Lindgren <tony@atomide.com>
soc: ti: omap-prm: Fix occasional abort on reset deassert for dra7 iva
Tony Lindgren <tony@atomide.com>
ARM: OMAP2+: Fix smartreflex init regression after dropping legacy data
Grygorii Strashko <grygorii.strashko@ti.com>
bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
Mikulas Patocka <mpatocka@redhat.com>
dm ioctl: fix out of bounds array access when no devices
JeongHyeon Lee <jhs2.lee@samsung.com>
dm verity: fix DM_VERITY_OPTS_MAX value
Imre Deak <imre.deak@intel.com>
drm/i915: Fix the GT fence revocation runtime PM logic
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Add additional Sienna Cichlid PCI ID
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/display: restore AUX_DPHY_TX_CONTROL for DCN2.x
Kenneth Feng <kenneth.feng@amd.com>
drm/amd/pm: workaround for audio noise issue
Daniel Vetter <daniel.vetter@ffwll.ch>
drm/etnaviv: Use FOLL_FORCE for userptr
Mimi Zohar <zohar@linux.ibm.com>
integrity: double check iint_cache was initialized
Claudiu Beznea <claudiu.beznea@microchip.com>
ARM: dts: at91-sama5d27_som1: fix phy address to 7
Nicolas Ferre <nicolas.ferre@microchip.com>
ARM: dts: at91: sam9x60: fix mux-mask to match product's datasheet
Federico Pellegrin <fede@evolware.org>
ARM: dts: at91: sam9x60: fix mux-mask for PA7 so it can be set to A, B and C
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1043a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1012a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1046a: mark crypto engine dma coherent
Mark Rutland <mark.rutland@arm.com>
arm64: stacktrace: don't trace arch_stack_walk()
Vegard Nossum <vegard.nossum@oracle.com>
ACPICA: Always create namespace nodes using acpi_ns_create_node()
Chris Chiu <chris.chiu@canonical.com>
ACPI: video: Add missing callback back for Sony VPCEH3U1E
Nick Desaulniers <ndesaulniers@google.com>
gcov: fix clang-11+ support
Andrey Konovalov <andreyknvl@google.com>
kasan: fix per-page tags for non-page_alloc pages
Miaohe Lin <linmiaohe@huawei.com>
hugetlb_cgroup: fix imbalanced css_get and css_put pair for shared mappings
Phillip Lougher <phillip@squashfs.org.uk>
squashfs: fix xattr id and id lookup sanity checks
Sean Nyekjaer <sean@geanix.com>
squashfs: fix inode lookup sanity checks
Thomas Hebb <tommyhebb@gmail.com>
z3fold: prevent reclaim/free race for headless pages
Ido Schimmel <idosch@nvidia.com>
psample: Fix user API breakage
Hans de Goede <hdegoede@redhat.com>
platform/x86: intel-vbtn: Stop reporting SW_DOCK events
Mian Yousaf Kaukab <ykaukab@suse.de>
netsec: restore phy power state after controller reset
Ondrej Mosnacek <omosnace@redhat.com>
selinux: fix variable scope issue in live sidtab conversion
Ondrej Mosnacek <omosnace@redhat.com>
selinux: don't log MAC_POLICY_LOAD record on failed policy load
Filipe Manana <fdmanana@suse.com>
btrfs: fix sleep while in non-sleep context during qgroup removal
Sean Christopherson <seanjc@google.com>
KVM: x86: Protect userspace MSR filter with SRCU, and set atomically-ish
Peter Zijlstra <peterz@infradead.org>
static_call: Fix static_call_set_init()
Peter Zijlstra <peterz@infradead.org>
static_call: Fix the module key fixup
Josh Poimboeuf <jpoimboe@redhat.com>
static_call: Allow module use without exposing static_call_key
Peter Zijlstra <peterz@infradead.org>
static_call: Pull some static_call declarations to the type headers
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
Fenghua Yu <fenghua.yu@intel.com>
mm/fork: clear PASID for new mm
Daniel Wagner <dwagner@suse.de>
block: Suppress uevent for hidden device when removed
J. Bruce Fields <bfields@redhat.com>
nfs: we don't support removing system.nfs4_acl
Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
Lv Yunlong <lyl2019@mail.ustc.edu.cn>
nvme-rdma: Fix a use after free in nvmet_rdma_write_data_done
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvme-core: check ctrl css before setting up zns
Hannes Reinecke <hare@suse.de>
nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
Hannes Reinecke <hare@suse.de>
nvme-fc: set NVME_REQ_CANCELLED in nvme_fc_terminate_exchange()
Hannes Reinecke <hare@suse.de>
nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
Hannes Reinecke <hare@suse.de>
nvme: simplify error logic in nvme_validate_ns()
Christian König <christian.koenig@amd.com>
drm/radeon: fix AGP dependency
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu: fb BO should be ttm_bo_type_device
Sung Lee <sung.lee@amd.com>
drm/amd/display: Revert dram_clock_change_latency for DCN2.1
Damien Le Moal <damien.lemoal@wdc.com>
block: Fix REQ_OP_ZONE_RESET_ALL handling
satya priya <skakit@codeaurora.org>
regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
Mark Brown <broonie@kernel.org>
kselftest: arm64: Fix exit code of sve-ptrace
Peter Zijlstra <peterz@infradead.org>
u64_stats,lockdep: Fix u64_stats_init() vs lockdep
Julian Braha <julianbraha@gmail.com>
staging: rtl8192e: fix kconfig dependency on CRYPTO
Tomer Tayar <ttayar@habana.ai>
habanalabs: Call put_pid() when releasing control device
Rob Gardner <rob.gardner@oracle.com>
sparc64: Fix opcode filtering in handling of no fault loads
Wei Yongjun <weiyongjun1@huawei.com>
umem: fix error return code in mm_pci_probe()
Jiri Slaby <jirislaby@kernel.org>
kbuild: dummy-tools: fix inverted tests for gcc
Masahiro Yamada <masahiroy@kernel.org>
kbuild: add image_name to no-sync-config-targets
Paul Cercueil <paul@crapouillou.net>
irqchip/ingenic: Add support for the JZ4760
Paulo Alcantara <pc@cjr.nz>
cifs: change noisy error message to FYI
Tong Zhang <ztong0001@gmail.com>
atm: idt77252: fix null-ptr-dereference
Tong Zhang <ztong0001@gmail.com>
atm: uPD98402: fix incorrect allocation
Alex Marginean <alexandru.marginean@nxp.com>
net: enetc: set MAC RX FIFO to recommended value
Paul Cercueil <paul@crapouillou.net>
net: davicom: Use platform_get_irq_optional()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: wan: fix error return code of uhdlc_init()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
Frank Sorenson <sorenson@redhat.com>
NFS: Correct size calculation for create reply length
Timo Rothenpieler <timo@rothenpieler.org>
nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
Yang Li <yang.lee@linux.alibaba.com>
gpiolib: acpi: Add missing IRQF_ONESHOT
Sudeep Holla <sudeep.holla@arm.com>
cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
Bob Peterson <rpeterso@redhat.com>
gfs2: fix use-after-free in trans_drain
Aurelien Aptel <aaptel@suse.com>
cifs: ask for more credit on async read/write code paths
Michael Braun <michael-dev@fami-braun.de>
gianfar: fix jumbo packets+napi+rx overrun crash
Denis Efremov <efremov@linux.com>
sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
Jia-Ju Bai <baijiaju1990@gmail.com>
net: intel: iavf: fix error return code of iavf_init_get_resources()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: tehuti: fix error return code in bdx_probe()
Xunlei Pang <xlpang@linux.alibaba.com>
blk-cgroup: Fix the recursive blkg rwstat
Nitin Rawat <nitirawa@codeaurora.org>
scsi: ufs: ufs-qcom: Disable interrupt in reset path
Dinghao Liu <dinghao.liu@zju.edu.cn>
ixgbe: Fix memleak in ixgbe_configure_clsu32
Mark Pearson <markpearson@lenovo.com>
ALSA: hda: ignore invalid NHLT table
Hayes Wang <hayeswang@realtek.com>
Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
Tong Zhang <ztong0001@gmail.com>
atm: lanai: dont run lanai_dev_close if not open
Tong Zhang <ztong0001@gmail.com>
atm: eni: dont release is never initialized
Michael Ellerman <mpe@ellerman.id.au>
powerpc/4xx: Fix build errors from mfdcr()
Heiko Thiery <heiko.thiery@gmail.com>
net: fec: ptp: avoid register access when ipg clock is disabled
Joakim Zhang <qiangqing.zhang@nxp.com>
net: stmmac: fix dma physical address of descriptor when display ring
Felix Fietkau <nbd@nbd.name>
mt76: fix tx skb error handling in mt76_dma_tx_queue_skb
Zhou Guanghui <zhouguanghui1@huawei.com>
mm/memcg: set memcg when splitting page
Zhou Guanghui <zhouguanghui1@huawei.com>
mm/memcg: rename mem_cgroup_split_huge_fixup to split_page_memcg and add nr_pages argument
-------------
Diffstat:
Documentation/virt/kvm/api.rst | 6 +-
Makefile | 7 +-
arch/arm/boot/dts/at91-sam9x60ek.dts | 8 --
arch/arm/boot/dts/at91-sama5d27_som1.dtsi | 4 +-
arch/arm/boot/dts/imx6ull-myir-mys-6ulx-eval.dts | 1 +
arch/arm/boot/dts/sam9x60.dtsi | 9 ++
arch/arm/mach-omap2/sr_device.c | 75 ++++++++---
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 1 +
arch/arm64/kernel/crash_dump.c | 2 +
arch/arm64/kernel/stacktrace.c | 9 +-
arch/ia64/include/asm/syscall.h | 2 +-
arch/ia64/kernel/ptrace.c | 24 +++-
arch/powerpc/include/asm/dcr-native.h | 8 +-
arch/sparc/kernel/traps_64.c | 13 +-
arch/x86/include/asm/kvm_host.h | 14 +-
arch/x86/include/asm/static_call.h | 7 +
arch/x86/include/asm/xen/page.h | 12 --
arch/x86/kvm/x86.c | 109 +++++++++------
arch/x86/mm/mem_encrypt.c | 2 +-
arch/x86/xen/p2m.c | 7 +-
arch/x86/xen/setup.c | 16 ++-
block/blk-cgroup-rwstat.c | 3 +-
block/blk-merge.c | 8 ++
block/blk-zoned.c | 2 +-
block/genhd.c | 4 +-
drivers/acpi/acpica/nsaccess.c | 3 +-
drivers/acpi/internal.h | 6 +-
drivers/acpi/scan.c | 88 +++++++-----
drivers/acpi/video_detect.c | 1 +
drivers/atm/eni.c | 3 +-
drivers/atm/idt77105.c | 4 +-
drivers/atm/lanai.c | 5 +-
drivers/atm/uPD98402.c | 2 +-
drivers/base/power/runtime.c | 45 ++++++-
drivers/block/umem.c | 5 +-
drivers/bus/omap_l3_noc.c | 4 +-
drivers/clk/qcom/gcc-sc7180.c | 4 +-
drivers/cpufreq/cpufreq-dt-platdev.c | 2 +
drivers/gpio/gpiolib-acpi.c | 2 +-
drivers/gpu/drm/Kconfig | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2 +-
.../drm/amd/display/dc/dcn20/dcn20_link_encoder.c | 3 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 +-
.../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 54 ++++++++
.../gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 74 +++++++++--
.../gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 24 ++++
.../gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 25 ++++
drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2 +-
drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 13 +-
drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++-
drivers/gpu/drm/i915/intel_runtime_pm.h | 5 +
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 2 +-
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 6 +-
drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c | 5 +-
drivers/gpu/drm/msm/msm_drv.c | 12 ++
drivers/infiniband/hw/cxgb4/cm.c | 4 +-
drivers/irqchip/irq-ingenic-tcu.c | 1 +
drivers/irqchip/irq-ingenic.c | 1 +
drivers/md/dm-ioctl.c | 2 +-
drivers/md/dm-table.c | 33 +++--
drivers/md/dm-verity-target.c | 2 +-
drivers/md/dm-zoned-target.c | 2 +-
drivers/misc/habanalabs/common/device.c | 2 +
drivers/net/bonding/bond_main.c | 8 +-
drivers/net/can/c_can/c_can.c | 24 +---
drivers/net/can/c_can/c_can_pci.c | 3 +-
drivers/net/can/c_can/c_can_platform.c | 6 +-
drivers/net/can/dev.c | 1 +
drivers/net/can/flexcan.c | 8 +-
drivers/net/can/kvaser_pciefd.c | 4 +
drivers/net/can/m_can/m_can.c | 5 +-
drivers/net/dsa/b53/b53_common.c | 14 +-
drivers/net/dsa/bcm_sf2.c | 6 +-
.../chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 2 +-
drivers/net/ethernet/davicom/dm9000.c | 2 +-
drivers/net/ethernet/faraday/ftgmac100.c | 1 +
drivers/net/ethernet/freescale/enetc/enetc_hw.h | 2 +
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6 +
drivers/net/ethernet/freescale/fec_ptp.c | 7 +
drivers/net/ethernet/freescale/gianfar.c | 15 +++
drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4 +-
drivers/net/ethernet/intel/e1000e/82571.c | 2 +
drivers/net/ethernet/intel/e1000e/netdev.c | 6 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 3 +-
drivers/net/ethernet/intel/igb/igb.h | 4 +-
drivers/net/ethernet/intel/igb/igb_main.c | 33 +++--
drivers/net/ethernet/intel/igb/igb_ptp.c | 31 ++++-
drivers/net/ethernet/intel/igc/igc.h | 2 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 7 +-
drivers/net/ethernet/intel/igc/igc_main.c | 9 ++
drivers/net/ethernet/intel/igc/igc_ptp.c | 72 +++++-----
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +-
drivers/net/ethernet/marvell/octeontx2/af/npc.h | 31 +++++
.../ethernet/marvell/octeontx2/af/npc_profile.h | 97 ++++++++++++--
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 4 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 48 ++++---
.../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 4 +
.../net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2 +-
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5 +
drivers/net/ethernet/mellanox/mlx5/core/en.h | 7 +-
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 3 +-
.../ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c | 4 +
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 6 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 17 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 54 ++++++--
.../net/ethernet/netronome/nfp/flower/metadata.c | 24 +++-
.../net/ethernet/netronome/nfp/flower/offload.c | 18 +++
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 15 ++-
drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 13 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 3 +
drivers/net/ethernet/realtek/r8169_main.c | 6 +-
drivers/net/ethernet/socionext/netsec.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 50 +++++--
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 +-
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 57 +++++---
drivers/net/ethernet/sun/niu.c | 2 -
drivers/net/ethernet/tehuti/tehuti.c | 1 +
drivers/net/ethernet/xilinx/xilinx_axienet.h | 3 +
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 125 +++++++++++++-----
drivers/net/ipa/ipa_qmi.c | 2 +
drivers/net/phy/broadcom.c | 147 +++++++++++++++------
drivers/net/phy/dp83822.c | 3 +
drivers/net/phy/dp83869.c | 4 +
drivers/net/phy/lxt.c | 1 +
drivers/net/phy/marvell.c | 1 +
drivers/net/phy/marvell10g.c | 2 +
drivers/net/phy/micrel.c | 14 +-
drivers/net/phy/phy.c | 2 +-
drivers/net/phy/phy_device.c | 9 ++
drivers/net/phy/phylink.c | 2 +-
drivers/net/usb/cdc-phonet.c | 2 +
drivers/net/usb/r8152.c | 40 ++----
drivers/net/veth.c | 3 +-
drivers/net/wan/fsl_ucc_hdlc.c | 8 +-
drivers/net/wan/hdlc_x25.c | 42 +++++-
drivers/net/wireless/mediatek/mt76/dma.c | 15 +--
drivers/nvme/host/core.c | 15 ++-
drivers/nvme/host/fc.c | 3 +-
drivers/nvme/host/pci.c | 1 +
drivers/nvme/target/rdma.c | 5 +-
drivers/platform/x86/intel-vbtn.c | 12 +-
drivers/regulator/qcom-rpmh-regulator.c | 4 +-
drivers/scsi/mpt3sas/mpt3sas_base.c | 8 +-
drivers/scsi/qedi/qedi_main.c | 1 +
drivers/scsi/qla2xxx/qla_target.c | 13 +-
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 -
drivers/scsi/ufs/ufs-qcom.c | 10 ++
drivers/soc/ti/omap_prm.c | 6 +-
drivers/staging/rtl8192e/Kconfig | 1 +
drivers/xen/Kconfig | 4 +-
fs/btrfs/qgroup.c | 12 +-
fs/cachefiles/rdwr.c | 7 +-
fs/cifs/cifsglob.h | 4 +-
fs/cifs/cifspdu.h | 5 +
fs/cifs/smb2glob.h | 1 +
fs/cifs/smb2ops.c | 27 +++-
fs/cifs/smb2pdu.c | 6 +-
fs/cifs/smb2transport.c | 37 ++++--
fs/cifs/transport.c | 2 +-
fs/ext4/mballoc.c | 11 +-
fs/ext4/xattr.c | 4 +
fs/gfs2/log.c | 4 +
fs/gfs2/trans.c | 2 +
fs/io_uring.c | 4 +-
fs/nfs/Kconfig | 2 +-
fs/nfs/nfs3xdr.c | 3 +-
fs/nfs/nfs4proc.c | 3 +
fs/squashfs/export.c | 8 +-
fs/squashfs/id.c | 6 +-
fs/squashfs/squashfs_fs.h | 1 +
fs/squashfs/xattr_id.c | 6 +-
include/acpi/acpi_bus.h | 1 +
include/asm-generic/vmlinux.lds.h | 5 +-
include/linux/bpf.h | 9 +-
include/linux/brcmphy.h | 4 +
include/linux/device-mapper.h | 15 ++-
include/linux/hugetlb_cgroup.h | 15 ++-
include/linux/if_macvlan.h | 3 +-
include/linux/memcontrol.h | 6 +-
include/linux/mm.h | 15 ++-
include/linux/mm_types.h | 1 +
include/linux/mmu_notifier.h | 10 +-
include/linux/mutex.h | 2 +-
include/linux/netfilter/x_tables.h | 7 +-
include/linux/pagemap.h | 1 -
include/linux/phy.h | 2 +
include/linux/static_call.h | 43 +++---
include/linux/static_call_types.h | 50 +++++++
include/linux/u64_stats_sync.h | 7 +-
include/linux/usermode_driver.h | 1 +
include/net/dst.h | 11 ++
include/net/inet_connection_sock.h | 2 +-
include/net/netfilter/nf_tables.h | 3 +
include/net/nexthop.h | 24 ++++
include/net/red.h | 10 +-
include/net/rtnetlink.h | 2 +
include/uapi/linux/psample.h | 5 +-
kernel/bpf/bpf_inode_storage.c | 2 +-
kernel/bpf/preload/bpf_preload_kern.c | 19 ++-
kernel/fork.c | 8 ++
kernel/gcov/clang.c | 69 ++++++++++
kernel/power/energy_model.c | 2 +-
kernel/static_call.c | 71 ++++++++--
kernel/trace/ftrace.c | 43 +++++-
kernel/usermode_driver.c | 21 ++-
mm/huge_memory.c | 2 +-
mm/hugetlb.c | 41 +++++-
mm/hugetlb_cgroup.c | 10 +-
mm/memcontrol.c | 17 ++-
mm/mmu_notifier.c | 23 ++++
mm/page_alloc.c | 1 +
mm/z3fold.c | 16 ++-
net/bridge/br_switchdev.c | 2 +
net/can/isotp.c | 18 ++-
net/core/dev.c | 14 +-
net/core/drop_monitor.c | 23 ++++
net/core/dst.c | 59 ++++++---
net/core/flow_dissector.c | 2 +-
net/dccp/ipv6.c | 5 +
net/ipv4/inet_connection_sock.c | 7 +-
net/ipv4/netfilter/arp_tables.c | 16 +--
net/ipv4/netfilter/ip_tables.c | 16 +--
net/ipv4/route.c | 45 ++-----
net/ipv4/tcp_minisocks.c | 7 +-
net/ipv6/ip6_fib.c | 2 +-
net/ipv6/ip6_input.c | 10 --
net/ipv6/netfilter/ip6_tables.c | 16 +--
net/ipv6/route.c | 36 ++---
net/ipv6/tcp_ipv6.c | 5 +
net/mac80211/cfg.c | 4 +-
net/mac80211/ibss.c | 2 +
net/mac80211/mlme.c | 2 +-
net/mac80211/util.c | 2 +-
net/mptcp/subflow.c | 5 +
net/netfilter/nf_conntrack_netlink.c | 1 +
net/netfilter/nf_flow_table_core.c | 2 +-
net/netfilter/nf_tables_api.c | 19 ++-
net/netfilter/x_tables.c | 49 ++++---
net/qrtr/qrtr.c | 5 +
net/sched/cls_flower.c | 2 +-
net/sched/sch_choke.c | 7 +-
net/sched/sch_gred.c | 2 +-
net/sched/sch_red.c | 7 +-
net/sched/sch_sfq.c | 2 +-
net/tipc/node.c | 11 +-
net/vmw_vsock/af_vsock.c | 1 +
scripts/dummy-tools/gcc | 5 +
security/integrity/iint.c | 8 ++
security/selinux/include/security.h | 15 ++-
security/selinux/selinuxfs.c | 13 +-
security/selinux/ss/services.c | 63 +++++----
sound/hda/intel-nhlt.c | 5 +
tools/include/linux/static_call_types.h | 50 +++++++
tools/lib/bpf/Makefile | 2 +-
tools/lib/bpf/btf_dump.c | 2 +-
tools/lib/bpf/libbpf.c | 3 +-
tools/lib/bpf/netlink.c | 2 +-
tools/objtool/check.c | 17 ++-
tools/perf/util/auxtrace.c | 4 -
tools/perf/util/synthetic-events.c | 9 +-
tools/testing/selftests/arm64/fp/sve-ptrace.c | 2 +-
.../testing/selftests/bpf/progs/test_tunnel_kern.c | 6 +-
.../selftests/net/forwarding/vxlan_bridge_1d.sh | 2 +-
.../selftests/net/reuseaddr_ports_exhausted.c | 32 ++---
271 files changed, 2578 insertions(+), 970 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.11 204/254] PM: EM: postpone creating the debugfs dir till fs_initcall
2021-03-29 7:55 1% [PATCH 5.11 000/254] 5.11.11-rc1 review Greg Kroah-Hartman
@ 2021-03-29 7:58 12% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-29 7:58 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Ionela Voinescu, Lukasz Luba,
Rafael J. Wysocki, Sasha Levin
From: Lukasz Luba <lukasz.luba@arm.com>
[ Upstream commit fb9d62b27ab1e07d625591549c314b7d406d21df ]
The debugfs directory '/sys/kernel/debug/energy_model' is needed before
the Energy Model registration can happen. With the recent change in
debugfs subsystem it's not allowed to create this directory at early
stage (core_initcall). Thus creating this directory would fail.
Postpone the creation of the EM debug dir to later stage: fs_initcall.
It should be safe since all clients: CPUFreq drivers, Devfreq drivers
will be initialized in later stages.
The custom debug log below prints the time of creation the EM debug dir
at fs_initcall and successful registration of EMs at later stages.
[ 1.505717] energy_model: creating rootdir
[ 3.698307] cpu cpu0: EM: created perf domain
[ 3.709022] cpu cpu1: EM: created perf domain
Fixes: 56348560d495 ("debugfs: do not attempt to create a new file before the filesystem is initalized")
Reported-by: Ionela Voinescu <ionela.voinescu@arm.com>
Signed-off-by: Lukasz Luba <lukasz.luba@arm.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/power/energy_model.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index 1358fa4abfa8..0f4530b3a8cd 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -98,7 +98,7 @@ static int __init em_debug_init(void)
return 0;
}
-core_initcall(em_debug_init);
+fs_initcall(em_debug_init);
#else /* CONFIG_DEBUG_FS */
static void em_debug_create_pd(struct device *dev) {}
static void em_debug_remove_pd(struct device *dev) {}
--
2.30.1
^ permalink raw reply related [relevance 12%]
* [PATCH 5.11 000/254] 5.11.11-rc1 review
@ 2021-03-29 7:55 1% Greg Kroah-Hartman
2021-03-29 7:58 12% ` [PATCH 5.11 204/254] PM: EM: postpone creating the debugfs dir till fs_initcall Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2021-03-29 7:55 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.11.11 release.
There are 254 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 31 Mar 2021 07:55:56 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.11-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.11.11-rc1
Alexei Starovoitov <ast@kernel.org>
selftest/bpf: Add a test to check trampoline freeing logic.
Marc Kleine-Budde <mkl@pengutronix.de>
can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
Christoph Hellwig <hch@lst.de>
nvme: fix the nsid value to print in nvme_validate_or_alloc_ns
Roger Pau Monne <roger.pau@citrix.com>
Revert "xen: fix p2m size in dom0 for disabled memory hotplug case"
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
fs/ext4: fix integer overflow in s_log_groups_per_flex
Jan Kara <jack@suse.cz>
ext4: add reclaim checks to xattr code
Markus Theil <markus.theil@tu-ilmenau.de>
mac80211: fix double free in ibss_leave
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: b53: VLAN filtering is global to all users
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix DMA being used after buffer free if WoL is enabled
Martin Willi <martin@strongswan.org>
can: dev: Move device back to init netns on owning netns delete
Arnd Bergmann <arnd@arndb.de>
ch_ktls: fix enum-conversion warning
Matthew Wilcox (Oracle) <willy@infradead.org>
fs/cachefiles: Remove wait_bit_key layout dependency
Isaku Yamahata <isaku.yamahata@intel.com>
x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
Thomas Gleixner <tglx@linutronix.de>
locking/mutex: Fix non debug version of mutex_lock_io_nested()
Shyam Prasad N <sprasad@microsoft.com>
cifs: Adjust key sizes and key generation routines for AES256 encryption
Steve French <stfrench@microsoft.com>
smb3: fix cached file size problems in duplicate extents (reflink)
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: qedi: Fix error return code of qedi_alloc_global_queues()
Bart Van Assche <bvanassche@acm.org>
scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
David Jeffery <djeffery@redhat.com>
block: recalculate segment count for multi-segment discards correctly
Pavel Begunkov <asml.silence@gmail.com>
io_uring: fix provide_buffers sign extension
Ian Rogers <irogers@google.com>
perf synthetic events: Avoid write of uninitialized memory when generating PERF_RECORD_MMAP* records
Adrian Hunter <adrian.hunter@intel.com>
perf auxtrace: Fix auxtrace queue conflict
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
ACPI: scan: Use unique number for instance_no
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: scan: Rearrange memory allocation in acpi_device_add()
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Update remaining dereference to RCU"
Sean Christopherson <seanjc@google.com>
mm/mmu_notifiers: ensure range_end() is paired with range_start()
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
dm table: Fix zoned model check and zone sectors check
Pavel Tatashin <pasha.tatashin@soleen.com>
arm64: mm: correct the inside linear map range during hotplug check
Anshuman Khandual <anshuman.khandual@arm.com>
arm64/mm: define arch_get_mappable_range()
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Cleanup create_attributes_level_sysfs_files()
Stanislav Fomichev <sdf@google.com>
bpf: Use NOP_ATOMIC5 instead of emit_nops(&prog, 5) for BPF_TRAMP_F_CALL_ORIG
Alexei Starovoitov <ast@kernel.org>
bpf: Fix fexit trampoline.
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
netfilter: x_tables: Use correct memory barriers.
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Switch synchronization to RCU"
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Fix RGMII delays for BCM50160 and BCM50610M
Robert Hancock <robert.hancock@calian.com>
net: phy: broadcom: Set proper 1000BaseX/SGMII interface mode for BCM54616S
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Avoid forward for bcm54xx_config_clock_delay()
Michael Walle <michael@walle.cc>
net: phy: introduce phydev->port
Robert Hancock <robert.hancock@calian.com>
net: axienet: Fix probe error cleanup
Li RongQing <lirongqing@baidu.com>
igb: avoid premature Rx buffer reuse
Daniel Borkmann <daniel@iogearbox.net>
net, bpf: Fix ip6ip6 crash with collect_md populated skbs
Daniel Borkmann <daniel@iogearbox.net>
net: Consolidate common blackhole dst ops
Sasha Levin <sashal@kernel.org>
bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
Mike Rapoport <rppt@kernel.org>
mm: memblock: fix section mismatch warning again
Potnuri Bharat Teja <bharat@chelsio.com>
RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server
Roger Pau Monne <roger.pau@citrix.com>
xen/x86: make XEN_BALLOON_MEMORY_HOTPLUG_LIMIT depend on MEMORY_HOTPLUG
Colin Ian King <colin.king@canonical.com>
octeontx2-af: Fix memory leak of object buf
Vladimir Oltean <vladimir.oltean@nxp.com>
net: bridge: don't notify switchdev for local FDB addresses
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt_crashlog: Fix incorrect macros
Lukasz Luba <lukasz.luba@arm.com>
PM: EM: postpone creating the debugfs dir till fs_initcall
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
mfd: intel_quark_i2c_gpio: Revert "Constify static struct resources"
Aya Levin <ayal@nvidia.com>
net/mlx5e: Fix error path for ethtool set-priv-flag
Dima Chumak <dchumak@nvidia.com>
net/mlx5e: Offload tuple rewrite for non-CT flows
Alaa Hleihel <alaa@nvidia.com>
net/mlx5e: Allow to match on MPLS parameters only for MPLS over UDP
Huy Nguyen <huyn@nvidia.com>
net/mlx5: Add back multicast stats for uplink representor
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PM: runtime: Defer suspending suppliers
Pavel Tatashin <pasha.tatashin@soleen.com>
arm64: kdump: update ppos when reading elfcorehdr
Fabio Estevam <festevam@gmail.com>
drm/msm: Fix suspend/resume on i.MX5
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: fix shutdown hook in case GPU components failed to bind
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Make sysman_init() return -ENODEV of the interfaces are not found
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Cleanup sysman_init() error-exit handling
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Fix release_attributes_data() getting called twice on init_bios_attributes() failure
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Make it safe to call exit_foo_attributes() multiple times
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Fix possible NULL pointer deref on exit
Hans de Goede <hdegoede@redhat.com>
platform/x86: dell-wmi-sysman: Fix crash caused by calling kset_unregister twice
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: tx-path: zero initialize outgoing CAN frames
Zqiang <qiang.zhang@windriver.com>
bpf: Fix umd memory leak in copy_process()
Jean-Philippe Brucker <jean-philippe@linaro.org>
libbpf: Fix BTF dump of pointer-to-array-of-struct
Hangbin Liu <liuhangbin@gmail.com>
selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
David Brazdil <dbrazdil@google.com>
selinux: vsock: Set SID for socket returned by accept()
Corentin Labbe <clabbe@baylibre.com>
net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
Hayes Wang <hayeswang@realtek.com>
r8152: limit the RX buffer size of RTL8153A for USB 2.0
Xin Long <lucien.xin@gmail.com>
sctp: move sk_route_caps check and set into sctp_outq_flush_transports
Jesse Brandeburg <jesse.brandeburg@intel.com>
igb: check timestamp validity
Johan Hovold <johan@kernel.org>
net: cdc-phonet: fix data-interface release on probe failure
Jiri Bohac <jbohac@suse.cz>
net: check all name nodes in __dev_alloc_name
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-af: fix infinite loop in unmapping NPC counter
Geetha sowjanya <gakula@marvell.com>
octeontx2-pf: Clear RSS enable flag on interace down
Geetha sowjanya <gakula@marvell.com>
octeontx2-af: Fix irq free in rvu teardown
Subbaraya Sundeep <sbhatta@marvell.com>
octeontx2-af: Remove TOS field from MKEX TX
Rakesh Babu <rsaladi2@marvell.com>
octeontx2-af: Formatting debugfs entry rsrc_alloc.
Jakub Kicinski <kuba@kernel.org>
ipv6: weaken the v4mapped source check
dillon min <dillon.minfei@gmail.com>
ARM: dts: imx6ull: fix ubi filesystem mount failed
Kumar Kartikeya Dwivedi <memxor@gmail.com>
libbpf: Use SOCK_CLOEXEC when opening the netlink socket
Namhyung Kim <namhyung@kernel.org>
libbpf: Fix error path in bpf_object__elf_init()
Yinjun Zhang <yinjun.zhang@corigine.com>
netfilter: flowtable: Make sure GC works periodically in idle system
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: allow to update flowtable flags
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: report EOPNOTSUPP on unsupported flowtable flags
wenxu <wenxu@ucloud.cn>
net/sched: cls_flower: fix only mask bit check in the validate_ct_state
Shannon Nelson <snelson@pensando.io>
ionic: linearize tso skb with too many frags
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix check-before-set in the 7nm dsi_pll code
Alexei Starovoitov <ast@kernel.org>
ftrace: Fix modify_ftrace_direct.
Louis Peens <louis.peens@corigine.com>
nfp: flower: fix pre_tun mask id allocation
Louis Peens <louis.peens@corigine.com>
nfp: flower: add ipv6 bit to pre_tunnel control message
Louis Peens <louis.peens@corigine.com>
nfp: flower: fix unsupported pre_tunnel flows
Carlos Llamas <cmllamas@google.com>
selftests/net: fix warnings on reuseaddr_ports_exhausted
Brian Norris <briannorris@chromium.org>
mac80211: Allow HE operation to be longer than expected.
Johannes Berg <johannes.berg@intel.com>
mac80211: fix rate mask reset
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
Tong Zhang <ztong0001@gmail.com>
can: c_can: move runtime PM enable/disable to c_can_platform
Tong Zhang <ztong0001@gmail.com>
can: c_can_pci: c_can_pci_remove(): fix use-after-free
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Always disable bus load reporting
Angelo Dureghello <angelo@kernel-space.org>
can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
Stephane Grosjean <s.grosjean@peak-system.com>
can: peak_usb: add forgotten supported devices
Marc Kleine-Budde <mkl@pengutronix.de>
can: isotp: TX-path: ensure that CAN frame flags are initialized
Marc Kleine-Budde <mkl@pengutronix.de>
can: isotp: isotp_setsockopt(): only allow to set low level TX flags for CAN-FD
Davide Caratti <dcaratti@redhat.com>
mptcp: fix ADD_ADDR HMAC in case port is specified
Alexander Ovechkin <ovov@yandex-team.ru>
tcp: relookup sock for RST+ACK packets handled by obsolete req sock
Eric Dumazet <edumazet@google.com>
tipc: better validate user input in tipc_nl_retrieve_key()
Ong Boon Leong <boon.leong.ong@intel.com>
net: phylink: Fix phylink_err() function name error in phylink_major_config
Xie He <xie.he.0141@gmail.com>
net: hdlc_x25: Prevent racing between "x25_close" and "x25_xmit"/"x25_rx"
Florian Westphal <fw@strlen.de>
netfilter: ctnetlink: fix dump of the expect mask attribute
Hangbin Liu <liuhangbin@gmail.com>
selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
Alexander Lobakin <alobakin@pm.me>
flow_dissector: fix byteorder of dissected ICMP ID
Eric Dumazet <edumazet@google.com>
net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
Alex Elder <elder@linaro.org>
net: ipa: terminate message handler arrays
Douglas Anderson <dianders@chromium.org>
clk: qcom: gcc-sc7180: Use floor ops for the correct sdcc1 clk
Dylan Hung <dylan_hung@aspeedtech.com>
ftgmac100: Restart MAC HW once
Magnus Karlsson <magnus.karlsson@intel.com>
ice: fix napi work done reporting in xsk path
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Add power down exit reset state delay
Lv Yunlong <lyl2019@mail.ustc.edu.cn>
net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
David Gow <davidgow@google.com>
kunit: tool: Disable PAGE_POISONING under --alltests
Dinghao Liu <dinghao.liu@zju.edu.cn>
e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
Vitaly Lifshits <vitaly.lifshits@intel.com>
e1000e: add rtnl_lock() to e1000_reset_task
Andre Guedes <andre.guedes@intel.com>
igc: Fix igc_ptp_rx_pktstamp()
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Supported Pause Frame Link Setting
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Pause Frame Advertising
Sasha Neftin <sasha.neftin@intel.com>
igc: reinit_locked() should be called with rtnl_lock
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
Eric Dumazet <edumazet@google.com>
net: sched: validate stab values
Eric Dumazet <edumazet@google.com>
macvlan: macvlan_count_rx() needs to be aware of preemption
Ido Schimmel <idosch@nvidia.com>
drop_monitor: Perform cleanup upon probe registration failure
Wei Wang <weiwan@google.com>
ipv6: fix suspecious RCU usage warning
Parav Pandit <parav@nvidia.com>
net/mlx5e: E-switch, Fix rate calculation division
Maor Dickman <maord@nvidia.com>
net/mlx5e: Don't match on Geneve options in case option masks are all zero
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Revert parameters on errors when changing PTP state without reset
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: When changing XDP program without reset, take refs for XSK RQs
Aya Levin <ayal@nvidia.com>
net/mlx5e: Set PTP channel pointer explicitly to NULL
Tariq Toukan <tariqt@nvidia.com>
net/mlx5e: RX, Mind the MPWQE gaps when calculating offsets
Georgi Valkov <gvalkov@abv.bg>
libbpf: Fix INSTALL flag order
Tal Lossos <tallossos@gmail.com>
bpf: Change inode_storage's lookup_elem return value from NULL to -EBADF
Alexei Starovoitov <ast@kernel.org>
bpf: Dont allow vmlinux BTF to be used in map_create and prog_load.
Maciej Fijalkowski <maciej.fijalkowski@intel.com>
veth: Store queue_mapping independently of XDP prog presence
Tony Lindgren <tony@atomide.com>
soc: ti: omap-prm: Fix occasional abort on reset deassert for dra7 iva
Tony Lindgren <tony@atomide.com>
ARM: OMAP2+: Fix smartreflex init regression after dropping legacy data
Tony Lindgren <tony@atomide.com>
soc: ti: omap-prm: Fix reboot issue with invalid pcie reset map for dra7
Grygorii Strashko <grygorii.strashko@ti.com>
bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
Mikulas Patocka <mpatocka@redhat.com>
dm ioctl: fix out of bounds array access when no devices
Mikulas Patocka <mpatocka@redhat.com>
dm: don't report "detected capacity change" on device creation
JeongHyeon Lee <jhs2.lee@samsung.com>
dm verity: fix DM_VERITY_OPTS_MAX value
Imre Deak <imre.deak@intel.com>
drm/i915: Fix the GT fence revocation runtime PM logic
Jani Nikula <jani.nikula@intel.com>
drm/i915/dsc: fix DSS CTL register usage for ICL DSI transcoders
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Add additional Sienna Cichlid PCI ID
Prike Liang <Prike.Liang@amd.com>
drm/amdgpu: fix the hibernation suspend with s0ix
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/display: restore AUX_DPHY_TX_CONTROL for DCN2.x
Kenneth Feng <kenneth.feng@amd.com>
drm/amd/pm: workaround for audio noise issue
Daniel Vetter <daniel.vetter@ffwll.ch>
drm/etnaviv: Use FOLL_FORCE for userptr
Lyude Paul <lyude@redhat.com>
drm/nouveau/kms/nve4-nv108: Limit cursors to 128x128
Mimi Zohar <zohar@linux.ibm.com>
integrity: double check iint_cache was initialized
Claudiu Beznea <claudiu.beznea@microchip.com>
ARM: dts: at91-sama5d27_som1: fix phy address to 7
Nicolas Ferre <nicolas.ferre@microchip.com>
ARM: dts: at91: sam9x60: fix mux-mask to match product's datasheet
Federico Pellegrin <fede@evolware.org>
ARM: dts: at91: sam9x60: fix mux-mask for PA7 so it can be set to A, B and C
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1043a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1012a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1046a: mark crypto engine dma coherent
Mark Rutland <mark.rutland@arm.com>
arm64: stacktrace: don't trace arch_stack_walk()
Vegard Nossum <vegard.nossum@oracle.com>
ACPICA: Always create namespace nodes using acpi_ns_create_node()
Chris Chiu <chris.chiu@canonical.com>
ACPI: video: Add missing callback back for Sony VPCEH3U1E
Ira Weiny <ira.weiny@intel.com>
mm/highmem: fix CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP
Nick Desaulniers <ndesaulniers@google.com>
gcov: fix clang-11+ support
Andrey Konovalov <andreyknvl@google.com>
kasan: fix per-page tags for non-page_alloc pages
Miaohe Lin <linmiaohe@huawei.com>
hugetlb_cgroup: fix imbalanced css_get and css_put pair for shared mappings
Phillip Lougher <phillip@squashfs.org.uk>
squashfs: fix xattr id and id lookup sanity checks
Sean Nyekjaer <sean@geanix.com>
squashfs: fix inode lookup sanity checks
Thomas Hebb <tommyhebb@gmail.com>
z3fold: prevent reclaim/free race for headless pages
Ido Schimmel <idosch@nvidia.com>
psample: Fix user API breakage
Hans de Goede <hdegoede@redhat.com>
platform/x86: intel-vbtn: Stop reporting SW_DOCK events
Mian Yousaf Kaukab <ykaukab@suse.de>
netsec: restore phy power state after controller reset
Ondrej Mosnacek <omosnace@redhat.com>
selinux: fix variable scope issue in live sidtab conversion
Ondrej Mosnacek <omosnace@redhat.com>
selinux: don't log MAC_POLICY_LOAD record on failed policy load
Filipe Manana <fdmanana@suse.com>
btrfs: fix subvolume/snapshot deletion not triggered on mount
Filipe Manana <fdmanana@suse.com>
btrfs: fix sleep while in non-sleep context during qgroup removal
Josef Bacik <josef@toxicpanda.com>
btrfs: initialize device::fs_info always
Omar Sandoval <osandov@fb.com>
btrfs: fix check_data_csum() error message for direct I/O
Josef Bacik <josef@toxicpanda.com>
btrfs: do not initialize dev replace for bad dev root
Josef Bacik <josef@toxicpanda.com>
btrfs: do not initialize dev stats if we have no dev_root
Sean Christopherson <seanjc@google.com>
KVM: x86: Protect userspace MSR filter with SRCU, and set atomically-ish
Peter Zijlstra <peterz@infradead.org>
static_call: Fix static_call_set_init()
Peter Zijlstra <peterz@infradead.org>
static_call: Fix the module key fixup
Josh Poimboeuf <jpoimboe@redhat.com>
static_call: Allow module use without exposing static_call_key
Peter Zijlstra <peterz@infradead.org>
static_call: Pull some static_call declarations to the type headers
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
Fenghua Yu <fenghua.yu@intel.com>
mm/fork: clear PASID for new mm
Pavel Begunkov <asml.silence@gmail.com>
io_uring: cancel deferred requests in try_cancel
Daniel Wagner <dwagner@suse.de>
block: Suppress uevent for hidden device when removed
J. Bruce Fields <bfields@redhat.com>
nfs: we don't support removing system.nfs4_acl
Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
Lv Yunlong <lyl2019@mail.ustc.edu.cn>
nvme-rdma: Fix a use after free in nvmet_rdma_write_data_done
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvme-core: check ctrl css before setting up zns
Hannes Reinecke <hare@suse.de>
nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
Hannes Reinecke <hare@suse.de>
nvme-fc: set NVME_REQ_CANCELLED in nvme_fc_terminate_exchange()
Hannes Reinecke <hare@suse.de>
nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
Hannes Reinecke <hare@suse.de>
nvme: simplify error logic in nvme_validate_ns()
Christian König <christian.koenig@amd.com>
drm/radeon: fix AGP dependency
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu: fb BO should be ttm_bo_type_device
Zhan Liu <zhan.liu@amd.com>
drm/amdgpu/display: Use wm_table.entries for dcn301 calculate_wm
Dillon Varone <dillon.varone@amd.com>
drm/amd/display: Enabled pipe harvesting in dcn30
Sung Lee <sung.lee@amd.com>
drm/amd/display: Revert dram_clock_change_latency for DCN2.1
Qingqing Zhuo <qingqing.zhuo@amd.com>
drm/amd/display: Enable pflip interrupt upon pipe enable
Damien Le Moal <damien.lemoal@wdc.com>
block: Fix REQ_OP_ZONE_RESET_ALL handling
satya priya <skakit@codeaurora.org>
regulator: qcom-rpmh: Use correct buck for S1C regulator
satya priya <skakit@codeaurora.org>
regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
Mark Brown <broonie@kernel.org>
kselftest: arm64: Fix exit code of sve-ptrace
Peter Zijlstra <peterz@infradead.org>
u64_stats,lockdep: Fix u64_stats_init() vs lockdep
Julian Braha <julianbraha@gmail.com>
staging: rtl8192e: fix kconfig dependency on CRYPTO
Tomer Tayar <ttayar@habana.ai>
habanalabs: Disable file operations after device is removed
Tomer Tayar <ttayar@habana.ai>
habanalabs: Call put_pid() when releasing control device
Rob Gardner <rob.gardner@oracle.com>
sparc64: Fix opcode filtering in handling of no fault loads
Wei Yongjun <weiyongjun1@huawei.com>
umem: fix error return code in mm_pci_probe()
Jiri Slaby <jirislaby@kernel.org>
kbuild: dummy-tools: fix inverted tests for gcc
Masahiro Yamada <masahiroy@kernel.org>
kbuild: add image_name to no-sync-config-targets
Paul Cercueil <paul@crapouillou.net>
irqchip/ingenic: Add support for the JZ4760
Paulo Alcantara <pc@cjr.nz>
cifs: change noisy error message to FYI
Tong Zhang <ztong0001@gmail.com>
atm: idt77252: fix null-ptr-dereference
Tong Zhang <ztong0001@gmail.com>
atm: uPD98402: fix incorrect allocation
Alex Marginean <alexandru.marginean@nxp.com>
net: enetc: set MAC RX FIFO to recommended value
Paul Cercueil <paul@crapouillou.net>
net: davicom: Use platform_get_irq_optional()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: wan: fix error return code of uhdlc_init()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
Frank Sorenson <sorenson@redhat.com>
NFS: Correct size calculation for create reply length
Timo Rothenpieler <timo@rothenpieler.org>
nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
Yang Li <yang.lee@linux.alibaba.com>
gpiolib: acpi: Add missing IRQF_ONESHOT
Sudeep Holla <sudeep.holla@arm.com>
cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
Bob Peterson <rpeterso@redhat.com>
gfs2: fix use-after-free in trans_drain
Aurelien Aptel <aaptel@suse.com>
cifs: ask for more credit on async read/write code paths
Michael Braun <michael-dev@fami-braun.de>
gianfar: fix jumbo packets+napi+rx overrun crash
Denis Efremov <efremov@linux.com>
sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
Jia-Ju Bai <baijiaju1990@gmail.com>
net: intel: iavf: fix error return code of iavf_init_get_resources()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: tehuti: fix error return code in bdx_probe()
Xunlei Pang <xlpang@linux.alibaba.com>
blk-cgroup: Fix the recursive blkg rwstat
Nitin Rawat <nitirawa@codeaurora.org>
scsi: ufs: ufs-qcom: Disable interrupt in reset path
Dinghao Liu <dinghao.liu@zju.edu.cn>
ixgbe: Fix memleak in ixgbe_configure_clsu32
Mark Pearson <markpearson@lenovo.com>
ALSA: hda: ignore invalid NHLT table
Hayes Wang <hayeswang@realtek.com>
Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
Tong Zhang <ztong0001@gmail.com>
atm: lanai: dont run lanai_dev_close if not open
Tong Zhang <ztong0001@gmail.com>
atm: eni: dont release is never initialized
Michael Ellerman <mpe@ellerman.id.au>
powerpc/4xx: Fix build errors from mfdcr()
Heiko Thiery <heiko.thiery@gmail.com>
net: fec: ptp: avoid register access when ipg clock is disabled
Joakim Zhang <qiangqing.zhang@nxp.com>
net: stmmac: fix dma physical address of descriptor when display ring
Felix Fietkau <nbd@nbd.name>
mt76: mt7915: only modify tx buffer list after allocating tx token id
Felix Fietkau <nbd@nbd.name>
mt76: fix tx skb error handling in mt76_dma_tx_queue_skb
-------------
Diffstat:
Documentation/virt/kvm/api.rst | 6 +-
Makefile | 7 +-
arch/arm/boot/dts/at91-sam9x60ek.dts | 8 -
arch/arm/boot/dts/at91-sama5d27_som1.dtsi | 4 +-
arch/arm/boot/dts/imx6ull-myir-mys-6ulx-eval.dts | 1 +
arch/arm/boot/dts/sam9x60.dtsi | 9 +
arch/arm/mach-omap2/sr_device.c | 75 +++++--
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 1 +
arch/arm64/kernel/crash_dump.c | 2 +
arch/arm64/kernel/stacktrace.c | 9 +-
arch/arm64/mm/mmu.c | 32 ++-
arch/ia64/include/asm/syscall.h | 2 +-
arch/ia64/kernel/ptrace.c | 24 ++-
arch/powerpc/include/asm/dcr-native.h | 8 +-
arch/sparc/kernel/traps_64.c | 13 +-
arch/x86/include/asm/kvm_host.h | 14 +-
arch/x86/include/asm/static_call.h | 7 +
arch/x86/include/asm/xen/page.h | 12 --
arch/x86/kvm/x86.c | 109 ++++++-----
arch/x86/mm/mem_encrypt.c | 2 +-
arch/x86/net/bpf_jit_comp.c | 27 ++-
arch/x86/xen/p2m.c | 7 +-
arch/x86/xen/setup.c | 16 +-
block/blk-cgroup-rwstat.c | 3 +-
block/blk-merge.c | 8 +
block/blk-zoned.c | 2 +-
block/genhd.c | 4 +-
drivers/acpi/acpica/nsaccess.c | 3 +-
drivers/acpi/internal.h | 6 +-
drivers/acpi/scan.c | 88 +++++----
drivers/acpi/video_detect.c | 1 +
drivers/atm/eni.c | 3 +-
drivers/atm/idt77105.c | 4 +-
drivers/atm/lanai.c | 5 +-
drivers/atm/uPD98402.c | 2 +-
drivers/base/power/runtime.c | 45 ++++-
drivers/block/umem.c | 5 +-
drivers/bus/omap_l3_noc.c | 4 +-
drivers/clk/qcom/gcc-sc7180.c | 4 +-
drivers/cpufreq/cpufreq-dt-platdev.c | 2 +
drivers/gpio/gpiolib-acpi.c | 2 +-
drivers/gpu/drm/Kconfig | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 +
drivers/gpu/drm/amd/display/dc/dc.h | 1 +
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 11 ++
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h | 6 +
.../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 7 +
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 1 +
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 6 +
.../drm/amd/display/dc/dcn20/dcn20_link_encoder.c | 3 +-
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c | 1 +
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c | 1 +
.../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 31 +++
.../drm/amd/display/dc/dcn301/dcn301_resource.c | 96 ++++++++-
drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 2 +
.../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 54 +++++
.../gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 74 +++++--
.../gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 24 +++
.../gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 25 +++
drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2 +-
drivers/gpu/drm/i915/display/intel_vdsc.c | 10 +-
drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 13 +-
drivers/gpu/drm/i915/intel_runtime_pm.c | 29 ++-
drivers/gpu/drm/i915/intel_runtime_pm.h | 5 +
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 2 +-
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 6 +-
drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c | 5 +-
drivers/gpu/drm/msm/msm_drv.c | 12 ++
drivers/gpu/drm/nouveau/dispnv50/disp.c | 13 +-
drivers/infiniband/hw/cxgb4/cm.c | 4 +-
drivers/irqchip/irq-ingenic-tcu.c | 1 +
drivers/irqchip/irq-ingenic.c | 1 +
drivers/md/dm-ioctl.c | 2 +-
drivers/md/dm-table.c | 33 +++-
drivers/md/dm-verity-target.c | 2 +-
drivers/md/dm-zoned-target.c | 2 +-
drivers/md/dm.c | 5 +-
drivers/mfd/intel_quark_i2c_gpio.c | 6 +-
drivers/misc/habanalabs/common/device.c | 40 +++-
drivers/misc/habanalabs/common/habanalabs_ioctl.c | 12 ++
drivers/net/can/c_can/c_can.c | 24 +--
drivers/net/can/c_can/c_can_pci.c | 3 +-
drivers/net/can/c_can/c_can_platform.c | 6 +-
drivers/net/can/dev.c | 1 +
drivers/net/can/flexcan.c | 8 +-
drivers/net/can/kvaser_pciefd.c | 4 +
drivers/net/can/m_can/m_can.c | 5 +-
drivers/net/dsa/b53/b53_common.c | 14 +-
drivers/net/dsa/bcm_sf2.c | 6 +-
.../chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 2 +-
drivers/net/ethernet/davicom/dm9000.c | 2 +-
drivers/net/ethernet/faraday/ftgmac100.c | 1 +
drivers/net/ethernet/freescale/enetc/enetc_hw.h | 2 +
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6 +
drivers/net/ethernet/freescale/fec_ptp.c | 7 +
drivers/net/ethernet/freescale/gianfar.c | 15 ++
drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4 +-
drivers/net/ethernet/intel/e1000e/82571.c | 2 +
drivers/net/ethernet/intel/e1000e/netdev.c | 6 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 3 +-
drivers/net/ethernet/intel/ice/ice_base.c | 6 +-
drivers/net/ethernet/intel/ice/ice_xsk.c | 10 +-
drivers/net/ethernet/intel/igb/igb.h | 4 +-
drivers/net/ethernet/intel/igb/igb_main.c | 33 ++--
drivers/net/ethernet/intel/igb/igb_ptp.c | 31 ++-
drivers/net/ethernet/intel/igc/igc.h | 2 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 7 +-
drivers/net/ethernet/intel/igc/igc_main.c | 9 +
drivers/net/ethernet/intel/igc/igc_ptp.c | 72 ++++---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +-
.../ethernet/marvell/octeontx2/af/npc_profile.h | 2 -
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 6 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 48 +++--
.../net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2 +-
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5 +
drivers/net/ethernet/mellanox/mlx5/core/en.h | 7 +-
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 3 +-
.../ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c | 4 +
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 11 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 21 +-
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 57 ++++--
.../net/ethernet/netronome/nfp/flower/metadata.c | 24 ++-
.../net/ethernet/netronome/nfp/flower/offload.c | 18 ++
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 15 +-
drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 13 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 3 +
drivers/net/ethernet/realtek/r8169_main.c | 6 +-
drivers/net/ethernet/socionext/netsec.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 50 ++++-
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 +-
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 57 ++++--
drivers/net/ethernet/sun/niu.c | 2 -
drivers/net/ethernet/tehuti/tehuti.c | 1 +
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 35 ++--
drivers/net/ipa/ipa_qmi.c | 2 +
drivers/net/phy/broadcom.c | 147 ++++++++++----
drivers/net/phy/dp83822.c | 3 +
drivers/net/phy/dp83869.c | 4 +
drivers/net/phy/lxt.c | 1 +
drivers/net/phy/marvell.c | 1 +
drivers/net/phy/marvell10g.c | 2 +
drivers/net/phy/micrel.c | 14 +-
drivers/net/phy/phy.c | 2 +-
drivers/net/phy/phy_device.c | 9 +
drivers/net/phy/phylink.c | 2 +-
drivers/net/usb/cdc-phonet.c | 2 +
drivers/net/usb/r8152.c | 40 +---
drivers/net/veth.c | 3 +-
drivers/net/wan/fsl_ucc_hdlc.c | 8 +-
drivers/net/wan/hdlc_x25.c | 42 +++-
drivers/net/wireless/mediatek/mt76/dma.c | 15 +-
drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 10 +-
drivers/nvme/host/core.c | 15 +-
drivers/nvme/host/fc.c | 3 +-
drivers/nvme/host/pci.c | 1 +
drivers/nvme/target/rdma.c | 5 +-
.../platform/x86/dell-wmi-sysman/enum-attributes.c | 3 +
.../platform/x86/dell-wmi-sysman/int-attributes.c | 3 +
.../x86/dell-wmi-sysman/passobj-attributes.c | 3 +
.../x86/dell-wmi-sysman/string-attributes.c | 3 +
drivers/platform/x86/dell-wmi-sysman/sysman.c | 84 +++-----
drivers/platform/x86/intel-vbtn.c | 12 +-
drivers/platform/x86/intel_pmt_crashlog.c | 13 +-
drivers/regulator/qcom-rpmh-regulator.c | 6 +-
drivers/scsi/mpt3sas/mpt3sas_base.c | 8 +-
drivers/scsi/qedi/qedi_main.c | 1 +
drivers/scsi/qla2xxx/qla_target.c | 13 +-
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 -
drivers/scsi/ufs/ufs-qcom.c | 10 +
drivers/soc/ti/omap_prm.c | 8 +-
drivers/staging/rtl8192e/Kconfig | 1 +
drivers/xen/Kconfig | 4 +-
fs/btrfs/dev-replace.c | 3 +
fs/btrfs/disk-io.c | 19 +-
fs/btrfs/inode.c | 14 +-
fs/btrfs/qgroup.c | 12 +-
fs/btrfs/volumes.c | 3 +
fs/cachefiles/rdwr.c | 7 +-
fs/cifs/cifsglob.h | 4 +-
fs/cifs/cifspdu.h | 5 +
fs/cifs/smb2glob.h | 1 +
fs/cifs/smb2ops.c | 27 ++-
fs/cifs/smb2pdu.c | 6 +-
fs/cifs/smb2transport.c | 37 +++-
fs/cifs/transport.c | 2 +-
fs/ext4/mballoc.c | 11 +-
fs/ext4/xattr.c | 4 +
fs/gfs2/log.c | 4 +
fs/gfs2/trans.c | 2 +
fs/io_uring.c | 14 +-
fs/nfs/Kconfig | 2 +-
fs/nfs/nfs3xdr.c | 3 +-
fs/nfs/nfs4proc.c | 3 +
fs/squashfs/export.c | 8 +-
fs/squashfs/id.c | 6 +-
fs/squashfs/squashfs_fs.h | 1 +
fs/squashfs/xattr_id.c | 6 +-
include/acpi/acpi_bus.h | 1 +
include/asm-generic/vmlinux.lds.h | 5 +-
include/linux/bpf.h | 33 +++-
include/linux/brcmphy.h | 4 +
include/linux/device-mapper.h | 15 +-
include/linux/hugetlb_cgroup.h | 15 +-
include/linux/if_macvlan.h | 3 +-
include/linux/memblock.h | 4 +-
include/linux/mm.h | 18 +-
include/linux/mm_types.h | 1 +
include/linux/mmu_notifier.h | 10 +-
include/linux/mutex.h | 2 +-
include/linux/netfilter/x_tables.h | 7 +-
include/linux/pagemap.h | 1 -
include/linux/phy.h | 2 +
include/linux/static_call.h | 43 ++--
include/linux/static_call_types.h | 50 +++++
include/linux/u64_stats_sync.h | 7 +-
include/linux/usermode_driver.h | 1 +
include/net/dst.h | 11 ++
include/net/inet_connection_sock.h | 2 +-
include/net/netfilter/nf_tables.h | 3 +
include/net/nexthop.h | 24 +++
include/net/red.h | 10 +-
include/net/rtnetlink.h | 2 +
include/uapi/linux/psample.h | 5 +-
kernel/bpf/bpf_inode_storage.c | 2 +-
kernel/bpf/bpf_struct_ops.c | 2 +-
kernel/bpf/core.c | 4 +-
kernel/bpf/preload/bpf_preload_kern.c | 19 +-
kernel/bpf/syscall.c | 5 +
kernel/bpf/trampoline.c | 218 ++++++++++++++++-----
kernel/bpf/verifier.c | 4 +
kernel/fork.c | 8 +
kernel/gcov/clang.c | 69 +++++++
kernel/power/energy_model.c | 2 +-
kernel/static_call.c | 71 ++++++-
kernel/trace/ftrace.c | 43 +++-
kernel/usermode_driver.c | 21 +-
mm/highmem.c | 4 +-
mm/hugetlb.c | 41 +++-
mm/hugetlb_cgroup.c | 10 +-
mm/mmu_notifier.c | 23 +++
mm/z3fold.c | 16 +-
net/bridge/br_switchdev.c | 2 +
net/can/isotp.c | 18 +-
net/core/dev.c | 14 +-
net/core/drop_monitor.c | 23 +++
net/core/dst.c | 59 ++++--
net/core/flow_dissector.c | 2 +-
net/dccp/ipv6.c | 5 +
net/ipv4/inet_connection_sock.c | 7 +-
net/ipv4/netfilter/arp_tables.c | 16 +-
net/ipv4/netfilter/ip_tables.c | 16 +-
net/ipv4/route.c | 45 +----
net/ipv4/tcp_minisocks.c | 7 +-
net/ipv6/ip6_fib.c | 2 +-
net/ipv6/ip6_input.c | 10 -
net/ipv6/netfilter/ip6_tables.c | 16 +-
net/ipv6/route.c | 36 +---
net/ipv6/tcp_ipv6.c | 5 +
net/mac80211/cfg.c | 4 +-
net/mac80211/ibss.c | 2 +
net/mac80211/mlme.c | 2 +-
net/mac80211/util.c | 2 +-
net/mptcp/options.c | 24 ++-
net/mptcp/subflow.c | 5 +
net/netfilter/nf_conntrack_netlink.c | 1 +
net/netfilter/nf_flow_table_core.c | 2 +-
net/netfilter/nf_tables_api.c | 19 +-
net/netfilter/x_tables.c | 49 +++--
net/qrtr/qrtr.c | 5 +
net/sched/cls_flower.c | 2 +-
net/sched/sch_choke.c | 7 +-
net/sched/sch_gred.c | 2 +-
net/sched/sch_red.c | 7 +-
net/sched/sch_sfq.c | 2 +-
net/sctp/output.c | 7 -
net/sctp/outqueue.c | 7 +
net/tipc/node.c | 11 +-
net/vmw_vsock/af_vsock.c | 1 +
scripts/dummy-tools/gcc | 5 +
security/integrity/iint.c | 8 +
security/selinux/include/security.h | 15 +-
security/selinux/selinuxfs.c | 13 +-
security/selinux/ss/services.c | 63 +++---
sound/hda/intel-nhlt.c | 5 +
tools/include/linux/static_call_types.h | 50 +++++
tools/lib/bpf/Makefile | 2 +-
tools/lib/bpf/btf_dump.c | 2 +-
tools/lib/bpf/libbpf.c | 3 +-
tools/lib/bpf/netlink.c | 2 +-
tools/objtool/check.c | 17 +-
tools/perf/util/auxtrace.c | 4 -
tools/perf/util/synthetic-events.c | 9 +-
tools/testing/kunit/configs/broken_on_uml.config | 2 +
tools/testing/selftests/arm64/fp/sve-ptrace.c | 2 +-
.../testing/selftests/bpf/prog_tests/fexit_sleep.c | 82 ++++++++
tools/testing/selftests/bpf/progs/fexit_sleep.c | 31 +++
.../testing/selftests/bpf/progs/test_tunnel_kern.c | 6 +-
.../selftests/net/forwarding/vxlan_bridge_1d.sh | 2 +-
.../selftests/net/reuseaddr_ports_exhausted.c | 32 +--
309 files changed, 3116 insertions(+), 1113 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.10 174/221] PM: EM: postpone creating the debugfs dir till fs_initcall
2021-03-29 7:55 1% [PATCH 5.10 000/221] 5.10.27-rc1 review Greg Kroah-Hartman
@ 2021-03-29 7:58 12% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-29 7:58 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Ionela Voinescu, Lukasz Luba,
Rafael J. Wysocki, Sasha Levin
From: Lukasz Luba <lukasz.luba@arm.com>
[ Upstream commit fb9d62b27ab1e07d625591549c314b7d406d21df ]
The debugfs directory '/sys/kernel/debug/energy_model' is needed before
the Energy Model registration can happen. With the recent change in
debugfs subsystem it's not allowed to create this directory at early
stage (core_initcall). Thus creating this directory would fail.
Postpone the creation of the EM debug dir to later stage: fs_initcall.
It should be safe since all clients: CPUFreq drivers, Devfreq drivers
will be initialized in later stages.
The custom debug log below prints the time of creation the EM debug dir
at fs_initcall and successful registration of EMs at later stages.
[ 1.505717] energy_model: creating rootdir
[ 3.698307] cpu cpu0: EM: created perf domain
[ 3.709022] cpu cpu1: EM: created perf domain
Fixes: 56348560d495 ("debugfs: do not attempt to create a new file before the filesystem is initalized")
Reported-by: Ionela Voinescu <ionela.voinescu@arm.com>
Signed-off-by: Lukasz Luba <lukasz.luba@arm.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/power/energy_model.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index c1ff7fa030ab..994ca8353543 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -85,7 +85,7 @@ static int __init em_debug_init(void)
return 0;
}
-core_initcall(em_debug_init);
+fs_initcall(em_debug_init);
#else /* CONFIG_DEBUG_FS */
static void em_debug_create_pd(struct device *dev) {}
static void em_debug_remove_pd(struct device *dev) {}
--
2.30.1
^ permalink raw reply related [relevance 12%]
* [PATCH 5.10 000/221] 5.10.27-rc1 review
@ 2021-03-29 7:55 1% Greg Kroah-Hartman
2021-03-29 7:58 12% ` [PATCH 5.10 174/221] PM: EM: postpone creating the debugfs dir till fs_initcall Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2021-03-29 7:55 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.10.27 release.
There are 221 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 31 Mar 2021 07:55:56 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.27-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.27-rc1
Marc Kleine-Budde <mkl@pengutronix.de>
can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
Christoph Hellwig <hch@lst.de>
nvme: fix the nsid value to print in nvme_validate_or_alloc_ns
David S. Miller <davem@davemloft.net>
Revert "net: bonding: fix error return code of bond_neigh_init()"
Roger Pau Monne <roger.pau@citrix.com>
Revert "xen: fix p2m size in dom0 for disabled memory hotplug case"
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
fs/ext4: fix integer overflow in s_log_groups_per_flex
Jan Kara <jack@suse.cz>
ext4: add reclaim checks to xattr code
Markus Theil <markus.theil@tu-ilmenau.de>
mac80211: fix double free in ibss_leave
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: b53: VLAN filtering is global to all users
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix DMA being used after buffer free if WoL is enabled
Martin Willi <martin@strongswan.org>
can: dev: Move device back to init netns on owning netns delete
Arnd Bergmann <arnd@arndb.de>
ch_ktls: fix enum-conversion warning
Matthew Wilcox (Oracle) <willy@infradead.org>
fs/cachefiles: Remove wait_bit_key layout dependency
Hugh Dickins <hughd@google.com>
mm/memcg: fix 5.10 backport of splitting page memcg
Isaku Yamahata <isaku.yamahata@intel.com>
x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
Thomas Gleixner <tglx@linutronix.de>
locking/mutex: Fix non debug version of mutex_lock_io_nested()
Shyam Prasad N <sprasad@microsoft.com>
cifs: Adjust key sizes and key generation routines for AES256 encryption
Steve French <stfrench@microsoft.com>
smb3: fix cached file size problems in duplicate extents (reflink)
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: qedi: Fix error return code of qedi_alloc_global_queues()
Bart Van Assche <bvanassche@acm.org>
scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
David Jeffery <djeffery@redhat.com>
block: recalculate segment count for multi-segment discards correctly
Pavel Begunkov <asml.silence@gmail.com>
io_uring: fix provide_buffers sign extension
Ian Rogers <irogers@google.com>
perf synthetic events: Avoid write of uninitialized memory when generating PERF_RECORD_MMAP* records
Adrian Hunter <adrian.hunter@intel.com>
perf auxtrace: Fix auxtrace queue conflict
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
ACPI: scan: Use unique number for instance_no
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: scan: Rearrange memory allocation in acpi_device_add()
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Update remaining dereference to RCU"
Sean Christopherson <seanjc@google.com>
mm/mmu_notifiers: ensure range_end() is paired with range_start()
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
dm table: Fix zoned model check and zone sectors check
Pavel Tatashin <pasha.tatashin@soleen.com>
arm64: mm: correct the inside linear map range during hotplug check
Anshuman Khandual <anshuman.khandual@arm.com>
arm64/mm: define arch_get_mappable_range()
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
netfilter: x_tables: Use correct memory barriers.
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Switch synchronization to RCU"
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Fix RGMII delays for BCM50160 and BCM50610M
Robert Hancock <robert.hancock@calian.com>
net: phy: broadcom: Set proper 1000BaseX/SGMII interface mode for BCM54616S
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Avoid forward for bcm54xx_config_clock_delay()
Michael Walle <michael@walle.cc>
net: phy: introduce phydev->port
Robert Hancock <robert.hancock@calian.com>
net: axienet: Fix probe error cleanup
Robert Hancock <robert.hancock@calian.com>
net: axienet: Properly handle PCS/PMA PHY for 1000BaseX mode
Li RongQing <lirongqing@baidu.com>
igb: avoid premature Rx buffer reuse
Daniel Borkmann <daniel@iogearbox.net>
net, bpf: Fix ip6ip6 crash with collect_md populated skbs
Daniel Borkmann <daniel@iogearbox.net>
net: Consolidate common blackhole dst ops
Sasha Levin <sashal@kernel.org>
bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
Potnuri Bharat Teja <bharat@chelsio.com>
RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server
Roger Pau Monne <roger.pau@citrix.com>
xen/x86: make XEN_BALLOON_MEMORY_HOTPLUG_LIMIT depend on MEMORY_HOTPLUG
Colin Ian King <colin.king@canonical.com>
octeontx2-af: Fix memory leak of object buf
Vladimir Oltean <vladimir.oltean@nxp.com>
net: bridge: don't notify switchdev for local FDB addresses
Lukasz Luba <lukasz.luba@arm.com>
PM: EM: postpone creating the debugfs dir till fs_initcall
Aya Levin <ayal@nvidia.com>
net/mlx5e: Fix error path for ethtool set-priv-flag
Dima Chumak <dchumak@nvidia.com>
net/mlx5e: Offload tuple rewrite for non-CT flows
Alaa Hleihel <alaa@nvidia.com>
net/mlx5e: Allow to match on MPLS parameters only for MPLS over UDP
Huy Nguyen <huyn@nvidia.com>
net/mlx5: Add back multicast stats for uplink representor
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PM: runtime: Defer suspending suppliers
Pavel Tatashin <pasha.tatashin@soleen.com>
arm64: kdump: update ppos when reading elfcorehdr
Fabio Estevam <festevam@gmail.com>
drm/msm: Fix suspend/resume on i.MX5
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: fix shutdown hook in case GPU components failed to bind
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: tx-path: zero initialize outgoing CAN frames
Zqiang <qiang.zhang@windriver.com>
bpf: Fix umd memory leak in copy_process()
Jean-Philippe Brucker <jean-philippe@linaro.org>
libbpf: Fix BTF dump of pointer-to-array-of-struct
Hangbin Liu <liuhangbin@gmail.com>
selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
David Brazdil <dbrazdil@google.com>
selinux: vsock: Set SID for socket returned by accept()
Corentin Labbe <clabbe@baylibre.com>
net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
Hayes Wang <hayeswang@realtek.com>
r8152: limit the RX buffer size of RTL8153A for USB 2.0
Jesse Brandeburg <jesse.brandeburg@intel.com>
igb: check timestamp validity
Johan Hovold <johan@kernel.org>
net: cdc-phonet: fix data-interface release on probe failure
Jiri Bohac <jbohac@suse.cz>
net: check all name nodes in __dev_alloc_name
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-af: fix infinite loop in unmapping NPC counter
Geetha sowjanya <gakula@marvell.com>
octeontx2-pf: Clear RSS enable flag on interace down
Geetha sowjanya <gakula@marvell.com>
octeontx2-af: Fix irq free in rvu teardown
Subbaraya Sundeep <sbhatta@marvell.com>
octeontx2-af: Remove TOS field from MKEX TX
Stanislaw Kardach <skardach@marvell.com>
octeontx2-af: Modify default KEX profile to extract TX packet fields
Rakesh Babu <rsaladi2@marvell.com>
octeontx2-af: Formatting debugfs entry rsrc_alloc.
Jakub Kicinski <kuba@kernel.org>
ipv6: weaken the v4mapped source check
dillon min <dillon.minfei@gmail.com>
ARM: dts: imx6ull: fix ubi filesystem mount failed
Kumar Kartikeya Dwivedi <memxor@gmail.com>
libbpf: Use SOCK_CLOEXEC when opening the netlink socket
Namhyung Kim <namhyung@kernel.org>
libbpf: Fix error path in bpf_object__elf_init()
Yinjun Zhang <yinjun.zhang@corigine.com>
netfilter: flowtable: Make sure GC works periodically in idle system
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: allow to update flowtable flags
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nftables: report EOPNOTSUPP on unsupported flowtable flags
wenxu <wenxu@ucloud.cn>
net/sched: cls_flower: fix only mask bit check in the validate_ct_state
Shannon Nelson <snelson@pensando.io>
ionic: linearize tso skb with too many frags
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm/dsi: fix check-before-set in the 7nm dsi_pll code
Alexei Starovoitov <ast@kernel.org>
ftrace: Fix modify_ftrace_direct.
Louis Peens <louis.peens@corigine.com>
nfp: flower: fix pre_tun mask id allocation
Louis Peens <louis.peens@corigine.com>
nfp: flower: add ipv6 bit to pre_tunnel control message
Louis Peens <louis.peens@corigine.com>
nfp: flower: fix unsupported pre_tunnel flows
Carlos Llamas <cmllamas@google.com>
selftests/net: fix warnings on reuseaddr_ports_exhausted
Brian Norris <briannorris@chromium.org>
mac80211: Allow HE operation to be longer than expected.
Johannes Berg <johannes.berg@intel.com>
mac80211: fix rate mask reset
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
Tong Zhang <ztong0001@gmail.com>
can: c_can: move runtime PM enable/disable to c_can_platform
Tong Zhang <ztong0001@gmail.com>
can: c_can_pci: c_can_pci_remove(): fix use-after-free
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Always disable bus load reporting
Angelo Dureghello <angelo@kernel-space.org>
can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
Stephane Grosjean <s.grosjean@peak-system.com>
can: peak_usb: add forgotten supported devices
Marc Kleine-Budde <mkl@pengutronix.de>
can: isotp: TX-path: ensure that CAN frame flags are initialized
Marc Kleine-Budde <mkl@pengutronix.de>
can: isotp: isotp_setsockopt(): only allow to set low level TX flags for CAN-FD
Alexander Ovechkin <ovov@yandex-team.ru>
tcp: relookup sock for RST+ACK packets handled by obsolete req sock
Eric Dumazet <edumazet@google.com>
tipc: better validate user input in tipc_nl_retrieve_key()
Ong Boon Leong <boon.leong.ong@intel.com>
net: phylink: Fix phylink_err() function name error in phylink_major_config
Xie He <xie.he.0141@gmail.com>
net: hdlc_x25: Prevent racing between "x25_close" and "x25_xmit"/"x25_rx"
Florian Westphal <fw@strlen.de>
netfilter: ctnetlink: fix dump of the expect mask attribute
Hangbin Liu <liuhangbin@gmail.com>
selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
Alexander Lobakin <alobakin@pm.me>
flow_dissector: fix byteorder of dissected ICMP ID
Eric Dumazet <edumazet@google.com>
net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
Alex Elder <elder@linaro.org>
net: ipa: terminate message handler arrays
Douglas Anderson <dianders@chromium.org>
clk: qcom: gcc-sc7180: Use floor ops for the correct sdcc1 clk
Dylan Hung <dylan_hung@aspeedtech.com>
ftgmac100: Restart MAC HW once
Florian Fainelli <f.fainelli@gmail.com>
net: phy: broadcom: Add power down exit reset state delay
Lv Yunlong <lyl2019@mail.ustc.edu.cn>
net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
Dinghao Liu <dinghao.liu@zju.edu.cn>
e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
Vitaly Lifshits <vitaly.lifshits@intel.com>
e1000e: add rtnl_lock() to e1000_reset_task
Andre Guedes <andre.guedes@intel.com>
igc: Fix igc_ptp_rx_pktstamp()
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Supported Pause Frame Link Setting
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Pause Frame Advertising
Sasha Neftin <sasha.neftin@intel.com>
igc: reinit_locked() should be called with rtnl_lock
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
Eric Dumazet <edumazet@google.com>
net: sched: validate stab values
Eric Dumazet <edumazet@google.com>
macvlan: macvlan_count_rx() needs to be aware of preemption
Ido Schimmel <idosch@nvidia.com>
drop_monitor: Perform cleanup upon probe registration failure
Wei Wang <weiwan@google.com>
ipv6: fix suspecious RCU usage warning
Maor Dickman <maord@nvidia.com>
net/mlx5e: Don't match on Geneve options in case option masks are all zero
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: When changing XDP program without reset, take refs for XSK RQs
Tariq Toukan <tariqt@nvidia.com>
net/mlx5e: RX, Mind the MPWQE gaps when calculating offsets
Georgi Valkov <gvalkov@abv.bg>
libbpf: Fix INSTALL flag order
Tal Lossos <tallossos@gmail.com>
bpf: Change inode_storage's lookup_elem return value from NULL to -EBADF
Maciej Fijalkowski <maciej.fijalkowski@intel.com>
veth: Store queue_mapping independently of XDP prog presence
Tony Lindgren <tony@atomide.com>
soc: ti: omap-prm: Fix occasional abort on reset deassert for dra7 iva
Tony Lindgren <tony@atomide.com>
ARM: OMAP2+: Fix smartreflex init regression after dropping legacy data
Grygorii Strashko <grygorii.strashko@ti.com>
bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
Mikulas Patocka <mpatocka@redhat.com>
dm ioctl: fix out of bounds array access when no devices
JeongHyeon Lee <jhs2.lee@samsung.com>
dm verity: fix DM_VERITY_OPTS_MAX value
Imre Deak <imre.deak@intel.com>
drm/i915: Fix the GT fence revocation runtime PM logic
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Add additional Sienna Cichlid PCI ID
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/display: restore AUX_DPHY_TX_CONTROL for DCN2.x
Kenneth Feng <kenneth.feng@amd.com>
drm/amd/pm: workaround for audio noise issue
Daniel Vetter <daniel.vetter@ffwll.ch>
drm/etnaviv: Use FOLL_FORCE for userptr
Mimi Zohar <zohar@linux.ibm.com>
integrity: double check iint_cache was initialized
Claudiu Beznea <claudiu.beznea@microchip.com>
ARM: dts: at91-sama5d27_som1: fix phy address to 7
Nicolas Ferre <nicolas.ferre@microchip.com>
ARM: dts: at91: sam9x60: fix mux-mask to match product's datasheet
Federico Pellegrin <fede@evolware.org>
ARM: dts: at91: sam9x60: fix mux-mask for PA7 so it can be set to A, B and C
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1043a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1012a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1046a: mark crypto engine dma coherent
Mark Rutland <mark.rutland@arm.com>
arm64: stacktrace: don't trace arch_stack_walk()
Vegard Nossum <vegard.nossum@oracle.com>
ACPICA: Always create namespace nodes using acpi_ns_create_node()
Chris Chiu <chris.chiu@canonical.com>
ACPI: video: Add missing callback back for Sony VPCEH3U1E
Nick Desaulniers <ndesaulniers@google.com>
gcov: fix clang-11+ support
Andrey Konovalov <andreyknvl@google.com>
kasan: fix per-page tags for non-page_alloc pages
Miaohe Lin <linmiaohe@huawei.com>
hugetlb_cgroup: fix imbalanced css_get and css_put pair for shared mappings
Phillip Lougher <phillip@squashfs.org.uk>
squashfs: fix xattr id and id lookup sanity checks
Sean Nyekjaer <sean@geanix.com>
squashfs: fix inode lookup sanity checks
Thomas Hebb <tommyhebb@gmail.com>
z3fold: prevent reclaim/free race for headless pages
Ido Schimmel <idosch@nvidia.com>
psample: Fix user API breakage
Hans de Goede <hdegoede@redhat.com>
platform/x86: intel-vbtn: Stop reporting SW_DOCK events
Mian Yousaf Kaukab <ykaukab@suse.de>
netsec: restore phy power state after controller reset
Ondrej Mosnacek <omosnace@redhat.com>
selinux: fix variable scope issue in live sidtab conversion
Ondrej Mosnacek <omosnace@redhat.com>
selinux: don't log MAC_POLICY_LOAD record on failed policy load
Filipe Manana <fdmanana@suse.com>
btrfs: fix sleep while in non-sleep context during qgroup removal
Sean Christopherson <seanjc@google.com>
KVM: x86: Protect userspace MSR filter with SRCU, and set atomically-ish
Peter Zijlstra <peterz@infradead.org>
static_call: Fix static_call_set_init()
Peter Zijlstra <peterz@infradead.org>
static_call: Fix the module key fixup
Josh Poimboeuf <jpoimboe@redhat.com>
static_call: Allow module use without exposing static_call_key
Peter Zijlstra <peterz@infradead.org>
static_call: Pull some static_call declarations to the type headers
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
Fenghua Yu <fenghua.yu@intel.com>
mm/fork: clear PASID for new mm
Daniel Wagner <dwagner@suse.de>
block: Suppress uevent for hidden device when removed
J. Bruce Fields <bfields@redhat.com>
nfs: we don't support removing system.nfs4_acl
Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
Lv Yunlong <lyl2019@mail.ustc.edu.cn>
nvme-rdma: Fix a use after free in nvmet_rdma_write_data_done
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvme-core: check ctrl css before setting up zns
Hannes Reinecke <hare@suse.de>
nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
Hannes Reinecke <hare@suse.de>
nvme-fc: set NVME_REQ_CANCELLED in nvme_fc_terminate_exchange()
Hannes Reinecke <hare@suse.de>
nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
Hannes Reinecke <hare@suse.de>
nvme: simplify error logic in nvme_validate_ns()
Christian König <christian.koenig@amd.com>
drm/radeon: fix AGP dependency
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu: fb BO should be ttm_bo_type_device
Sung Lee <sung.lee@amd.com>
drm/amd/display: Revert dram_clock_change_latency for DCN2.1
Damien Le Moal <damien.lemoal@wdc.com>
block: Fix REQ_OP_ZONE_RESET_ALL handling
satya priya <skakit@codeaurora.org>
regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
Mark Brown <broonie@kernel.org>
kselftest: arm64: Fix exit code of sve-ptrace
Peter Zijlstra <peterz@infradead.org>
u64_stats,lockdep: Fix u64_stats_init() vs lockdep
Julian Braha <julianbraha@gmail.com>
staging: rtl8192e: fix kconfig dependency on CRYPTO
Tomer Tayar <ttayar@habana.ai>
habanalabs: Call put_pid() when releasing control device
Rob Gardner <rob.gardner@oracle.com>
sparc64: Fix opcode filtering in handling of no fault loads
Wei Yongjun <weiyongjun1@huawei.com>
umem: fix error return code in mm_pci_probe()
Jiri Slaby <jirislaby@kernel.org>
kbuild: dummy-tools: fix inverted tests for gcc
Masahiro Yamada <masahiroy@kernel.org>
kbuild: add image_name to no-sync-config-targets
Paul Cercueil <paul@crapouillou.net>
irqchip/ingenic: Add support for the JZ4760
Paulo Alcantara <pc@cjr.nz>
cifs: change noisy error message to FYI
Tong Zhang <ztong0001@gmail.com>
atm: idt77252: fix null-ptr-dereference
Tong Zhang <ztong0001@gmail.com>
atm: uPD98402: fix incorrect allocation
Alex Marginean <alexandru.marginean@nxp.com>
net: enetc: set MAC RX FIFO to recommended value
Paul Cercueil <paul@crapouillou.net>
net: davicom: Use platform_get_irq_optional()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: wan: fix error return code of uhdlc_init()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
Frank Sorenson <sorenson@redhat.com>
NFS: Correct size calculation for create reply length
Timo Rothenpieler <timo@rothenpieler.org>
nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
Yang Li <yang.lee@linux.alibaba.com>
gpiolib: acpi: Add missing IRQF_ONESHOT
Sudeep Holla <sudeep.holla@arm.com>
cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
Bob Peterson <rpeterso@redhat.com>
gfs2: fix use-after-free in trans_drain
Aurelien Aptel <aaptel@suse.com>
cifs: ask for more credit on async read/write code paths
Michael Braun <michael-dev@fami-braun.de>
gianfar: fix jumbo packets+napi+rx overrun crash
Denis Efremov <efremov@linux.com>
sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
Jia-Ju Bai <baijiaju1990@gmail.com>
net: intel: iavf: fix error return code of iavf_init_get_resources()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: tehuti: fix error return code in bdx_probe()
Xunlei Pang <xlpang@linux.alibaba.com>
blk-cgroup: Fix the recursive blkg rwstat
Nitin Rawat <nitirawa@codeaurora.org>
scsi: ufs: ufs-qcom: Disable interrupt in reset path
Dinghao Liu <dinghao.liu@zju.edu.cn>
ixgbe: Fix memleak in ixgbe_configure_clsu32
Mark Pearson <markpearson@lenovo.com>
ALSA: hda: ignore invalid NHLT table
Hayes Wang <hayeswang@realtek.com>
Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
Tong Zhang <ztong0001@gmail.com>
atm: lanai: dont run lanai_dev_close if not open
Tong Zhang <ztong0001@gmail.com>
atm: eni: dont release is never initialized
Michael Ellerman <mpe@ellerman.id.au>
powerpc/4xx: Fix build errors from mfdcr()
Heiko Thiery <heiko.thiery@gmail.com>
net: fec: ptp: avoid register access when ipg clock is disabled
Joakim Zhang <qiangqing.zhang@nxp.com>
net: stmmac: fix dma physical address of descriptor when display ring
Felix Fietkau <nbd@nbd.name>
mt76: fix tx skb error handling in mt76_dma_tx_queue_skb
Zhou Guanghui <zhouguanghui1@huawei.com>
mm/memcg: set memcg when splitting page
Zhou Guanghui <zhouguanghui1@huawei.com>
mm/memcg: rename mem_cgroup_split_huge_fixup to split_page_memcg and add nr_pages argument
-------------
Diffstat:
Documentation/virt/kvm/api.rst | 6 +-
Makefile | 7 +-
arch/arm/boot/dts/at91-sam9x60ek.dts | 8 --
arch/arm/boot/dts/at91-sama5d27_som1.dtsi | 4 +-
arch/arm/boot/dts/imx6ull-myir-mys-6ulx-eval.dts | 1 +
arch/arm/boot/dts/sam9x60.dtsi | 9 ++
arch/arm/mach-omap2/sr_device.c | 75 ++++++++---
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 1 +
arch/arm64/kernel/crash_dump.c | 2 +
arch/arm64/kernel/stacktrace.c | 9 +-
arch/arm64/mm/mmu.c | 32 +++--
arch/ia64/include/asm/syscall.h | 2 +-
arch/ia64/kernel/ptrace.c | 24 +++-
arch/powerpc/include/asm/dcr-native.h | 8 +-
arch/sparc/kernel/traps_64.c | 13 +-
arch/x86/include/asm/kvm_host.h | 14 +-
arch/x86/include/asm/static_call.h | 7 +
arch/x86/include/asm/xen/page.h | 12 --
arch/x86/kvm/x86.c | 109 +++++++++------
arch/x86/mm/mem_encrypt.c | 2 +-
arch/x86/xen/p2m.c | 7 +-
arch/x86/xen/setup.c | 16 ++-
block/blk-cgroup-rwstat.c | 3 +-
block/blk-merge.c | 8 ++
block/blk-zoned.c | 2 +-
block/genhd.c | 4 +-
drivers/acpi/acpica/nsaccess.c | 3 +-
drivers/acpi/internal.h | 6 +-
drivers/acpi/scan.c | 88 +++++++-----
drivers/acpi/video_detect.c | 1 +
drivers/atm/eni.c | 3 +-
drivers/atm/idt77105.c | 4 +-
drivers/atm/lanai.c | 5 +-
drivers/atm/uPD98402.c | 2 +-
drivers/base/power/runtime.c | 45 ++++++-
drivers/block/umem.c | 5 +-
drivers/bus/omap_l3_noc.c | 4 +-
drivers/clk/qcom/gcc-sc7180.c | 4 +-
drivers/cpufreq/cpufreq-dt-platdev.c | 2 +
drivers/gpio/gpiolib-acpi.c | 2 +-
drivers/gpu/drm/Kconfig | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2 +-
.../drm/amd/display/dc/dcn20/dcn20_link_encoder.c | 3 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 +-
.../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 54 ++++++++
.../gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 74 +++++++++--
.../gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 24 ++++
.../gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 25 ++++
drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2 +-
drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 13 +-
drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++-
drivers/gpu/drm/i915/intel_runtime_pm.h | 5 +
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 2 +-
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 6 +-
drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c | 5 +-
drivers/gpu/drm/msm/msm_drv.c | 12 ++
drivers/infiniband/hw/cxgb4/cm.c | 4 +-
drivers/irqchip/irq-ingenic-tcu.c | 1 +
drivers/irqchip/irq-ingenic.c | 1 +
drivers/md/dm-ioctl.c | 2 +-
drivers/md/dm-table.c | 33 +++--
drivers/md/dm-verity-target.c | 2 +-
drivers/md/dm-zoned-target.c | 2 +-
drivers/misc/habanalabs/common/device.c | 2 +
drivers/net/bonding/bond_main.c | 8 +-
drivers/net/can/c_can/c_can.c | 24 +---
drivers/net/can/c_can/c_can_pci.c | 3 +-
drivers/net/can/c_can/c_can_platform.c | 6 +-
drivers/net/can/dev.c | 1 +
drivers/net/can/flexcan.c | 8 +-
drivers/net/can/kvaser_pciefd.c | 4 +
drivers/net/can/m_can/m_can.c | 5 +-
drivers/net/dsa/b53/b53_common.c | 14 +-
drivers/net/dsa/bcm_sf2.c | 6 +-
.../chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 2 +-
drivers/net/ethernet/davicom/dm9000.c | 2 +-
drivers/net/ethernet/faraday/ftgmac100.c | 1 +
drivers/net/ethernet/freescale/enetc/enetc_hw.h | 2 +
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6 +
drivers/net/ethernet/freescale/fec_ptp.c | 7 +
drivers/net/ethernet/freescale/gianfar.c | 15 +++
drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4 +-
drivers/net/ethernet/intel/e1000e/82571.c | 2 +
drivers/net/ethernet/intel/e1000e/netdev.c | 6 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 3 +-
drivers/net/ethernet/intel/igb/igb.h | 4 +-
drivers/net/ethernet/intel/igb/igb_main.c | 33 +++--
drivers/net/ethernet/intel/igb/igb_ptp.c | 31 ++++-
drivers/net/ethernet/intel/igc/igc.h | 2 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 7 +-
drivers/net/ethernet/intel/igc/igc_main.c | 9 ++
drivers/net/ethernet/intel/igc/igc_ptp.c | 72 +++++-----
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +-
drivers/net/ethernet/marvell/octeontx2/af/npc.h | 31 +++++
.../ethernet/marvell/octeontx2/af/npc_profile.h | 97 ++++++++++++--
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 4 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 48 ++++---
.../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 4 +
.../net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2 +-
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5 +
drivers/net/ethernet/mellanox/mlx5/core/en.h | 7 +-
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 3 +-
.../ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c | 4 +
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 6 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 17 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 54 ++++++--
.../net/ethernet/netronome/nfp/flower/metadata.c | 24 +++-
.../net/ethernet/netronome/nfp/flower/offload.c | 18 +++
.../ethernet/netronome/nfp/flower/tunnel_conf.c | 15 ++-
drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 13 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 3 +
drivers/net/ethernet/realtek/r8169_main.c | 6 +-
drivers/net/ethernet/socionext/netsec.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 50 +++++--
drivers/net/ethernet/stmicro/stmmac/enh_desc.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 +-
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 9 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 57 +++++---
drivers/net/ethernet/sun/niu.c | 2 -
drivers/net/ethernet/tehuti/tehuti.c | 1 +
drivers/net/ethernet/xilinx/xilinx_axienet.h | 3 +
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 125 +++++++++++++-----
drivers/net/ipa/ipa_qmi.c | 2 +
drivers/net/phy/broadcom.c | 147 +++++++++++++++------
drivers/net/phy/dp83822.c | 3 +
drivers/net/phy/dp83869.c | 4 +
drivers/net/phy/lxt.c | 1 +
drivers/net/phy/marvell.c | 1 +
drivers/net/phy/marvell10g.c | 2 +
drivers/net/phy/micrel.c | 14 +-
drivers/net/phy/phy.c | 2 +-
drivers/net/phy/phy_device.c | 9 ++
drivers/net/phy/phylink.c | 2 +-
drivers/net/usb/cdc-phonet.c | 2 +
drivers/net/usb/r8152.c | 40 ++----
drivers/net/veth.c | 3 +-
drivers/net/wan/fsl_ucc_hdlc.c | 8 +-
drivers/net/wan/hdlc_x25.c | 42 +++++-
drivers/net/wireless/mediatek/mt76/dma.c | 15 +--
drivers/nvme/host/core.c | 15 ++-
drivers/nvme/host/fc.c | 3 +-
drivers/nvme/host/pci.c | 1 +
drivers/nvme/target/rdma.c | 5 +-
drivers/platform/x86/intel-vbtn.c | 12 +-
drivers/regulator/qcom-rpmh-regulator.c | 4 +-
drivers/scsi/mpt3sas/mpt3sas_base.c | 8 +-
drivers/scsi/qedi/qedi_main.c | 1 +
drivers/scsi/qla2xxx/qla_target.c | 13 +-
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 -
drivers/scsi/ufs/ufs-qcom.c | 10 ++
drivers/soc/ti/omap_prm.c | 6 +-
drivers/staging/rtl8192e/Kconfig | 1 +
drivers/xen/Kconfig | 4 +-
fs/btrfs/qgroup.c | 12 +-
fs/cachefiles/rdwr.c | 7 +-
fs/cifs/cifsglob.h | 4 +-
fs/cifs/cifspdu.h | 5 +
fs/cifs/smb2glob.h | 1 +
fs/cifs/smb2ops.c | 27 +++-
fs/cifs/smb2pdu.c | 6 +-
fs/cifs/smb2transport.c | 37 ++++--
fs/cifs/transport.c | 2 +-
fs/ext4/mballoc.c | 11 +-
fs/ext4/xattr.c | 4 +
fs/gfs2/log.c | 4 +
fs/gfs2/trans.c | 2 +
fs/io_uring.c | 4 +-
fs/nfs/Kconfig | 2 +-
fs/nfs/nfs3xdr.c | 3 +-
fs/nfs/nfs4proc.c | 3 +
fs/squashfs/export.c | 8 +-
fs/squashfs/id.c | 6 +-
fs/squashfs/squashfs_fs.h | 1 +
fs/squashfs/xattr_id.c | 6 +-
include/acpi/acpi_bus.h | 1 +
include/asm-generic/vmlinux.lds.h | 5 +-
include/linux/bpf.h | 9 +-
include/linux/brcmphy.h | 4 +
include/linux/device-mapper.h | 15 ++-
include/linux/hugetlb_cgroup.h | 15 ++-
include/linux/if_macvlan.h | 3 +-
include/linux/memcontrol.h | 6 +-
include/linux/mm.h | 15 ++-
include/linux/mm_types.h | 1 +
include/linux/mmu_notifier.h | 10 +-
include/linux/mutex.h | 2 +-
include/linux/netfilter/x_tables.h | 7 +-
include/linux/pagemap.h | 1 -
include/linux/phy.h | 2 +
include/linux/static_call.h | 43 +++---
include/linux/static_call_types.h | 50 +++++++
include/linux/u64_stats_sync.h | 7 +-
include/linux/usermode_driver.h | 1 +
include/net/dst.h | 11 ++
include/net/inet_connection_sock.h | 2 +-
include/net/netfilter/nf_tables.h | 3 +
include/net/nexthop.h | 24 ++++
include/net/red.h | 10 +-
include/net/rtnetlink.h | 2 +
include/uapi/linux/psample.h | 5 +-
kernel/bpf/bpf_inode_storage.c | 2 +-
kernel/bpf/preload/bpf_preload_kern.c | 19 ++-
kernel/fork.c | 8 ++
kernel/gcov/clang.c | 69 ++++++++++
kernel/power/energy_model.c | 2 +-
kernel/static_call.c | 71 ++++++++--
kernel/trace/ftrace.c | 43 +++++-
kernel/usermode_driver.c | 21 ++-
mm/huge_memory.c | 2 +-
mm/hugetlb.c | 41 +++++-
mm/hugetlb_cgroup.c | 10 +-
mm/memcontrol.c | 17 ++-
mm/mmu_notifier.c | 23 ++++
mm/page_alloc.c | 1 +
mm/z3fold.c | 16 ++-
net/bridge/br_switchdev.c | 2 +
net/can/isotp.c | 18 ++-
net/core/dev.c | 14 +-
net/core/drop_monitor.c | 23 ++++
net/core/dst.c | 59 ++++++---
net/core/flow_dissector.c | 2 +-
net/dccp/ipv6.c | 5 +
net/ipv4/inet_connection_sock.c | 7 +-
net/ipv4/netfilter/arp_tables.c | 16 +--
net/ipv4/netfilter/ip_tables.c | 16 +--
net/ipv4/route.c | 45 ++-----
net/ipv4/tcp_minisocks.c | 7 +-
net/ipv6/ip6_fib.c | 2 +-
net/ipv6/ip6_input.c | 10 --
net/ipv6/netfilter/ip6_tables.c | 16 +--
net/ipv6/route.c | 36 ++---
net/ipv6/tcp_ipv6.c | 5 +
net/mac80211/cfg.c | 4 +-
net/mac80211/ibss.c | 2 +
net/mac80211/mlme.c | 2 +-
net/mac80211/util.c | 2 +-
net/mptcp/subflow.c | 5 +
net/netfilter/nf_conntrack_netlink.c | 1 +
net/netfilter/nf_flow_table_core.c | 2 +-
net/netfilter/nf_tables_api.c | 19 ++-
net/netfilter/x_tables.c | 49 ++++---
net/qrtr/qrtr.c | 5 +
net/sched/cls_flower.c | 2 +-
net/sched/sch_choke.c | 7 +-
net/sched/sch_gred.c | 2 +-
net/sched/sch_red.c | 7 +-
net/sched/sch_sfq.c | 2 +-
net/tipc/node.c | 11 +-
net/vmw_vsock/af_vsock.c | 1 +
scripts/dummy-tools/gcc | 5 +
security/integrity/iint.c | 8 ++
security/selinux/include/security.h | 15 ++-
security/selinux/selinuxfs.c | 13 +-
security/selinux/ss/services.c | 63 +++++----
sound/hda/intel-nhlt.c | 5 +
tools/include/linux/static_call_types.h | 50 +++++++
tools/lib/bpf/Makefile | 2 +-
tools/lib/bpf/btf_dump.c | 2 +-
tools/lib/bpf/libbpf.c | 3 +-
tools/lib/bpf/netlink.c | 2 +-
tools/objtool/check.c | 17 ++-
tools/perf/util/auxtrace.c | 4 -
tools/perf/util/synthetic-events.c | 9 +-
tools/testing/selftests/arm64/fp/sve-ptrace.c | 2 +-
.../testing/selftests/bpf/progs/test_tunnel_kern.c | 6 +-
.../selftests/net/forwarding/vxlan_bridge_1d.sh | 2 +-
.../selftests/net/reuseaddr_ports_exhausted.c | 32 ++---
272 files changed, 2602 insertions(+), 978 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.4 091/111] PM: EM: postpone creating the debugfs dir till fs_initcall
2021-03-29 7:57 2% [PATCH 5.4 000/111] 5.4.109-rc1 review Greg Kroah-Hartman
@ 2021-03-29 7:58 12% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-29 7:58 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Ionela Voinescu, Lukasz Luba,
Rafael J. Wysocki, Sasha Levin
From: Lukasz Luba <lukasz.luba@arm.com>
[ Upstream commit fb9d62b27ab1e07d625591549c314b7d406d21df ]
The debugfs directory '/sys/kernel/debug/energy_model' is needed before
the Energy Model registration can happen. With the recent change in
debugfs subsystem it's not allowed to create this directory at early
stage (core_initcall). Thus creating this directory would fail.
Postpone the creation of the EM debug dir to later stage: fs_initcall.
It should be safe since all clients: CPUFreq drivers, Devfreq drivers
will be initialized in later stages.
The custom debug log below prints the time of creation the EM debug dir
at fs_initcall and successful registration of EMs at later stages.
[ 1.505717] energy_model: creating rootdir
[ 3.698307] cpu cpu0: EM: created perf domain
[ 3.709022] cpu cpu1: EM: created perf domain
Fixes: 56348560d495 ("debugfs: do not attempt to create a new file before the filesystem is initalized")
Reported-by: Ionela Voinescu <ionela.voinescu@arm.com>
Signed-off-by: Lukasz Luba <lukasz.luba@arm.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/power/energy_model.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index 0a9326f5f421..8dac32bd9089 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -74,7 +74,7 @@ static int __init em_debug_init(void)
return 0;
}
-core_initcall(em_debug_init);
+fs_initcall(em_debug_init);
#else /* CONFIG_DEBUG_FS */
static void em_debug_create_pd(struct em_perf_domain *pd, int cpu) {}
#endif
--
2.30.1
^ permalink raw reply related [relevance 12%]
* [PATCH 5.4 000/111] 5.4.109-rc1 review
@ 2021-03-29 7:57 2% Greg Kroah-Hartman
2021-03-29 7:58 12% ` [PATCH 5.4 091/111] PM: EM: postpone creating the debugfs dir till fs_initcall Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2021-03-29 7:57 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.4.109 release.
There are 111 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 31 Mar 2021 07:55:56 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.109-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.4.109-rc1
Marc Kleine-Budde <mkl@pengutronix.de>
can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
Jan Kara <jack@suse.cz>
ext4: add reclaim checks to xattr code
Markus Theil <markus.theil@tu-ilmenau.de>
mac80211: fix double free in ibss_leave
Eric Dumazet <edumazet@google.com>
net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: b53: VLAN filtering is global to all users
Martin Willi <martin@strongswan.org>
can: dev: Move device back to init netns on owning netns delete
Isaku Yamahata <isaku.yamahata@intel.com>
x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
Thomas Gleixner <tglx@linutronix.de>
locking/mutex: Fix non debug version of mutex_lock_io_nested()
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
Jia-Ju Bai <baijiaju1990@gmail.com>
scsi: qedi: Fix error return code of qedi_alloc_global_queues()
Bart Van Assche <bvanassche@acm.org>
scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
David Jeffery <djeffery@redhat.com>
block: recalculate segment count for multi-segment discards correctly
Adrian Hunter <adrian.hunter@intel.com>
perf auxtrace: Fix auxtrace queue conflict
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
ACPI: scan: Use unique number for instance_no
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: scan: Rearrange memory allocation in acpi_device_add()
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Update remaining dereference to RCU"
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
netfilter: x_tables: Use correct memory barriers.
Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
Revert "netfilter: x_tables: Switch synchronization to RCU"
Sasha Levin <sashal@kernel.org>
bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
Potnuri Bharat Teja <bharat@chelsio.com>
RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server
Lukasz Luba <lukasz.luba@arm.com>
PM: EM: postpone creating the debugfs dir till fs_initcall
Aya Levin <ayal@nvidia.com>
net/mlx5e: Fix error path for ethtool set-priv-flag
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
PM: runtime: Defer suspending suppliers
Pavel Tatashin <pasha.tatashin@soleen.com>
arm64: kdump: update ppos when reading elfcorehdr
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drm/msm: fix shutdown hook in case GPU components failed to bind
Jean-Philippe Brucker <jean-philippe@linaro.org>
libbpf: Fix BTF dump of pointer-to-array-of-struct
Hangbin Liu <liuhangbin@gmail.com>
selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
Corentin Labbe <clabbe@baylibre.com>
net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
Hayes Wang <hayeswang@realtek.com>
r8152: limit the RX buffer size of RTL8153A for USB 2.0
Johan Hovold <johan@kernel.org>
net: cdc-phonet: fix data-interface release on probe failure
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-af: fix infinite loop in unmapping NPC counter
Geetha sowjanya <gakula@marvell.com>
octeontx2-af: Fix irq free in rvu teardown
Kumar Kartikeya Dwivedi <memxor@gmail.com>
libbpf: Use SOCK_CLOEXEC when opening the netlink socket
Louis Peens <louis.peens@corigine.com>
nfp: flower: fix pre_tun mask id allocation
Johannes Berg <johannes.berg@intel.com>
mac80211: fix rate mask reset
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
Torin Cooper-Bennun <torin@maxiluxsystems.com>
can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
Tong Zhang <ztong0001@gmail.com>
can: c_can: move runtime PM enable/disable to c_can_platform
Tong Zhang <ztong0001@gmail.com>
can: c_can_pci: c_can_pci_remove(): fix use-after-free
Jimmy Assarsson <extja@kvaser.com>
can: kvaser_pciefd: Always disable bus load reporting
Angelo Dureghello <angelo@kernel-space.org>
can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
Stephane Grosjean <s.grosjean@peak-system.com>
can: peak_usb: add forgotten supported devices
Alexander Ovechkin <ovov@yandex-team.ru>
tcp: relookup sock for RST+ACK packets handled by obsolete req sock
Florian Westphal <fw@strlen.de>
netfilter: ctnetlink: fix dump of the expect mask attribute
Hangbin Liu <liuhangbin@gmail.com>
selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
Dylan Hung <dylan_hung@aspeedtech.com>
ftgmac100: Restart MAC HW once
Lv Yunlong <lyl2019@mail.ustc.edu.cn>
net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
Dinghao Liu <dinghao.liu@zju.edu.cn>
e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
Vitaly Lifshits <vitaly.lifshits@intel.com>
e1000e: add rtnl_lock() to e1000_reset_task
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Supported Pause Frame Link Setting
Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
igc: Fix Pause Frame Advertising
Florian Fainelli <f.fainelli@gmail.com>
net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
Eric Dumazet <edumazet@google.com>
net: sched: validate stab values
Eric Dumazet <edumazet@google.com>
macvlan: macvlan_count_rx() needs to be aware of preemption
Wei Wang <weiwan@google.com>
ipv6: fix suspecious RCU usage warning
Maor Dickman <maord@nvidia.com>
net/mlx5e: Don't match on Geneve options in case option masks are all zero
Georgi Valkov <gvalkov@abv.bg>
libbpf: Fix INSTALL flag order
Maciej Fijalkowski <maciej.fijalkowski@intel.com>
veth: Store queue_mapping independently of XDP prog presence
Grygorii Strashko <grygorii.strashko@ti.com>
bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
Mikulas Patocka <mpatocka@redhat.com>
dm ioctl: fix out of bounds array access when no devices
JeongHyeon Lee <jhs2.lee@samsung.com>
dm verity: fix DM_VERITY_OPTS_MAX value
Mimi Zohar <zohar@linux.ibm.com>
integrity: double check iint_cache was initialized
Claudiu Beznea <claudiu.beznea@microchip.com>
ARM: dts: at91-sama5d27_som1: fix phy address to 7
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1043a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1012a: mark crypto engine dma coherent
Horia Geantă <horia.geanta@nxp.com>
arm64: dts: ls1046a: mark crypto engine dma coherent
Chris Chiu <chris.chiu@canonical.com>
ACPI: video: Add missing callback back for Sony VPCEH3U1E
Nick Desaulniers <ndesaulniers@google.com>
gcov: fix clang-11+ support
Andrey Konovalov <andreyknvl@google.com>
kasan: fix per-page tags for non-page_alloc pages
Phillip Lougher <phillip@squashfs.org.uk>
squashfs: fix xattr id and id lookup sanity checks
Sean Nyekjaer <sean@geanix.com>
squashfs: fix inode lookup sanity checks
Hans de Goede <hdegoede@redhat.com>
platform/x86: intel-vbtn: Stop reporting SW_DOCK events
Mian Yousaf Kaukab <ykaukab@suse.de>
netsec: restore phy power state after controller reset
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
Sergei Trofimovich <slyfox@gentoo.org>
ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
Daniel Wagner <dwagner@suse.de>
block: Suppress uevent for hidden device when removed
J. Bruce Fields <bfields@redhat.com>
nfs: we don't support removing system.nfs4_acl
Dmitry Monakhov <dmtrmonakhov@yandex-team.ru>
nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
Hannes Reinecke <hare@suse.de>
nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
Hannes Reinecke <hare@suse.de>
nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
Christian König <christian.koenig@amd.com>
drm/radeon: fix AGP dependency
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu: fb BO should be ttm_bo_type_device
Sung Lee <sung.lee@amd.com>
drm/amd/display: Revert dram_clock_change_latency for DCN2.1
satya priya <skakit@codeaurora.org>
regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
Peter Zijlstra <peterz@infradead.org>
u64_stats,lockdep: Fix u64_stats_init() vs lockdep
Tomer Tayar <ttayar@habana.ai>
habanalabs: Call put_pid() when releasing control device
Rob Gardner <rob.gardner@oracle.com>
sparc64: Fix opcode filtering in handling of no fault loads
Paul Cercueil <paul@crapouillou.net>
irqchip/ingenic: Add support for the JZ4760
Paulo Alcantara <pc@cjr.nz>
cifs: change noisy error message to FYI
Tong Zhang <ztong0001@gmail.com>
atm: idt77252: fix null-ptr-dereference
Tong Zhang <ztong0001@gmail.com>
atm: uPD98402: fix incorrect allocation
Paul Cercueil <paul@crapouillou.net>
net: davicom: Use platform_get_irq_optional()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: wan: fix error return code of uhdlc_init()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
Frank Sorenson <sorenson@redhat.com>
NFS: Correct size calculation for create reply length
Timo Rothenpieler <timo@rothenpieler.org>
nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
Yang Li <yang.lee@linux.alibaba.com>
gpiolib: acpi: Add missing IRQF_ONESHOT
Sudeep Holla <sudeep.holla@arm.com>
cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
Aurelien Aptel <aaptel@suse.com>
cifs: ask for more credit on async read/write code paths
Michael Braun <michael-dev@fami-braun.de>
gianfar: fix jumbo packets+napi+rx overrun crash
Denis Efremov <efremov@linux.com>
sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
Jia-Ju Bai <baijiaju1990@gmail.com>
net: intel: iavf: fix error return code of iavf_init_get_resources()
Jia-Ju Bai <baijiaju1990@gmail.com>
net: tehuti: fix error return code in bdx_probe()
Dinghao Liu <dinghao.liu@zju.edu.cn>
ixgbe: Fix memleak in ixgbe_configure_clsu32
Mark Pearson <markpearson@lenovo.com>
ALSA: hda: ignore invalid NHLT table
Hayes Wang <hayeswang@realtek.com>
Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
Tong Zhang <ztong0001@gmail.com>
atm: lanai: dont run lanai_dev_close if not open
Tong Zhang <ztong0001@gmail.com>
atm: eni: dont release is never initialized
Michael Ellerman <mpe@ellerman.id.au>
powerpc/4xx: Fix build errors from mfdcr()
Heiko Thiery <heiko.thiery@gmail.com>
net: fec: ptp: avoid register access when ipg clock is disabled
Mike Kravetz <mike.kravetz@oracle.com>
hugetlbfs: hugetlb_fault_mutex_hash() cleanup
-------------
Diffstat:
Makefile | 4 +-
arch/arm/boot/dts/at91-sama5d27_som1.dtsi | 4 +-
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1 +
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 1 +
arch/arm64/kernel/crash_dump.c | 2 +
arch/ia64/include/asm/syscall.h | 2 +-
arch/ia64/kernel/ptrace.c | 24 ++++--
arch/powerpc/include/asm/dcr-native.h | 8 +-
arch/sparc/kernel/traps_64.c | 13 ++--
arch/x86/mm/mem_encrypt.c | 2 +-
block/blk-merge.c | 8 ++
block/genhd.c | 4 +-
drivers/acpi/internal.h | 6 +-
drivers/acpi/scan.c | 88 +++++++++++++---------
drivers/acpi/video_detect.c | 1 +
drivers/atm/eni.c | 3 +-
drivers/atm/idt77105.c | 4 +-
drivers/atm/lanai.c | 5 +-
drivers/atm/uPD98402.c | 2 +-
drivers/base/power/runtime.c | 45 +++++++++--
drivers/bus/omap_l3_noc.c | 4 +-
drivers/cpufreq/cpufreq-dt-platdev.c | 2 +
drivers/gpio/gpiolib-acpi.c | 2 +-
drivers/gpu/drm/Kconfig | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 +-
drivers/gpu/drm/msm/msm_drv.c | 4 +
drivers/infiniband/hw/cxgb4/cm.c | 4 +-
drivers/irqchip/irq-ingenic-tcu.c | 1 +
drivers/irqchip/irq-ingenic.c | 1 +
drivers/md/dm-ioctl.c | 2 +-
drivers/md/dm-verity-target.c | 2 +-
drivers/misc/habanalabs/device.c | 2 +
drivers/net/can/c_can/c_can.c | 24 +-----
drivers/net/can/c_can/c_can_pci.c | 3 +-
drivers/net/can/c_can/c_can_platform.c | 6 +-
drivers/net/can/dev.c | 1 +
drivers/net/can/flexcan.c | 8 +-
drivers/net/can/kvaser_pciefd.c | 4 +
drivers/net/can/m_can/m_can.c | 5 +-
drivers/net/dsa/b53/b53_common.c | 14 ++--
drivers/net/dsa/bcm_sf2.c | 6 +-
drivers/net/ethernet/davicom/dm9000.c | 2 +-
drivers/net/ethernet/faraday/ftgmac100.c | 1 +
drivers/net/ethernet/freescale/fec_ptp.c | 7 ++
drivers/net/ethernet/freescale/gianfar.c | 15 ++++
drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4 +-
drivers/net/ethernet/intel/e1000e/82571.c | 2 +
drivers/net/ethernet/intel/e1000e/netdev.c | 6 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 3 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 7 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 4 +-
.../net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2 +-
.../ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c | 4 +
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 6 +-
.../net/ethernet/netronome/nfp/flower/metadata.c | 24 ++++--
.../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 3 +
drivers/net/ethernet/socionext/netsec.c | 9 ++-
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +
drivers/net/ethernet/sun/niu.c | 2 -
drivers/net/ethernet/tehuti/tehuti.c | 1 +
drivers/net/usb/cdc-phonet.c | 2 +
drivers/net/usb/r8152.c | 40 +++-------
drivers/net/veth.c | 3 +-
drivers/net/wan/fsl_ucc_hdlc.c | 8 +-
drivers/nvme/host/core.c | 1 +
drivers/nvme/host/fc.c | 2 +-
drivers/nvme/host/pci.c | 1 +
drivers/platform/x86/intel-vbtn.c | 12 ++-
drivers/regulator/qcom-rpmh-regulator.c | 4 +-
drivers/scsi/mpt3sas/mpt3sas_base.c | 8 +-
drivers/scsi/qedi/qedi_main.c | 1 +
drivers/scsi/qla2xxx/qla_target.c | 13 ++--
drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 -
fs/cifs/smb2pdu.c | 6 +-
fs/cifs/transport.c | 2 +-
fs/ext4/xattr.c | 4 +
fs/hugetlbfs/inode.c | 4 +-
fs/nfs/Kconfig | 2 +-
fs/nfs/nfs3xdr.c | 3 +-
fs/nfs/nfs4proc.c | 3 +
fs/squashfs/export.c | 8 +-
fs/squashfs/id.c | 6 +-
fs/squashfs/squashfs_fs.h | 1 +
fs/squashfs/xattr_id.c | 6 +-
include/acpi/acpi_bus.h | 1 +
include/linux/bpf.h | 9 ++-
include/linux/hugetlb.h | 2 +-
include/linux/if_macvlan.h | 3 +-
include/linux/mm.h | 15 +++-
include/linux/mutex.h | 2 +-
include/linux/netfilter/x_tables.h | 7 +-
include/linux/u64_stats_sync.h | 7 +-
include/net/inet_connection_sock.h | 2 +-
include/net/nexthop.h | 24 ++++++
include/net/red.h | 10 ++-
include/net/rtnetlink.h | 2 +
kernel/gcov/clang.c | 69 +++++++++++++++++
kernel/power/energy_model.c | 2 +-
mm/hugetlb.c | 10 +--
mm/userfaultfd.c | 2 +-
net/core/dev.c | 2 +-
net/ipv4/inet_connection_sock.c | 7 +-
net/ipv4/netfilter/arp_tables.c | 16 ++--
net/ipv4/netfilter/ip_tables.c | 16 ++--
net/ipv4/tcp_minisocks.c | 7 +-
net/ipv6/ip6_fib.c | 2 +-
net/ipv6/netfilter/ip6_tables.c | 16 ++--
net/mac80211/cfg.c | 4 +-
net/mac80211/ibss.c | 2 +
net/netfilter/nf_conntrack_netlink.c | 1 +
net/netfilter/x_tables.c | 49 ++++++++----
net/qrtr/qrtr.c | 5 ++
net/sched/sch_choke.c | 7 +-
net/sched/sch_gred.c | 2 +-
net/sched/sch_red.c | 7 +-
net/sched/sch_sfq.c | 2 +-
security/integrity/iint.c | 8 ++
sound/hda/intel-nhlt.c | 5 ++
tools/lib/bpf/Makefile | 2 +-
tools/lib/bpf/btf_dump.c | 2 +-
tools/lib/bpf/netlink.c | 2 +-
tools/perf/util/auxtrace.c | 4 -
.../testing/selftests/bpf/progs/test_tunnel_kern.c | 6 +-
.../selftests/net/forwarding/vxlan_bridge_1d.sh | 2 +-
127 files changed, 621 insertions(+), 304 deletions(-)
^ permalink raw reply [relevance 2%]
* Re: [PATCH 5.10 081/290] gpiolib: Read "gpio-line-names" from a firmware node
2021-03-15 16:32 0% ` Bartosz Golaszewski
@ 2021-03-17 16:05 0% ` Greg KH
0 siblings, 0 replies; 200+ results
From: Greg KH @ 2021-03-17 16:05 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Marek Vasut, LKML, Stable # 4 . 20+, Roman Guskov, Andy Shevchenko
On Mon, Mar 15, 2021 at 05:32:09PM +0100, Bartosz Golaszewski wrote:
> On Mon, Mar 15, 2021 at 4:01 PM Marek Vasut <marex@denx.de> wrote:
> >
> > On 3/15/21 2:52 PM, gregkh@linuxfoundation.org wrote:
> > > From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > >
> > > From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > >
> > > commit b41ba2ec54a70908067034f139aa23d0dd2985ce upstream.
> > >
> > > On STM32MP1, the GPIO banks are subnodes of pin-controller@50002000,
> > > see arch/arm/boot/dts/stm32mp151.dtsi. The driver for
> > > pin-controller@50002000 is in drivers/pinctrl/stm32/pinctrl-stm32.c
> > > and iterates over all of its DT subnodes when registering each GPIO
> > > bank gpiochip. Each gpiochip has:
> > >
> > > - gpio_chip.parent = dev,
> > > where dev is the device node of the pin controller
> > > - gpio_chip.of_node = np,
> > > which is the OF node of the GPIO bank
> > >
> > > Therefore, dev_fwnode(chip->parent) != of_fwnode_handle(chip.of_node),
> > > i.e. pin-controller@50002000 != pin-controller@50002000/gpio@5000*000.
> > >
> > > The original code behaved correctly, as it extracted the "gpio-line-names"
> > > from of_fwnode_handle(chip.of_node) = pin-controller@50002000/gpio@5000*000.
> > >
> > > To achieve the same behaviour, read property from the firmware node.
> >
> > There seem to be some discussion going on around this patch, so please
> > postpone backporting until that is settled. Same for v5.11 backport. I
> > hope Andy/Bartosz agrees ?
>
> Yes, this patch broke at least the testing module and we're working to
> determine if it breaks DT drivers too.
Now dropped, thanks.
greg k-h
^ permalink raw reply [relevance 0%]
* Re: [PATCH 5.10 081/290] gpiolib: Read "gpio-line-names" from a firmware node
2021-03-15 14:18 5% ` Marek Vasut
2021-03-15 16:32 0% ` Bartosz Golaszewski
@ 2021-03-15 18:18 5% ` Andy Shevchenko
1 sibling, 0 replies; 200+ results
From: Andy Shevchenko @ 2021-03-15 18:18 UTC (permalink / raw)
To: Marek Vasut
Cc: Greg Kroah-Hartman, Linux Kernel Mailing List, Stable,
Roman Guskov, Andy Shevchenko, Bartosz Golaszewski
On Mon, Mar 15, 2021 at 5:05 PM Marek Vasut <marex@denx.de> wrote:
>
> On 3/15/21 2:52 PM, gregkh@linuxfoundation.org wrote:
> > From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> >
> > From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> >
> > commit b41ba2ec54a70908067034f139aa23d0dd2985ce upstream.
> >
> > On STM32MP1, the GPIO banks are subnodes of pin-controller@50002000,
> > see arch/arm/boot/dts/stm32mp151.dtsi. The driver for
> > pin-controller@50002000 is in drivers/pinctrl/stm32/pinctrl-stm32.c
> > and iterates over all of its DT subnodes when registering each GPIO
> > bank gpiochip. Each gpiochip has:
> >
> > - gpio_chip.parent = dev,
> > where dev is the device node of the pin controller
> > - gpio_chip.of_node = np,
> > which is the OF node of the GPIO bank
> >
> > Therefore, dev_fwnode(chip->parent) != of_fwnode_handle(chip.of_node),
> > i.e. pin-controller@50002000 != pin-controller@50002000/gpio@5000*000.
> >
> > The original code behaved correctly, as it extracted the "gpio-line-names"
> > from of_fwnode_handle(chip.of_node) = pin-controller@50002000/gpio@5000*000.
> >
> > To achieve the same behaviour, read property from the firmware node.
>
> There seem to be some discussion going on around this patch, so please
> postpone backporting until that is settled. Same for v5.11 backport. I
> hope Andy/Bartosz agrees ?
No need to postpone. The fix will be somewhere else, though inside gpiolib.c.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [relevance 5%]
* Re: [PATCH 5.10 081/290] gpiolib: Read "gpio-line-names" from a firmware node
2021-03-15 14:18 5% ` Marek Vasut
@ 2021-03-15 16:32 0% ` Bartosz Golaszewski
2021-03-17 16:05 0% ` Greg KH
2021-03-15 18:18 5% ` Andy Shevchenko
1 sibling, 1 reply; 200+ results
From: Bartosz Golaszewski @ 2021-03-15 16:32 UTC (permalink / raw)
To: Marek Vasut
Cc: Greg KH, LKML, Stable # 4 . 20+, Roman Guskov, Andy Shevchenko
On Mon, Mar 15, 2021 at 4:01 PM Marek Vasut <marex@denx.de> wrote:
>
> On 3/15/21 2:52 PM, gregkh@linuxfoundation.org wrote:
> > From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> >
> > From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> >
> > commit b41ba2ec54a70908067034f139aa23d0dd2985ce upstream.
> >
> > On STM32MP1, the GPIO banks are subnodes of pin-controller@50002000,
> > see arch/arm/boot/dts/stm32mp151.dtsi. The driver for
> > pin-controller@50002000 is in drivers/pinctrl/stm32/pinctrl-stm32.c
> > and iterates over all of its DT subnodes when registering each GPIO
> > bank gpiochip. Each gpiochip has:
> >
> > - gpio_chip.parent = dev,
> > where dev is the device node of the pin controller
> > - gpio_chip.of_node = np,
> > which is the OF node of the GPIO bank
> >
> > Therefore, dev_fwnode(chip->parent) != of_fwnode_handle(chip.of_node),
> > i.e. pin-controller@50002000 != pin-controller@50002000/gpio@5000*000.
> >
> > The original code behaved correctly, as it extracted the "gpio-line-names"
> > from of_fwnode_handle(chip.of_node) = pin-controller@50002000/gpio@5000*000.
> >
> > To achieve the same behaviour, read property from the firmware node.
>
> There seem to be some discussion going on around this patch, so please
> postpone backporting until that is settled. Same for v5.11 backport. I
> hope Andy/Bartosz agrees ?
Yes, this patch broke at least the testing module and we're working to
determine if it breaks DT drivers too.
Bart
^ permalink raw reply [relevance 0%]
* Re: [PATCH 5.10 081/290] gpiolib: Read "gpio-line-names" from a firmware node
@ 2021-03-15 14:18 5% ` Marek Vasut
2021-03-15 16:32 0% ` Bartosz Golaszewski
2021-03-15 18:18 5% ` Andy Shevchenko
0 siblings, 2 replies; 200+ results
From: Marek Vasut @ 2021-03-15 14:18 UTC (permalink / raw)
To: gregkh, linux-kernel
Cc: stable, Roman Guskov, Andy Shevchenko, Bartosz Golaszewski
On 3/15/21 2:52 PM, gregkh@linuxfoundation.org wrote:
> From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>
> commit b41ba2ec54a70908067034f139aa23d0dd2985ce upstream.
>
> On STM32MP1, the GPIO banks are subnodes of pin-controller@50002000,
> see arch/arm/boot/dts/stm32mp151.dtsi. The driver for
> pin-controller@50002000 is in drivers/pinctrl/stm32/pinctrl-stm32.c
> and iterates over all of its DT subnodes when registering each GPIO
> bank gpiochip. Each gpiochip has:
>
> - gpio_chip.parent = dev,
> where dev is the device node of the pin controller
> - gpio_chip.of_node = np,
> which is the OF node of the GPIO bank
>
> Therefore, dev_fwnode(chip->parent) != of_fwnode_handle(chip.of_node),
> i.e. pin-controller@50002000 != pin-controller@50002000/gpio@5000*000.
>
> The original code behaved correctly, as it extracted the "gpio-line-names"
> from of_fwnode_handle(chip.of_node) = pin-controller@50002000/gpio@5000*000.
>
> To achieve the same behaviour, read property from the firmware node.
There seem to be some discussion going on around this patch, so please
postpone backporting until that is settled. Same for v5.11 backport. I
hope Andy/Bartosz agrees ?
^ permalink raw reply [relevance 5%]
* Linux 5.11.3
@ 2021-03-04 11:33 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-04 11:33 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.11.3 kernel.
All users of the 5.11 kernel series must upgrade.
The updated 5.11.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.11.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/admin-guide/perf/arm-cmn.rst | 2
Documentation/admin-guide/sysctl/vm.rst | 10
Documentation/filesystems/seq_file.rst | 6
Documentation/scsi/libsas.rst | 10
Documentation/security/keys/core.rst | 4
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/aspeed-g6.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/arm/boot/dts/tegra30-ouya.dts | 4
arch/arm/kernel/sys_oabi-compat.c | 15
arch/arm/mach-at91/pm_suspend.S | 2
arch/arm/mach-ixp4xx/Kconfig | 1
arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9
arch/arm64/Kconfig | 2
arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 5
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7
arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7
arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi | 2
arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi | 2
arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4
arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts | 2
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 10
arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi | 6
arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 15
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4
arch/arm64/boot/dts/qcom/sm8250.dtsi | 2
arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2
arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1
arch/arm64/crypto/aes-glue.c | 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/include/asm/module.lds.h | 6
arch/arm64/kernel/cpufeature.c | 2
arch/arm64/kernel/head.S | 1
arch/arm64/kernel/machine_kexec_file.c | 4
arch/arm64/kernel/probes/uprobes.c | 2
arch/arm64/kernel/ptrace.c | 2
arch/arm64/kernel/suspend.c | 2
arch/csky/kernel/ptrace.c | 2
arch/mips/Makefile | 19
arch/mips/boot/compressed/Makefile | 1
arch/mips/cavium-octeon/setup.c | 9
arch/mips/include/asm/asm.h | 18
arch/mips/include/asm/atomic.h | 2
arch/mips/include/asm/cmpxchg.h | 6
arch/mips/include/asm/page.h | 6
arch/mips/kernel/cpu-probe.c | 15
arch/mips/kernel/relocate.c | 10
arch/mips/kernel/setup.c | 3
arch/mips/kernel/vmlinux.lds.S | 2
arch/mips/lantiq/irq.c | 2
arch/mips/loongson64/Platform | 22
arch/mips/mm/c-r4k.c | 2
arch/mips/vdso/Makefile | 5
arch/nios2/kernel/entry.S | 3
arch/nios2/kernel/sys_nios2.c | 11
arch/powerpc/Kconfig | 2
arch/powerpc/include/asm/kexec.h | 1
arch/powerpc/include/asm/paravirt.h | 1
arch/powerpc/include/asm/uaccess.h | 13
arch/powerpc/kernel/entry_32.S | 3
arch/powerpc/kernel/head_32.h | 2
arch/powerpc/kernel/head_8xx.S | 2
arch/powerpc/kernel/head_book3s_32.S | 6
arch/powerpc/kernel/irq.c | 27
arch/powerpc/kernel/prom_init.c | 12
arch/powerpc/kernel/time.c | 2
arch/powerpc/kexec/elf_64.c | 2
arch/powerpc/kexec/file_load_64.c | 35
arch/powerpc/kvm/Kconfig | 1
arch/powerpc/kvm/powerpc.c | 8
arch/powerpc/lib/sstep.c | 101 +
arch/powerpc/platforms/pseries/dlpar.c | 7
arch/riscv/kernel/vdso/Makefile | 3
arch/s390/kernel/vtime.c | 3
arch/sparc/Kconfig | 2
arch/sparc/kernel/led.c | 2
arch/sparc/lib/memset.S | 1
arch/um/include/shared/skas/mm_id.h | 1
arch/um/kernel/tlb.c | 19
arch/um/os-Linux/skas/process.c | 4
arch/x86/crypto/aesni-intel_glue.c | 28
arch/x86/entry/common.c | 2
arch/x86/include/asm/virtext.h | 17
arch/x86/kernel/cpu/sgx/main.c | 14
arch/x86/kernel/msr.c | 7
arch/x86/kernel/reboot.c | 30
arch/x86/kvm/emulate.c | 4
arch/x86/kvm/mmu/tdp_mmu.c | 3
arch/x86/kvm/svm/nested.c | 22
arch/x86/kvm/svm/svm.c | 8
arch/x86/kvm/x86.c | 1
arch/x86/mm/fault.c | 27
arch/x86/mm/pat/memtype.c | 4
block/bfq-iosched.c | 1
block/blk-settings.c | 12
block/bsg.c | 4
block/genhd.c | 2
block/ioctl.c | 21
certs/blacklist.c | 2
crypto/ecdh_helper.c | 3
crypto/michael_mic.c | 31
drivers/acpi/acpi_configfs.c | 7
drivers/acpi/property.c | 44
drivers/amba/bus.c | 20
drivers/ata/ahci_brcm.c | 14
drivers/auxdisplay/Kconfig | 3
drivers/auxdisplay/ht16k33.c | 3
drivers/base/auxiliary.c | 13
drivers/base/base.h | 5
drivers/base/init.c | 1
drivers/base/regmap/regmap-sdw.c | 4
drivers/base/swnode.c | 8
drivers/block/floppy.c | 30
drivers/block/zram/zram_drv.c | 2
drivers/bluetooth/btqcomsmd.c | 27
drivers/bluetooth/btusb.c | 20
drivers/bluetooth/hci_ldisc.c | 41
drivers/bluetooth/hci_qca.c | 33
drivers/bluetooth/hci_serdev.c | 4
drivers/bus/mhi/core/init.c | 3
drivers/char/hw_random/ingenic-trng.c | 6
drivers/char/hw_random/timeriomem-rng.c | 2
drivers/char/random.c | 2
drivers/char/tpm/tpm.h | 4
drivers/char/tpm/tpm_tis_core.c | 50
drivers/clk/clk-ast2600.c | 37
drivers/clk/clk-divider.c | 9
drivers/clk/meson/clk-pll.c | 10
drivers/clk/qcom/gcc-msm8998.c | 100 -
drivers/clk/qcom/gcc-sc7180.c | 47
drivers/clk/qcom/lpass-gfm-sm8250.c | 8
drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10
drivers/clocksource/Kconfig | 1
drivers/clocksource/mxs_timer.c | 5
drivers/cpufreq/acpi-cpufreq.c | 62
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24
drivers/cpufreq/freq_table.c | 8
drivers/cpufreq/intel_pstate.c | 21
drivers/cpufreq/qcom-cpufreq-hw.c | 40
drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 +-
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2
drivers/crypto/bcm/cipher.c | 2
drivers/crypto/bcm/cipher.h | 4
drivers/crypto/bcm/util.c | 2
drivers/crypto/qat/Kconfig | 2
drivers/crypto/talitos.c | 50
drivers/crypto/talitos.h | 1
drivers/dax/bus.c | 2
drivers/dma/fsldma.c | 6
drivers/dma/hsu/pci.c | 21
drivers/dma/idxd/dma.c | 1
drivers/dma/owl-dma.c | 1
drivers/dma/qcom/gpi.c | 2
drivers/dma/ti/k3-udma.c | 1
drivers/firmware/arm_scmi/driver.c | 4
drivers/gpio/gpio-pcf857x.c | 2
drivers/gpu/drm/Kconfig | 3
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 22
drivers/gpu/drm/amd/amdgpu/soc15.c | 2
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2
drivers/gpu/drm/amd/display/dc/bios/command_table.c | 61
drivers/gpu/drm/amd/display/dc/core/dc.c | 27
drivers/gpu/drm/amd/display/dc/dc_stream.h | 3
drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 1
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2
drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6
drivers/gpu/drm/drm_dp_mst_topology.c | 3
drivers/gpu/drm/drm_fb_helper.c | 15
drivers/gpu/drm/drm_modes.c | 4
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22
drivers/gpu/drm/gma500/psb_drv.c | 2
drivers/gpu/drm/i915/display/intel_hdmi.c | 6
drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12
drivers/gpu/drm/lima/lima_sched.c | 2
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 10
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 10
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2
drivers/gpu/drm/msm/dp/dp_ctrl.c | 2
drivers/gpu/drm/msm/dp/dp_display.c | 5
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2
drivers/gpu/drm/msm/msm_drv.c | 3
drivers/gpu/drm/msm/msm_gem_submit.c | 2
drivers/gpu/drm/msm/msm_kms.h | 8
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h | 1
drivers/gpu/drm/nouveau/nouveau_chan.c | 1
drivers/gpu/drm/nouveau/nouveau_connector.c | 1
drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 59
drivers/gpu/drm/rcar-du/rcar_cmm.c | 2
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11
drivers/gpu/drm/scheduler/sched_main.c | 3
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1
drivers/gpu/drm/tegra/dc.c | 2
drivers/gpu/drm/tegra/dsi.c | 2
drivers/gpu/drm/tegra/hdmi.c | 2
drivers/gpu/drm/tegra/hub.c | 2
drivers/gpu/drm/tegra/sor.c | 2
drivers/gpu/drm/tegra/vic.c | 2
drivers/gpu/drm/ttm/ttm_bo.c | 9
drivers/gpu/drm/vc4/vc4_hdmi.c | 87 -
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4
drivers/gpu/drm/virtio/virtgpu_gem.c | 8
drivers/gpu/drm/virtio/virtgpu_kms.c | 1
drivers/hid/hid-core.c | 3
drivers/hid/hid-logitech-dj.c | 1
drivers/hid/wacom_wac.c | 7
drivers/hsi/controllers/omap_ssi_core.c | 2
drivers/hv/channel_mgmt.c | 3
drivers/hwtracing/coresight/coresight-etm4x-core.c | 21
drivers/hwtracing/coresight/coresight-etm4x-sysfs.c | 2
drivers/i2c/busses/i2c-bcm-iproc.c | 231 ++-
drivers/i2c/busses/i2c-brcmstb.c | 2
drivers/i2c/busses/i2c-exynos5.c | 8
drivers/i2c/busses/i2c-qcom-geni.c | 59
drivers/i3c/master/Kconfig | 1
drivers/ide/falconide.c | 3
drivers/infiniband/core/cm.c | 8
drivers/infiniband/core/cma.c | 70
drivers/infiniband/core/user_mad.c | 17
drivers/infiniband/hw/hns/hns_roce_device.h | 11
drivers/infiniband/hw/hns/hns_roce_hem.c | 9
drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 16
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 70
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 3
drivers/infiniband/hw/hns/hns_roce_main.c | 19
drivers/infiniband/hw/hns/hns_roce_mr.c | 56
drivers/infiniband/hw/hns/hns_roce_qp.c | 37
drivers/infiniband/hw/hns/hns_roce_srq.c | 52
drivers/infiniband/hw/mlx5/devx.c | 4
drivers/infiniband/hw/mlx5/main.c | 14
drivers/infiniband/hw/mlx5/qp.c | 27
drivers/infiniband/sw/rxe/rxe_net.c | 5
drivers/infiniband/sw/rxe/rxe_recv.c | 27
drivers/infiniband/sw/siw/siw.h | 2
drivers/infiniband/sw/siw/siw_main.c | 2
drivers/infiniband/sw/siw/siw_qp.c | 271 +--
drivers/infiniband/sw/siw/siw_qp_rx.c | 26
drivers/infiniband/sw/siw/siw_qp_tx.c | 4
drivers/infiniband/sw/siw/siw_verbs.c | 20
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51
drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1
drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 120 -
drivers/infiniband/ulp/rtrs/rtrs.c | 28
drivers/input/joydev.c | 7
drivers/input/joystick/xpad.c | 1
drivers/input/keyboard/Kconfig | 2
drivers/input/misc/da7280.c | 3
drivers/input/serio/i8042-x86ia64io.h | 4
drivers/input/serio/serport.c | 4
drivers/input/touchscreen/elo.c | 4
drivers/input/touchscreen/raydium_i2c_ts.c | 3
drivers/input/touchscreen/st1232.c | 9
drivers/input/touchscreen/sur40.c | 1
drivers/input/touchscreen/zinitix.c | 2
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2
drivers/iommu/iommu.c | 23
drivers/iommu/mtk_iommu.c | 2
drivers/irqchip/Kconfig | 3
drivers/irqchip/irq-loongson-pch-msi.c | 2
drivers/irqchip/irq-ls-extirq.c | 2
drivers/macintosh/adb-iop.c | 6
drivers/mailbox/arm_mhuv2.c | 4
drivers/mailbox/sprd-mailbox.c | 2
drivers/md/bcache/bcache.h | 3
drivers/md/bcache/btree.c | 21
drivers/md/bcache/journal.c | 4
drivers/md/bcache/super.c | 20
drivers/md/dm-core.h | 4
drivers/md/dm-crypt.c | 1
drivers/md/dm-era-target.c | 93 -
drivers/md/dm-table.c | 168 --
drivers/md/dm-writecache.c | 74
drivers/md/dm.c | 62
drivers/md/dm.h | 2
drivers/media/i2c/Kconfig | 1
drivers/media/i2c/max9286.c | 2
drivers/media/i2c/ov5670.c | 3
drivers/media/pci/cx25821/cx25821-core.c | 4
drivers/media/pci/intel/ipu3/Kconfig | 3
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2
drivers/media/pci/saa7134/saa7134-empress.c | 5
drivers/media/pci/smipcie/smipcie-ir.c | 46
drivers/media/platform/aspeed-video.c | 6
drivers/media/platform/marvell-ccic/mcam-core.c | 2
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4
drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3
drivers/media/platform/pxa_camera.c | 3
drivers/media/platform/qcom/camss/camss-video.c | 3
drivers/media/platform/ti-vpe/cal.c | 4
drivers/media/platform/vsp1/vsp1_drv.c | 4
drivers/media/rc/ir_toy.c | 1
drivers/media/rc/mceusb.c | 2
drivers/media/test-drivers/vidtv/vidtv_psi.c | 5
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/media/v4l2-core/v4l2-ioctl.c | 32
drivers/memory/mtk-smi.c | 4
drivers/memory/ti-aemif.c | 8
drivers/mfd/altera-sysmgr.c | 3
drivers/mfd/bd9571mwv.c | 6
drivers/mfd/gateworks-gsc.c | 2
drivers/mfd/wm831x-auxadc.c | 3
drivers/misc/cardreader/rts5227.c | 5
drivers/misc/eeprom/eeprom_93xx46.c | 1
drivers/misc/fastrpc.c | 7
drivers/misc/mei/bus.c | 7
drivers/misc/mei/hbm.c | 2
drivers/misc/mei/hw-me-regs.h | 5
drivers/misc/mei/interrupt.c | 33
drivers/misc/mei/pci-me.c | 5
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5
drivers/mmc/host/owl-mmc.c | 9
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4
drivers/mmc/host/sdhci-esdhc-imx.c | 3
drivers/mmc/host/sdhci-pci-o2micro.c | 20
drivers/mmc/host/sdhci-sprd.c | 6
drivers/mmc/host/usdhi6rol0.c | 4
drivers/mtd/devices/phram.c | 6
drivers/mtd/nand/raw/intel-nand-controller.c | 6
drivers/mtd/parsers/afs.c | 4
drivers/mtd/parsers/parser_imagetag.c | 4
drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4
drivers/mtd/spi-nor/core.c | 10
drivers/mtd/spi-nor/sfdp.c | 5
drivers/net/Kconfig | 2
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2
drivers/net/dsa/ocelot/felix.c | 16
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
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h | 3
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5
drivers/net/ethernet/ibm/ibmvnic.c | 43
drivers/net/ethernet/ibm/ibmvnic.h | 7
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16
drivers/net/ethernet/intel/i40e/i40e_main.c | 62
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 11
drivers/net/ethernet/intel/i40e/i40e_xsk.c | 2
drivers/net/ethernet/intel/ice/ice.h | 2
drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6
drivers/net/ethernet/intel/ice/ice_ethtool.c | 34
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33
drivers/net/ethernet/marvell/mvneta.c | 9
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 1
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 ++-
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h | 2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 22
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 2
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.h | 2
drivers/net/ethernet/mellanox/mlx5/core/health.c | 22
drivers/net/ethernet/mellanox/mlx5/core/main.c | 3
drivers/net/ethernet/realtek/r8169_main.c | 4
drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26
drivers/net/gtp.c | 1
drivers/net/ipa/ipa_main.c | 4
drivers/net/phy/micrel.c | 1
drivers/net/phy/mscc/Makefile | 1
drivers/net/phy/mscc/mscc.h | 28
drivers/net/phy/mscc/mscc_main.c | 608 ++++----
drivers/net/phy/mscc/mscc_serdes.c | 650 ++++++++
drivers/net/phy/mscc/mscc_serdes.h | 31
drivers/net/phy/phy_device.c | 53
drivers/net/phy/sfp.c | 100 -
drivers/net/ppp/ppp_async.c | 3
drivers/net/ppp/ppp_synctty.c | 3
drivers/net/vxlan.c | 11
drivers/net/wireguard/device.c | 19
drivers/net/wireguard/device.h | 15
drivers/net/wireguard/peer.c | 28
drivers/net/wireguard/peer.h | 4
drivers/net/wireguard/queueing.c | 86 -
drivers/net/wireguard/queueing.h | 45
drivers/net/wireguard/receive.c | 16
drivers/net/wireguard/send.c | 31
drivers/net/wireless/ath/ath10k/mac.c | 2
drivers/net/wireless/ath/ath10k/snoc.c | 5
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3
drivers/net/wireless/ath/ath11k/mac.c | 11
drivers/net/wireless/ath/ath9k/debug.c | 5
drivers/net/wireless/broadcom/b43/phy_n.c | 2
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43
drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 3
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21
drivers/net/xen-netback/interface.c | 8
drivers/nvme/host/multipath.c | 4
drivers/nvme/target/admin-cmd.c | 33
drivers/nvme/target/tcp.c | 59
drivers/nvmem/core.c | 5
drivers/nvmem/qcom-spmi-sdam.c | 7
drivers/of/fdt.c | 12
drivers/opp/of.c | 4
drivers/pci/controller/cadence/pcie-cadence-host.c | 5
drivers/pci/controller/dwc/pcie-qcom.c | 4
drivers/pci/controller/pcie-rcar-host.c | 2
drivers/pci/controller/pcie-rockchip.c | 12
drivers/pci/controller/pcie-xilinx-cpm.c | 1
drivers/pci/pci-bridge-emul.c | 11
drivers/pci/setup-res.c | 6
drivers/pci/syscall.c | 10
drivers/perf/arm-cmn.c | 17
drivers/phy/Kconfig | 1
drivers/phy/cadence/phy-cadence-torrent.c | 1
drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10
drivers/phy/rockchip/phy-rockchip-emmc.c | 8
drivers/platform/chrome/cros_ec_proto.c | 12
drivers/platform/x86/Kconfig | 4
drivers/power/reset/at91-sama5d2_shdwc.c | 2
drivers/power/supply/Kconfig | 1
drivers/power/supply/axp20x_usb_power.c | 2
drivers/power/supply/cpcap-battery.c | 12
drivers/power/supply/cpcap-charger.c | 4
drivers/power/supply/smb347-charger.c | 12
drivers/pwm/pwm-iqs620a.c | 8
drivers/pwm/pwm-rockchip.c | 18
drivers/regulator/axp20x-regulator.c | 7
drivers/regulator/core.c | 6
drivers/regulator/qcom-rpmh-regulator.c | 26
drivers/regulator/rohm-regulator.c | 9
drivers/regulator/s5m8767.c | 15
drivers/remoteproc/mtk_common.h | 1
drivers/remoteproc/mtk_scp.c | 20
drivers/rtc/Kconfig | 3
drivers/rtc/rtc-rx6110.c | 4
drivers/s390/crypto/zcrypt_api.c | 14
drivers/s390/virtio/virtio_ccw.c | 4
drivers/scsi/aic94xx/aic94xx_scb.c | 20
drivers/scsi/bnx2fc/Kconfig | 1
drivers/scsi/hisi_sas/hisi_sas_main.c | 12
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3
drivers/scsi/isci/port.c | 11
drivers/scsi/libsas/sas_event.c | 66
drivers/scsi/libsas/sas_init.c | 27
drivers/scsi/libsas/sas_internal.h | 5
drivers/scsi/lpfc/lpfc_hbadisc.c | 15
drivers/scsi/mvsas/mv_sas.c | 25
drivers/scsi/pm8001/pm8001_hwi.c | 40
drivers/scsi/pm8001/pm8001_sas.c | 7
drivers/scsi/pm8001/pm80xx_hwi.c | 35
drivers/scsi/qla2xxx/qla_dbg.c | 1
drivers/scsi/qla2xxx/qla_mbx.c | 3
drivers/scsi/sd.c | 6
drivers/scsi/sd_zbc.c | 6
drivers/scsi/ufs/ufshcd.c | 17
drivers/soc/aspeed/aspeed-lpc-snoop.c | 30
drivers/soc/aspeed/aspeed-socinfo.c | 33
drivers/soc/qcom/ocmem.c | 8
drivers/soc/qcom/socinfo.c | 2
drivers/soc/samsung/exynos-asv.c | 18
drivers/soc/ti/pm33xx.c | 5
drivers/soundwire/bus.c | 47
drivers/soundwire/cadence_master.c | 8
drivers/soundwire/intel_init.c | 3
drivers/spi/spi-atmel.c | 2
drivers/spi/spi-cadence-quadspi.c | 2
drivers/spi/spi-dw-bt1.c | 2
drivers/spi/spi-fsl-spi.c | 2
drivers/spi/spi-imx.c | 2
drivers/spi/spi-pxa2xx-pci.c | 27
drivers/spi/spi-stm32.c | 4
drivers/spi/spi-synquacer.c | 4
drivers/spi/spi.c | 2
drivers/spmi/spmi-pmic-arb.c | 5
drivers/staging/gdm724x/gdm_usb.c | 10
drivers/staging/media/allegro-dvt/allegro-core.c | 3
drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24
drivers/staging/media/atomisp/pci/hmm/hmm.c | 2
drivers/staging/media/imx/imx-media-csc-scaler.c | 4
drivers/staging/media/imx/imx-media-dev.c | 7
drivers/staging/media/imx/imx7-media-csi.c | 27
drivers/staging/mt7621-dma/Makefile | 2
drivers/staging/mt7621-dma/hsdma-mt7621.c | 760 ++++++++++
drivers/staging/mt7621-dma/mtk-hsdma.c | 760 ----------
drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1
drivers/staging/rtl8723bs/os_dep/wifi_regd.c | 2
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 6
drivers/staging/wfx/data_tx.c | 10
drivers/staging/wfx/data_tx.h | 1
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3
drivers/tee/optee/rpc.c | 31
drivers/thermal/cpufreq_cooling.c | 2
drivers/tty/n_gsm.c | 3
drivers/tty/n_hdlc.c | 60
drivers/tty/n_null.c | 3
drivers/tty/n_r3964.c | 10
drivers/tty/n_tracerouter.c | 4
drivers/tty/n_tracesink.c | 4
drivers/tty/n_tty.c | 82 -
drivers/tty/serial/stm32-usart.c | 24
drivers/tty/tty_io.c | 82 -
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/usb/serial/pl2303.c | 8
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2
drivers/vfio/pci/vfio_pci_zdev.c | 4
drivers/vfio/vfio_iommu_type1.c | 48
drivers/video/fbdev/Kconfig | 2
drivers/virt/vboxguest/vboxguest_utils.c | 18
drivers/w1/slaves/w1_therm.c | 22
drivers/watchdog/intel-mid_wdt.c | 8
drivers/watchdog/mei_wdt.c | 1
drivers/watchdog/qcom-wdt.c | 13
fs/affs/namei.c | 4
fs/btrfs/backref.c | 9
fs/btrfs/backref.h | 9
fs/btrfs/block-group.c | 29
fs/btrfs/ctree.c | 7
fs/btrfs/delayed-ref.c | 56
fs/btrfs/delayed-ref.h | 16
fs/btrfs/extent-tree.c | 128 -
fs/btrfs/free-space-cache.c | 6
fs/btrfs/inode.c | 3
fs/btrfs/relocation.c | 4
fs/btrfs/space-info.h | 17
fs/ceph/caps.c | 10
fs/cifs/cifs_swn.c | 2
fs/cifs/connect.c | 259 +--
fs/cifs/dfs_cache.c | 33
fs/cifs/fs_context.c | 43
fs/debugfs/inode.c | 5
fs/erofs/xattr.c | 10
fs/erofs/zmap.c | 10
fs/eventpoll.c | 4
fs/exfat/exfat_raw.h | 4
fs/exfat/super.c | 31
fs/ext4/Kconfig | 3
fs/ext4/namei.c | 7
fs/f2fs/compress.c | 5
fs/f2fs/data.c | 12
fs/f2fs/f2fs.h | 2
fs/f2fs/file.c | 30
fs/f2fs/inline.c | 4
fs/f2fs/super.c | 3
fs/gfs2/bmap.c | 6
fs/gfs2/lock_dlm.c | 8
fs/gfs2/recovery.c | 4
fs/gfs2/util.c | 16
fs/io_uring.c | 17
fs/isofs/dir.c | 1
fs/isofs/namei.c | 1
fs/jffs2/summary.c | 3
fs/jfs/jfs_dmap.c | 2
fs/nfs/nfs4proc.c | 15
fs/nfsd/nfsctl.c | 14
fs/ocfs2/cluster/heartbeat.c | 8
fs/proc/proc_sysctl.c | 4
fs/proc/self.c | 2
fs/proc/task_mmu.c | 9
fs/proc/thread_self.c | 7
fs/pstore/platform.c | 4
fs/quota/quota_v2.c | 11
fs/ubifs/auth.c | 2
fs/ubifs/replay.c | 4
fs/ubifs/super.c | 4
fs/zonefs/super.c | 3
include/acpi/acexcep.h | 10
include/asm-generic/vmlinux.lds.h | 16
include/linux/bpf.h | 8
include/linux/device-mapper.h | 5
include/linux/entry-kvm.h | 14
include/linux/eventpoll.h | 2
include/linux/filter.h | 2
include/linux/icmpv6.h | 28
include/linux/iommu.h | 4
include/linux/ipv6.h | 1
include/linux/kexec.h | 5
include/linux/key.h | 1
include/linux/kgdb.h | 2
include/linux/khugepaged.h | 2
include/linux/memremap.h | 6
include/linux/mfd/rohm-generic.h | 14
include/linux/rcupdate.h | 2
include/linux/rmap.h | 3
include/linux/soundwire/sdw.h | 2
include/linux/tpm.h | 5
include/linux/tty_ldisc.h | 3
include/linux/zsmalloc.h | 2
include/net/act_api.h | 6
include/net/icmp.h | 6
include/net/tcp.h | 9
include/scsi/libsas.h | 11
include/uapi/drm/drm_fourcc.h | 4
include/uapi/drm/drm_mode.h | 13
init/Kconfig | 11
init/main.c | 1
kernel/Makefile | 2
kernel/bpf/bpf_iter.c | 2
kernel/bpf/bpf_lru_list.c | 7
kernel/bpf/devmap.c | 4
kernel/bpf/verifier.c | 3
kernel/debug/debug_core.c | 11
kernel/debug/kdb/kdb_private.h | 2
kernel/entry/common.c | 7
kernel/kcsan/core.c | 26
kernel/kexec_file.c | 5
kernel/kprobes.c | 31
kernel/locking/lockdep.c | 3
kernel/module.c | 164 +-
kernel/module_signature.c | 2
kernel/module_signing.c | 2
kernel/printk/printk.c | 28
kernel/printk/printk_safe.c | 16
kernel/rcu/tree.c | 53
kernel/rcu/tree.h | 2
kernel/rcu/tree_plugin.h | 31
kernel/sched/fair.c | 45
kernel/sched/idle.c | 1
kernel/seccomp.c | 2
kernel/smp.c | 4
kernel/tracepoint.c | 80 -
mm/compaction.c | 43
mm/hugetlb.c | 14
mm/khugepaged.c | 22
mm/memcontrol.c | 30
mm/memory-failure.c | 6
mm/memory.c | 16
mm/memremap.c | 15
mm/slab_common.c | 4
mm/slub.c | 8
mm/vmscan.c | 9
mm/zsmalloc.c | 17
net/bluetooth/a2mp.c | 3
net/bluetooth/hci_core.c | 6
net/bluetooth/hci_request.c | 25
net/core/filter.c | 13
net/ipv4/icmp.c | 5
net/ipv6/icmp.c | 18
net/ipv6/ip6_icmp.c | 12
net/mac80211/mesh_hwmp.c | 2
net/nfc/nci/uart.c | 3
net/qrtr/tun.c | 12
net/sched/act_api.c | 106 -
net/sched/cls_api.c | 12
net/sunrpc/xprtrdma/svc_rdma_transport.c | 6
samples/Kconfig | 2
samples/watch_queue/watch_test.c | 2
security/commoncap.c | 12
security/integrity/evm/evm_crypto.c | 7
security/integrity/ima/ima_kexec.c | 3
security/integrity/ima/ima_mok.c | 5
security/keys/Kconfig | 8
security/keys/key.c | 2
security/keys/trusted-keys/trusted_tpm1.c | 22
security/keys/trusted-keys/trusted_tpm2.c | 22
security/selinux/hooks.c | 4
sound/core/init.c | 4
sound/core/pcm.c | 4
sound/core/pcm_local.h | 1
sound/core/pcm_native.c | 27
sound/firewire/fireface/ff-protocol-latter.c | 118 +
sound/pci/hda/hda_intel.c | 2
sound/pci/hda/patch_hdmi.c | 1
sound/pci/hda/patch_realtek.c | 40
sound/soc/codecs/cpcap.c | 12
sound/soc/codecs/cs42l56.c | 3
sound/soc/codecs/max98373.c | 2
sound/soc/codecs/rt5682-i2c.c | 3
sound/soc/codecs/wsa881x.c | 1
sound/soc/fsl/Kconfig | 1
sound/soc/generic/simple-card-utils.c | 13
sound/soc/intel/boards/sof_sdw.c | 9
sound/soc/qcom/lpass-apq8016.c | 2
sound/soc/qcom/lpass-cpu.c | 30
sound/soc/qcom/lpass-lpaif-reg.h | 3
sound/soc/qcom/lpass-sc7180.c | 2
sound/soc/qcom/lpass.h | 1
sound/soc/qcom/qdsp6/q6asm-dai.c | 21
sound/soc/qcom/qdsp6/q6routing.c | 18
sound/soc/sh/siu.h | 2
sound/soc/sh/siu_pcm.c | 2
sound/soc/sof/debug.c | 2
sound/soc/sof/intel/hda-dsp.c | 4
sound/soc/sof/sof-pci-dev.c | 7
sound/usb/card.h | 2
sound/usb/endpoint.c | 87 -
sound/usb/implicit.c | 2
sound/usb/pcm.c | 7
tools/lib/bpf/libbpf.c | 22
tools/objtool/arch/x86/special.c | 2
tools/objtool/check.c | 15
tools/objtool/check.h | 11
tools/perf/builtin-record.c | 2
tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json | 2
tools/perf/tests/sample-parsing.c | 2
tools/perf/util/cgroup.c | 8
tools/perf/util/event.c | 2
tools/perf/util/evlist.c | 8
tools/perf/util/evlist.h | 4
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 41
tools/perf/util/intel-pt-decoder/intel-pt-decoder.h | 2
tools/perf/util/intel-pt.c | 29
tools/perf/util/symbol.c | 7
tools/perf/util/unwind-libdw.c | 11
tools/testing/kunit/kunit_tool_test.py | 14
tools/testing/scatterlist/main.c | 1
tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c | 33
tools/testing/selftests/bpf/test_progs.c | 13
tools/testing/selftests/bpf/test_progs.h | 1
tools/testing/selftests/bpf/test_xdp_redirect.sh | 10
tools/testing/selftests/dmabuf-heaps/Makefile | 2
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc | 35
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2
tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2
tools/testing/selftests/seccomp/seccomp_bpf.c | 2
tools/testing/selftests/wireguard/netns.sh | 15
782 files changed, 8681 insertions(+), 4731 deletions(-)
Abhishek Pandit-Subedi (1):
Bluetooth: Remove hci_req_le_suspend_config
Adam Ford (2):
arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adrian Hunter (3):
perf intel-pt: Fix missing CYC processing in PSB
perf intel-pt: Fix premature IPC
perf intel-pt: Fix IPC with CYC threshold
Ahmad Fatoum (1):
nvmem: core: skip child nodes not matching binding
Ahmed S. Darwish (6):
scsi: libsas: docs: Remove notify_ha_event()
scsi: libsas: Introduce a _gfp() variant of event notifiers
scsi: mvsas: Pass gfp_t flags to libsas event notifiers
scsi: isci: Pass gfp_t flags in isci_port_link_down()
scsi: isci: Pass gfp_t flags in isci_port_link_up()
scsi: isci: Pass gfp_t flags in isci_port_bc_change_received()
Al Viro (1):
sparc32: fix a user-triggerable oops in clear_user()
Alain Volmat (1):
spi: stm32: properly handle 0 byte transfer
Alex Deucher (2):
Revert "drm/amd/display: Update NV1x SR latency values"
drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Alex Elder (1):
net: ipa: initialize all resources
Alexander Lobakin (3):
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
MIPS: properly stop .eh_frame generation
MIPS: compressed: fix build with enabled UBSAN
Alexander Usyskin (6):
mei: hbm: call mei_set_devstate() on hbm stop response
watchdog: mei_wdt: request stop on unregister
mei: bus: block send with vtag on non-conformat FW
mei: fix transfer over dma with extended header
mei: me: add adler lake point S DID
mei: me: add adler lake point LP DID
Alexey Kardashevskiy (2):
powerpc/uaccess: Avoid might_fault() when user access is enabled
powerpc/kuap: Restore AMR after replaying soft interrupts
Alyssa Rosenzweig (1):
drm/rockchip: Require the YTR modifier for AFBC
Amey Narkhede (1):
staging: gdm724x: Fix DMA from stack
Amir Goldstein (1):
selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Anand K Mistry (2):
ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Ananth N Mavinakayanahalli (2):
powerpc/sstep: Check instruction validity against ISA version before emulation
powerpc/sstep: Fix incorrect return from analyze_instr()
Andre Przywara (7):
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
arm64: dts: allwinner: H6: properly connect USB PHY to port 0
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
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()
Andreas Gruenbacher (2):
gfs2: Lock imbalance on error path in gfs2_recover_one
gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Oetken (1):
nios2: fixed broken sys_clone syscall
Andrey Grodzovsky (1):
drm/sched: Cancel and flush all outstanding jobs before finish.
Andrii Nakryiko (5):
bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
bpf: Declare __bpf_free_used_maps() unconditionally
selftests/bpf: Sync RCU before unloading bpf_testmod
selftests/bpf: Don't exit on failed bpf_testmod unload
Andy Lutomirski (1):
x86/fault: Fix AMD erratum #91 errata fixup for user code
Andy Shevchenko (3):
media: ipu3-cio2: Build only for x86
watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
spi: pxa2xx: Fix the controller numbering for Wildcat Point
AngeloGioacchino Del Regno (1):
clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Anson Jacob (1):
Revert "drm/amd/display: reuse current context instead of recreating one"
Ansuel Smith (1):
PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ard Biesheuvel (5):
PCI: Decline to resize resources if boot config must be preserved
crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
crypto: arm64/sha - add missing module aliases
crypto: aesni - prevent misaligned buffers on the stack
crypto: michael_mic - fix broken misalignment handling
Arnaldo Carvalho de Melo (1):
perf tools: Fix DSO filtering when not finding a map for a sampled address
Arnd Bergmann (8):
ARM: s3c: fix fiq for clang IAS
optee: simplify i2c access
ARM: at91: use proper asm syntax in pm_suspend
ASoC: fsl_aud2htx: select SND_SOC_IMX_PCM_DMA
ubifs: replay: Fix high stack usage, again
rtc: rx6110: fix build against modular I2C
clocksource/drivers/ixp4xx: Select TIMER_OF when needed
mfd: altera-sysmgr: Fix physical address storing more
Artem Lapkin (1):
arm64: dts: meson: fix broken wifi node for Khadas VIM3L
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
Aurelien Jarno (1):
MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Avihai Horon (1):
RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Ayush Sawal (1):
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Bard Liao (2):
soundwire: export sdw_write/read_no_pm functions
regmap: sdw: use _no_pm functions in regmap_read/write
Bart Van Assche (1):
scsi: sd: Fix Opal support
Bartosz Golaszewski (1):
rtc: s5m: select REGMAP_I2C
Bernard Metzler (1):
RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Biwen Li (1):
irqchip/ls-extirq: add IRQCHIP_SKIP_SET_WAKE to the irqchip flags
Bjarni Jonasson (3):
net: phy: mscc: adding LCPLL reset to VSC8514
net: phy: mscc: improved serdes calibration applied to VSC8514
net: phy: mscc: coma mode disabled for VSC8514
Björn Töpel (1):
selftests/bpf: Convert test_xdp_redirect.sh to bash
Bob Pearson (3):
RDMA/rxe: Fix coding error in rxe_recv.c
RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
RDMA/rxe: Correct skb on loopback path
Bob Peterson (2):
gfs2: fix glock confusion in function signal_our_withdraw
gfs2: Don't skip dlm unlock if glock has an lvb
Borislav Petkov (1):
staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Brett Creeley (1):
ice: Account for port VLAN in VF max packet size calculation
Camelia Groza (1):
dpaa_eth: fix the access method for the dpaa_napi_portal
Can Guo (1):
scsi: ufs: Fix a possible NULL pointer issue
Chaitanya Kulkarni (2):
nvmet: remove extra variable in identify ns
nvmet: set status to 0 in case for invalid nsid
Chao Yu (3):
f2fs: compress: fix potential deadlock
f2fs: fix out-of-repair __setattr_copy()
f2fs: enforce the immutable flag on open files
Chen Wandun (1):
mm/hugetlb: suppress wrong warning info when alloc gigantic page
Chen Yu (1):
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Chen-Yu Tsai (3):
arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
PCI: rockchip: Make 'ep-gpios' DT property optional
Chenyang Li (1):
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Chia-I Wu (1):
drm/virtio: make sure context is created in gem open
Chris Ruehl (1):
phy: rockchip-emmc: emmc_phy_init() always return 0
Chris Wilson (4):
drm/i915/gt: One more flush for Baytrail clear residuals
drm/i915/gt: Flush before changing register state
drm/i915/gt: Correct surface base address for renderclear
kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Christian Melki (1):
net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ8081
Christoph Hellwig (1):
block: reopen the device in blkdev_reread_part
Christophe JAILLET (14):
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()
soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
hwrng: ingenic - Fix a resource leak in an error handling path
media: vsp1: Fix an error handling path in the probe function
media: cx25821: Fix a bug when reallocating some dma memory
mtd: rawnand: intel: Fix an error handling path in 'ebu_dma_start()'
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: owl-mmc: Fix a resource leak in an error handling path and in the remove function
mmc: sdhci-sprd: Fix some resource leaks in the remove function
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe Leroy (7):
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
crypto: talitos - Fix ctr(aes) on SEC1
powerpc/kvm: Force selection of CONFIG_PPC_FPU
powerpc/47x: Disable 256k page size
powerpc/8xx: Fix software emulation interrupt
powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
powerpc/32s: Add missing call to kuep_lock on syscall entry
Christopher William Snowhill (1):
Bluetooth: Fix initializing response id after clearing struct
Chuck Lever (1):
svcrdma: Hold private mutex while invoking rdma_accept()
Chuhong Yuan (2):
drm/fb-helper: Add missed unlocks in setcmap_legacy()
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Claire Chang (1):
Bluetooth: hci_uart: Fix a race for write_work scheduling
Claudiu Beznea (1):
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Colin Ian King (4):
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
power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Cong Wang (1):
net_sched: fix RTNL deadlock again caused by request_module()
Corentin Labbe (6):
crypto: sun4i-ss - linearize buffers content must be kept
crypto: sun4i-ss - fix kmap usage
crypto: sun4i-ss - checking sg length is not sufficient
crypto: sun4i-ss - IV register does not work on A10 and A13
crypto: sun4i-ss - handle BigEndian for cipher
crypto: sun4i-ss - initialize need_fallback
Cornelia Huck (1):
virtio/s390: implement virtio-ccw revision 2 correctly
Cristian Marussi (1):
firmware: arm_scmi: Fix call site of scmi_notification_exit
Cédric Le Goater (2):
KVM: PPC: Make the VMX instruction emulation routines static
powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Daeho Jeong (1):
f2fs: fix null page reference in redirty_blocks
Dan Carpenter (22):
soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
ath11k: fix a locking bug in ath11k_mac_op_start()
gma500: clean up error handling in init
media: allegro: Fix use after free on error
media: camss: Fix signedness bug in video_enum_fmt()
media: camss: missing error code in msm_video_register()
ASoC: cs42l56: fix up error handling in probe
media: atomisp: Fix a buffer overflow in debug code
mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
drm/virtio: fix an error code in virtio_gpu_init()
scsi: lpfc: Fix ancient double free
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()
phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
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):
mm: fix memory_failure() handling of dax-namespace metadata
Daniel Latypov (1):
kunit: tool: fix unit test cleanup handling
Daniel Scally (1):
media: software_node: Fix refcounts in software_node_get_next_child()
Daniel W. S. Almeida (1):
media: vidtv: psi: fix missing crc for PMT
Daniele Alessandrelli (1):
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Dany Madden (1):
ibmvnic: change IBMVNIC_MAX_IND_DESCS to 16
Dave Ertman (2):
ice: report correct max number of TCs
ice: Fix state bits on LLDP mode switch
Dave Hansen (1):
mm/vmscan: restore zone_reclaim_mode ABI
Dave Jiang (2):
driver core: auxiliary bus: Fix calling stage for auxiliary bus init
dmaengine: idxd: set DMA channel to be private
Dave Rigby (1):
perf unwind: Set userdata for all __report_module() paths
David E. Box (3):
platform/x86: intel_pmt: Make INTEL_PMT_CLASS non-user-selectable
platform/x86: intel_pmt_telemetry: Add dependency on MFD_INTEL_PMT
platform/x86: intel_pmt_crashlog: Add dependency on MFD_INTEL_PMT
David Gow (2):
i3c/master/mipi-i3c-hci: Specify HAS_IOMEM dependency
rtc: zynqmp: depend on HAS_IOMEM
David Howells (1):
certs: Fix blacklist flag type confusion
Dehe Gu (1):
f2fs: fix a wrong condition in __submit_bio
Dinghao Liu (6):
Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
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
evm: Fix memleak in init_desc
ubifs: Fix memleak in ubifs_init_authentication
Dinh Nguyen (1):
arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Dmitry Baryshkov (4):
arm64: dts: qcom: sm8250: correct sdhc_2 xo clk
arm64: dts: qcom: qrb5165-rb5: fix uSD pins drive strength
regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Osipenko (2):
opp: Correct debug message in _opp_add_static_v2()
power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Dmitry Safonov (1):
perf symbols: Use (long) for iterator for bfd symbols
Dmitry Torokhov (4):
Input: da7280 - fix missing error test
Input: da7280 - protect OF match table with CONFIG_OF
Input: imx_keypad - add dependency on HAS_IOMEM
Input: zinitix - fix return type of zinitix_init_touch()
Dom Cobley (4):
drm/vc4: hdmi: Move hdmi reset to bind
drm/vc4: hdmi: Fix register offset with longer CEC messages
drm/vc4: hdmi: Fix up CEC registers
drm/vc4: hdmi: Restore cec physical address on reconnect
Douglas Anderson (1):
iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Edwin Peer (1):
bnxt_en: reverse order of TX disable and carrier off
Enric Balletbo i Serra (1):
arm64: dts: mt8183: Add missing power-domain for pwm0 node
Eric Anholt (2):
drm/msm: Fix race of GPU init vs timestamp power management.
drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Bernstein (1):
drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Eric Biggers (1):
random: fix the RNDRESEEDCRNG ioctl
Eric Dumazet (1):
tcp: fix SO_RCVLOWAT related hangs under mem pressure
Eric W. Biederman (1):
capabilities: Don't allow writing ambiguous v3 file capabilities
Erwan Le Ray (1):
serial: stm32: fix DMA initialization error handling
Evan Benn (2):
platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Ezequiel Garcia (2):
media: imx: Unregister csc/scaler only if registered
media: imx: Fix csc/scaler unregister
Fabio Estevam (1):
media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Fangrui Song (1):
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Felix Kuehling (1):
drm/amdkfd: Fix recursive lock warnings
Ferry Toth (1):
dmaengine: hsu: disable spurious interrupt
Filipe Laíns (1):
HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Filipe Manana (1):
btrfs: fix extent buffer leak on failure to copy root
Finn Thain (2):
macintosh/adb-iop: Use big-endian autopoll mask
ide/falconide: Fix module unload
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
Frank van der Linden (1):
module: harden ELF info handling
Frantisek Hrbata (1):
drm/nouveau: bail out of nouveau_channel_new if channel init fails
Frederic Weisbecker (5):
rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
rcu/nocb: Perform deferred wake up before last idle's need_resched() check
rcu/nocb: Trigger self-IPI on late deferred wake up before user resume
entry: Explicitly flush pending rcuog wakeup before last rescheduling point
entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point
Gabriel Krisman Bertazi (1):
watch_queue: Drop references to /dev/watch_queue
Gao Xiang (1):
erofs: initialized fields can only be observed after bit is set
Geert Uytterhoeven (9):
arm64: dts: renesas: beacon: Fix EEPROM compatible value
irqchip/imx: IMX_INTMUX should not default to y, unconditionally
clk: renesas: r8a779a0: Remove non-existent S2 clock
clk: renesas: r8a779a0: Fix parent of CBFUSA clock
auxdisplay: ht16k33: Fix refresh rate handling
auxdisplay: Fix duplicate CHARLCD config symbol
Input: st1232 - fix NORMAL vs. IDLE state handling
phy: USB_LGM_PHY should depend on X86
ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Gioh Kim (2):
RDMA/rtrs-srv: fix memory leak by missing kobject free
RDMA/rtrs-srv-sysfs: fix missing put_device
Giulio Benetti (1):
drm/sun4i: tcon: fix inverted DCLK polarity
Greg Kroah-Hartman (3):
debugfs: be more robust at handling improper input in debugfs_lookup()
debugfs: do not attempt to create a new file before the filesystem is initalized
Linux 5.11.3
Guchun Chen (1):
drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
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
Guido Günther (2):
drm/panel: mantix: Tweak init sequence
spi: imx: Don't print error on -EPROBEDEFER
Guoqing Jiang (3):
RDMA/rtrs-srv: Jump to dereg_mr label if allocate iu fails
RDMA/rtrs: Call kobject_put in the failure path
RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Hans de Goede (2):
virt: vbox: Do not use wait_event_interruptible when called from kernel context
regulator: core: Avoid debugfs: Directory ... already present! error
Hao Xu (1):
io_uring: fix possible deadlock in io_uring_poll
Harald Freudenberger (1):
s390/zcrypt: return EIO when msg retry limit reached
Hari Bathini (1):
powerpc/kexec_file: fix FDT size estimation for kdump kernel
He Zhe (1):
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
Heiko Carstens (1):
s390/vtime: fix inline assembly clobber list
Heiko Stuebner (1):
drm/panel: kd35t133: allow using non-continuous dsi clock
Heiner Kallweit (3):
net: phy: consider that suspend2ram may cut off PHY power
PCI: Align checking of syscall user config accessors
r8169: fix jumbo packet handling on RTL8168e
Henry Tieman (1):
ice: update the number of available RSS queues
Huacai Chen (1):
irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Hui Wang (1):
ASoC: SOF: debug: Fix a potential issue on string buffer termination
Ilya Leoshkevich (1):
bpf: Clear subreg_def for global function return values
Ilya Lipnitskiy (1):
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Imre Deak (1):
drm/dp_mst: Don't cache EDIDs for physical ports
Ioana Ciornei (1):
dpaa2-eth: fix memory leak in XDP_REDIRECT
Isaac J. Manjarres (1):
iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Iskren Chernev (2):
drm/msm: Fix MSM_INFO_GET_IOVA with carveout
drm/msm/mdp5: Fix wait-for-commit for cmd panels
Ivan Zaentsev (1):
w1: w1_therm: Fix conversion result for negative temperatures
J. Bruce Fields (1):
nfsd: register pernet ops last, unregister first
Jack Pham (1):
usb: gadget: u_audio: Free requests only after callback
Jack Wang (9):
RDMA/rtrs: Extend ibtrs_cq_qp_create
RDMA/rtrs-srv: Release lock before call into close_sess
RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
RDMA/rtrs-clt: Set mininum limit when create QP
RDMA/rtrs-srv: Fix missing wr_cqe
RDMA/rtrs-srv: Init wr_cnt as 1
RDMA/rtrs: Fix KASAN: stack-out-of-bounds bug
RDMA/rtrs-srv: Fix stack-out-of-bounds
RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Jacopo Mondi (1):
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Jae Hyun Yoo (1):
soc: aspeed: snoop: Add clock control logic
Jaegeuk Kim (1):
f2fs: flush data when enabling checkpoint back
James Bottomley (2):
tpm_tis: Fix check_locality for correct locality acquisition
tpm_tis: Clean up locality release
James Reynolds (1):
media: mceusb: Fix potential out-of-bounds shift
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
Jan Kokemüller (1):
drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Jann Horn (1):
Take mmap lock in cacheflush syscall
Jarkko Sakkinen (3):
KEYS: trusted: Fix incorrect handling of tpm_get_random()
KEYS: trusted: Fix migratable=1 failing
KEYS: trusted: Reserve TPM for seal and unseal operations
Jason A. Donenfeld (5):
wireguard: device: do not generate ICMP for non-IP packets
wireguard: kconfig: use arm chacha even with no neon
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
wireguard: selftests: test multiple parallel streams
wireguard: queueing: get rid of per-peer ring buffers
Jason Gerecke (1):
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Jeff Layton (1):
ceph: fix flush_snap logic after putting caps
Jeffle Xu (3):
dm table: fix iterate_devices based device capability checks
dm table: fix DAX iterate_devices based device capability checks
dm table: fix zoned iterate_devices based device capability checks
Jens Axboe (1):
proc: don't allow async path resolution of /proc/thread-self components
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()
Jinyang He (1):
MIPS: relocatable: Provide kaslr_offset() to get the kernel offset
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
Joel Stanley (1):
soc: aspeed: socinfo: Add new systems
Johan Hovold (2):
USB: serial: ftdi_sio: fix FTX sub-integer prescaler
USB: serial: pl2303: fix line-speed handling on newer chips
Johannes Berg (2):
um: mm: check more comprehensively for stub changes
um: defer killing userspace on page table update failures
Johannes Thumshirn (1):
scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
John Garry (2):
scsi: libsas: Remove notifier indirection
perf vendor events arm64: Fix Ampere eMag event typo
John Ogness (1):
printk: avoid prb_first_valid_seq() where possible
John Stultz (1):
kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
John Wang (1):
ARM: dts: aspeed: Add LCLK to lpc-snoop
Jonathan Marek (2):
regulator: qcom-rpmh: fix pm8009 ldo7
misc: fastrpc: fix incorrect usage of dma_map_sgtable
Jorgen Hansen (1):
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Josef Bacik (9):
proc: use kvzalloc for our kernel buffer
btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
btrfs: do not warn if we can't find the reloc root when looking up backref
btrfs: add asserts for deleting backref cache nodes
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
btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
btrfs: account for new extents being deleted in total_bytes_pinned
Josh Poimboeuf (3):
objtool: Fix error handling for STD/CLD warnings
objtool: Fix retpoline detection in asm code
objtool: Fix ".cold" section suffix check for newer versions of GCC
Judy Hsiao (2):
ASoC: max98373: Fixes a typo in max98373_feedback_get
drm/msm/dp: trigger unplug event in msm_dp_display_disable
Juergen Gross (1):
xen/netback: fix spurious event detection for common event case
Jun Nie (1):
ASoC: qcom: lpass: Fix i2s ctl register bit map
Jun'ichi Nomura (1):
bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Jupeng Zhong (1):
Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Jérôme Pouiller (1):
staging: wfx: fix possible panic with re-queued frames
Kai Krakow (3):
Revert "bcache: Kill btree_io_wq"
bcache: Give btree_io_wq correct semantics again
bcache: Move journal work to new flush wq
Kai Vehmanen (1):
ALSA: hda: Add another CometLake-H PCI ID
Kamal Heib (1):
RDMA/siw: Fix calculation of tx_valid_cpus size
KarimAllah Ahmed (1):
fdt: Properly handle "no-map" field in the memory region
Karol Herbst (1):
drm/nouveau/kms: handle mDP connectors
Kees Cook (1):
spi: dw: Avoid stack content exposure
Keith Busch (1):
nvme-multipath: set nr_zones for zoned namespaces
Keqian Zhu (2):
vfio/iommu_type1: Populate full dirty when detach non-pinned group
vfio/iommu_type1: Fix some sanity checks in detach group
Kevin Hao (1):
Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Konrad Dybcio (1):
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Krzysztof Kozlowski (10):
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
soc: samsung: exynos-asv: handle reading revision register error
Krzysztof Wilczyński (1):
PCI: cadence: Fix DMA range mapping early return error
Lad Prabhakar (1):
media: i2c/Kconfig: Select FWNODE for OV772x sensor
Lakshmi Ramasubramanian (2):
ima: Free IMA measurement buffer on error
ima: Free IMA measurement buffer after kexec syscall
Lang Cheng (2):
RDMA/hns: Allocate one more recv SGE for HIP08
RDMA/hns: Fixes missing error code of CMDQ
Laurent Pinchart (2):
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
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 Ou (1):
RDMA/hns: Disable RQ inline by default
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
Linus Torvalds (2):
tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
tty: implement read_iter
Linus Walleij (2):
drm/panel: s6e63m0: Fix init sequence again
drm/panel: s6e63m0: Support max-brightness
Loic Poulain (1):
mhi: Fix double dma free
Lubomir Rintel (1):
media: marvell-ccic: power up the device on mclk enable
Luca Coelho (7):
iwlwifi: mvm: set enabled in the PPAG command properly
iwlwifi: mvm: fix the type we use in the PPAG table validity checks
iwlwifi: mvm: store PPAG enabled/disabled flag properly
iwlwifi: mvm: send stored PPAG command instead of local
iwlwifi: mvm: assign SAR table revision to the command later
iwlwifi: pnvm: set the PNVM again if it was already loaded
iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Weiss (1):
soc: qcom: ocmem: don't return NULL in of_get_ocmem
Luo Meng (1):
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Magnum Shan (1):
mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Manivannan Sadhasivam (1):
mtd: parsers: afs: Fix freeing the part name memory in failure
Maor Gottlieb (1):
tools/testing/scatterlist: Fix overflow of max segment size
Marc Kleine-Budde (1):
can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Marc Zyngier (1):
arm64: Add missing ISB after invalidating TLB in __primary_switch
Marcin Ślusarz (1):
soundwire: intel: fix possible crash when no device is detected
Marco Chiappero (1):
crypto: qat - replace CRYPTO_AES with CRYPTO_LIB_AES in Kconfig
Marco Elver (2):
bpf_lru_list: Read double-checked variable once without lock
kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Marcos Paulo de Souza (1):
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Marek Behún (1):
arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Marek Olšák (1):
drm/amdgpu: fix CGTS_TCC_DISABLE register offset on gfx10.3
Marek Szyprowski (1):
soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Marek Vasut (1):
PCI: rcar: Always allocate MSI addresses in 32bit space
Mario Kleiner (2):
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Mark Bloch (1):
RDMA/mlx5: Allow creating all QPs even when non RDMA profile is used
Martin Blumenstingl (4):
net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
clk: meson: clk-pll: make "ret" a signed integer
clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin KaFai Lau (1):
libbpf: Ignore non function pointer member in struct_ops
Martin Kaiser (1):
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Masahisa Kojima (1):
spi: spi-synquacer: fix set_cs handling
Masami Hiramatsu (1):
kprobes: Fix to delay the kprobes jump optimization
Mateusz Palczewski (4):
i40e: Add zero-initialization of AQ command structures
i40e: Fix overwriting flow control settings during driver loading
i40e: Fix addition of RX filters after enabling FW LLDP agent
i40e: Fix add TC filter for IPv6
Mathias Kresin (1):
phy: lantiq: rcu-usb2: wait after clock enable
Matthias Brugger (1):
arm64: dts: mt8183: Fix GCE include path
Matthieu Baerts (1):
selftests: mptcp: fix ACKRX debug message
Matti Vaittinen (1):
regulator: bd718x7, bd71828, Fix dvs voltage levels
Max Gurtovoy (1):
vfio-pci/zdev: fix possible segmentation fault issue
Maxim Kiselev (1):
gpio: pcf857x: Fix missing first interrupt
Maxim Mikityanskiy (5):
net/mlx5e: Don't change interrupt moderation params when DIM is enabled
net/mlx5e: Change interrupt moderation channel params also when channels are closed
net/mlx5e: Replace synchronize_rcu with synchronize_net
net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
net/mlx5e: Fix CQ params of ICOSQ and async ICOSQ
Maxime Chevallier (1):
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Maxime Ripard (4):
drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Maximilian Luz (1):
ACPICA: Fix exception code class checks
Md Haris Iqbal (1):
RDMA/rtrs: Only allow addition of path to an already established session
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
Michael Tretter (2):
clk: divider: fix initialization with parent_hw
Input: st1232 - add IDLE state as ready condition
Michal Suchanek (1):
powerpc: Fix build error in paravirt.h
Mike Kravetz (2):
hugetlb: fix update_and_free_page contig page struct assumption
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mikulas Patocka (5):
blk-settings: align max_sectors on "logical_block_size" boundary
dm: fix deadlock when swapping to encrypted device
dm writecache: fix performance degradation in ssd mode
dm writecache: return the exact table values that were set
dm writecache: fix writing beyond end of underlying device when shrinking
Ming Lei (1):
block: fix logging on capacity change
Misono Tomohiro (1):
x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Moshe Shemesh (1):
net/mlx5e: Check tunnel offload is required before setting SWP
Muchun Song (5):
mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
mm: memcontrol: fix slub memory accounting
mm: memcontrol: fix swap undercounting in cgroup2
mm: memcontrol: fix get_active_memcg return value
printk: fix deadlock when kernel panic
Mårten Lindahl (1):
i2c: exynos5: Preserve high speed master code
Namhyung Kim (1):
perf test: Fix unaligned access in sample parsing test
Namjae Jeon (1):
exfat: fix shift-out-of-bounds in exfat_fill_super()
Nathan Chancellor (6):
vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
MIPS: Compare __SYNC_loongson3_war against 0
dmaengine: qcom: Always inline gpi_update_reg
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
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
Nicholas Fraser (1):
perf symbols: Fix return value when loading PE DSO
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
Nicolas Saenz Julienne (1):
spi: Skip zero-length transfers in spi_transfer_one_message()
Nikos Tsironis (7):
dm era: Recover committed writeset after crash
dm era: Update in-core bitset after committing the metadata
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
Nirmoy Das (1):
drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Norbert Ciosek (1):
i40e: Fix endianness conversions
Olivier Crête (1):
Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
Oz Shlomo (1):
net/mlx5e: CT: manage the lifetime of the ct entry object
Pali Rohár (1):
net: sfp: add workaround for Realtek RTL8672 and RTL9601C chips
Pan Bian (11):
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
bsg: free the request before return error code
regulator: axp20x: Fix reference cout leak
regulator: s5m8767: Fix reference count leak
spi: atmel: Put allocated master before return
isofs: release buffer head before return
PCI: xilinx-cpm: Fix reference count leak on error path
mtd: spi-nor: hisi-sfc: Put child node np on error path
fs/affs: release old buffer head on error path
Paolo Bonzini (1):
KVM: nSVM: fix running nested guests when npt=0
Parav Pandit (4):
net/mlx5e: E-switch, Fix rate calculation for overflow
IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
IB/mlx5: Return appropriate error code instead of ENOMEM
IB/cm: Avoid a loop when device has 255 ports
Paul Cercueil (4):
usb: musb: Fix runtime PM race in musb_queue_resume_work
MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
seccomp: Add missing return in non-void function
perf stat: Use nftw() instead of ftw()
Paulo Alcantara (4):
cifs: fix DFS failover
cifs: check all path components in resolved dfs target
cifs: introduce helper for finding referral server to improve DFS target resolution
cifs: fix nodfs mount option
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 Geis (1):
ARM: tegra: ouya: Fix eMMC on specific bootloaders
Peter Zijlstra (1):
locking/lockdep: Avoid unmatched unlock
Phil Elwell (2):
staging: vchiq: Fix bulk userdata handling
staging: vchiq: Fix bulk transfers on 64-bit builds
Pierre-Louis Bossart (8):
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A32
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
soundwire: cadence: fix ACK/NAK handling
soundwire: bus: use sdw_update_no_pm when initializing a device
soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
soundwire: bus: fix confusion on device used by pm_runtime
Pingfan Liu (1):
powerpc/time: Enable sched clock for irqtime
Po-Hsu Lin (1):
selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Pratyush Yadav (1):
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Prike Liang (1):
drm/amdgpu: fix shutdown and poweroff process failed with s0ix
Qais Yousef (1):
sched/eas: Don't update misfit status if the task is pinned
Qinglang Miao (4):
drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
drm/lima: fix reference leak in lima_pm_busy
ACPI: configfs: add missing check after configfs_register_default_group()
Qu Wenruo (1):
btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Quinn Tran (1):
scsi: qla2xxx: Fix mailbox Ch erroneous error
Raed Salem (2):
net/mlx5e: Enable XDP for Connect-X IPsec capable devices
net/mlx5e: Enable striding RQ for Connect-X IPsec capable devices
Rafael J. Wysocki (3):
ACPI: property: Fix fwnode string properties matching
cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Rafał Miłecki (1):
arm64: dts: broadcom: bcm4908: use proper NAND binding
Rakesh Pillai (1):
ath10k: Fix error handling in case of CE pipe init failure
Randy Dunlap (7):
fbdev: aty: SPARC64 requires FB_ATY_CT
HID: core: detect and skip invalid inputs to snto32()
power: supply: fix sbs-charger build, needs REGMAP_I2C
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
sparc: fix led.c driver when PROC_FS is not enabled
ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Ranjani Sridharan (1):
ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Rasmus Villemoes (1):
spi: fsl: invert spisel_boot signal on MPC8309
Rayagonda Kokatanur (3):
i2c: iproc: handle only slave interrupts which are enabled
i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
i2c: iproc: handle master read request
Ricky Wu (1):
misc: rtsx: init of rts522a add OCP power off when no card is present
Rik van Riel (1):
mm,thp,shmem: make khugepaged obey tmpfs mount flags
Rob Clark (1):
drm/msm: Fix legacy relocs path
Robert Foss (1):
arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Robert Hancock (1):
net: axienet: Handle deferred probe on clock properly
Robin Murphy (2):
perf/arm-cmn: Fix PMU instance naming
perf/arm-cmn: Move IRQs when migrating context
Rodrigo Siqueira (1):
drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Roja Rani Yarubandi (1):
i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Rokudo Yan (1):
zsmalloc: account the number of compacted pages correctly
Ronnie Sahlberg (1):
cifs: fix handling of escaped ',' in the password mount argument
Rosen Penev (2):
ARM: dts: armada388-helios4: assign pinctrl to LEDs
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rui Miguel Silva (1):
media: imx7: csi: Fix pad link validation
Russell King (1):
PCI: pci-bridge-emul: Fix array overruns, improve safety
Ryan Chen (1):
clk: aspeed: Fix APLL calculate formula from ast2600-A2
Sabyrzhan Tasbolatov (1):
drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Sagi Grimberg (2):
nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
nvmet-tcp: fix potential race of tcp socket closing accept_work
Sai Prakash Ranjan (2):
drm/msm: Add proper checks for GPU LLCC support
watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Sakari Ailus (1):
media: v4l: ioctl: Fix memory leak in video_usercopy
Sameer Pujar (1):
ASoC: simple-card-utils: Fix device module clock
Sami Tolvanen (1):
x86/sgx: Fix the return type of sgx_init()
Samuel Holland (1):
power: supply: axp20x_usb_power: Init work before enabling IRQs
Sandipan Das (2):
powerpc/sstep: Fix load-store and update emulation
powerpc/sstep: Fix darn emulation
Sara Sharon (1):
iwlwifi: mvm: don't check if CSA event is running before removing
Sathyanarayana Nujella (1):
ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Sean Christopherson (6):
KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
x86/virt: Eat faults on VMXOFF in reboot flows
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Young (2):
media: ir_toy: add another IR Droid device
media: smipcie: fix interrupt handling and IR timeout
Sebastian Andrzej Siewior (1):
smp: Process pending softirqs in flush_smp_call_function_from_idle()
Sebastian Reichel (1):
ASoC: cpcap: fix microphone timeslot mask
Shaoying Xu (1):
arm64 module: set plt* section addresses to 0x0
Shawn Guo (1):
cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Shay Drory (7):
net/mlx5: Fix health error state handling
net/mlx5: Disable devlink reload for multi port slave device
net/mlx5: Disallow RoCE on multi port slave device
net/mlx5: Disallow RoCE on lag device
net/mlx5: Disable devlink reload for lag devices
IB/umad: Return EIO in case of when device disassociated
IB/umad: Return EPOLLERR in case of when device disassociated
Shin'ichiro Kawasaki (1):
zonefs: Fix file size of zones in full condition
Shirley Her (1):
mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Shiyang Ruan (1):
device-dax: Fix default return code of range_parse()
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 Ser (2):
drm: document that user-space should force-probe connectors
drm/fourcc: fix Amlogic format modifier masks
Simon South (3):
pwm: rockchip: Enable APB clock during register access while probing
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
pwm: rockchip: Eliminate potential race condition when probing
Slawomir Laba (1):
i40e: Fix flow for IPv6 next header (extension header)
Song, Yoong Siang (1):
net: stmmac: fix CBS idleslope and sendslope calculation
Srinivas Kandagatla (2):
ASoC: codecs: add missing max_register in regmap config
clk: qcom: gfm-mux: fix clk mask
Srinivasa Rao Mandadapu (2):
ASoC: qcom: lpass-cpu: Remove bit clock state check
ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Stefano Garzarella (1):
vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Stephan Gerhold (3):
arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Stephen Boyd (2):
drm/msm/kms: Make a lock_class_key for each crtc mutex
drm/msm/dp: Add a missing semi-colon
Steven Rostedt (VMware) (1):
tracepoint: Do not fail unregistering a probe due to memory failure
Subbaraman Narayanamurthy (2):
nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
spmi: spmi-pmic-arb: Fix hw_irq overflow
Sukadev Bhattiprolu (2):
ibmvnic: Set to CLOSED state even on error
ibmvnic: serialize access to work queue on remove
Sumit Garg (2):
kdb: Make memory allocations more robust
kgdb: fix to kill breakpoints on initmem after boot
Suzuki K Poulose (3):
coresight: etm4x: Skip accessing TRCPDCR in save/restore
arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
coresight: etm4x: Handle accesses to TRCSTALLCTLR
Sylwester Dziedziuch (1):
i40e: Fix VFs not created
Taehee Yoo (1):
vxlan: move debug check after netdev unregister
Takahiro Kuwano (4):
mtd: spi-nor: sfdp: Fix last erase region marking
mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
mtd: spi-nor: core: Fix erase type discovery for overlaid region
mtd: spi-nor: core: Add erase size check for erase command initialization
Takashi Iwai (12):
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
ALSA: pcm: Call sync_stop at disconnection
ALSA: pcm: Assure sync with the pending stop operation at suspend
ALSA: pcm: Don't call sync_stop if it hasn't been stopped
ALSA: usb-audio: Correct document for snd_usb_endpoint_free_all()
ALSA: usb-audio: Handle invalid running state at releasing EP
ALSA: usb-audio: More strict state change in EP
ALSA: usb-audio: Don't avoid stopping the stream at disconnection
ALSA: usb-audio: Add implicit fb quirk for BOSS GP-10
ALSA: hda/hdmi: Drop bogus check at closing a stream
ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
ASoC: siu: Fix build error by a wrong const prefix
Takashi Sakamoto (1):
ALSA: fireface: fix to parse sync status register of latter protocol
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
Taniya Das (1):
clk: qcom: gcc-sc7180: Mark the MM XO clocks to be always ON
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
Thomas Gleixner (1):
x86/entry: Fix instrumentation annotation
Tim Harvey (1):
mfd: gateworks-gsc: Fix interrupt type
Timothy E Baldwin (1):
arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Tobias Klauser (1):
riscv: Disable KSAN_SANITIZE for vDSO
Tom Rix (4):
media: mtk-vcodec: fix argument used when DEBUG is defined
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
Tom Zanussi (1):
selftests/ftrace: Update synthetic event syntax errors
Tomas Winkler (1):
mei: me: emmitsburg workstation DID
Tomi Valkeinen (2):
media: ti-vpe: cal: fix write to unallocated memory
media: i2c: max9286: fix access to unallocated memory
Tony Lindgren (4):
ARM: dts: Configure missing thermal interrupt for 4430
power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
power: supply: cpcap-charger: Fix missing power_supply_put()
power: supply: cpcap-battery: Fix missing power_supply_put()
Trond Myklebust (1):
NFSv4: Fixes for nfs4_bitmask_adjust()
Tzung-Bi Shih (1):
remoteproc/mediatek: acknowledge watchdog IRQ after handled
Uwe Kleine-König (2):
amba: Fix resource leak for drivers without .remove
pwm: iqs620a: Fix overflow and optimize calculations
Vasundhara Volam (1):
bnxt_en: Fix devlink info's stored fw.psid version format.
Venkata Lakshmi Narayana Gubba (3):
Bluetooth: hci_qca: Wait for SSR completion during suspend
Bluetooth: hci_qca: check for SSR triggered flag while suspend
Bluetooth: hci_qca: Fixed issue during suspend
Vignesh Raghavendra (1):
dmaengine: ti: k3-udma: Set rflow count for BCDMA split channels
Ville Syrjälä (2):
drm/modes: Switch to 64bit maths to avoid integer overflow
drm/i915: Reject 446-480MHz HDMI clock on GLK
Vincent Knecht (1):
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Viresh Kumar (2):
mailbox: arm_mhuv2: Skip calling kfree() with invalid pointer
thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Vlad Buslov (1):
net: sched: fix police ext initialization
Vladimir Murzin (1):
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Vladimir Oltean (3):
net: dsa: felix: perform teardown in reverse order of setup
net: dsa: felix: don't deinitialize unused ports
net: enetc: fix destroyed phylink dereference during unbind
Vlastimil Babka (1):
mm, compaction: make fast_isolate_freepages() stay within zone
Wang ShaoBo (1):
ubifs: Fix error return code in alloc_wbufs()
Wang Xiaojun (1):
drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Weihang Li (2):
RDMA/hns: Avoid filling sgid index when modifying QP to RTR
RDMA/hns: Fix type of sq_signal_bits
Wenpeng Liang (4):
RDMA/hns: Bugfix for checking whether the srq is full when post wr
RDMA/hns: Force srq_limit to 0 when creating SRQ
RDMA/hns: Fixed wrong judgments in the goto branch
RDMA/hns: Remove the reserved WQE of SRQ
Will Deacon (2):
mm: proc: Invalidate TLB after clearing soft-dirty page state
arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Wonhyuk Yang (1):
mm/compaction: fix misbehaviors of fast_find_migrateblock()
Xi Wang (1):
RDMA/hns: Add mapped page count checking for MTR
Xuewen Yan (1):
sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Yang Jihong (1):
perf record: Fix continue profiling after draining the buffer
Yi Chen (1):
f2fs: fix to avoid inconsistent quota data
Yishai Hadas (1):
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Yong Wu (2):
iommu: Switch gather->end to the inclusive end
iommu: Move iotlb_sync_map out from __iommu_map
Yonghong Song (1):
bpf: Fix an unitialized value in bpf_iter
Yongqiang Niu (3):
arm64: dts: mt8183: rename rdma fifo size
arm64: dts: mt8183: refine gamma compatible name
drm/mediatek: Check if fb is null
Yoshihiro Shimoda (1):
mfd: bd9571mwv: Use devm_mfd_add_devices()
YueHaibing (1):
cifs: Fix inconsistent IS_ERR and PTR_ERR
Zhang Changzhong (2):
media: mtk-vcodec: fix error return code in vdec_vp9_decode()
media: aspeed: fix error return code in aspeed_video_setup_video()
Zhang Qilong (2):
memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
HSI: Fix PM usage counter unbalance in ssi_hw_init
Zhenzhong Duan (1):
csky: Fix a size determination in gpr_get()
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
qiuguorui1 (1):
arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
xinhui pan (1):
drm/ttm: Fix a memory leak
yangerkun (1):
mtd: phram: use div_u64_rem to stop overwrite len in phram_setup
^ permalink raw reply [relevance 1%]
* Linux 5.10.20
@ 2021-03-04 11:01 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-04 11:01 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.10.20 kernel.
All users of the 5.10 kernel series must upgrade.
The updated 5.10.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.10.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/admin-guide/perf/arm-cmn.rst | 2
Documentation/admin-guide/sysctl/vm.rst | 10
Documentation/filesystems/seq_file.rst | 6
Documentation/scsi/libsas.rst | 1
Documentation/security/keys/core.rst | 4
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/aspeed-g6.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/arm/kernel/sys_oabi-compat.c | 15
arch/arm/mach-at91/pm_suspend.S | 2
arch/arm/mach-ixp4xx/Kconfig | 1
arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9
arch/arm64/Kconfig | 2
arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 5
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7
arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7
arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi | 2
arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4
arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts | 2
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2
arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi | 6
arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 9
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4
arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2
arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1
arch/arm64/crypto/aes-glue.c | 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/include/asm/module.lds.h | 6
arch/arm64/kernel/cpufeature.c | 2
arch/arm64/kernel/head.S | 1
arch/arm64/kernel/machine_kexec_file.c | 4
arch/arm64/kernel/probes/uprobes.c | 2
arch/arm64/kernel/ptrace.c | 2
arch/arm64/kernel/suspend.c | 2
arch/csky/kernel/ptrace.c | 2
arch/mips/Makefile | 19
arch/mips/cavium-octeon/setup.c | 9
arch/mips/include/asm/asm.h | 18
arch/mips/include/asm/atomic.h | 2
arch/mips/include/asm/cmpxchg.h | 6
arch/mips/kernel/cpu-probe.c | 15
arch/mips/kernel/vmlinux.lds.S | 2
arch/mips/lantiq/irq.c | 2
arch/mips/loongson64/Platform | 22
arch/mips/mm/c-r4k.c | 2
arch/mips/vdso/Makefile | 5
arch/nios2/kernel/entry.S | 3
arch/nios2/kernel/sys_nios2.c | 11
arch/powerpc/Kconfig | 2
arch/powerpc/include/asm/kexec.h | 1
arch/powerpc/include/asm/uaccess.h | 13
arch/powerpc/kernel/entry_32.S | 3
arch/powerpc/kernel/head_32.h | 2
arch/powerpc/kernel/head_8xx.S | 2
arch/powerpc/kernel/head_book3s_32.S | 6
arch/powerpc/kernel/irq.c | 27
arch/powerpc/kernel/prom_init.c | 12
arch/powerpc/kernel/time.c | 2
arch/powerpc/kexec/elf_64.c | 2
arch/powerpc/kexec/file_load_64.c | 35
arch/powerpc/kvm/powerpc.c | 8
arch/powerpc/platforms/pseries/dlpar.c | 7
arch/riscv/kernel/vdso/Makefile | 3
arch/s390/kernel/vtime.c | 3
arch/sparc/Kconfig | 2
arch/sparc/kernel/led.c | 2
arch/sparc/lib/memset.S | 1
arch/um/include/shared/skas/mm_id.h | 1
arch/um/kernel/tlb.c | 19
arch/um/os-Linux/skas/process.c | 4
arch/x86/crypto/aesni-intel_glue.c | 28
arch/x86/entry/common.c | 2
arch/x86/include/asm/virtext.h | 17
arch/x86/kernel/msr.c | 7
arch/x86/kernel/reboot.c | 30
arch/x86/kvm/emulate.c | 4
arch/x86/kvm/mmu/tdp_mmu.c | 3
arch/x86/kvm/svm/nested.c | 22
arch/x86/kvm/svm/svm.c | 8
arch/x86/mm/fault.c | 27
arch/x86/mm/pat/memtype.c | 4
block/bfq-iosched.c | 1
block/blk-settings.c | 12
block/bsg.c | 4
block/ioctl.c | 21
certs/blacklist.c | 2
crypto/ecdh_helper.c | 3
crypto/michael_mic.c | 31
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/base/swnode.c | 8
drivers/block/floppy.c | 30
drivers/bluetooth/btqcomsmd.c | 27
drivers/bluetooth/btusb.c | 20
drivers/bluetooth/hci_ldisc.c | 41
drivers/bluetooth/hci_qca.c | 2
drivers/bluetooth/hci_serdev.c | 4
drivers/char/hw_random/ingenic-trng.c | 6
drivers/char/hw_random/timeriomem-rng.c | 2
drivers/char/random.c | 2
drivers/char/tpm/tpm.h | 4
drivers/char/tpm/tpm_tis_core.c | 50
drivers/clk/clk-ast2600.c | 37
drivers/clk/clk-divider.c | 9
drivers/clk/meson/clk-pll.c | 10
drivers/clk/qcom/gcc-msm8998.c | 100 -
drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10
drivers/clocksource/Kconfig | 1
drivers/clocksource/mxs_timer.c | 5
drivers/cpufreq/acpi-cpufreq.c | 62
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24
drivers/cpufreq/freq_table.c | 8
drivers/cpufreq/intel_pstate.c | 21
drivers/cpufreq/qcom-cpufreq-hw.c | 40
drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 +-
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2
drivers/crypto/bcm/cipher.c | 2
drivers/crypto/bcm/cipher.h | 4
drivers/crypto/bcm/util.c | 2
drivers/crypto/talitos.c | 50
drivers/crypto/talitos.h | 1
drivers/dax/bus.c | 2
drivers/dma/fsldma.c | 6
drivers/dma/hsu/pci.c | 21
drivers/dma/idxd/dma.c | 1
drivers/dma/owl-dma.c | 1
drivers/firmware/arm_scmi/driver.c | 4
drivers/gpio/gpio-pcf857x.c | 2
drivers/gpu/drm/Kconfig | 3
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2
drivers/gpu/drm/amd/amdgpu/soc15.c | 2
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2
drivers/gpu/drm/amd/display/dc/bios/command_table.c | 61
drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 1
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2
drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6
drivers/gpu/drm/drm_dp_mst_topology.c | 3
drivers/gpu/drm/drm_fb_helper.c | 15
drivers/gpu/drm/drm_modes.c | 4
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22
drivers/gpu/drm/gma500/psb_drv.c | 2
drivers/gpu/drm/i915/display/intel_hdmi.c | 6
drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12
drivers/gpu/drm/lima/lima_sched.c | 2
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 8
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2
drivers/gpu/drm/msm/dp/dp_display.c | 5
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2
drivers/gpu/drm/msm/msm_drv.c | 3
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h | 1
drivers/gpu/drm/nouveau/nouveau_chan.c | 1
drivers/gpu/drm/nouveau/nouveau_connector.c | 1
drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5
drivers/gpu/drm/rcar-du/rcar_cmm.c | 2
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11
drivers/gpu/drm/scheduler/sched_main.c | 3
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1
drivers/gpu/drm/tegra/dc.c | 2
drivers/gpu/drm/tegra/dsi.c | 2
drivers/gpu/drm/tegra/hdmi.c | 2
drivers/gpu/drm/tegra/hub.c | 2
drivers/gpu/drm/tegra/sor.c | 2
drivers/gpu/drm/tegra/vic.c | 2
drivers/gpu/drm/vc4/vc4_hdmi.c | 87 -
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4
drivers/gpu/drm/virtio/virtgpu_gem.c | 8
drivers/hid/hid-core.c | 3
drivers/hid/hid-logitech-dj.c | 1
drivers/hid/wacom_wac.c | 7
drivers/hsi/controllers/omap_ssi_core.c | 2
drivers/hv/channel_mgmt.c | 3
drivers/hwtracing/coresight/coresight-etm4x-core.c | 21
drivers/hwtracing/coresight/coresight-etm4x-sysfs.c | 2
drivers/i2c/busses/i2c-bcm-iproc.c | 231 ++-
drivers/i2c/busses/i2c-brcmstb.c | 2
drivers/i2c/busses/i2c-exynos5.c | 8
drivers/i2c/busses/i2c-qcom-geni.c | 59
drivers/ide/falconide.c | 3
drivers/infiniband/core/cm.c | 8
drivers/infiniband/core/cma.c | 70
drivers/infiniband/core/user_mad.c | 17
drivers/infiniband/hw/hns/hns_roce_device.h | 2
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 8
drivers/infiniband/hw/hns/hns_roce_main.c | 3
drivers/infiniband/hw/mlx5/devx.c | 4
drivers/infiniband/hw/mlx5/main.c | 14
drivers/infiniband/sw/rxe/rxe_net.c | 5
drivers/infiniband/sw/rxe/rxe_recv.c | 27
drivers/infiniband/sw/siw/siw.h | 2
drivers/infiniband/sw/siw/siw_main.c | 2
drivers/infiniband/sw/siw/siw_qp.c | 271 +--
drivers/infiniband/sw/siw/siw_qp_rx.c | 26
drivers/infiniband/sw/siw/siw_qp_tx.c | 4
drivers/infiniband/sw/siw/siw_verbs.c | 20
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51
drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1
drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 117 -
drivers/infiniband/ulp/rtrs/rtrs.c | 14
drivers/input/joydev.c | 7
drivers/input/joystick/xpad.c | 1
drivers/input/serio/i8042-x86ia64io.h | 4
drivers/input/serio/serport.c | 4
drivers/input/touchscreen/elo.c | 4
drivers/input/touchscreen/raydium_i2c_ts.c | 3
drivers/input/touchscreen/sur40.c | 1
drivers/input/touchscreen/zinitix.c | 2
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2
drivers/iommu/iommu.c | 23
drivers/iommu/mtk_iommu.c | 2
drivers/irqchip/Kconfig | 3
drivers/irqchip/irq-loongson-pch-msi.c | 2
drivers/macintosh/adb-iop.c | 6
drivers/mailbox/sprd-mailbox.c | 2
drivers/md/bcache/bcache.h | 3
drivers/md/bcache/btree.c | 21
drivers/md/bcache/journal.c | 4
drivers/md/bcache/super.c | 20
drivers/md/dm-core.h | 4
drivers/md/dm-crypt.c | 1
drivers/md/dm-era-target.c | 93 -
drivers/md/dm-table.c | 168 --
drivers/md/dm-writecache.c | 74
drivers/md/dm.c | 62
drivers/md/dm.h | 2
drivers/media/i2c/max9286.c | 2
drivers/media/i2c/ov5670.c | 3
drivers/media/pci/cx25821/cx25821-core.c | 4
drivers/media/pci/intel/ipu3/Kconfig | 3
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2
drivers/media/pci/saa7134/saa7134-empress.c | 5
drivers/media/pci/smipcie/smipcie-ir.c | 46
drivers/media/platform/aspeed-video.c | 6
drivers/media/platform/marvell-ccic/mcam-core.c | 2
drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4
drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3
drivers/media/platform/pxa_camera.c | 3
drivers/media/platform/qcom/camss/camss-video.c | 1
drivers/media/platform/ti-vpe/cal.c | 4
drivers/media/platform/vsp1/vsp1_drv.c | 4
drivers/media/rc/ir_toy.c | 1
drivers/media/rc/mceusb.c | 2
drivers/media/test-drivers/vidtv/vidtv_psi.c | 5
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/mtk-smi.c | 4
drivers/memory/ti-aemif.c | 8
drivers/mfd/altera-sysmgr.c | 3
drivers/mfd/bd9571mwv.c | 6
drivers/mfd/gateworks-gsc.c | 2
drivers/mfd/wm831x-auxadc.c | 3
drivers/misc/cardreader/rts5227.c | 5
drivers/misc/eeprom/eeprom_93xx46.c | 1
drivers/misc/fastrpc.c | 7
drivers/misc/mei/hbm.c | 2
drivers/misc/mei/hw-me-regs.h | 5
drivers/misc/mei/interrupt.c | 33
drivers/misc/mei/pci-me.c | 5
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5
drivers/mmc/host/owl-mmc.c | 9
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4
drivers/mmc/host/sdhci-esdhc-imx.c | 3
drivers/mmc/host/sdhci-pci-o2micro.c | 20
drivers/mmc/host/sdhci-sprd.c | 6
drivers/mmc/host/usdhi6rol0.c | 4
drivers/mtd/parsers/afs.c | 4
drivers/mtd/parsers/parser_imagetag.c | 4
drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4
drivers/mtd/spi-nor/core.c | 10
drivers/mtd/spi-nor/sfdp.c | 5
drivers/net/Kconfig | 2
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2
drivers/net/dsa/ocelot/felix.c | 16
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
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h | 3
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5
drivers/net/ethernet/ibm/ibmvnic.c | 16
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16
drivers/net/ethernet/intel/i40e/i40e_main.c | 50
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9
drivers/net/ethernet/intel/ice/ice.h | 2
drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6
drivers/net/ethernet/intel/ice/ice_ethtool.c | 34
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33
drivers/net/ethernet/marvell/mvneta.c | 9
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 1
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 ++-
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h | 2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8
drivers/net/ethernet/mellanox/mlx5/core/health.c | 22
drivers/net/ethernet/mellanox/mlx5/core/main.c | 3
drivers/net/ethernet/realtek/r8169_main.c | 4
drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26
drivers/net/gtp.c | 1
drivers/net/phy/mscc/mscc.h | 8
drivers/net/phy/mscc/mscc_main.c | 350 +++-
drivers/net/phy/phy_device.c | 53
drivers/net/ppp/ppp_async.c | 3
drivers/net/ppp/ppp_synctty.c | 3
drivers/net/vxlan.c | 11
drivers/net/wireguard/device.c | 19
drivers/net/wireguard/device.h | 15
drivers/net/wireguard/peer.c | 28
drivers/net/wireguard/peer.h | 4
drivers/net/wireguard/queueing.c | 86 -
drivers/net/wireguard/queueing.h | 45
drivers/net/wireguard/receive.c | 16
drivers/net/wireguard/send.c | 31
drivers/net/wireless/ath/ath10k/mac.c | 2
drivers/net/wireless/ath/ath10k/snoc.c | 5
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3
drivers/net/wireless/ath/ath11k/mac.c | 11
drivers/net/wireless/ath/ath9k/debug.c | 5
drivers/net/wireless/broadcom/b43/phy_n.c | 2
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43
drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 3
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21
drivers/net/xen-netback/interface.c | 8
drivers/nvme/host/multipath.c | 4
drivers/nvme/target/admin-cmd.c | 33
drivers/nvme/target/tcp.c | 59
drivers/nvmem/core.c | 5
drivers/nvmem/qcom-spmi-sdam.c | 7
drivers/of/fdt.c | 12
drivers/opp/of.c | 4
drivers/pci/controller/cadence/pcie-cadence-host.c | 5
drivers/pci/controller/dwc/pcie-qcom.c | 4
drivers/pci/controller/pcie-rcar-host.c | 2
drivers/pci/controller/pcie-rockchip.c | 12
drivers/pci/controller/pcie-xilinx-cpm.c | 1
drivers/pci/pci-bridge-emul.c | 11
drivers/pci/setup-res.c | 6
drivers/pci/syscall.c | 10
drivers/perf/arm-cmn.c | 17
drivers/phy/Kconfig | 1
drivers/phy/cadence/phy-cadence-torrent.c | 1
drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10
drivers/phy/rockchip/phy-rockchip-emmc.c | 8
drivers/platform/chrome/cros_ec_proto.c | 12
drivers/power/reset/at91-sama5d2_shdwc.c | 2
drivers/power/supply/Kconfig | 1
drivers/power/supply/axp20x_usb_power.c | 2
drivers/power/supply/cpcap-battery.c | 12
drivers/power/supply/cpcap-charger.c | 4
drivers/power/supply/smb347-charger.c | 12
drivers/pwm/pwm-iqs620a.c | 8
drivers/pwm/pwm-rockchip.c | 18
drivers/regulator/axp20x-regulator.c | 7
drivers/regulator/core.c | 6
drivers/regulator/qcom-rpmh-regulator.c | 26
drivers/regulator/rohm-regulator.c | 9
drivers/regulator/s5m8767.c | 15
drivers/remoteproc/mtk_common.h | 1
drivers/remoteproc/mtk_scp.c | 20
drivers/rtc/Kconfig | 3
drivers/s390/crypto/zcrypt_api.c | 14
drivers/s390/virtio/virtio_ccw.c | 4
drivers/scsi/bnx2fc/Kconfig | 1
drivers/scsi/lpfc/lpfc_hbadisc.c | 15
drivers/scsi/qla2xxx/qla_dbg.c | 1
drivers/scsi/qla2xxx/qla_mbx.c | 3
drivers/scsi/sd.c | 6
drivers/scsi/sd_zbc.c | 6
drivers/soc/aspeed/aspeed-lpc-snoop.c | 30
drivers/soc/qcom/ocmem.c | 8
drivers/soc/qcom/socinfo.c | 2
drivers/soc/samsung/exynos-asv.c | 18
drivers/soc/ti/pm33xx.c | 5
drivers/soundwire/bus.c | 47
drivers/soundwire/cadence_master.c | 8
drivers/soundwire/intel_init.c | 3
drivers/spi/spi-atmel.c | 2
drivers/spi/spi-cadence-quadspi.c | 2
drivers/spi/spi-dw-bt1.c | 2
drivers/spi/spi-fsl-spi.c | 2
drivers/spi/spi-imx.c | 2
drivers/spi/spi-pxa2xx-pci.c | 27
drivers/spi/spi-stm32.c | 4
drivers/spi/spi-synquacer.c | 4
drivers/spi/spi.c | 2
drivers/spmi/spmi-pmic-arb.c | 5
drivers/staging/gdm724x/gdm_usb.c | 10
drivers/staging/media/allegro-dvt/allegro-core.c | 3
drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24
drivers/staging/media/atomisp/pci/hmm/hmm.c | 2
drivers/staging/media/imx/imx-media-csc-scaler.c | 4
drivers/staging/media/imx/imx-media-dev.c | 7
drivers/staging/media/imx/imx7-media-csi.c | 27
drivers/staging/mt7621-dma/Makefile | 2
drivers/staging/mt7621-dma/hsdma-mt7621.c | 760 ++++++++++
drivers/staging/mt7621-dma/mtk-hsdma.c | 760 ----------
drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1
drivers/staging/rtl8723bs/os_dep/wifi_regd.c | 2
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 6
drivers/staging/wfx/data_tx.c | 10
drivers/staging/wfx/data_tx.h | 1
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3
drivers/tee/optee/rpc.c | 31
drivers/thermal/cpufreq_cooling.c | 2
drivers/tty/n_gsm.c | 3
drivers/tty/n_hdlc.c | 60
drivers/tty/n_null.c | 3
drivers/tty/n_r3964.c | 10
drivers/tty/n_tracerouter.c | 4
drivers/tty/n_tracesink.c | 4
drivers/tty/n_tty.c | 82 -
drivers/tty/tty_io.c | 82 -
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/usb/serial/pl2303.c | 8
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2
drivers/vfio/pci/vfio_pci_zdev.c | 4
drivers/vfio/vfio_iommu_type1.c | 63
drivers/video/fbdev/Kconfig | 2
drivers/virt/vboxguest/vboxguest_utils.c | 18
drivers/w1/slaves/w1_therm.c | 22
drivers/watchdog/intel-mid_wdt.c | 8
drivers/watchdog/mei_wdt.c | 1
drivers/watchdog/qcom-wdt.c | 13
fs/affs/namei.c | 4
fs/btrfs/backref.c | 9
fs/btrfs/backref.h | 9
fs/btrfs/block-group.c | 29
fs/btrfs/ctree.c | 7
fs/btrfs/delayed-ref.c | 56
fs/btrfs/delayed-ref.h | 16
fs/btrfs/extent-tree.c | 128 -
fs/btrfs/free-space-cache.c | 6
fs/btrfs/inode.c | 3
fs/btrfs/relocation.c | 4
fs/btrfs/space-info.h | 17
fs/ceph/caps.c | 10
fs/debugfs/inode.c | 5
fs/erofs/xattr.c | 10
fs/erofs/zmap.c | 10
fs/eventpoll.c | 4
fs/exfat/exfat_raw.h | 4
fs/exfat/super.c | 31
fs/ext4/Kconfig | 3
fs/ext4/namei.c | 7
fs/f2fs/compress.c | 5
fs/f2fs/data.c | 12
fs/f2fs/f2fs.h | 2
fs/f2fs/file.c | 24
fs/f2fs/inline.c | 4
fs/f2fs/super.c | 3
fs/gfs2/bmap.c | 6
fs/gfs2/lock_dlm.c | 8
fs/gfs2/recovery.c | 4
fs/gfs2/util.c | 16
fs/io_uring.c | 17
fs/isofs/dir.c | 1
fs/isofs/namei.c | 1
fs/jffs2/summary.c | 3
fs/jfs/jfs_dmap.c | 2
fs/nfs/nfs4proc.c | 15
fs/nfsd/nfsctl.c | 14
fs/ocfs2/cluster/heartbeat.c | 8
fs/proc/proc_sysctl.c | 4
fs/proc/self.c | 2
fs/proc/task_mmu.c | 9
fs/proc/thread_self.c | 7
fs/pstore/platform.c | 4
fs/quota/quota_v2.c | 11
fs/ubifs/auth.c | 2
fs/ubifs/replay.c | 4
fs/ubifs/super.c | 4
fs/zonefs/super.c | 3
include/acpi/acexcep.h | 10
include/asm-generic/vmlinux.lds.h | 16
include/linux/bpf.h | 3
include/linux/device-mapper.h | 5
include/linux/eventpoll.h | 2
include/linux/filter.h | 2
include/linux/icmpv6.h | 28
include/linux/iommu.h | 4
include/linux/ipv6.h | 1
include/linux/kexec.h | 5
include/linux/key.h | 1
include/linux/kgdb.h | 2
include/linux/khugepaged.h | 2
include/linux/memremap.h | 6
include/linux/mfd/rohm-generic.h | 14
include/linux/rcupdate.h | 2
include/linux/rmap.h | 3
include/linux/soundwire/sdw.h | 2
include/linux/tpm.h | 5
include/linux/tty_ldisc.h | 3
include/net/act_api.h | 6
include/net/icmp.h | 6
include/net/tcp.h | 9
include/uapi/drm/drm_fourcc.h | 4
init/Kconfig | 11
init/main.c | 1
kernel/Makefile | 2
kernel/bpf/bpf_iter.c | 2
kernel/bpf/bpf_lru_list.c | 7
kernel/bpf/devmap.c | 4
kernel/bpf/verifier.c | 3
kernel/debug/debug_core.c | 11
kernel/debug/kdb/kdb_private.h | 2
kernel/kcsan/core.c | 26
kernel/kexec_file.c | 5
kernel/kprobes.c | 31
kernel/locking/lockdep.c | 3
kernel/module.c | 21
kernel/printk/printk.c | 28
kernel/printk/printk_safe.c | 16
kernel/rcu/tree.c | 8
kernel/rcu/tree_plugin.h | 5
kernel/sched/fair.c | 45
kernel/sched/idle.c | 1
kernel/seccomp.c | 2
kernel/smp.c | 4
kernel/tracepoint.c | 80 -
mm/compaction.c | 43
mm/hugetlb.c | 14
mm/khugepaged.c | 22
mm/memcontrol.c | 30
mm/memory-failure.c | 6
mm/memory.c | 16
mm/memremap.c | 15
mm/slab_common.c | 4
mm/slub.c | 8
mm/vmscan.c | 9
net/bluetooth/a2mp.c | 3
net/bluetooth/hci_core.c | 6
net/core/filter.c | 13
net/ipv4/icmp.c | 5
net/ipv6/icmp.c | 18
net/ipv6/ip6_icmp.c | 12
net/mac80211/mesh_hwmp.c | 2
net/nfc/nci/uart.c | 3
net/qrtr/tun.c | 12
net/sched/act_api.c | 106 -
net/sched/cls_api.c | 12
net/sunrpc/xprtrdma/svc_rdma_transport.c | 6
samples/Kconfig | 2
samples/watch_queue/watch_test.c | 2
security/commoncap.c | 12
security/integrity/evm/evm_crypto.c | 7
security/integrity/ima/ima_kexec.c | 3
security/integrity/ima/ima_mok.c | 5
security/keys/Kconfig | 8
security/keys/key.c | 2
security/keys/trusted-keys/trusted_tpm1.c | 22
security/keys/trusted-keys/trusted_tpm2.c | 22
security/selinux/hooks.c | 4
sound/core/init.c | 4
sound/core/pcm.c | 4
sound/core/pcm_local.h | 1
sound/core/pcm_native.c | 27
sound/firewire/fireface/ff-protocol-latter.c | 118 +
sound/pci/hda/hda_intel.c | 2
sound/pci/hda/patch_hdmi.c | 1
sound/pci/hda/patch_realtek.c | 40
sound/soc/codecs/cpcap.c | 12
sound/soc/codecs/cs42l56.c | 3
sound/soc/codecs/rt5682-i2c.c | 3
sound/soc/codecs/wsa881x.c | 1
sound/soc/generic/simple-card-utils.c | 13
sound/soc/intel/boards/sof_sdw.c | 6
sound/soc/qcom/lpass-apq8016.c | 2
sound/soc/qcom/lpass-cpu.c | 30
sound/soc/qcom/lpass-lpaif-reg.h | 3
sound/soc/qcom/lpass.h | 1
sound/soc/qcom/qdsp6/q6asm-dai.c | 21
sound/soc/qcom/qdsp6/q6routing.c | 18
sound/soc/sh/siu.h | 2
sound/soc/sh/siu_pcm.c | 2
sound/soc/sof/debug.c | 2
sound/soc/sof/intel/hda-dsp.c | 4
sound/soc/sof/sof-pci-dev.c | 7
sound/usb/pcm.c | 2
tools/lib/bpf/libbpf.c | 22
tools/objtool/arch/x86/special.c | 2
tools/objtool/check.c | 15
tools/objtool/check.h | 11
tools/perf/builtin-record.c | 2
tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json | 2
tools/perf/tests/sample-parsing.c | 2
tools/perf/util/event.c | 2
tools/perf/util/evlist.c | 8
tools/perf/util/evlist.h | 4
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 41
tools/perf/util/intel-pt-decoder/intel-pt-decoder.h | 2
tools/perf/util/intel-pt.c | 29
tools/perf/util/symbol.c | 7
tools/testing/kunit/kunit_tool_test.py | 14
tools/testing/selftests/bpf/test_xdp_redirect.sh | 10
tools/testing/selftests/dmabuf-heaps/Makefile | 2
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic_event_syntax_errors.tc | 35
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2
tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2
tools/testing/selftests/seccomp/seccomp_bpf.c | 2
tools/testing/selftests/wireguard/netns.sh | 15
669 files changed, 6490 insertions(+), 3770 deletions(-)
Adam Ford (2):
arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adrian Hunter (3):
perf intel-pt: Fix missing CYC processing in PSB
perf intel-pt: Fix premature IPC
perf intel-pt: Fix IPC with CYC threshold
Ahmad Fatoum (1):
nvmem: core: skip child nodes not matching binding
Ahmed S. Darwish (1):
scsi: libsas: docs: Remove notify_ha_event()
Al Viro (1):
sparc32: fix a user-triggerable oops in clear_user()
Alain Volmat (1):
spi: stm32: properly handle 0 byte transfer
Alex Deucher (2):
Revert "drm/amd/display: Update NV1x SR latency values"
drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Alex Williamson (1):
vfio/type1: Use follow_pte()
Alexander Lobakin (2):
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
MIPS: properly stop .eh_frame generation
Alexander Usyskin (5):
mei: hbm: call mei_set_devstate() on hbm stop response
watchdog: mei_wdt: request stop on unregister
mei: fix transfer over dma with extended header
mei: me: add adler lake point S DID
mei: me: add adler lake point LP DID
Alexey Kardashevskiy (2):
powerpc/uaccess: Avoid might_fault() when user access is enabled
powerpc/kuap: Restore AMR after replaying soft interrupts
Alyssa Rosenzweig (1):
drm/rockchip: Require the YTR modifier for AFBC
Amey Narkhede (1):
staging: gdm724x: Fix DMA from stack
Amir Goldstein (1):
selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Anand K Mistry (2):
ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Andre Przywara (7):
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
arm64: dts: allwinner: H6: properly connect USB PHY to port 0
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
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()
Andreas Gruenbacher (2):
gfs2: Lock imbalance on error path in gfs2_recover_one
gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Oetken (1):
nios2: fixed broken sys_clone syscall
Andrey Grodzovsky (1):
drm/sched: Cancel and flush all outstanding jobs before finish.
Andrii Nakryiko (2):
bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
Andy Lutomirski (1):
x86/fault: Fix AMD erratum #91 errata fixup for user code
Andy Shevchenko (3):
media: ipu3-cio2: Build only for x86
watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
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 (5):
PCI: Decline to resize resources if boot config must be preserved
crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
crypto: arm64/sha - add missing module aliases
crypto: aesni - prevent misaligned buffers on the stack
crypto: michael_mic - fix broken misalignment handling
Arnaldo Carvalho de Melo (1):
perf tools: Fix DSO filtering when not finding a map for a sampled address
Arnd Bergmann (6):
ARM: s3c: fix fiq for clang IAS
optee: simplify i2c access
ARM: at91: use proper asm syntax in pm_suspend
ubifs: replay: Fix high stack usage, again
clocksource/drivers/ixp4xx: Select TIMER_OF when needed
mfd: altera-sysmgr: Fix physical address storing more
Artem Lapkin (1):
arm64: dts: meson: fix broken wifi node for Khadas VIM3L
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
Aurelien Jarno (1):
MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Avihai Horon (1):
RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Ayush Sawal (1):
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Bard Liao (2):
soundwire: export sdw_write/read_no_pm functions
regmap: sdw: use _no_pm functions in regmap_read/write
Bart Van Assche (1):
scsi: sd: Fix Opal support
Bartosz Golaszewski (1):
rtc: s5m: select REGMAP_I2C
Bernard Metzler (1):
RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Bjarni Jonasson (1):
net: phy: mscc: adding LCPLL reset to VSC8514
Björn Töpel (1):
selftests/bpf: Convert test_xdp_redirect.sh to bash
Bob Pearson (3):
RDMA/rxe: Fix coding error in rxe_recv.c
RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
RDMA/rxe: Correct skb on loopback path
Bob Peterson (2):
gfs2: fix glock confusion in function signal_our_withdraw
gfs2: Don't skip dlm unlock if glock has an lvb
Borislav Petkov (1):
staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Brett Creeley (1):
ice: Account for port VLAN in VF max packet size calculation
Chaitanya Kulkarni (2):
nvmet: remove extra variable in identify ns
nvmet: set status to 0 in case for invalid nsid
Chao Yu (3):
f2fs: compress: fix potential deadlock
f2fs: fix out-of-repair __setattr_copy()
f2fs: enforce the immutable flag on open files
Chen Wandun (1):
mm/hugetlb: suppress wrong warning info when alloc gigantic page
Chen Yu (1):
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Chen-Yu Tsai (3):
arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
PCI: rockchip: Make 'ep-gpios' DT property optional
Chenyang Li (1):
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Chia-I Wu (1):
drm/virtio: make sure context is created in gem open
Chris Ruehl (1):
phy: rockchip-emmc: emmc_phy_init() always return 0
Chris Wilson (4):
drm/i915/gt: One more flush for Baytrail clear residuals
drm/i915/gt: Flush before changing register state
drm/i915/gt: Correct surface base address for renderclear
kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Christoph Hellwig (1):
block: reopen the device in blkdev_reread_part
Christophe JAILLET (13):
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()
soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
hwrng: ingenic - Fix a resource leak in an error handling path
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: owl-mmc: Fix a resource leak in an error handling path and in the remove function
mmc: sdhci-sprd: Fix some resource leaks in the remove function
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe Leroy (6):
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
crypto: talitos - Fix ctr(aes) on SEC1
powerpc/47x: Disable 256k page size
powerpc/8xx: Fix software emulation interrupt
powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
powerpc/32s: Add missing call to kuep_lock on syscall entry
Christopher William Snowhill (1):
Bluetooth: Fix initializing response id after clearing struct
Chuck Lever (1):
svcrdma: Hold private mutex while invoking rdma_accept()
Chuhong Yuan (2):
drm/fb-helper: Add missed unlocks in setcmap_legacy()
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Claire Chang (1):
Bluetooth: hci_uart: Fix a race for write_work scheduling
Claudiu Beznea (1):
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Colin Ian King (4):
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
power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Cong Wang (1):
net_sched: fix RTNL deadlock again caused by request_module()
Corentin Labbe (6):
crypto: sun4i-ss - linearize buffers content must be kept
crypto: sun4i-ss - fix kmap usage
crypto: sun4i-ss - checking sg length is not sufficient
crypto: sun4i-ss - IV register does not work on A10 and A13
crypto: sun4i-ss - handle BigEndian for cipher
crypto: sun4i-ss - initialize need_fallback
Cornelia Huck (1):
virtio/s390: implement virtio-ccw revision 2 correctly
Cristian Marussi (1):
firmware: arm_scmi: Fix call site of scmi_notification_exit
Cédric Le Goater (2):
KVM: PPC: Make the VMX instruction emulation routines static
powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Dan Carpenter (20):
soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
ath11k: fix a locking bug in ath11k_mac_op_start()
gma500: clean up error handling in init
media: allegro: Fix use after free on error
media: camss: missing error code in msm_video_register()
ASoC: cs42l56: fix up error handling in probe
media: atomisp: Fix a buffer overflow in debug code
mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
scsi: lpfc: Fix ancient double free
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()
phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
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):
mm: fix memory_failure() handling of dax-namespace metadata
Daniel Latypov (1):
kunit: tool: fix unit test cleanup handling
Daniel Scally (1):
media: software_node: Fix refcounts in software_node_get_next_child()
Daniel W. S. Almeida (1):
media: vidtv: psi: fix missing crc for PMT
Daniele Alessandrelli (1):
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Dave Ertman (2):
ice: report correct max number of TCs
ice: Fix state bits on LLDP mode switch
Dave Hansen (1):
mm/vmscan: restore zone_reclaim_mode ABI
Dave Jiang (1):
dmaengine: idxd: set DMA channel to be private
David Gow (1):
rtc: zynqmp: depend on HAS_IOMEM
David Howells (1):
certs: Fix blacklist flag type confusion
Dehe Gu (1):
f2fs: fix a wrong condition in __submit_bio
Dinghao Liu (6):
Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
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
evm: Fix memleak in init_desc
ubifs: Fix memleak in ubifs_init_authentication
Dinh Nguyen (1):
arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Dmitry Baryshkov (2):
regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Osipenko (2):
opp: Correct debug message in _opp_add_static_v2()
power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Dmitry Safonov (1):
perf symbols: Use (long) for iterator for bfd symbols
Dmitry Torokhov (1):
Input: zinitix - fix return type of zinitix_init_touch()
Dom Cobley (4):
drm/vc4: hdmi: Move hdmi reset to bind
drm/vc4: hdmi: Fix register offset with longer CEC messages
drm/vc4: hdmi: Fix up CEC registers
drm/vc4: hdmi: Restore cec physical address on reconnect
Douglas Anderson (1):
iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Edwin Peer (1):
bnxt_en: reverse order of TX disable and carrier off
Eric Anholt (2):
drm/msm: Fix race of GPU init vs timestamp power management.
drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Bernstein (1):
drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Eric Biggers (1):
random: fix the RNDRESEEDCRNG ioctl
Eric Dumazet (1):
tcp: fix SO_RCVLOWAT related hangs under mem pressure
Eric W. Biederman (1):
capabilities: Don't allow writing ambiguous v3 file capabilities
Evan Benn (2):
platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Ezequiel Garcia (2):
media: imx: Unregister csc/scaler only if registered
media: imx: Fix csc/scaler unregister
Fabio Estevam (1):
media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Fangrui Song (1):
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Felix Kuehling (1):
drm/amdkfd: Fix recursive lock warnings
Ferry Toth (1):
dmaengine: hsu: disable spurious interrupt
Filipe Laíns (1):
HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Filipe Manana (1):
btrfs: fix extent buffer leak on failure to copy root
Finn Thain (2):
macintosh/adb-iop: Use big-endian autopoll mask
ide/falconide: Fix module unload
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
Frantisek Hrbata (1):
drm/nouveau: bail out of nouveau_channel_new if channel init fails
Frederic Weisbecker (2):
rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
rcu/nocb: Perform deferred wake up before last idle's need_resched() check
Gabriel Krisman Bertazi (1):
watch_queue: Drop references to /dev/watch_queue
Gao Xiang (1):
erofs: initialized fields can only be observed after bit is set
Geert Uytterhoeven (7):
arm64: dts: renesas: beacon: Fix EEPROM compatible value
irqchip/imx: IMX_INTMUX should not default to y, unconditionally
clk: renesas: r8a779a0: Remove non-existent S2 clock
clk: renesas: r8a779a0: Fix parent of CBFUSA clock
auxdisplay: ht16k33: Fix refresh rate handling
phy: USB_LGM_PHY should depend on X86
ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Gioh Kim (2):
RDMA/rtrs-srv: fix memory leak by missing kobject free
RDMA/rtrs-srv-sysfs: fix missing put_device
Giulio Benetti (1):
drm/sun4i: tcon: fix inverted DCLK polarity
Greg Kroah-Hartman (3):
debugfs: be more robust at handling improper input in debugfs_lookup()
debugfs: do not attempt to create a new file before the filesystem is initalized
Linux 5.10.20
Guchun Chen (1):
drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
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
Guido Günther (2):
drm/panel: mantix: Tweak init sequence
spi: imx: Don't print error on -EPROBEDEFER
Guoqing Jiang (2):
RDMA/rtrs: Call kobject_put in the failure path
RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Hans de Goede (2):
virt: vbox: Do not use wait_event_interruptible when called from kernel context
regulator: core: Avoid debugfs: Directory ... already present! error
Hao Xu (1):
io_uring: fix possible deadlock in io_uring_poll
Harald Freudenberger (1):
s390/zcrypt: return EIO when msg retry limit reached
Hari Bathini (1):
powerpc/kexec_file: fix FDT size estimation for kdump kernel
He Zhe (1):
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
Heiko Carstens (1):
s390/vtime: fix inline assembly clobber list
Heiko Stuebner (1):
drm/panel: kd35t133: allow using non-continuous dsi clock
Heiner Kallweit (3):
net: phy: consider that suspend2ram may cut off PHY power
PCI: Align checking of syscall user config accessors
r8169: fix jumbo packet handling on RTL8168e
Henry Tieman (1):
ice: update the number of available RSS queues
Huacai Chen (1):
irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Hui Wang (1):
ASoC: SOF: debug: Fix a potential issue on string buffer termination
Ilya Leoshkevich (1):
bpf: Clear subreg_def for global function return values
Ilya Lipnitskiy (1):
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Imre Deak (1):
drm/dp_mst: Don't cache EDIDs for physical ports
Ioana Ciornei (1):
dpaa2-eth: fix memory leak in XDP_REDIRECT
Isaac J. Manjarres (1):
iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Iskren Chernev (2):
drm/msm: Fix MSM_INFO_GET_IOVA with carveout
drm/msm/mdp5: Fix wait-for-commit for cmd panels
Ivan Zaentsev (1):
w1: w1_therm: Fix conversion result for negative temperatures
J. Bruce Fields (1):
nfsd: register pernet ops last, unregister first
Jack Pham (1):
usb: gadget: u_audio: Free requests only after callback
Jack Wang (8):
RDMA/rtrs: Extend ibtrs_cq_qp_create
RDMA/rtrs-srv: Release lock before call into close_sess
RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
RDMA/rtrs-clt: Set mininum limit when create QP
RDMA/rtrs-srv: Fix missing wr_cqe
RDMA/rtrs-srv: Init wr_cnt as 1
RDMA/rtrs-srv: Fix stack-out-of-bounds
RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Jacopo Mondi (1):
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Jae Hyun Yoo (1):
soc: aspeed: snoop: Add clock control logic
Jaegeuk Kim (1):
f2fs: flush data when enabling checkpoint back
James Bottomley (2):
tpm_tis: Fix check_locality for correct locality acquisition
tpm_tis: Clean up locality release
James Reynolds (1):
media: mceusb: Fix potential out-of-bounds shift
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
Jan Kokemüller (1):
drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Jann Horn (1):
Take mmap lock in cacheflush syscall
Jarkko Sakkinen (3):
KEYS: trusted: Fix incorrect handling of tpm_get_random()
KEYS: trusted: Fix migratable=1 failing
KEYS: trusted: Reserve TPM for seal and unseal operations
Jason A. Donenfeld (5):
wireguard: device: do not generate ICMP for non-IP packets
wireguard: kconfig: use arm chacha even with no neon
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
wireguard: selftests: test multiple parallel streams
wireguard: queueing: get rid of per-peer ring buffers
Jason Gerecke (1):
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Jeff Layton (1):
ceph: fix flush_snap logic after putting caps
Jeffle Xu (3):
dm table: fix iterate_devices based device capability checks
dm table: fix DAX iterate_devices based device capability checks
dm table: fix zoned iterate_devices based device capability checks
Jens Axboe (1):
proc: don't allow async path resolution of /proc/thread-self components
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: serial: ftdi_sio: fix FTX sub-integer prescaler
USB: serial: pl2303: fix line-speed handling on newer chips
Johannes Berg (2):
um: mm: check more comprehensively for stub changes
um: defer killing userspace on page table update failures
Johannes Thumshirn (1):
scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
John Garry (1):
perf vendor events arm64: Fix Ampere eMag event typo
John Ogness (1):
printk: avoid prb_first_valid_seq() where possible
John Stultz (1):
kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
John Wang (1):
ARM: dts: aspeed: Add LCLK to lpc-snoop
Jonathan Marek (2):
regulator: qcom-rpmh: fix pm8009 ldo7
misc: fastrpc: fix incorrect usage of dma_map_sgtable
Jorgen Hansen (1):
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Josef Bacik (9):
proc: use kvzalloc for our kernel buffer
btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
btrfs: do not warn if we can't find the reloc root when looking up backref
btrfs: add asserts for deleting backref cache nodes
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
btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
btrfs: account for new extents being deleted in total_bytes_pinned
Josh Poimboeuf (3):
objtool: Fix error handling for STD/CLD warnings
objtool: Fix retpoline detection in asm code
objtool: Fix ".cold" section suffix check for newer versions of GCC
Judy Hsiao (1):
drm/msm/dp: trigger unplug event in msm_dp_display_disable
Juergen Gross (1):
xen/netback: fix spurious event detection for common event case
Jun Nie (1):
ASoC: qcom: lpass: Fix i2s ctl register bit map
Jun'ichi Nomura (1):
bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Jupeng Zhong (1):
Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Jérôme Pouiller (1):
staging: wfx: fix possible panic with re-queued frames
Kai Krakow (3):
Revert "bcache: Kill btree_io_wq"
bcache: Give btree_io_wq correct semantics again
bcache: Move journal work to new flush wq
Kai Vehmanen (1):
ALSA: hda: Add another CometLake-H PCI ID
Kamal Heib (1):
RDMA/siw: Fix calculation of tx_valid_cpus size
KarimAllah Ahmed (1):
fdt: Properly handle "no-map" field in the memory region
Karol Herbst (1):
drm/nouveau/kms: handle mDP connectors
Kees Cook (1):
spi: dw: Avoid stack content exposure
Keith Busch (1):
nvme-multipath: set nr_zones for zoned namespaces
Keqian Zhu (2):
vfio/iommu_type1: Populate full dirty when detach non-pinned group
vfio/iommu_type1: Fix some sanity checks in detach group
Kevin Hao (1):
Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Konrad Dybcio (1):
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Krzysztof Kozlowski (10):
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
soc: samsung: exynos-asv: handle reading revision register error
Krzysztof Wilczyński (1):
PCI: cadence: Fix DMA range mapping early return error
Lakshmi Ramasubramanian (2):
ima: Free IMA measurement buffer on error
ima: Free IMA measurement buffer after kexec syscall
Lang Cheng (1):
RDMA/hns: Fixes missing error code of CMDQ
Laurent Pinchart (2):
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
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 Ou (1):
RDMA/hns: Disable RQ inline by default
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
Linus Torvalds (2):
tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
tty: implement read_iter
Lubomir Rintel (1):
media: marvell-ccic: power up the device on mclk enable
Luca Coelho (7):
iwlwifi: mvm: set enabled in the PPAG command properly
iwlwifi: mvm: fix the type we use in the PPAG table validity checks
iwlwifi: mvm: store PPAG enabled/disabled flag properly
iwlwifi: mvm: send stored PPAG command instead of local
iwlwifi: mvm: assign SAR table revision to the command later
iwlwifi: pnvm: set the PNVM again if it was already loaded
iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Weiss (1):
soc: qcom: ocmem: don't return NULL in of_get_ocmem
Luo Meng (1):
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Magnum Shan (1):
mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Manivannan Sadhasivam (1):
mtd: parsers: afs: Fix freeing the part name memory in failure
Marc Kleine-Budde (1):
can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Marc Zyngier (1):
arm64: Add missing ISB after invalidating TLB in __primary_switch
Marcin Ślusarz (1):
soundwire: intel: fix possible crash when no device is detected
Marco Elver (2):
bpf_lru_list: Read double-checked variable once without lock
kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Marcos Paulo de Souza (1):
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Marek Behún (1):
arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Marek Szyprowski (1):
soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Marek Vasut (1):
PCI: rcar: Always allocate MSI addresses in 32bit space
Mario Kleiner (2):
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Martin Blumenstingl (4):
net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
clk: meson: clk-pll: make "ret" a signed integer
clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin KaFai Lau (1):
libbpf: Ignore non function pointer member in struct_ops
Martin Kaiser (1):
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Masahisa Kojima (1):
spi: spi-synquacer: fix set_cs handling
Masami Hiramatsu (1):
kprobes: Fix to delay the kprobes jump optimization
Mateusz Palczewski (4):
i40e: Add zero-initialization of AQ command structures
i40e: Fix overwriting flow control settings during driver loading
i40e: Fix addition of RX filters after enabling FW LLDP agent
i40e: Fix add TC filter for IPv6
Mathias Kresin (1):
phy: lantiq: rcu-usb2: wait after clock enable
Matthieu Baerts (1):
selftests: mptcp: fix ACKRX debug message
Matti Vaittinen (1):
regulator: bd718x7, bd71828, Fix dvs voltage levels
Max Gurtovoy (1):
vfio-pci/zdev: fix possible segmentation fault issue
Maxim Kiselev (1):
gpio: pcf857x: Fix missing first interrupt
Maxim Mikityanskiy (4):
net/mlx5e: Don't change interrupt moderation params when DIM is enabled
net/mlx5e: Change interrupt moderation channel params also when channels are closed
net/mlx5e: Replace synchronize_rcu with synchronize_net
net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
Maxime Chevallier (1):
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Maxime Ripard (4):
drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Maximilian Luz (1):
ACPICA: Fix exception code class checks
Md Haris Iqbal (1):
RDMA/rtrs: Only allow addition of path to an already established session
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
Michael Tretter (1):
clk: divider: fix initialization with parent_hw
Mike Kravetz (2):
hugetlb: fix update_and_free_page contig page struct assumption
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mikulas Patocka (5):
blk-settings: align max_sectors on "logical_block_size" boundary
dm: fix deadlock when swapping to encrypted device
dm writecache: fix performance degradation in ssd mode
dm writecache: return the exact table values that were set
dm writecache: fix writing beyond end of underlying device when shrinking
Misono Tomohiro (1):
x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Moshe Shemesh (1):
net/mlx5e: Check tunnel offload is required before setting SWP
Muchun Song (5):
mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
mm: memcontrol: fix slub memory accounting
mm: memcontrol: fix swap undercounting in cgroup2
mm: memcontrol: fix get_active_memcg return value
printk: fix deadlock when kernel panic
Mårten Lindahl (1):
i2c: exynos5: Preserve high speed master code
Namhyung Kim (1):
perf test: Fix unaligned access in sample parsing test
Namjae Jeon (1):
exfat: fix shift-out-of-bounds in exfat_fill_super()
Nathan Chancellor (5):
vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
MIPS: Compare __SYNC_loongson3_war against 0
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
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
Nicholas Fraser (1):
perf symbols: Fix return value when loading PE DSO
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
Nicolas Saenz Julienne (1):
spi: Skip zero-length transfers in spi_transfer_one_message()
Nikos Tsironis (7):
dm era: Recover committed writeset after crash
dm era: Update in-core bitset after committing the metadata
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
Nirmoy Das (1):
drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Olivier Crête (1):
Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
Oz Shlomo (1):
net/mlx5e: CT: manage the lifetime of the ct entry object
Pan Bian (11):
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
bsg: free the request before return error code
regulator: axp20x: Fix reference cout leak
regulator: s5m8767: Fix reference count leak
spi: atmel: Put allocated master before return
isofs: release buffer head before return
PCI: xilinx-cpm: Fix reference count leak on error path
mtd: spi-nor: hisi-sfc: Put child node np on error path
fs/affs: release old buffer head on error path
Paolo Bonzini (1):
KVM: nSVM: fix running nested guests when npt=0
Parav Pandit (3):
IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
IB/mlx5: Return appropriate error code instead of ENOMEM
IB/cm: Avoid a loop when device has 255 ports
Paul Cercueil (3):
usb: musb: Fix runtime PM race in musb_queue_resume_work
MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
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 (1):
locking/lockdep: Avoid unmatched unlock
Phil Elwell (2):
staging: vchiq: Fix bulk userdata handling
staging: vchiq: Fix bulk transfers on 64-bit builds
Pierre-Louis Bossart (7):
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
soundwire: cadence: fix ACK/NAK handling
soundwire: bus: use sdw_update_no_pm when initializing a device
soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
soundwire: bus: fix confusion on device used by pm_runtime
Pingfan Liu (1):
powerpc/time: Enable sched clock for irqtime
Po-Hsu Lin (1):
selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Pratyush Yadav (1):
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Qais Yousef (1):
sched/eas: Don't update misfit status if the task is pinned
Qinglang Miao (4):
drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
drm/lima: fix reference leak in lima_pm_busy
ACPI: configfs: add missing check after configfs_register_default_group()
Qu Wenruo (1):
btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Quinn Tran (1):
scsi: qla2xxx: Fix mailbox Ch erroneous error
Rafael J. Wysocki (3):
ACPI: property: Fix fwnode string properties matching
cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Rakesh Pillai (1):
ath10k: Fix error handling in case of CE pipe init failure
Randy Dunlap (7):
fbdev: aty: SPARC64 requires FB_ATY_CT
HID: core: detect and skip invalid inputs to snto32()
power: supply: fix sbs-charger build, needs REGMAP_I2C
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
sparc: fix led.c driver when PROC_FS is not enabled
ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Ranjani Sridharan (1):
ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Rasmus Villemoes (1):
spi: fsl: invert spisel_boot signal on MPC8309
Rayagonda Kokatanur (3):
i2c: iproc: handle only slave interrupts which are enabled
i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
i2c: iproc: handle master read request
Ricky Wu (1):
misc: rtsx: init of rts522a add OCP power off when no card is present
Rik van Riel (1):
mm,thp,shmem: make khugepaged obey tmpfs mount flags
Robert Foss (1):
arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Robert Hancock (1):
net: axienet: Handle deferred probe on clock properly
Robin Murphy (2):
perf/arm-cmn: Fix PMU instance naming
perf/arm-cmn: Move IRQs when migrating context
Rodrigo Siqueira (1):
drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Roja Rani Yarubandi (1):
i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Rosen Penev (2):
ARM: dts: armada388-helios4: assign pinctrl to LEDs
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rui Miguel Silva (1):
media: imx7: csi: Fix pad link validation
Russell King (1):
PCI: pci-bridge-emul: Fix array overruns, improve safety
Ryan Chen (1):
clk: aspeed: Fix APLL calculate formula from ast2600-A2
Sabyrzhan Tasbolatov (1):
drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Sagi Grimberg (2):
nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
nvmet-tcp: fix potential race of tcp socket closing accept_work
Sai Prakash Ranjan (1):
watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Sameer Pujar (1):
ASoC: simple-card-utils: Fix device module clock
Samuel Holland (1):
power: supply: axp20x_usb_power: Init work before enabling IRQs
Sara Sharon (1):
iwlwifi: mvm: don't check if CSA event is running before removing
Sathyanarayana Nujella (1):
ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Sean Christopherson (6):
KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
x86/virt: Eat faults on VMXOFF in reboot flows
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Young (2):
media: ir_toy: add another IR Droid device
media: smipcie: fix interrupt handling and IR timeout
Sebastian Andrzej Siewior (1):
smp: Process pending softirqs in flush_smp_call_function_from_idle()
Sebastian Reichel (1):
ASoC: cpcap: fix microphone timeslot mask
Shaoying Xu (1):
arm64 module: set plt* section addresses to 0x0
Shawn Guo (1):
cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Shay Drory (7):
net/mlx5: Fix health error state handling
net/mlx5: Disable devlink reload for multi port slave device
net/mlx5: Disallow RoCE on multi port slave device
net/mlx5: Disallow RoCE on lag device
net/mlx5: Disable devlink reload for lag devices
IB/umad: Return EIO in case of when device disassociated
IB/umad: Return EPOLLERR in case of when device disassociated
Shin'ichiro Kawasaki (1):
zonefs: Fix file size of zones in full condition
Shirley Her (1):
mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Shiyang Ruan (1):
device-dax: Fix default return code of range_parse()
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 Ser (1):
drm/fourcc: fix Amlogic format modifier masks
Simon South (3):
pwm: rockchip: Enable APB clock during register access while probing
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
pwm: rockchip: Eliminate potential race condition when probing
Slawomir Laba (1):
i40e: Fix flow for IPv6 next header (extension header)
Song, Yoong Siang (1):
net: stmmac: fix CBS idleslope and sendslope calculation
Srinivas Kandagatla (1):
ASoC: codecs: add missing max_register in regmap config
Srinivasa Rao Mandadapu (2):
ASoC: qcom: lpass-cpu: Remove bit clock state check
ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Stefano Garzarella (1):
vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Stephan Gerhold (3):
arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Steven Rostedt (VMware) (1):
tracepoint: Do not fail unregistering a probe due to memory failure
Subbaraman Narayanamurthy (2):
nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
spmi: spmi-pmic-arb: Fix hw_irq overflow
Sukadev Bhattiprolu (1):
ibmvnic: Set to CLOSED state even on error
Sumit Garg (2):
kdb: Make memory allocations more robust
kgdb: fix to kill breakpoints on initmem after boot
Suzuki K Poulose (3):
coresight: etm4x: Skip accessing TRCPDCR in save/restore
arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
coresight: etm4x: Handle accesses to TRCSTALLCTLR
Sylwester Dziedziuch (1):
i40e: Fix VFs not created
Taehee Yoo (1):
vxlan: move debug check after netdev unregister
Takahiro Kuwano (4):
mtd: spi-nor: sfdp: Fix last erase region marking
mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
mtd: spi-nor: core: Fix erase type discovery for overlaid region
mtd: spi-nor: core: Add erase size check for erase command initialization
Takashi Iwai (7):
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
ALSA: pcm: Call sync_stop at disconnection
ALSA: pcm: Assure sync with the pending stop operation at suspend
ALSA: pcm: Don't call sync_stop if it hasn't been stopped
ALSA: hda/hdmi: Drop bogus check at closing a stream
ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
ASoC: siu: Fix build error by a wrong const prefix
Takashi Sakamoto (1):
ALSA: fireface: fix to parse sync status register of latter protocol
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
Thomas Gleixner (1):
x86/entry: Fix instrumentation annotation
Tim Harvey (1):
mfd: gateworks-gsc: Fix interrupt type
Timothy E Baldwin (1):
arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Tobias Klauser (1):
riscv: Disable KSAN_SANITIZE for vDSO
Tom Rix (4):
media: mtk-vcodec: fix argument used when DEBUG is defined
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
Tom Zanussi (1):
selftests/ftrace: Update synthetic event syntax errors
Tomas Winkler (1):
mei: me: emmitsburg workstation DID
Tomi Valkeinen (2):
media: ti-vpe: cal: fix write to unallocated memory
media: i2c: max9286: fix access to unallocated memory
Tony Lindgren (4):
ARM: dts: Configure missing thermal interrupt for 4430
power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
power: supply: cpcap-charger: Fix missing power_supply_put()
power: supply: cpcap-battery: Fix missing power_supply_put()
Trond Myklebust (1):
NFSv4: Fixes for nfs4_bitmask_adjust()
Tzung-Bi Shih (1):
remoteproc/mediatek: acknowledge watchdog IRQ after handled
Uwe Kleine-König (2):
amba: Fix resource leak for drivers without .remove
pwm: iqs620a: Fix overflow and optimize calculations
Vasundhara Volam (1):
bnxt_en: Fix devlink info's stored fw.psid version format.
Ville Syrjälä (2):
drm/modes: Switch to 64bit maths to avoid integer overflow
drm/i915: Reject 446-480MHz HDMI clock on GLK
Vincent Knecht (1):
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Viresh Kumar (1):
thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Vlad Buslov (1):
net: sched: fix police ext initialization
Vladimir Murzin (1):
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Vladimir Oltean (3):
net: dsa: felix: perform teardown in reverse order of setup
net: dsa: felix: don't deinitialize unused ports
net: enetc: fix destroyed phylink dereference during unbind
Vlastimil Babka (1):
mm, compaction: make fast_isolate_freepages() stay within zone
Wang ShaoBo (1):
ubifs: Fix error return code in alloc_wbufs()
Wang Xiaojun (1):
drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Weihang Li (1):
RDMA/hns: Fix type of sq_signal_bits
Wenpeng Liang (1):
RDMA/hns: Fixed wrong judgments in the goto branch
Will Deacon (2):
mm: proc: Invalidate TLB after clearing soft-dirty page state
arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Wonhyuk Yang (1):
mm/compaction: fix misbehaviors of fast_find_migrateblock()
Xuewen Yan (1):
sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Yang Jihong (1):
perf record: Fix continue profiling after draining the buffer
Yi Chen (1):
f2fs: fix to avoid inconsistent quota data
Yishai Hadas (1):
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Yong Wu (2):
iommu: Switch gather->end to the inclusive end
iommu: Move iotlb_sync_map out from __iommu_map
Yonghong Song (1):
bpf: Fix an unitialized value in bpf_iter
Yongqiang Niu (1):
drm/mediatek: Check if fb is null
Yoshihiro Shimoda (1):
mfd: bd9571mwv: Use devm_mfd_add_devices()
Zhang Changzhong (2):
media: mtk-vcodec: fix error return code in vdec_vp9_decode()
media: aspeed: fix error return code in aspeed_video_setup_video()
Zhang Qilong (2):
memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
HSI: Fix PM usage counter unbalance in ssi_hw_init
Zhenzhong Duan (1):
csky: Fix a size determination in gpr_get()
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
qiuguorui1 (1):
arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
^ permalink raw reply [relevance 1%]
* [PATCH 5.10 000/657] 5.10.20-rc4 review
@ 2021-03-02 19:28 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-02 19:28 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.10.20 release.
There are 657 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 04 Mar 2021 19:25:07 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.20-rc4.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.20-rc4
Cong Wang <cong.wang@bytedance.com>
net_sched: fix RTNL deadlock again caused by request_module()
Takeshi Misawa <jeliantsurux@gmail.com>
net: qrtr: Fix memory leak in qrtr_tun_open
Vlad Buslov <vladbu@nvidia.com>
net: sched: fix police ext initialization
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: get rid of per-peer ring buffers
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: selftests: test multiple parallel streams
Jason A. Donenfeld <Jason@zx2c4.com>
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Leon Romanovsky <leon@kernel.org>
ipv6: silence compilation warning for non-IPV6 builds
Sumit Garg <sumit.garg@linaro.org>
kgdb: fix to kill breakpoints on initmem after boot
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/i915: Reject 446-480MHz HDMI clock on GLK
Nikos Tsironis <ntsironis@arrikto.com>
dm era: only resize metadata in preresume
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Reinitialize bitset cache before digesting a new writeset
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Use correct value size in equality function of writeset tree
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Fix bitset memory leaks
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Verify the data block size hasn't changed
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Update in-core bitset after committing the metadata
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Recover committed writeset after crash
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix writing beyond end of underlying device when shrinking
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: return the exact table values that were set
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix performance degradation in ssd mode
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix zoned iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix DAX iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix iterate_devices based device capability checks
Mikulas Patocka <mpatocka@redhat.com>
dm: fix deadlock when swapping to encrypted device
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Lock imbalance on error path in gfs2_recover_one
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't skip dlm unlock if glock has an lvb
Bob Peterson <rpeterso@redhat.com>
gfs2: fix glock confusion in function signal_our_withdraw
Masahisa Kojima <masahisa.kojima@linaro.org>
spi: spi-synquacer: fix set_cs handling
Rasmus Villemoes <rasmus.villemoes@prevas.dk>
spi: fsl: invert spisel_boot signal on MPC8309
Al Viro <viro@zeniv.linux.org.uk>
sparc32: fix a user-triggerable oops in clear_user()
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: flush data when enabling checkpoint back
Chao Yu <chao@kernel.org>
f2fs: enforce the immutable flag on open files
Chao Yu <chao@kernel.org>
f2fs: fix out-of-repair __setattr_copy()
Huacai Chen <chenhuacai@loongson.cn>
irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Johannes Berg <johannes.berg@intel.com>
um: defer killing userspace on page table update failures
Johannes Berg <johannes.berg@intel.com>
um: mm: check more comprehensively for stub changes
Cornelia Huck <cohuck@redhat.com>
virtio/s390: implement virtio-ccw revision 2 correctly
Heiko Carstens <hca@linux.ibm.com>
s390/vtime: fix inline assembly clobber list
Jens Axboe <axboe@kernel.dk>
proc: don't allow async path resolution of /proc/thread-self components
Chen Yu <yu.c.chen@intel.com>
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Shawn Guo <shawn.guo@linaro.org>
cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Viresh Kumar <viresh.kumar@linaro.org>
thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Chris Wilson <chris@chris-wilson.co.uk>
kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
zonefs: Fix file size of zones in full condition
Namjae Jeon <namjae.jeon@samsung.com>
exfat: fix shift-out-of-bounds in exfat_fill_super()
Muchun Song <songmuchun@bytedance.com>
printk: fix deadlock when kernel panic
Tim Harvey <tharvey@gateworks.com>
mfd: gateworks-gsc: Fix interrupt type
Maxim Kiselev <bigunclemax@gmail.com>
gpio: pcf857x: Fix missing first interrupt
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point LP DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point S DID
Tomas Winkler <tomas.winkler@intel.com>
mei: me: emmitsburg workstation DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: fix transfer over dma with extended header
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
spmi: spmi-pmic-arb: Fix hw_irq overflow
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32s: Add missing call to kuep_lock on syscall entry
Hari Bathini <hbathini@linux.ibm.com>
powerpc/kexec_file: fix FDT size estimation for kdump kernel
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
Shirley Her <shirley.her@bayhubtech.com>
mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Frank Li <Frank.Li@nxp.com>
mmc: sdhci-esdhc-imx: fix kernel panic when remove module
Fangrui Song <maskray@google.com>
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
Paolo Bonzini <pbonzini@redhat.com>
KVM: nSVM: fix running nested guests when npt=0
Vlastimil Babka <vbabka@suse.cz>
mm, compaction: make fast_isolate_freepages() stay within zone
Dave Hansen <dave.hansen@linux.intel.com>
mm/vmscan: restore zone_reclaim_mode ABI
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix update_and_free_page contig page struct assumption
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix get_active_memcg return value
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix swap undercounting in cgroup2
NeilBrown <neilb@suse.de>
x86: fix seq_file iteration for pat/memtype.c
NeilBrown <neilb@suse.de>
seq_file: document how per-entry resources are managed.
Pan Bian <bianpan2016@163.com>
fs/affs: release old buffer head on error path
Pan Bian <bianpan2016@163.com>
mtd: spi-nor: hisi-sfc: Put child node np on error path
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Add erase size check for erase command initialization
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Fix erase type discovery for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix last erase region marking
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Handle accesses to TRCSTALLCTLR
Alexander Usyskin <alexander.usyskin@intel.com>
watchdog: mei_wdt: request stop on unregister
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Tobias Klauser <tklauser@distanz.ch>
riscv: Disable KSAN_SANITIZE for vDSO
Will Deacon <will@kernel.org>
arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Shaoying Xu <shaoyi@amazon.com>
arm64 module: set plt* section addresses to 0x0
He Zhe <zhe.he@windriver.com>
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
qiuguorui1 <qiuguorui1@huawei.com>
arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
Isaac J. Manjarres <isaacm@codeaurora.org>
iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Suzuki K Poulose <suzuki.poulose@arm.com>
arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
Masami Hiramatsu <mhiramat@kernel.org>
kprobes: Fix to delay the kprobes jump optimization
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Perform deferred wake up before last idle's need_resched() check
Frederic Weisbecker <frederic@kernel.org>
rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
Cédric Le Goater <clg@kaod.org>
powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Thomas Gleixner <tglx@linutronix.de>
x86/entry: Fix instrumentation annotation
Andy Lutomirski <luto@kernel.org>
x86/fault: Fix AMD erratum #91 errata fixup for user code
Sean Christopherson <seanjc@google.com>
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Christopherson <seanjc@google.com>
x86/virt: Eat faults on VMXOFF in reboot flows
Sean Young <sean@mess.org>
media: smipcie: fix interrupt handling and IR timeout
Lubomir Rintel <lkundrak@v3.sk>
media: marvell-ccic: power up the device on mclk enable
Pavel Machek <pavel@denx.de>
media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
Sean Young <sean@mess.org>
media: ir_toy: add another IR Droid device
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: i2c: max9286: fix access to unallocated memory
Jiri Kosina <jkosina@suse.cz>
floppy: reintroduce O_NDELAY fix
Martin Kaiser <martin@kaiser.cx>
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Amey Narkhede <ameynarkhede03@gmail.com>
staging: gdm724x: Fix DMA from stack
Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Dinh Nguyen <dinguyen@kernel.org>
arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Frank Wunderlich <frank-w@public-files.de>
dts64: mt7622: fix slow sd card access
Jiri Bohac <jbohac@suse.cz>
pstore: Fix typo in compression option name
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Ricky Wu <ricky_wu@realtek.com>
misc: rtsx: init of rts522a add OCP power off when no card is present
Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Paul Cercueil <paul@crapouillou.net>
seccomp: Add missing return in non-void function
Krzysztof Kozlowski <krzk@kernel.org>
soc: samsung: exynos-asv: handle reading revision register error
Marek Szyprowski <m.szyprowski@samsung.com>
soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - initialize need_fallback
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - handle BigEndian for cipher
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - IV register does not work on A10 and A13
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - checking sg length is not sufficient
Ard Biesheuvel <ardb@kernel.org>
crypto: michael_mic - fix broken misalignment handling
Ard Biesheuvel <ardb@kernel.org>
crypto: aesni - prevent misaligned buffers on the stack
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/sha - add missing module aliases
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Correct surface base address for renderclear
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Flush before changing register state
Filipe Manana <fdmanana@suse.com>
btrfs: fix extent buffer leak on failure to copy root
Josef Bacik <josef@toxicpanda.com>
btrfs: account for new extents being deleted in total_bytes_pinned
Josef Bacik <josef@toxicpanda.com>
btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
Josef Bacik <josef@toxicpanda.com>
btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
Josef Bacik <josef@toxicpanda.com>
btrfs: fix reloc root leak with 0 ref reloc roots on recovery
Josef Bacik <josef@toxicpanda.com>
btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
Josef Bacik <josef@toxicpanda.com>
btrfs: add asserts for deleting backref cache nodes
Josef Bacik <josef@toxicpanda.com>
btrfs: do not warn if we can't find the reloc root when looking up backref
Josef Bacik <josef@toxicpanda.com>
btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Reserve TPM for seal and unseal operations
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix migratable=1 failing
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix incorrect handling of tpm_get_random()
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Clean up locality release
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Fix check_locality for correct locality acquisition
Gao Xiang <hsiangkao@redhat.com>
erofs: initialized fields can only be observed after bit is set
Amir Goldstein <amir73il@gmail.com>
selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Takashi Iwai <tiwai@suse.de>
ASoC: siu: Fix build error by a wrong const prefix
Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
drm/rockchip: Require the YTR modifier for AFBC
Heiko Stuebner <heiko@sntech.de>
drm/panel: kd35t133: allow using non-continuous dsi clock
Andrey Grodzovsky <andrey.grodzovsky@amd.com>
drm/sched: Cancel and flush all outstanding jobs before finish.
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/modes: Switch to 64bit maths to avoid integer overflow
Karol Herbst <kherbst@redhat.com>
drm/nouveau/kms: handle mDP connectors
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Felix Kuehling <Felix.Kuehling@amd.com>
drm/amdkfd: Fix recursive lock warnings
Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Eric Bernstein <eric.bernstein@amd.com>
drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Jan Kokemüller <jan.kokemueller@gmail.com>
drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Alex Deucher <alexander.deucher@amd.com>
Revert "drm/amd/display: Update NV1x SR latency values"
Kai Krakow <kai@kaishome.de>
bcache: Move journal work to new flush wq
Kai Krakow <kai@kaishome.de>
bcache: Give btree_io_wq correct semantics again
Kai Krakow <kai@kaishome.de>
Revert "bcache: Kill btree_io_wq"
Kevin Hao <haokexin@gmail.com>
Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Nathan Chancellor <natechancellor@gmail.com>
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
Aurelien Jarno <aurelien@aurel32.net>
MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Paul Cercueil <paul@crapouillou.net>
MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
Takashi Iwai <tiwai@suse.de>
ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
PeiSen Hou <pshou@realtek.com>
ALSA: hda/realtek: modify EAPD in the ALC886
Takashi Iwai <tiwai@suse.de>
ALSA: hda/hdmi: Drop bogus check at closing a stream
Kai Vehmanen <kai.vehmanen@linux.intel.com>
ALSA: hda: Add another CometLake-H PCI ID
Takashi Sakamoto <o-takashi@sakamocchi.jp>
ALSA: fireface: fix to parse sync status register of latter protocol
Mathias Kresin <dev@kresin.me>
phy: lantiq: rcu-usb2: wait after clock enable
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7720: fix error code in mos7720_write()
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7840: fix error code in mos7840_write()
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix line-speed handling on newer chips
Johan Hovold <johan@kernel.org>
USB: serial: ftdi_sio: fix FTX sub-integer prescaler
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
Paul Cercueil <paul@crapouillou.net>
usb: musb: Fix runtime PM race in musb_queue_resume_work
Lech Perczak <lech.perczak@gmail.com>
USB: serial: option: update interface mapping for ZTE P685M
James Reynolds <jr@memlen.com>
media: mceusb: Fix potential out-of-bounds shift
Marcos Paulo de Souza <mpdesouza@suse.com>
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Dan Carpenter <dan.carpenter@oracle.com>
Input: joydev - prevent potential read overflow in ioctl
Olivier Crête <olivier.crete@ocrete.ca>
Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
jeffrey.lin <jeffrey.lin@rad-ic.com>
Input: raydium_ts_i2c - do not send zero length
Jason Gerecke <killertofu@gmail.com>
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Filipe Laíns <lains@riseup.net>
HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
Qinglang Miao <miaoqinglang@huawei.com>
ACPI: configfs: add missing check after configfs_register_default_group()
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: property: Fix fwnode string properties matching
Marcin Ślusarz <marcin.slusarz@intel.com>
soundwire: intel: fix possible crash when no device is detected
Mikulas Patocka <mpatocka@redhat.com>
blk-settings: align max_sectors on "logical_block_size" boundary
Bart Van Assche <bvanassche@acm.org>
scsi: sd: Fix Opal support
Finn Thain <fthain@telegraphics.com.au>
ide/falconide: Fix module unload
Christoph Hellwig <hch@lst.de>
block: reopen the device in blkdev_reread_part
Johannes Thumshirn <johannes.thumshirn@wdc.com>
scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
Randy Dunlap <rdunlap@infradead.org>
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Zhenzhong Duan <zhenzhong.duan@gmail.com>
csky: Fix a size determination in gpr_get()
Josef Bacik <josef@toxicpanda.com>
proc: use kvzalloc for our kernel buffer
Miaohe Lin <linmiaohe@huawei.com>
mm/rmap: fix potential pte_unmap on an not mapped pte
Dan Williams <dan.j.williams@intel.com>
mm: fix memory_failure() handling of dax-namespace metadata
Rik van Riel <riel@surriel.com>
mm,thp,shmem: make khugepaged obey tmpfs mount flags
Mårten Lindahl <martenli@axis.com>
i2c: exynos5: Preserve high speed master code
Maxime Ripard <maxime@cerno.tech>
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Marc Zyngier <maz@kernel.org>
arm64: Add missing ISB after invalidating TLB in __primary_switch
Sean Christopherson <seanjc@google.com>
KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
Sean Christopherson <seanjc@google.com>
KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4: Fixes for nfs4_bitmask_adjust()
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix jumbo packet handling on RTL8168e
Wonhyuk Yang <vvghjk1234@gmail.com>
mm/compaction: fix misbehaviors of fast_find_migrateblock()
Chen Wandun <chenwandun@huawei.com>
mm/hugetlb: suppress wrong warning info when alloc gigantic page
Miaohe Lin <linmiaohe@huawei.com>
mm/hugetlb: fix potential double free in hugetlb_register_node() error path
Miaohe Lin <linmiaohe@huawei.com>
mm/memory.c: fix potential pte_unmap_unlock pte error
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix slub memory accounting
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
Dan Carpenter <dan.carpenter@oracle.com>
ocfs2: fix a use after free on error
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: kconfig: use arm chacha even with no neon
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: device: do not generate ICMP for non-IP packets
Taehee Yoo <ap420073@gmail.com>
vxlan: move debug check after netdev unregister
Chen-Yu Tsai <wens@csie.org>
PCI: rockchip: Make 'ep-gpios' DT property optional
Chuhong Yuan <hslester96@gmail.com>
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Song, Yoong Siang <yoong.siang.song@intel.com>
net: stmmac: fix CBS idleslope and sendslope calculation
Henry Tieman <henry.w.tieman@intel.com>
ice: update the number of available RSS queues
Dave Ertman <david.m.ertman@intel.com>
ice: Fix state bits on LLDP mode switch
Brett Creeley <brett.creeley@intel.com>
ice: Account for port VLAN in VF max packet size calculation
Dave Ertman <david.m.ertman@intel.com>
ice: report correct max number of TCs
Alex Williamson <alex.williamson@redhat.com>
vfio/type1: Use follow_pte()
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
pwm: iqs620a: Fix overflow and optimize calculations
Dan Carpenter <dan.carpenter@oracle.com>
octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix add TC filter for IPv6
Andreas Oetken <andreas.oetken@siemens.com>
nios2: fixed broken sys_clone syscall
Jann Horn <jannh@google.com>
Take mmap lock in cacheflush syscall
Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
i40e: Fix VFs not created
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix addition of RX filters after enabling FW LLDP agent
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix overwriting flow control settings during driver loading
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Add zero-initialization of AQ command structures
Slawomir Laba <slawomirx.laba@intel.com>
i40e: Fix flow for IPv6 next header (extension header)
Krzysztof Wilczyński <kw@linux.com>
PCI: cadence: Fix DMA range mapping early return error
Russell King <rmk+kernel@armlinux.org.uk>
PCI: pci-bridge-emul: Fix array overruns, improve safety
Shiyang Ruan <ruansy.fnst@cn.fujitsu.com>
device-dax: Fix default return code of range_parse()
Magnum Shan <magnum.shan@unisoc.com>
mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Geert Uytterhoeven <geert@linux-m68k.org>
ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Bard Liao <yung-chuan.liao@linux.intel.com>
regmap: sdw: use _no_pm functions in regmap_read/write
Tzung-Bi Shih <tzungbi@google.com>
remoteproc/mediatek: acknowledge watchdog IRQ after handled
Jonathan Marek <jonathan@marek.ca>
misc: fastrpc: fix incorrect usage of dma_map_sgtable
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: fix confusion on device used by pm_runtime
Bard Liao <yung-chuan.liao@linux.intel.com>
soundwire: export sdw_write/read_no_pm functions
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_update_no_pm when initializing a device
Ahmad Fatoum <a.fatoum@pengutronix.de>
nvmem: core: skip child nodes not matching binding
Dan Carpenter <dan.carpenter@oracle.com>
nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Skip accessing TRCPDCR in save/restore
Geert Uytterhoeven <geert+renesas@glider.be>
phy: USB_LGM_PHY should depend on X86
Theodore Ts'o <tytso@mit.edu>
ext4: fix potential htree index checksum corruption
Max Gurtovoy <mgurtovoy@nvidia.com>
vfio-pci/zdev: fix possible segmentation fault issue
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Fix some sanity checks in detach group
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Populate full dirty when detach non-pinned group
Judy Hsiao <judyhsiao@google.com>
drm/msm/dp: trigger unplug event in msm_dp_display_disable
Eric Anholt <eric@anholt.net>
drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Anholt <eric@anholt.net>
drm/msm: Fix race of GPU init vs timestamp power management.
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm/mdp5: Fix wait-for-commit for cmd panels
Konrad Dybcio <konrad.dybcio@somainline.org>
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm: Fix MSM_INFO_GET_IOVA with carveout
Alexander Usyskin <alexander.usyskin@intel.com>
mei: hbm: call mei_set_devstate() on hbm stop response
Heiner Kallweit <hkallweit1@gmail.com>
PCI: Align checking of syscall user config accessors
Jorgen Hansen <jhansen@vmware.com>
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Pan Bian <bianpan2016@163.com>
PCI: xilinx-cpm: Fix reference count leak on error path
Simon South <simon@simonsouth.net>
pwm: rockchip: Eliminate potential race condition when probing
Simon South <simon@simonsouth.net>
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
Simon South <simon@simonsouth.net>
pwm: rockchip: Enable APB clock during register access while probing
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: cadence: fix ACK/NAK handling
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
soundwire: debugfs: use controller id instead of link_id
Marek Vasut <marek.vasut+renesas@gmail.com>
PCI: rcar: Always allocate MSI addresses in 32bit space
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Add module alias to avoid breaking support for non device tree users
Dan Carpenter <dan.carpenter@oracle.com>
phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
Chris Ruehl <chris.ruehl@gtsys.com.hk>
phy: rockchip-emmc: emmc_phy_init() always return 0
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Fix module alias to enable module autoprobe
Randy Dunlap <rdunlap@infradead.org>
ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: zinitix - fix return type of zinitix_init_touch()
Randy Dunlap <rdunlap@infradead.org>
sparc: fix led.c driver when PROC_FS is not enabled
Randy Dunlap <rdunlap@infradead.org>
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
Dan Carpenter <dan.carpenter@oracle.com>
Input: elo - fix an error code in elo_connect()
Namhyung Kim <namhyung@kernel.org>
perf test: Fix unaligned access in sample parsing test
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix IPC with CYC threshold
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix premature IPC
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix missing CYC processing in PSB
Yang Jihong <yangjihong1@huawei.com>
perf record: Fix continue profiling after draining the buffer
Dan Carpenter <dan.carpenter@oracle.com>
Input: sur40 - fix an error code in sur40_probe()
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv-sysfs: fix missing put_device
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv: fix memory leak by missing kobject free
Md Haris Iqbal <haris.iqbal@cloud.ionos.com>
RDMA/rtrs: Only allow addition of path to an already established session
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix stack-out-of-bounds
Avihai Horon <avihaih@nvidia.com>
RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Fixes missing error code of CMDQ
Jeff Layton <jlayton@kernel.org>
ceph: fix flush_snap logic after putting caps
Chuck Lever <chuck.lever@oracle.com>
svcrdma: Hold private mutex while invoking rdma_accept()
J. Bruce Fields <bfields@redhat.com>
nfsd: register pernet ops last, unregister first
Nicholas Fraser <nfraser@codeweavers.com>
perf symbols: Fix return value when loading PE DSO
John Ogness <john.ogness@linutronix.de>
printk: avoid prb_first_valid_seq() where possible
Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
spi: Skip zero-length transfers in spi_transfer_one_message()
Kees Cook <keescook@chromium.org>
spi: dw: Avoid stack content exposure
Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
regulator: bd718x7, bd71828, Fix dvs voltage levels
Dmitry Safonov <0x7f454c46@gmail.com>
perf symbols: Use (long) for iterator for bfd symbols
Tom Zanussi <zanussi@kernel.org>
selftests/ftrace: Update synthetic event syntax errors
Ryan Chen <ryan_chen@aspeedtech.com>
clk: aspeed: Fix APLL calculate formula from ast2600-A2
Jonathan Marek <jonathan@marek.ca>
regulator: qcom-rpmh: fix pm8009 ldo7
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/kuap: Restore AMR after replaying soft interrupts
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/uaccess: Avoid might_fault() when user access is enabled
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
spi: pxa2xx: Fix the controller numbering for Wildcat Point
Michael Tretter <m.tretter@pengutronix.de>
clk: divider: fix initialization with parent_hw
Lijun Ou <oulijun@huawei.com>
RDMA/hns: Disable RQ inline by default
Weihang Li <liweihang@huawei.com>
RDMA/hns: Fix type of sq_signal_bits
Kamal Heib <kamalheib1@gmail.com>
RDMA/siw: Fix calculation of tx_valid_cpus size
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Fixed wrong judgments in the goto branch
John Stultz <john.stultz@linaro.org>
kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
Daniel Latypov <dlatypov@google.com>
kunit: tool: fix unit test cleanup handling
AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/8xx: Fix software emulation interrupt
Nathan Lynch <nathanl@linux.ibm.com>
powerpc/pseries/dlpar: handle ibm, configure-connector delay status
Dan Carpenter <dan.carpenter@oracle.com>
mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
Arnd Bergmann <arnd@arndb.de>
mfd: altera-sysmgr: Fix physical address storing more
Alain Volmat <alain.volmat@foss.st.com>
spi: stm32: properly handle 0 byte transfer
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Correct skb on loopback path
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_recv.c
John Garry <john.garry@huawei.com>
perf vendor events arm64: Fix Ampere eMag event typo
Arnaldo Carvalho de Melo <acme@redhat.com>
perf tools: Fix DSO filtering when not finding a map for a sampled address
David Gow <davidgow@google.com>
rtc: zynqmp: depend on HAS_IOMEM
Steven Rostedt (VMware) <rostedt@goodmis.org>
tracepoint: Do not fail unregistering a probe due to memory failure
Parav Pandit <parav@nvidia.com>
IB/cm: Avoid a loop when device has 255 ports
Parav Pandit <parav@nvidia.com>
IB/mlx5: Return appropriate error code instead of ENOMEM
Douglas Anderson <dianders@chromium.org>
iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Yong Wu <yong.wu@mediatek.com>
iommu: Move iotlb_sync_map out from __iommu_map
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
amba: Fix resource leak for drivers without .remove
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: i2c-qcom-geni: Add shutdown callback for i2c
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Vladimir Murzin <vladimir.murzin@arm.com>
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Takeshi Saito <takeshi.saito.xv@renesas.com>
mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to 128-bytes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: sdhci-sprd: Fix some resource leaks in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: owl-mmc: Fix a resource leak in an error handling path and in the remove function
Pingfan Liu <kernelfans@gmail.com>
powerpc/time: Enable sched clock for irqtime
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/47x: Disable 256k page size
Cédric Le Goater <clg@kaod.org>
KVM: PPC: Make the VMX instruction emulation routines static
Shay Drory <shayd@nvidia.com>
IB/umad: Return EPOLLERR in case of when device disassociated
Shay Drory <shayd@nvidia.com>
IB/umad: Return EIO in case of when device disassociated
Yong Wu <yong.wu@mediatek.com>
iommu: Switch gather->end to the inclusive end
Dan Carpenter <dan.carpenter@oracle.com>
scsi: lpfc: Fix ancient double free
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix ".cold" section suffix check for newer versions of GCC
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix retpoline detection in asm code
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix error handling for STD/CLD warnings
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: ht16k33: Fix refresh rate handling
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
Pan Bian <bianpan2016@163.com>
isofs: release buffer head before return
Hans de Goede <hdegoede@redhat.com>
regulator: core: Avoid debugfs: Directory ... already present! error
Dmitry Osipenko <digetx@gmail.com>
power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Samuel Holland <samuel@sholland.org>
power: supply: axp20x_usb_power: Init work before enabling IRQs
Krzysztof Kozlowski <krzk@kernel.org>
regulator: s5m8767: Drop regulators OF node reference
Pan Bian <bianpan2016@163.com>
spi: atmel: Put allocated master before return
Pan Bian <bianpan2016@163.com>
regulator: s5m8767: Fix reference count leak
David Howells <dhowells@redhat.com>
certs: Fix blacklist flag type confusion
Gabriel Krisman Bertazi <krisman@collabora.com>
watch_queue: Drop references to /dev/watch_queue
Pan Bian <bianpan2016@163.com>
regulator: axp20x: Fix reference cout leak
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix clock divider range on some clocks
Parav Pandit <parav@nvidia.com>
IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
Yishai Hadas <yishaih@nvidia.com>
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Guido Günther <agx@sigxcpu.org>
spi: imx: Don't print error on -EPROBEDEFER
Tom Rix <trix@redhat.com>
clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
Arnd Bergmann <arnd@arndb.de>
clocksource/drivers/ixp4xx: Select TIMER_OF when needed
Randy Dunlap <rdunlap@infradead.org>
power: supply: fix sbs-charger build, needs REGMAP_I2C
Dave Jiang <dave.jiang@intel.com>
dmaengine: idxd: set DMA channel to be private
Bartosz Golaszewski <bgolaszewski@baylibre.com>
rtc: s5m: select REGMAP_I2C
Claudiu Beznea <claudiu.beznea@microchip.com>
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Init wr_cnt as 1
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix missing wr_cqe
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs: Call kobject_put in the failure path
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-clt: Set mininum limit when create QP
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Release lock before call into close_sess
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Extend ibtrs_cq_qp_create
Nicolas Boichat <drinkcat@chromium.org>
of/fdt: Make sure no-map does not remove already reserved regions
KarimAllah Ahmed <karahmed@amazon.de>
fdt: Properly handle "no-map" field in the memory region
Colin Ian King <colin.king@canonical.com>
power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-battery: Fix missing power_supply_put()
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-charger: Fix missing power_supply_put()
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
mfd: bd9571mwv: Use devm_mfd_add_devices()
Ferry Toth <ftoth@exalondelft.nl>
dmaengine: hsu: disable spurious interrupt
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: owl-dma: Fix a resource leak in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in the remove function
Bernard Metzler <bmt@zurich.ibm.com>
RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Randy Dunlap <rdunlap@infradead.org>
HID: core: detect and skip invalid inputs to snto32()
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Fix parent of CBFUSA clock
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Remove non-existent S2 clock
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix CEC clock
Pratyush Yadav <p.yadav@ti.com>
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle master read request
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle only slave interrupts which are enabled
Jan Kara <jack@suse.cz>
quota: Fix memory leak when handling corrupted quota file
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
Po-Hsu Lin <po-hsu.lin@canonical.com>
selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: make "ret" a signed integer
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
Tony Lindgren <tony@atomide.com>
power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
Zhang Qilong <zhangqilong3@huawei.com>
HSI: Fix PM usage counter unbalance in ssi_hw_init
Eric W. Biederman <ebiederm@xmission.com>
capabilities: Don't allow writing ambiguous v3 file capabilities
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
smp: Process pending softirqs in flush_smp_call_function_from_idle()
Geert Uytterhoeven <geert+renesas@glider.be>
irqchip/imx: IMX_INTMUX should not default to y, unconditionally
Wang ShaoBo <bobo.shaobowang@huawei.com>
ubifs: Fix error return code in alloc_wbufs()
Arnd Bergmann <arnd@arndb.de>
ubifs: replay: Fix high stack usage, again
Dinghao Liu <dinghao.liu@zju.edu.cn>
ubifs: Fix memleak in ubifs_init_authentication
Tom Rix <trix@redhat.com>
jffs2: fix use after free in jffs2_sum_write_data()
Colin Ian King <colin.king@canonical.com>
fs/jfs: fix potential integer overflow on shift of a int
Sameer Pujar <spujar@nvidia.com>
ASoC: simple-card-utils: Fix device module clock
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer after kexec syscall
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer on error
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: set status to 0 in case for invalid nsid
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: remove extra variable in identify ns
Keith Busch <kbusch@kernel.org>
nvme-multipath: set nr_zones for zoned namespaces
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix potential race of tcp socket closing accept_work
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
Hao Xu <haoxu@linux.alibaba.com>
io_uring: fix possible deadlock in io_uring_poll
Daniele Alessandrelli <daniele.alessandrelli@intel.com>
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Jan Henrik Weinstock <jan.weinstock@rwth-aachen.de>
hwrng: timeriomem - Fix cooldown period calculation
Imre Deak <imre.deak@intel.com>
drm/dp_mst: Don't cache EDIDs for physical ports
Qinglang Miao <miaoqinglang@huawei.com>
drm/lima: fix reference leak in lima_pm_busy
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Restore cec physical address on reconnect
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix up CEC registers
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix register offset with longer CEC messages
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Move hdmi reset to bind
Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: return EIO when msg retry limit reached
Sean Christopherson <seanjc@google.com>
KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
Qu Wenruo <wqu@suse.com>
btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Zhihao Cheng <chengzhihao1@huawei.com>
btrfs: clarify error returns values in __load_free_space_cache
Hui Wang <hui.wang@canonical.com>
ASoC: SOF: debug: Fix a potential issue on string buffer termination
Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>
ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Jun Nie <jun.nie@linaro.org>
ASoC: qcom: lpass: Fix i2s ctl register bit map
Peter Zijlstra <peterz@infradead.org>
locking/lockdep: Avoid unmatched unlock
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
Yongqiang Niu <yongqiang.niu@mediatek.com>
drm/mediatek: Check if fb is null
Sean Christopherson <seanjc@google.com>
KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Dehe Gu <gudehe@huawei.com>
f2fs: fix a wrong condition in __submit_bio
Dan Carpenter <dan.carpenter@oracle.com>
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
Yi Chen <chenyi77@huawei.com>
f2fs: fix to avoid inconsistent quota data
Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
mtd: parsers: afs: Fix freeing the part name memory in failure
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
ASoC: codecs: add missing max_register in regmap config
Sebastian Reichel <sre@kernel.org>
ASoC: cpcap: fix microphone timeslot mask
Florian Fainelli <f.fainelli@gmail.com>
ata: ahci_brcm: Add back regulators management
Will Deacon <will@kernel.org>
mm: proc: Invalidate TLB after clearing soft-dirty page state
Frantisek Hrbata <frantisek@hrbata.com>
drm/nouveau: bail out of nouveau_channel_new if channel init fails
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Fix ctr(aes) on SEC1
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
Dan Carpenter <dan.carpenter@oracle.com>
mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Move IRQs when migrating context
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix PMU instance naming
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: lpass-cpu: Remove bit clock state check
Chao Yu <chao@kernel.org>
f2fs: compress: fix potential deadlock
Qais Yousef <qais.yousef@arm.com>
sched/eas: Don't update misfit status if the task is pinned
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
Tom Rix <trix@redhat.com>
media: pxa_camera: declare variable when DEBUG is defined
Tom Rix <trix@redhat.com>
media: mtk-vcodec: fix argument used when DEBUG is defined
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: cx25821: Fix a bug when reallocating some dma memory
Luo Meng <luomeng12@huawei.com>
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Dan Carpenter <dan.carpenter@oracle.com>
media: atomisp: Fix a buffer overflow in debug code
Daniel W. S. Almeida <dwlsalmeida@gmail.com>
media: vidtv: psi: fix missing crc for PMT
Joe Perches <joe@perches.com>
media: lmedm04: Fix misuse of comma
Daniel Scally <djrscally@gmail.com>
media: software_node: Fix refcounts in software_node_get_next_child()
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
Finn Thain <fthain@telegraphics.com.au>
macintosh/adb-iop: Use big-endian autopoll mask
Pan Bian <bianpan2016@163.com>
bsg: free the request before return error code
Guchun Chen <guchun.chen@amd.com>
drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
Qinglang Miao <miaoqinglang@huawei.com>
drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
Nathan Chancellor <natechancellor@gmail.com>
MIPS: Compare __SYNC_loongson3_war against 0
Alexander Lobakin <alobakin@pm.me>
MIPS: properly stop .eh_frame generation
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: ti-vpe: cal: fix write to unallocated memory
Rui Miguel Silva <rmfrfs@gmail.com>
media: imx7: csi: Fix pad link validation
Fabio Estevam <festevam@gmail.com>
media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Giulio Benetti <giulio.benetti@micronovasrl.com>
drm/sun4i: tcon: fix inverted DCLK polarity
Xuewen Yan <xuewen.yan@unisoc.com>
sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Jiri Olsa <jolsa@kernel.org>
crypto: bcm - Rename struct device_private to bcm_device_private
Dinghao Liu <dinghao.liu@zju.edu.cn>
evm: Fix memleak in init_desc
Stephan Gerhold <stephan@gerhold.net>
ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Dan Carpenter <dan.carpenter@oracle.com>
ASoC: cs42l56: fix up error handling in probe
Zhang Changzhong <zhangchangzhong@huawei.com>
media: aspeed: fix error return code in aspeed_video_setup_video()
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: tm6000: Fix memleak in tm6000_start_stream
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: media/pci: Fix memleak in empress_init
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: em28xx: Fix use-after-free in em28xx_alloc_urbs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: vsp1: Fix an error handling path in the probe function
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: missing error code in msm_video_register()
Zhang Changzhong <zhangchangzhong@huawei.com>
media: mtk-vcodec: fix error return code in vdec_vp9_decode()
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Fix csc/scaler unregister
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Unregister csc/scaler only if registered
Jacopo Mondi <jacopo@jmondi.org>
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
media: ipu3-cio2: Build only for x86
Simon Ser <contact@emersion.fr>
drm/fourcc: fix Amlogic format modifier masks
Chia-I Wu <olvaffe@gmail.com>
drm/virtio: make sure context is created in gem open
Nathan Chancellor <natechancellor@gmail.com>
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Chancellor <natechancellor@gmail.com>
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
Chenyang Li <lichenyang@loongson.cn>
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Wang Xiaojun <wangxiaojun11@huawei.com>
drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
Qinglang Miao <miaoqinglang@huawei.com>
drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
Marco Elver <elver@google.com>
kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Dan Carpenter <dan.carpenter@oracle.com>
media: allegro: Fix use after free on error
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hwrng: ingenic - Fix a resource leak in an error handling path
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - fix kmap usage
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - linearize buffers content must be kept
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
Guido Günther <agx@sigxcpu.org>
drm/panel: mantix: Tweak init sequence
Chuhong Yuan <hslester96@gmail.com>
drm/fb-helper: Add missed unlocks in setcmap_legacy()
Dan Carpenter <dan.carpenter@oracle.com>
gma500: clean up error handling in init
Jialin Zhang <zhangjialin11@huawei.com>
drm/gma500: Fix error return code in psb_driver_load()
Randy Dunlap <rdunlap@infradead.org>
fbdev: aty: SPARC64 requires FB_ATY_CT
Linus Torvalds <torvalds@linux-foundation.org>
tty: implement read_iter
Linus Torvalds <torvalds@linux-foundation.org>
tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
Vladimir Oltean <vladimir.oltean@nxp.com>
net: enetc: fix destroyed phylink dereference during unbind
Maxime Chevallier <maxime.chevallier@bootlin.com>
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset link when the link never comes back
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: adding LCPLL reset to VSC8514
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: don't deinitialize unused ports
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: perform teardown in reverse order of setup
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: skip send_request_unmap for timeout reset
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: add memory barrier to protect long term buffer
Ilya Leoshkevich <iii@linux.ibm.com>
bpf: Clear subreg_def for global function return values
Colin Ian King <colin.king@canonical.com>
b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
Ayush Sawal <ayush.sawal@chelsio.com>
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Robert Hancock <robert.hancock@calian.com>
net: axienet: Handle deferred probe on clock properly
Eric Dumazet <edumazet@google.com>
tcp: fix SO_RCVLOWAT related hangs under mem pressure
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: fix ACKRX debug message
Jesper Dangaard Brouer <brouer@redhat.com>
bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Jun'ichi Nomura <junichi.nomura@nec.com>
bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Yonghong Song <yhs@fb.com>
bpf: Fix an unitialized value in bpf_iter
Martin KaFai Lau <kafai@fb.com>
libbpf: Ignore non function pointer member in struct_ops
Colin Ian King <colin.king@canonical.com>
mac80211: fix potential overflow when multiplying to u32 integers
Moshe Shemesh <moshe@nvidia.com>
net/mlx5e: Check tunnel offload is required before setting SWP
Oz Shlomo <ozsh@nvidia.com>
net/mlx5e: CT: manage the lifetime of the ct entry object
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for lag devices
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on lag device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on multi port slave device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for multi port slave device
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Replace synchronize_rcu with synchronize_net
Shay Drory <shayd@nvidia.com>
net/mlx5: Fix health error state handling
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Change interrupt moderation channel params also when channels are closed
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Don't change interrupt moderation params when DIM is enabled
Heiner Kallweit <hkallweit1@gmail.com>
net: phy: consider that suspend2ram may cut off PHY power
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: fix memory leak in XDP_REDIRECT
Juergen Gross <jgross@suse.com>
xen/netback: fix spurious event detection for common event case
Vasundhara Volam <vasundhara-v.volam@broadcom.com>
bnxt_en: Fix devlink info's stored fw.psid version format.
Edwin Peer <edwin.peer@broadcom.com>
bnxt_en: reverse order of TX disable and carrier off
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: Set to CLOSED state even on error
Björn Töpel <bjorn.topel@intel.com>
selftests/bpf: Convert test_xdp_redirect.sh to bash
Linus Lüssing <ll@simonwunderlich.de>
ath9k: fix data bus crash when setting nf_override via debugfs
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: set the PNVM again if it was already loaded
Marco Elver <elver@google.com>
bpf_lru_list: Read double-checked variable once without lock
Sara Sharon <sara.sharon@intel.com>
iwlwifi: mvm: don't check if CSA event is running before removing
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: assign SAR table revision to the command later
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: send stored PPAG command instead of local
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: store PPAG enabled/disabled flag properly
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: fix the type we use in the PPAG table validity checks
Jae Hyun Yoo <jae.hyun.yoo@intel.com>
soc: aspeed: snoop: Add clock control logic
Dan Carpenter <dan.carpenter@oracle.com>
ath11k: fix a locking bug in ath11k_mac_op_start()
Anand K Mistry <amistry@google.com>
ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Anand K Mistry <amistry@google.com>
ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
Arnd Bergmann <arnd@arndb.de>
ARM: at91: use proper asm syntax in pm_suspend
Jérôme Pouiller <jerome.pouiller@silabs.com>
staging: wfx: fix possible panic with re-queued frames
Arnd Bergmann <arnd@arndb.de>
optee: simplify i2c access
Arnd Bergmann <arnd@arndb.de>
ARM: s3c: fix fiq for clang IAS
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: set enabled in the PPAG command properly
Artem Lapkin <email2tema@gmail.com>
arm64: dts: meson: fix broken wifi node for Khadas VIM3L
Vincent Knecht <vincent.knecht@mailoo.org>
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Luca Weiss <luca@z3ntu.xyz>
soc: qcom: ocmem: don't return NULL in of_get_ocmem
Jupeng Zhong <zhongjupeng@yulong.com>
Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Dmitry Osipenko <digetx@gmail.com>
opp: Correct debug message in _opp_add_static_v2()
Marek Behún <kabel@kernel.org>
arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to LEDs
Marc Kleine-Budde <mkl@pengutronix.de>
can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Geert Uytterhoeven <geert+renesas@glider.be>
arm64: dts: renesas: beacon: Fix EEPROM compatible value
Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Chen-Yu Tsai <wens@csie.org>
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Make "trimming xfer length" a debug message
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Abort transaction after errors with unknown reason
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Do not update data length if it is 0 on inbound transfers
Tony Lindgren <tony@atomide.com>
ARM: dts: Configure missing thermal interrupt for 4430
Pan Bian <bianpan2016@163.com>
memory: ti-aemif: Drop child node when jumping out loop
Pan Bian <bianpan2016@163.com>
Bluetooth: Put HCI device if inquiry procedure interrupts
Pan Bian <bianpan2016@163.com>
Bluetooth: drop HCI device reference before return
Borislav Petkov <bp@suse.de>
staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
Dan Carpenter <dan.carpenter@oracle.com>
soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
Robert Foss <robert.foss@linaro.org>
arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Jack Pham <jackp@codeaurora.org>
usb: gadget: u_audio: Free requests only after callback
Maximilian Luz <luzmaximilian@gmail.com>
ACPICA: Fix exception code class checks
Chen-Yu Tsai <wens@csie.org>
arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Free resources in error path
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: properly connect USB PHY to port 0
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix call site of scmi_notification_exit
Andrii Nakryiko <andrii@kernel.org>
bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
Andrii Nakryiko <andrii@kernel.org>
bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk transfers on 64-bit builds
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk userdata handling
Dinghao Liu <dinghao.liu@zju.edu.cn>
Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
Zhang Qilong <zhangqilong3@huawei.com>
memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
Christopher William Snowhill <chris@kode54.net>
Bluetooth: Fix initializing response id after clearing struct
Claire Chang <tientzu@chromium.org>
Bluetooth: hci_uart: Fix a race for write_work scheduling
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the probe function
Rakesh Pillai <pillair@codeaurora.org>
ath10k: Fix error handling in case of CE pipe init failure
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: One more flush for Baytrail clear residuals
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Don't call sync_stop if it hasn't been stopped
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Assure sync with the pending stop operation at suspend
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Call sync_stop at disconnection
Eric Biggers <ebiggers@google.com>
random: fix the RNDRESEEDCRNG ioctl
Nathan Chancellor <nathan@kernel.org>
vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
Alexander Lobakin <alobakin@pm.me>
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
Jan Kara <jack@suse.cz>
bfq: Avoid false bfq queue merging
Hans de Goede <hdegoede@redhat.com>
virt: vbox: Do not use wait_event_interruptible when called from kernel context
Ard Biesheuvel <ardb@kernel.org>
PCI: Decline to resize resources if boot config must be preserved
Ansuel Smith <ansuelsmth@gmail.com>
PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ivan Zaentsev <ivan.zaentsev@wirenboard.ru>
w1: w1_therm: Fix conversion result for negative temperatures
Sumit Garg <sumit.garg@linaro.org>
kdb: Make memory allocations more robust
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix mailbox Ch erroneous error
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: docs: Remove notify_ha_event()
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: do not attempt to create a new file before the filesystem is initalized
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: be more robust at handling improper input in debugfs_lookup()
Stefano Garzarella <sgarzare@redhat.com>
vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Nick Desaulniers <ndesaulniers@google.com>
vmlinux.lds.h: add DWARF v5 sections
-------------
Diffstat:
Documentation/admin-guide/perf/arm-cmn.rst | 2 +-
Documentation/admin-guide/sysctl/vm.rst | 10 +-
Documentation/filesystems/seq_file.rst | 6 +
Documentation/scsi/libsas.rst | 1 -
Documentation/security/keys/core.rst | 4 +-
Makefile | 4 +-
arch/arm/boot/compressed/head.S | 4 +-
arch/arm/boot/dts/armada-388-helios4.dts | 28 +-
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/arm/kernel/sys_oabi-compat.c | 15 +
arch/arm/mach-at91/pm_suspend.S | 2 +-
arch/arm/mach-ixp4xx/Kconfig | 1 -
arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9 +-
arch/arm64/Kconfig | 2 +-
.../boot/dts/allwinner/sun50i-a64-pinebook.dts | 5 +-
.../boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 -
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 +-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7 +
.../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7 +-
.../boot/dts/exynos/exynos5433-tm2-common.dtsi | 2 +-
arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +-
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4 +-
.../boot/dts/marvell/armada-3720-turris-mox.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +
.../dts/qcom/msm8916-samsung-a2015-common.dtsi | 6 +
.../boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2 +-
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 9 +-
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 +-
.../boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +-
.../arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4 +-
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 +
arch/arm64/crypto/aes-glue.c | 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/include/asm/module.lds.h | 6 +-
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/head.S | 1 +
arch/arm64/kernel/machine_kexec_file.c | 4 +-
arch/arm64/kernel/probes/uprobes.c | 2 +-
arch/arm64/kernel/ptrace.c | 2 +-
arch/arm64/kernel/suspend.c | 2 +-
arch/csky/kernel/ptrace.c | 2 +-
arch/mips/Makefile | 19 ++
arch/mips/cavium-octeon/setup.c | 9 +-
arch/mips/include/asm/asm.h | 18 ++
arch/mips/include/asm/atomic.h | 2 +-
arch/mips/include/asm/cmpxchg.h | 6 +-
arch/mips/kernel/cpu-probe.c | 15 +-
arch/mips/kernel/vmlinux.lds.S | 2 +-
arch/mips/lantiq/irq.c | 2 +-
arch/mips/loongson64/Platform | 22 --
arch/mips/mm/c-r4k.c | 2 +-
arch/mips/vdso/Makefile | 5 +-
arch/nios2/kernel/entry.S | 3 +
arch/nios2/kernel/sys_nios2.c | 11 +-
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/kexec.h | 1 +
arch/powerpc/include/asm/uaccess.h | 13 +-
arch/powerpc/kernel/entry_32.S | 3 +
arch/powerpc/kernel/head_32.h | 2 +-
arch/powerpc/kernel/head_8xx.S | 2 +-
arch/powerpc/kernel/head_book3s_32.S | 6 -
arch/powerpc/kernel/irq.c | 27 +-
arch/powerpc/kernel/prom_init.c | 12 +-
arch/powerpc/kernel/time.c | 2 +
arch/powerpc/kexec/elf_64.c | 2 +-
arch/powerpc/kexec/file_load_64.c | 35 +++
arch/powerpc/kvm/powerpc.c | 8 +-
arch/powerpc/platforms/pseries/dlpar.c | 7 +-
arch/riscv/kernel/vdso/Makefile | 3 +-
arch/s390/kernel/vtime.c | 3 +-
arch/sparc/Kconfig | 2 +-
arch/sparc/kernel/led.c | 2 +
arch/sparc/lib/memset.S | 1 +
arch/um/include/shared/skas/mm_id.h | 1 +
arch/um/kernel/tlb.c | 19 +-
arch/um/os-Linux/skas/process.c | 4 +
arch/x86/crypto/aesni-intel_glue.c | 28 +-
arch/x86/entry/common.c | 2 +-
arch/x86/include/asm/virtext.h | 17 +-
arch/x86/kernel/msr.c | 7 +
arch/x86/kernel/reboot.c | 30 +-
arch/x86/kvm/emulate.c | 4 +-
arch/x86/kvm/mmu/tdp_mmu.c | 3 +-
arch/x86/kvm/svm/nested.c | 22 +-
arch/x86/kvm/svm/svm.c | 8 +-
arch/x86/mm/fault.c | 27 +-
arch/x86/mm/pat/memtype.c | 4 +-
block/bfq-iosched.c | 1 +
block/blk-settings.c | 12 +
block/bsg.c | 4 +-
block/ioctl.c | 21 +-
certs/blacklist.c | 2 +-
crypto/ecdh_helper.c | 3 +
crypto/michael_mic.c | 31 +-
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/base/swnode.c | 8 +-
drivers/block/floppy.c | 30 +-
drivers/bluetooth/btqcomsmd.c | 27 +-
drivers/bluetooth/btusb.c | 20 +-
drivers/bluetooth/hci_ldisc.c | 41 ++-
drivers/bluetooth/hci_qca.c | 2 +
drivers/bluetooth/hci_serdev.c | 4 +-
drivers/char/hw_random/ingenic-trng.c | 6 +-
drivers/char/hw_random/timeriomem-rng.c | 2 +-
drivers/char/random.c | 2 +-
drivers/char/tpm/tpm.h | 4 -
drivers/char/tpm/tpm_tis_core.c | 50 +--
drivers/clk/clk-ast2600.c | 37 ++-
drivers/clk/clk-divider.c | 9 +-
drivers/clk/meson/clk-pll.c | 10 +-
drivers/clk/qcom/gcc-msm8998.c | 100 +++---
drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +-
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/mxs_timer.c | 5 +-
drivers/cpufreq/acpi-cpufreq.c | 62 +---
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +-
drivers/cpufreq/freq_table.c | 8 +-
drivers/cpufreq/intel_pstate.c | 21 +-
drivers/cpufreq/qcom-cpufreq-hw.c | 40 ++-
.../crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 ++++++----
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2 +
drivers/crypto/bcm/cipher.c | 2 +-
drivers/crypto/bcm/cipher.h | 4 +-
drivers/crypto/bcm/util.c | 2 +-
drivers/crypto/talitos.c | 50 ++-
drivers/crypto/talitos.h | 1 +
drivers/dax/bus.c | 2 +-
drivers/dma/fsldma.c | 6 +
drivers/dma/hsu/pci.c | 21 +-
drivers/dma/idxd/dma.c | 1 +
drivers/dma/owl-dma.c | 1 +
drivers/firmware/arm_scmi/driver.c | 4 +-
drivers/gpio/gpio-pcf857x.c | 2 +-
drivers/gpu/drm/Kconfig | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +-
drivers/gpu/drm/amd/amdgpu/soc15.c | 2 +
.../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2 +-
.../gpu/drm/amd/display/dc/bios/command_table.c | 61 ++++
.../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14 +
.../drm/amd/display/dc/dce/dce_stream_encoder.c | 1 +
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8 +-
.../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1 -
.../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +
.../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 ++
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +-
drivers/gpu/drm/drm_dp_mst_topology.c | 3 +-
drivers/gpu/drm/drm_fb_helper.c | 15 +-
drivers/gpu/drm/drm_modes.c | 4 +-
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +-
drivers/gpu/drm/gma500/psb_drv.c | 2 +
drivers/gpu/drm/i915/display/intel_hdmi.c | 6 +-
drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12 +-
drivers/gpu/drm/lima/lima_sched.c | 2 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8 +
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 8 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 5 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +-
drivers/gpu/drm/msm/msm_drv.c | 3 +-
.../drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 +
drivers/gpu/drm/nouveau/nouveau_chan.c | 1 +
drivers/gpu/drm/nouveau/nouveau_connector.c | 1 +
drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3 +-
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5 +
drivers/gpu/drm/rcar-du/rcar_cmm.c | 2 +-
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 +-
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 +-
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11 +
drivers/gpu/drm/scheduler/sched_main.c | 3 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 +-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/tegra/dc.c | 2 +-
drivers/gpu/drm/tegra/dsi.c | 2 +-
drivers/gpu/drm/tegra/hdmi.c | 2 +-
drivers/gpu/drm/tegra/hub.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 2 +-
drivers/gpu/drm/tegra/vic.c | 2 +-
drivers/gpu/drm/vc4/vc4_hdmi.c | 87 +++--
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +-
drivers/gpu/drm/virtio/virtgpu_gem.c | 8 +-
drivers/hid/hid-core.c | 3 +
drivers/hid/hid-logitech-dj.c | 1 +
drivers/hid/wacom_wac.c | 7 +-
drivers/hsi/controllers/omap_ssi_core.c | 2 +-
drivers/hv/channel_mgmt.c | 3 +-
drivers/hwtracing/coresight/coresight-etm4x-core.c | 21 +-
.../hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +-
drivers/i2c/busses/i2c-bcm-iproc.c | 231 +++++++++++---
drivers/i2c/busses/i2c-brcmstb.c | 2 +-
drivers/i2c/busses/i2c-exynos5.c | 8 +-
drivers/i2c/busses/i2c-qcom-geni.c | 93 +++++-
drivers/ide/falconide.c | 3 +-
drivers/infiniband/core/cm.c | 8 +-
drivers/infiniband/core/cma.c | 70 +++--
drivers/infiniband/core/user_mad.c | 17 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 2 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 8 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 3 +-
drivers/infiniband/hw/mlx5/devx.c | 4 +-
drivers/infiniband/hw/mlx5/main.c | 14 +-
drivers/infiniband/sw/rxe/rxe_net.c | 5 +
drivers/infiniband/sw/rxe/rxe_recv.c | 27 +-
drivers/infiniband/sw/siw/siw.h | 2 +-
drivers/infiniband/sw/siw/siw_main.c | 2 +-
drivers/infiniband/sw/siw/siw_qp.c | 271 ++++++++--------
drivers/infiniband/sw/siw/siw_qp_rx.c | 26 +-
drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +-
drivers/infiniband/sw/siw/siw_verbs.c | 20 +-
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2 +
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51 +--
drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1 +
drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 117 ++++---
drivers/infiniband/ulp/rtrs/rtrs.c | 14 +-
drivers/input/joydev.c | 7 +-
drivers/input/joystick/xpad.c | 1 +
drivers/input/serio/i8042-x86ia64io.h | 4 +
drivers/input/serio/serport.c | 4 +-
drivers/input/touchscreen/elo.c | 4 +-
drivers/input/touchscreen/raydium_i2c_ts.c | 3 +-
drivers/input/touchscreen/sur40.c | 1 +
drivers/input/touchscreen/zinitix.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 +
drivers/iommu/iommu.c | 23 +-
drivers/iommu/mtk_iommu.c | 2 +-
drivers/irqchip/Kconfig | 3 +-
drivers/irqchip/irq-loongson-pch-msi.c | 2 +-
drivers/macintosh/adb-iop.c | 6 +-
drivers/mailbox/sprd-mailbox.c | 2 +-
drivers/md/bcache/bcache.h | 3 +
drivers/md/bcache/btree.c | 21 +-
drivers/md/bcache/journal.c | 4 +-
drivers/md/bcache/super.c | 20 ++
drivers/md/dm-core.h | 4 +
drivers/md/dm-crypt.c | 1 +
drivers/md/dm-era-target.c | 93 ++++--
drivers/md/dm-table.c | 168 +++++-----
drivers/md/dm-writecache.c | 74 +++--
drivers/md/dm.c | 62 +++-
drivers/md/dm.h | 2 +-
drivers/media/i2c/max9286.c | 2 +-
drivers/media/i2c/ov5670.c | 3 +-
drivers/media/pci/cx25821/cx25821-core.c | 4 +-
drivers/media/pci/intel/ipu3/Kconfig | 3 +-
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +-
drivers/media/pci/saa7134/saa7134-empress.c | 5 +-
drivers/media/pci/smipcie/smipcie-ir.c | 46 +--
drivers/media/platform/aspeed-video.c | 6 +-
drivers/media/platform/marvell-ccic/mcam-core.c | 2 +
.../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 +-
.../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3 +-
drivers/media/platform/pxa_camera.c | 3 +
drivers/media/platform/qcom/camss/camss-video.c | 1 +
drivers/media/platform/ti-vpe/cal.c | 4 +-
drivers/media/platform/vsp1/vsp1_drv.c | 4 +-
drivers/media/rc/ir_toy.c | 1 +
drivers/media/rc/mceusb.c | 2 +-
drivers/media/test-drivers/vidtv/vidtv_psi.c | 5 +-
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/mtk-smi.c | 4 +-
drivers/memory/ti-aemif.c | 8 +-
drivers/mfd/altera-sysmgr.c | 3 +-
drivers/mfd/bd9571mwv.c | 6 +-
drivers/mfd/gateworks-gsc.c | 2 +-
drivers/mfd/wm831x-auxadc.c | 3 +-
drivers/misc/cardreader/rts5227.c | 5 +
drivers/misc/eeprom/eeprom_93xx46.c | 1 +
drivers/misc/fastrpc.c | 7 +-
drivers/misc/mei/hbm.c | 2 +-
drivers/misc/mei/hw-me-regs.h | 5 +
drivers/misc/mei/interrupt.c | 33 +-
drivers/misc/mei/pci-me.c | 5 +
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +-
drivers/mmc/host/owl-mmc.c | 9 +-
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +-
drivers/mmc/host/sdhci-esdhc-imx.c | 3 +-
drivers/mmc/host/sdhci-pci-o2micro.c | 20 ++
drivers/mmc/host/sdhci-sprd.c | 6 +-
drivers/mmc/host/usdhi6rol0.c | 4 +-
drivers/mtd/parsers/afs.c | 4 +-
drivers/mtd/parsers/parser_imagetag.c | 4 +
drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4 +-
drivers/mtd/spi-nor/core.c | 10 +-
drivers/mtd/spi-nor/sfdp.c | 5 +-
drivers/net/Kconfig | 2 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +-
drivers/net/dsa/ocelot/felix.c | 16 +-
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 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +-
.../chelsio/inline_crypto/chtls/chtls_cm.h | 3 -
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14 +-
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
drivers/net/ethernet/ibm/ibmvnic.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 50 +--
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 +-
drivers/net/ethernet/intel/ice/ice.h | 2 -
drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6 +-
drivers/net/ethernet/intel/ice/ice_ethtool.c | 34 +-
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33 +-
drivers/net/ethernet/marvell/mvneta.c | 9 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2 +-
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9 +
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 +++++++++++----
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2 +-
.../mellanox/mlx5/core/en_accel/en_accel.h | 2 +-
.../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66 ++--
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8 +-
drivers/net/ethernet/mellanox/mlx5/core/health.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 +-
drivers/net/ethernet/realtek/r8169_main.c | 4 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 +-
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26 +-
drivers/net/gtp.c | 1 -
drivers/net/phy/mscc/mscc.h | 8 +
drivers/net/phy/mscc/mscc_main.c | 350 ++++++++++++++-------
drivers/net/phy/phy_device.c | 53 +---
drivers/net/ppp/ppp_async.c | 3 +-
drivers/net/ppp/ppp_synctty.c | 3 +-
drivers/net/vxlan.c | 11 +-
drivers/net/wireguard/device.c | 19 +-
drivers/net/wireguard/device.h | 15 +-
drivers/net/wireguard/peer.c | 28 +-
drivers/net/wireguard/peer.h | 4 +-
drivers/net/wireguard/queueing.c | 86 ++++-
drivers/net/wireguard/queueing.h | 45 ++-
drivers/net/wireguard/receive.c | 16 +-
drivers/net/wireguard/send.c | 31 +-
drivers/net/wireless/ath/ath10k/mac.c | 2 +
drivers/net/wireless/ath/ath10k/snoc.c | 5 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +
drivers/net/wireless/ath/ath11k/mac.c | 11 +-
drivers/net/wireless/ath/ath9k/debug.c | 5 +-
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43 ++-
.../net/wireless/intel/iwlwifi/mvm/time-event.c | 3 -
.../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21 +-
drivers/net/xen-netback/interface.c | 8 +-
drivers/nvme/host/multipath.c | 4 +
drivers/nvme/target/admin-cmd.c | 33 +-
drivers/nvme/target/tcp.c | 59 +++-
drivers/nvmem/core.c | 5 +-
drivers/nvmem/qcom-spmi-sdam.c | 7 +-
drivers/of/fdt.c | 12 +-
drivers/opp/of.c | 4 +-
drivers/pci/controller/cadence/pcie-cadence-host.c | 5 +-
drivers/pci/controller/dwc/pcie-qcom.c | 4 +-
drivers/pci/controller/pcie-rcar-host.c | 2 +-
drivers/pci/controller/pcie-rockchip.c | 12 +-
drivers/pci/controller/pcie-xilinx-cpm.c | 1 +
drivers/pci/pci-bridge-emul.c | 11 +-
drivers/pci/setup-res.c | 6 +
drivers/pci/syscall.c | 10 +-
drivers/perf/arm-cmn.c | 17 +-
drivers/phy/Kconfig | 1 +
drivers/phy/cadence/phy-cadence-torrent.c | 1 +
drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10 +-
drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +-
drivers/platform/chrome/cros_ec_proto.c | 12 +-
drivers/power/reset/at91-sama5d2_shdwc.c | 2 +-
drivers/power/supply/Kconfig | 1 +
drivers/power/supply/axp20x_usb_power.c | 2 +-
drivers/power/supply/cpcap-battery.c | 12 +-
drivers/power/supply/cpcap-charger.c | 4 +-
drivers/power/supply/smb347-charger.c | 12 +-
drivers/pwm/pwm-iqs620a.c | 8 +-
drivers/pwm/pwm-rockchip.c | 18 +-
drivers/regulator/axp20x-regulator.c | 7 +-
drivers/regulator/core.c | 6 +-
drivers/regulator/qcom-rpmh-regulator.c | 26 ++
drivers/regulator/rohm-regulator.c | 9 +-
drivers/regulator/s5m8767.c | 15 +-
drivers/remoteproc/mtk_common.h | 1 +
drivers/remoteproc/mtk_scp.c | 20 +-
drivers/rtc/Kconfig | 3 +-
drivers/s390/crypto/zcrypt_api.c | 14 +
drivers/s390/virtio/virtio_ccw.c | 4 +-
drivers/scsi/bnx2fc/Kconfig | 1 +
drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +-
drivers/scsi/qla2xxx/qla_dbg.c | 1 +
drivers/scsi/qla2xxx/qla_mbx.c | 3 +-
drivers/scsi/sd.c | 6 +-
drivers/scsi/sd_zbc.c | 6 +-
drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +-
drivers/soc/qcom/ocmem.c | 8 +-
drivers/soc/qcom/socinfo.c | 2 +-
drivers/soc/samsung/exynos-asv.c | 18 +-
drivers/soc/ti/pm33xx.c | 5 +-
drivers/soundwire/bus.c | 47 ++-
drivers/soundwire/cadence_master.c | 8 +-
drivers/soundwire/debugfs.c | 2 +-
drivers/soundwire/intel_init.c | 3 +-
drivers/spi/spi-atmel.c | 2 +-
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-dw-bt1.c | 2 +-
drivers/spi/spi-fsl-spi.c | 2 +-
drivers/spi/spi-imx.c | 2 +-
drivers/spi/spi-pxa2xx-pci.c | 27 +-
drivers/spi/spi-stm32.c | 4 +
drivers/spi/spi-synquacer.c | 4 +
drivers/spi/spi.c | 2 +-
drivers/spmi/spmi-pmic-arb.c | 5 +-
drivers/staging/gdm724x/gdm_usb.c | 10 +-
drivers/staging/media/allegro-dvt/allegro-core.c | 3 +-
drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24 +-
drivers/staging/media/atomisp/pci/hmm/hmm.c | 2 +-
drivers/staging/media/imx/imx-media-csc-scaler.c | 4 -
drivers/staging/media/imx/imx-media-dev.c | 7 +-
drivers/staging/media/imx/imx7-media-csi.c | 27 +-
drivers/staging/mt7621-dma/Makefile | 2 +-
.../mt7621-dma/{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 +-
.../vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 +-
drivers/staging/wfx/data_tx.c | 10 +-
drivers/staging/wfx/data_tx.h | 1 +
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-
drivers/tee/optee/rpc.c | 31 +-
drivers/thermal/cpufreq_cooling.c | 2 +-
drivers/tty/n_gsm.c | 3 +-
drivers/tty/n_hdlc.c | 60 ++--
drivers/tty/n_null.c | 3 +-
drivers/tty/n_r3964.c | 10 +-
drivers/tty/n_tracerouter.c | 4 +-
drivers/tty/n_tracesink.c | 4 +-
drivers/tty/n_tty.c | 82 ++---
drivers/tty/tty_io.c | 82 ++++-
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/usb/serial/pl2303.c | 8 +-
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
drivers/vfio/pci/vfio_pci_zdev.c | 4 +
drivers/vfio/vfio_iommu_type1.c | 63 ++--
drivers/video/fbdev/Kconfig | 2 +-
drivers/virt/vboxguest/vboxguest_utils.c | 18 +-
drivers/w1/slaves/w1_therm.c | 22 +-
drivers/watchdog/intel-mid_wdt.c | 8 +-
drivers/watchdog/mei_wdt.c | 1 +
drivers/watchdog/qcom-wdt.c | 13 +-
fs/affs/namei.c | 4 +-
fs/btrfs/backref.c | 9 +-
fs/btrfs/backref.h | 9 +-
fs/btrfs/block-group.c | 29 +-
fs/btrfs/ctree.c | 7 +-
fs/btrfs/delayed-ref.c | 56 ++--
fs/btrfs/delayed-ref.h | 16 +-
fs/btrfs/extent-tree.c | 128 ++------
fs/btrfs/free-space-cache.c | 6 +-
fs/btrfs/inode.c | 3 +-
fs/btrfs/relocation.c | 4 +-
fs/btrfs/space-info.h | 17 +
fs/ceph/caps.c | 10 +-
fs/debugfs/inode.c | 5 +-
fs/erofs/xattr.c | 10 +-
fs/erofs/zmap.c | 10 +-
fs/eventpoll.c | 4 +-
fs/exfat/exfat_raw.h | 4 +
fs/exfat/super.c | 31 +-
fs/ext4/Kconfig | 3 +-
fs/ext4/namei.c | 7 +-
fs/f2fs/compress.c | 5 +-
fs/f2fs/data.c | 12 +-
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 24 +-
fs/f2fs/inline.c | 4 +
fs/f2fs/super.c | 3 +
fs/gfs2/bmap.c | 6 +-
fs/gfs2/lock_dlm.c | 8 +-
fs/gfs2/recovery.c | 4 +-
fs/gfs2/util.c | 16 +-
fs/io_uring.c | 17 +-
fs/isofs/dir.c | 1 +
fs/isofs/namei.c | 1 +
fs/jffs2/summary.c | 3 +
fs/jfs/jfs_dmap.c | 2 +-
fs/nfs/nfs4proc.c | 15 +-
fs/nfsd/nfsctl.c | 14 +-
fs/ocfs2/cluster/heartbeat.c | 8 +-
fs/proc/proc_sysctl.c | 4 +-
fs/proc/self.c | 2 +-
fs/proc/task_mmu.c | 9 +-
fs/proc/thread_self.c | 7 +
fs/pstore/platform.c | 4 +-
fs/quota/quota_v2.c | 11 +-
fs/ubifs/auth.c | 2 +-
fs/ubifs/replay.c | 4 +-
fs/ubifs/super.c | 4 +-
fs/zonefs/super.c | 3 +
include/acpi/acexcep.h | 10 +-
include/asm-generic/vmlinux.lds.h | 16 +-
include/linux/bpf.h | 3 +
include/linux/device-mapper.h | 5 +
include/linux/eventpoll.h | 2 +-
include/linux/filter.h | 2 +-
include/linux/icmpv6.h | 28 +-
include/linux/iommu.h | 4 +-
include/linux/ipv6.h | 1 -
include/linux/kexec.h | 5 +
include/linux/key.h | 1 +
include/linux/kgdb.h | 2 +
include/linux/khugepaged.h | 2 +
include/linux/memremap.h | 6 +
include/linux/mfd/rohm-generic.h | 14 +-
include/linux/rcupdate.h | 2 +
include/linux/rmap.h | 3 +-
include/linux/soundwire/sdw.h | 2 +
include/linux/tpm.h | 5 +-
include/linux/tty_ldisc.h | 3 +-
include/net/act_api.h | 6 +-
include/net/icmp.h | 6 +-
include/net/tcp.h | 9 +-
include/uapi/drm/drm_fourcc.h | 4 +-
init/Kconfig | 11 +
init/main.c | 1 +
kernel/Makefile | 2 +-
kernel/bpf/bpf_iter.c | 2 +-
kernel/bpf/bpf_lru_list.c | 7 +-
kernel/bpf/devmap.c | 4 +-
kernel/bpf/verifier.c | 3 +-
kernel/debug/debug_core.c | 11 +
kernel/debug/kdb/kdb_private.h | 2 +-
kernel/kcsan/core.c | 26 +-
kernel/kexec_file.c | 5 +
kernel/kprobes.c | 31 +-
kernel/locking/lockdep.c | 3 +-
kernel/module.c | 21 +-
kernel/printk/printk.c | 28 +-
kernel/printk/printk_safe.c | 16 +-
kernel/rcu/tree.c | 8 +-
kernel/rcu/tree_plugin.h | 5 +
kernel/sched/fair.c | 45 ++-
kernel/sched/idle.c | 1 +
kernel/seccomp.c | 2 +
kernel/smp.c | 4 +
kernel/tracepoint.c | 80 ++++-
mm/compaction.c | 43 +--
mm/hugetlb.c | 14 +-
mm/khugepaged.c | 22 +-
mm/memcontrol.c | 30 +-
mm/memory-failure.c | 6 +
mm/memory.c | 16 +-
mm/memremap.c | 15 +
mm/slab_common.c | 4 +-
mm/slub.c | 8 +-
mm/vmscan.c | 9 +-
net/bluetooth/a2mp.c | 3 +-
net/bluetooth/hci_core.c | 6 +-
net/core/filter.c | 13 +-
net/ipv4/icmp.c | 5 +-
net/ipv6/icmp.c | 18 +-
net/ipv6/ip6_icmp.c | 12 +-
net/mac80211/mesh_hwmp.c | 2 +-
net/nfc/nci/uart.c | 3 +-
net/qrtr/tun.c | 12 +-
net/sched/act_api.c | 106 ++++---
net/sched/cls_api.c | 12 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 6 +-
samples/Kconfig | 2 +-
samples/watch_queue/watch_test.c | 2 +-
security/commoncap.c | 12 +-
security/integrity/evm/evm_crypto.c | 7 +-
security/integrity/ima/ima_kexec.c | 3 +
security/integrity/ima/ima_mok.c | 5 +-
security/keys/Kconfig | 8 +-
security/keys/key.c | 2 +
security/keys/trusted-keys/trusted_tpm1.c | 22 +-
security/keys/trusted-keys/trusted_tpm2.c | 22 +-
security/selinux/hooks.c | 4 +
sound/core/init.c | 4 +
sound/core/pcm.c | 4 +
sound/core/pcm_local.h | 1 +
sound/core/pcm_native.c | 27 +-
sound/firewire/fireface/ff-protocol-latter.c | 118 +++++--
sound/pci/hda/hda_intel.c | 2 +
sound/pci/hda/patch_hdmi.c | 1 -
sound/pci/hda/patch_realtek.c | 40 +++
sound/soc/codecs/cpcap.c | 12 +-
sound/soc/codecs/cs42l56.c | 3 +-
sound/soc/codecs/rt5682-i2c.c | 3 +
sound/soc/codecs/wsa881x.c | 1 +
sound/soc/generic/simple-card-utils.c | 13 +-
sound/soc/intel/boards/sof_sdw.c | 6 +-
sound/soc/qcom/lpass-apq8016.c | 2 +-
sound/soc/qcom/lpass-cpu.c | 30 +-
sound/soc/qcom/lpass-lpaif-reg.h | 3 -
sound/soc/qcom/lpass.h | 1 -
sound/soc/qcom/qdsp6/q6asm-dai.c | 21 ++
sound/soc/qcom/qdsp6/q6routing.c | 18 --
sound/soc/sh/siu.h | 2 +-
sound/soc/sh/siu_pcm.c | 2 +-
sound/soc/sof/debug.c | 2 +-
sound/soc/sof/intel/hda-dsp.c | 4 +
sound/soc/sof/sof-pci-dev.c | 7 +
sound/usb/pcm.c | 2 +-
tools/lib/bpf/libbpf.c | 22 +-
tools/objtool/arch/x86/special.c | 2 +-
tools/objtool/check.c | 15 +-
tools/objtool/check.h | 11 +
tools/perf/builtin-record.c | 2 +-
.../pmu-events/arch/arm64/ampere/emag/cache.json | 2 +-
tools/perf/tests/sample-parsing.c | 2 +-
tools/perf/util/event.c | 2 +
tools/perf/util/evlist.c | 8 +
tools/perf/util/evlist.h | 4 +
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 41 ++-
.../perf/util/intel-pt-decoder/intel-pt-decoder.h | 2 +
tools/perf/util/intel-pt.c | 29 +-
tools/perf/util/symbol.c | 7 +-
tools/testing/kunit/kunit_tool_test.py | 14 +-
tools/testing/selftests/bpf/test_xdp_redirect.sh | 10 +-
tools/testing/selftests/dmabuf-heaps/Makefile | 2 +-
.../trigger-synthetic_event_syntax_errors.tc | 35 ++-
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 +-
tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +-
tools/testing/selftests/seccomp/seccomp_bpf.c | 2 +-
tools/testing/selftests/wireguard/netns.sh | 15 +-
666 files changed, 5764 insertions(+), 3013 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.11 000/773] 5.11.3-rc3 review
@ 2021-03-02 19:29 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-02 19:29 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.11.3 release.
There are 773 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 04 Mar 2021 19:25:07 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.3-rc3.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.11.3-rc3
Cong Wang <cong.wang@bytedance.com>
net_sched: fix RTNL deadlock again caused by request_module()
Takeshi Misawa <jeliantsurux@gmail.com>
net: qrtr: Fix memory leak in qrtr_tun_open
Vlad Buslov <vladbu@nvidia.com>
net: sched: fix police ext initialization
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: get rid of per-peer ring buffers
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: selftests: test multiple parallel streams
Jason A. Donenfeld <Jason@zx2c4.com>
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Leon Romanovsky <leon@kernel.org>
ipv6: silence compilation warning for non-IPV6 builds
Sumit Garg <sumit.garg@linaro.org>
kgdb: fix to kill breakpoints on initmem after boot
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/i915: Reject 446-480MHz HDMI clock on GLK
Nikos Tsironis <ntsironis@arrikto.com>
dm era: only resize metadata in preresume
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Reinitialize bitset cache before digesting a new writeset
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Use correct value size in equality function of writeset tree
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Fix bitset memory leaks
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Verify the data block size hasn't changed
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Update in-core bitset after committing the metadata
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Recover committed writeset after crash
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix writing beyond end of underlying device when shrinking
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: return the exact table values that were set
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix performance degradation in ssd mode
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix zoned iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix DAX iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix iterate_devices based device capability checks
Mikulas Patocka <mpatocka@redhat.com>
dm: fix deadlock when swapping to encrypted device
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Lock imbalance on error path in gfs2_recover_one
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't skip dlm unlock if glock has an lvb
Bob Peterson <rpeterso@redhat.com>
gfs2: fix glock confusion in function signal_our_withdraw
Masahisa Kojima <masahisa.kojima@linaro.org>
spi: spi-synquacer: fix set_cs handling
Rasmus Villemoes <rasmus.villemoes@prevas.dk>
spi: fsl: invert spisel_boot signal on MPC8309
Paul Cercueil <paul@crapouillou.net>
perf stat: Use nftw() instead of ftw()
Al Viro <viro@zeniv.linux.org.uk>
sparc32: fix a user-triggerable oops in clear_user()
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: fix handling of escaped ',' in the password mount argument
Paulo Alcantara <pc@cjr.nz>
cifs: fix nodfs mount option
Paulo Alcantara <pc@cjr.nz>
cifs: introduce helper for finding referral server to improve DFS target resolution
Paulo Alcantara <pc@cjr.nz>
cifs: check all path components in resolved dfs target
Paulo Alcantara <pc@cjr.nz>
cifs: fix DFS failover
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: flush data when enabling checkpoint back
Chao Yu <chao@kernel.org>
f2fs: enforce the immutable flag on open files
Chao Yu <chao@kernel.org>
f2fs: fix out-of-repair __setattr_copy()
Huacai Chen <chenhuacai@kernel.org>
irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Johannes Berg <johannes.berg@intel.com>
um: defer killing userspace on page table update failures
Johannes Berg <johannes.berg@intel.com>
um: mm: check more comprehensively for stub changes
Cornelia Huck <cohuck@redhat.com>
virtio/s390: implement virtio-ccw revision 2 correctly
Heiko Carstens <hca@linux.ibm.com>
s390/vtime: fix inline assembly clobber list
Jens Axboe <axboe@kernel.dk>
proc: don't allow async path resolution of /proc/thread-self components
Chen Yu <yu.c.chen@intel.com>
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Shawn Guo <shawn.guo@linaro.org>
cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Viresh Kumar <viresh.kumar@linaro.org>
thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Chris Wilson <chris@chris-wilson.co.uk>
kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
zonefs: Fix file size of zones in full condition
Namjae Jeon <namjae.jeon@samsung.com>
exfat: fix shift-out-of-bounds in exfat_fill_super()
Muchun Song <songmuchun@bytedance.com>
printk: fix deadlock when kernel panic
Tim Harvey <tharvey@gateworks.com>
mfd: gateworks-gsc: Fix interrupt type
Maxim Kiselev <bigunclemax@gmail.com>
gpio: pcf857x: Fix missing first interrupt
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point LP DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point S DID
Tomas Winkler <tomas.winkler@intel.com>
mei: me: emmitsburg workstation DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: fix transfer over dma with extended header
Alexander Usyskin <alexander.usyskin@intel.com>
mei: bus: block send with vtag on non-conformat FW
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
spmi: spmi-pmic-arb: Fix hw_irq overflow
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32s: Add missing call to kuep_lock on syscall entry
Hari Bathini <hbathini@linux.ibm.com>
powerpc/kexec_file: fix FDT size estimation for kdump kernel
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
Shirley Her <shirley.her@bayhubtech.com>
mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Frank Li <Frank.Li@nxp.com>
mmc: sdhci-esdhc-imx: fix kernel panic when remove module
Fangrui Song <maskray@google.com>
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
Paolo Bonzini <pbonzini@redhat.com>
KVM: nSVM: fix running nested guests when npt=0
Vlastimil Babka <vbabka@suse.cz>
mm, compaction: make fast_isolate_freepages() stay within zone
Dave Hansen <dave.hansen@linux.intel.com>
mm/vmscan: restore zone_reclaim_mode ABI
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix update_and_free_page contig page struct assumption
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix get_active_memcg return value
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix swap undercounting in cgroup2
NeilBrown <neilb@suse.de>
x86: fix seq_file iteration for pat/memtype.c
NeilBrown <neilb@suse.de>
seq_file: document how per-entry resources are managed.
Pan Bian <bianpan2016@163.com>
fs/affs: release old buffer head on error path
Pan Bian <bianpan2016@163.com>
mtd: spi-nor: hisi-sfc: Put child node np on error path
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Add erase size check for erase command initialization
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Fix erase type discovery for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix last erase region marking
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Handle accesses to TRCSTALLCTLR
Alexander Usyskin <alexander.usyskin@intel.com>
watchdog: mei_wdt: request stop on unregister
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Tobias Klauser <tklauser@distanz.ch>
riscv: Disable KSAN_SANITIZE for vDSO
Will Deacon <will@kernel.org>
arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Shaoying Xu <shaoyi@amazon.com>
arm64 module: set plt* section addresses to 0x0
He Zhe <zhe.he@windriver.com>
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
qiuguorui1 <qiuguorui1@huawei.com>
arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
Viresh Kumar <viresh.kumar@linaro.org>
mailbox: arm_mhuv2: Skip calling kfree() with invalid pointer
Isaac J. Manjarres <isaacm@codeaurora.org>
iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Suzuki K Poulose <suzuki.poulose@arm.com>
arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
Masami Hiramatsu <mhiramat@kernel.org>
kprobes: Fix to delay the kprobes jump optimization
Frederic Weisbecker <frederic@kernel.org>
entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
entry: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Trigger self-IPI on late deferred wake up before user resume
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Perform deferred wake up before last idle's need_resched() check
Frederic Weisbecker <frederic@kernel.org>
rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
Cédric Le Goater <clg@kaod.org>
powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Thomas Gleixner <tglx@linutronix.de>
x86/entry: Fix instrumentation annotation
Andy Lutomirski <luto@kernel.org>
x86/fault: Fix AMD erratum #91 errata fixup for user code
Sean Christopherson <seanjc@google.com>
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Christopherson <seanjc@google.com>
x86/virt: Eat faults on VMXOFF in reboot flows
Sean Young <sean@mess.org>
media: smipcie: fix interrupt handling and IR timeout
Lubomir Rintel <lkundrak@v3.sk>
media: marvell-ccic: power up the device on mclk enable
Pavel Machek <pavel@denx.de>
media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
Sean Young <sean@mess.org>
media: ir_toy: add another IR Droid device
Sakari Ailus <sakari.ailus@linux.intel.com>
media: v4l: ioctl: Fix memory leak in video_usercopy
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: i2c: max9286: fix access to unallocated memory
Jiri Kosina <jkosina@suse.cz>
floppy: reintroduce O_NDELAY fix
Martin Kaiser <martin@kaiser.cx>
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Amey Narkhede <ameynarkhede03@gmail.com>
staging: gdm724x: Fix DMA from stack
Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Dinh Nguyen <dinguyen@kernel.org>
arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Frank Wunderlich <frank-w@public-files.de>
dts64: mt7622: fix slow sd card access
Jiri Bohac <jbohac@suse.cz>
pstore: Fix typo in compression option name
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Ricky Wu <ricky_wu@realtek.com>
misc: rtsx: init of rts522a add OCP power off when no card is present
Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Paul Cercueil <paul@crapouillou.net>
seccomp: Add missing return in non-void function
Krzysztof Kozlowski <krzk@kernel.org>
soc: samsung: exynos-asv: handle reading revision register error
Marek Szyprowski <m.szyprowski@samsung.com>
soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - initialize need_fallback
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - handle BigEndian for cipher
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - IV register does not work on A10 and A13
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - checking sg length is not sufficient
Ard Biesheuvel <ardb@kernel.org>
crypto: michael_mic - fix broken misalignment handling
Ard Biesheuvel <ardb@kernel.org>
crypto: aesni - prevent misaligned buffers on the stack
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/sha - add missing module aliases
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Correct surface base address for renderclear
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Flush before changing register state
Filipe Manana <fdmanana@suse.com>
btrfs: fix extent buffer leak on failure to copy root
Josef Bacik <josef@toxicpanda.com>
btrfs: account for new extents being deleted in total_bytes_pinned
Josef Bacik <josef@toxicpanda.com>
btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
Josef Bacik <josef@toxicpanda.com>
btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
Josef Bacik <josef@toxicpanda.com>
btrfs: fix reloc root leak with 0 ref reloc roots on recovery
Josef Bacik <josef@toxicpanda.com>
btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
Josef Bacik <josef@toxicpanda.com>
btrfs: add asserts for deleting backref cache nodes
Josef Bacik <josef@toxicpanda.com>
btrfs: do not warn if we can't find the reloc root when looking up backref
Josef Bacik <josef@toxicpanda.com>
btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Reserve TPM for seal and unseal operations
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix migratable=1 failing
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix incorrect handling of tpm_get_random()
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Clean up locality release
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Fix check_locality for correct locality acquisition
Gao Xiang <hsiangkao@redhat.com>
erofs: initialized fields can only be observed after bit is set
Amir Goldstein <amir73il@gmail.com>
selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Takashi Iwai <tiwai@suse.de>
ASoC: siu: Fix build error by a wrong const prefix
Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
drm/rockchip: Require the YTR modifier for AFBC
Heiko Stuebner <heiko@sntech.de>
drm/panel: kd35t133: allow using non-continuous dsi clock
Andrey Grodzovsky <andrey.grodzovsky@amd.com>
drm/sched: Cancel and flush all outstanding jobs before finish.
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/modes: Switch to 64bit maths to avoid integer overflow
Karol Herbst <kherbst@redhat.com>
drm/nouveau/kms: handle mDP connectors
xinhui pan <xinhui.pan@amd.com>
drm/ttm: Fix a memory leak
Prike Liang <Prike.Liang@amd.com>
drm/amdgpu: fix shutdown and poweroff process failed with s0ix
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Marek Olšák <marek.olsak@amd.com>
drm/amdgpu: fix CGTS_TCC_DISABLE register offset on gfx10.3
Felix Kuehling <Felix.Kuehling@amd.com>
drm/amdkfd: Fix recursive lock warnings
Anson Jacob <Anson.Jacob@amd.com>
Revert "drm/amd/display: reuse current context instead of recreating one"
Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Eric Bernstein <eric.bernstein@amd.com>
drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Jan Kokemüller <jan.kokemueller@gmail.com>
drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Alex Deucher <alexander.deucher@amd.com>
Revert "drm/amd/display: Update NV1x SR latency values"
Kai Krakow <kai@kaishome.de>
bcache: Move journal work to new flush wq
Kai Krakow <kai@kaishome.de>
bcache: Give btree_io_wq correct semantics again
Kai Krakow <kai@kaishome.de>
Revert "bcache: Kill btree_io_wq"
Alexander Lobakin <alobakin@pm.me>
MIPS: compressed: fix build with enabled UBSAN
Kevin Hao <haokexin@gmail.com>
Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Nathan Chancellor <nathan@kernel.org>
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
Aurelien Jarno <aurelien@aurel32.net>
MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Paul Cercueil <paul@crapouillou.net>
MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
Takashi Iwai <tiwai@suse.de>
ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
PeiSen Hou <pshou@realtek.com>
ALSA: hda/realtek: modify EAPD in the ALC886
Takashi Iwai <tiwai@suse.de>
ALSA: hda/hdmi: Drop bogus check at closing a stream
Kai Vehmanen <kai.vehmanen@linux.intel.com>
ALSA: hda: Add another CometLake-H PCI ID
Takashi Sakamoto <o-takashi@sakamocchi.jp>
ALSA: fireface: fix to parse sync status register of latter protocol
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Add implicit fb quirk for BOSS GP-10
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Don't avoid stopping the stream at disconnection
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: More strict state change in EP
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Handle invalid running state at releasing EP
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Correct document for snd_usb_endpoint_free_all()
Mathias Kresin <dev@kresin.me>
phy: lantiq: rcu-usb2: wait after clock enable
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7720: fix error code in mos7720_write()
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7840: fix error code in mos7840_write()
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix line-speed handling on newer chips
Johan Hovold <johan@kernel.org>
USB: serial: ftdi_sio: fix FTX sub-integer prescaler
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
Paul Cercueil <paul@crapouillou.net>
usb: musb: Fix runtime PM race in musb_queue_resume_work
Lech Perczak <lech.perczak@gmail.com>
USB: serial: option: update interface mapping for ZTE P685M
James Reynolds <jr@memlen.com>
media: mceusb: Fix potential out-of-bounds shift
Marcos Paulo de Souza <mpdesouza@suse.com>
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Dan Carpenter <dan.carpenter@oracle.com>
Input: joydev - prevent potential read overflow in ioctl
Olivier Crête <olivier.crete@ocrete.ca>
Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
jeffrey.lin <jeffrey.lin@rad-ic.com>
Input: raydium_ts_i2c - do not send zero length
Jason Gerecke <killertofu@gmail.com>
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Filipe Laíns <lains@riseup.net>
HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
Qinglang Miao <miaoqinglang@huawei.com>
ACPI: configfs: add missing check after configfs_register_default_group()
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: property: Fix fwnode string properties matching
Marcin Ślusarz <marcin.slusarz@intel.com>
soundwire: intel: fix possible crash when no device is detected
Mikulas Patocka <mpatocka@redhat.com>
blk-settings: align max_sectors on "logical_block_size" boundary
Bart Van Assche <bvanassche@acm.org>
scsi: sd: Fix Opal support
Finn Thain <fthain@telegraphics.com.au>
ide/falconide: Fix module unload
Ming Lei <ming.lei@redhat.com>
block: fix logging on capacity change
Christoph Hellwig <hch@lst.de>
block: reopen the device in blkdev_reread_part
Johannes Thumshirn <johannes.thumshirn@wdc.com>
scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
Randy Dunlap <rdunlap@infradead.org>
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Zhenzhong Duan <zhenzhong.duan@gmail.com>
csky: Fix a size determination in gpr_get()
Josef Bacik <josef@toxicpanda.com>
proc: use kvzalloc for our kernel buffer
Miaohe Lin <linmiaohe@huawei.com>
mm/rmap: fix potential pte_unmap on an not mapped pte
Dan Williams <dan.j.williams@intel.com>
mm: fix memory_failure() handling of dax-namespace metadata
Rik van Riel <riel@surriel.com>
mm,thp,shmem: make khugepaged obey tmpfs mount flags
Mårten Lindahl <martenli@axis.com>
i2c: exynos5: Preserve high speed master code
Maxime Ripard <maxime@cerno.tech>
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Marc Zyngier <maz@kernel.org>
arm64: Add missing ISB after invalidating TLB in __primary_switch
YueHaibing <yuehaibing@huawei.com>
cifs: Fix inconsistent IS_ERR and PTR_ERR
Sean Christopherson <seanjc@google.com>
KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
Sean Christopherson <seanjc@google.com>
KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4: Fixes for nfs4_bitmask_adjust()
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix jumbo packet handling on RTL8168e
Christian Melki <christian.melki@t2data.com>
net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ8081
Wonhyuk Yang <vvghjk1234@gmail.com>
mm/compaction: fix misbehaviors of fast_find_migrateblock()
Chen Wandun <chenwandun@huawei.com>
mm/hugetlb: suppress wrong warning info when alloc gigantic page
Miaohe Lin <linmiaohe@huawei.com>
mm/hugetlb: fix potential double free in hugetlb_register_node() error path
Miaohe Lin <linmiaohe@huawei.com>
mm/memory.c: fix potential pte_unmap_unlock pte error
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix slub memory accounting
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
Dan Carpenter <dan.carpenter@oracle.com>
ocfs2: fix a use after free on error
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: kconfig: use arm chacha even with no neon
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: device: do not generate ICMP for non-IP packets
Taehee Yoo <ap420073@gmail.com>
vxlan: move debug check after netdev unregister
Chen-Yu Tsai <wens@csie.org>
PCI: rockchip: Make 'ep-gpios' DT property optional
Chuhong Yuan <hslester96@gmail.com>
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Song, Yoong Siang <yoong.siang.song@intel.com>
net: stmmac: fix CBS idleslope and sendslope calculation
Camelia Groza <camelia.groza@nxp.com>
dpaa_eth: fix the access method for the dpaa_napi_portal
Henry Tieman <henry.w.tieman@intel.com>
ice: update the number of available RSS queues
Dave Ertman <david.m.ertman@intel.com>
ice: Fix state bits on LLDP mode switch
Brett Creeley <brett.creeley@intel.com>
ice: Account for port VLAN in VF max packet size calculation
Dave Ertman <david.m.ertman@intel.com>
ice: report correct max number of TCs
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
pwm: iqs620a: Fix overflow and optimize calculations
Dan Carpenter <dan.carpenter@oracle.com>
octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
Norbert Ciosek <norbertx.ciosek@intel.com>
i40e: Fix endianness conversions
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix add TC filter for IPv6
Andreas Oetken <andreas.oetken@siemens.com>
nios2: fixed broken sys_clone syscall
Jann Horn <jannh@google.com>
Take mmap lock in cacheflush syscall
Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
i40e: Fix VFs not created
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix addition of RX filters after enabling FW LLDP agent
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix overwriting flow control settings during driver loading
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Add zero-initialization of AQ command structures
Slawomir Laba <slawomirx.laba@intel.com>
i40e: Fix flow for IPv6 next header (extension header)
Krzysztof Wilczyński <kw@linux.com>
PCI: cadence: Fix DMA range mapping early return error
Russell King <rmk+kernel@armlinux.org.uk>
PCI: pci-bridge-emul: Fix array overruns, improve safety
Shiyang Ruan <ruansy.fnst@cn.fujitsu.com>
device-dax: Fix default return code of range_parse()
Magnum Shan <magnum.shan@unisoc.com>
mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Geert Uytterhoeven <geert@linux-m68k.org>
ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Bard Liao <yung-chuan.liao@linux.intel.com>
regmap: sdw: use _no_pm functions in regmap_read/write
Loic Poulain <loic.poulain@linaro.org>
mhi: Fix double dma free
Tzung-Bi Shih <tzungbi@google.com>
remoteproc/mediatek: acknowledge watchdog IRQ after handled
Jonathan Marek <jonathan@marek.ca>
misc: fastrpc: fix incorrect usage of dma_map_sgtable
Stephen Boyd <swboyd@chromium.org>
drm/msm/dp: Add a missing semi-colon
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: fix confusion on device used by pm_runtime
Bard Liao <yung-chuan.liao@linux.intel.com>
soundwire: export sdw_write/read_no_pm functions
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_update_no_pm when initializing a device
Rob Clark <robdclark@chromium.org>
drm/msm: Fix legacy relocs path
Ahmad Fatoum <a.fatoum@pengutronix.de>
nvmem: core: skip child nodes not matching binding
Dan Carpenter <dan.carpenter@oracle.com>
nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Skip accessing TRCPDCR in save/restore
Geert Uytterhoeven <geert+renesas@glider.be>
phy: USB_LGM_PHY should depend on X86
Theodore Ts'o <tytso@mit.edu>
ext4: fix potential htree index checksum corruption
Max Gurtovoy <mgurtovoy@nvidia.com>
vfio-pci/zdev: fix possible segmentation fault issue
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Fix some sanity checks in detach group
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Populate full dirty when detach non-pinned group
Judy Hsiao <judyhsiao@google.com>
drm/msm/dp: trigger unplug event in msm_dp_display_disable
Stephen Boyd <swboyd@chromium.org>
drm/msm/kms: Make a lock_class_key for each crtc mutex
Eric Anholt <eric@anholt.net>
drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Anholt <eric@anholt.net>
drm/msm: Fix race of GPU init vs timestamp power management.
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm/mdp5: Fix wait-for-commit for cmd panels
Konrad Dybcio <konrad.dybcio@somainline.org>
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
drm/msm: Add proper checks for GPU LLCC support
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm: Fix MSM_INFO_GET_IOVA with carveout
Alexander Usyskin <alexander.usyskin@intel.com>
mei: hbm: call mei_set_devstate() on hbm stop response
Heiner Kallweit <hkallweit1@gmail.com>
PCI: Align checking of syscall user config accessors
Jorgen Hansen <jhansen@vmware.com>
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Pan Bian <bianpan2016@163.com>
PCI: xilinx-cpm: Fix reference count leak on error path
Simon South <simon@simonsouth.net>
pwm: rockchip: Eliminate potential race condition when probing
Simon South <simon@simonsouth.net>
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
Simon South <simon@simonsouth.net>
pwm: rockchip: Enable APB clock during register access while probing
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: cadence: fix ACK/NAK handling
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
soundwire: debugfs: use controller id instead of link_id
Marek Vasut <marek.vasut+renesas@gmail.com>
PCI: rcar: Always allocate MSI addresses in 32bit space
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Add module alias to avoid breaking support for non device tree users
Dan Carpenter <dan.carpenter@oracle.com>
phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
Chris Ruehl <chris.ruehl@gtsys.com.hk>
phy: rockchip-emmc: emmc_phy_init() always return 0
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Fix module alias to enable module autoprobe
Geert Uytterhoeven <geert+renesas@glider.be>
Input: st1232 - fix NORMAL vs. IDLE state handling
Randy Dunlap <rdunlap@infradead.org>
ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
Michael Tretter <m.tretter@pengutronix.de>
Input: st1232 - add IDLE state as ready condition
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: zinitix - fix return type of zinitix_init_touch()
Randy Dunlap <rdunlap@infradead.org>
sparc: fix led.c driver when PROC_FS is not enabled
Randy Dunlap <rdunlap@infradead.org>
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
Dan Carpenter <dan.carpenter@oracle.com>
Input: elo - fix an error code in elo_connect()
Namhyung Kim <namhyung@kernel.org>
perf test: Fix unaligned access in sample parsing test
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix IPC with CYC threshold
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix premature IPC
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix missing CYC processing in PSB
Dave Rigby <d.rigby@me.com>
perf unwind: Set userdata for all __report_module() paths
Yang Jihong <yangjihong1@huawei.com>
perf record: Fix continue profiling after draining the buffer
Dan Carpenter <dan.carpenter@oracle.com>
Input: sur40 - fix an error code in sur40_probe()
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv-sysfs: fix missing put_device
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv: fix memory leak by missing kobject free
Md Haris Iqbal <haris.iqbal@cloud.ionos.com>
RDMA/rtrs: Only allow addition of path to an already established session
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix stack-out-of-bounds
Avihai Horon <avihaih@nvidia.com>
RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Fixes missing error code of CMDQ
Jeff Layton <jlayton@kernel.org>
ceph: fix flush_snap logic after putting caps
Chuck Lever <chuck.lever@oracle.com>
svcrdma: Hold private mutex while invoking rdma_accept()
J. Bruce Fields <bfields@redhat.com>
nfsd: register pernet ops last, unregister first
Nicholas Fraser <nfraser@codeweavers.com>
perf symbols: Fix return value when loading PE DSO
John Ogness <john.ogness@linutronix.de>
printk: avoid prb_first_valid_seq() where possible
Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
spi: Skip zero-length transfers in spi_transfer_one_message()
Kees Cook <keescook@chromium.org>
spi: dw: Avoid stack content exposure
Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
regulator: bd718x7, bd71828, Fix dvs voltage levels
Dmitry Safonov <0x7f454c46@gmail.com>
perf symbols: Use (long) for iterator for bfd symbols
Tom Zanussi <zanussi@kernel.org>
selftests/ftrace: Update synthetic event syntax errors
Ryan Chen <ryan_chen@aspeedtech.com>
clk: aspeed: Fix APLL calculate formula from ast2600-A2
Jonathan Marek <jonathan@marek.ca>
regulator: qcom-rpmh: fix pm8009 ldo7
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/kuap: Restore AMR after replaying soft interrupts
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/uaccess: Avoid might_fault() when user access is enabled
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
spi: pxa2xx: Fix the controller numbering for Wildcat Point
Michael Tretter <m.tretter@pengutronix.de>
clk: divider: fix initialization with parent_hw
Lijun Ou <oulijun@huawei.com>
RDMA/hns: Disable RQ inline by default
Xi Wang <wangxi11@huawei.com>
RDMA/hns: Add mapped page count checking for MTR
Weihang Li <liweihang@huawei.com>
RDMA/hns: Fix type of sq_signal_bits
Weihang Li <liweihang@huawei.com>
RDMA/hns: Avoid filling sgid index when modifying QP to RTR
Kamal Heib <kamalheib1@gmail.com>
RDMA/siw: Fix calculation of tx_valid_cpus size
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Remove the reserved WQE of SRQ
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Fixed wrong judgments in the goto branch
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Force srq_limit to 0 when creating SRQ
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Bugfix for checking whether the srq is full when post wr
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Allocate one more recv SGE for HIP08
John Stultz <john.stultz@linaro.org>
kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
Daniel Latypov <dlatypov@google.com>
kunit: tool: fix unit test cleanup handling
AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Taniya Das <tdas@codeaurora.org>
clk: qcom: gcc-sc7180: Mark the MM XO clocks to be always ON
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
clk: qcom: gfm-mux: fix clk mask
Sandipan Das <sandipan@linux.ibm.com>
powerpc/sstep: Fix darn emulation
Sandipan Das <sandipan@linux.ibm.com>
powerpc/sstep: Fix load-store and update emulation
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/8xx: Fix software emulation interrupt
Nathan Lynch <nathanl@linux.ibm.com>
powerpc/pseries/dlpar: handle ibm, configure-connector delay status
Dan Carpenter <dan.carpenter@oracle.com>
mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
Arnd Bergmann <arnd@arndb.de>
mfd: altera-sysmgr: Fix physical address storing more
Alain Volmat <alain.volmat@foss.st.com>
spi: stm32: properly handle 0 byte transfer
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Correct skb on loopback path
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_recv.c
John Garry <john.garry@huawei.com>
perf vendor events arm64: Fix Ampere eMag event typo
Arnaldo Carvalho de Melo <acme@redhat.com>
perf tools: Fix DSO filtering when not finding a map for a sampled address
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt_crashlog: Add dependency on MFD_INTEL_PMT
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt_telemetry: Add dependency on MFD_INTEL_PMT
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt: Make INTEL_PMT_CLASS non-user-selectable
David Gow <davidgow@google.com>
rtc: zynqmp: depend on HAS_IOMEM
Steven Rostedt (VMware) <rostedt@goodmis.org>
tracepoint: Do not fail unregistering a probe due to memory failure
Parav Pandit <parav@nvidia.com>
IB/cm: Avoid a loop when device has 255 ports
Parav Pandit <parav@nvidia.com>
IB/mlx5: Return appropriate error code instead of ENOMEM
Douglas Anderson <dianders@chromium.org>
iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Yong Wu <yong.wu@mediatek.com>
iommu: Move iotlb_sync_map out from __iommu_map
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
amba: Fix resource leak for drivers without .remove
David Gow <davidgow@google.com>
i3c/master/mipi-i3c-hci: Specify HAS_IOMEM dependency
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: i2c-qcom-geni: Add shutdown callback for i2c
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Vladimir Murzin <vladimir.murzin@arm.com>
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Takeshi Saito <takeshi.saito.xv@renesas.com>
mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to 128-bytes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: sdhci-sprd: Fix some resource leaks in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: owl-mmc: Fix a resource leak in an error handling path and in the remove function
Michal Suchanek <msuchanek@suse.de>
powerpc: Fix build error in paravirt.h
Pingfan Liu <kernelfans@gmail.com>
powerpc/time: Enable sched clock for irqtime
Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
powerpc/sstep: Fix incorrect return from analyze_instr()
Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
powerpc/sstep: Check instruction validity against ISA version before emulation
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/47x: Disable 256k page size
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/kvm: Force selection of CONFIG_PPC_FPU
Cédric Le Goater <clg@kaod.org>
KVM: PPC: Make the VMX instruction emulation routines static
Shay Drory <shayd@nvidia.com>
IB/umad: Return EPOLLERR in case of when device disassociated
Shay Drory <shayd@nvidia.com>
IB/umad: Return EIO in case of when device disassociated
Mark Bloch <mbloch@nvidia.com>
RDMA/mlx5: Allow creating all QPs even when non RDMA profile is used
Maor Gottlieb <maorg@nvidia.com>
tools/testing/scatterlist: Fix overflow of max segment size
Yong Wu <yong.wu@mediatek.com>
iommu: Switch gather->end to the inclusive end
Dan Carpenter <dan.carpenter@oracle.com>
scsi: lpfc: Fix ancient double free
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix ".cold" section suffix check for newer versions of GCC
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix retpoline detection in asm code
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix error handling for STD/CLD warnings
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: Fix duplicate CHARLCD config symbol
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: ht16k33: Fix refresh rate handling
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
Pan Bian <bianpan2016@163.com>
isofs: release buffer head before return
Hans de Goede <hdegoede@redhat.com>
regulator: core: Avoid debugfs: Directory ... already present! error
Dmitry Osipenko <digetx@gmail.com>
power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Samuel Holland <samuel@sholland.org>
power: supply: axp20x_usb_power: Init work before enabling IRQs
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: isci: Pass gfp_t flags in isci_port_bc_change_received()
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: isci: Pass gfp_t flags in isci_port_link_up()
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: isci: Pass gfp_t flags in isci_port_link_down()
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: mvsas: Pass gfp_t flags to libsas event notifiers
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: Introduce a _gfp() variant of event notifiers
John Garry <john.garry@huawei.com>
scsi: libsas: Remove notifier indirection
Krzysztof Kozlowski <krzk@kernel.org>
regulator: s5m8767: Drop regulators OF node reference
Pan Bian <bianpan2016@163.com>
spi: atmel: Put allocated master before return
Pan Bian <bianpan2016@163.com>
regulator: s5m8767: Fix reference count leak
David Howells <dhowells@redhat.com>
certs: Fix blacklist flag type confusion
Gabriel Krisman Bertazi <krisman@collabora.com>
watch_queue: Drop references to /dev/watch_queue
Pan Bian <bianpan2016@163.com>
regulator: axp20x: Fix reference cout leak
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix clock divider range on some clocks
Parav Pandit <parav@nvidia.com>
IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
Yishai Hadas <yishaih@nvidia.com>
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Guido Günther <agx@sigxcpu.org>
spi: imx: Don't print error on -EPROBEDEFER
Frank van der Linden <fllinden@amazon.com>
module: harden ELF info handling
Tom Rix <trix@redhat.com>
clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
Arnd Bergmann <arnd@arndb.de>
clocksource/drivers/ixp4xx: Select TIMER_OF when needed
Randy Dunlap <rdunlap@infradead.org>
power: supply: fix sbs-charger build, needs REGMAP_I2C
Dave Jiang <dave.jiang@intel.com>
dmaengine: idxd: set DMA channel to be private
Bartosz Golaszewski <bgolaszewski@baylibre.com>
rtc: s5m: select REGMAP_I2C
Claudiu Beznea <claudiu.beznea@microchip.com>
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Fix KASAN: stack-out-of-bounds bug
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Init wr_cnt as 1
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix missing wr_cqe
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs: Call kobject_put in the failure path
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-srv: Jump to dereg_mr label if allocate iu fails
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-clt: Set mininum limit when create QP
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Release lock before call into close_sess
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Extend ibtrs_cq_qp_create
Nicolas Boichat <drinkcat@chromium.org>
of/fdt: Make sure no-map does not remove already reserved regions
KarimAllah Ahmed <karahmed@amazon.de>
fdt: Properly handle "no-map" field in the memory region
Colin Ian King <colin.king@canonical.com>
power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Can Guo <cang@codeaurora.org>
scsi: ufs: Fix a possible NULL pointer issue
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-battery: Fix missing power_supply_put()
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-charger: Fix missing power_supply_put()
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
mfd: bd9571mwv: Use devm_mfd_add_devices()
Ferry Toth <ftoth@exalondelft.nl>
dmaengine: hsu: disable spurious interrupt
Vignesh Raghavendra <vigneshr@ti.com>
dmaengine: ti: k3-udma: Set rflow count for BCDMA split channels
Nathan Chancellor <nathan@kernel.org>
dmaengine: qcom: Always inline gpi_update_reg
Arnd Bergmann <arnd@arndb.de>
rtc: rx6110: fix build against modular I2C
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: owl-dma: Fix a resource leak in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in the remove function
Bernard Metzler <bmt@zurich.ibm.com>
RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Randy Dunlap <rdunlap@infradead.org>
HID: core: detect and skip invalid inputs to snto32()
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Fix parent of CBFUSA clock
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Remove non-existent S2 clock
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix CEC clock
Pratyush Yadav <p.yadav@ti.com>
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle master read request
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle only slave interrupts which are enabled
Jan Kara <jack@suse.cz>
quota: Fix memory leak when handling corrupted quota file
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
Po-Hsu Lin <po-hsu.lin@canonical.com>
selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: make "ret" a signed integer
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
Tony Lindgren <tony@atomide.com>
power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
Zhang Qilong <zhangqilong3@huawei.com>
HSI: Fix PM usage counter unbalance in ssi_hw_init
Eric W. Biederman <ebiederm@xmission.com>
capabilities: Don't allow writing ambiguous v3 file capabilities
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: imx_keypad - add dependency on HAS_IOMEM
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: da7280 - protect OF match table with CONFIG_OF
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: da7280 - fix missing error test
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
smp: Process pending softirqs in flush_smp_call_function_from_idle()
Geert Uytterhoeven <geert+renesas@glider.be>
irqchip/imx: IMX_INTMUX should not default to y, unconditionally
Wang ShaoBo <bobo.shaobowang@huawei.com>
ubifs: Fix error return code in alloc_wbufs()
Arnd Bergmann <arnd@arndb.de>
ubifs: replay: Fix high stack usage, again
Dinghao Liu <dinghao.liu@zju.edu.cn>
ubifs: Fix memleak in ubifs_init_authentication
Tom Rix <trix@redhat.com>
jffs2: fix use after free in jffs2_sum_write_data()
Colin Ian King <colin.king@canonical.com>
fs/jfs: fix potential integer overflow on shift of a int
Sameer Pujar <spujar@nvidia.com>
ASoC: simple-card-utils: Fix device module clock
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer after kexec syscall
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer on error
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: set status to 0 in case for invalid nsid
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: remove extra variable in identify ns
Keith Busch <kbusch@kernel.org>
nvme-multipath: set nr_zones for zoned namespaces
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix potential race of tcp socket closing accept_work
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
Hao Xu <haoxu@linux.alibaba.com>
io_uring: fix possible deadlock in io_uring_poll
Daniele Alessandrelli <daniele.alessandrelli@intel.com>
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Jan Henrik Weinstock <jan.weinstock@rwth-aachen.de>
hwrng: timeriomem - Fix cooldown period calculation
Imre Deak <imre.deak@intel.com>
drm/dp_mst: Don't cache EDIDs for physical ports
Dan Carpenter <dan.carpenter@oracle.com>
drm/virtio: fix an error code in virtio_gpu_init()
Qinglang Miao <miaoqinglang@huawei.com>
drm/lima: fix reference leak in lima_pm_busy
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Restore cec physical address on reconnect
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix up CEC registers
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix register offset with longer CEC messages
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Move hdmi reset to bind
Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: return EIO when msg retry limit reached
Sean Christopherson <seanjc@google.com>
KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
Jinyang He <hejinyang@loongson.cn>
MIPS: relocatable: Provide kaslr_offset() to get the kernel offset
Qu Wenruo <wqu@suse.com>
btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Zhihao Cheng <chengzhihao1@huawei.com>
btrfs: clarify error returns values in __load_free_space_cache
Hui Wang <hui.wang@canonical.com>
ASoC: SOF: debug: Fix a potential issue on string buffer termination
Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>
ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Jun Nie <jun.nie@linaro.org>
ASoC: qcom: lpass: Fix i2s ctl register bit map
Peter Zijlstra <peterz@infradead.org>
locking/lockdep: Avoid unmatched unlock
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A32
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
Yongqiang Niu <yongqiang.niu@mediatek.com>
drm/mediatek: Check if fb is null
Sean Christopherson <seanjc@google.com>
KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Dehe Gu <gudehe@huawei.com>
f2fs: fix a wrong condition in __submit_bio
Dan Carpenter <dan.carpenter@oracle.com>
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
Yi Chen <chenyi77@huawei.com>
f2fs: fix to avoid inconsistent quota data
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mtd: rawnand: intel: Fix an error handling path in 'ebu_dma_start()'
Manivannan Sadhasivam <mani@kernel.org>
mtd: parsers: afs: Fix freeing the part name memory in failure
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
ASoC: codecs: add missing max_register in regmap config
Sebastian Reichel <sre@kernel.org>
ASoC: cpcap: fix microphone timeslot mask
Florian Fainelli <f.fainelli@gmail.com>
ata: ahci_brcm: Add back regulators management
Will Deacon <will@kernel.org>
mm: proc: Invalidate TLB after clearing soft-dirty page state
Biwen Li <biwen.li@nxp.com>
irqchip/ls-extirq: add IRQCHIP_SKIP_SET_WAKE to the irqchip flags
Frantisek Hrbata <frantisek@hrbata.com>
drm/nouveau: bail out of nouveau_channel_new if channel init fails
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Fix ctr(aes) on SEC1
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
Dan Carpenter <dan.carpenter@oracle.com>
mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Move IRQs when migrating context
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix PMU instance naming
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: lpass-cpu: Remove bit clock state check
Chao Yu <chao@kernel.org>
f2fs: compress: fix potential deadlock
Daeho Jeong <daehojeong@google.com>
f2fs: fix null page reference in redirty_blocks
Qais Yousef <qais.yousef@arm.com>
sched/eas: Don't update misfit status if the task is pinned
Judy Hsiao <judyhsiao@google.com>
ASoC: max98373: Fixes a typo in max98373_feedback_get
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
media: i2c/Kconfig: Select FWNODE for OV772x sensor
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
Tom Rix <trix@redhat.com>
media: pxa_camera: declare variable when DEBUG is defined
yangerkun <yangerkun@huawei.com>
mtd: phram: use div_u64_rem to stop overwrite len in phram_setup
Tom Rix <trix@redhat.com>
media: mtk-vcodec: fix argument used when DEBUG is defined
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: cx25821: Fix a bug when reallocating some dma memory
Luo Meng <luomeng12@huawei.com>
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Dan Carpenter <dan.carpenter@oracle.com>
media: atomisp: Fix a buffer overflow in debug code
Daniel W. S. Almeida <dwlsalmeida@gmail.com>
media: vidtv: psi: fix missing crc for PMT
Joe Perches <joe@perches.com>
media: lmedm04: Fix misuse of comma
Daniel Scally <djrscally@gmail.com>
media: software_node: Fix refcounts in software_node_get_next_child()
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
Finn Thain <fthain@telegraphics.com.au>
macintosh/adb-iop: Use big-endian autopoll mask
Pan Bian <bianpan2016@163.com>
bsg: free the request before return error code
Guchun Chen <guchun.chen@amd.com>
drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
Qinglang Miao <miaoqinglang@huawei.com>
drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
Nathan Chancellor <nathan@kernel.org>
MIPS: Compare __SYNC_loongson3_war against 0
Alexander Lobakin <alobakin@pm.me>
MIPS: properly stop .eh_frame generation
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: ti-vpe: cal: fix write to unallocated memory
Rui Miguel Silva <rmfrfs@gmail.com>
media: imx7: csi: Fix pad link validation
Fabio Estevam <festevam@gmail.com>
media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Giulio Benetti <giulio.benetti@micronovasrl.com>
drm/sun4i: tcon: fix inverted DCLK polarity
Xuewen Yan <xuewen.yan@unisoc.com>
sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Jiri Olsa <jolsa@kernel.org>
crypto: bcm - Rename struct device_private to bcm_device_private
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - replace CRYPTO_AES with CRYPTO_LIB_AES in Kconfig
Dinghao Liu <dinghao.liu@zju.edu.cn>
evm: Fix memleak in init_desc
Stephan Gerhold <stephan@gerhold.net>
ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Dan Carpenter <dan.carpenter@oracle.com>
ASoC: cs42l56: fix up error handling in probe
Zhang Changzhong <zhangchangzhong@huawei.com>
media: aspeed: fix error return code in aspeed_video_setup_video()
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: tm6000: Fix memleak in tm6000_start_stream
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: media/pci: Fix memleak in empress_init
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: em28xx: Fix use-after-free in em28xx_alloc_urbs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: vsp1: Fix an error handling path in the probe function
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: missing error code in msm_video_register()
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: Fix signedness bug in video_enum_fmt()
Zhang Changzhong <zhangchangzhong@huawei.com>
media: mtk-vcodec: fix error return code in vdec_vp9_decode()
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Fix csc/scaler unregister
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Unregister csc/scaler only if registered
Jacopo Mondi <jacopo@jmondi.org>
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
media: ipu3-cio2: Build only for x86
Simon Ser <contact@emersion.fr>
drm/fourcc: fix Amlogic format modifier masks
Chia-I Wu <olvaffe@gmail.com>
drm/virtio: make sure context is created in gem open
Nathan Chancellor <nathan@kernel.org>
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Chancellor <nathan@kernel.org>
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
Chenyang Li <lichenyang@loongson.cn>
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Wang Xiaojun <wangxiaojun11@huawei.com>
drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
Qinglang Miao <miaoqinglang@huawei.com>
drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
Marco Elver <elver@google.com>
kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Arnd Bergmann <arnd@arndb.de>
ASoC: fsl_aud2htx: select SND_SOC_IMX_PCM_DMA
Dan Carpenter <dan.carpenter@oracle.com>
media: allegro: Fix use after free on error
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hwrng: ingenic - Fix a resource leak in an error handling path
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - fix kmap usage
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - linearize buffers content must be kept
Linus Walleij <linus.walleij@linaro.org>
drm/panel: s6e63m0: Support max-brightness
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
Guido Günther <agx@sigxcpu.org>
drm/panel: mantix: Tweak init sequence
Linus Walleij <linus.walleij@linaro.org>
drm/panel: s6e63m0: Fix init sequence again
Chuhong Yuan <hslester96@gmail.com>
drm/fb-helper: Add missed unlocks in setcmap_legacy()
Dan Carpenter <dan.carpenter@oracle.com>
gma500: clean up error handling in init
Simon Ser <contact@emersion.fr>
drm: document that user-space should force-probe connectors
Jialin Zhang <zhangjialin11@huawei.com>
drm/gma500: Fix error return code in psb_driver_load()
Randy Dunlap <rdunlap@infradead.org>
fbdev: aty: SPARC64 requires FB_ATY_CT
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: coma mode disabled for VSC8514
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: improved serdes calibration applied to VSC8514
Alex Elder <elder@linaro.org>
net: ipa: initialize all resources
Dany Madden <drt@linux.ibm.com>
ibmvnic: change IBMVNIC_MAX_IND_DESCS to 16
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Fix CQ params of ICOSQ and async ICOSQ
Raed Salem <raeds@nvidia.com>
net/mlx5e: Enable striding RQ for Connect-X IPsec capable devices
Parav Pandit <parav@nvidia.com>
net/mlx5e: E-switch, Fix rate calculation for overflow
Joel Stanley <joel@jms.id.au>
soc: aspeed: socinfo: Add new systems
Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Bluetooth: hci_qca: Fixed issue during suspend
Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Bluetooth: hci_qca: check for SSR triggered flag while suspend
Matthias Brugger <mbrugger@suse.com>
arm64: dts: mt8183: Fix GCE include path
Peter Geis <pgwipeout@gmail.com>
ARM: tegra: ouya: Fix eMMC on specific bootloaders
Pali Rohár <pali@kernel.org>
net: sfp: add workaround for Realtek RTL8672 and RTL9601C chips
Enric Balletbo i Serra <enric.balletbo@collabora.com>
arm64: dts: mt8183: Add missing power-domain for pwm0 node
Yongqiang Niu <yongqiang.niu@mediatek.com>
arm64: dts: mt8183: refine gamma compatible name
Yongqiang Niu <yongqiang.niu@mediatek.com>
arm64: dts: mt8183: rename rdma fifo size
Andrii Nakryiko <andrii@kernel.org>
selftests/bpf: Don't exit on failed bpf_testmod unload
Sami Tolvanen <samitolvanen@google.com>
x86/sgx: Fix the return type of sgx_init()
Linus Torvalds <torvalds@linux-foundation.org>
tty: implement read_iter
Linus Torvalds <torvalds@linux-foundation.org>
tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix uSD pins drive strength
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: sm8250: correct sdhc_2 xo clk
Andrii Nakryiko <andrii@kernel.org>
selftests/bpf: Sync RCU before unloading bpf_testmod
Andrii Nakryiko <andrii@kernel.org>
bpf: Declare __bpf_free_used_maps() unconditionally
Erwan Le Ray <erwan.leray@foss.st.com>
serial: stm32: fix DMA initialization error handling
Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Bluetooth: hci_qca: Wait for SSR completion during suspend
Rafał Miłecki <rafal@milecki.pl>
arm64: dts: broadcom: bcm4908: use proper NAND binding
Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Bluetooth: Remove hci_req_le_suspend_config
Vladimir Oltean <vladimir.oltean@nxp.com>
net: enetc: fix destroyed phylink dereference during unbind
Maxime Chevallier <maxime.chevallier@bootlin.com>
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset link when the link never comes back
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: adding LCPLL reset to VSC8514
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: don't deinitialize unused ports
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: perform teardown in reverse order of setup
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: serialize access to work queue on remove
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: skip send_request_unmap for timeout reset
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: add memory barrier to protect long term buffer
Ilya Leoshkevich <iii@linux.ibm.com>
bpf: Clear subreg_def for global function return values
Colin Ian King <colin.king@canonical.com>
b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
Ayush Sawal <ayush.sawal@chelsio.com>
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Robert Hancock <robert.hancock@calian.com>
net: axienet: Handle deferred probe on clock properly
Eric Dumazet <edumazet@google.com>
tcp: fix SO_RCVLOWAT related hangs under mem pressure
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: fix ACKRX debug message
Jesper Dangaard Brouer <brouer@redhat.com>
bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Jun'ichi Nomura <junichi.nomura@nec.com>
bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Yonghong Song <yhs@fb.com>
bpf: Fix an unitialized value in bpf_iter
Martin KaFai Lau <kafai@fb.com>
libbpf: Ignore non function pointer member in struct_ops
Colin Ian King <colin.king@canonical.com>
mac80211: fix potential overflow when multiplying to u32 integers
Moshe Shemesh <moshe@nvidia.com>
net/mlx5e: Check tunnel offload is required before setting SWP
Oz Shlomo <ozsh@nvidia.com>
net/mlx5e: CT: manage the lifetime of the ct entry object
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for lag devices
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on lag device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on multi port slave device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for multi port slave device
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Replace synchronize_rcu with synchronize_net
Shay Drory <shayd@nvidia.com>
net/mlx5: Fix health error state handling
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Change interrupt moderation channel params also when channels are closed
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Don't change interrupt moderation params when DIM is enabled
Raed Salem <raeds@nvidia.com>
net/mlx5e: Enable XDP for Connect-X IPsec capable devices
Heiner Kallweit <hkallweit1@gmail.com>
net: phy: consider that suspend2ram may cut off PHY power
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: fix memory leak in XDP_REDIRECT
Juergen Gross <jgross@suse.com>
xen/netback: fix spurious event detection for common event case
Vasundhara Volam <vasundhara-v.volam@broadcom.com>
bnxt_en: Fix devlink info's stored fw.psid version format.
Edwin Peer <edwin.peer@broadcom.com>
bnxt_en: reverse order of TX disable and carrier off
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: Set to CLOSED state even on error
Björn Töpel <bjorn@kernel.org>
selftests/bpf: Convert test_xdp_redirect.sh to bash
Linus Lüssing <ll@simonwunderlich.de>
ath9k: fix data bus crash when setting nf_override via debugfs
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: set the PNVM again if it was already loaded
Marco Elver <elver@google.com>
bpf_lru_list: Read double-checked variable once without lock
Sara Sharon <sara.sharon@intel.com>
iwlwifi: mvm: don't check if CSA event is running before removing
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: assign SAR table revision to the command later
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: send stored PPAG command instead of local
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: store PPAG enabled/disabled flag properly
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: fix the type we use in the PPAG table validity checks
Jae Hyun Yoo <jae.hyun.yoo@intel.com>
soc: aspeed: snoop: Add clock control logic
Dan Carpenter <dan.carpenter@oracle.com>
ath11k: fix a locking bug in ath11k_mac_op_start()
Anand K Mistry <amistry@google.com>
ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Anand K Mistry <amistry@google.com>
ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
Arnd Bergmann <arnd@arndb.de>
ARM: at91: use proper asm syntax in pm_suspend
Jérôme Pouiller <jerome.pouiller@silabs.com>
staging: wfx: fix possible panic with re-queued frames
Arnd Bergmann <arnd@arndb.de>
optee: simplify i2c access
Arnd Bergmann <arnd@arndb.de>
ARM: s3c: fix fiq for clang IAS
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: set enabled in the PPAG command properly
Artem Lapkin <email2tema@gmail.com>
arm64: dts: meson: fix broken wifi node for Khadas VIM3L
Vincent Knecht <vincent.knecht@mailoo.org>
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Luca Weiss <luca@z3ntu.xyz>
soc: qcom: ocmem: don't return NULL in of_get_ocmem
Jupeng Zhong <zhongjupeng@yulong.com>
Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Dmitry Osipenko <digetx@gmail.com>
opp: Correct debug message in _opp_add_static_v2()
Marek Behún <kabel@kernel.org>
arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to LEDs
Marc Kleine-Budde <mkl@pengutronix.de>
can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Geert Uytterhoeven <geert+renesas@glider.be>
arm64: dts: renesas: beacon: Fix EEPROM compatible value
Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Chen-Yu Tsai <wens@csie.org>
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Make "trimming xfer length" a debug message
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Abort transaction after errors with unknown reason
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Do not update data length if it is 0 on inbound transfers
Tony Lindgren <tony@atomide.com>
ARM: dts: Configure missing thermal interrupt for 4430
Pan Bian <bianpan2016@163.com>
memory: ti-aemif: Drop child node when jumping out loop
Pan Bian <bianpan2016@163.com>
Bluetooth: Put HCI device if inquiry procedure interrupts
Pan Bian <bianpan2016@163.com>
Bluetooth: drop HCI device reference before return
Borislav Petkov <bp@suse.de>
staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
Dan Carpenter <dan.carpenter@oracle.com>
soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
Robert Foss <robert.foss@linaro.org>
arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Jack Pham <jackp@codeaurora.org>
usb: gadget: u_audio: Free requests only after callback
Maximilian Luz <luzmaximilian@gmail.com>
ACPICA: Fix exception code class checks
Chen-Yu Tsai <wens@csie.org>
arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Free resources in error path
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: properly connect USB PHY to port 0
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix call site of scmi_notification_exit
Andrii Nakryiko <andrii@kernel.org>
bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
Andrii Nakryiko <andrii@kernel.org>
bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk transfers on 64-bit builds
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk userdata handling
Dinghao Liu <dinghao.liu@zju.edu.cn>
Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
Zhang Qilong <zhangqilong3@huawei.com>
memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
Christopher William Snowhill <chris@kode54.net>
Bluetooth: Fix initializing response id after clearing struct
Claire Chang <tientzu@chromium.org>
Bluetooth: hci_uart: Fix a race for write_work scheduling
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the probe function
Rakesh Pillai <pillair@codeaurora.org>
ath10k: Fix error handling in case of CE pipe init failure
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: One more flush for Baytrail clear residuals
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Don't call sync_stop if it hasn't been stopped
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Assure sync with the pending stop operation at suspend
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Call sync_stop at disconnection
Eric Biggers <ebiggers@google.com>
random: fix the RNDRESEEDCRNG ioctl
Nathan Chancellor <nathan@kernel.org>
vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
Alexander Lobakin <alobakin@pm.me>
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
Rokudo Yan <wu-yan@tcl.com>
zsmalloc: account the number of compacted pages correctly
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
Jan Kara <jack@suse.cz>
bfq: Avoid false bfq queue merging
Hans de Goede <hdegoede@redhat.com>
virt: vbox: Do not use wait_event_interruptible when called from kernel context
Ard Biesheuvel <ardb@kernel.org>
PCI: Decline to resize resources if boot config must be preserved
Ansuel Smith <ansuelsmth@gmail.com>
PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ivan Zaentsev <ivan.zaentsev@wirenboard.ru>
w1: w1_therm: Fix conversion result for negative temperatures
Sumit Garg <sumit.garg@linaro.org>
kdb: Make memory allocations more robust
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix mailbox Ch erroneous error
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: docs: Remove notify_ha_event()
Dave Jiang <dave.jiang@intel.com>
driver core: auxiliary bus: Fix calling stage for auxiliary bus init
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: do not attempt to create a new file before the filesystem is initalized
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: be more robust at handling improper input in debugfs_lookup()
Stefano Garzarella <sgarzare@redhat.com>
vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Nick Desaulniers <ndesaulniers@google.com>
vmlinux.lds.h: add DWARF v5 sections
-------------
Diffstat:
Documentation/admin-guide/perf/arm-cmn.rst | 2 +-
Documentation/admin-guide/sysctl/vm.rst | 10 +-
Documentation/filesystems/seq_file.rst | 6 +
Documentation/scsi/libsas.rst | 10 +-
Documentation/security/keys/core.rst | 4 +-
Makefile | 4 +-
arch/arm/boot/compressed/head.S | 4 +-
arch/arm/boot/dts/armada-388-helios4.dts | 28 +-
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/arm/boot/dts/tegra30-ouya.dts | 4 +-
arch/arm/kernel/sys_oabi-compat.c | 15 +
arch/arm/mach-at91/pm_suspend.S | 2 +-
arch/arm/mach-ixp4xx/Kconfig | 1 -
arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9 +-
arch/arm64/Kconfig | 2 +-
.../boot/dts/allwinner/sun50i-a64-pinebook.dts | 5 +-
.../boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 -
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 +-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7 +
.../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7 +-
arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi | 2 +-
.../boot/dts/exynos/exynos5433-tm2-common.dtsi | 2 +-
arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +-
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4 +-
.../boot/dts/marvell/armada-3720-turris-mox.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 10 +-
.../dts/qcom/msm8916-samsung-a2015-common.dtsi | 6 +
.../boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2 +-
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 15 +-
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 +-
arch/arm64/boot/dts/qcom/sm8250.dtsi | 2 +-
.../boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +-
.../arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4 +-
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 +
arch/arm64/crypto/aes-glue.c | 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/include/asm/module.lds.h | 6 +-
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/head.S | 1 +
arch/arm64/kernel/machine_kexec_file.c | 4 +-
arch/arm64/kernel/probes/uprobes.c | 2 +-
arch/arm64/kernel/ptrace.c | 2 +-
arch/arm64/kernel/suspend.c | 2 +-
arch/csky/kernel/ptrace.c | 2 +-
arch/mips/Makefile | 19 +
arch/mips/boot/compressed/Makefile | 1 +
arch/mips/cavium-octeon/setup.c | 9 +-
arch/mips/include/asm/asm.h | 18 +
arch/mips/include/asm/atomic.h | 2 +-
arch/mips/include/asm/cmpxchg.h | 6 +-
arch/mips/include/asm/page.h | 6 +
arch/mips/kernel/cpu-probe.c | 15 +-
arch/mips/kernel/relocate.c | 10 +
arch/mips/kernel/setup.c | 3 +
arch/mips/kernel/vmlinux.lds.S | 2 +-
arch/mips/lantiq/irq.c | 2 +-
arch/mips/loongson64/Platform | 22 -
arch/mips/mm/c-r4k.c | 2 +-
arch/mips/vdso/Makefile | 5 +-
arch/nios2/kernel/entry.S | 3 +
arch/nios2/kernel/sys_nios2.c | 11 +-
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/kexec.h | 1 +
arch/powerpc/include/asm/paravirt.h | 1 +
arch/powerpc/include/asm/uaccess.h | 13 +-
arch/powerpc/kernel/entry_32.S | 3 +
arch/powerpc/kernel/head_32.h | 2 +-
arch/powerpc/kernel/head_8xx.S | 2 +-
arch/powerpc/kernel/head_book3s_32.S | 6 -
arch/powerpc/kernel/irq.c | 27 +-
arch/powerpc/kernel/prom_init.c | 12 +-
arch/powerpc/kernel/time.c | 2 +
arch/powerpc/kexec/elf_64.c | 2 +-
arch/powerpc/kexec/file_load_64.c | 35 ++
arch/powerpc/kvm/Kconfig | 1 +
arch/powerpc/kvm/powerpc.c | 8 +-
arch/powerpc/lib/sstep.c | 101 +++-
arch/powerpc/platforms/pseries/dlpar.c | 7 +-
arch/riscv/kernel/vdso/Makefile | 3 +-
arch/s390/kernel/vtime.c | 3 +-
arch/sparc/Kconfig | 2 +-
arch/sparc/kernel/led.c | 2 +
arch/sparc/lib/memset.S | 1 +
arch/um/include/shared/skas/mm_id.h | 1 +
arch/um/kernel/tlb.c | 19 +-
arch/um/os-Linux/skas/process.c | 4 +
arch/x86/crypto/aesni-intel_glue.c | 28 +-
arch/x86/entry/common.c | 2 +-
arch/x86/include/asm/virtext.h | 17 +-
arch/x86/kernel/cpu/sgx/main.c | 14 +-
arch/x86/kernel/msr.c | 7 +
arch/x86/kernel/reboot.c | 30 +-
arch/x86/kvm/emulate.c | 4 +-
arch/x86/kvm/mmu/tdp_mmu.c | 3 +-
arch/x86/kvm/svm/nested.c | 22 +-
arch/x86/kvm/svm/svm.c | 8 +-
arch/x86/kvm/x86.c | 1 +
arch/x86/mm/fault.c | 27 +-
arch/x86/mm/pat/memtype.c | 4 +-
block/bfq-iosched.c | 1 +
block/blk-settings.c | 12 +
block/bsg.c | 4 +-
block/genhd.c | 2 +-
block/ioctl.c | 21 +-
certs/blacklist.c | 2 +-
crypto/ecdh_helper.c | 3 +
crypto/michael_mic.c | 31 +-
drivers/acpi/acpi_configfs.c | 7 +-
drivers/acpi/property.c | 44 +-
drivers/amba/bus.c | 20 +-
drivers/ata/ahci_brcm.c | 14 +-
drivers/auxdisplay/Kconfig | 3 -
drivers/auxdisplay/ht16k33.c | 3 +-
drivers/base/auxiliary.c | 13 +-
drivers/base/base.h | 5 +
drivers/base/init.c | 1 +
drivers/base/regmap/regmap-sdw.c | 4 +-
drivers/base/swnode.c | 8 +-
drivers/block/floppy.c | 30 +-
drivers/block/zram/zram_drv.c | 2 +-
drivers/bluetooth/btqcomsmd.c | 27 +-
drivers/bluetooth/btusb.c | 20 +-
drivers/bluetooth/hci_ldisc.c | 41 +-
drivers/bluetooth/hci_qca.c | 33 +-
drivers/bluetooth/hci_serdev.c | 4 +-
drivers/bus/mhi/core/init.c | 3 +
drivers/char/hw_random/ingenic-trng.c | 6 +-
drivers/char/hw_random/timeriomem-rng.c | 2 +-
drivers/char/random.c | 2 +-
drivers/char/tpm/tpm.h | 4 -
drivers/char/tpm/tpm_tis_core.c | 50 +-
drivers/clk/clk-ast2600.c | 37 +-
drivers/clk/clk-divider.c | 9 +-
drivers/clk/meson/clk-pll.c | 10 +-
drivers/clk/qcom/gcc-msm8998.c | 100 ++--
drivers/clk/qcom/gcc-sc7180.c | 47 +-
drivers/clk/qcom/lpass-gfm-sm8250.c | 8 +-
drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +-
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/mxs_timer.c | 5 +-
drivers/cpufreq/acpi-cpufreq.c | 62 +-
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +-
drivers/cpufreq/freq_table.c | 8 +-
drivers/cpufreq/intel_pstate.c | 21 +-
drivers/cpufreq/qcom-cpufreq-hw.c | 40 +-
.../crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 +++---
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2 +
drivers/crypto/bcm/cipher.c | 2 +-
drivers/crypto/bcm/cipher.h | 4 +-
drivers/crypto/bcm/util.c | 2 +-
drivers/crypto/qat/Kconfig | 2 +-
drivers/crypto/talitos.c | 50 +-
drivers/crypto/talitos.h | 1 +
drivers/dax/bus.c | 2 +-
drivers/dma/fsldma.c | 6 +
drivers/dma/hsu/pci.c | 21 +-
drivers/dma/idxd/dma.c | 1 +
drivers/dma/owl-dma.c | 1 +
drivers/dma/qcom/gpi.c | 2 +-
drivers/dma/ti/k3-udma.c | 1 +
drivers/firmware/arm_scmi/driver.c | 4 +-
drivers/gpio/gpio-pcf857x.c | 2 +-
drivers/gpu/drm/Kconfig | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +-
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 22 +-
drivers/gpu/drm/amd/amdgpu/soc15.c | 2 +
.../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2 +-
.../gpu/drm/amd/display/dc/bios/command_table.c | 61 ++
drivers/gpu/drm/amd/display/dc/core/dc.c | 27 +-
drivers/gpu/drm/amd/display/dc/dc_stream.h | 3 +-
.../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14 +
.../drm/amd/display/dc/dce/dce_stream_encoder.c | 1 +
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8 +-
.../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1 -
.../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +
.../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 +
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +-
drivers/gpu/drm/drm_dp_mst_topology.c | 3 +-
drivers/gpu/drm/drm_fb_helper.c | 15 +-
drivers/gpu/drm/drm_modes.c | 4 +-
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +-
drivers/gpu/drm/gma500/psb_drv.c | 2 +
drivers/gpu/drm/i915/display/intel_hdmi.c | 6 +-
drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12 +-
drivers/gpu/drm/lima/lima_sched.c | 2 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8 +
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 10 +-
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 10 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +-
drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 5 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +-
drivers/gpu/drm/msm/msm_drv.c | 3 +-
drivers/gpu/drm/msm/msm_gem_submit.c | 2 +
drivers/gpu/drm/msm/msm_kms.h | 8 +-
.../drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 +
drivers/gpu/drm/nouveau/nouveau_chan.c | 1 +
drivers/gpu/drm/nouveau/nouveau_connector.c | 1 +
drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3 +-
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5 +
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 59 +-
drivers/gpu/drm/rcar-du/rcar_cmm.c | 2 +-
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 +-
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 +-
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11 +
drivers/gpu/drm/scheduler/sched_main.c | 3 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 +-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/tegra/dc.c | 2 +-
drivers/gpu/drm/tegra/dsi.c | 2 +-
drivers/gpu/drm/tegra/hdmi.c | 2 +-
drivers/gpu/drm/tegra/hub.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 2 +-
drivers/gpu/drm/tegra/vic.c | 2 +-
drivers/gpu/drm/ttm/ttm_bo.c | 9 +-
drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++-
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +-
drivers/gpu/drm/virtio/virtgpu_gem.c | 8 +-
drivers/gpu/drm/virtio/virtgpu_kms.c | 1 +
drivers/hid/hid-core.c | 3 +
drivers/hid/hid-logitech-dj.c | 1 +
drivers/hid/wacom_wac.c | 7 +-
drivers/hsi/controllers/omap_ssi_core.c | 2 +-
drivers/hv/channel_mgmt.c | 3 +-
drivers/hwtracing/coresight/coresight-etm4x-core.c | 21 +-
.../hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +-
drivers/i2c/busses/i2c-bcm-iproc.c | 231 ++++++--
drivers/i2c/busses/i2c-brcmstb.c | 2 +-
drivers/i2c/busses/i2c-exynos5.c | 8 +-
drivers/i2c/busses/i2c-qcom-geni.c | 93 ++-
drivers/i3c/master/Kconfig | 1 +
drivers/ide/falconide.c | 3 +-
drivers/infiniband/core/cm.c | 8 +-
drivers/infiniband/core/cma.c | 70 ++-
drivers/infiniband/core/user_mad.c | 17 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 11 +-
drivers/infiniband/hw/hns/hns_roce_hem.c | 9 +-
drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 16 +
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 70 ++-
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 3 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 19 +-
drivers/infiniband/hw/hns/hns_roce_mr.c | 56 +-
drivers/infiniband/hw/hns/hns_roce_qp.c | 37 +-
drivers/infiniband/hw/hns/hns_roce_srq.c | 52 +-
drivers/infiniband/hw/mlx5/devx.c | 4 +-
drivers/infiniband/hw/mlx5/main.c | 14 +-
drivers/infiniband/hw/mlx5/qp.c | 27 +-
drivers/infiniband/sw/rxe/rxe_net.c | 5 +
drivers/infiniband/sw/rxe/rxe_recv.c | 27 +-
drivers/infiniband/sw/siw/siw.h | 2 +-
drivers/infiniband/sw/siw/siw_main.c | 2 +-
drivers/infiniband/sw/siw/siw_qp.c | 271 +++++----
drivers/infiniband/sw/siw/siw_qp_rx.c | 26 +-
drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +-
drivers/infiniband/sw/siw/siw_verbs.c | 20 +-
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2 +
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51 +-
drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1 +
drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 120 ++--
drivers/infiniband/ulp/rtrs/rtrs.c | 28 +-
drivers/input/joydev.c | 7 +-
drivers/input/joystick/xpad.c | 1 +
drivers/input/keyboard/Kconfig | 2 +-
drivers/input/misc/da7280.c | 3 +
drivers/input/serio/i8042-x86ia64io.h | 4 +
drivers/input/serio/serport.c | 4 +-
drivers/input/touchscreen/elo.c | 4 +-
drivers/input/touchscreen/raydium_i2c_ts.c | 3 +-
drivers/input/touchscreen/st1232.c | 9 +-
drivers/input/touchscreen/sur40.c | 1 +
drivers/input/touchscreen/zinitix.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 +
drivers/iommu/iommu.c | 23 +-
drivers/iommu/mtk_iommu.c | 2 +-
drivers/irqchip/Kconfig | 3 +-
drivers/irqchip/irq-loongson-pch-msi.c | 2 +-
drivers/irqchip/irq-ls-extirq.c | 2 +-
drivers/macintosh/adb-iop.c | 6 +-
drivers/mailbox/arm_mhuv2.c | 4 +-
drivers/mailbox/sprd-mailbox.c | 2 +-
drivers/md/bcache/bcache.h | 3 +
drivers/md/bcache/btree.c | 21 +-
drivers/md/bcache/journal.c | 4 +-
drivers/md/bcache/super.c | 20 +
drivers/md/dm-core.h | 4 +
drivers/md/dm-crypt.c | 1 +
drivers/md/dm-era-target.c | 93 +--
drivers/md/dm-table.c | 168 +++---
drivers/md/dm-writecache.c | 74 ++-
drivers/md/dm.c | 62 +-
drivers/md/dm.h | 2 +-
drivers/media/i2c/Kconfig | 1 +
drivers/media/i2c/max9286.c | 2 +-
drivers/media/i2c/ov5670.c | 3 +-
drivers/media/pci/cx25821/cx25821-core.c | 4 +-
drivers/media/pci/intel/ipu3/Kconfig | 3 +-
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +-
drivers/media/pci/saa7134/saa7134-empress.c | 5 +-
drivers/media/pci/smipcie/smipcie-ir.c | 46 +-
drivers/media/platform/aspeed-video.c | 6 +-
drivers/media/platform/marvell-ccic/mcam-core.c | 2 +
.../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 +-
.../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3 +-
drivers/media/platform/pxa_camera.c | 3 +
drivers/media/platform/qcom/camss/camss-video.c | 3 +-
drivers/media/platform/ti-vpe/cal.c | 4 +-
drivers/media/platform/vsp1/vsp1_drv.c | 4 +-
drivers/media/rc/ir_toy.c | 1 +
drivers/media/rc/mceusb.c | 2 +-
drivers/media/test-drivers/vidtv/vidtv_psi.c | 5 +-
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/media/v4l2-core/v4l2-ioctl.c | 32 +-
drivers/memory/mtk-smi.c | 4 +-
drivers/memory/ti-aemif.c | 8 +-
drivers/mfd/altera-sysmgr.c | 3 +-
drivers/mfd/bd9571mwv.c | 6 +-
drivers/mfd/gateworks-gsc.c | 2 +-
drivers/mfd/wm831x-auxadc.c | 3 +-
drivers/misc/cardreader/rts5227.c | 5 +
drivers/misc/eeprom/eeprom_93xx46.c | 1 +
drivers/misc/fastrpc.c | 7 +-
drivers/misc/mei/bus.c | 7 +
drivers/misc/mei/hbm.c | 2 +-
drivers/misc/mei/hw-me-regs.h | 5 +
drivers/misc/mei/interrupt.c | 33 +-
drivers/misc/mei/pci-me.c | 5 +
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +-
drivers/mmc/host/owl-mmc.c | 9 +-
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +-
drivers/mmc/host/sdhci-esdhc-imx.c | 3 +-
drivers/mmc/host/sdhci-pci-o2micro.c | 20 +
drivers/mmc/host/sdhci-sprd.c | 6 +-
drivers/mmc/host/usdhi6rol0.c | 4 +-
drivers/mtd/devices/phram.c | 6 +-
drivers/mtd/nand/raw/intel-nand-controller.c | 6 +-
drivers/mtd/parsers/afs.c | 4 +-
drivers/mtd/parsers/parser_imagetag.c | 4 +
drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4 +-
drivers/mtd/spi-nor/core.c | 10 +-
drivers/mtd/spi-nor/sfdp.c | 5 +-
drivers/net/Kconfig | 2 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +-
drivers/net/dsa/ocelot/felix.c | 16 +-
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 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +-
.../chelsio/inline_crypto/chtls/chtls_cm.h | 3 -
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +-
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14 +-
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
drivers/net/ethernet/ibm/ibmvnic.c | 43 +-
drivers/net/ethernet/ibm/ibmvnic.h | 7 +-
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 62 +-
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 11 +-
drivers/net/ethernet/intel/i40e/i40e_xsk.c | 2 +-
drivers/net/ethernet/intel/ice/ice.h | 2 -
drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6 +-
drivers/net/ethernet/intel/ice/ice_ethtool.c | 34 +-
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33 +-
drivers/net/ethernet/marvell/mvneta.c | 9 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2 +-
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9 +
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 +++++---
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2 +-
.../mellanox/mlx5/core/en_accel/en_accel.h | 2 +-
.../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66 +--
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/fpga/ipsec.h | 2 +
drivers/net/ethernet/mellanox/mlx5/core/health.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 +-
drivers/net/ethernet/realtek/r8169_main.c | 4 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 +-
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26 +-
drivers/net/gtp.c | 1 -
drivers/net/ipa/ipa_main.c | 4 +-
drivers/net/phy/micrel.c | 1 +
drivers/net/phy/mscc/Makefile | 1 +
drivers/net/phy/mscc/mscc.h | 28 +
drivers/net/phy/mscc/mscc_main.c | 608 +++++++++++--------
drivers/net/phy/mscc/mscc_serdes.c | 650 +++++++++++++++++++++
drivers/net/phy/mscc/mscc_serdes.h | 31 +
drivers/net/phy/phy_device.c | 53 +-
drivers/net/phy/sfp.c | 100 ++--
drivers/net/ppp/ppp_async.c | 3 +-
drivers/net/ppp/ppp_synctty.c | 3 +-
drivers/net/vxlan.c | 11 +-
drivers/net/wireguard/device.c | 19 +-
drivers/net/wireguard/device.h | 15 +-
drivers/net/wireguard/peer.c | 28 +-
drivers/net/wireguard/peer.h | 4 +-
drivers/net/wireguard/queueing.c | 86 ++-
drivers/net/wireguard/queueing.h | 45 +-
drivers/net/wireguard/receive.c | 16 +-
drivers/net/wireguard/send.c | 31 +-
drivers/net/wireless/ath/ath10k/mac.c | 2 +
drivers/net/wireless/ath/ath10k/snoc.c | 5 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +
drivers/net/wireless/ath/ath11k/mac.c | 11 +-
drivers/net/wireless/ath/ath9k/debug.c | 5 +-
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43 +-
.../net/wireless/intel/iwlwifi/mvm/time-event.c | 3 -
.../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21 +-
drivers/net/xen-netback/interface.c | 8 +-
drivers/nvme/host/multipath.c | 4 +
drivers/nvme/target/admin-cmd.c | 33 +-
drivers/nvme/target/tcp.c | 59 +-
drivers/nvmem/core.c | 5 +-
drivers/nvmem/qcom-spmi-sdam.c | 7 +-
drivers/of/fdt.c | 12 +-
drivers/opp/of.c | 4 +-
drivers/pci/controller/cadence/pcie-cadence-host.c | 5 +-
drivers/pci/controller/dwc/pcie-qcom.c | 4 +-
drivers/pci/controller/pcie-rcar-host.c | 2 +-
drivers/pci/controller/pcie-rockchip.c | 12 +-
drivers/pci/controller/pcie-xilinx-cpm.c | 1 +
drivers/pci/pci-bridge-emul.c | 11 +-
drivers/pci/setup-res.c | 6 +
drivers/pci/syscall.c | 10 +-
drivers/perf/arm-cmn.c | 17 +-
drivers/phy/Kconfig | 1 +
drivers/phy/cadence/phy-cadence-torrent.c | 1 +
drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10 +-
drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +-
drivers/platform/chrome/cros_ec_proto.c | 12 +-
drivers/platform/x86/Kconfig | 4 +-
drivers/power/reset/at91-sama5d2_shdwc.c | 2 +-
drivers/power/supply/Kconfig | 1 +
drivers/power/supply/axp20x_usb_power.c | 2 +-
drivers/power/supply/cpcap-battery.c | 12 +-
drivers/power/supply/cpcap-charger.c | 4 +-
drivers/power/supply/smb347-charger.c | 12 +-
drivers/pwm/pwm-iqs620a.c | 8 +-
drivers/pwm/pwm-rockchip.c | 18 +-
drivers/regulator/axp20x-regulator.c | 7 +-
drivers/regulator/core.c | 6 +-
drivers/regulator/qcom-rpmh-regulator.c | 26 +
drivers/regulator/rohm-regulator.c | 9 +-
drivers/regulator/s5m8767.c | 15 +-
drivers/remoteproc/mtk_common.h | 1 +
drivers/remoteproc/mtk_scp.c | 20 +-
drivers/rtc/Kconfig | 3 +-
drivers/rtc/rtc-rx6110.c | 4 +-
drivers/s390/crypto/zcrypt_api.c | 14 +
drivers/s390/virtio/virtio_ccw.c | 4 +-
drivers/scsi/aic94xx/aic94xx_scb.c | 20 +-
drivers/scsi/bnx2fc/Kconfig | 1 +
drivers/scsi/hisi_sas/hisi_sas_main.c | 12 +-
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 +-
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +-
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +-
drivers/scsi/isci/port.c | 11 +-
drivers/scsi/libsas/sas_event.c | 66 ++-
drivers/scsi/libsas/sas_init.c | 27 +-
drivers/scsi/libsas/sas_internal.h | 5 +-
drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +-
drivers/scsi/mvsas/mv_sas.c | 25 +-
drivers/scsi/pm8001/pm8001_hwi.c | 40 +-
drivers/scsi/pm8001/pm8001_sas.c | 7 +-
drivers/scsi/pm8001/pm80xx_hwi.c | 35 +-
drivers/scsi/qla2xxx/qla_dbg.c | 1 +
drivers/scsi/qla2xxx/qla_mbx.c | 3 +-
drivers/scsi/sd.c | 6 +-
drivers/scsi/sd_zbc.c | 6 +-
drivers/scsi/ufs/ufshcd.c | 17 +-
drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +-
drivers/soc/aspeed/aspeed-socinfo.c | 33 +-
drivers/soc/qcom/ocmem.c | 8 +-
drivers/soc/qcom/socinfo.c | 2 +-
drivers/soc/samsung/exynos-asv.c | 18 +-
drivers/soc/ti/pm33xx.c | 5 +-
drivers/soundwire/bus.c | 47 +-
drivers/soundwire/cadence_master.c | 8 +-
drivers/soundwire/debugfs.c | 2 +-
drivers/soundwire/intel_init.c | 3 +-
drivers/spi/spi-atmel.c | 2 +-
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-dw-bt1.c | 2 +-
drivers/spi/spi-fsl-spi.c | 2 +-
drivers/spi/spi-imx.c | 2 +-
drivers/spi/spi-pxa2xx-pci.c | 27 +-
drivers/spi/spi-stm32.c | 4 +
drivers/spi/spi-synquacer.c | 4 +
drivers/spi/spi.c | 2 +-
drivers/spmi/spmi-pmic-arb.c | 5 +-
drivers/staging/gdm724x/gdm_usb.c | 10 +-
drivers/staging/media/allegro-dvt/allegro-core.c | 3 +-
drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24 +-
drivers/staging/media/atomisp/pci/hmm/hmm.c | 2 +-
drivers/staging/media/imx/imx-media-csc-scaler.c | 4 -
drivers/staging/media/imx/imx-media-dev.c | 7 +-
drivers/staging/media/imx/imx7-media-csi.c | 27 +-
drivers/staging/mt7621-dma/Makefile | 2 +-
.../mt7621-dma/{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 +-
.../vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 +-
drivers/staging/wfx/data_tx.c | 10 +-
drivers/staging/wfx/data_tx.h | 1 +
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-
drivers/tee/optee/rpc.c | 31 +-
drivers/thermal/cpufreq_cooling.c | 2 +-
drivers/tty/n_gsm.c | 3 +-
drivers/tty/n_hdlc.c | 60 +-
drivers/tty/n_null.c | 3 +-
drivers/tty/n_r3964.c | 10 +-
drivers/tty/n_tracerouter.c | 4 +-
drivers/tty/n_tracesink.c | 4 +-
drivers/tty/n_tty.c | 82 ++-
drivers/tty/serial/stm32-usart.c | 24 +-
drivers/tty/tty_io.c | 82 ++-
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/usb/serial/pl2303.c | 8 +-
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
drivers/vfio/pci/vfio_pci_zdev.c | 4 +
drivers/vfio/vfio_iommu_type1.c | 48 +-
drivers/video/fbdev/Kconfig | 2 +-
drivers/virt/vboxguest/vboxguest_utils.c | 18 +-
drivers/w1/slaves/w1_therm.c | 22 +-
drivers/watchdog/intel-mid_wdt.c | 8 +-
drivers/watchdog/mei_wdt.c | 1 +
drivers/watchdog/qcom-wdt.c | 13 +-
fs/affs/namei.c | 4 +-
fs/btrfs/backref.c | 9 +-
fs/btrfs/backref.h | 9 +-
fs/btrfs/block-group.c | 29 +-
fs/btrfs/ctree.c | 7 +-
fs/btrfs/delayed-ref.c | 56 +-
fs/btrfs/delayed-ref.h | 16 +-
fs/btrfs/extent-tree.c | 128 +---
fs/btrfs/free-space-cache.c | 6 +-
fs/btrfs/inode.c | 3 +-
fs/btrfs/relocation.c | 4 +-
fs/btrfs/space-info.h | 17 +
fs/ceph/caps.c | 10 +-
fs/cifs/cifs_swn.c | 2 +-
fs/cifs/connect.c | 259 ++++----
fs/cifs/dfs_cache.c | 33 +-
fs/cifs/fs_context.c | 43 +-
fs/debugfs/inode.c | 5 +-
fs/erofs/xattr.c | 10 +-
fs/erofs/zmap.c | 10 +-
fs/eventpoll.c | 4 +-
fs/exfat/exfat_raw.h | 4 +
fs/exfat/super.c | 31 +-
fs/ext4/Kconfig | 3 +-
fs/ext4/namei.c | 7 +-
fs/f2fs/compress.c | 5 +-
fs/f2fs/data.c | 12 +-
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 30 +-
fs/f2fs/inline.c | 4 +
fs/f2fs/super.c | 3 +
fs/gfs2/bmap.c | 6 +-
fs/gfs2/lock_dlm.c | 8 +-
fs/gfs2/recovery.c | 4 +-
fs/gfs2/util.c | 16 +-
fs/io_uring.c | 17 +-
fs/isofs/dir.c | 1 +
fs/isofs/namei.c | 1 +
fs/jffs2/summary.c | 3 +
fs/jfs/jfs_dmap.c | 2 +-
fs/nfs/nfs4proc.c | 15 +-
fs/nfsd/nfsctl.c | 14 +-
fs/ocfs2/cluster/heartbeat.c | 8 +-
fs/proc/proc_sysctl.c | 4 +-
fs/proc/self.c | 2 +-
fs/proc/task_mmu.c | 9 +-
fs/proc/thread_self.c | 7 +
fs/pstore/platform.c | 4 +-
fs/quota/quota_v2.c | 11 +-
fs/ubifs/auth.c | 2 +-
fs/ubifs/replay.c | 4 +-
fs/ubifs/super.c | 4 +-
fs/zonefs/super.c | 3 +
include/acpi/acexcep.h | 10 +-
include/asm-generic/vmlinux.lds.h | 16 +-
include/linux/bpf.h | 8 +-
include/linux/device-mapper.h | 5 +
include/linux/entry-kvm.h | 14 +
include/linux/eventpoll.h | 2 +-
include/linux/filter.h | 2 +-
include/linux/icmpv6.h | 28 +-
include/linux/iommu.h | 4 +-
include/linux/ipv6.h | 1 -
include/linux/kexec.h | 5 +
include/linux/key.h | 1 +
include/linux/kgdb.h | 2 +
include/linux/khugepaged.h | 2 +
include/linux/memremap.h | 6 +
include/linux/mfd/rohm-generic.h | 14 +-
include/linux/rcupdate.h | 2 +
include/linux/rmap.h | 3 +-
include/linux/soundwire/sdw.h | 2 +
include/linux/tpm.h | 5 +-
include/linux/tty_ldisc.h | 3 +-
include/linux/zsmalloc.h | 2 +-
include/net/act_api.h | 6 +-
include/net/icmp.h | 6 +-
include/net/tcp.h | 9 +-
include/scsi/libsas.h | 11 +-
include/uapi/drm/drm_fourcc.h | 4 +-
include/uapi/drm/drm_mode.h | 13 +-
init/Kconfig | 11 +
init/main.c | 1 +
kernel/Makefile | 2 +-
kernel/bpf/bpf_iter.c | 2 +-
kernel/bpf/bpf_lru_list.c | 7 +-
kernel/bpf/devmap.c | 4 +-
kernel/bpf/verifier.c | 3 +-
kernel/debug/debug_core.c | 11 +
kernel/debug/kdb/kdb_private.h | 2 +-
kernel/entry/common.c | 7 +
kernel/kcsan/core.c | 26 +-
kernel/kexec_file.c | 5 +
kernel/kprobes.c | 31 +-
kernel/locking/lockdep.c | 3 +-
kernel/module.c | 164 +++++-
kernel/module_signature.c | 2 +-
kernel/module_signing.c | 2 +-
kernel/printk/printk.c | 28 +-
kernel/printk/printk_safe.c | 16 +-
kernel/rcu/tree.c | 53 +-
kernel/rcu/tree.h | 2 +-
kernel/rcu/tree_plugin.h | 31 +-
kernel/sched/fair.c | 45 +-
kernel/sched/idle.c | 1 +
kernel/seccomp.c | 2 +
kernel/smp.c | 4 +
kernel/tracepoint.c | 80 ++-
mm/compaction.c | 43 +-
mm/hugetlb.c | 14 +-
mm/khugepaged.c | 22 +-
mm/memcontrol.c | 30 +-
mm/memory-failure.c | 6 +
mm/memory.c | 16 +-
mm/memremap.c | 15 +
mm/slab_common.c | 4 +-
mm/slub.c | 8 +-
mm/vmscan.c | 9 +-
mm/zsmalloc.c | 17 +-
net/bluetooth/a2mp.c | 3 +-
net/bluetooth/hci_core.c | 6 +-
net/bluetooth/hci_request.c | 25 +-
net/core/filter.c | 13 +-
net/ipv4/icmp.c | 5 +-
net/ipv6/icmp.c | 18 +-
net/ipv6/ip6_icmp.c | 12 +-
net/mac80211/mesh_hwmp.c | 2 +-
net/nfc/nci/uart.c | 3 +-
net/qrtr/tun.c | 12 +-
net/sched/act_api.c | 106 ++--
net/sched/cls_api.c | 12 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 6 +-
samples/Kconfig | 2 +-
samples/watch_queue/watch_test.c | 2 +-
security/commoncap.c | 12 +-
security/integrity/evm/evm_crypto.c | 7 +-
security/integrity/ima/ima_kexec.c | 3 +
security/integrity/ima/ima_mok.c | 5 +-
security/keys/Kconfig | 8 +-
security/keys/key.c | 2 +
security/keys/trusted-keys/trusted_tpm1.c | 22 +-
security/keys/trusted-keys/trusted_tpm2.c | 22 +-
security/selinux/hooks.c | 4 +
sound/core/init.c | 4 +
sound/core/pcm.c | 4 +
sound/core/pcm_local.h | 1 +
sound/core/pcm_native.c | 27 +-
sound/firewire/fireface/ff-protocol-latter.c | 118 +++-
sound/pci/hda/hda_intel.c | 2 +
sound/pci/hda/patch_hdmi.c | 1 -
sound/pci/hda/patch_realtek.c | 40 ++
sound/soc/codecs/cpcap.c | 12 +-
sound/soc/codecs/cs42l56.c | 3 +-
sound/soc/codecs/max98373.c | 2 +-
sound/soc/codecs/rt5682-i2c.c | 3 +
sound/soc/codecs/wsa881x.c | 1 +
sound/soc/fsl/Kconfig | 1 +
sound/soc/generic/simple-card-utils.c | 13 +-
sound/soc/intel/boards/sof_sdw.c | 9 +-
sound/soc/qcom/lpass-apq8016.c | 2 +-
sound/soc/qcom/lpass-cpu.c | 30 +-
sound/soc/qcom/lpass-lpaif-reg.h | 3 -
sound/soc/qcom/lpass-sc7180.c | 2 +-
sound/soc/qcom/lpass.h | 1 -
sound/soc/qcom/qdsp6/q6asm-dai.c | 21 +
sound/soc/qcom/qdsp6/q6routing.c | 18 -
sound/soc/sh/siu.h | 2 +-
sound/soc/sh/siu_pcm.c | 2 +-
sound/soc/sof/debug.c | 2 +-
sound/soc/sof/intel/hda-dsp.c | 4 +
sound/soc/sof/sof-pci-dev.c | 7 +
sound/usb/card.h | 2 +-
sound/usb/endpoint.c | 87 +--
sound/usb/implicit.c | 2 +
sound/usb/pcm.c | 7 +-
tools/lib/bpf/libbpf.c | 22 +-
tools/objtool/arch/x86/special.c | 2 +-
tools/objtool/check.c | 15 +-
tools/objtool/check.h | 11 +
tools/perf/builtin-record.c | 2 +-
.../pmu-events/arch/arm64/ampere/emag/cache.json | 2 +-
tools/perf/tests/sample-parsing.c | 2 +-
tools/perf/util/cgroup.c | 8 +-
tools/perf/util/event.c | 2 +
tools/perf/util/evlist.c | 8 +
tools/perf/util/evlist.h | 4 +
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 41 +-
.../perf/util/intel-pt-decoder/intel-pt-decoder.h | 2 +
tools/perf/util/intel-pt.c | 29 +-
tools/perf/util/symbol.c | 7 +-
tools/perf/util/unwind-libdw.c | 11 +-
tools/testing/kunit/kunit_tool_test.py | 14 +-
tools/testing/scatterlist/main.c | 1 -
.../selftests/bpf/prog_tests/btf_map_in_map.c | 33 --
tools/testing/selftests/bpf/test_progs.c | 13 +-
tools/testing/selftests/bpf/test_progs.h | 1 +
tools/testing/selftests/bpf/test_xdp_redirect.sh | 10 +-
tools/testing/selftests/dmabuf-heaps/Makefile | 2 +-
.../trigger-synthetic_event_syntax_errors.tc | 35 +-
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 +-
tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +-
tools/testing/selftests/seccomp/seccomp_bpf.c | 2 +-
tools/testing/selftests/wireguard/netns.sh | 15 +-
779 files changed, 7955 insertions(+), 3974 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.10 000/658] 5.10.20-rc3 review
@ 2021-03-02 12:38 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-02 12:38 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.10.20 release.
There are 658 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu, 04 Mar 2021 12:32:41 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.20-rc3.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.20-rc3
Cong Wang <cong.wang@bytedance.com>
net_sched: fix RTNL deadlock again caused by request_module()
Takeshi Misawa <jeliantsurux@gmail.com>
net: qrtr: Fix memory leak in qrtr_tun_open
Vlad Buslov <vladbu@nvidia.com>
net: sched: fix police ext initialization
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: get rid of per-peer ring buffers
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: selftests: test multiple parallel streams
Jason A. Donenfeld <Jason@zx2c4.com>
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Leon Romanovsky <leon@kernel.org>
ipv6: silence compilation warning for non-IPV6 builds
Sumit Garg <sumit.garg@linaro.org>
kgdb: fix to kill breakpoints on initmem after boot
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/i915: Reject 446-480MHz HDMI clock on GLK
Nikos Tsironis <ntsironis@arrikto.com>
dm era: only resize metadata in preresume
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Reinitialize bitset cache before digesting a new writeset
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Use correct value size in equality function of writeset tree
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Fix bitset memory leaks
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Verify the data block size hasn't changed
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Update in-core bitset after committing the metadata
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Recover committed writeset after crash
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix writing beyond end of underlying device when shrinking
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: return the exact table values that were set
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix performance degradation in ssd mode
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix zoned iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix DAX iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix iterate_devices based device capability checks
Mikulas Patocka <mpatocka@redhat.com>
dm: fix deadlock when swapping to encrypted device
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Lock imbalance on error path in gfs2_recover_one
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't skip dlm unlock if glock has an lvb
Bob Peterson <rpeterso@redhat.com>
gfs2: fix glock confusion in function signal_our_withdraw
Masahisa Kojima <masahisa.kojima@linaro.org>
spi: spi-synquacer: fix set_cs handling
Rasmus Villemoes <rasmus.villemoes@prevas.dk>
spi: fsl: invert spisel_boot signal on MPC8309
Al Viro <viro@zeniv.linux.org.uk>
sparc32: fix a user-triggerable oops in clear_user()
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: flush data when enabling checkpoint back
Chao Yu <chao@kernel.org>
f2fs: enforce the immutable flag on open files
Chao Yu <chao@kernel.org>
f2fs: fix out-of-repair __setattr_copy()
Huacai Chen <chenhuacai@loongson.cn>
irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Johannes Berg <johannes.berg@intel.com>
um: defer killing userspace on page table update failures
Johannes Berg <johannes.berg@intel.com>
um: mm: check more comprehensively for stub changes
Cornelia Huck <cohuck@redhat.com>
virtio/s390: implement virtio-ccw revision 2 correctly
Heiko Carstens <hca@linux.ibm.com>
s390/vtime: fix inline assembly clobber list
Jens Axboe <axboe@kernel.dk>
proc: don't allow async path resolution of /proc/thread-self components
Chen Yu <yu.c.chen@intel.com>
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Shawn Guo <shawn.guo@linaro.org>
cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Viresh Kumar <viresh.kumar@linaro.org>
thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Chris Wilson <chris@chris-wilson.co.uk>
kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
zonefs: Fix file size of zones in full condition
Namjae Jeon <namjae.jeon@samsung.com>
exfat: fix shift-out-of-bounds in exfat_fill_super()
Muchun Song <songmuchun@bytedance.com>
printk: fix deadlock when kernel panic
Tim Harvey <tharvey@gateworks.com>
mfd: gateworks-gsc: Fix interrupt type
Maxim Kiselev <bigunclemax@gmail.com>
gpio: pcf857x: Fix missing first interrupt
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point LP DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point S DID
Tomas Winkler <tomas.winkler@intel.com>
mei: me: emmitsburg workstation DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: fix transfer over dma with extended header
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
spmi: spmi-pmic-arb: Fix hw_irq overflow
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32s: Add missing call to kuep_lock on syscall entry
Hari Bathini <hbathini@linux.ibm.com>
powerpc/kexec_file: fix FDT size estimation for kdump kernel
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
Shirley Her <shirley.her@bayhubtech.com>
mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Frank Li <Frank.Li@nxp.com>
mmc: sdhci-esdhc-imx: fix kernel panic when remove module
Fangrui Song <maskray@google.com>
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
Paolo Bonzini <pbonzini@redhat.com>
KVM: nSVM: fix running nested guests when npt=0
Vlastimil Babka <vbabka@suse.cz>
mm, compaction: make fast_isolate_freepages() stay within zone
Dave Hansen <dave.hansen@linux.intel.com>
mm/vmscan: restore zone_reclaim_mode ABI
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix update_and_free_page contig page struct assumption
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix get_active_memcg return value
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix swap undercounting in cgroup2
NeilBrown <neilb@suse.de>
x86: fix seq_file iteration for pat/memtype.c
NeilBrown <neilb@suse.de>
seq_file: document how per-entry resources are managed.
Pan Bian <bianpan2016@163.com>
fs/affs: release old buffer head on error path
Pan Bian <bianpan2016@163.com>
mtd: spi-nor: hisi-sfc: Put child node np on error path
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Add erase size check for erase command initialization
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Fix erase type discovery for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix last erase region marking
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Handle accesses to TRCSTALLCTLR
Alexander Usyskin <alexander.usyskin@intel.com>
watchdog: mei_wdt: request stop on unregister
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Tobias Klauser <tklauser@distanz.ch>
riscv: Disable KSAN_SANITIZE for vDSO
Will Deacon <will@kernel.org>
arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Shaoying Xu <shaoyi@amazon.com>
arm64 module: set plt* section addresses to 0x0
He Zhe <zhe.he@windriver.com>
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
qiuguorui1 <qiuguorui1@huawei.com>
arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
Isaac J. Manjarres <isaacm@codeaurora.org>
iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Suzuki K Poulose <suzuki.poulose@arm.com>
arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
Masami Hiramatsu <mhiramat@kernel.org>
kprobes: Fix to delay the kprobes jump optimization
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Perform deferred wake up before last idle's need_resched() check
Frederic Weisbecker <frederic@kernel.org>
rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
Cédric Le Goater <clg@kaod.org>
powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Thomas Gleixner <tglx@linutronix.de>
x86/entry: Fix instrumentation annotation
Andy Lutomirski <luto@kernel.org>
x86/fault: Fix AMD erratum #91 errata fixup for user code
Sean Christopherson <seanjc@google.com>
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Christopherson <seanjc@google.com>
x86/virt: Eat faults on VMXOFF in reboot flows
Sean Young <sean@mess.org>
media: smipcie: fix interrupt handling and IR timeout
Lubomir Rintel <lkundrak@v3.sk>
media: marvell-ccic: power up the device on mclk enable
Pavel Machek <pavel@denx.de>
media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
Sean Young <sean@mess.org>
media: ir_toy: add another IR Droid device
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: i2c: max9286: fix access to unallocated memory
Jiri Kosina <jkosina@suse.cz>
floppy: reintroduce O_NDELAY fix
Martin Kaiser <martin@kaiser.cx>
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Amey Narkhede <ameynarkhede03@gmail.com>
staging: gdm724x: Fix DMA from stack
Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Dinh Nguyen <dinguyen@kernel.org>
arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Frank Wunderlich <frank-w@public-files.de>
dts64: mt7622: fix slow sd card access
Jiri Bohac <jbohac@suse.cz>
pstore: Fix typo in compression option name
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Ricky Wu <ricky_wu@realtek.com>
misc: rtsx: init of rts522a add OCP power off when no card is present
Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Paul Cercueil <paul@crapouillou.net>
seccomp: Add missing return in non-void function
Krzysztof Kozlowski <krzk@kernel.org>
soc: samsung: exynos-asv: handle reading revision register error
Marek Szyprowski <m.szyprowski@samsung.com>
soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - initialize need_fallback
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - handle BigEndian for cipher
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - IV register does not work on A10 and A13
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - checking sg length is not sufficient
Ard Biesheuvel <ardb@kernel.org>
crypto: michael_mic - fix broken misalignment handling
Ard Biesheuvel <ardb@kernel.org>
crypto: aesni - prevent misaligned buffers on the stack
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/sha - add missing module aliases
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Correct surface base address for renderclear
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Flush before changing register state
Filipe Manana <fdmanana@suse.com>
btrfs: fix extent buffer leak on failure to copy root
Josef Bacik <josef@toxicpanda.com>
btrfs: account for new extents being deleted in total_bytes_pinned
Josef Bacik <josef@toxicpanda.com>
btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
Josef Bacik <josef@toxicpanda.com>
btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
Josef Bacik <josef@toxicpanda.com>
btrfs: fix reloc root leak with 0 ref reloc roots on recovery
Josef Bacik <josef@toxicpanda.com>
btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
Josef Bacik <josef@toxicpanda.com>
btrfs: add asserts for deleting backref cache nodes
Josef Bacik <josef@toxicpanda.com>
btrfs: do not warn if we can't find the reloc root when looking up backref
Josef Bacik <josef@toxicpanda.com>
btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Reserve TPM for seal and unseal operations
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix migratable=1 failing
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix incorrect handling of tpm_get_random()
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Clean up locality release
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Fix check_locality for correct locality acquisition
Gao Xiang <hsiangkao@redhat.com>
erofs: initialized fields can only be observed after bit is set
Amir Goldstein <amir73il@gmail.com>
selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Takashi Iwai <tiwai@suse.de>
ASoC: siu: Fix build error by a wrong const prefix
Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
drm/rockchip: Require the YTR modifier for AFBC
Heiko Stuebner <heiko@sntech.de>
drm/panel: kd35t133: allow using non-continuous dsi clock
Andrey Grodzovsky <andrey.grodzovsky@amd.com>
drm/sched: Cancel and flush all outstanding jobs before finish.
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/modes: Switch to 64bit maths to avoid integer overflow
Karol Herbst <kherbst@redhat.com>
drm/nouveau/kms: handle mDP connectors
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Felix Kuehling <Felix.Kuehling@amd.com>
drm/amdkfd: Fix recursive lock warnings
Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Eric Bernstein <eric.bernstein@amd.com>
drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Jan Kokemüller <jan.kokemueller@gmail.com>
drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Alex Deucher <alexander.deucher@amd.com>
Revert "drm/amd/display: Update NV1x SR latency values"
Kai Krakow <kai@kaishome.de>
bcache: Move journal work to new flush wq
Kai Krakow <kai@kaishome.de>
bcache: Give btree_io_wq correct semantics again
Kai Krakow <kai@kaishome.de>
Revert "bcache: Kill btree_io_wq"
Kevin Hao <haokexin@gmail.com>
Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Nathan Chancellor <natechancellor@gmail.com>
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
Aurelien Jarno <aurelien@aurel32.net>
MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Paul Cercueil <paul@crapouillou.net>
MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
Takashi Iwai <tiwai@suse.de>
ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
PeiSen Hou <pshou@realtek.com>
ALSA: hda/realtek: modify EAPD in the ALC886
Takashi Iwai <tiwai@suse.de>
ALSA: hda/hdmi: Drop bogus check at closing a stream
Kai Vehmanen <kai.vehmanen@linux.intel.com>
ALSA: hda: Add another CometLake-H PCI ID
Takashi Sakamoto <o-takashi@sakamocchi.jp>
ALSA: fireface: fix to parse sync status register of latter protocol
Mathias Kresin <dev@kresin.me>
phy: lantiq: rcu-usb2: wait after clock enable
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7720: fix error code in mos7720_write()
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7840: fix error code in mos7840_write()
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix line-speed handling on newer chips
Johan Hovold <johan@kernel.org>
USB: serial: ftdi_sio: fix FTX sub-integer prescaler
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
Paul Cercueil <paul@crapouillou.net>
usb: musb: Fix runtime PM race in musb_queue_resume_work
Lech Perczak <lech.perczak@gmail.com>
USB: serial: option: update interface mapping for ZTE P685M
James Reynolds <jr@memlen.com>
media: mceusb: Fix potential out-of-bounds shift
Marcos Paulo de Souza <mpdesouza@suse.com>
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Dan Carpenter <dan.carpenter@oracle.com>
Input: joydev - prevent potential read overflow in ioctl
Olivier Crête <olivier.crete@ocrete.ca>
Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
jeffrey.lin <jeffrey.lin@rad-ic.com>
Input: raydium_ts_i2c - do not send zero length
Jason Gerecke <killertofu@gmail.com>
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Filipe Laíns <lains@riseup.net>
HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
Qinglang Miao <miaoqinglang@huawei.com>
ACPI: configfs: add missing check after configfs_register_default_group()
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: property: Fix fwnode string properties matching
Marcin Ślusarz <marcin.slusarz@intel.com>
soundwire: intel: fix possible crash when no device is detected
Mikulas Patocka <mpatocka@redhat.com>
blk-settings: align max_sectors on "logical_block_size" boundary
Bart Van Assche <bvanassche@acm.org>
scsi: sd: Fix Opal support
Finn Thain <fthain@telegraphics.com.au>
ide/falconide: Fix module unload
Christoph Hellwig <hch@lst.de>
block: reopen the device in blkdev_reread_part
Johannes Thumshirn <johannes.thumshirn@wdc.com>
scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
Randy Dunlap <rdunlap@infradead.org>
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Zhenzhong Duan <zhenzhong.duan@gmail.com>
csky: Fix a size determination in gpr_get()
Josef Bacik <josef@toxicpanda.com>
proc: use kvzalloc for our kernel buffer
Miaohe Lin <linmiaohe@huawei.com>
mm/rmap: fix potential pte_unmap on an not mapped pte
Dan Williams <dan.j.williams@intel.com>
mm: fix memory_failure() handling of dax-namespace metadata
Rik van Riel <riel@surriel.com>
mm,thp,shmem: make khugepaged obey tmpfs mount flags
Mårten Lindahl <martenli@axis.com>
i2c: exynos5: Preserve high speed master code
Maxime Ripard <maxime@cerno.tech>
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Marc Zyngier <maz@kernel.org>
arm64: Add missing ISB after invalidating TLB in __primary_switch
Sean Christopherson <seanjc@google.com>
KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
Sean Christopherson <seanjc@google.com>
KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4: Fixes for nfs4_bitmask_adjust()
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix jumbo packet handling on RTL8168e
Wonhyuk Yang <vvghjk1234@gmail.com>
mm/compaction: fix misbehaviors of fast_find_migrateblock()
Chen Wandun <chenwandun@huawei.com>
mm/hugetlb: suppress wrong warning info when alloc gigantic page
Miaohe Lin <linmiaohe@huawei.com>
mm/hugetlb: fix potential double free in hugetlb_register_node() error path
Miaohe Lin <linmiaohe@huawei.com>
mm/memory.c: fix potential pte_unmap_unlock pte error
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix slub memory accounting
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
Dan Carpenter <dan.carpenter@oracle.com>
ocfs2: fix a use after free on error
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: kconfig: use arm chacha even with no neon
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: device: do not generate ICMP for non-IP packets
Taehee Yoo <ap420073@gmail.com>
vxlan: move debug check after netdev unregister
Chen-Yu Tsai <wens@csie.org>
PCI: rockchip: Make 'ep-gpios' DT property optional
Chuhong Yuan <hslester96@gmail.com>
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Song, Yoong Siang <yoong.siang.song@intel.com>
net: stmmac: fix CBS idleslope and sendslope calculation
Henry Tieman <henry.w.tieman@intel.com>
ice: update the number of available RSS queues
Dave Ertman <david.m.ertman@intel.com>
ice: Fix state bits on LLDP mode switch
Brett Creeley <brett.creeley@intel.com>
ice: Account for port VLAN in VF max packet size calculation
Dave Ertman <david.m.ertman@intel.com>
ice: report correct max number of TCs
Alex Williamson <alex.williamson@redhat.com>
vfio/type1: Use follow_pte()
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
pwm: iqs620a: Fix overflow and optimize calculations
Dan Carpenter <dan.carpenter@oracle.com>
octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix add TC filter for IPv6
Andreas Oetken <andreas.oetken@siemens.com>
nios2: fixed broken sys_clone syscall
Jann Horn <jannh@google.com>
Take mmap lock in cacheflush syscall
Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
i40e: Fix VFs not created
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix addition of RX filters after enabling FW LLDP agent
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix overwriting flow control settings during driver loading
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Add zero-initialization of AQ command structures
Slawomir Laba <slawomirx.laba@intel.com>
i40e: Fix flow for IPv6 next header (extension header)
Krzysztof Wilczyński <kw@linux.com>
PCI: cadence: Fix DMA range mapping early return error
Russell King <rmk+kernel@armlinux.org.uk>
PCI: pci-bridge-emul: Fix array overruns, improve safety
Shiyang Ruan <ruansy.fnst@cn.fujitsu.com>
device-dax: Fix default return code of range_parse()
Magnum Shan <magnum.shan@unisoc.com>
mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Geert Uytterhoeven <geert@linux-m68k.org>
ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Bard Liao <yung-chuan.liao@linux.intel.com>
regmap: sdw: use _no_pm functions in regmap_read/write
Tzung-Bi Shih <tzungbi@google.com>
remoteproc/mediatek: acknowledge watchdog IRQ after handled
Jonathan Marek <jonathan@marek.ca>
misc: fastrpc: fix incorrect usage of dma_map_sgtable
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: fix confusion on device used by pm_runtime
Bard Liao <yung-chuan.liao@linux.intel.com>
soundwire: export sdw_write/read_no_pm functions
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_update_no_pm when initializing a device
Ahmad Fatoum <a.fatoum@pengutronix.de>
nvmem: core: skip child nodes not matching binding
Dan Carpenter <dan.carpenter@oracle.com>
nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Skip accessing TRCPDCR in save/restore
Geert Uytterhoeven <geert+renesas@glider.be>
phy: USB_LGM_PHY should depend on X86
Theodore Ts'o <tytso@mit.edu>
ext4: fix potential htree index checksum corruption
Max Gurtovoy <mgurtovoy@nvidia.com>
vfio-pci/zdev: fix possible segmentation fault issue
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Fix some sanity checks in detach group
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Populate full dirty when detach non-pinned group
Judy Hsiao <judyhsiao@google.com>
drm/msm/dp: trigger unplug event in msm_dp_display_disable
Eric Anholt <eric@anholt.net>
drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Anholt <eric@anholt.net>
drm/msm: Fix race of GPU init vs timestamp power management.
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm/mdp5: Fix wait-for-commit for cmd panels
Konrad Dybcio <konrad.dybcio@somainline.org>
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm: Fix MSM_INFO_GET_IOVA with carveout
Alexander Usyskin <alexander.usyskin@intel.com>
mei: hbm: call mei_set_devstate() on hbm stop response
Heiner Kallweit <hkallweit1@gmail.com>
PCI: Align checking of syscall user config accessors
Jorgen Hansen <jhansen@vmware.com>
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Pan Bian <bianpan2016@163.com>
PCI: xilinx-cpm: Fix reference count leak on error path
Simon South <simon@simonsouth.net>
pwm: rockchip: Eliminate potential race condition when probing
Simon South <simon@simonsouth.net>
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
Simon South <simon@simonsouth.net>
pwm: rockchip: Enable APB clock during register access while probing
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: cadence: fix ACK/NAK handling
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
soundwire: debugfs: use controller id instead of link_id
Marek Vasut <marek.vasut+renesas@gmail.com>
PCI: rcar: Always allocate MSI addresses in 32bit space
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Add module alias to avoid breaking support for non device tree users
Dan Carpenter <dan.carpenter@oracle.com>
phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
Chris Ruehl <chris.ruehl@gtsys.com.hk>
phy: rockchip-emmc: emmc_phy_init() always return 0
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Fix module alias to enable module autoprobe
Randy Dunlap <rdunlap@infradead.org>
ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: zinitix - fix return type of zinitix_init_touch()
Randy Dunlap <rdunlap@infradead.org>
sparc: fix led.c driver when PROC_FS is not enabled
Randy Dunlap <rdunlap@infradead.org>
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
Dan Carpenter <dan.carpenter@oracle.com>
Input: elo - fix an error code in elo_connect()
Namhyung Kim <namhyung@kernel.org>
perf test: Fix unaligned access in sample parsing test
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix IPC with CYC threshold
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix premature IPC
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix missing CYC processing in PSB
Yang Jihong <yangjihong1@huawei.com>
perf record: Fix continue profiling after draining the buffer
Dan Carpenter <dan.carpenter@oracle.com>
Input: sur40 - fix an error code in sur40_probe()
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv-sysfs: fix missing put_device
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv: fix memory leak by missing kobject free
Md Haris Iqbal <haris.iqbal@cloud.ionos.com>
RDMA/rtrs: Only allow addition of path to an already established session
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix stack-out-of-bounds
Avihai Horon <avihaih@nvidia.com>
RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Fixes missing error code of CMDQ
Jeff Layton <jlayton@kernel.org>
ceph: fix flush_snap logic after putting caps
Chuck Lever <chuck.lever@oracle.com>
svcrdma: Hold private mutex while invoking rdma_accept()
J. Bruce Fields <bfields@redhat.com>
nfsd: register pernet ops last, unregister first
Nicholas Fraser <nfraser@codeweavers.com>
perf symbols: Fix return value when loading PE DSO
John Ogness <john.ogness@linutronix.de>
printk: avoid prb_first_valid_seq() where possible
Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
spi: Skip zero-length transfers in spi_transfer_one_message()
Kees Cook <keescook@chromium.org>
spi: dw: Avoid stack content exposure
Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
regulator: bd718x7, bd71828, Fix dvs voltage levels
Dmitry Safonov <0x7f454c46@gmail.com>
perf symbols: Use (long) for iterator for bfd symbols
Tom Zanussi <zanussi@kernel.org>
selftests/ftrace: Update synthetic event syntax errors
Ryan Chen <ryan_chen@aspeedtech.com>
clk: aspeed: Fix APLL calculate formula from ast2600-A2
Jonathan Marek <jonathan@marek.ca>
regulator: qcom-rpmh: fix pm8009 ldo7
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/kuap: Restore AMR after replaying soft interrupts
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/uaccess: Avoid might_fault() when user access is enabled
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
spi: pxa2xx: Fix the controller numbering for Wildcat Point
Michael Tretter <m.tretter@pengutronix.de>
clk: divider: fix initialization with parent_hw
Lijun Ou <oulijun@huawei.com>
RDMA/hns: Disable RQ inline by default
Weihang Li <liweihang@huawei.com>
RDMA/hns: Fix type of sq_signal_bits
Kamal Heib <kamalheib1@gmail.com>
RDMA/siw: Fix calculation of tx_valid_cpus size
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Fixed wrong judgments in the goto branch
John Stultz <john.stultz@linaro.org>
kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
Daniel Latypov <dlatypov@google.com>
kunit: tool: fix unit test cleanup handling
AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/8xx: Fix software emulation interrupt
Nathan Lynch <nathanl@linux.ibm.com>
powerpc/pseries/dlpar: handle ibm, configure-connector delay status
Dan Carpenter <dan.carpenter@oracle.com>
mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
Arnd Bergmann <arnd@arndb.de>
mfd: altera-sysmgr: Fix physical address storing more
Alain Volmat <alain.volmat@foss.st.com>
spi: stm32: properly handle 0 byte transfer
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Correct skb on loopback path
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_recv.c
John Garry <john.garry@huawei.com>
perf vendor events arm64: Fix Ampere eMag event typo
Arnaldo Carvalho de Melo <acme@redhat.com>
perf tools: Fix DSO filtering when not finding a map for a sampled address
David Gow <davidgow@google.com>
rtc: zynqmp: depend on HAS_IOMEM
Steven Rostedt (VMware) <rostedt@goodmis.org>
tracepoint: Do not fail unregistering a probe due to memory failure
Parav Pandit <parav@nvidia.com>
IB/cm: Avoid a loop when device has 255 ports
Parav Pandit <parav@nvidia.com>
IB/mlx5: Return appropriate error code instead of ENOMEM
Douglas Anderson <dianders@chromium.org>
iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Yong Wu <yong.wu@mediatek.com>
iommu: Move iotlb_sync_map out from __iommu_map
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
amba: Fix resource leak for drivers without .remove
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: i2c-qcom-geni: Add shutdown callback for i2c
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Vladimir Murzin <vladimir.murzin@arm.com>
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Takeshi Saito <takeshi.saito.xv@renesas.com>
mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to 128-bytes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: sdhci-sprd: Fix some resource leaks in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: owl-mmc: Fix a resource leak in an error handling path and in the remove function
Pingfan Liu <kernelfans@gmail.com>
powerpc/time: Enable sched clock for irqtime
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/47x: Disable 256k page size
Cédric Le Goater <clg@kaod.org>
KVM: PPC: Make the VMX instruction emulation routines static
Shay Drory <shayd@nvidia.com>
IB/umad: Return EPOLLERR in case of when device disassociated
Shay Drory <shayd@nvidia.com>
IB/umad: Return EIO in case of when device disassociated
Yong Wu <yong.wu@mediatek.com>
iommu: Switch gather->end to the inclusive end
Dan Carpenter <dan.carpenter@oracle.com>
scsi: lpfc: Fix ancient double free
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix ".cold" section suffix check for newer versions of GCC
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix retpoline detection in asm code
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix error handling for STD/CLD warnings
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: ht16k33: Fix refresh rate handling
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
Pan Bian <bianpan2016@163.com>
isofs: release buffer head before return
Hans de Goede <hdegoede@redhat.com>
regulator: core: Avoid debugfs: Directory ... already present! error
Dmitry Osipenko <digetx@gmail.com>
power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Samuel Holland <samuel@sholland.org>
power: supply: axp20x_usb_power: Init work before enabling IRQs
Krzysztof Kozlowski <krzk@kernel.org>
regulator: s5m8767: Drop regulators OF node reference
Pan Bian <bianpan2016@163.com>
spi: atmel: Put allocated master before return
Pan Bian <bianpan2016@163.com>
regulator: s5m8767: Fix reference count leak
David Howells <dhowells@redhat.com>
certs: Fix blacklist flag type confusion
Gabriel Krisman Bertazi <krisman@collabora.com>
watch_queue: Drop references to /dev/watch_queue
Pan Bian <bianpan2016@163.com>
regulator: axp20x: Fix reference cout leak
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix clock divider range on some clocks
Parav Pandit <parav@nvidia.com>
IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
Yishai Hadas <yishaih@nvidia.com>
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Guido Günther <agx@sigxcpu.org>
spi: imx: Don't print error on -EPROBEDEFER
Tom Rix <trix@redhat.com>
clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
Arnd Bergmann <arnd@arndb.de>
clocksource/drivers/ixp4xx: Select TIMER_OF when needed
Randy Dunlap <rdunlap@infradead.org>
power: supply: fix sbs-charger build, needs REGMAP_I2C
Dave Jiang <dave.jiang@intel.com>
dmaengine: idxd: set DMA channel to be private
Bartosz Golaszewski <bgolaszewski@baylibre.com>
rtc: s5m: select REGMAP_I2C
Claudiu Beznea <claudiu.beznea@microchip.com>
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Init wr_cnt as 1
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix missing wr_cqe
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs: Call kobject_put in the failure path
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-clt: Set mininum limit when create QP
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Release lock before call into close_sess
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Extend ibtrs_cq_qp_create
Nicolas Boichat <drinkcat@chromium.org>
of/fdt: Make sure no-map does not remove already reserved regions
KarimAllah Ahmed <karahmed@amazon.de>
fdt: Properly handle "no-map" field in the memory region
Colin Ian King <colin.king@canonical.com>
power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-battery: Fix missing power_supply_put()
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-charger: Fix missing power_supply_put()
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
mfd: bd9571mwv: Use devm_mfd_add_devices()
Ferry Toth <ftoth@exalondelft.nl>
dmaengine: hsu: disable spurious interrupt
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: owl-dma: Fix a resource leak in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in the remove function
Bernard Metzler <bmt@zurich.ibm.com>
RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Randy Dunlap <rdunlap@infradead.org>
HID: core: detect and skip invalid inputs to snto32()
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Fix parent of CBFUSA clock
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Remove non-existent S2 clock
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix CEC clock
Pratyush Yadav <p.yadav@ti.com>
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle master read request
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle only slave interrupts which are enabled
Jan Kara <jack@suse.cz>
quota: Fix memory leak when handling corrupted quota file
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
Po-Hsu Lin <po-hsu.lin@canonical.com>
selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: make "ret" a signed integer
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
Tony Lindgren <tony@atomide.com>
power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
Zhang Qilong <zhangqilong3@huawei.com>
HSI: Fix PM usage counter unbalance in ssi_hw_init
Eric W. Biederman <ebiederm@xmission.com>
capabilities: Don't allow writing ambiguous v3 file capabilities
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
smp: Process pending softirqs in flush_smp_call_function_from_idle()
Geert Uytterhoeven <geert+renesas@glider.be>
irqchip/imx: IMX_INTMUX should not default to y, unconditionally
Wang ShaoBo <bobo.shaobowang@huawei.com>
ubifs: Fix error return code in alloc_wbufs()
Arnd Bergmann <arnd@arndb.de>
ubifs: replay: Fix high stack usage, again
Dinghao Liu <dinghao.liu@zju.edu.cn>
ubifs: Fix memleak in ubifs_init_authentication
Tom Rix <trix@redhat.com>
jffs2: fix use after free in jffs2_sum_write_data()
Colin Ian King <colin.king@canonical.com>
fs/jfs: fix potential integer overflow on shift of a int
Sameer Pujar <spujar@nvidia.com>
ASoC: simple-card-utils: Fix device module clock
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer after kexec syscall
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer on error
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: set status to 0 in case for invalid nsid
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: remove extra variable in identify ns
Keith Busch <kbusch@kernel.org>
nvme-multipath: set nr_zones for zoned namespaces
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix potential race of tcp socket closing accept_work
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
Hao Xu <haoxu@linux.alibaba.com>
io_uring: fix possible deadlock in io_uring_poll
Daniele Alessandrelli <daniele.alessandrelli@intel.com>
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Jan Henrik Weinstock <jan.weinstock@rwth-aachen.de>
hwrng: timeriomem - Fix cooldown period calculation
Imre Deak <imre.deak@intel.com>
drm/dp_mst: Don't cache EDIDs for physical ports
Qinglang Miao <miaoqinglang@huawei.com>
drm/lima: fix reference leak in lima_pm_busy
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Restore cec physical address on reconnect
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix up CEC registers
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix register offset with longer CEC messages
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Move hdmi reset to bind
Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: return EIO when msg retry limit reached
Sean Christopherson <seanjc@google.com>
KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
Qu Wenruo <wqu@suse.com>
btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Zhihao Cheng <chengzhihao1@huawei.com>
btrfs: clarify error returns values in __load_free_space_cache
Hui Wang <hui.wang@canonical.com>
ASoC: SOF: debug: Fix a potential issue on string buffer termination
Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>
ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Jun Nie <jun.nie@linaro.org>
ASoC: qcom: lpass: Fix i2s ctl register bit map
Peter Zijlstra <peterz@infradead.org>
locking/lockdep: Avoid unmatched unlock
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
Sasha Levin <sashal@kernel.org>
drm/mediatek: Fix aal size config
Yongqiang Niu <yongqiang.niu@mediatek.com>
drm/mediatek: Check if fb is null
Sean Christopherson <seanjc@google.com>
KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Dehe Gu <gudehe@huawei.com>
f2fs: fix a wrong condition in __submit_bio
Dan Carpenter <dan.carpenter@oracle.com>
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
Yi Chen <chenyi77@huawei.com>
f2fs: fix to avoid inconsistent quota data
Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
mtd: parsers: afs: Fix freeing the part name memory in failure
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
ASoC: codecs: add missing max_register in regmap config
Sebastian Reichel <sre@kernel.org>
ASoC: cpcap: fix microphone timeslot mask
Florian Fainelli <f.fainelli@gmail.com>
ata: ahci_brcm: Add back regulators management
Will Deacon <will@kernel.org>
mm: proc: Invalidate TLB after clearing soft-dirty page state
Frantisek Hrbata <frantisek@hrbata.com>
drm/nouveau: bail out of nouveau_channel_new if channel init fails
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Fix ctr(aes) on SEC1
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
Dan Carpenter <dan.carpenter@oracle.com>
mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Move IRQs when migrating context
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix PMU instance naming
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: lpass-cpu: Remove bit clock state check
Chao Yu <chao@kernel.org>
f2fs: compress: fix potential deadlock
Qais Yousef <qais.yousef@arm.com>
sched/eas: Don't update misfit status if the task is pinned
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
Tom Rix <trix@redhat.com>
media: pxa_camera: declare variable when DEBUG is defined
Tom Rix <trix@redhat.com>
media: mtk-vcodec: fix argument used when DEBUG is defined
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: cx25821: Fix a bug when reallocating some dma memory
Luo Meng <luomeng12@huawei.com>
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Dan Carpenter <dan.carpenter@oracle.com>
media: atomisp: Fix a buffer overflow in debug code
Daniel W. S. Almeida <dwlsalmeida@gmail.com>
media: vidtv: psi: fix missing crc for PMT
Joe Perches <joe@perches.com>
media: lmedm04: Fix misuse of comma
Daniel Scally <djrscally@gmail.com>
media: software_node: Fix refcounts in software_node_get_next_child()
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
Finn Thain <fthain@telegraphics.com.au>
macintosh/adb-iop: Use big-endian autopoll mask
Pan Bian <bianpan2016@163.com>
bsg: free the request before return error code
Guchun Chen <guchun.chen@amd.com>
drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
Qinglang Miao <miaoqinglang@huawei.com>
drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
Nathan Chancellor <natechancellor@gmail.com>
MIPS: Compare __SYNC_loongson3_war against 0
Alexander Lobakin <alobakin@pm.me>
MIPS: properly stop .eh_frame generation
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: ti-vpe: cal: fix write to unallocated memory
Rui Miguel Silva <rmfrfs@gmail.com>
media: imx7: csi: Fix pad link validation
Fabio Estevam <festevam@gmail.com>
media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Giulio Benetti <giulio.benetti@micronovasrl.com>
drm/sun4i: tcon: fix inverted DCLK polarity
Xuewen Yan <xuewen.yan@unisoc.com>
sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Jiri Olsa <jolsa@kernel.org>
crypto: bcm - Rename struct device_private to bcm_device_private
Dinghao Liu <dinghao.liu@zju.edu.cn>
evm: Fix memleak in init_desc
Stephan Gerhold <stephan@gerhold.net>
ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Dan Carpenter <dan.carpenter@oracle.com>
ASoC: cs42l56: fix up error handling in probe
Zhang Changzhong <zhangchangzhong@huawei.com>
media: aspeed: fix error return code in aspeed_video_setup_video()
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: tm6000: Fix memleak in tm6000_start_stream
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: media/pci: Fix memleak in empress_init
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: em28xx: Fix use-after-free in em28xx_alloc_urbs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: vsp1: Fix an error handling path in the probe function
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: missing error code in msm_video_register()
Zhang Changzhong <zhangchangzhong@huawei.com>
media: mtk-vcodec: fix error return code in vdec_vp9_decode()
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Fix csc/scaler unregister
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Unregister csc/scaler only if registered
Jacopo Mondi <jacopo@jmondi.org>
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
media: ipu3-cio2: Build only for x86
Simon Ser <contact@emersion.fr>
drm/fourcc: fix Amlogic format modifier masks
Chia-I Wu <olvaffe@gmail.com>
drm/virtio: make sure context is created in gem open
Nathan Chancellor <natechancellor@gmail.com>
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Chancellor <natechancellor@gmail.com>
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
Chenyang Li <lichenyang@loongson.cn>
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Wang Xiaojun <wangxiaojun11@huawei.com>
drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
Qinglang Miao <miaoqinglang@huawei.com>
drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
Marco Elver <elver@google.com>
kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Dan Carpenter <dan.carpenter@oracle.com>
media: allegro: Fix use after free on error
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hwrng: ingenic - Fix a resource leak in an error handling path
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - fix kmap usage
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - linearize buffers content must be kept
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
Guido Günther <agx@sigxcpu.org>
drm/panel: mantix: Tweak init sequence
Chuhong Yuan <hslester96@gmail.com>
drm/fb-helper: Add missed unlocks in setcmap_legacy()
Dan Carpenter <dan.carpenter@oracle.com>
gma500: clean up error handling in init
Jialin Zhang <zhangjialin11@huawei.com>
drm/gma500: Fix error return code in psb_driver_load()
Randy Dunlap <rdunlap@infradead.org>
fbdev: aty: SPARC64 requires FB_ATY_CT
Linus Torvalds <torvalds@linux-foundation.org>
tty: implement read_iter
Linus Torvalds <torvalds@linux-foundation.org>
tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
Vladimir Oltean <vladimir.oltean@nxp.com>
net: enetc: fix destroyed phylink dereference during unbind
Maxime Chevallier <maxime.chevallier@bootlin.com>
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset link when the link never comes back
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: adding LCPLL reset to VSC8514
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: don't deinitialize unused ports
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: perform teardown in reverse order of setup
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: skip send_request_unmap for timeout reset
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: add memory barrier to protect long term buffer
Ilya Leoshkevich <iii@linux.ibm.com>
bpf: Clear subreg_def for global function return values
Colin Ian King <colin.king@canonical.com>
b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
Ayush Sawal <ayush.sawal@chelsio.com>
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Robert Hancock <robert.hancock@calian.com>
net: axienet: Handle deferred probe on clock properly
Eric Dumazet <edumazet@google.com>
tcp: fix SO_RCVLOWAT related hangs under mem pressure
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: fix ACKRX debug message
Jesper Dangaard Brouer <brouer@redhat.com>
bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Jun'ichi Nomura <junichi.nomura@nec.com>
bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Yonghong Song <yhs@fb.com>
bpf: Fix an unitialized value in bpf_iter
Martin KaFai Lau <kafai@fb.com>
libbpf: Ignore non function pointer member in struct_ops
Colin Ian King <colin.king@canonical.com>
mac80211: fix potential overflow when multiplying to u32 integers
Moshe Shemesh <moshe@nvidia.com>
net/mlx5e: Check tunnel offload is required before setting SWP
Oz Shlomo <ozsh@nvidia.com>
net/mlx5e: CT: manage the lifetime of the ct entry object
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for lag devices
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on lag device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on multi port slave device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for multi port slave device
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Replace synchronize_rcu with synchronize_net
Shay Drory <shayd@nvidia.com>
net/mlx5: Fix health error state handling
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Change interrupt moderation channel params also when channels are closed
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Don't change interrupt moderation params when DIM is enabled
Heiner Kallweit <hkallweit1@gmail.com>
net: phy: consider that suspend2ram may cut off PHY power
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: fix memory leak in XDP_REDIRECT
Juergen Gross <jgross@suse.com>
xen/netback: fix spurious event detection for common event case
Vasundhara Volam <vasundhara-v.volam@broadcom.com>
bnxt_en: Fix devlink info's stored fw.psid version format.
Edwin Peer <edwin.peer@broadcom.com>
bnxt_en: reverse order of TX disable and carrier off
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: Set to CLOSED state even on error
Björn Töpel <bjorn.topel@intel.com>
selftests/bpf: Convert test_xdp_redirect.sh to bash
Linus Lüssing <ll@simonwunderlich.de>
ath9k: fix data bus crash when setting nf_override via debugfs
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: set the PNVM again if it was already loaded
Marco Elver <elver@google.com>
bpf_lru_list: Read double-checked variable once without lock
Sara Sharon <sara.sharon@intel.com>
iwlwifi: mvm: don't check if CSA event is running before removing
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: assign SAR table revision to the command later
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: send stored PPAG command instead of local
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: store PPAG enabled/disabled flag properly
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: fix the type we use in the PPAG table validity checks
Jae Hyun Yoo <jae.hyun.yoo@intel.com>
soc: aspeed: snoop: Add clock control logic
Dan Carpenter <dan.carpenter@oracle.com>
ath11k: fix a locking bug in ath11k_mac_op_start()
Anand K Mistry <amistry@google.com>
ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Anand K Mistry <amistry@google.com>
ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
Arnd Bergmann <arnd@arndb.de>
ARM: at91: use proper asm syntax in pm_suspend
Jérôme Pouiller <jerome.pouiller@silabs.com>
staging: wfx: fix possible panic with re-queued frames
Arnd Bergmann <arnd@arndb.de>
optee: simplify i2c access
Arnd Bergmann <arnd@arndb.de>
ARM: s3c: fix fiq for clang IAS
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: set enabled in the PPAG command properly
Artem Lapkin <email2tema@gmail.com>
arm64: dts: meson: fix broken wifi node for Khadas VIM3L
Vincent Knecht <vincent.knecht@mailoo.org>
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Luca Weiss <luca@z3ntu.xyz>
soc: qcom: ocmem: don't return NULL in of_get_ocmem
Jupeng Zhong <zhongjupeng@yulong.com>
Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Dmitry Osipenko <digetx@gmail.com>
opp: Correct debug message in _opp_add_static_v2()
Marek Behún <kabel@kernel.org>
arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to LEDs
Marc Kleine-Budde <mkl@pengutronix.de>
can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Geert Uytterhoeven <geert+renesas@glider.be>
arm64: dts: renesas: beacon: Fix EEPROM compatible value
Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Chen-Yu Tsai <wens@csie.org>
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Make "trimming xfer length" a debug message
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Abort transaction after errors with unknown reason
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Do not update data length if it is 0 on inbound transfers
Tony Lindgren <tony@atomide.com>
ARM: dts: Configure missing thermal interrupt for 4430
Pan Bian <bianpan2016@163.com>
memory: ti-aemif: Drop child node when jumping out loop
Pan Bian <bianpan2016@163.com>
Bluetooth: Put HCI device if inquiry procedure interrupts
Pan Bian <bianpan2016@163.com>
Bluetooth: drop HCI device reference before return
Borislav Petkov <bp@suse.de>
staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
Dan Carpenter <dan.carpenter@oracle.com>
soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
Robert Foss <robert.foss@linaro.org>
arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Jack Pham <jackp@codeaurora.org>
usb: gadget: u_audio: Free requests only after callback
Maximilian Luz <luzmaximilian@gmail.com>
ACPICA: Fix exception code class checks
Chen-Yu Tsai <wens@csie.org>
arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Free resources in error path
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: properly connect USB PHY to port 0
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix call site of scmi_notification_exit
Andrii Nakryiko <andrii@kernel.org>
bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
Andrii Nakryiko <andrii@kernel.org>
bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk transfers on 64-bit builds
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk userdata handling
Dinghao Liu <dinghao.liu@zju.edu.cn>
Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
Zhang Qilong <zhangqilong3@huawei.com>
memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
Christopher William Snowhill <chris@kode54.net>
Bluetooth: Fix initializing response id after clearing struct
Claire Chang <tientzu@chromium.org>
Bluetooth: hci_uart: Fix a race for write_work scheduling
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the probe function
Rakesh Pillai <pillair@codeaurora.org>
ath10k: Fix error handling in case of CE pipe init failure
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: One more flush for Baytrail clear residuals
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Don't call sync_stop if it hasn't been stopped
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Assure sync with the pending stop operation at suspend
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Call sync_stop at disconnection
Eric Biggers <ebiggers@google.com>
random: fix the RNDRESEEDCRNG ioctl
Nathan Chancellor <nathan@kernel.org>
vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
Alexander Lobakin <alobakin@pm.me>
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
Jan Kara <jack@suse.cz>
bfq: Avoid false bfq queue merging
Hans de Goede <hdegoede@redhat.com>
virt: vbox: Do not use wait_event_interruptible when called from kernel context
Ard Biesheuvel <ardb@kernel.org>
PCI: Decline to resize resources if boot config must be preserved
Ansuel Smith <ansuelsmth@gmail.com>
PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ivan Zaentsev <ivan.zaentsev@wirenboard.ru>
w1: w1_therm: Fix conversion result for negative temperatures
Sumit Garg <sumit.garg@linaro.org>
kdb: Make memory allocations more robust
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix mailbox Ch erroneous error
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: docs: Remove notify_ha_event()
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: do not attempt to create a new file before the filesystem is initalized
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: be more robust at handling improper input in debugfs_lookup()
Stefano Garzarella <sgarzare@redhat.com>
vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Nick Desaulniers <ndesaulniers@google.com>
vmlinux.lds.h: add DWARF v5 sections
-------------
Diffstat:
Documentation/admin-guide/perf/arm-cmn.rst | 2 +-
Documentation/admin-guide/sysctl/vm.rst | 10 +-
Documentation/filesystems/seq_file.rst | 6 +
Documentation/scsi/libsas.rst | 1 -
Documentation/security/keys/core.rst | 4 +-
Makefile | 4 +-
arch/arm/boot/compressed/head.S | 4 +-
arch/arm/boot/dts/armada-388-helios4.dts | 28 +-
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/arm/kernel/sys_oabi-compat.c | 15 +
arch/arm/mach-at91/pm_suspend.S | 2 +-
arch/arm/mach-ixp4xx/Kconfig | 1 -
arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9 +-
arch/arm64/Kconfig | 2 +-
.../boot/dts/allwinner/sun50i-a64-pinebook.dts | 5 +-
.../boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 -
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 +-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7 +
.../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7 +-
.../boot/dts/exynos/exynos5433-tm2-common.dtsi | 2 +-
arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +-
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4 +-
.../boot/dts/marvell/armada-3720-turris-mox.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +
.../dts/qcom/msm8916-samsung-a2015-common.dtsi | 6 +
.../boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2 +-
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 9 +-
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 +-
.../boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +-
.../arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4 +-
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 +
arch/arm64/crypto/aes-glue.c | 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/include/asm/module.lds.h | 6 +-
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/head.S | 1 +
arch/arm64/kernel/machine_kexec_file.c | 4 +-
arch/arm64/kernel/probes/uprobes.c | 2 +-
arch/arm64/kernel/ptrace.c | 2 +-
arch/arm64/kernel/suspend.c | 2 +-
arch/csky/kernel/ptrace.c | 2 +-
arch/mips/Makefile | 19 ++
arch/mips/cavium-octeon/setup.c | 9 +-
arch/mips/include/asm/asm.h | 18 ++
arch/mips/include/asm/atomic.h | 2 +-
arch/mips/include/asm/cmpxchg.h | 6 +-
arch/mips/kernel/cpu-probe.c | 15 +-
arch/mips/kernel/vmlinux.lds.S | 2 +-
arch/mips/lantiq/irq.c | 2 +-
arch/mips/loongson64/Platform | 22 --
arch/mips/mm/c-r4k.c | 2 +-
arch/mips/vdso/Makefile | 5 +-
arch/nios2/kernel/entry.S | 3 +
arch/nios2/kernel/sys_nios2.c | 11 +-
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/kexec.h | 1 +
arch/powerpc/include/asm/uaccess.h | 13 +-
arch/powerpc/kernel/entry_32.S | 3 +
arch/powerpc/kernel/head_32.h | 2 +-
arch/powerpc/kernel/head_8xx.S | 2 +-
arch/powerpc/kernel/head_book3s_32.S | 6 -
arch/powerpc/kernel/irq.c | 27 +-
arch/powerpc/kernel/prom_init.c | 12 +-
arch/powerpc/kernel/time.c | 2 +
arch/powerpc/kexec/elf_64.c | 2 +-
arch/powerpc/kexec/file_load_64.c | 35 +++
arch/powerpc/kvm/powerpc.c | 8 +-
arch/powerpc/platforms/pseries/dlpar.c | 7 +-
arch/riscv/kernel/vdso/Makefile | 3 +-
arch/s390/kernel/vtime.c | 3 +-
arch/sparc/Kconfig | 2 +-
arch/sparc/kernel/led.c | 2 +
arch/sparc/lib/memset.S | 1 +
arch/um/include/shared/skas/mm_id.h | 1 +
arch/um/kernel/tlb.c | 19 +-
arch/um/os-Linux/skas/process.c | 4 +
arch/x86/crypto/aesni-intel_glue.c | 28 +-
arch/x86/entry/common.c | 2 +-
arch/x86/include/asm/virtext.h | 17 +-
arch/x86/kernel/msr.c | 7 +
arch/x86/kernel/reboot.c | 30 +-
arch/x86/kvm/emulate.c | 4 +-
arch/x86/kvm/mmu/tdp_mmu.c | 3 +-
arch/x86/kvm/svm/nested.c | 22 +-
arch/x86/kvm/svm/svm.c | 8 +-
arch/x86/mm/fault.c | 27 +-
arch/x86/mm/pat/memtype.c | 4 +-
block/bfq-iosched.c | 1 +
block/blk-settings.c | 12 +
block/bsg.c | 4 +-
block/ioctl.c | 21 +-
certs/blacklist.c | 2 +-
crypto/ecdh_helper.c | 3 +
crypto/michael_mic.c | 31 +-
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/base/swnode.c | 8 +-
drivers/block/floppy.c | 30 +-
drivers/bluetooth/btqcomsmd.c | 27 +-
drivers/bluetooth/btusb.c | 20 +-
drivers/bluetooth/hci_ldisc.c | 41 ++-
drivers/bluetooth/hci_qca.c | 2 +
drivers/bluetooth/hci_serdev.c | 4 +-
drivers/char/hw_random/ingenic-trng.c | 6 +-
drivers/char/hw_random/timeriomem-rng.c | 2 +-
drivers/char/random.c | 2 +-
drivers/char/tpm/tpm.h | 4 -
drivers/char/tpm/tpm_tis_core.c | 50 +--
drivers/clk/clk-ast2600.c | 37 ++-
drivers/clk/clk-divider.c | 9 +-
drivers/clk/meson/clk-pll.c | 10 +-
drivers/clk/qcom/gcc-msm8998.c | 100 +++---
drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +-
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/mxs_timer.c | 5 +-
drivers/cpufreq/acpi-cpufreq.c | 62 +---
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +-
drivers/cpufreq/freq_table.c | 8 +-
drivers/cpufreq/intel_pstate.c | 21 +-
drivers/cpufreq/qcom-cpufreq-hw.c | 40 ++-
.../crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 ++++++----
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2 +
drivers/crypto/bcm/cipher.c | 2 +-
drivers/crypto/bcm/cipher.h | 4 +-
drivers/crypto/bcm/util.c | 2 +-
drivers/crypto/talitos.c | 50 ++-
drivers/crypto/talitos.h | 1 +
drivers/dax/bus.c | 2 +-
drivers/dma/fsldma.c | 6 +
drivers/dma/hsu/pci.c | 21 +-
drivers/dma/idxd/dma.c | 1 +
drivers/dma/owl-dma.c | 1 +
drivers/firmware/arm_scmi/driver.c | 4 +-
drivers/gpio/gpio-pcf857x.c | 2 +-
drivers/gpu/drm/Kconfig | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +-
drivers/gpu/drm/amd/amdgpu/soc15.c | 2 +
.../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2 +-
.../gpu/drm/amd/display/dc/bios/command_table.c | 61 ++++
.../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14 +
.../drm/amd/display/dc/dce/dce_stream_encoder.c | 1 +
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8 +-
.../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1 -
.../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +
.../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 ++
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +-
drivers/gpu/drm/drm_dp_mst_topology.c | 3 +-
drivers/gpu/drm/drm_fb_helper.c | 15 +-
drivers/gpu/drm/drm_modes.c | 4 +-
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +-
drivers/gpu/drm/gma500/psb_drv.c | 2 +
drivers/gpu/drm/i915/display/intel_hdmi.c | 6 +-
drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12 +-
drivers/gpu/drm/lima/lima_sched.c | 2 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8 +
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 8 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 5 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +-
drivers/gpu/drm/msm/msm_drv.c | 3 +-
.../drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 +
drivers/gpu/drm/nouveau/nouveau_chan.c | 1 +
drivers/gpu/drm/nouveau/nouveau_connector.c | 1 +
drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3 +-
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5 +
drivers/gpu/drm/rcar-du/rcar_cmm.c | 2 +-
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 +-
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 +-
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11 +
drivers/gpu/drm/scheduler/sched_main.c | 3 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 +-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/tegra/dc.c | 2 +-
drivers/gpu/drm/tegra/dsi.c | 2 +-
drivers/gpu/drm/tegra/hdmi.c | 2 +-
drivers/gpu/drm/tegra/hub.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 2 +-
drivers/gpu/drm/tegra/vic.c | 2 +-
drivers/gpu/drm/vc4/vc4_hdmi.c | 87 +++--
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +-
drivers/gpu/drm/virtio/virtgpu_gem.c | 8 +-
drivers/hid/hid-core.c | 3 +
drivers/hid/hid-logitech-dj.c | 1 +
drivers/hid/wacom_wac.c | 7 +-
drivers/hsi/controllers/omap_ssi_core.c | 2 +-
drivers/hv/channel_mgmt.c | 3 +-
drivers/hwtracing/coresight/coresight-etm4x-core.c | 21 +-
.../hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +-
drivers/i2c/busses/i2c-bcm-iproc.c | 231 +++++++++++---
drivers/i2c/busses/i2c-brcmstb.c | 2 +-
drivers/i2c/busses/i2c-exynos5.c | 8 +-
drivers/i2c/busses/i2c-qcom-geni.c | 93 +++++-
drivers/ide/falconide.c | 3 +-
drivers/infiniband/core/cm.c | 8 +-
drivers/infiniband/core/cma.c | 70 +++--
drivers/infiniband/core/user_mad.c | 17 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 2 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 8 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 3 +-
drivers/infiniband/hw/mlx5/devx.c | 4 +-
drivers/infiniband/hw/mlx5/main.c | 14 +-
drivers/infiniband/sw/rxe/rxe_net.c | 5 +
drivers/infiniband/sw/rxe/rxe_recv.c | 27 +-
drivers/infiniband/sw/siw/siw.h | 2 +-
drivers/infiniband/sw/siw/siw_main.c | 2 +-
drivers/infiniband/sw/siw/siw_qp.c | 271 ++++++++--------
drivers/infiniband/sw/siw/siw_qp_rx.c | 26 +-
drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +-
drivers/infiniband/sw/siw/siw_verbs.c | 20 +-
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2 +
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51 +--
drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1 +
drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 117 ++++---
drivers/infiniband/ulp/rtrs/rtrs.c | 14 +-
drivers/input/joydev.c | 7 +-
drivers/input/joystick/xpad.c | 1 +
drivers/input/serio/i8042-x86ia64io.h | 4 +
drivers/input/serio/serport.c | 4 +-
drivers/input/touchscreen/elo.c | 4 +-
drivers/input/touchscreen/raydium_i2c_ts.c | 3 +-
drivers/input/touchscreen/sur40.c | 1 +
drivers/input/touchscreen/zinitix.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 +
drivers/iommu/iommu.c | 23 +-
drivers/iommu/mtk_iommu.c | 2 +-
drivers/irqchip/Kconfig | 3 +-
drivers/irqchip/irq-loongson-pch-msi.c | 2 +-
drivers/macintosh/adb-iop.c | 6 +-
drivers/mailbox/sprd-mailbox.c | 2 +-
drivers/md/bcache/bcache.h | 3 +
drivers/md/bcache/btree.c | 21 +-
drivers/md/bcache/journal.c | 4 +-
drivers/md/bcache/super.c | 20 ++
drivers/md/dm-core.h | 4 +
drivers/md/dm-crypt.c | 1 +
drivers/md/dm-era-target.c | 93 ++++--
drivers/md/dm-table.c | 168 +++++-----
drivers/md/dm-writecache.c | 74 +++--
drivers/md/dm.c | 62 +++-
drivers/md/dm.h | 2 +-
drivers/media/i2c/max9286.c | 2 +-
drivers/media/i2c/ov5670.c | 3 +-
drivers/media/pci/cx25821/cx25821-core.c | 4 +-
drivers/media/pci/intel/ipu3/Kconfig | 3 +-
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +-
drivers/media/pci/saa7134/saa7134-empress.c | 5 +-
drivers/media/pci/smipcie/smipcie-ir.c | 46 +--
drivers/media/platform/aspeed-video.c | 6 +-
drivers/media/platform/marvell-ccic/mcam-core.c | 2 +
.../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 +-
.../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3 +-
drivers/media/platform/pxa_camera.c | 3 +
drivers/media/platform/qcom/camss/camss-video.c | 1 +
drivers/media/platform/ti-vpe/cal.c | 4 +-
drivers/media/platform/vsp1/vsp1_drv.c | 4 +-
drivers/media/rc/ir_toy.c | 1 +
drivers/media/rc/mceusb.c | 2 +-
drivers/media/test-drivers/vidtv/vidtv_psi.c | 5 +-
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/mtk-smi.c | 4 +-
drivers/memory/ti-aemif.c | 8 +-
drivers/mfd/altera-sysmgr.c | 3 +-
drivers/mfd/bd9571mwv.c | 6 +-
drivers/mfd/gateworks-gsc.c | 2 +-
drivers/mfd/wm831x-auxadc.c | 3 +-
drivers/misc/cardreader/rts5227.c | 5 +
drivers/misc/eeprom/eeprom_93xx46.c | 1 +
drivers/misc/fastrpc.c | 7 +-
drivers/misc/mei/hbm.c | 2 +-
drivers/misc/mei/hw-me-regs.h | 5 +
drivers/misc/mei/interrupt.c | 33 +-
drivers/misc/mei/pci-me.c | 5 +
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +-
drivers/mmc/host/owl-mmc.c | 9 +-
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +-
drivers/mmc/host/sdhci-esdhc-imx.c | 3 +-
drivers/mmc/host/sdhci-pci-o2micro.c | 20 ++
drivers/mmc/host/sdhci-sprd.c | 6 +-
drivers/mmc/host/usdhi6rol0.c | 4 +-
drivers/mtd/parsers/afs.c | 4 +-
drivers/mtd/parsers/parser_imagetag.c | 4 +
drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4 +-
drivers/mtd/spi-nor/core.c | 10 +-
drivers/mtd/spi-nor/sfdp.c | 5 +-
drivers/net/Kconfig | 2 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +-
drivers/net/dsa/ocelot/felix.c | 16 +-
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 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +-
.../chelsio/inline_crypto/chtls/chtls_cm.h | 3 -
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14 +-
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
drivers/net/ethernet/ibm/ibmvnic.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 50 +--
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 +-
drivers/net/ethernet/intel/ice/ice.h | 2 -
drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6 +-
drivers/net/ethernet/intel/ice/ice_ethtool.c | 34 +-
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33 +-
drivers/net/ethernet/marvell/mvneta.c | 9 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2 +-
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9 +
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 +++++++++++----
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2 +-
.../mellanox/mlx5/core/en_accel/en_accel.h | 2 +-
.../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66 ++--
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8 +-
drivers/net/ethernet/mellanox/mlx5/core/health.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 +-
drivers/net/ethernet/realtek/r8169_main.c | 4 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 +-
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26 +-
drivers/net/gtp.c | 1 -
drivers/net/phy/mscc/mscc.h | 8 +
drivers/net/phy/mscc/mscc_main.c | 350 ++++++++++++++-------
drivers/net/phy/phy_device.c | 53 +---
drivers/net/ppp/ppp_async.c | 3 +-
drivers/net/ppp/ppp_synctty.c | 3 +-
drivers/net/vxlan.c | 11 +-
drivers/net/wireguard/device.c | 19 +-
drivers/net/wireguard/device.h | 15 +-
drivers/net/wireguard/peer.c | 28 +-
drivers/net/wireguard/peer.h | 4 +-
drivers/net/wireguard/queueing.c | 86 ++++-
drivers/net/wireguard/queueing.h | 45 ++-
drivers/net/wireguard/receive.c | 16 +-
drivers/net/wireguard/send.c | 31 +-
drivers/net/wireless/ath/ath10k/mac.c | 2 +
drivers/net/wireless/ath/ath10k/snoc.c | 5 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +
drivers/net/wireless/ath/ath11k/mac.c | 11 +-
drivers/net/wireless/ath/ath9k/debug.c | 5 +-
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43 ++-
.../net/wireless/intel/iwlwifi/mvm/time-event.c | 3 -
.../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21 +-
drivers/net/xen-netback/interface.c | 8 +-
drivers/nvme/host/multipath.c | 4 +
drivers/nvme/target/admin-cmd.c | 33 +-
drivers/nvme/target/tcp.c | 59 +++-
drivers/nvmem/core.c | 5 +-
drivers/nvmem/qcom-spmi-sdam.c | 7 +-
drivers/of/fdt.c | 12 +-
drivers/opp/of.c | 4 +-
drivers/pci/controller/cadence/pcie-cadence-host.c | 5 +-
drivers/pci/controller/dwc/pcie-qcom.c | 4 +-
drivers/pci/controller/pcie-rcar-host.c | 2 +-
drivers/pci/controller/pcie-rockchip.c | 12 +-
drivers/pci/controller/pcie-xilinx-cpm.c | 1 +
drivers/pci/pci-bridge-emul.c | 11 +-
drivers/pci/setup-res.c | 6 +
drivers/pci/syscall.c | 10 +-
drivers/perf/arm-cmn.c | 17 +-
drivers/phy/Kconfig | 1 +
drivers/phy/cadence/phy-cadence-torrent.c | 1 +
drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10 +-
drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +-
drivers/platform/chrome/cros_ec_proto.c | 12 +-
drivers/power/reset/at91-sama5d2_shdwc.c | 2 +-
drivers/power/supply/Kconfig | 1 +
drivers/power/supply/axp20x_usb_power.c | 2 +-
drivers/power/supply/cpcap-battery.c | 12 +-
drivers/power/supply/cpcap-charger.c | 4 +-
drivers/power/supply/smb347-charger.c | 12 +-
drivers/pwm/pwm-iqs620a.c | 8 +-
drivers/pwm/pwm-rockchip.c | 18 +-
drivers/regulator/axp20x-regulator.c | 7 +-
drivers/regulator/core.c | 6 +-
drivers/regulator/qcom-rpmh-regulator.c | 26 ++
drivers/regulator/rohm-regulator.c | 9 +-
drivers/regulator/s5m8767.c | 15 +-
drivers/remoteproc/mtk_common.h | 1 +
drivers/remoteproc/mtk_scp.c | 20 +-
drivers/rtc/Kconfig | 3 +-
drivers/s390/crypto/zcrypt_api.c | 14 +
drivers/s390/virtio/virtio_ccw.c | 4 +-
drivers/scsi/bnx2fc/Kconfig | 1 +
drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +-
drivers/scsi/qla2xxx/qla_dbg.c | 1 +
drivers/scsi/qla2xxx/qla_mbx.c | 3 +-
drivers/scsi/sd.c | 6 +-
drivers/scsi/sd_zbc.c | 6 +-
drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +-
drivers/soc/qcom/ocmem.c | 8 +-
drivers/soc/qcom/socinfo.c | 2 +-
drivers/soc/samsung/exynos-asv.c | 18 +-
drivers/soc/ti/pm33xx.c | 5 +-
drivers/soundwire/bus.c | 47 ++-
drivers/soundwire/cadence_master.c | 8 +-
drivers/soundwire/debugfs.c | 2 +-
drivers/soundwire/intel_init.c | 3 +-
drivers/spi/spi-atmel.c | 2 +-
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-dw-bt1.c | 2 +-
drivers/spi/spi-fsl-spi.c | 2 +-
drivers/spi/spi-imx.c | 2 +-
drivers/spi/spi-pxa2xx-pci.c | 27 +-
drivers/spi/spi-stm32.c | 4 +
drivers/spi/spi-synquacer.c | 4 +
drivers/spi/spi.c | 2 +-
drivers/spmi/spmi-pmic-arb.c | 5 +-
drivers/staging/gdm724x/gdm_usb.c | 10 +-
drivers/staging/media/allegro-dvt/allegro-core.c | 3 +-
drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24 +-
drivers/staging/media/atomisp/pci/hmm/hmm.c | 2 +-
drivers/staging/media/imx/imx-media-csc-scaler.c | 4 -
drivers/staging/media/imx/imx-media-dev.c | 7 +-
drivers/staging/media/imx/imx7-media-csi.c | 27 +-
drivers/staging/mt7621-dma/Makefile | 2 +-
.../mt7621-dma/{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 +-
.../vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 +-
drivers/staging/wfx/data_tx.c | 10 +-
drivers/staging/wfx/data_tx.h | 1 +
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-
drivers/tee/optee/rpc.c | 31 +-
drivers/thermal/cpufreq_cooling.c | 2 +-
drivers/tty/n_gsm.c | 3 +-
drivers/tty/n_hdlc.c | 60 ++--
drivers/tty/n_null.c | 3 +-
drivers/tty/n_r3964.c | 10 +-
drivers/tty/n_tracerouter.c | 4 +-
drivers/tty/n_tracesink.c | 4 +-
drivers/tty/n_tty.c | 82 ++---
drivers/tty/tty_io.c | 82 ++++-
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/usb/serial/pl2303.c | 8 +-
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
drivers/vfio/pci/vfio_pci_zdev.c | 4 +
drivers/vfio/vfio_iommu_type1.c | 63 ++--
drivers/video/fbdev/Kconfig | 2 +-
drivers/virt/vboxguest/vboxguest_utils.c | 18 +-
drivers/w1/slaves/w1_therm.c | 22 +-
drivers/watchdog/intel-mid_wdt.c | 8 +-
drivers/watchdog/mei_wdt.c | 1 +
drivers/watchdog/qcom-wdt.c | 13 +-
fs/affs/namei.c | 4 +-
fs/btrfs/backref.c | 9 +-
fs/btrfs/backref.h | 9 +-
fs/btrfs/block-group.c | 29 +-
fs/btrfs/ctree.c | 7 +-
fs/btrfs/delayed-ref.c | 56 ++--
fs/btrfs/delayed-ref.h | 16 +-
fs/btrfs/extent-tree.c | 128 ++------
fs/btrfs/free-space-cache.c | 6 +-
fs/btrfs/inode.c | 3 +-
fs/btrfs/relocation.c | 4 +-
fs/btrfs/space-info.h | 17 +
fs/ceph/caps.c | 10 +-
fs/debugfs/inode.c | 5 +-
fs/erofs/xattr.c | 10 +-
fs/erofs/zmap.c | 10 +-
fs/eventpoll.c | 4 +-
fs/exfat/exfat_raw.h | 4 +
fs/exfat/super.c | 31 +-
fs/ext4/Kconfig | 3 +-
fs/ext4/namei.c | 7 +-
fs/f2fs/compress.c | 5 +-
fs/f2fs/data.c | 12 +-
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 24 +-
fs/f2fs/inline.c | 4 +
fs/f2fs/super.c | 3 +
fs/gfs2/bmap.c | 6 +-
fs/gfs2/lock_dlm.c | 8 +-
fs/gfs2/recovery.c | 4 +-
fs/gfs2/util.c | 16 +-
fs/io_uring.c | 17 +-
fs/isofs/dir.c | 1 +
fs/isofs/namei.c | 1 +
fs/jffs2/summary.c | 3 +
fs/jfs/jfs_dmap.c | 2 +-
fs/nfs/nfs4proc.c | 15 +-
fs/nfsd/nfsctl.c | 14 +-
fs/ocfs2/cluster/heartbeat.c | 8 +-
fs/proc/proc_sysctl.c | 4 +-
fs/proc/self.c | 2 +-
fs/proc/task_mmu.c | 9 +-
fs/proc/thread_self.c | 7 +
fs/pstore/platform.c | 4 +-
fs/quota/quota_v2.c | 11 +-
fs/ubifs/auth.c | 2 +-
fs/ubifs/replay.c | 4 +-
fs/ubifs/super.c | 4 +-
fs/zonefs/super.c | 3 +
include/acpi/acexcep.h | 10 +-
include/asm-generic/vmlinux.lds.h | 16 +-
include/linux/bpf.h | 3 +
include/linux/device-mapper.h | 5 +
include/linux/eventpoll.h | 2 +-
include/linux/filter.h | 2 +-
include/linux/icmpv6.h | 28 +-
include/linux/iommu.h | 4 +-
include/linux/ipv6.h | 1 -
include/linux/kexec.h | 5 +
include/linux/key.h | 1 +
include/linux/kgdb.h | 2 +
include/linux/khugepaged.h | 2 +
include/linux/memremap.h | 6 +
include/linux/mfd/rohm-generic.h | 14 +-
include/linux/rcupdate.h | 2 +
include/linux/rmap.h | 3 +-
include/linux/soundwire/sdw.h | 2 +
include/linux/tpm.h | 5 +-
include/linux/tty_ldisc.h | 3 +-
include/net/act_api.h | 6 +-
include/net/icmp.h | 6 +-
include/net/tcp.h | 9 +-
include/uapi/drm/drm_fourcc.h | 4 +-
init/Kconfig | 11 +
init/main.c | 1 +
kernel/Makefile | 2 +-
kernel/bpf/bpf_iter.c | 2 +-
kernel/bpf/bpf_lru_list.c | 7 +-
kernel/bpf/devmap.c | 4 +-
kernel/bpf/verifier.c | 3 +-
kernel/debug/debug_core.c | 11 +
kernel/debug/kdb/kdb_private.h | 2 +-
kernel/kcsan/core.c | 26 +-
kernel/kexec_file.c | 5 +
kernel/kprobes.c | 31 +-
kernel/locking/lockdep.c | 3 +-
kernel/module.c | 21 +-
kernel/printk/printk.c | 28 +-
kernel/printk/printk_safe.c | 16 +-
kernel/rcu/tree.c | 8 +-
kernel/rcu/tree_plugin.h | 5 +
kernel/sched/fair.c | 45 ++-
kernel/sched/idle.c | 1 +
kernel/seccomp.c | 2 +
kernel/smp.c | 4 +
kernel/tracepoint.c | 80 ++++-
mm/compaction.c | 43 +--
mm/hugetlb.c | 14 +-
mm/khugepaged.c | 22 +-
mm/memcontrol.c | 30 +-
mm/memory-failure.c | 6 +
mm/memory.c | 16 +-
mm/memremap.c | 15 +
mm/slab_common.c | 4 +-
mm/slub.c | 8 +-
mm/vmscan.c | 9 +-
net/bluetooth/a2mp.c | 3 +-
net/bluetooth/hci_core.c | 6 +-
net/core/filter.c | 13 +-
net/ipv4/icmp.c | 5 +-
net/ipv6/icmp.c | 18 +-
net/ipv6/ip6_icmp.c | 12 +-
net/mac80211/mesh_hwmp.c | 2 +-
net/nfc/nci/uart.c | 3 +-
net/qrtr/tun.c | 12 +-
net/sched/act_api.c | 106 ++++---
net/sched/cls_api.c | 12 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 6 +-
samples/Kconfig | 2 +-
samples/watch_queue/watch_test.c | 2 +-
security/commoncap.c | 12 +-
security/integrity/evm/evm_crypto.c | 7 +-
security/integrity/ima/ima_kexec.c | 3 +
security/integrity/ima/ima_mok.c | 5 +-
security/keys/Kconfig | 8 +-
security/keys/key.c | 2 +
security/keys/trusted-keys/trusted_tpm1.c | 22 +-
security/keys/trusted-keys/trusted_tpm2.c | 22 +-
security/selinux/hooks.c | 4 +
sound/core/init.c | 4 +
sound/core/pcm.c | 4 +
sound/core/pcm_local.h | 1 +
sound/core/pcm_native.c | 27 +-
sound/firewire/fireface/ff-protocol-latter.c | 118 +++++--
sound/pci/hda/hda_intel.c | 2 +
sound/pci/hda/patch_hdmi.c | 1 -
sound/pci/hda/patch_realtek.c | 40 +++
sound/soc/codecs/cpcap.c | 12 +-
sound/soc/codecs/cs42l56.c | 3 +-
sound/soc/codecs/rt5682-i2c.c | 3 +
sound/soc/codecs/wsa881x.c | 1 +
sound/soc/generic/simple-card-utils.c | 13 +-
sound/soc/intel/boards/sof_sdw.c | 6 +-
sound/soc/qcom/lpass-apq8016.c | 2 +-
sound/soc/qcom/lpass-cpu.c | 30 +-
sound/soc/qcom/lpass-lpaif-reg.h | 3 -
sound/soc/qcom/lpass.h | 1 -
sound/soc/qcom/qdsp6/q6asm-dai.c | 21 ++
sound/soc/qcom/qdsp6/q6routing.c | 18 --
sound/soc/sh/siu.h | 2 +-
sound/soc/sh/siu_pcm.c | 2 +-
sound/soc/sof/debug.c | 2 +-
sound/soc/sof/intel/hda-dsp.c | 4 +
sound/soc/sof/sof-pci-dev.c | 7 +
sound/usb/pcm.c | 2 +-
tools/lib/bpf/libbpf.c | 22 +-
tools/objtool/arch/x86/special.c | 2 +-
tools/objtool/check.c | 15 +-
tools/objtool/check.h | 11 +
tools/perf/builtin-record.c | 2 +-
.../pmu-events/arch/arm64/ampere/emag/cache.json | 2 +-
tools/perf/tests/sample-parsing.c | 2 +-
tools/perf/util/event.c | 2 +
tools/perf/util/evlist.c | 8 +
tools/perf/util/evlist.h | 4 +
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 41 ++-
.../perf/util/intel-pt-decoder/intel-pt-decoder.h | 2 +
tools/perf/util/intel-pt.c | 29 +-
tools/perf/util/symbol.c | 7 +-
tools/testing/kunit/kunit_tool_test.py | 14 +-
tools/testing/selftests/bpf/test_xdp_redirect.sh | 10 +-
tools/testing/selftests/dmabuf-heaps/Makefile | 2 +-
.../trigger-synthetic_event_syntax_errors.tc | 35 ++-
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 +-
tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +-
tools/testing/selftests/seccomp/seccomp_bpf.c | 2 +-
tools/testing/selftests/wireguard/netns.sh | 15 +-
667 files changed, 5767 insertions(+), 3014 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.10 000/661] 5.10.20-rc2 review
@ 2021-03-01 19:37 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-01 19:37 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.10.20 release.
There are 661 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 03 Mar 2021 19:34:53 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.20-rc2.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.20-rc2
Cong Wang <cong.wang@bytedance.com>
net_sched: fix RTNL deadlock again caused by request_module()
Takeshi Misawa <jeliantsurux@gmail.com>
net: qrtr: Fix memory leak in qrtr_tun_open
Vlad Buslov <vladbu@nvidia.com>
net: sched: fix police ext initialization
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: get rid of per-peer ring buffers
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: selftests: test multiple parallel streams
Jason A. Donenfeld <Jason@zx2c4.com>
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Leon Romanovsky <leon@kernel.org>
ipv6: silence compilation warning for non-IPV6 builds
Sumit Garg <sumit.garg@linaro.org>
kgdb: fix to kill breakpoints on initmem after boot
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/i915: Reject 446-480MHz HDMI clock on GLK
Nikos Tsironis <ntsironis@arrikto.com>
dm era: only resize metadata in preresume
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Reinitialize bitset cache before digesting a new writeset
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Use correct value size in equality function of writeset tree
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Fix bitset memory leaks
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Verify the data block size hasn't changed
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Update in-core bitset after committing the metadata
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Recover committed writeset after crash
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix writing beyond end of underlying device when shrinking
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: return the exact table values that were set
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix performance degradation in ssd mode
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix zoned iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix DAX iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix iterate_devices based device capability checks
Mikulas Patocka <mpatocka@redhat.com>
dm: fix deadlock when swapping to encrypted device
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Lock imbalance on error path in gfs2_recover_one
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't skip dlm unlock if glock has an lvb
Bob Peterson <rpeterso@redhat.com>
gfs2: fix glock confusion in function signal_our_withdraw
Masahisa Kojima <masahisa.kojima@linaro.org>
spi: spi-synquacer: fix set_cs handling
Rasmus Villemoes <rasmus.villemoes@prevas.dk>
spi: fsl: invert spisel_boot signal on MPC8309
Al Viro <viro@zeniv.linux.org.uk>
sparc32: fix a user-triggerable oops in clear_user()
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: flush data when enabling checkpoint back
Chao Yu <chao@kernel.org>
f2fs: enforce the immutable flag on open files
Chao Yu <chao@kernel.org>
f2fs: fix out-of-repair __setattr_copy()
Huacai Chen <chenhuacai@loongson.cn>
irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Johannes Berg <johannes.berg@intel.com>
um: defer killing userspace on page table update failures
Johannes Berg <johannes.berg@intel.com>
um: mm: check more comprehensively for stub changes
Cornelia Huck <cohuck@redhat.com>
virtio/s390: implement virtio-ccw revision 2 correctly
Heiko Carstens <hca@linux.ibm.com>
s390/vtime: fix inline assembly clobber list
Jens Axboe <axboe@kernel.dk>
proc: don't allow async path resolution of /proc/thread-self components
Chen Yu <yu.c.chen@intel.com>
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Shawn Guo <shawn.guo@linaro.org>
cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Viresh Kumar <viresh.kumar@linaro.org>
thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Chris Wilson <chris@chris-wilson.co.uk>
kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
zonefs: Fix file size of zones in full condition
Namjae Jeon <namjae.jeon@samsung.com>
exfat: fix shift-out-of-bounds in exfat_fill_super()
Muchun Song <songmuchun@bytedance.com>
printk: fix deadlock when kernel panic
Tim Harvey <tharvey@gateworks.com>
mfd: gateworks-gsc: Fix interrupt type
Maxim Kiselev <bigunclemax@gmail.com>
gpio: pcf857x: Fix missing first interrupt
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point LP DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point S DID
Tomas Winkler <tomas.winkler@intel.com>
mei: me: emmitsburg workstation DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: fix transfer over dma with extended header
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
spmi: spmi-pmic-arb: Fix hw_irq overflow
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32s: Add missing call to kuep_lock on syscall entry
Hari Bathini <hbathini@linux.ibm.com>
powerpc/kexec_file: fix FDT size estimation for kdump kernel
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
Shirley Her <shirley.her@bayhubtech.com>
mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Frank Li <Frank.Li@nxp.com>
mmc: sdhci-esdhc-imx: fix kernel panic when remove module
Fangrui Song <maskray@google.com>
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
Paolo Bonzini <pbonzini@redhat.com>
KVM: nSVM: fix running nested guests when npt=0
Vlastimil Babka <vbabka@suse.cz>
mm, compaction: make fast_isolate_freepages() stay within zone
Dave Hansen <dave.hansen@linux.intel.com>
mm/vmscan: restore zone_reclaim_mode ABI
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix update_and_free_page contig page struct assumption
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix get_active_memcg return value
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix swap undercounting in cgroup2
NeilBrown <neilb@suse.de>
x86: fix seq_file iteration for pat/memtype.c
NeilBrown <neilb@suse.de>
seq_file: document how per-entry resources are managed.
Pan Bian <bianpan2016@163.com>
fs/affs: release old buffer head on error path
Pan Bian <bianpan2016@163.com>
mtd: spi-nor: hisi-sfc: Put child node np on error path
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Add erase size check for erase command initialization
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Fix erase type discovery for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix last erase region marking
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Handle accesses to TRCSTALLCTLR
Alexander Usyskin <alexander.usyskin@intel.com>
watchdog: mei_wdt: request stop on unregister
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Tobias Klauser <tklauser@distanz.ch>
riscv: Disable KSAN_SANITIZE for vDSO
Will Deacon <will@kernel.org>
arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Shaoying Xu <shaoyi@amazon.com>
arm64 module: set plt* section addresses to 0x0
He Zhe <zhe.he@windriver.com>
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
qiuguorui1 <qiuguorui1@huawei.com>
arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
Isaac J. Manjarres <isaacm@codeaurora.org>
iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Suzuki K Poulose <suzuki.poulose@arm.com>
arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
Masami Hiramatsu <mhiramat@kernel.org>
kprobes: Fix to delay the kprobes jump optimization
Frederic Weisbecker <frederic@kernel.org>
entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
entry: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Trigger self-IPI on late deferred wake up before user resume
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Perform deferred wake up before last idle's need_resched() check
Frederic Weisbecker <frederic@kernel.org>
rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
Cédric Le Goater <clg@kaod.org>
powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Thomas Gleixner <tglx@linutronix.de>
x86/entry: Fix instrumentation annotation
Andy Lutomirski <luto@kernel.org>
x86/fault: Fix AMD erratum #91 errata fixup for user code
Sean Christopherson <seanjc@google.com>
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Christopherson <seanjc@google.com>
x86/virt: Eat faults on VMXOFF in reboot flows
Sean Young <sean@mess.org>
media: smipcie: fix interrupt handling and IR timeout
Lubomir Rintel <lkundrak@v3.sk>
media: marvell-ccic: power up the device on mclk enable
Pavel Machek <pavel@denx.de>
media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
Sean Young <sean@mess.org>
media: ir_toy: add another IR Droid device
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: i2c: max9286: fix access to unallocated memory
Jiri Kosina <jkosina@suse.cz>
floppy: reintroduce O_NDELAY fix
Martin Kaiser <martin@kaiser.cx>
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Amey Narkhede <ameynarkhede03@gmail.com>
staging: gdm724x: Fix DMA from stack
Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Dinh Nguyen <dinguyen@kernel.org>
arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Frank Wunderlich <frank-w@public-files.de>
dts64: mt7622: fix slow sd card access
Jiri Bohac <jbohac@suse.cz>
pstore: Fix typo in compression option name
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Ricky Wu <ricky_wu@realtek.com>
misc: rtsx: init of rts522a add OCP power off when no card is present
Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Paul Cercueil <paul@crapouillou.net>
seccomp: Add missing return in non-void function
Krzysztof Kozlowski <krzk@kernel.org>
soc: samsung: exynos-asv: handle reading revision register error
Marek Szyprowski <m.szyprowski@samsung.com>
soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - initialize need_fallback
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - handle BigEndian for cipher
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - IV register does not work on A10 and A13
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - checking sg length is not sufficient
Ard Biesheuvel <ardb@kernel.org>
crypto: michael_mic - fix broken misalignment handling
Ard Biesheuvel <ardb@kernel.org>
crypto: aesni - prevent misaligned buffers on the stack
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/sha - add missing module aliases
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Correct surface base address for renderclear
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Flush before changing register state
Filipe Manana <fdmanana@suse.com>
btrfs: fix extent buffer leak on failure to copy root
Josef Bacik <josef@toxicpanda.com>
btrfs: account for new extents being deleted in total_bytes_pinned
Josef Bacik <josef@toxicpanda.com>
btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
Josef Bacik <josef@toxicpanda.com>
btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
Josef Bacik <josef@toxicpanda.com>
btrfs: fix reloc root leak with 0 ref reloc roots on recovery
Josef Bacik <josef@toxicpanda.com>
btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
Josef Bacik <josef@toxicpanda.com>
btrfs: add asserts for deleting backref cache nodes
Josef Bacik <josef@toxicpanda.com>
btrfs: do not warn if we can't find the reloc root when looking up backref
Josef Bacik <josef@toxicpanda.com>
btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Reserve TPM for seal and unseal operations
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix migratable=1 failing
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix incorrect handling of tpm_get_random()
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Clean up locality release
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Fix check_locality for correct locality acquisition
Gao Xiang <hsiangkao@redhat.com>
erofs: initialized fields can only be observed after bit is set
Amir Goldstein <amir73il@gmail.com>
selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Takashi Iwai <tiwai@suse.de>
ASoC: siu: Fix build error by a wrong const prefix
Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
drm/rockchip: Require the YTR modifier for AFBC
Heiko Stuebner <heiko@sntech.de>
drm/panel: kd35t133: allow using non-continuous dsi clock
Andrey Grodzovsky <andrey.grodzovsky@amd.com>
drm/sched: Cancel and flush all outstanding jobs before finish.
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/modes: Switch to 64bit maths to avoid integer overflow
Karol Herbst <kherbst@redhat.com>
drm/nouveau/kms: handle mDP connectors
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Felix Kuehling <Felix.Kuehling@amd.com>
drm/amdkfd: Fix recursive lock warnings
Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Eric Bernstein <eric.bernstein@amd.com>
drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Jan Kokemüller <jan.kokemueller@gmail.com>
drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Alex Deucher <alexander.deucher@amd.com>
Revert "drm/amd/display: Update NV1x SR latency values"
Kai Krakow <kai@kaishome.de>
bcache: Move journal work to new flush wq
Kai Krakow <kai@kaishome.de>
bcache: Give btree_io_wq correct semantics again
Kai Krakow <kai@kaishome.de>
Revert "bcache: Kill btree_io_wq"
Kevin Hao <haokexin@gmail.com>
Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Nathan Chancellor <natechancellor@gmail.com>
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
Aurelien Jarno <aurelien@aurel32.net>
MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Paul Cercueil <paul@crapouillou.net>
MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
Takashi Iwai <tiwai@suse.de>
ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
PeiSen Hou <pshou@realtek.com>
ALSA: hda/realtek: modify EAPD in the ALC886
Takashi Iwai <tiwai@suse.de>
ALSA: hda/hdmi: Drop bogus check at closing a stream
Kai Vehmanen <kai.vehmanen@linux.intel.com>
ALSA: hda: Add another CometLake-H PCI ID
Takashi Sakamoto <o-takashi@sakamocchi.jp>
ALSA: fireface: fix to parse sync status register of latter protocol
Mathias Kresin <dev@kresin.me>
phy: lantiq: rcu-usb2: wait after clock enable
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7720: fix error code in mos7720_write()
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7840: fix error code in mos7840_write()
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix line-speed handling on newer chips
Johan Hovold <johan@kernel.org>
USB: serial: ftdi_sio: fix FTX sub-integer prescaler
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
Paul Cercueil <paul@crapouillou.net>
usb: musb: Fix runtime PM race in musb_queue_resume_work
Lech Perczak <lech.perczak@gmail.com>
USB: serial: option: update interface mapping for ZTE P685M
James Reynolds <jr@memlen.com>
media: mceusb: Fix potential out-of-bounds shift
Marcos Paulo de Souza <mpdesouza@suse.com>
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Dan Carpenter <dan.carpenter@oracle.com>
Input: joydev - prevent potential read overflow in ioctl
Olivier Crête <olivier.crete@ocrete.ca>
Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
jeffrey.lin <jeffrey.lin@rad-ic.com>
Input: raydium_ts_i2c - do not send zero length
Jason Gerecke <killertofu@gmail.com>
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Filipe Laíns <lains@riseup.net>
HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
Qinglang Miao <miaoqinglang@huawei.com>
ACPI: configfs: add missing check after configfs_register_default_group()
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: property: Fix fwnode string properties matching
Marcin Ślusarz <marcin.slusarz@intel.com>
soundwire: intel: fix possible crash when no device is detected
Mikulas Patocka <mpatocka@redhat.com>
blk-settings: align max_sectors on "logical_block_size" boundary
Bart Van Assche <bvanassche@acm.org>
scsi: sd: Fix Opal support
Finn Thain <fthain@telegraphics.com.au>
ide/falconide: Fix module unload
Christoph Hellwig <hch@lst.de>
block: reopen the device in blkdev_reread_part
Johannes Thumshirn <johannes.thumshirn@wdc.com>
scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
Randy Dunlap <rdunlap@infradead.org>
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Zhenzhong Duan <zhenzhong.duan@gmail.com>
csky: Fix a size determination in gpr_get()
Josef Bacik <josef@toxicpanda.com>
proc: use kvzalloc for our kernel buffer
Miaohe Lin <linmiaohe@huawei.com>
mm/rmap: fix potential pte_unmap on an not mapped pte
Dan Williams <dan.j.williams@intel.com>
mm: fix memory_failure() handling of dax-namespace metadata
Rik van Riel <riel@surriel.com>
mm,thp,shmem: make khugepaged obey tmpfs mount flags
Mårten Lindahl <martenli@axis.com>
i2c: exynos5: Preserve high speed master code
Maxime Ripard <maxime@cerno.tech>
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Marc Zyngier <maz@kernel.org>
arm64: Add missing ISB after invalidating TLB in __primary_switch
Sean Christopherson <seanjc@google.com>
KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
Sean Christopherson <seanjc@google.com>
KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4: Fixes for nfs4_bitmask_adjust()
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix jumbo packet handling on RTL8168e
Wonhyuk Yang <vvghjk1234@gmail.com>
mm/compaction: fix misbehaviors of fast_find_migrateblock()
Chen Wandun <chenwandun@huawei.com>
mm/hugetlb: suppress wrong warning info when alloc gigantic page
Miaohe Lin <linmiaohe@huawei.com>
mm/hugetlb: fix potential double free in hugetlb_register_node() error path
Miaohe Lin <linmiaohe@huawei.com>
mm/memory.c: fix potential pte_unmap_unlock pte error
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix slub memory accounting
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
Dan Carpenter <dan.carpenter@oracle.com>
ocfs2: fix a use after free on error
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: kconfig: use arm chacha even with no neon
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: device: do not generate ICMP for non-IP packets
Taehee Yoo <ap420073@gmail.com>
vxlan: move debug check after netdev unregister
Chen-Yu Tsai <wens@csie.org>
PCI: rockchip: Make 'ep-gpios' DT property optional
Chuhong Yuan <hslester96@gmail.com>
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Song, Yoong Siang <yoong.siang.song@intel.com>
net: stmmac: fix CBS idleslope and sendslope calculation
Henry Tieman <henry.w.tieman@intel.com>
ice: update the number of available RSS queues
Dave Ertman <david.m.ertman@intel.com>
ice: Fix state bits on LLDP mode switch
Brett Creeley <brett.creeley@intel.com>
ice: Account for port VLAN in VF max packet size calculation
Dave Ertman <david.m.ertman@intel.com>
ice: report correct max number of TCs
Alex Williamson <alex.williamson@redhat.com>
vfio/type1: Use follow_pte()
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
pwm: iqs620a: Fix overflow and optimize calculations
Dan Carpenter <dan.carpenter@oracle.com>
octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix add TC filter for IPv6
Andreas Oetken <andreas.oetken@siemens.com>
nios2: fixed broken sys_clone syscall
Jann Horn <jannh@google.com>
Take mmap lock in cacheflush syscall
Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
i40e: Fix VFs not created
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix addition of RX filters after enabling FW LLDP agent
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix overwriting flow control settings during driver loading
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Add zero-initialization of AQ command structures
Slawomir Laba <slawomirx.laba@intel.com>
i40e: Fix flow for IPv6 next header (extension header)
Krzysztof Wilczyński <kw@linux.com>
PCI: cadence: Fix DMA range mapping early return error
Russell King <rmk+kernel@armlinux.org.uk>
PCI: pci-bridge-emul: Fix array overruns, improve safety
Shiyang Ruan <ruansy.fnst@cn.fujitsu.com>
device-dax: Fix default return code of range_parse()
Magnum Shan <magnum.shan@unisoc.com>
mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Geert Uytterhoeven <geert@linux-m68k.org>
ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Bard Liao <yung-chuan.liao@linux.intel.com>
regmap: sdw: use _no_pm functions in regmap_read/write
Tzung-Bi Shih <tzungbi@google.com>
remoteproc/mediatek: acknowledge watchdog IRQ after handled
Jonathan Marek <jonathan@marek.ca>
misc: fastrpc: fix incorrect usage of dma_map_sgtable
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: fix confusion on device used by pm_runtime
Bard Liao <yung-chuan.liao@linux.intel.com>
soundwire: export sdw_write/read_no_pm functions
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_update_no_pm when initializing a device
Ahmad Fatoum <a.fatoum@pengutronix.de>
nvmem: core: skip child nodes not matching binding
Dan Carpenter <dan.carpenter@oracle.com>
nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Skip accessing TRCPDCR in save/restore
Geert Uytterhoeven <geert+renesas@glider.be>
phy: USB_LGM_PHY should depend on X86
Theodore Ts'o <tytso@mit.edu>
ext4: fix potential htree index checksum corruption
Max Gurtovoy <mgurtovoy@nvidia.com>
vfio-pci/zdev: fix possible segmentation fault issue
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Fix some sanity checks in detach group
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Populate full dirty when detach non-pinned group
Judy Hsiao <judyhsiao@google.com>
drm/msm/dp: trigger unplug event in msm_dp_display_disable
Eric Anholt <eric@anholt.net>
drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Anholt <eric@anholt.net>
drm/msm: Fix race of GPU init vs timestamp power management.
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm/mdp5: Fix wait-for-commit for cmd panels
Konrad Dybcio <konrad.dybcio@somainline.org>
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm: Fix MSM_INFO_GET_IOVA with carveout
Alexander Usyskin <alexander.usyskin@intel.com>
mei: hbm: call mei_set_devstate() on hbm stop response
Heiner Kallweit <hkallweit1@gmail.com>
PCI: Align checking of syscall user config accessors
Jorgen Hansen <jhansen@vmware.com>
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Pan Bian <bianpan2016@163.com>
PCI: xilinx-cpm: Fix reference count leak on error path
Simon South <simon@simonsouth.net>
pwm: rockchip: Eliminate potential race condition when probing
Simon South <simon@simonsouth.net>
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
Simon South <simon@simonsouth.net>
pwm: rockchip: Enable APB clock during register access while probing
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: cadence: fix ACK/NAK handling
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
soundwire: debugfs: use controller id instead of link_id
Marek Vasut <marek.vasut+renesas@gmail.com>
PCI: rcar: Always allocate MSI addresses in 32bit space
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Add module alias to avoid breaking support for non device tree users
Dan Carpenter <dan.carpenter@oracle.com>
phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
Chris Ruehl <chris.ruehl@gtsys.com.hk>
phy: rockchip-emmc: emmc_phy_init() always return 0
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Fix module alias to enable module autoprobe
Randy Dunlap <rdunlap@infradead.org>
ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: zinitix - fix return type of zinitix_init_touch()
Randy Dunlap <rdunlap@infradead.org>
sparc: fix led.c driver when PROC_FS is not enabled
Randy Dunlap <rdunlap@infradead.org>
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
Dan Carpenter <dan.carpenter@oracle.com>
Input: elo - fix an error code in elo_connect()
Namhyung Kim <namhyung@kernel.org>
perf test: Fix unaligned access in sample parsing test
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix IPC with CYC threshold
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix premature IPC
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix missing CYC processing in PSB
Yang Jihong <yangjihong1@huawei.com>
perf record: Fix continue profiling after draining the buffer
Dan Carpenter <dan.carpenter@oracle.com>
Input: sur40 - fix an error code in sur40_probe()
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv-sysfs: fix missing put_device
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv: fix memory leak by missing kobject free
Md Haris Iqbal <haris.iqbal@cloud.ionos.com>
RDMA/rtrs: Only allow addition of path to an already established session
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix stack-out-of-bounds
Avihai Horon <avihaih@nvidia.com>
RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Fixes missing error code of CMDQ
Jeff Layton <jlayton@kernel.org>
ceph: fix flush_snap logic after putting caps
Chuck Lever <chuck.lever@oracle.com>
svcrdma: Hold private mutex while invoking rdma_accept()
J. Bruce Fields <bfields@redhat.com>
nfsd: register pernet ops last, unregister first
Nicholas Fraser <nfraser@codeweavers.com>
perf symbols: Fix return value when loading PE DSO
John Ogness <john.ogness@linutronix.de>
printk: avoid prb_first_valid_seq() where possible
Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
spi: Skip zero-length transfers in spi_transfer_one_message()
Kees Cook <keescook@chromium.org>
spi: dw: Avoid stack content exposure
Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
regulator: bd718x7, bd71828, Fix dvs voltage levels
Dmitry Safonov <0x7f454c46@gmail.com>
perf symbols: Use (long) for iterator for bfd symbols
Tom Zanussi <zanussi@kernel.org>
selftests/ftrace: Update synthetic event syntax errors
Ryan Chen <ryan_chen@aspeedtech.com>
clk: aspeed: Fix APLL calculate formula from ast2600-A2
Jonathan Marek <jonathan@marek.ca>
regulator: qcom-rpmh: fix pm8009 ldo7
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/kuap: Restore AMR after replaying soft interrupts
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/uaccess: Avoid might_fault() when user access is enabled
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
spi: pxa2xx: Fix the controller numbering for Wildcat Point
Michael Tretter <m.tretter@pengutronix.de>
clk: divider: fix initialization with parent_hw
Lijun Ou <oulijun@huawei.com>
RDMA/hns: Disable RQ inline by default
Weihang Li <liweihang@huawei.com>
RDMA/hns: Fix type of sq_signal_bits
Kamal Heib <kamalheib1@gmail.com>
RDMA/siw: Fix calculation of tx_valid_cpus size
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Fixed wrong judgments in the goto branch
John Stultz <john.stultz@linaro.org>
kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
Daniel Latypov <dlatypov@google.com>
kunit: tool: fix unit test cleanup handling
AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/8xx: Fix software emulation interrupt
Nathan Lynch <nathanl@linux.ibm.com>
powerpc/pseries/dlpar: handle ibm, configure-connector delay status
Dan Carpenter <dan.carpenter@oracle.com>
mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
Arnd Bergmann <arnd@arndb.de>
mfd: altera-sysmgr: Fix physical address storing more
Alain Volmat <alain.volmat@foss.st.com>
spi: stm32: properly handle 0 byte transfer
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Correct skb on loopback path
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_recv.c
John Garry <john.garry@huawei.com>
perf vendor events arm64: Fix Ampere eMag event typo
Arnaldo Carvalho de Melo <acme@redhat.com>
perf tools: Fix DSO filtering when not finding a map for a sampled address
David Gow <davidgow@google.com>
rtc: zynqmp: depend on HAS_IOMEM
Steven Rostedt (VMware) <rostedt@goodmis.org>
tracepoint: Do not fail unregistering a probe due to memory failure
Parav Pandit <parav@nvidia.com>
IB/cm: Avoid a loop when device has 255 ports
Parav Pandit <parav@nvidia.com>
IB/mlx5: Return appropriate error code instead of ENOMEM
Douglas Anderson <dianders@chromium.org>
iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Yong Wu <yong.wu@mediatek.com>
iommu: Move iotlb_sync_map out from __iommu_map
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
amba: Fix resource leak for drivers without .remove
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: i2c-qcom-geni: Add shutdown callback for i2c
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Vladimir Murzin <vladimir.murzin@arm.com>
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Takeshi Saito <takeshi.saito.xv@renesas.com>
mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to 128-bytes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: sdhci-sprd: Fix some resource leaks in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: owl-mmc: Fix a resource leak in an error handling path and in the remove function
Pingfan Liu <kernelfans@gmail.com>
powerpc/time: Enable sched clock for irqtime
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/47x: Disable 256k page size
Cédric Le Goater <clg@kaod.org>
KVM: PPC: Make the VMX instruction emulation routines static
Shay Drory <shayd@nvidia.com>
IB/umad: Return EPOLLERR in case of when device disassociated
Shay Drory <shayd@nvidia.com>
IB/umad: Return EIO in case of when device disassociated
Yong Wu <yong.wu@mediatek.com>
iommu: Switch gather->end to the inclusive end
Dan Carpenter <dan.carpenter@oracle.com>
scsi: lpfc: Fix ancient double free
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix ".cold" section suffix check for newer versions of GCC
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix retpoline detection in asm code
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix error handling for STD/CLD warnings
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: ht16k33: Fix refresh rate handling
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
Pan Bian <bianpan2016@163.com>
isofs: release buffer head before return
Hans de Goede <hdegoede@redhat.com>
regulator: core: Avoid debugfs: Directory ... already present! error
Dmitry Osipenko <digetx@gmail.com>
power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Samuel Holland <samuel@sholland.org>
power: supply: axp20x_usb_power: Init work before enabling IRQs
Krzysztof Kozlowski <krzk@kernel.org>
regulator: s5m8767: Drop regulators OF node reference
Pan Bian <bianpan2016@163.com>
spi: atmel: Put allocated master before return
Pan Bian <bianpan2016@163.com>
regulator: s5m8767: Fix reference count leak
David Howells <dhowells@redhat.com>
certs: Fix blacklist flag type confusion
Gabriel Krisman Bertazi <krisman@collabora.com>
watch_queue: Drop references to /dev/watch_queue
Pan Bian <bianpan2016@163.com>
regulator: axp20x: Fix reference cout leak
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix clock divider range on some clocks
Parav Pandit <parav@nvidia.com>
IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
Yishai Hadas <yishaih@nvidia.com>
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Guido Günther <agx@sigxcpu.org>
spi: imx: Don't print error on -EPROBEDEFER
Tom Rix <trix@redhat.com>
clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
Arnd Bergmann <arnd@arndb.de>
clocksource/drivers/ixp4xx: Select TIMER_OF when needed
Randy Dunlap <rdunlap@infradead.org>
power: supply: fix sbs-charger build, needs REGMAP_I2C
Dave Jiang <dave.jiang@intel.com>
dmaengine: idxd: set DMA channel to be private
Bartosz Golaszewski <bgolaszewski@baylibre.com>
rtc: s5m: select REGMAP_I2C
Claudiu Beznea <claudiu.beznea@microchip.com>
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Init wr_cnt as 1
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix missing wr_cqe
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs: Call kobject_put in the failure path
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-clt: Set mininum limit when create QP
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Release lock before call into close_sess
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Extend ibtrs_cq_qp_create
Nicolas Boichat <drinkcat@chromium.org>
of/fdt: Make sure no-map does not remove already reserved regions
KarimAllah Ahmed <karahmed@amazon.de>
fdt: Properly handle "no-map" field in the memory region
Colin Ian King <colin.king@canonical.com>
power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-battery: Fix missing power_supply_put()
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-charger: Fix missing power_supply_put()
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
mfd: bd9571mwv: Use devm_mfd_add_devices()
Ferry Toth <ftoth@exalondelft.nl>
dmaengine: hsu: disable spurious interrupt
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: owl-dma: Fix a resource leak in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in the remove function
Bernard Metzler <bmt@zurich.ibm.com>
RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Randy Dunlap <rdunlap@infradead.org>
HID: core: detect and skip invalid inputs to snto32()
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Fix parent of CBFUSA clock
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Remove non-existent S2 clock
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix CEC clock
Pratyush Yadav <p.yadav@ti.com>
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle master read request
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle only slave interrupts which are enabled
Jan Kara <jack@suse.cz>
quota: Fix memory leak when handling corrupted quota file
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
Po-Hsu Lin <po-hsu.lin@canonical.com>
selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: make "ret" a signed integer
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
Tony Lindgren <tony@atomide.com>
power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
Zhang Qilong <zhangqilong3@huawei.com>
HSI: Fix PM usage counter unbalance in ssi_hw_init
Eric W. Biederman <ebiederm@xmission.com>
capabilities: Don't allow writing ambiguous v3 file capabilities
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
smp: Process pending softirqs in flush_smp_call_function_from_idle()
Geert Uytterhoeven <geert+renesas@glider.be>
irqchip/imx: IMX_INTMUX should not default to y, unconditionally
Wang ShaoBo <bobo.shaobowang@huawei.com>
ubifs: Fix error return code in alloc_wbufs()
Arnd Bergmann <arnd@arndb.de>
ubifs: replay: Fix high stack usage, again
Dinghao Liu <dinghao.liu@zju.edu.cn>
ubifs: Fix memleak in ubifs_init_authentication
Tom Rix <trix@redhat.com>
jffs2: fix use after free in jffs2_sum_write_data()
Colin Ian King <colin.king@canonical.com>
fs/jfs: fix potential integer overflow on shift of a int
Sameer Pujar <spujar@nvidia.com>
ASoC: simple-card-utils: Fix device module clock
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer after kexec syscall
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer on error
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: set status to 0 in case for invalid nsid
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: remove extra variable in identify ns
Keith Busch <kbusch@kernel.org>
nvme-multipath: set nr_zones for zoned namespaces
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix potential race of tcp socket closing accept_work
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
Hao Xu <haoxu@linux.alibaba.com>
io_uring: fix possible deadlock in io_uring_poll
Daniele Alessandrelli <daniele.alessandrelli@intel.com>
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Jan Henrik Weinstock <jan.weinstock@rwth-aachen.de>
hwrng: timeriomem - Fix cooldown period calculation
Imre Deak <imre.deak@intel.com>
drm/dp_mst: Don't cache EDIDs for physical ports
Qinglang Miao <miaoqinglang@huawei.com>
drm/lima: fix reference leak in lima_pm_busy
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Restore cec physical address on reconnect
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix up CEC registers
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix register offset with longer CEC messages
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Move hdmi reset to bind
Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: return EIO when msg retry limit reached
Sean Christopherson <seanjc@google.com>
KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
Qu Wenruo <wqu@suse.com>
btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Zhihao Cheng <chengzhihao1@huawei.com>
btrfs: clarify error returns values in __load_free_space_cache
Hui Wang <hui.wang@canonical.com>
ASoC: SOF: debug: Fix a potential issue on string buffer termination
Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>
ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Jun Nie <jun.nie@linaro.org>
ASoC: qcom: lpass: Fix i2s ctl register bit map
Peter Zijlstra <peterz@infradead.org>
locking/lockdep: Avoid unmatched unlock
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
Sasha Levin <sashal@kernel.org>
drm/mediatek: Fix aal size config
Yongqiang Niu <yongqiang.niu@mediatek.com>
drm/mediatek: Check if fb is null
Sean Christopherson <seanjc@google.com>
KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Dehe Gu <gudehe@huawei.com>
f2fs: fix a wrong condition in __submit_bio
Dan Carpenter <dan.carpenter@oracle.com>
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
Yi Chen <chenyi77@huawei.com>
f2fs: fix to avoid inconsistent quota data
Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
mtd: parsers: afs: Fix freeing the part name memory in failure
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
ASoC: codecs: add missing max_register in regmap config
Sebastian Reichel <sre@kernel.org>
ASoC: cpcap: fix microphone timeslot mask
Florian Fainelli <f.fainelli@gmail.com>
ata: ahci_brcm: Add back regulators management
Will Deacon <will@kernel.org>
mm: proc: Invalidate TLB after clearing soft-dirty page state
Frantisek Hrbata <frantisek@hrbata.com>
drm/nouveau: bail out of nouveau_channel_new if channel init fails
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Fix ctr(aes) on SEC1
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
Dan Carpenter <dan.carpenter@oracle.com>
mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Move IRQs when migrating context
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix PMU instance naming
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: lpass-cpu: Remove bit clock state check
Chao Yu <chao@kernel.org>
f2fs: compress: fix potential deadlock
Qais Yousef <qais.yousef@arm.com>
sched/eas: Don't update misfit status if the task is pinned
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
Tom Rix <trix@redhat.com>
media: pxa_camera: declare variable when DEBUG is defined
Tom Rix <trix@redhat.com>
media: mtk-vcodec: fix argument used when DEBUG is defined
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: cx25821: Fix a bug when reallocating some dma memory
Luo Meng <luomeng12@huawei.com>
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Dan Carpenter <dan.carpenter@oracle.com>
media: atomisp: Fix a buffer overflow in debug code
Daniel W. S. Almeida <dwlsalmeida@gmail.com>
media: vidtv: psi: fix missing crc for PMT
Joe Perches <joe@perches.com>
media: lmedm04: Fix misuse of comma
Daniel Scally <djrscally@gmail.com>
media: software_node: Fix refcounts in software_node_get_next_child()
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
Finn Thain <fthain@telegraphics.com.au>
macintosh/adb-iop: Use big-endian autopoll mask
Pan Bian <bianpan2016@163.com>
bsg: free the request before return error code
Guchun Chen <guchun.chen@amd.com>
drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
Qinglang Miao <miaoqinglang@huawei.com>
drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
Nathan Chancellor <natechancellor@gmail.com>
MIPS: Compare __SYNC_loongson3_war against 0
Alexander Lobakin <alobakin@pm.me>
MIPS: properly stop .eh_frame generation
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: ti-vpe: cal: fix write to unallocated memory
Rui Miguel Silva <rmfrfs@gmail.com>
media: imx7: csi: Fix pad link validation
Fabio Estevam <festevam@gmail.com>
media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Giulio Benetti <giulio.benetti@micronovasrl.com>
drm/sun4i: tcon: fix inverted DCLK polarity
Xuewen Yan <xuewen.yan@unisoc.com>
sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Jiri Olsa <jolsa@kernel.org>
crypto: bcm - Rename struct device_private to bcm_device_private
Dinghao Liu <dinghao.liu@zju.edu.cn>
evm: Fix memleak in init_desc
Stephan Gerhold <stephan@gerhold.net>
ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Dan Carpenter <dan.carpenter@oracle.com>
ASoC: cs42l56: fix up error handling in probe
Zhang Changzhong <zhangchangzhong@huawei.com>
media: aspeed: fix error return code in aspeed_video_setup_video()
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: tm6000: Fix memleak in tm6000_start_stream
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: media/pci: Fix memleak in empress_init
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: em28xx: Fix use-after-free in em28xx_alloc_urbs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: vsp1: Fix an error handling path in the probe function
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: missing error code in msm_video_register()
Zhang Changzhong <zhangchangzhong@huawei.com>
media: mtk-vcodec: fix error return code in vdec_vp9_decode()
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Fix csc/scaler unregister
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Unregister csc/scaler only if registered
Jacopo Mondi <jacopo@jmondi.org>
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
media: ipu3-cio2: Build only for x86
Simon Ser <contact@emersion.fr>
drm/fourcc: fix Amlogic format modifier masks
Chia-I Wu <olvaffe@gmail.com>
drm/virtio: make sure context is created in gem open
Nathan Chancellor <natechancellor@gmail.com>
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Chancellor <natechancellor@gmail.com>
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
Chenyang Li <lichenyang@loongson.cn>
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Wang Xiaojun <wangxiaojun11@huawei.com>
drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
Qinglang Miao <miaoqinglang@huawei.com>
drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
Marco Elver <elver@google.com>
kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Dan Carpenter <dan.carpenter@oracle.com>
media: allegro: Fix use after free on error
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hwrng: ingenic - Fix a resource leak in an error handling path
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - fix kmap usage
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - linearize buffers content must be kept
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
Guido Günther <agx@sigxcpu.org>
drm/panel: mantix: Tweak init sequence
Chuhong Yuan <hslester96@gmail.com>
drm/fb-helper: Add missed unlocks in setcmap_legacy()
Dan Carpenter <dan.carpenter@oracle.com>
gma500: clean up error handling in init
Jialin Zhang <zhangjialin11@huawei.com>
drm/gma500: Fix error return code in psb_driver_load()
Randy Dunlap <rdunlap@infradead.org>
fbdev: aty: SPARC64 requires FB_ATY_CT
Linus Torvalds <torvalds@linux-foundation.org>
tty: implement read_iter
Linus Torvalds <torvalds@linux-foundation.org>
tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
Vladimir Oltean <vladimir.oltean@nxp.com>
net: enetc: fix destroyed phylink dereference during unbind
Maxime Chevallier <maxime.chevallier@bootlin.com>
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset link when the link never comes back
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: adding LCPLL reset to VSC8514
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: don't deinitialize unused ports
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: perform teardown in reverse order of setup
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: skip send_request_unmap for timeout reset
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: add memory barrier to protect long term buffer
Ilya Leoshkevich <iii@linux.ibm.com>
bpf: Clear subreg_def for global function return values
Colin Ian King <colin.king@canonical.com>
b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
Ayush Sawal <ayush.sawal@chelsio.com>
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Robert Hancock <robert.hancock@calian.com>
net: axienet: Handle deferred probe on clock properly
Eric Dumazet <edumazet@google.com>
tcp: fix SO_RCVLOWAT related hangs under mem pressure
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: fix ACKRX debug message
Jesper Dangaard Brouer <brouer@redhat.com>
bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Jun'ichi Nomura <junichi.nomura@nec.com>
bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Yonghong Song <yhs@fb.com>
bpf: Fix an unitialized value in bpf_iter
Martin KaFai Lau <kafai@fb.com>
libbpf: Ignore non function pointer member in struct_ops
Colin Ian King <colin.king@canonical.com>
mac80211: fix potential overflow when multiplying to u32 integers
Moshe Shemesh <moshe@nvidia.com>
net/mlx5e: Check tunnel offload is required before setting SWP
Oz Shlomo <ozsh@nvidia.com>
net/mlx5e: CT: manage the lifetime of the ct entry object
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for lag devices
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on lag device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on multi port slave device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for multi port slave device
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Replace synchronize_rcu with synchronize_net
Shay Drory <shayd@nvidia.com>
net/mlx5: Fix health error state handling
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Change interrupt moderation channel params also when channels are closed
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Don't change interrupt moderation params when DIM is enabled
Heiner Kallweit <hkallweit1@gmail.com>
net: phy: consider that suspend2ram may cut off PHY power
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: fix memory leak in XDP_REDIRECT
Juergen Gross <jgross@suse.com>
xen/netback: fix spurious event detection for common event case
Vasundhara Volam <vasundhara-v.volam@broadcom.com>
bnxt_en: Fix devlink info's stored fw.psid version format.
Edwin Peer <edwin.peer@broadcom.com>
bnxt_en: reverse order of TX disable and carrier off
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: Set to CLOSED state even on error
Björn Töpel <bjorn.topel@intel.com>
selftests/bpf: Convert test_xdp_redirect.sh to bash
Linus Lüssing <ll@simonwunderlich.de>
ath9k: fix data bus crash when setting nf_override via debugfs
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: set the PNVM again if it was already loaded
Marco Elver <elver@google.com>
bpf_lru_list: Read double-checked variable once without lock
Sara Sharon <sara.sharon@intel.com>
iwlwifi: mvm: don't check if CSA event is running before removing
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: assign SAR table revision to the command later
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: send stored PPAG command instead of local
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: store PPAG enabled/disabled flag properly
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: fix the type we use in the PPAG table validity checks
Jae Hyun Yoo <jae.hyun.yoo@intel.com>
soc: aspeed: snoop: Add clock control logic
Dan Carpenter <dan.carpenter@oracle.com>
ath11k: fix a locking bug in ath11k_mac_op_start()
Anand K Mistry <amistry@google.com>
ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Anand K Mistry <amistry@google.com>
ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
Arnd Bergmann <arnd@arndb.de>
ARM: at91: use proper asm syntax in pm_suspend
Jérôme Pouiller <jerome.pouiller@silabs.com>
staging: wfx: fix possible panic with re-queued frames
Arnd Bergmann <arnd@arndb.de>
optee: simplify i2c access
Arnd Bergmann <arnd@arndb.de>
ARM: s3c: fix fiq for clang IAS
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: set enabled in the PPAG command properly
Artem Lapkin <email2tema@gmail.com>
arm64: dts: meson: fix broken wifi node for Khadas VIM3L
Vincent Knecht <vincent.knecht@mailoo.org>
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Luca Weiss <luca@z3ntu.xyz>
soc: qcom: ocmem: don't return NULL in of_get_ocmem
Jupeng Zhong <zhongjupeng@yulong.com>
Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Dmitry Osipenko <digetx@gmail.com>
opp: Correct debug message in _opp_add_static_v2()
Marek Behún <kabel@kernel.org>
arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to LEDs
Marc Kleine-Budde <mkl@pengutronix.de>
can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Geert Uytterhoeven <geert+renesas@glider.be>
arm64: dts: renesas: beacon: Fix EEPROM compatible value
Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Chen-Yu Tsai <wens@csie.org>
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Make "trimming xfer length" a debug message
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Abort transaction after errors with unknown reason
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Do not update data length if it is 0 on inbound transfers
Tony Lindgren <tony@atomide.com>
ARM: dts: Configure missing thermal interrupt for 4430
Pan Bian <bianpan2016@163.com>
memory: ti-aemif: Drop child node when jumping out loop
Pan Bian <bianpan2016@163.com>
Bluetooth: Put HCI device if inquiry procedure interrupts
Pan Bian <bianpan2016@163.com>
Bluetooth: drop HCI device reference before return
Borislav Petkov <bp@suse.de>
staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
Dan Carpenter <dan.carpenter@oracle.com>
soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
Robert Foss <robert.foss@linaro.org>
arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Jack Pham <jackp@codeaurora.org>
usb: gadget: u_audio: Free requests only after callback
Maximilian Luz <luzmaximilian@gmail.com>
ACPICA: Fix exception code class checks
Chen-Yu Tsai <wens@csie.org>
arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Free resources in error path
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: properly connect USB PHY to port 0
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix call site of scmi_notification_exit
Andrii Nakryiko <andrii@kernel.org>
bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
Andrii Nakryiko <andrii@kernel.org>
bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk transfers on 64-bit builds
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk userdata handling
Dinghao Liu <dinghao.liu@zju.edu.cn>
Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
Zhang Qilong <zhangqilong3@huawei.com>
memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
Christopher William Snowhill <chris@kode54.net>
Bluetooth: Fix initializing response id after clearing struct
Claire Chang <tientzu@chromium.org>
Bluetooth: hci_uart: Fix a race for write_work scheduling
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the probe function
Rakesh Pillai <pillair@codeaurora.org>
ath10k: Fix error handling in case of CE pipe init failure
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: One more flush for Baytrail clear residuals
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Don't call sync_stop if it hasn't been stopped
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Assure sync with the pending stop operation at suspend
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Call sync_stop at disconnection
Eric Biggers <ebiggers@google.com>
random: fix the RNDRESEEDCRNG ioctl
Nathan Chancellor <nathan@kernel.org>
vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
Alexander Lobakin <alobakin@pm.me>
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
Jan Kara <jack@suse.cz>
bfq: Avoid false bfq queue merging
Hans de Goede <hdegoede@redhat.com>
virt: vbox: Do not use wait_event_interruptible when called from kernel context
Ard Biesheuvel <ardb@kernel.org>
PCI: Decline to resize resources if boot config must be preserved
Ansuel Smith <ansuelsmth@gmail.com>
PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ivan Zaentsev <ivan.zaentsev@wirenboard.ru>
w1: w1_therm: Fix conversion result for negative temperatures
Sumit Garg <sumit.garg@linaro.org>
kdb: Make memory allocations more robust
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix mailbox Ch erroneous error
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: docs: Remove notify_ha_event()
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: do not attempt to create a new file before the filesystem is initalized
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: be more robust at handling improper input in debugfs_lookup()
Stefano Garzarella <sgarzare@redhat.com>
vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Nick Desaulniers <ndesaulniers@google.com>
vmlinux.lds.h: add DWARF v5 sections
-------------
Diffstat:
Documentation/admin-guide/perf/arm-cmn.rst | 2 +-
Documentation/admin-guide/sysctl/vm.rst | 10 +-
Documentation/filesystems/seq_file.rst | 6 +
Documentation/scsi/libsas.rst | 1 -
Documentation/security/keys/core.rst | 4 +-
Makefile | 4 +-
arch/arm/boot/compressed/head.S | 4 +-
arch/arm/boot/dts/armada-388-helios4.dts | 28 +-
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/arm/kernel/sys_oabi-compat.c | 15 +
arch/arm/mach-at91/pm_suspend.S | 2 +-
arch/arm/mach-ixp4xx/Kconfig | 1 -
arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9 +-
arch/arm64/Kconfig | 2 +-
.../boot/dts/allwinner/sun50i-a64-pinebook.dts | 5 +-
.../boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 -
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 +-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7 +
.../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7 +-
.../boot/dts/exynos/exynos5433-tm2-common.dtsi | 2 +-
arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +-
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4 +-
.../boot/dts/marvell/armada-3720-turris-mox.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +
.../dts/qcom/msm8916-samsung-a2015-common.dtsi | 6 +
.../boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2 +-
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 9 +-
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 +-
.../boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +-
.../arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4 +-
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 +
arch/arm64/crypto/aes-glue.c | 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/include/asm/module.lds.h | 6 +-
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/head.S | 1 +
arch/arm64/kernel/machine_kexec_file.c | 4 +-
arch/arm64/kernel/probes/uprobes.c | 2 +-
arch/arm64/kernel/ptrace.c | 2 +-
arch/arm64/kernel/suspend.c | 2 +-
arch/csky/kernel/ptrace.c | 2 +-
arch/mips/Makefile | 19 ++
arch/mips/cavium-octeon/setup.c | 9 +-
arch/mips/include/asm/asm.h | 18 ++
arch/mips/include/asm/atomic.h | 2 +-
arch/mips/include/asm/cmpxchg.h | 6 +-
arch/mips/kernel/cpu-probe.c | 15 +-
arch/mips/kernel/vmlinux.lds.S | 2 +-
arch/mips/lantiq/irq.c | 2 +-
arch/mips/loongson64/Platform | 22 --
arch/mips/mm/c-r4k.c | 2 +-
arch/mips/vdso/Makefile | 5 +-
arch/nios2/kernel/entry.S | 3 +
arch/nios2/kernel/sys_nios2.c | 11 +-
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/kexec.h | 1 +
arch/powerpc/include/asm/uaccess.h | 13 +-
arch/powerpc/kernel/entry_32.S | 3 +
arch/powerpc/kernel/head_32.h | 2 +-
arch/powerpc/kernel/head_8xx.S | 2 +-
arch/powerpc/kernel/head_book3s_32.S | 6 -
arch/powerpc/kernel/irq.c | 27 +-
arch/powerpc/kernel/prom_init.c | 12 +-
arch/powerpc/kernel/time.c | 2 +
arch/powerpc/kexec/elf_64.c | 2 +-
arch/powerpc/kexec/file_load_64.c | 35 +++
arch/powerpc/kvm/powerpc.c | 8 +-
arch/powerpc/platforms/pseries/dlpar.c | 7 +-
arch/riscv/kernel/vdso/Makefile | 3 +-
arch/s390/kernel/vtime.c | 3 +-
arch/sparc/Kconfig | 2 +-
arch/sparc/kernel/led.c | 2 +
arch/sparc/lib/memset.S | 1 +
arch/um/include/shared/skas/mm_id.h | 1 +
arch/um/kernel/tlb.c | 19 +-
arch/um/os-Linux/skas/process.c | 4 +
arch/x86/crypto/aesni-intel_glue.c | 28 +-
arch/x86/entry/common.c | 2 +-
arch/x86/include/asm/virtext.h | 17 +-
arch/x86/kernel/msr.c | 7 +
arch/x86/kernel/reboot.c | 30 +-
arch/x86/kvm/emulate.c | 4 +-
arch/x86/kvm/mmu/tdp_mmu.c | 3 +-
arch/x86/kvm/svm/nested.c | 22 +-
arch/x86/kvm/svm/svm.c | 8 +-
arch/x86/kvm/x86.c | 1 +
arch/x86/mm/fault.c | 27 +-
arch/x86/mm/pat/memtype.c | 4 +-
block/bfq-iosched.c | 1 +
block/blk-settings.c | 12 +
block/bsg.c | 4 +-
block/ioctl.c | 21 +-
certs/blacklist.c | 2 +-
crypto/ecdh_helper.c | 3 +
crypto/michael_mic.c | 31 +-
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/base/swnode.c | 8 +-
drivers/block/floppy.c | 30 +-
drivers/bluetooth/btqcomsmd.c | 27 +-
drivers/bluetooth/btusb.c | 20 +-
drivers/bluetooth/hci_ldisc.c | 41 ++-
drivers/bluetooth/hci_qca.c | 2 +
drivers/bluetooth/hci_serdev.c | 4 +-
drivers/char/hw_random/ingenic-trng.c | 6 +-
drivers/char/hw_random/timeriomem-rng.c | 2 +-
drivers/char/random.c | 2 +-
drivers/char/tpm/tpm.h | 4 -
drivers/char/tpm/tpm_tis_core.c | 50 +--
drivers/clk/clk-ast2600.c | 37 ++-
drivers/clk/clk-divider.c | 9 +-
drivers/clk/meson/clk-pll.c | 10 +-
drivers/clk/qcom/gcc-msm8998.c | 100 +++---
drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +-
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/mxs_timer.c | 5 +-
drivers/cpufreq/acpi-cpufreq.c | 62 +---
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +-
drivers/cpufreq/freq_table.c | 8 +-
drivers/cpufreq/intel_pstate.c | 21 +-
drivers/cpufreq/qcom-cpufreq-hw.c | 40 ++-
.../crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 ++++++----
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2 +
drivers/crypto/bcm/cipher.c | 2 +-
drivers/crypto/bcm/cipher.h | 4 +-
drivers/crypto/bcm/util.c | 2 +-
drivers/crypto/talitos.c | 50 ++-
drivers/crypto/talitos.h | 1 +
drivers/dax/bus.c | 2 +-
drivers/dma/fsldma.c | 6 +
drivers/dma/hsu/pci.c | 21 +-
drivers/dma/idxd/dma.c | 1 +
drivers/dma/owl-dma.c | 1 +
drivers/firmware/arm_scmi/driver.c | 4 +-
drivers/gpio/gpio-pcf857x.c | 2 +-
drivers/gpu/drm/Kconfig | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +-
drivers/gpu/drm/amd/amdgpu/soc15.c | 2 +
.../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2 +-
.../gpu/drm/amd/display/dc/bios/command_table.c | 61 ++++
.../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14 +
.../drm/amd/display/dc/dce/dce_stream_encoder.c | 1 +
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8 +-
.../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1 -
.../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +
.../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 ++
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +-
drivers/gpu/drm/drm_dp_mst_topology.c | 3 +-
drivers/gpu/drm/drm_fb_helper.c | 15 +-
drivers/gpu/drm/drm_modes.c | 4 +-
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +-
drivers/gpu/drm/gma500/psb_drv.c | 2 +
drivers/gpu/drm/i915/display/intel_hdmi.c | 6 +-
drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12 +-
drivers/gpu/drm/lima/lima_sched.c | 2 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8 +
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 8 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 5 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +-
drivers/gpu/drm/msm/msm_drv.c | 3 +-
.../drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 +
drivers/gpu/drm/nouveau/nouveau_chan.c | 1 +
drivers/gpu/drm/nouveau/nouveau_connector.c | 1 +
drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3 +-
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5 +
drivers/gpu/drm/rcar-du/rcar_cmm.c | 2 +-
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 +-
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 +-
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11 +
drivers/gpu/drm/scheduler/sched_main.c | 3 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 +-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/tegra/dc.c | 2 +-
drivers/gpu/drm/tegra/dsi.c | 2 +-
drivers/gpu/drm/tegra/hdmi.c | 2 +-
drivers/gpu/drm/tegra/hub.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 2 +-
drivers/gpu/drm/tegra/vic.c | 2 +-
drivers/gpu/drm/vc4/vc4_hdmi.c | 87 +++--
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +-
drivers/gpu/drm/virtio/virtgpu_gem.c | 8 +-
drivers/hid/hid-core.c | 3 +
drivers/hid/hid-logitech-dj.c | 1 +
drivers/hid/wacom_wac.c | 7 +-
drivers/hsi/controllers/omap_ssi_core.c | 2 +-
drivers/hv/channel_mgmt.c | 3 +-
drivers/hwtracing/coresight/coresight-etm4x-core.c | 21 +-
.../hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +-
drivers/i2c/busses/i2c-bcm-iproc.c | 231 +++++++++++---
drivers/i2c/busses/i2c-brcmstb.c | 2 +-
drivers/i2c/busses/i2c-exynos5.c | 8 +-
drivers/i2c/busses/i2c-qcom-geni.c | 93 +++++-
drivers/ide/falconide.c | 3 +-
drivers/infiniband/core/cm.c | 8 +-
drivers/infiniband/core/cma.c | 70 +++--
drivers/infiniband/core/user_mad.c | 17 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 2 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 8 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 3 +-
drivers/infiniband/hw/mlx5/devx.c | 4 +-
drivers/infiniband/hw/mlx5/main.c | 14 +-
drivers/infiniband/sw/rxe/rxe_net.c | 5 +
drivers/infiniband/sw/rxe/rxe_recv.c | 27 +-
drivers/infiniband/sw/siw/siw.h | 2 +-
drivers/infiniband/sw/siw/siw_main.c | 2 +-
drivers/infiniband/sw/siw/siw_qp.c | 271 ++++++++--------
drivers/infiniband/sw/siw/siw_qp_rx.c | 26 +-
drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +-
drivers/infiniband/sw/siw/siw_verbs.c | 20 +-
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2 +
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51 +--
drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1 +
drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 117 ++++---
drivers/infiniband/ulp/rtrs/rtrs.c | 14 +-
drivers/input/joydev.c | 7 +-
drivers/input/joystick/xpad.c | 1 +
drivers/input/serio/i8042-x86ia64io.h | 4 +
drivers/input/serio/serport.c | 4 +-
drivers/input/touchscreen/elo.c | 4 +-
drivers/input/touchscreen/raydium_i2c_ts.c | 3 +-
drivers/input/touchscreen/sur40.c | 1 +
drivers/input/touchscreen/zinitix.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 +
drivers/iommu/iommu.c | 23 +-
drivers/iommu/mtk_iommu.c | 2 +-
drivers/irqchip/Kconfig | 3 +-
drivers/irqchip/irq-loongson-pch-msi.c | 2 +-
drivers/macintosh/adb-iop.c | 6 +-
drivers/mailbox/sprd-mailbox.c | 2 +-
drivers/md/bcache/bcache.h | 3 +
drivers/md/bcache/btree.c | 21 +-
drivers/md/bcache/journal.c | 4 +-
drivers/md/bcache/super.c | 20 ++
drivers/md/dm-core.h | 4 +
drivers/md/dm-crypt.c | 1 +
drivers/md/dm-era-target.c | 93 ++++--
drivers/md/dm-table.c | 168 +++++-----
drivers/md/dm-writecache.c | 74 +++--
drivers/md/dm.c | 62 +++-
drivers/md/dm.h | 2 +-
drivers/media/i2c/max9286.c | 2 +-
drivers/media/i2c/ov5670.c | 3 +-
drivers/media/pci/cx25821/cx25821-core.c | 4 +-
drivers/media/pci/intel/ipu3/Kconfig | 3 +-
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +-
drivers/media/pci/saa7134/saa7134-empress.c | 5 +-
drivers/media/pci/smipcie/smipcie-ir.c | 46 +--
drivers/media/platform/aspeed-video.c | 6 +-
drivers/media/platform/marvell-ccic/mcam-core.c | 2 +
.../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 +-
.../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3 +-
drivers/media/platform/pxa_camera.c | 3 +
drivers/media/platform/qcom/camss/camss-video.c | 1 +
drivers/media/platform/ti-vpe/cal.c | 4 +-
drivers/media/platform/vsp1/vsp1_drv.c | 4 +-
drivers/media/rc/ir_toy.c | 1 +
drivers/media/rc/mceusb.c | 2 +-
drivers/media/test-drivers/vidtv/vidtv_psi.c | 5 +-
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/mtk-smi.c | 4 +-
drivers/memory/ti-aemif.c | 8 +-
drivers/mfd/altera-sysmgr.c | 3 +-
drivers/mfd/bd9571mwv.c | 6 +-
drivers/mfd/gateworks-gsc.c | 2 +-
drivers/mfd/wm831x-auxadc.c | 3 +-
drivers/misc/cardreader/rts5227.c | 5 +
drivers/misc/eeprom/eeprom_93xx46.c | 1 +
drivers/misc/fastrpc.c | 7 +-
drivers/misc/mei/hbm.c | 2 +-
drivers/misc/mei/hw-me-regs.h | 5 +
drivers/misc/mei/interrupt.c | 33 +-
drivers/misc/mei/pci-me.c | 5 +
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +-
drivers/mmc/host/owl-mmc.c | 9 +-
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +-
drivers/mmc/host/sdhci-esdhc-imx.c | 3 +-
drivers/mmc/host/sdhci-pci-o2micro.c | 20 ++
drivers/mmc/host/sdhci-sprd.c | 6 +-
drivers/mmc/host/usdhi6rol0.c | 4 +-
drivers/mtd/parsers/afs.c | 4 +-
drivers/mtd/parsers/parser_imagetag.c | 4 +
drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4 +-
drivers/mtd/spi-nor/core.c | 10 +-
drivers/mtd/spi-nor/sfdp.c | 5 +-
drivers/net/Kconfig | 2 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +-
drivers/net/dsa/ocelot/felix.c | 16 +-
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 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +-
.../chelsio/inline_crypto/chtls/chtls_cm.h | 3 -
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14 +-
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
drivers/net/ethernet/ibm/ibmvnic.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 50 +--
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 +-
drivers/net/ethernet/intel/ice/ice.h | 2 -
drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6 +-
drivers/net/ethernet/intel/ice/ice_ethtool.c | 34 +-
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33 +-
drivers/net/ethernet/marvell/mvneta.c | 9 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2 +-
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9 +
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 +++++++++++----
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2 +-
.../mellanox/mlx5/core/en_accel/en_accel.h | 2 +-
.../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66 ++--
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8 +-
drivers/net/ethernet/mellanox/mlx5/core/health.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 +-
drivers/net/ethernet/realtek/r8169_main.c | 4 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 +-
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26 +-
drivers/net/gtp.c | 1 -
drivers/net/phy/mscc/mscc.h | 8 +
drivers/net/phy/mscc/mscc_main.c | 350 ++++++++++++++-------
drivers/net/phy/phy_device.c | 53 +---
drivers/net/ppp/ppp_async.c | 3 +-
drivers/net/ppp/ppp_synctty.c | 3 +-
drivers/net/vxlan.c | 11 +-
drivers/net/wireguard/device.c | 19 +-
drivers/net/wireguard/device.h | 15 +-
drivers/net/wireguard/peer.c | 28 +-
drivers/net/wireguard/peer.h | 4 +-
drivers/net/wireguard/queueing.c | 86 ++++-
drivers/net/wireguard/queueing.h | 45 ++-
drivers/net/wireguard/receive.c | 16 +-
drivers/net/wireguard/send.c | 31 +-
drivers/net/wireless/ath/ath10k/mac.c | 2 +
drivers/net/wireless/ath/ath10k/snoc.c | 5 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +
drivers/net/wireless/ath/ath11k/mac.c | 11 +-
drivers/net/wireless/ath/ath9k/debug.c | 5 +-
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43 ++-
.../net/wireless/intel/iwlwifi/mvm/time-event.c | 3 -
.../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21 +-
drivers/net/xen-netback/interface.c | 8 +-
drivers/nvme/host/multipath.c | 4 +
drivers/nvme/target/admin-cmd.c | 33 +-
drivers/nvme/target/tcp.c | 59 +++-
drivers/nvmem/core.c | 5 +-
drivers/nvmem/qcom-spmi-sdam.c | 7 +-
drivers/of/fdt.c | 12 +-
drivers/opp/of.c | 4 +-
drivers/pci/controller/cadence/pcie-cadence-host.c | 5 +-
drivers/pci/controller/dwc/pcie-qcom.c | 4 +-
drivers/pci/controller/pcie-rcar-host.c | 2 +-
drivers/pci/controller/pcie-rockchip.c | 12 +-
drivers/pci/controller/pcie-xilinx-cpm.c | 1 +
drivers/pci/pci-bridge-emul.c | 11 +-
drivers/pci/setup-res.c | 6 +
drivers/pci/syscall.c | 10 +-
drivers/perf/arm-cmn.c | 17 +-
drivers/phy/Kconfig | 1 +
drivers/phy/cadence/phy-cadence-torrent.c | 1 +
drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10 +-
drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +-
drivers/platform/chrome/cros_ec_proto.c | 12 +-
drivers/power/reset/at91-sama5d2_shdwc.c | 2 +-
drivers/power/supply/Kconfig | 1 +
drivers/power/supply/axp20x_usb_power.c | 2 +-
drivers/power/supply/cpcap-battery.c | 12 +-
drivers/power/supply/cpcap-charger.c | 4 +-
drivers/power/supply/smb347-charger.c | 12 +-
drivers/pwm/pwm-iqs620a.c | 8 +-
drivers/pwm/pwm-rockchip.c | 18 +-
drivers/regulator/axp20x-regulator.c | 7 +-
drivers/regulator/core.c | 6 +-
drivers/regulator/qcom-rpmh-regulator.c | 26 ++
drivers/regulator/rohm-regulator.c | 9 +-
drivers/regulator/s5m8767.c | 15 +-
drivers/remoteproc/mtk_common.h | 1 +
drivers/remoteproc/mtk_scp.c | 20 +-
drivers/rtc/Kconfig | 3 +-
drivers/s390/crypto/zcrypt_api.c | 14 +
drivers/s390/virtio/virtio_ccw.c | 4 +-
drivers/scsi/bnx2fc/Kconfig | 1 +
drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +-
drivers/scsi/qla2xxx/qla_dbg.c | 1 +
drivers/scsi/qla2xxx/qla_mbx.c | 3 +-
drivers/scsi/sd.c | 6 +-
drivers/scsi/sd_zbc.c | 6 +-
drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +-
drivers/soc/qcom/ocmem.c | 8 +-
drivers/soc/qcom/socinfo.c | 2 +-
drivers/soc/samsung/exynos-asv.c | 18 +-
drivers/soc/ti/pm33xx.c | 5 +-
drivers/soundwire/bus.c | 47 ++-
drivers/soundwire/cadence_master.c | 8 +-
drivers/soundwire/debugfs.c | 2 +-
drivers/soundwire/intel_init.c | 3 +-
drivers/spi/spi-atmel.c | 2 +-
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-dw-bt1.c | 2 +-
drivers/spi/spi-fsl-spi.c | 2 +-
drivers/spi/spi-imx.c | 2 +-
drivers/spi/spi-pxa2xx-pci.c | 27 +-
drivers/spi/spi-stm32.c | 4 +
drivers/spi/spi-synquacer.c | 4 +
drivers/spi/spi.c | 2 +-
drivers/spmi/spmi-pmic-arb.c | 5 +-
drivers/staging/gdm724x/gdm_usb.c | 10 +-
drivers/staging/media/allegro-dvt/allegro-core.c | 3 +-
drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24 +-
drivers/staging/media/atomisp/pci/hmm/hmm.c | 2 +-
drivers/staging/media/imx/imx-media-csc-scaler.c | 4 -
drivers/staging/media/imx/imx-media-dev.c | 7 +-
drivers/staging/media/imx/imx7-media-csi.c | 27 +-
drivers/staging/mt7621-dma/Makefile | 2 +-
.../mt7621-dma/{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 +-
.../vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 +-
drivers/staging/wfx/data_tx.c | 10 +-
drivers/staging/wfx/data_tx.h | 1 +
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-
drivers/tee/optee/rpc.c | 31 +-
drivers/thermal/cpufreq_cooling.c | 2 +-
drivers/tty/n_gsm.c | 3 +-
drivers/tty/n_hdlc.c | 60 ++--
drivers/tty/n_null.c | 3 +-
drivers/tty/n_r3964.c | 10 +-
drivers/tty/n_tracerouter.c | 4 +-
drivers/tty/n_tracesink.c | 4 +-
drivers/tty/n_tty.c | 82 ++---
drivers/tty/tty_io.c | 82 ++++-
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/usb/serial/pl2303.c | 8 +-
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
drivers/vfio/pci/vfio_pci_zdev.c | 4 +
drivers/vfio/vfio_iommu_type1.c | 63 ++--
drivers/video/fbdev/Kconfig | 2 +-
drivers/virt/vboxguest/vboxguest_utils.c | 18 +-
drivers/w1/slaves/w1_therm.c | 22 +-
drivers/watchdog/intel-mid_wdt.c | 8 +-
drivers/watchdog/mei_wdt.c | 1 +
drivers/watchdog/qcom-wdt.c | 13 +-
fs/affs/namei.c | 4 +-
fs/btrfs/backref.c | 9 +-
fs/btrfs/backref.h | 9 +-
fs/btrfs/block-group.c | 29 +-
fs/btrfs/ctree.c | 7 +-
fs/btrfs/delayed-ref.c | 56 ++--
fs/btrfs/delayed-ref.h | 16 +-
fs/btrfs/extent-tree.c | 128 ++------
fs/btrfs/free-space-cache.c | 6 +-
fs/btrfs/inode.c | 3 +-
fs/btrfs/relocation.c | 4 +-
fs/btrfs/space-info.h | 17 +
fs/ceph/caps.c | 10 +-
fs/debugfs/inode.c | 5 +-
fs/erofs/xattr.c | 10 +-
fs/erofs/zmap.c | 10 +-
fs/eventpoll.c | 4 +-
fs/exfat/exfat_raw.h | 4 +
fs/exfat/super.c | 31 +-
fs/ext4/Kconfig | 3 +-
fs/ext4/namei.c | 7 +-
fs/f2fs/compress.c | 5 +-
fs/f2fs/data.c | 12 +-
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 24 +-
fs/f2fs/inline.c | 4 +
fs/f2fs/super.c | 3 +
fs/gfs2/bmap.c | 6 +-
fs/gfs2/lock_dlm.c | 8 +-
fs/gfs2/recovery.c | 4 +-
fs/gfs2/util.c | 16 +-
fs/io_uring.c | 17 +-
fs/isofs/dir.c | 1 +
fs/isofs/namei.c | 1 +
fs/jffs2/summary.c | 3 +
fs/jfs/jfs_dmap.c | 2 +-
fs/nfs/nfs4proc.c | 15 +-
fs/nfsd/nfsctl.c | 14 +-
fs/ocfs2/cluster/heartbeat.c | 8 +-
fs/proc/proc_sysctl.c | 4 +-
fs/proc/self.c | 2 +-
fs/proc/task_mmu.c | 9 +-
fs/proc/thread_self.c | 7 +
fs/pstore/platform.c | 4 +-
fs/quota/quota_v2.c | 11 +-
fs/ubifs/auth.c | 2 +-
fs/ubifs/replay.c | 4 +-
fs/ubifs/super.c | 4 +-
fs/zonefs/super.c | 3 +
include/acpi/acexcep.h | 10 +-
include/asm-generic/vmlinux.lds.h | 16 +-
include/linux/bpf.h | 3 +
include/linux/device-mapper.h | 5 +
include/linux/entry-kvm.h | 14 +
include/linux/eventpoll.h | 2 +-
include/linux/filter.h | 2 +-
include/linux/icmpv6.h | 28 +-
include/linux/iommu.h | 4 +-
include/linux/ipv6.h | 1 -
include/linux/kexec.h | 5 +
include/linux/key.h | 1 +
include/linux/kgdb.h | 2 +
include/linux/khugepaged.h | 2 +
include/linux/memremap.h | 6 +
include/linux/mfd/rohm-generic.h | 14 +-
include/linux/rcupdate.h | 2 +
include/linux/rmap.h | 3 +-
include/linux/soundwire/sdw.h | 2 +
include/linux/tpm.h | 5 +-
include/linux/tty_ldisc.h | 3 +-
include/net/act_api.h | 6 +-
include/net/icmp.h | 6 +-
include/net/tcp.h | 9 +-
include/uapi/drm/drm_fourcc.h | 4 +-
init/Kconfig | 11 +
init/main.c | 1 +
kernel/Makefile | 2 +-
kernel/bpf/bpf_iter.c | 2 +-
kernel/bpf/bpf_lru_list.c | 7 +-
kernel/bpf/devmap.c | 4 +-
kernel/bpf/verifier.c | 3 +-
kernel/debug/debug_core.c | 11 +
kernel/debug/kdb/kdb_private.h | 2 +-
kernel/entry/common.c | 7 +
kernel/kcsan/core.c | 26 +-
kernel/kexec_file.c | 5 +
kernel/kprobes.c | 31 +-
kernel/locking/lockdep.c | 3 +-
kernel/module.c | 21 +-
kernel/printk/printk.c | 28 +-
kernel/printk/printk_safe.c | 16 +-
kernel/rcu/tree.c | 53 +++-
kernel/rcu/tree.h | 2 +-
kernel/rcu/tree_plugin.h | 31 +-
kernel/sched/fair.c | 45 ++-
kernel/sched/idle.c | 1 +
kernel/seccomp.c | 2 +
kernel/smp.c | 4 +
kernel/tracepoint.c | 80 ++++-
mm/compaction.c | 43 +--
mm/hugetlb.c | 14 +-
mm/khugepaged.c | 22 +-
mm/memcontrol.c | 30 +-
mm/memory-failure.c | 6 +
mm/memory.c | 16 +-
mm/memremap.c | 15 +
mm/slab_common.c | 4 +-
mm/slub.c | 8 +-
mm/vmscan.c | 9 +-
net/bluetooth/a2mp.c | 3 +-
net/bluetooth/hci_core.c | 6 +-
net/core/filter.c | 13 +-
net/ipv4/icmp.c | 5 +-
net/ipv6/icmp.c | 18 +-
net/ipv6/ip6_icmp.c | 12 +-
net/mac80211/mesh_hwmp.c | 2 +-
net/nfc/nci/uart.c | 3 +-
net/qrtr/tun.c | 12 +-
net/sched/act_api.c | 106 ++++---
net/sched/cls_api.c | 12 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 6 +-
samples/Kconfig | 2 +-
samples/watch_queue/watch_test.c | 2 +-
security/commoncap.c | 12 +-
security/integrity/evm/evm_crypto.c | 7 +-
security/integrity/ima/ima_kexec.c | 3 +
security/integrity/ima/ima_mok.c | 5 +-
security/keys/Kconfig | 8 +-
security/keys/key.c | 2 +
security/keys/trusted-keys/trusted_tpm1.c | 22 +-
security/keys/trusted-keys/trusted_tpm2.c | 22 +-
security/selinux/hooks.c | 4 +
sound/core/init.c | 4 +
sound/core/pcm.c | 4 +
sound/core/pcm_local.h | 1 +
sound/core/pcm_native.c | 27 +-
sound/firewire/fireface/ff-protocol-latter.c | 118 +++++--
sound/pci/hda/hda_intel.c | 2 +
sound/pci/hda/patch_hdmi.c | 1 -
sound/pci/hda/patch_realtek.c | 40 +++
sound/soc/codecs/cpcap.c | 12 +-
sound/soc/codecs/cs42l56.c | 3 +-
sound/soc/codecs/rt5682-i2c.c | 3 +
sound/soc/codecs/wsa881x.c | 1 +
sound/soc/generic/simple-card-utils.c | 13 +-
sound/soc/intel/boards/sof_sdw.c | 6 +-
sound/soc/qcom/lpass-apq8016.c | 2 +-
sound/soc/qcom/lpass-cpu.c | 30 +-
sound/soc/qcom/lpass-lpaif-reg.h | 3 -
sound/soc/qcom/lpass.h | 1 -
sound/soc/qcom/qdsp6/q6asm-dai.c | 21 ++
sound/soc/qcom/qdsp6/q6routing.c | 18 --
sound/soc/sh/siu.h | 2 +-
sound/soc/sh/siu_pcm.c | 2 +-
sound/soc/sof/debug.c | 2 +-
sound/soc/sof/intel/hda-dsp.c | 4 +
sound/soc/sof/sof-pci-dev.c | 7 +
sound/usb/pcm.c | 2 +-
tools/lib/bpf/libbpf.c | 22 +-
tools/objtool/arch/x86/special.c | 2 +-
tools/objtool/check.c | 15 +-
tools/objtool/check.h | 11 +
tools/perf/builtin-record.c | 2 +-
.../pmu-events/arch/arm64/ampere/emag/cache.json | 2 +-
tools/perf/tests/sample-parsing.c | 2 +-
tools/perf/util/event.c | 2 +
tools/perf/util/evlist.c | 8 +
tools/perf/util/evlist.h | 4 +
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 41 ++-
.../perf/util/intel-pt-decoder/intel-pt-decoder.h | 2 +
tools/perf/util/intel-pt.c | 29 +-
tools/perf/util/symbol.c | 7 +-
tools/testing/kunit/kunit_tool_test.py | 14 +-
tools/testing/selftests/bpf/test_xdp_redirect.sh | 10 +-
tools/testing/selftests/dmabuf-heaps/Makefile | 2 +-
.../trigger-synthetic_event_syntax_errors.tc | 35 ++-
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 +-
tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +-
tools/testing/selftests/seccomp/seccomp_bpf.c | 2 +-
tools/testing/selftests/wireguard/netns.sh | 15 +-
671 files changed, 5852 insertions(+), 3024 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.11 000/774] 5.11.3-rc2 review
@ 2021-03-01 19:38 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-01 19:38 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.11.3 release.
There are 774 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 03 Mar 2021 19:35:23 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.3-rc2.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.11.3-rc2
Cong Wang <cong.wang@bytedance.com>
net_sched: fix RTNL deadlock again caused by request_module()
Takeshi Misawa <jeliantsurux@gmail.com>
net: qrtr: Fix memory leak in qrtr_tun_open
Vlad Buslov <vladbu@nvidia.com>
net: sched: fix police ext initialization
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: get rid of per-peer ring buffers
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: selftests: test multiple parallel streams
Jason A. Donenfeld <Jason@zx2c4.com>
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Leon Romanovsky <leon@kernel.org>
ipv6: silence compilation warning for non-IPV6 builds
Sumit Garg <sumit.garg@linaro.org>
kgdb: fix to kill breakpoints on initmem after boot
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/i915: Reject 446-480MHz HDMI clock on GLK
Nikos Tsironis <ntsironis@arrikto.com>
dm era: only resize metadata in preresume
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Reinitialize bitset cache before digesting a new writeset
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Use correct value size in equality function of writeset tree
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Fix bitset memory leaks
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Verify the data block size hasn't changed
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Update in-core bitset after committing the metadata
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Recover committed writeset after crash
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix writing beyond end of underlying device when shrinking
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: return the exact table values that were set
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix performance degradation in ssd mode
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix zoned iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix DAX iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix iterate_devices based device capability checks
Mikulas Patocka <mpatocka@redhat.com>
dm: fix deadlock when swapping to encrypted device
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Lock imbalance on error path in gfs2_recover_one
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't skip dlm unlock if glock has an lvb
Bob Peterson <rpeterso@redhat.com>
gfs2: fix glock confusion in function signal_our_withdraw
Masahisa Kojima <masahisa.kojima@linaro.org>
spi: spi-synquacer: fix set_cs handling
Rasmus Villemoes <rasmus.villemoes@prevas.dk>
spi: fsl: invert spisel_boot signal on MPC8309
Paul Cercueil <paul@crapouillou.net>
perf stat: Use nftw() instead of ftw()
Al Viro <viro@zeniv.linux.org.uk>
sparc32: fix a user-triggerable oops in clear_user()
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: fix handling of escaped ',' in the password mount argument
Paulo Alcantara <pc@cjr.nz>
cifs: fix nodfs mount option
Paulo Alcantara <pc@cjr.nz>
cifs: introduce helper for finding referral server to improve DFS target resolution
Paulo Alcantara <pc@cjr.nz>
cifs: check all path components in resolved dfs target
Paulo Alcantara <pc@cjr.nz>
cifs: fix DFS failover
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: flush data when enabling checkpoint back
Chao Yu <chao@kernel.org>
f2fs: enforce the immutable flag on open files
Chao Yu <chao@kernel.org>
f2fs: fix out-of-repair __setattr_copy()
Huacai Chen <chenhuacai@kernel.org>
irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Johannes Berg <johannes.berg@intel.com>
um: defer killing userspace on page table update failures
Johannes Berg <johannes.berg@intel.com>
um: mm: check more comprehensively for stub changes
Cornelia Huck <cohuck@redhat.com>
virtio/s390: implement virtio-ccw revision 2 correctly
Heiko Carstens <hca@linux.ibm.com>
s390/vtime: fix inline assembly clobber list
Jens Axboe <axboe@kernel.dk>
proc: don't allow async path resolution of /proc/thread-self components
Chen Yu <yu.c.chen@intel.com>
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Shawn Guo <shawn.guo@linaro.org>
cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Viresh Kumar <viresh.kumar@linaro.org>
thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Chris Wilson <chris@chris-wilson.co.uk>
kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
zonefs: Fix file size of zones in full condition
Namjae Jeon <namjae.jeon@samsung.com>
exfat: fix shift-out-of-bounds in exfat_fill_super()
Muchun Song <songmuchun@bytedance.com>
printk: fix deadlock when kernel panic
Tim Harvey <tharvey@gateworks.com>
mfd: gateworks-gsc: Fix interrupt type
Maxim Kiselev <bigunclemax@gmail.com>
gpio: pcf857x: Fix missing first interrupt
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point LP DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point S DID
Tomas Winkler <tomas.winkler@intel.com>
mei: me: emmitsburg workstation DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: fix transfer over dma with extended header
Alexander Usyskin <alexander.usyskin@intel.com>
mei: bus: block send with vtag on non-conformat FW
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
spmi: spmi-pmic-arb: Fix hw_irq overflow
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32s: Add missing call to kuep_lock on syscall entry
Hari Bathini <hbathini@linux.ibm.com>
powerpc/kexec_file: fix FDT size estimation for kdump kernel
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
Shirley Her <shirley.her@bayhubtech.com>
mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Frank Li <Frank.Li@nxp.com>
mmc: sdhci-esdhc-imx: fix kernel panic when remove module
Fangrui Song <maskray@google.com>
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
Paolo Bonzini <pbonzini@redhat.com>
KVM: nSVM: fix running nested guests when npt=0
Vlastimil Babka <vbabka@suse.cz>
mm, compaction: make fast_isolate_freepages() stay within zone
Dave Hansen <dave.hansen@linux.intel.com>
mm/vmscan: restore zone_reclaim_mode ABI
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix update_and_free_page contig page struct assumption
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix get_active_memcg return value
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix swap undercounting in cgroup2
NeilBrown <neilb@suse.de>
x86: fix seq_file iteration for pat/memtype.c
NeilBrown <neilb@suse.de>
seq_file: document how per-entry resources are managed.
Pan Bian <bianpan2016@163.com>
fs/affs: release old buffer head on error path
Pan Bian <bianpan2016@163.com>
mtd: spi-nor: hisi-sfc: Put child node np on error path
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Add erase size check for erase command initialization
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Fix erase type discovery for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix last erase region marking
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Handle accesses to TRCSTALLCTLR
Alexander Usyskin <alexander.usyskin@intel.com>
watchdog: mei_wdt: request stop on unregister
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Tobias Klauser <tklauser@distanz.ch>
riscv: Disable KSAN_SANITIZE for vDSO
Will Deacon <will@kernel.org>
arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Shaoying Xu <shaoyi@amazon.com>
arm64 module: set plt* section addresses to 0x0
He Zhe <zhe.he@windriver.com>
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
qiuguorui1 <qiuguorui1@huawei.com>
arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
Viresh Kumar <viresh.kumar@linaro.org>
mailbox: arm_mhuv2: Skip calling kfree() with invalid pointer
Isaac J. Manjarres <isaacm@codeaurora.org>
iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Suzuki K Poulose <suzuki.poulose@arm.com>
arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
Masami Hiramatsu <mhiramat@kernel.org>
kprobes: Fix to delay the kprobes jump optimization
Frederic Weisbecker <frederic@kernel.org>
entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
entry: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Trigger self-IPI on late deferred wake up before user resume
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Perform deferred wake up before last idle's need_resched() check
Frederic Weisbecker <frederic@kernel.org>
rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
Cédric Le Goater <clg@kaod.org>
powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Thomas Gleixner <tglx@linutronix.de>
x86/entry: Fix instrumentation annotation
Andy Lutomirski <luto@kernel.org>
x86/fault: Fix AMD erratum #91 errata fixup for user code
Sean Christopherson <seanjc@google.com>
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Christopherson <seanjc@google.com>
x86/virt: Eat faults on VMXOFF in reboot flows
Sean Young <sean@mess.org>
media: smipcie: fix interrupt handling and IR timeout
Lubomir Rintel <lkundrak@v3.sk>
media: marvell-ccic: power up the device on mclk enable
Pavel Machek <pavel@denx.de>
media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
Sean Young <sean@mess.org>
media: ir_toy: add another IR Droid device
Sakari Ailus <sakari.ailus@linux.intel.com>
media: v4l: ioctl: Fix memory leak in video_usercopy
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: i2c: max9286: fix access to unallocated memory
Jiri Kosina <jkosina@suse.cz>
floppy: reintroduce O_NDELAY fix
Martin Kaiser <martin@kaiser.cx>
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Amey Narkhede <ameynarkhede03@gmail.com>
staging: gdm724x: Fix DMA from stack
Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Dinh Nguyen <dinguyen@kernel.org>
arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Frank Wunderlich <frank-w@public-files.de>
dts64: mt7622: fix slow sd card access
Jiri Bohac <jbohac@suse.cz>
pstore: Fix typo in compression option name
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Ricky Wu <ricky_wu@realtek.com>
misc: rtsx: init of rts522a add OCP power off when no card is present
Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Paul Cercueil <paul@crapouillou.net>
seccomp: Add missing return in non-void function
Krzysztof Kozlowski <krzk@kernel.org>
soc: samsung: exynos-asv: handle reading revision register error
Marek Szyprowski <m.szyprowski@samsung.com>
soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - initialize need_fallback
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - handle BigEndian for cipher
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - IV register does not work on A10 and A13
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - checking sg length is not sufficient
Ard Biesheuvel <ardb@kernel.org>
crypto: michael_mic - fix broken misalignment handling
Ard Biesheuvel <ardb@kernel.org>
crypto: aesni - prevent misaligned buffers on the stack
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/sha - add missing module aliases
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Correct surface base address for renderclear
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Flush before changing register state
Filipe Manana <fdmanana@suse.com>
btrfs: fix extent buffer leak on failure to copy root
Josef Bacik <josef@toxicpanda.com>
btrfs: account for new extents being deleted in total_bytes_pinned
Josef Bacik <josef@toxicpanda.com>
btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
Josef Bacik <josef@toxicpanda.com>
btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
Josef Bacik <josef@toxicpanda.com>
btrfs: fix reloc root leak with 0 ref reloc roots on recovery
Josef Bacik <josef@toxicpanda.com>
btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
Josef Bacik <josef@toxicpanda.com>
btrfs: add asserts for deleting backref cache nodes
Josef Bacik <josef@toxicpanda.com>
btrfs: do not warn if we can't find the reloc root when looking up backref
Josef Bacik <josef@toxicpanda.com>
btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Reserve TPM for seal and unseal operations
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix migratable=1 failing
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix incorrect handling of tpm_get_random()
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Clean up locality release
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Fix check_locality for correct locality acquisition
Gao Xiang <hsiangkao@redhat.com>
erofs: initialized fields can only be observed after bit is set
Amir Goldstein <amir73il@gmail.com>
selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Takashi Iwai <tiwai@suse.de>
ASoC: siu: Fix build error by a wrong const prefix
Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
drm/rockchip: Require the YTR modifier for AFBC
Heiko Stuebner <heiko@sntech.de>
drm/panel: kd35t133: allow using non-continuous dsi clock
Andrey Grodzovsky <andrey.grodzovsky@amd.com>
drm/sched: Cancel and flush all outstanding jobs before finish.
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/modes: Switch to 64bit maths to avoid integer overflow
Karol Herbst <kherbst@redhat.com>
drm/nouveau/kms: handle mDP connectors
xinhui pan <xinhui.pan@amd.com>
drm/ttm: Fix a memory leak
Prike Liang <Prike.Liang@amd.com>
drm/amdgpu: fix shutdown and poweroff process failed with s0ix
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Marek Olšák <marek.olsak@amd.com>
drm/amdgpu: fix CGTS_TCC_DISABLE register offset on gfx10.3
Felix Kuehling <Felix.Kuehling@amd.com>
drm/amdkfd: Fix recursive lock warnings
Anson Jacob <Anson.Jacob@amd.com>
Revert "drm/amd/display: reuse current context instead of recreating one"
Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Eric Bernstein <eric.bernstein@amd.com>
drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Jan Kokemüller <jan.kokemueller@gmail.com>
drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Alex Deucher <alexander.deucher@amd.com>
Revert "drm/amd/display: Update NV1x SR latency values"
Kai Krakow <kai@kaishome.de>
bcache: Move journal work to new flush wq
Kai Krakow <kai@kaishome.de>
bcache: Give btree_io_wq correct semantics again
Kai Krakow <kai@kaishome.de>
Revert "bcache: Kill btree_io_wq"
Alexander Lobakin <alobakin@pm.me>
MIPS: compressed: fix build with enabled UBSAN
Kevin Hao <haokexin@gmail.com>
Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Nathan Chancellor <nathan@kernel.org>
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
Aurelien Jarno <aurelien@aurel32.net>
MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Paul Cercueil <paul@crapouillou.net>
MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
Takashi Iwai <tiwai@suse.de>
ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
PeiSen Hou <pshou@realtek.com>
ALSA: hda/realtek: modify EAPD in the ALC886
Takashi Iwai <tiwai@suse.de>
ALSA: hda/hdmi: Drop bogus check at closing a stream
Kai Vehmanen <kai.vehmanen@linux.intel.com>
ALSA: hda: Add another CometLake-H PCI ID
Takashi Sakamoto <o-takashi@sakamocchi.jp>
ALSA: fireface: fix to parse sync status register of latter protocol
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Add implicit fb quirk for BOSS GP-10
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Don't avoid stopping the stream at disconnection
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: More strict state change in EP
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Handle invalid running state at releasing EP
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Correct document for snd_usb_endpoint_free_all()
Mathias Kresin <dev@kresin.me>
phy: lantiq: rcu-usb2: wait after clock enable
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7720: fix error code in mos7720_write()
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7840: fix error code in mos7840_write()
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix line-speed handling on newer chips
Johan Hovold <johan@kernel.org>
USB: serial: ftdi_sio: fix FTX sub-integer prescaler
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
Paul Cercueil <paul@crapouillou.net>
usb: musb: Fix runtime PM race in musb_queue_resume_work
Lech Perczak <lech.perczak@gmail.com>
USB: serial: option: update interface mapping for ZTE P685M
James Reynolds <jr@memlen.com>
media: mceusb: Fix potential out-of-bounds shift
Marcos Paulo de Souza <mpdesouza@suse.com>
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Dan Carpenter <dan.carpenter@oracle.com>
Input: joydev - prevent potential read overflow in ioctl
Olivier Crête <olivier.crete@ocrete.ca>
Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
jeffrey.lin <jeffrey.lin@rad-ic.com>
Input: raydium_ts_i2c - do not send zero length
Jason Gerecke <killertofu@gmail.com>
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Filipe Laíns <lains@riseup.net>
HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
Qinglang Miao <miaoqinglang@huawei.com>
ACPI: configfs: add missing check after configfs_register_default_group()
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: property: Fix fwnode string properties matching
Marcin Ślusarz <marcin.slusarz@intel.com>
soundwire: intel: fix possible crash when no device is detected
Mikulas Patocka <mpatocka@redhat.com>
blk-settings: align max_sectors on "logical_block_size" boundary
Bart Van Assche <bvanassche@acm.org>
scsi: sd: Fix Opal support
Finn Thain <fthain@telegraphics.com.au>
ide/falconide: Fix module unload
Ming Lei <ming.lei@redhat.com>
block: fix logging on capacity change
Christoph Hellwig <hch@lst.de>
block: reopen the device in blkdev_reread_part
Johannes Thumshirn <johannes.thumshirn@wdc.com>
scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
Randy Dunlap <rdunlap@infradead.org>
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Zhenzhong Duan <zhenzhong.duan@gmail.com>
csky: Fix a size determination in gpr_get()
Josef Bacik <josef@toxicpanda.com>
proc: use kvzalloc for our kernel buffer
Miaohe Lin <linmiaohe@huawei.com>
mm/rmap: fix potential pte_unmap on an not mapped pte
Dan Williams <dan.j.williams@intel.com>
mm: fix memory_failure() handling of dax-namespace metadata
Rik van Riel <riel@surriel.com>
mm,thp,shmem: make khugepaged obey tmpfs mount flags
Mårten Lindahl <martenli@axis.com>
i2c: exynos5: Preserve high speed master code
Maxime Ripard <maxime@cerno.tech>
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Marc Zyngier <maz@kernel.org>
arm64: Add missing ISB after invalidating TLB in __primary_switch
YueHaibing <yuehaibing@huawei.com>
cifs: Fix inconsistent IS_ERR and PTR_ERR
Sean Christopherson <seanjc@google.com>
KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
Sean Christopherson <seanjc@google.com>
KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4: Fixes for nfs4_bitmask_adjust()
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix jumbo packet handling on RTL8168e
Christian Melki <christian.melki@t2data.com>
net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ8081
Wonhyuk Yang <vvghjk1234@gmail.com>
mm/compaction: fix misbehaviors of fast_find_migrateblock()
Chen Wandun <chenwandun@huawei.com>
mm/hugetlb: suppress wrong warning info when alloc gigantic page
Miaohe Lin <linmiaohe@huawei.com>
mm/hugetlb: fix potential double free in hugetlb_register_node() error path
Miaohe Lin <linmiaohe@huawei.com>
mm/memory.c: fix potential pte_unmap_unlock pte error
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix slub memory accounting
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
Dan Carpenter <dan.carpenter@oracle.com>
ocfs2: fix a use after free on error
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: kconfig: use arm chacha even with no neon
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: device: do not generate ICMP for non-IP packets
Taehee Yoo <ap420073@gmail.com>
vxlan: move debug check after netdev unregister
Chen-Yu Tsai <wens@csie.org>
PCI: rockchip: Make 'ep-gpios' DT property optional
Chuhong Yuan <hslester96@gmail.com>
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Song, Yoong Siang <yoong.siang.song@intel.com>
net: stmmac: fix CBS idleslope and sendslope calculation
Camelia Groza <camelia.groza@nxp.com>
dpaa_eth: fix the access method for the dpaa_napi_portal
Henry Tieman <henry.w.tieman@intel.com>
ice: update the number of available RSS queues
Dave Ertman <david.m.ertman@intel.com>
ice: Fix state bits on LLDP mode switch
Brett Creeley <brett.creeley@intel.com>
ice: Account for port VLAN in VF max packet size calculation
Dave Ertman <david.m.ertman@intel.com>
ice: report correct max number of TCs
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
pwm: iqs620a: Fix overflow and optimize calculations
Dan Carpenter <dan.carpenter@oracle.com>
octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
Norbert Ciosek <norbertx.ciosek@intel.com>
i40e: Fix endianness conversions
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix add TC filter for IPv6
Andreas Oetken <andreas.oetken@siemens.com>
nios2: fixed broken sys_clone syscall
Jann Horn <jannh@google.com>
Take mmap lock in cacheflush syscall
Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
i40e: Fix VFs not created
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix addition of RX filters after enabling FW LLDP agent
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix overwriting flow control settings during driver loading
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Add zero-initialization of AQ command structures
Slawomir Laba <slawomirx.laba@intel.com>
i40e: Fix flow for IPv6 next header (extension header)
Krzysztof Wilczyński <kw@linux.com>
PCI: cadence: Fix DMA range mapping early return error
Russell King <rmk+kernel@armlinux.org.uk>
PCI: pci-bridge-emul: Fix array overruns, improve safety
Shiyang Ruan <ruansy.fnst@cn.fujitsu.com>
device-dax: Fix default return code of range_parse()
Magnum Shan <magnum.shan@unisoc.com>
mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Geert Uytterhoeven <geert@linux-m68k.org>
ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Bard Liao <yung-chuan.liao@linux.intel.com>
regmap: sdw: use _no_pm functions in regmap_read/write
Loic Poulain <loic.poulain@linaro.org>
mhi: Fix double dma free
Tzung-Bi Shih <tzungbi@google.com>
remoteproc/mediatek: acknowledge watchdog IRQ after handled
Jonathan Marek <jonathan@marek.ca>
misc: fastrpc: fix incorrect usage of dma_map_sgtable
Stephen Boyd <swboyd@chromium.org>
drm/msm/dp: Add a missing semi-colon
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: fix confusion on device used by pm_runtime
Bard Liao <yung-chuan.liao@linux.intel.com>
soundwire: export sdw_write/read_no_pm functions
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_update_no_pm when initializing a device
Rob Clark <robdclark@chromium.org>
drm/msm: Fix legacy relocs path
Ahmad Fatoum <a.fatoum@pengutronix.de>
nvmem: core: skip child nodes not matching binding
Dan Carpenter <dan.carpenter@oracle.com>
nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Skip accessing TRCPDCR in save/restore
Geert Uytterhoeven <geert+renesas@glider.be>
phy: USB_LGM_PHY should depend on X86
Theodore Ts'o <tytso@mit.edu>
ext4: fix potential htree index checksum corruption
Max Gurtovoy <mgurtovoy@nvidia.com>
vfio-pci/zdev: fix possible segmentation fault issue
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Fix some sanity checks in detach group
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Populate full dirty when detach non-pinned group
Judy Hsiao <judyhsiao@google.com>
drm/msm/dp: trigger unplug event in msm_dp_display_disable
Stephen Boyd <swboyd@chromium.org>
drm/msm/kms: Make a lock_class_key for each crtc mutex
Eric Anholt <eric@anholt.net>
drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Anholt <eric@anholt.net>
drm/msm: Fix race of GPU init vs timestamp power management.
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm/mdp5: Fix wait-for-commit for cmd panels
Konrad Dybcio <konrad.dybcio@somainline.org>
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
drm/msm: Add proper checks for GPU LLCC support
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm: Fix MSM_INFO_GET_IOVA with carveout
Alexander Usyskin <alexander.usyskin@intel.com>
mei: hbm: call mei_set_devstate() on hbm stop response
Heiner Kallweit <hkallweit1@gmail.com>
PCI: Align checking of syscall user config accessors
Jorgen Hansen <jhansen@vmware.com>
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Pan Bian <bianpan2016@163.com>
PCI: xilinx-cpm: Fix reference count leak on error path
Simon South <simon@simonsouth.net>
pwm: rockchip: Eliminate potential race condition when probing
Simon South <simon@simonsouth.net>
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
Simon South <simon@simonsouth.net>
pwm: rockchip: Enable APB clock during register access while probing
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: cadence: fix ACK/NAK handling
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
soundwire: debugfs: use controller id instead of link_id
Marek Vasut <marek.vasut+renesas@gmail.com>
PCI: rcar: Always allocate MSI addresses in 32bit space
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Add module alias to avoid breaking support for non device tree users
Dan Carpenter <dan.carpenter@oracle.com>
phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
Chris Ruehl <chris.ruehl@gtsys.com.hk>
phy: rockchip-emmc: emmc_phy_init() always return 0
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Fix module alias to enable module autoprobe
Geert Uytterhoeven <geert+renesas@glider.be>
Input: st1232 - fix NORMAL vs. IDLE state handling
Randy Dunlap <rdunlap@infradead.org>
ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
Michael Tretter <m.tretter@pengutronix.de>
Input: st1232 - add IDLE state as ready condition
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: zinitix - fix return type of zinitix_init_touch()
Randy Dunlap <rdunlap@infradead.org>
sparc: fix led.c driver when PROC_FS is not enabled
Randy Dunlap <rdunlap@infradead.org>
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
Dan Carpenter <dan.carpenter@oracle.com>
Input: elo - fix an error code in elo_connect()
Namhyung Kim <namhyung@kernel.org>
perf test: Fix unaligned access in sample parsing test
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix IPC with CYC threshold
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix premature IPC
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix missing CYC processing in PSB
Dave Rigby <d.rigby@me.com>
perf unwind: Set userdata for all __report_module() paths
Yang Jihong <yangjihong1@huawei.com>
perf record: Fix continue profiling after draining the buffer
Dan Carpenter <dan.carpenter@oracle.com>
Input: sur40 - fix an error code in sur40_probe()
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv-sysfs: fix missing put_device
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv: fix memory leak by missing kobject free
Md Haris Iqbal <haris.iqbal@cloud.ionos.com>
RDMA/rtrs: Only allow addition of path to an already established session
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix stack-out-of-bounds
Avihai Horon <avihaih@nvidia.com>
RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Fixes missing error code of CMDQ
Jeff Layton <jlayton@kernel.org>
ceph: fix flush_snap logic after putting caps
Chuck Lever <chuck.lever@oracle.com>
svcrdma: Hold private mutex while invoking rdma_accept()
J. Bruce Fields <bfields@redhat.com>
nfsd: register pernet ops last, unregister first
Nicholas Fraser <nfraser@codeweavers.com>
perf symbols: Fix return value when loading PE DSO
John Ogness <john.ogness@linutronix.de>
printk: avoid prb_first_valid_seq() where possible
Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
spi: Skip zero-length transfers in spi_transfer_one_message()
Kees Cook <keescook@chromium.org>
spi: dw: Avoid stack content exposure
Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
regulator: bd718x7, bd71828, Fix dvs voltage levels
Dmitry Safonov <0x7f454c46@gmail.com>
perf symbols: Use (long) for iterator for bfd symbols
Tom Zanussi <zanussi@kernel.org>
selftests/ftrace: Update synthetic event syntax errors
Ryan Chen <ryan_chen@aspeedtech.com>
clk: aspeed: Fix APLL calculate formula from ast2600-A2
Jonathan Marek <jonathan@marek.ca>
regulator: qcom-rpmh: fix pm8009 ldo7
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/kuap: Restore AMR after replaying soft interrupts
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/uaccess: Avoid might_fault() when user access is enabled
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
spi: pxa2xx: Fix the controller numbering for Wildcat Point
Michael Tretter <m.tretter@pengutronix.de>
clk: divider: fix initialization with parent_hw
Lijun Ou <oulijun@huawei.com>
RDMA/hns: Disable RQ inline by default
Xi Wang <wangxi11@huawei.com>
RDMA/hns: Add mapped page count checking for MTR
Weihang Li <liweihang@huawei.com>
RDMA/hns: Fix type of sq_signal_bits
Weihang Li <liweihang@huawei.com>
RDMA/hns: Avoid filling sgid index when modifying QP to RTR
Kamal Heib <kamalheib1@gmail.com>
RDMA/siw: Fix calculation of tx_valid_cpus size
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Remove the reserved WQE of SRQ
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Fixed wrong judgments in the goto branch
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Force srq_limit to 0 when creating SRQ
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Bugfix for checking whether the srq is full when post wr
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Allocate one more recv SGE for HIP08
John Stultz <john.stultz@linaro.org>
kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
Daniel Latypov <dlatypov@google.com>
kunit: tool: fix unit test cleanup handling
AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Taniya Das <tdas@codeaurora.org>
clk: qcom: gcc-sc7180: Mark the MM XO clocks to be always ON
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
clk: qcom: gfm-mux: fix clk mask
Sandipan Das <sandipan@linux.ibm.com>
powerpc/sstep: Fix darn emulation
Sandipan Das <sandipan@linux.ibm.com>
powerpc/sstep: Fix load-store and update emulation
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/8xx: Fix software emulation interrupt
Nathan Lynch <nathanl@linux.ibm.com>
powerpc/pseries/dlpar: handle ibm, configure-connector delay status
Dan Carpenter <dan.carpenter@oracle.com>
mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
Arnd Bergmann <arnd@arndb.de>
mfd: altera-sysmgr: Fix physical address storing more
Alain Volmat <alain.volmat@foss.st.com>
spi: stm32: properly handle 0 byte transfer
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Correct skb on loopback path
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_recv.c
John Garry <john.garry@huawei.com>
perf vendor events arm64: Fix Ampere eMag event typo
Arnaldo Carvalho de Melo <acme@redhat.com>
perf tools: Fix DSO filtering when not finding a map for a sampled address
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt_crashlog: Add dependency on MFD_INTEL_PMT
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt_telemetry: Add dependency on MFD_INTEL_PMT
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt: Make INTEL_PMT_CLASS non-user-selectable
David Gow <davidgow@google.com>
rtc: zynqmp: depend on HAS_IOMEM
Steven Rostedt (VMware) <rostedt@goodmis.org>
tracepoint: Do not fail unregistering a probe due to memory failure
Parav Pandit <parav@nvidia.com>
IB/cm: Avoid a loop when device has 255 ports
Parav Pandit <parav@nvidia.com>
IB/mlx5: Return appropriate error code instead of ENOMEM
Douglas Anderson <dianders@chromium.org>
iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Yong Wu <yong.wu@mediatek.com>
iommu: Move iotlb_sync_map out from __iommu_map
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
amba: Fix resource leak for drivers without .remove
David Gow <davidgow@google.com>
i3c/master/mipi-i3c-hci: Specify HAS_IOMEM dependency
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: i2c-qcom-geni: Add shutdown callback for i2c
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Vladimir Murzin <vladimir.murzin@arm.com>
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Takeshi Saito <takeshi.saito.xv@renesas.com>
mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to 128-bytes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: sdhci-sprd: Fix some resource leaks in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: owl-mmc: Fix a resource leak in an error handling path and in the remove function
Michal Suchanek <msuchanek@suse.de>
powerpc: Fix build error in paravirt.h
Pingfan Liu <kernelfans@gmail.com>
powerpc/time: Enable sched clock for irqtime
Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
powerpc/sstep: Fix incorrect return from analyze_instr()
Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
powerpc/sstep: Check instruction validity against ISA version before emulation
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/47x: Disable 256k page size
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/kvm: Force selection of CONFIG_PPC_FPU
Cédric Le Goater <clg@kaod.org>
KVM: PPC: Make the VMX instruction emulation routines static
Shay Drory <shayd@nvidia.com>
IB/umad: Return EPOLLERR in case of when device disassociated
Shay Drory <shayd@nvidia.com>
IB/umad: Return EIO in case of when device disassociated
Mark Bloch <mbloch@nvidia.com>
RDMA/mlx5: Allow creating all QPs even when non RDMA profile is used
Maor Gottlieb <maorg@nvidia.com>
tools/testing/scatterlist: Fix overflow of max segment size
Yong Wu <yong.wu@mediatek.com>
iommu: Switch gather->end to the inclusive end
Dan Carpenter <dan.carpenter@oracle.com>
scsi: lpfc: Fix ancient double free
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix ".cold" section suffix check for newer versions of GCC
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix retpoline detection in asm code
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix error handling for STD/CLD warnings
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: Fix duplicate CHARLCD config symbol
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: ht16k33: Fix refresh rate handling
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
Pan Bian <bianpan2016@163.com>
isofs: release buffer head before return
Hans de Goede <hdegoede@redhat.com>
regulator: core: Avoid debugfs: Directory ... already present! error
Dmitry Osipenko <digetx@gmail.com>
power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Samuel Holland <samuel@sholland.org>
power: supply: axp20x_usb_power: Init work before enabling IRQs
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: isci: Pass gfp_t flags in isci_port_bc_change_received()
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: isci: Pass gfp_t flags in isci_port_link_up()
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: isci: Pass gfp_t flags in isci_port_link_down()
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: mvsas: Pass gfp_t flags to libsas event notifiers
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: Introduce a _gfp() variant of event notifiers
John Garry <john.garry@huawei.com>
scsi: libsas: Remove notifier indirection
Krzysztof Kozlowski <krzk@kernel.org>
regulator: s5m8767: Drop regulators OF node reference
Pan Bian <bianpan2016@163.com>
spi: atmel: Put allocated master before return
Pan Bian <bianpan2016@163.com>
regulator: s5m8767: Fix reference count leak
David Howells <dhowells@redhat.com>
certs: Fix blacklist flag type confusion
Gabriel Krisman Bertazi <krisman@collabora.com>
watch_queue: Drop references to /dev/watch_queue
Pan Bian <bianpan2016@163.com>
regulator: axp20x: Fix reference cout leak
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix clock divider range on some clocks
Parav Pandit <parav@nvidia.com>
IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
Yishai Hadas <yishaih@nvidia.com>
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Guido Günther <agx@sigxcpu.org>
spi: imx: Don't print error on -EPROBEDEFER
Frank van der Linden <fllinden@amazon.com>
module: harden ELF info handling
Tom Rix <trix@redhat.com>
clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
Arnd Bergmann <arnd@arndb.de>
clocksource/drivers/ixp4xx: Select TIMER_OF when needed
Randy Dunlap <rdunlap@infradead.org>
power: supply: fix sbs-charger build, needs REGMAP_I2C
Dave Jiang <dave.jiang@intel.com>
dmaengine: idxd: set DMA channel to be private
Bartosz Golaszewski <bgolaszewski@baylibre.com>
rtc: s5m: select REGMAP_I2C
Claudiu Beznea <claudiu.beznea@microchip.com>
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Fix KASAN: stack-out-of-bounds bug
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Init wr_cnt as 1
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix missing wr_cqe
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs: Call kobject_put in the failure path
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-srv: Jump to dereg_mr label if allocate iu fails
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-clt: Set mininum limit when create QP
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Release lock before call into close_sess
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Extend ibtrs_cq_qp_create
Nicolas Boichat <drinkcat@chromium.org>
of/fdt: Make sure no-map does not remove already reserved regions
KarimAllah Ahmed <karahmed@amazon.de>
fdt: Properly handle "no-map" field in the memory region
Colin Ian King <colin.king@canonical.com>
power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Can Guo <cang@codeaurora.org>
scsi: ufs: Fix a possible NULL pointer issue
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-battery: Fix missing power_supply_put()
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-charger: Fix missing power_supply_put()
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
mfd: bd9571mwv: Use devm_mfd_add_devices()
Ferry Toth <ftoth@exalondelft.nl>
dmaengine: hsu: disable spurious interrupt
Vignesh Raghavendra <vigneshr@ti.com>
dmaengine: ti: k3-udma: Set rflow count for BCDMA split channels
Nathan Chancellor <nathan@kernel.org>
dmaengine: qcom: Always inline gpi_update_reg
Arnd Bergmann <arnd@arndb.de>
rtc: rx6110: fix build against modular I2C
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: owl-dma: Fix a resource leak in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in the remove function
Bernard Metzler <bmt@zurich.ibm.com>
RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Randy Dunlap <rdunlap@infradead.org>
HID: core: detect and skip invalid inputs to snto32()
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Fix parent of CBFUSA clock
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Remove non-existent S2 clock
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix CEC clock
Pratyush Yadav <p.yadav@ti.com>
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle master read request
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle only slave interrupts which are enabled
Jan Kara <jack@suse.cz>
quota: Fix memory leak when handling corrupted quota file
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
Po-Hsu Lin <po-hsu.lin@canonical.com>
selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: make "ret" a signed integer
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
Tony Lindgren <tony@atomide.com>
power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
Zhang Qilong <zhangqilong3@huawei.com>
HSI: Fix PM usage counter unbalance in ssi_hw_init
Eric W. Biederman <ebiederm@xmission.com>
capabilities: Don't allow writing ambiguous v3 file capabilities
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: imx_keypad - add dependency on HAS_IOMEM
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: da7280 - protect OF match table with CONFIG_OF
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: da7280 - fix missing error test
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
smp: Process pending softirqs in flush_smp_call_function_from_idle()
Geert Uytterhoeven <geert+renesas@glider.be>
irqchip/imx: IMX_INTMUX should not default to y, unconditionally
Wang ShaoBo <bobo.shaobowang@huawei.com>
ubifs: Fix error return code in alloc_wbufs()
Arnd Bergmann <arnd@arndb.de>
ubifs: replay: Fix high stack usage, again
Dinghao Liu <dinghao.liu@zju.edu.cn>
ubifs: Fix memleak in ubifs_init_authentication
Tom Rix <trix@redhat.com>
jffs2: fix use after free in jffs2_sum_write_data()
Colin Ian King <colin.king@canonical.com>
fs/jfs: fix potential integer overflow on shift of a int
Sameer Pujar <spujar@nvidia.com>
ASoC: simple-card-utils: Fix device module clock
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer after kexec syscall
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer on error
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: set status to 0 in case for invalid nsid
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: remove extra variable in identify ns
Keith Busch <kbusch@kernel.org>
nvme-multipath: set nr_zones for zoned namespaces
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix potential race of tcp socket closing accept_work
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
Hao Xu <haoxu@linux.alibaba.com>
io_uring: fix possible deadlock in io_uring_poll
Daniele Alessandrelli <daniele.alessandrelli@intel.com>
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Jan Henrik Weinstock <jan.weinstock@rwth-aachen.de>
hwrng: timeriomem - Fix cooldown period calculation
Imre Deak <imre.deak@intel.com>
drm/dp_mst: Don't cache EDIDs for physical ports
Dan Carpenter <dan.carpenter@oracle.com>
drm/virtio: fix an error code in virtio_gpu_init()
Qinglang Miao <miaoqinglang@huawei.com>
drm/lima: fix reference leak in lima_pm_busy
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Restore cec physical address on reconnect
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix up CEC registers
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix register offset with longer CEC messages
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Move hdmi reset to bind
Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: return EIO when msg retry limit reached
Sean Christopherson <seanjc@google.com>
KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
Jinyang He <hejinyang@loongson.cn>
MIPS: relocatable: Provide kaslr_offset() to get the kernel offset
Qu Wenruo <wqu@suse.com>
btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Zhihao Cheng <chengzhihao1@huawei.com>
btrfs: clarify error returns values in __load_free_space_cache
Hui Wang <hui.wang@canonical.com>
ASoC: SOF: debug: Fix a potential issue on string buffer termination
Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>
ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Jun Nie <jun.nie@linaro.org>
ASoC: qcom: lpass: Fix i2s ctl register bit map
Peter Zijlstra <peterz@infradead.org>
locking/lockdep: Avoid unmatched unlock
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A32
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
Sasha Levin <sashal@kernel.org>
drm/mediatek: Fix aal size config
Yongqiang Niu <yongqiang.niu@mediatek.com>
drm/mediatek: Check if fb is null
Sean Christopherson <seanjc@google.com>
KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Dehe Gu <gudehe@huawei.com>
f2fs: fix a wrong condition in __submit_bio
Dan Carpenter <dan.carpenter@oracle.com>
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
Yi Chen <chenyi77@huawei.com>
f2fs: fix to avoid inconsistent quota data
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mtd: rawnand: intel: Fix an error handling path in 'ebu_dma_start()'
Manivannan Sadhasivam <mani@kernel.org>
mtd: parsers: afs: Fix freeing the part name memory in failure
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
ASoC: codecs: add missing max_register in regmap config
Sebastian Reichel <sre@kernel.org>
ASoC: cpcap: fix microphone timeslot mask
Florian Fainelli <f.fainelli@gmail.com>
ata: ahci_brcm: Add back regulators management
Will Deacon <will@kernel.org>
mm: proc: Invalidate TLB after clearing soft-dirty page state
Biwen Li <biwen.li@nxp.com>
irqchip/ls-extirq: add IRQCHIP_SKIP_SET_WAKE to the irqchip flags
Frantisek Hrbata <frantisek@hrbata.com>
drm/nouveau: bail out of nouveau_channel_new if channel init fails
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Fix ctr(aes) on SEC1
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
Dan Carpenter <dan.carpenter@oracle.com>
mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Move IRQs when migrating context
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix PMU instance naming
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: lpass-cpu: Remove bit clock state check
Chao Yu <chao@kernel.org>
f2fs: compress: fix potential deadlock
Daeho Jeong <daehojeong@google.com>
f2fs: fix null page reference in redirty_blocks
Qais Yousef <qais.yousef@arm.com>
sched/eas: Don't update misfit status if the task is pinned
Judy Hsiao <judyhsiao@google.com>
ASoC: max98373: Fixes a typo in max98373_feedback_get
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
media: i2c/Kconfig: Select FWNODE for OV772x sensor
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
Tom Rix <trix@redhat.com>
media: pxa_camera: declare variable when DEBUG is defined
yangerkun <yangerkun@huawei.com>
mtd: phram: use div_u64_rem to stop overwrite len in phram_setup
Tom Rix <trix@redhat.com>
media: mtk-vcodec: fix argument used when DEBUG is defined
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: cx25821: Fix a bug when reallocating some dma memory
Luo Meng <luomeng12@huawei.com>
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Dan Carpenter <dan.carpenter@oracle.com>
media: atomisp: Fix a buffer overflow in debug code
Daniel W. S. Almeida <dwlsalmeida@gmail.com>
media: vidtv: psi: fix missing crc for PMT
Joe Perches <joe@perches.com>
media: lmedm04: Fix misuse of comma
Daniel Scally <djrscally@gmail.com>
media: software_node: Fix refcounts in software_node_get_next_child()
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
Finn Thain <fthain@telegraphics.com.au>
macintosh/adb-iop: Use big-endian autopoll mask
Pan Bian <bianpan2016@163.com>
bsg: free the request before return error code
Guchun Chen <guchun.chen@amd.com>
drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
Qinglang Miao <miaoqinglang@huawei.com>
drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
Nathan Chancellor <nathan@kernel.org>
MIPS: Compare __SYNC_loongson3_war against 0
Alexander Lobakin <alobakin@pm.me>
MIPS: properly stop .eh_frame generation
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: ti-vpe: cal: fix write to unallocated memory
Rui Miguel Silva <rmfrfs@gmail.com>
media: imx7: csi: Fix pad link validation
Fabio Estevam <festevam@gmail.com>
media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Giulio Benetti <giulio.benetti@micronovasrl.com>
drm/sun4i: tcon: fix inverted DCLK polarity
Xuewen Yan <xuewen.yan@unisoc.com>
sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Jiri Olsa <jolsa@kernel.org>
crypto: bcm - Rename struct device_private to bcm_device_private
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - replace CRYPTO_AES with CRYPTO_LIB_AES in Kconfig
Dinghao Liu <dinghao.liu@zju.edu.cn>
evm: Fix memleak in init_desc
Stephan Gerhold <stephan@gerhold.net>
ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Dan Carpenter <dan.carpenter@oracle.com>
ASoC: cs42l56: fix up error handling in probe
Zhang Changzhong <zhangchangzhong@huawei.com>
media: aspeed: fix error return code in aspeed_video_setup_video()
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: tm6000: Fix memleak in tm6000_start_stream
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: media/pci: Fix memleak in empress_init
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: em28xx: Fix use-after-free in em28xx_alloc_urbs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: vsp1: Fix an error handling path in the probe function
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: missing error code in msm_video_register()
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: Fix signedness bug in video_enum_fmt()
Zhang Changzhong <zhangchangzhong@huawei.com>
media: mtk-vcodec: fix error return code in vdec_vp9_decode()
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Fix csc/scaler unregister
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Unregister csc/scaler only if registered
Jacopo Mondi <jacopo@jmondi.org>
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
media: ipu3-cio2: Build only for x86
Simon Ser <contact@emersion.fr>
drm/fourcc: fix Amlogic format modifier masks
Chia-I Wu <olvaffe@gmail.com>
drm/virtio: make sure context is created in gem open
Nathan Chancellor <nathan@kernel.org>
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Chancellor <nathan@kernel.org>
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
Chenyang Li <lichenyang@loongson.cn>
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Wang Xiaojun <wangxiaojun11@huawei.com>
drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
Qinglang Miao <miaoqinglang@huawei.com>
drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
Marco Elver <elver@google.com>
kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Arnd Bergmann <arnd@arndb.de>
ASoC: fsl_aud2htx: select SND_SOC_IMX_PCM_DMA
Dan Carpenter <dan.carpenter@oracle.com>
media: allegro: Fix use after free on error
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hwrng: ingenic - Fix a resource leak in an error handling path
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - fix kmap usage
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - linearize buffers content must be kept
Linus Walleij <linus.walleij@linaro.org>
drm/panel: s6e63m0: Support max-brightness
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
Guido Günther <agx@sigxcpu.org>
drm/panel: mantix: Tweak init sequence
Linus Walleij <linus.walleij@linaro.org>
drm/panel: s6e63m0: Fix init sequence again
Chuhong Yuan <hslester96@gmail.com>
drm/fb-helper: Add missed unlocks in setcmap_legacy()
Dan Carpenter <dan.carpenter@oracle.com>
gma500: clean up error handling in init
Simon Ser <contact@emersion.fr>
drm: document that user-space should force-probe connectors
Jialin Zhang <zhangjialin11@huawei.com>
drm/gma500: Fix error return code in psb_driver_load()
Randy Dunlap <rdunlap@infradead.org>
fbdev: aty: SPARC64 requires FB_ATY_CT
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: coma mode disabled for VSC8514
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: improved serdes calibration applied to VSC8514
Alex Elder <elder@linaro.org>
net: ipa: initialize all resources
Dany Madden <drt@linux.ibm.com>
ibmvnic: change IBMVNIC_MAX_IND_DESCS to 16
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Fix CQ params of ICOSQ and async ICOSQ
Raed Salem <raeds@nvidia.com>
net/mlx5e: Enable striding RQ for Connect-X IPsec capable devices
Parav Pandit <parav@nvidia.com>
net/mlx5e: E-switch, Fix rate calculation for overflow
Joel Stanley <joel@jms.id.au>
soc: aspeed: socinfo: Add new systems
Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Bluetooth: hci_qca: Fixed issue during suspend
Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Bluetooth: hci_qca: check for SSR triggered flag while suspend
Matthias Brugger <mbrugger@suse.com>
arm64: dts: mt8183: Fix GCE include path
Peter Geis <pgwipeout@gmail.com>
ARM: tegra: ouya: Fix eMMC on specific bootloaders
Pali Rohár <pali@kernel.org>
net: sfp: add workaround for Realtek RTL8672 and RTL9601C chips
Enric Balletbo i Serra <enric.balletbo@collabora.com>
arm64: dts: mt8183: Add missing power-domain for pwm0 node
Yongqiang Niu <yongqiang.niu@mediatek.com>
arm64: dts: mt8183: refine gamma compatible name
Yongqiang Niu <yongqiang.niu@mediatek.com>
arm64: dts: mt8183: rename rdma fifo size
Andrii Nakryiko <andrii@kernel.org>
selftests/bpf: Don't exit on failed bpf_testmod unload
Sami Tolvanen <samitolvanen@google.com>
x86/sgx: Fix the return type of sgx_init()
Linus Torvalds <torvalds@linux-foundation.org>
tty: implement read_iter
Linus Torvalds <torvalds@linux-foundation.org>
tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix uSD pins drive strength
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: sm8250: correct sdhc_2 xo clk
Andrii Nakryiko <andrii@kernel.org>
selftests/bpf: Sync RCU before unloading bpf_testmod
Andrii Nakryiko <andrii@kernel.org>
bpf: Declare __bpf_free_used_maps() unconditionally
Erwan Le Ray <erwan.leray@foss.st.com>
serial: stm32: fix DMA initialization error handling
Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Bluetooth: hci_qca: Wait for SSR completion during suspend
Rafał Miłecki <rafal@milecki.pl>
arm64: dts: broadcom: bcm4908: use proper NAND binding
Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Bluetooth: Remove hci_req_le_suspend_config
Vladimir Oltean <vladimir.oltean@nxp.com>
net: enetc: fix destroyed phylink dereference during unbind
Maxime Chevallier <maxime.chevallier@bootlin.com>
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset link when the link never comes back
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: adding LCPLL reset to VSC8514
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: don't deinitialize unused ports
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: perform teardown in reverse order of setup
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: serialize access to work queue on remove
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: skip send_request_unmap for timeout reset
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: add memory barrier to protect long term buffer
Ilya Leoshkevich <iii@linux.ibm.com>
bpf: Clear subreg_def for global function return values
Colin Ian King <colin.king@canonical.com>
b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
Ayush Sawal <ayush.sawal@chelsio.com>
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Robert Hancock <robert.hancock@calian.com>
net: axienet: Handle deferred probe on clock properly
Eric Dumazet <edumazet@google.com>
tcp: fix SO_RCVLOWAT related hangs under mem pressure
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: fix ACKRX debug message
Jesper Dangaard Brouer <brouer@redhat.com>
bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Jun'ichi Nomura <junichi.nomura@nec.com>
bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Yonghong Song <yhs@fb.com>
bpf: Fix an unitialized value in bpf_iter
Martin KaFai Lau <kafai@fb.com>
libbpf: Ignore non function pointer member in struct_ops
Colin Ian King <colin.king@canonical.com>
mac80211: fix potential overflow when multiplying to u32 integers
Moshe Shemesh <moshe@nvidia.com>
net/mlx5e: Check tunnel offload is required before setting SWP
Oz Shlomo <ozsh@nvidia.com>
net/mlx5e: CT: manage the lifetime of the ct entry object
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for lag devices
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on lag device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on multi port slave device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for multi port slave device
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Replace synchronize_rcu with synchronize_net
Shay Drory <shayd@nvidia.com>
net/mlx5: Fix health error state handling
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Change interrupt moderation channel params also when channels are closed
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Don't change interrupt moderation params when DIM is enabled
Raed Salem <raeds@nvidia.com>
net/mlx5e: Enable XDP for Connect-X IPsec capable devices
Heiner Kallweit <hkallweit1@gmail.com>
net: phy: consider that suspend2ram may cut off PHY power
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: fix memory leak in XDP_REDIRECT
Juergen Gross <jgross@suse.com>
xen/netback: fix spurious event detection for common event case
Vasundhara Volam <vasundhara-v.volam@broadcom.com>
bnxt_en: Fix devlink info's stored fw.psid version format.
Edwin Peer <edwin.peer@broadcom.com>
bnxt_en: reverse order of TX disable and carrier off
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: Set to CLOSED state even on error
Björn Töpel <bjorn@kernel.org>
selftests/bpf: Convert test_xdp_redirect.sh to bash
Linus Lüssing <ll@simonwunderlich.de>
ath9k: fix data bus crash when setting nf_override via debugfs
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: set the PNVM again if it was already loaded
Marco Elver <elver@google.com>
bpf_lru_list: Read double-checked variable once without lock
Sara Sharon <sara.sharon@intel.com>
iwlwifi: mvm: don't check if CSA event is running before removing
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: assign SAR table revision to the command later
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: send stored PPAG command instead of local
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: store PPAG enabled/disabled flag properly
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: fix the type we use in the PPAG table validity checks
Jae Hyun Yoo <jae.hyun.yoo@intel.com>
soc: aspeed: snoop: Add clock control logic
Dan Carpenter <dan.carpenter@oracle.com>
ath11k: fix a locking bug in ath11k_mac_op_start()
Anand K Mistry <amistry@google.com>
ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Anand K Mistry <amistry@google.com>
ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
Arnd Bergmann <arnd@arndb.de>
ARM: at91: use proper asm syntax in pm_suspend
Jérôme Pouiller <jerome.pouiller@silabs.com>
staging: wfx: fix possible panic with re-queued frames
Arnd Bergmann <arnd@arndb.de>
optee: simplify i2c access
Arnd Bergmann <arnd@arndb.de>
ARM: s3c: fix fiq for clang IAS
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: set enabled in the PPAG command properly
Artem Lapkin <email2tema@gmail.com>
arm64: dts: meson: fix broken wifi node for Khadas VIM3L
Vincent Knecht <vincent.knecht@mailoo.org>
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Luca Weiss <luca@z3ntu.xyz>
soc: qcom: ocmem: don't return NULL in of_get_ocmem
Jupeng Zhong <zhongjupeng@yulong.com>
Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Dmitry Osipenko <digetx@gmail.com>
opp: Correct debug message in _opp_add_static_v2()
Marek Behún <kabel@kernel.org>
arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to LEDs
Marc Kleine-Budde <mkl@pengutronix.de>
can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Geert Uytterhoeven <geert+renesas@glider.be>
arm64: dts: renesas: beacon: Fix EEPROM compatible value
Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Chen-Yu Tsai <wens@csie.org>
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Make "trimming xfer length" a debug message
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Abort transaction after errors with unknown reason
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Do not update data length if it is 0 on inbound transfers
Tony Lindgren <tony@atomide.com>
ARM: dts: Configure missing thermal interrupt for 4430
Pan Bian <bianpan2016@163.com>
memory: ti-aemif: Drop child node when jumping out loop
Pan Bian <bianpan2016@163.com>
Bluetooth: Put HCI device if inquiry procedure interrupts
Pan Bian <bianpan2016@163.com>
Bluetooth: drop HCI device reference before return
Borislav Petkov <bp@suse.de>
staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
Dan Carpenter <dan.carpenter@oracle.com>
soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
Robert Foss <robert.foss@linaro.org>
arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Jack Pham <jackp@codeaurora.org>
usb: gadget: u_audio: Free requests only after callback
Maximilian Luz <luzmaximilian@gmail.com>
ACPICA: Fix exception code class checks
Chen-Yu Tsai <wens@csie.org>
arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Free resources in error path
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: properly connect USB PHY to port 0
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix call site of scmi_notification_exit
Andrii Nakryiko <andrii@kernel.org>
bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
Andrii Nakryiko <andrii@kernel.org>
bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk transfers on 64-bit builds
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk userdata handling
Dinghao Liu <dinghao.liu@zju.edu.cn>
Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
Zhang Qilong <zhangqilong3@huawei.com>
memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
Christopher William Snowhill <chris@kode54.net>
Bluetooth: Fix initializing response id after clearing struct
Claire Chang <tientzu@chromium.org>
Bluetooth: hci_uart: Fix a race for write_work scheduling
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the probe function
Rakesh Pillai <pillair@codeaurora.org>
ath10k: Fix error handling in case of CE pipe init failure
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: One more flush for Baytrail clear residuals
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Don't call sync_stop if it hasn't been stopped
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Assure sync with the pending stop operation at suspend
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Call sync_stop at disconnection
Eric Biggers <ebiggers@google.com>
random: fix the RNDRESEEDCRNG ioctl
Nathan Chancellor <nathan@kernel.org>
vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
Alexander Lobakin <alobakin@pm.me>
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
Rokudo Yan <wu-yan@tcl.com>
zsmalloc: account the number of compacted pages correctly
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
Jan Kara <jack@suse.cz>
bfq: Avoid false bfq queue merging
Hans de Goede <hdegoede@redhat.com>
virt: vbox: Do not use wait_event_interruptible when called from kernel context
Ard Biesheuvel <ardb@kernel.org>
PCI: Decline to resize resources if boot config must be preserved
Ansuel Smith <ansuelsmth@gmail.com>
PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ivan Zaentsev <ivan.zaentsev@wirenboard.ru>
w1: w1_therm: Fix conversion result for negative temperatures
Sumit Garg <sumit.garg@linaro.org>
kdb: Make memory allocations more robust
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix mailbox Ch erroneous error
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: docs: Remove notify_ha_event()
Dave Jiang <dave.jiang@intel.com>
driver core: auxiliary bus: Fix calling stage for auxiliary bus init
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: do not attempt to create a new file before the filesystem is initalized
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: be more robust at handling improper input in debugfs_lookup()
Stefano Garzarella <sgarzare@redhat.com>
vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Nick Desaulniers <ndesaulniers@google.com>
vmlinux.lds.h: add DWARF v5 sections
-------------
Diffstat:
Documentation/admin-guide/perf/arm-cmn.rst | 2 +-
Documentation/admin-guide/sysctl/vm.rst | 10 +-
Documentation/filesystems/seq_file.rst | 6 +
Documentation/scsi/libsas.rst | 10 +-
Documentation/security/keys/core.rst | 4 +-
Makefile | 4 +-
arch/arm/boot/compressed/head.S | 4 +-
arch/arm/boot/dts/armada-388-helios4.dts | 28 +-
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/arm/boot/dts/tegra30-ouya.dts | 4 +-
arch/arm/kernel/sys_oabi-compat.c | 15 +
arch/arm/mach-at91/pm_suspend.S | 2 +-
arch/arm/mach-ixp4xx/Kconfig | 1 -
arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9 +-
arch/arm64/Kconfig | 2 +-
.../boot/dts/allwinner/sun50i-a64-pinebook.dts | 5 +-
.../boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 -
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 +-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7 +
.../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7 +-
arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi | 2 +-
.../boot/dts/exynos/exynos5433-tm2-common.dtsi | 2 +-
arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +-
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4 +-
.../boot/dts/marvell/armada-3720-turris-mox.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 10 +-
.../dts/qcom/msm8916-samsung-a2015-common.dtsi | 6 +
.../boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2 +-
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 15 +-
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 +-
arch/arm64/boot/dts/qcom/sm8250.dtsi | 2 +-
.../boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +-
.../arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4 +-
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 +
arch/arm64/crypto/aes-glue.c | 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/include/asm/module.lds.h | 6 +-
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/head.S | 1 +
arch/arm64/kernel/machine_kexec_file.c | 4 +-
arch/arm64/kernel/probes/uprobes.c | 2 +-
arch/arm64/kernel/ptrace.c | 2 +-
arch/arm64/kernel/suspend.c | 2 +-
arch/csky/kernel/ptrace.c | 2 +-
arch/mips/Makefile | 19 +
arch/mips/boot/compressed/Makefile | 1 +
arch/mips/cavium-octeon/setup.c | 9 +-
arch/mips/include/asm/asm.h | 18 +
arch/mips/include/asm/atomic.h | 2 +-
arch/mips/include/asm/cmpxchg.h | 6 +-
arch/mips/include/asm/page.h | 6 +
arch/mips/kernel/cpu-probe.c | 15 +-
arch/mips/kernel/relocate.c | 10 +
arch/mips/kernel/setup.c | 3 +
arch/mips/kernel/vmlinux.lds.S | 2 +-
arch/mips/lantiq/irq.c | 2 +-
arch/mips/loongson64/Platform | 22 -
arch/mips/mm/c-r4k.c | 2 +-
arch/mips/vdso/Makefile | 5 +-
arch/nios2/kernel/entry.S | 3 +
arch/nios2/kernel/sys_nios2.c | 11 +-
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/kexec.h | 1 +
arch/powerpc/include/asm/paravirt.h | 1 +
arch/powerpc/include/asm/uaccess.h | 13 +-
arch/powerpc/kernel/entry_32.S | 3 +
arch/powerpc/kernel/head_32.h | 2 +-
arch/powerpc/kernel/head_8xx.S | 2 +-
arch/powerpc/kernel/head_book3s_32.S | 6 -
arch/powerpc/kernel/irq.c | 27 +-
arch/powerpc/kernel/prom_init.c | 12 +-
arch/powerpc/kernel/time.c | 2 +
arch/powerpc/kexec/elf_64.c | 2 +-
arch/powerpc/kexec/file_load_64.c | 35 ++
arch/powerpc/kvm/Kconfig | 1 +
arch/powerpc/kvm/powerpc.c | 8 +-
arch/powerpc/lib/sstep.c | 101 +++-
arch/powerpc/platforms/pseries/dlpar.c | 7 +-
arch/riscv/kernel/vdso/Makefile | 3 +-
arch/s390/kernel/vtime.c | 3 +-
arch/sparc/Kconfig | 2 +-
arch/sparc/kernel/led.c | 2 +
arch/sparc/lib/memset.S | 1 +
arch/um/include/shared/skas/mm_id.h | 1 +
arch/um/kernel/tlb.c | 19 +-
arch/um/os-Linux/skas/process.c | 4 +
arch/x86/crypto/aesni-intel_glue.c | 28 +-
arch/x86/entry/common.c | 2 +-
arch/x86/include/asm/virtext.h | 17 +-
arch/x86/kernel/cpu/sgx/main.c | 14 +-
arch/x86/kernel/msr.c | 7 +
arch/x86/kernel/reboot.c | 30 +-
arch/x86/kvm/emulate.c | 4 +-
arch/x86/kvm/mmu/tdp_mmu.c | 3 +-
arch/x86/kvm/svm/nested.c | 22 +-
arch/x86/kvm/svm/svm.c | 8 +-
arch/x86/kvm/x86.c | 1 +
arch/x86/mm/fault.c | 27 +-
arch/x86/mm/pat/memtype.c | 4 +-
block/bfq-iosched.c | 1 +
block/blk-settings.c | 12 +
block/bsg.c | 4 +-
block/genhd.c | 2 +-
block/ioctl.c | 21 +-
certs/blacklist.c | 2 +-
crypto/ecdh_helper.c | 3 +
crypto/michael_mic.c | 31 +-
drivers/acpi/acpi_configfs.c | 7 +-
drivers/acpi/property.c | 44 +-
drivers/amba/bus.c | 20 +-
drivers/ata/ahci_brcm.c | 14 +-
drivers/auxdisplay/Kconfig | 3 -
drivers/auxdisplay/ht16k33.c | 3 +-
drivers/base/auxiliary.c | 13 +-
drivers/base/base.h | 5 +
drivers/base/init.c | 1 +
drivers/base/regmap/regmap-sdw.c | 4 +-
drivers/base/swnode.c | 8 +-
drivers/block/floppy.c | 30 +-
drivers/block/zram/zram_drv.c | 2 +-
drivers/bluetooth/btqcomsmd.c | 27 +-
drivers/bluetooth/btusb.c | 20 +-
drivers/bluetooth/hci_ldisc.c | 41 +-
drivers/bluetooth/hci_qca.c | 33 +-
drivers/bluetooth/hci_serdev.c | 4 +-
drivers/bus/mhi/core/init.c | 3 +
drivers/char/hw_random/ingenic-trng.c | 6 +-
drivers/char/hw_random/timeriomem-rng.c | 2 +-
drivers/char/random.c | 2 +-
drivers/char/tpm/tpm.h | 4 -
drivers/char/tpm/tpm_tis_core.c | 50 +-
drivers/clk/clk-ast2600.c | 37 +-
drivers/clk/clk-divider.c | 9 +-
drivers/clk/meson/clk-pll.c | 10 +-
drivers/clk/qcom/gcc-msm8998.c | 100 ++--
drivers/clk/qcom/gcc-sc7180.c | 47 +-
drivers/clk/qcom/lpass-gfm-sm8250.c | 8 +-
drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +-
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/mxs_timer.c | 5 +-
drivers/cpufreq/acpi-cpufreq.c | 62 +-
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +-
drivers/cpufreq/freq_table.c | 8 +-
drivers/cpufreq/intel_pstate.c | 21 +-
drivers/cpufreq/qcom-cpufreq-hw.c | 40 +-
.../crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 +++---
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2 +
drivers/crypto/bcm/cipher.c | 2 +-
drivers/crypto/bcm/cipher.h | 4 +-
drivers/crypto/bcm/util.c | 2 +-
drivers/crypto/qat/Kconfig | 2 +-
drivers/crypto/talitos.c | 50 +-
drivers/crypto/talitos.h | 1 +
drivers/dax/bus.c | 2 +-
drivers/dma/fsldma.c | 6 +
drivers/dma/hsu/pci.c | 21 +-
drivers/dma/idxd/dma.c | 1 +
drivers/dma/owl-dma.c | 1 +
drivers/dma/qcom/gpi.c | 2 +-
drivers/dma/ti/k3-udma.c | 1 +
drivers/firmware/arm_scmi/driver.c | 4 +-
drivers/gpio/gpio-pcf857x.c | 2 +-
drivers/gpu/drm/Kconfig | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +-
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 22 +-
drivers/gpu/drm/amd/amdgpu/soc15.c | 2 +
.../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2 +-
.../gpu/drm/amd/display/dc/bios/command_table.c | 61 ++
drivers/gpu/drm/amd/display/dc/core/dc.c | 27 +-
drivers/gpu/drm/amd/display/dc/dc_stream.h | 3 +-
.../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14 +
.../drm/amd/display/dc/dce/dce_stream_encoder.c | 1 +
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8 +-
.../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1 -
.../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +
.../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 +
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +-
drivers/gpu/drm/drm_dp_mst_topology.c | 3 +-
drivers/gpu/drm/drm_fb_helper.c | 15 +-
drivers/gpu/drm/drm_modes.c | 4 +-
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +-
drivers/gpu/drm/gma500/psb_drv.c | 2 +
drivers/gpu/drm/i915/display/intel_hdmi.c | 6 +-
drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12 +-
drivers/gpu/drm/lima/lima_sched.c | 2 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8 +
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 10 +-
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 10 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +-
drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 5 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +-
drivers/gpu/drm/msm/msm_drv.c | 3 +-
drivers/gpu/drm/msm/msm_gem_submit.c | 2 +
drivers/gpu/drm/msm/msm_kms.h | 8 +-
.../drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 +
drivers/gpu/drm/nouveau/nouveau_chan.c | 1 +
drivers/gpu/drm/nouveau/nouveau_connector.c | 1 +
drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3 +-
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5 +
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 59 +-
drivers/gpu/drm/rcar-du/rcar_cmm.c | 2 +-
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 +-
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 +-
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11 +
drivers/gpu/drm/scheduler/sched_main.c | 3 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 +-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/tegra/dc.c | 2 +-
drivers/gpu/drm/tegra/dsi.c | 2 +-
drivers/gpu/drm/tegra/hdmi.c | 2 +-
drivers/gpu/drm/tegra/hub.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 2 +-
drivers/gpu/drm/tegra/vic.c | 2 +-
drivers/gpu/drm/ttm/ttm_bo.c | 9 +-
drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++-
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +-
drivers/gpu/drm/virtio/virtgpu_gem.c | 8 +-
drivers/gpu/drm/virtio/virtgpu_kms.c | 1 +
drivers/hid/hid-core.c | 3 +
drivers/hid/hid-logitech-dj.c | 1 +
drivers/hid/wacom_wac.c | 7 +-
drivers/hsi/controllers/omap_ssi_core.c | 2 +-
drivers/hv/channel_mgmt.c | 3 +-
drivers/hwtracing/coresight/coresight-etm4x-core.c | 21 +-
.../hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +-
drivers/i2c/busses/i2c-bcm-iproc.c | 231 ++++++--
drivers/i2c/busses/i2c-brcmstb.c | 2 +-
drivers/i2c/busses/i2c-exynos5.c | 8 +-
drivers/i2c/busses/i2c-qcom-geni.c | 93 ++-
drivers/i3c/master/Kconfig | 1 +
drivers/ide/falconide.c | 3 +-
drivers/infiniband/core/cm.c | 8 +-
drivers/infiniband/core/cma.c | 70 ++-
drivers/infiniband/core/user_mad.c | 17 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 11 +-
drivers/infiniband/hw/hns/hns_roce_hem.c | 9 +-
drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 16 +
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 70 ++-
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 3 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 19 +-
drivers/infiniband/hw/hns/hns_roce_mr.c | 56 +-
drivers/infiniband/hw/hns/hns_roce_qp.c | 37 +-
drivers/infiniband/hw/hns/hns_roce_srq.c | 52 +-
drivers/infiniband/hw/mlx5/devx.c | 4 +-
drivers/infiniband/hw/mlx5/main.c | 14 +-
drivers/infiniband/hw/mlx5/qp.c | 27 +-
drivers/infiniband/sw/rxe/rxe_net.c | 5 +
drivers/infiniband/sw/rxe/rxe_recv.c | 27 +-
drivers/infiniband/sw/siw/siw.h | 2 +-
drivers/infiniband/sw/siw/siw_main.c | 2 +-
drivers/infiniband/sw/siw/siw_qp.c | 271 +++++----
drivers/infiniband/sw/siw/siw_qp_rx.c | 26 +-
drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +-
drivers/infiniband/sw/siw/siw_verbs.c | 20 +-
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2 +
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51 +-
drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1 +
drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 120 ++--
drivers/infiniband/ulp/rtrs/rtrs.c | 28 +-
drivers/input/joydev.c | 7 +-
drivers/input/joystick/xpad.c | 1 +
drivers/input/keyboard/Kconfig | 2 +-
drivers/input/misc/da7280.c | 3 +
drivers/input/serio/i8042-x86ia64io.h | 4 +
drivers/input/serio/serport.c | 4 +-
drivers/input/touchscreen/elo.c | 4 +-
drivers/input/touchscreen/raydium_i2c_ts.c | 3 +-
drivers/input/touchscreen/st1232.c | 9 +-
drivers/input/touchscreen/sur40.c | 1 +
drivers/input/touchscreen/zinitix.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 +
drivers/iommu/iommu.c | 23 +-
drivers/iommu/mtk_iommu.c | 2 +-
drivers/irqchip/Kconfig | 3 +-
drivers/irqchip/irq-loongson-pch-msi.c | 2 +-
drivers/irqchip/irq-ls-extirq.c | 2 +-
drivers/macintosh/adb-iop.c | 6 +-
drivers/mailbox/arm_mhuv2.c | 4 +-
drivers/mailbox/sprd-mailbox.c | 2 +-
drivers/md/bcache/bcache.h | 3 +
drivers/md/bcache/btree.c | 21 +-
drivers/md/bcache/journal.c | 4 +-
drivers/md/bcache/super.c | 20 +
drivers/md/dm-core.h | 4 +
drivers/md/dm-crypt.c | 1 +
drivers/md/dm-era-target.c | 93 +--
drivers/md/dm-table.c | 168 +++---
drivers/md/dm-writecache.c | 74 ++-
drivers/md/dm.c | 62 +-
drivers/md/dm.h | 2 +-
drivers/media/i2c/Kconfig | 1 +
drivers/media/i2c/max9286.c | 2 +-
drivers/media/i2c/ov5670.c | 3 +-
drivers/media/pci/cx25821/cx25821-core.c | 4 +-
drivers/media/pci/intel/ipu3/Kconfig | 3 +-
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +-
drivers/media/pci/saa7134/saa7134-empress.c | 5 +-
drivers/media/pci/smipcie/smipcie-ir.c | 46 +-
drivers/media/platform/aspeed-video.c | 6 +-
drivers/media/platform/marvell-ccic/mcam-core.c | 2 +
.../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 +-
.../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3 +-
drivers/media/platform/pxa_camera.c | 3 +
drivers/media/platform/qcom/camss/camss-video.c | 3 +-
drivers/media/platform/ti-vpe/cal.c | 4 +-
drivers/media/platform/vsp1/vsp1_drv.c | 4 +-
drivers/media/rc/ir_toy.c | 1 +
drivers/media/rc/mceusb.c | 2 +-
drivers/media/test-drivers/vidtv/vidtv_psi.c | 5 +-
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/media/v4l2-core/v4l2-ioctl.c | 32 +-
drivers/memory/mtk-smi.c | 4 +-
drivers/memory/ti-aemif.c | 8 +-
drivers/mfd/altera-sysmgr.c | 3 +-
drivers/mfd/bd9571mwv.c | 6 +-
drivers/mfd/gateworks-gsc.c | 2 +-
drivers/mfd/wm831x-auxadc.c | 3 +-
drivers/misc/cardreader/rts5227.c | 5 +
drivers/misc/eeprom/eeprom_93xx46.c | 1 +
drivers/misc/fastrpc.c | 7 +-
drivers/misc/mei/bus.c | 7 +
drivers/misc/mei/hbm.c | 2 +-
drivers/misc/mei/hw-me-regs.h | 5 +
drivers/misc/mei/interrupt.c | 33 +-
drivers/misc/mei/pci-me.c | 5 +
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +-
drivers/mmc/host/owl-mmc.c | 9 +-
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +-
drivers/mmc/host/sdhci-esdhc-imx.c | 3 +-
drivers/mmc/host/sdhci-pci-o2micro.c | 20 +
drivers/mmc/host/sdhci-sprd.c | 6 +-
drivers/mmc/host/usdhi6rol0.c | 4 +-
drivers/mtd/devices/phram.c | 6 +-
drivers/mtd/nand/raw/intel-nand-controller.c | 6 +-
drivers/mtd/parsers/afs.c | 4 +-
drivers/mtd/parsers/parser_imagetag.c | 4 +
drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4 +-
drivers/mtd/spi-nor/core.c | 10 +-
drivers/mtd/spi-nor/sfdp.c | 5 +-
drivers/net/Kconfig | 2 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +-
drivers/net/dsa/ocelot/felix.c | 16 +-
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 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +-
.../chelsio/inline_crypto/chtls/chtls_cm.h | 3 -
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +-
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14 +-
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
drivers/net/ethernet/ibm/ibmvnic.c | 43 +-
drivers/net/ethernet/ibm/ibmvnic.h | 7 +-
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 62 +-
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 11 +-
drivers/net/ethernet/intel/i40e/i40e_xsk.c | 2 +-
drivers/net/ethernet/intel/ice/ice.h | 2 -
drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6 +-
drivers/net/ethernet/intel/ice/ice_ethtool.c | 34 +-
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33 +-
drivers/net/ethernet/marvell/mvneta.c | 9 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2 +-
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9 +
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 +++++---
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2 +-
.../mellanox/mlx5/core/en_accel/en_accel.h | 2 +-
.../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66 +--
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/fpga/ipsec.h | 2 +
drivers/net/ethernet/mellanox/mlx5/core/health.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 +-
drivers/net/ethernet/realtek/r8169_main.c | 4 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 +-
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26 +-
drivers/net/gtp.c | 1 -
drivers/net/ipa/ipa_main.c | 4 +-
drivers/net/phy/micrel.c | 1 +
drivers/net/phy/mscc/Makefile | 1 +
drivers/net/phy/mscc/mscc.h | 28 +
drivers/net/phy/mscc/mscc_main.c | 608 +++++++++++--------
drivers/net/phy/mscc/mscc_serdes.c | 650 +++++++++++++++++++++
drivers/net/phy/mscc/mscc_serdes.h | 31 +
drivers/net/phy/phy_device.c | 53 +-
drivers/net/phy/sfp.c | 100 ++--
drivers/net/ppp/ppp_async.c | 3 +-
drivers/net/ppp/ppp_synctty.c | 3 +-
drivers/net/vxlan.c | 11 +-
drivers/net/wireguard/device.c | 19 +-
drivers/net/wireguard/device.h | 15 +-
drivers/net/wireguard/peer.c | 28 +-
drivers/net/wireguard/peer.h | 4 +-
drivers/net/wireguard/queueing.c | 86 ++-
drivers/net/wireguard/queueing.h | 45 +-
drivers/net/wireguard/receive.c | 16 +-
drivers/net/wireguard/send.c | 31 +-
drivers/net/wireless/ath/ath10k/mac.c | 2 +
drivers/net/wireless/ath/ath10k/snoc.c | 5 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +
drivers/net/wireless/ath/ath11k/mac.c | 11 +-
drivers/net/wireless/ath/ath9k/debug.c | 5 +-
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43 +-
.../net/wireless/intel/iwlwifi/mvm/time-event.c | 3 -
.../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21 +-
drivers/net/xen-netback/interface.c | 8 +-
drivers/nvme/host/multipath.c | 4 +
drivers/nvme/target/admin-cmd.c | 33 +-
drivers/nvme/target/tcp.c | 59 +-
drivers/nvmem/core.c | 5 +-
drivers/nvmem/qcom-spmi-sdam.c | 7 +-
drivers/of/fdt.c | 12 +-
drivers/opp/of.c | 4 +-
drivers/pci/controller/cadence/pcie-cadence-host.c | 5 +-
drivers/pci/controller/dwc/pcie-qcom.c | 4 +-
drivers/pci/controller/pcie-rcar-host.c | 2 +-
drivers/pci/controller/pcie-rockchip.c | 12 +-
drivers/pci/controller/pcie-xilinx-cpm.c | 1 +
drivers/pci/pci-bridge-emul.c | 11 +-
drivers/pci/setup-res.c | 6 +
drivers/pci/syscall.c | 10 +-
drivers/perf/arm-cmn.c | 17 +-
drivers/phy/Kconfig | 1 +
drivers/phy/cadence/phy-cadence-torrent.c | 1 +
drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10 +-
drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +-
drivers/platform/chrome/cros_ec_proto.c | 12 +-
drivers/platform/x86/Kconfig | 4 +-
drivers/power/reset/at91-sama5d2_shdwc.c | 2 +-
drivers/power/supply/Kconfig | 1 +
drivers/power/supply/axp20x_usb_power.c | 2 +-
drivers/power/supply/cpcap-battery.c | 12 +-
drivers/power/supply/cpcap-charger.c | 4 +-
drivers/power/supply/smb347-charger.c | 12 +-
drivers/pwm/pwm-iqs620a.c | 8 +-
drivers/pwm/pwm-rockchip.c | 18 +-
drivers/regulator/axp20x-regulator.c | 7 +-
drivers/regulator/core.c | 6 +-
drivers/regulator/qcom-rpmh-regulator.c | 26 +
drivers/regulator/rohm-regulator.c | 9 +-
drivers/regulator/s5m8767.c | 15 +-
drivers/remoteproc/mtk_common.h | 1 +
drivers/remoteproc/mtk_scp.c | 20 +-
drivers/rtc/Kconfig | 3 +-
drivers/rtc/rtc-rx6110.c | 4 +-
drivers/s390/crypto/zcrypt_api.c | 14 +
drivers/s390/virtio/virtio_ccw.c | 4 +-
drivers/scsi/aic94xx/aic94xx_scb.c | 20 +-
drivers/scsi/bnx2fc/Kconfig | 1 +
drivers/scsi/hisi_sas/hisi_sas_main.c | 12 +-
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 +-
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +-
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +-
drivers/scsi/isci/port.c | 11 +-
drivers/scsi/libsas/sas_event.c | 66 ++-
drivers/scsi/libsas/sas_init.c | 27 +-
drivers/scsi/libsas/sas_internal.h | 5 +-
drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +-
drivers/scsi/mvsas/mv_sas.c | 25 +-
drivers/scsi/pm8001/pm8001_hwi.c | 40 +-
drivers/scsi/pm8001/pm8001_sas.c | 7 +-
drivers/scsi/pm8001/pm80xx_hwi.c | 35 +-
drivers/scsi/qla2xxx/qla_dbg.c | 1 +
drivers/scsi/qla2xxx/qla_mbx.c | 3 +-
drivers/scsi/sd.c | 6 +-
drivers/scsi/sd_zbc.c | 6 +-
drivers/scsi/ufs/ufshcd.c | 17 +-
drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +-
drivers/soc/aspeed/aspeed-socinfo.c | 33 +-
drivers/soc/qcom/ocmem.c | 8 +-
drivers/soc/qcom/socinfo.c | 2 +-
drivers/soc/samsung/exynos-asv.c | 18 +-
drivers/soc/ti/pm33xx.c | 5 +-
drivers/soundwire/bus.c | 47 +-
drivers/soundwire/cadence_master.c | 8 +-
drivers/soundwire/debugfs.c | 2 +-
drivers/soundwire/intel_init.c | 3 +-
drivers/spi/spi-atmel.c | 2 +-
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-dw-bt1.c | 2 +-
drivers/spi/spi-fsl-spi.c | 2 +-
drivers/spi/spi-imx.c | 2 +-
drivers/spi/spi-pxa2xx-pci.c | 27 +-
drivers/spi/spi-stm32.c | 4 +
drivers/spi/spi-synquacer.c | 4 +
drivers/spi/spi.c | 2 +-
drivers/spmi/spmi-pmic-arb.c | 5 +-
drivers/staging/gdm724x/gdm_usb.c | 10 +-
drivers/staging/media/allegro-dvt/allegro-core.c | 3 +-
drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24 +-
drivers/staging/media/atomisp/pci/hmm/hmm.c | 2 +-
drivers/staging/media/imx/imx-media-csc-scaler.c | 4 -
drivers/staging/media/imx/imx-media-dev.c | 7 +-
drivers/staging/media/imx/imx7-media-csi.c | 27 +-
drivers/staging/mt7621-dma/Makefile | 2 +-
.../mt7621-dma/{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 +-
.../vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 +-
drivers/staging/wfx/data_tx.c | 10 +-
drivers/staging/wfx/data_tx.h | 1 +
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-
drivers/tee/optee/rpc.c | 31 +-
drivers/thermal/cpufreq_cooling.c | 2 +-
drivers/tty/n_gsm.c | 3 +-
drivers/tty/n_hdlc.c | 60 +-
drivers/tty/n_null.c | 3 +-
drivers/tty/n_r3964.c | 10 +-
drivers/tty/n_tracerouter.c | 4 +-
drivers/tty/n_tracesink.c | 4 +-
drivers/tty/n_tty.c | 82 ++-
drivers/tty/serial/stm32-usart.c | 24 +-
drivers/tty/tty_io.c | 82 ++-
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/usb/serial/pl2303.c | 8 +-
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
drivers/vfio/pci/vfio_pci_zdev.c | 4 +
drivers/vfio/vfio_iommu_type1.c | 48 +-
drivers/video/fbdev/Kconfig | 2 +-
drivers/virt/vboxguest/vboxguest_utils.c | 18 +-
drivers/w1/slaves/w1_therm.c | 22 +-
drivers/watchdog/intel-mid_wdt.c | 8 +-
drivers/watchdog/mei_wdt.c | 1 +
drivers/watchdog/qcom-wdt.c | 13 +-
fs/affs/namei.c | 4 +-
fs/btrfs/backref.c | 9 +-
fs/btrfs/backref.h | 9 +-
fs/btrfs/block-group.c | 29 +-
fs/btrfs/ctree.c | 7 +-
fs/btrfs/delayed-ref.c | 56 +-
fs/btrfs/delayed-ref.h | 16 +-
fs/btrfs/extent-tree.c | 128 +---
fs/btrfs/free-space-cache.c | 6 +-
fs/btrfs/inode.c | 3 +-
fs/btrfs/relocation.c | 4 +-
fs/btrfs/space-info.h | 17 +
fs/ceph/caps.c | 10 +-
fs/cifs/cifs_swn.c | 2 +-
fs/cifs/connect.c | 259 ++++----
fs/cifs/dfs_cache.c | 33 +-
fs/cifs/fs_context.c | 43 +-
fs/debugfs/inode.c | 5 +-
fs/erofs/xattr.c | 10 +-
fs/erofs/zmap.c | 10 +-
fs/eventpoll.c | 4 +-
fs/exfat/exfat_raw.h | 4 +
fs/exfat/super.c | 31 +-
fs/ext4/Kconfig | 3 +-
fs/ext4/namei.c | 7 +-
fs/f2fs/compress.c | 5 +-
fs/f2fs/data.c | 12 +-
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 30 +-
fs/f2fs/inline.c | 4 +
fs/f2fs/super.c | 3 +
fs/gfs2/bmap.c | 6 +-
fs/gfs2/lock_dlm.c | 8 +-
fs/gfs2/recovery.c | 4 +-
fs/gfs2/util.c | 16 +-
fs/io_uring.c | 17 +-
fs/isofs/dir.c | 1 +
fs/isofs/namei.c | 1 +
fs/jffs2/summary.c | 3 +
fs/jfs/jfs_dmap.c | 2 +-
fs/nfs/nfs4proc.c | 15 +-
fs/nfsd/nfsctl.c | 14 +-
fs/ocfs2/cluster/heartbeat.c | 8 +-
fs/proc/proc_sysctl.c | 4 +-
fs/proc/self.c | 2 +-
fs/proc/task_mmu.c | 9 +-
fs/proc/thread_self.c | 7 +
fs/pstore/platform.c | 4 +-
fs/quota/quota_v2.c | 11 +-
fs/ubifs/auth.c | 2 +-
fs/ubifs/replay.c | 4 +-
fs/ubifs/super.c | 4 +-
fs/zonefs/super.c | 3 +
include/acpi/acexcep.h | 10 +-
include/asm-generic/vmlinux.lds.h | 16 +-
include/linux/bpf.h | 8 +-
include/linux/device-mapper.h | 5 +
include/linux/entry-kvm.h | 14 +
include/linux/eventpoll.h | 2 +-
include/linux/filter.h | 2 +-
include/linux/icmpv6.h | 28 +-
include/linux/iommu.h | 4 +-
include/linux/ipv6.h | 1 -
include/linux/kexec.h | 5 +
include/linux/key.h | 1 +
include/linux/kgdb.h | 2 +
include/linux/khugepaged.h | 2 +
include/linux/memremap.h | 6 +
include/linux/mfd/rohm-generic.h | 14 +-
include/linux/rcupdate.h | 2 +
include/linux/rmap.h | 3 +-
include/linux/soundwire/sdw.h | 2 +
include/linux/tpm.h | 5 +-
include/linux/tty_ldisc.h | 3 +-
include/linux/zsmalloc.h | 2 +-
include/net/act_api.h | 6 +-
include/net/icmp.h | 6 +-
include/net/tcp.h | 9 +-
include/scsi/libsas.h | 11 +-
include/uapi/drm/drm_fourcc.h | 4 +-
include/uapi/drm/drm_mode.h | 13 +-
init/Kconfig | 11 +
init/main.c | 1 +
kernel/Makefile | 2 +-
kernel/bpf/bpf_iter.c | 2 +-
kernel/bpf/bpf_lru_list.c | 7 +-
kernel/bpf/devmap.c | 4 +-
kernel/bpf/verifier.c | 3 +-
kernel/debug/debug_core.c | 11 +
kernel/debug/kdb/kdb_private.h | 2 +-
kernel/entry/common.c | 7 +
kernel/kcsan/core.c | 26 +-
kernel/kexec_file.c | 5 +
kernel/kprobes.c | 31 +-
kernel/locking/lockdep.c | 3 +-
kernel/module.c | 164 +++++-
kernel/module_signature.c | 2 +-
kernel/module_signing.c | 2 +-
kernel/printk/printk.c | 28 +-
kernel/printk/printk_safe.c | 16 +-
kernel/rcu/tree.c | 53 +-
kernel/rcu/tree.h | 2 +-
kernel/rcu/tree_plugin.h | 31 +-
kernel/sched/fair.c | 45 +-
kernel/sched/idle.c | 1 +
kernel/seccomp.c | 2 +
kernel/smp.c | 4 +
kernel/tracepoint.c | 80 ++-
mm/compaction.c | 43 +-
mm/hugetlb.c | 14 +-
mm/khugepaged.c | 22 +-
mm/memcontrol.c | 30 +-
mm/memory-failure.c | 6 +
mm/memory.c | 16 +-
mm/memremap.c | 15 +
mm/slab_common.c | 4 +-
mm/slub.c | 8 +-
mm/vmscan.c | 9 +-
mm/zsmalloc.c | 17 +-
net/bluetooth/a2mp.c | 3 +-
net/bluetooth/hci_core.c | 6 +-
net/bluetooth/hci_request.c | 25 +-
net/core/filter.c | 13 +-
net/ipv4/icmp.c | 5 +-
net/ipv6/icmp.c | 18 +-
net/ipv6/ip6_icmp.c | 12 +-
net/mac80211/mesh_hwmp.c | 2 +-
net/nfc/nci/uart.c | 3 +-
net/qrtr/tun.c | 12 +-
net/sched/act_api.c | 106 ++--
net/sched/cls_api.c | 12 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 6 +-
samples/Kconfig | 2 +-
samples/watch_queue/watch_test.c | 2 +-
security/commoncap.c | 12 +-
security/integrity/evm/evm_crypto.c | 7 +-
security/integrity/ima/ima_kexec.c | 3 +
security/integrity/ima/ima_mok.c | 5 +-
security/keys/Kconfig | 8 +-
security/keys/key.c | 2 +
security/keys/trusted-keys/trusted_tpm1.c | 22 +-
security/keys/trusted-keys/trusted_tpm2.c | 22 +-
security/selinux/hooks.c | 4 +
sound/core/init.c | 4 +
sound/core/pcm.c | 4 +
sound/core/pcm_local.h | 1 +
sound/core/pcm_native.c | 27 +-
sound/firewire/fireface/ff-protocol-latter.c | 118 +++-
sound/pci/hda/hda_intel.c | 2 +
sound/pci/hda/patch_hdmi.c | 1 -
sound/pci/hda/patch_realtek.c | 40 ++
sound/soc/codecs/cpcap.c | 12 +-
sound/soc/codecs/cs42l56.c | 3 +-
sound/soc/codecs/max98373.c | 2 +-
sound/soc/codecs/rt5682-i2c.c | 3 +
sound/soc/codecs/wsa881x.c | 1 +
sound/soc/fsl/Kconfig | 1 +
sound/soc/generic/simple-card-utils.c | 13 +-
sound/soc/intel/boards/sof_sdw.c | 9 +-
sound/soc/qcom/lpass-apq8016.c | 2 +-
sound/soc/qcom/lpass-cpu.c | 30 +-
sound/soc/qcom/lpass-lpaif-reg.h | 3 -
sound/soc/qcom/lpass-sc7180.c | 2 +-
sound/soc/qcom/lpass.h | 1 -
sound/soc/qcom/qdsp6/q6asm-dai.c | 21 +
sound/soc/qcom/qdsp6/q6routing.c | 18 -
sound/soc/sh/siu.h | 2 +-
sound/soc/sh/siu_pcm.c | 2 +-
sound/soc/sof/debug.c | 2 +-
sound/soc/sof/intel/hda-dsp.c | 4 +
sound/soc/sof/sof-pci-dev.c | 7 +
sound/usb/card.h | 2 +-
sound/usb/endpoint.c | 87 +--
sound/usb/implicit.c | 2 +
sound/usb/pcm.c | 7 +-
tools/lib/bpf/libbpf.c | 22 +-
tools/objtool/arch/x86/special.c | 2 +-
tools/objtool/check.c | 15 +-
tools/objtool/check.h | 11 +
tools/perf/builtin-record.c | 2 +-
.../pmu-events/arch/arm64/ampere/emag/cache.json | 2 +-
tools/perf/tests/sample-parsing.c | 2 +-
tools/perf/util/cgroup.c | 8 +-
tools/perf/util/event.c | 2 +
tools/perf/util/evlist.c | 8 +
tools/perf/util/evlist.h | 4 +
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 41 +-
.../perf/util/intel-pt-decoder/intel-pt-decoder.h | 2 +
tools/perf/util/intel-pt.c | 29 +-
tools/perf/util/symbol.c | 7 +-
tools/perf/util/unwind-libdw.c | 11 +-
tools/testing/kunit/kunit_tool_test.py | 14 +-
tools/testing/scatterlist/main.c | 1 -
.../selftests/bpf/prog_tests/btf_map_in_map.c | 33 --
tools/testing/selftests/bpf/test_progs.c | 13 +-
tools/testing/selftests/bpf/test_progs.h | 1 +
tools/testing/selftests/bpf/test_xdp_redirect.sh | 10 +-
tools/testing/selftests/dmabuf-heaps/Makefile | 2 +-
.../trigger-synthetic_event_syntax_errors.tc | 35 +-
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 +-
tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +-
tools/testing/selftests/seccomp/seccomp_bpf.c | 2 +-
tools/testing/selftests/wireguard/netns.sh | 15 +-
780 files changed, 7958 insertions(+), 3975 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.11 377/775] watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
2021-03-01 16:02 1% [PATCH 5.11 000/775] 5.11.3-rc1 review Greg Kroah-Hartman
@ 2021-03-01 16:09 7% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-01 16:09 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Andy Shevchenko, Guenter Roeck,
Linus Walleij, Mika Westerberg, Sasha Levin
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
[ Upstream commit f285c9532b5bd3de7e37a6203318437cab79bd9a ]
When SCU is not ready and CONFIG_DEBUG_SHIRQ=y we got deferred probe followed
by fired test IRQ which immediately makes kernel panic. Fix this by delaying
IRQ handler registration till SCU is ready.
Fixes: 80ae679b8f86 ("watchdog: intel-mid_wdt: Convert to use new SCU IPC API")
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/watchdog/intel-mid_wdt.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c
index 1ae03b64ef8bf..9b2173f765c8c 100644
--- a/drivers/watchdog/intel-mid_wdt.c
+++ b/drivers/watchdog/intel-mid_wdt.c
@@ -154,6 +154,10 @@ static int mid_wdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT);
watchdog_set_drvdata(wdt_dev, mid);
+ mid->scu = devm_intel_scu_ipc_dev_get(dev);
+ if (!mid->scu)
+ return -EPROBE_DEFER;
+
ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq,
IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog",
wdt_dev);
@@ -162,10 +166,6 @@ static int mid_wdt_probe(struct platform_device *pdev)
return ret;
}
- mid->scu = devm_intel_scu_ipc_dev_get(dev);
- if (!mid->scu)
- return -EPROBE_DEFER;
-
/*
* The firmware followed by U-Boot leaves the watchdog running
* with the default threshold which may vary. When we get here
--
2.27.0
^ permalink raw reply related [relevance 7%]
* [PATCH 5.11 000/775] 5.11.3-rc1 review
@ 2021-03-01 16:02 1% Greg Kroah-Hartman
2021-03-01 16:09 7% ` [PATCH 5.11 377/775] watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2021-03-01 16:02 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.11.3 release.
There are 775 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 03 Mar 2021 16:09:49 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.3-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.11.3-rc1
Cong Wang <cong.wang@bytedance.com>
net_sched: fix RTNL deadlock again caused by request_module()
Takeshi Misawa <jeliantsurux@gmail.com>
net: qrtr: Fix memory leak in qrtr_tun_open
Vlad Buslov <vladbu@nvidia.com>
net: sched: fix police ext initialization
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: get rid of per-peer ring buffers
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: selftests: test multiple parallel streams
Jason A. Donenfeld <Jason@zx2c4.com>
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Leon Romanovsky <leon@kernel.org>
ipv6: silence compilation warning for non-IPV6 builds
Sumit Garg <sumit.garg@linaro.org>
kgdb: fix to kill breakpoints on initmem after boot
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/i915: Reject 446-480MHz HDMI clock on GLK
Nikos Tsironis <ntsironis@arrikto.com>
dm era: only resize metadata in preresume
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Reinitialize bitset cache before digesting a new writeset
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Use correct value size in equality function of writeset tree
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Fix bitset memory leaks
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Verify the data block size hasn't changed
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Update in-core bitset after committing the metadata
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Recover committed writeset after crash
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix writing beyond end of underlying device when shrinking
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: return the exact table values that were set
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix performance degradation in ssd mode
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix zoned iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix DAX iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix iterate_devices based device capability checks
Mikulas Patocka <mpatocka@redhat.com>
dm: fix deadlock when swapping to encrypted device
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Lock imbalance on error path in gfs2_recover_one
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't skip dlm unlock if glock has an lvb
Bob Peterson <rpeterso@redhat.com>
gfs2: fix glock confusion in function signal_our_withdraw
Masahisa Kojima <masahisa.kojima@linaro.org>
spi: spi-synquacer: fix set_cs handling
Rasmus Villemoes <rasmus.villemoes@prevas.dk>
spi: fsl: invert spisel_boot signal on MPC8309
Paul Cercueil <paul@crapouillou.net>
perf stat: Use nftw() instead of ftw()
Al Viro <viro@zeniv.linux.org.uk>
sparc32: fix a user-triggerable oops in clear_user()
Ronnie Sahlberg <lsahlber@redhat.com>
cifs: fix handling of escaped ',' in the password mount argument
Paulo Alcantara <pc@cjr.nz>
cifs: fix nodfs mount option
Paulo Alcantara <pc@cjr.nz>
cifs: introduce helper for finding referral server to improve DFS target resolution
Paulo Alcantara <pc@cjr.nz>
cifs: check all path components in resolved dfs target
Paulo Alcantara <pc@cjr.nz>
cifs: fix DFS failover
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: flush data when enabling checkpoint back
Chao Yu <chao@kernel.org>
f2fs: enforce the immutable flag on open files
Chao Yu <chao@kernel.org>
f2fs: fix out-of-repair __setattr_copy()
Huacai Chen <chenhuacai@kernel.org>
irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Johannes Berg <johannes.berg@intel.com>
um: defer killing userspace on page table update failures
Johannes Berg <johannes.berg@intel.com>
um: mm: check more comprehensively for stub changes
Cornelia Huck <cohuck@redhat.com>
virtio/s390: implement virtio-ccw revision 2 correctly
Heiko Carstens <hca@linux.ibm.com>
s390/vtime: fix inline assembly clobber list
Jens Axboe <axboe@kernel.dk>
proc: don't allow async path resolution of /proc/thread-self components
Chen Yu <yu.c.chen@intel.com>
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Shawn Guo <shawn.guo@linaro.org>
cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Viresh Kumar <viresh.kumar@linaro.org>
thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Chris Wilson <chris@chris-wilson.co.uk>
kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
zonefs: Fix file size of zones in full condition
Namjae Jeon <namjae.jeon@samsung.com>
exfat: fix shift-out-of-bounds in exfat_fill_super()
Muchun Song <songmuchun@bytedance.com>
printk: fix deadlock when kernel panic
Tim Harvey <tharvey@gateworks.com>
mfd: gateworks-gsc: Fix interrupt type
Maxim Kiselev <bigunclemax@gmail.com>
gpio: pcf857x: Fix missing first interrupt
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point LP DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point S DID
Tomas Winkler <tomas.winkler@intel.com>
mei: me: emmitsburg workstation DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: fix transfer over dma with extended header
Alexander Usyskin <alexander.usyskin@intel.com>
mei: bus: block send with vtag on non-conformat FW
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
spmi: spmi-pmic-arb: Fix hw_irq overflow
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32s: Add missing call to kuep_lock on syscall entry
Hari Bathini <hbathini@linux.ibm.com>
powerpc/kexec_file: fix FDT size estimation for kdump kernel
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
Shirley Her <shirley.her@bayhubtech.com>
mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Frank Li <Frank.Li@nxp.com>
mmc: sdhci-esdhc-imx: fix kernel panic when remove module
Fangrui Song <maskray@google.com>
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
Paolo Bonzini <pbonzini@redhat.com>
KVM: nSVM: fix running nested guests when npt=0
Vlastimil Babka <vbabka@suse.cz>
mm, compaction: make fast_isolate_freepages() stay within zone
Dave Hansen <dave.hansen@linux.intel.com>
mm/vmscan: restore zone_reclaim_mode ABI
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix update_and_free_page contig page struct assumption
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix get_active_memcg return value
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix swap undercounting in cgroup2
NeilBrown <neilb@suse.de>
x86: fix seq_file iteration for pat/memtype.c
NeilBrown <neilb@suse.de>
seq_file: document how per-entry resources are managed.
Pan Bian <bianpan2016@163.com>
fs/affs: release old buffer head on error path
Pan Bian <bianpan2016@163.com>
mtd: spi-nor: hisi-sfc: Put child node np on error path
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Add erase size check for erase command initialization
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Fix erase type discovery for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix last erase region marking
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Handle accesses to TRCSTALLCTLR
Alexander Usyskin <alexander.usyskin@intel.com>
watchdog: mei_wdt: request stop on unregister
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Tobias Klauser <tklauser@distanz.ch>
riscv: Disable KSAN_SANITIZE for vDSO
Will Deacon <will@kernel.org>
arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Shaoying Xu <shaoyi@amazon.com>
arm64 module: set plt* section addresses to 0x0
He Zhe <zhe.he@windriver.com>
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
qiuguorui1 <qiuguorui1@huawei.com>
arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
Viresh Kumar <viresh.kumar@linaro.org>
mailbox: arm_mhuv2: Skip calling kfree() with invalid pointer
Isaac J. Manjarres <isaacm@codeaurora.org>
iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Suzuki K Poulose <suzuki.poulose@arm.com>
arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
Masami Hiramatsu <mhiramat@kernel.org>
kprobes: Fix to delay the kprobes jump optimization
Frederic Weisbecker <frederic@kernel.org>
entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
entry: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Trigger self-IPI on late deferred wake up before user resume
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Perform deferred wake up before last idle's need_resched() check
Frederic Weisbecker <frederic@kernel.org>
rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
Cédric Le Goater <clg@kaod.org>
powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Thomas Gleixner <tglx@linutronix.de>
x86/entry: Fix instrumentation annotation
Andy Lutomirski <luto@kernel.org>
x86/fault: Fix AMD erratum #91 errata fixup for user code
Sean Christopherson <seanjc@google.com>
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Christopherson <seanjc@google.com>
x86/virt: Eat faults on VMXOFF in reboot flows
Sean Young <sean@mess.org>
media: smipcie: fix interrupt handling and IR timeout
Lubomir Rintel <lkundrak@v3.sk>
media: marvell-ccic: power up the device on mclk enable
Pavel Machek <pavel@denx.de>
media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
Sean Young <sean@mess.org>
media: ir_toy: add another IR Droid device
Sakari Ailus <sakari.ailus@linux.intel.com>
media: v4l: ioctl: Fix memory leak in video_usercopy
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: i2c: max9286: fix access to unallocated memory
Jiri Kosina <jkosina@suse.cz>
floppy: reintroduce O_NDELAY fix
Martin Kaiser <martin@kaiser.cx>
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Amey Narkhede <ameynarkhede03@gmail.com>
staging: gdm724x: Fix DMA from stack
Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Dinh Nguyen <dinguyen@kernel.org>
arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Frank Wunderlich <frank-w@public-files.de>
dts64: mt7622: fix slow sd card access
Jiri Bohac <jbohac@suse.cz>
pstore: Fix typo in compression option name
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Ricky Wu <ricky_wu@realtek.com>
misc: rtsx: init of rts522a add OCP power off when no card is present
Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Paul Cercueil <paul@crapouillou.net>
seccomp: Add missing return in non-void function
Krzysztof Kozlowski <krzk@kernel.org>
soc: samsung: exynos-asv: handle reading revision register error
Marek Szyprowski <m.szyprowski@samsung.com>
soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - initialize need_fallback
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - handle BigEndian for cipher
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - IV register does not work on A10 and A13
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - checking sg length is not sufficient
Ard Biesheuvel <ardb@kernel.org>
crypto: michael_mic - fix broken misalignment handling
Ard Biesheuvel <ardb@kernel.org>
crypto: aesni - prevent misaligned buffers on the stack
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/sha - add missing module aliases
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Correct surface base address for renderclear
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Flush before changing register state
Filipe Manana <fdmanana@suse.com>
btrfs: fix extent buffer leak on failure to copy root
Josef Bacik <josef@toxicpanda.com>
btrfs: account for new extents being deleted in total_bytes_pinned
Josef Bacik <josef@toxicpanda.com>
btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
Josef Bacik <josef@toxicpanda.com>
btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
Josef Bacik <josef@toxicpanda.com>
btrfs: fix reloc root leak with 0 ref reloc roots on recovery
Josef Bacik <josef@toxicpanda.com>
btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
Josef Bacik <josef@toxicpanda.com>
btrfs: add asserts for deleting backref cache nodes
Josef Bacik <josef@toxicpanda.com>
btrfs: do not warn if we can't find the reloc root when looking up backref
Josef Bacik <josef@toxicpanda.com>
btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Reserve TPM for seal and unseal operations
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix migratable=1 failing
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix incorrect handling of tpm_get_random()
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Clean up locality release
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Fix check_locality for correct locality acquisition
Gao Xiang <hsiangkao@redhat.com>
erofs: initialized fields can only be observed after bit is set
Amir Goldstein <amir73il@gmail.com>
selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Takashi Iwai <tiwai@suse.de>
ASoC: siu: Fix build error by a wrong const prefix
Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
drm/rockchip: Require the YTR modifier for AFBC
Heiko Stuebner <heiko@sntech.de>
drm/panel: kd35t133: allow using non-continuous dsi clock
Andrey Grodzovsky <andrey.grodzovsky@amd.com>
drm/sched: Cancel and flush all outstanding jobs before finish.
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/modes: Switch to 64bit maths to avoid integer overflow
Karol Herbst <kherbst@redhat.com>
drm/nouveau/kms: handle mDP connectors
xinhui pan <xinhui.pan@amd.com>
drm/ttm: Fix a memory leak
Prike Liang <Prike.Liang@amd.com>
drm/amdgpu: fix shutdown and poweroff process failed with s0ix
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Marek Olšák <marek.olsak@amd.com>
drm/amdgpu: fix CGTS_TCC_DISABLE register offset on gfx10.3
Felix Kuehling <Felix.Kuehling@amd.com>
drm/amdkfd: Fix recursive lock warnings
Anson Jacob <Anson.Jacob@amd.com>
Revert "drm/amd/display: reuse current context instead of recreating one"
Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Eric Bernstein <eric.bernstein@amd.com>
drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Jan Kokemüller <jan.kokemueller@gmail.com>
drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Alex Deucher <alexander.deucher@amd.com>
Revert "drm/amd/display: Update NV1x SR latency values"
Kai Krakow <kai@kaishome.de>
bcache: Move journal work to new flush wq
Kai Krakow <kai@kaishome.de>
bcache: Give btree_io_wq correct semantics again
Kai Krakow <kai@kaishome.de>
Revert "bcache: Kill btree_io_wq"
Alexander Lobakin <alobakin@pm.me>
MIPS: compressed: fix build with enabled UBSAN
Kevin Hao <haokexin@gmail.com>
Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Nathan Chancellor <nathan@kernel.org>
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
Aurelien Jarno <aurelien@aurel32.net>
MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Paul Cercueil <paul@crapouillou.net>
MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
Takashi Iwai <tiwai@suse.de>
ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
PeiSen Hou <pshou@realtek.com>
ALSA: hda/realtek: modify EAPD in the ALC886
Takashi Iwai <tiwai@suse.de>
ALSA: hda/hdmi: Drop bogus check at closing a stream
Kai Vehmanen <kai.vehmanen@linux.intel.com>
ALSA: hda: Add another CometLake-H PCI ID
Takashi Sakamoto <o-takashi@sakamocchi.jp>
ALSA: fireface: fix to parse sync status register of latter protocol
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Add implicit fb quirk for BOSS GP-10
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Don't avoid stopping the stream at disconnection
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: More strict state change in EP
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Handle invalid running state at releasing EP
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Correct document for snd_usb_endpoint_free_all()
Mathias Kresin <dev@kresin.me>
phy: lantiq: rcu-usb2: wait after clock enable
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7720: fix error code in mos7720_write()
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7840: fix error code in mos7840_write()
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix line-speed handling on newer chips
Johan Hovold <johan@kernel.org>
USB: serial: ftdi_sio: fix FTX sub-integer prescaler
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
Paul Cercueil <paul@crapouillou.net>
usb: musb: Fix runtime PM race in musb_queue_resume_work
Lech Perczak <lech.perczak@gmail.com>
USB: serial: option: update interface mapping for ZTE P685M
James Reynolds <jr@memlen.com>
media: mceusb: Fix potential out-of-bounds shift
Marcos Paulo de Souza <mpdesouza@suse.com>
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Dan Carpenter <dan.carpenter@oracle.com>
Input: joydev - prevent potential read overflow in ioctl
Olivier Crête <olivier.crete@ocrete.ca>
Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
jeffrey.lin <jeffrey.lin@rad-ic.com>
Input: raydium_ts_i2c - do not send zero length
Jason Gerecke <killertofu@gmail.com>
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Filipe Laíns <lains@riseup.net>
HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
Qinglang Miao <miaoqinglang@huawei.com>
ACPI: configfs: add missing check after configfs_register_default_group()
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: property: Fix fwnode string properties matching
Marcin Ślusarz <marcin.slusarz@intel.com>
soundwire: intel: fix possible crash when no device is detected
Mikulas Patocka <mpatocka@redhat.com>
blk-settings: align max_sectors on "logical_block_size" boundary
Bart Van Assche <bvanassche@acm.org>
scsi: sd: Fix Opal support
Finn Thain <fthain@telegraphics.com.au>
ide/falconide: Fix module unload
Ming Lei <ming.lei@redhat.com>
block: fix logging on capacity change
Christoph Hellwig <hch@lst.de>
block: reopen the device in blkdev_reread_part
Johannes Thumshirn <johannes.thumshirn@wdc.com>
scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
Randy Dunlap <rdunlap@infradead.org>
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Zhenzhong Duan <zhenzhong.duan@gmail.com>
csky: Fix a size determination in gpr_get()
Josef Bacik <josef@toxicpanda.com>
proc: use kvzalloc for our kernel buffer
Miaohe Lin <linmiaohe@huawei.com>
mm/rmap: fix potential pte_unmap on an not mapped pte
Dan Williams <dan.j.williams@intel.com>
mm: fix memory_failure() handling of dax-namespace metadata
Rik van Riel <riel@surriel.com>
mm,thp,shmem: make khugepaged obey tmpfs mount flags
Mårten Lindahl <martenli@axis.com>
i2c: exynos5: Preserve high speed master code
Maxime Ripard <maxime@cerno.tech>
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Marc Zyngier <maz@kernel.org>
arm64: Add missing ISB after invalidating TLB in __primary_switch
YueHaibing <yuehaibing@huawei.com>
cifs: Fix inconsistent IS_ERR and PTR_ERR
Sean Christopherson <seanjc@google.com>
KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
Sean Christopherson <seanjc@google.com>
KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4: Fixes for nfs4_bitmask_adjust()
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix jumbo packet handling on RTL8168e
Christian Melki <christian.melki@t2data.com>
net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ8081
Wonhyuk Yang <vvghjk1234@gmail.com>
mm/compaction: fix misbehaviors of fast_find_migrateblock()
Chen Wandun <chenwandun@huawei.com>
mm/hugetlb: suppress wrong warning info when alloc gigantic page
Miaohe Lin <linmiaohe@huawei.com>
mm/hugetlb: fix potential double free in hugetlb_register_node() error path
Miaohe Lin <linmiaohe@huawei.com>
mm/memory.c: fix potential pte_unmap_unlock pte error
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix slub memory accounting
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
Dan Carpenter <dan.carpenter@oracle.com>
ocfs2: fix a use after free on error
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: kconfig: use arm chacha even with no neon
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: device: do not generate ICMP for non-IP packets
Taehee Yoo <ap420073@gmail.com>
vxlan: move debug check after netdev unregister
Chen-Yu Tsai <wens@csie.org>
PCI: rockchip: Make 'ep-gpios' DT property optional
Chuhong Yuan <hslester96@gmail.com>
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Song, Yoong Siang <yoong.siang.song@intel.com>
net: stmmac: fix CBS idleslope and sendslope calculation
Camelia Groza <camelia.groza@nxp.com>
dpaa_eth: fix the access method for the dpaa_napi_portal
Henry Tieman <henry.w.tieman@intel.com>
ice: update the number of available RSS queues
Dave Ertman <david.m.ertman@intel.com>
ice: Fix state bits on LLDP mode switch
Brett Creeley <brett.creeley@intel.com>
ice: Account for port VLAN in VF max packet size calculation
Dave Ertman <david.m.ertman@intel.com>
ice: report correct max number of TCs
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
pwm: iqs620a: Fix overflow and optimize calculations
Dan Carpenter <dan.carpenter@oracle.com>
octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
Norbert Ciosek <norbertx.ciosek@intel.com>
i40e: Fix endianness conversions
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix add TC filter for IPv6
Andreas Oetken <andreas.oetken@siemens.com>
nios2: fixed broken sys_clone syscall
Jann Horn <jannh@google.com>
Take mmap lock in cacheflush syscall
Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
i40e: Fix VFs not created
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix addition of RX filters after enabling FW LLDP agent
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix overwriting flow control settings during driver loading
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Add zero-initialization of AQ command structures
Slawomir Laba <slawomirx.laba@intel.com>
i40e: Fix flow for IPv6 next header (extension header)
Krzysztof Wilczyński <kw@linux.com>
PCI: cadence: Fix DMA range mapping early return error
Russell King <rmk+kernel@armlinux.org.uk>
PCI: pci-bridge-emul: Fix array overruns, improve safety
Shiyang Ruan <ruansy.fnst@cn.fujitsu.com>
device-dax: Fix default return code of range_parse()
Magnum Shan <magnum.shan@unisoc.com>
mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Geert Uytterhoeven <geert@linux-m68k.org>
ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Bard Liao <yung-chuan.liao@linux.intel.com>
regmap: sdw: use _no_pm functions in regmap_read/write
Loic Poulain <loic.poulain@linaro.org>
mhi: Fix double dma free
Tzung-Bi Shih <tzungbi@google.com>
remoteproc/mediatek: acknowledge watchdog IRQ after handled
Jonathan Marek <jonathan@marek.ca>
misc: fastrpc: fix incorrect usage of dma_map_sgtable
Stephen Boyd <swboyd@chromium.org>
drm/msm/dp: Add a missing semi-colon
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: fix confusion on device used by pm_runtime
Bard Liao <yung-chuan.liao@linux.intel.com>
soundwire: export sdw_write/read_no_pm functions
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_update_no_pm when initializing a device
Rob Clark <robdclark@chromium.org>
drm/msm: Fix legacy relocs path
Ahmad Fatoum <a.fatoum@pengutronix.de>
nvmem: core: skip child nodes not matching binding
Dan Carpenter <dan.carpenter@oracle.com>
nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Skip accessing TRCPDCR in save/restore
Geert Uytterhoeven <geert+renesas@glider.be>
phy: USB_LGM_PHY should depend on X86
Theodore Ts'o <tytso@mit.edu>
ext4: fix potential htree index checksum corruption
Max Gurtovoy <mgurtovoy@nvidia.com>
vfio-pci/zdev: fix possible segmentation fault issue
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Fix some sanity checks in detach group
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Populate full dirty when detach non-pinned group
Judy Hsiao <judyhsiao@google.com>
drm/msm/dp: trigger unplug event in msm_dp_display_disable
Stephen Boyd <swboyd@chromium.org>
drm/msm/kms: Make a lock_class_key for each crtc mutex
Eric Anholt <eric@anholt.net>
drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Anholt <eric@anholt.net>
drm/msm: Fix race of GPU init vs timestamp power management.
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm/mdp5: Fix wait-for-commit for cmd panels
Konrad Dybcio <konrad.dybcio@somainline.org>
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
drm/msm: Add proper checks for GPU LLCC support
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm: Fix MSM_INFO_GET_IOVA with carveout
Alexander Usyskin <alexander.usyskin@intel.com>
mei: hbm: call mei_set_devstate() on hbm stop response
Heiner Kallweit <hkallweit1@gmail.com>
PCI: Align checking of syscall user config accessors
Jorgen Hansen <jhansen@vmware.com>
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Pan Bian <bianpan2016@163.com>
PCI: xilinx-cpm: Fix reference count leak on error path
Simon South <simon@simonsouth.net>
pwm: rockchip: Eliminate potential race condition when probing
Simon South <simon@simonsouth.net>
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
Simon South <simon@simonsouth.net>
pwm: rockchip: Enable APB clock during register access while probing
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: cadence: fix ACK/NAK handling
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
soundwire: debugfs: use controller id instead of link_id
Marek Vasut <marek.vasut+renesas@gmail.com>
PCI: rcar: Always allocate MSI addresses in 32bit space
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Add module alias to avoid breaking support for non device tree users
Dan Carpenter <dan.carpenter@oracle.com>
phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
Chris Ruehl <chris.ruehl@gtsys.com.hk>
phy: rockchip-emmc: emmc_phy_init() always return 0
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Fix module alias to enable module autoprobe
Geert Uytterhoeven <geert+renesas@glider.be>
Input: st1232 - fix NORMAL vs. IDLE state handling
Randy Dunlap <rdunlap@infradead.org>
ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
Michael Tretter <m.tretter@pengutronix.de>
Input: st1232 - add IDLE state as ready condition
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: zinitix - fix return type of zinitix_init_touch()
Randy Dunlap <rdunlap@infradead.org>
sparc: fix led.c driver when PROC_FS is not enabled
Randy Dunlap <rdunlap@infradead.org>
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
Dan Carpenter <dan.carpenter@oracle.com>
Input: elo - fix an error code in elo_connect()
Namhyung Kim <namhyung@kernel.org>
perf test: Fix unaligned access in sample parsing test
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix IPC with CYC threshold
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix premature IPC
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix missing CYC processing in PSB
Dave Rigby <d.rigby@me.com>
perf unwind: Set userdata for all __report_module() paths
Yang Jihong <yangjihong1@huawei.com>
perf record: Fix continue profiling after draining the buffer
Dan Carpenter <dan.carpenter@oracle.com>
Input: sur40 - fix an error code in sur40_probe()
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv-sysfs: fix missing put_device
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv: fix memory leak by missing kobject free
Md Haris Iqbal <haris.iqbal@cloud.ionos.com>
RDMA/rtrs: Only allow addition of path to an already established session
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix stack-out-of-bounds
Avihai Horon <avihaih@nvidia.com>
RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Fixes missing error code of CMDQ
Jeff Layton <jlayton@kernel.org>
ceph: fix flush_snap logic after putting caps
Chuck Lever <chuck.lever@oracle.com>
svcrdma: Hold private mutex while invoking rdma_accept()
J. Bruce Fields <bfields@redhat.com>
nfsd: register pernet ops last, unregister first
Nicholas Fraser <nfraser@codeweavers.com>
perf symbols: Fix return value when loading PE DSO
John Ogness <john.ogness@linutronix.de>
printk: avoid prb_first_valid_seq() where possible
Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
spi: Skip zero-length transfers in spi_transfer_one_message()
Kees Cook <keescook@chromium.org>
spi: dw: Avoid stack content exposure
Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
regulator: bd718x7, bd71828, Fix dvs voltage levels
Dmitry Safonov <0x7f454c46@gmail.com>
perf symbols: Use (long) for iterator for bfd symbols
Tom Zanussi <zanussi@kernel.org>
selftests/ftrace: Update synthetic event syntax errors
Ryan Chen <ryan_chen@aspeedtech.com>
clk: aspeed: Fix APLL calculate formula from ast2600-A2
Jonathan Marek <jonathan@marek.ca>
regulator: qcom-rpmh: fix pm8009 ldo7
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/kuap: Restore AMR after replaying soft interrupts
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/uaccess: Avoid might_fault() when user access is enabled
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
spi: pxa2xx: Fix the controller numbering for Wildcat Point
Michael Tretter <m.tretter@pengutronix.de>
clk: divider: fix initialization with parent_hw
Lijun Ou <oulijun@huawei.com>
RDMA/hns: Disable RQ inline by default
Xi Wang <wangxi11@huawei.com>
RDMA/hns: Add mapped page count checking for MTR
Weihang Li <liweihang@huawei.com>
RDMA/hns: Fix type of sq_signal_bits
Weihang Li <liweihang@huawei.com>
RDMA/hns: Avoid filling sgid index when modifying QP to RTR
Kamal Heib <kamalheib1@gmail.com>
RDMA/siw: Fix calculation of tx_valid_cpus size
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Remove the reserved WQE of SRQ
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Fixed wrong judgments in the goto branch
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Force srq_limit to 0 when creating SRQ
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Bugfix for checking whether the srq is full when post wr
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Allocate one more recv SGE for HIP08
John Stultz <john.stultz@linaro.org>
kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
Daniel Latypov <dlatypov@google.com>
kunit: tool: fix unit test cleanup handling
AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Taniya Das <tdas@codeaurora.org>
clk: qcom: gcc-sc7180: Mark the MM XO clocks to be always ON
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
clk: qcom: gfm-mux: fix clk mask
Sandipan Das <sandipan@linux.ibm.com>
powerpc/sstep: Fix darn emulation
Sandipan Das <sandipan@linux.ibm.com>
powerpc/sstep: Fix load-store and update emulation
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/8xx: Fix software emulation interrupt
Nathan Lynch <nathanl@linux.ibm.com>
powerpc/pseries/dlpar: handle ibm, configure-connector delay status
Dan Carpenter <dan.carpenter@oracle.com>
mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
Arnd Bergmann <arnd@arndb.de>
mfd: altera-sysmgr: Fix physical address storing more
Alain Volmat <alain.volmat@foss.st.com>
spi: stm32: properly handle 0 byte transfer
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Correct skb on loopback path
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_recv.c
John Garry <john.garry@huawei.com>
perf vendor events arm64: Fix Ampere eMag event typo
Arnaldo Carvalho de Melo <acme@redhat.com>
perf tools: Fix DSO filtering when not finding a map for a sampled address
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt_crashlog: Add dependency on MFD_INTEL_PMT
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt_telemetry: Add dependency on MFD_INTEL_PMT
David E. Box <david.e.box@linux.intel.com>
platform/x86: intel_pmt: Make INTEL_PMT_CLASS non-user-selectable
David Gow <davidgow@google.com>
rtc: zynqmp: depend on HAS_IOMEM
Steven Rostedt (VMware) <rostedt@goodmis.org>
tracepoint: Do not fail unregistering a probe due to memory failure
Parav Pandit <parav@nvidia.com>
IB/cm: Avoid a loop when device has 255 ports
Parav Pandit <parav@nvidia.com>
IB/mlx5: Return appropriate error code instead of ENOMEM
Douglas Anderson <dianders@chromium.org>
iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Yong Wu <yong.wu@mediatek.com>
iommu: Move iotlb_sync_map out from __iommu_map
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
amba: Fix resource leak for drivers without .remove
David Gow <davidgow@google.com>
i3c/master/mipi-i3c-hci: Specify HAS_IOMEM dependency
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: i2c-qcom-geni: Add shutdown callback for i2c
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Vladimir Murzin <vladimir.murzin@arm.com>
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Takeshi Saito <takeshi.saito.xv@renesas.com>
mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to 128-bytes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: sdhci-sprd: Fix some resource leaks in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: owl-mmc: Fix a resource leak in an error handling path and in the remove function
Michal Suchanek <msuchanek@suse.de>
powerpc: Fix build error in paravirt.h
Pingfan Liu <kernelfans@gmail.com>
powerpc/time: Enable sched clock for irqtime
Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
powerpc/sstep: Fix incorrect return from analyze_instr()
Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
powerpc/sstep: Check instruction validity against ISA version before emulation
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/47x: Disable 256k page size
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/kvm: Force selection of CONFIG_PPC_FPU
Cédric Le Goater <clg@kaod.org>
KVM: PPC: Make the VMX instruction emulation routines static
Shay Drory <shayd@nvidia.com>
IB/umad: Return EPOLLERR in case of when device disassociated
Shay Drory <shayd@nvidia.com>
IB/umad: Return EIO in case of when device disassociated
Mark Bloch <mbloch@nvidia.com>
RDMA/mlx5: Allow creating all QPs even when non RDMA profile is used
Maor Gottlieb <maorg@nvidia.com>
tools/testing/scatterlist: Fix overflow of max segment size
Yong Wu <yong.wu@mediatek.com>
iommu: Switch gather->end to the inclusive end
Dan Carpenter <dan.carpenter@oracle.com>
scsi: lpfc: Fix ancient double free
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix ".cold" section suffix check for newer versions of GCC
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix retpoline detection in asm code
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix error handling for STD/CLD warnings
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: Fix duplicate CHARLCD config symbol
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: ht16k33: Fix refresh rate handling
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
Pan Bian <bianpan2016@163.com>
isofs: release buffer head before return
Hans de Goede <hdegoede@redhat.com>
regulator: core: Avoid debugfs: Directory ... already present! error
Dmitry Osipenko <digetx@gmail.com>
power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Samuel Holland <samuel@sholland.org>
power: supply: axp20x_usb_power: Init work before enabling IRQs
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: isci: Pass gfp_t flags in isci_port_bc_change_received()
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: isci: Pass gfp_t flags in isci_port_link_up()
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: isci: Pass gfp_t flags in isci_port_link_down()
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: mvsas: Pass gfp_t flags to libsas event notifiers
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: Introduce a _gfp() variant of event notifiers
John Garry <john.garry@huawei.com>
scsi: libsas: Remove notifier indirection
Krzysztof Kozlowski <krzk@kernel.org>
regulator: s5m8767: Drop regulators OF node reference
Pan Bian <bianpan2016@163.com>
spi: atmel: Put allocated master before return
Pan Bian <bianpan2016@163.com>
regulator: s5m8767: Fix reference count leak
David Howells <dhowells@redhat.com>
certs: Fix blacklist flag type confusion
Gabriel Krisman Bertazi <krisman@collabora.com>
watch_queue: Drop references to /dev/watch_queue
Pan Bian <bianpan2016@163.com>
regulator: axp20x: Fix reference cout leak
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix clock divider range on some clocks
Parav Pandit <parav@nvidia.com>
IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
Yishai Hadas <yishaih@nvidia.com>
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Guido Günther <agx@sigxcpu.org>
spi: imx: Don't print error on -EPROBEDEFER
Frank van der Linden <fllinden@amazon.com>
module: harden ELF info handling
Tom Rix <trix@redhat.com>
clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
Arnd Bergmann <arnd@arndb.de>
clocksource/drivers/ixp4xx: Select TIMER_OF when needed
Randy Dunlap <rdunlap@infradead.org>
power: supply: fix sbs-charger build, needs REGMAP_I2C
Dave Jiang <dave.jiang@intel.com>
dmaengine: idxd: set DMA channel to be private
Bartosz Golaszewski <bgolaszewski@baylibre.com>
rtc: s5m: select REGMAP_I2C
Claudiu Beznea <claudiu.beznea@microchip.com>
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Fix KASAN: stack-out-of-bounds bug
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Init wr_cnt as 1
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix missing wr_cqe
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs: Call kobject_put in the failure path
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-srv: Jump to dereg_mr label if allocate iu fails
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-clt: Set mininum limit when create QP
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Release lock before call into close_sess
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Extend ibtrs_cq_qp_create
Nicolas Boichat <drinkcat@chromium.org>
of/fdt: Make sure no-map does not remove already reserved regions
KarimAllah Ahmed <karahmed@amazon.de>
fdt: Properly handle "no-map" field in the memory region
Colin Ian King <colin.king@canonical.com>
power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Can Guo <cang@codeaurora.org>
scsi: ufs: Fix a possible NULL pointer issue
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-battery: Fix missing power_supply_put()
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-charger: Fix missing power_supply_put()
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
mfd: bd9571mwv: Use devm_mfd_add_devices()
Ferry Toth <ftoth@exalondelft.nl>
dmaengine: hsu: disable spurious interrupt
Vignesh Raghavendra <vigneshr@ti.com>
dmaengine: ti: k3-udma: Set rflow count for BCDMA split channels
Nathan Chancellor <nathan@kernel.org>
dmaengine: qcom: Always inline gpi_update_reg
Arnd Bergmann <arnd@arndb.de>
rtc: rx6110: fix build against modular I2C
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: owl-dma: Fix a resource leak in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in the remove function
Bernard Metzler <bmt@zurich.ibm.com>
RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Randy Dunlap <rdunlap@infradead.org>
HID: core: detect and skip invalid inputs to snto32()
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Fix parent of CBFUSA clock
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Remove non-existent S2 clock
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix CEC clock
Pratyush Yadav <p.yadav@ti.com>
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle master read request
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle only slave interrupts which are enabled
Jan Kara <jack@suse.cz>
quota: Fix memory leak when handling corrupted quota file
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
Po-Hsu Lin <po-hsu.lin@canonical.com>
selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: make "ret" a signed integer
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
Tony Lindgren <tony@atomide.com>
power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
Zhang Qilong <zhangqilong3@huawei.com>
HSI: Fix PM usage counter unbalance in ssi_hw_init
Eric W. Biederman <ebiederm@xmission.com>
capabilities: Don't allow writing ambiguous v3 file capabilities
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: imx_keypad - add dependency on HAS_IOMEM
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: da7280 - protect OF match table with CONFIG_OF
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: da7280 - fix missing error test
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
smp: Process pending softirqs in flush_smp_call_function_from_idle()
Geert Uytterhoeven <geert+renesas@glider.be>
irqchip/imx: IMX_INTMUX should not default to y, unconditionally
Wang ShaoBo <bobo.shaobowang@huawei.com>
ubifs: Fix error return code in alloc_wbufs()
Arnd Bergmann <arnd@arndb.de>
ubifs: replay: Fix high stack usage, again
Dinghao Liu <dinghao.liu@zju.edu.cn>
ubifs: Fix memleak in ubifs_init_authentication
Tom Rix <trix@redhat.com>
jffs2: fix use after free in jffs2_sum_write_data()
Colin Ian King <colin.king@canonical.com>
fs/jfs: fix potential integer overflow on shift of a int
Sameer Pujar <spujar@nvidia.com>
ASoC: simple-card-utils: Fix device module clock
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer after kexec syscall
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer on error
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: set status to 0 in case for invalid nsid
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: remove extra variable in identify ns
Keith Busch <kbusch@kernel.org>
nvme-multipath: set nr_zones for zoned namespaces
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix potential race of tcp socket closing accept_work
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
Hao Xu <haoxu@linux.alibaba.com>
io_uring: fix possible deadlock in io_uring_poll
Daniele Alessandrelli <daniele.alessandrelli@intel.com>
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Jan Henrik Weinstock <jan.weinstock@rwth-aachen.de>
hwrng: timeriomem - Fix cooldown period calculation
Imre Deak <imre.deak@intel.com>
drm/dp_mst: Don't cache EDIDs for physical ports
Dan Carpenter <dan.carpenter@oracle.com>
drm/virtio: fix an error code in virtio_gpu_init()
Qinglang Miao <miaoqinglang@huawei.com>
drm/lima: fix reference leak in lima_pm_busy
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Restore cec physical address on reconnect
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix up CEC registers
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix register offset with longer CEC messages
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Move hdmi reset to bind
Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: return EIO when msg retry limit reached
Sean Christopherson <seanjc@google.com>
KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
Jinyang He <hejinyang@loongson.cn>
MIPS: relocatable: Provide kaslr_offset() to get the kernel offset
Qu Wenruo <wqu@suse.com>
btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Zhihao Cheng <chengzhihao1@huawei.com>
btrfs: clarify error returns values in __load_free_space_cache
Hui Wang <hui.wang@canonical.com>
ASoC: SOF: debug: Fix a potential issue on string buffer termination
Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>
ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Jun Nie <jun.nie@linaro.org>
ASoC: qcom: lpass: Fix i2s ctl register bit map
Peter Zijlstra <peterz@infradead.org>
locking/lockdep: Avoid unmatched unlock
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A32
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
Sasha Levin <sashal@kernel.org>
drm/mediatek: Fix aal size config
Yongqiang Niu <yongqiang.niu@mediatek.com>
drm/mediatek: Check if fb is null
Sean Christopherson <seanjc@google.com>
KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Dehe Gu <gudehe@huawei.com>
f2fs: fix a wrong condition in __submit_bio
Dan Carpenter <dan.carpenter@oracle.com>
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
Yi Chen <chenyi77@huawei.com>
f2fs: fix to avoid inconsistent quota data
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mtd: rawnand: intel: Fix an error handling path in 'ebu_dma_start()'
Manivannan Sadhasivam <mani@kernel.org>
mtd: parsers: afs: Fix freeing the part name memory in failure
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
ASoC: codecs: add missing max_register in regmap config
Sebastian Reichel <sre@kernel.org>
ASoC: cpcap: fix microphone timeslot mask
Florian Fainelli <f.fainelli@gmail.com>
ata: ahci_brcm: Add back regulators management
Will Deacon <will@kernel.org>
mm: proc: Invalidate TLB after clearing soft-dirty page state
Biwen Li <biwen.li@nxp.com>
irqchip/ls-extirq: add IRQCHIP_SKIP_SET_WAKE to the irqchip flags
Frantisek Hrbata <frantisek@hrbata.com>
drm/nouveau: bail out of nouveau_channel_new if channel init fails
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Fix ctr(aes) on SEC1
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
Dan Carpenter <dan.carpenter@oracle.com>
mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Move IRQs when migrating context
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix PMU instance naming
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: lpass-cpu: Remove bit clock state check
Chao Yu <chao@kernel.org>
f2fs: compress: fix potential deadlock
Daeho Jeong <daehojeong@google.com>
f2fs: fix null page reference in redirty_blocks
Qais Yousef <qais.yousef@arm.com>
sched/eas: Don't update misfit status if the task is pinned
Judy Hsiao <judyhsiao@google.com>
ASoC: max98373: Fixes a typo in max98373_feedback_get
Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
media: i2c/Kconfig: Select FWNODE for OV772x sensor
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
Tom Rix <trix@redhat.com>
media: pxa_camera: declare variable when DEBUG is defined
yangerkun <yangerkun@huawei.com>
mtd: phram: use div_u64_rem to stop overwrite len in phram_setup
Tom Rix <trix@redhat.com>
media: mtk-vcodec: fix argument used when DEBUG is defined
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: cx25821: Fix a bug when reallocating some dma memory
Luo Meng <luomeng12@huawei.com>
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Dan Carpenter <dan.carpenter@oracle.com>
media: atomisp: Fix a buffer overflow in debug code
Daniel W. S. Almeida <dwlsalmeida@gmail.com>
media: vidtv: psi: fix missing crc for PMT
Joe Perches <joe@perches.com>
media: lmedm04: Fix misuse of comma
Daniel Scally <djrscally@gmail.com>
media: software_node: Fix refcounts in software_node_get_next_child()
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
Finn Thain <fthain@telegraphics.com.au>
macintosh/adb-iop: Use big-endian autopoll mask
Pan Bian <bianpan2016@163.com>
bsg: free the request before return error code
Guchun Chen <guchun.chen@amd.com>
drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
Qinglang Miao <miaoqinglang@huawei.com>
drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
Nathan Chancellor <nathan@kernel.org>
MIPS: Compare __SYNC_loongson3_war against 0
Alexander Lobakin <alobakin@pm.me>
MIPS: properly stop .eh_frame generation
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: ti-vpe: cal: fix write to unallocated memory
Rui Miguel Silva <rmfrfs@gmail.com>
media: imx7: csi: Fix pad link validation
Fabio Estevam <festevam@gmail.com>
media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Giulio Benetti <giulio.benetti@micronovasrl.com>
drm/sun4i: tcon: fix inverted DCLK polarity
Xuewen Yan <xuewen.yan@unisoc.com>
sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Jiri Olsa <jolsa@kernel.org>
crypto: bcm - Rename struct device_private to bcm_device_private
Marco Chiappero <marco.chiappero@intel.com>
crypto: qat - replace CRYPTO_AES with CRYPTO_LIB_AES in Kconfig
Dinghao Liu <dinghao.liu@zju.edu.cn>
evm: Fix memleak in init_desc
Stephan Gerhold <stephan@gerhold.net>
ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Dan Carpenter <dan.carpenter@oracle.com>
ASoC: cs42l56: fix up error handling in probe
Zhang Changzhong <zhangchangzhong@huawei.com>
media: aspeed: fix error return code in aspeed_video_setup_video()
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: tm6000: Fix memleak in tm6000_start_stream
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: media/pci: Fix memleak in empress_init
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: em28xx: Fix use-after-free in em28xx_alloc_urbs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: vsp1: Fix an error handling path in the probe function
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: missing error code in msm_video_register()
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: Fix signedness bug in video_enum_fmt()
Zhang Changzhong <zhangchangzhong@huawei.com>
media: mtk-vcodec: fix error return code in vdec_vp9_decode()
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Fix csc/scaler unregister
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Unregister csc/scaler only if registered
Jacopo Mondi <jacopo@jmondi.org>
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
media: ipu3-cio2: Build only for x86
Simon Ser <contact@emersion.fr>
drm/fourcc: fix Amlogic format modifier masks
Chia-I Wu <olvaffe@gmail.com>
drm/virtio: make sure context is created in gem open
Nathan Chancellor <nathan@kernel.org>
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Chancellor <nathan@kernel.org>
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
Chenyang Li <lichenyang@loongson.cn>
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm: rcar-du: Fix leak of CMM platform device reference
Wang Xiaojun <wangxiaojun11@huawei.com>
drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
Qinglang Miao <miaoqinglang@huawei.com>
drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
Marco Elver <elver@google.com>
kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Arnd Bergmann <arnd@arndb.de>
ASoC: fsl_aud2htx: select SND_SOC_IMX_PCM_DMA
Dan Carpenter <dan.carpenter@oracle.com>
media: allegro: Fix use after free on error
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hwrng: ingenic - Fix a resource leak in an error handling path
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - fix kmap usage
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - linearize buffers content must be kept
Linus Walleij <linus.walleij@linaro.org>
drm/panel: s6e63m0: Support max-brightness
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
Guido Günther <agx@sigxcpu.org>
drm/panel: mantix: Tweak init sequence
Linus Walleij <linus.walleij@linaro.org>
drm/panel: s6e63m0: Fix init sequence again
Chuhong Yuan <hslester96@gmail.com>
drm/fb-helper: Add missed unlocks in setcmap_legacy()
Dan Carpenter <dan.carpenter@oracle.com>
gma500: clean up error handling in init
Simon Ser <contact@emersion.fr>
drm: document that user-space should force-probe connectors
Jialin Zhang <zhangjialin11@huawei.com>
drm/gma500: Fix error return code in psb_driver_load()
Randy Dunlap <rdunlap@infradead.org>
fbdev: aty: SPARC64 requires FB_ATY_CT
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: coma mode disabled for VSC8514
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: improved serdes calibration applied to VSC8514
Alex Elder <elder@linaro.org>
net: ipa: initialize all resources
Dany Madden <drt@linux.ibm.com>
ibmvnic: change IBMVNIC_MAX_IND_DESCS to 16
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Fix CQ params of ICOSQ and async ICOSQ
Raed Salem <raeds@nvidia.com>
net/mlx5e: Enable striding RQ for Connect-X IPsec capable devices
Parav Pandit <parav@nvidia.com>
net/mlx5e: E-switch, Fix rate calculation for overflow
Joel Stanley <joel@jms.id.au>
soc: aspeed: socinfo: Add new systems
Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Bluetooth: hci_qca: Fixed issue during suspend
Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Bluetooth: hci_qca: check for SSR triggered flag while suspend
Matthias Brugger <mbrugger@suse.com>
arm64: dts: mt8183: Fix GCE include path
Peter Geis <pgwipeout@gmail.com>
ARM: tegra: ouya: Fix eMMC on specific bootloaders
Pali Rohár <pali@kernel.org>
net: sfp: add workaround for Realtek RTL8672 and RTL9601C chips
Enric Balletbo i Serra <enric.balletbo@collabora.com>
arm64: dts: mt8183: Add missing power-domain for pwm0 node
Yongqiang Niu <yongqiang.niu@mediatek.com>
arm64: dts: mt8183: refine gamma compatible name
Yongqiang Niu <yongqiang.niu@mediatek.com>
arm64: dts: mt8183: rename rdma fifo size
Andrii Nakryiko <andrii@kernel.org>
selftests/bpf: Don't exit on failed bpf_testmod unload
Sami Tolvanen <samitolvanen@google.com>
x86/sgx: Fix the return type of sgx_init()
Linus Torvalds <torvalds@linux-foundation.org>
tty: implement read_iter
Linus Torvalds <torvalds@linux-foundation.org>
tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix uSD pins drive strength
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: sm8250: correct sdhc_2 xo clk
Andrii Nakryiko <andrii@kernel.org>
selftests/bpf: Sync RCU before unloading bpf_testmod
Andrii Nakryiko <andrii@kernel.org>
bpf: Declare __bpf_free_used_maps() unconditionally
Erwan Le Ray <erwan.leray@foss.st.com>
serial: stm32: fix DMA initialization error handling
Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Bluetooth: hci_qca: Wait for SSR completion during suspend
Rafał Miłecki <rafal@milecki.pl>
arm64: dts: broadcom: bcm4908: use proper NAND binding
Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Bluetooth: Remove hci_req_le_suspend_config
Vladimir Oltean <vladimir.oltean@nxp.com>
net: enetc: fix destroyed phylink dereference during unbind
Maxime Chevallier <maxime.chevallier@bootlin.com>
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset link when the link never comes back
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: adding LCPLL reset to VSC8514
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: don't deinitialize unused ports
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: perform teardown in reverse order of setup
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: serialize access to work queue on remove
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: skip send_request_unmap for timeout reset
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: add memory barrier to protect long term buffer
Ilya Leoshkevich <iii@linux.ibm.com>
bpf: Clear subreg_def for global function return values
Colin Ian King <colin.king@canonical.com>
b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
Ayush Sawal <ayush.sawal@chelsio.com>
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Robert Hancock <robert.hancock@calian.com>
net: axienet: Handle deferred probe on clock properly
Eric Dumazet <edumazet@google.com>
tcp: fix SO_RCVLOWAT related hangs under mem pressure
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: fix ACKRX debug message
Jesper Dangaard Brouer <brouer@redhat.com>
bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Jun'ichi Nomura <junichi.nomura@nec.com>
bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Yonghong Song <yhs@fb.com>
bpf: Fix an unitialized value in bpf_iter
Martin KaFai Lau <kafai@fb.com>
libbpf: Ignore non function pointer member in struct_ops
Colin Ian King <colin.king@canonical.com>
mac80211: fix potential overflow when multiplying to u32 integers
Moshe Shemesh <moshe@nvidia.com>
net/mlx5e: Check tunnel offload is required before setting SWP
Oz Shlomo <ozsh@nvidia.com>
net/mlx5e: CT: manage the lifetime of the ct entry object
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for lag devices
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on lag device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on multi port slave device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for multi port slave device
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Replace synchronize_rcu with synchronize_net
Shay Drory <shayd@nvidia.com>
net/mlx5: Fix health error state handling
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Change interrupt moderation channel params also when channels are closed
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Don't change interrupt moderation params when DIM is enabled
Raed Salem <raeds@nvidia.com>
net/mlx5e: Enable XDP for Connect-X IPsec capable devices
Heiner Kallweit <hkallweit1@gmail.com>
net: phy: consider that suspend2ram may cut off PHY power
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: fix memory leak in XDP_REDIRECT
Juergen Gross <jgross@suse.com>
xen/netback: fix spurious event detection for common event case
Vasundhara Volam <vasundhara-v.volam@broadcom.com>
bnxt_en: Fix devlink info's stored fw.psid version format.
Edwin Peer <edwin.peer@broadcom.com>
bnxt_en: reverse order of TX disable and carrier off
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: Set to CLOSED state even on error
Björn Töpel <bjorn@kernel.org>
selftests/bpf: Convert test_xdp_redirect.sh to bash
Linus Lüssing <ll@simonwunderlich.de>
ath9k: fix data bus crash when setting nf_override via debugfs
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: set the PNVM again if it was already loaded
Marco Elver <elver@google.com>
bpf_lru_list: Read double-checked variable once without lock
Sara Sharon <sara.sharon@intel.com>
iwlwifi: mvm: don't check if CSA event is running before removing
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: assign SAR table revision to the command later
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: send stored PPAG command instead of local
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: store PPAG enabled/disabled flag properly
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: fix the type we use in the PPAG table validity checks
Jae Hyun Yoo <jae.hyun.yoo@intel.com>
soc: aspeed: snoop: Add clock control logic
Dan Carpenter <dan.carpenter@oracle.com>
ath11k: fix a locking bug in ath11k_mac_op_start()
Anand K Mistry <amistry@google.com>
ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Anand K Mistry <amistry@google.com>
ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
Arnd Bergmann <arnd@arndb.de>
ARM: at91: use proper asm syntax in pm_suspend
Jérôme Pouiller <jerome.pouiller@silabs.com>
staging: wfx: fix possible panic with re-queued frames
Arnd Bergmann <arnd@arndb.de>
optee: simplify i2c access
Arnd Bergmann <arnd@arndb.de>
ARM: s3c: fix fiq for clang IAS
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: set enabled in the PPAG command properly
Artem Lapkin <email2tema@gmail.com>
arm64: dts: meson: fix broken wifi node for Khadas VIM3L
Vincent Knecht <vincent.knecht@mailoo.org>
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Luca Weiss <luca@z3ntu.xyz>
soc: qcom: ocmem: don't return NULL in of_get_ocmem
Jupeng Zhong <zhongjupeng@yulong.com>
Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Dmitry Osipenko <digetx@gmail.com>
opp: Correct debug message in _opp_add_static_v2()
Marek Behún <kabel@kernel.org>
arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to LEDs
Marc Kleine-Budde <mkl@pengutronix.de>
can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Geert Uytterhoeven <geert+renesas@glider.be>
arm64: dts: renesas: beacon: Fix EEPROM compatible value
Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Chen-Yu Tsai <wens@csie.org>
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Make "trimming xfer length" a debug message
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Abort transaction after errors with unknown reason
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Do not update data length if it is 0 on inbound transfers
Tony Lindgren <tony@atomide.com>
ARM: dts: Configure missing thermal interrupt for 4430
Pan Bian <bianpan2016@163.com>
memory: ti-aemif: Drop child node when jumping out loop
Pan Bian <bianpan2016@163.com>
Bluetooth: Put HCI device if inquiry procedure interrupts
Pan Bian <bianpan2016@163.com>
Bluetooth: drop HCI device reference before return
Borislav Petkov <bp@suse.de>
staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
Dan Carpenter <dan.carpenter@oracle.com>
soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
Robert Foss <robert.foss@linaro.org>
arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Jack Pham <jackp@codeaurora.org>
usb: gadget: u_audio: Free requests only after callback
Maximilian Luz <luzmaximilian@gmail.com>
ACPICA: Fix exception code class checks
Chen-Yu Tsai <wens@csie.org>
arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Free resources in error path
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: properly connect USB PHY to port 0
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix call site of scmi_notification_exit
Andrii Nakryiko <andrii@kernel.org>
bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
Andrii Nakryiko <andrii@kernel.org>
bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk transfers on 64-bit builds
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk userdata handling
Dinghao Liu <dinghao.liu@zju.edu.cn>
Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
Zhang Qilong <zhangqilong3@huawei.com>
memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
Christopher William Snowhill <chris@kode54.net>
Bluetooth: Fix initializing response id after clearing struct
Claire Chang <tientzu@chromium.org>
Bluetooth: hci_uart: Fix a race for write_work scheduling
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the probe function
Rakesh Pillai <pillair@codeaurora.org>
ath10k: Fix error handling in case of CE pipe init failure
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: One more flush for Baytrail clear residuals
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Don't call sync_stop if it hasn't been stopped
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Assure sync with the pending stop operation at suspend
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Call sync_stop at disconnection
Eric Biggers <ebiggers@google.com>
random: fix the RNDRESEEDCRNG ioctl
Nathan Chancellor <nathan@kernel.org>
vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
Alexander Lobakin <alobakin@pm.me>
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
Rokudo Yan <wu-yan@tcl.com>
zsmalloc: account the number of compacted pages correctly
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
Jan Kara <jack@suse.cz>
bfq: Avoid false bfq queue merging
Hans de Goede <hdegoede@redhat.com>
virt: vbox: Do not use wait_event_interruptible when called from kernel context
Ard Biesheuvel <ardb@kernel.org>
PCI: Decline to resize resources if boot config must be preserved
Ansuel Smith <ansuelsmth@gmail.com>
PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ivan Zaentsev <ivan.zaentsev@wirenboard.ru>
w1: w1_therm: Fix conversion result for negative temperatures
Sumit Garg <sumit.garg@linaro.org>
kdb: Make memory allocations more robust
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix mailbox Ch erroneous error
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: docs: Remove notify_ha_event()
Dave Jiang <dave.jiang@intel.com>
driver core: auxiliary bus: Fix calling stage for auxiliary bus init
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: do not attempt to create a new file before the filesystem is initalized
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: be more robust at handling improper input in debugfs_lookup()
Stefano Garzarella <sgarzare@redhat.com>
vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Nick Desaulniers <ndesaulniers@google.com>
vmlinux.lds.h: add DWARF v5 sections
-------------
Diffstat:
Documentation/admin-guide/perf/arm-cmn.rst | 2 +-
Documentation/admin-guide/sysctl/vm.rst | 10 +-
Documentation/filesystems/seq_file.rst | 6 +
Documentation/scsi/libsas.rst | 10 +-
Documentation/security/keys/core.rst | 4 +-
Makefile | 4 +-
arch/arm/boot/compressed/head.S | 4 +-
arch/arm/boot/dts/armada-388-helios4.dts | 28 +-
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/arm/boot/dts/tegra30-ouya.dts | 4 +-
arch/arm/kernel/sys_oabi-compat.c | 15 +
arch/arm/mach-at91/pm_suspend.S | 2 +-
arch/arm/mach-ixp4xx/Kconfig | 1 -
arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9 +-
arch/arm64/Kconfig | 2 +-
.../boot/dts/allwinner/sun50i-a64-pinebook.dts | 5 +-
.../boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 -
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 +-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7 +
.../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7 +-
arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi | 2 +-
.../boot/dts/exynos/exynos5433-tm2-common.dtsi | 2 +-
arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +-
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4 +-
.../boot/dts/marvell/armada-3720-turris-mox.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +
arch/arm64/boot/dts/mediatek/mt8183.dtsi | 10 +-
.../dts/qcom/msm8916-samsung-a2015-common.dtsi | 6 +
.../boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2 +-
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 15 +-
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 +-
arch/arm64/boot/dts/qcom/sm8250.dtsi | 2 +-
.../boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +-
.../arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4 +-
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 +
arch/arm64/crypto/aes-glue.c | 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/include/asm/module.lds.h | 6 +-
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/head.S | 1 +
arch/arm64/kernel/machine_kexec_file.c | 4 +-
arch/arm64/kernel/probes/uprobes.c | 2 +-
arch/arm64/kernel/ptrace.c | 2 +-
arch/arm64/kernel/suspend.c | 2 +-
arch/csky/kernel/ptrace.c | 2 +-
arch/mips/Makefile | 19 +
arch/mips/boot/compressed/Makefile | 1 +
arch/mips/cavium-octeon/setup.c | 9 +-
arch/mips/include/asm/asm.h | 18 +
arch/mips/include/asm/atomic.h | 2 +-
arch/mips/include/asm/cmpxchg.h | 6 +-
arch/mips/include/asm/page.h | 6 +
arch/mips/kernel/cpu-probe.c | 15 +-
arch/mips/kernel/relocate.c | 10 +
arch/mips/kernel/setup.c | 3 +
arch/mips/kernel/vmlinux.lds.S | 2 +-
arch/mips/lantiq/irq.c | 2 +-
arch/mips/loongson64/Platform | 22 -
arch/mips/mm/c-r4k.c | 2 +-
arch/mips/vdso/Makefile | 5 +-
arch/nios2/kernel/entry.S | 3 +
arch/nios2/kernel/sys_nios2.c | 11 +-
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/kexec.h | 1 +
arch/powerpc/include/asm/paravirt.h | 1 +
arch/powerpc/include/asm/uaccess.h | 13 +-
arch/powerpc/kernel/entry_32.S | 3 +
arch/powerpc/kernel/head_32.h | 2 +-
arch/powerpc/kernel/head_8xx.S | 2 +-
arch/powerpc/kernel/head_book3s_32.S | 6 -
arch/powerpc/kernel/irq.c | 27 +-
arch/powerpc/kernel/prom_init.c | 12 +-
arch/powerpc/kernel/time.c | 2 +
arch/powerpc/kexec/elf_64.c | 2 +-
arch/powerpc/kexec/file_load_64.c | 35 ++
arch/powerpc/kvm/Kconfig | 1 +
arch/powerpc/kvm/powerpc.c | 8 +-
arch/powerpc/lib/sstep.c | 101 +++-
arch/powerpc/platforms/pseries/dlpar.c | 7 +-
arch/riscv/kernel/vdso/Makefile | 3 +-
arch/s390/kernel/vtime.c | 3 +-
arch/sparc/Kconfig | 2 +-
arch/sparc/kernel/led.c | 2 +
arch/sparc/lib/memset.S | 1 +
arch/um/include/shared/skas/mm_id.h | 1 +
arch/um/kernel/tlb.c | 19 +-
arch/um/os-Linux/skas/process.c | 4 +
arch/x86/crypto/aesni-intel_glue.c | 28 +-
arch/x86/entry/common.c | 2 +-
arch/x86/include/asm/virtext.h | 17 +-
arch/x86/kernel/cpu/sgx/main.c | 14 +-
arch/x86/kernel/msr.c | 7 +
arch/x86/kernel/reboot.c | 30 +-
arch/x86/kvm/emulate.c | 4 +-
arch/x86/kvm/mmu/tdp_mmu.c | 3 +-
arch/x86/kvm/svm/nested.c | 22 +-
arch/x86/kvm/svm/svm.c | 8 +-
arch/x86/kvm/x86.c | 1 +
arch/x86/mm/fault.c | 27 +-
arch/x86/mm/pat/memtype.c | 4 +-
block/bfq-iosched.c | 1 +
block/blk-settings.c | 12 +
block/bsg.c | 4 +-
block/genhd.c | 2 +-
block/ioctl.c | 21 +-
certs/blacklist.c | 2 +-
crypto/ecdh_helper.c | 3 +
crypto/michael_mic.c | 31 +-
drivers/acpi/acpi_configfs.c | 7 +-
drivers/acpi/property.c | 44 +-
drivers/amba/bus.c | 20 +-
drivers/ata/ahci_brcm.c | 14 +-
drivers/auxdisplay/Kconfig | 3 -
drivers/auxdisplay/ht16k33.c | 3 +-
drivers/base/auxiliary.c | 13 +-
drivers/base/base.h | 5 +
drivers/base/init.c | 1 +
drivers/base/regmap/regmap-sdw.c | 4 +-
drivers/base/swnode.c | 8 +-
drivers/block/floppy.c | 30 +-
drivers/block/zram/zram_drv.c | 2 +-
drivers/bluetooth/btqcomsmd.c | 27 +-
drivers/bluetooth/btusb.c | 20 +-
drivers/bluetooth/hci_ldisc.c | 41 +-
drivers/bluetooth/hci_qca.c | 33 +-
drivers/bluetooth/hci_serdev.c | 4 +-
drivers/bus/mhi/core/init.c | 3 +
drivers/char/hw_random/ingenic-trng.c | 6 +-
drivers/char/hw_random/timeriomem-rng.c | 2 +-
drivers/char/random.c | 2 +-
drivers/char/tpm/tpm.h | 4 -
drivers/char/tpm/tpm_tis_core.c | 50 +-
drivers/clk/clk-ast2600.c | 37 +-
drivers/clk/clk-divider.c | 9 +-
drivers/clk/meson/clk-pll.c | 10 +-
drivers/clk/qcom/gcc-msm8998.c | 100 ++--
drivers/clk/qcom/gcc-sc7180.c | 47 +-
drivers/clk/qcom/lpass-gfm-sm8250.c | 8 +-
drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +-
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/mxs_timer.c | 5 +-
drivers/cpufreq/acpi-cpufreq.c | 62 +-
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +-
drivers/cpufreq/freq_table.c | 8 +-
drivers/cpufreq/intel_pstate.c | 21 +-
drivers/cpufreq/qcom-cpufreq-hw.c | 40 +-
.../crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 +++---
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2 +
drivers/crypto/bcm/cipher.c | 2 +-
drivers/crypto/bcm/cipher.h | 4 +-
drivers/crypto/bcm/util.c | 2 +-
drivers/crypto/qat/Kconfig | 2 +-
drivers/crypto/talitos.c | 50 +-
drivers/crypto/talitos.h | 1 +
drivers/dax/bus.c | 2 +-
drivers/dma/fsldma.c | 6 +
drivers/dma/hsu/pci.c | 21 +-
drivers/dma/idxd/dma.c | 1 +
drivers/dma/owl-dma.c | 1 +
drivers/dma/qcom/gpi.c | 2 +-
drivers/dma/ti/k3-udma.c | 1 +
drivers/firmware/arm_scmi/driver.c | 4 +-
drivers/gpio/gpio-pcf857x.c | 2 +-
drivers/gpu/drm/Kconfig | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +-
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 22 +-
drivers/gpu/drm/amd/amdgpu/soc15.c | 2 +
.../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2 +-
.../gpu/drm/amd/display/dc/bios/command_table.c | 61 ++
drivers/gpu/drm/amd/display/dc/core/dc.c | 27 +-
drivers/gpu/drm/amd/display/dc/dc_stream.h | 3 +-
.../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14 +
.../drm/amd/display/dc/dce/dce_stream_encoder.c | 1 +
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8 +-
.../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1 -
.../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +
.../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 +
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +-
drivers/gpu/drm/drm_dp_mst_topology.c | 3 +-
drivers/gpu/drm/drm_fb_helper.c | 15 +-
drivers/gpu/drm/drm_modes.c | 4 +-
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +-
drivers/gpu/drm/gma500/psb_drv.c | 2 +
drivers/gpu/drm/i915/display/intel_hdmi.c | 6 +-
drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12 +-
drivers/gpu/drm/lima/lima_sched.c | 2 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8 +
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 10 +-
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 10 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +-
drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 5 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +-
drivers/gpu/drm/msm/msm_drv.c | 3 +-
drivers/gpu/drm/msm/msm_gem_submit.c | 2 +
drivers/gpu/drm/msm/msm_kms.h | 8 +-
.../drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 +
drivers/gpu/drm/nouveau/nouveau_chan.c | 1 +
drivers/gpu/drm/nouveau/nouveau_connector.c | 1 +
drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3 +-
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5 +
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 59 +-
drivers/gpu/drm/rcar-du/rcar_cmm.c | 2 +-
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 +-
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 +-
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 30 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11 +
drivers/gpu/drm/scheduler/sched_main.c | 3 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 +-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/tegra/dc.c | 2 +-
drivers/gpu/drm/tegra/dsi.c | 2 +-
drivers/gpu/drm/tegra/hdmi.c | 2 +-
drivers/gpu/drm/tegra/hub.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 2 +-
drivers/gpu/drm/tegra/vic.c | 2 +-
drivers/gpu/drm/ttm/ttm_bo.c | 9 +-
drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++-
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +-
drivers/gpu/drm/virtio/virtgpu_gem.c | 8 +-
drivers/gpu/drm/virtio/virtgpu_kms.c | 1 +
drivers/hid/hid-core.c | 3 +
drivers/hid/hid-logitech-dj.c | 1 +
drivers/hid/wacom_wac.c | 7 +-
drivers/hsi/controllers/omap_ssi_core.c | 2 +-
drivers/hv/channel_mgmt.c | 3 +-
drivers/hwtracing/coresight/coresight-etm4x-core.c | 21 +-
.../hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +-
drivers/i2c/busses/i2c-bcm-iproc.c | 231 ++++++--
drivers/i2c/busses/i2c-brcmstb.c | 2 +-
drivers/i2c/busses/i2c-exynos5.c | 8 +-
drivers/i2c/busses/i2c-qcom-geni.c | 93 ++-
drivers/i3c/master/Kconfig | 1 +
drivers/ide/falconide.c | 3 +-
drivers/infiniband/core/cm.c | 8 +-
drivers/infiniband/core/cma.c | 70 ++-
drivers/infiniband/core/user_mad.c | 17 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 11 +-
drivers/infiniband/hw/hns/hns_roce_hem.c | 9 +-
drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 16 +
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 70 ++-
drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 3 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 19 +-
drivers/infiniband/hw/hns/hns_roce_mr.c | 56 +-
drivers/infiniband/hw/hns/hns_roce_qp.c | 37 +-
drivers/infiniband/hw/hns/hns_roce_srq.c | 52 +-
drivers/infiniband/hw/mlx5/devx.c | 4 +-
drivers/infiniband/hw/mlx5/main.c | 14 +-
drivers/infiniband/hw/mlx5/qp.c | 27 +-
drivers/infiniband/sw/rxe/rxe_net.c | 5 +
drivers/infiniband/sw/rxe/rxe_recv.c | 27 +-
drivers/infiniband/sw/siw/siw.h | 2 +-
drivers/infiniband/sw/siw/siw_main.c | 2 +-
drivers/infiniband/sw/siw/siw_qp.c | 271 +++++----
drivers/infiniband/sw/siw/siw_qp_rx.c | 26 +-
drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +-
drivers/infiniband/sw/siw/siw_verbs.c | 20 +-
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2 +
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51 +-
drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1 +
drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 120 ++--
drivers/infiniband/ulp/rtrs/rtrs.c | 28 +-
drivers/input/joydev.c | 7 +-
drivers/input/joystick/xpad.c | 1 +
drivers/input/keyboard/Kconfig | 2 +-
drivers/input/misc/da7280.c | 3 +
drivers/input/serio/i8042-x86ia64io.h | 4 +
drivers/input/serio/serport.c | 4 +-
drivers/input/touchscreen/elo.c | 4 +-
drivers/input/touchscreen/raydium_i2c_ts.c | 3 +-
drivers/input/touchscreen/st1232.c | 9 +-
drivers/input/touchscreen/sur40.c | 1 +
drivers/input/touchscreen/zinitix.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 +
drivers/iommu/iommu.c | 23 +-
drivers/iommu/mtk_iommu.c | 2 +-
drivers/irqchip/Kconfig | 3 +-
drivers/irqchip/irq-loongson-pch-msi.c | 2 +-
drivers/irqchip/irq-ls-extirq.c | 2 +-
drivers/macintosh/adb-iop.c | 6 +-
drivers/mailbox/arm_mhuv2.c | 4 +-
drivers/mailbox/sprd-mailbox.c | 2 +-
drivers/md/bcache/bcache.h | 3 +
drivers/md/bcache/btree.c | 21 +-
drivers/md/bcache/journal.c | 4 +-
drivers/md/bcache/super.c | 20 +
drivers/md/dm-core.h | 4 +
drivers/md/dm-crypt.c | 1 +
drivers/md/dm-era-target.c | 93 +--
drivers/md/dm-table.c | 168 +++---
drivers/md/dm-writecache.c | 74 ++-
drivers/md/dm.c | 62 +-
drivers/md/dm.h | 2 +-
drivers/media/i2c/Kconfig | 1 +
drivers/media/i2c/max9286.c | 2 +-
drivers/media/i2c/ov5670.c | 3 +-
drivers/media/pci/cx25821/cx25821-core.c | 4 +-
drivers/media/pci/intel/ipu3/Kconfig | 3 +-
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +-
drivers/media/pci/saa7134/saa7134-empress.c | 5 +-
drivers/media/pci/smipcie/smipcie-ir.c | 46 +-
drivers/media/platform/aspeed-video.c | 6 +-
drivers/media/platform/marvell-ccic/mcam-core.c | 2 +
.../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 +-
.../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3 +-
drivers/media/platform/pxa_camera.c | 3 +
drivers/media/platform/qcom/camss/camss-video.c | 3 +-
drivers/media/platform/ti-vpe/cal.c | 4 +-
drivers/media/platform/vsp1/vsp1_drv.c | 4 +-
drivers/media/rc/ir_toy.c | 1 +
drivers/media/rc/mceusb.c | 2 +-
drivers/media/test-drivers/vidtv/vidtv_psi.c | 5 +-
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/media/v4l2-core/v4l2-ioctl.c | 32 +-
drivers/memory/mtk-smi.c | 4 +-
drivers/memory/ti-aemif.c | 8 +-
drivers/mfd/altera-sysmgr.c | 3 +-
drivers/mfd/bd9571mwv.c | 6 +-
drivers/mfd/gateworks-gsc.c | 2 +-
drivers/mfd/wm831x-auxadc.c | 3 +-
drivers/misc/cardreader/rts5227.c | 5 +
drivers/misc/eeprom/eeprom_93xx46.c | 1 +
drivers/misc/fastrpc.c | 7 +-
drivers/misc/mei/bus.c | 7 +
drivers/misc/mei/hbm.c | 2 +-
drivers/misc/mei/hw-me-regs.h | 5 +
drivers/misc/mei/interrupt.c | 33 +-
drivers/misc/mei/pci-me.c | 5 +
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +-
drivers/mmc/host/owl-mmc.c | 9 +-
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +-
drivers/mmc/host/sdhci-esdhc-imx.c | 3 +-
drivers/mmc/host/sdhci-pci-o2micro.c | 20 +
drivers/mmc/host/sdhci-sprd.c | 6 +-
drivers/mmc/host/usdhi6rol0.c | 4 +-
drivers/mtd/devices/phram.c | 6 +-
drivers/mtd/nand/raw/intel-nand-controller.c | 6 +-
drivers/mtd/parsers/afs.c | 4 +-
drivers/mtd/parsers/parser_imagetag.c | 4 +
drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4 +-
drivers/mtd/spi-nor/core.c | 10 +-
drivers/mtd/spi-nor/sfdp.c | 5 +-
drivers/net/Kconfig | 2 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +-
drivers/net/dsa/ocelot/felix.c | 16 +-
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 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +-
.../chelsio/inline_crypto/chtls/chtls_cm.h | 3 -
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +-
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14 +-
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
drivers/net/ethernet/ibm/ibmvnic.c | 43 +-
drivers/net/ethernet/ibm/ibmvnic.h | 7 +-
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 62 +-
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 11 +-
drivers/net/ethernet/intel/i40e/i40e_xsk.c | 2 +-
drivers/net/ethernet/intel/ice/ice.h | 2 -
drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6 +-
drivers/net/ethernet/intel/ice/ice_ethtool.c | 34 +-
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33 +-
drivers/net/ethernet/marvell/mvneta.c | 9 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2 +-
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9 +
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 +++++---
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2 +-
.../mellanox/mlx5/core/en_accel/en_accel.h | 2 +-
.../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66 +--
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/fpga/ipsec.h | 2 +
drivers/net/ethernet/mellanox/mlx5/core/health.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 +-
drivers/net/ethernet/realtek/r8169_main.c | 4 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 +-
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26 +-
drivers/net/gtp.c | 1 -
drivers/net/ipa/ipa_main.c | 4 +-
drivers/net/phy/micrel.c | 1 +
drivers/net/phy/mscc/Makefile | 1 +
drivers/net/phy/mscc/mscc.h | 28 +
drivers/net/phy/mscc/mscc_main.c | 608 +++++++++++--------
drivers/net/phy/mscc/mscc_serdes.c | 650 +++++++++++++++++++++
drivers/net/phy/mscc/mscc_serdes.h | 31 +
drivers/net/phy/phy_device.c | 53 +-
drivers/net/phy/sfp.c | 100 ++--
drivers/net/ppp/ppp_async.c | 3 +-
drivers/net/ppp/ppp_synctty.c | 3 +-
drivers/net/vxlan.c | 11 +-
drivers/net/wireguard/device.c | 19 +-
drivers/net/wireguard/device.h | 15 +-
drivers/net/wireguard/peer.c | 28 +-
drivers/net/wireguard/peer.h | 4 +-
drivers/net/wireguard/queueing.c | 86 ++-
drivers/net/wireguard/queueing.h | 45 +-
drivers/net/wireguard/receive.c | 16 +-
drivers/net/wireguard/send.c | 31 +-
drivers/net/wireless/ath/ath10k/mac.c | 2 +
drivers/net/wireless/ath/ath10k/snoc.c | 5 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +
drivers/net/wireless/ath/ath11k/mac.c | 11 +-
drivers/net/wireless/ath/ath9k/debug.c | 5 +-
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43 +-
.../net/wireless/intel/iwlwifi/mvm/time-event.c | 3 -
.../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21 +-
drivers/net/xen-netback/interface.c | 8 +-
drivers/nvme/host/multipath.c | 4 +
drivers/nvme/target/admin-cmd.c | 33 +-
drivers/nvme/target/tcp.c | 59 +-
drivers/nvmem/core.c | 5 +-
drivers/nvmem/qcom-spmi-sdam.c | 7 +-
drivers/of/fdt.c | 12 +-
drivers/opp/of.c | 4 +-
drivers/pci/controller/cadence/pcie-cadence-host.c | 5 +-
drivers/pci/controller/dwc/pcie-qcom.c | 4 +-
drivers/pci/controller/pcie-rcar-host.c | 2 +-
drivers/pci/controller/pcie-rockchip.c | 12 +-
drivers/pci/controller/pcie-xilinx-cpm.c | 1 +
drivers/pci/pci-bridge-emul.c | 11 +-
drivers/pci/setup-res.c | 6 +
drivers/pci/syscall.c | 10 +-
drivers/perf/arm-cmn.c | 17 +-
drivers/phy/Kconfig | 1 +
drivers/phy/cadence/phy-cadence-torrent.c | 1 +
drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10 +-
drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +-
drivers/platform/chrome/cros_ec_proto.c | 12 +-
drivers/platform/x86/Kconfig | 4 +-
drivers/power/reset/at91-sama5d2_shdwc.c | 2 +-
drivers/power/supply/Kconfig | 1 +
drivers/power/supply/axp20x_usb_power.c | 2 +-
drivers/power/supply/cpcap-battery.c | 12 +-
drivers/power/supply/cpcap-charger.c | 4 +-
drivers/power/supply/smb347-charger.c | 12 +-
drivers/pwm/pwm-iqs620a.c | 8 +-
drivers/pwm/pwm-rockchip.c | 18 +-
drivers/regulator/axp20x-regulator.c | 7 +-
drivers/regulator/core.c | 6 +-
drivers/regulator/qcom-rpmh-regulator.c | 26 +
drivers/regulator/rohm-regulator.c | 9 +-
drivers/regulator/s5m8767.c | 15 +-
drivers/remoteproc/mtk_common.h | 1 +
drivers/remoteproc/mtk_scp.c | 20 +-
drivers/rtc/Kconfig | 3 +-
drivers/rtc/rtc-rx6110.c | 4 +-
drivers/s390/crypto/zcrypt_api.c | 14 +
drivers/s390/virtio/virtio_ccw.c | 4 +-
drivers/scsi/aic94xx/aic94xx_scb.c | 20 +-
drivers/scsi/bnx2fc/Kconfig | 1 +
drivers/scsi/hisi_sas/hisi_sas_main.c | 12 +-
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 +-
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +-
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 3 +-
drivers/scsi/isci/port.c | 11 +-
drivers/scsi/libsas/sas_event.c | 66 ++-
drivers/scsi/libsas/sas_init.c | 27 +-
drivers/scsi/libsas/sas_internal.h | 5 +-
drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +-
drivers/scsi/mvsas/mv_sas.c | 25 +-
drivers/scsi/pm8001/pm8001_hwi.c | 40 +-
drivers/scsi/pm8001/pm8001_sas.c | 7 +-
drivers/scsi/pm8001/pm80xx_hwi.c | 35 +-
drivers/scsi/qla2xxx/qla_dbg.c | 1 +
drivers/scsi/qla2xxx/qla_mbx.c | 3 +-
drivers/scsi/sd.c | 6 +-
drivers/scsi/sd_zbc.c | 6 +-
drivers/scsi/ufs/ufshcd.c | 17 +-
drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +-
drivers/soc/aspeed/aspeed-socinfo.c | 33 +-
drivers/soc/qcom/ocmem.c | 8 +-
drivers/soc/qcom/socinfo.c | 2 +-
drivers/soc/samsung/exynos-asv.c | 18 +-
drivers/soc/ti/pm33xx.c | 5 +-
drivers/soundwire/bus.c | 47 +-
drivers/soundwire/cadence_master.c | 8 +-
drivers/soundwire/debugfs.c | 2 +-
drivers/soundwire/intel_init.c | 3 +-
drivers/spi/spi-atmel.c | 2 +-
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-dw-bt1.c | 2 +-
drivers/spi/spi-fsl-spi.c | 2 +-
drivers/spi/spi-imx.c | 2 +-
drivers/spi/spi-pxa2xx-pci.c | 27 +-
drivers/spi/spi-stm32.c | 4 +
drivers/spi/spi-synquacer.c | 4 +
drivers/spi/spi.c | 2 +-
drivers/spmi/spmi-pmic-arb.c | 5 +-
drivers/staging/gdm724x/gdm_usb.c | 10 +-
drivers/staging/media/allegro-dvt/allegro-core.c | 3 +-
drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24 +-
drivers/staging/media/atomisp/pci/hmm/hmm.c | 2 +-
drivers/staging/media/imx/imx-media-csc-scaler.c | 4 -
drivers/staging/media/imx/imx-media-dev.c | 7 +-
drivers/staging/media/imx/imx7-media-csi.c | 27 +-
drivers/staging/mt7621-dma/Makefile | 2 +-
.../mt7621-dma/{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 +-
.../vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 +-
drivers/staging/wfx/data_tx.c | 10 +-
drivers/staging/wfx/data_tx.h | 1 +
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-
drivers/tee/optee/rpc.c | 31 +-
drivers/thermal/cpufreq_cooling.c | 2 +-
drivers/tty/n_gsm.c | 3 +-
drivers/tty/n_hdlc.c | 60 +-
drivers/tty/n_null.c | 3 +-
drivers/tty/n_r3964.c | 10 +-
drivers/tty/n_tracerouter.c | 4 +-
drivers/tty/n_tracesink.c | 4 +-
drivers/tty/n_tty.c | 82 ++-
drivers/tty/serial/stm32-usart.c | 24 +-
drivers/tty/tty_io.c | 82 ++-
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/usb/serial/pl2303.c | 8 +-
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
drivers/vfio/pci/vfio_pci_zdev.c | 4 +
drivers/vfio/vfio_iommu_type1.c | 48 +-
drivers/video/fbdev/Kconfig | 2 +-
drivers/virt/vboxguest/vboxguest_utils.c | 18 +-
drivers/w1/slaves/w1_therm.c | 22 +-
drivers/watchdog/intel-mid_wdt.c | 8 +-
drivers/watchdog/mei_wdt.c | 1 +
drivers/watchdog/qcom-wdt.c | 13 +-
fs/affs/namei.c | 4 +-
fs/btrfs/backref.c | 9 +-
fs/btrfs/backref.h | 9 +-
fs/btrfs/block-group.c | 29 +-
fs/btrfs/ctree.c | 7 +-
fs/btrfs/delayed-ref.c | 56 +-
fs/btrfs/delayed-ref.h | 16 +-
fs/btrfs/extent-tree.c | 128 +---
fs/btrfs/free-space-cache.c | 6 +-
fs/btrfs/inode.c | 3 +-
fs/btrfs/relocation.c | 4 +-
fs/btrfs/space-info.h | 17 +
fs/ceph/caps.c | 10 +-
fs/cifs/cifs_swn.c | 2 +-
fs/cifs/connect.c | 259 ++++----
fs/cifs/dfs_cache.c | 33 +-
fs/cifs/fs_context.c | 43 +-
fs/debugfs/inode.c | 5 +-
fs/erofs/xattr.c | 10 +-
fs/erofs/zmap.c | 10 +-
fs/eventpoll.c | 4 +-
fs/exfat/exfat_raw.h | 4 +
fs/exfat/super.c | 31 +-
fs/ext4/Kconfig | 3 +-
fs/ext4/namei.c | 7 +-
fs/f2fs/compress.c | 5 +-
fs/f2fs/data.c | 12 +-
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 30 +-
fs/f2fs/inline.c | 4 +
fs/f2fs/super.c | 3 +
fs/gfs2/bmap.c | 6 +-
fs/gfs2/lock_dlm.c | 8 +-
fs/gfs2/recovery.c | 4 +-
fs/gfs2/util.c | 16 +-
fs/io_uring.c | 17 +-
fs/isofs/dir.c | 1 +
fs/isofs/namei.c | 1 +
fs/jffs2/summary.c | 3 +
fs/jfs/jfs_dmap.c | 2 +-
fs/nfs/nfs4proc.c | 15 +-
fs/nfsd/nfsctl.c | 14 +-
fs/ocfs2/cluster/heartbeat.c | 8 +-
fs/proc/proc_sysctl.c | 4 +-
fs/proc/self.c | 2 +-
fs/proc/task_mmu.c | 9 +-
fs/proc/thread_self.c | 7 +
fs/pstore/platform.c | 4 +-
fs/quota/quota_v2.c | 11 +-
fs/ubifs/auth.c | 2 +-
fs/ubifs/replay.c | 4 +-
fs/ubifs/super.c | 4 +-
fs/zonefs/super.c | 3 +
include/acpi/acexcep.h | 10 +-
include/asm-generic/vmlinux.lds.h | 16 +-
include/linux/bpf.h | 8 +-
include/linux/device-mapper.h | 5 +
include/linux/entry-kvm.h | 14 +
include/linux/eventpoll.h | 2 +-
include/linux/filter.h | 2 +-
include/linux/icmpv6.h | 28 +-
include/linux/iommu.h | 4 +-
include/linux/ipv6.h | 1 -
include/linux/kexec.h | 5 +
include/linux/key.h | 1 +
include/linux/kgdb.h | 2 +
include/linux/khugepaged.h | 2 +
include/linux/memremap.h | 6 +
include/linux/mfd/rohm-generic.h | 14 +-
include/linux/rcupdate.h | 2 +
include/linux/rmap.h | 3 +-
include/linux/soundwire/sdw.h | 2 +
include/linux/tpm.h | 5 +-
include/linux/tty_ldisc.h | 3 +-
include/linux/zsmalloc.h | 2 +-
include/net/act_api.h | 6 +-
include/net/icmp.h | 6 +-
include/net/tcp.h | 9 +-
include/scsi/libsas.h | 11 +-
include/uapi/drm/drm_fourcc.h | 4 +-
include/uapi/drm/drm_mode.h | 13 +-
init/Kconfig | 11 +
init/main.c | 1 +
kernel/Makefile | 2 +-
kernel/bpf/bpf_iter.c | 2 +-
kernel/bpf/bpf_lru_list.c | 7 +-
kernel/bpf/devmap.c | 4 +-
kernel/bpf/verifier.c | 3 +-
kernel/debug/debug_core.c | 11 +
kernel/debug/kdb/kdb_private.h | 2 +-
kernel/entry/common.c | 7 +
kernel/kcsan/core.c | 26 +-
kernel/kexec_file.c | 5 +
kernel/kprobes.c | 31 +-
kernel/locking/lockdep.c | 3 +-
kernel/module.c | 164 +++++-
kernel/module_signature.c | 2 +-
kernel/module_signing.c | 2 +-
kernel/printk/printk.c | 28 +-
kernel/printk/printk_safe.c | 16 +-
kernel/rcu/tree.c | 53 +-
kernel/rcu/tree.h | 2 +-
kernel/rcu/tree_plugin.h | 31 +-
kernel/sched/fair.c | 45 +-
kernel/sched/idle.c | 1 +
kernel/seccomp.c | 2 +
kernel/smp.c | 4 +
kernel/tracepoint.c | 80 ++-
mm/compaction.c | 43 +-
mm/hugetlb.c | 14 +-
mm/khugepaged.c | 22 +-
mm/memcontrol.c | 30 +-
mm/memory-failure.c | 6 +
mm/memory.c | 16 +-
mm/memremap.c | 15 +
mm/slab_common.c | 4 +-
mm/slub.c | 8 +-
mm/vmscan.c | 9 +-
mm/zsmalloc.c | 17 +-
net/bluetooth/a2mp.c | 3 +-
net/bluetooth/hci_core.c | 6 +-
net/bluetooth/hci_request.c | 25 +-
net/core/filter.c | 13 +-
net/ipv4/icmp.c | 5 +-
net/ipv6/icmp.c | 18 +-
net/ipv6/ip6_icmp.c | 12 +-
net/mac80211/mesh_hwmp.c | 2 +-
net/nfc/nci/uart.c | 3 +-
net/qrtr/tun.c | 12 +-
net/sched/act_api.c | 106 ++--
net/sched/cls_api.c | 12 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 6 +-
samples/Kconfig | 2 +-
samples/watch_queue/watch_test.c | 2 +-
security/commoncap.c | 12 +-
security/integrity/evm/evm_crypto.c | 7 +-
security/integrity/ima/ima_kexec.c | 3 +
security/integrity/ima/ima_mok.c | 5 +-
security/keys/Kconfig | 8 +-
security/keys/key.c | 2 +
security/keys/trusted-keys/trusted_tpm1.c | 22 +-
security/keys/trusted-keys/trusted_tpm2.c | 22 +-
security/selinux/hooks.c | 4 +
sound/core/init.c | 4 +
sound/core/pcm.c | 4 +
sound/core/pcm_local.h | 1 +
sound/core/pcm_native.c | 27 +-
sound/firewire/fireface/ff-protocol-latter.c | 118 +++-
sound/pci/hda/hda_intel.c | 2 +
sound/pci/hda/patch_hdmi.c | 1 -
sound/pci/hda/patch_realtek.c | 40 ++
sound/soc/codecs/cpcap.c | 12 +-
sound/soc/codecs/cs42l56.c | 3 +-
sound/soc/codecs/max98373.c | 2 +-
sound/soc/codecs/rt5682-i2c.c | 3 +
sound/soc/codecs/wsa881x.c | 1 +
sound/soc/fsl/Kconfig | 1 +
sound/soc/generic/simple-card-utils.c | 13 +-
sound/soc/intel/boards/sof_sdw.c | 9 +-
sound/soc/qcom/lpass-apq8016.c | 2 +-
sound/soc/qcom/lpass-cpu.c | 30 +-
sound/soc/qcom/lpass-lpaif-reg.h | 3 -
sound/soc/qcom/lpass-sc7180.c | 2 +-
sound/soc/qcom/lpass.h | 1 -
sound/soc/qcom/qdsp6/q6asm-dai.c | 21 +
sound/soc/qcom/qdsp6/q6routing.c | 18 -
sound/soc/sh/siu.h | 2 +-
sound/soc/sh/siu_pcm.c | 2 +-
sound/soc/sof/debug.c | 2 +-
sound/soc/sof/intel/hda-dsp.c | 4 +
sound/soc/sof/sof-pci-dev.c | 7 +
sound/usb/card.h | 2 +-
sound/usb/endpoint.c | 87 +--
sound/usb/implicit.c | 2 +
sound/usb/pcm.c | 7 +-
tools/lib/bpf/libbpf.c | 22 +-
tools/objtool/arch/x86/special.c | 2 +-
tools/objtool/check.c | 15 +-
tools/objtool/check.h | 11 +
tools/perf/builtin-record.c | 2 +-
.../pmu-events/arch/arm64/ampere/emag/cache.json | 2 +-
tools/perf/tests/sample-parsing.c | 2 +-
tools/perf/util/cgroup.c | 8 +-
tools/perf/util/event.c | 2 +
tools/perf/util/evlist.c | 8 +
tools/perf/util/evlist.h | 4 +
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 41 +-
.../perf/util/intel-pt-decoder/intel-pt-decoder.h | 2 +
tools/perf/util/intel-pt.c | 29 +-
tools/perf/util/symbol.c | 7 +-
tools/perf/util/unwind-libdw.c | 11 +-
tools/testing/kunit/kunit_tool_test.py | 14 +-
tools/testing/scatterlist/main.c | 1 -
.../selftests/bpf/prog_tests/btf_map_in_map.c | 33 --
tools/testing/selftests/bpf/test_progs.c | 13 +-
tools/testing/selftests/bpf/test_progs.h | 1 +
tools/testing/selftests/bpf/test_xdp_redirect.sh | 10 +-
tools/testing/selftests/dmabuf-heaps/Makefile | 2 +-
.../trigger-synthetic_event_syntax_errors.tc | 35 +-
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 +-
tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +-
tools/testing/selftests/seccomp/seccomp_bpf.c | 2 +-
tools/testing/selftests/wireguard/netns.sh | 15 +-
780 files changed, 7977 insertions(+), 3978 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.10 000/663] 5.10.20-rc1 review
@ 2021-03-01 16:04 1% Greg Kroah-Hartman
2021-03-01 16:09 7% ` [PATCH 5.10 316/663] watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready Greg Kroah-Hartman
0 siblings, 1 reply; 200+ results
From: Greg Kroah-Hartman @ 2021-03-01 16:04 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, stable
This is the start of the stable review cycle for the 5.10.20 release.
There are 663 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Wed, 03 Mar 2021 16:09:49 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.20-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.20-rc1
Cong Wang <cong.wang@bytedance.com>
net_sched: fix RTNL deadlock again caused by request_module()
Takeshi Misawa <jeliantsurux@gmail.com>
net: qrtr: Fix memory leak in qrtr_tun_open
Vlad Buslov <vladbu@nvidia.com>
net: sched: fix police ext initialization
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: queueing: get rid of per-peer ring buffers
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: selftests: test multiple parallel streams
Jason A. Donenfeld <Jason@zx2c4.com>
net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
Leon Romanovsky <leon@kernel.org>
ipv6: silence compilation warning for non-IPV6 builds
Sumit Garg <sumit.garg@linaro.org>
kgdb: fix to kill breakpoints on initmem after boot
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/i915: Reject 446-480MHz HDMI clock on GLK
Nikos Tsironis <ntsironis@arrikto.com>
dm era: only resize metadata in preresume
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Reinitialize bitset cache before digesting a new writeset
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Use correct value size in equality function of writeset tree
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Fix bitset memory leaks
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Verify the data block size hasn't changed
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Update in-core bitset after committing the metadata
Nikos Tsironis <ntsironis@arrikto.com>
dm era: Recover committed writeset after crash
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix writing beyond end of underlying device when shrinking
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: return the exact table values that were set
Mikulas Patocka <mpatocka@redhat.com>
dm writecache: fix performance degradation in ssd mode
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix zoned iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix DAX iterate_devices based device capability checks
Jeffle Xu <jefflexu@linux.alibaba.com>
dm table: fix iterate_devices based device capability checks
Mikulas Patocka <mpatocka@redhat.com>
dm: fix deadlock when swapping to encrypted device
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
Andreas Gruenbacher <agruenba@redhat.com>
gfs2: Lock imbalance on error path in gfs2_recover_one
Bob Peterson <rpeterso@redhat.com>
gfs2: Don't skip dlm unlock if glock has an lvb
Bob Peterson <rpeterso@redhat.com>
gfs2: fix glock confusion in function signal_our_withdraw
Masahisa Kojima <masahisa.kojima@linaro.org>
spi: spi-synquacer: fix set_cs handling
Rasmus Villemoes <rasmus.villemoes@prevas.dk>
spi: fsl: invert spisel_boot signal on MPC8309
Al Viro <viro@zeniv.linux.org.uk>
sparc32: fix a user-triggerable oops in clear_user()
Jaegeuk Kim <jaegeuk@kernel.org>
f2fs: flush data when enabling checkpoint back
Chao Yu <chao@kernel.org>
f2fs: enforce the immutable flag on open files
Chao Yu <chao@kernel.org>
f2fs: fix out-of-repair __setattr_copy()
Huacai Chen <chenhuacai@loongson.cn>
irqchip/loongson-pch-msi: Use bitmap_zalloc() to allocate bitmap
Johannes Berg <johannes.berg@intel.com>
um: defer killing userspace on page table update failures
Johannes Berg <johannes.berg@intel.com>
um: mm: check more comprehensively for stub changes
Cornelia Huck <cohuck@redhat.com>
virtio/s390: implement virtio-ccw revision 2 correctly
Heiko Carstens <hca@linux.ibm.com>
s390/vtime: fix inline assembly clobber list
Jens Axboe <axboe@kernel.dk>
proc: don't allow async path resolution of /proc/thread-self components
Chen Yu <yu.c.chen@intel.com>
cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if available
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: intel_pstate: Change intel_pstate_get_hwp_max() argument
Shawn Guo <shawn.guo@linaro.org>
cpufreq: qcom-hw: drop devm_xxx() calls from init/exit hooks
Viresh Kumar <viresh.kumar@linaro.org>
thermal: cpufreq_cooling: freq_qos_update_request() returns < 0 on error
Chris Wilson <chris@chris-wilson.co.uk>
kcmp: Support selection of SYS_kcmp without CHECKPOINT_RESTORE
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
zonefs: Fix file size of zones in full condition
Namjae Jeon <namjae.jeon@samsung.com>
exfat: fix shift-out-of-bounds in exfat_fill_super()
Muchun Song <songmuchun@bytedance.com>
printk: fix deadlock when kernel panic
Tim Harvey <tharvey@gateworks.com>
mfd: gateworks-gsc: Fix interrupt type
Maxim Kiselev <bigunclemax@gmail.com>
gpio: pcf857x: Fix missing first interrupt
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point LP DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: me: add adler lake point S DID
Tomas Winkler <tomas.winkler@intel.com>
mei: me: emmitsburg workstation DID
Alexander Usyskin <alexander.usyskin@intel.com>
mei: fix transfer over dma with extended header
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
spmi: spmi-pmic-arb: Fix hw_irq overflow
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32s: Add missing call to kuep_lock on syscall entry
Hari Bathini <hbathini@linux.ibm.com>
powerpc/kexec_file: fix FDT size estimation for kdump kernel
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/32: Preserve cr1 in exception prolog stack check to fix build error
Shirley Her <shirley.her@bayhubtech.com>
mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure
Frank Li <Frank.Li@nxp.com>
mmc: sdhci-esdhc-imx: fix kernel panic when remove module
Fangrui Song <maskray@google.com>
module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
Subbaraman Narayanamurthy <subbaram@codeaurora.org>
nvmem: qcom-spmi-sdam: Fix uninitialized pdev pointer
Paolo Bonzini <pbonzini@redhat.com>
KVM: nSVM: fix running nested guests when npt=0
Vlastimil Babka <vbabka@suse.cz>
mm, compaction: make fast_isolate_freepages() stay within zone
Dave Hansen <dave.hansen@linux.intel.com>
mm/vmscan: restore zone_reclaim_mode ABI
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix copy_huge_page_from_user contig page struct assumption
Mike Kravetz <mike.kravetz@oracle.com>
hugetlb: fix update_and_free_page contig page struct assumption
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix get_active_memcg return value
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix swap undercounting in cgroup2
NeilBrown <neilb@suse.de>
x86: fix seq_file iteration for pat/memtype.c
NeilBrown <neilb@suse.de>
seq_file: document how per-entry resources are managed.
Pan Bian <bianpan2016@163.com>
fs/affs: release old buffer head on error path
Pan Bian <bianpan2016@163.com>
mtd: spi-nor: hisi-sfc: Put child node np on error path
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Add erase size check for erase command initialization
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: core: Fix erase type discovery for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
mtd: spi-nor: sfdp: Fix last erase region marking
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Handle accesses to TRCSTALLCTLR
Alexander Usyskin <alexander.usyskin@intel.com>
watchdog: mei_wdt: request stop on unregister
Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
Tobias Klauser <tklauser@distanz.ch>
riscv: Disable KSAN_SANITIZE for vDSO
Will Deacon <will@kernel.org>
arm64: spectre: Prevent lockdep splat on v4 mitigation enable path
Shaoying Xu <shaoyi@amazon.com>
arm64 module: set plt* section addresses to 0x0
He Zhe <zhe.he@windriver.com>
arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
qiuguorui1 <qiuguorui1@huawei.com>
arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into() fails
Isaac J. Manjarres <isaacm@codeaurora.org>
iommu/arm-smmu-qcom: Fix mask extraction for bootloader programmed SMRs
Suzuki K Poulose <suzuki.poulose@arm.com>
arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
Masami Hiramatsu <mhiramat@kernel.org>
kprobes: Fix to delay the kprobes jump optimization
Frederic Weisbecker <frederic@kernel.org>
entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
entry: Explicitly flush pending rcuog wakeup before last rescheduling point
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Trigger self-IPI on late deferred wake up before user resume
Frederic Weisbecker <frederic@kernel.org>
rcu/nocb: Perform deferred wake up before last idle's need_resched() check
Frederic Weisbecker <frederic@kernel.org>
rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
Cédric Le Goater <clg@kaod.org>
powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
Thomas Gleixner <tglx@linutronix.de>
x86/entry: Fix instrumentation annotation
Andy Lutomirski <luto@kernel.org>
x86/fault: Fix AMD erratum #91 errata fixup for user code
Sean Christopherson <seanjc@google.com>
x86/reboot: Force all cpus to exit VMX root if VMX is supported
Sean Christopherson <seanjc@google.com>
x86/virt: Eat faults on VMXOFF in reboot flows
Sean Young <sean@mess.org>
media: smipcie: fix interrupt handling and IR timeout
Lubomir Rintel <lkundrak@v3.sk>
media: marvell-ccic: power up the device on mclk enable
Pavel Machek <pavel@denx.de>
media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
Sean Young <sean@mess.org>
media: ir_toy: add another IR Droid device
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: i2c: max9286: fix access to unallocated memory
Jiri Kosina <jkosina@suse.cz>
floppy: reintroduce O_NDELAY fix
Martin Kaiser <martin@kaiser.cx>
staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
Amey Narkhede <ameynarkhede03@gmail.com>
staging: gdm724x: Fix DMA from stack
Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
Dinh Nguyen <dinguyen@kernel.org>
arm64: dts: agilex: fix phy interface bit shift for gmac1 and gmac2
Frank Wunderlich <frank-w@public-files.de>
dts64: mt7622: fix slow sd card access
Jiri Bohac <jbohac@suse.cz>
pstore: Fix typo in compression option name
Sabyrzhan Tasbolatov <snovitoll@gmail.com>
drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
Ricky Wu <ricky_wu@realtek.com>
misc: rtsx: init of rts522a add OCP power off when no card is present
Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
Paul Cercueil <paul@crapouillou.net>
seccomp: Add missing return in non-void function
Krzysztof Kozlowski <krzk@kernel.org>
soc: samsung: exynos-asv: handle reading revision register error
Marek Szyprowski <m.szyprowski@samsung.com>
soc: samsung: exynos-asv: don't defer early on not-supported SoCs
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - initialize need_fallback
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - handle BigEndian for cipher
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - IV register does not work on A10 and A13
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - checking sg length is not sufficient
Ard Biesheuvel <ardb@kernel.org>
crypto: michael_mic - fix broken misalignment handling
Ard Biesheuvel <ardb@kernel.org>
crypto: aesni - prevent misaligned buffers on the stack
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/sha - add missing module aliases
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Correct surface base address for renderclear
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: Flush before changing register state
Filipe Manana <fdmanana@suse.com>
btrfs: fix extent buffer leak on failure to copy root
Josef Bacik <josef@toxicpanda.com>
btrfs: account for new extents being deleted in total_bytes_pinned
Josef Bacik <josef@toxicpanda.com>
btrfs: handle space_info::total_bytes_pinned inside the delayed ref itself
Josef Bacik <josef@toxicpanda.com>
btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
Josef Bacik <josef@toxicpanda.com>
btrfs: fix reloc root leak with 0 ref reloc roots on recovery
Josef Bacik <josef@toxicpanda.com>
btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
Josef Bacik <josef@toxicpanda.com>
btrfs: add asserts for deleting backref cache nodes
Josef Bacik <josef@toxicpanda.com>
btrfs: do not warn if we can't find the reloc root when looking up backref
Josef Bacik <josef@toxicpanda.com>
btrfs: do not cleanup upper nodes in btrfs_backref_cleanup_node
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Reserve TPM for seal and unseal operations
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix migratable=1 failing
Jarkko Sakkinen <jarkko@kernel.org>
KEYS: trusted: Fix incorrect handling of tpm_get_random()
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Clean up locality release
James Bottomley <James.Bottomley@HansenPartnership.com>
tpm_tis: Fix check_locality for correct locality acquisition
Gao Xiang <hsiangkao@redhat.com>
erofs: initialized fields can only be observed after bit is set
Amir Goldstein <amir73il@gmail.com>
selinux: fix inconsistency between inode_getxattr and inode_listsecurity
Takashi Iwai <tiwai@suse.de>
ASoC: siu: Fix build error by a wrong const prefix
Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
drm/rockchip: Require the YTR modifier for AFBC
Heiko Stuebner <heiko@sntech.de>
drm/panel: kd35t133: allow using non-continuous dsi clock
Andrey Grodzovsky <andrey.grodzovsky@amd.com>
drm/sched: Cancel and flush all outstanding jobs before finish.
Ville Syrjälä <ville.syrjala@linux.intel.com>
drm/modes: Switch to 64bit maths to avoid integer overflow
Karol Herbst <kherbst@redhat.com>
drm/nouveau/kms: handle mDP connectors
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
Felix Kuehling <Felix.Kuehling@amd.com>
drm/amdkfd: Fix recursive lock warnings
Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
Eric Bernstein <eric.bernstein@amd.com>
drm/amd/display: Remove Assert from dcn10_get_dig_frontend
Jan Kokemüller <jan.kokemueller@gmail.com>
drm/amd/display: Add FPU wrappers to dcn21_validate_bandwidth()
Alex Deucher <alexander.deucher@amd.com>
Revert "drm/amd/display: Update NV1x SR latency values"
Kai Krakow <kai@kaishome.de>
bcache: Move journal work to new flush wq
Kai Krakow <kai@kaishome.de>
bcache: Give btree_io_wq correct semantics again
Kai Krakow <kai@kaishome.de>
Revert "bcache: Kill btree_io_wq"
Kevin Hao <haokexin@gmail.com>
Revert "MIPS: Octeon: Remove special handling of CONFIG_MIPS_ELF_APPENDED_DTB=y"
Nathan Chancellor <natechancellor@gmail.com>
MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
Aurelien Jarno <aurelien@aurel32.net>
MIPS: Support binutils configured with --enable-mips-fix-loongson3-llsc=yes
Paul Cercueil <paul@crapouillou.net>
MIPS: Ingenic: Disable HPTLB for D0 XBurst CPUs too
Takashi Iwai <tiwai@suse.de>
ALSA: hda/realtek: Quirk for HP Spectre x360 14 amp setup
PeiSen Hou <pshou@realtek.com>
ALSA: hda/realtek: modify EAPD in the ALC886
Takashi Iwai <tiwai@suse.de>
ALSA: hda/hdmi: Drop bogus check at closing a stream
Kai Vehmanen <kai.vehmanen@linux.intel.com>
ALSA: hda: Add another CometLake-H PCI ID
Takashi Sakamoto <o-takashi@sakamocchi.jp>
ALSA: fireface: fix to parse sync status register of latter protocol
Mathias Kresin <dev@kresin.me>
phy: lantiq: rcu-usb2: wait after clock enable
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7720: fix error code in mos7720_write()
Dan Carpenter <dan.carpenter@oracle.com>
USB: serial: mos7840: fix error code in mos7840_write()
Johan Hovold <johan@kernel.org>
USB: serial: pl2303: fix line-speed handling on newer chips
Johan Hovold <johan@kernel.org>
USB: serial: ftdi_sio: fix FTX sub-integer prescaler
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
Thinh Nguyen <Thinh.Nguyen@synopsys.com>
usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
Paul Cercueil <paul@crapouillou.net>
usb: musb: Fix runtime PM race in musb_queue_resume_work
Lech Perczak <lech.perczak@gmail.com>
USB: serial: option: update interface mapping for ZTE P685M
James Reynolds <jr@memlen.com>
media: mceusb: Fix potential out-of-bounds shift
Marcos Paulo de Souza <mpdesouza@suse.com>
Input: i8042 - add ASUS Zenbook Flip to noselftest list
Dan Carpenter <dan.carpenter@oracle.com>
Input: joydev - prevent potential read overflow in ioctl
Olivier Crête <olivier.crete@ocrete.ca>
Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
jeffrey.lin <jeffrey.lin@rad-ic.com>
Input: raydium_ts_i2c - do not send zero length
Jason Gerecke <killertofu@gmail.com>
HID: wacom: Ignore attempts to overwrite the touch_max value from HID
Filipe Laíns <lains@riseup.net>
HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known
Qinglang Miao <miaoqinglang@huawei.com>
ACPI: configfs: add missing check after configfs_register_default_group()
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ACPI: property: Fix fwnode string properties matching
Marcin Ślusarz <marcin.slusarz@intel.com>
soundwire: intel: fix possible crash when no device is detected
Mikulas Patocka <mpatocka@redhat.com>
blk-settings: align max_sectors on "logical_block_size" boundary
Bart Van Assche <bvanassche@acm.org>
scsi: sd: Fix Opal support
Finn Thain <fthain@telegraphics.com.au>
ide/falconide: Fix module unload
Christoph Hellwig <hch@lst.de>
block: reopen the device in blkdev_reread_part
Johannes Thumshirn <johannes.thumshirn@wdc.com>
scsi: sd: sd_zbc: Don't pass GFP_NOIO to kvcalloc
Randy Dunlap <rdunlap@infradead.org>
scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
Zhenzhong Duan <zhenzhong.duan@gmail.com>
csky: Fix a size determination in gpr_get()
Josef Bacik <josef@toxicpanda.com>
proc: use kvzalloc for our kernel buffer
Miaohe Lin <linmiaohe@huawei.com>
mm/rmap: fix potential pte_unmap on an not mapped pte
Dan Williams <dan.j.williams@intel.com>
mm: fix memory_failure() handling of dax-namespace metadata
Rik van Riel <riel@surriel.com>
mm,thp,shmem: make khugepaged obey tmpfs mount flags
Mårten Lindahl <martenli@axis.com>
i2c: exynos5: Preserve high speed master code
Maxime Ripard <maxime@cerno.tech>
i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
Marc Zyngier <maz@kernel.org>
arm64: Add missing ISB after invalidating TLB in __primary_switch
Sean Christopherson <seanjc@google.com>
KVM: x86/mmu: Expand collapsible SPTE zap for TDP MMU to ZONE_DEVICE and HugeTLB pages
Sean Christopherson <seanjc@google.com>
KVM: SVM: Intercept INVPCID when it's disabled to inject #UD
Trond Myklebust <trond.myklebust@hammerspace.com>
NFSv4: Fixes for nfs4_bitmask_adjust()
Heiner Kallweit <hkallweit1@gmail.com>
r8169: fix jumbo packet handling on RTL8168e
Wonhyuk Yang <vvghjk1234@gmail.com>
mm/compaction: fix misbehaviors of fast_find_migrateblock()
Chen Wandun <chenwandun@huawei.com>
mm/hugetlb: suppress wrong warning info when alloc gigantic page
Miaohe Lin <linmiaohe@huawei.com>
mm/hugetlb: fix potential double free in hugetlb_register_node() error path
Miaohe Lin <linmiaohe@huawei.com>
mm/memory.c: fix potential pte_unmap_unlock pte error
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix slub memory accounting
Muchun Song <songmuchun@bytedance.com>
mm: memcontrol: fix NR_ANON_THPS accounting in charge moving
Dan Carpenter <dan.carpenter@oracle.com>
ocfs2: fix a use after free on error
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: kconfig: use arm chacha even with no neon
Jason A. Donenfeld <Jason@zx2c4.com>
wireguard: device: do not generate ICMP for non-IP packets
Taehee Yoo <ap420073@gmail.com>
vxlan: move debug check after netdev unregister
Chen-Yu Tsai <wens@csie.org>
PCI: rockchip: Make 'ep-gpios' DT property optional
Chuhong Yuan <hslester96@gmail.com>
net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
Song, Yoong Siang <yoong.siang.song@intel.com>
net: stmmac: fix CBS idleslope and sendslope calculation
Henry Tieman <henry.w.tieman@intel.com>
ice: update the number of available RSS queues
Dave Ertman <david.m.ertman@intel.com>
ice: Fix state bits on LLDP mode switch
Brett Creeley <brett.creeley@intel.com>
ice: Account for port VLAN in VF max packet size calculation
Dave Ertman <david.m.ertman@intel.com>
ice: report correct max number of TCs
Alex Williamson <alex.williamson@redhat.com>
vfio/type1: Use follow_pte()
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
pwm: iqs620a: Fix overflow and optimize calculations
Dan Carpenter <dan.carpenter@oracle.com>
octeontx2-af: Fix an off by one in rvu_dbg_qsize_write()
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix add TC filter for IPv6
Andreas Oetken <andreas.oetken@siemens.com>
nios2: fixed broken sys_clone syscall
Jann Horn <jannh@google.com>
Take mmap lock in cacheflush syscall
Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
i40e: Fix VFs not created
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix addition of RX filters after enabling FW LLDP agent
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Fix overwriting flow control settings during driver loading
Mateusz Palczewski <mateusz.palczewski@intel.com>
i40e: Add zero-initialization of AQ command structures
Slawomir Laba <slawomirx.laba@intel.com>
i40e: Fix flow for IPv6 next header (extension header)
Krzysztof Wilczyński <kw@linux.com>
PCI: cadence: Fix DMA range mapping early return error
Russell King <rmk+kernel@armlinux.org.uk>
PCI: pci-bridge-emul: Fix array overruns, improve safety
Shiyang Ruan <ruansy.fnst@cn.fujitsu.com>
device-dax: Fix default return code of range_parse()
Magnum Shan <magnum.shan@unisoc.com>
mailbox: sprd: correct definition of SPRD_OUTBOX_FIFO_FULL
Geert Uytterhoeven <geert@linux-m68k.org>
ext: EXT4_KUNIT_TESTS should depend on EXT4_FS instead of selecting it
Bard Liao <yung-chuan.liao@linux.intel.com>
regmap: sdw: use _no_pm functions in regmap_read/write
Tzung-Bi Shih <tzungbi@google.com>
remoteproc/mediatek: acknowledge watchdog IRQ after handled
Jonathan Marek <jonathan@marek.ca>
misc: fastrpc: fix incorrect usage of dma_map_sgtable
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: fix confusion on device used by pm_runtime
Bard Liao <yung-chuan.liao@linux.intel.com>
soundwire: export sdw_write/read_no_pm functions
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_write_no_pm when setting the bus scale registers
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: bus: use sdw_update_no_pm when initializing a device
Ahmad Fatoum <a.fatoum@pengutronix.de>
nvmem: core: skip child nodes not matching binding
Dan Carpenter <dan.carpenter@oracle.com>
nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
Suzuki K Poulose <suzuki.poulose@arm.com>
coresight: etm4x: Skip accessing TRCPDCR in save/restore
Geert Uytterhoeven <geert+renesas@glider.be>
phy: USB_LGM_PHY should depend on X86
Theodore Ts'o <tytso@mit.edu>
ext4: fix potential htree index checksum corruption
Max Gurtovoy <mgurtovoy@nvidia.com>
vfio-pci/zdev: fix possible segmentation fault issue
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Fix some sanity checks in detach group
Keqian Zhu <zhukeqian1@huawei.com>
vfio/iommu_type1: Populate full dirty when detach non-pinned group
Judy Hsiao <judyhsiao@google.com>
drm/msm/dp: trigger unplug event in msm_dp_display_disable
Eric Anholt <eric@anholt.net>
drm/msm: Fix races managing the OOB state for timestamp vs timestamps.
Eric Anholt <eric@anholt.net>
drm/msm: Fix race of GPU init vs timestamp power management.
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm/mdp5: Fix wait-for-commit for cmd panels
Konrad Dybcio <konrad.dybcio@somainline.org>
drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
Iskren Chernev <iskren.chernev@gmail.com>
drm/msm: Fix MSM_INFO_GET_IOVA with carveout
Alexander Usyskin <alexander.usyskin@intel.com>
mei: hbm: call mei_set_devstate() on hbm stop response
Heiner Kallweit <hkallweit1@gmail.com>
PCI: Align checking of syscall user config accessors
Jorgen Hansen <jhansen@vmware.com>
VMCI: Use set_page_dirty_lock() when unregistering guest memory
Pan Bian <bianpan2016@163.com>
PCI: xilinx-cpm: Fix reference count leak on error path
Simon South <simon@simonsouth.net>
pwm: rockchip: Eliminate potential race condition when probing
Simon South <simon@simonsouth.net>
pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
Simon South <simon@simonsouth.net>
pwm: rockchip: Enable APB clock during register access while probing
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
soundwire: cadence: fix ACK/NAK handling
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
soundwire: debugfs: use controller id instead of link_id
Marek Vasut <marek.vasut+renesas@gmail.com>
PCI: rcar: Always allocate MSI addresses in 32bit space
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Add module alias to avoid breaking support for non device tree users
Dan Carpenter <dan.carpenter@oracle.com>
phy: cadence-torrent: Fix error code in cdns_torrent_phy_probe()
Chris Ruehl <chris.ruehl@gtsys.com.hk>
phy: rockchip-emmc: emmc_phy_init() always return 0
Aswath Govindraju <a-govindraju@ti.com>
misc: eeprom_93xx46: Fix module alias to enable module autoprobe
Randy Dunlap <rdunlap@infradead.org>
ARM: 9065/1: OABI compat: fix build when EPOLL is not enabled
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: zinitix - fix return type of zinitix_init_touch()
Randy Dunlap <rdunlap@infradead.org>
sparc: fix led.c driver when PROC_FS is not enabled
Randy Dunlap <rdunlap@infradead.org>
sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
Dan Carpenter <dan.carpenter@oracle.com>
Input: elo - fix an error code in elo_connect()
Namhyung Kim <namhyung@kernel.org>
perf test: Fix unaligned access in sample parsing test
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix IPC with CYC threshold
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix premature IPC
Adrian Hunter <adrian.hunter@intel.com>
perf intel-pt: Fix missing CYC processing in PSB
Yang Jihong <yangjihong1@huawei.com>
perf record: Fix continue profiling after draining the buffer
Dan Carpenter <dan.carpenter@oracle.com>
Input: sur40 - fix an error code in sur40_probe()
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Do not pass a valid pointer to PTR_ERR()
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv-sysfs: fix missing put_device
Gioh Kim <gi-oh.kim@cloud.ionos.com>
RDMA/rtrs-srv: fix memory leak by missing kobject free
Md Haris Iqbal <haris.iqbal@cloud.ionos.com>
RDMA/rtrs: Only allow addition of path to an already established session
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix stack-out-of-bounds
Avihai Horon <avihaih@nvidia.com>
RDMA/ucma: Fix use-after-free bug in ucma_create_uevent
Lang Cheng <chenglang@huawei.com>
RDMA/hns: Fixes missing error code of CMDQ
Jeff Layton <jlayton@kernel.org>
ceph: fix flush_snap logic after putting caps
Chuck Lever <chuck.lever@oracle.com>
svcrdma: Hold private mutex while invoking rdma_accept()
J. Bruce Fields <bfields@redhat.com>
nfsd: register pernet ops last, unregister first
Nicholas Fraser <nfraser@codeweavers.com>
perf symbols: Fix return value when loading PE DSO
John Ogness <john.ogness@linutronix.de>
printk: avoid prb_first_valid_seq() where possible
Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
spi: Skip zero-length transfers in spi_transfer_one_message()
Kees Cook <keescook@chromium.org>
spi: dw: Avoid stack content exposure
Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
regulator: bd718x7, bd71828, Fix dvs voltage levels
Dmitry Safonov <0x7f454c46@gmail.com>
perf symbols: Use (long) for iterator for bfd symbols
Tom Zanussi <zanussi@kernel.org>
selftests/ftrace: Update synthetic event syntax errors
Ryan Chen <ryan_chen@aspeedtech.com>
clk: aspeed: Fix APLL calculate formula from ast2600-A2
Jonathan Marek <jonathan@marek.ca>
regulator: qcom-rpmh: fix pm8009 ldo7
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/kuap: Restore AMR after replaying soft interrupts
Alexey Kardashevskiy <aik@ozlabs.ru>
powerpc/uaccess: Avoid might_fault() when user access is enabled
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
spi: pxa2xx: Fix the controller numbering for Wildcat Point
Michael Tretter <m.tretter@pengutronix.de>
clk: divider: fix initialization with parent_hw
Lijun Ou <oulijun@huawei.com>
RDMA/hns: Disable RQ inline by default
Weihang Li <liweihang@huawei.com>
RDMA/hns: Fix type of sq_signal_bits
Kamal Heib <kamalheib1@gmail.com>
RDMA/siw: Fix calculation of tx_valid_cpus size
Wenpeng Liang <liangwenpeng@huawei.com>
RDMA/hns: Fixed wrong judgments in the goto branch
John Stultz <john.stultz@linaro.org>
kselftests: dmabuf-heaps: Fix Makefile's inclusion of the kernel's usr/include dir
Daniel Latypov <dlatypov@google.com>
kunit: tool: fix unit test cleanup handling
AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/8xx: Fix software emulation interrupt
Nathan Lynch <nathanl@linux.ibm.com>
powerpc/pseries/dlpar: handle ibm, configure-connector delay status
Dan Carpenter <dan.carpenter@oracle.com>
mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
Arnd Bergmann <arnd@arndb.de>
mfd: altera-sysmgr: Fix physical address storing more
Alain Volmat <alain.volmat@foss.st.com>
spi: stm32: properly handle 0 byte transfer
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Correct skb on loopback path
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
Bob Pearson <rpearsonhpe@gmail.com>
RDMA/rxe: Fix coding error in rxe_recv.c
John Garry <john.garry@huawei.com>
perf vendor events arm64: Fix Ampere eMag event typo
Arnaldo Carvalho de Melo <acme@redhat.com>
perf tools: Fix DSO filtering when not finding a map for a sampled address
David Gow <davidgow@google.com>
rtc: zynqmp: depend on HAS_IOMEM
Steven Rostedt (VMware) <rostedt@goodmis.org>
tracepoint: Do not fail unregistering a probe due to memory failure
Parav Pandit <parav@nvidia.com>
IB/cm: Avoid a loop when device has 255 ports
Parav Pandit <parav@nvidia.com>
IB/mlx5: Return appropriate error code instead of ENOMEM
Douglas Anderson <dianders@chromium.org>
iommu: Properly pass gfp_t in _iommu_map() to avoid atomic sleeping
Yong Wu <yong.wu@mediatek.com>
iommu: Move iotlb_sync_map out from __iommu_map
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
amba: Fix resource leak for drivers without .remove
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: i2c-qcom-geni: Add shutdown callback for i2c
Roja Rani Yarubandi <rojay@codeaurora.org>
i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
Vladimir Murzin <vladimir.murzin@arm.com>
ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
Takeshi Saito <takeshi.saito.xv@renesas.com>
mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to 128-bytes
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: sdhci-sprd: Fix some resource leaks in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
mmc: owl-mmc: Fix a resource leak in an error handling path and in the remove function
Pingfan Liu <kernelfans@gmail.com>
powerpc/time: Enable sched clock for irqtime
Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
powerpc/sstep: Fix incorrect return from analyze_instr()
Christophe Leroy <christophe.leroy@csgroup.eu>
powerpc/47x: Disable 256k page size
Cédric Le Goater <clg@kaod.org>
KVM: PPC: Make the VMX instruction emulation routines static
Shay Drory <shayd@nvidia.com>
IB/umad: Return EPOLLERR in case of when device disassociated
Shay Drory <shayd@nvidia.com>
IB/umad: Return EIO in case of when device disassociated
Yong Wu <yong.wu@mediatek.com>
iommu: Switch gather->end to the inclusive end
Dan Carpenter <dan.carpenter@oracle.com>
scsi: lpfc: Fix ancient double free
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix ".cold" section suffix check for newer versions of GCC
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix retpoline detection in asm code
Josh Poimboeuf <jpoimboe@redhat.com>
objtool: Fix error handling for STD/CLD warnings
Geert Uytterhoeven <geert@linux-m68k.org>
auxdisplay: ht16k33: Fix refresh rate handling
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
Pan Bian <bianpan2016@163.com>
isofs: release buffer head before return
Hans de Goede <hdegoede@redhat.com>
regulator: core: Avoid debugfs: Directory ... already present! error
Dmitry Osipenko <digetx@gmail.com>
power: supply: smb347-charger: Fix interrupt usage if interrupt is unavailable
Samuel Holland <samuel@sholland.org>
power: supply: axp20x_usb_power: Init work before enabling IRQs
Krzysztof Kozlowski <krzk@kernel.org>
regulator: s5m8767: Drop regulators OF node reference
Pan Bian <bianpan2016@163.com>
spi: atmel: Put allocated master before return
Pan Bian <bianpan2016@163.com>
regulator: s5m8767: Fix reference count leak
David Howells <dhowells@redhat.com>
certs: Fix blacklist flag type confusion
Gabriel Krisman Bertazi <krisman@collabora.com>
watch_queue: Drop references to /dev/watch_queue
Pan Bian <bianpan2016@163.com>
regulator: axp20x: Fix reference cout leak
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Add LID and BATTERY to default mask
Evan Benn <evanbenn@chromium.org>
platform/chrome: cros_ec_proto: Use EC_HOST_EVENT_MASK not BIT
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix clock divider range on some clocks
Parav Pandit <parav@nvidia.com>
IB/mlx5: Add mutex destroy call to cap_mask_mutex mutex
Yishai Hadas <yishaih@nvidia.com>
RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
Guido Günther <agx@sigxcpu.org>
spi: imx: Don't print error on -EPROBEDEFER
Tom Rix <trix@redhat.com>
clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
Arnd Bergmann <arnd@arndb.de>
clocksource/drivers/ixp4xx: Select TIMER_OF when needed
Randy Dunlap <rdunlap@infradead.org>
power: supply: fix sbs-charger build, needs REGMAP_I2C
Dave Jiang <dave.jiang@intel.com>
dmaengine: idxd: set DMA channel to be private
Bartosz Golaszewski <bgolaszewski@baylibre.com>
rtc: s5m: select REGMAP_I2C
Claudiu Beznea <claudiu.beznea@microchip.com>
power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Init wr_cnt as 1
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs-clt: Refactor the failure cases in alloc_clt
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Fix missing wr_cqe
Guoqing Jiang <guoqing.jiang@cloud.ionos.com>
RDMA/rtrs: Call kobject_put in the failure path
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-clt: Set mininum limit when create QP
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Use sysfs_remove_file_self for disconnect
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs-srv: Release lock before call into close_sess
Jack Wang <jinpu.wang@cloud.ionos.com>
RDMA/rtrs: Extend ibtrs_cq_qp_create
Nicolas Boichat <drinkcat@chromium.org>
of/fdt: Make sure no-map does not remove already reserved regions
KarimAllah Ahmed <karahmed@amazon.de>
fdt: Properly handle "no-map" field in the memory region
Colin Ian King <colin.king@canonical.com>
power: supply: cpcap-charger: Fix power_supply_put on null battery pointer
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-battery: Fix missing power_supply_put()
Tony Lindgren <tony@atomide.com>
power: supply: cpcap-charger: Fix missing power_supply_put()
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
mfd: bd9571mwv: Use devm_mfd_add_devices()
Ferry Toth <ftoth@exalondelft.nl>
dmaengine: hsu: disable spurious interrupt
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: owl-dma: Fix a resource leak in the remove function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in an error handling path of the probe function
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
dmaengine: fsldma: Fix a resource leak in the remove function
Bernard Metzler <bmt@zurich.ibm.com>
RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
Randy Dunlap <rdunlap@infradead.org>
HID: core: detect and skip invalid inputs to snto32()
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Fix parent of CBFUSA clock
Geert Uytterhoeven <geert+renesas@glider.be>
clk: renesas: r8a779a0: Remove non-existent S2 clock
Andre Przywara <andre.przywara@arm.com>
clk: sunxi-ng: h6: Fix CEC clock
Pratyush Yadav <p.yadav@ti.com>
spi: cadence-quadspi: Abort read if dummy cycles required are too many
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle master read request
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
Rayagonda Kokatanur <rayagonda.kokatanur@broadcom.com>
i2c: iproc: handle only slave interrupts which are enabled
Jan Kara <jack@suse.cz>
quota: Fix memory leak when handling corrupted quota file
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
arm64: dts: qcom: qrb5165-rb5: fix pm8009 regulators
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
regulator: qcom-rpmh-regulator: add pm8009-1 chip revision
Po-Hsu Lin <po-hsu.lin@canonical.com>
selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: make "ret" a signed integer
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
Tony Lindgren <tony@atomide.com>
power: supply: cpcap: Add missing IRQF_ONESHOT to fix regression
Zhang Qilong <zhangqilong3@huawei.com>
HSI: Fix PM usage counter unbalance in ssi_hw_init
Eric W. Biederman <ebiederm@xmission.com>
capabilities: Don't allow writing ambiguous v3 file capabilities
Nirmoy Das <nirmoy.das@amd.com>
drm/amdgpu/display: remove hdcp_srm sysfs on device removal
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
smp: Process pending softirqs in flush_smp_call_function_from_idle()
Geert Uytterhoeven <geert+renesas@glider.be>
irqchip/imx: IMX_INTMUX should not default to y, unconditionally
Wang ShaoBo <bobo.shaobowang@huawei.com>
ubifs: Fix error return code in alloc_wbufs()
Arnd Bergmann <arnd@arndb.de>
ubifs: replay: Fix high stack usage, again
Dinghao Liu <dinghao.liu@zju.edu.cn>
ubifs: Fix memleak in ubifs_init_authentication
Tom Rix <trix@redhat.com>
jffs2: fix use after free in jffs2_sum_write_data()
Colin Ian King <colin.king@canonical.com>
fs/jfs: fix potential integer overflow on shift of a int
Sameer Pujar <spujar@nvidia.com>
ASoC: simple-card-utils: Fix device module clock
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer after kexec syscall
Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
ima: Free IMA measurement buffer on error
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: SOF: sof-pci-dev: add missing Up-Extreme quirk
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: set status to 0 in case for invalid nsid
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
nvmet: remove extra variable in identify ns
Keith Busch <kbusch@kernel.org>
nvme-multipath: set nr_zones for zoned namespaces
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix potential race of tcp socket closing accept_work
Sagi Grimberg <sagi@grimberg.me>
nvmet-tcp: fix receive data digest calculation for multiple h2cdata PDUs
Hao Xu <haoxu@linux.alibaba.com>
io_uring: fix possible deadlock in io_uring_poll
Daniele Alessandrelli <daniele.alessandrelli@intel.com>
crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
Jan Henrik Weinstock <jan.weinstock@rwth-aachen.de>
hwrng: timeriomem - Fix cooldown period calculation
Imre Deak <imre.deak@intel.com>
drm/dp_mst: Don't cache EDIDs for physical ports
Qinglang Miao <miaoqinglang@huawei.com>
drm/lima: fix reference leak in lima_pm_busy
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Update the CEC clock divider on HSM rate change
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Compute the CEC clock divider from the clock rate
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Restore cec physical address on reconnect
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix up CEC registers
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Fix register offset with longer CEC messages
Dom Cobley <popcornmix@gmail.com>
drm/vc4: hdmi: Move hdmi reset to bind
Harald Freudenberger <freude@linux.ibm.com>
s390/zcrypt: return EIO when msg retry limit reached
Sean Christopherson <seanjc@google.com>
KVM: x86: Restore all 64 bits of DR6 and DR7 during RSM on x86-64
Qu Wenruo <wqu@suse.com>
btrfs: fix double accounting of ordered extent for subpage case in btrfs_invalidapge
Zhihao Cheng <chengzhihao1@huawei.com>
btrfs: clarify error returns values in __load_free_space_cache
Hui Wang <hui.wang@canonical.com>
ASoC: SOF: debug: Fix a potential issue on string buffer termination
Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>
ASoC: rt5682: Fix panic in rt5682_jack_detect_handler happening during system shutdown
Jun Nie <jun.nie@linaro.org>
ASoC: qcom: lpass: Fix i2s ctl register bit map
Peter Zijlstra <peterz@infradead.org>
locking/lockdep: Avoid unmatched unlock
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A3E
Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
ASoC: Intel: sof_sdw: add missing TGL_HDMI quirk for Dell SKU 0A5E
Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
Sasha Levin <sashal@kernel.org>
drm/mediatek: Fix aal size config
Yongqiang Niu <yongqiang.niu@mediatek.com>
drm/mediatek: Check if fb is null
Sean Christopherson <seanjc@google.com>
KVM: nSVM: Don't strip host's C-bit from guest's CR3 when reading PDPTRs
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: Fix typo error in HDMI regmap config callbacks
Dehe Gu <gudehe@huawei.com>
f2fs: fix a wrong condition in __submit_bio
Dan Carpenter <dan.carpenter@oracle.com>
drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
Yi Chen <chenyi77@huawei.com>
f2fs: fix to avoid inconsistent quota data
Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
mtd: parsers: afs: Fix freeing the part name memory in failure
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
ASoC: codecs: add missing max_register in regmap config
Sebastian Reichel <sre@kernel.org>
ASoC: cpcap: fix microphone timeslot mask
Florian Fainelli <f.fainelli@gmail.com>
ata: ahci_brcm: Add back regulators management
Will Deacon <will@kernel.org>
mm: proc: Invalidate TLB after clearing soft-dirty page state
Frantisek Hrbata <frantisek@hrbata.com>
drm/nouveau: bail out of nouveau_channel_new if channel init fails
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Fix ctr(aes) on SEC1
Christophe Leroy <christophe.leroy@csgroup.eu>
crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
Dan Carpenter <dan.carpenter@oracle.com>
mtd: parser: imagetag: fix error codes in bcm963xx_parse_imagetag_partitions()
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Move IRQs when migrating context
Robin Murphy <robin.murphy@arm.com>
perf/arm-cmn: Fix PMU instance naming
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
ASoC: SOF: Intel: hda: cancel D0i3 work during runtime suspend
Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
ASoC: qcom: lpass-cpu: Remove bit clock state check
Chao Yu <chao@kernel.org>
f2fs: compress: fix potential deadlock
Qais Yousef <qais.yousef@arm.com>
sched/eas: Don't update misfit status if the task is pinned
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
Tom Rix <trix@redhat.com>
media: pxa_camera: declare variable when DEBUG is defined
Tom Rix <trix@redhat.com>
media: mtk-vcodec: fix argument used when DEBUG is defined
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: cx25821: Fix a bug when reallocating some dma memory
Luo Meng <luomeng12@huawei.com>
media: qm1d1c0042: fix error return code in qm1d1c0042_init()
Dan Carpenter <dan.carpenter@oracle.com>
media: atomisp: Fix a buffer overflow in debug code
Daniel W. S. Almeida <dwlsalmeida@gmail.com>
media: vidtv: psi: fix missing crc for PMT
Joe Perches <joe@perches.com>
media: lmedm04: Fix misuse of comma
Daniel Scally <djrscally@gmail.com>
media: software_node: Fix refcounts in software_node_get_next_child()
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix HDMI deep color output for DCE 6-11.
Mario Kleiner <mario.kleiner.de@gmail.com>
drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
Finn Thain <fthain@telegraphics.com.au>
macintosh/adb-iop: Use big-endian autopoll mask
Pan Bian <bianpan2016@163.com>
bsg: free the request before return error code
Guchun Chen <guchun.chen@amd.com>
drm/amdgpu: toggle on DF Cstate after finishing xgmi injection
Qinglang Miao <miaoqinglang@huawei.com>
drm/tegra: Fix reference leak when pm_runtime_get_sync() fails
Nathan Chancellor <natechancellor@gmail.com>
MIPS: Compare __SYNC_loongson3_war against 0
Alexander Lobakin <alobakin@pm.me>
MIPS: properly stop .eh_frame generation
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
media: ti-vpe: cal: fix write to unallocated memory
Rui Miguel Silva <rmfrfs@gmail.com>
media: imx7: csi: Fix pad link validation
Fabio Estevam <festevam@gmail.com>
media: imx7: csi: Fix regression for parallel cameras on i.MX6UL
Giulio Benetti <giulio.benetti@micronovasrl.com>
drm/sun4i: tcon: fix inverted DCLK polarity
Xuewen Yan <xuewen.yan@unisoc.com>
sched/fair: Avoid stale CPU util_est value for schedutil in task dequeue
Jiri Olsa <jolsa@kernel.org>
crypto: bcm - Rename struct device_private to bcm_device_private
Dinghao Liu <dinghao.liu@zju.edu.cn>
evm: Fix memleak in init_desc
Stephan Gerhold <stephan@gerhold.net>
ASoC: qcom: qdsp6: Move frontend AIFs to q6asm-dai
Dan Carpenter <dan.carpenter@oracle.com>
ASoC: cs42l56: fix up error handling in probe
Zhang Changzhong <zhangchangzhong@huawei.com>
media: aspeed: fix error return code in aspeed_video_setup_video()
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: tm6000: Fix memleak in tm6000_start_stream
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: media/pci: Fix memleak in empress_init
Dinghao Liu <dinghao.liu@zju.edu.cn>
media: em28xx: Fix use-after-free in em28xx_alloc_urbs
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
media: vsp1: Fix an error handling path in the probe function
Dan Carpenter <dan.carpenter@oracle.com>
media: camss: missing error code in msm_video_register()
Zhang Changzhong <zhangchangzhong@huawei.com>
media: mtk-vcodec: fix error return code in vdec_vp9_decode()
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Fix csc/scaler unregister
Ezequiel Garcia <ezequiel@collabora.com>
media: imx: Unregister csc/scaler only if registered
Jacopo Mondi <jacopo@jmondi.org>
media: i2c: ov5670: Fix PIXEL_RATE minimum value
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
media: ipu3-cio2: Build only for x86
Simon Ser <contact@emersion.fr>
drm/fourcc: fix Amlogic format modifier masks
Chia-I Wu <olvaffe@gmail.com>
drm/virtio: make sure context is created in gem open
Nathan Chancellor <natechancellor@gmail.com>
MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
Nathan Chancellor <natechancellor@gmail.com>
MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
Chenyang Li <lichenyang@loongson.cn>
drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm: rcar-du: Fix leak of CMM platform device reference
Wang Xiaojun <wangxiaojun11@huawei.com>
drm: rcar-du: Fix the return check of of_parse_phandle and of_find_device_by_node
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
drm: rcar-du: Fix crash when using LVDS1 clock for CRTC
Qinglang Miao <miaoqinglang@huawei.com>
drm: rcar-du: Fix PM reference leak in rcar_cmm_enable()
Marco Elver <elver@google.com>
kcsan: Rewrite kcsan_prandom_u32_max() without prandom_u32_state()
Dan Carpenter <dan.carpenter@oracle.com>
media: allegro: Fix use after free on error
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
hwrng: ingenic - Fix a resource leak in an error handling path
Ard Biesheuvel <ardb@kernel.org>
crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - fix kmap usage
Corentin Labbe <clabbe@baylibre.com>
crypto: sun4i-ss - linearize buffers content must be kept
Maxime Ripard <maxime@cerno.tech>
drm/vc4: hdmi: Take into account the clock doubling flag in atomic_check
Guido Günther <agx@sigxcpu.org>
drm/panel: mantix: Tweak init sequence
Chuhong Yuan <hslester96@gmail.com>
drm/fb-helper: Add missed unlocks in setcmap_legacy()
Dan Carpenter <dan.carpenter@oracle.com>
gma500: clean up error handling in init
Jialin Zhang <zhangjialin11@huawei.com>
drm/gma500: Fix error return code in psb_driver_load()
Randy Dunlap <rdunlap@infradead.org>
fbdev: aty: SPARC64 requires FB_ATY_CT
Linus Torvalds <torvalds@linux-foundation.org>
tty: implement read_iter
Linus Torvalds <torvalds@linux-foundation.org>
tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer
Vladimir Oltean <vladimir.oltean@nxp.com>
net: enetc: fix destroyed phylink dereference during unbind
Maxime Chevallier <maxime.chevallier@bootlin.com>
net: mvneta: Remove per-cpu queue mapping for Armada 3700
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset link when the link never comes back
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
Bjarni Jonasson <bjarni.jonasson@microchip.com>
net: phy: mscc: adding LCPLL reset to VSC8514
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: don't deinitialize unused ports
Vladimir Oltean <vladimir.oltean@nxp.com>
net: dsa: felix: perform teardown in reverse order of setup
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: skip send_request_unmap for timeout reset
Lijun Pan <ljp@linux.ibm.com>
ibmvnic: add memory barrier to protect long term buffer
Ilya Leoshkevich <iii@linux.ibm.com>
bpf: Clear subreg_def for global function return values
Colin Ian King <colin.king@canonical.com>
b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
Ayush Sawal <ayush.sawal@chelsio.com>
cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4 and ulds
Robert Hancock <robert.hancock@calian.com>
net: axienet: Handle deferred probe on clock properly
Eric Dumazet <edumazet@google.com>
tcp: fix SO_RCVLOWAT related hangs under mem pressure
Matthieu Baerts <matthieu.baerts@tessares.net>
selftests: mptcp: fix ACKRX debug message
Jesper Dangaard Brouer <brouer@redhat.com>
bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
Jun'ichi Nomura <junichi.nomura@nec.com>
bpf, devmap: Use GFP_KERNEL for xdp bulk queue allocation
Yonghong Song <yhs@fb.com>
bpf: Fix an unitialized value in bpf_iter
Martin KaFai Lau <kafai@fb.com>
libbpf: Ignore non function pointer member in struct_ops
Colin Ian King <colin.king@canonical.com>
mac80211: fix potential overflow when multiplying to u32 integers
Moshe Shemesh <moshe@nvidia.com>
net/mlx5e: Check tunnel offload is required before setting SWP
Oz Shlomo <ozsh@nvidia.com>
net/mlx5e: CT: manage the lifetime of the ct entry object
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for lag devices
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on lag device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disallow RoCE on multi port slave device
Shay Drory <shayd@nvidia.com>
net/mlx5: Disable devlink reload for multi port slave device
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: kTLS, Use refcounts to free kTLS RX priv context
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Replace synchronize_rcu with synchronize_net
Shay Drory <shayd@nvidia.com>
net/mlx5: Fix health error state handling
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Change interrupt moderation channel params also when channels are closed
Maxim Mikityanskiy <maximmi@mellanox.com>
net/mlx5e: Don't change interrupt moderation params when DIM is enabled
Heiner Kallweit <hkallweit1@gmail.com>
net: phy: consider that suspend2ram may cut off PHY power
Ioana Ciornei <ioana.ciornei@nxp.com>
dpaa2-eth: fix memory leak in XDP_REDIRECT
Juergen Gross <jgross@suse.com>
xen/netback: fix spurious event detection for common event case
Vasundhara Volam <vasundhara-v.volam@broadcom.com>
bnxt_en: Fix devlink info's stored fw.psid version format.
Edwin Peer <edwin.peer@broadcom.com>
bnxt_en: reverse order of TX disable and carrier off
Sukadev Bhattiprolu <sukadev@linux.ibm.com>
ibmvnic: Set to CLOSED state even on error
Björn Töpel <bjorn.topel@intel.com>
selftests/bpf: Convert test_xdp_redirect.sh to bash
Linus Lüssing <ll@simonwunderlich.de>
ath9k: fix data bus crash when setting nf_override via debugfs
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: increment the pointer before checking the TLV
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: pnvm: set the PNVM again if it was already loaded
Marco Elver <elver@google.com>
bpf_lru_list: Read double-checked variable once without lock
Sara Sharon <sara.sharon@intel.com>
iwlwifi: mvm: don't check if CSA event is running before removing
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: assign SAR table revision to the command later
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: send stored PPAG command instead of local
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: store PPAG enabled/disabled flag properly
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: fix the type we use in the PPAG table validity checks
Jae Hyun Yoo <jae.hyun.yoo@intel.com>
soc: aspeed: snoop: Add clock control logic
Dan Carpenter <dan.carpenter@oracle.com>
ath11k: fix a locking bug in ath11k_mac_op_start()
Anand K Mistry <amistry@google.com>
ath10k: Fix lockdep assertion warning in ath10k_sta_statistics
Anand K Mistry <amistry@google.com>
ath10k: Fix suspicious RCU usage warning in ath10k_wmi_tlv_parse_peer_stats_info()
Arnd Bergmann <arnd@arndb.de>
ARM: at91: use proper asm syntax in pm_suspend
Jérôme Pouiller <jerome.pouiller@silabs.com>
staging: wfx: fix possible panic with re-queued frames
Arnd Bergmann <arnd@arndb.de>
optee: simplify i2c access
Arnd Bergmann <arnd@arndb.de>
ARM: s3c: fix fiq for clang IAS
Luca Coelho <luciano.coelho@intel.com>
iwlwifi: mvm: set enabled in the PPAG command properly
Artem Lapkin <email2tema@gmail.com>
arm64: dts: meson: fix broken wifi node for Khadas VIM3L
Vincent Knecht <vincent.knecht@mailoo.org>
arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
Luca Weiss <luca@z3ntu.xyz>
soc: qcom: ocmem: don't return NULL in of_get_ocmem
Jupeng Zhong <zhongjupeng@yulong.com>
Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
Dmitry Osipenko <digetx@gmail.com>
opp: Correct debug message in _opp_add_static_v2()
Marek Behún <kabel@kernel.org>
arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to a53-firmware
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to each fan
Rosen Penev <rosenp@gmail.com>
ARM: dts: armada388-helios4: assign pinctrl to LEDs
Marc Kleine-Budde <mkl@pengutronix.de>
can: mcp251xfd: mcp251xfd_probe(): fix errata reference
Geert Uytterhoeven <geert+renesas@glider.be>
arm64: dts: renesas: beacon: Fix EEPROM compatible value
Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
x86/MSR: Filter MSR writes through X86_IOC_WRMSR_REGS ioctl too
Chen-Yu Tsai <wens@csie.org>
staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Make "trimming xfer length" a debug message
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Abort transaction after errors with unknown reason
Guenter Roeck <linux@roeck-us.net>
usb: dwc2: Do not update data length if it is 0 on inbound transfers
Tony Lindgren <tony@atomide.com>
ARM: dts: Configure missing thermal interrupt for 4430
Pan Bian <bianpan2016@163.com>
memory: ti-aemif: Drop child node when jumping out loop
Pan Bian <bianpan2016@163.com>
Bluetooth: Put HCI device if inquiry procedure interrupts
Pan Bian <bianpan2016@163.com>
Bluetooth: drop HCI device reference before return
Borislav Petkov <bp@suse.de>
staging: media: atomisp: Fix size_t format specifier in hmm_alloc() debug statemenet
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
soc: ti: pm33xx: Fix some resource leak in the error handling paths of the probe function
Dan Carpenter <dan.carpenter@oracle.com>
soc: qcom: socinfo: Fix an off by one in qcom_show_pmic_model()
Robert Foss <robert.foss@linaro.org>
arm64: dts: qcom: sdm845-db845c: Fix reset-pin of ov8856 node
Jack Pham <jackp@codeaurora.org>
usb: gadget: u_audio: Free requests only after callback
Maximilian Luz <luzmaximilian@gmail.com>
ACPICA: Fix exception code class checks
Chen-Yu Tsai <wens@csie.org>
arm64: dts: rockchip: rk3328: Add clock_in_out property to gmac2phy node
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
cpufreq: brcmstb-avs-cpufreq: Free resources in error path
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a2015: Fix sensors
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: H6: properly connect USB PHY to port 0
Andre Przywara <andre.przywara@arm.com>
arm64: dts: allwinner: A64: properly connect USB PHY to port 0
Cristian Marussi <cristian.marussi@arm.com>
firmware: arm_scmi: Fix call site of scmi_notification_exit
Andrii Nakryiko <andrii@kernel.org>
bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
Andrii Nakryiko <andrii@kernel.org>
bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
Martin Blumenstingl <martin.blumenstingl@googlemail.com>
net: stmmac: dwmac-meson8b: fix enabling the timing-adjustment clock
Stephan Gerhold <stephan@gerhold.net>
arm64: dts: qcom: msm8916-samsung-a5u: Fix iris compatible
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk transfers on 64-bit builds
Phil Elwell <phil@raspberrypi.com>
staging: vchiq: Fix bulk userdata handling
Dinghao Liu <dinghao.liu@zju.edu.cn>
Bluetooth: hci_qca: Fix memleak in qca_controller_memdump
Zhang Qilong <zhangqilong3@huawei.com>
memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
Krzysztof Kozlowski <krzk@kernel.org>
arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
Krzysztof Kozlowski <krzk@kernel.org>
ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon: Fix audio-1.8V pin enable
Adam Ford <aford173@gmail.com>
arm64: dts: renesas: beacon kit: Fix choppy Bluetooth Audio
Christopher William Snowhill <chris@kode54.net>
Bluetooth: Fix initializing response id after clearing struct
Claire Chang <tientzu@chromium.org>
Bluetooth: hci_uart: Fix a race for write_work scheduling
Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the probe function
Rakesh Pillai <pillair@codeaurora.org>
ath10k: Fix error handling in case of CE pipe init failure
Chris Wilson <chris@chris-wilson.co.uk>
drm/i915/gt: One more flush for Baytrail clear residuals
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Don't call sync_stop if it hasn't been stopped
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Assure sync with the pending stop operation at suspend
Takashi Iwai <tiwai@suse.de>
ALSA: pcm: Call sync_stop at disconnection
Eric Biggers <ebiggers@google.com>
random: fix the RNDRESEEDCRNG ioctl
Nathan Chancellor <nathan@kernel.org>
vmlinux.lds.h: Define SANTIZER_DISCARDS with CONFIG_GCOV_KERNEL=y
Alexander Lobakin <alobakin@pm.me>
MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
Jan Kara <jack@suse.cz>
bfq: Avoid false bfq queue merging
Hans de Goede <hdegoede@redhat.com>
virt: vbox: Do not use wait_event_interruptible when called from kernel context
Ard Biesheuvel <ardb@kernel.org>
PCI: Decline to resize resources if boot config must be preserved
Ansuel Smith <ansuelsmth@gmail.com>
PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
Ivan Zaentsev <ivan.zaentsev@wirenboard.ru>
w1: w1_therm: Fix conversion result for negative temperatures
Sumit Garg <sumit.garg@linaro.org>
kdb: Make memory allocations more robust
Quinn Tran <qutran@marvell.com>
scsi: qla2xxx: Fix mailbox Ch erroneous error
Ahmed S. Darwish <a.darwish@linutronix.de>
scsi: libsas: docs: Remove notify_ha_event()
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: do not attempt to create a new file before the filesystem is initalized
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
debugfs: be more robust at handling improper input in debugfs_lookup()
Stefano Garzarella <sgarzare@redhat.com>
vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()
Nick Desaulniers <ndesaulniers@google.com>
vmlinux.lds.h: add DWARF v5 sections
-------------
Diffstat:
Documentation/admin-guide/perf/arm-cmn.rst | 2 +-
Documentation/admin-guide/sysctl/vm.rst | 10 +-
Documentation/filesystems/seq_file.rst | 6 +
Documentation/scsi/libsas.rst | 1 -
Documentation/security/keys/core.rst | 4 +-
Makefile | 4 +-
arch/arm/boot/compressed/head.S | 4 +-
arch/arm/boot/dts/armada-388-helios4.dts | 28 +-
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/arm/kernel/sys_oabi-compat.c | 15 +
arch/arm/mach-at91/pm_suspend.S | 2 +-
arch/arm/mach-ixp4xx/Kconfig | 1 -
arch/arm/mach-s3c/irq-s3c24xx-fiq.S | 9 +-
arch/arm64/Kconfig | 2 +-
.../boot/dts/allwinner/sun50i-a64-pinebook.dts | 5 +-
.../boot/dts/allwinner/sun50i-a64-sopine.dtsi | 1 -
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 +-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 7 +
.../boot/dts/amlogic/meson-sm1-khadas-vim3l.dts | 7 +-
.../boot/dts/exynos/exynos5433-tm2-common.dtsi | 2 +-
arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 2 +-
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 4 +-
.../boot/dts/marvell/armada-3720-turris-mox.dts | 2 +-
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +
.../dts/qcom/msm8916-samsung-a2015-common.dtsi | 6 +
.../boot/dts/qcom/msm8916-samsung-a5u-eur.dts | 2 +-
arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 +-
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 9 +-
arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 4 +-
.../boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +-
.../arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 4 +-
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 +
arch/arm64/crypto/aes-glue.c | 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/include/asm/module.lds.h | 6 +-
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/head.S | 1 +
arch/arm64/kernel/machine_kexec_file.c | 4 +-
arch/arm64/kernel/probes/uprobes.c | 2 +-
arch/arm64/kernel/ptrace.c | 2 +-
arch/arm64/kernel/suspend.c | 2 +-
arch/csky/kernel/ptrace.c | 2 +-
arch/mips/Makefile | 19 ++
arch/mips/cavium-octeon/setup.c | 9 +-
arch/mips/include/asm/asm.h | 18 ++
arch/mips/include/asm/atomic.h | 2 +-
arch/mips/include/asm/cmpxchg.h | 6 +-
arch/mips/kernel/cpu-probe.c | 15 +-
arch/mips/kernel/vmlinux.lds.S | 2 +-
arch/mips/lantiq/irq.c | 2 +-
arch/mips/loongson64/Platform | 22 --
arch/mips/mm/c-r4k.c | 2 +-
arch/mips/vdso/Makefile | 5 +-
arch/nios2/kernel/entry.S | 3 +
arch/nios2/kernel/sys_nios2.c | 11 +-
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/kexec.h | 1 +
arch/powerpc/include/asm/uaccess.h | 13 +-
arch/powerpc/kernel/entry_32.S | 3 +
arch/powerpc/kernel/head_32.h | 2 +-
arch/powerpc/kernel/head_8xx.S | 2 +-
arch/powerpc/kernel/head_book3s_32.S | 6 -
arch/powerpc/kernel/irq.c | 27 +-
arch/powerpc/kernel/prom_init.c | 12 +-
arch/powerpc/kernel/time.c | 2 +
arch/powerpc/kexec/elf_64.c | 2 +-
arch/powerpc/kexec/file_load_64.c | 35 +++
arch/powerpc/kvm/powerpc.c | 8 +-
arch/powerpc/lib/sstep.c | 7 +-
arch/powerpc/platforms/pseries/dlpar.c | 7 +-
arch/riscv/kernel/vdso/Makefile | 3 +-
arch/s390/kernel/vtime.c | 3 +-
arch/sparc/Kconfig | 2 +-
arch/sparc/kernel/led.c | 2 +
arch/sparc/lib/memset.S | 1 +
arch/um/include/shared/skas/mm_id.h | 1 +
arch/um/kernel/tlb.c | 19 +-
arch/um/os-Linux/skas/process.c | 4 +
arch/x86/crypto/aesni-intel_glue.c | 28 +-
arch/x86/entry/common.c | 2 +-
arch/x86/include/asm/virtext.h | 17 +-
arch/x86/kernel/msr.c | 7 +
arch/x86/kernel/reboot.c | 30 +-
arch/x86/kvm/emulate.c | 4 +-
arch/x86/kvm/mmu/tdp_mmu.c | 3 +-
arch/x86/kvm/svm/nested.c | 22 +-
arch/x86/kvm/svm/svm.c | 8 +-
arch/x86/kvm/x86.c | 1 +
arch/x86/mm/fault.c | 27 +-
arch/x86/mm/pat/memtype.c | 4 +-
block/bfq-iosched.c | 1 +
block/blk-settings.c | 12 +
block/bsg.c | 4 +-
block/ioctl.c | 21 +-
certs/blacklist.c | 2 +-
crypto/ecdh_helper.c | 3 +
crypto/michael_mic.c | 31 +-
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/base/swnode.c | 8 +-
drivers/block/floppy.c | 30 +-
drivers/bluetooth/btqcomsmd.c | 27 +-
drivers/bluetooth/btusb.c | 20 +-
drivers/bluetooth/hci_ldisc.c | 41 ++-
drivers/bluetooth/hci_qca.c | 2 +
drivers/bluetooth/hci_serdev.c | 4 +-
drivers/char/hw_random/ingenic-trng.c | 6 +-
drivers/char/hw_random/timeriomem-rng.c | 2 +-
drivers/char/random.c | 2 +-
drivers/char/tpm/tpm.h | 4 -
drivers/char/tpm/tpm_tis_core.c | 50 +--
drivers/clk/clk-ast2600.c | 37 ++-
drivers/clk/clk-divider.c | 9 +-
drivers/clk/meson/clk-pll.c | 10 +-
drivers/clk/qcom/gcc-msm8998.c | 100 +++---
drivers/clk/renesas/r8a779a0-cpg-mssr.c | 3 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 10 +-
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/mxs_timer.c | 5 +-
drivers/cpufreq/acpi-cpufreq.c | 62 +---
drivers/cpufreq/brcmstb-avs-cpufreq.c | 24 +-
drivers/cpufreq/freq_table.c | 8 +-
drivers/cpufreq/intel_pstate.c | 21 +-
drivers/cpufreq/qcom-cpufreq-hw.c | 40 ++-
.../crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c | 173 ++++++----
drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h | 2 +
drivers/crypto/bcm/cipher.c | 2 +-
drivers/crypto/bcm/cipher.h | 4 +-
drivers/crypto/bcm/util.c | 2 +-
drivers/crypto/talitos.c | 50 ++-
drivers/crypto/talitos.h | 1 +
drivers/dax/bus.c | 2 +-
drivers/dma/fsldma.c | 6 +
drivers/dma/hsu/pci.c | 21 +-
drivers/dma/idxd/dma.c | 1 +
drivers/dma/owl-dma.c | 1 +
drivers/firmware/arm_scmi/driver.c | 4 +-
drivers/gpio/gpio-pcf857x.c | 2 +-
drivers/gpu/drm/Kconfig | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 2 +-
drivers/gpu/drm/amd/amdgpu/soc15.c | 2 +
.../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 4 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 3 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 2 +-
.../gpu/drm/amd/display/dc/bios/command_table.c | 61 ++++
.../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 14 +
.../drm/amd/display/dc/dce/dce_stream_encoder.c | 1 +
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 8 +-
.../drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1 -
.../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 6 +-
.../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 20 +-
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +
.../amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 ++
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +-
drivers/gpu/drm/drm_dp_mst_topology.c | 3 +-
drivers/gpu/drm/drm_fb_helper.c | 15 +-
drivers/gpu/drm/drm_modes.c | 4 +-
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 22 +-
drivers/gpu/drm/gma500/psb_drv.c | 2 +
drivers/gpu/drm/i915/display/intel_hdmi.c | 6 +-
drivers/gpu/drm/i915/gt/gen7_renderclear.c | 12 +-
drivers/gpu/drm/lima/lima_sched.c | 2 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 2 +-
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 4 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 8 +
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 8 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 5 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c | 2 +-
drivers/gpu/drm/msm/msm_drv.c | 3 +-
.../drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 +
drivers/gpu/drm/nouveau/nouveau_chan.c | 1 +
drivers/gpu/drm/nouveau/nouveau_connector.c | 1 +
drivers/gpu/drm/panel/panel-elida-kd35t133.c | 3 +-
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c | 5 +
drivers/gpu/drm/rcar-du/rcar_cmm.c | 2 +-
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 +-
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 5 +-
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 30 +-
drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 11 +
drivers/gpu/drm/scheduler/sched_main.c | 3 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 21 +-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/tegra/dc.c | 2 +-
drivers/gpu/drm/tegra/dsi.c | 2 +-
drivers/gpu/drm/tegra/hdmi.c | 2 +-
drivers/gpu/drm/tegra/hub.c | 2 +-
drivers/gpu/drm/tegra/sor.c | 2 +-
drivers/gpu/drm/tegra/vic.c | 2 +-
drivers/gpu/drm/vc4/vc4_hdmi.c | 87 +++--
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +-
drivers/gpu/drm/virtio/virtgpu_gem.c | 8 +-
drivers/hid/hid-core.c | 3 +
drivers/hid/hid-logitech-dj.c | 1 +
drivers/hid/wacom_wac.c | 7 +-
drivers/hsi/controllers/omap_ssi_core.c | 2 +-
drivers/hv/channel_mgmt.c | 3 +-
drivers/hwtracing/coresight/coresight-etm4x-core.c | 21 +-
.../hwtracing/coresight/coresight-etm4x-sysfs.c | 2 +-
drivers/i2c/busses/i2c-bcm-iproc.c | 231 +++++++++++---
drivers/i2c/busses/i2c-brcmstb.c | 2 +-
drivers/i2c/busses/i2c-exynos5.c | 8 +-
drivers/i2c/busses/i2c-qcom-geni.c | 93 +++++-
drivers/ide/falconide.c | 3 +-
drivers/infiniband/core/cm.c | 8 +-
drivers/infiniband/core/cma.c | 70 +++--
drivers/infiniband/core/user_mad.c | 17 +-
drivers/infiniband/hw/hns/hns_roce_device.h | 2 +-
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 8 +-
drivers/infiniband/hw/hns/hns_roce_main.c | 3 +-
drivers/infiniband/hw/mlx5/devx.c | 4 +-
drivers/infiniband/hw/mlx5/main.c | 14 +-
drivers/infiniband/sw/rxe/rxe_net.c | 5 +
drivers/infiniband/sw/rxe/rxe_recv.c | 27 +-
drivers/infiniband/sw/siw/siw.h | 2 +-
drivers/infiniband/sw/siw/siw_main.c | 2 +-
drivers/infiniband/sw/siw/siw_qp.c | 271 ++++++++--------
drivers/infiniband/sw/siw/siw_qp_rx.c | 26 +-
drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +-
drivers/infiniband/sw/siw/siw_verbs.c | 20 +-
drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c | 2 +
drivers/infiniband/ulp/rtrs/rtrs-clt.c | 51 +--
drivers/infiniband/ulp/rtrs/rtrs-clt.h | 1 +
drivers/infiniband/ulp/rtrs/rtrs-pri.h | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 9 +-
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 117 ++++---
drivers/infiniband/ulp/rtrs/rtrs.c | 14 +-
drivers/input/joydev.c | 7 +-
drivers/input/joystick/xpad.c | 1 +
drivers/input/serio/i8042-x86ia64io.h | 4 +
drivers/input/serio/serport.c | 4 +-
drivers/input/touchscreen/elo.c | 4 +-
drivers/input/touchscreen/raydium_i2c_ts.c | 3 +-
drivers/input/touchscreen/sur40.c | 1 +
drivers/input/touchscreen/zinitix.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 +
drivers/iommu/iommu.c | 23 +-
drivers/iommu/mtk_iommu.c | 2 +-
drivers/irqchip/Kconfig | 3 +-
drivers/irqchip/irq-loongson-pch-msi.c | 2 +-
drivers/macintosh/adb-iop.c | 6 +-
drivers/mailbox/sprd-mailbox.c | 2 +-
drivers/md/bcache/bcache.h | 3 +
drivers/md/bcache/btree.c | 21 +-
drivers/md/bcache/journal.c | 4 +-
drivers/md/bcache/super.c | 20 ++
drivers/md/dm-core.h | 4 +
drivers/md/dm-crypt.c | 1 +
drivers/md/dm-era-target.c | 93 ++++--
drivers/md/dm-table.c | 168 +++++-----
drivers/md/dm-writecache.c | 74 +++--
drivers/md/dm.c | 62 +++-
drivers/md/dm.h | 2 +-
drivers/media/i2c/max9286.c | 2 +-
drivers/media/i2c/ov5670.c | 3 +-
drivers/media/pci/cx25821/cx25821-core.c | 4 +-
drivers/media/pci/intel/ipu3/Kconfig | 3 +-
drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +-
drivers/media/pci/saa7134/saa7134-empress.c | 5 +-
drivers/media/pci/smipcie/smipcie-ir.c | 46 +--
drivers/media/platform/aspeed-video.c | 6 +-
drivers/media/platform/marvell-ccic/mcam-core.c | 2 +
.../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 4 +-
.../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 3 +-
drivers/media/platform/pxa_camera.c | 3 +
drivers/media/platform/qcom/camss/camss-video.c | 1 +
drivers/media/platform/ti-vpe/cal.c | 4 +-
drivers/media/platform/vsp1/vsp1_drv.c | 4 +-
drivers/media/rc/ir_toy.c | 1 +
drivers/media/rc/mceusb.c | 2 +-
drivers/media/test-drivers/vidtv/vidtv_psi.c | 5 +-
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/mtk-smi.c | 4 +-
drivers/memory/ti-aemif.c | 8 +-
drivers/mfd/altera-sysmgr.c | 3 +-
drivers/mfd/bd9571mwv.c | 6 +-
drivers/mfd/gateworks-gsc.c | 2 +-
drivers/mfd/wm831x-auxadc.c | 3 +-
drivers/misc/cardreader/rts5227.c | 5 +
drivers/misc/eeprom/eeprom_93xx46.c | 1 +
drivers/misc/fastrpc.c | 7 +-
drivers/misc/mei/hbm.c | 2 +-
drivers/misc/mei/hw-me-regs.h | 5 +
drivers/misc/mei/interrupt.c | 33 +-
drivers/misc/mei/pci-me.c | 5 +
drivers/misc/vmw_vmci/vmci_queue_pair.c | 5 +-
drivers/mmc/host/owl-mmc.c | 9 +-
drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 +-
drivers/mmc/host/sdhci-esdhc-imx.c | 3 +-
drivers/mmc/host/sdhci-pci-o2micro.c | 20 ++
drivers/mmc/host/sdhci-sprd.c | 6 +-
drivers/mmc/host/usdhi6rol0.c | 4 +-
drivers/mtd/parsers/afs.c | 4 +-
drivers/mtd/parsers/parser_imagetag.c | 4 +
drivers/mtd/spi-nor/controllers/hisi-sfc.c | 4 +-
drivers/mtd/spi-nor/core.c | 10 +-
drivers/mtd/spi-nor/sfdp.c | 5 +-
drivers/net/Kconfig | 2 +-
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +-
drivers/net/dsa/ocelot/felix.c | 16 +-
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 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 4 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 3 +
drivers/net/ethernet/chelsio/cxgb4/sge.c | 11 +-
.../chelsio/inline_crypto/chtls/chtls_cm.h | 3 -
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 14 +-
drivers/net/ethernet/freescale/enetc/enetc_pf.c | 5 +-
drivers/net/ethernet/ibm/ibmvnic.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 50 +--
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 +-
drivers/net/ethernet/intel/ice/ice.h | 2 -
drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 6 +-
drivers/net/ethernet/intel/ice/ice_ethtool.c | 34 +-
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 33 +-
drivers/net/ethernet/marvell/mvneta.c | 9 +-
.../ethernet/marvell/octeontx2/af/rvu_debugfs.c | 2 +-
.../net/ethernet/mellanox/mlx4/resource_tracker.c | 1 +
drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 9 +
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 259 +++++++++++----
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/en/xsk/setup.c | 2 +-
.../mellanox/mlx5/core/en_accel/en_accel.h | 2 +-
.../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 66 ++--
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8 +-
drivers/net/ethernet/mellanox/mlx5/core/health.c | 22 +-
drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 +-
drivers/net/ethernet/realtek/r8169_main.c | 4 +-
.../net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 +-
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 26 +-
drivers/net/gtp.c | 1 -
drivers/net/phy/mscc/mscc.h | 8 +
drivers/net/phy/mscc/mscc_main.c | 350 ++++++++++++++-------
drivers/net/phy/phy_device.c | 53 +---
drivers/net/ppp/ppp_async.c | 3 +-
drivers/net/ppp/ppp_synctty.c | 3 +-
drivers/net/vxlan.c | 11 +-
drivers/net/wireguard/device.c | 19 +-
drivers/net/wireguard/device.h | 15 +-
drivers/net/wireguard/peer.c | 28 +-
drivers/net/wireguard/peer.h | 4 +-
drivers/net/wireguard/queueing.c | 86 ++++-
drivers/net/wireguard/queueing.h | 45 ++-
drivers/net/wireguard/receive.c | 16 +-
drivers/net/wireguard/send.c | 31 +-
drivers/net/wireless/ath/ath10k/mac.c | 2 +
drivers/net/wireless/ath/ath10k/snoc.c | 5 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 3 +
drivers/net/wireless/ath/ath11k/mac.c | 11 +-
drivers/net/wireless/ath/ath9k/debug.c | 5 +-
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 13 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 43 ++-
.../net/wireless/intel/iwlwifi/mvm/time-event.c | 3 -
.../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 21 +-
drivers/net/xen-netback/interface.c | 8 +-
drivers/nvme/host/multipath.c | 4 +
drivers/nvme/target/admin-cmd.c | 33 +-
drivers/nvme/target/tcp.c | 59 +++-
drivers/nvmem/core.c | 5 +-
drivers/nvmem/qcom-spmi-sdam.c | 7 +-
drivers/of/fdt.c | 12 +-
drivers/opp/of.c | 4 +-
drivers/pci/controller/cadence/pcie-cadence-host.c | 5 +-
drivers/pci/controller/dwc/pcie-qcom.c | 4 +-
drivers/pci/controller/pcie-rcar-host.c | 2 +-
drivers/pci/controller/pcie-rockchip.c | 12 +-
drivers/pci/controller/pcie-xilinx-cpm.c | 1 +
drivers/pci/pci-bridge-emul.c | 11 +-
drivers/pci/setup-res.c | 6 +
drivers/pci/syscall.c | 10 +-
drivers/perf/arm-cmn.c | 17 +-
drivers/phy/Kconfig | 1 +
drivers/phy/cadence/phy-cadence-torrent.c | 1 +
drivers/phy/lantiq/phy-lantiq-rcu-usb2.c | 10 +-
drivers/phy/rockchip/phy-rockchip-emmc.c | 8 +-
drivers/platform/chrome/cros_ec_proto.c | 12 +-
drivers/power/reset/at91-sama5d2_shdwc.c | 2 +-
drivers/power/supply/Kconfig | 1 +
drivers/power/supply/axp20x_usb_power.c | 2 +-
drivers/power/supply/cpcap-battery.c | 12 +-
drivers/power/supply/cpcap-charger.c | 4 +-
drivers/power/supply/smb347-charger.c | 12 +-
drivers/pwm/pwm-iqs620a.c | 8 +-
drivers/pwm/pwm-rockchip.c | 18 +-
drivers/regulator/axp20x-regulator.c | 7 +-
drivers/regulator/core.c | 6 +-
drivers/regulator/qcom-rpmh-regulator.c | 26 ++
drivers/regulator/rohm-regulator.c | 9 +-
drivers/regulator/s5m8767.c | 15 +-
drivers/remoteproc/mtk_common.h | 1 +
drivers/remoteproc/mtk_scp.c | 20 +-
drivers/rtc/Kconfig | 3 +-
drivers/s390/crypto/zcrypt_api.c | 14 +
drivers/s390/virtio/virtio_ccw.c | 4 +-
drivers/scsi/bnx2fc/Kconfig | 1 +
drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +-
drivers/scsi/qla2xxx/qla_dbg.c | 1 +
drivers/scsi/qla2xxx/qla_mbx.c | 3 +-
drivers/scsi/sd.c | 6 +-
drivers/scsi/sd_zbc.c | 6 +-
drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +-
drivers/soc/qcom/ocmem.c | 8 +-
drivers/soc/qcom/socinfo.c | 2 +-
drivers/soc/samsung/exynos-asv.c | 18 +-
drivers/soc/ti/pm33xx.c | 5 +-
drivers/soundwire/bus.c | 47 ++-
drivers/soundwire/cadence_master.c | 8 +-
drivers/soundwire/debugfs.c | 2 +-
drivers/soundwire/intel_init.c | 3 +-
drivers/spi/spi-atmel.c | 2 +-
drivers/spi/spi-cadence-quadspi.c | 2 +-
drivers/spi/spi-dw-bt1.c | 2 +-
drivers/spi/spi-fsl-spi.c | 2 +-
drivers/spi/spi-imx.c | 2 +-
drivers/spi/spi-pxa2xx-pci.c | 27 +-
drivers/spi/spi-stm32.c | 4 +
drivers/spi/spi-synquacer.c | 4 +
drivers/spi/spi.c | 2 +-
drivers/spmi/spmi-pmic-arb.c | 5 +-
drivers/staging/gdm724x/gdm_usb.c | 10 +-
drivers/staging/media/allegro-dvt/allegro-core.c | 3 +-
drivers/staging/media/atomisp/pci/atomisp_subdev.c | 24 +-
drivers/staging/media/atomisp/pci/hmm/hmm.c | 2 +-
drivers/staging/media/imx/imx-media-csc-scaler.c | 4 -
drivers/staging/media/imx/imx-media-dev.c | 7 +-
drivers/staging/media/imx/imx7-media-csi.c | 27 +-
drivers/staging/mt7621-dma/Makefile | 2 +-
.../mt7621-dma/{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 +-
.../vc04_services/interface/vchiq_arm/vchiq_arm.c | 6 +-
drivers/staging/wfx/data_tx.c | 10 +-
drivers/staging/wfx/data_tx.h | 1 +
drivers/target/iscsi/cxgbit/cxgbit_target.c | 3 +-
drivers/tee/optee/rpc.c | 31 +-
drivers/thermal/cpufreq_cooling.c | 2 +-
drivers/tty/n_gsm.c | 3 +-
drivers/tty/n_hdlc.c | 60 ++--
drivers/tty/n_null.c | 3 +-
drivers/tty/n_r3964.c | 10 +-
drivers/tty/n_tracerouter.c | 4 +-
drivers/tty/n_tracesink.c | 4 +-
drivers/tty/n_tty.c | 82 ++---
drivers/tty/tty_io.c | 82 ++++-
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/usb/serial/pl2303.c | 8 +-
drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
drivers/vfio/pci/vfio_pci_zdev.c | 4 +
drivers/vfio/vfio_iommu_type1.c | 63 ++--
drivers/video/fbdev/Kconfig | 2 +-
drivers/virt/vboxguest/vboxguest_utils.c | 18 +-
drivers/w1/slaves/w1_therm.c | 22 +-
drivers/watchdog/intel-mid_wdt.c | 8 +-
drivers/watchdog/mei_wdt.c | 1 +
drivers/watchdog/qcom-wdt.c | 13 +-
fs/affs/namei.c | 4 +-
fs/btrfs/backref.c | 9 +-
fs/btrfs/backref.h | 9 +-
fs/btrfs/block-group.c | 29 +-
fs/btrfs/ctree.c | 7 +-
fs/btrfs/delayed-ref.c | 56 ++--
fs/btrfs/delayed-ref.h | 16 +-
fs/btrfs/extent-tree.c | 128 ++------
fs/btrfs/free-space-cache.c | 6 +-
fs/btrfs/inode.c | 3 +-
fs/btrfs/relocation.c | 4 +-
fs/btrfs/space-info.h | 17 +
fs/ceph/caps.c | 10 +-
fs/debugfs/inode.c | 5 +-
fs/erofs/xattr.c | 10 +-
fs/erofs/zmap.c | 10 +-
fs/eventpoll.c | 4 +-
fs/exfat/exfat_raw.h | 4 +
fs/exfat/super.c | 31 +-
fs/ext4/Kconfig | 3 +-
fs/ext4/namei.c | 7 +-
fs/f2fs/compress.c | 5 +-
fs/f2fs/data.c | 12 +-
fs/f2fs/f2fs.h | 2 +-
fs/f2fs/file.c | 24 +-
fs/f2fs/inline.c | 4 +
fs/f2fs/super.c | 3 +
fs/gfs2/bmap.c | 6 +-
fs/gfs2/lock_dlm.c | 8 +-
fs/gfs2/recovery.c | 4 +-
fs/gfs2/util.c | 16 +-
fs/io_uring.c | 17 +-
fs/isofs/dir.c | 1 +
fs/isofs/namei.c | 1 +
fs/jffs2/summary.c | 3 +
fs/jfs/jfs_dmap.c | 2 +-
fs/nfs/nfs4proc.c | 15 +-
fs/nfsd/nfsctl.c | 14 +-
fs/ocfs2/cluster/heartbeat.c | 8 +-
fs/proc/proc_sysctl.c | 4 +-
fs/proc/self.c | 2 +-
fs/proc/task_mmu.c | 9 +-
fs/proc/thread_self.c | 7 +
fs/pstore/platform.c | 4 +-
fs/quota/quota_v2.c | 11 +-
fs/ubifs/auth.c | 2 +-
fs/ubifs/replay.c | 4 +-
fs/ubifs/super.c | 4 +-
fs/zonefs/super.c | 3 +
include/acpi/acexcep.h | 10 +-
include/asm-generic/vmlinux.lds.h | 16 +-
include/linux/bpf.h | 3 +
include/linux/device-mapper.h | 5 +
include/linux/entry-kvm.h | 14 +
include/linux/eventpoll.h | 2 +-
include/linux/filter.h | 2 +-
include/linux/icmpv6.h | 28 +-
include/linux/iommu.h | 4 +-
include/linux/ipv6.h | 1 -
include/linux/kexec.h | 5 +
include/linux/key.h | 1 +
include/linux/kgdb.h | 2 +
include/linux/khugepaged.h | 2 +
include/linux/memremap.h | 6 +
include/linux/mfd/rohm-generic.h | 14 +-
include/linux/rcupdate.h | 2 +
include/linux/rmap.h | 3 +-
include/linux/soundwire/sdw.h | 2 +
include/linux/tpm.h | 5 +-
include/linux/tty_ldisc.h | 3 +-
include/net/act_api.h | 6 +-
include/net/icmp.h | 6 +-
include/net/tcp.h | 9 +-
include/uapi/drm/drm_fourcc.h | 4 +-
init/Kconfig | 11 +
init/main.c | 1 +
kernel/Makefile | 2 +-
kernel/bpf/bpf_iter.c | 2 +-
kernel/bpf/bpf_lru_list.c | 7 +-
kernel/bpf/devmap.c | 4 +-
kernel/bpf/verifier.c | 3 +-
kernel/debug/debug_core.c | 11 +
kernel/debug/kdb/kdb_private.h | 2 +-
kernel/entry/common.c | 7 +
kernel/kcsan/core.c | 26 +-
kernel/kexec_file.c | 5 +
kernel/kprobes.c | 31 +-
kernel/locking/lockdep.c | 3 +-
kernel/module.c | 21 +-
kernel/printk/printk.c | 28 +-
kernel/printk/printk_safe.c | 16 +-
kernel/rcu/tree.c | 53 +++-
kernel/rcu/tree.h | 2 +-
kernel/rcu/tree_plugin.h | 31 +-
kernel/sched/fair.c | 45 ++-
kernel/sched/idle.c | 1 +
kernel/seccomp.c | 2 +
kernel/smp.c | 4 +
kernel/tracepoint.c | 80 ++++-
mm/compaction.c | 43 +--
mm/hugetlb.c | 14 +-
mm/khugepaged.c | 22 +-
mm/memcontrol.c | 30 +-
mm/memory-failure.c | 6 +
mm/memory.c | 16 +-
mm/memremap.c | 15 +
mm/slab_common.c | 4 +-
mm/slub.c | 8 +-
mm/vmscan.c | 9 +-
net/bluetooth/a2mp.c | 3 +-
net/bluetooth/hci_core.c | 6 +-
net/core/filter.c | 13 +-
net/ipv4/icmp.c | 5 +-
net/ipv6/icmp.c | 18 +-
net/ipv6/ip6_icmp.c | 12 +-
net/mac80211/mesh_hwmp.c | 2 +-
net/nfc/nci/uart.c | 3 +-
net/qrtr/tun.c | 12 +-
net/sched/act_api.c | 106 ++++---
net/sched/cls_api.c | 12 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 6 +-
samples/Kconfig | 2 +-
samples/watch_queue/watch_test.c | 2 +-
security/commoncap.c | 12 +-
security/integrity/evm/evm_crypto.c | 7 +-
security/integrity/ima/ima_kexec.c | 3 +
security/integrity/ima/ima_mok.c | 5 +-
security/keys/Kconfig | 8 +-
security/keys/key.c | 2 +
security/keys/trusted-keys/trusted_tpm1.c | 22 +-
security/keys/trusted-keys/trusted_tpm2.c | 22 +-
security/selinux/hooks.c | 4 +
sound/core/init.c | 4 +
sound/core/pcm.c | 4 +
sound/core/pcm_local.h | 1 +
sound/core/pcm_native.c | 27 +-
sound/firewire/fireface/ff-protocol-latter.c | 118 +++++--
sound/pci/hda/hda_intel.c | 2 +
sound/pci/hda/patch_hdmi.c | 1 -
sound/pci/hda/patch_realtek.c | 40 +++
sound/soc/codecs/cpcap.c | 12 +-
sound/soc/codecs/cs42l56.c | 3 +-
sound/soc/codecs/rt5682-i2c.c | 3 +
sound/soc/codecs/wsa881x.c | 1 +
sound/soc/generic/simple-card-utils.c | 13 +-
sound/soc/intel/boards/sof_sdw.c | 6 +-
sound/soc/qcom/lpass-apq8016.c | 2 +-
sound/soc/qcom/lpass-cpu.c | 30 +-
sound/soc/qcom/lpass-lpaif-reg.h | 3 -
sound/soc/qcom/lpass.h | 1 -
sound/soc/qcom/qdsp6/q6asm-dai.c | 21 ++
sound/soc/qcom/qdsp6/q6routing.c | 18 --
sound/soc/sh/siu.h | 2 +-
sound/soc/sh/siu_pcm.c | 2 +-
sound/soc/sof/debug.c | 2 +-
sound/soc/sof/intel/hda-dsp.c | 4 +
sound/soc/sof/sof-pci-dev.c | 7 +
sound/usb/pcm.c | 2 +-
tools/lib/bpf/libbpf.c | 22 +-
tools/objtool/arch/x86/special.c | 2 +-
tools/objtool/check.c | 15 +-
tools/objtool/check.h | 11 +
tools/perf/builtin-record.c | 2 +-
.../pmu-events/arch/arm64/ampere/emag/cache.json | 2 +-
tools/perf/tests/sample-parsing.c | 2 +-
tools/perf/util/event.c | 2 +
tools/perf/util/evlist.c | 8 +
tools/perf/util/evlist.h | 4 +
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 41 ++-
.../perf/util/intel-pt-decoder/intel-pt-decoder.h | 2 +
tools/perf/util/intel-pt.c | 29 +-
tools/perf/util/symbol.c | 7 +-
tools/testing/kunit/kunit_tool_test.py | 14 +-
tools/testing/selftests/bpf/test_xdp_redirect.sh | 10 +-
tools/testing/selftests/dmabuf-heaps/Makefile | 2 +-
.../trigger-synthetic_event_syntax_errors.tc | 35 ++-
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 2 +-
tools/testing/selftests/powerpc/eeh/eeh-basic.sh | 2 +-
tools/testing/selftests/seccomp/seccomp_bpf.c | 2 +-
tools/testing/selftests/wireguard/netns.sh | 15 +-
672 files changed, 5877 insertions(+), 3028 deletions(-)
^ permalink raw reply [relevance 1%]
* [PATCH 5.10 316/663] watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready
2021-03-01 16:04 1% [PATCH 5.10 000/663] 5.10.20-rc1 review Greg Kroah-Hartman
@ 2021-03-01 16:09 7% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2021-03-01 16:09 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Andy Shevchenko, Guenter Roeck,
Linus Walleij, Mika Westerberg, Sasha Levin
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
[ Upstream commit f285c9532b5bd3de7e37a6203318437cab79bd9a ]
When SCU is not ready and CONFIG_DEBUG_SHIRQ=y we got deferred probe followed
by fired test IRQ which immediately makes kernel panic. Fix this by delaying
IRQ handler registration till SCU is ready.
Fixes: 80ae679b8f86 ("watchdog: intel-mid_wdt: Convert to use new SCU IPC API")
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/watchdog/intel-mid_wdt.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c
index 1ae03b64ef8bf..9b2173f765c8c 100644
--- a/drivers/watchdog/intel-mid_wdt.c
+++ b/drivers/watchdog/intel-mid_wdt.c
@@ -154,6 +154,10 @@ static int mid_wdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT);
watchdog_set_drvdata(wdt_dev, mid);
+ mid->scu = devm_intel_scu_ipc_dev_get(dev);
+ if (!mid->scu)
+ return -EPROBE_DEFER;
+
ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq,
IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog",
wdt_dev);
@@ -162,10 +166,6 @@ static int mid_wdt_probe(struct platform_device *pdev)
return ret;
}
- mid->scu = devm_intel_scu_ipc_dev_get(dev);
- if (!mid->scu)
- return -EPROBE_DEFER;
-
/*
* The firmware followed by U-Boot leaves the watchdog running
* with the default threshold which may vary. When we get here
--
2.27.0
^ permalink raw reply related [relevance 7%]
* [PATCH AUTOSEL 5.10 071/217] RDMA/core: Postpone uobject cleanup on failure till FD close
@ 2020-12-23 2:14 3% ` Sasha Levin
0 siblings, 0 replies; 200+ results
From: Sasha Levin @ 2020-12-23 2:14 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Leon Romanovsky, Jason Gunthorpe, Sasha Levin, linux-rdma
From: Leon Romanovsky <leonro@nvidia.com>
[ Upstream commit efa968ee20248ebf8da8542f21d5d2811e86392f ]
Remove the ib_is_destroyable_retryable() concept.
The idea here was to allow the drivers to forcibly clean the HW object
even if they otherwise didn't want to (eg because of usecnt). This was an
attempt to clean up in a world where drivers were not allowed to fail HW
object destruction.
Now that we are going back to allowing HW objects to fail destroy this
doesn't make sense. Instead if a uobject's HW object can't be destroyed it
is left on the uobject list and it is up to uverbs_destroy_ufile_hw() to
clean it. Multiple passes over the uobject list allow hidden dependencies
to be resolved. If that fails the HW driver is broken, throw a WARN_ON and
leak the HW object memory.
All the other tricky failure paths (eg on creation error unwind) have
already been updated to this new model.
Link: https://lore.kernel.org/r/20201104144556.3809085-2-leon@kernel.org
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/infiniband/core/rdma_core.c | 51 +++++++------------
drivers/infiniband/core/uverbs_cmd.c | 5 +-
drivers/infiniband/core/uverbs_std_types.c | 15 +++---
.../core/uverbs_std_types_counters.c | 5 +-
drivers/infiniband/core/uverbs_std_types_cq.c | 4 +-
drivers/infiniband/core/uverbs_std_types_dm.c | 6 +--
.../core/uverbs_std_types_flow_action.c | 6 +--
drivers/infiniband/core/uverbs_std_types_qp.c | 4 +-
.../infiniband/core/uverbs_std_types_srq.c | 4 +-
drivers/infiniband/core/uverbs_std_types_wq.c | 4 +-
drivers/infiniband/hw/mlx5/devx.c | 4 +-
drivers/infiniband/hw/mlx5/fs.c | 6 +--
include/rdma/ib_verbs.h | 44 +---------------
13 files changed, 45 insertions(+), 113 deletions(-)
diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index ffe11b03724cf..61fa0a3f8e5ee 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -137,15 +137,9 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj,
} else if (uobj->object) {
ret = uobj->uapi_object->type_class->destroy_hw(uobj, reason,
attrs);
- if (ret) {
- if (ib_is_destroy_retryable(ret, reason, uobj))
- return ret;
-
- /* Nothing to be done, dangle the memory and move on */
- WARN(true,
- "ib_uverbs: failed to remove uobject id %d, driver err=%d",
- uobj->id, ret);
- }
+ if (ret)
+ /* Nothing to be done, wait till ucontext will clean it */
+ return ret;
uobj->object = NULL;
}
@@ -543,12 +537,7 @@ static int __must_check destroy_hw_idr_uobject(struct ib_uobject *uobj,
struct uverbs_obj_idr_type, type);
int ret = idr_type->destroy_object(uobj, why, attrs);
- /*
- * We can only fail gracefully if the user requested to destroy the
- * object or when a retry may be called upon an error.
- * In the rest of the cases, just remove whatever you can.
- */
- if (ib_is_destroy_retryable(ret, why, uobj))
+ if (ret)
return ret;
if (why == RDMA_REMOVE_ABORT)
@@ -581,12 +570,8 @@ static int __must_check destroy_hw_fd_uobject(struct ib_uobject *uobj,
{
const struct uverbs_obj_fd_type *fd_type = container_of(
uobj->uapi_object->type_attrs, struct uverbs_obj_fd_type, type);
- int ret = fd_type->destroy_object(uobj, why);
- if (ib_is_destroy_retryable(ret, why, uobj))
- return ret;
-
- return 0;
+ return fd_type->destroy_object(uobj, why);
}
static void remove_handle_fd_uobject(struct ib_uobject *uobj)
@@ -863,11 +848,18 @@ static int __uverbs_cleanup_ufile(struct ib_uverbs_file *ufile,
* racing with a lookup_get.
*/
WARN_ON(uverbs_try_lock_object(obj, UVERBS_LOOKUP_WRITE));
+ if (reason == RDMA_REMOVE_DRIVER_FAILURE)
+ obj->object = NULL;
if (!uverbs_destroy_uobject(obj, reason, &attrs))
ret = 0;
else
atomic_set(&obj->usecnt, 0);
}
+
+ if (reason == RDMA_REMOVE_DRIVER_FAILURE) {
+ WARN_ON(!list_empty(&ufile->uobjects));
+ return 0;
+ }
return ret;
}
@@ -889,21 +881,12 @@ void uverbs_destroy_ufile_hw(struct ib_uverbs_file *ufile,
if (!ufile->ucontext)
goto done;
- ufile->ucontext->cleanup_retryable = true;
- while (!list_empty(&ufile->uobjects))
- if (__uverbs_cleanup_ufile(ufile, reason)) {
- /*
- * No entry was cleaned-up successfully during this
- * iteration. It is a driver bug to fail destruction.
- */
- WARN_ON(!list_empty(&ufile->uobjects));
- break;
- }
-
- ufile->ucontext->cleanup_retryable = false;
- if (!list_empty(&ufile->uobjects))
- __uverbs_cleanup_ufile(ufile, reason);
+ while (!list_empty(&ufile->uobjects) &&
+ !__uverbs_cleanup_ufile(ufile, reason)) {
+ }
+ if (WARN_ON(!list_empty(&ufile->uobjects)))
+ __uverbs_cleanup_ufile(ufile, RDMA_REMOVE_DRIVER_FAILURE);
ufile_destroy_ucontext(ufile, reason);
done:
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 418d133a8fb08..c05be41f0199d 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -681,8 +681,7 @@ int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd,
return 0;
ret = ib_dealloc_xrcd_user(xrcd, &attrs->driver_udata);
-
- if (ib_is_destroy_retryable(ret, why, uobject)) {
+ if (ret) {
atomic_inc(&xrcd->usecnt);
return ret;
}
@@ -690,7 +689,7 @@ int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd,
if (inode)
xrcd_table_delete(dev, inode);
- return ret;
+ return 0;
}
static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
diff --git a/drivers/infiniband/core/uverbs_std_types.c b/drivers/infiniband/core/uverbs_std_types.c
index 0658101fca004..585042ead9392 100644
--- a/drivers/infiniband/core/uverbs_std_types.c
+++ b/drivers/infiniband/core/uverbs_std_types.c
@@ -88,7 +88,7 @@ static int uverbs_free_rwq_ind_tbl(struct ib_uobject *uobject,
return -EBUSY;
ret = rwq_ind_tbl->device->ops.destroy_rwq_ind_table(rwq_ind_tbl);
- if (ib_is_destroy_retryable(ret, why, uobject))
+ if (ret)
return ret;
for (i = 0; i < table_size; i++)
@@ -96,7 +96,7 @@ static int uverbs_free_rwq_ind_tbl(struct ib_uobject *uobject,
kfree(rwq_ind_tbl);
kfree(ind_tbl);
- return ret;
+ return 0;
}
static int uverbs_free_xrcd(struct ib_uobject *uobject,
@@ -108,9 +108,8 @@ static int uverbs_free_xrcd(struct ib_uobject *uobject,
container_of(uobject, struct ib_uxrcd_object, uobject);
int ret;
- ret = ib_destroy_usecnt(&uxrcd->refcnt, why, uobject);
- if (ret)
- return ret;
+ if (atomic_read(&uxrcd->refcnt))
+ return -EBUSY;
mutex_lock(&attrs->ufile->device->xrcd_tree_mutex);
ret = ib_uverbs_dealloc_xrcd(uobject, xrcd, why, attrs);
@@ -124,11 +123,9 @@ static int uverbs_free_pd(struct ib_uobject *uobject,
struct uverbs_attr_bundle *attrs)
{
struct ib_pd *pd = uobject->object;
- int ret;
- ret = ib_destroy_usecnt(&pd->usecnt, why, uobject);
- if (ret)
- return ret;
+ if (atomic_read(&pd->usecnt))
+ return -EBUSY;
return ib_dealloc_pd_user(pd, &attrs->driver_udata);
}
diff --git a/drivers/infiniband/core/uverbs_std_types_counters.c b/drivers/infiniband/core/uverbs_std_types_counters.c
index b3c6c066b6010..999da9c798668 100644
--- a/drivers/infiniband/core/uverbs_std_types_counters.c
+++ b/drivers/infiniband/core/uverbs_std_types_counters.c
@@ -42,9 +42,8 @@ static int uverbs_free_counters(struct ib_uobject *uobject,
struct ib_counters *counters = uobject->object;
int ret;
- ret = ib_destroy_usecnt(&counters->usecnt, why, uobject);
- if (ret)
- return ret;
+ if (atomic_read(&counters->usecnt))
+ return -EBUSY;
ret = counters->device->ops.destroy_counters(counters);
if (ret)
diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c
index 8dabd05988b23..370ad7c83f880 100644
--- a/drivers/infiniband/core/uverbs_std_types_cq.c
+++ b/drivers/infiniband/core/uverbs_std_types_cq.c
@@ -46,7 +46,7 @@ static int uverbs_free_cq(struct ib_uobject *uobject,
int ret;
ret = ib_destroy_cq_user(cq, &attrs->driver_udata);
- if (ib_is_destroy_retryable(ret, why, uobject))
+ if (ret)
return ret;
ib_uverbs_release_ucq(
@@ -55,7 +55,7 @@ static int uverbs_free_cq(struct ib_uobject *uobject,
ev_queue) :
NULL,
ucq);
- return ret;
+ return 0;
}
static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
diff --git a/drivers/infiniband/core/uverbs_std_types_dm.c b/drivers/infiniband/core/uverbs_std_types_dm.c
index d5a1de33c2c9a..98c522cf86d6f 100644
--- a/drivers/infiniband/core/uverbs_std_types_dm.c
+++ b/drivers/infiniband/core/uverbs_std_types_dm.c
@@ -39,11 +39,9 @@ static int uverbs_free_dm(struct ib_uobject *uobject,
struct uverbs_attr_bundle *attrs)
{
struct ib_dm *dm = uobject->object;
- int ret;
- ret = ib_destroy_usecnt(&dm->usecnt, why, uobject);
- if (ret)
- return ret;
+ if (atomic_read(&dm->usecnt))
+ return -EBUSY;
return dm->device->ops.dealloc_dm(dm, attrs);
}
diff --git a/drivers/infiniband/core/uverbs_std_types_flow_action.c b/drivers/infiniband/core/uverbs_std_types_flow_action.c
index 459cf165b231e..d42ed7ff223e3 100644
--- a/drivers/infiniband/core/uverbs_std_types_flow_action.c
+++ b/drivers/infiniband/core/uverbs_std_types_flow_action.c
@@ -39,11 +39,9 @@ static int uverbs_free_flow_action(struct ib_uobject *uobject,
struct uverbs_attr_bundle *attrs)
{
struct ib_flow_action *action = uobject->object;
- int ret;
- ret = ib_destroy_usecnt(&action->usecnt, why, uobject);
- if (ret)
- return ret;
+ if (atomic_read(&action->usecnt))
+ return -EBUSY;
return action->device->ops.destroy_flow_action(action);
}
diff --git a/drivers/infiniband/core/uverbs_std_types_qp.c b/drivers/infiniband/core/uverbs_std_types_qp.c
index 3bf8dcdfe7eb6..294cd29d5cede 100644
--- a/drivers/infiniband/core/uverbs_std_types_qp.c
+++ b/drivers/infiniband/core/uverbs_std_types_qp.c
@@ -32,14 +32,14 @@ static int uverbs_free_qp(struct ib_uobject *uobject,
}
ret = ib_destroy_qp_user(qp, &attrs->driver_udata);
- if (ib_is_destroy_retryable(ret, why, uobject))
+ if (ret)
return ret;
if (uqp->uxrcd)
atomic_dec(&uqp->uxrcd->refcnt);
ib_uverbs_release_uevent(&uqp->uevent);
- return ret;
+ return 0;
}
static int check_creation_flags(enum ib_qp_type qp_type,
diff --git a/drivers/infiniband/core/uverbs_std_types_srq.c b/drivers/infiniband/core/uverbs_std_types_srq.c
index c0ecbba26bf49..e5513f828bdc1 100644
--- a/drivers/infiniband/core/uverbs_std_types_srq.c
+++ b/drivers/infiniband/core/uverbs_std_types_srq.c
@@ -18,7 +18,7 @@ static int uverbs_free_srq(struct ib_uobject *uobject,
int ret;
ret = ib_destroy_srq_user(srq, &attrs->driver_udata);
- if (ib_is_destroy_retryable(ret, why, uobject))
+ if (ret)
return ret;
if (srq_type == IB_SRQT_XRC) {
@@ -30,7 +30,7 @@ static int uverbs_free_srq(struct ib_uobject *uobject,
}
ib_uverbs_release_uevent(uevent);
- return ret;
+ return 0;
}
static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_CREATE)(
diff --git a/drivers/infiniband/core/uverbs_std_types_wq.c b/drivers/infiniband/core/uverbs_std_types_wq.c
index f2e6a625724a4..7ded8339346f3 100644
--- a/drivers/infiniband/core/uverbs_std_types_wq.c
+++ b/drivers/infiniband/core/uverbs_std_types_wq.c
@@ -17,11 +17,11 @@ static int uverbs_free_wq(struct ib_uobject *uobject,
int ret;
ret = ib_destroy_wq_user(wq, &attrs->driver_udata);
- if (ib_is_destroy_retryable(ret, why, uobject))
+ if (ret)
return ret;
ib_uverbs_release_uevent(&uwq->uevent);
- return ret;
+ return 0;
}
static int UVERBS_HANDLER(UVERBS_METHOD_WQ_CREATE)(
diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index 9e3d8b8264980..cb9b263f6bf30 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -1311,7 +1311,7 @@ static int devx_obj_cleanup(struct ib_uobject *uobject,
else
ret = mlx5_cmd_exec(obj->ib_dev->mdev, obj->dinbox,
obj->dinlen, out, sizeof(out));
- if (ib_is_destroy_retryable(ret, why, uobject))
+ if (ret)
return ret;
devx_event_table = &dev->devx_event_table;
@@ -2187,7 +2187,7 @@ static int devx_umem_cleanup(struct ib_uobject *uobject,
int err;
err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
- if (ib_is_destroy_retryable(err, why, uobject))
+ if (err)
return err;
ib_umem_release(obj->umem);
diff --git a/drivers/infiniband/hw/mlx5/fs.c b/drivers/infiniband/hw/mlx5/fs.c
index 492cfe063bcad..25da0b05b4e2f 100644
--- a/drivers/infiniband/hw/mlx5/fs.c
+++ b/drivers/infiniband/hw/mlx5/fs.c
@@ -2035,11 +2035,9 @@ static int flow_matcher_cleanup(struct ib_uobject *uobject,
struct uverbs_attr_bundle *attrs)
{
struct mlx5_ib_flow_matcher *obj = uobject->object;
- int ret;
- ret = ib_destroy_usecnt(&obj->usecnt, why, uobject);
- if (ret)
- return ret;
+ if (atomic_read(&obj->usecnt))
+ return -EBUSY;
kfree(obj);
return 0;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 9bf6c319a670e..a767ca63f08d7 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1469,6 +1469,8 @@ enum rdma_remove_reason {
RDMA_REMOVE_DRIVER_REMOVE,
/* uobj is being cleaned-up before being committed */
RDMA_REMOVE_ABORT,
+ /* The driver failed to destroy the uobject and is being disconnected */
+ RDMA_REMOVE_DRIVER_FAILURE,
};
struct ib_rdmacg_object {
@@ -1481,8 +1483,6 @@ struct ib_ucontext {
struct ib_device *device;
struct ib_uverbs_file *ufile;
- bool cleanup_retryable;
-
struct ib_rdmacg_object cg_obj;
/*
* Implementation details of the RDMA core, don't use in drivers:
@@ -2900,46 +2900,6 @@ static inline bool ib_is_udata_cleared(struct ib_udata *udata,
return ib_is_buffer_cleared(udata->inbuf + offset, len);
}
-/**
- * ib_is_destroy_retryable - Check whether the uobject destruction
- * is retryable.
- * @ret: The initial destruction return code
- * @why: remove reason
- * @uobj: The uobject that is destroyed
- *
- * This function is a helper function that IB layer and low-level drivers
- * can use to consider whether the destruction of the given uobject is
- * retry-able.
- * It checks the original return code, if it wasn't success the destruction
- * is retryable according to the ucontext state (i.e. cleanup_retryable) and
- * the remove reason. (i.e. why).
- * Must be called with the object locked for destroy.
- */
-static inline bool ib_is_destroy_retryable(int ret, enum rdma_remove_reason why,
- struct ib_uobject *uobj)
-{
- return ret && (why == RDMA_REMOVE_DESTROY ||
- uobj->context->cleanup_retryable);
-}
-
-/**
- * ib_destroy_usecnt - Called during destruction to check the usecnt
- * @usecnt: The usecnt atomic
- * @why: remove reason
- * @uobj: The uobject that is destroyed
- *
- * Non-zero usecnts will block destruction unless destruction was triggered by
- * a ucontext cleanup.
- */
-static inline int ib_destroy_usecnt(atomic_t *usecnt,
- enum rdma_remove_reason why,
- struct ib_uobject *uobj)
-{
- if (atomic_read(usecnt) && ib_is_destroy_retryable(-EBUSY, why, uobj))
- return -EBUSY;
- return 0;
-}
-
/**
* ib_modify_qp_is_ok - Check that the supplied attribute mask
* contains all required attributes and no attributes not allowed for
--
2.27.0
^ permalink raw reply related [relevance 3%]
* Linux 5.9.11
@ 2020-11-24 16:51 1% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2020-11-24 16:51 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.9.11 kernel.
All users of the 5.9 kernel series must upgrade.
The updated 5.9.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.9.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/xtensa/mmu.rst | 9
Makefile | 2
arch/arm/boot/compressed/head.S | 3
arch/arm/boot/dts/imx50-evk.dts | 2
arch/arm/boot/dts/imx6q-prti6q.dts | 4
arch/arm/boot/dts/imx6qdl-udoo.dtsi | 2
arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi | 19 -
arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi | 2
arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi | 4
arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 2
arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 2
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 2
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts | 2
arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts | 2
arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts | 5
arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts | 2
arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts | 2
arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 2
arch/arm/boot/dts/sun9i-a80-optimus.dts | 2
arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi | 2
arch/arm/boot/dts/vf610-zii-dev-rev-b.dts | 3
arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h5-cc.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 2
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts | 2
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts | 2
arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 1
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 1
arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 1
arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi | 1
arch/arm64/boot/dts/freescale/imx8mm.dtsi | 2
arch/arm64/boot/dts/freescale/imx8mn.dtsi | 30 --
arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts | 2
arch/arm64/include/asm/cpufeature.h | 2
arch/arm64/include/asm/cputype.h | 4
arch/arm64/kernel/cpu_errata.c | 2
arch/arm64/kernel/cpufeature.c | 2
arch/arm64/kernel/process.c | 5
arch/arm64/kernel/psci.c | 5
arch/arm64/kernel/smp.c | 1
arch/mips/alchemy/common/clock.c | 9
arch/mips/mm/tlb-r4k.c | 1
arch/s390/kernel/entry.S | 2
arch/s390/kernel/perf_cpum_sf.c | 2
arch/um/include/asm/pgalloc.h | 8
arch/x86/kernel/cpu/microcode/intel.c | 63 -----
arch/x86/kernel/tboot.c | 3
arch/x86/platform/efi/efi_64.c | 24 +-
arch/xtensa/include/asm/pgtable.h | 2
arch/xtensa/mm/cache.c | 14 +
block/blk-cgroup.c | 1
drivers/accessibility/speakup/spk_ttyio.c | 12 -
drivers/acpi/button.c | 13 +
drivers/acpi/fan.c | 1
drivers/atm/nicstar.c | 2
drivers/counter/ti-eqep.c | 4
drivers/dma/dmaengine.c | 17 -
drivers/dma/idxd/device.c | 31 +-
drivers/dma/idxd/idxd.h | 3
drivers/dma/idxd/init.c | 5
drivers/dma/idxd/registers.h | 25 ++
drivers/dma/idxd/submit.c | 2
drivers/dma/ti/omap-dma.c | 37 ++-
drivers/dma/xilinx/xilinx_dma.c | 36 ++-
drivers/gpio/gpio-omap.c | 12 -
drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c | 4
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 6
drivers/gpu/drm/i915/display/intel_display.c | 3
drivers/gpu/drm/i915/gt/intel_rc6.c | 22 +
drivers/gpu/drm/i915/i915_reg.h | 12 -
drivers/gpu/drm/i915/intel_pm.c | 13 -
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 1
drivers/hid/hid-logitech-dj.c | 22 +
drivers/hid/hid-logitech-hidpp.c | 26 ++
drivers/hid/hid-mcp2221.c | 48 +++-
drivers/hv/hv.c | 8
drivers/hwmon/pwm-fan.c | 16 -
drivers/iio/accel/kxcjk-1013.c | 51 ++++
drivers/iio/adc/ingenic-adc.c | 34 ++
drivers/iio/adc/mt6577_auxadc.c | 6
drivers/iio/adc/stm32-adc-core.c | 41 +--
drivers/iio/adc/stm32-adc.c | 50 ++++
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 16 -
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 6
drivers/iio/light/Kconfig | 1
drivers/infiniband/Kconfig | 3
drivers/infiniband/hw/hfi1/chip.c | 3
drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c | 2
drivers/infiniband/sw/rdmavt/Kconfig | 3
drivers/infiniband/sw/rxe/Kconfig | 2
drivers/infiniband/sw/siw/Kconfig | 1
drivers/input/misc/adxl34x.c | 2
drivers/input/mouse/elan_i2c.h | 2
drivers/input/mouse/elan_i2c_core.c | 3
drivers/input/mouse/elan_i2c_i2c.c | 10
drivers/input/mouse/elan_i2c_smbus.c | 2
drivers/input/touchscreen/Kconfig | 1
drivers/iommu/intel/iommu.c | 5
drivers/misc/habanalabs/include/gaudi/gaudi_masks.h | 1
drivers/mmc/host/sdhci-of-arasan.c | 51 +---
drivers/mmc/host/sdhci-pci-core.c | 13 -
drivers/net/can/dev.c | 2
drivers/net/can/flexcan.c | 26 +-
drivers/net/can/kvaser_pciefd.c | 4
drivers/net/can/m_can/Kconfig | 3
drivers/net/can/m_can/m_can.c | 18 +
drivers/net/can/m_can/m_can.h | 1
drivers/net/can/m_can/m_can_platform.c | 23 +-
drivers/net/can/m_can/tcan4x5x.c | 32 ++
drivers/net/can/ti_hecc.c | 13 -
drivers/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/lantiq_gswip.c | 11
drivers/net/dsa/mv88e6xxx/global1_vtu.c | 59 ++++-
drivers/net/ethernet/broadcom/b44.c | 3
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2
drivers/net/ethernet/faraday/ftgmac100.c | 4
drivers/net/ethernet/freescale/enetc/Kconfig | 1
drivers/net/ethernet/freescale/enetc/enetc.c | 62 +++--
drivers/net/ethernet/freescale/enetc/enetc_hw.h | 115 +++++++++-
drivers/net/ethernet/freescale/enetc/enetc_mdio.c | 8
drivers/net/ethernet/freescale/fec_main.c | 12 -
drivers/net/ethernet/marvell/mvneta.c | 5
drivers/net/ethernet/mediatek/mtk_star_emac.c | 3
drivers/net/ethernet/mellanox/mlx4/fw.c | 6
drivers/net/ethernet/mellanox/mlx4/fw.h | 4
drivers/net/ethernet/mellanox/mlx5/core/en/rep/bond.c | 2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c | 13 -
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 20 +
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 7
drivers/net/ethernet/mellanox/mlxsw/core.c | 3
drivers/net/ethernet/microchip/lan743x_main.c | 13 -
drivers/net/ethernet/qlogic/qed/qed_cxt.c | 4
drivers/net/ethernet/qlogic/qed/qed_cxt.h | 3
drivers/net/ethernet/qlogic/qed/qed_iwarp.c | 12 -
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 3
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c | 5
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2
drivers/net/ethernet/ti/am65-cpts.c | 3
drivers/net/ethernet/ti/cpsw.c | 11
drivers/net/ethernet/ti/cpsw_new.c | 9
drivers/net/geneve.c | 3
drivers/net/ipa/gsi_trans.c | 15 +
drivers/net/netdevsim/dev.c | 2
drivers/net/netdevsim/health.c | 1
drivers/net/netdevsim/udp_tunnels.c | 1
drivers/net/phy/mscc/mscc_macsec.c | 1
drivers/net/usb/qmi_wwan.c | 2
drivers/pinctrl/pinctrl-mcp23s08_spi.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 | 32 ++
drivers/scsi/ufs/ufshcd.h | 2
drivers/spi/spi-bcm2835aux.c | 21 -
drivers/spi/spi-cadence-quadspi.c | 2
drivers/spi/spi-fsl-lpspi.c | 3
drivers/spi/spi-npcm-fiu.c | 2
drivers/spi/spi.c | 81 +++++--
drivers/staging/mt7621-pci/pci-mt7621.c | 15 -
drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 1
drivers/tee/amdtee/amdtee_private.h | 8
drivers/tee/amdtee/core.c | 26 +-
drivers/tty/serial/ar933x_uart.c | 6
drivers/tty/serial/imx.c | 30 --
drivers/usb/dwc2/platform.c | 3
fs/afs/dir.c | 1
fs/afs/inode.c | 8
fs/afs/internal.h | 1
fs/efivarfs/super.c | 1
fs/ext4/ext4.h | 3
fs/gfs2/aops.c | 2
fs/gfs2/glops.c | 13 +
fs/gfs2/log.c | 2
fs/gfs2/rgrp.c | 10
fs/io_uring.c | 1
fs/libfs.c | 6
fs/notify/fsnotify.c | 12 -
fs/super.c | 33 --
fs/xfs/libxfs/xfs_attr_leaf.c | 8
fs/xfs/libxfs/xfs_rmap_btree.c | 16 -
fs/xfs/scrub/bmap.c | 8
fs/xfs/scrub/btree.c | 45 ++-
fs/xfs/scrub/dir.c | 21 +
fs/xfs/xfs_iwalk.c | 27 ++
fs/xfs/xfs_mount.c | 11
include/drm/intel-gtt.h | 5
include/linux/intel-iommu.h | 2
include/linux/pagemap.h | 2
include/linux/pm_runtime.h | 21 +
include/linux/sched.h | 16 +
include/linux/spi/spi.h | 19 +
include/linux/swiotlb.h | 1
include/net/ip_tunnels.h | 7
include/net/neighbour.h | 1
include/net/tls.h | 16 +
include/trace/events/sunrpc.h | 3
kernel/fail_function.c | 5
kernel/ptrace.c | 16 -
kernel/rcu/tree.c | 2
kernel/rcu/tree_stall.h | 22 +
kernel/sched/core.c | 15 -
kernel/sched/fair.c | 3
kernel/seccomp.c | 5
kernel/trace/bpf_trace.c | 10
lib/strncpy_from_user.c | 19 +
mm/filemap.c | 18 +
mm/huge_memory.c | 9
mm/memcontrol.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/neighbour.c | 2
net/core/netpoll.c | 22 +
net/core/skmsg.c | 94 ++++++--
net/ipv4/arp.c | 6
net/ipv4/inet_diag.c | 4
net/ipv4/tcp_bbr.c | 2
net/ipv4/tcp_bpf.c | 18 -
net/ipv6/addrconf.c | 8
net/ipv6/ah6.c | 3
net/ipv6/ndisc.c | 7
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/rfkill/core.c | 3
net/sctp/input.c | 4
net/sctp/sm_sideeffect.c | 4
net/sctp/transport.c | 2
net/smc/smc_ib.c | 6
net/tls/tls_device.c | 37 ++-
net/tls/tls_sw.c | 2
net/vmw_vsock/af_vsock.c | 2
net/x25/af_x25.c | 1
sound/core/control.c | 2
sound/firewire/fireworks/fireworks_transaction.c | 4
sound/pci/hda/patch_realtek.c | 85 +++++++
sound/pci/mixart/mixart_core.c | 5
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 2
sound/soc/intel/keembay/kmb_platform.c | 6
sound/soc/qcom/lpass-platform.c | 5
sound/usb/quirks.c | 10
tools/bpf/bpftool/feature.c | 7
tools/bpf/bpftool/net.c | 18 -
tools/lib/bpf/Makefile | 2
tools/perf/builtin-lock.c | 4
tools/testing/kunit/.gitattributes | 1
tools/testing/selftests/bpf/prog_tests/sockopt_multi.c | 3
tools/testing/selftests/kvm/include/x86_64/processor.h | 2
tools/testing/selftests/kvm/lib/x86_64/processor.c | 3
tools/testing/selftests/seccomp/seccomp_bpf.c | 8
265 files changed, 1919 insertions(+), 913 deletions(-)
Aaron Lewis (1):
selftests: kvm: Fix the segment descriptor layout to match the actual layout
Adam Ford (2):
arm64: dts: imx8mm-beacon-som: Fix Choppy BT audio
arm64: dts imx8mn: Remove non-existent USB OTG2
Adrian Hunter (1):
mmc: sdhci-pci: Prefer SDR25 timing for High Speed mode for BYT-based Intel controllers
Alejandro Concepcion Rodriguez (1):
can: dev: can_restart(): post buffer from the right context
Alex Deucher (1):
drm/amd/display: Add missing pflip irq for dcn2.0
Alex Elder (1):
net: ipa: lock when freeing transaction
Alex Marginean (1):
enetc: Workaround for MDIO register access issue
Amir Goldstein (1):
fanotify: fix logic of reporting name info with watched parent
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()
Andrew Lunn (1):
ARM: dts: vf610-zii-dev-rev-b: Fix MDIO over clocking
Andy Shevchenko (2):
pinctrl: mcp23s08: Print error message when regmap init fails
iommu/vt-d: Move intel_iommu_gfx_mapped to Intel IOMMU header
Ard Biesheuvel (1):
efi/arm: set HSCTLR Thumb2 bit correctly for HVC calls from HYP
Arvind Sankar (1):
efi/x86: Free efi_pgd with free_pages()
Aya Levin (1):
net/mlx4_core: Fix init_hca fields offset
Biwen Li (1):
arm64: dts: fsl: fix endianness issue of rcpm
Bob Peterson (2):
gfs2: Fix case in which ail writes are done to jdata holes
gfs2: Fix regression in freeze_go_sync
Brendan Higgins (1):
kunit: tool: unmark test_data as binary blobs
Brian O'Keefe (1):
staging: rtl8723bs: Add 024c:0627 to the list of SDIO device-ids
Can Guo (2):
scsi: ufs: Fix unbalanced scsi_block_reqs_cnt caused by ufshcd_hold()
scsi: ufs: Try to save power mode change and UIC cmd completion timeout
Chen Yu (1):
x86/microcode/intel: Check patch signature before saving microcode for early loading
Chen-Yu Tsai (10):
Revert "arm: sun8i: orangepi-pc-plus: Set EMAC activity LEDs to active high"
ARM: dts: sun6i: a31-hummingbird: Enable RGMII RX/TX delay on Ethernet PHY
ARM: dts: sun7i: cubietruck: Enable RGMII RX/TX delay on Ethernet PHY
ARM: dts: sun7i: bananapi-m1-plus: Enable RGMII RX/TX delay on Ethernet PHY
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
ARM: dts: sun9i: Enable both RGMII RX/TX delay on Ethernet PHY
ARM: dts: sunxi: bananapi-m2-plus: Enable RGMII RX/TX delay on Ethernet PHY
arm64: dts: allwinner: h5: libretech-all-h5-cc: Enable RGMII RX/TX delay on PHY
arm64: dts: allwinner: a64: bananapi-m64: Enable RGMII RX/TX delay on PHY
Chris Co (1):
Drivers: hv: vmbus: Allow cleanup of VMBUS_CONNECT_CPU if disconnected
Christoph Hellwig (2):
RMDA/sw: Don't allow drivers using dma_virt_ops on highmem configs
blk-cgroup: fix a hd_struct leak in blkcg_fill_root_iostats
Claire Chang (1):
rfkill: Fix use-after-free in rfkill_resume()
Clément Péron (1):
arm64: dts: allwinner: beelink-gs1: Enable both RGMII RX/TX delay
Colin Ian King (1):
can: peak_usb: fix potential integer overflow on shift of a int
Corentin Labbe (1):
arm64: dts: allwinner: Pine H64: Enable both RGMII RX/TX delay
Dan Carpenter (3):
Input: adxl34x - clean up a data type in adxl34x_probe()
dmaengine: fix error codes in channel_register()
ALSA: firewire: Clean up a locking issue in copy_resp_to_buf()
Dan Murphy (2):
can: m_can: m_can_class_free_dev(): introduce new function
can: m_can: Fix freeing of can device from peripherials
Daniel Xu (1):
lib/strncpy_from_user.c: Mask out bytes after NUL terminator.
Darrick J. Wong (6):
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: directory scrub should check the null bestfree entries too
xfs: ensure inobt record walks always make forward progress
xfs: revert "xfs: fix rmap key and record comparison functions"
Dave Jiang (2):
dmaengine: idxd: fix wq config registers offset programming
dmaengine: idxd: fix mapping of portal size
David Howells (1):
afs: Fix speculative status fetch going out of order wrt to modifications
David Lechner (1):
counter/ti-eqep: Fix regmap max_register
Dinh Nguyen (1):
arm64: dts: agilex/stratix10: Fix qspi node compatible
Dmitry Bogdanov (1):
qed: fix ILT configuration of SRC block
Dongli Zhang (1):
page_frag: Recover from memory pressure
Edwin Peer (1):
bnxt_en: read EEPROM A2h address using page 0
Eli Cohen (1):
net/mlx5: E-Switch, Fail mlx5_esw_modify_vport_rate if qos disabled
Enric Balletbo i Serra (1):
can: tcan4x5x: replace depends on REGMAP_SPI with depends on SPI
Fabien Parent (1):
iio: adc: mediatek: fix unset field
Fabio Estevam (1):
ARM: dts: imx50-evk: Fix the chip select 1 IOMUX
Faiz Abbas (1):
can: m_can: m_can_stop(): set device to software init mode before closing
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
Gao Xiang (1):
xfs: fix forkoff miscalculation related to XFS_LITINO(mp)
Gerald Schaefer (1):
mm/userfaultfd: do not access vma->vm_mm after calling handle_userfault()
Greg Kroah-Hartman (1):
Linux 5.9.11
Grygorii Strashko (1):
net: ethernet: ti: cpsw: fix cpts irq after suspend
Guenter Roeck (2):
ASOC: Intel: kbl_rt5663_rt5514_max98927: Do not try to disable disabled clock
ACPI: fan: Initialize performance state sysfs attribute
Gwendal Grignou (1):
iio: cros_ec: Use default frequencies when EC returns invalid information
Hans de Goede (6):
ACPI: button: Add DMI quirk for Medion Akoya E2228T
HID: logitech-dj: Handle quad/bluetooth keyboards with a builtin trackpad
HID: logitech-dj: Fix Dinovo Mini when paired with a MX5x00 receiver
HID: logitech-dj: Fix an error in mse_bluetooth_descriptor
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
Harry Cutts (1):
HID: logitech-hidpp: Add PID for MX Anywhere 2
Heiko Carstens (1):
s390: fix system call exit path
Heiner Kallweit (1):
net: bridge: add missing counters to ndo_get_stats64 callback
Ian Rogers (1):
tools, bpftool: Avoid array index warnings.
Ido Schimmel (1):
mlxsw: core: Use variable timeout for EMAD retries
Jan Kara (1):
ext4: fix bogus warning in ext4_update_dx_flag()
Jarkko Nikula (1):
can: m_can: process interrupt only when not runtime suspended
Jeff Dike (1):
Exempt multicast addresses from five-second neighbor lifetime
Jens Axboe (2):
io_uring: don't double complete failed reissue request
mm: never attempt async page lock if we've transferred data already
Jernej Skrabec (4):
arm64: dts: allwinner: a64: OrangePi Win: Fix ethernet node
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 (2):
can: kvaser_pciefd: Fix KCAN bittiming limits
can: kvaser_usb: kvaser_usb_hydra: Fix KCAN bittiming limits
Jiri Olsa (1):
libbpf: Fix VERSIONED_SYM_COUNT number parsing
Joakim Tjernlund (1):
ALSA: usb-audio: Add delay quirk for all Logitech USB devices
Joel Stanley (2):
net: ftgmac100: Fix crash when removing driver
net/ncsi: Fix netlink registration
Johannes Berg (1):
mac80211: free sta in sta_info_insert_finish() on errors
John Fastabend (6):
bpf, sockmap: Fix partial copy_page_to_iter so progress can still be made
bpf, sockmap: Ensure SO_RCVBUF memory is observed on ingress redirect
bpf, sockmap: Skb verdict SK_PASS to self already checked rmem limits
bpf, sockmap: On receive programs try to fast track SK_PASS ingress
bpf, sockmap: Use truesize with sk_rmem_schedule()
bpf, sockmap: Avoid returning unneeded EAGAIN when redirecting to self
Jonathan Liu (1):
drm: bridge: dw-hdmi: Avoid resetting force in the detect function
Kailang Yang (3):
ALSA: hda/realtek - Add supported for Lenovo ThinkPad Headset Button
ALSA: hda/realtek - Add supported mute Led for HP
ALSA: hda/realtek - HP Headset Mic can't detect after boot
Karsten Graul (1):
net/smc: fix direct access to ib_gid_addr->ndev in smc_ib_determine_gid()
Kees Cook (2):
selftests/seccomp: powerpc: Fix typo in macro variable name
selftests/seccomp: sh: Fix register names
Konrad Dybcio (3):
arm64: Add MIDR value for KRYO2XX gold/silver CPU cores
arm64: kpti: Add KRYO2XX gold/silver CPU cores to kpti safelist
arm64: cpu_errata: Apply Erratum 845719 to KRYO2XX Silver
Lars Povlsen (1):
HID: mcp2221: Fix GPIO output handling
Leo Yan (2):
perf lock: Correct field name "flags"
perf lock: Don't free "lock_seq_stat" if read_count isn't zero
Lorenzo Bianconi (2):
net: mvneta: fix possible memory leak in mvneta_swbm_add_rx_fragment
iio: imu: st_lsm6dsx: set 10ms as min shub slave timeout
Lucas Stach (1):
arm64: dts: imx8mm: fix voltage for 1.6GHz CPU operating point
Lukas Wunner (4):
spi: lpspi: Fix use-after-free on unbind
spi: Introduce device-managed SPI controller allocation
spi: npcm-fiu: Don't leak SPI master in probe error path
spi: bcm2835aux: Fix use-after-free on unbind
Luo Meng (1):
fail_function: Remove a redundant mutex unlock
Manish Narani (3):
mmc: sdhci-of-arasan: Allow configuring zero tap values
mmc: sdhci-of-arasan: Use Mask writes for Tap delays
mmc: sdhci-of-arasan: Issue DLL reset explicitly
Maor Dickman (1):
net/mlx5e: Fix check if netdev is bond slave
Marc Kleine-Budde (4):
can: mcba_usb: mcba_usb_start_xmit(): first fill skb, then pass to can_put_echo_skb()
can: tcan4x5x: tcan4x5x_can_probe(): add missing error checking for devm_regmap_init()
can: tcan4x5x: tcan4x5x_can_remove(): fix order of deregistration
can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery
Marek Vasut (5):
ARM: dts: stm32: Fix TA3-GPIO-C key on STM32MP1 DHCOM PDK2
ARM: dts: stm32: Fix LED5 on STM32MP1 DHCOM PDK2
ARM: dts: stm32: Define VIO regulator supply on DHCOM
ARM: dts: stm32: Enable thermal sensor support on stm32mp15xx-dhcor
ARM: dts: stm32: Keep VDDA LDO1 always on on DHCOM
Martin Blumenstingl (2):
net: lantiq: Wait for the GPHY firmware to be ready
usb: dwc2: Avoid leaving the error_debugfs label unused
Matthew Murrian (2):
dmaengine: xilinx_dma: Fix usage of xilinx_aximcdma_tx_segment
dmaengine: xilinx_dma: Fix SG capability check for MCDMA
Matthew Wilcox (Oracle) (1):
mm: fix readahead_page_batch for retry entries
Max Filippov (2):
xtensa: fix TLBTEMP area placement
xtensa: disable preemption around cache alias management calls
Maxim Mikityanskiy (1):
net/mlx5e: Fix refcount leak on kTLS RX resync
Michael Chan (2):
bnxt_en: Fix counter overflow logic.
bnxt_en: Free port stats during firmware reset.
Michael Guralnik (1):
net/mlx5: Add handling of port type in rule deletion
Michael Sit Wei Hong (1):
ASoC: Intel: KMB: Fix S24_LE configuration
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
Muchun Song (1):
mm: memcg/slab: fix root memcg vmstats
Necip Fazil Yildiran (2):
Input: resistive-adc-touch - fix kconfig dependency on IIO_BUFFER
iio: light: fix kconfig dependency bug for VCNL4035
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
Oded Gabbay (1):
habanalabs/gaudi: mask WDT error in QMAN
Oleksij Rempel (1):
ARM: dts: imx6q-prti6q: fix PHY address
Olivier Moysan (1):
iio: adc: stm32-adc: fix a regression when using dma and irq
Paul Barker (1):
hwmon: (pwm-fan) Fix RPM calculation
Paul Cercueil (2):
iio/adc: ingenic: Fix AUX/VBAT readings when touchscreen is used
iio/adc: ingenic: Fix battery VREF for JZ4770 SoC
Paul E. McKenney (1):
rcu: Don't invoke try_invoke_on_locked_down_task() with irqs disabled
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)
Peter Zijlstra (2):
sched: Fix data-race in wakeup
sched: Fix rq->nr_iowait ordering
Qinglang Miao (1):
RDMA/pvrdma: Fix missing kfree() in pvrdma_register_device()
Quentin Perret (1):
sched/fair: Fix overutilized update in enqueue_task_fair()
Randy Dunlap (1):
MIPS: export has_transparent_hugepage() for modules
Richard Weinberger (1):
um: Call pgtable_pmd_page_dtor() in __pmd_free_tlb()
Rijo Thomas (2):
tee: amdtee: fix memory leak due to reset of global shm list
tee: amdtee: synchronize access to shm list
Rodrigo Vivi (1):
drm/i915/tgl: Fix Media power gate sequence.
Ryan Sharpelletti (1):
tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
Sam Nobs (1):
tty: serial: imx: fix potential deadlock
Samuel Thibault (1):
speakup: Do not let the line discipline be used several times
Scott Mayhew (1):
SUNRPC: Fix oops in the rpc_xdr_buf event class
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
Sergio Paracuellos (1):
staging: mt7621-pci: avoid to request pci bus resources
Srinivasa Rao Mandadapu (1):
ASoC: qcom: lpass-platform: Fix memory leak
Steen Hegelund (1):
net: phy: mscc: remove non-MACSec compatible phy
Stefan Haberland (1):
s390/dasd: fix null pointer dereference for ERP requests
Stefano Garzarella (1):
vsock: forward all packets to the host when no H2G is registered
Stephen Rothwell (1):
swiotlb: using SIZE_MAX needs limits.h included
Subash Abhinov Kasiviswanathan (1):
net: qualcomm: rmnet: Fix incorrect receive packet handling during cleanup
Sven Van Asbroeck (3):
lan743x: fix issue causing intermittent kernel log warnings
lan743x: prevent entire kernel HANG on open, for some platforms
spi: fix client driver breakages when using GPIO descriptors
Taehee Yoo (1):
netdevsim: set .owner to THIS_MODULE
Takashi Iwai (1):
ALSA: mixart: Fix mutex deadlock
Takashi Sakamoto (1):
ALSA: ctl: fix error path at adding user-defined element set
Tariq Toukan (1):
net/tls: Fix wrong record sn in async mode of device resync
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
Tony Lindgren (2):
Revert "Revert "gpio: omap: Fix lost edge wake-up interrupts""
dmaengine: ti: omap-dma: Block PM if SDMA is busy to fix audio
Vadim Fedorenko (1):
net/tls: fix corrupted data in recvmsg
Vamshi K Sthambamkadi (1):
efivarfs: fix memory leak in efivarfs_create()
Ville Syrjälä (1):
drm/i915: Handle max_bpc==16
Vincent Stehlé (1):
net: ethernet: mtk-star-emac: return ok when xmit drops
Vladyslav Tarasiuk (2):
net/mlx5: Clear bw_share upon VF disable
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()
tools, bpftool: Add missing close before bpftool net attach exit
selftests/bpf: Fix error return code in run_getsockopt_test()
Wang Qing (1):
net: ethernet: ti: am65-cpts: update ret when ptp_clock is ERROR
Will Deacon (3):
arm64: errata: Fix handling of 1418040 with late CPU onlining
arm64: psci: Avoid printing in cpu_psci_cpu_die()
arm64: smp: Tell RCU about CPUs that fail to come online
Wong Vee Khee (1):
net: stmmac: Use rtnl_lock/unlock on netif_set_real_num_rx_queues() call
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()
Yu Kuai (1):
xfs: return corresponding errcode if xfs_initialize_perag() fail
Zhang Changzhong (7):
ah6: fix error return code in ah6_input()
net: b44: fix error return code in b44_init_one()
net: ethernet: mtk-star-emac: fix error return code in mtk_star_enable()
net: ethernet: ti: cpsw: fix error return code in cpsw_probe()
qed: fix error return code in qed_iwarp_ll2_start()
qlcnic: fix error return code in qlcnic_83xx_restart_hw()
IB/hfi1: Fix error return code in hfi1_init_dd()
Zhang Qilong (7):
ipv6: Fix error path to cancel the meseage
PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter
net: fec: Fix reference count leak in fec series ops
gfs2: fix possible reference leak in gfs2_check_blk_type
can: ti_hecc: Fix memleak in ti_hecc_probe
can: flexcan: fix failure handling of pm_runtime_get_sync()
MIPS: Alchemy: Fix memleak in alchemy_clk_setup_cpu
Zheng Zengkai (1):
serial: ar933x_uart: disable clk on error handling path in probe
Zhenzhong Duan (1):
iommu/vt-d: Avoid panic if iommu init fails in tboot system
Zhihao Cheng (1):
spi: cadence-quadspi: Fix error return code in cqspi_probe
jingle.wu (1):
Input: elan_i2c - fix firmware update on newer ICs
^ permalink raw reply [relevance 1%]
* Linux 5.4.80
@ 2020-11-24 16:51 2% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2020-11-24 16:51 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 5.4.80 kernel.
All users of the 5.4 kernel series must upgrade.
The updated 5.4.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.4.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/xtensa/mmu.rst | 9 -
Makefile | 2
arch/arm/boot/dts/imx50-evk.dts | 2
arch/arm/boot/dts/imx6qdl-udoo.dtsi | 2
arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 2
arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 2
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 2
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts | 2
arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts | 2
arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts | 5
arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts | 2
arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts | 2
arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 2
arch/arm/boot/dts/sun9i-a80-optimus.dts | 2
arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi | 2
arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 2
arch/arm64/boot/dts/freescale/imx8mm.dtsi | 2
arch/arm64/boot/dts/freescale/imx8mn.dtsi | 30 ---
arch/arm64/include/asm/cpufeature.h | 2
arch/arm64/kernel/process.c | 5
arch/arm64/kernel/psci.c | 5
arch/arm64/kernel/smp.c | 1
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/kernel/tboot.c | 3
arch/x86/platform/efi/efi_64.c | 24 +-
arch/xtensa/include/asm/pgtable.h | 2
arch/xtensa/mm/cache.c | 14 +
drivers/acpi/button.c | 13 +
drivers/atm/nicstar.c | 2
drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c | 4
drivers/gpu/drm/i915/display/intel_display.c | 3
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 1
drivers/hid/hid-logitech-dj.c | 22 ++
drivers/hid/hid-logitech-hidpp.c | 26 +++
drivers/hv/hv.c | 8
drivers/hwmon/pwm-fan.c | 16 +
drivers/iio/accel/kxcjk-1013.c | 51 +++++
drivers/iio/adc/mt6577_auxadc.c | 6
drivers/iio/light/Kconfig | 1
drivers/infiniband/Kconfig | 3
drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c | 2
drivers/infiniband/sw/rdmavt/Kconfig | 3
drivers/infiniband/sw/rxe/Kconfig | 2
drivers/infiniband/sw/siw/Kconfig | 1
drivers/input/misc/adxl34x.c | 2
drivers/input/touchscreen/Kconfig | 1
drivers/iommu/intel-iommu.c | 5
drivers/mmc/host/sdhci-pci-core.c | 13 +
drivers/net/can/dev.c | 2
drivers/net/can/flexcan.c | 26 +--
drivers/net/can/kvaser_pciefd.c | 4
drivers/net/can/m_can/Kconfig | 3
drivers/net/can/m_can/m_can.c | 15 +
drivers/net/can/m_can/m_can.h | 1
drivers/net/can/m_can/tcan4x5x.c | 8
drivers/net/can/ti_hecc.c | 13 -
drivers/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/lantiq_gswip.c | 11 +
drivers/net/dsa/mv88e6xxx/global1_vtu.c | 59 +++++-
drivers/net/ethernet/broadcom/b44.c | 3
drivers/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
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 19 +-
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 7
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 +
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 3
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c | 5
drivers/net/ethernet/ti/cpsw.c | 1
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/spi/spi-bcm2835aux.c | 21 --
drivers/spi/spi-fsl-lpspi.c | 3
drivers/spi/spi-npcm-fiu.c | 2
drivers/spi/spi.c | 58 ++++++
drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 1
drivers/staging/speakup/spk_ttyio.c | 12 +
drivers/tty/serial/imx.c | 30 +--
fs/efivarfs/super.c | 1
fs/ext4/ext4.h | 3
fs/gfs2/rgrp.c | 10 -
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 +++--
fs/xfs/xfs_mount.c | 11 -
include/drm/intel-gtt.h | 5
include/linux/intel-iommu.h | 2
include/linux/spi/spi.h | 19 ++
include/linux/swiotlb.h | 1
include/net/ip_tunnels.h | 7
include/net/neighbour.h | 1
kernel/fail_function.c | 5
kernel/ptrace.c | 16 -
kernel/rcu/tree.c | 2
kernel/sched/fair.c | 3
kernel/seccomp.c | 5
mm/huge_memory.c | 9 -
mm/memcontrol.c | 9 -
mm/page_alloc.c | 30 +++
net/bridge/br_device.c | 1
net/can/af_can.c | 38 +++-
net/core/devlink.c | 6
net/core/neighbour.c | 2
net/core/netpoll.c | 22 ++
net/core/skmsg.c | 94 ++++++++---
net/ipv4/arp.c | 6
net/ipv4/inet_diag.c | 4
net/ipv4/tcp_bbr.c | 2
net/ipv4/tcp_bpf.c | 18 +-
net/ipv6/addrconf.c | 8
net/ipv6/ah6.c | 3
net/ipv6/ndisc.c | 7
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/rfkill/core.c | 3
net/sctp/input.c | 4
net/sctp/sm_sideeffect.c | 4
net/sctp/transport.c | 2
net/smc/smc_ib.c | 6
net/tls/tls_sw.c | 2
net/x25/af_x25.c | 1
sound/core/control.c | 2
sound/firewire/fireworks/fireworks_transaction.c | 4
sound/pci/hda/patch_realtek.c | 59 ++++++
sound/pci/mixart/mixart_core.c | 5
sound/soc/qcom/lpass-platform.c | 5
sound/usb/quirks.c | 10 -
tools/bpf/bpftool/net.c | 18 +-
tools/perf/builtin-lock.c | 2
tools/testing/selftests/bpf/prog_tests/sockopt_multi.c | 3
tools/testing/selftests/kvm/include/x86_64/processor.h | 2
tools/testing/selftests/kvm/lib/x86_64/processor.c | 3
159 files changed, 977 insertions(+), 550 deletions(-)
Aaron Lewis (1):
selftests: kvm: Fix the segment descriptor layout to match the actual layout
Adam Ford (1):
arm64: dts imx8mn: Remove non-existent USB OTG2
Adrian Hunter (1):
mmc: sdhci-pci: Prefer SDR25 timing for High Speed mode for BYT-based Intel controllers
Alejandro Concepcion Rodriguez (1):
can: dev: can_restart(): post buffer from the right context
Alex Deucher (1):
drm/amd/display: Add missing pflip irq for dcn2.0
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()
Andy Shevchenko (1):
iommu/vt-d: Move intel_iommu_gfx_mapped to Intel IOMMU header
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()
Charan Teja Reddy (1):
mm, page_alloc: skip ->waternark_boost for atomic order-0 allocations
Chen Yu (1):
x86/microcode/intel: Check patch signature before saving microcode for early loading
Chen-Yu Tsai (9):
Revert "arm: sun8i: orangepi-pc-plus: Set EMAC activity LEDs to active high"
ARM: dts: sun6i: a31-hummingbird: Enable RGMII RX/TX delay on Ethernet PHY
ARM: dts: sun7i: cubietruck: Enable RGMII RX/TX delay on Ethernet PHY
ARM: dts: sun7i: bananapi-m1-plus: Enable RGMII RX/TX delay on Ethernet PHY
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
ARM: dts: sun9i: Enable both RGMII RX/TX delay on Ethernet PHY
ARM: dts: sunxi: bananapi-m2-plus: Enable RGMII RX/TX delay on Ethernet PHY
arm64: dts: allwinner: a64: bananapi-m64: Enable RGMII RX/TX delay on PHY
Chris Co (1):
Drivers: hv: vmbus: Allow cleanup of VMBUS_CONNECT_CPU if disconnected
Christoph Hellwig (1):
RMDA/sw: Don't allow drivers using dma_virt_ops on highmem configs
Claire Chang (1):
rfkill: Fix use-after-free in rfkill_resume()
Clément Péron (1):
arm64: dts: allwinner: beelink-gs1: Enable both RGMII RX/TX delay
Colin Ian King (1):
can: peak_usb: fix potential integer overflow on shift of a int
Corentin Labbe (1):
arm64: dts: allwinner: Pine H64: Enable both RGMII RX/TX delay
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()
Dan Murphy (1):
can: m_can: m_can_class_free_dev(): introduce new function
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
Eli Cohen (1):
net/mlx5: E-Switch, Fail mlx5_esw_modify_vport_rate if qos disabled
Enric Balletbo i Serra (1):
can: tcan4x5x: replace depends on REGMAP_SPI with depends on SPI
Fabien Parent (1):
iio: adc: mediatek: fix unset field
Fabio Estevam (1):
ARM: dts: imx50-evk: Fix the chip select 1 IOMUX
Faiz Abbas (1):
can: m_can: m_can_stop(): set device to software init mode before closing
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 5.4.80
Hans de Goede (6):
ACPI: button: Add DMI quirk for Medion Akoya E2228T
HID: logitech-dj: Handle quad/bluetooth keyboards with a builtin trackpad
HID: logitech-dj: Fix Dinovo Mini when paired with a MX5x00 receiver
HID: logitech-dj: Fix an error in mse_bluetooth_descriptor
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
Harry Cutts (1):
HID: logitech-hidpp: Add PID for MX Anywhere 2
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()
Jarkko Nikula (1):
can: m_can: process interrupt only when not runtime suspended
Jeff Dike (1):
Exempt multicast addresses from five-second neighbor lifetime
Jernej Skrabec (4):
arm64: dts: allwinner: a64: OrangePi Win: Fix ethernet node
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 (2):
can: kvaser_pciefd: Fix KCAN bittiming limits
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
John Fastabend (6):
bpf, sockmap: Fix partial copy_page_to_iter so progress can still be made
bpf, sockmap: Ensure SO_RCVBUF memory is observed on ingress redirect
bpf, sockmap: Skb verdict SK_PASS to self already checked rmem limits
bpf, sockmap: On receive programs try to fast track SK_PASS ingress
bpf, sockmap: Use truesize with sk_rmem_schedule()
bpf, sockmap: Avoid returning unneeded EAGAIN when redirecting to self
Kailang Yang (1):
ALSA: hda/realtek - Add supported for Lenovo ThinkPad Headset Button
Karsten Graul (1):
net/smc: fix direct access to ib_gid_addr->ndev in smc_ib_determine_gid()
Leo Yan (1):
perf lock: Don't free "lock_seq_stat" if read_count isn't zero
Lucas Stach (1):
arm64: dts: imx8mm: fix voltage for 1.6GHz CPU operating point
Lukas Wunner (4):
spi: lpspi: Fix use-after-free on unbind
spi: Introduce device-managed SPI controller allocation
spi: npcm-fiu: Don't leak SPI master in probe error path
spi: bcm2835aux: Fix use-after-free on unbind
Luo Meng (1):
fail_function: Remove a redundant mutex unlock
Marc Kleine-Budde (4):
can: mcba_usb: mcba_usb_start_xmit(): first fill skb, then pass to can_put_echo_skb()
can: tcan4x5x: tcan4x5x_can_probe(): add missing error checking for devm_regmap_init()
can: tcan4x5x: tcan4x5x_can_remove(): fix order of deregistration
can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery
Martin Blumenstingl (1):
net: lantiq: Wait for the GPHY firmware to be ready
Max Filippov (2):
xtensa: fix TLBTEMP area placement
xtensa: disable preemption around cache alias management calls
Michael Guralnik (1):
net/mlx5: Add handling of port type in rule deletion
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
Muchun Song (1):
mm: memcg/slab: fix root memcg vmstats
Necip Fazil Yildiran (2):
Input: resistive-adc-touch - fix kconfig dependency on IIO_BUFFER
iio: light: fix kconfig dependency bug for VCNL4035
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 Barker (1):
hwmon: (pwm-fan) Fix RPM calculation
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)
Qinglang Miao (1):
RDMA/pvrdma: Fix missing kfree() in pvrdma_register_device()
Quentin Perret (1):
sched/fair: Fix overutilized update in enqueue_task_fair()
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
Sam Nobs (1):
tty: serial: imx: fix potential deadlock
Samuel Thibault (1):
speakup: Do not let the line discipline be used several times
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
Stephen Rothwell (1):
swiotlb: using SIZE_MAX needs limits.h included
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
Vadim Fedorenko (1):
net/tls: fix corrupted data in recvmsg
Vamshi K Sthambamkadi (1):
efivarfs: fix memory leak in efivarfs_create()
Ville Syrjälä (1):
drm/i915: Handle max_bpc==16
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()
tools, bpftool: Add missing close before bpftool net attach exit
selftests/bpf: Fix error return code in run_getsockopt_test()
Will Deacon (3):
arm64: errata: Fix handling of 1418040 with late CPU onlining
arm64: psci: Avoid printing in cpu_psci_cpu_die()
arm64: smp: Tell RCU about CPUs that fail to come online
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()
Yu Kuai (1):
xfs: return corresponding errcode if xfs_initialize_perag() fail
Zhang Changzhong (5):
ah6: fix error return code in ah6_input()
net: b44: fix error return code in b44_init_one()
net: ethernet: ti: cpsw: fix error return code in cpsw_probe()
qed: fix error return code in qed_iwarp_ll2_start()
qlcnic: fix error return code in qlcnic_83xx_restart_hw()
Zhang Qilong (5):
ipv6: Fix error path to cancel the meseage
gfs2: fix possible reference leak in gfs2_check_blk_type
can: ti_hecc: Fix memleak in ti_hecc_probe
can: flexcan: fix failure handling of pm_runtime_get_sync()
MIPS: Alchemy: Fix memleak in alchemy_clk_setup_cpu
Zhenzhong Duan (1):
iommu/vt-d: Avoid panic if iommu init fails in tboot system
^ permalink raw reply [relevance 2%]
* Linux 4.19.160
@ 2020-11-24 16:51 3% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2020-11-24 16:51 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 4.19.160 kernel.
All users of the 4.19 kernel series must upgrade.
The updated 4.19.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-4.19.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
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
arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts | 2
arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts | 5 -
arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts | 2
arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 2
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts | 2
arch/arm64/boot/dts/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 +-
drivers/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
drivers/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
drivers/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 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 3
drivers/net/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/staging/speakup/spk_ttyio.c | 12 ++
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
sound/firewire/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
94 files changed, 528 insertions(+), 378 deletions(-)
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
Samuel Thibault (1):
speakup: Do not let the line discipline be used several times
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
^ permalink raw reply [relevance 3%]
* Linux 4.14.209
@ 2020-11-24 16:51 3% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2020-11-24 16:51 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 4.14.209 kernel.
All users of the 4.14 kernel series must upgrade.
The updated 4.14.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-4.14.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Makefile | 2
arch/arm/boot/dts/imx50-evk.dts | 2
arch/arm/boot/dts/imx6qdl-udoo.dtsi | 2
arch/arm64/kernel/psci.c | 5 -
arch/mips/alchemy/common/clock.c | 9 ++
arch/mips/mm/tlb-r4k.c | 1
arch/powerpc/include/asm/book3s/64/kup-radix.h | 1
arch/s390/kernel/perf_cpum_sf.c | 2
arch/x86/kernel/cpu/microcode/intel.c | 63 ++----------------
arch/xtensa/mm/cache.c | 14 ++++
drivers/atm/nicstar.c | 2
drivers/iio/accel/kxcjk-1013.c | 51 +++++++++++++-
drivers/input/misc/adxl34x.c | 2
drivers/net/can/dev.c | 2
drivers/net/can/m_can/m_can.c | 4 -
drivers/net/can/ti_hecc.c | 13 ++-
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
drivers/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 -
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 15 ++--
drivers/net/ethernet/mellanox/mlxsw/core.c | 3
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 3
drivers/net/usb/qmi_wwan.c | 2
drivers/pinctrl/pinctrl-rockchip.c | 2
drivers/regulator/core.c | 38 ++++++----
drivers/regulator/ti-abb-regulator.c | 12 +++
drivers/s390/block/dasd.c | 6 +
drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 1
drivers/staging/speakup/spk_ttyio.c | 9 ++
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 ++--
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/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
sound/pci/mixart/mixart_core.c | 5 -
sound/soc/qcom/lpass-platform.c | 5 +
tools/perf/builtin-lock.c | 2
59 files changed, 342 insertions(+), 249 deletions(-)
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()
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
Chen Yu (1):
x86/microcode/intel: Check patch signature before saving microcode for early loading
Colin Ian King (1):
can: peak_usb: fix potential integer overflow on shift of a int
Dan Carpenter (1):
Input: adxl34x - clean up a data type in adxl34x_probe()
Daniel Axtens (1):
powerpc/uaccess-flush: fix missing includes in kup-radix.h
Darrick J. Wong (2):
vfs: remove lockdep bogosity in __sb_start_write
xfs: revert "xfs: fix rmap key and record comparison functions"
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
Greg Kroah-Hartman (1):
Linux 4.14.209
Hans de Goede (2):
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()
Jianqun Xu (1):
pinctrl: rockchip: enable gpio pclk for rockchip_gpio_to_irq
Joel Stanley (1):
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
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
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()
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
Samuel Thibault (1):
speakup: Do not let the line discipline be used several times
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
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
Yicong Yang (1):
libfs: fix error cast of negative value in simple_attr_write()
Zhang Changzhong (3):
ah6: fix error return code in ah6_input()
net: b44: fix error return code in b44_init_one()
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
^ permalink raw reply [relevance 3%]
* Linux 4.9.246
@ 2020-11-24 16:51 4% Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2020-11-24 16:51 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
I'm announcing the release of the 4.9.246 kernel.
All users of the 4.9 kernel series must upgrade.
The updated 4.9.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-4.9.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Makefile | 2
arch/arm/boot/dts/imx50-evk.dts | 2
arch/arm/boot/dts/imx6qdl-udoo.dtsi | 2
arch/arm64/kernel/psci.c | 5 -
arch/mips/alchemy/common/clock.c | 9 +++
arch/mips/mm/tlb-r4k.c | 1
arch/powerpc/include/asm/book3s/64/kup-radix.h | 1
arch/s390/kernel/perf_cpum_sf.c | 2
arch/x86/kernel/cpu/microcode/intel.c | 48 ------------------
arch/xtensa/mm/cache.c | 14 +++++
drivers/atm/nicstar.c | 2
drivers/iio/accel/kxcjk-1013.c | 15 +++--
drivers/input/misc/adxl34x.c | 2
drivers/net/can/dev.c | 2
drivers/net/can/m_can/m_can.c | 4 -
drivers/net/can/usb/peak_usb/pcan_usb_core.c | 4 -
drivers/net/ethernet/broadcom/b44.c | 3 -
drivers/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 -
drivers/net/ethernet/mellanox/mlxsw/core.c | 2
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 3 -
drivers/net/usb/qmi_wwan.c | 2
drivers/pinctrl/pinctrl-rockchip.c | 2
drivers/regulator/core.c | 29 ++++------
drivers/regulator/ti-abb-regulator.c | 12 ++++
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 +++---
net/bridge/br_device.c | 1
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/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
sound/pci/mixart/mixart_core.c | 5 -
tools/perf/builtin-lock.c | 2
50 files changed, 173 insertions(+), 207 deletions(-)
Alejandro Concepcion Rodriguez (1):
can: dev: can_restart(): post buffer from the right context
Aya Levin (1):
net/mlx4_core: Fix init_hca fields offset
Chen Yu (1):
x86/microcode/intel: Check patch signature before saving microcode for early loading
Colin Ian King (1):
can: peak_usb: fix potential integer overflow on shift of a int
Dan Carpenter (1):
Input: adxl34x - clean up a data type in adxl34x_probe()
Daniel Axtens (1):
powerpc/uaccess-flush: fix missing includes in kup-radix.h
Darrick J. Wong (2):
vfs: remove lockdep bogosity in __sb_start_write
xfs: revert "xfs: fix rmap key and record comparison functions"
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
Greg Kroah-Hartman (1):
Linux 4.9.246
Hans de Goede (1):
iio: accel: kxcjk1013: Replace is_smo8500_device with an acpi_type enum
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()
Jianqun Xu (1):
pinctrl: rockchip: enable gpio pclk for rockchip_gpio_to_irq
Joel Stanley (1):
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
Max Filippov (1):
xtensa: disable preemption around cache alias management calls
Michał Mirosław (1):
regulator: fix memory leak with repeated set_machine_constraints()
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()
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
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
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
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()
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
Yicong Yang (1):
libfs: fix error cast of negative value in simple_attr_write()
Zhang Changzhong (3):
ah6: fix error return code in ah6_input()
net: b44: fix error return code in b44_init_one()
qlcnic: fix error return code in qlcnic_83xx_restart_hw()
Zhang Qilong (1):
MIPS: Alchemy: Fix memleak in alchemy_clk_setup_cpu
^ permalink raw reply [relevance 4%]
* [PATCH 4.14 19/60] tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
@ 2020-11-23 12:22 6% ` Greg Kroah-Hartman
0 siblings, 0 replies; 200+ results
From: Greg Kroah-Hartman @ 2020-11-23 12:22 UTC (permalink / raw)
To: linux-kernel
Cc: Greg Kroah-Hartman, stable, Ryan Sharpelletti, Neal Cardwell,
Soheil Hassas Yeganeh, Yuchung Cheng, Jakub Kicinski
From: Ryan Sharpelletti <sharpelletti@google.com>
[ Upstream commit 1b9e2a8c99a5c021041bfb2d512dc3ed92a94ffd ]
During loss recovery, retransmitted packets are forced to use TCP
timestamps to calculate the RTT samples, which have a millisecond
granularity. BBR is designed using a microsecond granularity. As a
result, multiple RTT samples could be truncated to the same RTT value
during loss recovery. This is problematic, as BBR will not enter
PROBE_RTT if the RTT sample is <= the current min_rtt sample, meaning
that if there are persistent losses, PROBE_RTT will constantly be
pushed off and potentially never re-entered. This patch makes sure
that BBR enters PROBE_RTT by checking if RTT sample is < the current
min_rtt sample, rather than <=.
The Netflix transport/TCP team discovered this bug in the Linux TCP
BBR code during lab tests.
Fixes: 0f8782ea1497 ("tcp_bbr: add BBR congestion control")
Signed-off-by: Ryan Sharpelletti <sharpelletti@google.com>
Signed-off-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com>
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Link: https://lore.kernel.org/r/20201116174412.1433277-1-sharpelletti.kdev@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv4/tcp_bbr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ipv4/tcp_bbr.c
+++ b/net/ipv4/tcp_bbr.c
@@ -769,7 +769,7 @@ static void bbr_update_min_rtt(struct so
filter_expired = after(tcp_jiffies32,
bbr->min_rtt_stamp + bbr_min_rtt_win_sec * HZ);
if (rs->rtt_us >= 0 &&
- (rs->rtt_us <= bbr->min_rtt_us || filter_expired)) {
+ (rs->rtt_us < bbr->min_rtt_us || filter_expired)) {
bbr->min_rtt_us = rs->rtt_us;
bbr->min_rtt_stamp = tcp_jiffies32;
}
^ permalink raw reply [relevance 6%]
Results 1-200 of ~800 next (older) | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2020-11-23 12:21 [PATCH 4.14 00/60] 4.14.209-rc1 review Greg Kroah-Hartman
2020-11-23 12:22 6% ` [PATCH 4.14 19/60] tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate Greg Kroah-Hartman
2020-11-24 16:51 4% Linux 4.9.246 Greg Kroah-Hartman
2020-11-24 16:51 3% Linux 4.14.209 Greg Kroah-Hartman
2020-11-24 16:51 3% Linux 4.19.160 Greg Kroah-Hartman
2020-11-24 16:51 2% Linux 5.4.80 Greg Kroah-Hartman
2020-11-24 16:51 1% Linux 5.9.11 Greg Kroah-Hartman
2020-12-23 2:12 [PATCH AUTOSEL 5.10 001/217] soc: aspeed-lpc-ctrl: Fail probe of lpc-ctrl if reserved memory is not aligned Sasha Levin
2020-12-23 2:14 3% ` [PATCH AUTOSEL 5.10 071/217] RDMA/core: Postpone uobject cleanup on failure till FD close Sasha Levin
2021-03-01 16:02 1% [PATCH 5.11 000/775] 5.11.3-rc1 review Greg Kroah-Hartman
2021-03-01 16:09 7% ` [PATCH 5.11 377/775] watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready Greg Kroah-Hartman
2021-03-01 16:04 1% [PATCH 5.10 000/663] 5.10.20-rc1 review Greg Kroah-Hartman
2021-03-01 16:09 7% ` [PATCH 5.10 316/663] watchdog: intel-mid_wdt: Postpone IRQ handler registration till SCU is ready Greg Kroah-Hartman
2021-03-01 19:37 1% [PATCH 5.10 000/661] 5.10.20-rc2 review Greg Kroah-Hartman
2021-03-01 19:38 1% [PATCH 5.11 000/774] 5.11.3-rc2 review Greg Kroah-Hartman
2021-03-02 12:38 1% [PATCH 5.10 000/658] 5.10.20-rc3 review Greg Kroah-Hartman
2021-03-02 19:28 1% [PATCH 5.10 000/657] 5.10.20-rc4 review Greg Kroah-Hartman
2021-03-02 19:29 1% [PATCH 5.11 000/773] 5.11.3-rc3 review Greg Kroah-Hartman
2021-03-04 11:01 1% Linux 5.10.20 Greg Kroah-Hartman
2021-03-04 11:33 1% Linux 5.11.3 Greg Kroah-Hartman
2021-03-15 13:51 [PATCH 5.10 000/290] 5.10.24-rc1 review gregkh
2021-03-15 13:52 ` [PATCH 5.10 081/290] gpiolib: Read "gpio-line-names" from a firmware node gregkh
2021-03-15 14:18 5% ` Marek Vasut
2021-03-15 16:32 0% ` Bartosz Golaszewski
2021-03-17 16:05 0% ` Greg KH
2021-03-15 18:18 5% ` Andy Shevchenko
2021-03-29 7:55 1% [PATCH 5.11 000/254] 5.11.11-rc1 review Greg Kroah-Hartman
2021-03-29 7:58 12% ` [PATCH 5.11 204/254] PM: EM: postpone creating the debugfs dir till fs_initcall Greg Kroah-Hartman
2021-03-29 7:55 1% [PATCH 5.10 000/221] 5.10.27-rc1 review Greg Kroah-Hartman
2021-03-29 7:58 12% ` [PATCH 5.10 174/221] PM: EM: postpone creating the debugfs dir till fs_initcall Greg Kroah-Hartman
2021-03-29 7:57 2% [PATCH 5.4 000/111] 5.4.109-rc1 review Greg Kroah-Hartman
2021-03-29 7:58 12% ` [PATCH 5.4 091/111] PM: EM: postpone creating the debugfs dir till fs_initcall Greg Kroah-Hartman
2021-03-29 10:14 1% [PATCH 5.10 000/219] 5.10.27-rc2 review Greg Kroah-Hartman
2021-03-29 10:14 1% [PATCH 5.11 000/252] 5.11.11-rc2 review Greg Kroah-Hartman
2021-03-30 13:36 2% Linux 5.4.109 Greg Kroah-Hartman
2021-03-30 13:36 1% Linux 5.11.11 Greg Kroah-Hartman
2021-03-30 13:37 1% Linux 5.10.27 Greg Kroah-Hartman
2021-08-18 8:48 5% Backporting CVE-2020-3702 ath9k patches to stable Pali Rohár
2021-08-18 9:02 0% ` Greg KH
2021-08-18 9:10 0% ` Pali Rohár
2021-08-18 9:18 0% ` Greg KH
2021-08-20 11:35 0% ` Pali Rohár
2021-08-20 21:23 0% ` Sasha Levin
2021-08-20 22:27 0% ` Toke Høiland-Jørgensen
2021-08-20 23:07 0% ` Pali Rohár
2021-08-20 22:41 0% ` Pali Rohár
2021-09-02 11:48 0% ` Pavel Machek
2021-09-02 12:02 0% ` Greg KH
2021-08-23 14:08 Drivers for Qualcomm wifi chips (ath*k) and security issues Pali Rohár
2021-08-23 14:32 ` Ben Greear
2021-08-23 14:58 ` Pali Rohár
2021-08-23 19:26 5% ` Sudip Mukherjee
2021-08-24 16:57 2% [PATCH 5.10 00/98] 5.10.61-rc1 review Sasha Levin
2021-08-24 16:57 5% ` [PATCH 5.10 05/98] ath9k: Postpone key cache entry deletion for TXQ frames reference it Sasha Levin
2021-08-24 17:00 3% [PATCH 5.4 00/61] 5.4.143-rc1 review Sasha Levin
2021-08-24 17:00 5% ` [PATCH 5.4 07/61] ath9k: Postpone key cache entry deletion for TXQ frames reference it Sasha Levin
2021-08-24 17:01 3% [PATCH 4.19 00/84] 4.19.205-rc1 review Sasha Levin
2021-08-24 17:02 5% ` [PATCH 4.19 49/84] ath9k: Postpone key cache entry deletion for TXQ frames reference it Sasha Levin
2021-08-24 17:03 3% [PATCH 4.14 00/64] 4.14.245-rc1 review Sasha Levin
2021-08-24 17:04 5% ` [PATCH 4.14 38/64] ath9k: Postpone key cache entry deletion for TXQ frames reference it Sasha Levin
2021-08-26 13:25 3% Linux 5.10.61 Sasha Levin
2021-08-26 13:26 3% Linux 5.4.143 Sasha Levin
2021-08-26 13:26 3% Linux 4.19.205 Sasha Levin
2021-08-26 13:26 3% Linux 4.14.245 Sasha Levin
2021-09-20 8:01 4% FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 5.10-stable tree gregkh
2021-09-20 8:01 4% FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 5.4-stable tree gregkh
2021-09-20 8:01 4% FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 4.19-stable tree gregkh
2021-09-20 8:01 4% FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 4.14-stable tree gregkh
2021-09-20 8:01 4% FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 4.4-stable tree gregkh
2021-09-20 8:01 4% FAILED: patch "[PATCH] net: stmmac: fix system hang caused by eee_ctrl_timer during" failed to apply to 4.9-stable tree gregkh
2021-09-20 16:40 1% [PATCH 4.9 000/175] 4.9.283-rc1 review Greg Kroah-Hartman
2021-09-20 16:41 5% ` [PATCH 4.9 014/175] ath9k: Postpone key cache entry deletion for TXQ frames reference it Greg Kroah-Hartman
2021-09-20 16:41 2% [PATCH 4.4 000/133] 4.4.284-rc1 review Greg Kroah-Hartman
2021-09-20 16:41 5% ` [PATCH 4.4 012/133] ath9k: Postpone key cache entry deletion for TXQ frames reference it Greg Kroah-Hartman
2021-09-20 16:42 [PATCH 5.14 000/168] 5.14.7-rc1 review Greg Kroah-Hartman
2021-09-20 16:43 4% ` [PATCH 5.14 053/168] net: stmmac: fix system hang caused by eee_ctrl_timer during suspend/resume Greg Kroah-Hartman
2021-09-21 12:48 1% [PATCH 4.9 000/174] 4.9.283-rc2 review Greg Kroah-Hartman
2021-09-22 11:12 2% Linux 4.4.284 Greg Kroah-Hartman
2021-09-22 11:12 2% Linux 4.9.283 Greg Kroah-Hartman
2021-09-24 12:43 [PATCH 5.14 000/100] 5.14.8-rc1 review Greg Kroah-Hartman
2021-09-24 12:43 4% ` [PATCH 5.14 037/100] init: move usermodehelper_enable() to populate_rootfs() Greg Kroah-Hartman
2021-11-09 19:06 [PATCH v3] mm: fix panic in __alloc_pages Dennis Zhou
2021-11-09 19:54 ` Michal Hocko
2021-11-16 1:31 ` Alexey Makhalov
2021-11-16 9:17 ` Michal Hocko
2021-11-16 20:22 ` Alexey Makhalov
2021-11-18 8:35 ` Michal Hocko
2021-12-07 10:54 ` Michal Hocko
2021-12-07 11:08 ` David Hildenbrand
2021-12-07 12:13 ` Michal Hocko
2021-12-07 12:28 ` David Hildenbrand
2021-12-07 13:23 7% ` Michal Hocko
2021-11-19 17:39 [PATCH 5.15 00/20] 5.15.4-rc1 review Greg Kroah-Hartman
2021-11-19 17:39 5% ` [PATCH 5.15 01/20] string: uninline memcpy_and_pad Greg Kroah-Hartman
2021-11-29 18:17 [PATCH 5.10 000/121] 5.10.83-rc1 review Greg Kroah-Hartman
2021-11-29 18:18 4% ` [PATCH 5.10 066/121] net: stmmac: fix system hang caused by eee_ctrl_timer during suspend/resume Greg Kroah-Hartman
2022-03-16 14:13 [PATCH AUTOSEL 5.16 01/13] arm64: dts: qcom: c630: disable crypto due to serror Sasha Levin
2022-03-16 14:13 ` [PATCH AUTOSEL 5.16 12/13] spi: Fix invalid sgs value Sasha Levin
2022-03-16 16:07 5% ` Geert Uytterhoeven
2022-03-16 16:40 0% ` Sasha Levin
2022-04-13 4:01 [PATCH net 1/1] net: stmmac: add fsleep() in HW Rx timestamp checking loop Tan Tee Min
2022-04-13 12:59 ` Richard Cochran
2022-04-14 7:29 ` Tan Tee Min
2022-04-14 8:42 ` Jakub Kicinski
2022-04-19 0:52 ` Tan Tee Min
2022-04-19 13:28 ` Richard Cochran
2022-04-20 5:15 ` Tan Tee Min
2022-04-20 12:54 5% ` Richard Cochran
2022-04-18 12:09 [PATCH 5.17 000/219] 5.17.4-rc1 review Greg Kroah-Hartman
2022-04-18 12:11 5% ` [PATCH 5.17 118/219] net: ftgmac100: access hardware register after clock ready Greg Kroah-Hartman
2022-04-18 12:10 [PATCH 5.15 000/189] 5.15.35-rc1 review Greg Kroah-Hartman
2022-04-18 12:11 5% ` [PATCH 5.15 098/189] net: ftgmac100: access hardware register after clock ready Greg Kroah-Hartman
2022-05-13 14:23 [PATCH 5.15 00/21] 5.15.40-rc1 review Greg Kroah-Hartman
2022-05-13 14:23 5% ` [PATCH 5.15 06/21] kbuild: move objtool_args back to scripts/Makefile.build Greg Kroah-Hartman
2022-06-07 16:51 1% [PATCH 5.18 000/879] 5.18.3-rc1 review Greg Kroah-Hartman
2022-06-07 17:00 7% ` [PATCH 5.18 527/879] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
2022-06-07 16:53 1% [PATCH 5.17 000/772] 5.17.14-rc1 review Greg Kroah-Hartman
2022-06-07 17:00 7% ` [PATCH 5.17 445/772] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
2022-06-07 16:54 1% [PATCH 5.15 000/667] 5.15.46-rc1 review Greg Kroah-Hartman
2022-06-07 17:00 7% ` [PATCH 5.15 376/667] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
2022-06-07 16:57 1% [PATCH 5.10 000/452] 5.10.121-rc1 review Greg Kroah-Hartman
2022-06-07 17:01 7% ` [PATCH 5.10 257/452] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
2022-06-09 8:38 1% Linux 5.10.121 Greg Kroah-Hartman
2022-06-09 8:39 1% Linux 5.15.46 Greg Kroah-Hartman
2022-06-09 8:39 1% Linux 5.17.14 Greg Kroah-Hartman
2022-06-09 8:39 1% Linux 5.18.3 Greg Kroah-Hartman
2022-06-13 10:04 1% [PATCH 5.4 000/411] 5.4.198-rc1 review Greg Kroah-Hartman
2022-06-13 10:07 7% ` [PATCH 5.4 155/411] net/smc: postpone sk_refcnt increment in connect() Greg Kroah-Hartman
2022-06-14 2:03 [PATCH AUTOSEL 5.18 01/47] powerpc/kasan: Silence KASAN warnings in __get_wchan() Sasha Levin
2022-06-14 2:04 5% ` [PATCH AUTOSEL 5.18 42/47] gpio: dwapb: Don't print error on -EPROBE_DEFER Sasha Levin
2022-06-14 2:05 [PATCH AUTOSEL 5.17 01/43] powerpc/kasan: Silence KASAN warnings in __get_wchan() Sasha Levin
2022-06-14 2:05 5% ` [PATCH AUTOSEL 5.17 38/43] gpio: dwapb: Don't print error on -EPROBE_DEFER Sasha Levin
2022-06-14 2:06 [PATCH AUTOSEL 5.15 01/41] powerpc/kasan: Silence KASAN warnings in __get_wchan() Sasha Levin
2022-06-14 2:07 5% ` [PATCH AUTOSEL 5.15 37/41] gpio: dwapb: Don't print error on -EPROBE_DEFER Sasha Levin
2022-06-14 2:07 [PATCH AUTOSEL 5.10 01/29] powerpc/kasan: Silence KASAN warnings in __get_wchan() Sasha Levin
2022-06-14 2:08 5% ` [PATCH AUTOSEL 5.10 29/29] gpio: dwapb: Don't print error on -EPROBE_DEFER Sasha Levin
2022-06-14 16:49 1% Linux 5.4.198 Greg Kroah-Hartman
2022-06-20 12:48 [PATCH 5.18 000/141] 5.18.6-rc1 review Greg Kroah-Hartman
2022-06-20 12:49 5% ` [PATCH 5.18 046/141] gpio: dwapb: Dont print error on -EPROBE_DEFER Greg Kroah-Hartman
2022-06-20 12:50 [PATCH 5.15 000/106] 5.15.49-rc1 review Greg Kroah-Hartman
2022-06-20 12:50 5% ` [PATCH 5.15 040/106] gpio: dwapb: Dont print error on -EPROBE_DEFER Greg Kroah-Hartman
2022-06-20 12:50 [PATCH 5.10 00/84] 5.10.124-rc1 review Greg Kroah-Hartman
2022-06-20 12:50 5% ` [PATCH 5.10 33/84] gpio: dwapb: Dont print error on -EPROBE_DEFER Greg Kroah-Hartman
2022-07-04 7:36 11% FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 4.9-stable tree gregkh
2022-07-04 7:36 11% FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 4.14-stable tree gregkh
2022-07-04 7:36 11% FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 4.19-stable tree gregkh
2022-07-04 7:36 11% FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 5.4-stable tree gregkh
2022-07-04 7:44 11% FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 5.10-stable tree gregkh
2022-07-04 7:44 11% FAILED: patch "[PATCH] net: phy: Don't trigger state machine while in suspend" failed to apply to 5.4-stable tree gregkh
2022-07-05 11:57 [PATCH 5.15 00/98] 5.15.53-rc1 review Greg Kroah-Hartman
2022-07-05 11:57 11% ` [PATCH 5.15 07/98] net: phy: Dont trigger state machine while in suspend Greg Kroah-Hartman
2022-07-05 11:57 [PATCH 5.18 000/102] 5.18.10-rc1 review Greg Kroah-Hartman
2022-07-05 11:57 11% ` [PATCH 5.18 008/102] net: phy: Dont trigger state machine while in suspend Greg Kroah-Hartman
2022-07-07 16:08 Linux 5.15.53 Greg Kroah-Hartman
2022-07-07 16:08 1% ` Greg Kroah-Hartman
2022-07-07 16:08 Linux 5.18.10 Greg Kroah-Hartman
2022-07-07 16:08 1% ` Greg Kroah-Hartman
2022-07-12 18:38 [PATCH 5.18 00/61] 5.18.12-rc1 review Greg Kroah-Hartman
2022-07-15 11:27 5% ` Greg Kroah-Hartman
2022-11-08 13:37 [PATCH 6.0 000/197] 6.0.8-rc1 review Greg Kroah-Hartman
2022-11-08 13:37 5% ` [PATCH 6.0 031/197] netfilter: nf_tables: release flow rule object from commit path Greg Kroah-Hartman
2022-11-08 13:37 [PATCH 5.15 000/144] 5.15.78-rc1 review Greg Kroah-Hartman
2022-11-08 13:38 5% ` [PATCH 5.15 037/144] netfilter: nf_tables: release flow rule object from commit path Greg Kroah-Hartman
2022-11-08 13:37 [PATCH 5.10 000/118] 5.10.154-rc1 review Greg Kroah-Hartman
2022-11-08 13:38 5% ` [PATCH 5.10 032/118] netfilter: nf_tables: release flow rule object from commit path Greg Kroah-Hartman
2022-11-08 13:38 [PATCH 5.4 00/74] 5.4.224-rc1 review Greg Kroah-Hartman
2022-11-08 13:38 5% ` [PATCH 5.4 15/74] netfilter: nf_tables: release flow rule object from commit path Greg Kroah-Hartman
[not found] <cover.1672826282.git.jani.nikula@intel.com>
2023-01-04 10:05 5% ` [PATCH v7 01/22] drm/edid: fix AVI infoframe aspect ratio handling Jani Nikula
2023-01-18 14:56 0% ` Ville Syrjälä
2023-02-22 12:03 Linux 4.19.273 Greg Kroah-Hartman
2023-02-22 12:03 1% ` Greg Kroah-Hartman
2023-03-07 16:46 [PATCH 6.2 0000/1001] 6.2.3-rc1 review Greg Kroah-Hartman
2023-03-07 17:02 5% ` [PATCH 6.2 1000/1001] drm/edid: fix AVI infoframe aspect ratio handling Greg Kroah-Hartman
2023-03-07 16:48 [PATCH 6.1 000/885] 6.1.16-rc1 review Greg Kroah-Hartman
2023-03-07 17:03 5% ` [PATCH 6.1 884/885] drm/edid: fix AVI infoframe aspect ratio handling Greg Kroah-Hartman
2023-03-07 16:55 [PATCH 5.15 000/567] 5.15.99-rc1 review Greg Kroah-Hartman
2023-03-07 17:05 5% ` [PATCH 5.15 567/567] drm/edid: fix AVI infoframe aspect ratio handling Greg Kroah-Hartman
2023-03-10 13:32 [PATCH 5.10 000/529] 5.10.173-rc1 review Greg Kroah-Hartman
2023-03-10 13:39 5% ` [PATCH 5.10 425/529] drm/edid: fix AVI infoframe aspect ratio handling Greg Kroah-Hartman
2023-03-10 13:36 [PATCH 6.2 000/211] 6.2.4-rc1 review Greg Kroah-Hartman
2023-03-10 13:38 5% ` [PATCH 6.2 116/211] ASoC: apple: mca: Improve handling of unavailable DMA channels Greg Kroah-Hartman
2023-03-10 13:36 [PATCH 6.1 000/200] 6.1.17-rc1 review Greg Kroah-Hartman
2023-03-10 13:38 5% ` [PATCH 6.1 107/200] ASoC: apple: mca: Improve handling of unavailable DMA channels Greg Kroah-Hartman
2023-03-15 12:11 [PATCH 6.1 000/143] 6.1.20-rc1 review Greg Kroah-Hartman
2023-03-15 12:12 5% ` [PATCH 6.1 090/143] m68k: mm: Move initrd phys_to_virt handling after paging_init() Greg Kroah-Hartman
2023-03-15 12:11 [PATCH 6.2 000/141] 6.2.7-rc1 review Greg Kroah-Hartman
2023-03-15 12:13 5% ` [PATCH 6.2 084/141] m68k: mm: Move initrd phys_to_virt handling after paging_init() Greg Kroah-Hartman
2023-03-15 12:11 [PATCH 5.4 00/68] 5.4.237-rc1 review Greg Kroah-Hartman
2023-03-15 12:12 5% ` [PATCH 5.4 13/68] drm/edid: fix AVI infoframe aspect ratio handling Greg Kroah-Hartman
2023-03-17 10:30 6% [PATCH 1/1] serial: 8250: Prevent starting up DMA Rx on THRI interrupt Ilpo Järvinen
2023-03-20 9:52 0% ` Hans de Goede
2023-04-05 9:46 Linux 4.19.280 Greg Kroah-Hartman
2023-04-05 9:46 1% ` Greg Kroah-Hartman
2023-04-12 8:32 [PATCH 6.1 000/164] 6.1.24-rc1 review Greg Kroah-Hartman
2023-04-12 8:33 6% ` [PATCH 6.1 085/164] serial: 8250: Prevent starting up DMA Rx on THRI interrupt Greg Kroah-Hartman
2023-04-12 8:32 [PATCH 6.2 000/173] 6.2.11-rc1 review Greg Kroah-Hartman
2023-04-12 8:33 6% ` [PATCH 6.2 092/173] serial: 8250: Prevent starting up DMA Rx on THRI interrupt Greg Kroah-Hartman
2023-04-13 15:19 Linux 6.1.24 Greg Kroah-Hartman
2023-04-13 15:19 1% ` Greg Kroah-Hartman
2023-04-13 15:19 Linux 6.2.11 Greg Kroah-Hartman
2023-04-13 15:19 1% ` Greg Kroah-Hartman
[not found] <20230420234951.1772270-1-Rodrigo.Siqueira@amd.com>
2023-04-20 23:49 5% ` [PATCH 14/21] drm/amd/display: Fix in secure display context creation Rodrigo Siqueira
2023-05-01 2:55 [PATCH AUTOSEL 6.3 01/44] drm/displayid: add displayid_get_header() and check bounds better Sasha Levin
2023-05-01 2:55 10% ` [PATCH AUTOSEL 6.3 11/44] accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release() Sasha Levin
2023-05-01 2:59 [PATCH AUTOSEL 6.2 01/37] drm/displayid: add displayid_get_header() and check bounds better Sasha Levin
2023-05-01 2:59 10% ` [PATCH AUTOSEL 6.2 11/37] accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release() Sasha Levin
2023-05-22 19:05 1% [PATCH 6.3 000/364] 6.3.4-rc1 review Greg Kroah-Hartman
2023-05-22 19:06 10% ` [PATCH 6.3 055/364] accel/habanalabs: postpone mem_mgr IDR destruction to hpriv_release() Greg Kroah-Hartman
2023-05-23 17:01 1% [PATCH 6.3 000/363] 6.3.4-rc2 review Greg Kroah-Hartman
2023-05-24 10:10 amd_sfh driver causes kernel oops during boot Bagas Sanjaya
2023-06-05 11:24 5% ` Malte Starostik
2023-05-24 17:20 1% Linux 6.3.4 Greg Kroah-Hartman
2023-06-07 20:11 [PATCH 6.3 000/286] 6.3.7-rc1 review Greg Kroah-Hartman
2023-06-07 20:13 5% ` [PATCH 6.3 081/286] mptcp: simplify subflow_syn_recv_sock() Greg Kroah-Hartman
2023-06-07 20:13 [PATCH 6.1 000/225] 6.1.33-rc1 review Greg Kroah-Hartman
2023-06-07 20:14 5% ` [PATCH 6.1 056/225] mptcp: simplify subflow_syn_recv_sock() Greg Kroah-Hartman
2023-06-15 11:37 [PATCH AUTOSEL 6.3 01/19] regmap: Account for register length when chunking Sasha Levin
2023-06-15 11:37 6% ` [PATCH AUTOSEL 6.3 16/19] nvme: double KA polling frequency to avoid KATO with TBKAS on Sasha Levin
2023-06-15 11:38 [PATCH AUTOSEL 6.1 01/16] regmap: Account for register length when chunking Sasha Levin
2023-06-15 11:38 6% ` [PATCH AUTOSEL 6.1 13/16] nvme: double KA polling frequency to avoid KATO with TBKAS on Sasha Levin
2023-06-15 11:38 [PATCH AUTOSEL 5.15 01/10] regmap: Account for register length when chunking Sasha Levin
2023-06-15 11:38 6% ` [PATCH AUTOSEL 5.15 09/10] nvme: double KA polling frequency to avoid KATO with TBKAS on Sasha Levin
2023-06-26 18:08 [PATCH 6.3 000/199] 6.3.10-rc1 review Greg Kroah-Hartman
2023-06-26 18:11 6% ` [PATCH 6.3 162/199] nvme: double KA polling frequency to avoid KATO with TBKAS on Greg Kroah-Hartman
2023-06-26 18:09 [PATCH 6.1 000/170] 6.1.36-rc1 review Greg Kroah-Hartman
2023-06-26 18:11 6% ` [PATCH 6.1 141/170] nvme: double KA polling frequency to avoid KATO with TBKAS on Greg Kroah-Hartman
2023-06-26 18:11 [PATCH 5.15 00/96] 5.15.119-rc1 review Greg Kroah-Hartman
2023-06-26 18:12 6% ` [PATCH 5.15 82/96] nvme: double KA polling frequency to avoid KATO with TBKAS on Greg Kroah-Hartman
2023-06-28 9:25 Linux 5.15.119 Greg Kroah-Hartman
2023-06-28 9:25 1% ` Greg Kroah-Hartman
2023-06-28 9:25 Linux 6.1.36 Greg Kroah-Hartman
2023-06-28 9:25 1% ` Greg Kroah-Hartman
2023-06-28 9:26 Linux 6.3.10 Greg Kroah-Hartman
2023-06-28 9:26 1% ` Greg Kroah-Hartman
2023-07-09 11:09 [PATCH 6.3 000/431] 6.3.13-rc1 review Greg Kroah-Hartman
2023-07-09 11:11 5% ` [PATCH 6.3 118/431] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-07-16 19:37 [PATCH 6.4 000/800] 6.4.4-rc1 review Greg Kroah-Hartman
2023-07-16 19:40 5% ` [PATCH 6.4 161/800] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-07-16 19:42 [PATCH 6.1 000/591] 6.1.39-rc1 review Greg Kroah-Hartman
2023-07-16 19:44 5% ` [PATCH 6.1 105/591] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-07-21 7:23 4% FAILED: patch "[PATCH] drm/amd/display: Fix in secure display context creation" failed to apply to 6.1-stable tree gregkh
2023-07-21 15:58 1% [PATCH 5.15 000/532] 5.15.121-rc1 review Greg Kroah-Hartman
2023-07-21 15:59 5% ` [PATCH 5.15 066/532] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-07-21 16:05 7% ` [PATCH 5.15 410/532] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
2023-07-21 16:01 1% [PATCH 6.4 000/292] 6.4.5-rc1 review Greg Kroah-Hartman
2023-07-21 16:02 7% ` [PATCH 6.4 052/292] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
2023-07-21 16:05 5% ` [PATCH 6.4 198/292] drm/amd/display: Fix in secure display context creation Greg Kroah-Hartman
2023-07-21 16:04 1% [PATCH 6.1 000/223] 6.1.40-rc1 review Greg Kroah-Hartman
2023-07-21 16:04 7% ` [PATCH 6.1 032/223] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
2023-07-23 12:26 1% Linux 5.15.121 Greg Kroah-Hartman
2023-07-23 12:28 1% Linux 6.1.40 Greg Kroah-Hartman
2023-07-23 12:28 1% Linux 6.4.5 Greg Kroah-Hartman
2023-07-25 10:38 1% [PATCH 5.10 000/509] 5.10.188-rc1 review Greg Kroah-Hartman
2023-07-25 10:40 5% ` [PATCH 5.10 073/509] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-07-25 10:44 7% ` [PATCH 5.10 348/509] net: bgmac: postpone turning IRQs off to avoid SoC hangs Greg Kroah-Hartman
2023-07-28 9:31 0% ` [PATCH 5.10 000/509] 5.10.188-rc1 review luomeng
2023-07-25 10:42 [PATCH 5.4 000/313] 5.4.251-rc1 review Greg Kroah-Hartman
2023-07-25 10:43 5% ` [PATCH 5.4 055/313] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-07-26 4:54 1% [PATCH 5.10 000/508] 5.10.188-rc2 review Greg Kroah-Hartman
2023-07-27 7:13 1% Linux 5.10.188 Greg Kroah-Hartman
2023-08-09 10:37 [PATCH 4.19 000/323] 4.19.291-rc1 review Greg Kroah-Hartman
2023-08-09 10:38 5% ` [PATCH 4.19 045/323] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-08-09 10:38 [PATCH 4.14 000/204] 4.14.322-rc1 review Greg Kroah-Hartman
2023-08-09 10:39 5% ` [PATCH 4.14 026/204] wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key() Greg Kroah-Hartman
2023-08-20 15:21 [PATCH 0/6] Backport rework of deadline bandwidth restoration for 5.10.y Qais Yousef
2023-08-20 15:21 4% ` [PATCH 6/6] cgroup/cpuset: Free DL BW in case can_attach() fails Qais Yousef
2023-08-20 15:22 [PATCH 0/6] Backport rework of deadline bandwidth restoration for 5.15.y Qais Yousef
2023-08-20 15:22 4% ` [PATCH 6/6] cgroup/cpuset: Free DL BW in case can_attach() fails Qais Yousef
2023-08-20 15:24 [PATCH 0/6] Backport rework of deadline bandwidth restoration for 6.1.y Qais Yousef
2023-08-20 15:24 4% ` [PATCH 6/6] cgroup/cpuset: Free DL BW in case can_attach() fails Qais Yousef
2023-08-21 22:19 [PATCH 0/6] Backport rework of deadline bandwidth restoration for 6.4.y Qais Yousef
2023-08-21 22:19 4% ` [PATCH 6/6] cgroup/cpuset: Free DL BW in case can_attach() fails Qais Yousef
2023-08-28 10:11 [PATCH 6.4 000/129] 6.4.13-rc1 review Greg Kroah-Hartman
2023-08-28 10:12 4% ` [PATCH 6.4 084/129] cgroup/cpuset: Free DL BW in case can_attach() fails Greg Kroah-Hartman
2023-08-28 10:11 [PATCH 6.1 000/122] 6.1.50-rc1 review Greg Kroah-Hartman
2023-08-28 10:13 4% ` [PATCH 6.1 106/122] cgroup/cpuset: Free DL BW in case can_attach() fails Greg Kroah-Hartman
2023-08-28 10:13 [PATCH 5.15 00/89] 5.15.129-rc1 review Greg Kroah-Hartman
2023-08-28 10:14 4% ` [PATCH 5.15 79/89] cgroup/cpuset: Free DL BW in case can_attach() fails Greg Kroah-Hartman
2023-08-28 10:13 [PATCH 5.10 00/84] 5.10.193-rc1 review Greg Kroah-Hartman
2023-08-28 10:14 4% ` [PATCH 5.10 71/84] cgroup/cpuset: Free DL BW in case can_attach() fails Greg Kroah-Hartman
2023-09-17 19:12 [PATCH 6.1 000/219] 6.1.54-rc1 review Greg Kroah-Hartman
2023-09-17 19:12 ` [PATCH 6.1 033/219] memcg: drop kmem.limit_in_bytes Greg Kroah-Hartman
2023-09-20 8:11 ` [REGRESSION] " Jeremi Piotrowski
2023-09-20 8:43 ` Michal Hocko
2023-09-20 9:25 5% ` Greg Kroah-Hartman
2023-09-20 10:21 0% ` Jeremi Piotrowski
2023-09-20 10:45 0% ` Greg Kroah-Hartman
2023-09-24 13:14 [PATCH AUTOSEL 6.5 01/41] nvme-fc: Prevent null pointer dereference in nvme_fc_io_getuuid() Sasha Levin
2023-09-24 13:15 ` [PATCH AUTOSEL 6.5 13/41] btrfs: do not block starts waiting on previous transaction commit Sasha Levin
2023-09-25 13:01 5% ` David Sterba
2023-09-25 17:47 0% ` Sasha Levin
2023-11-15 20:35 2% [PATCH 4.19 00/88] 4.19.299-rc1 review Greg Kroah-Hartman
2023-11-15 20:36 6% ` [PATCH 4.19 78/88] net/smc: postpone release of clcsock Greg Kroah-Hartman
2023-11-20 10:04 3% Linux 4.19.299 Greg Kroah-Hartman
[not found] <20231215123208.516590-1-miquel.raynal@bootlin.com>
2023-12-15 12:32 5% ` [PATCH 2/4] mtd: rawnand: Fix core interference with sequential reads Miquel Raynal
2023-12-22 11:37 0% ` Miquel Raynal
2024-01-29 17:00 [PATCH 6.7 000/346] 6.7.3-rc1 review Greg Kroah-Hartman
2024-01-29 17:00 5% ` [PATCH 6.7 024/346] mtd: rawnand: Fix core interference with sequential reads Greg Kroah-Hartman
2024-01-29 17:01 [PATCH 6.6 000/331] 6.6.15-rc1 review Greg Kroah-Hartman
2024-01-29 17:01 5% ` [PATCH 6.6 047/331] mtd: rawnand: Fix core interference with sequential reads Greg Kroah-Hartman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).